[kernel] r11188 - in dists/trunk/linux-2.6/debian/patches: bugfix/all series

Maximilian Attems maks at alioth.debian.org
Sat Apr 26 21:59:25 UTC 2008


Author: maks
Date: Sat Apr 26 21:59:14 2008
New Revision: 11188

Log:
update to patch-2.6.25-git9

push it out
* debian integration of experimental kernel
* allow early beta testing
* 2.6.26 is Lenny goal


Added:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9
Modified:
   dists/trunk/linux-2.6/debian/patches/series/1~experimental.1

Added: dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9	Sat Apr 26 21:59:14 2008
@@ -0,0 +1,952011 @@
+diff --git a/.gitignore b/.gitignore
+index fdcce40..3016ed3 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -27,6 +27,7 @@ TAGS
+ vmlinux*
+ !vmlinux.lds.S
+ System.map
++Module.markers
+ Module.symvers
+ !.gitignore
+ 
+diff --git a/CREDITS b/CREDITS
+index da0a56e..8fec7b3 100644
+--- a/CREDITS
++++ b/CREDITS
+@@ -403,6 +403,8 @@ D: Linux CD and Support Giveaway List
+ N: Erik Inge Bolsø
+ E: knan at mo.himolde.no
+ D: Misc kernel hacks
++D: Updated PC speaker driver for 2.3
++S: Norway
+ 
+ N: Andreas E. Bombe
+ E: andreas.bombe at munich.netsurf.de
+@@ -3116,6 +3118,12 @@ S: Post Office Box 64132
+ S: Sunnyvale, California 94088-4132
+ S: USA
+ 
++N: Stas Sergeev
++E: stsp at users.sourceforge.net
++D: PCM PC-Speaker driver
++D: misc fixes
++S: Russia
++
+ N: Simon Shapiro
+ E: shimon at i-Connect.Net
+ W: http://www.-i-Connect.Net/~shimon
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index e8fb246..1977fab 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -25,8 +25,6 @@ DMA-API.txt
+ 	- DMA API, pci_ API & extensions for non-consistent memory machines.
+ DMA-ISA-LPC.txt
+ 	- How to do DMA with ISA (and LPC) devices.
+-DMA-mapping.txt
+-	- info for PCI drivers using DMA portably across all platforms.
+ DocBook/
+ 	- directory with DocBook templates etc. for kernel documentation.
+ HOWTO
+@@ -43,8 +41,6 @@ ManagementStyle
+ 	- how to (attempt to) manage kernel hackers.
+ MSI-HOWTO.txt
+ 	- the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
+-PCIEBUS-HOWTO.txt
+-	- a guide describing the PCI Express Port Bus driver.
+ RCU/
+ 	- directory with info on RCU (read-copy update).
+ README.DAC960
+@@ -167,10 +163,8 @@ highuid.txt
+ 	- notes on the change from 16 bit to 32 bit user/group IDs.
+ hpet.txt
+ 	- High Precision Event Timer Driver for Linux.
+-hrtimer/
+-	- info on the timer_stats debugging facility for timer (ab)use.
+-hrtimers/
+-	- info on the hrtimers subsystem for high-resolution kernel timers.
++timers/
++	- info on the timer related topics
+ hw_random.txt
+ 	- info on Linux support for random number generator in i8xx chipsets.
+ hwmon/
+@@ -287,12 +281,6 @@ parport.txt
+ 	- how to use the parallel-port driver.
+ parport-lowlevel.txt
+ 	- description and usage of the low level parallel port functions.
+-pci-error-recovery.txt
+-	- info on PCI error recovery.
+-pci.txt
+-	- info on the PCI subsystem for device driver authors.
+-pcieaer-howto.txt
+-	- the PCI Express Advanced Error Reporting Driver Guide HOWTO.
+ pcmcia/
+ 	- info on the Linux PCMCIA driver.
+ pi-futex.txt
+@@ -341,8 +329,6 @@ sgi-visws.txt
+ 	- short blurb on the SGI Visual Workstations.
+ sh/
+ 	- directory with info on porting Linux to a new architecture.
+-smart-config.txt
+-	- description of the Smart Config makefile feature.
+ sound/
+ 	- directory with info on sound card support.
+ sparc/
+diff --git a/Documentation/ABI/obsolete/o2cb b/Documentation/ABI/obsolete/o2cb
+new file mode 100644
+index 0000000..9c49d8e
+--- /dev/null
++++ b/Documentation/ABI/obsolete/o2cb
+@@ -0,0 +1,11 @@
++What:		/sys/o2cb symlink
++Date:		Dec 2005
++KernelVersion:	2.6.16
++Contact:	ocfs2-devel at oss.oracle.com
++Description:	This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink will
++		be removed when new versions of ocfs2-tools which know to look
++		in /sys/fs/o2cb are sufficiently prevalent. Don't code new
++		software to look here, it should try /sys/fs/o2cb instead.
++		See Documentation/ABI/stable/o2cb for more information on usage.
++Users:		ocfs2-tools. It's sufficient to mail proposed changes to
++		ocfs2-devel at oss.oracle.com.
+diff --git a/Documentation/ABI/stable/o2cb b/Documentation/ABI/stable/o2cb
+new file mode 100644
+index 0000000..5eb1545
+--- /dev/null
++++ b/Documentation/ABI/stable/o2cb
+@@ -0,0 +1,10 @@
++What:		/sys/fs/o2cb/ (was /sys/o2cb)
++Date:		Dec 2005
++KernelVersion:	2.6.16
++Contact:	ocfs2-devel at oss.oracle.com
++Description:	Ocfs2-tools looks at 'interface-revision' for versioning
++		information. Each logmask/ file controls a set of debug prints
++		and can be written into with the strings "allow", "deny", or
++		"off". Reading the file returns the current state.
++Users:		ocfs2-tools. It's sufficient to mail proposed changes to
++		ocfs2-devel at oss.oracle.com.
+diff --git a/Documentation/ABI/stable/sysfs-class-ubi b/Documentation/ABI/stable/sysfs-class-ubi
+new file mode 100644
+index 0000000..18d471d
+--- /dev/null
++++ b/Documentation/ABI/stable/sysfs-class-ubi
+@@ -0,0 +1,212 @@
++What:		/sys/class/ubi/
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		The ubi/ class sub-directory belongs to the UBI subsystem and
++		provides general UBI information, per-UBI device information
++		and per-UBI volume information.
++
++What:		/sys/class/ubi/version
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		This file contains version of the latest supported UBI on-media
++		format. Currently it is 1, and there is no plan to change this.
++		However, if in the future UBI needs on-flash format changes
++		which cannot be done in a compatible manner, a new format
++		version will be added. So this is a mechanism for possible
++		future backward-compatible (but forward-incompatible)
++		improvements.
++
++What:		/sys/class/ubiX/
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		The /sys/class/ubi0, /sys/class/ubi1, etc directories describe
++		UBI devices (UBI device 0, 1, etc). They contain general UBI
++		device information and per UBI volume information (each UBI
++		device may have many UBI volumes)
++
++What:		/sys/class/ubi/ubiX/avail_eraseblocks
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Amount of available logical eraseblock. For example, one may
++		create a new UBI volume which has this amount of logical
++		eraseblocks.
++
++What:		/sys/class/ubi/ubiX/bad_peb_count
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Count of bad physical eraseblocks on the underlying MTD device.
++
++What:		/sys/class/ubi/ubiX/bgt_enabled
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Contains ASCII "0\n" if the UBI background thread is disabled,
++		and ASCII "1\n" if it is enabled.
++
++What:		/sys/class/ubi/ubiX/dev
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Major and minor numbers of the character device corresponding
++		to this UBI device (in <major>:<minor> format).
++
++What:		/sys/class/ubi/ubiX/eraseblock_size
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Maximum logical eraseblock size this UBI device may provide. UBI
++		volumes may have smaller logical eraseblock size because of their
++		alignment.
++
++What:		/sys/class/ubi/ubiX/max_ec
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Maximum physical eraseblock erase counter value.
++
++What:		/sys/class/ubi/ubiX/max_vol_count
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Maximum number of volumes which this UBI device may have.
++
++What:		/sys/class/ubi/ubiX/min_io_size
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Minimum input/output unit size. All the I/O may only be done
++		in fractions of the contained number.
++
++What:		/sys/class/ubi/ubiX/mtd_num
++Date:		January 2008
++KernelVersion:	2.6.25
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Number of the underlying MTD device.
++
++What:		/sys/class/ubi/ubiX/reserved_for_bad
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Number of physical eraseblocks reserved for bad block handling.
++
++What:		/sys/class/ubi/ubiX/total_eraseblocks
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Total number of good (not marked as bad) physical eraseblocks on
++		the underlying MTD device.
++
++What:		/sys/class/ubi/ubiX/volumes_count
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Count of volumes on this UBI device.
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		The /sys/class/ubi/ubiX/ubiX_0/, /sys/class/ubi/ubiX/ubiX_1/,
++		etc directories describe UBI volumes on UBI device X (volumes
++		0, 1, etc).
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/alignment
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Volume alignment - the value the logical eraseblock size of
++		this volume has to be aligned on. For example, 2048 means that
++		logical eraseblock size is multiple of 2048. In other words,
++		volume logical eraseblock size is UBI device logical eraseblock
++		size aligned to the alignment value.
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/corrupted
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Contains ASCII "0\n" if the UBI volume is OK, and ASCII "1\n"
++		if it is corrupted (e.g., due to an interrupted volume update).
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/data_bytes
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		The amount of data this volume contains. This value makes sense
++		only for static volumes, and for dynamic volume it equivalent
++		to the total volume size in bytes.
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/dev
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Major and minor numbers of the character device corresponding
++		to this UBI volume (in <major>:<minor> format).
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/name
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Volume name.
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/reserved_ebs
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Count of physical eraseblock reserved for this volume.
++		Equivalent to the volume size in logical eraseblocks.
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/type
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Volume type. Contains ASCII "dynamic\n" for dynamic volumes and
++		"static\n" for static volumes.
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/upd_marker
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Contains ASCII "0\n" if the update marker is not set for this
++		volume, and "1\n" if it is set. The update marker is set when
++		volume update starts, and cleaned when it ends. So the presence
++		of the update marker indicates that the volume is being updated
++		at the moment of the update was interrupted. The later may be
++		checked using the "corrupted" sysfs file.
++
++What:		/sys/class/ubi/ubiX/ubiX_Y/usable_eb_size
++Date:		July 2006
++KernelVersion:	2.6.22
++Contact:	Artem Bityutskiy <dedekind at infradead.org>
++Description:
++		Logical eraseblock size of this volume. Equivalent to logical
++		eraseblock size of the device aligned on the volume alignment
++		value.
+diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
+new file mode 100644
+index 0000000..ceddcff
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-bus-pci
+@@ -0,0 +1,11 @@
++What:		/sys/bus/pci/devices/.../vpd
++Date:		February 2008
++Contact:	Ben Hutchings <bhutchings at solarflare.com>
++Description:
++		A file named vpd in a device directory will be a
++		binary file containing the Vital Product Data for the
++		device.  It should follow the VPD format defined in
++		PCI Specification 2.1 or 2.2, but users should consider
++		that some devices may have malformatted data.  If the
++		underlying VPD has a writable section then the
++		corresponding section of this file will be writable.
+diff --git a/Documentation/ABI/testing/sysfs-ibft b/Documentation/ABI/testing/sysfs-ibft
+new file mode 100644
+index 0000000..c2b7d11
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-ibft
+@@ -0,0 +1,23 @@
++What:		/sys/firmware/ibft/initiator
++Date:		November 2007
++Contact:	Konrad Rzeszutek <ketuzsezr at darnok.org>
++Description:	The /sys/firmware/ibft/initiator directory will contain
++		files that expose the iSCSI Boot Firmware Table initiator data.
++		Usually this contains the Initiator name.
++
++What:		/sys/firmware/ibft/targetX
++Date:		November 2007
++Contact:	Konrad Rzeszutek <ketuzsezr at darnok.org>
++Description:	The /sys/firmware/ibft/targetX directory will contain
++		files that expose the iSCSI Boot Firmware Table target data.
++		Usually this contains the target's IP address, boot LUN,
++		target name, and what NIC it is associated with. It can also
++		contain the CHAP name (and password), the reverse CHAP
++		name (and password)
++
++What:		/sys/firmware/ibft/ethernetX
++Date:		November 2007
++Contact:	Konrad Rzeszutek <ketuzsezr at darnok.org>
++Description:	The /sys/firmware/ibft/ethernetX directory will contain
++		files that expose the iSCSI Boot Firmware Table NIC data.
++		This can this can the IP address, MAC, and gateway of the NIC.
+diff --git a/Documentation/ABI/testing/sysfs-ocfs2 b/Documentation/ABI/testing/sysfs-ocfs2
+new file mode 100644
+index 0000000..b7cc516
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-ocfs2
+@@ -0,0 +1,89 @@
++What:		/sys/fs/ocfs2/
++Date:		April 2008
++Contact:	ocfs2-devel at oss.oracle.com
++Description:
++		The /sys/fs/ocfs2 directory contains knobs used by the
++		ocfs2-tools to interact with the filesystem.
++
++What:		/sys/fs/ocfs2/max_locking_protocol
++Date:		April 2008
++Contact:	ocfs2-devel at oss.oracle.com
++Description:
++		The /sys/fs/ocfs2/max_locking_protocol file displays version
++		of ocfs2 locking supported by the filesystem.  This version
++		covers how ocfs2 uses distributed locking between cluster
++		nodes.
++
++		The protocol version has a major and minor number.  Two
++		cluster nodes can interoperate if they have an identical
++		major number and an overlapping minor number - thus,
++		a node with version 1.10 can interoperate with a node
++		sporting version 1.8, as long as both use the 1.8 protocol.
++
++		Reading from this file returns a single line, the major
++		number and minor number joined by a period, eg "1.10".
++
++		This file is read-only.  The value is compiled into the
++		driver.
++
++What:		/sys/fs/ocfs2/loaded_cluster_plugins
++Date:		April 2008
++Contact:	ocfs2-devel at oss.oracle.com
++Description:
++		The /sys/fs/ocfs2/loaded_cluster_plugins file describes
++		the available plugins to support ocfs2 cluster operation.
++		A cluster plugin is required to use ocfs2 in a cluster.
++		There are currently two available plugins:
++
++		* 'o2cb' - The classic o2cb cluster stack that ocfs2 has
++			used since its inception.
++		* 'user' - A plugin supporting userspace cluster software
++			in conjunction with fs/dlm.
++
++		Reading from this file returns the names of all loaded
++		plugins, one per line.
++
++		This file is read-only.  Its contents may change as
++		plugins are loaded or removed.
++
++What:		/sys/fs/ocfs2/active_cluster_plugin
++Date:		April 2008
++Contact:	ocfs2-devel at oss.oracle.com
++Description:
++		The /sys/fs/ocfs2/active_cluster_plugin displays which
++		cluster plugin is currently in use by the filesystem.
++		The active plugin will appear in the loaded_cluster_plugins
++		file as well.  Only one plugin can be used at a time.
++
++		Reading from this file returns the name of the active plugin
++		on a single line.
++
++		This file is read-only.  Which plugin is active depends on
++		the cluster stack in use.  The contents may change
++		when all filesystems are unmounted and the cluster stack
++		is changed.
++
++What:		/sys/fs/ocfs2/cluster_stack
++Date:		April 2008
++Contact:	ocfs2-devel at oss.oracle.com
++Description:
++		The /sys/fs/ocfs2/cluster_stack file contains the name
++		of current ocfs2 cluster stack.  This value is set by
++		userspace tools when bringing the cluster stack online.
++
++		Cluster stack names are 4 characters in length.
++
++		When the 'o2cb' cluster stack is used, the 'o2cb' cluster
++		plugin is active.  All other cluster stacks use the 'user'
++		cluster plugin.
++
++		Reading from this file returns the name of the current
++		cluster stack on a single line.
++
++		Writing a new stack name to this file changes the current
++		cluster stack unless there are mounted ocfs2 filesystems.
++		If there are mounted filesystems, attempts to change the
++		stack return an error.
++
++Users:
++	ocfs2-tools <ocfs2-tools-devel at oss.oracle.com>
+diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
+index 300e170..83966e9 100644
+--- a/Documentation/DocBook/Makefile
++++ b/Documentation/DocBook/Makefile
+@@ -9,9 +9,10 @@
+ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
+ 	    kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
+ 	    procfs-guide.xml writing_usb_driver.xml networking.xml \
+-	    kernel-api.xml filesystems.xml lsm.xml usb.xml \
++	    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
++	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
++	    mac80211.xml
+ 
+ ###
+ # The build process is as follows (targets):
+@@ -186,8 +187,11 @@ quiet_cmd_fig2png = FIG2PNG $@
+ 
+ ###
+ # Rule to convert a .c file to inline XML documentation
++       gen_xml = :
++ quiet_gen_xml = echo '  GEN     $@'
++silent_gen_xml = :
+ %.xml: %.c
+-	@echo '  GEN     $@'
++	@$($(quiet)gen_xml)
+ 	@(                            \
+ 	   echo "<programlisting>";   \
+ 	   expand --tabs=8 < $< |     \
+diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
+index dc0f30c..488dd4a 100644
+--- a/Documentation/DocBook/kernel-api.tmpl
++++ b/Documentation/DocBook/kernel-api.tmpl
+@@ -297,11 +297,6 @@ X!Earch/x86/kernel/mca_32.c
+ !Ikernel/acct.c
+   </chapter>
+ 
+-  <chapter id="pmfuncs">
+-     <title>Power Management</title>
+-!Ekernel/power/pm.c
+-  </chapter>
+-
+   <chapter id="devdrivers">
+      <title>Device drivers infrastructure</title>
+      <sect1><title>Device Drivers Base</title>
+diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
+index 2e9d6b4..77c42f4 100644
+--- a/Documentation/DocBook/kernel-locking.tmpl
++++ b/Documentation/DocBook/kernel-locking.tmpl
+@@ -241,7 +241,7 @@
+    </para>
+    <para>
+      The third type is a semaphore
+-     (<filename class="headerfile">include/asm/semaphore.h</filename>): it
++     (<filename class="headerfile">include/linux/semaphore.h</filename>): it
+      can have more than one holder at any time (the number decided at
+      initialization time), although it is most commonly used as a
+      single-holder lock (a mutex).  If you can't get a semaphore, your
+@@ -290,7 +290,7 @@
+      <para>
+        If you have a data structure which is only ever accessed from
+        user context, then you can use a simple semaphore
+-       (<filename>linux/asm/semaphore.h</filename>) to protect it.  This 
++       (<filename>linux/linux/semaphore.h</filename>) to protect it.  This
+        is the most trivial case: you initialize the semaphore to the number 
+        of resources available (usually 1), and call
+        <function>down_interruptible()</function> to grab the semaphore, and 
+@@ -854,7 +854,7 @@ The change is shown below, in standard patch format: the
+  };
+ 
+ -static DEFINE_MUTEX(cache_lock);
+-+static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED;
+++static DEFINE_SPINLOCK(cache_lock);
+  static LIST_HEAD(cache);
+  static unsigned int cache_num = 0;
+  #define MAX_CACHE_SIZE 10
+@@ -1238,7 +1238,7 @@ Here is the "lock-per-object" implementation:
+ -        int popularity;
+  };
+ 
+- static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED;
++ static DEFINE_SPINLOCK(cache_lock);
+ @@ -77,6 +84,7 @@
+          obj-&gt;id = id;
+          obj-&gt;popularity = 0;
+@@ -1656,7 +1656,7 @@ the amount of locking which needs to be done.
+  #include &lt;linux/slab.h&gt;
+  #include &lt;linux/string.h&gt;
+ +#include &lt;linux/rcupdate.h&gt;
+- #include &lt;asm/semaphore.h&gt;
++ #include &lt;linux/semaphore.h&gt;
+  #include &lt;asm/errno.h&gt;
+ 
+  struct object
+diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl
+new file mode 100644
+index 0000000..97618be
+--- /dev/null
++++ b/Documentation/DocBook/kgdb.tmpl
+@@ -0,0 +1,447 @@
++<?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="kgdbOnLinux">
++ <bookinfo>
++  <title>Using kgdb and the kgdb Internals</title>
++
++  <authorgroup>
++   <author>
++    <firstname>Jason</firstname>
++    <surname>Wessel</surname>
++    <affiliation>
++     <address>
++      <email>jason.wessel at windriver.com</email>
++     </address>
++    </affiliation>
++   </author>
++  </authorgroup>
++
++  <authorgroup>
++   <author>
++    <firstname>Tom</firstname>
++    <surname>Rini</surname>
++    <affiliation>
++     <address>
++      <email>trini at kernel.crashing.org</email>
++     </address>
++    </affiliation>
++   </author>
++  </authorgroup>
++
++  <authorgroup>
++   <author>
++    <firstname>Amit S.</firstname>
++    <surname>Kale</surname>
++    <affiliation>
++     <address>
++      <email>amitkale at linsyssoft.com</email>
++     </address>
++    </affiliation>
++   </author>
++  </authorgroup>
++
++  <copyright>
++   <year>2008</year>
++   <holder>Wind River Systems, Inc.</holder>
++  </copyright>
++  <copyright>
++   <year>2004-2005</year>
++   <holder>MontaVista Software, Inc.</holder>
++  </copyright>
++  <copyright>
++   <year>2004</year>
++   <holder>Amit S. Kale</holder>
++  </copyright>
++
++  <legalnotice>
++   <para>
++   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.
++   </para>
++
++  </legalnotice>
++ </bookinfo>
++
++<toc></toc>
++  <chapter id="Introduction">
++    <title>Introduction</title>
++    <para>
++    kgdb is a source level debugger for linux kernel. It is used along
++    with gdb to debug a linux kernel.  The expectation is that gdb can
++    be used to "break in" to the kernel to inspect memory, variables
++    and look through a cal stack information similar to what an
++    application developer would use gdb for.  It is possible to place
++    breakpoints in kernel code and perform some limited execution
++    stepping.
++    </para>
++    <para>
++    Two machines are required for using kgdb. One of these machines is a
++    development machine and the other is a test machine.  The kernel
++    to be debugged runs on the test machine. The development machine
++    runs an instance of gdb against the vmlinux file which contains
++    the symbols (not boot image such as bzImage, zImage, uImage...).
++    In gdb the developer specifies the connection parameters and
++    connects to kgdb.  Depending on which kgdb I/O modules exist in
++    the kernel for a given architecture, it may be possible to debug
++    the test machine's kernel with the development machine using a
++    rs232 or ethernet connection.
++    </para>
++  </chapter>
++  <chapter id="CompilingAKernel">
++    <title>Compiling a kernel</title>
++    <para>
++    To enable <symbol>CONFIG_KGDB</symbol>, look under the "Kernel debugging"
++    and then select "KGDB: kernel debugging with remote gdb".
++    </para>
++    <para>
++    Next you should choose one of more I/O drivers to interconnect debugging
++    host and debugged target.  Early boot debugging requires a KGDB
++    I/O driver that supports early debugging and the driver must be
++    built into the kernel directly. Kgdb I/O driver configuration
++    takes place via kernel or module parameters, see following
++    chapter.
++    </para>
++    <para>
++    The kgdb test compile options are described in the kgdb test suite chapter.
++    </para>
++
++  </chapter>
++  <chapter id="EnableKGDB">
++   <title>Enable kgdb for debugging</title>
++   <para>
++   In order to use kgdb you must activate it by passing configuration
++   information to one of the kgdb I/O drivers.  If you do not pass any
++   configuration information kgdb will not do anything at all.  Kgdb
++   will only actively hook up to the kernel trap hooks if a kgdb I/O
++   driver is loaded and configured.  If you unconfigure a kgdb I/O
++   driver, kgdb will unregister all the kernel hook points.
++   </para>
++   <para>
++   All drivers can be reconfigured at run time, if
++   <symbol>CONFIG_SYSFS</symbol> and <symbol>CONFIG_MODULES</symbol>
++   are enabled, by echo'ing a new config string to
++   <constant>/sys/module/&lt;driver&gt;/parameter/&lt;option&gt;</constant>.
++   The driver can be unconfigured by passing an empty string.  You cannot
++   change the configuration while the debugger is attached.  Make sure
++   to detach the debugger with the <constant>detach</constant> command
++   prior to trying unconfigure a kgdb I/O driver.
++   </para>
++   <sect1 id="kgdbwait">
++   <title>Kernel parameter: kgdbwait</title>
++   <para>
++   The Kernel command line option <constant>kgdbwait</constant> makes
++   kgdb wait for a debugger connection during booting of a kernel.  You
++   can only use this option you compiled a kgdb I/O driver into the
++   kernel and you specified the I/O driver configuration as a kernel
++   command line option.  The kgdbwait parameter should always follow the
++   configuration parameter for the kgdb I/O driver in the kernel
++   command line else the I/O driver will not be configured prior to
++   asking the kernel to use it to wait.
++   </para>
++   <para>
++   The kernel will stop and wait as early as the I/O driver and
++   architecture will allow when you use this option.  If you build the
++   kgdb I/O driver as a kernel module kgdbwait will not do anything.
++   </para>
++   </sect1>
++  <sect1 id="kgdboc">
++  <title>Kernel parameter: kgdboc</title>
++  <para>
++  The kgdboc driver was originally an abbreviation meant to stand for
++  "kgdb over console".  Kgdboc is designed to work with a single
++  serial port. It was meant to cover the circumstance
++  where you wanted to use a serial console as your primary console as
++  well as using it to perform kernel debugging.  Of course you can
++  also use kgdboc without assigning a console to the same port.
++  </para>
++  <sect2 id="UsingKgdboc">
++  <title>Using kgdboc</title>
++  <para>
++  You can configure kgdboc via sysfs or a module or kernel boot line
++  parameter depending on if you build with CONFIG_KGDBOC as a module
++  or built-in.
++  <orderedlist>
++  <listitem><para>From the module load or build-in</para>
++  <para><constant>kgdboc=&lt;tty-device&gt;,[baud]</constant></para>
++  <para>
++  The example here would be if your console port was typically ttyS0, you would use something like <constant>kgdboc=ttyS0,115200</constant> or on the ARM Versatile AB you would likely use <constant>kgdboc=ttyAMA0,115200</constant>
++  </para>
++  </listitem>
++  <listitem><para>From sysfs</para>
++  <para><constant>echo ttyS0 &gt; /sys/module/kgdboc/parameters/kgdboc</constant></para>
++  </listitem>
++  </orderedlist>
++  </para>
++  <para>
++  NOTE: Kgdboc does not support interrupting the target via the
++  gdb remote protocol.  You must manually send a sysrq-g unless you
++  have a proxy that splits console output to a terminal problem and
++  has a separate port for the debugger to connect to that sends the
++  sysrq-g for you.
++  </para>
++  <para>When using kgdboc with no debugger proxy, you can end up
++  connecting the debugger for one of two entry points.  If an
++  exception occurs after you have loaded kgdboc a message should print
++  on the console stating it is waiting for the debugger.  In case you
++  disconnect your terminal program and then connect the debugger in
++  its place.  If you want to interrupt the target system and forcibly
++  enter a debug session you have to issue a Sysrq sequence and then
++  type the letter <constant>g</constant>.  Then you disconnect the
++  terminal session and connect gdb.  Your options if you don't like
++  this are to hack gdb to send the sysrq-g for you as well as on the
++  initial connect, or to use a debugger proxy that allows an
++  unmodified gdb to do the debugging.
++  </para>
++  </sect2>
++  </sect1>
++  <sect1 id="kgdbcon">
++  <title>Kernel parameter: kgdbcon</title>
++  <para>
++  Kgdb supports using the gdb serial protocol to send console messages
++  to the debugger when the debugger is connected and running.  There
++  are two ways to activate this feature.
++  <orderedlist>
++  <listitem><para>Activate with the kernel command line option:</para>
++  <para><constant>kgdbcon</constant></para>
++  </listitem>
++  <listitem><para>Use sysfs before configuring an io driver</para>
++  <para>
++  <constant>echo 1 &gt; /sys/module/kgdb/parameters/kgdb_use_con</constant>
++  </para>
++  <para>
++  NOTE: If you do this after you configure the kgdb I/O driver, the
++  setting will not take effect until the next point the I/O is
++  reconfigured.
++  </para>
++  </listitem>
++  </orderedlist>
++  </para>
++  <para>
++  IMPORTANT NOTE: Using this option with kgdb over the console
++  (kgdboc) or kgdb over ethernet (kgdboe) is not supported.
++  </para>
++  </sect1>
++  </chapter>
++  <chapter id="ConnectingGDB">
++  <title>Connecting gdb</title>
++    <para>
++    If you are using kgdboc, you need to have used kgdbwait as a boot
++    argument, issued a sysrq-g, or the system you are going to debug
++    has already taken an exception and is waiting for the debugger to
++    attach before you can connect gdb.
++    </para>
++    <para>
++    If you are not using different kgdb I/O driver other than kgdboc,
++    you should be able to connect and the target will automatically
++    respond.
++    </para>
++    <para>
++    Example (using a serial port):
++    </para>
++    <programlisting>
++    % gdb ./vmlinux
++    (gdb) set remotebaud 115200
++    (gdb) target remote /dev/ttyS0
++    </programlisting>
++    <para>
++    Example (kgdb to a terminal server):
++    </para>
++    <programlisting>
++    % gdb ./vmlinux
++    (gdb) target remote udp:192.168.2.2:6443
++    </programlisting>
++    <para>
++    Example (kgdb over ethernet):
++    </para>
++    <programlisting>
++    % gdb ./vmlinux
++    (gdb) target remote udp:192.168.2.2:6443
++    </programlisting>
++    <para>
++    Once connected, you can debug a kernel the way you would debug an
++    application program.
++    </para>
++    <para>
++    If you are having problems connecting or something is going
++    seriously wrong while debugging, it will most often be the case
++    that you want to enable gdb to be verbose about its target
++    communications.  You do this prior to issuing the <constant>target
++    remote</constant> command by typing in: <constant>set remote debug 1</constant>
++    </para>
++  </chapter>
++  <chapter id="KGDBTestSuite">
++    <title>kgdb Test Suite</title>
++    <para>
++    When kgdb is enabled in the kernel config you can also elect to
++    enable the config parameter KGDB_TESTS.  Turning this on will
++    enable a special kgdb I/O module which is designed to test the
++    kgdb internal functions.
++    </para>
++    <para>
++    The kgdb tests are mainly intended for developers to test the kgdb
++    internals as well as a tool for developing a new kgdb architecture
++    specific implementation.  These tests are not really for end users
++    of the Linux kernel.  The primary source of documentation would be
++    to look in the drivers/misc/kgdbts.c file.
++    </para>
++    <para>
++    The kgdb test suite can also be configured at compile time to run
++    the core set of tests by setting the kernel config parameter
++    KGDB_TESTS_ON_BOOT.  This particular option is aimed at automated
++    regression testing and does not require modifying the kernel boot
++    config arguments.  If this is turned on, the kgdb test suite can
++    be disabled by specifying "kgdbts=" as a kernel boot argument.
++    </para>
++  </chapter>
++  <chapter id="CommonBackEndReq">
++  <title>KGDB Internals</title>
++  <sect1 id="kgdbArchitecture">
++    <title>Architecture Specifics</title>
++      <para>
++      Kgdb is organized into three basic components:
++      <orderedlist>
++      <listitem><para>kgdb core</para>
++      <para>
++      The kgdb core is found in kernel/kgdb.c.  It contains:
++      <itemizedlist>
++      <listitem><para>All the logic to implement the gdb serial protocol</para></listitem>
++      <listitem><para>A generic OS exception handler which includes sync'ing the processors into a stopped state on an multi cpu system.</para></listitem>
++      <listitem><para>The API to talk to the kgdb I/O drivers</para></listitem>
++      <listitem><para>The API to make calls to the arch specific kgdb implementation</para></listitem>
++      <listitem><para>The logic to perform safe memory reads and writes to memory while using the debugger</para></listitem>
++      <listitem><para>A full implementation for software breakpoints unless overridden by the arch</para></listitem>
++      </itemizedlist>
++      </para>
++      </listitem>
++      <listitem><para>kgdb arch specific implementation</para>
++      <para>
++      This implementation is generally found in arch/*/kernel/kgdb.c.
++      As an example, arch/x86/kernel/kgdb.c contains the specifics to
++      implement HW breakpoint as well as the initialization to
++      dynamically register and unregister for the trap handlers on
++      this architecture.  The arch specific portion implements:
++      <itemizedlist>
++      <listitem><para>contains an arch specific trap catcher which
++      invokes kgdb_handle_exception() to start kgdb about doing its
++      work</para></listitem>
++      <listitem><para>translation to and from gdb specific packet format to pt_regs</para></listitem>
++      <listitem><para>Registration and unregistration of architecture specific trap hooks</para></listitem>
++      <listitem><para>Any special exception handling and cleanup</para></listitem>
++      <listitem><para>NMI exception handling and cleanup</para></listitem>
++      <listitem><para>(optional)HW breakpoints</para></listitem>
++      </itemizedlist>
++      </para>
++      </listitem>
++      <listitem><para>kgdb I/O driver</para>
++      <para>
++      Each kgdb I/O driver has to provide an implemenation for the following:
++      <itemizedlist>
++      <listitem><para>configuration via builtin or module</para></listitem>
++      <listitem><para>dynamic configuration and kgdb hook registration calls</para></listitem>
++      <listitem><para>read and write character interface</para></listitem>
++      <listitem><para>A cleanup handler for unconfiguring from the kgdb core</para></listitem>
++      <listitem><para>(optional) Early debug methodology</para></listitem>
++      </itemizedlist>
++      Any given kgdb I/O driver has to operate very closely with the
++      hardware and must do it in such a way that does not enable
++      interrupts or change other parts of the system context without
++      completely restoring them. The kgdb core will repeatedly "poll"
++      a kgdb I/O driver for characters when it needs input.  The I/O
++      driver is expected to return immediately if there is no data
++      available.  Doing so allows for the future possibility to touch
++      watch dog hardware in such a way as to have a target system not
++      reset when these are enabled.
++      </para>
++      </listitem>
++      </orderedlist>
++      </para>
++      <para>
++      If you are intent on adding kgdb architecture specific support
++      for a new architecture, the architecture should define
++      <constant>HAVE_ARCH_KGDB</constant> in the architecture specific
++      Kconfig file.  This will enable kgdb for the architecture, and
++      at that point you must create an architecture specific kgdb
++      implementation.
++      </para>
++      <para>
++      There are a few flags which must be set on every architecture in
++      their &lt;asm/kgdb.h&gt; file.  These are:
++      <itemizedlist>
++        <listitem>
++	  <para>
++	  NUMREGBYTES: The size in bytes of all of the registers, so
++	  that we can ensure they will all fit into a packet.
++	  </para>
++	  <para>
++	  BUFMAX: The size in bytes of the buffer GDB will read into.
++	  This must be larger than NUMREGBYTES.
++	  </para>
++	  <para>
++	  CACHE_FLUSH_IS_SAFE: Set to 1 if it is always safe to call
++	  flush_cache_range or flush_icache_range.  On some architectures,
++	  these functions may not be safe to call on SMP since we keep other
++	  CPUs in a holding pattern.
++	  </para>
++	</listitem>
++      </itemizedlist>
++      </para>
++      <para>
++      There are also the following functions for the common backend,
++      found in kernel/kgdb.c, that must be supplied by the
++      architecture-specific backend unless marked as (optional), in
++      which case a default function maybe used if the architecture
++      does not need to provide a specific implementation.
++      </para>
++!Iinclude/linux/kgdb.h
++  </sect1>
++  <sect1 id="kgdbocDesign">
++  <title>kgdboc internals</title>
++  <para>
++  The kgdboc driver is actually a very thin driver that relies on the
++  underlying low level to the hardware driver having "polling hooks"
++  which the to which the tty driver is attached.  In the initial
++  implementation of kgdboc it the serial_core was changed to expose a
++  low level uart hook for doing polled mode reading and writing of a
++  single character while in an atomic context.  When kgdb makes an I/O
++  request to the debugger, kgdboc invokes a call back in the serial
++  core which in turn uses the call back in the uart driver.  It is
++  certainly possible to extend kgdboc to work with non-uart based
++  consoles in the future.
++  </para>
++  <para>
++  When using kgdboc with a uart, the uart driver must implement two callbacks in the <constant>struct uart_ops</constant>. Example from drivers/8250.c:<programlisting>
++#ifdef CONFIG_CONSOLE_POLL
++	.poll_get_char = serial8250_get_poll_char,
++	.poll_put_char = serial8250_put_poll_char,
++#endif
++  </programlisting>
++  Any implementation specifics around creating a polling driver use the
++  <constant>#ifdef CONFIG_CONSOLE_POLL</constant>, as shown above.
++  Keep in mind that polling hooks have to be implemented in such a way
++  that they can be called from an atomic context and have to restore
++  the state of the uart chip on return such that the system can return
++  to normal when the debugger detaches.  You need to be very careful
++  with any kind of lock you consider, because failing here is most
++  going to mean pressing the reset button.
++  </para>
++  </sect1>
++  </chapter>
++  <chapter id="credits">
++     <title>Credits</title>
++	<para>
++		The following people have contributed to this document:
++		<orderedlist>
++			<listitem><para>Amit Kale<email>amitkale at linsyssoft.com</email></para></listitem>
++			<listitem><para>Tom Rini<email>trini at kernel.crashing.org</email></para></listitem>
++		</orderedlist>
++                In March 2008 this document was completely rewritten by:
++		<itemizedlist>
++		<listitem><para>Jason Wessel<email>jason.wessel at windriver.com</email></para></listitem>
++		</itemizedlist>
++	</para>
++  </chapter>
++</book>
++
+diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl
+new file mode 100644
+index 0000000..b651e0a
+--- /dev/null
++++ b/Documentation/DocBook/mac80211.tmpl
+@@ -0,0 +1,335 @@
++<?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 at sipsolutions.net</email></address>
++        </affiliation>
++      </author>
++    </authorgroup>
++
++    <copyright>
++      <year>2007</year>
++      <year>2008</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_if_types
++!Finclude/net/mac80211.h ieee80211_if_init_conf
++!Finclude/net/mac80211.h ieee80211_if_conf
++    </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>Alignment issues</title>
++        <para>TBD</para>
++      </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_control
++!Finclude/net/mac80211.h ieee80211_tx_status_flags
++!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_get_hdrlen_from_skb
++!Finclude/net/mac80211.h ieee80211_get_hdrlen
++!Finclude/net/mac80211.h ieee80211_wake_queue
++!Finclude/net/mac80211.h ieee80211_stop_queue
++!Finclude/net/mac80211.h ieee80211_start_queues
++!Finclude/net/mac80211.h ieee80211_stop_queues
++!Finclude/net/mac80211.h ieee80211_wake_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="qos">
++      <title>Multiple queues and QoS support</title>
++      <para>TBD</para>
++!Finclude/net/mac80211.h ieee80211_tx_queue_params
++!Finclude/net/mac80211.h ieee80211_tx_queue_stats_data
++!Finclude/net/mac80211.h ieee80211_tx_queue
++    </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/DocBook/writing_usb_driver.tmpl b/Documentation/DocBook/writing_usb_driver.tmpl
+index d4188d4..eeff19c 100644
+--- a/Documentation/DocBook/writing_usb_driver.tmpl
++++ b/Documentation/DocBook/writing_usb_driver.tmpl
+@@ -100,8 +100,8 @@
+       useful documents, at the USB home page (see Resources). An excellent
+       introduction to the Linux USB subsystem can be found at the USB Working
+       Devices List (see Resources). It explains how the Linux USB subsystem is
+-      structured and introduces the reader to the concept of USB urbs, which
+-      are essential to USB drivers.
++      structured and introduces the reader to the concept of USB urbs
++      (USB Request Blocks), which are essential to USB drivers.
+   </para>
+   <para>
+       The first thing a Linux USB driver needs to do is register itself with
+@@ -162,8 +162,8 @@ static int __init usb_skel_init(void)
+ module_init(usb_skel_init);
+   </programlisting>
+   <para>
+-      When the driver is unloaded from the system, it needs to unregister
+-      itself with the USB subsystem. This is done with the usb_unregister
++      When the driver is unloaded from the system, it needs to deregister
++      itself with the USB subsystem. This is done with the usb_deregister
+       function:
+   </para>
+   <programlisting>
+@@ -232,7 +232,7 @@ static int skel_probe(struct usb_interface *interface,
+      were passed to the USB subsystem will be called from a user program trying
+      to talk to the device. The first function called will be open, as the
+      program tries to open the device for I/O. We increment our private usage
+-     count and save off a pointer to our internal structure in the file
++     count and save a pointer to our internal structure in the file
+      structure. This is done so that future calls to file operations will
+      enable the driver to determine which device the user is addressing.  All
+      of this is done with the following code:
+@@ -252,8 +252,8 @@ file->private_data = dev;
+      send to the device based on the size of the write urb it has created (this
+      size depends on the size of the bulk out end point that the device has).
+      Then it copies the data from user space to kernel space, points the urb to
+-     the data and submits the urb to the USB subsystem.  This can be shown in
+-     he following code:
++     the data and submits the urb to the USB subsystem.  This can be seen in
++     the following code:
+   </para>
+   <programlisting>
+ /* we can only write as much as 1 urb will hold */
+diff --git a/Documentation/HOWTO b/Documentation/HOWTO
+index 5483561..0291ade 100644
+--- a/Documentation/HOWTO
++++ b/Documentation/HOWTO
+@@ -249,9 +249,11 @@ process is as follows:
+     release a new -rc kernel every week.
+   - Process continues until the kernel is considered "ready", the
+     process should last around 6 weeks.
+-  - A list of known regressions present in each -rc release is
+-    tracked at the following URI:
+-    http://kernelnewbies.org/known_regressions
++  - Known regressions in each release are periodically posted to the 
++    linux-kernel mailing list.  The goal is to reduce the length of 
++    that list to zero before declaring the kernel to be "ready," but, in
++    the real world, a small number of regressions often remain at 
++    release time.
+ 
+ It is worth mentioning what Andrew Morton wrote on the linux-kernel
+ mailing list about kernel releases:
+@@ -261,7 +263,7 @@ mailing list about kernel releases:
+ 
+ 2.6.x.y -stable kernel tree
+ ---------------------------
+-Kernels with 4 digit versions are -stable kernels. They contain
++Kernels with 4-part versions are -stable kernels. They contain
+ relatively small and critical fixes for security problems or significant
+ regressions discovered in a given 2.6.x kernel.
+ 
+@@ -273,7 +275,10 @@ If no 2.6.x.y kernel is available, then the highest numbered 2.6.x
+ kernel is the current stable kernel.
+ 
+ 2.6.x.y are maintained by the "stable" team <stable at kernel.org>, and are
+-released almost every other week.
++released as needs dictate.  The normal release period is approximately 
++two weeks, but it can be longer if there are no pressing problems.  A
++security-related problem, instead, can cause a release to happen almost
++instantly.
+ 
+ The file Documentation/stable_kernel_rules.txt in the kernel tree
+ documents what kinds of changes are acceptable for the -stable tree, and
+@@ -298,7 +303,9 @@ a while Andrew or the subsystem maintainer pushes it on to Linus for
+ inclusion in mainline.
+ 
+ It is heavily encouraged that all new patches get tested in the -mm tree
+-before they are sent to Linus for inclusion in the main kernel tree.
++before they are sent to Linus for inclusion in the main kernel tree.  Code
++which does not make an appearance in -mm before the opening of the merge
++window will prove hard to merge into the mainline.
+ 
+ These kernels are not appropriate for use on systems that are supposed
+ to be stable and they are more risky to run than any of the other
+@@ -354,11 +361,12 @@ Here is a list of some of the different kernel trees available:
+     - SCSI, James Bottomley <James.Bottomley at SteelEye.com>
+ 	git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
+ 
++    - x86, Ingo Molnar <mingo at elte.hu>
++	git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
++
+   quilt trees:
+-    - USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <gregkh at suse.de>
++    - USB, Driver Core, and I2C, Greg Kroah-Hartman <gregkh at suse.de>
+ 	kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
+-    - x86-64, partly i386, Andi Kleen <ak at suse.de>
+-        ftp.firstfloor.org:/pub/ak/x86_64/quilt/
+ 
+   Other kernel trees can be found listed at http://git.kernel.org/ and in
+   the MAINTAINERS file.
+@@ -392,8 +400,8 @@ If you want to be advised of the future bug reports, you can subscribe to the
+ bugme-new mailing list (only new bug reports are mailed here) or to the
+ bugme-janitor mailing list (every change in the bugzilla is mailed here)
+ 
+-	http://lists.osdl.org/mailman/listinfo/bugme-new
+-	http://lists.osdl.org/mailman/listinfo/bugme-janitors
++	http://lists.linux-foundation.org/mailman/listinfo/bugme-new
++	http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
+ 
+ 
+ 
+diff --git a/Documentation/PCI/00-INDEX b/Documentation/PCI/00-INDEX
+new file mode 100644
+index 0000000..49f4394
+--- /dev/null
++++ b/Documentation/PCI/00-INDEX
+@@ -0,0 +1,12 @@
++00-INDEX
++	- this file
++PCI-DMA-mapping.txt
++	- info for PCI drivers using DMA portably across all platforms
++PCIEBUS-HOWTO.txt
++	- a guide describing the PCI Express Port Bus driver
++pci-error-recovery.txt
++	- info on PCI error recovery
++pci.txt
++	- info on the PCI subsystem for device driver authors
++pcieaer-howto.txt
++	- the PCI Express Advanced Error Reporting Driver Guide HOWTO
+diff --git a/Documentation/PCI/PCIEBUS-HOWTO.txt b/Documentation/PCI/PCIEBUS-HOWTO.txt
+new file mode 100644
+index 0000000..9a07e38
+--- /dev/null
++++ b/Documentation/PCI/PCIEBUS-HOWTO.txt
+@@ -0,0 +1,217 @@
++		The PCI Express Port Bus Driver Guide HOWTO
++	Tom L Nguyen tom.l.nguyen at intel.com
++			11/03/2004
++
++1. About this guide
++
++This guide describes the basics of the PCI Express Port Bus driver
++and provides information on how to enable the service drivers to
++register/unregister with the PCI Express Port Bus Driver.
++
++2. Copyright 2004 Intel Corporation
++
++3. What is the PCI Express Port Bus Driver
++
++A PCI Express Port is a logical PCI-PCI Bridge structure. There
++are two types of PCI Express Port: the Root Port and the Switch
++Port. The Root Port originates a PCI Express link from a PCI Express
++Root Complex and the Switch Port connects PCI Express links to
++internal logical PCI buses. The Switch Port, which has its secondary
++bus representing the switch's internal routing logic, is called the
++switch's Upstream Port. The switch's Downstream Port is bridging from
++switch's internal routing bus to a bus representing the downstream
++PCI Express link from the PCI Express Switch.
++
++A PCI Express Port can provide up to four distinct functions,
++referred to in this document as services, depending on its port type.
++PCI Express Port's services include native hotplug support (HP),
++power management event support (PME), advanced error reporting
++support (AER), and virtual channel support (VC). These services may
++be handled by a single complex driver or be individually distributed
++and handled by corresponding service drivers.
++
++4. Why use the PCI Express Port Bus Driver?
++
++In existing Linux kernels, the Linux Device Driver Model allows a
++physical device to be handled by only a single driver. The PCI
++Express Port is a PCI-PCI Bridge device with multiple distinct
++services. To maintain a clean and simple solution each service
++may have its own software service driver. In this case several
++service drivers will compete for a single PCI-PCI Bridge device.
++For example, if the PCI Express Root Port native hotplug service
++driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
++kernel therefore does not load other service drivers for that Root
++Port. In other words, it is impossible to have multiple service
++drivers load and run on a PCI-PCI Bridge device simultaneously
++using the current driver model.
++
++To enable multiple service drivers running simultaneously requires
++having a PCI Express Port Bus driver, which manages all populated
++PCI Express Ports and distributes all provided service requests
++to the corresponding service drivers as required. Some key
++advantages of using the PCI Express Port Bus driver are listed below:
++
++	- Allow multiple service drivers to run simultaneously on
++	  a PCI-PCI Bridge Port device.
++
++	- Allow service drivers implemented in an independent
++	  staged approach.
++
++	- Allow one service driver to run on multiple PCI-PCI Bridge
++	  Port devices.
++
++	- Manage and distribute resources of a PCI-PCI Bridge Port
++	  device to requested service drivers.
++
++5. Configuring the PCI Express Port Bus Driver vs. Service Drivers
++
++5.1 Including the PCI Express Port Bus Driver Support into the Kernel
++
++Including the PCI Express Port Bus driver depends on whether the PCI
++Express support is included in the kernel config. The kernel will
++automatically include the PCI Express Port Bus driver as a kernel
++driver when the PCI Express support is enabled in the kernel.
++
++5.2 Enabling Service Driver Support
++
++PCI device drivers are implemented based on Linux Device Driver Model.
++All service drivers are PCI device drivers. As discussed above, it is
++impossible to load any service driver once the kernel has loaded the
++PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
++Model requires some minimal changes on existing service drivers that
++imposes no impact on the functionality of existing service drivers.
++
++A service driver is required to use the two APIs shown below to
++register its service with the PCI Express Port Bus driver (see
++section 5.2.1 & 5.2.2). It is important that a service driver
++initializes the pcie_port_service_driver data structure, included in
++header file /include/linux/pcieport_if.h, before calling these APIs.
++Failure to do so will result an identity mismatch, which prevents
++the PCI Express Port Bus driver from loading a service driver.
++
++5.2.1 pcie_port_service_register
++
++int pcie_port_service_register(struct pcie_port_service_driver *new)
++
++This API replaces the Linux Driver Model's pci_module_init API. A
++service driver should always calls pcie_port_service_register at
++module init. Note that after service driver being loaded, calls
++such as pci_enable_device(dev) and pci_set_master(dev) are no longer
++necessary since these calls are executed by the PCI Port Bus driver.
++
++5.2.2 pcie_port_service_unregister
++
++void pcie_port_service_unregister(struct pcie_port_service_driver *new)
++
++pcie_port_service_unregister replaces the Linux Driver Model's
++pci_unregister_driver. It's always called by service driver when a
++module exits.
++
++5.2.3 Sample Code
++
++Below is sample service driver code to initialize the port service
++driver data structure.
++
++static struct pcie_port_service_id service_id[] = { {
++	.vendor = PCI_ANY_ID,
++	.device = PCI_ANY_ID,
++	.port_type = PCIE_RC_PORT,
++	.service_type = PCIE_PORT_SERVICE_AER,
++	}, { /* end: all zeroes */ }
++};
++
++static struct pcie_port_service_driver root_aerdrv = {
++	.name		= (char *)device_name,
++	.id_table	= &service_id[0],
++
++	.probe		= aerdrv_load,
++	.remove		= aerdrv_unload,
++
++	.suspend	= aerdrv_suspend,
++	.resume		= aerdrv_resume,
++};
++
++Below is a sample code for registering/unregistering a service
++driver.
++
++static int __init aerdrv_service_init(void)
++{
++	int retval = 0;
++
++	retval = pcie_port_service_register(&root_aerdrv);
++	if (!retval) {
++		/*
++		 * FIX ME
++		 */
++	}
++	return retval;
++}
++
++static void __exit aerdrv_service_exit(void)
++{
++	pcie_port_service_unregister(&root_aerdrv);
++}
++
++module_init(aerdrv_service_init);
++module_exit(aerdrv_service_exit);
++
++6. Possible Resource Conflicts
++
++Since all service drivers of a PCI-PCI Bridge Port device are
++allowed to run simultaneously, below lists a few of possible resource
++conflicts with proposed solutions.
++
++6.1 MSI Vector Resource
++
++The MSI capability structure enables a device software driver to call
++pci_enable_msi to request MSI based interrupts. Once MSI interrupts
++are enabled on a device, it stays in this mode until a device driver
++calls pci_disable_msi to disable MSI interrupts and revert back to
++INTx emulation mode. Since service drivers of the same PCI-PCI Bridge
++port share the same physical device, if an individual service driver
++calls pci_enable_msi/pci_disable_msi it may result unpredictable
++behavior. For example, two service drivers run simultaneously on the
++same physical Root Port. Both service drivers call pci_enable_msi to
++request MSI based interrupts. A service driver may not know whether
++any other service drivers have run on this Root Port. If either one
++of them calls pci_disable_msi, it puts the other service driver
++in a wrong interrupt mode.
++
++To avoid this situation all service drivers are not permitted to
++switch interrupt mode on its device. The PCI Express Port Bus driver
++is responsible for determining the interrupt mode and this should be
++transparent to service drivers. Service drivers need to know only
++the vector IRQ assigned to the field irq of struct pcie_device, which
++is passed in when the PCI Express Port Bus driver probes each service
++driver. Service drivers should use (struct pcie_device*)dev->irq to
++call request_irq/free_irq. In addition, the interrupt mode is stored
++in the field interrupt_mode of struct pcie_device.
++
++6.2 MSI-X Vector Resources
++
++Similar to the MSI a device driver for an MSI-X capable device can
++call pci_enable_msix to request MSI-X interrupts. All service drivers
++are not permitted to switch interrupt mode on its device. The PCI
++Express Port Bus driver is responsible for determining the interrupt
++mode and this should be transparent to service drivers. Any attempt
++by service driver to call pci_enable_msix/pci_disable_msix may
++result unpredictable behavior. Service drivers should use
++(struct pcie_device*)dev->irq and call request_irq/free_irq.
++
++6.3 PCI Memory/IO Mapped Regions
++
++Service drivers for PCI Express Power Management (PME), Advanced
++Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
++PCI configuration space on the PCI Express port. In all cases the
++registers accessed are independent of each other. This patch assumes
++that all service drivers will be well behaved and not overwrite
++other service driver's configuration settings.
++
++6.4 PCI Config Registers
++
++Each service driver runs its PCI config operations on its own
++capability structure except the PCI Express capability structure, in
++which Root Control register and Device Control register are shared
++between PME and AER. This patch assumes that all service drivers
++will be well behaved and not overwrite other service driver's
++configuration settings.
+diff --git a/Documentation/PCI/pci-error-recovery.txt b/Documentation/PCI/pci-error-recovery.txt
+new file mode 100644
+index 0000000..6650af4
+--- /dev/null
++++ b/Documentation/PCI/pci-error-recovery.txt
+@@ -0,0 +1,396 @@
++
++                       PCI Error Recovery
++                       ------------------
++                        February 2, 2006
++
++                 Current document maintainer:
++             Linas Vepstas <linas at austin.ibm.com>
++
++
++Many PCI bus controllers are able to detect a variety of hardware
++PCI errors on the bus, such as parity errors on the data and address
++busses, as well as SERR and PERR errors.  Some of the more advanced
++chipsets are able to deal with these errors; these include PCI-E chipsets,
++and the PCI-host bridges found on IBM Power4 and Power5-based pSeries
++boxes. A typical action taken is to disconnect the affected device,
++halting all I/O to it.  The goal of a disconnection is to avoid system
++corruption; for example, to halt system memory corruption due to DMA's
++to "wild" addresses. Typically, a reconnection mechanism is also
++offered, so that the affected PCI device(s) are reset and put back
++into working condition. The reset phase requires coordination
++between the affected device drivers and the PCI controller chip.
++This document describes a generic API for notifying device drivers
++of a bus disconnection, and then performing error recovery.
++This API is currently implemented in the 2.6.16 and later kernels.
++
++Reporting and recovery is performed in several steps. First, when
++a PCI hardware error has resulted in a bus disconnect, that event
++is reported as soon as possible to all affected device drivers,
++including multiple instances of a device driver on multi-function
++cards. This allows device drivers to avoid deadlocking in spinloops,
++waiting for some i/o-space register to change, when it never will.
++It also gives the drivers a chance to defer incoming I/O as
++needed.
++
++Next, recovery is performed in several stages. Most of the complexity
++is forced by the need to handle multi-function devices, that is,
++devices that have multiple device drivers associated with them.
++In the first stage, each driver is allowed to indicate what type
++of reset it desires, the choices being a simple re-enabling of I/O
++or requesting a hard reset (a full electrical #RST of the PCI card).
++If any driver requests a full reset, that is what will be done.
++
++After a full reset and/or a re-enabling of I/O, all drivers are
++again notified, so that they may then perform any device setup/config
++that may be required.  After these have all completed, a final
++"resume normal operations" event is sent out.
++
++The biggest reason for choosing a kernel-based implementation rather
++than a user-space implementation was the need to deal with bus
++disconnects of PCI devices attached to storage media, and, in particular,
++disconnects from devices holding the root file system.  If the root
++file system is disconnected, a user-space mechanism would have to go
++through a large number of contortions to complete recovery. Almost all
++of the current Linux file systems are not tolerant of disconnection
++from/reconnection to their underlying block device. By contrast,
++bus errors are easy to manage in the device driver. Indeed, most
++device drivers already handle very similar recovery procedures;
++for example, the SCSI-generic layer already provides significant
++mechanisms for dealing with SCSI bus errors and SCSI bus resets.
++
++
++Detailed Design
++---------------
++Design and implementation details below, based on a chain of
++public email discussions with Ben Herrenschmidt, circa 5 April 2005.
++
++The error recovery API support is exposed to the driver in the form of
++a structure of function pointers pointed to by a new field in struct
++pci_driver. A driver that fails to provide the structure is "non-aware",
++and the actual recovery steps taken are platform dependent.  The
++arch/powerpc implementation will simulate a PCI hotplug remove/add.
++
++This structure has the form:
++struct pci_error_handlers
++{
++	int (*error_detected)(struct pci_dev *dev, enum pci_channel_state);
++	int (*mmio_enabled)(struct pci_dev *dev);
++	int (*link_reset)(struct pci_dev *dev);
++	int (*slot_reset)(struct pci_dev *dev);
++	void (*resume)(struct pci_dev *dev);
++};
++
++The possible channel states are:
++enum pci_channel_state {
++	pci_channel_io_normal,  /* I/O channel is in normal state */
++	pci_channel_io_frozen,  /* I/O to channel is blocked */
++	pci_channel_io_perm_failure, /* PCI card is dead */
++};
++
++Possible return values are:
++enum pci_ers_result {
++	PCI_ERS_RESULT_NONE,        /* no result/none/not supported in device driver */
++	PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */
++	PCI_ERS_RESULT_NEED_RESET,  /* Device driver wants slot to be reset. */
++	PCI_ERS_RESULT_DISCONNECT,  /* Device has completely failed, is unrecoverable */
++	PCI_ERS_RESULT_RECOVERED,   /* Device driver is fully recovered and operational */
++};
++
++A driver does not have to implement all of these callbacks; however,
++if it implements any, it must implement error_detected(). If a callback
++is not implemented, the corresponding feature is considered unsupported.
++For example, if mmio_enabled() and resume() aren't there, then it
++is assumed that the driver is not doing any direct recovery and requires
++a reset. If link_reset() is not implemented, the card is assumed as
++not care about link resets. Typically a driver will want to know about
++a slot_reset().
++
++The actual steps taken by a platform to recover from a PCI error
++event will be platform-dependent, but will follow the general
++sequence described below.
++
++STEP 0: Error Event
++-------------------
++PCI bus error is detect by the PCI hardware.  On powerpc, the slot
++is isolated, in that all I/O is blocked: all reads return 0xffffffff,
++all writes are ignored.
++
++
++STEP 1: Notification
++--------------------
++Platform calls the error_detected() callback on every instance of
++every driver affected by the error.
++
++At this point, the device might not be accessible anymore, depending on
++the platform (the slot will be isolated on powerpc). The driver may
++already have "noticed" the error because of a failing I/O, but this
++is the proper "synchronization point", that is, it gives the driver
++a chance to cleanup, waiting for pending stuff (timers, whatever, etc...)
++to complete; it can take semaphores, schedule, etc... everything but
++touch the device. Within this function and after it returns, the driver
++shouldn't do any new IOs. Called in task context. This is sort of a
++"quiesce" point. See note about interrupts at the end of this doc.
++
++All drivers participating in this system must implement this call.
++The driver must return one of the following result codes:
++		- PCI_ERS_RESULT_CAN_RECOVER:
++		  Driver returns this if it thinks it might be able to recover
++		  the HW by just banging IOs or if it wants to be given
++		  a chance to extract some diagnostic information (see
++		  mmio_enable, below).
++		- PCI_ERS_RESULT_NEED_RESET:
++		  Driver returns this if it can't recover without a hard
++		  slot reset.
++		- PCI_ERS_RESULT_DISCONNECT:
++		  Driver returns this if it doesn't want to recover at all.
++
++The next step taken will depend on the result codes returned by the
++drivers.
++
++If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER,
++then the platform should re-enable IOs on the slot (or do nothing in
++particular, if the platform doesn't isolate slots), and recovery
++proceeds to STEP 2 (MMIO Enable).
++
++If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET),
++then recovery proceeds to STEP 4 (Slot Reset).
++
++If the platform is unable to recover the slot, the next step
++is STEP 6 (Permanent Failure).
++
++>>> The current powerpc implementation assumes that a device driver will
++>>> *not* schedule or semaphore in this routine; the current powerpc
++>>> implementation uses one kernel thread to notify all devices;
++>>> thus, if one device sleeps/schedules, all devices are affected.
++>>> Doing better requires complex multi-threaded logic in the error
++>>> recovery implementation (e.g. waiting for all notification threads
++>>> to "join" before proceeding with recovery.)  This seems excessively
++>>> complex and not worth implementing.
++
++>>> The current powerpc implementation doesn't much care if the device
++>>> attempts I/O at this point, or not.  I/O's will fail, returning
++>>> a value of 0xff on read, and writes will be dropped. If the device
++>>> driver attempts more than 10K I/O's to a frozen adapter, it will
++>>> assume that the device driver has gone into an infinite loop, and
++>>> it will panic the kernel. There doesn't seem to be any other
++>>> way of stopping a device driver that insists on spinning on I/O.
++
++STEP 2: MMIO Enabled
++-------------------
++The platform re-enables MMIO to the device (but typically not the
++DMA), and then calls the mmio_enabled() callback on all affected
++device drivers.
++
++This is the "early recovery" call. IOs are allowed again, but DMA is
++not (hrm... to be discussed, I prefer not), with some restrictions. This
++is NOT a callback for the driver to start operations again, only to
++peek/poke at the device, extract diagnostic information, if any, and
++eventually do things like trigger a device local reset or some such,
++but not restart operations. This is callback is made if all drivers on
++a segment agree that they can try to recover and if no automatic link reset
++was performed by the HW. If the platform can't just re-enable IOs without
++a slot reset or a link reset, it wont call this callback, and instead
++will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
++
++>>> The following is proposed; no platform implements this yet:
++>>> Proposal: All I/O's should be done _synchronously_ from within
++>>> this callback, errors triggered by them will be returned via
++>>> the normal pci_check_whatever() API, no new error_detected()
++>>> callback will be issued due to an error happening here. However,
++>>> such an error might cause IOs to be re-blocked for the whole
++>>> segment, and thus invalidate the recovery that other devices
++>>> on the same segment might have done, forcing the whole segment
++>>> into one of the next states, that is, link reset or slot reset.
++
++The driver should return one of the following result codes:
++		- PCI_ERS_RESULT_RECOVERED
++		  Driver returns this if it thinks the device is fully
++		  functional and thinks it is ready to start
++		  normal driver operations again. There is no
++		  guarantee that the driver will actually be
++		  allowed to proceed, as another driver on the
++		  same segment might have failed and thus triggered a
++		  slot reset on platforms that support it.
++
++		- PCI_ERS_RESULT_NEED_RESET
++		  Driver returns this if it thinks the device is not
++		  recoverable in it's current state and it needs a slot
++		  reset to proceed.
++
++		- PCI_ERS_RESULT_DISCONNECT
++		  Same as above. Total failure, no recovery even after
++		  reset driver dead. (To be defined more precisely)
++
++The next step taken depends on the results returned by the drivers.
++If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform
++proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
++
++If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
++proceeds to STEP 4 (Slot Reset)
++
++>>> The current powerpc implementation does not implement this callback.
++
++
++STEP 3: Link Reset
++------------------
++The platform resets the link, and then calls the link_reset() callback
++on all affected device drivers.  This is a PCI-Express specific state
++and is done whenever a non-fatal error has been detected that can be
++"solved" by resetting the link. This call informs the driver of the
++reset and the driver should check to see if the device appears to be
++in working condition.
++
++The driver is not supposed to restart normal driver I/O operations
++at this point.  It should limit itself to "probing" the device to
++check it's recoverability status. If all is right, then the platform
++will call resume() once all drivers have ack'd link_reset().
++
++	Result codes:
++		(identical to STEP 3 (MMIO Enabled)
++
++The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5
++(Resume Operations).
++
++>>> The current powerpc implementation does not implement this callback.
++
++
++STEP 4: Slot Reset
++------------------
++The platform performs a soft or hard reset of the device, and then
++calls the slot_reset() callback.
++
++A soft reset consists of asserting the adapter #RST line and then
++restoring the PCI BAR's and PCI configuration header to a state
++that is equivalent to what it would be after a fresh system
++power-on followed by power-on BIOS/system firmware initialization.
++If the platform supports PCI hotplug, then the reset might be
++performed by toggling the slot electrical power off/on.
++
++It is important for the platform to restore the PCI config space
++to the "fresh poweron" state, rather than the "last state". After
++a slot reset, the device driver will almost always use its standard
++device initialization routines, and an unusual config space setup
++may result in hung devices, kernel panics, or silent data corruption.
++
++This call gives drivers the chance to re-initialize the hardware
++(re-download firmware, etc.).  At this point, the driver may assume
++that he card is in a fresh state and is fully functional. In
++particular, interrupt generation should work normally.
++
++Drivers should not yet restart normal I/O processing operations
++at this point.  If all device drivers report success on this
++callback, the platform will call resume() to complete the sequence,
++and let the driver restart normal I/O processing.
++
++A driver can still return a critical failure for this function if
++it can't get the device operational after reset.  If the platform
++previously tried a soft reset, it might now try a hard reset (power
++cycle) and then call slot_reset() again.  It the device still can't
++be recovered, there is nothing more that can be done;  the platform
++will typically report a "permanent failure" in such a case.  The
++device will be considered "dead" in this case.
++
++Drivers for multi-function cards will need to coordinate among
++themselves as to which driver instance will perform any "one-shot"
++or global device initialization. For example, the Symbios sym53cxx2
++driver performs device init only from PCI function 0:
++
+++       if (PCI_FUNC(pdev->devfn) == 0)
+++               sym_reset_scsi_bus(np, 0);
++
++	Result codes:
++		- PCI_ERS_RESULT_DISCONNECT
++		Same as above.
++
++Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
++Failure).
++
++>>> The current powerpc implementation does not currently try a
++>>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
++>>> However, it probably should.
++
++
++STEP 5: Resume Operations
++-------------------------
++The platform will call the resume() callback on all affected device
++drivers if all drivers on the segment have returned
++PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks.
++The goal of this callback is to tell the driver to restart activity,
++that everything is back and running. This callback does not return
++a result code.
++
++At this point, if a new error happens, the platform will restart
++a new error recovery sequence.
++
++STEP 6: Permanent Failure
++-------------------------
++A "permanent failure" has occurred, and the platform cannot recover
++the device.  The platform will call error_detected() with a
++pci_channel_state value of pci_channel_io_perm_failure.
++
++The device driver should, at this point, assume the worst. It should
++cancel all pending I/O, refuse all new I/O, returning -EIO to
++higher layers. The device driver should then clean up all of its
++memory and remove itself from kernel operations, much as it would
++during system shutdown.
++
++The platform will typically notify the system operator of the
++permanent failure in some way.  If the device is hotplug-capable,
++the operator will probably want to remove and replace the device.
++Note, however, not all failures are truly "permanent". Some are
++caused by over-heating, some by a poorly seated card. Many
++PCI error events are caused by software bugs, e.g. DMA's to
++wild addresses or bogus split transactions due to programming
++errors. See the discussion in powerpc/eeh-pci-error-recovery.txt
++for additional detail on real-life experience of the causes of
++software errors.
++
++
++Conclusion; General Remarks
++---------------------------
++The way those callbacks are called is platform policy. A platform with
++no slot reset capability may want to just "ignore" drivers that can't
++recover (disconnect them) and try to let other cards on the same segment
++recover. Keep in mind that in most real life cases, though, there will
++be only one driver per segment.
++
++Now, a note about interrupts. If you get an interrupt and your
++device is dead or has been isolated, there is a problem :)
++The current policy is to turn this into a platform policy.
++That is, the recovery API only requires that:
++
++ - There is no guarantee that interrupt delivery can proceed from any
++device on the segment starting from the error detection and until the
++resume callback is sent, at which point interrupts are expected to be
++fully operational.
++
++ - There is no guarantee that interrupt delivery is stopped, that is,
++a driver that gets an interrupt after detecting an error, or that detects
++an error within the interrupt handler such that it prevents proper
++ack'ing of the interrupt (and thus removal of the source) should just
++return IRQ_NOTHANDLED. It's up to the platform to deal with that
++condition, typically by masking the IRQ source during the duration of
++the error handling. It is expected that the platform "knows" which
++interrupts are routed to error-management capable slots and can deal
++with temporarily disabling that IRQ number during error processing (this
++isn't terribly complex). That means some IRQ latency for other devices
++sharing the interrupt, but there is simply no other way. High end
++platforms aren't supposed to share interrupts between many devices
++anyway :)
++
++>>> Implementation details for the powerpc platform are discussed in
++>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
++
++>>> As of this writing, there are six device drivers with patches
++>>> implementing error recovery. Not all of these patches are in
++>>> mainline yet. These may be used as "examples":
++>>>
++>>> drivers/scsi/ipr.c
++>>> drivers/scsi/sym53cxx_2
++>>> drivers/next/e100.c
++>>> drivers/net/e1000
++>>> drivers/net/ixgb
++>>> drivers/net/s2io.c
++
++The End
++-------
+diff --git a/Documentation/PCI/pci.txt b/Documentation/PCI/pci.txt
+new file mode 100644
+index 0000000..8d4dc62
+--- /dev/null
++++ b/Documentation/PCI/pci.txt
+@@ -0,0 +1,646 @@
++
++			How To Write Linux PCI Drivers
++
++		by Martin Mares <mj at ucw.cz> on 07-Feb-2000
++	updated by Grant Grundler <grundler at parisc-linux.org> on 23-Dec-2006
++
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++The world of PCI is vast and full of (mostly unpleasant) surprises.
++Since each CPU architecture implements different chip-sets and PCI devices
++have different requirements (erm, "features"), the result is the PCI support
++in the Linux kernel is not as trivial as one would wish. This short paper
++tries to introduce all potential driver authors to Linux APIs for
++PCI device drivers.
++
++A more complete resource is the third edition of "Linux Device Drivers"
++by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.
++LDD3 is available for free (under Creative Commons License) from:
++
++	http://lwn.net/Kernel/LDD3/
++
++However, keep in mind that all documents are subject to "bit rot".
++Refer to the source code if things are not working as described here.
++
++Please send questions/comments/patches about Linux PCI API to the
++"Linux PCI" <linux-pci at atrey.karlin.mff.cuni.cz> mailing list.
++
++
++
++0. Structure of PCI drivers
++~~~~~~~~~~~~~~~~~~~~~~~~~~~
++PCI drivers "discover" PCI devices in a system via pci_register_driver().
++Actually, it's the other way around. When the PCI generic code discovers
++a new device, the driver with a matching "description" will be notified.
++Details on this below.
++
++pci_register_driver() leaves most of the probing for devices to
++the PCI layer and supports online insertion/removal of devices [thus
++supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver].
++pci_register_driver() call requires passing in a table of function
++pointers and thus dictates the high level structure of a driver.
++
++Once the driver knows about a PCI device and takes ownership, the
++driver generally needs to perform the following initialization:
++
++	Enable the device
++	Request MMIO/IOP resources
++	Set the DMA mask size (for both coherent and streaming DMA)
++	Allocate and initialize shared control data (pci_allocate_coherent())
++	Access device configuration space (if needed)
++	Register IRQ handler (request_irq())
++	Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
++	Enable DMA/processing engines
++
++When done using the device, and perhaps the module needs to be unloaded,
++the driver needs to take the follow steps:
++	Disable the device from generating IRQs
++	Release the IRQ (free_irq())
++	Stop all DMA activity
++	Release DMA buffers (both streaming and coherent)
++	Unregister from other subsystems (e.g. scsi or netdev)
++	Release MMIO/IOP resources
++	Disable the device
++
++Most of these topics are covered in the following sections.
++For the rest look at LDD3 or <linux/pci.h> .
++
++If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
++the PCI functions described below are defined as inline functions either
++completely empty or just returning an appropriate error codes to avoid
++lots of ifdefs in the drivers.
++
++
++
++1. pci_register_driver() call
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++PCI device drivers call pci_register_driver() during their
++initialization with a pointer to a structure describing the driver
++(struct pci_driver):
++
++	field name	Description
++	----------	------------------------------------------------------
++	id_table	Pointer to table of device ID's the driver is
++			interested in.  Most drivers should export this
++			table using MODULE_DEVICE_TABLE(pci,...).
++
++	probe		This probing function gets called (during execution
++			of pci_register_driver() for already existing
++			devices or later if a new device gets inserted) for
++			all PCI devices which match the ID table and are not
++			"owned" by the other drivers yet. This function gets
++			passed a "struct pci_dev *" for each device whose
++			entry in the ID table matches the device. The probe
++			function returns zero when the driver chooses to
++			take "ownership" of the device or an error code
++			(negative number) otherwise.
++			The probe function always gets called from process
++			context, so it can sleep.
++
++	remove		The remove() function gets called whenever a device
++			being handled by this driver is removed (either during
++			deregistration of the driver or when it's manually
++			pulled out of a hot-pluggable slot).
++			The remove function always gets called from process
++			context, so it can sleep.
++
++	suspend		Put device into low power state.
++	suspend_late	Put device into low power state.
++
++	resume_early	Wake device from low power state.
++	resume		Wake device from low power state.
++
++		(Please see Documentation/power/pci.txt for descriptions
++		of PCI Power Management and the related functions.)
++
++	shutdown	Hook into reboot_notifier_list (kernel/sys.c).
++			Intended to stop any idling DMA operations.
++			Useful for enabling wake-on-lan (NIC) or changing
++			the power state of a device before reboot.
++			e.g. drivers/net/e100.c.
++
++	err_handler	See Documentation/PCI/pci-error-recovery.txt
++
++
++The ID table is an array of struct pci_device_id entries ending with an
++all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred
++method of declaring the table.  Each entry consists of:
++
++	vendor,device	Vendor and device ID to match (or PCI_ANY_ID)
++
++	subvendor,	Subsystem vendor and device ID to match (or PCI_ANY_ID)
++	subdevice,
++
++	class		Device class, subclass, and "interface" to match.
++			See Appendix D of the PCI Local Bus Spec or
++			include/linux/pci_ids.h for a full list of classes.
++			Most drivers do not need to specify class/class_mask
++			as vendor/device is normally sufficient.
++
++	class_mask	limit which sub-fields of the class field are compared.
++			See drivers/scsi/sym53c8xx_2/ for example of usage.
++
++	driver_data	Data private to the driver.
++			Most drivers don't need to use driver_data field.
++			Best practice is to use driver_data as an index
++			into a static list of equivalent device types,
++			instead of using it as a pointer.
++
++
++Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up
++a pci_device_id table.
++
++New PCI IDs may be added to a device driver pci_ids table at runtime
++as shown below:
++
++echo "vendor device subvendor subdevice class class_mask driver_data" > \
++/sys/bus/pci/drivers/{driver}/new_id
++
++All fields are passed in as hexadecimal values (no leading 0x).
++The vendor and device fields are mandatory, the others are optional. Users
++need pass only as many optional fields as necessary:
++	o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
++	o class and classmask fields default to 0
++	o driver_data defaults to 0UL.
++
++Once added, the driver probe routine will be invoked for any unclaimed
++PCI devices listed in its (newly updated) pci_ids list.
++
++When the driver exits, it just calls pci_unregister_driver() and the PCI layer
++automatically calls the remove hook for all devices handled by the driver.
++
++
++1.1 "Attributes" for driver functions/data
++
++Please mark the initialization and cleanup functions where appropriate
++(the corresponding macros are defined in <linux/init.h>):
++
++	__init		Initialization code. Thrown away after the driver
++			initializes.
++	__exit		Exit code. Ignored for non-modular drivers.
++
++
++	__devinit	Device initialization code.
++			Identical to __init if the kernel is not compiled
++			with CONFIG_HOTPLUG, normal function otherwise.
++	__devexit	The same for __exit.
++
++Tips on when/where to use the above attributes:
++	o The module_init()/module_exit() functions (and all
++	  initialization functions called _only_ from these)
++	  should be marked __init/__exit.
++
++	o Do not mark the struct pci_driver.
++
++	o The ID table array should be marked __devinitconst; this is done
++	  automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE().
++
++	o The probe() and remove() functions should be marked __devinit
++	  and __devexit respectively.  All initialization functions
++	  exclusively called by the probe() routine, can be marked __devinit.
++	  Ditto for remove() and __devexit.
++
++	o If mydriver_remove() is marked with __devexit(), then all address
++	  references to mydriver_remove must use __devexit_p(mydriver_remove)
++	  (in the struct pci_driver declaration for example).
++	  __devexit_p() will generate the function name _or_ NULL if the
++	  function will be discarded.  For an example, see drivers/net/tg3.c.
++
++	o Do NOT mark a function if you are not sure which mark to use.
++	  Better to not mark the function than mark the function wrong.
++
++
++
++2. How to find PCI devices manually
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++PCI drivers should have a really good reason for not using the
++pci_register_driver() interface to search for PCI devices.
++The main reason PCI devices are controlled by multiple drivers
++is because one PCI device implements several different HW services.
++E.g. combined serial/parallel port/floppy controller.
++
++A manual search may be performed using the following constructs:
++
++Searching by vendor and device ID:
++
++	struct pci_dev *dev = NULL;
++	while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev))
++		configure_device(dev);
++
++Searching by class ID (iterate in a similar way):
++
++	pci_get_class(CLASS_ID, dev)
++
++Searching by both vendor/device and subsystem vendor/device ID:
++
++	pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
++
++You can use the constant PCI_ANY_ID as a wildcard replacement for
++VENDOR_ID or DEVICE_ID.  This allows searching for any device from a
++specific vendor, for example.
++
++These functions are hotplug-safe. They increment the reference count on
++the pci_dev that they return. You must eventually (possibly at module unload)
++decrement the reference count on these devices by calling pci_dev_put().
++
++
++
++3. Device Initialization Steps
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++As noted in the introduction, most PCI drivers need the following steps
++for device initialization:
++
++	Enable the device
++	Request MMIO/IOP resources
++	Set the DMA mask size (for both coherent and streaming DMA)
++	Allocate and initialize shared control data (pci_allocate_coherent())
++	Access device configuration space (if needed)
++	Register IRQ handler (request_irq())
++	Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
++	Enable DMA/processing engines.
++
++The driver can access PCI config space registers at any time.
++(Well, almost. When running BIST, config space can go away...but
++that will just result in a PCI Bus Master Abort and config reads
++will return garbage).
++
++
++3.1 Enable the PCI device
++~~~~~~~~~~~~~~~~~~~~~~~~~
++Before touching any device registers, the driver needs to enable
++the PCI device by calling pci_enable_device(). This will:
++	o wake up the device if it was in suspended state,
++	o allocate I/O and memory regions of the device (if BIOS did not),
++	o allocate an IRQ (if BIOS did not).
++
++NOTE: pci_enable_device() can fail! Check the return value.
++
++[ OS BUG: we don't check resource allocations before enabling those
++  resources. The sequence would make more sense if we called
++  pci_request_resources() before calling pci_enable_device().
++  Currently, the device drivers can't detect the bug when when two
++  devices have been allocated the same range. This is not a common
++  problem and unlikely to get fixed soon.
++
++  This has been discussed before but not changed as of 2.6.19:
++	http://lkml.org/lkml/2006/3/2/194
++]
++
++pci_set_master() will enable DMA by setting the bus master bit
++in the PCI_COMMAND register. It also fixes the latency timer value if
++it's set to something bogus by the BIOS.
++
++If the PCI device can use the PCI Memory-Write-Invalidate transaction,
++call pci_set_mwi().  This enables the PCI_COMMAND bit for Mem-Wr-Inval
++and also ensures that the cache line size register is set correctly.
++Check the return value of pci_set_mwi() as not all architectures
++or chip-sets may support Memory-Write-Invalidate.  Alternatively,
++if Mem-Wr-Inval would be nice to have but is not required, call
++pci_try_set_mwi() to have the system do its best effort at enabling
++Mem-Wr-Inval.
++
++
++3.2 Request MMIO/IOP resources
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Memory (MMIO), and I/O port addresses should NOT be read directly
++from the PCI device config space. Use the values in the pci_dev structure
++as the PCI "bus address" might have been remapped to a "host physical"
++address by the arch/chip-set specific kernel support.
++
++See Documentation/IO-mapping.txt for how to access device registers
++or device memory.
++
++The device driver needs to call pci_request_region() to verify
++no other device is already using the same address resource.
++Conversely, drivers should call pci_release_region() AFTER
++calling pci_disable_device().
++The idea is to prevent two devices colliding on the same address range.
++
++[ See OS BUG comment above. Currently (2.6.19), The driver can only
++  determine MMIO and IO Port resource availability _after_ calling
++  pci_enable_device(). ]
++
++Generic flavors of pci_request_region() are request_mem_region()
++(for MMIO ranges) and request_region() (for IO Port ranges).
++Use these for address resources that are not described by "normal" PCI
++BARs.
++
++Also see pci_request_selected_regions() below.
++
++
++3.3 Set the DMA mask size
++~~~~~~~~~~~~~~~~~~~~~~~~~
++[ If anything below doesn't make sense, please refer to
++  Documentation/DMA-API.txt. This section is just a reminder that
++  drivers need to indicate DMA capabilities of the device and is not
++  an authoritative source for DMA interfaces. ]
++
++While all drivers should explicitly indicate the DMA capability
++(e.g. 32 or 64 bit) of the PCI bus master, devices with more than
++32-bit bus master capability for streaming data need the driver
++to "register" this capability by calling pci_set_dma_mask() with
++appropriate parameters.  In general this allows more efficient DMA
++on systems where System RAM exists above 4G _physical_ address.
++
++Drivers for all PCI-X and PCIe compliant devices must call
++pci_set_dma_mask() as they are 64-bit DMA devices.
++
++Similarly, drivers must also "register" this capability if the device
++can directly address "consistent memory" in System RAM above 4G physical
++address by calling pci_set_consistent_dma_mask().
++Again, this includes drivers for all PCI-X and PCIe compliant devices.
++Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
++64-bit DMA capable for payload ("streaming") data but not control
++("consistent") data.
++
++
++3.4 Setup shared control data
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
++memory.  See Documentation/DMA-API.txt for a full description of
++the DMA APIs. This section is just a reminder that it needs to be done
++before enabling DMA on the device.
++
++
++3.5 Initialize device registers
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Some drivers will need specific "capability" fields programmed
++or other "vendor specific" register initialized or reset.
++E.g. clearing pending interrupts.
++
++
++3.6 Register IRQ handler
++~~~~~~~~~~~~~~~~~~~~~~~~
++While calling request_irq() is the last step described here,
++this is often just another intermediate step to initialize a device.
++This step can often be deferred until the device is opened for use.
++
++All interrupt handlers for IRQ lines should be registered with IRQF_SHARED
++and use the devid to map IRQs to devices (remember that all PCI IRQ lines
++can be shared).
++
++request_irq() will associate an interrupt handler and device handle
++with an interrupt number. Historically interrupt numbers represent
++IRQ lines which run from the PCI device to the Interrupt controller.
++With MSI and MSI-X (more below) the interrupt number is a CPU "vector".
++
++request_irq() also enables the interrupt. Make sure the device is
++quiesced and does not have any interrupts pending before registering
++the interrupt handler.
++
++MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts"
++which deliver interrupts to the CPU via a DMA write to a Local APIC.
++The fundamental difference between MSI and MSI-X is how multiple
++"vectors" get allocated. MSI requires contiguous blocks of vectors
++while MSI-X can allocate several individual ones.
++
++MSI capability can be enabled by calling pci_enable_msi() or
++pci_enable_msix() before calling request_irq(). This causes
++the PCI support to program CPU vector data into the PCI device
++capability registers.
++
++If your PCI device supports both, try to enable MSI-X first.
++Only one can be enabled at a time.  Many architectures, chip-sets,
++or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix
++will fail. This is important to note since many drivers have
++two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs.
++They choose which handler to register with request_irq() based on the
++return value from pci_enable_msi/msix().
++
++There are (at least) two really good reasons for using MSI:
++1) MSI is an exclusive interrupt vector by definition.
++   This means the interrupt handler doesn't have to verify
++   its device caused the interrupt.
++
++2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed
++   to be visible to the host CPU(s) when the MSI is delivered. This
++   is important for both data coherency and avoiding stale control data.
++   This guarantee allows the driver to omit MMIO reads to flush
++   the DMA stream.
++
++See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples
++of MSI/MSI-X usage.
++
++
++
++4. PCI device shutdown
++~~~~~~~~~~~~~~~~~~~~~~~
++
++When a PCI device driver is being unloaded, most of the following
++steps need to be performed:
++
++	Disable the device from generating IRQs
++	Release the IRQ (free_irq())
++	Stop all DMA activity
++	Release DMA buffers (both streaming and consistent)
++	Unregister from other subsystems (e.g. scsi or netdev)
++	Disable device from responding to MMIO/IO Port addresses
++	Release MMIO/IO Port resource(s)
++
++
++4.1 Stop IRQs on the device
++~~~~~~~~~~~~~~~~~~~~~~~~~~~
++How to do this is chip/device specific. If it's not done, it opens
++the possibility of a "screaming interrupt" if (and only if)
++the IRQ is shared with another device.
++
++When the shared IRQ handler is "unhooked", the remaining devices
++using the same IRQ line will still need the IRQ enabled. Thus if the
++"unhooked" device asserts IRQ line, the system will respond assuming
++it was one of the remaining devices asserted the IRQ line. Since none
++of the other devices will handle the IRQ, the system will "hang" until
++it decides the IRQ isn't going to get handled and masks the IRQ (100,000
++iterations later). Once the shared IRQ is masked, the remaining devices
++will stop functioning properly. Not a nice situation.
++
++This is another reason to use MSI or MSI-X if it's available.
++MSI and MSI-X are defined to be exclusive interrupts and thus
++are not susceptible to the "screaming interrupt" problem.
++
++
++4.2 Release the IRQ
++~~~~~~~~~~~~~~~~~~~
++Once the device is quiesced (no more IRQs), one can call free_irq().
++This function will return control once any pending IRQs are handled,
++"unhook" the drivers IRQ handler from that IRQ, and finally release
++the IRQ if no one else is using it.
++
++
++4.3 Stop all DMA activity
++~~~~~~~~~~~~~~~~~~~~~~~~~
++It's extremely important to stop all DMA operations BEFORE attempting
++to deallocate DMA control data. Failure to do so can result in memory
++corruption, hangs, and on some chip-sets a hard crash.
++
++Stopping DMA after stopping the IRQs can avoid races where the
++IRQ handler might restart DMA engines.
++
++While this step sounds obvious and trivial, several "mature" drivers
++didn't get this step right in the past.
++
++
++4.4 Release DMA buffers
++~~~~~~~~~~~~~~~~~~~~~~~
++Once DMA is stopped, clean up streaming DMA first.
++I.e. unmap data buffers and return buffers to "upstream"
++owners if there is one.
++
++Then clean up "consistent" buffers which contain the control data.
++
++See Documentation/DMA-API.txt for details on unmapping interfaces.
++
++
++4.5 Unregister from other subsystems
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Most low level PCI device drivers support some other subsystem
++like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your
++driver isn't losing resources from that other subsystem.
++If this happens, typically the symptom is an Oops (panic) when
++the subsystem attempts to call into a driver that has been unloaded.
++
++
++4.6 Disable Device from responding to MMIO/IO Port addresses
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++io_unmap() MMIO or IO Port resources and then call pci_disable_device().
++This is the symmetric opposite of pci_enable_device().
++Do not access device registers after calling pci_disable_device().
++
++
++4.7 Release MMIO/IO Port Resource(s)
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Call pci_release_region() to mark the MMIO or IO Port range as available.
++Failure to do so usually results in the inability to reload the driver.
++
++
++
++5. How to access PCI config space
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++You can use pci_(read|write)_config_(byte|word|dword) to access the config
++space of a device represented by struct pci_dev *. All these functions return 0
++when successful or an error code (PCIBIOS_...) which can be translated to a text
++string by pcibios_strerror. Most drivers expect that accesses to valid PCI
++devices don't fail.
++
++If you don't have a struct pci_dev available, you can call
++pci_bus_(read|write)_config_(byte|word|dword) to access a given device
++and function on that bus.
++
++If you access fields in the standard portion of the config header, please
++use symbolic names of locations and bits declared in <linux/pci.h>.
++
++If you need to access Extended PCI Capability registers, just call
++pci_find_capability() for the particular capability and it will find the
++corresponding register block for you.
++
++
++
++6. Other interesting functions
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++pci_find_slot()			Find pci_dev corresponding to given bus and
++				slot numbers.
++pci_set_power_state()		Set PCI Power Management state (0=D0 ... 3=D3)
++pci_find_capability()		Find specified capability in device's capability
++				list.
++pci_resource_start()		Returns bus start address for a given PCI region
++pci_resource_end()		Returns bus end address for a given PCI region
++pci_resource_len()		Returns the byte length of a PCI region
++pci_set_drvdata()		Set private driver data pointer for a pci_dev
++pci_get_drvdata()		Return private driver data pointer for a pci_dev
++pci_set_mwi()			Enable Memory-Write-Invalidate transactions.
++pci_clear_mwi()			Disable Memory-Write-Invalidate transactions.
++
++
++
++7. Miscellaneous hints
++~~~~~~~~~~~~~~~~~~~~~~
++
++When displaying PCI device names to the user (for example when a driver wants
++to tell the user what card has it found), please use pci_name(pci_dev).
++
++Always refer to the PCI devices by a pointer to the pci_dev structure.
++All PCI layer functions use this identification and it's the only
++reasonable one. Don't use bus/slot/function numbers except for very
++special purposes -- on systems with multiple primary buses their semantics
++can be pretty complex.
++
++Don't try to turn on Fast Back to Back writes in your driver.  All devices
++on the bus need to be capable of doing it, so this is something which needs
++to be handled by platform and generic code, not individual drivers.
++
++
++
++8. Vendor and device identifications
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++One is not not required to add new device ids to include/linux/pci_ids.h.
++Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
++
++PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
++hex numbers (vendor controlled) and normally used only in a single
++location, the pci_device_id table.
++
++Please DO submit new vendor/device ids to pciids.sourceforge.net project.
++
++
++
++9. Obsolete functions
++~~~~~~~~~~~~~~~~~~~~~
++
++There are several functions which you might come across when trying to
++port an old driver to the new PCI interface.  They are no longer present
++in the kernel as they aren't compatible with hotplug or PCI domains or
++having sane locking.
++
++pci_find_device()	Superseded by pci_get_device()
++pci_find_subsys()	Superseded by pci_get_subsys()
++pci_find_slot()		Superseded by pci_get_slot()
++
++
++The alternative is the traditional PCI device driver that walks PCI
++device lists. This is still possible but discouraged.
++
++
++
++10. MMIO Space and "Write Posting"
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++Converting a driver from using I/O Port space to using MMIO space
++often requires some additional changes. Specifically, "write posting"
++needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2)
++already do this. I/O Port space guarantees write transactions reach the PCI
++device before the CPU can continue. Writes to MMIO space allow the CPU
++to continue before the transaction reaches the PCI device. HW weenies
++call this "Write Posting" because the write completion is "posted" to
++the CPU before the transaction has reached its destination.
++
++Thus, timing sensitive code should add readl() where the CPU is
++expected to wait before doing other work.  The classic "bit banging"
++sequence works fine for I/O Port space:
++
++       for (i = 8; --i; val >>= 1) {
++               outb(val & 1, ioport_reg);      /* write bit */
++               udelay(10);
++       }
++
++The same sequence for MMIO space should be:
++
++       for (i = 8; --i; val >>= 1) {
++               writeb(val & 1, mmio_reg);      /* write bit */
++               readb(safe_mmio_reg);           /* flush posted write */
++               udelay(10);
++       }
++
++It is important that "safe_mmio_reg" not have any side effects that
++interferes with the correct operation of the device.
++
++Another case to watch out for is when resetting a PCI device. Use PCI
++Configuration space reads to flush the writel(). This will gracefully
++handle the PCI master abort on all platforms if the PCI device is
++expected to not respond to a readl().  Most x86 platforms will allow
++MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage
++(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").
++
+diff --git a/Documentation/PCI/pcieaer-howto.txt b/Documentation/PCI/pcieaer-howto.txt
+new file mode 100644
+index 0000000..16c2512
+--- /dev/null
++++ b/Documentation/PCI/pcieaer-howto.txt
+@@ -0,0 +1,253 @@
++   The PCI Express Advanced Error Reporting Driver Guide HOWTO
++		T. Long Nguyen	<tom.l.nguyen at intel.com>
++		Yanmin Zhang	<yanmin.zhang at intel.com>
++				07/29/2006
++
++
++1. Overview
++
++1.1 About this guide
++
++This guide describes the basics of the PCI Express Advanced Error
++Reporting (AER) driver and provides information on how to use it, as
++well as how to enable the drivers of endpoint devices to conform with
++PCI Express AER driver.
++
++1.2 Copyright © Intel Corporation 2006.
++
++1.3 What is the PCI Express AER Driver?
++
++PCI Express error signaling can occur on the PCI Express link itself
++or on behalf of transactions initiated on the link. PCI Express
++defines two error reporting paradigms: the baseline capability and
++the Advanced Error Reporting capability. The baseline capability is
++required of all PCI Express components providing a minimum defined
++set of error reporting requirements. Advanced Error Reporting
++capability is implemented with a PCI Express advanced error reporting
++extended capability structure providing more robust error reporting.
++
++The PCI Express AER driver provides the infrastructure to support PCI
++Express Advanced Error Reporting capability. The PCI Express AER
++driver provides three basic functions:
++
++-	Gathers the comprehensive error information if errors occurred.
++-	Reports error to the users.
++-	Performs error recovery actions.
++
++AER driver only attaches root ports which support PCI-Express AER
++capability.
++
++
++2. User Guide
++
++2.1 Include the PCI Express AER Root Driver into the Linux Kernel
++
++The PCI Express AER Root driver is a Root Port service driver attached
++to the PCI Express Port Bus driver. If a user wants to use it, the driver
++has to be compiled. Option CONFIG_PCIEAER supports this capability. It
++depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
++CONFIG_PCIEAER = y.
++
++2.2 Load PCI Express AER Root Driver
++There is a case where a system has AER support in BIOS. Enabling the AER
++Root driver and having AER support in BIOS may result unpredictable
++behavior. To avoid this conflict, a successful load of the AER Root driver
++requires ACPI _OSC support in the BIOS to allow the AER Root driver to
++request for native control of AER. See the PCI FW 3.0 Specification for
++details regarding OSC usage. Currently, lots of firmwares don't provide
++_OSC support while they use PCI Express. To support such firmwares,
++forceload, a parameter of type bool, could enable AER to continue to
++be initiated although firmwares have no _OSC support. To enable the
++walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
++when booting kernel. Note that forceload=n by default.
++
++2.3 AER error output
++When a PCI-E AER error is captured, an error message will be outputed to
++console. If it's a correctable error, it is outputed as a warning.
++Otherwise, it is printed as an error. So users could choose different
++log level to filter out correctable error messages.
++
++Below shows an example.
+++------ PCI-Express Device Error -----+
++Error Severity          : Uncorrected (Fatal)
++PCIE Bus Error type     : Transaction Layer
++Unsupported Request     : First
++Requester ID            : 0500
++VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
++TLB Header:
++04000001 00200a03 05010000 00050100
++
++In the example, 'Requester ID' means the ID of the device who sends
++the error message to root port. Pls. refer to pci express specs for
++other fields.
++
++
++3. Developer Guide
++
++To enable AER aware support requires a software driver to configure
++the AER capability structure within its device and to provide callbacks.
++
++To support AER better, developers need understand how AER does work
++firstly.
++
++PCI Express errors are classified into two types: correctable errors
++and uncorrectable errors. This classification is based on the impacts
++of those errors, which may result in degraded performance or function
++failure.
++
++Correctable errors pose no impacts on the functionality of the
++interface. The PCI Express protocol can recover without any software
++intervention or any loss of data. These errors are detected and
++corrected by hardware. Unlike correctable errors, uncorrectable
++errors impact functionality of the interface. Uncorrectable errors
++can cause a particular transaction or a particular PCI Express link
++to be unreliable. Depending on those error conditions, uncorrectable
++errors are further classified into non-fatal errors and fatal errors.
++Non-fatal errors cause the particular transaction to be unreliable,
++but the PCI Express link itself is fully functional. Fatal errors, on
++the other hand, cause the link to be unreliable.
++
++When AER is enabled, a PCI Express device will automatically send an
++error message to the PCIE root port above it when the device captures
++an error. The Root Port, upon receiving an error reporting message,
++internally processes and logs the error message in its PCI Express
++capability structure. Error information being logged includes storing
++the error reporting agent's requestor ID into the Error Source
++Identification Registers and setting the error bits of the Root Error
++Status Register accordingly. If AER error reporting is enabled in Root
++Error Command Register, the Root Port generates an interrupt if an
++error is detected.
++
++Note that the errors as described above are related to the PCI Express
++hierarchy and links. These errors do not include any device specific
++errors because device specific errors will still get sent directly to
++the device driver.
++
++3.1 Configure the AER capability structure
++
++AER aware drivers of PCI Express component need change the device
++control registers to enable AER. They also could change AER registers,
++including mask and severity registers. Helper function
++pci_enable_pcie_error_reporting could be used to enable AER. See
++section 3.3.
++
++3.2. Provide callbacks
++
++3.2.1 callback reset_link to reset pci express link
++
++This callback is used to reset the pci express physical link when a
++fatal error happens. The root port aer service driver provides a
++default reset_link function, but different upstream ports might
++have different specifications to reset pci express link, so all
++upstream ports should provide their own reset_link functions.
++
++In struct pcie_port_service_driver, a new pointer, reset_link, is
++added.
++
++pci_ers_result_t (*reset_link) (struct pci_dev *dev);
++
++Section 3.2.2.2 provides more detailed info on when to call
++reset_link.
++
++3.2.2 PCI error-recovery callbacks
++
++The PCI Express AER Root driver uses error callbacks to coordinate
++with downstream device drivers associated with a hierarchy in question
++when performing error recovery actions.
++
++Data struct pci_driver has a pointer, err_handler, to point to
++pci_error_handlers who consists of a couple of callback function
++pointers. AER driver follows the rules defined in
++pci-error-recovery.txt except pci express specific parts (e.g.
++reset_link). Pls. refer to pci-error-recovery.txt for detailed
++definitions of the callbacks.
++
++Below sections specify when to call the error callback functions.
++
++3.2.2.1 Correctable errors
++
++Correctable errors pose no impacts on the functionality of
++the interface. The PCI Express protocol can recover without any
++software intervention or any loss of data. These errors do not
++require any recovery actions. The AER driver clears the device's
++correctable error status register accordingly and logs these errors.
++
++3.2.2.2 Non-correctable (non-fatal and fatal) errors
++
++If an error message indicates a non-fatal error, performing link reset
++at upstream is not required. The AER driver calls error_detected(dev,
++pci_channel_io_normal) to all drivers associated within a hierarchy in
++question. for example,
++EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort.
++If Upstream port A captures an AER error, the hierarchy consists of
++Downstream port B and EndPoint.
++
++A driver may return PCI_ERS_RESULT_CAN_RECOVER,
++PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
++whether it can recover or the AER driver calls mmio_enabled as next.
++
++If an error message indicates a fatal error, kernel will broadcast
++error_detected(dev, pci_channel_io_frozen) to all drivers within
++a hierarchy in question. Then, performing link reset at upstream is
++necessary. As different kinds of devices might use different approaches
++to reset link, AER port service driver is required to provide the
++function to reset link. Firstly, kernel looks for if the upstream
++component has an aer driver. If it has, kernel uses the reset_link
++callback of the aer driver. If the upstream component has no aer driver
++and the port is downstream port, we will use the aer driver of the
++root port who reports the AER error. As for upstream ports,
++they should provide their own aer service drivers with reset_link
++function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
++reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
++to mmio_enabled.
++
++3.3 helper functions
++
++3.3.1 int pci_find_aer_capability(struct pci_dev *dev);
++pci_find_aer_capability locates the PCI Express AER capability
++in the device configuration space. If the device doesn't support
++PCI-Express AER, the function returns 0.
++
++3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
++pci_enable_pcie_error_reporting enables the device to send error
++messages to root port when an error is detected. Note that devices
++don't enable the error reporting by default, so device drivers need
++call this function to enable it.
++
++3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
++pci_disable_pcie_error_reporting disables the device to send error
++messages to root port when an error is detected.
++
++3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
++pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
++error status register.
++
++3.4 Frequent Asked Questions
++
++Q: What happens if a PCI Express device driver does not provide an
++error recovery handler (pci_driver->err_handler is equal to NULL)?
++
++A: The devices attached with the driver won't be recovered. If the
++error is fatal, kernel will print out warning messages. Please refer
++to section 3 for more information.
++
++Q: What happens if an upstream port service driver does not provide
++callback reset_link?
++
++A: Fatal error recovery will fail if the errors are reported by the
++upstream ports who are attached by the service driver.
++
++Q: How does this infrastructure deal with driver that is not PCI
++Express aware?
++
++A: This infrastructure calls the error callback functions of the
++driver when an error happens. But if the driver is not aware of
++PCI Express, the device might not report its own errors to root
++port.
++
++Q: What modifications will that driver need to make it compatible
++with the PCI Express AER Root driver?
++
++A: It could call the helper functions to enable AER in devices and
++cleanup uncorrectable status register. Pls. refer to section 3.3.
++
+diff --git a/Documentation/PCIEBUS-HOWTO.txt b/Documentation/PCIEBUS-HOWTO.txt
+deleted file mode 100644
+index c93f42a..0000000
+--- a/Documentation/PCIEBUS-HOWTO.txt
++++ /dev/null
+@@ -1,217 +0,0 @@
+-		The PCI Express Port Bus Driver Guide HOWTO
+-	Tom L Nguyen tom.l.nguyen at intel.com
+-			11/03/2004
+-
+-1. About this guide
+-
+-This guide describes the basics of the PCI Express Port Bus driver
+-and provides information on how to enable the service drivers to
+-register/unregister with the PCI Express Port Bus Driver.
+-
+-2. Copyright 2004 Intel Corporation
+-
+-3. What is the PCI Express Port Bus Driver
+-
+-A PCI Express Port is a logical PCI-PCI Bridge structure. There
+-are two types of PCI Express Port: the Root Port and the Switch
+-Port. The Root Port originates a PCI Express link from a PCI Express
+-Root Complex and the Switch Port connects PCI Express links to
+-internal logical PCI buses. The Switch Port, which has its secondary
+-bus representing the switch's internal routing logic, is called the
+-switch's Upstream Port. The switch's Downstream Port is bridging from
+-switch's internal routing bus to a bus representing the downstream
+-PCI Express link from the PCI Express Switch.
+-
+-A PCI Express Port can provide up to four distinct functions,
+-referred to in this document as services, depending on its port type.
+-PCI Express Port's services include native hotplug support (HP),
+-power management event support (PME), advanced error reporting
+-support (AER), and virtual channel support (VC). These services may
+-be handled by a single complex driver or be individually distributed
+-and handled by corresponding service drivers.
+-
+-4. Why use the PCI Express Port Bus Driver?
+-
+-In existing Linux kernels, the Linux Device Driver Model allows a
+-physical device to be handled by only a single driver. The PCI
+-Express Port is a PCI-PCI Bridge device with multiple distinct
+-services. To maintain a clean and simple solution each service
+-may have its own software service driver. In this case several
+-service drivers will compete for a single PCI-PCI Bridge device.
+-For example, if the PCI Express Root Port native hotplug service
+-driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
+-kernel therefore does not load other service drivers for that Root
+-Port. In other words, it is impossible to have multiple service
+-drivers load and run on a PCI-PCI Bridge device simultaneously
+-using the current driver model.
+-
+-To enable multiple service drivers running simultaneously requires
+-having a PCI Express Port Bus driver, which manages all populated
+-PCI Express Ports and distributes all provided service requests
+-to the corresponding service drivers as required. Some key
+-advantages of using the PCI Express Port Bus driver are listed below:
+-
+-	- Allow multiple service drivers to run simultaneously on
+-	  a PCI-PCI Bridge Port device.
+-
+-	- Allow service drivers implemented in an independent
+-	  staged approach.
+-	
+-	- Allow one service driver to run on multiple PCI-PCI Bridge
+-	  Port devices. 
+-
+-	- Manage and distribute resources of a PCI-PCI Bridge Port
+-	  device to requested service drivers.
+-
+-5. Configuring the PCI Express Port Bus Driver vs. Service Drivers
+-
+-5.1 Including the PCI Express Port Bus Driver Support into the Kernel
+-
+-Including the PCI Express Port Bus driver depends on whether the PCI
+-Express support is included in the kernel config. The kernel will
+-automatically include the PCI Express Port Bus driver as a kernel
+-driver when the PCI Express support is enabled in the kernel.
+-
+-5.2 Enabling Service Driver Support
+-
+-PCI device drivers are implemented based on Linux Device Driver Model.
+-All service drivers are PCI device drivers. As discussed above, it is
+-impossible to load any service driver once the kernel has loaded the
+-PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
+-Model requires some minimal changes on existing service drivers that
+-imposes no impact on the functionality of existing service drivers.
+-
+-A service driver is required to use the two APIs shown below to
+-register its service with the PCI Express Port Bus driver (see 
+-section 5.2.1 & 5.2.2). It is important that a service driver
+-initializes the pcie_port_service_driver data structure, included in
+-header file /include/linux/pcieport_if.h, before calling these APIs.
+-Failure to do so will result an identity mismatch, which prevents
+-the PCI Express Port Bus driver from loading a service driver.
+-
+-5.2.1 pcie_port_service_register
+-
+-int pcie_port_service_register(struct pcie_port_service_driver *new)
+-
+-This API replaces the Linux Driver Model's pci_module_init API. A
+-service driver should always calls pcie_port_service_register at
+-module init. Note that after service driver being loaded, calls
+-such as pci_enable_device(dev) and pci_set_master(dev) are no longer
+-necessary since these calls are executed by the PCI Port Bus driver.
+-
+-5.2.2 pcie_port_service_unregister
+-
+-void pcie_port_service_unregister(struct pcie_port_service_driver *new)
+-
+-pcie_port_service_unregister replaces the Linux Driver Model's
+-pci_unregister_driver. It's always called by service driver when a
+-module exits.
+-
+-5.2.3 Sample Code
+-
+-Below is sample service driver code to initialize the port service
+-driver data structure.
+-
+-static struct pcie_port_service_id service_id[] = { {
+-	.vendor = PCI_ANY_ID,
+-	.device = PCI_ANY_ID,
+-	.port_type = PCIE_RC_PORT,
+-	.service_type = PCIE_PORT_SERVICE_AER,
+-	}, { /* end: all zeroes */ }
+-};
+-
+-static struct pcie_port_service_driver root_aerdrv = {
+-	.name		= (char *)device_name,
+-	.id_table	= &service_id[0],
+-
+-	.probe		= aerdrv_load,
+-	.remove		= aerdrv_unload,
+-
+-	.suspend	= aerdrv_suspend,
+-	.resume		= aerdrv_resume,
+-};
+-
+-Below is a sample code for registering/unregistering a service
+-driver.
+-
+-static int __init aerdrv_service_init(void)
+-{
+-	int retval = 0;
+-	
+-	retval = pcie_port_service_register(&root_aerdrv);
+-	if (!retval) {
+-		/*
+-		 * FIX ME
+-		 */
+-	}
+-	return retval;
+-}
+-
+-static void __exit aerdrv_service_exit(void) 
+-{
+-	pcie_port_service_unregister(&root_aerdrv);
+-}
+-
+-module_init(aerdrv_service_init);
+-module_exit(aerdrv_service_exit);
+-
+-6. Possible Resource Conflicts
+-
+-Since all service drivers of a PCI-PCI Bridge Port device are
+-allowed to run simultaneously, below lists a few of possible resource
+-conflicts with proposed solutions.
+-
+-6.1 MSI Vector Resource
+-
+-The MSI capability structure enables a device software driver to call
+-pci_enable_msi to request MSI based interrupts. Once MSI interrupts
+-are enabled on a device, it stays in this mode until a device driver
+-calls pci_disable_msi to disable MSI interrupts and revert back to
+-INTx emulation mode. Since service drivers of the same PCI-PCI Bridge
+-port share the same physical device, if an individual service driver
+-calls pci_enable_msi/pci_disable_msi it may result unpredictable
+-behavior. For example, two service drivers run simultaneously on the
+-same physical Root Port. Both service drivers call pci_enable_msi to
+-request MSI based interrupts. A service driver may not know whether
+-any other service drivers have run on this Root Port. If either one
+-of them calls pci_disable_msi, it puts the other service driver
+-in a wrong interrupt mode. 
+-
+-To avoid this situation all service drivers are not permitted to
+-switch interrupt mode on its device. The PCI Express Port Bus driver
+-is responsible for determining the interrupt mode and this should be
+-transparent to service drivers. Service drivers need to know only
+-the vector IRQ assigned to the field irq of struct pcie_device, which
+-is passed in when the PCI Express Port Bus driver probes each service
+-driver. Service drivers should use (struct pcie_device*)dev->irq to
+-call request_irq/free_irq. In addition, the interrupt mode is stored
+-in the field interrupt_mode of struct pcie_device.
+-
+-6.2 MSI-X Vector Resources
+-
+-Similar to the MSI a device driver for an MSI-X capable device can
+-call pci_enable_msix to request MSI-X interrupts. All service drivers
+-are not permitted to switch interrupt mode on its device. The PCI
+-Express Port Bus driver is responsible for determining the interrupt
+-mode and this should be transparent to service drivers. Any attempt
+-by service driver to call pci_enable_msix/pci_disable_msix may
+-result unpredictable behavior. Service drivers should use
+-(struct pcie_device*)dev->irq and call request_irq/free_irq.
+-
+-6.3 PCI Memory/IO Mapped Regions
+-
+-Service drivers for PCI Express Power Management (PME), Advanced
+-Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
+-PCI configuration space on the PCI Express port. In all cases the
+-registers accessed are independent of each other. This patch assumes
+-that all service drivers will be well behaved and not overwrite
+-other service driver's configuration settings.
+-
+-6.4 PCI Config Registers
+-
+-Each service driver runs its PCI config operations on its own
+-capability structure except the PCI Express capability structure, in
+-which Root Control register and Device Control register are shared
+-between PME and AER. This patch assumes that all service drivers
+-will be well behaved and not overwrite other service driver's
+-configuration settings.
+diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
+index 1fc4e71..9c93a03 100644
+--- a/Documentation/SubmittingPatches
++++ b/Documentation/SubmittingPatches
+@@ -183,7 +183,7 @@ Even if the maintainer did not respond in step #4, make sure to ALWAYS
+ copy the maintainer when you change their code.
+ 
+ For small patches you may want to CC the Trivial Patch Monkey
+-trivial at kernel.org managed by Adrian Bunk; which collects "trivial"
++trivial at kernel.org managed by Jesper Juhl; which collects "trivial"
+ patches. Trivial patches must qualify for one of the following rules:
+  Spelling fixes in documentation
+  Spelling fixes which could break grep(1)
+@@ -196,7 +196,7 @@ patches. Trivial patches must qualify for one of the following rules:
+  since people copy, as long as it's trivial)
+  Any fix by the author/maintainer of the file (ie. patch monkey
+  in re-transmission mode)
+-URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
++URL: <http://www.kernel.org/pub/linux/kernel/people/juhl/trivial/>
+ 
+ 
+ 
+diff --git a/Documentation/arm/Samsung-S3C24XX/NAND.txt b/Documentation/arm/Samsung-S3C24XX/NAND.txt
+new file mode 100644
+index 0000000..bc478a3
+--- /dev/null
++++ b/Documentation/arm/Samsung-S3C24XX/NAND.txt
+@@ -0,0 +1,30 @@
++			S3C24XX NAND Support
++			====================
++
++Introduction
++------------
++
++Small Page NAND
++---------------
++
++The driver uses a 512 byte (1 page) ECC code for this setup. The
++ECC code is not directly compatible with the default kernel ECC
++code, so the driver enforces its own OOB layout and ECC parameters
++
++Large Page NAND
++---------------
++
++The driver is capable of handling NAND flash with a 2KiB page
++size, with support for hardware ECC generation and correction.
++
++Unlike the 512byte page mode, the driver generates ECC data for
++each 256 byte block in an 2KiB page. This means that more than
++one error in a page can be rectified. It also means that the
++OOB layout remains the default kernel layout for these flashes.
++
++
++Document Author
++---------------
++
++Ben Dooks, Copyright 2007 Simtec Electronics
++
+diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
+index c31b76f..d04e1e3 100644
+--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
++++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
+@@ -156,6 +156,8 @@ NAND
+   controller. If there are any problems the latest linux-mtd
+   code can be found from http://www.linux-mtd.infradead.org/
+ 
++  For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt
++
+ 
+ Serial
+ ------
+diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
+index 93f223b..4dbb8be 100644
+--- a/Documentation/block/biodoc.txt
++++ b/Documentation/block/biodoc.txt
+@@ -1097,7 +1097,7 @@ lock themselves, if required. Drivers that explicitly used the
+ io_request_lock for serialization need to be modified accordingly.
+ Usually it's as easy as adding a global lock:
+ 
+-	static spinlock_t my_driver_lock = SPIN_LOCK_UNLOCKED;
++	static DEFINE_SPINLOCK(my_driver_lock);
+ 
+ and passing the address to that lock to blk_init_queue().
+ 
+diff --git a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex
+index c713aeb..c06233f 100644
+--- a/Documentation/cdrom/cdrom-standard.tex
++++ b/Documentation/cdrom/cdrom-standard.tex
+@@ -777,7 +777,7 @@ Note that a driver must have one static structure, $<device>_dops$, while
+ it may have as many structures $<device>_info$ as there are minor devices
+ active. $Register_cdrom()$ builds a linked list from these. 
+ 
+-\subsection{$Int\ unregister_cdrom(struct\ cdrom_device_info * cdi)$}
++\subsection{$Void\ unregister_cdrom(struct\ cdrom_device_info * cdi)$}
+ 
+ Unregistering device $cdi$ with minor number $MINOR(cdi\to dev)$ removes
+ the minor device from the list. If it was the last registered minor for
+diff --git a/Documentation/cli-sti-removal.txt b/Documentation/cli-sti-removal.txt
+index 0223c9d..60932b0 100644
+--- a/Documentation/cli-sti-removal.txt
++++ b/Documentation/cli-sti-removal.txt
+@@ -43,7 +43,7 @@ would execute while the cli()-ed section is executing.
+ 
+ but from now on a more direct method of locking has to be used:
+ 
+-	spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
++	DEFINE_SPINLOCK(driver_lock);
+ 	struct driver_data;
+ 
+ 	irq_handler (...)
+diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
+index ad2bb3b..aa854b9 100644
+--- a/Documentation/cpusets.txt
++++ b/Documentation/cpusets.txt
+@@ -8,6 +8,7 @@ Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
+ Modified by Paul Jackson <pj at sgi.com>
+ Modified by Christoph Lameter <clameter at sgi.com>
+ Modified by Paul Menage <menage at google.com>
++Modified by Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
+ 
+ CONTENTS:
+ =========
+@@ -20,7 +21,8 @@ CONTENTS:
+   1.5 What is memory_pressure ?
+   1.6 What is memory spread ?
+   1.7 What is sched_load_balance ?
+-  1.8 How do I use cpusets ?
++  1.8 What is sched_relax_domain_level ?
++  1.9 How do I use cpusets ?
+ 2. Usage Examples and Syntax
+   2.1 Basic Usage
+   2.2 Adding/removing cpus
+@@ -497,7 +499,73 @@ the cpuset code to update these sched domains, it compares the new
+ partition requested with the current, and updates its sched domains,
+ removing the old and adding the new, for each change.
+ 
+-1.8 How do I use cpusets ?
++
++1.8 What is sched_relax_domain_level ?
++--------------------------------------
++
++In sched domain, the scheduler migrates tasks in 2 ways; periodic load
++balance on tick, and at time of some schedule events.
++
++When a task is woken up, scheduler try to move the task on idle CPU.
++For example, if a task A running on CPU X activates another task B
++on the same CPU X, and if CPU Y is X's sibling and performing idle,
++then scheduler migrate task B to CPU Y so that task B can start on
++CPU Y without waiting task A on CPU X.
++
++And if a CPU run out of tasks in its runqueue, the CPU try to pull
++extra tasks from other busy CPUs to help them before it is going to
++be idle.
++
++Of course it takes some searching cost to find movable tasks and/or
++idle CPUs, the scheduler might not search all CPUs in the domain
++everytime.  In fact, in some architectures, the searching ranges on
++events are limited in the same socket or node where the CPU locates,
++while the load balance on tick searchs all.
++
++For example, assume CPU Z is relatively far from CPU X.  Even if CPU Z
++is idle while CPU X and the siblings are busy, scheduler can't migrate
++woken task B from X to Z since it is out of its searching range.
++As the result, task B on CPU X need to wait task A or wait load balance
++on the next tick.  For some applications in special situation, waiting
++1 tick may be too long.
++
++The 'sched_relax_domain_level' file allows you to request changing
++this searching range as you like.  This file takes int value which
++indicates size of searching range in levels ideally as follows,
++otherwise initial value -1 that indicates the cpuset has no request.
++
++  -1  : no request. use system default or follow request of others.
++   0  : no search.
++   1  : search siblings (hyperthreads in a core).
++   2  : search cores in a package.
++   3  : search cpus in a node [= system wide on non-NUMA system]
++ ( 4  : search nodes in a chunk of node [on NUMA system] )
++ ( 5~ : search system wide [on NUMA system])
++
++This file is per-cpuset and affect the sched domain where the cpuset
++belongs to.  Therefore if the flag 'sched_load_balance' of a cpuset
++is disabled, then 'sched_relax_domain_level' have no effect since
++there is no sched domain belonging the cpuset.
++
++If multiple cpusets are overlapping and hence they form a single sched
++domain, the largest value among those is used.  Be careful, if one
++requests 0 and others are -1 then 0 is used.
++
++Note that modifying this file will have both good and bad effects,
++and whether it is acceptable or not will be depend on your situation.
++Don't modify this file if you are not sure.
++
++If your situation is:
++ - The migration costs between each cpu can be assumed considerably
++   small(for you) due to your special application's behavior or
++   special hardware support for CPU cache etc.
++ - The searching cost doesn't have impact(for you) or you can make
++   the searching cost enough small by managing cpuset to compact etc.
++ - The latency is required even it sacrifices cache hit rate etc.
++then increasing 'sched_relax_domain_level' would benefit you.
++
++
++1.9 How do I use cpusets ?
+ --------------------------
+ 
+ In order to minimize the impact of cpusets on critical kernel
+diff --git a/Documentation/debugging-via-ohci1394.txt b/Documentation/debugging-via-ohci1394.txt
+index c360d4e..59a91e5 100644
+--- a/Documentation/debugging-via-ohci1394.txt
++++ b/Documentation/debugging-via-ohci1394.txt
+@@ -41,15 +41,19 @@ to a working state and enables physical DMA by default for all remote nodes.
+ This can be turned off by ohci1394's module parameter phys_dma=0.
+ 
+ The alternative firewire-ohci driver in drivers/firewire uses filtered physical
+-DMA, hence is not yet suitable for remote debugging.
++DMA by default, which is more secure but not suitable for remote debugging.
++Compile the driver with CONFIG_FIREWIRE_OHCI_REMOTE_DMA (Kernel hacking menu:
++Remote debugging over FireWire with firewire-ohci) to get unfiltered physical
++DMA.
+ 
+-Because ohci1394 depends on the PCI enumeration to be completed, an
+-initialization routine which runs pretty early (long before console_init()
+-which makes the printk buffer appear on the console can be called) was written.
++Because ohci1394 and firewire-ohci depend on the PCI enumeration to be
++completed, an initialization routine which runs pretty early has been
++implemented for x86.  This routine runs long before console_init() can be
++called, i.e. before the printk buffer appears on the console.
+ 
+ To activate it, enable CONFIG_PROVIDE_OHCI1394_DMA_INIT (Kernel hacking menu:
+-Provide code for enabling DMA over FireWire early on boot) and pass the
+-parameter "ohci1394_dma=early" to the recompiled kernel on boot.
++Remote debugging over FireWire early on boot) and pass the parameter
++"ohci1394_dma=early" to the recompiled kernel on boot.
+ 
+ Tools
+ -----
+diff --git a/Documentation/device-mapper/dm-crypt.txt b/Documentation/device-mapper/dm-crypt.txt
+new file mode 100644
+index 0000000..6680cab
+--- /dev/null
++++ b/Documentation/device-mapper/dm-crypt.txt
+@@ -0,0 +1,52 @@
++dm-crypt
++=========
++
++Device-Mapper's "crypt" target provides transparent encryption of block devices
++using the kernel crypto API.
++
++Parameters: <cipher> <key> <iv_offset> <device path> <offset>
++
++<cipher>
++    Encryption cipher and an optional IV generation mode.
++    (In format cipher-chainmode-ivopts:ivmode).
++    Examples:
++       des
++       aes-cbc-essiv:sha256
++       twofish-ecb
++
++    /proc/crypto contains supported crypto modes
++
++<key>
++    Key used for encryption. It is encoded as a hexadecimal number.
++    You can only use key sizes that are valid for the selected cipher.
++
++<iv_offset>
++    The IV offset is a sector count that is added to the sector number
++    before creating the IV.
++
++<device path>
++    This is the device that is going to be used as backend and contains the
++    encrypted data.  You can specify it as a path like /dev/xxx or a device
++    number <major>:<minor>.
++
++<offset>
++    Starting sector within the device where the encrypted data begins.
++
++Example scripts
++===============
++LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
++encryption with dm-crypt using the 'cryptsetup' utility, see
++http://luks.endorphin.org/
++
++[[
++#!/bin/sh
++# Create a crypt device using dmsetup
++dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
++]]
++
++[[
++#!/bin/sh
++# Create a crypt device using cryptsetup and LUKS header with default cipher
++cryptsetup luksFormat $1
++cryptsetup luksOpen $1 crypt1
++]]
+diff --git a/Documentation/dontdiff b/Documentation/dontdiff
+index c09a96b..354aec0 100644
+--- a/Documentation/dontdiff
++++ b/Documentation/dontdiff
+@@ -47,7 +47,6 @@
+ .mm
+ 53c700_d.h
+ 53c8xx_d.h*
+-BitKeeper
+ COPYING
+ CREDITS
+ CVS
+diff --git a/Documentation/early-userspace/README b/Documentation/early-userspace/README
+index 766d320..e35d830 100644
+--- a/Documentation/early-userspace/README
++++ b/Documentation/early-userspace/README
+@@ -89,8 +89,8 @@ the 2.7 era (it missed the boat for 2.5).
+ You can obtain somewhat infrequent snapshots of klibc from
+ ftp://ftp.kernel.org/pub/linux/libs/klibc/
+ 
+-For active users, you are better off using the klibc BitKeeper
+-repositories, at http://klibc.bkbits.net/
++For active users, you are better off using the klibc git
++repository, at http://git.kernel.org/?p=libs/klibc/klibc.git
+ 
+ The standalone klibc distribution currently provides three components,
+ in addition to the klibc library:
+diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
+index bf0e3df..448729f 100644
+--- a/Documentation/feature-removal-schedule.txt
++++ b/Documentation/feature-removal-schedule.txt
+@@ -203,16 +203,8 @@ Who:  linuxppc-dev at ozlabs.org
+ 
+ ---------------------------
+ 
+-What:   sk98lin network driver
+-When:   Feburary 2008
+-Why:    In kernel tree version of driver is unmaintained. Sk98lin driver
+-	replaced by the skge driver. 
+-Who:    Stephen Hemminger <shemminger at linux-foundation.org>
+-
+----------------------------
+-
+ What:	i386/x86_64 bzImage symlinks
+-When:	April 2008
++When:	April 2010
+ 
+ Why:	The i386/x86_64 merge provides a symlink to the old bzImage
+ 	location so not yet updated user space tools, e.g. package
+@@ -221,8 +213,6 @@ Who:	Thomas Gleixner <tglx at linutronix.de>
+ 
+ ---------------------------
+ 
+----------------------------
+-
+ What:	i2c-i810, i2c-prosavage and i2c-savage4
+ When:	May 2008
+ Why:	These drivers are superseded by i810fb, intelfb and savagefb.
+@@ -230,33 +220,6 @@ Who:	Jean Delvare <khali at linux-fr.org>
+ 
+ ---------------------------
+ 
+-What:	bcm43xx wireless network driver
+-When:	2.6.26
+-Files:	drivers/net/wireless/bcm43xx
+-Why:	This driver's functionality has been replaced by the
+-	mac80211-based b43 and b43legacy drivers.
+-Who:	John W. Linville <linville at tuxdriver.com>
+-
+----------------------------
+-
+-What:	ieee80211 softmac wireless networking component
+-When:	2.6.26 (or after removal of bcm43xx and port of zd1211rw to mac80211)
+-Files:	net/ieee80211/softmac
+-Why:	No in-kernel drivers will depend on it any longer.
+-Who:	John W. Linville <linville at tuxdriver.com>
+-
+----------------------------
+-
+-What:	rc80211-simple rate control algorithm for mac80211
+-When:	2.6.26
+-Files:	net/mac80211/rc80211-simple.c
+-Why:	This algorithm was provided for reference but always exhibited bad
+-	responsiveness and performance and has some serious flaws. It has been
+-	replaced by rc80211-pid.
+-Who:	Stefano Brivio <stefano.brivio at polimi.it>
+-
+----------------------------
+-
+ What (Why):
+ 	- include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
+ 	  (superseded by xt_TOS/xt_tos target & match)
+@@ -298,17 +261,6 @@ Who:	Michael Buesch <mb at bu3sch.de>
+ 
+ ---------------------------
+ 
+-What:	Solaris/SunOS syscall and binary support on Sparc
+-When:	2.6.26
+-Why:	Largely unmaintained and almost entirely unused.  File system
+-	layering used to divert library and dynamic linker searches to
+-	/usr/gnemul is extremely buggy and unfixable.  Making it work
+-	is largely pointless as without a lot of work only the most
+-	trivial of Solaris binaries can work with the emulation code.
+-Who:	David S. Miller <davem at davemloft.net>
+-
+----------------------------
+-
+ What:	init_mm export
+ When:	2.6.26
+ Why:	Not used in-tree. The current out-of-tree users used it to
+@@ -318,3 +270,28 @@ Why:	Not used in-tree. The current out-of-tree users used it to
+ 	code / infrastructure should be in the kernel and not in some
+ 	out-of-tree driver.
+ Who:	Thomas Gleixner <tglx at linutronix.de>
++
++----------------------------
++
++What:	usedac i386 kernel parameter
++When:	2.6.27
++Why:	replaced by allowdac and no dac combination
++Who:	Glauber Costa <gcosta at redhat.com>
++
++---------------------------
++
++What:	/sys/o2cb symlink
++When:	January 2010
++Why:	/sys/fs/o2cb is the proper location for this information - /sys/o2cb
++	exists as a symlink for backwards compatibility for old versions of
++	ocfs2-tools. 2 years should be sufficient time to phase in new versions
++	which know to look in /sys/fs/o2cb.
++Who:	ocfs2-devel at oss.oracle.com
++
++---------------------------
++
++What:	asm/semaphore.h
++When:	2.6.26
++Why:	Implementation became generic; users should now include
++	linux/semaphore.h instead.
++Who:	Matthew Wilcox <willy at linux.intel.com>
+diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt
+new file mode 100644
+index 0000000..d0ec45a
+--- /dev/null
++++ b/Documentation/filesystems/nfs-rdma.txt
+@@ -0,0 +1,256 @@
++################################################################################
++#									       #
++#				NFS/RDMA README				       #
++#									       #
++################################################################################
++
++ Author: NetApp and Open Grid Computing
++ Date: April 15, 2008
++
++Table of Contents
++~~~~~~~~~~~~~~~~~
++ - Overview
++ - Getting Help
++ - Installation
++ - Check RDMA and NFS Setup
++ - NFS/RDMA Setup
++
++Overview
++~~~~~~~~
++
++  This document describes how to install and setup the Linux NFS/RDMA client
++  and server software.
++
++  The NFS/RDMA client was first included in Linux 2.6.24. The NFS/RDMA server
++  was first included in the following release, Linux 2.6.25.
++
++  In our testing, we have obtained excellent performance results (full 10Gbit
++  wire bandwidth at minimal client CPU) under many workloads. The code passes
++  the full Connectathon test suite and operates over both Infiniband and iWARP
++  RDMA adapters.
++
++Getting Help
++~~~~~~~~~~~~
++
++  If you get stuck, you can ask questions on the
++
++                nfs-rdma-devel at lists.sourceforge.net
++
++  mailing list.
++
++Installation
++~~~~~~~~~~~~
++
++  These instructions are a step by step guide to building a machine for
++  use with NFS/RDMA.
++
++  - Install an RDMA device
++
++    Any device supported by the drivers in drivers/infiniband/hw is acceptable.
++
++    Testing has been performed using several Mellanox-based IB cards, the
++    Ammasso AMS1100 iWARP adapter, and the Chelsio cxgb3 iWARP adapter.
++
++  - Install a Linux distribution and tools
++
++    The first kernel release to contain both the NFS/RDMA client and server was
++    Linux 2.6.25  Therefore, a distribution compatible with this and subsequent
++    Linux kernel release should be installed.
++
++    The procedures described in this document have been tested with
++    distributions from Red Hat's Fedora Project (http://fedora.redhat.com/).
++
++  - Install nfs-utils-1.1.1 or greater on the client
++
++    An NFS/RDMA mount point can only be obtained by using the mount.nfs
++    command in nfs-utils-1.1.1 or greater. To see which version of mount.nfs
++    you are using, type:
++
++    > /sbin/mount.nfs -V
++
++    If the version is less than 1.1.1 or the command does not exist,
++    then you will need to install the latest version of nfs-utils.
++
++    Download the latest package from:
++
++    http://www.kernel.org/pub/linux/utils/nfs
++
++    Uncompress the package and follow the installation instructions.
++
++    If you will not be using GSS and NFSv4, the installation process
++    can be simplified by disabling these features when running configure:
++
++    > ./configure --disable-gss --disable-nfsv4
++
++    For more information on this see the package's README and INSTALL files.
++
++    After building the nfs-utils package, there will be a mount.nfs binary in
++    the utils/mount directory. This binary can be used to initiate NFS v2, v3,
++    or v4 mounts. To initiate a v4 mount, the binary must be called mount.nfs4.
++    The standard technique is to create a symlink called mount.nfs4 to mount.nfs.
++
++    NOTE: mount.nfs and therefore nfs-utils-1.1.1 or greater is only needed
++    on the NFS client machine. You do not need this specific version of
++    nfs-utils on the server. Furthermore, only the mount.nfs command from
++    nfs-utils-1.1.1 is needed on the client.
++
++  - Install a Linux kernel with NFS/RDMA
++
++    The NFS/RDMA client and server are both included in the mainline Linux
++    kernel version 2.6.25 and later. This and other versions of the 2.6 Linux
++    kernel can be found at:
++
++    ftp://ftp.kernel.org/pub/linux/kernel/v2.6/
++
++    Download the sources and place them in an appropriate location.
++
++  - Configure the RDMA stack
++
++    Make sure your kernel configuration has RDMA support enabled. Under
++    Device Drivers -> InfiniBand support, update the kernel configuration
++    to enable InfiniBand support [NOTE: the option name is misleading. Enabling
++    InfiniBand support is required for all RDMA devices (IB, iWARP, etc.)].
++
++    Enable the appropriate IB HCA support (mlx4, mthca, ehca, ipath, etc.) or
++    iWARP adapter support (amso, cxgb3, etc.).
++
++    If you are using InfiniBand, be sure to enable IP-over-InfiniBand support.
++
++  - Configure the NFS client and server
++
++    Your kernel configuration must also have NFS file system support and/or
++    NFS server support enabled. These and other NFS related configuration
++    options can be found under File Systems -> Network File Systems.
++
++  - Build, install, reboot
++
++    The NFS/RDMA code will be enabled automatically if NFS and RDMA
++    are turned on. The NFS/RDMA client and server are configured via the hidden
++    SUNRPC_XPRT_RDMA config option that depends on SUNRPC and INFINIBAND. The
++    value of SUNRPC_XPRT_RDMA will be:
++
++     - N if either SUNRPC or INFINIBAND are N, in this case the NFS/RDMA client
++       and server will not be built
++     - M if both SUNRPC and INFINIBAND are on (M or Y) and at least one is M,
++       in this case the NFS/RDMA client and server will be built as modules
++     - Y if both SUNRPC and INFINIBAND are Y, in this case the NFS/RDMA client
++       and server will be built into the kernel
++
++    Therefore, if you have followed the steps above and turned no NFS and RDMA,
++    the NFS/RDMA client and server will be built.
++
++    Build a new kernel, install it, boot it.
++
++Check RDMA and NFS Setup
++~~~~~~~~~~~~~~~~~~~~~~~~
++
++    Before configuring the NFS/RDMA software, it is a good idea to test
++    your new kernel to ensure that the kernel is working correctly.
++    In particular, it is a good idea to verify that the RDMA stack
++    is functioning as expected and standard NFS over TCP/IP and/or UDP/IP
++    is working properly.
++
++  - Check RDMA Setup
++
++    If you built the RDMA components as modules, load them at
++    this time. For example, if you are using a Mellanox Tavor/Sinai/Arbel
++    card:
++
++    > modprobe ib_mthca
++    > modprobe ib_ipoib
++
++    If you are using InfiniBand, make sure there is a Subnet Manager (SM)
++    running on the network. If your IB switch has an embedded SM, you can
++    use it. Otherwise, you will need to run an SM, such as OpenSM, on one
++    of your end nodes.
++
++    If an SM is running on your network, you should see the following:
++
++    > cat /sys/class/infiniband/driverX/ports/1/state
++    4: ACTIVE
++
++    where driverX is mthca0, ipath5, ehca3, etc.
++
++    To further test the InfiniBand software stack, use IPoIB (this
++    assumes you have two IB hosts named host1 and host2):
++
++    host1> ifconfig ib0 a.b.c.x
++    host2> ifconfig ib0 a.b.c.y
++    host1> ping a.b.c.y
++    host2> ping a.b.c.x
++
++    For other device types, follow the appropriate procedures.
++
++  - Check NFS Setup
++
++    For the NFS components enabled above (client and/or server),
++    test their functionality over standard Ethernet using TCP/IP or UDP/IP.
++
++NFS/RDMA Setup
++~~~~~~~~~~~~~~
++
++  We recommend that you use two machines, one to act as the client and
++  one to act as the server.
++
++  One time configuration:
++
++  - On the server system, configure the /etc/exports file and
++    start the NFS/RDMA server.
++
++    Exports entries with the following formats have been tested:
++
++    /vol0   192.168.0.47(fsid=0,rw,async,insecure,no_root_squash)
++    /vol0   192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash)
++
++    The IP address(es) is(are) the client's IPoIB address for an InfiniBand HCA or the
++    cleint's iWARP address(es) for an RNIC.
++
++    NOTE: The "insecure" option must be used because the NFS/RDMA client does not
++    use a reserved port.
++
++ Each time a machine boots:
++
++  - Load and configure the RDMA drivers
++
++    For InfiniBand using a Mellanox adapter:
++
++    > modprobe ib_mthca
++    > modprobe ib_ipoib
++    > ifconfig ib0 a.b.c.d
++
++    NOTE: use unique addresses for the client and server
++
++  - Start the NFS server
++
++    If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config),
++    load the RDMA transport module:
++
++    > modprobe svcrdma
++
++    Regardless of how the server was built (module or built-in), start the server:
++
++    > /etc/init.d/nfs start
++
++    or
++
++    > service nfs start
++
++    Instruct the server to listen on the RDMA transport:
++
++    > echo rdma 2050 > /proc/fs/nfsd/portlist
++
++  - On the client system
++
++    If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config),
++    load the RDMA client module:
++
++    > modprobe xprtrdma.ko
++
++    Regardless of how the client was built (module or built-in), issue the mount.nfs command:
++
++    > /path/to/your/mount.nfs <IPoIB-server-name-or-address>:/<export> /mnt -i -o rdma,port=2050
++
++    To verify that the mount is using RDMA, run "cat /proc/mounts" and check the
++    "proto" field for the given mount.
++
++  Congratulations! You're using NFS/RDMA!
+diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
+index 518ebe6..2a99116 100644
+--- a/Documentation/filesystems/proc.txt
++++ b/Documentation/filesystems/proc.txt
+@@ -43,6 +43,7 @@ Table of Contents
+   2.13	/proc/<pid>/oom_score - Display current oom-killer score
+   2.14	/proc/<pid>/io - Display the IO accounting fields
+   2.15	/proc/<pid>/coredump_filter - Core dump filtering settings
++  2.16	/proc/<pid>/mountinfo - Information about mounts
+ 
+ ------------------------------------------------------------------------------
+ Preface
+@@ -2348,4 +2349,41 @@ For example:
+   $ echo 0x7 > /proc/self/coredump_filter
+   $ ./some_program
+ 
++2.16	/proc/<pid>/mountinfo - Information about mounts
++--------------------------------------------------------
++
++This file contains lines of the form:
++
++36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
++(1)(2)(3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)
++
++(1) mount ID:  unique identifier of the mount (may be reused after umount)
++(2) parent ID:  ID of parent (or of self for the top of the mount tree)
++(3) major:minor:  value of st_dev for files on filesystem
++(4) root:  root of the mount within the filesystem
++(5) mount point:  mount point relative to the process's root
++(6) mount options:  per mount options
++(7) optional fields:  zero or more fields of the form "tag[:value]"
++(8) separator:  marks the end of the optional fields
++(9) filesystem type:  name of filesystem of the form "type[.subtype]"
++(10) mount source:  filesystem specific information or "none"
++(11) super options:  per super block options
++
++Parsers should ignore all unrecognised optional fields.  Currently the
++possible optional fields are:
++
++shared:X  mount is shared in peer group X
++master:X  mount is slave to peer group X
++propagate_from:X  mount is slave and receives propagation from peer group X (*)
++unbindable  mount is unbindable
++
++(*) X is the closest dominant peer group under the process's root.  If
++X is the immediate master of the mount, or if there's no dominant peer
++group under the same root, then only the "master:X" field is present
++and not the "propagate_from:X" field.
++
++For more information on mount propagation see:
++
++  Documentation/filesystems/sharedsubtree.txt
++
+ ------------------------------------------------------------------------------
+diff --git a/Documentation/filesystems/seq_file.txt b/Documentation/filesystems/seq_file.txt
+index 7fb8e6d..b843743 100644
+--- a/Documentation/filesystems/seq_file.txt
++++ b/Documentation/filesystems/seq_file.txt
+@@ -122,8 +122,7 @@ stop() is the place to free it.
+ 	}
+ 
+ Finally, the show() function should format the object currently pointed to
+-by the iterator for output. It should return zero, or an error code if
+-something goes wrong. The example module's show() function is:
++by the iterator for output.  The example module's show() function is:
+ 
+ 	static int ct_seq_show(struct seq_file *s, void *v)
+ 	{
+@@ -132,6 +131,12 @@ something goes wrong. The example module's show() function is:
+ 	        return 0;
+ 	}
+ 
++If all is well, the show() function should return zero.  A negative error
++code in the usual manner indicates that something went wrong; it will be
++passed back to user space.  This function can also return SEQ_SKIP, which
++causes the current item to be skipped; if the show() function has already
++generated output before returning SEQ_SKIP, that output will be dropped.
++
+ We will look at seq_printf() in a moment. But first, the definition of the
+ seq_file iterator is finished by creating a seq_operations structure with
+ the four functions we have just defined:
+@@ -182,12 +187,18 @@ The first two output a single character and a string, just like one would
+ expect. seq_escape() is like seq_puts(), except that any character in s
+ which is in the string esc will be represented in octal form in the output.
+ 
+-There is also a function for printing filenames:
++There is also a pair of functions for printing filenames:
+ 
+ 	int seq_path(struct seq_file *m, struct path *path, char *esc);
++	int seq_path_root(struct seq_file *m, struct path *path,
++			  struct path *root, char *esc)
+ 
+ Here, path indicates the file of interest, and esc is a set of characters
+-which should be escaped in the output.
++which should be escaped in the output.  A call to seq_path() will output
++the path relative to the current process's filesystem root.  If a different
++root is desired, it can be used with seq_path_root().  Note that, if it
++turns out that path cannot be reached from root, the value of root will be
++changed in seq_file_root() to a root which *does* work.
+ 
+ 
+ Making it all work
+diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
+index 4598ef7..7f27b8f 100644
+--- a/Documentation/filesystems/sysfs.txt
++++ b/Documentation/filesystems/sysfs.txt
+@@ -176,8 +176,10 @@ implementations:
+   Recall that an attribute should only be exporting one value, or an
+   array of similar values, so this shouldn't be that expensive. 
+ 
+-  This allows userspace to do partial reads and seeks arbitrarily over
+-  the entire file at will. 
++  This allows userspace to do partial reads and forward seeks
++  arbitrarily over the entire file at will. If userspace seeks back to
++  zero or does a pread(2) with an offset of '0' the show() method will
++  be called again, rearmed, to fill the buffer.
+ 
+ - On write(2), sysfs expects the entire buffer to be passed during the
+   first write. Sysfs then passes the entire buffer to the store()
+@@ -192,6 +194,9 @@ implementations:
+ 
+ Other notes:
+ 
++- Writing causes the show() method to be rearmed regardless of current
++  file position.
++
+ - The buffer will always be PAGE_SIZE bytes in length. On i386, this
+   is 4096. 
+ 
+diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt
+index 74aeb14..0a1668b 100644
+--- a/Documentation/filesystems/xfs.txt
++++ b/Documentation/filesystems/xfs.txt
+@@ -52,16 +52,15 @@ When mounting an XFS filesystem, the following options are accepted.
+ 	and also gets the setgid bit set if it is a directory itself.
+ 
+   ihashsize=value
+-	Sets the number of hash buckets available for hashing the
+-	in-memory inodes of the specified mount point.  If a value
+-	of zero is used, the value selected by the default algorithm
+-	will be displayed in /proc/mounts.
++	In memory inode hashes have been removed, so this option has
++	no function as of August 2007. Option is deprecated.
+ 
+   ikeep/noikeep
+-	When inode clusters are emptied of inodes, keep them around
+-	on the disk (ikeep) - this is the traditional XFS behaviour
+-	and is still the default for now.  Using the noikeep option,
+-	inode clusters are returned to the free space pool.
++	When ikeep is specified, XFS does not delete empty inode clusters
++	and keeps them around on disk. ikeep is the traditional XFS
++	behaviour. When noikeep is specified, empty inode clusters
++	are returned to the free space pool. The default is noikeep for
++	non-DMAPI mounts, while ikeep is the default when DMAPI is in use.
+ 
+   inode64
+ 	Indicates that XFS is allowed to create inodes at any location
+diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
+deleted file mode 100644
+index 6865cbe..0000000
+--- a/Documentation/firmware_class/firmware_sample_driver.c
++++ /dev/null
+@@ -1,115 +0,0 @@
+-/*
+- * firmware_sample_driver.c -
+- *
+- * Copyright (c) 2003 Manuel Estrada Sainz
+- *
+- * Sample code on how to use request_firmware() from drivers.
+- *
+- */
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/device.h>
+-#include <linux/string.h>
+-
+-#include "linux/firmware.h"
+-
+-static struct device ghost_device = {
+-	.bus_id    = "ghost0",
+-};
+-
+-
+-static void sample_firmware_load(char *firmware, int size)
+-{
+-	u8 buf[size+1];
+-	memcpy(buf, firmware, size);
+-	buf[size] = '\0';
+-	printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf);
+-}
+-
+-static void sample_probe_default(void)
+-{
+-	/* uses the default method to get the firmware */
+-        const struct firmware *fw_entry;
+-	printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
+-
+-        if(request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0)
+-	{
+-		printk(KERN_ERR
+-		       "firmware_sample_driver: Firmware not available\n");
+-		return;
+-	}
+-	
+-	sample_firmware_load(fw_entry->data, fw_entry->size);
+-
+-	release_firmware(fw_entry);
+-
+-	/* finish setting up the device */
+-}
+-static void sample_probe_specific(void)
+-{
+-	/* Uses some specific hotplug support to get the firmware from
+-	 * userspace  directly into the hardware, or via some sysfs file */
+-
+-	/* NOTE: This currently doesn't work */
+-
+-	printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
+-
+-        if(request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0)
+-	{
+-		printk(KERN_ERR
+-		       "firmware_sample_driver: Firmware load failed\n");
+-		return;
+-	}
+-	
+-	/* request_firmware blocks until userspace finished, so at
+-	 * this point the firmware should be already in the device */
+-
+-	/* finish setting up the device */
+-}
+-static void sample_probe_async_cont(const struct firmware *fw, void *context)
+-{
+-	if(!fw){
+-		printk(KERN_ERR
+-		       "firmware_sample_driver: firmware load failed\n");
+-		return;
+-	}
+-
+-	printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n",
+-	       (char *)context);
+-	sample_firmware_load(fw->data, fw->size);
+-}
+-static void sample_probe_async(void)
+-{
+-	/* Let's say that I can't sleep */
+-	int error;
+-	error = request_firmware_nowait (THIS_MODULE, FW_ACTION_NOHOTPLUG,
+-					 "sample_driver_fw", &ghost_device,
+-					 "my device pointer",
+-					 sample_probe_async_cont);
+-	if(error){
+-		printk(KERN_ERR 
+-		       "firmware_sample_driver:"
+-		       " request_firmware_nowait failed\n");
+-	}
+-}
+-
+-static int sample_init(void)
+-{
+-	device_initialize(&ghost_device);
+-	/* since there is no real hardware insertion I just call the
+-	 * sample probe functions here */
+-	sample_probe_specific();
+-	sample_probe_default();
+-	sample_probe_async();
+-	return 0;
+-}
+-static void __exit sample_exit(void)
+-{
+-}
+-
+-module_init (sample_init);
+-module_exit (sample_exit);
+-
+-MODULE_LICENSE("GPL");
+diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
+deleted file mode 100644
+index 2de6285..0000000
+--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
++++ /dev/null
+@@ -1,207 +0,0 @@
+-/*
+- * firmware_sample_firmware_class.c -
+- *
+- * Copyright (c) 2003 Manuel Estrada Sainz
+- *
+- * NOTE: This is just a probe of concept, if you think that your driver would
+- * be well served by this mechanism please contact me first.
+- *
+- * DON'T USE THIS CODE AS IS
+- *
+- */
+-
+-#include <linux/device.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/timer.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/firmware.h>
+-
+-
+-MODULE_AUTHOR("Manuel Estrada Sainz");
+-MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
+-MODULE_LICENSE("GPL");
+-
+-static inline struct class_device *to_class_dev(struct kobject *obj)
+-{
+-	return container_of(obj,struct class_device,kobj);
+-}
+-static inline
+-struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
+-{
+-	return container_of(_attr,struct class_device_attribute,attr);
+-}
+-
+-int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
+-int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
+-
+-struct firmware_priv {
+-	char fw_id[FIRMWARE_NAME_MAX];
+-	s32 loading:2;
+-	u32 abort:1;
+-};
+-
+-extern struct class firmware_class;
+-
+-static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf)
+-{
+-	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+-	return sprintf(buf, "%d\n", fw_priv->loading);
+-}
+-static ssize_t firmware_loading_store(struct class_device *class_dev,
+-				      const char *buf, size_t count)
+-{
+-	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+-	int prev_loading = fw_priv->loading;
+-
+-	fw_priv->loading = simple_strtol(buf, NULL, 10);
+-	
+-	switch(fw_priv->loading){
+-	case -1:
+-		/* abort load an panic */
+-		break;
+-	case 1:
+-		/* setup load */
+-		break;
+-	case 0:
+-		if(prev_loading==1){
+-			/* finish load and get the device back to working
+-			 * state */
+-		}
+-		break;
+-	}
+-
+-	return count;
+-}
+-static CLASS_DEVICE_ATTR(loading, 0644,
+-			 firmware_loading_show, firmware_loading_store);
+-
+-static ssize_t firmware_data_read(struct kobject *kobj,
+-				  struct bin_attribute *bin_attr,
+-				  char *buffer, loff_t offset, size_t count)
+-{
+-	struct class_device *class_dev = to_class_dev(kobj);
+-	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+-
+-	/* read from the devices firmware memory */
+-
+-	return count;
+-}
+-static ssize_t firmware_data_write(struct kobject *kobj,
+-				   struct bin_attribute *bin_attr,
+-				   char *buffer, loff_t offset, size_t count)
+-{
+-	struct class_device *class_dev = to_class_dev(kobj);
+-	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+-
+-	/* write to the devices firmware memory */
+-
+-	return count;
+-}
+-static struct bin_attribute firmware_attr_data = {
+-	.attr = {.name = "data", .mode = 0644},
+-	.size = 0,
+-	.read = firmware_data_read,
+-	.write = firmware_data_write,
+-};
+-static int fw_setup_class_device(struct class_device *class_dev,
+-				 const char *fw_name,
+-				 struct device *device)
+-{
+-	int retval;
+-	struct firmware_priv *fw_priv;
+-
+-	fw_priv = kzalloc(sizeof(struct firmware_priv),	GFP_KERNEL);
+-	if (!fw_priv) {
+-		retval = -ENOMEM;
+-		goto out;
+-	}
+-
+-	memset(class_dev, 0, sizeof(*class_dev));
+-
+-	strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
+-	fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0';
+-
+-	strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE);
+-	class_dev->class_id[BUS_ID_SIZE-1] = '\0';
+-	class_dev->dev = device;
+-
+-	class_dev->class = &firmware_class,
+-	class_set_devdata(class_dev, fw_priv);
+-	retval = class_device_register(class_dev);
+-	if (retval){
+-		printk(KERN_ERR "%s: class_device_register failed\n",
+-		       __FUNCTION__);
+-		goto error_free_fw_priv;
+-	}
+-
+-	retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data);
+-	if (retval){
+-		printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
+-		       __FUNCTION__);
+-		goto error_unreg_class_dev;
+-	}
+-
+-	retval = class_device_create_file(class_dev,
+-					  &class_device_attr_loading);
+-	if (retval){
+-		printk(KERN_ERR "%s: class_device_create_file failed\n",
+-		       __FUNCTION__);
+-		goto error_remove_data;
+-	}
+-
+-	goto out;
+-	
+-error_remove_data:
+-	sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
+-error_unreg_class_dev:
+-	class_device_unregister(class_dev);
+-error_free_fw_priv:
+-	kfree(fw_priv);
+-out:
+-	return retval;
+-}
+-static void fw_remove_class_device(struct class_device *class_dev)
+-{
+-	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+-
+-	class_device_remove_file(class_dev, &class_device_attr_loading);
+-	sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
+-	class_device_unregister(class_dev);
+-}
+-
+-static struct class_device *class_dev;
+-
+-static struct device my_device = {
+-	.bus_id    = "my_dev0",
+-};
+-
+-static int __init firmware_sample_init(void)
+-{
+-	int error;
+-
+-	device_initialize(&my_device);
+-	class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+-	if(!class_dev)
+-		return -ENOMEM;
+-
+-	error = fw_setup_class_device(class_dev, "my_firmware_image",
+-				      &my_device);
+-	if(error){
+-		kfree(class_dev);
+-		return error;
+-	}
+-        return 0;
+-
+-}
+-static void __exit firmware_sample_exit(void)
+-{
+-	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+-	fw_remove_class_device(class_dev);
+-	kfree(fw_priv);
+-	kfree(class_dev);
+-}
+-module_init(firmware_sample_init);
+-module_exit(firmware_sample_exit);
+-
+diff --git a/Documentation/highuid.txt b/Documentation/highuid.txt
+index 76034d9..6bad6f1 100644
+--- a/Documentation/highuid.txt
++++ b/Documentation/highuid.txt
+@@ -28,8 +28,6 @@ What's left to be done for 32-bit UIDs on all Linux architectures:
+   uses the 32-bit UID system calls properly otherwise.
+ 
+   This affects at least:
+-	SunOS emulation
+-	Solaris emulation
+ 	iBCS on Intel
+ 
+ 	sparc32 emulation on sparc64
+diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
+deleted file mode 100644
+index 20d368c..0000000
+--- a/Documentation/hrtimer/timer_stats.txt
++++ /dev/null
+@@ -1,73 +0,0 @@
+-timer_stats - timer usage statistics
+-------------------------------------
+-
+-timer_stats is a debugging facility to make the timer (ab)usage in a Linux
+-system visible to kernel and userspace developers. If enabled in the config
+-but not used it has almost zero runtime overhead, and a relatively small
+-data structure overhead. Even if collection is enabled runtime all the
+-locking is per-CPU and lookup is hashed.
+-
+-timer_stats should be used by kernel and userspace developers to verify that
+-their code does not make unduly use of timers. This helps to avoid unnecessary
+-wakeups, which should be avoided to optimize power consumption.
+-
+-It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration
+-section.
+-
+-timer_stats collects information about the timer events which are fired in a
+-Linux system over a sample period:
+-
+-- the pid of the task(process) which initialized the timer
+-- the name of the process which initialized the timer
+-- the function where the timer was intialized
+-- the callback function which is associated to the timer
+-- the number of events (callbacks)
+-
+-timer_stats adds an entry to /proc: /proc/timer_stats
+-
+-This entry is used to control the statistics functionality and to read out the
+-sampled information.
+-
+-The timer_stats functionality is inactive on bootup.
+-
+-To activate a sample period issue:
+-# echo 1 >/proc/timer_stats
+-
+-To stop a sample period issue:
+-# echo 0 >/proc/timer_stats
+-
+-The statistics can be retrieved by:
+-# cat /proc/timer_stats
+-
+-The readout of /proc/timer_stats automatically disables sampling. The sampled
+-information is kept until a new sample period is started. This allows multiple
+-readouts.
+-
+-Sample output of /proc/timer_stats:
+-
+-Timerstats sample period: 3.888770 s
+-  12,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
+-  15,     1 swapper          hcd_submit_urb (rh_timer_func)
+-   4,   959 kedac            schedule_timeout (process_timeout)
+-   1,     0 swapper          page_writeback_init (wb_timer_fn)
+-  28,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
+-  22,  2948 IRQ 4            tty_flip_buffer_push (delayed_work_timer_fn)
+-   3,  3100 bash             schedule_timeout (process_timeout)
+-   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
+-   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
+-   1,     1 swapper          neigh_table_init_no_netlink (neigh_periodic_timer)
+-   1,  2292 ip               __netdev_watchdog_up (dev_watchdog)
+-   1,    23 events/1         do_cache_clean (delayed_work_timer_fn)
+-90 total events, 30.0 events/sec
+-
+-The first column is the number of events, the second column the pid, the third
+-column is the name of the process. The forth column shows the function which
+-initialized the timer and in parantheses the callback function which was
+-executed on expiry.
+-
+-    Thomas, Ingo
+-
+-Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
+-timer will appear as follows
+-  10D,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
+-
+diff --git a/Documentation/hrtimers/highres.txt b/Documentation/hrtimers/highres.txt
+deleted file mode 100644
+index a73ecf5..0000000
+--- a/Documentation/hrtimers/highres.txt
++++ /dev/null
+@@ -1,249 +0,0 @@
+-High resolution timers and dynamic ticks design notes
+------------------------------------------------------
+-
+-Further information can be found in the paper of the OLS 2006 talk "hrtimers
+-and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can
+-be found on the OLS website:
+-http://www.linuxsymposium.org/2006/linuxsymposium_procv1.pdf
+-
+-The slides to this talk are available from:
+-http://tglx.de/projects/hrtimers/ols2006-hrtimers.pdf
+-
+-The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the
+-changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the
+-design of the Linux time(r) system before hrtimers and other building blocks
+-got merged into mainline.
+-
+-Note: the paper and the slides are talking about "clock event source", while we
+-switched to the name "clock event devices" in meantime.
+-
+-The design contains the following basic building blocks:
+-
+-- hrtimer base infrastructure
+-- timeofday and clock source management
+-- clock event management
+-- high resolution timer functionality
+-- dynamic ticks
+-
+-
+-hrtimer base infrastructure
+----------------------------
+-
+-The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
+-the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See
+-also figure #2 (OLS slides p. 15)
+-
+-The main differences to the timer wheel, which holds the armed timer_list type
+-timers are:
+-       - time ordered enqueueing into a rb-tree
+-       - independent of ticks (the processing is based on nanoseconds)
+-
+-
+-timeofday and clock source management
+--------------------------------------
+-
+-John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of
+-code out of the architecture-specific areas into a generic management
+-framework, as illustrated in figure #3 (OLS slides p. 18). The architecture
+-specific portion is reduced to the low level hardware details of the clock
+-sources, which are registered in the framework and selected on a quality based
+-decision. The low level code provides hardware setup and readout routines and
+-initializes data structures, which are used by the generic time keeping code to
+-convert the clock ticks to nanosecond based time values. All other time keeping
+-related functionality is moved into the generic code. The GTOD base patch got
+-merged into the 2.6.18 kernel.
+-
+-Further information about the Generic Time Of Day framework is available in the
+-OLS 2005 Proceedings Volume 1:
+-http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf
+-
+-The paper "We Are Not Getting Any Younger: A New Approach to Time and
+-Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan.
+-
+-Figure #3 (OLS slides p.18) illustrates the transformation.
+-
+-
+-clock event management
+-----------------------
+-
+-While clock sources provide read access to the monotonically increasing time
+-value, clock event devices are used to schedule the next event
+-interrupt(s). The next event is currently defined to be periodic, with its
+-period defined at compile time. The setup and selection of the event device
+-for various event driven functionalities is hardwired into the architecture
+-dependent code. This results in duplicated code across all architectures and
+-makes it extremely difficult to change the configuration of the system to use
+-event interrupt devices other than those already built into the
+-architecture. Another implication of the current design is that it is necessary
+-to touch all the architecture-specific implementations in order to provide new
+-functionality like high resolution timers or dynamic ticks.
+-
+-The clock events subsystem tries to address this problem by providing a generic
+-solution to manage clock event devices and their usage for the various clock
+-event driven kernel functionalities. The goal of the clock event subsystem is
+-to minimize the clock event related architecture dependent code to the pure
+-hardware related handling and to allow easy addition and utilization of new
+-clock event devices. It also minimizes the duplicated code across the
+-architectures as it provides generic functionality down to the interrupt
+-service handler, which is almost inherently hardware dependent.
+-
+-Clock event devices are registered either by the architecture dependent boot
+-code or at module insertion time. Each clock event device fills a data
+-structure with clock-specific property parameters and callback functions. The
+-clock event management decides, by using the specified property parameters, the
+-set of system functions a clock event device will be used to support. This
+-includes the distinction of per-CPU and per-system global event devices.
+-
+-System-level global event devices are used for the Linux periodic tick. Per-CPU
+-event devices are used to provide local CPU functionality such as process
+-accounting, profiling, and high resolution timers.
+-
+-The management layer assigns one or more of the following functions to a clock
+-event device:
+-      - system global periodic tick (jiffies update)
+-      - cpu local update_process_times
+-      - cpu local profiling
+-      - cpu local next event interrupt (non periodic mode)
+-
+-The clock event device delegates the selection of those timer interrupt related
+-functions completely to the management layer. The clock management layer stores
+-a function pointer in the device description structure, which has to be called
+-from the hardware level handler. This removes a lot of duplicated code from the
+-architecture specific timer interrupt handlers and hands the control over the
+-clock event devices and the assignment of timer interrupt related functionality
+-to the core code.
+-
+-The clock event layer API is rather small. Aside from the clock event device
+-registration interface it provides functions to schedule the next event
+-interrupt, clock event device notification service and support for suspend and
+-resume.
+-
+-The framework adds about 700 lines of code which results in a 2KB increase of
+-the kernel binary size. The conversion of i386 removes about 100 lines of
+-code. The binary size decrease is in the range of 400 byte. We believe that the
+-increase of flexibility and the avoidance of duplicated code across
+-architectures justifies the slight increase of the binary size.
+-
+-The conversion of an architecture has no functional impact, but allows to
+-utilize the high resolution and dynamic tick functionalites without any change
+-to the clock event device and timer interrupt code. After the conversion the
+-enabling of high resolution timers and dynamic ticks is simply provided by
+-adding the kernel/time/Kconfig file to the architecture specific Kconfig and
+-adding the dynamic tick specific calls to the idle routine (a total of 3 lines
+-added to the idle function and the Kconfig file)
+-
+-Figure #4 (OLS slides p.20) illustrates the transformation.
+-
+-
+-high resolution timer functionality
+------------------------------------
+-
+-During system boot it is not possible to use the high resolution timer
+-functionality, while making it possible would be difficult and would serve no
+-useful function. The initialization of the clock event device framework, the
+-clock source framework (GTOD) and hrtimers itself has to be done and
+-appropriate clock sources and clock event devices have to be registered before
+-the high resolution functionality can work. Up to the point where hrtimers are
+-initialized, the system works in the usual low resolution periodic mode. The
+-clock source and the clock event device layers provide notification functions
+-which inform hrtimers about availability of new hardware. hrtimers validates
+-the usability of the registered clock sources and clock event devices before
+-switching to high resolution mode. This ensures also that a kernel which is
+-configured for high resolution timers can run on a system which lacks the
+-necessary hardware support.
+-
+-The high resolution timer code does not support SMP machines which have only
+-global clock event devices. The support of such hardware would involve IPI
+-calls when an interrupt happens. The overhead would be much larger than the
+-benefit. This is the reason why we currently disable high resolution and
+-dynamic ticks on i386 SMP systems which stop the local APIC in C3 power
+-state. A workaround is available as an idea, but the problem has not been
+-tackled yet.
+-
+-The time ordered insertion of timers provides all the infrastructure to decide
+-whether the event device has to be reprogrammed when a timer is added. The
+-decision is made per timer base and synchronized across per-cpu timer bases in
+-a support function. The design allows the system to utilize separate per-CPU
+-clock event devices for the per-CPU timer bases, but currently only one
+-reprogrammable clock event device per-CPU is utilized.
+-
+-When the timer interrupt happens, the next event interrupt handler is called
+-from the clock event distribution code and moves expired timers from the
+-red-black tree to a separate double linked list and invokes the softirq
+-handler. An additional mode field in the hrtimer structure allows the system to
+-execute callback functions directly from the next event interrupt handler. This
+-is restricted to code which can safely be executed in the hard interrupt
+-context. This applies, for example, to the common case of a wakeup function as
+-used by nanosleep. The advantage of executing the handler in the interrupt
+-context is the avoidance of up to two context switches - from the interrupted
+-context to the softirq and to the task which is woken up by the expired
+-timer.
+-
+-Once a system has switched to high resolution mode, the periodic tick is
+-switched off. This disables the per system global periodic clock event device -
+-e.g. the PIT on i386 SMP systems.
+-
+-The periodic tick functionality is provided by an per-cpu hrtimer. The callback
+-function is executed in the next event interrupt context and updates jiffies
+-and calls update_process_times and profiling. The implementation of the hrtimer
+-based periodic tick is designed to be extended with dynamic tick functionality.
+-This allows to use a single clock event device to schedule high resolution
+-timer and periodic events (jiffies tick, profiling, process accounting) on UP
+-systems. This has been proved to work with the PIT on i386 and the Incrementer
+-on PPC.
+-
+-The softirq for running the hrtimer queues and executing the callbacks has been
+-separated from the tick bound timer softirq to allow accurate delivery of high
+-resolution timer signals which are used by itimer and POSIX interval
+-timers. The execution of this softirq can still be delayed by other softirqs,
+-but the overall latencies have been significantly improved by this separation.
+-
+-Figure #5 (OLS slides p.22) illustrates the transformation.
+-
+-
+-dynamic ticks
+--------------
+-
+-Dynamic ticks are the logical consequence of the hrtimer based periodic tick
+-replacement (sched_tick). The functionality of the sched_tick hrtimer is
+-extended by three functions:
+-
+-- hrtimer_stop_sched_tick
+-- hrtimer_restart_sched_tick
+-- hrtimer_update_jiffies
+-
+-hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code
+-evaluates the next scheduled timer event (from both hrtimers and the timer
+-wheel) and in case that the next event is further away than the next tick it
+-reprograms the sched_tick to this future event, to allow longer idle sleeps
+-without worthless interruption by the periodic tick. The function is also
+-called when an interrupt happens during the idle period, which does not cause a
+-reschedule. The call is necessary as the interrupt handler might have armed a
+-new timer whose expiry time is before the time which was identified as the
+-nearest event in the previous call to hrtimer_stop_sched_tick.
+-
+-hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before
+-it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick,
+-which is kept active until the next call to hrtimer_stop_sched_tick().
+-
+-hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens
+-in the idle period to make sure that jiffies are up to date and the interrupt
+-handler has not to deal with an eventually stale jiffy value.
+-
+-The dynamic tick feature provides statistical values which are exported to
+-userspace via /proc/stats and can be made available for enhanced power
+-management control.
+-
+-The implementation leaves room for further development like full tickless
+-systems, where the time slice is controlled by the scheduler, variable
+-frequency profiling, and a complete removal of jiffies in the future.
+-
+-
+-Aside the current initial submission of i386 support, the patchset has been
+-extended to x86_64 and ARM already. Initial (work in progress) support is also
+-available for MIPS and PowerPC.
+-
+-	  Thomas, Ingo
+-
+-
+-
+diff --git a/Documentation/hrtimers/hrtimers.txt b/Documentation/hrtimers/hrtimers.txt
+deleted file mode 100644
+index ce31f65..0000000
+--- a/Documentation/hrtimers/hrtimers.txt
++++ /dev/null
+@@ -1,178 +0,0 @@
+-
+-hrtimers - subsystem for high-resolution kernel timers
+-----------------------------------------------------
+-
+-This patch introduces a new subsystem for high-resolution kernel timers.
+-
+-One might ask the question: we already have a timer subsystem
+-(kernel/timers.c), why do we need two timer subsystems? After a lot of
+-back and forth trying to integrate high-resolution and high-precision
+-features into the existing timer framework, and after testing various
+-such high-resolution timer implementations in practice, we came to the
+-conclusion that the timer wheel code is fundamentally not suitable for
+-such an approach. We initially didn't believe this ('there must be a way
+-to solve this'), and spent a considerable effort trying to integrate
+-things into the timer wheel, but we failed. In hindsight, there are
+-several reasons why such integration is hard/impossible:
+-
+-- the forced handling of low-resolution and high-resolution timers in
+-  the same way leads to a lot of compromises, macro magic and #ifdef
+-  mess. The timers.c code is very "tightly coded" around jiffies and
+-  32-bitness assumptions, and has been honed and micro-optimized for a
+-  relatively narrow use case (jiffies in a relatively narrow HZ range)
+-  for many years - and thus even small extensions to it easily break
+-  the wheel concept, leading to even worse compromises. The timer wheel
+-  code is very good and tight code, there's zero problems with it in its
+-  current usage - but it is simply not suitable to be extended for
+-  high-res timers.
+-
+-- the unpredictable [O(N)] overhead of cascading leads to delays which
+-  necessitate a more complex handling of high resolution timers, which
+-  in turn decreases robustness. Such a design still led to rather large
+-  timing inaccuracies. Cascading is a fundamental property of the timer
+-  wheel concept, it cannot be 'designed out' without unevitably
+-  degrading other portions of the timers.c code in an unacceptable way.
+-
+-- the implementation of the current posix-timer subsystem on top of
+-  the timer wheel has already introduced a quite complex handling of
+-  the required readjusting of absolute CLOCK_REALTIME timers at
+-  settimeofday or NTP time - further underlying our experience by
+-  example: that the timer wheel data structure is too rigid for high-res
+-  timers.
+-
+-- the timer wheel code is most optimal for use cases which can be
+-  identified as "timeouts". Such timeouts are usually set up to cover
+-  error conditions in various I/O paths, such as networking and block
+-  I/O. The vast majority of those timers never expire and are rarely
+-  recascaded because the expected correct event arrives in time so they
+-  can be removed from the timer wheel before any further processing of
+-  them becomes necessary. Thus the users of these timeouts can accept
+-  the granularity and precision tradeoffs of the timer wheel, and
+-  largely expect the timer subsystem to have near-zero overhead.
+-  Accurate timing for them is not a core purpose - in fact most of the
+-  timeout values used are ad-hoc. For them it is at most a necessary
+-  evil to guarantee the processing of actual timeout completions
+-  (because most of the timeouts are deleted before completion), which
+-  should thus be as cheap and unintrusive as possible.
+-
+-The primary users of precision timers are user-space applications that
+-utilize nanosleep, posix-timers and itimer interfaces. Also, in-kernel
+-users like drivers and subsystems which require precise timed events
+-(e.g. multimedia) can benefit from the availability of a separate
+-high-resolution timer subsystem as well.
+-
+-While this subsystem does not offer high-resolution clock sources just
+-yet, the hrtimer subsystem can be easily extended with high-resolution
+-clock capabilities, and patches for that exist and are maturing quickly.
+-The increasing demand for realtime and multimedia applications along
+-with other potential users for precise timers gives another reason to
+-separate the "timeout" and "precise timer" subsystems.
+-
+-Another potential benefit is that such a separation allows even more
+-special-purpose optimization of the existing timer wheel for the low
+-resolution and low precision use cases - once the precision-sensitive
+-APIs are separated from the timer wheel and are migrated over to
+-hrtimers. E.g. we could decrease the frequency of the timeout subsystem
+-from 250 Hz to 100 HZ (or even smaller).
+-
+-hrtimer subsystem implementation details
+-----------------------------------------
+-
+-the basic design considerations were:
+-
+-- simplicity
+-
+-- data structure not bound to jiffies or any other granularity. All the
+-  kernel logic works at 64-bit nanoseconds resolution - no compromises.
+-
+-- simplification of existing, timing related kernel code
+-
+-another basic requirement was the immediate enqueueing and ordering of
+-timers at activation time. After looking at several possible solutions
+-such as radix trees and hashes, we chose the red black tree as the basic
+-data structure. Rbtrees are available as a library in the kernel and are
+-used in various performance-critical areas of e.g. memory management and
+-file systems. The rbtree is solely used for time sorted ordering, while
+-a separate list is used to give the expiry code fast access to the
+-queued timers, without having to walk the rbtree.
+-
+-(This separate list is also useful for later when we'll introduce
+-high-resolution clocks, where we need separate pending and expired
+-queues while keeping the time-order intact.)
+-
+-Time-ordered enqueueing is not purely for the purposes of
+-high-resolution clocks though, it also simplifies the handling of
+-absolute timers based on a low-resolution CLOCK_REALTIME. The existing
+-implementation needed to keep an extra list of all armed absolute
+-CLOCK_REALTIME timers along with complex locking. In case of
+-settimeofday and NTP, all the timers (!) had to be dequeued, the
+-time-changing code had to fix them up one by one, and all of them had to
+-be enqueued again. The time-ordered enqueueing and the storage of the
+-expiry time in absolute time units removes all this complex and poorly
+-scaling code from the posix-timer implementation - the clock can simply
+-be set without having to touch the rbtree. This also makes the handling
+-of posix-timers simpler in general.
+-
+-The locking and per-CPU behavior of hrtimers was mostly taken from the
+-existing timer wheel code, as it is mature and well suited. Sharing code
+-was not really a win, due to the different data structures. Also, the
+-hrtimer functions now have clearer behavior and clearer names - such as
+-hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
+-equivalent to del_timer() and del_timer_sync()] - so there's no direct
+-1:1 mapping between them on the algorithmical level, and thus no real
+-potential for code sharing either.
+-
+-Basic data types: every time value, absolute or relative, is in a
+-special nanosecond-resolution type: ktime_t. The kernel-internal
+-representation of ktime_t values and operations is implemented via
+-macros and inline functions, and can be switched between a "hybrid
+-union" type and a plain "scalar" 64bit nanoseconds representation (at
+-compile time). The hybrid union type optimizes time conversions on 32bit
+-CPUs. This build-time-selectable ktime_t storage format was implemented
+-to avoid the performance impact of 64-bit multiplications and divisions
+-on 32bit CPUs. Such operations are frequently necessary to convert
+-between the storage formats provided by kernel and userspace interfaces
+-and the internal time format. (See include/linux/ktime.h for further
+-details.)
+-
+-hrtimers - rounding of timer values
+------------------------------------
+-
+-the hrtimer code will round timer events to lower-resolution clocks
+-because it has to. Otherwise it will do no artificial rounding at all.
+-
+-one question is, what resolution value should be returned to the user by
+-the clock_getres() interface. This will return whatever real resolution
+-a given clock has - be it low-res, high-res, or artificially-low-res.
+-
+-hrtimers - testing and verification
+-----------------------------------
+-
+-We used the high-resolution clock subsystem ontop of hrtimers to verify
+-the hrtimer implementation details in praxis, and we also ran the posix
+-timer tests in order to ensure specification compliance. We also ran
+-tests on low-resolution clocks.
+-
+-The hrtimer patch converts the following kernel functionality to use
+-hrtimers:
+-
+- - nanosleep
+- - itimers
+- - posix-timers
+-
+-The conversion of nanosleep and posix-timers enabled the unification of
+-nanosleep and clock_nanosleep.
+-
+-The code was successfully compiled for the following platforms:
+-
+- i386, x86_64, ARM, PPC, PPC64, IA64
+-
+-The code was run-tested on the following platforms:
+-
+- i386(UP/SMP), x86_64(UP/SMP), ARM, PPC
+-
+-hrtimers were also integrated into the -rt tree, along with a
+-hrtimers-based high-resolution clock implementation, so the hrtimers
+-code got a healthy amount of testing and use in practice.
+-
+-	Thomas Gleixner, Ingo Molnar
+diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt
+index fc49b79..2eb1610 100644
+--- a/Documentation/i386/boot.txt
++++ b/Documentation/i386/boot.txt
+@@ -170,6 +170,8 @@ Offset	Proto	Name		Meaning
+ 0238/4	2.06+	cmdline_size	Maximum size of the kernel command line
+ 023C/4	2.07+	hardware_subarch Hardware subarchitecture
+ 0240/8	2.07+	hardware_subarch_data Subarchitecture-specific data
++0248/4	2.08+	payload_offset	Offset of kernel payload
++024C/4	2.08+	payload_length	Length of kernel payload
+ 
+ (1) For backwards compatibility, if the setup_sects field contains 0, the
+     real value is 4.
+@@ -512,6 +514,32 @@ Protocol:	2.07+
+ 
+   A pointer to data that is specific to hardware subarch
+ 
++Field name:	payload_offset
++Type:		read
++Offset/size:	0x248/4
++Protocol:	2.08+
++
++  If non-zero then this field contains the offset from the end of the
++  real-mode code to the payload.
++
++  The payload may be compressed. The format of both the compressed and
++  uncompressed data should be determined using the standard magic
++  numbers. Currently only gzip compressed ELF is used.
++  
++Field name:	payload_length
++Type:		read
++Offset/size:	0x24c/4
++Protocol:	2.08+
++
++  The length of the payload.
++
++**** THE IMAGE CHECKSUM
++
++From boot protocol version 2.08 onwards the CRC-32 is calculated over
++the entire file using the characteristic polynomial 0x04C11DB7 and an
++initial remainder of 0xffffffff.  The checksum is appended to the
++file; therefore the CRC of the file up to the limit specified in the
++syssize field of the header is always 0.
+ 
+ **** THE KERNEL COMMAND LINE
+ 
+diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt
+index 818676a..486c699 100644
+--- a/Documentation/ide/ide.txt
++++ b/Documentation/ide/ide.txt
+@@ -71,29 +71,6 @@ This driver automatically probes for most IDE interfaces (including all PCI
+ ones), for the drives/geometries attached to those interfaces, and for the IRQ
+ lines being used by the interfaces (normally 14, 15 for ide0/ide1).
+ 
+-For special cases, interfaces may be specified using kernel "command line"
+-options.  For example,
+-
+-	ide3=0x168,0x36e,10	/* ioports 0x168-0x16f,0x36e, irq 10 */
+-
+-Normally the irq number need not be specified, as ide.c will probe for it:
+-
+-	ide3=0x168,0x36e	/* ioports 0x168-0x16f,0x36e */
+-
+-The standard port, and irq values are these:
+-
+-	ide0=0x1f0,0x3f6,14
+-	ide1=0x170,0x376,15
+-	ide2=0x1e8,0x3ee,11
+-	ide3=0x168,0x36e,10
+-
+-Note that the first parameter reserves 8 contiguous ioports, whereas the
+-second value denotes a single ioport. If in doubt, do a 'cat /proc/ioports'.
+-
+-In all probability the device uses these ports and IRQs if it is attached
+-to the appropriate ide channel.  Pass the parameter for the correct ide
+-channel to the kernel, as explained above.
+-
+ Any number of interfaces may share a single IRQ if necessary, at a slight
+ performance penalty, whether on separate cards or a single VLB card.
+ The IDE driver automatically detects and handles this.  However, this may
+@@ -184,13 +161,6 @@ provided it is mounted with the default block size of 1024 (as above).
+ Please pass on any feedback on any of this stuff to the maintainer,
+ whose address can be found in linux/MAINTAINERS.
+ 
+-Note that if BOTH hd.c and ide.c are configured into the kernel,
+-hd.c will normally be allowed to control the primary IDE interface.
+-This is useful for older hardware that may be incompatible with ide.c,
+-and still allows newer hardware to run on the 2nd/3rd/4th IDE ports
+-under control of ide.c.   To have ide.c also "take over" the primary
+-IDE port in this situation, use the "command line" parameter:  ide0=0x1f0
+-
+ The IDE driver is modularized.  The high level disk/CD-ROM/tape/floppy
+ drivers can always be compiled as loadable modules, the chipset drivers
+ can only be compiled into the kernel, and the core code (ide.c) can be
+@@ -206,7 +176,7 @@ When ide.c is used as a module, you can pass command line parameters to the
+ driver using the "options=" keyword to insmod, while replacing any ',' with
+ ';'.  For example:
+ 
+-	insmod ide.o options="ide0=serialize ide1=serialize ide2=0x1e8;0x3ee;11"
++	insmod ide.o options="hda=nodma hdb=nodma"
+ 
+ 
+ ================================================================================
+@@ -247,21 +217,11 @@ Summary of ide driver parameters for kernel command line
+ 			  As for VLB, it is safest to not specify it.
+ 			  Bigger values are safer than smaller ones.
+ 
+- "idex=base"		: probe for an interface at the addr specified,
+-			  where "base" is usually 0x1f0 or 0x170
+-			  and "ctl" is assumed to be "base"+0x206
+-
+- "idex=base,ctl"	: specify both base and ctl
+-
+- "idex=base,ctl,irq"	: specify base, ctl, and irq number
+-
+  "idex=serialize"	: do not overlap operations on idex. Please note
+ 			  that you will have to specify this option for
+ 			  both the respective primary and secondary channel
+ 			  to take effect.
+ 
+- "idex=four"		: four drives on idex and ide(x^1) share same ports
+-
+  "idex=reset"		: reset interface after probe
+ 
+  "idex=ata66"		: informs the interface that it has an 80c cable
+@@ -269,8 +229,6 @@ Summary of ide driver parameters for kernel command line
+ 			  ability to bit test for detection is currently
+ 			  unknown.
+ 
+- "ide=reverse"		: formerly called to pci sub-system, but now local.
+-
+  "ide=doubler"		: probe/support IDE doublers on Amiga
+ 
+ There may be more options than shown -- use the source, Luke!
+@@ -290,6 +248,9 @@ Also for legacy CMD640 host driver (cmd640) you need to use "probe_vlb"
+ kernel paremeter to enable probing for VLB version of the chipset (PCI ones
+ are detected automatically).
+ 
++You also need to use "probe" kernel parameter for ide-4drives driver
++(support for IDE generic chipset with four drives on one port).
++
+ ================================================================================
+ 
+ Some Terminology
+diff --git a/Documentation/ide/warm-plug-howto.txt b/Documentation/ide/warm-plug-howto.txt
+new file mode 100644
+index 0000000..d588546
+--- /dev/null
++++ b/Documentation/ide/warm-plug-howto.txt
+@@ -0,0 +1,13 @@
++
++IDE warm-plug HOWTO
++===================
++
++To warm-plug devices on a port 'idex':
++
++# echo -n "1" > /sys/class/ide_port/idex/delete_devices
++
++unplug old device(s) and plug new device(s)
++
++# echo -n "1" > /sys/class/ide_port/idex/scan
++
++done
+diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
+index 1d247d5..1821c07 100644
+--- a/Documentation/kbuild/modules.txt
++++ b/Documentation/kbuild/modules.txt
+@@ -486,7 +486,7 @@ Module.symvers contains a list of all exported symbols from a kernel build.
+ 	Sometimes, an external module uses exported symbols from another
+ 	external module. Kbuild needs to have full knowledge on all symbols
+ 	to avoid spitting out warnings about undefined symbols.
+-	Two solutions exist to let kbuild know all symbols of more than
++	Three solutions exist to let kbuild know all symbols of more than
+ 	one external module.
+ 	The method with a top-level kbuild file is recommended but may be
+ 	impractical in certain situations.
+@@ -523,6 +523,13 @@ Module.symvers contains a list of all exported symbols from a kernel build.
+ 		containing the sum of all symbols defined and not part of the
+ 		kernel.
+ 
++	Use make variable KBUILD_EXTRA_SYMBOLS in the Makefile
++		If it is impractical to copy Module.symvers from another
++		module, you can assign a space separated list of files to
++		KBUILD_EXTRA_SYMBOLS in your Makfile. These files will be
++		loaded by modpost during the initialisation of its symbol
++		tables.
++
+ === 8. Tips & Tricks
+ 
+ --- 8.1 Testing for CONFIG_FOO_BAR
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index dafd001..bf6303e 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -366,6 +366,12 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			possible to determine what the correct size should be.
+ 			This option provides an override for these situations.
+ 
++	security=	[SECURITY] Choose a security module to enable at boot.
++			If this boot parameter is not specified, only the first
++			security module asking for security registration will be
++			loaded. An invalid security module name will be treated
++			as if no module has been chosen.
++
+ 	capability.disable=
+ 			[SECURITY] Disable capabilities.  This would normally
+ 			be used only if an alternative security model is to be
+@@ -763,11 +769,11 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
+ 
+ 	ide=		[HW] (E)IDE subsystem
+-			Format: ide=nodma or ide=doubler or ide=reverse
++			Format: ide=nodma or ide=doubler
+ 			See Documentation/ide/ide.txt.
+ 
+ 	ide?=		[HW] (E)IDE subsystem
+-			Format: ide?=noprobe or chipset specific parameters.
++			Format: ide?=ata66 or chipset specific parameters.
+ 			See Documentation/ide/ide.txt.
+ 
+ 	idebus=		[HW] (E)IDE subsystem - VLB/PCI bus speed
+@@ -812,6 +818,19 @@ and is between 256 and 4096 characters. It is defined in the file
+ 
+ 	inttest=	[IA64]
+ 
++	iommu=		[x86]
++		off
++		force
++		noforce
++		biomerge
++		panic
++		nopanic
++		merge
++		nomerge
++		forcesac
++		soft
++
++
+ 	intel_iommu=	[DMAR] Intel IOMMU driver (DMAR) option
+ 		off
+ 			Disable intel iommu driver.
+@@ -828,6 +847,10 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			than 32 bit addressing. The default is to look
+ 			for translation below 32 bit and if not available
+ 			then look in the higher range.
++		strict [Default Off]
++			With this option on every unmap_single operation will
++			result in a hardware IOTLB flush operation as opposed
++			to batching them for performance.
+ 
+ 	io_delay=	[X86-32,X86-64] I/O delay method
+ 		0x80
+@@ -928,8 +951,15 @@ and is between 256 and 4096 characters. It is defined in the file
+ 	kstack=N	[X86-32,X86-64] Print N words from the kernel stack
+ 			in oops dumps.
+ 
++	kgdboc=		[HW] kgdb over consoles.
++			Requires a tty driver that supports console polling.
++			(only serial suported for now)
++			Format: <serial_device>[,baud]
++
+ 	l2cr=		[PPC]
+ 
++	l3cr=		[PPC]
++
+ 	lapic		[X86-32,APIC] Enable the local APIC even if BIOS
+ 			disabled it.
+ 
+@@ -1134,6 +1164,11 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			         or
+ 			         memmap=0x10000$0x18690000
+ 
++	memtest=	[KNL,X86_64] Enable memtest
++			Format: <integer>
++			range: 0,4 : pattern number
++			default : 0 <disable>
++
+ 	meye.*=		[HW] Set MotionEye Camera parameters
+ 			See Documentation/video4linux/meye.txt.
+ 
+@@ -1251,8 +1286,16 @@ and is between 256 and 4096 characters. It is defined in the file
+ 	noexec		[IA-64]
+ 
+ 	noexec		[X86-32,X86-64]
++			On X86-32 available only on PAE configured kernels.
+ 			noexec=on: enable non-executable mappings (default)
+-			noexec=off: disable nn-executable mappings
++			noexec=off: disable non-executable mappings
++
++	noexec32	[X86-64]
++			This affects only 32-bit executables.
++			noexec32=on: enable non-executable mappings (default)
++				read doesn't imply executable mappings
++			noexec32=off: disable non-executable mappings
++				read implies executable mappings
+ 
+ 	nofxsr		[BUGS=X86-32] Disables x86 floating point extended
+ 			register save and restore. The kernel will only save
+@@ -1339,6 +1382,10 @@ and is between 256 and 4096 characters. It is defined in the file
+ 
+ 	nowb		[ARM]
+ 
++	nptcg=		[IA64] Override max number of concurrent global TLB
++			purges which is reported from either PAL_VM_SUMMARY or
++			SAL PALO.
++
+ 	numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
+ 			one of ['zone', 'node', 'default'] can be specified
+ 			This can be set from sysctl after boot.
+@@ -1428,10 +1475,6 @@ and is between 256 and 4096 characters. It is defined in the file
+ 		nomsi		[MSI] If the PCI_MSI kernel config parameter is
+ 				enabled, this kernel boot option can be used to
+ 				disable the use of MSI interrupts system-wide.
+-		nosort		[X86-32] Don't sort PCI devices according to
+-				order given by the PCI BIOS. This sorting is
+-				done to get a device order compatible with
+-				older kernels.
+ 		biosirq		[X86-32] Use PCI BIOS calls to get the interrupt
+ 				routing table. These calls are known to be buggy
+ 				on several machines and they hang the machine
+diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt
+index 23df051..79b7dbd 100644
+--- a/Documentation/laptops/acer-wmi.txt
++++ b/Documentation/laptops/acer-wmi.txt
+@@ -80,7 +80,7 @@ once you enable the radio, will depend on your hardware and driver combination.
+ e.g. With the BCM4318 on the Acer Aspire 5020 series:
+ 
+ ndiswrapper: Light blinks on when transmitting
+-bcm43xx/b43: Solid light, blinks off when transmitting
++b43: Solid light, blinks off when transmitting
+ 
+ Wireless radio control is unconditionally enabled - all Acer laptops that support
+ acer-wmi come with built-in wireless. However, should you feel so inclined to
+diff --git a/Documentation/leds-class.txt b/Documentation/leds-class.txt
+index 56757c7..18860ad 100644
+--- a/Documentation/leds-class.txt
++++ b/Documentation/leds-class.txt
+@@ -19,6 +19,12 @@ optimises away.
+ 
+ Complex triggers whilst available to all LEDs have LED specific
+ parameters and work on a per LED basis. The timer trigger is an example.
++The timer trigger will periodically change the LED brightness between
++LED_OFF and the current brightness setting. The "on" and "off" time can
++be specified via /sys/class/leds/<device>/delay_{on,off} in milliseconds.
++You can change the brightness value of a LED independently of the timer
++trigger. However, if you set the brightness value to LED_OFF it will
++also disable the timer trigger.
+ 
+ You can change triggers in a similar manner to the way an IO scheduler
+ is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
+@@ -63,9 +69,9 @@ value if it is called with *delay_on==0 && *delay_off==0 parameters. In
+ this case the driver should give back the chosen value through delay_on
+ and delay_off parameters to the leds subsystem.
+ 
+-Any call to the brightness_set() callback function should cancel the
+-previously programmed hardware blinking function so setting the brightness
+-to 0 can also cancel the blinking of the LED.
++Setting the brightness to zero with brightness_set() callback function
++should completely turn off the LED and cancel the previously programmed
++hardware blinking function, if any.
+ 
+ 
+ Known Issues
+diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt
+index bd450e7..9507002 100644
+--- a/Documentation/magic-number.txt
++++ b/Documentation/magic-number.txt
+@@ -95,7 +95,6 @@ RFCOMM_TTY_MAGIC      0x6d02                        net/bluetooth/rfcomm/tty.c
+ USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
+ CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
+ A2232_MAGIC           0x000a2232  gs_port           drivers/char/ser_a2232.h
+-SOLARIS_SOCKET_MAGIC  0x000ADDED  sol_socket_struct arch/sparc64/solaris/socksys.h
+ RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
+ LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
+ GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
+diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
+index 1f506f7..e5a819a 100644
+--- a/Documentation/memory-barriers.txt
++++ b/Documentation/memory-barriers.txt
+@@ -430,8 +430,8 @@ There are certain things that the Linux kernel memory barriers do not guarantee:
+ 
+ 	[*] For information on bus mastering DMA and coherency please read:
+ 
+-	    Documentation/pci.txt
+-	    Documentation/DMA-mapping.txt
++	    Documentation/PCI/pci.txt
++	    Documentation/PCI/PCI-DMA-mapping.txt
+ 	    Documentation/DMA-API.txt
+ 
+ 
+diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
+index c485ee0..1634c6d 100644
+--- a/Documentation/networking/00-INDEX
++++ b/Documentation/networking/00-INDEX
+@@ -100,8 +100,6 @@ tuntap.txt
+ 	- TUN/TAP device driver, allowing user space Rx/Tx of packets.
+ vortex.txt
+ 	- info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards.
+-wan-router.txt
+-	- WAN router documentation
+ wavelan.txt
+ 	- AT&T GIS (nee NCR) WaveLAN card: An Ethernet-like radio transceiver
+ x25.txt
+diff --git a/Documentation/networking/bcm43xx.txt b/Documentation/networking/bcm43xx.txt
+deleted file mode 100644
+index d602c8d..0000000
+--- a/Documentation/networking/bcm43xx.txt
++++ /dev/null
+@@ -1,89 +0,0 @@
+-
+-			BCM43xx Linux Driver Project
+-			============================
+-
+-Introduction
+-------------
+-
+-Many of the wireless devices found in modern notebook computers are
+-based on the wireless chips produced by Broadcom. These devices have
+-been a problem for Linux users as there is no open-source driver
+-available. In addition, Broadcom has not released specifications
+-for the device, and driver availability has been limited to the
+-binary-only form used in the GPL versions of AP hardware such as the
+-Linksys WRT54G, and the Windows and OS X drivers.  Before this project
+-began, the only way to use these devices were to use the Windows or
+-OS X drivers with either the Linuxant or ndiswrapper modules. There
+-is a strong penalty if this method is used as loading the binary-only
+-module "taints" the kernel, and no kernel developer will help diagnose
+-any kernel problems.
+-
+-Development
+------------
+-
+-This driver has been developed using
+-a clean-room technique that is described at
+-http://bcm-specs.sipsolutions.net/ReverseEngineeringProcess. For legal
+-reasons, none of the clean-room crew works on the on the Linux driver,
+-and none of the Linux developers sees anything but the specifications,
+-which are the ultimate product of the reverse-engineering group.
+-
+-Software
+---------
+-
+-Since the release of the 2.6.17 kernel, the bcm43xx driver has been
+-distributed with the kernel source, and is prebuilt in most, if not
+-all, distributions.  There is, however, additional software that is
+-required. The firmware used by the chip is the intellectual property
+-of Broadcom and they have not given the bcm43xx team redistribution
+-rights to this firmware.  Since we cannot legally redistribute
+-the firmware we cannot include it with the driver. Furthermore, it
+-cannot be placed in the downloadable archives of any distributing
+-organization; therefore, the user is responsible for obtaining the
+-firmware and placing it in the appropriate location so that the driver
+-can find it when initializing.
+-
+-To help with this process, the bcm43xx developers provide a separate
+-program named bcm43xx-fwcutter to "cut" the firmware out of a
+-Windows or OS X driver and write the extracted files to the proper
+-location. This program is usually provided with the distribution;
+-however, it may be downloaded from
+-
+-http://developer.berlios.de/project/showfiles.php?group_id=4547
+-
+-The firmware is available in two versions. V3 firmware is used with
+-the in-kernel bcm43xx driver that uses a software MAC layer called
+-SoftMAC, and will have a microcode revision of 0x127 or smaller. The
+-V4 firmware is used by an out-of-kernel driver employing a variation of
+-the Devicescape MAC layer known as d80211. Once bcm43xx-d80211 reaches
+-a satisfactory level of development, it will replace bcm43xx-softmac
+-in the kernel as it is much more flexible and powerful.
+-
+-A source for the latest V3 firmware is
+-
+-http://downloads.openwrt.org/sources/wl_apsta-3.130.20.0.o
+-
+-Once this file is downloaded, the command
+-'bcm43xx-fwcutter -w <dir> <filename>'
+-will extract the microcode and write it to directory
+-<dir>. The correct directory will depend on your distribution;
+-however, most use '/lib/firmware'. Once this step is completed,
+-the bcm3xx driver should load when the system is booted. To see
+-any messages relating to the driver, issue the command 'dmesg |
+-grep bcm43xx' from a terminal window. If there are any problems,
+-please send that output to Bcm43xx-dev at lists.berlios.de.
+-
+-Although the driver has been in-kernel since 2.6.17, the earliest
+-version is quite limited in its capability. Patches that include
+-all features of later versions are available for the stable kernel
+-versions from 2.6.18. These will be needed if you use a BCM4318,
+-or a PCI Express version (BCM4311 and BCM4312). In addition, if you
+-have an early BCM4306 and more than 1 GB RAM, your kernel will need
+-to be patched.	These patches, which are being updated regularly,
+-are available at ftp://lwfinger.dynalias.org/patches. Look for
+-combined_2.6.YY.patch. Of course you will need kernel source downloaded
+-from kernel.org, or the source from your distribution.
+-
+-If you build your own kernel, please enable CONFIG_BCM43XX_DEBUG
+-and CONFIG_IEEE80211_SOFTMAC_DEBUG. The log information provided is
+-essential for solving any problems.
+diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
+index 0bc95ea..8df6a7b 100644
+--- a/Documentation/networking/phy.txt
++++ b/Documentation/networking/phy.txt
+@@ -1,7 +1,7 @@
+ 
+ -------
+ PHY Abstraction Layer
+-(Updated 2006-11-30)
++(Updated 2008-04-08)
+ 
+ Purpose
+ 
+@@ -291,3 +291,39 @@ Writing a PHY driver
+  Feel free to look at the Marvell, Cicada, and Davicom drivers in
+  drivers/net/phy/ for examples (the lxt and qsemi drivers have
+  not been tested as of this writing)
++
++Board Fixups
++
++ Sometimes the specific interaction between the platform and the PHY requires
++ special handling.  For instance, to change where the PHY's clock input is,
++ or to add a delay to account for latency issues in the data path.  In order
++ to support such contingencies, the PHY Layer allows platform code to register
++ fixups to be run when the PHY is brought up (or subsequently reset).
++
++ When the PHY Layer brings up a PHY it checks to see if there are any fixups
++ registered for it, matching based on UID (contained in the PHY device's phy_id
++ field) and the bus identifier (contained in phydev->dev.bus_id).  Both must
++ match, however two constants, PHY_ANY_ID and PHY_ANY_UID, are provided as
++ wildcards for the bus ID and UID, respectively.
++
++ When a match is found, the PHY layer will invoke the run function associated
++ with the fixup.  This function is passed a pointer to the phy_device of
++ interest.  It should therefore only operate on that PHY.
++
++ The platform code can either register the fixup using phy_register_fixup():
++
++	int phy_register_fixup(const char *phy_id,
++		u32 phy_uid, u32 phy_uid_mask,
++		int (*run)(struct phy_device *));
++
++ Or using one of the two stubs, phy_register_fixup_for_uid() and
++ phy_register_fixup_for_id():
++
++ int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
++		int (*run)(struct phy_device *));
++ int phy_register_fixup_for_id(const char *phy_id,
++		int (*run)(struct phy_device *));
++
++ The stubs set one of the two matching criteria, and set the other one to
++ match anything.
++
+diff --git a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt
+deleted file mode 100644
+index bc2ab41..0000000
+--- a/Documentation/networking/wan-router.txt
++++ /dev/null
+@@ -1,621 +0,0 @@
+-------------------------------------------------------------------------------
+-Linux WAN Router Utilities Package
+-------------------------------------------------------------------------------
+-Version 2.2.1 
+-Mar 28, 2001
+-Author: Nenad Corbic <ncorbic at sangoma.com>
+-Copyright (c) 1995-2001 Sangoma Technologies Inc.
+-------------------------------------------------------------------------------
+-
+-INTRODUCTION
+-
+-Wide Area Networks (WANs) are used to interconnect Local Area Networks (LANs)
+-and/or stand-alone hosts over vast distances with data transfer rates
+-significantly higher than those achievable with commonly used dial-up
+-connections.
+-
+-Usually an external device called `WAN router' sitting on your local network
+-or connected to your machine's serial port provides physical connection to
+-WAN.  Although router's job may be as simple as taking your local network
+-traffic, converting it to WAN format and piping it through the WAN link, these
+-devices are notoriously expensive, with prices as much as 2 - 5 times higher
+-then the price of a typical PC box.
+-
+-Alternatively, considering robustness and multitasking capabilities of Linux,
+-an internal router can be built (most routers use some sort of stripped down
+-Unix-like operating system anyway). With a number of relatively inexpensive WAN
+-interface cards available on the market, a perfectly usable router can be
+-built for less than half a price of an external router.  Yet a Linux box
+-acting as a router can still be used for other purposes, such as fire-walling,
+-running FTP, WWW or DNS server, etc.
+-
+-This kernel module introduces the notion of a WAN Link Driver (WLD) to Linux
+-operating system and provides generic hardware-independent services for such
+-drivers.  Why can existing Linux network device interface not be used for
+-this purpose?  Well, it can.  However, there are a few key differences between
+-a typical network interface (e.g. Ethernet) and a WAN link.
+-
+-Many WAN protocols, such as X.25 and frame relay, allow for multiple logical
+-connections (known as `virtual circuits' in X.25 terminology) over a single
+-physical link.  Each such virtual circuit may (and almost always does) lead
+-to a different geographical location and, therefore, different network.  As a
+-result, it is the virtual circuit, not the physical link, that represents a
+-route and, therefore, a network interface in Linux terms.
+-
+-To further complicate things, virtual circuits are usually volatile in nature
+-(excluding so called `permanent' virtual circuits or PVCs).  With almost no
+-time required to set up and tear down a virtual circuit, it is highly desirable
+-to implement on-demand connections in order to minimize network charges.  So
+-unlike a typical network driver, the WAN driver must be able to handle multiple
+-network interfaces and cope as multiple virtual circuits come into existence
+-and go away dynamically.
+- 
+-Last, but not least, WAN configuration is much more complex than that of say
+-Ethernet and may well amount to several dozens of parameters.  Some of them
+-are "link-wide"  while others are virtual circuit-specific.  The same holds
+-true for WAN statistics which is by far more extensive and extremely useful
+-when troubleshooting WAN connections.  Extending the ifconfig utility to suit
+-these needs may be possible, but does not seem quite reasonable.  Therefore, a
+-WAN configuration utility and corresponding application programmer's interface
+-is needed for this purpose.
+-
+-Most of these problems are taken care of by this module.  Its goal is to
+-provide a user with more-or-less standard look and feel for all WAN devices and
+-assist a WAN device driver writer by providing common services, such as:
+-
+- o User-level interface via /proc file system
+- o Centralized configuration
+- o Device management (setup, shutdown, etc.)
+- o Network interface management (dynamic creation/destruction)
+- o Protocol encapsulation/decapsulation
+-
+-To ba able to use the Linux WAN Router you will also need a WAN Tools package
+-available from
+-
+-	ftp.sangoma.com/pub/linux/current_wanpipe/wanpipe-X.Y.Z.tgz
+-
+-where vX.Y.Z represent the wanpipe version number.
+-
+-For technical questions and/or comments please e-mail to ncorbic at sangoma.com.
+-For general inquiries please contact Sangoma Technologies Inc. by
+-
+-	Hotline:	1-800-388-2475	(USA and Canada, toll free)
+-	Phone:		(905) 474-1990  ext: 106
+-	Fax:		(905) 474-9223
+-	E-mail:		dm at sangoma.com	(David Mandelstam)
+-	WWW:		http://www.sangoma.com
+-
+-
+-INSTALLATION
+-
+-Please read the WanpipeForLinux.pdf manual on how to 
+-install the WANPIPE tools and drivers properly. 
+-
+-
+-After installing wanpipe package: /usr/local/wanrouter/doc. 
+-On the ftp.sangoma.com : /linux/current_wanpipe/doc
+-
+-
+-COPYRIGHT AND LICENSING INFORMATION
+-
+-This program is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free Software
+-Foundation; either version 2, or (at your option) any later version.
+-
+-This program is distributed in the hope that it will be useful, but WITHOUT
+-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+-
+-You 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.
+-
+-
+-
+-ACKNOWLEDGEMENTS
+-
+-This product is based on the WANPIPE(tm) Multiprotocol WAN Router developed
+-by Sangoma Technologies Inc. for Linux 2.0.x and 2.2.x.  Success of the WANPIPE
+-together with the next major release of Linux kernel in summer 1996 commanded
+-adequate changes to the WANPIPE code to take full advantage of new Linux
+-features.
+-
+-Instead of continuing developing proprietary interface tied to Sangoma WAN
+-cards, we decided to separate all hardware-independent code into a separate
+-module and defined two levels of interfaces - one for user-level applications
+-and another for kernel-level WAN drivers.  WANPIPE is now implemented as a
+-WAN driver compliant with the WAN Link Driver interface.  Also a general
+-purpose WAN configuration utility and a set of shell scripts was developed to 
+-support WAN router at the user level.
+-
+-Many useful ideas concerning hardware-independent interface implementation
+-were given by Mike McLagan <mike.mclagan at linux.org> and his implementation
+-of the Frame Relay router and drivers for Sangoma cards (dlci/sdla).
+-
+-With the new implementation of the APIs being incorporated into the WANPIPE,
+-a special thank goes to Alan Cox in providing insight into BSD sockets.
+-
+-Special thanks to all the WANPIPE users who performed field-testing, reported
+-bugs and made valuable comments and suggestions that help us to improve this
+-product.
+-
+-
+-
+-NEW IN THIS RELEASE
+-
+-	o Updated the WANCFG utility
+-		Calls the pppconfig to configure the PPPD
+-		for async connections.
+-
+-	o Added the PPPCONFIG utility
+-		Used to configure the PPPD daemon for the
+-		WANPIPE Async PPP and standard serial port.
+-		The wancfg calls the pppconfig to configure
+-		the pppd.
+-
+-	o Fixed the PCI autodetect feature.  
+-		The SLOT 0 was used as an autodetect option
+-		however, some high end PC's slot numbers start
+-		from 0. 
+-
+-	o This release has been tested with the new backupd
+-	  daemon release.
+-	
+-
+-PRODUCT COMPONENTS AND RELATED FILES
+-
+-/etc: (or user defined)
+-	wanpipe1.conf	default router configuration file
+-
+-/lib/modules/X.Y.Z/misc:
+-	wanrouter.o	router kernel loadable module
+-	af_wanpipe.o	wanpipe api socket module
+-
+-/lib/modules/X.Y.Z/net:
+-	sdladrv.o	Sangoma SDLA support module
+-	wanpipe.o	Sangoma WANPIPE(tm) driver module
+-
+-/proc/net/wanrouter
+-	Config		reads current router configuration
+-	Status		reads current router status
+-	{name}		reads WAN driver statistics
+-
+-/usr/sbin:
+-	wanrouter	wanrouter start-up script
+-	wanconfig	wanrouter configuration utility
+-	sdladump	WANPIPE adapter memory dump utility
+-        fpipemon        Monitor for Frame Relay
+-        cpipemon        Monitor for Cisco HDLC
+-	ppipemon 	Monitor for PPP
+-	xpipemon 	Monitor for X25
+-	wpkbdmon        WANPIPE keyboard led monitor/debugger
+-
+-/usr/local/wanrouter:
+-	README		this file
+-	COPYING		GNU General Public License
+-	Setup		installation script
+-	Filelist	distribution definition file
+-	wanrouter.rc	meta-configuration file 
+-			(used by the Setup and wanrouter script)
+-
+-/usr/local/wanrouter/doc:
+-	wanpipeForLinux.pdf 	WAN Router User's Manual
+-
+-/usr/local/wanrouter/patches:
+-	wanrouter-v2213.gz  	patch for Linux kernels 2.2.11 up to 2.2.13.
+-	wanrouter-v2214.gz	patch for Linux kernel 2.2.14. 
+-	wanrouter-v2215.gz	patch for Linux kernels 2.2.15 to 2.2.17.
+-	wanrouter-v2218.gz	patch for Linux kernels 2.2.18 and up.
+-	wanrouter-v240.gz	patch for Linux kernel 2.4.0.  
+-	wanrouter-v242.gz	patch for Linux kernel 2.4.2 and up.
+-	wanrouter-v2034.gz	patch for Linux kernel 2.0.34
+-	wanrouter-v2036.gz 	patch for Linux kernel 2.0.36 and up. 
+-
+-/usr/local/wanrouter/patches/kdrivers:
+-	Sources of the latest WANPIPE device drivers.
+-	These are used to UPGRADE the linux kernel to the newest
+-	version if the kernel source has already been patched with
+-	WANPIPE drivers.
+-
+-/usr/local/wanrouter/samples:
+-	interface	sample interface configuration file
+-	wanpipe1.cpri 	CHDLC primary port
+-     	wanpipe2.csec 	CHDLC secondary port
+-     	wanpipe1.fr   	Frame Relay protocol
+-     	wanpipe1.ppp  	PPP protocol ) 
+-	wanpipe1.asy	CHDLC ASYNC protocol
+-	wanpipe1.x25	X25 protocol
+-	wanpipe1.stty	Sync TTY driver (Used by Kernel PPPD daemon)
+-	wanpipe1.atty	Async TTY driver (Used by Kernel PPPD daemon)
+-	wanrouter.rc	sample meta-configuration file
+-
+-/usr/local/wanrouter/util:
+-	*		wan-tools utilities source code
+-
+-/usr/local/wanrouter/api/x25:
+-	*		x25 api sample programs.
+-/usr/local/wanrouter/api/chdlc:
+-	*		chdlc api sample programs.
+-/usr/local/wanrouter/api/fr:
+-	*		fr api sample programs.
+-/usr/local/wanrouter/config/wancfg:
+-	wancfg		WANPIPE GUI configuration program.
+-                        Creates wanpipe#.conf files. 
+-/usr/local/wanrouter/config/cfgft1:
+-	cfgft1		GUI CSU/DSU configuration program.
+-
+-/usr/include/linux:
+-	wanrouter.h	router API definitions
+-	wanpipe.h	WANPIPE API definitions
+-	sdladrv.h	SDLA support module API definitions
+-	sdlasfm.h	SDLA firmware module definitions
+-	if_wanpipe.h	WANPIPE Socket definitions
+-	sdlapci.h	WANPIPE PCI definitions
+-	
+-
+-/usr/src/linux/net/wanrouter:
+-	*		wanrouter source code
+-
+-/var/log:
+-	wanrouter	wanrouter start-up log (created by the Setup script)
+-
+-/var/lock:  (or /var/lock/subsys for RedHat)
+-	wanrouter	wanrouter lock file (created by the Setup script)
+-
+-/usr/local/wanrouter/firmware:
+-	fr514.sfm	Frame relay firmware for Sangoma S508/S514 card
+-	cdual514.sfm	Dual Port Cisco HDLC firmware for Sangoma S508/S514 card
+-	ppp514.sfm      PPP Firmware for Sangoma S508 and S514 cards
+-	x25_508.sfm	X25 Firmware for Sangoma S508 card.
+-
+-
+-REVISION HISTORY
+-
+-1.0.0	December 31, 1996	Initial version
+-
+-1.0.1	January 30, 1997	Status and statistics can be read via /proc
+-				filesystem entries.
+-
+-1.0.2   April 30, 1997          Added UDP management via monitors.
+-
+-1.0.3	June 3, 1997		UDP management for multiple boards using Frame
+-				Relay and PPP
+-				Enabled continuous transmission of Configure 
+-				Request Packet for PPP (for 508 only)
+-				Connection Timeout for PPP changed from 900 to 0
+-				Flow Control Problem fixed for Frame Relay
+-
+-1.0.4	July 10, 1997		S508/FT1 monitoring capability in fpipemon and
+-				ppipemon utilities.
+-				Configurable TTL for UDP packets.
+-				Multicast and Broadcast IP source addresses are
+-				silently discarded.
+-
+-1.0.5	July 28, 1997		Configurable T391,T392,N391,N392,N393 for Frame
+-				Relay in router.conf.
+-				Configurable Memory Address through router.conf 
+-				for Frame Relay, PPP and X.25. (commenting this
+- 				out enables auto-detection).
+-				Fixed freeing up received buffers using kfree()
+- 				for Frame Relay and X.25.
+-				Protect sdla_peek() by calling save_flags(),
+-				cli() and restore_flags().
+-				Changed number of Trace elements from 32 to 20
+-				Added DLCI specific data monitoring in FPIPEMON. 
+-2.0.0	Nov 07, 1997		Implemented protection of RACE conditions by 
+-				critical flags for FRAME RELAY and PPP.
+-				DLCI List interrupt mode implemented.
+-				IPX support in FRAME RELAY and PPP.
+-				IPX Server Support (MARS)
+-				More driver specific stats included in FPIPEMON
+-				and PIPEMON.
+-
+-2.0.1	Nov 28, 1997		Bug Fixes for version 2.0.0.
+-				Protection of "enable_irq()" while 
+-				"disable_irq()" has been enabled from any other
+-				routine (for Frame Relay, PPP and X25).
+-				Added additional Stats for Fpipemon and Ppipemon
+-				Improved Load Sharing for multiple boards
+-
+-2.0.2	Dec 09, 1997		Support for PAP and CHAP for ppp has been
+-				implemented.
+-
+-2.0.3	Aug 15, 1998		New release supporting Cisco HDLC, CIR for Frame
+-				relay, Dynamic IP assignment for PPP and Inverse
+-				Arp support for Frame-relay.  Man Pages are 
+-				included for better support and a new utility
+-				for configuring FT1 cards.
+-
+-2.0.4	Dec 09, 1998	        Dual Port support for Cisco HDLC.
+-				Support for HDLC (LAPB) API.
+-				Supports BiSync Streaming code for S502E 
+-				and S503 cards.
+-				Support for Streaming HDLC API.
+-				Provides a BSD socket interface for 
+-				creating applications using BiSync
+-   				streaming.        
+-
+-2.0.5   Aug 04, 1999 		CHDLC initialization bug fix.
+-				PPP interrupt driven driver: 
+-  				Fix to the PPP line hangup problem.
+-				New PPP firmware
+-				Added comments to the startup SYSTEM ERROR messages
+-				Xpipemon debugging application for the X25 protocol
+-				New USER_MANUAL.txt
+-				Fixed the odd boundary 4byte writes to the board.
+-				BiSync Streaming code has been taken out.  
+-				 Available as a patch.
+-				Streaming HDLC API has been taken out.  
+-				 Available as a patch.                 
+-
+-2.0.6   Aug 17, 1999		Increased debugging in statup scripts
+-				Fixed installation bugs from 2.0.5
+-				Kernel patch works for both 2.2.10 and 2.2.11 kernels.
+-				There is no functional difference between the two packages         
+-
+-2.0.7   Aug 26, 1999		o  Merged X25API code into WANPIPE.
+-				o  Fixed a memory leak for X25API
+-				o  Updated the X25API code for 2.2.X kernels.
+-				o  Improved NEM handling.   
+-
+-2.1.0	Oct 25, 1999		o New code for S514 PCI Card
+-				o New CHDLC and Frame Relay drivers
+-				o PPP and X25 are not supported in this release    
+-
+-2.1.1	Nov 30, 1999		o PPP support for S514 PCI Cards
+-
+-2.1.3   Apr 06, 2000		o Socket based x25api 
+-				o Socket based chdlc api
+-				o Socket based fr api
+-				o Dual Port Receive only CHDLC support.
+-				o Asynchronous CHDLC support (Secondary Port)
+-				o cfgft1 GUI csu/dsu configurator
+-				o wancfg GUI configuration file 
+-				  configurator.
+-				o Architectural directory changes.
+-
+-beta-2.1.4 Jul 2000		o Dynamic interface configuration:
+-					Network interfaces reflect the state
+-					of protocol layer.  If the protocol becomes
+-					disconnected, driver will bring down
+-					the interface.  Once the protocol reconnects
+-					the interface will be brought up. 
+-					
+-					Note: This option is turned off by default.
+-
+-				o Dynamic wanrouter setup using 'wanconfig':
+-					wanconfig utility can be used to
+-					shutdown,restart,start or reconfigure 
+-					a virtual circuit dynamically.
+-				     
+-					Frame Relay:  Each DLCI can be: 
+-						      created,stopped,restarted and reconfigured
+-						      dynamically using wanconfig.
+-					
+-						      ex: wanconfig card wanpipe1 dev wp1_fr16 up
+-				  
+-				o Wanrouter startup via command line arguments:
+-					wanconfig also supports wanrouter startup via command line
+-					arguments.  Thus, there is no need to create a wanpipe#.conf
+-					configuration file.  
+-
+-				o Socket based x25api update/bug fixes.
+-					Added support for LCN numbers greater than 255.
+-					Option to pass up modem messages.
+-					Provided a PCI IRQ check, so a single S514
+-					card is guaranteed to have a non-sharing interrupt.
+-
+-				o Fixes to the wancfg utility.
+-				o New FT1 debugging support via *pipemon utilities.
+-				o Frame Relay ARP support Enabled.
+-
+-beta3-2.1.4 Jul 2000		o X25 M_BIT Problem fix.
+-				o Added the Multi-Port PPP
+-				  Updated utilities for the Multi-Port PPP.
+-
+-2.1.4	Aut 2000
+-				o In X25API:
+-					Maximum packet an application can send
+-					to the driver has been extended to 4096 bytes.
+-
+-					Fixed the x25 startup bug. Enable 
+-					communications only after all interfaces
+-					come up.  HIGH SVC/PVC is used to calculate
+-					the number of channels.
+-					Enable protocol only after all interfaces
+-					are enabled.
+-
+-				o Added an extra state to the FT1 config, kernel module.
+-				o Updated the pipemon debuggers.
+-
+-				o Blocked the Multi-Port PPP from running on kernels
+-				  2.2.16 or greater, due to syncppp kernel module
+-				  change. 
+-	  
+-beta1-2.1.5 	Nov 15 2000
+-				o Fixed the MultiPort PPP Support for kernels 2.2.16 and above.
+-				  2.2.X kernels only
+-
+-				o Secured the driver UDP debugging calls
+-					- All illegal network debugging calls are reported to
+-					  the log.
+-					- Defined a set of allowed commands, all other denied.
+-					
+-				o Cpipemon
+-					- Added set FT1 commands to the cpipemon. Thus CSU/DSU
+-					  configuration can be performed using cpipemon.
+-					  All systems that cannot run cfgft1 GUI utility should
+-					  use cpipemon to configure the on board CSU/DSU.
+-
+-
+-				o Keyboard Led Monitor/Debugger
+-					- A new utility /usr/sbin/wpkbdmon uses keyboard leds
+-					  to convey operational statistic information of the 
+-					  Sangoma WANPIPE cards.
+-					NUM_LOCK    = Line State  (On=connected,    Off=disconnected)
+-					CAPS_LOCK   = Tx data     (On=transmitting, Off=no tx data)
+-					SCROLL_LOCK = Rx data     (On=receiving,    Off=no rx data
+-					
+-				o Hardware probe on module load and dynamic device allocation
+-					- During WANPIPE module load, all Sangoma cards are probed
+-					  and found information is printed in the /var/log/messages.
+-					- If no cards are found, the module load fails.
+-					- Appropriate number of devices are dynamically loaded 
+-					  based on the number of Sangoma cards found.
+-
+-					  Note: The kernel configuration option 
+-						CONFIG_WANPIPE_CARDS has been taken out.
+-					
+-				o Fixed the Frame Relay and Chdlc network interfaces so they are
+-				  compatible with libpcap libraries.  Meaning, tcpdump, snort,
+-				  ethereal, and all other packet sniffers and debuggers work on
+-				  all WANPIPE network interfaces.
+-					- Set the network interface encoding type to ARPHRD_PPP.
+-					  This tell the sniffers that data obtained from the
+-					  network interface is in pure IP format.
+-				  Fix for 2.2.X kernels only.
+-				
+-				o True interface encoding option for Frame Relay and CHDLC
+-					- The above fix sets the network interface encoding
+-					  type to ARPHRD_PPP, however some customers use
+-					  the encoding interface type to determine the
+-					  protocol running.  Therefore, the TURE ENCODING
+-					  option will set the interface type back to the
+-					  original value.  
+-
+-					  NOTE: If this option is used with Frame Relay and CHDLC
+-						libpcap library support will be broken.  
+-						i.e. tcpdump will not work.
+-					Fix for 2.2.x Kernels only.
+-						
+-				o Ethernet Bridgind over Frame Relay
+-					- The Frame Relay bridging has been developed by 
+-					  Kristian Hoffmann and Mark Wells.  
+-					- The Linux kernel bridge is used to send ethernet 
+-					  data over the frame relay links.
+-					For 2.2.X Kernels only.
+-
+-				o Added extensive 2.0.X support. Most new features of
+-				  2.1.5 for protocols Frame Relay, PPP and CHDLC are
+-				  supported under 2.0.X kernels. 
+-
+-beta1-2.2.0 	Dec 30 2000
+-				o Updated drivers for 2.4.X kernels.
+-				o Updated drivers for SMP support.
+-				o X25API is now able to share PCI interrupts.
+-				o Took out a general polling routine that was used
+-				  only by X25API. 
+-				o Added appropriate locks to the dynamic reconfiguration
+-				  code.
+-				o Fixed a bug in the keyboard debug monitor.
+-
+-beta2-2.2.0	Jan 8 2001
+-				o Patches for 2.4.0 kernel
+-				o Patches for 2.2.18 kernel
+-				o Minor updates to PPP and CHLDC drivers.
+-				  Note: No functional difference.
+-
+-beta3-2.2.9	Jan 10 2001
+-				o I missed the 2.2.18 kernel patches in beta2-2.2.0
+-				  release.  They are included in this release.
+-
+-Stable Release
+-2.2.0		Feb 01 2001
+-				o Bug fix in wancfg GUI configurator.
+-					The edit function didn't work properly.
+-
+-
+-bata1-2.2.1	Feb 09 2001
+-			o WANPIPE TTY Driver emulation. 
+-			  Two modes of operation Sync and Async.
+-				Sync: Using the PPPD daemon, kernel SyncPPP layer
+-				      and the Wanpipe sync TTY driver: a PPP protocol 
+-				      connection can be established via Sangoma adapter, over
+-				      a T1 leased line.
+-			
+-				      The 2.4.0 kernel PPP layer supports MULTILINK
+-				      protocol, that can be used to bundle any number of Sangoma
+-				      adapters (T1 lines) into one, under a single IP address.
+-				      Thus, efficiently obtaining multiple T1 throughput. 
+-
+-				      NOTE: The remote side must also implement MULTILINK PPP
+-					    protocol.
+-
+-				Async:Using the PPPD daemon, kernel AsyncPPP layer
+-				      and the WANPIPE async TTY driver: a PPP protocol
+-				      connection can be established via Sangoma adapter and
+-				      a modem, over a telephone line.
+-
+-				      Thus, the WANPIPE async TTY driver simulates a serial
+-				      TTY driver that would normally be used to interface the 
+-				      MODEM to the linux kernel.
+-				
+-			o WANPIPE PPP Backup Utility
+-				This utility will monitor the state of the PPP T1 line.
+-				In case of failure, a dial up connection will be established
+-				via pppd daemon, ether via a serial tty driver (serial port), 
+-				or a WANPIPE async TTY driver (in case serial port is unavailable).
+-				
+-				Furthermore, while in dial up mode, the primary PPP T1 link
+-				will be monitored for signs of life.  
+-
+-				If the PPP T1 link comes back to life, the dial up connection
+-				will be shutdown and T1 line re-established.
+-			
+-
+-			o New Setup installation script.
+-				Option to UPGRADE device drivers if the kernel source has
+-				already been patched with WANPIPE.
+-
+-				Option to COMPILE WANPIPE modules against the currently 
+-				running kernel, thus no need for manual kernel and module
+-				re-compilation.
+-			
+-			o Updates and Bug Fixes to wancfg utility.
+-
+-bata2-2.2.1	Feb 20 2001
+-
+-			o Bug fixes to the CHDLC device drivers.
+-				The driver had compilation problems under kernels
+-				2.2.14 or lower.
+-
+-			o Bug fixes to the Setup installation script.
+-				The device drivers compilation options didn't work
+-				properly.
+-
+-			o Update to the wpbackupd daemon.  
+-				Optimized the cross-over times, between the primary
+-				link and the backup dialup.
+-
+-beta3-2.2.1	Mar 02 2001
+-			o Patches for 2.4.2 kernel.
+-
+-			o Bug fixes to util/ make files.
+-			o Bug fixes to the Setup installation script.
+-
+-			o Took out the backupd support and made it into
+-			  as separate package.
+-			  
+-beta4-2.2.1     Mar 12 2001
+-
+-		o Fix to the Frame Relay Device driver.
+-			IPSAC sends a packet of zero length
+-			header to the frame relay driver.  The
+-			driver tries to push its own 2 byte header
+-			into the packet, which causes the driver to
+-			crash.
+-
+-		o Fix the WANPIPE re-configuration code.
+-			Bug was found by trying to run  the cfgft1 while the
+-			interface was already running.  
+-
+-		o Updates to cfgft1.
+-			Writes a wanpipe#.cfgft1 configuration file
+-			once the CSU/DSU is configured. This file can
+-			holds the current CSU/DSU configuration.
+-
+-
+-
+->>>>>> END OF README <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+-
+-
+diff --git a/Documentation/pci-error-recovery.txt b/Documentation/pci-error-recovery.txt
+deleted file mode 100644
+index 6650af4..0000000
+--- a/Documentation/pci-error-recovery.txt
++++ /dev/null
+@@ -1,396 +0,0 @@
+-
+-                       PCI Error Recovery
+-                       ------------------
+-                        February 2, 2006
+-
+-                 Current document maintainer:
+-             Linas Vepstas <linas at austin.ibm.com>
+-
+-
+-Many PCI bus controllers are able to detect a variety of hardware
+-PCI errors on the bus, such as parity errors on the data and address
+-busses, as well as SERR and PERR errors.  Some of the more advanced
+-chipsets are able to deal with these errors; these include PCI-E chipsets,
+-and the PCI-host bridges found on IBM Power4 and Power5-based pSeries
+-boxes. A typical action taken is to disconnect the affected device,
+-halting all I/O to it.  The goal of a disconnection is to avoid system
+-corruption; for example, to halt system memory corruption due to DMA's
+-to "wild" addresses. Typically, a reconnection mechanism is also
+-offered, so that the affected PCI device(s) are reset and put back
+-into working condition. The reset phase requires coordination
+-between the affected device drivers and the PCI controller chip.
+-This document describes a generic API for notifying device drivers
+-of a bus disconnection, and then performing error recovery.
+-This API is currently implemented in the 2.6.16 and later kernels.
+-
+-Reporting and recovery is performed in several steps. First, when
+-a PCI hardware error has resulted in a bus disconnect, that event
+-is reported as soon as possible to all affected device drivers,
+-including multiple instances of a device driver on multi-function
+-cards. This allows device drivers to avoid deadlocking in spinloops,
+-waiting for some i/o-space register to change, when it never will.
+-It also gives the drivers a chance to defer incoming I/O as
+-needed.
+-
+-Next, recovery is performed in several stages. Most of the complexity
+-is forced by the need to handle multi-function devices, that is,
+-devices that have multiple device drivers associated with them.
+-In the first stage, each driver is allowed to indicate what type
+-of reset it desires, the choices being a simple re-enabling of I/O
+-or requesting a hard reset (a full electrical #RST of the PCI card).
+-If any driver requests a full reset, that is what will be done.
+-
+-After a full reset and/or a re-enabling of I/O, all drivers are
+-again notified, so that they may then perform any device setup/config
+-that may be required.  After these have all completed, a final
+-"resume normal operations" event is sent out.
+-
+-The biggest reason for choosing a kernel-based implementation rather
+-than a user-space implementation was the need to deal with bus
+-disconnects of PCI devices attached to storage media, and, in particular,
+-disconnects from devices holding the root file system.  If the root
+-file system is disconnected, a user-space mechanism would have to go
+-through a large number of contortions to complete recovery. Almost all
+-of the current Linux file systems are not tolerant of disconnection
+-from/reconnection to their underlying block device. By contrast,
+-bus errors are easy to manage in the device driver. Indeed, most
+-device drivers already handle very similar recovery procedures;
+-for example, the SCSI-generic layer already provides significant
+-mechanisms for dealing with SCSI bus errors and SCSI bus resets.
+-
+-
+-Detailed Design
+----------------
+-Design and implementation details below, based on a chain of
+-public email discussions with Ben Herrenschmidt, circa 5 April 2005.
+-
+-The error recovery API support is exposed to the driver in the form of
+-a structure of function pointers pointed to by a new field in struct
+-pci_driver. A driver that fails to provide the structure is "non-aware",
+-and the actual recovery steps taken are platform dependent.  The
+-arch/powerpc implementation will simulate a PCI hotplug remove/add.
+-
+-This structure has the form:
+-struct pci_error_handlers
+-{
+-	int (*error_detected)(struct pci_dev *dev, enum pci_channel_state);
+-	int (*mmio_enabled)(struct pci_dev *dev);
+-	int (*link_reset)(struct pci_dev *dev);
+-	int (*slot_reset)(struct pci_dev *dev);
+-	void (*resume)(struct pci_dev *dev);
+-};
+-
+-The possible channel states are:
+-enum pci_channel_state {
+-	pci_channel_io_normal,  /* I/O channel is in normal state */
+-	pci_channel_io_frozen,  /* I/O to channel is blocked */
+-	pci_channel_io_perm_failure, /* PCI card is dead */
+-};
+-
+-Possible return values are:
+-enum pci_ers_result {
+-	PCI_ERS_RESULT_NONE,        /* no result/none/not supported in device driver */
+-	PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */
+-	PCI_ERS_RESULT_NEED_RESET,  /* Device driver wants slot to be reset. */
+-	PCI_ERS_RESULT_DISCONNECT,  /* Device has completely failed, is unrecoverable */
+-	PCI_ERS_RESULT_RECOVERED,   /* Device driver is fully recovered and operational */
+-};
+-
+-A driver does not have to implement all of these callbacks; however,
+-if it implements any, it must implement error_detected(). If a callback
+-is not implemented, the corresponding feature is considered unsupported.
+-For example, if mmio_enabled() and resume() aren't there, then it
+-is assumed that the driver is not doing any direct recovery and requires
+-a reset. If link_reset() is not implemented, the card is assumed as
+-not care about link resets. Typically a driver will want to know about
+-a slot_reset().
+-
+-The actual steps taken by a platform to recover from a PCI error
+-event will be platform-dependent, but will follow the general
+-sequence described below.
+-
+-STEP 0: Error Event
+--------------------
+-PCI bus error is detect by the PCI hardware.  On powerpc, the slot
+-is isolated, in that all I/O is blocked: all reads return 0xffffffff,
+-all writes are ignored.
+-
+-
+-STEP 1: Notification
+---------------------
+-Platform calls the error_detected() callback on every instance of
+-every driver affected by the error.
+-
+-At this point, the device might not be accessible anymore, depending on
+-the platform (the slot will be isolated on powerpc). The driver may
+-already have "noticed" the error because of a failing I/O, but this
+-is the proper "synchronization point", that is, it gives the driver
+-a chance to cleanup, waiting for pending stuff (timers, whatever, etc...)
+-to complete; it can take semaphores, schedule, etc... everything but
+-touch the device. Within this function and after it returns, the driver
+-shouldn't do any new IOs. Called in task context. This is sort of a
+-"quiesce" point. See note about interrupts at the end of this doc.
+-
+-All drivers participating in this system must implement this call.
+-The driver must return one of the following result codes:
+-		- PCI_ERS_RESULT_CAN_RECOVER:
+-		  Driver returns this if it thinks it might be able to recover
+-		  the HW by just banging IOs or if it wants to be given
+-		  a chance to extract some diagnostic information (see
+-		  mmio_enable, below).
+-		- PCI_ERS_RESULT_NEED_RESET:
+-		  Driver returns this if it can't recover without a hard
+-		  slot reset.
+-		- PCI_ERS_RESULT_DISCONNECT:
+-		  Driver returns this if it doesn't want to recover at all.
+-
+-The next step taken will depend on the result codes returned by the
+-drivers.
+-
+-If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER,
+-then the platform should re-enable IOs on the slot (or do nothing in
+-particular, if the platform doesn't isolate slots), and recovery
+-proceeds to STEP 2 (MMIO Enable).
+-
+-If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET),
+-then recovery proceeds to STEP 4 (Slot Reset).
+-
+-If the platform is unable to recover the slot, the next step
+-is STEP 6 (Permanent Failure).
+-
+->>> The current powerpc implementation assumes that a device driver will
+->>> *not* schedule or semaphore in this routine; the current powerpc
+->>> implementation uses one kernel thread to notify all devices;
+->>> thus, if one device sleeps/schedules, all devices are affected.
+->>> Doing better requires complex multi-threaded logic in the error
+->>> recovery implementation (e.g. waiting for all notification threads
+->>> to "join" before proceeding with recovery.)  This seems excessively
+->>> complex and not worth implementing.
+-
+->>> The current powerpc implementation doesn't much care if the device
+->>> attempts I/O at this point, or not.  I/O's will fail, returning
+->>> a value of 0xff on read, and writes will be dropped. If the device
+->>> driver attempts more than 10K I/O's to a frozen adapter, it will
+->>> assume that the device driver has gone into an infinite loop, and
+->>> it will panic the kernel. There doesn't seem to be any other
+->>> way of stopping a device driver that insists on spinning on I/O.
+-
+-STEP 2: MMIO Enabled
+--------------------
+-The platform re-enables MMIO to the device (but typically not the
+-DMA), and then calls the mmio_enabled() callback on all affected
+-device drivers.
+-
+-This is the "early recovery" call. IOs are allowed again, but DMA is
+-not (hrm... to be discussed, I prefer not), with some restrictions. This
+-is NOT a callback for the driver to start operations again, only to
+-peek/poke at the device, extract diagnostic information, if any, and
+-eventually do things like trigger a device local reset or some such,
+-but not restart operations. This is callback is made if all drivers on
+-a segment agree that they can try to recover and if no automatic link reset
+-was performed by the HW. If the platform can't just re-enable IOs without
+-a slot reset or a link reset, it wont call this callback, and instead
+-will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
+-
+->>> The following is proposed; no platform implements this yet:
+->>> Proposal: All I/O's should be done _synchronously_ from within
+->>> this callback, errors triggered by them will be returned via
+->>> the normal pci_check_whatever() API, no new error_detected()
+->>> callback will be issued due to an error happening here. However,
+->>> such an error might cause IOs to be re-blocked for the whole
+->>> segment, and thus invalidate the recovery that other devices
+->>> on the same segment might have done, forcing the whole segment
+->>> into one of the next states, that is, link reset or slot reset.
+-
+-The driver should return one of the following result codes:
+-		- PCI_ERS_RESULT_RECOVERED
+-		  Driver returns this if it thinks the device is fully
+-		  functional and thinks it is ready to start
+-		  normal driver operations again. There is no
+-		  guarantee that the driver will actually be
+-		  allowed to proceed, as another driver on the
+-		  same segment might have failed and thus triggered a
+-		  slot reset on platforms that support it.
+-
+-		- PCI_ERS_RESULT_NEED_RESET
+-		  Driver returns this if it thinks the device is not
+-		  recoverable in it's current state and it needs a slot
+-		  reset to proceed.
+-
+-		- PCI_ERS_RESULT_DISCONNECT
+-		  Same as above. Total failure, no recovery even after
+-		  reset driver dead. (To be defined more precisely)
+-
+-The next step taken depends on the results returned by the drivers.
+-If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform
+-proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
+-
+-If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
+-proceeds to STEP 4 (Slot Reset)
+-
+->>> The current powerpc implementation does not implement this callback.
+-
+-
+-STEP 3: Link Reset
+-------------------
+-The platform resets the link, and then calls the link_reset() callback
+-on all affected device drivers.  This is a PCI-Express specific state
+-and is done whenever a non-fatal error has been detected that can be
+-"solved" by resetting the link. This call informs the driver of the
+-reset and the driver should check to see if the device appears to be
+-in working condition.
+-
+-The driver is not supposed to restart normal driver I/O operations
+-at this point.  It should limit itself to "probing" the device to
+-check it's recoverability status. If all is right, then the platform
+-will call resume() once all drivers have ack'd link_reset().
+-
+-	Result codes:
+-		(identical to STEP 3 (MMIO Enabled)
+-
+-The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5
+-(Resume Operations).
+-
+->>> The current powerpc implementation does not implement this callback.
+-
+-
+-STEP 4: Slot Reset
+-------------------
+-The platform performs a soft or hard reset of the device, and then
+-calls the slot_reset() callback.
+-
+-A soft reset consists of asserting the adapter #RST line and then
+-restoring the PCI BAR's and PCI configuration header to a state
+-that is equivalent to what it would be after a fresh system
+-power-on followed by power-on BIOS/system firmware initialization.
+-If the platform supports PCI hotplug, then the reset might be
+-performed by toggling the slot electrical power off/on.
+-
+-It is important for the platform to restore the PCI config space
+-to the "fresh poweron" state, rather than the "last state". After
+-a slot reset, the device driver will almost always use its standard
+-device initialization routines, and an unusual config space setup
+-may result in hung devices, kernel panics, or silent data corruption.
+-
+-This call gives drivers the chance to re-initialize the hardware
+-(re-download firmware, etc.).  At this point, the driver may assume
+-that he card is in a fresh state and is fully functional. In
+-particular, interrupt generation should work normally.
+-
+-Drivers should not yet restart normal I/O processing operations
+-at this point.  If all device drivers report success on this
+-callback, the platform will call resume() to complete the sequence,
+-and let the driver restart normal I/O processing.
+-
+-A driver can still return a critical failure for this function if
+-it can't get the device operational after reset.  If the platform
+-previously tried a soft reset, it might now try a hard reset (power
+-cycle) and then call slot_reset() again.  It the device still can't
+-be recovered, there is nothing more that can be done;  the platform
+-will typically report a "permanent failure" in such a case.  The
+-device will be considered "dead" in this case.
+-
+-Drivers for multi-function cards will need to coordinate among
+-themselves as to which driver instance will perform any "one-shot"
+-or global device initialization. For example, the Symbios sym53cxx2
+-driver performs device init only from PCI function 0:
+-
+-+       if (PCI_FUNC(pdev->devfn) == 0)
+-+               sym_reset_scsi_bus(np, 0);
+-
+-	Result codes:
+-		- PCI_ERS_RESULT_DISCONNECT
+-		Same as above.
+-
+-Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
+-Failure).
+-
+->>> The current powerpc implementation does not currently try a
+->>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
+->>> However, it probably should.
+-
+-
+-STEP 5: Resume Operations
+--------------------------
+-The platform will call the resume() callback on all affected device
+-drivers if all drivers on the segment have returned
+-PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks.
+-The goal of this callback is to tell the driver to restart activity,
+-that everything is back and running. This callback does not return
+-a result code.
+-
+-At this point, if a new error happens, the platform will restart
+-a new error recovery sequence.
+-
+-STEP 6: Permanent Failure
+--------------------------
+-A "permanent failure" has occurred, and the platform cannot recover
+-the device.  The platform will call error_detected() with a
+-pci_channel_state value of pci_channel_io_perm_failure.
+-
+-The device driver should, at this point, assume the worst. It should
+-cancel all pending I/O, refuse all new I/O, returning -EIO to
+-higher layers. The device driver should then clean up all of its
+-memory and remove itself from kernel operations, much as it would
+-during system shutdown.
+-
+-The platform will typically notify the system operator of the
+-permanent failure in some way.  If the device is hotplug-capable,
+-the operator will probably want to remove and replace the device.
+-Note, however, not all failures are truly "permanent". Some are
+-caused by over-heating, some by a poorly seated card. Many
+-PCI error events are caused by software bugs, e.g. DMA's to
+-wild addresses or bogus split transactions due to programming
+-errors. See the discussion in powerpc/eeh-pci-error-recovery.txt
+-for additional detail on real-life experience of the causes of
+-software errors.
+-
+-
+-Conclusion; General Remarks
+----------------------------
+-The way those callbacks are called is platform policy. A platform with
+-no slot reset capability may want to just "ignore" drivers that can't
+-recover (disconnect them) and try to let other cards on the same segment
+-recover. Keep in mind that in most real life cases, though, there will
+-be only one driver per segment.
+-
+-Now, a note about interrupts. If you get an interrupt and your
+-device is dead or has been isolated, there is a problem :)
+-The current policy is to turn this into a platform policy.
+-That is, the recovery API only requires that:
+-
+- - There is no guarantee that interrupt delivery can proceed from any
+-device on the segment starting from the error detection and until the
+-resume callback is sent, at which point interrupts are expected to be
+-fully operational.
+-
+- - There is no guarantee that interrupt delivery is stopped, that is,
+-a driver that gets an interrupt after detecting an error, or that detects
+-an error within the interrupt handler such that it prevents proper
+-ack'ing of the interrupt (and thus removal of the source) should just
+-return IRQ_NOTHANDLED. It's up to the platform to deal with that
+-condition, typically by masking the IRQ source during the duration of
+-the error handling. It is expected that the platform "knows" which
+-interrupts are routed to error-management capable slots and can deal
+-with temporarily disabling that IRQ number during error processing (this
+-isn't terribly complex). That means some IRQ latency for other devices
+-sharing the interrupt, but there is simply no other way. High end
+-platforms aren't supposed to share interrupts between many devices
+-anyway :)
+-
+->>> Implementation details for the powerpc platform are discussed in
+->>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
+-
+->>> As of this writing, there are six device drivers with patches
+->>> implementing error recovery. Not all of these patches are in
+->>> mainline yet. These may be used as "examples":
+->>>
+->>> drivers/scsi/ipr.c
+->>> drivers/scsi/sym53cxx_2
+->>> drivers/next/e100.c
+->>> drivers/net/e1000
+->>> drivers/net/ixgb
+->>> drivers/net/s2io.c
+-
+-The End
+--------
+diff --git a/Documentation/pci.txt b/Documentation/pci.txt
+deleted file mode 100644
+index d2c2e6e..0000000
+--- a/Documentation/pci.txt
++++ /dev/null
+@@ -1,646 +0,0 @@
+-
+-			How To Write Linux PCI Drivers
+-
+-		by Martin Mares <mj at ucw.cz> on 07-Feb-2000
+-	updated by Grant Grundler <grundler at parisc-linux.org> on 23-Dec-2006
+-
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-The world of PCI is vast and full of (mostly unpleasant) surprises.
+-Since each CPU architecture implements different chip-sets and PCI devices
+-have different requirements (erm, "features"), the result is the PCI support
+-in the Linux kernel is not as trivial as one would wish. This short paper
+-tries to introduce all potential driver authors to Linux APIs for
+-PCI device drivers.
+-
+-A more complete resource is the third edition of "Linux Device Drivers"
+-by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.
+-LDD3 is available for free (under Creative Commons License) from:
+-
+-	http://lwn.net/Kernel/LDD3/
+-
+-However, keep in mind that all documents are subject to "bit rot".
+-Refer to the source code if things are not working as described here.
+-
+-Please send questions/comments/patches about Linux PCI API to the
+-"Linux PCI" <linux-pci at atrey.karlin.mff.cuni.cz> mailing list.
+-
+-
+-
+-0. Structure of PCI drivers
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-PCI drivers "discover" PCI devices in a system via pci_register_driver().
+-Actually, it's the other way around. When the PCI generic code discovers
+-a new device, the driver with a matching "description" will be notified.
+-Details on this below.
+-
+-pci_register_driver() leaves most of the probing for devices to
+-the PCI layer and supports online insertion/removal of devices [thus
+-supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver].
+-pci_register_driver() call requires passing in a table of function
+-pointers and thus dictates the high level structure of a driver.
+-
+-Once the driver knows about a PCI device and takes ownership, the
+-driver generally needs to perform the following initialization:
+-
+-	Enable the device
+-	Request MMIO/IOP resources
+-	Set the DMA mask size (for both coherent and streaming DMA)
+-	Allocate and initialize shared control data (pci_allocate_coherent())
+-	Access device configuration space (if needed)
+-	Register IRQ handler (request_irq())
+-	Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+-	Enable DMA/processing engines
+-
+-When done using the device, and perhaps the module needs to be unloaded,
+-the driver needs to take the follow steps:
+-	Disable the device from generating IRQs
+-	Release the IRQ (free_irq())
+-	Stop all DMA activity
+-	Release DMA buffers (both streaming and coherent)
+-	Unregister from other subsystems (e.g. scsi or netdev)
+-	Release MMIO/IOP resources
+-	Disable the device
+-
+-Most of these topics are covered in the following sections.
+-For the rest look at LDD3 or <linux/pci.h> .
+-
+-If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
+-the PCI functions described below are defined as inline functions either
+-completely empty or just returning an appropriate error codes to avoid
+-lots of ifdefs in the drivers.
+-
+-
+-
+-1. pci_register_driver() call
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-PCI device drivers call pci_register_driver() during their
+-initialization with a pointer to a structure describing the driver
+-(struct pci_driver):
+-
+-	field name	Description
+-	----------	------------------------------------------------------
+-	id_table	Pointer to table of device ID's the driver is
+-			interested in.  Most drivers should export this
+-			table using MODULE_DEVICE_TABLE(pci,...).
+-
+-	probe		This probing function gets called (during execution
+-			of pci_register_driver() for already existing
+-			devices or later if a new device gets inserted) for
+-			all PCI devices which match the ID table and are not
+-			"owned" by the other drivers yet. This function gets
+-			passed a "struct pci_dev *" for each device whose
+-			entry in the ID table matches the device. The probe
+-			function returns zero when the driver chooses to
+-			take "ownership" of the device or an error code
+-			(negative number) otherwise.
+-			The probe function always gets called from process
+-			context, so it can sleep.
+-
+-	remove		The remove() function gets called whenever a device
+-			being handled by this driver is removed (either during
+-			deregistration of the driver or when it's manually
+-			pulled out of a hot-pluggable slot).
+-			The remove function always gets called from process
+-			context, so it can sleep.
+-
+-	suspend		Put device into low power state.
+-	suspend_late	Put device into low power state.
+-
+-	resume_early	Wake device from low power state.
+-	resume		Wake device from low power state.
+-
+-		(Please see Documentation/power/pci.txt for descriptions
+-		of PCI Power Management and the related functions.)
+-
+-	shutdown	Hook into reboot_notifier_list (kernel/sys.c).
+-			Intended to stop any idling DMA operations.
+-			Useful for enabling wake-on-lan (NIC) or changing
+-			the power state of a device before reboot.
+-			e.g. drivers/net/e100.c.
+-
+-	err_handler	See Documentation/pci-error-recovery.txt
+-
+-
+-The ID table is an array of struct pci_device_id entries ending with an
+-all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred
+-method of declaring the table.  Each entry consists of:
+-
+-	vendor,device	Vendor and device ID to match (or PCI_ANY_ID)
+-
+-	subvendor,	Subsystem vendor and device ID to match (or PCI_ANY_ID)
+-	subdevice,
+-
+-	class		Device class, subclass, and "interface" to match.
+-			See Appendix D of the PCI Local Bus Spec or
+-			include/linux/pci_ids.h for a full list of classes.
+-			Most drivers do not need to specify class/class_mask
+-			as vendor/device is normally sufficient.
+-
+-	class_mask	limit which sub-fields of the class field are compared.
+-			See drivers/scsi/sym53c8xx_2/ for example of usage.
+-
+-	driver_data	Data private to the driver.
+-			Most drivers don't need to use driver_data field.
+-			Best practice is to use driver_data as an index
+-			into a static list of equivalent device types,
+-			instead of using it as a pointer.
+-
+-
+-Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up
+-a pci_device_id table.
+-
+-New PCI IDs may be added to a device driver pci_ids table at runtime
+-as shown below:
+-
+-echo "vendor device subvendor subdevice class class_mask driver_data" > \
+-/sys/bus/pci/drivers/{driver}/new_id
+-
+-All fields are passed in as hexadecimal values (no leading 0x).
+-The vendor and device fields are mandatory, the others are optional. Users
+-need pass only as many optional fields as necessary:
+-	o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
+-	o class and classmask fields default to 0
+-	o driver_data defaults to 0UL.
+-
+-Once added, the driver probe routine will be invoked for any unclaimed
+-PCI devices listed in its (newly updated) pci_ids list.
+-
+-When the driver exits, it just calls pci_unregister_driver() and the PCI layer
+-automatically calls the remove hook for all devices handled by the driver.
+-
+-
+-1.1 "Attributes" for driver functions/data
+-
+-Please mark the initialization and cleanup functions where appropriate
+-(the corresponding macros are defined in <linux/init.h>):
+-
+-	__init		Initialization code. Thrown away after the driver
+-			initializes.
+-	__exit		Exit code. Ignored for non-modular drivers.
+-
+-
+-	__devinit	Device initialization code.
+-			Identical to __init if the kernel is not compiled
+-			with CONFIG_HOTPLUG, normal function otherwise.
+-	__devexit	The same for __exit.
+-
+-Tips on when/where to use the above attributes:
+-	o The module_init()/module_exit() functions (and all
+-	  initialization functions called _only_ from these)
+-	  should be marked __init/__exit.
+-
+-	o Do not mark the struct pci_driver.
+-
+-	o The ID table array should be marked __devinitconst; this is done
+-	  automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE().
+-
+-	o The probe() and remove() functions should be marked __devinit
+-	  and __devexit respectively.  All initialization functions
+-	  exclusively called by the probe() routine, can be marked __devinit.
+-	  Ditto for remove() and __devexit.
+-
+-	o If mydriver_remove() is marked with __devexit(), then all address
+-	  references to mydriver_remove must use __devexit_p(mydriver_remove)
+-	  (in the struct pci_driver declaration for example).
+-	  __devexit_p() will generate the function name _or_ NULL if the
+-	  function will be discarded.  For an example, see drivers/net/tg3.c.
+-
+-	o Do NOT mark a function if you are not sure which mark to use.
+-	  Better to not mark the function than mark the function wrong.
+-
+-
+-
+-2. How to find PCI devices manually
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-PCI drivers should have a really good reason for not using the
+-pci_register_driver() interface to search for PCI devices.
+-The main reason PCI devices are controlled by multiple drivers
+-is because one PCI device implements several different HW services.
+-E.g. combined serial/parallel port/floppy controller.
+-
+-A manual search may be performed using the following constructs:
+-
+-Searching by vendor and device ID:
+-
+-	struct pci_dev *dev = NULL;
+-	while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev))
+-		configure_device(dev);
+-
+-Searching by class ID (iterate in a similar way):
+-
+-	pci_get_class(CLASS_ID, dev)
+-
+-Searching by both vendor/device and subsystem vendor/device ID:
+-
+-	pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
+-
+-You can use the constant PCI_ANY_ID as a wildcard replacement for
+-VENDOR_ID or DEVICE_ID.  This allows searching for any device from a
+-specific vendor, for example.
+-
+-These functions are hotplug-safe. They increment the reference count on
+-the pci_dev that they return. You must eventually (possibly at module unload)
+-decrement the reference count on these devices by calling pci_dev_put().
+-
+-
+-
+-3. Device Initialization Steps
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-As noted in the introduction, most PCI drivers need the following steps
+-for device initialization:
+-
+-	Enable the device
+-	Request MMIO/IOP resources
+-	Set the DMA mask size (for both coherent and streaming DMA)
+-	Allocate and initialize shared control data (pci_allocate_coherent())
+-	Access device configuration space (if needed)
+-	Register IRQ handler (request_irq())
+-	Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+-	Enable DMA/processing engines.
+-
+-The driver can access PCI config space registers at any time.
+-(Well, almost. When running BIST, config space can go away...but
+-that will just result in a PCI Bus Master Abort and config reads
+-will return garbage).
+-
+-
+-3.1 Enable the PCI device
+-~~~~~~~~~~~~~~~~~~~~~~~~~
+-Before touching any device registers, the driver needs to enable
+-the PCI device by calling pci_enable_device(). This will:
+-	o wake up the device if it was in suspended state,
+-	o allocate I/O and memory regions of the device (if BIOS did not),
+-	o allocate an IRQ (if BIOS did not).
+-
+-NOTE: pci_enable_device() can fail! Check the return value.
+-
+-[ OS BUG: we don't check resource allocations before enabling those
+-  resources. The sequence would make more sense if we called
+-  pci_request_resources() before calling pci_enable_device().
+-  Currently, the device drivers can't detect the bug when when two
+-  devices have been allocated the same range. This is not a common
+-  problem and unlikely to get fixed soon.
+-
+-  This has been discussed before but not changed as of 2.6.19:
+-	http://lkml.org/lkml/2006/3/2/194
+-]
+-
+-pci_set_master() will enable DMA by setting the bus master bit
+-in the PCI_COMMAND register. It also fixes the latency timer value if
+-it's set to something bogus by the BIOS.
+-
+-If the PCI device can use the PCI Memory-Write-Invalidate transaction,
+-call pci_set_mwi().  This enables the PCI_COMMAND bit for Mem-Wr-Inval
+-and also ensures that the cache line size register is set correctly.
+-Check the return value of pci_set_mwi() as not all architectures
+-or chip-sets may support Memory-Write-Invalidate.  Alternatively,
+-if Mem-Wr-Inval would be nice to have but is not required, call
+-pci_try_set_mwi() to have the system do its best effort at enabling
+-Mem-Wr-Inval.
+-
+-
+-3.2 Request MMIO/IOP resources
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Memory (MMIO), and I/O port addresses should NOT be read directly
+-from the PCI device config space. Use the values in the pci_dev structure
+-as the PCI "bus address" might have been remapped to a "host physical"
+-address by the arch/chip-set specific kernel support.
+-
+-See Documentation/IO-mapping.txt for how to access device registers
+-or device memory.
+-
+-The device driver needs to call pci_request_region() to verify
+-no other device is already using the same address resource.
+-Conversely, drivers should call pci_release_region() AFTER
+-calling pci_disable_device().
+-The idea is to prevent two devices colliding on the same address range.
+-
+-[ See OS BUG comment above. Currently (2.6.19), The driver can only
+-  determine MMIO and IO Port resource availability _after_ calling
+-  pci_enable_device(). ]
+-
+-Generic flavors of pci_request_region() are request_mem_region()
+-(for MMIO ranges) and request_region() (for IO Port ranges).
+-Use these for address resources that are not described by "normal" PCI
+-BARs.
+-
+-Also see pci_request_selected_regions() below.
+-
+-
+-3.3 Set the DMA mask size
+-~~~~~~~~~~~~~~~~~~~~~~~~~
+-[ If anything below doesn't make sense, please refer to
+-  Documentation/DMA-API.txt. This section is just a reminder that
+-  drivers need to indicate DMA capabilities of the device and is not
+-  an authoritative source for DMA interfaces. ]
+-
+-While all drivers should explicitly indicate the DMA capability
+-(e.g. 32 or 64 bit) of the PCI bus master, devices with more than
+-32-bit bus master capability for streaming data need the driver
+-to "register" this capability by calling pci_set_dma_mask() with
+-appropriate parameters.  In general this allows more efficient DMA
+-on systems where System RAM exists above 4G _physical_ address.
+-
+-Drivers for all PCI-X and PCIe compliant devices must call
+-pci_set_dma_mask() as they are 64-bit DMA devices.
+-
+-Similarly, drivers must also "register" this capability if the device
+-can directly address "consistent memory" in System RAM above 4G physical
+-address by calling pci_set_consistent_dma_mask().
+-Again, this includes drivers for all PCI-X and PCIe compliant devices.
+-Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
+-64-bit DMA capable for payload ("streaming") data but not control
+-("consistent") data.
+-
+-
+-3.4 Setup shared control data
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
+-memory.  See Documentation/DMA-API.txt for a full description of
+-the DMA APIs. This section is just a reminder that it needs to be done
+-before enabling DMA on the device.
+-
+-
+-3.5 Initialize device registers
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Some drivers will need specific "capability" fields programmed
+-or other "vendor specific" register initialized or reset.
+-E.g. clearing pending interrupts.
+-
+-
+-3.6 Register IRQ handler
+-~~~~~~~~~~~~~~~~~~~~~~~~
+-While calling request_irq() is the last step described here,
+-this is often just another intermediate step to initialize a device.
+-This step can often be deferred until the device is opened for use.
+-
+-All interrupt handlers for IRQ lines should be registered with IRQF_SHARED
+-and use the devid to map IRQs to devices (remember that all PCI IRQ lines
+-can be shared).
+-
+-request_irq() will associate an interrupt handler and device handle
+-with an interrupt number. Historically interrupt numbers represent
+-IRQ lines which run from the PCI device to the Interrupt controller.
+-With MSI and MSI-X (more below) the interrupt number is a CPU "vector".
+-
+-request_irq() also enables the interrupt. Make sure the device is
+-quiesced and does not have any interrupts pending before registering
+-the interrupt handler.
+-
+-MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts"
+-which deliver interrupts to the CPU via a DMA write to a Local APIC.
+-The fundamental difference between MSI and MSI-X is how multiple
+-"vectors" get allocated. MSI requires contiguous blocks of vectors
+-while MSI-X can allocate several individual ones.
+-
+-MSI capability can be enabled by calling pci_enable_msi() or
+-pci_enable_msix() before calling request_irq(). This causes
+-the PCI support to program CPU vector data into the PCI device
+-capability registers.
+-
+-If your PCI device supports both, try to enable MSI-X first.
+-Only one can be enabled at a time.  Many architectures, chip-sets,
+-or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix
+-will fail. This is important to note since many drivers have
+-two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs.
+-They choose which handler to register with request_irq() based on the
+-return value from pci_enable_msi/msix().
+-
+-There are (at least) two really good reasons for using MSI:
+-1) MSI is an exclusive interrupt vector by definition.
+-   This means the interrupt handler doesn't have to verify
+-   its device caused the interrupt.
+-
+-2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed
+-   to be visible to the host CPU(s) when the MSI is delivered. This
+-   is important for both data coherency and avoiding stale control data.
+-   This guarantee allows the driver to omit MMIO reads to flush
+-   the DMA stream.
+-
+-See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples
+-of MSI/MSI-X usage.
+-
+-
+-
+-4. PCI device shutdown
+-~~~~~~~~~~~~~~~~~~~~~~~
+-
+-When a PCI device driver is being unloaded, most of the following
+-steps need to be performed:
+-
+-	Disable the device from generating IRQs
+-	Release the IRQ (free_irq())
+-	Stop all DMA activity
+-	Release DMA buffers (both streaming and consistent)
+-	Unregister from other subsystems (e.g. scsi or netdev)
+-	Disable device from responding to MMIO/IO Port addresses
+-	Release MMIO/IO Port resource(s)
+-
+-
+-4.1 Stop IRQs on the device
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-How to do this is chip/device specific. If it's not done, it opens
+-the possibility of a "screaming interrupt" if (and only if)
+-the IRQ is shared with another device.
+-
+-When the shared IRQ handler is "unhooked", the remaining devices
+-using the same IRQ line will still need the IRQ enabled. Thus if the
+-"unhooked" device asserts IRQ line, the system will respond assuming
+-it was one of the remaining devices asserted the IRQ line. Since none
+-of the other devices will handle the IRQ, the system will "hang" until
+-it decides the IRQ isn't going to get handled and masks the IRQ (100,000
+-iterations later). Once the shared IRQ is masked, the remaining devices
+-will stop functioning properly. Not a nice situation.
+-
+-This is another reason to use MSI or MSI-X if it's available.
+-MSI and MSI-X are defined to be exclusive interrupts and thus
+-are not susceptible to the "screaming interrupt" problem.
+-
+-
+-4.2 Release the IRQ
+-~~~~~~~~~~~~~~~~~~~
+-Once the device is quiesced (no more IRQs), one can call free_irq().
+-This function will return control once any pending IRQs are handled,
+-"unhook" the drivers IRQ handler from that IRQ, and finally release
+-the IRQ if no one else is using it.
+-
+-
+-4.3 Stop all DMA activity
+-~~~~~~~~~~~~~~~~~~~~~~~~~
+-It's extremely important to stop all DMA operations BEFORE attempting
+-to deallocate DMA control data. Failure to do so can result in memory
+-corruption, hangs, and on some chip-sets a hard crash.
+-
+-Stopping DMA after stopping the IRQs can avoid races where the
+-IRQ handler might restart DMA engines.
+-
+-While this step sounds obvious and trivial, several "mature" drivers
+-didn't get this step right in the past.
+-
+-
+-4.4 Release DMA buffers
+-~~~~~~~~~~~~~~~~~~~~~~~
+-Once DMA is stopped, clean up streaming DMA first.
+-I.e. unmap data buffers and return buffers to "upstream"
+-owners if there is one.
+-
+-Then clean up "consistent" buffers which contain the control data.
+-
+-See Documentation/DMA-API.txt for details on unmapping interfaces.
+-
+-
+-4.5 Unregister from other subsystems
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Most low level PCI device drivers support some other subsystem
+-like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your
+-driver isn't losing resources from that other subsystem.
+-If this happens, typically the symptom is an Oops (panic) when
+-the subsystem attempts to call into a driver that has been unloaded.
+-
+-
+-4.6 Disable Device from responding to MMIO/IO Port addresses
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-io_unmap() MMIO or IO Port resources and then call pci_disable_device().
+-This is the symmetric opposite of pci_enable_device().
+-Do not access device registers after calling pci_disable_device().
+-
+-
+-4.7 Release MMIO/IO Port Resource(s)
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Call pci_release_region() to mark the MMIO or IO Port range as available.
+-Failure to do so usually results in the inability to reload the driver.
+-
+-
+-
+-5. How to access PCI config space
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-You can use pci_(read|write)_config_(byte|word|dword) to access the config
+-space of a device represented by struct pci_dev *. All these functions return 0
+-when successful or an error code (PCIBIOS_...) which can be translated to a text
+-string by pcibios_strerror. Most drivers expect that accesses to valid PCI
+-devices don't fail.
+-
+-If you don't have a struct pci_dev available, you can call
+-pci_bus_(read|write)_config_(byte|word|dword) to access a given device
+-and function on that bus.
+-
+-If you access fields in the standard portion of the config header, please
+-use symbolic names of locations and bits declared in <linux/pci.h>.
+-
+-If you need to access Extended PCI Capability registers, just call
+-pci_find_capability() for the particular capability and it will find the
+-corresponding register block for you.
+-
+-
+-
+-6. Other interesting functions
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-pci_find_slot()			Find pci_dev corresponding to given bus and
+-				slot numbers.
+-pci_set_power_state()		Set PCI Power Management state (0=D0 ... 3=D3)
+-pci_find_capability()		Find specified capability in device's capability
+-				list.
+-pci_resource_start()		Returns bus start address for a given PCI region
+-pci_resource_end()		Returns bus end address for a given PCI region
+-pci_resource_len()		Returns the byte length of a PCI region
+-pci_set_drvdata()		Set private driver data pointer for a pci_dev
+-pci_get_drvdata()		Return private driver data pointer for a pci_dev
+-pci_set_mwi()			Enable Memory-Write-Invalidate transactions.
+-pci_clear_mwi()			Disable Memory-Write-Invalidate transactions.
+-
+-
+-
+-7. Miscellaneous hints
+-~~~~~~~~~~~~~~~~~~~~~~
+-
+-When displaying PCI device names to the user (for example when a driver wants
+-to tell the user what card has it found), please use pci_name(pci_dev).
+-
+-Always refer to the PCI devices by a pointer to the pci_dev structure.
+-All PCI layer functions use this identification and it's the only
+-reasonable one. Don't use bus/slot/function numbers except for very
+-special purposes -- on systems with multiple primary buses their semantics
+-can be pretty complex.
+-
+-Don't try to turn on Fast Back to Back writes in your driver.  All devices
+-on the bus need to be capable of doing it, so this is something which needs
+-to be handled by platform and generic code, not individual drivers.
+-
+-
+-
+-8. Vendor and device identifications
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-One is not not required to add new device ids to include/linux/pci_ids.h.
+-Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
+-
+-PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
+-hex numbers (vendor controlled) and normally used only in a single
+-location, the pci_device_id table.
+-
+-Please DO submit new vendor/device ids to pciids.sourceforge.net project.
+-
+-
+-
+-9. Obsolete functions
+-~~~~~~~~~~~~~~~~~~~~~
+-
+-There are several functions which you might come across when trying to
+-port an old driver to the new PCI interface.  They are no longer present
+-in the kernel as they aren't compatible with hotplug or PCI domains or
+-having sane locking.
+-
+-pci_find_device()	Superseded by pci_get_device()
+-pci_find_subsys()	Superseded by pci_get_subsys()
+-pci_find_slot()		Superseded by pci_get_slot()
+-
+-
+-The alternative is the traditional PCI device driver that walks PCI
+-device lists. This is still possible but discouraged.
+-
+-
+-
+-10. MMIO Space and "Write Posting"
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-Converting a driver from using I/O Port space to using MMIO space
+-often requires some additional changes. Specifically, "write posting"
+-needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2)
+-already do this. I/O Port space guarantees write transactions reach the PCI
+-device before the CPU can continue. Writes to MMIO space allow the CPU
+-to continue before the transaction reaches the PCI device. HW weenies
+-call this "Write Posting" because the write completion is "posted" to
+-the CPU before the transaction has reached its destination.
+-
+-Thus, timing sensitive code should add readl() where the CPU is
+-expected to wait before doing other work.  The classic "bit banging"
+-sequence works fine for I/O Port space:
+-
+-       for (i = 8; --i; val >>= 1) {
+-               outb(val & 1, ioport_reg);      /* write bit */
+-               udelay(10);
+-       }
+-
+-The same sequence for MMIO space should be:
+-
+-       for (i = 8; --i; val >>= 1) {
+-               writeb(val & 1, mmio_reg);      /* write bit */
+-               readb(safe_mmio_reg);           /* flush posted write */
+-               udelay(10);
+-       }
+-
+-It is important that "safe_mmio_reg" not have any side effects that
+-interferes with the correct operation of the device.
+-
+-Another case to watch out for is when resetting a PCI device. Use PCI
+-Configuration space reads to flush the writel(). This will gracefully
+-handle the PCI master abort on all platforms if the PCI device is
+-expected to not respond to a readl().  Most x86 platforms will allow
+-MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage
+-(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").
+-
+diff --git a/Documentation/pcieaer-howto.txt b/Documentation/pcieaer-howto.txt
+deleted file mode 100644
+index d5da861..0000000
+--- a/Documentation/pcieaer-howto.txt
++++ /dev/null
+@@ -1,253 +0,0 @@
+-   The PCI Express Advanced Error Reporting Driver Guide HOWTO
+-		T. Long Nguyen	<tom.l.nguyen at intel.com>
+-		Yanmin Zhang	<yanmin.zhang at intel.com>
+-				07/29/2006
+-
+-
+-1. Overview
+-
+-1.1 About this guide
+-
+-This guide describes the basics of the PCI Express Advanced Error
+-Reporting (AER) driver and provides information on how to use it, as
+-well as how to enable the drivers of endpoint devices to conform with
+-PCI Express AER driver.
+-
+-1.2 Copyright © Intel Corporation 2006.
+-
+-1.3 What is the PCI Express AER Driver?
+-
+-PCI Express error signaling can occur on the PCI Express link itself
+-or on behalf of transactions initiated on the link. PCI Express
+-defines two error reporting paradigms: the baseline capability and
+-the Advanced Error Reporting capability. The baseline capability is
+-required of all PCI Express components providing a minimum defined
+-set of error reporting requirements. Advanced Error Reporting
+-capability is implemented with a PCI Express advanced error reporting
+-extended capability structure providing more robust error reporting.
+-
+-The PCI Express AER driver provides the infrastructure to support PCI
+-Express Advanced Error Reporting capability. The PCI Express AER
+-driver provides three basic functions:
+-
+--	Gathers the comprehensive error information if errors occurred.
+--	Reports error to the users.
+--	Performs error recovery actions.
+-
+-AER driver only attaches root ports which support PCI-Express AER
+-capability.
+-
+-
+-2. User Guide
+-
+-2.1 Include the PCI Express AER Root Driver into the Linux Kernel
+-
+-The PCI Express AER Root driver is a Root Port service driver attached
+-to the PCI Express Port Bus driver. If a user wants to use it, the driver
+-has to be compiled. Option CONFIG_PCIEAER supports this capability. It
+-depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
+-CONFIG_PCIEAER = y.
+-
+-2.2 Load PCI Express AER Root Driver
+-There is a case where a system has AER support in BIOS. Enabling the AER
+-Root driver and having AER support in BIOS may result unpredictable
+-behavior. To avoid this conflict, a successful load of the AER Root driver
+-requires ACPI _OSC support in the BIOS to allow the AER Root driver to
+-request for native control of AER. See the PCI FW 3.0 Specification for
+-details regarding OSC usage. Currently, lots of firmwares don't provide
+-_OSC support while they use PCI Express. To support such firmwares,
+-forceload, a parameter of type bool, could enable AER to continue to
+-be initiated although firmwares have no _OSC support. To enable the
+-walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
+-when booting kernel. Note that forceload=n by default.
+-
+-2.3 AER error output
+-When a PCI-E AER error is captured, an error message will be outputed to
+-console. If it's a correctable error, it is outputed as a warning.
+-Otherwise, it is printed as an error. So users could choose different
+-log level to filter out correctable error messages.
+-
+-Below shows an example.
+-+------ PCI-Express Device Error -----+
+-Error Severity          : Uncorrected (Fatal)
+-PCIE Bus Error type     : Transaction Layer
+-Unsupported Request     : First
+-Requester ID            : 0500
+-VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
+-TLB Header:
+-04000001 00200a03 05010000 00050100
+-
+-In the example, 'Requester ID' means the ID of the device who sends
+-the error message to root port. Pls. refer to pci express specs for
+-other fields.
+-
+-
+-3. Developer Guide
+-
+-To enable AER aware support requires a software driver to configure
+-the AER capability structure within its device and to provide callbacks.
+-
+-To support AER better, developers need understand how AER does work
+-firstly.
+-
+-PCI Express errors are classified into two types: correctable errors
+-and uncorrectable errors. This classification is based on the impacts
+-of those errors, which may result in degraded performance or function
+-failure.
+-
+-Correctable errors pose no impacts on the functionality of the
+-interface. The PCI Express protocol can recover without any software
+-intervention or any loss of data. These errors are detected and
+-corrected by hardware. Unlike correctable errors, uncorrectable
+-errors impact functionality of the interface. Uncorrectable errors
+-can cause a particular transaction or a particular PCI Express link
+-to be unreliable. Depending on those error conditions, uncorrectable
+-errors are further classified into non-fatal errors and fatal errors.
+-Non-fatal errors cause the particular transaction to be unreliable,
+-but the PCI Express link itself is fully functional. Fatal errors, on
+-the other hand, cause the link to be unreliable.
+-
+-When AER is enabled, a PCI Express device will automatically send an
+-error message to the PCIE root port above it when the device captures
+-an error. The Root Port, upon receiving an error reporting message,
+-internally processes and logs the error message in its PCI Express
+-capability structure. Error information being logged includes storing
+-the error reporting agent's requestor ID into the Error Source
+-Identification Registers and setting the error bits of the Root Error
+-Status Register accordingly. If AER error reporting is enabled in Root
+-Error Command Register, the Root Port generates an interrupt if an
+-error is detected.
+-
+-Note that the errors as described above are related to the PCI Express
+-hierarchy and links. These errors do not include any device specific
+-errors because device specific errors will still get sent directly to
+-the device driver.
+-
+-3.1 Configure the AER capability structure
+-
+-AER aware drivers of PCI Express component need change the device
+-control registers to enable AER. They also could change AER registers,
+-including mask and severity registers. Helper function
+-pci_enable_pcie_error_reporting could be used to enable AER. See
+-section 3.3.
+-
+-3.2. Provide callbacks
+-
+-3.2.1 callback reset_link to reset pci express link
+-
+-This callback is used to reset the pci express physical link when a
+-fatal error happens. The root port aer service driver provides a
+-default reset_link function, but different upstream ports might
+-have different specifications to reset pci express link, so all
+-upstream ports should provide their own reset_link functions.
+-
+-In struct pcie_port_service_driver, a new pointer, reset_link, is
+-added.
+-
+-pci_ers_result_t (*reset_link) (struct pci_dev *dev);
+-
+-Section 3.2.2.2 provides more detailed info on when to call
+-reset_link.
+-
+-3.2.2 PCI error-recovery callbacks
+-
+-The PCI Express AER Root driver uses error callbacks to coordinate
+-with downstream device drivers associated with a hierarchy in question
+-when performing error recovery actions.
+-
+-Data struct pci_driver has a pointer, err_handler, to point to
+-pci_error_handlers who consists of a couple of callback function
+-pointers. AER driver follows the rules defined in
+-pci-error-recovery.txt except pci express specific parts (e.g.
+-reset_link). Pls. refer to pci-error-recovery.txt for detailed
+-definitions of the callbacks.
+-
+-Below sections specify when to call the error callback functions.
+-
+-3.2.2.1 Correctable errors
+-
+-Correctable errors pose no impacts on the functionality of
+-the interface. The PCI Express protocol can recover without any
+-software intervention or any loss of data. These errors do not
+-require any recovery actions. The AER driver clears the device's
+-correctable error status register accordingly and logs these errors.
+-
+-3.2.2.2 Non-correctable (non-fatal and fatal) errors
+-
+-If an error message indicates a non-fatal error, performing link reset
+-at upstream is not required. The AER driver calls error_detected(dev,
+-pci_channel_io_normal) to all drivers associated within a hierarchy in
+-question. for example,
+-EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort.
+-If Upstream port A captures an AER error, the hierarchy consists of
+-Downstream port B and EndPoint.
+-
+-A driver may return PCI_ERS_RESULT_CAN_RECOVER,
+-PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
+-whether it can recover or the AER driver calls mmio_enabled as next.
+-
+-If an error message indicates a fatal error, kernel will broadcast
+-error_detected(dev, pci_channel_io_frozen) to all drivers within
+-a hierarchy in question. Then, performing link reset at upstream is
+-necessary. As different kinds of devices might use different approaches
+-to reset link, AER port service driver is required to provide the
+-function to reset link. Firstly, kernel looks for if the upstream
+-component has an aer driver. If it has, kernel uses the reset_link
+-callback of the aer driver. If the upstream component has no aer driver
+-and the port is downstream port, we will use the aer driver of the
+-root port who reports the AER error. As for upstream ports,
+-they should provide their own aer service drivers with reset_link
+-function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
+-reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
+-to mmio_enabled.
+-
+-3.3 helper functions
+-
+-3.3.1 int pci_find_aer_capability(struct pci_dev *dev);
+-pci_find_aer_capability locates the PCI Express AER capability
+-in the device configuration space. If the device doesn't support
+-PCI-Express AER, the function returns 0.
+-
+-3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
+-pci_enable_pcie_error_reporting enables the device to send error
+-messages to root port when an error is detected. Note that devices
+-don't enable the error reporting by default, so device drivers need
+-call this function to enable it.
+-
+-3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
+-pci_disable_pcie_error_reporting disables the device to send error
+-messages to root port when an error is detected.
+-
+-3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+-pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
+-error status register.
+-
+-3.4 Frequent Asked Questions
+-
+-Q: What happens if a PCI Express device driver does not provide an
+-error recovery handler (pci_driver->err_handler is equal to NULL)?
+-
+-A: The devices attached with the driver won't be recovered. If the
+-error is fatal, kernel will print out warning messages. Please refer
+-to section 3 for more information.
+-
+-Q: What happens if an upstream port service driver does not provide
+-callback reset_link?
+-
+-A: Fatal error recovery will fail if the errors are reported by the
+-upstream ports who are attached by the service driver.
+-
+-Q: How does this infrastructure deal with driver that is not PCI
+-Express aware?
+-
+-A: This infrastructure calls the error callback functions of the
+-driver when an error happens. But if the driver is not aware of
+-PCI Express, the device might not report its own errors to root
+-port.
+-
+-Q: What modifications will that driver need to make it compatible
+-with the PCI Express AER Root driver?
+-
+-A: It could call the helper functions to enable AER in devices and
+-cleanup uncorrectable status register. Pls. refer to section 3.3.
+-
+diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
+index 461e4f1..421e7d0 100644
+--- a/Documentation/power/devices.txt
++++ b/Documentation/power/devices.txt
+@@ -196,6 +196,11 @@ its parent; and can't be removed or suspended after that parent.
+ 
+ The policy is that the device tree should match hardware bus topology.
+ (Or at least the control bus, for devices which use multiple busses.)
++In particular, this means that a device registration may fail if the parent of
++the device is suspending (ie. has been chosen by the PM core as the next
++device to suspend) or has already suspended, as well as after all of the other
++devices have been suspended.  Device drivers must be prepared to cope with such
++situations.
+ 
+ 
+ Suspending Devices
+diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
+index 7b4e8a7..cf89e8c 100644
+--- a/Documentation/powerpc/booting-without-of.txt
++++ b/Documentation/powerpc/booting-without-of.txt
+@@ -59,12 +59,39 @@ Table of Contents
+       p) Freescale Synchronous Serial Interface
+ 	  q) USB EHCI controllers
+ 
+-  VII - Specifying interrupt information for devices
++  VII - Marvell Discovery mv64[345]6x System Controller chips
++    1) The /system-controller node
++    2) Child nodes of /system-controller
++      a) Marvell Discovery MDIO bus
++      b) Marvell Discovery ethernet controller
++      c) Marvell Discovery PHY nodes
++      d) Marvell Discovery SDMA nodes
++      e) Marvell Discovery BRG nodes
++      f) Marvell Discovery CUNIT nodes
++      g) Marvell Discovery MPSCROUTING nodes
++      h) Marvell Discovery MPSCINTR nodes
++      i) Marvell Discovery MPSC nodes
++      j) Marvell Discovery Watch Dog Timer nodes
++      k) Marvell Discovery I2C nodes
++      l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
++      m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
++      n) Marvell Discovery GPP (General Purpose Pins) nodes
++      o) Marvell Discovery PCI host bridge node
++      p) Marvell Discovery CPU Error nodes
++      q) Marvell Discovery SRAM Controller nodes
++      r) Marvell Discovery PCI Error Handler nodes
++      s) Marvell Discovery Memory Controller nodes
++
++  VIII - Specifying interrupt information for devices
+     1) interrupts property
+     2) interrupt-parent property
+     3) OpenPIC Interrupt Controllers
+     4) ISA Interrupt Controllers
+ 
++  VIII - Specifying GPIO information for devices
++    1) gpios property
++    2) gpio-controller nodes
++
+   Appendix A - Sample SOC node for MPC8540
+ 
+ 
+@@ -1269,10 +1296,6 @@ platforms are moved over to use the flattened-device-tree model.
+ 
+   Recommended properties:
+ 
+-    - linux,network-index : This is the intended "index" of this
+-      network device.  This is used by the bootwrapper to interpret
+-      MAC addresses passed by the firmware when no information other
+-      than indices is available to associate an address with a device.
+     - phy-connection-type : a string naming the controller/PHY interface type,
+       i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii",
+       "tbi", or "rtbi".  This property is only really needed if the connection
+@@ -1622,8 +1645,7 @@ platforms are moved over to use the flattened-device-tree model.
+    - device_type : should be "network", "hldc", "uart", "transparent"
+      "bisync", "atm", or "serial".
+    - compatible : could be "ucc_geth" or "fsl_atm" and so on.
+-   - model : should be "UCC".
+-   - device-id : the ucc number(1-8), corresponding to UCCx in UM.
++   - cell-index : the ucc number(1-8), corresponding to UCCx in UM.
+    - reg : Offset and length of the register set for the device
+    - interrupts : <a b> where a is the interrupt number and b is a
+      field that represents an encoding of the sense and level
+@@ -1667,10 +1689,6 @@ platforms are moved over to use the flattened-device-tree model.
+    - phy-handle : The phandle for the PHY connected to this controller.
+ 
+    Recommended properties:
+-   - linux,network-index : This is the intended "index" of this
+-     network device.  This is used by the bootwrapper to interpret
+-     MAC addresses passed by the firmware when no information other
+-     than indices is available to associate an address with a device.
+    - phy-connection-type : a string naming the controller/PHY interface type,
+      i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id" (Internal
+      Delay), "rgmii-txid" (delay on TX only), "rgmii-rxid" (delay on RX only),
+@@ -1680,8 +1698,7 @@ platforms are moved over to use the flattened-device-tree model.
+ 	ucc at 2000 {
+ 		device_type = "network";
+ 		compatible = "ucc_geth";
+-		model = "UCC";
+-		device-id = <1>;
++		cell-index = <1>;
+ 		reg = <2000 200>;
+ 		interrupts = <a0 0>;
+ 		interrupt-parent = <700>;
+@@ -1995,7 +2012,6 @@ platforms are moved over to use the flattened-device-tree model.
+ 		interrupts = <20 8>;
+ 		interrupt-parent = <&PIC>;
+ 		phy-handle = <&PHY0>;
+-		linux,network-index = <0>;
+ 		fsl,cpm-command = <12000300>;
+ 	};
+ 
+@@ -2217,12 +2233,6 @@ platforms are moved over to use the flattened-device-tree model.
+ 			  EMAC, that is the content of the current (bogus) "phy-port"
+ 			  property.
+ 
+-    Recommended properties:
+-    - linux,network-index : This is the intended "index" of this
+-      network device.  This is used by the bootwrapper to interpret
+-      MAC addresses passed by the firmware when no information other
+-      than indices is available to associate an address with a device.
+-
+     Optional properties:
+     - phy-address       : 1 cell, optional, MDIO address of the PHY. If absent,
+ 			  a search is performed.
+@@ -2246,7 +2256,6 @@ platforms are moved over to use the flattened-device-tree model.
+     Example:
+ 
+ 	EMAC0: ethernet at 40000800 {
+-		linux,network-index = <0>;
+ 		device_type = "network";
+ 		compatible = "ibm,emac-440gp", "ibm,emac";
+ 		interrupt-parent = <&UIC1>;
+@@ -2592,6 +2601,17 @@ platforms are moved over to use the flattened-device-tree model.
+                       differ between different families.  May be
+                       'virtex2p', 'virtex4', or 'virtex5'.
+ 
++      vi) Xilinx Uart 16550
++
++      Xilinx UART 16550 devices are very similar to the NS16550 but with
++      different register spacing and an offset from the base address.
++
++      Requred properties:
++       - clock-frequency : Frequency of the clock input
++       - reg-offset : A value of 3 is required
++       - reg-shift : A value of 2 is required
++
++
+     p) Freescale Synchronous Serial Interface
+ 
+        The SSI is a serial device that communicates with audio codecs.  It can
+@@ -2817,9 +2837,528 @@ platforms are moved over to use the flattened-device-tree model.
+ 	   };
+ 
+ 
+-   More devices will be defined as this spec matures.
++VII - Marvell Discovery mv64[345]6x System Controller chips
++===========================================================
++
++The Marvell mv64[345]60 series of system controller chips contain
++many of the peripherals needed to implement a complete computer
++system.  In this section, we define device tree nodes to describe
++the system controller chip itself and each of the peripherals
++which it contains.  Compatible string values for each node are
++prefixed with the string "marvell,", for Marvell Technology Group Ltd.
++
++1) The /system-controller node
++
++  This node is used to represent the system-controller and must be
++  present when the system uses a system contller chip. The top-level
++  system-controller node contains information that is global to all
++  devices within the system controller chip. The node name begins
++  with "system-controller" followed by the unit address, which is
++  the base address of the memory-mapped register set for the system
++  controller chip.
++
++  Required properties:
++
++    - ranges : Describes the translation of system controller addresses
++      for memory mapped registers.
++    - clock-frequency: Contains the main clock frequency for the system
++      controller chip.
++    - reg : This property defines the address and size of the
++      memory-mapped registers contained within the system controller
++      chip.  The address specified in the "reg" property should match
++      the unit address of the system-controller node.
++    - #address-cells : Address representation for system controller
++      devices.  This field represents the number of cells needed to
++      represent the address of the memory-mapped registers of devices
++      within the system controller chip.
++    - #size-cells : Size representation for for the memory-mapped
++      registers within the system controller chip.
++    - #interrupt-cells : Defines the width of cells used to represent
++      interrupts.
++
++  Optional properties:
++
++    - model : The specific model of the system controller chip.  Such
++      as, "mv64360", "mv64460", or "mv64560".
++    - compatible : A string identifying the compatibility identifiers
++      of the system controller chip.
++
++  The system-controller node contains child nodes for each system
++  controller device that the platform uses.  Nodes should not be created
++  for devices which exist on the system controller chip but are not used
++
++  Example Marvell Discovery mv64360 system-controller node:
++
++    system-controller at f1000000 { /* Marvell Discovery mv64360 */
++	    #address-cells = <1>;
++	    #size-cells = <1>;
++	    model = "mv64360";                      /* Default */
++	    compatible = "marvell,mv64360";
++	    clock-frequency = <133333333>;
++	    reg = <0xf1000000 0x10000>;
++	    virtual-reg = <0xf1000000>;
++	    ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
++		    0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
++		    0xa0000000 0xa0000000 0x4000000 /* User FLASH */
++		    0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
++		    0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
++
++	    [ child node definitions... ]
++    }
++
++2) Child nodes of /system-controller
++
++   a) Marvell Discovery MDIO bus
++
++   The MDIO is a bus to which the PHY devices are connected.  For each
++   device that exists on this bus, a child node should be created.  See
++   the definition of the PHY node below for an example of how to define
++   a PHY.
++
++   Required properties:
++     - #address-cells : Should be <1>
++     - #size-cells : Should be <0>
++     - device_type : Should be "mdio"
++     - compatible : Should be "marvell,mv64360-mdio"
++
++   Example:
++
++     mdio {
++	     #address-cells = <1>;
++	     #size-cells = <0>;
++	     device_type = "mdio";
++	     compatible = "marvell,mv64360-mdio";
++
++	     ethernet-phy at 0 {
++		     ......
++	     };
++     };
++
++
++   b) Marvell Discovery ethernet controller
++
++   The Discover ethernet controller is described with two levels
++   of nodes.  The first level describes an ethernet silicon block
++   and the second level describes up to 3 ethernet nodes within
++   that block.  The reason for the multiple levels is that the
++   registers for the node are interleaved within a single set
++   of registers.  The "ethernet-block" level describes the
++   shared register set, and the "ethernet" nodes describe ethernet
++   port-specific properties.
++
++   Ethernet block node
++
++   Required properties:
++     - #address-cells : <1>
++     - #size-cells : <0>
++     - compatible : "marvell,mv64360-eth-block"
++     - reg : Offset and length of the register set for this block
++
++   Example Discovery Ethernet block node:
++     ethernet-block at 2000 {
++	     #address-cells = <1>;
++	     #size-cells = <0>;
++	     compatible = "marvell,mv64360-eth-block";
++	     reg = <0x2000 0x2000>;
++	     ethernet at 0 {
++		     .......
++	     };
++     };
++
++   Ethernet port node
++
++   Required properties:
++     - device_type : Should be "network".
++     - compatible : Should be "marvell,mv64360-eth".
++     - reg : Should be <0>, <1>, or <2>, according to which registers
++       within the silicon block the device uses.
++     - interrupts : <a> where a is the interrupt number for the port.
++     - interrupt-parent : the phandle for the interrupt controller
++       that services interrupts for this device.
++     - phy : the phandle for the PHY connected to this ethernet
++       controller.
++     - local-mac-address : 6 bytes, MAC address
++
++   Example Discovery Ethernet port node:
++     ethernet at 0 {
++	     device_type = "network";
++	     compatible = "marvell,mv64360-eth";
++	     reg = <0>;
++	     interrupts = <32>;
++	     interrupt-parent = <&PIC>;
++	     phy = <&PHY0>;
++	     local-mac-address = [ 00 00 00 00 00 00 ];
++     };
++
++
++
++   c) Marvell Discovery PHY nodes
++
++   Required properties:
++     - device_type : Should be "ethernet-phy"
++     - interrupts : <a> where a is the interrupt number for this phy.
++     - interrupt-parent : the phandle for the interrupt controller that
++       services interrupts for this device.
++     - reg : The ID number for the phy, usually a small integer
++
++   Example Discovery PHY node:
++     ethernet-phy at 1 {
++	     device_type = "ethernet-phy";
++	     compatible = "broadcom,bcm5421";
++	     interrupts = <76>;      /* GPP 12 */
++	     interrupt-parent = <&PIC>;
++	     reg = <1>;
++     };
++
++
++   d) Marvell Discovery SDMA nodes
++
++   Represent DMA hardware associated with the MPSC (multiprotocol
++   serial controllers).
++
++   Required properties:
++     - compatible : "marvell,mv64360-sdma"
++     - reg : Offset and length of the register set for this device
++     - interrupts : <a> where a is the interrupt number for the DMA
++       device.
++     - interrupt-parent : the phandle for the interrupt controller
++       that services interrupts for this device.
++
++   Example Discovery SDMA node:
++     sdma at 4000 {
++	     compatible = "marvell,mv64360-sdma";
++	     reg = <0x4000 0xc18>;
++	     virtual-reg = <0xf1004000>;
++	     interrupts = <36>;
++	     interrupt-parent = <&PIC>;
++     };
++
++
++   e) Marvell Discovery BRG nodes
++
++   Represent baud rate generator hardware associated with the MPSC
++   (multiprotocol serial controllers).
++
++   Required properties:
++     - compatible : "marvell,mv64360-brg"
++     - reg : Offset and length of the register set for this device
++     - clock-src : A value from 0 to 15 which selects the clock
++       source for the baud rate generator.  This value corresponds
++       to the CLKS value in the BRGx configuration register.  See
++       the mv64x60 User's Manual.
++     - clock-frequence : The frequency (in Hz) of the baud rate
++       generator's input clock.
++     - current-speed : The current speed setting (presumably by
++       firmware) of the baud rate generator.
++
++   Example Discovery BRG node:
++     brg at b200 {
++	     compatible = "marvell,mv64360-brg";
++	     reg = <0xb200 0x8>;
++	     clock-src = <8>;
++	     clock-frequency = <133333333>;
++	     current-speed = <9600>;
++     };
++
++
++   f) Marvell Discovery CUNIT nodes
++
++   Represent the Serial Communications Unit device hardware.
++
++   Required properties:
++     - reg : Offset and length of the register set for this device
++
++   Example Discovery CUNIT node:
++     cunit at f200 {
++	     reg = <0xf200 0x200>;
++     };
++
++
++   g) Marvell Discovery MPSCROUTING nodes
++
++   Represent the Discovery's MPSC routing hardware
++
++   Required properties:
++     - reg : Offset and length of the register set for this device
++
++   Example Discovery CUNIT node:
++     mpscrouting at b500 {
++	     reg = <0xb400 0xc>;
++     };
++
++
++   h) Marvell Discovery MPSCINTR nodes
+ 
+-VII - Specifying interrupt information for devices
++   Represent the Discovery's MPSC DMA interrupt hardware registers
++   (SDMA cause and mask registers).
++
++   Required properties:
++     - reg : Offset and length of the register set for this device
++
++   Example Discovery MPSCINTR node:
++     mpsintr at b800 {
++	     reg = <0xb800 0x100>;
++     };
++
++
++   i) Marvell Discovery MPSC nodes
++
++   Represent the Discovery's MPSC (Multiprotocol Serial Controller)
++   serial port.
++
++   Required properties:
++     - device_type : "serial"
++     - compatible : "marvell,mv64360-mpsc"
++     - reg : Offset and length of the register set for this device
++     - sdma : the phandle for the SDMA node used by this port
++     - brg : the phandle for the BRG node used by this port
++     - cunit : the phandle for the CUNIT node used by this port
++     - mpscrouting : the phandle for the MPSCROUTING node used by this port
++     - mpscintr : the phandle for the MPSCINTR node used by this port
++     - cell-index : the hardware index of this cell in the MPSC core
++     - max_idle : value needed for MPSC CHR3 (Maximum Frame Length)
++       register
++     - interrupts : <a> where a is the interrupt number for the MPSC.
++     - interrupt-parent : the phandle for the interrupt controller
++       that services interrupts for this device.
++
++   Example Discovery MPSCINTR node:
++     mpsc at 8000 {
++	     device_type = "serial";
++	     compatible = "marvell,mv64360-mpsc";
++	     reg = <0x8000 0x38>;
++	     virtual-reg = <0xf1008000>;
++	     sdma = <&SDMA0>;
++	     brg = <&BRG0>;
++	     cunit = <&CUNIT>;
++	     mpscrouting = <&MPSCROUTING>;
++	     mpscintr = <&MPSCINTR>;
++	     cell-index = <0>;
++	     max_idle = <40>;
++	     interrupts = <40>;
++	     interrupt-parent = <&PIC>;
++     };
++
++
++   j) Marvell Discovery Watch Dog Timer nodes
++
++   Represent the Discovery's watchdog timer hardware
++
++   Required properties:
++     - compatible : "marvell,mv64360-wdt"
++     - reg : Offset and length of the register set for this device
++
++   Example Discovery Watch Dog Timer node:
++     wdt at b410 {
++	     compatible = "marvell,mv64360-wdt";
++	     reg = <0xb410 0x8>;
++     };
++
++
++   k) Marvell Discovery I2C nodes
++
++   Represent the Discovery's I2C hardware
++
++   Required properties:
++     - device_type : "i2c"
++     - compatible : "marvell,mv64360-i2c"
++     - reg : Offset and length of the register set for this device
++     - interrupts : <a> where a is the interrupt number for the I2C.
++     - interrupt-parent : the phandle for the interrupt controller
++       that services interrupts for this device.
++
++   Example Discovery I2C node:
++	     compatible = "marvell,mv64360-i2c";
++	     reg = <0xc000 0x20>;
++	     virtual-reg = <0xf100c000>;
++	     interrupts = <37>;
++	     interrupt-parent = <&PIC>;
++     };
++
++
++   l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
++
++   Represent the Discovery's PIC hardware
++
++   Required properties:
++     - #interrupt-cells : <1>
++     - #address-cells : <0>
++     - compatible : "marvell,mv64360-pic"
++     - reg : Offset and length of the register set for this device
++     - interrupt-controller
++
++   Example Discovery PIC node:
++     pic {
++	     #interrupt-cells = <1>;
++	     #address-cells = <0>;
++	     compatible = "marvell,mv64360-pic";
++	     reg = <0x0 0x88>;
++	     interrupt-controller;
++     };
++
++
++   m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
++
++   Represent the Discovery's MPP hardware
++
++   Required properties:
++     - compatible : "marvell,mv64360-mpp"
++     - reg : Offset and length of the register set for this device
++
++   Example Discovery MPP node:
++     mpp at f000 {
++	     compatible = "marvell,mv64360-mpp";
++	     reg = <0xf000 0x10>;
++     };
++
++
++   n) Marvell Discovery GPP (General Purpose Pins) nodes
++
++   Represent the Discovery's GPP hardware
++
++   Required properties:
++     - compatible : "marvell,mv64360-gpp"
++     - reg : Offset and length of the register set for this device
++
++   Example Discovery GPP node:
++     gpp at f000 {
++	     compatible = "marvell,mv64360-gpp";
++	     reg = <0xf100 0x20>;
++     };
++
++
++   o) Marvell Discovery PCI host bridge node
++
++   Represents the Discovery's PCI host bridge device.  The properties
++   for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE
++   1275-1994.  A typical value for the compatible property is
++   "marvell,mv64360-pci".
++
++   Example Discovery PCI host bridge node
++     pci at 80000000 {
++	     #address-cells = <3>;
++	     #size-cells = <2>;
++	     #interrupt-cells = <1>;
++	     device_type = "pci";
++	     compatible = "marvell,mv64360-pci";
++	     reg = <0xcf8 0x8>;
++	     ranges = <0x01000000 0x0        0x0
++			     0x88000000 0x0 0x01000000
++		       0x02000000 0x0 0x80000000
++			     0x80000000 0x0 0x08000000>;
++	     bus-range = <0 255>;
++	     clock-frequency = <66000000>;
++	     interrupt-parent = <&PIC>;
++	     interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
++	     interrupt-map = <
++		     /* IDSEL 0x0a */
++		     0x5000 0 0 1 &PIC 80
++		     0x5000 0 0 2 &PIC 81
++		     0x5000 0 0 3 &PIC 91
++		     0x5000 0 0 4 &PIC 93
++
++		     /* IDSEL 0x0b */
++		     0x5800 0 0 1 &PIC 91
++		     0x5800 0 0 2 &PIC 93
++		     0x5800 0 0 3 &PIC 80
++		     0x5800 0 0 4 &PIC 81
++
++		     /* IDSEL 0x0c */
++		     0x6000 0 0 1 &PIC 91
++		     0x6000 0 0 2 &PIC 93
++		     0x6000 0 0 3 &PIC 80
++		     0x6000 0 0 4 &PIC 81
++
++		     /* IDSEL 0x0d */
++		     0x6800 0 0 1 &PIC 93
++		     0x6800 0 0 2 &PIC 80
++		     0x6800 0 0 3 &PIC 81
++		     0x6800 0 0 4 &PIC 91
++	     >;
++     };
++
++
++   p) Marvell Discovery CPU Error nodes
++
++   Represent the Discovery's CPU error handler device.
++
++   Required properties:
++     - compatible : "marvell,mv64360-cpu-error"
++     - reg : Offset and length of the register set for this device
++     - interrupts : the interrupt number for this device
++     - interrupt-parent : the phandle for the interrupt controller
++       that services interrupts for this device.
++
++   Example Discovery CPU Error node:
++     cpu-error at 0070 {
++	     compatible = "marvell,mv64360-cpu-error";
++	     reg = <0x70 0x10 0x128 0x28>;
++	     interrupts = <3>;
++	     interrupt-parent = <&PIC>;
++     };
++
++
++   q) Marvell Discovery SRAM Controller nodes
++
++   Represent the Discovery's SRAM controller device.
++
++   Required properties:
++     - compatible : "marvell,mv64360-sram-ctrl"
++     - reg : Offset and length of the register set for this device
++     - interrupts : the interrupt number for this device
++     - interrupt-parent : the phandle for the interrupt controller
++       that services interrupts for this device.
++
++   Example Discovery SRAM Controller node:
++     sram-ctrl at 0380 {
++	     compatible = "marvell,mv64360-sram-ctrl";
++	     reg = <0x380 0x80>;
++	     interrupts = <13>;
++	     interrupt-parent = <&PIC>;
++     };
++
++
++   r) Marvell Discovery PCI Error Handler nodes
++
++   Represent the Discovery's PCI error handler device.
++
++   Required properties:
++     - compatible : "marvell,mv64360-pci-error"
++     - reg : Offset and length of the register set for this device
++     - interrupts : the interrupt number for this device
++     - interrupt-parent : the phandle for the interrupt controller
++       that services interrupts for this device.
++
++   Example Discovery PCI Error Handler node:
++     pci-error at 1d40 {
++	     compatible = "marvell,mv64360-pci-error";
++	     reg = <0x1d40 0x40 0xc28 0x4>;
++	     interrupts = <12>;
++	     interrupt-parent = <&PIC>;
++     };
++
++
++   s) Marvell Discovery Memory Controller nodes
++
++   Represent the Discovery's memory controller device.
++
++   Required properties:
++     - compatible : "marvell,mv64360-mem-ctrl"
++     - reg : Offset and length of the register set for this device
++     - interrupts : the interrupt number for this device
++     - interrupt-parent : the phandle for the interrupt controller
++       that services interrupts for this device.
++
++   Example Discovery Memory Controller node:
++     mem-ctrl at 1400 {
++	     compatible = "marvell,mv64360-mem-ctrl";
++	     reg = <0x1400 0x60>;
++	     interrupts = <17>;
++	     interrupt-parent = <&PIC>;
++     };
++
++
++VIII - Specifying interrupt information for devices
+ ===================================================
+ 
+ The device tree represents the busses and devices of a hardware
+@@ -2905,6 +3444,54 @@ encodings listed below:
+ 	2 =  high to low edge sensitive type enabled
+ 	3 =  low to high edge sensitive type enabled
+ 
++VIII - Specifying GPIO information for devices
++==============================================
++
++1) gpios property
++-----------------
++
++Nodes that makes use of GPIOs should define them using `gpios' property,
++format of which is: <&gpio-controller1-phandle gpio1-specifier
++		     &gpio-controller2-phandle gpio2-specifier
++		     0 /* holes are permitted, means no GPIO 3 */
++		     &gpio-controller4-phandle gpio4-specifier
++		     ...>;
++
++Note that gpio-specifier length is controller dependent.
++
++gpio-specifier may encode: bank, pin position inside the bank,
++whether pin is open-drain and whether pin is logically inverted.
++
++Example of the node using GPIOs:
++
++	node {
++		gpios = <&qe_pio_e 18 0>;
++	};
++
++In this example gpio-specifier is "18 0" and encodes GPIO pin number,
++and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
++
++2) gpio-controller nodes
++------------------------
++
++Every GPIO controller node must have #gpio-cells property defined,
++this information will be used to translate gpio-specifiers.
++
++Example of two SOC GPIO banks defined as gpio-controller nodes:
++
++	qe_pio_a: gpio-controller at 1400 {
++		#gpio-cells = <2>;
++		compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
++		reg = <0x1400 0x18>;
++		gpio-controller;
++	};
++
++	qe_pio_e: gpio-controller at 1460 {
++		#gpio-cells = <2>;
++		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
++		reg = <0x1460 0x18>;
++		gpio-controller;
++	};
+ 
+ Appendix A - Sample SOC node for MPC8540
+ ========================================
+diff --git a/Documentation/powerpc/phyp-assisted-dump.txt b/Documentation/powerpc/phyp-assisted-dump.txt
+new file mode 100644
+index 0000000..c4682b9
+--- /dev/null
++++ b/Documentation/powerpc/phyp-assisted-dump.txt
+@@ -0,0 +1,127 @@
++
++                   Hypervisor-Assisted Dump
++                   ------------------------
++                       November 2007
++
++The goal of hypervisor-assisted dump is to enable the dump of
++a crashed system, and to do so from a fully-reset system, and
++to minimize the total elapsed time until the system is back
++in production use.
++
++As compared to kdump or other strategies, hypervisor-assisted
++dump offers several strong, practical advantages:
++
++-- Unlike kdump, the system has been reset, and loaded
++   with a fresh copy of the kernel.  In particular,
++   PCI and I/O devices have been reinitialized and are
++   in a clean, consistent state.
++-- As the dump is performed, the dumped memory becomes
++   immediately available to the system for normal use.
++-- After the dump is completed, no further reboots are
++   required; the system will be fully usable, and running
++   in it's normal, production mode on it normal kernel.
++
++The above can only be accomplished by coordination with,
++and assistance from the hypervisor. The procedure is
++as follows:
++
++-- When a system crashes, the hypervisor will save
++   the low 256MB of RAM to a previously registered
++   save region. It will also save system state, system
++   registers, and hardware PTE's.
++
++-- After the low 256MB area has been saved, the
++   hypervisor will reset PCI and other hardware state.
++   It will *not* clear RAM. It will then launch the
++   bootloader, as normal.
++
++-- The freshly booted kernel will notice that there
++   is a new node (ibm,dump-kernel) in the device tree,
++   indicating that there is crash data available from
++   a previous boot. It will boot into only 256MB of RAM,
++   reserving the rest of system memory.
++
++-- Userspace tools will parse /sys/kernel/release_region
++   and read /proc/vmcore to obtain the contents of memory,
++   which holds the previous crashed kernel. The userspace
++   tools may copy this info to disk, or network, nas, san,
++   iscsi, etc. as desired.
++
++   For Example: the values in /sys/kernel/release-region
++   would look something like this (address-range pairs).
++   CPU:0x177fee000-0x10000: HPTE:0x177ffe020-0x1000: /
++   DUMP:0x177fff020-0x10000000, 0x10000000-0x16F1D370A
++
++-- As the userspace tools complete saving a portion of
++   dump, they echo an offset and size to
++   /sys/kernel/release_region to release the reserved
++   memory back to general use.
++
++   An example of this is:
++     "echo 0x40000000 0x10000000 > /sys/kernel/release_region"
++   which will release 256MB at the 1GB boundary.
++
++Please note that the hypervisor-assisted dump feature
++is only available on Power6-based systems with recent
++firmware versions.
++
++Implementation details:
++----------------------
++
++During boot, a check is made to see if firmware supports
++this feature on this particular machine. If it does, then
++we check to see if a active dump is waiting for us. If yes
++then everything but 256 MB of RAM is reserved during early
++boot. This area is released once we collect a dump from user
++land scripts that are run. If there is dump data, then
++the /sys/kernel/release_region file is created, and
++the reserved memory is held.
++
++If there is no waiting dump data, then only the highest
++256MB of the ram is reserved as a scratch area. This area
++is *not* released: this region will be kept permanently
++reserved, so that it can act as a receptacle for a copy
++of the low 256MB in the case a crash does occur. See,
++however, "open issues" below, as to whether
++such a reserved region is really needed.
++
++Currently the dump will be copied from /proc/vmcore to a
++a new file upon user intervention. The starting address
++to be read and the range for each data point in provided
++in /sys/kernel/release_region.
++
++The tools to examine the dump will be same as the ones
++used for kdump.
++
++General notes:
++--------------
++Security: please note that there are potential security issues
++with any sort of dump mechanism. In particular, plaintext
++(unencrypted) data, and possibly passwords, may be present in
++the dump data. Userspace tools must take adequate precautions to
++preserve security.
++
++Open issues/ToDo:
++------------
++ o The various code paths that tell the hypervisor that a crash
++   occurred, vs. it simply being a normal reboot, should be
++   reviewed, and possibly clarified/fixed.
++
++ o Instead of using /sys/kernel, should there be a /sys/dump
++   instead? There is a dump_subsys being created by the s390 code,
++   perhaps the pseries code should use a similar layout as well.
++
++ o Is reserving a 256MB region really required? The goal of
++   reserving a 256MB scratch area is to make sure that no
++   important crash data is clobbered when the hypervisor
++   save low mem to the scratch area. But, if one could assure
++   that nothing important is located in some 256MB area, then
++   it would not need to be reserved. Something that can be
++   improved in subsequent versions.
++
++ o Still working the kdump team to integrate this with kdump,
++   some work remains but this would not affect the current
++   patches.
++
++ o Still need to write a shell script, to copy the dump away.
++   Currently I am parsing it manually.
+diff --git a/Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c b/Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c
+new file mode 100644
+index 0000000..f8e8e95
+--- /dev/null
++++ b/Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c
+@@ -0,0 +1,96 @@
++/*
++ * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
++ *
++ * Tests if the control register is updated correctly
++ * at context switches
++ *
++ * Warning: this test will cause a very high load for a few seconds
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <signal.h>
++#include <inttypes.h>
++#include <wait.h>
++
++
++#include <sys/prctl.h>
++#include <linux/prctl.h>
++
++/* Get/set the process' ability to use the timestamp counter instruction */
++#ifndef PR_GET_TSC
++#define PR_GET_TSC 25
++#define PR_SET_TSC 26
++# define PR_TSC_ENABLE		1   /* allow the use of the timestamp counter */
++# define PR_TSC_SIGSEGV		2   /* throw a SIGSEGV instead of reading the TSC */
++#endif
++
++uint64_t rdtsc() {
++uint32_t lo, hi;
++/* We cannot use "=A", since this would use %rax on x86_64 */
++__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
++return (uint64_t)hi << 32 | lo;
++}
++
++void sigsegv_expect(int sig)
++{
++	/* */
++}
++
++void segvtask(void)
++{
++	if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
++	{
++		perror("prctl");
++		exit(0);
++	}
++	signal(SIGSEGV, sigsegv_expect);
++	alarm(10);
++	rdtsc();
++	fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
++	exit(0);
++}
++
++
++void sigsegv_fail(int sig)
++{
++	fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
++	exit(0);
++}
++
++void rdtsctask(void)
++{
++	if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
++	{
++		perror("prctl");
++		exit(0);
++	}
++	signal(SIGSEGV, sigsegv_fail);
++	alarm(10);
++	for(;;) rdtsc();
++}
++
++
++int main(int argc, char **argv)
++{
++	int n_tasks = 100, i;
++
++	fprintf(stderr, "[No further output means we're allright]\n");
++
++	for (i=0; i<n_tasks; i++)
++		if (fork() == 0)
++		{
++			if (i & 1)
++				segvtask();
++			else
++				rdtsctask();
++		}
++
++	for (i=0; i<n_tasks; i++)
++		wait(NULL);
++
++	exit(0);
++}
++
+diff --git a/Documentation/prctl/disable-tsc-on-off-stress-test.c b/Documentation/prctl/disable-tsc-on-off-stress-test.c
+new file mode 100644
+index 0000000..1fcd914
+--- /dev/null
++++ b/Documentation/prctl/disable-tsc-on-off-stress-test.c
+@@ -0,0 +1,95 @@
++/*
++ * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
++ *
++ * Tests if the control register is updated correctly
++ * when set with prctl()
++ *
++ * Warning: this test will cause a very high load for a few seconds
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <signal.h>
++#include <inttypes.h>
++#include <wait.h>
++
++
++#include <sys/prctl.h>
++#include <linux/prctl.h>
++
++/* Get/set the process' ability to use the timestamp counter instruction */
++#ifndef PR_GET_TSC
++#define PR_GET_TSC 25
++#define PR_SET_TSC 26
++# define PR_TSC_ENABLE		1   /* allow the use of the timestamp counter */
++# define PR_TSC_SIGSEGV		2   /* throw a SIGSEGV instead of reading the TSC */
++#endif
++
++/* snippet from wikipedia :-) */
++
++uint64_t rdtsc() {
++uint32_t lo, hi;
++/* We cannot use "=A", since this would use %rax on x86_64 */
++__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
++return (uint64_t)hi << 32 | lo;
++}
++
++int should_segv = 0;
++
++void sigsegv_cb(int sig)
++{
++	if (!should_segv)
++	{
++		fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
++		exit(0);
++	}
++	if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
++	{
++		perror("prctl");
++		exit(0);
++	}
++	should_segv = 0;
++
++	rdtsc();
++}
++
++void task(void)
++{
++	signal(SIGSEGV, sigsegv_cb);
++	alarm(10);
++	for(;;)
++	{
++		rdtsc();
++		if (should_segv)
++		{
++			fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
++			exit(0);
++		}
++		if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
++		{
++			perror("prctl");
++			exit(0);
++		}
++		should_segv = 1;
++	}
++}
++
++
++int main(int argc, char **argv)
++{
++	int n_tasks = 100, i;
++
++	fprintf(stderr, "[No further output means we're allright]\n");
++
++	for (i=0; i<n_tasks; i++)
++		if (fork() == 0)
++			task();
++
++	for (i=0; i<n_tasks; i++)
++		wait(NULL);
++
++	exit(0);
++}
++
+diff --git a/Documentation/prctl/disable-tsc-test.c b/Documentation/prctl/disable-tsc-test.c
+new file mode 100644
+index 0000000..843c81e
+--- /dev/null
++++ b/Documentation/prctl/disable-tsc-test.c
+@@ -0,0 +1,94 @@
++/*
++ * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
++ *
++ * Basic test to test behaviour of PR_GET_TSC and PR_SET_TSC
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <signal.h>
++#include <inttypes.h>
++
++
++#include <sys/prctl.h>
++#include <linux/prctl.h>
++
++/* Get/set the process' ability to use the timestamp counter instruction */
++#ifndef PR_GET_TSC
++#define PR_GET_TSC 25
++#define PR_SET_TSC 26
++# define PR_TSC_ENABLE		1   /* allow the use of the timestamp counter */
++# define PR_TSC_SIGSEGV		2   /* throw a SIGSEGV instead of reading the TSC */
++#endif
++
++const char *tsc_names[] =
++{
++	[0] = "[not set]",
++	[PR_TSC_ENABLE] = "PR_TSC_ENABLE",
++	[PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV",
++};
++
++uint64_t rdtsc() {
++uint32_t lo, hi;
++/* We cannot use "=A", since this would use %rax on x86_64 */
++__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
++return (uint64_t)hi << 32 | lo;
++}
++
++void sigsegv_cb(int sig)
++{
++	int tsc_val = 0;
++
++	printf("[ SIG_SEGV ]\n");
++	printf("prctl(PR_GET_TSC, &tsc_val); ");
++	fflush(stdout);
++
++	if ( prctl(PR_GET_TSC, &tsc_val) == -1)
++		perror("prctl");
++
++	printf("tsc_val == %s\n", tsc_names[tsc_val]);
++	printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
++	fflush(stdout);
++	if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
++		perror("prctl");
++
++	printf("rdtsc() == ");
++}
++
++int main(int argc, char **argv)
++{
++	int tsc_val = 0;
++
++	signal(SIGSEGV, sigsegv_cb);
++
++	printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
++	printf("prctl(PR_GET_TSC, &tsc_val); ");
++	fflush(stdout);
++
++	if ( prctl(PR_GET_TSC, &tsc_val) == -1)
++		perror("prctl");
++
++	printf("tsc_val == %s\n", tsc_names[tsc_val]);
++	printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
++	printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
++	fflush(stdout);
++
++	if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
++		perror("prctl");
++
++	printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
++	printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV)\n");
++	fflush(stdout);
++
++	if ( prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1)
++		perror("prctl");
++
++	printf("rdtsc() == ");
++	fflush(stdout);
++	printf("%llu\n", (unsigned long long)rdtsc());
++	fflush(stdout);
++
++	exit(EXIT_SUCCESS);
++}
++
+diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
+index 0eb7c58..e054209 100644
+--- a/Documentation/s390/s390dbf.txt
++++ b/Documentation/s390/s390dbf.txt
+@@ -115,6 +115,27 @@ Return Value: Handle for generated debug area
+ Description:  Allocates memory for a debug log     
+               Must not be called within an interrupt handler 
+ 
++----------------------------------------------------------------------------
++debug_info_t *debug_register_mode(char *name, int pages, int nr_areas,
++				  int buf_size, mode_t mode, uid_t uid,
++				  gid_t gid);
++
++Parameter:    name:	   Name of debug log (e.g. used for debugfs entry)
++	      pages:	   Number of pages, which will be allocated per area
++	      nr_areas:    Number of debug areas
++	      buf_size:    Size of data area in each debug entry
++	      mode:	   File mode for debugfs files. E.g. S_IRWXUGO
++	      uid:	   User ID for debugfs files. Currently only 0 is
++			   supported.
++	      gid:	   Group ID for debugfs files. Currently only 0 is
++			   supported.
++
++Return Value: Handle for generated debug area
++	      NULL if register failed
++
++Description:  Allocates memory for a debug log
++	      Must not be called within an interrupt handler
++
+ ---------------------------------------------------------------------------
+ void debug_unregister (debug_info_t * id);
+ 
+diff --git a/Documentation/scheduler/sched-rt-group.txt b/Documentation/scheduler/sched-rt-group.txt
+index 1c6332f..14f901f 100644
+--- a/Documentation/scheduler/sched-rt-group.txt
++++ b/Documentation/scheduler/sched-rt-group.txt
+@@ -1,59 +1,177 @@
++				Real-Time group scheduling
++				--------------------------
+ 
++CONTENTS
++========
+ 
+-Real-Time group scheduling.
++1. Overview
++  1.1 The problem
++  1.2 The solution
++2. The interface
++  2.1 System-wide settings
++  2.2 Default behaviour
++  2.3 Basis for grouping tasks
++3. Future plans
+ 
+-The problem space:
+ 
+-In order to schedule multiple groups of realtime tasks each group must
+-be assigned a fixed portion of the CPU time available. Without a minimum
+-guarantee a realtime group can obviously fall short. A fuzzy upper limit
+-is of no use since it cannot be relied upon. Which leaves us with just
+-the single fixed portion.
++1. Overview
++===========
+ 
+-CPU time is divided by means of specifying how much time can be spent
+-running in a given period. Say a frame fixed realtime renderer must
+-deliver 25 frames a second, which yields a period of 0.04s. Now say
+-it will also have to play some music and respond to input, leaving it
+-with around 80% for the graphics. We can then give this group a runtime
+-of 0.8 * 0.04s = 0.032s.
+ 
+-This way the graphics group will have a 0.04s period with a 0.032s runtime
+-limit.
++1.1 The problem
++---------------
+ 
+-Now if the audio thread needs to refill the DMA buffer every 0.005s, but
+-needs only about 3% CPU time to do so, it can do with a 0.03 * 0.005s
+-= 0.00015s.
++Realtime scheduling is all about determinism, a group has to be able to rely on
++the amount of bandwidth (eg. CPU time) being constant. In order to schedule
++multiple groups of realtime tasks, each group must be assigned a fixed portion
++of the CPU time available.  Without a minimum guarantee a realtime group can
++obviously fall short. A fuzzy upper limit is of no use since it cannot be
++relied upon. Which leaves us with just the single fixed portion.
+ 
++1.2 The solution
++----------------
+ 
+-The Interface:
++CPU time is divided by means of specifying how much time can be spent running
++in a given period. We allocate this "run time" for each realtime group which
++the other realtime groups will not be permitted to use.
+ 
+-system wide:
++Any time not allocated to a realtime group will be used to run normal priority
++tasks (SCHED_OTHER). Any allocated run time not used will also be picked up by
++SCHED_OTHER.
+ 
+-/proc/sys/kernel/sched_rt_period_ms
+-/proc/sys/kernel/sched_rt_runtime_us
++Let's consider an example: a frame fixed realtime renderer must deliver 25
++frames a second, which yields a period of 0.04s per frame. Now say it will also
++have to play some music and respond to input, leaving it with around 80% CPU
++time dedicated for the graphics. We can then give this group a run time of 0.8
++* 0.04s = 0.032s.
+ 
+-CONFIG_FAIR_USER_SCHED
++This way the graphics group will have a 0.04s period with a 0.032s run time
++limit. Now if the audio thread needs to refill the DMA buffer every 0.005s, but
++needs only about 3% CPU time to do so, it can do with a 0.03 * 0.005s =
++0.00015s. So this group can be scheduled with a period of 0.005s and a run time
++of 0.00015s.
+ 
+-/sys/kernel/uids/<uid>/cpu_rt_runtime_us
++The remaining CPU time will be used for user input and other tass. Because
++realtime tasks have explicitly allocated the CPU time they need to perform
++their tasks, buffer underruns in the graphocs or audio can be eliminated.
+ 
+-or
++NOTE: the above example is not fully implemented as of yet (2.6.25). We still
++lack an EDF scheduler to make non-uniform periods usable.
+ 
+-CONFIG_FAIR_CGROUP_SCHED
+ 
+-/cgroup/<cgroup>/cpu.rt_runtime_us
++2. The Interface
++================
+ 
+-[ time is specified in us because the interface is s32; this gives an
+-  operating range of ~35m to 1us ]
+ 
+-The period takes values in [ 1, INT_MAX ], runtime in [ -1, INT_MAX - 1 ].
++2.1 System wide settings
++------------------------
+ 
+-A runtime of -1 specifies runtime == period, ie. no limit.
++The system wide settings are configured under the /proc virtual file system:
+ 
+-New groups get the period from /proc/sys/kernel/sched_rt_period_us and
+-a runtime of 0.
++/proc/sys/kernel/sched_rt_period_us:
++  The scheduling period that is equivalent to 100% CPU bandwidth
+ 
+-Settings are constrained to:
++/proc/sys/kernel/sched_rt_runtime_us:
++  A global limit on how much time realtime scheduling may use.  Even without
++  CONFIG_RT_GROUP_SCHED enabled, this will limit time reserved to realtime
++  processes. With CONFIG_RT_GROUP_SCHED it signifies the total bandwidth
++  available to all realtime groups.
++
++  * Time is specified in us because the interface is s32. This gives an
++    operating range from 1us to about 35 minutes.
++  * sched_rt_period_us takes values from 1 to INT_MAX.
++  * sched_rt_runtime_us takes values from -1 to (INT_MAX - 1).
++  * A run time of -1 specifies runtime == period, ie. no limit.
++
++
++2.2 Default behaviour
++---------------------
++
++The default values for sched_rt_period_us (1000000 or 1s) and
++sched_rt_runtime_us (950000 or 0.95s).  This gives 0.05s to be used by
++SCHED_OTHER (non-RT tasks). These defaults were chosen so that a run-away
++realtime tasks will not lock up the machine but leave a little time to recover
++it.  By setting runtime to -1 you'd get the old behaviour back.
++
++By default all bandwidth is assigned to the root group and new groups get the
++period from /proc/sys/kernel/sched_rt_period_us and a run time of 0. If you
++want to assign bandwidth to another group, reduce the root group's bandwidth
++and assign some or all of the difference to another group.
++
++Realtime group scheduling means you have to assign a portion of total CPU
++bandwidth to the group before it will accept realtime tasks. Therefore you will
++not be able to run realtime tasks as any user other than root until you have
++done that, even if the user has the rights to run processes with realtime
++priority!
++
++
++2.3 Basis for grouping tasks
++----------------------------
++
++There are two compile-time settings for allocating CPU bandwidth. These are
++configured using the "Basis for grouping tasks" multiple choice menu under
++General setup > Group CPU Scheduler:
++
++a. CONFIG_USER_SCHED (aka "Basis for grouping tasks" =  "user id")
++
++This lets you use the virtual files under
++"/sys/kernel/uids/<uid>/cpu_rt_runtime_us" to control he CPU time reserved for
++each user .
++
++The other option is:
++
++.o CONFIG_CGROUP_SCHED (aka "Basis for grouping tasks" = "Control groups")
++
++This uses the /cgroup virtual file system and "/cgroup/<cgroup>/cpu.rt_runtime_us"
++to control the CPU time reserved for each control group instead.
++
++For more information on working with control groups, you should read
++Documentation/cgroups.txt as well.
++
++Group settings are checked against the following limits in order to keep the configuration
++schedulable:
+ 
+    \Sum_{i} runtime_{i} / global_period <= global_runtime / global_period
+ 
+-in order to keep the configuration schedulable.
++For now, this can be simplified to just the following (but see Future plans):
++
++   \Sum_{i} runtime_{i} <= global_runtime
++
++
++3. Future plans
++===============
++
++There is work in progress to make the scheduling period for each group
++("/sys/kernel/uids/<uid>/cpu_rt_period_us" or
++"/cgroup/<cgroup>/cpu.rt_period_us" respectively) configurable as well.
++
++The constraint on the period is that a subgroup must have a smaller or
++equal period to its parent. But realistically its not very useful _yet_
++as its prone to starvation without deadline scheduling.
++
++Consider two sibling groups A and B; both have 50% bandwidth, but A's
++period is twice the length of B's.
++
++* group A: period=100000us, runtime=10000us
++	- this runs for 0.01s once every 0.1s
++
++* group B: period= 50000us, runtime=10000us
++	- this runs for 0.01s twice every 0.1s (or once every 0.05 sec).
++
++This means that currently a while (1) loop in A will run for the full period of
++B and can starve B's tasks (assuming they are of lower priority) for a whole
++period.
++
++The next project will be SCHED_EDF (Earliest Deadline First scheduling) to bring
++full deadline scheduling to the linux kernel. Deadline scheduling the above
++groups and treating end of the period as a deadline will ensure that they both
++get their allocated time.
++
++Implementing SCHED_EDF might take a while to complete. Priority Inheritance is
++the biggest challenge as the current linux PI infrastructure is geared towards
++the limited static priority levels 0-139. With deadline scheduling you need to
++do deadline inheritance (since priority is inversely proportional to the
++deadline delta (deadline - now).
++
++This means the whole PI machinery will have to be reworked - and that is one of
++the most complex pieces of code we have.
+diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
+index b7be95b..4075260 100644
+--- a/Documentation/scsi/st.txt
++++ b/Documentation/scsi/st.txt
+@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
+ The driver is currently maintained by Kai Mäkisara (email
+ Kai.Makisara at kolumbus.fi)
+ 
+-Last modified: Mon Mar  7 21:14:44 2005 by kai.makisara
++Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara
+ 
+ 
+ BASICS
+@@ -133,6 +133,11 @@ the defaults set by the user. The value -1 means the default is not set. The
+ file 'dev' contains the device numbers corresponding to this device. The links
+ 'device' and 'driver' point to the SCSI device and driver entries.
+ 
++Each directory also contains the entry 'options' which shows the currently
++enabled driver and mode options. The value in the file is a bit mask where the
++bit definitions are the same as those used with MTSETDRVBUFFER in setting the
++options.
++
+ A link named 'tape' is made from the SCSI device directory to the class
+ directory corresponding to the mode 0 auto-rewind device (e.g., st0). 
+ 
+@@ -372,6 +377,11 @@ MTSETDRVBUFFER
+ 	     MT_ST_SYSV sets the SYSV semantics (mode)
+ 	     MT_ST_NOWAIT enables immediate mode (i.e., don't wait for
+ 	        the command to finish) for some commands (e.g., rewind)
++	     MT_ST_SILI enables setting the SILI bit in SCSI commands when
++		reading in variable block mode to enhance performance when
++		reading blocks shorter than the byte count; set this only
++		if you are sure that the drive supports SILI and the HBA
++		correctly returns transfer residuals
+ 	     MT_ST_DEBUGGING debugging (global; debugging must be
+ 		compiled into the driver)
+ 	MT_ST_SETBOOLEANS
+diff --git a/Documentation/smart-config.txt b/Documentation/smart-config.txt
+deleted file mode 100644
+index 8467447..0000000
+--- a/Documentation/smart-config.txt
++++ /dev/null
+@@ -1,98 +0,0 @@
+-Smart CONFIG_* Dependencies
+-1 August 1999
+-
+-Michael Chastain   <mec at shout.net>
+-Werner Almesberger <almesber at lrc.di.epfl.ch>
+-Martin von Loewis  <martin at mira.isdn.cs.tu-berlin.de>
+-
+-Here is the problem:
+-
+-    Suppose that drivers/net/foo.c has the following lines:
+-
+-	#include <linux/config.h>
+-
+-	...
+-
+-	#ifdef CONFIG_FOO_AUTOFROB
+-	    /* Code for auto-frobbing */
+-	#else
+-	    /* Manual frobbing only */
+-	#endif
+-
+-	...
+-
+-	#ifdef CONFIG_FOO_MODEL_TWO
+-	    /* Code for model two */
+-	#endif
+-
+-    Now suppose the user (the person building kernels) reconfigures the
+-    kernel to change some unrelated setting.  This will regenerate the
+-    file include/linux/autoconf.h, which will cause include/linux/config.h
+-    to be out of date, which will cause drivers/net/foo.c to be recompiled.
+-
+-    Most kernel sources, perhaps 80% of them, have at least one CONFIG_*
+-    dependency somewhere.  So changing _any_ CONFIG_* setting requires
+-    almost _all_ of the kernel to be recompiled.
+-
+-Here is the solution:
+-
+-    We've made the dependency generator, mkdep.c, smarter.  Instead of
+-    generating this dependency:
+-
+-	drivers/net/foo.c: include/linux/config.h
+-
+-    It now generates these dependencies:
+-
+-	drivers/net/foo.c: \
+-	    include/config/foo/autofrob.h \
+-	    include/config/foo/model/two.h
+-
+-    So drivers/net/foo.c depends only on the CONFIG_* lines that
+-    it actually uses.
+-
+-    A new program, split-include.c, runs at the beginning of
+-    compilation (make bzImage or make zImage).  split-include reads
+-    include/linux/autoconf.h and updates the include/config/ tree,
+-    writing one file per option.  It updates only the files for options
+-    that have changed.
+-
+-Flag Dependencies
+-
+-    Martin Von Loewis contributed another feature to this patch:
+-    'flag dependencies'.  The idea is that a .o file depends on
+-    the compilation flags used to build it.  The file foo.o has
+-    its flags stored in .flags.foo.o.
+-
+-    Suppose the user changes the foo driver from resident to modular.
+-    'make' will notice that the current foo.o was not compiled with
+-    -DMODULE and will recompile foo.c.
+-
+-    All .o files made from C source have flag dependencies.  So do .o
+-    files made with ld, and .a files made with ar.  However, .o files
+-    made from assembly source do not have flag dependencies (nobody
+-    needs this yet, but it would be good to fix).
+-
+-Per-source-file Flags
+-
+-    Flag dependencies also work with per-source-file flags.
+-    You can specify compilation flags for individual source files
+-    like this:
+-
+-	CFLAGS_foo.o = -DSPECIAL_FOO_DEFINE
+-
+-    This helps clean up drivers/net/Makefile, drivers/scsi/Makefile,
+-    and several other Makefiles.
+-
+-Credit
+-
+-    Werner Almesberger had the original idea and wrote the first
+-    version of this patch.
+-    
+-    Michael Chastain picked it up and continued development.  He is
+-    now the principal author and maintainer.  Please report any bugs
+-    to him.
+-
+-    Martin von Loewis wrote flag dependencies, with some modifications
+-    by Michael Chastain.
+-
+-    Thanks to all of the beta testers.
+diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
+index e985cf5..fd4c32a 100644
+--- a/Documentation/sound/alsa/ALSA-Configuration.txt
++++ b/Documentation/sound/alsa/ALSA-Configuration.txt
+@@ -284,6 +284,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+            control correctly. If you have problems regarding this, try
+            another ALSA compliant mixer (alsamixer works).
+ 
++  Module snd-aw2
++  --------------
++
++    Module for Audiowerk2 sound card
++
++    This module supports multiple cards.
++
+   Module snd-azt2320
+   ------------------
+ 
+@@ -818,19 +825,25 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 	  hippo_1	Hippo (Benq) with jack detection
+ 	  sony-assamd	Sony ASSAMD
+ 	  ultra		Samsung Q1 Ultra Vista model
++	  lenovo-3000	Lenovo 3000 y410
+ 	  basic		fixed pin assignment w/o SPDIF
+ 	  auto		auto-config reading BIOS (default)
+ 
+-	ALC268
++	ALC267/268
++	  quanta-il1	Quanta IL1 mini-notebook
+ 	  3stack	3-stack model
+ 	  toshiba	Toshiba A205
+ 	  acer		Acer laptops
+ 	  dell		Dell OEM laptops (Vostro 1200)
++	  zepto		Zepto laptops
+ 	  test		for testing/debugging purpose, almost all controls can
+ 			adjusted.  Appearing only when compiled with
+ 			$CONFIG_SND_DEBUG=y
+ 	  auto		auto-config reading BIOS (default)
+ 
++	ALC269
++	  basic		Basic preset
++
+ 	ALC662
+ 	  3stack-dig	3-stack (2-channel) with SPDIF
+ 	  3stack-6ch	 3-stack (6-channel)
+@@ -871,10 +884,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 	  lenovo-nb0763	Lenovo NB0763
+ 	  lenovo-ms7195-dig Lenovo MS7195
+ 	  haier-w66	Haier W66
+-	  6stack-hp	HP machines with 6stack (Nettle boards)
+ 	  3stack-hp	HP machines with 3stack (Lucknow, Samba boards)
+ 	  6stack-dell	Dell machines with 6stack (Inspiron 530)
+ 	  mitac		Mitac 8252D
++	  clevo-m720	Clevo M720 laptop series
++	  fujitsu-pi2515 Fujitsu AMILO Pi2515
+ 	  auto		auto-config reading BIOS (default)
+ 
+ 	ALC861/660
+@@ -911,6 +925,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 	  3stack	3-stack mode (default)
+ 	  6stack	6-stack mode
+ 
++	AD1884A / AD1883 / AD1984A / AD1984B
++	  desktop	3-stack desktop (default)
++	  laptop	laptop with HP jack sensing
++	  mobile	mobile devices with HP jack sensing
++	  thinkpad	Lenovo Thinkpad X300
++
+ 	AD1884
+ 	  N/A
+ 
+@@ -936,7 +956,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 	  laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100)
+ 	  ultra		2-channel with EAPD (Samsung Ultra tablet PC)
+ 
+-	AD1988
++	AD1988/AD1988B/AD1989A/AD1989B
+ 	  6stack	6-jack
+ 	  6stack-dig	ditto with SPDIF
+ 	  3stack	3-jack
+@@ -979,6 +999,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 	  dell-m26	Dell Inspiron 1501
+ 	  dell-m27	Dell Inspiron E1705/9400
+ 	  gateway	Gateway laptops with EAPD control
++	  panasonic	Panasonic CF-74
+ 
+ 	STAC9205/9254
+ 	  ref		Reference board
+@@ -1017,6 +1038,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 	  3stack	D965 3stack
+ 	  5stack	D965 5stack + SPDIF
+ 	  dell-3stack	Dell Dimension E520
++	  dell-bios	Fixes with Dell BIOS setup
++
++	STAC92HD71B*
++	  ref		Reference board
++	  dell-m4-1	Dell desktops
++	  dell-m4-2	Dell desktops
++
++	STAC92HD73*
++	  ref		Reference board
++	  dell-m6	Dell desktops
+ 
+ 	STAC9872
+ 	  vaio		Setup for VAIO FE550G/SZ110
+@@ -1590,6 +1621,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 
+     Power management is _not_ supported.
+ 
++  Module snd-pcsp
++  -----------------
++
++    Module for internal PC-Speaker.
++
++    nforce_wa	- enable NForce chipset workaround. Expect bad sound.
++
++    This module supports system beeps, some kind of PCM playback and
++    even a few mixer controls.
++
+   Module snd-pcxhr
+   ----------------
+ 
+diff --git a/Documentation/timers/highres.txt b/Documentation/timers/highres.txt
+new file mode 100644
+index 0000000..a73ecf5
+--- /dev/null
++++ b/Documentation/timers/highres.txt
+@@ -0,0 +1,249 @@
++High resolution timers and dynamic ticks design notes
++-----------------------------------------------------
++
++Further information can be found in the paper of the OLS 2006 talk "hrtimers
++and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can
++be found on the OLS website:
++http://www.linuxsymposium.org/2006/linuxsymposium_procv1.pdf
++
++The slides to this talk are available from:
++http://tglx.de/projects/hrtimers/ols2006-hrtimers.pdf
++
++The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the
++changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the
++design of the Linux time(r) system before hrtimers and other building blocks
++got merged into mainline.
++
++Note: the paper and the slides are talking about "clock event source", while we
++switched to the name "clock event devices" in meantime.
++
++The design contains the following basic building blocks:
++
++- hrtimer base infrastructure
++- timeofday and clock source management
++- clock event management
++- high resolution timer functionality
++- dynamic ticks
++
++
++hrtimer base infrastructure
++---------------------------
++
++The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
++the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See
++also figure #2 (OLS slides p. 15)
++
++The main differences to the timer wheel, which holds the armed timer_list type
++timers are:
++       - time ordered enqueueing into a rb-tree
++       - independent of ticks (the processing is based on nanoseconds)
++
++
++timeofday and clock source management
++-------------------------------------
++
++John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of
++code out of the architecture-specific areas into a generic management
++framework, as illustrated in figure #3 (OLS slides p. 18). The architecture
++specific portion is reduced to the low level hardware details of the clock
++sources, which are registered in the framework and selected on a quality based
++decision. The low level code provides hardware setup and readout routines and
++initializes data structures, which are used by the generic time keeping code to
++convert the clock ticks to nanosecond based time values. All other time keeping
++related functionality is moved into the generic code. The GTOD base patch got
++merged into the 2.6.18 kernel.
++
++Further information about the Generic Time Of Day framework is available in the
++OLS 2005 Proceedings Volume 1:
++http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf
++
++The paper "We Are Not Getting Any Younger: A New Approach to Time and
++Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan.
++
++Figure #3 (OLS slides p.18) illustrates the transformation.
++
++
++clock event management
++----------------------
++
++While clock sources provide read access to the monotonically increasing time
++value, clock event devices are used to schedule the next event
++interrupt(s). The next event is currently defined to be periodic, with its
++period defined at compile time. The setup and selection of the event device
++for various event driven functionalities is hardwired into the architecture
++dependent code. This results in duplicated code across all architectures and
++makes it extremely difficult to change the configuration of the system to use
++event interrupt devices other than those already built into the
++architecture. Another implication of the current design is that it is necessary
++to touch all the architecture-specific implementations in order to provide new
++functionality like high resolution timers or dynamic ticks.
++
++The clock events subsystem tries to address this problem by providing a generic
++solution to manage clock event devices and their usage for the various clock
++event driven kernel functionalities. The goal of the clock event subsystem is
++to minimize the clock event related architecture dependent code to the pure
++hardware related handling and to allow easy addition and utilization of new
++clock event devices. It also minimizes the duplicated code across the
++architectures as it provides generic functionality down to the interrupt
++service handler, which is almost inherently hardware dependent.
++
++Clock event devices are registered either by the architecture dependent boot
++code or at module insertion time. Each clock event device fills a data
++structure with clock-specific property parameters and callback functions. The
++clock event management decides, by using the specified property parameters, the
++set of system functions a clock event device will be used to support. This
++includes the distinction of per-CPU and per-system global event devices.
++
++System-level global event devices are used for the Linux periodic tick. Per-CPU
++event devices are used to provide local CPU functionality such as process
++accounting, profiling, and high resolution timers.
++
++The management layer assigns one or more of the following functions to a clock
++event device:
++      - system global periodic tick (jiffies update)
++      - cpu local update_process_times
++      - cpu local profiling
++      - cpu local next event interrupt (non periodic mode)
++
++The clock event device delegates the selection of those timer interrupt related
++functions completely to the management layer. The clock management layer stores
++a function pointer in the device description structure, which has to be called
++from the hardware level handler. This removes a lot of duplicated code from the
++architecture specific timer interrupt handlers and hands the control over the
++clock event devices and the assignment of timer interrupt related functionality
++to the core code.
++
++The clock event layer API is rather small. Aside from the clock event device
++registration interface it provides functions to schedule the next event
++interrupt, clock event device notification service and support for suspend and
++resume.
++
++The framework adds about 700 lines of code which results in a 2KB increase of
++the kernel binary size. The conversion of i386 removes about 100 lines of
++code. The binary size decrease is in the range of 400 byte. We believe that the
++increase of flexibility and the avoidance of duplicated code across
++architectures justifies the slight increase of the binary size.
++
++The conversion of an architecture has no functional impact, but allows to
++utilize the high resolution and dynamic tick functionalites without any change
++to the clock event device and timer interrupt code. After the conversion the
++enabling of high resolution timers and dynamic ticks is simply provided by
++adding the kernel/time/Kconfig file to the architecture specific Kconfig and
++adding the dynamic tick specific calls to the idle routine (a total of 3 lines
++added to the idle function and the Kconfig file)
++
++Figure #4 (OLS slides p.20) illustrates the transformation.
++
++
++high resolution timer functionality
++-----------------------------------
++
++During system boot it is not possible to use the high resolution timer
++functionality, while making it possible would be difficult and would serve no
++useful function. The initialization of the clock event device framework, the
++clock source framework (GTOD) and hrtimers itself has to be done and
++appropriate clock sources and clock event devices have to be registered before
++the high resolution functionality can work. Up to the point where hrtimers are
++initialized, the system works in the usual low resolution periodic mode. The
++clock source and the clock event device layers provide notification functions
++which inform hrtimers about availability of new hardware. hrtimers validates
++the usability of the registered clock sources and clock event devices before
++switching to high resolution mode. This ensures also that a kernel which is
++configured for high resolution timers can run on a system which lacks the
++necessary hardware support.
++
++The high resolution timer code does not support SMP machines which have only
++global clock event devices. The support of such hardware would involve IPI
++calls when an interrupt happens. The overhead would be much larger than the
++benefit. This is the reason why we currently disable high resolution and
++dynamic ticks on i386 SMP systems which stop the local APIC in C3 power
++state. A workaround is available as an idea, but the problem has not been
++tackled yet.
++
++The time ordered insertion of timers provides all the infrastructure to decide
++whether the event device has to be reprogrammed when a timer is added. The
++decision is made per timer base and synchronized across per-cpu timer bases in
++a support function. The design allows the system to utilize separate per-CPU
++clock event devices for the per-CPU timer bases, but currently only one
++reprogrammable clock event device per-CPU is utilized.
++
++When the timer interrupt happens, the next event interrupt handler is called
++from the clock event distribution code and moves expired timers from the
++red-black tree to a separate double linked list and invokes the softirq
++handler. An additional mode field in the hrtimer structure allows the system to
++execute callback functions directly from the next event interrupt handler. This
++is restricted to code which can safely be executed in the hard interrupt
++context. This applies, for example, to the common case of a wakeup function as
++used by nanosleep. The advantage of executing the handler in the interrupt
++context is the avoidance of up to two context switches - from the interrupted
++context to the softirq and to the task which is woken up by the expired
++timer.
++
++Once a system has switched to high resolution mode, the periodic tick is
++switched off. This disables the per system global periodic clock event device -
++e.g. the PIT on i386 SMP systems.
++
++The periodic tick functionality is provided by an per-cpu hrtimer. The callback
++function is executed in the next event interrupt context and updates jiffies
++and calls update_process_times and profiling. The implementation of the hrtimer
++based periodic tick is designed to be extended with dynamic tick functionality.
++This allows to use a single clock event device to schedule high resolution
++timer and periodic events (jiffies tick, profiling, process accounting) on UP
++systems. This has been proved to work with the PIT on i386 and the Incrementer
++on PPC.
++
++The softirq for running the hrtimer queues and executing the callbacks has been
++separated from the tick bound timer softirq to allow accurate delivery of high
++resolution timer signals which are used by itimer and POSIX interval
++timers. The execution of this softirq can still be delayed by other softirqs,
++but the overall latencies have been significantly improved by this separation.
++
++Figure #5 (OLS slides p.22) illustrates the transformation.
++
++
++dynamic ticks
++-------------
++
++Dynamic ticks are the logical consequence of the hrtimer based periodic tick
++replacement (sched_tick). The functionality of the sched_tick hrtimer is
++extended by three functions:
++
++- hrtimer_stop_sched_tick
++- hrtimer_restart_sched_tick
++- hrtimer_update_jiffies
++
++hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code
++evaluates the next scheduled timer event (from both hrtimers and the timer
++wheel) and in case that the next event is further away than the next tick it
++reprograms the sched_tick to this future event, to allow longer idle sleeps
++without worthless interruption by the periodic tick. The function is also
++called when an interrupt happens during the idle period, which does not cause a
++reschedule. The call is necessary as the interrupt handler might have armed a
++new timer whose expiry time is before the time which was identified as the
++nearest event in the previous call to hrtimer_stop_sched_tick.
++
++hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before
++it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick,
++which is kept active until the next call to hrtimer_stop_sched_tick().
++
++hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens
++in the idle period to make sure that jiffies are up to date and the interrupt
++handler has not to deal with an eventually stale jiffy value.
++
++The dynamic tick feature provides statistical values which are exported to
++userspace via /proc/stats and can be made available for enhanced power
++management control.
++
++The implementation leaves room for further development like full tickless
++systems, where the time slice is controlled by the scheduler, variable
++frequency profiling, and a complete removal of jiffies in the future.
++
++
++Aside the current initial submission of i386 support, the patchset has been
++extended to x86_64 and ARM already. Initial (work in progress) support is also
++available for MIPS and PowerPC.
++
++	  Thomas, Ingo
++
++
++
+diff --git a/Documentation/timers/hrtimers.txt b/Documentation/timers/hrtimers.txt
+new file mode 100644
+index 0000000..ce31f65
+--- /dev/null
++++ b/Documentation/timers/hrtimers.txt
+@@ -0,0 +1,178 @@
++
++hrtimers - subsystem for high-resolution kernel timers
++----------------------------------------------------
++
++This patch introduces a new subsystem for high-resolution kernel timers.
++
++One might ask the question: we already have a timer subsystem
++(kernel/timers.c), why do we need two timer subsystems? After a lot of
++back and forth trying to integrate high-resolution and high-precision
++features into the existing timer framework, and after testing various
++such high-resolution timer implementations in practice, we came to the
++conclusion that the timer wheel code is fundamentally not suitable for
++such an approach. We initially didn't believe this ('there must be a way
++to solve this'), and spent a considerable effort trying to integrate
++things into the timer wheel, but we failed. In hindsight, there are
++several reasons why such integration is hard/impossible:
++
++- the forced handling of low-resolution and high-resolution timers in
++  the same way leads to a lot of compromises, macro magic and #ifdef
++  mess. The timers.c code is very "tightly coded" around jiffies and
++  32-bitness assumptions, and has been honed and micro-optimized for a
++  relatively narrow use case (jiffies in a relatively narrow HZ range)
++  for many years - and thus even small extensions to it easily break
++  the wheel concept, leading to even worse compromises. The timer wheel
++  code is very good and tight code, there's zero problems with it in its
++  current usage - but it is simply not suitable to be extended for
++  high-res timers.
++
++- the unpredictable [O(N)] overhead of cascading leads to delays which
++  necessitate a more complex handling of high resolution timers, which
++  in turn decreases robustness. Such a design still led to rather large
++  timing inaccuracies. Cascading is a fundamental property of the timer
++  wheel concept, it cannot be 'designed out' without unevitably
++  degrading other portions of the timers.c code in an unacceptable way.
++
++- the implementation of the current posix-timer subsystem on top of
++  the timer wheel has already introduced a quite complex handling of
++  the required readjusting of absolute CLOCK_REALTIME timers at
++  settimeofday or NTP time - further underlying our experience by
++  example: that the timer wheel data structure is too rigid for high-res
++  timers.
++
++- the timer wheel code is most optimal for use cases which can be
++  identified as "timeouts". Such timeouts are usually set up to cover
++  error conditions in various I/O paths, such as networking and block
++  I/O. The vast majority of those timers never expire and are rarely
++  recascaded because the expected correct event arrives in time so they
++  can be removed from the timer wheel before any further processing of
++  them becomes necessary. Thus the users of these timeouts can accept
++  the granularity and precision tradeoffs of the timer wheel, and
++  largely expect the timer subsystem to have near-zero overhead.
++  Accurate timing for them is not a core purpose - in fact most of the
++  timeout values used are ad-hoc. For them it is at most a necessary
++  evil to guarantee the processing of actual timeout completions
++  (because most of the timeouts are deleted before completion), which
++  should thus be as cheap and unintrusive as possible.
++
++The primary users of precision timers are user-space applications that
++utilize nanosleep, posix-timers and itimer interfaces. Also, in-kernel
++users like drivers and subsystems which require precise timed events
++(e.g. multimedia) can benefit from the availability of a separate
++high-resolution timer subsystem as well.
++
++While this subsystem does not offer high-resolution clock sources just
++yet, the hrtimer subsystem can be easily extended with high-resolution
++clock capabilities, and patches for that exist and are maturing quickly.
++The increasing demand for realtime and multimedia applications along
++with other potential users for precise timers gives another reason to
++separate the "timeout" and "precise timer" subsystems.
++
++Another potential benefit is that such a separation allows even more
++special-purpose optimization of the existing timer wheel for the low
++resolution and low precision use cases - once the precision-sensitive
++APIs are separated from the timer wheel and are migrated over to
++hrtimers. E.g. we could decrease the frequency of the timeout subsystem
++from 250 Hz to 100 HZ (or even smaller).
++
++hrtimer subsystem implementation details
++----------------------------------------
++
++the basic design considerations were:
++
++- simplicity
++
++- data structure not bound to jiffies or any other granularity. All the
++  kernel logic works at 64-bit nanoseconds resolution - no compromises.
++
++- simplification of existing, timing related kernel code
++
++another basic requirement was the immediate enqueueing and ordering of
++timers at activation time. After looking at several possible solutions
++such as radix trees and hashes, we chose the red black tree as the basic
++data structure. Rbtrees are available as a library in the kernel and are
++used in various performance-critical areas of e.g. memory management and
++file systems. The rbtree is solely used for time sorted ordering, while
++a separate list is used to give the expiry code fast access to the
++queued timers, without having to walk the rbtree.
++
++(This separate list is also useful for later when we'll introduce
++high-resolution clocks, where we need separate pending and expired
++queues while keeping the time-order intact.)
++
++Time-ordered enqueueing is not purely for the purposes of
++high-resolution clocks though, it also simplifies the handling of
++absolute timers based on a low-resolution CLOCK_REALTIME. The existing
++implementation needed to keep an extra list of all armed absolute
++CLOCK_REALTIME timers along with complex locking. In case of
++settimeofday and NTP, all the timers (!) had to be dequeued, the
++time-changing code had to fix them up one by one, and all of them had to
++be enqueued again. The time-ordered enqueueing and the storage of the
++expiry time in absolute time units removes all this complex and poorly
++scaling code from the posix-timer implementation - the clock can simply
++be set without having to touch the rbtree. This also makes the handling
++of posix-timers simpler in general.
++
++The locking and per-CPU behavior of hrtimers was mostly taken from the
++existing timer wheel code, as it is mature and well suited. Sharing code
++was not really a win, due to the different data structures. Also, the
++hrtimer functions now have clearer behavior and clearer names - such as
++hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
++equivalent to del_timer() and del_timer_sync()] - so there's no direct
++1:1 mapping between them on the algorithmical level, and thus no real
++potential for code sharing either.
++
++Basic data types: every time value, absolute or relative, is in a
++special nanosecond-resolution type: ktime_t. The kernel-internal
++representation of ktime_t values and operations is implemented via
++macros and inline functions, and can be switched between a "hybrid
++union" type and a plain "scalar" 64bit nanoseconds representation (at
++compile time). The hybrid union type optimizes time conversions on 32bit
++CPUs. This build-time-selectable ktime_t storage format was implemented
++to avoid the performance impact of 64-bit multiplications and divisions
++on 32bit CPUs. Such operations are frequently necessary to convert
++between the storage formats provided by kernel and userspace interfaces
++and the internal time format. (See include/linux/ktime.h for further
++details.)
++
++hrtimers - rounding of timer values
++-----------------------------------
++
++the hrtimer code will round timer events to lower-resolution clocks
++because it has to. Otherwise it will do no artificial rounding at all.
++
++one question is, what resolution value should be returned to the user by
++the clock_getres() interface. This will return whatever real resolution
++a given clock has - be it low-res, high-res, or artificially-low-res.
++
++hrtimers - testing and verification
++----------------------------------
++
++We used the high-resolution clock subsystem ontop of hrtimers to verify
++the hrtimer implementation details in praxis, and we also ran the posix
++timer tests in order to ensure specification compliance. We also ran
++tests on low-resolution clocks.
++
++The hrtimer patch converts the following kernel functionality to use
++hrtimers:
++
++ - nanosleep
++ - itimers
++ - posix-timers
++
++The conversion of nanosleep and posix-timers enabled the unification of
++nanosleep and clock_nanosleep.
++
++The code was successfully compiled for the following platforms:
++
++ i386, x86_64, ARM, PPC, PPC64, IA64
++
++The code was run-tested on the following platforms:
++
++ i386(UP/SMP), x86_64(UP/SMP), ARM, PPC
++
++hrtimers were also integrated into the -rt tree, along with a
++hrtimers-based high-resolution clock implementation, so the hrtimers
++code got a healthy amount of testing and use in practice.
++
++	Thomas Gleixner, Ingo Molnar
+diff --git a/Documentation/timers/timer_stats.txt b/Documentation/timers/timer_stats.txt
+new file mode 100644
+index 0000000..20d368c
+--- /dev/null
++++ b/Documentation/timers/timer_stats.txt
+@@ -0,0 +1,73 @@
++timer_stats - timer usage statistics
++------------------------------------
++
++timer_stats is a debugging facility to make the timer (ab)usage in a Linux
++system visible to kernel and userspace developers. If enabled in the config
++but not used it has almost zero runtime overhead, and a relatively small
++data structure overhead. Even if collection is enabled runtime all the
++locking is per-CPU and lookup is hashed.
++
++timer_stats should be used by kernel and userspace developers to verify that
++their code does not make unduly use of timers. This helps to avoid unnecessary
++wakeups, which should be avoided to optimize power consumption.
++
++It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration
++section.
++
++timer_stats collects information about the timer events which are fired in a
++Linux system over a sample period:
++
++- the pid of the task(process) which initialized the timer
++- the name of the process which initialized the timer
++- the function where the timer was intialized
++- the callback function which is associated to the timer
++- the number of events (callbacks)
++
++timer_stats adds an entry to /proc: /proc/timer_stats
++
++This entry is used to control the statistics functionality and to read out the
++sampled information.
++
++The timer_stats functionality is inactive on bootup.
++
++To activate a sample period issue:
++# echo 1 >/proc/timer_stats
++
++To stop a sample period issue:
++# echo 0 >/proc/timer_stats
++
++The statistics can be retrieved by:
++# cat /proc/timer_stats
++
++The readout of /proc/timer_stats automatically disables sampling. The sampled
++information is kept until a new sample period is started. This allows multiple
++readouts.
++
++Sample output of /proc/timer_stats:
++
++Timerstats sample period: 3.888770 s
++  12,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
++  15,     1 swapper          hcd_submit_urb (rh_timer_func)
++   4,   959 kedac            schedule_timeout (process_timeout)
++   1,     0 swapper          page_writeback_init (wb_timer_fn)
++  28,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
++  22,  2948 IRQ 4            tty_flip_buffer_push (delayed_work_timer_fn)
++   3,  3100 bash             schedule_timeout (process_timeout)
++   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
++   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
++   1,     1 swapper          neigh_table_init_no_netlink (neigh_periodic_timer)
++   1,  2292 ip               __netdev_watchdog_up (dev_watchdog)
++   1,    23 events/1         do_cache_clean (delayed_work_timer_fn)
++90 total events, 30.0 events/sec
++
++The first column is the number of events, the second column the pid, the third
++column is the name of the process. The forth column shows the function which
++initialized the timer and in parantheses the callback function which was
++executed on expiry.
++
++    Thomas, Ingo
++
++Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
++timer will appear as follows
++  10D,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
++
+diff --git a/Documentation/usb/anchors.txt b/Documentation/usb/anchors.txt
+new file mode 100644
+index 0000000..7304bcf
+--- /dev/null
++++ b/Documentation/usb/anchors.txt
+@@ -0,0 +1,50 @@
++What is anchor?
++===============
++
++A USB driver needs to support some callbacks requiring
++a driver to cease all IO to an interface. To do so, a
++driver has to keep track of the URBs it has submitted
++to know they've all completed or to call usb_kill_urb
++for them. The anchor is a data structure takes care of
++keeping track of URBs and provides methods to deal with
++multiple URBs.
++
++Allocation and Initialisation
++=============================
++
++There's no API to allocate an anchor. It is simply declared
++as struct usb_anchor. init_usb_anchor() must be called to
++initialise the data structure.
++
++Deallocation
++============
++
++Once it has no more URBs associated with it, the anchor can be
++freed with normal memory management operations.
++
++Association and disassociation of URBs with anchors
++===================================================
++
++An association of URBs to an anchor is made by an explicit
++call to usb_anchor_urb(). The association is maintained until
++an URB is finished by (successfull) completion. Thus disassociation
++is automatic. A function is provided to forcibly finish (kill)
++all URBs associated with an anchor.
++Furthermore, disassociation can be made with usb_unanchor_urb()
++
++Operations on multitudes of URBs
++================================
++
++usb_kill_anchored_urbs()
++------------------------
++
++This function kills all URBs associated with an anchor. The URBs
++are called in the reverse temporal order they were submitted.
++This way no data can be reordered.
++
++usb_wait_anchor_empty_timeout()
++-------------------------------
++
++This function waits for all URBs associated with an anchor to finish
++or a timeout, whichever comes first. Its return value will tell you
++whether the timeout was reached.
+diff --git a/Documentation/usb/callbacks.txt b/Documentation/usb/callbacks.txt
+new file mode 100644
+index 0000000..7c81241
+--- /dev/null
++++ b/Documentation/usb/callbacks.txt
+@@ -0,0 +1,132 @@
++What callbacks will usbcore do?
++===============================
++
++Usbcore will call into a driver through callbacks defined in the driver
++structure and through the completion handler of URBs a driver submits.
++Only the former are in the scope of this document. These two kinds of
++callbacks are completely independent of each other. Information on the
++completion callback can be found in Documentation/usb/URB.txt.
++
++The callbacks defined in the driver structure are:
++
++1. Hotplugging callbacks:
++
++ * @probe: Called to see if the driver is willing to manage a particular
++ *	interface on a device.
++ * @disconnect: Called when the interface is no longer accessible, usually
++ *	because its device has been (or is being) disconnected or the
++ *	driver module is being unloaded.
++
++2. Odd backdoor through usbfs:
++
++ * @ioctl: Used for drivers that want to talk to userspace through
++ *	the "usbfs" filesystem.  This lets devices provide ways to
++ *	expose information to user space regardless of where they
++ *	do (or don't) show up otherwise in the filesystem.
++
++3. Power management (PM) callbacks:
++
++ * @suspend: Called when the device is going to be suspended.
++ * @resume: Called when the device is being resumed.
++ * @reset_resume: Called when the suspended device has been reset instead
++ *	of being resumed.
++
++4. Device level operations:
++
++ * @pre_reset: Called when the device is about to be reset.
++ * @post_reset: Called after the device has been reset
++
++The ioctl interface (2) should be used only if you have a very good
++reason. Sysfs is preferred these days. The PM callbacks are covered
++separately in Documentation/usb/power-management.txt.
++
++Calling conventions
++===================
++
++All callbacks are mutually exclusive. There's no need for locking
++against other USB callbacks. All callbacks are called from a task
++context. You may sleep. However, it is important that all sleeps have a
++small fixed upper limit in time. In particular you must not call out to
++user space and await results.
++
++Hotplugging callbacks
++=====================
++
++These callbacks are intended to associate and disassociate a driver with
++an interface. A driver's bond to an interface is exclusive.
++
++The probe() callback
++--------------------
++
++int (*probe) (struct usb_interface *intf,
++		const struct usb_device_id *id);
++
++Accept or decline an interface. If you accept the device return 0,
++otherwise -ENODEV or -ENXIO. Other error codes should be used only if a
++genuine error occurred during initialisation which prevented a driver
++from accepting a device that would else have been accepted.
++You are strongly encouraged to use usbcore'sfacility,
++usb_set_intfdata(), to associate a data structure with an interface, so
++that you know which internal state and identity you associate with a
++particular interface. The device will not be suspended and you may do IO
++to the interface you are called for and endpoint 0 of the device. Device
++initialisation that doesn't take too long is a good idea here.
++
++The disconnect() callback
++-------------------------
++
++void (*disconnect) (struct usb_interface *intf);
++
++This callback is a signal to break any connection with an interface.
++You are not allowed any IO to a device after returning from this
++callback. You also may not do any other operation that may interfere
++with another driver bound the interface, eg. a power management
++operation.
++If you are called due to a physical disconnection, all your URBs will be
++killed by usbcore. Note that in this case disconnect will be called some
++time after the physical disconnection. Thus your driver must be prepared
++to deal with failing IO even prior to the callback.
++
++Device level callbacks
++======================
++
++pre_reset
++---------
++
++int (*pre_reset)(struct usb_interface *intf);
++
++Another driver or user space is triggering a reset on the device which
++contains the interface passed as an argument. Cease IO and save any
++device state you need to restore.
++
++If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
++are in atomic context.
++
++post_reset
++----------
++
++int (*post_reset)(struct usb_interface *intf);
++
++The reset has completed.  Restore any saved device state and begin
++using the device again.
++
++If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
++are in atomic context.
++
++Call sequences
++==============
++
++No callbacks other than probe will be invoked for an interface
++that isn't bound to your driver.
++
++Probe will never be called for an interface bound to a driver.
++Hence following a successful probe, disconnect will be called
++before there is another probe for the same interface.
++
++Once your driver is bound to an interface, disconnect can be
++called at any time except in between pre_reset and post_reset.
++pre_reset is always followed by post_reset, even if the reset
++failed or the device has been unplugged.
++
++suspend is always followed by one of: resume, reset_resume, or
++disconnect.
+diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
+index df54d64..d56cb1a 100644
+--- a/Documentation/usb/persist.txt
++++ b/Documentation/usb/persist.txt
+@@ -2,7 +2,7 @@
+ 
+ 		   Alan Stern <stern at rowland.harvard.edu>
+ 
+-		 September 2, 2006 (Updated May 29, 2007)
++		September 2, 2006 (Updated February 25, 2008)
+ 
+ 
+ 	What is the problem?
+@@ -65,9 +65,10 @@ much better.)
+ 
+ 	What is the solution?
+ 
+-Setting CONFIG_USB_PERSIST will cause the kernel to work around these
+-issues.  It enables a mode in which the core USB device data
+-structures are allowed to persist across a power-session disruption.
++The kernel includes a feature called USB-persist.  It tries to work
++around these issues by allowing the core USB device data structures to
++persist across a power-session disruption.
++
+ It works like this.  If the kernel sees that a USB host controller is
+ not in the expected state during resume (i.e., if the controller was
+ reset or otherwise had lost power) then it applies a persistence check
+@@ -80,28 +81,30 @@ re-enumeration shows that the device now attached to that port has the
+ same descriptors as before, including the Vendor and Product IDs, then
+ the kernel continues to use the same device structure.  In effect, the
+ kernel treats the device as though it had merely been reset instead of
+-unplugged.
++unplugged.  The same thing happens if the host controller is in the
++expected state but a USB device was unplugged and then replugged.
+ 
+ If no device is now attached to the port, or if the descriptors are
+ different from what the kernel remembers, then the treatment is what
+ you would expect.  The kernel destroys the old device structure and
+ behaves as though the old device had been unplugged and a new device
+-plugged in, just as it would without the CONFIG_USB_PERSIST option.
++plugged in.
+ 
+ The end result is that the USB device remains available and usable.
+ Filesystem mounts and memory mappings are unaffected, and the world is
+ now a good and happy place.
+ 
+-Note that even when CONFIG_USB_PERSIST is set, the "persist" feature
+-will be applied only to those devices for which it is enabled.  You
+-can enable the feature by doing (as root):
++Note that the "USB-persist" feature will be applied only to those
++devices for which it is enabled.  You can enable the feature by doing
++(as root):
+ 
+ 	echo 1 >/sys/bus/usb/devices/.../power/persist
+ 
+ where the "..." should be filled in the with the device's ID.  Disable
+ the feature by writing 0 instead of 1.  For hubs the feature is
+-automatically and permanently enabled, so you only have to worry about
+-setting it for devices where it really matters.
++automatically and permanently enabled and the power/persist file
++doesn't even exist, so you only have to worry about setting it for
++devices where it really matters.
+ 
+ 
+ 	Is this the best solution?
+@@ -112,19 +115,19 @@ centralized Logical Volume Manager.  Such a solution would allow you
+ to plug in a USB flash device, create a persistent volume associated
+ with it, unplug the flash device, plug it back in later, and still
+ have the same persistent volume associated with the device.  As such
+-it would be more far-reaching than CONFIG_USB_PERSIST.
++it would be more far-reaching than USB-persist.
+ 
+ On the other hand, writing a persistent volume manager would be a big
+ job and using it would require significant input from the user.  This
+ solution is much quicker and easier -- and it exists now, a giant
+ point in its favor!
+ 
+-Furthermore, the USB_PERSIST option applies to _all_ USB devices, not
++Furthermore, the USB-persist feature applies to _all_ USB devices, not
+ just mass-storage devices.  It might turn out to be equally useful for
+ other device types, such as network interfaces.
+ 
+ 
+-	WARNING: Using CONFIG_USB_PERSIST can be dangerous!!
++	WARNING: USB-persist can be dangerous!!
+ 
+ When recovering an interrupted power session the kernel does its best
+ to make sure the USB device hasn't been changed; that is, the same
+@@ -133,10 +136,10 @@ aren't guaranteed to be 100% accurate.
+ 
+ If you replace one USB device with another of the same type (same
+ manufacturer, same IDs, and so on) there's an excellent chance the
+-kernel won't detect the change.  Serial numbers and other strings are
+-not compared.  In many cases it wouldn't help if they were, because
+-manufacturers frequently omit serial numbers entirely in their
+-devices.
++kernel won't detect the change.  The serial number string and other
++descriptors are compared with the kernel's stored values, but this
++might not help since manufacturers frequently omit serial numbers
++entirely in their devices.
+ 
+ Furthermore it's quite possible to leave a USB device exactly the same
+ while changing its media.  If you replace the flash memory card in a
+@@ -152,5 +155,5 @@ but yourself.
+ YOU HAVE BEEN WARNED!  USE AT YOUR OWN RISK!
+ 
+ That having been said, most of the time there shouldn't be any trouble
+-at all.  The "persist" feature can be extremely useful.  Make the most
+-of it.
++at all.  The USB-persist feature can be extremely useful.  Make the
++most of it.
+diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
+index 8b077e4..ff2c1ff 100644
+--- a/Documentation/usb/usb-serial.txt
++++ b/Documentation/usb/usb-serial.txt
+@@ -192,12 +192,9 @@ Keyspan USA-series Serial Adapters
+ 
+ FTDI Single Port Serial Driver
+ 
+-  This is a single port DB-25 serial adapter. More information about this
+-  device and the Linux driver can be found at:
+-	http://reality.sgi.com/bryder_wellington/ftdi_sio/
++  This is a single port DB-25 serial adapter.
+ 
+-  For any questions or problems with this driver, please contact Bill Ryder
+-  at bryder at sgi.com
++  For any questions or problems with this driver, please contact Bill Ryder.
+ 
+ 
+ ZyXEL omni.net lcd plus ISDN TA
+diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828
+new file mode 100644
+index 0000000..aaae360
+--- /dev/null
++++ b/Documentation/video4linux/CARDLIST.au0828
+@@ -0,0 +1,4 @@
++  0 -> Unknown board                            (au0828)
++  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200]
++  2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
++  3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
+diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
+index d97cf7c..f32efb6 100644
+--- a/Documentation/video4linux/CARDLIST.bttv
++++ b/Documentation/video4linux/CARDLIST.bttv
+@@ -148,3 +148,5 @@
+ 147 -> VoodooTV 200 (USA)                                  [121a:3000]
+ 148 -> DViCO FusionHDTV 2                                  [dbc0:d200]
+ 149 -> Typhoon TV-Tuner PCI (50684)
++150 -> Geovision GV-600                                    [008a:763c]
++151 -> Kozumi KTV-01C
+diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885
+index 0924e6e..929b90c 100644
+--- a/Documentation/video4linux/CARDLIST.cx23885
++++ b/Documentation/video4linux/CARDLIST.cx23885
+@@ -5,3 +5,6 @@
+   4 -> DViCO FusionHDTV5 Express                           [18ac:d500]
+   5 -> Hauppauge WinTV-HVR1500Q                            [0070:7790,0070:7797]
+   6 -> Hauppauge WinTV-HVR1500                             [0070:7710,0070:7717]
++  7 -> Hauppauge WinTV-HVR1200                             [0070:71d1]
++  8 -> Hauppauge WinTV-HVR1700                             [0070:8101]
++  9 -> Hauppauge WinTV-HVR1400                             [0070:8010]
+diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
+index bc5593b..5439573 100644
+--- a/Documentation/video4linux/CARDLIST.cx88
++++ b/Documentation/video4linux/CARDLIST.cx88
+@@ -57,3 +57,12 @@
+  56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder   [0070:9600,0070:9601,0070:9602]
+  57 -> ADS Tech Instant Video PCI                          [1421:0390]
+  58 -> Pinnacle PCTV HD 800i                               [11bd:0051]
++ 59 -> DViCO FusionHDTV 5 PCI nano                         [18ac:d530]
++ 60 -> Pinnacle Hybrid PCTV                                [12ab:1788]
++ 61 -> Winfast TV2000 XP Global                            [107d:6f18]
++ 62 -> PowerColor Real Angel 330                           [14f1:ea3d]
++ 63 -> Geniatech X8000-MT DVBT                             [14f1:8852]
++ 64 -> DViCO FusionHDTV DVB-T PRO                          [18ac:db30]
++ 65 -> DViCO FusionHDTV 7 Gold                             [18ac:d610]
++ 66 -> Prolink Pixelview MPEG 8000GT                       [1554:4935]
++ 67 -> Kworld PlusTV HD PCI 120 (ATSC 120)                 [17de:08c1]
+diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
+index 0424901..44d84dd 100644
+--- a/Documentation/video4linux/CARDLIST.saa7134
++++ b/Documentation/video4linux/CARDLIST.saa7134
+@@ -25,8 +25,8 @@
+  24 -> KNC One TV-Station DVR                   [1894:a006]
+  25 -> ASUS TV-FM 7133                          [1043:4843]
+  26 -> Pinnacle PCTV Stereo (saa7134)           [11bd:002b]
+- 27 -> Manli MuchTV M-TV002/Behold TV 403 FM
+- 28 -> Manli MuchTV M-TV001/Behold TV 401
++ 27 -> Manli MuchTV M-TV002
++ 28 -> Manli MuchTV M-TV001
+  29 -> Nagase Sangyo TransGear 3000TV           [1461:050c]
+  30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM)  [1019:4cb4]
+  31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
+@@ -131,3 +131,12 @@
+ 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]
+ 131 -> Twinhan Hybrid DTV-DVB 3056 PCI          [1822:0022]
+ 132 -> Genius TVGO AM11MCE
++133 -> NXP Snake DVB-S reference design
++134 -> Medion/Creatix CTX953 Hybrid             [16be:0010]
++135 -> MSI TV at nywhere A/D v1.1                  [1462:8625]
++136 -> AVerMedia Cardbus TV/Radio (E506R)       [1461:f436]
++137 -> AVerMedia Hybrid TV/Radio (A16D)         [1461:f936]
++138 -> Avermedia M115                           [1461:a836]
++139 -> Compro VideoMate T750                    [185b:c900]
++140 -> Avermedia DVB-S Pro A700                 [1461:a7a1]
++141 -> Avermedia DVB-S Hybrid+FM A700           [1461:a7a2]
+diff --git a/Documentation/video4linux/extract_xc3028.pl b/Documentation/video4linux/extract_xc3028.pl
+index cced8ac..2cb8160 100644
+--- a/Documentation/video4linux/extract_xc3028.pl
++++ b/Documentation/video4linux/extract_xc3028.pl
+@@ -686,11 +686,11 @@ sub main_firmware($$$$)
+ 	write_hunk(812664, 192);
+ 
+ 	#
+-	# Firmware 58, type: SCODE FW  HAS IF (0x60000000), IF = 4.50 MHz id: NTSC/M Jp (0000000000002000), size: 192
++	# Firmware 58, type: SCODE FW  MTS LCD NOGD MONO IF HAS IF (0x6002b004), IF = 4.50 MHz id: NTSC PAL/M PAL/N (000000000000b700), size: 192
+ 	#
+ 
+-	write_le32(0x60000000);			# Type
+-	write_le64(0x00000000, 0x00002000);	# ID
++	write_le32(0x6002b004);			# Type
++	write_le64(0x00000000, 0x0000b700);	# ID
+ 	write_le16(4500);			# IF
+ 	write_le32(192);			# Size
+ 	write_hunk(807672, 192);
+@@ -706,10 +706,10 @@ sub main_firmware($$$$)
+ 	write_hunk(807864, 192);
+ 
+ 	#
+-	# Firmware 60, type: SCODE FW  DTV78 ZARLINK456 HAS IF (0x62000100), IF = 4.76 MHz id: (0000000000000000), size: 192
++	# Firmware 60, type: SCODE FW  DTV6 QAM DTV7 DTV78 DTV8 ZARLINK456 HAS IF (0x620003e0), IF = 4.76 MHz id: (0000000000000000), size: 192
+ 	#
+ 
+-	write_le32(0x62000100);			# Type
++	write_le32(0x620003e0);			# Type
+ 	write_le64(0x00000000, 0x00000000);	# ID
+ 	write_le16(4760);			# IF
+ 	write_le32(192);			# Size
+@@ -726,30 +726,30 @@ sub main_firmware($$$$)
+ 	write_hunk(811512, 192);
+ 
+ 	#
+-	# Firmware 62, type: SCODE FW  DTV7 ZARLINK456 HAS IF (0x62000080), IF = 5.26 MHz id: (0000000000000000), size: 192
++	# Firmware 62, type: SCODE FW  HAS IF (0x60000000), IF = 5.26 MHz id: (0000000000000000), size: 192
+ 	#
+ 
+-	write_le32(0x62000080);			# Type
++	write_le32(0x60000000);			# Type
+ 	write_le64(0x00000000, 0x00000000);	# ID
+ 	write_le16(5260);			# IF
+ 	write_le32(192);			# Size
+ 	write_hunk(810552, 192);
+ 
+ 	#
+-	# Firmware 63, type: SCODE FW  MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
++	# Firmware 63, type: SCODE FW  MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG A2 NICAM (0000000f00000007), size: 192
+ 	#
+ 
+ 	write_le32(0x60008000);			# Type
+-	write_le64(0x00000008, 0x00000007);	# ID
++	write_le64(0x0000000f, 0x00000007);	# ID
+ 	write_le16(5320);			# IF
+ 	write_le32(192);			# Size
+ 	write_hunk(810744, 192);
+ 
+ 	#
+-	# Firmware 64, type: SCODE FW  DTV8 CHINA HAS IF (0x64000200), IF = 5.40 MHz id: (0000000000000000), size: 192
++	# Firmware 64, type: SCODE FW  DTV7 DTV78 DTV8 DIBCOM52 CHINA HAS IF (0x65000380), IF = 5.40 MHz id: (0000000000000000), size: 192
+ 	#
+ 
+-	write_le32(0x64000200);			# Type
++	write_le32(0x65000380);			# Type
+ 	write_le64(0x00000000, 0x00000000);	# ID
+ 	write_le16(5400);			# IF
+ 	write_le32(192);			# Size
+@@ -766,50 +766,50 @@ sub main_firmware($$$$)
+ 	write_hunk(809592, 192);
+ 
+ 	#
+-	# Firmware 66, type: SCODE FW  HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2/B (0000000200000007), size: 192
++	# Firmware 66, type: SCODE FW  HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2 (0000000300000007), size: 192
+ 	#
+ 
+ 	write_le32(0x60000000);			# Type
+-	write_le64(0x00000002, 0x00000007);	# ID
++	write_le64(0x00000003, 0x00000007);	# ID
+ 	write_le16(5640);			# IF
+ 	write_le32(192);			# Size
+ 	write_hunk(808440, 192);
+ 
+ 	#
+-	# Firmware 67, type: SCODE FW  HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
++	# Firmware 67, type: SCODE FW  HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM (0000000c00000007), size: 192
+ 	#
+ 
+ 	write_le32(0x60000000);			# Type
+-	write_le64(0x00000008, 0x00000007);	# ID
++	write_le64(0x0000000c, 0x00000007);	# ID
+ 	write_le16(5740);			# IF
+ 	write_le32(192);			# Size
+ 	write_hunk(808632, 192);
+ 
+ 	#
+-	# Firmware 68, type: SCODE FW  DTV7 DIBCOM52 HAS IF (0x61000080), IF = 5.90 MHz id: (0000000000000000), size: 192
++	# Firmware 68, type: SCODE FW  HAS IF (0x60000000), IF = 5.90 MHz id: (0000000000000000), size: 192
+ 	#
+ 
+-	write_le32(0x61000080);			# Type
++	write_le32(0x60000000);			# Type
+ 	write_le64(0x00000000, 0x00000000);	# ID
+ 	write_le16(5900);			# IF
+ 	write_le32(192);			# Size
+ 	write_hunk(810360, 192);
+ 
+ 	#
+-	# Firmware 69, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/I (0000000000000010), size: 192
++	# Firmware 69, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/DK PAL/I SECAM/K3 SECAM/L SECAM/Lc NICAM (0000000c04c000f0), size: 192
+ 	#
+ 
+ 	write_le32(0x60008000);			# Type
+-	write_le64(0x00000000, 0x00000010);	# ID
++	write_le64(0x0000000c, 0x04c000f0);	# ID
+ 	write_le16(6000);			# IF
+ 	write_le32(192);			# Size
+ 	write_hunk(808824, 192);
+ 
+ 	#
+-	# Firmware 70, type: SCODE FW  DTV6 QAM F6MHZ HAS IF (0x68000060), IF = 6.20 MHz id: (0000000000000000), size: 192
++	# Firmware 70, type: SCODE FW  DTV6 QAM ATSC LG60 F6MHZ HAS IF (0x68050060), IF = 6.20 MHz id: (0000000000000000), size: 192
+ 	#
+ 
+-	write_le32(0x68000060);			# Type
++	write_le32(0x68050060);			# Type
+ 	write_le64(0x00000000, 0x00000000);	# ID
+ 	write_le16(6200);			# IF
+ 	write_le32(192);			# Size
+@@ -846,11 +846,11 @@ sub main_firmware($$$$)
+ 	write_hunk(809208, 192);
+ 
+ 	#
+-	# Firmware 74, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.50 MHz id: SECAM/K3 (0000000004000000), size: 192
++	# Firmware 74, type: SCODE FW  MONO HAS IF (0x60008000), IF = 6.50 MHz id: PAL/DK SECAM/K3 SECAM/L NICAM (0000000c044000e0), size: 192
+ 	#
+ 
+ 	write_le32(0x60008000);			# Type
+-	write_le64(0x00000000, 0x04000000);	# ID
++	write_le64(0x0000000c, 0x044000e0);	# ID
+ 	write_le16(6500);			# IF
+ 	write_le32(192);			# Size
+ 	write_hunk(811128, 192);
+diff --git a/Documentation/x86/pat.txt b/Documentation/x86/pat.txt
+new file mode 100644
+index 0000000..17965f9
+--- /dev/null
++++ b/Documentation/x86/pat.txt
+@@ -0,0 +1,100 @@
++
++PAT (Page Attribute Table)
++
++x86 Page Attribute Table (PAT) allows for setting the memory attribute at the
++page level granularity. PAT is complementary to the MTRR settings which allows
++for setting of memory types over physical address ranges. However, PAT is
++more flexible than MTRR due to its capability to set attributes at page level
++and also due to the fact that there are no hardware limitations on number of
++such attribute settings allowed. Added flexibility comes with guidelines for
++not having memory type aliasing for the same physical memory with multiple
++virtual addresses.
++
++PAT allows for different types of memory attributes. The most commonly used
++ones that will be supported at this time are Write-back, Uncached,
++Write-combined and Uncached Minus.
++
++There are many different APIs in the kernel that allows setting of memory
++attributes at the page level. In order to avoid aliasing, these interfaces
++should be used thoughtfully. Below is a table of interfaces available,
++their intended usage and their memory attribute relationships. Internally,
++these APIs use a reserve_memtype()/free_memtype() interface on the physical
++address range to avoid any aliasing.
++
++
++-------------------------------------------------------------------
++API                    |    RAM   |  ACPI,...  |  Reserved/Holes  |
++-----------------------|----------|------------|------------------|
++                       |          |            |                  |
++ioremap                |    --    |    UC      |       UC         |
++                       |          |            |                  |
++ioremap_cache          |    --    |    WB      |       WB         |
++                       |          |            |                  |
++ioremap_nocache        |    --    |    UC      |       UC         |
++                       |          |            |                  |
++ioremap_wc             |    --    |    --      |       WC         |
++                       |          |            |                  |
++set_memory_uc          |    UC    |    --      |       --         |
++ set_memory_wb         |          |            |                  |
++                       |          |            |                  |
++set_memory_wc          |    WC    |    --      |       --         |
++ set_memory_wb         |          |            |                  |
++                       |          |            |                  |
++pci sysfs resource     |    --    |    --      |       UC         |
++                       |          |            |                  |
++pci sysfs resource_wc  |    --    |    --      |       WC         |
++ is IORESOURCE_PREFETCH|          |            |                  |
++                       |          |            |                  |
++pci proc               |    --    |    --      |       UC         |
++ !PCIIOC_WRITE_COMBINE |          |            |                  |
++                       |          |            |                  |
++pci proc               |    --    |    --      |       WC         |
++ PCIIOC_WRITE_COMBINE  |          |            |                  |
++                       |          |            |                  |
++/dev/mem               |    --    |    UC      |       UC         |
++ read-write            |          |            |                  |
++                       |          |            |                  |
++/dev/mem               |    --    |    UC      |       UC         |
++ mmap SYNC flag        |          |            |                  |
++                       |          |            |                  |
++/dev/mem               |    --    |  WB/WC/UC  |    WB/WC/UC      |
++ mmap !SYNC flag       |          |(from exist-|  (from exist-    |
++ and                   |          |  ing alias)|    ing alias)    |
++ any alias to this area|          |            |                  |
++                       |          |            |                  |
++/dev/mem               |    --    |    WB      |       WB         |
++ mmap !SYNC flag       |          |            |                  |
++ no alias to this area |          |            |                  |
++ and                   |          |            |                  |
++ MTRR says WB          |          |            |                  |
++                       |          |            |                  |
++/dev/mem               |    --    |    --      |    UC_MINUS      |
++ mmap !SYNC flag       |          |            |                  |
++ no alias to this area |          |            |                  |
++ and                   |          |            |                  |
++ MTRR says !WB         |          |            |                  |
++                       |          |            |                  |
++-------------------------------------------------------------------
++
++Notes:
++
++-- in the above table mean "Not suggested usage for the API". Some of the --'s
++are strictly enforced by the kernel. Some others are not really enforced
++today, but may be enforced in future.
++
++For ioremap and pci access through /sys or /proc - The actual type returned
++can be more restrictive, in case of any existing aliasing for that address.
++For example: If there is an existing uncached mapping, a new ioremap_wc can
++return uncached mapping in place of write-combine requested.
++
++set_memory_[uc|wc] and set_memory_wb should be used in pairs, where driver will
++first make a region uc or wc and switch it back to wb after use.
++
++Over time writes to /proc/mtrr will be deprecated in favor of using PAT based
++interfaces. Users writing to /proc/mtrr are suggested to use above interfaces.
++
++Drivers should use ioremap_[uc|wc] to access PCI BARs with [uc|wc] access
++types.
++
++Drivers should use set_memory_[uc|wc] to set access type for RAM ranges.
++
+diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
+index 34abae4..b0c7b6c 100644
+--- a/Documentation/x86_64/boot-options.txt
++++ b/Documentation/x86_64/boot-options.txt
+@@ -307,3 +307,8 @@ Debugging
+ 			stuck (default)
+ 
+ Miscellaneous
++
++	nogbpages
++		Do not use GB pages for kernel direct mappings.
++	gbpages
++		Use GB pages for kernel direct mappings.
+diff --git a/MAINTAINERS b/MAINTAINERS
+index e467758..a942f38 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -486,6 +486,12 @@ M:	kernel at wantstofly.org
+ L:	linux-arm-kernel at lists.arm.linux.org.uk (subscribers-only)
+ S:	Maintained
+ 
++ARM/GUMSTIX MACHINE SUPPORT
++P:	Steve Sakoman
++M:	sakoman at gmail.com
++L:	linux-arm-kernel at lists.arm.linux.org.uk (subscribers-only)
++S:	Maintained
++
+ ARM/HP JORNADA 7XX MACHINE SUPPORT
+ P:      Kristoffer Ericson
+ M:      kristoffer.ericson at gmail.com
+@@ -678,6 +684,11 @@ L:	linux-wireless at vger.kernel.org
+ L:	ath5k-devel at lists.ath5k.org
+ S:	Maintained
+ 
++ATI_REMOTE2 DRIVER
++P:	Ville Syrjala
++M:	syrjala at sci.fi
++S:	Maintained
++
+ ATL1 ETHERNET DRIVER
+ P:	Jay Cliburn
+ M:	jcliburn at gmail.com
+@@ -840,15 +851,6 @@ L:	linux-wireless at vger.kernel.org
+ W:	http://linuxwireless.org/en/users/Drivers/b43
+ S:	Maintained
+ 
+-BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION)
+-P:	Larry Finger
+-M:	Larry.Finger at lwfinger.net
+-P:	Stefano Brivio
+-M:	stefano.brivio at polimi.it
+-L:	linux-wireless at vger.kernel.org
+-W:	http://bcm43xx.berlios.de/
+-S:	Obsolete
+-
+ BEFS FILE SYSTEM
+ P:	Sergey S. Kostyliov
+ M:	rathamahata at php4.ru
+@@ -1104,6 +1106,12 @@ M:	kernel at wantstofly.org
+ L:	linux-usb at vger.kernel.org
+ S:	Maintained
+ 
++CIRRUS LOGIC CS4270 SOUND DRIVER
++P:	Timur Tabi
++M:	timur at freescale.com
++L:	alsa-devel at alsa-project.org
++S:	Supported
++
+ CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
+ P:	Cirrus Logic Corporation (kernel 2.2 driver)
+ M:	Cirrus Logic Corporation, Thomas Woller <twoller at crystal.cirrus.com>
+@@ -1626,6 +1634,12 @@ L:	linuxppc-dev at ozlabs.org
+ L:	netdev at vger.kernel.org
+ S:	Maintained
+ 
++FREESCALE QUICC ENGINE LIBRARY
++P:	Timur Tabi
++M:	timur at freescale.com
++L:	linuxppc-dev at ozlabs.org
++S:	Supported
++
+ FREESCALE HIGHSPEED USB DEVICE DRIVER
+ P:	Li Yang
+ M:	leoli at freescale.com
+@@ -1640,6 +1654,19 @@ L:	netdev at vger.kernel.org
+ L:	linuxppc-dev at ozlabs.org
+ S:	Maintained
+ 
++FREESCALE QUICC ENGINE UCC UART DRIVER
++P:	Timur Tabi
++M:	timur at freescale.com
++L:	linuxppc-dev at ozlabs.org
++S:	Supported
++
++FREESCALE SOC SOUND DRIVERS
++P:	Timur Tabi
++M:	timur at freescale.com
++L:	alsa-devel at alsa-project.org
++L:	linuxppc-dev at ozlabs.org
++S:	Supported
++
+ FILE LOCKING (flock() and fcntl()/lockf())
+ P:	Matthew Wilcox
+ M:	matthew at wil.cx
+@@ -2319,6 +2346,12 @@ L:	linux-kernel at vger.kernel.org
+ L:	kexec at lists.infradead.org
+ S:	Maintained
+ 
++KGDB
++P:	Jason Wessel
++M:	jason.wessel at windriver.com
++L:	kgdb-bugreport at lists.sourceforge.net
++S:	Maintained
++
+ KPROBES
+ P:	Ananth N Mavinakayanahalli
+ M:	ananth at in.ibm.com
+@@ -2550,12 +2583,10 @@ W:	http://www.tazenda.demon.co.uk/phil/linux-hp
+ S:	Maintained
+ 
+ MAC80211
+-P:	Michael Wu
+-M:	flamingice at sourmilk.net
+ P:	Johannes Berg
+ M:	johannes at sipsolutions.net
+-P:	Jiri Benc
+-M:	jbenc at suse.cz
++P:	Michael Wu
++M:	flamingice at sourmilk.net
+ L:	linux-wireless at vger.kernel.org
+ W:	http://linuxwireless.org/
+ T:	git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
+@@ -2944,8 +2975,9 @@ P:	Mark Fasheh
+ M:	mfasheh at suse.com
+ P:	Joel Becker
+ M:	joel.becker at oracle.com
+-L:	ocfs2-devel at oss.oracle.com
++L:	ocfs2-devel at oss.oracle.com (moderated for non-subscribers)
+ W:	http://oss.oracle.com/projects/ocfs2/
++T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git
+ S:	Supported
+ 
+ OMNIKEY CARDMAN 4000 DRIVER
+@@ -3061,11 +3093,10 @@ L:	linux-pci at atrey.karlin.mff.cuni.cz
+ S:	Supported
+ 
+ PCI SUBSYSTEM
+-P:	Greg Kroah-Hartman
+-M:	gregkh at suse.de
++P:	Jesse Barnes
++M:	jbarnes at virtuousgeek.org
+ L:	linux-kernel at vger.kernel.org
+ L:	linux-pci at atrey.karlin.mff.cuni.cz
+-T:	quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
+ S:	Supported
+ 
+ PCI HOTPLUG CORE
+@@ -3472,7 +3503,7 @@ P:	Vlad Yasevich
+ M:	vladislav.yasevich at hp.com
+ P:	Sridhar Samudrala
+ M:	sri at us.ibm.com
+-L:	lksctp-developers at lists.sourceforge.net
++L:	linux-sctp at vger.kernel.org
+ W:	http://lksctp.sourceforge.net
+ S:	Supported
+ 
+@@ -3606,11 +3637,10 @@ M:	mhoffman at lightlink.com
+ L:	lm-sensors at lm-sensors.org
+ S:	Maintained
+ 
+-SOFTMAC LAYER (IEEE 802.11)
+-P:	Daniel Drake
+-M:	dsd at gentoo.org
+-L:	linux-wireless at vger.kernel.org
+-S:	Obsolete
++SMX UIO Interface
++P:	Ben Nizette
++M:	bn at niasdigital.com
++S:	Maintained
+ 
+ SOFTWARE RAID (Multiple Disks) SUPPORT
+ P:	Ingo Molnar
+@@ -4351,6 +4381,16 @@ L:	linux-wireless at vger.kernel.org
+ W:	http://oops.ghostprotocols.net:81/blog
+ S:	Maintained
+ 
++WM97XX TOUCHSCREEN DRIVERS
++P:	Mark Brown
++M:	broonie at opensource.wolfsonmicro.com
++P:	Liam Girdwood
++M:	liam.girdwood at wolfsonmicro.com
++L:	linux-input at vger.kernel.org
++T:	git git://opensource.wolfsonmicro.com/linux-2.6-touch
++W:	http://opensource.wolfsonmicro.com/node/7
++S:	Supported
++
+ X.25 NETWORK LAYER
+ P:	Henner Eisen
+ M:	eis at baty.hanse.de
+diff --git a/Makefile b/Makefile
+index 39516bf..cbd79f3 100644
+--- a/Makefile
++++ b/Makefile
+@@ -507,6 +507,10 @@ else
+ KBUILD_CFLAGS	+= -O2
+ endif
+ 
++ifneq (CONFIG_FRAME_WARN,0)
++KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
++endif
++
+ # Force gcc to behave correct even for buggy distributions
+ # Arch Makefiles may override this setting
+ KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
+@@ -1396,7 +1400,7 @@ define xtags
+ 	    $(all-kconfigs) | xargs $1 -a \
+ 		--langdef=kconfig \
+ 		--language-force=kconfig \
+-		--regex-kconfig='/^[[:blank:]]*config[[:blank:]]+([[:alnum:]_]+)/\1/'; \
++		--regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/'; \
+ 	    $(all-defconfigs) | xargs -r $1 -a \
+ 		--langdef=dotconfig \
+ 		--language-force=dotconfig \
+@@ -1404,7 +1408,7 @@ define xtags
+ 	elif $1 --version 2>&1 | grep -iq emacs; then \
+ 	    $(all-sources) | xargs $1 -a; \
+ 	    $(all-kconfigs) | xargs $1 -a \
+-		--regex='/^[ \t]*config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \
++		--regex='/^[ \t]*(menu|)config[ \t]+\([a-zA-Z0-9_]+\)/\2/'; \
+ 	    $(all-defconfigs) | xargs -r $1 -a \
+ 		--regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \
+ 	else \
+@@ -1538,8 +1542,7 @@ quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN   $(wildcard $(rm-dirs)))
+ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files)))
+       cmd_rmfiles = rm -f $(rm-files)
+ 
+-# Run depmod only is we have System.map and depmod is executable
+-# and we build for the host arch
++# Run depmod only if we have System.map and depmod is executable
+ quiet_cmd_depmod = DEPMOD  $(KERNELRELEASE)
+       cmd_depmod = \
+ 	if [ -r System.map -a -x $(DEPMOD) ]; then                              \
+diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
+index dccf052..ac706c1 100644
+--- a/arch/alpha/kernel/Makefile
++++ b/arch/alpha/kernel/Makefile
+@@ -7,7 +7,7 @@ EXTRA_AFLAGS	:= $(KBUILD_CFLAGS)
+ EXTRA_CFLAGS	:= -Werror -Wno-sign-compare
+ 
+ obj-y    := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
+-	    irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
++	    irq_alpha.o signal.o setup.o ptrace.o time.o \
+ 	    alpha_ksyms.o systbls.o err_common.o io.o
+ 
+ obj-$(CONFIG_VGA_HOSE)	+= console.o
+diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
+index e9762a3..d96e742 100644
+--- a/arch/alpha/kernel/alpha_ksyms.c
++++ b/arch/alpha/kernel/alpha_ksyms.c
+@@ -77,15 +77,6 @@ EXPORT_SYMBOL(__do_clear_user);
+ EXPORT_SYMBOL(__strncpy_from_user);
+ EXPORT_SYMBOL(__strnlen_user);
+ 
+-/* Semaphore helper functions.  */
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__up_wakeup);
+-EXPORT_SYMBOL(down);
+-EXPORT_SYMBOL(down_interruptible);
+-EXPORT_SYMBOL(down_trylock);
+-EXPORT_SYMBOL(up);
+-
+ /* 
+  * SMP-specific symbols.
+  */
+diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
+index 8c71daf..9fee37e 100644
+--- a/arch/alpha/kernel/osf_sys.c
++++ b/arch/alpha/kernel/osf_sys.c
+@@ -75,6 +75,7 @@ osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
+ 	lock_kernel();
+ 	mm = current->mm;
+ 	mm->end_code = bss_start + bss_len;
++	mm->start_brk = bss_start + bss_len;
+ 	mm->brk = bss_start + bss_len;
+ #if 0
+ 	printk("set_program_attributes(%lx %lx %lx %lx)\n",
+diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
+index 9dc1cee..7835779 100644
+--- a/arch/alpha/kernel/pci.c
++++ b/arch/alpha/kernel/pci.c
+@@ -71,25 +71,13 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_i
+ static void __init
+ quirk_cypress(struct pci_dev *dev)
+ {
+-	/* The Notorious Cy82C693 chip.  */
+-
+-	/* The Cypress IDE controller doesn't support native mode, but it
+-	   has programmable addresses of IDE command/control registers.
+-	   This violates PCI specifications, confuses the IDE subsystem and
+-	   causes resource conflicts between the primary HD_CMD register and
+-	   the floppy controller.  Ugh.  Fix that.  */
+-	if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
+-		dev->resource[0].flags = 0;
+-		dev->resource[1].flags = 0;
+-	}
+-
+ 	/* The Cypress bridge responds on the PCI bus in the address range
+ 	   0xffff0000-0xffffffff (conventional x86 BIOS ROM).  There is no
+ 	   way to turn this off.  The bridge also supports several extended
+ 	   BIOS ranges (disabled after power-up), and some consoles do turn
+ 	   them on.  So if we use a large direct-map window, or a large SG
+ 	   window, we must avoid the entire 0xfff00000-0xffffffff region.  */
+-	else if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
++	if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
+ 		if (__direct_map_base + __direct_map_size >= 0xfff00000UL)
+ 			__direct_map_size = 0xfff00000UL - __direct_map_base;
+ 		else {
+@@ -372,28 +360,7 @@ EXPORT_SYMBOL(pcibios_bus_to_resource);
+ int
+ pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+-	u16 cmd, oldcmd;
+-	int i;
+-
+-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+-	oldcmd = cmd;
+-
+-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+-		struct resource *res = &dev->resource[i];
+-
+-		if (res->flags & IORESOURCE_IO)
+-			cmd |= PCI_COMMAND_IO;
+-		else if (res->flags & IORESOURCE_MEM)
+-			cmd |= PCI_COMMAND_MEMORY;
+-	}
+-
+-	if (cmd != oldcmd) {
+-		printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n",
+-		       pci_name(dev), cmd);
+-		/* Enable the appropriate bits in the PCI command register.  */
+-		pci_write_config_word(dev, PCI_COMMAND, cmd);
+-	}
+-	return 0;
++	return pci_enable_resources(dev, mask);
+ }
+ 
+ /*
+@@ -412,7 +379,7 @@ pcibios_set_master(struct pci_dev *dev)
+ 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+ }
+ 
+-static void __init
++void __init
+ pcibios_claim_one_bus(struct pci_bus *b)
+ {
+ 	struct pci_dev *dev;
+@@ -426,7 +393,8 @@ pcibios_claim_one_bus(struct pci_bus *b)
+ 
+ 			if (r->parent || !r->start || !r->flags)
+ 				continue;
+-			pci_claim_resource(dev, i);
++			if (pci_probe_only || (r->flags & IORESOURCE_PCI_FIXED))
++				pci_claim_resource(dev, i);
+ 		}
+ 	}
+ 
+@@ -465,8 +433,7 @@ common_init_pci(void)
+ 		}
+ 	}
+ 
+-	if (pci_probe_only)
+-		pcibios_claim_console_setup();
++	pcibios_claim_console_setup();
+ 
+ 	pci_assign_unassigned_resources();
+ 	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c
+deleted file mode 100644
+index 8d2982a..0000000
+--- a/arch/alpha/kernel/semaphore.c
++++ /dev/null
+@@ -1,224 +0,0 @@
+-/*
+- * Alpha semaphore implementation.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- * (C) Copyright 1999, 2000 Richard Henderson
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-
+-/*
+- * This is basically the PPC semaphore scheme ported to use
+- * the Alpha ll/sc sequences, so see the PPC code for
+- * credits.
+- */
+-
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- *	old_count = sem->count;
+- *	tmp = MAX(old_count, 0) + incr;
+- *	sem->count = tmp;
+- *	return old_count;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+-	long old_count, tmp = 0;
+-
+-	__asm__ __volatile__(
+-	"1:	ldl_l	%0,%2\n"
+-	"	cmovgt	%0,%0,%1\n"
+-	"	addl	%1,%3,%1\n"
+-	"	stl_c	%1,%2\n"
+-	"	beq	%1,2f\n"
+-	"	mb\n"
+-	".subsection 2\n"
+-	"2:	br	1b\n"
+-	".previous"
+-	: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+-	: "Ir" (incr), "1" (tmp), "m" (sem->count));
+-
+-	return old_count;
+-}
+-
+-/*
+- * Perform the "down" function.  Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from down, the return is ignored and the wait loop is
+- * not interruptible.  This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from down_interruptible, the return value gets checked
+- * upon return.  If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- */
+-
+-void __sched
+-__down_failed(struct semaphore *sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	printk("%s(%d): down failed(%p)\n",
+-	       tsk->comm, task_pid_nr(tsk), sem);
+-#endif
+-
+-	tsk->state = TASK_UNINTERRUPTIBLE;
+-	wmb();
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	/*
+-	 * Try to get the semaphore.  If the count is > 0, then we've
+-	 * got the semaphore; we decrement count and exit the loop.
+-	 * If the count is 0 or negative, we set it to -1, indicating
+-	 * that we are asleep, and then sleep.
+-	 */
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		schedule();
+-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-	}
+-	remove_wait_queue(&sem->wait, &wait);
+-	tsk->state = TASK_RUNNING;
+-
+-	/*
+-	 * If there are any more sleepers, wake one of them up so
+-	 * that it can either get the semaphore, or set count to -1
+-	 * indicating that there are still processes sleeping.
+-	 */
+-	wake_up(&sem->wait);
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	printk("%s(%d): down acquired(%p)\n",
+-	       tsk->comm, task_pid_nr(tsk), sem);
+-#endif
+-}
+-
+-int __sched
+-__down_failed_interruptible(struct semaphore *sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	long ret = 0;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	printk("%s(%d): down failed(%p)\n",
+-	       tsk->comm, task_pid_nr(tsk), sem);
+-#endif
+-
+-	tsk->state = TASK_INTERRUPTIBLE;
+-	wmb();
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		if (signal_pending(current)) {
+-			/*
+-			 * A signal is pending - give up trying.
+-			 * Set sem->count to 0 if it is negative,
+-			 * since we are no longer sleeping.
+-			 */
+-			__sem_update_count(sem, 0);
+-			ret = -EINTR;
+-			break;
+-		}
+-		schedule();
+-		set_task_state(tsk, TASK_INTERRUPTIBLE);
+-	}
+-
+-	remove_wait_queue(&sem->wait, &wait);
+-	tsk->state = TASK_RUNNING;
+-	wake_up(&sem->wait);
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	printk("%s(%d): down %s(%p)\n",
+-	       current->comm, task_pid_nr(current),
+-	       (ret < 0 ? "interrupted" : "acquired"), sem);
+-#endif
+-	return ret;
+-}
+-
+-void
+-__up_wakeup(struct semaphore *sem)
+-{
+-	/*
+-	 * Note that we incremented count in up() before we came here,
+-	 * but that was ineffective since the result was <= 0, and
+-	 * any negative value of count is equivalent to 0.
+-	 * This ends up setting count to 1, unless count is now > 0
+-	 * (i.e. because some other cpu has called up() in the meantime),
+-	 * in which case we just increment count.
+-	 */
+-	__sem_update_count(sem, 1);
+-	wake_up(&sem->wait);
+-}
+-
+-void __sched
+-down(struct semaphore *sem)
+-{
+-#ifdef WAITQUEUE_DEBUG
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	printk("%s(%d): down(%p) <count=%d> from %p\n",
+-	       current->comm, task_pid_nr(current), sem,
+-	       atomic_read(&sem->count), __builtin_return_address(0));
+-#endif
+-	__down(sem);
+-}
+-
+-int __sched
+-down_interruptible(struct semaphore *sem)
+-{
+-#ifdef WAITQUEUE_DEBUG
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	printk("%s(%d): down(%p) <count=%d> from %p\n",
+-	       current->comm, task_pid_nr(current), sem,
+-	       atomic_read(&sem->count), __builtin_return_address(0));
+-#endif
+-	return __down_interruptible(sem);
+-}
+-
+-int
+-down_trylock(struct semaphore *sem)
+-{
+-	int ret;
+-
+-#ifdef WAITQUEUE_DEBUG
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-
+-	ret = __down_trylock(sem);
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	printk("%s(%d): down_trylock %s from %p\n",
+-	       current->comm, task_pid_nr(current),
+-	       ret ? "failed" : "acquired",
+-	       __builtin_return_address(0));
+-#endif
+-
+-	return ret;
+-}
+-
+-void
+-up(struct semaphore *sem)
+-{
+-#ifdef WAITQUEUE_DEBUG
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	printk("%s(%d): up(%p) <count=%d> from %p\n",
+-	       current->comm, task_pid_nr(current), sem,
+-	       atomic_read(&sem->count), __builtin_return_address(0));
+-#endif
+-	__up(sem);
+-}
+diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
+index 920196b..a7f23b5 100644
+--- a/arch/alpha/kernel/sys_nautilus.c
++++ b/arch/alpha/kernel/sys_nautilus.c
+@@ -187,6 +187,7 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
+ }
+ 
+ extern void free_reserved_mem(void *, void *);
++extern void pcibios_claim_one_bus(struct pci_bus *);
+ 
+ static struct resource irongate_mem = {
+ 	.name	= "Irongate PCI MEM",
+@@ -205,6 +206,7 @@ nautilus_init_pci(void)
+ 	/* Scan our single hose.  */
+ 	bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
+ 	hose->bus = bus;
++	pcibios_claim_one_bus(bus);
+ 
+ 	irongate = pci_get_bus_and_slot(0, 0);
+ 	bus->self = irongate;
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 4039a13..d8d2532 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -255,6 +255,7 @@ config ARCH_EP93XX
+ 	select ARM_AMBA
+ 	select ARM_VIC
+ 	select GENERIC_GPIO
++	select HAVE_GPIO_LIB
+ 	help
+ 	  This enables support for the Cirrus EP93xx series of CPUs.
+ 
+@@ -377,15 +378,17 @@ config ARCH_MXC
+ 	help
+ 	  Support for Freescale MXC/iMX-based family of processors
+ 
+-config ARCH_ORION
++config ARCH_ORION5X
+ 	bool "Marvell Orion"
+ 	depends on MMU
+ 	select PCI
+ 	select GENERIC_GPIO
+ 	select GENERIC_TIME
+ 	select GENERIC_CLOCKEVENTS
++	select PLAT_ORION
+ 	help
+-	  Support for Marvell Orion System on Chip family.
++	  Support for the following Marvell Orion 5x series SoCs:
++	  Orion-1 (5181), Orion-NAS (5182), Orion-2 (5281.)
+ 
+ config ARCH_PNX4008
+ 	bool "Philips Nexperia PNX4008 Mobile"
+@@ -422,10 +425,15 @@ config ARCH_SA1100
+ 	bool "SA1100-based"
+ 	select ISA
+ 	select ARCH_DISCONTIGMEM_ENABLE
++	select ARCH_SPARSEMEM_ENABLE
++	select ARCH_SELECT_MEMORY_MODEL
+ 	select ARCH_MTD_XIP
+ 	select GENERIC_GPIO
+ 	select GENERIC_TIME
++	select GENERIC_CLOCKEVENTS
++	select TICK_ONESHOT
+ 	select HAVE_IDE
++	select HAVE_GPIO_LIB
+ 	help
+ 	  Support for StrongARM 11x0 based boards.
+ 
+@@ -468,6 +476,7 @@ config ARCH_DAVINCI
+ config ARCH_OMAP
+ 	bool "TI OMAP"
+ 	select GENERIC_GPIO
++	select HAVE_GPIO_LIB
+ 	select GENERIC_TIME
+ 	select GENERIC_CLOCKEVENTS
+ 	help
+@@ -516,7 +525,7 @@ source "arch/arm/mach-omap1/Kconfig"
+ 
+ source "arch/arm/mach-omap2/Kconfig"
+ 
+-source "arch/arm/mach-orion/Kconfig"
++source "arch/arm/mach-orion5x/Kconfig"
+ 
+ source "arch/arm/plat-s3c24xx/Kconfig"
+ source "arch/arm/plat-s3c/Kconfig"
+@@ -563,6 +572,9 @@ config ARCH_ACORN
+ config PLAT_IOP
+ 	bool
+ 
++config PLAT_ORION
++	bool
++
+ source arch/arm/mm/Kconfig
+ 
+ config IWMMXT
+@@ -650,7 +662,7 @@ source "kernel/time/Kconfig"
+ 
+ config SMP
+ 	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
+-	depends on EXPERIMENTAL && REALVIEW_EB_ARM11MP
++	depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP)
+ 	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
+@@ -683,7 +695,7 @@ config HOTPLUG_CPU
+ 
+ config LOCAL_TIMERS
+ 	bool "Use local timer interrupts"
+-	depends on SMP && REALVIEW_EB_ARM11MP
++	depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP)
+ 	default y
+ 	help
+ 	  Enable support for local timers on SMP platforms, rather then the
+@@ -774,6 +786,12 @@ config ARCH_DISCONTIGMEM_ENABLE
+ 	  or have huge holes in the physical address space for other reasons.
+ 	  See <file:Documentation/vm/numa> for more.
+ 
++config ARCH_SPARSEMEM_ENABLE
++	bool
++
++config ARCH_SELECT_MEMORY_MODEL
++	bool
++
+ config NODES_SHIFT
+ 	int
+ 	default "4" if ARCH_LH7A40X
+@@ -1174,6 +1192,8 @@ source "drivers/dma/Kconfig"
+ 
+ source "drivers/dca/Kconfig"
+ 
++source "drivers/uio/Kconfig"
++
+ endmenu
+ 
+ source "fs/Kconfig"
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index 1a46496..e72db27 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -134,12 +134,11 @@ endif
+  machine-$(CONFIG_ARCH_PNX4008)	   := pnx4008
+  machine-$(CONFIG_ARCH_NETX)	   := netx
+  machine-$(CONFIG_ARCH_NS9XXX)	   := ns9xxx
+- textofs-$(CONFIG_ARCH_NS9XXX)	   := 0x00108000
+  machine-$(CONFIG_ARCH_DAVINCI)	   := davinci
+  machine-$(CONFIG_ARCH_KS8695)     := ks8695
+   incdir-$(CONFIG_ARCH_MXC)	   := mxc
+  machine-$(CONFIG_ARCH_MX3)	   := mx3
+- machine-$(CONFIG_ARCH_ORION)	   := orion
++ machine-$(CONFIG_ARCH_ORION5X)	   := orion5x
+  machine-$(CONFIG_ARCH_MSM7X00A)   := msm
+ 
+ ifeq ($(CONFIG_ARCH_EBSA110),y)
+@@ -185,6 +184,7 @@ core-$(CONFIG_VFP)		+= arch/arm/vfp/
+ 
+ # If we have a common platform directory, then include it in the build.
+ core-$(CONFIG_PLAT_IOP)		+= arch/arm/plat-iop/
++core-$(CONFIG_PLAT_ORION)		+= arch/arm/plat-orion/
+ core-$(CONFIG_ARCH_OMAP)	+= arch/arm/plat-omap/
+ core-$(CONFIG_PLAT_S3C24XX)		+= arch/arm/plat-s3c24xx/
+ core-$(CONFIG_ARCH_MXC)		+= arch/arm/plat-mxc/
+diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
+index 25f1230..da226ab 100644
+--- a/arch/arm/boot/Makefile
++++ b/arch/arm/boot/Makefile
+@@ -61,9 +61,15 @@ endif
+ 
+ quiet_cmd_uimage = UIMAGE  $@
+       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
+-		   -C none -a $(ZRELADDR) -e $(ZRELADDR) \
++		   -C none -a $(LOADADDR) -e $(LOADADDR) \
+ 		   -n 'Linux-$(KERNELRELEASE)' -d $< $@
+ 
++ifeq ($(CONFIG_ZBOOT_ROM),y)
++$(obj)/uImage: LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT)
++else
++$(obj)/uImage: LOADADDR=$(ZRELADDR)
++endif
++
+ $(obj)/uImage:	$(obj)/zImage FORCE
+ 	$(call if_changed,uimage)
+ 	@echo '  Image $@ is ready'
+diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
+index f53bca4..aa8f773 100644
+--- a/arch/arm/common/rtctime.c
++++ b/arch/arm/common/rtctime.c
+@@ -22,7 +22,6 @@
+ #include <linux/mutex.h>
+ 
+ #include <asm/rtc.h>
+-#include <asm/semaphore.h>
+ 
+ static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
+ static struct fasync_struct *rtc_async_queue;
+diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
+index 314ebd3..bc299b0 100644
+--- a/arch/arm/common/scoop.c
++++ b/arch/arm/common/scoop.c
+@@ -16,6 +16,7 @@
+ #include <linux/slab.h>
+ #include <linux/platform_device.h>
+ #include <asm/io.h>
++#include <asm/gpio.h>
+ #include <asm/hardware/scoop.h>
+ 
+ /* PCMCIA to Scoop linkage
+@@ -30,10 +31,9 @@
+ struct scoop_pcmcia_config *platform_scoop_config;
+ EXPORT_SYMBOL(platform_scoop_config);
+ 
+-#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
+-
+ struct  scoop_dev {
+-	void  *base;
++	void __iomem *base;
++	struct gpio_chip gpio;
+ 	spinlock_t scoop_lock;
+ 	unsigned short suspend_clr;
+ 	unsigned short suspend_set;
+@@ -44,13 +44,84 @@ void reset_scoop(struct device *dev)
+ {
+ 	struct scoop_dev *sdev = dev_get_drvdata(dev);
+ 
+-	SCOOP_REG(sdev->base,SCOOP_MCR) = 0x0100;  // 00
+-	SCOOP_REG(sdev->base,SCOOP_CDR) = 0x0000;  // 04
+-	SCOOP_REG(sdev->base,SCOOP_CCR) = 0x0000;  // 10
+-	SCOOP_REG(sdev->base,SCOOP_IMR) = 0x0000;  // 18
+-	SCOOP_REG(sdev->base,SCOOP_IRM) = 0x00FF;  // 14
+-	SCOOP_REG(sdev->base,SCOOP_ISR) = 0x0000;  // 1C
+-	SCOOP_REG(sdev->base,SCOOP_IRM) = 0x0000;
++	iowrite16(0x0100, sdev->base + SCOOP_MCR);  // 00
++	iowrite16(0x0000, sdev->base + SCOOP_CDR);  // 04
++	iowrite16(0x0000, sdev->base + SCOOP_CCR);  // 10
++	iowrite16(0x0000, sdev->base + SCOOP_IMR);  // 18
++	iowrite16(0x00FF, sdev->base + SCOOP_IRM);  // 14
++	iowrite16(0x0000, sdev->base + SCOOP_ISR);  // 1C
++	iowrite16(0x0000, sdev->base + SCOOP_IRM);
++}
++
++static void __scoop_gpio_set(struct scoop_dev *sdev,
++			unsigned offset, int value)
++{
++	unsigned short gpwr;
++
++	gpwr = ioread16(sdev->base + SCOOP_GPWR);
++	if (value)
++		gpwr |= 1 << (offset + 1);
++	else
++		gpwr &= ~(1 << (offset + 1));
++	iowrite16(gpwr, sdev->base + SCOOP_GPWR);
++}
++
++static void scoop_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++	struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
++	unsigned long flags;
++
++	spin_lock_irqsave(&sdev->scoop_lock, flags);
++
++	__scoop_gpio_set(sdev, offset, value);
++
++	spin_unlock_irqrestore(&sdev->scoop_lock, flags);
++}
++
++static int scoop_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++	struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
++
++	/* XXX: I'm usure,  but it seems so */
++	return ioread16(sdev->base + SCOOP_GPRR) & (1 << (offset + 1));
++}
++
++static int scoop_gpio_direction_input(struct gpio_chip *chip,
++			unsigned offset)
++{
++	struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
++	unsigned long flags;
++	unsigned short gpcr;
++
++	spin_lock_irqsave(&sdev->scoop_lock, flags);
++
++	gpcr = ioread16(sdev->base + SCOOP_GPCR);
++	gpcr &= ~(1 << (offset + 1));
++	iowrite16(gpcr, sdev->base + SCOOP_GPCR);
++
++	spin_unlock_irqrestore(&sdev->scoop_lock, flags);
++
++	return 0;
++}
++
++static int scoop_gpio_direction_output(struct gpio_chip *chip,
++			unsigned offset, int value)
++{
++	struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
++	unsigned long flags;
++	unsigned short gpcr;
++
++	spin_lock_irqsave(&sdev->scoop_lock, flags);
++
++	__scoop_gpio_set(sdev, offset, value);
++
++	gpcr = ioread16(sdev->base + SCOOP_GPCR);
++	gpcr |= 1 << (offset + 1);
++	iowrite16(gpcr, sdev->base + SCOOP_GPCR);
++
++	spin_unlock_irqrestore(&sdev->scoop_lock, flags);
++
++	return 0;
+ }
+ 
+ unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
+@@ -60,8 +131,8 @@ unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
+ 	struct scoop_dev *sdev = dev_get_drvdata(dev);
+ 
+ 	spin_lock_irqsave(&sdev->scoop_lock, flag);
+-	gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) | bit;
+-	SCOOP_REG(sdev->base, SCOOP_GPWR) = gpio_bit;
++	gpio_bit = ioread16(sdev->base + SCOOP_GPWR) | bit;
++	iowrite16(gpio_bit, sdev->base + SCOOP_GPWR);
+ 	spin_unlock_irqrestore(&sdev->scoop_lock, flag);
+ 
+ 	return gpio_bit;
+@@ -74,8 +145,8 @@ unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit)
+ 	struct scoop_dev *sdev = dev_get_drvdata(dev);
+ 
+ 	spin_lock_irqsave(&sdev->scoop_lock, flag);
+-	gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) & ~bit;
+-	SCOOP_REG(sdev->base,SCOOP_GPWR) = gpio_bit;
++	gpio_bit = ioread16(sdev->base + SCOOP_GPWR) & ~bit;
++	iowrite16(gpio_bit, sdev->base + SCOOP_GPWR);
+ 	spin_unlock_irqrestore(&sdev->scoop_lock, flag);
+ 
+ 	return gpio_bit;
+@@ -87,13 +158,13 @@ EXPORT_SYMBOL(reset_scoop_gpio);
+ unsigned short read_scoop_reg(struct device *dev, unsigned short reg)
+ {
+ 	struct scoop_dev *sdev = dev_get_drvdata(dev);
+-	return SCOOP_REG(sdev->base,reg);
++	return ioread16(sdev->base + reg);
+ }
+ 
+ void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data)
+ {
+ 	struct scoop_dev *sdev = dev_get_drvdata(dev);
+-	SCOOP_REG(sdev->base,reg)=data;
++	iowrite16(data, sdev->base + reg);
+ }
+ 
+ EXPORT_SYMBOL(reset_scoop);
+@@ -104,9 +175,9 @@ static void check_scoop_reg(struct scoop_dev *sdev)
+ {
+ 	unsigned short mcr;
+ 
+-	mcr = SCOOP_REG(sdev->base, SCOOP_MCR);
++	mcr = ioread16(sdev->base + SCOOP_MCR);
+ 	if ((mcr & 0x100) == 0)
+-		SCOOP_REG(sdev->base, SCOOP_MCR) = 0x0101;
++		iowrite16(0x0101, sdev->base + SCOOP_MCR);
+ }
+ 
+ #ifdef CONFIG_PM
+@@ -115,8 +186,8 @@ static int scoop_suspend(struct platform_device *dev, pm_message_t state)
+ 	struct scoop_dev *sdev = platform_get_drvdata(dev);
+ 
+ 	check_scoop_reg(sdev);
+-	sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
+-	SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
++	sdev->scoop_gpwr = ioread16(sdev->base + SCOOP_GPWR);
++	iowrite16((sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set, sdev->base + SCOOP_GPWR);
+ 
+ 	return 0;
+ }
+@@ -126,7 +197,7 @@ static int scoop_resume(struct platform_device *dev)
+ 	struct scoop_dev *sdev = platform_get_drvdata(dev);
+ 
+ 	check_scoop_reg(sdev);
+-	SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
++	iowrite16(sdev->scoop_gpwr, sdev->base + SCOOP_GPWR);
+ 
+ 	return 0;
+ }
+@@ -135,11 +206,13 @@ static int scoop_resume(struct platform_device *dev)
+ #define scoop_resume	NULL
+ #endif
+ 
+-int __init scoop_probe(struct platform_device *pdev)
++static int __devinit scoop_probe(struct platform_device *pdev)
+ {
+ 	struct scoop_dev *devptr;
+ 	struct scoop_config *inf;
+ 	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	int ret;
++	int temp;
+ 
+ 	if (!mem)
+ 		return -EINVAL;
+@@ -154,40 +227,78 @@ int __init scoop_probe(struct platform_device *pdev)
+ 	devptr->base = ioremap(mem->start, mem->end - mem->start + 1);
+ 
+ 	if (!devptr->base) {
+-		kfree(devptr);
+-		return -ENOMEM;
++		ret = -ENOMEM;
++		goto err_ioremap;
+ 	}
+ 
+ 	platform_set_drvdata(pdev, devptr);
+ 
+-	printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base);
++	printk("Sharp Scoop Device found at 0x%08x -> 0x%8p\n",(unsigned int)mem->start, devptr->base);
+ 
+-	SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140;
++	iowrite16(0x0140, devptr->base + SCOOP_MCR);
+ 	reset_scoop(&pdev->dev);
+-	SCOOP_REG(devptr->base, SCOOP_CPR) = 0x0000;
+-	SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff;
+-	SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff;
++	iowrite16(0x0000, devptr->base + SCOOP_CPR);
++	iowrite16(inf->io_dir & 0xffff, devptr->base + SCOOP_GPCR);
++	iowrite16(inf->io_out & 0xffff, devptr->base + SCOOP_GPWR);
+ 
+ 	devptr->suspend_clr = inf->suspend_clr;
+ 	devptr->suspend_set = inf->suspend_set;
+ 
++	devptr->gpio.base = -1;
++
++	if (inf->gpio_base != 0) {
++		devptr->gpio.label = pdev->dev.bus_id;
++		devptr->gpio.base = inf->gpio_base;
++		devptr->gpio.ngpio = 12; /* PA11 = 0, PA12 = 1, etc. up to PA22 = 11 */
++		devptr->gpio.set = scoop_gpio_set;
++		devptr->gpio.get = scoop_gpio_get;
++		devptr->gpio.direction_input = scoop_gpio_direction_input;
++		devptr->gpio.direction_output = scoop_gpio_direction_output;
++
++		ret = gpiochip_add(&devptr->gpio);
++		if (ret)
++			goto err_gpio;
++	}
++
+ 	return 0;
++
++	if (devptr->gpio.base != -1)
++		temp = gpiochip_remove(&devptr->gpio);
++err_gpio:
++	platform_set_drvdata(pdev, NULL);
++err_ioremap:
++	iounmap(devptr->base);
++	kfree(devptr);
++
++	return ret;
+ }
+ 
+-static int scoop_remove(struct platform_device *pdev)
++static int __devexit scoop_remove(struct platform_device *pdev)
+ {
+ 	struct scoop_dev *sdev = platform_get_drvdata(pdev);
+-	if (sdev) {
+-		iounmap(sdev->base);
+-		kfree(sdev);
+-		platform_set_drvdata(pdev, NULL);
++	int ret;
++
++	if (!sdev)
++		return -EINVAL;
++
++	if (sdev->gpio.base != -1) {
++		ret = gpiochip_remove(&sdev->gpio);
++		if (ret) {
++			dev_err(&pdev->dev, "Can't remove gpio chip: %d\n", ret);
++			return ret;
++		}
+ 	}
++
++	platform_set_drvdata(pdev, NULL);
++	iounmap(sdev->base);
++	kfree(sdev);
++
+ 	return 0;
+ }
+ 
+ static struct platform_driver scoop_driver = {
+ 	.probe		= scoop_probe,
+-	.remove 	= scoop_remove,
++	.remove		= __devexit_p(scoop_remove),
+ 	.suspend	= scoop_suspend,
+ 	.resume		= scoop_resume,
+ 	.driver		= {
+@@ -195,7 +306,7 @@ static struct platform_driver scoop_driver = {
+ 	},
+ };
+ 
+-int __init scoop_init(void)
++static int __init scoop_init(void)
+ {
+ 	return platform_driver_register(&scoop_driver);
+ }
+diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
+new file mode 100644
+index 0000000..dc030cf
+--- /dev/null
++++ b/arch/arm/configs/am200epdkit_defconfig
+@@ -0,0 +1,1149 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc3
++# Sun Mar  9 06:33:33 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ARCH_SUPPORTS_AOUT=y
++CONFIG_ZONE_DMA=y
++CONFIG_ARCH_MTD_XIP=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION="gum"
++CONFIG_LOCALVERSION_AUTO=y
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=17
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++# CONFIG_BLK_DEV_INITRD is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++# CONFIG_SHMEM is not set
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION is not set
++# CONFIG_ARCH_PNX4008 is not set
++CONFIG_ARCH_PXA=y
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM7X00A is not set
++
++#
++# Intel PXA2xx/PXA3xx Implementations
++#
++CONFIG_ARCH_GUMSTIX=y
++# CONFIG_ARCH_LUBBOCK is not set
++# CONFIG_MACH_LOGICPD_PXA270 is not set
++# CONFIG_MACH_MAINSTONE is not set
++# CONFIG_ARCH_PXA_IDP is not set
++# CONFIG_PXA_SHARPSL is not set
++# CONFIG_ARCH_PXA_ESERIES is not set
++# CONFIG_MACH_TRIZEPS4 is not set
++# CONFIG_MACH_EM_X270 is not set
++# CONFIG_MACH_COLIBRI is not set
++# CONFIG_MACH_ZYLONITE is not set
++# CONFIG_MACH_LITTLETON is not set
++# CONFIG_MACH_ARMCORE is not set
++# CONFIG_MACH_MAGICIAN is not set
++# CONFIG_MACH_PCM027 is not set
++CONFIG_MACH_GUMSTIX_F=y
++CONFIG_PXA25x=y
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_XSCALE=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5T=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_OUTER_CACHE is not set
++# CONFIG_IWMMXT is not set
++CONFIG_XSCALE_PMU=y
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++CONFIG_PCCARD=y
++# CONFIG_PCMCIA_DEBUG is not set
++CONFIG_PCMCIA=y
++CONFIG_PCMCIA_LOAD_CIS=y
++# CONFIG_PCMCIA_IOCTL is not set
++
++#
++# PC-card bridges
++#
++CONFIG_PCMCIA_PXA2XX=y
++
++#
++# Kernel Features
++#
++CONFIG_TICK_ONESHOT=y
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_PREEMPT=y
++CONFIG_HZ=100
++CONFIG_AEABI=y
++# CONFIG_OABI_COMPAT is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=ttyS0,115200n8 root=1f01 rootfstype=jffs2"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=m
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++CONFIG_BT=m
++CONFIG_BT_L2CAP=m
++CONFIG_BT_SCO=m
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++# CONFIG_BT_BNEP_MC_FILTER is not set
++# CONFIG_BT_BNEP_PROTO_FILTER is not set
++# CONFIG_BT_HIDP is not set
++
++#
++# Bluetooth device drivers
++#
++# CONFIG_BT_HCIBTSDIO is not set
++CONFIG_BT_HCIUART=m
++CONFIG_BT_HCIUART_H4=y
++# CONFIG_BT_HCIUART_BCSP is not set
++# CONFIG_BT_HCIUART_LL is not set
++# CONFIG_BT_HCIDTL1 is not set
++# CONFIG_BT_HCIBT3C is not set
++# CONFIG_BT_HCIBLUECARD is not set
++# CONFIG_BT_HCIBTUART is not set
++# CONFIG_BT_HCIVHCI is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_EXT=y
++# CONFIG_MAC80211 is not set
++CONFIG_IEEE80211=m
++# CONFIG_IEEE80211_DEBUG is not set
++CONFIG_IEEE80211_CRYPT_WEP=m
++# CONFIG_IEEE80211_CRYPT_CCMP is not set
++# CONFIG_IEEE80211_CRYPT_TKIP is not set
++# CONFIG_IEEE80211_SOFTMAC is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++# CONFIG_MTD_CFI_I2 is not set
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PXA2XX=y
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_SHARP_SL is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=m
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=m
++CONFIG_IDE_MAX_HWIFS=2
++CONFIG_BLK_DEV_IDE=m
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=m
++# CONFIG_IDEDISK_MULTI_MODE is not set
++CONFIG_BLK_DEV_IDECS=m
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=m
++# CONFIG_BLK_DEV_PLATFORM is not set
++# CONFIG_BLK_DEV_IDEDMA is not set
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=m
++# CONFIG_AX88796 is not set
++CONFIG_SMC91X=m
++# CONFIG_DM9000 is not set
++# CONFIG_SMC911X is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_NET_PCMCIA is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_PXA=y
++CONFIG_SERIAL_PXA_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++
++#
++# PCMCIA character devices
++#
++# CONFIG_SYNCLINK_CS is not set
++# CONFIG_CARDMAN_4000 is not set
++# CONFIG_CARDMAN_4040 is not set
++# CONFIG_IPWIRELESS is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++CONFIG_HAVE_GPIO_LIB=y
++
++#
++# GPIO Support
++#
++# CONFIG_DEBUG_GPIO is not set
++
++#
++# I2C GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_SA1100_WATCHDOG=m
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++CONFIG_FB_SYS_FILLRECT=m
++CONFIG_FB_SYS_COPYAREA=m
++CONFIG_FB_SYS_IMAGEBLIT=m
++CONFIG_FB_SYS_FOPS=m
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++CONFIG_FB_MODE_HELPERS=y
++CONFIG_FB_TILEBLITTING=y
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_PXA=y
++CONFIG_FB_PXA_PARAMETERS=y
++CONFIG_FB_MBX=m
++CONFIG_FB_VIRTUAL=m
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE is not set
++# CONFIG_LOGO is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=m
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=m
++CONFIG_SND_TIMER=m
++CONFIG_SND_PCM=m
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=m
++CONFIG_SND_PCM_OSS=m
++CONFIG_SND_PCM_OSS_PLUGINS=y
++# CONFIG_SND_DYNAMIC_MINORS is not set
++# CONFIG_SND_SUPPORT_OLD_API is not set
++# CONFIG_SND_VERBOSE_PROCFS is not set
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++CONFIG_SND_AC97_CODEC=m
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++CONFIG_SND_PXA2XX_PCM=m
++CONFIG_SND_PXA2XX_AC97=m
++
++#
++# PCMCIA devices
++#
++# CONFIG_SND_VXPOCKET is not set
++# CONFIG_SND_PDAUDIOCF is not set
++
++#
++# System on Chip audio support
++#
++# CONFIG_SND_SOC is not set
++
++#
++# SoC Audio support for SuperH
++#
++
++#
++# ALSA SoC audio for Freescale SOCs
++#
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=m
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++CONFIG_USB_GADGET_PXA2XX=y
++CONFIG_USB_PXA2XX=y
++# CONFIG_USB_PXA2XX_SMALL is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++# CONFIG_USB_GADGET_DUALSPEED is not set
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_PXA=y
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_DNOTIFY is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++CONFIG_JFFS2_RUBIN=y
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_DETECT_SOFTLOCKUP is not set
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_PREEMPT is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_LL is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=m
++CONFIG_CRYPTO_BLKCIPHER=m
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=m
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=m
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++CONFIG_CRYPTO_ARC4=m
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
+index e10d003..2dbbbc3 100644
+--- a/arch/arm/configs/at91rm9200dk_defconfig
++++ b/arch/arm/configs/at91rm9200dk_defconfig
+@@ -620,14 +620,14 @@ CONFIG_I2C_CHARDEV=y
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+ 
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+ # CONFIG_I2C_PCA_ISA is not set
+diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
+index 834dddb..6e994f7 100644
+--- a/arch/arm/configs/at91rm9200ek_defconfig
++++ b/arch/arm/configs/at91rm9200ek_defconfig
+@@ -594,14 +594,14 @@ CONFIG_I2C_CHARDEV=y
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+ 
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+ # CONFIG_I2C_PCA_ISA is not set
+diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
+index 46b0c73..f659c93 100644
+--- a/arch/arm/configs/at91sam9260ek_defconfig
++++ b/arch/arm/configs/at91sam9260ek_defconfig
+@@ -1,43 +1,56 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.19-rc6
+-# Fri Nov 17 18:42:21 2006
++# Linux kernel version: 2.6.24-rc7
++# Tue Jan  8 22:20:50 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
+ # CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
+ CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+ 
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ # CONFIG_LOCALVERSION_AUTO is not set
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
+ # CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SYSCTL=y
+@@ -53,30 +66,30 @@ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+ CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+ CONFIG_BLOCK=y
++# CONFIG_LBD is not set
+ # CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+ 
+ #
+ # IO Schedulers
+@@ -108,12 +121,16 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+ # CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+ # CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+@@ -121,29 +138,52 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+ 
+ #
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
+ # Atmel AT91 System-on-Chip
+ #
+ # CONFIG_ARCH_AT91RM9200 is not set
+ CONFIG_ARCH_AT91SAM9260=y
+ # CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
++
++#
++# AT91SAM9260 Variants
++#
++# CONFIG_ARCH_AT91SAM9260_SAM9XE is not set
+ 
+ #
+-# AT91SAM9260 Board Type
++# AT91SAM9260 / AT91SAM9XE Board Type
+ #
+ CONFIG_MACH_AT91SAM9260EK=y
++# CONFIG_MACH_CAM60 is not set
++# CONFIG_MACH_SAM9_L9260 is not set
+ 
+ #
+ # AT91 Board Options
+ #
++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+ # CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
+ 
+ #
+ # AT91 Feature Selections
+ #
+-# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=100
+ 
+ #
+ # Processor Type
+@@ -166,19 +206,19 @@ CONFIG_CPU_CP15_MMU=y
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+ # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
+ 
+ #
+ # Bus support
+ #
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ # CONFIG_PCCARD is not set
+ 
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
+ # CONFIG_PREEMPT is not set
+ # CONFIG_NO_IDLE_HZ is not set
+ CONFIG_HZ=100
+@@ -191,8 +231,12 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
+ # CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
+ 
+@@ -203,6 +247,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+ 
+ #
+ # Floating point emulation
+@@ -228,7 +273,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
+-# CONFIG_APM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+ 
+ #
+ # Networking
+@@ -238,13 +283,9 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-# CONFIG_NETDEBUG is not set
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+@@ -263,33 +304,23 @@ CONFIG_IP_PNP_BOOTP=y
+ # CONFIG_INET_IPCOMP is not set
+ # CONFIG_INET_XFRM_TUNNEL is not set
+ # CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=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=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+ CONFIG_TCP_CONG_CUBIC=y
+ CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
+ # CONFIG_IPV6 is not set
+ # CONFIG_INET6_XFRM_TUNNEL is not set
+ # CONFIG_INET6_TUNNEL is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
+-
+-#
+-# TIPC Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+@@ -302,10 +333,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+ 
+ #
+@@ -315,7 +342,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+ 
+ #
+ # Device Drivers
+@@ -324,34 +361,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ # CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ # CONFIG_BLK_DEV_LOOP is not set
+ # CONFIG_BLK_DEV_NBD is not set
+@@ -360,15 +380,19 @@ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-CONFIG_BLK_DEV_INITRD=y
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+ 
+ #
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+ 
+@@ -388,6 +412,8 @@ CONFIG_BLK_DEV_SD=y
+ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+ 
+ #
+ # SCSI Transports
+@@ -395,43 +421,72 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
++# CONFIG_ATA is not set
+ # CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_MACB=y
++# CONFIG_AX88796 is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+ 
+ #
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
++# USB Network Adapters
+ #
+-# CONFIG_NETDEVICES is not set
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+ 
+ #
+@@ -439,6 +494,7 @@ CONFIG_SCSI_MULTI_LUN=y
+ #
+ CONFIG_INPUT=y
+ # CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+ 
+ #
+ # Userland interfaces
+@@ -448,7 +504,6 @@ CONFIG_INPUT_MOUSEDEV=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+ 
+@@ -458,6 +513,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ # CONFIG_INPUT_TOUCHSCREEN is not set
+ # CONFIG_INPUT_MISC is not set
+ 
+@@ -492,114 +548,131 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM is not set
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
+ 
+ #
+-# Ftape, the floppy tape device driver
++# I2C Algorithms
+ #
+-# CONFIG_RAW_DRIVER is not set
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
+ 
+ #
+-# TPM devices
++# I2C Hardware Bus support
+ #
+-# CONFIG_TCG_TPM is not set
++CONFIG_I2C_GPIO=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_PCA is not set
+ 
+ #
+-# I2C support
++# Miscellaneous I2C Chip support
+ #
+-# CONFIG_I2C is not set
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
+ 
+ #
+ # SPI support
+ #
+ # CONFIG_SPI is not set
+ # CONFIG_SPI_MASTER is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+ # CONFIG_W1 is not set
+-
+-#
+-# Hardware Monitoring support
+-#
++# CONFIG_POWER_SUPPLY is not set
+ # CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+ 
+ #
+-# Misc devices
++# Watchdog Device Drivers
+ #
+-# CONFIG_TIFM_CORE is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91SAM9_WATCHDOG=y
+ 
+ #
+-# LED devices
++# USB-based Watchdog Cards
+ #
+-# CONFIG_NEW_LEDS is not set
++# CONFIG_USBPCWATCHDOG is not set
+ 
+ #
+-# LED drivers
++# Sonics Silicon Backplane
+ #
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+ 
+ #
+-# LED Triggers
++# Multifunction device drivers
+ #
++# CONFIG_MFD_SM501 is not set
+ 
+ #
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
+ 
+ #
+-# Digital Video Broadcasting Devices
++# Graphics support
+ #
+-# CONFIG_DVB is not set
+-# CONFIG_USB_DABUSB is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+ 
+ #
+-# Graphics support
++# Display device support
+ #
+-# CONFIG_FIRMWARE_EDID is not set
+-# CONFIG_FB is not set
++# CONFIG_DISPLAY_SUPPORT is not set
+ 
+ #
+ # Console display driver support
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+ 
+ #
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
+ 
+ #
+-# USB support
++# USB Input Devices
+ #
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+ # CONFIG_USB_ARCH_HAS_EHCI is not set
+@@ -610,7 +683,7 @@ CONFIG_USB=y
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+ # CONFIG_USB_OTG is not set
+ 
+@@ -619,9 +692,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+ 
+ #
+ # USB Device Class drivers
+@@ -640,6 +715,7 @@ CONFIG_USB_STORAGE=y
+ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+@@ -650,43 +726,10 @@ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_LIBUSUAL is not set
+ 
+ #
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_TOUCHSCREEN is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_ATI_REMOTE2 is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
+-
+-#
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET_MII is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+ 
+ #
+@@ -708,6 +751,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
+ # CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+@@ -717,6 +761,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
+ # CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
+ 
+ #
+@@ -727,13 +772,19 @@ CONFIG_USB_MON=y
+ # USB Gadget Support
+ #
+ CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
+ # CONFIG_USB_GADGET_DEBUG_FILES is not set
+ CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
+ # CONFIG_USB_GADGET_LH7A40X is not set
+ # CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
+ CONFIG_USB_GADGET_AT91=y
+ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+@@ -745,17 +796,56 @@ CONFIG_USB_FILE_STORAGE=m
+ # CONFIG_USB_FILE_STORAGE_TEST is not set
+ CONFIG_USB_G_SERIAL=m
+ # CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
+ 
+ #
+-# MMC/SD Card support
++# RTC interfaces
+ #
+-# CONFIG_MMC is not set
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
+ 
+ #
+-# Real Time Clock
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
+ #
+-CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91SAM9=y
+ 
+ #
+ # File systems
+@@ -806,7 +896,6 @@ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+ 
+ #
+@@ -825,10 +914,7 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ # CONFIG_NFS_FS is not set
+ # CONFIG_NFSD is not set
+ # CONFIG_SMB_FS is not set
+@@ -836,17 +922,12 @@ CONFIG_CRAMFS=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+ 
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+@@ -887,41 +968,49 @@ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+-
+-#
+-# Profiling support
+-#
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+ 
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
+ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_SLAB is not set
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_RWSEMS is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_FS is not set
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
+ CONFIG_FORCED_INLINING=y
+-# CONFIG_HEADERS_CHECK is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -932,18 +1021,21 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ # CONFIG_CRYPTO is not set
+ 
+ #
+ # Library routines
+ #
++CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig
+index fcd8fa0..3802e85 100644
+--- a/arch/arm/configs/at91sam9261ek_defconfig
++++ b/arch/arm/configs/at91sam9261ek_defconfig
+@@ -1,43 +1,56 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.19-rc6
+-# Fri Nov 17 18:00:38 2006
++# Linux kernel version: 2.6.24-rc7
++# Tue Jan  8 22:21:49 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
+ # CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
+ CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+ 
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ # CONFIG_LOCALVERSION_AUTO is not set
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
+ # CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SYSCTL=y
+@@ -53,30 +66,30 @@ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+ CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+ CONFIG_BLOCK=y
++# CONFIG_LBD is not set
+ # CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+ 
+ #
+ # IO Schedulers
+@@ -108,12 +121,16 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+ # CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+ # CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+@@ -121,14 +138,27 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+ 
+ #
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
+ # Atmel AT91 System-on-Chip
+ #
+ # CONFIG_ARCH_AT91RM9200 is not set
+ # CONFIG_ARCH_AT91SAM9260 is not set
+ CONFIG_ARCH_AT91SAM9261=y
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
+ 
+ #
+ # AT91SAM9261 Board Type
+@@ -138,12 +168,15 @@ CONFIG_MACH_AT91SAM9261EK=y
+ #
+ # AT91 Board Options
+ #
++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+ # CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
+ 
+ #
+ # AT91 Feature Selections
+ #
+-# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=100
+ 
+ #
+ # Processor Type
+@@ -166,19 +199,19 @@ CONFIG_CPU_CP15_MMU=y
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+ # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
+ 
+ #
+ # Bus support
+ #
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ # CONFIG_PCCARD is not set
+ 
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
+ # CONFIG_PREEMPT is not set
+ # CONFIG_NO_IDLE_HZ is not set
+ CONFIG_HZ=100
+@@ -191,8 +224,12 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
+ # CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
+ 
+@@ -203,6 +240,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+ 
+ #
+ # Floating point emulation
+@@ -228,7 +266,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
+-# CONFIG_APM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+ 
+ #
+ # Networking
+@@ -238,13 +276,13 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-# CONFIG_NETDEBUG is not set
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
+ CONFIG_XFRM=y
+ # CONFIG_XFRM_USER is not set
+ # CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+@@ -266,30 +304,20 @@ CONFIG_IP_PNP_BOOTP=y
+ CONFIG_INET_XFRM_MODE_TRANSPORT=y
+ CONFIG_INET_XFRM_MODE_TUNNEL=y
+ CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+ CONFIG_TCP_CONG_CUBIC=y
+ CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
+ # CONFIG_IPV6 is not set
+ # CONFIG_INET6_XFRM_TUNNEL is not set
+ # CONFIG_INET6_TUNNEL is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
+-
+-#
+-# TIPC Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+@@ -302,10 +330,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+ 
+ #
+@@ -315,7 +339,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+ 
+ #
+ # Device Drivers
+@@ -324,20 +358,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ # CONFIG_MTD_CONCAT is not set
+@@ -350,12 +378,14 @@ CONFIG_MTD_CMDLINE_PARTS=y
+ # User Modules And Translation Layers
+ #
+ # CONFIG_MTD_CHAR is not set
++CONFIG_MTD_BLKDEVS=y
+ CONFIG_MTD_BLOCK=y
+ # CONFIG_FTL is not set
+ # CONFIG_NFTL is not set
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
+ # CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+ 
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -375,7 +405,6 @@ CONFIG_MTD_CFI_I2=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+ 
+ #
+ # Mapping drivers for chip access
+@@ -386,6 +415,8 @@ CONFIG_MTD_CFI_I2=y
+ #
+ # Self-contained MTD device drivers
+ #
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
+ # CONFIG_MTD_SLRAM is not set
+ # CONFIG_MTD_PHRAM is not set
+ # CONFIG_MTD_MTDRAM is not set
+@@ -397,35 +428,24 @@ CONFIG_MTD_CFI_I2=y
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ CONFIG_MTD_NAND=y
+ # CONFIG_MTD_NAND_VERIFY_WRITE is not set
+ # CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ CONFIG_MTD_NAND_IDS=y
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
+ CONFIG_MTD_NAND_AT91=y
+ # CONFIG_MTD_NAND_NANDSIM is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
+ # CONFIG_MTD_ONENAND is not set
+ 
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ # CONFIG_BLK_DEV_LOOP is not set
+ # CONFIG_BLK_DEV_NBD is not set
+@@ -434,15 +454,19 @@ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-CONFIG_BLK_DEV_INITRD=y
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+ 
+ #
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+ 
+@@ -462,6 +486,8 @@ CONFIG_BLK_DEV_SD=y
+ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+ 
+ #
+ # SCSI Transports
+@@ -469,75 +495,49 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
++# CONFIG_ATA is not set
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+-
+-#
+-# PHY device support
+-#
++# CONFIG_VETH is not set
+ # CONFIG_PHYLIB is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
++# CONFIG_AX88796 is not set
+ # CONFIG_SMC91X is not set
+ CONFIG_DM9000=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
+ 
+ #
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
++# Wireless LAN
+ #
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+ 
+ #
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# Wan interfaces
++# USB Network Adapters
+ #
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+@@ -545,10 +545,6 @@ CONFIG_DM9000=y
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+ 
+ #
+@@ -556,6 +552,7 @@ CONFIG_DM9000=y
+ #
+ CONFIG_INPUT=y
+ # CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+ 
+ #
+ # Userland interfaces
+@@ -565,23 +562,43 @@ CONFIG_INPUT_MOUSEDEV=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+ 
+ #
+ # Input Device Drivers
+ #
+-# CONFIG_INPUT_KEYBOARD is not set
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++CONFIG_KEYBOARD_GPIO=y
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ADS7846=y
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++# CONFIG_TOUCHSCREEN_PENMOUNT is not set
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++# CONFIG_TOUCHSCREEN_UCB1400 is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+ # CONFIG_INPUT_MISC is not set
+ 
+ #
+ # Hardware I/O ports
+ #
+-# CONFIG_SERIO is not set
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_RAW is not set
+ # CONFIG_GAMEPORT is not set
+ 
+ #
+@@ -609,75 +626,47 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+ CONFIG_HW_RANDOM=y
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+-
+-#
+-# Ftape, the floppy tape device driver
+-#
+ # CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+ # CONFIG_TCG_TPM is not set
+-
+-#
+-# I2C support
+-#
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
+ CONFIG_I2C_CHARDEV=y
+ 
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+ 
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
+ # CONFIG_I2C_PCA is not set
+-# CONFIG_I2C_PCA_ISA is not set
+ 
+ #
+ # Miscellaneous I2C Chip support
+ #
+ # CONFIG_SENSORS_DS1337 is not set
+ # CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
+ # CONFIG_SENSORS_EEPROM is not set
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+@@ -686,70 +675,125 @@ CONFIG_I2C_AT91=y
+ #
+ # SPI support
+ #
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
+ 
+ #
+-# Dallas's 1-wire bus
++# SPI Master Controller Drivers
+ #
+-# CONFIG_W1 is not set
++CONFIG_SPI_ATMEL=y
++# CONFIG_SPI_BITBANG is not set
+ 
+ #
+-# Hardware Monitoring support
++# SPI Protocol Masters
+ #
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
+ # CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+ 
+ #
+-# Misc devices
++# Watchdog Device Drivers
+ #
+-# CONFIG_TIFM_CORE is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91SAM9_WATCHDOG=y
+ 
+ #
+-# LED devices
++# USB-based Watchdog Cards
+ #
+-# CONFIG_NEW_LEDS is not set
++# CONFIG_USBPCWATCHDOG is not set
+ 
+ #
+-# LED drivers
++# Sonics Silicon Backplane
+ #
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+ 
+ #
+-# LED Triggers
++# Multifunction device drivers
+ #
++# CONFIG_MFD_SM501 is not set
+ 
+ #
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
+ # CONFIG_USB_DABUSB is not set
+ 
+ #
+ # Graphics support
+ #
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
+ # CONFIG_FIRMWARE_EDID is not set
+-# CONFIG_FB is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D15605 is not set
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_ATMEL=y
++# CONFIG_FB_INTSRAM is not set
++# CONFIG_FB_ATMEL_STN is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+ 
+ #
+ # Console display driver support
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++# CONFIG_FRAMEBUFFER_CONSOLE is not set
++# CONFIG_LOGO is not set
+ 
+ #
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
+ 
+ #
+-# USB support
++# USB Input Devices
+ #
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+ # CONFIG_USB_ARCH_HAS_EHCI is not set
+@@ -760,7 +804,7 @@ CONFIG_USB=y
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+ # CONFIG_USB_OTG is not set
+ 
+@@ -769,9 +813,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+ 
+ #
+ # USB Device Class drivers
+@@ -790,6 +836,7 @@ CONFIG_USB_STORAGE=y
+ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+@@ -800,43 +847,10 @@ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_LIBUSUAL is not set
+ 
+ #
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_TOUCHSCREEN is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_ATI_REMOTE2 is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
+-
+-#
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET_MII is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+ 
+ #
+@@ -858,6 +872,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
+ # CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+@@ -867,6 +882,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
+ # CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
+ 
+ #
+@@ -877,13 +893,19 @@ CONFIG_USB_MON=y
+ # USB Gadget Support
+ #
+ CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
+ # CONFIG_USB_GADGET_DEBUG_FILES is not set
+ CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
+ # CONFIG_USB_GADGET_LH7A40X is not set
+ # CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
+ CONFIG_USB_GADGET_AT91=y
+ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+@@ -895,21 +917,73 @@ CONFIG_USB_FILE_STORAGE=m
+ # CONFIG_USB_FILE_STORAGE_TEST is not set
+ CONFIG_USB_G_SERIAL=m
+ # CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
+ 
+ #
+-# MMC/SD Card support
++# MMC/SD Card Drivers
+ #
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+ CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_AT91=m
+-# CONFIG_MMC_TIFM_SD is not set
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
+ 
+ #
+-# Real Time Clock
++# MMC/SD Host Controller Drivers
+ #
++CONFIG_MMC_AT91=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_NEW_LEDS is not set
+ CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91SAM9=y
+ 
+ #
+ # File systems
+@@ -960,7 +1034,6 @@ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+ 
+ #
+@@ -973,7 +1046,6 @@ CONFIG_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
+-# CONFIG_JFFS_FS is not set
+ # CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=y
+ # CONFIG_VXFS_FS is not set
+@@ -981,10 +1053,7 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ # CONFIG_NFS_FS is not set
+ # CONFIG_NFSD is not set
+ # CONFIG_SMB_FS is not set
+@@ -992,17 +1061,12 @@ CONFIG_CRAMFS=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+ 
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+@@ -1043,41 +1107,49 @@ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+-
+-#
+-# Profiling support
+-#
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+ 
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
+ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_SLAB is not set
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_RWSEMS is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_FS is not set
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
+ CONFIG_FORCED_INLINING=y
+-# CONFIG_HEADERS_CHECK is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -1088,18 +1160,21 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ # CONFIG_CRYPTO is not set
+ 
+ #
+ # Library routines
+ #
++CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig
+index c72ab82..32a0d74 100644
+--- a/arch/arm/configs/at91sam9263ek_defconfig
++++ b/arch/arm/configs/at91sam9263ek_defconfig
+@@ -1,12 +1,18 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.20-rc1
+-# Mon Jan  8 16:06:54 2007
++# Linux kernel version: 2.6.24-rc7
++# Tue Jan  8 22:12:20 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
+ # CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
+ CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+@@ -15,32 +21,36 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
+ # CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+ 
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ # CONFIG_LOCALVERSION_AUTO is not set
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ # CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SYSCTL=y
+@@ -56,32 +66,30 @@ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+ CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+ CONFIG_BLOCK=y
+ # CONFIG_LBD is not set
+ # CONFIG_BLK_DEV_IO_TRACE is not set
+ # CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+ 
+ #
+ # IO Schedulers
+@@ -113,13 +121,16 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+ # CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IOP13XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+ # CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+@@ -127,15 +138,27 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+ 
+ #
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
+ # Atmel AT91 System-on-Chip
+ #
+ # CONFIG_ARCH_AT91RM9200 is not set
+ # CONFIG_ARCH_AT91SAM9260 is not set
+ # CONFIG_ARCH_AT91SAM9261 is not set
+ CONFIG_ARCH_AT91SAM9263=y
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
+ 
+ #
+ # AT91SAM9263 Board Type
+@@ -152,6 +175,8 @@ CONFIG_MTD_AT91_DATAFLASH_CARD=y
+ # AT91 Feature Selections
+ #
+ # CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=100
+ 
+ #
+ # Processor Type
+@@ -174,19 +199,19 @@ CONFIG_CPU_CP15_MMU=y
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+ # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
+ 
+ #
+ # Bus support
+ #
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ # CONFIG_PCCARD is not set
+ 
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
+ # CONFIG_PREEMPT is not set
+ # CONFIG_NO_IDLE_HZ is not set
+ CONFIG_HZ=100
+@@ -199,8 +224,12 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
+ # CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
+ 
+@@ -211,6 +240,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+ 
+ #
+ # Floating point emulation
+@@ -236,7 +266,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
+-# CONFIG_APM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+ 
+ #
+ # Networking
+@@ -246,7 +276,6 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-# CONFIG_NETDEBUG is not set
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
+@@ -271,6 +300,7 @@ CONFIG_IP_PNP_RARP=y
+ # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+ # CONFIG_INET_XFRM_MODE_TUNNEL is not set
+ # CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
+ # CONFIG_INET_DIAG is not set
+ # CONFIG_TCP_CONG_ADVANCED is not set
+ CONFIG_TCP_CONG_CUBIC=y
+@@ -281,20 +311,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_INET6_TUNNEL is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
+-
+-#
+-# TIPC Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+@@ -307,10 +325,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+ 
+ #
+@@ -320,7 +334,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+ 
+ #
+ # Device Drivers
+@@ -329,20 +353,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ # CONFIG_MTD_CONCAT is not set
+@@ -362,6 +380,7 @@ CONFIG_MTD_BLOCK=y
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
+ # CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+ 
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -381,7 +400,6 @@ CONFIG_MTD_CFI_I2=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+ 
+ #
+ # Mapping drivers for chip access
+@@ -405,35 +423,24 @@ CONFIG_MTD_DATAFLASH=y
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ CONFIG_MTD_NAND=y
+ # CONFIG_MTD_NAND_VERIFY_WRITE is not set
+ # CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ CONFIG_MTD_NAND_IDS=y
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
+ CONFIG_MTD_NAND_AT91=y
+ # CONFIG_MTD_NAND_NANDSIM is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
+ # CONFIG_MTD_ONENAND is not set
+ 
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+@@ -443,15 +450,18 @@ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-CONFIG_BLK_DEV_INITRD=y
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+ 
+ #
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
+ # CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+@@ -473,6 +483,7 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+ # CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+ 
+ #
+ # SCSI Transports
+@@ -480,80 +491,65 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+-#
+ # CONFIG_ATA is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+-
+-#
+-# PHY device support
+-#
+-# CONFIG_PHYLIB is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
++CONFIG_MACB=y
++# CONFIG_AX88796 is not set
+ # CONFIG_SMC91X is not set
+ # CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++CONFIG_NETDEV_10000=y
+ 
+ #
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
++# Wireless LAN
+ #
+-# CONFIG_NET_RADIO is not set
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+ 
+ #
+-# Wan interfaces
++# USB Network Adapters
+ #
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+@@ -561,10 +557,6 @@ CONFIG_MII=y
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+ 
+ #
+@@ -572,6 +564,7 @@ CONFIG_MII=y
+ #
+ CONFIG_INPUT=y
+ # CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+ 
+ #
+ # Userland interfaces
+@@ -581,20 +574,26 @@ CONFIG_INPUT_MOUSEDEV=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-CONFIG_INPUT_TSDEV=y
+-CONFIG_INPUT_TSDEV_SCREEN_X=240
+-CONFIG_INPUT_TSDEV_SCREEN_Y=320
+ CONFIG_INPUT_EVDEV=y
+ # CONFIG_INPUT_EVBUG is not set
+ 
+ #
+ # Input Device Drivers
+ #
+-# CONFIG_INPUT_KEYBOARD is not set
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++CONFIG_KEYBOARD_GPIO=y
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ CONFIG_INPUT_TOUCHSCREEN=y
+ CONFIG_TOUCHSCREEN_ADS7846=y
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
+ # CONFIG_TOUCHSCREEN_GUNZE is not set
+ # CONFIG_TOUCHSCREEN_ELO is not set
+ # CONFIG_TOUCHSCREEN_MTOUCH is not set
+@@ -603,6 +602,7 @@ CONFIG_TOUCHSCREEN_ADS7846=y
+ # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+ # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+ # CONFIG_TOUCHSCREEN_UCB1400 is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+ # CONFIG_INPUT_MISC is not set
+ 
+ #
+@@ -636,71 +636,47 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+ CONFIG_HW_RANDOM=y
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+ # CONFIG_TCG_TPM is not set
+-
+-#
+-# I2C support
+-#
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
+ CONFIG_I2C_CHARDEV=y
+ 
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+ 
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
+ # CONFIG_I2C_PCA is not set
+-# CONFIG_I2C_PCA_ISA is not set
+ 
+ #
+ # Miscellaneous I2C Chip support
+ #
+ # CONFIG_SENSORS_DS1337 is not set
+ # CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
+ # CONFIG_SENSORS_EEPROM is not set
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+@@ -722,61 +698,80 @@ CONFIG_SPI_ATMEL=y
+ #
+ # SPI Protocol Masters
+ #
+-
+-#
+-# Dallas's 1-wire bus
+-#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
+ # CONFIG_W1 is not set
+-
+-#
+-# Hardware Monitoring support
+-#
++# CONFIG_POWER_SUPPLY is not set
+ # CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+ 
+ #
+-# Misc devices
++# Watchdog Device Drivers
+ #
+-# CONFIG_TIFM_CORE is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91SAM9_WATCHDOG=y
+ 
+ #
+-# LED devices
++# USB-based Watchdog Cards
+ #
+-# CONFIG_NEW_LEDS is not set
++# CONFIG_USBPCWATCHDOG is not set
+ 
+ #
+-# LED drivers
++# Sonics Silicon Backplane
+ #
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+ 
+ #
+-# LED Triggers
++# Multifunction device drivers
+ #
++# CONFIG_MFD_SM501 is not set
+ 
+ #
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
+-# CONFIG_USB_DABUSB is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
+ 
+ #
+ # Graphics support
+ #
+-# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ CONFIG_FB=y
+-# CONFIG_FB_CFB_FILLRECT is not set
+-# CONFIG_FB_CFB_COPYAREA is not set
+-# CONFIG_FB_CFB_IMAGEBLIT is not set
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
+ # CONFIG_FB_MACMODES is not set
+ # CONFIG_FB_BACKLIGHT is not set
+ # CONFIG_FB_MODE_HELPERS is not set
+ # CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D15605 is not set
+ # CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_ATMEL=y
+ # CONFIG_FB_VIRTUAL is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+ 
+ #
+ # Console display driver support
+@@ -784,26 +779,28 @@ CONFIG_FB=y
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+ # CONFIG_FRAMEBUFFER_CONSOLE is not set
+-
+-#
+-# Logo configuration
+-#
+ # CONFIG_LOGO is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+ 
+ #
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
+ 
+ #
+-# HID Devices
++# USB Input Devices
+ #
+-CONFIG_HID=y
++# CONFIG_USB_HID is not set
+ 
+ #
+-# USB support
++# USB HID Boot Protocol drivers
+ #
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+ # CONFIG_USB_ARCH_HAS_EHCI is not set
+@@ -814,9 +811,8 @@ CONFIG_USB=y
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_MULTITHREAD_PROBE is not set
+ # CONFIG_USB_OTG is not set
+ 
+ #
+@@ -824,9 +820,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+ 
+ #
+ # USB Device Class drivers
+@@ -845,6 +843,7 @@ CONFIG_USB_STORAGE=y
+ # CONFIG_USB_STORAGE_DEBUG is not set
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+@@ -856,43 +855,10 @@ CONFIG_USB_STORAGE=y
+ # CONFIG_USB_LIBUSUAL is not set
+ 
+ #
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_TOUCHSCREEN is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_ATI_REMOTE2 is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
+-
+-#
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET_MII is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+ 
+ #
+@@ -914,6 +880,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
+ # CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+@@ -923,6 +890,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
+ # CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
+ 
+ #
+@@ -933,13 +901,19 @@ CONFIG_USB_MON=y
+ # USB Gadget Support
+ #
+ CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
+ # CONFIG_USB_GADGET_DEBUG_FILES is not set
+ CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
+ # CONFIG_USB_GADGET_LH7A40X is not set
+ # CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
+ CONFIG_USB_GADGET_AT91=y
+ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+@@ -951,21 +925,73 @@ CONFIG_USB_FILE_STORAGE=m
+ # CONFIG_USB_FILE_STORAGE_TEST is not set
+ CONFIG_USB_G_SERIAL=m
+ # CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
+ 
+ #
+-# MMC/SD Card support
++# MMC/SD Card Drivers
+ #
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+ CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_AT91=m
+-# CONFIG_MMC_TIFM_SD is not set
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
+ 
+ #
+-# Real Time Clock
++# MMC/SD Host Controller Drivers
+ #
++CONFIG_MMC_AT91=m
++# CONFIG_MMC_SPI is not set
++# CONFIG_NEW_LEDS is not set
+ CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91SAM9=y
+ 
+ #
+ # File systems
+@@ -1016,7 +1042,6 @@ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+ 
+ #
+@@ -1032,10 +1057,12 @@ CONFIG_RAMFS=y
+ CONFIG_JFFS2_FS=y
+ CONFIG_JFFS2_FS_DEBUG=0
+ CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+ # CONFIG_JFFS2_SUMMARY is not set
+ # CONFIG_JFFS2_FS_XATTR is not set
+ # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+ CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
+ CONFIG_JFFS2_RTIME=y
+ # CONFIG_JFFS2_RUBIN is not set
+ CONFIG_CRAMFS=y
+@@ -1044,10 +1071,7 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ # CONFIG_NFS_V3 is not set
+ # CONFIG_NFS_V4 is not set
+@@ -1057,6 +1081,7 @@ CONFIG_ROOT_NFS=y
+ CONFIG_LOCKD=y
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
+ # CONFIG_RPCSEC_GSS_KRB5 is not set
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1064,17 +1089,12 @@ CONFIG_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+ 
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+@@ -1115,36 +1135,35 @@ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+-
+-#
+-# Distributed Lock Manager
+-#
+ # CONFIG_DLM is not set
+-
+-#
+-# Profiling support
+-#
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+ 
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
+ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_UNUSED_SYMBOLS is not set
+ # CONFIG_DEBUG_FS is not set
+ # CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_SLAB is not set
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_RWSEMS is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+@@ -1152,9 +1171,13 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
+ CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -1165,10 +1188,7 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ # CONFIG_CRYPTO is not set
+ 
+ #
+@@ -1177,8 +1197,13 @@ CONFIG_DEBUG_LL=y
+ CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+ CONFIG_PLIST=y
+-CONFIG_IOMAP_COPY=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/at91sam9rlek_defconfig b/arch/arm/configs/at91sam9rlek_defconfig
+index fbe8b30..98e6746 100644
+--- a/arch/arm/configs/at91sam9rlek_defconfig
++++ b/arch/arm/configs/at91sam9rlek_defconfig
+@@ -1,15 +1,18 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.21
+-# Mon May  7 16:30:40 2007
++# Linux kernel version: 2.6.24-rc7
++# Tue Jan  8 22:24:14 2008
+ #
+ CONFIG_ARM=y
+ CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+ CONFIG_GENERIC_GPIO=y
+ # CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
+ CONFIG_MMU=y
+ # CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+@@ -23,27 +26,28 @@ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+ 
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ # CONFIG_LOCALVERSION_AUTO is not set
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
+ CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ # CONFIG_RELAY is not set
+ CONFIG_BLK_DEV_INITRD=y
+@@ -62,32 +66,30 @@ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+ CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+ CONFIG_BLOCK=y
+ # CONFIG_LBD is not set
+ # CONFIG_BLK_DEV_IO_TRACE is not set
+ # CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+ 
+ #
+ # IO Schedulers
+@@ -119,14 +121,16 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+ # CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IOP13XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+ # CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
+ # CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+@@ -134,9 +138,18 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+ 
+ #
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
+ # Atmel AT91 System-on-Chip
+ #
+ # CONFIG_ARCH_AT91RM9200 is not set
+@@ -144,6 +157,8 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_AT91SAM9261 is not set
+ # CONFIG_ARCH_AT91SAM9263 is not set
+ CONFIG_ARCH_AT91SAM9RL=y
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
+ 
+ #
+ # AT91SAM9RL Board Type
+@@ -157,7 +172,9 @@ CONFIG_MACH_AT91SAM9RLEK=y
+ #
+ # AT91 Feature Selections
+ #
+-# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=100
+ 
+ #
+ # Processor Type
+@@ -185,15 +202,14 @@ CONFIG_CPU_CP15_MMU=y
+ #
+ # Bus support
+ #
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ # CONFIG_PCCARD is not set
+ 
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
+ # CONFIG_PREEMPT is not set
+ # CONFIG_NO_IDLE_HZ is not set
+ CONFIG_HZ=100
+@@ -206,9 +222,12 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
+ # CONFIG_RESOURCES_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
+ 
+@@ -245,6 +264,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+ 
+ #
+ # Networking
+@@ -254,7 +274,6 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-# CONFIG_NETDEBUG is not set
+ # CONFIG_PACKET is not set
+ CONFIG_UNIX=y
+ # CONFIG_NET_KEY is not set
+@@ -271,10 +290,6 @@ CONFIG_UNIX=y
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+ 
+ #
+@@ -284,7 +299,16 @@ CONFIG_UNIX=y
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+ 
+ #
+ # Device Drivers
+@@ -293,21 +317,14 @@ CONFIG_UNIX=y
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
+ # CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ CONFIG_MTD_CONCAT=y
+@@ -327,6 +344,7 @@ CONFIG_MTD_BLOCK=y
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
+ # CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+ 
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -346,7 +364,6 @@ CONFIG_MTD_CFI_I2=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+ 
+ #
+ # Mapping drivers for chip access
+@@ -370,36 +387,23 @@ CONFIG_MTD_DATAFLASH=y
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ CONFIG_MTD_NAND=y
+ # CONFIG_MTD_NAND_VERIFY_WRITE is not set
+ # CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ CONFIG_MTD_NAND_IDS=y
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
+ CONFIG_MTD_NAND_AT91=y
+ # CONFIG_MTD_NAND_NANDSIM is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
++# CONFIG_MTD_NAND_PLATFORM is not set
+ # CONFIG_MTD_ONENAND is not set
+ 
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-# CONFIG_PNPACPI is not set
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+@@ -410,12 +414,16 @@ CONFIG_BLK_DEV_RAM_SIZE=24576
+ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+ 
+ #
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
+ # CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+@@ -437,6 +445,7 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+ # CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+ 
+ #
+ # SCSI Transports
+@@ -444,47 +453,13 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+-#
+ # CONFIG_ATA is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ # CONFIG_NETDEVICES is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+ 
+ #
+@@ -492,6 +467,7 @@ CONFIG_SCSI_MULTI_LUN=y
+ #
+ CONFIG_INPUT=y
+ # CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+ 
+ #
+ # Userland interfaces
+@@ -501,7 +477,6 @@ CONFIG_INPUT_MOUSEDEV=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ CONFIG_INPUT_EVDEV=y
+ # CONFIG_INPUT_EVBUG is not set
+ 
+@@ -511,8 +486,10 @@ CONFIG_INPUT_EVDEV=y
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ CONFIG_INPUT_TOUCHSCREEN=y
+ # CONFIG_TOUCHSCREEN_ADS7846 is not set
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
+ # CONFIG_TOUCHSCREEN_GUNZE is not set
+ # CONFIG_TOUCHSCREEN_ELO is not set
+ # CONFIG_TOUCHSCREEN_MTOUCH is not set
+@@ -521,6 +498,7 @@ CONFIG_INPUT_TOUCHSCREEN=y
+ # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+ # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+ # CONFIG_TOUCHSCREEN_UCB1400 is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+ # CONFIG_INPUT_MISC is not set
+ 
+ #
+@@ -554,37 +532,50 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM is not set
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
+ 
+ #
+-# TPM devices
++# I2C Algorithms
+ #
+-# CONFIG_TCG_TPM is not set
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
+ 
+ #
+-# I2C support
++# I2C Hardware Bus support
+ #
+-# CONFIG_I2C is not set
++CONFIG_I2C_GPIO=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
+ 
+ #
+ # SPI support
+@@ -603,21 +594,25 @@ CONFIG_SPI_ATMEL=y
+ # SPI Protocol Masters
+ #
+ # CONFIG_SPI_AT25 is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
+ # CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+ 
+ #
+-# Hardware Monitoring support
++# Watchdog Device Drivers
+ #
+-# CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91SAM9_WATCHDOG=y
+ 
+ #
+-# Misc devices
++# Sonics Silicon Backplane
+ #
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+ 
+ #
+ # Multifunction device drivers
+@@ -625,37 +620,28 @@ CONFIG_SPI_ATMEL=y
+ # CONFIG_MFD_SM501 is not set
+ 
+ #
+-# LED devices
+-#
+-# CONFIG_NEW_LEDS is not set
+-
+-#
+-# LED drivers
+-#
+-
+-#
+-# LED Triggers
+-#
+-
+-#
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
++# CONFIG_DAB is not set
+ 
+ #
+ # Graphics support
+ #
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ CONFIG_FB=y
+ # CONFIG_FIRMWARE_EDID is not set
+ # CONFIG_FB_DDC is not set
+ CONFIG_FB_CFB_FILLRECT=y
+ CONFIG_FB_CFB_COPYAREA=y
+ CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
+ # CONFIG_FB_SVGALIB is not set
+ # CONFIG_FB_MACMODES is not set
+ # CONFIG_FB_BACKLIGHT is not set
+@@ -665,9 +651,16 @@ CONFIG_FB_CFB_IMAGEBLIT=y
+ #
+ # Frame buffer hardware drivers
+ #
++# CONFIG_FB_S1D15605 is not set
+ # CONFIG_FB_S1D13XXX is not set
+ CONFIG_FB_ATMEL=y
+ # CONFIG_FB_VIRTUAL is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+ 
+ #
+ # Console display driver support
+@@ -675,97 +668,97 @@ CONFIG_FB_ATMEL=y
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+ # CONFIG_FRAMEBUFFER_CONSOLE is not set
+-
+-#
+-# Logo configuration
+-#
+ # CONFIG_LOGO is not set
+ 
+ #
+ # Sound
+ #
+-CONFIG_SOUND=y
+-
+-#
+-# Advanced Linux Sound Architecture
+-#
+-CONFIG_SND=y
+-CONFIG_SND_TIMER=y
+-CONFIG_SND_PCM=y
+-CONFIG_SND_SEQUENCER=y
+-CONFIG_SND_SEQ_DUMMY=y
+-CONFIG_SND_OSSEMUL=y
+-CONFIG_SND_MIXER_OSS=y
+-CONFIG_SND_PCM_OSS=y
+-CONFIG_SND_PCM_OSS_PLUGINS=y
+-CONFIG_SND_SEQUENCER_OSS=y
+-# CONFIG_SND_DYNAMIC_MINORS is not set
+-CONFIG_SND_SUPPORT_OLD_API=y
+-CONFIG_SND_VERBOSE_PROCFS=y
+-CONFIG_SND_VERBOSE_PRINTK=y
+-CONFIG_SND_DEBUG=y
+-CONFIG_SND_DEBUG_DETECT=y
+-# CONFIG_SND_PCM_XRUN_DEBUG is not set
+-
+-#
+-# Generic devices
+-#
+-# CONFIG_SND_DUMMY is not set
+-# CONFIG_SND_VIRMIDI is not set
+-# CONFIG_SND_MTPAV is not set
+-# CONFIG_SND_SERIAL_U16550 is not set
+-# CONFIG_SND_MPU401 is not set
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
+ 
+ #
+-# ALSA ARM devices
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+ #
+ 
+ #
+-# SoC audio support
++# USB Gadget Support
+ #
+-# CONFIG_SND_SOC is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
+ 
+ #
+-# Open Sound System
++# MMC/SD Card Drivers
+ #
+-# CONFIG_SOUND_PRIME is not set
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
+ 
+ #
+-# HID Devices
++# MMC/SD Host Controller Drivers
+ #
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
++CONFIG_MMC_AT91=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
+ 
+ #
+-# USB support
++# RTC interfaces
+ #
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-# CONFIG_USB is not set
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
+ 
+ #
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++# I2C RTC drivers
+ #
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
+ 
+ #
+-# USB Gadget Support
++# SPI RTC drivers
+ #
+-# CONFIG_USB_GADGET is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
+ 
+ #
+-# MMC/SD Card support
++# Platform RTC drivers
+ #
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+-CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_AT91=y
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
+ 
+ #
+-# Real Time Clock
++# on-CPU RTC drivers
+ #
+-CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
++CONFIG_RTC_DRV_AT91SAM9=y
+ 
+ #
+ # File systems
+@@ -816,7 +809,6 @@ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+ 
+ #
+@@ -836,20 +828,13 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ 
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+@@ -890,16 +875,15 @@ CONFIG_NLS_ISO8859_15=y
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ CONFIG_NLS_UTF8=y
+-
+-#
+-# Profiling support
+-#
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+ 
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
+ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_UNUSED_SYMBOLS is not set
+@@ -907,8 +891,8 @@ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+ # CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_LOG_BUF_SHIFT=14
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
+ # CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_SLAB is not set
+@@ -916,6 +900,9 @@ CONFIG_DETECT_SOFTLOCKUP=y
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+@@ -923,10 +910,13 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ CONFIG_DEBUG_INFO=y
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
+ CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -937,10 +927,7 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ # CONFIG_CRYPTO is not set
+ 
+ #
+@@ -949,9 +936,12 @@ CONFIG_DEBUG_LL=y
+ CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
+index baa9769..d846a49 100644
+--- a/arch/arm/configs/ateb9200_defconfig
++++ b/arch/arm/configs/ateb9200_defconfig
+@@ -714,7 +714,7 @@ CONFIG_I2C_ALGOPCA=m
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=m
++CONFIG_I2C_GPIO=m
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+ # CONFIG_I2C_PCA_ISA is not set
+diff --git a/arch/arm/configs/cam60_defconfig b/arch/arm/configs/cam60_defconfig
+new file mode 100644
+index 0000000..f3cd4a9
+--- /dev/null
++++ b/arch/arm/configs/cam60_defconfig
+@@ -0,0 +1,1228 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24
++# Thu Mar  6 10:07:26 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_AUDIT=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=17
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_RELAY=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++CONFIG_BLK_DEV_IO_TRACE=y
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Atmel AT91 System-on-Chip
++#
++# CONFIG_ARCH_AT91RM9200 is not set
++CONFIG_ARCH_AT91SAM9260=y
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91CAP9 is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
++
++#
++# AT91SAM9260 Variants
++#
++# CONFIG_ARCH_AT91SAM9260_SAM9XE is not set
++
++#
++# AT91SAM9260 / AT91SAM9XE Board Type
++#
++# CONFIG_MACH_AT91SAM9260EK is not set
++CONFIG_MACH_CAM60=y
++# CONFIG_MACH_SAM9_L9260 is not set
++
++#
++# AT91 Board Options
++#
++
++#
++# AT91 Feature Selections
++#
++# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++CONFIG_AT91_TIMER_HZ=100
++CONFIG_AT91_EARLY_DBGU=y
++# CONFIG_AT91_EARLY_USART0 is not set
++# CONFIG_AT91_EARLY_USART1 is not set
++# CONFIG_AT91_EARLY_USART2 is not set
++# CONFIG_AT91_EARLY_USART3 is not set
++# CONFIG_AT91_EARLY_USART4 is not set
++# CONFIG_AT91_EARLY_USART5 is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0x20004000
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_CMDLINE="console=ttyS0,115200 noinitrd root=/dev/mtdblock0 rootfstype=jffs2 mem=64M"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++# CONFIG_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_AOUT=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_NETWORK_SECMARK=y
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++CONFIG_CFG80211=m
++CONFIG_NL80211=y
++CONFIG_WIRELESS_EXT=y
++CONFIG_MAC80211=m
++CONFIG_MAC80211_RCSIMPLE=y
++# CONFIG_MAC80211_DEBUGFS is not set
++# CONFIG_MAC80211_DEBUG is not set
++CONFIG_IEEE80211=m
++# CONFIG_IEEE80211_DEBUG is not set
++CONFIG_IEEE80211_CRYPT_WEP=m
++CONFIG_IEEE80211_CRYPT_CCMP=m
++CONFIG_IEEE80211_CRYPT_TKIP=m
++CONFIG_IEEE80211_SOFTMAC=m
++# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_RAM=m
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++CONFIG_MTD_PLATRAM=m
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_DATAFLASH=y
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++CONFIG_MTD_NAND_AT91=y
++# CONFIG_MTD_NAND_AT91_ECC_SOFT is not set
++CONFIG_MTD_NAND_AT91_ECC_HW=y
++# CONFIG_MTD_NAND_AT91_ECC_NONE is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++CONFIG_SCSI_NETLINK=y
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++CONFIG_CHR_DEV_SCH=y
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++CONFIG_SCSI_LOGGING=y
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=m
++CONFIG_SCSI_FC_ATTRS=m
++# CONFIG_SCSI_FC_TGT_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++CONFIG_SCSI_SAS_ATTRS=m
++CONFIG_SCSI_SAS_LIBSAS=m
++# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=m
++CONFIG_DAVICOM_PHY=m
++CONFIG_QSEMI_PHY=m
++CONFIG_LXT_PHY=m
++CONFIG_CICADA_PHY=m
++CONFIG_VITESSE_PHY=m
++CONFIG_SMSC_PHY=m
++CONFIG_BROADCOM_PHY=m
++# CONFIG_ICPLUS_PHY is not set
++CONFIG_FIXED_PHY=m
++# CONFIG_FIXED_MII_10_FDX is not set
++# CONFIG_FIXED_MII_100_FDX is not set
++# CONFIG_FIXED_MII_1000_FDX is not set
++CONFIG_FIXED_MII_AMNT=1
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_MACB=y
++# CONFIG_AX88796 is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++CONFIG_KEYBOARD_SUNKBD=m
++CONFIG_KEYBOARD_LKKBD=m
++CONFIG_KEYBOARD_XTKBD=m
++CONFIG_KEYBOARD_NEWTON=m
++CONFIG_KEYBOARD_STOWAWAY=m
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=m
++CONFIG_MOUSE_APPLETOUCH=m
++CONFIG_MOUSE_VSXXXAA=m
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++# CONFIG_SERIO_SERPORT is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++CONFIG_VT_HW_CONSOLE_BINDING=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_MOXA_SMARTIO is not set
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_ATMEL=y
++CONFIG_SERIAL_ATMEL_CONSOLE=y
++# CONFIG_SERIAL_ATMEL_TTYAT is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_PCA is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_ATMEL=y
++# CONFIG_SPI_BITBANG is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++CONFIG_USB_LIBUSUAL=y
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++CONFIG_RTC_DRV_TEST=m
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91SAM9=y
++CONFIG_RTC_DRV_AT91SAM9_RTT=0
++CONFIG_RTC_DRV_AT91SAM9_GPBR=0
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++CONFIG_QUOTA=y
++# CONFIG_QUOTA_NETLINK_INTERFACE is not set
++CONFIG_PRINT_QUOTA_WARNING=y
++# CONFIG_QFMT_V1 is not set
++# CONFIG_QFMT_V2 is not set
++CONFIG_QUOTACTL=y
++CONFIG_DNOTIFY=y
++CONFIG_AUTOFS_FS=y
++CONFIG_AUTOFS4_FS=y
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_9BYTE_TAGS is not set
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="cp437"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++# CONFIG_INSTRUMENTATION is not set
++
++#
++# Kernel hacking
++#
++CONFIG_PRINTK_TIME=y
++CONFIG_ENABLE_WARN_DEPRECATED=y
++# CONFIG_ENABLE_MUST_CHECK is not set
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_UNUSED_SYMBOLS=y
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_FORCED_INLINING is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_ERRORS is not set
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ABLKCIPHER=m
++CONFIG_CRYPTO_BLKCIPHER=m
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++CONFIG_CRYPTO_XCBC=m
++CONFIG_CRYPTO_NULL=m
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++CONFIG_CRYPTO_SHA256=y
++CONFIG_CRYPTO_SHA512=y
++CONFIG_CRYPTO_WP512=m
++CONFIG_CRYPTO_TGR192=m
++CONFIG_CRYPTO_GF128MUL=m
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=m
++CONFIG_CRYPTO_PCBC=m
++CONFIG_CRYPTO_LRW=m
++# CONFIG_CRYPTO_XTS is not set
++CONFIG_CRYPTO_CRYPTD=m
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_FCRYPT=m
++CONFIG_CRYPTO_BLOWFISH=m
++CONFIG_CRYPTO_TWOFISH=m
++CONFIG_CRYPTO_TWOFISH_COMMON=m
++CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_AES=m
++CONFIG_CRYPTO_CAST5=m
++CONFIG_CRYPTO_CAST6=m
++CONFIG_CRYPTO_TEA=m
++CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_KHAZAD=m
++CONFIG_CRYPTO_ANUBIS=m
++# CONFIG_CRYPTO_SEED is not set
++CONFIG_CRYPTO_DEFLATE=m
++CONFIG_CRYPTO_MICHAEL_MIC=m
++CONFIG_CRYPTO_CRC32C=m
++CONFIG_CRYPTO_CAMELLIA=m
++CONFIG_CRYPTO_TEST=m
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=m
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=m
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_AUDIT_GENERIC=y
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
+index 88e5d28..67e65e4 100644
+--- a/arch/arm/configs/csb337_defconfig
++++ b/arch/arm/configs/csb337_defconfig
+@@ -1,69 +1,96 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.15
+-# Mon Jan  9 21:51:31 2006
++# Linux kernel version: 2.6.24-rc7
++# Wed Jan  9 22:19:24 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
+ CONFIG_MMU=y
+-CONFIG_UID16=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+ 
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+-CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ CONFIG_LOCALVERSION_AUTO=y
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+-CONFIG_SYSCTL=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_KOBJECT_UEVENT=y
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
+ # CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+ # CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
+ CONFIG_PRINTK=y
+ CONFIG_BUG=y
++CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_CC_ALIGN_FUNCTIONS=0
+-CONFIG_CC_ALIGN_LABELS=0
+-CONFIG_CC_ALIGN_LOOPS=0
+-CONFIG_CC_ALIGN_JUMPS=0
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+-CONFIG_OBSOLETE_MODPARM=y
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+ 
+ #
+ # IO Schedulers
+@@ -81,62 +108,101 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ #
+ # System Type
+ #
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_CLPS7500 is not set
+ # CONFIG_ARCH_CLPS711X is not set
+ # CONFIG_ARCH_CO285 is not set
+ # CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
+ # CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_IOP3XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
+ # CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+ # CONFIG_ARCH_SA1100 is not set
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_IMX is not set
+-# CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_AAEC2000 is not set
+-CONFIG_ARCH_AT91=y
+-CONFIG_ARCH_AT91RM9200=y
+ 
+ #
+-# AT91RM9200 Implementations
++# Boot options
+ #
+ 
+ #
++# Power management
++#
++
++#
++# Atmel AT91 System-on-Chip
++#
++CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_AT91SAM9260 is not set
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
++
++#
+ # AT91RM9200 Board Type
+ #
++# CONFIG_MACH_ONEARM is not set
+ # CONFIG_ARCH_AT91RM9200DK is not set
+ # CONFIG_MACH_AT91RM9200EK is not set
+ CONFIG_MACH_CSB337=y
+ # CONFIG_MACH_CSB637 is not set
+ # CONFIG_MACH_CARMEVA is not set
+-# CONFIG_MACH_KB9200 is not set
+ # CONFIG_MACH_ATEB9200 is not set
++# CONFIG_MACH_KB9200 is not set
++# CONFIG_MACH_PICOTUX2XX is not set
++# CONFIG_MACH_KAFA is not set
++# CONFIG_MACH_CHUB is not set
++# CONFIG_MACH_HOMEMATIC is not set
++# CONFIG_MACH_ECBAT91 is not set
++# CONFIG_MACH_SWEDATMS is not set
++
++#
++# AT91 Board Options
++#
+ 
+ #
+-# AT91RM9200 Feature Selections
++# AT91 Feature Selections
+ #
+ CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=128
+ 
+ #
+ # Processor Type
+ #
+ CONFIG_CPU_32=y
+ CONFIG_CPU_ARM920T=y
+-CONFIG_CPU_32v4=y
++CONFIG_CPU_32v4T=y
+ CONFIG_CPU_ABRT_EV4T=y
+ CONFIG_CPU_CACHE_V4WT=y
+ CONFIG_CPU_CACHE_VIVT=y
+ CONFIG_CPU_COPY_V4WB=y
+ CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
+ 
+ #
+ # Processor Features
+@@ -145,15 +211,13 @@ CONFIG_CPU_TLB_V4WBI=y
+ # CONFIG_CPU_ICACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
+ 
+ #
+ # Bus support
+ #
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ CONFIG_PCCARD=y
+ # CONFIG_PCMCIA_DEBUG is not set
+ CONFIG_PCMCIA=y
+@@ -168,8 +232,13 @@ CONFIG_AT91_CF=y
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+ # CONFIG_PREEMPT is not set
+-# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=128
++# CONFIG_AEABI is not set
+ # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+@@ -178,9 +247,13 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ CONFIG_LEDS=y
+-CONFIG_LEDS_TIMER=y
+ CONFIG_LEDS_CPU=y
+ CONFIG_ALIGNMENT_TRAP=y
+ 
+@@ -191,6 +264,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20410000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+ 
+ #
+ # Floating point emulation
+@@ -215,6 +289,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+ 
+ #
+ # Networking
+@@ -227,6 +302,10 @@ CONFIG_NET=y
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+@@ -243,23 +322,26 @@ CONFIG_IP_PNP_BOOTP=y
+ # CONFIG_INET_AH is not set
+ # CONFIG_INET_ESP is not set
+ # CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
+ # CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_BIC=y
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
+ # CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_VLAN_8021Q is not set
+@@ -269,13 +351,8 @@ CONFIG_TCP_CONG_BIC=y
+ # CONFIG_ATALK is not set
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+-# CONFIG_NET_DIVERT is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+ 
+ #
+@@ -285,7 +362,17 @@ CONFIG_TCP_CONG_BIC=y
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+ 
+ #
+ # Device Drivers
+@@ -294,19 +381,14 @@ CONFIG_TCP_CONG_BIC=y
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ CONFIG_FW_LOADER=y
+ # CONFIG_DEBUG_DRIVER is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ # CONFIG_MTD_CONCAT is not set
+@@ -319,11 +401,14 @@ CONFIG_MTD_CMDLINE_PARTS=y
+ # User Modules And Translation Layers
+ #
+ CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
+ CONFIG_MTD_BLOCK=y
+ # CONFIG_FTL is not set
+ # CONFIG_NFTL is not set
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+ 
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -349,15 +434,14 @@ CONFIG_MTD_CFI_UTIL=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_XIP is not set
+ 
+ #
+ # Mapping drivers for chip access
+ #
+ # CONFIG_MTD_COMPLEX_MAPPINGS is not set
+ CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0
+-CONFIG_MTD_PHYSMAP_LEN=0
++CONFIG_MTD_PHYSMAP_START=0x0
++CONFIG_MTD_PHYSMAP_LEN=0x0
+ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_ARM_INTEGRATOR is not set
+ # CONFIG_MTD_PLATRAM is not set
+@@ -368,7 +452,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_SLRAM is not set
+ # CONFIG_MTD_PHRAM is not set
+ # CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLKMTD is not set
+ # CONFIG_MTD_BLOCK2MTD is not set
+ 
+ #
+@@ -378,29 +461,15 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+ # CONFIG_MTD_AT91_DATAFLASH is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ # CONFIG_MTD_NAND is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
+ # CONFIG_MTD_ONENAND is not set
+ 
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+@@ -409,13 +478,12 @@ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+-CONFIG_BLK_DEV_INITRD=y
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+ # CONFIG_IDE is not set
+ 
+ #
+@@ -423,6 +491,9 @@ CONFIG_BLK_DEV_INITRD=y
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+ 
+ #
+@@ -441,97 +512,61 @@ CONFIG_SCSI_PROC_FS=y
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+ 
+ #
+-# SCSI Transport Attributes
++# SCSI Transports
+ #
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+-# CONFIG_SCSI_SATA is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# PCMCIA SCSI adapter support
+-#
+-# CONFIG_PCMCIA_AHA152X is not set
+-# CONFIG_PCMCIA_FDOMAIN is not set
+-# CONFIG_PCMCIA_NINJA_SCSI is not set
+-# CONFIG_PCMCIA_QLOGIC is not set
+-# CONFIG_PCMCIA_SYM53C500 is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
++# CONFIG_ATA is not set
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+-
+-#
+-# PHY device support
+-#
++# CONFIG_VETH is not set
+ # CONFIG_PHYLIB is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
+ CONFIG_ARM_AT91_ETHER=y
++# CONFIG_AX88796 is not set
+ # CONFIG_SMC91X is not set
+ # CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++CONFIG_NETDEV_10000=y
+ 
+ #
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
++# Wireless LAN
+ #
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+ 
+ #
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# PCMCIA network device support
++# USB Network Adapters
+ #
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_NET_PCMCIA is not set
+-
+-#
+-# Wan interfaces
+-#
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+@@ -539,26 +574,23 @@ CONFIG_ARM_AT91_ETHER=y
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+ 
+ #
+ # Input device support
+ #
+ CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+ 
+ #
+ # Userland interfaces
+ #
+ CONFIG_INPUT_MOUSEDEV=y
+-CONFIG_INPUT_MOUSEDEV_PSAUX=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+ 
+@@ -568,6 +600,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ # CONFIG_INPUT_TOUCHSCREEN is not set
+ # CONFIG_INPUT_MISC is not set
+ 
+@@ -583,6 +616,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ CONFIG_VT=y
+ CONFIG_VT_CONSOLE=y
+ CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+ 
+ #
+@@ -601,152 +635,114 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_AT91RM9200_WATCHDOG=y
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+ # CONFIG_HW_RANDOM is not set
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ 
+ #
+-# Ftape, the floppy tape device driver
+-#
+-
+-#
+ # PCMCIA character devices
+ #
+ # CONFIG_SYNCLINK_CS is not set
+ # CONFIG_CARDMAN_4000 is not set
+ # CONFIG_CARDMAN_4040 is not set
+ # CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+ # CONFIG_TCG_TPM is not set
+-# CONFIG_TELCLOCK is not set
+ CONFIG_AT91_SPI=y
+ CONFIG_AT91_SPIDEV=y
+-
+-#
+-# I2C support
+-#
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
+ CONFIG_I2C_CHARDEV=y
+ 
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+ 
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
++# CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_PCA_ISA is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_PCA is not set
+ 
+ #
+ # Miscellaneous I2C Chip support
+ #
+ # CONFIG_SENSORS_DS1337 is not set
+ # CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
+ # CONFIG_SENSORS_EEPROM is not set
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_SENSORS_RTC8564 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_RTC_X1205_I2C is not set
++# CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+ # CONFIG_I2C_DEBUG_CHIP is not set
+ 
+ #
+-# Hardware Monitoring support
+-#
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ASB100 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_FSCHER is not set
+-# CONFIG_SENSORS_FSCPOS is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-
+-#
+-# Misc devices
+-#
+-
+-#
+-# Multimedia Capabilities Port drivers
++# SPI support
+ #
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+ 
+ #
+-# Multimedia devices
++# Watchdog Device Drivers
+ #
+-# CONFIG_VIDEO_DEV is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91RM9200_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+ 
+ #
+-# Digital Video Broadcasting Devices
++# Multifunction device drivers
+ #
+-# CONFIG_DVB is not set
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
+ 
+ #
+ # Graphics support
+ #
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ # CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+ 
+ #
+ # Console display driver support
+@@ -758,12 +754,25 @@ CONFIG_DUMMY_CONSOLE=y
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
+ 
+ #
+-# USB support
++# USB HID Boot Protocol drivers
+ #
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
+ CONFIG_USB=y
+ CONFIG_USB_DEBUG=y
+ 
+@@ -771,7 +780,7 @@ CONFIG_USB_DEBUG=y
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+ # CONFIG_USB_OTG is not set
+ 
+@@ -780,9 +789,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+ 
+ #
+ # USB Device Class drivers
+@@ -801,59 +812,21 @@ CONFIG_USB_STORAGE=y
+ # CONFIG_USB_STORAGE_DEBUG is not set
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+ # CONFIG_USB_STORAGE_SDDR55 is not set
+ # CONFIG_USB_STORAGE_JUMPSHOT is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_MTOUCH is not set
+-# CONFIG_USB_ITMTOUCH is not set
+-# CONFIG_USB_EGALAX is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
+ 
+ #
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Multimedia devices
+-#
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Video4Linux support is needed for USB Multimedia device support
+-#
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+ 
+ #
+@@ -866,15 +839,18 @@ CONFIG_USB_MON=y
+ CONFIG_USB_SERIAL=y
+ CONFIG_USB_SERIAL_CONSOLE=y
+ CONFIG_USB_SERIAL_GENERIC=y
++# CONFIG_USB_SERIAL_AIRCABLE is not set
+ # CONFIG_USB_SERIAL_AIRPRIME is not set
+-# CONFIG_USB_SERIAL_ANYDATA is not set
++# CONFIG_USB_SERIAL_ARK3116 is not set
+ # CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_CH341 is not set
+ # CONFIG_USB_SERIAL_WHITEHEAT is not set
+ # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+ # CONFIG_USB_SERIAL_CP2101 is not set
+ # CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+ # CONFIG_USB_SERIAL_EMPEG is not set
+ CONFIG_USB_SERIAL_FTDI_SIO=y
++# CONFIG_USB_SERIAL_FUNSOFT is not set
+ # CONFIG_USB_SERIAL_VISOR is not set
+ # CONFIG_USB_SERIAL_IPAQ is not set
+ # CONFIG_USB_SERIAL_IR is not set
+@@ -899,14 +875,20 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+ # CONFIG_USB_SERIAL_KLSI is not set
+ # CONFIG_USB_SERIAL_KOBIL_SCT is not set
+ CONFIG_USB_SERIAL_MCT_U232=y
++# CONFIG_USB_SERIAL_MOS7720 is not set
++# CONFIG_USB_SERIAL_MOS7840 is not set
++# CONFIG_USB_SERIAL_NAVMAN is not set
+ # CONFIG_USB_SERIAL_PL2303 is not set
++# CONFIG_USB_SERIAL_OTI6858 is not set
+ # CONFIG_USB_SERIAL_HP4X is not set
+ # CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+ # CONFIG_USB_SERIAL_TI is not set
+ # CONFIG_USB_SERIAL_CYBERJACK is not set
+ # CONFIG_USB_SERIAL_XIRCOM is not set
+ # CONFIG_USB_SERIAL_OPTION is not set
+ # CONFIG_USB_SERIAL_OMNINET is not set
++# CONFIG_USB_SERIAL_DEBUG is not set
+ CONFIG_USB_EZUSB=y
+ 
+ #
+@@ -914,16 +896,22 @@ CONFIG_USB_EZUSB=y
+ #
+ # CONFIG_USB_EMI62 is not set
+ # CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGETKIT is not set
+-# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_PHIDGET is not set
+ # CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
+ 
+ #
+@@ -934,13 +922,19 @@ CONFIG_USB_EZUSB=y
+ # USB Gadget Support
+ #
+ CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
+ # CONFIG_USB_GADGET_DEBUG_FILES is not set
+ CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
+ # CONFIG_USB_GADGET_LH7A40X is not set
+ # CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
+ CONFIG_USB_GADGET_AT91=y
+ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+@@ -950,22 +944,28 @@ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGETFS is not set
+ # CONFIG_USB_FILE_STORAGE is not set
+ # CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
+ 
+ #
+-# MMC/SD Card support
++# MMC/SD Card Drivers
+ #
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+ CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_AT91RM9200=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
+ 
+ #
+-# Real Time Clock
++# MMC/SD Host Controller Drivers
+ #
++# CONFIG_MMC_AT91 is not set
++# CONFIG_NEW_LEDS is not set
+ CONFIG_RTC_LIB=y
+ CONFIG_RTC_CLASS=y
+ CONFIG_RTC_HCTOSYS=y
+ CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
++# CONFIG_RTC_DEBUG is not set
+ 
+ #
+ # RTC interfaces
+@@ -974,39 +974,60 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
+ CONFIG_RTC_INTF_PROC=y
+ CONFIG_RTC_INTF_DEV=y
+ # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
+ 
+ #
+-# RTC drivers
++# I2C RTC drivers
+ #
+-# CONFIG_RTC_DRV_X1205 is not set
+ CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
+ # CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
+ # CONFIG_RTC_DRV_PCF8563 is not set
+ # CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
+ # CONFIG_RTC_DRV_M48T86 is not set
+-CONFIG_RTC_DRV_AT91RM9200=y
+-# CONFIG_RTC_DRV_TEST is not set
++# CONFIG_RTC_DRV_M48T59 is not set
+ # CONFIG_RTC_DRV_V3020 is not set
+ 
+ #
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91RM9200=y
++
++#
+ # File systems
+ #
+ CONFIG_EXT2_FS=y
+ # CONFIG_EXT2_FS_XATTR is not set
+ # CONFIG_EXT2_FS_XIP is not set
+ # CONFIG_EXT3_FS is not set
+-# CONFIG_JBD is not set
++# CONFIG_EXT4DEV_FS is not set
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
+ # CONFIG_FS_POSIX_ACL is not set
+ # CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
+ # CONFIG_MINIX_FS is not set
+ # CONFIG_ROMFS_FS is not set
+ CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
+ # CONFIG_QUOTA is not set
+ CONFIG_DNOTIFY=y
+ # CONFIG_AUTOFS_FS is not set
+@@ -1030,11 +1051,12 @@ CONFIG_DNOTIFY=y
+ # Pseudo filesystems
+ #
+ CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
+ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-# CONFIG_RELAYFS_FS is not set
++# CONFIG_CONFIGFS_FS is not set
+ 
+ #
+ # Miscellaneous filesystems
+@@ -1046,7 +1068,6 @@ CONFIG_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
+-# CONFIG_JFFS_FS is not set
+ # CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=y
+ # CONFIG_VXFS_FS is not set
+@@ -1054,10 +1075,7 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V3_ACL is not set
+@@ -1070,6 +1088,7 @@ CONFIG_LOCKD_V4=y
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
+ CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
+ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1077,43 +1096,56 @@ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+ 
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ # CONFIG_NLS is not set
+-
+-#
+-# Profiling support
+-#
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+ 
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
+-CONFIG_DEBUG_KERNEL=y
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
+-# CONFIG_DEBUG_SLAB is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_FS is not set
+ # CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -1124,12 +1156,13 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_MANAGER=y
+ # CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
+ # CONFIG_CRYPTO_NULL is not set
+ # CONFIG_CRYPTO_MD4 is not set
+ CONFIG_CRYPTO_MD5=y
+@@ -1138,7 +1171,15 @@ CONFIG_CRYPTO_MD5=y
+ # CONFIG_CRYPTO_SHA512 is not set
+ # CONFIG_CRYPTO_WP512 is not set
+ # CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CRYPTD is not set
+ CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
+ # CONFIG_CRYPTO_BLOWFISH is not set
+ # CONFIG_CRYPTO_TWOFISH is not set
+ # CONFIG_CRYPTO_SERPENT is not set
+@@ -1149,20 +1190,27 @@ CONFIG_CRYPTO_DES=y
+ # CONFIG_CRYPTO_ARC4 is not set
+ # CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
+ # CONFIG_CRYPTO_DEFLATE is not set
+ # CONFIG_CRYPTO_MICHAEL_MIC is not set
+ # CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
+ # CONFIG_CRYPTO_TEST is not set
+-
+-#
+-# Hardware crypto devices
+-#
++# CONFIG_CRYPTO_AUTHENC is not set
++CONFIG_CRYPTO_HW=y
+ 
+ #
+ # Library routines
+ #
++CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig
+index 669f035..9970214 100644
+--- a/arch/arm/configs/csb637_defconfig
++++ b/arch/arm/configs/csb637_defconfig
+@@ -1,69 +1,112 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.15
+-# Mon Jan  9 21:52:00 2006
++# Linux kernel version: 2.6.25-rc8
++# Fri Apr  4 22:06:15 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
+ CONFIG_MMU=y
+-CONFIG_UID16=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ARCH_SUPPORTS_AOUT=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+ 
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+-CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ CONFIG_LOCALVERSION_AUTO=y
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+-CONFIG_SYSCTL=y
++# CONFIG_TASKSTATS is not set
+ # CONFIG_AUDIT is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_KOBJECT_UEVENT=y
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
+ # CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+ # CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
+ CONFIG_PRINTK=y
+ CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_CC_ALIGN_FUNCTIONS=0
+-CONFIG_CC_ALIGN_LABELS=0
+-CONFIG_CC_ALIGN_LOOPS=0
+-CONFIG_CC_ALIGN_JUMPS=0
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+-CONFIG_OBSOLETE_MODPARM=y
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+ 
+ #
+ # IO Schedulers
+@@ -77,66 +120,111 @@ CONFIG_DEFAULT_AS=y
+ # CONFIG_DEFAULT_CFQ is not set
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
+ 
+ #
+ # System Type
+ #
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_CLPS7500 is not set
+ # CONFIG_ARCH_CLPS711X is not set
+ # CONFIG_ARCH_CO285 is not set
+ # CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
+ # CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_IOP3XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
+ # CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION is not set
++# CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+ # CONFIG_ARCH_SA1100 is not set
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_IMX is not set
+-# CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_AAEC2000 is not set
+-CONFIG_ARCH_AT91=y
+-CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_MSM7X00A is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
+ 
+ #
+-# AT91RM9200 Implementations
++# Atmel AT91 System-on-Chip
+ #
++CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_AT91SAM9260 is not set
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91CAP9 is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
+ 
+ #
+ # AT91RM9200 Board Type
+ #
++# CONFIG_MACH_ONEARM is not set
+ # CONFIG_ARCH_AT91RM9200DK is not set
+ # CONFIG_MACH_AT91RM9200EK is not set
+ # CONFIG_MACH_CSB337 is not set
+ CONFIG_MACH_CSB637=y
+ # CONFIG_MACH_CARMEVA is not set
+-# CONFIG_MACH_KB9200 is not set
+ # CONFIG_MACH_ATEB9200 is not set
++# CONFIG_MACH_KB9200 is not set
++# CONFIG_MACH_PICOTUX2XX is not set
++# CONFIG_MACH_KAFA is not set
+ 
+ #
+-# AT91RM9200 Feature Selections
++# AT91 Board Options
++#
++
++#
++# AT91 Feature Selections
+ #
+ CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++CONFIG_AT91_TIMER_HZ=128
++CONFIG_AT91_EARLY_DBGU=y
++# CONFIG_AT91_EARLY_USART0 is not set
++# CONFIG_AT91_EARLY_USART1 is not set
++# CONFIG_AT91_EARLY_USART2 is not set
++# CONFIG_AT91_EARLY_USART3 is not set
++# CONFIG_AT91_EARLY_USART4 is not set
++# CONFIG_AT91_EARLY_USART5 is not set
+ 
+ #
+ # Processor Type
+ #
+ CONFIG_CPU_32=y
+ CONFIG_CPU_ARM920T=y
+-CONFIG_CPU_32v4=y
++CONFIG_CPU_32v4T=y
+ CONFIG_CPU_ABRT_EV4T=y
+ CONFIG_CPU_CACHE_V4WT=y
+ CONFIG_CPU_CACHE_VIVT=y
+ CONFIG_CPU_COPY_V4WB=y
+ CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
+ 
+ #
+ # Processor Features
+@@ -145,15 +233,13 @@ CONFIG_CPU_TLB_V4WBI=y
+ # CONFIG_CPU_ICACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
+ 
+ #
+ # Bus support
+ #
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ CONFIG_PCCARD=y
+ # CONFIG_PCMCIA_DEBUG is not set
+ CONFIG_PCMCIA=y
+@@ -168,8 +254,13 @@ CONFIG_AT91_CF=y
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+ # CONFIG_PREEMPT is not set
+-# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=128
++# CONFIG_AEABI is not set
+ # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+@@ -178,9 +269,13 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ CONFIG_LEDS=y
+-CONFIG_LEDS_TIMER=y
+ CONFIG_LEDS_CPU=y
+ CONFIG_ALIGNMENT_TRAP=y
+ 
+@@ -191,6 +286,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20410000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+ 
+ #
+ # Floating point emulation
+@@ -215,6 +311,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
+ 
+ #
+ # Networking
+@@ -227,6 +324,11 @@ CONFIG_NET=y
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+@@ -243,23 +345,26 @@ CONFIG_IP_PNP_BOOTP=y
+ # CONFIG_INET_AH is not set
+ # CONFIG_INET_ESP is not set
+ # CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
+ # CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_BIC=y
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
+ # CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_VLAN_8021Q is not set
+@@ -269,13 +374,8 @@ CONFIG_TCP_CONG_BIC=y
+ # CONFIG_ATALK is not set
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+-# CONFIG_NET_DIVERT is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+ 
+ #
+@@ -283,9 +383,20 @@ CONFIG_TCP_CONG_BIC=y
+ #
+ # CONFIG_NET_PKTGEN is not set
+ # CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+ 
+ #
+ # Device Drivers
+@@ -294,19 +405,14 @@ CONFIG_TCP_CONG_BIC=y
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ CONFIG_FW_LOADER=y
+ # CONFIG_DEBUG_DRIVER is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ # CONFIG_MTD_CONCAT is not set
+@@ -319,11 +425,14 @@ CONFIG_MTD_CMDLINE_PARTS=y
+ # User Modules And Translation Layers
+ #
+ CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
+ CONFIG_MTD_BLOCK=y
+ # CONFIG_FTL is not set
+ # CONFIG_NFTL is not set
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+ 
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -349,15 +458,14 @@ CONFIG_MTD_CFI_UTIL=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_XIP is not set
+ 
+ #
+ # Mapping drivers for chip access
+ #
+ # CONFIG_MTD_COMPLEX_MAPPINGS is not set
+ CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0
+-CONFIG_MTD_PHYSMAP_LEN=0
++CONFIG_MTD_PHYSMAP_START=0x0
++CONFIG_MTD_PHYSMAP_LEN=0x0
+ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_ARM_INTEGRATOR is not set
+ # CONFIG_MTD_PLATRAM is not set
+@@ -368,7 +476,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_SLRAM is not set
+ # CONFIG_MTD_PHRAM is not set
+ # CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLKMTD is not set
+ # CONFIG_MTD_BLOCK2MTD is not set
+ 
+ #
+@@ -377,30 +484,15 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_AT91_DATAFLASH is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ # CONFIG_MTD_NAND is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
+ # CONFIG_MTD_ONENAND is not set
+ 
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+@@ -409,13 +501,15 @@ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+-CONFIG_BLK_DEV_INITRD=y
++# CONFIG_BLK_DEV_XIP is not set
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
++CONFIG_MISC_DEVICES=y
++# CONFIG_ATMEL_PWM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ATMEL_SSC is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
+ # CONFIG_IDE is not set
+ 
+ #
+@@ -423,6 +517,9 @@ CONFIG_BLK_DEV_INITRD=y
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+ 
+ #
+@@ -441,114 +538,78 @@ CONFIG_SCSI_PROC_FS=y
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+ 
+ #
+-# SCSI Transport Attributes
++# SCSI Transports
+ #
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+-# CONFIG_SCSI_SATA is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# PCMCIA SCSI adapter support
+-#
+-# CONFIG_PCMCIA_AHA152X is not set
+-# CONFIG_PCMCIA_FDOMAIN is not set
+-# CONFIG_PCMCIA_NINJA_SCSI is not set
+-# CONFIG_PCMCIA_QLOGIC is not set
+-# CONFIG_PCMCIA_SYM53C500 is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
++# CONFIG_ATA is not set
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+-
+-#
+-# PHY device support
+-#
++# CONFIG_VETH is not set
+ # CONFIG_PHYLIB is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
+ CONFIG_ARM_AT91_ETHER=y
++# CONFIG_AX88796 is not set
+ # CONFIG_SMC91X is not set
++# CONFIG_SMSC911X is not set
+ # CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_CS89x0 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_NETDEV_10000=y
+ 
+ #
+-# Ethernet (1000 Mbit)
++# Wireless LAN
+ #
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+ 
+ #
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# PCMCIA network device support
++# USB Network Adapters
+ #
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_NET_PCMCIA is not set
+-
+-#
+-# Wan interfaces
+-#
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+ 
+ #
+ # Input device support
+ #
+ CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+ 
+ #
+ # Userland interfaces
+@@ -558,7 +619,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+ 
+@@ -568,6 +628,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ # CONFIG_INPUT_TOUCHSCREEN is not set
+ # CONFIG_INPUT_MISC is not set
+ 
+@@ -583,6 +644,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ CONFIG_VT=y
+ CONFIG_VT_CONSOLE=y
+ CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+ 
+ #
+@@ -595,64 +657,29 @@ CONFIG_HW_CONSOLE=y
+ #
+ CONFIG_SERIAL_ATMEL=y
+ CONFIG_SERIAL_ATMEL_CONSOLE=y
++CONFIG_SERIAL_ATMEL_PDC=y
+ # CONFIG_SERIAL_ATMEL_TTYAT is not set
+ CONFIG_SERIAL_CORE=y
+ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_AT91RM9200_WATCHDOG=y
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
++CONFIG_HW_RANDOM=m
+ # CONFIG_NVRAM is not set
+-CONFIG_RTC=y
+-# CONFIG_AT91RM9200_RTC is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ 
+ #
+-# Ftape, the floppy tape device driver
+-#
+-
+-#
+ # PCMCIA character devices
+ #
+ # CONFIG_SYNCLINK_CS is not set
+ # CONFIG_CARDMAN_4000 is not set
+ # CONFIG_CARDMAN_4040 is not set
++# CONFIG_IPWIRELESS is not set
+ # CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+ # CONFIG_TCG_TPM is not set
+-# CONFIG_TELCLOCK is not set
+-CONFIG_AT91_SPI=y
+-CONFIG_AT91_SPIDEV=y
+-
+-#
+-# I2C support
+-#
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
+ CONFIG_I2C_CHARDEV=y
+ 
+ #
+@@ -665,43 +692,53 @@ CONFIG_I2C_CHARDEV=y
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_PCA_ISA is not set
++# CONFIG_I2C_TINY_USB is not set
+ 
+ #
+ # Miscellaneous I2C Chip support
+ #
+-# CONFIG_SENSORS_DS1337 is not set
+-# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
+ # CONFIG_SENSORS_EEPROM is not set
+ # CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_PCF8575 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_TPS65010 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_RTC_X1205_I2C is not set
++# CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+ # CONFIG_I2C_DEBUG_CHIP is not set
+ 
+ #
+-# Hardware Monitoring support
++# SPI support
+ #
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
+ CONFIG_HWMON=y
+ # CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
+ # CONFIG_SENSORS_ADM1021 is not set
+ # CONFIG_SENSORS_ADM1025 is not set
+ # CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
+ # CONFIG_SENSORS_ADM1031 is not set
+ # CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
+ # CONFIG_SENSORS_ATXP1 is not set
+ # CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_FSCHER is not set
+-# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
+ # CONFIG_SENSORS_GL518SM is not set
+ # CONFIG_SENSORS_GL520SM is not set
+ # CONFIG_SENSORS_IT87 is not set
+@@ -715,39 +752,72 @@ CONFIG_HWMON=y
+ # CONFIG_SENSORS_LM87 is not set
+ # CONFIG_SENSORS_LM90 is not set
+ # CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
+ # CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
+ # CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
+ # CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
+ # CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
+ # CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
+ # CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
+ # CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
+ # CONFIG_SENSORS_W83627HF is not set
+ # CONFIG_SENSORS_W83627EHF is not set
+ # CONFIG_HWMON_DEBUG_CHIP is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+ 
+ #
+-# Misc devices
++# Watchdog Device Drivers
+ #
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91RM9200_WATCHDOG=y
+ 
+ #
+-# Multimedia Capabilities Port drivers
++# USB-based Watchdog Cards
+ #
++# CONFIG_USBPCWATCHDOG is not set
+ 
+ #
+-# Multimedia devices
++# Sonics Silicon Backplane
+ #
+-# CONFIG_VIDEO_DEV is not set
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+ 
+ #
+-# Digital Video Broadcasting Devices
++# Multifunction device drivers
+ #
+-# CONFIG_DVB is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
+ 
+ #
+ # Graphics support
+ #
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ # CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+ 
+ #
+ # Console display driver support
+@@ -759,20 +829,34 @@ CONFIG_DUMMY_CONSOLE=y
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
+ 
+ #
+-# USB support
++# USB Input Devices
+ #
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
+ CONFIG_USB=y
+ CONFIG_USB_DEBUG=y
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+ 
+ #
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+ # CONFIG_USB_OTG is not set
+ 
+@@ -781,9 +865,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+ 
+ #
+ # USB Device Class drivers
+@@ -802,80 +888,42 @@ CONFIG_USB_STORAGE=y
+ # CONFIG_USB_STORAGE_DEBUG is not set
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+ # CONFIG_USB_STORAGE_SDDR55 is not set
+ # CONFIG_USB_STORAGE_JUMPSHOT is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_MTOUCH is not set
+-# CONFIG_USB_ITMTOUCH is not set
+-# CONFIG_USB_EGALAX is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
+ 
+ #
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Multimedia devices
+-#
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Video4Linux support is needed for USB Multimedia device support
+-#
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+ 
+ #
+ # USB port drivers
+ #
+-
+-#
+-# USB Serial Converter support
+-#
+ CONFIG_USB_SERIAL=y
+ CONFIG_USB_SERIAL_CONSOLE=y
++CONFIG_USB_EZUSB=y
+ CONFIG_USB_SERIAL_GENERIC=y
++# CONFIG_USB_SERIAL_AIRCABLE is not set
+ # CONFIG_USB_SERIAL_AIRPRIME is not set
+-# CONFIG_USB_SERIAL_ANYDATA is not set
++# CONFIG_USB_SERIAL_ARK3116 is not set
+ # CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_CH341 is not set
+ # CONFIG_USB_SERIAL_WHITEHEAT is not set
+ # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+ # CONFIG_USB_SERIAL_CP2101 is not set
+ # CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+ # CONFIG_USB_SERIAL_EMPEG is not set
+ CONFIG_USB_SERIAL_FTDI_SIO=y
++# CONFIG_USB_SERIAL_FUNSOFT is not set
+ # CONFIG_USB_SERIAL_VISOR is not set
+ # CONFIG_USB_SERIAL_IPAQ is not set
+ # CONFIG_USB_SERIAL_IR is not set
+@@ -883,6 +931,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=y
+ # CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+ # CONFIG_USB_SERIAL_GARMIN is not set
+ # CONFIG_USB_SERIAL_IPW is not set
++# CONFIG_USB_SERIAL_IUU is not set
+ # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+ CONFIG_USB_SERIAL_KEYSPAN=y
+ CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+@@ -900,46 +949,66 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+ # CONFIG_USB_SERIAL_KLSI is not set
+ # CONFIG_USB_SERIAL_KOBIL_SCT is not set
+ CONFIG_USB_SERIAL_MCT_U232=y
++# CONFIG_USB_SERIAL_MOS7720 is not set
++# CONFIG_USB_SERIAL_MOS7840 is not set
++# CONFIG_USB_SERIAL_NAVMAN is not set
+ # CONFIG_USB_SERIAL_PL2303 is not set
++# CONFIG_USB_SERIAL_OTI6858 is not set
+ # CONFIG_USB_SERIAL_HP4X is not set
+ # CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+ # CONFIG_USB_SERIAL_TI is not set
+ # CONFIG_USB_SERIAL_CYBERJACK is not set
+ # CONFIG_USB_SERIAL_XIRCOM is not set
+ # CONFIG_USB_SERIAL_OPTION is not set
+ # CONFIG_USB_SERIAL_OMNINET is not set
+-CONFIG_USB_EZUSB=y
++# CONFIG_USB_SERIAL_DEBUG is not set
+ 
+ #
+ # USB Miscellaneous drivers
+ #
+ # CONFIG_USB_EMI62 is not set
+ # CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGETKIT is not set
+-# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_PHIDGET is not set
+ # CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
+ 
+ #
+-# USB DSL modem support
++# LED drivers
+ #
++CONFIG_LEDS_GPIO=y
+ 
+ #
+-# USB Gadget Support
++# LED Triggers
+ #
+-# CONFIG_USB_GADGET is not set
++CONFIG_LEDS_TRIGGERS=y
++# CONFIG_LEDS_TRIGGER_TIMER is not set
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
+ 
+ #
+-# MMC/SD Card support
++# Userspace I/O
+ #
+-# CONFIG_MMC is not set
++# CONFIG_UIO is not set
+ 
+ #
+ # File systems
+@@ -948,16 +1017,17 @@ CONFIG_EXT2_FS=y
+ # CONFIG_EXT2_FS_XATTR is not set
+ # CONFIG_EXT2_FS_XIP is not set
+ # CONFIG_EXT3_FS is not set
+-# CONFIG_JBD is not set
++# CONFIG_EXT4DEV_FS is not set
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
+ # CONFIG_FS_POSIX_ACL is not set
+ # CONFIG_XFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
+ CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
+ # CONFIG_QUOTA is not set
+-CONFIG_DNOTIFY=y
+ # CONFIG_AUTOFS_FS is not set
+ # CONFIG_AUTOFS4_FS is not set
+ # CONFIG_FUSE_FS is not set
+@@ -979,11 +1049,12 @@ CONFIG_DNOTIFY=y
+ # Pseudo filesystems
+ #
+ CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
+ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-# CONFIG_RELAYFS_FS is not set
++# CONFIG_CONFIGFS_FS is not set
+ 
+ #
+ # Miscellaneous filesystems
+@@ -995,18 +1066,16 @@ CONFIG_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
+-# CONFIG_JFFS_FS is not set
+ # CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=y
+ # CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
+ # CONFIG_HPFS_FS is not set
+ # CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V3_ACL is not set
+@@ -1019,6 +1088,7 @@ CONFIG_LOCKD_V4=y
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
+ CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
+ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1026,45 +1096,57 @@ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+ 
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ # CONFIG_NLS is not set
+-
+-#
+-# Profiling support
+-#
+-# CONFIG_PROFILING is not set
++# CONFIG_DLM is not set
+ 
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
+-CONFIG_DEBUG_KERNEL=y
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
+-# CONFIG_DEBUG_SLAB is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_FS is not set
+ # CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
+ CONFIG_DEBUG_LL=y
+ # CONFIG_DEBUG_ICEDCC is not set
+ 
+@@ -1073,12 +1155,14 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
+ # CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
+ # CONFIG_CRYPTO_NULL is not set
+ # CONFIG_CRYPTO_MD4 is not set
+ CONFIG_CRYPTO_MD5=y
+@@ -1087,7 +1171,18 @@ CONFIG_CRYPTO_MD5=y
+ # CONFIG_CRYPTO_SHA512 is not set
+ # CONFIG_CRYPTO_WP512 is not set
+ # CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
+ CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
+ # CONFIG_CRYPTO_BLOWFISH is not set
+ # CONFIG_CRYPTO_TWOFISH is not set
+ # CONFIG_CRYPTO_SERPENT is not set
+@@ -1098,20 +1193,29 @@ CONFIG_CRYPTO_DES=y
+ # CONFIG_CRYPTO_ARC4 is not set
+ # CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
+ # CONFIG_CRYPTO_DEFLATE is not set
+ # CONFIG_CRYPTO_MICHAEL_MIC is not set
+ # CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
+ # CONFIG_CRYPTO_TEST is not set
+-
+-#
+-# Hardware crypto devices
+-#
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
+ 
+ #
+ # Library routines
+ #
++CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ecbat91_defconfig b/arch/arm/configs/ecbat91_defconfig
+new file mode 100644
+index 0000000..90ed214
+--- /dev/null
++++ b/arch/arm/configs/ecbat91_defconfig
+@@ -0,0 +1,1315 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22-rc4
++# Sat Jun  9 01:30:18 2007
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Atmel AT91 System-on-Chip
++#
++CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_AT91SAM9260 is not set
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++
++#
++# AT91RM9200 Board Type
++#
++# CONFIG_MACH_ONEARM is not set
++# CONFIG_ARCH_AT91RM9200DK is not set
++# CONFIG_MACH_AT91RM9200EK is not set
++# CONFIG_MACH_CSB337 is not set
++# CONFIG_MACH_CSB637 is not set
++# CONFIG_MACH_CARMEVA is not set
++# CONFIG_MACH_ATEB9200 is not set
++# CONFIG_MACH_KB9200 is not set
++# CONFIG_MACH_PICOTUX2XX is not set
++# CONFIG_MACH_KAFA is not set
++# CONFIG_MACH_CHUB is not set
++CONFIG_MACH_ECBAT91=y
++
++#
++# AT91 Board Options
++#
++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
++
++#
++# AT91 Feature Selections
++#
++CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4T=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++CONFIG_PCCARD=y
++# CONFIG_PCMCIA_DEBUG is not set
++CONFIG_PCMCIA=y
++CONFIG_PCMCIA_LOAD_CIS=y
++CONFIG_PCMCIA_IOCTL=y
++
++#
++# PC-card bridges
++#
++CONFIG_AT91_CF=y
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++CONFIG_PREEMPT=y
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="rootfstype=reiserfs root=/dev/mmcblk0p1 console=ttyS0,115200n8 rootdelay=1"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++CONFIG_CFG80211=y
++CONFIG_WIRELESS_EXT=y
++CONFIG_MAC80211=y
++# CONFIG_MAC80211_DEBUG is not set
++CONFIG_IEEE80211=y
++# CONFIG_IEEE80211_DEBUG is not set
++CONFIG_IEEE80211_CRYPT_WEP=y
++# CONFIG_IEEE80211_CRYPT_CCMP is not set
++# CONFIG_IEEE80211_CRYPT_TKIP is not set
++CONFIG_IEEE80211_SOFTMAC=y
++CONFIG_IEEE80211_SOFTMAC_DEBUG=y
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++# CONFIG_STANDALONE is not set
++# CONFIG_PREVENT_FIRMWARE_BUILD is not set
++CONFIG_FW_LOADER=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_AFS_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_DATAFLASH=y
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# PCMCIA SCSI adapter support
++#
++# CONFIG_PCMCIA_AHA152X is not set
++# CONFIG_PCMCIA_FDOMAIN is not set
++# CONFIG_PCMCIA_NINJA_SCSI is not set
++# CONFIG_PCMCIA_QLOGIC is not set
++# CONFIG_PCMCIA_SYM53C500 is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_ARM_AT91_ETHER=y
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET_MII is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_NET_PCMCIA is not set
++# CONFIG_WAN is not set
++CONFIG_PPP=y
++CONFIG_PPP_MULTILINK=y
++CONFIG_PPP_FILTER=y
++CONFIG_PPP_ASYNC=y
++# CONFIG_PPP_SYNC_TTY is not set
++# CONFIG_PPP_DEFLATE is not set
++# CONFIG_PPP_BSDCOMP is not set
++# CONFIG_PPP_MPPE is not set
++# CONFIG_PPPOE is not set
++# CONFIG_SLIP is not set
++CONFIG_SLHC=y
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_ATMEL=y
++CONFIG_SERIAL_ATMEL_CONSOLE=y
++# CONFIG_SERIAL_ATMEL_TTYAT is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_AT91RM9200_WATCHDOG is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++
++#
++# PCMCIA character devices
++#
++# CONFIG_SYNCLINK_CS is not set
++# CONFIG_CARDMAN_4000 is not set
++# CONFIG_CARDMAN_4040 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_AT91_SPI is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_GPIO=y
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_PCA is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_ATMEL is not set
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_AT91=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Misc devices
++#
++# CONFIG_BLINK is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# LED devices
++#
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++# CONFIG_LEDS_TRIGGERS is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# HID Devices
++#
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_DEVICE_CLASS is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++CONFIG_USB_PRINTER=y
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++CONFIG_USB_GADGET_AT91=y
++CONFIG_USB_AT91=y
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++# CONFIG_USB_GADGET_DUALSPEED is not set
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_ETH is not set
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++CONFIG_MMC_DEBUG=y
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_AT91=y
++
++#
++# Real Time Clock
++#
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91RM9200=y
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++CONFIG_CONFIGFS_FS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_ACL_SUPPORT=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++CONFIG_CRYPTO_AES=y
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++CONFIG_CRYPTO_ARC4=y
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
+index a0f48d5..ae51a40 100644
+--- a/arch/arm/configs/kafa_defconfig
++++ b/arch/arm/configs/kafa_defconfig
+@@ -587,14 +587,14 @@ CONFIG_I2C_CHARDEV=y
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+ 
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+ # CONFIG_I2C_PCA_ISA is not set
+diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig
+new file mode 100644
+index 0000000..4d11678
+--- /dev/null
++++ b/arch/arm/configs/magician_defconfig
+@@ -0,0 +1,1182 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24-rc6
++# Sun Dec 30 13:02:54 2007
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_ARCH_MTD_XIP=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
++CONFIG_ARCH_PXA=y
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Intel PXA2xx/PXA3xx Implementations
++#
++# CONFIG_ARCH_LUBBOCK is not set
++# CONFIG_MACH_LOGICPD_PXA270 is not set
++# CONFIG_MACH_MAINSTONE is not set
++# CONFIG_ARCH_PXA_IDP is not set
++# CONFIG_PXA_SHARPSL is not set
++# CONFIG_MACH_TRIZEPS4 is not set
++# CONFIG_MACH_EM_X270 is not set
++# CONFIG_MACH_ZYLONITE is not set
++# CONFIG_MACH_ARMCORE is not set
++CONFIG_MACH_MAGICIAN=y
++CONFIG_PXA27x=y
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_XSCALE=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5T=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_OUTER_CACHE is not set
++CONFIG_IWMMXT=y
++CONFIG_XSCALE_PMU=y
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_PREEMPT=y
++CONFIG_HZ=100
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=y
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="keepinitrd"
++# CONFIG_XIP_KERNEL is not set
++CONFIG_KEXEC=y
++
++#
++# CPU Frequency scaling
++#
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++# CONFIG_CPU_FREQ_DEBUG is not set
++CONFIG_CPU_FREQ_STAT=y
++# CONFIG_CPU_FREQ_STAT_DETAILS is not set
++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
++CONFIG_CPU_FREQ_GOV_ONDEMAND=y
++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND_UP_POSSIBLE=y
++CONFIG_SUSPEND=y
++CONFIG_APM_EMULATION=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK is not set
++# CONFIG_NF_CONNTRACK_ENABLED is not set
++# CONFIG_NF_CONNTRACK is not set
++# CONFIG_NETFILTER_XTABLES is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++CONFIG_IRDA=m
++
++#
++# IrDA protocols
++#
++CONFIG_IRLAN=m
++# CONFIG_IRNET is not set
++CONFIG_IRCOMM=m
++CONFIG_IRDA_ULTRA=y
++
++#
++# IrDA options
++#
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++CONFIG_IRDA_FAST_RR=y
++CONFIG_IRDA_DEBUG=y
++
++#
++# Infrared-port device drivers
++#
++
++#
++# SIR device drivers
++#
++CONFIG_IRTTY_SIR=m
++
++#
++# Dongle support
++#
++# CONFIG_DONGLE is not set
++
++#
++# Old SIR device drivers
++#
++# CONFIG_IRPORT_SIR is not set
++
++#
++# Old Serial dongle support
++#
++
++#
++# FIR device drivers
++#
++CONFIG_PXA_FICP=m
++CONFIG_BT=m
++CONFIG_BT_L2CAP=m
++CONFIG_BT_SCO=m
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=m
++
++#
++# Bluetooth device drivers
++#
++# CONFIG_BT_HCIUART is not set
++# CONFIG_BT_HCIVHCI is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++CONFIG_MTD_DEBUG=y
++CONFIG_MTD_DEBUG_VERBOSE=0
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=m
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x00000000
++CONFIG_MTD_PHYSMAP_LEN=0x04000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++# CONFIG_MTD_PXA2XX is not set
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_SHARP_SL is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++CONFIG_PPP=m
++# CONFIG_PPP_MULTILINK is not set
++# CONFIG_PPP_FILTER is not set
++CONFIG_PPP_ASYNC=m
++# CONFIG_PPP_SYNC_TTY is not set
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_MPPE=m
++# CONFIG_PPPOE is not set
++# CONFIG_PPPOL2TP is not set
++# CONFIG_SLIP is not set
++CONFIG_SLHC=m
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_PXA27x is not set
++CONFIG_KEYBOARD_GPIO=y
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_UINPUT=m
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_PXA=y
++# CONFIG_SERIAL_PXA_CONSOLE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=m
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=m
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_GPIO is not set
++CONFIG_I2C_PXA=m
++# CONFIG_I2C_PXA_SLAVE is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++CONFIG_W1=y
++
++#
++# 1-wire Bus Masters
++#
++# CONFIG_W1_MASTER_DS2482 is not set
++CONFIG_W1_MASTER_DS1WM=y
++
++#
++# 1-wire Slaves
++#
++# CONFIG_W1_SLAVE_THERM is not set
++# CONFIG_W1_SLAVE_SMEM is not set
++# CONFIG_W1_SLAVE_DS2433 is not set
++CONFIG_W1_SLAVE_DS2760=y
++CONFIG_POWER_SUPPLY=y
++# CONFIG_POWER_SUPPLY_DEBUG is not set
++CONFIG_PDA_POWER=y
++# CONFIG_APM_POWER is not set
++CONFIG_BATTERY_DS2760=y
++# CONFIG_HWMON is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++CONFIG_HTC_EGPIO=y
++CONFIG_HTC_PASIC3=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_PXA=y
++# CONFIG_FB_PXA_PARAMETERS is not set
++# CONFIG_FB_MBX is not set
++# CONFIG_FB_VIRTUAL is not set
++CONFIG_BACKLIGHT_LCD_SUPPORT=y
++CONFIG_LCD_CLASS_DEVICE=y
++CONFIG_BACKLIGHT_CLASS_DEVICE=y
++CONFIG_BACKLIGHT_CORGI=y
++
++#
++# Display device support
++#
++CONFIG_DISPLAY_SUPPORT=y
++
++#
++# Display hardware drivers
++#
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
++CONFIG_FONTS=y
++# CONFIG_FONT_8x8 is not set
++# CONFIG_FONT_8x16 is not set
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_7x14 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++CONFIG_FONT_MINI_4x6=y
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_10x18 is not set
++# CONFIG_LOGO is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=m
++CONFIG_SND_TIMER=m
++CONFIG_SND_PCM=m
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=m
++CONFIG_SND_PCM_OSS=m
++CONFIG_SND_PCM_OSS_PLUGINS=y
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++# CONFIG_SND_PXA2XX_AC97 is not set
++
++#
++# System on Chip audio support
++#
++CONFIG_SND_SOC=m
++CONFIG_SND_PXA2XX_SOC=m
++
++#
++# SoC Audio support for SuperH
++#
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_HID=m
++# CONFIG_USB_SUPPORT is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++CONFIG_SDIO_UART=m
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_PXA=y
++CONFIG_NEW_LEDS=y
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++CONFIG_RTC_DEBUG=y
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_SA1100=y
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=m
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_LZO=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++CONFIG_NLS_CODEPAGE_1251=m
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++CONFIG_PRINTK_TIME=y
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_SCHED_DEBUG is not set
++# CONFIG_SCHEDSTATS is not set
++CONFIG_TIMER_STATS=y
++# CONFIG_DEBUG_SLAB is not set
++CONFIG_DEBUG_PREEMPT=y
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++CONFIG_DEBUG_VM=y
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=m
++CONFIG_CRYPTO_BLKCIPHER=m
++CONFIG_CRYPTO_MANAGER=m
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++CONFIG_CRYPTO_SHA1=m
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_CBC is not set
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++CONFIG_CRYPTO_ARC4=m
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_LZO_COMPRESS=y
++CONFIG_LZO_DECOMPRESS=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ns9xxx_defconfig b/arch/arm/configs/ns9xxx_defconfig
+index 0e5794c..7dc1580 100644
+--- a/arch/arm/configs/ns9xxx_defconfig
++++ b/arch/arm/configs/ns9xxx_defconfig
+@@ -1,621 +1,79 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.20
+-# Thu Feb 15 20:51:47 2007
+-#
+-CONFIG_ARM=y
+-# CONFIG_GENERIC_TIME is not set
+-CONFIG_MMU=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+-CONFIG_HARDIRQS_SW_RESEND=y
+-CONFIG_GENERIC_IRQ_PROBE=y
+-CONFIG_RWSEM_GENERIC_SPINLOCK=y
+-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_VECTORS_BASE=0xffff0000
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_UTS_NS is not set
+ CONFIG_IKCONFIG=y
+ CONFIG_IKCONFIG_PROC=y
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_UID16=y
+-# CONFIG_SYSCTL_SYSCALL is not set
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_EPOLL=y
+-CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+-# CONFIG_VM_EVENT_COUNTERS is not set
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+-CONFIG_MODULE_FORCE_UNLOAD=y
+-CONFIG_MODVERSIONS=y
+-CONFIG_MODULE_SRCVERSION_ALL=y
+-CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+ # CONFIG_IOSCHED_AS is not set
+ # CONFIG_IOSCHED_DEADLINE is not set
+ # CONFIG_IOSCHED_CFQ is not set
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-CONFIG_DEFAULT_NOOP=y
+-CONFIG_DEFAULT_IOSCHED="noop"
+-
+-#
+-# System Type
+-#
+-# CONFIG_ARCH_AAEC2000 is not set
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_AT91 is not set
+-# CONFIG_ARCH_CLPS7500 is not set
+-# CONFIG_ARCH_CLPS711X is not set
+-# CONFIG_ARCH_CO285 is not set
+-# CONFIG_ARCH_EBSA110 is not set
+-# CONFIG_ARCH_EP93XX is not set
+-# CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_NETX is not set
+-# CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_IMX is not set
+-# CONFIG_ARCH_IOP32X is not set
+-# CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IOP13XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+-# CONFIG_ARCH_IXP23XX is not set
+-# CONFIG_ARCH_L7200 is not set
+ CONFIG_ARCH_NS9XXX=y
+-# CONFIG_ARCH_PNX4008 is not set
+-# CONFIG_ARCH_PXA is not set
+-# CONFIG_ARCH_RPC is not set
+-# CONFIG_ARCH_SA1100 is not set
+-# CONFIG_ARCH_S3C2410 is not set
+-# CONFIG_ARCH_SHARK is not set
+-# CONFIG_ARCH_LH7A40X is not set
+-# CONFIG_ARCH_OMAP is not set
+-
+-#
+-# NS9xxx Implementations
+-#
++CONFIG_MACH_A9M9360=y
++CONFIG_MACH_A9M9750=y
++CONFIG_MACH_CC7UCAMRY=y
++CONFIG_MACH_CC9C=y
++CONFIG_MACH_CC9P9210=y
++CONFIG_MACH_CC9P9210JS=y
++CONFIG_MACH_CC9P9215=y
++CONFIG_MACH_CC9P9215JS=y
+ CONFIG_MACH_CC9P9360DEV=y
+-CONFIG_PROCESSOR_NS9360=y
+-CONFIG_BOARD_A9M9750DEV=y
+-
+-#
+-# Processor Type
+-#
+-CONFIG_CPU_32=y
+-CONFIG_CPU_ARM926T=y
+-CONFIG_CPU_32v5=y
+-CONFIG_CPU_ABRT_EV5TJ=y
+-CONFIG_CPU_CACHE_VIVT=y
+-CONFIG_CPU_COPY_V4WB=y
+-CONFIG_CPU_TLB_V4WBI=y
+-CONFIG_CPU_CP15=y
+-CONFIG_CPU_CP15_MMU=y
+-
+-#
+-# Processor Features
+-#
+-# CONFIG_ARM_THUMB is not set
+-# CONFIG_CPU_ICACHE_DISABLE is not set
+-# CONFIG_CPU_DCACHE_DISABLE is not set
+-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+-# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+-
+-#
+-# Bus support
+-#
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Kernel Features
+-#
+-# CONFIG_PREEMPT is not set
+-# CONFIG_NO_IDLE_HZ is not set
+-CONFIG_HZ=100
+-# CONFIG_AEABI is not set
+-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4096
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ALIGNMENT_TRAP=y
+-
+-#
+-# Boot options
+-#
+-CONFIG_ZBOOT_ROM_TEXT=0x0
+-CONFIG_ZBOOT_ROM_BSS=0x0
+-CONFIG_CMDLINE=""
+-# CONFIG_XIP_KERNEL is not set
+-
+-#
+-# Floating point emulation
+-#
+-
+-#
+-# At least one emulation must be selected
+-#
++CONFIG_MACH_CC9P9360JS=y
++CONFIG_MACH_CC9P9360VAL=y
++CONFIG_MACH_CC9P9750DEV=y
++CONFIG_MACH_CC9P9750VAL=y
++CONFIG_MACH_CCW9C=y
++CONFIG_MACH_INC20OTTER=y
++CONFIG_MACH_OTTER=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
+ CONFIG_FPE_NWFPE=y
+-# CONFIG_FPE_NWFPE_XP is not set
+-# CONFIG_FPE_FASTFPE is not set
+-# CONFIG_VFP is not set
+-
+-#
+-# Userspace binary formats
+-#
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_AOUT is not set
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_ARTHUR is not set
+-
+-#
+-# Power management options
+-#
+-# CONFIG_PM is not set
+-# CONFIG_APM is not set
+-
+-#
+-# Networking
+-#
+-# CONFIG_NET is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+-# CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+-# CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=4096
+-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-CONFIG_BLK_DEV_INITRD=y
+-# CONFIG_CDROM_PKTCDVD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_NETLINK is not set
+-
+-#
+-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+-#
+-# CONFIG_ATA is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+-# CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# ISDN subsystem
+-#
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-CONFIG_SERIO=y
++CONFIG_NET=y
++CONFIG_PACKET=m
++CONFIG_INET=y
++CONFIG_IP_PNP=y
++CONFIG_SYN_COOKIES=y
++CONFIG_MTD=m
++CONFIG_MTD_CONCAT=m
++CONFIG_MTD_CHAR=m
++CONFIG_MTD_BLOCK=m
++CONFIG_MTD_CFI=m
++CONFIG_MTD_JEDECPROBE=m
++CONFIG_MTD_CFI_AMDSTD=m
++CONFIG_MTD_PHYSMAP=m
++CONFIG_MTD_PHYSMAP_START=0x0
++CONFIG_BLK_DEV_LOOP=m
++CONFIG_NETDEVICES=y
++CONFIG_NET_ETHERNET=y
++CONFIG_NS9XXX_ETH=y
+ # CONFIG_SERIO_SERPORT is not set
+-CONFIG_SERIO_LIBPS2=y
+-# CONFIG_SERIO_RAW is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_UNIX98_PTYS=y
++CONFIG_SERIAL_NS921X=y
++CONFIG_SERIAL_NS921X_CONSOLE=y
+ # CONFIG_LEGACY_PTYS is not set
+-
+-#
+-# IPMI
+-#
+-# CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-# CONFIG_WATCHDOG is not set
+ # CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+-# CONFIG_TCG_TPM is not set
+-
+-#
+-# I2C support
+-#
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+-# CONFIG_W1 is not set
+-
+-#
+-# Hardware Monitoring support
+-#
++CONFIG_ADC_NS9215=m
++CONFIG_I2C=m
++CONFIG_I2C_GPIO=m
+ # CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
+-
+-#
+-# Misc devices
+-#
+-# CONFIG_TIFM_CORE is not set
+-
+-#
+-# LED devices
+-#
+-# CONFIG_NEW_LEDS is not set
+-
+-#
+-# LED drivers
+-#
+-
+-#
+-# LED Triggers
+-#
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_FIRMWARE_EDID is not set
+-# CONFIG_FB is not set
+-
+-#
+-# Console display driver support
+-#
+ # CONFIG_VGA_CONSOLE is not set
+-CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-
+-#
+-# HID Devices
+-#
+-CONFIG_HID=y
+-
+-#
+-# USB support
+-#
+-CONFIG_USB_ARCH_HAS_HCD=y
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-
+-#
+-# MMC/SD Card support
+-#
+-# CONFIG_MMC is not set
+-
+-#
+-# Real Time Clock
+-#
+-CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_DNOTIFY is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_USB_SUPPORT is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=m
++CONFIG_LEDS_GPIO=m
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=m
++CONFIG_LEDS_TRIGGER_HEARTBEAT=m
++CONFIG_RTC_CLASS=m
++CONFIG_RTC_DRV_NS9215=m
++CONFIG_EXT2_FS=m
+ CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+-# CONFIG_NLS is not set
+-
+-#
+-# Profiling support
+-#
+-# CONFIG_PROFILING is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
++CONFIG_JFFS2_FS=m
++CONFIG_NFS_FS=y
++CONFIG_ROOT_NFS=y
+ # CONFIG_ENABLE_MUST_CHECK is not set
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_DETECT_SOFTLOCKUP is not set
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_DEBUG_SLAB is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_RWSEMS is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ CONFIG_DEBUG_INFO=y
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-CONFIG_FRAME_POINTER=y
+-CONFIG_FORCED_INLINING=y
+-# CONFIG_RCU_TORTURE_TEST is not set
+ CONFIG_DEBUG_USER=y
+ CONFIG_DEBUG_ERRORS=y
+-CONFIG_DEBUG_LL=y
+-CONFIG_DEBUG_ICEDCC=y
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
+-# CONFIG_CRYPTO is not set
+-
+-#
+-# Library routines
+-#
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC32 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_IOMAP_COPY=y
+diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig
+new file mode 100644
+index 0000000..52cd99b
+--- /dev/null
++++ b/arch/arm/configs/orion5x_defconfig
+@@ -0,0 +1,1383 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24
++# Thu Feb  7 14:10:30 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++CONFIG_ARCH_ORION5X=y
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM7X00A is not set
++
++#
++# Orion Implementations
++#
++CONFIG_MACH_DB88F5281=y
++CONFIG_MACH_RD88F5182=y
++CONFIG_MACH_KUROBOX_PRO=y
++CONFIG_MACH_DNS323=y
++CONFIG_MACH_TS209=y
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_FEROCEON=y
++CONFIG_CPU_FEROCEON_OLD_ID=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5T=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_PCI=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_PREEMPT=y
++CONFIG_HZ=100
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=y
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_LEDS=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++# CONFIG_ATAGS_PROC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++CONFIG_NET_PKTGEN=m
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_EXT=y
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++CONFIG_FTL=y
++CONFIG_NFTL=y
++# CONFIG_NFTL_RW is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++CONFIG_MTD_CFI_I4=y
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP is not set
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++CONFIG_MTD_CFI_STAA=y
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x0
++CONFIG_MTD_PHYSMAP_LEN=0x0
++CONFIG_MTD_PHYSMAP_BANKWIDTH=0
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_IMPA7 is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_CAFE is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++CONFIG_MTD_NAND_ORION=y
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=m
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++CONFIG_SATA_MV=y
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_PATA_ALI is not set
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++# CONFIG_PATA_PLATFORM is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_AX88796 is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++CONFIG_E1000=y
++CONFIG_E1000_NAPI=y
++# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++CONFIG_SKGE=y
++CONFIG_SKY2=y
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++CONFIG_TIGON3=y
++# CONFIG_BNX2 is not set
++CONFIG_MV643XX_ETH=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=16
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++CONFIG_I2C_MV64XXX=y
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++CONFIG_USB_EHCI_TT_NEWSCHED=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_OHCI_HCD is not set
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++CONFIG_USB_PRINTER=y
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++CONFIG_USB_STORAGE_DATAFAB=y
++CONFIG_USB_STORAGE_FREECOM=y
++# CONFIG_USB_STORAGE_ISD200 is not set
++CONFIG_USB_STORAGE_DPCM=y
++# CONFIG_USB_STORAGE_USBAT is not set
++CONFIG_USB_STORAGE_SDDR09=y
++CONFIG_USB_STORAGE_SDDR55=y
++CONFIG_USB_STORAGE_JUMPSHOT=y
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++# CONFIG_LEDS_GPIO is not set
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++CONFIG_RTC_DRV_RS5C372=y
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++CONFIG_RTC_DRV_M41T80=y
++# CONFIG_RTC_DRV_M41T80_WDT is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++# CONFIG_EXT3_FS_XATTR is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++# CONFIG_JOLIET is not set
++# CONFIG_ZISOFS is not set
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_BSD_DISKLABEL=y
++CONFIG_MINIX_SUBPARTITION=y
++CONFIG_SOLARIS_X86_PARTITION=y
++CONFIG_UNIXWARE_DISKLABEL=y
++CONFIG_LDM_PARTITION=y
++CONFIG_LDM_DEBUG=y
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++CONFIG_SUN_PARTITION=y
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++CONFIG_NLS_ISO8859_2=y
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_USER=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=m
++CONFIG_CRYPTO_BLKCIPHER=m
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=m
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=m
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++CONFIG_CRC16=y
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/orion_defconfig b/arch/arm/configs/orion_defconfig
+deleted file mode 100644
+index 1e5aaa6..0000000
+--- a/arch/arm/configs/orion_defconfig
++++ /dev/null
+@@ -1,1383 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.24
+-# Thu Feb  7 14:10:30 2008
+-#
+-CONFIG_ARM=y
+-CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+-CONFIG_GENERIC_GPIO=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_MMU=y
+-# CONFIG_NO_IOPORT is not set
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_STACKTRACE_SUPPORT=y
+-CONFIG_LOCKDEP_SUPPORT=y
+-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+-CONFIG_HARDIRQS_SW_RESEND=y
+-CONFIG_GENERIC_IRQ_PROBE=y
+-CONFIG_RWSEM_GENERIC_SPINLOCK=y
+-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_ZONE_DMA=y
+-CONFIG_VECTORS_BASE=0xffff0000
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_LOCK_KERNEL=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_USER_NS is not set
+-# CONFIG_PID_NS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_FAIR_GROUP_SCHED=y
+-CONFIG_FAIR_USER_SCHED=y
+-# CONFIG_FAIR_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_BLK_DEV_INITRD is not set
+-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_UID16=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-
+-#
+-# System Type
+-#
+-# CONFIG_ARCH_AAEC2000 is not set
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_AT91 is not set
+-# CONFIG_ARCH_CLPS7500 is not set
+-# CONFIG_ARCH_CLPS711X is not set
+-# CONFIG_ARCH_CO285 is not set
+-# CONFIG_ARCH_EBSA110 is not set
+-# CONFIG_ARCH_EP93XX is not set
+-# CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_NETX is not set
+-# CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_IMX is not set
+-# CONFIG_ARCH_IOP13XX is not set
+-# CONFIG_ARCH_IOP32X is not set
+-# CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IXP23XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_L7200 is not set
+-# CONFIG_ARCH_KS8695 is not set
+-# CONFIG_ARCH_NS9XXX is not set
+-# CONFIG_ARCH_MXC is not set
+-CONFIG_ARCH_ORION=y
+-# CONFIG_ARCH_PNX4008 is not set
+-# CONFIG_ARCH_PXA is not set
+-# CONFIG_ARCH_RPC is not set
+-# CONFIG_ARCH_SA1100 is not set
+-# CONFIG_ARCH_S3C2410 is not set
+-# CONFIG_ARCH_SHARK is not set
+-# CONFIG_ARCH_LH7A40X is not set
+-# CONFIG_ARCH_DAVINCI is not set
+-# CONFIG_ARCH_OMAP is not set
+-# CONFIG_ARCH_MSM7X00A is not set
+-
+-#
+-# Orion Implementations
+-#
+-CONFIG_MACH_DB88F5281=y
+-CONFIG_MACH_RD88F5182=y
+-CONFIG_MACH_KUROBOX_PRO=y
+-CONFIG_MACH_DNS323=y
+-CONFIG_MACH_TS209=y
+-
+-#
+-# Boot options
+-#
+-
+-#
+-# Power management
+-#
+-
+-#
+-# Processor Type
+-#
+-CONFIG_CPU_32=y
+-CONFIG_CPU_FEROCEON=y
+-CONFIG_CPU_FEROCEON_OLD_ID=y
+-CONFIG_CPU_32v5=y
+-CONFIG_CPU_ABRT_EV5T=y
+-CONFIG_CPU_CACHE_VIVT=y
+-CONFIG_CPU_COPY_V4WB=y
+-CONFIG_CPU_TLB_V4WBI=y
+-CONFIG_CPU_CP15=y
+-CONFIG_CPU_CP15_MMU=y
+-
+-#
+-# Processor Features
+-#
+-CONFIG_ARM_THUMB=y
+-# CONFIG_CPU_ICACHE_DISABLE is not set
+-# CONFIG_CPU_DCACHE_DISABLE is not set
+-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+-# CONFIG_OUTER_CACHE is not set
+-
+-#
+-# Bus support
+-#
+-CONFIG_PCI=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Kernel Features
+-#
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-CONFIG_PREEMPT=y
+-CONFIG_HZ=100
+-CONFIG_AEABI=y
+-CONFIG_OABI_COMPAT=y
+-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4096
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_LEDS=y
+-CONFIG_LEDS_CPU=y
+-CONFIG_ALIGNMENT_TRAP=y
+-
+-#
+-# Boot options
+-#
+-CONFIG_ZBOOT_ROM_TEXT=0x0
+-CONFIG_ZBOOT_ROM_BSS=0x0
+-CONFIG_CMDLINE=""
+-# CONFIG_XIP_KERNEL is not set
+-# CONFIG_KEXEC is not set
+-# CONFIG_ATAGS_PROC is not set
+-
+-#
+-# Floating point emulation
+-#
+-
+-#
+-# At least one emulation must be selected
+-#
+-CONFIG_FPE_NWFPE=y
+-# CONFIG_FPE_NWFPE_XP is not set
+-# CONFIG_FPE_FASTFPE is not set
+-CONFIG_VFP=y
+-
+-#
+-# Userspace binary formats
+-#
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_AOUT is not set
+-# CONFIG_BINFMT_MISC is not set
+-
+-#
+-# Power management options
+-#
+-# CONFIG_PM is not set
+-CONFIG_ARCH_SUSPEND_POSSIBLE=y
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-CONFIG_PACKET_MMAP=y
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-CONFIG_NET_PKTGEN=m
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-CONFIG_WIRELESS_EXT=y
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_AFS_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-CONFIG_FTL=y
+-CONFIG_NFTL=y
+-# CONFIG_NFTL_RW is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-CONFIG_MTD_CFI_ADV_OPTIONS=y
+-CONFIG_MTD_CFI_NOSWAP=y
+-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+-CONFIG_MTD_CFI_GEOMETRY=y
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-CONFIG_MTD_CFI_I4=y
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_OTP is not set
+-CONFIG_MTD_CFI_INTELEXT=y
+-CONFIG_MTD_CFI_AMDSTD=y
+-CONFIG_MTD_CFI_STAA=y
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0x0
+-CONFIG_MTD_PHYSMAP_LEN=0x0
+-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+-# CONFIG_MTD_ARM_INTEGRATOR is not set
+-# CONFIG_MTD_IMPA7 is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-CONFIG_MTD_NAND=y
+-CONFIG_MTD_NAND_VERIFY_WRITE=y
+-# CONFIG_MTD_NAND_ECC_SMC is not set
+-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+-CONFIG_MTD_NAND_IDS=y
+-# CONFIG_MTD_NAND_DISKONCHIP is not set
+-# CONFIG_MTD_NAND_CAFE is not set
+-# CONFIG_MTD_NAND_NANDSIM is not set
+-# CONFIG_MTD_NAND_PLATFORM is not set
+-# CONFIG_MTD_ALAUDA is not set
+-CONFIG_MTD_NAND_ORION=y
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-# CONFIG_BLK_DEV_RAM is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_SCSI_PROC_FS is not set
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-CONFIG_BLK_DEV_SR=m
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-CONFIG_CHR_DEV_SG=m
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_AHCI is not set
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-CONFIG_SATA_MV=y
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-# CONFIG_SATA_SIL is not set
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-# CONFIG_PATA_ALI is not set
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-# CONFIG_PATA_PLATFORM is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_AX88796 is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_SMC91X is not set
+-# CONFIG_DM9000 is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-CONFIG_E1000=y
+-CONFIG_E1000_NAPI=y
+-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-CONFIG_SKGE=y
+-CONFIG_SKY2=y
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-CONFIG_TIGON3=y
+-# CONFIG_BNX2 is not set
+-CONFIG_MV643XX_ETH=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-CONFIG_INPUT_MOUSEDEV=y
+-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=16
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=m
+-# CONFIG_NVRAM is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_GPIO is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-CONFIG_I2C_MV64XXX=y
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Console display driver support
+-#
+-# CONFIG_VGA_CONSOLE is not set
+-CONFIG_DUMMY_CONSOLE=y
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-CONFIG_USB_HID=y
+-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+-# CONFIG_HID_FF is not set
+-# CONFIG_USB_HIDDEV is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-CONFIG_USB_EHCI_TT_NEWSCHED=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-# CONFIG_USB_OHCI_HCD is not set
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-CONFIG_USB_PRINTER=y
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-CONFIG_USB_STORAGE_DATAFAB=y
+-CONFIG_USB_STORAGE_FREECOM=y
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-CONFIG_USB_STORAGE_DPCM=y
+-# CONFIG_USB_STORAGE_USBAT is not set
+-CONFIG_USB_STORAGE_SDDR09=y
+-CONFIG_USB_STORAGE_SDDR55=y
+-CONFIG_USB_STORAGE_JUMPSHOT=y
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-# CONFIG_USB_MON is not set
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-CONFIG_NEW_LEDS=y
+-CONFIG_LEDS_CLASS=y
+-
+-#
+-# LED drivers
+-#
+-# CONFIG_LEDS_GPIO is not set
+-
+-#
+-# LED Triggers
+-#
+-CONFIG_LEDS_TRIGGERS=y
+-CONFIG_LEDS_TRIGGER_TIMER=y
+-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-CONFIG_RTC_DRV_RS5C372=y
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-CONFIG_RTC_DRV_M41T80=y
+-# CONFIG_RTC_DRV_M41T80_WDT is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-# CONFIG_EXT3_FS_XATTR is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-CONFIG_DNOTIFY=y
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-CONFIG_ISO9660_FS=y
+-# CONFIG_JOLIET is not set
+-# CONFIG_ZISOFS is not set
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-CONFIG_BSD_DISKLABEL=y
+-CONFIG_MINIX_SUBPARTITION=y
+-CONFIG_SOLARIS_X86_PARTITION=y
+-CONFIG_UNIXWARE_DISKLABEL=y
+-CONFIG_LDM_PARTITION=y
+-CONFIG_LDM_DEBUG=y
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-CONFIG_SUN_PARTITION=y
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-CONFIG_NLS_CODEPAGE_437=y
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-CONFIG_NLS_CODEPAGE_850=y
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-CONFIG_NLS_ISO8859_1=y
+-CONFIG_NLS_ISO8859_2=y
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-CONFIG_FRAME_POINTER=y
+-# CONFIG_SAMPLES is not set
+-CONFIG_DEBUG_USER=y
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=m
+-CONFIG_CRYPTO_BLKCIPHER=m
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=m
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=m
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-CONFIG_CRC_CCITT=y
+-CONFIG_CRC16=y
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-CONFIG_LIBCRC32C=y
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/picotux200_defconfig b/arch/arm/configs/picotux200_defconfig
+index 3c0c4f1..95a22f5 100644
+--- a/arch/arm/configs/picotux200_defconfig
++++ b/arch/arm/configs/picotux200_defconfig
+@@ -727,14 +727,14 @@ CONFIG_I2C_CHARDEV=m
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=m
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+ 
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=m
++CONFIG_I2C_GPIO=m
+ # CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+diff --git a/arch/arm/configs/sam9_l9260_defconfig b/arch/arm/configs/sam9_l9260_defconfig
+new file mode 100644
+index 0000000..484dc97
+--- /dev/null
++++ b/arch/arm/configs/sam9_l9260_defconfig
+@@ -0,0 +1,1098 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.23
++# Sun Oct 14 02:01:07 2007
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++CONFIG_AUDIT=y
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=15
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++CONFIG_LSF=y
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Atmel AT91 System-on-Chip
++#
++# CONFIG_ARCH_AT91RM9200 is not set
++CONFIG_ARCH_AT91SAM9260=y
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++
++#
++# AT91SAM9260 Variants
++#
++# CONFIG_ARCH_AT91SAM9260_SAM9XE is not set
++
++#
++# AT91SAM9260 / AT91SAM9XE Board Type
++#
++# CONFIG_MACH_AT91SAM9260EK is not set
++# CONFIG_MACH_CAM60 is not set
++CONFIG_MACH_SAM9_L9260=y
++
++#
++# AT91 Board Options
++#
++CONFIG_MTD_AT91_DATAFLASH_CARD=y
++
++#
++# AT91 Feature Selections
++#
++# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++# CONFIG_ATMEL_TCLIB is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++CONFIG_PREEMPT=y
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=ttyS0,115200 mem=64M initrd=0x21100000,4194304 root=/dev/ram0 rw"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++# CONFIG_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++CONFIG_MTD_BLOCK2MTD=y
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++CONFIG_MTD_NAND_AT91=y
++# CONFIG_MTD_NAND_NANDSIM is not set
++CONFIG_MTD_NAND_PLATFORM=y
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++CONFIG_MTD_UBI=y
++CONFIG_MTD_UBI_WL_THRESHOLD=4096
++CONFIG_MTD_UBI_BEB_RESERVE=3
++CONFIG_MTD_UBI_GLUEBI=y
++
++#
++# UBI debugging options
++#
++# CONFIG_MTD_UBI_DEBUG is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=8192
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# SCSI device support
++#
++CONFIG_RAID_ATTRS=y
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++CONFIG_SCSI_CONSTANTS=y
++CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_SCAN_ASYNC is not set
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_FIXED_PHY is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_MACB=y
++# CONFIG_AX88796 is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET_MII is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_ATMEL=y
++CONFIG_SERIAL_ATMEL_CONSOLE=y
++# CONFIG_SERIAL_ATMEL_TTYAT is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=16
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_WATCHDOG is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_HWMON is not set
++# CONFIG_MISC_DEVICES is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++CONFIG_LEDS_GPIO=y
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++CONFIG_USB_LIBUSUAL=y
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++CONFIG_USB_GADGET_AT91=y
++CONFIG_USB_AT91=y
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++# CONFIG_USB_GADGET_DUALSPEED is not set
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++CONFIG_MMC_DEBUG=y
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_AT91=y
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++CONFIG_RTC_DRV_DS1553=y
++# CONFIG_RTC_DRV_STK17TA8 is not set
++CONFIG_RTC_DRV_DS1742=y
++CONFIG_RTC_DRV_M48T86=y
++# CONFIG_RTC_DRV_M48T59 is not set
++CONFIG_RTC_DRV_V3020=y
++
++#
++# on-CPU RTC drivers
++#
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++CONFIG_EXT3_FS_POSIX_ACL=y
++CONFIG_EXT3_FS_SECURITY=y
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_NFS_DIRECTIO=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_CODEPAGE_737=y
++CONFIG_NLS_CODEPAGE_775=y
++CONFIG_NLS_CODEPAGE_850=y
++CONFIG_NLS_CODEPAGE_852=y
++CONFIG_NLS_CODEPAGE_855=y
++CONFIG_NLS_CODEPAGE_857=y
++CONFIG_NLS_CODEPAGE_860=y
++CONFIG_NLS_CODEPAGE_861=y
++CONFIG_NLS_CODEPAGE_862=y
++CONFIG_NLS_CODEPAGE_863=y
++CONFIG_NLS_CODEPAGE_864=y
++CONFIG_NLS_CODEPAGE_865=y
++CONFIG_NLS_CODEPAGE_866=y
++CONFIG_NLS_CODEPAGE_869=y
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++CONFIG_NLS_CODEPAGE_949=y
++CONFIG_NLS_CODEPAGE_874=y
++CONFIG_NLS_ISO8859_8=y
++CONFIG_NLS_CODEPAGE_1250=y
++CONFIG_NLS_CODEPAGE_1251=y
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++CONFIG_NLS_ISO8859_2=y
++CONFIG_NLS_ISO8859_3=y
++CONFIG_NLS_ISO8859_4=y
++CONFIG_NLS_ISO8859_5=y
++CONFIG_NLS_ISO8859_6=y
++CONFIG_NLS_ISO8859_7=y
++CONFIG_NLS_ISO8859_9=y
++CONFIG_NLS_ISO8859_13=y
++CONFIG_NLS_ISO8859_14=y
++CONFIG_NLS_ISO8859_15=y
++CONFIG_NLS_KOI8_R=y
++CONFIG_NLS_KOI8_U=y
++CONFIG_NLS_UTF8=y
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_UNUSED_SYMBOLS=y
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++CONFIG_DEBUG_PREEMPT=y
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_FORCED_INLINING=y
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_ERRORS is not set
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_AUDIT_GENERIC=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/tct_hammer_defconfig b/arch/arm/configs/tct_hammer_defconfig
+new file mode 100644
+index 0000000..576b833
+--- /dev/null
++++ b/arch/arm/configs/tct_hammer_defconfig
+@@ -0,0 +1,886 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7-hammer
++# Thu Mar 27 16:39:48 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++CONFIG_NO_IOPORT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ARCH_SUPPORTS_AOUT=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++# CONFIG_BUG is not set
++# CONFIG_ELF_CORE is not set
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++# CONFIG_SHMEM is not set
++CONFIG_VM_EVENT_COUNTERS=y
++# CONFIG_SLAB is not set
++# CONFIG_SLUB is not set
++CONFIG_SLOB=y
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++CONFIG_ARCH_S3C2410=y
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM7X00A is not set
++CONFIG_PLAT_S3C24XX=y
++# CONFIG_S3C2410_DMA is not set
++CONFIG_PLAT_S3C=y
++CONFIG_CPU_LLSERIAL_S3C2410_ONLY=y
++CONFIG_CPU_LLSERIAL_S3C2410=y
++
++#
++# Boot options
++#
++# CONFIG_S3C_BOOT_ERROR_RESET is not set
++
++#
++# Power management
++#
++CONFIG_S3C_LOWLEVEL_UART_PORT=0
++
++#
++# S3C2400 Machines
++#
++CONFIG_CPU_S3C2410=y
++CONFIG_S3C2410_GPIO=y
++CONFIG_S3C2410_CLOCK=y
++
++#
++# S3C2410 Machines
++#
++# CONFIG_ARCH_SMDK2410 is not set
++# CONFIG_ARCH_H1940 is not set
++# CONFIG_MACH_N30 is not set
++# CONFIG_ARCH_BAST is not set
++# CONFIG_MACH_OTOM is not set
++# CONFIG_MACH_AML_M5900 is not set
++CONFIG_MACH_TCT_HAMMER=y
++# CONFIG_MACH_VR1000 is not set
++# CONFIG_MACH_QT2410 is not set
++
++#
++# S3C2412 Machines
++#
++# CONFIG_MACH_SMDK2413 is not set
++# CONFIG_MACH_SMDK2412 is not set
++# CONFIG_MACH_VSTMS is not set
++
++#
++# S3C2440 Machines
++#
++# CONFIG_MACH_ANUBIS is not set
++# CONFIG_MACH_OSIRIS is not set
++# CONFIG_MACH_RX3715 is not set
++# CONFIG_ARCH_S3C2440 is not set
++# CONFIG_MACH_NEXCODER_2440 is not set
++
++#
++# S3C2442 Machines
++#
++
++#
++# S3C2443 Machines
++#
++# CONFIG_MACH_SMDK2443 is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4T=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=200
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="mem=64M root=/dev/ram0 init=/linuxrc rw"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++# CONFIG_INET is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++# CONFIG_PREVENT_FIRMWARE_BUILD is not set
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x00000000
++CONFIG_MTD_PHYSMAP_LEN=0x0
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=10240
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_NETDEVICES is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++# CONFIG_VT_CONSOLE is not set
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_S3C2410=y
++CONFIG_SERIAL_S3C2410_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++CONFIG_USB_DEBUG=y
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++# CONFIG_USB_DEVICE_CLASS is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++CONFIG_USB_GADGET_S3C2410=y
++CONFIG_USB_S3C2410=y
++# CONFIG_USB_S3C2410_DEBUG is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++# CONFIG_USB_GADGET_DUALSPEED is not set
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_DNOTIFY is not set
++# CONFIG_INOTIFY is not set
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_SYSCTL is not set
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++# CONFIG_ENABLE_MUST_CHECK is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_DETECT_SOFTLOCKUP is not set
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_USER is not set
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_STACK_USAGE is not set
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++# CONFIG_DEBUG_S3C_PORT is not set
++CONFIG_DEBUG_S3C_UART=0
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/yl9200_defconfig b/arch/arm/configs/yl9200_defconfig
+new file mode 100644
+index 0000000..26de37f
+--- /dev/null
++++ b/arch/arm/configs/yl9200_defconfig
+@@ -0,0 +1,1216 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24-rc6
++# Fri Jan 11 09:53:59 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++# CONFIG_EXPERIMENTAL is not set
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Atmel AT91 System-on-Chip
++#
++CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_AT91SAM9260 is not set
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
++
++#
++# AT91RM9200 Board Type
++#
++# CONFIG_MACH_ONEARM is not set
++CONFIG_ARCH_AT91RM9200DK=y
++# CONFIG_MACH_AT91RM9200EK is not set
++# CONFIG_MACH_CSB337 is not set
++# CONFIG_MACH_CSB637 is not set
++# CONFIG_MACH_CARMEVA is not set
++# CONFIG_MACH_ATEB9200 is not set
++# CONFIG_MACH_KB9200 is not set
++# CONFIG_MACH_PICOTUX2XX is not set
++# CONFIG_MACH_KAFA is not set
++CONFIG_MACH_YL9200=y
++
++#
++# AT91 Board Options
++#
++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
++
++#
++# AT91 Feature Selections
++#
++# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4T=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x0000000
++CONFIG_MTD_PHYSMAP_LEN=0
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_IMPA7 is not set
++CONFIG_MTD_PLATRAM=y
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++CONFIG_MTD_NAND_AT91=y
++# CONFIG_MTD_NAND_NANDSIM is not set
++CONFIG_MTD_NAND_PLATFORM=y
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=3
++CONFIG_BLK_DEV_RAM_SIZE=8192
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++CONFIG_DAVICOM_PHY=y
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_ARM_AT91_ETHER=y
++# CONFIG_AX88796 is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++CONFIG_KEYBOARD_GPIO=y
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ADS7846=y
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++# CONFIG_TOUCHSCREEN_PENMOUNT is not set
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++# CONFIG_TOUCHSCREEN_UCB1400 is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++# CONFIG_SERIO_SERPORT is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_ATMEL=y
++CONFIG_SERIAL_ATMEL_CONSOLE=y
++# CONFIG_SERIAL_ATMEL_TTYAT is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++# CONFIG_I2C_CHARDEV is not set
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_DEBUG=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_ATMEL=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_S1D135XX=y
++# CONFIG_FB_VIRTUAL is not set
++CONFIG_BACKLIGHT_LCD_SUPPORT=y
++CONFIG_LCD_CLASS_DEVICE=y
++# CONFIG_LCD_LTV350QV is not set
++CONFIG_BACKLIGHT_CLASS_DEVICE=y
++# CONFIG_BACKLIGHT_CORGI is not set
++
++#
++# Display device support
++#
++CONFIG_DISPLAY_SUPPORT=y
++
++#
++# Display hardware drivers
++#
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE is not set
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_LOGO_LINUX_CLUT224=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++CONFIG_USB_DEBUG=y
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_DEVICE_CLASS is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++# CONFIG_USB_GADGET_DEBUG_FS is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++CONFIG_USB_GADGET_M66592=y
++CONFIG_USB_M66592=y
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_ETH is not set
++# CONFIG_USB_GADGETFS is not set
++CONFIG_USB_FILE_STORAGE=y
++# CONFIG_USB_FILE_STORAGE_TEST is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++CONFIG_MMC_DEBUG=y
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++# CONFIG_MMC_BLOCK_BOUNCE is not set
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_AT91=y
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++CONFIG_LEDS_GPIO=y
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91RM9200=y
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=y
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_HFSPLUS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=1
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++CONFIG_JFFS2_RUBIN=y
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++CONFIG_INSTRUMENTATION=y
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++# CONFIG_ENABLE_MUST_CHECK is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++CONFIG_SLUB_DEBUG_ON=y
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++CONFIG_DEBUG_KOBJECT=y
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++CONFIG_DEBUG_LIST=y
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
+index 00d44c6..ad455ff 100644
+--- a/arch/arm/kernel/Makefile
++++ b/arch/arm/kernel/Makefile
+@@ -7,7 +7,7 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
+ # Object file lists.
+ 
+ obj-y		:= compat.o entry-armv.o entry-common.o irq.o \
+-		   process.o ptrace.o semaphore.o setup.o signal.o \
++		   process.o ptrace.o setup.o signal.o \
+ 		   sys_arm.o stacktrace.o time.o traps.o
+ 
+ obj-$(CONFIG_ISA_DMA_API)	+= dma.o
+@@ -22,6 +22,7 @@ obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
+ obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-decode.o
+ obj-$(CONFIG_ATAGS_PROC)	+= atags.o
+ obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
++obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
+ 
+ obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
+ AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep9312
+diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
+index 3278e71..0a0d247 100644
+--- a/arch/arm/kernel/asm-offsets.c
++++ b/arch/arm/kernel/asm-offsets.c
+@@ -58,6 +58,9 @@ int main(void)
+   DEFINE(TI_TP_VALUE,		offsetof(struct thread_info, tp_value));
+   DEFINE(TI_FPSTATE,		offsetof(struct thread_info, fpstate));
+   DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate));
++#ifdef CONFIG_ARM_THUMBEE
++  DEFINE(TI_THUMBEE_STATE,	offsetof(struct thread_info, thumbee_state));
++#endif
+ #ifdef CONFIG_IWMMXT
+   DEFINE(TI_IWMMXT_STATE,	offsetof(struct thread_info, fpstate.iwmmxt));
+ #endif
+@@ -108,5 +111,12 @@ int main(void)
+   DEFINE(PROCINFO_INITFUNC,	offsetof(struct proc_info_list, __cpu_flush));
+   DEFINE(PROCINFO_MM_MMUFLAGS,	offsetof(struct proc_info_list, __cpu_mm_mmu_flags));
+   DEFINE(PROCINFO_IO_MMUFLAGS,	offsetof(struct proc_info_list, __cpu_io_mmu_flags));
++  BLANK();
++#ifdef MULTI_DABORT
++  DEFINE(PROCESSOR_DABT_FUNC,	offsetof(struct processor, _data_abort));
++#endif
++#ifdef MULTI_PABORT
++  DEFINE(PROCESSOR_PABT_FUNC,	offsetof(struct processor, _prefetch_abort));
++#endif
+   return 0; 
+ }
+diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
+index 7e97b73..30a67a5 100644
+--- a/arch/arm/kernel/calls.S
++++ b/arch/arm/kernel/calls.S
+@@ -359,9 +359,11 @@
+ 		CALL(sys_kexec_load)
+ 		CALL(sys_utimensat)
+ 		CALL(sys_signalfd)
+-/* 350 */	CALL(sys_ni_syscall)
++/* 350 */	CALL(sys_timerfd_create)
+ 		CALL(sys_eventfd)
+ 		CALL(sys_fallocate)
++		CALL(sys_timerfd_settime)
++		CALL(sys_timerfd_gettime)
+ #ifndef syscalls_counted
+ .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
+ #define syscalls_counted
+diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
+index a46d5b4..7dca225 100644
+--- a/arch/arm/kernel/entry-armv.S
++++ b/arch/arm/kernel/entry-armv.S
+@@ -166,12 +166,12 @@ __dabt_svc:
+ 	@ The abort handler must return the aborted address in r0, and
+ 	@ the fault status register in r1.  r9 must be preserved.
+ 	@
+-#ifdef MULTI_ABORT
++#ifdef MULTI_DABORT
+ 	ldr	r4, .LCprocfns
+ 	mov	lr, pc
+-	ldr	pc, [r4]
++	ldr	pc, [r4, #PROCESSOR_DABT_FUNC]
+ #else
+-	bl	CPU_ABORT_HANDLER
++	bl	CPU_DABORT_HANDLER
+ #endif
+ 
+ 	@
+@@ -209,14 +209,12 @@ __irq_svc:
+ 
+ 	irq_handler
+ #ifdef CONFIG_PREEMPT
++	str	r8, [tsk, #TI_PREEMPT]		@ restore preempt count
+ 	ldr	r0, [tsk, #TI_FLAGS]		@ get flags
++	teq	r8, #0				@ if preempt count != 0
++	movne	r0, #0				@ force flags to 0
+ 	tst	r0, #_TIF_NEED_RESCHED
+ 	blne	svc_preempt
+-preempt_return:
+-	ldr	r0, [tsk, #TI_PREEMPT]		@ read preempt value
+-	str	r8, [tsk, #TI_PREEMPT]		@ restore preempt count
+-	teq	r0, r7
+-	strne	r0, [r0, -r0]			@ bug()
+ #endif
+ 	ldr	r0, [sp, #S_PSR]		@ irqs are already disabled
+ 	msr	spsr_cxsf, r0
+@@ -230,19 +228,11 @@ preempt_return:
+ 
+ #ifdef CONFIG_PREEMPT
+ svc_preempt:
+-	teq	r8, #0				@ was preempt count = 0
+-	ldreq	r6, .LCirq_stat
+-	movne	pc, lr				@ no
+-	ldr	r0, [r6, #4]			@ local_irq_count
+-	ldr	r1, [r6, #8]			@ local_bh_count
+-	adds	r0, r0, r1
+-	movne	pc, lr
+-	mov	r7, #0				@ preempt_schedule_irq
+-	str	r7, [tsk, #TI_PREEMPT]		@ expects preempt_count == 0
++	mov	r8, lr
+ 1:	bl	preempt_schedule_irq		@ irq en/disable is done inside
+ 	ldr	r0, [tsk, #TI_FLAGS]		@ get new tasks TI_FLAGS
+ 	tst	r0, #_TIF_NEED_RESCHED
+-	beq	preempt_return			@ go again
++	moveq	pc, r8				@ go again
+ 	b	1b
+ #endif
+ 
+@@ -293,7 +283,6 @@ __pabt_svc:
+ 	mrs	r9, cpsr
+ 	tst	r3, #PSR_I_BIT
+ 	biceq	r9, r9, #PSR_I_BIT
+-	msr	cpsr_c, r9
+ 
+ 	@
+ 	@ set args, then call main handler
+@@ -301,7 +290,15 @@ __pabt_svc:
+ 	@  r0 - address of faulting instruction
+ 	@  r1 - pointer to registers on stack
+ 	@
+-	mov	r0, r2				@ address (pc)
++#ifdef MULTI_PABORT
++	mov	r0, r2			@ pass address of aborted instruction.
++	ldr	r4, .LCprocfns
++	mov	lr, pc
++	ldr	pc, [r4, #PROCESSOR_PABT_FUNC]
++#else
++	CPU_PABORT_HANDLER(r0, r2)
++#endif
++	msr	cpsr_c, r9			@ Maybe enable interrupts
+ 	mov	r1, sp				@ regs
+ 	bl	do_PrefetchAbort		@ call abort handler
+ 
+@@ -320,16 +317,12 @@ __pabt_svc:
+ 	.align	5
+ .LCcralign:
+ 	.word	cr_alignment
+-#ifdef MULTI_ABORT
++#ifdef MULTI_DABORT
+ .LCprocfns:
+ 	.word	processor
+ #endif
+ .LCfp:
+ 	.word	fp_enter
+-#ifdef CONFIG_PREEMPT
+-.LCirq_stat:
+-	.word	irq_stat
+-#endif
+ 
+ /*
+  * User mode handlers
+@@ -404,12 +397,12 @@ __dabt_usr:
+ 	@ The abort handler must return the aborted address in r0, and
+ 	@ the fault status register in r1.
+ 	@
+-#ifdef MULTI_ABORT
++#ifdef MULTI_DABORT
+ 	ldr	r4, .LCprocfns
+ 	mov	lr, pc
+-	ldr	pc, [r4]
++	ldr	pc, [r4, #PROCESSOR_DABT_FUNC]
+ #else
+-	bl	CPU_ABORT_HANDLER
++	bl	CPU_DABORT_HANDLER
+ #endif
+ 
+ 	@
+@@ -455,10 +448,6 @@ __irq_usr:
+ __und_usr:
+ 	usr_entry
+ 
+-	tst	r3, #PSR_T_BIT			@ Thumb mode?
+-	bne	__und_usr_unknown		@ ignore FP
+-	sub	r4, r2, #4
+-
+ 	@
+ 	@ fall through to the emulation code, which returns using r9 if
+ 	@ it has emulated the instruction, or the more conventional lr
+@@ -468,7 +457,24 @@ __und_usr:
+ 	@
+ 	adr	r9, ret_from_exception
+ 	adr	lr, __und_usr_unknown
+-1:	ldrt	r0, [r4]
++	tst	r3, #PSR_T_BIT			@ Thumb mode?
++	subeq	r4, r2, #4			@ ARM instr at LR - 4
++	subne	r4, r2, #2			@ Thumb instr at LR - 2
++1:	ldreqt	r0, [r4]
++	beq	call_fpe
++	@ Thumb instruction
++#if __LINUX_ARM_ARCH__ >= 7
++2:	ldrht	r5, [r4], #2
++	and	r0, r5, #0xf800			@ mask bits 111x x... .... ....
++	cmp	r0, #0xe800			@ 32bit instruction if xx != 0
++	blo	__und_usr_unknown
++3:	ldrht	r0, [r4]
++	add	r2, r2, #2			@ r2 is PC + 2, make it PC + 4
++	orr	r0, r0, r5, lsl #16
++#else
++	b	__und_usr_unknown
++#endif
++
+ 	@
+ 	@ fallthrough to call_fpe
+ 	@
+@@ -477,10 +483,14 @@ __und_usr:
+  * The out of line fixup for the ldrt above.
+  */
+ 	.section .fixup, "ax"
+-2:	mov	pc, r9
++4:	mov	pc, r9
+ 	.previous
+ 	.section __ex_table,"a"
+-	.long	1b, 2b
++	.long	1b, 4b
++#if __LINUX_ARM_ARCH__ >= 7
++	.long	2b, 4b
++	.long	3b, 4b
++#endif
+ 	.previous
+ 
+ /*
+@@ -507,9 +517,16 @@ __und_usr:
+  *  r10 = this threads thread_info structure.
+  *  lr  = unrecognised instruction return address
+  */
++	@
++	@ Fall-through from Thumb-2 __und_usr
++	@
++#ifdef CONFIG_NEON
++	adr	r6, .LCneon_thumb_opcodes
++	b	2f
++#endif
+ call_fpe:
+ #ifdef CONFIG_NEON
+-	adr	r6, .LCneon_opcodes
++	adr	r6, .LCneon_arm_opcodes
+ 2:
+ 	ldr	r7, [r6], #4			@ mask value
+ 	cmp	r7, #0				@ end mask?
+@@ -526,6 +543,7 @@ call_fpe:
+ 1:
+ #endif
+ 	tst	r0, #0x08000000			@ only CDP/CPRT/LDC/STC have bit 27
++	tstne	r0, #0x04000000			@ bit 26 set on both ARM and Thumb-2
+ #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+ 	and	r8, r0, #0x0f000000		@ mask out op-code bits
+ 	teqne	r8, #0x0f000000			@ SWI (ARM6/7 bug)?
+@@ -577,7 +595,7 @@ call_fpe:
+ #ifdef CONFIG_NEON
+ 	.align	6
+ 
+-.LCneon_opcodes:
++.LCneon_arm_opcodes:
+ 	.word	0xfe000000			@ mask
+ 	.word	0xf2000000			@ opcode
+ 
+@@ -586,6 +604,16 @@ call_fpe:
+ 
+ 	.word	0x00000000			@ mask
+ 	.word	0x00000000			@ opcode
++
++.LCneon_thumb_opcodes:
++	.word	0xef000000			@ mask
++	.word	0xef000000			@ opcode
++
++	.word	0xff100000			@ mask
++	.word	0xf9000000			@ opcode
++
++	.word	0x00000000			@ mask
++	.word	0x00000000			@ opcode
+ #endif
+ 
+ do_fpe:
+@@ -619,8 +647,15 @@ __und_usr_unknown:
+ __pabt_usr:
+ 	usr_entry
+ 
++#ifdef MULTI_PABORT
++	mov	r0, r2			@ pass address of aborted instruction.
++	ldr	r4, .LCprocfns
++	mov	lr, pc
++	ldr	pc, [r4, #PROCESSOR_PABT_FUNC]
++#else
++	CPU_PABORT_HANDLER(r0, r2)
++#endif
+ 	enable_irq				@ Enable interrupts
+-	mov	r0, r2				@ address (pc)
+ 	mov	r1, sp				@ regs
+ 	bl	do_PrefetchAbort		@ call abort handler
+ 	/* fall through */
+diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
+index 6c90c50..597ed00 100644
+--- a/arch/arm/kernel/entry-common.S
++++ b/arch/arm/kernel/entry-common.S
+@@ -352,6 +352,11 @@ sys_mmap2:
+ 		b	do_mmap2
+ #endif
+ 
++ENTRY(pabort_ifar)
++		mrc	p15, 0, r0, cr6, cr0, 2
++ENTRY(pabort_noifar)
++		mov	pc, lr
++
+ #ifdef CONFIG_OABI_COMPAT
+ 
+ /*
+diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
+index 50f667f..7e9c00a 100644
+--- a/arch/arm/kernel/head-common.S
++++ b/arch/arm/kernel/head-common.S
+@@ -75,8 +75,13 @@ __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.\n"
++str_p1:	.asciz	"\nError: unrecognized/unsupported processor variant (0x"
++str_p2:	.asciz	").\n"
+ 	.align
+ #endif
+ 
+diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
+deleted file mode 100644
+index 981fe5c..0000000
+--- a/arch/arm/kernel/semaphore.c
++++ /dev/null
+@@ -1,221 +0,0 @@
+-/*
+- *  ARM semaphore implementation, taken from
+- *
+- *  i386 semaphore implementation.
+- *
+- *  (C) Copyright 1999 Linus Torvalds
+- *
+- *  Modified for ARM by Russell King
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is
+- * protected by the semaphore spinlock.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- *  - only on a boundary condition do we need to care. When we go
+- *    from a negative count to a non-negative, we wake people up.
+- *  - when we go from a non-negative count to a negative do we
+- *    (a) synchronize with the "sleeper" count and (b) make sure
+- *    that we're on the wakeup list before we synchronize so that
+- *    we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+-	wake_up(&sem->wait);
+-}
+-
+-static DEFINE_SPINLOCK(semaphore_lock);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	tsk->state = TASK_UNINTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	spin_lock_irq(&semaphore_lock);
+-	sem->sleepers++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irq(&semaphore_lock);
+-
+-		schedule();
+-		tsk->state = TASK_UNINTERRUPTIBLE;
+-		spin_lock_irq(&semaphore_lock);
+-	}
+-	spin_unlock_irq(&semaphore_lock);
+-	remove_wait_queue(&sem->wait, &wait);
+-	tsk->state = TASK_RUNNING;
+-	wake_up(&sem->wait);
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	tsk->state = TASK_INTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	spin_lock_irq(&semaphore_lock);
+-	sem->sleepers ++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * With signals pending, this turns into
+-		 * the trylock failure case - we won't be
+-		 * sleeping, and we* can't get the lock as
+-		 * it has contention. Just correct the count
+-		 * and exit.
+-		 */
+-		if (signal_pending(current)) {
+-			retval = -EINTR;
+-			sem->sleepers = 0;
+-			atomic_add(sleepers, &sem->count);
+-			break;
+-		}
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock. The
+-		 * "-1" is because we're still hoping to get
+-		 * the lock.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irq(&semaphore_lock);
+-
+-		schedule();
+-		tsk->state = TASK_INTERRUPTIBLE;
+-		spin_lock_irq(&semaphore_lock);
+-	}
+-	spin_unlock_irq(&semaphore_lock);
+-	tsk->state = TASK_RUNNING;
+-	remove_wait_queue(&sem->wait, &wait);
+-	wake_up(&sem->wait);
+-	return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- *
+- * We could have done the trylock with a
+- * single "cmpxchg" without failure cases,
+- * but then it wouldn't work on a 386.
+- */
+-int __down_trylock(struct semaphore * sem)
+-{
+-	int sleepers;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_lock, flags);
+-	sleepers = sem->sleepers + 1;
+-	sem->sleepers = 0;
+-
+-	/*
+-	 * Add "everybody else" and us into it. They aren't
+-	 * playing, because we own the spinlock.
+-	 */
+-	if (!atomic_add_negative(sleepers, &sem->count))
+-		wake_up(&sem->wait);
+-
+-	spin_unlock_irqrestore(&semaphore_lock, flags);
+-	return 1;
+-}
+-
+-/*
+- * The semaphore operations have a special calling sequence that
+- * allow us to do a simpler in-line version of them. These routines
+- * need to convert that sequence back into the C sequence when
+- * there is contention on the semaphore.
+- *
+- * ip contains the semaphore pointer on entry. Save the C-clobbered
+- * registers (r0 to r3 and lr), but not ip, as we use it as a return
+- * value in some cases..
+- * To remain AAPCS compliant (64-bit stack align) we save r4 as well.
+- */
+-asm("	.section .sched.text,\"ax\",%progbits	\n\
+-	.align	5				\n\
+-	.globl	__down_failed			\n\
+-__down_failed:					\n\
+-	stmfd	sp!, {r0 - r4, lr}		\n\
+-	mov	r0, ip				\n\
+-	bl	__down				\n\
+-	ldmfd	sp!, {r0 - r4, pc}		\n\
+-						\n\
+-	.align	5				\n\
+-	.globl	__down_interruptible_failed	\n\
+-__down_interruptible_failed:			\n\
+-	stmfd	sp!, {r0 - r4, lr}		\n\
+-	mov	r0, ip				\n\
+-	bl	__down_interruptible		\n\
+-	mov	ip, r0				\n\
+-	ldmfd	sp!, {r0 - r4, pc}		\n\
+-						\n\
+-	.align	5				\n\
+-	.globl	__down_trylock_failed		\n\
+-__down_trylock_failed:				\n\
+-	stmfd	sp!, {r0 - r4, lr}		\n\
+-	mov	r0, ip				\n\
+-	bl	__down_trylock			\n\
+-	mov	ip, r0				\n\
+-	ldmfd	sp!, {r0 - r4, pc}		\n\
+-						\n\
+-	.align	5				\n\
+-	.globl	__up_wakeup			\n\
+-__up_wakeup:					\n\
+-	stmfd	sp!, {r0 - r4, lr}		\n\
+-	mov	r0, ip				\n\
+-	bl	__up				\n\
+-	ldmfd	sp!, {r0 - r4, pc}		\n\
+-	");
+-
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_interruptible_failed);
+-EXPORT_SYMBOL(__down_trylock_failed);
+-EXPORT_SYMBOL(__up_wakeup);
+diff --git a/arch/arm/kernel/thumbee.c b/arch/arm/kernel/thumbee.c
+new file mode 100644
+index 0000000..df3f6b7
+--- /dev/null
++++ b/arch/arm/kernel/thumbee.c
+@@ -0,0 +1,81 @@
++/*
++ * arch/arm/kernel/thumbee.c
++ *
++ * Copyright (C) 2008 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <asm/thread_notify.h>
++
++/*
++ * Access to the ThumbEE Handler Base register
++ */
++static inline unsigned long teehbr_read()
++{
++	unsigned long v;
++	asm("mrc	p14, 6, %0, c1, c0, 0\n" : "=r" (v));
++	return v;
++}
++
++static inline void teehbr_write(unsigned long v)
++{
++	asm("mcr	p14, 6, %0, c1, c0, 0\n" : : "r" (v));
++}
++
++static int thumbee_notifier(struct notifier_block *self, unsigned long cmd, void *t)
++{
++	struct thread_info *thread = t;
++
++	switch (cmd) {
++	case THREAD_NOTIFY_FLUSH:
++		thread->thumbee_state = 0;
++		break;
++	case THREAD_NOTIFY_SWITCH:
++		current_thread_info()->thumbee_state = teehbr_read();
++		teehbr_write(thread->thumbee_state);
++		break;
++	}
++
++	return NOTIFY_DONE;
++}
++
++static struct notifier_block thumbee_notifier_block = {
++	.notifier_call	= thumbee_notifier,
++};
++
++static int __init thumbee_init(void)
++{
++	unsigned long pfr0;
++	unsigned int cpu_arch = cpu_architecture();
++
++	if (cpu_arch < CPU_ARCH_ARMv7)
++		return 0;
++
++	/* processor feature register 0 */
++	asm("mrc	p15, 0, %0, c0, c1, 0\n" : "=r" (pfr0));
++	if ((pfr0 & 0x0000f000) != 0x00001000)
++		return 0;
++
++	printk(KERN_INFO "ThumbEE CPU extension supported.\n");
++	elf_hwcap |= HWCAP_THUMBEE;
++	thread_register_notifier(&thumbee_notifier_block);
++
++	return 0;
++}
++
++late_initcall(thumbee_init);
+diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c
+index 74aa7a3..e10ee15 100644
+--- a/arch/arm/mach-aaec2000/clock.c
++++ b/arch/arm/mach-aaec2000/clock.c
+@@ -18,8 +18,6 @@
+ #include <linux/clk.h>
+ #include <linux/mutex.h>
+ 
+-#include <asm/semaphore.h>
+-
+ #include "clock.h"
+ 
+ static LIST_HEAD(clocks);
+diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
+index 074dcd5..0fc07b6 100644
+--- a/arch/arm/mach-at91/Kconfig
++++ b/arch/arm/mach-at91/Kconfig
+@@ -12,18 +12,28 @@ config ARCH_AT91RM9200
+ 
+ config ARCH_AT91SAM9260
+ 	bool "AT91SAM9260 or AT91SAM9XE"
++	select GENERIC_TIME
++	select GENERIC_CLOCKEVENTS
+ 
+ config ARCH_AT91SAM9261
+ 	bool "AT91SAM9261"
++	select GENERIC_TIME
++	select GENERIC_CLOCKEVENTS
+ 
+ config ARCH_AT91SAM9263
+ 	bool "AT91SAM9263"
++	select GENERIC_TIME
++	select GENERIC_CLOCKEVENTS
+ 
+ config ARCH_AT91SAM9RL
+ 	bool "AT91SAM9RL"
++	select GENERIC_TIME
++	select GENERIC_CLOCKEVENTS
+ 
+ config ARCH_AT91CAP9
+ 	bool "AT91CAP9"
++	select GENERIC_TIME
++	select GENERIC_CLOCKEVENTS
+ 
+ config ARCH_AT91X40
+ 	bool "AT91x40"
+@@ -109,6 +119,13 @@ config MACH_KAFA
+ 	help
+ 	  Select this if you are using Sperry-Sun's KAFA board.
+ 
++config MACH_ECBAT91
++	bool "emQbit ECB_AT91 SBC"
++	depends on ARCH_AT91RM9200
++	help
++	  Select this if you are using emQbit's ECB_AT91 board.
++	  <http://wiki.emqbit.com/free-ecb-at91>
++
+ endif
+ 
+ # ----------------------------------------------------------
+@@ -133,6 +150,20 @@ config MACH_AT91SAM9260EK
+ 	  Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
+ 	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
+ 
++config MACH_CAM60
++	bool "KwikByte KB9260 (CAM60) board"
++	depends on ARCH_AT91SAM9260
++	help
++	  Select this if you are using KwikByte's KB9260 (CAM60) board based on the Atmel AT91SAM9260.
++	  <http://www.kwikbyte.com/KB9260.html>
++
++config MACH_SAM9_L9260
++	bool "Olimex SAM9-L9260 board"
++	depends on ARCH_AT91SAM9260
++	help
++	  Select this if you are using Olimex's SAM9-L9260 board based on the Atmel AT91SAM9260.
++	  <http://www.olimex.com/dev/sam9-L9260.html>
++
+ endif
+ 
+ # ----------------------------------------------------------
+@@ -216,7 +247,7 @@ comment "AT91 Board Options"
+ 
+ config MTD_AT91_DATAFLASH_CARD
+ 	bool "Enable DataFlash Card support"
+-	depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91CAP9ADK)
++	depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91CAP9ADK || MACH_SAM9_L9260 || MACH_ECBAT91)
+ 	help
+ 	  Enable support for the DataFlash card.
+ 
+diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
+index bf5f293..8d9bc01 100644
+--- a/arch/arm/mach-at91/Makefile
++++ b/arch/arm/mach-at91/Makefile
+@@ -29,9 +29,12 @@ obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o
+ obj-$(CONFIG_MACH_ATEB9200)	+= board-eb9200.o
+ obj-$(CONFIG_MACH_KAFA)		+= board-kafa.o
+ obj-$(CONFIG_MACH_PICOTUX2XX)	+= board-picotux200.o
++obj-$(CONFIG_MACH_ECBAT91)	+= board-ecbat91.o
+ 
+ # AT91SAM9260 board-specific support
+ obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
++obj-$(CONFIG_MACH_CAM60)	+= board-cam60.o
++obj-$(CONFIG_MACH_SAM9_L9260)	+= board-sam9-l9260.o
+ 
+ # AT91SAM9261 board-specific support
+ obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
+diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
+index 48d27d8..933fa8f 100644
+--- a/arch/arm/mach-at91/at91cap9.c
++++ b/arch/arm/mach-at91/at91cap9.c
+@@ -13,12 +13,14 @@
+  */
+ 
+ #include <linux/module.h>
++#include <linux/pm.h>
+ 
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/arch/at91cap9.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+ 
+ #include "generic.h"
+ #include "clock.h"
+@@ -288,6 +290,12 @@ static void at91cap9_reset(void)
+ 	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+ 
++static void at91cap9_poweroff(void)
++{
++	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
++
+ /* --------------------------------------------------------------------
+  *  AT91CAP9 processor initialization
+  * -------------------------------------------------------------------- */
+@@ -298,6 +306,7 @@ void __init at91cap9_initialize(unsigned long main_clock)
+ 	iotable_init(at91cap9_io_desc, ARRAY_SIZE(at91cap9_io_desc));
+ 
+ 	at91_arch_reset = at91cap9_reset;
++	pm_power_off = at91cap9_poweroff;
+ 	at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1);
+ 
+ 	/* Init clock subsystem */
+diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
+index c50fad9..f1a80d7 100644
+--- a/arch/arm/mach-at91/at91cap9_devices.c
++++ b/arch/arm/mach-at91/at91cap9_devices.c
+@@ -16,15 +16,15 @@
+ 
+ #include <linux/dma-mapping.h>
+ #include <linux/platform_device.h>
+-#include <linux/mtd/physmap.h>
++#include <linux/i2c-gpio.h>
+ 
+ #include <video/atmel_lcdc.h>
+ 
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91cap9.h>
+-#include <asm/arch/at91sam926x_mc.h>
+ #include <asm/arch/at91cap9_matrix.h>
++#include <asm/arch/at91sam9_smc.h>
+ 
+ #include "generic.h"
+ 
+@@ -283,10 +283,15 @@ static struct at91_nand_data nand_data;
+ #define NAND_BASE	AT91_CHIPSELECT_3
+ 
+ static struct resource nand_resources[] = {
+-	{
++	[0] = {
+ 		.start	= NAND_BASE,
+ 		.end	= NAND_BASE + SZ_256M - 1,
+ 		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91_BASE_SYS + AT91_ECC,
++		.end	= AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
++		.flags	= IORESOURCE_MEM,
+ 	}
+ };
+ 
+@@ -344,6 +349,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
+ void __init at91_add_device_nand(struct at91_nand_data *data) {}
+ #endif
+ 
++
+ /* --------------------------------------------------------------------
+  *  TWI (i2c)
+  * -------------------------------------------------------------------- */
+@@ -532,13 +538,59 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+ 
+ 
+ /* --------------------------------------------------------------------
++ *  Timer/Counter block
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb_resources[] = {
++	[0] = {
++		.start	= AT91CAP9_BASE_TCB0,
++		.end	= AT91CAP9_BASE_TCB0 + SZ_16K - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91CAP9_ID_TCB,
++		.end	= AT91CAP9_ID_TCB,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device at91cap9_tcb_device = {
++	.name		= "atmel_tcb",
++	.id		= 0,
++	.resource	= tcb_resources,
++	.num_resources	= ARRAY_SIZE(tcb_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++	/* this chip has one clock and irq for all three TC channels */
++	at91_clock_associate("tcb_clk", &at91cap9_tcb_device.dev, "t0_clk");
++	platform_device_register(&at91cap9_tcb_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+  *  RTT
+  * -------------------------------------------------------------------- */
+ 
++static struct resource rtt_resources[] = {
++	{
++		.start	= AT91_BASE_SYS + AT91_RTT,
++		.end	= AT91_BASE_SYS + AT91_RTT + SZ_16 - 1,
++		.flags	= IORESOURCE_MEM,
++	}
++};
++
+ static struct platform_device at91cap9_rtt_device = {
+ 	.name		= "at91_rtt",
+-	.id		= -1,
+-	.num_resources	= 0,
++	.id		= 0,
++	.resource	= rtt_resources,
++	.num_resources	= ARRAY_SIZE(rtt_resources),
+ };
+ 
+ static void __init at91_add_device_rtt(void)
+@@ -990,7 +1042,7 @@ static inline void configure_usart2_pins(unsigned pins)
+ 		at91_set_B_periph(AT91_PIN_PD6, 0);	/* CTS2 */
+ }
+ 
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+ struct platform_device *atmel_default_console_device;	/* the serial console device */
+ 
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+@@ -1031,8 +1083,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ 	if (portnr < ATMEL_MAX_UART)
+ 		atmel_default_console_device = at91_uarts[portnr];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ 
+ void __init at91_add_device_serial(void)
+@@ -1043,6 +1093,9 @@ void __init at91_add_device_serial(void)
+ 		if (at91_uarts[i])
+ 			platform_device_register(at91_uarts[i]);
+ 	}
++
++	if (!atmel_default_console_device)
++		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+@@ -1060,6 +1113,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ 	at91_add_device_rtt();
+ 	at91_add_device_watchdog();
++	at91_add_device_tc();
+ 	return 0;
+ }
+ 
+diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
+index ef6aeb8..de19bee 100644
+--- a/arch/arm/mach-at91/at91rm9200_devices.c
++++ b/arch/arm/mach-at91/at91rm9200_devices.c
+@@ -577,6 +577,90 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+ 
+ 
+ /* --------------------------------------------------------------------
++ *  Timer/Counter blocks
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb0_resources[] = {
++	[0] = {
++		.start	= AT91RM9200_BASE_TCB0,
++		.end	= AT91RM9200_BASE_TCB0 + SZ_16K - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91RM9200_ID_TC0,
++		.end	= AT91RM9200_ID_TC0,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[2] = {
++		.start	= AT91RM9200_ID_TC1,
++		.end	= AT91RM9200_ID_TC1,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[3] = {
++		.start	= AT91RM9200_ID_TC2,
++		.end	= AT91RM9200_ID_TC2,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device at91rm9200_tcb0_device = {
++	.name		= "atmel_tcb",
++	.id		= 0,
++	.resource	= tcb0_resources,
++	.num_resources	= ARRAY_SIZE(tcb0_resources),
++};
++
++static struct resource tcb1_resources[] = {
++	[0] = {
++		.start	= AT91RM9200_BASE_TCB1,
++		.end	= AT91RM9200_BASE_TCB1 + SZ_16K - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91RM9200_ID_TC3,
++		.end	= AT91RM9200_ID_TC3,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[2] = {
++		.start	= AT91RM9200_ID_TC4,
++		.end	= AT91RM9200_ID_TC4,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[3] = {
++		.start	= AT91RM9200_ID_TC5,
++		.end	= AT91RM9200_ID_TC5,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device at91rm9200_tcb1_device = {
++	.name		= "atmel_tcb",
++	.id		= 1,
++	.resource	= tcb1_resources,
++	.num_resources	= ARRAY_SIZE(tcb1_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++	/* this chip has a separate clock and irq for each TC channel */
++	at91_clock_associate("tc0_clk", &at91rm9200_tcb0_device.dev, "t0_clk");
++	at91_clock_associate("tc1_clk", &at91rm9200_tcb0_device.dev, "t1_clk");
++	at91_clock_associate("tc2_clk", &at91rm9200_tcb0_device.dev, "t2_clk");
++	platform_device_register(&at91rm9200_tcb0_device);
++
++	at91_clock_associate("tc3_clk", &at91rm9200_tcb1_device.dev, "t0_clk");
++	at91_clock_associate("tc4_clk", &at91rm9200_tcb1_device.dev, "t1_clk");
++	at91_clock_associate("tc5_clk", &at91rm9200_tcb1_device.dev, "t2_clk");
++	platform_device_register(&at91rm9200_tcb1_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+  *  RTC
+  * -------------------------------------------------------------------- */
+ 
+@@ -1019,7 +1103,7 @@ static inline void configure_usart3_pins(unsigned pins)
+ 		at91_set_B_periph(AT91_PIN_PB0, 0);	/* RTS3 */
+ }
+ 
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+ struct platform_device *atmel_default_console_device;	/* the serial console device */
+ 
+ void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+@@ -1110,8 +1194,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ 	if (portnr < ATMEL_MAX_UART)
+ 		atmel_default_console_device = at91_uarts[portnr];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ 
+ void __init at91_add_device_serial(void)
+@@ -1122,6 +1204,9 @@ void __init at91_add_device_serial(void)
+ 		if (at91_uarts[i])
+ 			platform_device_register(at91_uarts[i]);
+ 	}
++
++	if (!atmel_default_console_device)
++		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+ void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
+@@ -1141,6 +1226,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ 	at91_add_device_rtc();
+ 	at91_add_device_watchdog();
++	at91_add_device_tc();
+ 	return 0;
+ }
+ 
+diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
+index 18d0661..ee26550 100644
+--- a/arch/arm/mach-at91/at91sam9260.c
++++ b/arch/arm/mach-at91/at91sam9260.c
+@@ -11,6 +11,7 @@
+  */
+ 
+ #include <linux/module.h>
++#include <linux/pm.h>
+ 
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+@@ -18,6 +19,7 @@
+ #include <asm/arch/at91sam9260.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+ 
+ #include "generic.h"
+ #include "clock.h"
+@@ -267,6 +269,11 @@ static void at91sam9260_reset(void)
+ 	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+ 
++static void at91sam9260_poweroff(void)
++{
++	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
+ 
+ /* --------------------------------------------------------------------
+  *  AT91SAM9260 processor initialization
+@@ -304,6 +311,7 @@ void __init at91sam9260_initialize(unsigned long main_clock)
+ 		iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
+ 
+ 	at91_arch_reset = at91sam9260_reset;
++	pm_power_off = at91sam9260_poweroff;
+ 	at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
+ 			| (1 << AT91SAM9260_ID_IRQ2);
+ 
+diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
+index 105f840..393a32a 100644
+--- a/arch/arm/mach-at91/at91sam9260_devices.c
++++ b/arch/arm/mach-at91/at91sam9260_devices.c
+@@ -19,8 +19,8 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91sam9260.h>
+-#include <asm/arch/at91sam926x_mc.h>
+ #include <asm/arch/at91sam9260_matrix.h>
++#include <asm/arch/at91sam9_smc.h>
+ 
+ #include "generic.h"
+ 
+@@ -288,10 +288,15 @@ static struct at91_nand_data nand_data;
+ #define NAND_BASE	AT91_CHIPSELECT_3
+ 
+ static struct resource nand_resources[] = {
+-	{
++	[0] = {
+ 		.start	= NAND_BASE,
+ 		.end	= NAND_BASE + SZ_256M - 1,
+ 		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91_BASE_SYS + AT91_ECC,
++		.end	= AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
++		.flags	= IORESOURCE_MEM,
+ 	}
+ };
+ 
+@@ -540,6 +545,90 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+ 
+ 
+ /* --------------------------------------------------------------------
++ *  Timer/Counter blocks
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb0_resources[] = {
++	[0] = {
++		.start	= AT91SAM9260_BASE_TCB0,
++		.end	= AT91SAM9260_BASE_TCB0 + SZ_16K - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91SAM9260_ID_TC0,
++		.end	= AT91SAM9260_ID_TC0,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[2] = {
++		.start	= AT91SAM9260_ID_TC1,
++		.end	= AT91SAM9260_ID_TC1,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[3] = {
++		.start	= AT91SAM9260_ID_TC2,
++		.end	= AT91SAM9260_ID_TC2,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device at91sam9260_tcb0_device = {
++	.name		= "atmel_tcb",
++	.id		= 0,
++	.resource	= tcb0_resources,
++	.num_resources	= ARRAY_SIZE(tcb0_resources),
++};
++
++static struct resource tcb1_resources[] = {
++	[0] = {
++		.start	= AT91SAM9260_BASE_TCB1,
++		.end	= AT91SAM9260_BASE_TCB1 + SZ_16K - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91SAM9260_ID_TC3,
++		.end	= AT91SAM9260_ID_TC3,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[2] = {
++		.start	= AT91SAM9260_ID_TC4,
++		.end	= AT91SAM9260_ID_TC4,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[3] = {
++		.start	= AT91SAM9260_ID_TC5,
++		.end	= AT91SAM9260_ID_TC5,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device at91sam9260_tcb1_device = {
++	.name		= "atmel_tcb",
++	.id		= 1,
++	.resource	= tcb1_resources,
++	.num_resources	= ARRAY_SIZE(tcb1_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++	/* this chip has a separate clock and irq for each TC channel */
++	at91_clock_associate("tc0_clk", &at91sam9260_tcb0_device.dev, "t0_clk");
++	at91_clock_associate("tc1_clk", &at91sam9260_tcb0_device.dev, "t1_clk");
++	at91_clock_associate("tc2_clk", &at91sam9260_tcb0_device.dev, "t2_clk");
++	platform_device_register(&at91sam9260_tcb0_device);
++
++	at91_clock_associate("tc3_clk", &at91sam9260_tcb1_device.dev, "t0_clk");
++	at91_clock_associate("tc4_clk", &at91sam9260_tcb1_device.dev, "t1_clk");
++	at91_clock_associate("tc5_clk", &at91sam9260_tcb1_device.dev, "t2_clk");
++	platform_device_register(&at91sam9260_tcb1_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+  *  RTT
+  * -------------------------------------------------------------------- */
+ 
+@@ -553,7 +642,7 @@ static struct resource rtt_resources[] = {
+ 
+ static struct platform_device at91sam9260_rtt_device = {
+ 	.name		= "at91_rtt",
+-	.id		= -1,
++	.id		= 0,
+ 	.resource	= rtt_resources,
+ 	.num_resources	= ARRAY_SIZE(rtt_resources),
+ };
+@@ -962,64 +1051,9 @@ static inline void configure_usart5_pins(void)
+ 	at91_set_A_periph(AT91_PIN_PB13, 0);		/* RXD5 */
+ }
+ 
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+ struct platform_device *atmel_default_console_device;	/* the serial console device */
+ 
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+-{
+-	int i;
+-
+-	/* Fill in list of supported UARTs */
+-	for (i = 0; i < config->nr_tty; i++) {
+-		switch (config->tty_map[i]) {
+-			case 0:
+-				configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS | ATMEL_UART_DSR | ATMEL_UART_DTR | ATMEL_UART_DCD | ATMEL_UART_RI);
+-				at91_uarts[i] = &at91sam9260_uart0_device;
+-				at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart");
+-				break;
+-			case 1:
+-				configure_usart1_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+-				at91_uarts[i] = &at91sam9260_uart1_device;
+-				at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart");
+-				break;
+-			case 2:
+-				configure_usart2_pins(0);
+-				at91_uarts[i] = &at91sam9260_uart2_device;
+-				at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart");
+-				break;
+-			case 3:
+-				configure_usart3_pins(0);
+-				at91_uarts[i] = &at91sam9260_uart3_device;
+-				at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart");
+-				break;
+-			case 4:
+-				configure_usart4_pins();
+-				at91_uarts[i] = &at91sam9260_uart4_device;
+-				at91_clock_associate("usart4_clk", &at91sam9260_uart4_device.dev, "usart");
+-				break;
+-			case 5:
+-				configure_usart5_pins();
+-				at91_uarts[i] = &at91sam9260_uart5_device;
+-				at91_clock_associate("usart5_clk", &at91sam9260_uart5_device.dev, "usart");
+-				break;
+-			case 6:
+-				configure_dbgu_pins();
+-				at91_uarts[i] = &at91sam9260_dbgu_device;
+-				at91_clock_associate("mck", &at91sam9260_dbgu_device.dev, "usart");
+-				break;
+-			default:
+-				continue;
+-		}
+-		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+-	}
+-
+-	/* Set serial console device */
+-	if (config->console_tty < ATMEL_MAX_UART)
+-		atmel_default_console_device = at91_uarts[config->console_tty];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+-}
+-
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+ {
+ 	struct platform_device *pdev;
+@@ -1073,8 +1107,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ 	if (portnr < ATMEL_MAX_UART)
+ 		atmel_default_console_device = at91_uarts[portnr];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ 
+ void __init at91_add_device_serial(void)
+@@ -1085,9 +1117,11 @@ void __init at91_add_device_serial(void)
+ 		if (at91_uarts[i])
+ 			platform_device_register(at91_uarts[i]);
+ 	}
++
++	if (!atmel_default_console_device)
++		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+ void __init at91_set_serial_console(unsigned portnr) {}
+ void __init at91_add_device_serial(void) {}
+@@ -1103,6 +1137,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ 	at91_add_device_rtt();
+ 	at91_add_device_watchdog();
++	at91_add_device_tc();
+ 	return 0;
+ }
+ 
+diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
+index 90b87e1..35bf6fd 100644
+--- a/arch/arm/mach-at91/at91sam9261.c
++++ b/arch/arm/mach-at91/at91sam9261.c
+@@ -11,12 +11,14 @@
+  */
+ 
+ #include <linux/module.h>
++#include <linux/pm.h>
+ 
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/arch/at91sam9261.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+ 
+ #include "generic.h"
+ #include "clock.h"
+@@ -245,6 +247,11 @@ static void at91sam9261_reset(void)
+ 	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+ 
++static void at91sam9261_poweroff(void)
++{
++	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
+ 
+ /* --------------------------------------------------------------------
+  *  AT91SAM9261 processor initialization
+@@ -256,6 +263,7 @@ void __init at91sam9261_initialize(unsigned long main_clock)
+ 	iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
+ 
+ 	at91_arch_reset = at91sam9261_reset;
++	pm_power_off = at91sam9261_poweroff;
+ 	at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
+ 			| (1 << AT91SAM9261_ID_IRQ2);
+ 
+diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
+index 2456412..37cd547 100644
+--- a/arch/arm/mach-at91/at91sam9261_devices.c
++++ b/arch/arm/mach-at91/at91sam9261_devices.c
+@@ -24,7 +24,7 @@
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91sam9261.h>
+ #include <asm/arch/at91sam9261_matrix.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+ 
+ #include "generic.h"
+ 
+@@ -548,6 +548,55 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+ 
+ 
+ /* --------------------------------------------------------------------
++ *  Timer/Counter block
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb_resources[] = {
++	[0] = {
++		.start	= AT91SAM9261_BASE_TCB0,
++		.end	= AT91SAM9261_BASE_TCB0 + SZ_16K - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91SAM9261_ID_TC0,
++		.end	= AT91SAM9261_ID_TC0,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[2] = {
++		.start	= AT91SAM9261_ID_TC1,
++		.end	= AT91SAM9261_ID_TC1,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[3] = {
++		.start	= AT91SAM9261_ID_TC2,
++		.end	= AT91SAM9261_ID_TC2,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device at91sam9261_tcb_device = {
++	.name		= "atmel_tcb",
++	.id		= 0,
++	.resource	= tcb_resources,
++	.num_resources	= ARRAY_SIZE(tcb_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++	/* this chip has a separate clock and irq for each TC channel */
++	at91_clock_associate("tc0_clk", &at91sam9261_tcb_device.dev, "t0_clk");
++	at91_clock_associate("tc1_clk", &at91sam9261_tcb_device.dev, "t1_clk");
++	at91_clock_associate("tc2_clk", &at91sam9261_tcb_device.dev, "t2_clk");
++	platform_device_register(&at91sam9261_tcb_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+  *  RTT
+  * -------------------------------------------------------------------- */
+ 
+@@ -561,7 +610,7 @@ static struct resource rtt_resources[] = {
+ 
+ static struct platform_device at91sam9261_rtt_device = {
+ 	.name		= "at91_rtt",
+-	.id		= -1,
++	.id		= 0,
+ 	.resource	= rtt_resources,
+ 	.num_resources	= ARRAY_SIZE(rtt_resources),
+ };
+@@ -938,49 +987,9 @@ static inline void configure_usart2_pins(unsigned pins)
+ 		at91_set_B_periph(AT91_PIN_PA16, 0);	/* CTS2 */
+ }
+ 
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+ struct platform_device *atmel_default_console_device;	/* the serial console device */
+ 
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+-{
+-	int i;
+-
+-	/* Fill in list of supported UARTs */
+-	for (i = 0; i < config->nr_tty; i++) {
+-		switch (config->tty_map[i]) {
+-			case 0:
+-				configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+-				at91_uarts[i] = &at91sam9261_uart0_device;
+-				at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart");
+-				break;
+-			case 1:
+-				configure_usart1_pins(0);
+-				at91_uarts[i] = &at91sam9261_uart1_device;
+-				at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart");
+-				break;
+-			case 2:
+-				configure_usart2_pins(0);
+-				at91_uarts[i] = &at91sam9261_uart2_device;
+-				at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart");
+-				break;
+-			case 3:
+-				configure_dbgu_pins();
+-				at91_uarts[i] = &at91sam9261_dbgu_device;
+-				at91_clock_associate("mck", &at91sam9261_dbgu_device.dev, "usart");
+-				break;
+-			default:
+-				continue;
+-		}
+-		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+-	}
+-
+-	/* Set serial console device */
+-	if (config->console_tty < ATMEL_MAX_UART)
+-		atmel_default_console_device = at91_uarts[config->console_tty];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+-}
+-
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+ {
+ 	struct platform_device *pdev;
+@@ -1019,8 +1028,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ 	if (portnr < ATMEL_MAX_UART)
+ 		atmel_default_console_device = at91_uarts[portnr];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ 
+ void __init at91_add_device_serial(void)
+@@ -1031,9 +1038,11 @@ void __init at91_add_device_serial(void)
+ 		if (at91_uarts[i])
+ 			platform_device_register(at91_uarts[i]);
+ 	}
++
++	if (!atmel_default_console_device)
++		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+ void __init at91_set_serial_console(unsigned portnr) {}
+ void __init at91_add_device_serial(void) {}
+@@ -1050,6 +1059,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ 	at91_add_device_rtt();
+ 	at91_add_device_watchdog();
++	at91_add_device_tc();
+ 	return 0;
+ }
+ 
+diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
+index a53ba0f..052074a 100644
+--- a/arch/arm/mach-at91/at91sam9263.c
++++ b/arch/arm/mach-at91/at91sam9263.c
+@@ -11,12 +11,14 @@
+  */
+ 
+ #include <linux/module.h>
++#include <linux/pm.h>
+ 
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/arch/at91sam9263.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+ 
+ #include "generic.h"
+ #include "clock.h"
+@@ -271,6 +273,11 @@ static void at91sam9263_reset(void)
+ 	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+ 
++static void at91sam9263_poweroff(void)
++{
++	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
+ 
+ /* --------------------------------------------------------------------
+  *  AT91SAM9263 processor initialization
+@@ -282,6 +289,7 @@ void __init at91sam9263_initialize(unsigned long main_clock)
+ 	iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
+ 
+ 	at91_arch_reset = at91sam9263_reset;
++	pm_power_off = at91sam9263_poweroff;
+ 	at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
+ 
+ 	/* Init clock subsystem */
+diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
+index 0b12e1a..b6454c5 100644
+--- a/arch/arm/mach-at91/at91sam9263_devices.c
++++ b/arch/arm/mach-at91/at91sam9263_devices.c
+@@ -22,8 +22,8 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91sam9263.h>
+-#include <asm/arch/at91sam926x_mc.h>
+ #include <asm/arch/at91sam9263_matrix.h>
++#include <asm/arch/at91sam9_smc.h>
+ 
+ #include "generic.h"
+ 
+@@ -358,10 +358,15 @@ static struct at91_nand_data nand_data;
+ #define NAND_BASE	AT91_CHIPSELECT_3
+ 
+ static struct resource nand_resources[] = {
+-	{
++	[0] = {
+ 		.start	= NAND_BASE,
+ 		.end	= NAND_BASE + SZ_256M - 1,
+ 		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91_BASE_SYS + AT91_ECC0,
++		.end	= AT91_BASE_SYS + AT91_ECC0 + SZ_512 - 1,
++		.flags	= IORESOURCE_MEM,
+ 	}
+ };
+ 
+@@ -783,6 +788,43 @@ void __init at91_add_device_isi(void) {}
+ 
+ 
+ /* --------------------------------------------------------------------
++ *  Timer/Counter block
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb_resources[] = {
++	[0] = {
++		.start	= AT91SAM9263_BASE_TCB0,
++		.end	= AT91SAM9263_BASE_TCB0 + SZ_16K - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91SAM9263_ID_TCB,
++		.end	= AT91SAM9263_ID_TCB,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device at91sam9263_tcb_device = {
++	.name		= "atmel_tcb",
++	.id		= 0,
++	.resource	= tcb_resources,
++	.num_resources	= ARRAY_SIZE(tcb_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++	/* this chip has one clock and irq for all three TC channels */
++	at91_clock_associate("tcb_clk", &at91sam9263_tcb_device.dev, "t0_clk");
++	platform_device_register(&at91sam9263_tcb_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+  *  RTT
+  * -------------------------------------------------------------------- */
+ 
+@@ -933,9 +975,6 @@ static inline void configure_ssc1_pins(unsigned pins)
+ }
+ 
+ /*
+- * Return the device node so that board init code can use it as the
+- * parent for the device node reflecting how it's used on this board.
+- *
+  * SSC controllers are accessed through library code, instead of any
+  * kind of all-singing/all-dancing driver.  For example one could be
+  * used by a particular I2S audio codec's driver, while another one
+@@ -1146,49 +1185,9 @@ static inline void configure_usart2_pins(unsigned pins)
+ 		at91_set_B_periph(AT91_PIN_PD6, 0);	/* CTS2 */
+ }
+ 
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+ struct platform_device *atmel_default_console_device;	/* the serial console device */
+ 
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+-{
+-	int i;
+-
+-	/* Fill in list of supported UARTs */
+-	for (i = 0; i < config->nr_tty; i++) {
+-		switch (config->tty_map[i]) {
+-			case 0:
+-				configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+-				at91_uarts[i] = &at91sam9263_uart0_device;
+-				at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart");
+-				break;
+-			case 1:
+-				configure_usart1_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+-				at91_uarts[i] = &at91sam9263_uart1_device;
+-				at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart");
+-				break;
+-			case 2:
+-				configure_usart2_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+-				at91_uarts[i] = &at91sam9263_uart2_device;
+-				at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart");
+-				break;
+-			case 3:
+-				configure_dbgu_pins();
+-				at91_uarts[i] = &at91sam9263_dbgu_device;
+-				at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart");
+-				break;
+-			default:
+-				continue;
+-		}
+-		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+-	}
+-
+-	/* Set serial console device */
+-	if (config->console_tty < ATMEL_MAX_UART)
+-		atmel_default_console_device = at91_uarts[config->console_tty];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+-}
+-
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+ {
+ 	struct platform_device *pdev;
+@@ -1227,8 +1226,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ 	if (portnr < ATMEL_MAX_UART)
+ 		atmel_default_console_device = at91_uarts[portnr];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ 
+ void __init at91_add_device_serial(void)
+@@ -1239,9 +1236,11 @@ void __init at91_add_device_serial(void)
+ 		if (at91_uarts[i])
+ 			platform_device_register(at91_uarts[i]);
+ 	}
++
++	if (!atmel_default_console_device)
++		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+-void __init at91_init_serial(struct at91_uart_config *config) {}
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+ void __init at91_set_serial_console(unsigned portnr) {}
+ void __init at91_add_device_serial(void) {}
+@@ -1257,6 +1256,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ 	at91_add_device_rtt();
+ 	at91_add_device_watchdog();
++	at91_add_device_tc();
+ 	return 0;
+ }
+ 
+diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
+index e38d237..5cecbd7 100644
+--- a/arch/arm/mach-at91/at91sam926x_time.c
++++ b/arch/arm/mach-at91/at91sam926x_time.c
+@@ -1,23 +1,20 @@
+ /*
+- * linux/arch/arm/mach-at91/at91sam926x_time.c
++ * at91sam926x_time.c - Periodic Interval Timer (PIT) for at91sam926x
+  *
+  * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
+  * Revision	 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
++ * Converted to ClockSource/ClockEvents by David Brownell.
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
+-
+-#include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/time.h>
++#include <linux/clk.h>
++#include <linux/clockchips.h>
+ 
+-#include <asm/hardware.h>
+-#include <asm/io.h>
+ #include <asm/mach/time.h>
+ 
+ #include <asm/arch/at91_pit.h>
+@@ -26,85 +23,167 @@
+ #define PIT_CPIV(x)	((x) & AT91_PIT_CPIV)
+ #define PIT_PICNT(x)	(((x) & AT91_PIT_PICNT) >> 20)
+ 
++static u32 pit_cycle;		/* write-once */
++static u32 pit_cnt;		/* access only w/system irq blocked */
++
++
+ /*
+- * Returns number of microseconds since last timer interrupt.  Note that interrupts
+- * will have been disabled by do_gettimeofday()
+- *  'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
++ * Clocksource:  just a monotonic counter of MCK/16 cycles.
++ * We don't care whether or not PIT irqs are enabled.
+  */
+-static unsigned long at91sam926x_gettimeoffset(void)
++static cycle_t read_pit_clk(void)
+ {
+-	unsigned long elapsed;
+-	unsigned long t = at91_sys_read(AT91_PIT_PIIR);
++	unsigned long flags;
++	u32 elapsed;
++	u32 t;
++
++	raw_local_irq_save(flags);
++	elapsed = pit_cnt;
++	t = at91_sys_read(AT91_PIT_PIIR);
++	raw_local_irq_restore(flags);
++
++	elapsed += PIT_PICNT(t) * pit_cycle;
++	elapsed += PIT_CPIV(t);
++	return elapsed;
++}
++
++static struct clocksource pit_clk = {
++	.name		= "pit",
++	.rating		= 175,
++	.read		= read_pit_clk,
++	.shift		= 20,
++	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
++};
+ 
+-	elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t);		/* hardware clock cycles */
+ 
+-	return (unsigned long)(elapsed * jiffies_to_usecs(1)) / LATCH;
++/*
++ * Clockevent device:  interrupts every 1/HZ (== pit_cycles * MCK/16)
++ */
++static void
++pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
++{
++	unsigned long	flags;
++
++	switch (mode) {
++	case CLOCK_EVT_MODE_PERIODIC:
++		/* update clocksource counter, then enable the IRQ */
++		raw_local_irq_save(flags);
++		pit_cnt += pit_cycle * PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
++		at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN
++				| AT91_PIT_PITIEN);
++		raw_local_irq_restore(flags);
++		break;
++	case CLOCK_EVT_MODE_ONESHOT:
++		BUG();
++		/* FALLTHROUGH */
++	case CLOCK_EVT_MODE_SHUTDOWN:
++	case CLOCK_EVT_MODE_UNUSED:
++		/* disable irq, leaving the clocksource active */
++		at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
++		break;
++	case CLOCK_EVT_MODE_RESUME:
++		break;
++	}
+ }
+ 
++static struct clock_event_device pit_clkevt = {
++	.name		= "pit",
++	.features	= CLOCK_EVT_FEAT_PERIODIC,
++	.shift		= 32,
++	.rating		= 100,
++	.cpumask	= CPU_MASK_CPU0,
++	.set_mode	= pit_clkevt_mode,
++};
++
++
+ /*
+  * IRQ handler for the timer.
+  */
+-static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
++static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
+ {
+-	volatile long nr_ticks;
+ 
+-	if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) {	/* This is a shared interrupt */
+-		/* Get number to ticks performed before interrupt and clear PIT interrupt */
++	/* The PIT interrupt may be disabled, and is shared */
++	if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC)
++			&& (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS)) {
++		unsigned nr_ticks;
++
++		/* Get number of ticks performed before irq, and ack it */
+ 		nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
+ 		do {
+-			timer_tick();
++			pit_cnt += pit_cycle;
++			pit_clkevt.event_handler(&pit_clkevt);
+ 			nr_ticks--;
+ 		} while (nr_ticks);
+ 
+ 		return IRQ_HANDLED;
+-	} else
+-		return IRQ_NONE;		/* not handled */
++	}
++
++	return IRQ_NONE;
+ }
+ 
+-static struct irqaction at91sam926x_timer_irq = {
++static struct irqaction at91sam926x_pit_irq = {
+ 	.name		= "at91_tick",
+ 	.flags		= IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+-	.handler	= at91sam926x_timer_interrupt
++	.handler	= at91sam926x_pit_interrupt
+ };
+ 
+-void at91sam926x_timer_reset(void)
++static void at91sam926x_pit_reset(void)
+ {
+-	/* Disable timer */
++	/* Disable timer and irqs */
+ 	at91_sys_write(AT91_PIT_MR, 0);
+ 
+-	/* Clear any pending interrupts */
+-	(void) at91_sys_read(AT91_PIT_PIVR);
++	/* Clear any pending interrupts, wait for PIT to stop counting */
++	while (PIT_CPIV(at91_sys_read(AT91_PIT_PIVR)) != 0)
++		cpu_relax();
+ 
+-	/* Set Period Interval timer and enable its interrupt */
+-	at91_sys_write(AT91_PIT_MR, (LATCH & AT91_PIT_PIV) | AT91_PIT_PITIEN | AT91_PIT_PITEN);
++	/* Start PIT but don't enable IRQ */
++	at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
+ }
+ 
+ /*
+- * Set up timer interrupt.
++ * Set up both clocksource and clockevent support.
+  */
+-void __init at91sam926x_timer_init(void)
++static void __init at91sam926x_pit_init(void)
+ {
+-	/* Initialize and enable the timer */
+-	at91sam926x_timer_reset();
++	unsigned long	pit_rate;
++	unsigned	bits;
++
++	/*
++	 * Use our actual MCK to figure out how many MCK/16 ticks per
++	 * 1/HZ period (instead of a compile-time constant LATCH).
++	 */
++	pit_rate = clk_get_rate(clk_get(NULL, "mck")) / 16;
++	pit_cycle = (pit_rate + HZ/2) / HZ;
++	WARN_ON(((pit_cycle - 1) & ~AT91_PIT_PIV) != 0);
+ 
+-	/* Make IRQs happen for the system timer. */
+-	setup_irq(AT91_ID_SYS, &at91sam926x_timer_irq);
++	/* Initialize and enable the timer */
++	at91sam926x_pit_reset();
++
++	/*
++	 * Register clocksource.  The high order bits of PIV are unused,
++	 * so this isn't a 32-bit counter unless we get clockevent irqs.
++	 */
++	pit_clk.mult = clocksource_hz2mult(pit_rate, pit_clk.shift);
++	bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */;
++	pit_clk.mask = CLOCKSOURCE_MASK(bits);
++	clocksource_register(&pit_clk);
++
++	/* Set up irq handler */
++	setup_irq(AT91_ID_SYS, &at91sam926x_pit_irq);
++
++	/* Set up and register clockevents */
++	pit_clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, pit_clkevt.shift);
++	clockevents_register_device(&pit_clkevt);
+ }
+ 
+-#ifdef CONFIG_PM
+-static void at91sam926x_timer_suspend(void)
++static void at91sam926x_pit_suspend(void)
+ {
+ 	/* Disable timer */
+ 	at91_sys_write(AT91_PIT_MR, 0);
+ }
+-#else
+-#define at91sam926x_timer_suspend	NULL
+-#endif
+ 
+ struct sys_timer at91sam926x_timer = {
+-	.init		= at91sam926x_timer_init,
+-	.offset		= at91sam926x_gettimeoffset,
+-	.suspend	= at91sam926x_timer_suspend,
+-	.resume		= at91sam926x_timer_reset,
++	.init		= at91sam926x_pit_init,
++	.suspend	= at91sam926x_pit_suspend,
++	.resume		= at91sam926x_pit_reset,
+ };
+-
+diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
+index 4813a35..902c798 100644
+--- a/arch/arm/mach-at91/at91sam9rl.c
++++ b/arch/arm/mach-at91/at91sam9rl.c
+@@ -10,6 +10,7 @@
+  */
+ 
+ #include <linux/module.h>
++#include <linux/pm.h>
+ 
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+@@ -17,6 +18,7 @@
+ #include <asm/arch/at91sam9rl.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+ 
+ #include "generic.h"
+ #include "clock.h"
+@@ -244,6 +246,11 @@ static void at91sam9rl_reset(void)
+ 	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+ 
++static void at91sam9rl_poweroff(void)
++{
++	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
+ 
+ /* --------------------------------------------------------------------
+  *  AT91SAM9RL processor initialization
+@@ -274,6 +281,7 @@ void __init at91sam9rl_initialize(unsigned long main_clock)
+ 	iotable_init(at91sam9rl_sram_desc, ARRAY_SIZE(at91sam9rl_sram_desc));
+ 
+ 	at91_arch_reset = at91sam9rl_reset;
++	pm_power_off = at91sam9rl_poweroff;
+ 	at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0);
+ 
+ 	/* Init clock subsystem */
+diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
+index f43b5c3..dbb9a5f 100644
+--- a/arch/arm/mach-at91/at91sam9rl_devices.c
++++ b/arch/arm/mach-at91/at91sam9rl_devices.c
+@@ -20,7 +20,7 @@
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91sam9rl.h>
+ #include <asm/arch/at91sam9rl_matrix.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+ 
+ #include "generic.h"
+ 
+@@ -105,10 +105,15 @@ static struct at91_nand_data nand_data;
+ #define NAND_BASE	AT91_CHIPSELECT_3
+ 
+ static struct resource nand_resources[] = {
+-	{
++	[0] = {
+ 		.start	= NAND_BASE,
+ 		.end	= NAND_BASE + SZ_256M - 1,
+ 		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91_BASE_SYS + AT91_ECC,
++		.end	= AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
++		.flags	= IORESOURCE_MEM,
+ 	}
+ };
+ 
+@@ -385,6 +390,55 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+ 
+ 
+ /* --------------------------------------------------------------------
++ *  Timer/Counter block
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb_resources[] = {
++	[0] = {
++		.start	= AT91SAM9RL_BASE_TCB0,
++		.end	= AT91SAM9RL_BASE_TCB0 + SZ_16K - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= AT91SAM9RL_ID_TC0,
++		.end	= AT91SAM9RL_ID_TC0,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[2] = {
++		.start	= AT91SAM9RL_ID_TC1,
++		.end	= AT91SAM9RL_ID_TC1,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[3] = {
++		.start	= AT91SAM9RL_ID_TC2,
++		.end	= AT91SAM9RL_ID_TC2,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device at91sam9rl_tcb_device = {
++	.name		= "atmel_tcb",
++	.id		= 0,
++	.resource	= tcb_resources,
++	.num_resources	= ARRAY_SIZE(tcb_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++	/* this chip has a separate clock and irq for each TC channel */
++	at91_clock_associate("tc0_clk", &at91sam9rl_tcb_device.dev, "t0_clk");
++	at91_clock_associate("tc1_clk", &at91sam9rl_tcb_device.dev, "t1_clk");
++	at91_clock_associate("tc2_clk", &at91sam9rl_tcb_device.dev, "t2_clk");
++	platform_device_register(&at91sam9rl_tcb_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+  *  RTC
+  * -------------------------------------------------------------------- */
+ 
+@@ -418,7 +472,7 @@ static struct resource rtt_resources[] = {
+ 
+ static struct platform_device at91sam9rl_rtt_device = {
+ 	.name		= "at91_rtt",
+-	.id		= -1,
++	.id		= 0,
+ 	.resource	= rtt_resources,
+ 	.num_resources	= ARRAY_SIZE(rtt_resources),
+ };
+@@ -539,9 +593,6 @@ static inline void configure_ssc1_pins(unsigned pins)
+ }
+ 
+ /*
+- * Return the device node so that board init code can use it as the
+- * parent for the device node reflecting how it's used on this board.
+- *
+  * SSC controllers are accessed through library code, instead of any
+  * kind of all-singing/all-dancing driver.  For example one could be
+  * used by a particular I2S audio codec's driver, while another one
+@@ -802,54 +853,9 @@ static inline void configure_usart3_pins(unsigned pins)
+ 		at91_set_B_periph(AT91_PIN_PD3, 0);	/* CTS3 */
+ }
+ 
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
+ struct platform_device *atmel_default_console_device;	/* the serial console device */
+ 
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+-{
+-	int i;
+-
+-	/* Fill in list of supported UARTs */
+-	for (i = 0; i < config->nr_tty; i++) {
+-		switch (config->tty_map[i]) {
+-			case 0:
+-				configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+-				at91_uarts[i] = &at91sam9rl_uart0_device;
+-				at91_clock_associate("usart0_clk", &at91sam9rl_uart0_device.dev, "usart");
+-				break;
+-			case 1:
+-				configure_usart1_pins(0);
+-				at91_uarts[i] = &at91sam9rl_uart1_device;
+-				at91_clock_associate("usart1_clk", &at91sam9rl_uart1_device.dev, "usart");
+-				break;
+-			case 2:
+-				configure_usart2_pins(0);
+-				at91_uarts[i] = &at91sam9rl_uart2_device;
+-				at91_clock_associate("usart2_clk", &at91sam9rl_uart2_device.dev, "usart");
+-				break;
+-			case 3:
+-				configure_usart3_pins(0);
+-				at91_uarts[i] = &at91sam9rl_uart3_device;
+-				at91_clock_associate("usart3_clk", &at91sam9rl_uart3_device.dev, "usart");
+-				break;
+-			case 4:
+-				configure_dbgu_pins();
+-				at91_uarts[i] = &at91sam9rl_dbgu_device;
+-				at91_clock_associate("mck", &at91sam9rl_dbgu_device.dev, "usart");
+-				break;
+-			default:
+-				continue;
+-		}
+-		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+-	}
+-
+-	/* Set serial console device */
+-	if (config->console_tty < ATMEL_MAX_UART)
+-		atmel_default_console_device = at91_uarts[config->console_tty];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+-}
+-
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+ {
+ 	struct platform_device *pdev;
+@@ -893,8 +899,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ 	if (portnr < ATMEL_MAX_UART)
+ 		atmel_default_console_device = at91_uarts[portnr];
+-	if (!atmel_default_console_device)
+-		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ 
+ void __init at91_add_device_serial(void)
+@@ -905,9 +909,11 @@ void __init at91_add_device_serial(void)
+ 		if (at91_uarts[i])
+ 			platform_device_register(at91_uarts[i]);
+ 	}
++
++	if (!atmel_default_console_device)
++		printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+ void __init at91_set_serial_console(unsigned portnr) {}
+ void __init at91_add_device_serial(void) {}
+@@ -925,6 +931,7 @@ static int __init at91_add_standard_devices(void)
+ 	at91_add_device_rtc();
+ 	at91_add_device_rtt();
+ 	at91_add_device_watchdog();
++	at91_add_device_tc();
+ 	return 0;
+ }
+ 
+diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
+new file mode 100644
+index 0000000..b22a1a0
+--- /dev/null
++++ b/arch/arm/mach-at91/board-cam60.c
+@@ -0,0 +1,180 @@
++/*
++ * KwikByte CAM60 (KB9260)
++ *
++ * based on board-sam9260ek.c
++ *   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/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/flash.h>
++
++#include <asm/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 <asm/arch/board.h>
++#include <asm/arch/gpio.h>
++
++#include "generic.h"
++
++
++static void __init cam60_map_io(void)
++{
++	/* Initialize processor: 10 MHz crystal */
++	at91sam9260_initialize(10000000);
++
++	/* DGBU 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 cam60_init_irq(void)
++{
++	at91sam9260_init_interrupts(NULL);
++}
++
++
++/*
++ * USB Host
++ */
++static struct at91_usbh_data __initdata cam60_usbh_data = {
++	.ports		= 1,
++};
++
++
++/*
++ * SPI devices.
++ */
++#if defined(CONFIG_MTD_DATAFLASH)
++static struct mtd_partition __initdata cam60_spi_partitions[] = {
++	{
++		.name	= "BOOT1",
++		.offset	= 0,
++		.size	= 4 * 1056,
++	},
++	{
++		.name	= "BOOT2",
++		.offset	= MTDPART_OFS_NXTBLK,
++		.size	= 256 * 1056,
++	},
++	{
++		.name	= "kernel",
++		.offset	= MTDPART_OFS_NXTBLK,
++		.size	= 2222 * 1056,
++	},
++	{
++		.name	= "file system",
++		.offset	= MTDPART_OFS_NXTBLK,
++		.size	= MTDPART_SIZ_FULL,
++	},
++};
++
++static struct flash_platform_data __initdata cam60_spi_flash_platform_data = {
++	.name		= "spi_flash",
++	.parts		= cam60_spi_partitions,
++	.nr_parts	= ARRAY_SIZE(cam60_spi_partitions)
++};
++#endif
++
++static struct spi_board_info cam60_spi_devices[] = {
++#if defined(CONFIG_MTD_DATAFLASH)
++	{	/* DataFlash chip */
++		.modalias	= "mtd_dataflash",
++		.chip_select	= 0,
++		.max_speed_hz	= 15 * 1000 * 1000,
++		.bus_num	= 0,
++		.platform_data	= &cam60_spi_flash_platform_data
++	},
++#endif
++};
++
++
++/*
++ * MACB Ethernet device
++ */
++static struct __initdata at91_eth_data cam60_macb_data = {
++	.phy_irq_pin	= AT91_PIN_PB5,
++	.is_rmii	= 0,
++};
++
++
++/*
++ * NAND Flash
++ */
++static struct mtd_partition __initdata cam60_nand_partition[] = {
++	{
++		.name	= "nand_fs",
++		.offset	= 0,
++		.size	= MTDPART_SIZ_FULL,
++	},
++};
++
++static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
++{
++	*num_partitions = ARRAY_SIZE(cam60_nand_partition);
++	return cam60_nand_partition;
++}
++
++static struct at91_nand_data __initdata cam60_nand_data = {
++	.ale		= 21,
++	.cle		= 22,
++	// .det_pin	= ... not there
++	.rdy_pin	= AT91_PIN_PA9,
++	.enable_pin	= AT91_PIN_PA7,
++	.partition_info	= nand_partitions,
++};
++
++
++static void __init cam60_board_init(void)
++{
++	/* Serial */
++	at91_add_device_serial();
++	/* SPI */
++	at91_add_device_spi(cam60_spi_devices, ARRAY_SIZE(cam60_spi_devices));
++	/* Ethernet */
++	at91_add_device_eth(&cam60_macb_data);
++	/* USB Host */
++	/* enable USB power supply circuit */
++	at91_set_gpio_output(AT91_PIN_PB18, 1);
++	at91_add_device_usbh(&cam60_usbh_data);
++	/* NAND */
++	at91_add_device_nand(&cam60_nand_data);
++}
++
++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,
++	.init_irq	= cam60_init_irq,
++	.init_machine	= cam60_board_init,
++MACHINE_END
+diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
+index 1854371..e5512d1 100644
+--- a/arch/arm/mach-at91/board-cap9adk.c
++++ b/arch/arm/mach-at91/board-cap9adk.c
+@@ -45,7 +45,7 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91cap9_matrix.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+ 
+ #include "generic.h"
+ 
+diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
+index 0e2a11f..26fea4d 100644
+--- a/arch/arm/mach-at91/board-csb337.c
++++ b/arch/arm/mach-at91/board-csb337.c
+@@ -43,17 +43,6 @@
+ #include "generic.h"
+ 
+ 
+-/*
+- * Serial port configuration.
+- *    0 .. 3 = USART0 .. USART3
+- *    4      = DBGU
+- */
+-static struct at91_uart_config __initdata csb337_uart_config = {
+-	.console_tty	= 0,				/* ttyS0 */
+-	.nr_tty		= 2,
+-	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+-};
+-
+ static void __init csb337_map_io(void)
+ {
+ 	/* Initialize processor: 3.6864 MHz crystal */
+@@ -62,8 +51,11 @@ static void __init csb337_map_io(void)
+ 	/* Setup the LEDs */
+ 	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
+ 
+-	/* Setup the serial ports and console */
+-	at91_init_serial(&csb337_uart_config);
++	/* DBGU on ttyS0 */
++	at91_register_uart(0, 0, 0);
++
++	/* make console=ttyS0 the default */
++	at91_set_serial_console(0);
+ }
+ 
+ static void __init csb337_init_irq(void)
+diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
+index c5c721d..419fd19 100644
+--- a/arch/arm/mach-at91/board-csb637.c
++++ b/arch/arm/mach-at91/board-csb637.c
+@@ -40,27 +40,16 @@
+ #include "generic.h"
+ 
+ 
+-/*
+- * Serial port configuration.
+- *    0 .. 3 = USART0 .. USART3
+- *    4      = DBGU
+- */
+-static struct at91_uart_config __initdata csb637_uart_config = {
+-	.console_tty	= 0,				/* ttyS0 */
+-	.nr_tty		= 2,
+-	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+-};
+-
+ static void __init csb637_map_io(void)
+ {
+ 	/* Initialize processor: 3.6864 MHz crystal */
+ 	at91rm9200_initialize(3686400, AT91RM9200_BGA);
+ 
+-	/* Setup the LEDs */
+-	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
++	/* DBGU on ttyS0 */
++	at91_register_uart(0, 0, 0);
+ 
+-	/* Setup the serial ports and console */
+-	at91_init_serial(&csb637_uart_config);
++	/* make console=ttyS0 the default */
++	at91_set_serial_console(0);
+ }
+ 
+ static void __init csb637_init_irq(void)
+@@ -118,8 +107,19 @@ static struct platform_device csb_flash = {
+ 	.num_resources	= ARRAY_SIZE(csb_flash_resources),
+ };
+ 
++static struct gpio_led csb_leds[] = {
++	{	/* "d1", red */
++		.name			= "d1",
++		.gpio			= AT91_PIN_PB2,
++		.active_low		= 1,
++		.default_trigger	= "heartbeat",
++	},
++};
++
+ static void __init csb637_board_init(void)
+ {
++	/* LED(s) */
++	at91_gpio_leds(csb_leds, ARRAY_SIZE(csb_leds));
+ 	/* Serial */
+ 	at91_add_device_serial();
+ 	/* Ethernet */
+diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
+new file mode 100644
+index 0000000..e77fad4
+--- /dev/null
++++ b/arch/arm/mach-at91/board-ecbat91.c
+@@ -0,0 +1,178 @@
++/*
++ * linux/arch/arm/mach-at91rm9200/board-ecbat91.c
++ * Copyright (C) 2007 emQbit.com.
++ *
++ * We started from board-dk.c, which is Copyright (C) 2005 SAN People.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public 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/flash.h>
++
++#include <asm/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 <asm/arch/board.h>
++#include <asm/arch/gpio.h>
++
++#include "generic.h"
++
++
++static void __init ecb_at91map_io(void)
++{
++	/* Initialize processor: 18.432 MHz crystal */
++	at91rm9200_initialize(18432000, AT91RM9200_PQFP);
++
++	/* Setup the LEDs */
++	at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7);
++
++	/* DBGU on ttyS0. (Rx & Tx only) */
++	at91_register_uart(0, 0, 0);
++
++	/* USART0 on ttyS1. (Rx & Tx only) */
++	at91_register_uart(AT91RM9200_ID_US0, 1, 0);
++
++	/* set serial console to ttyS0 (ie, DBGU) */
++	at91_set_serial_console(0);
++}
++
++static void __init ecb_at91init_irq(void)
++{
++	at91rm9200_init_interrupts(NULL);
++}
++
++static struct at91_eth_data __initdata ecb_at91eth_data = {
++	.phy_irq_pin	= AT91_PIN_PC4,
++	.is_rmii	= 0,
++};
++
++static struct at91_usbh_data __initdata ecb_at91usbh_data = {
++	.ports		= 1,
++};
++
++static struct at91_mmc_data __initdata ecb_at91mmc_data = {
++	.slot_b		= 0,
++	.wire4		= 1,
++};
++
++
++#if defined(CONFIG_MTD_DATAFLASH)
++static struct mtd_partition __initdata my_flash0_partitions[] =
++{
++	{	/* 0x8400 */
++		.name	= "Darrell-loader",
++		.offset	= 0,
++		.size	= 12* 1056,
++	},
++	{
++		.name	= "U-boot",
++		.offset	= MTDPART_OFS_NXTBLK,
++		.size	= 110 * 1056,
++	},
++	{	/* 1336 (167 blocks) pages * 1056 bytes = 0x158700 bytes */
++		.name	= "UBoot-env",
++		.offset	= MTDPART_OFS_NXTBLK,
++		.size	= 8 * 1056,
++	},
++	{	/* 1336 (167 blocks) pages * 1056 bytes = 0x158700 bytes */
++		.name	= "Kernel",
++		.offset	= MTDPART_OFS_NXTBLK,
++		.size	= 1534 * 1056,
++	},
++	{	/* 190200 - jffs2 root filesystem */
++		.name	= "Filesystem",
++		.offset	= MTDPART_OFS_NXTBLK,
++		.size	= MTDPART_SIZ_FULL,	/* 26 sectors */
++	}
++};
++
++static struct flash_platform_data __initdata my_flash0_platform = {
++	.name		= "Removable flash card",
++	.parts		= my_flash0_partitions,
++	.nr_parts	= ARRAY_SIZE(my_flash0_partitions)
++};
++
++#endif
++
++static struct spi_board_info __initdata ecb_at91spi_devices[] = {
++	{	/* DataFlash chip */
++		.modalias	= "mtd_dataflash",
++		.chip_select	= 0,
++		.max_speed_hz	= 10 * 1000 * 1000,
++		.bus_num	= 0,
++#if defined(CONFIG_MTD_DATAFLASH)
++		.platform_data	= &my_flash0_platform,
++#endif
++	},
++	{	/* User accessable spi - cs1 (250KHz) */
++		.modalias	= "spi-cs1",
++		.chip_select	= 1,
++		.max_speed_hz	= 250 * 1000,
++	},
++	{	/* User accessable spi - cs2 (1MHz) */
++		.modalias	= "spi-cs2",
++		.chip_select	= 2,
++		.max_speed_hz	= 1 * 1000 * 1000,
++	},
++	{	/* User accessable spi - cs3 (10MHz) */
++		.modalias	= "spi-cs3",
++		.chip_select	= 3,
++		.max_speed_hz	= 10 * 1000 * 1000,
++	},
++};
++
++static void __init ecb_at91board_init(void)
++{
++	/* Serial */
++	at91_add_device_serial();
++
++	/* Ethernet */
++	at91_add_device_eth(&ecb_at91eth_data);
++
++	/* USB Host */
++	at91_add_device_usbh(&ecb_at91usbh_data);
++
++	/* I2C */
++	at91_add_device_i2c(NULL, 0);
++
++	/* MMC */
++	at91_add_device_mmc(0, &ecb_at91mmc_data);
++
++	/* SPI */
++	at91_add_device_spi(ecb_at91spi_devices, ARRAY_SIZE(ecb_at91spi_devices));
++}
++
++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,
++	.init_irq	= ecb_at91init_irq,
++	.init_machine	= ecb_at91board_init,
++MACHINE_END
+diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
+new file mode 100644
+index 0000000..8f76af5
+--- /dev/null
++++ b/arch/arm/mach-at91/board-sam9-l9260.c
+@@ -0,0 +1,199 @@
++/*
++ * linux/arch/arm/mach-at91/board-sam9-l9260.c
++ *
++ *  Copyright (C) 2005 SAN People
++ *  Copyright (C) 2006 Atmel
++ *  Copyright (C) 2007 Olimex Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <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 <asm/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 <asm/arch/board.h>
++#include <asm/arch/gpio.h>
++
++#include "generic.h"
++
++
++static void __init ek_map_io(void)
++{
++	/* Initialize processor: 18.432 MHz crystal */
++	at91sam9260_initialize(18432000);
++
++	/* Setup the LEDs */
++	at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6);
++
++	/* DBGU 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, CTS, RTS) */
++	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_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_PA7,
++	.is_rmii	= 0,
++};
++
++
++/*
++ * NAND flash
++ */
++static struct mtd_partition __initdata ek_nand_partition[] = {
++	{
++		.name	= "Bootloader Area",
++		.offset	= 0,
++		.size	= 10 * 1024 * 1024,
++	},
++	{
++		.name	= "User Area",
++		.offset	= 10 * 1024 * 1024,
++		.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;
++}
++
++static struct at91_nand_data __initdata ek_nand_data = {
++	.ale		= 21,
++	.cle		= 22,
++//	.det_pin	= ... not connected
++	.rdy_pin	= AT91_PIN_PC13,
++	.enable_pin	= AT91_PIN_PC14,
++	.partition_info	= nand_partitions,
++#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
++	.bus_width_16	= 1,
++#else
++	.bus_width_16	= 0,
++#endif
++};
++
++
++/*
++ * MCI (SD/MMC)
++ */
++static struct at91_mmc_data __initdata ek_mmc_data = {
++	.slot_b		= 1,
++	.wire4		= 1,
++	.det_pin	= AT91_PIN_PC8,
++	.wp_pin		= AT91_PIN_PC4,
++//	.vcc_pin	= ... not connected
++};
++
++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 */
++	at91_add_device_nand(&ek_nand_data);
++	/* Ethernet */
++	at91_add_device_eth(&ek_macb_data);
++	/* MMC */
++	at91_add_device_mmc(0, &ek_mmc_data);
++	/* I2C */
++	at91_add_device_i2c(NULL, 0);
++}
++
++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,
++	.init_irq	= ek_init_irq,
++	.init_machine	= ek_board_init,
++MACHINE_END
+diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
+index b343a6c..4d1d9c7 100644
+--- a/arch/arm/mach-at91/board-sam9260ek.c
++++ b/arch/arm/mach-at91/board-sam9260ek.c
+@@ -25,6 +25,8 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/spi/spi.h>
++#include <linux/spi/at73c213.h>
++#include <linux/clk.h>
+ 
+ #include <asm/hardware.h>
+ #include <asm/setup.h>
+@@ -37,29 +39,28 @@
+ 
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+-#include <asm/arch/at91sam926x_mc.h>
+ 
+ #include "generic.h"
+ 
+ 
+-/*
+- * Serial port configuration.
+- *    0 .. 5 = USART0 .. USART5
+- *    6      = DBGU
+- */
+-static struct at91_uart_config __initdata ek_uart_config = {
+-	.console_tty	= 0,				/* ttyS0 */
+-	.nr_tty		= 3,
+-	.tty_map	= { 6, 0, 1, -1, -1, -1, -1 }	/* ttyS0, ..., ttyS6 */
+-};
+-
+ static void __init ek_map_io(void)
+ {
+ 	/* Initialize processor: 18.432 MHz crystal */
+ 	at91sam9260_initialize(18432000);
+ 
+-	/* Setup the serial ports and console */
+-	at91_init_serial(&ek_uart_config);
++	/* 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)
+@@ -85,6 +86,35 @@ static struct at91_udc_data __initdata ek_udc_data = {
+ 
+ 
+ /*
++ * Audio
++ */
++static struct at73c213_board_info at73c213_data = {
++	.ssc_id		= 0,
++	.shortname	= "AT91SAM9260-EK external DAC",
++};
++
++#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
++static void __init at73c213_set_clk(struct at73c213_board_info *info)
++{
++	struct clk *pck0;
++	struct clk *plla;
++
++	pck0 = clk_get(NULL, "pck0");
++	plla = clk_get(NULL, "plla");
++
++	/* AT73C213 MCK Clock */
++	at91_set_B_periph(AT91_PIN_PC1, 0);	/* PCK0 */
++
++	clk_set_parent(pck0, plla);
++	clk_put(plla);
++
++	info->dac_clk = pck0;
++}
++#else
++static void __init at73c213_set_clk(struct at73c213_board_info *info) {}
++#endif
++
++/*
+  * SPI devices.
+  */
+ static struct spi_board_info ek_spi_devices[] = {
+@@ -110,6 +140,8 @@ static struct spi_board_info ek_spi_devices[] = {
+ 		.chip_select	= 0,
+ 		.max_speed_hz	= 10 * 1000 * 1000,
+ 		.bus_num	= 1,
++		.mode		= SPI_MODE_1,
++		.platform_data	= &at73c213_data,
+ 	},
+ #endif
+ };
+@@ -172,6 +204,24 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
+ //	.vcc_pin	= ... not connected
+ };
+ 
++
++/*
++ * LEDs
++ */
++static struct gpio_led ek_leds[] = {
++	{	/* "bottom" led, green, userled1 to be defined */
++		.name			= "ds5",
++		.gpio			= AT91_PIN_PA6,
++		.active_low		= 1,
++		.default_trigger	= "none",
++	},
++	{	/* "power" led, yellow */
++		.name			= "ds1",
++		.gpio			= AT91_PIN_PA9,
++		.default_trigger	= "heartbeat",
++	}
++};
++
+ static void __init ek_board_init(void)
+ {
+ 	/* Serial */
+@@ -190,6 +240,11 @@ static void __init ek_board_init(void)
+ 	at91_add_device_mmc(0, &ek_mmc_data);
+ 	/* I2C */
+ 	at91_add_device_i2c(NULL, 0);
++	/* SSC (to AT73C213) */
++	at73c213_set_clk(&at73c213_data);
++	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
++	/* LEDs */
++	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+ }
+ 
+ MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
+diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
+index 0ce38df..08382c0 100644
+--- a/arch/arm/mach-at91/board-sam9261ek.c
++++ b/arch/arm/mach-at91/board-sam9261ek.c
+@@ -26,6 +26,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/ads7846.h>
++#include <linux/spi/at73c213.h>
++#include <linux/clk.h>
+ #include <linux/dm9000.h>
+ #include <linux/fb.h>
+ #include <linux/gpio_keys.h>
+@@ -44,22 +46,11 @@
+ 
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+ 
+ #include "generic.h"
+ 
+ 
+-/*
+- * Serial port configuration.
+- *    0 .. 2 = USART0 .. USART2
+- *    3      = DBGU
+- */
+-static struct at91_uart_config __initdata ek_uart_config = {
+-	.console_tty	= 0,				/* ttyS0 */
+-	.nr_tty		= 1,
+-	.tty_map	= { 3, -1, -1, -1 }		/* ttyS0, ..., ttyS3 */
+-};
+-
+ static void __init ek_map_io(void)
+ {
+ 	/* Initialize processor: 18.432 MHz crystal */
+@@ -68,8 +59,11 @@ static void __init ek_map_io(void)
+ 	/* Setup the LEDs */
+ 	at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);
+ 
+-	/* Setup the serial ports and console */
+-	at91_init_serial(&ek_uart_config);
++	/* DGBU 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 ek_init_irq(void)
+@@ -239,6 +233,35 @@ static void __init ek_add_device_ts(void) {}
+ #endif
+ 
+ /*
++ * Audio
++ */
++static struct at73c213_board_info at73c213_data = {
++	.ssc_id		= 1,
++	.shortname	= "AT91SAM9261-EK external DAC",
++};
++
++#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
++static void __init at73c213_set_clk(struct at73c213_board_info *info)
++{
++	struct clk *pck2;
++	struct clk *plla;
++
++	pck2 = clk_get(NULL, "pck2");
++	plla = clk_get(NULL, "plla");
++
++	/* AT73C213 MCK Clock */
++	at91_set_B_periph(AT91_PIN_PB31, 0);	/* PCK2 */
++
++	clk_set_parent(pck2, plla);
++	clk_put(plla);
++
++	info->dac_clk = pck2;
++}
++#else
++static void __init at73c213_set_clk(struct at73c213_board_info *info) {}
++#endif
++
++/*
+  * SPI devices
+  */
+ static struct spi_board_info ek_spi_devices[] = {
+@@ -256,6 +279,7 @@ static struct spi_board_info ek_spi_devices[] = {
+ 		.bus_num	= 0,
+ 		.platform_data	= &ads_info,
+ 		.irq		= AT91SAM9261_ID_IRQ0,
++		.controller_data = (void *) AT91_PIN_PA28,	/* CS pin */
+ 	},
+ #endif
+ #if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+@@ -271,6 +295,9 @@ static struct spi_board_info ek_spi_devices[] = {
+ 		.chip_select	= 3,
+ 		.max_speed_hz	= 10 * 1000 * 1000,
+ 		.bus_num	= 0,
++		.mode		= SPI_MODE_1,
++		.platform_data	= &at73c213_data,
++		.controller_data = (void*) AT91_PIN_PA29,	/* default for CS3 is PA6, but it must be PA29 */
+ 	},
+ #endif
+ };
+@@ -460,6 +487,29 @@ static void __init ek_add_device_buttons(void)
+ static void __init ek_add_device_buttons(void) {}
+ #endif
+ 
++/*
++ * LEDs
++ */
++static struct gpio_led ek_leds[] = {
++	{	/* "bottom" led, green, userled1 to be defined */
++		.name			= "ds7",
++		.gpio			= AT91_PIN_PA14,
++		.active_low		= 1,
++		.default_trigger	= "none",
++	},
++	{	/* "top" led, green, userled2 to be defined */
++		.name			= "ds8",
++		.gpio			= AT91_PIN_PA13,
++		.active_low		= 1,
++		.default_trigger	= "none",
++	},
++	{	/* "power" led, yellow */
++		.name			= "ds1",
++		.gpio			= AT91_PIN_PA23,
++		.default_trigger	= "heartbeat",
++	}
++};
++
+ static void __init ek_board_init(void)
+ {
+ 	/* Serial */
+@@ -481,6 +531,9 @@ static void __init ek_board_init(void)
+ 	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+ 	/* Touchscreen */
+ 	ek_add_device_ts();
++	/* SSC (to AT73C213) */
++	at73c213_set_clk(&at73c213_data);
++	at91_add_device_ssc(AT91SAM9261_ID_SSC1, ATMEL_SSC_TX);
+ #else
+ 	/* MMC */
+ 	at91_add_device_mmc(0, &ek_mmc_data);
+@@ -489,6 +542,8 @@ static void __init ek_board_init(void)
+ 	at91_add_device_lcdc(&ek_lcdc_data);
+ 	/* Push Buttons */
+ 	ek_add_device_buttons();
++	/* LEDs */
++	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+ }
+ 
+ MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
+diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
+index bf103b2..b4cd5d0 100644
+--- a/arch/arm/mach-at91/board-sam9263ek.c
++++ b/arch/arm/mach-at91/board-sam9263ek.c
+@@ -43,29 +43,24 @@
+ 
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+ 
+ #include "generic.h"
+ 
+ 
+-/*
+- * Serial port configuration.
+- *    0 .. 2 = USART0 .. USART2
+- *    3      = DBGU
+- */
+-static struct at91_uart_config __initdata ek_uart_config = {
+-	.console_tty	= 0,				/* ttyS0 */
+-	.nr_tty		= 2,
+-	.tty_map	= { 3, 0, -1, -1, }		/* ttyS0, ..., ttyS3 */
+-};
+-
+ static void __init ek_map_io(void)
+ {
+ 	/* Initialize processor: 16.367 MHz crystal */
+ 	at91sam9263_initialize(16367660);
+ 
+-	/* Setup the serial ports and console */
+-	at91_init_serial(&ek_uart_config);
++	/* DGBU on ttyS0. (Rx & Tx only) */
++	at91_register_uart(0, 0, 0);
++
++	/* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
++	at91_register_uart(AT91SAM9263_ID_US0, 1, 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)
+@@ -341,7 +336,7 @@ static struct gpio_led ek_leds[] = {
+ 		.name			= "ds3",
+ 		.gpio			= AT91_PIN_PB7,
+ 		.default_trigger	= "heartbeat",
+-	},
++	}
+ };
+ 
+ 
+diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
+index bc0546d..ffc0597 100644
+--- a/arch/arm/mach-at91/board-sam9rlek.c
++++ b/arch/arm/mach-at91/board-sam9rlek.c
+@@ -29,29 +29,24 @@
+ 
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+ 
+ #include "generic.h"
+ 
+ 
+-/*
+- * Serial port configuration.
+- *    0 .. 3 = USART0 .. USART3
+- *    4      = DBGU
+- */
+-static struct at91_uart_config __initdata ek_uart_config = {
+-	.console_tty	= 0,				/* ttyS0 */
+-	.nr_tty		= 2,
+-	.tty_map	= { 4, 0, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+-};
+-
+ static void __init ek_map_io(void)
+ {
+ 	/* Initialize processor: 12.000 MHz crystal */
+ 	at91sam9rl_initialize(12000000);
+ 
+-	/* Setup the serial ports and console */
+-	at91_init_serial(&ek_uart_config);
++	/* DGBU on ttyS0. (Rx & Tx only) */
++	at91_register_uart(0, 0, 0);
++
++	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
++	at91_register_uart(AT91SAM9RL_ID_US0, 1, 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)
+diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
+new file mode 100755
+index 0000000..b571710
+--- /dev/null
++++ b/arch/arm/mach-at91/board-yl-9200.c
+@@ -0,0 +1,683 @@
++/*
++ * linux/arch/arm/mach-at91/board-yl-9200.c
++ *
++ * Adapted from:
++ *various board files in
++ * /arch/arm/mach-at91
++ * modifications  to convert to  YL-9200 platform
++ *  Copyright (C) 2007 S.Birtles
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public 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/can_bus/candata.h>*/
++#include <linux/spi/ads7846.h>
++#include <linux/mtd/physmap.h>
++
++/*#include <sound/gpio_sounder.h>*/
++#include <asm/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 <asm/arch/board.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/at91rm9200_mc.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
++
++#include "generic.h"
++#include <asm/arch/at91_pio.h>
++
++#define YL_9200_FLASH_BASE	AT91_CHIPSELECT_0
++#define YL_9200_FLASH_SIZE	0x800000
++
++/*
++ * Serial port configuration.
++ *    0 .. 3 = USART0 .. USART3
++ *    4      = DBGU
++ *atmel_usart.0: ttyS0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL
++ *atmel_usart.1: ttyS1 at MMIO 0xfffc0000 (irq = 6) is a ATMEL_SERIAL
++ *atmel_usart.2: ttyS2 at MMIO 0xfffc4000 (irq = 7) is a ATMEL_SERIAL
++ *atmel_usart.3: ttyS3 at MMIO 0xfffc8000 (irq = 8) is a ATMEL_SERIAL
++ *atmel_usart.4: ttyS4 at MMIO 0xfffcc000 (irq = 9) is a ATMEL_SERIAL
++ * on the YL-9200 we are sitting at the following
++ *ttyS0 at MMIO 0xfefff200 (irq = 1) is a AT91_SERIAL
++ *ttyS1 at MMIO 0xfefc4000 (irq = 7) is a AT91_SERIAL
++ */
++
++/* extern void __init yl_9200_add_device_sounder(struct gpio_sounder *sounders, int nr);*/
++
++static struct at91_uart_config __initdata yl_9200_uart_config = {
++	.console_tty	= 0,				/* ttyS0 */
++	.nr_tty		= 3,
++	.tty_map	= { 4, 1, 0, -1, -1 }		/* ttyS0, ..., ttyS4 */
++};
++
++static void __init yl_9200_map_io(void)
++{
++	/* Initialize processor: 18.432 MHz crystal */
++	/*Also initialises register clocks & gpio*/
++	at91rm9200_initialize(18432000, AT91RM9200_PQFP); /*we have a 3 bank system*/
++
++	/* Setup the serial ports and console */
++	at91_init_serial(&yl_9200_uart_config);
++
++	/* Setup the LEDs D2=PB17,D3=PB16 */
++	at91_init_leds(AT91_PIN_PB16,AT91_PIN_PB17); /*cpu-led,timer-led*/
++}
++
++static void __init yl_9200_init_irq(void)
++{
++	at91rm9200_init_interrupts(NULL);
++}
++
++static struct at91_eth_data __initdata yl_9200_eth_data = {
++	.phy_irq_pin	= AT91_PIN_PB28,
++	.is_rmii	= 1,
++};
++
++static struct at91_usbh_data __initdata yl_9200_usbh_data = {
++	.ports		= 1,  /* this should be 1 not 2 for the Yl9200*/
++};
++
++static struct at91_udc_data __initdata yl_9200_udc_data = {
++/*on sheet 7 Schemitic rev 1.0*/
++	.pullup_pin	= AT91_PIN_PC4,
++	.vbus_pin=  AT91_PIN_PC5,
++	.pullup_active_low = 1, /*ACTIVE LOW!! due to PNP transistor on page 7*/
++
++};
++/*
++static struct at91_cf_data __initdata yl_9200_cf_data = {
++TODO S.BIRTLES
++	.det_pin	= AT91_PIN_xxx,
++	.rst_pin	= AT91_PIN_xxx,
++	.irq_pin	= ... not connected
++	.vcc_pin	= ... always powered
++
++};
++*/
++static struct at91_mmc_data __initdata yl_9200_mmc_data = {
++	.det_pin	= AT91_PIN_PB9, /*THIS LOOKS CORRECT SHEET7*/
++/*	.wp_pin		= ... not connected  SHEET7*/
++	.slot_b		= 0,
++	.wire4		= 1,
++
++};
++
++/* --------------------------------------------------------------------
++ *  Touch screen
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++static int ads7843_pendown_state(void)
++{
++	return !at91_get_gpio_value(AT91_PIN_PB11);	/* Touchscreen PENIRQ */
++}
++
++static void __init at91_init_device_ts(void)
++{
++/*IMPORTANT NOTE THE SPI INTERFACE IS ALREADY CONFIGURED BY XXX_DEVICES.C
++THAT IS TO SAY THAT  MISO,MOSI,SPCK AND CS  are already configured
++we only need to enable the other datapins which are:
++PB10/RK1 BUSY
++*/
++/* Touchscreen BUSY signal ,  pin,use pullup ( TODO not currently used in the ADS7843/6.c driver)*/
++at91_set_gpio_input(AT91_PIN_PB10, 1);
++}
++
++#else
++static void __init at91_init_device_ts(void) {}
++#endif
++
++static struct ads7846_platform_data ads_info = {
++	.model			= 7843,
++	.x_min			= 150,
++	.x_max			= 3830,
++	.y_min			= 190,
++	.y_max			= 3830,
++	.vref_delay_usecs	= 100,
++/* for a 8" touch screen*/
++	//.x_plate_ohms		= 603, //= 450, S.Birtles TODO
++	//.y_plate_ohms		= 332, //= 250, S.Birtles TODO
++/*for a 10.4" touch screen*/
++	//.x_plate_ohms		=611,
++	//.y_plate_ohms		=325,
++
++	.x_plate_ohms	= 576,
++	.y_plate_ohms	= 366,
++		//
++	.pressure_max		= 15000, /*generally nonsense on the 7843*/
++	 /*number of times to send query to chip in a given run 0 equals one time (do not set to 0!! ,there is a bug in ADS 7846 code)*/
++	.debounce_max		= 1,
++	.debounce_rep		= 0,
++	.debounce_tol		= (~0),
++	.get_pendown_state	= ads7843_pendown_state,
++};
++
++/*static struct canbus_platform_data can_info = {
++	.model			= 2510,
++};
++*/
++
++static struct spi_board_info yl_9200_spi_devices[] = {
++/*this sticks it at:
++ /sys/devices/platform/atmel_spi.0/spi0.0
++ /sys/bus/platform/devices/
++Documentation/spi IIRC*/
++
++#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++ /*(this IS correct 04-NOV-2007)*/
++	{
++		.modalias		= "ads7846", /* because the driver is called ads7846*/
++		.chip_select	= 0, /*THIS MUST BE AN INDEX INTO AN ARRAY OF  pins */
++/*this is ONLY TO BE USED if chipselect above is not used, it passes a pin directly for the chip select*/
++		/*.controller_data =AT91_PIN_PA3 ,*/
++		.max_speed_hz	= 5000*26, /*(4700 * 26)-125000 * 26, (max sample rate @ 3V) * (cmd + data + overhead) */
++		.bus_num		= 0,
++		.platform_data	= &ads_info,
++		.irq			= AT91_PIN_PB11,
++	},
++#endif
++/*we need to put our CAN driver data here!!*/
++/*THIS IS ALL DUMMY DATA*/
++/*	{
++		.modalias		= "mcp2510", //DUMMY for MCP2510 chip
++		.chip_select	= 1,*/ /*THIS MUST BE AN INDEX INTO AN ARRAY OF  pins */
++	/*this is ONLY TO BE USED if chipselect above is not used, it passes a pin directly for the chip select */
++	/*  .controller_data =AT91_PIN_PA4 ,
++		.max_speed_hz	= 25000 * 26,
++		.bus_num		= 0,
++		.platform_data	= &can_info,
++		.irq			= AT91_PIN_PC0,
++	},
++	*/
++	//max SPI chip needs to go here
++};
++
++static struct mtd_partition __initdata yl_9200_nand_partition[] = {
++	{
++		.name	= "AT91 NAND partition 1, boot",
++		.offset	= 0,
++		.size	= 1 * SZ_256K
++	},
++	{
++		.name	= "AT91 NAND partition 2, kernel",
++		.offset	= 1 * SZ_256K,
++		.size	= 2 * SZ_1M - 1 * SZ_256K
++	},
++	{
++		.name	= "AT91 NAND partition 3, filesystem",
++		.offset	= 2 * SZ_1M,
++		.size	= 14 * SZ_1M
++	},
++	{
++		.name	= "AT91 NAND partition 4, storage",
++		.offset	= 16 * SZ_1M,
++		.size	= 16 * SZ_1M
++	},
++	{
++		.name	= "AT91 NAND partition 5, ext-fs",
++		.offset	= 32 * SZ_1M,
++		.size	= 32 * SZ_1M
++	},
++};
++
++static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
++{
++	*num_partitions = ARRAY_SIZE(yl_9200_nand_partition);
++	return yl_9200_nand_partition;
++}
++
++static struct at91_nand_data __initdata yl_9200_nand_data = {
++	.ale= 6,
++	.cle= 7,
++	/*.det_pin	= AT91_PIN_PCxx,*/   /*we don't have a det pin because NandFlash is fixed to board*/
++	.rdy_pin	= AT91_PIN_PC14,  /*R/!B Sheet10*/
++	.enable_pin	= AT91_PIN_PC15,  /*!CE  Sheet10 */
++	.partition_info	= nand_partitions,
++};
++
++
++
++/*
++TODO S.Birtles
++potentially a problem with the size above
++physmap platform flash device: 00800000 at 10000000
++physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank
++NOR chip too large to fit in mapping. Attempting to cope...
++ Intel/Sharp Extended Query Table at 0x0031
++Using buffer write method
++cfi_cmdset_0001: Erase suspend on write enabled
++Reducing visibility of 16384KiB chip to 8192KiB
++*/
++
++static struct mtd_partition yl_9200_flash_partitions[] = {
++	{
++		.name =		"Bootloader",
++		.size =		0x00040000,
++		.offset =	0,
++		.mask_flags =	MTD_WRITEABLE  /* force read-only */
++	},{
++		.name =		"Kernel",
++		.size =		0x001C0000,
++		.offset =	0x00040000,
++	},{
++		.name =		"Filesystem",
++		.size =		MTDPART_SIZ_FULL,
++		.offset =	0x00200000
++	}
++
++};
++
++static struct physmap_flash_data yl_9200_flash_data = {
++	.width	= 2,
++	.parts          = yl_9200_flash_partitions,
++	.nr_parts       = ARRAY_SIZE(yl_9200_flash_partitions),
++};
++
++static struct resource yl_9200_flash_resources[] = {
++{
++	.start		= YL_9200_FLASH_BASE,
++	.end		= YL_9200_FLASH_BASE + YL_9200_FLASH_SIZE - 1,
++	.flags		= IORESOURCE_MEM,
++	}
++};
++
++static struct platform_device yl_9200_flash = {
++	.name		= "physmap-flash",
++	.id		= 0,
++	.dev		= {
++				.platform_data	= &yl_9200_flash_data,
++			},
++	.resource	= yl_9200_flash_resources,
++	.num_resources  = ARRAY_SIZE(yl_9200_flash_resources),
++};
++
++
++static struct gpio_led yl_9200_leds[] = {
++/*D2 &D3 are passed directly in via at91_init_leds*/
++	{
++		.name			= "led4",  /*D4*/
++		.gpio			= AT91_PIN_PB15,
++		.active_low		= 1,
++		.default_trigger	= "heartbeat",
++		/*.default_trigger	= "timer",*/
++	},
++	{
++		.name			= "led5",  /*D5*/
++		.gpio			= AT91_PIN_PB8,
++		.active_low		= 1,
++		.default_trigger	= "heartbeat",
++	}
++};
++
++//static struct gpio_sounder yl_9200_sounder[] = {*/
++/*This is a simple speaker attached to a gpo line*/
++
++//	{
++//		.name			= "Speaker",  /*LS1*/
++//		.gpio			= AT91_PIN_PA22,
++//		.active_low		= 0,
++//		.default_trigger	= "heartbeat",
++		/*.default_trigger	= "timer",*/
++//	},
++//};
++
++
++
++static struct i2c_board_info __initdata yl_9200_i2c_devices[] = {
++	{
++	/*TODO*/
++		I2C_BOARD_INFO("CS4334", 0x00),
++	}
++};
++
++
++ /*
++ * GPIO Buttons
++ */
++#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
++static struct gpio_keys_button yl_9200_buttons[] = {
++	{
++		.gpio		= AT91_PIN_PA24,
++		.code	= BTN_2,
++		.desc		= "SW2",
++		.active_low	= 1,
++		.wakeup		= 1,
++	},
++	{
++		.gpio		= AT91_PIN_PB1,
++		.code	= BTN_3,
++		.desc		= "SW3",
++		.active_low	= 1,
++		.wakeup		= 1,
++	},
++	{
++		.gpio		= AT91_PIN_PB2,
++		.code	= BTN_4,
++		.desc		= "SW4",
++		.active_low	= 1,
++		.wakeup		= 1,
++	},
++	{
++		.gpio		= AT91_PIN_PB6,
++		.code	= BTN_5,
++		.desc		= "SW5",
++		.active_low	= 1,
++		.wakeup		= 1,
++	},
++
++};
++
++static struct gpio_keys_platform_data yl_9200_button_data = {
++	.buttons	= yl_9200_buttons,
++	.nbuttons	= ARRAY_SIZE(yl_9200_buttons),
++};
++
++static struct platform_device yl_9200_button_device = {
++	.name		= "gpio-keys",
++	.id		= -1,
++	.num_resources	= 0,
++	.dev		= {
++	.platform_data	= &yl_9200_button_data,
++	}
++};
++
++static void __init yl_9200_add_device_buttons(void)
++{
++	//SW2
++	at91_set_gpio_input(AT91_PIN_PA24, 0);
++	at91_set_deglitch(AT91_PIN_PA24, 1);
++
++	//SW3
++	at91_set_gpio_input(AT91_PIN_PB1, 0);
++	at91_set_deglitch(AT91_PIN_PB1, 1);
++	//SW4
++	at91_set_gpio_input(AT91_PIN_PB2, 0);
++	at91_set_deglitch(AT91_PIN_PB2, 1);
++
++	//SW5
++	at91_set_gpio_input(AT91_PIN_PB6, 0);
++	at91_set_deglitch(AT91_PIN_PB6, 1);
++
++
++	at91_set_gpio_output(AT91_PIN_PB7, 1);	/* #TURN BUTTONS ON, SHEET 5  of schematics */
++	platform_device_register(&yl_9200_button_device);
++}
++#else
++static void __init yl_9200_add_device_buttons(void) {}
++#endif
++
++#if defined(CONFIG_FB_S1D135XX) || defined(CONFIG_FB_S1D13XXX_MODULE)
++#include <video/s1d13xxxfb.h>
++
++/* EPSON S1D13806 FB (discontinued chip)*/
++/* EPSON S1D13506 FB */
++
++#define AT91_FB_REG_BASE	0x80000000L
++#define AT91_FB_REG_SIZE	0x200
++#define AT91_FB_VMEM_BASE	0x80200000L
++#define AT91_FB_VMEM_SIZE	0x200000L
++
++/*#define S1D_DISPLAY_WIDTH           640*/
++/*#define S1D_DISPLAY_HEIGHT          480*/
++
++
++static void __init yl_9200_init_video(void)
++{
++	at91_sys_write(AT91_PIOC + PIO_ASR,AT91_PIN_PC6);
++	at91_sys_write(AT91_PIOC + PIO_BSR,0);
++	at91_sys_write(AT91_PIOC + PIO_ASR,AT91_PIN_PC6);
++
++	at91_sys_write( AT91_SMC_CSR(2),
++	AT91_SMC_NWS_(0x4) |
++	AT91_SMC_WSEN |
++	AT91_SMC_TDF_(0x100) |
++	AT91_SMC_DBW
++	);
++
++
++
++}
++
++
++static struct s1d13xxxfb_regval yl_9200_s1dfb_initregs[] =
++{
++	{S1DREG_MISC,				0x00},   /* Miscellaneous Register*/
++	{S1DREG_COM_DISP_MODE,		0x01},   /* Display Mode Register, LCD only*/
++	{S1DREG_GPIO_CNF0,			0x00},   /* General IO Pins Configuration Register*/
++	{S1DREG_GPIO_CTL0,			0x00},   /* General IO Pins Control Register*/
++	{S1DREG_CLK_CNF,			0x11},   /* Memory Clock Configuration Register*/
++	{S1DREG_LCD_CLK_CNF,		0x10},   /* LCD Pixel Clock Configuration Register*/
++	{S1DREG_CRT_CLK_CNF,		0x12},   /* CRT/TV Pixel Clock Configuration Register*/
++	{S1DREG_MPLUG_CLK_CNF,		0x01},   /* MediaPlug Clock Configuration Register*/
++	{S1DREG_CPU2MEM_WST_SEL,	0x02},   /* CPU To Memory Wait State Select Register*/
++	{S1DREG_MEM_CNF,			0x00},   /* Memory Configuration Register*/
++	{S1DREG_SDRAM_REF_RATE,		0x04},   /* DRAM Refresh Rate Register, MCLK source*/
++	{S1DREG_SDRAM_TC0,			0x12},   /* DRAM Timings Control Register 0*/
++	{S1DREG_SDRAM_TC1,			0x02},   /* DRAM Timings Control Register 1*/
++	{S1DREG_PANEL_TYPE,			0x25},   /* Panel Type Register*/
++	{S1DREG_MOD_RATE,			0x00},   /* MOD Rate Register*/
++	{S1DREG_LCD_DISP_HWIDTH,	0x4F},   /* LCD Horizontal Display Width Register*/
++	{S1DREG_LCD_NDISP_HPER,		0x13},   /* LCD Horizontal Non-Display Period Register*/
++	{S1DREG_TFT_FPLINE_START,	0x01},   /* TFT FPLINE Start Position Register*/
++	{S1DREG_TFT_FPLINE_PWIDTH,	0x0c},   /* TFT FPLINE Pulse Width Register*/
++	{S1DREG_LCD_DISP_VHEIGHT0,	0xDF},   /* LCD Vertical Display Height Register 0*/
++	{S1DREG_LCD_DISP_VHEIGHT1,	0x01},   /* LCD Vertical Display Height Register 1*/
++	{S1DREG_LCD_NDISP_VPER,		0x2c},   /* LCD Vertical Non-Display Period Register*/
++	{S1DREG_TFT_FPFRAME_START,	0x0a},   /* TFT FPFRAME Start Position Register*/
++	{S1DREG_TFT_FPFRAME_PWIDTH,	0x02},   /* TFT FPFRAME Pulse Width Register*/
++	{S1DREG_LCD_DISP_MODE,		0x05},   /* LCD Display Mode Register*/
++	{S1DREG_LCD_MISC,			0x01},   /* LCD Miscellaneous Register*/
++	{S1DREG_LCD_DISP_START0,	0x00},   /* LCD Display Start Address Register 0*/
++	{S1DREG_LCD_DISP_START1,	0x00},   /* LCD Display Start Address Register 1*/
++	{S1DREG_LCD_DISP_START2,	0x00},   /* LCD Display Start Address Register 2*/
++	{S1DREG_LCD_MEM_OFF0,		0x80},   /* LCD Memory Address Offset Register 0*/
++	{S1DREG_LCD_MEM_OFF1,		0x02},   /* LCD Memory Address Offset Register 1*/
++	{S1DREG_LCD_PIX_PAN,		0x03},   /* LCD Pixel Panning Register*/
++	{S1DREG_LCD_DISP_FIFO_HTC,	0x00},   /* LCD Display FIFO High Threshold Control Register*/
++	{S1DREG_LCD_DISP_FIFO_LTC,	0x00},   /* LCD Display FIFO Low Threshold Control Register*/
++	{S1DREG_CRT_DISP_HWIDTH,	0x4F},   /* CRT/TV Horizontal Display Width Register*/
++	{S1DREG_CRT_NDISP_HPER,		0x13},   /* CRT/TV Horizontal Non-Display Period Register*/
++	{S1DREG_CRT_HRTC_START,		0x01},   /* CRT/TV HRTC Start Position Register*/
++	{S1DREG_CRT_HRTC_PWIDTH,	0x0B},   /* CRT/TV HRTC Pulse Width Register*/
++	{S1DREG_CRT_DISP_VHEIGHT0,	0xDF},   /* CRT/TV Vertical Display Height Register 0*/
++	{S1DREG_CRT_DISP_VHEIGHT1,	0x01},   /* CRT/TV Vertical Display Height Register 1*/
++	{S1DREG_CRT_NDISP_VPER,		0x2B},   /* CRT/TV Vertical Non-Display Period Register*/
++	{S1DREG_CRT_VRTC_START,		0x09},   /* CRT/TV VRTC Start Position Register*/
++	{S1DREG_CRT_VRTC_PWIDTH,	0x01},   /* CRT/TV VRTC Pulse Width Register*/
++	{S1DREG_TV_OUT_CTL,			0x18},   /* TV Output Control Register */
++	{S1DREG_CRT_DISP_MODE,		0x05},   /* CRT/TV Display Mode Register, 16BPP*/
++	{S1DREG_CRT_DISP_START0,	0x00},   /* CRT/TV Display Start Address Register 0*/
++	{S1DREG_CRT_DISP_START1,	0x00},   /* CRT/TV Display Start Address Register 1*/
++	{S1DREG_CRT_DISP_START2,	0x00},   /* CRT/TV Display Start Address Register 2*/
++	{S1DREG_CRT_MEM_OFF0,		0x80},   /* CRT/TV Memory Address Offset Register 0*/
++	{S1DREG_CRT_MEM_OFF1,		0x02},   /* CRT/TV Memory Address Offset Register 1*/
++	{S1DREG_CRT_PIX_PAN,		0x00},   /* CRT/TV Pixel Panning Register*/
++	{S1DREG_CRT_DISP_FIFO_HTC,	0x00},   /* CRT/TV Display FIFO High Threshold Control Register*/
++	{S1DREG_CRT_DISP_FIFO_LTC,	0x00},   /* CRT/TV Display FIFO Low Threshold Control Register*/
++	{S1DREG_LCD_CUR_CTL,		0x00},   /* LCD Ink/Cursor Control Register*/
++	{S1DREG_LCD_CUR_START,		0x01},   /* LCD Ink/Cursor Start Address Register*/
++	{S1DREG_LCD_CUR_XPOS0,		0x00},   /* LCD Cursor X Position Register 0*/
++	{S1DREG_LCD_CUR_XPOS1,		0x00},   /* LCD Cursor X Position Register 1*/
++	{S1DREG_LCD_CUR_YPOS0,		0x00},   /* LCD Cursor Y Position Register 0*/
++	{S1DREG_LCD_CUR_YPOS1,		0x00},   /* LCD Cursor Y Position Register 1*/
++	{S1DREG_LCD_CUR_BCTL0,		0x00},   /* LCD Ink/Cursor Blue Color 0 Register*/
++	{S1DREG_LCD_CUR_GCTL0,		0x00},   /* LCD Ink/Cursor Green Color 0 Register*/
++	{S1DREG_LCD_CUR_RCTL0,		0x00},   /* LCD Ink/Cursor Red Color 0 Register*/
++	{S1DREG_LCD_CUR_BCTL1,		0x1F},   /* LCD Ink/Cursor Blue Color 1 Register*/
++	{S1DREG_LCD_CUR_GCTL1,		0x3F},   /* LCD Ink/Cursor Green Color 1 Register*/
++	{S1DREG_LCD_CUR_RCTL1,		0x1F},   /* LCD Ink/Cursor Red Color 1 Register*/
++	{S1DREG_LCD_CUR_FIFO_HTC,	0x00},   /* LCD Ink/Cursor FIFO Threshold Register*/
++	{S1DREG_CRT_CUR_CTL,		0x00},   /* CRT/TV Ink/Cursor Control Register*/
++	{S1DREG_CRT_CUR_START,		0x01},   /* CRT/TV Ink/Cursor Start Address Register*/
++	{S1DREG_CRT_CUR_XPOS0,		0x00},   /* CRT/TV Cursor X Position Register 0*/
++	{S1DREG_CRT_CUR_XPOS1,		0x00},   /* CRT/TV Cursor X Position Register 1*/
++	{S1DREG_CRT_CUR_YPOS0,		0x00},   /* CRT/TV Cursor Y Position Register 0*/
++	{S1DREG_CRT_CUR_YPOS1,		0x00},   /* CRT/TV Cursor Y Position Register 1*/
++	{S1DREG_CRT_CUR_BCTL0,		0x00},   /* CRT/TV Ink/Cursor Blue Color 0 Register*/
++	{S1DREG_CRT_CUR_GCTL0,		0x00},   /* CRT/TV Ink/Cursor Green Color 0 Register*/
++	{S1DREG_CRT_CUR_RCTL0,		0x00},   /* CRT/TV Ink/Cursor Red Color 0 Register*/
++	{S1DREG_CRT_CUR_BCTL1,		0x1F},   /* CRT/TV Ink/Cursor Blue Color 1 Register*/
++	{S1DREG_CRT_CUR_GCTL1,		0x3F},   /* CRT/TV Ink/Cursor Green Color 1 Register*/
++	{S1DREG_CRT_CUR_RCTL1,		0x1F},   /* CRT/TV Ink/Cursor Red Color 1 Register*/
++	{S1DREG_CRT_CUR_FIFO_HTC,	0x00},   /* CRT/TV Ink/Cursor FIFO Threshold Register*/
++	{S1DREG_BBLT_CTL0,			0x00},   /* BitBlt Control Register 0*/
++	{S1DREG_BBLT_CTL1,			0x01},   /* BitBlt Control Register 1*/
++	{S1DREG_BBLT_CC_EXP,		0x00},   /* BitBlt ROP Code/Color Expansion Register*/
++	{S1DREG_BBLT_OP,			0x00},   /* BitBlt Operation Register*/
++	{S1DREG_BBLT_SRC_START0,	0x00},   /* BitBlt Source Start Address Register 0*/
++	{S1DREG_BBLT_SRC_START1,	0x00},   /* BitBlt Source Start Address Register 1*/
++	{S1DREG_BBLT_SRC_START2,	0x00},   /* BitBlt Source Start Address Register 2*/
++	{S1DREG_BBLT_DST_START0,	0x00},   /* BitBlt Destination Start Address Register 0*/
++	{S1DREG_BBLT_DST_START1,	0x00},   /* BitBlt Destination Start Address Register 1*/
++	{S1DREG_BBLT_DST_START2,	0x00},   /* BitBlt Destination Start Address Register 2*/
++	{S1DREG_BBLT_MEM_OFF0,		0x00},   /* BitBlt Memory Address Offset Register 0*/
++	{S1DREG_BBLT_MEM_OFF1,		0x00},   /* BitBlt Memory Address Offset Register 1*/
++	{S1DREG_BBLT_WIDTH0,		0x00},   /* BitBlt Width Register 0*/
++	{S1DREG_BBLT_WIDTH1,		0x00},   /* BitBlt Width Register 1*/
++	{S1DREG_BBLT_HEIGHT0,		0x00},   /* BitBlt Height Register 0*/
++	{S1DREG_BBLT_HEIGHT1,		0x00},   /* BitBlt Height Register 1*/
++	{S1DREG_BBLT_BGC0,			0x00},   /* BitBlt Background Color Register 0*/
++	{S1DREG_BBLT_BGC1,			0x00},   /* BitBlt Background Color Register 1*/
++	{S1DREG_BBLT_FGC0,			0x00},   /* BitBlt Foreground Color Register 0*/
++	{S1DREG_BBLT_FGC1,			0x00},   /* BitBlt Foreground Color Register 1*/
++	{S1DREG_LKUP_MODE,			0x00},   /* Look-Up Table Mode Register*/
++	{S1DREG_LKUP_ADDR,			0x00},   /* Look-Up Table Address Register*/
++	{S1DREG_PS_CNF,				0x00},   /* Power Save Configuration Register*/
++	{S1DREG_PS_STATUS,			0x00},   /* Power Save Status Register*/
++	{S1DREG_CPU2MEM_WDOGT,		0x00},   /* CPU-to-Memory Access Watchdog Timer Register*/
++	{S1DREG_COM_DISP_MODE,		0x01},   /* Display Mode Register, LCD only*/
++};
++
++static u64 s1dfb_dmamask = 0xffffffffUL;
++
++static struct s1d13xxxfb_pdata yl_9200_s1dfb_pdata = {
++		.initregs				= yl_9200_s1dfb_initregs,
++		.initregssize			= ARRAY_SIZE(yl_9200_s1dfb_initregs),
++		.platform_init_video	= yl_9200_init_video,
++};
++
++static struct resource yl_9200_s1dfb_resource[] = {
++	[0] = {	/* video mem */
++		.name   = "s1d13xxxfb memory",
++	/*	.name   = "s1d13806 memory",*/
++		.start  = AT91_FB_VMEM_BASE,
++		.end    = AT91_FB_VMEM_BASE + AT91_FB_VMEM_SIZE -1,
++		.flags  = IORESOURCE_MEM,
++	},
++	[1] = {	/* video registers */
++		.name   = "s1d13xxxfb registers",
++	/*	.name   = "s1d13806 registers",*/
++		.start  = AT91_FB_REG_BASE,
++		.end    = AT91_FB_REG_BASE + AT91_FB_REG_SIZE -1,
++		.flags  = IORESOURCE_MEM,
++	},
++};
++
++static struct platform_device yl_9200_s1dfb_device = {
++	/*TODO S.Birtles , really we need the chip revision in here as well*/
++		.name		= "s1d13806fb",
++	/*  .name		= "s1d13506fb",*/
++		.id			= -1,
++		.dev		= {
++	/*TODO theres a waring here!!*/
++	/*WARNING: vmlinux.o(.data+0x2dbc): Section mismatch: reference to .init.text: (between 'yl_9200_s1dfb_pdata' and 's1dfb_dmamask')*/
++		.dma_mask		= &s1dfb_dmamask,
++		.coherent_dma_mask	= 0xffffffff,
++		.platform_data		= &yl_9200_s1dfb_pdata,
++	},
++	.resource	= yl_9200_s1dfb_resource,
++	.num_resources	= ARRAY_SIZE(yl_9200_s1dfb_resource),
++};
++
++void __init yl_9200_add_device_video(void)
++{
++	platform_device_register(&yl_9200_s1dfb_device);
++}
++#else
++	void __init yl_9200_add_device_video(void) {}
++#endif
++
++/*this is not called first , yl_9200_map_io is called first*/
++static void __init yl_9200_board_init(void)
++{
++	/* Serial */
++	at91_add_device_serial();
++	/* Ethernet */
++	at91_add_device_eth(&yl_9200_eth_data);
++	/* USB Host */
++	at91_add_device_usbh(&yl_9200_usbh_data);
++	/* USB Device */
++	at91_add_device_udc(&yl_9200_udc_data);
++	/* pullup_pin it is  actually active low, but this is not needed, driver sets it up */
++	/*at91_set_multi_drive(yl_9200_udc_data.pullup_pin, 0);*/
++
++	/* Compact Flash */
++	/*at91_add_device_cf(&yl_9200_cf_data);*/
++
++	/* I2C */
++	at91_add_device_i2c(yl_9200_i2c_devices, ARRAY_SIZE(yl_9200_i2c_devices));
++	/* SPI */
++	/*TODO YL9200 we have 2 spi interfaces touch screen & CAN*/
++	/* AT91_PIN_PA5, AT91_PIN_PA6 , are used on the  max 485 NOT SPI*/
++
++	/*touch screen and CAN*/
++	at91_add_device_spi(yl_9200_spi_devices, ARRAY_SIZE(yl_9200_spi_devices));
++
++	/*Basically the  TS uses  PB11 & PB10 , PB11 is configured by the SPI system BP10 IS NOT USED!!*/
++	/* we need this incase the board is running without a touch screen*/
++	#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++	at91_init_device_ts(); /*init the touch screen device*/
++	#endif
++	/* DataFlash card */
++	at91_add_device_mmc(0, &yl_9200_mmc_data);
++	/* NAND */
++	at91_add_device_nand(&yl_9200_nand_data);
++	/* NOR Flash */
++	platform_device_register(&yl_9200_flash);
++	/* LEDs. Note!! this does not include the led's we passed for the processor status */
++	at91_gpio_leds(yl_9200_leds, ARRAY_SIZE(yl_9200_leds));
++	/* VGA  */
++	/*this is self registered by including the s1d13xxx chip in the kernel build*/
++	yl_9200_add_device_video();
++	/* Push Buttons */
++	yl_9200_add_device_buttons();
++	/*TODO fixup the Sounder */
++//	yl_9200_add_device_sounder(yl_9200_sounder,ARRAY_SIZE(yl_9200_sounder));
++
++}
++
++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			= yl_9200_map_io,
++	.init_irq		= yl_9200_init_irq,
++	.init_machine	= yl_9200_board_init,
++MACHINE_END
+diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
+index de6424e..a33dfe4 100644
+--- a/arch/arm/mach-at91/clock.c
++++ b/arch/arm/mach-at91/clock.c
+@@ -23,7 +23,6 @@
+ #include <linux/delay.h>
+ #include <linux/clk.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+ #include <asm/mach-types.h>
+ 
+diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
+index a67defd..39733b6 100644
+--- a/arch/arm/mach-at91/pm.c
++++ b/arch/arm/mach-at91/pm.c
+@@ -26,12 +26,135 @@
+ #include <asm/mach-types.h>
+ 
+ #include <asm/arch/at91_pmc.h>
+-#include <asm/arch/at91rm9200_mc.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/cpu.h>
+ 
+ #include "generic.h"
+ 
++#ifdef CONFIG_ARCH_AT91RM9200
++#include <asm/arch/at91rm9200_mc.h>
++
++/*
++ * The AT91RM9200 goes into self-refresh mode with this command, and will
++ * terminate self-refresh automatically on the next SDRAM access.
++ */
++#define sdram_selfrefresh_enable()	at91_sys_write(AT91_SDRAMC_SRR, 1)
++#define sdram_selfrefresh_disable()	do {} while (0)
++
++#elif defined(CONFIG_ARCH_AT91CAP9)
++#include <asm/arch/at91cap9_ddrsdr.h>
++
++static u32 saved_lpr;
++
++static inline void sdram_selfrefresh_enable(void)
++{
++	u32 lpr;
++
++	saved_lpr = at91_sys_read(AT91_DDRSDRC_LPR);
++
++	lpr = saved_lpr & ~AT91_DDRSDRC_LPCB;
++	at91_sys_write(AT91_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
++}
++
++#define sdram_selfrefresh_disable()	at91_sys_write(AT91_DDRSDRC_LPR, saved_lpr)
++
++#else
++#include <asm/arch/at91sam9_sdramc.h>
++
++static u32 saved_lpr;
++
++static inline void sdram_selfrefresh_enable(void)
++{
++	u32 lpr;
++
++	saved_lpr = at91_sys_read(AT91_SDRAMC_LPR);
++
++	lpr = saved_lpr & ~AT91_SDRAMC_LPCB;
++	at91_sys_write(AT91_SDRAMC_LPR, lpr | AT91_SDRAMC_LPCB_SELF_REFRESH);
++}
++
++#define sdram_selfrefresh_disable()	at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
++
++/*
++ * FIXME: The AT91SAM9263 has a second EBI controller which may have
++ *        additional SDRAM.  pm_slowclock.S will require a similar fix.
++ */
++
++#endif
++
++
++/*
++ * Show the reason for the previous system reset.
++ */
++#if defined(AT91_SHDWC)
++
++#include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
++
++static void __init show_reset_status(void)
++{
++	static char reset[] __initdata = "reset";
++
++	static char general[] __initdata = "general";
++	static char wakeup[] __initdata = "wakeup";
++	static char watchdog[] __initdata = "watchdog";
++	static char software[] __initdata = "software";
++	static char user[] __initdata = "user";
++	static char unknown[] __initdata = "unknown";
++
++	static char signal[] __initdata = "signal";
++	static char rtc[] __initdata = "rtc";
++	static char rtt[] __initdata = "rtt";
++	static char restore[] __initdata = "power-restored";
++
++	char *reason, *r2 = reset;
++	u32 reset_type, wake_type;
++
++	reset_type = at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
++	wake_type = at91_sys_read(AT91_SHDW_SR);
++
++	switch (reset_type) {
++	case AT91_RSTC_RSTTYP_GENERAL:
++		reason = general;
++		break;
++	case AT91_RSTC_RSTTYP_WAKEUP:
++		/* board-specific code enabled the wakeup sources */
++		reason = wakeup;
++
++		/* "wakeup signal" */
++		if (wake_type & AT91_SHDW_WAKEUP0)
++			r2 = signal;
++		else {
++			r2 = reason;
++			if (wake_type & AT91_SHDW_RTTWK)	/* rtt wakeup */
++				reason = rtt;
++			else if (wake_type & AT91_SHDW_RTCWK)	/* rtc wakeup */
++				reason = rtc;
++			else if (wake_type == 0)	/* power-restored wakeup */
++				reason = restore;
++			else				/* unknown wakeup */
++				reason = unknown;
++		}
++		break;
++	case AT91_RSTC_RSTTYP_WATCHDOG:
++		reason = watchdog;
++		break;
++	case AT91_RSTC_RSTTYP_SOFTWARE:
++		reason = software;
++		break;
++	case AT91_RSTC_RSTTYP_USER:
++		reason = user;
++		break;
++	default:
++		reason = unknown;
++		break;
++	}
++	pr_info("AT91: Starting after %s %s\n", reason, r2);
++}
++#else
++static void __init show_reset_status(void) {}
++#endif
++
+ 
+ static int at91_pm_valid_state(suspend_state_t state)
+ {
+@@ -125,6 +248,11 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
+ 
+ static void (*slow_clock)(void);
+ 
++#ifdef CONFIG_AT91_SLOW_CLOCK
++extern void at91_slow_clock(void);
++extern u32 at91_slow_clock_sz;
++#endif
++
+ 
+ static int at91_pm_enter(suspend_state_t state)
+ {
+@@ -158,11 +286,14 @@ static int at91_pm_enter(suspend_state_t state)
+ 			 * turning off the main oscillator; reverse on wakeup.
+ 			 */
+ 			if (slow_clock) {
++#ifdef CONFIG_AT91_SLOW_CLOCK
++				/* copy slow_clock handler to SRAM, and call it */
++				memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz);
++#endif
+ 				slow_clock();
+ 				break;
+ 			} else {
+-				/* DEVELOPMENT ONLY */
+-				pr_info("AT91: PM - no slow clock mode yet ...\n");
++				pr_info("AT91: PM - no slow clock mode enabled ...\n");
+ 				/* FALLTHROUGH leaving master clock alone */
+ 			}
+ 
+@@ -175,13 +306,15 @@ static int at91_pm_enter(suspend_state_t state)
+ 		case PM_SUSPEND_STANDBY:
+ 			/*
+ 			 * NOTE: the Wait-for-Interrupt instruction needs to be
+-			 * in icache so the SDRAM stays in self-refresh mode until
+-			 * the wakeup IRQ occurs.
++			 * in icache so no SDRAM accesses are needed until the
++			 * wakeup IRQ occurs and self-refresh is terminated.
+ 			 */
+ 			asm("b 1f; .align 5; 1:");
+ 			asm("mcr p15, 0, r0, c7, c10, 4");	/* drain write buffer */
+-			at91_sys_write(AT91_SDRAMC_SRR, 1);	/* self-refresh mode */
+-			/* fall though to next state */
++			sdram_selfrefresh_enable();
++			asm("mcr p15, 0, r0, c7, c0, 4");	/* wait for interrupt */
++			sdram_selfrefresh_disable();
++			break;
+ 
+ 		case PM_SUSPEND_ON:
+ 			asm("mcr p15, 0, r0, c7, c0, 4");	/* wait for interrupt */
+@@ -196,6 +329,7 @@ static int at91_pm_enter(suspend_state_t state)
+ 			at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
+ 
+ error:
++	sdram_selfrefresh_disable();
+ 	target_state = PM_SUSPEND_ON;
+ 	at91_irq_resume();
+ 	at91_gpio_resume();
+@@ -220,21 +354,20 @@ static struct platform_suspend_ops at91_pm_ops ={
+ 
+ static int __init at91_pm_init(void)
+ {
+-	printk("AT91: Power Management\n");
+-
+-#ifdef CONFIG_AT91_PM_SLOW_CLOCK
+-	/* REVISIT allocations of SRAM should be dynamically managed.
+-	 * FIQ handlers and other components will want SRAM/TCM too...
+-	 */
+-	slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K));
+-	memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz);
++#ifdef CONFIG_AT91_SLOW_CLOCK
++	slow_clock = (void *) (AT91_IO_VIRT_BASE - at91_slow_clock_sz);
+ #endif
+ 
+-	/* Disable SDRAM low-power mode.  Cannot be used with self-refresh. */
++	pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : ""));
++
++#ifdef CONFIG_ARCH_AT91RM9200
++	/* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
+ 	at91_sys_write(AT91_SDRAMC_LPR, 0);
++#endif
+ 
+ 	suspend_set_ops(&at91_pm_ops);
+ 
++	show_reset_status();
+ 	return 0;
+ }
+ arch_initcall(at91_pm_init);
+diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
+index 0e2b641..dbaae5f 100644
+--- a/arch/arm/mach-clps711x/Kconfig
++++ b/arch/arm/mach-clps711x/Kconfig
+@@ -31,6 +31,8 @@ config ARCH_EDB7211
+ 	bool "EDB7211"
+ 	select ISA
+ 	select ARCH_DISCONTIGMEM_ENABLE
++	select ARCH_SPARSEMEM_ENABLE
++	select ARCH_SELECT_MEMORY_MODEL
+ 	help
+ 	  Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211
+ 	  evaluation board.
+diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
+index 0ecf997..c1252ca 100644
+--- a/arch/arm/mach-ep93xx/Makefile
++++ b/arch/arm/mach-ep93xx/Makefile
+@@ -1,7 +1,7 @@
+ #
+ # Makefile for the linux kernel.
+ #
+-obj-y			:= core.o clock.o
++obj-y			:= core.o clock.o gpio.o
+ obj-m			:=
+ obj-n			:=
+ obj-			:=
+diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
+index 91f6a07..8bc1872 100644
+--- a/arch/arm/mach-ep93xx/core.c
++++ b/arch/arm/mach-ep93xx/core.c
+@@ -159,7 +159,7 @@ static const u8 int_type2_register_offset[3]	= { 0x94, 0xb0, 0x50 };
+ static const u8 eoi_register_offset[3]		= { 0x98, 0xb4, 0x54 };
+ static const u8 int_en_register_offset[3]	= { 0x9c, 0xb8, 0x5c };
+ 
+-static void update_gpio_int_params(unsigned port)
++void ep93xx_gpio_update_int_params(unsigned port)
+ {
+ 	BUG_ON(port > 2);
+ 
+@@ -175,98 +175,10 @@ static void update_gpio_int_params(unsigned port)
+ 		EP93XX_GPIO_REG(int_en_register_offset[port]));
+ }
+ 
+-/* Port ordering is: A B F D E C G H */
+-static const u8 data_register_offset[8] = {
+-	0x00, 0x04, 0x30, 0x0c, 0x20, 0x08, 0x38, 0x40,
+-};
+-
+-static const u8 data_direction_register_offset[8] = {
+-	0x10, 0x14, 0x34, 0x1c, 0x24, 0x18, 0x3c, 0x44,
+-};
+-
+-#define GPIO_IN		0
+-#define GPIO_OUT	1
+-
+-static void ep93xx_gpio_set_direction(unsigned line, int direction)
+-{
+-	unsigned int data_direction_register;
+-	unsigned long flags;
+-	unsigned char v;
+-
+-	data_direction_register =
+-		EP93XX_GPIO_REG(data_direction_register_offset[line >> 3]);
+-
+-	local_irq_save(flags);
+-	if (direction == GPIO_OUT) {
+-		if (line >= 0 && line <= EP93XX_GPIO_LINE_MAX_IRQ) {
+-			/* Port A/B/F */
+-			gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
+-			update_gpio_int_params(line >> 3);
+-		}
+-
+-		v = __raw_readb(data_direction_register);
+-		v |= 1 << (line & 7);
+-		__raw_writeb(v, data_direction_register);
+-	} else if (direction == GPIO_IN) {
+-		v = __raw_readb(data_direction_register);
+-		v &= ~(1 << (line & 7));
+-		__raw_writeb(v, data_direction_register);
+-	}
+-	local_irq_restore(flags);
+-}
+-
+-int gpio_direction_input(unsigned gpio)
+-{
+-	if (gpio > EP93XX_GPIO_LINE_MAX)
+-		return -EINVAL;
+-
+-	ep93xx_gpio_set_direction(gpio, GPIO_IN);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_input);
+-
+-int gpio_direction_output(unsigned gpio, int value)
+-{
+-	if (gpio > EP93XX_GPIO_LINE_MAX)
+-		return -EINVAL;
+-
+-	gpio_set_value(gpio, value);
+-	ep93xx_gpio_set_direction(gpio, GPIO_OUT);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_output);
+-
+-int gpio_get_value(unsigned gpio)
+-{
+-	unsigned int data_register;
+-
+-	data_register = EP93XX_GPIO_REG(data_register_offset[gpio >> 3]);
+-
+-	return !!(__raw_readb(data_register) & (1 << (gpio & 7)));
+-}
+-EXPORT_SYMBOL(gpio_get_value);
+-
+-void gpio_set_value(unsigned gpio, int value)
++void ep93xx_gpio_int_mask(unsigned line)
+ {
+-	unsigned int data_register;
+-	unsigned long flags;
+-	unsigned char v;
+-
+-	data_register = EP93XX_GPIO_REG(data_register_offset[gpio >> 3]);
+-
+-	local_irq_save(flags);
+-	v = __raw_readb(data_register);
+-	if (value)
+-		v |= 1 << (gpio & 7);
+-	else
+-		v &= ~(1 << (gpio & 7));
+-	__raw_writeb(v, data_register);
+-	local_irq_restore(flags);
++	gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
+ }
+-EXPORT_SYMBOL(gpio_set_value);
+-
+ 
+ /*************************************************************************
+  * EP93xx IRQ handling
+@@ -316,7 +228,7 @@ static void ep93xx_gpio_irq_ack(unsigned int irq)
+ 
+ 	if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
+ 		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
+-		update_gpio_int_params(port);
++		ep93xx_gpio_update_int_params(port);
+ 	}
+ 
+ 	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
+@@ -332,7 +244,7 @@ static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
+ 		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
+ 
+ 	gpio_int_unmasked[port] &= ~port_mask;
+-	update_gpio_int_params(port);
++	ep93xx_gpio_update_int_params(port);
+ 
+ 	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
+ }
+@@ -343,7 +255,7 @@ static void ep93xx_gpio_irq_mask(unsigned int irq)
+ 	int port = line >> 3;
+ 
+ 	gpio_int_unmasked[port] &= ~(1 << (line & 7));
+-	update_gpio_int_params(port);
++	ep93xx_gpio_update_int_params(port);
+ }
+ 
+ static void ep93xx_gpio_irq_unmask(unsigned int irq)
+@@ -352,7 +264,7 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq)
+ 	int port = line >> 3;
+ 
+ 	gpio_int_unmasked[port] |= 1 << (line & 7);
+-	update_gpio_int_params(port);
++	ep93xx_gpio_update_int_params(port);
+ }
+ 
+ 
+@@ -368,7 +280,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
+ 	const int port = gpio >> 3;
+ 	const int port_mask = 1 << (gpio & 7);
+ 
+-	ep93xx_gpio_set_direction(gpio, GPIO_IN);
++	gpio_direction_output(gpio, gpio_get_value(gpio));
+ 
+ 	switch (type) {
+ 	case IRQT_RISING:
+@@ -411,7 +323,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
+ 	desc->status &= ~IRQ_TYPE_SENSE_MASK;
+ 	desc->status |= type & IRQ_TYPE_SENSE_MASK;
+ 
+-	update_gpio_int_params(port);
++	ep93xx_gpio_update_int_params(port);
+ 
+ 	return 0;
+ }
+@@ -549,6 +461,7 @@ static struct platform_device ep93xx_ohci_device = {
+ 	.resource	= ep93xx_ohci_resources,
+ };
+ 
++extern void ep93xx_gpio_init(void);
+ 
+ void __init ep93xx_init_devices(void)
+ {
+@@ -562,6 +475,8 @@ void __init ep93xx_init_devices(void)
+ 	__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+ 	__raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG);
+ 
++	ep93xx_gpio_init();
++
+ 	amba_device_register(&uart1_device, &iomem_resource);
+ 	amba_device_register(&uart2_device, &iomem_resource);
+ 	amba_device_register(&uart3_device, &iomem_resource);
+diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c
+new file mode 100644
+index 0000000..dc2e4c0
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/gpio.c
+@@ -0,0 +1,158 @@
++/*
++ * linux/arch/arm/mach-ep93xx/gpio.c
++ *
++ * Generic EP93xx GPIO handling
++ *
++ * Copyright (c) 2008 Ryan Mallon <ryan at bluewatersys.com>
++ *
++ * Based on code originally from:
++ *  linux/arch/arm/mach-ep93xx/core.c
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++
++#include <asm/arch/ep93xx-regs.h>
++#include <asm/io.h>
++#include <asm/gpio.h>
++
++struct ep93xx_gpio_chip {
++	struct gpio_chip	chip;
++
++	unsigned int		data_reg;
++	unsigned int		data_dir_reg;
++};
++
++#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip)
++
++/* From core.c */
++extern void ep93xx_gpio_int_mask(unsigned line);
++extern void ep93xx_gpio_update_int_params(unsigned port);
++
++static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++	unsigned long flags;
++	u8 v;
++
++	local_irq_save(flags);
++	v = __raw_readb(ep93xx_chip->data_dir_reg);
++	v &= ~(1 << offset);
++	__raw_writeb(v, ep93xx_chip->data_dir_reg);
++	local_irq_restore(flags);
++
++	return 0;
++}
++
++static int ep93xx_gpio_direction_output(struct gpio_chip *chip,
++					unsigned offset, int val)
++{
++	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++	unsigned long flags;
++	int line;
++	u8 v;
++
++	local_irq_save(flags);
++
++	/* Set the value */
++	v = __raw_readb(ep93xx_chip->data_reg);
++	if (val)
++		v |= (1 << offset);
++	else
++		v &= ~(1 << offset);
++	__raw_writeb(v, ep93xx_chip->data_reg);
++
++	/* Drive as an output */
++	line = chip->base + offset;
++	if (line <= EP93XX_GPIO_LINE_MAX_IRQ) {
++		/* Ports A/B/F */
++		ep93xx_gpio_int_mask(line);
++		ep93xx_gpio_update_int_params(line >> 3);
++	}
++
++	v = __raw_readb(ep93xx_chip->data_dir_reg);
++	v |= (1 << offset);
++	__raw_writeb(v, ep93xx_chip->data_dir_reg);
++
++	local_irq_restore(flags);
++
++	return 0;
++}
++
++static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++
++	return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset));
++}
++
++static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
++{
++	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++	unsigned long flags;
++	u8 v;
++
++	local_irq_save(flags);
++	v = __raw_readb(ep93xx_chip->data_reg);
++	if (val)
++		v |= (1 << offset);
++	else
++		v &= ~(1 << offset);
++	__raw_writeb(v, ep93xx_chip->data_reg);
++	local_irq_restore(flags);
++}
++
++static void ep93xx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
++{
++	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++	u8 data_reg, data_dir_reg;
++	int i;
++
++	data_reg = __raw_readb(ep93xx_chip->data_reg);
++	data_dir_reg = __raw_readb(ep93xx_chip->data_dir_reg);
++
++	for (i = 0; i < chip->ngpio; i++)
++		seq_printf(s, "GPIO %s%d: %s %s\n", chip->label, i,
++			   (data_reg & (1 << i)) ? "set" : "clear",
++			   (data_dir_reg & (1 << i)) ? "out" : "in");
++}
++
++#define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio)			\
++	{								\
++		.chip = {						\
++			.label		  = name,			\
++			.direction_input  = ep93xx_gpio_direction_input, \
++			.direction_output = ep93xx_gpio_direction_output, \
++			.get		  = ep93xx_gpio_get,		\
++			.set		  = ep93xx_gpio_set,		\
++			.dbg_show	  = ep93xx_gpio_dbg_show,	\
++			.base		  = base_gpio,			\
++			.ngpio		  = 8,				\
++		},							\
++		.data_reg	= EP93XX_GPIO_REG(dr),			\
++		.data_dir_reg	= EP93XX_GPIO_REG(ddr),			\
++	}
++
++static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = {
++	EP93XX_GPIO_BANK("A", 0x00, 0x10, 0),
++	EP93XX_GPIO_BANK("B", 0x04, 0x14, 8),
++	EP93XX_GPIO_BANK("C", 0x30, 0x34, 40),
++	EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24),
++	EP93XX_GPIO_BANK("E", 0x20, 0x24, 32),
++	EP93XX_GPIO_BANK("F", 0x08, 0x18, 16),
++	EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48),
++	EP93XX_GPIO_BANK("H", 0x40, 0x44, 56),
++};
++
++void __init ep93xx_gpio_init(void)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++)
++		gpiochip_add(&ep93xx_gpio_banks[i].chip);
++}
+diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c
+index 95a1e26..8d761fd 100644
+--- a/arch/arm/mach-integrator/clock.c
++++ b/arch/arm/mach-integrator/clock.c
+@@ -17,7 +17,6 @@
+ #include <linux/clk.h>
+ #include <linux/mutex.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/hardware/icst525.h>
+ 
+ #include "clock.h"
+diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
+index 5278f58..8508a0d 100644
+--- a/arch/arm/mach-integrator/time.c
++++ b/arch/arm/mach-integrator/time.c
+@@ -124,6 +124,9 @@ static int rtc_probe(struct amba_device *dev, void *id)
+ 
+ 	xtime.tv_sec = __raw_readl(rtc_base + RTC_DR);
+ 
++	/* note that 'dev' is merely used for irq disambiguation;
++	 * it is not actually referenced in the irq handler
++	 */
+ 	ret = request_irq(dev->irq[0], arm_rtc_interrupt, IRQF_DISABLED,
+ 			  "rtc-pl030", dev);
+ 	if (ret)
+diff --git a/arch/arm/mach-iop32x/Kconfig b/arch/arm/mach-iop32x/Kconfig
+index dbe07c9..5e8c6f7 100644
+--- a/arch/arm/mach-iop32x/Kconfig
++++ b/arch/arm/mach-iop32x/Kconfig
+@@ -34,14 +34,6 @@ config MACH_N2100
+ 	  Say Y here if you want to run your kernel on the Thecus n2100
+ 	  NAS appliance.
+ 
+-config IOP3XX_ATU
+-        bool "Enable the PCI Controller"
+-        default y
+-        help
+-          Say Y here if you want the IOP to initialize its PCI Controller.
+-          Say N if the IOP is an add in card, the host system owns the PCI
+-          bus in this case.
+-
+ config MACH_EM7210
+ 	bool "Enable support for the Lanner EM7210"
+ 	help
+diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
+index 98cfa1c..4a89823 100644
+--- a/arch/arm/mach-iop32x/iq31244.c
++++ b/arch/arm/mach-iop32x/iq31244.c
+@@ -178,10 +178,9 @@ static struct hw_pci iq31244_pci __initdata = {
+ 
+ static int __init iq31244_pci_init(void)
+ {
+-	if (is_ep80219()) {
+-		if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
+-			pci_common_init(&ep80219_pci);
+-	} else if (machine_is_iq31244()) {
++	if (is_ep80219())
++		pci_common_init(&ep80219_pci);
++	else if (machine_is_iq31244()) {
+ 		if (is_80219()) {
+ 			printk("note: iq31244 board type has been selected\n");
+ 			printk("note: to select ep80219 operation:\n");
+@@ -190,9 +189,7 @@ static int __init iq31244_pci_init(void)
+ 			printk("\t2/ update boot loader to pass"
+ 				" the ep80219 id: %d\n", MACH_TYPE_EP80219);
+ 		}
+-
+-		if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
+-			pci_common_init(&iq31244_pci);
++		pci_common_init(&iq31244_pci);
+ 	}
+ 
+ 	return 0;
+diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
+index 18ad29f..1da3c91 100644
+--- a/arch/arm/mach-iop32x/iq80321.c
++++ b/arch/arm/mach-iop32x/iq80321.c
+@@ -106,7 +106,7 @@ static struct hw_pci iq80321_pci __initdata = {
+ 	.swizzle	= pci_std_swizzle,
+ 	.nr_controllers = 1,
+ 	.setup		= iop3xx_pci_setup,
+-	.preinit	= iop3xx_pci_preinit,
++	.preinit	= iop3xx_pci_preinit_cond,
+ 	.scan		= iop3xx_pci_scan_bus,
+ 	.map_irq	= iq80321_pci_map_irq,
+ };
+diff --git a/arch/arm/mach-iop33x/Kconfig b/arch/arm/mach-iop33x/Kconfig
+index 45598e0..9aa016b 100644
+--- a/arch/arm/mach-iop33x/Kconfig
++++ b/arch/arm/mach-iop33x/Kconfig
+@@ -16,14 +16,6 @@ config MACH_IQ80332
+ 	  Say Y here if you want to run your kernel on the Intel IQ80332
+ 	  evaluation kit for the IOP332 chipset.
+ 
+-config IOP3XX_ATU
+-	bool "Enable the PCI Controller"
+-	default y
+-	help
+-	  Say Y here if you want the IOP to initialize its PCI Controller.
+-	  Say N if the IOP is an add in card, the host system owns the PCI
+-	  bus in this case.
+-
+ endmenu
+ 
+ endif
+diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
+index 433188e..de39fd7 100644
+--- a/arch/arm/mach-iop33x/iq80331.c
++++ b/arch/arm/mach-iop33x/iq80331.c
+@@ -89,7 +89,7 @@ static struct hw_pci iq80331_pci __initdata = {
+ 	.swizzle	= pci_std_swizzle,
+ 	.nr_controllers = 1,
+ 	.setup		= iop3xx_pci_setup,
+-	.preinit	= iop3xx_pci_preinit,
++	.preinit	= iop3xx_pci_preinit_cond,
+ 	.scan		= iop3xx_pci_scan_bus,
+ 	.map_irq	= iq80331_pci_map_irq,
+ };
+diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
+index 416c095..4904fd7 100644
+--- a/arch/arm/mach-iop33x/iq80332.c
++++ b/arch/arm/mach-iop33x/iq80332.c
+@@ -89,7 +89,7 @@ static struct hw_pci iq80332_pci __initdata = {
+ 	.swizzle	= pci_std_swizzle,
+ 	.nr_controllers = 1,
+ 	.setup		= iop3xx_pci_setup,
+-	.preinit	= iop3xx_pci_preinit,
++	.preinit	= iop3xx_pci_preinit_cond,
+ 	.scan		= iop3xx_pci_scan_bus,
+ 	.map_irq	= iq80332_pci_map_irq,
+ };
+diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
+index 730a3af..ade42b7 100644
+--- a/arch/arm/mach-ks8695/Makefile
++++ b/arch/arm/mach-ks8695/Makefile
+@@ -11,5 +11,8 @@ obj-				:=
+ # PCI support is optional
+ obj-$(CONFIG_PCI)		+= pci.o
+ 
++# LEDs
++obj-$(CONFIG_LEDS)		+= leds.o
++
+ # Board-specific support
+ obj-$(CONFIG_MACH_KS8695)	+= board-micrel.o
+diff --git a/arch/arm/mach-ks8695/devices.c b/arch/arm/mach-ks8695/devices.c
+index 386593f..3db2ec6 100644
+--- a/arch/arm/mach-ks8695/devices.c
++++ b/arch/arm/mach-ks8695/devices.c
+@@ -176,6 +176,27 @@ static void __init ks8695_add_device_watchdog(void) {}
+ #endif
+ 
+ 
++/* --------------------------------------------------------------------
++ *  LEDs
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_LEDS)
++short ks8695_leds_cpu = -1;
++short ks8695_leds_timer = -1;
++
++void __init ks8695_init_leds(u8 cpu_led, u8 timer_led)
++{
++	/* Enable GPIO to access the LEDs */
++	gpio_direction_output(cpu_led, 1);
++	gpio_direction_output(timer_led, 1);
++
++	ks8695_leds_cpu   = cpu_led;
++	ks8695_leds_timer = timer_led;
++}
++#else
++void __init ks8695_init_leds(u8 cpu_led, u8 timer_led) {}
++#endif
++
+ /* -------------------------------------------------------------------- */
+ 
+ /*
+diff --git a/arch/arm/mach-ks8695/leds.c b/arch/arm/mach-ks8695/leds.c
+new file mode 100644
+index 0000000..d61762a
+--- /dev/null
++++ b/arch/arm/mach-ks8695/leds.c
+@@ -0,0 +1,94 @@
++/*
++ * LED driver for KS8695-based boards.
++ *
++ * Copyright (C) Andrew Victor
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <asm/mach-types.h>
++#include <asm/leds.h>
++#include <asm/arch/devices.h>
++#include <asm/arch/gpio.h>
++
++
++static inline void ks8695_led_on(unsigned int led)
++{
++	gpio_set_value(led, 0);
++}
++
++static inline void ks8695_led_off(unsigned int led)
++{
++	gpio_set_value(led, 1);
++}
++
++static inline void ks8695_led_toggle(unsigned int led)
++{
++	unsigned long is_off = gpio_get_value(led);
++	if (is_off)
++		ks8695_led_on(led);
++	else
++		ks8695_led_off(led);
++}
++
++
++/*
++ * Handle LED events.
++ */
++static void ks8695_leds_event(led_event_t evt)
++{
++	unsigned long flags;
++
++	local_irq_save(flags);
++
++	switch(evt) {
++	case led_start:		/* System startup */
++		ks8695_led_on(ks8695_leds_cpu);
++		break;
++
++	case led_stop:		/* System stop / suspend */
++		ks8695_led_off(ks8695_leds_cpu);
++		break;
++
++#ifdef CONFIG_LEDS_TIMER
++	case led_timer:		/* Every 50 timer ticks */
++		ks8695_led_toggle(ks8695_leds_timer);
++		break;
++#endif
++
++#ifdef CONFIG_LEDS_CPU
++	case led_idle_start:	/* Entering idle state */
++		ks8695_led_off(ks8695_leds_cpu);
++		break;
++
++	case led_idle_end:	/* Exit idle state */
++		ks8695_led_on(ks8695_leds_cpu);
++		break;
++#endif
++
++	default:
++		break;
++	}
++
++	local_irq_restore(flags);
++}
++
++
++static int __init leds_init(void)
++{
++	if ((ks8695_leds_timer == -1) || (ks8695_leds_cpu == -1))
++		return -ENODEV;
++
++	leds_event = ks8695_leds_event;
++
++	leds_event(led_start);
++	return 0;
++}
++
++__initcall(leds_init);
+diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
+index 6d26661..2ef7d00 100644
+--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
++++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
+@@ -75,10 +75,9 @@ static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
+ {
+ 	u32 mask = CPLD_LATCHED_INTS;
+ 	irq = IRQ_KEV7A400_CPLD;
+-	for (; mask; mask >>= 1, ++irq) {
++	for (; mask; mask >>= 1, ++irq)
+ 		if (mask & 1)
+-			desc[irq].handle (irq, desc);
+-	}
++			desc_handle_irq(irq, desc);
+ }
+ 
+ void __init lh7a40x_init_board_irq (void)
+diff --git a/arch/arm/mach-ns9xxx/Kconfig b/arch/arm/mach-ns9xxx/Kconfig
+index 8584ed1..dd0cd5a 100644
+--- a/arch/arm/mach-ns9xxx/Kconfig
++++ b/arch/arm/mach-ns9xxx/Kconfig
+@@ -2,9 +2,26 @@ if ARCH_NS9XXX
+ 
+ menu "NS9xxx Implementations"
+ 
++config NS9XXX_HAVE_SERIAL8250
++	bool
++
++config PROCESSOR_NS9360
++	bool
++
++config MODULE_CC9P9360
++	bool
++	select PROCESSOR_NS9360
++
++config BOARD_A9M9750DEV
++	select NS9XXX_HAVE_SERIAL8250
++	bool
++
++config BOARD_JSCC9P9360
++	bool
++
+ config MACH_CC9P9360DEV
+ 	bool "ConnectCore 9P 9360 on an A9M9750 Devboard"
+-	select PROCESSOR_NS9360
++	select MODULE_CC9P9360
+ 	select BOARD_A9M9750DEV
+ 	help
+ 	  Say Y here if you are using the Digi ConnectCore 9P 9360
+@@ -12,21 +29,12 @@ config MACH_CC9P9360DEV
+ 
+ config MACH_CC9P9360JS
+ 	bool "ConnectCore 9P 9360 on a JSCC9P9360 Devboard"
+-	select PROCESSOR_NS9360
++	select MODULE_CC9P9360
+ 	select BOARD_JSCC9P9360
+ 	help
+ 	  Say Y here if you are using the Digi ConnectCore 9P 9360
+ 	  on an JSCC9P9360 Development Board.
+ 
+-config PROCESSOR_NS9360
+-	bool
+-
+-config BOARD_A9M9750DEV
+-	bool
+-
+-config BOARD_JSCC9P9360
+-	bool
+-
+ endmenu
+ 
+ endif
+diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile
+index 6fb82b8..41efaf9 100644
+--- a/arch/arm/mach-ns9xxx/Makefile
++++ b/arch/arm/mach-ns9xxx/Makefile
+@@ -1,7 +1,12 @@
+-obj-y := irq.o time.o generic.o gpio.o
++obj-y := clock.o generic.o gpio.o irq.o
+ 
+ obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
+ obj-$(CONFIG_MACH_CC9P9360JS) += mach-cc9p9360js.o
+ 
++obj-$(CONFIG_PROCESSOR_NS9360) += gpio-ns9360.o processor-ns9360.o time-ns9360.o
++
+ obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
+ obj-$(CONFIG_BOARD_JSCC9P9360) += board-jscc9p9360.o
++
++# platform devices
++obj-$(CONFIG_NS9XXX_HAVE_SERIAL8250) += plat-serial8250.o
+diff --git a/arch/arm/mach-ns9xxx/Makefile.boot b/arch/arm/mach-ns9xxx/Makefile.boot
+index 75ed64e..5465491 100644
+--- a/arch/arm/mach-ns9xxx/Makefile.boot
++++ b/arch/arm/mach-ns9xxx/Makefile.boot
+@@ -1,2 +1,2 @@
+-zreladdr-y := 0x108000
++zreladdr-y := 0x8000
+ params_phys-y := 0x100
+diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.c b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
+index 0f65177..a494b71 100644
+--- a/arch/arm/mach-ns9xxx/board-a9m9750dev.c
++++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
+@@ -8,15 +8,14 @@
+  * under the terms of the GNU General Public License version 2 as published by
+  * the Free Software Foundation.
+  */
+-#include <linux/platform_device.h>
+-#include <linux/serial_8250.h>
+ #include <linux/irq.h>
+ 
+ #include <asm/mach/map.h>
+ #include <asm/gpio.h>
+ 
+ #include <asm/arch-ns9xxx/board.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++#include <asm/arch-ns9xxx/regs-sys-ns9360.h>
+ #include <asm/arch-ns9xxx/regs-mem.h>
+ #include <asm/arch-ns9xxx/regs-bbu.h>
+ #include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
+@@ -105,9 +104,9 @@ void __init board_a9m9750dev_init_irq(void)
+ 	int i;
+ 
+ 	if (gpio_request(11, "board a9m9750dev extirq2") == 0)
+-		ns9xxx_gpio_configure(11, 0, 1);
++		ns9360_gpio_configure(11, 0, 1);
+ 	else
+-		printk(KERN_ERR "%s: cannot get gpio 11 for IRQ_EXT2\n",
++		printk(KERN_ERR "%s: cannot get gpio 11 for IRQ_NS9XXX_EXT2\n",
+ 				__func__);
+ 
+ 	for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
+@@ -116,69 +115,16 @@ void __init board_a9m9750dev_init_irq(void)
+ 		set_irq_flags(i, IRQF_VALID);
+ 	}
+ 
+-	/* IRQ_EXT2: level sensitive + active low */
++	/* IRQ_NS9XXX_EXT2: level sensitive + active low */
+ 	eic = __raw_readl(SYS_EIC(2));
+ 	REGSET(eic, SYS_EIC, PLTY, AL);
+ 	REGSET(eic, SYS_EIC, LVEDG, LEVEL);
+ 	__raw_writel(eic, SYS_EIC(2));
+ 
+-	set_irq_chained_handler(IRQ_EXT2,
++	set_irq_chained_handler(IRQ_NS9XXX_EXT2,
+ 			a9m9750dev_fpga_demux_handler);
+ }
+ 
+-static struct plat_serial8250_port board_a9m9750dev_serial8250_port[] = {
+-	{
+-		.iobase         = FPGA_UARTA_BASE,
+-		.membase        = (unsigned char*)FPGA_UARTA_BASE,
+-		.mapbase        = FPGA_UARTA_BASE,
+-		.irq            = IRQ_FPGA_UARTA,
+-		.iotype         = UPIO_MEM,
+-		.uartclk        = 18432000,
+-		.regshift       = 0,
+-		.flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+-	}, {
+-		.iobase         = FPGA_UARTB_BASE,
+-		.membase        = (unsigned char*)FPGA_UARTB_BASE,
+-		.mapbase        = FPGA_UARTB_BASE,
+-		.irq            = IRQ_FPGA_UARTB,
+-		.iotype         = UPIO_MEM,
+-		.uartclk        = 18432000,
+-		.regshift       = 0,
+-		.flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+-	}, {
+-		.iobase         = FPGA_UARTC_BASE,
+-		.membase        = (unsigned char*)FPGA_UARTC_BASE,
+-		.mapbase        = FPGA_UARTC_BASE,
+-		.irq            = IRQ_FPGA_UARTC,
+-		.iotype         = UPIO_MEM,
+-		.uartclk        = 18432000,
+-		.regshift       = 0,
+-		.flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+-	}, {
+-		.iobase         = FPGA_UARTD_BASE,
+-		.membase        = (unsigned char*)FPGA_UARTD_BASE,
+-		.mapbase        = FPGA_UARTD_BASE,
+-		.irq            = IRQ_FPGA_UARTD,
+-		.iotype         = UPIO_MEM,
+-		.uartclk        = 18432000,
+-		.regshift       = 0,
+-		.flags          = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+-	}, {
+-		/* end marker */
+-	},
+-};
+-
+-static struct platform_device board_a9m9750dev_serial_device = {
+-	.name = "serial8250",
+-	.dev = {
+-		.platform_data = board_a9m9750dev_serial8250_port,
+-	},
+-};
+-
+-static struct platform_device *board_a9m9750dev_devices[] __initdata = {
+-	&board_a9m9750dev_serial_device,
+-};
+-
+ void __init board_a9m9750dev_init_machine(void)
+ {
+ 	u32 reg;
+@@ -210,7 +156,4 @@ void __init board_a9m9750dev_init_machine(void)
+ 	__raw_writel(0x2, MEM_SMOED(0));
+ 	__raw_writel(0x6, MEM_SMRD(0));
+ 	__raw_writel(0x6, MEM_SMWD(0));
+-
+-	platform_add_devices(board_a9m9750dev_devices,
+-			ARRAY_SIZE(board_a9m9750dev_devices));
+ }
+diff --git a/arch/arm/mach-ns9xxx/clock.c b/arch/arm/mach-ns9xxx/clock.c
+new file mode 100644
+index 0000000..f863916
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/clock.c
+@@ -0,0 +1,215 @@
++/*
++ * arch/arm/mach-ns9xxx/clock.c
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/list.h>
++#include <linux/clk.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <asm/semaphore.h>
++#include "clock.h"
++
++static LIST_HEAD(clocks);
++static DEFINE_SPINLOCK(clk_lock);
++
++struct clk *clk_get(struct device *dev, const char *id)
++{
++	struct clk *p, *ret = NULL, *retgen = NULL;
++	unsigned long flags;
++	int idno;
++
++	if (dev == NULL || dev->bus != &platform_bus_type)
++		idno = -1;
++	else
++		idno = to_platform_device(dev)->id;
++
++	spin_lock_irqsave(&clk_lock, flags);
++	list_for_each_entry(p, &clocks, node) {
++		if (strcmp(id, p->name) == 0) {
++			if (p->id == idno) {
++				if (!try_module_get(p->owner))
++					continue;
++				ret = p;
++				break;
++			} else if (p->id == -1)
++				/* remember match with id == -1 in case there is
++				 * no clock for idno */
++				retgen = p;
++		}
++	}
++
++	if (!ret && retgen && try_module_get(retgen->owner))
++		ret = retgen;
++
++	if (ret)
++		++ret->refcount;
++
++	spin_unlock_irqrestore(&clk_lock, flags);
++
++	return ret ? ret : ERR_PTR(-ENOENT);
++}
++EXPORT_SYMBOL(clk_get);
++
++void clk_put(struct clk *clk)
++{
++	module_put(clk->owner);
++	--clk->refcount;
++}
++EXPORT_SYMBOL(clk_put);
++
++static int clk_enable_unlocked(struct clk *clk)
++{
++	int ret = 0;
++	if (clk->parent) {
++		ret = clk_enable_unlocked(clk->parent);
++		if (ret)
++			return ret;
++	}
++
++	if (clk->usage++ == 0 && clk->endisable)
++		ret = clk->endisable(clk, 1);
++
++	return ret;
++}
++
++int clk_enable(struct clk *clk)
++{
++	int ret;
++	unsigned long flags;
++
++	spin_lock_irqsave(&clk_lock, flags);
++
++	ret = clk_enable_unlocked(clk);
++
++	spin_unlock_irqrestore(&clk_lock, flags);
++
++	return ret;
++}
++EXPORT_SYMBOL(clk_enable);
++
++static void clk_disable_unlocked(struct clk *clk)
++{
++	if (--clk->usage == 0 && clk->endisable)
++		clk->endisable(clk, 0);
++
++	if (clk->parent)
++		clk_disable_unlocked(clk->parent);
++}
++
++void clk_disable(struct clk *clk)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&clk_lock, flags);
++
++	clk_disable_unlocked(clk);
++
++	spin_unlock_irqrestore(&clk_lock, flags);
++}
++EXPORT_SYMBOL(clk_disable);
++
++unsigned long clk_get_rate(struct clk *clk)
++{
++	if (clk->get_rate)
++		return clk->get_rate(clk);
++
++	if (clk->rate)
++		return clk->rate;
++
++	if (clk->parent)
++		return clk_get_rate(clk->parent);
++
++	return 0;
++}
++EXPORT_SYMBOL(clk_get_rate);
++
++int clk_register(struct clk *clk)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&clk_lock, flags);
++
++	list_add(&clk->node, &clocks);
++
++	if (clk->parent)
++		++clk->parent->refcount;
++
++	spin_unlock_irqrestore(&clk_lock, flags);
++
++	return 0;
++}
++
++int clk_unregister(struct clk *clk)
++{
++	int ret = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&clk_lock, flags);
++
++	if (clk->usage || clk->refcount)
++		ret = -EBUSY;
++	else
++		list_del(&clk->node);
++
++	if (clk->parent)
++		--clk->parent->refcount;
++
++	spin_unlock_irqrestore(&clk_lock, flags);
++
++	return ret;
++}
++
++#if defined CONFIG_DEBUG_FS
++
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
++
++static int clk_debugfs_show(struct seq_file *s, void *null)
++{
++	unsigned long flags;
++	struct clk *p;
++
++	spin_lock_irqsave(&clk_lock, flags);
++
++	list_for_each_entry(p, &clocks, node)
++		seq_printf(s, "%s.%d: usage=%lu refcount=%lu rate=%lu\n",
++				p->name, p->id, p->usage, p->refcount,
++				p->usage ? clk_get_rate(p) : 0);
++
++	spin_unlock_irqrestore(&clk_lock, flags);
++
++	return 0;
++}
++
++static int clk_debugfs_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, clk_debugfs_show, NULL);
++}
++
++static struct file_operations clk_debugfs_operations = {
++	.open = clk_debugfs_open,
++	.read = seq_read,
++	.llseek = seq_lseek,
++	.release = single_release,
++};
++
++static int __init clk_debugfs_init(void)
++{
++	struct dentry *dentry;
++
++	dentry = debugfs_create_file("clk", S_IFREG | S_IRUGO, NULL, NULL,
++			&clk_debugfs_operations);
++	return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
++}
++subsys_initcall(clk_debugfs_init);
++
++#endif /* if defined CONFIG_DEBUG_FS */
+diff --git a/arch/arm/mach-ns9xxx/clock.h b/arch/arm/mach-ns9xxx/clock.h
+new file mode 100644
+index 0000000..b86c30d
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/clock.h
+@@ -0,0 +1,35 @@
++/*
++ * arch/arm/mach-ns9xxx/clock.h
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#ifndef __NS9XXX_CLOCK_H
++#define __NS9XXX_CLOCK_H
++
++#include <linux/list.h>
++
++struct clk {
++	struct module *owner;
++	const char *name;
++	int id;
++
++	struct clk *parent;
++
++	unsigned long rate;
++	int (*endisable)(struct clk *, int enable);
++	unsigned long (*get_rate)(struct clk *);
++
++	struct list_head node;
++	unsigned long refcount;
++	unsigned long usage;
++};
++
++int clk_register(struct clk *clk);
++int clk_unregister(struct clk *clk);
++
++#endif /* ifndef __NS9XXX_CLOCK_H */
+diff --git a/arch/arm/mach-ns9xxx/generic.c b/arch/arm/mach-ns9xxx/generic.c
+index d742c92..1e0f467 100644
+--- a/arch/arm/mach-ns9xxx/generic.c
++++ b/arch/arm/mach-ns9xxx/generic.c
+@@ -1,7 +1,7 @@
+ /*
+  * arch/arm/mach-ns9xxx/generic.c
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -11,34 +11,9 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <asm/memory.h>
+-#include <asm/page.h>
+-#include <asm/mach-types.h>
+-#include <asm/mach/map.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
+-#include <asm/arch-ns9xxx/regs-mem.h>
+-#include <asm/arch-ns9xxx/board.h>
+ 
+ #include "generic.h"
+ 
+-static struct map_desc standard_io_desc[] __initdata = {
+-	{ /* BBus */
+-		.virtual = io_p2v(0x90000000),
+-		.pfn = __phys_to_pfn(0x90000000),
+-		.length = 0x00700000,
+-		.type = MT_DEVICE,
+-	}, { /* AHB */
+-		.virtual = io_p2v(0xa0100000),
+-		.pfn = __phys_to_pfn(0xa0100000),
+-		.length = 0x00900000,
+-		.type = MT_DEVICE,
+-	},
+-};
+-
+-void __init ns9xxx_map_io(void)
+-{
+-	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+-}
+-
+ void __init ns9xxx_init_machine(void)
+ {
+ }
+diff --git a/arch/arm/mach-ns9xxx/generic.h b/arch/arm/mach-ns9xxx/generic.h
+index 687e291..8249319 100644
+--- a/arch/arm/mach-ns9xxx/generic.h
++++ b/arch/arm/mach-ns9xxx/generic.h
+@@ -1,7 +1,7 @@
+ /*
+  * arch/arm/mach-ns9xxx/generic.h
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -13,7 +13,4 @@
+ #include <linux/init.h>
+ 
+ void __init ns9xxx_init_irq(void);
+-void __init ns9xxx_map_io(void);
+ void __init ns9xxx_init_machine(void);
+-
+-extern struct sys_timer ns9xxx_timer;
+diff --git a/arch/arm/mach-ns9xxx/gpio-ns9360.c b/arch/arm/mach-ns9xxx/gpio-ns9360.c
+new file mode 100644
+index 0000000..cabfb87
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/gpio-ns9360.c
+@@ -0,0 +1,118 @@
++/*
++ * arch/arm/mach-ns9xxx/gpio-ns9360.c
++ *
++ * Copyright (C) 2006,2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/bug.h>
++#include <linux/errno.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include <asm/arch-ns9xxx/regs-bbu.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++
++#include "gpio-ns9360.h"
++
++static inline int ns9360_valid_gpio(unsigned gpio)
++{
++	return gpio <= 72;
++}
++
++static inline void __iomem *ns9360_gpio_get_gconfaddr(unsigned gpio)
++{
++	if (gpio < 56)
++		return BBU_GCONFb1(gpio / 8);
++	else
++		/*
++		 * this could be optimised away on
++		 * ns9750 only builds, but it isn't ...
++		 */
++		return BBU_GCONFb2((gpio - 56) / 8);
++}
++
++static inline void __iomem *ns9360_gpio_get_gctrladdr(unsigned gpio)
++{
++	if (gpio < 32)
++		return BBU_GCTRL1;
++	else if (gpio < 64)
++		return BBU_GCTRL2;
++	else
++		/* this could be optimised away on ns9750 only builds */
++		return BBU_GCTRL3;
++}
++
++static inline void __iomem *ns9360_gpio_get_gstataddr(unsigned gpio)
++{
++	if (gpio < 32)
++		return BBU_GSTAT1;
++	else if (gpio < 64)
++		return BBU_GSTAT2;
++	else
++		/* this could be optimised away on ns9750 only builds */
++		return BBU_GSTAT3;
++}
++
++/*
++ * each gpio can serve for 4 different purposes [0..3].  These are called
++ * "functions" and passed in the parameter func.  Functions 0-2 are always some
++ * special things, function 3 is GPIO.  If func == 3 dir specifies input or
++ * output, and with inv you can enable an inverter (independent of func).
++ */
++int __ns9360_gpio_configure(unsigned gpio, int dir, int inv, int func)
++{
++	void __iomem *conf = ns9360_gpio_get_gconfaddr(gpio);
++	u32 confval;
++
++	confval = __raw_readl(conf);
++	REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
++	REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
++	REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
++	__raw_writel(confval, conf);
++
++	return 0;
++}
++
++int ns9360_gpio_configure(unsigned gpio, int inv, int func)
++{
++	if (likely(ns9360_valid_gpio(gpio))) {
++		if (func == 3) {
++			printk(KERN_WARNING "use gpio_direction_input "
++					"or gpio_direction_output\n");
++			return -EINVAL;
++		} else
++			return __ns9360_gpio_configure(gpio, 0, inv, func);
++	} else
++		return -EINVAL;
++}
++EXPORT_SYMBOL(ns9360_gpio_configure);
++
++int ns9360_gpio_get_value(unsigned gpio)
++{
++	void __iomem *stat = ns9360_gpio_get_gstataddr(gpio);
++	int ret;
++
++	ret = 1 & (__raw_readl(stat) >> (gpio & 31));
++
++	return ret;
++}
++
++void ns9360_gpio_set_value(unsigned gpio, int value)
++{
++	void __iomem *ctrl = ns9360_gpio_get_gctrladdr(gpio);
++	u32 ctrlval;
++
++	ctrlval = __raw_readl(ctrl);
++
++	if (value)
++		ctrlval |= 1 << (gpio & 31);
++	else
++		ctrlval &= ~(1 << (gpio & 31));
++
++	__raw_writel(ctrlval, ctrl);
++}
+diff --git a/arch/arm/mach-ns9xxx/gpio-ns9360.h b/arch/arm/mach-ns9xxx/gpio-ns9360.h
+new file mode 100644
+index 0000000..131cd17
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/gpio-ns9360.h
+@@ -0,0 +1,13 @@
++/*
++ * arch/arm/mach-ns9xxx/gpio-ns9360.h
++ *
++ * Copyright (C) 2006,2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++int __ns9360_gpio_configure(unsigned gpio, int dir, int inv, int func);
++int ns9360_gpio_get_value(unsigned gpio);
++void ns9360_gpio_set_value(unsigned gpio, int value);
+diff --git a/arch/arm/mach-ns9xxx/gpio.c b/arch/arm/mach-ns9xxx/gpio.c
+index 5286e9f..b3c963b 100644
+--- a/arch/arm/mach-ns9xxx/gpio.c
++++ b/arch/arm/mach-ns9xxx/gpio.c
+@@ -1,7 +1,7 @@
+ /*
+  * arch/arm/mach-ns9xxx/gpio.c
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -15,12 +15,13 @@
+ 
+ #include <asm/arch-ns9xxx/gpio.h>
+ #include <asm/arch-ns9xxx/processor.h>
+-#include <asm/arch-ns9xxx/regs-bbu.h>
+-#include <asm/io.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
+ #include <asm/bug.h>
+ #include <asm/types.h>
+ #include <asm/bitops.h>
+ 
++#include "gpio-ns9360.h"
++
+ #if defined(CONFIG_PROCESSOR_NS9360)
+ #define GPIO_MAX 72
+ #elif defined(CONFIG_PROCESSOR_NS9750)
+@@ -45,41 +46,10 @@ static inline int ns9xxx_valid_gpio(unsigned gpio)
+ 		return gpio <= 49;
+ 	else
+ #endif
++	{
+ 		BUG();
+-}
+-
+-static inline void __iomem *ns9xxx_gpio_get_gconfaddr(unsigned gpio)
+-{
+-	if (gpio < 56)
+-		return BBU_GCONFb1(gpio / 8);
+-	else
+-		/*
+-		 * this could be optimised away on
+-		 * ns9750 only builds, but it isn't ...
+-		 */
+-		return BBU_GCONFb2((gpio - 56) / 8);
+-}
+-
+-static inline void __iomem *ns9xxx_gpio_get_gctrladdr(unsigned gpio)
+-{
+-	if (gpio < 32)
+-		return BBU_GCTRL1;
+-	else if (gpio < 64)
+-		return BBU_GCTRL2;
+-	else
+-		/* this could be optimised away on ns9750 only builds */
+-		return BBU_GCTRL3;
+-}
+-
+-static inline void __iomem *ns9xxx_gpio_get_gstataddr(unsigned gpio)
+-{
+-	if (gpio < 32)
+-		return BBU_GSTAT1;
+-	else if (gpio < 64)
+-		return BBU_GSTAT2;
+-	else
+-		/* this could be optimised away on ns9750 only builds */
+-		return BBU_GSTAT3;
++		return 0;
++	}
+ }
+ 
+ int gpio_request(unsigned gpio, const char *label)
+@@ -98,49 +68,24 @@ void gpio_free(unsigned gpio)
+ }
+ EXPORT_SYMBOL(gpio_free);
+ 
+-/*
+- * each gpio can serve for 4 different purposes [0..3].  These are called
+- * "functions" and passed in the parameter func.  Functions 0-2 are always some
+- * special things, function 3 is GPIO.  If func == 3 dir specifies input or
+- * output, and with inv you can enable an inverter (independent of func).
+- */
+-static int __ns9xxx_gpio_configure(unsigned gpio, int dir, int inv, int func)
++int gpio_direction_input(unsigned gpio)
+ {
+-	void __iomem *conf = ns9xxx_gpio_get_gconfaddr(gpio);
+-	u32 confval;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&gpio_lock, flags);
+-
+-	confval = __raw_readl(conf);
+-	REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
+-	REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
+-	REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
+-	__raw_writel(confval, conf);
++	if (likely(ns9xxx_valid_gpio(gpio))) {
++		int ret = -EINVAL;
++		unsigned long flags;
+ 
+-	spin_unlock_irqrestore(&gpio_lock, flags);
++		spin_lock_irqsave(&gpio_lock, flags);
++#if defined(CONFIG_PROCESSOR_NS9360)
++		if (processor_is_ns9360())
++			ret = __ns9360_gpio_configure(gpio, 0, 0, 3);
++		else
++#endif
++			BUG();
+ 
+-	return 0;
+-}
++		spin_unlock_irqrestore(&gpio_lock, flags);
+ 
+-int ns9xxx_gpio_configure(unsigned gpio, int inv, int func)
+-{
+-	if (likely(ns9xxx_valid_gpio(gpio))) {
+-		if (func == 3) {
+-			printk(KERN_WARNING "use gpio_direction_input "
+-					"or gpio_direction_output\n");
+-			return -EINVAL;
+-		} else
+-			return __ns9xxx_gpio_configure(gpio, 0, inv, func);
+-	} else
+-		return -EINVAL;
+-}
+-EXPORT_SYMBOL(ns9xxx_gpio_configure);
++		return ret;
+ 
+-int gpio_direction_input(unsigned gpio)
+-{
+-	if (likely(ns9xxx_valid_gpio(gpio))) {
+-		return __ns9xxx_gpio_configure(gpio, 0, 0, 3);
+ 	} else
+ 		return -EINVAL;
+ }
+@@ -149,9 +94,22 @@ EXPORT_SYMBOL(gpio_direction_input);
+ int gpio_direction_output(unsigned gpio, int value)
+ {
+ 	if (likely(ns9xxx_valid_gpio(gpio))) {
++		int ret = -EINVAL;
++		unsigned long flags;
++
+ 		gpio_set_value(gpio, value);
+ 
+-		return __ns9xxx_gpio_configure(gpio, 1, 0, 3);
++		spin_lock_irqsave(&gpio_lock, flags);
++#if defined(CONFIG_PROCESSOR_NS9360)
++		if (processor_is_ns9360())
++			ret = __ns9360_gpio_configure(gpio, 1, 0, 3);
++		else
++#endif
++			BUG();
++
++		spin_unlock_irqrestore(&gpio_lock, flags);
++
++		return ret;
+ 	} else
+ 		return -EINVAL;
+ }
+@@ -159,31 +117,28 @@ EXPORT_SYMBOL(gpio_direction_output);
+ 
+ int gpio_get_value(unsigned gpio)
+ {
+-	void __iomem *stat = ns9xxx_gpio_get_gstataddr(gpio);
+-	int ret;
+-
+-	ret = 1 & (__raw_readl(stat) >> (gpio & 31));
+-
+-	return ret;
++#if defined(CONFIG_PROCESSOR_NS9360)
++	if (processor_is_ns9360())
++		return ns9360_gpio_get_value(gpio);
++	else
++#endif
++	{
++		BUG();
++		return -EINVAL;
++	}
+ }
+ EXPORT_SYMBOL(gpio_get_value);
+ 
+ void gpio_set_value(unsigned gpio, int value)
+ {
+-	void __iomem *ctrl = ns9xxx_gpio_get_gctrladdr(gpio);
+-	u32 ctrlval;
+ 	unsigned long flags;
+-
+ 	spin_lock_irqsave(&gpio_lock, flags);
+-
+-	ctrlval = __raw_readl(ctrl);
+-
+-	if (value)
+-		ctrlval |= 1 << (gpio & 31);
++#if defined(CONFIG_PROCESSOR_NS9360)
++	if (processor_is_ns9360())
++		ns9360_gpio_set_value(gpio, value);
+ 	else
+-		ctrlval &= ~(1 << (gpio & 31));
+-
+-	__raw_writel(ctrlval, ctrl);
++#endif
++		BUG();
+ 
+ 	spin_unlock_irqrestore(&gpio_lock, flags);
+ }
+diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c
+index 00001b8..36e5835 100644
+--- a/arch/arm/mach-ns9xxx/irq.c
++++ b/arch/arm/mach-ns9xxx/irq.c
+@@ -9,21 +9,27 @@
+  * the Free Software Foundation.
+  */
+ #include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
+ #include <asm/io.h>
+ #include <asm/mach/irq.h>
+ #include <asm/mach-types.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
++#include <asm/arch-ns9xxx/regs-sys-common.h>
+ #include <asm/arch-ns9xxx/irqs.h>
+ #include <asm/arch-ns9xxx/board.h>
+ 
+ #include "generic.h"
+ 
++/* simple interrupt prio table: prio(x) < prio(y) <=> x < y */
++#define irq2prio(i) (i)
++#define prio2irq(p) (p)
++
+ static void ns9xxx_mask_irq(unsigned int irq)
+ {
+ 	/* XXX: better use cpp symbols */
+-	u32 ic = __raw_readl(SYS_IC(irq / 4));
+-	ic &= ~(1 << (7 + 8 * (3 - (irq & 3))));
+-	__raw_writel(ic, SYS_IC(irq / 4));
++	int prio = irq2prio(irq);
++	u32 ic = __raw_readl(SYS_IC(prio / 4));
++	ic &= ~(1 << (7 + 8 * (3 - (prio & 3))));
++	__raw_writel(ic, SYS_IC(prio / 4));
+ }
+ 
+ static void ns9xxx_ack_irq(unsigned int irq)
+@@ -40,9 +46,10 @@ static void ns9xxx_maskack_irq(unsigned int irq)
+ static void ns9xxx_unmask_irq(unsigned int irq)
+ {
+ 	/* XXX: better use cpp symbols */
+-	u32 ic = __raw_readl(SYS_IC(irq / 4));
+-	ic |= 1 << (7 + 8 * (3 - (irq & 3)));
+-	__raw_writel(ic, SYS_IC(irq / 4));
++	int prio = irq2prio(irq);
++	u32 ic = __raw_readl(SYS_IC(prio / 4));
++	ic |= 1 << (7 + 8 * (3 - (prio & 3)));
++	__raw_writel(ic, SYS_IC(prio / 4));
+ }
+ 
+ static struct irq_chip ns9xxx_chip = {
+@@ -52,24 +59,61 @@ static struct irq_chip ns9xxx_chip = {
+ 	.unmask		= ns9xxx_unmask_irq,
+ };
+ 
++#if 0
++#define handle_irq handle_level_irq
++#else
++void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
++{
++	unsigned int cpu = smp_processor_id();
++	struct irqaction *action;
++	irqreturn_t action_ret;
++
++	spin_lock(&desc->lock);
++
++	if (unlikely(desc->status & IRQ_INPROGRESS))
++		goto out_unlock;
++
++	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
++	kstat_cpu(cpu).irqs[irq]++;
++
++	action = desc->action;
++	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
++		goto out_unlock;
++
++	desc->status |= IRQ_INPROGRESS;
++	spin_unlock(&desc->lock);
++
++	action_ret = handle_IRQ_event(irq, action);
++
++	spin_lock(&desc->lock);
++	desc->status &= ~IRQ_INPROGRESS;
++	if (!(desc->status & IRQ_DISABLED) && desc->chip->ack)
++		desc->chip->ack(irq);
++
++out_unlock:
++	spin_unlock(&desc->lock);
++}
++#define handle_irq handle_prio_irq
++#endif
++
+ void __init ns9xxx_init_irq(void)
+ {
+ 	int i;
+ 
+ 	/* disable all IRQs */
+ 	for (i = 0; i < 8; ++i)
+-		__raw_writel((4 * i) << 24 | (4 * i + 1) << 16 |
+-				(4 * i + 2) << 8 | (4 * i + 3), SYS_IC(i));
++		__raw_writel(prio2irq(4 * i) << 24 |
++				prio2irq(4 * i + 1) << 16 |
++				prio2irq(4 * i + 2) << 8 |
++				prio2irq(4 * i + 3),
++				SYS_IC(i));
+ 
+-	/* simple interrupt prio table:
+-	 * prio(x) < prio(y) <=> x < y
+-	 */
+ 	for (i = 0; i < 32; ++i)
+-		__raw_writel(i, SYS_IVA(i));
++		__raw_writel(prio2irq(i), SYS_IVA(i));
+ 
+-	for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) {
++	for (i = 0; i <= 31; ++i) {
+ 		set_irq_chip(i, &ns9xxx_chip);
+-		set_irq_handler(i, handle_level_irq);
++		set_irq_handler(i, handle_irq);
+ 		set_irq_flags(i, IRQF_VALID);
+ 	}
+ }
+diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
+index 760c9d0..9623fff 100644
+--- a/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
++++ b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
+@@ -1,7 +1,7 @@
+ /*
+  * arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -11,12 +11,14 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach-types.h>
+ 
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++
+ #include "board-a9m9750dev.h"
+ #include "generic.h"
+ 
+ static void __init mach_cc9p9360dev_map_io(void)
+ {
+-	ns9xxx_map_io();
++	ns9360_map_io();
+ 	board_a9m9750dev_map_io();
+ }
+ 
+@@ -36,6 +38,6 @@ MACHINE_START(CC9P9360DEV, "Digi ConnectCore 9P 9360 on an A9M9750 Devboard")
+ 	.map_io = mach_cc9p9360dev_map_io,
+ 	.init_irq = mach_cc9p9360dev_init_irq,
+ 	.init_machine = mach_cc9p9360dev_init_machine,
+-	.timer = &ns9xxx_timer,
++	.timer = &ns9360_timer,
+ 	.boot_params = 0x100,
+ MACHINE_END
+diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360js.c b/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
+index 85c8b41..fcc815b 100644
+--- a/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
++++ b/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
+@@ -1,7 +1,7 @@
+ /*
+  * arch/arm/mach-ns9xxx/mach-cc9p9360js.c
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -11,6 +11,8 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach-types.h>
+ 
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++
+ #include "board-jscc9p9360.h"
+ #include "generic.h"
+ 
+@@ -21,9 +23,9 @@ static void __init mach_cc9p9360js_init_machine(void)
+ }
+ 
+ MACHINE_START(CC9P9360JS, "Digi ConnectCore 9P 9360 on an JSCC9P9360 Devboard")
+-	.map_io = ns9xxx_map_io,
++	.map_io = ns9360_map_io,
+ 	.init_irq = ns9xxx_init_irq,
+ 	.init_machine = mach_cc9p9360js_init_machine,
+-	.timer = &ns9xxx_timer,
++	.timer = &ns9360_timer,
+ 	.boot_params = 0x100,
+ MACHINE_END
+diff --git a/arch/arm/mach-ns9xxx/plat-serial8250.c b/arch/arm/mach-ns9xxx/plat-serial8250.c
+new file mode 100644
+index 0000000..5aa5d9b
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/plat-serial8250.c
+@@ -0,0 +1,69 @@
++/*
++ * arch/arm/mach-ns9xxx/plat-serial8250.c
++ *
++ * Copyright (C) 2008 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/platform_device.h>
++#include <linux/serial_8250.h>
++
++#include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
++#include <asm/arch-ns9xxx/board.h>
++
++#define DRIVER_NAME "serial8250"
++
++static int __init ns9xxx_plat_serial8250_init(void)
++{
++	struct plat_serial8250_port *pdata;
++	struct platform_device *pdev;
++	int ret = -ENOMEM;
++	int i;
++
++	if (!board_is_a9m9750dev())
++		return -ENODEV;
++
++	pdev = platform_device_alloc(DRIVER_NAME, 0);
++	if (!pdev)
++		goto err;
++
++	pdata = kzalloc(5 * sizeof(*pdata), GFP_KERNEL);
++	if (!pdata)
++		goto err;
++
++	pdev->dev.platform_data = pdata;
++
++	pdata[0].iobase = FPGA_UARTA_BASE;
++	pdata[1].iobase = FPGA_UARTB_BASE;
++	pdata[2].iobase = FPGA_UARTC_BASE;
++	pdata[3].iobase = FPGA_UARTD_BASE;
++
++	for (i = 0; i < 4; ++i) {
++		pdata[i].membase = (void __iomem *)pdata[i].iobase;
++		pdata[i].mapbase = pdata[i].iobase;
++		pdata[i].iotype = UPIO_MEM;
++		pdata[i].uartclk = 18432000;
++		pdata[i].flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
++	}
++
++	pdata[0].irq = IRQ_FPGA_UARTA;
++	pdata[1].irq = IRQ_FPGA_UARTB;
++	pdata[2].irq = IRQ_FPGA_UARTC;
++	pdata[3].irq = IRQ_FPGA_UARTD;
++
++	ret = platform_device_add(pdev);
++	if (ret) {
++err:
++		platform_device_put(pdev);
++
++		printk(KERN_WARNING "Could not add %s (errno=%d)\n",
++				DRIVER_NAME, ret);
++	}
++
++	return 0;
++}
++
++arch_initcall(ns9xxx_plat_serial8250_init);
+diff --git a/arch/arm/mach-ns9xxx/processor-ns9360.c b/arch/arm/mach-ns9xxx/processor-ns9360.c
+new file mode 100644
+index 0000000..2bee0b7
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/processor-ns9360.c
+@@ -0,0 +1,54 @@
++/*
++ * arch/arm/mach-ns9xxx/processor-ns9360.c
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++
++#include <asm/page.h>
++#include <asm/mach/map.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++#include <asm/arch-ns9xxx/regs-sys-ns9360.h>
++
++void ns9360_reset(char mode)
++{
++	u32 reg;
++
++	reg = __raw_readl(SYS_PLL) >> 16;
++	REGSET(reg, SYS_PLL, SWC, YES);
++	__raw_writel(reg, SYS_PLL);
++}
++
++#define CRYSTAL 29491200 /* Hz */
++unsigned long ns9360_systemclock(void)
++{
++	u32 pll = __raw_readl(SYS_PLL);
++	return CRYSTAL * (REGGETIM(pll, SYS_PLL, ND) + 1)
++		>> REGGETIM(pll, SYS_PLL, FS);
++}
++
++static struct map_desc ns9360_io_desc[] __initdata = {
++	{ /* BBus */
++		.virtual = io_p2v(0x90000000),
++		.pfn = __phys_to_pfn(0x90000000),
++		.length = 0x00700000,
++		.type = MT_DEVICE,
++	}, { /* AHB */
++		.virtual = io_p2v(0xa0100000),
++		.pfn = __phys_to_pfn(0xa0100000),
++		.length = 0x00900000,
++		.type = MT_DEVICE,
++	},
++};
++
++void __init ns9360_map_io(void)
++{
++	iotable_init(ns9360_io_desc, ARRAY_SIZE(ns9360_io_desc));
++}
+diff --git a/arch/arm/mach-ns9xxx/time-ns9360.c b/arch/arm/mach-ns9xxx/time-ns9360.c
+new file mode 100644
+index 0000000..4d573c9
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/time-ns9360.c
+@@ -0,0 +1,185 @@
++/*
++ * arch/arm/mach-ns9xxx/time-ns9360.c
++ *
++ * Copyright (C) 2006,2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/jiffies.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/stringify.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++#include <asm/arch-ns9xxx/regs-sys-ns9360.h>
++#include <asm/arch-ns9xxx/irqs.h>
++#include <asm/arch/system.h>
++#include "generic.h"
++
++#define TIMER_CLOCKSOURCE 0
++#define TIMER_CLOCKEVENT 1
++static u32 latch;
++
++static cycle_t ns9360_clocksource_read(void)
++{
++	return __raw_readl(SYS_TR(TIMER_CLOCKSOURCE));
++}
++
++static struct clocksource ns9360_clocksource = {
++	.name	= "ns9360-timer" __stringify(TIMER_CLOCKSOURCE),
++	.rating	= 300,
++	.read	= ns9360_clocksource_read,
++	.mask	= CLOCKSOURCE_MASK(32),
++	.shift	= 20,
++	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++static void ns9360_clockevent_setmode(enum clock_event_mode mode,
++		struct clock_event_device *clk)
++{
++	u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
++
++	switch (mode) {
++	case CLOCK_EVT_MODE_PERIODIC:
++		__raw_writel(latch, SYS_TRC(TIMER_CLOCKEVENT));
++		REGSET(tc, SYS_TCx, REN, EN);
++		REGSET(tc, SYS_TCx, INTS, EN);
++		REGSET(tc, SYS_TCx, TEN, EN);
++		break;
++
++	case CLOCK_EVT_MODE_ONESHOT:
++		REGSET(tc, SYS_TCx, REN, DIS);
++		REGSET(tc, SYS_TCx, INTS, EN);
++
++		/* fall through */
++
++	case CLOCK_EVT_MODE_UNUSED:
++	case CLOCK_EVT_MODE_SHUTDOWN:
++	case CLOCK_EVT_MODE_RESUME:
++	default:
++		REGSET(tc, SYS_TCx, TEN, DIS);
++		break;
++	}
++
++	__raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
++}
++
++static int ns9360_clockevent_setnextevent(unsigned long evt,
++		struct clock_event_device *clk)
++{
++	u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
++
++	if (REGGET(tc, SYS_TCx, TEN)) {
++		REGSET(tc, SYS_TCx, TEN, DIS);
++		__raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
++	}
++
++	REGSET(tc, SYS_TCx, TEN, EN);
++
++	__raw_writel(evt, SYS_TRC(TIMER_CLOCKEVENT));
++
++	__raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
++
++	return 0;
++}
++
++static struct clock_event_device ns9360_clockevent_device = {
++	.name		= "ns9360-timer" __stringify(TIMER_CLOCKEVENT),
++	.shift		= 20,
++	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++	.set_mode	= ns9360_clockevent_setmode,
++	.set_next_event	= ns9360_clockevent_setnextevent,
++};
++
++static irqreturn_t ns9360_clockevent_handler(int irq, void *dev_id)
++{
++	int timerno = irq - IRQ_NS9360_TIMER0;
++	u32 tc;
++
++	struct clock_event_device *evt = &ns9360_clockevent_device;
++
++	/* clear irq */
++	tc = __raw_readl(SYS_TC(timerno));
++	if (REGGET(tc, SYS_TCx, REN) == SYS_TCx_REN_DIS) {
++		REGSET(tc, SYS_TCx, TEN, DIS);
++		__raw_writel(tc, SYS_TC(timerno));
++	}
++	REGSET(tc, SYS_TCx, INTC, SET);
++	__raw_writel(tc, SYS_TC(timerno));
++	REGSET(tc, SYS_TCx, INTC, UNSET);
++	__raw_writel(tc, SYS_TC(timerno));
++
++	evt->event_handler(evt);
++
++	return IRQ_HANDLED;
++}
++
++static struct irqaction ns9360_clockevent_action = {
++	.name		= "ns9360-timer" __stringify(TIMER_CLOCKEVENT),
++	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++	.handler	= ns9360_clockevent_handler,
++};
++
++static void __init ns9360_timer_init(void)
++{
++	int tc;
++
++	tc = __raw_readl(SYS_TC(TIMER_CLOCKSOURCE));
++	if (REGGET(tc, SYS_TCx, TEN)) {
++		REGSET(tc, SYS_TCx, TEN, DIS);
++		__raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
++	}
++
++	__raw_writel(0, SYS_TRC(TIMER_CLOCKSOURCE));
++
++	REGSET(tc, SYS_TCx, TEN, EN);
++	REGSET(tc, SYS_TCx, TDBG, STOP);
++	REGSET(tc, SYS_TCx, TLCS, CPU);
++	REGSET(tc, SYS_TCx, TM, IEE);
++	REGSET(tc, SYS_TCx, INTS, DIS);
++	REGSET(tc, SYS_TCx, UDS, UP);
++	REGSET(tc, SYS_TCx, TSZ, 32);
++	REGSET(tc, SYS_TCx, REN, EN);
++
++	__raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
++
++	ns9360_clocksource.mult = clocksource_hz2mult(ns9360_cpuclock(),
++			ns9360_clocksource.shift);
++
++	clocksource_register(&ns9360_clocksource);
++
++	latch = SH_DIV(ns9360_cpuclock(), HZ, 0);
++
++	tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
++	REGSET(tc, SYS_TCx, TEN, DIS);
++	REGSET(tc, SYS_TCx, TDBG, STOP);
++	REGSET(tc, SYS_TCx, TLCS, CPU);
++	REGSET(tc, SYS_TCx, TM, IEE);
++	REGSET(tc, SYS_TCx, INTS, DIS);
++	REGSET(tc, SYS_TCx, UDS, DOWN);
++	REGSET(tc, SYS_TCx, TSZ, 32);
++	REGSET(tc, SYS_TCx, REN, EN);
++	__raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
++
++	ns9360_clockevent_device.mult = div_sc(ns9360_cpuclock(),
++			NSEC_PER_SEC, ns9360_clockevent_device.shift);
++	ns9360_clockevent_device.max_delta_ns =
++		clockevent_delta2ns(-1, &ns9360_clockevent_device);
++	ns9360_clockevent_device.min_delta_ns =
++		clockevent_delta2ns(1, &ns9360_clockevent_device);
++
++	ns9360_clockevent_device.cpumask = cpumask_of_cpu(0);
++	clockevents_register_device(&ns9360_clockevent_device);
++
++	setup_irq(IRQ_NS9360_TIMER0 + TIMER_CLOCKEVENT,
++			&ns9360_clockevent_action);
++}
++
++struct sys_timer ns9360_timer = {
++	.init = ns9360_timer_init,
++};
+diff --git a/arch/arm/mach-ns9xxx/time.c b/arch/arm/mach-ns9xxx/time.c
+deleted file mode 100644
+index c3dd1f4..0000000
+--- a/arch/arm/mach-ns9xxx/time.c
++++ /dev/null
+@@ -1,184 +0,0 @@
+-/*
+- * arch/arm/mach-ns9xxx/time.c
+- *
+- * Copyright (C) 2006 by Digi International Inc.
+- * All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License version 2 as published by
+- * the Free Software Foundation.
+- */
+-#include <linux/jiffies.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/stringify.h>
+-#include <linux/clocksource.h>
+-#include <linux/clockchips.h>
+-
+-#include <asm/arch-ns9xxx/regs-sys.h>
+-#include <asm/arch-ns9xxx/clock.h>
+-#include <asm/arch-ns9xxx/irqs.h>
+-#include <asm/arch/system.h>
+-#include "generic.h"
+-
+-#define TIMER_CLOCKSOURCE 0
+-#define TIMER_CLOCKEVENT 1
+-static u32 latch;
+-
+-static cycle_t ns9xxx_clocksource_read(void)
+-{
+-	return __raw_readl(SYS_TR(TIMER_CLOCKSOURCE));
+-}
+-
+-static struct clocksource ns9xxx_clocksource = {
+-	.name	= "ns9xxx-timer" __stringify(TIMER_CLOCKSOURCE),
+-	.rating	= 300,
+-	.read	= ns9xxx_clocksource_read,
+-	.mask	= CLOCKSOURCE_MASK(32),
+-	.shift	= 20,
+-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+-};
+-
+-static void ns9xxx_clockevent_setmode(enum clock_event_mode mode,
+-		struct clock_event_device *clk)
+-{
+-	u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+-
+-	switch(mode) {
+-	case CLOCK_EVT_MODE_PERIODIC:
+-		__raw_writel(latch, SYS_TRC(TIMER_CLOCKEVENT));
+-		REGSET(tc, SYS_TCx, REN, EN);
+-		REGSET(tc, SYS_TCx, INTS, EN);
+-		REGSET(tc, SYS_TCx, TEN, EN);
+-		break;
+-
+-	case CLOCK_EVT_MODE_ONESHOT:
+-		REGSET(tc, SYS_TCx, REN, DIS);
+-		REGSET(tc, SYS_TCx, INTS, EN);
+-
+-		/* fall through */
+-
+-	case CLOCK_EVT_MODE_UNUSED:
+-	case CLOCK_EVT_MODE_SHUTDOWN:
+-	case CLOCK_EVT_MODE_RESUME:
+-	default:
+-		REGSET(tc, SYS_TCx, TEN, DIS);
+-		break;
+-	}
+-
+-	__raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+-}
+-
+-static int ns9xxx_clockevent_setnextevent(unsigned long evt,
+-		struct clock_event_device *clk)
+-{
+-	u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+-
+-	if (REGGET(tc, SYS_TCx, TEN)) {
+-		REGSET(tc, SYS_TCx, TEN, DIS);
+-		__raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+-	}
+-
+-	REGSET(tc, SYS_TCx, TEN, EN);
+-
+-	__raw_writel(evt, SYS_TRC(TIMER_CLOCKEVENT));
+-
+-	__raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+-
+-	return 0;
+-}
+-
+-static struct clock_event_device ns9xxx_clockevent_device = {
+-	.name		= "ns9xxx-timer" __stringify(TIMER_CLOCKEVENT),
+-	.shift		= 20,
+-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+-	.set_mode	= ns9xxx_clockevent_setmode,
+-	.set_next_event	= ns9xxx_clockevent_setnextevent,
+-};
+-
+-static irqreturn_t ns9xxx_clockevent_handler(int irq, void *dev_id)
+-{
+-	int timerno = irq - IRQ_TIMER0;
+-	u32 tc;
+-
+-	struct clock_event_device *evt = &ns9xxx_clockevent_device;
+-
+-	/* clear irq */
+-	tc = __raw_readl(SYS_TC(timerno));
+-	if (REGGET(tc, SYS_TCx, REN) == SYS_TCx_REN_DIS) {
+-		REGSET(tc, SYS_TCx, TEN, DIS);
+-		__raw_writel(tc, SYS_TC(timerno));
+-	}
+-	REGSET(tc, SYS_TCx, INTC, SET);
+-	__raw_writel(tc, SYS_TC(timerno));
+-	REGSET(tc, SYS_TCx, INTC, UNSET);
+-	__raw_writel(tc, SYS_TC(timerno));
+-
+-	evt->event_handler(evt);
+-
+-	return IRQ_HANDLED;
+-}
+-
+-static struct irqaction ns9xxx_clockevent_action = {
+-	.name		= "ns9xxx-timer" __stringify(TIMER_CLOCKEVENT),
+-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+-	.handler	= ns9xxx_clockevent_handler,
+-};
+-
+-static void __init ns9xxx_timer_init(void)
+-{
+-	int tc;
+-
+-	tc = __raw_readl(SYS_TC(TIMER_CLOCKSOURCE));
+-	if (REGGET(tc, SYS_TCx, TEN)) {
+-		REGSET(tc, SYS_TCx, TEN, DIS);
+-		__raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
+-	}
+-
+-	__raw_writel(0, SYS_TRC(TIMER_CLOCKSOURCE));
+-
+-	REGSET(tc, SYS_TCx, TEN, EN);
+-	REGSET(tc, SYS_TCx, TDBG, STOP);
+-	REGSET(tc, SYS_TCx, TLCS, CPU);
+-	REGSET(tc, SYS_TCx, TM, IEE);
+-	REGSET(tc, SYS_TCx, INTS, DIS);
+-	REGSET(tc, SYS_TCx, UDS, UP);
+-	REGSET(tc, SYS_TCx, TSZ, 32);
+-	REGSET(tc, SYS_TCx, REN, EN);
+-
+-	__raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
+-
+-	ns9xxx_clocksource.mult = clocksource_hz2mult(ns9xxx_cpuclock(),
+-			ns9xxx_clocksource.shift);
+-
+-	clocksource_register(&ns9xxx_clocksource);
+-
+-	latch = SH_DIV(ns9xxx_cpuclock(), HZ, 0);
+-
+-	tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+-	REGSET(tc, SYS_TCx, TEN, DIS);
+-	REGSET(tc, SYS_TCx, TDBG, STOP);
+-	REGSET(tc, SYS_TCx, TLCS, CPU);
+-	REGSET(tc, SYS_TCx, TM, IEE);
+-	REGSET(tc, SYS_TCx, INTS, DIS);
+-	REGSET(tc, SYS_TCx, UDS, DOWN);
+-	REGSET(tc, SYS_TCx, TSZ, 32);
+-	REGSET(tc, SYS_TCx, REN, EN);
+-	__raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+-
+-	ns9xxx_clockevent_device.mult = div_sc(ns9xxx_cpuclock(),
+-			NSEC_PER_SEC, ns9xxx_clockevent_device.shift);
+-	ns9xxx_clockevent_device.max_delta_ns =
+-		clockevent_delta2ns(-1, &ns9xxx_clockevent_device);
+-	ns9xxx_clockevent_device.min_delta_ns =
+-		clockevent_delta2ns(1, &ns9xxx_clockevent_device);
+-
+-	ns9xxx_clockevent_device.cpumask = cpumask_of_cpu(0);
+-	clockevents_register_device(&ns9xxx_clockevent_device);
+-
+-	setup_irq(IRQ_TIMER0 + TIMER_CLOCKEVENT, &ns9xxx_clockevent_action);
+-}
+-
+-struct sys_timer ns9xxx_timer = {
+-	.init = ns9xxx_timer_init,
+-};
+diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
+index 015a66b..c06f525 100644
+--- a/arch/arm/mach-omap1/Makefile
++++ b/arch/arm/mach-omap1/Makefile
+@@ -5,7 +5,8 @@
+ # Common support
+ obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o
+ 
+-obj-$(CONFIG_OMAP_MPU_TIMER)		+= time.o
++obj-$(CONFIG_OMAP_MPU_TIMER)	+= time.o
++obj-$(CONFIG_OMAP_32K_TIMER)	+= timer32k.o
+ 
+ # Power Management
+ obj-$(CONFIG_PM) += pm.o sleep.o
+diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
+index 5279e35..4f9baba 100644
+--- a/arch/arm/mach-omap1/board-osk.c
++++ b/arch/arm/mach-omap1/board-osk.c
+@@ -32,6 +32,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/i2c.h>
++#include <linux/leds.h>
+ 
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+@@ -183,11 +184,80 @@ static struct platform_device *osk5912_devices[] __initdata = {
+ 	&osk5912_mcbsp1_device,
+ };
+ 
++static struct gpio_led tps_leds[] = {
++	/* NOTE:  D9 and D2 have hardware blink support.
++	 * Also, D9 requires non-battery power.
++	 */
++	{ .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9", },
++	{ .gpio = OSK_TPS_GPIO_LED_D2, .name = "d2", },
++	{ .gpio = OSK_TPS_GPIO_LED_D3, .name = "d3", .active_low = 1,
++			.default_trigger = "heartbeat", },
++};
++
++static struct gpio_led_platform_data tps_leds_data = {
++	.num_leds	= 3,
++	.leds		= tps_leds,
++};
++
++static struct platform_device osk5912_tps_leds = {
++	.name			= "leds-gpio",
++	.id			= 0,
++	.dev.platform_data	= &tps_leds_data,
++};
++
++static int osk_tps_setup(struct i2c_client *client, void *context)
++{
++	/* Set GPIO 1 HIGH to disable VBUS power supply;
++	 * OHCI driver powers it up/down as needed.
++	 */
++	gpio_request(OSK_TPS_GPIO_USB_PWR_EN, "n_vbus_en");
++	gpio_direction_output(OSK_TPS_GPIO_USB_PWR_EN, 1);
++
++	/* Set GPIO 2 high so LED D3 is off by default */
++	tps65010_set_gpio_out_value(GPIO2, HIGH);
++
++	/* Set GPIO 3 low to take ethernet out of reset */
++	gpio_request(OSK_TPS_GPIO_LAN_RESET, "smc_reset");
++	gpio_direction_output(OSK_TPS_GPIO_LAN_RESET, 0);
++
++	/* GPIO4 is VDD_DSP */
++	gpio_request(OSK_TPS_GPIO_DSP_PWR_EN, "dsp_power");
++	gpio_direction_output(OSK_TPS_GPIO_DSP_PWR_EN, 1);
++	/* REVISIT if DSP support isn't configured, power it off ... */
++
++	/* Let LED1 (D9) blink; leds-gpio may override it */
++	tps65010_set_led(LED1, BLINK);
++
++	/* Set LED2 off by default */
++	tps65010_set_led(LED2, OFF);
++
++	/* Enable LOW_PWR handshake */
++	tps65010_set_low_pwr(ON);
++
++	/* Switch VLDO2 to 3.0V for AIC23 */
++	tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
++			| TPS_LDO1_ENABLE);
++
++	/* register these three LEDs */
++	osk5912_tps_leds.dev.parent = &client->dev;
++	platform_device_register(&osk5912_tps_leds);
++
++	return 0;
++}
++
++static struct tps65010_board tps_board = {
++	.base		= OSK_TPS_GPIO_BASE,
++	.outmask	= 0x0f,
++	.setup		= osk_tps_setup,
++};
++
+ static struct i2c_board_info __initdata osk_i2c_board_info[] = {
+ 	{
+ 		I2C_BOARD_INFO("tps65010", 0x48),
+ 		.type		= "tps65010",
+ 		.irq		= OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
++		.platform_data	= &tps_board,
++
+ 	},
+ 	/* TODO when driver support is ready:
+ 	 *  - aic23 audio chip at 0x1a
+@@ -198,7 +268,7 @@ static struct i2c_board_info __initdata osk_i2c_board_info[] = {
+ 
+ static void __init osk_init_smc91x(void)
+ {
+-	if ((omap_request_gpio(0)) < 0) {
++	if ((gpio_request(0, "smc_irq")) < 0) {
+ 		printk("Error requesting gpio 0 for smc91x irq\n");
+ 		return;
+ 	}
+@@ -210,7 +280,7 @@ static void __init osk_init_smc91x(void)
+ static void __init osk_init_cf(void)
+ {
+ 	omap_cfg_reg(M7_1610_GPIO62);
+-	if ((omap_request_gpio(62)) < 0) {
++	if ((gpio_request(62, "cf_irq")) < 0) {
+ 		printk("Error requesting gpio 62 for CF irq\n");
+ 		return;
+ 	}
+@@ -334,7 +404,7 @@ static struct platform_device *mistral_devices[] __initdata = {
+ 
+ static int mistral_get_pendown_state(void)
+ {
+-	return !omap_get_gpio_datain(4);
++	return !gpio_get_value(4);
+ }
+ 
+ static const struct ads7846_platform_data mistral_ts_info = {
+@@ -396,25 +466,31 @@ static void __init osk_mistral_init(void)
+ 	omap_cfg_reg(W14_1610_CCP_DATAP);
+ 
+ 	/* CAM_PWDN */
+-	if (omap_request_gpio(11) == 0) {
++	if (gpio_request(11, "cam_pwdn") == 0) {
+ 		omap_cfg_reg(N20_1610_GPIO11);
+-		omap_set_gpio_direction(11, 0 /* out */);
+-		omap_set_gpio_dataout(11, 0 /* off */);
++		gpio_direction_output(11, 0);
+ 	} else
+ 		pr_debug("OSK+Mistral: CAM_PWDN is awol\n");
+ 
+ 
+ 	/* omap_cfg_reg(P19_1610_GPIO6); */	/* BUSY */
++	gpio_request(6, "ts_busy");
++	gpio_direction_input(6);
++
+ 	omap_cfg_reg(P20_1610_GPIO4);	/* PENIRQ */
++	gpio_request(4, "ts_int");
++	gpio_direction_input(4);
+ 	set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
++
+ 	spi_register_board_info(mistral_boardinfo,
+ 			ARRAY_SIZE(mistral_boardinfo));
+ 
+ 	/* the sideways button (SW1) is for use as a "wakeup" button */
+ 	omap_cfg_reg(N15_1610_MPUIO2);
+-	if (omap_request_gpio(OMAP_MPUIO(2)) == 0) {
++	if (gpio_request(OMAP_MPUIO(2), "wakeup") == 0) {
+ 		int ret = 0;
+-		omap_set_gpio_direction(OMAP_MPUIO(2), 1);
++
++		gpio_direction_input(OMAP_MPUIO(2));
+ 		set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING);
+ #ifdef	CONFIG_PM
+ 		/* share the IRQ in case someone wants to use the
+@@ -425,7 +501,7 @@ static void __init osk_mistral_init(void)
+ 				IRQF_SHARED, "mistral_wakeup",
+ 				&osk_mistral_wake_interrupt);
+ 		if (ret != 0) {
+-			omap_free_gpio(OMAP_MPUIO(2));
++			gpio_free(OMAP_MPUIO(2));
+ 			printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n",
+ 				ret);
+ 		} else
+@@ -438,10 +514,8 @@ static void __init osk_mistral_init(void)
+ 	 * board, like the touchscreen, EEPROM, and wakeup (!) switch.
+ 	 */
+ 	omap_cfg_reg(PWL);
+-	if (omap_request_gpio(2) == 0) {
+-		omap_set_gpio_direction(2, 0 /* out */);
+-		omap_set_gpio_dataout(2, 1 /* on */);
+-	}
++	if (gpio_request(2, "lcd_pwr") == 0)
++		gpio_direction_output(2, 1);
+ 
+ 	platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices));
+ }
+@@ -484,44 +558,6 @@ static void __init osk_map_io(void)
+ 	omap1_map_common_io();
+ }
+ 
+-#ifdef CONFIG_TPS65010
+-static int __init osk_tps_init(void)
+-{
+-	if (!machine_is_omap_osk())
+-		return 0;
+-
+-	/* Let LED1 (D9) blink */
+-	tps65010_set_led(LED1, BLINK);
+-
+-	/* Disable LED 2 (D2) */
+-	tps65010_set_led(LED2, OFF);
+-
+-	/* Set GPIO 1 HIGH to disable VBUS power supply;
+-	 * OHCI driver powers it up/down as needed.
+-	 */
+-	tps65010_set_gpio_out_value(GPIO1, HIGH);
+-
+-	/* Set GPIO 2 low to turn on LED D3 */
+-	tps65010_set_gpio_out_value(GPIO2, HIGH);
+-
+-	/* Set GPIO 3 low to take ethernet out of reset */
+-	tps65010_set_gpio_out_value(GPIO3, LOW);
+-
+-	/* gpio4 for VDD_DSP */
+-	/* FIXME send power to DSP iff it's configured */
+-
+-	/* Enable LOW_PWR */
+-	tps65010_set_low_pwr(ON);
+-
+-	/* Switch VLDO2 to 3.0V for AIC23 */
+-	tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
+-			| TPS_LDO1_ENABLE);
+-
+-	return 0;
+-}
+-fs_initcall(osk_tps_init);
+-#endif
+-
+ MACHINE_START(OMAP_OSK, "TI-OSK")
+ 	/* Maintainer: Dirk Behme <dirk.behme at de.bosch.com> */
+ 	.phys_io	= 0xfff00000,
+diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c
+index 026685e..754383d 100644
+--- a/arch/arm/mach-omap1/leds-osk.c
++++ b/arch/arm/mach-omap1/leds-osk.c
+@@ -1,11 +1,9 @@
+ /*
+  * linux/arch/arm/mach-omap1/leds-osk.c
+  *
+- * LED driver for OSK, and optionally Mistral QVGA, boards
++ * LED driver for OSK with optional Mistral QVGA board
+  */
+ #include <linux/init.h>
+-#include <linux/workqueue.h>
+-#include <linux/i2c/tps65010.h>
+ 
+ #include <asm/hardware.h>
+ #include <asm/leds.h>
+@@ -20,49 +18,11 @@
+ #define LED_STATE_CLAIMED	(1 << 1)
+ static u8 led_state;
+ 
+-#define	GREEN_LED		(1 << 0)	/* TPS65010 LED1 */
+-#define	AMBER_LED		(1 << 1)	/* TPS65010 LED2 */
+-#define	RED_LED			(1 << 2)	/* TPS65010 GPIO2 */
+ #define	TIMER_LED		(1 << 3)	/* Mistral board */
+ #define	IDLE_LED		(1 << 4)	/* Mistral board */
+ static u8 hw_led_state;
+ 
+ 
+-/* TPS65010 leds are changed using i2c -- from a task context.
+- * Using one of these for the "idle" LED would be impractical...
+- */
+-#define	TPS_LEDS	(GREEN_LED | RED_LED | AMBER_LED)
+-
+-static u8 tps_leds_change;
+-
+-static void tps_work(struct work_struct *unused)
+-{
+-	for (;;) {
+-		u8	leds;
+-
+-		local_irq_disable();
+-		leds = tps_leds_change;
+-		tps_leds_change = 0;
+-		local_irq_enable();
+-
+-		if (!leds)
+-			break;
+-
+-		/* careful:  the set_led() value is on/off/blink */
+-		if (leds & GREEN_LED)
+-			tps65010_set_led(LED1, !!(hw_led_state & GREEN_LED));
+-		if (leds & AMBER_LED)
+-			tps65010_set_led(LED2, !!(hw_led_state & AMBER_LED));
+-
+-		/* the gpio led doesn't have that issue */
+-		if (leds & RED_LED)
+-			tps65010_set_gpio_out_value(GPIO2,
+-					!(hw_led_state & RED_LED));
+-	}
+-}
+-
+-static DECLARE_WORK(work, tps_work);
+-
+ #ifdef	CONFIG_OMAP_OSK_MISTRAL
+ 
+ /* For now, all system indicators require the Mistral board, since that
+@@ -112,7 +72,6 @@ void osk_leds_event(led_event_t evt)
+ 	case led_stop:
+ 		led_state &= ~LED_STATE_ENABLED;
+ 		hw_led_state = 0;
+-		/* NOTE:  work may still be pending!! */
+ 		break;
+ 
+ 	case led_claim:
+@@ -145,48 +104,11 @@ void osk_leds_event(led_event_t evt)
+ 
+ #endif	/* CONFIG_OMAP_OSK_MISTRAL */
+ 
+-	/* "green" == tps LED1 (leftmost, normally power-good)
+-	 * works only with DC adapter, not on battery power!
+-	 */
+-	case led_green_on:
+-		if (led_state & LED_STATE_CLAIMED)
+-			hw_led_state |= GREEN_LED;
+-		break;
+-	case led_green_off:
+-		if (led_state & LED_STATE_CLAIMED)
+-			hw_led_state &= ~GREEN_LED;
+-		break;
+-
+-	/* "amber" == tps LED2 (middle) */
+-	case led_amber_on:
+-		if (led_state & LED_STATE_CLAIMED)
+-			hw_led_state |= AMBER_LED;
+-		break;
+-	case led_amber_off:
+-		if (led_state & LED_STATE_CLAIMED)
+-			hw_led_state &= ~AMBER_LED;
+-		break;
+-
+-	/* "red" == LED on tps gpio3 (rightmost) */
+-	case led_red_on:
+-		if (led_state & LED_STATE_CLAIMED)
+-			hw_led_state |= RED_LED;
+-		break;
+-	case led_red_off:
+-		if (led_state & LED_STATE_CLAIMED)
+-			hw_led_state &= ~RED_LED;
+-		break;
+-
+ 	default:
+ 		break;
+ 	}
+ 
+ 	leds ^= hw_led_state;
+-	leds &= TPS_LEDS;
+-	if (leds && (led_state & LED_STATE_CLAIMED)) {
+-		tps_leds_change |= leds;
+-		schedule_work(&work);
+-	}
+ 
+ done:
+ 	local_irq_restore(flags);
+diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
+index 52c70e5..e207bf7 100644
+--- a/arch/arm/mach-omap1/mux.c
++++ b/arch/arm/mach-omap1/mux.c
+@@ -3,9 +3,9 @@
+  *
+  * OMAP1 pin multiplexing configurations
+  *
+- * Copyright (C) 2003 - 2005 Nokia Corporation
++ * Copyright (C) 2003 - 2008 Nokia Corporation
+  *
+- * Written by Tony Lindgren <tony.lindgren at nokia.com>
++ * Written by Tony Lindgren
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -32,8 +32,10 @@
+ 
+ #ifdef CONFIG_OMAP_MUX
+ 
++static struct omap_mux_cfg arch_mux_cfg;
++
+ #ifdef CONFIG_ARCH_OMAP730
+-struct pin_config __initdata_or_module omap730_pins[] = {
++static struct pin_config __initdata_or_module omap730_pins[] = {
+ MUX_CFG_730("E2_730_KBR0",        12,   21,    0,   20,   1, 0)
+ MUX_CFG_730("J7_730_KBR1",        12,   25,    0,   24,   1, 0)
+ MUX_CFG_730("E1_730_KBR2",        12,   29,    0,   28,   1, 0)
+@@ -49,10 +51,14 @@ MUX_CFG_730("AA17_730_USB_DM",     2,   21,    0,   20,   0, 0)
+ MUX_CFG_730("W16_730_USB_PU_EN",   2,   25,    0,   24,   0, 0)
+ MUX_CFG_730("W17_730_USB_VBUSI",   2,   29,    0,   28,   0, 0)
+ };
+-#endif
++#define OMAP730_PINS_SZ		ARRAY_SIZE(omap730_pins)
++#else
++#define omap730_pins		NULL
++#define OMAP730_PINS_SZ		0
++#endif	/* CONFIG_ARCH_OMAP730 */
+ 
+ #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+-struct pin_config __initdata_or_module omap1xxx_pins[] = {
++static struct pin_config __initdata_or_module omap1xxx_pins[] = {
+ /*
+  *	 description		mux  mode   mux	 pull pull  pull  pu_pd	 pu  dbg
+  *				reg  offset mode reg  bit   ena	  reg
+@@ -306,22 +312,136 @@ MUX_CFG("Y12_1610_CCP_CLKP",	 8,   18,    6,   1,  24,   1,    1,     0,  0)
+ MUX_CFG("W13_1610_CCP_CLKM",	 9,    0,    6,   1,  28,   1,    1,     0,  0)
+ MUX_CFG("W14_1610_CCP_DATAP",	 9,   24,    6,   2,   4,   1,    2,     0,  0)
+ MUX_CFG("Y14_1610_CCP_DATAM",	 9,   21,    6,   2,   3,   1,    2,     0,  0)
+-
+ };
++#define OMAP1XXX_PINS_SZ	ARRAY_SIZE(omap1xxx_pins)
++#else
++#define omap1xxx_pins		NULL
++#define OMAP1XXX_PINS_SZ	0
+ #endif	/* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */
+ 
+-int __init omap1_mux_init(void)
++int __init_or_module omap1_cfg_reg(const struct pin_config *cfg)
+ {
+-
+-#ifdef CONFIG_ARCH_OMAP730
+-	omap_mux_register(omap730_pins, ARRAY_SIZE(omap730_pins));
++	static DEFINE_SPINLOCK(mux_spin_lock);
++	unsigned long flags;
++	unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
++		pull_orig = 0, pull = 0;
++	unsigned int mask, warn = 0;
++
++	/* Check the mux register in question */
++	if (cfg->mux_reg) {
++		unsigned	tmp1, tmp2;
++
++		spin_lock_irqsave(&mux_spin_lock, flags);
++		reg_orig = omap_readl(cfg->mux_reg);
++
++		/* The mux registers always seem to be 3 bits long */
++		mask = (0x7 << cfg->mask_offset);
++		tmp1 = reg_orig & mask;
++		reg = reg_orig & ~mask;
++
++		tmp2 = (cfg->mask << cfg->mask_offset);
++		reg |= tmp2;
++
++		if (tmp1 != tmp2)
++			warn = 1;
++
++		omap_writel(reg, cfg->mux_reg);
++		spin_unlock_irqrestore(&mux_spin_lock, flags);
++	}
++
++	/* Check for pull up or pull down selection on 1610 */
++	if (!cpu_is_omap15xx()) {
++		if (cfg->pu_pd_reg && cfg->pull_val) {
++			spin_lock_irqsave(&mux_spin_lock, flags);
++			pu_pd_orig = omap_readl(cfg->pu_pd_reg);
++			mask = 1 << cfg->pull_bit;
++
++			if (cfg->pu_pd_val) {
++				if (!(pu_pd_orig & mask))
++					warn = 1;
++				/* Use pull up */
++				pu_pd = pu_pd_orig | mask;
++			} else {
++				if (pu_pd_orig & mask)
++					warn = 1;
++				/* Use pull down */
++				pu_pd = pu_pd_orig & ~mask;
++			}
++			omap_writel(pu_pd, cfg->pu_pd_reg);
++			spin_unlock_irqrestore(&mux_spin_lock, flags);
++		}
++	}
++
++	/* Check for an associated pull down register */
++	if (cfg->pull_reg) {
++		spin_lock_irqsave(&mux_spin_lock, flags);
++		pull_orig = omap_readl(cfg->pull_reg);
++		mask = 1 << cfg->pull_bit;
++
++		if (cfg->pull_val) {
++			if (pull_orig & mask)
++				warn = 1;
++			/* Low bit = pull enabled */
++			pull = pull_orig & ~mask;
++		} else {
++			if (!(pull_orig & mask))
++				warn = 1;
++			/* High bit = pull disabled */
++			pull = pull_orig | mask;
++		}
++
++		omap_writel(pull, cfg->pull_reg);
++		spin_unlock_irqrestore(&mux_spin_lock, flags);
++	}
++
++	if (warn) {
++#ifdef CONFIG_OMAP_MUX_WARNINGS
++		printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
+ #endif
+-
+-#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+-	omap_mux_register(omap1xxx_pins, ARRAY_SIZE(omap1xxx_pins));
++	}
++
++#ifdef CONFIG_OMAP_MUX_DEBUG
++	if (cfg->debug || warn) {
++		printk("MUX: Setting register %s\n", cfg->name);
++		printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
++		       cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
++
++		if (!cpu_is_omap15xx()) {
++			if (cfg->pu_pd_reg && cfg->pull_val) {
++				printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
++				       cfg->pu_pd_name, cfg->pu_pd_reg,
++				       pu_pd_orig, pu_pd);
++			}
++		}
++
++		if (cfg->pull_reg)
++			printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
++			       cfg->pull_name, cfg->pull_reg, pull_orig, pull);
++	}
+ #endif
+ 
++#ifdef CONFIG_OMAP_MUX_ERRORS
++	return warn ? -ETXTBSY : 0;
++#else
+ 	return 0;
++#endif
++}
++
++int __init omap1_mux_init(void)
++{
++	if (cpu_is_omap730()) {
++		arch_mux_cfg.pins	= omap730_pins;
++		arch_mux_cfg.size	= OMAP730_PINS_SZ;
++		arch_mux_cfg.cfg_reg	= omap1_cfg_reg;
++	}
++
++	if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
++		arch_mux_cfg.pins	= omap1xxx_pins;
++		arch_mux_cfg.size	= OMAP1XXX_PINS_SZ;
++		arch_mux_cfg.cfg_reg	= omap1_cfg_reg;
++	}
++
++	return omap_mux_register(&arch_mux_cfg);
+ }
+ 
+ #endif
+diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
+index a4f8b20..5d2b270 100644
+--- a/arch/arm/mach-omap1/time.c
++++ b/arch/arm/mach-omap1/time.c
+@@ -56,37 +56,6 @@
+ #define OMAP_MPU_TIMER_BASE		OMAP_MPU_TIMER1_BASE
+ #define OMAP_MPU_TIMER_OFFSET		0x100
+ 
+-/* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c,
+- * converted to use kHz by Kevin Hilman */
+-/* convert from cycles(64bits) => nanoseconds (64bits)
+- *  basic equation:
+- *		ns = cycles / (freq / ns_per_sec)
+- *		ns = cycles * (ns_per_sec / freq)
+- *		ns = cycles * (10^9 / (cpu_khz * 10^3))
+- *		ns = cycles * (10^6 / cpu_khz)
+- *
+- *	Then we use scaling math (suggested by george at mvista.com) to get:
+- *		ns = cycles * (10^6 * SC / cpu_khz / SC
+- *		ns = cycles * cyc2ns_scale / SC
+- *
+- *	And since SC is a constant power of two, we can convert the div
+- *  into a shift.
+- *			-johnstul at us.ibm.com "math is hard, lets go shopping!"
+- */
+-static unsigned long cyc2ns_scale;
+-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+-
+-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
+-{
+-	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
+-}
+-
+-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
+-{
+-	return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
+-}
+-
+-
+ typedef struct {
+ 	u32 cntl;			/* CNTL_TIMER, R/W */
+ 	u32 load_tim;			/* LOAD_TIM,   W */
+@@ -194,8 +163,6 @@ static struct irqaction omap_mpu_timer1_irq = {
+ 
+ static __init void omap_init_mpu_timer(unsigned long rate)
+ {
+-	set_cyc2ns_scale(rate / 1000);
+-
+ 	setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
+ 	omap_mpu_timer_start(0, (rate / HZ) - 1, 1);
+ 
+@@ -260,22 +227,6 @@ static void __init omap_init_clocksource(unsigned long rate)
+ 		printk(err, clocksource_mpu.name);
+ }
+ 
+-
+-/*
+- * Scheduler clock - returns current time in nanosec units.
+- */
+-unsigned long long sched_clock(void)
+-{
+-	unsigned long ticks = 0 - omap_mpu_timer_read(1);
+-	unsigned long long ticks64;
+-
+-	ticks64 = omap_mpu_timer2_overflows;
+-	ticks64 <<= 32;
+-	ticks64 |= ticks;
+-
+-	return cycles_2_ns(ticks64);
+-}
+-
+ /*
+  * ---------------------------------------------------------------------------
+  * Timer initialization
+diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
+new file mode 100644
+index 0000000..fbbdb80
+--- /dev/null
++++ b/arch/arm/mach-omap1/timer32k.c
+@@ -0,0 +1,209 @@
++/*
++ * linux/arch/arm/mach-omap1/timer32k.c
++ *
++ * OMAP 32K Timer
++ *
++ * Copyright (C) 2004 - 2005 Nokia Corporation
++ * Partial timer rewrite and additional dynamic tick timer support by
++ * Tony Lindgen <tony at atomide.com> and
++ * Tuukka Tikkanen <tuukka.tikkanen at elektrobit.com>
++ * OMAP Dual-mode timer framework support by Timo Teras
++ *
++ * MPU timer code based on the older MPU timer code for OMAP
++ * Copyright (C) 2000 RidgeRun, Inc.
++ * Author: Greg Lonnon <glonnon at ridgerun.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the  GNU General Public License along
++ * with this program; if not, write  to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++
++#include <asm/system.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/leds.h>
++#include <asm/irq.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/time.h>
++#include <asm/arch/dmtimer.h>
++
++struct sys_timer omap_timer;
++
++/*
++ * ---------------------------------------------------------------------------
++ * 32KHz OS timer
++ *
++ * This currently works only on 16xx, as 1510 does not have the continuous
++ * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
++ * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
++ * on 1510 would be possible, but the timer would not be as accurate as
++ * with the 32KHz synchronized timer.
++ * ---------------------------------------------------------------------------
++ */
++
++#if defined(CONFIG_ARCH_OMAP16XX)
++#define TIMER_32K_SYNCHRONIZED		0xfffbc410
++#else
++#error OMAP 32KHz timer does not currently work on 15XX!
++#endif
++
++/* 16xx specific defines */
++#define OMAP1_32K_TIMER_BASE		0xfffb9000
++#define OMAP1_32K_TIMER_CR		0x08
++#define OMAP1_32K_TIMER_TVR		0x00
++#define OMAP1_32K_TIMER_TCR		0x04
++
++#define OMAP_32K_TICKS_PER_SEC		(32768)
++
++/*
++ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
++ * so with HZ = 128, TVR = 255.
++ */
++#define OMAP_32K_TIMER_TICK_PERIOD	((OMAP_32K_TICKS_PER_SEC / HZ) - 1)
++
++#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)			\
++				(((nr_jiffies) * (clock_rate)) / HZ)
++
++static inline void omap_32k_timer_write(int val, int reg)
++{
++	omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
++}
++
++static inline unsigned long omap_32k_timer_read(int reg)
++{
++	return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
++}
++
++static inline void omap_32k_timer_start(unsigned long load_val)
++{
++	if (!load_val)
++		load_val = 1;
++	omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
++	omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
++}
++
++static inline void omap_32k_timer_stop(void)
++{
++	omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
++}
++
++#define omap_32k_timer_ack_irq()
++
++static int omap_32k_timer_set_next_event(unsigned long delta,
++					 struct clock_event_device *dev)
++{
++	omap_32k_timer_start(delta);
++
++	return 0;
++}
++
++static void omap_32k_timer_set_mode(enum clock_event_mode mode,
++				    struct clock_event_device *evt)
++{
++	omap_32k_timer_stop();
++
++	switch (mode) {
++	case CLOCK_EVT_MODE_PERIODIC:
++		omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
++		break;
++	case CLOCK_EVT_MODE_ONESHOT:
++	case CLOCK_EVT_MODE_UNUSED:
++	case CLOCK_EVT_MODE_SHUTDOWN:
++		break;
++	case CLOCK_EVT_MODE_RESUME:
++		break;
++	}
++}
++
++static struct clock_event_device clockevent_32k_timer = {
++	.name		= "32k-timer",
++	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++	.shift		= 32,
++	.set_next_event	= omap_32k_timer_set_next_event,
++	.set_mode	= omap_32k_timer_set_mode,
++};
++
++/*
++ * The 32KHz synchronized timer is an additional timer on 16xx.
++ * It is always running.
++ */
++static inline unsigned long omap_32k_sync_timer_read(void)
++{
++	return omap_readl(TIMER_32K_SYNCHRONIZED);
++}
++
++static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
++{
++	struct clock_event_device *evt = &clockevent_32k_timer;
++	omap_32k_timer_ack_irq();
++
++	evt->event_handler(evt);
++
++	return IRQ_HANDLED;
++}
++
++static struct irqaction omap_32k_timer_irq = {
++	.name		= "32KHz timer",
++	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++	.handler	= omap_32k_timer_interrupt,
++};
++
++static __init void omap_init_32k_timer(void)
++{
++	setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
++
++	clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC,
++					   NSEC_PER_SEC,
++					   clockevent_32k_timer.shift);
++	clockevent_32k_timer.max_delta_ns =
++		clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer);
++	clockevent_32k_timer.min_delta_ns =
++		clockevent_delta2ns(1, &clockevent_32k_timer);
++
++	clockevent_32k_timer.cpumask = cpumask_of_cpu(0);
++	clockevents_register_device(&clockevent_32k_timer);
++}
++
++/*
++ * ---------------------------------------------------------------------------
++ * Timer initialization
++ * ---------------------------------------------------------------------------
++ */
++static void __init omap_timer_init(void)
++{
++#ifdef CONFIG_OMAP_DM_TIMER
++	omap_dm_timer_init();
++#endif
++	omap_init_32k_timer();
++}
++
++struct sys_timer omap_timer = {
++	.init		= omap_timer_init,
++};
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index b05b738..2feb687 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -3,13 +3,15 @@
+ #
+ 
+ # Common support
+-obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o \
+-	 serial.o gpmc.o
+-
+-obj-$(CONFIG_OMAP_MPU_TIMER)		+= timer-gp.o
++obj-y := irq.o id.o io.o sram-fn.o memory.o control.o prcm.o clock.o mux.o \
++		devices.o serial.o gpmc.o timer-gp.o
+ 
+ # Power Management
+-obj-$(CONFIG_PM) += pm.o pm-domain.o sleep.o
++obj-$(CONFIG_PM) += pm.o sleep.o
++
++# Clock framework
++obj-$(CONFIG_ARCH_OMAP2)		+= clock24xx.o
++obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o
+ 
+ # Specific board support
+ obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
+diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
+index 64235de..1c12d7c 100644
+--- a/arch/arm/mach-omap2/board-2430sdp.c
++++ b/arch/arm/mach-omap2/board-2430sdp.c
+@@ -33,7 +33,6 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/common.h>
+ #include <asm/arch/gpmc.h>
+-#include "prcm-regs.h"
+ 
+ #include <asm/io.h>
+ 
+@@ -125,15 +124,18 @@ static inline void __init sdp2430_init_smc91x(void)
+ 	int eth_cs;
+ 	unsigned long cs_mem_base;
+ 	unsigned int rate;
+-	struct clk *l3ck;
++	struct clk *gpmc_fck;
+ 
+ 	eth_cs = SDP2430_SMC91X_CS;
+ 
+-	l3ck = clk_get(NULL, "core_l3_ck");
+-	if (IS_ERR(l3ck))
+-		rate = 100000000;
+-	else
+-		rate = clk_get_rate(l3ck);
++	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
++	if (IS_ERR(gpmc_fck)) {
++		WARN_ON(1);
++		return;
++	}
++
++	clk_enable(gpmc_fck);
++	rate = clk_get_rate(gpmc_fck);
+ 
+ 	/* Make sure CS1 timings are correct, for 2430 always muxed */
+ 	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
+@@ -160,7 +162,7 @@ static inline void __init sdp2430_init_smc91x(void)
+ 
+ 	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
+ 		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
+-		return;
++		goto out;
+ 	}
+ 
+ 	sdp2430_smc91x_resources[0].start = cs_mem_base + 0x300;
+@@ -171,10 +173,13 @@ static inline void __init sdp2430_init_smc91x(void)
+ 		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+ 			OMAP24XX_ETHR_GPIO_IRQ);
+ 		gpmc_cs_free(eth_cs);
+-		return;
++		goto out;
+ 	}
+ 	omap_set_gpio_direction(OMAP24XX_ETHR_GPIO_IRQ, 1);
+ 
++out:
++	clk_disable(gpmc_fck);
++	clk_put(gpmc_fck);
+ }
+ 
+ static void __init omap_2430sdp_init_irq(void)
+diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
+index 7846551..a1e1e67 100644
+--- a/arch/arm/mach-omap2/board-apollon.c
++++ b/arch/arm/mach-omap2/board-apollon.c
+@@ -26,6 +26,8 @@
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+ #include <linux/leds.h>
++#include <linux/err.h>
++#include <linux/clk.h>
+ 
+ #include <asm/hardware.h>
+ #include <asm/mach-types.h>
+@@ -39,7 +41,7 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/common.h>
+ #include <asm/arch/gpmc.h>
+-#include "prcm-regs.h"
++#include <asm/arch/control.h>
+ 
+ /* LED & Switch macros */
+ #define LED0_GPIO13		13
+@@ -187,17 +189,47 @@ static inline void __init apollon_init_smc91x(void)
+ {
+ 	unsigned long base;
+ 
++	unsigned int rate;
++	struct clk *gpmc_fck;
++	int eth_cs;
++
++	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
++	if (IS_ERR(gpmc_fck)) {
++		WARN_ON(1);
++		return;
++	}
++
++	clk_enable(gpmc_fck);
++	rate = clk_get_rate(gpmc_fck);
++
++	eth_cs = APOLLON_ETH_CS;
++
+ 	/* Make sure CS1 timings are correct */
+-	GPMC_CONFIG1_1 = 0x00011203;
+-	GPMC_CONFIG2_1 = 0x001f1f01;
+-	GPMC_CONFIG3_1 = 0x00080803;
+-	GPMC_CONFIG4_1 = 0x1c091c09;
+-	GPMC_CONFIG5_1 = 0x041f1f1f;
+-	GPMC_CONFIG6_1 = 0x000004c4;
++	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
++
++	if (rate >= 160000000) {
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
++	} else if (rate >= 130000000) {
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
++	} else {/* rate = 100000000 */
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
++	}
+ 
+ 	if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) {
+ 		printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
+-		return;
++		goto out;
+ 	}
+ 	apollon_smc91x_resources[0].start = base + 0x300;
+ 	apollon_smc91x_resources[0].end   = base + 0x30f;
+@@ -208,9 +240,13 @@ static inline void __init apollon_init_smc91x(void)
+ 		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+ 			APOLLON_ETHR_GPIO_IRQ);
+ 		gpmc_cs_free(APOLLON_ETH_CS);
+-		return;
++		goto out;
+ 	}
+ 	omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
++
++out:
++	clk_disable(gpmc_fck);
++	clk_put(gpmc_fck);
+ }
+ 
+ static void __init omap_apollon_init_irq(void)
+@@ -330,6 +366,8 @@ static void __init apollon_usb_init(void)
+ 
+ static void __init omap_apollon_init(void)
+ {
++	u32 v;
++
+ 	apollon_led_init();
+ 	apollon_sw_init();
+ 	apollon_flash_init();
+@@ -339,7 +377,9 @@ static void __init omap_apollon_init(void)
+ 	omap_cfg_reg(W19_24XX_SYS_NIRQ);
+ 
+ 	/* Use Interal loop-back in MMC/SDIO Module Input Clock selection */
+-	CONTROL_DEVCONF |= (1 << 24);
++	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++	v |= (1 << 24);
++	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+ 
+ 	/*
+  	 * Make sure the serial ports are muxed on at this point.
+diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
+index f125f43..d1915f9 100644
+--- a/arch/arm/mach-omap2/board-h4.c
++++ b/arch/arm/mach-omap2/board-h4.c
+@@ -19,6 +19,8 @@
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+ #include <linux/input.h>
++#include <linux/err.h>
++#include <linux/clk.h>
+ 
+ #include <asm/hardware.h>
+ #include <asm/mach-types.h>
+@@ -26,6 +28,7 @@
+ #include <asm/mach/map.h>
+ #include <asm/mach/flash.h>
+ 
++#include <asm/arch/control.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/gpioexpander.h>
+ #include <asm/arch/mux.h>
+@@ -36,10 +39,13 @@
+ #include <asm/arch/keypad.h>
+ #include <asm/arch/menelaus.h>
+ #include <asm/arch/dma.h>
+-#include "prcm-regs.h"
++#include <asm/arch/gpmc.h>
+ 
+ #include <asm/io.h>
+ 
++#define H4_FLASH_CS	0
++#define H4_SMC91X_CS	1
++
+ static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
+ static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
+ 
+@@ -116,8 +122,6 @@ static struct flash_platform_data h4_flash_data = {
+ };
+ 
+ static struct resource h4_flash_resource = {
+-	.start		= H4_CS0_BASE,
+-	.end		= H4_CS0_BASE + SZ_64M - 1,
+ 	.flags		= IORESOURCE_MEM,
+ };
+ 
+@@ -253,21 +257,107 @@ static struct platform_device *h4_devices[] __initdata = {
+ 	&h4_lcd_device,
+ };
+ 
++/* 2420 Sysboot setup (2430 is different) */
++static u32 get_sysboot_value(void)
++{
++	return (omap_ctrl_readl(OMAP24XX_CONTROL_STATUS) &
++		(OMAP2_SYSBOOT_5_MASK | OMAP2_SYSBOOT_4_MASK |
++		 OMAP2_SYSBOOT_3_MASK | OMAP2_SYSBOOT_2_MASK |
++		 OMAP2_SYSBOOT_1_MASK | OMAP2_SYSBOOT_0_MASK));
++}
++
++/* H4-2420's always used muxed mode, H4-2422's always use non-muxed
++ *
++ * Note: OMAP-GIT doesn't correctly do is_cpu_omap2422 and is_cpu_omap2423
++ *  correctly.  The macro needs to look at production_id not just hawkeye.
++ */
++static u32 is_gpmc_muxed(void)
++{
++	u32 mux;
++	mux = get_sysboot_value();
++	if ((mux & 0xF) == 0xd)
++		return 1;	/* NAND config (could be either) */
++	if (mux & 0x2)		/* if mux'ed */
++		return 1;
++	else
++		return 0;
++}
++
+ static inline void __init h4_init_debug(void)
+ {
++	int eth_cs;
++	unsigned long cs_mem_base;
++	unsigned int muxed, rate;
++	struct clk *gpmc_fck;
++
++	eth_cs	= H4_SMC91X_CS;
++
++	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
++	if (IS_ERR(gpmc_fck)) {
++		WARN_ON(1);
++		return;
++	}
++
++	clk_enable(gpmc_fck);
++	rate = clk_get_rate(gpmc_fck);
++	clk_disable(gpmc_fck);
++	clk_put(gpmc_fck);
++
++	if (is_gpmc_muxed())
++		muxed = 0x200;
++	else
++		muxed = 0;
++
+ 	/* Make sure CS1 timings are correct */
+-	GPMC_CONFIG1_1 = 0x00011200;
+-	GPMC_CONFIG2_1 = 0x001f1f01;
+-	GPMC_CONFIG3_1 = 0x00080803;
+-	GPMC_CONFIG4_1 = 0x1c091c09;
+-	GPMC_CONFIG5_1 = 0x041f1f1f;
+-	GPMC_CONFIG6_1 = 0x000004c4;
+-	GPMC_CONFIG7_1 = 0x00000f40 | (0x08000000 >> 24);
++	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1,
++			  0x00011000 | muxed);
++
++	if (rate >= 160000000) {
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
++	} else if (rate >= 130000000) {
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
++	} else {/* rate = 100000000 */
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
++		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
++	}
++
++	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
++		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
++		goto out;
++	}
++
+ 	udelay(100);
+ 
+ 	omap_cfg_reg(M15_24XX_GPIO92);
+ 	if (debug_card_init(cs_mem_base, OMAP24XX_ETHR_GPIO_IRQ) < 0)
+ 		gpmc_cs_free(eth_cs);
++
++out:
++	clk_disable(gpmc_fck);
++	clk_put(gpmc_fck);
++}
++
++static void __init h4_init_flash(void)
++{
++	unsigned long base;
++
++	if (gpmc_cs_request(H4_FLASH_CS, SZ_64M, &base) < 0) {
++		printk("Can't request GPMC CS for flash\n");
++		return;
++	}
++	h4_flash_resource.start	= base;
++	h4_flash_resource.end	= base + SZ_64M - 1;
+ }
+ 
+ static void __init omap_h4_init_irq(void)
+@@ -275,6 +365,7 @@ static void __init omap_h4_init_irq(void)
+ 	omap2_init_common_hw();
+ 	omap_init_irq();
+ 	omap_gpio_init();
++	h4_init_flash();
+ }
+ 
+ static struct omap_uart_config h4_uart_config __initdata = {
+diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
+index e6e85b7..b57ffb5 100644
+--- a/arch/arm/mach-omap2/clock.c
++++ b/arch/arm/mach-omap2/clock.c
+@@ -1,20 +1,19 @@
+ /*
+  *  linux/arch/arm/mach-omap2/clock.c
+  *
+- *  Copyright (C) 2005 Texas Instruments Inc.
+- *  Richard Woodruff <r-woodruff2 at ti.com>
+- *  Created for OMAP2.
+- *
+- *  Cleaned up and modified to use omap shared clock framework by
+- *  Tony Lindgren <tony at atomide.com>
++ *  Copyright (C) 2005-2008 Texas Instruments, Inc.
++ *  Copyright (C) 2004-2008 Nokia Corporation
+  *
+- *  Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation
+- *  Written by Tuukka Tikkanen <tuukka.tikkanen at elektrobit.com>
++ *  Contacts:
++ *  Richard Woodruff <r-woodruff2 at ti.com>
++ *  Paul Walmsley
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
++#undef DEBUG
++
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/device.h>
+@@ -22,176 +21,227 @@
+ #include <linux/errno.h>
+ #include <linux/delay.h>
+ #include <linux/clk.h>
++#include <asm/bitops.h>
+ 
+ #include <asm/io.h>
+ 
+ #include <asm/arch/clock.h>
+ #include <asm/arch/sram.h>
++#include <asm/arch/cpu.h>
+ #include <asm/div64.h>
+ 
+-#include "prcm-regs.h"
+ #include "memory.h"
++#include "sdrc.h"
+ #include "clock.h"
++#include "prm.h"
++#include "prm-regbits-24xx.h"
++#include "cm.h"
++#include "cm-regbits-24xx.h"
++#include "cm-regbits-34xx.h"
+ 
+-#undef DEBUG
+-
+-//#define DOWN_VARIABLE_DPLL 1			/* Experimental */
++#define MAX_CLOCK_ENABLE_WAIT		100000
+ 
+-static struct prcm_config *curr_prcm_set;
+-static u32 curr_perf_level = PRCM_FULL_SPEED;
+-static struct clk *vclk;
+-static struct clk *sclk;
++u8 cpu_mask;
+ 
+ /*-------------------------------------------------------------------------
+  * Omap2 specific clock functions
+  *-------------------------------------------------------------------------*/
+ 
+-/* Recalculate SYST_CLK */
+-static void omap2_sys_clk_recalc(struct clk * clk)
++/**
++ * omap2_init_clksel_parent - set a clksel clk's parent field from the hardware
++ * @clk: OMAP clock struct ptr to use
++ *
++ * Given a pointer to a source-selectable struct clk, read the hardware
++ * register and determine what its parent is currently set to.  Update the
++ * clk->parent field with the appropriate clk ptr.
++ */
++void omap2_init_clksel_parent(struct clk *clk)
+ {
+-	u32 div = PRCM_CLKSRC_CTRL;
+-	div &= (1 << 7) | (1 << 6);	/* Test if ext clk divided by 1 or 2 */
+-	div >>= clk->rate_offset;
+-	clk->rate = (clk->parent->rate / div);
+-	propagate_rate(clk);
++	const struct clksel *clks;
++	const struct clksel_rate *clkr;
++	u32 r, found = 0;
++
++	if (!clk->clksel)
++		return;
++
++	r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
++	r >>= __ffs(clk->clksel_mask);
++
++	for (clks = clk->clksel; clks->parent && !found; clks++) {
++		for (clkr = clks->rates; clkr->div && !found; clkr++) {
++			if ((clkr->flags & cpu_mask) && (clkr->val == r)) {
++				if (clk->parent != clks->parent) {
++					pr_debug("clock: inited %s parent "
++						 "to %s (was %s)\n",
++						 clk->name, clks->parent->name,
++						 ((clk->parent) ?
++						  clk->parent->name : "NULL"));
++					clk->parent = clks->parent;
++				};
++				found = 1;
++			}
++		}
++	}
++
++	if (!found)
++		printk(KERN_ERR "clock: init parent: could not find "
++		       "regval %0x for clock %s\n", r,  clk->name);
++
++	return;
+ }
+ 
+-static u32 omap2_get_dpll_rate(struct clk * tclk)
++/* Returns the DPLL rate */
++u32 omap2_get_dpll_rate(struct clk *clk)
+ {
+ 	long long dpll_clk;
+-	int dpll_mult, dpll_div, amult;
++	u32 dpll_mult, dpll_div, dpll;
++	const struct dpll_data *dd;
++
++	dd = clk->dpll_data;
++	/* REVISIT: What do we return on error? */
++	if (!dd)
++		return 0;
++
++	dpll = __raw_readl(dd->mult_div1_reg);
++	dpll_mult = dpll & dd->mult_mask;
++	dpll_mult >>= __ffs(dd->mult_mask);
++	dpll_div = dpll & dd->div1_mask;
++	dpll_div >>= __ffs(dd->div1_mask);
+ 
+-	dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff;	/* 10 bits */
+-	dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f;	/* 4 bits */
+-	dpll_clk = (long long)tclk->parent->rate * dpll_mult;
++	dpll_clk = (long long)clk->parent->rate * dpll_mult;
+ 	do_div(dpll_clk, dpll_div + 1);
+-	amult = CM_CLKSEL2_PLL & 0x3;
+-	dpll_clk *= amult;
+ 
+ 	return dpll_clk;
+ }
+ 
+-static void omap2_followparent_recalc(struct clk *clk)
+-{
+-	followparent_recalc(clk);
+-}
+-
+-static void omap2_propagate_rate(struct clk * clk)
++/*
++ * Used for clocks that have the same value as the parent clock,
++ * divided by some factor
++ */
++void omap2_fixed_divisor_recalc(struct clk *clk)
+ {
+-	if (!(clk->flags & RATE_FIXED))
+-		clk->rate = clk->parent->rate;
++	WARN_ON(!clk->fixed_div);
+ 
+-	propagate_rate(clk);
+-}
++	clk->rate = clk->parent->rate / clk->fixed_div;
+ 
+-static void omap2_set_osc_ck(int enable)
+-{
+-	if (enable)
+-		PRCM_CLKSRC_CTRL &= ~(0x3 << 3);
+-	else
+-		PRCM_CLKSRC_CTRL |= 0x3 << 3;
++	if (clk->flags & RATE_PROPAGATES)
++		propagate_rate(clk);
+ }
+ 
+-/* Enable an APLL if off */
+-static void omap2_clk_fixed_enable(struct clk *clk)
++/**
++ * omap2_wait_clock_ready - wait for clock to enable
++ * @reg: physical address of clock IDLEST register
++ * @mask: value to mask against to determine if the clock is active
++ * @name: name of the clock (for printk)
++ *
++ * Returns 1 if the clock enabled in time, or 0 if it failed to enable
++ * in roughly MAX_CLOCK_ENABLE_WAIT microseconds.
++ */
++int omap2_wait_clock_ready(void __iomem *reg, u32 mask, const char *name)
+ {
+-	u32 cval, i=0;
++	int i = 0;
++	int ena = 0;
+ 
+-	if (clk->enable_bit == 0xff)			/* Parent will do it */
+-		return;
++	/*
++	 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
++	 * 34xx reverses this, just to keep us on our toes
++	 */
++	if (cpu_mask & (RATE_IN_242X | RATE_IN_243X)) {
++		ena = mask;
++	} else if (cpu_mask & RATE_IN_343X) {
++		ena = 0;
++	}
+ 
+-	cval = CM_CLKEN_PLL;
++	/* Wait for lock */
++	while (((__raw_readl(reg) & mask) != ena) &&
++	       (i++ < MAX_CLOCK_ENABLE_WAIT)) {
++		udelay(1);
++	}
+ 
+-	if ((cval & (0x3 << clk->enable_bit)) == (0x3 << clk->enable_bit))
+-		return;
++	if (i < MAX_CLOCK_ENABLE_WAIT)
++		pr_debug("Clock %s stable after %d loops\n", name, i);
++	else
++		printk(KERN_ERR "Clock %s didn't enable in %d tries\n",
++		       name, MAX_CLOCK_ENABLE_WAIT);
+ 
+-	cval &= ~(0x3 << clk->enable_bit);
+-	cval |= (0x3 << clk->enable_bit);
+-	CM_CLKEN_PLL = cval;
+ 
+-	if (clk == &apll96_ck)
+-		cval = (1 << 8);
+-	else if (clk == &apll54_ck)
+-		cval = (1 << 6);
++	return (i < MAX_CLOCK_ENABLE_WAIT) ? 1 : 0;
++};
+ 
+-	while (!(CM_IDLEST_CKGEN & cval)) {		/* Wait for lock */
+-		++i;
+-		udelay(1);
+-		if (i == 100000) {
+-			printk(KERN_ERR "Clock %s didn't lock\n", clk->name);
+-			break;
+-		}
+-	}
+-}
+ 
++/*
++ * Note: We don't need special code here for INVERT_ENABLE
++ * for the time being since INVERT_ENABLE only applies to clocks enabled by
++ * CM_CLKEN_PLL
++ */
+ static void omap2_clk_wait_ready(struct clk *clk)
+ {
+-	unsigned long reg, other_reg, st_reg;
++	void __iomem *reg, *other_reg, *st_reg;
+ 	u32 bit;
+-	int i;
+-
+-	reg = (unsigned long) clk->enable_reg;
+-	if (reg == (unsigned long) &CM_FCLKEN1_CORE ||
+-	    reg == (unsigned long) &CM_FCLKEN2_CORE)
+-		other_reg = (reg & ~0xf0) | 0x10;
+-	else if (reg == (unsigned long) &CM_ICLKEN1_CORE ||
+-		 reg == (unsigned long) &CM_ICLKEN2_CORE)
+-		other_reg = (reg & ~0xf0) | 0x00;
++
++	/*
++	 * REVISIT: This code is pretty ugly.  It would be nice to generalize
++	 * it and pull it into struct clk itself somehow.
++	 */
++	reg = clk->enable_reg;
++	if ((((u32)reg & 0xff) >= CM_FCLKEN1) &&
++	    (((u32)reg & 0xff) <= OMAP24XX_CM_FCLKEN2))
++		other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x10); /* CM_ICLKEN* */
++	else if ((((u32)reg & 0xff) >= CM_ICLKEN1) &&
++		 (((u32)reg & 0xff) <= OMAP24XX_CM_ICLKEN4))
++		other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x00); /* CM_FCLKEN* */
+ 	else
+ 		return;
+ 
++	/* REVISIT: What are the appropriate exclusions for 34XX? */
+ 	/* No check for DSS or cam clocks */
+-	if ((reg & 0x0f) == 0) {
+-		if (clk->enable_bit <= 1 || clk->enable_bit == 31)
++	if (cpu_is_omap24xx() && ((u32)reg & 0x0f) == 0) { /* CM_{F,I}CLKEN1 */
++		if (clk->enable_bit == OMAP24XX_EN_DSS2_SHIFT ||
++		    clk->enable_bit == OMAP24XX_EN_DSS1_SHIFT ||
++		    clk->enable_bit == OMAP24XX_EN_CAM_SHIFT)
+ 			return;
+ 	}
+ 
++	/* REVISIT: What are the appropriate exclusions for 34XX? */
++	/* OMAP3: ignore DSS-mod clocks */
++	if (cpu_is_omap34xx() &&
++	    (((u32)reg & ~0xff) == (u32)OMAP_CM_REGADDR(OMAP3430_DSS_MOD, 0)))
++		return;
++
+ 	/* Check if both functional and interface clocks
+ 	 * are running. */
+ 	bit = 1 << clk->enable_bit;
+ 	if (!(__raw_readl(other_reg) & bit))
+ 		return;
+-	st_reg = (other_reg & ~0xf0) | 0x20;
+-	i = 0;
+-	while (!(__raw_readl(st_reg) & bit)) {
+-		i++;
+-		if (i == 100000) {
+-			printk(KERN_ERR "Timeout enabling clock %s\n", clk->name);
+-			break;
+-		}
+-	}
+-	if (i)
+-		pr_debug("Clock %s stable after %d loops\n", clk->name, i);
++	st_reg = (void __iomem *)(((u32)other_reg & ~0xf0) | 0x20); /* CM_IDLEST* */
++
++	omap2_wait_clock_ready(st_reg, bit, clk->name);
+ }
+ 
+ /* Enables clock without considering parent dependencies or use count
+  * REVISIT: Maybe change this to use clk->enable like on omap1?
+  */
+-static int _omap2_clk_enable(struct clk * clk)
++int _omap2_clk_enable(struct clk *clk)
+ {
+ 	u32 regval32;
+ 
+-	if (clk->flags & ALWAYS_ENABLED)
++	if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
+ 		return 0;
+ 
+-	if (unlikely(clk == &osc_ck)) {
+-		omap2_set_osc_ck(1);
+-		return 0;
+-	}
++	if (clk->enable)
++		return clk->enable(clk);
+ 
+ 	if (unlikely(clk->enable_reg == 0)) {
+ 		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
+ 		       clk->name);
+-		return 0;
+-	}
+-
+-	if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
+-		omap2_clk_fixed_enable(clk);
+-		return 0;
++		return 0; /* REVISIT: -EINVAL */
+ 	}
+ 
+ 	regval32 = __raw_readl(clk->enable_reg);
+-	regval32 |= (1 << clk->enable_bit);
++	if (clk->flags & INVERT_ENABLE)
++		regval32 &= ~(1 << clk->enable_bit);
++	else
++		regval32 |= (1 << clk->enable_bit);
+ 	__raw_writel(regval32, clk->enable_reg);
+ 	wmb();
+ 
+@@ -200,44 +250,48 @@ static int _omap2_clk_enable(struct clk * clk)
+ 	return 0;
+ }
+ 
+-/* Stop APLL */
+-static void omap2_clk_fixed_disable(struct clk *clk)
+-{
+-	u32 cval;
+-
+-	if(clk->enable_bit == 0xff)		/* let parent off do it */
+-		return;
+-
+-	cval = CM_CLKEN_PLL;
+-	cval &= ~(0x3 << clk->enable_bit);
+-	CM_CLKEN_PLL = cval;
+-}
+-
+ /* Disables clock without considering parent dependencies or use count */
+-static void _omap2_clk_disable(struct clk *clk)
++void _omap2_clk_disable(struct clk *clk)
+ {
+ 	u32 regval32;
+ 
+-	if (unlikely(clk == &osc_ck)) {
+-		omap2_set_osc_ck(0);
++	if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
+ 		return;
+-	}
+ 
+-	if (clk->enable_reg == 0)
++	if (clk->disable) {
++		clk->disable(clk);
+ 		return;
++	}
+ 
+-	if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
+-		omap2_clk_fixed_disable(clk);
++	if (clk->enable_reg == 0) {
++		/*
++		 * 'Independent' here refers to a clock which is not
++		 * controlled by its parent.
++		 */
++		printk(KERN_ERR "clock: clk_disable called on independent "
++		       "clock %s which has no enable_reg\n", clk->name);
+ 		return;
+ 	}
+ 
+ 	regval32 = __raw_readl(clk->enable_reg);
+-	regval32 &= ~(1 << clk->enable_bit);
++	if (clk->flags & INVERT_ENABLE)
++		regval32 |= (1 << clk->enable_bit);
++	else
++		regval32 &= ~(1 << clk->enable_bit);
+ 	__raw_writel(regval32, clk->enable_reg);
+ 	wmb();
+ }
+ 
+-static int omap2_clk_enable(struct clk *clk)
++void omap2_clk_disable(struct clk *clk)
++{
++	if (clk->usecount > 0 && !(--clk->usecount)) {
++		_omap2_clk_disable(clk);
++		if (likely((u32)clk->parent))
++			omap2_clk_disable(clk->parent);
++	}
++}
++
++int omap2_clk_enable(struct clk *clk)
+ {
+ 	int ret = 0;
+ 
+@@ -261,519 +315,314 @@ static int omap2_clk_enable(struct clk *clk)
+ 	return ret;
+ }
+ 
+-static void omap2_clk_disable(struct clk *clk)
+-{
+-	if (clk->usecount > 0 && !(--clk->usecount)) {
+-		_omap2_clk_disable(clk);
+-		if (likely((u32)clk->parent))
+-			omap2_clk_disable(clk->parent);
+-	}
+-}
+-
+-/*
+- * Uses the current prcm set to tell if a rate is valid.
+- * You can go slower, but not faster within a given rate set.
+- */
+-static u32 omap2_dpll_round_rate(unsigned long target_rate)
+-{
+-	u32 high, low;
+-
+-	if ((CM_CLKSEL2_PLL & 0x3) == 1) {	/* DPLL clockout */
+-		high = curr_prcm_set->dpll_speed * 2;
+-		low = curr_prcm_set->dpll_speed;
+-	} else {				/* DPLL clockout x 2 */
+-		high = curr_prcm_set->dpll_speed;
+-		low = curr_prcm_set->dpll_speed / 2;
+-	}
+-
+-#ifdef DOWN_VARIABLE_DPLL
+-	if (target_rate > high)
+-		return high;
+-	else
+-		return target_rate;
+-#else
+-	if (target_rate > low)
+-		return high;
+-	else
+-		return low;
+-#endif
+-
+-}
+-
+ /*
+  * Used for clocks that are part of CLKSEL_xyz governed clocks.
+  * REVISIT: Maybe change to use clk->enable() functions like on omap1?
+  */
+-static void omap2_clksel_recalc(struct clk * clk)
++void omap2_clksel_recalc(struct clk *clk)
+ {
+-	u32 fixed = 0, div = 0;
++	u32 div = 0;
+ 
+-	if (clk == &dpll_ck) {
+-		clk->rate = omap2_get_dpll_rate(clk);
+-		fixed = 1;
+-		div = 0;
+-	}
++	pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
+ 
+-	if (clk == &iva1_mpu_int_ifck) {
+-		div = 2;
+-		fixed = 1;
+-	}
+-
+-	if ((clk == &dss1_fck) && ((CM_CLKSEL1_CORE & (0x1f << 8)) == 0)) {
+-		clk->rate = sys_ck.rate;
++	div = omap2_clksel_get_divisor(clk);
++	if (div == 0)
+ 		return;
+-	}
+ 
+-	if (!fixed) {
+-		div = omap2_clksel_get_divisor(clk);
+-		if (div == 0)
+-			return;
+-	}
++	if (unlikely(clk->rate == clk->parent->rate / div))
++		return;
++	clk->rate = clk->parent->rate / div;
+ 
+-	if (div != 0) {
+-		if (unlikely(clk->rate == clk->parent->rate / div))
+-			return;
+-		clk->rate = clk->parent->rate / div;
+-	}
++	pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
+ 
+ 	if (unlikely(clk->flags & RATE_PROPAGATES))
+ 		propagate_rate(clk);
+ }
+ 
+-/*
+- * Finds best divider value in an array based on the source and target
+- * rates. The divider array must be sorted with smallest divider first.
++/**
++ * omap2_get_clksel_by_parent - return clksel struct for a given clk & parent
++ * @clk: OMAP struct clk ptr to inspect
++ * @src_clk: OMAP struct clk ptr of the parent clk to search for
++ *
++ * Scan the struct clksel array associated with the clock to find
++ * the element associated with the supplied parent clock address.
++ * Returns a pointer to the struct clksel on success or NULL on error.
+  */
+-static inline u32 omap2_divider_from_table(u32 size, u32 *div_array,
+-					   u32 src_rate, u32 tgt_rate)
++const struct clksel *omap2_get_clksel_by_parent(struct clk *clk,
++						struct clk *src_clk)
+ {
+-	int i, test_rate;
++	const struct clksel *clks;
+ 
+-	if (div_array == NULL)
+-		return ~1;
++	if (!clk->clksel)
++		return NULL;
+ 
+-	for (i=0; i < size; i++) {
+-		test_rate = src_rate / *div_array;
+-		if (test_rate <= tgt_rate)
+-			return *div_array;
+-		++div_array;
++	for (clks = clk->clksel; clks->parent; clks++) {
++		if (clks->parent == src_clk)
++			break; /* Found the requested parent */
+ 	}
+ 
+-	return ~0;	/* No acceptable divider */
++	if (!clks->parent) {
++		printk(KERN_ERR "clock: Could not find parent clock %s in "
++		       "clksel array of clock %s\n", src_clk->name,
++		       clk->name);
++		return NULL;
++	}
++
++	return clks;
+ }
+ 
+-/*
+- * Find divisor for the given clock and target rate.
++/**
++ * omap2_clksel_round_rate_div - find divisor for the given clock and rate
++ * @clk: OMAP struct clk to use
++ * @target_rate: desired clock rate
++ * @new_div: ptr to where we should store the divisor
+  *
++ * Finds 'best' divider value in an array based on the source and target
++ * rates.  The divider array must be sorted with smallest divider first.
+  * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
+  * they are only settable as part of virtual_prcm set.
++ *
++ * Returns the rounded clock rate or returns 0xffffffff on error.
+  */
+-static u32 omap2_clksel_round_rate(struct clk *tclk, u32 target_rate,
+-	u32 *new_div)
++u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
++				u32 *new_div)
+ {
+-	u32 gfx_div[] = {2, 3, 4};
+-	u32 sysclkout_div[] = {1, 2, 4, 8, 16};
+-	u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16};
+-	u32 vylnq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18};
+-	u32 best_div = ~0, asize = 0;
+-	u32 *div_array = NULL;
+-
+-	switch (tclk->flags & SRC_RATE_SEL_MASK) {
+-	case CM_GFX_SEL1:
+-		asize = 3;
+-		div_array = gfx_div;
+-		break;
+-	case CM_PLL_SEL1:
+-		return omap2_dpll_round_rate(target_rate);
+-	case CM_SYSCLKOUT_SEL1:
+-		asize = 5;
+-		div_array = sysclkout_div;
+-		break;
+-	case CM_CORE_SEL1:
+-		if(tclk == &dss1_fck){
+-			if(tclk->parent == &core_ck){
+-				asize = 10;
+-				div_array = dss1_div;
+-			} else {
+-				*new_div = 0; /* fixed clk */
+-				return(tclk->parent->rate);
+-			}
+-		} else if((tclk == &vlynq_fck) && cpu_is_omap2420()){
+-			if(tclk->parent == &core_ck){
+-				asize = 10;
+-				div_array = vylnq_div;
+-			} else {
+-				*new_div = 0; /* fixed clk */
+-				return(tclk->parent->rate);
+-			}
+-		}
+-		break;
++	unsigned long test_rate;
++	const struct clksel *clks;
++	const struct clksel_rate *clkr;
++	u32 last_div = 0;
++
++	printk(KERN_INFO "clock: clksel_round_rate_div: %s target_rate %ld\n",
++	       clk->name, target_rate);
++
++	*new_div = 1;
++
++	clks = omap2_get_clksel_by_parent(clk, clk->parent);
++	if (clks == NULL)
++		return ~0;
++
++	for (clkr = clks->rates; clkr->div; clkr++) {
++		if (!(clkr->flags & cpu_mask))
++		    continue;
++
++		/* Sanity check */
++		if (clkr->div <= last_div)
++			printk(KERN_ERR "clock: clksel_rate table not sorted "
++			       "for clock %s", clk->name);
++
++		last_div = clkr->div;
++
++		test_rate = clk->parent->rate / clkr->div;
++
++		if (test_rate <= target_rate)
++			break; /* found it */
+ 	}
+ 
+-	best_div = omap2_divider_from_table(asize, div_array,
+-	 tclk->parent->rate, target_rate);
+-	if (best_div == ~0){
+-		*new_div = 1;
+-		return best_div; /* signal error */
++	if (!clkr->div) {
++		printk(KERN_ERR "clock: Could not find divisor for target "
++		       "rate %ld for clock %s parent %s\n", target_rate,
++		       clk->name, clk->parent->name);
++		return ~0;
+ 	}
+ 
+-	*new_div = best_div;
+-	return (tclk->parent->rate / best_div);
++	*new_div = clkr->div;
++
++	printk(KERN_INFO "clock: new_div = %d, new_rate = %ld\n", *new_div,
++	       (clk->parent->rate / clkr->div));
++
++	return (clk->parent->rate / clkr->div);
+ }
+ 
+-/* Given a clock and a rate apply a clock specific rounding function */
+-static long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
++/**
++ * omap2_clksel_round_rate - find rounded rate for the given clock and rate
++ * @clk: OMAP struct clk to use
++ * @target_rate: desired clock rate
++ *
++ * Compatibility wrapper for OMAP clock framework
++ * Finds best target rate based on the source clock and possible dividers.
++ * rates. The divider array must be sorted with smallest divider first.
++ * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
++ * they are only settable as part of virtual_prcm set.
++ *
++ * Returns the rounded clock rate or returns 0xffffffff on error.
++ */
++long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
+ {
+-	u32 new_div = 0;
+-	int valid_rate;
++	u32 new_div;
+ 
+-	if (clk->flags & RATE_FIXED)
+-		return clk->rate;
++	return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
++}
+ 
+-	if (clk->flags & RATE_CKCTL) {
+-		valid_rate = omap2_clksel_round_rate(clk, rate, &new_div);
+-		return valid_rate;
+-	}
+ 
++/* Given a clock and a rate apply a clock specific rounding function */
++long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
++{
+ 	if (clk->round_rate != 0)
+ 		return clk->round_rate(clk, rate);
+ 
++	if (clk->flags & RATE_FIXED)
++		printk(KERN_ERR "clock: generic omap2_clk_round_rate called "
++		       "on fixed-rate clock %s\n", clk->name);
++
+ 	return clk->rate;
+ }
+ 
+-/*
+- * Check the DLL lock state, and return tue if running in unlock mode.
+- * This is needed to compensate for the shifted DLL value in unlock mode.
++/**
++ * omap2_clksel_to_divisor() - turn clksel field value into integer divider
++ * @clk: OMAP struct clk to use
++ * @field_val: register field value to find
++ *
++ * Given a struct clk of a rate-selectable clksel clock, and a register field
++ * value to search for, find the corresponding clock divisor.  The register
++ * field value should be pre-masked and shifted down so the LSB is at bit 0
++ * before calling.  Returns 0 on error
+  */
+-static u32 omap2_dll_force_needed(void)
++u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
+ {
+-	u32 dll_state = SDRC_DLLA_CTRL;		/* dlla and dllb are a set */
++	const struct clksel *clks;
++	const struct clksel_rate *clkr;
+ 
+-	if ((dll_state & (1 << 2)) == (1 << 2))
+-		return 1;
+-	else
++	clks = omap2_get_clksel_by_parent(clk, clk->parent);
++	if (clks == NULL)
+ 		return 0;
+-}
+ 
+-static u32 omap2_reprogram_sdrc(u32 level, u32 force)
+-{
+-	u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
+-	u32 prev = curr_perf_level, flags;
+-
+-	if ((curr_perf_level == level) && !force)
+-		return prev;
+-
+-	m_type = omap2_memory_get_type();
+-	slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
+-	fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
+-
+-	if (level == PRCM_HALF_SPEED) {
+-		local_irq_save(flags);
+-		PRCM_VOLTSETUP = 0xffff;
+-		omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
+-					  slow_dll_ctrl, m_type);
+-		curr_perf_level = PRCM_HALF_SPEED;
+-		local_irq_restore(flags);
++	for (clkr = clks->rates; clkr->div; clkr++) {
++		if ((clkr->flags & cpu_mask) && (clkr->val == field_val))
++			break;
+ 	}
+-	if (level == PRCM_FULL_SPEED) {
+-		local_irq_save(flags);
+-		PRCM_VOLTSETUP = 0xffff;
+-		omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
+-					  fast_dll_ctrl, m_type);
+-		curr_perf_level = PRCM_FULL_SPEED;
+-		local_irq_restore(flags);
++
++	if (!clkr->div) {
++		printk(KERN_ERR "clock: Could not find fieldval %d for "
++		       "clock %s parent %s\n", field_val, clk->name,
++		       clk->parent->name);
++		return 0;
+ 	}
+ 
+-	return prev;
++	return clkr->div;
+ }
+ 
+-static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
++/**
++ * omap2_divisor_to_clksel() - turn clksel integer divisor into a field value
++ * @clk: OMAP struct clk to use
++ * @div: integer divisor to search for
++ *
++ * Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
++ * find the corresponding register field value.  The return register value is
++ * the value before left-shifting.  Returns 0xffffffff on error
++ */
++u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
+ {
+-	u32 flags, cur_rate, low, mult, div, valid_rate, done_rate;
+-	u32 bypass = 0;
+-	struct prcm_config tmpset;
+-	int ret = -EINVAL;
++	const struct clksel *clks;
++	const struct clksel_rate *clkr;
+ 
+-	local_irq_save(flags);
+-	cur_rate = omap2_get_dpll_rate(&dpll_ck);
+-	mult = CM_CLKSEL2_PLL & 0x3;
+-
+-	if ((rate == (cur_rate / 2)) && (mult == 2)) {
+-		omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
+-	} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
+-		omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
+-	} else if (rate != cur_rate) {
+-		valid_rate = omap2_dpll_round_rate(rate);
+-		if (valid_rate != rate)
+-			goto dpll_exit;
+-
+-		if ((CM_CLKSEL2_PLL & 0x3) == 1)
+-			low = curr_prcm_set->dpll_speed;
+-		else
+-			low = curr_prcm_set->dpll_speed / 2;
+-
+-		tmpset.cm_clksel1_pll = CM_CLKSEL1_PLL;
+-		tmpset.cm_clksel1_pll &= ~(0x3FFF << 8);
+-		div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
+-		tmpset.cm_clksel2_pll = CM_CLKSEL2_PLL;
+-		tmpset.cm_clksel2_pll &= ~0x3;
+-		if (rate > low) {
+-			tmpset.cm_clksel2_pll |= 0x2;
+-			mult = ((rate / 2) / 1000000);
+-			done_rate = PRCM_FULL_SPEED;
+-		} else {
+-			tmpset.cm_clksel2_pll |= 0x1;
+-			mult = (rate / 1000000);
+-			done_rate = PRCM_HALF_SPEED;
+-		}
+-		tmpset.cm_clksel1_pll |= ((div << 8) | (mult << 12));
+-
+-		/* Worst case */
+-		tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS;
+-
+-		if (rate == curr_prcm_set->xtal_speed)	/* If asking for 1-1 */
+-			bypass = 1;
++	/* should never happen */
++	WARN_ON(div == 0);
+ 
+-		omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); /* For init_mem */
+-
+-		/* Force dll lock mode */
+-		omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
+-			       bypass);
++	clks = omap2_get_clksel_by_parent(clk, clk->parent);
++	if (clks == NULL)
++		return 0;
+ 
+-		/* Errata: ret dll entry state */
+-		omap2_init_memory_params(omap2_dll_force_needed());
+-		omap2_reprogram_sdrc(done_rate, 0);
++	for (clkr = clks->rates; clkr->div; clkr++) {
++		if ((clkr->flags & cpu_mask) && (clkr->div == div))
++			break;
+ 	}
+-	omap2_clksel_recalc(&dpll_ck);
+-	ret = 0;
+ 
+-dpll_exit:
+-	local_irq_restore(flags);
+-	return(ret);
+-}
++	if (!clkr->div) {
++		printk(KERN_ERR "clock: Could not find divisor %d for "
++		       "clock %s parent %s\n", div, clk->name,
++		       clk->parent->name);
++		return 0;
++	}
+ 
+-/* Just return the MPU speed */
+-static void omap2_mpu_recalc(struct clk * clk)
+-{
+-	clk->rate = curr_prcm_set->mpu_speed;
++	return clkr->val;
+ }
+ 
+-/*
+- * Look for a rate equal or less than the target rate given a configuration set.
++/**
++ * omap2_get_clksel - find clksel register addr & field mask for a clk
++ * @clk: struct clk to use
++ * @field_mask: ptr to u32 to store the register field mask
+  *
+- * What's not entirely clear is "which" field represents the key field.
+- * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
+- * just uses the ARM rates.
++ * Returns the address of the clksel register upon success or NULL on error.
+  */
+-static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate)
++void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask)
+ {
+-	struct prcm_config * ptr;
+-	long highest_rate;
+-
+-	if (clk != &virt_prcm_set)
+-		return -EINVAL;
+-
+-	highest_rate = -EINVAL;
+-
+-	for (ptr = rate_table; ptr->mpu_speed; ptr++) {
+-		if (ptr->xtal_speed != sys_ck.rate)
+-			continue;
++	if (unlikely((clk->clksel_reg == 0) || (clk->clksel_mask == 0)))
++		return NULL;
+ 
+-		highest_rate = ptr->mpu_speed;
++	*field_mask = clk->clksel_mask;
+ 
+-		/* Can check only after xtal frequency check */
+-		if (ptr->mpu_speed <= rate)
+-			break;
+-	}
+-	return highest_rate;
++	return clk->clksel_reg;
+ }
+ 
+-/*
+- * omap2_convert_field_to_div() - turn field value into integer divider
++/**
++ * omap2_clksel_get_divisor - get current divider applied to parent clock.
++ * @clk: OMAP struct clk to use.
++ *
++ * Returns the integer divisor upon success or 0 on error.
+  */
+-static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val)
++u32 omap2_clksel_get_divisor(struct clk *clk)
+ {
+-	u32 i;
+-	u32 clkout_array[] = {1, 2, 4, 8, 16};
++	u32 field_mask, field_val;
++	void __iomem *div_addr;
+ 
+-	if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
+-		for (i = 0; i < 5; i++) {
+-			if (field_val == i)
+-				return clkout_array[i];
+-		}
+-		return ~0;
+-	} else
+-		return field_val;
++	div_addr = omap2_get_clksel(clk, &field_mask);
++	if (div_addr == 0)
++		return 0;
++
++	field_val = __raw_readl(div_addr) & field_mask;
++	field_val >>= __ffs(field_mask);
++
++	return omap2_clksel_to_divisor(clk, field_val);
+ }
+ 
+-/*
+- * Returns the CLKSEL divider register value
+- * REVISIT: This should be cleaned up to work nicely with void __iomem *
+- */
+-static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
+-			    struct clk *clk)
++int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
+ {
+-	int ret = ~0;
+-	u32 reg_val, div_off;
+-	u32 div_addr = 0;
+-	u32 mask = ~0;
+-
+-	div_off = clk->rate_offset;
+-
+-	switch ((*div_sel & SRC_RATE_SEL_MASK)) {
+-	case CM_MPU_SEL1:
+-		div_addr = (u32)&CM_CLKSEL_MPU;
+-		mask = 0x1f;
+-		break;
+-	case CM_DSP_SEL1:
+-		div_addr = (u32)&CM_CLKSEL_DSP;
+-		if (cpu_is_omap2420()) {
+-			if ((div_off == 0) || (div_off == 8))
+-				mask = 0x1f;
+-			else if (div_off == 5)
+-				mask = 0x3;
+-		} else if (cpu_is_omap2430()) {
+-			if (div_off == 0)
+-				mask = 0x1f;
+-			else if (div_off == 5)
+-				mask = 0x3;
+-		}
+-		break;
+-	case CM_GFX_SEL1:
+-		div_addr = (u32)&CM_CLKSEL_GFX;
+-		if (div_off == 0)
+-			mask = 0x7;
+-		break;
+-	case CM_MODEM_SEL1:
+-		div_addr = (u32)&CM_CLKSEL_MDM;
+-		if (div_off == 0)
+-			mask = 0xf;
+-		break;
+-	case CM_SYSCLKOUT_SEL1:
+-		div_addr = (u32)&PRCM_CLKOUT_CTRL;
+-		if ((div_off == 3) || (div_off == 11))
+-			mask= 0x3;
+-		break;
+-	case CM_CORE_SEL1:
+-		div_addr = (u32)&CM_CLKSEL1_CORE;
+-		switch (div_off) {
+-		case 0:					/* l3 */
+-		case 8:					/* dss1 */
+-		case 15:				/* vylnc-2420 */
+-		case 20:				/* ssi */
+-			mask = 0x1f; break;
+-		case 5:					/* l4 */
+-			mask = 0x3; break;
+-		case 13:				/* dss2 */
+-			mask = 0x1; break;
+-		case 25:				/* usb */
+-			mask = 0x7; break;
+-		}
+-	}
++	u32 field_mask, field_val, reg_val, validrate, new_div = 0;
++	void __iomem *div_addr;
+ 
+-	*field_mask = mask;
++	validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
++	if (validrate != rate)
++		return -EINVAL;
+ 
+-	if (unlikely(mask == ~0))
+-		div_addr = 0;
++	div_addr = omap2_get_clksel(clk, &field_mask);
++	if (div_addr == 0)
++		return -EINVAL;
+ 
+-	*div_sel = div_addr;
++	field_val = omap2_divisor_to_clksel(clk, new_div);
++	if (field_val == ~0)
++		return -EINVAL;
+ 
+-	if (unlikely(div_addr == 0))
+-		return ret;
++	reg_val = __raw_readl(div_addr);
++	reg_val &= ~field_mask;
++	reg_val |= (field_val << __ffs(field_mask));
++	__raw_writel(reg_val, div_addr);
++	wmb();
+ 
+-	/* Isolate field */
+-	reg_val = __raw_readl((void __iomem *)div_addr) & (mask << div_off);
++	clk->rate = clk->parent->rate / new_div;
+ 
+-	/* Normalize back to divider value */
+-	reg_val >>= div_off;
++	if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
++		__raw_writel(OMAP24XX_VALID_CONFIG, OMAP24XX_PRCM_CLKCFG_CTRL);
++		wmb();
++	}
+ 
+-	return reg_val;
++	return 0;
+ }
+ 
+-/*
+- * Return divider to be applied to parent clock.
+- * Return 0 on error.
+- */
+-static u32 omap2_clksel_get_divisor(struct clk *clk)
+-{
+-	int ret = 0;
+-	u32 div, div_sel, div_off, field_mask, field_val;
+-
+-	/* isolate control register */
+-	div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+-
+-	div_off = clk->rate_offset;
+-	field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
+-	if (div_sel == 0)
+-		return ret;
+-
+-	div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+-	div = omap2_clksel_to_divisor(div_sel, field_val);
+-
+-	return div;
+-}
+ 
+ /* Set the clock rate for a clock source */
+-static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+-
++int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+ {
+ 	int ret = -EINVAL;
+-	void __iomem * reg;
+-	u32 div_sel, div_off, field_mask, field_val, reg_val, validrate;
+-	u32 new_div = 0;
+-
+-	if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) {
+-		if (clk == &dpll_ck)
+-			return omap2_reprogram_dpll(clk, rate);
+-
+-		/* Isolate control register */
+-		div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+-		div_off = clk->rate_offset;
+-
+-		validrate = omap2_clksel_round_rate(clk, rate, &new_div);
+-		if (validrate != rate)
+-			return(ret);
+ 
+-		field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
+-		if (div_sel == 0)
+-			return ret;
+-
+-		if (clk->flags & CM_SYSCLKOUT_SEL1) {
+-			switch (new_div) {
+-			case 16:
+-				field_val = 4;
+-				break;
+-			case 8:
+-				field_val = 3;
+-				break;
+-			case 4:
+-				field_val = 2;
+-				break;
+-			case 2:
+-				field_val = 1;
+-				break;
+-			case 1:
+-				field_val = 0;
+-				break;
+-			}
+-		} else
+-			field_val = new_div;
++	pr_debug("clock: set_rate for clock %s to rate %ld\n", clk->name, rate);
+ 
+-		reg = (void __iomem *)div_sel;
+-
+-		reg_val = __raw_readl(reg);
+-		reg_val &= ~(field_mask << div_off);
+-		reg_val |= (field_val << div_off);
+-		__raw_writel(reg_val, reg);
+-		wmb();
+-		clk->rate = clk->parent->rate / field_val;
++	/* CONFIG_PARTICIPANT clocks are changed only in sets via the
++	   rate table mechanism, driven by mpu_speed  */
++	if (clk->flags & CONFIG_PARTICIPANT)
++		return -EINVAL;
+ 
+-		if (clk->flags & DELAYED_APP) {
+-			__raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
+-			wmb();
+-		}
+-		ret = 0;
+-	} else if (clk->set_rate != 0)
++	/* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
++	if (clk->set_rate != 0)
+ 		ret = clk->set_rate(clk, rate);
+ 
+ 	if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
+@@ -782,242 +631,92 @@ static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+ 	return ret;
+ }
+ 
+-/* Converts encoded control register address into a full address */
+-static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset,
+-			       struct clk *src_clk, u32 *field_mask)
+-{
+-	u32 val = ~0, src_reg_addr = 0, mask = 0;
+-
+-	/* Find target control register.*/
+-	switch ((*type_to_addr & SRC_RATE_SEL_MASK)) {
+-	case CM_CORE_SEL1:
+-		src_reg_addr = (u32)&CM_CLKSEL1_CORE;
+-		if (reg_offset == 13) {			/* DSS2_fclk */
+-			mask = 0x1;
+-			if (src_clk == &sys_ck)
+-				val = 0;
+-			if (src_clk == &func_48m_ck)
+-				val = 1;
+-		} else if (reg_offset == 8) {		/* DSS1_fclk */
+-			mask = 0x1f;
+-			if (src_clk == &sys_ck)
+-				val = 0;
+-			else if (src_clk == &core_ck)	/* divided clock */
+-				val = 0x10;		/* rate needs fixing */
+-		} else if ((reg_offset == 15) && cpu_is_omap2420()){ /*vlnyq*/
+-			mask = 0x1F;
+-			if(src_clk == &func_96m_ck)
+-				val = 0;
+-			else if (src_clk == &core_ck)
+-				val = 0x10;
+-		}
+-		break;
+-	case CM_CORE_SEL2:
+-		src_reg_addr = (u32)&CM_CLKSEL2_CORE;
+-		mask = 0x3;
+-		if (src_clk == &func_32k_ck)
+-			val = 0x0;
+-		if (src_clk == &sys_ck)
+-			val = 0x1;
+-		if (src_clk == &alt_ck)
+-			val = 0x2;
+-		break;
+-	case CM_WKUP_SEL1:
+-		src_reg_addr = (u32)&CM_CLKSEL_WKUP;
+-		mask = 0x3;
+-		if (src_clk == &func_32k_ck)
+-			val = 0x0;
+-		if (src_clk == &sys_ck)
+-			val = 0x1;
+-		if (src_clk == &alt_ck)
+-			val = 0x2;
+-		break;
+-	case CM_PLL_SEL1:
+-		src_reg_addr = (u32)&CM_CLKSEL1_PLL;
+-		mask = 0x1;
+-		if (reg_offset == 0x3) {
+-			if (src_clk == &apll96_ck)
+-				val = 0;
+-			if (src_clk == &alt_ck)
+-				val = 1;
+-		}
+-		else if (reg_offset == 0x5) {
+-			if (src_clk == &apll54_ck)
+-				val = 0;
+-			if (src_clk == &alt_ck)
+-				val = 1;
+-		}
+-		break;
+-	case CM_PLL_SEL2:
+-		src_reg_addr = (u32)&CM_CLKSEL2_PLL;
+-		mask = 0x3;
+-		if (src_clk == &func_32k_ck)
+-			val = 0x0;
+-		if (src_clk == &dpll_ck)
+-			val = 0x2;
+-		break;
+-	case CM_SYSCLKOUT_SEL1:
+-		src_reg_addr = (u32)&PRCM_CLKOUT_CTRL;
+-		mask = 0x3;
+-		if (src_clk == &dpll_ck)
+-			val = 0;
+-		if (src_clk == &sys_ck)
+-			val = 1;
+-		if (src_clk == &func_96m_ck)
+-			val = 2;
+-		if (src_clk == &func_54m_ck)
+-			val = 3;
+-		break;
+-	}
+-
+-	if (val == ~0)			/* Catch errors in offset */
+-		*type_to_addr = 0;
+-	else
+-		*type_to_addr = src_reg_addr;
+-	*field_mask = mask;
+-
+-	return val;
+-}
+-
+-static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
++/*
++ * Converts encoded control register address into a full address
++ * On error, *src_addr will be returned as 0.
++ */
++static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
++				      struct clk *src_clk, u32 *field_mask,
++				      struct clk *clk, u32 *parent_div)
+ {
+-	void __iomem * reg;
+-	u32 src_sel, src_off, field_val, field_mask, reg_val, rate;
+-	int ret = -EINVAL;
+-
+-	if (unlikely(clk->flags & CONFIG_PARTICIPANT))
+-		return ret;
+-
+-	if (clk->flags & SRC_SEL_MASK) {	/* On-chip SEL collection */
+-		src_sel = (SRC_RATE_SEL_MASK & clk->flags);
+-		src_off = clk->src_offset;
+-
+-		if (src_sel == 0)
+-			goto set_parent_error;
+-
+-		field_val = omap2_get_src_field(&src_sel, src_off, new_parent,
+-						&field_mask);
+-
+-		reg = (void __iomem *)src_sel;
+-
+-		if (clk->usecount > 0)
+-			_omap2_clk_disable(clk);
+-
+-		/* Set new source value (previous dividers if any in effect) */
+-		reg_val = __raw_readl(reg) & ~(field_mask << src_off);
+-		reg_val |= (field_val << src_off);
+-		__raw_writel(reg_val, reg);
+-		wmb();
++	const struct clksel *clks;
++	const struct clksel_rate *clkr;
+ 
+-		if (clk->flags & DELAYED_APP) {
+-			__raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
+-			wmb();
+-		}
+-		if (clk->usecount > 0)
+-			_omap2_clk_enable(clk);
+-
+-		clk->parent = new_parent;
++	*parent_div = 0;
++	*src_addr = 0;
+ 
+-		/* SRC_RATE_SEL_MASK clocks follow their parents rates.*/
+-		if ((new_parent == &core_ck) && (clk == &dss1_fck))
+-			clk->rate = new_parent->rate / 0x10;
+-		else
+-			clk->rate = new_parent->rate;
++	clks = omap2_get_clksel_by_parent(clk, src_clk);
++	if (clks == NULL)
++		return 0;
+ 
+-		if (unlikely(clk->flags & RATE_PROPAGATES))
+-			propagate_rate(clk);
++	for (clkr = clks->rates; clkr->div; clkr++) {
++		if (clkr->flags & (cpu_mask | DEFAULT_RATE))
++			break; /* Found the default rate for this platform */
++	}
+ 
++	if (!clkr->div) {
++		printk(KERN_ERR "clock: Could not find default rate for "
++		       "clock %s parent %s\n", clk->name,
++		       src_clk->parent->name);
+ 		return 0;
+-	} else {
+-		clk->parent = new_parent;
+-		rate = new_parent->rate;
+-		omap2_clk_set_rate(clk, rate);
+-		ret = 0;
+ 	}
+ 
+- set_parent_error:
+-	return ret;
++	/* Should never happen.  Add a clksel mask to the struct clk. */
++	WARN_ON(clk->clksel_mask == 0);
++
++	*field_mask = clk->clksel_mask;
++	*src_addr = clk->clksel_reg;
++	*parent_div = clkr->div;
++
++	return clkr->val;
+ }
+ 
+-/* Sets basic clocks based on the specified rate */
+-static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
++int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
+ {
+-	u32 flags, cur_rate, done_rate, bypass = 0;
+-	u8 cpu_mask = 0;
+-	struct prcm_config *prcm;
+-	unsigned long found_speed = 0;
++	void __iomem *src_addr;
++	u32 field_val, field_mask, reg_val, parent_div;
+ 
+-	if (clk != &virt_prcm_set)
++	if (unlikely(clk->flags & CONFIG_PARTICIPANT))
+ 		return -EINVAL;
+ 
+-	/* FIXME: Change cpu_is_omap2420() to cpu_is_omap242x() */
+-	if (cpu_is_omap2420())
+-		cpu_mask = RATE_IN_242X;
+-	else if (cpu_is_omap2430())
+-		cpu_mask = RATE_IN_243X;
+-
+-	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+-		if (!(prcm->flags & cpu_mask))
+-			continue;
+-
+-		if (prcm->xtal_speed != sys_ck.rate)
+-			continue;
+-
+-		if (prcm->mpu_speed <= rate) {
+-			found_speed = prcm->mpu_speed;
+-			break;
+-		}
+-	}
+-
+-	if (!found_speed) {
+-		printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
+-	 rate / 1000000);
++	if (!clk->clksel)
+ 		return -EINVAL;
+-	}
+-
+-	curr_prcm_set = prcm;
+-	cur_rate = omap2_get_dpll_rate(&dpll_ck);
+-
+-	if (prcm->dpll_speed == cur_rate / 2) {
+-		omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
+-	} else if (prcm->dpll_speed == cur_rate * 2) {
+-		omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
+-	} else if (prcm->dpll_speed != cur_rate) {
+-		local_irq_save(flags);
+ 
+-		if (prcm->dpll_speed == prcm->xtal_speed)
+-			bypass = 1;
++	field_val = omap2_clksel_get_src_field(&src_addr, new_parent,
++					       &field_mask, clk, &parent_div);
++	if (src_addr == 0)
++		return -EINVAL;
+ 
+-		if ((prcm->cm_clksel2_pll & 0x3) == 2)
+-			done_rate = PRCM_FULL_SPEED;
+-		else
+-			done_rate = PRCM_HALF_SPEED;
++	if (clk->usecount > 0)
++		_omap2_clk_disable(clk);
+ 
+-		/* MPU divider */
+-		CM_CLKSEL_MPU = prcm->cm_clksel_mpu;
++	/* Set new source value (previous dividers if any in effect) */
++	reg_val = __raw_readl(src_addr) & ~field_mask;
++	reg_val |= (field_val << __ffs(field_mask));
++	__raw_writel(reg_val, src_addr);
++	wmb();
+ 
+-		/* dsp + iva1 div(2420), iva2.1(2430) */
+-		CM_CLKSEL_DSP = prcm->cm_clksel_dsp;
++	if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
++		__raw_writel(OMAP24XX_VALID_CONFIG, OMAP24XX_PRCM_CLKCFG_CTRL);
++		wmb();
++	}
+ 
+-		CM_CLKSEL_GFX = prcm->cm_clksel_gfx;
++	if (clk->usecount > 0)
++		_omap2_clk_enable(clk);
+ 
+-		/* Major subsystem dividers */
+-		CM_CLKSEL1_CORE = prcm->cm_clksel1_core;
+-		if (cpu_is_omap2430())
+-			CM_CLKSEL_MDM = prcm->cm_clksel_mdm;
++	clk->parent = new_parent;
+ 
+-		/* x2 to enter init_mem */
+-		omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
++	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
++	clk->rate = new_parent->rate;
+ 
+-		omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
+-			       bypass);
++	if (parent_div > 0)
++		clk->rate /= parent_div;
+ 
+-		omap2_init_memory_params(omap2_dll_force_needed());
+-		omap2_reprogram_sdrc(done_rate, 0);
++	pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
++		 clk->name, clk->parent->name, clk->rate);
+ 
+-		local_irq_restore(flags);
+-	}
+-	omap2_clksel_recalc(&dpll_ck);
++	if (unlikely(clk->flags & RATE_PROPAGATES))
++		propagate_rate(clk);
+ 
+ 	return 0;
+ }
+@@ -1027,150 +726,17 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
+  *-------------------------------------------------------------------------*/
+ 
+ #ifdef CONFIG_OMAP_RESET_CLOCKS
+-static void __init omap2_clk_disable_unused(struct clk *clk)
++void omap2_clk_disable_unused(struct clk *clk)
+ {
+-	u32 regval32;
++	u32 regval32, v;
++
++	v = (clk->flags & INVERT_ENABLE) ? (1 << clk->enable_bit) : 0;
+ 
+ 	regval32 = __raw_readl(clk->enable_reg);
+-	if ((regval32 & (1 << clk->enable_bit)) == 0)
++	if ((regval32 & (1 << clk->enable_bit)) == v)
+ 		return;
+ 
+ 	printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
+ 	_omap2_clk_disable(clk);
+ }
+-#else
+-#define omap2_clk_disable_unused	NULL
+ #endif
+-
+-static struct clk_functions omap2_clk_functions = {
+-	.clk_enable		= omap2_clk_enable,
+-	.clk_disable		= omap2_clk_disable,
+-	.clk_round_rate		= omap2_clk_round_rate,
+-	.clk_set_rate		= omap2_clk_set_rate,
+-	.clk_set_parent		= omap2_clk_set_parent,
+-	.clk_disable_unused	= omap2_clk_disable_unused,
+-};
+-
+-static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
+-{
+-	u32 div, aplls, sclk = 13000000;
+-
+-	aplls = CM_CLKSEL1_PLL;
+-	aplls &= ((1 << 23) | (1 << 24) | (1 << 25));
+-	aplls >>= 23;			/* Isolate field, 0,2,3 */
+-
+-	if (aplls == 0)
+-		sclk = 19200000;
+-	else if (aplls == 2)
+-		sclk = 13000000;
+-	else if (aplls == 3)
+-		sclk = 12000000;
+-
+-	div = PRCM_CLKSRC_CTRL;
+-	div &= ((1 << 7) | (1 << 6));
+-	div >>= sys->rate_offset;
+-
+-	osc->rate = sclk * div;
+-	sys->rate = sclk;
+-}
+-
+-/*
+- * Set clocks for bypass mode for reboot to work.
+- */
+-void omap2_clk_prepare_for_reboot(void)
+-{
+-	u32 rate;
+-
+-	if (vclk == NULL || sclk == NULL)
+-		return;
+-
+-	rate = clk_get_rate(sclk);
+-	clk_set_rate(vclk, rate);
+-}
+-
+-/*
+- * Switch the MPU rate if specified on cmdline.
+- * We cannot do this early until cmdline is parsed.
+- */
+-static int __init omap2_clk_arch_init(void)
+-{
+-	if (!mpurate)
+-		return -EINVAL;
+-
+-	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+-		printk(KERN_ERR "Could not find matching MPU rate\n");
+-
+-	propagate_rate(&osc_ck);		/* update main root fast */
+-	propagate_rate(&func_32k_ck);		/* update main root slow */
+-
+-	printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
+-	       "%ld.%01ld/%ld/%ld MHz\n",
+-	       (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
+-	       (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
+-
+-	return 0;
+-}
+-arch_initcall(omap2_clk_arch_init);
+-
+-int __init omap2_clk_init(void)
+-{
+-	struct prcm_config *prcm;
+-	struct clk ** clkp;
+-	u32 clkrate;
+-
+-	clk_init(&omap2_clk_functions);
+-	omap2_get_crystal_rate(&osc_ck, &sys_ck);
+-
+-	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+-	     clkp++) {
+-
+-		if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
+-			clk_register(*clkp);
+-			continue;
+-		}
+-
+-		if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
+-			clk_register(*clkp);
+-			continue;
+-		}
+-	}
+-
+-	/* Check the MPU rate set by bootloader */
+-	clkrate = omap2_get_dpll_rate(&dpll_ck);
+-	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+-		if (prcm->xtal_speed != sys_ck.rate)
+-			continue;
+-		if (prcm->dpll_speed <= clkrate)
+-			 break;
+-	}
+-	curr_prcm_set = prcm;
+-
+-	propagate_rate(&osc_ck);		/* update main root fast */
+-	propagate_rate(&func_32k_ck);		/* update main root slow */
+-
+-	printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
+-	       "%ld.%01ld/%ld/%ld MHz\n",
+-	       (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
+-	       (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
+-
+-	/*
+-	 * Only enable those clocks we will need, let the drivers
+-	 * enable other clocks as necessary
+-	 */
+-	clk_enable(&sync_32k_ick);
+-	clk_enable(&omapctrl_ick);
+-
+-	/* Force the APLLs always active. The clocks are idled
+-	 * automatically by hardware. */
+-	clk_enable(&apll96_ck);
+-	clk_enable(&apll54_ck);
+-
+-	if (cpu_is_omap2430())
+-		clk_enable(&sdrc_ick);
+-
+-	/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
+-	vclk = clk_get(NULL, "virt_prcm_set");
+-	sclk = clk_get(NULL, "sys_ck");
+-
+-	return 0;
+-}
+diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
+index 4f79186..d5980a9 100644
+--- a/arch/arm/mach-omap2/clock.h
++++ b/arch/arm/mach-omap2/clock.h
+@@ -1,13 +1,12 @@
+ /*
+- *  linux/arch/arm/mach-omap24xx/clock.h
++ *  linux/arch/arm/mach-omap2/clock.h
+  *
+- *  Copyright (C) 2005 Texas Instruments Inc.
+- *  Richard Woodruff <r-woodruff2 at ti.com>
+- *  Created for OMAP2.
++ *  Copyright (C) 2005-2008 Texas Instruments, Inc.
++ *  Copyright (C) 2004-2008 Nokia Corporation
+  *
+- *  Copyright (C) 2004 Nokia corporation
+- *  Written by Tuukka Tikkanen <tuukka.tikkanen at elektrobit.com>
+- *  Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
++ *  Contacts:
++ *  Richard Woodruff <r-woodruff2 at ti.com>
++ *  Paul Walmsley
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+@@ -17,2095 +16,53 @@
+ #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_H
+ #define __ARCH_ARM_MACH_OMAP2_CLOCK_H
+ 
+-static void omap2_sys_clk_recalc(struct clk * clk);
+-static void omap2_clksel_recalc(struct clk * clk);
+-static void omap2_followparent_recalc(struct clk * clk);
+-static void omap2_propagate_rate(struct clk * clk);
+-static void omap2_mpu_recalc(struct clk * clk);
+-static int omap2_select_table_rate(struct clk * clk, unsigned long rate);
+-static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate);
+-static void omap2_clk_disable(struct clk *clk);
+-static void omap2_sys_clk_recalc(struct clk * clk);
+-static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val);
+-static u32 omap2_clksel_get_divisor(struct clk *clk);
+-
+-
+-#define RATE_IN_242X	(1 << 0)
+-#define RATE_IN_243X	(1 << 1)
+-
+-/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
+- * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
+- * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
+- */
+-struct prcm_config {
+-	unsigned long xtal_speed;	/* crystal rate */
+-	unsigned long dpll_speed;	/* dpll: out*xtal*M/(N-1)table_recalc */
+-	unsigned long mpu_speed;	/* speed of MPU */
+-	unsigned long cm_clksel_mpu;	/* mpu divider */
+-	unsigned long cm_clksel_dsp;	/* dsp+iva1 div(2420), iva2.1(2430) */
+-	unsigned long cm_clksel_gfx;	/* gfx dividers */
+-	unsigned long cm_clksel1_core;	/* major subsystem dividers */
+-	unsigned long cm_clksel1_pll;	/* m,n */
+-	unsigned long cm_clksel2_pll;	/* dpllx1 or x2 out */
+-	unsigned long cm_clksel_mdm;	/* modem dividers 2430 only */
+-	unsigned long base_sdrc_rfr;	/* base refresh timing for a set */
+-	unsigned char flags;
+-};
+-
+-/* Mask for clksel which support parent settign in set_rate */
+-#define SRC_SEL_MASK (CM_CORE_SEL1 | CM_CORE_SEL2 | CM_WKUP_SEL1 | \
+-			CM_PLL_SEL1 | CM_PLL_SEL2 | CM_SYSCLKOUT_SEL1)
+-
+-/* Mask for clksel regs which support rate operations */
+-#define SRC_RATE_SEL_MASK (CM_MPU_SEL1 | CM_DSP_SEL1 | CM_GFX_SEL1 | \
+-			CM_MODEM_SEL1 | CM_CORE_SEL1 | CM_CORE_SEL2 | \
+-			CM_WKUP_SEL1 | CM_PLL_SEL1 | CM_PLL_SEL2 | \
+-			CM_SYSCLKOUT_SEL1)
+-
+-/*
+- * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
+- * These configurations are characterized by voltage and speed for clocks.
+- * The device is only validated for certain combinations. One way to express
+- * these combinations is via the 'ratio's' which the clocks operate with
+- * respect to each other. These ratio sets are for a given voltage/DPLL
+- * setting. All configurations can be described by a DPLL setting and a ratio
+- * There are 3 ratio sets for the 2430 and X ratio sets for 2420.
+- *
+- * 2430 differs from 2420 in that there are no more phase synchronizers used.
+- * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs
+- * 2430 (iva2.1, NOdsp, mdm)
+- */
+-
+-/* Core fields for cm_clksel, not ratio governed */
+-#define RX_CLKSEL_DSS1			(0x10 << 8)
+-#define RX_CLKSEL_DSS2			(0x0 << 13)
+-#define RX_CLKSEL_SSI			(0x5 << 20)
+-
+-/*-------------------------------------------------------------------------
+- * Voltage/DPLL ratios
+- *-------------------------------------------------------------------------*/
+-
+-/* 2430 Ratio's, 2430-Ratio Config 1 */
+-#define R1_CLKSEL_L3			(4 << 0)
+-#define R1_CLKSEL_L4			(2 << 5)
+-#define R1_CLKSEL_USB			(4 << 25)
+-#define R1_CM_CLKSEL1_CORE_VAL		R1_CLKSEL_USB | RX_CLKSEL_SSI | \
+-					RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+-					R1_CLKSEL_L4 | R1_CLKSEL_L3
+-#define R1_CLKSEL_MPU			(2 << 0)
+-#define R1_CM_CLKSEL_MPU_VAL		R1_CLKSEL_MPU
+-#define R1_CLKSEL_DSP			(2 << 0)
+-#define R1_CLKSEL_DSP_IF		(2 << 5)
+-#define R1_CM_CLKSEL_DSP_VAL		R1_CLKSEL_DSP | R1_CLKSEL_DSP_IF
+-#define R1_CLKSEL_GFX			(2 << 0)
+-#define R1_CM_CLKSEL_GFX_VAL		R1_CLKSEL_GFX
+-#define R1_CLKSEL_MDM			(4 << 0)
+-#define R1_CM_CLKSEL_MDM_VAL		R1_CLKSEL_MDM
+-
+-/* 2430-Ratio Config 2 */
+-#define R2_CLKSEL_L3			(6 << 0)
+-#define R2_CLKSEL_L4			(2 << 5)
+-#define R2_CLKSEL_USB			(2 << 25)
+-#define R2_CM_CLKSEL1_CORE_VAL		R2_CLKSEL_USB | RX_CLKSEL_SSI | \
+-					RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+-					R2_CLKSEL_L4 | R2_CLKSEL_L3
+-#define R2_CLKSEL_MPU			(2 << 0)
+-#define R2_CM_CLKSEL_MPU_VAL		R2_CLKSEL_MPU
+-#define R2_CLKSEL_DSP			(2 << 0)
+-#define R2_CLKSEL_DSP_IF		(3 << 5)
+-#define R2_CM_CLKSEL_DSP_VAL		R2_CLKSEL_DSP | R2_CLKSEL_DSP_IF
+-#define R2_CLKSEL_GFX			(2 << 0)
+-#define R2_CM_CLKSEL_GFX_VAL		R2_CLKSEL_GFX
+-#define R2_CLKSEL_MDM			(6 << 0)
+-#define R2_CM_CLKSEL_MDM_VAL		R2_CLKSEL_MDM
+-
+-/* 2430-Ratio Bootm (BYPASS) */
+-#define RB_CLKSEL_L3			(1 << 0)
+-#define RB_CLKSEL_L4			(1 << 5)
+-#define RB_CLKSEL_USB			(1 << 25)
+-#define RB_CM_CLKSEL1_CORE_VAL		RB_CLKSEL_USB | RX_CLKSEL_SSI | \
+-					RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+-					RB_CLKSEL_L4 | RB_CLKSEL_L3
+-#define RB_CLKSEL_MPU			(1 << 0)
+-#define RB_CM_CLKSEL_MPU_VAL		RB_CLKSEL_MPU
+-#define RB_CLKSEL_DSP			(1 << 0)
+-#define RB_CLKSEL_DSP_IF		(1 << 5)
+-#define RB_CM_CLKSEL_DSP_VAL		RB_CLKSEL_DSP | RB_CLKSEL_DSP_IF
+-#define RB_CLKSEL_GFX			(1 << 0)
+-#define RB_CM_CLKSEL_GFX_VAL		RB_CLKSEL_GFX
+-#define RB_CLKSEL_MDM			(1 << 0)
+-#define RB_CM_CLKSEL_MDM_VAL		RB_CLKSEL_MDM
+-
+-/* 2420 Ratio Equivalents */
+-#define RXX_CLKSEL_VLYNQ		(0x12 << 15)
+-#define RXX_CLKSEL_SSI			(0x8 << 20)
+-
+-/* 2420-PRCM III 532MHz core */
+-#define RIII_CLKSEL_L3			(4 << 0)	/* 133MHz */
+-#define RIII_CLKSEL_L4			(2 << 5)	/* 66.5MHz */
+-#define RIII_CLKSEL_USB			(4 << 25)	/* 33.25MHz */
+-#define RIII_CM_CLKSEL1_CORE_VAL	RIII_CLKSEL_USB | RXX_CLKSEL_SSI | \
+-					RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \
+-					RX_CLKSEL_DSS1 | RIII_CLKSEL_L4 | \
+-					RIII_CLKSEL_L3
+-#define RIII_CLKSEL_MPU			(2 << 0)	/* 266MHz */
+-#define RIII_CM_CLKSEL_MPU_VAL		RIII_CLKSEL_MPU
+-#define RIII_CLKSEL_DSP			(3 << 0)	/* c5x - 177.3MHz */
+-#define RIII_CLKSEL_DSP_IF		(2 << 5)	/* c5x - 88.67MHz */
+-#define RIII_SYNC_DSP			(1 << 7)	/* Enable sync */
+-#define RIII_CLKSEL_IVA			(6 << 8)	/* iva1 - 88.67MHz */
+-#define RIII_SYNC_IVA			(1 << 13)	/* Enable sync */
+-#define RIII_CM_CLKSEL_DSP_VAL		RIII_SYNC_IVA | RIII_CLKSEL_IVA | \
+-					RIII_SYNC_DSP | RIII_CLKSEL_DSP_IF | \
+-					RIII_CLKSEL_DSP
+-#define RIII_CLKSEL_GFX			(2 << 0)	/* 66.5MHz */
+-#define RIII_CM_CLKSEL_GFX_VAL		RIII_CLKSEL_GFX
+-
+-/* 2420-PRCM II 600MHz core */
+-#define RII_CLKSEL_L3			(6 << 0)	/* 100MHz */
+-#define RII_CLKSEL_L4			(2 << 5)	/* 50MHz */
+-#define RII_CLKSEL_USB			(2 << 25)	/* 50MHz */
+-#define RII_CM_CLKSEL1_CORE_VAL		RII_CLKSEL_USB | \
+-					RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \
+-					RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+-					RII_CLKSEL_L4 | RII_CLKSEL_L3
+-#define RII_CLKSEL_MPU			(2 << 0)	/* 300MHz */
+-#define RII_CM_CLKSEL_MPU_VAL		RII_CLKSEL_MPU
+-#define RII_CLKSEL_DSP			(3 << 0)	/* c5x - 200MHz */
+-#define RII_CLKSEL_DSP_IF		(2 << 5)	/* c5x - 100MHz */
+-#define RII_SYNC_DSP			(0 << 7)	/* Bypass sync */
+-#define RII_CLKSEL_IVA			(6 << 8)	/* iva1 - 200MHz */
+-#define RII_SYNC_IVA			(0 << 13)	/* Bypass sync */
+-#define RII_CM_CLKSEL_DSP_VAL		RII_SYNC_IVA | RII_CLKSEL_IVA | \
+-					RII_SYNC_DSP | RII_CLKSEL_DSP_IF | \
+-					RII_CLKSEL_DSP
+-#define RII_CLKSEL_GFX			(2 << 0)	/* 50MHz */
+-#define RII_CM_CLKSEL_GFX_VAL		RII_CLKSEL_GFX
+-
+-/* 2420-PRCM VII (boot) */
+-#define RVII_CLKSEL_L3			(1 << 0)
+-#define RVII_CLKSEL_L4			(1 << 5)
+-#define RVII_CLKSEL_DSS1		(1 << 8)
+-#define RVII_CLKSEL_DSS2		(0 << 13)
+-#define RVII_CLKSEL_VLYNQ		(1 << 15)
+-#define RVII_CLKSEL_SSI			(1 << 20)
+-#define RVII_CLKSEL_USB			(1 << 25)
+-
+-#define RVII_CM_CLKSEL1_CORE_VAL	RVII_CLKSEL_USB | RVII_CLKSEL_SSI | \
+-					RVII_CLKSEL_VLYNQ | RVII_CLKSEL_DSS2 | \
+-					RVII_CLKSEL_DSS1 | RVII_CLKSEL_L4 | RVII_CLKSEL_L3
+-
+-#define RVII_CLKSEL_MPU			(1 << 0) /* all divide by 1 */
+-#define RVII_CM_CLKSEL_MPU_VAL		RVII_CLKSEL_MPU
++#include <asm/arch/clock.h>
+ 
+-#define RVII_CLKSEL_DSP			(1 << 0)
+-#define RVII_CLKSEL_DSP_IF		(1 << 5)
+-#define RVII_SYNC_DSP			(0 << 7)
+-#define RVII_CLKSEL_IVA			(1 << 8)
+-#define RVII_SYNC_IVA			(0 << 13)
+-#define RVII_CM_CLKSEL_DSP_VAL		RVII_SYNC_IVA | RVII_CLKSEL_IVA | RVII_SYNC_DSP | \
+-					RVII_CLKSEL_DSP_IF | RVII_CLKSEL_DSP
+-
+-#define RVII_CLKSEL_GFX			(1 << 0)
+-#define RVII_CM_CLKSEL_GFX_VAL		RVII_CLKSEL_GFX
+-
+-/*-------------------------------------------------------------------------
+- * 2430 Target modes: Along with each configuration the CPU has several
+- * modes which goes along with them. Modes mainly are the addition of
+- * describe DPLL combinations to go along with a ratio.
+- *-------------------------------------------------------------------------*/
+-
+-/* Hardware governed */
+-#define MX_48M_SRC			(0 << 3)
+-#define MX_54M_SRC			(0 << 5)
+-#define MX_APLLS_CLIKIN_12		(3 << 23)
+-#define MX_APLLS_CLIKIN_13		(2 << 23)
+-#define MX_APLLS_CLIKIN_19_2		(0 << 23)
+-
+-/*
+- * 2430 - standalone, 2*ref*M/(n+1), M/N is for exactness not relock speed
+- * #2	(ratio1) baseport-target
+- * #5a	(ratio1) baseport-target, target DPLL = 266*2 = 532MHz
+- */
+-#define M5A_DPLL_MULT_12		(133 << 12)
+-#define M5A_DPLL_DIV_12			(5 << 8)
+-#define M5A_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					M5A_DPLL_DIV_12 | M5A_DPLL_MULT_12 | \
+-					MX_APLLS_CLIKIN_12
+-#define M5A_DPLL_MULT_13		(266 << 12)
+-#define M5A_DPLL_DIV_13			(12 << 8)
+-#define M5A_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					M5A_DPLL_DIV_13 | M5A_DPLL_MULT_13 | \
+-					MX_APLLS_CLIKIN_13
+-#define M5A_DPLL_MULT_19		(180 << 12)
+-#define M5A_DPLL_DIV_19			(12 << 8)
+-#define M5A_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					M5A_DPLL_DIV_19 | M5A_DPLL_MULT_19 | \
+-					MX_APLLS_CLIKIN_19_2
+-/* #5b	(ratio1) target DPLL = 200*2 = 400MHz */
+-#define M5B_DPLL_MULT_12		(50 << 12)
+-#define M5B_DPLL_DIV_12			(2 << 8)
+-#define M5B_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					M5B_DPLL_DIV_12 | M5B_DPLL_MULT_12 | \
+-					MX_APLLS_CLIKIN_12
+-#define M5B_DPLL_MULT_13		(200 << 12)
+-#define M5B_DPLL_DIV_13			(12 << 8)
+-
+-#define M5B_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					M5B_DPLL_DIV_13 | M5B_DPLL_MULT_13 | \
+-					MX_APLLS_CLIKIN_13
+-#define M5B_DPLL_MULT_19		(125 << 12)
+-#define M5B_DPLL_DIV_19			(31 << 8)
+-#define M5B_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					M5B_DPLL_DIV_19 | M5B_DPLL_MULT_19 | \
+-					MX_APLLS_CLIKIN_19_2
+-/*
+- * #4	(ratio2)
+- * #3	(ratio2) baseport-target, target DPLL = 330*2 = 660MHz
+- */
+-#define M3_DPLL_MULT_12			(55 << 12)
+-#define M3_DPLL_DIV_12			(1 << 8)
+-#define M3_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					M3_DPLL_DIV_12 | M3_DPLL_MULT_12 | \
+-					MX_APLLS_CLIKIN_12
+-#define M3_DPLL_MULT_13			(330 << 12)
+-#define M3_DPLL_DIV_13			(12 << 8)
+-#define M3_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					M3_DPLL_DIV_13 | M3_DPLL_MULT_13 | \
+-					MX_APLLS_CLIKIN_13
+-#define M3_DPLL_MULT_19			(275 << 12)
+-#define M3_DPLL_DIV_19			(15 << 8)
+-#define M3_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					M3_DPLL_DIV_19 | M3_DPLL_MULT_19 | \
+-					MX_APLLS_CLIKIN_19_2
+-/* boot (boot) */
+-#define MB_DPLL_MULT			(1 << 12)
+-#define MB_DPLL_DIV			(0 << 8)
+-#define MB_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
+-					MB_DPLL_MULT | MX_APLLS_CLIKIN_12
+-
+-#define MB_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
+-					MB_DPLL_MULT | MX_APLLS_CLIKIN_13
+-
+-#define MB_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
+-					MB_DPLL_MULT | MX_APLLS_CLIKIN_19
+-
+-/*
+- * 2430 - chassis (sedna)
+- * 165 (ratio1) same as above #2
+- * 150 (ratio1)
+- * 133 (ratio2) same as above #4
+- * 110 (ratio2) same as above #3
+- * 104 (ratio2)
+- * boot (boot)
+- */
+-
+-/*
+- * 2420 Equivalent - mode registers
+- * PRCM II , target DPLL = 2*300MHz = 600MHz
+- */
+-#define MII_DPLL_MULT_12		(50 << 12)
+-#define MII_DPLL_DIV_12			(1 << 8)
+-#define MII_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					MII_DPLL_DIV_12 | MII_DPLL_MULT_12 | \
+-					MX_APLLS_CLIKIN_12
+-#define MII_DPLL_MULT_13		(300 << 12)
+-#define MII_DPLL_DIV_13			(12 << 8)
+-#define MII_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					MII_DPLL_DIV_13 | MII_DPLL_MULT_13 | \
+-					MX_APLLS_CLIKIN_13
+-
+-/* PRCM III target DPLL = 2*266 = 532MHz*/
+-#define MIII_DPLL_MULT_12		(133 << 12)
+-#define MIII_DPLL_DIV_12		(5 << 8)
+-#define MIII_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					MIII_DPLL_DIV_12 | MIII_DPLL_MULT_12 | \
+-					MX_APLLS_CLIKIN_12
+-#define MIII_DPLL_MULT_13		(266 << 12)
+-#define MIII_DPLL_DIV_13		(12 << 8)
+-#define MIII_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
+-					MIII_DPLL_DIV_13 | MIII_DPLL_MULT_13 | \
+-					MX_APLLS_CLIKIN_13
+-
+-/* PRCM VII (boot bypass) */
+-#define MVII_CM_CLKSEL1_PLL_12_VAL	MB_CM_CLKSEL1_PLL_12_VAL
+-#define MVII_CM_CLKSEL1_PLL_13_VAL	MB_CM_CLKSEL1_PLL_13_VAL
+-
+-/* High and low operation value */
+-#define MX_CLKSEL2_PLL_2x_VAL		(2 << 0)
+-#define MX_CLKSEL2_PLL_1x_VAL		(1 << 0)
+-
+-/*
+- * These represent optimal values for common parts, it won't work for all.
+- * As long as you scale down, most parameters are still work, they just
+- * become sub-optimal. The RFR value goes in the opposite direction. If you
+- * don't adjust it down as your clock period increases the refresh interval
+- * will not be met. Setting all parameters for complete worst case may work,
+- * but may cut memory performance by 2x. Due to errata the DLLs need to be
+- * unlocked and their value needs run time calibration.	A dynamic call is
+- * need for that as no single right value exists acorss production samples.
+- *
+- * Only the FULL speed values are given. Current code is such that rate
+- * changes must be made at DPLLoutx2. The actual value adjustment for low
+- * frequency operation will be handled by omap_set_performance()
+- *
+- * By having the boot loader boot up in the fastest L4 speed available likely
+- * will result in something which you can switch between.
+- */
+-#define V24XX_SDRC_RFR_CTRL_133MHz	(0x0003de00 | 1)
+-#define V24XX_SDRC_RFR_CTRL_100MHz	(0x0002da01 | 1)
+-#define V24XX_SDRC_RFR_CTRL_110MHz	(0x0002da01 | 1) /* Need to calc */
+-#define V24XX_SDRC_RFR_CTRL_BYPASS	(0x00005000 | 1) /* Need to calc */
+-
+-/* MPU speed defines */
+-#define S12M	12000000
+-#define S13M	13000000
+-#define S19M	19200000
+-#define S26M	26000000
+-#define S100M	100000000
+-#define S133M	133000000
+-#define S150M	150000000
+-#define S165M	165000000
+-#define S200M	200000000
+-#define S266M	266000000
+-#define S300M	300000000
+-#define S330M	330000000
+-#define S400M	400000000
+-#define S532M	532000000
+-#define S600M	600000000
+-#define S660M	660000000
+-
+-/*-------------------------------------------------------------------------
+- * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
+- * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,
+- * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL,
+- * CM_CLKSEL2_PLL, CM_CLKSEL_MDM
+- *
+- * Filling in table based on H4 boards and 2430-SDPs variants available.
+- * There are quite a few more rates combinations which could be defined.
+- *
+- * When multiple values are defined the start up will try and choose the
+- * fastest one. If a 'fast' value is defined, then automatically, the /2
+- * one should be included as it can be used.	Generally having more that
+- * one fast set does not make sense, as static timings need to be changed
+- * to change the set.	 The exception is the bypass setting which is
+- * availble for low power bypass.
+- *
+- * Note: This table needs to be sorted, fastest to slowest.
+- *-------------------------------------------------------------------------*/
+-static struct prcm_config rate_table[] = {
+-	/* PRCM II - FAST */
+-	{S12M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL,		/* 300MHz ARM */
+-		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+-		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+-		RATE_IN_242X},
+-
+-	{S13M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL,		/* 300MHz ARM */
+-		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+-		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+-		RATE_IN_242X},
+-
+-	/* PRCM III - FAST */
+-	{S12M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL,		/* 266MHz ARM */
+-		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+-		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+-		RATE_IN_242X},
+-
+-	{S13M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL,		/* 266MHz ARM */
+-		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+-		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+-		RATE_IN_242X},
+-
+-	/* PRCM II - SLOW */
+-	{S12M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL,		/* 150MHz ARM */
+-		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+-		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+-		RATE_IN_242X},
+-
+-	{S13M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL,		/* 150MHz ARM */
+-		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+-		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+-		RATE_IN_242X},
+-
+-	/* PRCM III - SLOW */
+-	{S12M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL,		/* 133MHz ARM */
+-		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+-		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+-		RATE_IN_242X},
+-
+-	{S13M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL,		/* 133MHz ARM */
+-		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+-		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+-		RATE_IN_242X},
+-
+-	/* PRCM-VII (boot-bypass) */
+-	{S12M, S12M, S12M, RVII_CM_CLKSEL_MPU_VAL,		/* 12MHz ARM*/
+-		RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
+-		RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_12_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_BYPASS,
+-		RATE_IN_242X},
+-
+-	/* PRCM-VII (boot-bypass) */
+-	{S13M, S13M, S13M, RVII_CM_CLKSEL_MPU_VAL,		/* 13MHz ARM */
+-		RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
+-		RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_BYPASS,
+-		RATE_IN_242X},
+-
+-	/* PRCM #3 - ratio2 (ES2) - FAST */
+-	{S13M, S660M, S330M, R2_CM_CLKSEL_MPU_VAL,		/* 330MHz ARM */
+-		R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
+-		R2_CM_CLKSEL1_CORE_VAL, M3_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, R2_CM_CLKSEL_MDM_VAL,
+-		V24XX_SDRC_RFR_CTRL_110MHz,
+-		RATE_IN_243X},
+-
+-	/* PRCM #5a - ratio1 - FAST */
+-	{S13M, S532M, S266M, R1_CM_CLKSEL_MPU_VAL,		/* 266MHz ARM */
+-		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+-		R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
+-		V24XX_SDRC_RFR_CTRL_133MHz,
+-		RATE_IN_243X},
+-
+-	/* PRCM #5b - ratio1 - FAST */
+-	{S13M, S400M, S200M, R1_CM_CLKSEL_MPU_VAL,		/* 200MHz ARM */
+-		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+-		R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
+-		V24XX_SDRC_RFR_CTRL_100MHz,
+-		RATE_IN_243X},
+-
+-	/* PRCM #3 - ratio2 (ES2) - SLOW */
+-	{S13M, S330M, S165M, R2_CM_CLKSEL_MPU_VAL,		/* 165MHz ARM */
+-		R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
+-		R2_CM_CLKSEL1_CORE_VAL, M3_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_1x_VAL, R2_CM_CLKSEL_MDM_VAL,
+-		V24XX_SDRC_RFR_CTRL_110MHz,
+-		RATE_IN_243X},
+-
+-	/* PRCM #5a - ratio1 - SLOW */
+-	{S13M, S266M, S133M, R1_CM_CLKSEL_MPU_VAL,		/* 133MHz ARM */
+-		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+-		R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
+-		V24XX_SDRC_RFR_CTRL_133MHz,
+-		RATE_IN_243X},
+-
+-	/* PRCM #5b - ratio1 - SLOW*/
+-	{S13M, S200M, S100M, R1_CM_CLKSEL_MPU_VAL,		/* 100MHz ARM */
+-		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+-		R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
+-		V24XX_SDRC_RFR_CTRL_100MHz,
+-		RATE_IN_243X},
+-
+-	/* PRCM-boot/bypass */
+-	{S13M, S13M, S13M, RB_CM_CLKSEL_MPU_VAL,		/* 13Mhz */
+-		RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
+-		RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_13_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
+-		V24XX_SDRC_RFR_CTRL_BYPASS,
+-		RATE_IN_243X},
+-
+-	/* PRCM-boot/bypass */
+-	{S12M, S12M, S12M, RB_CM_CLKSEL_MPU_VAL,		/* 12Mhz */
+-		RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
+-		RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_12_VAL,
+-		MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
+-		V24XX_SDRC_RFR_CTRL_BYPASS,
+-		RATE_IN_243X},
+-
+-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+-};
+-
+-/*-------------------------------------------------------------------------
+- * 24xx clock tree.
+- *
+- * NOTE:In many cases here we are assigning a 'default' parent.	In many
+- *	cases the parent is selectable.	The get/set parent calls will also
+- *	switch sources.
+- *
+- *	Many some clocks say always_enabled, but they can be auto idled for
+- *	power savings. They will always be available upon clock request.
+- *
+- *	Several sources are given initial rates which may be wrong, this will
+- *	be fixed up in the init func.
+- *
+- *	Things are broadly separated below by clock domains. It is
+- *	noteworthy that most periferals have dependencies on multiple clock
+- *	domains. Many get their interface clocks from the L4 domain, but get
+- *	functional clocks from fixed sources or other core domain derived
+- *	clocks.
+- *-------------------------------------------------------------------------*/
+-
+-/* Base external input clocks */
+-static struct clk func_32k_ck = {
+-	.name		= "func_32k_ck",
+-	.rate		= 32000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | ALWAYS_ENABLED,
+-};
+-
+-/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
+-static struct clk osc_ck = {		/* (*12, *13, 19.2, *26, 38.4)MHz */
+-	.name		= "osc_ck",
+-	.rate		= 26000000,		/* fixed up in clock init */
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | RATE_PROPAGATES,
+-};
+-
+-/* With out modem likely 12MHz, with modem likely 13MHz */
+-static struct clk sys_ck = {		/* (*12, *13, 19.2, 26, 38.4)MHz */
+-	.name		= "sys_ck",		/* ~ ref_clk also */
+-	.parent		= &osc_ck,
+-	.rate		= 13000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+-	.rate_offset	= 6, /* sysclkdiv 1 or 2, already handled or no boot */
+-	.recalc		= &omap2_sys_clk_recalc,
+-};
+-
+-static struct clk alt_ck = {		/* Typical 54M or 48M, may not exist */
+-	.name		= "alt_ck",
+-	.rate		= 54000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+-	.recalc		= &omap2_propagate_rate,
+-};
+-
+-/*
+- * Analog domain root source clocks
+- */
+-
+-/* dpll_ck, is broken out in to special cases through clksel */
+-static struct clk dpll_ck = {
+-	.name		= "dpll_ck",
+-	.parent		= &sys_ck,		/* Can be func_32k also */
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_PROPAGATES | RATE_CKCTL | CM_PLL_SEL1,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk apll96_ck = {
+-	.name		= "apll96_ck",
+-	.parent		= &sys_ck,
+-	.rate		= 96000000,
+-	.flags		= CLOCK_IN_OMAP242X |CLOCK_IN_OMAP243X |
+-				RATE_FIXED | RATE_PROPAGATES,
+-	.enable_reg	= (void __iomem *)&CM_CLKEN_PLL,
+-	.enable_bit	= 0x2,
+-	.recalc		= &omap2_propagate_rate,
+-};
+-
+-static struct clk apll54_ck = {
+-	.name		= "apll54_ck",
+-	.parent		= &sys_ck,
+-	.rate		= 54000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | RATE_PROPAGATES,
+-	.enable_reg	= (void __iomem *)&CM_CLKEN_PLL,
+-	.enable_bit	= 0x6,
+-	.recalc		= &omap2_propagate_rate,
+-};
++int omap2_clk_enable(struct clk *clk);
++void omap2_clk_disable(struct clk *clk);
++long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
++int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
++int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
+ 
+-/*
+- * PRCM digital base sources
+- */
+-static struct clk func_54m_ck = {
+-	.name		= "func_54m_ck",
+-	.parent		= &apll54_ck,	/* can also be alt_clk */
+-	.rate		= 54000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES,
+-	.src_offset	= 5,
+-	.enable_reg	= (void __iomem *)&CM_CLKEN_PLL,
+-	.enable_bit	= 0xff,
+-	.recalc		= &omap2_propagate_rate,
+-};
+-
+-static struct clk core_ck = {
+-	.name		= "core_ck",
+-	.parent		= &dpll_ck,		/* can also be 32k */
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				ALWAYS_ENABLED | RATE_PROPAGATES,
+-	.recalc		= &omap2_propagate_rate,
+-};
+-
+-static struct clk sleep_ck = {		/* sys_clk or 32k */
+-	.name		= "sleep_ck",
+-	.parent		= &func_32k_ck,
+-	.rate		= 32000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.recalc		= &omap2_propagate_rate,
+-};
+-
+-static struct clk func_96m_ck = {
+-	.name		= "func_96m_ck",
+-	.parent		= &apll96_ck,
+-	.rate		= 96000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | RATE_PROPAGATES,
+-	.enable_reg	= (void __iomem *)&CM_CLKEN_PLL,
+-	.enable_bit	= 0xff,
+-	.recalc		= &omap2_propagate_rate,
+-};
+-
+-static struct clk func_48m_ck = {
+-	.name		= "func_48m_ck",
+-	.parent		= &apll96_ck,	 /* 96M or Alt */
+-	.rate		= 48000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES,
+-	.src_offset	= 3,
+-	.enable_reg	= (void __iomem *)&CM_CLKEN_PLL,
+-	.enable_bit	= 0xff,
+-	.recalc		= &omap2_propagate_rate,
+-};
+-
+-static struct clk func_12m_ck = {
+-	.name		= "func_12m_ck",
+-	.parent		= &func_48m_ck,
+-	.rate		= 12000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | RATE_PROPAGATES,
+-	.recalc		= &omap2_propagate_rate,
+-	.enable_reg	= (void __iomem *)&CM_CLKEN_PLL,
+-	.enable_bit	= 0xff,
+-};
+-
+-/* Secure timer, only available in secure mode */
+-static struct clk wdt1_osc_ck = {
+-	.name		= "ck_wdt1_osc",
+-	.parent		= &osc_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk sys_clkout = {
+-	.name		= "sys_clkout",
+-	.parent		= &func_54m_ck,
+-	.rate		= 54000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_SYSCLKOUT_SEL1 | RATE_CKCTL,
+-	.src_offset	= 0,
+-	.enable_reg	= (void __iomem *)&PRCM_CLKOUT_CTRL,
+-	.enable_bit	= 7,
+-	.rate_offset	= 3,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-/* In 2430, new in 2420 ES2 */
+-static struct clk sys_clkout2 = {
+-	.name		= "sys_clkout2",
+-	.parent		= &func_54m_ck,
+-	.rate		= 54000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_SYSCLKOUT_SEL1 | RATE_CKCTL,
+-	.src_offset	= 8,
+-	.enable_reg	= (void __iomem *)&PRCM_CLKOUT_CTRL,
+-	.enable_bit	= 15,
+-	.rate_offset	= 11,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk emul_ck = {
+-	.name		= "emul_ck",
+-	.parent		= &func_54m_ck,
+-	.flags		= CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&PRCM_CLKEMUL_CTRL,
+-	.enable_bit	= 0,
+-	.recalc		= &omap2_propagate_rate,
+-
+-};
+-
+-/*
+- * MPU clock domain
+- *	Clocks:
+- *		MPU_FCLK, MPU_ICLK
+- *		INT_M_FCLK, INT_M_I_CLK
+- *
+- * - Individual clocks are hardware managed.
+- * - Base divider comes from: CM_CLKSEL_MPU
+- *
+- */
+-static struct clk mpu_ck = {	/* Control cpu */
+-	.name		= "mpu_ck",
+-	.parent		= &core_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL |
+-				ALWAYS_ENABLED | CM_MPU_SEL1 | DELAYED_APP |
+-				CONFIG_PARTICIPANT | RATE_PROPAGATES,
+-	.rate_offset	= 0,	/* bits 0-4 */
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-/*
+- * DSP (2430-IVA2.1) (2420-UMA+IVA1) clock domain
+- * Clocks:
+- *	2430: IVA2.1_FCLK, IVA2.1_ICLK
+- *	2420: UMA_FCLK, UMA_ICLK, IVA_MPU, IVA_COP
+- */
+-static struct clk iva2_1_fck = {
+-	.name		= "iva2_1_fck",
+-	.parent		= &core_ck,
+-	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
+-				DELAYED_APP | RATE_PROPAGATES |
+-				CONFIG_PARTICIPANT,
+-	.rate_offset	= 0,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_DSP,
+-	.enable_bit	= 0,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk iva2_1_ick = {
+-	.name		= "iva2_1_ick",
+-	.parent		= &iva2_1_fck,
+-	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
+-				DELAYED_APP | CONFIG_PARTICIPANT,
+-	.rate_offset	= 5,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-/*
+- * Won't be too specific here. The core clock comes into this block
+- * it is divided then tee'ed. One branch goes directly to xyz enable
+- * controls. The other branch gets further divided by 2 then possibly
+- * routed into a synchronizer and out of clocks abc.
+- */
+-static struct clk dsp_fck = {
+-	.name		= "dsp_fck",
+-	.parent		= &core_ck,
+-	.flags		= CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
+-			DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES,
+-	.rate_offset	= 0,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_DSP,
+-	.enable_bit	= 0,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk dsp_ick = {
+-	.name		= "dsp_ick",	 /* apparently ipi and isp */
+-	.parent		= &dsp_fck,
+-	.flags		= CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
+-				DELAYED_APP | CONFIG_PARTICIPANT,
+-	.rate_offset = 5,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_DSP,
+-	.enable_bit	= 1,		/* for ipi */
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk iva1_ifck = {
+-	.name		= "iva1_ifck",
+-	.parent		= &core_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CM_DSP_SEL1 | RATE_CKCTL |
+-			CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP,
+-	.rate_offset= 8,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_DSP,
+-	.enable_bit	= 10,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-/* IVA1 mpu/int/i/f clocks are /2 of parent */
+-static struct clk iva1_mpu_int_ifck = {
+-	.name		= "iva1_mpu_int_ifck",
+-	.parent		= &iva1_ifck,
+-	.flags		= CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_DSP,
+-	.enable_bit	= 8,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-/*
+- * L3 clock domain
+- * L3 clocks are used for both interface and functional clocks to
+- * multiple entities. Some of these clocks are completely managed
+- * by hardware, and some others allow software control. Hardware
+- * managed ones general are based on directly CLK_REQ signals and
+- * various auto idle settings. The functional spec sets many of these
+- * as 'tie-high' for their enables.
+- *
+- * I-CLOCKS:
+- *	L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA
+- *	CAM, HS-USB.
+- * F-CLOCK
+- *	SSI.
+- *
+- * GPMC memories and SDRC have timing and clock sensitive registers which
+- * may very well need notification when the clock changes. Currently for low
+- * operating points, these are taken care of in sleep.S.
+- */
+-static struct clk core_l3_ck = {	/* Used for ick and fck, interconnect */
+-	.name		= "core_l3_ck",
+-	.parent		= &core_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
+-				DELAYED_APP | CONFIG_PARTICIPANT |
+-				RATE_PROPAGATES,
+-	.rate_offset	= 0,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk usb_l4_ick = {	/* FS-USB interface clock */
+-	.name		= "usb_l4_ick",
+-	.parent		= &core_l3_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP |
+-				CONFIG_PARTICIPANT,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 0,
+-	.rate_offset = 25,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-/*
+- * SSI is in L3 management domain, its direct parent is core not l3,
+- * many core power domain entities are grouped into the L3 clock
+- * domain.
+- * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_CLIK
+- *
+- * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
+- */
+-static struct clk ssi_ssr_sst_fck = {
+-	.name		= "ssi_fck",
+-	.parent		= &core_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,	/* bit 1 */
+-	.enable_bit	= 1,
+-	.rate_offset = 20,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-/*
+- * GFX clock domain
+- *	Clocks:
+- * GFX_FCLK, GFX_ICLK
+- * GFX_CG1(2d), GFX_CG2(3d)
+- *
+- * GFX_FCLK runs from L3, and is divided by (1,2,3,4)
+- * The 2d and 3d clocks run at a hardware determined
+- * divided value of fclk.
+- *
+- */
+-static struct clk gfx_3d_fck = {
+-	.name		= "gfx_3d_fck",
+-	.parent		= &core_l3_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_CKCTL | CM_GFX_SEL1,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_GFX,
+-	.enable_bit	= 2,
+-	.rate_offset= 0,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk gfx_2d_fck = {
+-	.name		= "gfx_2d_fck",
+-	.parent		= &core_l3_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_CKCTL | CM_GFX_SEL1,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_GFX,
+-	.enable_bit	= 1,
+-	.rate_offset= 0,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk gfx_ick = {
+-	.name		= "gfx_ick",		/* From l3 */
+-	.parent		= &core_l3_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_CKCTL,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_GFX,	/* bit 0 */
+-	.enable_bit	= 0,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-/*
+- * Modem clock domain (2430)
+- *	CLOCKS:
+- *		MDM_OSC_CLK
+- *		MDM_ICLK
+- */
+-static struct clk mdm_ick = {		/* used both as a ick and fck */
+-	.name		= "mdm_ick",
+-	.parent		= &core_ck,
+-	.flags		= CLOCK_IN_OMAP243X | RATE_CKCTL | CM_MODEM_SEL1 |
+-				DELAYED_APP | CONFIG_PARTICIPANT,
+-	.rate_offset	= 0,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_MDM,
+-	.enable_bit	= 0,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk mdm_osc_ck = {
+-	.name		= "mdm_osc_ck",
+-	.rate		= 26000000,
+-	.parent		= &osc_ck,
+-	.flags		= CLOCK_IN_OMAP243X | RATE_FIXED,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_MDM,
+-	.enable_bit	= 1,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-/*
+- * L4 clock management domain
+- *
+- * This domain contains lots of interface clocks from the L4 interface, some
+- * functional clocks.	Fixed APLL functional source clocks are managed in
+- * this domain.
+- */
+-static struct clk l4_ck = {		/* used both as an ick and fck */
+-	.name		= "l4_ck",
+-	.parent		= &core_l3_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
+-				DELAYED_APP | RATE_PROPAGATES,
+-	.rate_offset	= 5,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk ssi_l4_ick = {
+-	.name		= "ssi_l4_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,	/* bit 1 */
+-	.enable_bit	= 1,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-/*
+- * DSS clock domain
+- * CLOCKs:
+- * DSS_L4_ICLK, DSS_L3_ICLK,
+- * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK
+- *
+- * DSS is both initiator and target.
+- */
+-static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
+-	.name		= "dss_ick",
+-	.parent		= &l4_ck,	/* really both l3 and l4 */
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 0,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk dss1_fck = {
+-	.name		= "dss1_fck",
+-	.parent		= &core_ck,		/* Core or sys */
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 0,
+-	.rate_offset	= 8,
+-	.src_offset	= 8,
+-	.recalc		= &omap2_clksel_recalc,
+-};
+-
+-static struct clk dss2_fck = {		/* Alt clk used in power management */
+-	.name		= "dss2_fck",
+-	.parent		= &sys_ck,		/* fixed at sys_ck or 48MHz */
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_CKCTL | CM_CORE_SEL1 | RATE_FIXED |
+-				DELAYED_APP,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 1,
+-	.src_offset	= 13,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk dss_54m_fck = {	/* Alt clk used in power management */
+-	.name		= "dss_54m_fck",	/* 54m tv clk */
+-	.parent		= &func_54m_ck,
+-	.rate		= 54000000,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				RATE_FIXED | RATE_PROPAGATES,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 2,
+-	.recalc		= &omap2_propagate_rate,
+-};
+-
+-/*
+- * CORE power domain ICLK & FCLK defines.
+- * Many of the these can have more than one possible parent. Entries
+- * here will likely have an L4 interface parent, and may have multiple
+- * functional clock parents.
+- */
+-static struct clk gpt1_ick = {
+-	.name		= "gpt1_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_WKUP,	/* Bit0 */
+-	.enable_bit	= 0,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt1_fck = {
+-	.name		= "gpt1_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_WKUP_SEL1,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_WKUP,	/* Bit0 */
+-	.enable_bit	= 0,
+-	.src_offset	= 0,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt2_ick = {
+-	.name		= "gpt2_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	/* Bit4 */
+-	.enable_bit	= 4,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt2_fck = {
+-	.name		= "gpt2_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 4,
+-	.src_offset	= 2,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt3_ick = {
+-	.name		= "gpt3_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	/* Bit5 */
+-	.enable_bit	= 5,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt3_fck = {
+-	.name		= "gpt3_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 5,
+-	.src_offset	= 4,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt4_ick = {
+-	.name		= "gpt4_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	/* Bit6 */
+-	.enable_bit	= 6,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt4_fck = {
+-	.name		= "gpt4_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 6,
+-	.src_offset	= 6,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt5_ick = {
+-	.name		= "gpt5_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	 /* Bit7 */
+-	.enable_bit	= 7,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt5_fck = {
+-	.name		= "gpt5_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 7,
+-	.src_offset	= 8,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt6_ick = {
+-	.name		= "gpt6_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_bit	= 8,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	 /* bit8 */
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt6_fck = {
+-	.name		= "gpt6_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 8,
+-	.src_offset	= 10,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt7_ick = {
+-	.name		= "gpt7_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	 /* bit9 */
+-	.enable_bit	= 9,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt7_fck = {
+-	.name		= "gpt7_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 9,
+-	.src_offset	= 12,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt8_ick = {
+-	.name		= "gpt8_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	 /* bit10 */
+-	.enable_bit	= 10,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt8_fck = {
+-	.name		= "gpt8_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 10,
+-	.src_offset	= 14,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt9_ick = {
+-	.name		= "gpt9_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 11,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt9_fck = {
+-	.name		= "gpt9_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-					CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 11,
+-	.src_offset	= 16,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt10_ick = {
+-	.name		= "gpt10_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 12,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt10_fck = {
+-	.name		= "gpt10_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-					CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 12,
+-	.src_offset	= 18,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt11_ick = {
+-	.name		= "gpt11_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 13,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt11_fck = {
+-	.name		= "gpt11_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-					CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 13,
+-	.src_offset	= 20,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt12_ick = {
+-	.name		= "gpt12_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	 /* bit14 */
+-	.enable_bit	= 14,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt12_fck = {
+-	.name		= "gpt12_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-					CM_CORE_SEL2,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 14,
+-	.src_offset	= 22,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp1_ick = {
+-	.name		= "mcbsp1_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_bit	= 15,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,	 /* bit16 */
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp1_fck = {
+-	.name		= "mcbsp1_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_bit	= 15,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp2_ick = {
+-	.name		= "mcbsp2_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_bit	= 16,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp2_fck = {
+-	.name		= "mcbsp2_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_bit	= 16,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp3_ick = {
+-	.name		= "mcbsp3_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 3,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp3_fck = {
+-	.name		= "mcbsp3_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 3,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp4_ick = {
+-	.name		= "mcbsp4_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 4,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp4_fck = {
+-	.name		= "mcbsp4_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 4,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp5_ick = {
+-	.name		= "mcbsp5_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 5,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp5_fck = {
+-	.name		= "mcbsp5_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 5,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi1_ick = {
+-	.name		= "mcspi_ick",
+-	.id		= 1,
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 17,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi1_fck = {
+-	.name		= "mcspi_fck",
+-	.id		= 1,
+-	.parent		= &func_48m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 17,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi2_ick = {
+-	.name		= "mcspi_ick",
+-	.id		= 2,
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 18,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi2_fck = {
+-	.name		= "mcspi_fck",
+-	.id		= 2,
+-	.parent		= &func_48m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 18,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi3_ick = {
+-	.name		= "mcspi_ick",
+-	.id		= 3,
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 9,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi3_fck = {
+-	.name		= "mcspi_fck",
+-	.id		= 3,
+-	.parent		= &func_48m_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 9,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart1_ick = {
+-	.name		= "uart1_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 21,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart1_fck = {
+-	.name		= "uart1_fck",
+-	.parent		= &func_48m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 21,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart2_ick = {
+-	.name		= "uart2_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 22,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart2_fck = {
+-	.name		= "uart2_fck",
+-	.parent		= &func_48m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 22,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart3_ick = {
+-	.name		= "uart3_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 2,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart3_fck = {
+-	.name		= "uart3_fck",
+-	.parent		= &func_48m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 2,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpios_ick = {
+-	.name		= "gpios_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_WKUP,
+-	.enable_bit	= 2,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpios_fck = {
+-	.name		= "gpios_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_WKUP,
+-	.enable_bit	= 2,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mpu_wdt_ick = {
+-	.name		= "mpu_wdt_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_WKUP,
+-	.enable_bit	= 3,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mpu_wdt_fck = {
+-	.name		= "mpu_wdt_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN_WKUP,
+-	.enable_bit	= 3,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk sync_32k_ick = {
+-	.name		= "sync_32k_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_WKUP,
+-	.enable_bit	= 1,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-static struct clk wdt1_ick = {
+-	.name		= "wdt1_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_WKUP,
+-	.enable_bit	= 4,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-static struct clk omapctrl_ick = {
+-	.name		= "omapctrl_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_WKUP,
+-	.enable_bit	= 5,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-static struct clk icr_ick = {
+-	.name		= "icr_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN_WKUP,
+-	.enable_bit	= 6,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk cam_ick = {
+-	.name		= "cam_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 31,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk cam_fck = {
+-	.name		= "cam_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 31,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mailboxes_ick = {
+-	.name		= "mailboxes_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 30,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk wdt4_ick = {
+-	.name		= "wdt4_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 29,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk wdt4_fck = {
+-	.name		= "wdt4_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 29,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk wdt3_ick = {
+-	.name		= "wdt3_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 28,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk wdt3_fck = {
+-	.name		= "wdt3_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 28,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mspro_ick = {
+-	.name		= "mspro_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 27,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mspro_fck = {
+-	.name		= "mspro_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 27,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmc_ick = {
+-	.name		= "mmc_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 26,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmc_fck = {
+-	.name		= "mmc_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 26,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk fac_ick = {
+-	.name		= "fac_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 25,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk fac_fck = {
+-	.name		= "fac_fck",
+-	.parent		= &func_12m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 25,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk eac_ick = {
+-	.name		= "eac_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 24,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk eac_fck = {
+-	.name		= "eac_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 24,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk hdq_ick = {
+-	.name		= "hdq_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 23,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk hdq_fck = {
+-	.name		= "hdq_fck",
+-	.parent		= &func_12m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 23,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2c2_ick = {
+-	.name		= "i2c_ick",
+-	.id		= 2,
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 20,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2c2_fck = {
+-	.name		= "i2c_fck",
+-	.id		= 2,
+-	.parent		= &func_12m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 20,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2chs2_fck = {
+-	.name		= "i2chs2_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 20,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2c1_ick = {
+-	.name		= "i2c_ick",
+-	.id		= 1,
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 19,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2c1_fck = {
+-	.name		= "i2c_fck",
+-	.id		= 1,
+-	.parent		= &func_12m_ck,
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 19,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2chs1_fck = {
+-	.name		= "i2chs1_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 19,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk vlynq_ick = {
+-	.name		= "vlynq_ick",
+-	.parent		= &core_l3_ck,
+-	.flags		= CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
+-	.enable_bit	= 3,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk vlynq_fck = {
+-	.name		= "vlynq_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP242X  | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
+-	.enable_bit	= 3,
+-	.src_offset	= 15,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk sdrc_ick = {
+-	.name		= "sdrc_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN3_CORE,
+-	.enable_bit	= 2,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk des_ick = {
+-	.name		= "des_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN4_CORE,
+-	.enable_bit	= 0,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk sha_ick = {
+-	.name		= "sha_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN4_CORE,
+-	.enable_bit	= 1,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk rng_ick = {
+-	.name		= "rng_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN4_CORE,
+-	.enable_bit	= 2,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk aes_ick = {
+-	.name		= "aes_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN4_CORE,
+-	.enable_bit	= 3,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk pka_ick = {
+-	.name		= "pka_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN4_CORE,
+-	.enable_bit	= 4,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk usb_fck = {
+-	.name		= "usb_fck",
+-	.parent		= &func_48m_ck,
+-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 0,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk usbhs_ick = {
+-	.name		= "usbhs_ick",
+-	.parent		= &core_l3_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 6,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmchs1_ick = {
+-	.name		= "mmchs1_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 7,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmchs1_fck = {
+-	.name		= "mmchs1_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 7,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmchs2_ick = {
+-	.name		= "mmchs2_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 8,
+-	.recalc		= &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmchs2_fck = {
+-	.name		= "mmchs2_fck",
+-	.parent		= &func_96m_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 8,
+-	.recalc		= &omap2_followparent_recalc,
+-};
++#ifdef CONFIG_OMAP_RESET_CLOCKS
++void omap2_clk_disable_unused(struct clk *clk);
++#else
++#define omap2_clk_disable_unused	NULL
++#endif
+ 
+-static struct clk gpio5_ick = {
+-	.name		= "gpio5_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 10,
+-	.recalc		= &omap2_followparent_recalc,
+-};
++void omap2_clksel_recalc(struct clk *clk);
++void omap2_init_clksel_parent(struct clk *clk);
++u32 omap2_clksel_get_divisor(struct clk *clk);
++u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
++				u32 *new_div);
++u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val);
++u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
++void omap2_fixed_divisor_recalc(struct clk *clk);
++long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
++int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
++u32 omap2_get_dpll_rate(struct clk *clk);
++int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
+ 
+-static struct clk gpio5_fck = {
+-	.name		= "gpio5_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 10,
+-	.recalc		= &omap2_followparent_recalc,
+-};
++extern u8 cpu_mask;
+ 
+-static struct clk mdm_intc_ick = {
+-	.name		= "mdm_intc_ick",
+-	.parent		= &l4_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_ICLKEN2_CORE,
+-	.enable_bit	= 11,
+-	.recalc		= &omap2_followparent_recalc,
++/* clksel_rate data common to 24xx/343x */
++static const struct clksel_rate gpt_32k_rates[] = {
++	 { .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
++	 { .div = 0 }
+ };
+ 
+-static struct clk mmchsdb1_fck = {
+-	.name		= "mmchsdb1_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 16,
+-	.recalc		= &omap2_followparent_recalc,
++static const struct clksel_rate gpt_sys_rates[] = {
++	 { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
++	 { .div = 0 }
+ };
+ 
+-static struct clk mmchsdb2_fck = {
+-	.name		= "mmchsdb2_fck",
+-	.parent		= &func_32k_ck,
+-	.flags		= CLOCK_IN_OMAP243X,
+-	.enable_reg	= (void __iomem *)&CM_FCLKEN2_CORE,
+-	.enable_bit	= 17,
+-	.recalc		= &omap2_followparent_recalc,
++static const struct clksel_rate gfx_l3_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X },
++	{ .div = 2, .val = 2, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 3, .val = 3, .flags = RATE_IN_243X | RATE_IN_343X },
++	{ .div = 4, .val = 4, .flags = RATE_IN_243X | RATE_IN_343X },
++	{ .div = 0 }
+ };
+ 
+-/*
+- * This clock is a composite clock which does entire set changes then
+- * forces a rebalance. It keys on the MPU speed, but it really could
+- * be any key speed part of a set in the rate table.
+- *
+- * to really change a set, you need memory table sets which get changed
+- * in sram, pre-notifiers & post notifiers, changing the top set, without
+- * having low level display recalc's won't work... this is why dpm notifiers
+- * work, isr's off, walk a list of clocks already _off_ and not messing with
+- * the bus.
+- *
+- * This clock should have no parent. It embodies the entire upper level
+- * active set. A parent will mess up some of the init also.
+- */
+-static struct clk virt_prcm_set = {
+-	.name		= "virt_prcm_set",
+-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+-				VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP,
+-	.parent		= &mpu_ck,	/* Indexed by mpu speed, no parent */
+-	.recalc		= &omap2_mpu_recalc,	/* sets are keyed on mpu rate */
+-	.set_rate	= &omap2_select_table_rate,
+-	.round_rate	= &omap2_round_to_table_rate,
+-};
+-
+-static struct clk *onchip_clks[] = {
+-	/* external root sources */
+-	&func_32k_ck,
+-	&osc_ck,
+-	&sys_ck,
+-	&alt_ck,
+-	/* internal analog sources */
+-	&dpll_ck,
+-	&apll96_ck,
+-	&apll54_ck,
+-	/* internal prcm root sources */
+-	&func_54m_ck,
+-	&core_ck,
+-	&sleep_ck,
+-	&func_96m_ck,
+-	&func_48m_ck,
+-	&func_12m_ck,
+-	&wdt1_osc_ck,
+-	&sys_clkout,
+-	&sys_clkout2,
+-	&emul_ck,
+-	/* mpu domain clocks */
+-	&mpu_ck,
+-	/* dsp domain clocks */
+-	&iva2_1_fck,		/* 2430 */
+-	&iva2_1_ick,
+-	&dsp_ick,		/* 2420 */
+-	&dsp_fck,
+-	&iva1_ifck,
+-	&iva1_mpu_int_ifck,
+-	/* GFX domain clocks */
+-	&gfx_3d_fck,
+-	&gfx_2d_fck,
+-	&gfx_ick,
+-	/* Modem domain clocks */
+-	&mdm_ick,
+-	&mdm_osc_ck,
+-	/* DSS domain clocks */
+-	&dss_ick,
+-	&dss1_fck,
+-	&dss2_fck,
+-	&dss_54m_fck,
+-	/* L3 domain clocks */
+-	&core_l3_ck,
+-	&ssi_ssr_sst_fck,
+-	&usb_l4_ick,
+-	/* L4 domain clocks */
+-	&l4_ck,			/* used as both core_l4 and wu_l4 */
+-	&ssi_l4_ick,
+-	/* virtual meta-group clock */
+-	&virt_prcm_set,
+-	/* general l4 interface ck, multi-parent functional clk */
+-	&gpt1_ick,
+-	&gpt1_fck,
+-	&gpt2_ick,
+-	&gpt2_fck,
+-	&gpt3_ick,
+-	&gpt3_fck,
+-	&gpt4_ick,
+-	&gpt4_fck,
+-	&gpt5_ick,
+-	&gpt5_fck,
+-	&gpt6_ick,
+-	&gpt6_fck,
+-	&gpt7_ick,
+-	&gpt7_fck,
+-	&gpt8_ick,
+-	&gpt8_fck,
+-	&gpt9_ick,
+-	&gpt9_fck,
+-	&gpt10_ick,
+-	&gpt10_fck,
+-	&gpt11_ick,
+-	&gpt11_fck,
+-	&gpt12_ick,
+-	&gpt12_fck,
+-	&mcbsp1_ick,
+-	&mcbsp1_fck,
+-	&mcbsp2_ick,
+-	&mcbsp2_fck,
+-	&mcbsp3_ick,
+-	&mcbsp3_fck,
+-	&mcbsp4_ick,
+-	&mcbsp4_fck,
+-	&mcbsp5_ick,
+-	&mcbsp5_fck,
+-	&mcspi1_ick,
+-	&mcspi1_fck,
+-	&mcspi2_ick,
+-	&mcspi2_fck,
+-	&mcspi3_ick,
+-	&mcspi3_fck,
+-	&uart1_ick,
+-	&uart1_fck,
+-	&uart2_ick,
+-	&uart2_fck,
+-	&uart3_ick,
+-	&uart3_fck,
+-	&gpios_ick,
+-	&gpios_fck,
+-	&mpu_wdt_ick,
+-	&mpu_wdt_fck,
+-	&sync_32k_ick,
+-	&wdt1_ick,
+-	&omapctrl_ick,
+-	&icr_ick,
+-	&cam_fck,
+-	&cam_ick,
+-	&mailboxes_ick,
+-	&wdt4_ick,
+-	&wdt4_fck,
+-	&wdt3_ick,
+-	&wdt3_fck,
+-	&mspro_ick,
+-	&mspro_fck,
+-	&mmc_ick,
+-	&mmc_fck,
+-	&fac_ick,
+-	&fac_fck,
+-	&eac_ick,
+-	&eac_fck,
+-	&hdq_ick,
+-	&hdq_fck,
+-	&i2c1_ick,
+-	&i2c1_fck,
+-	&i2chs1_fck,
+-	&i2c2_ick,
+-	&i2c2_fck,
+-	&i2chs2_fck,
+-	&vlynq_ick,
+-	&vlynq_fck,
+-	&sdrc_ick,
+-	&des_ick,
+-	&sha_ick,
+-	&rng_ick,
+-	&aes_ick,
+-	&pka_ick,
+-	&usb_fck,
+-	&usbhs_ick,
+-	&mmchs1_ick,
+-	&mmchs1_fck,
+-	&mmchs2_ick,
+-	&mmchs2_fck,
+-	&gpio5_ick,
+-	&gpio5_fck,
+-	&mdm_intc_ick,
+-	&mmchsdb1_fck,
+-	&mmchsdb2_fck,
+-};
+ 
+ #endif
+diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
+new file mode 100644
+index 0000000..ece32d8
+--- /dev/null
++++ b/arch/arm/mach-omap2/clock24xx.c
+@@ -0,0 +1,539 @@
++/*
++ *  linux/arch/arm/mach-omap2/clock.c
++ *
++ *  Copyright (C) 2005-2008 Texas Instruments, Inc.
++ *  Copyright (C) 2004-2008 Nokia Corporation
++ *
++ *  Contacts:
++ *  Richard Woodruff <r-woodruff2 at ti.com>
++ *  Paul Walmsley
++ *
++ *  Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
++ *  Gordon McNutt and RidgeRun, 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.
++ */
++#undef DEBUG
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <linux/list.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++
++#include <linux/io.h>
++#include <linux/cpufreq.h>
++
++#include <asm/arch/clock.h>
++#include <asm/arch/sram.h>
++#include <asm/div64.h>
++#include <asm/bitops.h>
++
++#include "memory.h"
++#include "clock.h"
++#include "clock24xx.h"
++#include "prm.h"
++#include "prm-regbits-24xx.h"
++#include "cm.h"
++#include "cm-regbits-24xx.h"
++
++/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
++#define EN_APLL_STOPPED			0
++#define EN_APLL_LOCKED			3
++
++/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
++#define APLLS_CLKIN_19_2MHZ		0
++#define APLLS_CLKIN_13MHZ		2
++#define APLLS_CLKIN_12MHZ		3
++
++/* #define DOWN_VARIABLE_DPLL 1 */		/* Experimental */
++
++static struct prcm_config *curr_prcm_set;
++static struct clk *vclk;
++static struct clk *sclk;
++
++/*-------------------------------------------------------------------------
++ * Omap24xx specific clock functions
++ *-------------------------------------------------------------------------*/
++
++/* This actually returns the rate of core_ck, not dpll_ck. */
++static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
++{
++	long long dpll_clk;
++	u8 amult;
++
++	dpll_clk = omap2_get_dpll_rate(tclk);
++
++	amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
++	amult &= OMAP24XX_CORE_CLK_SRC_MASK;
++	dpll_clk *= amult;
++
++	return dpll_clk;
++}
++
++static int omap2_enable_osc_ck(struct clk *clk)
++{
++	u32 pcc;
++
++	pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
++
++	__raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK,
++		      OMAP24XX_PRCM_CLKSRC_CTRL);
++
++	return 0;
++}
++
++static void omap2_disable_osc_ck(struct clk *clk)
++{
++	u32 pcc;
++
++	pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
++
++	__raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK,
++		      OMAP24XX_PRCM_CLKSRC_CTRL);
++}
++
++#ifdef OLD_CK
++/* Recalculate SYST_CLK */
++static void omap2_sys_clk_recalc(struct clk * clk)
++{
++	u32 div = PRCM_CLKSRC_CTRL;
++	div &= (1 << 7) | (1 << 6);	/* Test if ext clk divided by 1 or 2 */
++	div >>= clk->rate_offset;
++	clk->rate = (clk->parent->rate / div);
++	propagate_rate(clk);
++}
++#endif	/* OLD_CK */
++
++/* Enable an APLL if off */
++static int omap2_clk_fixed_enable(struct clk *clk)
++{
++	u32 cval, apll_mask;
++
++	apll_mask = EN_APLL_LOCKED << clk->enable_bit;
++
++	cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
++
++	if ((cval & apll_mask) == apll_mask)
++		return 0;   /* apll already enabled */
++
++	cval &= ~apll_mask;
++	cval |= apll_mask;
++	cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
++
++	if (clk == &apll96_ck)
++		cval = OMAP24XX_ST_96M_APLL;
++	else if (clk == &apll54_ck)
++		cval = OMAP24XX_ST_54M_APLL;
++
++	omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
++			    clk->name);
++
++	/*
++	 * REVISIT: Should we return an error code if omap2_wait_clock_ready()
++	 * fails?
++	 */
++	return 0;
++}
++
++/* Stop APLL */
++static void omap2_clk_fixed_disable(struct clk *clk)
++{
++	u32 cval;
++
++	cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
++	cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
++	cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
++}
++
++/*
++ * Uses the current prcm set to tell if a rate is valid.
++ * You can go slower, but not faster within a given rate set.
++ */
++static u32 omap2_dpll_round_rate(unsigned long target_rate)
++{
++	u32 high, low, core_clk_src;
++
++	core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
++	core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
++
++	if (core_clk_src == CORE_CLK_SRC_DPLL) {	/* DPLL clockout */
++		high = curr_prcm_set->dpll_speed * 2;
++		low = curr_prcm_set->dpll_speed;
++	} else {				/* DPLL clockout x 2 */
++		high = curr_prcm_set->dpll_speed;
++		low = curr_prcm_set->dpll_speed / 2;
++	}
++
++#ifdef DOWN_VARIABLE_DPLL
++	if (target_rate > high)
++		return high;
++	else
++		return target_rate;
++#else
++	if (target_rate > low)
++		return high;
++	else
++		return low;
++#endif
++
++}
++
++static void omap2_dpll_recalc(struct clk *clk)
++{
++	clk->rate = omap2_get_dpll_rate_24xx(clk);
++
++	propagate_rate(clk);
++}
++
++static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate)
++{
++	u32 cur_rate, low, mult, div, valid_rate, done_rate;
++	u32 bypass = 0;
++	struct prcm_config tmpset;
++	const struct dpll_data *dd;
++	unsigned long flags;
++	int ret = -EINVAL;
++
++	local_irq_save(flags);
++	cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
++	mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
++	mult &= OMAP24XX_CORE_CLK_SRC_MASK;
++
++	if ((rate == (cur_rate / 2)) && (mult == 2)) {
++		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
++	} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
++		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
++	} else if (rate != cur_rate) {
++		valid_rate = omap2_dpll_round_rate(rate);
++		if (valid_rate != rate)
++			goto dpll_exit;
++
++		if (mult == 1)
++			low = curr_prcm_set->dpll_speed;
++		else
++			low = curr_prcm_set->dpll_speed / 2;
++
++		dd = clk->dpll_data;
++		if (!dd)
++			goto dpll_exit;
++
++		tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
++		tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
++					   dd->div1_mask);
++		div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
++		tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
++		tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
++		if (rate > low) {
++			tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
++			mult = ((rate / 2) / 1000000);
++			done_rate = CORE_CLK_SRC_DPLL_X2;
++		} else {
++			tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
++			mult = (rate / 1000000);
++			done_rate = CORE_CLK_SRC_DPLL;
++		}
++		tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
++		tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));
++
++		/* Worst case */
++		tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;
++
++		if (rate == curr_prcm_set->xtal_speed)	/* If asking for 1-1 */
++			bypass = 1;
++
++		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */
++
++		/* Force dll lock mode */
++		omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
++			       bypass);
++
++		/* Errata: ret dll entry state */
++		omap2_init_memory_params(omap2_dll_force_needed());
++		omap2_reprogram_sdrc(done_rate, 0);
++	}
++	omap2_dpll_recalc(&dpll_ck);
++	ret = 0;
++
++dpll_exit:
++	local_irq_restore(flags);
++	return(ret);
++}
++
++/**
++ * omap2_table_mpu_recalc - just return the MPU speed
++ * @clk: virt_prcm_set struct clk
++ *
++ * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
++ */
++static void omap2_table_mpu_recalc(struct clk *clk)
++{
++	clk->rate = curr_prcm_set->mpu_speed;
++}
++
++/*
++ * Look for a rate equal or less than the target rate given a configuration set.
++ *
++ * What's not entirely clear is "which" field represents the key field.
++ * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
++ * just uses the ARM rates.
++ */
++static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
++{
++	struct prcm_config *ptr;
++	long highest_rate;
++
++	if (clk != &virt_prcm_set)
++		return -EINVAL;
++
++	highest_rate = -EINVAL;
++
++	for (ptr = rate_table; ptr->mpu_speed; ptr++) {
++		if (!(ptr->flags & cpu_mask))
++			continue;
++		if (ptr->xtal_speed != sys_ck.rate)
++			continue;
++
++		highest_rate = ptr->mpu_speed;
++
++		/* Can check only after xtal frequency check */
++		if (ptr->mpu_speed <= rate)
++			break;
++	}
++	return highest_rate;
++}
++
++/* Sets basic clocks based on the specified rate */
++static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
++{
++	u32 cur_rate, done_rate, bypass = 0, tmp;
++	struct prcm_config *prcm;
++	unsigned long found_speed = 0;
++	unsigned long flags;
++
++	if (clk != &virt_prcm_set)
++		return -EINVAL;
++
++	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
++		if (!(prcm->flags & cpu_mask))
++			continue;
++
++		if (prcm->xtal_speed != sys_ck.rate)
++			continue;
++
++		if (prcm->mpu_speed <= rate) {
++			found_speed = prcm->mpu_speed;
++			break;
++		}
++	}
++
++	if (!found_speed) {
++		printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
++		       rate / 1000000);
++		return -EINVAL;
++	}
++
++	curr_prcm_set = prcm;
++	cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
++
++	if (prcm->dpll_speed == cur_rate / 2) {
++		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
++	} else if (prcm->dpll_speed == cur_rate * 2) {
++		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
++	} else if (prcm->dpll_speed != cur_rate) {
++		local_irq_save(flags);
++
++		if (prcm->dpll_speed == prcm->xtal_speed)
++			bypass = 1;
++
++		if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
++		    CORE_CLK_SRC_DPLL_X2)
++			done_rate = CORE_CLK_SRC_DPLL_X2;
++		else
++			done_rate = CORE_CLK_SRC_DPLL;
++
++		/* MPU divider */
++		cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
++
++		/* dsp + iva1 div(2420), iva2.1(2430) */
++		cm_write_mod_reg(prcm->cm_clksel_dsp,
++				 OMAP24XX_DSP_MOD, CM_CLKSEL);
++
++		cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
++
++		/* Major subsystem dividers */
++		tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
++		cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1);
++		if (cpu_is_omap2430())
++			cm_write_mod_reg(prcm->cm_clksel_mdm,
++					 OMAP2430_MDM_MOD, CM_CLKSEL);
++
++		/* x2 to enter init_mem */
++		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
++
++		omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
++			       bypass);
++
++		omap2_init_memory_params(omap2_dll_force_needed());
++		omap2_reprogram_sdrc(done_rate, 0);
++
++		local_irq_restore(flags);
++	}
++	omap2_dpll_recalc(&dpll_ck);
++
++	return 0;
++}
++
++static struct clk_functions omap2_clk_functions = {
++	.clk_enable		= omap2_clk_enable,
++	.clk_disable		= omap2_clk_disable,
++	.clk_round_rate		= omap2_clk_round_rate,
++	.clk_set_rate		= omap2_clk_set_rate,
++	.clk_set_parent		= omap2_clk_set_parent,
++	.clk_disable_unused	= omap2_clk_disable_unused,
++};
++
++static u32 omap2_get_apll_clkin(void)
++{
++	u32 aplls, sclk = 0;
++
++	aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
++	aplls &= OMAP24XX_APLLS_CLKIN_MASK;
++	aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
++
++	if (aplls == APLLS_CLKIN_19_2MHZ)
++		sclk = 19200000;
++	else if (aplls == APLLS_CLKIN_13MHZ)
++		sclk = 13000000;
++	else if (aplls == APLLS_CLKIN_12MHZ)
++		sclk = 12000000;
++
++	return sclk;
++}
++
++static u32 omap2_get_sysclkdiv(void)
++{
++	u32 div;
++
++	div = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
++	div &= OMAP_SYSCLKDIV_MASK;
++	div >>= OMAP_SYSCLKDIV_SHIFT;
++
++	return div;
++}
++
++static void omap2_osc_clk_recalc(struct clk *clk)
++{
++	clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
++	propagate_rate(clk);
++}
++
++static void omap2_sys_clk_recalc(struct clk *clk)
++{
++	clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
++	propagate_rate(clk);
++}
++
++/*
++ * Set clocks for bypass mode for reboot to work.
++ */
++void omap2_clk_prepare_for_reboot(void)
++{
++	u32 rate;
++
++	if (vclk == NULL || sclk == NULL)
++		return;
++
++	rate = clk_get_rate(sclk);
++	clk_set_rate(vclk, rate);
++}
++
++/*
++ * Switch the MPU rate if specified on cmdline.
++ * We cannot do this early until cmdline is parsed.
++ */
++static int __init omap2_clk_arch_init(void)
++{
++	if (!mpurate)
++		return -EINVAL;
++
++	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
++		printk(KERN_ERR "Could not find matching MPU rate\n");
++
++	recalculate_root_clocks();
++
++	printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
++	       "%ld.%01ld/%ld/%ld MHz\n",
++	       (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
++	       (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
++
++	return 0;
++}
++arch_initcall(omap2_clk_arch_init);
++
++int __init omap2_clk_init(void)
++{
++	struct prcm_config *prcm;
++	struct clk **clkp;
++	u32 clkrate;
++
++	if (cpu_is_omap242x())
++		cpu_mask = RATE_IN_242X;
++	else if (cpu_is_omap2430())
++		cpu_mask = RATE_IN_243X;
++
++	clk_init(&omap2_clk_functions);
++
++	omap2_osc_clk_recalc(&osc_ck);
++	omap2_sys_clk_recalc(&sys_ck);
++
++	for (clkp = onchip_24xx_clks;
++	     clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks);
++	     clkp++) {
++
++		if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
++			clk_register(*clkp);
++			continue;
++		}
++
++		if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
++			clk_register(*clkp);
++			continue;
++		}
++	}
++
++	/* Check the MPU rate set by bootloader */
++	clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
++	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
++		if (!(prcm->flags & cpu_mask))
++			continue;
++		if (prcm->xtal_speed != sys_ck.rate)
++			continue;
++		if (prcm->dpll_speed <= clkrate)
++			 break;
++	}
++	curr_prcm_set = prcm;
++
++	recalculate_root_clocks();
++
++	printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
++	       "%ld.%01ld/%ld/%ld MHz\n",
++	       (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
++	       (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
++
++	/*
++	 * Only enable those clocks we will need, let the drivers
++	 * enable other clocks as necessary
++	 */
++	clk_enable_init_clocks();
++
++	/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
++	vclk = clk_get(NULL, "virt_prcm_set");
++	sclk = clk_get(NULL, "sys_ck");
++
++	return 0;
++}
+diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
+new file mode 100644
+index 0000000..88081ed
+--- /dev/null
++++ b/arch/arm/mach-omap2/clock24xx.h
+@@ -0,0 +1,2643 @@
++/*
++ *  linux/arch/arm/mach-omap2/clock24xx.h
++ *
++ *  Copyright (C) 2005-2008 Texas Instruments, Inc.
++ *  Copyright (C) 2004-2008 Nokia Corporation
++ *
++ *  Contacts:
++ *  Richard Woodruff <r-woodruff2 at ti.com>
++ *  Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK24XX_H
++#define __ARCH_ARM_MACH_OMAP2_CLOCK24XX_H
++
++#include "clock.h"
++
++#include "prm.h"
++#include "cm.h"
++#include "prm-regbits-24xx.h"
++#include "cm-regbits-24xx.h"
++#include "sdrc.h"
++
++static void omap2_table_mpu_recalc(struct clk *clk);
++static int omap2_select_table_rate(struct clk *clk, unsigned long rate);
++static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
++static void omap2_sys_clk_recalc(struct clk *clk);
++static void omap2_osc_clk_recalc(struct clk *clk);
++static void omap2_sys_clk_recalc(struct clk *clk);
++static void omap2_dpll_recalc(struct clk *clk);
++static int omap2_clk_fixed_enable(struct clk *clk);
++static void omap2_clk_fixed_disable(struct clk *clk);
++static int omap2_enable_osc_ck(struct clk *clk);
++static void omap2_disable_osc_ck(struct clk *clk);
++static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate);
++
++/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
++ * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
++ * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
++ */
++struct prcm_config {
++	unsigned long xtal_speed;	/* crystal rate */
++	unsigned long dpll_speed;	/* dpll: out*xtal*M/(N-1)table_recalc */
++	unsigned long mpu_speed;	/* speed of MPU */
++	unsigned long cm_clksel_mpu;	/* mpu divider */
++	unsigned long cm_clksel_dsp;	/* dsp+iva1 div(2420), iva2.1(2430) */
++	unsigned long cm_clksel_gfx;	/* gfx dividers */
++	unsigned long cm_clksel1_core;	/* major subsystem dividers */
++	unsigned long cm_clksel1_pll;	/* m,n */
++	unsigned long cm_clksel2_pll;	/* dpllx1 or x2 out */
++	unsigned long cm_clksel_mdm;	/* modem dividers 2430 only */
++	unsigned long base_sdrc_rfr;	/* base refresh timing for a set */
++	unsigned char flags;
++};
++
++/*
++ * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
++ * These configurations are characterized by voltage and speed for clocks.
++ * The device is only validated for certain combinations. One way to express
++ * these combinations is via the 'ratio's' which the clocks operate with
++ * respect to each other. These ratio sets are for a given voltage/DPLL
++ * setting. All configurations can be described by a DPLL setting and a ratio
++ * There are 3 ratio sets for the 2430 and X ratio sets for 2420.
++ *
++ * 2430 differs from 2420 in that there are no more phase synchronizers used.
++ * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs
++ * 2430 (iva2.1, NOdsp, mdm)
++ */
++
++/* Core fields for cm_clksel, not ratio governed */
++#define RX_CLKSEL_DSS1			(0x10 << 8)
++#define RX_CLKSEL_DSS2			(0x0 << 13)
++#define RX_CLKSEL_SSI			(0x5 << 20)
++
++/*-------------------------------------------------------------------------
++ * Voltage/DPLL ratios
++ *-------------------------------------------------------------------------*/
++
++/* 2430 Ratio's, 2430-Ratio Config 1 */
++#define R1_CLKSEL_L3			(4 << 0)
++#define R1_CLKSEL_L4			(2 << 5)
++#define R1_CLKSEL_USB			(4 << 25)
++#define R1_CM_CLKSEL1_CORE_VAL		R1_CLKSEL_USB | RX_CLKSEL_SSI | \
++					RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++					R1_CLKSEL_L4 | R1_CLKSEL_L3
++#define R1_CLKSEL_MPU			(2 << 0)
++#define R1_CM_CLKSEL_MPU_VAL		R1_CLKSEL_MPU
++#define R1_CLKSEL_DSP			(2 << 0)
++#define R1_CLKSEL_DSP_IF		(2 << 5)
++#define R1_CM_CLKSEL_DSP_VAL		R1_CLKSEL_DSP | R1_CLKSEL_DSP_IF
++#define R1_CLKSEL_GFX			(2 << 0)
++#define R1_CM_CLKSEL_GFX_VAL		R1_CLKSEL_GFX
++#define R1_CLKSEL_MDM			(4 << 0)
++#define R1_CM_CLKSEL_MDM_VAL		R1_CLKSEL_MDM
++
++/* 2430-Ratio Config 2 */
++#define R2_CLKSEL_L3			(6 << 0)
++#define R2_CLKSEL_L4			(2 << 5)
++#define R2_CLKSEL_USB			(2 << 25)
++#define R2_CM_CLKSEL1_CORE_VAL		R2_CLKSEL_USB | RX_CLKSEL_SSI | \
++					RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++					R2_CLKSEL_L4 | R2_CLKSEL_L3
++#define R2_CLKSEL_MPU			(2 << 0)
++#define R2_CM_CLKSEL_MPU_VAL		R2_CLKSEL_MPU
++#define R2_CLKSEL_DSP			(2 << 0)
++#define R2_CLKSEL_DSP_IF		(3 << 5)
++#define R2_CM_CLKSEL_DSP_VAL		R2_CLKSEL_DSP | R2_CLKSEL_DSP_IF
++#define R2_CLKSEL_GFX			(2 << 0)
++#define R2_CM_CLKSEL_GFX_VAL		R2_CLKSEL_GFX
++#define R2_CLKSEL_MDM			(6 << 0)
++#define R2_CM_CLKSEL_MDM_VAL		R2_CLKSEL_MDM
++
++/* 2430-Ratio Bootm (BYPASS) */
++#define RB_CLKSEL_L3			(1 << 0)
++#define RB_CLKSEL_L4			(1 << 5)
++#define RB_CLKSEL_USB			(1 << 25)
++#define RB_CM_CLKSEL1_CORE_VAL		RB_CLKSEL_USB | RX_CLKSEL_SSI | \
++					RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++					RB_CLKSEL_L4 | RB_CLKSEL_L3
++#define RB_CLKSEL_MPU			(1 << 0)
++#define RB_CM_CLKSEL_MPU_VAL		RB_CLKSEL_MPU
++#define RB_CLKSEL_DSP			(1 << 0)
++#define RB_CLKSEL_DSP_IF		(1 << 5)
++#define RB_CM_CLKSEL_DSP_VAL		RB_CLKSEL_DSP | RB_CLKSEL_DSP_IF
++#define RB_CLKSEL_GFX			(1 << 0)
++#define RB_CM_CLKSEL_GFX_VAL		RB_CLKSEL_GFX
++#define RB_CLKSEL_MDM			(1 << 0)
++#define RB_CM_CLKSEL_MDM_VAL		RB_CLKSEL_MDM
++
++/* 2420 Ratio Equivalents */
++#define RXX_CLKSEL_VLYNQ		(0x12 << 15)
++#define RXX_CLKSEL_SSI			(0x8 << 20)
++
++/* 2420-PRCM III 532MHz core */
++#define RIII_CLKSEL_L3			(4 << 0)	/* 133MHz */
++#define RIII_CLKSEL_L4			(2 << 5)	/* 66.5MHz */
++#define RIII_CLKSEL_USB			(4 << 25)	/* 33.25MHz */
++#define RIII_CM_CLKSEL1_CORE_VAL	RIII_CLKSEL_USB | RXX_CLKSEL_SSI | \
++					RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \
++					RX_CLKSEL_DSS1 | RIII_CLKSEL_L4 | \
++					RIII_CLKSEL_L3
++#define RIII_CLKSEL_MPU			(2 << 0)	/* 266MHz */
++#define RIII_CM_CLKSEL_MPU_VAL		RIII_CLKSEL_MPU
++#define RIII_CLKSEL_DSP			(3 << 0)	/* c5x - 177.3MHz */
++#define RIII_CLKSEL_DSP_IF		(2 << 5)	/* c5x - 88.67MHz */
++#define RIII_SYNC_DSP			(1 << 7)	/* Enable sync */
++#define RIII_CLKSEL_IVA			(6 << 8)	/* iva1 - 88.67MHz */
++#define RIII_SYNC_IVA			(1 << 13)	/* Enable sync */
++#define RIII_CM_CLKSEL_DSP_VAL		RIII_SYNC_IVA | RIII_CLKSEL_IVA | \
++					RIII_SYNC_DSP | RIII_CLKSEL_DSP_IF | \
++					RIII_CLKSEL_DSP
++#define RIII_CLKSEL_GFX			(2 << 0)	/* 66.5MHz */
++#define RIII_CM_CLKSEL_GFX_VAL		RIII_CLKSEL_GFX
++
++/* 2420-PRCM II 600MHz core */
++#define RII_CLKSEL_L3			(6 << 0)	/* 100MHz */
++#define RII_CLKSEL_L4			(2 << 5)	/* 50MHz */
++#define RII_CLKSEL_USB			(2 << 25)	/* 50MHz */
++#define RII_CM_CLKSEL1_CORE_VAL		RII_CLKSEL_USB | \
++					RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \
++					RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++					RII_CLKSEL_L4 | RII_CLKSEL_L3
++#define RII_CLKSEL_MPU			(2 << 0)	/* 300MHz */
++#define RII_CM_CLKSEL_MPU_VAL		RII_CLKSEL_MPU
++#define RII_CLKSEL_DSP			(3 << 0)	/* c5x - 200MHz */
++#define RII_CLKSEL_DSP_IF		(2 << 5)	/* c5x - 100MHz */
++#define RII_SYNC_DSP			(0 << 7)	/* Bypass sync */
++#define RII_CLKSEL_IVA			(3 << 8)	/* iva1 - 200MHz */
++#define RII_SYNC_IVA			(0 << 13)	/* Bypass sync */
++#define RII_CM_CLKSEL_DSP_VAL		RII_SYNC_IVA | RII_CLKSEL_IVA | \
++					RII_SYNC_DSP | RII_CLKSEL_DSP_IF | \
++					RII_CLKSEL_DSP
++#define RII_CLKSEL_GFX			(2 << 0)	/* 50MHz */
++#define RII_CM_CLKSEL_GFX_VAL		RII_CLKSEL_GFX
++
++/* 2420-PRCM I 660MHz core */
++#define RI_CLKSEL_L3			(4 << 0)	/* 165MHz */
++#define RI_CLKSEL_L4			(2 << 5)	/* 82.5MHz */
++#define RI_CLKSEL_USB			(4 << 25)	/* 41.25MHz */
++#define RI_CM_CLKSEL1_CORE_VAL		RI_CLKSEL_USB | \
++					RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \
++					RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++					RI_CLKSEL_L4 | RI_CLKSEL_L3
++#define RI_CLKSEL_MPU			(2 << 0)	/* 330MHz */
++#define RI_CM_CLKSEL_MPU_VAL		RI_CLKSEL_MPU
++#define RI_CLKSEL_DSP			(3 << 0)	/* c5x - 220MHz */
++#define RI_CLKSEL_DSP_IF		(2 << 5)	/* c5x - 110MHz */
++#define RI_SYNC_DSP			(1 << 7)	/* Activate sync */
++#define RI_CLKSEL_IVA			(4 << 8)	/* iva1 - 165MHz */
++#define RI_SYNC_IVA			(0 << 13)	/* Bypass sync */
++#define RI_CM_CLKSEL_DSP_VAL		RI_SYNC_IVA | RI_CLKSEL_IVA | \
++					RI_SYNC_DSP | RI_CLKSEL_DSP_IF | \
++					RI_CLKSEL_DSP
++#define RI_CLKSEL_GFX			(1 << 0)	/* 165MHz */
++#define RI_CM_CLKSEL_GFX_VAL		RI_CLKSEL_GFX
++
++/* 2420-PRCM VII (boot) */
++#define RVII_CLKSEL_L3			(1 << 0)
++#define RVII_CLKSEL_L4			(1 << 5)
++#define RVII_CLKSEL_DSS1		(1 << 8)
++#define RVII_CLKSEL_DSS2		(0 << 13)
++#define RVII_CLKSEL_VLYNQ		(1 << 15)
++#define RVII_CLKSEL_SSI			(1 << 20)
++#define RVII_CLKSEL_USB			(1 << 25)
++
++#define RVII_CM_CLKSEL1_CORE_VAL	RVII_CLKSEL_USB | RVII_CLKSEL_SSI | \
++					RVII_CLKSEL_VLYNQ | RVII_CLKSEL_DSS2 | \
++					RVII_CLKSEL_DSS1 | RVII_CLKSEL_L4 | RVII_CLKSEL_L3
++
++#define RVII_CLKSEL_MPU			(1 << 0) /* all divide by 1 */
++#define RVII_CM_CLKSEL_MPU_VAL		RVII_CLKSEL_MPU
++
++#define RVII_CLKSEL_DSP			(1 << 0)
++#define RVII_CLKSEL_DSP_IF		(1 << 5)
++#define RVII_SYNC_DSP			(0 << 7)
++#define RVII_CLKSEL_IVA			(1 << 8)
++#define RVII_SYNC_IVA			(0 << 13)
++#define RVII_CM_CLKSEL_DSP_VAL		RVII_SYNC_IVA | RVII_CLKSEL_IVA | RVII_SYNC_DSP | \
++					RVII_CLKSEL_DSP_IF | RVII_CLKSEL_DSP
++
++#define RVII_CLKSEL_GFX			(1 << 0)
++#define RVII_CM_CLKSEL_GFX_VAL		RVII_CLKSEL_GFX
++
++/*-------------------------------------------------------------------------
++ * 2430 Target modes: Along with each configuration the CPU has several
++ * modes which goes along with them. Modes mainly are the addition of
++ * describe DPLL combinations to go along with a ratio.
++ *-------------------------------------------------------------------------*/
++
++/* Hardware governed */
++#define MX_48M_SRC			(0 << 3)
++#define MX_54M_SRC			(0 << 5)
++#define MX_APLLS_CLIKIN_12		(3 << 23)
++#define MX_APLLS_CLIKIN_13		(2 << 23)
++#define MX_APLLS_CLIKIN_19_2		(0 << 23)
++
++/*
++ * 2430 - standalone, 2*ref*M/(n+1), M/N is for exactness not relock speed
++ * #5a	(ratio1) baseport-target, target DPLL = 266*2 = 532MHz
++ */
++#define M5A_DPLL_MULT_12		(133 << 12)
++#define M5A_DPLL_DIV_12			(5 << 8)
++#define M5A_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M5A_DPLL_DIV_12 | M5A_DPLL_MULT_12 | \
++					MX_APLLS_CLIKIN_12
++#define M5A_DPLL_MULT_13		(61 << 12)
++#define M5A_DPLL_DIV_13			(2 << 8)
++#define M5A_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M5A_DPLL_DIV_13 | M5A_DPLL_MULT_13 | \
++					MX_APLLS_CLIKIN_13
++#define M5A_DPLL_MULT_19		(55 << 12)
++#define M5A_DPLL_DIV_19			(3 << 8)
++#define M5A_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M5A_DPLL_DIV_19 | M5A_DPLL_MULT_19 | \
++					MX_APLLS_CLIKIN_19_2
++/* #5b	(ratio1) target DPLL = 200*2 = 400MHz */
++#define M5B_DPLL_MULT_12		(50 << 12)
++#define M5B_DPLL_DIV_12			(2 << 8)
++#define M5B_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M5B_DPLL_DIV_12 | M5B_DPLL_MULT_12 | \
++					MX_APLLS_CLIKIN_12
++#define M5B_DPLL_MULT_13		(200 << 12)
++#define M5B_DPLL_DIV_13			(12 << 8)
++
++#define M5B_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M5B_DPLL_DIV_13 | M5B_DPLL_MULT_13 | \
++					MX_APLLS_CLIKIN_13
++#define M5B_DPLL_MULT_19		(125 << 12)
++#define M5B_DPLL_DIV_19			(31 << 8)
++#define M5B_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M5B_DPLL_DIV_19 | M5B_DPLL_MULT_19 | \
++					MX_APLLS_CLIKIN_19_2
++/*
++ * #4	(ratio2), DPLL = 399*2 = 798MHz, L3=133MHz
++ */
++#define M4_DPLL_MULT_12			(133 << 12)
++#define M4_DPLL_DIV_12			(3 << 8)
++#define M4_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M4_DPLL_DIV_12 | M4_DPLL_MULT_12 | \
++					MX_APLLS_CLIKIN_12
++
++#define M4_DPLL_MULT_13			(399 << 12)
++#define M4_DPLL_DIV_13			(12 << 8)
++#define M4_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M4_DPLL_DIV_13 | M4_DPLL_MULT_13 | \
++					MX_APLLS_CLIKIN_13
++
++#define M4_DPLL_MULT_19			(145 << 12)
++#define M4_DPLL_DIV_19			(6 << 8)
++#define M4_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M4_DPLL_DIV_19 | M4_DPLL_MULT_19 | \
++					MX_APLLS_CLIKIN_19_2
++
++/*
++ * #3	(ratio2) baseport-target, target DPLL = 330*2 = 660MHz
++ */
++#define M3_DPLL_MULT_12			(55 << 12)
++#define M3_DPLL_DIV_12			(1 << 8)
++#define M3_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M3_DPLL_DIV_12 | M3_DPLL_MULT_12 | \
++					MX_APLLS_CLIKIN_12
++#define M3_DPLL_MULT_13			(76 << 12)
++#define M3_DPLL_DIV_13			(2 << 8)
++#define M3_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M3_DPLL_DIV_13 | M3_DPLL_MULT_13 | \
++					MX_APLLS_CLIKIN_13
++#define M3_DPLL_MULT_19			(17 << 12)
++#define M3_DPLL_DIV_19			(0 << 8)
++#define M3_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M3_DPLL_DIV_19 | M3_DPLL_MULT_19 | \
++					MX_APLLS_CLIKIN_19_2
++
++/*
++ * #2   (ratio1) DPLL = 330*2 = 660MHz, L3=165MHz
++ */
++#define M2_DPLL_MULT_12		        (55 << 12)
++#define M2_DPLL_DIV_12		        (1 << 8)
++#define M2_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M2_DPLL_DIV_12 | M2_DPLL_MULT_12 | \
++					MX_APLLS_CLIKIN_12
++
++/* Speed changes - Used 658.7MHz instead of 660MHz for LP-Refresh M=76 N=2,
++ * relock time issue */
++/* Core frequency changed from 330/165 to 329/164 MHz*/
++#define M2_DPLL_MULT_13		        (76 << 12)
++#define M2_DPLL_DIV_13		        (2 << 8)
++#define M2_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M2_DPLL_DIV_13 | M2_DPLL_MULT_13 | \
++					MX_APLLS_CLIKIN_13
++
++#define M2_DPLL_MULT_19		        (17 << 12)
++#define M2_DPLL_DIV_19		        (0 << 8)
++#define M2_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | \
++					M2_DPLL_DIV_19 | M2_DPLL_MULT_19 | \
++					MX_APLLS_CLIKIN_19_2
++
++/* boot (boot) */
++#define MB_DPLL_MULT			(1 << 12)
++#define MB_DPLL_DIV			(0 << 8)
++#define MB_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
++					MB_DPLL_MULT | MX_APLLS_CLIKIN_12
++
++#define MB_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
++					MB_DPLL_MULT | MX_APLLS_CLIKIN_13
++
++#define MB_CM_CLKSEL1_PLL_19_VAL	MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
++					MB_DPLL_MULT | MX_APLLS_CLIKIN_19
++
++/*
++ * 2430 - chassis (sedna)
++ * 165 (ratio1) same as above #2
++ * 150 (ratio1)
++ * 133 (ratio2) same as above #4
++ * 110 (ratio2) same as above #3
++ * 104 (ratio2)
++ * boot (boot)
++ */
++
++/* PRCM I target DPLL = 2*330MHz = 660MHz */
++#define MI_DPLL_MULT_12			(55 << 12)
++#define MI_DPLL_DIV_12			(1 << 8)
++#define MI_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
++					MI_DPLL_DIV_12 | MI_DPLL_MULT_12 | \
++					MX_APLLS_CLIKIN_12
++
++/*
++ * 2420 Equivalent - mode registers
++ * PRCM II , target DPLL = 2*300MHz = 600MHz
++ */
++#define MII_DPLL_MULT_12		(50 << 12)
++#define MII_DPLL_DIV_12			(1 << 8)
++#define MII_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
++					MII_DPLL_DIV_12 | MII_DPLL_MULT_12 | \
++					MX_APLLS_CLIKIN_12
++#define MII_DPLL_MULT_13		(300 << 12)
++#define MII_DPLL_DIV_13			(12 << 8)
++#define MII_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
++					MII_DPLL_DIV_13 | MII_DPLL_MULT_13 | \
++					MX_APLLS_CLIKIN_13
++
++/* PRCM III target DPLL = 2*266 = 532MHz*/
++#define MIII_DPLL_MULT_12		(133 << 12)
++#define MIII_DPLL_DIV_12		(5 << 8)
++#define MIII_CM_CLKSEL1_PLL_12_VAL	MX_48M_SRC | MX_54M_SRC | \
++					MIII_DPLL_DIV_12 | MIII_DPLL_MULT_12 | \
++					MX_APLLS_CLIKIN_12
++#define MIII_DPLL_MULT_13		(266 << 12)
++#define MIII_DPLL_DIV_13		(12 << 8)
++#define MIII_CM_CLKSEL1_PLL_13_VAL	MX_48M_SRC | MX_54M_SRC | \
++					MIII_DPLL_DIV_13 | MIII_DPLL_MULT_13 | \
++					MX_APLLS_CLIKIN_13
++
++/* PRCM VII (boot bypass) */
++#define MVII_CM_CLKSEL1_PLL_12_VAL	MB_CM_CLKSEL1_PLL_12_VAL
++#define MVII_CM_CLKSEL1_PLL_13_VAL	MB_CM_CLKSEL1_PLL_13_VAL
++
++/* High and low operation value */
++#define MX_CLKSEL2_PLL_2x_VAL		(2 << 0)
++#define MX_CLKSEL2_PLL_1x_VAL		(1 << 0)
++
++/* MPU speed defines */
++#define S12M	12000000
++#define S13M	13000000
++#define S19M	19200000
++#define S26M	26000000
++#define S100M	100000000
++#define S133M	133000000
++#define S150M	150000000
++#define S164M	164000000
++#define S165M	165000000
++#define S199M	199000000
++#define S200M	200000000
++#define S266M	266000000
++#define S300M	300000000
++#define S329M	329000000
++#define S330M	330000000
++#define S399M	399000000
++#define S400M	400000000
++#define S532M	532000000
++#define S600M	600000000
++#define S658M	658000000
++#define S660M	660000000
++#define S798M	798000000
++
++/*-------------------------------------------------------------------------
++ * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
++ * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,
++ * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL,
++ * CM_CLKSEL2_PLL, CM_CLKSEL_MDM
++ *
++ * Filling in table based on H4 boards and 2430-SDPs variants available.
++ * There are quite a few more rates combinations which could be defined.
++ *
++ * When multiple values are defined the start up will try and choose the
++ * fastest one. If a 'fast' value is defined, then automatically, the /2
++ * one should be included as it can be used.	Generally having more that
++ * one fast set does not make sense, as static timings need to be changed
++ * to change the set.	 The exception is the bypass setting which is
++ * availble for low power bypass.
++ *
++ * Note: This table needs to be sorted, fastest to slowest.
++ *-------------------------------------------------------------------------*/
++static struct prcm_config rate_table[] = {
++	/* PRCM I - FAST */
++	{S12M, S660M, S330M, RI_CM_CLKSEL_MPU_VAL,		/* 330MHz ARM */
++		RI_CM_CLKSEL_DSP_VAL, RI_CM_CLKSEL_GFX_VAL,
++		RI_CM_CLKSEL1_CORE_VAL, MI_CM_CLKSEL1_PLL_12_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_165MHz,
++		RATE_IN_242X},
++
++	/* PRCM II - FAST */
++	{S12M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL,		/* 300MHz ARM */
++		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
++		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
++		RATE_IN_242X},
++
++	{S13M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL,		/* 300MHz ARM */
++		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
++		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
++		RATE_IN_242X},
++
++	/* PRCM III - FAST */
++	{S12M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL,		/* 266MHz ARM */
++		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
++		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
++		RATE_IN_242X},
++
++	{S13M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL,		/* 266MHz ARM */
++		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
++		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
++		RATE_IN_242X},
++
++	/* PRCM II - SLOW */
++	{S12M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL,		/* 150MHz ARM */
++		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
++		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
++		RATE_IN_242X},
++
++	{S13M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL,		/* 150MHz ARM */
++		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
++		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
++		RATE_IN_242X},
++
++	/* PRCM III - SLOW */
++	{S12M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL,		/* 133MHz ARM */
++		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
++		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
++		RATE_IN_242X},
++
++	{S13M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL,		/* 133MHz ARM */
++		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
++		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
++		RATE_IN_242X},
++
++	/* PRCM-VII (boot-bypass) */
++	{S12M, S12M, S12M, RVII_CM_CLKSEL_MPU_VAL,		/* 12MHz ARM*/
++		RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
++		RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_12_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS,
++		RATE_IN_242X},
++
++	/* PRCM-VII (boot-bypass) */
++	{S13M, S13M, S13M, RVII_CM_CLKSEL_MPU_VAL,		/* 13MHz ARM */
++		RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
++		RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS,
++		RATE_IN_242X},
++
++	/* PRCM #4 - ratio2 (ES2.1) - FAST */
++	{S13M, S798M, S399M, R2_CM_CLKSEL_MPU_VAL,		/* 399MHz ARM */
++		R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
++		R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, R2_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_133MHz,
++		RATE_IN_243X},
++
++	/* PRCM #2 - ratio1 (ES2) - FAST */
++	{S13M, S658M, S329M, R1_CM_CLKSEL_MPU_VAL,		/* 330MHz ARM */
++		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++		R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_165MHz,
++		RATE_IN_243X},
++
++	/* PRCM #5a - ratio1 - FAST */
++	{S13M, S532M, S266M, R1_CM_CLKSEL_MPU_VAL,		/* 266MHz ARM */
++		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++		R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_133MHz,
++		RATE_IN_243X},
++
++	/* PRCM #5b - ratio1 - FAST */
++	{S13M, S400M, S200M, R1_CM_CLKSEL_MPU_VAL,		/* 200MHz ARM */
++		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++		R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_100MHz,
++		RATE_IN_243X},
++
++	/* PRCM #4 - ratio1 (ES2.1) - SLOW */
++	{S13M, S399M, S199M, R2_CM_CLKSEL_MPU_VAL,		/* 200MHz ARM */
++		R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
++		R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_1x_VAL, R2_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_133MHz,
++		RATE_IN_243X},
++
++	/* PRCM #2 - ratio1 (ES2) - SLOW */
++	{S13M, S329M, S164M, R1_CM_CLKSEL_MPU_VAL,		/* 165MHz ARM */
++		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++		R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_165MHz,
++		RATE_IN_243X},
++
++	/* PRCM #5a - ratio1 - SLOW */
++	{S13M, S266M, S133M, R1_CM_CLKSEL_MPU_VAL,		/* 133MHz ARM */
++		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++		R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_133MHz,
++		RATE_IN_243X},
++
++	/* PRCM #5b - ratio1 - SLOW*/
++	{S13M, S200M, S100M, R1_CM_CLKSEL_MPU_VAL,		/* 100MHz ARM */
++		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++		R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_100MHz,
++		RATE_IN_243X},
++
++	/* PRCM-boot/bypass */
++	{S13M, S13M, S13M, RB_CM_CLKSEL_MPU_VAL,		/* 13Mhz */
++		RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
++		RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_13_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_BYPASS,
++		RATE_IN_243X},
++
++	/* PRCM-boot/bypass */
++	{S12M, S12M, S12M, RB_CM_CLKSEL_MPU_VAL,		/* 12Mhz */
++		RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
++		RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_12_VAL,
++		MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
++		SDRC_RFR_CTRL_BYPASS,
++		RATE_IN_243X},
++
++	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
++};
++
++/*-------------------------------------------------------------------------
++ * 24xx clock tree.
++ *
++ * NOTE:In many cases here we are assigning a 'default' parent.	In many
++ *	cases the parent is selectable.	The get/set parent calls will also
++ *	switch sources.
++ *
++ *	Many some clocks say always_enabled, but they can be auto idled for
++ *	power savings. They will always be available upon clock request.
++ *
++ *	Several sources are given initial rates which may be wrong, this will
++ *	be fixed up in the init func.
++ *
++ *	Things are broadly separated below by clock domains. It is
++ *	noteworthy that most periferals have dependencies on multiple clock
++ *	domains. Many get their interface clocks from the L4 domain, but get
++ *	functional clocks from fixed sources or other core domain derived
++ *	clocks.
++ *-------------------------------------------------------------------------*/
++
++/* Base external input clocks */
++static struct clk func_32k_ck = {
++	.name		= "func_32k_ck",
++	.rate		= 32000,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
++	.recalc		= &propagate_rate,
++};
++
++/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
++static struct clk osc_ck = {		/* (*12, *13, 19.2, *26, 38.4)MHz */
++	.name		= "osc_ck",
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_PROPAGATES,
++	.enable		= &omap2_enable_osc_ck,
++	.disable	= &omap2_disable_osc_ck,
++	.recalc		= &omap2_osc_clk_recalc,
++};
++
++/* With out modem likely 12MHz, with modem likely 13MHz */
++static struct clk sys_ck = {		/* (*12, *13, 19.2, 26, 38.4)MHz */
++	.name		= "sys_ck",		/* ~ ref_clk also */
++	.parent		= &osc_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				ALWAYS_ENABLED | RATE_PROPAGATES,
++	.recalc		= &omap2_sys_clk_recalc,
++};
++
++static struct clk alt_ck = {		/* Typical 54M or 48M, may not exist */
++	.name		= "alt_ck",
++	.rate		= 54000000,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
++	.recalc		= &propagate_rate,
++};
++
++/*
++ * Analog domain root source clocks
++ */
++
++/* dpll_ck, is broken out in to special cases through clksel */
++/* REVISIT: Rate changes on dpll_ck trigger a full set change.	...
++ * deal with this
++ */
++
++static const struct dpll_data dpll_dd = {
++	.mult_div1_reg		= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++	.mult_mask		= OMAP24XX_DPLL_MULT_MASK,
++	.div1_mask		= OMAP24XX_DPLL_DIV_MASK,
++};
++
++static struct clk dpll_ck = {
++	.name		= "dpll_ck",
++	.parent		= &sys_ck,		/* Can be func_32k also */
++	.dpll_data	= &dpll_dd,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap2_dpll_recalc,
++	.set_rate	= &omap2_reprogram_dpll,
++};
++
++static struct clk apll96_ck = {
++	.name		= "apll96_ck",
++	.parent		= &sys_ck,
++	.rate		= 96000000,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
++	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
++	.enable		= &omap2_clk_fixed_enable,
++	.disable	= &omap2_clk_fixed_disable,
++	.recalc		= &propagate_rate,
++};
++
++static struct clk apll54_ck = {
++	.name		= "apll54_ck",
++	.parent		= &sys_ck,
++	.rate		= 54000000,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
++	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
++	.enable		= &omap2_clk_fixed_enable,
++	.disable	= &omap2_clk_fixed_disable,
++	.recalc		= &propagate_rate,
++};
++
++/*
++ * PRCM digital base sources
++ */
++
++/* func_54m_ck */
++
++static const struct clksel_rate func_54m_apll54_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel_rate func_54m_alt_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel func_54m_clksel[] = {
++	{ .parent = &apll54_ck, .rates = func_54m_apll54_rates, },
++	{ .parent = &alt_ck,	.rates = func_54m_alt_rates, },
++	{ .parent = NULL },
++};
++
++static struct clk func_54m_ck = {
++	.name		= "func_54m_ck",
++	.parent		= &apll54_ck,	/* can also be alt_clk */
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP24XX_54M_SOURCE,
++	.clksel		= func_54m_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk core_ck = {
++	.name		= "core_ck",
++	.parent		= &dpll_ck,		/* can also be 32k */
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				ALWAYS_ENABLED | RATE_PROPAGATES,
++	.recalc		= &followparent_recalc,
++};
++
++/* func_96m_ck */
++static const struct clksel_rate func_96m_apll96_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel_rate func_96m_alt_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_243X | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel func_96m_clksel[] = {
++	{ .parent = &apll96_ck,	.rates = func_96m_apll96_rates },
++	{ .parent = &alt_ck,	.rates = func_96m_alt_rates },
++	{ .parent = NULL }
++};
++
++/* The parent of this clock is not selectable on 2420. */
++static struct clk func_96m_ck = {
++	.name		= "func_96m_ck",
++	.parent		= &apll96_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP2430_96M_SOURCE,
++	.clksel		= func_96m_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++/* func_48m_ck */
++
++static const struct clksel_rate func_48m_apll96_rates[] = {
++	{ .div = 2, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel_rate func_48m_alt_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel func_48m_clksel[] = {
++	{ .parent = &apll96_ck,	.rates = func_48m_apll96_rates },
++	{ .parent = &alt_ck, .rates = func_48m_alt_rates },
++	{ .parent = NULL }
++};
++
++static struct clk func_48m_ck = {
++	.name		= "func_48m_ck",
++	.parent		= &apll96_ck,	 /* 96M or Alt */
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP24XX_48M_SOURCE,
++	.clksel		= func_48m_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static struct clk func_12m_ck = {
++	.name		= "func_12m_ck",
++	.parent		= &func_48m_ck,
++	.fixed_div	= 4,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_fixed_divisor_recalc,
++};
++
++/* Secure timer, only available in secure mode */
++static struct clk wdt1_osc_ck = {
++	.name		= "ck_wdt1_osc",
++	.parent		= &osc_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.recalc		= &followparent_recalc,
++};
++
++/*
++ * The common_clkout* clksel_rate structs are common to
++ * sys_clkout, sys_clkout_src, sys_clkout2, and sys_clkout2_src.
++ * sys_clkout2_* are 2420-only, so the
++ * clksel_rate flags fields are inaccurate for those clocks. This is
++ * harmless since access to those clocks are gated by the struct clk
++ * flags fields, which mark them as 2420-only.
++ */
++static const struct clksel_rate common_clkout_src_core_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate common_clkout_src_sys_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate common_clkout_src_96m_rates[] = {
++	{ .div = 1, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate common_clkout_src_54m_rates[] = {
++	{ .div = 1, .val = 3, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel common_clkout_src_clksel[] = {
++	{ .parent = &core_ck,	  .rates = common_clkout_src_core_rates },
++	{ .parent = &sys_ck,	  .rates = common_clkout_src_sys_rates },
++	{ .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
++	{ .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
++	{ .parent = NULL }
++};
++
++static struct clk sys_clkout_src = {
++	.name		= "sys_clkout_src",
++	.parent		= &func_54m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				RATE_PROPAGATES,
++	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
++	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
++	.clksel_mask	= OMAP24XX_CLKOUT_SOURCE_MASK,
++	.clksel		= common_clkout_src_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static const struct clksel_rate common_clkout_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 2, .val = 1, .flags = RATE_IN_24XX },
++	{ .div = 4, .val = 2, .flags = RATE_IN_24XX },
++	{ .div = 8, .val = 3, .flags = RATE_IN_24XX },
++	{ .div = 16, .val = 4, .flags = RATE_IN_24XX },
++	{ .div = 0 },
++};
++
++static const struct clksel sys_clkout_clksel[] = {
++	{ .parent = &sys_clkout_src, .rates = common_clkout_rates },
++	{ .parent = NULL }
++};
++
++static struct clk sys_clkout = {
++	.name		= "sys_clkout",
++	.parent		= &sys_clkout_src,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				PARENT_CONTROLS_CLOCK,
++	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
++	.clksel_mask	= OMAP24XX_CLKOUT_DIV_MASK,
++	.clksel		= sys_clkout_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++/* In 2430, new in 2420 ES2 */
++static struct clk sys_clkout2_src = {
++	.name		= "sys_clkout2_src",
++	.parent		= &func_54m_ck,
++	.flags		= CLOCK_IN_OMAP242X | RATE_PROPAGATES,
++	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
++	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
++	.clksel_mask	= OMAP2420_CLKOUT2_SOURCE_MASK,
++	.clksel		= common_clkout_src_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static const struct clksel sys_clkout2_clksel[] = {
++	{ .parent = &sys_clkout2_src, .rates = common_clkout_rates },
++	{ .parent = NULL }
++};
++
++/* In 2430, new in 2420 ES2 */
++static struct clk sys_clkout2 = {
++	.name		= "sys_clkout2",
++	.parent		= &sys_clkout2_src,
++	.flags		= CLOCK_IN_OMAP242X | PARENT_CONTROLS_CLOCK,
++	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
++	.clksel_mask	= OMAP2420_CLKOUT2_DIV_MASK,
++	.clksel		= sys_clkout2_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static struct clk emul_ck = {
++	.name		= "emul_ck",
++	.parent		= &func_54m_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP24XX_PRCM_CLKEMUL_CTRL,
++	.enable_bit	= OMAP24XX_EMULATION_EN_SHIFT,
++	.recalc		= &followparent_recalc,
++
++};
++
++/*
++ * MPU clock domain
++ *	Clocks:
++ *		MPU_FCLK, MPU_ICLK
++ *		INT_M_FCLK, INT_M_I_CLK
++ *
++ * - Individual clocks are hardware managed.
++ * - Base divider comes from: CM_CLKSEL_MPU
++ *
++ */
++static const struct clksel_rate mpu_core_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
++	{ .div = 4, .val = 4, .flags = RATE_IN_242X },
++	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
++	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
++	{ .div = 0 },
++};
++
++static const struct clksel mpu_clksel[] = {
++	{ .parent = &core_ck, .rates = mpu_core_rates },
++	{ .parent = NULL }
++};
++
++static struct clk mpu_ck = {	/* Control cpu */
++	.name		= "mpu_ck",
++	.parent		= &core_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				ALWAYS_ENABLED | DELAYED_APP |
++				CONFIG_PARTICIPANT | RATE_PROPAGATES,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP24XX_CLKSEL_MPU_MASK,
++	.clksel		= mpu_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate     = &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++/*
++ * DSP (2430-IVA2.1) (2420-UMA+IVA1) clock domain
++ * Clocks:
++ *	2430: IVA2.1_FCLK (really just DSP_FCLK), IVA2.1_ICLK
++ *	2420: UMA_FCLK, UMA_ICLK, IVA_MPU, IVA_COP
++ *
++ * Won't be too specific here. The core clock comes into this block
++ * it is divided then tee'ed. One branch goes directly to xyz enable
++ * controls. The other branch gets further divided by 2 then possibly
++ * routed into a synchronizer and out of clocks abc.
++ */
++static const struct clksel_rate dsp_fck_core_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
++	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
++	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
++	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
++	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
++	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
++	{ .div = 0 },
++};
++
++static const struct clksel dsp_fck_clksel[] = {
++	{ .parent = &core_ck, .rates = dsp_fck_core_rates },
++	{ .parent = NULL }
++};
++
++static struct clk dsp_fck = {
++	.name		= "dsp_fck",
++	.parent		= &core_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP |
++				CONFIG_PARTICIPANT | RATE_PROPAGATES,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP24XX_CLKSEL_DSP_MASK,
++	.clksel		= dsp_fck_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++/* DSP interface clock */
++static const struct clksel_rate dsp_irate_ick_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
++	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
++	{ .div = 0 },
++};
++
++static const struct clksel dsp_irate_ick_clksel[] = {
++	{ .parent = &dsp_fck, .rates = dsp_irate_ick_rates },
++	{ .parent = NULL }
++};
++
++/*
++ * This clock does not exist as such in the TRM, but is added to
++ * separate source selection from  XXX
++ */
++static struct clk dsp_irate_ick = {
++	.name		= "dsp_irate_ick",
++	.parent		= &dsp_fck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP |
++				CONFIG_PARTICIPANT | PARENT_CONTROLS_CLOCK,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
++	.clksel		= dsp_irate_ick_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	      = &omap2_clksel_set_rate
++};
++
++/* 2420 only */
++static struct clk dsp_ick = {
++	.name		= "dsp_ick",	 /* apparently ipi and isp */
++	.parent		= &dsp_irate_ick,
++	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP | CONFIG_PARTICIPANT,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,	      /* for ipi */
++};
++
++/* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */
++static struct clk iva2_1_ick = {
++	.name		= "iva2_1_ick",
++	.parent		= &dsp_irate_ick,
++	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
++};
++
++static struct clk iva1_ifck = {
++	.name		= "iva1_ifck",
++	.parent		= &core_ck,
++	.flags		= CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT |
++				RATE_PROPAGATES | DELAYED_APP,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP2420_CLKSEL_IVA_MASK,
++	.clksel		= dsp_fck_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++/* IVA1 mpu/int/i/f clocks are /2 of parent */
++static struct clk iva1_mpu_int_ifck = {
++	.name		= "iva1_mpu_int_ifck",
++	.parent		= &iva1_ifck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP2420_EN_IVA_MPU_SHIFT,
++	.fixed_div	= 2,
++	.recalc		= &omap2_fixed_divisor_recalc,
++};
++
++/*
++ * L3 clock domain
++ * L3 clocks are used for both interface and functional clocks to
++ * multiple entities. Some of these clocks are completely managed
++ * by hardware, and some others allow software control. Hardware
++ * managed ones general are based on directly CLK_REQ signals and
++ * various auto idle settings. The functional spec sets many of these
++ * as 'tie-high' for their enables.
++ *
++ * I-CLOCKS:
++ *	L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA
++ *	CAM, HS-USB.
++ * F-CLOCK
++ *	SSI.
++ *
++ * GPMC memories and SDRC have timing and clock sensitive registers which
++ * may very well need notification when the clock changes. Currently for low
++ * operating points, these are taken care of in sleep.S.
++ */
++static const struct clksel_rate core_l3_core_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
++	{ .div = 2, .val = 2, .flags = RATE_IN_242X },
++	{ .div = 4, .val = 4, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
++	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
++	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
++	{ .div = 16, .val = 16, .flags = RATE_IN_242X },
++	{ .div = 0 }
++};
++
++static const struct clksel core_l3_clksel[] = {
++	{ .parent = &core_ck, .rates = core_l3_core_rates },
++	{ .parent = NULL }
++};
++
++static struct clk core_l3_ck = {	/* Used for ick and fck, interconnect */
++	.name		= "core_l3_ck",
++	.parent		= &core_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				ALWAYS_ENABLED | DELAYED_APP |
++				CONFIG_PARTICIPANT | RATE_PROPAGATES,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP24XX_CLKSEL_L3_MASK,
++	.clksel		= core_l3_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++/* usb_l4_ick */
++static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
++	{ .div = 2, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
++	{ .div = 0 }
++};
++
++static const struct clksel usb_l4_ick_clksel[] = {
++	{ .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
++	{ .parent = NULL },
++};
++
++static struct clk usb_l4_ick = {	/* FS-USB interface clock */
++	.name		= "usb_l4_ick",
++	.parent		= &core_l3_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				DELAYED_APP | CONFIG_PARTICIPANT,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP24XX_CLKSEL_USB_MASK,
++	.clksel		= usb_l4_ick_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++/*
++ * SSI is in L3 management domain, its direct parent is core not l3,
++ * many core power domain entities are grouped into the L3 clock
++ * domain.
++ * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_CLIK
++ *
++ * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
++ */
++static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
++	{ .div = 2, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
++	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
++	{ .div = 5, .val = 5, .flags = RATE_IN_243X },
++	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
++	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
++	{ .div = 0 }
++};
++
++static const struct clksel ssi_ssr_sst_fck_clksel[] = {
++	{ .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
++	{ .parent = NULL }
++};
++
++static struct clk ssi_ssr_sst_fck = {
++	.name		= "ssi_fck",
++	.parent		= &core_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				DELAYED_APP,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP24XX_CLKSEL_SSI_MASK,
++	.clksel		= ssi_ssr_sst_fck_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++/*
++ * GFX clock domain
++ *	Clocks:
++ * GFX_FCLK, GFX_ICLK
++ * GFX_CG1(2d), GFX_CG2(3d)
++ *
++ * GFX_FCLK runs from L3, and is divided by (1,2,3,4)
++ * The 2d and 3d clocks run at a hardware determined
++ * divided value of fclk.
++ *
++ */
++/* XXX REVISIT: GFX clock is part of CONFIG_PARTICIPANT, no? doublecheck. */
++
++/* This clksel struct is shared between gfx_3d_fck and gfx_2d_fck */
++static const struct clksel gfx_fck_clksel[] = {
++	{ .parent = &core_l3_ck, .rates = gfx_l3_rates },
++	{ .parent = NULL },
++};
++
++static struct clk gfx_3d_fck = {
++	.name		= "gfx_3d_fck",
++	.parent		= &core_l3_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP24XX_EN_3D_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
++	.clksel		= gfx_fck_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static struct clk gfx_2d_fck = {
++	.name		= "gfx_2d_fck",
++	.parent		= &core_l3_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP24XX_EN_2D_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
++	.clksel		= gfx_fck_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static struct clk gfx_ick = {
++	.name		= "gfx_ick",		/* From l3 */
++	.parent		= &core_l3_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP_EN_GFX_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++/*
++ * Modem clock domain (2430)
++ *	CLOCKS:
++ *		MDM_OSC_CLK
++ *		MDM_ICLK
++ * These clocks are usable in chassis mode only.
++ */
++static const struct clksel_rate mdm_ick_core_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_243X },
++	{ .div = 4, .val = 4, .flags = RATE_IN_243X | DEFAULT_RATE },
++	{ .div = 6, .val = 6, .flags = RATE_IN_243X },
++	{ .div = 9, .val = 9, .flags = RATE_IN_243X },
++	{ .div = 0 }
++};
++
++static const struct clksel mdm_ick_clksel[] = {
++	{ .parent = &core_ck, .rates = mdm_ick_core_rates },
++	{ .parent = NULL }
++};
++
++static struct clk mdm_ick = {		/* used both as a ick and fck */
++	.name		= "mdm_ick",
++	.parent		= &core_ck,
++	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP2430_CLKSEL_MDM_MASK,
++	.clksel		= mdm_ick_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static struct clk mdm_osc_ck = {
++	.name		= "mdm_osc_ck",
++	.parent		= &osc_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP2430_EN_OSC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++/*
++ * L4 clock management domain
++ *
++ * This domain contains lots of interface clocks from the L4 interface, some
++ * functional clocks.	Fixed APLL functional source clocks are managed in
++ * this domain.
++ */
++static const struct clksel_rate l4_core_l3_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
++	{ .div = 0 }
++};
++
++static const struct clksel l4_clksel[] = {
++	{ .parent = &core_l3_ck, .rates = l4_core_l3_rates },
++	{ .parent = NULL }
++};
++
++static struct clk l4_ck = {		/* used both as an ick and fck */
++	.name		= "l4_ck",
++	.parent		= &core_l3_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
++	.clksel		= l4_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static struct clk ssi_l4_ick = {
++	.name		= "ssi_l4_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++/*
++ * DSS clock domain
++ * CLOCKs:
++ * DSS_L4_ICLK, DSS_L3_ICLK,
++ * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK
++ *
++ * DSS is both initiator and target.
++ */
++/* XXX Add RATE_NOT_VALIDATED */
++
++static const struct clksel_rate dss1_fck_sys_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate dss1_fck_core_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
++	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
++	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
++	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
++	{ .div = 5, .val = 5, .flags = RATE_IN_24XX },
++	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
++	{ .div = 8, .val = 8, .flags = RATE_IN_24XX },
++	{ .div = 9, .val = 9, .flags = RATE_IN_24XX },
++	{ .div = 12, .val = 12, .flags = RATE_IN_24XX },
++	{ .div = 16, .val = 16, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel dss1_fck_clksel[] = {
++	{ .parent = &sys_ck,  .rates = dss1_fck_sys_rates },
++	{ .parent = &core_ck, .rates = dss1_fck_core_rates },
++	{ .parent = NULL },
++};
++
++static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
++	.name		= "dss_ick",
++	.parent		= &l4_ck,	/* really both l3 and l4 */
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk dss1_fck = {
++	.name		= "dss1_fck",
++	.parent		= &core_ck,		/* Core or sys */
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				DELAYED_APP,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP24XX_CLKSEL_DSS1_MASK,
++	.clksel		= dss1_fck_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static const struct clksel_rate dss2_fck_sys_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate dss2_fck_48m_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel dss2_fck_clksel[] = {
++	{ .parent = &sys_ck,	  .rates = dss2_fck_sys_rates },
++	{ .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
++	{ .parent = NULL }
++};
++
++static struct clk dss2_fck = {		/* Alt clk used in power management */
++	.name		= "dss2_fck",
++	.parent		= &sys_ck,		/* fixed at sys_ck or 48MHz */
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				DELAYED_APP,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP24XX_CLKSEL_DSS2_MASK,
++	.clksel		= dss2_fck_clksel,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk dss_54m_fck = {	/* Alt clk used in power management */
++	.name		= "dss_54m_fck",	/* 54m tv clk */
++	.parent		= &func_54m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_TV_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++/*
++ * CORE power domain ICLK & FCLK defines.
++ * Many of the these can have more than one possible parent. Entries
++ * here will likely have an L4 interface parent, and may have multiple
++ * functional clock parents.
++ */
++static const struct clksel_rate gpt_alt_rates[] = {
++	{ .div = 1, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel omap24xx_gpt_clksel[] = {
++	{ .parent = &func_32k_ck, .rates = gpt_32k_rates },
++	{ .parent = &sys_ck,	  .rates = gpt_sys_rates },
++	{ .parent = &alt_ck,	  .rates = gpt_alt_rates },
++	{ .parent = NULL },
++};
++
++static struct clk gpt1_ick = {
++	.name		= "gpt1_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt1_fck = {
++	.name		= "gpt1_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT1_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static struct clk gpt2_ick = {
++	.name		= "gpt2_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt2_fck = {
++	.name		= "gpt2_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT2_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt3_ick = {
++	.name		= "gpt3_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt3_fck = {
++	.name		= "gpt3_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT3_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt4_ick = {
++	.name		= "gpt4_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt4_fck = {
++	.name		= "gpt4_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT4_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt5_ick = {
++	.name		= "gpt5_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt5_fck = {
++	.name		= "gpt5_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT5_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt6_ick = {
++	.name		= "gpt6_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt6_fck = {
++	.name		= "gpt6_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT6_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt7_ick = {
++	.name		= "gpt7_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt7_fck = {
++	.name		= "gpt7_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT7_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt8_ick = {
++	.name		= "gpt8_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt8_fck = {
++	.name		= "gpt8_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT8_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt9_ick = {
++	.name		= "gpt9_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt9_fck = {
++	.name		= "gpt9_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT9_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt10_ick = {
++	.name		= "gpt10_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt10_fck = {
++	.name		= "gpt10_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT10_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt11_ick = {
++	.name		= "gpt11_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt11_fck = {
++	.name		= "gpt11_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT11_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt12_ick = {
++	.name		= "gpt12_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt12_fck = {
++	.name		= "gpt12_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++	.clksel_mask	= OMAP24XX_CLKSEL_GPT12_MASK,
++	.clksel		= omap24xx_gpt_clksel,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk mcbsp1_ick = {
++	.name		= "mcbsp1_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp1_fck = {
++	.name		= "mcbsp1_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp2_ick = {
++	.name		= "mcbsp2_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp2_fck = {
++	.name		= "mcbsp2_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp3_ick = {
++	.name		= "mcbsp3_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp3_fck = {
++	.name		= "mcbsp3_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp4_ick = {
++	.name		= "mcbsp4_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp4_fck = {
++	.name		= "mcbsp4_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp5_ick = {
++	.name		= "mcbsp5_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp5_fck = {
++	.name		= "mcbsp5_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi1_ick = {
++	.name		= "mcspi_ick",
++	.id		= 1,
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi1_fck = {
++	.name		= "mcspi_fck",
++	.id		= 1,
++	.parent		= &func_48m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi2_ick = {
++	.name		= "mcspi_ick",
++	.id		= 2,
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi2_fck = {
++	.name		= "mcspi_fck",
++	.id		= 2,
++	.parent		= &func_48m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi3_ick = {
++	.name		= "mcspi_ick",
++	.id		= 3,
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi3_fck = {
++	.name		= "mcspi_fck",
++	.id		= 3,
++	.parent		= &func_48m_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart1_ick = {
++	.name		= "uart1_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart1_fck = {
++	.name		= "uart1_fck",
++	.parent		= &func_48m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart2_ick = {
++	.name		= "uart2_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart2_fck = {
++	.name		= "uart2_fck",
++	.parent		= &func_48m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart3_ick = {
++	.name		= "uart3_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart3_fck = {
++	.name		= "uart3_fck",
++	.parent		= &func_48m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpios_ick = {
++	.name		= "gpios_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpios_fck = {
++	.name		= "gpios_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mpu_wdt_ick = {
++	.name		= "mpu_wdt_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mpu_wdt_fck = {
++	.name		= "mpu_wdt_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk sync_32k_ick = {
++	.name		= "sync_32k_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++static struct clk wdt1_ick = {
++	.name		= "wdt1_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++static struct clk omapctrl_ick = {
++	.name		= "omapctrl_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++static struct clk icr_ick = {
++	.name		= "icr_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP2430_EN_ICR_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk cam_ick = {
++	.name		= "cam_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk cam_fck = {
++	.name		= "cam_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mailboxes_ick = {
++	.name		= "mailboxes_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_MAILBOXES_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt4_ick = {
++	.name		= "wdt4_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt4_fck = {
++	.name		= "wdt4_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt3_ick = {
++	.name		= "wdt3_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt3_fck = {
++	.name		= "wdt3_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mspro_ick = {
++	.name		= "mspro_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mspro_fck = {
++	.name		= "mspro_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmc_ick = {
++	.name		= "mmc_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmc_fck = {
++	.name		= "mmc_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk fac_ick = {
++	.name		= "fac_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk fac_fck = {
++	.name		= "fac_fck",
++	.parent		= &func_12m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk eac_ick = {
++	.name		= "eac_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk eac_fck = {
++	.name		= "eac_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk hdq_ick = {
++	.name		= "hdq_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk hdq_fck = {
++	.name		= "hdq_fck",
++	.parent		= &func_12m_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c2_ick = {
++	.name		= "i2c_ick",
++	.id		= 2,
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c2_fck = {
++	.name		= "i2c_fck",
++	.id		= 2,
++	.parent		= &func_12m_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2chs2_fck = {
++	.name		= "i2chs_fck",
++	.id		= 2,
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_I2CHS2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c1_ick = {
++	.name		= "i2c_ick",
++	.id		= 1,
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c1_fck = {
++	.name		= "i2c_fck",
++	.id		= 1,
++	.parent		= &func_12m_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2chs1_fck = {
++	.name		= "i2chs_fck",
++	.id		= 1,
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_I2CHS1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpmc_fck = {
++	.name		= "gpmc_fck",
++	.parent		= &core_l3_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk sdma_fck = {
++	.name		= "sdma_fck",
++	.parent		= &core_l3_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk sdma_ick = {
++	.name		= "sdma_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk vlynq_ick = {
++	.name		= "vlynq_ick",
++	.parent		= &core_l3_ck,
++	.flags		= CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static const struct clksel_rate vlynq_fck_96m_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_242X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate vlynq_fck_core_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_242X },
++	{ .div = 2, .val = 2, .flags = RATE_IN_242X },
++	{ .div = 3, .val = 3, .flags = RATE_IN_242X },
++	{ .div = 4, .val = 4, .flags = RATE_IN_242X },
++	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
++	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
++	{ .div = 9, .val = 9, .flags = RATE_IN_242X },
++	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
++	{ .div = 16, .val = 16, .flags = RATE_IN_242X | DEFAULT_RATE },
++	{ .div = 18, .val = 18, .flags = RATE_IN_242X },
++	{ .div = 0 }
++};
++
++static const struct clksel vlynq_fck_clksel[] = {
++	{ .parent = &func_96m_ck, .rates = vlynq_fck_96m_rates },
++	{ .parent = &core_ck,	  .rates = vlynq_fck_core_rates },
++	{ .parent = NULL }
++};
++
++static struct clk vlynq_fck = {
++	.name		= "vlynq_fck",
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP2420_CLKSEL_VLYNQ_MASK,
++	.clksel		= vlynq_fck_clksel,
++	.recalc		= &omap2_clksel_recalc,
++	.round_rate	= &omap2_clksel_round_rate,
++	.set_rate	= &omap2_clksel_set_rate
++};
++
++static struct clk sdrc_ick = {
++	.name		= "sdrc_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
++	.enable_bit	= OMAP2430_EN_SDRC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk des_ick = {
++	.name		= "des_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++	.enable_bit	= OMAP24XX_EN_DES_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk sha_ick = {
++	.name		= "sha_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++	.enable_bit	= OMAP24XX_EN_SHA_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk rng_ick = {
++	.name		= "rng_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++	.enable_bit	= OMAP24XX_EN_RNG_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk aes_ick = {
++	.name		= "aes_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++	.enable_bit	= OMAP24XX_EN_AES_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk pka_ick = {
++	.name		= "pka_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++	.enable_bit	= OMAP24XX_EN_PKA_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk usb_fck = {
++	.name		= "usb_fck",
++	.parent		= &func_48m_ck,
++	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk usbhs_ick = {
++	.name		= "usbhs_ick",
++	.parent		= &core_l3_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP2430_EN_USBHS_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs1_ick = {
++	.name		= "mmchs_ick",
++	.id		= 1,
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs1_fck = {
++	.name		= "mmchs_fck",
++	.id		= 1,
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs2_ick = {
++	.name		= "mmchs_ick",
++	.id		= 2,
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs2_fck = {
++	.name		= "mmchs_fck",
++	.id		= 2,
++	.parent		= &func_96m_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio5_ick = {
++	.name		= "gpio5_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio5_fck = {
++	.name		= "gpio5_fck",
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mdm_intc_ick = {
++	.name		= "mdm_intc_ick",
++	.parent		= &l4_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP2430_EN_MDM_INTC_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchsdb1_fck = {
++	.name		= "mmchsdb_fck",
++	.id		= 1,
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_MMCHSDB1_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchsdb2_fck = {
++	.name		= "mmchsdb_fck",
++	.id		= 2,
++	.parent		= &func_32k_ck,
++	.flags		= CLOCK_IN_OMAP243X,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++	.enable_bit	= OMAP2430_EN_MMCHSDB2_SHIFT,
++	.recalc		= &followparent_recalc,
++};
++
++/*
++ * This clock is a composite clock which does entire set changes then
++ * forces a rebalance. It keys on the MPU speed, but it really could
++ * be any key speed part of a set in the rate table.
++ *
++ * to really change a set, you need memory table sets which get changed
++ * in sram, pre-notifiers & post notifiers, changing the top set, without
++ * having low level display recalc's won't work... this is why dpm notifiers
++ * work, isr's off, walk a list of clocks already _off_ and not messing with
++ * the bus.
++ *
++ * This clock should have no parent. It embodies the entire upper level
++ * active set. A parent will mess up some of the init also.
++ */
++static struct clk virt_prcm_set = {
++	.name		= "virt_prcm_set",
++	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++				VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP,
++	.parent		= &mpu_ck,	/* Indexed by mpu speed, no parent */
++	.recalc		= &omap2_table_mpu_recalc,	/* sets are keyed on mpu rate */
++	.set_rate	= &omap2_select_table_rate,
++	.round_rate	= &omap2_round_to_table_rate,
++};
++
++static struct clk *onchip_24xx_clks[] __initdata = {
++	/* external root sources */
++	&func_32k_ck,
++	&osc_ck,
++	&sys_ck,
++	&alt_ck,
++	/* internal analog sources */
++	&dpll_ck,
++	&apll96_ck,
++	&apll54_ck,
++	/* internal prcm root sources */
++	&func_54m_ck,
++	&core_ck,
++	&func_96m_ck,
++	&func_48m_ck,
++	&func_12m_ck,
++	&wdt1_osc_ck,
++	&sys_clkout_src,
++	&sys_clkout,
++	&sys_clkout2_src,
++	&sys_clkout2,
++	&emul_ck,
++	/* mpu domain clocks */
++	&mpu_ck,
++	/* dsp domain clocks */
++	&dsp_fck,
++	&dsp_irate_ick,
++	&dsp_ick,		/* 242x */
++	&iva2_1_ick,		/* 243x */
++	&iva1_ifck,		/* 242x */
++	&iva1_mpu_int_ifck,	/* 242x */
++	/* GFX domain clocks */
++	&gfx_3d_fck,
++	&gfx_2d_fck,
++	&gfx_ick,
++	/* Modem domain clocks */
++	&mdm_ick,
++	&mdm_osc_ck,
++	/* DSS domain clocks */
++	&dss_ick,
++	&dss1_fck,
++	&dss2_fck,
++	&dss_54m_fck,
++	/* L3 domain clocks */
++	&core_l3_ck,
++	&ssi_ssr_sst_fck,
++	&usb_l4_ick,
++	/* L4 domain clocks */
++	&l4_ck,			/* used as both core_l4 and wu_l4 */
++	&ssi_l4_ick,
++	/* virtual meta-group clock */
++	&virt_prcm_set,
++	/* general l4 interface ck, multi-parent functional clk */
++	&gpt1_ick,
++	&gpt1_fck,
++	&gpt2_ick,
++	&gpt2_fck,
++	&gpt3_ick,
++	&gpt3_fck,
++	&gpt4_ick,
++	&gpt4_fck,
++	&gpt5_ick,
++	&gpt5_fck,
++	&gpt6_ick,
++	&gpt6_fck,
++	&gpt7_ick,
++	&gpt7_fck,
++	&gpt8_ick,
++	&gpt8_fck,
++	&gpt9_ick,
++	&gpt9_fck,
++	&gpt10_ick,
++	&gpt10_fck,
++	&gpt11_ick,
++	&gpt11_fck,
++	&gpt12_ick,
++	&gpt12_fck,
++	&mcbsp1_ick,
++	&mcbsp1_fck,
++	&mcbsp2_ick,
++	&mcbsp2_fck,
++	&mcbsp3_ick,
++	&mcbsp3_fck,
++	&mcbsp4_ick,
++	&mcbsp4_fck,
++	&mcbsp5_ick,
++	&mcbsp5_fck,
++	&mcspi1_ick,
++	&mcspi1_fck,
++	&mcspi2_ick,
++	&mcspi2_fck,
++	&mcspi3_ick,
++	&mcspi3_fck,
++	&uart1_ick,
++	&uart1_fck,
++	&uart2_ick,
++	&uart2_fck,
++	&uart3_ick,
++	&uart3_fck,
++	&gpios_ick,
++	&gpios_fck,
++	&mpu_wdt_ick,
++	&mpu_wdt_fck,
++	&sync_32k_ick,
++	&wdt1_ick,
++	&omapctrl_ick,
++	&icr_ick,
++	&cam_fck,
++	&cam_ick,
++	&mailboxes_ick,
++	&wdt4_ick,
++	&wdt4_fck,
++	&wdt3_ick,
++	&wdt3_fck,
++	&mspro_ick,
++	&mspro_fck,
++	&mmc_ick,
++	&mmc_fck,
++	&fac_ick,
++	&fac_fck,
++	&eac_ick,
++	&eac_fck,
++	&hdq_ick,
++	&hdq_fck,
++	&i2c1_ick,
++	&i2c1_fck,
++	&i2chs1_fck,
++	&i2c2_ick,
++	&i2c2_fck,
++	&i2chs2_fck,
++	&gpmc_fck,
++	&sdma_fck,
++	&sdma_ick,
++	&vlynq_ick,
++	&vlynq_fck,
++	&sdrc_ick,
++	&des_ick,
++	&sha_ick,
++	&rng_ick,
++	&aes_ick,
++	&pka_ick,
++	&usb_fck,
++	&usbhs_ick,
++	&mmchs1_ick,
++	&mmchs1_fck,
++	&mmchs2_ick,
++	&mmchs2_fck,
++	&gpio5_ick,
++	&gpio5_fck,
++	&mdm_intc_ick,
++	&mmchsdb1_fck,
++	&mmchsdb2_fck,
++};
++
++#endif
++
+diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
+new file mode 100644
+index 0000000..b42bdd6
+--- /dev/null
++++ b/arch/arm/mach-omap2/clock34xx.c
+@@ -0,0 +1,235 @@
++/*
++ * OMAP3-specific clock framework functions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * Parts of this code are based on code written by
++ * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#undef DEBUG
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <linux/list.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++
++#include <asm/arch/clock.h>
++#include <asm/arch/sram.h>
++#include <asm/div64.h>
++#include <asm/bitops.h>
++
++#include "memory.h"
++#include "clock.h"
++#include "clock34xx.h"
++#include "prm.h"
++#include "prm-regbits-34xx.h"
++#include "cm.h"
++#include "cm-regbits-34xx.h"
++
++/* CM_CLKEN_PLL*.EN* bit values */
++#define DPLL_LOCKED		0x7
++
++/**
++ * omap3_dpll_recalc - recalculate DPLL rate
++ * @clk: DPLL struct clk
++ *
++ * Recalculate and propagate the DPLL rate.
++ */
++static void omap3_dpll_recalc(struct clk *clk)
++{
++	clk->rate = omap2_get_dpll_rate(clk);
++
++	propagate_rate(clk);
++}
++
++/**
++ * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
++ * @clk: DPLL output struct clk
++ *
++ * Using parent clock DPLL data, look up DPLL state.  If locked, set our
++ * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
++ */
++static void omap3_clkoutx2_recalc(struct clk *clk)
++{
++	const struct dpll_data *dd;
++	u32 v;
++	struct clk *pclk;
++
++	/* Walk up the parents of clk, looking for a DPLL */
++	pclk = clk->parent;
++	while (pclk && !pclk->dpll_data)
++		pclk = pclk->parent;
++
++	/* clk does not have a DPLL as a parent? */
++	WARN_ON(!pclk);
++
++	dd = pclk->dpll_data;
++
++	WARN_ON(!dd->control_reg || !dd->enable_mask);
++
++	v = __raw_readl(dd->control_reg) & dd->enable_mask;
++	v >>= __ffs(dd->enable_mask);
++	if (v != DPLL_LOCKED)
++		clk->rate = clk->parent->rate;
++	else
++		clk->rate = clk->parent->rate * 2;
++
++	if (clk->flags & RATE_PROPAGATES)
++		propagate_rate(clk);
++}
++
++/*
++ * As it is structured now, this will prevent an OMAP2/3 multiboot
++ * kernel from compiling.  This will need further attention.
++ */
++#if defined(CONFIG_ARCH_OMAP3)
++
++static struct clk_functions omap2_clk_functions = {
++	.clk_enable		= omap2_clk_enable,
++	.clk_disable		= omap2_clk_disable,
++	.clk_round_rate		= omap2_clk_round_rate,
++	.clk_set_rate		= omap2_clk_set_rate,
++	.clk_set_parent		= omap2_clk_set_parent,
++	.clk_disable_unused	= omap2_clk_disable_unused,
++};
++
++/*
++ * Set clocks for bypass mode for reboot to work.
++ */
++void omap2_clk_prepare_for_reboot(void)
++{
++	/* REVISIT: Not ready for 343x */
++#if 0
++	u32 rate;
++
++	if (vclk == NULL || sclk == NULL)
++		return;
++
++	rate = clk_get_rate(sclk);
++	clk_set_rate(vclk, rate);
++#endif
++}
++
++/* REVISIT: Move this init stuff out into clock.c */
++
++/*
++ * Switch the MPU rate if specified on cmdline.
++ * We cannot do this early until cmdline is parsed.
++ */
++static int __init omap2_clk_arch_init(void)
++{
++	if (!mpurate)
++		return -EINVAL;
++
++	/* REVISIT: not yet ready for 343x */
++#if 0
++	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
++		printk(KERN_ERR "Could not find matching MPU rate\n");
++#endif
++
++	recalculate_root_clocks();
++
++	printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL3/MPU): "
++	       "%ld.%01ld/%ld/%ld MHz\n",
++	       (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
++	       (core_ck.rate / 1000000), (dpll1_fck.rate / 1000000)) ;
++
++	return 0;
++}
++arch_initcall(omap2_clk_arch_init);
++
++int __init omap2_clk_init(void)
++{
++	/* struct prcm_config *prcm; */
++	struct clk **clkp;
++	/* u32 clkrate; */
++	u32 cpu_clkflg;
++
++	/* REVISIT: Ultimately this will be used for multiboot */
++#if 0
++	if (cpu_is_omap242x()) {
++		cpu_mask = RATE_IN_242X;
++		cpu_clkflg = CLOCK_IN_OMAP242X;
++		clkp = onchip_24xx_clks;
++	} else if (cpu_is_omap2430()) {
++		cpu_mask = RATE_IN_243X;
++		cpu_clkflg = CLOCK_IN_OMAP243X;
++		clkp = onchip_24xx_clks;
++	}
++#endif
++	if (cpu_is_omap34xx()) {
++		cpu_mask = RATE_IN_343X;
++		cpu_clkflg = CLOCK_IN_OMAP343X;
++		clkp = onchip_34xx_clks;
++
++		/*
++		 * Update this if there are further clock changes between ES2
++		 * and production parts
++		 */
++		if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) {
++			/* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */
++			cpu_clkflg |= CLOCK_IN_OMAP3430ES1;
++		} else {
++			cpu_mask |= RATE_IN_3430ES2;
++			cpu_clkflg |= CLOCK_IN_OMAP3430ES2;
++		}
++	}
++
++	clk_init(&omap2_clk_functions);
++
++	for (clkp = onchip_34xx_clks;
++	     clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks);
++	     clkp++) {
++		if ((*clkp)->flags & cpu_clkflg)
++			clk_register(*clkp);
++	}
++
++	/* REVISIT: Not yet ready for OMAP3 */
++#if 0
++	/* Check the MPU rate set by bootloader */
++	clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
++	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
++		if (!(prcm->flags & cpu_mask))
++			continue;
++		if (prcm->xtal_speed != sys_ck.rate)
++			continue;
++		if (prcm->dpll_speed <= clkrate)
++			 break;
++	}
++	curr_prcm_set = prcm;
++#endif
++
++	recalculate_root_clocks();
++
++	printk(KERN_INFO "Clocking rate (Crystal/DPLL/ARM core): "
++	       "%ld.%01ld/%ld/%ld MHz\n",
++	       (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
++	       (core_ck.rate / 1000000), (arm_fck.rate / 1000000));
++
++	/*
++	 * Only enable those clocks we will need, let the drivers
++	 * enable other clocks as necessary
++	 */
++	clk_enable_init_clocks();
++
++	/* Avoid sleeping during omap2_clk_prepare_for_reboot() */
++	/* REVISIT: not yet ready for 343x */
++#if 0
++	vclk = clk_get(NULL, "virt_prcm_set");
++	sclk = clk_get(NULL, "sys_ck");
++#endif
++	return 0;
++}
++
++#endif
+diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
+new file mode 100644
+index 0000000..cf4644a
+--- /dev/null
++++ b/arch/arm/mach-omap2/clock34xx.h
+@@ -0,0 +1,3009 @@
++/*
++ * OMAP3 clock framework
++ *
++ * Virtual clocks are introduced as a convenient tools.
++ * They are sources for other clocks and not supposed
++ * to be requested from drivers directly.
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ */
++
++#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
++#define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
++
++#include <asm/arch/control.h>
++
++#include "clock.h"
++#include "cm.h"
++#include "cm-regbits-34xx.h"
++#include "prm.h"
++#include "prm-regbits-34xx.h"
++
++static void omap3_dpll_recalc(struct clk *clk);
++static void omap3_clkoutx2_recalc(struct clk *clk);
++
++/*
++ * DPLL1 supplies clock to the MPU.
++ * DPLL2 supplies clock to the IVA2.
++ * DPLL3 supplies CORE domain clocks.
++ * DPLL4 supplies peripheral clocks.
++ * DPLL5 supplies other peripheral clocks (USBHOST, USIM).
++ */
++
++/* PRM CLOCKS */
++
++/* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
++static struct clk omap_32k_fck = {
++	.name		= "omap_32k_fck",
++	.rate		= 32768,
++	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++static struct clk secure_32k_fck = {
++	.name		= "secure_32k_fck",
++	.rate		= 32768,
++	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++/* Virtual source clocks for osc_sys_ck */
++static struct clk virt_12m_ck = {
++	.name		= "virt_12m_ck",
++	.rate		= 12000000,
++	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++static struct clk virt_13m_ck = {
++	.name		= "virt_13m_ck",
++	.rate		= 13000000,
++	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++static struct clk virt_16_8m_ck = {
++	.name		= "virt_16_8m_ck",
++	.rate		= 16800000,
++	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_FIXED | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++static struct clk virt_19_2m_ck = {
++	.name		= "virt_19_2m_ck",
++	.rate		= 19200000,
++	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++static struct clk virt_26m_ck = {
++	.name		= "virt_26m_ck",
++	.rate		= 26000000,
++	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++static struct clk virt_38_4m_ck = {
++	.name		= "virt_38_4m_ck",
++	.rate		= 38400000,
++	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++static const struct clksel_rate osc_sys_12m_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_13m_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_16_8m_rates[] = {
++	{ .div = 1, .val = 5, .flags = RATE_IN_3430ES2 | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_19_2m_rates[] = {
++	{ .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_26m_rates[] = {
++	{ .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_38_4m_rates[] = {
++	{ .div = 1, .val = 4, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel osc_sys_clksel[] = {
++	{ .parent = &virt_12m_ck,   .rates = osc_sys_12m_rates },
++	{ .parent = &virt_13m_ck,   .rates = osc_sys_13m_rates },
++	{ .parent = &virt_16_8m_ck, .rates = osc_sys_16_8m_rates },
++	{ .parent = &virt_19_2m_ck, .rates = osc_sys_19_2m_rates },
++	{ .parent = &virt_26m_ck,   .rates = osc_sys_26m_rates },
++	{ .parent = &virt_38_4m_ck, .rates = osc_sys_38_4m_rates },
++	{ .parent = NULL },
++};
++
++/* Oscillator clock */
++/* 12, 13, 16.8, 19.2, 26, or 38.4 MHz */
++static struct clk osc_sys_ck = {
++	.name		= "osc_sys_ck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP3430_PRM_CLKSEL,
++	.clksel_mask	= OMAP3430_SYS_CLKIN_SEL_MASK,
++	.clksel		= osc_sys_clksel,
++	/* REVISIT: deal with autoextclkmode? */
++	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate div2_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_343X },
++	{ .div = 0 }
++};
++
++static const struct clksel sys_clksel[] = {
++	{ .parent = &osc_sys_ck, .rates = div2_rates },
++	{ .parent = NULL }
++};
++
++/* Latency: this clock is only enabled after PRM_CLKSETUP.SETUP_TIME */
++/* Feeds DPLLs - divided first by PRM_CLKSRC_CTRL.SYSCLKDIV? */
++static struct clk sys_ck = {
++	.name		= "sys_ck",
++	.parent		= &osc_sys_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP3430_PRM_CLKSRC_CTRL,
++	.clksel_mask	= OMAP_SYSCLKDIV_MASK,
++	.clksel		= sys_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk sys_altclk = {
++	.name		= "sys_altclk",
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++/* Optional external clock input for some McBSPs */
++static struct clk mcbsp_clks = {
++	.name		= "mcbsp_clks",
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &propagate_rate,
++};
++
++/* PRM EXTERNAL CLOCK OUTPUT */
++
++static struct clk sys_clkout1 = {
++	.name		= "sys_clkout1",
++	.parent		= &osc_sys_ck,
++	.enable_reg	= OMAP3430_PRM_CLKOUT_CTRL,
++	.enable_bit	= OMAP3430_CLKOUT_EN_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++/* DPLLS */
++
++/* CM CLOCKS */
++
++static const struct clksel_rate dpll_bypass_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate dpll_locked_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate div16_dpll_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_343X },
++	{ .div = 3, .val = 3, .flags = RATE_IN_343X },
++	{ .div = 4, .val = 4, .flags = RATE_IN_343X },
++	{ .div = 5, .val = 5, .flags = RATE_IN_343X },
++	{ .div = 6, .val = 6, .flags = RATE_IN_343X },
++	{ .div = 7, .val = 7, .flags = RATE_IN_343X },
++	{ .div = 8, .val = 8, .flags = RATE_IN_343X },
++	{ .div = 9, .val = 9, .flags = RATE_IN_343X },
++	{ .div = 10, .val = 10, .flags = RATE_IN_343X },
++	{ .div = 11, .val = 11, .flags = RATE_IN_343X },
++	{ .div = 12, .val = 12, .flags = RATE_IN_343X },
++	{ .div = 13, .val = 13, .flags = RATE_IN_343X },
++	{ .div = 14, .val = 14, .flags = RATE_IN_343X },
++	{ .div = 15, .val = 15, .flags = RATE_IN_343X },
++	{ .div = 16, .val = 16, .flags = RATE_IN_343X },
++	{ .div = 0 }
++};
++
++/* DPLL1 */
++/* MPU clock source */
++/* Type: DPLL */
++static const struct dpll_data dpll1_dd = {
++	.mult_div1_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
++	.mult_mask	= OMAP3430_MPU_DPLL_MULT_MASK,
++	.div1_mask	= OMAP3430_MPU_DPLL_DIV_MASK,
++	.control_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
++	.enable_mask	= OMAP3430_EN_MPU_DPLL_MASK,
++	.auto_recal_bit	= OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT,
++	.recal_en_bit	= OMAP3430_MPU_DPLL_RECAL_EN_SHIFT,
++	.recal_st_bit	= OMAP3430_MPU_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll1_ck = {
++	.name		= "dpll1_ck",
++	.parent		= &sys_ck,
++	.dpll_data	= &dpll1_dd,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap3_dpll_recalc,
++};
++
++/*
++ * This virtual clock provides the CLKOUTX2 output from the DPLL if the
++ * DPLL isn't bypassed.
++ */
++static struct clk dpll1_x2_ck = {
++	.name		= "dpll1_x2_ck",
++	.parent		= &dpll1_ck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap3_clkoutx2_recalc,
++};
++
++/* On DPLL1, unlike other DPLLs, the divider is downstream from CLKOUTX2 */
++static const struct clksel div16_dpll1_x2m2_clksel[] = {
++	{ .parent = &dpll1_x2_ck, .rates = div16_dpll_rates },
++	{ .parent = NULL }
++};
++
++/*
++ * Does not exist in the TRM - needed to separate the M2 divider from
++ * bypass selection in mpu_ck
++ */
++static struct clk dpll1_x2m2_ck = {
++	.name		= "dpll1_x2m2_ck",
++	.parent		= &dpll1_x2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
++	.clksel_mask	= OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK,
++	.clksel		= div16_dpll1_x2m2_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* DPLL2 */
++/* IVA2 clock source */
++/* Type: DPLL */
++
++static const struct dpll_data dpll2_dd = {
++	.mult_div1_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
++	.mult_mask	= OMAP3430_IVA2_DPLL_MULT_MASK,
++	.div1_mask	= OMAP3430_IVA2_DPLL_DIV_MASK,
++	.control_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
++	.enable_mask	= OMAP3430_EN_IVA2_DPLL_MASK,
++	.auto_recal_bit	= OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT,
++	.recal_en_bit	= OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT,
++	.recal_st_bit	= OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll2_ck = {
++	.name		= "dpll2_ck",
++	.parent		= &sys_ck,
++	.dpll_data	= &dpll2_dd,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap3_dpll_recalc,
++};
++
++static const struct clksel div16_dpll2_m2x2_clksel[] = {
++	{ .parent = &dpll2_ck, .rates = div16_dpll_rates },
++	{ .parent = NULL }
++};
++
++/*
++ * The TRM is conflicted on whether IVA2 clock comes from DPLL2 CLKOUT
++ * or CLKOUTX2. CLKOUT seems most plausible.
++ */
++static struct clk dpll2_m2_ck = {
++	.name		= "dpll2_m2_ck",
++	.parent		= &dpll2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD,
++					  OMAP3430_CM_CLKSEL2_PLL),
++	.clksel_mask	= OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK,
++	.clksel		= div16_dpll2_m2x2_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* DPLL3 */
++/* Source clock for all interfaces and for some device fclks */
++/* Type: DPLL */
++static const struct dpll_data dpll3_dd = {
++	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++	.mult_mask	= OMAP3430_CORE_DPLL_MULT_MASK,
++	.div1_mask	= OMAP3430_CORE_DPLL_DIV_MASK,
++	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_mask	= OMAP3430_EN_CORE_DPLL_MASK,
++	.auto_recal_bit	= OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
++	.recal_en_bit	= OMAP3430_CORE_DPLL_RECAL_EN_SHIFT,
++	.recal_st_bit	= OMAP3430_CORE_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll3_ck = {
++	.name		= "dpll3_ck",
++	.parent		= &sys_ck,
++	.dpll_data	= &dpll3_dd,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap3_dpll_recalc,
++};
++
++/*
++ * This virtual clock provides the CLKOUTX2 output from the DPLL if the
++ * DPLL isn't bypassed
++ */
++static struct clk dpll3_x2_ck = {
++	.name		= "dpll3_x2_ck",
++	.parent		= &dpll3_ck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel_rate div31_dpll3_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_343X },
++	{ .div = 3, .val = 3, .flags = RATE_IN_3430ES2 },
++	{ .div = 4, .val = 4, .flags = RATE_IN_3430ES2 },
++	{ .div = 5, .val = 5, .flags = RATE_IN_3430ES2 },
++	{ .div = 6, .val = 6, .flags = RATE_IN_3430ES2 },
++	{ .div = 7, .val = 7, .flags = RATE_IN_3430ES2 },
++	{ .div = 8, .val = 8, .flags = RATE_IN_3430ES2 },
++	{ .div = 9, .val = 9, .flags = RATE_IN_3430ES2 },
++	{ .div = 10, .val = 10, .flags = RATE_IN_3430ES2 },
++	{ .div = 11, .val = 11, .flags = RATE_IN_3430ES2 },
++	{ .div = 12, .val = 12, .flags = RATE_IN_3430ES2 },
++	{ .div = 13, .val = 13, .flags = RATE_IN_3430ES2 },
++	{ .div = 14, .val = 14, .flags = RATE_IN_3430ES2 },
++	{ .div = 15, .val = 15, .flags = RATE_IN_3430ES2 },
++	{ .div = 16, .val = 16, .flags = RATE_IN_3430ES2 },
++	{ .div = 17, .val = 17, .flags = RATE_IN_3430ES2 },
++	{ .div = 18, .val = 18, .flags = RATE_IN_3430ES2 },
++	{ .div = 19, .val = 19, .flags = RATE_IN_3430ES2 },
++	{ .div = 20, .val = 20, .flags = RATE_IN_3430ES2 },
++	{ .div = 21, .val = 21, .flags = RATE_IN_3430ES2 },
++	{ .div = 22, .val = 22, .flags = RATE_IN_3430ES2 },
++	{ .div = 23, .val = 23, .flags = RATE_IN_3430ES2 },
++	{ .div = 24, .val = 24, .flags = RATE_IN_3430ES2 },
++	{ .div = 25, .val = 25, .flags = RATE_IN_3430ES2 },
++	{ .div = 26, .val = 26, .flags = RATE_IN_3430ES2 },
++	{ .div = 27, .val = 27, .flags = RATE_IN_3430ES2 },
++	{ .div = 28, .val = 28, .flags = RATE_IN_3430ES2 },
++	{ .div = 29, .val = 29, .flags = RATE_IN_3430ES2 },
++	{ .div = 30, .val = 30, .flags = RATE_IN_3430ES2 },
++	{ .div = 31, .val = 31, .flags = RATE_IN_3430ES2 },
++	{ .div = 0 },
++};
++
++static const struct clksel div31_dpll3m2_clksel[] = {
++	{ .parent = &dpll3_ck, .rates = div31_dpll3_rates },
++	{ .parent = NULL }
++};
++
++/*
++ * DPLL3 output M2
++ * REVISIT: This DPLL output divider must be changed in SRAM, so until
++ * that code is ready, this should remain a 'read-only' clksel clock.
++ */
++static struct clk dpll3_m2_ck = {
++	.name		= "dpll3_m2_ck",
++	.parent		= &dpll3_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK,
++	.clksel		= div31_dpll3m2_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel core_ck_clksel[] = {
++	{ .parent = &sys_ck,      .rates = dpll_bypass_rates },
++	{ .parent = &dpll3_m2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk core_ck = {
++	.name		= "core_ck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++	.clksel_mask	= OMAP3430_ST_CORE_CLK,
++	.clksel		= core_ck_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel dpll3_m2x2_ck_clksel[] = {
++	{ .parent = &sys_ck,      .rates = dpll_bypass_rates },
++	{ .parent = &dpll3_x2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk dpll3_m2x2_ck = {
++	.name		= "dpll3_m2x2_ck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++	.clksel_mask	= OMAP3430_ST_CORE_CLK,
++	.clksel		= dpll3_m2x2_ck_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static const struct clksel div16_dpll3_clksel[] = {
++	{ .parent = &dpll3_ck, .rates = div16_dpll_rates },
++	{ .parent = NULL }
++};
++
++/* This virtual clock is the source for dpll3_m3x2_ck */
++static struct clk dpll3_m3_ck = {
++	.name		= "dpll3_m3_ck",
++	.parent		= &dpll3_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_DIV_DPLL3_MASK,
++	.clksel		= div16_dpll3_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll3_m3x2_ck = {
++	.name		= "dpll3_m3x2_ck",
++	.parent		= &dpll3_m3_ck,
++	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_bit	= OMAP3430_PWRDN_EMU_CORE_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++	.recalc		= &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel emu_core_alwon_ck_clksel[] = {
++	{ .parent = &sys_ck,        .rates = dpll_bypass_rates },
++	{ .parent = &dpll3_m3x2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk emu_core_alwon_ck = {
++	.name		= "emu_core_alwon_ck",
++	.parent		= &dpll3_m3x2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++	.clksel_mask	= OMAP3430_ST_CORE_CLK,
++	.clksel		= emu_core_alwon_ck_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* DPLL4 */
++/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */
++/* Type: DPLL */
++static const struct dpll_data dpll4_dd = {
++	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
++	.mult_mask	= OMAP3430_PERIPH_DPLL_MULT_MASK,
++	.div1_mask	= OMAP3430_PERIPH_DPLL_DIV_MASK,
++	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_mask	= OMAP3430_EN_PERIPH_DPLL_MASK,
++	.auto_recal_bit	= OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
++	.recal_en_bit	= OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
++	.recal_st_bit	= OMAP3430_PERIPH_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll4_ck = {
++	.name		= "dpll4_ck",
++	.parent		= &sys_ck,
++	.dpll_data	= &dpll4_dd,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap3_dpll_recalc,
++};
++
++/*
++ * This virtual clock provides the CLKOUTX2 output from the DPLL if the
++ * DPLL isn't bypassed --
++ * XXX does this serve any downstream clocks?
++ */
++static struct clk dpll4_x2_ck = {
++	.name		= "dpll4_x2_ck",
++	.parent		= &dpll4_ck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel div16_dpll4_clksel[] = {
++	{ .parent = &dpll4_ck, .rates = div16_dpll_rates },
++	{ .parent = NULL }
++};
++
++/* This virtual clock is the source for dpll4_m2x2_ck */
++static struct clk dpll4_m2_ck = {
++	.name		= "dpll4_m2_ck",
++	.parent		= &dpll4_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
++	.clksel_mask	= OMAP3430_DIV_96M_MASK,
++	.clksel		= div16_dpll4_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m2x2_ck = {
++	.name		= "dpll4_m2x2_ck",
++	.parent		= &dpll4_m2_ck,
++	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_bit	= OMAP3430_PWRDN_96M_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++	.recalc		= &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel omap_96m_alwon_fck_clksel[] = {
++	{ .parent = &sys_ck,        .rates = dpll_bypass_rates },
++	{ .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk omap_96m_alwon_fck = {
++	.name		= "omap_96m_alwon_fck",
++	.parent		= &dpll4_m2x2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++	.clksel_mask	= OMAP3430_ST_PERIPH_CLK,
++	.clksel		= omap_96m_alwon_fck_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				 PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk omap_96m_fck = {
++	.name		= "omap_96m_fck",
++	.parent		= &omap_96m_alwon_fck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static const struct clksel cm_96m_fck_clksel[] = {
++	{ .parent = &sys_ck,        .rates = dpll_bypass_rates },
++	{ .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk cm_96m_fck = {
++	.name		= "cm_96m_fck",
++	.parent		= &dpll4_m2x2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++	.clksel_mask	= OMAP3430_ST_PERIPH_CLK,
++	.clksel		= cm_96m_fck_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* This virtual clock is the source for dpll4_m3x2_ck */
++static struct clk dpll4_m3_ck = {
++	.name		= "dpll4_m3_ck",
++	.parent		= &dpll4_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_TV_MASK,
++	.clksel		= div16_dpll4_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m3x2_ck = {
++	.name		= "dpll4_m3x2_ck",
++	.parent		= &dpll4_m3_ck,
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_bit	= OMAP3430_PWRDN_TV_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++	.recalc		= &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel virt_omap_54m_fck_clksel[] = {
++	{ .parent = &sys_ck,        .rates = dpll_bypass_rates },
++	{ .parent = &dpll4_m3x2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk virt_omap_54m_fck = {
++	.name		= "virt_omap_54m_fck",
++	.parent		= &dpll4_m3x2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++	.clksel_mask	= OMAP3430_ST_PERIPH_CLK,
++	.clksel		= virt_omap_54m_fck_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate omap_54m_d4m3x2_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate omap_54m_alt_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel omap_54m_clksel[] = {
++	{ .parent = &virt_omap_54m_fck, .rates = omap_54m_d4m3x2_rates },
++	{ .parent = &sys_altclk,    .rates = omap_54m_alt_rates },
++	{ .parent = NULL }
++};
++
++static struct clk omap_54m_fck = {
++	.name		= "omap_54m_fck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_SOURCE_54M,
++	.clksel		= omap_54m_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate omap_48m_96md2_rates[] = {
++	{ .div = 2, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate omap_48m_alt_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel omap_48m_clksel[] = {
++	{ .parent = &cm_96m_fck, .rates = omap_48m_96md2_rates },
++	{ .parent = &sys_altclk, .rates = omap_48m_alt_rates },
++	{ .parent = NULL }
++};
++
++static struct clk omap_48m_fck = {
++	.name		= "omap_48m_fck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_SOURCE_48M,
++	.clksel		= omap_48m_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk omap_12m_fck = {
++	.name		= "omap_12m_fck",
++	.parent		= &omap_48m_fck,
++	.fixed_div	= 4,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_fixed_divisor_recalc,
++};
++
++/* This virstual clock is the source for dpll4_m4x2_ck */
++static struct clk dpll4_m4_ck = {
++	.name		= "dpll4_m4_ck",
++	.parent		= &dpll4_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_DSS1_MASK,
++	.clksel		= div16_dpll4_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m4x2_ck = {
++	.name		= "dpll4_m4x2_ck",
++	.parent		= &dpll4_m4_ck,
++	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_bit	= OMAP3430_PWRDN_CAM_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++	.recalc		= &omap3_clkoutx2_recalc,
++};
++
++/* This virtual clock is the source for dpll4_m5x2_ck */
++static struct clk dpll4_m5_ck = {
++	.name		= "dpll4_m5_ck",
++	.parent		= &dpll4_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_CAM_MASK,
++	.clksel		= div16_dpll4_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m5x2_ck = {
++	.name		= "dpll4_m5x2_ck",
++	.parent		= &dpll4_m5_ck,
++	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_bit	= OMAP3430_PWRDN_CAM_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++	.recalc		= &omap3_clkoutx2_recalc,
++};
++
++/* This virtual clock is the source for dpll4_m6x2_ck */
++static struct clk dpll4_m6_ck = {
++	.name		= "dpll4_m6_ck",
++	.parent		= &dpll4_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_DIV_DPLL4_MASK,
++	.clksel		= div16_dpll4_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m6x2_ck = {
++	.name		= "dpll4_m6x2_ck",
++	.parent		= &dpll4_m6_ck,
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++	.enable_bit	= OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++	.recalc		= &omap3_clkoutx2_recalc,
++};
++
++static struct clk emu_per_alwon_ck = {
++	.name		= "emu_per_alwon_ck",
++	.parent		= &dpll4_m6x2_ck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++/* DPLL5 */
++/* Supplies 120MHz clock, USIM source clock */
++/* Type: DPLL */
++/* 3430ES2 only */
++static const struct dpll_data dpll5_dd = {
++	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
++	.mult_mask	= OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
++	.div1_mask	= OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
++	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
++	.enable_mask	= OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
++	.auto_recal_bit	= OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT,
++	.recal_en_bit	= OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT,
++	.recal_st_bit	= OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll5_ck = {
++	.name		= "dpll5_ck",
++	.parent		= &sys_ck,
++	.dpll_data	= &dpll5_dd,
++	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
++				ALWAYS_ENABLED,
++	.recalc		= &omap3_dpll_recalc,
++};
++
++static const struct clksel div16_dpll5_clksel[] = {
++	{ .parent = &dpll5_ck, .rates = div16_dpll_rates },
++	{ .parent = NULL }
++};
++
++static struct clk dpll5_m2_ck = {
++	.name		= "dpll5_m2_ck",
++	.parent		= &dpll5_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
++	.clksel_mask	= OMAP3430ES2_DIV_120M_MASK,
++	.clksel		= div16_dpll5_clksel,
++	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel omap_120m_fck_clksel[] = {
++	{ .parent = &sys_ck,      .rates = dpll_bypass_rates },
++	{ .parent = &dpll5_m2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk omap_120m_fck = {
++	.name		= "omap_120m_fck",
++	.parent		= &dpll5_m2_ck,
++	.init           = &omap2_init_clksel_parent,
++	.clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
++	.clksel_mask    = OMAP3430ES2_ST_PERIPH2_CLK_MASK,
++	.clksel         = omap_120m_fck_clksel,
++	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc         = &omap2_clksel_recalc,
++};
++
++/* CM EXTERNAL CLOCK OUTPUTS */
++
++static const struct clksel_rate clkout2_src_core_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate clkout2_src_sys_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate clkout2_src_96m_rates[] = {
++	{ .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate clkout2_src_54m_rates[] = {
++	{ .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel clkout2_src_clksel[] = {
++	{ .parent = &core_ck,		  .rates = clkout2_src_core_rates },
++	{ .parent = &sys_ck,		  .rates = clkout2_src_sys_rates },
++	{ .parent = &omap_96m_alwon_fck,  .rates = clkout2_src_96m_rates },
++	{ .parent = &omap_54m_fck,	  .rates = clkout2_src_54m_rates },
++	{ .parent = NULL }
++};
++
++static struct clk clkout2_src_ck = {
++	.name		= "clkout2_src_ck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP3430_CM_CLKOUT_CTRL,
++	.enable_bit	= OMAP3430_CLKOUT2_EN_SHIFT,
++	.clksel_reg	= OMAP3430_CM_CLKOUT_CTRL,
++	.clksel_mask	= OMAP3430_CLKOUT2SOURCE_MASK,
++	.clksel		= clkout2_src_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate sys_clkout2_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 2, .val = 1, .flags = RATE_IN_343X },
++	{ .div = 4, .val = 2, .flags = RATE_IN_343X },
++	{ .div = 8, .val = 3, .flags = RATE_IN_343X },
++	{ .div = 16, .val = 4, .flags = RATE_IN_343X },
++	{ .div = 0 },
++};
++
++static const struct clksel sys_clkout2_clksel[] = {
++	{ .parent = &clkout2_src_ck, .rates = sys_clkout2_rates },
++	{ .parent = NULL },
++};
++
++static struct clk sys_clkout2 = {
++	.name		= "sys_clkout2",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP3430_CM_CLKOUT_CTRL,
++	.clksel_mask	= OMAP3430_CLKOUT2_DIV_MASK,
++	.clksel		= sys_clkout2_clksel,
++	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* CM OUTPUT CLOCKS */
++
++static struct clk corex2_fck = {
++	.name		= "corex2_fck",
++	.parent		= &dpll3_m2x2_ck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++/* DPLL power domain clock controls */
++
++static const struct clksel div2_core_clksel[] = {
++	{ .parent = &core_ck, .rates = div2_rates },
++	{ .parent = NULL }
++};
++
++/*
++ * REVISIT: Are these in DPLL power domain or CM power domain? docs
++ * may be inconsistent here?
++ */
++static struct clk dpll1_fck = {
++	.name		= "dpll1_fck",
++	.parent		= &core_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
++	.clksel_mask	= OMAP3430_MPU_CLK_SRC_MASK,
++	.clksel		= div2_core_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/*
++ * MPU clksel:
++ * If DPLL1 is locked, mpu_ck derives from DPLL1; otherwise, mpu_ck
++ * derives from the high-frequency bypass clock originating from DPLL3,
++ * called 'dpll1_fck'
++ */
++static const struct clksel mpu_clksel[] = {
++	{ .parent = &dpll1_fck,     .rates = dpll_bypass_rates },
++	{ .parent = &dpll1_x2m2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk mpu_ck = {
++	.name		= "mpu_ck",
++	.parent		= &dpll1_x2m2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
++	.clksel_mask	= OMAP3430_ST_MPU_CLK_MASK,
++	.clksel		= mpu_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* arm_fck is divided by two when DPLL1 locked; otherwise, passthrough mpu_ck */
++static const struct clksel_rate arm_fck_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 2, .val = 1, .flags = RATE_IN_343X },
++	{ .div = 0 },
++};
++
++static const struct clksel arm_fck_clksel[] = {
++	{ .parent = &mpu_ck, .rates = arm_fck_rates },
++	{ .parent = NULL }
++};
++
++static struct clk arm_fck = {
++	.name		= "arm_fck",
++	.parent		= &mpu_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
++	.clksel_mask	= OMAP3430_ST_MPU_CLK_MASK,
++	.clksel		= arm_fck_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/*
++ * REVISIT: This clock is never specifically defined in the 3430 TRM,
++ * although it is referenced - so this is a guess
++ */
++static struct clk emu_mpu_alwon_ck = {
++	.name		= "emu_mpu_alwon_ck",
++	.parent		= &mpu_ck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk dpll2_fck = {
++	.name		= "dpll2_fck",
++	.parent		= &core_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
++	.clksel_mask	= OMAP3430_IVA2_CLK_SRC_MASK,
++	.clksel		= div2_core_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/*
++ * IVA2 clksel:
++ * If DPLL2 is locked, iva2_ck derives from DPLL2; otherwise, iva2_ck
++ * derives from the high-frequency bypass clock originating from DPLL3,
++ * called 'dpll2_fck'
++ */
++
++static const struct clksel iva2_clksel[] = {
++	{ .parent = &dpll2_fck,   .rates = dpll_bypass_rates },
++	{ .parent = &dpll2_m2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk iva2_ck = {
++	.name		= "iva2_ck",
++	.parent		= &dpll2_m2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD,
++					  OMAP3430_CM_IDLEST_PLL),
++	.clksel_mask	= OMAP3430_ST_IVA2_CLK_MASK,
++	.clksel		= iva2_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* Common interface clocks */
++
++static struct clk l3_ick = {
++	.name		= "l3_ick",
++	.parent		= &core_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_L3_MASK,
++	.clksel		= div2_core_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel div2_l3_clksel[] = {
++	{ .parent = &l3_ick, .rates = div2_rates },
++	{ .parent = NULL }
++};
++
++static struct clk l4_ick = {
++	.name		= "l4_ick",
++	.parent		= &l3_ick,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_L4_MASK,
++	.clksel		= div2_l3_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++
++};
++
++static const struct clksel div2_l4_clksel[] = {
++	{ .parent = &l4_ick, .rates = div2_rates },
++	{ .parent = NULL }
++};
++
++static struct clk rm_ick = {
++	.name		= "rm_ick",
++	.parent		= &l4_ick,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_RM_MASK,
++	.clksel		= div2_l4_clksel,
++	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* GFX power domain */
++
++/* GFX clocks are in 3430ES1 only. 3430ES2 and later uses the SGX instead */
++
++static const struct clksel gfx_l3_clksel[] = {
++	{ .parent = &l3_ick, .rates = gfx_l3_rates },
++	{ .parent = NULL }
++};
++
++static struct clk gfx_l3_fck = {
++	.name		= "gfx_l3_fck",
++	.parent		= &l3_ick,
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP_EN_GFX_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
++	.clksel		= gfx_l3_clksel,
++	.flags		= CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gfx_l3_ick = {
++	.name		= "gfx_l3_ick",
++	.parent		= &l3_ick,
++	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP_EN_GFX_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES1,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gfx_cg1_ck = {
++	.name		= "gfx_cg1_ck",
++	.parent		= &gfx_l3_fck, /* REVISIT: correct? */
++	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430ES1_EN_2D_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES1,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gfx_cg2_ck = {
++	.name		= "gfx_cg2_ck",
++	.parent		= &gfx_l3_fck, /* REVISIT: correct? */
++	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430ES1_EN_3D_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES1,
++	.recalc		= &followparent_recalc,
++};
++
++/* SGX power domain - 3430ES2 only */
++
++static const struct clksel_rate sgx_core_rates[] = {
++	{ .div = 3, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 4, .val = 1, .flags = RATE_IN_343X },
++	{ .div = 6, .val = 2, .flags = RATE_IN_343X },
++	{ .div = 0 },
++};
++
++static const struct clksel_rate sgx_96m_rates[] = {
++	{ .div = 1,  .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel sgx_clksel[] = {
++	{ .parent = &core_ck,	 .rates = sgx_core_rates },
++	{ .parent = &cm_96m_fck, .rates = sgx_96m_rates },
++	{ .parent = NULL },
++};
++
++static struct clk sgx_fck = {
++	.name		= "sgx_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430ES2_EN_SGX_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430ES2_CLKSEL_SGX_MASK,
++	.clksel		= sgx_clksel,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk sgx_ick = {
++	.name		= "sgx_ick",
++	.parent		= &l3_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430ES2_EN_SGX_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++/* CORE power domain */
++
++static struct clk d2d_26m_fck = {
++	.name		= "d2d_26m_fck",
++	.parent		= &sys_ck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430ES1_EN_D2D_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES1,
++	.recalc		= &followparent_recalc,
++};
++
++static const struct clksel omap343x_gpt_clksel[] = {
++	{ .parent = &omap_32k_fck, .rates = gpt_32k_rates },
++	{ .parent = &sys_ck,	   .rates = gpt_sys_rates },
++	{ .parent = NULL}
++};
++
++static struct clk gpt10_fck = {
++	.name		= "gpt10_fck",
++	.parent		= &sys_ck,
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_GPT10_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT10_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt11_fck = {
++	.name		= "gpt11_fck",
++	.parent		= &sys_ck,
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_GPT11_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT11_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk cpefuse_fck = {
++	.name		= "cpefuse_fck",
++	.parent		= &sys_ck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
++	.enable_bit	= OMAP3430ES2_EN_CPEFUSE_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk ts_fck = {
++	.name		= "ts_fck",
++	.parent		= &omap_32k_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
++	.enable_bit	= OMAP3430ES2_EN_TS_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk usbtll_fck = {
++	.name		= "usbtll_fck",
++	.parent		= &omap_120m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
++	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++/* CORE 96M FCLK-derived clocks */
++
++static struct clk core_96m_fck = {
++	.name		= "core_96m_fck",
++	.parent		= &omap_96m_fck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs3_fck = {
++	.name		= "mmchs_fck",
++	.id		= 3,
++	.parent		= &core_96m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs2_fck = {
++	.name		= "mmchs_fck",
++	.id		= 2,
++	.parent		= &core_96m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mspro_fck = {
++	.name		= "mspro_fck",
++	.parent		= &core_96m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs1_fck = {
++	.name		= "mmchs_fck",
++	.id		= 1,
++	.parent		= &core_96m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c3_fck = {
++	.name		= "i2c_fck",
++	.id		= 3,
++	.parent		= &core_96m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c2_fck = {
++	.name		= "i2c_fck",
++	.id 		= 2,
++	.parent		= &core_96m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c1_fck = {
++	.name		= "i2c_fck",
++	.id		= 1,
++	.parent		= &core_96m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++/*
++ * MCBSP 1 & 5 get their 96MHz clock from core_96m_fck;
++ * MCBSP 2, 3, 4 get their 96MHz clock from per_96m_fck.
++ */
++static const struct clksel_rate common_mcbsp_96m_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 }
++};
++
++static const struct clksel mcbsp_15_clksel[] = {
++	{ .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates },
++	{ .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
++	{ .parent = NULL }
++};
++
++static struct clk mcbsp5_fck = {
++	.name		= "mcbsp5_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_MCBSP5_SHIFT,
++	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
++	.clksel_mask	= OMAP2_MCBSP5_CLKS_MASK,
++	.clksel		= mcbsp_15_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk mcbsp1_fck = {
++	.name		= "mcbsp1_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_MCBSP1_SHIFT,
++	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
++	.clksel_mask	= OMAP2_MCBSP1_CLKS_MASK,
++	.clksel		= mcbsp_15_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* CORE_48M_FCK-derived clocks */
++
++static struct clk core_48m_fck = {
++	.name		= "core_48m_fck",
++	.parent		= &omap_48m_fck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi4_fck = {
++	.name		= "mcspi_fck",
++	.id		= 4,
++	.parent		= &core_48m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi3_fck = {
++	.name		= "mcspi_fck",
++	.id		= 3,
++	.parent		= &core_48m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi2_fck = {
++	.name		= "mcspi_fck",
++	.id		= 2,
++	.parent		= &core_48m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi1_fck = {
++	.name		= "mcspi_fck",
++	.id		= 1,
++	.parent		= &core_48m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart2_fck = {
++	.name		= "uart2_fck",
++	.parent		= &core_48m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart1_fck = {
++	.name		= "uart1_fck",
++	.parent		= &core_48m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk fshostusb_fck = {
++	.name		= "fshostusb_fck",
++	.parent		= &core_48m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES1,
++	.recalc		= &followparent_recalc,
++};
++
++/* CORE_12M_FCK based clocks */
++
++static struct clk core_12m_fck = {
++	.name		= "core_12m_fck",
++	.parent		= &omap_12m_fck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk hdq_fck = {
++	.name		= "hdq_fck",
++	.parent		= &core_12m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++/* DPLL3-derived clock */
++
++static const struct clksel_rate ssi_ssr_corex2_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_343X },
++	{ .div = 3, .val = 3, .flags = RATE_IN_343X },
++	{ .div = 4, .val = 4, .flags = RATE_IN_343X },
++	{ .div = 6, .val = 6, .flags = RATE_IN_343X },
++	{ .div = 8, .val = 8, .flags = RATE_IN_343X },
++	{ .div = 0 }
++};
++
++static const struct clksel ssi_ssr_clksel[] = {
++	{ .parent = &corex2_fck, .rates = ssi_ssr_corex2_rates },
++	{ .parent = NULL }
++};
++
++static struct clk ssi_ssr_fck = {
++	.name		= "ssi_ssr_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_SSI_MASK,
++	.clksel		= ssi_ssr_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk ssi_sst_fck = {
++	.name		= "ssi_sst_fck",
++	.parent		= &ssi_ssr_fck,
++	.fixed_div	= 2,
++	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
++	.recalc		= &omap2_fixed_divisor_recalc,
++};
++
++
++
++/* CORE_L3_ICK based clocks */
++
++static struct clk core_l3_ick = {
++	.name		= "core_l3_ick",
++	.parent		= &l3_ick,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk hsotgusb_ick = {
++	.name		= "hsotgusb_ick",
++	.parent		= &core_l3_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk sdrc_ick = {
++	.name		= "sdrc_ick",
++	.parent		= &core_l3_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_SDRC_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | ENABLE_ON_INIT,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpmc_fck = {
++	.name		= "gpmc_fck",
++	.parent		= &core_l3_ick,
++	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK |
++				ENABLE_ON_INIT,
++	.recalc		= &followparent_recalc,
++};
++
++/* SECURITY_L3_ICK based clocks */
++
++static struct clk security_l3_ick = {
++	.name		= "security_l3_ick",
++	.parent		= &l3_ick,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk pka_ick = {
++	.name		= "pka_ick",
++	.parent		= &security_l3_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP3430_EN_PKA_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++/* CORE_L4_ICK based clocks */
++
++static struct clk core_l4_ick = {
++	.name		= "core_l4_ick",
++	.parent		= &l4_ick,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk usbtll_ick = {
++	.name		= "usbtll_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
++	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs3_ick = {
++	.name		= "mmchs_ick",
++	.id		= 3,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++/* Intersystem Communication Registers - chassis mode only */
++static struct clk icr_ick = {
++	.name		= "icr_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_ICR_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk aes2_ick = {
++	.name		= "aes2_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_AES2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk sha12_ick = {
++	.name		= "sha12_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_SHA12_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk des2_ick = {
++	.name		= "des2_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_DES2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs2_ick = {
++	.name		= "mmchs_ick",
++	.id		= 2,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mmchs1_ick = {
++	.name		= "mmchs_ick",
++	.id		= 1,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mspro_ick = {
++	.name		= "mspro_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk hdq_ick = {
++	.name		= "hdq_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi4_ick = {
++	.name		= "mcspi_ick",
++	.id		= 4,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi3_ick = {
++	.name		= "mcspi_ick",
++	.id		= 3,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi2_ick = {
++	.name		= "mcspi_ick",
++	.id		= 2,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcspi1_ick = {
++	.name		= "mcspi_ick",
++	.id		= 1,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c3_ick = {
++	.name		= "i2c_ick",
++	.id		= 3,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c2_ick = {
++	.name		= "i2c_ick",
++	.id		= 2,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk i2c1_ick = {
++	.name		= "i2c_ick",
++	.id		= 1,
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart2_ick = {
++	.name		= "uart2_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart1_ick = {
++	.name		= "uart1_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt11_ick = {
++	.name		= "gpt11_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_GPT11_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt10_ick = {
++	.name		= "gpt10_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_GPT10_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp5_ick = {
++	.name		= "mcbsp5_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MCBSP5_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp1_ick = {
++	.name		= "mcbsp1_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MCBSP1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk fac_ick = {
++	.name		= "fac_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430ES1_EN_FAC_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES1,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mailboxes_ick = {
++	.name		= "mailboxes_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_MAILBOXES_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk omapctrl_ick = {
++	.name		= "omapctrl_ick",
++	.parent		= &core_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_OMAPCTRL_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | ENABLE_ON_INIT,
++	.recalc		= &followparent_recalc,
++};
++
++/* SSI_L4_ICK based clocks */
++
++static struct clk ssi_l4_ick = {
++	.name		= "ssi_l4_ick",
++	.parent		= &l4_ick,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk ssi_ick = {
++	.name		= "ssi_ick",
++	.parent		= &ssi_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++/* REVISIT: Technically the TRM claims that this is CORE_CLK based,
++ * but l4_ick makes more sense to me */
++
++static const struct clksel usb_l4_clksel[] = {
++	{ .parent = &l4_ick, .rates = div2_rates },
++	{ .parent = NULL },
++};
++
++static struct clk usb_l4_ick = {
++	.name		= "usb_l4_ick",
++	.parent		= &l4_ick,
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++	.enable_bit	= OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
++	.clksel		= usb_l4_clksel,
++	.flags		= CLOCK_IN_OMAP3430ES1,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* XXX MDM_INTC_ICK, SAD2D_ICK ?? */
++
++/* SECURITY_L4_ICK2 based clocks */
++
++static struct clk security_l4_ick2 = {
++	.name		= "security_l4_ick2",
++	.parent		= &l4_ick,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk aes1_ick = {
++	.name		= "aes1_ick",
++	.parent		= &security_l4_ick2,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP3430_EN_AES1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk rng_ick = {
++	.name		= "rng_ick",
++	.parent		= &security_l4_ick2,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP3430_EN_RNG_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk sha11_ick = {
++	.name		= "sha11_ick",
++	.parent		= &security_l4_ick2,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP3430_EN_SHA11_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk des1_ick = {
++	.name		= "des1_ick",
++	.parent		= &security_l4_ick2,
++	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++	.enable_bit	= OMAP3430_EN_DES1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++/* DSS */
++static const struct clksel dss1_alwon_fck_clksel[] = {
++	{ .parent = &sys_ck,        .rates = dpll_bypass_rates },
++	{ .parent = &dpll4_m4x2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk dss1_alwon_fck = {
++	.name		= "dss1_alwon_fck",
++	.parent		= &dpll4_m4x2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_DSS1_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++	.clksel_mask	= OMAP3430_ST_PERIPH_CLK,
++	.clksel		= dss1_alwon_fck_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk dss_tv_fck = {
++	.name		= "dss_tv_fck",
++	.parent		= &omap_54m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_TV_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk dss_96m_fck = {
++	.name		= "dss_96m_fck",
++	.parent		= &omap_96m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_TV_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk dss2_alwon_fck = {
++	.name		= "dss2_alwon_fck",
++	.parent		= &sys_ck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_DSS2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk dss_ick = {
++	/* Handles both L3 and L4 clocks */
++	.name		= "dss_ick",
++	.parent		= &l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++/* CAM */
++
++static const struct clksel cam_mclk_clksel[] = {
++	{ .parent = &sys_ck,        .rates = dpll_bypass_rates },
++	{ .parent = &dpll4_m5x2_ck, .rates = dpll_locked_rates },
++	{ .parent = NULL }
++};
++
++static struct clk cam_mclk = {
++	.name		= "cam_mclk",
++	.parent		= &dpll4_m5x2_ck,
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++	.clksel_mask	= OMAP3430_ST_PERIPH_CLK,
++	.clksel		= cam_mclk_clksel,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk cam_l3_ick = {
++	.name		= "cam_l3_ick",
++	.parent		= &l3_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk cam_l4_ick = {
++	.name		= "cam_l4_ick",
++	.parent		= &l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++/* USBHOST - 3430ES2 only */
++
++static struct clk usbhost_120m_fck = {
++	.name		= "usbhost_120m_fck",
++	.parent		= &omap_120m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430ES2_EN_USBHOST2_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk usbhost_48m_fck = {
++	.name		= "usbhost_48m_fck",
++	.parent		= &omap_48m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430ES2_EN_USBHOST1_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk usbhost_l3_ick = {
++	.name		= "usbhost_l3_ick",
++	.parent		= &l3_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430ES2_EN_USBHOST_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk usbhost_l4_ick = {
++	.name		= "usbhost_l4_ick",
++	.parent		= &l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430ES2_EN_USBHOST_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk usbhost_sar_fck = {
++	.name		= "usbhost_sar_fck",
++	.parent		= &osc_sys_ck,
++	.enable_reg	= OMAP_PRM_REGADDR(OMAP3430ES2_USBHOST_MOD, PM_PWSTCTRL),
++	.enable_bit	= OMAP3430ES2_SAVEANDRESTORE_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++/* WKUP */
++
++static const struct clksel_rate usim_96m_rates[] = {
++	{ .div = 2,  .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 4,  .val = 4, .flags = RATE_IN_343X },
++	{ .div = 8,  .val = 5, .flags = RATE_IN_343X },
++	{ .div = 10, .val = 6, .flags = RATE_IN_343X },
++	{ .div = 0 },
++};
++
++static const struct clksel_rate usim_120m_rates[] = {
++	{ .div = 4,  .val = 7,	.flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 8,  .val = 8,	.flags = RATE_IN_343X },
++	{ .div = 16, .val = 9,	.flags = RATE_IN_343X },
++	{ .div = 20, .val = 10, .flags = RATE_IN_343X },
++	{ .div = 0 },
++};
++
++static const struct clksel usim_clksel[] = {
++	{ .parent = &omap_96m_fck,	.rates = usim_96m_rates },
++	{ .parent = &omap_120m_fck,	.rates = usim_120m_rates },
++	{ .parent = &sys_ck,		.rates = div2_rates },
++	{ .parent = NULL },
++};
++
++/* 3430ES2 only */
++static struct clk usim_fck = {
++	.name		= "usim_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430ES2_CLKSEL_USIMOCP_MASK,
++	.clksel		= usim_clksel,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt1_fck = {
++	.name		= "gpt1_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT1_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk wkup_32k_fck = {
++	.name		= "wkup_32k_fck",
++	.parent		= &omap_32k_fck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio1_fck = {
++	.name		= "gpio1_fck",
++	.parent		= &wkup_32k_fck,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt2_fck = {
++	.name		= "wdt2_fck",
++	.parent		= &wkup_32k_fck,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wkup_l4_ick = {
++	.name		= "wkup_l4_ick",
++	.parent		= &sys_ck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &followparent_recalc,
++};
++
++/* 3430ES2 only */
++/* Never specifically named in the TRM, so we have to infer a likely name */
++static struct clk usim_ick = {
++	.name		= "usim_ick",
++	.parent		= &wkup_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
++	.flags		= CLOCK_IN_OMAP3430ES2,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt2_ick = {
++	.name		= "wdt2_ick",
++	.parent		= &wkup_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt1_ick = {
++	.name		= "wdt1_ick",
++	.parent		= &wkup_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_WDT1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio1_ick = {
++	.name		= "gpio1_ick",
++	.parent		= &wkup_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk omap_32ksync_ick = {
++	.name		= "omap_32ksync_ick",
++	.parent		= &wkup_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_32KSYNC_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt12_ick = {
++	.name		= "gpt12_ick",
++	.parent		= &wkup_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT12_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt1_ick = {
++	.name		= "gpt1_ick",
++	.parent		= &wkup_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++
++
++/* PER clock domain */
++
++static struct clk per_96m_fck = {
++	.name		= "per_96m_fck",
++	.parent		= &omap_96m_alwon_fck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk per_48m_fck = {
++	.name		= "per_48m_fck",
++	.parent		= &omap_48m_fck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart3_fck = {
++	.name		= "uart3_fck",
++	.parent		= &per_48m_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt2_fck = {
++	.name		= "gpt2_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT2_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt3_fck = {
++	.name		= "gpt3_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT3_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt4_fck = {
++	.name		= "gpt4_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT4_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt5_fck = {
++	.name		= "gpt5_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT5_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt6_fck = {
++	.name		= "gpt6_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT6_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt7_fck = {
++	.name		= "gpt7_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT7_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt8_fck = {
++	.name		= "gpt8_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT8_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk gpt9_fck = {
++	.name		= "gpt9_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++	.clksel_mask	= OMAP3430_CLKSEL_GPT9_MASK,
++	.clksel		= omap343x_gpt_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk per_32k_alwon_fck = {
++	.name		= "per_32k_alwon_fck",
++	.parent		= &omap_32k_fck,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio6_fck = {
++	.name		= "gpio6_fck",
++	.parent		= &per_32k_alwon_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio5_fck = {
++	.name		= "gpio5_fck",
++	.parent		= &per_32k_alwon_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio4_fck = {
++	.name		= "gpio4_fck",
++	.parent		= &per_32k_alwon_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio3_fck = {
++	.name		= "gpio3_fck",
++	.parent		= &per_32k_alwon_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio2_fck = {
++	.name		= "gpio2_fck",
++	.parent		= &per_32k_alwon_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt3_fck = {
++	.name		= "wdt3_fck",
++	.parent		= &per_32k_alwon_fck,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk per_l4_ick = {
++	.name		= "per_l4_ick",
++	.parent		= &l4_ick,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++				PARENT_CONTROLS_CLOCK,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio6_ick = {
++	.name		= "gpio6_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio5_ick = {
++	.name		= "gpio5_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio4_ick = {
++	.name		= "gpio4_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio3_ick = {
++	.name		= "gpio3_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpio2_ick = {
++	.name		= "gpio2_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt3_ick = {
++	.name		= "wdt3_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk uart3_ick = {
++	.name		= "uart3_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt9_ick = {
++	.name		= "gpt9_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt8_ick = {
++	.name		= "gpt8_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt7_ick = {
++	.name		= "gpt7_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt6_ick = {
++	.name		= "gpt6_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt5_ick = {
++	.name		= "gpt5_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt4_ick = {
++	.name		= "gpt4_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt3_ick = {
++	.name		= "gpt3_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk gpt2_ick = {
++	.name		= "gpt2_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp2_ick = {
++	.name		= "mcbsp2_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_MCBSP2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp3_ick = {
++	.name		= "mcbsp3_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_MCBSP3_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk mcbsp4_ick = {
++	.name		= "mcbsp4_ick",
++	.parent		= &per_l4_ick,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++	.enable_bit	= OMAP3430_EN_MCBSP4_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++static const struct clksel mcbsp_234_clksel[] = {
++	{ .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates },
++	{ .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
++	{ .parent = NULL }
++};
++
++static struct clk mcbsp2_fck = {
++	.name		= "mcbsp2_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_MCBSP2_SHIFT,
++	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
++	.clksel_mask	= OMAP2_MCBSP2_CLKS_MASK,
++	.clksel		= mcbsp_234_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk mcbsp3_fck = {
++	.name		= "mcbsp3_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_MCBSP3_SHIFT,
++	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
++	.clksel_mask	= OMAP2_MCBSP3_CLKS_MASK,
++	.clksel		= mcbsp_234_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk mcbsp4_fck = {
++	.name		= "mcbsp4_fck",
++	.init		= &omap2_init_clksel_parent,
++	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_MCBSP4_SHIFT,
++	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
++	.clksel_mask	= OMAP2_MCBSP4_CLKS_MASK,
++	.clksel		= mcbsp_234_clksel,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* EMU clocks */
++
++/* More information: ARM Cortex-A8 Technical Reference Manual, sect 10.1 */
++
++static const struct clksel_rate emu_src_sys_rates[] = {
++	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel_rate emu_src_core_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel_rate emu_src_per_rates[] = {
++	{ .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel_rate emu_src_mpu_rates[] = {
++	{ .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 0 },
++};
++
++static const struct clksel emu_src_clksel[] = {
++	{ .parent = &sys_ck,		.rates = emu_src_sys_rates },
++	{ .parent = &emu_core_alwon_ck, .rates = emu_src_core_rates },
++	{ .parent = &emu_per_alwon_ck,	.rates = emu_src_per_rates },
++	{ .parent = &emu_mpu_alwon_ck,	.rates = emu_src_mpu_rates },
++	{ .parent = NULL },
++};
++
++/*
++ * Like the clkout_src clocks, emu_src_clk is a virtual clock, existing only
++ * to switch the source of some of the EMU clocks.
++ * XXX Are there CLKEN bits for these EMU clks?
++ */
++static struct clk emu_src_ck = {
++	.name		= "emu_src_ck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_MUX_CTRL_MASK,
++	.clksel		= emu_src_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate pclk_emu_rates[] = {
++	{ .div = 2, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 3, .val = 3, .flags = RATE_IN_343X },
++	{ .div = 4, .val = 4, .flags = RATE_IN_343X },
++	{ .div = 6, .val = 6, .flags = RATE_IN_343X },
++	{ .div = 0 },
++};
++
++static const struct clksel pclk_emu_clksel[] = {
++	{ .parent = &emu_src_ck, .rates = pclk_emu_rates },
++	{ .parent = NULL },
++};
++
++static struct clk pclk_fck = {
++	.name		= "pclk_fck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_CLKSEL_PCLK_MASK,
++	.clksel		= pclk_emu_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate pclkx2_emu_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_343X },
++	{ .div = 3, .val = 3, .flags = RATE_IN_343X },
++	{ .div = 0 },
++};
++
++static const struct clksel pclkx2_emu_clksel[] = {
++	{ .parent = &emu_src_ck, .rates = pclkx2_emu_rates },
++	{ .parent = NULL },
++};
++
++static struct clk pclkx2_fck = {
++	.name		= "pclkx2_fck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_CLKSEL_PCLKX2_MASK,
++	.clksel		= pclkx2_emu_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel atclk_emu_clksel[] = {
++	{ .parent = &emu_src_ck, .rates = div2_rates },
++	{ .parent = NULL },
++};
++
++static struct clk atclk_fck = {
++	.name		= "atclk_fck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_CLKSEL_ATCLK_MASK,
++	.clksel		= atclk_emu_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static struct clk traceclk_src_fck = {
++	.name		= "traceclk_src_fck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_TRACE_MUX_CTRL_MASK,
++	.clksel		= emu_src_clksel,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate traceclk_rates[] = {
++	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++	{ .div = 2, .val = 2, .flags = RATE_IN_343X },
++	{ .div = 4, .val = 4, .flags = RATE_IN_343X },
++	{ .div = 0 },
++};
++
++static const struct clksel traceclk_clksel[] = {
++	{ .parent = &traceclk_src_fck, .rates = traceclk_rates },
++	{ .parent = NULL },
++};
++
++static struct clk traceclk_fck = {
++	.name		= "traceclk_fck",
++	.init		= &omap2_init_clksel_parent,
++	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++	.clksel_mask	= OMAP3430_CLKSEL_TRACECLK_MASK,
++	.clksel		= traceclk_clksel,
++	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
++	.recalc		= &omap2_clksel_recalc,
++};
++
++/* SR clocks */
++
++/* SmartReflex fclk (VDD1) */
++static struct clk sr1_fck = {
++	.name		= "sr1_fck",
++	.parent		= &sys_ck,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_SR1_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++	.recalc		= &followparent_recalc,
++};
++
++/* SmartReflex fclk (VDD2) */
++static struct clk sr2_fck = {
++	.name		= "sr2_fck",
++	.parent		= &sys_ck,
++	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++	.enable_bit	= OMAP3430_EN_SR2_SHIFT,
++	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk sr_l4_ick = {
++	.name		= "sr_l4_ick",
++	.parent		= &l4_ick,
++	.flags		= CLOCK_IN_OMAP343X,
++	.recalc		= &followparent_recalc,
++};
++
++/* SECURE_32K_FCK clocks */
++
++static struct clk gpt12_fck = {
++	.name		= "gpt12_fck",
++	.parent		= &secure_32k_fck,
++	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk wdt1_fck = {
++	.name		= "wdt1_fck",
++	.parent		= &secure_32k_fck,
++	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
++	.recalc		= &followparent_recalc,
++};
++
++static struct clk *onchip_34xx_clks[] __initdata = {
++	&omap_32k_fck,
++	&virt_12m_ck,
++	&virt_13m_ck,
++	&virt_16_8m_ck,
++	&virt_19_2m_ck,
++	&virt_26m_ck,
++	&virt_38_4m_ck,
++	&osc_sys_ck,
++	&sys_ck,
++	&sys_altclk,
++	&mcbsp_clks,
++	&sys_clkout1,
++	&dpll1_ck,
++	&dpll1_x2_ck,
++	&dpll1_x2m2_ck,
++	&dpll2_ck,
++	&dpll2_m2_ck,
++	&dpll3_ck,
++	&core_ck,
++	&dpll3_x2_ck,
++	&dpll3_m2_ck,
++	&dpll3_m2x2_ck,
++	&dpll3_m3_ck,
++	&dpll3_m3x2_ck,
++	&emu_core_alwon_ck,
++	&dpll4_ck,
++	&dpll4_x2_ck,
++	&omap_96m_alwon_fck,
++	&omap_96m_fck,
++	&cm_96m_fck,
++	&virt_omap_54m_fck,
++	&omap_54m_fck,
++	&omap_48m_fck,
++	&omap_12m_fck,
++	&dpll4_m2_ck,
++	&dpll4_m2x2_ck,
++	&dpll4_m3_ck,
++	&dpll4_m3x2_ck,
++	&dpll4_m4_ck,
++	&dpll4_m4x2_ck,
++	&dpll4_m5_ck,
++	&dpll4_m5x2_ck,
++	&dpll4_m6_ck,
++	&dpll4_m6x2_ck,
++	&emu_per_alwon_ck,
++	&dpll5_ck,
++	&dpll5_m2_ck,
++	&omap_120m_fck,
++	&clkout2_src_ck,
++	&sys_clkout2,
++	&corex2_fck,
++	&dpll1_fck,
++	&mpu_ck,
++	&arm_fck,
++	&emu_mpu_alwon_ck,
++	&dpll2_fck,
++	&iva2_ck,
++	&l3_ick,
++	&l4_ick,
++	&rm_ick,
++	&gfx_l3_fck,
++	&gfx_l3_ick,
++	&gfx_cg1_ck,
++	&gfx_cg2_ck,
++	&sgx_fck,
++	&sgx_ick,
++	&d2d_26m_fck,
++	&gpt10_fck,
++	&gpt11_fck,
++	&cpefuse_fck,
++	&ts_fck,
++	&usbtll_fck,
++	&core_96m_fck,
++	&mmchs3_fck,
++	&mmchs2_fck,
++	&mspro_fck,
++	&mmchs1_fck,
++	&i2c3_fck,
++	&i2c2_fck,
++	&i2c1_fck,
++	&mcbsp5_fck,
++	&mcbsp1_fck,
++	&core_48m_fck,
++	&mcspi4_fck,
++	&mcspi3_fck,
++	&mcspi2_fck,
++	&mcspi1_fck,
++	&uart2_fck,
++	&uart1_fck,
++	&fshostusb_fck,
++	&core_12m_fck,
++	&hdq_fck,
++	&ssi_ssr_fck,
++	&ssi_sst_fck,
++	&core_l3_ick,
++	&hsotgusb_ick,
++	&sdrc_ick,
++	&gpmc_fck,
++	&security_l3_ick,
++	&pka_ick,
++	&core_l4_ick,
++	&usbtll_ick,
++	&mmchs3_ick,
++	&icr_ick,
++	&aes2_ick,
++	&sha12_ick,
++	&des2_ick,
++	&mmchs2_ick,
++	&mmchs1_ick,
++	&mspro_ick,
++	&hdq_ick,
++	&mcspi4_ick,
++	&mcspi3_ick,
++	&mcspi2_ick,
++	&mcspi1_ick,
++	&i2c3_ick,
++	&i2c2_ick,
++	&i2c1_ick,
++	&uart2_ick,
++	&uart1_ick,
++	&gpt11_ick,
++	&gpt10_ick,
++	&mcbsp5_ick,
++	&mcbsp1_ick,
++	&fac_ick,
++	&mailboxes_ick,
++	&omapctrl_ick,
++	&ssi_l4_ick,
++	&ssi_ick,
++	&usb_l4_ick,
++	&security_l4_ick2,
++	&aes1_ick,
++	&rng_ick,
++	&sha11_ick,
++	&des1_ick,
++	&dss1_alwon_fck,
++	&dss_tv_fck,
++	&dss_96m_fck,
++	&dss2_alwon_fck,
++	&dss_ick,
++	&cam_mclk,
++	&cam_l3_ick,
++	&cam_l4_ick,
++	&usbhost_120m_fck,
++	&usbhost_48m_fck,
++	&usbhost_l3_ick,
++	&usbhost_l4_ick,
++	&usbhost_sar_fck,
++	&usim_fck,
++	&gpt1_fck,
++	&wkup_32k_fck,
++	&gpio1_fck,
++	&wdt2_fck,
++	&wkup_l4_ick,
++	&usim_ick,
++	&wdt2_ick,
++	&wdt1_ick,
++	&gpio1_ick,
++	&omap_32ksync_ick,
++	&gpt12_ick,
++	&gpt1_ick,
++	&per_96m_fck,
++	&per_48m_fck,
++	&uart3_fck,
++	&gpt2_fck,
++	&gpt3_fck,
++	&gpt4_fck,
++	&gpt5_fck,
++	&gpt6_fck,
++	&gpt7_fck,
++	&gpt8_fck,
++	&gpt9_fck,
++	&per_32k_alwon_fck,
++	&gpio6_fck,
++	&gpio5_fck,
++	&gpio4_fck,
++	&gpio3_fck,
++	&gpio2_fck,
++	&wdt3_fck,
++	&per_l4_ick,
++	&gpio6_ick,
++	&gpio5_ick,
++	&gpio4_ick,
++	&gpio3_ick,
++	&gpio2_ick,
++	&wdt3_ick,
++	&uart3_ick,
++	&gpt9_ick,
++	&gpt8_ick,
++	&gpt7_ick,
++	&gpt6_ick,
++	&gpt5_ick,
++	&gpt4_ick,
++	&gpt3_ick,
++	&gpt2_ick,
++	&mcbsp2_ick,
++	&mcbsp3_ick,
++	&mcbsp4_ick,
++	&mcbsp2_fck,
++	&mcbsp3_fck,
++	&mcbsp4_fck,
++	&emu_src_ck,
++	&pclk_fck,
++	&pclkx2_fck,
++	&atclk_fck,
++	&traceclk_src_fck,
++	&traceclk_fck,
++	&sr1_fck,
++	&sr2_fck,
++	&sr_l4_ick,
++	&secure_32k_fck,
++	&gpt12_fck,
++	&wdt1_fck,
++};
++
++#endif
+diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h
+new file mode 100644
+index 0000000..20ac381
+--- /dev/null
++++ b/arch/arm/mach-omap2/cm-regbits-24xx.h
+@@ -0,0 +1,401 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_24XX_H
++#define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_24XX_H
++
++/*
++ * OMAP24XX Clock Management register bits
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "cm.h"
++
++/* Bits shared between registers */
++
++/* CM_FCLKEN1_CORE and CM_ICLKEN1_CORE shared bits */
++#define OMAP24XX_EN_CAM_SHIFT				31
++#define OMAP24XX_EN_CAM					(1 << 31)
++#define OMAP24XX_EN_WDT4_SHIFT				29
++#define OMAP24XX_EN_WDT4				(1 << 29)
++#define OMAP2420_EN_WDT3_SHIFT				28
++#define OMAP2420_EN_WDT3				(1 << 28)
++#define OMAP24XX_EN_MSPRO_SHIFT				27
++#define OMAP24XX_EN_MSPRO				(1 << 27)
++#define OMAP24XX_EN_FAC_SHIFT				25
++#define OMAP24XX_EN_FAC					(1 << 25)
++#define OMAP2420_EN_EAC_SHIFT				24
++#define OMAP2420_EN_EAC					(1 << 24)
++#define OMAP24XX_EN_HDQ_SHIFT				23
++#define OMAP24XX_EN_HDQ					(1 << 23)
++#define OMAP2420_EN_I2C2_SHIFT				20
++#define OMAP2420_EN_I2C2				(1 << 20)
++#define OMAP2420_EN_I2C1_SHIFT				19
++#define OMAP2420_EN_I2C1				(1 << 19)
++
++/* CM_FCLKEN2_CORE and CM_ICLKEN2_CORE shared bits */
++#define OMAP2430_EN_MCBSP5_SHIFT			5
++#define OMAP2430_EN_MCBSP5				(1 << 5)
++#define OMAP2430_EN_MCBSP4_SHIFT			4
++#define OMAP2430_EN_MCBSP4				(1 << 4)
++#define OMAP2430_EN_MCBSP3_SHIFT			3
++#define OMAP2430_EN_MCBSP3				(1 << 3)
++#define OMAP24XX_EN_SSI_SHIFT				1
++#define OMAP24XX_EN_SSI					(1 << 1)
++
++/* CM_FCLKEN_WKUP and CM_ICLKEN_WKUP shared bits */
++#define OMAP24XX_EN_MPU_WDT_SHIFT			3
++#define OMAP24XX_EN_MPU_WDT				(1 << 3)
++
++/* Bits specific to each register */
++
++/* CM_IDLEST_MPU */
++/* 2430 only */
++#define OMAP2430_ST_MPU					(1 << 0)
++
++/* CM_CLKSEL_MPU */
++#define OMAP24XX_CLKSEL_MPU_SHIFT			0
++#define OMAP24XX_CLKSEL_MPU_MASK			(0x1f << 0)
++
++/* CM_CLKSTCTRL_MPU */
++#define OMAP24XX_AUTOSTATE_MPU				(1 << 0)
++
++/* CM_FCLKEN1_CORE specific bits*/
++#define OMAP24XX_EN_TV_SHIFT				2
++#define OMAP24XX_EN_TV					(1 << 2)
++#define OMAP24XX_EN_DSS2_SHIFT				1
++#define OMAP24XX_EN_DSS2				(1 << 1)
++#define OMAP24XX_EN_DSS1_SHIFT				0
++#define OMAP24XX_EN_DSS1				(1 << 0)
++
++/* CM_FCLKEN2_CORE specific bits */
++#define OMAP2430_EN_I2CHS2_SHIFT			20
++#define OMAP2430_EN_I2CHS2				(1 << 20)
++#define OMAP2430_EN_I2CHS1_SHIFT			19
++#define OMAP2430_EN_I2CHS1				(1 << 19)
++#define OMAP2430_EN_MMCHSDB2_SHIFT			17
++#define OMAP2430_EN_MMCHSDB2				(1 << 17)
++#define OMAP2430_EN_MMCHSDB1_SHIFT			16
++#define OMAP2430_EN_MMCHSDB1				(1 << 16)
++
++/* CM_ICLKEN1_CORE specific bits */
++#define OMAP24XX_EN_MAILBOXES_SHIFT			30
++#define OMAP24XX_EN_MAILBOXES				(1 << 30)
++#define OMAP24XX_EN_DSS_SHIFT				0
++#define OMAP24XX_EN_DSS					(1 << 0)
++
++/* CM_ICLKEN2_CORE specific bits */
++
++/* CM_ICLKEN3_CORE */
++/* 2430 only */
++#define OMAP2430_EN_SDRC_SHIFT				2
++#define OMAP2430_EN_SDRC				(1 << 2)
++
++/* CM_ICLKEN4_CORE */
++#define OMAP24XX_EN_PKA_SHIFT				4
++#define OMAP24XX_EN_PKA					(1 << 4)
++#define OMAP24XX_EN_AES_SHIFT				3
++#define OMAP24XX_EN_AES					(1 << 3)
++#define OMAP24XX_EN_RNG_SHIFT				2
++#define OMAP24XX_EN_RNG					(1 << 2)
++#define OMAP24XX_EN_SHA_SHIFT				1
++#define OMAP24XX_EN_SHA					(1 << 1)
++#define OMAP24XX_EN_DES_SHIFT				0
++#define OMAP24XX_EN_DES					(1 << 0)
++
++/* CM_IDLEST1_CORE specific bits */
++#define OMAP24XX_ST_MAILBOXES				(1 << 30)
++#define OMAP24XX_ST_WDT4				(1 << 29)
++#define OMAP2420_ST_WDT3				(1 << 28)
++#define OMAP24XX_ST_MSPRO				(1 << 27)
++#define OMAP24XX_ST_FAC					(1 << 25)
++#define OMAP2420_ST_EAC					(1 << 24)
++#define OMAP24XX_ST_HDQ					(1 << 23)
++#define OMAP24XX_ST_I2C2				(1 << 20)
++#define OMAP24XX_ST_I2C1				(1 << 19)
++#define OMAP24XX_ST_MCBSP2				(1 << 16)
++#define OMAP24XX_ST_MCBSP1				(1 << 15)
++#define OMAP24XX_ST_DSS					(1 << 0)
++
++/* CM_IDLEST2_CORE */
++#define OMAP2430_ST_MCBSP5				(1 << 5)
++#define OMAP2430_ST_MCBSP4				(1 << 4)
++#define OMAP2430_ST_MCBSP3				(1 << 3)
++#define OMAP24XX_ST_SSI					(1 << 1)
++
++/* CM_IDLEST3_CORE */
++/* 2430 only */
++#define OMAP2430_ST_SDRC				(1 << 2)
++
++/* CM_IDLEST4_CORE */
++#define OMAP24XX_ST_PKA					(1 << 4)
++#define OMAP24XX_ST_AES					(1 << 3)
++#define OMAP24XX_ST_RNG					(1 << 2)
++#define OMAP24XX_ST_SHA					(1 << 1)
++#define OMAP24XX_ST_DES					(1 << 0)
++
++/* CM_AUTOIDLE1_CORE */
++#define OMAP24XX_AUTO_CAM				(1 << 31)
++#define OMAP24XX_AUTO_MAILBOXES				(1 << 30)
++#define OMAP24XX_AUTO_WDT4				(1 << 29)
++#define OMAP2420_AUTO_WDT3				(1 << 28)
++#define OMAP24XX_AUTO_MSPRO				(1 << 27)
++#define OMAP2420_AUTO_MMC				(1 << 26)
++#define OMAP24XX_AUTO_FAC				(1 << 25)
++#define OMAP2420_AUTO_EAC				(1 << 24)
++#define OMAP24XX_AUTO_HDQ				(1 << 23)
++#define OMAP24XX_AUTO_UART2				(1 << 22)
++#define OMAP24XX_AUTO_UART1				(1 << 21)
++#define OMAP24XX_AUTO_I2C2				(1 << 20)
++#define OMAP24XX_AUTO_I2C1				(1 << 19)
++#define OMAP24XX_AUTO_MCSPI2				(1 << 18)
++#define OMAP24XX_AUTO_MCSPI1				(1 << 17)
++#define OMAP24XX_AUTO_MCBSP2				(1 << 16)
++#define OMAP24XX_AUTO_MCBSP1				(1 << 15)
++#define OMAP24XX_AUTO_GPT12				(1 << 14)
++#define OMAP24XX_AUTO_GPT11				(1 << 13)
++#define OMAP24XX_AUTO_GPT10				(1 << 12)
++#define OMAP24XX_AUTO_GPT9				(1 << 11)
++#define OMAP24XX_AUTO_GPT8				(1 << 10)
++#define OMAP24XX_AUTO_GPT7				(1 << 9)
++#define OMAP24XX_AUTO_GPT6				(1 << 8)
++#define OMAP24XX_AUTO_GPT5				(1 << 7)
++#define OMAP24XX_AUTO_GPT4				(1 << 6)
++#define OMAP24XX_AUTO_GPT3				(1 << 5)
++#define OMAP24XX_AUTO_GPT2				(1 << 4)
++#define OMAP2420_AUTO_VLYNQ				(1 << 3)
++#define OMAP24XX_AUTO_DSS				(1 << 0)
++
++/* CM_AUTOIDLE2_CORE */
++#define OMAP2430_AUTO_MDM_INTC				(1 << 11)
++#define OMAP2430_AUTO_GPIO5				(1 << 10)
++#define OMAP2430_AUTO_MCSPI3				(1 << 9)
++#define OMAP2430_AUTO_MMCHS2				(1 << 8)
++#define OMAP2430_AUTO_MMCHS1				(1 << 7)
++#define OMAP2430_AUTO_USBHS				(1 << 6)
++#define OMAP2430_AUTO_MCBSP5				(1 << 5)
++#define OMAP2430_AUTO_MCBSP4				(1 << 4)
++#define OMAP2430_AUTO_MCBSP3				(1 << 3)
++#define OMAP24XX_AUTO_UART3				(1 << 2)
++#define OMAP24XX_AUTO_SSI				(1 << 1)
++#define OMAP24XX_AUTO_USB				(1 << 0)
++
++/* CM_AUTOIDLE3_CORE */
++#define OMAP24XX_AUTO_SDRC				(1 << 2)
++#define OMAP24XX_AUTO_GPMC				(1 << 1)
++#define OMAP24XX_AUTO_SDMA				(1 << 0)
++
++/* CM_AUTOIDLE4_CORE */
++#define OMAP24XX_AUTO_PKA				(1 << 4)
++#define OMAP24XX_AUTO_AES				(1 << 3)
++#define OMAP24XX_AUTO_RNG				(1 << 2)
++#define OMAP24XX_AUTO_SHA				(1 << 1)
++#define OMAP24XX_AUTO_DES				(1 << 0)
++
++/* CM_CLKSEL1_CORE */
++#define OMAP24XX_CLKSEL_USB_SHIFT			25
++#define OMAP24XX_CLKSEL_USB_MASK			(0x7 << 25)
++#define OMAP24XX_CLKSEL_SSI_SHIFT			20
++#define OMAP24XX_CLKSEL_SSI_MASK			(0x1f << 20)
++#define OMAP2420_CLKSEL_VLYNQ_SHIFT			15
++#define OMAP2420_CLKSEL_VLYNQ_MASK			(0x1f << 15)
++#define OMAP24XX_CLKSEL_DSS2_SHIFT			13
++#define OMAP24XX_CLKSEL_DSS2_MASK			(0x1 << 13)
++#define OMAP24XX_CLKSEL_DSS1_SHIFT			8
++#define OMAP24XX_CLKSEL_DSS1_MASK			(0x1f << 8)
++#define OMAP24XX_CLKSEL_L4_SHIFT			5
++#define OMAP24XX_CLKSEL_L4_MASK				(0x3 << 5)
++#define OMAP24XX_CLKSEL_L3_SHIFT			0
++#define OMAP24XX_CLKSEL_L3_MASK				(0x1f << 0)
++
++/* CM_CLKSEL2_CORE */
++#define OMAP24XX_CLKSEL_GPT12_SHIFT			22
++#define OMAP24XX_CLKSEL_GPT12_MASK			(0x3 << 22)
++#define OMAP24XX_CLKSEL_GPT11_SHIFT			20
++#define OMAP24XX_CLKSEL_GPT11_MASK			(0x3 << 20)
++#define OMAP24XX_CLKSEL_GPT10_SHIFT			18
++#define OMAP24XX_CLKSEL_GPT10_MASK			(0x3 << 18)
++#define OMAP24XX_CLKSEL_GPT9_SHIFT			16
++#define OMAP24XX_CLKSEL_GPT9_MASK			(0x3 << 16)
++#define OMAP24XX_CLKSEL_GPT8_SHIFT			14
++#define OMAP24XX_CLKSEL_GPT8_MASK			(0x3 << 14)
++#define OMAP24XX_CLKSEL_GPT7_SHIFT			12
++#define OMAP24XX_CLKSEL_GPT7_MASK			(0x3 << 12)
++#define OMAP24XX_CLKSEL_GPT6_SHIFT			10
++#define OMAP24XX_CLKSEL_GPT6_MASK			(0x3 << 10)
++#define OMAP24XX_CLKSEL_GPT5_SHIFT			8
++#define OMAP24XX_CLKSEL_GPT5_MASK			(0x3 << 8)
++#define OMAP24XX_CLKSEL_GPT4_SHIFT			6
++#define OMAP24XX_CLKSEL_GPT4_MASK			(0x3 << 6)
++#define OMAP24XX_CLKSEL_GPT3_SHIFT			4
++#define OMAP24XX_CLKSEL_GPT3_MASK			(0x3 << 4)
++#define OMAP24XX_CLKSEL_GPT2_SHIFT			2
++#define OMAP24XX_CLKSEL_GPT2_MASK			(0x3 << 2)
++
++/* CM_CLKSTCTRL_CORE */
++#define OMAP24XX_AUTOSTATE_DSS				(1 << 2)
++#define OMAP24XX_AUTOSTATE_L4				(1 << 1)
++#define OMAP24XX_AUTOSTATE_L3				(1 << 0)
++
++/* CM_FCLKEN_GFX */
++#define OMAP24XX_EN_3D_SHIFT				2
++#define OMAP24XX_EN_3D					(1 << 2)
++#define OMAP24XX_EN_2D_SHIFT				1
++#define OMAP24XX_EN_2D					(1 << 1)
++
++/* CM_ICLKEN_GFX specific bits */
++
++/* CM_IDLEST_GFX specific bits */
++
++/* CM_CLKSEL_GFX specific bits */
++
++/* CM_CLKSTCTRL_GFX */
++#define OMAP24XX_AUTOSTATE_GFX				(1 << 0)
++
++/* CM_FCLKEN_WKUP specific bits */
++
++/* CM_ICLKEN_WKUP specific bits */
++#define OMAP2430_EN_ICR_SHIFT				6
++#define OMAP2430_EN_ICR					(1 << 6)
++#define OMAP24XX_EN_OMAPCTRL_SHIFT			5
++#define OMAP24XX_EN_OMAPCTRL				(1 << 5)
++#define OMAP24XX_EN_WDT1_SHIFT				4
++#define OMAP24XX_EN_WDT1				(1 << 4)
++#define OMAP24XX_EN_32KSYNC_SHIFT			1
++#define OMAP24XX_EN_32KSYNC				(1 << 1)
++
++/* CM_IDLEST_WKUP specific bits */
++#define OMAP2430_ST_ICR					(1 << 6)
++#define OMAP24XX_ST_OMAPCTRL				(1 << 5)
++#define OMAP24XX_ST_WDT1				(1 << 4)
++#define OMAP24XX_ST_MPU_WDT				(1 << 3)
++#define OMAP24XX_ST_32KSYNC				(1 << 1)
++
++/* CM_AUTOIDLE_WKUP */
++#define OMAP24XX_AUTO_OMAPCTRL				(1 << 5)
++#define OMAP24XX_AUTO_WDT1				(1 << 4)
++#define OMAP24XX_AUTO_MPU_WDT				(1 << 3)
++#define OMAP24XX_AUTO_GPIOS				(1 << 2)
++#define OMAP24XX_AUTO_32KSYNC				(1 << 1)
++#define OMAP24XX_AUTO_GPT1				(1 << 0)
++
++/* CM_CLKSEL_WKUP */
++#define OMAP24XX_CLKSEL_GPT1_SHIFT			0
++#define OMAP24XX_CLKSEL_GPT1_MASK			(0x3 << 0)
++
++/* CM_CLKEN_PLL */
++#define OMAP24XX_EN_54M_PLL_SHIFT			6
++#define OMAP24XX_EN_54M_PLL_MASK			(0x3 << 6)
++#define OMAP24XX_EN_96M_PLL_SHIFT			2
++#define OMAP24XX_EN_96M_PLL_MASK			(0x3 << 2)
++#define OMAP24XX_EN_DPLL_SHIFT				0
++#define OMAP24XX_EN_DPLL_MASK				(0x3 << 0)
++
++/* CM_IDLEST_CKGEN */
++#define OMAP24XX_ST_54M_APLL				(1 << 9)
++#define OMAP24XX_ST_96M_APLL				(1 << 8)
++#define OMAP24XX_ST_54M_CLK				(1 << 6)
++#define OMAP24XX_ST_12M_CLK				(1 << 5)
++#define OMAP24XX_ST_48M_CLK				(1 << 4)
++#define OMAP24XX_ST_96M_CLK				(1 << 2)
++#define OMAP24XX_ST_CORE_CLK_SHIFT			0
++#define OMAP24XX_ST_CORE_CLK_MASK			(0x3 << 0)
++
++/* CM_AUTOIDLE_PLL */
++#define OMAP24XX_AUTO_54M_SHIFT				6
++#define OMAP24XX_AUTO_54M_MASK				(0x3 << 6)
++#define OMAP24XX_AUTO_96M_SHIFT				2
++#define OMAP24XX_AUTO_96M_MASK				(0x3 << 2)
++#define OMAP24XX_AUTO_DPLL_SHIFT			0
++#define OMAP24XX_AUTO_DPLL_MASK				(0x3 << 0)
++
++/* CM_CLKSEL1_PLL */
++#define OMAP2430_MAXDPLLFASTLOCK_SHIFT			28
++#define OMAP2430_MAXDPLLFASTLOCK_MASK			(0x7 << 28)
++#define OMAP24XX_APLLS_CLKIN_SHIFT			23
++#define OMAP24XX_APLLS_CLKIN_MASK			(0x7 << 23)
++#define OMAP24XX_DPLL_MULT_SHIFT			12
++#define OMAP24XX_DPLL_MULT_MASK				(0x3ff << 12)
++#define OMAP24XX_DPLL_DIV_SHIFT				8
++#define OMAP24XX_DPLL_DIV_MASK				(0xf << 8)
++#define OMAP24XX_54M_SOURCE_SHIFT			5
++#define OMAP24XX_54M_SOURCE				(1 << 5)
++#define OMAP2430_96M_SOURCE_SHIFT			4
++#define OMAP2430_96M_SOURCE				(1 << 4)
++#define OMAP24XX_48M_SOURCE_SHIFT			3
++#define OMAP24XX_48M_SOURCE				(1 << 3)
++#define OMAP2430_ALTCLK_SOURCE_SHIFT			0
++#define OMAP2430_ALTCLK_SOURCE_MASK			(0x7 << 0)
++
++/* CM_CLKSEL2_PLL */
++#define OMAP24XX_CORE_CLK_SRC_SHIFT			0
++#define OMAP24XX_CORE_CLK_SRC_MASK			(0x3 << 0)
++
++/* CM_FCLKEN_DSP */
++#define OMAP2420_EN_IVA_COP_SHIFT			10
++#define OMAP2420_EN_IVA_COP				(1 << 10)
++#define OMAP2420_EN_IVA_MPU_SHIFT			8
++#define OMAP2420_EN_IVA_MPU				(1 << 8)
++#define OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT		0
++#define OMAP24XX_CM_FCLKEN_DSP_EN_DSP			(1 << 0)
++
++/* CM_ICLKEN_DSP */
++#define OMAP2420_EN_DSP_IPI_SHIFT			1
++#define OMAP2420_EN_DSP_IPI				(1 << 1)
++
++/* CM_IDLEST_DSP */
++#define OMAP2420_ST_IVA					(1 << 8)
++#define OMAP2420_ST_IPI					(1 << 1)
++#define OMAP24XX_ST_DSP					(1 << 0)
++
++/* CM_AUTOIDLE_DSP */
++#define OMAP2420_AUTO_DSP_IPI				(1 << 1)
++
++/* CM_CLKSEL_DSP */
++#define OMAP2420_SYNC_IVA				(1 << 13)
++#define OMAP2420_CLKSEL_IVA_SHIFT			8
++#define OMAP2420_CLKSEL_IVA_MASK			(0x1f << 8)
++#define OMAP24XX_SYNC_DSP				(1 << 7)
++#define OMAP24XX_CLKSEL_DSP_IF_SHIFT			5
++#define OMAP24XX_CLKSEL_DSP_IF_MASK			(0x3 << 5)
++#define OMAP24XX_CLKSEL_DSP_SHIFT			0
++#define OMAP24XX_CLKSEL_DSP_MASK			(0x1f << 0)
++
++/* CM_CLKSTCTRL_DSP */
++#define OMAP2420_AUTOSTATE_IVA				(1 << 8)
++#define OMAP24XX_AUTOSTATE_DSP				(1 << 0)
++
++/* CM_FCLKEN_MDM */
++/* 2430 only */
++#define OMAP2430_EN_OSC_SHIFT				1
++#define OMAP2430_EN_OSC					(1 << 1)
++
++/* CM_ICLKEN_MDM */
++/* 2430 only */
++#define OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT		0
++#define OMAP2430_CM_ICLKEN_MDM_EN_MDM			(1 << 0)
++
++/* CM_IDLEST_MDM specific bits */
++/* 2430 only */
++
++/* CM_AUTOIDLE_MDM */
++/* 2430 only */
++#define OMAP2430_AUTO_OSC				(1 << 1)
++#define OMAP2430_AUTO_MDM				(1 << 0)
++
++/* CM_CLKSEL_MDM */
++/* 2430 only */
++#define OMAP2430_SYNC_MDM				(1 << 4)
++#define OMAP2430_CLKSEL_MDM_SHIFT			0
++#define OMAP2430_CLKSEL_MDM_MASK			(0xf << 0)
++
++/* CM_CLKSTCTRL_MDM */
++/* 2430 only */
++#define OMAP2430_AUTOSTATE_MDM				(1 << 0)
++
++#endif
+diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
+new file mode 100644
+index 0000000..9249129
+--- /dev/null
++++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
+@@ -0,0 +1,673 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_34XX_H
++#define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_34XX_H
++
++/*
++ * OMAP3430 Clock Management register bits
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "cm.h"
++
++/* Bits shared between registers */
++
++/* CM_FCLKEN1_CORE and CM_ICLKEN1_CORE shared bits */
++#define OMAP3430ES2_EN_MMC3_MASK			(1 << 30)
++#define OMAP3430ES2_EN_MMC3_SHIFT			30
++#define OMAP3430_EN_MSPRO				(1 << 23)
++#define OMAP3430_EN_MSPRO_SHIFT				23
++#define OMAP3430_EN_HDQ					(1 << 22)
++#define OMAP3430_EN_HDQ_SHIFT				22
++#define OMAP3430ES1_EN_FSHOSTUSB			(1 << 5)
++#define OMAP3430ES1_EN_FSHOSTUSB_SHIFT			5
++#define OMAP3430ES1_EN_D2D				(1 << 3)
++#define OMAP3430ES1_EN_D2D_SHIFT			3
++#define OMAP3430_EN_SSI					(1 << 0)
++#define OMAP3430_EN_SSI_SHIFT				0
++
++/* CM_FCLKEN3_CORE and CM_ICLKEN3_CORE shared bits */
++#define OMAP3430ES2_EN_USBTLL_SHIFT			2
++#define OMAP3430ES2_EN_USBTLL_MASK			(1 << 2)
++
++/* CM_FCLKEN_WKUP and CM_ICLKEN_WKUP shared bits */
++#define OMAP3430_EN_WDT2				(1 << 5)
++#define OMAP3430_EN_WDT2_SHIFT				5
++
++/* CM_ICLKEN_CAM, CM_FCLKEN_CAM shared bits */
++#define OMAP3430_EN_CAM					(1 << 0)
++#define OMAP3430_EN_CAM_SHIFT				0
++
++/* CM_FCLKEN_PER, CM_ICLKEN_PER shared bits */
++#define OMAP3430_EN_WDT3				(1 << 12)
++#define OMAP3430_EN_WDT3_SHIFT				12
++
++/* CM_CLKSEL2_EMU, CM_CLKSEL3_EMU shared bits */
++#define OMAP3430_OVERRIDE_ENABLE			(1 << 19)
++
++
++/* Bits specific to each register */
++
++/* CM_FCLKEN_IVA2 */
++#define OMAP3430_CM_FCLKEN_IVA2_EN_IVA2			(1 << 0)
++
++/* CM_CLKEN_PLL_IVA2 */
++#define OMAP3430_IVA2_DPLL_RAMPTIME_SHIFT		8
++#define OMAP3430_IVA2_DPLL_RAMPTIME_MASK		(0x3 << 8)
++#define OMAP3430_IVA2_DPLL_FREQSEL_SHIFT		4
++#define OMAP3430_IVA2_DPLL_FREQSEL_MASK			(0xf << 4)
++#define OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT		3
++#define OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_MASK		(1 << 3)
++#define OMAP3430_EN_IVA2_DPLL_SHIFT			0
++#define OMAP3430_EN_IVA2_DPLL_MASK			(0x7 << 0)
++
++/* CM_IDLEST_IVA2 */
++#define OMAP3430_ST_IVA2				(1 << 0)
++
++/* CM_IDLEST_PLL_IVA2 */
++#define OMAP3430_ST_IVA2_CLK				(1 << 0)
++
++/* CM_AUTOIDLE_PLL_IVA2 */
++#define OMAP3430_AUTO_IVA2_DPLL_SHIFT			0
++#define OMAP3430_AUTO_IVA2_DPLL_MASK			(0x7 << 0)
++
++/* CM_CLKSEL1_PLL_IVA2 */
++#define OMAP3430_IVA2_CLK_SRC_SHIFT			19
++#define OMAP3430_IVA2_CLK_SRC_MASK			(0x3 << 19)
++#define OMAP3430_IVA2_DPLL_MULT_SHIFT			8
++#define OMAP3430_IVA2_DPLL_MULT_MASK			(0x7ff << 8)
++#define OMAP3430_IVA2_DPLL_DIV_SHIFT			0
++#define OMAP3430_IVA2_DPLL_DIV_MASK			(0x7f << 0)
++
++/* CM_CLKSEL2_PLL_IVA2 */
++#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT		0
++#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK		(0x1f << 0)
++
++/* CM_CLKSTCTRL_IVA2 */
++#define OMAP3430_CLKTRCTRL_IVA2_SHIFT			0
++#define OMAP3430_CLKTRCTRL_IVA2_MASK			(0x3 << 0)
++
++/* CM_CLKSTST_IVA2 */
++#define OMAP3430_CLKACTIVITY_IVA2			(1 << 0)
++
++/* CM_REVISION specific bits */
++
++/* CM_SYSCONFIG specific bits */
++
++/* CM_CLKEN_PLL_MPU */
++#define OMAP3430_MPU_DPLL_RAMPTIME_SHIFT		8
++#define OMAP3430_MPU_DPLL_RAMPTIME_MASK			(0x3 << 8)
++#define OMAP3430_MPU_DPLL_FREQSEL_SHIFT			4
++#define OMAP3430_MPU_DPLL_FREQSEL_MASK			(0xf << 4)
++#define OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT		3
++#define OMAP3430_EN_MPU_DPLL_DRIFTGUARD_MASK		(1 << 3)
++#define OMAP3430_EN_MPU_DPLL_SHIFT			0
++#define OMAP3430_EN_MPU_DPLL_MASK			(0x7 << 0)
++
++/* CM_IDLEST_MPU */
++#define OMAP3430_ST_MPU					(1 << 0)
++
++/* CM_IDLEST_PLL_MPU */
++#define OMAP3430_ST_MPU_CLK				(1 << 0)
++#define OMAP3430_ST_IVA2_CLK_MASK			(1 << 0)
++
++/* CM_IDLEST_PLL_MPU */
++#define OMAP3430_ST_MPU_CLK_MASK			(1 << 0)
++
++/* CM_AUTOIDLE_PLL_MPU */
++#define OMAP3430_AUTO_MPU_DPLL_SHIFT			0
++#define OMAP3430_AUTO_MPU_DPLL_MASK			(0x7 << 0)
++
++/* CM_CLKSEL1_PLL_MPU */
++#define OMAP3430_MPU_CLK_SRC_SHIFT			19
++#define OMAP3430_MPU_CLK_SRC_MASK			(0x3 << 19)
++#define OMAP3430_MPU_DPLL_MULT_SHIFT			8
++#define OMAP3430_MPU_DPLL_MULT_MASK			(0x7ff << 8)
++#define OMAP3430_MPU_DPLL_DIV_SHIFT			0
++#define OMAP3430_MPU_DPLL_DIV_MASK			(0x7f << 0)
++
++/* CM_CLKSEL2_PLL_MPU */
++#define OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT		0
++#define OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK		(0x1f << 0)
++
++/* CM_CLKSTCTRL_MPU */
++#define OMAP3430_CLKTRCTRL_MPU_SHIFT			0
++#define OMAP3430_CLKTRCTRL_MPU_MASK			(0x3 << 0)
++
++/* CM_CLKSTST_MPU */
++#define OMAP3430_CLKACTIVITY_MPU			(1 << 0)
++
++/* CM_FCLKEN1_CORE specific bits */
++
++/* CM_ICLKEN1_CORE specific bits */
++#define OMAP3430_EN_ICR					(1 << 29)
++#define OMAP3430_EN_ICR_SHIFT				29
++#define OMAP3430_EN_AES2				(1 << 28)
++#define OMAP3430_EN_AES2_SHIFT				28
++#define OMAP3430_EN_SHA12				(1 << 27)
++#define OMAP3430_EN_SHA12_SHIFT				27
++#define OMAP3430_EN_DES2				(1 << 26)
++#define OMAP3430_EN_DES2_SHIFT				26
++#define OMAP3430ES1_EN_FAC				(1 << 8)
++#define OMAP3430ES1_EN_FAC_SHIFT			8
++#define OMAP3430_EN_MAILBOXES				(1 << 7)
++#define OMAP3430_EN_MAILBOXES_SHIFT			7
++#define OMAP3430_EN_OMAPCTRL				(1 << 6)
++#define OMAP3430_EN_OMAPCTRL_SHIFT			6
++#define OMAP3430_EN_SDRC				(1 << 1)
++#define OMAP3430_EN_SDRC_SHIFT				1
++
++/* CM_ICLKEN2_CORE */
++#define OMAP3430_EN_PKA					(1 << 4)
++#define OMAP3430_EN_PKA_SHIFT				4
++#define OMAP3430_EN_AES1				(1 << 3)
++#define OMAP3430_EN_AES1_SHIFT				3
++#define OMAP3430_EN_RNG					(1 << 2)
++#define OMAP3430_EN_RNG_SHIFT				2
++#define OMAP3430_EN_SHA11				(1 << 1)
++#define OMAP3430_EN_SHA11_SHIFT				1
++#define OMAP3430_EN_DES1				(1 << 0)
++#define OMAP3430_EN_DES1_SHIFT				0
++
++/* CM_FCLKEN3_CORE specific bits */
++#define OMAP3430ES2_EN_TS_SHIFT				1
++#define OMAP3430ES2_EN_TS_MASK				(1 << 1)
++#define OMAP3430ES2_EN_CPEFUSE_SHIFT			0
++#define OMAP3430ES2_EN_CPEFUSE_MASK			(1 << 0)
++
++/* CM_IDLEST1_CORE specific bits */
++#define OMAP3430_ST_ICR					(1 << 29)
++#define OMAP3430_ST_AES2				(1 << 28)
++#define OMAP3430_ST_SHA12				(1 << 27)
++#define OMAP3430_ST_DES2				(1 << 26)
++#define OMAP3430_ST_MSPRO				(1 << 23)
++#define OMAP3430_ST_HDQ					(1 << 22)
++#define OMAP3430ES1_ST_FAC				(1 << 8)
++#define OMAP3430ES1_ST_MAILBOXES			(1 << 7)
++#define OMAP3430_ST_OMAPCTRL				(1 << 6)
++#define OMAP3430_ST_SDMA				(1 << 2)
++#define OMAP3430_ST_SDRC				(1 << 1)
++#define OMAP3430_ST_SSI					(1 << 0)
++
++/* CM_IDLEST2_CORE */
++#define OMAP3430_ST_PKA					(1 << 4)
++#define OMAP3430_ST_AES1				(1 << 3)
++#define OMAP3430_ST_RNG					(1 << 2)
++#define OMAP3430_ST_SHA11				(1 << 1)
++#define OMAP3430_ST_DES1				(1 << 0)
++
++/* CM_IDLEST3_CORE */
++#define OMAP3430ES2_ST_USBTLL_SHIFT			2
++#define OMAP3430ES2_ST_USBTLL_MASK			(1 << 2)
++
++/* CM_AUTOIDLE1_CORE */
++#define OMAP3430_AUTO_AES2				(1 << 28)
++#define OMAP3430_AUTO_AES2_SHIFT			28
++#define OMAP3430_AUTO_SHA12				(1 << 27)
++#define OMAP3430_AUTO_SHA12_SHIFT			27
++#define OMAP3430_AUTO_DES2				(1 << 26)
++#define OMAP3430_AUTO_DES2_SHIFT			26
++#define OMAP3430_AUTO_MMC2				(1 << 25)
++#define OMAP3430_AUTO_MMC2_SHIFT			25
++#define OMAP3430_AUTO_MMC1				(1 << 24)
++#define OMAP3430_AUTO_MMC1_SHIFT			24
++#define OMAP3430_AUTO_MSPRO				(1 << 23)
++#define OMAP3430_AUTO_MSPRO_SHIFT			23
++#define OMAP3430_AUTO_HDQ				(1 << 22)
++#define OMAP3430_AUTO_HDQ_SHIFT				22
++#define OMAP3430_AUTO_MCSPI4				(1 << 21)
++#define OMAP3430_AUTO_MCSPI4_SHIFT			21
++#define OMAP3430_AUTO_MCSPI3				(1 << 20)
++#define OMAP3430_AUTO_MCSPI3_SHIFT			20
++#define OMAP3430_AUTO_MCSPI2				(1 << 19)
++#define OMAP3430_AUTO_MCSPI2_SHIFT			19
++#define OMAP3430_AUTO_MCSPI1				(1 << 18)
++#define OMAP3430_AUTO_MCSPI1_SHIFT			18
++#define OMAP3430_AUTO_I2C3				(1 << 17)
++#define OMAP3430_AUTO_I2C3_SHIFT			17
++#define OMAP3430_AUTO_I2C2				(1 << 16)
++#define OMAP3430_AUTO_I2C2_SHIFT			16
++#define OMAP3430_AUTO_I2C1				(1 << 15)
++#define OMAP3430_AUTO_I2C1_SHIFT			15
++#define OMAP3430_AUTO_UART2				(1 << 14)
++#define OMAP3430_AUTO_UART2_SHIFT			14
++#define OMAP3430_AUTO_UART1				(1 << 13)
++#define OMAP3430_AUTO_UART1_SHIFT			13
++#define OMAP3430_AUTO_GPT11				(1 << 12)
++#define OMAP3430_AUTO_GPT11_SHIFT			12
++#define OMAP3430_AUTO_GPT10				(1 << 11)
++#define OMAP3430_AUTO_GPT10_SHIFT			11
++#define OMAP3430_AUTO_MCBSP5				(1 << 10)
++#define OMAP3430_AUTO_MCBSP5_SHIFT			10
++#define OMAP3430_AUTO_MCBSP1				(1 << 9)
++#define OMAP3430_AUTO_MCBSP1_SHIFT			9
++#define OMAP3430ES1_AUTO_FAC				(1 << 8)
++#define OMAP3430ES1_AUTO_FAC_SHIFT			8
++#define OMAP3430_AUTO_MAILBOXES				(1 << 7)
++#define OMAP3430_AUTO_MAILBOXES_SHIFT			7
++#define OMAP3430_AUTO_OMAPCTRL				(1 << 6)
++#define OMAP3430_AUTO_OMAPCTRL_SHIFT			6
++#define OMAP3430ES1_AUTO_FSHOSTUSB			(1 << 5)
++#define OMAP3430ES1_AUTO_FSHOSTUSB_SHIFT		5
++#define OMAP3430_AUTO_HSOTGUSB				(1 << 4)
++#define OMAP3430_AUTO_HSOTGUSB_SHIFT			4
++#define OMAP3430ES1_AUTO_D2D				(1 << 3)
++#define OMAP3430ES1_AUTO_D2D_SHIFT			3
++#define OMAP3430_AUTO_SSI				(1 << 0)
++#define OMAP3430_AUTO_SSI_SHIFT				0
++
++/* CM_AUTOIDLE2_CORE */
++#define OMAP3430_AUTO_PKA				(1 << 4)
++#define OMAP3430_AUTO_PKA_SHIFT				4
++#define OMAP3430_AUTO_AES1				(1 << 3)
++#define OMAP3430_AUTO_AES1_SHIFT			3
++#define OMAP3430_AUTO_RNG				(1 << 2)
++#define OMAP3430_AUTO_RNG_SHIFT				2
++#define OMAP3430_AUTO_SHA11				(1 << 1)
++#define OMAP3430_AUTO_SHA11_SHIFT			1
++#define OMAP3430_AUTO_DES1				(1 << 0)
++#define OMAP3430_AUTO_DES1_SHIFT			0
++
++/* CM_AUTOIDLE3_CORE */
++#define OMAP3430ES2_AUTO_USBTLL_SHIFT			2
++#define OMAP3430ES2_AUTO_USBTLL_MASK			(1 << 2)
++
++/* CM_CLKSEL_CORE */
++#define OMAP3430_CLKSEL_SSI_SHIFT			8
++#define OMAP3430_CLKSEL_SSI_MASK			(0xf << 8)
++#define OMAP3430_CLKSEL_GPT11_MASK			(1 << 7)
++#define OMAP3430_CLKSEL_GPT11_SHIFT			7
++#define OMAP3430_CLKSEL_GPT10_MASK			(1 << 6)
++#define OMAP3430_CLKSEL_GPT10_SHIFT			6
++#define OMAP3430ES1_CLKSEL_FSHOSTUSB_SHIFT		4
++#define OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK		(0x3 << 4)
++#define OMAP3430_CLKSEL_L4_SHIFT			2
++#define OMAP3430_CLKSEL_L4_MASK				(0x3 << 2)
++#define OMAP3430_CLKSEL_L3_SHIFT			0
++#define OMAP3430_CLKSEL_L3_MASK				(0x3 << 0)
++
++/* CM_CLKSTCTRL_CORE */
++#define OMAP3430ES1_CLKTRCTRL_D2D_SHIFT			4
++#define OMAP3430ES1_CLKTRCTRL_D2D_MASK			(0x3 << 4)
++#define OMAP3430_CLKTRCTRL_L4_SHIFT			2
++#define OMAP3430_CLKTRCTRL_L4_MASK			(0x3 << 2)
++#define OMAP3430_CLKTRCTRL_L3_SHIFT			0
++#define OMAP3430_CLKTRCTRL_L3_MASK			(0x3 << 0)
++
++/* CM_CLKSTST_CORE */
++#define OMAP3430ES1_CLKACTIVITY_D2D			(1 << 2)
++#define OMAP3430_CLKACTIVITY_L4				(1 << 1)
++#define OMAP3430_CLKACTIVITY_L3				(1 << 0)
++
++/* CM_FCLKEN_GFX */
++#define OMAP3430ES1_EN_3D				(1 << 2)
++#define OMAP3430ES1_EN_3D_SHIFT				2
++#define OMAP3430ES1_EN_2D				(1 << 1)
++#define OMAP3430ES1_EN_2D_SHIFT				1
++
++/* CM_ICLKEN_GFX specific bits */
++
++/* CM_IDLEST_GFX specific bits */
++
++/* CM_CLKSEL_GFX specific bits */
++
++/* CM_SLEEPDEP_GFX specific bits */
++
++/* CM_CLKSTCTRL_GFX */
++#define OMAP3430ES1_CLKTRCTRL_GFX_SHIFT			0
++#define OMAP3430ES1_CLKTRCTRL_GFX_MASK			(0x3 << 0)
++
++/* CM_CLKSTST_GFX */
++#define OMAP3430ES1_CLKACTIVITY_GFX			(1 << 0)
++
++/* CM_FCLKEN_SGX */
++#define OMAP3430ES2_EN_SGX_SHIFT			1
++#define OMAP3430ES2_EN_SGX_MASK				(1 << 1)
++
++/* CM_CLKSEL_SGX */
++#define OMAP3430ES2_CLKSEL_SGX_SHIFT			0
++#define OMAP3430ES2_CLKSEL_SGX_MASK			(0x7 << 0)
++
++/* CM_FCLKEN_WKUP specific bits */
++#define OMAP3430ES2_EN_USIMOCP_SHIFT			9
++
++/* CM_ICLKEN_WKUP specific bits */
++#define OMAP3430_EN_WDT1				(1 << 4)
++#define OMAP3430_EN_WDT1_SHIFT				4
++#define OMAP3430_EN_32KSYNC				(1 << 2)
++#define OMAP3430_EN_32KSYNC_SHIFT			2
++
++/* CM_IDLEST_WKUP specific bits */
++#define OMAP3430_ST_WDT2				(1 << 5)
++#define OMAP3430_ST_WDT1				(1 << 4)
++#define OMAP3430_ST_32KSYNC				(1 << 2)
++
++/* CM_AUTOIDLE_WKUP */
++#define OMAP3430_AUTO_WDT2				(1 << 5)
++#define OMAP3430_AUTO_WDT2_SHIFT			5
++#define OMAP3430_AUTO_WDT1				(1 << 4)
++#define OMAP3430_AUTO_WDT1_SHIFT			4
++#define OMAP3430_AUTO_GPIO1				(1 << 3)
++#define OMAP3430_AUTO_GPIO1_SHIFT			3
++#define OMAP3430_AUTO_32KSYNC				(1 << 2)
++#define OMAP3430_AUTO_32KSYNC_SHIFT			2
++#define OMAP3430_AUTO_GPT12				(1 << 1)
++#define OMAP3430_AUTO_GPT12_SHIFT			1
++#define OMAP3430_AUTO_GPT1				(1 << 0)
++#define OMAP3430_AUTO_GPT1_SHIFT			0
++
++/* CM_CLKSEL_WKUP */
++#define OMAP3430ES2_CLKSEL_USIMOCP_MASK			(0xf << 3)
++#define OMAP3430_CLKSEL_RM_SHIFT			1
++#define OMAP3430_CLKSEL_RM_MASK				(0x3 << 1)
++#define OMAP3430_CLKSEL_GPT1_SHIFT			0
++#define OMAP3430_CLKSEL_GPT1_MASK			(1 << 0)
++
++/* CM_CLKEN_PLL */
++#define OMAP3430_PWRDN_EMU_PERIPH_SHIFT			31
++#define OMAP3430_PWRDN_CAM_SHIFT			30
++#define OMAP3430_PWRDN_DSS1_SHIFT			29
++#define OMAP3430_PWRDN_TV_SHIFT				28
++#define OMAP3430_PWRDN_96M_SHIFT			27
++#define OMAP3430_PERIPH_DPLL_RAMPTIME_SHIFT		24
++#define OMAP3430_PERIPH_DPLL_RAMPTIME_MASK		(0x3 << 24)
++#define OMAP3430_PERIPH_DPLL_FREQSEL_SHIFT		20
++#define OMAP3430_PERIPH_DPLL_FREQSEL_MASK		(0xf << 20)
++#define OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT	19
++#define OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_MASK		(1 << 19)
++#define OMAP3430_EN_PERIPH_DPLL_SHIFT			16
++#define OMAP3430_EN_PERIPH_DPLL_MASK			(0x7 << 16)
++#define OMAP3430_PWRDN_EMU_CORE_SHIFT			12
++#define OMAP3430_CORE_DPLL_RAMPTIME_SHIFT		8
++#define OMAP3430_CORE_DPLL_RAMPTIME_MASK		(0x3 << 8)
++#define OMAP3430_CORE_DPLL_FREQSEL_SHIFT		4
++#define OMAP3430_CORE_DPLL_FREQSEL_MASK			(0xf << 4)
++#define OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT		3
++#define OMAP3430_EN_CORE_DPLL_DRIFTGUARD_MASK		(1 << 3)
++#define OMAP3430_EN_CORE_DPLL_SHIFT			0
++#define OMAP3430_EN_CORE_DPLL_MASK			(0x7 << 0)
++
++/* CM_CLKEN2_PLL */
++#define OMAP3430ES2_EN_PERIPH2_DPLL_LPMODE_SHIFT		10
++#define OMAP3430ES2_PERIPH2_DPLL_RAMPTIME_MASK		(0x3 << 8)
++#define OMAP3430ES2_PERIPH2_DPLL_FREQSEL_SHIFT		4
++#define OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK		(0xf << 4)
++#define OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT	3
++#define OMAP3430ES2_EN_PERIPH2_DPLL_SHIFT		0
++#define OMAP3430ES2_EN_PERIPH2_DPLL_MASK		(0x7 << 0)
++
++/* CM_IDLEST_CKGEN */
++#define OMAP3430_ST_54M_CLK				(1 << 5)
++#define OMAP3430_ST_12M_CLK				(1 << 4)
++#define OMAP3430_ST_48M_CLK				(1 << 3)
++#define OMAP3430_ST_96M_CLK				(1 << 2)
++#define OMAP3430_ST_PERIPH_CLK				(1 << 1)
++#define OMAP3430_ST_CORE_CLK				(1 << 0)
++
++/* CM_IDLEST2_CKGEN */
++#define OMAP3430ES2_ST_120M_CLK_SHIFT			1
++#define OMAP3430ES2_ST_120M_CLK_MASK			(1 << 1)
++#define OMAP3430ES2_ST_PERIPH2_CLK_SHIFT		0
++#define OMAP3430ES2_ST_PERIPH2_CLK_MASK			(1 << 0)
++
++/* CM_AUTOIDLE_PLL */
++#define OMAP3430_AUTO_PERIPH_DPLL_SHIFT			3
++#define OMAP3430_AUTO_PERIPH_DPLL_MASK			(0x7 << 3)
++#define OMAP3430_AUTO_CORE_DPLL_SHIFT			0
++#define OMAP3430_AUTO_CORE_DPLL_MASK			(0x7 << 0)
++
++/* CM_CLKSEL1_PLL */
++/* Note that OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK was (0x3 << 27) on 3430ES1 */
++#define OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT		27
++#define OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK		(0x1f << 27)
++#define OMAP3430_CORE_DPLL_MULT_SHIFT			16
++#define OMAP3430_CORE_DPLL_MULT_MASK			(0x7ff << 16)
++#define OMAP3430_CORE_DPLL_DIV_SHIFT			8
++#define OMAP3430_CORE_DPLL_DIV_MASK			(0x7f << 8)
++#define OMAP3430_SOURCE_54M				(1 << 5)
++#define OMAP3430_SOURCE_48M				(1 << 3)
++
++/* CM_CLKSEL2_PLL */
++#define OMAP3430_PERIPH_DPLL_MULT_SHIFT			8
++#define OMAP3430_PERIPH_DPLL_MULT_MASK			(0x7ff << 8)
++#define OMAP3430_PERIPH_DPLL_DIV_SHIFT			0
++#define OMAP3430_PERIPH_DPLL_DIV_MASK			(0x7f << 0)
++
++/* CM_CLKSEL3_PLL */
++#define OMAP3430_DIV_96M_SHIFT				0
++#define OMAP3430_DIV_96M_MASK				(0x1f << 0)
++
++/* CM_CLKSEL4_PLL */
++#define OMAP3430ES2_PERIPH2_DPLL_MULT_SHIFT		8
++#define OMAP3430ES2_PERIPH2_DPLL_MULT_MASK		(0x7ff << 8)
++#define OMAP3430ES2_PERIPH2_DPLL_DIV_SHIFT		0
++#define OMAP3430ES2_PERIPH2_DPLL_DIV_MASK		(0x7f << 0)
++
++/* CM_CLKSEL5_PLL */
++#define OMAP3430ES2_DIV_120M_SHIFT			0
++#define OMAP3430ES2_DIV_120M_MASK			(0x1f << 0)
++
++/* CM_CLKOUT_CTRL */
++#define OMAP3430_CLKOUT2_EN_SHIFT			7
++#define OMAP3430_CLKOUT2_EN				(1 << 7)
++#define OMAP3430_CLKOUT2_DIV_SHIFT			3
++#define OMAP3430_CLKOUT2_DIV_MASK			(0x7 << 3)
++#define OMAP3430_CLKOUT2SOURCE_SHIFT			0
++#define OMAP3430_CLKOUT2SOURCE_MASK			(0x3 << 0)
++
++/* CM_FCLKEN_DSS */
++#define OMAP3430_EN_TV					(1 << 2)
++#define OMAP3430_EN_TV_SHIFT				2
++#define OMAP3430_EN_DSS2				(1 << 1)
++#define OMAP3430_EN_DSS2_SHIFT				1
++#define OMAP3430_EN_DSS1				(1 << 0)
++#define OMAP3430_EN_DSS1_SHIFT				0
++
++/* CM_ICLKEN_DSS */
++#define OMAP3430_CM_ICLKEN_DSS_EN_DSS			(1 << 0)
++#define OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT		0
++
++/* CM_IDLEST_DSS */
++#define OMAP3430_ST_DSS					(1 << 0)
++
++/* CM_AUTOIDLE_DSS */
++#define OMAP3430_AUTO_DSS				(1 << 0)
++#define OMAP3430_AUTO_DSS_SHIFT				0
++
++/* CM_CLKSEL_DSS */
++#define OMAP3430_CLKSEL_TV_SHIFT			8
++#define OMAP3430_CLKSEL_TV_MASK				(0x1f << 8)
++#define OMAP3430_CLKSEL_DSS1_SHIFT			0
++#define OMAP3430_CLKSEL_DSS1_MASK			(0x1f << 0)
++
++/* CM_SLEEPDEP_DSS specific bits */
++
++/* CM_CLKSTCTRL_DSS */
++#define OMAP3430_CLKTRCTRL_DSS_SHIFT			0
++#define OMAP3430_CLKTRCTRL_DSS_MASK			(0x3 << 0)
++
++/* CM_CLKSTST_DSS */
++#define OMAP3430_CLKACTIVITY_DSS			(1 << 0)
++
++/* CM_FCLKEN_CAM specific bits */
++
++/* CM_ICLKEN_CAM specific bits */
++
++/* CM_IDLEST_CAM */
++#define OMAP3430_ST_CAM					(1 << 0)
++
++/* CM_AUTOIDLE_CAM */
++#define OMAP3430_AUTO_CAM				(1 << 0)
++#define OMAP3430_AUTO_CAM_SHIFT				0
++
++/* CM_CLKSEL_CAM */
++#define OMAP3430_CLKSEL_CAM_SHIFT			0
++#define OMAP3430_CLKSEL_CAM_MASK			(0x1f << 0)
++
++/* CM_SLEEPDEP_CAM specific bits */
++
++/* CM_CLKSTCTRL_CAM */
++#define OMAP3430_CLKTRCTRL_CAM_SHIFT			0
++#define OMAP3430_CLKTRCTRL_CAM_MASK			(0x3 << 0)
++
++/* CM_CLKSTST_CAM */
++#define OMAP3430_CLKACTIVITY_CAM			(1 << 0)
++
++/* CM_FCLKEN_PER specific bits */
++
++/* CM_ICLKEN_PER specific bits */
++
++/* CM_IDLEST_PER */
++#define OMAP3430_ST_WDT3				(1 << 12)
++#define OMAP3430_ST_MCBSP4				(1 << 2)
++#define OMAP3430_ST_MCBSP3				(1 << 1)
++#define OMAP3430_ST_MCBSP2				(1 << 0)
++
++/* CM_AUTOIDLE_PER */
++#define OMAP3430_AUTO_GPIO6				(1 << 17)
++#define OMAP3430_AUTO_GPIO6_SHIFT			17
++#define OMAP3430_AUTO_GPIO5				(1 << 16)
++#define OMAP3430_AUTO_GPIO5_SHIFT			16
++#define OMAP3430_AUTO_GPIO4				(1 << 15)
++#define OMAP3430_AUTO_GPIO4_SHIFT			15
++#define OMAP3430_AUTO_GPIO3				(1 << 14)
++#define OMAP3430_AUTO_GPIO3_SHIFT			14
++#define OMAP3430_AUTO_GPIO2				(1 << 13)
++#define OMAP3430_AUTO_GPIO2_SHIFT			13
++#define OMAP3430_AUTO_WDT3				(1 << 12)
++#define OMAP3430_AUTO_WDT3_SHIFT			12
++#define OMAP3430_AUTO_UART3				(1 << 11)
++#define OMAP3430_AUTO_UART3_SHIFT			11
++#define OMAP3430_AUTO_GPT9				(1 << 10)
++#define OMAP3430_AUTO_GPT9_SHIFT			10
++#define OMAP3430_AUTO_GPT8				(1 << 9)
++#define OMAP3430_AUTO_GPT8_SHIFT			9
++#define OMAP3430_AUTO_GPT7				(1 << 8)
++#define OMAP3430_AUTO_GPT7_SHIFT			8
++#define OMAP3430_AUTO_GPT6				(1 << 7)
++#define OMAP3430_AUTO_GPT6_SHIFT			7
++#define OMAP3430_AUTO_GPT5				(1 << 6)
++#define OMAP3430_AUTO_GPT5_SHIFT			6
++#define OMAP3430_AUTO_GPT4				(1 << 5)
++#define OMAP3430_AUTO_GPT4_SHIFT			5
++#define OMAP3430_AUTO_GPT3				(1 << 4)
++#define OMAP3430_AUTO_GPT3_SHIFT			4
++#define OMAP3430_AUTO_GPT2				(1 << 3)
++#define OMAP3430_AUTO_GPT2_SHIFT			3
++#define OMAP3430_AUTO_MCBSP4				(1 << 2)
++#define OMAP3430_AUTO_MCBSP4_SHIFT			2
++#define OMAP3430_AUTO_MCBSP3				(1 << 1)
++#define OMAP3430_AUTO_MCBSP3_SHIFT			1
++#define OMAP3430_AUTO_MCBSP2				(1 << 0)
++#define OMAP3430_AUTO_MCBSP2_SHIFT			0
++
++/* CM_CLKSEL_PER */
++#define OMAP3430_CLKSEL_GPT9_MASK			(1 << 7)
++#define OMAP3430_CLKSEL_GPT9_SHIFT			7
++#define OMAP3430_CLKSEL_GPT8_MASK			(1 << 6)
++#define OMAP3430_CLKSEL_GPT8_SHIFT			6
++#define OMAP3430_CLKSEL_GPT7_MASK			(1 << 5)
++#define OMAP3430_CLKSEL_GPT7_SHIFT			5
++#define OMAP3430_CLKSEL_GPT6_MASK			(1 << 4)
++#define OMAP3430_CLKSEL_GPT6_SHIFT			4
++#define OMAP3430_CLKSEL_GPT5_MASK			(1 << 3)
++#define OMAP3430_CLKSEL_GPT5_SHIFT			3
++#define OMAP3430_CLKSEL_GPT4_MASK			(1 << 2)
++#define OMAP3430_CLKSEL_GPT4_SHIFT			2
++#define OMAP3430_CLKSEL_GPT3_MASK			(1 << 1)
++#define OMAP3430_CLKSEL_GPT3_SHIFT			1
++#define OMAP3430_CLKSEL_GPT2_MASK			(1 << 0)
++#define OMAP3430_CLKSEL_GPT2_SHIFT			0
++
++/* CM_SLEEPDEP_PER specific bits */
++#define OMAP3430_CM_SLEEPDEP_PER_EN_IVA2		(1 << 2)
++
++/* CM_CLKSTCTRL_PER */
++#define OMAP3430_CLKTRCTRL_PER_SHIFT			0
++#define OMAP3430_CLKTRCTRL_PER_MASK			(0x3 << 0)
++
++/* CM_CLKSTST_PER */
++#define OMAP3430_CLKACTIVITY_PER			(1 << 0)
++
++/* CM_CLKSEL1_EMU */
++#define OMAP3430_DIV_DPLL4_SHIFT			24
++#define OMAP3430_DIV_DPLL4_MASK				(0x1f << 24)
++#define OMAP3430_DIV_DPLL3_SHIFT			16
++#define OMAP3430_DIV_DPLL3_MASK				(0x1f << 16)
++#define OMAP3430_CLKSEL_TRACECLK_SHIFT			11
++#define OMAP3430_CLKSEL_TRACECLK_MASK			(0x7 << 11)
++#define OMAP3430_CLKSEL_PCLK_SHIFT			8
++#define OMAP3430_CLKSEL_PCLK_MASK			(0x7 << 8)
++#define OMAP3430_CLKSEL_PCLKX2_SHIFT			6
++#define OMAP3430_CLKSEL_PCLKX2_MASK			(0x3 << 6)
++#define OMAP3430_CLKSEL_ATCLK_SHIFT			4
++#define OMAP3430_CLKSEL_ATCLK_MASK			(0x3 << 4)
++#define OMAP3430_TRACE_MUX_CTRL_SHIFT			2
++#define OMAP3430_TRACE_MUX_CTRL_MASK			(0x3 << 2)
++#define OMAP3430_MUX_CTRL_SHIFT				0
++#define OMAP3430_MUX_CTRL_MASK				(0x3 << 0)
++
++/* CM_CLKSTCTRL_EMU */
++#define OMAP3430_CLKTRCTRL_EMU_SHIFT			0
++#define OMAP3430_CLKTRCTRL_EMU_MASK			(0x3 << 0)
++
++/* CM_CLKSTST_EMU */
++#define OMAP3430_CLKACTIVITY_EMU			(1 << 0)
++
++/* CM_CLKSEL2_EMU specific bits */
++#define OMAP3430_CORE_DPLL_EMU_MULT_SHIFT		8
++#define OMAP3430_CORE_DPLL_EMU_MULT_MASK		(0x7ff << 8)
++#define OMAP3430_CORE_DPLL_EMU_DIV_SHIFT		0
++#define OMAP3430_CORE_DPLL_EMU_DIV_MASK			(0x7f << 0)
++
++/* CM_CLKSEL3_EMU specific bits */
++#define OMAP3430_PERIPH_DPLL_EMU_MULT_SHIFT		8
++#define OMAP3430_PERIPH_DPLL_EMU_MULT_MASK		(0x7ff << 8)
++#define OMAP3430_PERIPH_DPLL_EMU_DIV_SHIFT		0
++#define OMAP3430_PERIPH_DPLL_EMU_DIV_MASK		(0x7f << 0)
++
++/* CM_POLCTRL */
++#define OMAP3430_CLKOUT2_POL				(1 << 0)
++
++/* CM_IDLEST_NEON */
++#define OMAP3430_ST_NEON				(1 << 0)
++
++/* CM_CLKSTCTRL_NEON */
++#define OMAP3430_CLKTRCTRL_NEON_SHIFT			0
++#define OMAP3430_CLKTRCTRL_NEON_MASK			(0x3 << 0)
++
++/* CM_FCLKEN_USBHOST */
++#define OMAP3430ES2_EN_USBHOST2_SHIFT			1
++#define OMAP3430ES2_EN_USBHOST2_MASK			(1 << 1)
++#define OMAP3430ES2_EN_USBHOST1_SHIFT			0
++#define OMAP3430ES2_EN_USBHOST1_MASK			(1 << 0)
++
++/* CM_ICLKEN_USBHOST */
++#define OMAP3430ES2_EN_USBHOST_SHIFT			0
++#define OMAP3430ES2_EN_USBHOST_MASK			(1 << 0)
++
++/* CM_IDLEST_USBHOST */
++
++/* CM_AUTOIDLE_USBHOST */
++#define OMAP3430ES2_AUTO_USBHOST_SHIFT			0
++#define OMAP3430ES2_AUTO_USBHOST_MASK			(1 << 0)
++
++/* CM_SLEEPDEP_USBHOST */
++#define OMAP3430ES2_EN_MPU_SHIFT			1
++#define OMAP3430ES2_EN_MPU_MASK				(1 << 1)
++#define OMAP3430ES2_EN_IVA2_SHIFT			2
++#define OMAP3430ES2_EN_IVA2_MASK			(1 << 2)
++
++/* CM_CLKSTCTRL_USBHOST */
++#define OMAP3430ES2_CLKTRCTRL_USBHOST_SHIFT		0
++#define OMAP3430ES2_CLKTRCTRL_USBHOST_MASK		(3 << 0)
++
++
++
++#endif
+diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h
+new file mode 100644
+index 0000000..8489f30
+--- /dev/null
++++ b/arch/arm/mach-omap2/cm.h
+@@ -0,0 +1,124 @@
++#ifndef __ARCH_ASM_MACH_OMAP2_CM_H
++#define __ARCH_ASM_MACH_OMAP2_CM_H
++
++/*
++ * OMAP2/3 Clock Management (CM) register definitions
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "prcm-common.h"
++
++#ifndef __ASSEMBLER__
++#define OMAP_CM_REGADDR(module, reg)					\
++	(void __iomem *)IO_ADDRESS(OMAP2_CM_BASE + (module) + (reg))
++#else
++#define OMAP2420_CM_REGADDR(module, reg)				\
++			IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
++#define OMAP2430_CM_REGADDR(module, reg)				\
++			IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
++#define OMAP34XX_CM_REGADDR(module, reg)				\
++			IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
++#endif
++
++/*
++ * Architecture-specific global CM registers
++ * Use cm_{read,write}_reg() with these registers.
++ * These registers appear once per CM module.
++ */
++
++#define OMAP3430_CM_REVISION		OMAP_CM_REGADDR(OCP_MOD, 0x0000)
++#define OMAP3430_CM_SYSCONFIG		OMAP_CM_REGADDR(OCP_MOD, 0x0010)
++#define OMAP3430_CM_POLCTRL		OMAP_CM_REGADDR(OCP_MOD, 0x009c)
++
++#define OMAP3430_CM_CLKOUT_CTRL		OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
++
++/*
++ * Module specific CM registers from CM_BASE + domain offset
++ * Use cm_{read,write}_mod_reg() with these registers.
++ * These register offsets generally appear in more than one PRCM submodule.
++ */
++
++/* Common between 24xx and 34xx */
++
++#define CM_FCLKEN					0x0000
++#define CM_FCLKEN1					CM_FCLKEN
++#define CM_CLKEN					CM_FCLKEN
++#define CM_ICLKEN					0x0010
++#define CM_ICLKEN1					CM_ICLKEN
++#define CM_ICLKEN2					0x0014
++#define CM_ICLKEN3					0x0018
++#define CM_IDLEST					0x0020
++#define CM_IDLEST1					CM_IDLEST
++#define CM_IDLEST2					0x0024
++#define CM_AUTOIDLE					0x0030
++#define CM_AUTOIDLE1					CM_AUTOIDLE
++#define CM_AUTOIDLE2					0x0034
++#define CM_AUTOIDLE3					0x0038
++#define CM_CLKSEL					0x0040
++#define CM_CLKSEL1					CM_CLKSEL
++#define CM_CLKSEL2					0x0044
++#define CM_CLKSTCTRL					0x0048
++
++
++/* Architecture-specific registers */
++
++#define OMAP24XX_CM_FCLKEN2				0x0004
++#define OMAP24XX_CM_ICLKEN4				0x001c
++#define OMAP24XX_CM_AUTOIDLE4				0x003c
++
++#define OMAP2430_CM_IDLEST3				0x0028
++
++#define OMAP3430_CM_CLKEN_PLL				0x0004
++#define OMAP3430ES2_CM_CLKEN2				0x0004
++#define OMAP3430ES2_CM_FCLKEN3				0x0008
++#define OMAP3430_CM_IDLEST_PLL				CM_IDLEST2
++#define OMAP3430_CM_AUTOIDLE_PLL			CM_AUTOIDLE2
++#define OMAP3430_CM_CLKSEL1				CM_CLKSEL
++#define OMAP3430_CM_CLKSEL1_PLL				CM_CLKSEL
++#define OMAP3430_CM_CLKSEL2_PLL				CM_CLKSEL2
++#define OMAP3430_CM_SLEEPDEP				CM_CLKSEL2
++#define OMAP3430_CM_CLKSEL3				CM_CLKSTCTRL
++#define OMAP3430_CM_CLKSTST				0x004c
++#define OMAP3430ES2_CM_CLKSEL4				0x004c
++#define OMAP3430ES2_CM_CLKSEL5				0x0050
++#define OMAP3430_CM_CLKSEL2_EMU				0x0050
++#define OMAP3430_CM_CLKSEL3_EMU				0x0054
++
++
++/* Clock management domain register get/set */
++
++#ifndef __ASSEMBLER__
++static inline void cm_write_mod_reg(u32 val, s16 module, s16 idx)
++{
++	__raw_writel(val, OMAP_CM_REGADDR(module, idx));
++}
++
++static inline u32 cm_read_mod_reg(s16 module, s16 idx)
++{
++	return __raw_readl(OMAP_CM_REGADDR(module, idx));
++}
++#endif
++
++/* CM register bits shared between 24XX and 3430 */
++
++/* CM_CLKSEL_GFX */
++#define OMAP_CLKSEL_GFX_SHIFT				0
++#define OMAP_CLKSEL_GFX_MASK				(0x7 << 0)
++
++/* CM_ICLKEN_GFX */
++#define OMAP_EN_GFX_SHIFT				0
++#define OMAP_EN_GFX					(1 << 0)
++
++/* CM_IDLEST_GFX */
++#define OMAP_ST_GFX					(1 << 0)
++
++
++#endif
+diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
+new file mode 100644
+index 0000000..a5d86a4
+--- /dev/null
++++ b/arch/arm/mach-omap2/control.c
+@@ -0,0 +1,74 @@
++/*
++ * OMAP2/3 System Control Module register access
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#undef DEBUG
++
++#include <linux/kernel.h>
++
++#include <asm/io.h>
++
++#include <asm/arch/control.h>
++
++static u32 omap2_ctrl_base;
++
++#define OMAP_CTRL_REGADDR(reg)	(void __iomem *)IO_ADDRESS(omap2_ctrl_base \
++								+ (reg))
++
++void omap_ctrl_base_set(u32 base)
++{
++	omap2_ctrl_base = base;
++}
++
++u32 omap_ctrl_base_get(void)
++{
++	return omap2_ctrl_base;
++}
++
++u8 omap_ctrl_readb(u16 offset)
++{
++	return __raw_readb(OMAP_CTRL_REGADDR(offset));
++}
++
++u16 omap_ctrl_readw(u16 offset)
++{
++	return __raw_readw(OMAP_CTRL_REGADDR(offset));
++}
++
++u32 omap_ctrl_readl(u16 offset)
++{
++	return __raw_readl(OMAP_CTRL_REGADDR(offset));
++}
++
++void omap_ctrl_writeb(u8 val, u16 offset)
++{
++	pr_debug("omap_ctrl_writeb: writing 0x%0x to 0x%0x\n", val,
++		 (u32)OMAP_CTRL_REGADDR(offset));
++
++	__raw_writeb(val, OMAP_CTRL_REGADDR(offset));
++}
++
++void omap_ctrl_writew(u16 val, u16 offset)
++{
++	pr_debug("omap_ctrl_writew: writing 0x%0x to 0x%0x\n", val,
++		 (u32)OMAP_CTRL_REGADDR(offset));
++
++	__raw_writew(val, OMAP_CTRL_REGADDR(offset));
++}
++
++void omap_ctrl_writel(u32 val, u16 offset)
++{
++	pr_debug("omap_ctrl_writel: writing 0x%0x to 0x%0x\n", val,
++		 (u32)OMAP_CTRL_REGADDR(offset));
++
++	__raw_writel(val, OMAP_CTRL_REGADDR(offset));
++}
++
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 5a4cc20..02cede2 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -69,7 +69,7 @@ static void __iomem *gpmc_base =
+ static void __iomem *gpmc_cs_base =
+ 	(void __iomem *) IO_ADDRESS(GPMC_BASE) + GPMC_CS0;
+ 
+-static struct clk *gpmc_l3_clk;
++static struct clk *gpmc_fck;
+ 
+ static void gpmc_write_reg(int idx, u32 val)
+ {
+@@ -94,11 +94,10 @@ u32 gpmc_cs_read_reg(int cs, int idx)
+ 	return __raw_readl(gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx);
+ }
+ 
+-/* TODO: Add support for gpmc_fck to clock framework and use it */
+ unsigned long gpmc_get_fclk_period(void)
+ {
+ 	/* In picoseconds */
+-	return 1000000000 / ((clk_get_rate(gpmc_l3_clk)) / 1000);
++	return 1000000000 / ((clk_get_rate(gpmc_fck)) / 1000);
+ }
+ 
+ unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+@@ -398,8 +397,11 @@ void __init gpmc_init(void)
+ {
+ 	u32 l;
+ 
+-	gpmc_l3_clk = clk_get(NULL, "core_l3_ck");
+-	BUG_ON(IS_ERR(gpmc_l3_clk));
++	gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */
++	if (IS_ERR(gpmc_fck))
++		WARN_ON(1);
++	else
++		clk_enable(gpmc_fck);
+ 
+ 	l = gpmc_read_reg(GPMC_REVISION);
+ 	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
+diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c
+index 3e5d8cd..1247908 100644
+--- a/arch/arm/mach-omap2/memory.c
++++ b/arch/arm/mach-omap2/memory.c
+@@ -27,11 +27,16 @@
+ #include <asm/arch/clock.h>
+ #include <asm/arch/sram.h>
+ 
+-#include "prcm-regs.h"
++#include "prm.h"
++
+ #include "memory.h"
++#include "sdrc.h"
+ 
++unsigned long omap2_sdrc_base;
++unsigned long omap2_sms_base;
+ 
+ static struct memory_timings mem_timings;
++static u32 curr_perf_level = CORE_CLK_SRC_DPLL_X2;
+ 
+ u32 omap2_memory_get_slow_dll_ctrl(void)
+ {
+@@ -48,12 +53,60 @@ u32 omap2_memory_get_type(void)
+ 	return mem_timings.m_type;
+ }
+ 
++/*
++ * Check the DLL lock state, and return tue if running in unlock mode.
++ * This is needed to compensate for the shifted DLL value in unlock mode.
++ */
++u32 omap2_dll_force_needed(void)
++{
++	/* dlla and dllb are a set */
++	u32 dll_state = sdrc_read_reg(SDRC_DLLA_CTRL);
++
++	if ((dll_state & (1 << 2)) == (1 << 2))
++		return 1;
++	else
++		return 0;
++}
++
++/*
++ * 'level' is the value to store to CM_CLKSEL2_PLL.CORE_CLK_SRC.
++ * Practical values are CORE_CLK_SRC_DPLL (for CORE_CLK = DPLL_CLK) or
++ * CORE_CLK_SRC_DPLL_X2 (for CORE_CLK = * DPLL_CLK * 2)
++ */
++u32 omap2_reprogram_sdrc(u32 level, u32 force)
++{
++	u32 dll_ctrl, m_type;
++	u32 prev = curr_perf_level;
++	unsigned long flags;
++
++	if ((curr_perf_level == level) && !force)
++		return prev;
++
++	if (level == CORE_CLK_SRC_DPLL) {
++		dll_ctrl = omap2_memory_get_slow_dll_ctrl();
++	} else if (level == CORE_CLK_SRC_DPLL_X2) {
++		dll_ctrl = omap2_memory_get_fast_dll_ctrl();
++	} else {
++		return prev;
++	}
++
++	m_type = omap2_memory_get_type();
++
++	local_irq_save(flags);
++	__raw_writel(0xffff, OMAP24XX_PRCM_VOLTSETUP);
++	omap2_sram_reprogram_sdrc(level, dll_ctrl, m_type);
++	curr_perf_level = level;
++	local_irq_restore(flags);
++
++	return prev;
++}
++
+ void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+ {
+ 	unsigned long dll_cnt;
+ 	u32 fast_dll = 0;
+ 
+-	mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
++	mem_timings.m_type = !((sdrc_read_reg(SDRC_MR_0) & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+ 
+ 	/* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
+ 	 * In the case of 2422, its ok to use CS1 instead of CS0.
+@@ -73,11 +126,11 @@ void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+ 		mem_timings.dll_mode = M_LOCK;
+ 
+ 	if (mem_timings.base_cs == 0) {
+-		fast_dll = SDRC_DLLA_CTRL;
+-		dll_cnt = SDRC_DLLA_STATUS & 0xff00;
++		fast_dll = sdrc_read_reg(SDRC_DLLA_CTRL);
++		dll_cnt = sdrc_read_reg(SDRC_DLLA_STATUS) & 0xff00;
+ 	} else {
+-		fast_dll = SDRC_DLLB_CTRL;
+-		dll_cnt = SDRC_DLLB_STATUS & 0xff00;
++		fast_dll = sdrc_read_reg(SDRC_DLLB_CTRL);
++		dll_cnt = sdrc_read_reg(SDRC_DLLB_STATUS) & 0xff00;
+ 	}
+ 	if (force_lock_to_unlock_mode) {
+ 		fast_dll &= ~0xff00;
+@@ -106,14 +159,13 @@ void __init omap2_init_memory(void)
+ {
+ 	u32 l;
+ 
+-	l = SMS_SYSCONFIG;
++	l = sms_read_reg(SMS_SYSCONFIG);
+ 	l &= ~(0x3 << 3);
+ 	l |= (0x2 << 3);
+-	SMS_SYSCONFIG = l;
++	sms_write_reg(l, SMS_SYSCONFIG);
+ 
+-	l = SDRC_SYSCONFIG;
++	l = sdrc_read_reg(SDRC_SYSCONFIG);
+ 	l &= ~(0x3 << 3);
+ 	l |= (0x2 << 3);
+-	SDRC_SYSCONFIG = l;
+-
++	sdrc_write_reg(l, SDRC_SYSCONFIG);
+ }
+diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h
+index d212eea..9a280b5 100644
+--- a/arch/arm/mach-omap2/memory.h
++++ b/arch/arm/mach-omap2/memory.h
+@@ -32,3 +32,5 @@ extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
+ extern u32 omap2_memory_get_slow_dll_ctrl(void);
+ extern u32 omap2_memory_get_fast_dll_ctrl(void);
+ extern u32 omap2_memory_get_type(void);
++u32 omap2_dll_force_needed(void);
++u32 omap2_reprogram_sdrc(u32 level, u32 force);
+diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
+index 0575097..9307700 100644
+--- a/arch/arm/mach-omap2/mux.c
++++ b/arch/arm/mach-omap2/mux.c
+@@ -1,11 +1,12 @@
+ /*
+  * linux/arch/arm/mach-omap2/mux.c
+  *
+- * OMAP1 pin multiplexing configurations
++ * OMAP2 pin multiplexing configurations
+  *
+- * Copyright (C) 2003 - 2005 Nokia Corporation
++ * Copyright (C) 2004 - 2008 Texas Instruments Inc.
++ * Copyright (C) 2003 - 2008 Nokia Corporation
+  *
+- * Written by Tony Lindgren <tony.lindgren at nokia.com>
++ * Written by Tony Lindgren
+  *
+  * This 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,13 +29,17 @@
+ #include <asm/io.h>
+ #include <linux/spinlock.h>
+ 
++#include <asm/arch/control.h>
+ #include <asm/arch/mux.h>
+ 
+ #ifdef CONFIG_OMAP_MUX
+ 
++static struct omap_mux_cfg arch_mux_cfg;
++
+ /* NOTE: See mux.h for the enumeration */
+ 
+-struct pin_config __initdata_or_module omap24xx_pins[] = {
++#ifdef CONFIG_ARCH_OMAP24XX
++static struct pin_config __initdata_or_module omap24xx_pins[] = {
+ /*
+  *	description			mux	mux	pull	pull	debug
+  *					offset	mode	ena	type
+@@ -77,7 +82,12 @@ MUX_CFG_24XX("AA12_242X_GPIO17",	0x0e9,	3,	0,	0,	1)
+ MUX_CFG_24XX("AA8_242X_GPIO58",		0x0ea,	3,	0,	0,	1)
+ MUX_CFG_24XX("Y20_24XX_GPIO60",		0x12c,	3,	0,	0,	1)
+ MUX_CFG_24XX("W4__24XX_GPIO74",		0x0f2,	3,	0,	0,	1)
++MUX_CFG_24XX("N15_24XX_GPIO85",		0x103,	3,	0,	0,	1)
+ MUX_CFG_24XX("M15_24XX_GPIO92",		0x10a,	3,	0,	0,	1)
++MUX_CFG_24XX("P20_24XX_GPIO93",		0x10b,	3,	0,	0,	1)
++MUX_CFG_24XX("P18_24XX_GPIO95",		0x10d,	3,	0,	0,	1)
++MUX_CFG_24XX("M18_24XX_GPIO96",		0x10e,	3,	0,	0,	1)
++MUX_CFG_24XX("L14_24XX_GPIO97",		0x10f,	3,	0,	0,	1)
+ MUX_CFG_24XX("J15_24XX_GPIO99",		0x113,	3,	1,	1,	1)
+ MUX_CFG_24XX("V14_24XX_GPIO117",	0x128,	3,	1,	0,	1)
+ MUX_CFG_24XX("P14_24XX_GPIO125",	0x140,	3,	1,	1,	1)
+@@ -102,9 +112,6 @@ MUX_CFG_24XX("G4_242X_DMAREQ3",		0x073,	2,	0,	0,	1)
+ MUX_CFG_24XX("D3_242X_DMAREQ4",		0x072,	2,	0,	0,	1)
+ MUX_CFG_24XX("E3_242X_DMAREQ5",		0x071,	2,	0,	0,	1)
+ 
+-/* TSC IRQ */
+-MUX_CFG_24XX("P20_24XX_TSC_IRQ",	0x108,	0,	0,	0,	1)
+-
+ /* UART3 */
+ MUX_CFG_24XX("K15_24XX_UART3_TX",	0x118,	0,	0,	0,	1)
+ MUX_CFG_24XX("K14_24XX_UART3_RX",	0x119,	0,	0,	0,	1)
+@@ -167,12 +174,108 @@ MUX_CFG_24XX("B3__24XX_KBR5",		0x30,	3,	1,	1,	1)
+ MUX_CFG_24XX("AA4_24XX_KBC2",		0xe7,	3,	0,	0,	1)
+ MUX_CFG_24XX("B13_24XX_KBC6",		0x110,	3,	0,	0,	1)
+ 
++/* 2430 USB */
++MUX_CFG_24XX("AD9_2430_USB0_PUEN",	0x133,	4,	0,	0,	1)
++MUX_CFG_24XX("Y11_2430_USB0_VP",	0x134,	4,	0,	0,	1)
++MUX_CFG_24XX("AD7_2430_USB0_VM",	0x135,	4,	0,	0,	1)
++MUX_CFG_24XX("AE7_2430_USB0_RCV",	0x136,	4,	0,	0,	1)
++MUX_CFG_24XX("AD4_2430_USB0_TXEN",	0x137,	4,	0,	0,	1)
++MUX_CFG_24XX("AF9_2430_USB0_SE0",	0x138,	4,	0,	0,	1)
++MUX_CFG_24XX("AE6_2430_USB0_DAT",	0x139,	4,	0,	0,	1)
++MUX_CFG_24XX("AD24_2430_USB1_SE0",	0x107,	2,	0,	0,	1)
++MUX_CFG_24XX("AB24_2430_USB1_RCV",	0x108,	2,	0,	0,	1)
++MUX_CFG_24XX("Y25_2430_USB1_TXEN",	0x109,	2,	0,	0,	1)
++MUX_CFG_24XX("AA26_2430_USB1_DAT",	0x10A,	2,	0,	0,	1)
++
++/* 2430 HS-USB */
++MUX_CFG_24XX("AD9_2430_USB0HS_DATA3",	0x133,	0,	0,	0,	1)
++MUX_CFG_24XX("Y11_2430_USB0HS_DATA4",	0x134,	0,	0,	0,	1)
++MUX_CFG_24XX("AD7_2430_USB0HS_DATA5",	0x135,	0,	0,	0,	1)
++MUX_CFG_24XX("AE7_2430_USB0HS_DATA6",	0x136,	0,	0,	0,	1)
++MUX_CFG_24XX("AD4_2430_USB0HS_DATA2",	0x137,	0,	0,	0,	1)
++MUX_CFG_24XX("AF9_2430_USB0HS_DATA0",	0x138,	0,	0,	0,	1)
++MUX_CFG_24XX("AE6_2430_USB0HS_DATA1",	0x139,	0,	0,	0,	1)
++MUX_CFG_24XX("AE8_2430_USB0HS_CLK",	0x13A,	0,	0,	0,	1)
++MUX_CFG_24XX("AD8_2430_USB0HS_DIR",	0x13B,	0,	0,	0,	1)
++MUX_CFG_24XX("AE5_2430_USB0HS_STP",	0x13c,	0,	1,	1,	1)
++MUX_CFG_24XX("AE9_2430_USB0HS_NXT",	0x13D,	0,	0,	0,	1)
++MUX_CFG_24XX("AC7_2430_USB0HS_DATA7",	0x13E,	0,	0,	0,	1)
++
++/* 2430 McBSP */
++MUX_CFG_24XX("AC10_2430_MCBSP2_FSX",	0x012E,	1,	0,	0,	1)
++MUX_CFG_24XX("AD16_2430_MCBSP2_CLX",	0x012F,	1,	0,	0,	1)
++MUX_CFG_24XX("AE13_2430_MCBSP2_DX",	0x0130,	1,	0,	0,	1)
++MUX_CFG_24XX("AD13_2430_MCBSP2_DR",	0x0131,	1,	0,	0,	1)
++MUX_CFG_24XX("AC10_2430_MCBSP2_FSX_OFF",0x012E,	0,	0,	0,	1)
++MUX_CFG_24XX("AD16_2430_MCBSP2_CLX_OFF",0x012F,	0,	0,	0,	1)
++MUX_CFG_24XX("AE13_2430_MCBSP2_DX_OFF",	0x0130,	0,	0,	0,	1)
++MUX_CFG_24XX("AD13_2430_MCBSP2_DR_OFF",	0x0131,	0,	0,	0,	1)
+ };
+ 
+-int __init omap2_mux_init(void)
++#define OMAP24XX_PINS_SZ	ARRAY_SIZE(omap24xx_pins)
++
++#else
++#define omap24xx_pins		NULL
++#define OMAP24XX_PINS_SZ	0
++#endif	/* CONFIG_ARCH_OMAP24XX */
++
++#define OMAP24XX_PULL_ENA	(1 << 3)
++#define OMAP24XX_PULL_UP	(1 << 4)
++
++#if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
++void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u8 reg)
+ {
+-	omap_mux_register(omap24xx_pins, ARRAY_SIZE(omap24xx_pins));
++	u16 orig;
++	u8 warn = 0, debug = 0;
++
++	orig = omap_ctrl_readb(cfg->mux_reg);
++
++#ifdef	CONFIG_OMAP_MUX_DEBUG
++	debug = cfg->debug;
++#endif
++	warn = (orig != reg);
++	if (debug || warn)
++		printk(KERN_WARNING
++			"MUX: setup %s (0x%08x): 0x%02x -> 0x%02x\n",
++			cfg->name, omap_ctrl_base_get() + cfg->mux_reg,
++			orig, reg);
++}
++#else
++#define omap2_cfg_debug(x, y)	do {} while (0)
++#endif
++
++#ifdef CONFIG_ARCH_OMAP24XX
++int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg)
++{
++	static DEFINE_SPINLOCK(mux_spin_lock);
++	unsigned long flags;
++	u8 reg = 0;
++
++	spin_lock_irqsave(&mux_spin_lock, flags);
++	reg |= cfg->mask & 0x7;
++	if (cfg->pull_val)
++		reg |= OMAP24XX_PULL_ENA;
++	if (cfg->pu_pd_val)
++		reg |= OMAP24XX_PULL_UP;
++	omap2_cfg_debug(cfg, reg);
++	omap_ctrl_writeb(reg, cfg->mux_reg);
++	spin_unlock_irqrestore(&mux_spin_lock, flags);
++
+ 	return 0;
+ }
++#else
++#define omap24xx_cfg_reg	0
++#endif
++
++int __init omap2_mux_init(void)
++{
++	if (cpu_is_omap24xx()) {
++		arch_mux_cfg.pins	= omap24xx_pins;
++		arch_mux_cfg.size	= OMAP24XX_PINS_SZ;
++		arch_mux_cfg.cfg_reg	= omap24xx_cfg_reg;
++	}
++
++	return omap_mux_register(&arch_mux_cfg);
++}
+ 
+ #endif
+diff --git a/arch/arm/mach-omap2/pm-domain.c b/arch/arm/mach-omap2/pm-domain.c
+deleted file mode 100644
+index 2494091..0000000
+--- a/arch/arm/mach-omap2/pm-domain.c
++++ /dev/null
+@@ -1,299 +0,0 @@
+-/*
+- * linux/arch/arm/mach-omap2/pm-domain.c
+- *
+- * Power domain functions for OMAP2
+- *
+- * Copyright (C) 2006 Nokia Corporation
+- * Tony Lindgren <tony at atomide.com>
+- *
+- * Some code based on earlier OMAP2 sample PM code
+- * Copyright (C) 2005 Texas Instruments, Inc.
+- * Richard Woodruff <r-woodruff2 at ti.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/clk.h>
+-
+-#include <asm/io.h>
+-
+-#include "prcm-regs.h"
+-
+-/* Power domain offsets */
+-#define PM_MPU_OFFSET			0x100
+-#define PM_CORE_OFFSET			0x200
+-#define PM_GFX_OFFSET			0x300
+-#define PM_WKUP_OFFSET			0x400		/* Autoidle only */
+-#define PM_PLL_OFFSET			0x500		/* Autoidle only */
+-#define PM_DSP_OFFSET			0x800
+-#define PM_MDM_OFFSET			0xc00
+-
+-/* Power domain wake-up dependency control register */
+-#define PM_WKDEP_OFFSET			0xc8
+-#define		EN_MDM			(1 << 5)
+-#define		EN_WKUP			(1 << 4)
+-#define		EN_GFX			(1 << 3)
+-#define		EN_DSP			(1 << 2)
+-#define		EN_MPU			(1 << 1)
+-#define		EN_CORE			(1 << 0)
+-
+-/* Core power domain state transition control register */
+-#define PM_PWSTCTRL_OFFSET		0xe0
+-#define		FORCESTATE		(1 << 18)	/* Only for DSP & GFX */
+-#define		MEM4RETSTATE		(1 << 6)
+-#define		MEM3RETSTATE		(1 << 5)
+-#define		MEM2RETSTATE		(1 << 4)
+-#define		MEM1RETSTATE		(1 << 3)
+-#define		LOGICRETSTATE		(1 << 2)	/* Logic is retained */
+-#define		POWERSTATE_OFF		0x3
+-#define		POWERSTATE_RETENTION	0x1
+-#define		POWERSTATE_ON		0x0
+-
+-/* Power domain state register */
+-#define PM_PWSTST_OFFSET		0xe4
+-
+-/* Hardware supervised state transition control register */
+-#define CM_CLKSTCTRL_OFFSET		0x48
+-#define		AUTOSTAT_MPU		(1 << 0)	/* MPU */
+-#define		AUTOSTAT_DSS		(1 << 2)	/* Core */
+-#define		AUTOSTAT_L4		(1 << 1)	/* Core */
+-#define		AUTOSTAT_L3		(1 << 0)	/* Core */
+-#define		AUTOSTAT_GFX		(1 << 0)	/* GFX */
+-#define		AUTOSTAT_IVA		(1 << 8)	/* 2420 IVA in DSP domain */
+-#define		AUTOSTAT_DSP		(1 << 0)	/* DSP */
+-#define		AUTOSTAT_MDM		(1 << 0)	/* MDM */
+-
+-/* Automatic control of interface clock idling */
+-#define CM_AUTOIDLE1_OFFSET		0x30
+-#define CM_AUTOIDLE2_OFFSET		0x34		/* Core only */
+-#define CM_AUTOIDLE3_OFFSET		0x38		/* Core only */
+-#define CM_AUTOIDLE4_OFFSET		0x3c		/* Core only */
+-#define		AUTO_54M(x)		(((x) & 0x3) << 6)
+-#define		AUTO_96M(x)		(((x) & 0x3) << 2)
+-#define		AUTO_DPLL(x)		(((x) & 0x3) << 0)
+-#define		AUTO_STOPPED		0x3
+-#define		AUTO_BYPASS_FAST	0x2		/* DPLL only */
+-#define		AUTO_BYPASS_LOW_POWER	0x1		/* DPLL only */
+-#define		AUTO_DISABLED		0x0
+-
+-/* Voltage control PRCM_VOLTCTRL bits */
+-#define		AUTO_EXTVOLT		(1 << 15)
+-#define		FORCE_EXTVOLT		(1 << 14)
+-#define		SETOFF_LEVEL(x)		(((x) & 0x3) << 12)
+-#define		MEMRETCTRL		(1 << 8)
+-#define		SETRET_LEVEL(x)		(((x) & 0x3) << 6)
+-#define		VOLT_LEVEL(x)		(((x) & 0x3) << 0)
+-
+-#define OMAP24XX_PRCM_VBASE	IO_ADDRESS(OMAP24XX_PRCM_BASE)
+-#define prcm_readl(r)		__raw_readl(OMAP24XX_PRCM_VBASE + (r))
+-#define prcm_writel(v, r)	__raw_writel((v), OMAP24XX_PRCM_VBASE + (r))
+-
+-static u32 pmdomain_get_wakeup_dependencies(int domain_offset)
+-{
+-	return prcm_readl(domain_offset + PM_WKDEP_OFFSET);
+-}
+-
+-static void pmdomain_set_wakeup_dependencies(u32 state, int domain_offset)
+-{
+-	prcm_writel(state, domain_offset + PM_WKDEP_OFFSET);
+-}
+-
+-static u32 pmdomain_get_powerstate(int domain_offset)
+-{
+-	return prcm_readl(domain_offset + PM_PWSTCTRL_OFFSET);
+-}
+-
+-static void pmdomain_set_powerstate(u32 state, int domain_offset)
+-{
+-	prcm_writel(state, domain_offset + PM_PWSTCTRL_OFFSET);
+-}
+-
+-static u32 pmdomain_get_clock_autocontrol(int domain_offset)
+-{
+-	return prcm_readl(domain_offset + CM_CLKSTCTRL_OFFSET);
+-}
+-
+-static void pmdomain_set_clock_autocontrol(u32 state, int domain_offset)
+-{
+-	prcm_writel(state, domain_offset + CM_CLKSTCTRL_OFFSET);
+-}
+-
+-static u32 pmdomain_get_clock_autoidle1(int domain_offset)
+-{
+-	return prcm_readl(domain_offset + CM_AUTOIDLE1_OFFSET);
+-}
+-
+-/* Core domain only */
+-static u32 pmdomain_get_clock_autoidle2(int domain_offset)
+-{
+-	return prcm_readl(domain_offset + CM_AUTOIDLE2_OFFSET);
+-}
+-
+-/* Core domain only */
+-static u32 pmdomain_get_clock_autoidle3(int domain_offset)
+-{
+-	return prcm_readl(domain_offset + CM_AUTOIDLE3_OFFSET);
+-}
+-
+-/* Core domain only */
+-static u32 pmdomain_get_clock_autoidle4(int domain_offset)
+-{
+-	return prcm_readl(domain_offset + CM_AUTOIDLE4_OFFSET);
+-}
+-
+-static void pmdomain_set_clock_autoidle1(u32 state, int domain_offset)
+-{
+-	prcm_writel(state, CM_AUTOIDLE1_OFFSET + domain_offset);
+-}
+-
+-/* Core domain only */
+-static void pmdomain_set_clock_autoidle2(u32 state, int domain_offset)
+-{
+-	prcm_writel(state, CM_AUTOIDLE2_OFFSET + domain_offset);
+-}
+-
+-/* Core domain only */
+-static void pmdomain_set_clock_autoidle3(u32 state, int domain_offset)
+-{
+-	prcm_writel(state, CM_AUTOIDLE3_OFFSET + domain_offset);
+-}
+-
+-/* Core domain only */
+-static void pmdomain_set_clock_autoidle4(u32 state, int domain_offset)
+-{
+-	prcm_writel(state, CM_AUTOIDLE4_OFFSET + domain_offset);
+-}
+-
+-/*
+- * Configures power management domains to idle clocks automatically.
+- */
+-void pmdomain_set_autoidle(void)
+-{
+-	u32 val;
+-
+-	/* Set PLL auto stop for 54M, 96M & DPLL */
+-	pmdomain_set_clock_autoidle1(AUTO_54M(AUTO_STOPPED) |
+-				     AUTO_96M(AUTO_STOPPED) |
+-				     AUTO_DPLL(AUTO_STOPPED), PM_PLL_OFFSET);
+-
+-	/* External clock input control
+-	 * REVISIT: Should this be in clock framework?
+-	 */
+-	PRCM_CLKSRC_CTRL |= (0x3 << 3);
+-
+-	/* Configure number of 32KHz clock cycles for sys_clk */
+-	PRCM_CLKSSETUP = 0x00ff;
+-
+-	/* Configure automatic voltage transition */
+-	PRCM_VOLTSETUP = 0;
+-	val = PRCM_VOLTCTRL;
+-	val &= ~(SETOFF_LEVEL(0x3) | VOLT_LEVEL(0x3));
+-	val |= SETOFF_LEVEL(1) | VOLT_LEVEL(1) | AUTO_EXTVOLT;
+-	PRCM_VOLTCTRL = val;
+-
+-	/* Disable emulation tools functional clock */
+-	PRCM_CLKEMUL_CTRL = 0x0;
+-
+-	/* Set core memory retention state */
+-	val = pmdomain_get_powerstate(PM_CORE_OFFSET);
+-	if (cpu_is_omap2420()) {
+-		val &= ~(0x7 << 3);
+-		val |= (MEM3RETSTATE | MEM2RETSTATE | MEM1RETSTATE);
+-	} else {
+-		val &= ~(0xf << 3);
+-		val |= (MEM4RETSTATE | MEM3RETSTATE | MEM2RETSTATE |
+-			MEM1RETSTATE);
+-	}
+-	pmdomain_set_powerstate(val, PM_CORE_OFFSET);
+-
+-	/* OCP interface smart idle. REVISIT: Enable autoidle bit0 ? */
+-	val = SMS_SYSCONFIG;
+-	val &= ~(0x3 << 3);
+-	val |= (0x2 << 3) | (1 << 0);
+-	SMS_SYSCONFIG |= val;
+-
+-	val = SDRC_SYSCONFIG;
+-	val &= ~(0x3 << 3);
+-	val |= (0x2 << 3);
+-	SDRC_SYSCONFIG = val;
+-
+-	/* Configure L3 interface for smart idle.
+-	 * REVISIT: Enable autoidle bit0 ?
+-	 */
+-	val = GPMC_SYSCONFIG;
+-	val &= ~(0x3 << 3);
+-	val |= (0x2 << 3) | (1 << 0);
+-	GPMC_SYSCONFIG = val;
+-
+-	pmdomain_set_powerstate(LOGICRETSTATE | POWERSTATE_RETENTION,
+-				PM_MPU_OFFSET);
+-	pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_CORE_OFFSET);
+-	if (!cpu_is_omap2420())
+-		pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_MDM_OFFSET);
+-
+-	/* Assume suspend function has saved the state for DSP and GFX */
+-	pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_DSP_OFFSET);
+-	pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_GFX_OFFSET);
+-
+-#if 0
+-	/* REVISIT: Internal USB needs special handling */
+-	force_standby_usb();
+-	if (cpu_is_omap2430())
+-		force_hsmmc();
+-	sdram_self_refresh_on_idle_req(1);
+-#endif
+-
+-	/* Enable clock auto control for all domains.
+-	 * Note that CORE domain includes also DSS, L4 & L3.
+-	 */
+-	pmdomain_set_clock_autocontrol(AUTOSTAT_MPU, PM_MPU_OFFSET);
+-	pmdomain_set_clock_autocontrol(AUTOSTAT_GFX, PM_GFX_OFFSET);
+-	pmdomain_set_clock_autocontrol(AUTOSTAT_DSS | AUTOSTAT_L4 | AUTOSTAT_L3,
+-				       PM_CORE_OFFSET);
+-	if (cpu_is_omap2420())
+-		pmdomain_set_clock_autocontrol(AUTOSTAT_IVA | AUTOSTAT_DSP,
+-					       PM_DSP_OFFSET);
+-	else {
+-		pmdomain_set_clock_autocontrol(AUTOSTAT_DSP, PM_DSP_OFFSET);
+-		pmdomain_set_clock_autocontrol(AUTOSTAT_MDM, PM_MDM_OFFSET);
+-	}
+-
+-	/* Enable clock autoidle for all domains */
+-	pmdomain_set_clock_autoidle1(0x2, PM_DSP_OFFSET);
+-	if (cpu_is_omap2420()) {
+-		pmdomain_set_clock_autoidle1(0xfffffff9, PM_CORE_OFFSET);
+-		pmdomain_set_clock_autoidle2(0x7, PM_CORE_OFFSET);
+-		pmdomain_set_clock_autoidle1(0x3f, PM_WKUP_OFFSET);
+-	} else {
+-		pmdomain_set_clock_autoidle1(0xeafffff1, PM_CORE_OFFSET);
+-		pmdomain_set_clock_autoidle2(0xfff, PM_CORE_OFFSET);
+-		pmdomain_set_clock_autoidle1(0x7f, PM_WKUP_OFFSET);
+-		pmdomain_set_clock_autoidle1(0x3, PM_MDM_OFFSET);
+-	}
+-	pmdomain_set_clock_autoidle3(0x7, PM_CORE_OFFSET);
+-	pmdomain_set_clock_autoidle4(0x1f, PM_CORE_OFFSET);
+-}
+-
+-/*
+- * Initializes power domains by removing wake-up dependencies and powering
+- * down DSP and GFX. Gets called from PM init. Note that DSP and IVA code
+- * must re-enable DSP and GFX when used.
+- */
+-void __init pmdomain_init(void)
+-{
+-	/* Remove all domain wakeup dependencies */
+-	pmdomain_set_wakeup_dependencies(EN_WKUP | EN_CORE, PM_MPU_OFFSET);
+-	pmdomain_set_wakeup_dependencies(0, PM_DSP_OFFSET);
+-	pmdomain_set_wakeup_dependencies(0, PM_GFX_OFFSET);
+-	pmdomain_set_wakeup_dependencies(EN_WKUP | EN_MPU, PM_CORE_OFFSET);
+-	if (cpu_is_omap2430())
+-		pmdomain_set_wakeup_dependencies(0, PM_MDM_OFFSET);
+-
+-	/* Power down DSP and GFX */
+-	pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_DSP_OFFSET);
+-	pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_GFX_OFFSET);
+-}
+diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
+index baf7d82..aad781d 100644
+--- a/arch/arm/mach-omap2/pm.c
++++ b/arch/arm/mach-omap2/pm.c
+@@ -23,6 +23,7 @@
+ #include <linux/sysfs.h>
+ #include <linux/module.h>
+ #include <linux/delay.h>
++#include <linux/clk.h>
+ 
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -36,8 +37,6 @@
+ #include <asm/arch/sram.h>
+ #include <asm/arch/pm.h>
+ 
+-#include "prcm-regs.h"
+-
+ static struct clk *vclk;
+ static void (*omap2_sram_idle)(void);
+ static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
+@@ -78,251 +77,8 @@ static int omap2_pm_prepare(void)
+ 	return 0;
+ }
+ 
+-#define INT0_WAKE_MASK	(OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) |	\
+-			OMAP_IRQ_BIT(INT_24XX_GPIO_BANK2) |	\
+-			OMAP_IRQ_BIT(INT_24XX_GPIO_BANK3))
+-
+-#define INT1_WAKE_MASK	(OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4))
+-
+-#define INT2_WAKE_MASK	(OMAP_IRQ_BIT(INT_24XX_UART1_IRQ) |	\
+-			OMAP_IRQ_BIT(INT_24XX_UART2_IRQ) |	\
+-			OMAP_IRQ_BIT(INT_24XX_UART3_IRQ))
+-
+-#define preg(reg)	printk("%s\t(0x%p):\t0x%08x\n", #reg, &reg, reg);
+-
+-static void omap2_pm_debug(char * desc)
+-{
+-	printk("%s:\n", desc);
+-
+-	preg(CM_CLKSTCTRL_MPU);
+-	preg(CM_CLKSTCTRL_CORE);
+-	preg(CM_CLKSTCTRL_GFX);
+-	preg(CM_CLKSTCTRL_DSP);
+-	preg(CM_CLKSTCTRL_MDM);
+-
+-	preg(PM_PWSTCTRL_MPU);
+-	preg(PM_PWSTCTRL_CORE);
+-	preg(PM_PWSTCTRL_GFX);
+-	preg(PM_PWSTCTRL_DSP);
+-	preg(PM_PWSTCTRL_MDM);
+-
+-	preg(PM_PWSTST_MPU);
+-	preg(PM_PWSTST_CORE);
+-	preg(PM_PWSTST_GFX);
+-	preg(PM_PWSTST_DSP);
+-	preg(PM_PWSTST_MDM);
+-
+-	preg(CM_AUTOIDLE1_CORE);
+-	preg(CM_AUTOIDLE2_CORE);
+-	preg(CM_AUTOIDLE3_CORE);
+-	preg(CM_AUTOIDLE4_CORE);
+-	preg(CM_AUTOIDLE_WKUP);
+-	preg(CM_AUTOIDLE_PLL);
+-	preg(CM_AUTOIDLE_DSP);
+-	preg(CM_AUTOIDLE_MDM);
+-
+-	preg(CM_ICLKEN1_CORE);
+-	preg(CM_ICLKEN2_CORE);
+-	preg(CM_ICLKEN3_CORE);
+-	preg(CM_ICLKEN4_CORE);
+-	preg(CM_ICLKEN_GFX);
+-	preg(CM_ICLKEN_WKUP);
+-	preg(CM_ICLKEN_DSP);
+-	preg(CM_ICLKEN_MDM);
+-
+-	preg(CM_IDLEST1_CORE);
+-	preg(CM_IDLEST2_CORE);
+-	preg(CM_IDLEST3_CORE);
+-	preg(CM_IDLEST4_CORE);
+-	preg(CM_IDLEST_GFX);
+-	preg(CM_IDLEST_WKUP);
+-	preg(CM_IDLEST_CKGEN);
+-	preg(CM_IDLEST_DSP);
+-	preg(CM_IDLEST_MDM);
+-
+-	preg(RM_RSTST_MPU);
+-	preg(RM_RSTST_GFX);
+-	preg(RM_RSTST_WKUP);
+-	preg(RM_RSTST_DSP);
+-	preg(RM_RSTST_MDM);
+-
+-	preg(PM_WKDEP_MPU);
+-	preg(PM_WKDEP_CORE);
+-	preg(PM_WKDEP_GFX);
+-	preg(PM_WKDEP_DSP);
+-	preg(PM_WKDEP_MDM);
+-
+-	preg(CM_FCLKEN_WKUP);
+-	preg(CM_ICLKEN_WKUP);
+-	preg(CM_IDLEST_WKUP);
+-	preg(CM_AUTOIDLE_WKUP);
+-	preg(CM_CLKSEL_WKUP);
+-
+-	preg(PM_WKEN_WKUP);
+-	preg(PM_WKST_WKUP);
+-}
+-
+-static inline void omap2_pm_save_registers(void)
+-{
+-	/* Save interrupt registers */
+-	OMAP24XX_SAVE(INTC_MIR0);
+-	OMAP24XX_SAVE(INTC_MIR1);
+-	OMAP24XX_SAVE(INTC_MIR2);
+-
+-	/* Save power control registers */
+-	OMAP24XX_SAVE(CM_CLKSTCTRL_MPU);
+-	OMAP24XX_SAVE(CM_CLKSTCTRL_CORE);
+-	OMAP24XX_SAVE(CM_CLKSTCTRL_GFX);
+-	OMAP24XX_SAVE(CM_CLKSTCTRL_DSP);
+-	OMAP24XX_SAVE(CM_CLKSTCTRL_MDM);
+-
+-	/* Save power state registers */
+-	OMAP24XX_SAVE(PM_PWSTCTRL_MPU);
+-	OMAP24XX_SAVE(PM_PWSTCTRL_CORE);
+-	OMAP24XX_SAVE(PM_PWSTCTRL_GFX);
+-	OMAP24XX_SAVE(PM_PWSTCTRL_DSP);
+-	OMAP24XX_SAVE(PM_PWSTCTRL_MDM);
+-
+-	/* Save autoidle registers */
+-	OMAP24XX_SAVE(CM_AUTOIDLE1_CORE);
+-	OMAP24XX_SAVE(CM_AUTOIDLE2_CORE);
+-	OMAP24XX_SAVE(CM_AUTOIDLE3_CORE);
+-	OMAP24XX_SAVE(CM_AUTOIDLE4_CORE);
+-	OMAP24XX_SAVE(CM_AUTOIDLE_WKUP);
+-	OMAP24XX_SAVE(CM_AUTOIDLE_PLL);
+-	OMAP24XX_SAVE(CM_AUTOIDLE_DSP);
+-	OMAP24XX_SAVE(CM_AUTOIDLE_MDM);
+-
+-	/* Save idle state registers */
+-	OMAP24XX_SAVE(CM_IDLEST1_CORE);
+-	OMAP24XX_SAVE(CM_IDLEST2_CORE);
+-	OMAP24XX_SAVE(CM_IDLEST3_CORE);
+-	OMAP24XX_SAVE(CM_IDLEST4_CORE);
+-	OMAP24XX_SAVE(CM_IDLEST_GFX);
+-	OMAP24XX_SAVE(CM_IDLEST_WKUP);
+-	OMAP24XX_SAVE(CM_IDLEST_CKGEN);
+-	OMAP24XX_SAVE(CM_IDLEST_DSP);
+-	OMAP24XX_SAVE(CM_IDLEST_MDM);
+-
+-	/* Save clock registers */
+-	OMAP24XX_SAVE(CM_FCLKEN1_CORE);
+-	OMAP24XX_SAVE(CM_FCLKEN2_CORE);
+-	OMAP24XX_SAVE(CM_ICLKEN1_CORE);
+-	OMAP24XX_SAVE(CM_ICLKEN2_CORE);
+-	OMAP24XX_SAVE(CM_ICLKEN3_CORE);
+-	OMAP24XX_SAVE(CM_ICLKEN4_CORE);
+-}
+-
+-static inline void omap2_pm_restore_registers(void)
+-{
+-	/* Restore clock state registers */
+-	OMAP24XX_RESTORE(CM_CLKSTCTRL_MPU);
+-	OMAP24XX_RESTORE(CM_CLKSTCTRL_CORE);
+-	OMAP24XX_RESTORE(CM_CLKSTCTRL_GFX);
+-	OMAP24XX_RESTORE(CM_CLKSTCTRL_DSP);
+-	OMAP24XX_RESTORE(CM_CLKSTCTRL_MDM);
+-
+-	/* Restore power state registers */
+-	OMAP24XX_RESTORE(PM_PWSTCTRL_MPU);
+-	OMAP24XX_RESTORE(PM_PWSTCTRL_CORE);
+-	OMAP24XX_RESTORE(PM_PWSTCTRL_GFX);
+-	OMAP24XX_RESTORE(PM_PWSTCTRL_DSP);
+-	OMAP24XX_RESTORE(PM_PWSTCTRL_MDM);
+-
+-	/* Restore idle state registers */
+-	OMAP24XX_RESTORE(CM_IDLEST1_CORE);
+-	OMAP24XX_RESTORE(CM_IDLEST2_CORE);
+-	OMAP24XX_RESTORE(CM_IDLEST3_CORE);
+-	OMAP24XX_RESTORE(CM_IDLEST4_CORE);
+-	OMAP24XX_RESTORE(CM_IDLEST_GFX);
+-	OMAP24XX_RESTORE(CM_IDLEST_WKUP);
+-	OMAP24XX_RESTORE(CM_IDLEST_CKGEN);
+-	OMAP24XX_RESTORE(CM_IDLEST_DSP);
+-	OMAP24XX_RESTORE(CM_IDLEST_MDM);
+-
+-	/* Restore autoidle registers */
+-	OMAP24XX_RESTORE(CM_AUTOIDLE1_CORE);
+-	OMAP24XX_RESTORE(CM_AUTOIDLE2_CORE);
+-	OMAP24XX_RESTORE(CM_AUTOIDLE3_CORE);
+-	OMAP24XX_RESTORE(CM_AUTOIDLE4_CORE);
+-	OMAP24XX_RESTORE(CM_AUTOIDLE_WKUP);
+-	OMAP24XX_RESTORE(CM_AUTOIDLE_PLL);
+-	OMAP24XX_RESTORE(CM_AUTOIDLE_DSP);
+-	OMAP24XX_RESTORE(CM_AUTOIDLE_MDM);
+-
+-	/* Restore clock registers */
+-	OMAP24XX_RESTORE(CM_FCLKEN1_CORE);
+-	OMAP24XX_RESTORE(CM_FCLKEN2_CORE);
+-	OMAP24XX_RESTORE(CM_ICLKEN1_CORE);
+-	OMAP24XX_RESTORE(CM_ICLKEN2_CORE);
+-	OMAP24XX_RESTORE(CM_ICLKEN3_CORE);
+-	OMAP24XX_RESTORE(CM_ICLKEN4_CORE);
+-
+-	/* REVISIT: Clear interrupts here */
+-
+-	/* Restore interrupt registers */
+-	OMAP24XX_RESTORE(INTC_MIR0);
+-	OMAP24XX_RESTORE(INTC_MIR1);
+-	OMAP24XX_RESTORE(INTC_MIR2);
+-}
+-
+ static int omap2_pm_suspend(void)
+ {
+-	int processor_type = 0;
+-
+-	/* REVISIT: 0x21 or 0x26? */
+-	if (cpu_is_omap2420())
+-		processor_type = 0x21;
+-
+-	if (!processor_type)
+-		return -ENOTSUPP;
+-
+-	local_irq_disable();
+-	local_fiq_disable();
+-
+-	omap2_pm_save_registers();
+-
+-	/* Disable interrupts except for the wake events */
+-	INTC_MIR_SET0 = 0xffffffff & ~INT0_WAKE_MASK;
+-	INTC_MIR_SET1 = 0xffffffff & ~INT1_WAKE_MASK;
+-	INTC_MIR_SET2 = 0xffffffff & ~INT2_WAKE_MASK;
+-
+-	pmdomain_set_autoidle();
+-
+-	/* Clear old wake-up events */
+-	PM_WKST1_CORE = 0;
+-	PM_WKST2_CORE = 0;
+-	PM_WKST_WKUP = 0;
+-
+-	/* Enable wake-up events */
+-	PM_WKEN1_CORE = (1 << 22) | (1 << 21);	/* UART1 & 2 */
+-	PM_WKEN2_CORE = (1 << 2);		/* UART3 */
+-	PM_WKEN_WKUP = (1 << 2) | (1 << 0);	/* GPIO & GPT1 */
+-
+-	/* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled
+-	 * in the SRAM suspend code */
+-	CM_FCLKEN1_CORE = 0;
+-	CM_FCLKEN2_CORE = 0;
+-	CM_ICLKEN1_CORE = 0;
+-	CM_ICLKEN3_CORE = 0;
+-	CM_ICLKEN4_CORE = 0;
+-
+-	omap2_pm_debug("Status before suspend");
+-
+-	/* Must wait for serial buffers to clear */
+-	mdelay(200);
+-
+-	/* Jump to SRAM suspend code
+-	 * REVISIT: When is this SDRC_DLLB_CTRL?
+-	 */
+-	omap2_sram_suspend(SDRC_DLLA_CTRL, processor_type);
+-
+-	/* Back from sleep */
+-	omap2_pm_restore_registers();
+-
+-	local_fiq_enable();
+-	local_irq_enable();
+-
+ 	return 0;
+ }
+ 
+@@ -357,30 +113,6 @@ static struct platform_suspend_ops omap_pm_ops = {
+ 
+ int __init omap2_pm_init(void)
+ {
+-	printk("Power Management for TI OMAP.\n");
+-
+-	vclk = clk_get(NULL, "virt_prcm_set");
+-	if (IS_ERR(vclk)) {
+-		printk(KERN_ERR "Could not get PM vclk\n");
+-		return -ENODEV;
+-	}
+-
+-	/*
+-	 * We copy the assembler sleep/wakeup routines to SRAM.
+-	 * These routines need to be in SRAM as that's the only
+-	 * memory the MPU can see when it wakes up.
+-	 */
+-	omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+-					 omap24xx_idle_loop_suspend_sz);
+-
+-	omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+-					    omap24xx_cpu_suspend_sz);
+-
+-	suspend_set_ops(&omap_pm_ops);
+-	pm_idle = omap2_pm_idle;
+-
+-	pmdomain_init();
+-
+ 	return 0;
+ }
+ 
+diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
+new file mode 100644
+index 0000000..cacb340
+--- /dev/null
++++ b/arch/arm/mach-omap2/prcm-common.h
+@@ -0,0 +1,317 @@
++#ifndef __ARCH_ASM_MACH_OMAP2_PRCM_COMMON_H
++#define __ARCH_ASM_MACH_OMAP2_PRCM_COMMON_H
++
++/*
++ * OMAP2/3 PRCM base and module definitions
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++
++/* Module offsets from both CM_BASE & PRM_BASE */
++
++/*
++ * Offsets that are the same on 24xx and 34xx
++ *
++ * Technically, in terms of the TRM, OCP_MOD is 34xx only; PLL_MOD is
++ * CCR_MOD on 3430; and GFX_MOD only exists < 3430ES2.
++ */
++#define OCP_MOD						0x000
++#define MPU_MOD						0x100
++#define CORE_MOD					0x200
++#define GFX_MOD						0x300
++#define WKUP_MOD					0x400
++#define PLL_MOD						0x500
++
++
++/* Chip-specific module offsets */
++#define OMAP24XX_DSP_MOD				0x800
++
++#define OMAP2430_MDM_MOD				0xc00
++
++/* IVA2 module is < base on 3430 */
++#define OMAP3430_IVA2_MOD				-0x800
++#define OMAP3430ES2_SGX_MOD				GFX_MOD
++#define OMAP3430_CCR_MOD				PLL_MOD
++#define OMAP3430_DSS_MOD				0x600
++#define OMAP3430_CAM_MOD				0x700
++#define OMAP3430_PER_MOD				0x800
++#define OMAP3430_EMU_MOD				0x900
++#define OMAP3430_GR_MOD					0xa00
++#define OMAP3430_NEON_MOD				0xb00
++#define OMAP3430ES2_USBHOST_MOD				0xc00
++
++
++/* 24XX register bits shared between CM & PRM registers */
++
++/* CM_FCLKEN1_CORE, CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */
++#define OMAP2420_EN_MMC_SHIFT				26
++#define OMAP2420_EN_MMC					(1 << 26)
++#define OMAP24XX_EN_UART2_SHIFT				22
++#define OMAP24XX_EN_UART2				(1 << 22)
++#define OMAP24XX_EN_UART1_SHIFT				21
++#define OMAP24XX_EN_UART1				(1 << 21)
++#define OMAP24XX_EN_MCSPI2_SHIFT			18
++#define OMAP24XX_EN_MCSPI2				(1 << 18)
++#define OMAP24XX_EN_MCSPI1_SHIFT			17
++#define OMAP24XX_EN_MCSPI1				(1 << 17)
++#define OMAP24XX_EN_MCBSP2_SHIFT			16
++#define OMAP24XX_EN_MCBSP2				(1 << 16)
++#define OMAP24XX_EN_MCBSP1_SHIFT			15
++#define OMAP24XX_EN_MCBSP1				(1 << 15)
++#define OMAP24XX_EN_GPT12_SHIFT				14
++#define OMAP24XX_EN_GPT12				(1 << 14)
++#define OMAP24XX_EN_GPT11_SHIFT				13
++#define OMAP24XX_EN_GPT11				(1 << 13)
++#define OMAP24XX_EN_GPT10_SHIFT				12
++#define OMAP24XX_EN_GPT10				(1 << 12)
++#define OMAP24XX_EN_GPT9_SHIFT				11
++#define OMAP24XX_EN_GPT9				(1 << 11)
++#define OMAP24XX_EN_GPT8_SHIFT				10
++#define OMAP24XX_EN_GPT8				(1 << 10)
++#define OMAP24XX_EN_GPT7_SHIFT				9
++#define OMAP24XX_EN_GPT7				(1 << 9)
++#define OMAP24XX_EN_GPT6_SHIFT				8
++#define OMAP24XX_EN_GPT6				(1 << 8)
++#define OMAP24XX_EN_GPT5_SHIFT				7
++#define OMAP24XX_EN_GPT5				(1 << 7)
++#define OMAP24XX_EN_GPT4_SHIFT				6
++#define OMAP24XX_EN_GPT4				(1 << 6)
++#define OMAP24XX_EN_GPT3_SHIFT				5
++#define OMAP24XX_EN_GPT3				(1 << 5)
++#define OMAP24XX_EN_GPT2_SHIFT				4
++#define OMAP24XX_EN_GPT2				(1 << 4)
++#define OMAP2420_EN_VLYNQ_SHIFT				3
++#define OMAP2420_EN_VLYNQ				(1 << 3)
++
++/* CM_FCLKEN2_CORE, CM_ICLKEN2_CORE, PM_WKEN2_CORE shared bits */
++#define OMAP2430_EN_GPIO5_SHIFT				10
++#define OMAP2430_EN_GPIO5				(1 << 10)
++#define OMAP2430_EN_MCSPI3_SHIFT			9
++#define OMAP2430_EN_MCSPI3				(1 << 9)
++#define OMAP2430_EN_MMCHS2_SHIFT			8
++#define OMAP2430_EN_MMCHS2				(1 << 8)
++#define OMAP2430_EN_MMCHS1_SHIFT			7
++#define OMAP2430_EN_MMCHS1				(1 << 7)
++#define OMAP24XX_EN_UART3_SHIFT				2
++#define OMAP24XX_EN_UART3				(1 << 2)
++#define OMAP24XX_EN_USB_SHIFT				0
++#define OMAP24XX_EN_USB					(1 << 0)
++
++/* CM_ICLKEN2_CORE, PM_WKEN2_CORE shared bits */
++#define OMAP2430_EN_MDM_INTC_SHIFT			11
++#define OMAP2430_EN_MDM_INTC				(1 << 11)
++#define OMAP2430_EN_USBHS_SHIFT				6
++#define OMAP2430_EN_USBHS				(1 << 6)
++
++/* CM_IDLEST1_CORE, PM_WKST1_CORE shared bits */
++#define OMAP2420_ST_MMC					(1 << 26)
++#define OMAP24XX_ST_UART2				(1 << 22)
++#define OMAP24XX_ST_UART1				(1 << 21)
++#define OMAP24XX_ST_MCSPI2				(1 << 18)
++#define OMAP24XX_ST_MCSPI1				(1 << 17)
++#define OMAP24XX_ST_GPT12				(1 << 14)
++#define OMAP24XX_ST_GPT11				(1 << 13)
++#define OMAP24XX_ST_GPT10				(1 << 12)
++#define OMAP24XX_ST_GPT9				(1 << 11)
++#define OMAP24XX_ST_GPT8				(1 << 10)
++#define OMAP24XX_ST_GPT7				(1 << 9)
++#define OMAP24XX_ST_GPT6				(1 << 8)
++#define OMAP24XX_ST_GPT5				(1 << 7)
++#define OMAP24XX_ST_GPT4				(1 << 6)
++#define OMAP24XX_ST_GPT3				(1 << 5)
++#define OMAP24XX_ST_GPT2				(1 << 4)
++#define OMAP2420_ST_VLYNQ				(1 << 3)
++
++/* CM_IDLEST2_CORE, PM_WKST2_CORE shared bits */
++#define OMAP2430_ST_MDM_INTC				(1 << 11)
++#define OMAP2430_ST_GPIO5				(1 << 10)
++#define OMAP2430_ST_MCSPI3				(1 << 9)
++#define OMAP2430_ST_MMCHS2				(1 << 8)
++#define OMAP2430_ST_MMCHS1				(1 << 7)
++#define OMAP2430_ST_USBHS				(1 << 6)
++#define OMAP24XX_ST_UART3				(1 << 2)
++#define OMAP24XX_ST_USB					(1 << 0)
++
++/* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
++#define OMAP24XX_EN_GPIOS_SHIFT				2
++#define OMAP24XX_EN_GPIOS				(1 << 2)
++#define OMAP24XX_EN_GPT1_SHIFT				0
++#define OMAP24XX_EN_GPT1				(1 << 0)
++
++/* PM_WKST_WKUP, CM_IDLEST_WKUP shared bits */
++#define OMAP24XX_ST_GPIOS				(1 << 2)
++#define OMAP24XX_ST_GPT1				(1 << 0)
++
++/* CM_IDLEST_MDM and PM_WKST_MDM shared bits */
++#define OMAP2430_ST_MDM					(1 << 0)
++
++
++/* 3430 register bits shared between CM & PRM registers */
++
++/* CM_REVISION, PRM_REVISION shared bits */
++#define OMAP3430_REV_SHIFT				0
++#define OMAP3430_REV_MASK				(0xff << 0)
++
++/* CM_SYSCONFIG, PRM_SYSCONFIG shared bits */
++#define OMAP3430_AUTOIDLE				(1 << 0)
++
++/* CM_FCLKEN1_CORE, CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */
++#define OMAP3430_EN_MMC2				(1 << 25)
++#define OMAP3430_EN_MMC2_SHIFT				25
++#define OMAP3430_EN_MMC1				(1 << 24)
++#define OMAP3430_EN_MMC1_SHIFT				24
++#define OMAP3430_EN_MCSPI4				(1 << 21)
++#define OMAP3430_EN_MCSPI4_SHIFT			21
++#define OMAP3430_EN_MCSPI3				(1 << 20)
++#define OMAP3430_EN_MCSPI3_SHIFT			20
++#define OMAP3430_EN_MCSPI2				(1 << 19)
++#define OMAP3430_EN_MCSPI2_SHIFT			19
++#define OMAP3430_EN_MCSPI1				(1 << 18)
++#define OMAP3430_EN_MCSPI1_SHIFT			18
++#define OMAP3430_EN_I2C3				(1 << 17)
++#define OMAP3430_EN_I2C3_SHIFT				17
++#define OMAP3430_EN_I2C2				(1 << 16)
++#define OMAP3430_EN_I2C2_SHIFT				16
++#define OMAP3430_EN_I2C1				(1 << 15)
++#define OMAP3430_EN_I2C1_SHIFT				15
++#define OMAP3430_EN_UART2				(1 << 14)
++#define OMAP3430_EN_UART2_SHIFT				14
++#define OMAP3430_EN_UART1				(1 << 13)
++#define OMAP3430_EN_UART1_SHIFT				13
++#define OMAP3430_EN_GPT11				(1 << 12)
++#define OMAP3430_EN_GPT11_SHIFT				12
++#define OMAP3430_EN_GPT10				(1 << 11)
++#define OMAP3430_EN_GPT10_SHIFT				11
++#define OMAP3430_EN_MCBSP5				(1 << 10)
++#define OMAP3430_EN_MCBSP5_SHIFT			10
++#define OMAP3430_EN_MCBSP1				(1 << 9)
++#define OMAP3430_EN_MCBSP1_SHIFT			9
++#define OMAP3430_EN_FSHOSTUSB				(1 << 5)
++#define OMAP3430_EN_FSHOSTUSB_SHIFT			5
++#define OMAP3430_EN_D2D					(1 << 3)
++#define OMAP3430_EN_D2D_SHIFT				3
++
++/* CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */
++#define OMAP3430_EN_HSOTGUSB				(1 << 4)
++#define OMAP3430_EN_HSOTGUSB_SHIFT				4
++
++/* PM_WKST1_CORE, CM_IDLEST1_CORE shared bits */
++#define OMAP3430_ST_MMC2				(1 << 25)
++#define OMAP3430_ST_MMC1				(1 << 24)
++#define OMAP3430_ST_MCSPI4				(1 << 21)
++#define OMAP3430_ST_MCSPI3				(1 << 20)
++#define OMAP3430_ST_MCSPI2				(1 << 19)
++#define OMAP3430_ST_MCSPI1				(1 << 18)
++#define OMAP3430_ST_I2C3				(1 << 17)
++#define OMAP3430_ST_I2C2				(1 << 16)
++#define OMAP3430_ST_I2C1				(1 << 15)
++#define OMAP3430_ST_UART2				(1 << 14)
++#define OMAP3430_ST_UART1				(1 << 13)
++#define OMAP3430_ST_GPT11				(1 << 12)
++#define OMAP3430_ST_GPT10				(1 << 11)
++#define OMAP3430_ST_MCBSP5				(1 << 10)
++#define OMAP3430_ST_MCBSP1				(1 << 9)
++#define OMAP3430_ST_FSHOSTUSB				(1 << 5)
++#define OMAP3430_ST_HSOTGUSB				(1 << 4)
++#define OMAP3430_ST_D2D					(1 << 3)
++
++/* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
++#define OMAP3430_EN_GPIO1				(1 << 3)
++#define OMAP3430_EN_GPIO1_SHIFT				3
++#define OMAP3430_EN_GPT1				(1 << 0)
++#define OMAP3430_EN_GPT1_SHIFT				0
++
++/* CM_FCLKEN_WKUP, PM_WKEN_WKUP shared bits */
++#define OMAP3430_EN_SR2					(1 << 7)
++#define OMAP3430_EN_SR2_SHIFT				7
++#define OMAP3430_EN_SR1					(1 << 6)
++#define OMAP3430_EN_SR1_SHIFT				6
++
++/* CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
++#define OMAP3430_EN_GPT12				(1 << 1)
++#define OMAP3430_EN_GPT12_SHIFT				1
++
++/* CM_IDLEST_WKUP, PM_WKST_WKUP shared bits */
++#define OMAP3430_ST_SR2					(1 << 7)
++#define OMAP3430_ST_SR1					(1 << 6)
++#define OMAP3430_ST_GPIO1				(1 << 3)
++#define OMAP3430_ST_GPT12				(1 << 1)
++#define OMAP3430_ST_GPT1				(1 << 0)
++
++/*
++ * CM_SLEEPDEP_GFX, CM_SLEEPDEP_DSS, CM_SLEEPDEP_CAM,
++ * CM_SLEEPDEP_PER, PM_WKDEP_IVA2, PM_WKDEP_GFX,
++ * PM_WKDEP_DSS, PM_WKDEP_CAM, PM_WKDEP_PER, PM_WKDEP_NEON shared bits
++ */
++#define OMAP3430_EN_MPU					(1 << 1)
++#define OMAP3430_EN_MPU_SHIFT				1
++
++/* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER shared bits */
++#define OMAP3430_EN_GPIO6				(1 << 17)
++#define OMAP3430_EN_GPIO6_SHIFT				17
++#define OMAP3430_EN_GPIO5				(1 << 16)
++#define OMAP3430_EN_GPIO5_SHIFT				16
++#define OMAP3430_EN_GPIO4				(1 << 15)
++#define OMAP3430_EN_GPIO4_SHIFT				15
++#define OMAP3430_EN_GPIO3				(1 << 14)
++#define OMAP3430_EN_GPIO3_SHIFT				14
++#define OMAP3430_EN_GPIO2				(1 << 13)
++#define OMAP3430_EN_GPIO2_SHIFT				13
++#define OMAP3430_EN_UART3				(1 << 11)
++#define OMAP3430_EN_UART3_SHIFT				11
++#define OMAP3430_EN_GPT9				(1 << 10)
++#define OMAP3430_EN_GPT9_SHIFT				10
++#define OMAP3430_EN_GPT8				(1 << 9)
++#define OMAP3430_EN_GPT8_SHIFT				9
++#define OMAP3430_EN_GPT7				(1 << 8)
++#define OMAP3430_EN_GPT7_SHIFT				8
++#define OMAP3430_EN_GPT6				(1 << 7)
++#define OMAP3430_EN_GPT6_SHIFT				7
++#define OMAP3430_EN_GPT5				(1 << 6)
++#define OMAP3430_EN_GPT5_SHIFT				6
++#define OMAP3430_EN_GPT4				(1 << 5)
++#define OMAP3430_EN_GPT4_SHIFT				5
++#define OMAP3430_EN_GPT3				(1 << 4)
++#define OMAP3430_EN_GPT3_SHIFT				4
++#define OMAP3430_EN_GPT2				(1 << 3)
++#define OMAP3430_EN_GPT2_SHIFT				3
++
++/* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER, PM_WKST_PER shared bits */
++/* XXX Possible TI documentation bug: should the PM_WKST_PER EN_* bits
++ * be ST_* bits instead? */
++#define OMAP3430_EN_MCBSP4				(1 << 2)
++#define OMAP3430_EN_MCBSP4_SHIFT			2
++#define OMAP3430_EN_MCBSP3				(1 << 1)
++#define OMAP3430_EN_MCBSP3_SHIFT			1
++#define OMAP3430_EN_MCBSP2				(1 << 0)
++#define OMAP3430_EN_MCBSP2_SHIFT			0
++
++/* CM_IDLEST_PER, PM_WKST_PER shared bits */
++#define OMAP3430_ST_GPIO6				(1 << 17)
++#define OMAP3430_ST_GPIO5				(1 << 16)
++#define OMAP3430_ST_GPIO4				(1 << 15)
++#define OMAP3430_ST_GPIO3				(1 << 14)
++#define OMAP3430_ST_GPIO2				(1 << 13)
++#define OMAP3430_ST_UART3				(1 << 11)
++#define OMAP3430_ST_GPT9				(1 << 10)
++#define OMAP3430_ST_GPT8				(1 << 9)
++#define OMAP3430_ST_GPT7				(1 << 8)
++#define OMAP3430_ST_GPT6				(1 << 7)
++#define OMAP3430_ST_GPT5				(1 << 6)
++#define OMAP3430_ST_GPT4				(1 << 5)
++#define OMAP3430_ST_GPT3				(1 << 4)
++#define OMAP3430_ST_GPT2				(1 << 3)
++
++/* CM_SLEEPDEP_PER, PM_WKDEP_IVA2, PM_WKDEP_MPU, PM_WKDEP_PER shared bits */
++#define OMAP3430_EN_CORE				(1 << 0)
++
++#endif
++
+diff --git a/arch/arm/mach-omap2/prcm-regs.h b/arch/arm/mach-omap2/prcm-regs.h
+deleted file mode 100644
+index 5e1c4b5..0000000
+--- a/arch/arm/mach-omap2/prcm-regs.h
++++ /dev/null
+@@ -1,483 +0,0 @@
+-/*
+- * linux/arch/arm/mach-omap2/prcm-regs.h
+- *
+- * OMAP24XX Power Reset and Clock Management (PRCM) registers
+- *
+- * Copyright (C) 2005 Texas Instruments, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#ifndef __ARCH_ARM_MACH_OMAP2_PRCM_H
+-#define __ARCH_ARM_MACH_OMAP2_PRCM_H
+-
+-/* SET_PERFORMANCE_LEVEL PARAMETERS */
+-#define PRCM_HALF_SPEED 1
+-#define PRCM_FULL_SPEED 2
+-
+-#ifndef __ASSEMBLER__
+-
+-#define PRCM_REG32(offset)	__REG32(OMAP24XX_PRCM_BASE + (offset))
+-
+-#define PRCM_REVISION		PRCM_REG32(0x000)
+-#define PRCM_SYSCONFIG		PRCM_REG32(0x010)
+-#define PRCM_IRQSTATUS_MPU	PRCM_REG32(0x018)
+-#define PRCM_IRQENABLE_MPU	PRCM_REG32(0x01C)
+-#define PRCM_VOLTCTRL		PRCM_REG32(0x050)
+-#define PRCM_VOLTST		PRCM_REG32(0x054)
+-#define PRCM_CLKSRC_CTRL	PRCM_REG32(0x060)
+-#define PRCM_CLKOUT_CTRL	PRCM_REG32(0x070)
+-#define PRCM_CLKEMUL_CTRL	PRCM_REG32(0x078)
+-#define PRCM_CLKCFG_CTRL	PRCM_REG32(0x080)
+-#define PRCM_CLKCFG_STATUS	PRCM_REG32(0x084)
+-#define PRCM_VOLTSETUP		PRCM_REG32(0x090)
+-#define PRCM_CLKSSETUP		PRCM_REG32(0x094)
+-#define PRCM_POLCTRL		PRCM_REG32(0x098)
+-
+-/* GENERAL PURPOSE */
+-#define GENERAL_PURPOSE1	PRCM_REG32(0x0B0)
+-#define GENERAL_PURPOSE2	PRCM_REG32(0x0B4)
+-#define GENERAL_PURPOSE3	PRCM_REG32(0x0B8)
+-#define GENERAL_PURPOSE4	PRCM_REG32(0x0BC)
+-#define GENERAL_PURPOSE5	PRCM_REG32(0x0C0)
+-#define GENERAL_PURPOSE6	PRCM_REG32(0x0C4)
+-#define GENERAL_PURPOSE7	PRCM_REG32(0x0C8)
+-#define GENERAL_PURPOSE8	PRCM_REG32(0x0CC)
+-#define GENERAL_PURPOSE9	PRCM_REG32(0x0D0)
+-#define GENERAL_PURPOSE10	PRCM_REG32(0x0D4)
+-#define GENERAL_PURPOSE11	PRCM_REG32(0x0D8)
+-#define GENERAL_PURPOSE12	PRCM_REG32(0x0DC)
+-#define GENERAL_PURPOSE13	PRCM_REG32(0x0E0)
+-#define GENERAL_PURPOSE14	PRCM_REG32(0x0E4)
+-#define GENERAL_PURPOSE15	PRCM_REG32(0x0E8)
+-#define GENERAL_PURPOSE16	PRCM_REG32(0x0EC)
+-#define GENERAL_PURPOSE17	PRCM_REG32(0x0F0)
+-#define GENERAL_PURPOSE18	PRCM_REG32(0x0F4)
+-#define GENERAL_PURPOSE19	PRCM_REG32(0x0F8)
+-#define GENERAL_PURPOSE20	PRCM_REG32(0x0FC)
+-
+-/* MPU */
+-#define CM_CLKSEL_MPU		PRCM_REG32(0x140)
+-#define CM_CLKSTCTRL_MPU	PRCM_REG32(0x148)
+-#define RM_RSTST_MPU		PRCM_REG32(0x158)
+-#define PM_WKDEP_MPU		PRCM_REG32(0x1C8)
+-#define PM_EVGENCTRL_MPU	PRCM_REG32(0x1D4)
+-#define PM_EVEGENONTIM_MPU	PRCM_REG32(0x1D8)
+-#define PM_EVEGENOFFTIM_MPU	PRCM_REG32(0x1DC)
+-#define PM_PWSTCTRL_MPU		PRCM_REG32(0x1E0)
+-#define PM_PWSTST_MPU		PRCM_REG32(0x1E4)
+-
+-/* CORE */
+-#define CM_FCLKEN1_CORE		PRCM_REG32(0x200)
+-#define CM_FCLKEN2_CORE		PRCM_REG32(0x204)
+-#define CM_FCLKEN3_CORE		PRCM_REG32(0x208)
+-#define CM_ICLKEN1_CORE		PRCM_REG32(0x210)
+-#define CM_ICLKEN2_CORE		PRCM_REG32(0x214)
+-#define CM_ICLKEN3_CORE		PRCM_REG32(0x218)
+-#define CM_ICLKEN4_CORE		PRCM_REG32(0x21C)
+-#define CM_IDLEST1_CORE		PRCM_REG32(0x220)
+-#define CM_IDLEST2_CORE		PRCM_REG32(0x224)
+-#define CM_IDLEST3_CORE		PRCM_REG32(0x228)
+-#define CM_IDLEST4_CORE		PRCM_REG32(0x22C)
+-#define CM_AUTOIDLE1_CORE	PRCM_REG32(0x230)
+-#define CM_AUTOIDLE2_CORE	PRCM_REG32(0x234)
+-#define CM_AUTOIDLE3_CORE	PRCM_REG32(0x238)
+-#define CM_AUTOIDLE4_CORE	PRCM_REG32(0x23C)
+-#define CM_CLKSEL1_CORE		PRCM_REG32(0x240)
+-#define CM_CLKSEL2_CORE		PRCM_REG32(0x244)
+-#define CM_CLKSTCTRL_CORE	PRCM_REG32(0x248)
+-#define PM_WKEN1_CORE		PRCM_REG32(0x2A0)
+-#define PM_WKEN2_CORE		PRCM_REG32(0x2A4)
+-#define PM_WKST1_CORE		PRCM_REG32(0x2B0)
+-#define PM_WKST2_CORE		PRCM_REG32(0x2B4)
+-#define PM_WKDEP_CORE		PRCM_REG32(0x2C8)
+-#define PM_PWSTCTRL_CORE	PRCM_REG32(0x2E0)
+-#define PM_PWSTST_CORE		PRCM_REG32(0x2E4)
+-
+-/* GFX */
+-#define CM_FCLKEN_GFX		PRCM_REG32(0x300)
+-#define CM_ICLKEN_GFX		PRCM_REG32(0x310)
+-#define CM_IDLEST_GFX		PRCM_REG32(0x320)
+-#define CM_CLKSEL_GFX		PRCM_REG32(0x340)
+-#define CM_CLKSTCTRL_GFX	PRCM_REG32(0x348)
+-#define RM_RSTCTRL_GFX		PRCM_REG32(0x350)
+-#define RM_RSTST_GFX		PRCM_REG32(0x358)
+-#define PM_WKDEP_GFX		PRCM_REG32(0x3C8)
+-#define PM_PWSTCTRL_GFX		PRCM_REG32(0x3E0)
+-#define PM_PWSTST_GFX		PRCM_REG32(0x3E4)
+-
+-/* WAKE-UP */
+-#define CM_FCLKEN_WKUP		PRCM_REG32(0x400)
+-#define CM_ICLKEN_WKUP		PRCM_REG32(0x410)
+-#define CM_IDLEST_WKUP		PRCM_REG32(0x420)
+-#define CM_AUTOIDLE_WKUP	PRCM_REG32(0x430)
+-#define CM_CLKSEL_WKUP		PRCM_REG32(0x440)
+-#define RM_RSTCTRL_WKUP		PRCM_REG32(0x450)
+-#define RM_RSTTIME_WKUP		PRCM_REG32(0x454)
+-#define RM_RSTST_WKUP		PRCM_REG32(0x458)
+-#define PM_WKEN_WKUP		PRCM_REG32(0x4A0)
+-#define PM_WKST_WKUP		PRCM_REG32(0x4B0)
+-
+-/* CLOCKS */
+-#define CM_CLKEN_PLL		PRCM_REG32(0x500)
+-#define CM_IDLEST_CKGEN		PRCM_REG32(0x520)
+-#define CM_AUTOIDLE_PLL		PRCM_REG32(0x530)
+-#define CM_CLKSEL1_PLL		PRCM_REG32(0x540)
+-#define CM_CLKSEL2_PLL		PRCM_REG32(0x544)
+-
+-/* DSP */
+-#define CM_FCLKEN_DSP		PRCM_REG32(0x800)
+-#define CM_ICLKEN_DSP		PRCM_REG32(0x810)
+-#define CM_IDLEST_DSP		PRCM_REG32(0x820)
+-#define CM_AUTOIDLE_DSP		PRCM_REG32(0x830)
+-#define CM_CLKSEL_DSP		PRCM_REG32(0x840)
+-#define CM_CLKSTCTRL_DSP	PRCM_REG32(0x848)
+-#define RM_RSTCTRL_DSP		PRCM_REG32(0x850)
+-#define RM_RSTST_DSP		PRCM_REG32(0x858)
+-#define PM_WKEN_DSP		PRCM_REG32(0x8A0)
+-#define PM_WKDEP_DSP		PRCM_REG32(0x8C8)
+-#define PM_PWSTCTRL_DSP		PRCM_REG32(0x8E0)
+-#define PM_PWSTST_DSP		PRCM_REG32(0x8E4)
+-#define PRCM_IRQSTATUS_DSP	PRCM_REG32(0x8F0)
+-#define PRCM_IRQENABLE_DSP	PRCM_REG32(0x8F4)
+-
+-/* IVA */
+-#define PRCM_IRQSTATUS_IVA	PRCM_REG32(0x8F8)
+-#define PRCM_IRQENABLE_IVA	PRCM_REG32(0x8FC)
+-
+-/* Modem on 2430 */
+-#define CM_FCLKEN_MDM		PRCM_REG32(0xC00)
+-#define CM_ICLKEN_MDM		PRCM_REG32(0xC10)
+-#define CM_IDLEST_MDM		PRCM_REG32(0xC20)
+-#define CM_AUTOIDLE_MDM		PRCM_REG32(0xC30)
+-#define CM_CLKSEL_MDM		PRCM_REG32(0xC40)
+-#define CM_CLKSTCTRL_MDM	PRCM_REG32(0xC48)
+-#define RM_RSTCTRL_MDM		PRCM_REG32(0xC50)
+-#define RM_RSTST_MDM		PRCM_REG32(0xC58)
+-#define PM_WKEN_MDM		PRCM_REG32(0xCA0)
+-#define PM_WKST_MDM		PRCM_REG32(0xCB0)
+-#define PM_WKDEP_MDM		PRCM_REG32(0xCC8)
+-#define PM_PWSTCTRL_MDM		PRCM_REG32(0xCE0)
+-#define PM_PWSTST_MDM		PRCM_REG32(0xCE4)
+-
+-#define OMAP24XX_L4_IO_BASE	0x48000000
+-
+-#define DISP_BASE		(OMAP24XX_L4_IO_BASE + 0x50000)
+-#define DISP_REG32(offset)	__REG32(DISP_BASE + (offset))
+-
+-#define OMAP24XX_GPMC_BASE	(L3_24XX_BASE + 0xa000)
+-#define GPMC_REG32(offset)	__REG32(OMAP24XX_GPMC_BASE + (offset))
+-
+-/* FIXME: Move these to timer code */
+-#define GPT1_BASE		(0x48028000)
+-#define GPT1_REG32(offset)	__REG32(GPT1_BASE + (offset))
+-
+-/* Misc sysconfig */
+-#define DISPC_SYSCONFIG		DISP_REG32(0x410)
+-#define SPI_BASE		(OMAP24XX_L4_IO_BASE + 0x98000)
+-#define MCSPI1_SYSCONFIG	__REG32(SPI_BASE + 0x10)
+-#define MCSPI2_SYSCONFIG	__REG32(SPI_BASE + 0x2000 + 0x10)
+-#define MCSPI3_SYSCONFIG	__REG32(OMAP24XX_L4_IO_BASE + 0xb8010)
+-
+-#define CAMERA_MMU_SYSCONFIG	__REG32(DISP_BASE + 0x2C10)
+-#define CAMERA_DMA_SYSCONFIG	__REG32(DISP_BASE + 0x282C)
+-#define SYSTEM_DMA_SYSCONFIG	__REG32(DISP_BASE + 0x602C)
+-#define GPMC_SYSCONFIG		GPMC_REG32(0x010)
+-#define MAILBOXES_SYSCONFIG	__REG32(OMAP24XX_L4_IO_BASE + 0x94010)
+-#define UART1_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE + 0x6A054)
+-#define UART2_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE + 0x6C054)
+-#define UART3_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE + 0x6E054)
+-#define SDRC_SYSCONFIG		__REG32(OMAP24XX_SDRC_BASE + 0x10)
+-#define OMAP24XX_SMS_BASE	(L3_24XX_BASE + 0x8000)
+-#define SMS_SYSCONFIG		__REG32(OMAP24XX_SMS_BASE + 0x10)
+-#define SSI_SYSCONFIG		__REG32(DISP_BASE + 0x8010)
+-
+-/* rkw - good cannidates for PM_ to start what nm was trying */
+-#define OMAP24XX_GPT2		(OMAP24XX_L4_IO_BASE + 0x2A000)
+-#define OMAP24XX_GPT3		(OMAP24XX_L4_IO_BASE + 0x78000)
+-#define OMAP24XX_GPT4		(OMAP24XX_L4_IO_BASE + 0x7A000)
+-#define OMAP24XX_GPT5		(OMAP24XX_L4_IO_BASE + 0x7C000)
+-#define OMAP24XX_GPT6		(OMAP24XX_L4_IO_BASE + 0x7E000)
+-#define OMAP24XX_GPT7		(OMAP24XX_L4_IO_BASE + 0x80000)
+-#define OMAP24XX_GPT8		(OMAP24XX_L4_IO_BASE + 0x82000)
+-#define OMAP24XX_GPT9		(OMAP24XX_L4_IO_BASE + 0x84000)
+-#define OMAP24XX_GPT10		(OMAP24XX_L4_IO_BASE + 0x86000)
+-#define OMAP24XX_GPT11		(OMAP24XX_L4_IO_BASE + 0x88000)
+-#define OMAP24XX_GPT12		(OMAP24XX_L4_IO_BASE + 0x8A000)
+-
+-/* FIXME: Move these to timer code */
+-#define GPTIMER1_SYSCONFIG	GPT1_REG32(0x010)
+-#define GPTIMER2_SYSCONFIG	__REG32(OMAP24XX_GPT2 + 0x10)
+-#define GPTIMER3_SYSCONFIG	__REG32(OMAP24XX_GPT3 + 0x10)
+-#define GPTIMER4_SYSCONFIG	__REG32(OMAP24XX_GPT4 + 0x10)
+-#define GPTIMER5_SYSCONFIG	__REG32(OMAP24XX_GPT5 + 0x10)
+-#define GPTIMER6_SYSCONFIG	__REG32(OMAP24XX_GPT6 + 0x10)
+-#define GPTIMER7_SYSCONFIG	__REG32(OMAP24XX_GPT7 + 0x10)
+-#define GPTIMER8_SYSCONFIG	__REG32(OMAP24XX_GPT8 + 0x10)
+-#define GPTIMER9_SYSCONFIG	__REG32(OMAP24XX_GPT9 + 0x10)
+-#define GPTIMER10_SYSCONFIG	__REG32(OMAP24XX_GPT10 + 0x10)
+-#define GPTIMER11_SYSCONFIG	__REG32(OMAP24XX_GPT11 + 0x10)
+-#define GPTIMER12_SYSCONFIG	__REG32(OMAP24XX_GPT12 + 0x10)
+-
+-/* FIXME: Move these to gpio code */
+-#define OMAP24XX_GPIO_BASE	0x48018000
+-#define GPIOX_BASE(X)		(OMAP24XX_GPIO_BASE + (0x2000 * ((X) - 1)))
+-
+-#define GPIO1_SYSCONFIG		__REG32((GPIOX_BASE(1) + 0x10))
+-#define GPIO2_SYSCONFIG		__REG32((GPIOX_BASE(2) + 0x10))
+-#define GPIO3_SYSCONFIG		__REG32((GPIOX_BASE(3) + 0x10))
+-#define GPIO4_SYSCONFIG		__REG32((GPIOX_BASE(4) + 0x10))
+-
+-#if defined(CONFIG_ARCH_OMAP243X)
+-#define GPIO5_SYSCONFIG		__REG32((OMAP24XX_GPIO5_BASE + 0x10))
+-#endif
+-
+-/* GP TIMER 1 */
+-#define GPTIMER1_TISTAT		GPT1_REG32(0x014)
+-#define GPTIMER1_TISR		GPT1_REG32(0x018)
+-#define GPTIMER1_TIER		GPT1_REG32(0x01C)
+-#define GPTIMER1_TWER		GPT1_REG32(0x020)
+-#define GPTIMER1_TCLR		GPT1_REG32(0x024)
+-#define GPTIMER1_TCRR		GPT1_REG32(0x028)
+-#define GPTIMER1_TLDR		GPT1_REG32(0x02C)
+-#define GPTIMER1_TTGR		GPT1_REG32(0x030)
+-#define GPTIMER1_TWPS		GPT1_REG32(0x034)
+-#define GPTIMER1_TMAR		GPT1_REG32(0x038)
+-#define GPTIMER1_TCAR1		GPT1_REG32(0x03C)
+-#define GPTIMER1_TSICR		GPT1_REG32(0x040)
+-#define GPTIMER1_TCAR2		GPT1_REG32(0x044)
+-
+-/* rkw -- base fix up please... */
+-#define GPTIMER3_TISR		__REG32(OMAP24XX_L4_IO_BASE + 0x78018)
+-
+-/* SDRC */
+-#define SDRC_DLLA_CTRL		__REG32(OMAP24XX_SDRC_BASE + 0x060)
+-#define SDRC_DLLA_STATUS	__REG32(OMAP24XX_SDRC_BASE + 0x064)
+-#define SDRC_DLLB_CTRL		__REG32(OMAP24XX_SDRC_BASE + 0x068)
+-#define SDRC_DLLB_STATUS	__REG32(OMAP24XX_SDRC_BASE + 0x06C)
+-#define SDRC_POWER		__REG32(OMAP24XX_SDRC_BASE + 0x070)
+-#define SDRC_MR_0		__REG32(OMAP24XX_SDRC_BASE + 0x084)
+-
+-/* GPIO 1 */
+-#define GPIO1_BASE		GPIOX_BASE(1)
+-#define GPIO1_REG32(offset)	__REG32(GPIO1_BASE + (offset))
+-#define GPIO1_IRQENABLE1	GPIO1_REG32(0x01C)
+-#define GPIO1_IRQSTATUS1	GPIO1_REG32(0x018)
+-#define GPIO1_IRQENABLE2	GPIO1_REG32(0x02C)
+-#define GPIO1_IRQSTATUS2	GPIO1_REG32(0x028)
+-#define GPIO1_WAKEUPENABLE	GPIO1_REG32(0x020)
+-#define GPIO1_RISINGDETECT	GPIO1_REG32(0x048)
+-#define GPIO1_DATAIN		GPIO1_REG32(0x038)
+-#define GPIO1_OE		GPIO1_REG32(0x034)
+-#define GPIO1_DATAOUT		GPIO1_REG32(0x03C)
+-
+-/* GPIO2 */
+-#define GPIO2_BASE		GPIOX_BASE(2)
+-#define GPIO2_REG32(offset)	__REG32(GPIO2_BASE + (offset))
+-#define GPIO2_IRQENABLE1	GPIO2_REG32(0x01C)
+-#define GPIO2_IRQSTATUS1	GPIO2_REG32(0x018)
+-#define GPIO2_IRQENABLE2	GPIO2_REG32(0x02C)
+-#define GPIO2_IRQSTATUS2	GPIO2_REG32(0x028)
+-#define GPIO2_WAKEUPENABLE	GPIO2_REG32(0x020)
+-#define GPIO2_RISINGDETECT	GPIO2_REG32(0x048)
+-#define GPIO2_DATAIN		GPIO2_REG32(0x038)
+-#define GPIO2_OE		GPIO2_REG32(0x034)
+-#define GPIO2_DATAOUT		GPIO2_REG32(0x03C)
+-#define GPIO2_DEBOUNCENABLE	GPIO2_REG32(0x050)
+-#define GPIO2_DEBOUNCINGTIME	GPIO2_REG32(0x054)
+-
+-/* GPIO 3 */
+-#define GPIO3_BASE		GPIOX_BASE(3)
+-#define GPIO3_REG32(offset)	__REG32(GPIO3_BASE + (offset))
+-#define GPIO3_IRQENABLE1	GPIO3_REG32(0x01C)
+-#define GPIO3_IRQSTATUS1	GPIO3_REG32(0x018)
+-#define GPIO3_IRQENABLE2	GPIO3_REG32(0x02C)
+-#define GPIO3_IRQSTATUS2	GPIO3_REG32(0x028)
+-#define GPIO3_WAKEUPENABLE	GPIO3_REG32(0x020)
+-#define GPIO3_RISINGDETECT	GPIO3_REG32(0x048)
+-#define GPIO3_FALLINGDETECT	GPIO3_REG32(0x04C)
+-#define GPIO3_DATAIN		GPIO3_REG32(0x038)
+-#define GPIO3_OE		GPIO3_REG32(0x034)
+-#define GPIO3_DATAOUT		GPIO3_REG32(0x03C)
+-#define GPIO3_DEBOUNCENABLE	GPIO3_REG32(0x050)
+-#define GPIO3_DEBOUNCINGTIME	GPIO3_REG32(0x054)
+-#define GPIO3_DEBOUNCENABLE	GPIO3_REG32(0x050)
+-#define GPIO3_DEBOUNCINGTIME	GPIO3_REG32(0x054)
+-
+-/* GPIO 4 */
+-#define GPIO4_BASE		GPIOX_BASE(4)
+-#define GPIO4_REG32(offset)	__REG32(GPIO4_BASE + (offset))
+-#define GPIO4_IRQENABLE1	GPIO4_REG32(0x01C)
+-#define GPIO4_IRQSTATUS1	GPIO4_REG32(0x018)
+-#define GPIO4_IRQENABLE2	GPIO4_REG32(0x02C)
+-#define GPIO4_IRQSTATUS2	GPIO4_REG32(0x028)
+-#define GPIO4_WAKEUPENABLE	GPIO4_REG32(0x020)
+-#define GPIO4_RISINGDETECT	GPIO4_REG32(0x048)
+-#define GPIO4_FALLINGDETECT	GPIO4_REG32(0x04C)
+-#define GPIO4_DATAIN		GPIO4_REG32(0x038)
+-#define GPIO4_OE		GPIO4_REG32(0x034)
+-#define GPIO4_DATAOUT		GPIO4_REG32(0x03C)
+-#define GPIO4_DEBOUNCENABLE	GPIO4_REG32(0x050)
+-#define GPIO4_DEBOUNCINGTIME	GPIO4_REG32(0x054)
+-
+-#if defined(CONFIG_ARCH_OMAP243X)
+-/* GPIO 5 */
+-#define GPIO5_REG32(offset)	__REG32((OMAP24XX_GPIO5_BASE + (offset)))
+-#define GPIO5_IRQENABLE1	GPIO5_REG32(0x01C)
+-#define GPIO5_IRQSTATUS1	GPIO5_REG32(0x018)
+-#define GPIO5_IRQENABLE2	GPIO5_REG32(0x02C)
+-#define GPIO5_IRQSTATUS2	GPIO5_REG32(0x028)
+-#define GPIO5_WAKEUPENABLE	GPIO5_REG32(0x020)
+-#define GPIO5_RISINGDETECT	GPIO5_REG32(0x048)
+-#define GPIO5_FALLINGDETECT	GPIO5_REG32(0x04C)
+-#define GPIO5_DATAIN		GPIO5_REG32(0x038)
+-#define GPIO5_OE		GPIO5_REG32(0x034)
+-#define GPIO5_DATAOUT		GPIO5_REG32(0x03C)
+-#define GPIO5_DEBOUNCENABLE	GPIO5_REG32(0x050)
+-#define GPIO5_DEBOUNCINGTIME	GPIO5_REG32(0x054)
+-#endif
+-
+-/* IO CONFIG */
+-#define OMAP24XX_CTRL_BASE		(L4_24XX_BASE)
+-#define CONTROL_REG32(offset)		__REG32(OMAP24XX_CTRL_BASE + (offset))
+-
+-#define CONTROL_PADCONF_SPI1_NCS2	CONTROL_REG32(0x104)
+-#define CONTROL_PADCONF_SYS_XTALOUT	CONTROL_REG32(0x134)
+-#define CONTROL_PADCONF_UART1_RX	CONTROL_REG32(0x0C8)
+-#define CONTROL_PADCONF_MCBSP1_DX	CONTROL_REG32(0x10C)
+-#define CONTROL_PADCONF_GPMC_NCS4	CONTROL_REG32(0x090)
+-#define CONTROL_PADCONF_DSS_D5		CONTROL_REG32(0x0B8)
+-#define CONTROL_PADCONF_DSS_D9		CONTROL_REG32(0x0BC)	/* 2420 */
+-#define CONTROL_PADCONF_DSS_D13		CONTROL_REG32(0x0C0)
+-#define CONTROL_PADCONF_DSS_VSYNC	CONTROL_REG32(0x0CC)
+-#define CONTROL_PADCONF_SYS_NIRQW0	CONTROL_REG32(0x0BC)	/* 2430 */
+-#define CONTROL_PADCONF_SSI1_FLAG_TX	CONTROL_REG32(0x108)	/* 2430 */
+-
+-/* CONTROL */
+-#define CONTROL_DEVCONF		CONTROL_REG32(0x274)
+-#define CONTROL_DEVCONF1	CONTROL_REG32(0x2E8)
+-
+-/* INTERRUPT CONTROLLER */
+-#define INTC_BASE		((L4_24XX_BASE) + 0xfe000)
+-#define INTC_REG32(offset)	__REG32(INTC_BASE + (offset))
+-
+-#define INTC1_U_BASE		INTC_REG32(0x000)
+-#define INTC_MIR0		INTC_REG32(0x084)
+-#define INTC_MIR_SET0		INTC_REG32(0x08C)
+-#define INTC_MIR_CLEAR0		INTC_REG32(0x088)
+-#define INTC_ISR_CLEAR0		INTC_REG32(0x094)
+-#define INTC_MIR1		INTC_REG32(0x0A4)
+-#define INTC_MIR_SET1		INTC_REG32(0x0AC)
+-#define INTC_MIR_CLEAR1		INTC_REG32(0x0A8)
+-#define INTC_ISR_CLEAR1		INTC_REG32(0x0B4)
+-#define INTC_MIR2		INTC_REG32(0x0C4)
+-#define INTC_MIR_SET2		INTC_REG32(0x0CC)
+-#define INTC_MIR_CLEAR2		INTC_REG32(0x0C8)
+-#define INTC_ISR_CLEAR2		INTC_REG32(0x0D4)
+-#define INTC_SIR_IRQ		INTC_REG32(0x040)
+-#define INTC_CONTROL		INTC_REG32(0x048)
+-#define INTC_ILR11		INTC_REG32(0x12C)	/* PRCM on MPU PIC */
+-#define INTC_ILR30		INTC_REG32(0x178)
+-#define INTC_ILR31		INTC_REG32(0x17C)
+-#define INTC_ILR32		INTC_REG32(0x180)
+-#define INTC_ILR37		INTC_REG32(0x194)	/* GPIO4 on MPU PIC */
+-#define INTC_SYSCONFIG		INTC_REG32(0x010)	/* GPT1 on MPU PIC */
+-
+-/* RAM FIREWALL */
+-#define RAMFW_BASE		(0x68005000)
+-#define RAMFW_REG32(offset)	__REG32(RAMFW_BASE + (offset))
+-
+-#define RAMFW_REQINFOPERM0	RAMFW_REG32(0x048)
+-#define RAMFW_READPERM0		RAMFW_REG32(0x050)
+-#define RAMFW_WRITEPERM0	RAMFW_REG32(0x058)
+-
+-/* GPMC CS1 FPGA ON USER INTERFACE MODULE */
+-//#define DEBUG_BOARD_LED_REGISTER 0x04000014
+-
+-/* GPMC CS0 */
+-#define GPMC_CONFIG1_0		GPMC_REG32(0x060)
+-#define GPMC_CONFIG2_0		GPMC_REG32(0x064)
+-#define GPMC_CONFIG3_0		GPMC_REG32(0x068)
+-#define GPMC_CONFIG4_0		GPMC_REG32(0x06C)
+-#define GPMC_CONFIG5_0		GPMC_REG32(0x070)
+-#define GPMC_CONFIG6_0		GPMC_REG32(0x074)
+-#define GPMC_CONFIG7_0		GPMC_REG32(0x078)
+-
+-/* GPMC CS1 */
+-#define GPMC_CONFIG1_1		GPMC_REG32(0x090)
+-#define GPMC_CONFIG2_1		GPMC_REG32(0x094)
+-#define GPMC_CONFIG3_1		GPMC_REG32(0x098)
+-#define GPMC_CONFIG4_1		GPMC_REG32(0x09C)
+-#define GPMC_CONFIG5_1		GPMC_REG32(0x0a0)
+-#define GPMC_CONFIG6_1		GPMC_REG32(0x0a4)
+-#define GPMC_CONFIG7_1		GPMC_REG32(0x0a8)
+-
+-/* GPMC CS3 */
+-#define GPMC_CONFIG1_3		GPMC_REG32(0x0F0)
+-#define GPMC_CONFIG2_3		GPMC_REG32(0x0F4)
+-#define GPMC_CONFIG3_3		GPMC_REG32(0x0F8)
+-#define GPMC_CONFIG4_3		GPMC_REG32(0x0FC)
+-#define GPMC_CONFIG5_3		GPMC_REG32(0x100)
+-#define GPMC_CONFIG6_3		GPMC_REG32(0x104)
+-#define GPMC_CONFIG7_3		GPMC_REG32(0x108)
+-
+-/* DSS */
+-#define DSS_CONTROL		DISP_REG32(0x040)
+-#define DISPC_CONTROL		DISP_REG32(0x440)
+-#define DISPC_SYSSTATUS		DISP_REG32(0x414)
+-#define DISPC_IRQSTATUS		DISP_REG32(0x418)
+-#define DISPC_IRQENABLE		DISP_REG32(0x41C)
+-#define DISPC_CONFIG		DISP_REG32(0x444)
+-#define DISPC_DEFAULT_COLOR0	DISP_REG32(0x44C)
+-#define DISPC_DEFAULT_COLOR1	DISP_REG32(0x450)
+-#define DISPC_TRANS_COLOR0	DISP_REG32(0x454)
+-#define DISPC_TRANS_COLOR1	DISP_REG32(0x458)
+-#define DISPC_LINE_NUMBER	DISP_REG32(0x460)
+-#define DISPC_TIMING_H		DISP_REG32(0x464)
+-#define DISPC_TIMING_V		DISP_REG32(0x468)
+-#define DISPC_POL_FREQ		DISP_REG32(0x46C)
+-#define DISPC_DIVISOR		DISP_REG32(0x470)
+-#define DISPC_SIZE_DIG		DISP_REG32(0x478)
+-#define DISPC_SIZE_LCD		DISP_REG32(0x47C)
+-#define DISPC_GFX_BA0		DISP_REG32(0x480)
+-#define DISPC_GFX_BA1		DISP_REG32(0x484)
+-#define DISPC_GFX_POSITION	DISP_REG32(0x488)
+-#define DISPC_GFX_SIZE		DISP_REG32(0x48C)
+-#define DISPC_GFX_ATTRIBUTES	DISP_REG32(0x4A0)
+-#define DISPC_GFX_FIFO_THRESHOLD	DISP_REG32(0x4A4)
+-#define DISPC_GFX_ROW_INC	DISP_REG32(0x4AC)
+-#define DISPC_GFX_PIXEL_INC	DISP_REG32(0x4B0)
+-#define DISPC_GFX_WINDOW_SKIP	DISP_REG32(0x4B4)
+-#define DISPC_GFX_TABLE_BA	DISP_REG32(0x4B8)
+-#define DISPC_DATA_CYCLE1	DISP_REG32(0x5D4)
+-#define DISPC_DATA_CYCLE2	DISP_REG32(0x5D8)
+-#define DISPC_DATA_CYCLE3	DISP_REG32(0x5DC)
+-
+-/* HSUSB Suspend */
+-#define HSUSB_CTRL		__REG8(0x480AC001)
+-#define USBOTG_POWER		__REG32(0x480AC000)
+-
+-/* HS MMC */
+-#define MMCHS1_SYSCONFIG	__REG32(0x4809C010)
+-#define MMCHS2_SYSCONFIG	__REG32(0x480b4010)
+-
+-#endif	/* __ASSEMBLER__ */
+-
+-#endif
+-
+-
+-
+-
+-
+diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
+index 90f5305..b12f423 100644
+--- a/arch/arm/mach-omap2/prcm.c
++++ b/arch/arm/mach-omap2/prcm.c
+@@ -17,19 +17,27 @@
+ #include <linux/init.h>
+ #include <linux/clk.h>
+ 
+-#include "prcm-regs.h"
++#include <asm/io.h>
++
++#include "prm.h"
++#include "prm-regbits-24xx.h"
+ 
+ extern void omap2_clk_prepare_for_reboot(void);
+ 
+ u32 omap_prcm_get_reset_sources(void)
+ {
+-	return RM_RSTST_WKUP & 0x7f;
++	return prm_read_mod_reg(WKUP_MOD, RM_RSTST) & 0x7f;
+ }
+ EXPORT_SYMBOL(omap_prcm_get_reset_sources);
+ 
+ /* Resets clock rates and reboots the system. Only called from system.h */
+ void omap_prcm_arch_reset(char mode)
+ {
++	u32 wkup;
+ 	omap2_clk_prepare_for_reboot();
+-	RM_RSTCTRL_WKUP |= 2;
++
++	if (cpu_is_omap24xx()) {
++		wkup = prm_read_mod_reg(WKUP_MOD, RM_RSTCTRL) | OMAP_RST_DPLL3;
++		prm_write_mod_reg(wkup, WKUP_MOD, RM_RSTCTRL);
++	}
+ }
+diff --git a/arch/arm/mach-omap2/prm-regbits-24xx.h b/arch/arm/mach-omap2/prm-regbits-24xx.h
+new file mode 100644
+index 0000000..c6d17a3
+--- /dev/null
++++ b/arch/arm/mach-omap2/prm-regbits-24xx.h
+@@ -0,0 +1,279 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_24XX_H
++#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_24XX_H
++
++/*
++ * OMAP24XX Power/Reset Management register bits
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "prm.h"
++
++/* Bits shared between registers */
++
++/* PRCM_IRQSTATUS_MPU, PM_IRQSTATUS_DSP, PRCM_IRQSTATUS_IVA shared bits */
++#define OMAP24XX_VOLTTRANS_ST				(1 << 2)
++#define OMAP24XX_WKUP2_ST				(1 << 1)
++#define OMAP24XX_WKUP1_ST				(1 << 0)
++
++/* PRCM_IRQENABLE_MPU, PM_IRQENABLE_DSP, PRCM_IRQENABLE_IVA shared bits */
++#define OMAP24XX_VOLTTRANS_EN				(1 << 2)
++#define OMAP24XX_WKUP2_EN				(1 << 1)
++#define OMAP24XX_WKUP1_EN				(1 << 0)
++
++/* PM_WKDEP_GFX, PM_WKDEP_MPU, PM_WKDEP_DSP, PM_WKDEP_MDM shared bits */
++#define OMAP24XX_EN_MPU					(1 << 1)
++#define OMAP24XX_EN_CORE				(1 << 0)
++
++/*
++ * PM_PWSTCTRL_MPU, PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSP, PM_PWSTCTRL_MDM
++ * shared bits
++ */
++#define OMAP24XX_MEMONSTATE_SHIFT			10
++#define OMAP24XX_MEMONSTATE_MASK			(0x3 << 10)
++#define OMAP24XX_MEMRETSTATE				(1 << 3)
++
++/* PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSP, PM_PWSTCTRL_MDM shared bits */
++#define OMAP24XX_FORCESTATE				(1 << 18)
++
++/*
++ * PM_PWSTST_CORE, PM_PWSTST_GFX, PM_PWSTST_MPU, PM_PWSTST_DSP,
++ * PM_PWSTST_MDM shared bits
++ */
++#define OMAP24XX_CLKACTIVITY				(1 << 19)
++
++/* PM_PWSTST_MPU, PM_PWSTST_CORE, PM_PWSTST_DSP shared bits */
++#define OMAP24XX_LASTSTATEENTERED_SHIFT			4
++#define OMAP24XX_LASTSTATEENTERED_MASK			(0x3 << 4)
++
++/* PM_PWSTST_MPU and PM_PWSTST_DSP shared bits */
++#define OMAP2430_MEMSTATEST_SHIFT			10
++#define OMAP2430_MEMSTATEST_MASK			(0x3 << 10)
++
++/* PM_PWSTST_GFX, PM_PWSTST_DSP, PM_PWSTST_MDM shared bits */
++#define OMAP24XX_POWERSTATEST_SHIFT			0
++#define OMAP24XX_POWERSTATEST_MASK			(0x3 << 0)
++
++
++/* Bits specific to each register */
++
++/* PRCM_REVISION */
++#define OMAP24XX_REV_SHIFT				0
++#define OMAP24XX_REV_MASK				(0xff << 0)
++
++/* PRCM_SYSCONFIG */
++#define OMAP24XX_AUTOIDLE				(1 << 0)
++
++/* PRCM_IRQSTATUS_MPU specific bits */
++#define OMAP2430_DPLL_RECAL_ST				(1 << 6)
++#define OMAP24XX_TRANSITION_ST				(1 << 5)
++#define OMAP24XX_EVGENOFF_ST				(1 << 4)
++#define OMAP24XX_EVGENON_ST				(1 << 3)
++
++/* PRCM_IRQENABLE_MPU specific bits */
++#define OMAP2430_DPLL_RECAL_EN				(1 << 6)
++#define OMAP24XX_TRANSITION_EN				(1 << 5)
++#define OMAP24XX_EVGENOFF_EN				(1 << 4)
++#define OMAP24XX_EVGENON_EN				(1 << 3)
++
++/* PRCM_VOLTCTRL */
++#define OMAP24XX_AUTO_EXTVOLT				(1 << 15)
++#define OMAP24XX_FORCE_EXTVOLT				(1 << 14)
++#define OMAP24XX_SETOFF_LEVEL_SHIFT			12
++#define OMAP24XX_SETOFF_LEVEL_MASK			(0x3 << 12)
++#define OMAP24XX_MEMRETCTRL				(1 << 8)
++#define OMAP24XX_SETRET_LEVEL_SHIFT			6
++#define OMAP24XX_SETRET_LEVEL_MASK			(0x3 << 6)
++#define OMAP24XX_VOLT_LEVEL_SHIFT			0
++#define OMAP24XX_VOLT_LEVEL_MASK			(0x3 << 0)
++
++/* PRCM_VOLTST */
++#define OMAP24XX_ST_VOLTLEVEL_SHIFT			0
++#define OMAP24XX_ST_VOLTLEVEL_MASK			(0x3 << 0)
++
++/* PRCM_CLKSRC_CTRL specific bits */
++
++/* PRCM_CLKOUT_CTRL */
++#define OMAP2420_CLKOUT2_EN_SHIFT			15
++#define OMAP2420_CLKOUT2_EN				(1 << 15)
++#define OMAP2420_CLKOUT2_DIV_SHIFT			11
++#define OMAP2420_CLKOUT2_DIV_MASK			(0x7 << 11)
++#define OMAP2420_CLKOUT2_SOURCE_SHIFT			8
++#define OMAP2420_CLKOUT2_SOURCE_MASK			(0x3 << 8)
++#define OMAP24XX_CLKOUT_EN_SHIFT			7
++#define OMAP24XX_CLKOUT_EN				(1 << 7)
++#define OMAP24XX_CLKOUT_DIV_SHIFT			3
++#define OMAP24XX_CLKOUT_DIV_MASK			(0x7 << 3)
++#define OMAP24XX_CLKOUT_SOURCE_SHIFT			0
++#define OMAP24XX_CLKOUT_SOURCE_MASK			(0x3 << 0)
++
++/* PRCM_CLKEMUL_CTRL */
++#define OMAP24XX_EMULATION_EN_SHIFT			0
++#define OMAP24XX_EMULATION_EN				(1 << 0)
++
++/* PRCM_CLKCFG_CTRL */
++#define OMAP24XX_VALID_CONFIG				(1 << 0)
++
++/* PRCM_CLKCFG_STATUS */
++#define OMAP24XX_CONFIG_STATUS				(1 << 0)
++
++/* PRCM_VOLTSETUP specific bits */
++
++/* PRCM_CLKSSETUP specific bits */
++
++/* PRCM_POLCTRL */
++#define OMAP2420_CLKOUT2_POL				(1 << 10)
++#define OMAP24XX_CLKOUT_POL				(1 << 9)
++#define OMAP24XX_CLKREQ_POL				(1 << 8)
++#define OMAP2430_USE_POWEROK				(1 << 2)
++#define OMAP2430_POWEROK_POL				(1 << 1)
++#define OMAP24XX_EXTVOL_POL				(1 << 0)
++
++/* RM_RSTST_MPU specific bits */
++/* 2430 calls GLOBALWMPU_RST "GLOBALWARM_RST" instead */
++
++/* PM_WKDEP_MPU specific bits */
++#define OMAP2430_PM_WKDEP_MPU_EN_MDM			(1 << 5)
++#define OMAP24XX_PM_WKDEP_MPU_EN_DSP			(1 << 2)
++
++/* PM_EVGENCTRL_MPU specific bits */
++
++/* PM_EVEGENONTIM_MPU specific bits */
++
++/* PM_EVEGENOFFTIM_MPU specific bits */
++
++/* PM_PWSTCTRL_MPU specific bits */
++#define OMAP2430_FORCESTATE				(1 << 18)
++
++/* PM_PWSTST_MPU specific bits */
++/* INTRANSITION, CLKACTIVITY, POWERSTATE, MEMSTATEST are 2430 only */
++
++/* PM_WKEN1_CORE specific bits */
++
++/* PM_WKEN2_CORE specific bits */
++
++/* PM_WKST1_CORE specific bits*/
++
++/* PM_WKST2_CORE specific bits */
++
++/* PM_WKDEP_CORE specific bits*/
++#define OMAP2430_PM_WKDEP_CORE_EN_MDM			(1 << 5)
++#define OMAP24XX_PM_WKDEP_CORE_EN_GFX			(1 << 3)
++#define OMAP24XX_PM_WKDEP_CORE_EN_DSP			(1 << 2)
++
++/* PM_PWSTCTRL_CORE specific bits */
++#define OMAP24XX_MEMORYCHANGE				(1 << 20)
++#define OMAP24XX_MEM3ONSTATE_SHIFT			14
++#define OMAP24XX_MEM3ONSTATE_MASK			(0x3 << 14)
++#define OMAP24XX_MEM2ONSTATE_SHIFT			12
++#define OMAP24XX_MEM2ONSTATE_MASK			(0x3 << 12)
++#define OMAP24XX_MEM1ONSTATE_SHIFT			10
++#define OMAP24XX_MEM1ONSTATE_MASK			(0x3 << 10)
++#define OMAP24XX_MEM3RETSTATE				(1 << 5)
++#define OMAP24XX_MEM2RETSTATE				(1 << 4)
++#define OMAP24XX_MEM1RETSTATE				(1 << 3)
++
++/* PM_PWSTST_CORE specific bits */
++#define OMAP24XX_MEM3STATEST_SHIFT			14
++#define OMAP24XX_MEM3STATEST_MASK			(0x3 << 14)
++#define OMAP24XX_MEM2STATEST_SHIFT			12
++#define OMAP24XX_MEM2STATEST_MASK			(0x3 << 12)
++#define OMAP24XX_MEM1STATEST_SHIFT			10
++#define OMAP24XX_MEM1STATEST_MASK			(0x3 << 10)
++
++/* RM_RSTCTRL_GFX */
++#define OMAP24XX_GFX_RST				(1 << 0)
++
++/* RM_RSTST_GFX specific bits */
++#define OMAP24XX_GFX_SW_RST				(1 << 4)
++
++/* PM_PWSTCTRL_GFX specific bits */
++
++/* PM_WKDEP_GFX specific bits */
++/* 2430 often calls EN_WAKEUP "EN_WKUP" */
++
++/* RM_RSTCTRL_WKUP specific bits */
++
++/* RM_RSTTIME_WKUP specific bits */
++
++/* RM_RSTST_WKUP specific bits */
++/* 2430 calls EXTWMPU_RST "EXTWARM_RST" and GLOBALWMPU_RST "GLOBALWARM_RST" */
++#define OMAP24XX_EXTWMPU_RST				(1 << 6)
++#define OMAP24XX_SECU_WD_RST				(1 << 5)
++#define OMAP24XX_MPU_WD_RST				(1 << 4)
++#define OMAP24XX_SECU_VIOL_RST				(1 << 3)
++
++/* PM_WKEN_WKUP specific bits */
++
++/* PM_WKST_WKUP specific bits */
++
++/* RM_RSTCTRL_DSP */
++#define OMAP2420_RST_IVA				(1 << 8)
++#define OMAP24XX_RST2_DSP				(1 << 1)
++#define OMAP24XX_RST1_DSP				(1 << 0)
++
++/* RM_RSTST_DSP specific bits */
++/* 2430 calls GLOBALWMPU_RST "GLOBALWARM_RST" */
++#define OMAP2420_IVA_SW_RST				(1 << 8)
++#define OMAP24XX_DSP_SW_RST2				(1 << 5)
++#define OMAP24XX_DSP_SW_RST1				(1 << 4)
++
++/* PM_WKDEP_DSP specific bits */
++
++/* PM_PWSTCTRL_DSP specific bits */
++/* 2430 only: MEMONSTATE, MEMRETSTATE */
++#define OMAP2420_MEMIONSTATE_SHIFT			12
++#define OMAP2420_MEMIONSTATE_MASK			(0x3 << 12)
++#define OMAP2420_MEMIRETSTATE				(1 << 4)
++
++/* PM_PWSTST_DSP specific bits */
++/* MEMSTATEST is 2430 only */
++#define OMAP2420_MEMISTATEST_SHIFT			12
++#define OMAP2420_MEMISTATEST_MASK			(0x3 << 12)
++
++/* PRCM_IRQSTATUS_DSP specific bits */
++
++/* PRCM_IRQENABLE_DSP specific bits */
++
++/* RM_RSTCTRL_MDM */
++/* 2430 only */
++#define OMAP2430_PWRON1_MDM				(1 << 1)
++#define OMAP2430_RST1_MDM				(1 << 0)
++
++/* RM_RSTST_MDM specific bits */
++/* 2430 only */
++#define OMAP2430_MDM_SECU_VIOL				(1 << 6)
++#define OMAP2430_MDM_SW_PWRON1				(1 << 5)
++#define OMAP2430_MDM_SW_RST1				(1 << 4)
++
++/* PM_WKEN_MDM */
++/* 2430 only */
++#define OMAP2430_PM_WKEN_MDM_EN_MDM			(1 << 0)
++
++/* PM_WKST_MDM specific bits */
++/* 2430 only */
++
++/* PM_WKDEP_MDM specific bits */
++/* 2430 only */
++
++/* PM_PWSTCTRL_MDM specific bits */
++/* 2430 only */
++#define OMAP2430_KILLDOMAINWKUP				(1 << 19)
++
++/* PM_PWSTST_MDM specific bits */
++/* 2430 only */
++
++/* PRCM_IRQSTATUS_IVA */
++/* 2420 only */
++
++/* PRCM_IRQENABLE_IVA */
++/* 2420 only */
++
++#endif
+diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
+new file mode 100644
+index 0000000..b4686bc
+--- /dev/null
++++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
+@@ -0,0 +1,582 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
++#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
++
++/*
++ * OMAP3430 Power/Reset Management register bits
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "prm.h"
++
++/* Shared register bits */
++
++/* PRM_VC_CMD_VAL_0, PRM_VC_CMD_VAL_1 shared bits */
++#define OMAP3430_ON_SHIFT				24
++#define OMAP3430_ON_MASK				(0xff << 24)
++#define OMAP3430_ONLP_SHIFT				16
++#define OMAP3430_ONLP_MASK				(0xff << 16)
++#define OMAP3430_RET_SHIFT				8
++#define OMAP3430_RET_MASK				(0xff << 8)
++#define OMAP3430_OFF_SHIFT				0
++#define OMAP3430_OFF_MASK				(0xff << 0)
++
++/* PRM_VP1_CONFIG, PRM_VP2_CONFIG shared bits */
++#define OMAP3430_ERROROFFSET_SHIFT			24
++#define OMAP3430_ERROROFFSET_MASK			(0xff << 24)
++#define OMAP3430_ERRORGAIN_SHIFT			16
++#define OMAP3430_ERRORGAIN_MASK				(0xff << 16)
++#define OMAP3430_INITVOLTAGE_SHIFT			8
++#define OMAP3430_INITVOLTAGE_MASK			(0xff << 8)
++#define OMAP3430_TIMEOUTEN				(1 << 3)
++#define OMAP3430_INITVDD				(1 << 2)
++#define OMAP3430_FORCEUPDATE				(1 << 1)
++#define OMAP3430_VPENABLE				(1 << 0)
++
++/* PRM_VP1_VSTEPMIN, PRM_VP2_VSTEPMIN shared bits */
++#define OMAP3430_SMPSWAITTIMEMIN_SHIFT			8
++#define OMAP3430_SMPSWAITTIMEMIN_MASK			(0xffff << 8)
++#define OMAP3430_VSTEPMIN_SHIFT				0
++#define OMAP3430_VSTEPMIN_MASK				(0xff << 0)
++
++/* PRM_VP1_VSTEPMAX, PRM_VP2_VSTEPMAX shared bits */
++#define OMAP3430_SMPSWAITTIMEMAX_SHIFT			8
++#define OMAP3430_SMPSWAITTIMEMAX_MASK			(0xffff << 8)
++#define OMAP3430_VSTEPMAX_SHIFT				0
++#define OMAP3430_VSTEPMAX_MASK				(0xff << 0)
++
++/* PRM_VP1_VLIMITTO, PRM_VP2_VLIMITTO shared bits */
++#define OMAP3430_VDDMAX_SHIFT				24
++#define OMAP3430_VDDMAX_MASK				(0xff << 24)
++#define OMAP3430_VDDMIN_SHIFT				16
++#define OMAP3430_VDDMIN_MASK				(0xff << 16)
++#define OMAP3430_TIMEOUT_SHIFT				0
++#define OMAP3430_TIMEOUT_MASK				(0xffff << 0)
++
++/* PRM_VP1_VOLTAGE, PRM_VP2_VOLTAGE shared bits */
++#define OMAP3430_VPVOLTAGE_SHIFT			0
++#define OMAP3430_VPVOLTAGE_MASK				(0xff << 0)
++
++/* PRM_VP1_STATUS, PRM_VP2_STATUS shared bits */
++#define OMAP3430_VPINIDLE				(1 << 0)
++
++/* PM_WKDEP_IVA2, PM_WKDEP_MPU shared bits */
++#define OMAP3430_EN_PER					(1 << 7)
++
++/* PM_PWSTCTRL_IVA2, PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE shared bits */
++#define OMAP3430_MEMORYCHANGE				(1 << 3)
++
++/* PM_PWSTST_IVA2, PM_PWSTST_CORE shared bits */
++#define OMAP3430_LOGICSTATEST				(1 << 2)
++
++/* PM_PREPWSTST_IVA2, PM_PREPWSTST_CORE shared bits */
++#define OMAP3430_LASTLOGICSTATEENTERED				(1 << 2)
++
++/*
++ * PM_PREPWSTST_IVA2, PM_PREPWSTST_MPU, PM_PREPWSTST_CORE,
++ * PM_PREPWSTST_GFX, PM_PREPWSTST_DSS, PM_PREPWSTST_CAM,
++ * PM_PREPWSTST_PER, PM_PREPWSTST_NEON shared bits
++ */
++#define OMAP3430_LASTPOWERSTATEENTERED_SHIFT			0
++#define OMAP3430_LASTPOWERSTATEENTERED_MASK			(0x3 << 0)
++
++/* PRM_IRQSTATUS_IVA2, PRM_IRQSTATUS_MPU shared bits */
++#define OMAP3430_WKUP_ST				(1 << 0)
++
++/* PRM_IRQENABLE_IVA2, PRM_IRQENABLE_MPU shared bits */
++#define OMAP3430_WKUP_EN					(1 << 0)
++
++/* PM_MPUGRPSEL1_CORE, PM_IVA2GRPSEL1_CORE shared bits */
++#define OMAP3430_GRPSEL_MMC2				(1 << 25)
++#define OMAP3430_GRPSEL_MMC1				(1 << 24)
++#define OMAP3430_GRPSEL_MCSPI4				(1 << 21)
++#define OMAP3430_GRPSEL_MCSPI3				(1 << 20)
++#define OMAP3430_GRPSEL_MCSPI2				(1 << 19)
++#define OMAP3430_GRPSEL_MCSPI1				(1 << 18)
++#define OMAP3430_GRPSEL_I2C3				(1 << 17)
++#define OMAP3430_GRPSEL_I2C2				(1 << 16)
++#define OMAP3430_GRPSEL_I2C1				(1 << 15)
++#define OMAP3430_GRPSEL_UART2				(1 << 14)
++#define OMAP3430_GRPSEL_UART1				(1 << 13)
++#define OMAP3430_GRPSEL_GPT11				(1 << 12)
++#define OMAP3430_GRPSEL_GPT10				(1 << 11)
++#define OMAP3430_GRPSEL_MCBSP5				(1 << 10)
++#define OMAP3430_GRPSEL_MCBSP1				(1 << 9)
++#define OMAP3430_GRPSEL_HSOTGUSB			(1 << 4)
++#define OMAP3430_GRPSEL_D2D				(1 << 3)
++
++/*
++ * PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSS, PM_PWSTCTRL_CAM,
++ * PM_PWSTCTRL_PER shared bits
++ */
++#define OMAP3430_MEMONSTATE_SHIFT			16
++#define OMAP3430_MEMONSTATE_MASK			(0x3 << 16)
++#define OMAP3430_MEMRETSTATE				(1 << 8)
++
++/* PM_MPUGRPSEL_PER, PM_IVA2GRPSEL_PER shared bits */
++#define OMAP3430_GRPSEL_GPIO6				(1 << 17)
++#define OMAP3430_GRPSEL_GPIO5				(1 << 16)
++#define OMAP3430_GRPSEL_GPIO4				(1 << 15)
++#define OMAP3430_GRPSEL_GPIO3				(1 << 14)
++#define OMAP3430_GRPSEL_GPIO2				(1 << 13)
++#define OMAP3430_GRPSEL_UART3				(1 << 11)
++#define OMAP3430_GRPSEL_GPT9				(1 << 10)
++#define OMAP3430_GRPSEL_GPT8				(1 << 9)
++#define OMAP3430_GRPSEL_GPT7				(1 << 8)
++#define OMAP3430_GRPSEL_GPT6				(1 << 7)
++#define OMAP3430_GRPSEL_GPT5				(1 << 6)
++#define OMAP3430_GRPSEL_GPT4				(1 << 5)
++#define OMAP3430_GRPSEL_GPT3				(1 << 4)
++#define OMAP3430_GRPSEL_GPT2				(1 << 3)
++#define OMAP3430_GRPSEL_MCBSP4				(1 << 2)
++#define OMAP3430_GRPSEL_MCBSP3				(1 << 1)
++#define OMAP3430_GRPSEL_MCBSP2				(1 << 0)
++
++/* PM_MPUGRPSEL_WKUP, PM_IVA2GRPSEL_WKUP shared bits */
++#define OMAP3430_GRPSEL_IO				(1 << 8)
++#define OMAP3430_GRPSEL_SR2				(1 << 7)
++#define OMAP3430_GRPSEL_SR1				(1 << 6)
++#define OMAP3430_GRPSEL_GPIO1				(1 << 3)
++#define OMAP3430_GRPSEL_GPT12				(1 << 1)
++#define OMAP3430_GRPSEL_GPT1				(1 << 0)
++
++/* Bits specific to each register */
++
++/* RM_RSTCTRL_IVA2 */
++#define OMAP3430_RST3_IVA2				(1 << 2)
++#define OMAP3430_RST2_IVA2				(1 << 1)
++#define OMAP3430_RST1_IVA2				(1 << 0)
++
++/* RM_RSTST_IVA2 specific bits */
++#define OMAP3430_EMULATION_VSEQ_RST			(1 << 13)
++#define OMAP3430_EMULATION_VHWA_RST			(1 << 12)
++#define OMAP3430_EMULATION_IVA2_RST			(1 << 11)
++#define OMAP3430_IVA2_SW_RST3				(1 << 10)
++#define OMAP3430_IVA2_SW_RST2				(1 << 9)
++#define OMAP3430_IVA2_SW_RST1				(1 << 8)
++
++/* PM_WKDEP_IVA2 specific bits */
++
++/* PM_PWSTCTRL_IVA2 specific bits */
++#define OMAP3430_L2FLATMEMONSTATE_SHIFT			22
++#define OMAP3430_L2FLATMEMONSTATE_MASK			(0x3 << 22)
++#define OMAP3430_SHAREDL2CACHEFLATONSTATE_SHIFT		20
++#define OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK		(0x3 << 20)
++#define OMAP3430_L1FLATMEMONSTATE_SHIFT			18
++#define OMAP3430_L1FLATMEMONSTATE_MASK			(0x3 << 18)
++#define OMAP3430_SHAREDL1CACHEFLATONSTATE_SHIFT		16
++#define OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK		(0x3 << 16)
++#define OMAP3430_L2FLATMEMRETSTATE			(1 << 11)
++#define OMAP3430_SHAREDL2CACHEFLATRETSTATE		(1 << 10)
++#define OMAP3430_L1FLATMEMRETSTATE			(1 << 9)
++#define OMAP3430_SHAREDL1CACHEFLATRETSTATE		(1 << 8)
++
++/* PM_PWSTST_IVA2 specific bits */
++#define OMAP3430_L2FLATMEMSTATEST_SHIFT			10
++#define OMAP3430_L2FLATMEMSTATEST_MASK			(0x3 << 10)
++#define OMAP3430_SHAREDL2CACHEFLATSTATEST_SHIFT		8
++#define OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK		(0x3 << 8)
++#define OMAP3430_L1FLATMEMSTATEST_SHIFT			6
++#define OMAP3430_L1FLATMEMSTATEST_MASK			(0x3 << 6)
++#define OMAP3430_SHAREDL1CACHEFLATSTATEST_SHIFT		4
++#define OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK		(0x3 << 4)
++
++/* PM_PREPWSTST_IVA2 specific bits */
++#define OMAP3430_LASTL2FLATMEMSTATEENTERED_SHIFT		10
++#define OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK			(0x3 << 10)
++#define OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_SHIFT	8
++#define OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK		(0x3 << 8)
++#define OMAP3430_LASTL1FLATMEMSTATEENTERED_SHIFT		6
++#define OMAP3430_LASTL1FLATMEMSTATEENTERED_MASK			(0x3 << 6)
++#define OMAP3430_LASTSHAREDL1CACHEFLATSTATEENTERED_SHIFT	4
++#define OMAP3430_LASTSHAREDL1CACHEFLATSTATEENTERED_MASK		(0x3 << 4)
++
++/* PRM_IRQSTATUS_IVA2 specific bits */
++#define OMAP3430_PRM_IRQSTATUS_IVA2_IVA2_DPLL_ST	(1 << 2)
++#define OMAP3430_FORCEWKUP_ST				(1 << 1)
++
++/* PRM_IRQENABLE_IVA2 specific bits */
++#define OMAP3430_PRM_IRQENABLE_IVA2_IVA2_DPLL_RECAL_EN		(1 << 2)
++#define OMAP3430_FORCEWKUP_EN					(1 << 1)
++
++/* PRM_REVISION specific bits */
++
++/* PRM_SYSCONFIG specific bits */
++
++/* PRM_IRQSTATUS_MPU specific bits */
++#define OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT		25
++#define OMAP3430ES2_SND_PERIPH_DPLL_ST			(1 << 25)
++#define OMAP3430_VC_TIMEOUTERR_ST			(1 << 24)
++#define OMAP3430_VC_RAERR_ST				(1 << 23)
++#define OMAP3430_VC_SAERR_ST				(1 << 22)
++#define OMAP3430_VP2_TRANXDONE_ST			(1 << 21)
++#define OMAP3430_VP2_EQVALUE_ST				(1 << 20)
++#define OMAP3430_VP2_NOSMPSACK_ST			(1 << 19)
++#define OMAP3430_VP2_MAXVDD_ST				(1 << 18)
++#define OMAP3430_VP2_MINVDD_ST				(1 << 17)
++#define OMAP3430_VP2_OPPCHANGEDONE_ST			(1 << 16)
++#define OMAP3430_VP1_TRANXDONE_ST			(1 << 15)
++#define OMAP3430_VP1_EQVALUE_ST				(1 << 14)
++#define OMAP3430_VP1_NOSMPSACK_ST			(1 << 13)
++#define OMAP3430_VP1_MAXVDD_ST				(1 << 12)
++#define OMAP3430_VP1_MINVDD_ST				(1 << 11)
++#define OMAP3430_VP1_OPPCHANGEDONE_ST			(1 << 10)
++#define OMAP3430_IO_ST					(1 << 9)
++#define OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST		(1 << 8)
++#define OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT	8
++#define OMAP3430_MPU_DPLL_ST				(1 << 7)
++#define OMAP3430_MPU_DPLL_ST_SHIFT			7
++#define OMAP3430_PERIPH_DPLL_ST				(1 << 6)
++#define OMAP3430_PERIPH_DPLL_ST_SHIFT			6
++#define OMAP3430_CORE_DPLL_ST				(1 << 5)
++#define OMAP3430_CORE_DPLL_ST_SHIFT			5
++#define OMAP3430_TRANSITION_ST				(1 << 4)
++#define OMAP3430_EVGENOFF_ST				(1 << 3)
++#define OMAP3430_EVGENON_ST				(1 << 2)
++#define OMAP3430_FS_USB_WKUP_ST				(1 << 1)
++
++/* PRM_IRQENABLE_MPU specific bits */
++#define OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT		25
++#define OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN			(1 << 25)
++#define OMAP3430_VC_TIMEOUTERR_EN				(1 << 24)
++#define OMAP3430_VC_RAERR_EN					(1 << 23)
++#define OMAP3430_VC_SAERR_EN					(1 << 22)
++#define OMAP3430_VP2_TRANXDONE_EN				(1 << 21)
++#define OMAP3430_VP2_EQVALUE_EN					(1 << 20)
++#define OMAP3430_VP2_NOSMPSACK_EN				(1 << 19)
++#define OMAP3430_VP2_MAXVDD_EN					(1 << 18)
++#define OMAP3430_VP2_MINVDD_EN					(1 << 17)
++#define OMAP3430_VP2_OPPCHANGEDONE_EN				(1 << 16)
++#define OMAP3430_VP1_TRANXDONE_EN				(1 << 15)
++#define OMAP3430_VP1_EQVALUE_EN					(1 << 14)
++#define OMAP3430_VP1_NOSMPSACK_EN				(1 << 13)
++#define OMAP3430_VP1_MAXVDD_EN					(1 << 12)
++#define OMAP3430_VP1_MINVDD_EN					(1 << 11)
++#define OMAP3430_VP1_OPPCHANGEDONE_EN				(1 << 10)
++#define OMAP3430_IO_EN						(1 << 9)
++#define OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN		(1 << 8)
++#define OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT	8
++#define OMAP3430_MPU_DPLL_RECAL_EN				(1 << 7)
++#define OMAP3430_MPU_DPLL_RECAL_EN_SHIFT			7
++#define OMAP3430_PERIPH_DPLL_RECAL_EN				(1 << 6)
++#define OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT			6
++#define OMAP3430_CORE_DPLL_RECAL_EN				(1 << 5)
++#define OMAP3430_CORE_DPLL_RECAL_EN_SHIFT			5
++#define OMAP3430_TRANSITION_EN					(1 << 4)
++#define OMAP3430_EVGENOFF_EN					(1 << 3)
++#define OMAP3430_EVGENON_EN					(1 << 2)
++#define OMAP3430_FS_USB_WKUP_EN					(1 << 1)
++
++/* RM_RSTST_MPU specific bits */
++#define OMAP3430_EMULATION_MPU_RST			(1 << 11)
++
++/* PM_WKDEP_MPU specific bits */
++#define OMAP3430_PM_WKDEP_MPU_EN_DSS			(1 << 5)
++#define OMAP3430_PM_WKDEP_MPU_EN_IVA2			(1 << 2)
++
++/* PM_EVGENCTRL_MPU */
++#define OMAP3430_OFFLOADMODE_SHIFT			3
++#define OMAP3430_OFFLOADMODE_MASK			(0x3 << 3)
++#define OMAP3430_ONLOADMODE_SHIFT			1
++#define OMAP3430_ONLOADMODE_MASK			(0x3 << 1)
++#define OMAP3430_ENABLE					(1 << 0)
++
++/* PM_EVGENONTIM_MPU */
++#define OMAP3430_ONTIMEVAL_SHIFT			0
++#define OMAP3430_ONTIMEVAL_MASK				(0xffffffff << 0)
++
++/* PM_EVGENOFFTIM_MPU */
++#define OMAP3430_OFFTIMEVAL_SHIFT			0
++#define OMAP3430_OFFTIMEVAL_MASK			(0xffffffff << 0)
++
++/* PM_PWSTCTRL_MPU specific bits */
++#define OMAP3430_L2CACHEONSTATE_SHIFT			16
++#define OMAP3430_L2CACHEONSTATE_MASK			(0x3 << 16)
++#define OMAP3430_L2CACHERETSTATE			(1 << 8)
++#define OMAP3430_LOGICL1CACHERETSTATE			(1 << 2)
++
++/* PM_PWSTST_MPU specific bits */
++#define OMAP3430_L2CACHESTATEST_SHIFT			6
++#define OMAP3430_L2CACHESTATEST_MASK			(0x3 << 6)
++#define OMAP3430_LOGICL1CACHESTATEST			(1 << 2)
++
++/* PM_PREPWSTST_MPU specific bits */
++#define OMAP3430_LASTL2CACHESTATEENTERED_SHIFT		6
++#define OMAP3430_LASTL2CACHESTATEENTERED_MASK		(0x3 << 6)
++#define OMAP3430_LASTLOGICL1CACHESTATEENTERED		(1 << 2)
++
++/* RM_RSTCTRL_CORE */
++#define OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON		(1 << 1)
++#define OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST			(1 << 0)
++
++/* RM_RSTST_CORE specific bits */
++#define OMAP3430_MODEM_SECURITY_VIOL_RST		(1 << 10)
++#define OMAP3430_RM_RSTST_CORE_MODEM_SW_RSTPWRON	(1 << 9)
++#define OMAP3430_RM_RSTST_CORE_MODEM_SW_RST		(1 << 8)
++
++/* PM_WKEN1_CORE specific bits */
++
++/* PM_MPUGRPSEL1_CORE specific bits */
++#define OMAP3430_GRPSEL_FSHOSTUSB			(1 << 5)
++
++/* PM_IVA2GRPSEL1_CORE specific bits */
++
++/* PM_WKST1_CORE specific bits */
++
++/* PM_PWSTCTRL_CORE specific bits */
++#define OMAP3430_MEM2ONSTATE_SHIFT			18
++#define OMAP3430_MEM2ONSTATE_MASK			(0x3 << 18)
++#define OMAP3430_MEM1ONSTATE_SHIFT			16
++#define OMAP3430_MEM1ONSTATE_MASK			(0x3 << 16)
++#define OMAP3430_MEM2RETSTATE				(1 << 9)
++#define OMAP3430_MEM1RETSTATE				(1 << 8)
++
++/* PM_PWSTST_CORE specific bits */
++#define OMAP3430_MEM2STATEST_SHIFT			6
++#define OMAP3430_MEM2STATEST_MASK			(0x3 << 6)
++#define OMAP3430_MEM1STATEST_SHIFT			4
++#define OMAP3430_MEM1STATEST_MASK			(0x3 << 4)
++
++/* PM_PREPWSTST_CORE specific bits */
++#define OMAP3430_LASTMEM2STATEENTERED_SHIFT		6
++#define OMAP3430_LASTMEM2STATEENTERED_MASK		(0x3 << 6)
++#define OMAP3430_LASTMEM1STATEENTERED_SHIFT		4
++#define OMAP3430_LASTMEM1STATEENTERED_MASK		(0x3 << 4)
++
++/* RM_RSTST_GFX specific bits */
++
++/* PM_WKDEP_GFX specific bits */
++#define OMAP3430_PM_WKDEP_GFX_EN_IVA2			(1 << 2)
++
++/* PM_PWSTCTRL_GFX specific bits */
++
++/* PM_PWSTST_GFX specific bits */
++
++/* PM_PREPWSTST_GFX specific bits */
++
++/* PM_WKEN_WKUP specific bits */
++#define OMAP3430_EN_IO					(1 << 8)
++
++/* PM_MPUGRPSEL_WKUP specific bits */
++
++/* PM_IVA2GRPSEL_WKUP specific bits */
++
++/* PM_WKST_WKUP specific bits */
++#define OMAP3430_ST_IO					(1 << 8)
++
++/* PRM_CLKSEL */
++#define OMAP3430_SYS_CLKIN_SEL_SHIFT			0
++#define OMAP3430_SYS_CLKIN_SEL_MASK			(0x7 << 0)
++
++/* PRM_CLKOUT_CTRL */
++#define OMAP3430_CLKOUT_EN				(1 << 7)
++#define OMAP3430_CLKOUT_EN_SHIFT			7
++
++/* RM_RSTST_DSS specific bits */
++
++/* PM_WKEN_DSS */
++#define OMAP3430_PM_WKEN_DSS_EN_DSS			(1 << 0)
++
++/* PM_WKDEP_DSS specific bits */
++#define OMAP3430_PM_WKDEP_DSS_EN_IVA2			(1 << 2)
++
++/* PM_PWSTCTRL_DSS specific bits */
++
++/* PM_PWSTST_DSS specific bits */
++
++/* PM_PREPWSTST_DSS specific bits */
++
++/* RM_RSTST_CAM specific bits */
++
++/* PM_WKDEP_CAM specific bits */
++#define OMAP3430_PM_WKDEP_CAM_EN_IVA2			(1 << 2)
++
++/* PM_PWSTCTRL_CAM specific bits */
++
++/* PM_PWSTST_CAM specific bits */
++
++/* PM_PREPWSTST_CAM specific bits */
++
++/* PM_PWSTCTRL_USBHOST specific bits */
++#define OMAP3430ES2_SAVEANDRESTORE_SHIFT		(1 << 4)
++
++/* RM_RSTST_PER specific bits */
++
++/* PM_WKEN_PER specific bits */
++
++/* PM_MPUGRPSEL_PER specific bits */
++
++/* PM_IVA2GRPSEL_PER specific bits */
++
++/* PM_WKST_PER specific bits */
++
++/* PM_WKDEP_PER specific bits */
++#define OMAP3430_PM_WKDEP_PER_EN_IVA2			(1 << 2)
++
++/* PM_PWSTCTRL_PER specific bits */
++
++/* PM_PWSTST_PER specific bits */
++
++/* PM_PREPWSTST_PER specific bits */
++
++/* RM_RSTST_EMU specific bits */
++
++/* PM_PWSTST_EMU specific bits */
++
++/* PRM_VC_SMPS_SA */
++#define OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT		16
++#define OMAP3430_PRM_VC_SMPS_SA_SA1_MASK		(0x7f << 16)
++#define OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT		0
++#define OMAP3430_PRM_VC_SMPS_SA_SA0_MASK		(0x7f << 0)
++
++/* PRM_VC_SMPS_VOL_RA */
++#define OMAP3430_VOLRA1_SHIFT				16
++#define OMAP3430_VOLRA1_MASK				(0xff << 16)
++#define OMAP3430_VOLRA0_SHIFT				0
++#define OMAP3430_VOLRA0_MASK				(0xff << 0)
++
++/* PRM_VC_SMPS_CMD_RA */
++#define OMAP3430_CMDRA1_SHIFT				16
++#define OMAP3430_CMDRA1_MASK				(0xff << 16)
++#define OMAP3430_CMDRA0_SHIFT				0
++#define OMAP3430_CMDRA0_MASK				(0xff << 0)
++
++/* PRM_VC_CMD_VAL_0 specific bits */
++
++/* PRM_VC_CMD_VAL_1 specific bits */
++
++/* PRM_VC_CH_CONF */
++#define OMAP3430_CMD1					(1 << 20)
++#define OMAP3430_RACEN1					(1 << 19)
++#define OMAP3430_RAC1					(1 << 18)
++#define OMAP3430_RAV1					(1 << 17)
++#define OMAP3430_PRM_VC_CH_CONF_SA1			(1 << 16)
++#define OMAP3430_CMD0					(1 << 4)
++#define OMAP3430_RACEN0					(1 << 3)
++#define OMAP3430_RAC0					(1 << 2)
++#define OMAP3430_RAV0					(1 << 1)
++#define OMAP3430_PRM_VC_CH_CONF_SA0			(1 << 0)
++
++/* PRM_VC_I2C_CFG */
++#define OMAP3430_HSMASTER				(1 << 5)
++#define OMAP3430_SREN					(1 << 4)
++#define OMAP3430_HSEN					(1 << 3)
++#define OMAP3430_MCODE_SHIFT				0
++#define OMAP3430_MCODE_MASK				(0x7 << 0)
++
++/* PRM_VC_BYPASS_VAL */
++#define OMAP3430_VALID					(1 << 24)
++#define OMAP3430_DATA_SHIFT				16
++#define OMAP3430_DATA_MASK				(0xff << 16)
++#define OMAP3430_REGADDR_SHIFT				8
++#define OMAP3430_REGADDR_MASK				(0xff << 8)
++#define OMAP3430_SLAVEADDR_SHIFT			0
++#define OMAP3430_SLAVEADDR_MASK				(0x7f << 0)
++
++/* PRM_RSTCTRL */
++#define OMAP3430_RST_DPLL3				(1 << 2)
++#define OMAP3430_RST_GS					(1 << 1)
++
++/* PRM_RSTTIME */
++#define OMAP3430_RSTTIME2_SHIFT				8
++#define OMAP3430_RSTTIME2_MASK				(0x1f << 8)
++#define OMAP3430_RSTTIME1_SHIFT				0
++#define OMAP3430_RSTTIME1_MASK				(0xff << 0)
++
++/* PRM_RSTST */
++#define OMAP3430_ICECRUSHER_RST				(1 << 10)
++#define OMAP3430_ICEPICK_RST				(1 << 9)
++#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST		(1 << 8)
++#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST		(1 << 7)
++#define OMAP3430_EXTERNAL_WARM_RST			(1 << 6)
++#define OMAP3430_SECURE_WD_RST				(1 << 5)
++#define OMAP3430_MPU_WD_RST				(1 << 4)
++#define OMAP3430_SECURITY_VIOL_RST			(1 << 3)
++#define OMAP3430_GLOBAL_SW_RST				(1 << 1)
++#define OMAP3430_GLOBAL_COLD_RST			(1 << 0)
++
++/* PRM_VOLTCTRL */
++#define OMAP3430_SEL_VMODE				(1 << 4)
++#define OMAP3430_SEL_OFF				(1 << 3)
++#define OMAP3430_AUTO_OFF				(1 << 2)
++#define OMAP3430_AUTO_RET				(1 << 1)
++#define OMAP3430_AUTO_SLEEP				(1 << 0)
++
++/* PRM_SRAM_PCHARGE */
++#define OMAP3430_PCHARGE_TIME_SHIFT			0
++#define OMAP3430_PCHARGE_TIME_MASK			(0xff << 0)
++
++/* PRM_CLKSRC_CTRL */
++#define OMAP3430_SYSCLKDIV_SHIFT			6
++#define OMAP3430_SYSCLKDIV_MASK				(0x3 << 6)
++#define OMAP3430_AUTOEXTCLKMODE_SHIFT			3
++#define OMAP3430_AUTOEXTCLKMODE_MASK			(0x3 << 3)
++#define OMAP3430_SYSCLKSEL_SHIFT			0
++#define OMAP3430_SYSCLKSEL_MASK				(0x3 << 0)
++
++/* PRM_VOLTSETUP1 */
++#define OMAP3430_SETUP_TIME2_SHIFT			16
++#define OMAP3430_SETUP_TIME2_MASK			(0xffff << 16)
++#define OMAP3430_SETUP_TIME1_SHIFT			0
++#define OMAP3430_SETUP_TIME1_MASK			(0xffff << 0)
++
++/* PRM_VOLTOFFSET */
++#define OMAP3430_OFFSET_TIME_SHIFT			0
++#define OMAP3430_OFFSET_TIME_MASK			(0xffff << 0)
++
++/* PRM_CLKSETUP */
++#define OMAP3430_SETUP_TIME_SHIFT			0
++#define OMAP3430_SETUP_TIME_MASK			(0xffff << 0)
++
++/* PRM_POLCTRL */
++#define OMAP3430_OFFMODE_POL				(1 << 3)
++#define OMAP3430_CLKOUT_POL				(1 << 2)
++#define OMAP3430_CLKREQ_POL				(1 << 1)
++#define OMAP3430_EXTVOL_POL				(1 << 0)
++
++/* PRM_VOLTSETUP2 */
++#define OMAP3430_OFFMODESETUPTIME_SHIFT			0
++#define OMAP3430_OFFMODESETUPTIME_MASK			(0xffff << 0)
++
++/* PRM_VP1_CONFIG specific bits */
++
++/* PRM_VP1_VSTEPMIN specific bits */
++
++/* PRM_VP1_VSTEPMAX specific bits */
++
++/* PRM_VP1_VLIMITTO specific bits */
++
++/* PRM_VP1_VOLTAGE specific bits */
++
++/* PRM_VP1_STATUS specific bits */
++
++/* PRM_VP2_CONFIG specific bits */
++
++/* PRM_VP2_VSTEPMIN specific bits */
++
++/* PRM_VP2_VSTEPMAX specific bits */
++
++/* PRM_VP2_VLIMITTO specific bits */
++
++/* PRM_VP2_VOLTAGE specific bits */
++
++/* PRM_VP2_STATUS specific bits */
++
++/* RM_RSTST_NEON specific bits */
++
++/* PM_WKDEP_NEON specific bits */
++
++/* PM_PWSTCTRL_NEON specific bits */
++
++/* PM_PWSTST_NEON specific bits */
++
++/* PM_PREPWSTST_NEON specific bits */
++
++#endif
+diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
+new file mode 100644
+index 0000000..ab7649a
+--- /dev/null
++++ b/arch/arm/mach-omap2/prm.h
+@@ -0,0 +1,316 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_PRM_H
++#define __ARCH_ARM_MACH_OMAP2_PRM_H
++
++/*
++ * OMAP2/3 Power/Reset Management (PRM) register definitions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "prcm-common.h"
++
++#ifndef __ASSEMBLER__
++#define OMAP_PRM_REGADDR(module, reg)					\
++	(void __iomem *)IO_ADDRESS(OMAP2_PRM_BASE + (module) + (reg))
++#else
++#define OMAP2420_PRM_REGADDR(module, reg)				\
++			IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
++#define OMAP2430_PRM_REGADDR(module, reg)				\
++			IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
++#define OMAP34XX_PRM_REGADDR(module, reg)				\
++			IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
++#endif
++
++/*
++ * Architecture-specific global PRM registers
++ * Use prm_{read,write}_reg() with these registers.
++ *
++ * With a few exceptions, these are the register names beginning with
++ * PRCM_* on 24xx, and PRM_* on 34xx.  (The exceptions are the
++ * IRQSTATUS and IRQENABLE bits.)
++ *
++ */
++
++#define OMAP24XX_PRCM_REVISION		OMAP_PRM_REGADDR(OCP_MOD, 0x0000)
++#define OMAP24XX_PRCM_SYSCONFIG		OMAP_PRM_REGADDR(OCP_MOD, 0x0010)
++
++#define OMAP24XX_PRCM_IRQSTATUS_MPU	OMAP_PRM_REGADDR(OCP_MOD, 0x0018)
++#define OMAP24XX_PRCM_IRQENABLE_MPU	OMAP_PRM_REGADDR(OCP_MOD, 0x001c)
++
++#define OMAP24XX_PRCM_VOLTCTRL		OMAP_PRM_REGADDR(OCP_MOD, 0x0050)
++#define OMAP24XX_PRCM_VOLTST		OMAP_PRM_REGADDR(OCP_MOD, 0x0054)
++#define OMAP24XX_PRCM_CLKSRC_CTRL	OMAP_PRM_REGADDR(OCP_MOD, 0x0060)
++#define OMAP24XX_PRCM_CLKOUT_CTRL	OMAP_PRM_REGADDR(OCP_MOD, 0x0070)
++#define OMAP24XX_PRCM_CLKEMUL_CTRL	OMAP_PRM_REGADDR(OCP_MOD, 0x0078)
++#define OMAP24XX_PRCM_CLKCFG_CTRL	OMAP_PRM_REGADDR(OCP_MOD, 0x0080)
++#define OMAP24XX_PRCM_CLKCFG_STATUS	OMAP_PRM_REGADDR(OCP_MOD, 0x0084)
++#define OMAP24XX_PRCM_VOLTSETUP		OMAP_PRM_REGADDR(OCP_MOD, 0x0090)
++#define OMAP24XX_PRCM_CLKSSETUP		OMAP_PRM_REGADDR(OCP_MOD, 0x0094)
++#define OMAP24XX_PRCM_POLCTRL		OMAP_PRM_REGADDR(OCP_MOD, 0x0098)
++
++#define OMAP3430_PRM_REVISION		OMAP_PRM_REGADDR(OCP_MOD, 0x0004)
++#define OMAP3430_PRM_SYSCONFIG		OMAP_PRM_REGADDR(OCP_MOD, 0x0014)
++
++#define OMAP3430_PRM_IRQSTATUS_MPU	OMAP_PRM_REGADDR(OCP_MOD, 0x0018)
++#define OMAP3430_PRM_IRQENABLE_MPU	OMAP_PRM_REGADDR(OCP_MOD, 0x001c)
++
++
++#define OMAP3430_PRM_VC_SMPS_SA		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
++#define OMAP3430_PRM_VC_SMPS_VOL_RA	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
++#define OMAP3430_PRM_VC_SMPS_CMD_RA	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
++#define OMAP3430_PRM_VC_CMD_VAL_0	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
++#define OMAP3430_PRM_VC_CMD_VAL_1	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
++#define OMAP3430_PRM_VC_CH_CONF		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
++#define OMAP3430_PRM_VC_I2C_CFG		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
++#define OMAP3430_PRM_VC_BYPASS_VAL	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
++#define OMAP3430_PRM_RSTCTRL		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
++#define OMAP3430_PRM_RSTTIME		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
++#define OMAP3430_PRM_RSTST		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
++#define OMAP3430_PRM_VOLTCTRL		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
++#define OMAP3430_PRM_SRAM_PCHARGE	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
++#define OMAP3430_PRM_CLKSRC_CTRL	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
++#define OMAP3430_PRM_VOLTSETUP1		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
++#define OMAP3430_PRM_VOLTOFFSET		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
++#define OMAP3430_PRM_CLKSETUP		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
++#define OMAP3430_PRM_POLCTRL		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
++#define OMAP3430_PRM_VOLTSETUP2		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
++#define OMAP3430_PRM_VP1_CONFIG		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
++#define OMAP3430_PRM_VP1_VSTEPMIN	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
++#define OMAP3430_PRM_VP1_VSTEPMAX	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
++#define OMAP3430_PRM_VP1_VLIMITTO	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
++#define OMAP3430_PRM_VP1_VOLTAGE	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
++#define OMAP3430_PRM_VP1_STATUS		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
++#define OMAP3430_PRM_VP2_CONFIG		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
++#define OMAP3430_PRM_VP2_VSTEPMIN	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
++#define OMAP3430_PRM_VP2_VSTEPMAX	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
++#define OMAP3430_PRM_VP2_VLIMITTO	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
++#define OMAP3430_PRM_VP2_VOLTAGE	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
++#define OMAP3430_PRM_VP2_STATUS		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
++
++#define OMAP3430_PRM_CLKSEL		OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
++#define OMAP3430_PRM_CLKOUT_CTRL	OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
++
++/*
++ * Module specific PRM registers from PRM_BASE + domain offset
++ *
++ * Use prm_{read,write}_mod_reg() with these registers.
++ *
++ * With a few exceptions, these are the register names beginning with
++ * {PM,RM}_* on both architectures.  (The exceptions are the IRQSTATUS
++ * and IRQENABLE bits.)
++ *
++ */
++
++/* Registers appearing on both 24xx and 34xx */
++
++#define RM_RSTCTRL					0x0050
++#define RM_RSTTIME					0x0054
++#define RM_RSTST					0x0058
++
++#define PM_WKEN						0x00a0
++#define PM_WKEN1					PM_WKEN
++#define PM_WKST						0x00b0
++#define PM_WKST1					PM_WKST
++#define PM_WKDEP					0x00c8
++#define PM_EVGENCTRL					0x00d4
++#define PM_EVGENONTIM					0x00d8
++#define PM_EVGENOFFTIM					0x00dc
++#define PM_PWSTCTRL					0x00e0
++#define PM_PWSTST					0x00e4
++
++#define OMAP3430_PM_MPUGRPSEL				0x00a4
++#define OMAP3430_PM_MPUGRPSEL1				OMAP3430_PM_MPUGRPSEL
++
++#define OMAP3430_PM_IVAGRPSEL				0x00a8
++#define OMAP3430_PM_IVAGRPSEL1				OMAP3430_PM_IVAGRPSEL
++
++#define OMAP3430_PM_PREPWSTST				0x00e8
++
++#define OMAP3430_PRM_IRQSTATUS_IVA2			0x00f8
++#define OMAP3430_PRM_IRQENABLE_IVA2			0x00fc
++
++
++/* Architecture-specific registers */
++
++#define OMAP24XX_PM_WKEN2				0x00a4
++#define OMAP24XX_PM_WKST2				0x00b4
++
++#define OMAP24XX_PRCM_IRQSTATUS_DSP			0x00f0	/* IVA mod */
++#define OMAP24XX_PRCM_IRQENABLE_DSP			0x00f4	/* IVA mod */
++#define OMAP24XX_PRCM_IRQSTATUS_IVA			0x00f8
++#define OMAP24XX_PRCM_IRQENABLE_IVA			0x00fc
++
++#ifndef __ASSEMBLER__
++
++/* Power/reset management domain register get/set */
++
++static inline void prm_write_mod_reg(u32 val, s16 module, s16 idx)
++{
++	__raw_writel(val, OMAP_PRM_REGADDR(module, idx));
++}
++
++static inline u32 prm_read_mod_reg(s16 module, s16 idx)
++{
++	return __raw_readl(OMAP_PRM_REGADDR(module, idx));
++}
++
++#endif
++
++/*
++ * Bits common to specific registers
++ *
++ * The 3430 register and bit names are generally used,
++ * since they tend to make more sense
++ */
++
++/* PM_EVGENONTIM_MPU */
++/* Named PM_EVEGENONTIM_MPU on the 24XX */
++#define OMAP_ONTIMEVAL_SHIFT				0
++#define OMAP_ONTIMEVAL_MASK				(0xffffffff << 0)
++
++/* PM_EVGENOFFTIM_MPU */
++/* Named PM_EVEGENOFFTIM_MPU on the 24XX */
++#define OMAP_OFFTIMEVAL_SHIFT				0
++#define OMAP_OFFTIMEVAL_MASK				(0xffffffff << 0)
++
++/* PRM_CLKSETUP and PRCM_VOLTSETUP */
++/* Named PRCM_CLKSSETUP on the 24XX */
++#define OMAP_SETUP_TIME_SHIFT				0
++#define OMAP_SETUP_TIME_MASK				(0xffff << 0)
++
++/* PRM_CLKSRC_CTRL */
++/* Named PRCM_CLKSRC_CTRL on the 24XX */
++#define OMAP_SYSCLKDIV_SHIFT				6
++#define OMAP_SYSCLKDIV_MASK				(0x3 << 6)
++#define OMAP_AUTOEXTCLKMODE_SHIFT			3
++#define OMAP_AUTOEXTCLKMODE_MASK			(0x3 << 3)
++#define OMAP_SYSCLKSEL_SHIFT				0
++#define OMAP_SYSCLKSEL_MASK				(0x3 << 0)
++
++/* PM_EVGENCTRL_MPU */
++#define OMAP_OFFLOADMODE_SHIFT				3
++#define OMAP_OFFLOADMODE_MASK				(0x3 << 3)
++#define OMAP_ONLOADMODE_SHIFT				1
++#define OMAP_ONLOADMODE_MASK				(0x3 << 1)
++#define OMAP_ENABLE					(1 << 0)
++
++/* PRM_RSTTIME */
++/* Named RM_RSTTIME_WKUP on the 24xx */
++#define OMAP_RSTTIME2_SHIFT				8
++#define OMAP_RSTTIME2_MASK				(0x1f << 8)
++#define OMAP_RSTTIME1_SHIFT				0
++#define OMAP_RSTTIME1_MASK				(0xff << 0)
++
++
++/* PRM_RSTCTRL */
++/* Named RM_RSTCTRL_WKUP on the 24xx */
++/* 2420 calls RST_DPLL3 'RST_DPLL' */
++#define OMAP_RST_DPLL3					(1 << 2)
++#define OMAP_RST_GS					(1 << 1)
++
++
++/*
++ * Bits common to module-shared registers
++ *
++ * Not all registers of a particular type support all of these bits -
++ * check TRM if you are unsure
++ */
++
++/*
++ * 24XX: PM_PWSTST_CORE, PM_PWSTST_GFX, PM_PWSTST_MPU, PM_PWSTST_DSP
++ *
++ * 2430: PM_PWSTST_MDM
++ *
++ * 3430: PM_PWSTST_IVA2, PM_PWSTST_MPU, PM_PWSTST_CORE, PM_PWSTST_GFX,
++ *	 PM_PWSTST_DSS, PM_PWSTST_CAM, PM_PWSTST_PER, PM_PWSTST_EMU,
++ *	 PM_PWSTST_NEON
++ */
++#define OMAP_INTRANSITION				(1 << 20)
++
++
++/*
++ * 24XX: PM_PWSTST_GFX, PM_PWSTST_DSP
++ *
++ * 2430: PM_PWSTST_MDM
++ *
++ * 3430: PM_PWSTST_IVA2, PM_PWSTST_MPU, PM_PWSTST_CORE, PM_PWSTST_GFX,
++ *	 PM_PWSTST_DSS, PM_PWSTST_CAM, PM_PWSTST_PER, PM_PWSTST_EMU,
++ *	 PM_PWSTST_NEON
++ */
++#define OMAP_POWERSTATEST_SHIFT				0
++#define OMAP_POWERSTATEST_MASK				(0x3 << 0)
++
++/*
++ * 24XX: RM_RSTST_MPU and RM_RSTST_DSP - on 24XX, 'COREDOMAINWKUP_RST' is
++ *	 called 'COREWKUP_RST'
++ *
++ * 3430: RM_RSTST_IVA2, RM_RSTST_MPU, RM_RSTST_GFX, RM_RSTST_DSS,
++ *	 RM_RSTST_CAM, RM_RSTST_PER, RM_RSTST_NEON
++ */
++#define OMAP_COREDOMAINWKUP_RST				(1 << 3)
++
++/*
++ * 24XX: RM_RSTST_MPU, RM_RSTST_GFX, RM_RSTST_DSP
++ *
++ * 2430: RM_RSTST_MDM
++ *
++ * 3430: RM_RSTST_CORE, RM_RSTST_EMU
++ */
++#define OMAP_DOMAINWKUP_RST				(1 << 2)
++
++/*
++ * 24XX: RM_RSTST_MPU, RM_RSTST_WKUP, RM_RSTST_DSP
++ *	 On 24XX, 'GLOBALWARM_RST' is called 'GLOBALWMPU_RST'.
++ *
++ * 2430: RM_RSTST_MDM
++ *
++ * 3430: RM_RSTST_CORE, RM_RSTST_EMU
++ */
++#define OMAP_GLOBALWARM_RST				(1 << 1)
++#define OMAP_GLOBALCOLD_RST				(1 << 0)
++
++/*
++ * 24XX: PM_WKDEP_GFX, PM_WKDEP_MPU, PM_WKDEP_CORE, PM_WKDEP_DSP
++ *	 2420 TRM sometimes uses "EN_WAKEUP" instead of "EN_WKUP"
++ *
++ * 2430: PM_WKDEP_MDM
++ *
++ * 3430: PM_WKDEP_IVA2, PM_WKDEP_GFX, PM_WKDEP_DSS, PM_WKDEP_CAM,
++ *	 PM_WKDEP_PER
++ */
++#define OMAP_EN_WKUP					(1 << 4)
++
++/*
++ * 24XX: PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
++ *	 PM_PWSTCTRL_DSP
++ *
++ * 2430: PM_PWSTCTRL_MDM
++ *
++ * 3430: PM_PWSTCTRL_IVA2, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
++ *	 PM_PWSTCTRL_DSS, PM_PWSTCTRL_CAM, PM_PWSTCTRL_PER,
++ *	 PM_PWSTCTRL_NEON
++ */
++#define OMAP_LOGICRETSTATE				(1 << 2)
++
++/*
++ * 24XX: PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
++ *       PM_PWSTCTRL_DSP, PM_PWSTST_MPU
++ *
++ * 2430: PM_PWSTCTRL_MDM shared bits
++ *
++ * 3430: PM_PWSTCTRL_IVA2, PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE,
++ *	 PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSS, PM_PWSTCTRL_CAM, PM_PWSTCTRL_PER,
++ *	 PM_PWSTCTRL_NEON shared bits
++ */
++#define OMAP_POWERSTATE_SHIFT				0
++#define OMAP_POWERSTATE_MASK				(0x3 << 0)
++
++
++#endif
+diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h
+new file mode 100644
+index 0000000..d7f23bc
+--- /dev/null
++++ b/arch/arm/mach-omap2/sdrc.h
+@@ -0,0 +1,58 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_SDRC_H
++#define __ARCH_ARM_MACH_OMAP2_SDRC_H
++
++/*
++ * OMAP2 SDRC register definitions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#undef DEBUG
++
++#include <asm/arch/sdrc.h>
++
++#ifndef __ASSEMBLER__
++extern unsigned long omap2_sdrc_base;
++extern unsigned long omap2_sms_base;
++
++#define OMAP_SDRC_REGADDR(reg)						\
++		(void __iomem *)IO_ADDRESS(omap2_sdrc_base + (reg))
++#define OMAP_SMS_REGADDR(reg)						\
++		(void __iomem *)IO_ADDRESS(omap2_sms_base + (reg))
++
++/* SDRC global register get/set */
++
++static inline void sdrc_write_reg(u32 val, u16 reg)
++{
++	__raw_writel(val, OMAP_SDRC_REGADDR(reg));
++}
++
++static inline u32 sdrc_read_reg(u16 reg)
++{
++	return __raw_readl(OMAP_SDRC_REGADDR(reg));
++}
++
++/* SMS global register get/set */
++
++static inline void sms_write_reg(u32 val, u16 reg)
++{
++	__raw_writel(val, OMAP_SMS_REGADDR(reg));
++}
++
++static inline u32 sms_read_reg(u16 reg)
++{
++	return __raw_readl(OMAP_SMS_REGADDR(reg));
++}
++#else
++#define OMAP242X_SDRC_REGADDR(reg)	IO_ADDRESS(OMAP2420_SDRC_BASE + (reg))
++#define OMAP243X_SDRC_REGADDR(reg)	IO_ADDRESS(OMAP243X_SDRC_BASE + (reg))
++#define OMAP34XX_SDRC_REGADDR(reg)	IO_ADDRESS(OMAP343X_SDRC_BASE + (reg))
++#endif	/* __ASSEMBLER__ */
++
++#endif
+diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
+index 16247d5..46ccb9b 100644
+--- a/arch/arm/mach-omap2/sleep.S
++++ b/arch/arm/mach-omap2/sleep.S
+@@ -26,19 +26,10 @@
+ #include <asm/arch/io.h>
+ #include <asm/arch/pm.h>
+ 
+-#define A_32KSYNC_CR_V		IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
+-#define A_PRCM_VOLTCTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
+-#define A_PRCM_CLKCFG_CTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
+-#define A_CM_CLKEN_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
+-#define A_CM_IDLEST_CKGEN_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
+-#define A_CM_CLKSEL1_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
+-#define A_CM_CLKSEL2_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
++#include "sdrc.h"
+ 
+-#define A_SDRC_DLLA_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
+-#define	A_SDRC_POWER_V		IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
+-#define A_SDRC_RFR_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
++/* First address of reserved address space?  apparently valid for OMAP2 & 3 */
+ #define A_SDRC0_V		(0xC0000000)
+-#define A_SDRC_MANUAL_V		IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
+ 
+ 	.text
+ 
+@@ -126,17 +117,11 @@ loop2:
+ 	ldmfd	sp!, {r0 - r12, pc}	@ restore regs and return
+ 
+ A_SDRC_POWER:
+-	.word A_SDRC_POWER_V
++	.word OMAP242X_SDRC_REGADDR(SDRC_POWER)
+ A_SDRC0:
+ 	.word A_SDRC0_V
+-A_CM_CLKSEL2_PLL_S:
+-	.word A_CM_CLKSEL2_PLL_V
+-A_CM_CLKEN_PLL:
+-	.word A_CM_CLKEN_PLL_V
+ A_SDRC_DLLA_CTRL_S:
+-	.word A_SDRC_DLLA_CTRL_V
+-A_SDRC_MANUAL_S:
+-	.word A_SDRC_MANUAL_V
++	.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
+ 
+ ENTRY(omap24xx_cpu_suspend_sz)
+ 	.word	. - omap24xx_cpu_suspend
+diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S
+index b275766..4a9e491 100644
+--- a/arch/arm/mach-omap2/sram-fn.S
++++ b/arch/arm/mach-omap2/sram-fn.S
+@@ -27,19 +27,11 @@
+ #include <asm/arch/io.h>
+ #include <asm/hardware.h>
+ 
+-#include "prcm-regs.h"
++#include "sdrc.h"
++#include "prm.h"
++#include "cm.h"
+ 
+-#define TIMER_32KSYNCT_CR_V	IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010)
+-
+-#define CM_CLKSEL2_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x544)
+-#define PRCM_VOLTCTRL_V		IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x050)
+-#define PRCM_CLKCFG_CTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x080)
+-#define CM_CLKEN_PLL_V		IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x500)
+-#define CM_IDLEST_CKGEN_V	IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x520)
+-#define CM_CLKSEL1_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x540)
+-
+-#define SDRC_DLLA_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE + 0x060)
+-#define SDRC_RFR_CTRL_V		IO_ADDRESS(OMAP24XX_SDRC_BASE + 0x0a4)
++#define TIMER_32KSYNCT_CR_V	IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010)
+ 
+ 	.text
+ 
+@@ -131,11 +123,11 @@ volt_delay:
+ 
+ /* relative load constants */
+ cm_clksel2_pll:
+-	.word CM_CLKSEL2_PLL_V
++	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
+ sdrc_dlla_ctrl:
+-	.word SDRC_DLLA_CTRL_V
++	.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
+ prcm_voltctrl:
+-	.word PRCM_VOLTCTRL_V
++	.word OMAP2420_PRM_REGADDR(OCP_MOD, 0x50)
+ prcm_mask_val:
+ 	.word 0xFFFF3FFC
+ timer_32ksynct_cr:
+@@ -225,13 +217,13 @@ volt_delay_c:
+ 	mov	pc, lr			@ back to caller
+ 
+ ddr_cm_clksel2_pll:
+-	.word CM_CLKSEL2_PLL_V
++	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
+ ddr_sdrc_dlla_ctrl:
+-	.word SDRC_DLLA_CTRL_V
++	.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
+ ddr_sdrc_rfr_ctrl:
+-	.word SDRC_RFR_CTRL_V
++	.word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
+ ddr_prcm_voltctrl:
+-	.word PRCM_VOLTCTRL_V
++	.word OMAP2420_PRM_REGADDR(OCP_MOD, 0x50)
+ ddr_prcm_mask_val:
+ 	.word 0xFFFF3FFC
+ ddr_timer_32ksynct:
+@@ -316,17 +308,17 @@ wait_dll_lock:
+ 	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+ 
+ set_config:
+-	.word PRCM_CLKCFG_CTRL_V
++	.word OMAP2420_PRM_REGADDR(OCP_MOD, 0x80)
+ pll_ctl:
+-	.word CM_CLKEN_PLL_V
++	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_FCLKEN1)
+ pll_stat:
+-	.word CM_IDLEST_CKGEN_V
++	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_IDLEST1)
+ pll_div:
+-	.word CM_CLKSEL1_PLL_V
++	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL)
+ sdrc_rfr:
+-	.word SDRC_RFR_CTRL_V
++	.word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
+ dlla_ctrl:
+-	.word SDRC_DLLA_CTRL_V
++	.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
+ 
+ ENTRY(sram_set_prcm_sz)
+ 	.word	. - sram_set_prcm
+diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
+index 3234dee..78d05f2 100644
+--- a/arch/arm/mach-omap2/timer-gp.c
++++ b/arch/arm/mach-omap2/timer-gp.c
+@@ -3,6 +3,11 @@
+  *
+  * OMAP2 GP timer support.
+  *
++ * Update to use new clocksource/clockevent layers
++ * Author: Kevin Hilman, MontaVista Software, Inc. <source at mvista.com>
++ * Copyright (C) 2007 MontaVista Software, Inc.
++ *
++ * Original driver:
+  * Copyright (C) 2005 Nokia Corporation
+  * Author: Paul Mundt <paul.mundt at nokia.com>
+  *         Juha Yrjölä <juha.yrjola at nokia.com>
+@@ -25,24 +30,23 @@
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/irq.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
+ 
+ #include <asm/mach/time.h>
+ #include <asm/arch/dmtimer.h>
+ 
+ static struct omap_dm_timer *gptimer;
+-
+-static inline void omap2_gp_timer_start(unsigned long load_val)
+-{
+-	omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val);
+-	omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
+-	omap_dm_timer_start(gptimer);
+-}
++static struct clock_event_device clockevent_gpt;
+ 
+ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
+ {
+-	omap_dm_timer_write_status(gptimer, OMAP_TIMER_INT_OVERFLOW);
+-	timer_tick();
++	struct omap_dm_timer *gpt = (struct omap_dm_timer *)dev_id;
++	struct clock_event_device *evt = &clockevent_gpt;
++
++	omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_OVERFLOW);
+ 
++	evt->event_handler(evt);
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -52,20 +56,138 @@ static struct irqaction omap2_gp_timer_irq = {
+ 	.handler	= omap2_gp_timer_interrupt,
+ };
+ 
+-static void __init omap2_gp_timer_init(void)
++static int omap2_gp_timer_set_next_event(unsigned long cycles,
++					 struct clock_event_device *evt)
+ {
+-	u32 tick_period;
++	omap_dm_timer_set_load(gptimer, 0, 0xffffffff - cycles);
++	omap_dm_timer_start(gptimer);
++
++	return 0;
++}
++
++static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
++				    struct clock_event_device *evt)
++{
++	u32 period;
++
++	omap_dm_timer_stop(gptimer);
++
++	switch (mode) {
++	case CLOCK_EVT_MODE_PERIODIC:
++		period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
++		period -= 1;
++
++		omap_dm_timer_set_load(gptimer, 1, 0xffffffff - period);
++		omap_dm_timer_start(gptimer);
++		break;
++	case CLOCK_EVT_MODE_ONESHOT:
++		break;
++	case CLOCK_EVT_MODE_UNUSED:
++	case CLOCK_EVT_MODE_SHUTDOWN:
++	case CLOCK_EVT_MODE_RESUME:
++		break;
++	}
++}
++
++static struct clock_event_device clockevent_gpt = {
++	.name		= "gp timer",
++	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++	.shift		= 32,
++	.set_next_event	= omap2_gp_timer_set_next_event,
++	.set_mode	= omap2_gp_timer_set_mode,
++};
++
++static void __init omap2_gp_clockevent_init(void)
++{
++	u32 tick_rate;
+ 
+-	omap_dm_timer_init();
+ 	gptimer = omap_dm_timer_request_specific(1);
+ 	BUG_ON(gptimer == NULL);
+ 
++#if defined(CONFIG_OMAP_32K_TIMER)
++	omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ);
++#else
+ 	omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK);
+-	tick_period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
+-	tick_period -= 1;
++#endif
++	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
+ 
++	omap2_gp_timer_irq.dev_id = (void *)gptimer;
+ 	setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
+-	omap2_gp_timer_start(tick_period);
++	omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
++
++	clockevent_gpt.mult = div_sc(tick_rate, NSEC_PER_SEC,
++				     clockevent_gpt.shift);
++	clockevent_gpt.max_delta_ns =
++		clockevent_delta2ns(0xffffffff, &clockevent_gpt);
++	clockevent_gpt.min_delta_ns =
++		clockevent_delta2ns(1, &clockevent_gpt);
++
++	clockevent_gpt.cpumask = cpumask_of_cpu(0);
++	clockevents_register_device(&clockevent_gpt);
++}
++
++#ifdef CONFIG_OMAP_32K_TIMER
++/* 
++ * When 32k-timer is enabled, don't use GPTimer for clocksource
++ * instead, just leave default clocksource which uses the 32k
++ * sync counter.  See clocksource setup in see plat-omap/common.c. 
++ */
++
++static inline void __init omap2_gp_clocksource_init(void) {}
++#else
++/*
++ * clocksource
++ */
++static struct omap_dm_timer *gpt_clocksource;
++static cycle_t clocksource_read_cycles(void)
++{
++	return (cycle_t)omap_dm_timer_read_counter(gpt_clocksource);
++}
++
++static struct clocksource clocksource_gpt = {
++	.name		= "gp timer",
++	.rating		= 300,
++	.read		= clocksource_read_cycles,
++	.mask		= CLOCKSOURCE_MASK(32),
++	.shift		= 24,
++	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++/* Setup free-running counter for clocksource */
++static void __init omap2_gp_clocksource_init(void)
++{
++	static struct omap_dm_timer *gpt;
++	u32 tick_rate, tick_period;
++	static char err1[] __initdata = KERN_ERR
++		"%s: failed to request dm-timer\n";
++	static char err2[] __initdata = KERN_ERR
++		"%s: can't register clocksource!\n";
++
++	gpt = omap_dm_timer_request();
++	if (!gpt)
++		printk(err1, clocksource_gpt.name);
++	gpt_clocksource = gpt;
++
++	omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
++	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
++	tick_period = (tick_rate / HZ) - 1;
++
++	omap_dm_timer_set_load(gpt, 1, 0);
++	omap_dm_timer_start(gpt);
++
++	clocksource_gpt.mult =
++		clocksource_khz2mult(tick_rate/1000, clocksource_gpt.shift);
++	if (clocksource_register(&clocksource_gpt))
++		printk(err2, clocksource_gpt.name);
++}
++#endif
++
++static void __init omap2_gp_timer_init(void)
++{
++	omap_dm_timer_init();
++
++	omap2_gp_clockevent_init();
++	omap2_gp_clocksource_init();
+ }
+ 
+ struct sys_timer omap_timer = {
+diff --git a/arch/arm/mach-orion/Kconfig b/arch/arm/mach-orion/Kconfig
+deleted file mode 100644
+index 1dcbb6a..0000000
+--- a/arch/arm/mach-orion/Kconfig
++++ /dev/null
+@@ -1,41 +0,0 @@
+-if ARCH_ORION
+-
+-menu "Orion Implementations"
+-
+-config MACH_DB88F5281
+-	bool "Marvell Orion-2 Development Board"
+-	select I2C_BOARDINFO
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  Marvell Orion-2 (88F5281) Development Board
+-
+-config MACH_RD88F5182
+-	bool "Marvell Orion-NAS Reference Design"
+-	select I2C_BOARDINFO
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  Marvell Orion-NAS (88F5182) RD2
+-
+-config MACH_KUROBOX_PRO
+-	bool "KuroBox Pro"
+-	select I2C_BOARDINFO
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  KuroBox Pro platform.
+-
+-config MACH_DNS323
+-	bool "D-Link DNS-323"
+-	select I2C_BOARDINFO
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  D-Link DNS-323 platform.
+-
+-config MACH_TS209
+-	bool "QNAP TS-109/TS-209"
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  QNAP TS-109/TS-209 platform.
+-
+-endmenu
+-
+-endif
+diff --git a/arch/arm/mach-orion/Makefile b/arch/arm/mach-orion/Makefile
+deleted file mode 100644
+index f91d937..0000000
+--- a/arch/arm/mach-orion/Makefile
++++ /dev/null
+@@ -1,6 +0,0 @@
+-obj-y				+= common.o addr-map.o pci.o gpio.o irq.o time.o
+-obj-$(CONFIG_MACH_DB88F5281)	+= db88f5281-setup.o
+-obj-$(CONFIG_MACH_RD88F5182)	+= rd88f5182-setup.o
+-obj-$(CONFIG_MACH_KUROBOX_PRO)	+= kurobox_pro-setup.o
+-obj-$(CONFIG_MACH_DNS323)	+= dns323-setup.o
+-obj-$(CONFIG_MACH_TS209)	+= ts209-setup.o
+diff --git a/arch/arm/mach-orion/Makefile.boot b/arch/arm/mach-orion/Makefile.boot
+deleted file mode 100644
+index 67039c3..0000000
+--- a/arch/arm/mach-orion/Makefile.boot
++++ /dev/null
+@@ -1,3 +0,0 @@
+-   zreladdr-y	:= 0x00008000
+-params_phys-y	:= 0x00000100
+-initrd_phys-y	:= 0x00800000
+diff --git a/arch/arm/mach-orion/addr-map.c b/arch/arm/mach-orion/addr-map.c
+deleted file mode 100644
+index 58cc3c0..0000000
+--- a/arch/arm/mach-orion/addr-map.c
++++ /dev/null
+@@ -1,490 +0,0 @@
+-/*
+- * arch/arm/mach-orion/addr-map.c
+- *
+- * Address map functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
+-#include <linux/init.h>
+-#include <asm/hardware.h>
+-#include "common.h"
+-
+-/*
+- * The Orion has fully programable address map. There's a separate address
+- * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB,
+- * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
+- * address decode windows that allow it to access any of the Orion resources.
+- *
+- * CPU address decoding --
+- * Linux assumes that it is the boot loader that already setup the access to
+- * DDR and internal registers.
+- * Setup access to PCI and PCI-E IO/MEM space is issued by core.c.
+- * Setup access to various devices located on the device bus interface (e.g.
+- * flashes, RTC, etc) should be issued by machine-setup.c according to
+- * specific board population (by using orion_setup_cpu_win()).
+- *
+- * Non-CPU Masters address decoding --
+- * Unlike the CPU, we setup the access from Orion's master interfaces to DDR
+- * banks only (the typical use case).
+- * Setup access for each master to DDR is issued by common.c.
+- *
+- * Note: although orion_setbits() and orion_clrbits() are not atomic
+- * no locking is necessary here since code in this file is only called
+- * at boot time when there is no concurrency issues.
+- */
+-
+-/*
+- * Generic Address Decode Windows bit settings
+- */
+-#define TARGET_DDR		0
+-#define TARGET_PCI		3
+-#define TARGET_PCIE		4
+-#define TARGET_DEV_BUS		1
+-#define ATTR_DDR_CS(n)		(((n) ==0) ? 0xe :	\
+-				((n) == 1) ? 0xd :	\
+-				((n) == 2) ? 0xb :	\
+-				((n) == 3) ? 0x7 : 0xf)
+-#define ATTR_PCIE_MEM		0x59
+-#define ATTR_PCIE_IO		0x51
+-#define ATTR_PCI_MEM		0x59
+-#define ATTR_PCI_IO		0x51
+-#define ATTR_DEV_CS0		0x1e
+-#define ATTR_DEV_CS1		0x1d
+-#define ATTR_DEV_CS2		0x1b
+-#define ATTR_DEV_BOOT		0xf
+-#define WIN_EN			1
+-
+-/*
+- * Helpers to get DDR banks info
+- */
+-#define DDR_BASE_CS(n)		ORION_DDR_REG(0x1500 + ((n) * 8))
+-#define DDR_SIZE_CS(n)		ORION_DDR_REG(0x1504 + ((n) * 8))
+-#define DDR_MAX_CS		4
+-#define DDR_REG_TO_SIZE(reg)	(((reg) | 0xffffff) + 1)
+-#define DDR_REG_TO_BASE(reg)	((reg) & 0xff000000)
+-#define DDR_BANK_EN		1
+-
+-/*
+- * CPU Address Decode Windows registers
+- */
+-#define CPU_WIN_CTRL(n)		ORION_BRIDGE_REG(0x000 | ((n) << 4))
+-#define CPU_WIN_BASE(n)		ORION_BRIDGE_REG(0x004 | ((n) << 4))
+-#define CPU_WIN_REMAP_LO(n)	ORION_BRIDGE_REG(0x008 | ((n) << 4))
+-#define CPU_WIN_REMAP_HI(n)	ORION_BRIDGE_REG(0x00c | ((n) << 4))
+-#define CPU_MAX_WIN		8
+-
+-/*
+- * Use this CPU address decode windows allocation
+- */
+-#define CPU_WIN_PCIE_IO		0
+-#define CPU_WIN_PCI_IO		1
+-#define CPU_WIN_PCIE_MEM	2
+-#define CPU_WIN_PCI_MEM		3
+-#define CPU_WIN_DEV_BOOT	4
+-#define CPU_WIN_DEV_CS0		5
+-#define CPU_WIN_DEV_CS1		6
+-#define CPU_WIN_DEV_CS2		7
+-
+-/*
+- * PCIE Address Decode Windows registers
+- */
+-#define PCIE_BAR_CTRL(n)	ORION_PCIE_REG(0x1804 + ((n - 1) * 4))
+-#define PCIE_BAR_LO(n)		ORION_PCIE_REG(0x0010 + ((n) * 8))
+-#define PCIE_BAR_HI(n)		ORION_PCIE_REG(0x0014 + ((n) * 8))
+-#define PCIE_WIN_CTRL(n)	(((n) < 5) ? \
+-					ORION_PCIE_REG(0x1820 + ((n) << 4)) : \
+-					ORION_PCIE_REG(0x1880))
+-#define PCIE_WIN_BASE(n)	(((n) < 5) ? \
+-					ORION_PCIE_REG(0x1824 + ((n) << 4)) : \
+-					ORION_PCIE_REG(0x1884))
+-#define PCIE_WIN_REMAP(n)	(((n) < 5) ? \
+-					ORION_PCIE_REG(0x182c + ((n) << 4)) : \
+-					ORION_PCIE_REG(0x188c))
+-#define PCIE_DEFWIN_CTRL	ORION_PCIE_REG(0x18b0)
+-#define PCIE_EXPROM_WIN_CTRL	ORION_PCIE_REG(0x18c0)
+-#define PCIE_EXPROM_WIN_REMP	ORION_PCIE_REG(0x18c4)
+-#define PCIE_MAX_BARS		3
+-#define PCIE_MAX_WINS		6
+-
+-/*
+- * Use PCIE BAR '1' for all DDR banks
+- */
+-#define PCIE_DRAM_BAR		1
+-
+-/*
+- * PCI Address Decode Windows registers
+- */
+-#define PCI_BAR_SIZE_DDR_CS(n)	(((n) == 0) ? ORION_PCI_REG(0xc08) : \
+-				((n) == 1) ? ORION_PCI_REG(0xd08) :  \
+-				((n) == 2) ? ORION_PCI_REG(0xc0c) :  \
+-				((n) == 3) ? ORION_PCI_REG(0xd0c) : 0)
+-#define PCI_BAR_REMAP_DDR_CS(n)	(((n) ==0) ? ORION_PCI_REG(0xc48) : \
+-				((n) == 1) ? ORION_PCI_REG(0xd48) :  \
+-				((n) == 2) ? ORION_PCI_REG(0xc4c) :  \
+-				((n) == 3) ? ORION_PCI_REG(0xd4c) : 0)
+-#define PCI_BAR_ENABLE		ORION_PCI_REG(0xc3c)
+-#define PCI_CTRL_BASE_LO(n)	ORION_PCI_REG(0x1e00 | ((n) << 4))
+-#define PCI_CTRL_BASE_HI(n)	ORION_PCI_REG(0x1e04 | ((n) << 4))
+-#define PCI_CTRL_SIZE(n)	ORION_PCI_REG(0x1e08 | ((n) << 4))
+-#define PCI_ADDR_DECODE_CTRL	ORION_PCI_REG(0xd3c)
+-
+-/*
+- * PCI configuration heleprs for BAR settings
+- */
+-#define PCI_CONF_FUNC_BAR_CS(n)		((n) >> 1)
+-#define PCI_CONF_REG_BAR_LO_CS(n)	(((n) & 1) ? 0x18 : 0x10)
+-#define PCI_CONF_REG_BAR_HI_CS(n)	(((n) & 1) ? 0x1c : 0x14)
+-
+-/*
+- * Gigabit Ethernet Address Decode Windows registers
+- */
+-#define ETH_WIN_BASE(win)	ORION_ETH_REG(0x200 + ((win) * 8))
+-#define ETH_WIN_SIZE(win)	ORION_ETH_REG(0x204 + ((win) * 8))
+-#define ETH_WIN_REMAP(win)	ORION_ETH_REG(0x280 + ((win) * 4))
+-#define ETH_WIN_EN		ORION_ETH_REG(0x290)
+-#define ETH_WIN_PROT		ORION_ETH_REG(0x294)
+-#define ETH_MAX_WIN		6
+-#define ETH_MAX_REMAP_WIN	4
+-
+-/*
+- * USB Address Decode Windows registers
+- */
+-#define USB_WIN_CTRL(i, w)	((i == 0) ? ORION_USB0_REG(0x320 + ((w) << 4)) \
+-					: ORION_USB1_REG(0x320 + ((w) << 4)))
+-#define USB_WIN_BASE(i, w)	((i == 0) ? ORION_USB0_REG(0x324 + ((w) << 4)) \
+-					: ORION_USB1_REG(0x324 + ((w) << 4)))
+-#define USB_MAX_WIN		4
+-
+-/*
+- * SATA Address Decode Windows registers
+- */
+-#define SATA_WIN_CTRL(win)	ORION_SATA_REG(0x30 + ((win) * 0x10))
+-#define SATA_WIN_BASE(win)	ORION_SATA_REG(0x34 + ((win) * 0x10))
+-#define SATA_MAX_WIN		4
+-
+-static int __init orion_cpu_win_can_remap(u32 win)
+-{
+-	u32 dev, rev;
+-
+-	orion_pcie_id(&dev, &rev);
+-	if ((dev == MV88F5281_DEV_ID && win < 4)
+-	    || (dev == MV88F5182_DEV_ID && win < 2)
+-	    || (dev == MV88F5181_DEV_ID && win < 2))
+-		return 1;
+-
+-	return 0;
+-}
+-
+-void __init orion_setup_cpu_win(enum orion_target target, u32 base, u32 size, int remap)
+-{
+-	u32 win, attr, ctrl;
+-
+-	switch (target) {
+-	case ORION_PCIE_IO:
+-		target = TARGET_PCIE;
+-		attr = ATTR_PCIE_IO;
+-		win = CPU_WIN_PCIE_IO;
+-		break;
+-	case ORION_PCI_IO:
+-		target = TARGET_PCI;
+-		attr = ATTR_PCI_IO;
+-		win = CPU_WIN_PCI_IO;
+-		break;
+-	case ORION_PCIE_MEM:
+-		target = TARGET_PCIE;
+-		attr = ATTR_PCIE_MEM;
+-		win = CPU_WIN_PCIE_MEM;
+-		break;
+-	case ORION_PCI_MEM:
+-		target = TARGET_PCI;
+-		attr = ATTR_PCI_MEM;
+-		win = CPU_WIN_PCI_MEM;
+-		break;
+-	case ORION_DEV_BOOT:
+-		target = TARGET_DEV_BUS;
+-		attr = ATTR_DEV_BOOT;
+-		win = CPU_WIN_DEV_BOOT;
+-		break;
+-	case ORION_DEV0:
+-		target = TARGET_DEV_BUS;
+-		attr = ATTR_DEV_CS0;
+-		win = CPU_WIN_DEV_CS0;
+-		break;
+-	case ORION_DEV1:
+-		target = TARGET_DEV_BUS;
+-		attr = ATTR_DEV_CS1;
+-		win = CPU_WIN_DEV_CS1;
+-		break;
+-	case ORION_DEV2:
+-		target = TARGET_DEV_BUS;
+-		attr = ATTR_DEV_CS2;
+-		win = CPU_WIN_DEV_CS2;
+-		break;
+-	case ORION_DDR:
+-	case ORION_REGS:
+-		/*
+-		 * Must be mapped by bootloader.
+-		 */
+-	default:
+-		target = attr = win = -1;
+-		BUG();
+-	}
+-
+-	base &= 0xffff0000;
+-	ctrl = (((size - 1) & 0xffff0000) | (attr << 8) |
+-		(target << 4) | WIN_EN);
+-
+-	orion_write(CPU_WIN_BASE(win), base);
+-	orion_write(CPU_WIN_CTRL(win), ctrl);
+-
+-	if (orion_cpu_win_can_remap(win)) {
+-		if (remap >= 0) {
+-			orion_write(CPU_WIN_REMAP_LO(win), remap & 0xffff0000);
+-			orion_write(CPU_WIN_REMAP_HI(win), 0);
+-		} else {
+-			orion_write(CPU_WIN_REMAP_LO(win), base);
+-			orion_write(CPU_WIN_REMAP_HI(win), 0);
+-		}
+-	}
+-}
+-
+-void __init orion_setup_cpu_wins(void)
+-{
+-	int i;
+-
+-	/*
+-	 * First, disable and clear windows
+-	 */
+-	for (i = 0; i < CPU_MAX_WIN; i++) {
+-		orion_write(CPU_WIN_BASE(i), 0);
+-		orion_write(CPU_WIN_CTRL(i), 0);
+-		if (orion_cpu_win_can_remap(i)) {
+-			orion_write(CPU_WIN_REMAP_LO(i), 0);
+-			orion_write(CPU_WIN_REMAP_HI(i), 0);
+-		}
+-	}
+-
+-	/*
+-	 * Setup windows for PCI+PCIe IO+MEM space.
+-	 */
+-	orion_setup_cpu_win(ORION_PCIE_IO, ORION_PCIE_IO_PHYS_BASE,
+-				ORION_PCIE_IO_SIZE, ORION_PCIE_IO_BUS_BASE);
+-	orion_setup_cpu_win(ORION_PCI_IO, ORION_PCI_IO_PHYS_BASE,
+-				ORION_PCI_IO_SIZE, ORION_PCI_IO_BUS_BASE);
+-	orion_setup_cpu_win(ORION_PCIE_MEM, ORION_PCIE_MEM_PHYS_BASE,
+-				ORION_PCIE_MEM_SIZE, -1);
+-	orion_setup_cpu_win(ORION_PCI_MEM, ORION_PCI_MEM_PHYS_BASE,
+-				ORION_PCI_MEM_SIZE, -1);
+-}
+-
+-/*
+- * Setup PCIE BARs and Address Decode Wins:
+- * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
+- * WIN[0-3] -> DRAM bank[0-3]
+- */
+-void __init orion_setup_pcie_wins(void)
+-{
+-	u32 base, size, i;
+-
+-	/*
+-	 * First, disable and clear BARs and windows
+-	 */
+-	for (i = 1; i < PCIE_MAX_BARS; i++) {
+-		orion_write(PCIE_BAR_CTRL(i), 0);
+-		orion_write(PCIE_BAR_LO(i), 0);
+-		orion_write(PCIE_BAR_HI(i), 0);
+-	}
+-
+-	for (i = 0; i < PCIE_MAX_WINS; i++) {
+-		orion_write(PCIE_WIN_CTRL(i), 0);
+-		orion_write(PCIE_WIN_BASE(i), 0);
+-		orion_write(PCIE_WIN_REMAP(i), 0);
+-	}
+-
+-	/*
+-	 * Setup windows for DDR banks. Count total DDR size on the fly.
+-	 */
+-	base = DDR_REG_TO_BASE(orion_read(DDR_BASE_CS(0)));
+-	size = 0;
+-	for (i = 0; i < DDR_MAX_CS; i++) {
+-		u32 bank_base, bank_size;
+-		bank_size = orion_read(DDR_SIZE_CS(i));
+-		bank_base = orion_read(DDR_BASE_CS(i));
+-		if (bank_size & DDR_BANK_EN) {
+-			bank_size = DDR_REG_TO_SIZE(bank_size);
+-			bank_base = DDR_REG_TO_BASE(bank_base);
+-			orion_write(PCIE_WIN_BASE(i), bank_base & 0xffff0000);
+-			orion_write(PCIE_WIN_REMAP(i), 0);
+-			orion_write(PCIE_WIN_CTRL(i),
+-					((bank_size-1) & 0xffff0000) |
+-					(ATTR_DDR_CS(i) << 8) |
+-					(TARGET_DDR << 4) |
+-					(PCIE_DRAM_BAR << 1) | WIN_EN);
+-			size += bank_size;
+-		}
+-	}
+-
+-	/*
+-	 * Setup BAR[1] to all DRAM banks
+-	 */
+-	orion_write(PCIE_BAR_LO(PCIE_DRAM_BAR), base & 0xffff0000);
+-	orion_write(PCIE_BAR_HI(PCIE_DRAM_BAR), 0);
+-	orion_write(PCIE_BAR_CTRL(PCIE_DRAM_BAR),
+-				((size - 1) & 0xffff0000) | WIN_EN);
+-}
+-
+-void __init orion_setup_pci_wins(void)
+-{
+-	u32 base, size, i;
+-
+-	/*
+-	 * First, disable windows
+-	 */
+-	orion_write(PCI_BAR_ENABLE, 0xffffffff);
+-
+-	/*
+-	 * Setup windows for DDR banks.
+-	 */
+-	for (i = 0; i < DDR_MAX_CS; i++) {
+-		base = orion_read(DDR_BASE_CS(i));
+-		size = orion_read(DDR_SIZE_CS(i));
+-		if (size & DDR_BANK_EN) {
+-			u32 bus, dev, func, reg, val;
+-			size = DDR_REG_TO_SIZE(size);
+-			base = DDR_REG_TO_BASE(base);
+-			bus = orion_pci_local_bus_nr();
+-			dev = orion_pci_local_dev_nr();
+-			func = PCI_CONF_FUNC_BAR_CS(i);
+-			reg = PCI_CONF_REG_BAR_LO_CS(i);
+-			orion_pci_hw_rd_conf(bus, dev, func, reg, 4, &val);
+-			orion_pci_hw_wr_conf(bus, dev, func, reg, 4,
+-					(base & 0xfffff000) | (val & 0xfff));
+-			reg = PCI_CONF_REG_BAR_HI_CS(i);
+-			orion_pci_hw_wr_conf(bus, dev, func, reg, 4, 0);
+-			orion_write(PCI_BAR_SIZE_DDR_CS(i),
+-					(size - 1) & 0xfffff000);
+-			orion_write(PCI_BAR_REMAP_DDR_CS(i),
+-					base & 0xfffff000);
+-			orion_clrbits(PCI_BAR_ENABLE, (1 << i));
+-		}
+-	}
+-
+-	/*
+-	 * Disable automatic update of address remaping when writing to BARs
+-	 */
+-	orion_setbits(PCI_ADDR_DECODE_CTRL, 1);
+-}
+-
+-void __init orion_setup_usb_wins(void)
+-{
+-	int i;
+-	u32 usb_if, dev, rev;
+-	u32 max_usb_if = 1;
+-
+-	orion_pcie_id(&dev, &rev);
+-	if (dev == MV88F5182_DEV_ID)
+-		max_usb_if = 2;
+-
+-	for (usb_if = 0; usb_if < max_usb_if; usb_if++) {
+-		/*
+-		 * First, disable and clear windows
+-		 */
+-		for (i = 0; i < USB_MAX_WIN; i++) {
+-			orion_write(USB_WIN_BASE(usb_if, i), 0);
+-			orion_write(USB_WIN_CTRL(usb_if, i), 0);
+-		}
+-
+-		/*
+-		 * Setup windows for DDR banks.
+-		 */
+-		for (i = 0; i < DDR_MAX_CS; i++) {
+-			u32 base, size;
+-			size = orion_read(DDR_SIZE_CS(i));
+-			base = orion_read(DDR_BASE_CS(i));
+-			if (size & DDR_BANK_EN) {
+-				base = DDR_REG_TO_BASE(base);
+-				size = DDR_REG_TO_SIZE(size);
+-				orion_write(USB_WIN_CTRL(usb_if, i),
+-						((size-1) & 0xffff0000) |
+-						(ATTR_DDR_CS(i) << 8) |
+-						(TARGET_DDR << 4) | WIN_EN);
+-				orion_write(USB_WIN_BASE(usb_if, i),
+-						base & 0xffff0000);
+-			}
+-		}
+-	}
+-}
+-
+-void __init orion_setup_eth_wins(void)
+-{
+-	int i;
+-
+-	/*
+-	 * First, disable and clear windows
+-	 */
+-	for (i = 0; i < ETH_MAX_WIN; i++) {
+-		orion_write(ETH_WIN_BASE(i), 0);
+-		orion_write(ETH_WIN_SIZE(i), 0);
+-		orion_setbits(ETH_WIN_EN, 1 << i);
+-		orion_clrbits(ETH_WIN_PROT, 0x3 << (i * 2));
+-		if (i < ETH_MAX_REMAP_WIN)
+-			orion_write(ETH_WIN_REMAP(i), 0);
+-	}
+-
+-	/*
+-	 * Setup windows for DDR banks.
+-	 */
+-	for (i = 0; i < DDR_MAX_CS; i++) {
+-		u32 base, size;
+-		size = orion_read(DDR_SIZE_CS(i));
+-		base = orion_read(DDR_BASE_CS(i));
+-		if (size & DDR_BANK_EN) {
+-			base = DDR_REG_TO_BASE(base);
+-			size = DDR_REG_TO_SIZE(size);
+-			orion_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000);
+-			orion_write(ETH_WIN_BASE(i), (base & 0xffff0000) |
+-					(ATTR_DDR_CS(i) << 8) |
+-					TARGET_DDR);
+-			orion_clrbits(ETH_WIN_EN, 1 << i);
+-			orion_setbits(ETH_WIN_PROT, 0x3 << (i * 2));
+-		}
+-	}
+-}
+-
+-void __init orion_setup_sata_wins(void)
+-{
+-	int i;
+-
+-	/*
+-	 * First, disable and clear windows
+-	 */
+-	for (i = 0; i < SATA_MAX_WIN; i++) {
+-		orion_write(SATA_WIN_BASE(i), 0);
+-		orion_write(SATA_WIN_CTRL(i), 0);
+-	}
+-
+-	/*
+-	 * Setup windows for DDR banks.
+-	 */
+-	for (i = 0; i < DDR_MAX_CS; i++) {
+-		u32 base, size;
+-		size = orion_read(DDR_SIZE_CS(i));
+-		base = orion_read(DDR_BASE_CS(i));
+-		if (size & DDR_BANK_EN) {
+-			base = DDR_REG_TO_BASE(base);
+-			size = DDR_REG_TO_SIZE(size);
+-			orion_write(SATA_WIN_CTRL(i),
+-					((size-1) & 0xffff0000) |
+-					(ATTR_DDR_CS(i) << 8) |
+-					(TARGET_DDR << 4) | WIN_EN);
+-			orion_write(SATA_WIN_BASE(i),
+-					base & 0xffff0000);
+-		}
+-	}
+-}
+diff --git a/arch/arm/mach-orion/common.c b/arch/arm/mach-orion/common.c
+deleted file mode 100644
+index bbc2b4e..0000000
+--- a/arch/arm/mach-orion/common.c
++++ /dev/null
+@@ -1,369 +0,0 @@
+-/*
+- * arch/arm/mach-orion/common.c
+- *
+- * Core functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/serial_8250.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/mv643xx_i2c.h>
+-#include <asm/page.h>
+-#include <asm/setup.h>
+-#include <asm/timex.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/map.h>
+-#include <asm/arch/hardware.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * I/O Address Mapping
+- ****************************************************************************/
+-static struct map_desc orion_io_desc[] __initdata = {
+-	{
+-		.virtual	= ORION_REGS_VIRT_BASE,
+-		.pfn		= __phys_to_pfn(ORION_REGS_PHYS_BASE),
+-		.length		= ORION_REGS_SIZE,
+-		.type		= MT_DEVICE
+-	},
+-	{
+-		.virtual	= ORION_PCIE_IO_VIRT_BASE,
+-		.pfn		= __phys_to_pfn(ORION_PCIE_IO_PHYS_BASE),
+-		.length		= ORION_PCIE_IO_SIZE,
+-		.type		= MT_DEVICE
+-	},
+-	{
+-		.virtual	= ORION_PCI_IO_VIRT_BASE,
+-		.pfn		= __phys_to_pfn(ORION_PCI_IO_PHYS_BASE),
+-		.length		= ORION_PCI_IO_SIZE,
+-		.type		= MT_DEVICE
+-	},
+-	{
+-		.virtual	= ORION_PCIE_WA_VIRT_BASE,
+-		.pfn		= __phys_to_pfn(ORION_PCIE_WA_PHYS_BASE),
+-		.length		= ORION_PCIE_WA_SIZE,
+-		.type		= MT_DEVICE
+-	},
+-};
+-
+-void __init orion_map_io(void)
+-{
+-	iotable_init(orion_io_desc, ARRAY_SIZE(orion_io_desc));
+-}
+-
+-/*****************************************************************************
+- * UART
+- ****************************************************************************/
+-
+-static struct resource orion_uart_resources[] = {
+-	{
+-		.start		= UART0_PHYS_BASE,
+-		.end		= UART0_PHYS_BASE + 0xff,
+-		.flags		= IORESOURCE_MEM,
+-	},
+-	{
+-		.start		= IRQ_ORION_UART0,
+-		.end		= IRQ_ORION_UART0,
+-		.flags		= IORESOURCE_IRQ,
+-	},
+-	{
+-		.start		= UART1_PHYS_BASE,
+-		.end		= UART1_PHYS_BASE + 0xff,
+-		.flags		= IORESOURCE_MEM,
+-	},
+-	{
+-		.start		= IRQ_ORION_UART1,
+-		.end		= IRQ_ORION_UART1,
+-		.flags		= IORESOURCE_IRQ,
+-	},
+-};
+-
+-static struct plat_serial8250_port orion_uart_data[] = {
+-	{
+-		.mapbase	= UART0_PHYS_BASE,
+-		.membase	= (char *)UART0_VIRT_BASE,
+-		.irq		= IRQ_ORION_UART0,
+-		.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+-		.iotype		= UPIO_MEM,
+-		.regshift	= 2,
+-		.uartclk	= ORION_TCLK,
+-	},
+-	{
+-		.mapbase	= UART1_PHYS_BASE,
+-		.membase	= (char *)UART1_VIRT_BASE,
+-		.irq		= IRQ_ORION_UART1,
+-		.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+-		.iotype		= UPIO_MEM,
+-		.regshift	= 2,
+-		.uartclk	= ORION_TCLK,
+-	},
+-	{ },
+-};
+-
+-static struct platform_device orion_uart = {
+-	.name			= "serial8250",
+-	.id			= PLAT8250_DEV_PLATFORM,
+-	.dev			= {
+-		.platform_data	= orion_uart_data,
+-	},
+-	.resource		= orion_uart_resources,
+-	.num_resources		= ARRAY_SIZE(orion_uart_resources),
+-};
+-
+-/*******************************************************************************
+- * USB Controller - 2 interfaces
+- ******************************************************************************/
+-
+-static struct resource orion_ehci0_resources[] = {
+-	{
+-		.start	= ORION_USB0_PHYS_BASE,
+-		.end	= ORION_USB0_PHYS_BASE + SZ_4K,
+-		.flags	= IORESOURCE_MEM,
+-	},
+-	{
+-		.start	= IRQ_ORION_USB0_CTRL,
+-		.end	= IRQ_ORION_USB0_CTRL,
+-		.flags	= IORESOURCE_IRQ,
+-	},
+-};
+-
+-static struct resource orion_ehci1_resources[] = {
+-	{
+-		.start	= ORION_USB1_PHYS_BASE,
+-		.end	= ORION_USB1_PHYS_BASE + SZ_4K,
+-		.flags	= IORESOURCE_MEM,
+-	},
+-	{
+-		.start	= IRQ_ORION_USB1_CTRL,
+-		.end	= IRQ_ORION_USB1_CTRL,
+-		.flags	= IORESOURCE_IRQ,
+-	},
+-};
+-
+-static u64 ehci_dmamask = 0xffffffffUL;
+-
+-static struct platform_device orion_ehci0 = {
+-	.name		= "orion-ehci",
+-	.id		= 0,
+-	.dev		= {
+-		.dma_mask		= &ehci_dmamask,
+-		.coherent_dma_mask	= 0xffffffff,
+-	},
+-	.resource	= orion_ehci0_resources,
+-	.num_resources	= ARRAY_SIZE(orion_ehci0_resources),
+-};
+-
+-static struct platform_device orion_ehci1 = {
+-	.name		= "orion-ehci",
+-	.id		= 1,
+-	.dev		= {
+-		.dma_mask		= &ehci_dmamask,
+-		.coherent_dma_mask	= 0xffffffff,
+-	},
+-	.resource	= orion_ehci1_resources,
+-	.num_resources	= ARRAY_SIZE(orion_ehci1_resources),
+-};
+-
+-/*****************************************************************************
+- * Gigabit Ethernet port
+- * (The Orion and Discovery (MV643xx) families use the same Ethernet driver)
+- ****************************************************************************/
+-
+-static struct resource orion_eth_shared_resources[] = {
+-	{
+-		.start	= ORION_ETH_PHYS_BASE + 0x2000,
+-		.end	= ORION_ETH_PHYS_BASE + 0x3fff,
+-		.flags	= IORESOURCE_MEM,
+-	},
+-};
+-
+-static struct platform_device orion_eth_shared = {
+-	.name		= MV643XX_ETH_SHARED_NAME,
+-	.id		= 0,
+-	.num_resources	= 1,
+-	.resource	= orion_eth_shared_resources,
+-};
+-
+-static struct resource orion_eth_resources[] = {
+-	{
+-		.name	= "eth irq",
+-		.start	= IRQ_ORION_ETH_SUM,
+-		.end	= IRQ_ORION_ETH_SUM,
+-		.flags	= IORESOURCE_IRQ,
+-	}
+-};
+-
+-static struct platform_device orion_eth = {
+-	.name		= MV643XX_ETH_NAME,
+-	.id		= 0,
+-	.num_resources	= 1,
+-	.resource	= orion_eth_resources,
+-};
+-
+-void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data)
+-{
+-	orion_eth.dev.platform_data = eth_data;
+-	platform_device_register(&orion_eth_shared);
+-	platform_device_register(&orion_eth);
+-}
+-
+-/*****************************************************************************
+- * I2C controller
+- * (The Orion and Discovery (MV643xx) families share the same I2C controller)
+- ****************************************************************************/
+-
+-static struct mv64xxx_i2c_pdata orion_i2c_pdata = {
+-	.freq_m		= 8, /* assumes 166 MHz TCLK */
+-	.freq_n		= 3,
+-	.timeout	= 1000, /* Default timeout of 1 second */
+-};
+-
+-static struct resource orion_i2c_resources[] = {
+-	{
+-		.name   = "i2c base",
+-		.start  = I2C_PHYS_BASE,
+-		.end    = I2C_PHYS_BASE + 0x20 -1,
+-		.flags  = IORESOURCE_MEM,
+-	},
+-	{
+-		.name   = "i2c irq",
+-		.start  = IRQ_ORION_I2C,
+-		.end    = IRQ_ORION_I2C,
+-		.flags  = IORESOURCE_IRQ,
+-	},
+-};
+-
+-static struct platform_device orion_i2c = {
+-	.name		= MV64XXX_I2C_CTLR_NAME,
+-	.id		= 0,
+-	.num_resources	= ARRAY_SIZE(orion_i2c_resources),
+-	.resource	= orion_i2c_resources,
+-	.dev		= {
+-		.platform_data = &orion_i2c_pdata,
+-	},
+-};
+-
+-/*****************************************************************************
+- * Sata port
+- ****************************************************************************/
+-static struct resource orion_sata_resources[] = {
+-        {
+-                .name   = "sata base",
+-                .start  = ORION_SATA_PHYS_BASE,
+-                .end    = ORION_SATA_PHYS_BASE + 0x5000 - 1,
+-                .flags  = IORESOURCE_MEM,
+-        },
+-	{
+-                .name   = "sata irq",
+-                .start  = IRQ_ORION_SATA,
+-                .end    = IRQ_ORION_SATA,
+-                .flags  = IORESOURCE_IRQ,
+-        },
+-};
+-
+-static struct platform_device orion_sata = {
+-	.name           = "sata_mv",
+-	.id             = 0,
+-	.dev		= {
+-		.coherent_dma_mask	= 0xffffffff,
+-	},
+-	.num_resources  = ARRAY_SIZE(orion_sata_resources),
+-	.resource       = orion_sata_resources,
+-};
+-
+-void __init orion_sata_init(struct mv_sata_platform_data *sata_data)
+-{
+-	orion_sata.dev.platform_data = sata_data;
+-	platform_device_register(&orion_sata);
+-}
+-
+-/*****************************************************************************
+- * General
+- ****************************************************************************/
+-
+-/*
+- * Identify device ID and rev from PCIE configuration header space '0'.
+- */
+-static void orion_id(u32 *dev, u32 *rev, char **dev_name)
+-{
+-	orion_pcie_id(dev, rev);
+-
+-	if (*dev == MV88F5281_DEV_ID) {
+-		if (*rev == MV88F5281_REV_D2) {
+-			*dev_name = "MV88F5281-D2";
+-		} else if (*rev == MV88F5281_REV_D1) {
+-			*dev_name = "MV88F5281-D1";
+-		} else {
+-			*dev_name = "MV88F5281-Rev-Unsupported";
+-		}
+-	} else if (*dev == MV88F5182_DEV_ID) {
+-		if (*rev == MV88F5182_REV_A2) {
+-			*dev_name = "MV88F5182-A2";
+-		} else {
+-			*dev_name = "MV88F5182-Rev-Unsupported";
+-		}
+-	} else if (*dev == MV88F5181_DEV_ID) {
+-		if (*rev == MV88F5181_REV_B1) {
+-			*dev_name = "MV88F5181-Rev-B1";
+-		} else {
+-			*dev_name = "MV88F5181-Rev-Unsupported";
+-		}
+-	} else {
+-		*dev_name = "Device-Unknown";
+-	}
+-}
+-
+-void __init orion_init(void)
+-{
+-	char *dev_name;
+-	u32 dev, rev;
+-
+-	orion_id(&dev, &rev, &dev_name);
+-	printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION_TCLK);
+-
+-	/*
+-	 * Setup Orion address map
+-	 */
+-	orion_setup_cpu_wins();
+-	orion_setup_usb_wins();
+-	orion_setup_eth_wins();
+-	orion_setup_pci_wins();
+-	orion_setup_pcie_wins();
+-	if (dev == MV88F5182_DEV_ID)
+-		orion_setup_sata_wins();
+-
+-	/*
+-	 * REgister devices
+-	 */
+-	platform_device_register(&orion_uart);
+-	platform_device_register(&orion_ehci0);
+-	if (dev == MV88F5182_DEV_ID)
+-		platform_device_register(&orion_ehci1);
+-	platform_device_register(&orion_i2c);
+-}
+-
+-/*
+- * Many orion-based systems have buggy bootloader implementations.
+- * This is a common fixup for bogus memory tags.
+- */
+-void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
+-			    char **from, struct meminfo *meminfo)
+-{
+-	for (; t->hdr.size; t = tag_next(t))
+-		if (t->hdr.tag == ATAG_MEM &&
+-		    (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
+-		     t->u.mem.start & ~PAGE_MASK)) {
+-			printk(KERN_WARNING
+-			       "Clearing invalid memory bank %dKB at 0x%08x\n",
+-			       t->u.mem.size / 1024, t->u.mem.start);
+-			t->hdr.tag = 0;
+-		}
+-}
+diff --git a/arch/arm/mach-orion/common.h b/arch/arm/mach-orion/common.h
+deleted file mode 100644
+index 501497c..0000000
+--- a/arch/arm/mach-orion/common.h
++++ /dev/null
+@@ -1,92 +0,0 @@
+-#ifndef __ARCH_ORION_COMMON_H__
+-#define __ARCH_ORION_COMMON_H__
+-
+-/*
+- * Basic Orion init functions used early by machine-setup.
+- */
+-
+-void __init orion_map_io(void);
+-void __init orion_init_irq(void);
+-void __init orion_init(void);
+-
+-/*
+- * Enumerations and functions for Orion windows mapping. Used by Orion core
+- * functions to map its interfaces and by the machine-setup to map its on-
+- * board devices. Details in /mach-orion/addr-map.c
+- */
+-
+-enum orion_target {
+-	ORION_DEV_BOOT = 0,
+-	ORION_DEV0,
+-	ORION_DEV1,
+-	ORION_DEV2,
+-	ORION_PCIE_MEM,
+-	ORION_PCIE_IO,
+-	ORION_PCI_MEM,
+-	ORION_PCI_IO,
+-	ORION_DDR,
+-	ORION_REGS,
+-	ORION_MAX_TARGETS
+-};
+-
+-void orion_setup_cpu_win(enum orion_target target, u32 base, u32 size, int remap);
+-void orion_setup_cpu_wins(void);
+-void orion_setup_eth_wins(void);
+-void orion_setup_usb_wins(void);
+-void orion_setup_pci_wins(void);
+-void orion_setup_pcie_wins(void);
+-void orion_setup_sata_wins(void);
+-
+-/*
+- * Shared code used internally by other Orion core functions.
+- * (/mach-orion/pci.c)
+- */
+-
+-struct pci_sys_data;
+-struct pci_bus;
+-
+-void orion_pcie_id(u32 *dev, u32 *rev);
+-u32 orion_pcie_local_bus_nr(void);
+-u32 orion_pci_local_bus_nr(void);
+-u32 orion_pci_local_dev_nr(void);
+-int orion_pci_sys_setup(int nr, struct pci_sys_data *sys);
+-struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
+-int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 *val);
+-int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 val);
+-
+-/*
+- * Valid GPIO pins according to MPP setup, used by machine-setup.
+- * (/mach-orion/gpio.c).
+- */
+-
+-void __init orion_gpio_set_valid_pins(u32 pins);
+-void gpio_display(void);	/* debug */
+-
+-/*
+- * Orion system timer (clocksource + clockevnt, /mach-orion/time.c)
+- */
+-extern struct sys_timer orion_timer;
+-
+-/*
+- * Pull in Orion Ethernet platform_data, used by machine-setup
+- */
+-
+-struct mv643xx_eth_platform_data;
+-
+-void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data);
+-
+-/*
+- * Orion Sata platform_data, used by machine-setup
+- */
+-
+-struct mv_sata_platform_data;
+-
+-void __init orion_sata_init(struct mv_sata_platform_data *sata_data);
+-
+-struct machine_desc;
+-struct meminfo;
+-struct tag;
+-extern void __init tag_fixup_mem32(struct machine_desc *, struct tag *,
+-				   char **, struct meminfo *);
+-
+-#endif /* __ARCH_ORION_COMMON_H__ */
+diff --git a/arch/arm/mach-orion/db88f5281-setup.c b/arch/arm/mach-orion/db88f5281-setup.c
+deleted file mode 100644
+index 5ef44e1..0000000
+--- a/arch/arm/mach-orion/db88f5281-setup.c
++++ /dev/null
+@@ -1,364 +0,0 @@
+-/*
+- * arch/arm/mach-orion/db88f5281-setup.c
+- *
+- * Marvell Orion-2 Development Board Setup
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mtd/nand.h>
+-#include <linux/timer.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/i2c.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * DB-88F5281 on board devices
+- ****************************************************************************/
+-
+-/*
+- * 512K NOR flash Device bus boot chip select
+- */
+-
+-#define DB88F5281_NOR_BOOT_BASE		0xf4000000
+-#define DB88F5281_NOR_BOOT_SIZE		SZ_512K
+-
+-/*
+- * 7-Segment on Device bus chip select 0
+- */
+-
+-#define DB88F5281_7SEG_BASE		0xfa000000
+-#define DB88F5281_7SEG_SIZE		SZ_1K
+-
+-/*
+- * 32M NOR flash on Device bus chip select 1
+- */
+-
+-#define DB88F5281_NOR_BASE		0xfc000000
+-#define DB88F5281_NOR_SIZE		SZ_32M
+-
+-/*
+- * 32M NAND flash on Device bus chip select 2
+- */
+-
+-#define DB88F5281_NAND_BASE		0xfa800000
+-#define DB88F5281_NAND_SIZE		SZ_1K
+-
+-/*
+- * PCI
+- */
+-
+-#define DB88F5281_PCI_SLOT0_OFFS		7
+-#define DB88F5281_PCI_SLOT0_IRQ_PIN		12
+-#define DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN	13
+-
+-/*****************************************************************************
+- * 512M NOR Flash on Device bus Boot CS
+- ****************************************************************************/
+-
+-static struct physmap_flash_data db88f5281_boot_flash_data = {
+-	.width		= 1,	/* 8 bit bus width */
+-};
+-
+-static struct resource db88f5281_boot_flash_resource = {
+-	.flags		= IORESOURCE_MEM,
+-	.start		= DB88F5281_NOR_BOOT_BASE,
+-	.end		= DB88F5281_NOR_BOOT_BASE + DB88F5281_NOR_BOOT_SIZE - 1,
+-};
+-
+-static struct platform_device db88f5281_boot_flash = {
+-	.name		= "physmap-flash",
+-	.id		= 0,
+-	.dev		= {
+-		.platform_data = &db88f5281_boot_flash_data,
+-	},
+-	.num_resources	= 1,
+-	.resource	= &db88f5281_boot_flash_resource,
+-};
+-
+-/*****************************************************************************
+- * 32M NOR Flash on Device bus CS1
+- ****************************************************************************/
+-
+-static struct physmap_flash_data db88f5281_nor_flash_data = {
+-	.width		= 4,	/* 32 bit bus width */
+-};
+-
+-static struct resource db88f5281_nor_flash_resource = {
+-	.flags		= IORESOURCE_MEM,
+-	.start		= DB88F5281_NOR_BASE,
+-	.end		= DB88F5281_NOR_BASE + DB88F5281_NOR_SIZE - 1,
+-};
+-
+-static struct platform_device db88f5281_nor_flash = {
+-	.name		= "physmap-flash",
+-	.id		= 1,
+-	.dev		= {
+-		.platform_data = &db88f5281_nor_flash_data,
+-	},
+-	.num_resources	= 1,
+-	.resource	= &db88f5281_nor_flash_resource,
+-};
+-
+-/*****************************************************************************
+- * 32M NAND Flash on Device bus CS2
+- ****************************************************************************/
+-
+-static struct mtd_partition db88f5281_nand_parts[] = {
+-	{
+-		.name = "kernel",
+-		.offset = 0,
+-		.size = SZ_2M,
+-	},
+-	{
+-		.name = "root",
+-		.offset = SZ_2M,
+-		.size = (SZ_16M - SZ_2M),
+-	},
+-	{
+-		.name = "user",
+-		.offset = SZ_16M,
+-		.size = SZ_8M,
+-	},
+-	{
+-		.name = "recovery",
+-		.offset = (SZ_16M + SZ_8M),
+-		.size = SZ_8M,
+-	},
+-};
+-
+-static struct resource db88f5281_nand_resource = {
+-	.flags		= IORESOURCE_MEM,
+-	.start		= DB88F5281_NAND_BASE,
+-	.end		= DB88F5281_NAND_BASE + DB88F5281_NAND_SIZE - 1,
+-};
+-
+-static struct orion_nand_data db88f5281_nand_data = {
+-	.parts		= db88f5281_nand_parts,
+-	.nr_parts	= ARRAY_SIZE(db88f5281_nand_parts),
+-	.cle		= 0,
+-	.ale		= 1,
+-	.width		= 8,
+-};
+-
+-static struct platform_device db88f5281_nand_flash = {
+-	.name		= "orion_nand",
+-	.id		= -1,
+-	.dev		= {
+-		.platform_data	= &db88f5281_nand_data,
+-	},
+-	.resource	= &db88f5281_nand_resource,
+-	.num_resources	= 1,
+-};
+-
+-/*****************************************************************************
+- * 7-Segment on Device bus CS0
+- * Dummy counter every 2 sec
+- ****************************************************************************/
+-
+-static void __iomem *db88f5281_7seg;
+-static struct timer_list db88f5281_timer;
+-
+-static void db88f5281_7seg_event(unsigned long data)
+-{
+-	static int count = 0;
+-	writel(0, db88f5281_7seg + (count << 4));
+-	count = (count + 1) & 7;
+-	mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
+-}
+-
+-static int __init db88f5281_7seg_init(void)
+-{
+-	if (machine_is_db88f5281()) {
+-		db88f5281_7seg = ioremap(DB88F5281_7SEG_BASE,
+-					DB88F5281_7SEG_SIZE);
+-		if (!db88f5281_7seg) {
+-			printk(KERN_ERR "Failed to ioremap db88f5281_7seg\n");
+-			return -EIO;
+-		}
+-		setup_timer(&db88f5281_timer, db88f5281_7seg_event, 0);
+-		mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
+-	}
+-
+-	return 0;
+-}
+-
+-__initcall(db88f5281_7seg_init);
+-
+-/*****************************************************************************
+- * PCI
+- ****************************************************************************/
+-
+-void __init db88f5281_pci_preinit(void)
+-{
+-	int pin;
+-
+-	/*
+-	 * Configure PCI GPIO IRQ pins
+-	 */
+-	pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
+-	if (gpio_request(pin, "PCI Int1") == 0) {
+-		if (gpio_direction_input(pin) == 0) {
+-			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+-		} else {
+-			printk(KERN_ERR "db88f5281_pci_preinit faield to "
+-					"set_irq_type pin %d\n", pin);
+-			gpio_free(pin);
+-		}
+-	} else {
+-		printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
+-	}
+-
+-	pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
+-	if (gpio_request(pin, "PCI Int2") == 0) {
+-		if (gpio_direction_input(pin) == 0) {
+-			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+-		} else {
+-			printk(KERN_ERR "db88f5281_pci_preinit faield "
+-					"to set_irq_type pin %d\n", pin);
+-			gpio_free(pin);
+-		}
+-	} else {
+-		printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
+-	}
+-}
+-
+-static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+-	/*
+-	 * PCIE IRQ is connected internally (not GPIO)
+-	 */
+-	if (dev->bus->number == orion_pcie_local_bus_nr())
+-		return IRQ_ORION_PCIE0_INT;
+-
+-	/*
+-	 * PCI IRQs are connected via GPIOs
+-	 */
+-	switch (slot - DB88F5281_PCI_SLOT0_OFFS) {
+-	case 0:
+-		return gpio_to_irq(DB88F5281_PCI_SLOT0_IRQ_PIN);
+-	case 1:
+-	case 2:
+-		return gpio_to_irq(DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN);
+-	default:
+-		return -1;
+-	}
+-}
+-
+-static struct hw_pci db88f5281_pci __initdata = {
+-	.nr_controllers	= 2,
+-	.preinit	= db88f5281_pci_preinit,
+-	.swizzle	= pci_std_swizzle,
+-	.setup		= orion_pci_sys_setup,
+-	.scan		= orion_pci_sys_scan_bus,
+-	.map_irq	= db88f5281_pci_map_irq,
+-};
+-
+-static int __init db88f5281_pci_init(void)
+-{
+-	if (machine_is_db88f5281())
+-		pci_common_init(&db88f5281_pci);
+-
+-	return 0;
+-}
+-
+-subsys_initcall(db88f5281_pci_init);
+-
+-/*****************************************************************************
+- * Ethernet
+- ****************************************************************************/
+-static struct mv643xx_eth_platform_data db88f5281_eth_data = {
+-	.phy_addr	= 8,
+-	.force_phy_addr = 1,
+-};
+-
+-/*****************************************************************************
+- * RTC DS1339 on I2C bus
+- ****************************************************************************/
+-static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
+-	.driver_name	= "rtc-ds1307",
+-	.type		= "ds1339",
+-	.addr		= 0x68,
+-};
+-
+-/*****************************************************************************
+- * General Setup
+- ****************************************************************************/
+-
+-static struct platform_device *db88f5281_devs[] __initdata = {
+-	&db88f5281_boot_flash,
+-	&db88f5281_nor_flash,
+-	&db88f5281_nand_flash,
+-};
+-
+-static void __init db88f5281_init(void)
+-{
+-	/*
+-	 * Basic Orion setup. Need to be called early.
+-	 */
+-	orion_init();
+-
+-	/*
+-	 * Setup the CPU address decode windows for our on-board devices
+-	 */
+-	orion_setup_cpu_win(ORION_DEV_BOOT, DB88F5281_NOR_BOOT_BASE,
+-				DB88F5281_NOR_BOOT_SIZE, -1);
+-	orion_setup_cpu_win(ORION_DEV0,	DB88F5281_7SEG_BASE,
+-				DB88F5281_7SEG_SIZE, -1);
+-	orion_setup_cpu_win(ORION_DEV1, DB88F5281_NOR_BASE,
+-				DB88F5281_NOR_SIZE, -1);
+-	orion_setup_cpu_win(ORION_DEV2,	DB88F5281_NAND_BASE,
+-				DB88F5281_NAND_SIZE, -1);
+-
+-	/*
+-	 * Setup Multiplexing Pins:
+-	 * MPP0: GPIO (USB Over Current)	MPP1: GPIO (USB Vbat input)
+-	 * MPP2: PCI_REQn[2]			MPP3: PCI_GNTn[2]
+-	 * MPP4: PCI_REQn[3]			MPP5: PCI_GNTn[3]
+-	 * MPP6: GPIO (JP0, CON17.2)		MPP7: GPIO (JP1, CON17.1)
+-	 * MPP8: GPIO (JP2, CON11.2)		MPP9: GPIO (JP3, CON11.3)
+-	 * MPP10: GPIO (RTC int)		MPP11: GPIO (Baud Rate Generator)
+-	 * MPP12: GPIO (PCI int 1)		MPP13: GPIO (PCI int 2)
+-	 * MPP14: NAND_REn[2]			MPP15: NAND_WEn[2]
+-	 * MPP16: UART1_RX			MPP17: UART1_TX
+-	 * MPP18: UART1_CTS			MPP19: UART1_RTS
+-	 * MPP-DEV: DEV_D[16:31]
+-	 */
+-	orion_write(MPP_0_7_CTRL, 0x00222203);
+-	orion_write(MPP_8_15_CTRL, 0x44000000);
+-	orion_write(MPP_16_19_CTRL, 0);
+-	orion_write(MPP_DEV_CTRL, 0);
+-
+-	orion_gpio_set_valid_pins(0x00003fc3);
+-
+-	platform_add_devices(db88f5281_devs, ARRAY_SIZE(db88f5281_devs));
+-	i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
+-	orion_eth_init(&db88f5281_eth_data);
+-}
+-
+-MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
+-	/* Maintainer: Tzachi Perelstein <tzachi at marvell.com> */
+-	.phys_io	= ORION_REGS_PHYS_BASE,
+-	.io_pg_offst	= ((ORION_REGS_VIRT_BASE) >> 18) & 0xfffc,
+-	.boot_params	= 0x00000100,
+-	.init_machine	= db88f5281_init,
+-	.map_io		= orion_map_io,
+-	.init_irq	= orion_init_irq,
+-	.timer		= &orion_timer,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion/dns323-setup.c b/arch/arm/mach-orion/dns323-setup.c
+deleted file mode 100644
+index 076e155..0000000
+--- a/arch/arm/mach-orion/dns323-setup.c
++++ /dev/null
+@@ -1,323 +0,0 @@
+-/*
+- * arch/arm/mach-orion/dns323-setup.c
+- *
+- * Copyright (C) 2007 Herbert Valerio Riedel <hvr at gnu.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License as
+- * published by the Free Software Foundation; either version 2 of the
+- * License, or (at your option) any later version.
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/leds.h>
+-#include <linux/gpio_keys.h>
+-#include <linux/input.h>
+-#include <linux/i2c.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-#define DNS323_GPIO_LED_RIGHT_AMBER	1
+-#define DNS323_GPIO_LED_LEFT_AMBER	2
+-#define DNS323_GPIO_LED_POWER		5
+-#define DNS323_GPIO_OVERTEMP		6
+-#define DNS323_GPIO_RTC			7
+-#define DNS323_GPIO_POWER_OFF		8
+-#define DNS323_GPIO_KEY_POWER		9
+-#define DNS323_GPIO_KEY_RESET		10
+-
+-/****************************************************************************
+- * PCI setup
+- */
+-
+-static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+-	/* PCI-E */
+-	if (dev->bus->number == orion_pcie_local_bus_nr())
+-		return IRQ_ORION_PCIE0_INT;
+-
+-	pr_err("%s: requested mapping for unknown bus\n", __func__);
+-
+-	return -1;
+-}
+-
+-static struct hw_pci dns323_pci __initdata = {
+-	.nr_controllers = 1,
+-	.swizzle	= pci_std_swizzle,
+-	.setup		= orion_pci_sys_setup,
+-	.scan		= orion_pci_sys_scan_bus,
+-	.map_irq	= dns323_pci_map_irq,
+-};
+-
+-static int __init dns323_pci_init(void)
+-{
+-	if (machine_is_dns323())
+-		pci_common_init(&dns323_pci);
+-
+-	return 0;
+-}
+-
+-subsys_initcall(dns323_pci_init);
+-
+-/****************************************************************************
+- * Ethernet
+- */
+-
+-static struct mv643xx_eth_platform_data dns323_eth_data = {
+-	.phy_addr = 8,
+-	.force_phy_addr = 1,
+-};
+-
+-/****************************************************************************
+- * 8MiB NOR flash (Spansion S29GL064M90TFIR4)
+- *
+- * Layout as used by D-Link:
+- *  0x00000000-0x00010000 : "MTD1"
+- *  0x00010000-0x00020000 : "MTD2"
+- *  0x00020000-0x001a0000 : "Linux Kernel"
+- *  0x001a0000-0x007d0000 : "File System"
+- *  0x007d0000-0x00800000 : "u-boot"
+- */
+-
+-#define DNS323_NOR_BOOT_BASE 0xf4000000
+-#define DNS323_NOR_BOOT_SIZE SZ_8M
+-
+-static struct mtd_partition dns323_partitions[] = {
+-	{
+-		.name	= "MTD1",
+-		.size	= 0x00010000,
+-		.offset	= 0,
+-	}, {
+-		.name	= "MTD2",
+-		.size	= 0x00010000,
+-		.offset = 0x00010000,
+-	}, {
+-		.name	= "Linux Kernel",
+-		.size	= 0x00180000,
+-		.offset	= 0x00020000,
+-	}, {
+-		.name	= "File System",
+-		.size	= 0x00630000,
+-		.offset	= 0x001A0000,
+-	}, {
+-		.name	= "u-boot",
+-		.size	= 0x00030000,
+-		.offset	= 0x007d0000,
+-	}
+-};
+-
+-static struct physmap_flash_data dns323_nor_flash_data = {
+-	.width		= 1,
+-	.parts		= dns323_partitions,
+-	.nr_parts	= ARRAY_SIZE(dns323_partitions)
+-};
+-
+-static struct resource dns323_nor_flash_resource = {
+-	.flags		= IORESOURCE_MEM,
+-	.start		= DNS323_NOR_BOOT_BASE,
+-	.end		= DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1,
+-};
+-
+-static struct platform_device dns323_nor_flash = {
+-	.name		= "physmap-flash",
+-	.id		= 0,
+-	.dev		= { .platform_data = &dns323_nor_flash_data, },
+-	.resource	= &dns323_nor_flash_resource,
+-	.num_resources	= 1,
+-};
+-
+-/****************************************************************************
+- * GPIO LEDs (simple - doesn't use hardware blinking support)
+- */
+-
+-static struct gpio_led dns323_leds[] = {
+-	{
+-		.name = "power:blue",
+-		.gpio = DNS323_GPIO_LED_POWER,
+-		.active_low = 1,
+-	}, {
+-		.name = "right:amber",
+-		.gpio = DNS323_GPIO_LED_RIGHT_AMBER,
+-		.active_low = 1,
+-	}, {
+-		.name = "left:amber",
+-		.gpio = DNS323_GPIO_LED_LEFT_AMBER,
+-		.active_low = 1,
+-	},
+-};
+-
+-static struct gpio_led_platform_data dns323_led_data = {
+-	.num_leds	= ARRAY_SIZE(dns323_leds),
+-	.leds		= dns323_leds,
+-};
+-
+-static struct platform_device dns323_gpio_leds = {
+-	.name		= "leds-gpio",
+-	.id		= -1,
+-	.dev		= { .platform_data = &dns323_led_data, },
+-};
+-
+-/****************************************************************************
+- * GPIO Attached Keys
+- */
+-
+-static struct gpio_keys_button dns323_buttons[] = {
+-	{
+-		.code		= KEY_RESTART,
+-		.gpio		= DNS323_GPIO_KEY_RESET,
+-		.desc		= "Reset Button",
+-		.active_low	= 1,
+-	},
+-	{
+-		.code		= KEY_POWER,
+-		.gpio		= DNS323_GPIO_KEY_POWER,
+-		.desc		= "Power Button",
+-		.active_low	= 1,
+-	}
+-};
+-
+-static struct gpio_keys_platform_data dns323_button_data = {
+-	.buttons	= dns323_buttons,
+-	.nbuttons       = ARRAY_SIZE(dns323_buttons),
+-};
+-
+-static struct platform_device dns323_button_device = {
+-	.name		= "gpio-keys",
+-	.id		= -1,
+-	.num_resources	= 0,
+-	.dev		= { .platform_data  = &dns323_button_data, },
+-};
+-
+-/****************************************************************************
+- * General Setup
+- */
+-
+-static struct platform_device *dns323_plat_devices[] __initdata = {
+-	&dns323_nor_flash,
+-	&dns323_gpio_leds,
+-	&dns323_button_device,
+-};
+-
+-/*
+- * On the DNS-323 the following devices are attached via I2C:
+- *
+- *  i2c addr | chip        | description
+- *  0x3e     | GMT G760Af  | fan speed PWM controller
+- *  0x48     | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
+- *  0x68     | ST M41T80   | RTC w/ alarm
+- */
+-static struct i2c_board_info __initdata dns323_i2c_devices[] = {
+-	{
+-		I2C_BOARD_INFO("g760a", 0x3e),
+-		.type = "g760a",
+-	},
+-#if 0
+-	/* this entry requires the new-style driver model lm75 driver,
+-	 * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
+-	{
+-		I2C_BOARD_INFO("lm75", 0x48),
+-		.type = "g751",
+-	},
+-#endif
+-	{
+-		I2C_BOARD_INFO("rtc-m41t80", 0x68),
+-		.type = "m41t80",
+-	}
+-};
+-
+-/* DNS-323 specific power off method */
+-static void dns323_power_off(void)
+-{
+-	pr_info("%s: triggering power-off...\n", __func__);
+-	gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
+-}
+-
+-static void __init dns323_init(void)
+-{
+-	/* Setup basic Orion functions. Need to be called early. */
+-	orion_init();
+-
+-	/* setup flash mapping
+-	 * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
+-	 */
+-	orion_setup_cpu_win(ORION_DEV_BOOT, DNS323_NOR_BOOT_BASE,
+-			    DNS323_NOR_BOOT_SIZE, -1);
+-
+-	/* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIE
+-	 *
+-	 * Open a special address decode windows for the PCIE WA.
+-	 */
+-	orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+-	orion_write(ORION_REGS_VIRT_BASE | 0x20070,
+-		    (0x7941 | (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
+-
+-	/* set MPP to 0 as D-Link's 2.6.12.6 kernel did */
+-	orion_write(MPP_0_7_CTRL, 0);
+-	orion_write(MPP_8_15_CTRL, 0);
+-	orion_write(MPP_16_19_CTRL, 0);
+-	orion_write(MPP_DEV_CTRL, 0);
+-
+-	/* Define used GPIO pins
+-
+-	  GPIO Map:
+-
+-	  |  0 |     | PEX_RST_OUT (not controlled by GPIO)
+-	  |  1 | Out | right amber LED (= sata ch0 LED)  (low-active)
+-	  |  2 | Out | left  amber LED (= sata ch1 LED)  (low-active)
+-	  |  3 | Out | //unknown//
+-	  |  4 | Out | power button LED (low-active, together with pin #5)
+-	  |  5 | Out | power button LED (low-active, together with pin #4)
+-	  |  6 | In  | GMT G751-2f overtemp. shutdown signal (low-active)
+-	  |  7 | In  | M41T80 nIRQ/OUT/SQW signal
+-	  |  8 | Out | triggers power off (high-active)
+-	  |  9 | In  | power button switch (low-active)
+-	  | 10 | In  | reset button switch (low-active)
+-	  | 11 | Out | //unknown//
+-	  | 12 | Out | //unknown//
+-	  | 13 | Out | //unknown//
+-	  | 14 | Out | //unknown//
+-	  | 15 | Out | //unknown//
+-	*/
+-	orion_gpio_set_valid_pins(0x07f6);
+-
+-	/* register dns323 specific power-off method */
+-	if ((gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0)
+-	    || (gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0))
+-		pr_err("DNS323: failed to setup power-off GPIO\n");
+-
+-	pm_power_off = dns323_power_off;
+-
+-	/* register flash and other platform devices */
+-	platform_add_devices(dns323_plat_devices,
+-			     ARRAY_SIZE(dns323_plat_devices));
+-
+-	i2c_register_board_info(0, dns323_i2c_devices,
+-				ARRAY_SIZE(dns323_i2c_devices));
+-
+-	orion_eth_init(&dns323_eth_data);
+-}
+-
+-/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
+-MACHINE_START(DNS323, "D-Link DNS-323")
+-	/* Maintainer: Herbert Valerio Riedel <hvr at gnu.org> */
+-	.phys_io	= ORION_REGS_PHYS_BASE,
+-	.io_pg_offst	= ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+-	.boot_params	= 0x00000100,
+-	.init_machine	= dns323_init,
+-	.map_io		= orion_map_io,
+-	.init_irq	= orion_init_irq,
+-	.timer		= &orion_timer,
+-	.fixup		= tag_fixup_mem32,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion/gpio.c b/arch/arm/mach-orion/gpio.c
+deleted file mode 100644
+index f713818..0000000
+--- a/arch/arm/mach-orion/gpio.c
++++ /dev/null
+@@ -1,225 +0,0 @@
+-/*
+- * arch/arm/mach-orion/gpio.c
+- *
+- * GPIO functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/spinlock.h>
+-#include <linux/bitops.h>
+-#include <asm/gpio.h>
+-#include <asm/arch/orion.h>
+-#include "common.h"
+-
+-static DEFINE_SPINLOCK(gpio_lock);
+-static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
+-static const char *gpio_label[GPIO_MAX];  /* non null for allocated GPIOs */
+-
+-void __init orion_gpio_set_valid_pins(u32 pins)
+-{
+-	gpio_valid[0] = pins;
+-}
+-
+-/*
+- * GENERIC_GPIO primitives
+- */
+-int gpio_direction_input(unsigned pin)
+-{
+-	unsigned long flags;
+-
+-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+-		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+-		return -EINVAL;
+-	}
+-
+-	spin_lock_irqsave(&gpio_lock, flags);
+-
+-	/*
+-	 * Some callers might have not used the gpio_request(),
+-	 * so flag this pin as requested now.
+-	 */
+-	if (!gpio_label[pin])
+-		gpio_label[pin] = "?";
+-
+-	orion_setbits(GPIO_IO_CONF, 1 << pin);
+-
+-	spin_unlock_irqrestore(&gpio_lock, flags);
+-	return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_input);
+-
+-int gpio_direction_output(unsigned pin, int value)
+-{
+-	unsigned long flags;
+-	int mask;
+-
+-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+-		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+-		return -EINVAL;
+-	}
+-
+-	spin_lock_irqsave(&gpio_lock, flags);
+-
+-	/*
+-	 * Some callers might have not used the gpio_request(),
+-	 * so flag this pin as requested now.
+-	 */
+-	if (!gpio_label[pin])
+-		gpio_label[pin] = "?";
+-
+-	mask = 1 << pin;
+-	orion_clrbits(GPIO_BLINK_EN, mask);
+-	if (value)
+-		orion_setbits(GPIO_OUT, mask);
+-	else
+-		orion_clrbits(GPIO_OUT, mask);
+-	orion_clrbits(GPIO_IO_CONF, mask);
+-
+-	spin_unlock_irqrestore(&gpio_lock, flags);
+-	return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_output);
+-
+-int gpio_get_value(unsigned pin)
+-{
+-	int val, mask = 1 << pin;
+-
+-	if (orion_read(GPIO_IO_CONF) & mask)
+-		val = orion_read(GPIO_DATA_IN) ^ orion_read(GPIO_IN_POL);
+-	else
+-		val = orion_read(GPIO_OUT);
+-
+-	return val & mask;
+-}
+-EXPORT_SYMBOL(gpio_get_value);
+-
+-void gpio_set_value(unsigned pin, int value)
+-{
+-	unsigned long flags;
+-	int mask = 1 << pin;
+-
+-	spin_lock_irqsave(&gpio_lock, flags);
+-
+-	orion_clrbits(GPIO_BLINK_EN, mask);
+-	if (value)
+-		orion_setbits(GPIO_OUT, mask);
+-	else
+-		orion_clrbits(GPIO_OUT, mask);
+-
+-	spin_unlock_irqrestore(&gpio_lock, flags);
+-}
+-EXPORT_SYMBOL(gpio_set_value);
+-
+-void orion_gpio_set_blink(unsigned pin, int blink)
+-{
+-	unsigned long flags;
+-	int mask = 1 << pin;
+-
+-	spin_lock_irqsave(&gpio_lock, flags);
+-
+-	orion_clrbits(GPIO_OUT, mask);
+-	if (blink)
+-		orion_setbits(GPIO_BLINK_EN, mask);
+-	else
+-		orion_clrbits(GPIO_BLINK_EN, mask);
+-
+-	spin_unlock_irqrestore(&gpio_lock, flags);
+-}
+-EXPORT_SYMBOL(orion_gpio_set_blink);
+-
+-int gpio_request(unsigned pin, const char *label)
+-{
+-	int ret = 0;
+-	unsigned long flags;
+-
+-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+-		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+-		return -EINVAL;
+-	}
+-
+-	spin_lock_irqsave(&gpio_lock, flags);
+-
+-	if (gpio_label[pin]) {
+-		pr_debug("%s: GPIO %d already used as %s\n",
+-			 __func__, pin, gpio_label[pin]);
+-		ret = -EBUSY;
+-	} else
+-		gpio_label[pin] = label ? label : "?";
+-
+-	spin_unlock_irqrestore(&gpio_lock, flags);
+-	return ret;
+-}
+-EXPORT_SYMBOL(gpio_request);
+-
+-void gpio_free(unsigned pin)
+-{
+-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+-		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+-		return;
+-	}
+-
+-	if (!gpio_label[pin])
+-		pr_warning("%s: GPIO %d already freed\n", __func__, pin);
+-	else
+-		gpio_label[pin] = NULL;
+-}
+-EXPORT_SYMBOL(gpio_free);
+-
+-/* Debug helper */
+-void gpio_display(void)
+-{
+-	int i;
+-
+-	for (i = 0; i < GPIO_MAX; i++) {
+-		printk(KERN_DEBUG "Pin-%d: ", i);
+-
+-		if (!test_bit(i, gpio_valid)) {
+-			printk("non-GPIO\n");
+-		} else if (!gpio_label[i]) {
+-			printk("GPIO, free\n");
+-		} else {
+-			printk("GPIO, used by %s, ", gpio_label[i]);
+-			if (orion_read(GPIO_IO_CONF) & (1 << i)) {
+-				printk("input, active %s, level %s, edge %s\n",
+-				((orion_read(GPIO_IN_POL) >> i) & 1) ? "low" : "high",
+-				((orion_read(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked",
+-				((orion_read(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked");
+-			} else {
+-				printk("output, val=%d\n", (orion_read(GPIO_OUT) >> i) & 1);
+-			}
+-		}
+-	}
+-
+-	printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n",
+-				MPP_0_7_CTRL, orion_read(MPP_0_7_CTRL));
+-	printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n",
+-				MPP_8_15_CTRL, orion_read(MPP_8_15_CTRL));
+-	printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n",
+-				MPP_16_19_CTRL, orion_read(MPP_16_19_CTRL));
+-	printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n",
+-				MPP_DEV_CTRL, orion_read(MPP_DEV_CTRL));
+-	printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n",
+-				GPIO_OUT, orion_read(GPIO_OUT));
+-	printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n",
+-				GPIO_IO_CONF, orion_read(GPIO_IO_CONF));
+-	printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n",
+-				GPIO_BLINK_EN, orion_read(GPIO_BLINK_EN));
+-	printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n",
+-				GPIO_IN_POL, orion_read(GPIO_IN_POL));
+-	printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n",
+-				GPIO_DATA_IN, orion_read(GPIO_DATA_IN));
+-	printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n",
+-				GPIO_LEVEL_MASK, orion_read(GPIO_LEVEL_MASK));
+-	printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n",
+-				GPIO_EDGE_CAUSE, orion_read(GPIO_EDGE_CAUSE));
+-	printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n",
+-				GPIO_EDGE_MASK, orion_read(GPIO_EDGE_MASK));
+-}
+diff --git a/arch/arm/mach-orion/irq.c b/arch/arm/mach-orion/irq.c
+deleted file mode 100644
+index df7e12a..0000000
+--- a/arch/arm/mach-orion/irq.c
++++ /dev/null
+@@ -1,241 +0,0 @@
+-/*
+- * arch/arm/mach-orion/irq.c
+- *
+- * Core IRQ functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
+-#include <linux/init.h>
+-#include <linux/irq.h>
+-#include <asm/gpio.h>
+-#include <asm/arch/orion.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * Orion GPIO IRQ
+- *
+- * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same
+- * value of the line or the opposite value.
+- *
+- * Level IRQ handlers: DATA_IN is used directly as cause register.
+- *                     Interrupt are masked by LEVEL_MASK registers.
+- * Edge IRQ handlers:  Change in DATA_IN are latched in EDGE_CAUSE.
+- *                     Interrupt are masked by EDGE_MASK registers.
+- * Both-edge handlers: Similar to regular Edge handlers, but also swaps
+- *                     the polarity to catch the next line transaction.
+- *                     This is a race condition that might not perfectly
+- *                     work on some use cases.
+- *
+- * Every eight GPIO lines are grouped (OR'ed) before going up to main
+- * cause register.
+- *
+- *                    EDGE  cause    mask
+- *        data-in   /--------| |-----| |----\
+- *     -----| |-----                         ---- to main cause reg
+- *           X      \----------------| |----/
+- *        polarity    LEVEL          mask
+- *
+- ****************************************************************************/
+-static void orion_gpio_irq_ack(u32 irq)
+-{
+-	int pin = irq_to_gpio(irq);
+-	if (irq_desc[irq].status & IRQ_LEVEL)
+-		/*
+-		 * Mask bit for level interrupt
+-		 */
+-		orion_clrbits(GPIO_LEVEL_MASK, 1 << pin);
+-	else
+-		/*
+-		 * Clear casue bit for egde interrupt
+-		 */
+-		orion_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
+-}
+-
+-static void orion_gpio_irq_mask(u32 irq)
+-{
+-	int pin = irq_to_gpio(irq);
+-	if (irq_desc[irq].status & IRQ_LEVEL)
+-		orion_clrbits(GPIO_LEVEL_MASK, 1 << pin);
+-	else
+-		orion_clrbits(GPIO_EDGE_MASK, 1 << pin);
+-}
+-
+-static void orion_gpio_irq_unmask(u32 irq)
+-{
+-	int pin = irq_to_gpio(irq);
+-	if (irq_desc[irq].status & IRQ_LEVEL)
+-		orion_setbits(GPIO_LEVEL_MASK, 1 << pin);
+-	else
+-		orion_setbits(GPIO_EDGE_MASK, 1 << pin);
+-}
+-
+-static int orion_gpio_set_irq_type(u32 irq, u32 type)
+-{
+-	int pin = irq_to_gpio(irq);
+-	struct irq_desc *desc;
+-
+-	if ((orion_read(GPIO_IO_CONF) & (1 << pin)) == 0) {
+-		printk(KERN_ERR "orion_gpio_set_irq_type failed "
+-				"(irq %d, pin %d).\n", irq, pin);
+-		return -EINVAL;
+-	}
+-
+-	desc = irq_desc + irq;
+-
+-	switch (type) {
+-	case IRQT_HIGH:
+-		desc->handle_irq = handle_level_irq;
+-		desc->status |= IRQ_LEVEL;
+-		orion_clrbits(GPIO_IN_POL, (1 << pin));
+-		break;
+-	case IRQT_LOW:
+-		desc->handle_irq = handle_level_irq;
+-		desc->status |= IRQ_LEVEL;
+-		orion_setbits(GPIO_IN_POL, (1 << pin));
+-		break;
+-	case IRQT_RISING:
+-		desc->handle_irq = handle_edge_irq;
+-		desc->status &= ~IRQ_LEVEL;
+-		orion_clrbits(GPIO_IN_POL, (1 << pin));
+-		break;
+-	case IRQT_FALLING:
+-		desc->handle_irq = handle_edge_irq;
+-		desc->status &= ~IRQ_LEVEL;
+-		orion_setbits(GPIO_IN_POL, (1 << pin));
+-		break;
+-	case IRQT_BOTHEDGE:
+-		desc->handle_irq = handle_edge_irq;
+-		desc->status &= ~IRQ_LEVEL;
+-		/*
+-		 * set initial polarity based on current input level
+-		 */
+-		if ((orion_read(GPIO_IN_POL) ^ orion_read(GPIO_DATA_IN))
+-		    & (1 << pin))
+-			orion_setbits(GPIO_IN_POL, (1 << pin)); /* falling */
+-		else
+-			orion_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */
+-
+-		break;
+-	default:
+-		printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
+-		return -EINVAL;
+-	}
+-
+-	desc->status &= ~IRQ_TYPE_SENSE_MASK;
+-	desc->status |= type & IRQ_TYPE_SENSE_MASK;
+-
+-	return 0;
+-}
+-
+-static struct irq_chip orion_gpio_irq_chip = {
+-	.name		= "Orion-IRQ-GPIO",
+-	.ack		= orion_gpio_irq_ack,
+-	.mask		= orion_gpio_irq_mask,
+-	.unmask		= orion_gpio_irq_unmask,
+-	.set_type	= orion_gpio_set_irq_type,
+-};
+-
+-static void orion_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+-{
+-	u32 cause, offs, pin;
+-
+-	BUG_ON(irq < IRQ_ORION_GPIO_0_7 || irq > IRQ_ORION_GPIO_24_31);
+-	offs = (irq - IRQ_ORION_GPIO_0_7) * 8;
+-	cause = (orion_read(GPIO_DATA_IN) & orion_read(GPIO_LEVEL_MASK)) |
+-		(orion_read(GPIO_EDGE_CAUSE) & orion_read(GPIO_EDGE_MASK));
+-
+-	for (pin = offs; pin < offs + 8; pin++) {
+-		if (cause & (1 << pin)) {
+-			irq = gpio_to_irq(pin);
+-			desc = irq_desc + irq;
+-			if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
+-				/* Swap polarity (race with GPIO line) */
+-				u32 polarity = orion_read(GPIO_IN_POL);
+-				polarity ^= 1 << pin;
+-				orion_write(GPIO_IN_POL, polarity);
+-			}
+-			desc_handle_irq(irq, desc);
+-		}
+-	}
+-}
+-
+-static void __init orion_init_gpio_irq(void)
+-{
+-	int i;
+-	struct irq_desc *desc;
+-
+-	/*
+-	 * Mask and clear GPIO IRQ interrupts
+-	 */
+-	orion_write(GPIO_LEVEL_MASK, 0x0);
+-	orion_write(GPIO_EDGE_MASK, 0x0);
+-	orion_write(GPIO_EDGE_CAUSE, 0x0);
+-
+-	/*
+-	 * Register chained level handlers for GPIO IRQs by default.
+-	 * User can use set_type() if he wants to use edge types handlers.
+-	 */
+-	for (i = IRQ_ORION_GPIO_START; i < NR_IRQS; i++) {
+-		set_irq_chip(i, &orion_gpio_irq_chip);
+-		set_irq_handler(i, handle_level_irq);
+-		desc = irq_desc + i;
+-		desc->status |= IRQ_LEVEL;
+-		set_irq_flags(i, IRQF_VALID);
+-	}
+-	set_irq_chained_handler(IRQ_ORION_GPIO_0_7, orion_gpio_irq_handler);
+-	set_irq_chained_handler(IRQ_ORION_GPIO_8_15, orion_gpio_irq_handler);
+-	set_irq_chained_handler(IRQ_ORION_GPIO_16_23, orion_gpio_irq_handler);
+-	set_irq_chained_handler(IRQ_ORION_GPIO_24_31, orion_gpio_irq_handler);
+-}
+-
+-/*****************************************************************************
+- * Orion Main IRQ
+- ****************************************************************************/
+-static void orion_main_irq_mask(u32 irq)
+-{
+-	orion_clrbits(MAIN_IRQ_MASK, 1 << irq);
+-}
+-
+-static void orion_main_irq_unmask(u32 irq)
+-{
+-	orion_setbits(MAIN_IRQ_MASK, 1 << irq);
+-}
+-
+-static struct irq_chip orion_main_irq_chip = {
+-	.name		= "Orion-IRQ-Main",
+-	.ack		= orion_main_irq_mask,
+-	.mask		= orion_main_irq_mask,
+-	.unmask		= orion_main_irq_unmask,
+-};
+-
+-static void __init orion_init_main_irq(void)
+-{
+-	int i;
+-
+-	/*
+-	 * Mask and clear Main IRQ interrupts
+-	 */
+-	orion_write(MAIN_IRQ_MASK, 0x0);
+-	orion_write(MAIN_IRQ_CAUSE, 0x0);
+-
+-	/*
+-	 * Register level handler for Main IRQs
+-	 */
+-	for (i = 0; i < IRQ_ORION_GPIO_START; i++) {
+-		set_irq_chip(i, &orion_main_irq_chip);
+-		set_irq_handler(i, handle_level_irq);
+-		set_irq_flags(i, IRQF_VALID);
+-	}
+-}
+-
+-void __init orion_init_irq(void)
+-{
+-	orion_init_main_irq();
+-	orion_init_gpio_irq();
+-}
+diff --git a/arch/arm/mach-orion/kurobox_pro-setup.c b/arch/arm/mach-orion/kurobox_pro-setup.c
+deleted file mode 100644
+index 785a07b..0000000
+--- a/arch/arm/mach-orion/kurobox_pro-setup.c
++++ /dev/null
+@@ -1,244 +0,0 @@
+-/*
+- * arch/arm/mach-orion/kurobox_pro-setup.c
+- *
+- * Maintainer: Ronen Shitrit <rshitrit at marvell.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/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mtd/nand.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/i2c.h>
+-#include <linux/ata_platform.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * KUROBOX-PRO Info
+- ****************************************************************************/
+-
+-/*
+- * 256K NOR flash Device bus boot chip select
+- */
+-
+-#define KUROBOX_PRO_NOR_BOOT_BASE	0xf4000000
+-#define KUROBOX_PRO_NOR_BOOT_SIZE	SZ_256K
+-
+-/*
+- * 256M NAND flash on Device bus chip select 1
+- */
+-
+-#define KUROBOX_PRO_NAND_BASE		0xfc000000
+-#define KUROBOX_PRO_NAND_SIZE		SZ_2M
+-
+-/*****************************************************************************
+- * 256MB NAND Flash on Device bus CS0
+- ****************************************************************************/
+-
+-static struct mtd_partition kurobox_pro_nand_parts[] = {
+-	{
+-		.name	= "uImage",
+-		.offset	= 0,
+-		.size	= SZ_4M,
+-	},
+-	{
+-		.name	= "rootfs",
+-		.offset	= SZ_4M,
+-		.size	= SZ_64M,
+-	},
+-	{
+-		.name	= "extra",
+-		.offset	= SZ_4M + SZ_64M,
+-		.size	= SZ_256M - (SZ_4M + SZ_64M),
+-	},
+-};
+-
+-static struct resource kurobox_pro_nand_resource = {
+-	.flags		= IORESOURCE_MEM,
+-	.start		= KUROBOX_PRO_NAND_BASE,
+-	.end		= KUROBOX_PRO_NAND_BASE + KUROBOX_PRO_NAND_SIZE - 1,
+-};
+-
+-static struct orion_nand_data kurobox_pro_nand_data = {
+-	.parts		= kurobox_pro_nand_parts,
+-	.nr_parts	= ARRAY_SIZE(kurobox_pro_nand_parts),
+-	.cle		= 0,
+-	.ale		= 1,
+-	.width		= 8,
+-};
+-
+-static struct platform_device kurobox_pro_nand_flash = {
+-	.name		= "orion_nand",
+-	.id		= -1,
+-	.dev		= {
+-		.platform_data	= &kurobox_pro_nand_data,
+-	},
+-	.resource	= &kurobox_pro_nand_resource,
+-	.num_resources	= 1,
+-};
+-
+-/*****************************************************************************
+- * 256KB NOR Flash on BOOT Device
+- ****************************************************************************/
+-
+-static struct physmap_flash_data kurobox_pro_nor_flash_data = {
+-	.width		= 1,
+-};
+-
+-static struct resource kurobox_pro_nor_flash_resource = {
+-	.flags			= IORESOURCE_MEM,
+-	.start			= KUROBOX_PRO_NOR_BOOT_BASE,
+-	.end			= KUROBOX_PRO_NOR_BOOT_BASE + KUROBOX_PRO_NOR_BOOT_SIZE - 1,
+-};
+-
+-static struct platform_device kurobox_pro_nor_flash = {
+-	.name			= "physmap-flash",
+-	.id			= 0,
+-	.dev		= {
+-		.platform_data	= &kurobox_pro_nor_flash_data,
+-	},
+-	.num_resources		= 1,
+-	.resource		= &kurobox_pro_nor_flash_resource,
+-};
+-
+-/*****************************************************************************
+- * PCI
+- ****************************************************************************/
+-
+-static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+-	/*
+-	 * PCI isn't used on the Kuro
+-	 */
+-	if (dev->bus->number == orion_pcie_local_bus_nr())
+-		return IRQ_ORION_PCIE0_INT;
+-	else
+-		printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
+-
+-	return -1;
+-}
+-
+-static struct hw_pci kurobox_pro_pci __initdata = {
+-	.nr_controllers	= 1,
+-	.swizzle	= pci_std_swizzle,
+-	.setup		= orion_pci_sys_setup,
+-	.scan		= orion_pci_sys_scan_bus,
+-	.map_irq	= kurobox_pro_pci_map_irq,
+-};
+-
+-static int __init kurobox_pro_pci_init(void)
+-{
+-	if (machine_is_kurobox_pro())
+-		pci_common_init(&kurobox_pro_pci);
+-
+-	return 0;
+-}
+-
+-subsys_initcall(kurobox_pro_pci_init);
+-
+-/*****************************************************************************
+- * Ethernet
+- ****************************************************************************/
+-
+-static struct mv643xx_eth_platform_data kurobox_pro_eth_data = {
+-	.phy_addr	= 8,
+-	.force_phy_addr = 1,
+-};
+-
+-/*****************************************************************************
+- * RTC 5C372a on I2C bus
+- ****************************************************************************/
+-static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
+-       .driver_name    = "rtc-rs5c372",
+-       .type           = "rs5c372a",
+-       .addr           = 0x32,
+-};
+-
+-/*****************************************************************************
+- * SATA
+- ****************************************************************************/
+-static struct mv_sata_platform_data kurobox_pro_sata_data = {
+-	.n_ports        = 2,
+-};
+-
+-/*****************************************************************************
+- * General Setup
+- ****************************************************************************/
+-
+-static struct platform_device *kurobox_pro_devices[] __initdata = {
+-	&kurobox_pro_nor_flash,
+-	&kurobox_pro_nand_flash,
+-};
+-
+-static void __init kurobox_pro_init(void)
+-{
+-	/*
+-	 * Setup basic Orion functions. Need to be called early.
+-	 */
+-	orion_init();
+-
+-	/*
+-	 * Setup the CPU address decode windows for our devices
+-	 */
+-	orion_setup_cpu_win(ORION_DEV_BOOT, KUROBOX_PRO_NOR_BOOT_BASE,
+-				KUROBOX_PRO_NOR_BOOT_SIZE, -1);
+-	orion_setup_cpu_win(ORION_DEV0,	KUROBOX_PRO_NAND_BASE,
+-				KUROBOX_PRO_NAND_SIZE, -1);
+-	/*
+-	 * Open a special address decode windows for the PCIE WA.
+-	 */
+-	orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+-	orion_write(ORION_REGS_VIRT_BASE | 0x20070, (0x7941 |
+-		(((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
+-
+-	/*
+-	 * Setup Multiplexing Pins --
+-	 * MPP[0-1] Not used
+-	 * MPP[2] GPIO Micon
+-	 * MPP[3] GPIO RTC
+-	 * MPP[4-5] Not used
+-	 * MPP[6] Nand Flash REn
+-	 * MPP[7] Nand Flash WEn
+-	 * MPP[8-11] Not used
+-	 * MPP[12] SATA 0 presence Indication
+-	 * MPP[13] SATA 1 presence Indication
+-	 * MPP[14] SATA 0 active Indication
+-	 * MPP[15] SATA 1 active indication
+-	 * MPP[16-19] Not used
+-	 */
+-	orion_write(MPP_0_7_CTRL, 0x44220003);
+-	orion_write(MPP_8_15_CTRL, 0x55550000);
+-	orion_write(MPP_16_19_CTRL, 0x0);
+-
+-	orion_gpio_set_valid_pins(0x0000000c);
+-
+-	platform_add_devices(kurobox_pro_devices, ARRAY_SIZE(kurobox_pro_devices));
+-	i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
+-	orion_eth_init(&kurobox_pro_eth_data);
+-	orion_sata_init(&kurobox_pro_sata_data);
+-}
+-
+-MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
+-	/* Maintainer: Ronen Shitrit <rshitrit at marvell.com> */
+-	.phys_io	= ORION_REGS_PHYS_BASE,
+-	.io_pg_offst	= ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+-	.boot_params	= 0x00000100,
+-	.init_machine	= kurobox_pro_init,
+-	.map_io		= orion_map_io,
+-	.init_irq	= orion_init_irq,
+-	.timer		= &orion_timer,
+-	.fixup		= tag_fixup_mem32,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion/pci.c b/arch/arm/mach-orion/pci.c
+deleted file mode 100644
+index b109bb4..0000000
+--- a/arch/arm/mach-orion/pci.c
++++ /dev/null
+@@ -1,557 +0,0 @@
+-/*
+- * arch/arm/mach-orion/pci.c
+- *
+- * PCI and PCIE functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
+-#include <linux/pci.h>
+-#include <asm/mach/pci.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * Orion has one PCIE controller and one PCI controller.
+- *
+- * Note1: The local PCIE bus number is '0'. The local PCI bus number
+- * follows the scanned PCIE bridged busses, if any.
+- *
+- * Note2: It is possible for PCI/PCIE agents to access many subsystem's
+- * space, by configuring BARs and Address Decode Windows, e.g. flashes on
+- * device bus, Orion registers, etc. However this code only enable the
+- * access to DDR banks.
+- ****************************************************************************/
+-
+-
+-/*****************************************************************************
+- * PCIE controller
+- ****************************************************************************/
+-#define PCIE_CTRL		ORION_PCIE_REG(0x1a00)
+-#define PCIE_STAT		ORION_PCIE_REG(0x1a04)
+-#define PCIE_DEV_ID		ORION_PCIE_REG(0x0000)
+-#define PCIE_CMD_STAT		ORION_PCIE_REG(0x0004)
+-#define PCIE_DEV_REV		ORION_PCIE_REG(0x0008)
+-#define PCIE_MASK		ORION_PCIE_REG(0x1910)
+-#define PCIE_CONF_ADDR		ORION_PCIE_REG(0x18f8)
+-#define PCIE_CONF_DATA		ORION_PCIE_REG(0x18fc)
+-
+-/*
+- * PCIE_STAT bits
+- */
+-#define PCIE_STAT_LINK_DOWN		1
+-#define PCIE_STAT_BUS_OFFS		8
+-#define PCIE_STAT_BUS_MASK		(0xff << PCIE_STAT_BUS_OFFS)
+-#define PCIE_STAT_DEV_OFFS		20
+-#define PCIE_STAT_DEV_MASK		(0x1f << PCIE_STAT_DEV_OFFS)
+-
+-/*
+- * PCIE_CONF_ADDR bits
+- */
+-#define PCIE_CONF_REG(r)		((((r) & 0xf00) << 24) | ((r) & 0xfc))
+-#define PCIE_CONF_FUNC(f)		(((f) & 0x3) << 8)
+-#define PCIE_CONF_DEV(d)		(((d) & 0x1f) << 11)
+-#define PCIE_CONF_BUS(b)		(((b) & 0xff) << 16)
+-#define PCIE_CONF_ADDR_EN		(1 << 31)
+-
+-/*
+- * PCIE config cycles are done by programming the PCIE_CONF_ADDR register
+- * and then reading the PCIE_CONF_DATA register. Need to make sure these
+- * transactions are atomic.
+- */
+-static DEFINE_SPINLOCK(orion_pcie_lock);
+-
+-void orion_pcie_id(u32 *dev, u32 *rev)
+-{
+-	*dev = orion_read(PCIE_DEV_ID) >> 16;
+-	*rev = orion_read(PCIE_DEV_REV) & 0xff;
+-}
+-
+-u32 orion_pcie_local_bus_nr(void)
+-{
+-	u32 stat = orion_read(PCIE_STAT);
+-	return((stat & PCIE_STAT_BUS_MASK) >> PCIE_STAT_BUS_OFFS);
+-}
+-
+-static u32 orion_pcie_local_dev_nr(void)
+-{
+-	u32 stat = orion_read(PCIE_STAT);
+-	return((stat & PCIE_STAT_DEV_MASK) >> PCIE_STAT_DEV_OFFS);
+-}
+-
+-static u32 orion_pcie_no_link(void)
+-{
+-	u32 stat = orion_read(PCIE_STAT);
+-	return(stat & PCIE_STAT_LINK_DOWN);
+-}
+-
+-static void orion_pcie_set_bus_nr(int nr)
+-{
+-	orion_clrbits(PCIE_STAT, PCIE_STAT_BUS_MASK);
+-	orion_setbits(PCIE_STAT, nr << PCIE_STAT_BUS_OFFS);
+-}
+-
+-static void orion_pcie_master_slave_enable(void)
+-{
+-	orion_setbits(PCIE_CMD_STAT, PCI_COMMAND_MASTER |
+-					  PCI_COMMAND_IO |
+-					  PCI_COMMAND_MEMORY);
+-}
+-
+-static void orion_pcie_enable_interrupts(void)
+-{
+-	/*
+-	 * Enable interrupts lines
+-	 * INTA[24] INTB[25] INTC[26] INTD[27]
+-	 */
+-	orion_setbits(PCIE_MASK, 0xf<<24);
+-}
+-
+-static int orion_pcie_valid_config(u32 bus, u32 dev)
+-{
+-	/*
+-	 * Don't go out when trying to access --
+-	 * 1. our own device
+-	 * 2. where there's no device connected (no link)
+-	 * 3. nonexisting devices on local bus
+-	 */
+-
+-	if ((orion_pcie_local_bus_nr() == bus) &&
+-	   (orion_pcie_local_dev_nr() == dev))
+-		return 0;
+-
+-	if (orion_pcie_no_link())
+-		return 0;
+-
+-	if (bus == orion_pcie_local_bus_nr())
+-		if (((orion_pcie_local_dev_nr() == 0) && (dev != 1)) ||
+-		   ((orion_pcie_local_dev_nr() != 0) && (dev != 0)))
+-		return 0;
+-
+-	return 1;
+-}
+-
+-static int orion_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+-						int size, u32 *val)
+-{
+-	unsigned long flags;
+-	unsigned int dev, rev, pcie_addr;
+-
+-	if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
+-		*val = 0xffffffff;
+-		return PCIBIOS_DEVICE_NOT_FOUND;
+-	}
+-
+-	spin_lock_irqsave(&orion_pcie_lock, flags);
+-
+-	orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) |
+-			PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+-			PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+-			PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN);
+-
+-	orion_pcie_id(&dev, &rev);
+-	if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
+-		/* extended register space */
+-		pcie_addr = ORION_PCIE_WA_VIRT_BASE;
+-		pcie_addr |= PCIE_CONF_BUS(bus->number) |
+-			PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+-			PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+-			PCIE_CONF_REG(where);
+-		*val = orion_read(pcie_addr);
+-	} else
+-		*val = orion_read(PCIE_CONF_DATA);
+-
+-	if (size == 1)
+-		*val = (*val >> (8*(where & 0x3))) & 0xff;
+-	else if (size == 2)
+-		*val = (*val >> (8*(where & 0x3))) & 0xffff;
+-
+-	spin_unlock_irqrestore(&orion_pcie_lock, flags);
+-
+-	return PCIBIOS_SUCCESSFUL;
+-}
+-
+-
+-static int orion_pcie_wr_conf(struct pci_bus *bus, u32 devfn, int where,
+-						int size, u32 val)
+-{
+-	unsigned long flags;
+-	int ret;
+-
+-	if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0)
+-		return PCIBIOS_DEVICE_NOT_FOUND;
+-
+-	spin_lock_irqsave(&orion_pcie_lock, flags);
+-
+-	ret = PCIBIOS_SUCCESSFUL;
+-
+-	orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) |
+-			PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+-			PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+-			PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN);
+-
+-	if (size == 4) {
+-		__raw_writel(val, PCIE_CONF_DATA);
+-	} else if (size == 2) {
+-		__raw_writew(val, PCIE_CONF_DATA + (where & 0x3));
+-	} else if (size == 1) {
+-		__raw_writeb(val, PCIE_CONF_DATA + (where & 0x3));
+-	} else {
+-		ret = PCIBIOS_BAD_REGISTER_NUMBER;
+-	}
+-
+-	spin_unlock_irqrestore(&orion_pcie_lock, flags);
+-
+-	return ret;
+-}
+-
+-struct pci_ops orion_pcie_ops = {
+-	.read = orion_pcie_rd_conf,
+-	.write = orion_pcie_wr_conf,
+-};
+-
+-
+-static int orion_pcie_setup(struct pci_sys_data *sys)
+-{
+-	struct resource *res;
+-
+-	/*
+-	 * Master + Slave enable
+-	 */
+-	orion_pcie_master_slave_enable();
+-
+-	/*
+-	 * Enable interrupts lines A-D
+-	 */
+-	orion_pcie_enable_interrupts();
+-
+-	/*
+-	 * Request resource
+-	 */
+-	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+-	if (!res)
+-		panic("orion_pci_setup unable to alloc resources");
+-
+-	/*
+-	 * IORESOURCE_IO
+-	 */
+-	res[0].name = "PCI-EX I/O Space";
+-	res[0].flags = IORESOURCE_IO;
+-	res[0].start = ORION_PCIE_IO_BUS_BASE;
+-	res[0].end = res[0].start + ORION_PCIE_IO_SIZE - 1;
+-	if (request_resource(&ioport_resource, &res[0]))
+-		panic("Request PCIE IO resource failed\n");
+-	sys->resource[0] = &res[0];
+-
+-	/*
+-	 * IORESOURCE_MEM
+-	 */
+-	res[1].name = "PCI-EX Memory Space";
+-	res[1].flags = IORESOURCE_MEM;
+-	res[1].start = ORION_PCIE_MEM_PHYS_BASE;
+-	res[1].end = res[1].start + ORION_PCIE_MEM_SIZE - 1;
+-	if (request_resource(&iomem_resource, &res[1]))
+-		panic("Request PCIE Memory resource failed\n");
+-	sys->resource[1] = &res[1];
+-
+-	sys->resource[2] = NULL;
+-	sys->io_offset = 0;
+-
+-	return 1;
+-}
+-
+-/*****************************************************************************
+- * PCI controller
+- ****************************************************************************/
+-#define PCI_MODE		ORION_PCI_REG(0xd00)
+-#define PCI_CMD			ORION_PCI_REG(0xc00)
+-#define PCI_P2P_CONF		ORION_PCI_REG(0x1d14)
+-#define PCI_CONF_ADDR		ORION_PCI_REG(0xc78)
+-#define PCI_CONF_DATA		ORION_PCI_REG(0xc7c)
+-
+-/*
+- * PCI_MODE bits
+- */
+-#define PCI_MODE_64BIT			(1 << 2)
+-#define PCI_MODE_PCIX			((1 << 4) | (1 << 5))
+-
+-/*
+- * PCI_CMD bits
+- */
+-#define PCI_CMD_HOST_REORDER		(1 << 29)
+-
+-/*
+- * PCI_P2P_CONF bits
+- */
+-#define PCI_P2P_BUS_OFFS		16
+-#define PCI_P2P_BUS_MASK		(0xff << PCI_P2P_BUS_OFFS)
+-#define PCI_P2P_DEV_OFFS		24
+-#define PCI_P2P_DEV_MASK		(0x1f << PCI_P2P_DEV_OFFS)
+-
+-/*
+- * PCI_CONF_ADDR bits
+- */
+-#define PCI_CONF_REG(reg)		((reg) & 0xfc)
+-#define PCI_CONF_FUNC(func)		(((func) & 0x3) << 8)
+-#define PCI_CONF_DEV(dev)		(((dev) & 0x1f) << 11)
+-#define PCI_CONF_BUS(bus)		(((bus) & 0xff) << 16)
+-#define PCI_CONF_ADDR_EN		(1 << 31)
+-
+-/*
+- * Internal configuration space
+- */
+-#define PCI_CONF_FUNC_STAT_CMD		0
+-#define PCI_CONF_REG_STAT_CMD		4
+-#define PCIX_STAT			0x64
+-#define PCIX_STAT_BUS_OFFS		8
+-#define PCIX_STAT_BUS_MASK		(0xff << PCIX_STAT_BUS_OFFS)
+-
+-/*
+- * PCI config cycles are done by programming the PCI_CONF_ADDR register
+- * and then reading the PCI_CONF_DATA register. Need to make sure these
+- * transactions are atomic.
+- */
+-static DEFINE_SPINLOCK(orion_pci_lock);
+-
+-u32 orion_pci_local_bus_nr(void)
+-{
+-	u32 conf = orion_read(PCI_P2P_CONF);
+-	return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
+-}
+-
+-u32 orion_pci_local_dev_nr(void)
+-{
+-	u32 conf = orion_read(PCI_P2P_CONF);
+-	return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS);
+-}
+-
+-int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func,
+-					u32 where, u32 size, u32 *val)
+-{
+-	unsigned long flags;
+-	spin_lock_irqsave(&orion_pci_lock, flags);
+-
+-	orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
+-			PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
+-			PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
+-
+-	*val = orion_read(PCI_CONF_DATA);
+-
+-	if (size == 1)
+-		*val = (*val >> (8*(where & 0x3))) & 0xff;
+-	else if (size == 2)
+-		*val = (*val >> (8*(where & 0x3))) & 0xffff;
+-
+-	spin_unlock_irqrestore(&orion_pci_lock, flags);
+-
+-	return PCIBIOS_SUCCESSFUL;
+-}
+-
+-int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func,
+-					u32 where, u32 size, u32 val)
+-{
+-	unsigned long flags;
+-	int ret = PCIBIOS_SUCCESSFUL;
+-
+-	spin_lock_irqsave(&orion_pci_lock, flags);
+-
+-	orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
+-			PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
+-			PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
+-
+-	if (size == 4) {
+-		__raw_writel(val, PCI_CONF_DATA);
+-	} else if (size == 2) {
+-		__raw_writew(val, PCI_CONF_DATA + (where & 0x3));
+-	} else if (size == 1) {
+-		__raw_writeb(val, PCI_CONF_DATA + (where & 0x3));
+-	} else {
+-		ret = PCIBIOS_BAD_REGISTER_NUMBER;
+-	}
+-
+-	spin_unlock_irqrestore(&orion_pci_lock, flags);
+-
+-	return ret;
+-}
+-
+-static int orion_pci_rd_conf(struct pci_bus *bus, u32 devfn,
+-				int where, int size, u32 *val)
+-{
+-	/*
+-	 * Don't go out for local device
+-	 */
+-	if ((orion_pci_local_bus_nr() == bus->number) &&
+-	   (orion_pci_local_dev_nr() == PCI_SLOT(devfn))) {
+-		*val = 0xffffffff;
+-		return PCIBIOS_DEVICE_NOT_FOUND;
+-	}
+-
+-	return orion_pci_hw_rd_conf(bus->number, PCI_SLOT(devfn),
+-					PCI_FUNC(devfn), where, size, val);
+-}
+-
+-static int orion_pci_wr_conf(struct pci_bus *bus, u32 devfn,
+-				int where, int size, u32 val)
+-{
+-	/*
+-	 * Don't go out for local device
+-	 */
+-	if ((orion_pci_local_bus_nr() == bus->number) &&
+-	   (orion_pci_local_dev_nr() == PCI_SLOT(devfn)))
+-		return PCIBIOS_DEVICE_NOT_FOUND;
+-
+-	return orion_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn),
+-					PCI_FUNC(devfn), where, size, val);
+-}
+-
+-struct pci_ops orion_pci_ops = {
+-	.read = orion_pci_rd_conf,
+-	.write = orion_pci_wr_conf,
+-};
+-
+-static void orion_pci_set_bus_nr(int nr)
+-{
+-	u32 p2p = orion_read(PCI_P2P_CONF);
+-
+-	if (orion_read(PCI_MODE) & PCI_MODE_PCIX) {
+-		/*
+-		 * PCI-X mode
+-		 */
+-		u32 pcix_status, bus, dev;
+-		bus = (p2p & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS;
+-		dev = (p2p & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS;
+-		orion_pci_hw_rd_conf(bus, dev, 0, PCIX_STAT, 4, &pcix_status);
+-		pcix_status &= ~PCIX_STAT_BUS_MASK;
+-		pcix_status |= (nr << PCIX_STAT_BUS_OFFS);
+-		orion_pci_hw_wr_conf(bus, dev, 0, PCIX_STAT, 4, pcix_status);
+-	} else {
+-		/*
+-		 * PCI Conventional mode
+-		 */
+-		p2p &= ~PCI_P2P_BUS_MASK;
+-		p2p |= (nr << PCI_P2P_BUS_OFFS);
+-		orion_write(PCI_P2P_CONF, p2p);
+-	}
+-}
+-
+-static void orion_pci_master_slave_enable(void)
+-{
+-	u32 bus_nr, dev_nr, func, reg, val;
+-
+-	bus_nr = orion_pci_local_bus_nr();
+-	dev_nr = orion_pci_local_dev_nr();
+-	func = PCI_CONF_FUNC_STAT_CMD;
+-	reg = PCI_CONF_REG_STAT_CMD;
+-	orion_pci_hw_rd_conf(bus_nr, dev_nr, func, reg, 4, &val);
+-	val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+-	orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7);
+-}
+-
+-static int orion_pci_setup(struct pci_sys_data *sys)
+-{
+-	struct resource *res;
+-
+-	/*
+-	 * Master + Slave enable
+-	 */
+-	orion_pci_master_slave_enable();
+-
+-	/*
+-	 * Force ordering
+-	 */
+-	orion_setbits(PCI_CMD, PCI_CMD_HOST_REORDER);
+-
+-	/*
+-	 * Request resources
+-	 */
+-	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+-	if (!res)
+-		panic("orion_pci_setup unable to alloc resources");
+-
+-	/*
+-	 * IORESOURCE_IO
+-	 */
+-	res[0].name = "PCI I/O Space";
+-	res[0].flags = IORESOURCE_IO;
+-	res[0].start = ORION_PCI_IO_BUS_BASE;
+-	res[0].end = res[0].start + ORION_PCI_IO_SIZE - 1;
+-	if (request_resource(&ioport_resource, &res[0]))
+-		panic("Request PCI IO resource failed\n");
+-	sys->resource[0] = &res[0];
+-
+-	/*
+-	 * IORESOURCE_MEM
+-	 */
+-	res[1].name = "PCI Memory Space";
+-	res[1].flags = IORESOURCE_MEM;
+-	res[1].start = ORION_PCI_MEM_PHYS_BASE;
+-	res[1].end = res[1].start + ORION_PCI_MEM_SIZE - 1;
+-	if (request_resource(&iomem_resource, &res[1]))
+-		panic("Request PCI Memory resource failed\n");
+-	sys->resource[1] = &res[1];
+-
+-	sys->resource[2] = NULL;
+-	sys->io_offset = 0;
+-
+-	return 1;
+-}
+-
+-
+-/*****************************************************************************
+- * General PCIE + PCI
+- ****************************************************************************/
+-int orion_pci_sys_setup(int nr, struct pci_sys_data *sys)
+-{
+-	int ret = 0;
+-
+-	if (nr == 0) {
+-		/*
+-		 * PCIE setup
+-		 */
+-		orion_pcie_set_bus_nr(0);
+-		ret = orion_pcie_setup(sys);
+-	} else if (nr == 1) {
+-		/*
+-		 * PCI setup
+-		 */
+-		ret = orion_pci_setup(sys);
+-	}
+-
+-	return ret;
+-}
+-
+-struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
+-{
+-	struct pci_ops *ops;
+-	struct pci_bus *bus;
+-
+-
+-	if (nr == 0) {
+-		u32 pci_bus;
+-		/*
+-		 * PCIE scan
+-		 */
+-		ops = &orion_pcie_ops;
+-		bus = pci_scan_bus(sys->busnr, ops, sys);
+-		/*
+-		 * Set local PCI bus number to follow PCIE bridges (if any)
+-		 */
+-		pci_bus	= bus->number + bus->subordinate - bus->secondary + 1;
+-		orion_pci_set_bus_nr(pci_bus);
+-	} else if (nr == 1) {
+-		/*
+-		 * PCI scan
+-		 */
+-		ops = &orion_pci_ops;
+-		bus = pci_scan_bus(sys->busnr, ops, sys);
+-	} else {
+-		BUG();
+-		bus = NULL;
+-	}
+-
+-	return bus;
+-}
+diff --git a/arch/arm/mach-orion/rd88f5182-setup.c b/arch/arm/mach-orion/rd88f5182-setup.c
+deleted file mode 100644
+index e851b8c..0000000
+--- a/arch/arm/mach-orion/rd88f5182-setup.c
++++ /dev/null
+@@ -1,315 +0,0 @@
+-/*
+- * arch/arm/mach-orion/rd88f5182-setup.c
+- *
+- * Marvell Orion-NAS Reference Design Setup
+- *
+- * Maintainer: Ronen Shitrit <rshitrit at marvell.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/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/ata_platform.h>
+-#include <linux/i2c.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/leds.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * RD-88F5182 Info
+- ****************************************************************************/
+-
+-/*
+- * 512K NOR flash Device bus boot chip select
+- */
+-
+-#define RD88F5182_NOR_BOOT_BASE		0xf4000000
+-#define RD88F5182_NOR_BOOT_SIZE		SZ_512K
+-
+-/*
+- * 16M NOR flash on Device bus chip select 1
+- */
+-
+-#define RD88F5182_NOR_BASE		0xfc000000
+-#define RD88F5182_NOR_SIZE		SZ_16M
+-
+-/*
+- * PCI
+- */
+-
+-#define RD88F5182_PCI_SLOT0_OFFS	7
+-#define RD88F5182_PCI_SLOT0_IRQ_A_PIN	7
+-#define RD88F5182_PCI_SLOT0_IRQ_B_PIN	6
+-
+-/*
+- * GPIO Debug LED
+- */
+-
+-#define RD88F5182_GPIO_DBG_LED		0
+-
+-/*****************************************************************************
+- * 16M NOR Flash on Device bus CS1
+- ****************************************************************************/
+-
+-static struct physmap_flash_data rd88f5182_nor_flash_data = {
+-	.width		= 1,
+-};
+-
+-static struct resource rd88f5182_nor_flash_resource = {
+-	.flags			= IORESOURCE_MEM,
+-	.start			= RD88F5182_NOR_BASE,
+-	.end			= RD88F5182_NOR_BASE + RD88F5182_NOR_SIZE - 1,
+-};
+-
+-static struct platform_device rd88f5182_nor_flash = {
+-	.name			= "physmap-flash",
+-	.id			= 0,
+-	.dev		= {
+-		.platform_data	= &rd88f5182_nor_flash_data,
+-	},
+-	.num_resources		= 1,
+-	.resource		= &rd88f5182_nor_flash_resource,
+-};
+-
+-#ifdef CONFIG_LEDS
+-
+-/*****************************************************************************
+- * Use GPIO debug led as CPU active indication
+- ****************************************************************************/
+-
+-static void rd88f5182_dbgled_event(led_event_t evt)
+-{
+-	int val;
+-
+-	if (evt == led_idle_end)
+-		val = 1;
+-	else if (evt == led_idle_start)
+-		val = 0;
+-	else
+-		return;
+-
+-	gpio_set_value(RD88F5182_GPIO_DBG_LED, val);
+-}
+-
+-static int __init rd88f5182_dbgled_init(void)
+-{
+-	int pin;
+-
+-	if (machine_is_rd88f5182()) {
+-		pin = RD88F5182_GPIO_DBG_LED;
+-
+-		if (gpio_request(pin, "DBGLED") == 0) {
+-			if (gpio_direction_output(pin, 0) != 0) {
+-				printk(KERN_ERR "rd88f5182_dbgled_init failed "
+-						"to set output pin %d\n", pin);
+-				gpio_free(pin);
+-				return 0;
+-			}
+-		} else {
+-			printk(KERN_ERR "rd88f5182_dbgled_init failed "
+-					"to request gpio %d\n", pin);
+-			return 0;
+-		}
+-
+-		leds_event = rd88f5182_dbgled_event;
+-	}
+-	return 0;
+-}
+-
+-__initcall(rd88f5182_dbgled_init);
+-
+-#endif
+-
+-/*****************************************************************************
+- * PCI
+- ****************************************************************************/
+-
+-void __init rd88f5182_pci_preinit(void)
+-{
+-	int pin;
+-
+-	/*
+-	 * Configure PCI GPIO IRQ pins
+-	 */
+-	pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
+-	if (gpio_request(pin, "PCI IntA") == 0) {
+-		if (gpio_direction_input(pin) == 0) {
+-			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+-		} else {
+-			printk(KERN_ERR "rd88f5182_pci_preinit faield to "
+-					"set_irq_type pin %d\n", pin);
+-			gpio_free(pin);
+-		}
+-	} else {
+-		printk(KERN_ERR "rd88f5182_pci_preinit failed to request gpio %d\n", pin);
+-	}
+-
+-	pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
+-	if (gpio_request(pin, "PCI IntB") == 0) {
+-		if (gpio_direction_input(pin) == 0) {
+-			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+-		} else {
+-			printk(KERN_ERR "rd88f5182_pci_preinit faield to "
+-					"set_irq_type pin %d\n", pin);
+-			gpio_free(pin);
+-		}
+-	} else {
+-		printk(KERN_ERR "rd88f5182_pci_preinit failed to gpio_request %d\n", pin);
+-	}
+-}
+-
+-static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+-	/*
+-	 * PCI-E isn't used on the RD2
+-	 */
+-	if (dev->bus->number == orion_pcie_local_bus_nr())
+-		return IRQ_ORION_PCIE0_INT;
+-
+-	/*
+-	 * PCI IRQs are connected via GPIOs
+-	 */
+-	switch (slot - RD88F5182_PCI_SLOT0_OFFS) {
+-	case 0:
+-		if (pin == 1)
+-			return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_A_PIN);
+-		else
+-			return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_B_PIN);
+-	default:
+-		return -1;
+-	}
+-}
+-
+-static struct hw_pci rd88f5182_pci __initdata = {
+-	.nr_controllers	= 2,
+-	.preinit	= rd88f5182_pci_preinit,
+-	.swizzle	= pci_std_swizzle,
+-	.setup		= orion_pci_sys_setup,
+-	.scan		= orion_pci_sys_scan_bus,
+-	.map_irq	= rd88f5182_pci_map_irq,
+-};
+-
+-static int __init rd88f5182_pci_init(void)
+-{
+-	if (machine_is_rd88f5182())
+-		pci_common_init(&rd88f5182_pci);
+-
+-	return 0;
+-}
+-
+-subsys_initcall(rd88f5182_pci_init);
+-
+-/*****************************************************************************
+- * Ethernet
+- ****************************************************************************/
+-
+-static struct mv643xx_eth_platform_data rd88f5182_eth_data = {
+-	.phy_addr	= 8,
+-	.force_phy_addr = 1,
+-};
+-
+-/*****************************************************************************
+- * RTC DS1338 on I2C bus
+- ****************************************************************************/
+-static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
+-	.driver_name	= "rtc-ds1307",
+-	.type		= "ds1338",
+-	.addr		= 0x68,
+-};
+-
+-/*****************************************************************************
+- * Sata
+- ****************************************************************************/
+-static struct mv_sata_platform_data rd88f5182_sata_data = {
+-	.n_ports        = 2,
+-};
+-
+-/*****************************************************************************
+- * General Setup
+- ****************************************************************************/
+-
+-static struct platform_device *rd88f5182_devices[] __initdata = {
+-	&rd88f5182_nor_flash,
+-};
+-
+-static void __init rd88f5182_init(void)
+-{
+-	/*
+-	 * Setup basic Orion functions. Need to be called early.
+-	 */
+-	orion_init();
+-
+-	/*
+-	 * Setup the CPU address decode windows for our devices
+-	 */
+-	orion_setup_cpu_win(ORION_DEV_BOOT, RD88F5182_NOR_BOOT_BASE,
+-				RD88F5182_NOR_BOOT_SIZE, -1);
+-	orion_setup_cpu_win(ORION_DEV1, RD88F5182_NOR_BASE,
+-				RD88F5182_NOR_SIZE, -1);
+-
+-	/*
+-	 * Open a special address decode windows for the PCIE WA.
+-	 */
+-	orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+-	orion_write(ORION_REGS_VIRT_BASE | 0x20070, (0x7941 |
+-		(((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
+-
+-	/*
+-	 * Setup Multiplexing Pins --
+-	 * MPP[0] Debug Led (GPIO - Out)
+-	 * MPP[1] Debug Led (GPIO - Out)
+-	 * MPP[2] N/A
+-	 * MPP[3] RTC_Int (GPIO - In)
+-	 * MPP[4] GPIO
+-	 * MPP[5] GPIO
+-	 * MPP[6] PCI_intA (GPIO - In)
+-	 * MPP[7] PCI_intB (GPIO - In)
+-	 * MPP[8-11] N/A
+-	 * MPP[12] SATA 0 presence Indication
+-	 * MPP[13] SATA 1 presence Indication
+-	 * MPP[14] SATA 0 active Indication
+-	 * MPP[15] SATA 1 active indication
+-	 * MPP[16-19] Not used
+-	 * MPP[20] PCI Clock to MV88F5182
+-	 * MPP[21] PCI Clock to mini PCI CON11
+-	 * MPP[22] USB 0 over current indication
+-	 * MPP[23] USB 1 over current indication
+-	 * MPP[24] USB 1 over current enable
+-	 * MPP[25] USB 0 over current enable
+-	 */
+-
+-	orion_write(MPP_0_7_CTRL, 0x00000003);
+-	orion_write(MPP_8_15_CTRL, 0x55550000);
+-	orion_write(MPP_16_19_CTRL, 0x5555);
+-
+-	orion_gpio_set_valid_pins(0x000000fb);
+-
+-	platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices));
+-	i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
+-	orion_eth_init(&rd88f5182_eth_data);
+-	orion_sata_init(&rd88f5182_sata_data);
+-}
+-
+-MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
+-	/* Maintainer: Ronen Shitrit <rshitrit at marvell.com> */
+-	.phys_io	= ORION_REGS_PHYS_BASE,
+-	.io_pg_offst	= ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+-	.boot_params	= 0x00000100,
+-	.init_machine	= rd88f5182_init,
+-	.map_io		= orion_map_io,
+-	.init_irq	= orion_init_irq,
+-	.timer		= &orion_timer,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion/time.c b/arch/arm/mach-orion/time.c
+deleted file mode 100644
+index bd4262d..0000000
+--- a/arch/arm/mach-orion/time.c
++++ /dev/null
+@@ -1,181 +0,0 @@
+-/*
+- * arch/arm/mach-orion/time.c
+- *
+- * Core time functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
+-#include <linux/clockchips.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <asm/mach/time.h>
+-#include <asm/arch/orion.h>
+-#include "common.h"
+-
+-/*
+- * Timer0: clock_event_device, Tick.
+- * Timer1: clocksource, Free running.
+- * WatchDog: Not used.
+- *
+- * Timers are counting down.
+- */
+-#define CLOCKEVENT	0
+-#define CLOCKSOURCE	1
+-
+-/*
+- * Timers bits
+- */
+-#define BRIDGE_INT_TIMER(x)	(1 << ((x) + 1))
+-#define TIMER_EN(x)		(1 << ((x) * 2))
+-#define TIMER_RELOAD_EN(x)	(1 << (((x) * 2) + 1))
+-#define BRIDGE_INT_TIMER_WD	(1 << 3)
+-#define TIMER_WD_EN		(1 << 4)
+-#define TIMER_WD_RELOAD_EN	(1 << 5)
+-
+-static cycle_t orion_clksrc_read(void)
+-{
+-	return (0xffffffff - orion_read(TIMER_VAL(CLOCKSOURCE)));
+-}
+-
+-static struct clocksource orion_clksrc = {
+-	.name		= "orion_clocksource",
+-	.shift		= 20,
+-	.rating		= 300,
+-	.read		= orion_clksrc_read,
+-	.mask		= CLOCKSOURCE_MASK(32),
+-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+-};
+-
+-static int
+-orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
+-{
+-	unsigned long flags;
+-
+-	if (delta == 0)
+-		return -ETIME;
+-
+-	local_irq_save(flags);
+-
+-	/*
+-	 * Clear and enable timer interrupt bit
+-	 */
+-	orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+-	orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT));
+-
+-	/*
+-	 * Setup new timer value
+-	 */
+-	orion_write(TIMER_VAL(CLOCKEVENT), delta);
+-
+-	/*
+-	 * Disable auto reload and kickoff the timer
+-	 */
+-	orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT));
+-	orion_setbits(TIMER_CTRL, TIMER_EN(CLOCKEVENT));
+-
+-	local_irq_restore(flags);
+-
+-	return 0;
+-}
+-
+-static void
+-orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+-{
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-
+-	if (mode == CLOCK_EVT_MODE_PERIODIC) {
+-		/*
+-		 * Setup latch cycles in timer and enable reload interrupt.
+-		 */
+-		orion_write(TIMER_VAL_RELOAD(CLOCKEVENT), LATCH);
+-		orion_write(TIMER_VAL(CLOCKEVENT), LATCH);
+-		orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT));
+-		orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) |
+-					  TIMER_EN(CLOCKEVENT));
+-	} else {
+-		/*
+-		 * Disable timer and interrupt
+-		 */
+-		orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT));
+-		orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+-		orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) |
+-					  TIMER_EN(CLOCKEVENT));
+-	}
+-
+-	local_irq_restore(flags);
+-}
+-
+-static struct clock_event_device orion_clkevt = {
+-	.name		= "orion_tick",
+-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+-	.shift		= 32,
+-	.rating		= 300,
+-	.cpumask	= CPU_MASK_CPU0,
+-	.set_next_event	= orion_clkevt_next_event,
+-	.set_mode	= orion_clkevt_mode,
+-};
+-
+-static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
+-{
+-	/*
+-	 * Clear cause bit and do event
+-	 */
+-	orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+-	orion_clkevt.event_handler(&orion_clkevt);
+-	return IRQ_HANDLED;
+-}
+-
+-static struct irqaction orion_timer_irq = {
+-	.name		= "orion_tick",
+-	.flags		= IRQF_DISABLED | IRQF_TIMER,
+-	.handler	= orion_timer_interrupt
+-};
+-
+-static void orion_timer_init(void)
+-{
+-	/*
+-	 * Setup clocksource free running timer (no interrupt on reload)
+-	 */
+-	orion_write(TIMER_VAL(CLOCKSOURCE), 0xffffffff);
+-	orion_write(TIMER_VAL_RELOAD(CLOCKSOURCE), 0xffffffff);
+-	orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKSOURCE));
+-	orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKSOURCE) |
+-				  TIMER_EN(CLOCKSOURCE));
+-
+-	/*
+-	 * Register clocksource
+-	 */
+-	orion_clksrc.mult =
+-		clocksource_hz2mult(CLOCK_TICK_RATE, orion_clksrc.shift);
+-
+-	clocksource_register(&orion_clksrc);
+-
+-	/*
+-	 * Connect and enable tick handler
+-	 */
+-	setup_irq(IRQ_ORION_BRIDGE, &orion_timer_irq);
+-
+-	/*
+-	 * Register clockevent
+-	 */
+-	orion_clkevt.mult =
+-		div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, orion_clkevt.shift);
+-	orion_clkevt.max_delta_ns =
+-		clockevent_delta2ns(0xfffffffe, &orion_clkevt);
+-	orion_clkevt.min_delta_ns =
+-		clockevent_delta2ns(1, &orion_clkevt);
+-
+-	clockevents_register_device(&orion_clkevt);
+-}
+-
+-struct sys_timer orion_timer = {
+-	.init = orion_timer_init,
+-};
+diff --git a/arch/arm/mach-orion/ts209-setup.c b/arch/arm/mach-orion/ts209-setup.c
+deleted file mode 100644
+index 45764da..0000000
+--- a/arch/arm/mach-orion/ts209-setup.c
++++ /dev/null
+@@ -1,361 +0,0 @@
+-/*
+- * QNAP TS-109/TS-209 Board Setup
+- *
+- * Maintainer: Byron Bradley <byron.bbradley at gmail.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mtd/nand.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/gpio_keys.h>
+-#include <linux/input.h>
+-#include <linux/i2c.h>
+-#include <linux/serial_reg.h>
+-#include <linux/ata_platform.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-#define QNAP_TS209_NOR_BOOT_BASE 0xf4000000
+-#define QNAP_TS209_NOR_BOOT_SIZE SZ_8M
+-
+-/****************************************************************************
+- * 8MiB NOR flash. The struct mtd_partition is not in the same order as the
+- *     partitions on the device because we want to keep compatability with
+- *     existing QNAP firmware.
+- *
+- * Layout as used by QNAP:
+- *  [2] 0x00000000-0x00200000 : "Kernel"
+- *  [3] 0x00200000-0x00600000 : "RootFS1"
+- *  [4] 0x00600000-0x00700000 : "RootFS2"
+- *  [6] 0x00700000-0x00760000 : "NAS Config" (read-only)
+- *  [5] 0x00760000-0x00780000 : "U-Boot Config"
+- *  [1] 0x00780000-0x00800000 : "U-Boot" (read-only)
+- ***************************************************************************/
+-static struct mtd_partition qnap_ts209_partitions[] = {
+-	{
+-		.name       = "U-Boot",
+-		.size       = 0x00080000,
+-		.offset     = 0x00780000,
+-		.mask_flags = MTD_WRITEABLE,
+-	}, {
+-		.name   = "Kernel",
+-		.size   = 0x00200000,
+-		.offset = 0,
+-	}, {
+-		.name   = "RootFS1",
+-		.size   = 0x00400000,
+-		.offset = 0x00200000,
+-	}, {
+-		.name   = "RootFS2",
+-		.size   = 0x00100000,
+-		.offset = 0x00600000,
+-	}, {
+-		.name   = "U-Boot Config",
+-		.size   = 0x00020000,
+-		.offset = 0x00760000,
+-	}, {
+-		.name       = "NAS Config",
+-		.size       = 0x00060000,
+-		.offset     = 0x00700000,
+-		.mask_flags = MTD_WRITEABLE,
+-	}
+-};
+-
+-static struct physmap_flash_data qnap_ts209_nor_flash_data = {
+-	.width    = 1,
+-	.parts    = qnap_ts209_partitions,
+-	.nr_parts = ARRAY_SIZE(qnap_ts209_partitions)
+-};
+-
+-static struct resource qnap_ts209_nor_flash_resource = {
+-	.flags = IORESOURCE_MEM,
+-	.start = QNAP_TS209_NOR_BOOT_BASE,
+-	.end   = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1,
+-};
+-
+-static struct platform_device qnap_ts209_nor_flash = {
+-	.name          = "physmap-flash",
+-	.id            = 0,
+-	.dev           = { .platform_data = &qnap_ts209_nor_flash_data, },
+-	.resource      = &qnap_ts209_nor_flash_resource,
+-	.num_resources = 1,
+-};
+-
+-/*****************************************************************************
+- * PCI
+- ****************************************************************************/
+-
+-#define QNAP_TS209_PCI_SLOT0_OFFS	7
+-#define QNAP_TS209_PCI_SLOT0_IRQ_PIN	6
+-#define QNAP_TS209_PCI_SLOT1_IRQ_PIN	7
+-
+-void __init qnap_ts209_pci_preinit(void)
+-{
+-	int pin;
+-
+-	/*
+-	 * Configure PCI GPIO IRQ pins
+-	 */
+-	pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
+-	if (gpio_request(pin, "PCI Int1") == 0) {
+-		if (gpio_direction_input(pin) == 0) {
+-			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+-		} else {
+-			printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
+-					"set_irq_type pin %d\n", pin);
+-			gpio_free(pin);
+-		}
+-	} else {
+-		printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
+-				"%d\n", pin);
+-	}
+-
+-	pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
+-	if (gpio_request(pin, "PCI Int2") == 0) {
+-		if (gpio_direction_input(pin) == 0) {
+-			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+-		} else {
+-			printk(KERN_ERR "qnap_ts209_pci_preinit failed "
+-					"to set_irq_type pin %d\n", pin);
+-			gpio_free(pin);
+-		}
+-	} else {
+-		printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
+-				"%d\n", pin);
+-	}
+-}
+-
+-static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+-	/*
+-	 * PCIE IRQ is connected internally (not GPIO)
+-	 */
+-	if (dev->bus->number == orion_pcie_local_bus_nr())
+-		return IRQ_ORION_PCIE0_INT;
+-
+-	/*
+-	 * PCI IRQs are connected via GPIOs
+-	 */
+-	switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) {
+-	case 0:
+-		return gpio_to_irq(QNAP_TS209_PCI_SLOT0_IRQ_PIN);
+-	case 1:
+-		return gpio_to_irq(QNAP_TS209_PCI_SLOT1_IRQ_PIN);
+-	default:
+-		return -1;
+-	}
+-}
+-
+-static struct hw_pci qnap_ts209_pci __initdata = {
+-	.nr_controllers = 2,
+-	.preinit        = qnap_ts209_pci_preinit,
+-	.swizzle        = pci_std_swizzle,
+-	.setup          = orion_pci_sys_setup,
+-	.scan           = orion_pci_sys_scan_bus,
+-	.map_irq        = qnap_ts209_pci_map_irq,
+-};
+-
+-static int __init qnap_ts209_pci_init(void)
+-{
+-	if (machine_is_ts_x09())
+-		pci_common_init(&qnap_ts209_pci);
+-
+-	return 0;
+-}
+-
+-subsys_initcall(qnap_ts209_pci_init);
+-
+-/*****************************************************************************
+- * Ethernet
+- ****************************************************************************/
+-
+-static struct mv643xx_eth_platform_data qnap_ts209_eth_data = {
+-	.phy_addr       = 8,
+-	.force_phy_addr = 1,
+-};
+-
+-/*****************************************************************************
+- * RTC S35390A on I2C bus
+- ****************************************************************************/
+-
+-#define TS209_RTC_GPIO	3
+-
+-static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
+-       .driver_name = "rtc-s35390a",
+-       .addr        = 0x30,
+-       .irq         = 0,
+-};
+-
+-/****************************************************************************
+- * GPIO Attached Keys
+- *     Power button is attached to the PIC microcontroller
+- ****************************************************************************/
+-
+-#define QNAP_TS209_GPIO_KEY_MEDIA	1
+-#define QNAP_TS209_GPIO_KEY_RESET	2
+-
+-static struct gpio_keys_button qnap_ts209_buttons[] = {
+-	{
+-		.code		= KEY_RESTART,
+-		.gpio		= QNAP_TS209_GPIO_KEY_MEDIA,
+-		.desc		= "USB Copy Button",
+-		.active_low	= 1,
+-	},
+-	{
+-		.code		= KEY_POWER,
+-		.gpio		= QNAP_TS209_GPIO_KEY_RESET,
+-		.desc		= "Reset Button",
+-		.active_low	= 1,
+-	}
+-};
+-
+-static struct gpio_keys_platform_data qnap_ts209_button_data = {
+-	.buttons	= qnap_ts209_buttons,
+-	.nbuttons       = ARRAY_SIZE(qnap_ts209_buttons),
+-};
+-
+-static struct platform_device qnap_ts209_button_device = {
+-	.name		= "gpio-keys",
+-	.id		= -1,
+-	.num_resources	= 0,
+-	.dev		= { .platform_data  = &qnap_ts209_button_data, },
+-};
+-
+-/*****************************************************************************
+- * SATA
+- ****************************************************************************/
+-static struct mv_sata_platform_data qnap_ts209_sata_data = {
+-	.n_ports        = 2,
+-};
+-
+-/*****************************************************************************
+-
+- * General Setup
+- ****************************************************************************/
+-
+-static struct platform_device *qnap_ts209_devices[] __initdata = {
+-	&qnap_ts209_nor_flash,
+-	&qnap_ts209_button_device,
+-};
+-
+-/*
+- * QNAP TS-[12]09 specific power off method via UART1-attached PIC
+- */
+-
+-#define UART1_REG(x)  (UART1_VIRT_BASE + ((UART_##x) << 2))
+-
+-static void qnap_ts209_power_off(void)
+-{
+-	/* 19200 baud divisor */
+-	const unsigned divisor = ((ORION_TCLK + (8 * 19200)) / (16 * 19200));
+-
+-	pr_info("%s: triggering power-off...\n", __func__);
+-
+-	/* hijack uart1 and reset into sane state (19200,8n1) */
+-	orion_write(UART1_REG(LCR), 0x83);
+-	orion_write(UART1_REG(DLL), divisor & 0xff);
+-	orion_write(UART1_REG(DLM), (divisor >> 8) & 0xff);
+-	orion_write(UART1_REG(LCR), 0x03);
+-	orion_write(UART1_REG(IER), 0x00);
+-	orion_write(UART1_REG(FCR), 0x00);
+-	orion_write(UART1_REG(MCR), 0x00);
+-
+-	/* send the power-off command 'A' to PIC */
+-	orion_write(UART1_REG(TX), 'A');
+-}
+-
+-static void __init qnap_ts209_init(void)
+-{
+-	/*
+-	 * Setup basic Orion functions. Need to be called early.
+-	 */
+-	orion_init();
+-
+-	/*
+-	 * Setup flash mapping
+-	 */
+-	orion_setup_cpu_win(ORION_DEV_BOOT, QNAP_TS209_NOR_BOOT_BASE,
+-			    QNAP_TS209_NOR_BOOT_SIZE, -1);
+-
+-	/*
+-	 * Open a special address decode windows for the PCIE WA.
+-	 */
+-	orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+-	orion_write(ORION_REGS_VIRT_BASE | 0x20070, (0x7941 |
+-		(((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
+-
+-	/*
+-	 * Setup Multiplexing Pins --
+-	 * MPP[0] Reserved
+-	 * MPP[1] USB copy button (0 active)
+-	 * MPP[2] Load defaults button (0 active)
+-	 * MPP[3] GPIO RTC
+-	 * MPP[4-5] Reserved
+-	 * MPP[6] PCI Int A
+-	 * MPP[7] PCI Int B
+-	 * MPP[8-11] Reserved
+-	 * MPP[12] SATA 0 presence
+-	 * MPP[13] SATA 1 presence
+-	 * MPP[14] SATA 0 active
+-	 * MPP[15] SATA 1 active
+-	 * MPP[16] UART1 RXD
+-	 * MPP[17] UART1 TXD
+-	 * MPP[18] SW_RST (0 active)
+-	 * MPP[19] Reserved
+-	 * MPP[20] PCI clock 0
+-	 * MPP[21] PCI clock 1
+-	 * MPP[22] USB 0 over current
+-	 * MPP[23-25] Reserved
+-	 */
+-	orion_write(MPP_0_7_CTRL, 0x3);
+-	orion_write(MPP_8_15_CTRL, 0x55550000);
+-	orion_write(MPP_16_19_CTRL, 0x5500);
+-	orion_gpio_set_valid_pins(0x3cc0fff);
+-
+-	/* register ts209 specific power-off method */
+-	pm_power_off = qnap_ts209_power_off;
+-
+-	platform_add_devices(qnap_ts209_devices,
+-				ARRAY_SIZE(qnap_ts209_devices));
+-
+-	/* Get RTC IRQ and register the chip */
+-	if (gpio_request(TS209_RTC_GPIO, "rtc") == 0) {
+-		if (gpio_direction_input(TS209_RTC_GPIO) == 0)
+-			qnap_ts209_i2c_rtc.irq = gpio_to_irq(TS209_RTC_GPIO);
+-		else
+-			gpio_free(TS209_RTC_GPIO);
+-	}
+-	if (qnap_ts209_i2c_rtc.irq == 0)
+-		pr_warning("qnap_ts209_init: failed to get RTC IRQ\n");
+-	i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);
+-
+-	orion_eth_init(&qnap_ts209_eth_data);
+-	orion_sata_init(&qnap_ts209_sata_data);
+-}
+-
+-MACHINE_START(TS209, "QNAP TS-109/TS-209")
+-	/* Maintainer:  Byron Bradley <byron.bbradley at gmail.com> */
+-	.phys_io	= ORION_REGS_PHYS_BASE,
+-	.io_pg_offst	= ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+-	.boot_params	= 0x00000100,
+-	.init_machine	= qnap_ts209_init,
+-	.map_io		= orion_map_io,
+-	.init_irq	= orion_init_irq,
+-	.timer		= &orion_timer,
+-	.fixup		= tag_fixup_mem32,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
+new file mode 100644
+index 0000000..93debf3
+--- /dev/null
++++ b/arch/arm/mach-orion5x/Kconfig
+@@ -0,0 +1,49 @@
++if ARCH_ORION5X
++
++menu "Orion Implementations"
++
++config MACH_DB88F5281
++	bool "Marvell Orion-2 Development Board"
++	select I2C_BOARDINFO
++	help
++	  Say 'Y' here if you want your kernel to support the
++	  Marvell Orion-2 (88F5281) Development Board
++
++config MACH_RD88F5182
++	bool "Marvell Orion-NAS Reference Design"
++	select I2C_BOARDINFO
++	help
++	  Say 'Y' here if you want your kernel to support the
++	  Marvell Orion-NAS (88F5182) RD2
++
++config MACH_KUROBOX_PRO
++	bool "KuroBox Pro"
++	select I2C_BOARDINFO
++	help
++	  Say 'Y' here if you want your kernel to support the
++	  KuroBox Pro platform.
++
++config MACH_DNS323
++	bool "D-Link DNS-323"
++	select I2C_BOARDINFO
++	help
++	  Say 'Y' here if you want your kernel to support the
++	  D-Link DNS-323 platform.
++
++config MACH_TS209
++	bool "QNAP TS-109/TS-209"
++	help
++	  Say 'Y' here if you want your kernel to support the
++	  QNAP TS-109/TS-209 platform.
++
++config MACH_LINKSTATION_PRO
++	bool "Buffalo Linkstation Pro/Live"
++	select I2C_BOARDINFO
++	help
++	  Say 'Y' here if you want your kernel to support the
++	  Buffalo Linkstation Pro/Live platform. Both v1 and
++	  v2 devices are supported.
++
++endmenu
++
++endif
+diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
+new file mode 100644
+index 0000000..9301bf5
+--- /dev/null
++++ b/arch/arm/mach-orion5x/Makefile
+@@ -0,0 +1,7 @@
++obj-y				+= common.o addr-map.o pci.o gpio.o irq.o
++obj-$(CONFIG_MACH_DB88F5281)	+= db88f5281-setup.o
++obj-$(CONFIG_MACH_RD88F5182)	+= rd88f5182-setup.o
++obj-$(CONFIG_MACH_KUROBOX_PRO)	+= kurobox_pro-setup.o
++obj-$(CONFIG_MACH_LINKSTATION_PRO) += kurobox_pro-setup.o
++obj-$(CONFIG_MACH_DNS323)	+= dns323-setup.o
++obj-$(CONFIG_MACH_TS209)	+= ts209-setup.o
+diff --git a/arch/arm/mach-orion5x/Makefile.boot b/arch/arm/mach-orion5x/Makefile.boot
+new file mode 100644
+index 0000000..67039c3
+--- /dev/null
++++ b/arch/arm/mach-orion5x/Makefile.boot
+@@ -0,0 +1,3 @@
++   zreladdr-y	:= 0x00008000
++params_phys-y	:= 0x00000100
++initrd_phys-y	:= 0x00800000
+diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c
+new file mode 100644
+index 0000000..6b17937
+--- /dev/null
++++ b/arch/arm/mach-orion5x/addr-map.c
+@@ -0,0 +1,240 @@
++/*
++ * arch/arm/mach-orion5x/addr-map.c
++ *
++ * Address map functions for Marvell Orion 5x SoCs
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
++#include <linux/init.h>
++#include <linux/mbus.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include "common.h"
++
++/*
++ * The Orion has fully programable address map. There's a separate address
++ * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB,
++ * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
++ * address decode windows that allow it to access any of the Orion resources.
++ *
++ * CPU address decoding --
++ * Linux assumes that it is the boot loader that already setup the access to
++ * DDR and internal registers.
++ * Setup access to PCI and PCI-E IO/MEM space is issued by this file.
++ * Setup access to various devices located on the device bus interface (e.g.
++ * flashes, RTC, etc) should be issued by machine-setup.c according to
++ * specific board population (by using orion5x_setup_*_win()).
++ *
++ * Non-CPU Masters address decoding --
++ * Unlike the CPU, we setup the access from Orion's master interfaces to DDR
++ * banks only (the typical use case).
++ * Setup access for each master to DDR is issued by common.c.
++ *
++ * Note: although orion_setbits() and orion_clrbits() are not atomic
++ * no locking is necessary here since code in this file is only called
++ * at boot time when there is no concurrency issues.
++ */
++
++/*
++ * Generic Address Decode Windows bit settings
++ */
++#define TARGET_DDR		0
++#define TARGET_DEV_BUS		1
++#define TARGET_PCI		3
++#define TARGET_PCIE		4
++#define ATTR_DDR_CS(n)		(((n) ==0) ? 0xe :	\
++				((n) == 1) ? 0xd :	\
++				((n) == 2) ? 0xb :	\
++				((n) == 3) ? 0x7 : 0xf)
++#define ATTR_PCIE_MEM		0x59
++#define ATTR_PCIE_IO		0x51
++#define ATTR_PCIE_WA		0x79
++#define ATTR_PCI_MEM		0x59
++#define ATTR_PCI_IO		0x51
++#define ATTR_DEV_CS0		0x1e
++#define ATTR_DEV_CS1		0x1d
++#define ATTR_DEV_CS2		0x1b
++#define ATTR_DEV_BOOT		0xf
++#define WIN_EN			1
++
++/*
++ * Helpers to get DDR bank info
++ */
++#define DDR_BASE_CS(n)		ORION5X_DDR_REG(0x1500 + ((n) * 8))
++#define DDR_SIZE_CS(n)		ORION5X_DDR_REG(0x1504 + ((n) * 8))
++#define DDR_MAX_CS		4
++#define DDR_REG_TO_SIZE(reg)	(((reg) | 0xffffff) + 1)
++#define DDR_REG_TO_BASE(reg)	((reg) & 0xff000000)
++#define DDR_BANK_EN		1
++
++/*
++ * CPU Address Decode Windows registers
++ */
++#define CPU_WIN_CTRL(n)		ORION5X_BRIDGE_REG(0x000 | ((n) << 4))
++#define CPU_WIN_BASE(n)		ORION5X_BRIDGE_REG(0x004 | ((n) << 4))
++#define CPU_WIN_REMAP_LO(n)	ORION5X_BRIDGE_REG(0x008 | ((n) << 4))
++#define CPU_WIN_REMAP_HI(n)	ORION5X_BRIDGE_REG(0x00c | ((n) << 4))
++
++/*
++ * Gigabit Ethernet Address Decode Windows registers
++ */
++#define ETH_WIN_BASE(win)	ORION5X_ETH_REG(0x200 + ((win) * 8))
++#define ETH_WIN_SIZE(win)	ORION5X_ETH_REG(0x204 + ((win) * 8))
++#define ETH_WIN_REMAP(win)	ORION5X_ETH_REG(0x280 + ((win) * 4))
++#define ETH_WIN_EN		ORION5X_ETH_REG(0x290)
++#define ETH_WIN_PROT		ORION5X_ETH_REG(0x294)
++#define ETH_MAX_WIN		6
++#define ETH_MAX_REMAP_WIN	4
++
++
++struct mbus_dram_target_info orion5x_mbus_dram_info;
++
++static int __init orion5x_cpu_win_can_remap(int win)
++{
++	u32 dev, rev;
++
++	orion5x_pcie_id(&dev, &rev);
++	if ((dev == MV88F5281_DEV_ID && win < 4)
++	    || (dev == MV88F5182_DEV_ID && win < 2)
++	    || (dev == MV88F5181_DEV_ID && win < 2))
++		return 1;
++
++	return 0;
++}
++
++static void __init setup_cpu_win(int win, u32 base, u32 size,
++				 u8 target, u8 attr, int remap)
++{
++	orion5x_write(CPU_WIN_BASE(win), base & 0xffff0000);
++	orion5x_write(CPU_WIN_CTRL(win),
++		((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1);
++
++	if (orion5x_cpu_win_can_remap(win)) {
++		if (remap < 0)
++			remap = base;
++
++		orion5x_write(CPU_WIN_REMAP_LO(win), remap & 0xffff0000);
++		orion5x_write(CPU_WIN_REMAP_HI(win), 0);
++	}
++}
++
++void __init orion5x_setup_cpu_mbus_bridge(void)
++{
++	int i;
++	int cs;
++
++	/*
++	 * First, disable and clear windows.
++	 */
++	for (i = 0; i < 8; i++) {
++		orion5x_write(CPU_WIN_BASE(i), 0);
++		orion5x_write(CPU_WIN_CTRL(i), 0);
++		if (orion5x_cpu_win_can_remap(i)) {
++			orion5x_write(CPU_WIN_REMAP_LO(i), 0);
++			orion5x_write(CPU_WIN_REMAP_HI(i), 0);
++		}
++	}
++
++	/*
++	 * Setup windows for PCI+PCIe IO+MEM space.
++	 */
++	setup_cpu_win(0, ORION5X_PCIE_IO_PHYS_BASE, ORION5X_PCIE_IO_SIZE,
++		TARGET_PCIE, ATTR_PCIE_IO, ORION5X_PCIE_IO_BUS_BASE);
++	setup_cpu_win(1, ORION5X_PCI_IO_PHYS_BASE, ORION5X_PCI_IO_SIZE,
++		TARGET_PCI, ATTR_PCI_IO, ORION5X_PCI_IO_BUS_BASE);
++	setup_cpu_win(2, ORION5X_PCIE_MEM_PHYS_BASE, ORION5X_PCIE_MEM_SIZE,
++		TARGET_PCIE, ATTR_PCIE_MEM, -1);
++	setup_cpu_win(3, ORION5X_PCI_MEM_PHYS_BASE, ORION5X_PCI_MEM_SIZE,
++		TARGET_PCI, ATTR_PCI_MEM, -1);
++
++	/*
++	 * Setup MBUS dram target info.
++	 */
++	orion5x_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
++
++	for (i = 0, cs = 0; i < 4; i++) {
++		u32 base = readl(DDR_BASE_CS(i));
++		u32 size = readl(DDR_SIZE_CS(i));
++
++		/*
++		 * Chip select enabled?
++		 */
++		if (size & 1) {
++			struct mbus_dram_window *w;
++
++			w = &orion5x_mbus_dram_info.cs[cs++];
++			w->cs_index = i;
++			w->mbus_attr = 0xf & ~(1 << i);
++			w->base = base & 0xff000000;
++			w->size = (size | 0x00ffffff) + 1;
++		}
++	}
++	orion5x_mbus_dram_info.num_cs = cs;
++}
++
++void __init orion5x_setup_dev_boot_win(u32 base, u32 size)
++{
++	setup_cpu_win(4, base, size, TARGET_DEV_BUS, ATTR_DEV_BOOT, -1);
++}
++
++void __init orion5x_setup_dev0_win(u32 base, u32 size)
++{
++	setup_cpu_win(5, base, size, TARGET_DEV_BUS, ATTR_DEV_CS0, -1);
++}
++
++void __init orion5x_setup_dev1_win(u32 base, u32 size)
++{
++	setup_cpu_win(6, base, size, TARGET_DEV_BUS, ATTR_DEV_CS1, -1);
++}
++
++void __init orion5x_setup_dev2_win(u32 base, u32 size)
++{
++	setup_cpu_win(7, base, size, TARGET_DEV_BUS, ATTR_DEV_CS2, -1);
++}
++
++void __init orion5x_setup_pcie_wa_win(u32 base, u32 size)
++{
++	setup_cpu_win(7, base, size, TARGET_PCIE, ATTR_PCIE_WA, -1);
++}
++
++void __init orion5x_setup_eth_wins(void)
++{
++	int i;
++
++	/*
++	 * First, disable and clear windows
++	 */
++	for (i = 0; i < ETH_MAX_WIN; i++) {
++		orion5x_write(ETH_WIN_BASE(i), 0);
++		orion5x_write(ETH_WIN_SIZE(i), 0);
++		orion5x_setbits(ETH_WIN_EN, 1 << i);
++		orion5x_clrbits(ETH_WIN_PROT, 0x3 << (i * 2));
++		if (i < ETH_MAX_REMAP_WIN)
++			orion5x_write(ETH_WIN_REMAP(i), 0);
++	}
++
++	/*
++	 * Setup windows for DDR banks.
++	 */
++	for (i = 0; i < DDR_MAX_CS; i++) {
++		u32 base, size;
++		size = orion5x_read(DDR_SIZE_CS(i));
++		base = orion5x_read(DDR_BASE_CS(i));
++		if (size & DDR_BANK_EN) {
++			base = DDR_REG_TO_BASE(base);
++			size = DDR_REG_TO_SIZE(size);
++			orion5x_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000);
++			orion5x_write(ETH_WIN_BASE(i), (base & 0xffff0000) |
++					(ATTR_DDR_CS(i) << 8) |
++					TARGET_DDR);
++			orion5x_clrbits(ETH_WIN_EN, 1 << i);
++			orion5x_setbits(ETH_WIN_PROT, 0x3 << (i * 2));
++		}
++	}
++}
+diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
+new file mode 100644
+index 0000000..439c778
+--- /dev/null
++++ b/arch/arm/mach-orion5x/common.c
+@@ -0,0 +1,391 @@
++/*
++ * arch/arm/mach-orion5x/common.c
++ *
++ * Core functions for Marvell Orion 5x SoCs
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/serial_8250.h>
++#include <linux/mbus.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/mv643xx_i2c.h>
++#include <linux/ata_platform.h>
++#include <asm/page.h>
++#include <asm/setup.h>
++#include <asm/timex.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/time.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/orion5x.h>
++#include <asm/plat-orion/ehci-orion.h>
++#include <asm/plat-orion/orion_nand.h>
++#include <asm/plat-orion/time.h>
++#include "common.h"
++
++/*****************************************************************************
++ * I/O Address Mapping
++ ****************************************************************************/
++static struct map_desc orion5x_io_desc[] __initdata = {
++	{
++		.virtual	= ORION5X_REGS_VIRT_BASE,
++		.pfn		= __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
++		.length		= ORION5X_REGS_SIZE,
++		.type		= MT_DEVICE
++	},
++	{
++		.virtual	= ORION5X_PCIE_IO_VIRT_BASE,
++		.pfn		= __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
++		.length		= ORION5X_PCIE_IO_SIZE,
++		.type		= MT_DEVICE
++	},
++	{
++		.virtual	= ORION5X_PCI_IO_VIRT_BASE,
++		.pfn		= __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
++		.length		= ORION5X_PCI_IO_SIZE,
++		.type		= MT_DEVICE
++	},
++	{
++		.virtual	= ORION5X_PCIE_WA_VIRT_BASE,
++		.pfn		= __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
++		.length		= ORION5X_PCIE_WA_SIZE,
++		.type		= MT_DEVICE
++	},
++};
++
++void __init orion5x_map_io(void)
++{
++	iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
++}
++
++/*****************************************************************************
++ * UART
++ ****************************************************************************/
++
++static struct resource orion5x_uart_resources[] = {
++	{
++		.start		= UART0_PHYS_BASE,
++		.end		= UART0_PHYS_BASE + 0xff,
++		.flags		= IORESOURCE_MEM,
++	},
++	{
++		.start		= IRQ_ORION5X_UART0,
++		.end		= IRQ_ORION5X_UART0,
++		.flags		= IORESOURCE_IRQ,
++	},
++	{
++		.start		= UART1_PHYS_BASE,
++		.end		= UART1_PHYS_BASE + 0xff,
++		.flags		= IORESOURCE_MEM,
++	},
++	{
++		.start		= IRQ_ORION5X_UART1,
++		.end		= IRQ_ORION5X_UART1,
++		.flags		= IORESOURCE_IRQ,
++	},
++};
++
++static struct plat_serial8250_port orion5x_uart_data[] = {
++	{
++		.mapbase	= UART0_PHYS_BASE,
++		.membase	= (char *)UART0_VIRT_BASE,
++		.irq		= IRQ_ORION5X_UART0,
++		.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++		.iotype		= UPIO_MEM,
++		.regshift	= 2,
++		.uartclk	= ORION5X_TCLK,
++	},
++	{
++		.mapbase	= UART1_PHYS_BASE,
++		.membase	= (char *)UART1_VIRT_BASE,
++		.irq		= IRQ_ORION5X_UART1,
++		.flags		= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++		.iotype		= UPIO_MEM,
++		.regshift	= 2,
++		.uartclk	= ORION5X_TCLK,
++	},
++	{ },
++};
++
++static struct platform_device orion5x_uart = {
++	.name			= "serial8250",
++	.id			= PLAT8250_DEV_PLATFORM,
++	.dev			= {
++		.platform_data	= orion5x_uart_data,
++	},
++	.resource		= orion5x_uart_resources,
++	.num_resources		= ARRAY_SIZE(orion5x_uart_resources),
++};
++
++/*******************************************************************************
++ * USB Controller - 2 interfaces
++ ******************************************************************************/
++
++static struct resource orion5x_ehci0_resources[] = {
++	{
++		.start	= ORION5X_USB0_PHYS_BASE,
++		.end	= ORION5X_USB0_PHYS_BASE + SZ_4K,
++		.flags	= IORESOURCE_MEM,
++	},
++	{
++		.start	= IRQ_ORION5X_USB0_CTRL,
++		.end	= IRQ_ORION5X_USB0_CTRL,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct resource orion5x_ehci1_resources[] = {
++	{
++		.start	= ORION5X_USB1_PHYS_BASE,
++		.end	= ORION5X_USB1_PHYS_BASE + SZ_4K,
++		.flags	= IORESOURCE_MEM,
++	},
++	{
++		.start	= IRQ_ORION5X_USB1_CTRL,
++		.end	= IRQ_ORION5X_USB1_CTRL,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct orion_ehci_data orion5x_ehci_data = {
++	.dram		= &orion5x_mbus_dram_info,
++};
++
++static u64 ehci_dmamask = 0xffffffffUL;
++
++static struct platform_device orion5x_ehci0 = {
++	.name		= "orion-ehci",
++	.id		= 0,
++	.dev		= {
++		.dma_mask		= &ehci_dmamask,
++		.coherent_dma_mask	= 0xffffffff,
++		.platform_data		= &orion5x_ehci_data,
++	},
++	.resource	= orion5x_ehci0_resources,
++	.num_resources	= ARRAY_SIZE(orion5x_ehci0_resources),
++};
++
++static struct platform_device orion5x_ehci1 = {
++	.name		= "orion-ehci",
++	.id		= 1,
++	.dev		= {
++		.dma_mask		= &ehci_dmamask,
++		.coherent_dma_mask	= 0xffffffff,
++		.platform_data		= &orion5x_ehci_data,
++	},
++	.resource	= orion5x_ehci1_resources,
++	.num_resources	= ARRAY_SIZE(orion5x_ehci1_resources),
++};
++
++/*****************************************************************************
++ * Gigabit Ethernet port
++ * (The Orion and Discovery (MV643xx) families use the same Ethernet driver)
++ ****************************************************************************/
++
++static struct resource orion5x_eth_shared_resources[] = {
++	{
++		.start	= ORION5X_ETH_PHYS_BASE + 0x2000,
++		.end	= ORION5X_ETH_PHYS_BASE + 0x3fff,
++		.flags	= IORESOURCE_MEM,
++	},
++};
++
++static struct platform_device orion5x_eth_shared = {
++	.name		= MV643XX_ETH_SHARED_NAME,
++	.id		= 0,
++	.num_resources	= 1,
++	.resource	= orion5x_eth_shared_resources,
++};
++
++static struct resource orion5x_eth_resources[] = {
++	{
++		.name	= "eth irq",
++		.start	= IRQ_ORION5X_ETH_SUM,
++		.end	= IRQ_ORION5X_ETH_SUM,
++		.flags	= IORESOURCE_IRQ,
++	}
++};
++
++static struct platform_device orion5x_eth = {
++	.name		= MV643XX_ETH_NAME,
++	.id		= 0,
++	.num_resources	= 1,
++	.resource	= orion5x_eth_resources,
++};
++
++void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
++{
++	orion5x_eth.dev.platform_data = eth_data;
++	platform_device_register(&orion5x_eth_shared);
++	platform_device_register(&orion5x_eth);
++}
++
++/*****************************************************************************
++ * I2C controller
++ * (The Orion and Discovery (MV643xx) families share the same I2C controller)
++ ****************************************************************************/
++
++static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = {
++	.freq_m		= 8, /* assumes 166 MHz TCLK */
++	.freq_n		= 3,
++	.timeout	= 1000, /* Default timeout of 1 second */
++};
++
++static struct resource orion5x_i2c_resources[] = {
++	{
++		.name   = "i2c base",
++		.start  = I2C_PHYS_BASE,
++		.end    = I2C_PHYS_BASE + 0x20 -1,
++		.flags  = IORESOURCE_MEM,
++	},
++	{
++		.name   = "i2c irq",
++		.start  = IRQ_ORION5X_I2C,
++		.end    = IRQ_ORION5X_I2C,
++		.flags  = IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device orion5x_i2c = {
++	.name		= MV64XXX_I2C_CTLR_NAME,
++	.id		= 0,
++	.num_resources	= ARRAY_SIZE(orion5x_i2c_resources),
++	.resource	= orion5x_i2c_resources,
++	.dev		= {
++		.platform_data = &orion5x_i2c_pdata,
++	},
++};
++
++/*****************************************************************************
++ * Sata port
++ ****************************************************************************/
++static struct resource orion5x_sata_resources[] = {
++        {
++                .name   = "sata base",
++                .start  = ORION5X_SATA_PHYS_BASE,
++                .end    = ORION5X_SATA_PHYS_BASE + 0x5000 - 1,
++                .flags  = IORESOURCE_MEM,
++        },
++	{
++                .name   = "sata irq",
++                .start  = IRQ_ORION5X_SATA,
++                .end    = IRQ_ORION5X_SATA,
++                .flags  = IORESOURCE_IRQ,
++        },
++};
++
++static struct platform_device orion5x_sata = {
++	.name           = "sata_mv",
++	.id             = 0,
++	.dev		= {
++		.coherent_dma_mask	= 0xffffffff,
++	},
++	.num_resources  = ARRAY_SIZE(orion5x_sata_resources),
++	.resource       = orion5x_sata_resources,
++};
++
++void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
++{
++	sata_data->dram = &orion5x_mbus_dram_info;
++	orion5x_sata.dev.platform_data = sata_data;
++	platform_device_register(&orion5x_sata);
++}
++
++/*****************************************************************************
++ * Time handling
++ ****************************************************************************/
++
++static void orion5x_timer_init(void)
++{
++	orion_time_init(IRQ_ORION5X_BRIDGE, ORION5X_TCLK);
++}
++
++struct sys_timer orion5x_timer = {
++        .init = orion5x_timer_init,
++};
++
++/*****************************************************************************
++ * General
++ ****************************************************************************/
++
++/*
++ * Identify device ID and rev from PCIE configuration header space '0'.
++ */
++static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
++{
++	orion5x_pcie_id(dev, rev);
++
++	if (*dev == MV88F5281_DEV_ID) {
++		if (*rev == MV88F5281_REV_D2) {
++			*dev_name = "MV88F5281-D2";
++		} else if (*rev == MV88F5281_REV_D1) {
++			*dev_name = "MV88F5281-D1";
++		} else {
++			*dev_name = "MV88F5281-Rev-Unsupported";
++		}
++	} else if (*dev == MV88F5182_DEV_ID) {
++		if (*rev == MV88F5182_REV_A2) {
++			*dev_name = "MV88F5182-A2";
++		} else {
++			*dev_name = "MV88F5182-Rev-Unsupported";
++		}
++	} else if (*dev == MV88F5181_DEV_ID) {
++		if (*rev == MV88F5181_REV_B1) {
++			*dev_name = "MV88F5181-Rev-B1";
++		} else {
++			*dev_name = "MV88F5181-Rev-Unsupported";
++		}
++	} else {
++		*dev_name = "Device-Unknown";
++	}
++}
++
++void __init orion5x_init(void)
++{
++	char *dev_name;
++	u32 dev, rev;
++
++	orion5x_id(&dev, &rev, &dev_name);
++	printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION5X_TCLK);
++
++	/*
++	 * Setup Orion address map
++	 */
++	orion5x_setup_cpu_mbus_bridge();
++	orion5x_setup_eth_wins();
++
++	/*
++	 * Register devices.
++	 */
++	platform_device_register(&orion5x_uart);
++	platform_device_register(&orion5x_ehci0);
++	if (dev == MV88F5182_DEV_ID)
++		platform_device_register(&orion5x_ehci1);
++	platform_device_register(&orion5x_i2c);
++}
++
++/*
++ * Many orion-based systems have buggy bootloader implementations.
++ * This is a common fixup for bogus memory tags.
++ */
++void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
++			    char **from, struct meminfo *meminfo)
++{
++	for (; t->hdr.size; t = tag_next(t))
++		if (t->hdr.tag == ATAG_MEM &&
++		    (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
++		     t->u.mem.start & ~PAGE_MASK)) {
++			printk(KERN_WARNING
++			       "Clearing invalid memory bank %dKB at 0x%08x\n",
++			       t->u.mem.size / 1024, t->u.mem.start);
++			t->hdr.tag = 0;
++		}
++}
+diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
+new file mode 100644
+index 0000000..f4c4c9a
+--- /dev/null
++++ b/arch/arm/mach-orion5x/common.h
+@@ -0,0 +1,72 @@
++#ifndef __ARCH_ORION5X_COMMON_H
++#define __ARCH_ORION5X_COMMON_H
++
++/*
++ * Basic Orion init functions used early by machine-setup.
++ */
++
++void orion5x_map_io(void);
++void orion5x_init_irq(void);
++void orion5x_init(void);
++extern struct sys_timer orion5x_timer;
++
++/*
++ * Enumerations and functions for Orion windows mapping. Used by Orion core
++ * functions to map its interfaces and by the machine-setup to map its on-
++ * board devices. Details in /mach-orion/addr-map.c
++ */
++extern struct mbus_dram_target_info orion5x_mbus_dram_info;
++void orion5x_setup_cpu_mbus_bridge(void);
++void orion5x_setup_dev_boot_win(u32 base, u32 size);
++void orion5x_setup_dev0_win(u32 base, u32 size);
++void orion5x_setup_dev1_win(u32 base, u32 size);
++void orion5x_setup_dev2_win(u32 base, u32 size);
++void orion5x_setup_pcie_wa_win(u32 base, u32 size);
++void orion5x_setup_eth_wins(void);
++
++/*
++ * Shared code used internally by other Orion core functions.
++ * (/mach-orion/pci.c)
++ */
++
++struct pci_sys_data;
++struct pci_bus;
++
++void orion5x_pcie_id(u32 *dev, u32 *rev);
++int orion5x_pcie_local_bus_nr(void);
++int orion5x_pci_local_bus_nr(void);
++int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
++struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
++
++/*
++ * Valid GPIO pins according to MPP setup, used by machine-setup.
++ * (/mach-orion/gpio.c).
++ */
++
++void orion5x_gpio_set_valid_pins(u32 pins);
++void gpio_display(void);	/* debug */
++
++/*
++ * Pull in Orion Ethernet platform_data, used by machine-setup
++ */
++
++struct mv643xx_eth_platform_data;
++
++void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data);
++
++/*
++ * Orion Sata platform_data, used by machine-setup
++ */
++
++struct mv_sata_platform_data;
++
++void orion5x_sata_init(struct mv_sata_platform_data *sata_data);
++
++struct machine_desc;
++struct meminfo;
++struct tag;
++extern void __init tag_fixup_mem32(struct machine_desc *, struct tag *,
++				   char **, struct meminfo *);
++
++
++#endif
+diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
+new file mode 100644
+index 0000000..872aed3
+--- /dev/null
++++ b/arch/arm/mach-orion5x/db88f5281-setup.c
+@@ -0,0 +1,361 @@
++/*
++ * arch/arm/mach-orion5x/db88f5281-setup.c
++ *
++ * Marvell Orion-2 Development Board Setup
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mtd/nand.h>
++#include <linux/timer.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/i2c.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include <asm/plat-orion/orion_nand.h>
++#include "common.h"
++
++/*****************************************************************************
++ * DB-88F5281 on board devices
++ ****************************************************************************/
++
++/*
++ * 512K NOR flash Device bus boot chip select
++ */
++
++#define DB88F5281_NOR_BOOT_BASE		0xf4000000
++#define DB88F5281_NOR_BOOT_SIZE		SZ_512K
++
++/*
++ * 7-Segment on Device bus chip select 0
++ */
++
++#define DB88F5281_7SEG_BASE		0xfa000000
++#define DB88F5281_7SEG_SIZE		SZ_1K
++
++/*
++ * 32M NOR flash on Device bus chip select 1
++ */
++
++#define DB88F5281_NOR_BASE		0xfc000000
++#define DB88F5281_NOR_SIZE		SZ_32M
++
++/*
++ * 32M NAND flash on Device bus chip select 2
++ */
++
++#define DB88F5281_NAND_BASE		0xfa800000
++#define DB88F5281_NAND_SIZE		SZ_1K
++
++/*
++ * PCI
++ */
++
++#define DB88F5281_PCI_SLOT0_OFFS		7
++#define DB88F5281_PCI_SLOT0_IRQ_PIN		12
++#define DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN	13
++
++/*****************************************************************************
++ * 512M NOR Flash on Device bus Boot CS
++ ****************************************************************************/
++
++static struct physmap_flash_data db88f5281_boot_flash_data = {
++	.width		= 1,	/* 8 bit bus width */
++};
++
++static struct resource db88f5281_boot_flash_resource = {
++	.flags		= IORESOURCE_MEM,
++	.start		= DB88F5281_NOR_BOOT_BASE,
++	.end		= DB88F5281_NOR_BOOT_BASE + DB88F5281_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device db88f5281_boot_flash = {
++	.name		= "physmap-flash",
++	.id		= 0,
++	.dev		= {
++		.platform_data = &db88f5281_boot_flash_data,
++	},
++	.num_resources	= 1,
++	.resource	= &db88f5281_boot_flash_resource,
++};
++
++/*****************************************************************************
++ * 32M NOR Flash on Device bus CS1
++ ****************************************************************************/
++
++static struct physmap_flash_data db88f5281_nor_flash_data = {
++	.width		= 4,	/* 32 bit bus width */
++};
++
++static struct resource db88f5281_nor_flash_resource = {
++	.flags		= IORESOURCE_MEM,
++	.start		= DB88F5281_NOR_BASE,
++	.end		= DB88F5281_NOR_BASE + DB88F5281_NOR_SIZE - 1,
++};
++
++static struct platform_device db88f5281_nor_flash = {
++	.name		= "physmap-flash",
++	.id		= 1,
++	.dev		= {
++		.platform_data = &db88f5281_nor_flash_data,
++	},
++	.num_resources	= 1,
++	.resource	= &db88f5281_nor_flash_resource,
++};
++
++/*****************************************************************************
++ * 32M NAND Flash on Device bus CS2
++ ****************************************************************************/
++
++static struct mtd_partition db88f5281_nand_parts[] = {
++	{
++		.name = "kernel",
++		.offset = 0,
++		.size = SZ_2M,
++	},
++	{
++		.name = "root",
++		.offset = SZ_2M,
++		.size = (SZ_16M - SZ_2M),
++	},
++	{
++		.name = "user",
++		.offset = SZ_16M,
++		.size = SZ_8M,
++	},
++	{
++		.name = "recovery",
++		.offset = (SZ_16M + SZ_8M),
++		.size = SZ_8M,
++	},
++};
++
++static struct resource db88f5281_nand_resource = {
++	.flags		= IORESOURCE_MEM,
++	.start		= DB88F5281_NAND_BASE,
++	.end		= DB88F5281_NAND_BASE + DB88F5281_NAND_SIZE - 1,
++};
++
++static struct orion_nand_data db88f5281_nand_data = {
++	.parts		= db88f5281_nand_parts,
++	.nr_parts	= ARRAY_SIZE(db88f5281_nand_parts),
++	.cle		= 0,
++	.ale		= 1,
++	.width		= 8,
++};
++
++static struct platform_device db88f5281_nand_flash = {
++	.name		= "orion_nand",
++	.id		= -1,
++	.dev		= {
++		.platform_data	= &db88f5281_nand_data,
++	},
++	.resource	= &db88f5281_nand_resource,
++	.num_resources	= 1,
++};
++
++/*****************************************************************************
++ * 7-Segment on Device bus CS0
++ * Dummy counter every 2 sec
++ ****************************************************************************/
++
++static void __iomem *db88f5281_7seg;
++static struct timer_list db88f5281_timer;
++
++static void db88f5281_7seg_event(unsigned long data)
++{
++	static int count = 0;
++	writel(0, db88f5281_7seg + (count << 4));
++	count = (count + 1) & 7;
++	mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
++}
++
++static int __init db88f5281_7seg_init(void)
++{
++	if (machine_is_db88f5281()) {
++		db88f5281_7seg = ioremap(DB88F5281_7SEG_BASE,
++					DB88F5281_7SEG_SIZE);
++		if (!db88f5281_7seg) {
++			printk(KERN_ERR "Failed to ioremap db88f5281_7seg\n");
++			return -EIO;
++		}
++		setup_timer(&db88f5281_timer, db88f5281_7seg_event, 0);
++		mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
++	}
++
++	return 0;
++}
++
++__initcall(db88f5281_7seg_init);
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++void __init db88f5281_pci_preinit(void)
++{
++	int pin;
++
++	/*
++	 * Configure PCI GPIO IRQ pins
++	 */
++	pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
++	if (gpio_request(pin, "PCI Int1") == 0) {
++		if (gpio_direction_input(pin) == 0) {
++			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++		} else {
++			printk(KERN_ERR "db88f5281_pci_preinit faield to "
++					"set_irq_type pin %d\n", pin);
++			gpio_free(pin);
++		}
++	} else {
++		printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
++	}
++
++	pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
++	if (gpio_request(pin, "PCI Int2") == 0) {
++		if (gpio_direction_input(pin) == 0) {
++			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++		} else {
++			printk(KERN_ERR "db88f5281_pci_preinit faield "
++					"to set_irq_type pin %d\n", pin);
++			gpio_free(pin);
++		}
++	} else {
++		printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
++	}
++}
++
++static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++	/*
++	 * PCIE IRQ is connected internally (not GPIO)
++	 */
++	if (dev->bus->number == orion5x_pcie_local_bus_nr())
++		return IRQ_ORION5X_PCIE0_INT;
++
++	/*
++	 * PCI IRQs are connected via GPIOs
++	 */
++	switch (slot - DB88F5281_PCI_SLOT0_OFFS) {
++	case 0:
++		return gpio_to_irq(DB88F5281_PCI_SLOT0_IRQ_PIN);
++	case 1:
++	case 2:
++		return gpio_to_irq(DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN);
++	default:
++		return -1;
++	}
++}
++
++static struct hw_pci db88f5281_pci __initdata = {
++	.nr_controllers	= 2,
++	.preinit	= db88f5281_pci_preinit,
++	.swizzle	= pci_std_swizzle,
++	.setup		= orion5x_pci_sys_setup,
++	.scan		= orion5x_pci_sys_scan_bus,
++	.map_irq	= db88f5281_pci_map_irq,
++};
++
++static int __init db88f5281_pci_init(void)
++{
++	if (machine_is_db88f5281())
++		pci_common_init(&db88f5281_pci);
++
++	return 0;
++}
++
++subsys_initcall(db88f5281_pci_init);
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++static struct mv643xx_eth_platform_data db88f5281_eth_data = {
++	.phy_addr	= 8,
++	.force_phy_addr = 1,
++};
++
++/*****************************************************************************
++ * RTC DS1339 on I2C bus
++ ****************************************************************************/
++static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
++	.driver_name	= "rtc-ds1307",
++	.type		= "ds1339",
++	.addr		= 0x68,
++};
++
++/*****************************************************************************
++ * General Setup
++ ****************************************************************************/
++
++static struct platform_device *db88f5281_devs[] __initdata = {
++	&db88f5281_boot_flash,
++	&db88f5281_nor_flash,
++	&db88f5281_nand_flash,
++};
++
++static void __init db88f5281_init(void)
++{
++	/*
++	 * Basic Orion setup. Need to be called early.
++	 */
++	orion5x_init();
++
++	/*
++	 * Setup the CPU address decode windows for our on-board devices
++	 */
++	orion5x_setup_dev_boot_win(DB88F5281_NOR_BOOT_BASE,
++				DB88F5281_NOR_BOOT_SIZE);
++	orion5x_setup_dev0_win(DB88F5281_7SEG_BASE, DB88F5281_7SEG_SIZE);
++	orion5x_setup_dev1_win(DB88F5281_NOR_BASE, DB88F5281_NOR_SIZE);
++	orion5x_setup_dev2_win(DB88F5281_NAND_BASE, DB88F5281_NAND_SIZE);
++
++	/*
++	 * Setup Multiplexing Pins:
++	 * MPP0: GPIO (USB Over Current)	MPP1: GPIO (USB Vbat input)
++	 * MPP2: PCI_REQn[2]			MPP3: PCI_GNTn[2]
++	 * MPP4: PCI_REQn[3]			MPP5: PCI_GNTn[3]
++	 * MPP6: GPIO (JP0, CON17.2)		MPP7: GPIO (JP1, CON17.1)
++	 * MPP8: GPIO (JP2, CON11.2)		MPP9: GPIO (JP3, CON11.3)
++	 * MPP10: GPIO (RTC int)		MPP11: GPIO (Baud Rate Generator)
++	 * MPP12: GPIO (PCI int 1)		MPP13: GPIO (PCI int 2)
++	 * MPP14: NAND_REn[2]			MPP15: NAND_WEn[2]
++	 * MPP16: UART1_RX			MPP17: UART1_TX
++	 * MPP18: UART1_CTS			MPP19: UART1_RTS
++	 * MPP-DEV: DEV_D[16:31]
++	 */
++	orion5x_write(MPP_0_7_CTRL, 0x00222203);
++	orion5x_write(MPP_8_15_CTRL, 0x44000000);
++	orion5x_write(MPP_16_19_CTRL, 0);
++	orion5x_write(MPP_DEV_CTRL, 0);
++
++	orion5x_gpio_set_valid_pins(0x00003fc3);
++
++	platform_add_devices(db88f5281_devs, ARRAY_SIZE(db88f5281_devs));
++	i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
++	orion5x_eth_init(&db88f5281_eth_data);
++}
++
++MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
++	/* Maintainer: Tzachi Perelstein <tzachi at 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,
++	.init_irq	= orion5x_init_irq,
++	.timer		= &orion5x_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
+new file mode 100644
+index 0000000..d67790e
+--- /dev/null
++++ b/arch/arm/mach-orion5x/dns323-setup.c
+@@ -0,0 +1,320 @@
++/*
++ * arch/arm/mach-orion5x/dns323-setup.c
++ *
++ * Copyright (C) 2007 Herbert Valerio Riedel <hvr at gnu.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/leds.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
++#include <linux/i2c.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++
++#define DNS323_GPIO_LED_RIGHT_AMBER	1
++#define DNS323_GPIO_LED_LEFT_AMBER	2
++#define DNS323_GPIO_LED_POWER		5
++#define DNS323_GPIO_OVERTEMP		6
++#define DNS323_GPIO_RTC			7
++#define DNS323_GPIO_POWER_OFF		8
++#define DNS323_GPIO_KEY_POWER		9
++#define DNS323_GPIO_KEY_RESET		10
++
++/****************************************************************************
++ * PCI setup
++ */
++
++static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++	/* PCI-E */
++	if (dev->bus->number == orion5x_pcie_local_bus_nr())
++		return IRQ_ORION5X_PCIE0_INT;
++
++	pr_err("%s: requested mapping for unknown bus\n", __func__);
++
++	return -1;
++}
++
++static struct hw_pci dns323_pci __initdata = {
++	.nr_controllers = 1,
++	.swizzle	= pci_std_swizzle,
++	.setup		= orion5x_pci_sys_setup,
++	.scan		= orion5x_pci_sys_scan_bus,
++	.map_irq	= dns323_pci_map_irq,
++};
++
++static int __init dns323_pci_init(void)
++{
++	if (machine_is_dns323())
++		pci_common_init(&dns323_pci);
++
++	return 0;
++}
++
++subsys_initcall(dns323_pci_init);
++
++/****************************************************************************
++ * Ethernet
++ */
++
++static struct mv643xx_eth_platform_data dns323_eth_data = {
++	.phy_addr = 8,
++	.force_phy_addr = 1,
++};
++
++/****************************************************************************
++ * 8MiB NOR flash (Spansion S29GL064M90TFIR4)
++ *
++ * Layout as used by D-Link:
++ *  0x00000000-0x00010000 : "MTD1"
++ *  0x00010000-0x00020000 : "MTD2"
++ *  0x00020000-0x001a0000 : "Linux Kernel"
++ *  0x001a0000-0x007d0000 : "File System"
++ *  0x007d0000-0x00800000 : "u-boot"
++ */
++
++#define DNS323_NOR_BOOT_BASE 0xf4000000
++#define DNS323_NOR_BOOT_SIZE SZ_8M
++
++static struct mtd_partition dns323_partitions[] = {
++	{
++		.name	= "MTD1",
++		.size	= 0x00010000,
++		.offset	= 0,
++	}, {
++		.name	= "MTD2",
++		.size	= 0x00010000,
++		.offset = 0x00010000,
++	}, {
++		.name	= "Linux Kernel",
++		.size	= 0x00180000,
++		.offset	= 0x00020000,
++	}, {
++		.name	= "File System",
++		.size	= 0x00630000,
++		.offset	= 0x001A0000,
++	}, {
++		.name	= "u-boot",
++		.size	= 0x00030000,
++		.offset	= 0x007d0000,
++	}
++};
++
++static struct physmap_flash_data dns323_nor_flash_data = {
++	.width		= 1,
++	.parts		= dns323_partitions,
++	.nr_parts	= ARRAY_SIZE(dns323_partitions)
++};
++
++static struct resource dns323_nor_flash_resource = {
++	.flags		= IORESOURCE_MEM,
++	.start		= DNS323_NOR_BOOT_BASE,
++	.end		= DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device dns323_nor_flash = {
++	.name		= "physmap-flash",
++	.id		= 0,
++	.dev		= { .platform_data = &dns323_nor_flash_data, },
++	.resource	= &dns323_nor_flash_resource,
++	.num_resources	= 1,
++};
++
++/****************************************************************************
++ * GPIO LEDs (simple - doesn't use hardware blinking support)
++ */
++
++static struct gpio_led dns323_leds[] = {
++	{
++		.name = "power:blue",
++		.gpio = DNS323_GPIO_LED_POWER,
++		.active_low = 1,
++	}, {
++		.name = "right:amber",
++		.gpio = DNS323_GPIO_LED_RIGHT_AMBER,
++		.active_low = 1,
++	}, {
++		.name = "left:amber",
++		.gpio = DNS323_GPIO_LED_LEFT_AMBER,
++		.active_low = 1,
++	},
++};
++
++static struct gpio_led_platform_data dns323_led_data = {
++	.num_leds	= ARRAY_SIZE(dns323_leds),
++	.leds		= dns323_leds,
++};
++
++static struct platform_device dns323_gpio_leds = {
++	.name		= "leds-gpio",
++	.id		= -1,
++	.dev		= { .platform_data = &dns323_led_data, },
++};
++
++/****************************************************************************
++ * GPIO Attached Keys
++ */
++
++static struct gpio_keys_button dns323_buttons[] = {
++	{
++		.code		= KEY_RESTART,
++		.gpio		= DNS323_GPIO_KEY_RESET,
++		.desc		= "Reset Button",
++		.active_low	= 1,
++	},
++	{
++		.code		= KEY_POWER,
++		.gpio		= DNS323_GPIO_KEY_POWER,
++		.desc		= "Power Button",
++		.active_low	= 1,
++	}
++};
++
++static struct gpio_keys_platform_data dns323_button_data = {
++	.buttons	= dns323_buttons,
++	.nbuttons       = ARRAY_SIZE(dns323_buttons),
++};
++
++static struct platform_device dns323_button_device = {
++	.name		= "gpio-keys",
++	.id		= -1,
++	.num_resources	= 0,
++	.dev		= { .platform_data  = &dns323_button_data, },
++};
++
++/****************************************************************************
++ * General Setup
++ */
++
++static struct platform_device *dns323_plat_devices[] __initdata = {
++	&dns323_nor_flash,
++	&dns323_gpio_leds,
++	&dns323_button_device,
++};
++
++/*
++ * On the DNS-323 the following devices are attached via I2C:
++ *
++ *  i2c addr | chip        | description
++ *  0x3e     | GMT G760Af  | fan speed PWM controller
++ *  0x48     | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
++ *  0x68     | ST M41T80   | RTC w/ alarm
++ */
++static struct i2c_board_info __initdata dns323_i2c_devices[] = {
++	{
++		I2C_BOARD_INFO("g760a", 0x3e),
++		.type = "g760a",
++	},
++#if 0
++	/* this entry requires the new-style driver model lm75 driver,
++	 * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
++	{
++		I2C_BOARD_INFO("lm75", 0x48),
++		.type = "g751",
++	},
++#endif
++	{
++		I2C_BOARD_INFO("rtc-m41t80", 0x68),
++		.type = "m41t80",
++	}
++};
++
++/* DNS-323 specific power off method */
++static void dns323_power_off(void)
++{
++	pr_info("%s: triggering power-off...\n", __func__);
++	gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
++}
++
++static void __init dns323_init(void)
++{
++	/* Setup basic Orion functions. Need to be called early. */
++	orion5x_init();
++
++	/* setup flash mapping
++	 * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
++	 */
++	orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE);
++
++	/* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIE
++	 *
++	 * Open a special address decode windows for the PCIE WA.
++	 */
++	orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
++				ORION5X_PCIE_WA_SIZE);
++
++	/* set MPP to 0 as D-Link's 2.6.12.6 kernel did */
++	orion5x_write(MPP_0_7_CTRL, 0);
++	orion5x_write(MPP_8_15_CTRL, 0);
++	orion5x_write(MPP_16_19_CTRL, 0);
++	orion5x_write(MPP_DEV_CTRL, 0);
++
++	/* Define used GPIO pins
++
++	  GPIO Map:
++
++	  |  0 |     | PEX_RST_OUT (not controlled by GPIO)
++	  |  1 | Out | right amber LED (= sata ch0 LED)  (low-active)
++	  |  2 | Out | left  amber LED (= sata ch1 LED)  (low-active)
++	  |  3 | Out | //unknown//
++	  |  4 | Out | power button LED (low-active, together with pin #5)
++	  |  5 | Out | power button LED (low-active, together with pin #4)
++	  |  6 | In  | GMT G751-2f overtemp. shutdown signal (low-active)
++	  |  7 | In  | M41T80 nIRQ/OUT/SQW signal
++	  |  8 | Out | triggers power off (high-active)
++	  |  9 | In  | power button switch (low-active)
++	  | 10 | In  | reset button switch (low-active)
++	  | 11 | Out | //unknown//
++	  | 12 | Out | //unknown//
++	  | 13 | Out | //unknown//
++	  | 14 | Out | //unknown//
++	  | 15 | Out | //unknown//
++	*/
++	orion5x_gpio_set_valid_pins(0x07f6);
++
++	/* register dns323 specific power-off method */
++	if ((gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0)
++	    || (gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0))
++		pr_err("DNS323: failed to setup power-off GPIO\n");
++
++	pm_power_off = dns323_power_off;
++
++	/* register flash and other platform devices */
++	platform_add_devices(dns323_plat_devices,
++			     ARRAY_SIZE(dns323_plat_devices));
++
++	i2c_register_board_info(0, dns323_i2c_devices,
++				ARRAY_SIZE(dns323_i2c_devices));
++
++	orion5x_eth_init(&dns323_eth_data);
++}
++
++/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
++MACHINE_START(DNS323, "D-Link DNS-323")
++	/* Maintainer: Herbert Valerio Riedel <hvr at 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,
++	.init_irq	= orion5x_init_irq,
++	.timer		= &orion5x_timer,
++	.fixup		= tag_fixup_mem32,
++MACHINE_END
+diff --git a/arch/arm/mach-orion5x/gpio.c b/arch/arm/mach-orion5x/gpio.c
+new file mode 100644
+index 0000000..8108c31
+--- /dev/null
++++ b/arch/arm/mach-orion5x/gpio.c
+@@ -0,0 +1,226 @@
++/*
++ * arch/arm/mach-orion5x/gpio.c
++ *
++ * GPIO functions for Marvell Orion System On Chip
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/bitops.h>
++#include <asm/gpio.h>
++#include <asm/io.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++
++static DEFINE_SPINLOCK(gpio_lock);
++static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
++static const char *gpio_label[GPIO_MAX];  /* non null for allocated GPIOs */
++
++void __init orion5x_gpio_set_valid_pins(u32 pins)
++{
++	gpio_valid[0] = pins;
++}
++
++/*
++ * GENERIC_GPIO primitives
++ */
++int gpio_direction_input(unsigned pin)
++{
++	unsigned long flags;
++
++	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
++		return -EINVAL;
++	}
++
++	spin_lock_irqsave(&gpio_lock, flags);
++
++	/*
++	 * Some callers might have not used the gpio_request(),
++	 * so flag this pin as requested now.
++	 */
++	if (!gpio_label[pin])
++		gpio_label[pin] = "?";
++
++	orion5x_setbits(GPIO_IO_CONF, 1 << pin);
++
++	spin_unlock_irqrestore(&gpio_lock, flags);
++	return 0;
++}
++EXPORT_SYMBOL(gpio_direction_input);
++
++int gpio_direction_output(unsigned pin, int value)
++{
++	unsigned long flags;
++	int mask;
++
++	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
++		return -EINVAL;
++	}
++
++	spin_lock_irqsave(&gpio_lock, flags);
++
++	/*
++	 * Some callers might have not used the gpio_request(),
++	 * so flag this pin as requested now.
++	 */
++	if (!gpio_label[pin])
++		gpio_label[pin] = "?";
++
++	mask = 1 << pin;
++	orion5x_clrbits(GPIO_BLINK_EN, mask);
++	if (value)
++		orion5x_setbits(GPIO_OUT, mask);
++	else
++		orion5x_clrbits(GPIO_OUT, mask);
++	orion5x_clrbits(GPIO_IO_CONF, mask);
++
++	spin_unlock_irqrestore(&gpio_lock, flags);
++	return 0;
++}
++EXPORT_SYMBOL(gpio_direction_output);
++
++int gpio_get_value(unsigned pin)
++{
++	int val, mask = 1 << pin;
++
++	if (orion5x_read(GPIO_IO_CONF) & mask)
++		val = orion5x_read(GPIO_DATA_IN) ^ orion5x_read(GPIO_IN_POL);
++	else
++		val = orion5x_read(GPIO_OUT);
++
++	return val & mask;
++}
++EXPORT_SYMBOL(gpio_get_value);
++
++void gpio_set_value(unsigned pin, int value)
++{
++	unsigned long flags;
++	int mask = 1 << pin;
++
++	spin_lock_irqsave(&gpio_lock, flags);
++
++	orion5x_clrbits(GPIO_BLINK_EN, mask);
++	if (value)
++		orion5x_setbits(GPIO_OUT, mask);
++	else
++		orion5x_clrbits(GPIO_OUT, mask);
++
++	spin_unlock_irqrestore(&gpio_lock, flags);
++}
++EXPORT_SYMBOL(gpio_set_value);
++
++void orion5x_gpio_set_blink(unsigned pin, int blink)
++{
++	unsigned long flags;
++	int mask = 1 << pin;
++
++	spin_lock_irqsave(&gpio_lock, flags);
++
++	orion5x_clrbits(GPIO_OUT, mask);
++	if (blink)
++		orion5x_setbits(GPIO_BLINK_EN, mask);
++	else
++		orion5x_clrbits(GPIO_BLINK_EN, mask);
++
++	spin_unlock_irqrestore(&gpio_lock, flags);
++}
++EXPORT_SYMBOL(orion5x_gpio_set_blink);
++
++int gpio_request(unsigned pin, const char *label)
++{
++	int ret = 0;
++	unsigned long flags;
++
++	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
++		return -EINVAL;
++	}
++
++	spin_lock_irqsave(&gpio_lock, flags);
++
++	if (gpio_label[pin]) {
++		pr_debug("%s: GPIO %d already used as %s\n",
++			 __func__, pin, gpio_label[pin]);
++		ret = -EBUSY;
++	} else
++		gpio_label[pin] = label ? label : "?";
++
++	spin_unlock_irqrestore(&gpio_lock, flags);
++	return ret;
++}
++EXPORT_SYMBOL(gpio_request);
++
++void gpio_free(unsigned pin)
++{
++	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
++		return;
++	}
++
++	if (!gpio_label[pin])
++		pr_warning("%s: GPIO %d already freed\n", __func__, pin);
++	else
++		gpio_label[pin] = NULL;
++}
++EXPORT_SYMBOL(gpio_free);
++
++/* Debug helper */
++void gpio_display(void)
++{
++	int i;
++
++	for (i = 0; i < GPIO_MAX; i++) {
++		printk(KERN_DEBUG "Pin-%d: ", i);
++
++		if (!test_bit(i, gpio_valid)) {
++			printk("non-GPIO\n");
++		} else if (!gpio_label[i]) {
++			printk("GPIO, free\n");
++		} else {
++			printk("GPIO, used by %s, ", gpio_label[i]);
++			if (orion5x_read(GPIO_IO_CONF) & (1 << i)) {
++				printk("input, active %s, level %s, edge %s\n",
++				((orion5x_read(GPIO_IN_POL) >> i) & 1) ? "low" : "high",
++				((orion5x_read(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked",
++				((orion5x_read(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked");
++			} else {
++				printk("output, val=%d\n", (orion5x_read(GPIO_OUT) >> i) & 1);
++			}
++		}
++	}
++
++	printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n",
++				MPP_0_7_CTRL, orion5x_read(MPP_0_7_CTRL));
++	printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n",
++				MPP_8_15_CTRL, orion5x_read(MPP_8_15_CTRL));
++	printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n",
++				MPP_16_19_CTRL, orion5x_read(MPP_16_19_CTRL));
++	printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n",
++				MPP_DEV_CTRL, orion5x_read(MPP_DEV_CTRL));
++	printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n",
++				GPIO_OUT, orion5x_read(GPIO_OUT));
++	printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n",
++				GPIO_IO_CONF, orion5x_read(GPIO_IO_CONF));
++	printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n",
++				GPIO_BLINK_EN, orion5x_read(GPIO_BLINK_EN));
++	printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n",
++				GPIO_IN_POL, orion5x_read(GPIO_IN_POL));
++	printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n",
++				GPIO_DATA_IN, orion5x_read(GPIO_DATA_IN));
++	printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n",
++				GPIO_LEVEL_MASK, orion5x_read(GPIO_LEVEL_MASK));
++	printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n",
++				GPIO_EDGE_CAUSE, orion5x_read(GPIO_EDGE_CAUSE));
++	printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n",
++				GPIO_EDGE_MASK, orion5x_read(GPIO_EDGE_MASK));
++}
+diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
+new file mode 100644
+index 0000000..dd21f38
+--- /dev/null
++++ b/arch/arm/mach-orion5x/irq.c
+@@ -0,0 +1,211 @@
++/*
++ * arch/arm/mach-orion5x/irq.c
++ *
++ * Core IRQ functions for Marvell Orion System On Chip
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <asm/gpio.h>
++#include <asm/io.h>
++#include <asm/arch/orion5x.h>
++#include <asm/plat-orion/irq.h>
++#include "common.h"
++
++/*****************************************************************************
++ * Orion GPIO IRQ
++ *
++ * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same
++ * value of the line or the opposite value.
++ *
++ * Level IRQ handlers: DATA_IN is used directly as cause register.
++ *                     Interrupt are masked by LEVEL_MASK registers.
++ * Edge IRQ handlers:  Change in DATA_IN are latched in EDGE_CAUSE.
++ *                     Interrupt are masked by EDGE_MASK registers.
++ * Both-edge handlers: Similar to regular Edge handlers, but also swaps
++ *                     the polarity to catch the next line transaction.
++ *                     This is a race condition that might not perfectly
++ *                     work on some use cases.
++ *
++ * Every eight GPIO lines are grouped (OR'ed) before going up to main
++ * cause register.
++ *
++ *                    EDGE  cause    mask
++ *        data-in   /--------| |-----| |----\
++ *     -----| |-----                         ---- to main cause reg
++ *           X      \----------------| |----/
++ *        polarity    LEVEL          mask
++ *
++ ****************************************************************************/
++static void orion5x_gpio_irq_ack(u32 irq)
++{
++	int pin = irq_to_gpio(irq);
++	if (irq_desc[irq].status & IRQ_LEVEL)
++		/*
++		 * Mask bit for level interrupt
++		 */
++		orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
++	else
++		/*
++		 * Clear casue bit for egde interrupt
++		 */
++		orion5x_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
++}
++
++static void orion5x_gpio_irq_mask(u32 irq)
++{
++	int pin = irq_to_gpio(irq);
++	if (irq_desc[irq].status & IRQ_LEVEL)
++		orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
++	else
++		orion5x_clrbits(GPIO_EDGE_MASK, 1 << pin);
++}
++
++static void orion5x_gpio_irq_unmask(u32 irq)
++{
++	int pin = irq_to_gpio(irq);
++	if (irq_desc[irq].status & IRQ_LEVEL)
++		orion5x_setbits(GPIO_LEVEL_MASK, 1 << pin);
++	else
++		orion5x_setbits(GPIO_EDGE_MASK, 1 << pin);
++}
++
++static int orion5x_gpio_set_irq_type(u32 irq, u32 type)
++{
++	int pin = irq_to_gpio(irq);
++	struct irq_desc *desc;
++
++	if ((orion5x_read(GPIO_IO_CONF) & (1 << pin)) == 0) {
++		printk(KERN_ERR "orion5x_gpio_set_irq_type failed "
++				"(irq %d, pin %d).\n", irq, pin);
++		return -EINVAL;
++	}
++
++	desc = irq_desc + irq;
++
++	switch (type) {
++	case IRQT_HIGH:
++		desc->handle_irq = handle_level_irq;
++		desc->status |= IRQ_LEVEL;
++		orion5x_clrbits(GPIO_IN_POL, (1 << pin));
++		break;
++	case IRQT_LOW:
++		desc->handle_irq = handle_level_irq;
++		desc->status |= IRQ_LEVEL;
++		orion5x_setbits(GPIO_IN_POL, (1 << pin));
++		break;
++	case IRQT_RISING:
++		desc->handle_irq = handle_edge_irq;
++		desc->status &= ~IRQ_LEVEL;
++		orion5x_clrbits(GPIO_IN_POL, (1 << pin));
++		break;
++	case IRQT_FALLING:
++		desc->handle_irq = handle_edge_irq;
++		desc->status &= ~IRQ_LEVEL;
++		orion5x_setbits(GPIO_IN_POL, (1 << pin));
++		break;
++	case IRQT_BOTHEDGE:
++		desc->handle_irq = handle_edge_irq;
++		desc->status &= ~IRQ_LEVEL;
++		/*
++		 * set initial polarity based on current input level
++		 */
++		if ((orion5x_read(GPIO_IN_POL) ^ orion5x_read(GPIO_DATA_IN))
++		    & (1 << pin))
++			orion5x_setbits(GPIO_IN_POL, (1 << pin)); /* falling */
++		else
++			orion5x_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */
++
++		break;
++	default:
++		printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
++		return -EINVAL;
++	}
++
++	desc->status &= ~IRQ_TYPE_SENSE_MASK;
++	desc->status |= type & IRQ_TYPE_SENSE_MASK;
++
++	return 0;
++}
++
++static struct irq_chip orion5x_gpio_irq_chip = {
++	.name		= "Orion-IRQ-GPIO",
++	.ack		= orion5x_gpio_irq_ack,
++	.mask		= orion5x_gpio_irq_mask,
++	.unmask		= orion5x_gpio_irq_unmask,
++	.set_type	= orion5x_gpio_set_irq_type,
++};
++
++static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
++{
++	u32 cause, offs, pin;
++
++	BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31);
++	offs = (irq - IRQ_ORION5X_GPIO_0_7) * 8;
++	cause = (orion5x_read(GPIO_DATA_IN) & orion5x_read(GPIO_LEVEL_MASK)) |
++		(orion5x_read(GPIO_EDGE_CAUSE) & orion5x_read(GPIO_EDGE_MASK));
++
++	for (pin = offs; pin < offs + 8; pin++) {
++		if (cause & (1 << pin)) {
++			irq = gpio_to_irq(pin);
++			desc = irq_desc + irq;
++			if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
++				/* Swap polarity (race with GPIO line) */
++				u32 polarity = orion5x_read(GPIO_IN_POL);
++				polarity ^= 1 << pin;
++				orion5x_write(GPIO_IN_POL, polarity);
++			}
++			desc_handle_irq(irq, desc);
++		}
++	}
++}
++
++static void __init orion5x_init_gpio_irq(void)
++{
++	int i;
++	struct irq_desc *desc;
++
++	/*
++	 * Mask and clear GPIO IRQ interrupts
++	 */
++	orion5x_write(GPIO_LEVEL_MASK, 0x0);
++	orion5x_write(GPIO_EDGE_MASK, 0x0);
++	orion5x_write(GPIO_EDGE_CAUSE, 0x0);
++
++	/*
++	 * Register chained level handlers for GPIO IRQs by default.
++	 * User can use set_type() if he wants to use edge types handlers.
++	 */
++	for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
++		set_irq_chip(i, &orion5x_gpio_irq_chip);
++		set_irq_handler(i, handle_level_irq);
++		desc = irq_desc + i;
++		desc->status |= IRQ_LEVEL;
++		set_irq_flags(i, IRQF_VALID);
++	}
++	set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, orion5x_gpio_irq_handler);
++	set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, orion5x_gpio_irq_handler);
++	set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, orion5x_gpio_irq_handler);
++	set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, orion5x_gpio_irq_handler);
++}
++
++/*****************************************************************************
++ * Orion Main IRQ
++ ****************************************************************************/
++static void __init orion5x_init_main_irq(void)
++{
++	orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
++}
++
++void __init orion5x_init_irq(void)
++{
++	orion5x_init_main_irq();
++	orion5x_init_gpio_irq();
++}
+diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+new file mode 100644
+index 0000000..9141345
+--- /dev/null
++++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+@@ -0,0 +1,256 @@
++/*
++ * arch/arm/mach-orion5x/kurobox_pro-setup.c
++ *
++ * Maintainer: Ronen Shitrit <rshitrit at marvell.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/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mtd/nand.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/i2c.h>
++#include <linux/ata_platform.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include <asm/plat-orion/orion_nand.h>
++#include "common.h"
++
++/*****************************************************************************
++ * KUROBOX-PRO Info
++ ****************************************************************************/
++
++/*
++ * 256K NOR flash Device bus boot chip select
++ */
++
++#define KUROBOX_PRO_NOR_BOOT_BASE	0xf4000000
++#define KUROBOX_PRO_NOR_BOOT_SIZE	SZ_256K
++
++/*
++ * 256M NAND flash on Device bus chip select 1
++ */
++
++#define KUROBOX_PRO_NAND_BASE		0xfc000000
++#define KUROBOX_PRO_NAND_SIZE		SZ_2M
++
++/*****************************************************************************
++ * 256MB NAND Flash on Device bus CS0
++ ****************************************************************************/
++
++static struct mtd_partition kurobox_pro_nand_parts[] = {
++	{
++		.name	= "uImage",
++		.offset	= 0,
++		.size	= SZ_4M,
++	},
++	{
++		.name	= "rootfs",
++		.offset	= SZ_4M,
++		.size	= SZ_64M,
++	},
++	{
++		.name	= "extra",
++		.offset	= SZ_4M + SZ_64M,
++		.size	= SZ_256M - (SZ_4M + SZ_64M),
++	},
++};
++
++static struct resource kurobox_pro_nand_resource = {
++	.flags		= IORESOURCE_MEM,
++	.start		= KUROBOX_PRO_NAND_BASE,
++	.end		= KUROBOX_PRO_NAND_BASE + KUROBOX_PRO_NAND_SIZE - 1,
++};
++
++static struct orion_nand_data kurobox_pro_nand_data = {
++	.parts		= kurobox_pro_nand_parts,
++	.nr_parts	= ARRAY_SIZE(kurobox_pro_nand_parts),
++	.cle		= 0,
++	.ale		= 1,
++	.width		= 8,
++};
++
++static struct platform_device kurobox_pro_nand_flash = {
++	.name		= "orion_nand",
++	.id		= -1,
++	.dev		= {
++		.platform_data	= &kurobox_pro_nand_data,
++	},
++	.resource	= &kurobox_pro_nand_resource,
++	.num_resources	= 1,
++};
++
++/*****************************************************************************
++ * 256KB NOR Flash on BOOT Device
++ ****************************************************************************/
++
++static struct physmap_flash_data kurobox_pro_nor_flash_data = {
++	.width		= 1,
++};
++
++static struct resource kurobox_pro_nor_flash_resource = {
++	.flags			= IORESOURCE_MEM,
++	.start			= KUROBOX_PRO_NOR_BOOT_BASE,
++	.end			= KUROBOX_PRO_NOR_BOOT_BASE + KUROBOX_PRO_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device kurobox_pro_nor_flash = {
++	.name			= "physmap-flash",
++	.id			= 0,
++	.dev		= {
++		.platform_data	= &kurobox_pro_nor_flash_data,
++	},
++	.num_resources		= 1,
++	.resource		= &kurobox_pro_nor_flash_resource,
++};
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++	/*
++	 * PCI isn't used on the Kuro
++	 */
++	if (dev->bus->number == orion5x_pcie_local_bus_nr())
++		return IRQ_ORION5X_PCIE0_INT;
++	else
++		printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
++
++	return -1;
++}
++
++static struct hw_pci kurobox_pro_pci __initdata = {
++	.nr_controllers	= 1,
++	.swizzle	= pci_std_swizzle,
++	.setup		= orion5x_pci_sys_setup,
++	.scan		= orion5x_pci_sys_scan_bus,
++	.map_irq	= kurobox_pro_pci_map_irq,
++};
++
++static int __init kurobox_pro_pci_init(void)
++{
++	if (machine_is_kurobox_pro())
++		pci_common_init(&kurobox_pro_pci);
++
++	return 0;
++}
++
++subsys_initcall(kurobox_pro_pci_init);
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++
++static struct mv643xx_eth_platform_data kurobox_pro_eth_data = {
++	.phy_addr	= 8,
++	.force_phy_addr = 1,
++};
++
++/*****************************************************************************
++ * RTC 5C372a on I2C bus
++ ****************************************************************************/
++static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
++       .driver_name    = "rtc-rs5c372",
++       .type           = "rs5c372a",
++       .addr           = 0x32,
++};
++
++/*****************************************************************************
++ * SATA
++ ****************************************************************************/
++static struct mv_sata_platform_data kurobox_pro_sata_data = {
++	.n_ports        = 2,
++};
++
++/*****************************************************************************
++ * General Setup
++ ****************************************************************************/
++
++static void __init kurobox_pro_init(void)
++{
++	/*
++	 * Setup basic Orion functions. Need to be called early.
++	 */
++	orion5x_init();
++
++	/*
++	 * Setup the CPU address decode windows for our devices
++	 */
++	orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE,
++				KUROBOX_PRO_NOR_BOOT_SIZE);
++	orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, KUROBOX_PRO_NAND_SIZE);
++
++	/*
++	 * Open a special address decode windows for the PCIE WA.
++	 */
++	orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
++				ORION5X_PCIE_WA_SIZE);
++
++	/*
++	 * Setup Multiplexing Pins --
++	 * MPP[0-1] Not used
++	 * MPP[2] GPIO Micon
++	 * MPP[3] GPIO RTC
++	 * MPP[4-5] Not used
++	 * MPP[6] Nand Flash REn
++	 * MPP[7] Nand Flash WEn
++	 * MPP[8-11] Not used
++	 * MPP[12] SATA 0 presence Indication
++	 * MPP[13] SATA 1 presence Indication
++	 * MPP[14] SATA 0 active Indication
++	 * MPP[15] SATA 1 active indication
++	 * MPP[16-19] Not used
++	 */
++	orion5x_write(MPP_0_7_CTRL, 0x44220003);
++	orion5x_write(MPP_8_15_CTRL, 0x55550000);
++	orion5x_write(MPP_16_19_CTRL, 0x0);
++
++	orion5x_gpio_set_valid_pins(0x0000000c);
++
++	platform_device_register(&kurobox_pro_nor_flash);
++	if (machine_is_kurobox_pro())
++		platform_device_register(&kurobox_pro_nand_flash);
++	i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
++	orion5x_eth_init(&kurobox_pro_eth_data);
++	orion5x_sata_init(&kurobox_pro_sata_data);
++}
++
++#ifdef CONFIG_MACH_KUROBOX_PRO
++MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
++	/* Maintainer: Ronen Shitrit <rshitrit at 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,
++	.init_irq	= orion5x_init_irq,
++	.timer		= &orion5x_timer,
++	.fixup		= tag_fixup_mem32,
++MACHINE_END
++#endif
++
++#ifdef CONFIG_MACH_LINKSTATION_PRO
++MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
++	/* Maintainer: Byron Bradley <byron.bbradley at 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,
++	.init_irq	= orion5x_init_irq,
++	.timer		= &orion5x_timer,
++	.fixup		= tag_fixup_mem32,
++MACHINE_END
++#endif
+diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
+new file mode 100644
+index 0000000..fdf99fc
+--- /dev/null
++++ b/arch/arm/mach-orion5x/pci.c
+@@ -0,0 +1,559 @@
++/*
++ * arch/arm/mach-orion5x/pci.c
++ *
++ * PCI and PCIe functions for Marvell Orion System On Chip
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.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/kernel.h>
++#include <linux/pci.h>
++#include <linux/mbus.h>
++#include <asm/mach/pci.h>
++#include <asm/plat-orion/pcie.h>
++#include "common.h"
++
++/*****************************************************************************
++ * Orion has one PCIe controller and one PCI controller.
++ *
++ * Note1: The local PCIe bus number is '0'. The local PCI bus number
++ * follows the scanned PCIe bridged busses, if any.
++ *
++ * Note2: It is possible for PCI/PCIe agents to access many subsystem's
++ * space, by configuring BARs and Address Decode Windows, e.g. flashes on
++ * device bus, Orion registers, etc. However this code only enable the
++ * access to DDR banks.
++ ****************************************************************************/
++
++
++/*****************************************************************************
++ * PCIe controller
++ ****************************************************************************/
++#define PCIE_BASE	((void __iomem *)ORION5X_PCIE_VIRT_BASE)
++
++void __init orion5x_pcie_id(u32 *dev, u32 *rev)
++{
++	*dev = orion_pcie_dev_id(PCIE_BASE);
++	*rev = orion_pcie_rev(PCIE_BASE);
++}
++
++int __init orion5x_pcie_local_bus_nr(void)
++{
++	return orion_pcie_get_local_bus_nr(PCIE_BASE);
++}
++
++static int pcie_valid_config(int bus, int dev)
++{
++	/*
++	 * Don't go out when trying to access --
++	 * 1. nonexisting device on local bus
++	 * 2. where there's no device connected (no link)
++	 */
++	if (bus == 0 && dev == 0)
++		return 1;
++
++	if (!orion_pcie_link_up(PCIE_BASE))
++		return 0;
++
++	if (bus == 0 && dev != 1)
++		return 0;
++
++	return 1;
++}
++
++
++/*
++ * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
++ * and then reading the PCIE_CONF_DATA register. Need to make sure these
++ * transactions are atomic.
++ */
++static DEFINE_SPINLOCK(orion5x_pcie_lock);
++
++static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
++			int size, u32 *val)
++{
++	unsigned long flags;
++	int ret;
++
++	if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
++		*val = 0xffffffff;
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	}
++
++	spin_lock_irqsave(&orion5x_pcie_lock, flags);
++	ret = orion_pcie_rd_conf(PCIE_BASE, bus, devfn, where, size, val);
++	spin_unlock_irqrestore(&orion5x_pcie_lock, flags);
++
++	return ret;
++}
++
++static int pcie_rd_conf_wa(struct pci_bus *bus, u32 devfn,
++			   int where, int size, u32 *val)
++{
++	int ret;
++
++	if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
++		*val = 0xffffffff;
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	}
++
++	/*
++	 * We only support access to the non-extended configuration
++	 * space when using the WA access method (or we would have to
++	 * sacrifice 256M of CPU virtual address space.)
++	 */
++	if (where >= 0x100) {
++		*val = 0xffffffff;
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	}
++
++	ret = orion_pcie_rd_conf_wa((void __iomem *)ORION5X_PCIE_WA_VIRT_BASE,
++				    bus, devfn, where, size, val);
++
++	return ret;
++}
++
++static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
++			int where, int size, u32 val)
++{
++	unsigned long flags;
++	int ret;
++
++	if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	spin_lock_irqsave(&orion5x_pcie_lock, flags);
++	ret = orion_pcie_wr_conf(PCIE_BASE, bus, devfn, where, size, val);
++	spin_unlock_irqrestore(&orion5x_pcie_lock, flags);
++
++	return ret;
++}
++
++static struct pci_ops pcie_ops = {
++	.read = pcie_rd_conf,
++	.write = pcie_wr_conf,
++};
++
++
++static int __init pcie_setup(struct pci_sys_data *sys)
++{
++	struct resource *res;
++	int dev;
++
++	/*
++	 * Generic PCIe unit setup.
++	 */
++	orion_pcie_setup(PCIE_BASE, &orion5x_mbus_dram_info);
++
++	/*
++	 * Check whether to apply Orion-1/Orion-NAS PCIe config
++	 * read transaction workaround.
++	 */
++	dev = orion_pcie_dev_id(PCIE_BASE);
++	if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
++		printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config "
++				   "read transaction workaround\n");
++		pcie_ops.read = pcie_rd_conf_wa;
++	}
++
++	/*
++	 * Request resources.
++	 */
++	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
++	if (!res)
++		panic("pcie_setup unable to alloc resources");
++
++	/*
++	 * IORESOURCE_IO
++	 */
++	res[0].name = "PCIe I/O Space";
++	res[0].flags = IORESOURCE_IO;
++	res[0].start = ORION5X_PCIE_IO_BUS_BASE;
++	res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1;
++	if (request_resource(&ioport_resource, &res[0]))
++		panic("Request PCIe IO resource failed\n");
++	sys->resource[0] = &res[0];
++
++	/*
++	 * IORESOURCE_MEM
++	 */
++	res[1].name = "PCIe Memory Space";
++	res[1].flags = IORESOURCE_MEM;
++	res[1].start = ORION5X_PCIE_MEM_PHYS_BASE;
++	res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1;
++	if (request_resource(&iomem_resource, &res[1]))
++		panic("Request PCIe Memory resource failed\n");
++	sys->resource[1] = &res[1];
++
++	sys->resource[2] = NULL;
++	sys->io_offset = 0;
++
++	return 1;
++}
++
++/*****************************************************************************
++ * PCI controller
++ ****************************************************************************/
++#define PCI_MODE		ORION5X_PCI_REG(0xd00)
++#define PCI_CMD			ORION5X_PCI_REG(0xc00)
++#define PCI_P2P_CONF		ORION5X_PCI_REG(0x1d14)
++#define PCI_CONF_ADDR		ORION5X_PCI_REG(0xc78)
++#define PCI_CONF_DATA		ORION5X_PCI_REG(0xc7c)
++
++/*
++ * PCI_MODE bits
++ */
++#define PCI_MODE_64BIT			(1 << 2)
++#define PCI_MODE_PCIX			((1 << 4) | (1 << 5))
++
++/*
++ * PCI_CMD bits
++ */
++#define PCI_CMD_HOST_REORDER		(1 << 29)
++
++/*
++ * PCI_P2P_CONF bits
++ */
++#define PCI_P2P_BUS_OFFS		16
++#define PCI_P2P_BUS_MASK		(0xff << PCI_P2P_BUS_OFFS)
++#define PCI_P2P_DEV_OFFS		24
++#define PCI_P2P_DEV_MASK		(0x1f << PCI_P2P_DEV_OFFS)
++
++/*
++ * PCI_CONF_ADDR bits
++ */
++#define PCI_CONF_REG(reg)		((reg) & 0xfc)
++#define PCI_CONF_FUNC(func)		(((func) & 0x3) << 8)
++#define PCI_CONF_DEV(dev)		(((dev) & 0x1f) << 11)
++#define PCI_CONF_BUS(bus)		(((bus) & 0xff) << 16)
++#define PCI_CONF_ADDR_EN		(1 << 31)
++
++/*
++ * Internal configuration space
++ */
++#define PCI_CONF_FUNC_STAT_CMD		0
++#define PCI_CONF_REG_STAT_CMD		4
++#define PCIX_STAT			0x64
++#define PCIX_STAT_BUS_OFFS		8
++#define PCIX_STAT_BUS_MASK		(0xff << PCIX_STAT_BUS_OFFS)
++
++/*
++ * PCI Address Decode Windows registers
++ */
++#define PCI_BAR_SIZE_DDR_CS(n)	(((n) == 0) ? ORION5X_PCI_REG(0xc08) : \
++				((n) == 1) ? ORION5X_PCI_REG(0xd08) :  \
++				((n) == 2) ? ORION5X_PCI_REG(0xc0c) :  \
++				((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0)
++#define PCI_BAR_REMAP_DDR_CS(n)	(((n) ==0) ? ORION5X_PCI_REG(0xc48) :  \
++				((n) == 1) ? ORION5X_PCI_REG(0xd48) :  \
++				((n) == 2) ? ORION5X_PCI_REG(0xc4c) :  \
++				((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0)
++#define PCI_BAR_ENABLE		ORION5X_PCI_REG(0xc3c)
++#define PCI_ADDR_DECODE_CTRL	ORION5X_PCI_REG(0xd3c)
++
++/*
++ * PCI configuration helpers for BAR settings
++ */
++#define PCI_CONF_FUNC_BAR_CS(n)		((n) >> 1)
++#define PCI_CONF_REG_BAR_LO_CS(n)	(((n) & 1) ? 0x18 : 0x10)
++#define PCI_CONF_REG_BAR_HI_CS(n)	(((n) & 1) ? 0x1c : 0x14)
++
++/*
++ * PCI config cycles are done by programming the PCI_CONF_ADDR register
++ * and then reading the PCI_CONF_DATA register. Need to make sure these
++ * transactions are atomic.
++ */
++static DEFINE_SPINLOCK(orion5x_pci_lock);
++
++int orion5x_pci_local_bus_nr(void)
++{
++	u32 conf = orion5x_read(PCI_P2P_CONF);
++	return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
++}
++
++static int orion5x_pci_hw_rd_conf(int bus, int dev, u32 func,
++					u32 where, u32 size, u32 *val)
++{
++	unsigned long flags;
++	spin_lock_irqsave(&orion5x_pci_lock, flags);
++
++	orion5x_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
++			PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
++			PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
++
++	*val = orion5x_read(PCI_CONF_DATA);
++
++	if (size == 1)
++		*val = (*val >> (8*(where & 0x3))) & 0xff;
++	else if (size == 2)
++		*val = (*val >> (8*(where & 0x3))) & 0xffff;
++
++	spin_unlock_irqrestore(&orion5x_pci_lock, flags);
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static int orion5x_pci_hw_wr_conf(int bus, int dev, u32 func,
++					u32 where, u32 size, u32 val)
++{
++	unsigned long flags;
++	int ret = PCIBIOS_SUCCESSFUL;
++
++	spin_lock_irqsave(&orion5x_pci_lock, flags);
++
++	orion5x_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
++			PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
++			PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
++
++	if (size == 4) {
++		__raw_writel(val, PCI_CONF_DATA);
++	} else if (size == 2) {
++		__raw_writew(val, PCI_CONF_DATA + (where & 0x3));
++	} else if (size == 1) {
++		__raw_writeb(val, PCI_CONF_DATA + (where & 0x3));
++	} else {
++		ret = PCIBIOS_BAD_REGISTER_NUMBER;
++	}
++
++	spin_unlock_irqrestore(&orion5x_pci_lock, flags);
++
++	return ret;
++}
++
++static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn,
++				int where, int size, u32 *val)
++{
++	/*
++	 * Don't go out for local device
++	 */
++	if (bus->number == orion5x_pci_local_bus_nr() &&
++	    PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0) {
++		*val = 0xffffffff;
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	}
++
++	return orion5x_pci_hw_rd_conf(bus->number, PCI_SLOT(devfn),
++					PCI_FUNC(devfn), where, size, val);
++}
++
++static int orion5x_pci_wr_conf(struct pci_bus *bus, u32 devfn,
++				int where, int size, u32 val)
++{
++	if (bus->number == orion5x_pci_local_bus_nr() &&
++	    PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	return orion5x_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn),
++					PCI_FUNC(devfn), where, size, val);
++}
++
++static struct pci_ops pci_ops = {
++	.read = orion5x_pci_rd_conf,
++	.write = orion5x_pci_wr_conf,
++};
++
++static void __init orion5x_pci_set_bus_nr(int nr)
++{
++	u32 p2p = orion5x_read(PCI_P2P_CONF);
++
++	if (orion5x_read(PCI_MODE) & PCI_MODE_PCIX) {
++		/*
++		 * PCI-X mode
++		 */
++		u32 pcix_status, bus, dev;
++		bus = (p2p & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS;
++		dev = (p2p & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS;
++		orion5x_pci_hw_rd_conf(bus, dev, 0, PCIX_STAT, 4, &pcix_status);
++		pcix_status &= ~PCIX_STAT_BUS_MASK;
++		pcix_status |= (nr << PCIX_STAT_BUS_OFFS);
++		orion5x_pci_hw_wr_conf(bus, dev, 0, PCIX_STAT, 4, pcix_status);
++	} else {
++		/*
++		 * PCI Conventional mode
++		 */
++		p2p &= ~PCI_P2P_BUS_MASK;
++		p2p |= (nr << PCI_P2P_BUS_OFFS);
++		orion5x_write(PCI_P2P_CONF, p2p);
++	}
++}
++
++static void __init orion5x_pci_master_slave_enable(void)
++{
++	int bus_nr, func, reg;
++	u32 val;
++
++	bus_nr = orion5x_pci_local_bus_nr();
++	func = PCI_CONF_FUNC_STAT_CMD;
++	reg = PCI_CONF_REG_STAT_CMD;
++	orion5x_pci_hw_rd_conf(bus_nr, 0, func, reg, 4, &val);
++	val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
++	orion5x_pci_hw_wr_conf(bus_nr, 0, func, reg, 4, val | 0x7);
++}
++
++static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram)
++{
++	u32 win_enable;
++	int bus;
++	int i;
++
++	/*
++	 * First, disable windows.
++	 */
++	win_enable = 0xffffffff;
++	orion5x_write(PCI_BAR_ENABLE, win_enable);
++
++	/*
++	 * Setup windows for DDR banks.
++	 */
++	bus = orion5x_pci_local_bus_nr();
++
++	for (i = 0; i < dram->num_cs; i++) {
++		struct mbus_dram_window *cs = dram->cs + i;
++		u32 func = PCI_CONF_FUNC_BAR_CS(cs->cs_index);
++		u32 reg;
++		u32 val;
++
++		/*
++		 * Write DRAM bank base address register.
++		 */
++		reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index);
++		orion5x_pci_hw_rd_conf(bus, 0, func, reg, 4, &val);
++		val = (cs->base & 0xfffff000) | (val & 0xfff);
++		orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, val);
++
++		/*
++		 * Write DRAM bank size register.
++		 */
++		reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index);
++		orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, 0);
++		orion5x_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index),
++				(cs->size - 1) & 0xfffff000);
++		orion5x_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index),
++				cs->base & 0xfffff000);
++
++		/*
++		 * Enable decode window for this chip select.
++		 */
++		win_enable &= ~(1 << cs->cs_index);
++	}
++
++	/*
++	 * Re-enable decode windows.
++	 */
++	orion5x_write(PCI_BAR_ENABLE, win_enable);
++
++	/*
++	 * Disable automatic update of address remaping when writing to BARs.
++	 */
++	orion5x_setbits(PCI_ADDR_DECODE_CTRL, 1);
++}
++
++static int __init pci_setup(struct pci_sys_data *sys)
++{
++	struct resource *res;
++
++	/*
++	 * Point PCI unit MBUS decode windows to DRAM space.
++	 */
++	orion5x_setup_pci_wins(&orion5x_mbus_dram_info);
++
++	/*
++	 * Master + Slave enable
++	 */
++	orion5x_pci_master_slave_enable();
++
++	/*
++	 * Force ordering
++	 */
++	orion5x_setbits(PCI_CMD, PCI_CMD_HOST_REORDER);
++
++	/*
++	 * Request resources
++	 */
++	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
++	if (!res)
++		panic("pci_setup unable to alloc resources");
++
++	/*
++	 * IORESOURCE_IO
++	 */
++	res[0].name = "PCI I/O Space";
++	res[0].flags = IORESOURCE_IO;
++	res[0].start = ORION5X_PCI_IO_BUS_BASE;
++	res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1;
++	if (request_resource(&ioport_resource, &res[0]))
++		panic("Request PCI IO resource failed\n");
++	sys->resource[0] = &res[0];
++
++	/*
++	 * IORESOURCE_MEM
++	 */
++	res[1].name = "PCI Memory Space";
++	res[1].flags = IORESOURCE_MEM;
++	res[1].start = ORION5X_PCI_MEM_PHYS_BASE;
++	res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1;
++	if (request_resource(&iomem_resource, &res[1]))
++		panic("Request PCI Memory resource failed\n");
++	sys->resource[1] = &res[1];
++
++	sys->resource[2] = NULL;
++	sys->io_offset = 0;
++
++	return 1;
++}
++
++
++/*****************************************************************************
++ * General PCIe + PCI
++ ****************************************************************************/
++static void __devinit rc_pci_fixup(struct pci_dev *dev)
++{
++	/*
++	 * Prevent enumeration of root complex.
++	 */
++	if (dev->bus->parent == NULL && dev->devfn == 0) {
++		int i;
++
++		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++			dev->resource[i].start = 0;
++			dev->resource[i].end   = 0;
++			dev->resource[i].flags = 0;
++		}
++	}
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
++
++int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
++{
++	int ret = 0;
++
++	if (nr == 0) {
++		orion_pcie_set_local_bus_nr(PCIE_BASE, sys->busnr);
++		ret = pcie_setup(sys);
++	} else if (nr == 1) {
++		orion5x_pci_set_bus_nr(sys->busnr);
++		ret = pci_setup(sys);
++	}
++
++	return ret;
++}
++
++struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
++{
++	struct pci_bus *bus;
++
++	if (nr == 0) {
++		bus = pci_scan_bus(sys->busnr, &pcie_ops, sys);
++	} else if (nr == 1) {
++		bus = pci_scan_bus(sys->busnr, &pci_ops, sys);
++	} else {
++		bus = NULL;
++		BUG();
++	}
++
++	return bus;
++}
+diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
+new file mode 100644
+index 0000000..37e8b2d
+--- /dev/null
++++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
+@@ -0,0 +1,312 @@
++/*
++ * arch/arm/mach-orion5x/rd88f5182-setup.c
++ *
++ * Marvell Orion-NAS Reference Design Setup
++ *
++ * Maintainer: Ronen Shitrit <rshitrit at marvell.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/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/ata_platform.h>
++#include <linux/i2c.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/leds.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++
++/*****************************************************************************
++ * RD-88F5182 Info
++ ****************************************************************************/
++
++/*
++ * 512K NOR flash Device bus boot chip select
++ */
++
++#define RD88F5182_NOR_BOOT_BASE		0xf4000000
++#define RD88F5182_NOR_BOOT_SIZE		SZ_512K
++
++/*
++ * 16M NOR flash on Device bus chip select 1
++ */
++
++#define RD88F5182_NOR_BASE		0xfc000000
++#define RD88F5182_NOR_SIZE		SZ_16M
++
++/*
++ * PCI
++ */
++
++#define RD88F5182_PCI_SLOT0_OFFS	7
++#define RD88F5182_PCI_SLOT0_IRQ_A_PIN	7
++#define RD88F5182_PCI_SLOT0_IRQ_B_PIN	6
++
++/*
++ * GPIO Debug LED
++ */
++
++#define RD88F5182_GPIO_DBG_LED		0
++
++/*****************************************************************************
++ * 16M NOR Flash on Device bus CS1
++ ****************************************************************************/
++
++static struct physmap_flash_data rd88f5182_nor_flash_data = {
++	.width		= 1,
++};
++
++static struct resource rd88f5182_nor_flash_resource = {
++	.flags			= IORESOURCE_MEM,
++	.start			= RD88F5182_NOR_BASE,
++	.end			= RD88F5182_NOR_BASE + RD88F5182_NOR_SIZE - 1,
++};
++
++static struct platform_device rd88f5182_nor_flash = {
++	.name			= "physmap-flash",
++	.id			= 0,
++	.dev		= {
++		.platform_data	= &rd88f5182_nor_flash_data,
++	},
++	.num_resources		= 1,
++	.resource		= &rd88f5182_nor_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++/*****************************************************************************
++ * Use GPIO debug led as CPU active indication
++ ****************************************************************************/
++
++static void rd88f5182_dbgled_event(led_event_t evt)
++{
++	int val;
++
++	if (evt == led_idle_end)
++		val = 1;
++	else if (evt == led_idle_start)
++		val = 0;
++	else
++		return;
++
++	gpio_set_value(RD88F5182_GPIO_DBG_LED, val);
++}
++
++static int __init rd88f5182_dbgled_init(void)
++{
++	int pin;
++
++	if (machine_is_rd88f5182()) {
++		pin = RD88F5182_GPIO_DBG_LED;
++
++		if (gpio_request(pin, "DBGLED") == 0) {
++			if (gpio_direction_output(pin, 0) != 0) {
++				printk(KERN_ERR "rd88f5182_dbgled_init failed "
++						"to set output pin %d\n", pin);
++				gpio_free(pin);
++				return 0;
++			}
++		} else {
++			printk(KERN_ERR "rd88f5182_dbgled_init failed "
++					"to request gpio %d\n", pin);
++			return 0;
++		}
++
++		leds_event = rd88f5182_dbgled_event;
++	}
++	return 0;
++}
++
++__initcall(rd88f5182_dbgled_init);
++
++#endif
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++void __init rd88f5182_pci_preinit(void)
++{
++	int pin;
++
++	/*
++	 * Configure PCI GPIO IRQ pins
++	 */
++	pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
++	if (gpio_request(pin, "PCI IntA") == 0) {
++		if (gpio_direction_input(pin) == 0) {
++			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++		} else {
++			printk(KERN_ERR "rd88f5182_pci_preinit faield to "
++					"set_irq_type pin %d\n", pin);
++			gpio_free(pin);
++		}
++	} else {
++		printk(KERN_ERR "rd88f5182_pci_preinit failed to request gpio %d\n", pin);
++	}
++
++	pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
++	if (gpio_request(pin, "PCI IntB") == 0) {
++		if (gpio_direction_input(pin) == 0) {
++			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++		} else {
++			printk(KERN_ERR "rd88f5182_pci_preinit faield to "
++					"set_irq_type pin %d\n", pin);
++			gpio_free(pin);
++		}
++	} else {
++		printk(KERN_ERR "rd88f5182_pci_preinit failed to gpio_request %d\n", pin);
++	}
++}
++
++static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++	/*
++	 * PCI-E isn't used on the RD2
++	 */
++	if (dev->bus->number == orion5x_pcie_local_bus_nr())
++		return IRQ_ORION5X_PCIE0_INT;
++
++	/*
++	 * PCI IRQs are connected via GPIOs
++	 */
++	switch (slot - RD88F5182_PCI_SLOT0_OFFS) {
++	case 0:
++		if (pin == 1)
++			return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_A_PIN);
++		else
++			return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_B_PIN);
++	default:
++		return -1;
++	}
++}
++
++static struct hw_pci rd88f5182_pci __initdata = {
++	.nr_controllers	= 2,
++	.preinit	= rd88f5182_pci_preinit,
++	.swizzle	= pci_std_swizzle,
++	.setup		= orion5x_pci_sys_setup,
++	.scan		= orion5x_pci_sys_scan_bus,
++	.map_irq	= rd88f5182_pci_map_irq,
++};
++
++static int __init rd88f5182_pci_init(void)
++{
++	if (machine_is_rd88f5182())
++		pci_common_init(&rd88f5182_pci);
++
++	return 0;
++}
++
++subsys_initcall(rd88f5182_pci_init);
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++
++static struct mv643xx_eth_platform_data rd88f5182_eth_data = {
++	.phy_addr	= 8,
++	.force_phy_addr = 1,
++};
++
++/*****************************************************************************
++ * RTC DS1338 on I2C bus
++ ****************************************************************************/
++static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
++	.driver_name	= "rtc-ds1307",
++	.type		= "ds1338",
++	.addr		= 0x68,
++};
++
++/*****************************************************************************
++ * Sata
++ ****************************************************************************/
++static struct mv_sata_platform_data rd88f5182_sata_data = {
++	.n_ports        = 2,
++};
++
++/*****************************************************************************
++ * General Setup
++ ****************************************************************************/
++
++static struct platform_device *rd88f5182_devices[] __initdata = {
++	&rd88f5182_nor_flash,
++};
++
++static void __init rd88f5182_init(void)
++{
++	/*
++	 * Setup basic Orion functions. Need to be called early.
++	 */
++	orion5x_init();
++
++	/*
++	 * Setup the CPU address decode windows for our devices
++	 */
++	orion5x_setup_dev_boot_win(RD88F5182_NOR_BOOT_BASE,
++				RD88F5182_NOR_BOOT_SIZE);
++	orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);
++
++	/*
++	 * Open a special address decode windows for the PCIE WA.
++	 */
++	orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
++				ORION5X_PCIE_WA_SIZE);
++
++	/*
++	 * Setup Multiplexing Pins --
++	 * MPP[0] Debug Led (GPIO - Out)
++	 * MPP[1] Debug Led (GPIO - Out)
++	 * MPP[2] N/A
++	 * MPP[3] RTC_Int (GPIO - In)
++	 * MPP[4] GPIO
++	 * MPP[5] GPIO
++	 * MPP[6] PCI_intA (GPIO - In)
++	 * MPP[7] PCI_intB (GPIO - In)
++	 * MPP[8-11] N/A
++	 * MPP[12] SATA 0 presence Indication
++	 * MPP[13] SATA 1 presence Indication
++	 * MPP[14] SATA 0 active Indication
++	 * MPP[15] SATA 1 active indication
++	 * MPP[16-19] Not used
++	 * MPP[20] PCI Clock to MV88F5182
++	 * MPP[21] PCI Clock to mini PCI CON11
++	 * MPP[22] USB 0 over current indication
++	 * MPP[23] USB 1 over current indication
++	 * MPP[24] USB 1 over current enable
++	 * MPP[25] USB 0 over current enable
++	 */
++
++	orion5x_write(MPP_0_7_CTRL, 0x00000003);
++	orion5x_write(MPP_8_15_CTRL, 0x55550000);
++	orion5x_write(MPP_16_19_CTRL, 0x5555);
++
++	orion5x_gpio_set_valid_pins(0x000000fb);
++
++	platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices));
++	i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
++	orion5x_eth_init(&rd88f5182_eth_data);
++	orion5x_sata_init(&rd88f5182_sata_data);
++}
++
++MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
++	/* Maintainer: Ronen Shitrit <rshitrit at 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,
++	.init_irq	= orion5x_init_irq,
++	.timer		= &orion5x_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
+new file mode 100644
+index 0000000..fd43863
+--- /dev/null
++++ b/arch/arm/mach-orion5x/ts209-setup.c
+@@ -0,0 +1,442 @@
++/*
++ * QNAP TS-109/TS-209 Board Setup
++ *
++ * Maintainer: Byron Bradley <byron.bbradley at gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mtd/nand.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
++#include <linux/i2c.h>
++#include <linux/serial_reg.h>
++#include <linux/ata_platform.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++
++#define QNAP_TS209_NOR_BOOT_BASE 0xf4000000
++#define QNAP_TS209_NOR_BOOT_SIZE SZ_8M
++
++/****************************************************************************
++ * 8MiB NOR flash. The struct mtd_partition is not in the same order as the
++ *     partitions on the device because we want to keep compatability with
++ *     existing QNAP firmware.
++ *
++ * Layout as used by QNAP:
++ *  [2] 0x00000000-0x00200000 : "Kernel"
++ *  [3] 0x00200000-0x00600000 : "RootFS1"
++ *  [4] 0x00600000-0x00700000 : "RootFS2"
++ *  [6] 0x00700000-0x00760000 : "NAS Config" (read-only)
++ *  [5] 0x00760000-0x00780000 : "U-Boot Config"
++ *  [1] 0x00780000-0x00800000 : "U-Boot" (read-only)
++ ***************************************************************************/
++static struct mtd_partition qnap_ts209_partitions[] = {
++	{
++		.name       = "U-Boot",
++		.size       = 0x00080000,
++		.offset     = 0x00780000,
++		.mask_flags = MTD_WRITEABLE,
++	}, {
++		.name   = "Kernel",
++		.size   = 0x00200000,
++		.offset = 0,
++	}, {
++		.name   = "RootFS1",
++		.size   = 0x00400000,
++		.offset = 0x00200000,
++	}, {
++		.name   = "RootFS2",
++		.size   = 0x00100000,
++		.offset = 0x00600000,
++	}, {
++		.name   = "U-Boot Config",
++		.size   = 0x00020000,
++		.offset = 0x00760000,
++	}, {
++		.name       = "NAS Config",
++		.size       = 0x00060000,
++		.offset     = 0x00700000,
++		.mask_flags = MTD_WRITEABLE,
++	}
++};
++
++static struct physmap_flash_data qnap_ts209_nor_flash_data = {
++	.width    = 1,
++	.parts    = qnap_ts209_partitions,
++	.nr_parts = ARRAY_SIZE(qnap_ts209_partitions)
++};
++
++static struct resource qnap_ts209_nor_flash_resource = {
++	.flags = IORESOURCE_MEM,
++	.start = QNAP_TS209_NOR_BOOT_BASE,
++	.end   = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device qnap_ts209_nor_flash = {
++	.name          = "physmap-flash",
++	.id            = 0,
++	.dev           = { .platform_data = &qnap_ts209_nor_flash_data, },
++	.resource      = &qnap_ts209_nor_flash_resource,
++	.num_resources = 1,
++};
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++#define QNAP_TS209_PCI_SLOT0_OFFS	7
++#define QNAP_TS209_PCI_SLOT0_IRQ_PIN	6
++#define QNAP_TS209_PCI_SLOT1_IRQ_PIN	7
++
++void __init qnap_ts209_pci_preinit(void)
++{
++	int pin;
++
++	/*
++	 * Configure PCI GPIO IRQ pins
++	 */
++	pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
++	if (gpio_request(pin, "PCI Int1") == 0) {
++		if (gpio_direction_input(pin) == 0) {
++			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++		} else {
++			printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
++					"set_irq_type pin %d\n", pin);
++			gpio_free(pin);
++		}
++	} else {
++		printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
++				"%d\n", pin);
++	}
++
++	pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
++	if (gpio_request(pin, "PCI Int2") == 0) {
++		if (gpio_direction_input(pin) == 0) {
++			set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++		} else {
++			printk(KERN_ERR "qnap_ts209_pci_preinit failed "
++					"to set_irq_type pin %d\n", pin);
++			gpio_free(pin);
++		}
++	} else {
++		printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
++				"%d\n", pin);
++	}
++}
++
++static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++	/*
++	 * PCIE IRQ is connected internally (not GPIO)
++	 */
++	if (dev->bus->number == orion5x_pcie_local_bus_nr())
++		return IRQ_ORION5X_PCIE0_INT;
++
++	/*
++	 * PCI IRQs are connected via GPIOs
++	 */
++	switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) {
++	case 0:
++		return gpio_to_irq(QNAP_TS209_PCI_SLOT0_IRQ_PIN);
++	case 1:
++		return gpio_to_irq(QNAP_TS209_PCI_SLOT1_IRQ_PIN);
++	default:
++		return -1;
++	}
++}
++
++static struct hw_pci qnap_ts209_pci __initdata = {
++	.nr_controllers = 2,
++	.preinit        = qnap_ts209_pci_preinit,
++	.swizzle        = pci_std_swizzle,
++	.setup          = orion5x_pci_sys_setup,
++	.scan           = orion5x_pci_sys_scan_bus,
++	.map_irq        = qnap_ts209_pci_map_irq,
++};
++
++static int __init qnap_ts209_pci_init(void)
++{
++	if (machine_is_ts_x09())
++		pci_common_init(&qnap_ts209_pci);
++
++	return 0;
++}
++
++subsys_initcall(qnap_ts209_pci_init);
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++
++static struct mv643xx_eth_platform_data qnap_ts209_eth_data = {
++	.phy_addr       = 8,
++	.force_phy_addr = 1,
++};
++
++static int __init parse_hex_nibble(char n)
++{
++	if (n >= '0' && n <= '9')
++		return n - '0';
++
++	if (n >= 'A' && n <= 'F')
++		return n - 'A' + 10;
++
++	if (n >= 'a' && n <= 'f')
++		return n - 'a' + 10;
++
++	return -1;
++}
++
++static int __init parse_hex_byte(const char *b)
++{
++	int hi;
++	int lo;
++
++	hi = parse_hex_nibble(b[0]);
++	lo = parse_hex_nibble(b[1]);
++
++	if (hi < 0 || lo < 0)
++		return -1;
++
++	return (hi << 4) | lo;
++}
++
++static int __init check_mac_addr(const char *addr_str)
++{
++	u_int8_t addr[6];
++	int i;
++
++	for (i = 0; i < 6; i++) {
++		int byte;
++
++		/*
++		 * Enforce "xx:xx:xx:xx:xx:xx\n" format.
++		 */
++		if (addr_str[(i * 3) + 2] != ((i < 5) ? ':' : '\n'))
++			return -1;
++
++		byte = parse_hex_byte(addr_str + (i * 3));
++		if (byte < 0)
++			return -1;
++		addr[i] = byte;
++	}
++
++	printk(KERN_INFO "ts209: found ethernet mac address ");
++	for (i = 0; i < 6; i++)
++		printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
++
++	memcpy(qnap_ts209_eth_data.mac_addr, addr, 6);
++
++	return 0;
++}
++
++/*
++ * The 'NAS Config' flash partition has an ext2 filesystem which
++ * contains a file that has the ethernet MAC address in plain text
++ * (format "xx:xx:xx:xx:xx:xx\n".)
++ */
++static void __init ts209_find_mac_addr(void)
++{
++	unsigned long addr;
++
++	for (addr = 0x00700000; addr < 0x00760000; addr += 1024) {
++		char *nor_page;
++		int ret = 0;
++
++		nor_page = ioremap(QNAP_TS209_NOR_BOOT_BASE + addr, 1024);
++		if (nor_page != NULL) {
++			ret = check_mac_addr(nor_page);
++			iounmap(nor_page);
++		}
++
++		if (ret == 0)
++			break;
++	}
++}
++
++/*****************************************************************************
++ * RTC S35390A on I2C bus
++ ****************************************************************************/
++
++#define TS209_RTC_GPIO	3
++
++static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
++       .driver_name = "rtc-s35390a",
++       .addr        = 0x30,
++       .irq         = 0,
++};
++
++/****************************************************************************
++ * GPIO Attached Keys
++ *     Power button is attached to the PIC microcontroller
++ ****************************************************************************/
++
++#define QNAP_TS209_GPIO_KEY_MEDIA	1
++#define QNAP_TS209_GPIO_KEY_RESET	2
++
++static struct gpio_keys_button qnap_ts209_buttons[] = {
++	{
++		.code		= KEY_RESTART,
++		.gpio		= QNAP_TS209_GPIO_KEY_MEDIA,
++		.desc		= "USB Copy Button",
++		.active_low	= 1,
++	},
++	{
++		.code		= KEY_POWER,
++		.gpio		= QNAP_TS209_GPIO_KEY_RESET,
++		.desc		= "Reset Button",
++		.active_low	= 1,
++	}
++};
++
++static struct gpio_keys_platform_data qnap_ts209_button_data = {
++	.buttons	= qnap_ts209_buttons,
++	.nbuttons       = ARRAY_SIZE(qnap_ts209_buttons),
++};
++
++static struct platform_device qnap_ts209_button_device = {
++	.name		= "gpio-keys",
++	.id		= -1,
++	.num_resources	= 0,
++	.dev		= { .platform_data  = &qnap_ts209_button_data, },
++};
++
++/*****************************************************************************
++ * SATA
++ ****************************************************************************/
++static struct mv_sata_platform_data qnap_ts209_sata_data = {
++	.n_ports        = 2,
++};
++
++/*****************************************************************************
++
++ * General Setup
++ ****************************************************************************/
++
++static struct platform_device *qnap_ts209_devices[] __initdata = {
++	&qnap_ts209_nor_flash,
++	&qnap_ts209_button_device,
++};
++
++/*
++ * QNAP TS-[12]09 specific power off method via UART1-attached PIC
++ */
++
++#define UART1_REG(x)  (UART1_VIRT_BASE + ((UART_##x) << 2))
++
++static void qnap_ts209_power_off(void)
++{
++	/* 19200 baud divisor */
++	const unsigned divisor = ((ORION5X_TCLK + (8 * 19200)) / (16 * 19200));
++
++	pr_info("%s: triggering power-off...\n", __func__);
++
++	/* hijack uart1 and reset into sane state (19200,8n1) */
++	orion5x_write(UART1_REG(LCR), 0x83);
++	orion5x_write(UART1_REG(DLL), divisor & 0xff);
++	orion5x_write(UART1_REG(DLM), (divisor >> 8) & 0xff);
++	orion5x_write(UART1_REG(LCR), 0x03);
++	orion5x_write(UART1_REG(IER), 0x00);
++	orion5x_write(UART1_REG(FCR), 0x00);
++	orion5x_write(UART1_REG(MCR), 0x00);
++
++	/* send the power-off command 'A' to PIC */
++	orion5x_write(UART1_REG(TX), 'A');
++}
++
++static void __init qnap_ts209_init(void)
++{
++	/*
++	 * Setup basic Orion functions. Need to be called early.
++	 */
++	orion5x_init();
++
++	/*
++	 * Setup flash mapping
++	 */
++	orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE,
++			    QNAP_TS209_NOR_BOOT_SIZE);
++
++	/*
++	 * Open a special address decode windows for the PCIE WA.
++	 */
++	orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
++				ORION5X_PCIE_WA_SIZE);
++
++	/*
++	 * Setup Multiplexing Pins --
++	 * MPP[0] Reserved
++	 * MPP[1] USB copy button (0 active)
++	 * MPP[2] Load defaults button (0 active)
++	 * MPP[3] GPIO RTC
++	 * MPP[4-5] Reserved
++	 * MPP[6] PCI Int A
++	 * MPP[7] PCI Int B
++	 * MPP[8-11] Reserved
++	 * MPP[12] SATA 0 presence
++	 * MPP[13] SATA 1 presence
++	 * MPP[14] SATA 0 active
++	 * MPP[15] SATA 1 active
++	 * MPP[16] UART1 RXD
++	 * MPP[17] UART1 TXD
++	 * MPP[18] SW_RST (0 active)
++	 * MPP[19] Reserved
++	 * MPP[20] PCI clock 0
++	 * MPP[21] PCI clock 1
++	 * MPP[22] USB 0 over current
++	 * MPP[23-25] Reserved
++	 */
++	orion5x_write(MPP_0_7_CTRL, 0x3);
++	orion5x_write(MPP_8_15_CTRL, 0x55550000);
++	orion5x_write(MPP_16_19_CTRL, 0x5500);
++	orion5x_gpio_set_valid_pins(0x3cc0fff);
++
++	/* register ts209 specific power-off method */
++	pm_power_off = qnap_ts209_power_off;
++
++	platform_add_devices(qnap_ts209_devices,
++				ARRAY_SIZE(qnap_ts209_devices));
++
++	/* Get RTC IRQ and register the chip */
++	if (gpio_request(TS209_RTC_GPIO, "rtc") == 0) {
++		if (gpio_direction_input(TS209_RTC_GPIO) == 0)
++			qnap_ts209_i2c_rtc.irq = gpio_to_irq(TS209_RTC_GPIO);
++		else
++			gpio_free(TS209_RTC_GPIO);
++	}
++	if (qnap_ts209_i2c_rtc.irq == 0)
++		pr_warning("qnap_ts209_init: failed to get RTC IRQ\n");
++	i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);
++
++	ts209_find_mac_addr();
++	orion5x_eth_init(&qnap_ts209_eth_data);
++
++	orion5x_sata_init(&qnap_ts209_sata_data);
++}
++
++MACHINE_START(TS209, "QNAP TS-109/TS-209")
++	/* Maintainer:  Byron Bradley <byron.bbradley at 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,
++	.init_irq	= orion5x_init_irq,
++	.timer		= &orion5x_timer,
++	.fixup		= tag_fixup_mem32,
++MACHINE_END
+diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c
+index 8e00ed4..a5268c3 100644
+--- a/arch/arm/mach-pnx4008/clock.c
++++ b/arch/arm/mach-pnx4008/clock.c
+@@ -21,7 +21,6 @@
+ #include <linux/err.h>
+ #include <linux/delay.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ 
+diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c
+index 1ab84ce..ef179ca 100644
+--- a/arch/arm/mach-pnx4008/gpio.c
++++ b/arch/arm/mach-pnx4008/gpio.c
+@@ -17,7 +17,6 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+ #include <asm/arch/platform.h>
+ #include <asm/arch/gpio.h>
+diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
+index 0908bea..5da7a68 100644
+--- a/arch/arm/mach-pxa/Kconfig
++++ b/arch/arm/mach-pxa/Kconfig
+@@ -23,6 +23,12 @@ endif
+ choice
+ 	prompt "Select target board"
+ 
++config ARCH_GUMSTIX
++	bool "Gumstix XScale boards"
++	help
++	  Say Y here if you intend to run this kernel on a
++	  Gumstix Full Function Minature Computer.
++
+ config ARCH_LUBBOCK
+ 	bool "Intel DBPXA250 Development Platform"
+ 	select PXA25x
+@@ -160,6 +166,20 @@ endchoice
+ 
+ endif
+ 
++if ARCH_GUMSTIX
++
++choice
++	prompt "Select target Gumstix board"
++
++config MACH_GUMSTIX_F
++	bool "Basix, Connex, ws-200ax, ws-400ax systems"
++	select PXA25x
++
++endchoice
++
++endif
++
++
+ if MACH_TRIZEPS4
+ 
+ choice
+diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
+index 6e0c4f5..7cdcb45 100644
+--- a/arch/arm/mach-pxa/Makefile
++++ b/arch/arm/mach-pxa/Makefile
+@@ -5,13 +5,14 @@
+ # Common support (must be linked before board specific support)
+ obj-y				+= clock.o devices.o generic.o irq.o dma.o \
+ 				   time.o gpio.o
+-obj-$(CONFIG_PXA25x)		+= pxa25x.o
+-obj-$(CONFIG_PXA27x)		+= pxa27x.o
+-obj-$(CONFIG_PXA3xx)		+= pxa3xx.o mfp.o smemc.o
++obj-$(CONFIG_PXA25x)		+= pxa25x.o mfp-pxa2xx.o
++obj-$(CONFIG_PXA27x)		+= pxa27x.o mfp-pxa2xx.o
++obj-$(CONFIG_PXA3xx)		+= pxa3xx.o mfp-pxa3xx.o smemc.o
+ obj-$(CONFIG_CPU_PXA300)	+= pxa300.o
+ obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
+ 
+ # Specific board support
++obj-$(CONFIG_ARCH_GUMSTIX)	+= gumstix.o
+ obj-$(CONFIG_ARCH_LUBBOCK)	+= lubbock.o
+ obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
+ obj-$(CONFIG_MACH_MAINSTONE)	+= mainstone.o
+diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
+index df5ae27..e97dc59 100644
+--- a/arch/arm/mach-pxa/clock.c
++++ b/arch/arm/mach-pxa/clock.c
+@@ -13,6 +13,7 @@
+ #include <linux/delay.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/hardware.h>
+ 
+ #include "devices.h"
+diff --git a/arch/arm/mach-pxa/cm-x270-pci.c b/arch/arm/mach-pxa/cm-x270-pci.c
+index fcda7d5..ac7f05f 100644
+--- a/arch/arm/mach-pxa/cm-x270-pci.c
++++ b/arch/arm/mach-pxa/cm-x270-pci.c
+@@ -23,6 +23,7 @@
+ #include <asm/mach/pci.h>
+ #include <asm/arch/cm-x270.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/mach-types.h>
+ 
+ #include <asm/hardware/it8152.h>
+diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
+index ecdbc96..6d4416a 100644
+--- a/arch/arm/mach-pxa/cm-x270.c
++++ b/arch/arm/mach-pxa/cm-x270.c
+@@ -30,6 +30,7 @@
+ 
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/ohci.h>
+ #include <asm/arch/mmc.h>
+diff --git a/arch/arm/mach-pxa/colibri.c b/arch/arm/mach-pxa/colibri.c
+index 6db54e3..43bf5a1 100644
+--- a/arch/arm/mach-pxa/colibri.c
++++ b/arch/arm/mach-pxa/colibri.c
+@@ -29,6 +29,7 @@
+ #include <asm/mach/irq.h>
+ #include <asm/mach/flash.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/colibri.h>
+ 
+ #include "generic.h"
+diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
+index 9292576..259ca82 100644
+--- a/arch/arm/mach-pxa/corgi.c
++++ b/arch/arm/mach-pxa/corgi.c
+@@ -36,6 +36,7 @@
+ #include <asm/mach/irq.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/udc.h>
+diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c
+index 392c387..0a85f70 100644
+--- a/arch/arm/mach-pxa/corgi_pm.c
++++ b/arch/arm/mach-pxa/corgi_pm.c
+@@ -26,6 +26,7 @@
+ #include <asm/arch/sharpsl.h>
+ #include <asm/arch/corgi.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include "sharpsl.h"
+ 
+ #define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
+diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
+index 3170622..eccc45d 100644
+--- a/arch/arm/mach-pxa/corgi_ssp.c
++++ b/arch/arm/mach-pxa/corgi_ssp.c
+@@ -21,6 +21,7 @@
+ 
+ #include <asm/arch/ssp.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/regs-ssp.h>
+ #include "sharpsl.h"
+ 
+diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
+index bfccb80..d6c05b6 100644
+--- a/arch/arm/mach-pxa/devices.c
++++ b/arch/arm/mach-pxa/devices.c
+@@ -11,6 +11,8 @@
+ #include <asm/arch/irda.h>
+ #include <asm/arch/i2c.h>
+ #include <asm/arch/ohci.h>
++#include <asm/arch/pxa27x_keypad.h>
++#include <asm/arch/camera.h>
+ 
+ #include "devices.h"
+ 
+@@ -396,6 +398,31 @@ struct platform_device pxa25x_device_assp = {
+ 
+ #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ 
++static struct resource pxa27x_resource_keypad[] = {
++	[0] = {
++		.start	= 0x41500000,
++		.end	= 0x4150004c,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= IRQ_KEYPAD,
++		.end	= IRQ_KEYPAD,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++struct platform_device pxa27x_device_keypad = {
++	.name		= "pxa27x-keypad",
++	.id		= -1,
++	.resource	= pxa27x_resource_keypad,
++	.num_resources	= ARRAY_SIZE(pxa27x_resource_keypad),
++};
++
++void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
++{
++	pxa_register_device(&pxa27x_device_keypad, info);
++}
++
+ static u64 pxa27x_ohci_dma_mask = DMA_BIT_MASK(32);
+ 
+ static struct resource pxa27x_resource_ohci[] = {
+@@ -540,6 +567,37 @@ struct platform_device pxa27x_device_ssp3 = {
+ 	.resource	= pxa27x_resource_ssp3,
+ 	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp3),
+ };
++
++static struct resource pxa27x_resource_camera[] = {
++	[0] = {
++		.start	= 0x50000000,
++		.end	= 0x50000fff,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= IRQ_CAMERA,
++		.end	= IRQ_CAMERA,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32);
++
++static struct platform_device pxa27x_device_camera = {
++	.name		= "pxa27x-camera",
++	.id		= 0, /* This is used to put cameras on this interface */
++	.dev		= {
++		.dma_mask      		= &pxa27x_dma_mask_camera,
++		.coherent_dma_mask	= 0xffffffff,
++	},
++	.num_resources	= ARRAY_SIZE(pxa27x_resource_camera),
++	.resource	= pxa27x_resource_camera,
++};
++
++void __init pxa_set_camera_info(struct pxacamera_platform_data *info)
++{
++	pxa_register_device(&pxa27x_device_camera, info);
++}
+ #endif /* CONFIG_PXA27x || CONFIG_PXA3xx */
+ 
+ #ifdef CONFIG_PXA3xx
+diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
+index 96c7c89..fcab017 100644
+--- a/arch/arm/mach-pxa/devices.h
++++ b/arch/arm/mach-pxa/devices.h
+@@ -14,6 +14,7 @@ extern struct platform_device pxa_device_rtc;
+ 
+ extern struct platform_device pxa27x_device_i2c_power;
+ extern struct platform_device pxa27x_device_ohci;
++extern struct platform_device pxa27x_device_keypad;
+ 
+ extern struct platform_device pxa25x_device_ssp;
+ extern struct platform_device pxa25x_device_nssp;
+diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
+index 3bb3131..edc4f07 100644
+--- a/arch/arm/mach-pxa/em-x270.c
++++ b/arch/arm/mach-pxa/em-x270.c
+@@ -23,6 +23,7 @@
+ #include <asm/mach/arch.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/ohci.h>
+ #include <asm/arch/mmc.h>
+diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
+index 80721c6..331f29b 100644
+--- a/arch/arm/mach-pxa/generic.c
++++ b/arch/arm/mach-pxa/generic.c
+@@ -19,14 +19,8 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/ioport.h>
+-#include <linux/pm.h>
+-#include <linux/string.h>
+-#include <linux/sysdev.h>
+ 
+ #include <asm/hardware.h>
+-#include <asm/irq.h>
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+ #include <asm/mach/map.h>
+@@ -134,59 +128,3 @@ void __init pxa_map_io(void)
+ 	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+ 	get_clk_frequency_khz(1);
+ }
+-
+-#ifdef CONFIG_PM
+-
+-static unsigned long saved_gplr[4];
+-static unsigned long saved_gpdr[4];
+-static unsigned long saved_grer[4];
+-static unsigned long saved_gfer[4];
+-
+-static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
+-{
+-	int i, gpio;
+-
+-	for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
+-		saved_gplr[i] = GPLR(gpio);
+-		saved_gpdr[i] = GPDR(gpio);
+-		saved_grer[i] = GRER(gpio);
+-		saved_gfer[i] = GFER(gpio);
+-
+-		/* Clear GPIO transition detect bits */
+-		GEDR(gpio) = GEDR(gpio);
+-	}
+-	return 0;
+-}
+-
+-static int pxa_gpio_resume(struct sys_device *dev)
+-{
+-	int i, gpio;
+-
+-	for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
+-		/* restore level with set/clear */
+-		GPSR(gpio) = saved_gplr[i];
+-		GPCR(gpio) = ~saved_gplr[i];
+-
+-		GRER(gpio) = saved_grer[i];
+-		GFER(gpio) = saved_gfer[i];
+-		GPDR(gpio) = saved_gpdr[i];
+-	}
+-	return 0;
+-}
+-#else
+-#define pxa_gpio_suspend	NULL
+-#define pxa_gpio_resume		NULL
+-#endif
+-
+-struct sysdev_class pxa_gpio_sysclass = {
+-	.name		= "gpio",
+-	.suspend	= pxa_gpio_suspend,
+-	.resume		= pxa_gpio_resume,
+-};
+-
+-static int __init pxa_gpio_init(void)
+-{
+-	return sysdev_class_register(&pxa_gpio_sysclass);
+-}
+-
+-core_initcall(pxa_gpio_init);
+diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
+index b3d10b0..5bb7ae7 100644
+--- a/arch/arm/mach-pxa/generic.h
++++ b/arch/arm/mach-pxa/generic.h
+@@ -9,14 +9,13 @@
+  * published by the Free Software Foundation.
+  */
+ 
++typedef int (*set_wake_t)(unsigned int, unsigned int);
++
+ struct sys_timer;
+ 
+ extern struct sys_timer pxa_timer;
+-extern void __init pxa_init_irq_low(void);
+-extern void __init pxa_init_irq_high(void);
+-extern void __init pxa_init_irq_gpio(int gpio_nr);
+-extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
+-extern void __init pxa_init_gpio(int gpio_nr);
++extern void __init pxa_init_irq(int irq_nr, set_wake_t fn);
++extern void __init pxa_init_gpio(int gpio_nr, set_wake_t fn);
+ extern void __init pxa25x_init_irq(void);
+ extern void __init pxa27x_init_irq(void);
+ extern void __init pxa3xx_init_irq(void);
+@@ -30,6 +29,8 @@ extern int pxa_last_gpio;
+ 	mi->bank[__nr].size = (__size), \
+ 	mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
+ 
++#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
++
+ #ifdef CONFIG_PXA25x
+ extern unsigned pxa25x_get_clk_frequency_khz(int);
+ extern unsigned pxa25x_get_memclk_frequency_10khz(void);
+@@ -56,3 +57,4 @@ extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
+ 
+ extern struct sysdev_class pxa_irq_sysclass;
+ extern struct sysdev_class pxa_gpio_sysclass;
++extern struct sysdev_class pxa3xx_mfp_sysclass;
+diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
+index 8638dd7..7d3e169 100644
+--- a/arch/arm/mach-pxa/gpio.c
++++ b/arch/arm/mach-pxa/gpio.c
+@@ -14,11 +14,14 @@
+ 
+ #include <linux/init.h>
+ #include <linux/module.h>
++#include <linux/irq.h>
++#include <linux/sysdev.h>
+ 
+ #include <asm/gpio.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ 
+ #include "generic.h"
+ 
+@@ -129,69 +132,283 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+ 		__raw_writel(mask, pxa->regbase + GPCR_OFFSET);
+ }
+ 
++#define GPIO_CHIP(_n)							\
++	[_n] = {							\
++		.regbase = GPIO##_n##_BASE,				\
++		.chip = {						\
++			.label		  = "gpio-" #_n,		\
++			.direction_input  = pxa_gpio_direction_input,	\
++			.direction_output = pxa_gpio_direction_output,	\
++			.get		  = pxa_gpio_get,		\
++			.set		  = pxa_gpio_set,		\
++			.base		  = (_n) * 32,			\
++			.ngpio		  = 32,				\
++		},							\
++	}
++
+ static struct pxa_gpio_chip pxa_gpio_chip[] = {
+-	[0] = {
+-		.regbase = GPIO0_BASE,
+-		.chip = {
+-			.label            = "gpio-0",
+-			.direction_input  = pxa_gpio_direction_input,
+-			.direction_output = pxa_gpio_direction_output,
+-			.get              = pxa_gpio_get,
+-			.set              = pxa_gpio_set,
+-			.base             = 0,
+-			.ngpio            = 32,
+-		},
+-	},
+-	[1] = {
+-		.regbase = GPIO1_BASE,
+-		.chip = {
+-			.label            = "gpio-1",
+-			.direction_input  = pxa_gpio_direction_input,
+-			.direction_output = pxa_gpio_direction_output,
+-			.get              = pxa_gpio_get,
+-			.set              = pxa_gpio_set,
+-			.base             = 32,
+-			.ngpio            = 32,
+-		},
+-	},
+-	[2] = {
+-		.regbase = GPIO2_BASE,
+-		.chip = {
+-			.label            = "gpio-2",
+-			.direction_input  = pxa_gpio_direction_input,
+-			.direction_output = pxa_gpio_direction_output,
+-			.get              = pxa_gpio_get,
+-			.set              = pxa_gpio_set,
+-			.base             = 64,
+-			.ngpio            = 32, /* 21 for PXA25x */
+-		},
+-	},
++	GPIO_CHIP(0),
++	GPIO_CHIP(1),
++	GPIO_CHIP(2),
+ #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+-	[3] = {
+-		.regbase = GPIO3_BASE,
+-		.chip = {
+-			.label            = "gpio-3",
+-			.direction_input  = pxa_gpio_direction_input,
+-			.direction_output = pxa_gpio_direction_output,
+-			.get              = pxa_gpio_get,
+-			.set              = pxa_gpio_set,
+-			.base             = 96,
+-			.ngpio            = 32,
+-		},
+-	},
++	GPIO_CHIP(3),
+ #endif
+ };
+ 
+-void __init pxa_init_gpio(int gpio_nr)
++/*
++ * PXA GPIO edge detection for IRQs:
++ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
++ * Use this instead of directly setting GRER/GFER.
++ */
++
++static unsigned long GPIO_IRQ_rising_edge[4];
++static unsigned long GPIO_IRQ_falling_edge[4];
++static unsigned long GPIO_IRQ_mask[4];
++
++/*
++ * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
++ * function of a GPIO, and GPDRx cannot be altered once configured. It
++ * is attributed as "occupied" here (I know this terminology isn't
++ * accurate, you are welcome to propose a better one :-)
++ */
++static int __gpio_is_occupied(unsigned gpio)
++{
++	if (cpu_is_pxa25x() || cpu_is_pxa27x())
++		return GAFR(gpio) & (0x3 << (((gpio) & 0xf) * 2));
++	else
++		return 0;
++}
++
++static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
++{
++	int gpio, idx;
++
++	gpio = IRQ_TO_GPIO(irq);
++	idx = gpio >> 5;
++
++	if (type == IRQ_TYPE_PROBE) {
++		/* Don't mess with enabled GPIOs using preconfigured edges or
++		 * GPIOs set to alternate function or to output during probe
++		 */
++		if ((GPIO_IRQ_rising_edge[idx] |
++		     GPIO_IRQ_falling_edge[idx] |
++		     GPDR(gpio)) & GPIO_bit(gpio))
++			return 0;
++
++		if (__gpio_is_occupied(gpio))
++			return 0;
++
++		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
++	}
++
++	GPDR(gpio) &= ~GPIO_bit(gpio);
++
++	if (type & IRQ_TYPE_EDGE_RISING)
++		__set_bit(gpio, GPIO_IRQ_rising_edge);
++	else
++		__clear_bit(gpio, GPIO_IRQ_rising_edge);
++
++	if (type & IRQ_TYPE_EDGE_FALLING)
++		__set_bit(gpio, GPIO_IRQ_falling_edge);
++	else
++		__clear_bit(gpio, GPIO_IRQ_falling_edge);
++
++	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
++	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
++
++	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio,
++		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
++		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
++	return 0;
++}
++
++/*
++ * GPIO IRQs must be acknowledged.  This is for GPIO 0 and 1.
++ */
++
++static void pxa_ack_low_gpio(unsigned int irq)
++{
++	GEDR0 = (1 << (irq - IRQ_GPIO0));
++}
++
++static void pxa_mask_low_gpio(unsigned int irq)
++{
++	ICMR &= ~(1 << (irq - PXA_IRQ(0)));
++}
++
++static void pxa_unmask_low_gpio(unsigned int irq)
++{
++	ICMR |= 1 << (irq - PXA_IRQ(0));
++}
++
++static struct irq_chip pxa_low_gpio_chip = {
++	.name		= "GPIO-l",
++	.ack		= pxa_ack_low_gpio,
++	.mask		= pxa_mask_low_gpio,
++	.unmask		= pxa_unmask_low_gpio,
++	.set_type	= pxa_gpio_irq_type,
++};
++
++/*
++ * Demux handler for GPIO>=2 edge detect interrupts
++ */
++
++#define GEDR_BITS	(sizeof(gedr) * BITS_PER_BYTE)
++
++static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
++{
++	int loop, bit, n;
++	unsigned long gedr[4];
++
++	do {
++		gedr[0] = GEDR0 & GPIO_IRQ_mask[0] & ~3;
++		gedr[1] = GEDR1 & GPIO_IRQ_mask[1];
++		gedr[2] = GEDR2 & GPIO_IRQ_mask[2];
++		gedr[3] = GEDR3 & GPIO_IRQ_mask[3];
++
++		GEDR0 = gedr[0]; GEDR1 = gedr[1];
++		GEDR2 = gedr[2]; GEDR3 = gedr[3];
++
++		loop = 0;
++		bit = find_first_bit(gedr, GEDR_BITS);
++		while (bit < GEDR_BITS) {
++			loop = 1;
++
++			n = PXA_GPIO_IRQ_BASE + bit;
++			desc_handle_irq(n, irq_desc + n);
++
++			bit = find_next_bit(gedr, GEDR_BITS, bit + 1);
++		}
++	} while (loop);
++}
++
++static void pxa_ack_muxed_gpio(unsigned int irq)
++{
++	int gpio = irq - IRQ_GPIO(2) + 2;
++	GEDR(gpio) = GPIO_bit(gpio);
++}
++
++static void pxa_mask_muxed_gpio(unsigned int irq)
++{
++	int gpio = irq - IRQ_GPIO(2) + 2;
++	__clear_bit(gpio, GPIO_IRQ_mask);
++	GRER(gpio) &= ~GPIO_bit(gpio);
++	GFER(gpio) &= ~GPIO_bit(gpio);
++}
++
++static void pxa_unmask_muxed_gpio(unsigned int irq)
++{
++	int gpio = irq - IRQ_GPIO(2) + 2;
++	int idx = gpio >> 5;
++	__set_bit(gpio, GPIO_IRQ_mask);
++	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
++	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
++}
++
++static struct irq_chip pxa_muxed_gpio_chip = {
++	.name		= "GPIO",
++	.ack		= pxa_ack_muxed_gpio,
++	.mask		= pxa_mask_muxed_gpio,
++	.unmask		= pxa_unmask_muxed_gpio,
++	.set_type	= pxa_gpio_irq_type,
++};
++
++void __init pxa_init_gpio(int gpio_nr, set_wake_t fn)
+ {
+-	int i;
++	int irq, i, gpio;
++
++	pxa_last_gpio = gpio_nr - 1;
++
++	/* clear all GPIO edge detects */
++	for (i = 0; i < gpio_nr; i += 32) {
++		GFER(i) = 0;
++		GRER(i) = 0;
++		GEDR(i) = GEDR(i);
++	}
++
++	/* GPIO 0 and 1 must have their mask bit always set */
++	GPIO_IRQ_mask[0] = 3;
++
++	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
++		set_irq_chip(irq, &pxa_low_gpio_chip);
++		set_irq_handler(irq, handle_edge_irq);
++		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++	}
++
++	for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) {
++		set_irq_chip(irq, &pxa_muxed_gpio_chip);
++		set_irq_handler(irq, handle_edge_irq);
++		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++	}
++
++	/* Install handler for GPIO>=2 edge detect interrupts */
++	set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
++
++	pxa_low_gpio_chip.set_wake = fn;
++	pxa_muxed_gpio_chip.set_wake = fn;
+ 
+ 	/* add a GPIO chip for each register bank.
+ 	 * the last PXA25x register only contains 21 GPIOs
+ 	 */
+-	for (i = 0; i < gpio_nr; i += 32) {
+-		if (i+32 > gpio_nr)
+-			pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i;
+-		gpiochip_add(&pxa_gpio_chip[i/32].chip);
++	for (gpio = 0, i = 0; gpio < gpio_nr; gpio += 32, i++) {
++		if (gpio + 32 > gpio_nr)
++			pxa_gpio_chip[i].chip.ngpio = gpio_nr - gpio;
++		gpiochip_add(&pxa_gpio_chip[i].chip);
+ 	}
+ }
++
++#ifdef CONFIG_PM
++
++static unsigned long saved_gplr[4];
++static unsigned long saved_gpdr[4];
++static unsigned long saved_grer[4];
++static unsigned long saved_gfer[4];
++
++static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
++{
++	int i, gpio;
++
++	for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
++		saved_gplr[i] = GPLR(gpio);
++		saved_gpdr[i] = GPDR(gpio);
++		saved_grer[i] = GRER(gpio);
++		saved_gfer[i] = GFER(gpio);
++
++		/* Clear GPIO transition detect bits */
++		GEDR(gpio) = GEDR(gpio);
++	}
++	return 0;
++}
++
++static int pxa_gpio_resume(struct sys_device *dev)
++{
++	int i, gpio;
++
++	for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
++		/* restore level with set/clear */
++		GPSR(gpio) = saved_gplr[i];
++		GPCR(gpio) = ~saved_gplr[i];
++
++		GRER(gpio) = saved_grer[i];
++		GFER(gpio) = saved_gfer[i];
++		GPDR(gpio) = saved_gpdr[i];
++	}
++	return 0;
++}
++#else
++#define pxa_gpio_suspend	NULL
++#define pxa_gpio_resume		NULL
++#endif
++
++struct sysdev_class pxa_gpio_sysclass = {
++	.name		= "gpio",
++	.suspend	= pxa_gpio_suspend,
++	.resume		= pxa_gpio_resume,
++};
++
++static int __init pxa_gpio_init(void)
++{
++	return sysdev_class_register(&pxa_gpio_sysclass);
++}
++
++core_initcall(pxa_gpio_init);
+diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
+new file mode 100644
+index 0000000..f01d185
+--- /dev/null
++++ b/arch/arm/mach-pxa/gumstix.c
+@@ -0,0 +1,147 @@
++/*
++ *  linux/arch/arm/mach-pxa/gumstix.c
++ *
++ *  Support for the Gumstix motherboards.
++ *
++ *  Original Author:	Craig Hughes
++ *  Created:	Feb 14, 2008
++ *  Copyright:	Craig Hughes
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ *
++ *  Implemented based on lubbock.c by Nicolas Pitre and code from Craig
++ *  Hughes
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/setup.h>
++#include <asm/memory.h>
++#include <asm/mach-types.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/sizes.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/flash.h>
++#include <asm/arch/mmc.h>
++#include <asm/arch/udc.h>
++#include <asm/arch/gumstix.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-regs.h>
++
++#include "generic.h"
++
++static struct resource flash_resource = {
++	.start	= 0x00000000,
++	.end	= SZ_64M - 1,
++	.flags	= IORESOURCE_MEM,
++};
++
++static struct mtd_partition gumstix_partitions[] = {
++	{
++		.name =		"Bootloader",
++		.size =		0x00040000,
++		.offset =	0,
++		.mask_flags =	MTD_WRITEABLE  /* force read-only */
++	} , {
++		.name =		"rootfs",
++		.size =		MTDPART_SIZ_FULL,
++		.offset =	MTDPART_OFS_APPEND
++	}
++};
++
++static struct flash_platform_data gumstix_flash_data = {
++	.map_name	= "cfi_probe",
++	.parts		= gumstix_partitions,
++	.nr_parts	= ARRAY_SIZE(gumstix_partitions),
++	.width		= 2,
++};
++
++static struct platform_device gumstix_flash_device = {
++	.name		= "pxa2xx-flash",
++	.id		= 0,
++	.dev = {
++		.platform_data = &gumstix_flash_data,
++	},
++	.resource = &flash_resource,
++	.num_resources = 1,
++};
++
++static struct platform_device *devices[] __initdata = {
++	&gumstix_flash_device,
++};
++
++#ifdef CONFIG_MMC_PXA
++static struct pxamci_platform_data gumstix_mci_platform_data;
++
++static int gumstix_mci_init(struct device *dev, irq_handler_t detect_int,
++				void *data)
++{
++	pxa_gpio_mode(GPIO6_MMCCLK_MD);
++	pxa_gpio_mode(GPIO53_MMCCLK_MD);
++	pxa_gpio_mode(GPIO8_MMCCS0_MD);
++
++	return 0;
++}
++
++static struct pxamci_platform_data gumstix_mci_platform_data = {
++	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
++	.init		= gumstix_mci_init,
++};
++
++static void __init gumstix_mmc_init(void)
++{
++	pxa_set_mci_info(&gumstix_mci_platform_data);
++}
++#else
++static void __init gumstix_mmc_init(void)
++{
++	printk(KERN_INFO "Gumstix mmc disabled\n");
++}
++#endif
++
++#ifdef CONFIG_USB_GADGET_PXA2XX
++static struct pxa2xx_udc_mach_info gumstix_udc_info __initdata = {
++	.gpio_vbus		= GPIO_GUMSTIX_USB_GPIOn,
++	.gpio_pullup		= GPIO_GUMSTIX_USB_GPIOx,
++};
++
++static void __init gumstix_udc_init(void)
++{
++	pxa_set_udc_info(&gumstix_udc_info);
++}
++#else
++static void gumstix_udc_init(void)
++{
++	printk(KERN_INFO "Gumstix udc is disabled\n");
++}
++#endif
++
++static void __init gumstix_init(void)
++{
++	gumstix_udc_init();
++	gumstix_mmc_init();
++	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
++}
++
++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,
++	.init_machine	= gumstix_init,
++MACHINE_END
+diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
+index 0a94344..2637633 100644
+--- a/arch/arm/mach-pxa/idp.c
++++ b/arch/arm/mach-pxa/idp.c
+@@ -32,6 +32,7 @@
+ #include <asm/mach/map.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/idp.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/bitfield.h>
+diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
+index 36c6a68..a9a0c3f 100644
+--- a/arch/arm/mach-pxa/irq.c
++++ b/arch/arm/mach-pxa/irq.c
+@@ -1,7 +1,7 @@
+ /*
+  *  linux/arch/arm/mach-pxa/irq.c
+  *
+- *  Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc.
++ *  Generic PXA IRQ handling
+  *
+  *  Author:	Nicolas Pitre
+  *  Created:	Jun 15, 2001
+@@ -21,308 +21,58 @@
+ #include <asm/irq.h>
+ #include <asm/mach/irq.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ 
+ #include "generic.h"
+ 
++#define IRQ_BIT(n)	(((n) - PXA_IRQ(0)) & 0x1f)
++#define _ICMR(n)	(*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR))
++#define _ICLR(n)	(*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR))
+ 
+ /*
+  * This is for peripheral IRQs internal to the PXA chip.
+  */
+ 
+-static void pxa_mask_low_irq(unsigned int irq)
++static int pxa_internal_irq_nr;
++
++static void pxa_mask_irq(unsigned int irq)
+ {
+-	ICMR &= ~(1 << irq);
++	_ICMR(irq) &= ~(1 << IRQ_BIT(irq));
+ }
+ 
+-static void pxa_unmask_low_irq(unsigned int irq)
++static void pxa_unmask_irq(unsigned int irq)
+ {
+-	ICMR |= (1 << irq);
++	_ICMR(irq) |= 1 << IRQ_BIT(irq);
+ }
+ 
+-static struct irq_chip pxa_internal_chip_low = {
++static struct irq_chip pxa_internal_irq_chip = {
+ 	.name		= "SC",
+-	.ack		= pxa_mask_low_irq,
+-	.mask		= pxa_mask_low_irq,
+-	.unmask		= pxa_unmask_low_irq,
++	.ack		= pxa_mask_irq,
++	.mask		= pxa_mask_irq,
++	.unmask		= pxa_unmask_irq,
+ };
+ 
+-void __init pxa_init_irq_low(void)
++void __init pxa_init_irq(int irq_nr, set_wake_t fn)
+ {
+ 	int irq;
+ 
+-	/* disable all IRQs */
+-	ICMR = 0;
++	pxa_internal_irq_nr = irq_nr;
+ 
+-	/* all IRQs are IRQ, not FIQ */
+-	ICLR = 0;
++	for (irq = 0; irq < irq_nr; irq += 32) {
++		_ICMR(irq) = 0;	/* disable all IRQs */
++		_ICLR(irq) = 0;	/* all IRQs are IRQ, not FIQ */
++	}
+ 
+ 	/* only unmasked interrupts kick us out of idle */
+ 	ICCR = 1;
+ 
+-	for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
+-		set_irq_chip(irq, &pxa_internal_chip_low);
+-		set_irq_handler(irq, handle_level_irq);
+-		set_irq_flags(irq, IRQF_VALID);
+-	}
+-}
+-
+-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+-
+-/*
+- * This is for the second set of internal IRQs as found on the PXA27x.
+- */
+-
+-static void pxa_mask_high_irq(unsigned int irq)
+-{
+-	ICMR2 &= ~(1 << (irq - 32));
+-}
+-
+-static void pxa_unmask_high_irq(unsigned int irq)
+-{
+-	ICMR2 |= (1 << (irq - 32));
+-}
+-
+-static struct irq_chip pxa_internal_chip_high = {
+-	.name		= "SC-hi",
+-	.ack		= pxa_mask_high_irq,
+-	.mask		= pxa_mask_high_irq,
+-	.unmask		= pxa_unmask_high_irq,
+-};
+-
+-void __init pxa_init_irq_high(void)
+-{
+-	int irq;
+-
+-	ICMR2 = 0;
+-	ICLR2 = 0;
+-
+-	for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
+-		set_irq_chip(irq, &pxa_internal_chip_high);
++	for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) {
++		set_irq_chip(irq, &pxa_internal_irq_chip);
+ 		set_irq_handler(irq, handle_level_irq);
+ 		set_irq_flags(irq, IRQF_VALID);
+ 	}
+-}
+-#endif
+-
+-/*
+- * PXA GPIO edge detection for IRQs:
+- * IRQs are generated on Falling-Edge, Rising-Edge, or both.
+- * Use this instead of directly setting GRER/GFER.
+- */
+-
+-static long GPIO_IRQ_rising_edge[4];
+-static long GPIO_IRQ_falling_edge[4];
+-static long GPIO_IRQ_mask[4];
+-
+-static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
+-{
+-	int gpio, idx;
+-
+-	gpio = IRQ_TO_GPIO(irq);
+-	idx = gpio >> 5;
+-
+-	if (type == IRQT_PROBE) {
+-	    /* Don't mess with enabled GPIOs using preconfigured edges or
+-	       GPIOs set to alternate function or to output during probe */
+-		if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx] | GPDR(gpio)) &
+-		    GPIO_bit(gpio))
+-			return 0;
+-		if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
+-			return 0;
+-		type = __IRQT_RISEDGE | __IRQT_FALEDGE;
+-	}
+-
+-	/* printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio); */
+-
+-	pxa_gpio_mode(gpio | GPIO_IN);
+-
+-	if (type & __IRQT_RISEDGE) {
+-		/* printk("rising "); */
+-		__set_bit (gpio, GPIO_IRQ_rising_edge);
+-	} else {
+-		__clear_bit (gpio, GPIO_IRQ_rising_edge);
+-	}
+-
+-	if (type & __IRQT_FALEDGE) {
+-		/* printk("falling "); */
+-		__set_bit (gpio, GPIO_IRQ_falling_edge);
+-	} else {
+-		__clear_bit (gpio, GPIO_IRQ_falling_edge);
+-	}
+-
+-	/* printk("edges\n"); */
+-
+-	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
+-	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
+-	return 0;
+-}
+-
+-/*
+- * GPIO IRQs must be acknowledged.  This is for GPIO 0 and 1.
+- */
+-
+-static void pxa_ack_low_gpio(unsigned int irq)
+-{
+-	GEDR0 = (1 << (irq - IRQ_GPIO0));
+-}
+-
+-static struct irq_chip pxa_low_gpio_chip = {
+-	.name		= "GPIO-l",
+-	.ack		= pxa_ack_low_gpio,
+-	.mask		= pxa_mask_low_irq,
+-	.unmask		= pxa_unmask_low_irq,
+-	.set_type	= pxa_gpio_irq_type,
+-};
+-
+-/*
+- * Demux handler for GPIO>=2 edge detect interrupts
+- */
+-
+-static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
+-{
+-	unsigned int mask;
+-	int loop;
+-
+-	do {
+-		loop = 0;
+-
+-		mask = GEDR0 & GPIO_IRQ_mask[0] & ~3;
+-		if (mask) {
+-			GEDR0 = mask;
+-			irq = IRQ_GPIO(2);
+-			desc = irq_desc + irq;
+-			mask >>= 2;
+-			do {
+-				if (mask & 1)
+-					desc_handle_irq(irq, desc);
+-				irq++;
+-				desc++;
+-				mask >>= 1;
+-			} while (mask);
+-			loop = 1;
+-		}
+-
+-		mask = GEDR1 & GPIO_IRQ_mask[1];
+-		if (mask) {
+-			GEDR1 = mask;
+-			irq = IRQ_GPIO(32);
+-			desc = irq_desc + irq;
+-			do {
+-				if (mask & 1)
+-					desc_handle_irq(irq, desc);
+-				irq++;
+-				desc++;
+-				mask >>= 1;
+-			} while (mask);
+-			loop = 1;
+-		}
+-
+-		mask = GEDR2 & GPIO_IRQ_mask[2];
+-		if (mask) {
+-			GEDR2 = mask;
+-			irq = IRQ_GPIO(64);
+-			desc = irq_desc + irq;
+-			do {
+-				if (mask & 1)
+-					desc_handle_irq(irq, desc);
+-				irq++;
+-				desc++;
+-				mask >>= 1;
+-			} while (mask);
+-			loop = 1;
+-		}
+-
+-		mask = GEDR3 & GPIO_IRQ_mask[3];
+-		if (mask) {
+-			GEDR3 = mask;
+-			irq = IRQ_GPIO(96);
+-			desc = irq_desc + irq;
+-			do {
+-				if (mask & 1)
+-					desc_handle_irq(irq, desc);
+-				irq++;
+-				desc++;
+-				mask >>= 1;
+-			} while (mask);
+-			loop = 1;
+-		}
+-	} while (loop);
+-}
+-
+-static void pxa_ack_muxed_gpio(unsigned int irq)
+-{
+-	int gpio = irq - IRQ_GPIO(2) + 2;
+-	GEDR(gpio) = GPIO_bit(gpio);
+-}
+-
+-static void pxa_mask_muxed_gpio(unsigned int irq)
+-{
+-	int gpio = irq - IRQ_GPIO(2) + 2;
+-	__clear_bit(gpio, GPIO_IRQ_mask);
+-	GRER(gpio) &= ~GPIO_bit(gpio);
+-	GFER(gpio) &= ~GPIO_bit(gpio);
+-}
+-
+-static void pxa_unmask_muxed_gpio(unsigned int irq)
+-{
+-	int gpio = irq - IRQ_GPIO(2) + 2;
+-	int idx = gpio >> 5;
+-	__set_bit(gpio, GPIO_IRQ_mask);
+-	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
+-	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
+-}
+-
+-static struct irq_chip pxa_muxed_gpio_chip = {
+-	.name		= "GPIO",
+-	.ack		= pxa_ack_muxed_gpio,
+-	.mask		= pxa_mask_muxed_gpio,
+-	.unmask		= pxa_unmask_muxed_gpio,
+-	.set_type	= pxa_gpio_irq_type,
+-};
+-
+-void __init pxa_init_irq_gpio(int gpio_nr)
+-{
+-	int irq, i;
+-
+-	pxa_last_gpio = gpio_nr - 1;
+-
+-	/* clear all GPIO edge detects */
+-	for (i = 0; i < gpio_nr; i += 32) {
+-		GFER(i) = 0;
+-		GRER(i) = 0;
+-		GEDR(i) = GEDR(i);
+-	}
+-
+-	/* GPIO 0 and 1 must have their mask bit always set */
+-	GPIO_IRQ_mask[0] = 3;
+-
+-	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
+-		set_irq_chip(irq, &pxa_low_gpio_chip);
+-		set_irq_handler(irq, handle_edge_irq);
+-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+-	}
+ 
+-	for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) {
+-		set_irq_chip(irq, &pxa_muxed_gpio_chip);
+-		set_irq_handler(irq, handle_edge_irq);
+-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+-	}
+-
+-	/* Install handler for GPIO>=2 edge detect interrupts */
+-	set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
+-	set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
+-
+-	pxa_init_gpio(gpio_nr);
+-}
+-
+-void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
+-{
+-	pxa_internal_chip_low.set_wake = set_wake;
+-#ifdef CONFIG_PXA27x
+-	pxa_internal_chip_high.set_wake = set_wake;
+-#endif
+-	pxa_low_gpio_chip.set_wake = set_wake;
+-	pxa_muxed_gpio_chip.set_wake = set_wake;
++	pxa_internal_irq_chip.set_wake = fn;
+ }
+ 
+ #ifdef CONFIG_PM
+@@ -330,19 +80,11 @@ static unsigned long saved_icmr[2];
+ 
+ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
+ {
+-	switch (dev->id) {
+-	case 0:
+-		saved_icmr[0] = ICMR;
+-		ICMR = 0;
+-		break;
+-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+-	case 1:
+-		saved_icmr[1] = ICMR2;
+-		ICMR2 = 0;
+-		break;
+-#endif
+-	default:
+-		return -EINVAL;
++	int i, irq = PXA_IRQ(0);
++
++	for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
++		saved_icmr[i] = _ICMR(irq);
++		_ICMR(irq) = 0;
+ 	}
+ 
+ 	return 0;
+@@ -350,22 +92,14 @@ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
+ 
+ static int pxa_irq_resume(struct sys_device *dev)
+ {
+-	switch (dev->id) {
+-	case 0:
+-		ICMR = saved_icmr[0];
+-		ICLR = 0;
+-		ICCR = 1;
+-		break;
+-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+-	case 1:
+-		ICMR2 = saved_icmr[1];
+-		ICLR2 = 0;
+-		break;
+-#endif
+-	default:
+-		return -EINVAL;
++	int i, irq = PXA_IRQ(0);
++
++	for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
++		_ICMR(irq) = saved_icmr[i];
++		_ICLR(irq) = 0;
+ 	}
+ 
++	ICCR = 1;
+ 	return 0;
+ }
+ #else
+diff --git a/arch/arm/mach-pxa/leds-trizeps4.c b/arch/arm/mach-pxa/leds-trizeps4.c
+index 2271d20..21880da 100644
+--- a/arch/arm/mach-pxa/leds-trizeps4.c
++++ b/arch/arm/mach-pxa/leds-trizeps4.c
+@@ -18,6 +18,7 @@
+ #include <asm/leds.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/trizeps4.h>
+ 
+ #include "leds.h"
+diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
+index 0a4b54c..0339606 100644
+--- a/arch/arm/mach-pxa/littleton.c
++++ b/arch/arm/mach-pxa/littleton.c
+@@ -37,12 +37,11 @@
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/ssp.h>
++#include <asm/arch/pxa27x_keypad.h>
+ #include <asm/arch/littleton.h>
+ 
+ #include "generic.h"
+ 
+-#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
+-
+ /* Littleton MFP configurations */
+ static mfp_cfg_t littleton_mfp_cfg[] __initdata = {
+ 	/* LCD */
+@@ -76,6 +75,21 @@ static mfp_cfg_t littleton_mfp_cfg[] __initdata = {
+ 
+ 	/* Debug Ethernet */
+ 	GPIO90_GPIO,
++
++	/* Keypad */
++	GPIO107_KP_DKIN_0,
++	GPIO108_KP_DKIN_1,
++	GPIO115_KP_MKIN_0,
++	GPIO116_KP_MKIN_1,
++	GPIO117_KP_MKIN_2,
++	GPIO118_KP_MKIN_3,
++	GPIO119_KP_MKIN_4,
++	GPIO120_KP_MKIN_5,
++	GPIO121_KP_MKOUT_0,
++	GPIO122_KP_MKOUT_1,
++	GPIO123_KP_MKOUT_2,
++	GPIO124_KP_MKOUT_3,
++	GPIO125_KP_MKOUT_4,
+ };
+ 
+ static struct resource smc91x_resources[] = {
+@@ -300,6 +314,54 @@ static void littleton_init_lcd(void)
+ static inline void littleton_init_lcd(void) {};
+ #endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULES */
+ 
++#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
++static unsigned int littleton_matrix_key_map[] = {
++	/* KEY(row, col, key_code) */
++	KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3),
++	KEY(0, 1, KEY_4), KEY(1, 1, KEY_5), KEY(2, 1, KEY_6), KEY(0, 2, KEY_7),
++	KEY(1, 2, KEY_8), KEY(2, 2, KEY_9),
++
++	KEY(0, 3, KEY_KPASTERISK), 	/* * */
++	KEY(2, 3, KEY_KPDOT), 		/* # */
++
++	KEY(5, 4, KEY_ENTER),
++
++	KEY(5, 0, KEY_UP),
++	KEY(5, 1, KEY_DOWN),
++	KEY(5, 2, KEY_LEFT),
++	KEY(5, 3, KEY_RIGHT),
++	KEY(3, 2, KEY_HOME),
++	KEY(4, 1, KEY_END),
++	KEY(3, 3, KEY_BACK),
++
++	KEY(4, 0, KEY_SEND),
++	KEY(4, 2, KEY_VOLUMEUP),
++	KEY(4, 3, KEY_VOLUMEDOWN),
++
++	KEY(3, 0, KEY_F22),	/* soft1 */
++	KEY(3, 1, KEY_F23),	/* soft2 */
++};
++
++static struct pxa27x_keypad_platform_data littleton_keypad_info = {
++	.matrix_key_rows	= 6,
++	.matrix_key_cols	= 5,
++	.matrix_key_map		= littleton_matrix_key_map,
++	.matrix_key_map_size	= ARRAY_SIZE(littleton_matrix_key_map),
++
++	.enable_rotary0		= 1,
++	.rotary0_up_key		= KEY_UP,
++	.rotary0_down_key	= KEY_DOWN,
++
++	.debounce_interval	= 30,
++};
++static void __init littleton_init_keypad(void)
++{
++	pxa_set_keypad_info(&littleton_keypad_info);
++}
++#else
++static inline void littleton_init_keypad(void) {}
++#endif
++
+ static void __init littleton_init(void)
+ {
+ 	/* initialize MFP configurations */
+@@ -312,6 +374,7 @@ static void __init littleton_init(void)
+ 	platform_device_register(&smc91x_device);
+ 
+ 	littleton_init_lcd();
++	littleton_init_keypad();
+ }
+ 
+ MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
+diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
+index afa62ff..a20e4b1 100644
+--- a/arch/arm/mach-pxa/lpd270.c
++++ b/arch/arm/mach-pxa/lpd270.c
+@@ -39,6 +39,7 @@
+ 
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/lpd270.h>
+ #include <asm/arch/audio.h>
+ #include <asm/arch/pxafb.h>
+diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
+index e7ae4bb..ca209c4 100644
+--- a/arch/arm/mach-pxa/lubbock.c
++++ b/arch/arm/mach-pxa/lubbock.c
+@@ -42,6 +42,7 @@
+ 
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/mfp-pxa25x.h>
+ #include <asm/arch/lubbock.h>
+ #include <asm/arch/udc.h>
+ #include <asm/arch/irda.h>
+@@ -51,6 +52,40 @@
+ #include "generic.h"
+ #include "devices.h"
+ 
++static unsigned long lubbock_pin_config[] __initdata = {
++	GPIO15_nCS_1,	/* CS1 - Flash */
++	GPIO79_nCS_3,	/* CS3 - SMC ethernet */
++
++	/* SSP data pins */
++	GPIO23_SSP1_SCLK,
++	GPIO25_SSP1_TXD,
++	GPIO26_SSP1_RXD,
++
++	/* BTUART */
++	GPIO42_BTUART_RXD,
++	GPIO43_BTUART_TXD,
++	GPIO44_BTUART_CTS,
++	GPIO45_BTUART_RTS,
++
++	/* PC Card */
++	GPIO48_nPOE,
++	GPIO49_nPWE,
++	GPIO50_nPIOR,
++	GPIO51_nPIOW,
++	GPIO52_nPCE_1,
++	GPIO53_nPCE_2,
++	GPIO54_nPSKTSEL,
++	GPIO55_nPREG,
++	GPIO56_nPWAIT,
++	GPIO57_nIOIS16,
++
++	/* MMC */
++	GPIO6_MMC_CLK,
++	GPIO8_MMC_CS0,
++
++	/* wakeup */
++	GPIO1_GPIO | WAKEUP_ON_EDGE_RISE,
++};
+ 
+ #define LUB_MISC_WR		__LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
+ 
+@@ -186,26 +221,6 @@ static struct platform_device sa1111_device = {
+ 	.resource	= sa1111_resources,
+ };
+ 
+-static struct resource smc91x_resources[] = {
+-	[0] = {
+-		.name	= "smc91x-regs",
+-		.start	= 0x0c000c00,
+-		.end	= 0x0c0fffff,
+-		.flags	= IORESOURCE_MEM,
+-	},
+-	[1] = {
+-		.start	= LUBBOCK_ETH_IRQ,
+-		.end	= LUBBOCK_ETH_IRQ,
+-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+-	},
+-	[2] = {
+-		.name	= "smc91x-attrib",
+-		.start	= 0x0e000000,
+-		.end	= 0x0e0fffff,
+-		.flags	= IORESOURCE_MEM,
+-	},
+-};
+-
+ /* ADS7846 is connected through SSP ... and if your board has J5 populated,
+  * you can select it to replace the ucb1400 by switching the touchscreen cable
+  * (to J5) and poking board registers (as done below).  Else it's only useful
+@@ -261,6 +276,26 @@ static struct spi_board_info spi_board_info[] __initdata = { {
+ },
+ };
+ 
++static struct resource smc91x_resources[] = {
++	[0] = {
++		.name	= "smc91x-regs",
++		.start	= 0x0c000c00,
++		.end	= 0x0c0fffff,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= LUBBOCK_ETH_IRQ,
++		.end	= LUBBOCK_ETH_IRQ,
++		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
++	},
++	[2] = {
++		.name	= "smc91x-attrib",
++		.start	= 0x0e000000,
++		.end	= 0x0e0fffff,
++		.flags	= IORESOURCE_MEM,
++	},
++};
++
+ static struct platform_device smc91x_device = {
+ 	.name		= "smc91x",
+ 	.id		= -1,
+@@ -404,10 +439,6 @@ static int lubbock_mci_init(struct device *dev,
+ 		irq_handler_t detect_int,
+ 		void *data)
+ {
+-	/* setup GPIO for PXA25x MMC controller	*/
+-	pxa_gpio_mode(GPIO6_MMCCLK_MD);
+-	pxa_gpio_mode(GPIO8_MMCCS0_MD);
+-
+ 	/* detect card insert/eject */
+ 	mmc_detect_int = detect_int;
+ 	init_timer(&mmc_timer);
+@@ -457,6 +488,8 @@ static void __init lubbock_init(void)
+ {
+ 	int flashboot = (LUB_CONF_SWITCHES & 1);
+ 
++	pxa2xx_mfp_config(ARRAY_AND_SIZE(lubbock_pin_config));
++
+ 	pxa_set_udc_info(&udc_info);
+ 	set_pxa_fb_info(&sharp_lm8v31);
+ 	pxa_set_mci_info(&lubbock_mci_platform_data);
+@@ -489,46 +522,6 @@ static void __init lubbock_map_io(void)
+ 	pxa_map_io();
+ 	iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc));
+ 
+-	/* SSP data pins */
+-	pxa_gpio_mode(GPIO23_SCLK_MD);
+-	pxa_gpio_mode(GPIO25_STXD_MD);
+-	pxa_gpio_mode(GPIO26_SRXD_MD);
+-
+-	/* This enables the BTUART */
+-	pxa_gpio_mode(GPIO42_BTRXD_MD);
+-	pxa_gpio_mode(GPIO43_BTTXD_MD);
+-	pxa_gpio_mode(GPIO44_BTCTS_MD);
+-	pxa_gpio_mode(GPIO45_BTRTS_MD);
+-
+-	GPSR(GPIO48_nPOE) =
+-		GPIO_bit(GPIO48_nPOE) |
+-		GPIO_bit(GPIO49_nPWE) |
+-		GPIO_bit(GPIO50_nPIOR) |
+-		GPIO_bit(GPIO51_nPIOW) |
+-		GPIO_bit(GPIO52_nPCE_1) |
+-		GPIO_bit(GPIO53_nPCE_2);
+-
+-	pxa_gpio_mode(GPIO48_nPOE_MD);
+-	pxa_gpio_mode(GPIO49_nPWE_MD);
+-	pxa_gpio_mode(GPIO50_nPIOR_MD);
+-	pxa_gpio_mode(GPIO51_nPIOW_MD);
+-	pxa_gpio_mode(GPIO52_nPCE_1_MD);
+-	pxa_gpio_mode(GPIO53_nPCE_2_MD);
+-	pxa_gpio_mode(GPIO54_pSKTSEL_MD);
+-	pxa_gpio_mode(GPIO55_nPREG_MD);
+-	pxa_gpio_mode(GPIO56_nPWAIT_MD);
+-	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+-
+-	/* This is for the SMC chip select */
+-	pxa_gpio_mode(GPIO79_nCS_3_MD);
+-
+-	/* setup sleep mode values */
+-	PWER  = 0x00000002;
+-	PFER  = 0x00000000;
+-	PRER  = 0x00000002;
+-	PGSR0 = 0x00008000;
+-	PGSR1 = 0x003F0202;
+-	PGSR2 = 0x0001C000;
+ 	PCFR |= PCFR_OPDE;
+ }
+ 
+diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
+index d98ef7a..d70be75 100644
+--- a/arch/arm/mach-pxa/magician.c
++++ b/arch/arm/mach-pxa/magician.c
+@@ -16,24 +16,106 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
++#include <linux/delay.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/input.h>
++#include <linux/mfd/htc-egpio.h>
++#include <linux/mfd/htc-pasic3.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/map.h>
+ #include <linux/mtd/physmap.h>
++#include <linux/pda_power.h>
+ 
+ #include <asm/gpio.h>
+ #include <asm/hardware.h>
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+ #include <asm/arch/magician.h>
++#include <asm/arch/mfp-pxa27x.h>
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxafb.h>
++#include <asm/arch/i2c.h>
++#include <asm/arch/mmc.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/ohci.h>
+ 
+ #include "generic.h"
+ 
++static unsigned long magician_pin_config[] = {
++
++	/* SDRAM and Static Memory I/O Signals */
++	GPIO20_nSDCS_2,
++	GPIO21_nSDCS_3,
++	GPIO15_nCS_1,
++	GPIO78_nCS_2,   /* PASIC3 */
++	GPIO79_nCS_3,   /* EGPIO CPLD */
++	GPIO80_nCS_4,
++	GPIO33_nCS_5,
++
++	/* I2C */
++	GPIO117_I2C_SCL,
++	GPIO118_I2C_SDA,
++
++	/* PWM 0 */
++	GPIO16_PWM0_OUT,
++
++	/* I2S */
++	GPIO28_I2S_BITCLK_OUT,
++	GPIO29_I2S_SDATA_IN,
++	GPIO31_I2S_SYNC,
++	GPIO113_I2S_SYSCLK,
++
++	/* SSP 2 */
++	GPIO19_SSP2_SCLK,
++	GPIO14_SSP2_SFRM,
++	GPIO89_SSP2_TXD,
++	GPIO88_SSP2_RXD,
++
++	/* MMC */
++	GPIO32_MMC_CLK,
++	GPIO92_MMC_DAT_0,
++	GPIO109_MMC_DAT_1,
++	GPIO110_MMC_DAT_2,
++	GPIO111_MMC_DAT_3,
++	GPIO112_MMC_CMD,
++
++	/* LCD */
++	GPIO58_LCD_LDD_0,
++	GPIO59_LCD_LDD_1,
++	GPIO60_LCD_LDD_2,
++	GPIO61_LCD_LDD_3,
++	GPIO62_LCD_LDD_4,
++	GPIO63_LCD_LDD_5,
++	GPIO64_LCD_LDD_6,
++	GPIO65_LCD_LDD_7,
++	GPIO66_LCD_LDD_8,
++	GPIO67_LCD_LDD_9,
++	GPIO68_LCD_LDD_10,
++	GPIO69_LCD_LDD_11,
++	GPIO70_LCD_LDD_12,
++	GPIO71_LCD_LDD_13,
++	GPIO72_LCD_LDD_14,
++	GPIO73_LCD_LDD_15,
++	GPIO74_LCD_FCLK,
++	GPIO75_LCD_LCLK,
++	GPIO76_LCD_PCLK,
++	GPIO77_LCD_BIAS,
++
++	/* QCI */
++	GPIO12_CIF_DD_7,
++	GPIO17_CIF_DD_6,
++	GPIO50_CIF_DD_3,
++	GPIO51_CIF_DD_2,
++	GPIO52_CIF_DD_4,
++	GPIO53_CIF_MCLK,
++	GPIO54_CIF_PCLK,
++	GPIO55_CIF_DD_1,
++	GPIO81_CIF_DD_0,
++	GPIO82_CIF_DD_5,
++	GPIO84_CIF_FV,
++	GPIO85_CIF_LV,
++};
++
+ /*
+  * IRDA
+  */
+@@ -83,8 +165,64 @@ static struct platform_device gpio_keys = {
+ 	.id   = -1,
+ };
+ 
++
++/*
++ * EGPIO (Xilinx CPLD)
++ *
++ * 7 32-bit aligned 8-bit registers: 3x output, 1x irq, 3x input
++ */
++
++static struct resource egpio_resources[] = {
++	[0] = {
++		.start = PXA_CS3_PHYS,
++		.end   = PXA_CS3_PHYS + 0x20,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ),
++		.end   = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ),
++		.flags = IORESOURCE_IRQ,
++	},
++};
++
++static struct htc_egpio_chip egpio_chips[] = {
++	[0] = {
++		.reg_start = 0,
++		.gpio_base = MAGICIAN_EGPIO(0, 0),
++		.num_gpios = 24,
++		.direction = HTC_EGPIO_OUTPUT,
++		.initial_values = 0x40, /* EGPIO_MAGICIAN_GSM_RESET */
++	},
++	[1] = {
++		.reg_start = 4,
++		.gpio_base = MAGICIAN_EGPIO(4, 0),
++		.num_gpios = 24,
++		.direction = HTC_EGPIO_INPUT,
++	},
++};
++
++static struct htc_egpio_platform_data egpio_info = {
++	.reg_width    = 8,
++	.bus_width    = 32,
++	.irq_base     = IRQ_BOARD_START,
++	.num_irqs     = 4,
++	.ack_register = 3,
++	.chip         = egpio_chips,
++	.num_chips    = ARRAY_SIZE(egpio_chips),
++};
++
++static struct platform_device egpio = {
++	.name          = "htc-egpio",
++	.id            = -1,
++	.resource      = egpio_resources,
++	.num_resources = ARRAY_SIZE(egpio_resources),
++	.dev = {
++		.platform_data = &egpio_info,
++	},
++};
++
+ /*
+- * LCD - Toppoly TD028STEB1
++ * LCD - Toppoly TD028STEB1 or Samsung LTP280QV
+  */
+ 
+ static struct pxafb_mode_info toppoly_modes[] = {
+@@ -103,12 +241,99 @@ static struct pxafb_mode_info toppoly_modes[] = {
+ 	},
+ };
+ 
++static struct pxafb_mode_info samsung_modes[] = {
++	{
++		.pixclock     = 96153,
++		.bpp          = 16,
++		.xres         = 240,
++		.yres         = 320,
++		.hsync_len    = 8,
++		.vsync_len    = 4,
++		.left_margin  = 9,
++		.upper_margin = 4,
++		.right_margin = 9,
++		.lower_margin = 4,
++		.sync         = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++	},
++};
++
++static void toppoly_lcd_power(int on, struct fb_var_screeninfo *si)
++{
++	pr_debug("Toppoly LCD power\n");
++
++	if (on) {
++		pr_debug("on\n");
++		gpio_set_value(EGPIO_MAGICIAN_TOPPOLY_POWER, 1);
++		gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1);
++		udelay(2000);
++		gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1);
++		udelay(2000);
++		/* FIXME: enable LCDC here */
++		udelay(2000);
++		gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1);
++		udelay(2000);
++		gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1);
++	} else {
++		pr_debug("off\n");
++		msleep(15);
++		gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0);
++		udelay(500);
++		gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0);
++		udelay(1000);
++		gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0);
++		gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0);
++	}
++}
++
++static void samsung_lcd_power(int on, struct fb_var_screeninfo *si)
++{
++	pr_debug("Samsung LCD power\n");
++
++	if (on) {
++		pr_debug("on\n");
++		if (system_rev < 3)
++			gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 1);
++		else
++			gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1);
++		mdelay(10);
++		gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1);
++		mdelay(10);
++		gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1);
++		mdelay(30);
++		gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1);
++		mdelay(10);
++	} else {
++		pr_debug("off\n");
++		mdelay(10);
++		gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0);
++		mdelay(30);
++		gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0);
++		mdelay(10);
++		gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0);
++		mdelay(10);
++		if (system_rev < 3)
++			gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);
++		else
++			gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0);
++	}
++}
++
+ static struct pxafb_mach_info toppoly_info = {
+-	.modes       = toppoly_modes,
+-	.num_modes   = 1,
+-	.fixed_modes = 1,
+-	.lccr0       = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+-	.lccr3       = LCCR3_PixRsEdg,
++	.modes           = toppoly_modes,
++	.num_modes       = 1,
++	.fixed_modes     = 1,
++	.lccr0           = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
++	.lccr3           = LCCR3_PixRsEdg,
++	.pxafb_lcd_power = toppoly_lcd_power,
++};
++
++static struct pxafb_mach_info samsung_info = {
++	.modes           = samsung_modes,
++	.num_modes       = 1,
++	.fixed_modes     = 1,
++	.lccr0           = LCCR0_LDDALT | LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
++	.lccr3           = LCCR3_PixFlEdg,
++	.pxafb_lcd_power = samsung_lcd_power,
+ };
+ 
+ /*
+@@ -120,9 +345,18 @@ static void magician_set_bl_intensity(int intensity)
+ 	if (intensity) {
+ 		PWM_CTRL0 = 1;
+ 		PWM_PERVAL0 = 0xc8;
+-		PWM_PWDUTY0 = intensity;
++		if (intensity > 0xc7) {
++			PWM_PWDUTY0 = intensity - 0x48;
++			gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 1);
++		} else {
++			PWM_PWDUTY0 = intensity;
++			gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 0);
++		}
++		gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 1);
+ 		pxa_set_cken(CKEN_PWM0, 1);
+ 	} else {
++		/* PWM_PWDUTY0 = intensity; */
++		gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 0);
+ 		pxa_set_cken(CKEN_PWM0, 0);
+ 	}
+ }
+@@ -130,18 +364,215 @@ static void magician_set_bl_intensity(int intensity)
+ static struct generic_bl_info backlight_info = {
+ 	.default_intensity = 0x64,
+ 	.limit_mask        = 0x0b,
+-	.max_intensity     = 0xc7,
++	.max_intensity     = 0xc7+0x48,
+ 	.set_bl_intensity  = magician_set_bl_intensity,
+ };
+ 
+ static struct platform_device backlight = {
+-	.name = "corgi-bl",
++	.name = "generic-bl",
+ 	.dev  = {
+ 		.platform_data = &backlight_info,
+ 	},
+ 	.id   = -1,
+ };
+ 
++/*
++ * LEDs
++ */
++
++struct gpio_led gpio_leds[] = {
++	{
++		.name = "magician::vibra",
++		.default_trigger = "none",
++		.gpio = GPIO22_MAGICIAN_VIBRA_EN,
++	},
++	{
++		.name = "magician::phone_bl",
++		.default_trigger = "none",
++		.gpio = GPIO103_MAGICIAN_LED_KP,
++	},
++};
++
++static struct gpio_led_platform_data gpio_led_info = {
++	.leds = gpio_leds,
++	.num_leds = ARRAY_SIZE(gpio_leds),
++};
++
++static struct platform_device leds_gpio = {
++	.name = "leds-gpio",
++	.id   = -1,
++	.dev  = {
++		.platform_data = &gpio_led_info,
++	},
++};
++
++static struct pasic3_led pasic3_leds[] = {
++	{
++		.led = {
++			.name            = "magician:red",
++			.default_trigger = "ds2760-battery.0-charging",
++		},
++		.hw_num = 0,
++		.bit2   = PASIC3_BIT2_LED0,
++		.mask   = PASIC3_MASK_LED0,
++	},
++	{
++		.led = {
++			.name            = "magician:green",
++			.default_trigger = "ds2760-battery.0-charging-or-full",
++		},
++		.hw_num = 1,
++		.bit2   = PASIC3_BIT2_LED1,
++		.mask   = PASIC3_MASK_LED1,
++	},
++	{
++		.led = {
++			.name            = "magician:blue",
++			.default_trigger = "bluetooth",
++		},
++		.hw_num = 2,
++		.bit2   = PASIC3_BIT2_LED2,
++		.mask   = PASIC3_MASK_LED2,
++	},
++};
++
++static struct platform_device pasic3;
++
++static struct pasic3_leds_machinfo __devinit pasic3_leds_info = {
++	.num_leds   = ARRAY_SIZE(pasic3_leds),
++	.power_gpio = EGPIO_MAGICIAN_LED_POWER,
++	.leds       = pasic3_leds,
++};
++
++/*
++ * PASIC3 with DS1WM
++ */
++
++static struct resource pasic3_resources[] = {
++	[0] = {
++		.start  = PXA_CS2_PHYS,
++		.end	= PXA_CS2_PHYS + 0x1b,
++		.flags  = IORESOURCE_MEM,
++	},
++	/* No IRQ handler in the PASIC3, DS1WM needs an external IRQ */
++	[1] = {
++		.start  = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ),
++		.end    = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ),
++		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
++	}
++};
++
++static struct pasic3_platform_data pasic3_platform_data = {
++	.bus_shift  = 2,
++	.led_pdata  = &pasic3_leds_info,
++	.clock_rate = 4000000,
++};
++
++static struct platform_device pasic3 = {
++	.name		= "pasic3",
++	.id		= -1,
++	.num_resources	= ARRAY_SIZE(pasic3_resources),
++	.resource	= pasic3_resources,
++	.dev = {
++		.platform_data = &pasic3_platform_data,
++	},
++};
++
++/*
++ * External power
++ */
++
++static int magician_is_ac_online(void)
++{
++	return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC);
++}
++
++static int magician_is_usb_online(void)
++{
++	return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_USB);
++}
++
++static void magician_set_charge(int flags)
++{
++	gpio_set_value(GPIO30_MAGICIAN_nCHARGE_EN, !flags);
++	gpio_set_value(EGPIO_MAGICIAN_CHARGE_EN, flags);
++}
++
++static char *magician_supplicants[] = {
++	"ds2760-battery.0", "backup-battery"
++};
++
++static struct pda_power_pdata power_supply_info = {
++	.is_ac_online    = magician_is_ac_online,
++	.is_usb_online   = magician_is_usb_online,
++	.set_charge      = magician_set_charge,
++	.supplied_to     = magician_supplicants,
++	.num_supplicants = ARRAY_SIZE(magician_supplicants),
++};
++
++static struct resource power_supply_resources[] = {
++	[0] = {
++		.name  = "ac",
++		.flags = IORESOURCE_IRQ,
++		.start = IRQ_MAGICIAN_AC,
++		.end   = IRQ_MAGICIAN_AC,
++	},
++	[1] = {
++		.name  = "usb",
++		.flags = IORESOURCE_IRQ,
++		.start = IRQ_MAGICIAN_AC,
++		.end   = IRQ_MAGICIAN_AC,
++	},
++};
++
++static struct platform_device power_supply = {
++	.name = "pda-power",
++	.id   = -1,
++	.dev  = {
++		.platform_data = &power_supply_info,
++	},
++	.resource      = power_supply_resources,
++	.num_resources = ARRAY_SIZE(power_supply_resources),
++};
++
++
++/*
++ * MMC/SD
++ */
++
++static int magician_mci_init(struct device *dev,
++				irq_handler_t detect_irq, void *data)
++{
++	return request_irq(IRQ_MAGICIAN_SD, detect_irq,
++				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
++				"MMC card detect", data);
++}
++
++static void magician_mci_setpower(struct device *dev, unsigned int vdd)
++{
++	struct pxamci_platform_data *pdata = dev->platform_data;
++
++	gpio_set_value(EGPIO_MAGICIAN_SD_POWER, (1 << vdd) & pdata->ocr_mask);
++}
++
++static int magician_mci_get_ro(struct device *dev)
++{
++	return (!gpio_get_value(EGPIO_MAGICIAN_nSD_READONLY));
++}
++
++static void magician_mci_exit(struct device *dev, void *data)
++{
++	free_irq(IRQ_MAGICIAN_SD, data);
++}
++
++static struct pxamci_platform_data magician_mci_info = {
++	.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
++	.init     = magician_mci_init,
++	.get_ro   = magician_mci_get_ro,
++	.setpower = magician_mci_setpower,
++	.exit     = magician_mci_exit,
++};
++
+ 
+ /*
+  * USB OHCI
+@@ -166,6 +597,11 @@ static struct pxaohci_platform_data magician_ohci_info = {
+  * StrataFlash
+  */
+ 
++static void magician_set_vpp(struct map_info *map, int vpp)
++{
++	gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, vpp);
++}
++
+ #define PXA_CS_SIZE		0x04000000
+ 
+ static struct resource strataflash_resource = {
+@@ -176,13 +612,14 @@ static struct resource strataflash_resource = {
+ 
+ static struct physmap_flash_data strataflash_data = {
+ 	.width = 4,
++	.set_vpp = magician_set_vpp,
+ };
+ 
+ static struct platform_device strataflash = {
+ 	.name          = "physmap-flash",
+ 	.id            = -1,
+-	.num_resources = 1,
+ 	.resource      = &strataflash_resource,
++	.num_resources = 1,
+ 	.dev = {
+ 		.platform_data = &strataflash_data,
+ 	},
+@@ -194,16 +631,43 @@ static struct platform_device strataflash = {
+ 
+ static struct platform_device *devices[] __initdata = {
+ 	&gpio_keys,
++	&egpio,
+ 	&backlight,
++	&pasic3,
++	&power_supply,
+ 	&strataflash,
++	&leds_gpio,
+ };
+ 
+ static void __init magician_init(void)
+ {
++	void __iomem *cpld;
++	int lcd_select;
++
++	pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));
++
+ 	platform_add_devices(devices, ARRAY_SIZE(devices));
++	pxa_set_i2c_info(NULL);
++	pxa_set_mci_info(&magician_mci_info);
+ 	pxa_set_ohci_info(&magician_ohci_info);
+ 	pxa_set_ficp_info(&magician_ficp_info);
+-	set_pxa_fb_info(&toppoly_info);
++
++	/* Check LCD type we have */
++	cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000);
++	if (cpld) {
++		u8 board_id = __raw_readb(cpld+0x14);
++		system_rev = board_id & 0x7;
++		lcd_select = board_id & 0x8;
++		iounmap(cpld);
++		pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");
++		if (lcd_select && (system_rev < 3))
++			pxa_gpio_mode(GPIO75_MAGICIAN_SAMSUNG_POWER_MD);
++		pxa_gpio_mode(GPIO104_MAGICIAN_LCD_POWER_1_MD);
++		pxa_gpio_mode(GPIO105_MAGICIAN_LCD_POWER_2_MD);
++		pxa_gpio_mode(GPIO106_MAGICIAN_LCD_POWER_3_MD);
++		set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
++	} else
++		pr_err("LCD detection: CPLD mapping failed\n");
+ }
+ 
+ 
+diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
+index 72a436f..18d47cf 100644
+--- a/arch/arm/mach-pxa/mainstone.c
++++ b/arch/arm/mach-pxa/mainstone.c
+@@ -24,6 +24,8 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/backlight.h>
++#include <linux/input.h>
++#include <linux/gpio_keys.h>
+ 
+ #include <asm/types.h>
+ #include <asm/setup.h>
+@@ -40,16 +42,94 @@
+ 
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/mfp-pxa27x.h>
+ #include <asm/arch/mainstone.h>
+ #include <asm/arch/audio.h>
+ #include <asm/arch/pxafb.h>
++#include <asm/arch/i2c.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/ohci.h>
++#include <asm/arch/pxa27x_keypad.h>
+ 
+ #include "generic.h"
+ #include "devices.h"
+ 
++static unsigned long mainstone_pin_config[] = {
++	/* Chip Select */
++	GPIO15_nCS_1,
++
++	/* LCD - 16bpp Active TFT */
++	GPIO58_LCD_LDD_0,
++	GPIO59_LCD_LDD_1,
++	GPIO60_LCD_LDD_2,
++	GPIO61_LCD_LDD_3,
++	GPIO62_LCD_LDD_4,
++	GPIO63_LCD_LDD_5,
++	GPIO64_LCD_LDD_6,
++	GPIO65_LCD_LDD_7,
++	GPIO66_LCD_LDD_8,
++	GPIO67_LCD_LDD_9,
++	GPIO68_LCD_LDD_10,
++	GPIO69_LCD_LDD_11,
++	GPIO70_LCD_LDD_12,
++	GPIO71_LCD_LDD_13,
++	GPIO72_LCD_LDD_14,
++	GPIO73_LCD_LDD_15,
++	GPIO74_LCD_FCLK,
++	GPIO75_LCD_LCLK,
++	GPIO76_LCD_PCLK,
++	GPIO77_LCD_BIAS,
++	GPIO16_PWM0_OUT,	/* Backlight */
++
++	/* MMC */
++	GPIO32_MMC_CLK,
++	GPIO112_MMC_CMD,
++	GPIO92_MMC_DAT_0,
++	GPIO109_MMC_DAT_1,
++	GPIO110_MMC_DAT_2,
++	GPIO111_MMC_DAT_3,
++
++	/* USB Host Port 1 */
++	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,
++
++	/* AC97 */
++	GPIO45_AC97_SYSCLK,
++
++	/* Keypad */
++	GPIO93_KP_DKIN_0	| WAKEUP_ON_LEVEL_HIGH,
++	GPIO94_KP_DKIN_1	| WAKEUP_ON_LEVEL_HIGH,
++	GPIO95_KP_DKIN_2	| WAKEUP_ON_LEVEL_HIGH,
++	GPIO100_KP_MKIN_0	| WAKEUP_ON_LEVEL_HIGH,
++	GPIO101_KP_MKIN_1	| WAKEUP_ON_LEVEL_HIGH,
++	GPIO102_KP_MKIN_2	| WAKEUP_ON_LEVEL_HIGH,
++	GPIO97_KP_MKIN_3	| WAKEUP_ON_LEVEL_HIGH,
++	GPIO98_KP_MKIN_4	| WAKEUP_ON_LEVEL_HIGH,
++	GPIO99_KP_MKIN_5	| WAKEUP_ON_LEVEL_HIGH,
++	GPIO103_KP_MKOUT_0,
++	GPIO104_KP_MKOUT_1,
++	GPIO105_KP_MKOUT_2,
++	GPIO106_KP_MKOUT_3,
++	GPIO107_KP_MKOUT_4,
++	GPIO108_KP_MKOUT_5,
++	GPIO96_KP_MKOUT_6,
++
++	/* GPIO */
++	GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
++};
+ 
+ static unsigned long mainstone_irq_enabled;
+ 
+@@ -278,13 +358,13 @@ static int mainstone_backlight_update_status(struct backlight_device *bl)
+ 	    bl->props.fb_blank != FB_BLANK_UNBLANK)
+ 		brightness = 0;
+ 
+-	if (brightness != 0) {
+-		pxa_gpio_mode(GPIO16_PWM0_MD);
++	if (brightness != 0)
+ 		pxa_set_cken(CKEN_PWM0, 1);
+-	}
++
+ 	PWM_CTRL0 = 0;
+ 	PWM_PWDUTY0 = brightness;
+ 	PWM_PERVAL0 = bl->props.max_brightness;
++
+ 	if (brightness == 0)
+ 		pxa_set_cken(CKEN_PWM0, 0);
+ 	return 0; /* pointless return value */
+@@ -362,16 +442,6 @@ static int mainstone_mci_init(struct device *dev, irq_handler_t mstone_detect_in
+ {
+ 	int err;
+ 
+-	/*
+-	 * setup GPIO for PXA27x MMC controller
+-	 */
+-	pxa_gpio_mode(GPIO32_MMCCLK_MD);
+-	pxa_gpio_mode(GPIO112_MMCCMD_MD);
+-	pxa_gpio_mode(GPIO92_MMCDAT0_MD);
+-	pxa_gpio_mode(GPIO109_MMCDAT1_MD);
+-	pxa_gpio_mode(GPIO110_MMCDAT2_MD);
+-	pxa_gpio_mode(GPIO111_MMCDAT3_MD);
+-
+ 	/* make sure SD/Memory Stick multiplexer's signals
+ 	 * are routed to MMC controller
+ 	 */
+@@ -434,19 +504,39 @@ static struct pxaficp_platform_data mainstone_ficp_platform_data = {
+ 	.transceiver_mode = mainstone_irda_transceiver_mode,
+ };
+ 
++static struct gpio_keys_button gpio_keys_button[] = {
++	[0] = {
++		.desc	= "wakeup",
++		.code	= KEY_SUSPEND,
++		.type	= EV_KEY,
++		.gpio	= 1,
++		.wakeup	= 1,
++	},
++};
++
++static struct gpio_keys_platform_data mainstone_gpio_keys = {
++	.buttons	= gpio_keys_button,
++	.nbuttons	= 1,
++};
++
++static struct platform_device mst_gpio_keys_device = {
++	.name		= "gpio-keys",
++	.id		= -1,
++	.dev		= {
++		.platform_data	= &mainstone_gpio_keys,
++	},
++};
++
+ static struct platform_device *platform_devices[] __initdata = {
+ 	&smc91x_device,
+ 	&mst_audio_device,
+ 	&mst_flash_device[0],
+ 	&mst_flash_device[1],
++	&mst_gpio_keys_device,
+ };
+ 
+ static int mainstone_ohci_init(struct device *dev)
+ {
+-	/* setup Port1 GPIO pin. */
+-	pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN);	/* USBHPWR1 */
+-	pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT);	/* USBHPEN1 */
+-
+ 	/* Set the Power Control Polarity Low and Power Sense
+ 	   Polarity Low to active low. */
+ 	UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
+@@ -460,10 +550,63 @@ static struct pxaohci_platform_data mainstone_ohci_platform_data = {
+ 	.init		= mainstone_ohci_init,
+ };
+ 
++#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
++static unsigned int mainstone_matrix_keys[] = {
++	KEY(0, 0, KEY_A), KEY(1, 0, KEY_B), KEY(2, 0, KEY_C),
++	KEY(3, 0, KEY_D), KEY(4, 0, KEY_E), KEY(5, 0, KEY_F),
++	KEY(0, 1, KEY_G), KEY(1, 1, KEY_H), KEY(2, 1, KEY_I),
++	KEY(3, 1, KEY_J), KEY(4, 1, KEY_K), KEY(5, 1, KEY_L),
++	KEY(0, 2, KEY_M), KEY(1, 2, KEY_N), KEY(2, 2, KEY_O),
++	KEY(3, 2, KEY_P), KEY(4, 2, KEY_Q), KEY(5, 2, KEY_R),
++	KEY(0, 3, KEY_S), KEY(1, 3, KEY_T), KEY(2, 3, KEY_U),
++	KEY(3, 3, KEY_V), KEY(4, 3, KEY_W), KEY(5, 3, KEY_X),
++	KEY(2, 4, KEY_Y), KEY(3, 4, KEY_Z),
++
++	KEY(0, 4, KEY_DOT),	/* . */
++	KEY(1, 4, KEY_CLOSE),	/* @ */
++	KEY(4, 4, KEY_SLASH),
++	KEY(5, 4, KEY_BACKSLASH),
++	KEY(0, 5, KEY_HOME),
++	KEY(1, 5, KEY_LEFTSHIFT),
++	KEY(2, 5, KEY_SPACE),
++	KEY(3, 5, KEY_SPACE),
++	KEY(4, 5, KEY_ENTER),
++	KEY(5, 5, KEY_BACKSPACE),
++
++	KEY(0, 6, KEY_UP),
++	KEY(1, 6, KEY_DOWN),
++	KEY(2, 6, KEY_LEFT),
++	KEY(3, 6, KEY_RIGHT),
++	KEY(4, 6, KEY_SELECT),
++};
++
++struct pxa27x_keypad_platform_data mainstone_keypad_info = {
++	.matrix_key_rows	= 6,
++	.matrix_key_cols	= 7,
++	.matrix_key_map		= mainstone_matrix_keys,
++	.matrix_key_map_size	= ARRAY_SIZE(mainstone_matrix_keys),
++
++	.enable_rotary0		= 1,
++	.rotary0_up_key		= KEY_UP,
++	.rotary0_down_key	= KEY_DOWN,
++
++	.debounce_interval	= 30,
++};
++
++static void __init mainstone_init_keypad(void)
++{
++	pxa_set_keypad_info(&mainstone_keypad_info);
++}
++#else
++static inline void mainstone_init_keypad(void) {}
++#endif
++
+ static void __init mainstone_init(void)
+ {
+ 	int SW7 = 0;  /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
+ 
++	pxa2xx_mfp_config(ARRAY_AND_SIZE(mainstone_pin_config));
++
+ 	mst_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
+ 	mst_flash_data[1].width = 4;
+ 
+@@ -480,31 +623,6 @@ static void __init mainstone_init(void)
+ 	 */
+ 	ARB_CNTRL = ARB_CORE_PARK | 0x234;
+ 
+-	/*
+-	 * On Mainstone, we route AC97_SYSCLK via GPIO45 to
+-	 * the audio daughter card
+-	 */
+-	pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD);
+-
+-	GPSR(GPIO48_nPOE) =
+-		GPIO_bit(GPIO48_nPOE) |
+-		GPIO_bit(GPIO49_nPWE) |
+-		GPIO_bit(GPIO50_nPIOR) |
+-		GPIO_bit(GPIO51_nPIOW) |
+-		GPIO_bit(GPIO85_nPCE_1) |
+-		GPIO_bit(GPIO54_nPCE_2);
+-
+-	pxa_gpio_mode(GPIO48_nPOE_MD);
+-	pxa_gpio_mode(GPIO49_nPWE_MD);
+-	pxa_gpio_mode(GPIO50_nPIOR_MD);
+-	pxa_gpio_mode(GPIO51_nPIOW_MD);
+-	pxa_gpio_mode(GPIO85_nPCE_1_MD);
+-	pxa_gpio_mode(GPIO54_nPCE_2_MD);
+-	pxa_gpio_mode(GPIO79_pSKTSEL_MD);
+-	pxa_gpio_mode(GPIO55_nPREG_MD);
+-	pxa_gpio_mode(GPIO56_nPWAIT_MD);
+-	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+-
+ 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+ 
+ 	/* reading Mainstone's "Virtual Configuration Register"
+@@ -520,6 +638,9 @@ static void __init mainstone_init(void)
+ 	pxa_set_mci_info(&mainstone_mci_platform_data);
+ 	pxa_set_ficp_info(&mainstone_ficp_platform_data);
+ 	pxa_set_ohci_info(&mainstone_ohci_platform_data);
++	pxa_set_i2c_info(NULL);
++
++	mainstone_init_keypad();
+ }
+ 
+ 
+@@ -537,23 +658,9 @@ static void __init mainstone_map_io(void)
+ 	pxa_map_io();
+ 	iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
+ 
+-	/* initialize sleep mode regs (wake-up sources, etc) */
+-	PGSR0 = 0x00008800;
+-	PGSR1 = 0x00000002;
+-	PGSR2 = 0x0001FC00;
+-	PGSR3 = 0x00001F81;
+-	PWER  = 0xC0000002;
+-	PRER  = 0x00000002;
+-	PFER  = 0x00000002;
+  	/*	for use I SRAM as framebuffer.	*/
+  	PSLR |= 0xF04;
+  	PCFR = 0x66;
+- 	/*	For Keypad wakeup.	*/
+- 	KPC &=~KPC_ASACT;
+- 	KPC |=KPC_AS;
+- 	PKWR  = 0x000FD000;
+- 	/*	Need read PKWR back after set it.	*/
+- 	PKWR;
+ }
+ 
+ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
+diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
+new file mode 100644
+index 0000000..22097a1
+--- /dev/null
++++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
+@@ -0,0 +1,245 @@
++/*
++ *  linux/arch/arm/mach-pxa/mfp-pxa2xx.c
++ *
++ *  PXA2xx pin mux configuration support
++ *
++ *  The GPIOs on PXA2xx can be configured as one of many alternate
++ *  functions, this is by concept samilar to the MFP configuration
++ *  on PXA3xx,  what's more important, the low power pin state and
++ *  wakeup detection are also supported by the same framework.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/sysdev.h>
++
++#include <asm/arch/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/mfp-pxa2xx.h>
++
++#include "generic.h"
++
++#define PGSR(x)		__REG2(0x40F00020, ((x) & 0x60) >> 3)
++
++#define PWER_WE35	(1 << 24)
++
++struct gpio_desc {
++	unsigned	valid		: 1;
++	unsigned	can_wakeup	: 1;
++	unsigned	keypad_gpio	: 1;
++	unsigned int	mask; /* bit mask in PWER or PKWR */
++	unsigned long	config;
++};
++
++static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1];
++
++static int __mfp_config_gpio(unsigned gpio, unsigned long c)
++{
++	unsigned long gafr, mask = GPIO_bit(gpio);
++	int fn;
++
++	fn = MFP_AF(c);
++	if (fn > 3)
++		return -EINVAL;
++
++	/* alternate function and direction */
++	gafr = GAFR(gpio) & ~(0x3 << ((gpio & 0xf) * 2));
++	GAFR(gpio) = gafr |  (fn  << ((gpio & 0xf) * 2));
++
++	if (c & MFP_DIR_OUT)
++		GPDR(gpio) |= mask;
++	else
++		GPDR(gpio) &= ~mask;
++
++	/* low power state */
++	switch (c & MFP_LPM_STATE_MASK) {
++	case MFP_LPM_DRIVE_HIGH:
++		PGSR(gpio) |= mask;
++		break;
++	case MFP_LPM_DRIVE_LOW:
++		PGSR(gpio) &= ~mask;
++		break;
++	case MFP_LPM_INPUT:
++		break;
++	default:
++		pr_warning("%s: invalid low power state for GPIO%d\n",
++				__func__, gpio);
++		return -EINVAL;
++	}
++
++	/* give early warning if MFP_LPM_CAN_WAKEUP is set on the
++	 * configurations of those pins not able to wakeup
++	 */
++	if ((c & MFP_LPM_CAN_WAKEUP) && !gpio_desc[gpio].can_wakeup) {
++		pr_warning("%s: GPIO%d unable to wakeup\n",
++				__func__, gpio);
++		return -EINVAL;
++	}
++
++	if ((c & MFP_LPM_CAN_WAKEUP) && (c & MFP_DIR_OUT)) {
++		pr_warning("%s: output GPIO%d unable to wakeup\n",
++				__func__, gpio);
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
++{
++	unsigned long flags;
++	unsigned long *c;
++	int i, gpio;
++
++	for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
++
++		gpio = mfp_to_gpio(MFP_PIN(*c));
++
++		if (!gpio_desc[gpio].valid) {
++			pr_warning("%s: GPIO%d is invalid pin\n",
++				__func__, gpio);
++			continue;
++		}
++
++		local_irq_save(flags);
++
++		gpio_desc[gpio].config = *c;
++		__mfp_config_gpio(gpio, *c);
++
++		local_irq_restore(flags);
++	}
++}
++
++int gpio_set_wake(unsigned int gpio, unsigned int on)
++{
++	struct gpio_desc *d;
++	unsigned long c;
++
++	if (gpio > mfp_to_gpio(MFP_PIN_GPIO127))
++		return -EINVAL;
++
++	d = &gpio_desc[gpio];
++	c = d->config;
++
++	if (!d->valid)
++		return -EINVAL;
++
++	if (d->keypad_gpio)
++		return -EINVAL;
++
++	if (d->can_wakeup && (c & MFP_LPM_CAN_WAKEUP)) {
++		if (on) {
++			PWER |= d->mask;
++
++			if (c & MFP_LPM_EDGE_RISE)
++				PRER |= d->mask;
++			else
++				PRER &= ~d->mask;
++
++			if (c & MFP_LPM_EDGE_FALL)
++				PFER |= d->mask;
++			else
++				PFER &= ~d->mask;
++		} else {
++			PWER &= ~d->mask;
++			PRER &= ~d->mask;
++			PFER &= ~d->mask;
++		}
++	}
++	return 0;
++}
++
++#ifdef CONFIG_PXA25x
++static int __init pxa25x_mfp_init(void)
++{
++	int i;
++
++	if (cpu_is_pxa25x()) {
++		for (i = 0; i <= 84; i++)
++			gpio_desc[i].valid = 1;
++
++		for (i = 0; i <= 15; i++) {
++			gpio_desc[i].can_wakeup = 1;
++			gpio_desc[i].mask = GPIO_bit(i);
++		}
++	}
++
++	return 0;
++}
++postcore_initcall(pxa25x_mfp_init);
++#endif /* CONFIG_PXA25x */
++
++#ifdef CONFIG_PXA27x
++static int pxa27x_pkwr_gpio[] = {
++	13, 16, 17, 34, 36, 37, 38, 39, 90, 91, 93, 94,
++	95, 96, 97, 98, 99, 100, 101, 102
++};
++
++int keypad_set_wake(unsigned int on)
++{
++	unsigned int i, gpio, mask = 0;
++
++	if (!on) {
++		PKWR = 0;
++		return 0;
++	}
++
++	for (i = 0; i < ARRAY_SIZE(pxa27x_pkwr_gpio); i++) {
++
++		gpio = pxa27x_pkwr_gpio[i];
++
++		if (gpio_desc[gpio].config & MFP_LPM_CAN_WAKEUP)
++			mask |= gpio_desc[gpio].mask;
++	}
++
++	PKWR = mask;
++	return 0;
++}
++
++static int __init pxa27x_mfp_init(void)
++{
++	int i, gpio;
++
++	if (cpu_is_pxa27x()) {
++		for (i = 0; i <= 120; i++) {
++			/* skip GPIO2, 5, 6, 7, 8, they are not
++			 * valid pins allow configuration
++			 */
++			if (i == 2 || i == 5 || i == 6 ||
++			    i == 7 || i == 8)
++				continue;
++
++			gpio_desc[i].valid = 1;
++		}
++
++		/* Keypad GPIOs */
++		for (i = 0; i < ARRAY_SIZE(pxa27x_pkwr_gpio); i++) {
++			gpio = pxa27x_pkwr_gpio[i];
++			gpio_desc[gpio].can_wakeup = 1;
++			gpio_desc[gpio].keypad_gpio = 1;
++			gpio_desc[gpio].mask = 1 << i;
++		}
++
++		/* Overwrite GPIO13 as a PWER wakeup source */
++		for (i = 0; i <= 15; i++) {
++			/* skip GPIO2, 5, 6, 7, 8 */
++			if (GPIO_bit(i) & 0x1e4)
++				continue;
++
++			gpio_desc[i].can_wakeup = 1;
++			gpio_desc[i].mask = GPIO_bit(i);
++		}
++
++		gpio_desc[35].can_wakeup = 1;
++		gpio_desc[35].mask = PWER_WE35;
++	}
++
++	return 0;
++}
++postcore_initcall(pxa27x_mfp_init);
++#endif /* CONFIG_PXA27x */
+diff --git a/arch/arm/mach-pxa/mfp-pxa3xx.c b/arch/arm/mach-pxa/mfp-pxa3xx.c
+new file mode 100644
+index 0000000..3a5b0fc
+--- /dev/null
++++ b/arch/arm/mach-pxa/mfp-pxa3xx.c
+@@ -0,0 +1,255 @@
++/*
++ * linux/arch/arm/mach-pxa/mfp.c
++ *
++ * PXA3xx Multi-Function Pin Support
++ *
++ * Copyright (C) 2007 Marvell Internation Ltd.
++ *
++ * 2007-08-21: eric miao <eric.miao at marvell.com>
++ *             initial version
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/sysdev.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/mfp.h>
++#include <asm/arch/mfp-pxa3xx.h>
++#include <asm/arch/pxa3xx-regs.h>
++
++/* mfp_spin_lock is used to ensure that MFP register configuration
++ * (most likely a read-modify-write operation) is atomic, and that
++ * mfp_table[] is consistent
++ */
++static DEFINE_SPINLOCK(mfp_spin_lock);
++
++static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
++
++struct pxa3xx_mfp_pin {
++	unsigned long	config;		/* -1 for not configured */
++	unsigned long	mfpr_off;	/* MFPRxx Register offset */
++	unsigned long	mfpr_run;	/* Run-Mode Register Value */
++	unsigned long	mfpr_lpm;	/* Low Power Mode Register Value */
++};
++
++static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
++
++/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
++static const unsigned long mfpr_lpm[] = {
++	MFPR_LPM_INPUT,
++	MFPR_LPM_DRIVE_LOW,
++	MFPR_LPM_DRIVE_HIGH,
++	MFPR_LPM_PULL_LOW,
++	MFPR_LPM_PULL_HIGH,
++	MFPR_LPM_FLOAT,
++};
++
++/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */
++static const unsigned long mfpr_pull[] = {
++	MFPR_PULL_NONE,
++	MFPR_PULL_LOW,
++	MFPR_PULL_HIGH,
++	MFPR_PULL_BOTH,
++};
++
++/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */
++static const unsigned long mfpr_edge[] = {
++	MFPR_EDGE_NONE,
++	MFPR_EDGE_RISE,
++	MFPR_EDGE_FALL,
++	MFPR_EDGE_BOTH,
++};
++
++#define mfpr_readl(off)			\
++	__raw_readl(mfpr_mmio_base + (off))
++
++#define mfpr_writel(off, val)		\
++	__raw_writel(val, mfpr_mmio_base + (off))
++
++#define mfp_configured(p)	((p)->config != -1)
++
++/*
++ * perform a read-back of any MFPR register to make sure the
++ * previous writings are finished
++ */
++#define mfpr_sync()	(void)__raw_readl(mfpr_mmio_base + 0)
++
++static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p)
++{
++	if (mfp_configured(p))
++		mfpr_writel(p->mfpr_off, p->mfpr_run);
++}
++
++static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p)
++{
++	if (mfp_configured(p)) {
++		unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR;
++		if (mfpr_clr != p->mfpr_run)
++			mfpr_writel(p->mfpr_off, mfpr_clr);
++		if (p->mfpr_lpm != mfpr_clr)
++			mfpr_writel(p->mfpr_off, p->mfpr_lpm);
++	}
++}
++
++void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num)
++{
++	unsigned long flags;
++	int i;
++
++	spin_lock_irqsave(&mfp_spin_lock, flags);
++
++	for (i = 0; i < num; i++, mfp_cfgs++) {
++		unsigned long tmp, c = *mfp_cfgs;
++		struct pxa3xx_mfp_pin *p;
++		int pin, af, drv, lpm, edge, pull;
++
++		pin = MFP_PIN(c);
++		BUG_ON(pin >= MFP_PIN_MAX);
++		p = &mfp_table[pin];
++
++		af  = MFP_AF(c);
++		drv = MFP_DS(c);
++		lpm = MFP_LPM_STATE(c);
++		edge = MFP_LPM_EDGE(c);
++		pull = MFP_PULL(c);
++
++		/* run-mode pull settings will conflict with MFPR bits of
++		 * low power mode state,  calculate mfpr_run and mfpr_lpm
++		 * individually if pull != MFP_PULL_NONE
++		 */
++		tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv);
++
++		if (likely(pull == MFP_PULL_NONE)) {
++			p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
++			p->mfpr_lpm = p->mfpr_run;
++		} else {
++			p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
++			p->mfpr_run = tmp | mfpr_pull[pull];
++		}
++
++		p->config = c; __mfp_config_run(p);
++	}
++
++	mfpr_sync();
++	spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++unsigned long pxa3xx_mfp_read(int mfp)
++{
++	unsigned long val, flags;
++
++	BUG_ON(mfp >= MFP_PIN_MAX);
++
++	spin_lock_irqsave(&mfp_spin_lock, flags);
++	val = mfpr_readl(mfp_table[mfp].mfpr_off);
++	spin_unlock_irqrestore(&mfp_spin_lock, flags);
++
++	return val;
++}
++
++void pxa3xx_mfp_write(int mfp, unsigned long val)
++{
++	unsigned long flags;
++
++	BUG_ON(mfp >= MFP_PIN_MAX);
++
++	spin_lock_irqsave(&mfp_spin_lock, flags);
++	mfpr_writel(mfp_table[mfp].mfpr_off, val);
++	mfpr_sync();
++	spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
++{
++	struct pxa3xx_mfp_addr_map *p;
++	unsigned long offset, flags;
++	int i;
++
++	spin_lock_irqsave(&mfp_spin_lock, flags);
++
++	for (p = map; p->start != MFP_PIN_INVALID; p++) {
++		offset = p->offset;
++		i = p->start;
++
++		do {
++			mfp_table[i].mfpr_off = offset;
++			mfp_table[i].mfpr_run = 0;
++			mfp_table[i].mfpr_lpm = 0;
++			offset += 4; i++;
++		} while ((i <= p->end) && (p->end != -1));
++	}
++
++	spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void __init pxa3xx_init_mfp(void)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
++		mfp_table[i].config = -1;
++}
++
++#ifdef CONFIG_PM
++/*
++ * Configure the MFPs appropriately for suspend/resume.
++ * FIXME: this should probably depend on which system state we're
++ * entering - for instance, we might not want to place MFP pins in
++ * a pull-down mode if they're an active low chip select, and we're
++ * just entering standby.
++ */
++static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state)
++{
++	int pin;
++
++	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
++		struct pxa3xx_mfp_pin *p = &mfp_table[pin];
++		__mfp_config_lpm(p);
++	}
++	return 0;
++}
++
++static int pxa3xx_mfp_resume(struct sys_device *d)
++{
++	int pin;
++
++	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
++		struct pxa3xx_mfp_pin *p = &mfp_table[pin];
++		__mfp_config_run(p);
++	}
++
++	/* clear RDH bit when MFP settings are restored
++	 *
++	 * NOTE: the last 3 bits DxS are write-1-to-clear so carefully
++	 * preserve them here in case they will be referenced later
++	 */
++	ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
++
++	return 0;
++}
++#else
++#define pxa3xx_mfp_suspend	NULL
++#define pxa3xx_mfp_resume	NULL
++#endif
++
++struct sysdev_class pxa3xx_mfp_sysclass = {
++	.name		= "mfp",
++	.suspend	= pxa3xx_mfp_suspend,
++	.resume 	= pxa3xx_mfp_resume,
++};
++
++static int __init mfp_init_devicefs(void)
++{
++	if (cpu_is_pxa3xx())
++		return sysdev_class_register(&pxa3xx_mfp_sysclass);
++
++	return 0;
++}
++postcore_initcall(mfp_init_devicefs);
+diff --git a/arch/arm/mach-pxa/mfp.c b/arch/arm/mach-pxa/mfp.c
+deleted file mode 100644
+index f5809ad..0000000
+--- a/arch/arm/mach-pxa/mfp.c
++++ /dev/null
+@@ -1,255 +0,0 @@
+-/*
+- * linux/arch/arm/mach-pxa/mfp.c
+- *
+- * PXA3xx Multi-Function Pin Support
+- *
+- * Copyright (C) 2007 Marvell Internation Ltd.
+- *
+- * 2007-08-21: eric miao <eric.miao at marvell.com>
+- *             initial version
+- *
+- *  This program is free software; you can redistribute it and/or modify
+- *  it under the terms of the GNU General Public License version 2 as
+- *  published by the Free Software Foundation.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/io.h>
+-#include <linux/sysdev.h>
+-
+-#include <asm/hardware.h>
+-#include <asm/arch/mfp.h>
+-#include <asm/arch/mfp-pxa3xx.h>
+-#include <asm/arch/pxa3xx-regs.h>
+-
+-/* mfp_spin_lock is used to ensure that MFP register configuration
+- * (most likely a read-modify-write operation) is atomic, and that
+- * mfp_table[] is consistent
+- */
+-static DEFINE_SPINLOCK(mfp_spin_lock);
+-
+-static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
+-
+-struct pxa3xx_mfp_pin {
+-	unsigned long	config;		/* -1 for not configured */
+-	unsigned long	mfpr_off;	/* MFPRxx Register offset */
+-	unsigned long	mfpr_run;	/* Run-Mode Register Value */
+-	unsigned long	mfpr_lpm;	/* Low Power Mode Register Value */
+-};
+-
+-static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
+-
+-/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
+-const static unsigned long mfpr_lpm[] = {
+-	MFPR_LPM_INPUT,
+-	MFPR_LPM_DRIVE_LOW,
+-	MFPR_LPM_DRIVE_HIGH,
+-	MFPR_LPM_PULL_LOW,
+-	MFPR_LPM_PULL_HIGH,
+-	MFPR_LPM_FLOAT,
+-};
+-
+-/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */
+-const static unsigned long mfpr_pull[] = {
+-	MFPR_PULL_NONE,
+-	MFPR_PULL_LOW,
+-	MFPR_PULL_HIGH,
+-	MFPR_PULL_BOTH,
+-};
+-
+-/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */
+-const static unsigned long mfpr_edge[] = {
+-	MFPR_EDGE_NONE,
+-	MFPR_EDGE_RISE,
+-	MFPR_EDGE_FALL,
+-	MFPR_EDGE_BOTH,
+-};
+-
+-#define mfpr_readl(off)			\
+-	__raw_readl(mfpr_mmio_base + (off))
+-
+-#define mfpr_writel(off, val)		\
+-	__raw_writel(val, mfpr_mmio_base + (off))
+-
+-#define mfp_configured(p)	((p)->config != -1)
+-
+-/*
+- * perform a read-back of any MFPR register to make sure the
+- * previous writings are finished
+- */
+-#define mfpr_sync()	(void)__raw_readl(mfpr_mmio_base + 0)
+-
+-static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p)
+-{
+-	if (mfp_configured(p))
+-		mfpr_writel(p->mfpr_off, p->mfpr_run);
+-}
+-
+-static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p)
+-{
+-	if (mfp_configured(p)) {
+-		unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR;
+-		if (mfpr_clr != p->mfpr_run)
+-			mfpr_writel(p->mfpr_off, mfpr_clr);
+-		if (p->mfpr_lpm != mfpr_clr)
+-			mfpr_writel(p->mfpr_off, p->mfpr_lpm);
+-	}
+-}
+-
+-void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num)
+-{
+-	unsigned long flags;
+-	int i;
+-
+-	spin_lock_irqsave(&mfp_spin_lock, flags);
+-
+-	for (i = 0; i < num; i++, mfp_cfgs++) {
+-		unsigned long tmp, c = *mfp_cfgs;
+-		struct pxa3xx_mfp_pin *p;
+-		int pin, af, drv, lpm, edge, pull;
+-
+-		pin = MFP_PIN(c);
+-		BUG_ON(pin >= MFP_PIN_MAX);
+-		p = &mfp_table[pin];
+-
+-		af  = MFP_AF(c);
+-		drv = MFP_DS(c);
+-		lpm = MFP_LPM_STATE(c);
+-		edge = MFP_LPM_EDGE(c);
+-		pull = MFP_PULL(c);
+-
+-		/* run-mode pull settings will conflict with MFPR bits of
+-		 * low power mode state,  calculate mfpr_run and mfpr_lpm
+-		 * individually if pull != MFP_PULL_NONE
+-		 */
+-		tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv);
+-
+-		if (likely(pull == MFP_PULL_NONE)) {
+-			p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
+-			p->mfpr_lpm = p->mfpr_run;
+-		} else {
+-			p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
+-			p->mfpr_run = tmp | mfpr_pull[pull];
+-		}
+-
+-		p->config = c; __mfp_config_run(p);
+-	}
+-
+-	mfpr_sync();
+-	spin_unlock_irqrestore(&mfp_spin_lock, flags);
+-}
+-
+-unsigned long pxa3xx_mfp_read(int mfp)
+-{
+-	unsigned long val, flags;
+-
+-	BUG_ON(mfp >= MFP_PIN_MAX);
+-
+-	spin_lock_irqsave(&mfp_spin_lock, flags);
+-	val = mfpr_readl(mfp_table[mfp].mfpr_off);
+-	spin_unlock_irqrestore(&mfp_spin_lock, flags);
+-
+-	return val;
+-}
+-
+-void pxa3xx_mfp_write(int mfp, unsigned long val)
+-{
+-	unsigned long flags;
+-
+-	BUG_ON(mfp >= MFP_PIN_MAX);
+-
+-	spin_lock_irqsave(&mfp_spin_lock, flags);
+-	mfpr_writel(mfp_table[mfp].mfpr_off, val);
+-	mfpr_sync();
+-	spin_unlock_irqrestore(&mfp_spin_lock, flags);
+-}
+-
+-void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
+-{
+-	struct pxa3xx_mfp_addr_map *p;
+-	unsigned long offset, flags;
+-	int i;
+-
+-	spin_lock_irqsave(&mfp_spin_lock, flags);
+-
+-	for (p = map; p->start != MFP_PIN_INVALID; p++) {
+-		offset = p->offset;
+-		i = p->start;
+-
+-		do {
+-			mfp_table[i].mfpr_off = offset;
+-			mfp_table[i].mfpr_run = 0;
+-			mfp_table[i].mfpr_lpm = 0;
+-			offset += 4; i++;
+-		} while ((i <= p->end) && (p->end != -1));
+-	}
+-
+-	spin_unlock_irqrestore(&mfp_spin_lock, flags);
+-}
+-
+-void __init pxa3xx_init_mfp(void)
+-{
+-	int i;
+-
+-	for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
+-		mfp_table[i].config = -1;
+-}
+-
+-#ifdef CONFIG_PM
+-/*
+- * Configure the MFPs appropriately for suspend/resume.
+- * FIXME: this should probably depend on which system state we're
+- * entering - for instance, we might not want to place MFP pins in
+- * a pull-down mode if they're an active low chip select, and we're
+- * just entering standby.
+- */
+-static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state)
+-{
+-	int pin;
+-
+-	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
+-		struct pxa3xx_mfp_pin *p = &mfp_table[pin];
+-		__mfp_config_lpm(p);
+-	}
+-	return 0;
+-}
+-
+-static int pxa3xx_mfp_resume(struct sys_device *d)
+-{
+-	int pin;
+-
+-	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
+-		struct pxa3xx_mfp_pin *p = &mfp_table[pin];
+-		__mfp_config_run(p);
+-	}
+-
+-	/* clear RDH bit when MFP settings are restored
+-	 *
+-	 * NOTE: the last 3 bits DxS are write-1-to-clear so carefully
+-	 * preserve them here in case they will be referenced later
+-	 */
+-	ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
+-
+-	return 0;
+-}
+-
+-static struct sysdev_class mfp_sysclass = {
+-	.name		= "mfp",
+-	.suspend	= pxa3xx_mfp_suspend,
+-	.resume 	= pxa3xx_mfp_resume,
+-};
+-
+-static struct sys_device mfp_device = {
+-	.id		= 0,
+-	.cls		= &mfp_sysclass,
+-};
+-
+-static int __init mfp_init_devicefs(void)
+-{
+-	sysdev_class_register(&mfp_sysclass);
+-	return sysdev_register(&mfp_device);
+-}
+-device_initcall(mfp_init_devicefs);
+-#endif
+diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
+index c14696b..3b945eb 100644
+--- a/arch/arm/mach-pxa/pcm027.c
++++ b/arch/arm/mach-pxa/pcm027.c
+@@ -29,6 +29,7 @@
+ #include <asm/mach/arch.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/pxa2xx-regs.h>
+ #include <asm/arch/pxa2xx_spi.h>
+ #include <asm/arch/pcm027.h>
+diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
+index 3dda16a..e6be9d0 100644
+--- a/arch/arm/mach-pxa/pcm990-baseboard.c
++++ b/arch/arm/mach-pxa/pcm990-baseboard.c
+@@ -23,8 +23,16 @@
+ #include <linux/irq.h>
+ #include <linux/platform_device.h>
+ #include <linux/ide.h>
++#include <linux/i2c.h>
++
++#include <media/soc_camera.h>
++
++#include <asm/gpio.h>
++#include <asm/arch/i2c.h>
++#include <asm/arch/camera.h>
+ #include <asm/mach/map.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/ohci.h>
+ #include <asm/arch/pcm990_baseboard.h>
+@@ -258,6 +266,76 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = {
+ };
+ 
+ /*
++ * PXA27x Camera specific stuff
++ */
++#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
++static int pcm990_pxacamera_init(struct device *dev)
++{
++	pxa_gpio_mode(GPIO98_CIF_DD_0_MD);
++	pxa_gpio_mode(GPIO105_CIF_DD_1_MD);
++	pxa_gpio_mode(GPIO104_CIF_DD_2_MD);
++	pxa_gpio_mode(GPIO103_CIF_DD_3_MD);
++	pxa_gpio_mode(GPIO95_CIF_DD_4_MD);
++	pxa_gpio_mode(GPIO94_CIF_DD_5_MD);
++	pxa_gpio_mode(GPIO93_CIF_DD_6_MD);
++	pxa_gpio_mode(GPIO108_CIF_DD_7_MD);
++	pxa_gpio_mode(GPIO107_CIF_DD_8_MD);
++	pxa_gpio_mode(GPIO106_CIF_DD_9_MD);
++	pxa_gpio_mode(GPIO42_CIF_MCLK_MD);
++	pxa_gpio_mode(GPIO45_CIF_PCLK_MD);
++	pxa_gpio_mode(GPIO43_CIF_FV_MD);
++	pxa_gpio_mode(GPIO44_CIF_LV_MD);
++
++	return 0;
++}
++
++/*
++ * CICR4: PCLK_EN:	Pixel clock is supplied by the sensor
++ *	MCLK_EN:	Master clock is generated by PXA
++ *	PCP:		Data sampled on the falling edge of pixel clock
++ */
++struct pxacamera_platform_data pcm990_pxacamera_platform_data = {
++	.init	= pcm990_pxacamera_init,
++	.flags  = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | PXA_CAMERA_DATAWIDTH_10 |
++		PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN/* | PXA_CAMERA_PCP*/,
++	.mclk_10khz = 1000,
++};
++
++#include <linux/i2c/pca953x.h>
++
++static struct pca953x_platform_data pca9536_data = {
++	.gpio_base	= NR_BUILTIN_GPIO + 1,
++};
++
++static struct soc_camera_link iclink[] = {
++	{
++		.bus_id	= 0, /* Must match with the camera ID above */
++		.gpio	= NR_BUILTIN_GPIO + 1,
++	}, {
++		.bus_id	= 0, /* Must match with the camera ID above */
++	}
++};
++
++/* Board I2C devices. */
++static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
++	{
++		/* Must initialize before the camera(s) */
++		I2C_BOARD_INFO("pca953x", 0x41),
++		.type = "pca9536",
++		.platform_data = &pca9536_data,
++	}, {
++		I2C_BOARD_INFO("mt9v022", 0x48),
++		.type = "mt9v022",
++		.platform_data = &iclink[0], /* With extender */
++	}, {
++		I2C_BOARD_INFO("mt9m001", 0x5d),
++		.type = "mt9m001",
++		.platform_data = &iclink[0], /* With extender */
++	},
++};
++#endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
++
++/*
+  * AC97 support
+  * Note: The connected AC97 mixer also reports interrupts at PCM990_AC97_IRQ
+  */
+@@ -326,5 +404,14 @@ void __init pcm990_baseboard_init(void)
+ 	/* USB host */
+ 	pxa_set_ohci_info(&pcm990_ohci_platform_data);
+ 
++	pxa_set_i2c_info(NULL);
++
++#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
++	pxa_set_camera_info(&pcm990_pxacamera_platform_data);
++
++	i2c_register_board_info(0, pcm990_i2c_devices,
++		ARRAY_SIZE(pcm990_i2c_devices));
++#endif
++
+ 	printk(KERN_INFO"PCM-990 Evaluation baseboard initialized\n");
+ }
+diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
+index 209eabf..ca5ac19 100644
+--- a/arch/arm/mach-pxa/poodle.c
++++ b/arch/arm/mach-pxa/poodle.c
+@@ -32,6 +32,7 @@
+ #include <asm/mach/irq.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/udc.h>
+ #include <asm/arch/irda.h>
+diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
+index 599e53f..d9b5450 100644
+--- a/arch/arm/mach-pxa/pxa25x.c
++++ b/arch/arm/mach-pxa/pxa25x.c
+@@ -26,6 +26,7 @@
+ #include <asm/hardware.h>
+ #include <asm/arch/irqs.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/mfp-pxa25x.h>
+ #include <asm/arch/pm.h>
+ #include <asm/arch/dma.h>
+ 
+@@ -129,6 +130,8 @@ static struct clk pxa25x_clks[] = {
+ 	INIT_CKEN("SSPCLK", NSSP, 3686400, 0, &pxa25x_device_nssp.dev),
+ 	INIT_CKEN("SSPCLK", ASSP, 3686400, 0, &pxa25x_device_assp.dev),
+ 
++	INIT_CKEN("AC97CLK",     AC97,     24576000, 0, NULL),
++
+ 	/*
+ 	INIT_CKEN("PWMCLK",  PWM0, 3686400,  0, NULL),
+ 	INIT_CKEN("PWMCLK",  PWM0, 3686400,  0, NULL),
+@@ -228,24 +231,10 @@ static inline void pxa25x_init_pm(void) {}
+ static int pxa25x_set_wake(unsigned int irq, unsigned int on)
+ {
+ 	int gpio = IRQ_TO_GPIO(irq);
+-	uint32_t gpio_bit, mask = 0;
+-
+-	if (gpio >= 0 && gpio <= 15) {
+-		gpio_bit = GPIO_bit(gpio);
+-		mask = gpio_bit;
+-		if (on) {
+-			if (GRER(gpio) | gpio_bit)
+-				PRER |= gpio_bit;
+-			else
+-				PRER &= ~gpio_bit;
+-
+-			if (GFER(gpio) | gpio_bit)
+-				PFER |= gpio_bit;
+-			else
+-				PFER &= ~gpio_bit;
+-		}
+-		goto set_pwer;
+-	}
++	uint32_t mask = 0;
++
++	if (gpio >= 0 && gpio < 85)
++		return gpio_set_wake(gpio, on);
+ 
+ 	if (irq == IRQ_RTCAlrm) {
+ 		mask = PWER_RTC;
+@@ -265,9 +254,8 @@ set_pwer:
+ 
+ void __init pxa25x_init_irq(void)
+ {
+-	pxa_init_irq_low();
+-	pxa_init_irq_gpio(85);
+-	pxa_init_irq_set_wake(pxa25x_set_wake);
++	pxa_init_irq(32, pxa25x_set_wake);
++	pxa_init_gpio(85, pxa25x_set_wake);
+ }
+ 
+ static struct platform_device *pxa25x_devices[] __initdata = {
+@@ -325,4 +313,4 @@ static int __init pxa25x_init(void)
+ 	return ret;
+ }
+ 
+-subsys_initcall(pxa25x_init);
++postcore_initcall(pxa25x_init);
+diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
+index 46a951c..7a2449d 100644
+--- a/arch/arm/mach-pxa/pxa27x.c
++++ b/arch/arm/mach-pxa/pxa27x.c
+@@ -23,6 +23,7 @@
+ #include <asm/arch/irqs.h>
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/mfp-pxa27x.h>
+ #include <asm/arch/ohci.h>
+ #include <asm/arch/pm.h>
+ #include <asm/arch/dma.h>
+@@ -151,12 +152,15 @@ static struct clk pxa27x_clks[] = {
+ 
+ 	INIT_CKEN("USBCLK", USBHOST, 48000000, 0, &pxa27x_device_ohci.dev),
+ 	INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
+-	INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL),
++	INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, &pxa27x_device_keypad.dev),
+ 
+ 	INIT_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
+ 	INIT_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
+ 	INIT_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
+ 
++	INIT_CKEN("AC97CLK",     AC97,     24576000, 0, NULL),
++	INIT_CKEN("AC97CONFCLK", AC97CONF, 24576000, 0, NULL),
++
+ 	/*
+ 	INIT_CKEN("PWMCLK",  PWM0, 13000000, 0, NULL),
+ 	INIT_CKEN("MSLCLK",  MSL,  48000000, 0, NULL),
+@@ -283,37 +287,16 @@ static inline void pxa27x_init_pm(void) {}
+ /* PXA27x:  Various gpios can issue wakeup events.  This logic only
+  * handles the simple cases, not the WEMUX2 and WEMUX3 options
+  */
+-#define PXA27x_GPIO_NOWAKE_MASK \
+-        ((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
+-#define WAKEMASK(gpio) \
+-        (((gpio) <= 15) \
+-                 ? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
+-                 : ((gpio == 35) ? (1 << 24) : 0))
+-
+ static int pxa27x_set_wake(unsigned int irq, unsigned int on)
+ {
+ 	int gpio = IRQ_TO_GPIO(irq);
+ 	uint32_t mask;
+ 
+-	if ((gpio >= 0 && gpio <= 15) || (gpio == 35)) {
+-		if (WAKEMASK(gpio) == 0)
+-			return -EINVAL;
+-
+-		mask = WAKEMASK(gpio);
+-
+-		if (on) {
+-			if (GRER(gpio) | GPIO_bit(gpio))
+-				PRER |= mask;
+-			else
+-				PRER &= ~mask;
++	if (gpio >= 0 && gpio < 128)
++		return gpio_set_wake(gpio, on);
+ 
+-			if (GFER(gpio) | GPIO_bit(gpio))
+-				PFER |= mask;
+-			else
+-				PFER &= ~mask;
+-		}
+-		goto set_pwer;
+-	}
++	if (irq == IRQ_KEYPAD)
++		return keypad_set_wake(on);
+ 
+ 	switch (irq) {
+ 	case IRQ_RTCAlrm:
+@@ -326,7 +309,6 @@ static int pxa27x_set_wake(unsigned int irq, unsigned int on)
+ 		return -EINVAL;
+ 	}
+ 
+-set_pwer:
+ 	if (on)
+ 		PWER |= mask;
+ 	else
+@@ -337,10 +319,8 @@ set_pwer:
+ 
+ void __init pxa27x_init_irq(void)
+ {
+-	pxa_init_irq_low();
+-	pxa_init_irq_high();
+-	pxa_init_irq_gpio(128);
+-	pxa_init_irq_set_wake(pxa27x_set_wake);
++	pxa_init_irq(34, pxa27x_set_wake);
++	pxa_init_gpio(128, pxa27x_set_wake);
+ }
+ 
+ /*
+@@ -386,10 +366,6 @@ static struct platform_device *devices[] __initdata = {
+ 
+ static struct sys_device pxa27x_sysdev[] = {
+ 	{
+-		.id	= 0,
+-		.cls	= &pxa_irq_sysclass,
+-	}, {
+-		.id	= 1,
+ 		.cls	= &pxa_irq_sysclass,
+ 	}, {
+ 		.cls	= &pxa_gpio_sysclass,
+@@ -420,4 +396,4 @@ static int __init pxa27x_init(void)
+ 	return ret;
+ }
+ 
+-subsys_initcall(pxa27x_init);
++postcore_initcall(pxa27x_init);
+diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
+index 35f25fd..dde355e 100644
+--- a/arch/arm/mach-pxa/pxa3xx.c
++++ b/arch/arm/mach-pxa/pxa3xx.c
+@@ -110,6 +110,25 @@ unsigned int pxa3xx_get_memclk_frequency_10khz(void)
+ }
+ 
+ /*
++ * Return the current AC97 clock frequency.
++ */
++static unsigned long clk_pxa3xx_ac97_getrate(struct clk *clk)
++{
++	unsigned long rate = 312000000;
++	unsigned long ac97_div;
++
++	ac97_div = AC97_DIV;
++
++	/* This may loose precision for some rates but won't for the
++	 * standard 24.576MHz.
++	 */
++	rate /= (ac97_div >> 12) & 0x7fff;
++	rate *= (ac97_div & 0xfff);
++
++	return rate;
++}
++
++/*
+  * Return the current HSIO bus clock frequency
+  */
+ static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
+@@ -156,6 +175,27 @@ static const struct clkops clk_pxa3xx_hsio_ops = {
+ 	.getrate	= clk_pxa3xx_hsio_getrate,
+ };
+ 
++static const struct clkops clk_pxa3xx_ac97_ops = {
++	.enable		= clk_pxa3xx_cken_enable,
++	.disable	= clk_pxa3xx_cken_disable,
++	.getrate	= clk_pxa3xx_ac97_getrate,
++};
++
++static void clk_pout_enable(struct clk *clk)
++{
++	OSCC |= OSCC_PEN;
++}
++
++static void clk_pout_disable(struct clk *clk)
++{
++	OSCC &= ~OSCC_PEN;
++}
++
++static const struct clkops clk_pout_ops = {
++	.enable		= clk_pout_enable,
++	.disable	= clk_pout_disable,
++};
++
+ #define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev)	\
+ 	{						\
+ 		.name	= _name,			\
+@@ -175,8 +215,16 @@ static const struct clkops clk_pxa3xx_hsio_ops = {
+ 	}
+ 
+ static struct clk pxa3xx_clks[] = {
+-	PXA3xx_CK("LCDCLK", LCD,    &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
+-	PXA3xx_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
++	{
++		.name           = "CLK_POUT",
++		.ops            = &clk_pout_ops,
++		.rate           = 13000000,
++		.delay          = 70,
++	},
++
++	PXA3xx_CK("LCDCLK",  LCD,    &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
++	PXA3xx_CK("CAMCLK",  CAMERA, &clk_pxa3xx_hsio_ops, NULL),
++	PXA3xx_CK("AC97CLK", AC97,   &clk_pxa3xx_ac97_ops, NULL),
+ 
+ 	PXA3xx_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
+ 	PXA3xx_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
+@@ -185,6 +233,7 @@ static struct clk pxa3xx_clks[] = {
+ 	PXA3xx_CKEN("I2CCLK", I2C,  32842000, 0, &pxa_device_i2c.dev),
+ 	PXA3xx_CKEN("UDCCLK", UDC,  48000000, 5, &pxa_device_udc.dev),
+ 	PXA3xx_CKEN("USBCLK", USBH, 48000000, 0, &pxa27x_device_ohci.dev),
++	PXA3xx_CKEN("KBDCLK", KEYPAD,  32768, 0, &pxa27x_device_keypad.dev),
+ 
+ 	PXA3xx_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
+ 	PXA3xx_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
+@@ -305,8 +354,10 @@ static void pxa3xx_cpu_pm_enter(suspend_state_t state)
+ 	/*
+ 	 * Don't sleep if no wakeup sources are defined
+ 	 */
+-	if (wakeup_src == 0)
++	if (wakeup_src == 0) {
++		printk(KERN_ERR "Not suspending: no wakeup sources\n");
+ 		return;
++	}
+ 
+ 	switch (state) {
+ 	case PM_SUSPEND_STANDBY:
+@@ -446,15 +497,9 @@ static int pxa3xx_set_wake(unsigned int irq, unsigned int on)
+ 
+ 	return 0;
+ }
+-
+-static void pxa3xx_init_irq_pm(void)
+-{
+-	pxa_init_irq_set_wake(pxa3xx_set_wake);
+-}
+-
+ #else
+ static inline void pxa3xx_init_pm(void) {}
+-static inline void pxa3xx_init_irq_pm(void) {}
++#define pxa3xx_set_wake	NULL
+ #endif
+ 
+ void __init pxa3xx_init_irq(void)
+@@ -465,10 +510,8 @@ void __init pxa3xx_init_irq(void)
+ 	value |= (1 << 6);
+ 	__asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
+ 
+-	pxa_init_irq_low();
+-	pxa_init_irq_high();
+-	pxa_init_irq_gpio(128);
+-	pxa3xx_init_irq_pm();
++	pxa_init_irq(56, pxa3xx_set_wake);
++	pxa_init_gpio(128, NULL);
+ }
+ 
+ /*
+@@ -490,11 +533,9 @@ static struct platform_device *devices[] __initdata = {
+ 
+ static struct sys_device pxa3xx_sysdev[] = {
+ 	{
+-		.id	= 0,
+ 		.cls	= &pxa_irq_sysclass,
+ 	}, {
+-		.id	= 1,
+-		.cls	= &pxa_irq_sysclass,
++		.cls	= &pxa3xx_mfp_sysclass,
+ 	}, {
+ 		.cls	= &pxa_gpio_sysclass,
+ 	},
+@@ -532,4 +573,4 @@ static int __init pxa3xx_init(void)
+ 	return ret;
+ }
+ 
+-subsys_initcall(pxa3xx_init);
++postcore_initcall(pxa3xx_init);
+diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
+index f9d1b61..34cd585 100644
+--- a/arch/arm/mach-pxa/sharpsl_pm.c
++++ b/arch/arm/mach-pxa/sharpsl_pm.c
+@@ -26,6 +26,7 @@
+ #include <asm/mach-types.h>
+ #include <asm/arch/pm.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/sharpsl.h>
+ #include "sharpsl.h"
+ 
+diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
+index 9e7773f..62a02c3 100644
+--- a/arch/arm/mach-pxa/spitz.c
++++ b/arch/arm/mach-pxa/spitz.c
+@@ -37,6 +37,7 @@
+ 
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/ohci.h>
+diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c
+index 745a4dc..7a7f5f9 100644
+--- a/arch/arm/mach-pxa/spitz_pm.c
++++ b/arch/arm/mach-pxa/spitz_pm.c
+@@ -26,6 +26,7 @@
+ #include <asm/arch/sharpsl.h>
+ #include <asm/arch/spitz.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include "sharpsl.h"
+ 
+ #define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
+diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
+index f99112d..6458f6d 100644
+--- a/arch/arm/mach-pxa/tosa.c
++++ b/arch/arm/mach-pxa/tosa.c
+@@ -23,6 +23,7 @@
+ #include <linux/delay.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/input.h>
++#include <linux/gpio.h>
+ 
+ #include <asm/setup.h>
+ #include <asm/memory.h>
+@@ -32,7 +33,9 @@
+ #include <asm/system.h>
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/mfp-pxa25x.h>
+ #include <asm/arch/irda.h>
++#include <asm/arch/i2c.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/udc.h>
+ 
+@@ -47,6 +50,110 @@
+ #include "generic.h"
+ #include "devices.h"
+ 
++static unsigned long tosa_pin_config[] = {
++	GPIO78_nCS_2, /* Scoop */
++	GPIO80_nCS_4, /* tg6393xb */
++	GPIO33_nCS_5, /* Scoop */
++
++	// GPIO76 CARD_VCC_ON1
++
++	GPIO19_GPIO, /* Reset out */
++	GPIO1_RST | WAKEUP_ON_EDGE_FALL,
++
++	GPIO0_GPIO | WAKEUP_ON_EDGE_FALL, /* WAKE_UP */
++	GPIO2_GPIO | WAKEUP_ON_EDGE_BOTH, /* AC_IN */
++	GPIO3_GPIO | WAKEUP_ON_EDGE_FALL, /* RECORD */
++	GPIO4_GPIO | WAKEUP_ON_EDGE_FALL, /* SYNC */
++	GPIO20_GPIO, /* EAR_IN */
++	GPIO22_GPIO, /* On */
++
++	GPIO5_GPIO, /* USB_IN */
++	GPIO32_GPIO, /* Pen IRQ */
++
++	GPIO7_GPIO, /* Jacket Detect */
++	GPIO14_GPIO, /* BAT0_CRG */
++	GPIO12_GPIO, /* BAT1_CRG */
++	GPIO17_GPIO, /* BAT0_LOW */
++	GPIO84_GPIO, /* BAT1_LOW */
++	GPIO38_GPIO, /* BAT_LOCK */
++
++	GPIO11_3_6MHz,
++	GPIO15_GPIO, /* TC6393XB IRQ */
++	GPIO18_RDY,
++	GPIO27_GPIO, /* LCD Sync */
++
++	/* MMC */
++	GPIO6_MMC_CLK,
++	GPIO8_MMC_CS0,
++	GPIO9_GPIO, /* Detect */
++	// GPIO10 nSD_INT
++
++	/* CF */
++	GPIO13_GPIO, /* CD_IRQ */
++	GPIO21_GPIO, /* Main Slot IRQ */
++	GPIO36_GPIO, /* Jacket Slot IRQ */
++	GPIO48_nPOE,
++	GPIO49_nPWE,
++	GPIO50_nPIOR,
++	GPIO51_nPIOW,
++	GPIO52_nPCE_1,
++	GPIO53_nPCE_2,
++	GPIO54_nPSKTSEL,
++	GPIO55_nPREG,
++	GPIO56_nPWAIT,
++	GPIO57_nIOIS16,
++
++	/* AC97 */
++	GPIO31_AC97_SYNC,
++	GPIO30_AC97_SDATA_OUT,
++	GPIO28_AC97_BITCLK,
++	GPIO29_AC97_SDATA_IN_0,
++	// GPIO79 nAUD_IRQ
++
++	/* FFUART */
++	GPIO34_FFUART_RXD,
++	GPIO35_FFUART_CTS,
++	GPIO37_FFUART_DSR,
++	GPIO39_FFUART_TXD,
++	GPIO40_FFUART_DTR,
++	GPIO41_FFUART_RTS,
++
++	/* BTUART */
++	GPIO42_BTUART_RXD,
++	GPIO43_BTUART_TXD,
++	GPIO44_BTUART_CTS,
++	GPIO45_BTUART_RTS,
++
++	/* IrDA */
++	GPIO46_STUART_RXD,
++	GPIO47_STUART_TXD,
++
++	/* Keybd */
++	GPIO58_GPIO,
++	GPIO59_GPIO,
++	GPIO60_GPIO,
++	GPIO61_GPIO,
++	GPIO62_GPIO,
++	GPIO63_GPIO,
++	GPIO64_GPIO,
++	GPIO65_GPIO,
++	GPIO66_GPIO,
++	GPIO67_GPIO,
++	GPIO68_GPIO,
++	GPIO69_GPIO,
++	GPIO70_GPIO,
++	GPIO71_GPIO,
++	GPIO72_GPIO,
++	GPIO73_GPIO,
++	GPIO74_GPIO,
++	GPIO75_GPIO,
++
++	/* SPI */
++	GPIO81_SSP2_CLK_OUT,
++	GPIO82_SSP2_FRM_OUT,
++	GPIO83_SSP2_TXD,
++};
++
+ /*
+  * SCOOP Device
+  */
+@@ -60,11 +167,10 @@ static struct resource tosa_scoop_resources[] = {
+ 
+ static struct scoop_config tosa_scoop_setup = {
+ 	.io_dir 	= TOSA_SCOOP_IO_DIR,
+-	.io_out		= TOSA_SCOOP_IO_OUT,
+-
++	.gpio_base	= TOSA_SCOOP_GPIO_BASE,
+ };
+ 
+-struct platform_device tosascoop_device = {
++static struct platform_device tosascoop_device = {
+ 	.name		= "sharp-scoop",
+ 	.id		= 0,
+ 	.dev		= {
+@@ -88,10 +194,10 @@ static struct resource tosa_scoop_jc_resources[] = {
+ 
+ static struct scoop_config tosa_scoop_jc_setup = {
+ 	.io_dir 	= TOSA_SCOOP_JC_IO_DIR,
+-	.io_out		= TOSA_SCOOP_JC_IO_OUT,
++	.gpio_base	= TOSA_SCOOP_JC_GPIO_BASE,
+ };
+ 
+-struct platform_device tosascoop_jc_device = {
++static struct platform_device tosascoop_jc_device = {
+ 	.name		= "sharp-scoop",
+ 	.id		= 1,
+ 	.dev		= {
+@@ -118,50 +224,16 @@ static struct scoop_pcmcia_dev tosa_pcmcia_scoop[] = {
+ },
+ };
+ 
+-static void tosa_pcmcia_init(void)
+-{
+-	/* Setup default state of GPIO outputs
+-	   before we enable them as outputs. */
+-	GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
+-		GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) |
+-		GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) |
+-		GPIO_bit(GPIO53_nPCE_2);
+-
+-	pxa_gpio_mode(GPIO48_nPOE_MD);
+-	pxa_gpio_mode(GPIO49_nPWE_MD);
+-	pxa_gpio_mode(GPIO50_nPIOR_MD);
+-	pxa_gpio_mode(GPIO51_nPIOW_MD);
+-	pxa_gpio_mode(GPIO55_nPREG_MD);
+-	pxa_gpio_mode(GPIO56_nPWAIT_MD);
+-	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+-	pxa_gpio_mode(GPIO52_nPCE_1_MD);
+-	pxa_gpio_mode(GPIO53_nPCE_2_MD);
+-	pxa_gpio_mode(GPIO54_pSKTSEL_MD);
+-}
+-
+ static struct scoop_pcmcia_config tosa_pcmcia_config = {
+ 	.devs         = &tosa_pcmcia_scoop[0],
+ 	.num_devs     = 2,
+-	.pcmcia_init  = tosa_pcmcia_init,
+ };
+ 
+ /*
+  * USB Device Controller
+  */
+-static void tosa_udc_command(int cmd)
+-{
+-	switch(cmd)	{
+-		case PXA2XX_UDC_CMD_CONNECT:
+-			set_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_USB_PULLUP);
+-			break;
+-		case PXA2XX_UDC_CMD_DISCONNECT:
+-			reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_USB_PULLUP);
+-			break;
+-	}
+-}
+-
+ static struct pxa2xx_udc_mach_info udc_info __initdata = {
+-	.udc_command		= tosa_udc_command,
++	.gpio_pullup		= TOSA_GPIO_USB_PULLUP,
+ 	.gpio_vbus		= TOSA_GPIO_USB_IN,
+ 	.gpio_vbus_inverted	= 1,
+ };
+@@ -175,19 +247,44 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
+ {
+ 	int err;
+ 
+-	/* setup GPIO for PXA25x MMC controller */
+-	pxa_gpio_mode(GPIO6_MMCCLK_MD);
+-	pxa_gpio_mode(GPIO8_MMCCS0_MD);
+-	pxa_gpio_mode(TOSA_GPIO_nSD_DETECT | GPIO_IN);
+-
+ 	tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+ 
+ 	err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int,
+ 			  IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ 				"MMC/SD card detect", data);
+-	if (err)
++	if (err) {
+ 		printk(KERN_ERR "tosa_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
++		goto err_irq;
++	}
+ 
++	err = gpio_request(TOSA_GPIO_SD_WP, "sd_wp");
++	if (err) {
++		printk(KERN_ERR "tosa_mci_init: can't request SD_WP gpio\n");
++		goto err_gpio_wp;
++	}
++	err = gpio_direction_input(TOSA_GPIO_SD_WP);
++	if (err)
++		goto err_gpio_wp_dir;
++
++	err = gpio_request(TOSA_GPIO_PWR_ON, "sd_pwr");
++	if (err) {
++		printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
++		goto err_gpio_pwr;
++	}
++	err = gpio_direction_output(TOSA_GPIO_PWR_ON, 0);
++	if (err)
++		goto err_gpio_pwr_dir;
++
++	return 0;
++
++err_gpio_pwr_dir:
++	gpio_free(TOSA_GPIO_PWR_ON);
++err_gpio_pwr:
++err_gpio_wp_dir:
++	gpio_free(TOSA_GPIO_SD_WP);
++err_gpio_wp:
++	free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
++err_irq:
+ 	return err;
+ }
+ 
+@@ -196,19 +293,21 @@ static void tosa_mci_setpower(struct device *dev, unsigned int vdd)
+ 	struct pxamci_platform_data* p_d = dev->platform_data;
+ 
+ 	if (( 1 << vdd) & p_d->ocr_mask) {
+-		set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_PWR_ON);
++		gpio_set_value(TOSA_GPIO_PWR_ON, 1);
+ 	} else {
+-		reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_PWR_ON);
++		gpio_set_value(TOSA_GPIO_PWR_ON, 0);
+ 	}
+ }
+ 
+ static int tosa_mci_get_ro(struct device *dev)
+ {
+-	return (read_scoop_reg(&tosascoop_device.dev, SCOOP_GPWR)&TOSA_SCOOP_SD_WP);
++	return gpio_get_value(TOSA_GPIO_SD_WP);
+ }
+ 
+ static void tosa_mci_exit(struct device *dev, void *data)
+ {
++	gpio_free(TOSA_GPIO_PWR_ON);
++	gpio_free(TOSA_GPIO_SD_WP);
+ 	free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
+ }
+ 
+@@ -223,21 +322,36 @@ static struct pxamci_platform_data tosa_mci_platform_data = {
+ /*
+  * Irda
+  */
+-static void tosa_irda_transceiver_mode(struct device *dev, int mode)
++static int tosa_irda_startup(struct device *dev)
+ {
+-	if (mode & IR_OFF) {
+-		reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_IR_POWERDWN);
+-		pxa_gpio_mode(GPIO47_STTXD|GPIO_DFLT_LOW);
+-		pxa_gpio_mode(GPIO47_STTXD|GPIO_OUT);
+-	} else {
+-		pxa_gpio_mode(GPIO47_STTXD_MD);
+-		set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_IR_POWERDWN);
++	int ret;
++
++	ret = gpio_request(TOSA_GPIO_IR_POWERDWN, "IrDA powerdown");
++	if (ret)
++		return ret;
++
++	ret = gpio_direction_output(TOSA_GPIO_IR_POWERDWN, 0);
++	if (ret)
++		gpio_free(TOSA_GPIO_IR_POWERDWN);
++
++	return ret;
+ 	}
++
++static void tosa_irda_shutdown(struct device *dev)
++{
++	gpio_free(TOSA_GPIO_IR_POWERDWN);
++}
++
++static void tosa_irda_transceiver_mode(struct device *dev, int mode)
++{
++	gpio_set_value(TOSA_GPIO_IR_POWERDWN, !(mode & IR_OFF));
+ }
+ 
+ static struct pxaficp_platform_data tosa_ficp_platform_data = {
+ 	.transceiver_cap  = IR_SIRMODE | IR_OFF,
+ 	.transceiver_mode = tosa_irda_transceiver_mode,
++	.startup = tosa_irda_startup,
++	.shutdown = tosa_irda_shutdown,
+ };
+ 
+ /*
+@@ -249,12 +363,28 @@ static struct platform_device tosakbd_device = {
+ };
+ 
+ static struct gpio_keys_button tosa_gpio_keys[] = {
++	/*
++	 * Two following keys are directly tied to "ON" button of tosa. Why?
++	 * The first one can be used as a wakeup source, the second can't;
++	 * also the first one is OR of ac_powered and on_button.
++	 */
++	{
++		.type	= EV_PWR,
++		.code	= KEY_RESERVED,
++		.gpio	= TOSA_GPIO_POWERON,
++		.desc	= "Poweron",
++		.wakeup	= 1,
++		.active_low = 1,
++	},
+ 	{
+ 		.type	= EV_PWR,
+ 		.code	= KEY_SUSPEND,
+ 		.gpio	= TOSA_GPIO_ON_KEY,
+ 		.desc	= "On key",
+-		.wakeup	= 1,
++		/*
++		 * can't be used as wakeup
++		 * .wakeup	= 1,
++		 */
+ 		.active_low = 1,
+ 	},
+ 	{
+@@ -291,9 +421,40 @@ static struct platform_device tosa_gpio_keys_device = {
+ /*
+  * Tosa LEDs
+  */
++static struct gpio_led tosa_gpio_leds[] = {
++	{
++		.name			= "tosa:amber:charge",
++		.default_trigger	= "main-battery-charging",
++		.gpio			= TOSA_GPIO_CHRG_ERR_LED,
++	},
++	{
++		.name			= "tosa:green:mail",
++		.default_trigger	= "nand-disk",
++		.gpio			= TOSA_GPIO_NOTE_LED,
++	},
++	{
++		.name			= "tosa:dual:wlan",
++		.default_trigger	= "none",
++		.gpio			= TOSA_GPIO_WLAN_LED,
++	},
++	{
++		.name			= "tosa:blue:bluetooth",
++		.default_trigger	= "none",
++		.gpio			= TOSA_GPIO_BT_LED,
++	},
++};
++
++static struct gpio_led_platform_data tosa_gpio_leds_platform_data = {
++	.leds		= tosa_gpio_leds,
++	.num_leds	= ARRAY_SIZE(tosa_gpio_leds),
++};
++
+ static struct platform_device tosaled_device = {
+-    .name   = "tosa-led",
+-    .id     = -1,
++	.name	= "leds-gpio",
++	.id	= -1,
++	.dev	= {
++		.platform_data	= &tosa_gpio_leds_platform_data,
++	},
+ };
+ 
+ static struct platform_device *devices[] __initdata = {
+@@ -326,20 +487,13 @@ static void tosa_restart(char mode)
+ 
+ static void __init tosa_init(void)
+ {
++	pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config));
++	gpio_set_wake(MFP_PIN_GPIO1, 1);
++	/* We can't pass to gpio-keys since it will drop the Reset altfunc */
++
+ 	pm_power_off = tosa_poweroff;
+ 	arm_pm_restart = tosa_restart;
+ 
+-	pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN);
+-	pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN);
+-	pxa_gpio_mode(TOSA_GPIO_USB_IN | GPIO_IN);
+-
+-	/* setup sleep mode values */
+-	PWER  = 0x00000002;
+-	PFER  = 0x00000000;
+-	PRER  = 0x00000002;
+-	PGSR0 = 0x00000000;
+-	PGSR1 = 0x00FF0002;
+-	PGSR2 = 0x00014000;
+ 	PCFR |= PCFR_OPDE;
+ 
+ 	/* enable batt_fault */
+@@ -348,6 +502,7 @@ static void __init tosa_init(void)
+ 	pxa_set_mci_info(&tosa_mci_platform_data);
+ 	pxa_set_udc_info(&udc_info);
+ 	pxa_set_ficp_info(&tosa_ficp_platform_data);
++	pxa_set_i2c_info(NULL);
+ 	platform_scoop_config = &tosa_pcmcia_config;
+ 
+ 	platform_add_devices(devices, ARRAY_SIZE(devices));
+diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
+index f207fcd..931885d 100644
+--- a/arch/arm/mach-pxa/trizeps4.c
++++ b/arch/arm/mach-pxa/trizeps4.c
+@@ -41,6 +41,7 @@
+ #include <asm/mach/flash.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/trizeps4.h>
+ #include <asm/arch/audio.h>
+ #include <asm/arch/pxafb.h>
+diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
+index afd2cbf..dbb5462 100644
+--- a/arch/arm/mach-pxa/zylonite.c
++++ b/arch/arm/mach-pxa/zylonite.c
+@@ -26,6 +26,7 @@
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/zylonite.h>
+ #include <asm/arch/mmc.h>
++#include <asm/arch/pxa27x_keypad.h>
+ 
+ #include "generic.h"
+ 
+@@ -35,6 +36,8 @@ struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS];
+ int gpio_backlight;
+ int gpio_eth_irq;
+ 
++int wm9713_irq;
++
+ int lcd_id;
+ int lcd_orientation;
+ 
+@@ -249,6 +252,71 @@ static void __init zylonite_init_mmc(void)
+ static inline void zylonite_init_mmc(void) {}
+ #endif
+ 
++#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
++static unsigned int zylonite_matrix_key_map[] = {
++	/* KEY(row, col, key_code) */
++	KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D),
++	KEY(1, 0, KEY_E), KEY(1, 1, KEY_F), KEY(1, 2, KEY_G), KEY(1, 5, KEY_H),
++	KEY(2, 0, KEY_I), KEY(2, 1, KEY_J), KEY(2, 2, KEY_K), KEY(2, 5, KEY_L),
++	KEY(3, 0, KEY_M), KEY(3, 1, KEY_N), KEY(3, 2, KEY_O), KEY(3, 5, KEY_P),
++	KEY(5, 0, KEY_Q), KEY(5, 1, KEY_R), KEY(5, 2, KEY_S), KEY(5, 5, KEY_T),
++	KEY(6, 0, KEY_U), KEY(6, 1, KEY_V), KEY(6, 2, KEY_W), KEY(6, 5, KEY_X),
++	KEY(7, 1, KEY_Y), KEY(7, 2, KEY_Z),
++
++	KEY(4, 4, KEY_0), KEY(1, 3, KEY_1), KEY(4, 1, KEY_2), KEY(1, 4, KEY_3),
++	KEY(2, 3, KEY_4), KEY(4, 2, KEY_5), KEY(2, 4, KEY_6), KEY(3, 3, KEY_7),
++	KEY(4, 3, KEY_8), KEY(3, 4, KEY_9),
++
++	KEY(4, 5, KEY_SPACE),
++	KEY(5, 3, KEY_KPASTERISK), 	/* * */
++	KEY(5, 4, KEY_KPDOT), 		/* #" */
++
++	KEY(0, 7, KEY_UP),
++	KEY(1, 7, KEY_DOWN),
++	KEY(2, 7, KEY_LEFT),
++	KEY(3, 7, KEY_RIGHT),
++	KEY(2, 6, KEY_HOME),
++	KEY(3, 6, KEY_END),
++	KEY(6, 4, KEY_DELETE),
++	KEY(6, 6, KEY_BACK),
++	KEY(6, 3, KEY_CAPSLOCK),	/* KEY_LEFTSHIFT), */
++
++	KEY(4, 6, KEY_ENTER),		/* scroll push */
++	KEY(5, 7, KEY_ENTER),		/* keypad action */
++
++	KEY(0, 4, KEY_EMAIL),
++	KEY(5, 6, KEY_SEND),
++	KEY(4, 0, KEY_CALENDAR),
++	KEY(7, 6, KEY_RECORD),
++	KEY(6, 7, KEY_VOLUMEUP),
++	KEY(7, 7, KEY_VOLUMEDOWN),
++
++	KEY(0, 6, KEY_F22),	/* soft1 */
++	KEY(1, 6, KEY_F23),	/* soft2 */
++	KEY(0, 3, KEY_AUX),	/* contact */
++};
++
++static struct pxa27x_keypad_platform_data zylonite_keypad_info = {
++	.matrix_key_rows	= 8,
++	.matrix_key_cols	= 8,
++	.matrix_key_map		= zylonite_matrix_key_map,
++	.matrix_key_map_size	= ARRAY_SIZE(zylonite_matrix_key_map),
++
++	.enable_rotary0		= 1,
++	.rotary0_up_key		= KEY_UP,
++	.rotary0_down_key	= KEY_DOWN,
++
++	.debounce_interval	= 30,
++};
++
++static void __init zylonite_init_keypad(void)
++{
++	pxa_set_keypad_info(&zylonite_keypad_info);
++}
++#else
++static inline void zylonite_init_keypad(void) {}
++#endif
++
+ static void __init zylonite_init(void)
+ {
+ 	/* board-processor specific initialization */
+@@ -265,6 +333,7 @@ static void __init zylonite_init(void)
+ 
+ 	zylonite_init_lcd();
+ 	zylonite_init_mmc();
++	zylonite_init_keypad();
+ }
+ 
+ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
+diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
+index 6ac04c0..324fb9d 100644
+--- a/arch/arm/mach-pxa/zylonite_pxa300.c
++++ b/arch/arm/mach-pxa/zylonite_pxa300.c
+@@ -21,7 +21,7 @@
+ #include <asm/arch/mfp-pxa300.h>
+ #include <asm/arch/zylonite.h>
+ 
+-#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
++#include "generic.h"
+ 
+ /* PXA300/PXA310 common configurations */
+ static mfp_cfg_t common_mfp_cfg[] __initdata = {
+@@ -69,6 +69,9 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = {
+ 	GPIO27_AC97_SDATA_OUT,
+ 	GPIO28_AC97_SYNC,
+ 
++	/* WM9713 IRQ */
++	GPIO26_GPIO,
++
+ 	/* Keypad */
+ 	GPIO107_KP_DKIN_0 | MFP_LPM_EDGE_BOTH,
+ 	GPIO108_KP_DKIN_1 | MFP_LPM_EDGE_BOTH,
+@@ -203,6 +206,9 @@ void __init zylonite_pxa300_init(void)
+ 		/* MMC card detect & write protect for controller 0 */
+ 		zylonite_mmc_slot[0].gpio_cd  = EXT_GPIO(0);
+ 		zylonite_mmc_slot[0].gpio_wp  = EXT_GPIO(2);
++
++		/* WM9713 IRQ */
++		wm9713_irq = mfp_to_gpio(MFP_PIN_GPIO26);
+ 	}
+ 
+ 	if (cpu_is_pxa300()) {
+diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c
+index dfa7999..193d079 100644
+--- a/arch/arm/mach-pxa/zylonite_pxa320.c
++++ b/arch/arm/mach-pxa/zylonite_pxa320.c
+@@ -21,7 +21,7 @@
+ #include <asm/arch/mfp-pxa320.h>
+ #include <asm/arch/zylonite.h>
+ 
+-#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
++#include "generic.h"
+ 
+ static mfp_cfg_t mfp_cfg[] __initdata = {
+ 	/* LCD */
+@@ -68,6 +68,9 @@ static mfp_cfg_t mfp_cfg[] __initdata = {
+ 	GPIO39_AC97_BITCLK,
+ 	GPIO40_AC97_nACRESET,
+ 
++	/* WM9713 IRQ */
++	GPIO15_GPIO,
++
+ 	/* I2C */
+ 	GPIO32_I2C_SCL,
+ 	GPIO33_I2C_SDA,
+@@ -190,5 +193,8 @@ void __init zylonite_pxa320_init(void)
+ 		/* MMC card detect & write protect for controller 0 */
+ 		zylonite_mmc_slot[0].gpio_cd  = mfp_to_gpio(MFP_PIN_GPIO1);
+ 		zylonite_mmc_slot[0].gpio_wp  = mfp_to_gpio(MFP_PIN_GPIO5);
++
++		/* WM9713 IRQ */
++		wm9713_irq = mfp_to_gpio(MFP_PIN_GPIO15);
+ 	}
+ }
+diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
+index 39b3bb7..5ccde7c 100644
+--- a/arch/arm/mach-realview/Kconfig
++++ b/arch/arm/mach-realview/Kconfig
+@@ -10,7 +10,6 @@ config MACH_REALVIEW_EB
+ config REALVIEW_EB_ARM11MP
+ 	bool "Support ARM11MPCore tile"
+ 	depends on MACH_REALVIEW_EB
+-	select CACHE_L2X0
+ 	help
+ 	  Enable support for the ARM11MPCore tile on the Realview platform.
+ 
+@@ -24,4 +23,18 @@ config REALVIEW_EB_ARM11MP_REVB
+ 	  kernel built with this option enabled is not compatible with
+ 	  other revisions of the ARM11MPCore tile.
+ 
++config MACH_REALVIEW_PB11MP
++	bool "Support RealView/PB11MPCore platform"
++	select ARM_GIC
++	help
++	  Include support for the ARM(R) RealView MPCore Platform Baseboard.
++	  PB11MPCore is a platform with an on-board ARM11MPCore and has
++	  support for PCI-E and Compact Flash.
++
++config MACH_REALVIEW_PB1176
++	bool "Support RealView/PB1176 platform"
++	select ARM_GIC
++	help
++	  Include support for the ARM(R) RealView ARM1176 Platform Baseboard.
++
+ endmenu
+diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
+index ca1e390..d2ae077 100644
+--- a/arch/arm/mach-realview/Makefile
++++ b/arch/arm/mach-realview/Makefile
+@@ -4,5 +4,7 @@
+ 
+ obj-y					:= core.o clock.o
+ obj-$(CONFIG_MACH_REALVIEW_EB)		+= realview_eb.o
++obj-$(CONFIG_MACH_REALVIEW_PB11MP)	+= realview_pb11mp.o
++obj-$(CONFIG_MACH_REALVIEW_PB1176)	+= realview_pb1176.o
+ obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o localtimer.o
+ obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
+diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c
+index 21325a4..3e706c5 100644
+--- a/arch/arm/mach-realview/clock.c
++++ b/arch/arm/mach-realview/clock.c
+@@ -16,7 +16,6 @@
+ #include <linux/clk.h>
+ #include <linux/mutex.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/hardware/icst307.h>
+ 
+ #include "clock.h"
+diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
+index 98aefc9..131990d 100644
+--- a/arch/arm/mach-realview/core.c
++++ b/arch/arm/mach-realview/core.c
+@@ -109,22 +109,21 @@ static struct flash_platform_data realview_flash_data = {
+ 	.set_vpp		= realview_flash_set_vpp,
+ };
+ 
+-static struct resource realview_flash_resource = {
+-	.start			= REALVIEW_FLASH_BASE,
+-	.end			= REALVIEW_FLASH_BASE + REALVIEW_FLASH_SIZE,
+-	.flags			= IORESOURCE_MEM,
+-};
+-
+ struct platform_device realview_flash_device = {
+ 	.name			= "armflash",
+ 	.id			= 0,
+ 	.dev			= {
+ 		.platform_data	= &realview_flash_data,
+ 	},
+-	.num_resources		= 1,
+-	.resource		= &realview_flash_resource,
+ };
+ 
++int realview_flash_register(struct resource *res, u32 num)
++{
++	realview_flash_device.resource = res;
++	realview_flash_device.num_resources = num;
++	return platform_device_register(&realview_flash_device);
++}
++
+ static struct resource realview_i2c_resource = {
+ 	.start		= REALVIEW_I2C_BASE,
+ 	.end		= REALVIEW_I2C_BASE + SZ_4K - 1,
+@@ -445,10 +444,10 @@ void realview_leds_event(led_event_t ledevt)
+ /*
+  * Where is the timer (VA)?
+  */
+-#define TIMER0_VA_BASE		 __io_address(REALVIEW_TIMER0_1_BASE)
+-#define TIMER1_VA_BASE		(__io_address(REALVIEW_TIMER0_1_BASE) + 0x20)
+-#define TIMER2_VA_BASE		 __io_address(REALVIEW_TIMER2_3_BASE)
+-#define TIMER3_VA_BASE		(__io_address(REALVIEW_TIMER2_3_BASE) + 0x20)
++void __iomem *timer0_va_base;
++void __iomem *timer1_va_base;
++void __iomem *timer2_va_base;
++void __iomem *timer3_va_base;
+ 
+ /*
+  * How long is the timer interval?
+@@ -475,7 +474,7 @@ static void timer_set_mode(enum clock_event_mode mode,
+ 
+ 	switch(mode) {
+ 	case CLOCK_EVT_MODE_PERIODIC:
+-		writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
++		writel(TIMER_RELOAD, timer0_va_base + TIMER_LOAD);
+ 
+ 		ctrl = TIMER_CTRL_PERIODIC;
+ 		ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
+@@ -491,16 +490,16 @@ static void timer_set_mode(enum clock_event_mode mode,
+ 		ctrl = 0;
+ 	}
+ 
+-	writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
++	writel(ctrl, timer0_va_base + TIMER_CTRL);
+ }
+ 
+ static int timer_set_next_event(unsigned long evt,
+ 				struct clock_event_device *unused)
+ {
+-	unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
++	unsigned long ctrl = readl(timer0_va_base + TIMER_CTRL);
+ 
+-	writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
+-	writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
++	writel(evt, timer0_va_base + TIMER_LOAD);
++	writel(ctrl | TIMER_CTRL_ENABLE, timer0_va_base + TIMER_CTRL);
+ 
+ 	return 0;
+ }
+@@ -536,7 +535,7 @@ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
+ 	struct clock_event_device *evt = &timer0_clockevent;
+ 
+ 	/* clear the interrupt */
+-	writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
++	writel(1, timer0_va_base + TIMER_INTCLR);
+ 
+ 	evt->event_handler(evt);
+ 
+@@ -551,7 +550,7 @@ static struct irqaction realview_timer_irq = {
+ 
+ static cycle_t realview_get_cycles(void)
+ {
+-	return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
++	return ~readl(timer3_va_base + TIMER_VALUE);
+ }
+ 
+ static struct clocksource clocksource_realview = {
+@@ -566,11 +565,11 @@ static struct clocksource clocksource_realview = {
+ static void __init realview_clocksource_init(void)
+ {
+ 	/* setup timer 0 as free-running clocksource */
+-	writel(0, TIMER3_VA_BASE + TIMER_CTRL);
+-	writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
+-	writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
++	writel(0, timer3_va_base + TIMER_CTRL);
++	writel(0xffffffff, timer3_va_base + TIMER_LOAD);
++	writel(0xffffffff, timer3_va_base + TIMER_VALUE);
+ 	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
+-		TIMER3_VA_BASE + TIMER_CTRL);
++		timer3_va_base + TIMER_CTRL);
+ 
+ 	clocksource_realview.mult =
+ 		clocksource_khz2mult(1000, clocksource_realview.shift);
+@@ -607,10 +606,10 @@ void __init realview_timer_init(unsigned int timer_irq)
+ 	/*
+ 	 * Initialise to a known state (all timers off)
+ 	 */
+-	writel(0, TIMER0_VA_BASE + TIMER_CTRL);
+-	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
+-	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
+-	writel(0, TIMER3_VA_BASE + TIMER_CTRL);
++	writel(0, timer0_va_base + TIMER_CTRL);
++	writel(0, timer1_va_base + TIMER_CTRL);
++	writel(0, timer2_va_base + TIMER_CTRL);
++	writel(0, timer3_va_base + TIMER_CTRL);
+ 
+ 	/* 
+ 	 * Make irqs happen for the system timer
+diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
+index 492a14c..33dbbb4 100644
+--- a/arch/arm/mach-realview/core.h
++++ b/arch/arm/mach-realview/core.h
+@@ -55,8 +55,13 @@ extern void __iomem *gic_cpu_base_addr;
+ extern void __iomem *twd_base_addr;
+ extern unsigned int twd_size;
+ #endif
++extern void __iomem *timer0_va_base;
++extern void __iomem *timer1_va_base;
++extern void __iomem *timer2_va_base;
++extern void __iomem *timer3_va_base;
+ 
+ extern void realview_leds_event(led_event_t ledevt);
+ extern void realview_timer_init(unsigned int timer_irq);
++extern int realview_flash_register(struct resource *res, u32 num);
+ 
+ #endif
+diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
+index de2b715..3e57428 100644
+--- a/arch/arm/mach-realview/platsmp.c
++++ b/arch/arm/mach-realview/platsmp.c
+@@ -15,11 +15,14 @@
+ #include <linux/smp.h>
+ 
+ #include <asm/cacheflush.h>
+-#include <asm/hardware/arm_scu.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/mach-types.h>
+ 
++#include <asm/arch/board-eb.h>
++#include <asm/arch/board-pb11mp.h>
++#include <asm/arch/scu.h>
++
+ extern void realview_secondary_startup(void);
+ 
+ /*
+@@ -31,9 +34,15 @@ volatile int __cpuinitdata pen_release = -1;
+ static unsigned int __init get_core_count(void)
+ {
+ 	unsigned int ncores;
++	void __iomem *scu_base = 0;
++
++	if (machine_is_realview_eb() && core_tile_eb11mp())
++		scu_base = __io_address(REALVIEW_EB11MP_SCU_BASE);
++	else if (machine_is_realview_pb11mp())
++		scu_base = __io_address(REALVIEW_TC11MP_SCU_BASE);
+ 
+-	if (machine_is_realview_eb() && core_tile_eb11mp()) {
+-		ncores = __raw_readl(__io_address(REALVIEW_EB11MP_SCU_BASE) + SCU_CONFIG);
++	if (scu_base) {
++		ncores = __raw_readl(scu_base + SCU_CONFIG);
+ 		ncores = (ncores & 0x03) + 1;
+ 	} else
+ 		ncores = 1;
+@@ -41,6 +50,26 @@ static unsigned int __init get_core_count(void)
+ 	return ncores;
+ }
+ 
++/*
++ * Setup the SCU
++ */
++static void scu_enable(void)
++{
++	u32 scu_ctrl;
++	void __iomem *scu_base;
++
++	if (machine_is_realview_eb() && core_tile_eb11mp())
++		scu_base = __io_address(REALVIEW_EB11MP_SCU_BASE);
++	else if (machine_is_realview_pb11mp())
++		scu_base = __io_address(REALVIEW_TC11MP_SCU_BASE);
++	else
++		BUG();
++
++	scu_ctrl = __raw_readl(scu_base + SCU_CTRL);
++	scu_ctrl |= 1;
++	__raw_writel(scu_ctrl, scu_base + SCU_CTRL);
++}
++
+ static DEFINE_SPINLOCK(boot_lock);
+ 
+ void __cpuinit platform_secondary_init(unsigned int cpu)
+@@ -57,7 +86,10 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
+ 	 * core (e.g. timer irq), then they will not have been enabled
+ 	 * for us: do so
+ 	 */
+-	gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
++	if (machine_is_realview_eb() && core_tile_eb11mp())
++		gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
++	else if (machine_is_realview_pb11mp())
++		gic_cpu_init(0, __io_address(REALVIEW_TC11MP_GIC_CPU_BASE));
+ 
+ 	/*
+ 	 * let the primary processor know we're out of the
+@@ -198,7 +230,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
+ 	 * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in
+ 	 * realview_timer_init
+ 	 */
+-	if (machine_is_realview_eb() && core_tile_eb11mp())
++	if ((machine_is_realview_eb() && core_tile_eb11mp()) ||
++	    machine_is_realview_pb11mp())
+ 		local_timer_setup(cpu);
+ #endif
+ 
+@@ -210,11 +243,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
+ 		cpu_set(i, cpu_present_map);
+ 
+ 	/*
+-	 * Do we need any more CPUs? If so, then let them know where
+-	 * to start. Note that, on modern versions of MILO, the "poke"
+-	 * doesn't actually do anything until each individual core is
+-	 * sent a soft interrupt to get it out of WFI
++	 * Initialise the SCU if there are more than one CPU and let
++	 * them know where to start. Note that, on modern versions of
++	 * MILO, the "poke" doesn't actually do anything until each
++	 * individual core is sent a soft interrupt to get it out of
++	 * WFI
+ 	 */
+-	if (max_cpus > 1)
++	if (max_cpus > 1) {
++		scu_enable();
+ 		poke_milo();
++	}
+ }
+diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
+index 60d9eb8..5782d83 100644
+--- a/arch/arm/mach-realview/realview_eb.c
++++ b/arch/arm/mach-realview/realview_eb.c
+@@ -51,13 +51,13 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
+ 		.length		= SZ_4K,
+ 		.type		= MT_DEVICE,
+ 	}, {
+-		.virtual	= IO_ADDRESS(REALVIEW_GIC_CPU_BASE),
+-		.pfn		= __phys_to_pfn(REALVIEW_GIC_CPU_BASE),
++		.virtual	= IO_ADDRESS(REALVIEW_EB_GIC_CPU_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_EB_GIC_CPU_BASE),
+ 		.length		= SZ_4K,
+ 		.type		= MT_DEVICE,
+ 	}, {
+-		.virtual	= IO_ADDRESS(REALVIEW_GIC_DIST_BASE),
+-		.pfn		= __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
++		.virtual	= IO_ADDRESS(REALVIEW_EB_GIC_DIST_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_EB_GIC_DIST_BASE),
+ 		.length		= SZ_4K,
+ 		.type		= MT_DEVICE,
+ 	}, {
+@@ -66,20 +66,20 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
+ 		.length		= SZ_4K,
+ 		.type		= MT_DEVICE,
+ 	}, {
+-		.virtual	= IO_ADDRESS(REALVIEW_TIMER0_1_BASE),
+-		.pfn		= __phys_to_pfn(REALVIEW_TIMER0_1_BASE),
++		.virtual	= IO_ADDRESS(REALVIEW_EB_TIMER0_1_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_EB_TIMER0_1_BASE),
+ 		.length		= SZ_4K,
+ 		.type		= MT_DEVICE,
+ 	}, {
+-		.virtual	= IO_ADDRESS(REALVIEW_TIMER2_3_BASE),
+-		.pfn		= __phys_to_pfn(REALVIEW_TIMER2_3_BASE),
++		.virtual	= IO_ADDRESS(REALVIEW_EB_TIMER2_3_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_EB_TIMER2_3_BASE),
+ 		.length		= SZ_4K,
+ 		.type		= MT_DEVICE,
+ 	},
+ #ifdef CONFIG_DEBUG_LL
+ 	{
+-		.virtual	= IO_ADDRESS(REALVIEW_UART0_BASE),
+-		.pfn		= __phys_to_pfn(REALVIEW_UART0_BASE),
++		.virtual	= IO_ADDRESS(REALVIEW_EB_UART0_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_EB_UART0_BASE),
+ 		.length		= SZ_4K,
+ 		.type		= MT_DEVICE,
+ 	}
+@@ -136,12 +136,12 @@ static void __init realview_eb_map_io(void)
+ /*
+  * These devices are connected directly to the multi-layer AHB switch
+  */
+-#define SMC_IRQ		{ NO_IRQ, NO_IRQ }
+-#define SMC_DMA		{ 0, 0 }
++#define EB_SMC_IRQ	{ NO_IRQ, NO_IRQ }
++#define EB_SMC_DMA	{ 0, 0 }
+ #define MPMC_IRQ	{ NO_IRQ, NO_IRQ }
+ #define MPMC_DMA	{ 0, 0 }
+-#define CLCD_IRQ	{ IRQ_EB_CLCD, NO_IRQ }
+-#define CLCD_DMA	{ 0, 0 }
++#define EB_CLCD_IRQ	{ IRQ_EB_CLCD, NO_IRQ }
++#define EB_CLCD_DMA	{ 0, 0 }
+ #define DMAC_IRQ	{ IRQ_EB_DMA, NO_IRQ }
+ #define DMAC_DMA	{ 0, 0 }
+ 
+@@ -150,53 +150,53 @@ static void __init realview_eb_map_io(void)
+  */
+ #define SCTL_IRQ	{ NO_IRQ, NO_IRQ }
+ #define SCTL_DMA	{ 0, 0 }
+-#define WATCHDOG_IRQ	{ IRQ_EB_WDOG, NO_IRQ }
+-#define WATCHDOG_DMA	{ 0, 0 }
+-#define GPIO0_IRQ	{ IRQ_EB_GPIO0, NO_IRQ }
+-#define GPIO0_DMA	{ 0, 0 }
++#define EB_WATCHDOG_IRQ	{ IRQ_EB_WDOG, NO_IRQ }
++#define EB_WATCHDOG_DMA	{ 0, 0 }
++#define EB_GPIO0_IRQ	{ IRQ_EB_GPIO0, NO_IRQ }
++#define EB_GPIO0_DMA	{ 0, 0 }
+ #define GPIO1_IRQ	{ IRQ_EB_GPIO1, NO_IRQ }
+ #define GPIO1_DMA	{ 0, 0 }
+-#define RTC_IRQ		{ IRQ_EB_RTC, NO_IRQ }
+-#define RTC_DMA		{ 0, 0 }
++#define EB_RTC_IRQ	{ IRQ_EB_RTC, NO_IRQ }
++#define EB_RTC_DMA	{ 0, 0 }
+ 
+ /*
+  * These devices are connected via the DMA APB bridge
+  */
+ #define SCI_IRQ		{ IRQ_EB_SCI, NO_IRQ }
+ #define SCI_DMA		{ 7, 6 }
+-#define UART0_IRQ	{ IRQ_EB_UART0, NO_IRQ }
+-#define UART0_DMA	{ 15, 14 }
+-#define UART1_IRQ	{ IRQ_EB_UART1, NO_IRQ }
+-#define UART1_DMA	{ 13, 12 }
+-#define UART2_IRQ	{ IRQ_EB_UART2, NO_IRQ }
+-#define UART2_DMA	{ 11, 10 }
+-#define UART3_IRQ	{ IRQ_EB_UART3, NO_IRQ }
+-#define UART3_DMA	{ 0x86, 0x87 }
+-#define SSP_IRQ		{ IRQ_EB_SSP, NO_IRQ }
+-#define SSP_DMA		{ 9, 8 }
++#define EB_UART0_IRQ	{ IRQ_EB_UART0, NO_IRQ }
++#define EB_UART0_DMA	{ 15, 14 }
++#define EB_UART1_IRQ	{ IRQ_EB_UART1, NO_IRQ }
++#define EB_UART1_DMA	{ 13, 12 }
++#define EB_UART2_IRQ	{ IRQ_EB_UART2, NO_IRQ }
++#define EB_UART2_DMA	{ 11, 10 }
++#define EB_UART3_IRQ	{ IRQ_EB_UART3, NO_IRQ }
++#define EB_UART3_DMA	{ 0x86, 0x87 }
++#define EB_SSP_IRQ	{ IRQ_EB_SSP, NO_IRQ }
++#define EB_SSP_DMA	{ 9, 8 }
+ 
+ /* FPGA Primecells */
+ AMBA_DEVICE(aaci,  "fpga:04", AACI,     NULL);
+ AMBA_DEVICE(mmc0,  "fpga:05", MMCI0,    &realview_mmc0_plat_data);
+ AMBA_DEVICE(kmi0,  "fpga:06", KMI0,     NULL);
+ AMBA_DEVICE(kmi1,  "fpga:07", KMI1,     NULL);
+-AMBA_DEVICE(uart3, "fpga:09", UART3,    NULL);
++AMBA_DEVICE(uart3, "fpga:09", EB_UART3, NULL);
+ 
+ /* DevChip Primecells */
+-AMBA_DEVICE(smc,   "dev:00",  SMC,      NULL);
+-AMBA_DEVICE(clcd,  "dev:20",  CLCD,     &clcd_plat_data);
++AMBA_DEVICE(smc,   "dev:00",  EB_SMC,   NULL);
++AMBA_DEVICE(clcd,  "dev:20",  EB_CLCD,  &clcd_plat_data);
+ AMBA_DEVICE(dmac,  "dev:30",  DMAC,     NULL);
+ AMBA_DEVICE(sctl,  "dev:e0",  SCTL,     NULL);
+-AMBA_DEVICE(wdog,  "dev:e1",  WATCHDOG, NULL);
+-AMBA_DEVICE(gpio0, "dev:e4",  GPIO0,    NULL);
++AMBA_DEVICE(wdog,  "dev:e1",  EB_WATCHDOG, NULL);
++AMBA_DEVICE(gpio0, "dev:e4",  EB_GPIO0, NULL);
+ AMBA_DEVICE(gpio1, "dev:e5",  GPIO1,    NULL);
+ AMBA_DEVICE(gpio2, "dev:e6",  GPIO2,    NULL);
+-AMBA_DEVICE(rtc,   "dev:e8",  RTC,      NULL);
++AMBA_DEVICE(rtc,   "dev:e8",  EB_RTC,   NULL);
+ AMBA_DEVICE(sci0,  "dev:f0",  SCI,      NULL);
+-AMBA_DEVICE(uart0, "dev:f1",  UART0,    NULL);
+-AMBA_DEVICE(uart1, "dev:f2",  UART1,    NULL);
+-AMBA_DEVICE(uart2, "dev:f3",  UART2,    NULL);
+-AMBA_DEVICE(ssp0,  "dev:f4",  SSP,      NULL);
++AMBA_DEVICE(uart0, "dev:f1",  EB_UART0, NULL);
++AMBA_DEVICE(uart1, "dev:f2",  EB_UART1, NULL);
++AMBA_DEVICE(uart2, "dev:f3",  EB_UART2, NULL);
++AMBA_DEVICE(ssp0,  "dev:f4",  EB_SSP,   NULL);
+ 
+ static struct amba_device *amba_devs[] __initdata = {
+ 	&dmac_device,
+@@ -223,11 +223,16 @@ static struct amba_device *amba_devs[] __initdata = {
+ /*
+  * RealView EB platform devices
+  */
++static struct resource realview_eb_flash_resource = {
++	.start			= REALVIEW_EB_FLASH_BASE,
++	.end			= REALVIEW_EB_FLASH_BASE + REALVIEW_EB_FLASH_SIZE - 1,
++	.flags			= IORESOURCE_MEM,
++};
+ 
+-static struct resource realview_eb_smc91x_resources[] = {
++static struct resource realview_eb_eth_resources[] = {
+ 	[0] = {
+-		.start		= REALVIEW_ETH_BASE,
+-		.end		= REALVIEW_ETH_BASE + SZ_64K - 1,
++		.start		= REALVIEW_EB_ETH_BASE,
++		.end		= REALVIEW_EB_ETH_BASE + SZ_64K - 1,
+ 		.flags		= IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+@@ -237,13 +242,36 @@ static struct resource realview_eb_smc91x_resources[] = {
+ 	},
+ };
+ 
+-static struct platform_device realview_eb_smc91x_device = {
+-	.name		= "smc91x",
++static struct platform_device realview_eb_eth_device = {
+ 	.id		= 0,
+-	.num_resources	= ARRAY_SIZE(realview_eb_smc91x_resources),
+-	.resource	= realview_eb_smc91x_resources,
++	.num_resources	= ARRAY_SIZE(realview_eb_eth_resources),
++	.resource	= realview_eb_eth_resources,
+ };
+ 
++/*
++ * Detect and register the correct Ethernet device. RealView/EB rev D
++ * platforms use the newer SMSC LAN9118 Ethernet chip
++ */
++static int eth_device_register(void)
++{
++	void __iomem *eth_addr = ioremap(REALVIEW_EB_ETH_BASE, SZ_4K);
++	u32 idrev;
++
++	if (!eth_addr)
++		return -ENOMEM;
++
++	idrev = readl(eth_addr + 0x50);
++	if ((idrev & 0xFFFF0000) == 0x01180000)
++		/* SMSC LAN9118 chip present */
++		realview_eb_eth_device.name = "smc911x";
++	else
++		/* SMSC 91C111 chip present */
++		realview_eb_eth_device.name = "smc91x";
++
++	iounmap(eth_addr);
++	return platform_device_register(&realview_eb_eth_device);
++}
++
+ static void __init gic_init_irq(void)
+ {
+ 	if (core_tile_eb11mp()) {
+@@ -263,14 +291,14 @@ static void __init gic_init_irq(void)
+ 
+ #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
+ 		/* board GIC, secondary */
+-		gic_dist_init(1, __io_address(REALVIEW_GIC_DIST_BASE), 64);
+-		gic_cpu_init(1, __io_address(REALVIEW_GIC_CPU_BASE));
++		gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64);
++		gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE));
+ 		gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
+ #endif
+ 	} else {
+ 		/* board GIC, primary */
+-		gic_cpu_base_addr = __io_address(REALVIEW_GIC_CPU_BASE);
+-		gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
++		gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE);
++		gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29);
+ 		gic_cpu_init(0, gic_cpu_base_addr);
+ 	}
+ }
+@@ -301,14 +329,19 @@ static void realview_eb11mp_fixup(void)
+ 	kmi1_device.irq[0]	= IRQ_EB11MP_KMI1;
+ 
+ 	/* platform devices */
+-	realview_eb_smc91x_resources[1].start	= IRQ_EB11MP_ETH;
+-	realview_eb_smc91x_resources[1].end	= IRQ_EB11MP_ETH;
++	realview_eb_eth_resources[1].start	= IRQ_EB11MP_ETH;
++	realview_eb_eth_resources[1].end	= IRQ_EB11MP_ETH;
+ }
+ 
+ static void __init realview_eb_timer_init(void)
+ {
+ 	unsigned int timer_irq;
+ 
++	timer0_va_base = __io_address(REALVIEW_EB_TIMER0_1_BASE);
++	timer1_va_base = __io_address(REALVIEW_EB_TIMER0_1_BASE) + 0x20;
++	timer2_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE);
++	timer3_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE) + 0x20;
++
+ 	if (core_tile_eb11mp()) {
+ #ifdef CONFIG_LOCAL_TIMERS
+ 		twd_base_addr = __io_address(REALVIEW_EB11MP_TWD_BASE);
+@@ -332,16 +365,18 @@ static void __init realview_eb_init(void)
+ 	if (core_tile_eb11mp()) {
+ 		realview_eb11mp_fixup();
+ 
++#ifdef CONFIG_CACHE_L2X0
+ 		/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
+ 		 * Bits:  .... ...0 0111 1001 0000 .... .... .... */
+ 		l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
++#endif
+ 	}
+ 
+ 	clk_register(&realview_clcd_clk);
+ 
+-	platform_device_register(&realview_flash_device);
+-	platform_device_register(&realview_eb_smc91x_device);
++	realview_flash_register(&realview_eb_flash_resource, 1);
+ 	platform_device_register(&realview_i2c_device);
++	eth_device_register();
+ 
+ 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ 		struct amba_device *d = amba_devs[i];
+@@ -355,8 +390,8 @@ static void __init realview_eb_init(void)
+ 
+ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
+ 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
+-	.phys_io	= REALVIEW_UART0_BASE,
+-	.io_pg_offst	= (IO_ADDRESS(REALVIEW_UART0_BASE) >> 18) & 0xfffc,
++	.phys_io	= REALVIEW_EB_UART0_BASE,
++	.io_pg_offst	= (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc,
+ 	.boot_params	= 0x00000100,
+ 	.map_io		= realview_eb_map_io,
+ 	.init_irq	= gic_init_irq,
+diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
+new file mode 100644
+index 0000000..cf7f576
+--- /dev/null
++++ b/arch/arm/mach-realview/realview_pb1176.c
+@@ -0,0 +1,292 @@
++/*
++ *  linux/arch/arm/mach-realview/realview_pb1176.c
++ *
++ *  Copyright (C) 2008 ARM Limited
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public 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/sysdev.h>
++#include <linux/amba/bus.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/leds.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/gic.h>
++#include <asm/hardware/icst307.h>
++#include <asm/hardware/cache-l2x0.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++#include <asm/mach/mmc.h>
++#include <asm/mach/time.h>
++
++#include <asm/arch/board-pb1176.h>
++#include <asm/arch/irqs.h>
++
++#include "core.h"
++#include "clock.h"
++
++static struct map_desc realview_pb1176_io_desc[] __initdata = {
++	{
++		.virtual	= IO_ADDRESS(REALVIEW_SYS_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_SYS_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_PB1176_GIC_CPU_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB1176_GIC_CPU_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_PB1176_GIC_DIST_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB1176_GIC_DIST_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_DC1176_GIC_CPU_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_DC1176_GIC_CPU_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_DC1176_GIC_DIST_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_DC1176_GIC_DIST_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_SCTL_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_SCTL_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_PB1176_TIMER0_1_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB1176_TIMER0_1_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_PB1176_TIMER2_3_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB1176_TIMER2_3_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_PB1176_L220_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB1176_L220_BASE),
++		.length		= SZ_8K,
++		.type		= MT_DEVICE,
++	},
++#ifdef CONFIG_DEBUG_LL
++	{
++		.virtual	= IO_ADDRESS(REALVIEW_PB1176_UART0_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB1176_UART0_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	},
++#endif
++};
++
++static void __init realview_pb1176_map_io(void)
++{
++	iotable_init(realview_pb1176_io_desc, ARRAY_SIZE(realview_pb1176_io_desc));
++}
++
++/*
++ * RealView PB1176 AMBA devices
++ */
++#define GPIO2_IRQ	{ IRQ_PB1176_GPIO2, NO_IRQ }
++#define GPIO2_DMA	{ 0, 0 }
++#define GPIO3_IRQ	{ IRQ_PB1176_GPIO3, NO_IRQ }
++#define GPIO3_DMA	{ 0, 0 }
++#define AACI_IRQ	{ IRQ_PB1176_AACI, NO_IRQ }
++#define AACI_DMA	{ 0x80, 0x81 }
++#define MMCI0_IRQ	{ IRQ_PB1176_MMCI0A, IRQ_PB1176_MMCI0B }
++#define MMCI0_DMA	{ 0x84, 0 }
++#define KMI0_IRQ	{ IRQ_PB1176_KMI0, NO_IRQ }
++#define KMI0_DMA	{ 0, 0 }
++#define KMI1_IRQ	{ IRQ_PB1176_KMI1, NO_IRQ }
++#define KMI1_DMA	{ 0, 0 }
++#define PB1176_SMC_IRQ	{ NO_IRQ, NO_IRQ }
++#define PB1176_SMC_DMA	{ 0, 0 }
++#define MPMC_IRQ	{ NO_IRQ, NO_IRQ }
++#define MPMC_DMA	{ 0, 0 }
++#define PB1176_CLCD_IRQ	{ IRQ_DC1176_CLCD, NO_IRQ }
++#define PB1176_CLCD_DMA	{ 0, 0 }
++#define DMAC_IRQ	{ IRQ_PB1176_DMAC, NO_IRQ }
++#define DMAC_DMA	{ 0, 0 }
++#define SCTL_IRQ	{ NO_IRQ, NO_IRQ }
++#define SCTL_DMA	{ 0, 0 }
++#define PB1176_WATCHDOG_IRQ	{ IRQ_DC1176_WATCHDOG, NO_IRQ }
++#define PB1176_WATCHDOG_DMA	{ 0, 0 }
++#define PB1176_GPIO0_IRQ	{ IRQ_PB1176_GPIO0, NO_IRQ }
++#define PB1176_GPIO0_DMA	{ 0, 0 }
++#define GPIO1_IRQ	{ IRQ_PB1176_GPIO1, NO_IRQ }
++#define GPIO1_DMA	{ 0, 0 }
++#define PB1176_RTC_IRQ	{ IRQ_DC1176_RTC, NO_IRQ }
++#define PB1176_RTC_DMA	{ 0, 0 }
++#define SCI_IRQ		{ IRQ_PB1176_SCI, NO_IRQ }
++#define SCI_DMA		{ 7, 6 }
++#define PB1176_UART0_IRQ	{ IRQ_DC1176_UART0, NO_IRQ }
++#define PB1176_UART0_DMA	{ 15, 14 }
++#define PB1176_UART1_IRQ	{ IRQ_DC1176_UART1, NO_IRQ }
++#define PB1176_UART1_DMA	{ 13, 12 }
++#define PB1176_UART2_IRQ	{ IRQ_DC1176_UART2, NO_IRQ }
++#define PB1176_UART2_DMA	{ 11, 10 }
++#define PB1176_UART3_IRQ	{ IRQ_DC1176_UART3, NO_IRQ }
++#define PB1176_UART3_DMA	{ 0x86, 0x87 }
++#define PB1176_SSP_IRQ		{ IRQ_PB1176_SSP, NO_IRQ }
++#define PB1176_SSP_DMA		{ 9, 8 }
++
++/* FPGA Primecells */
++AMBA_DEVICE(aaci,	"fpga:04",	AACI,		NULL);
++AMBA_DEVICE(mmc0,	"fpga:05",	MMCI0,		&realview_mmc0_plat_data);
++AMBA_DEVICE(kmi0,	"fpga:06",	KMI0,		NULL);
++AMBA_DEVICE(kmi1,	"fpga:07",	KMI1,		NULL);
++AMBA_DEVICE(uart3,	"fpga:09",	PB1176_UART3,	NULL);
++
++/* DevChip Primecells */
++AMBA_DEVICE(smc,	"dev:00",	PB1176_SMC,	NULL);
++AMBA_DEVICE(sctl,	"dev:e0",	SCTL,		NULL);
++AMBA_DEVICE(wdog,	"dev:e1",	PB1176_WATCHDOG,	NULL);
++AMBA_DEVICE(gpio0,	"dev:e4",	PB1176_GPIO0,	NULL);
++AMBA_DEVICE(gpio1,	"dev:e5",	GPIO1,		NULL);
++AMBA_DEVICE(gpio2,	"dev:e6",	GPIO2,		NULL);
++AMBA_DEVICE(rtc,	"dev:e8",	PB1176_RTC,	NULL);
++AMBA_DEVICE(sci0,	"dev:f0",	SCI,		NULL);
++AMBA_DEVICE(uart0,	"dev:f1",	PB1176_UART0,	NULL);
++AMBA_DEVICE(uart1,	"dev:f2",	PB1176_UART1,	NULL);
++AMBA_DEVICE(uart2,	"dev:f3",	PB1176_UART2,	NULL);
++AMBA_DEVICE(ssp0,	"dev:f4",	PB1176_SSP,	NULL);
++
++/* Primecells on the NEC ISSP chip */
++AMBA_DEVICE(clcd,	"issp:20",	PB1176_CLCD,	&clcd_plat_data);
++//AMBA_DEVICE(dmac,	"issp:30",	PB1176_DMAC,	NULL);
++
++static struct amba_device *amba_devs[] __initdata = {
++//	&dmac_device,
++	&uart0_device,
++	&uart1_device,
++	&uart2_device,
++	&uart3_device,
++	&smc_device,
++	&clcd_device,
++	&sctl_device,
++	&wdog_device,
++	&gpio0_device,
++	&gpio1_device,
++	&gpio2_device,
++	&rtc_device,
++	&sci0_device,
++	&ssp0_device,
++	&aaci_device,
++	&mmc0_device,
++	&kmi0_device,
++	&kmi1_device,
++};
++
++/*
++ * RealView PB1176 platform devices
++ */
++static struct resource realview_pb1176_flash_resource = {
++	.start			= REALVIEW_PB1176_FLASH_BASE,
++	.end			= REALVIEW_PB1176_FLASH_BASE + REALVIEW_PB1176_FLASH_SIZE - 1,
++	.flags			= IORESOURCE_MEM,
++};
++
++static struct resource realview_pb1176_smsc911x_resources[] = {
++	[0] = {
++		.start		= REALVIEW_PB1176_ETH_BASE,
++		.end		= REALVIEW_PB1176_ETH_BASE + SZ_64K - 1,
++		.flags		= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start		= IRQ_PB1176_ETH,
++		.end		= IRQ_PB1176_ETH,
++		.flags		= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device realview_pb1176_smsc911x_device = {
++	.name		= "smc911x",
++	.id		= 0,
++	.num_resources	= ARRAY_SIZE(realview_pb1176_smsc911x_resources),
++	.resource	= realview_pb1176_smsc911x_resources,
++};
++
++static void __init gic_init_irq(void)
++{
++	/* ARM1176 DevChip GIC, primary */
++	gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE);
++	gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START);
++	gic_cpu_init(0, gic_cpu_base_addr);
++
++	/* board GIC, secondary */
++	gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START);
++	gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
++	gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1);
++}
++
++static void __init realview_pb1176_timer_init(void)
++{
++	timer0_va_base = __io_address(REALVIEW_PB1176_TIMER0_1_BASE);
++	timer1_va_base = __io_address(REALVIEW_PB1176_TIMER0_1_BASE) + 0x20;
++	timer2_va_base = __io_address(REALVIEW_PB1176_TIMER2_3_BASE);
++	timer3_va_base = __io_address(REALVIEW_PB1176_TIMER2_3_BASE) + 0x20;
++
++	realview_timer_init(IRQ_DC1176_TIMER0);
++}
++
++static struct sys_timer realview_pb1176_timer = {
++	.init		= realview_pb1176_timer_init,
++};
++
++static void __init realview_pb1176_init(void)
++{
++	int i;
++
++#ifdef CONFIG_CACHE_L2X0
++	/* 128Kb (16Kb/way) 8-way associativity. evmon/parity/share enabled. */
++	l2x0_init(__io_address(REALVIEW_PB1176_L220_BASE), 0x00730000, 0xfe000fff);
++#endif
++
++	clk_register(&realview_clcd_clk);
++
++	realview_flash_register(&realview_pb1176_flash_resource, 1);
++	platform_device_register(&realview_pb1176_smsc911x_device);
++
++	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
++		struct amba_device *d = amba_devs[i];
++		amba_device_register(d, &iomem_resource);
++	}
++
++#ifdef CONFIG_LEDS
++	leds_event = realview_leds_event;
++#endif
++}
++
++MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
++	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
++	.phys_io	= REALVIEW_PB1176_UART0_BASE,
++	.io_pg_offst	= (IO_ADDRESS(REALVIEW_PB1176_UART0_BASE) >> 18) & 0xfffc,
++	.boot_params	= 0x00000100,
++	.map_io		= realview_pb1176_map_io,
++	.init_irq	= gic_init_irq,
++	.timer		= &realview_pb1176_timer,
++	.init_machine	= realview_pb1176_init,
++MACHINE_END
+diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
+new file mode 100644
+index 0000000..f7ce1c5
+--- /dev/null
++++ b/arch/arm/mach-realview/realview_pb11mp.c
+@@ -0,0 +1,342 @@
++/*
++ *  linux/arch/arm/mach-realview/realview_pb11mp.c
++ *
++ *  Copyright (C) 2008 ARM Limited
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public 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/sysdev.h>
++#include <linux/amba/bus.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/leds.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/gic.h>
++#include <asm/hardware/icst307.h>
++#include <asm/hardware/cache-l2x0.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++#include <asm/mach/mmc.h>
++#include <asm/mach/time.h>
++
++#include <asm/arch/board-pb11mp.h>
++#include <asm/arch/irqs.h>
++
++#include "core.h"
++#include "clock.h"
++
++static struct map_desc realview_pb11mp_io_desc[] __initdata = {
++	{
++		.virtual	= IO_ADDRESS(REALVIEW_SYS_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_SYS_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_PB11MP_GIC_CPU_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB11MP_GIC_CPU_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_PB11MP_GIC_DIST_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB11MP_GIC_DIST_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_TC11MP_GIC_CPU_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_TC11MP_GIC_CPU_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_TC11MP_GIC_DIST_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_TC11MP_GIC_DIST_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_SCTL_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_SCTL_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_PB11MP_TIMER0_1_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB11MP_TIMER0_1_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_PB11MP_TIMER2_3_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB11MP_TIMER2_3_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_TC11MP_L220_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_TC11MP_L220_BASE),
++		.length		= SZ_8K,
++		.type		= MT_DEVICE,
++	},
++#ifdef CONFIG_DEBUG_LL
++	{
++		.virtual	= IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_PB11MP_UART0_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	},
++#endif
++};
++
++static void __init realview_pb11mp_map_io(void)
++{
++	iotable_init(realview_pb11mp_io_desc, ARRAY_SIZE(realview_pb11mp_io_desc));
++}
++
++/*
++ * RealView PB11MPCore AMBA devices
++ */
++
++#define GPIO2_IRQ		{ IRQ_PB11MP_GPIO2, NO_IRQ }
++#define GPIO2_DMA		{ 0, 0 }
++#define GPIO3_IRQ		{ IRQ_PB11MP_GPIO3, NO_IRQ }
++#define GPIO3_DMA		{ 0, 0 }
++#define AACI_IRQ		{ IRQ_TC11MP_AACI, NO_IRQ }
++#define AACI_DMA		{ 0x80, 0x81 }
++#define MMCI0_IRQ		{ IRQ_TC11MP_MMCI0A, IRQ_TC11MP_MMCI0B }
++#define MMCI0_DMA		{ 0x84, 0 }
++#define KMI0_IRQ		{ IRQ_TC11MP_KMI0, NO_IRQ }
++#define KMI0_DMA		{ 0, 0 }
++#define KMI1_IRQ		{ IRQ_TC11MP_KMI1, NO_IRQ }
++#define KMI1_DMA		{ 0, 0 }
++#define PB11MP_SMC_IRQ		{ NO_IRQ, NO_IRQ }
++#define PB11MP_SMC_DMA		{ 0, 0 }
++#define MPMC_IRQ		{ NO_IRQ, NO_IRQ }
++#define MPMC_DMA		{ 0, 0 }
++#define PB11MP_CLCD_IRQ		{ IRQ_PB11MP_CLCD, NO_IRQ }
++#define PB11MP_CLCD_DMA		{ 0, 0 }
++#define DMAC_IRQ		{ IRQ_PB11MP_DMAC, NO_IRQ }
++#define DMAC_DMA		{ 0, 0 }
++#define SCTL_IRQ		{ NO_IRQ, NO_IRQ }
++#define SCTL_DMA		{ 0, 0 }
++#define PB11MP_WATCHDOG_IRQ	{ IRQ_PB11MP_WATCHDOG, NO_IRQ }
++#define PB11MP_WATCHDOG_DMA	{ 0, 0 }
++#define PB11MP_GPIO0_IRQ	{ IRQ_PB11MP_GPIO0, NO_IRQ }
++#define PB11MP_GPIO0_DMA	{ 0, 0 }
++#define GPIO1_IRQ		{ IRQ_PB11MP_GPIO1, NO_IRQ }
++#define GPIO1_DMA		{ 0, 0 }
++#define PB11MP_RTC_IRQ		{ IRQ_TC11MP_RTC, NO_IRQ }
++#define PB11MP_RTC_DMA		{ 0, 0 }
++#define SCI_IRQ			{ IRQ_PB11MP_SCI, NO_IRQ }
++#define SCI_DMA			{ 7, 6 }
++#define PB11MP_UART0_IRQ	{ IRQ_TC11MP_UART0, NO_IRQ }
++#define PB11MP_UART0_DMA	{ 15, 14 }
++#define PB11MP_UART1_IRQ	{ IRQ_TC11MP_UART1, NO_IRQ }
++#define PB11MP_UART1_DMA	{ 13, 12 }
++#define PB11MP_UART2_IRQ	{ IRQ_PB11MP_UART2, NO_IRQ }
++#define PB11MP_UART2_DMA	{ 11, 10 }
++#define PB11MP_UART3_IRQ	{ IRQ_PB11MP_UART3, NO_IRQ }
++#define PB11MP_UART3_DMA	{ 0x86, 0x87 }
++#define PB11MP_SSP_IRQ		{ IRQ_PB11MP_SSP, NO_IRQ }
++#define PB11MP_SSP_DMA		{ 9, 8 }
++
++/* FPGA Primecells */
++AMBA_DEVICE(aaci,	"fpga:04",	AACI,		NULL);
++AMBA_DEVICE(mmc0,	"fpga:05",	MMCI0,		&realview_mmc0_plat_data);
++AMBA_DEVICE(kmi0,	"fpga:06",	KMI0,		NULL);
++AMBA_DEVICE(kmi1,	"fpga:07",	KMI1,		NULL);
++AMBA_DEVICE(uart3,	"fpga:09",	PB11MP_UART3,	NULL);
++
++/* DevChip Primecells */
++AMBA_DEVICE(smc,	"dev:00",	PB11MP_SMC,	NULL);
++AMBA_DEVICE(sctl,	"dev:e0",	SCTL,		NULL);
++AMBA_DEVICE(wdog,	"dev:e1",	PB11MP_WATCHDOG, NULL);
++AMBA_DEVICE(gpio0,	"dev:e4",	PB11MP_GPIO0,	NULL);
++AMBA_DEVICE(gpio1,	"dev:e5",	GPIO1,		NULL);
++AMBA_DEVICE(gpio2,	"dev:e6",	GPIO2,		NULL);
++AMBA_DEVICE(rtc,	"dev:e8",	PB11MP_RTC,	NULL);
++AMBA_DEVICE(sci0,	"dev:f0",	SCI,		NULL);
++AMBA_DEVICE(uart0,	"dev:f1",	PB11MP_UART0,	NULL);
++AMBA_DEVICE(uart1,	"dev:f2",	PB11MP_UART1,	NULL);
++AMBA_DEVICE(uart2,	"dev:f3",	PB11MP_UART2,	NULL);
++AMBA_DEVICE(ssp0,	"dev:f4",	PB11MP_SSP,	NULL);
++
++/* Primecells on the NEC ISSP chip */
++AMBA_DEVICE(clcd,	"issp:20",	PB11MP_CLCD,	&clcd_plat_data);
++AMBA_DEVICE(dmac,	"issp:30",	DMAC,		NULL);
++
++static struct amba_device *amba_devs[] __initdata = {
++	&dmac_device,
++	&uart0_device,
++	&uart1_device,
++	&uart2_device,
++	&uart3_device,
++	&smc_device,
++	&clcd_device,
++	&sctl_device,
++	&wdog_device,
++	&gpio0_device,
++	&gpio1_device,
++	&gpio2_device,
++	&rtc_device,
++	&sci0_device,
++	&ssp0_device,
++	&aaci_device,
++	&mmc0_device,
++	&kmi0_device,
++	&kmi1_device,
++};
++
++/*
++ * RealView PB11MPCore platform devices
++ */
++static struct resource realview_pb11mp_flash_resource[] = {
++	[0] = {
++		.start		= REALVIEW_PB11MP_FLASH0_BASE,
++		.end		= REALVIEW_PB11MP_FLASH0_BASE + REALVIEW_PB11MP_FLASH0_SIZE - 1,
++		.flags		= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start		= REALVIEW_PB11MP_FLASH1_BASE,
++		.end		= REALVIEW_PB11MP_FLASH1_BASE + REALVIEW_PB11MP_FLASH1_SIZE - 1,
++		.flags		= IORESOURCE_MEM,
++	},
++};
++
++static struct resource realview_pb11mp_smsc911x_resources[] = {
++	[0] = {
++		.start		= REALVIEW_PB11MP_ETH_BASE,
++		.end		= REALVIEW_PB11MP_ETH_BASE + SZ_64K - 1,
++		.flags		= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start		= IRQ_TC11MP_ETH,
++		.end		= IRQ_TC11MP_ETH,
++		.flags		= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device realview_pb11mp_smsc911x_device = {
++	.name		= "smc911x",
++	.id		= 0,
++	.num_resources	= ARRAY_SIZE(realview_pb11mp_smsc911x_resources),
++	.resource	= realview_pb11mp_smsc911x_resources,
++};
++
++struct resource realview_pb11mp_cf_resources[] = {
++	[0] = {
++		.start		= REALVIEW_PB11MP_CF_BASE,
++		.end		= REALVIEW_PB11MP_CF_BASE + SZ_4K - 1,
++		.flags		= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start		= REALVIEW_PB11MP_CF_MEM_BASE,
++		.end		= REALVIEW_PB11MP_CF_MEM_BASE + SZ_4K - 1,
++		.flags		= IORESOURCE_MEM,
++	},
++	[2] = {
++		.start		= -1,		/* FIXME: Find correct irq */
++		.end		= -1,
++		.flags		= IORESOURCE_IRQ,
++	},
++};
++
++struct platform_device realview_pb11mp_cf_device = {
++	.name		= "compactflash",
++	.id		= 0,
++	.num_resources	= ARRAY_SIZE(realview_pb11mp_cf_resources),
++	.resource	= realview_pb11mp_cf_resources,
++};
++
++static void __init gic_init_irq(void)
++{
++	unsigned int pldctrl;
++
++	/* new irq mode with no DCC */
++	writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
++	pldctrl = readl(__io_address(REALVIEW_SYS_BASE)	+ REALVIEW_PB11MP_SYS_PLD_CTRL1);
++	pldctrl |= 2 << 22;
++	writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_PB11MP_SYS_PLD_CTRL1);
++	writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
++
++	/* ARM11MPCore test chip GIC, primary */
++	gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE);
++	gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29);
++	gic_cpu_init(0, gic_cpu_base_addr);
++
++	/* board GIC, secondary */
++	gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START);
++	gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
++	gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1);
++}
++
++static void __init realview_pb11mp_timer_init(void)
++{
++	timer0_va_base = __io_address(REALVIEW_PB11MP_TIMER0_1_BASE);
++	timer1_va_base = __io_address(REALVIEW_PB11MP_TIMER0_1_BASE) + 0x20;
++	timer2_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE);
++	timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20;
++
++#ifdef CONFIG_LOCAL_TIMERS
++	twd_base_addr = __io_address(REALVIEW_TC11MP_TWD_BASE);
++	twd_size = REALVIEW_TC11MP_TWD_SIZE;
++#endif
++	realview_timer_init(IRQ_TC11MP_TIMER0_1);
++}
++
++static struct sys_timer realview_pb11mp_timer = {
++	.init		= realview_pb11mp_timer_init,
++};
++
++static void __init realview_pb11mp_init(void)
++{
++	int i;
++
++#ifdef CONFIG_CACHE_L2X0
++	/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
++	 * Bits:  .... ...0 0111 1001 0000 .... .... .... */
++	l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff);
++#endif
++
++	clk_register(&realview_clcd_clk);
++
++	realview_flash_register(realview_pb11mp_flash_resource,
++				ARRAY_SIZE(realview_pb11mp_flash_resource));
++	platform_device_register(&realview_pb11mp_smsc911x_device);
++	platform_device_register(&realview_i2c_device);
++	platform_device_register(&realview_pb11mp_cf_device);
++
++	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
++		struct amba_device *d = amba_devs[i];
++		amba_device_register(d, &iomem_resource);
++	}
++
++#ifdef CONFIG_LEDS
++	leds_event = realview_leds_event;
++#endif
++}
++
++MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
++	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
++	.phys_io	= REALVIEW_PB11MP_UART0_BASE,
++	.io_pg_offst	= (IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE) >> 18) & 0xfffc,
++	.boot_params	= 0x00000100,
++	.map_io		= realview_pb11mp_map_io,
++	.init_irq	= gic_init_irq,
++	.timer		= &realview_pb11mp_timer,
++	.init_machine	= realview_pb11mp_init,
++MACHINE_END
+diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
+index e2079cf..cd3dc08 100644
+--- a/arch/arm/mach-s3c2410/Kconfig
++++ b/arch/arm/mach-s3c2410/Kconfig
+@@ -97,6 +97,13 @@ config BAST_PC104_IRQ
+ 	  Say Y	here to enable the PC104 IRQ routing on the
+ 	  Simtec BAST (EB2410ITX)
+ 
++config MACH_TCT_HAMMER
++	bool "TCT Hammer Board"
++	select CPU_S3C2410
++	help
++	   Say Y here if you are using the TinCanTools Hammer Board
++           <http://www.tincantools.com>
++
+ config MACH_VR1000
+ 	bool "Thorcom VR1000"
+ 	select PM_SIMTEC if PM
+diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
+index 3e7a855..cabc13c 100644
+--- a/arch/arm/mach-s3c2410/Makefile
++++ b/arch/arm/mach-s3c2410/Makefile
+@@ -27,5 +27,6 @@ obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
+ obj-$(CONFIG_MACH_OTOM)		+= mach-otom.o
+ obj-$(CONFIG_MACH_AML_M5900)	+= mach-amlm5900.o
+ obj-$(CONFIG_BAST_PC104_IRQ)	+= bast-irq.o
++obj-$(CONFIG_MACH_TCT_HAMMER)	+= mach-tct_hammer.o
+ obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
+ obj-$(CONFIG_MACH_QT2410)	+= mach-qt2410.o
+diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
+index 6617547..661a235 100644
+--- a/arch/arm/mach-s3c2410/mach-bast.c
++++ b/arch/arm/mach-s3c2410/mach-bast.c
+@@ -16,6 +16,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
++#include <linux/sysdev.h>
+ #include <linux/serial_core.h>
+ #include <linux/platform_device.h>
+ #include <linux/dm9000.h>
+@@ -236,6 +237,36 @@ static struct platform_device bast_device_nor = {
+ 
+ /* NAND Flash on BAST board */
+ 
++#ifdef CONFIG_PM
++static int bast_pm_suspend(struct sys_device *sd, pm_message_t state)
++{
++	/* ensure that an nRESET is not generated on resume. */
++	s3c2410_gpio_setpin(S3C2410_GPA21, 1);
++	s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_OUT);
++
++	return 0;
++}
++
++static int bast_pm_resume(struct sys_device *sd)
++{
++	s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_nRSTOUT);
++	return 0;
++}
++
++#else
++#define bast_pm_suspend NULL
++#define bast_pm_resume NULL
++#endif
++
++static struct sysdev_class bast_pm_sysclass = {
++	.name		= "mach-bast",
++	.suspend	= bast_pm_suspend,
++	.resume		= bast_pm_resume,
++};
++
++static struct sys_device bast_pm_sysdev = {
++	.cls		= &bast_pm_sysclass,
++};
+ 
+ static int smartmedia_map[] = { 0 };
+ static int chip0_map[] = { 1 };
+@@ -561,10 +592,10 @@ static void __init bast_map_io(void)
+ {
+ 	/* initialise the clocks */
+ 
+-	s3c24xx_dclk0.parent = NULL;
++	s3c24xx_dclk0.parent = &clk_upll;
+ 	s3c24xx_dclk0.rate   = 12*1000*1000;
+ 
+-	s3c24xx_dclk1.parent = NULL;
++	s3c24xx_dclk1.parent = &clk_upll;
+ 	s3c24xx_dclk1.rate   = 24*1000*1000;
+ 
+ 	s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
+@@ -586,6 +617,9 @@ static void __init bast_map_io(void)
+ 
+ static void __init bast_init(void)
+ {
++	sysdev_class_register(&bast_pm_sysclass);
++	sysdev_register(&bast_pm_sysdev);
++
+ 	s3c24xx_fb_set_platdata(&bast_fb_info);
+ 	platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices));
+ }
+diff --git a/arch/arm/mach-s3c2410/mach-tct_hammer.c b/arch/arm/mach-s3c2410/mach-tct_hammer.c
+new file mode 100644
+index 0000000..d90d445
+--- /dev/null
++++ b/arch/arm/mach-s3c2410/mach-tct_hammer.c
+@@ -0,0 +1,160 @@
++/* linux/arch/arm/mach-s3c2410/mach-tct_hammer.c
++ *
++ * Copyright (c) 2007 TinCanTools
++ *	David Anders <danders at amltd.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
++ *
++ * @History:
++ * derived from linux/arch/arm/mach-s3c2410/mach-bast.c, written by
++ * Ben Dooks <ben at simtec.co.uk>
++ *
++ ***********************************************************************/
++
++#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/device.h>
++#include <linux/platform_device.h>
++#include <linux/serial_core.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/flash.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/mach-types.h>
++
++#include <asm/plat-s3c/regs-serial.h>
++#include <asm/plat-s3c24xx/devs.h>
++#include <asm/plat-s3c24xx/cpu.h>
++
++#ifdef CONFIG_MTD_PARTITIONS
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/physmap.h>
++
++static struct resource tct_hammer_nor_resource = {
++		.start = 0x00000000,
++		.end   = 0x01000000 - 1,
++		.flags = IORESOURCE_MEM,
++};
++
++static struct mtd_partition tct_hammer_mtd_partitions[] = {
++	{
++		.name		= "System",
++		.size		= 0x240000,
++		.offset		= 0,
++		.mask_flags 	= MTD_WRITEABLE,  /* force read-only */
++	}, {
++		.name		= "JFFS2",
++		.size		= MTDPART_SIZ_FULL,
++		.offset		= MTDPART_OFS_APPEND,
++	}
++};
++
++static struct physmap_flash_data tct_hammer_flash_data = {
++	.width		= 2,
++	.parts		= tct_hammer_mtd_partitions,
++	.nr_parts	= ARRAY_SIZE(tct_hammer_mtd_partitions),
++};
++
++static struct platform_device tct_hammer_device_nor = {
++	.name		= "physmap-flash",
++	.id		= 0,
++	.dev = {
++			.platform_data = &tct_hammer_flash_data,
++		},
++	.num_resources	= 1,
++	.resource	= &tct_hammer_nor_resource,
++};
++
++#endif
++
++static struct map_desc tct_hammer_iodesc[] __initdata = {
++};
++
++#define UCON S3C2410_UCON_DEFAULT
++#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
++#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
++
++static struct s3c2410_uartcfg tct_hammer_uartcfgs[] = {
++	[0] = {
++		.hwport	     = 0,
++		.flags	     = 0,
++		.ucon	     = UCON,
++		.ulcon	     = ULCON,
++		.ufcon	     = UFCON,
++	},
++	[1] = {
++		.hwport	     = 1,
++		.flags	     = 0,
++		.ucon	     = UCON,
++		.ulcon	     = ULCON,
++		.ufcon	     = UFCON,
++	},
++	[2] = {
++		.hwport	     = 2,
++		.flags	     = 0,
++		.ucon	     = UCON,
++		.ulcon	     = ULCON,
++		.ufcon	     = UFCON,
++	}
++};
++
++
++static struct platform_device *tct_hammer_devices[] __initdata = {
++	&s3c_device_adc,
++	&s3c_device_wdt,
++	&s3c_device_i2c,
++	&s3c_device_usb,
++	&s3c_device_rtc,
++	&s3c_device_usbgadget,
++	&s3c_device_sdi,
++#ifdef CONFIG_MTD_PARTITIONS
++	&tct_hammer_device_nor,
++#endif
++};
++
++static void __init tct_hammer_map_io(void)
++{
++	s3c24xx_init_io(tct_hammer_iodesc, ARRAY_SIZE(tct_hammer_iodesc));
++	s3c24xx_init_clocks(0);
++	s3c24xx_init_uarts(tct_hammer_uartcfgs, ARRAY_SIZE(tct_hammer_uartcfgs));
++}
++
++static void __init tct_hammer_init(void)
++{
++	platform_add_devices(tct_hammer_devices, ARRAY_SIZE(tct_hammer_devices));
++}
++
++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,
++	.init_machine	= tct_hammer_init,
++	.timer		= &s3c24xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
+index 3aade7b..c564233 100644
+--- a/arch/arm/mach-s3c2410/mach-vr1000.c
++++ b/arch/arm/mach-s3c2410/mach-vr1000.c
+@@ -393,7 +393,7 @@ static void __init vr1000_map_io(void)
+ {
+ 	/* initialise clock sources */
+ 
+-	s3c24xx_dclk0.parent = NULL;
++	s3c24xx_dclk0.parent = &clk_upll;
+ 	s3c24xx_dclk0.rate   = 12*1000*1000;
+ 
+ 	s3c24xx_dclk1.parent = NULL;
+diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
+index abf1599..98a0de9 100644
+--- a/arch/arm/mach-s3c2412/s3c2412.c
++++ b/arch/arm/mach-s3c2412/s3c2412.c
+@@ -175,7 +175,7 @@ void __init s3c2412_init_clocks(int xtal)
+ 	/* work out clock scalings */
+ 
+ 	hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
+-	hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
++	hclk /= ((tmp & S3C2412_CLKDIVN_ARMDIVN) ? 2 : 1);
+ 	pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
+ 
+ 	/* print brieft summary of clocks, etc */
+diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
+index 3d3dfa9..4725891 100644
+--- a/arch/arm/mach-s3c2440/mach-anubis.c
++++ b/arch/arm/mach-s3c2440/mach-anubis.c
+@@ -413,10 +413,10 @@ static void __init anubis_map_io(void)
+ {
+ 	/* initialise the clocks */
+ 
+-	s3c24xx_dclk0.parent = NULL;
++	s3c24xx_dclk0.parent = &clk_upll;
+ 	s3c24xx_dclk0.rate   = 12*1000*1000;
+ 
+-	s3c24xx_dclk1.parent = NULL;
++	s3c24xx_dclk1.parent = &clk_upll;
+ 	s3c24xx_dclk1.rate   = 24*1000*1000;
+ 
+ 	s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
+diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
+index 78af766..8a8acdb 100644
+--- a/arch/arm/mach-s3c2440/mach-osiris.c
++++ b/arch/arm/mach-s3c2440/mach-osiris.c
+@@ -18,6 +18,7 @@
+ #include <linux/device.h>
+ #include <linux/sysdev.h>
+ #include <linux/serial_core.h>
++#include <linux/clk.h>
+ 
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+@@ -344,10 +345,10 @@ static void __init osiris_map_io(void)
+ 
+ 	/* initialise the clocks */
+ 
+-	s3c24xx_dclk0.parent = NULL;
++	s3c24xx_dclk0.parent = &clk_upll;
+ 	s3c24xx_dclk0.rate   = 12*1000*1000;
+ 
+-	s3c24xx_dclk1.parent = NULL;
++	s3c24xx_dclk1.parent = &clk_upll;
+ 	s3c24xx_dclk1.rate   = 24*1000*1000;
+ 
+ 	s3c24xx_clkout0.parent  = &s3c24xx_dclk0;
+diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
+index 7a61e8d..8e02446 100644
+--- a/arch/arm/mach-sa1100/Makefile
++++ b/arch/arm/mach-sa1100/Makefile
+@@ -3,7 +3,7 @@
+ #
+ 
+ # Common support
+-obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o
++obj-y := clock.o generic.o gpio.o irq.o dma.o time.o #nmi-oopser.o
+ obj-m :=
+ obj-n :=
+ obj-  :=
+diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
+index 5c84c60..0c2fa1c 100644
+--- a/arch/arm/mach-sa1100/generic.c
++++ b/arch/arm/mach-sa1100/generic.c
+@@ -139,37 +139,6 @@ unsigned long long sched_clock(void)
+ 	return v;
+ }
+ 
+-int gpio_direction_input(unsigned gpio)
+-{
+-	unsigned long flags;
+-
+-	if (gpio > GPIO_MAX)
+-		return -EINVAL;
+-
+-	local_irq_save(flags);
+-	GPDR &= ~GPIO_GPIO(gpio);
+-	local_irq_restore(flags);
+-	return 0;
+-}
+-
+-EXPORT_SYMBOL(gpio_direction_input);
+-
+-int gpio_direction_output(unsigned gpio, int value)
+-{
+-	unsigned long flags;
+-
+-	if (gpio > GPIO_MAX)
+-		return -EINVAL;
+-
+-	local_irq_save(flags);
+-	gpio_set_value(gpio, value);
+-	GPDR |= GPIO_GPIO(gpio);
+-	local_irq_restore(flags);
+-	return 0;
+-}
+-
+-EXPORT_SYMBOL(gpio_direction_output);
+-
+ /*
+  * Default power-off for SA1100
+  */
+diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
+index f085d68..793c2e6 100644
+--- a/arch/arm/mach-sa1100/generic.h
++++ b/arch/arm/mach-sa1100/generic.h
+@@ -9,6 +9,7 @@ struct sys_timer;
+ extern struct sys_timer sa1100_timer;
+ extern void __init sa1100_map_io(void);
+ extern void __init sa1100_init_irq(void);
++extern void __init sa1100_init_gpio(void);
+ 
+ #define SET_BANK(__nr,__start,__size) \
+ 	mi->bank[__nr].start = (__start), \
+diff --git a/arch/arm/mach-sa1100/gpio.c b/arch/arm/mach-sa1100/gpio.c
+new file mode 100644
+index 0000000..372f1f4
+--- /dev/null
++++ b/arch/arm/mach-sa1100/gpio.c
+@@ -0,0 +1,65 @@
++/*
++ * linux/arch/arm/mach-sa1100/gpio.c
++ *
++ * Generic SA-1100 GPIO handling
++ *
++ * This program is free software; you can redistribute it 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 <asm/gpio.h>
++#include <asm/hardware.h>
++#include "generic.h"
++
++static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++	return GPLR & GPIO_GPIO(offset);
++}
++
++static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++	if (value)
++		GPSR = GPIO_GPIO(offset);
++	else
++		GPCR = GPIO_GPIO(offset);
++}
++
++static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++	unsigned long flags;
++
++	local_irq_save(flags);
++	GPDR &= ~GPIO_GPIO(offset);
++	local_irq_restore(flags);
++	return 0;
++}
++
++static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
++{
++	unsigned long flags;
++
++	local_irq_save(flags);
++	sa1100_gpio_set(chip, offset, value);
++	GPDR |= GPIO_GPIO(offset);
++	local_irq_restore(flags);
++	return 0;
++}
++
++static struct gpio_chip sa1100_gpio_chip = {
++	.label			= "gpio",
++	.direction_input	= sa1100_direction_input,
++	.direction_output	= sa1100_direction_output,
++	.set			= sa1100_gpio_set,
++	.get			= sa1100_gpio_get,
++	.base			= 0,
++	.ngpio			= GPIO_MAX + 1,
++};
++
++void __init sa1100_init_gpio(void)
++{
++	gpiochip_add(&sa1100_gpio_chip);
++}
+diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
+index 3dc17d7..fa0403a 100644
+--- a/arch/arm/mach-sa1100/irq.c
++++ b/arch/arm/mach-sa1100/irq.c
+@@ -347,4 +347,6 @@ void __init sa1100_init_irq(void)
+ 	 */
+ 	set_irq_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
+ 	set_irq_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
++
++	sa1100_init_gpio();
+ }
+diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
+index c267736..a9799cb 100644
+--- a/arch/arm/mach-sa1100/time.c
++++ b/arch/arm/mach-sa1100/time.c
+@@ -13,67 +13,69 @@
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/timex.h>
+-#include <linux/signal.h>
+-#include <linux/clocksource.h>
++#include <linux/clockchips.h>
+ 
+ #include <asm/mach/time.h>
+ #include <asm/hardware.h>
+ 
+-#define RTC_DEF_DIVIDER		(32768 - 1)
+-#define RTC_DEF_TRIM            0
++#define MIN_OSCR_DELTA 2
+ 
+-static int sa1100_set_rtc(void)
++static irqreturn_t sa1100_ost0_interrupt(int irq, void *dev_id)
+ {
+-	unsigned long current_time = xtime.tv_sec;
++	struct clock_event_device *c = dev_id;
+ 
+-	if (RTSR & RTSR_ALE) {
+-		/* make sure not to forward the clock over an alarm */
+-		unsigned long alarm = RTAR;
+-		if (current_time >= alarm && alarm >= RCNR)
+-			return -ERESTARTSYS;
+-	}
+-	RCNR = current_time;
+-	return 0;
+-}
++	/* Disarm the compare/match, signal the event. */
++	OIER &= ~OIER_E0;
++	OSSR = OSSR_M0;
++	c->event_handler(c);
+ 
+-#ifdef CONFIG_NO_IDLE_HZ
+-static unsigned long initial_match;
+-static int match_posponed;
+-#endif
++	return IRQ_HANDLED;
++}
+ 
+-static irqreturn_t
+-sa1100_timer_interrupt(int irq, void *dev_id)
++static int
++sa1100_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c)
+ {
+-	unsigned int next_match;
++	unsigned long flags, next, oscr;
+ 
+-#ifdef CONFIG_NO_IDLE_HZ
+-	if (match_posponed) {
+-		match_posponed = 0;
+-		OSMR0 = initial_match;
+-	}
+-#endif
++	raw_local_irq_save(flags);
++	OIER |= OIER_E0;
++	next = OSCR + delta;
++	OSMR0 = next;
++	oscr = OSCR;
++	raw_local_irq_restore(flags);
+ 
+-	/*
+-	 * Loop until we get ahead of the free running timer.
+-	 * This ensures an exact clock tick count and time accuracy.
+-	 * Since IRQs are disabled at this point, coherence between
+-	 * lost_ticks(updated in do_timer()) and the match reg value is
+-	 * ensured, hence we can use do_gettimeofday() from interrupt
+-	 * handlers.
+-	 */
+-	do {
+-		timer_tick();
+-		OSSR = OSSR_M0;  /* Clear match on timer 0 */
+-		next_match = (OSMR0 += LATCH);
+-	} while ((signed long)(next_match - OSCR) <= 0);
++	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
++}
+ 
+-	return IRQ_HANDLED;
++static void
++sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
++{
++	unsigned long flags;
++
++	switch (mode) {
++	case CLOCK_EVT_MODE_ONESHOT:
++	case CLOCK_EVT_MODE_UNUSED:
++	case CLOCK_EVT_MODE_SHUTDOWN:
++		raw_local_irq_save(flags);
++		OIER &= ~OIER_E0;
++		OSSR = OSSR_M0;
++		raw_local_irq_restore(flags);
++		break;
++
++	case CLOCK_EVT_MODE_RESUME:
++	case CLOCK_EVT_MODE_PERIODIC:
++		break;
++	}
+ }
+ 
+-static struct irqaction sa1100_timer_irq = {
+-	.name		= "SA11xx Timer Tick",
+-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+-	.handler	= sa1100_timer_interrupt,
++static struct clock_event_device ckevt_sa1100_osmr0 = {
++	.name		= "osmr0",
++	.features	= CLOCK_EVT_FEAT_ONESHOT,
++	.shift		= 32,
++	.rating		= 200,
++	.cpumask	= CPU_MASK_CPU0,
++	.set_next_event	= sa1100_osmr0_set_next_event,
++	.set_mode	= sa1100_osmr0_set_mode,
+ };
+ 
+ static cycle_t sa1100_read_oscr(void)
+@@ -90,62 +92,34 @@ static struct clocksource cksrc_sa1100_oscr = {
+ 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+ };
+ 
++static struct irqaction sa1100_timer_irq = {
++	.name		= "ost0",
++	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++	.handler	= sa1100_ost0_interrupt,
++	.dev_id		= &ckevt_sa1100_osmr0,
++};
++
+ static void __init sa1100_timer_init(void)
+ {
+-	unsigned long flags;
+-
+-	set_rtc = sa1100_set_rtc;
+-
+ 	OIER = 0;		/* disable any timer interrupts */
+ 	OSSR = 0xf;		/* clear status on all timers */
+-	setup_irq(IRQ_OST0, &sa1100_timer_irq);
+-	local_irq_save(flags);
+-	OIER = OIER_E0;		/* enable match on timer 0 to cause interrupts */
+-	OSMR0 = OSCR + LATCH;	/* set initial match */
+-	local_irq_restore(flags);
++
++	ckevt_sa1100_osmr0.mult =
++		div_sc(3686400, NSEC_PER_SEC, ckevt_sa1100_osmr0.shift);
++	ckevt_sa1100_osmr0.max_delta_ns =
++		clockevent_delta2ns(0x7fffffff, &ckevt_sa1100_osmr0);
++	ckevt_sa1100_osmr0.min_delta_ns =
++		clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1;
+ 
+ 	cksrc_sa1100_oscr.mult =
+ 		clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_sa1100_oscr.shift);
+ 
+-	clocksource_register(&cksrc_sa1100_oscr);
+-}
+-
+-#ifdef CONFIG_NO_IDLE_HZ
+-static int sa1100_dyn_tick_enable_disable(void)
+-{
+-	/* nothing to do */
+-	return 0;
+-}
+-
+-static void sa1100_dyn_tick_reprogram(unsigned long ticks)
+-{
+-	if (ticks > 1) {
+-		initial_match = OSMR0;
+-		OSMR0 = initial_match + ticks * LATCH;
+-		match_posponed = 1;
+-	}
+-}
++	setup_irq(IRQ_OST0, &sa1100_timer_irq);
+ 
+-static irqreturn_t
+-sa1100_dyn_tick_handler(int irq, void *dev_id)
+-{
+-	if (match_posponed) {
+-		match_posponed = 0;
+-		OSMR0 = initial_match;
+-		if ((signed long)(initial_match - OSCR) <= 0)
+-			return sa1100_timer_interrupt(irq, dev_id);
+-	}
+-	return IRQ_NONE;
++	clocksource_register(&cksrc_sa1100_oscr);
++	clockevents_register_device(&ckevt_sa1100_osmr0);
+ }
+ 
+-static struct dyn_tick_timer sa1100_dyn_tick = {
+-	.enable		= sa1100_dyn_tick_enable_disable,
+-	.disable	= sa1100_dyn_tick_enable_disable,
+-	.reprogram	= sa1100_dyn_tick_reprogram,
+-	.handler	= sa1100_dyn_tick_handler,
+-};
+-#endif
+-
+ #ifdef CONFIG_PM
+ unsigned long osmr[4], oier;
+ 
+@@ -181,7 +155,4 @@ struct sys_timer sa1100_timer = {
+ 	.init		= sa1100_timer_init,
+ 	.suspend	= sa1100_timer_suspend,
+ 	.resume		= sa1100_timer_resume,
+-#ifdef CONFIG_NO_IDLE_HZ
+-	.dyn_tick	= &sa1100_dyn_tick,
+-#endif
+ };
+diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c
+index 9858c96..9336508 100644
+--- a/arch/arm/mach-versatile/clock.c
++++ b/arch/arm/mach-versatile/clock.c
+@@ -17,7 +17,6 @@
+ #include <linux/clk.h>
+ #include <linux/mutex.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/hardware/icst307.h>
+ 
+ #include "clock.h"
+diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
+index 76348f0..1b8229d 100644
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -18,6 +18,7 @@ config CPU_ARM610
+ 	select CPU_CP15_MMU
+ 	select CPU_COPY_V3 if MMU
+ 	select CPU_TLB_V3 if MMU
++	select CPU_PABRT_NOIFAR
+ 	help
+ 	  The ARM610 is the successor to the ARM3 processor
+ 	  and was produced by VLSI Technology Inc.
+@@ -31,6 +32,7 @@ config CPU_ARM7TDMI
+ 	depends on !MMU
+ 	select CPU_32v4T
+ 	select CPU_ABRT_LV4T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4
+ 	help
+ 	  A 32-bit RISC microprocessor based on the ARM7 processor core
+@@ -49,6 +51,7 @@ config CPU_ARM710
+ 	select CPU_CP15_MMU
+ 	select CPU_COPY_V3 if MMU
+ 	select CPU_TLB_V3 if MMU
++	select CPU_PABRT_NOIFAR
+ 	help
+ 	  A 32-bit RISC microprocessor based on the ARM7 processor core
+ 	  designed by Advanced RISC Machines Ltd. The ARM710 is the
+@@ -64,6 +67,7 @@ config CPU_ARM720T
+ 	default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X
+ 	select CPU_32v4T
+ 	select CPU_ABRT_LV4T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+@@ -82,6 +86,7 @@ config CPU_ARM740T
+ 	depends on !MMU
+ 	select CPU_32v4T
+ 	select CPU_ABRT_LV4T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V3	# although the core is v4t
+ 	select CPU_CP15_MPU
+ 	help
+@@ -98,6 +103,7 @@ config CPU_ARM9TDMI
+ 	depends on !MMU
+ 	select CPU_32v4T
+ 	select CPU_ABRT_NOMMU
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4
+ 	help
+ 	  A 32-bit RISC microprocessor based on the ARM9 processor core
+@@ -113,6 +119,7 @@ config CPU_ARM920T
+ 	default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
+ 	select CPU_32v4T
+ 	select CPU_ABRT_EV4T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4WT
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+@@ -135,6 +142,7 @@ config CPU_ARM922T
+ 	default y if ARCH_LH7A40X || ARCH_KS8695
+ 	select CPU_32v4T
+ 	select CPU_ABRT_EV4T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4WT
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+@@ -155,6 +163,7 @@ config CPU_ARM925T
+  	default y if ARCH_OMAP15XX
+ 	select CPU_32v4T
+ 	select CPU_ABRT_EV4T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4WT
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+@@ -175,6 +184,7 @@ config CPU_ARM926T
+ 	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || ARCH_NS9XXX || ARCH_DAVINCI
+ 	select CPU_32v5
+ 	select CPU_ABRT_EV5TJ
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+ 	select CPU_COPY_V4WB if MMU
+@@ -193,6 +203,7 @@ config CPU_ARM940T
+ 	depends on !MMU
+ 	select CPU_32v4T
+ 	select CPU_ABRT_NOMMU
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MPU
+ 	help
+@@ -210,6 +221,7 @@ config CPU_ARM946E
+ 	depends on !MMU
+ 	select CPU_32v5
+ 	select CPU_ABRT_NOMMU
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MPU
+ 	help
+@@ -226,6 +238,7 @@ config CPU_ARM1020
+ 	depends on ARCH_INTEGRATOR
+ 	select CPU_32v5
+ 	select CPU_ABRT_EV4T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4WT
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+@@ -244,6 +257,7 @@ config CPU_ARM1020E
+ 	depends on ARCH_INTEGRATOR
+ 	select CPU_32v5
+ 	select CPU_ABRT_EV4T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4WT
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+@@ -257,6 +271,7 @@ config CPU_ARM1022
+ 	depends on ARCH_INTEGRATOR
+ 	select CPU_32v5
+ 	select CPU_ABRT_EV4T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+ 	select CPU_COPY_V4WB if MMU # can probably do better
+@@ -275,6 +290,7 @@ config CPU_ARM1026
+ 	depends on ARCH_INTEGRATOR
+ 	select CPU_32v5
+ 	select CPU_ABRT_EV5T # But need Jazelle, but EV5TJ ignores bit 10
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+ 	select CPU_COPY_V4WB if MMU # can probably do better
+@@ -293,6 +309,7 @@ config CPU_SA110
+ 	select CPU_32v3 if ARCH_RPC
+ 	select CPU_32v4 if !ARCH_RPC
+ 	select CPU_ABRT_EV4
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4WB
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+@@ -314,6 +331,7 @@ config CPU_SA1100
+ 	default y
+ 	select CPU_32v4
+ 	select CPU_ABRT_EV4
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V4WB
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+@@ -326,6 +344,7 @@ config CPU_XSCALE
+ 	default y
+ 	select CPU_32v5
+ 	select CPU_ABRT_EV5T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+ 	select CPU_TLB_V4WBI if MMU
+@@ -337,6 +356,7 @@ config CPU_XSC3
+ 	default y
+ 	select CPU_32v5
+ 	select CPU_ABRT_EV5T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+ 	select CPU_TLB_V4WBI if MMU
+@@ -345,10 +365,11 @@ config CPU_XSC3
+ # Feroceon
+ config CPU_FEROCEON
+ 	bool
+-	depends on ARCH_ORION
++	depends on ARCH_ORION5X
+ 	default y
+ 	select CPU_32v5
+ 	select CPU_ABRT_EV5T
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_VIVT
+ 	select CPU_CP15_MMU
+ 	select CPU_COPY_V4WB if MMU
+@@ -366,11 +387,12 @@ config CPU_FEROCEON_OLD_ID
+ # ARMv6
+ config CPU_V6
+ 	bool "Support ARM V6 processor"
+-	depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3 || ARCH_MSM7X00A
++	depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3 || ARCH_MSM7X00A || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176
+ 	default y if ARCH_MX3
+ 	default y if ARCH_MSM7X00A
+ 	select CPU_32v6
+ 	select CPU_ABRT_EV6
++	select CPU_PABRT_NOIFAR
+ 	select CPU_CACHE_V6
+ 	select CPU_CACHE_VIPT
+ 	select CPU_CP15_MMU
+@@ -393,10 +415,11 @@ config CPU_32v6K
+ # ARMv7
+ config CPU_V7
+ 	bool "Support ARM V7 processor"
+-	depends on ARCH_INTEGRATOR
++	depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB
+ 	select CPU_32v6K
+ 	select CPU_32v7
+ 	select CPU_ABRT_EV7
++	select CPU_PABRT_IFAR
+ 	select CPU_CACHE_V7
+ 	select CPU_CACHE_VIPT
+ 	select CPU_CP15_MMU
+@@ -458,6 +481,12 @@ config CPU_ABRT_EV6
+ config CPU_ABRT_EV7
+ 	bool
+ 
++config CPU_PABRT_IFAR
++	bool
++
++config CPU_PABRT_NOIFAR
++	bool
++
+ # The cache model
+ config CPU_CACHE_V3
+ 	bool
+@@ -572,6 +601,13 @@ config ARM_THUMB
+ 
+ 	  If you don't know what this all is, saying Y is a safe choice.
+ 
++config ARM_THUMBEE
++	bool "Enable ThumbEE CPU extension"
++	depends on CPU_V7
++	help
++	  Say Y here if you have a CPU with the ThumbEE extension and code to
++	  make use of it. Say N for code that can run on CPUs without ThumbEE.
++
+ config CPU_BIG_ENDIAN
+ 	bool "Build big-endian kernel"
+ 	depends on ARCH_SUPPORTS_BIG_ENDIAN
+@@ -671,5 +707,9 @@ config OUTER_CACHE
+ 	default n
+ 
+ config CACHE_L2X0
+-	bool
++	bool "Enable the L2x0 outer cache controller"
++	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176
++	default y
+ 	select OUTER_CACHE
++	help
++	  This option enables the L2x0 PrimeCell.
+diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
+index ec00f26..b657f17 100644
+--- a/arch/arm/mm/init.c
++++ b/arch/arm/mm/init.c
+@@ -48,8 +48,6 @@ void show_mem(void)
+ 
+ 	printk("Mem-info:\n");
+ 	show_free_areas();
+-	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+-
+ 	for_each_online_node(node) {
+ 		pg_data_t *n = NODE_DATA(node);
+ 		struct page *map = n->node_mem_map - n->node_start_pfn;
+diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
+index 700c04d..5673f4d 100644
+--- a/arch/arm/mm/proc-arm1020.S
++++ b/arch/arm/mm/proc-arm1020.S
+@@ -471,6 +471,7 @@ arm1020_crval:
+ 	.type	arm1020_processor_functions, #object
+ arm1020_processor_functions:
+ 	.word	v4t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm1020_proc_init
+ 	.word	cpu_arm1020_proc_fin
+ 	.word	cpu_arm1020_reset
+diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
+index 1cc206a..4343fdb 100644
+--- a/arch/arm/mm/proc-arm1020e.S
++++ b/arch/arm/mm/proc-arm1020e.S
+@@ -452,6 +452,7 @@ arm1020e_crval:
+ 	.type	arm1020e_processor_functions, #object
+ arm1020e_processor_functions:
+ 	.word	v4t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm1020e_proc_init
+ 	.word	cpu_arm1020e_proc_fin
+ 	.word	cpu_arm1020e_reset
+diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
+index aff0ea0..2a4ea16 100644
+--- a/arch/arm/mm/proc-arm1022.S
++++ b/arch/arm/mm/proc-arm1022.S
+@@ -435,6 +435,7 @@ arm1022_crval:
+ 	.type	arm1022_processor_functions, #object
+ arm1022_processor_functions:
+ 	.word	v4t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm1022_proc_init
+ 	.word	cpu_arm1022_proc_fin
+ 	.word	cpu_arm1022_reset
+diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
+index 65e43a1..77a1bab 100644
+--- a/arch/arm/mm/proc-arm1026.S
++++ b/arch/arm/mm/proc-arm1026.S
+@@ -430,6 +430,7 @@ arm1026_crval:
+ 	.type	arm1026_processor_functions, #object
+ arm1026_processor_functions:
+ 	.word	v5t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm1026_proc_init
+ 	.word	cpu_arm1026_proc_fin
+ 	.word	cpu_arm1026_reset
+diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
+index 123a7dc..c371fc8 100644
+--- a/arch/arm/mm/proc-arm6_7.S
++++ b/arch/arm/mm/proc-arm6_7.S
+@@ -293,6 +293,7 @@ __arm7_setup:	mov	r0, #0
+ 		.type	arm6_processor_functions, #object
+ ENTRY(arm6_processor_functions)
+ 		.word	cpu_arm6_data_abort
++		.word	pabort_noifar
+ 		.word	cpu_arm6_proc_init
+ 		.word	cpu_arm6_proc_fin
+ 		.word	cpu_arm6_reset
+@@ -309,6 +310,7 @@ ENTRY(arm6_processor_functions)
+ 		.type	arm7_processor_functions, #object
+ ENTRY(arm7_processor_functions)
+ 		.word	cpu_arm7_data_abort
++		.word	pabort_noifar
+ 		.word	cpu_arm7_proc_init
+ 		.word	cpu_arm7_proc_fin
+ 		.word	cpu_arm7_reset
+diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
+index dc763be..d64f8e6 100644
+--- a/arch/arm/mm/proc-arm720.S
++++ b/arch/arm/mm/proc-arm720.S
+@@ -198,6 +198,7 @@ arm720_crval:
+ 		.type	arm720_processor_functions, #object
+ ENTRY(arm720_processor_functions)
+ 		.word	v4t_late_abort
++		.word	pabort_noifar
+ 		.word	cpu_arm720_proc_init
+ 		.word	cpu_arm720_proc_fin
+ 		.word	cpu_arm720_reset
+diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
+index 7069f49..3a57376 100644
+--- a/arch/arm/mm/proc-arm740.S
++++ b/arch/arm/mm/proc-arm740.S
+@@ -126,6 +126,7 @@ __arm740_setup:
+ 	.type	arm740_processor_functions, #object
+ ENTRY(arm740_processor_functions)
+ 	.word	v4t_late_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm740_proc_init
+ 	.word	cpu_arm740_proc_fin
+ 	.word	cpu_arm740_reset
+diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
+index d091c25..7b3ecde 100644
+--- a/arch/arm/mm/proc-arm7tdmi.S
++++ b/arch/arm/mm/proc-arm7tdmi.S
+@@ -64,6 +64,7 @@ __arm7tdmi_setup:
+ 		.type	arm7tdmi_processor_functions, #object
+ ENTRY(arm7tdmi_processor_functions)
+ 		.word	v4t_late_abort
++		.word	pabort_noifar
+ 		.word	cpu_arm7tdmi_proc_init
+ 		.word	cpu_arm7tdmi_proc_fin
+ 		.word	cpu_arm7tdmi_reset
+diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
+index 75c945e..28cdb06 100644
+--- a/arch/arm/mm/proc-arm920.S
++++ b/arch/arm/mm/proc-arm920.S
+@@ -417,6 +417,7 @@ arm920_crval:
+ 	.type	arm920_processor_functions, #object
+ arm920_processor_functions:
+ 	.word	v4t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm920_proc_init
+ 	.word	cpu_arm920_proc_fin
+ 	.word	cpu_arm920_reset
+diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
+index ffb751b..94ddcb4 100644
+--- a/arch/arm/mm/proc-arm922.S
++++ b/arch/arm/mm/proc-arm922.S
+@@ -421,6 +421,7 @@ arm922_crval:
+ 	.type	arm922_processor_functions, #object
+ arm922_processor_functions:
+ 	.word	v4t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm922_proc_init
+ 	.word	cpu_arm922_proc_fin
+ 	.word	cpu_arm922_reset
+diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
+index 44c2c99..065087a 100644
+--- a/arch/arm/mm/proc-arm925.S
++++ b/arch/arm/mm/proc-arm925.S
+@@ -484,6 +484,7 @@ arm925_crval:
+ 	.type	arm925_processor_functions, #object
+ arm925_processor_functions:
+ 	.word	v4t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm925_proc_init
+ 	.word	cpu_arm925_proc_fin
+ 	.word	cpu_arm925_reset
+diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
+index 194ef48..997db84 100644
+--- a/arch/arm/mm/proc-arm926.S
++++ b/arch/arm/mm/proc-arm926.S
+@@ -437,6 +437,7 @@ arm926_crval:
+ 	.type	arm926_processor_functions, #object
+ arm926_processor_functions:
+ 	.word	v5tj_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm926_proc_init
+ 	.word	cpu_arm926_proc_fin
+ 	.word	cpu_arm926_reset
+diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
+index 786c593..44ead90 100644
+--- a/arch/arm/mm/proc-arm940.S
++++ b/arch/arm/mm/proc-arm940.S
+@@ -321,6 +321,7 @@ __arm940_setup:
+ 	.type	arm940_processor_functions, #object
+ ENTRY(arm940_processor_functions)
+ 	.word	nommu_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm940_proc_init
+ 	.word	cpu_arm940_proc_fin
+ 	.word	cpu_arm940_reset
+diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
+index a60c142..2218b0c 100644
+--- a/arch/arm/mm/proc-arm946.S
++++ b/arch/arm/mm/proc-arm946.S
+@@ -376,6 +376,7 @@ __arm946_setup:
+ 	.type	arm946_processor_functions, #object
+ ENTRY(arm946_processor_functions)
+ 	.word	nommu_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_arm946_proc_init
+ 	.word	cpu_arm946_proc_fin
+ 	.word	cpu_arm946_reset
+diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
+index 4848eea..c85c1f5 100644
+--- a/arch/arm/mm/proc-arm9tdmi.S
++++ b/arch/arm/mm/proc-arm9tdmi.S
+@@ -64,6 +64,7 @@ __arm9tdmi_setup:
+ 		.type	arm9tdmi_processor_functions, #object
+ ENTRY(arm9tdmi_processor_functions)
+ 		.word	nommu_early_abort
++		.word	pabort_noifar
+ 		.word	cpu_arm9tdmi_proc_init
+ 		.word	cpu_arm9tdmi_proc_fin
+ 		.word	cpu_arm9tdmi_reset
+diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
+index fa0dc7e..90e7594 100644
+--- a/arch/arm/mm/proc-feroceon.S
++++ b/arch/arm/mm/proc-feroceon.S
+@@ -423,6 +423,7 @@ feroceon_crval:
+ 	.type	feroceon_processor_functions, #object
+ feroceon_processor_functions:
+ 	.word	v5t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_feroceon_proc_init
+ 	.word	cpu_feroceon_proc_fin
+ 	.word	cpu_feroceon_reset
+diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
+index 6e226e1..9818195 100644
+--- a/arch/arm/mm/proc-sa110.S
++++ b/arch/arm/mm/proc-sa110.S
+@@ -216,6 +216,7 @@ sa110_crval:
+ 	.type	sa110_processor_functions, #object
+ ENTRY(sa110_processor_functions)
+ 	.word	v4_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_sa110_proc_init
+ 	.word	cpu_sa110_proc_fin
+ 	.word	cpu_sa110_reset
+diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
+index 9afb11d..c5fe27a 100644
+--- a/arch/arm/mm/proc-sa1100.S
++++ b/arch/arm/mm/proc-sa1100.S
+@@ -231,6 +231,7 @@ sa1100_crval:
+ 	.type	sa1100_processor_functions, #object
+ ENTRY(sa1100_processor_functions)
+ 	.word	v4_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_sa1100_proc_init
+ 	.word	cpu_sa1100_proc_fin
+ 	.word	cpu_sa1100_reset
+diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
+index eb42e5b..5702ec5 100644
+--- a/arch/arm/mm/proc-v6.S
++++ b/arch/arm/mm/proc-v6.S
+@@ -17,10 +17,6 @@
+ #include <asm/pgtable-hwdef.h>
+ #include <asm/pgtable.h>
+ 
+-#ifdef CONFIG_SMP
+-#include <asm/hardware/arm_scu.h>
+-#endif
+-
+ #include "proc-macros.S"
+ 
+ #define D_CACHE_LINE_SIZE	32
+@@ -187,20 +183,10 @@ cpu_v6_name:
+  */
+ __v6_setup:
+ #ifdef CONFIG_SMP
+-	/* Set up the SCU on core 0 only */
+-	mrc	p15, 0, r0, c0, c0, 5		@ CPU core number
+-	ands	r0, r0, #15
+-	ldreq	r0, =SCU_BASE
+-	ldreq	r5, [r0, #SCU_CTRL]
+-	orreq	r5, r5, #1
+-	streq	r5, [r0, #SCU_CTRL]
+-
+-#ifndef CONFIG_CPU_DCACHE_DISABLE
+ 	mrc	p15, 0, r0, c1, c0, 1		@ Enable SMP/nAMP mode
+ 	orr	r0, r0, #0x20
+ 	mcr	p15, 0, r0, c1, c0, 1
+ #endif
+-#endif
+ 
+ 	mov	r0, #0
+ 	mcr	p15, 0, r0, c7, c14, 0		@ clean+invalidate D cache
+@@ -233,6 +219,7 @@ v6_crval:
+ 	.type	v6_processor_functions, #object
+ ENTRY(v6_processor_functions)
+ 	.word	v6_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_v6_proc_init
+ 	.word	cpu_v6_proc_fin
+ 	.word	cpu_v6_reset
+diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
+index e0acc5a..b49f9a4 100644
+--- a/arch/arm/mm/proc-v7.S
++++ b/arch/arm/mm/proc-v7.S
+@@ -205,6 +205,7 @@ __v7_setup_stack:
+ 	.type	v7_processor_functions, #object
+ ENTRY(v7_processor_functions)
+ 	.word	v7_early_abort
++	.word	pabort_ifar
+ 	.word	cpu_v7_proc_init
+ 	.word	cpu_v7_proc_fin
+ 	.word	cpu_v7_reset
+diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
+index d95921a..3533741 100644
+--- a/arch/arm/mm/proc-xsc3.S
++++ b/arch/arm/mm/proc-xsc3.S
+@@ -450,6 +450,7 @@ xsc3_crval:
+ 	.type	xsc3_processor_functions, #object
+ ENTRY(xsc3_processor_functions)
+ 	.word	v5t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_xsc3_proc_init
+ 	.word	cpu_xsc3_proc_fin
+ 	.word	cpu_xsc3_reset
+diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
+index 016690b..2dd8527 100644
+--- a/arch/arm/mm/proc-xscale.S
++++ b/arch/arm/mm/proc-xscale.S
+@@ -527,6 +527,7 @@ xscale_crval:
+ 	.type	xscale_processor_functions, #object
+ ENTRY(xscale_processor_functions)
+ 	.word	v5t_early_abort
++	.word	pabort_noifar
+ 	.word	cpu_xscale_proc_init
+ 	.word	cpu_xscale_proc_fin
+ 	.word	cpu_xscale_reset
+diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
+index 98d0151..d9bc15a 100644
+--- a/arch/arm/plat-iop/pci.c
++++ b/arch/arm/plat-iop/pci.c
+@@ -24,6 +24,7 @@
+ #include <asm/hardware.h>
+ #include <asm/mach/pci.h>
+ #include <asm/hardware/iop3xx.h>
++#include <asm/mach-types.h>
+ 
+ // #define DEBUG
+ 
+@@ -209,8 +210,11 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
+ 	res[1].flags = IORESOURCE_MEM;
+ 	request_resource(&iomem_resource, &res[1]);
+ 
+-	sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - IOP3XX_PCI_LOWER_MEM_BA;
+-	sys->io_offset  = IOP3XX_PCI_LOWER_IO_PA - IOP3XX_PCI_LOWER_IO_BA;
++	/*
++	 * Use whatever translation is already setup.
++	 */
++	sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0;
++	sys->io_offset  = IOP3XX_PCI_LOWER_IO_PA - *IOP3XX_OIOWTVR;
+ 
+ 	sys->resource[0] = &res[0];
+ 	sys->resource[1] = &res[1];
+@@ -250,11 +254,11 @@ void __init iop3xx_atu_setup(void)
+ 	*IOP3XX_IATVR2 = PHYS_OFFSET;
+ 
+ 	/* Outbound window 0 */
+-	*IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_PA;
++	*IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_BA;
+ 	*IOP3XX_OUMWTVR0 = 0;
+ 
+ 	/* Outbound window 1 */
+-	*IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE;
++	*IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_BA + IOP3XX_PCI_MEM_WINDOW_SIZE;
+ 	*IOP3XX_OUMWTVR1 = 0;
+ 
+ 	/* BAR 3 ( Disabled ) */
+@@ -265,7 +269,7 @@ void __init iop3xx_atu_setup(void)
+ 
+ 	/* Setup the I/O Bar
+ 	 */
+-	*IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_PA;;
++	*IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_BA;
+ 
+ 	/* Enable inbound and outbound cycles
+ 	 */
+@@ -322,34 +326,59 @@ void __init iop3xx_atu_disable(void)
+ /* Flag to determine whether the ATU is initialized and the PCI bus scanned */
+ int init_atu;
+ 
+-void __init iop3xx_pci_preinit(void)
++int iop3xx_get_init_atu(void) {
++	/* check if default has been overridden */
++	if (init_atu != IOP3XX_INIT_ATU_DEFAULT)
++		return init_atu;
++	else
++		return IOP3XX_INIT_ATU_DISABLE;
++}
++
++static void __init iop3xx_atu_debug(void)
+ {
+-	if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) {
+-		iop3xx_atu_disable();
+-		iop3xx_atu_setup();
+-	}
++	DBG("PCI: Intel IOP3xx PCI init.\n");
++	DBG("PCI: Outbound memory window 0: PCI 0x%08x%08x\n",
++		*IOP3XX_OUMWTVR0, *IOP3XX_OMWTVR0);
++	DBG("PCI: Outbound memory window 1: PCI 0x%08x%08x\n",
++		*IOP3XX_OUMWTVR1, *IOP3XX_OMWTVR1);
++	DBG("PCI: Outbound IO window: PCI 0x%08x\n",
++		*IOP3XX_OIOWTVR);
++
++	DBG("PCI: Inbound memory window 0: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
++		*IOP3XX_IAUBAR0, *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0);
++	DBG("PCI: Inbound memory window 1: PCI 0x%08x%08x 0x%08x\n",
++		*IOP3XX_IAUBAR1, *IOP3XX_IABAR1, *IOP3XX_IALR1);
++	DBG("PCI: Inbound memory window 2: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
++		*IOP3XX_IAUBAR2, *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2);
++	DBG("PCI: Inbound memory window 3: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
++		*IOP3XX_IAUBAR3, *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3);
++
++	DBG("PCI: Expansion ROM window: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
++		0, *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR);
+ 
+-	DBG("PCI:  Intel 803xx PCI init code.\n");
+ 	DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD);
+-	DBG("ATU: IOP3XX_OMWTVR0=0x%04x, IOP3XX_OIOWTVR=0x%04x\n",
+-			*IOP3XX_OMWTVR0,
+-			*IOP3XX_OIOWTVR);
+ 	DBG("ATU: IOP3XX_ATUCR=0x%08x\n", *IOP3XX_ATUCR);
+-	DBG("ATU: IOP3XX_IABAR0=0x%08x IOP3XX_IALR0=0x%08x IOP3XX_IATVR0=%08x\n",
+-			*IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0);
+-	DBG("ATU: IOP3XX_OMWTVR0=0x%08x\n", *IOP3XX_OMWTVR0);
+-	DBG("ATU: IOP3XX_IABAR1=0x%08x IOP3XX_IALR1=0x%08x\n",
+-			*IOP3XX_IABAR1, *IOP3XX_IALR1);
+-	DBG("ATU: IOP3XX_ERBAR=0x%08x IOP3XX_ERLR=0x%08x IOP3XX_ERTVR=%08x\n",
+-			*IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR);
+-	DBG("ATU: IOP3XX_IABAR2=0x%08x IOP3XX_IALR2=0x%08x IOP3XX_IATVR2=%08x\n",
+-			*IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2);
+-	DBG("ATU: IOP3XX_IABAR3=0x%08x IOP3XX_IALR3=0x%08x IOP3XX_IATVR3=%08x\n",
+-			*IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3);
+ 
+ 	hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, "imprecise external abort");
+ }
+ 
++/* for platforms that might be host-bus-adapters */
++void __init iop3xx_pci_preinit_cond(void)
++{
++	if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) {
++		iop3xx_atu_disable();
++		iop3xx_atu_setup();
++		iop3xx_atu_debug();
++	}
++}
++
++void __init iop3xx_pci_preinit(void)
++{
++	iop3xx_atu_disable();
++	iop3xx_atu_setup();
++	iop3xx_atu_debug();
++}
++
+ /* allow init_atu to be user overridden */
+ static int __init iop3xx_init_atu_setup(char *str)
+ {
+diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
+index 03a65c0..bb6e127 100644
+--- a/arch/arm/plat-mxc/Kconfig
++++ b/arch/arm/plat-mxc/Kconfig
+@@ -4,7 +4,7 @@ menu "Freescale MXC Implementations"
+ 
+ choice
+ 	prompt "MXC/iMX System Type"
+-	default 0
++	default ARCH_MX3
+ 
+ config ARCH_MX3
+ 	bool "MX3-based"
+diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
+index 66ad9c2..f96dc03 100644
+--- a/arch/arm/plat-mxc/Makefile
++++ b/arch/arm/plat-mxc/Makefile
+@@ -4,7 +4,3 @@
+ 
+ # Common support
+ obj-y := irq.o
+-
+-obj-m :=
+-obj-n :=
+-obj-  :=
+diff --git a/arch/arm/plat-mxc/irq.c b/arch/arm/plat-mxc/irq.c
+index 87d253b..2ad5a69 100644
+--- a/arch/arm/plat-mxc/irq.c
++++ b/arch/arm/plat-mxc/irq.c
+@@ -19,21 +19,13 @@
+ #include <asm/mach/irq.h>
+ #include <asm/arch/common.h>
+ 
+-/*!
+- * Disable interrupt number "irq" in the AVIC
+- *
+- * @param  irq          interrupt source number
+- */
++/* Disable interrupt number "irq" in the AVIC */
+ static void mxc_mask_irq(unsigned int irq)
+ {
+ 	__raw_writel(irq, AVIC_INTDISNUM);
+ }
+ 
+-/*!
+- * Enable interrupt number "irq" in the AVIC
+- *
+- * @param  irq          interrupt source number
+- */
++/* Enable interrupt number "irq" in the AVIC */
+ static void mxc_unmask_irq(unsigned int irq)
+ {
+ 	__raw_writel(irq, AVIC_INTENNUM);
+@@ -45,7 +37,7 @@ static struct irq_chip mxc_avic_chip = {
+ 	.unmask = mxc_unmask_irq,
+ };
+ 
+-/*!
++/*
+  * This function initializes the AVIC hardware and disables all the
+  * interrupts. It registers the interrupt enable and disable functions
+  * to the kernel for each interrupt source.
+diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
+index 8f56c25..bc639a3 100644
+--- a/arch/arm/plat-omap/Makefile
++++ b/arch/arm/plat-omap/Makefile
+@@ -9,8 +9,6 @@ obj-m :=
+ obj-n :=
+ obj-  :=
+ 
+-obj-$(CONFIG_OMAP_32K_TIMER)	+= timer32k.o
+-
+ # OCPI interconnect support for 1710, 1610 and 5912
+ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
+ 
+diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
+index 0a60324..72d34a2 100644
+--- a/arch/arm/plat-omap/clock.c
++++ b/arch/arm/plat-omap/clock.c
+@@ -23,7 +23,6 @@
+ #include <linux/platform_device.h>
+ 
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ 
+ #include <asm/arch/clock.h>
+ 
+@@ -304,6 +303,23 @@ void propagate_rate(struct clk * tclk)
+ 	}
+ }
+ 
++/**
++ * recalculate_root_clocks - recalculate and propagate all root clocks
++ *
++ * Recalculates all root clocks (clocks with no parent), which if the
++ * clock's .recalc is set correctly, should also propagate their rates.
++ * Called at init.
++ */
++void recalculate_root_clocks(void)
++{
++	struct clk *clkp;
++
++	list_for_each_entry(clkp, &clocks, node) {
++		if (unlikely(!clkp->parent) && likely((u32)clkp->recalc))
++			clkp->recalc(clkp);
++	}
++}
++
+ int clk_register(struct clk *clk)
+ {
+ 	if (clk == NULL || IS_ERR(clk))
+@@ -358,6 +374,30 @@ void clk_allow_idle(struct clk *clk)
+ }
+ EXPORT_SYMBOL(clk_allow_idle);
+ 
++void clk_enable_init_clocks(void)
++{
++	struct clk *clkp;
++
++	list_for_each_entry(clkp, &clocks, node) {
++		if (clkp->flags & ENABLE_ON_INIT)
++			clk_enable(clkp);
++	}
++}
++EXPORT_SYMBOL(clk_enable_init_clocks);
++
++#ifdef CONFIG_CPU_FREQ
++void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&clockfw_lock, flags);
++	if (arch_clock->clk_init_cpufreq_table)
++		arch_clock->clk_init_cpufreq_table(table);
++	spin_unlock_irqrestore(&clockfw_lock, flags);
++}
++EXPORT_SYMBOL(clk_init_cpufreq_table);
++#endif
++
+ /*-------------------------------------------------------------------------*/
+ 
+ #ifdef CONFIG_OMAP_RESET_CLOCKS
+@@ -396,3 +436,4 @@ int __init clk_init(struct clk_functions * custom_clocks)
+ 
+ 	return 0;
+ }
++
+diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
+index 4f0f9c4..bd1cef2 100644
+--- a/arch/arm/plat-omap/common.c
++++ b/arch/arm/plat-omap/common.c
+@@ -27,11 +27,16 @@
+ #include <asm/setup.h>
+ 
+ #include <asm/arch/board.h>
++#include <asm/arch/control.h>
+ #include <asm/arch/mux.h>
+ #include <asm/arch/fpga.h>
+ 
+ #include <asm/arch/clock.h>
+ 
++#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
++# include "../mach-omap2/sdrc.h"
++#endif
++
+ #define NO_LENGTH_CHECK 0xffffffff
+ 
+ unsigned char omap_bootloader_tag[512];
+@@ -171,8 +176,8 @@ console_initcall(omap_add_serial_console);
+ 
+ #if defined(CONFIG_ARCH_OMAP16XX)
+ #define TIMER_32K_SYNCHRONIZED		0xfffbc410
+-#elif defined(CONFIG_ARCH_OMAP24XX)
+-#define TIMER_32K_SYNCHRONIZED		(OMAP24XX_32KSYNCT_BASE + 0x10)
++#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
++#define TIMER_32K_SYNCHRONIZED		(OMAP2_32KSYNCT_BASE + 0x10)
+ #endif
+ 
+ #ifdef	TIMER_32K_SYNCHRONIZED
+@@ -193,12 +198,35 @@ static struct clocksource clocksource_32k = {
+ 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+ };
+ 
++/*
++ * Rounds down to nearest nsec.
++ */
++unsigned long long omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
++{
++	return cyc2ns(&clocksource_32k, ticks_32k);
++}
++
++/*
++ * Returns current time from boot in nsecs. It's OK for this to wrap
++ * around for now, as it's just a relative time stamp.
++ */
++unsigned long long sched_clock(void)
++{
++	return omap_32k_ticks_to_nsecs(omap_32k_read());
++}
++
+ static int __init omap_init_clocksource_32k(void)
+ {
+ 	static char err[] __initdata = KERN_ERR
+ 			"%s: can't register clocksource!\n";
+ 
+-	if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
++	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
++		struct clk *sync_32k_ick;
++
++		sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
++		if (sync_32k_ick)
++			clk_enable(sync_32k_ick);
++
+ 		clocksource_32k.mult = clocksource_hz2mult(32768,
+ 					    clocksource_32k.shift);
+ 
+@@ -210,3 +238,33 @@ static int __init omap_init_clocksource_32k(void)
+ arch_initcall(omap_init_clocksource_32k);
+ 
+ #endif	/* TIMER_32K_SYNCHRONIZED */
++
++/* Global address base setup code */
++
++#if defined(CONFIG_ARCH_OMAP2420)
++void __init omap2_set_globals_242x(void)
++{
++	omap2_sdrc_base = OMAP2420_SDRC_BASE;
++	omap2_sms_base = OMAP2420_SMS_BASE;
++	omap_ctrl_base_set(OMAP2420_CTRL_BASE);
++}
++#endif
++
++#if defined(CONFIG_ARCH_OMAP2430)
++void __init omap2_set_globals_243x(void)
++{
++	omap2_sdrc_base = OMAP243X_SDRC_BASE;
++	omap2_sms_base = OMAP243X_SMS_BASE;
++	omap_ctrl_base_set(OMAP243X_CTRL_BASE);
++}
++#endif
++
++#if defined(CONFIG_ARCH_OMAP3430)
++void __init omap2_set_globals_343x(void)
++{
++	omap2_sdrc_base = OMAP343X_SDRC_BASE;
++	omap2_sms_base = OMAP343X_SMS_BASE;
++	omap_ctrl_base_set(OMAP343X_CTRL_BASE);
++}
++#endif
++
+diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
+index 8c78e4e..1903a34 100644
+--- a/arch/arm/plat-omap/gpio.c
++++ b/arch/arm/plat-omap/gpio.c
+@@ -136,7 +136,6 @@ struct gpio_bank {
+ 	u16 irq;
+ 	u16 virtual_irq_start;
+ 	int method;
+-	u32 reserved_map;
+ #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+ 	u32 suspend_wakeup;
+ 	u32 saved_wakeup;
+@@ -149,7 +148,9 @@ struct gpio_bank {
+ 	u32 saved_fallingdetect;
+ 	u32 saved_risingdetect;
+ #endif
++	u32 level_mask;
+ 	spinlock_t lock;
++	struct gpio_chip chip;
+ };
+ 
+ #define METHOD_MPUIO		0
+@@ -538,10 +539,9 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
+ 			bank->enabled_non_wakeup_gpios &= ~gpio_bit;
+ 	}
+ 
+-	/*
+-	 * FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only
+-	 * level triggering requested.
+-	 */
++	bank->level_mask =
++		__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) |
++		__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+ }
+ #endif
+ 
+@@ -652,6 +652,12 @@ static int gpio_irq_type(unsigned irq, unsigned type)
+ 		irq_desc[irq].status |= type;
+ 	}
+ 	spin_unlock_irqrestore(&bank->lock, flags);
++
++	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
++		__set_irq_handler_unlocked(irq, handle_level_irq);
++	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
++		__set_irq_handler_unlocked(irq, handle_edge_irq);
++
+ 	return retval;
+ }
+ 
+@@ -903,19 +909,17 @@ int omap_request_gpio(int gpio)
+ {
+ 	struct gpio_bank *bank;
+ 	unsigned long flags;
++	int status;
+ 
+ 	if (check_gpio(gpio) < 0)
+ 		return -EINVAL;
+ 
++	status = gpio_request(gpio, NULL);
++	if (status < 0)
++		return status;
++
+ 	bank = get_gpio_bank(gpio);
+ 	spin_lock_irqsave(&bank->lock, flags);
+-	if (unlikely(bank->reserved_map & (1 << get_gpio_index(gpio)))) {
+-		printk(KERN_ERR "omap-gpio: GPIO %d is already reserved!\n", gpio);
+-		dump_stack();
+-		spin_unlock_irqrestore(&bank->lock, flags);
+-		return -1;
+-	}
+-	bank->reserved_map |= (1 << get_gpio_index(gpio));
+ 
+ 	/* Set trigger to none. You need to enable the desired trigger with
+ 	 * request_irq() or set_irq_type().
+@@ -945,10 +949,11 @@ void omap_free_gpio(int gpio)
+ 		return;
+ 	bank = get_gpio_bank(gpio);
+ 	spin_lock_irqsave(&bank->lock, flags);
+-	if (unlikely(!(bank->reserved_map & (1 << get_gpio_index(gpio))))) {
++	if (unlikely(!gpiochip_is_requested(&bank->chip,
++				get_gpio_index(gpio)))) {
++		spin_unlock_irqrestore(&bank->lock, flags);
+ 		printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio);
+ 		dump_stack();
+-		spin_unlock_irqrestore(&bank->lock, flags);
+ 		return;
+ 	}
+ #ifdef CONFIG_ARCH_OMAP16XX
+@@ -965,9 +970,9 @@ void omap_free_gpio(int gpio)
+ 		__raw_writel(1 << get_gpio_index(gpio), reg);
+ 	}
+ #endif
+-	bank->reserved_map &= ~(1 << get_gpio_index(gpio));
+ 	_reset_gpio(bank, gpio);
+ 	spin_unlock_irqrestore(&bank->lock, flags);
++	gpio_free(gpio);
+ }
+ 
+ /*
+@@ -1022,12 +1027,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+ 			isr &= 0x0000ffff;
+ 
+ 		if (cpu_class_is_omap2()) {
+-			level_mask =
+-				__raw_readl(bank->base +
+-					OMAP24XX_GPIO_LEVELDETECT0) |
+-				__raw_readl(bank->base +
+-					OMAP24XX_GPIO_LEVELDETECT1);
+-			level_mask &= enabled;
++			level_mask = bank->level_mask & enabled;
+ 		}
+ 
+ 		/* clear edge sensitive interrupts before handler(s) are
+@@ -1052,51 +1052,13 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+ 		gpio_irq = bank->virtual_irq_start;
+ 		for (; isr != 0; isr >>= 1, gpio_irq++) {
+ 			struct irq_desc *d;
+-			int irq_mask;
++
+ 			if (!(isr & 1))
+ 				continue;
+ 			d = irq_desc + gpio_irq;
+-			/* Don't run the handler if it's already running
+-			 * or was disabled lazely.
+-			 */
+-			if (unlikely((d->depth ||
+-				      (d->status & IRQ_INPROGRESS)))) {
+-				irq_mask = 1 <<
+-					(gpio_irq - bank->virtual_irq_start);
+-				/* The unmasking will be done by
+-				 * enable_irq in case it is disabled or
+-				 * after returning from the handler if
+-				 * it's already running.
+-				 */
+-				_enable_gpio_irqbank(bank, irq_mask, 0);
+-				if (!d->depth) {
+-					/* Level triggered interrupts
+-					 * won't ever be reentered
+-					 */
+-					BUG_ON(level_mask & irq_mask);
+-					d->status |= IRQ_PENDING;
+-				}
+-				continue;
+-			}
+ 
+ 			desc_handle_irq(gpio_irq, d);
+-
+-			if (unlikely((d->status & IRQ_PENDING) && !d->depth)) {
+-				irq_mask = 1 <<
+-					(gpio_irq - bank->virtual_irq_start);
+-				d->status &= ~IRQ_PENDING;
+-				_enable_gpio_irqbank(bank, irq_mask, 1);
+-				retrigger |= irq_mask;
+-			}
+ 		}
+-
+-		if (cpu_class_is_omap2()) {
+-			/* clear level sensitive interrupts after handler(s) */
+-			_enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
+-			_clear_gpio_irqbank(bank, isr_saved & level_mask);
+-			_enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
+-		}
+-
+ 	}
+ 	/* if bank has any level sensitive GPIO pin interrupt
+ 	configured, we must unmask the bank interrupt only after
+@@ -1135,6 +1097,14 @@ static void gpio_unmask_irq(unsigned int irq)
+ {
+ 	unsigned int gpio = irq - IH_GPIO_BASE;
+ 	struct gpio_bank *bank = get_irq_chip_data(irq);
++	unsigned int irq_mask = 1 << get_gpio_index(gpio);
++
++	/* For level-triggered GPIOs, the clearing must be done after
++	 * the HW source is cleared, thus after the handler has run */
++	if (bank->level_mask & irq_mask) {
++		_set_gpio_irqenable(bank, gpio, 0);
++		_clear_gpio_irqstatus(bank, gpio);
++	}
+ 
+ 	_set_gpio_irqenable(bank, gpio, 1);
+ }
+@@ -1266,6 +1236,53 @@ static inline void mpuio_init(void) {}
+ 
+ /*---------------------------------------------------------------------*/
+ 
++/* REVISIT these are stupid implementations!  replace by ones that
++ * don't switch on METHOD_* and which mostly avoid spinlocks
++ */
++
++static int gpio_input(struct gpio_chip *chip, unsigned offset)
++{
++	struct gpio_bank *bank;
++	unsigned long flags;
++
++	bank = container_of(chip, struct gpio_bank, chip);
++	spin_lock_irqsave(&bank->lock, flags);
++	_set_gpio_direction(bank, offset, 1);
++	spin_unlock_irqrestore(&bank->lock, flags);
++	return 0;
++}
++
++static int gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++	return omap_get_gpio_datain(chip->base + offset);
++}
++
++static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
++{
++	struct gpio_bank *bank;
++	unsigned long flags;
++
++	bank = container_of(chip, struct gpio_bank, chip);
++	spin_lock_irqsave(&bank->lock, flags);
++	_set_gpio_dataout(bank, offset, value);
++	_set_gpio_direction(bank, offset, 0);
++	spin_unlock_irqrestore(&bank->lock, flags);
++	return 0;
++}
++
++static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++	struct gpio_bank *bank;
++	unsigned long flags;
++
++	bank = container_of(chip, struct gpio_bank, chip);
++	spin_lock_irqsave(&bank->lock, flags);
++	_set_gpio_dataout(bank, offset, value);
++	spin_unlock_irqrestore(&bank->lock, flags);
++}
++
++/*---------------------------------------------------------------------*/
++
+ static int initialized;
+ #if !defined(CONFIG_ARCH_OMAP3)
+ static struct clk * gpio_ick;
+@@ -1293,6 +1310,7 @@ static struct lock_class_key gpio_lock_class;
+ static int __init _omap_gpio_init(void)
+ {
+ 	int i;
++	int gpio = 0;
+ 	struct gpio_bank *bank;
+ #if defined(CONFIG_ARCH_OMAP3)
+ 	char clk_name[11];
+@@ -1423,7 +1441,6 @@ static int __init _omap_gpio_init(void)
+ 		int j, gpio_count = 16;
+ 
+ 		bank = &gpio_bank[i];
+-		bank->reserved_map = 0;
+ 		bank->base = IO_ADDRESS(bank->base);
+ 		spin_lock_init(&bank->lock);
+ 		if (bank_is_mpuio(bank))
+@@ -1461,6 +1478,26 @@ static int __init _omap_gpio_init(void)
+ 			gpio_count = 32;
+ 		}
+ #endif
++
++		/* REVISIT eventually switch from OMAP-specific gpio structs
++		 * over to the generic ones
++		 */
++		bank->chip.direction_input = gpio_input;
++		bank->chip.get = gpio_get;
++		bank->chip.direction_output = gpio_output;
++		bank->chip.set = gpio_set;
++		if (bank_is_mpuio(bank)) {
++			bank->chip.label = "mpuio";
++			bank->chip.base = OMAP_MPUIO(0);
++		} else {
++			bank->chip.label = "gpio";
++			bank->chip.base = gpio;
++			gpio += gpio_count;
++		}
++		bank->chip.ngpio = gpio_count;
++
++		gpiochip_add(&bank->chip);
++
+ 		for (j = bank->virtual_irq_start;
+ 		     j < bank->virtual_irq_start + gpio_count; j++) {
+ 			lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class);
+@@ -1757,8 +1794,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
+ 
+ 		for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
+ 			unsigned	irq, value, is_in, irqstat;
++			const char	*label;
+ 
+-			if (!(bank->reserved_map & mask))
++			label = gpiochip_is_requested(&bank->chip, j);
++			if (!label)
+ 				continue;
+ 
+ 			irq = bank->virtual_irq_start + j;
+@@ -1766,13 +1805,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
+ 			is_in = gpio_is_input(bank, mask);
+ 
+ 			if (bank_is_mpuio(bank))
+-				seq_printf(s, "MPUIO %2d: ", j);
++				seq_printf(s, "MPUIO %2d ", j);
+ 			else
+-				seq_printf(s, "GPIO %3d: ", gpio);
+-			seq_printf(s, "%s %s",
++				seq_printf(s, "GPIO %3d ", gpio);
++			seq_printf(s, "(%10s): %s %s",
++					label,
+ 					is_in ? "in " : "out",
+ 					value ? "hi"  : "lo");
+ 
++/* FIXME for at least omap2, show pullup/pulldown state */
++
+ 			irqstat = irq_desc[irq].status;
+ 			if (is_in && ((bank->suspend_wakeup & mask)
+ 					|| irqstat & IRQ_TYPE_SENSE_MASK)) {
+@@ -1795,10 +1837,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
+ 					trigger = "high";
+ 					break;
+ 				case IRQ_TYPE_NONE:
+-					trigger = "(unspecified)";
++					trigger = "(?)";
+ 					break;
+ 				}
+-				seq_printf(s, ", irq-%d %s%s",
++				seq_printf(s, ", irq-%d %-8s%s",
+ 						irq, trigger,
+ 						(bank->suspend_wakeup & mask)
+ 							? " wakeup" : "");
+diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c
+index 75211f2..6f3f459 100644
+--- a/arch/arm/plat-omap/mux.c
++++ b/arch/arm/plat-omap/mux.c
+@@ -3,9 +3,9 @@
+  *
+  * Utility to set the Omap MUX and PULL_DWN registers from a table in mux.h
+  *
+- * Copyright (C) 2003 - 2005 Nokia Corporation
++ * Copyright (C) 2003 - 2008 Nokia Corporation
+  *
+- * Written by Tony Lindgren <tony.lindgren at nokia.com>
++ * Written by Tony Lindgren
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -32,21 +32,17 @@
+ 
+ #ifdef CONFIG_OMAP_MUX
+ 
+-#define OMAP24XX_L4_BASE	0x48000000
+-#define OMAP24XX_PULL_ENA	(1 << 3)
+-#define OMAP24XX_PULL_UP	(1 << 4)
++static struct omap_mux_cfg *mux_cfg;
+ 
+-static struct pin_config * pin_table;
+-static unsigned long pin_table_sz;
+-
+-extern struct pin_config * omap730_pins;
+-extern struct pin_config * omap1xxx_pins;
+-extern struct pin_config * omap24xx_pins;
+-
+-int __init omap_mux_register(struct pin_config * pins, unsigned long size)
++int __init omap_mux_register(struct omap_mux_cfg *arch_mux_cfg)
+ {
+-	pin_table = pins;
+-	pin_table_sz = size;
++	if (!arch_mux_cfg || !arch_mux_cfg->pins || arch_mux_cfg->size == 0
++			|| !arch_mux_cfg->cfg_reg) {
++		printk(KERN_ERR "Invalid pin table\n");
++		return -EINVAL;
++	}
++
++	mux_cfg = arch_mux_cfg;
+ 
+ 	return 0;
+ }
+@@ -56,152 +52,26 @@ int __init omap_mux_register(struct pin_config * pins, unsigned long size)
+  */
+ int __init_or_module omap_cfg_reg(const unsigned long index)
+ {
+-	static DEFINE_SPINLOCK(mux_spin_lock);
+-
+-	unsigned long flags;
+-	struct pin_config *cfg;
+-	unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
+-		pull_orig = 0, pull = 0;
+-	unsigned int mask, warn = 0;
++	struct pin_config *reg;
+ 
+-	if (!pin_table)
+-		BUG();
++	if (mux_cfg == NULL) {
++		printk(KERN_ERR "Pin mux table not initialized\n");
++		return -ENODEV;
++	}
+ 
+-	if (index >= pin_table_sz) {
++	if (index >= mux_cfg->size) {
+ 		printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
+-		       index, pin_table_sz);
++		       index, mux_cfg->size);
+ 		dump_stack();
+ 		return -ENODEV;
+ 	}
+ 
+-	cfg = (struct pin_config *)&pin_table[index];
+-	if (cpu_is_omap24xx()) {
+-		u8 reg = 0;
+-
+-		reg |= cfg->mask & 0x7;
+-		if (cfg->pull_val)
+-			reg |= OMAP24XX_PULL_ENA;
+-		if(cfg->pu_pd_val)
+-			reg |= OMAP24XX_PULL_UP;
+-#if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
+-		{
+-			u8 orig = omap_readb(OMAP24XX_L4_BASE + cfg->mux_reg);
+-			u8 debug = 0;
+-
+-#ifdef	CONFIG_OMAP_MUX_DEBUG
+-			debug = cfg->debug;
+-#endif
+-			warn = (orig != reg);
+-			if (debug || warn)
+-				printk("MUX: setup %s (0x%08x): 0x%02x -> 0x%02x\n",
+-						cfg->name,
+-						OMAP24XX_L4_BASE + cfg->mux_reg,
+-						orig, reg);
+-		}
+-#endif
+-		omap_writeb(reg, OMAP24XX_L4_BASE + cfg->mux_reg);
++	reg = (struct pin_config *)&mux_cfg->pins[index];
+ 
+-		return 0;
+-	}
+-
+-	/* Check the mux register in question */
+-	if (cfg->mux_reg) {
+-		unsigned	tmp1, tmp2;
+-
+-		spin_lock_irqsave(&mux_spin_lock, flags);
+-		reg_orig = omap_readl(cfg->mux_reg);
+-
+-		/* The mux registers always seem to be 3 bits long */
+-		mask = (0x7 << cfg->mask_offset);
+-		tmp1 = reg_orig & mask;
+-		reg = reg_orig & ~mask;
+-
+-		tmp2 = (cfg->mask << cfg->mask_offset);
+-		reg |= tmp2;
+-
+-		if (tmp1 != tmp2)
+-			warn = 1;
+-
+-		omap_writel(reg, cfg->mux_reg);
+-		spin_unlock_irqrestore(&mux_spin_lock, flags);
+-	}
+-
+-	/* Check for pull up or pull down selection on 1610 */
+-	if (!cpu_is_omap15xx()) {
+-		if (cfg->pu_pd_reg && cfg->pull_val) {
+-			spin_lock_irqsave(&mux_spin_lock, flags);
+-			pu_pd_orig = omap_readl(cfg->pu_pd_reg);
+-			mask = 1 << cfg->pull_bit;
+-
+-			if (cfg->pu_pd_val) {
+-				if (!(pu_pd_orig & mask))
+-					warn = 1;
+-				/* Use pull up */
+-				pu_pd = pu_pd_orig | mask;
+-			} else {
+-				if (pu_pd_orig & mask)
+-					warn = 1;
+-				/* Use pull down */
+-				pu_pd = pu_pd_orig & ~mask;
+-			}
+-			omap_writel(pu_pd, cfg->pu_pd_reg);
+-			spin_unlock_irqrestore(&mux_spin_lock, flags);
+-		}
+-	}
+-
+-	/* Check for an associated pull down register */
+-	if (cfg->pull_reg) {
+-		spin_lock_irqsave(&mux_spin_lock, flags);
+-		pull_orig = omap_readl(cfg->pull_reg);
+-		mask = 1 << cfg->pull_bit;
+-
+-		if (cfg->pull_val) {
+-			if (pull_orig & mask)
+-				warn = 1;
+-			/* Low bit = pull enabled */
+-			pull = pull_orig & ~mask;
+-		} else {
+-			if (!(pull_orig & mask))
+-				warn = 1;
+-			/* High bit = pull disabled */
+-			pull = pull_orig | mask;
+-		}
+-
+-		omap_writel(pull, cfg->pull_reg);
+-		spin_unlock_irqrestore(&mux_spin_lock, flags);
+-	}
+-
+-	if (warn) {
+-#ifdef CONFIG_OMAP_MUX_WARNINGS
+-		printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
+-#endif
+-	}
+-
+-#ifdef CONFIG_OMAP_MUX_DEBUG
+-	if (cfg->debug || warn) {
+-		printk("MUX: Setting register %s\n", cfg->name);
+-		printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
+-		       cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
+-
+-		if (!cpu_is_omap15xx()) {
+-			if (cfg->pu_pd_reg && cfg->pull_val) {
+-				printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
+-				       cfg->pu_pd_name, cfg->pu_pd_reg,
+-				       pu_pd_orig, pu_pd);
+-			}
+-		}
+-
+-		if (cfg->pull_reg)
+-			printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
+-			       cfg->pull_name, cfg->pull_reg, pull_orig, pull);
+-	}
+-#endif
++	if (!mux_cfg->cfg_reg)
++		return -ENODEV;
+ 
+-#ifdef CONFIG_OMAP_MUX_ERRORS
+-	return warn ? -ETXTBSY : 0;
+-#else
+-	return 0;
+-#endif
++	return mux_cfg->cfg_reg(reg);
+ }
+ EXPORT_SYMBOL(omap_cfg_reg);
+ #else
+diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
+deleted file mode 100644
+index ea76f19..0000000
+--- a/arch/arm/plat-omap/timer32k.c
++++ /dev/null
+@@ -1,269 +0,0 @@
+-/*
+- * linux/arch/arm/plat-omap/timer32k.c
+- *
+- * OMAP 32K Timer
+- *
+- * Copyright (C) 2004 - 2005 Nokia Corporation
+- * Partial timer rewrite and additional dynamic tick timer support by
+- * Tony Lindgen <tony at atomide.com> and
+- * Tuukka Tikkanen <tuukka.tikkanen at elektrobit.com>
+- * OMAP Dual-mode timer framework support by Timo Teras
+- *
+- * MPU timer code based on the older MPU timer code for OMAP
+- * Copyright (C) 2000 RidgeRun, Inc.
+- * Author: Greg Lonnon <glonnon at ridgerun.com>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- * You should have received a copy of the  GNU General Public License along
+- * with this program; if not, write  to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/interrupt.h>
+-#include <linux/sched.h>
+-#include <linux/spinlock.h>
+-#include <linux/err.h>
+-#include <linux/clk.h>
+-#include <linux/clocksource.h>
+-#include <linux/clockchips.h>
+-
+-#include <asm/system.h>
+-#include <asm/hardware.h>
+-#include <asm/io.h>
+-#include <asm/leds.h>
+-#include <asm/irq.h>
+-#include <asm/mach/irq.h>
+-#include <asm/mach/time.h>
+-#include <asm/arch/dmtimer.h>
+-
+-struct sys_timer omap_timer;
+-
+-/*
+- * ---------------------------------------------------------------------------
+- * 32KHz OS timer
+- *
+- * This currently works only on 16xx, as 1510 does not have the continuous
+- * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
+- * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
+- * on 1510 would be possible, but the timer would not be as accurate as
+- * with the 32KHz synchronized timer.
+- * ---------------------------------------------------------------------------
+- */
+-
+-#if defined(CONFIG_ARCH_OMAP16XX)
+-#define TIMER_32K_SYNCHRONIZED		0xfffbc410
+-#elif defined(CONFIG_ARCH_OMAP24XX)
+-#define TIMER_32K_SYNCHRONIZED		(OMAP24XX_32KSYNCT_BASE + 0x10)
+-#else
+-#error OMAP 32KHz timer does not currently work on 15XX!
+-#endif
+-
+-/* 16xx specific defines */
+-#define OMAP1_32K_TIMER_BASE		0xfffb9000
+-#define OMAP1_32K_TIMER_CR		0x08
+-#define OMAP1_32K_TIMER_TVR		0x00
+-#define OMAP1_32K_TIMER_TCR		0x04
+-
+-#define OMAP_32K_TICKS_PER_SEC		(32768)
+-
+-/*
+- * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+- * so with HZ = 128, TVR = 255.
+- */
+-#define OMAP_32K_TIMER_TICK_PERIOD	((OMAP_32K_TICKS_PER_SEC / HZ) - 1)
+-
+-#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)			\
+-				(((nr_jiffies) * (clock_rate)) / HZ)
+-
+-#if defined(CONFIG_ARCH_OMAP1)
+-
+-static inline void omap_32k_timer_write(int val, int reg)
+-{
+-	omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
+-}
+-
+-static inline unsigned long omap_32k_timer_read(int reg)
+-{
+-	return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
+-}
+-
+-static inline void omap_32k_timer_start(unsigned long load_val)
+-{
+-	if (!load_val)
+-		load_val = 1;
+-	omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
+-	omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
+-}
+-
+-static inline void omap_32k_timer_stop(void)
+-{
+-	omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
+-}
+-
+-#define omap_32k_timer_ack_irq()
+-
+-#elif defined(CONFIG_ARCH_OMAP2)
+-
+-static struct omap_dm_timer *gptimer;
+-
+-static inline void omap_32k_timer_start(unsigned long load_val)
+-{
+-	omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val);
+-	omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
+-	omap_dm_timer_start(gptimer);
+-}
+-
+-static inline void omap_32k_timer_stop(void)
+-{
+-	omap_dm_timer_stop(gptimer);
+-}
+-
+-static inline void omap_32k_timer_ack_irq(void)
+-{
+-	u32 status = omap_dm_timer_read_status(gptimer);
+-	omap_dm_timer_write_status(gptimer, status);
+-}
+-
+-#endif
+-
+-static void omap_32k_timer_set_mode(enum clock_event_mode mode,
+-				    struct clock_event_device *evt)
+-{
+-	omap_32k_timer_stop();
+-
+-	switch (mode) {
+-	case CLOCK_EVT_MODE_PERIODIC:
+-		omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+-		break;
+-	case CLOCK_EVT_MODE_ONESHOT:
+-	case CLOCK_EVT_MODE_UNUSED:
+-	case CLOCK_EVT_MODE_SHUTDOWN:
+-		break;
+-	case CLOCK_EVT_MODE_RESUME:
+-		break;
+-	}
+-}
+-
+-static struct clock_event_device clockevent_32k_timer = {
+-	.name		= "32k-timer",
+-	.features       = CLOCK_EVT_FEAT_PERIODIC,
+-	.shift		= 32,
+-	.set_mode	= omap_32k_timer_set_mode,
+-};
+-
+-/*
+- * The 32KHz synchronized timer is an additional timer on 16xx.
+- * It is always running.
+- */
+-static inline unsigned long omap_32k_sync_timer_read(void)
+-{
+-	return omap_readl(TIMER_32K_SYNCHRONIZED);
+-}
+-
+-/*
+- * Rounds down to nearest usec. Note that this will overflow for larger values.
+- */
+-static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
+-{
+-	return (ticks_32k * 5*5*5*5*5*5) >> 9;
+-}
+-
+-/*
+- * Rounds down to nearest nsec.
+- */
+-static inline unsigned long long
+-omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
+-{
+-	return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
+-}
+-
+-/*
+- * Returns current time from boot in nsecs. It's OK for this to wrap
+- * around for now, as it's just a relative time stamp.
+- */
+-unsigned long long sched_clock(void)
+-{
+-	return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
+-}
+-
+-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
+-{
+-	struct clock_event_device *evt = &clockevent_32k_timer;
+-	omap_32k_timer_ack_irq();
+-
+-	evt->event_handler(evt);
+-
+-	return IRQ_HANDLED;
+-}
+-
+-static struct irqaction omap_32k_timer_irq = {
+-	.name		= "32KHz timer",
+-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+-	.handler	= omap_32k_timer_interrupt,
+-};
+-
+-static __init void omap_init_32k_timer(void)
+-{
+-	if (cpu_class_is_omap1())
+-		setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+-
+-#ifdef CONFIG_ARCH_OMAP2
+-	/* REVISIT: Check 24xx TIOCP_CFG settings after idle works */
+-	if (cpu_is_omap24xx()) {
+-		gptimer = omap_dm_timer_request_specific(1);
+-		BUG_ON(gptimer == NULL);
+-
+-		omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ);
+-		setup_irq(omap_dm_timer_get_irq(gptimer), &omap_32k_timer_irq);
+-		omap_dm_timer_set_int_enable(gptimer,
+-			OMAP_TIMER_INT_CAPTURE | OMAP_TIMER_INT_OVERFLOW |
+-			OMAP_TIMER_INT_MATCH);
+-	}
+-#endif
+-
+-	clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC,
+-					   NSEC_PER_SEC,
+-					   clockevent_32k_timer.shift);
+-	clockevent_32k_timer.max_delta_ns =
+-		clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer);
+-	clockevent_32k_timer.min_delta_ns =
+-		clockevent_delta2ns(1, &clockevent_32k_timer);
+-
+-	clockevent_32k_timer.cpumask = cpumask_of_cpu(0);
+-	clockevents_register_device(&clockevent_32k_timer);
+-}
+-
+-/*
+- * ---------------------------------------------------------------------------
+- * Timer initialization
+- * ---------------------------------------------------------------------------
+- */
+-static void __init omap_timer_init(void)
+-{
+-#ifdef CONFIG_OMAP_DM_TIMER
+-	omap_dm_timer_init();
+-#endif
+-	omap_init_32k_timer();
+-}
+-
+-struct sys_timer omap_timer = {
+-	.init		= omap_timer_init,
+-};
+diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
+index a5aedf9..a619475 100644
+--- a/arch/arm/plat-omap/usb.c
++++ b/arch/arm/plat-omap/usb.c
+@@ -33,6 +33,7 @@
+ #include <asm/system.h>
+ #include <asm/hardware.h>
+ 
++#include <asm/arch/control.h>
+ #include <asm/arch/mux.h>
+ #include <asm/arch/usb.h>
+ #include <asm/arch/board.h>
+@@ -76,7 +77,7 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#ifdef	CONFIG_ARCH_OMAP_OTG
++#if	defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_USB_MUSB_OTG)
+ 
+ static struct otg_transceiver *xceiv;
+ 
+@@ -110,12 +111,48 @@ EXPORT_SYMBOL(otg_set_transceiver);
+ 
+ #if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP15XX)
+ 
++static void omap2_usb_devconf_clear(u8 port, u32 mask)
++{
++	u32 r;
++
++	r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++	r &= ~USBTXWRMODEI(port, mask);
++	omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
++}
++
++static void omap2_usb_devconf_set(u8 port, u32 mask)
++{
++	u32 r;
++
++	r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++	r |= USBTXWRMODEI(port, mask);
++	omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
++}
++
++static void omap2_usb2_disable_5pinbitll(void)
++{
++	u32 r;
++
++	r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++	r &= ~(USBTXWRMODEI(2, USB_BIDIR_TLL) | USBT2TLL5PI);
++	omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
++}
++
++static void omap2_usb2_enable_5pinunitll(void)
++{
++	u32 r;
++
++	r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++	r |= USBTXWRMODEI(2, USB_UNIDIR_TLL) | USBT2TLL5PI;
++	omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
++}
++
+ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
+ {
+ 	u32	syscon1 = 0;
+ 
+ 	if (cpu_is_omap24xx())
+-		CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL);
++		omap2_usb_devconf_clear(0, USB_BIDIR_TLL);
+ 
+ 	if (nwires == 0) {
+ 		if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
+@@ -187,19 +224,19 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
+ 	case 3:
+ 		syscon1 = 2;
+ 		if (cpu_is_omap24xx())
+-			CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
++			omap2_usb_devconf_set(0, USB_BIDIR);
+ 		break;
+ 	case 4:
+ 		syscon1 = 1;
+ 		if (cpu_is_omap24xx())
+-			CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
++			omap2_usb_devconf_set(0, USB_BIDIR);
+ 		break;
+ 	case 6:
+ 		syscon1 = 3;
+ 		if (cpu_is_omap24xx()) {
+ 			omap_cfg_reg(J19_24XX_USB0_VP);
+ 			omap_cfg_reg(K20_24XX_USB0_VM);
+-			CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR);
++			omap2_usb_devconf_set(0, USB_UNIDIR);
+ 		} else {
+ 			omap_cfg_reg(AA9_USB0_VP);
+ 			omap_cfg_reg(R9_USB0_VM);
+@@ -220,7 +257,7 @@ static u32 __init omap_usb1_init(unsigned nwires)
+ 	if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6)
+ 		USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
+ 	if (cpu_is_omap24xx())
+-		CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL);
++		omap2_usb_devconf_clear(1, USB_BIDIR_TLL);
+ 
+ 	if (nwires == 0)
+ 		return 0;
+@@ -261,17 +298,17 @@ static u32 __init omap_usb1_init(unsigned nwires)
+ 		 * this TLL link is not using DP/DM
+ 		 */
+ 		syscon1 = 1;
+-		CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL);
++		omap2_usb_devconf_set(1, USB_BIDIR_TLL);
+ 		break;
+ 	case 3:
+ 		syscon1 = 2;
+ 		if (cpu_is_omap24xx())
+-			CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
++			omap2_usb_devconf_set(1, USB_BIDIR);
+ 		break;
+ 	case 4:
+ 		syscon1 = 1;
+ 		if (cpu_is_omap24xx())
+-			CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
++			omap2_usb_devconf_set(1, USB_BIDIR);
+ 		break;
+ 	case 6:
+ 		if (cpu_is_omap24xx())
+@@ -295,8 +332,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
+ 	u32	syscon1 = 0;
+ 
+ 	if (cpu_is_omap24xx()) {
+-		CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL)
+-					| USBT2TLL5PI);
++		omap2_usb2_disable_5pinbitll();
+ 		alt_pingroup = 0;
+ 	}
+ 
+@@ -343,17 +379,17 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
+ 		 * this TLL link is not using DP/DM
+ 		 */
+ 		syscon1 = 1;
+-		CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL);
++		omap2_usb_devconf_set(2, USB_BIDIR_TLL);
+ 		break;
+ 	case 3:
+ 		syscon1 = 2;
+ 		if (cpu_is_omap24xx())
+-			CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
++			omap2_usb_devconf_set(2, USB_BIDIR);
+ 		break;
+ 	case 4:
+ 		syscon1 = 1;
+ 		if (cpu_is_omap24xx())
+-			CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
++			omap2_usb_devconf_set(2, USB_BIDIR);
+ 		break;
+ 	case 5:
+ 		if (!cpu_is_omap24xx())
+@@ -364,8 +400,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
+ 		 * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED}
+ 		 */
+ 		syscon1 = 3;
+-		CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL)
+-					| USBT2TLL5PI;
++		omap2_usb2_enable_5pinunitll();
+ 		break;
+ 	case 6:
+ 		if (cpu_is_omap24xx())
+diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile
+new file mode 100644
+index 0000000..198f3dd
+--- /dev/null
++++ b/arch/arm/plat-orion/Makefile
+@@ -0,0 +1,8 @@
++#
++# Makefile for the linux kernel.
++#
++
++obj-y	:= irq.o pcie.o time.o
++obj-m	:=
++obj-n	:=
++obj-	:=
+diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c
+new file mode 100644
+index 0000000..c5b669d
+--- /dev/null
++++ b/arch/arm/plat-orion/irq.c
+@@ -0,0 +1,64 @@
++/*
++ * arch/arm/plat-orion/irq.c
++ *
++ * Marvell Orion SoC IRQ handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <asm/plat-orion/irq.h>
++
++static void orion_irq_mask(u32 irq)
++{
++	void __iomem *maskaddr = get_irq_chip_data(irq);
++	u32 mask;
++
++	mask = readl(maskaddr);
++	mask &= ~(1 << (irq & 31));
++	writel(mask, maskaddr);
++}
++
++static void orion_irq_unmask(u32 irq)
++{
++	void __iomem *maskaddr = get_irq_chip_data(irq);
++	u32 mask;
++
++	mask = readl(maskaddr);
++	mask |= 1 << (irq & 31);
++	writel(mask, maskaddr);
++}
++
++static struct irq_chip orion_irq_chip = {
++	.name		= "orion_irq",
++	.ack		= orion_irq_mask,
++	.mask		= orion_irq_mask,
++	.unmask		= orion_irq_unmask,
++};
++
++void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
++{
++	unsigned int i;
++
++	/*
++	 * Mask all interrupts initially.
++	 */
++	writel(0, maskaddr);
++
++	/*
++	 * Register IRQ sources.
++	 */
++	for (i = 0; i < 32; i++) {
++		unsigned int irq = irq_start + i;
++
++		set_irq_chip(irq, &orion_irq_chip);
++		set_irq_chip_data(irq, maskaddr);
++		set_irq_handler(irq, handle_level_irq);
++		set_irq_flags(irq, IRQF_VALID);
++	}
++}
+diff --git a/arch/arm/plat-orion/pcie.c b/arch/arm/plat-orion/pcie.c
+new file mode 100644
+index 0000000..abfda53
+--- /dev/null
++++ b/arch/arm/plat-orion/pcie.c
+@@ -0,0 +1,245 @@
++/*
++ * arch/arm/plat-orion/pcie.c
++ *
++ * Marvell Orion SoC PCIe handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/mbus.h>
++#include <asm/mach/pci.h>
++#include <asm/plat-orion/pcie.h>
++
++/*
++ * PCIe unit register offsets.
++ */
++#define PCIE_DEV_ID_OFF		0x0000
++#define PCIE_CMD_OFF		0x0004
++#define PCIE_DEV_REV_OFF	0x0008
++#define PCIE_BAR_LO_OFF(n)	(0x0010 + ((n) << 3))
++#define PCIE_BAR_HI_OFF(n)	(0x0014 + ((n) << 3))
++#define PCIE_HEADER_LOG_4_OFF	0x0128
++#define PCIE_BAR_CTRL_OFF(n)	(0x1804 + ((n - 1) * 4))
++#define PCIE_WIN04_CTRL_OFF(n)	(0x1820 + ((n) << 4))
++#define PCIE_WIN04_BASE_OFF(n)	(0x1824 + ((n) << 4))
++#define PCIE_WIN04_REMAP_OFF(n)	(0x182c + ((n) << 4))
++#define PCIE_WIN5_CTRL_OFF	0x1880
++#define PCIE_WIN5_BASE_OFF	0x1884
++#define PCIE_WIN5_REMAP_OFF	0x188c
++#define PCIE_CONF_ADDR_OFF	0x18f8
++#define  PCIE_CONF_ADDR_EN		0x80000000
++#define  PCIE_CONF_REG(r)		((((r) & 0xf00) << 16) | ((r) & 0xfc))
++#define  PCIE_CONF_BUS(b)		(((b) & 0xff) << 16)
++#define  PCIE_CONF_DEV(d)		(((d) & 0x1f) << 11)
++#define  PCIE_CONF_FUNC(f)		(((f) & 0x3) << 8)
++#define PCIE_CONF_DATA_OFF	0x18fc
++#define PCIE_MASK_OFF		0x1910
++#define PCIE_CTRL_OFF		0x1a00
++#define PCIE_STAT_OFF		0x1a04
++#define  PCIE_STAT_DEV_OFFS		20
++#define  PCIE_STAT_DEV_MASK		0x1f
++#define  PCIE_STAT_BUS_OFFS		8
++#define  PCIE_STAT_BUS_MASK		0xff
++#define  PCIE_STAT_LINK_DOWN		1
++
++
++u32 __init orion_pcie_dev_id(void __iomem *base)
++{
++	return readl(base + PCIE_DEV_ID_OFF) >> 16;
++}
++
++u32 __init orion_pcie_rev(void __iomem *base)
++{
++	return readl(base + PCIE_DEV_REV_OFF) & 0xff;
++}
++
++int orion_pcie_link_up(void __iomem *base)
++{
++	return !(readl(base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
++}
++
++int orion_pcie_get_local_bus_nr(void __iomem *base)
++{
++	u32 stat = readl(base + PCIE_STAT_OFF);
++
++	return (stat >> PCIE_STAT_BUS_OFFS) & PCIE_STAT_BUS_MASK;
++}
++
++void __init orion_pcie_set_local_bus_nr(void __iomem *base, int nr)
++{
++	u32 stat;
++
++	stat = readl(base + PCIE_STAT_OFF);
++	stat &= ~(PCIE_STAT_BUS_MASK << PCIE_STAT_BUS_OFFS);
++	stat |= nr << PCIE_STAT_BUS_OFFS;
++	writel(stat, base + PCIE_STAT_OFF);
++}
++
++/*
++ * Setup PCIE BARs and Address Decode Wins:
++ * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
++ * WIN[0-3] -> DRAM bank[0-3]
++ */
++static void __init orion_pcie_setup_wins(void __iomem *base,
++					 struct mbus_dram_target_info *dram)
++{
++	u32 size;
++	int i;
++
++	/*
++	 * First, disable and clear BARs and windows.
++	 */
++	for (i = 1; i <= 2; i++) {
++		writel(0, base + PCIE_BAR_CTRL_OFF(i));
++		writel(0, base + PCIE_BAR_LO_OFF(i));
++		writel(0, base + PCIE_BAR_HI_OFF(i));
++	}
++
++	for (i = 0; i < 5; i++) {
++		writel(0, base + PCIE_WIN04_CTRL_OFF(i));
++		writel(0, base + PCIE_WIN04_BASE_OFF(i));
++		writel(0, base + PCIE_WIN04_REMAP_OFF(i));
++	}
++
++	writel(0, base + PCIE_WIN5_CTRL_OFF);
++	writel(0, base + PCIE_WIN5_BASE_OFF);
++	writel(0, base + PCIE_WIN5_REMAP_OFF);
++
++	/*
++	 * Setup windows for DDR banks.  Count total DDR size on the fly.
++	 */
++	size = 0;
++	for (i = 0; i < dram->num_cs; i++) {
++		struct mbus_dram_window *cs = dram->cs + i;
++
++		writel(cs->base & 0xffff0000, base + PCIE_WIN04_BASE_OFF(i));
++		writel(0, base + PCIE_WIN04_REMAP_OFF(i));
++		writel(((cs->size - 1) & 0xffff0000) |
++			(cs->mbus_attr << 8) |
++			(dram->mbus_dram_target_id << 4) | 1,
++				base + PCIE_WIN04_CTRL_OFF(i));
++
++		size += cs->size;
++	}
++
++	/*
++	 * Setup BAR[1] to all DRAM banks.
++	 */
++	writel(dram->cs[0].base, base + PCIE_BAR_LO_OFF(1));
++	writel(0, base + PCIE_BAR_HI_OFF(1));
++	writel(((size - 1) & 0xffff0000) | 1, base + PCIE_BAR_CTRL_OFF(1));
++}
++
++void __init orion_pcie_setup(void __iomem *base,
++			     struct mbus_dram_target_info *dram)
++{
++	u16 cmd;
++	u32 mask;
++
++	/*
++	 * Point PCIe unit MBUS decode windows to DRAM space.
++	 */
++	orion_pcie_setup_wins(base, dram);
++
++	/*
++	 * Master + slave enable.
++	 */
++	cmd = readw(base + PCIE_CMD_OFF);
++	cmd |= PCI_COMMAND_IO;
++	cmd |= PCI_COMMAND_MEMORY;
++	cmd |= PCI_COMMAND_MASTER;
++	writew(cmd, base + PCIE_CMD_OFF);
++
++	/*
++	 * Enable interrupt lines A-D.
++	 */
++	mask = readl(base + PCIE_MASK_OFF);
++	mask |= 0x0f000000;
++	writel(mask, base + PCIE_MASK_OFF);
++}
++
++int orion_pcie_rd_conf(void __iomem *base, struct pci_bus *bus,
++		       u32 devfn, int where, int size, u32 *val)
++{
++	writel(PCIE_CONF_BUS(bus->number) |
++		PCIE_CONF_DEV(PCI_SLOT(devfn)) |
++		PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
++		PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
++			base + PCIE_CONF_ADDR_OFF);
++
++	*val = readl(base + PCIE_CONF_DATA_OFF);
++
++	if (size == 1)
++		*val = (*val >> (8 * (where & 3))) & 0xff;
++	else if (size == 2)
++		*val = (*val >> (8 * (where & 3))) & 0xffff;
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++int orion_pcie_rd_conf_tlp(void __iomem *base, struct pci_bus *bus,
++			   u32 devfn, int where, int size, u32 *val)
++{
++	writel(PCIE_CONF_BUS(bus->number) |
++		PCIE_CONF_DEV(PCI_SLOT(devfn)) |
++		PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
++		PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
++			base + PCIE_CONF_ADDR_OFF);
++
++	*val = readl(base + PCIE_CONF_DATA_OFF);
++
++	if (bus->number != orion_pcie_get_local_bus_nr(base) ||
++	    PCI_FUNC(devfn) != 0)
++		*val = readl(base + PCIE_HEADER_LOG_4_OFF);
++
++	if (size == 1)
++		*val = (*val >> (8 * (where & 3))) & 0xff;
++	else if (size == 2)
++		*val = (*val >> (8 * (where & 3))) & 0xffff;
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++int orion_pcie_rd_conf_wa(void __iomem *wa_base, struct pci_bus *bus,
++			  u32 devfn, int where, int size, u32 *val)
++{
++	*val = readl(wa_base + (PCIE_CONF_BUS(bus->number) |
++				PCIE_CONF_DEV(PCI_SLOT(devfn)) |
++				PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
++				PCIE_CONF_REG(where)));
++
++	if (size == 1)
++		*val = (*val >> (8 * (where & 3))) & 0xff;
++	else if (size == 2)
++		*val = (*val >> (8 * (where & 3))) & 0xffff;
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++int orion_pcie_wr_conf(void __iomem *base, struct pci_bus *bus,
++		       u32 devfn, int where, int size, u32 val)
++{
++	int ret = PCIBIOS_SUCCESSFUL;
++
++	writel(PCIE_CONF_BUS(bus->number) |
++		PCIE_CONF_DEV(PCI_SLOT(devfn)) |
++		PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
++		PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
++			base + PCIE_CONF_ADDR_OFF);
++
++	if (size == 4) {
++		writel(val, base + PCIE_CONF_DATA_OFF);
++	} else if (size == 2) {
++		writew(val, base + PCIE_CONF_DATA_OFF + (where & 3));
++	} else if (size == 1) {
++		writeb(val, base + PCIE_CONF_DATA_OFF + (where & 3));
++	} else {
++		ret = PCIBIOS_BAD_REGISTER_NUMBER;
++	}
++
++	return ret;
++}
+diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
+new file mode 100644
+index 0000000..28b5285
+--- /dev/null
++++ b/arch/arm/plat-orion/time.c
+@@ -0,0 +1,203 @@
++/*
++ * arch/arm/plat-orion/time.c
++ *
++ * Marvell Orion SoC timer handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ *
++ * Timer 0 is used as free-running clocksource, while timer 1 is
++ * used as clock_event_device.
++ */
++
++#include <linux/kernel.h>
++#include <linux/clockchips.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <asm/mach/time.h>
++#include <asm/arch/hardware.h>
++
++/*
++ * Number of timer ticks per jiffy.
++ */
++static u32 ticks_per_jiffy;
++
++
++/*
++ * Timer block registers.
++ */
++#define TIMER_CTRL		(TIMER_VIRT_BASE + 0x0000)
++#define  TIMER0_EN		0x0001
++#define  TIMER0_RELOAD_EN	0x0002
++#define  TIMER1_EN		0x0004
++#define  TIMER1_RELOAD_EN	0x0008
++#define TIMER0_RELOAD		(TIMER_VIRT_BASE + 0x0010)
++#define TIMER0_VAL		(TIMER_VIRT_BASE + 0x0014)
++#define TIMER1_RELOAD		(TIMER_VIRT_BASE + 0x0018)
++#define TIMER1_VAL		(TIMER_VIRT_BASE + 0x001c)
++
++
++/*
++ * Clocksource handling.
++ */
++static cycle_t orion_clksrc_read(void)
++{
++	return 0xffffffff - readl(TIMER0_VAL);
++}
++
++static struct clocksource orion_clksrc = {
++	.name		= "orion_clocksource",
++	.shift		= 20,
++	.rating		= 300,
++	.read		= orion_clksrc_read,
++	.mask		= CLOCKSOURCE_MASK(32),
++	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++
++
++/*
++ * Clockevent handling.
++ */
++static int
++orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
++{
++	unsigned long flags;
++	u32 u;
++
++	if (delta == 0)
++		return -ETIME;
++
++	local_irq_save(flags);
++
++	/*
++	 * Clear and enable clockevent timer interrupt.
++	 */
++	writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE);
++
++	u = readl(BRIDGE_MASK);
++	u |= BRIDGE_INT_TIMER1;
++	writel(u, BRIDGE_MASK);
++
++	/*
++	 * Setup new clockevent timer value.
++	 */
++	writel(delta, TIMER1_VAL);
++
++	/*
++	 * Enable the timer.
++	 */
++	u = readl(TIMER_CTRL);
++	u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN;
++	writel(u, TIMER_CTRL);
++
++	local_irq_restore(flags);
++
++	return 0;
++}
++
++static void
++orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
++{
++	unsigned long flags;
++	u32 u;
++
++	local_irq_save(flags);
++	if (mode == CLOCK_EVT_MODE_PERIODIC) {
++		/*
++		 * Setup timer to fire at 1/HZ intervals.
++		 */
++		writel(ticks_per_jiffy - 1, TIMER1_RELOAD);
++		writel(ticks_per_jiffy - 1, TIMER1_VAL);
++
++		/*
++		 * Enable timer interrupt.
++		 */
++		u = readl(BRIDGE_MASK);
++		writel(u | BRIDGE_INT_TIMER1, BRIDGE_MASK);
++
++		/*
++		 * Enable timer.
++		 */
++		u = readl(TIMER_CTRL);
++		writel(u | TIMER1_EN | TIMER1_RELOAD_EN, TIMER_CTRL);
++	} else {
++		/*
++		 * Disable timer.
++		 */
++		u = readl(TIMER_CTRL);
++		writel(u & ~TIMER1_EN, TIMER_CTRL);
++
++		/*
++		 * Disable timer interrupt.
++		 */
++		u = readl(BRIDGE_MASK);
++		writel(u & ~BRIDGE_INT_TIMER1, BRIDGE_MASK);
++
++		/*
++		 * ACK pending timer interrupt.
++		 */
++		writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE);
++
++	}
++	local_irq_restore(flags);
++}
++
++static struct clock_event_device orion_clkevt = {
++	.name		= "orion_tick",
++	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
++	.shift		= 32,
++	.rating		= 300,
++	.cpumask	= CPU_MASK_CPU0,
++	.set_next_event	= orion_clkevt_next_event,
++	.set_mode	= orion_clkevt_mode,
++};
++
++static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
++{
++	/*
++	 * ACK timer interrupt and call event handler.
++	 */
++	writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE);
++	orion_clkevt.event_handler(&orion_clkevt);
++
++	return IRQ_HANDLED;
++}
++
++static struct irqaction orion_timer_irq = {
++	.name		= "orion_tick",
++	.flags		= IRQF_DISABLED | IRQF_TIMER,
++	.handler	= orion_timer_interrupt
++};
++
++void __init orion_time_init(unsigned int irq, unsigned int tclk)
++{
++	u32 u;
++
++	ticks_per_jiffy = (tclk + HZ/2) / HZ;
++
++
++	/*
++	 * Setup free-running clocksource timer (interrupts
++	 * disabled.)
++	 */
++	writel(0xffffffff, TIMER0_VAL);
++	writel(0xffffffff, TIMER0_RELOAD);
++	u = readl(BRIDGE_MASK);
++	writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK);
++	u = readl(TIMER_CTRL);
++	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL);
++	orion_clksrc.mult = clocksource_hz2mult(tclk, orion_clksrc.shift);
++	clocksource_register(&orion_clksrc);
++
++
++	/*
++	 * Setup clockevent timer (interrupt-driven.)
++	 */
++	setup_irq(irq, &orion_timer_irq);
++	orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
++	orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt);
++	orion_clkevt.min_delta_ns = clockevent_delta2ns(1, &orion_clkevt);
++	clockevents_register_device(&orion_clkevt);
++}
+diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c
+index 99a4474..d84167f 100644
+--- a/arch/arm/plat-s3c24xx/clock.c
++++ b/arch/arm/plat-s3c24xx/clock.c
+@@ -332,6 +332,58 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
+ 	return 0;
+ }
+ 
++static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate)
++{
++	unsigned long div;
++
++	if ((rate == 0) || !clk->parent)
++		return 0;
++
++	div = clk_get_rate(clk->parent) / rate;
++	if (div < 2)
++		div = 2;
++	else if (div > 16)
++		div = 16;
++
++	return div;
++}
++
++static unsigned long s3c24xx_round_dclk_rate(struct clk *clk,
++	unsigned long rate)
++{
++	unsigned long div = s3c24xx_calc_div(clk, rate);
++
++	if (div == 0)
++		return 0;
++
++	return clk_get_rate(clk->parent) / div;
++}
++
++static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate)
++{
++	unsigned long mask, data, div = s3c24xx_calc_div(clk, rate);
++
++	if (div == 0)
++		return -EINVAL;
++
++	if (clk == &s3c24xx_dclk0) {
++		mask = S3C2410_DCLKCON_DCLK0_DIV_MASK |
++			S3C2410_DCLKCON_DCLK0_CMP_MASK;
++		data = S3C2410_DCLKCON_DCLK0_DIV(div) |
++			S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2);
++	} else if (clk == &s3c24xx_dclk1) {
++		mask = S3C2410_DCLKCON_DCLK1_DIV_MASK |
++			S3C2410_DCLKCON_DCLK1_CMP_MASK;
++		data = S3C2410_DCLKCON_DCLK1_DIV(div) |
++			S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2);
++	} else
++		return -EINVAL;
++
++	clk->rate = clk_get_rate(clk->parent) / div;
++	__raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data),
++		S3C24XX_DCLKCON);
++	return clk->rate;
++}
+ 
+ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
+ {
+@@ -378,6 +430,8 @@ struct clk s3c24xx_dclk0 = {
+ 	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
+ 	.enable	        = s3c24xx_dclk_enable,
+ 	.set_parent	= s3c24xx_dclk_setparent,
++	.set_rate	= s3c24xx_set_dclk_rate,
++	.round_rate	= s3c24xx_round_dclk_rate,
+ };
+ 
+ struct clk s3c24xx_dclk1 = {
+@@ -386,6 +440,8 @@ struct clk s3c24xx_dclk1 = {
+ 	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
+ 	.enable		= s3c24xx_dclk_enable,
+ 	.set_parent	= s3c24xx_dclk_setparent,
++	.set_rate	= s3c24xx_set_dclk_rate,
++	.round_rate	= s3c24xx_round_dclk_rate,
+ };
+ 
+ struct clk s3c24xx_clkout0 = {
+diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
+index f513ab0..f5699ca 100644
+--- a/arch/arm/plat-s3c24xx/cpu.c
++++ b/arch/arm/plat-s3c24xx/cpu.c
+@@ -28,15 +28,19 @@
+ #include <linux/ioport.h>
+ #include <linux/serial_core.h>
+ #include <linux/platform_device.h>
++#include <linux/delay.h>
+ 
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+ #include <asm/delay.h>
++#include <asm/cacheflush.h>
+ 
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ 
++#include <asm/arch/system-reset.h>
++
+ #include <asm/arch/regs-gpio.h>
+ #include <asm/plat-s3c/regs-serial.h>
+ 
+@@ -203,6 +207,27 @@ static unsigned long s3c24xx_read_idcode_v4(void)
+ #endif
+ }
+ 
++/* Hook for arm_pm_restart to ensure we execute the reset code
++ * with the caches enabled. It seems at least the S3C2440 has a problem
++ * resetting if there is bus activity interrupted by the reset.
++ */
++static void s3c24xx_pm_restart(char mode)
++{
++	if (mode != 's') {
++		unsigned long flags;
++
++		local_irq_save(flags);
++		__cpuc_flush_kern_all();
++		__cpuc_flush_user_all();
++
++		arch_reset(mode);
++		local_irq_restore(flags);
++	}
++
++	/* fallback, or unhandled */
++	arm_machine_restart(mode);
++}
++
+ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
+ {
+ 	unsigned long idcode = 0x0;
+@@ -230,6 +255,8 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
+ 		panic("Unsupported S3C24XX CPU");
+ 	}
+ 
++	arm_pm_restart = s3c24xx_pm_restart;
++
+ 	(cpu->map_io)(mach_desc, size);
+ }
+ 
+diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
+index 7ed58c0..207a8b5 100644
+--- a/arch/arm/tools/mach-types
++++ b/arch/arm/tools/mach-types
+@@ -12,7 +12,7 @@
+ #
+ #   http://www.arm.linux.org.uk/developer/machines/?action=new
+ #
+-# Last update: Sat Jan 26 14:45:34 2008
++# Last update: Sat Apr 19 11:23:38 2008
+ #
+ # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
+ #
+@@ -381,13 +381,13 @@ ks8695p			ARCH_KS8695P		KS8695P			363
+ se4000			ARCH_SE4000		SE4000			364
+ quadriceps		ARCH_QUADRICEPS		QUADRICEPS		365
+ bronco			ARCH_BRONCO		BRONCO			366
+-esl_wireless_tab	ARCH_ESL_WIRELESS_TABLETESL_WIRELESS_TABLET	367
++esl_wireless_tab	ARCH_ESL_WIRELESS_TAB	ESL_WIRELESS_TAB	367
+ esl_sofcomp		ARCH_ESL_SOFCOMP	ESL_SOFCOMP		368
+ s5c7375			ARCH_S5C7375		S5C7375			369
+ spearhead		ARCH_SPEARHEAD		SPEARHEAD		370
+ pantera			ARCH_PANTERA		PANTERA			371
+ prayoglite		ARCH_PRAYOGLITE		PRAYOGLITE		372
+-gumstix			ARCH_GUMSTIK		GUMSTIK			373
++gumstix			ARCH_GUMSTIX		GUMSTIX			373
+ rcube			ARCH_RCUBE		RCUBE			374
+ rea_olv			ARCH_REA_OLV		REA_OLV			375
+ pxa_iphone		ARCH_PXA_IPHONE		PXA_IPHONE		376
+@@ -1463,7 +1463,7 @@ artemis			MACH_ARTEMIS		ARTEMIS			1462
+ htctitan		MACH_HTCTITAN		HTCTITAN		1463
+ qranium			MACH_QRANIUM		QRANIUM			1464
+ adx_wsc2		MACH_ADX_WSC2		ADX_WSC2		1465
+-adx_medinet		MACH_ADX_MEDINET	ADX_MEDINET		1466
++adx_medcom		MACH_ADX_MEDINET	ADX_MEDINET		1466
+ bboard			MACH_BBOARD		BBOARD			1467
+ cambria			MACH_CAMBRIA		CAMBRIA			1468
+ mt7xxx			MACH_MT7XXX		MT7XXX			1469
+@@ -1611,3 +1611,112 @@ kb9263			MACH_KB9263		KB9263			1612
+ mt7108			MACH_MT7108		MT7108			1613
+ smtr2440		MACH_SMTR2440		SMTR2440		1614
+ manao			MACH_MANAO		MANAO			1615
++cm_x300			MACH_CM_X300		CM_X300			1616
++gulfstream_kp		MACH_GULFSTREAM_KP	GULFSTREAM_KP		1617
++lanreadyfn522		MACH_LANREADYFN522	LANREADYFN522		1618
++arma37			MACH_ARMA37		ARMA37			1619
++mendel			MACH_MENDEL		MENDEL			1620
++pelco_iliad		MACH_PELCO_ILIAD	PELCO_ILIAD		1621
++unit2p			MACH_UNIT2P		UNIT2P			1622
++inc20otter		MACH_INC20OTTER		INC20OTTER		1623
++at91sam9g20ek		MACH_AT91SAM9G20EK	AT91SAM9G20EK		1624
++sc_ge2			MACH_STORCENTER		STORCENTER		1625
++smdk6410		MACH_SMDK6410		SMDK6410		1626
++u300			MACH_U300		U300			1627
++u500			MACH_U500		U500			1628
++ds9260			MACH_DS9260		DS9260			1629
++riverrock		MACH_RIVERROCK		RIVERROCK		1630
++scibath			MACH_SCIBATH		SCIBATH			1631
++at91sam7se		MACH_AT91SAM7SE512EK	AT91SAM7SE512EK		1632
++wrt350n_v2		MACH_WRT350N_V2		WRT350N_V2		1633
++multimedia		MACH_MULTIMEDIA		MULTIMEDIA		1634
++marvin			MACH_MARVIN		MARVIN			1635
++x500			MACH_X500		X500			1636
++awlug4lcu		MACH_AWLUG4LCU		AWLUG4LCU		1637
++palermoc		MACH_PALERMOC		PALERMOC		1638
++omap_ldp		MACH_OMAP_LDP		OMAP_LDP		1639
++ip500			MACH_IP500		IP500			1640
++mx35ads			MACH_MACH_MX35ADS	MACH_MX35ADS		1641
++ase2			MACH_ASE2		ASE2			1642
++mx35evb			MACH_MX35EVB		MX35EVB			1643
++aml_m8050		MACH_AML_M8050		AML_M8050		1644
++mx35_3ds		MACH_MX35_3DS		MX35_3DS		1645
++mars			MACH_MARS		MARS			1646
++ntosd_644xa		MACH_NTOSD_644XA	NTOSD_644XA		1647
++badger			MACH_BADGER		BADGER			1648
++trizeps4wl		MACH_TRIZEPS4WL		TRIZEPS4WL		1649
++trizeps5		MACH_TRIZEPS5		TRIZEPS5		1650
++marlin			MACH_MARLIN		MARLIN			1651
++ts7800			MACH_TS7800		TS7800			1652
++hpipaq214		MACH_HPIPAQ214		HPIPAQ214		1653
++at572d940dcm		MACH_AT572D940DCM	AT572D940DCM		1654
++ne1board		MACH_NE1BOARD		NE1BOARD		1655
++zante			MACH_ZANTE		ZANTE			1656
++sffsdr			MACH_SFFSDR		SFFSDR			1657
++tw2662			MACH_TW2662		TW2662			1658
++vf10xx			MACH_VF10XX		VF10XX			1659
++zoran43xx		MACH_ZORAN43XX		ZORAN43XX		1660
++sonix926		MACH_SONIX926		SONIX926		1661
++celestialsemi		MACH_CELESTIALSEMI	CELESTIALSEMI		1662
++cc9m2443		MACH_CC9M2443		CC9M2443		1663
++tw5334			MACH_TW5334		TW5334			1664
++omap_htcartemis		MACH_HTCARTEMIS		HTCARTEMIS		1665
++nal_hlite		MACH_NAL_HLITE		NAL_HLITE		1666
++htcvogue		MACH_HTCVOGUE		HTCVOGUE		1667
++smartweb		MACH_SMARTWEB		SMARTWEB		1668
++mv86xx			MACH_MV86XX		MV86XX			1669
++mv87xx			MACH_MV87XX		MV87XX			1670
++songyoungho		MACH_SONGYOUNGHO	SONGYOUNGHO		1671
++younghotema		MACH_YOUNGHOTEMA	YOUNGHOTEMA		1672
++pcm037			MACH_PCM037		PCM037			1673
++mmvp			MACH_MMVP		MMVP			1674
++mmap			MACH_MMAP		MMAP			1675
++ptid2410		MACH_PTID2410		PTID2410		1676
++james_926		MACH_JAMES_926		JAMES_926		1677
++fm6000			MACH_FM6000		FM6000			1678
++db88f6281_bp		MACH_DB88F6281_BP	DB88F6281_BP		1680
++rd88f6192_nas		MACH_RD88F6192_NAS	RD88F6192_NAS		1681
++rd88f6281		MACH_RD88F6281		RD88F6281		1682
++db78x00_bp		MACH_DB78X00_BP		DB78X00_BP		1683
++smdk2416		MACH_SMDK2416		SMDK2416		1685
++oce_spider_si		MACH_OCE_SPIDER_SI	OCE_SPIDER_SI		1686
++oce_spider_sk		MACH_OCE_SPIDER_SK	OCE_SPIDER_SK		1687
++rovern6			MACH_ROVERN6		ROVERN6			1688
++pelco_evolution		MACH_PELCO_EVOLUTION	PELCO_EVOLUTION		1689
++wbd111			MACH_WBD111		WBD111			1690
++elaracpe		MACH_ELARACPE		ELARACPE		1691
++mabv3			MACH_MABV3		MABV3			1692
++mv2120			MACH_MV2120		MV2120			1693
++csb737			MACH_CSB737		CSB737			1695
++mx51_3ds		MACH_MX51_3DS		MX51_3DS		1696
++g900			MACH_G900		G900			1697
++apf27			MACH_APF27		APF27			1698
++ggus2000		MACH_GGUS2000		GGUS2000		1699
++omap_2430_mimic		MACH_OMAP_2430_MIMIC	OMAP_2430_MIMIC		1700
++imx27lite		MACH_IMX27LITE		IMX27LITE		1701
++almex			MACH_ALMEX		ALMEX			1702
++control			MACH_CONTROL		CONTROL			1703
++mba2410			MACH_MBA2410		MBA2410			1704
++volcano			MACH_VOLCANO		VOLCANO			1705
++zenith			MACH_ZENITH		ZENITH			1706
++muchip			MACH_MUCHIP		MUCHIP			1707
++magellan		MACH_MAGELLAN		MAGELLAN		1708
++usb_a9260		MACH_USB_A9260		USB_A9260		1709
++usb_a9263		MACH_USB_A9263		USB_A9263		1710
++qil_a9260		MACH_QIL_A9260		QIL_A9260		1711
++cme9210			MACH_CME9210		CME9210			1712
++hczh4			MACH_HCZH4		HCZH4			1713
++spearbasic		MACH_SPEARBASIC		SPEARBASIC		1714
++dep2440			MACH_DEP2440		DEP2440			1715
++hdl_gxr			MACH_HDL_GXR		HDL_GXR			1716
++hdl_gt			MACH_HDL_GT		HDL_GT			1717
++hdl_4g			MACH_HDL_4G		HDL_4G			1718
++s3c6000			MACH_S3C6000		S3C6000			1719
++mmsp2_mdk		MACH_MMSP2_MDK		MMSP2_MDK		1720
++mpx220			MACH_MPX220		MPX220			1721
++kzm_arm11_01		MACH_KZM_ARM11_01	KZM_ARM11_01		1722
++htc_polaris		MACH_HTC_POLARIS	HTC_POLARIS		1723
++htc_kaiser		MACH_HTC_KAISER		HTC_KAISER		1724
++lg_ks20			MACH_LG_KS20		LG_KS20			1725
++hhgps			MACH_HHGPS		HHGPS			1726
++nokia_n810_wimax	MACH_NOKIA_N810_WIMAX	NOKIA_N810_WIMAX	1727
+diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
+index 28e0caf..09ad799 100644
+--- a/arch/avr32/Kconfig
++++ b/arch/avr32/Kconfig
+@@ -47,6 +47,9 @@ config RWSEM_GENERIC_SPINLOCK
+ config GENERIC_TIME
+ 	def_bool y
+ 
++config GENERIC_CLOCKEVENTS
++	def_bool y
++
+ config RWSEM_XCHGADD_ALGORITHM
+ 	def_bool n
+ 
+@@ -70,6 +73,8 @@ source "init/Kconfig"
+ 
+ menu "System Type and features"
+ 
++source "kernel/time/Kconfig"
++
+ config SUBARCH_AVR32B
+ 	bool
+ config MMU
+diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile
+index e4b6d12..18229d0 100644
+--- a/arch/avr32/kernel/Makefile
++++ b/arch/avr32/kernel/Makefile
+@@ -6,7 +6,7 @@ extra-y				:= head.o vmlinux.lds
+ 
+ obj-$(CONFIG_SUBARCH_AVR32B)	+= entry-avr32b.o
+ obj-y				+= syscall_table.o syscall-stubs.o irq.o
+-obj-y				+= setup.o traps.o semaphore.o ocd.o ptrace.o
++obj-y				+= setup.o traps.o ocd.o ptrace.o
+ obj-y				+= signal.o sys_avr32.o process.o time.o
+ obj-y				+= init_task.o switch_to.o cpu.o
+ obj-$(CONFIG_MODULES)		+= module.o avr32_ksyms.o
+diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
+index 8cf16d7..5f31702 100644
+--- a/arch/avr32/kernel/entry-avr32b.S
++++ b/arch/avr32/kernel/entry-avr32b.S
+@@ -741,26 +741,6 @@ irq_level\level:
+ 
+ 	.section .irq.text,"ax", at progbits
+ 
+-.global cpu_idle_sleep
+-cpu_idle_sleep:
+-	mask_interrupts
+-	get_thread_info r8
+-	ld.w	r9, r8[TI_flags]
+-	bld	r9, TIF_NEED_RESCHED
+-	brcs	cpu_idle_enable_int_and_exit
+-	sbr	r9, TIF_CPU_GOING_TO_SLEEP
+-	st.w	r8[TI_flags], r9
+-	unmask_interrupts
+-	sleep 0
+-cpu_idle_skip_sleep:
+-	mask_interrupts
+-	ld.w	r9, r8[TI_flags]
+-	cbr	r9, TIF_CPU_GOING_TO_SLEEP
+-	st.w	r8[TI_flags], r9
+-cpu_idle_enable_int_and_exit:
+-	unmask_interrupts
+-	retal	r12
+-
+ 	.global	irq_level0
+ 	.global	irq_level1
+ 	.global	irq_level2
+diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
+index 7f4af0b..6cf9df1 100644
+--- a/arch/avr32/kernel/process.c
++++ b/arch/avr32/kernel/process.c
+@@ -18,11 +18,11 @@
+ #include <asm/sysreg.h>
+ #include <asm/ocd.h>
+ 
++#include <asm/arch/pm.h>
++
+ void (*pm_power_off)(void) = NULL;
+ EXPORT_SYMBOL(pm_power_off);
+ 
+-extern void cpu_idle_sleep(void);
+-
+ /*
+  * This file handles the architecture-dependent parts of process handling..
+  */
+@@ -54,6 +54,8 @@ void machine_halt(void)
+ 
+ void machine_power_off(void)
+ {
++	if (pm_power_off)
++		pm_power_off();
+ }
+ 
+ void machine_restart(char *cmd)
+diff --git a/arch/avr32/kernel/semaphore.c b/arch/avr32/kernel/semaphore.c
+deleted file mode 100644
+index 1e2705a..0000000
+--- a/arch/avr32/kernel/semaphore.c
++++ /dev/null
+@@ -1,148 +0,0 @@
+-/*
+- * AVR32 sempahore implementation.
+- *
+- * Copyright (C) 2004-2006 Atmel Corporation
+- *
+- * Based on linux/arch/i386/kernel/semaphore.c
+- *  Copyright (C) 1999 Linus Torvalds
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/module.h>
+-
+-#include <asm/semaphore.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is protected
+- * by the spinlock in the semaphore's waitqueue head.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- *  - only on a boundary condition do we need to care. When we go
+- *    from a negative count to a non-negative, we wake people up.
+- *  - when we go from a non-negative count to a negative do we
+- *    (a) synchronize with the "sleeper" count and (b) make sure
+- *    that we're on the wakeup list before we synchronize so that
+- *    we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+-	wake_up(&sem->wait);
+-}
+-EXPORT_SYMBOL(__up);
+-
+-void __sched __down(struct semaphore *sem)
+-{
+-	struct task_struct *tsk = current;
+-        DECLARE_WAITQUEUE(wait, tsk);
+-        unsigned long flags;
+-
+-        tsk->state = TASK_UNINTERRUPTIBLE;
+-        spin_lock_irqsave(&sem->wait.lock, flags);
+-        add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+-        sem->sleepers++;
+-        for (;;) {
+-                int sleepers = sem->sleepers;
+-
+-                /*
+-                 * Add "everybody else" into it. They aren't
+-                 * playing, because we own the spinlock in
+-                 * the wait_queue_head.
+-                 */
+-                if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
+-                        sem->sleepers = 0;
+-                        break;
+-                }
+-                sem->sleepers = 1;      /* us - see -1 above */
+-                spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-                schedule();
+-
+-                spin_lock_irqsave(&sem->wait.lock, flags);
+-                tsk->state = TASK_UNINTERRUPTIBLE;
+-        }
+-        remove_wait_queue_locked(&sem->wait, &wait);
+-        wake_up_locked(&sem->wait);
+-        spin_unlock_irqrestore(&sem->wait.lock, flags);
+-        tsk->state = TASK_RUNNING;
+-}
+-EXPORT_SYMBOL(__down);
+-
+-int __sched __down_interruptible(struct semaphore *sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-        DECLARE_WAITQUEUE(wait, tsk);
+-        unsigned long flags;
+-
+-        tsk->state = TASK_INTERRUPTIBLE;
+-        spin_lock_irqsave(&sem->wait.lock, flags);
+-        add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+-        sem->sleepers++;
+-        for (;;) {
+-                int sleepers = sem->sleepers;
+-
+-		/*
+-		 * With signals pending, this turns into the trylock
+-		 * failure case - we won't be sleeping, and we can't
+-		 * get the lock as it has contention. Just correct the
+-		 * count and exit.
+-		 */
+-		if (signal_pending(current)) {
+-			retval = -EINTR;
+-			sem->sleepers = 0;
+-			atomic_add(sleepers, &sem->count);
+-			break;
+-		}
+-
+-                /*
+-                 * Add "everybody else" into it. They aren't
+-                 * playing, because we own the spinlock in
+-                 * the wait_queue_head.
+-                 */
+-                if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
+-                        sem->sleepers = 0;
+-                        break;
+-                }
+-                sem->sleepers = 1;      /* us - see -1 above */
+-                spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-                schedule();
+-
+-                spin_lock_irqsave(&sem->wait.lock, flags);
+-                tsk->state = TASK_INTERRUPTIBLE;
+-        }
+-        remove_wait_queue_locked(&sem->wait, &wait);
+-        wake_up_locked(&sem->wait);
+-        spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-        tsk->state = TASK_RUNNING;
+-	return retval;
+-}
+-EXPORT_SYMBOL(__down_interruptible);
+diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
+index 36a46c3..00a9862 100644
+--- a/arch/avr32/kernel/time.c
++++ b/arch/avr32/kernel/time.c
+@@ -1,16 +1,12 @@
+ /*
+  * Copyright (C) 2004-2007 Atmel Corporation
+  *
+- * Based on MIPS implementation arch/mips/kernel/time.c
+- *   Copyright 2001 MontaVista Software Inc.
+- *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
+-
+ #include <linux/clk.h>
+-#include <linux/clocksource.h>
++#include <linux/clockchips.h>
+ #include <linux/time.h>
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
+@@ -27,207 +23,133 @@
+ #include <asm/io.h>
+ #include <asm/sections.h>
+ 
+-/* how many counter cycles in a jiffy? */
+-static u32 cycles_per_jiffy;
++#include <asm/arch/pm.h>
+ 
+-/* the count value for the next timer interrupt */
+-static u32 expirelo;
+ 
+-cycle_t __weak read_cycle_count(void)
++static cycle_t read_cycle_count(void)
+ {
+ 	return (cycle_t)sysreg_read(COUNT);
+ }
+ 
+-struct clocksource __weak clocksource_avr32 = {
+-	.name		= "avr32",
+-	.rating		= 350,
++/*
++ * The architectural cycle count registers are a fine clocksource unless
++ * the system idle loop use sleep states like "idle":  the CPU cycles
++ * measured by COUNT (and COMPARE) don't happen during sleep states.
++ * Their duration also changes if cpufreq changes the CPU clock rate.
++ * So we rate the clocksource using COUNT as very low quality.
++ */
++static struct clocksource counter = {
++	.name		= "avr32_counter",
++	.rating		= 50,
+ 	.read		= read_cycle_count,
+ 	.mask		= CLOCKSOURCE_MASK(32),
+ 	.shift		= 16,
+ 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+ };
+ 
+-irqreturn_t __weak timer_interrupt(int irq, void *dev_id);
+-
+-struct irqaction timer_irqaction = {
+-	.handler	= timer_interrupt,
+-	.flags		= IRQF_DISABLED,
+-	.name		= "timer",
+-};
+-
+-/*
+- * By default we provide the null RTC ops
+- */
+-static unsigned long null_rtc_get_time(void)
++static irqreturn_t timer_interrupt(int irq, void *dev_id)
+ {
+-	return mktime(2007, 1, 1, 0, 0, 0);
+-}
+-
+-static int null_rtc_set_time(unsigned long sec)
+-{
+-	return 0;
+-}
++	struct clock_event_device *evdev = dev_id;
+ 
+-static unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
+-static int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
+-
+-static void avr32_timer_ack(void)
+-{
+-	u32 count;
+-
+-	/* Ack this timer interrupt and set the next one */
+-	expirelo += cycles_per_jiffy;
+-	/* setting COMPARE to 0 stops the COUNT-COMPARE */
+-	if (expirelo == 0) {
+-		sysreg_write(COMPARE, expirelo + 1);
+-	} else {
+-		sysreg_write(COMPARE, expirelo);
+-	}
++	/*
++	 * Disable the interrupt until the clockevent subsystem
++	 * reprograms it.
++	 */
++	sysreg_write(COMPARE, 0);
+ 
+-	/* Check to see if we have missed any timer interrupts */
+-	count = sysreg_read(COUNT);
+-	if ((count - expirelo) < 0x7fffffff) {
+-		expirelo = count + cycles_per_jiffy;
+-		sysreg_write(COMPARE, expirelo);
+-	}
++	evdev->event_handler(evdev);
++	return IRQ_HANDLED;
+ }
+ 
+-int __weak avr32_hpt_init(void)
+-{
+-	int ret;
+-	unsigned long mult, shift, count_hz;
+-
+-	count_hz = clk_get_rate(boot_cpu_data.clk);
+-	shift = clocksource_avr32.shift;
+-	mult = clocksource_hz2mult(count_hz, shift);
+-	clocksource_avr32.mult = mult;
+-
+-	{
+-		u64 tmp;
+-
+-		tmp = TICK_NSEC;
+-		tmp <<= shift;
+-		tmp += mult / 2;
+-		do_div(tmp, mult);
+-
+-		cycles_per_jiffy = tmp;
+-	}
++static struct irqaction timer_irqaction = {
++	.handler	= timer_interrupt,
++	.flags		= IRQF_TIMER | IRQF_DISABLED,
++	.name		= "avr32_comparator",
++};
+ 
+-	ret = setup_irq(0, &timer_irqaction);
+-	if (ret) {
+-		pr_debug("timer: could not request IRQ 0: %d\n", ret);
+-		return -ENODEV;
+-	}
++static int comparator_next_event(unsigned long delta,
++		struct clock_event_device *evdev)
++{
++	unsigned long	flags;
+ 
+-	printk(KERN_INFO "timer: AT32AP COUNT-COMPARE at irq 0, "
+-			"%lu.%03lu MHz\n",
+-			((count_hz + 500) / 1000) / 1000,
+-			((count_hz + 500) / 1000) % 1000);
++	raw_local_irq_save(flags);
+ 
+-	return 0;
+-}
++	/* The time to read COUNT then update COMPARE must be less
++	 * than the min_delta_ns value for this clockevent source.
++	 */
++	sysreg_write(COMPARE, (sysreg_read(COUNT) + delta) ? : 1);
+ 
+-/*
+- * Taken from MIPS c0_hpt_timer_init().
+- *
+- * The reason COUNT is written twice is probably to make sure we don't get any
+- * timer interrupts while we are messing with the counter.
+- */
+-int __weak avr32_hpt_start(void)
+-{
+-	u32 count = sysreg_read(COUNT);
+-	expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
+-	sysreg_write(COUNT, expirelo - cycles_per_jiffy);
+-	sysreg_write(COMPARE, expirelo);
+-	sysreg_write(COUNT, count);
++	raw_local_irq_restore(flags);
+ 
+ 	return 0;
+ }
+ 
+-/*
+- * local_timer_interrupt() does profiling and process accounting on a
+- * per-CPU basis.
+- *
+- * In UP mode, it is invoked from the (global) timer_interrupt.
+- */
+-void local_timer_interrupt(int irq, void *dev_id)
++static void comparator_mode(enum clock_event_mode mode,
++		struct clock_event_device *evdev)
+ {
+-	if (current->pid)
+-		profile_tick(CPU_PROFILING);
+-	update_process_times(user_mode(get_irq_regs()));
++	switch (mode) {
++	case CLOCK_EVT_MODE_ONESHOT:
++		pr_debug("%s: start\n", evdev->name);
++		/* FALLTHROUGH */
++	case CLOCK_EVT_MODE_RESUME:
++		cpu_disable_idle_sleep();
++		break;
++	case CLOCK_EVT_MODE_UNUSED:
++	case CLOCK_EVT_MODE_SHUTDOWN:
++		sysreg_write(COMPARE, 0);
++		pr_debug("%s: stop\n", evdev->name);
++		cpu_enable_idle_sleep();
++		break;
++	default:
++		BUG();
++	}
+ }
+ 
+-irqreturn_t __weak timer_interrupt(int irq, void *dev_id)
+-{
+-	/* ack timer interrupt and try to set next interrupt */
+-	avr32_timer_ack();
+-
+-	/*
+-	 * Call the generic timer interrupt handler
+-	 */
+-	write_seqlock(&xtime_lock);
+-	do_timer(1);
+-	write_sequnlock(&xtime_lock);
+-
+-	/*
+-	 * In UP mode, we call local_timer_interrupt() to do profiling
+-	 * and process accounting.
+-	 *
+-	 * SMP is not supported yet.
+-	 */
+-	local_timer_interrupt(irq, dev_id);
+-
+-	return IRQ_HANDLED;
+-}
++static struct clock_event_device comparator = {
++	.name		= "avr32_comparator",
++	.features	= CLOCK_EVT_FEAT_ONESHOT,
++	.shift		= 16,
++	.rating		= 50,
++	.cpumask	= CPU_MASK_CPU0,
++	.set_next_event	= comparator_next_event,
++	.set_mode	= comparator_mode,
++};
+ 
+ void __init time_init(void)
+ {
++	unsigned long counter_hz;
+ 	int ret;
+ 
+-	/*
+-	 * Make sure we don't get any COMPARE interrupts before we can
+-	 * handle them.
+-	 */
+-	sysreg_write(COMPARE, 0);
+-
+-	xtime.tv_sec = rtc_get_time();
++	xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0);
+ 	xtime.tv_nsec = 0;
+ 
+ 	set_normalized_timespec(&wall_to_monotonic,
+ 				-xtime.tv_sec, -xtime.tv_nsec);
+ 
+-	ret = avr32_hpt_init();
+-	if (ret) {
+-		pr_debug("timer: failed setup: %d\n", ret);
+-		return;
+-	}
++	/* figure rate for counter */
++	counter_hz = clk_get_rate(boot_cpu_data.clk);
++	counter.mult = clocksource_hz2mult(counter_hz, counter.shift);
+ 
+-	ret = clocksource_register(&clocksource_avr32);
++	ret = clocksource_register(&counter);
+ 	if (ret)
+ 		pr_debug("timer: could not register clocksource: %d\n", ret);
+ 
+-	ret = avr32_hpt_start();
+-	if (ret) {
+-		pr_debug("timer: failed starting: %d\n", ret);
+-		return;
+-	}
+-}
++	/* setup COMPARE clockevent */
++	comparator.mult = div_sc(counter_hz, NSEC_PER_SEC, comparator.shift);
++	comparator.max_delta_ns = clockevent_delta2ns((u32)~0, &comparator);
++	comparator.min_delta_ns = clockevent_delta2ns(50, &comparator) + 1;
+ 
+-static struct sysdev_class timer_class = {
+-	.name = "timer",
+-};
++	sysreg_write(COMPARE, 0);
++	timer_irqaction.dev_id = &comparator;
+ 
+-static struct sys_device timer_device = {
+-	.id	= 0,
+-	.cls	= &timer_class,
+-};
++	ret = setup_irq(0, &timer_irqaction);
++	if (ret)
++		pr_debug("timer: could not request IRQ 0: %d\n", ret);
++	else {
++		clockevents_register_device(&comparator);
+ 
+-static int __init init_timer_sysfs(void)
+-{
+-	int err = sysdev_class_register(&timer_class);
+-	if (!err)
+-		err = sysdev_register(&timer_device);
+-	return err;
++		pr_info("%s: irq 0, %lu.%03lu MHz\n", comparator.name,
++				((counter_hz + 500) / 1000) / 1000,
++				((counter_hz + 500) / 1000) % 1000);
++	}
+ }
+-
+-device_initcall(init_timer_sysfs);
+diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile
+index 5e9f821..e890094 100644
+--- a/arch/avr32/mach-at32ap/Makefile
++++ b/arch/avr32/mach-at32ap/Makefile
+@@ -1,4 +1,3 @@
+ obj-y				+= at32ap.o clock.o intc.o extint.o pio.o hsmc.o
+-obj-$(CONFIG_CPU_AT32AP700X)	+= at32ap700x.o
+-obj-$(CONFIG_CPU_AT32AP700X)	+= time-tc.o
++obj-$(CONFIG_CPU_AT32AP700X)	+= at32ap700x.o pm-at32ap700x.o
+ obj-$(CONFIG_CPU_FREQ_AT32AP)	+= cpufreq.o
+diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
+index 7678fee..0f24b4f 100644
+--- a/arch/avr32/mach-at32ap/at32ap700x.c
++++ b/arch/avr32/mach-at32ap/at32ap700x.c
+@@ -6,11 +6,13 @@
+  * published by the Free Software Foundation.
+  */
+ #include <linux/clk.h>
++#include <linux/delay.h>
+ #include <linux/fb.h>
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/spi/spi.h>
++#include <linux/usb/atmel_usba_udc.h>
+ 
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -98,6 +100,9 @@ unsigned long at32ap7000_osc_rates[3] = {
+ 	[2] = 12000000,
+ };
+ 
++static struct clk osc0;
++static struct clk osc1;
++
+ static unsigned long osc_get_rate(struct clk *clk)
+ {
+ 	return at32ap7000_osc_rates[clk->index];
+@@ -107,9 +112,6 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
+ {
+ 	unsigned long div, mul, rate;
+ 
+-	if (!(control & PM_BIT(PLLEN)))
+-		return 0;
+-
+ 	div = PM_BFEXT(PLLDIV, control) + 1;
+ 	mul = PM_BFEXT(PLLMUL, control) + 1;
+ 
+@@ -120,6 +122,71 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
+ 	return rate;
+ }
+ 
++static long pll_set_rate(struct clk *clk, unsigned long rate,
++			 u32 *pll_ctrl)
++{
++	unsigned long mul;
++	unsigned long mul_best_fit = 0;
++	unsigned long div;
++	unsigned long div_min;
++	unsigned long div_max;
++	unsigned long div_best_fit = 0;
++	unsigned long base;
++	unsigned long pll_in;
++	unsigned long actual = 0;
++	unsigned long rate_error;
++	unsigned long rate_error_prev = ~0UL;
++	u32 ctrl;
++
++	/* Rate must be between 80 MHz and 200 Mhz. */
++	if (rate < 80000000UL || rate > 200000000UL)
++		return -EINVAL;
++
++	ctrl = PM_BF(PLLOPT, 4);
++	base = clk->parent->get_rate(clk->parent);
++
++	/* PLL input frequency must be between 6 MHz and 32 MHz. */
++	div_min = DIV_ROUND_UP(base, 32000000UL);
++	div_max = base / 6000000UL;
++
++	if (div_max < div_min)
++		return -EINVAL;
++
++	for (div = div_min; div <= div_max; div++) {
++		pll_in = (base + div / 2) / div;
++		mul = (rate + pll_in / 2) / pll_in;
++
++		if (mul == 0)
++			continue;
++
++		actual = pll_in * mul;
++		rate_error = abs(actual - rate);
++
++		if (rate_error < rate_error_prev) {
++			mul_best_fit = mul;
++			div_best_fit = div;
++			rate_error_prev = rate_error;
++		}
++
++		if (rate_error == 0)
++			break;
++	}
++
++	if (div_best_fit == 0)
++		return -EINVAL;
++
++	ctrl |= PM_BF(PLLMUL, mul_best_fit - 1);
++	ctrl |= PM_BF(PLLDIV, div_best_fit - 1);
++	ctrl |= PM_BF(PLLCOUNT, 16);
++
++	if (clk->parent == &osc1)
++		ctrl |= PM_BIT(PLLOSC);
++
++	*pll_ctrl = ctrl;
++
++	return actual;
++}
++
+ static unsigned long pll0_get_rate(struct clk *clk)
+ {
+ 	u32 control;
+@@ -129,6 +196,41 @@ static unsigned long pll0_get_rate(struct clk *clk)
+ 	return pll_get_rate(clk, control);
+ }
+ 
++static void pll1_mode(struct clk *clk, int enabled)
++{
++	unsigned long timeout;
++	u32 status;
++	u32 ctrl;
++
++	ctrl = pm_readl(PLL1);
++
++	if (enabled) {
++		if (!PM_BFEXT(PLLMUL, ctrl) && !PM_BFEXT(PLLDIV, ctrl)) {
++			pr_debug("clk %s: failed to enable, rate not set\n",
++					clk->name);
++			return;
++		}
++
++		ctrl |= PM_BIT(PLLEN);
++		pm_writel(PLL1, ctrl);
++
++		/* Wait for PLL lock. */
++		for (timeout = 10000; timeout; timeout--) {
++			status = pm_readl(ISR);
++			if (status & PM_BIT(LOCK1))
++				break;
++			udelay(10);
++		}
++
++		if (!(status & PM_BIT(LOCK1)))
++			printk(KERN_ERR "clk %s: timeout waiting for lock\n",
++					clk->name);
++	} else {
++		ctrl &= ~PM_BIT(PLLEN);
++		pm_writel(PLL1, ctrl);
++	}
++}
++
+ static unsigned long pll1_get_rate(struct clk *clk)
+ {
+ 	u32 control;
+@@ -138,6 +240,49 @@ static unsigned long pll1_get_rate(struct clk *clk)
+ 	return pll_get_rate(clk, control);
+ }
+ 
++static long pll1_set_rate(struct clk *clk, unsigned long rate, int apply)
++{
++	u32 ctrl = 0;
++	unsigned long actual_rate;
++
++	actual_rate = pll_set_rate(clk, rate, &ctrl);
++
++	if (apply) {
++		if (actual_rate != rate)
++			return -EINVAL;
++		if (clk->users > 0)
++			return -EBUSY;
++		pr_debug(KERN_INFO "clk %s: new rate %lu (actual rate %lu)\n",
++				clk->name, rate, actual_rate);
++		pm_writel(PLL1, ctrl);
++	}
++
++	return actual_rate;
++}
++
++static int pll1_set_parent(struct clk *clk, struct clk *parent)
++{
++	u32 ctrl;
++
++	if (clk->users > 0)
++		return -EBUSY;
++
++	ctrl = pm_readl(PLL1);
++	WARN_ON(ctrl & PM_BIT(PLLEN));
++
++	if (parent == &osc0)
++		ctrl &= ~PM_BIT(PLLOSC);
++	else if (parent == &osc1)
++		ctrl |= PM_BIT(PLLOSC);
++	else
++		return -EINVAL;
++
++	pm_writel(PLL1, ctrl);
++	clk->parent = parent;
++
++	return 0;
++}
++
+ /*
+  * The AT32AP7000 has five primary clock sources: One 32kHz
+  * oscillator, two crystal oscillators and two PLLs.
+@@ -166,7 +311,10 @@ static struct clk pll0 = {
+ };
+ static struct clk pll1 = {
+ 	.name		= "pll1",
++	.mode		= pll1_mode,
+ 	.get_rate	= pll1_get_rate,
++	.set_rate	= pll1_set_rate,
++	.set_parent	= pll1_set_parent,
+ 	.parent		= &osc0,
+ };
+ 
+@@ -605,19 +753,32 @@ static inline void set_ebi_sfr_bits(u32 mask)
+ }
+ 
+ /* --------------------------------------------------------------------
+- *  System Timer/Counter (TC)
++ *  Timer/Counter (TC)
+  * -------------------------------------------------------------------- */
+-static struct resource at32_systc0_resource[] = {
++
++static struct resource at32_tcb0_resource[] = {
+ 	PBMEM(0xfff00c00),
+ 	IRQ(22),
+ };
+-struct platform_device at32_systc0_device = {
+-	.name		= "systc",
++static struct platform_device at32_tcb0_device = {
++	.name		= "atmel_tcb",
+ 	.id		= 0,
+-	.resource	= at32_systc0_resource,
+-	.num_resources	= ARRAY_SIZE(at32_systc0_resource),
++	.resource	= at32_tcb0_resource,
++	.num_resources	= ARRAY_SIZE(at32_tcb0_resource),
+ };
+-DEV_CLK(pclk, at32_systc0, pbb, 3);
++DEV_CLK(t0_clk, at32_tcb0, pbb, 3);
++
++static struct resource at32_tcb1_resource[] = {
++	PBMEM(0xfff01000),
++	IRQ(23),
++};
++static struct platform_device at32_tcb1_device = {
++	.name		= "atmel_tcb",
++	.id		= 1,
++	.resource	= at32_tcb1_resource,
++	.num_resources	= ARRAY_SIZE(at32_tcb1_resource),
++};
++DEV_CLK(t0_clk, at32_tcb1, pbb, 4);
+ 
+ /* --------------------------------------------------------------------
+  *  PIO
+@@ -669,7 +830,8 @@ void __init at32_add_system_devices(void)
+ 	platform_device_register(&pdc_device);
+ 	platform_device_register(&dmaca0_device);
+ 
+-	platform_device_register(&at32_systc0_device);
++	platform_device_register(&at32_tcb0_device);
++	platform_device_register(&at32_tcb1_device);
+ 
+ 	platform_device_register(&pio0_device);
+ 	platform_device_register(&pio1_device);
+@@ -989,7 +1151,9 @@ static struct clk atmel_twi0_pclk = {
+ 	.index		= 2,
+ };
+ 
+-struct platform_device *__init at32_add_device_twi(unsigned int id)
++struct platform_device *__init at32_add_device_twi(unsigned int id,
++						    struct i2c_board_info *b,
++						    unsigned int n)
+ {
+ 	struct platform_device *pdev;
+ 
+@@ -1009,6 +1173,9 @@ struct platform_device *__init at32_add_device_twi(unsigned int id)
+ 
+ 	atmel_twi0_pclk.dev = &pdev->dev;
+ 
++	if (b)
++		i2c_register_board_info(id, b, n);
++
+ 	platform_device_add(pdev);
+ 	return pdev;
+ 
+@@ -1351,9 +1518,39 @@ static struct clk usba0_hclk = {
+ 	.index		= 6,
+ };
+ 
++#define EP(nam, idx, maxpkt, maxbk, dma, isoc)			\
++	[idx] = {						\
++		.name		= nam,				\
++		.index		= idx,				\
++		.fifo_size	= maxpkt,			\
++		.nr_banks	= maxbk,			\
++		.can_dma	= dma,				\
++		.can_isoc	= isoc,				\
++	}
++
++static struct usba_ep_data at32_usba_ep[] __initdata = {
++	EP("ep0",     0,   64, 1, 0, 0),
++	EP("ep1",     1,  512, 2, 1, 1),
++	EP("ep2",     2,  512, 2, 1, 1),
++	EP("ep3-int", 3,   64, 3, 1, 0),
++	EP("ep4-int", 4,   64, 3, 1, 0),
++	EP("ep5",     5, 1024, 3, 1, 1),
++	EP("ep6",     6, 1024, 3, 1, 1),
++};
++
++#undef EP
++
+ struct platform_device *__init
+ at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
+ {
++	/*
++	 * pdata doesn't have room for any endpoints, so we need to
++	 * append room for the ones we need right after it.
++	 */
++	struct {
++		struct usba_platform_data pdata;
++		struct usba_ep_data ep[7];
++	} usba_data;
+ 	struct platform_device *pdev;
+ 
+ 	if (id != 0)
+@@ -1367,13 +1564,20 @@ at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
+ 					  ARRAY_SIZE(usba0_resource)))
+ 		goto out_free_pdev;
+ 
+-	if (data) {
+-		if (platform_device_add_data(pdev, data, sizeof(*data)))
+-			goto out_free_pdev;
++	if (data)
++		usba_data.pdata.vbus_pin = data->vbus_pin;
++	else
++		usba_data.pdata.vbus_pin = -EINVAL;
++
++	data = &usba_data.pdata;
++	data->num_ep = ARRAY_SIZE(at32_usba_ep);
++	memcpy(data->ep, at32_usba_ep, sizeof(at32_usba_ep));
+ 
+-		if (data->vbus_pin != GPIO_PIN_NONE)
+-			at32_select_gpio(data->vbus_pin, 0);
+-	}
++	if (platform_device_add_data(pdev, data, sizeof(usba_data)))
++		goto out_free_pdev;
++
++	if (data->vbus_pin >= 0)
++		at32_select_gpio(data->vbus_pin, 0);
+ 
+ 	usba0_pclk.dev = &pdev->dev;
+ 	usba0_hclk.dev = &pdev->dev;
+@@ -1694,7 +1898,8 @@ struct clk *at32_clock_list[] = {
+ 	&pio2_mck,
+ 	&pio3_mck,
+ 	&pio4_mck,
+-	&at32_systc0_pclk,
++	&at32_tcb0_t0_clk,
++	&at32_tcb1_t0_clk,
+ 	&atmel_usart0_usart,
+ 	&atmel_usart1_usart,
+ 	&atmel_usart2_usart,
+diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
+index 0b286cd..097cf4e 100644
+--- a/arch/avr32/mach-at32ap/intc.c
++++ b/arch/avr32/mach-at32ap/intc.c
+@@ -13,7 +13,6 @@
+ #include <linux/irq.h>
+ #include <linux/platform_device.h>
+ 
+-#include <asm/intc.h>
+ #include <asm/io.h>
+ 
+ #include "intc.h"
+diff --git a/arch/avr32/mach-at32ap/pm-at32ap700x.S b/arch/avr32/mach-at32ap/pm-at32ap700x.S
+new file mode 100644
+index 0000000..949e248
+--- /dev/null
++++ b/arch/avr32/mach-at32ap/pm-at32ap700x.S
+@@ -0,0 +1,66 @@
++/*
++ * Low-level Power Management code.
++ *
++ * Copyright (C) 2008 Atmel Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <asm/asm.h>
++#include <asm/asm-offsets.h>
++#include <asm/thread_info.h>
++#include <asm/arch/pm.h>
++
++	.section .bss, "wa", @nobits
++	.global	disable_idle_sleep
++	.type	disable_idle_sleep, @object
++disable_idle_sleep:
++	.int	4
++	.size	disable_idle_sleep, . - disable_idle_sleep
++
++	/* Keep this close to the irq handlers */
++	.section .irq.text, "ax", @progbits
++
++	/*
++	 * void cpu_enter_idle(void)
++	 *
++	 * Put the CPU into "idle" mode, in which it will consume
++	 * significantly less power.
++	 *
++	 * If an interrupt comes along in the window between
++	 * unmask_interrupts and the sleep instruction below, the
++	 * interrupt code will adjust the return address so that we
++	 * never execute the sleep instruction. This is required
++	 * because the AP7000 doesn't unmask interrupts when entering
++	 * sleep modes; later CPUs may not need this workaround.
++	 */
++	.global	cpu_enter_idle
++	.type	cpu_enter_idle, @function
++cpu_enter_idle:
++	mask_interrupts
++	get_thread_info r8
++	ld.w	r9, r8[TI_flags]
++	bld	r9, TIF_NEED_RESCHED
++	brcs	.Lret_from_sleep
++	sbr	r9, TIF_CPU_GOING_TO_SLEEP
++	st.w	r8[TI_flags], r9
++	unmask_interrupts
++	sleep	CPU_SLEEP_IDLE
++	.size	cpu_idle_sleep, . - cpu_idle_sleep
++
++	/*
++	 * Common return path for PM functions that don't run from
++	 * SRAM.
++	 */
++	.global cpu_idle_skip_sleep
++	.type	cpu_idle_skip_sleep, @function
++cpu_idle_skip_sleep:
++	mask_interrupts
++	ld.w	r9, r8[TI_flags]
++	cbr	r9, TIF_CPU_GOING_TO_SLEEP
++	st.w	r8[TI_flags], r9
++.Lret_from_sleep:
++	unmask_interrupts
++	retal	r12
++	.size	cpu_idle_skip_sleep, . - cpu_idle_skip_sleep
+diff --git a/arch/avr32/mach-at32ap/time-tc.c b/arch/avr32/mach-at32ap/time-tc.c
+deleted file mode 100644
+index 1026586..0000000
+--- a/arch/avr32/mach-at32ap/time-tc.c
++++ /dev/null
+@@ -1,218 +0,0 @@
+-/*
+- * Copyright (C) 2004-2007 Atmel Corporation
+- *
+- * Based on MIPS implementation arch/mips/kernel/time.c
+- *   Copyright 2001 MontaVista Software Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/clk.h>
+-#include <linux/clocksource.h>
+-#include <linux/time.h>
+-#include <linux/module.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-#include <linux/profile.h>
+-#include <linux/sysdev.h>
+-#include <linux/err.h>
+-
+-#include <asm/div64.h>
+-#include <asm/sysreg.h>
+-#include <asm/io.h>
+-#include <asm/sections.h>
+-
+-#include <asm/arch/time.h>
+-
+-/* how many counter cycles in a jiffy? */
+-static u32 cycles_per_jiffy;
+-
+-/* the count value for the next timer interrupt */
+-static u32 expirelo;
+-
+-/* the I/O registers of the TC module */
+-static void __iomem *ioregs;
+-
+-cycle_t read_cycle_count(void)
+-{
+-	return (cycle_t)timer_read(ioregs, 0, CV);
+-}
+-
+-struct clocksource clocksource_avr32 = {
+-	.name		= "avr32",
+-	.rating		= 342,
+-	.read		= read_cycle_count,
+-	.mask		= CLOCKSOURCE_MASK(16),
+-	.shift		= 16,
+-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+-};
+-
+-static void avr32_timer_ack(void)
+-{
+-	u16 count = expirelo;
+-
+-	/* Ack this timer interrupt and set the next one, use a u16
+-	 * variable so it will wrap around correctly */
+-	count += cycles_per_jiffy;
+-	expirelo = count;
+-	timer_write(ioregs, 0, RC, expirelo);
+-
+-	/* Check to see if we have missed any timer interrupts */
+-	count = timer_read(ioregs, 0, CV);
+-	if ((count - expirelo) < 0x7fff) {
+-		expirelo = count + cycles_per_jiffy;
+-		timer_write(ioregs, 0, RC, expirelo);
+-	}
+-}
+-
+-u32 avr32_hpt_read(void)
+-{
+-	return timer_read(ioregs, 0, CV);
+-}
+-
+-static int avr32_timer_calc_div_and_set_jiffies(struct clk *pclk)
+-{
+-	unsigned int cycles_max = (clocksource_avr32.mask + 1) / 2;
+-	unsigned int divs[] = { 4, 8, 16, 32 };
+-	int divs_size = ARRAY_SIZE(divs);
+-	int i = 0;
+-	unsigned long count_hz;
+-	unsigned long shift;
+-	unsigned long mult;
+-	int clock_div = -1;
+-	u64 tmp;
+-
+-	shift = clocksource_avr32.shift;
+-
+-	do {
+-		count_hz = clk_get_rate(pclk) / divs[i];
+-		mult = clocksource_hz2mult(count_hz, shift);
+-		clocksource_avr32.mult = mult;
+-
+-		tmp = TICK_NSEC;
+-		tmp <<= shift;
+-		tmp += mult / 2;
+-		do_div(tmp, mult);
+-
+-		cycles_per_jiffy = tmp;
+-	} while (cycles_per_jiffy > cycles_max && ++i < divs_size);
+-
+-	clock_div = i + 1;
+-
+-	if (clock_div > divs_size) {
+-		pr_debug("timer: could not calculate clock divider\n");
+-		return -EFAULT;
+-	}
+-
+-	/* Set the clock divider */
+-	timer_write(ioregs, 0, CMR, TIMER_BF(CMR_TCCLKS, clock_div));
+-
+-	return 0;
+-}
+-
+-int avr32_hpt_init(unsigned int count)
+-{
+-	struct resource *regs;
+-	struct clk *pclk;
+-	int irq = -1;
+-	int ret = 0;
+-
+-	ret = -ENXIO;
+-
+-	irq = platform_get_irq(&at32_systc0_device, 0);
+-	if (irq < 0) {
+-		pr_debug("timer: could not get irq\n");
+-		goto out_error;
+-	}
+-
+-	pclk = clk_get(&at32_systc0_device.dev, "pclk");
+-	if (IS_ERR(pclk)) {
+-		pr_debug("timer: could not get clk: %ld\n", PTR_ERR(pclk));
+-		goto out_error;
+-	}
+-	clk_enable(pclk);
+-
+-	regs = platform_get_resource(&at32_systc0_device, IORESOURCE_MEM, 0);
+-	if (!regs) {
+-		pr_debug("timer: could not get resource\n");
+-		goto out_error_clk;
+-	}
+-
+-	ioregs = ioremap(regs->start, regs->end - regs->start + 1);
+-	if (!ioregs) {
+-		pr_debug("timer: could not get ioregs\n");
+-		goto out_error_clk;
+-	}
+-
+-	ret = avr32_timer_calc_div_and_set_jiffies(pclk);
+-	if (ret)
+-		goto out_error_io;
+-
+-	ret = setup_irq(irq, &timer_irqaction);
+-	if (ret) {
+-		pr_debug("timer: could not request irq %d: %d\n",
+-				irq, ret);
+-		goto out_error_io;
+-	}
+-
+-	expirelo = (timer_read(ioregs, 0, CV) / cycles_per_jiffy + 1)
+-		* cycles_per_jiffy;
+-
+-	/* Enable clock and interrupts on RC compare */
+-	timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_CLKEN));
+-	timer_write(ioregs, 0, IER, TIMER_BIT(IER_CPCS));
+-	/* Set cycles to first interrupt */
+-	timer_write(ioregs, 0,  RC, expirelo);
+-
+-	printk(KERN_INFO "timer: AT32AP system timer/counter at 0x%p irq %d\n",
+-			ioregs, irq);
+-
+-	return 0;
+-
+-out_error_io:
+-	iounmap(ioregs);
+-out_error_clk:
+-	clk_put(pclk);
+-out_error:
+-	return ret;
+-}
+-
+-int avr32_hpt_start(void)
+-{
+-	timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_SWTRG));
+-	return 0;
+-}
+-
+-irqreturn_t timer_interrupt(int irq, void *dev_id)
+-{
+-	unsigned int sr = timer_read(ioregs, 0, SR);
+-
+-	if (sr & TIMER_BIT(SR_CPCS)) {
+-		/* ack timer interrupt and try to set next interrupt */
+-		avr32_timer_ack();
+-
+-		/*
+-		 * Call the generic timer interrupt handler
+-		 */
+-		write_seqlock(&xtime_lock);
+-		do_timer(1);
+-		write_sequnlock(&xtime_lock);
+-
+-		/*
+-		 * In UP mode, we call local_timer_interrupt() to do profiling
+-		 * and process accounting.
+-		 *
+-		 * SMP is not supported yet.
+-		 */
+-		local_timer_interrupt(irq, dev_id);
+-
+-		return IRQ_HANDLED;
+-	}
+-
+-	return IRQ_NONE;
+-}
+diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c
+index 480760b..0e64ddc 100644
+--- a/arch/avr32/mm/init.c
++++ b/arch/avr32/mm/init.c
+@@ -34,9 +34,6 @@ struct page *empty_zero_page;
+  */
+ unsigned long mmu_context_cache = NO_CONTEXT;
+ 
+-#define START_PFN	(NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
+-#define MAX_LOW_PFN	(NODE_DATA(0)->bdata->node_low_pfn)
+-
+ void show_mem(void)
+ {
+ 	int total = 0, reserved = 0, cached = 0;
+diff --git a/arch/avr32/oprofile/op_model_avr32.c b/arch/avr32/oprofile/op_model_avr32.c
+index e2f876b..df42325 100644
+--- a/arch/avr32/oprofile/op_model_avr32.c
++++ b/arch/avr32/oprofile/op_model_avr32.c
+@@ -16,7 +16,6 @@
+ #include <linux/sched.h>
+ #include <linux/types.h>
+ 
+-#include <asm/intc.h>
+ #include <asm/sysreg.h>
+ #include <asm/system.h>
+ 
+diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
+index 589c6ac..795d0ac 100644
+--- a/arch/blackfin/Kconfig
++++ b/arch/blackfin/Kconfig
+@@ -31,10 +31,6 @@ config ZONE_DMA
+ 	bool
+ 	default y
+ 
+-config SEMAPHORE_SLEEPERS
+-	bool
+-	default y
+-
+ config GENERIC_FIND_NEXT_BIT
+ 	bool
+ 	default y
+@@ -51,10 +47,6 @@ config GENERIC_IRQ_PROBE
+ 	bool
+ 	default y
+ 
+-config GENERIC_TIME
+-	bool
+-	default n
+-
+ config GENERIC_GPIO
+ 	bool
+ 	default y
+@@ -228,16 +220,6 @@ config BF54x
+ 	depends on (BF542 || BF544 || BF547 || BF548 || BF549)
+ 	default y
+ 
+-config BFIN_DUAL_CORE
+-	bool
+-	depends on (BF561)
+-	default y
+-
+-config BFIN_SINGLE_CORE
+-	bool
+-	depends on !BFIN_DUAL_CORE
+-	default y
+-
+ config MEM_GENERIC_BOARD
+ 	bool
+ 	depends on GENERIC_BOARD
+@@ -267,7 +249,7 @@ config MEM_MT48LC8M32B2B5_7
+ 
+ config MEM_MT48LC32M16A2TG_75
+ 	bool
+-	depends on (BFIN527_EZKIT)
++	depends on (BFIN527_EZKIT || BFIN532_IP0X)
+ 	default y
+ 
+ source "arch/blackfin/mach-bf527/Kconfig"
+@@ -290,17 +272,34 @@ config CMDLINE
+ 	  to the kernel, you may specify one here. As a minimum, you should specify
+ 	  the memory size and the root device (e.g., mem=8M, root=/dev/nfs).
+ 
++config BOOT_LOAD
++	hex "Kernel load address for booting"
++	default "0x1000"
++	range 0x1000 0x20000000
++	help
++	  This option allows you to set the load address of the kernel.
++	  This can be useful if you are on a board which has a small amount
++	  of memory or you wish to reserve some memory at the beginning of
++	  the address space.
++
++	  Note that you need to keep this value above 4k (0x1000) as this
++	  memory region is used to capture NULL pointer references as well
++	  as some core kernel functions.
++
+ comment "Clock/PLL Setup"
+ 
+ config CLKIN_HZ
+-	int "Crystal Frequency in Hz"
++	int "Frequency of the crystal on the board in Hz"
+ 	default "11059200" if BFIN533_STAMP
+ 	default "27000000" if BFIN533_EZKIT
+ 	default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS)
+ 	default "30000000" if BFIN561_EZKIT
+ 	default "24576000" if PNAV10
++	default "10000000" if BFIN532_IP0X
+ 	help
+ 	  The frequency of CLKIN crystal oscillator on the board in Hz.
++	  Warning: This value should match the crystal on the board. Otherwise,
++	  peripherals won't work properly.
+ 
+ config BFIN_KERNEL_CLOCK
+ 	bool "Re-program Clocks while Kernel boots?"
+@@ -311,6 +310,25 @@ config BFIN_KERNEL_CLOCK
+ 	  are also not changed, and the Bootloader does 100% of the hardware
+ 	  configuration.
+ 
++config MEM_SIZE
++	int "SDRAM Memory Size in MBytes"
++	depends on BFIN_KERNEL_CLOCK
++	default 64
++
++config MEM_ADD_WIDTH
++	int "Memory Address Width"
++	depends on BFIN_KERNEL_CLOCK
++	depends on (!BF54x)
++	range 8 11
++	default  9 if BFIN533_EZKIT
++	default  9 if BFIN561_EZKIT
++	default  9 if H8606_HVSISTEMAS
++	default 10 if BFIN527_EZKIT
++	default 10 if BFIN537_STAMP
++	default 11 if BFIN533_STAMP
++	default 10 if PNAV10
++	default 10 if BFIN532_IP0X
++
+ config PLL_BYPASS
+ 	bool "Bypass PLL"
+ 	depends on BFIN_KERNEL_CLOCK
+@@ -329,7 +347,7 @@ config VCO_MULT
+ 	range 1 64
+ 	default "22" if BFIN533_EZKIT
+ 	default "45" if BFIN533_STAMP
+-	default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT)
++	default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM)
+ 	default "22" if BFIN533_BLUETECHNIX_CM
+ 	default "20" if BFIN537_BLUETECHNIX_CM
+ 	default "20" if BFIN561_BLUETECHNIX_CM
+@@ -364,19 +382,33 @@ config SCLK_DIV
+ 	int "System Clock Divider"
+ 	depends on BFIN_KERNEL_CLOCK
+ 	range 1 15
+-	default 5 if BFIN533_EZKIT
+-	default 5 if BFIN533_STAMP
+-	default 4 if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT)
+-	default 5 if BFIN533_BLUETECHNIX_CM
+-	default 4 if BFIN537_BLUETECHNIX_CM
+-	default 4 if BFIN561_BLUETECHNIX_CM
+-	default 5 if BFIN561_EZKIT
+-	default 3 if H8606_HVSISTEMAS
++	default 5
+ 	help
+ 	  This sets the frequency of the system clock (including SDRAM or DDR).
+ 	  This can be between 1 and 15
+ 	  System Clock = (PLL frequency) / (this setting)
+ 
++config MAX_MEM_SIZE
++	int "Max SDRAM Memory Size in MBytes"
++	depends on !BFIN_KERNEL_CLOCK && !MPU
++	default 512
++	help
++	  This is the max memory size that the kernel will create CPLB
++	  tables for.  Your system will not be able to handle any more.
++
++choice
++	prompt "DDR SDRAM Chip Type"
++	depends on BFIN_KERNEL_CLOCK
++	depends on BF54x
++	default MEM_MT46V32M16_5B
++
++config MEM_MT46V32M16_6T
++	bool "MT46V32M16_6T"
++
++config MEM_MT46V32M16_5B
++	bool "MT46V32M16_5B"
++endchoice
++
+ #
+ # Max & Min Speeds for various Chips
+ #
+@@ -419,42 +451,33 @@ comment "Kernel Timer/Scheduler"
+ 
+ source kernel/Kconfig.hz
+ 
+-comment "Memory Setup"
+-
+-config MEM_SIZE
+-	int "SDRAM Memory Size in MBytes"
+-	default  32 if BFIN533_EZKIT
+-	default  64 if BFIN527_EZKIT
+-	default  64 if BFIN537_STAMP
+-	default  64 if BFIN548_EZKIT
+-	default  64 if BFIN561_EZKIT
+-	default 128 if BFIN533_STAMP
+-	default  64 if PNAV10
+-	default  32 if H8606_HVSISTEMAS
++config GENERIC_TIME
++	bool "Generic time"
++	default y
+ 
+-config MEM_ADD_WIDTH
+-	int "SDRAM Memory Address Width"
+-	depends on (!BF54x)
+-	default  9 if BFIN533_EZKIT
+-	default  9 if BFIN561_EZKIT
+-	default  9 if H8606_HVSISTEMAS
+-	default 10 if BFIN527_EZKIT
+-	default 10 if BFIN537_STAMP
+-	default 11 if BFIN533_STAMP
+-	default 10 if PNAV10
++config GENERIC_CLOCKEVENTS
++	bool "Generic clock events"
++	depends on GENERIC_TIME
++	default y
+ 
++config CYCLES_CLOCKSOURCE
++	bool "Use 'CYCLES' as a clocksource (EXPERIMENTAL)"
++	depends on EXPERIMENTAL
++	depends on GENERIC_CLOCKEVENTS
++	depends on !BFIN_SCRATCH_REG_CYCLES
++	default n
++	help
++	  If you say Y here, you will enable support for using the 'cycles'
++	  registers as a clock source.  Doing so means you will be unable to
++	  safely write to the 'cycles' register during runtime.  You will
++	  still be able to read it (such as for performance monitoring), but
++	  writing the registers will most likely crash the kernel.
+ 
+-choice
+-	prompt "DDR SDRAM Chip Type"
+-	depends on BFIN548_EZKIT
+-	default MEM_MT46V32M16_5B
++source kernel/time/Kconfig
+ 
+-config MEM_MT46V32M16_6T
+-        bool "MT46V32M16_6T"
++comment "Memory Setup"
+ 
+-config MEM_MT46V32M16_5B
+-        bool "MT46V32M16_5B"
+-endchoice
++comment "Misc"
+ 
+ config ENET_FLASH_PIN
+ 	int "PF port/pin used for flash and ethernet sharing"
+@@ -466,20 +489,6 @@ config ENET_FLASH_PIN
+ 	  code.
+ 	  For example: PF0 --> 0,PF1 --> 1,PF2 --> 2, etc.
+ 
+-config BOOT_LOAD
+-	hex "Kernel load address for booting"
+-	default "0x1000"
+-	range 0x1000 0x20000000
+-	help
+-	  This option allows you to set the load address of the kernel.
+-	  This can be useful if you are on a board which has a small amount
+-	  of memory or you wish to reserve some memory at the beginning of
+-	  the address space.
+-
+-	  Note that you need to keep this value above 4k (0x1000) as this
+-	  memory region is used to capture NULL pointer references as well
+-	  as some core kernel functions.
+-
+ choice
+ 	prompt "Blackfin Exception Scratch Register"
+ 	default BFIN_SCRATCH_REG_RETN
+@@ -665,14 +674,6 @@ endchoice
+ 
+ source "mm/Kconfig"
+ 
+-config LARGE_ALLOCS
+-	bool "Allow allocating large blocks (> 1MB) of memory"
+-	help
+-	  Allow the slab memory allocator to keep chains for very large
+-	  memory sizes - upto 32MB. You may need this if your system has
+-	  a lot of RAM, and you need to able to allocate very large
+-	  contiguous chunks. If unsure, say N.
+-
+ config BFIN_GPTIMERS
+ 	tristate "Enable Blackfin General Purpose Timers API"
+ 	default n
+diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
+index 75eba2c..3cbe16c 100644
+--- a/arch/blackfin/Makefile
++++ b/arch/blackfin/Makefile
+@@ -72,6 +72,11 @@ rev-$(CONFIG_BF_REV_ANY)  := any
+ KBUILD_CFLAGS += -mcpu=$(cpu-y)-$(rev-y)
+ 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__
++
+ head-y   := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o
+ 
+ core-y   += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ arch/$(ARCH)/mach-common/
+diff --git a/arch/blackfin/boot/.gitignore b/arch/blackfin/boot/.gitignore
+new file mode 100644
+index 0000000..3ae0399
+--- /dev/null
++++ b/arch/blackfin/boot/.gitignore
+@@ -0,0 +1 @@
+++vmImage
+diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
+index ae320dc..64876df 100644
+--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
++++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -250,7 +250,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=10
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+@@ -720,8 +720,8 @@ CONFIG_BFIN_OTP=y
+ #
+ CONFIG_SERIAL_BFIN=y
+ CONFIG_SERIAL_BFIN_CONSOLE=y
+-# CONFIG_SERIAL_BFIN_DMA is not set
+-CONFIG_SERIAL_BFIN_PIO=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
+ # CONFIG_SERIAL_BFIN_UART0 is not set
+ CONFIG_SERIAL_BFIN_UART1=y
+ # CONFIG_BFIN_UART1_CTSRTS is not set
+diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
+index 9621caa..8d817ba 100644
+--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
++++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -212,7 +212,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=32
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=9
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
+index b51e76c..20d598d 100644
+--- a/arch/blackfin/configs/BF533-STAMP_defconfig
++++ b/arch/blackfin/configs/BF533-STAMP_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -212,7 +212,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=128
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=11
+ CONFIG_ENET_FLASH_PIN=0
+ CONFIG_BOOT_LOAD=0x1000
+diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
+index d45fa53..b5189c8 100644
+--- a/arch/blackfin/configs/BF537-STAMP_defconfig
++++ b/arch/blackfin/configs/BF537-STAMP_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -220,7 +220,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=10
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
+index c9707f7..5bfdfb2 100644
+--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
++++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -285,7 +285,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=512
+ # CONFIG_MEM_MT46V32M16_6T is not set
+ CONFIG_MEM_MT46V32M16_5B=y
+ CONFIG_BOOT_LOAD=0x1000
+@@ -813,8 +813,8 @@ CONFIG_HW_CONSOLE=y
+ #
+ CONFIG_SERIAL_BFIN=y
+ CONFIG_SERIAL_BFIN_CONSOLE=y
+-# CONFIG_SERIAL_BFIN_DMA is not set
+-CONFIG_SERIAL_BFIN_PIO=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
+ # CONFIG_SERIAL_BFIN_UART0 is not set
+ CONFIG_SERIAL_BFIN_UART1=y
+ # CONFIG_BFIN_UART1_CTSRTS is not set
+diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
+index 4d8a633..b4a20c8 100644
+--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
++++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -256,7 +256,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=9
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/CM-BF533_defconfig b/arch/blackfin/configs/CM-BF533_defconfig
+new file mode 100644
+index 0000000..560890f
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF533_defconfig
+@@ -0,0 +1,912 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.16
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++CONFIG_BF533=y
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++# CONFIG_BF537 is not set
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++# CONFIG_BF_REV_0_2 is not set
++CONFIG_BF_REV_0_3=y
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++CONFIG_MEM_MT48LC16M16A2TG_75=y
++# CONFIG_BFIN533_EZKIT is not set
++# CONFIG_BFIN533_STAMP is not set
++CONFIG_BFIN533_BLUETECHNIX_CM=y
++# CONFIG_H8606_HVSISTEMAS is not set
++# CONFIG_GENERIC_BF533_BOARD is not set
++
++#
++# BF533/2/1 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_UART_ERROR=7
++CONFIG_SPORT0_ERROR=7
++CONFIG_SPI_ERROR=7
++CONFIG_SPORT1_ERROR=7
++CONFIG_PPI_ERROR=7
++CONFIG_DMA_ERROR=7
++CONFIG_PLLWAKE_ERROR=7
++CONFIG_RTC_ERROR=8
++CONFIG_DMA0_PPI=8
++CONFIG_DMA1_SPORT0RX=9
++CONFIG_DMA2_SPORT0TX=9
++CONFIG_DMA3_SPORT1RX=9
++CONFIG_DMA4_SPORT1TX=9
++CONFIG_DMA5_SPI=10
++CONFIG_DMA6_UARTRX=10
++CONFIG_DMA7_UARTTX=10
++CONFIG_TIMER0=11
++CONFIG_TIMER1=11
++CONFIG_TIMER2=11
++CONFIG_PFA=12
++CONFIG_PFB=12
++CONFIG_MEMDMA0=13
++CONFIG_MEMDMA1=13
++CONFIG_WDTIMER=13
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=25000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=750000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_MEM_ADD_WIDTH=9
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++CONFIG_IP_CHECKSUM_L1=y
++CONFIG_CACHELINE_ALIGNED_L1=y
++CONFIG_SYSCALL_TAB_L1=y
++CONFIG_CPLB_SWITCH_TAB_L1=y
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_BFIN_WB=y
++# CONFIG_BFIN_WT is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0xFFC3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++CONFIG_BINFMT_SHARED_FLAT=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_SMC91X=y
++# CONFIG_SMSC911X is not set
++# CONFIG_DM9000 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PFLAGS is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_SPORT=y
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_WATCHDOG is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# Enable Host or Gadget support to see Inventra options
++#
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++# CONFIG_RTC_CLASS is not set
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_YAFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++# CONFIG_NLS is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_MMRS is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig
+new file mode 100644
+index 0000000..9f66d2d
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF537E_defconfig
+@@ -0,0 +1,940 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.16
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++CONFIG_BF537=y
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++CONFIG_BF_REV_0_2=y
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++CONFIG_MEM_MT48LC16M16A2TG_75=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_RTC=8
++CONFIG_IRQ_PPI=8
++CONFIG_IRQ_SPORT0_RX=9
++CONFIG_IRQ_SPORT0_TX=9
++CONFIG_IRQ_SPORT1_RX=9
++CONFIG_IRQ_SPORT1_TX=9
++CONFIG_IRQ_TWI=10
++CONFIG_IRQ_SPI=10
++CONFIG_IRQ_UART0_RX=10
++CONFIG_IRQ_UART0_TX=10
++CONFIG_IRQ_UART1_RX=10
++CONFIG_IRQ_UART1_TX=10
++CONFIG_IRQ_MAC_RX=11
++CONFIG_IRQ_MAC_TX=11
++CONFIG_IRQ_TMR0=12
++CONFIG_IRQ_TMR1=12
++CONFIG_IRQ_TMR2=12
++CONFIG_IRQ_TMR3=12
++CONFIG_IRQ_TMR4=12
++CONFIG_IRQ_TMR5=12
++CONFIG_IRQ_TMR6=12
++CONFIG_IRQ_TMR7=12
++CONFIG_IRQ_PORTG_INTB=12
++CONFIG_IRQ_MEM_DMA0=13
++CONFIG_IRQ_MEM_DMA1=13
++CONFIG_IRQ_WATCH=13
++# CONFIG_BFIN537_STAMP is not set
++CONFIG_BFIN537_BLUETECHNIX_CM=y
++# CONFIG_PNAV10 is not set
++# CONFIG_CAMSIG_MINOTAUR is not set
++# CONFIG_GENERIC_BF537_BOARD is not set
++
++#
++# BF537 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMA_ERROR=7
++CONFIG_IRQ_ERROR=7
++CONFIG_IRQ_CAN_RX=11
++CONFIG_IRQ_CAN_TX=11
++CONFIG_IRQ_PROG_INTA=12
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=25000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_MEM_ADD_WIDTH=9
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++CONFIG_IP_CHECKSUM_L1=y
++CONFIG_CACHELINE_ALIGNED_L1=y
++CONFIG_SYSCALL_TAB_L1=y
++CONFIG_CPLB_SWITCH_TAB_L1=y
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_BFIN_WB=y
++# CONFIG_BFIN_WT is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0xFFC3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++CONFIG_BINFMT_SHARED_FLAT=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_FIXED_PHY is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_SMC91X is not set
++CONFIG_BFIN_MAC=y
++CONFIG_BFIN_MAC_USE_L1=y
++CONFIG_BFIN_TX_DESC_NUM=10
++CONFIG_BFIN_RX_DESC_NUM=20
++# CONFIG_BFIN_MAC_RMII is not set
++# CONFIG_SMSC911X is not set
++# CONFIG_DM9000 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PFLAGS is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_SPORT=y
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_BFIN_UART1=y
++# CONFIG_BFIN_UART1_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_WATCHDOG is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# Enable Host or Gadget support to see Inventra options
++#
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++# CONFIG_RTC_CLASS is not set
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_YAFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++# CONFIG_NLS is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_MMRS is not set
++# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/CM-BF537U_defconfig b/arch/blackfin/configs/CM-BF537U_defconfig
+new file mode 100644
+index 0000000..2694d06
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF537U_defconfig
+@@ -0,0 +1,940 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.16
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++CONFIG_BF537=y
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++CONFIG_BF_REV_0_2=y
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++CONFIG_MEM_MT48LC16M16A2TG_75=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_RTC=8
++CONFIG_IRQ_PPI=8
++CONFIG_IRQ_SPORT0_RX=9
++CONFIG_IRQ_SPORT0_TX=9
++CONFIG_IRQ_SPORT1_RX=9
++CONFIG_IRQ_SPORT1_TX=9
++CONFIG_IRQ_TWI=10
++CONFIG_IRQ_SPI=10
++CONFIG_IRQ_UART0_RX=10
++CONFIG_IRQ_UART0_TX=10
++CONFIG_IRQ_UART1_RX=10
++CONFIG_IRQ_UART1_TX=10
++CONFIG_IRQ_MAC_RX=11
++CONFIG_IRQ_MAC_TX=11
++CONFIG_IRQ_TMR0=12
++CONFIG_IRQ_TMR1=12
++CONFIG_IRQ_TMR2=12
++CONFIG_IRQ_TMR3=12
++CONFIG_IRQ_TMR4=12
++CONFIG_IRQ_TMR5=12
++CONFIG_IRQ_TMR6=12
++CONFIG_IRQ_TMR7=12
++CONFIG_IRQ_PORTG_INTB=12
++CONFIG_IRQ_MEM_DMA0=13
++CONFIG_IRQ_MEM_DMA1=13
++CONFIG_IRQ_WATCH=13
++# CONFIG_BFIN537_STAMP is not set
++CONFIG_BFIN537_BLUETECHNIX_CM=y
++# CONFIG_PNAV10 is not set
++# CONFIG_CAMSIG_MINOTAUR is not set
++# CONFIG_GENERIC_BF537_BOARD is not set
++
++#
++# BF537 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMA_ERROR=7
++CONFIG_IRQ_ERROR=7
++CONFIG_IRQ_CAN_RX=11
++CONFIG_IRQ_CAN_TX=11
++CONFIG_IRQ_PROG_INTA=12
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=30000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_MEM_ADD_WIDTH=9
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++CONFIG_IP_CHECKSUM_L1=y
++CONFIG_CACHELINE_ALIGNED_L1=y
++CONFIG_SYSCALL_TAB_L1=y
++CONFIG_CPLB_SWITCH_TAB_L1=y
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_BFIN_WB=y
++# CONFIG_BFIN_WT is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0xFFC3
++CONFIG_BANK_3=0xFFC3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++CONFIG_BINFMT_SHARED_FLAT=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_SMC91X=y
++# CONFIG_BFIN_MAC is not set
++# CONFIG_SMSC911X is not set
++# CONFIG_DM9000 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PFLAGS is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_SPORT=y
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_BFIN_UART1=y
++# CONFIG_BFIN_UART1_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_WATCHDOG is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++# CONFIG_USB_MUSB_HDRC is not set
++# CONFIG_USB_GADGET_MUSB_HDRC is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++CONFIG_USB_GADGET_NET2272=y
++CONFIG_USB_NET2272=y
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_ETH is not set
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_MMC is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++# CONFIG_RTC_CLASS is not set
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_YAFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++# CONFIG_NLS is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_MMRS is not set
++# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
+new file mode 100644
+index 0000000..9020725
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF548_defconfig
+@@ -0,0 +1,1373 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24.4
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++# CONFIG_PREEMPT_NONE is not set
++CONFIG_PREEMPT_VOLUNTARY=y
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++# CONFIG_BF537 is not set
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++CONFIG_BF548=y
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++CONFIG_BF_REV_0_0=y
++# CONFIG_BF_REV_0_1 is not set
++# CONFIG_BF_REV_0_2 is not set
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF54x=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_RTC=8
++CONFIG_IRQ_SPORT0_RX=9
++CONFIG_IRQ_SPORT0_TX=9
++CONFIG_IRQ_SPORT1_RX=9
++CONFIG_IRQ_SPORT1_TX=9
++CONFIG_IRQ_UART0_RX=10
++CONFIG_IRQ_UART0_TX=10
++CONFIG_IRQ_UART1_RX=10
++CONFIG_IRQ_UART1_TX=10
++CONFIG_IRQ_CNT=8
++CONFIG_IRQ_USB_INT0=11
++CONFIG_IRQ_USB_INT1=11
++CONFIG_IRQ_USB_INT2=11
++CONFIG_IRQ_USB_DMA=11
++CONFIG_IRQ_TIMER0=11
++CONFIG_IRQ_TIMER1=11
++CONFIG_IRQ_TIMER2=11
++CONFIG_IRQ_TIMER3=11
++CONFIG_IRQ_TIMER4=11
++CONFIG_IRQ_TIMER5=11
++CONFIG_IRQ_TIMER6=11
++CONFIG_IRQ_TIMER7=11
++CONFIG_IRQ_TIMER8=11
++CONFIG_IRQ_TIMER9=11
++CONFIG_IRQ_TIMER10=11
++# CONFIG_BFIN548_EZKIT is not set
++CONFIG_BFIN548_BLUETECHNIX_CM=y
++
++#
++# BF548 Specific Configuration
++#
++# CONFIG_DEB_DMA_URGENT is not set
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMAC0_ERR=7
++CONFIG_IRQ_EPPI0_ERR=7
++CONFIG_IRQ_SPORT0_ERR=7
++CONFIG_IRQ_SPORT1_ERR=7
++CONFIG_IRQ_SPI0_ERR=7
++CONFIG_IRQ_UART0_ERR=7
++CONFIG_IRQ_EPPI0=8
++CONFIG_IRQ_SPI0=10
++CONFIG_IRQ_PINT0=12
++CONFIG_IRQ_PINT1=12
++CONFIG_IRQ_MDMAS0=13
++CONFIG_IRQ_MDMAS1=13
++CONFIG_IRQ_WATCHDOG=13
++CONFIG_IRQ_DMAC1_ERR=7
++CONFIG_IRQ_SPORT2_ERR=7
++CONFIG_IRQ_SPORT3_ERR=7
++CONFIG_IRQ_MXVR_DATA=7
++CONFIG_IRQ_SPI1_ERR=7
++CONFIG_IRQ_SPI2_ERR=7
++CONFIG_IRQ_UART1_ERR=7
++CONFIG_IRQ_UART2_ERR=7
++CONFIG_IRQ_CAN0_ERR=7
++CONFIG_IRQ_SPORT2_RX=9
++CONFIG_IRQ_SPORT2_TX=9
++CONFIG_IRQ_SPORT3_RX=9
++CONFIG_IRQ_SPORT3_TX=9
++CONFIG_IRQ_EPPI1=9
++CONFIG_IRQ_EPPI2=9
++CONFIG_IRQ_SPI1=10
++CONFIG_IRQ_SPI2=10
++CONFIG_IRQ_ATAPI_RX=10
++CONFIG_IRQ_ATAPI_TX=10
++CONFIG_IRQ_TWI0=11
++CONFIG_IRQ_TWI1=11
++CONFIG_IRQ_CAN0_RX=11
++CONFIG_IRQ_CAN0_TX=11
++CONFIG_IRQ_MDMAS2=13
++CONFIG_IRQ_MDMAS3=13
++CONFIG_IRQ_MXVR_ERR=11
++CONFIG_IRQ_MXVR_MSG=11
++CONFIG_IRQ_MXVR_PKT=11
++CONFIG_IRQ_EPPI1_ERR=7
++CONFIG_IRQ_EPPI2_ERR=7
++CONFIG_IRQ_UART3_ERR=7
++CONFIG_IRQ_HOST_ERR=7
++CONFIG_IRQ_PIXC_ERR=7
++CONFIG_IRQ_NFC_ERR=7
++CONFIG_IRQ_ATAPI_ERR=7
++CONFIG_IRQ_CAN1_ERR=7
++CONFIG_IRQ_HS_DMA_ERR=7
++CONFIG_IRQ_PIXC_IN0=8
++CONFIG_IRQ_PIXC_IN1=8
++CONFIG_IRQ_PIXC_OUT=8
++CONFIG_IRQ_SDH=8
++CONFIG_IRQ_KEY=8
++CONFIG_IRQ_CAN1_RX=11
++CONFIG_IRQ_CAN1_TX=11
++CONFIG_IRQ_SDH_MASK0=11
++CONFIG_IRQ_SDH_MASK1=11
++CONFIG_IRQ_OTPSEC=11
++CONFIG_IRQ_PINT2=11
++CONFIG_IRQ_PINT3=11
++
++#
++# Pin Interrupt to Port Assignment
++#
++
++#
++# Assignment
++#
++CONFIG_PINTx_REASSIGN=y
++CONFIG_PINT0_ASSIGN=0x00000101
++CONFIG_PINT1_ASSIGN=0x01010000
++CONFIG_PINT2_ASSIGN=0x07000101
++CONFIG_PINT3_ASSIGN=0x02020303
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=25000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_TICK_ONESHOT is not set
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=64
++# CONFIG_MEM_MT46V32M16_6T is not set
++CONFIG_MEM_MT46V32M16_5B=y
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++# CONFIG_SCHEDULE_L1 is not set
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++# CONFIG_MEMSET_L1 is not set
++# CONFIG_MEMCPY_L1 is not set
++# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set
++# CONFIG_IP_CHECKSUM_L1 is not set
++CONFIG_CACHELINE_ALIGNED_L1=y
++# CONFIG_SYSCALL_TAB_L1 is not set
++# CONFIG_CPLB_SWITCH_TAB_L1 is not set
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++# CONFIG_BFIN_WB is not set
++CONFIG_BFIN_WT=y
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++# CONFIG_C_CDPRIO is not set
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x5554
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0x99B3
++CONFIG_EBIU_MBSCTLVAL=0x0
++CONFIG_EBIU_MODEVAL=0x1
++CONFIG_EBIU_FCTLVAL=0x6
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++# CONFIG_BINFMT_SHARED_FLAT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x20000000
++CONFIG_MTD_PHYSMAP_LEN=0x800000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_UCLINUX is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=y
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_SMC91X is not set
++CONFIG_SMSC911X=y
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=m
++CONFIG_INPUT_EVBUG=m
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++# CONFIG_KEYBOARD_BFIN is not set
++# CONFIG_KEYBOARD_OPENCORES is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_OTP=y
++# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
++# CONFIG_BFIN_SPORT is not set
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_TWI_LCD is not set
++# CONFIG_SIMPLE_GPIO is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++# CONFIG_SERIAL_BFIN_DMA is not set
++CONFIG_SERIAL_BFIN_PIO=y
++# CONFIG_SERIAL_BFIN_UART0 is not set
++CONFIG_SERIAL_BFIN_UART1=y
++# CONFIG_BFIN_UART1_CTSRTS is not set
++# CONFIG_SERIAL_BFIN_UART2 is not set
++# CONFIG_SERIAL_BFIN_UART3 is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_BLACKFIN_TWI=y
++CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_AD5252 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8575 is not set
++# CONFIG_SENSORS_PCA9543 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BFIN=y
++# CONFIG_SPI_BITBANG is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_BFIN_WDT=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_ISP1362_HCD is not set
++# CONFIG_USB_ISP1760_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++CONFIG_USB_MUSB_HDRC=y
++CONFIG_USB_MUSB_SOC=y
++
++#
++# Blackfin BF54x, BF525 and BF527 high speed USB support
++#
++CONFIG_USB_MUSB_HOST=y
++# CONFIG_USB_MUSB_PERIPHERAL is not set
++# CONFIG_USB_MUSB_OTG is not set
++CONFIG_USB_MUSB_HDRC_HCD=y
++# CONFIG_MUSB_PIO_ONLY is not set
++# CONFIG_USB_INVENTRA_DMA is not set
++# CONFIG_USB_TI_CPPI_DMA is not set
++CONFIG_USB_MUSB_LOGLEVEL=0
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_SDH_BFIN=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_SPI_MMC is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_BFIN=y
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=m
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=m
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=m
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++CONFIG_JFFS2_FS=m
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=m
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++CONFIG_NFSD=m
++CONFIG_NFSD_V3=y
++# CONFIG_NFSD_V3_ACL is not set
++# CONFIG_NFSD_V4 is not set
++CONFIG_NFSD_TCP=y
++CONFIG_LOCKD=m
++CONFIG_LOCKD_V4=y
++CONFIG_EXPORTFS=m
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=m
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++CONFIG_SMB_FS=m
++CONFIG_SMB_NLS_DEFAULT=y
++CONFIG_SMB_NLS_REMOTE="cp437"
++CONFIG_CIFS=y
++# CONFIG_CIFS_STATS is not set
++# CONFIG_CIFS_WEAK_PW_HASH is not set
++# CONFIG_CIFS_XATTR is not set
++# CONFIG_CIFS_DEBUG2 is not set
++# CONFIG_CIFS_EXPERIMENTAL is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=m
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ASCII=m
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_NLS_UTF8=m
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_MMRS is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++# CONFIG_SECURITY_CAPABILITIES is not set
++# CONFIG_SECURITY_ROOTPLUG is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig
+new file mode 100644
+index 0000000..daf0090
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF561_defconfig
+@@ -0,0 +1,876 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24.4
++# Tue Apr  1 10:50:11 2008
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++# CONFIG_BF537 is not set
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++CONFIG_BF561=y
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++# CONFIG_BF_REV_0_2 is not set
++CONFIG_BF_REV_0_3=y
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BFIN_DUAL_CORE=y
++CONFIG_MEM_MT48LC8M32B2B5_7=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_SPORT0_ERROR=7
++CONFIG_IRQ_SPORT1_ERROR=7
++CONFIG_IRQ_SPI_ERROR=7
++# CONFIG_BFIN561_EZKIT is not set
++# CONFIG_BFIN561_TEPLA is not set
++CONFIG_BFIN561_BLUETECHNIX_CM=y
++# CONFIG_GENERIC_BF561_BOARD is not set
++
++#
++# BF561 Specific Configuration
++#
++
++#
++# Core B Support
++#
++
++#
++# Core B Support
++#
++CONFIG_BF561_COREB=y
++# CONFIG_BF561_COREB_RESET is not set
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMA1_ERROR=7
++CONFIG_IRQ_DMA2_ERROR=7
++CONFIG_IRQ_IMDMA_ERROR=7
++CONFIG_IRQ_PPI0_ERROR=7
++CONFIG_IRQ_PPI1_ERROR=7
++CONFIG_IRQ_UART_ERROR=7
++CONFIG_IRQ_RESERVED_ERROR=7
++CONFIG_IRQ_DMA1_0=8
++CONFIG_IRQ_DMA1_1=8
++CONFIG_IRQ_DMA1_2=8
++CONFIG_IRQ_DMA1_3=8
++CONFIG_IRQ_DMA1_4=8
++CONFIG_IRQ_DMA1_5=8
++CONFIG_IRQ_DMA1_6=8
++CONFIG_IRQ_DMA1_7=8
++CONFIG_IRQ_DMA1_8=8
++CONFIG_IRQ_DMA1_9=8
++CONFIG_IRQ_DMA1_10=8
++CONFIG_IRQ_DMA1_11=8
++CONFIG_IRQ_DMA2_0=9
++CONFIG_IRQ_DMA2_1=9
++CONFIG_IRQ_DMA2_2=9
++CONFIG_IRQ_DMA2_3=9
++CONFIG_IRQ_DMA2_4=9
++CONFIG_IRQ_DMA2_5=9
++CONFIG_IRQ_DMA2_6=9
++CONFIG_IRQ_DMA2_7=9
++CONFIG_IRQ_DMA2_8=9
++CONFIG_IRQ_DMA2_9=9
++CONFIG_IRQ_DMA2_10=9
++CONFIG_IRQ_DMA2_11=9
++CONFIG_IRQ_TIMER0=10
++CONFIG_IRQ_TIMER1=10
++CONFIG_IRQ_TIMER2=10
++CONFIG_IRQ_TIMER3=10
++CONFIG_IRQ_TIMER4=10
++CONFIG_IRQ_TIMER5=10
++CONFIG_IRQ_TIMER6=10
++CONFIG_IRQ_TIMER7=10
++CONFIG_IRQ_TIMER8=10
++CONFIG_IRQ_TIMER9=10
++CONFIG_IRQ_TIMER10=10
++CONFIG_IRQ_TIMER11=10
++CONFIG_IRQ_PROG0_INTA=11
++CONFIG_IRQ_PROG0_INTB=11
++CONFIG_IRQ_PROG1_INTA=11
++CONFIG_IRQ_PROG1_INTB=11
++CONFIG_IRQ_PROG2_INTA=11
++CONFIG_IRQ_PROG2_INTB=11
++CONFIG_IRQ_DMA1_WRRD0=8
++CONFIG_IRQ_DMA1_WRRD1=8
++CONFIG_IRQ_DMA2_WRRD0=9
++CONFIG_IRQ_DMA2_WRRD1=9
++CONFIG_IRQ_IMDMA_WRRD0=12
++CONFIG_IRQ_IMDMA_WRRD1=12
++CONFIG_IRQ_WDTIMER=13
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=25000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++# CONFIG_CYCLES_CLOCKSOURCE is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++CONFIG_IP_CHECKSUM_L1=y
++CONFIG_CACHELINE_ALIGNED_L1=y
++CONFIG_SYSCALL_TAB_L1=y
++CONFIG_CPLB_SWITCH_TAB_L1=y
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_VIRT_TO_BUS=y
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_BFIN_WB=y
++# CONFIG_BFIN_WT is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++CONFIG_C_B0PEN=y
++CONFIG_C_B1PEN=y
++CONFIG_C_B2PEN=y
++# CONFIG_C_B3PEN is not set
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0xFFC3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++CONFIG_BINFMT_SHARED_FLAT=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_IDE is not set
++# CONFIG_BFIN_IDE_ADDRESS_MAPPING_MODE0 is not set
++# CONFIG_BFIN_IDE_ADDRESS_MAPPING_MODE1 is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_SMC91X=y
++# CONFIG_SMSC911X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++# CONFIG_BFIN_SPORT is not set
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_SIMPLE_GPIO is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# Enable Host or Gadget support to see Inventra options
++#
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_YAFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_MMRS is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++# CONFIG_DUAL_CORE_TEST_MODULE is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig
+index 18cbb8c..679c748 100644
+--- a/arch/blackfin/configs/H8606_defconfig
++++ b/arch/blackfin/configs/H8606_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -207,7 +207,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=32
++CONFIG_MAX_MEM_SIZE=32
+ CONFIG_MEM_ADD_WIDTH=9
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig
+new file mode 100644
+index 0000000..5f6ff04
+--- /dev/null
++++ b/arch/blackfin/configs/IP0X_defconfig
+@@ -0,0 +1,1252 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.18
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++CONFIG_BF532=y
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++# CONFIG_BF537 is not set
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++# CONFIG_BF_REV_0_2 is not set
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++CONFIG_BF_REV_0_5=y
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++CONFIG_MEM_MT48LC32M16A2TG_75=y
++# CONFIG_BFIN533_EZKIT is not set
++# CONFIG_BFIN533_STAMP is not set
++# CONFIG_BFIN533_BLUETECHNIX_CM is not set
++# CONFIG_H8606_HVSISTEMAS is not set
++CONFIG_BFIN532_IP0X=y
++# CONFIG_GENERIC_BF533_BOARD is not set
++
++#
++# BF533/2/1 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_UART_ERROR=7
++CONFIG_SPORT0_ERROR=7
++CONFIG_SPI_ERROR=7
++CONFIG_SPORT1_ERROR=7
++CONFIG_PPI_ERROR=7
++CONFIG_DMA_ERROR=7
++CONFIG_PLLWAKE_ERROR=7
++CONFIG_RTC_ERROR=8
++CONFIG_DMA0_PPI=8
++CONFIG_DMA1_SPORT0RX=9
++CONFIG_DMA2_SPORT0TX=9
++CONFIG_DMA3_SPORT1RX=9
++CONFIG_DMA4_SPORT1TX=9
++CONFIG_DMA5_SPI=10
++CONFIG_DMA6_UARTRX=10
++CONFIG_DMA7_UARTTX=10
++CONFIG_TIMER0=11
++CONFIG_TIMER1=11
++CONFIG_TIMER2=11
++CONFIG_PFA=12
++CONFIG_PFB=12
++CONFIG_MEMDMA0=13
++CONFIG_MEMDMA1=13
++CONFIG_WDTIMER=13
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=10000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=400000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MEM_SIZE=64
++CONFIG_MEM_ADD_WIDTH=10
++
++#
++# Hardware addresses
++#
++CONFIG_IP0X_NET1=0x20100000
++CONFIG_IP0X_NET2=0x20200000
++CONFIG_IP0X_USB=0x20300000
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++# CONFIG_IP_CHECKSUM_L1 is not set
++CONFIG_CACHELINE_ALIGNED_L1=y
++# CONFIG_SYSCALL_TAB_L1 is not set
++# CONFIG_CPLB_SWITCH_TAB_L1 is not set
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++# CONFIG_BFIN_ICACHE is not set
++# CONFIG_BFIN_DCACHE is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0xffc2
++CONFIG_BANK_1=0xffc2
++CONFIG_BANK_2=0xffc2
++CONFIG_BANK_3=0xffc2
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++# CONFIG_BINFMT_SHARED_FLAT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
++# CONFIG_PM_SYSFS_DEPRECATED is not set
++CONFIG_PM_BFIN_SLEEP_DEEPER=y
++# CONFIG_PM_BFIN_SLEEP is not set
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK is not set
++# CONFIG_NF_CONNTRACK_ENABLED is not set
++# CONFIG_NF_CONNTRACK is not set
++CONFIG_NETFILTER_XTABLES=y
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++CONFIG_NETFILTER_XT_MATCH_MAC=y
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_QUEUE is not set
++CONFIG_IP_NF_IPTABLES=y
++CONFIG_IP_NF_MATCH_IPRANGE=y
++CONFIG_IP_NF_MATCH_TOS=y
++# CONFIG_IP_NF_MATCH_RECENT is not set
++# CONFIG_IP_NF_MATCH_ECN is not set
++# CONFIG_IP_NF_MATCH_AH is not set
++# CONFIG_IP_NF_MATCH_TTL is not set
++# CONFIG_IP_NF_MATCH_OWNER is not set
++# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
++CONFIG_IP_NF_FILTER=y
++CONFIG_IP_NF_TARGET_REJECT=y
++# CONFIG_IP_NF_TARGET_LOG is not set
++# CONFIG_IP_NF_TARGET_ULOG is not set
++CONFIG_IP_NF_MANGLE=y
++CONFIG_IP_NF_TARGET_TOS=y
++# CONFIG_IP_NF_TARGET_ECN is not set
++# CONFIG_IP_NF_TARGET_TTL is not set
++# CONFIG_IP_NF_RAW is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_UCLINUX=y
++CONFIG_MTD_PLATRAM=y
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_BFIN=y
++CONFIG_BFIN_NAND_BASE=0x20000000
++CONFIG_BFIN_NAND_SIZE=0x10000000
++CONFIG_BFIN_NAND_CLE=2
++CONFIG_BFIN_NAND_ALE=1
++CONFIG_BFIN_NAND_READY=10
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_SMC91X is not set
++# CONFIG_SMSC911X is not set
++CONFIG_DM9000=y
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET_MII is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PFLAGS is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_SPORT=y
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_AD5304 is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_BFIN_WDT is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BFIN=y
++# CONFIG_SPI_BITBANG is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++# CONFIG_HWMON is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++CONFIG_USB_OTG_WHITELIST=y
++# CONFIG_USB_OTG_BLACKLIST_HUB is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_ISP1362_HCD=y
++# CONFIG_USB_ISP1760_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_MUSB_HDRC is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=m
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=m
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_SPI_MMC=m
++CONFIG_SPI_MMC_FRAMEWORK_DRIVER=y
++# CONFIG_SPI_MMC_BFIN_PIO_SPI is not set
++CONFIG_SPI_MMC_CS_CHAN=5
++CONFIG_SPI_MMC_MAX_HZ=20000000
++# CONFIG_SPI_MMC_CARD_DETECT is not set
++# CONFIG_SPI_MMC_DEBUG_MODE is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_BFIN=y
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_MMRS is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=m
++# CONFIG_SECURITY_ROOTPLUG is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
+index 25709f5..87622ad 100644
+--- a/arch/blackfin/configs/PNAV-10_defconfig
++++ b/arch/blackfin/configs/PNAV-10_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -214,7 +214,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=64
+ CONFIG_MEM_ADD_WIDTH=10
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig
+new file mode 100644
+index 0000000..951ea04
+--- /dev/null
++++ b/arch/blackfin/configs/SRV1_defconfig
+@@ -0,0 +1,1290 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.10
++# Fri Nov  2 20:50:23 2007
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_BFIN=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_IRQCHIP_DEMUX_GPIO=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++# CONFIG_PREEMPT_NONE is not set
++CONFIG_PREEMPT_VOLUNTARY=y
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++CONFIG_BF537=y
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++CONFIG_BF_REV_0_2=y
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++# CONFIG_BFIN527_EZKIT is not set
++# CONFIG_BFIN533_EZKIT is not set
++# CONFIG_BFIN533_STAMP is not set
++# CONFIG_BFIN537_STAMP is not set
++# CONFIG_CAMSIG_MINOTAUR is not set
++# CONFIG_BFIN533_BLUETECHNIX_CM is not set
++# CONFIG_BFIN537_BLUETECHNIX_CM is not set
++# CONFIG_BFIN548_EZKIT is not set
++# CONFIG_BFIN561_BLUETECHNIX_CM is not set
++# CONFIG_BFIN561_EZKIT is not set
++# CONFIG_BFIN561_TEPLA is not set
++# CONFIG_PNAV10 is not set
++# CONFIG_VISTASCAN is not set
++# CONFIG_BFIN533_SR3K is not set
++CONFIG_GENERIC_BOARD=y
++CONFIG_MEM_GENERIC_BOARD=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_RTC=8
++CONFIG_IRQ_PPI=8
++CONFIG_IRQ_SPORT0_RX=9
++CONFIG_IRQ_SPORT0_TX=9
++CONFIG_IRQ_SPORT1_RX=9
++CONFIG_IRQ_SPORT1_TX=9
++CONFIG_IRQ_TWI=10
++CONFIG_IRQ_SPI=10
++CONFIG_IRQ_UART0_RX=10
++CONFIG_IRQ_UART0_TX=10
++CONFIG_IRQ_UART1_RX=10
++CONFIG_IRQ_UART1_TX=10
++CONFIG_IRQ_MAC_RX=11
++CONFIG_IRQ_MAC_TX=11
++CONFIG_IRQ_TMR0=12
++CONFIG_IRQ_TMR1=12
++CONFIG_IRQ_TMR2=12
++CONFIG_IRQ_TMR3=12
++CONFIG_IRQ_TMR4=12
++CONFIG_IRQ_TMR5=12
++CONFIG_IRQ_TMR6=12
++CONFIG_IRQ_TMR7=12
++CONFIG_IRQ_PORTG_INTB=12
++CONFIG_IRQ_MEM_DMA0=13
++CONFIG_IRQ_MEM_DMA1=13
++CONFIG_IRQ_WATCH=13
++
++#
++# BF537 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMA_ERROR=7
++CONFIG_IRQ_ERROR=7
++CONFIG_IRQ_CAN_RX=11
++CONFIG_IRQ_CAN_TX=11
++CONFIG_IRQ_PROG_INTA=12
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=22118400
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133000000
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_MEM_ADD_WIDTH=9
++CONFIG_BOOT_LOAD=0x400000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++# CONFIG_IP_CHECKSUM_L1 is not set
++CONFIG_CACHELINE_ALIGNED_L1=y
++# CONFIG_SYSCALL_TAB_L1 is not set
++# CONFIG_CPLB_SWITCH_TAB_L1 is not set
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++CONFIG_BFIN_DMA_5XX=y
++CONFIG_DMA_UNCACHED_2M=y
++# CONFIG_DMA_UNCACHED_1M is not set
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++# CONFIG_BFIN_WB is not set
++CONFIG_BFIN_WT=y
++CONFIG_L1_MAX_PIECE=16
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0x99B3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++# CONFIG_BINFMT_SHARED_FLAT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
++# CONFIG_PM_SYSFS_DEPRECATED is not set
++CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++# CONFIG_PM_WAKEUP_GPIO_API is not set
++CONFIG_PM_WAKEUP_SIC_IWR=0x80000000
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++CONFIG_IRDA=m
++
++#
++# IrDA protocols
++#
++CONFIG_IRLAN=m
++CONFIG_IRCOMM=m
++# CONFIG_IRDA_ULTRA is not set
++
++#
++# IrDA options
++#
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++# CONFIG_IRDA_FAST_RR is not set
++# CONFIG_IRDA_DEBUG is not set
++
++#
++# Infrared-port device drivers
++#
++
++#
++# SIR device drivers
++#
++CONFIG_IRTTY_SIR=m
++
++#
++# Dongle support
++#
++# CONFIG_DONGLE is not set
++
++#
++# Old SIR device drivers
++#
++# CONFIG_IRPORT_SIR is not set
++
++#
++# Old Serial dongle support
++#
++
++#
++# FIR device drivers
++#
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=m
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++CONFIG_MTD_JEDECPROBE=m
++CONFIG_MTD_GEN_PROBE=m
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_MW320D=m
++CONFIG_MTD_RAM=y
++CONFIG_MTD_ROM=m
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_BF5xx=m
++CONFIG_BFIN_FLASH_SIZE=0x400000
++CONFIG_EBIU_FLASH_BASE=0x20000000
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=m
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_BFIN=m
++CONFIG_BFIN_NAND_BASE=0x20212000
++CONFIG_BFIN_NAND_CLE=2
++CONFIG_BFIN_NAND_ALE=1
++CONFIG_BFIN_NAND_READY=3
++CONFIG_MTD_NAND_IDS=m
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++# CONFIG_NET_ETHERNET is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=m
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++CONFIG_INPUT_MISC=y
++# CONFIG_INPUT_ATI_REMOTE is not set
++# CONFIG_INPUT_ATI_REMOTE2 is not set
++# CONFIG_INPUT_KEYSPAN_REMOTE is not set
++# CONFIG_INPUT_POWERMATE is not set
++# CONFIG_INPUT_YEALINK is not set
++CONFIG_INPUT_UINPUT=y
++# CONFIG_BF53X_PFBUTTONS is not set
++# CONFIG_TWI_KEYPAD is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++CONFIG_BF5xx_PFLAGS=y
++# CONFIG_BF5xx_PFLAGS_PROC is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BF5xx_TIMERS is not set
++# CONFIG_BF5xx_PPI is not set
++# CONFIG_BFIN_SPORT is not set
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_TWI_LCD is not set
++# CONFIG_AD5304 is not set
++# CONFIG_BF5xx_TEA5764 is not set
++# CONFIG_BF5xx_FBDMA is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++# CONFIG_SERIAL_BFIN_UART1 is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_BFIN_WDT=y
++CONFIG_HW_RANDOM=m
++# CONFIG_GEN_RTC is not set
++CONFIG_BLACKFIN_DPMC=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_BLACKFIN_GPIO is not set
++CONFIG_I2C_BLACKFIN_TWI=y
++CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_AD5252 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8575 is not set
++# CONFIG_SENSORS_PCA9543 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BFIN=y
++# CONFIG_SPI_BITBANG is not set
++
++#
++# SPI Protocol Masters
++#
++CONFIG_SPI_AT25=m
++# CONFIG_SPI_SPIDEV is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=m
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++CONFIG_VIDEO_DEV=y
++# CONFIG_VIDEO_V4L1 is not set
++CONFIG_VIDEO_V4L1_COMPAT=y
++CONFIG_VIDEO_V4L2=y
++CONFIG_VIDEO_CAPTURE_DRIVERS=y
++# CONFIG_VIDEO_ADV_DEBUG is not set
++# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
++
++#
++# Encoders/decoders and other helper chips
++#
++
++#
++# Audio decoders
++#
++# CONFIG_VIDEO_TDA9840 is not set
++# CONFIG_VIDEO_TEA6415C is not set
++# CONFIG_VIDEO_TEA6420 is not set
++# CONFIG_VIDEO_MSP3400 is not set
++# CONFIG_VIDEO_CS53L32A is not set
++# CONFIG_VIDEO_TLV320AIC23B is not set
++# CONFIG_VIDEO_WM8775 is not set
++# CONFIG_VIDEO_WM8739 is not set
++
++#
++# Video decoders
++#
++# CONFIG_VIDEO_OV7670 is not set
++# CONFIG_VIDEO_SAA711X is not set
++# CONFIG_VIDEO_TVP5150 is not set
++
++#
++# Video and audio decoders
++#
++# CONFIG_VIDEO_CX25840 is not set
++
++#
++# MPEG video encoders
++#
++# CONFIG_VIDEO_CX2341X is not set
++
++#
++# Video encoders
++#
++# CONFIG_VIDEO_SAA7127 is not set
++
++#
++# Video improvement chips
++#
++# CONFIG_VIDEO_UPD64031A is not set
++# CONFIG_VIDEO_UPD64083 is not set
++# CONFIG_VIDEO_SAA5246A is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_VIDEO_PPI_GENERIC is not set
++CONFIG_VIDEO_BLACKFIN_CAM=m
++# CONFIG_VIDEO_BLACKFIN_MT9M001 is not set
++
++#
++# CMOS Camera Sensor Selection
++#
++# CONFIG_MT9V022 is not set
++# CONFIG_MT9M001 is not set
++# CONFIG_VS6524 is not set
++# CONFIG_VS6624 is not set
++CONFIG_OV9655=y
++# CONFIG_RADIO_ADAPTERS is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# HID Devices
++#
++# CONFIG_HID is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# Enable Host or Gadget support to see Inventra options
++#
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++# CONFIG_RTC_CLASS is not set
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=m
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++CONFIG_JFFS2_FS=m
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=m
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=m
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=m
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++CONFIG_SMB_FS=m
++# CONFIG_SMB_NLS_DEFAULT is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS=m
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_FRAME_POINTER is not set
++# CONFIG_FORCED_INLINING is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_DEBUG_MMRS is not set
++# CONFIG_DEBUG_HWERR is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
+index 318b9b6..6140cd6 100644
+--- a/arch/blackfin/kernel/Makefile
++++ b/arch/blackfin/kernel/Makefile
+@@ -6,9 +6,15 @@ extra-y := init_task.o vmlinux.lds
+ 
+ obj-y := \
+ 	entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
+-	sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \
++	sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \
+ 	fixed_code.o reboot.o bfin_gpio.o
+ 
++ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
++    obj-y += time-ts.o
++else
++    obj-y += time.o
++endif
++
+ obj-$(CONFIG_BFIN_GPTIMERS)          += gptimers.o
+ obj-$(CONFIG_MODULES)                += module.o
+ obj-$(CONFIG_BFIN_DMA_5XX)           += bfin_dma_5xx.o
+diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
+index 8fd5d22..fd5448d 100644
+--- a/arch/blackfin/kernel/bfin_dma_5xx.c
++++ b/arch/blackfin/kernel/bfin_dma_5xx.c
+@@ -67,7 +67,7 @@ static int __init blackfin_dma_init(void)
+ 
+ 	for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
+ 		dma_ch[i].chan_status = DMA_CHANNEL_FREE;
+-		dma_ch[i].regs = base_addr[i];
++		dma_ch[i].regs = dma_io_base_addr[i];
+ 		mutex_init(&(dma_ch[i].dmalock));
+ 	}
+ 	/* Mark MEMDMA Channel 0 as requested since we're using it internally */
+@@ -106,12 +106,15 @@ int request_dma(unsigned int channel, char *device_id)
+ 
+ #ifdef CONFIG_BF54x
+ 	if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
+-		if (strncmp(device_id, "BFIN_UART", 9) == 0)
++		if (strncmp(device_id, "BFIN_UART", 9) == 0) {
++			dma_ch[channel].regs->peripheral_map &= 0x0FFF;
+ 			dma_ch[channel].regs->peripheral_map |=
+-				(channel - CH_UART2_RX + 0xC);
+-		else
++				((channel - CH_UART2_RX + 0xC)<<12);
++		} else {
++			dma_ch[channel].regs->peripheral_map &= 0x0FFF;
+ 			dma_ch[channel].regs->peripheral_map |=
+-				(channel - CH_UART2_RX + 0x6);
++				((channel - CH_UART2_RX + 0x6)<<12);
++		}
+ 	}
+ #endif
+ 
+diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
+index 08788f7..7e8eaf4 100644
+--- a/arch/blackfin/kernel/bfin_gpio.c
++++ b/arch/blackfin/kernel/bfin_gpio.c
+@@ -95,14 +95,14 @@ enum {
+ 	AWA_data_clear = SYSCR,
+ 	AWA_data_set = SYSCR,
+ 	AWA_toggle = SYSCR,
+-	AWA_maska = UART_SCR,
+-	AWA_maska_clear = UART_SCR,
+-	AWA_maska_set = UART_SCR,
+-	AWA_maska_toggle = UART_SCR,
+-	AWA_maskb = UART_GCTL,
+-	AWA_maskb_clear = UART_GCTL,
+-	AWA_maskb_set = UART_GCTL,
+-	AWA_maskb_toggle = UART_GCTL,
++	AWA_maska = BFIN_UART_SCR,
++	AWA_maska_clear = BFIN_UART_SCR,
++	AWA_maska_set = BFIN_UART_SCR,
++	AWA_maska_toggle = BFIN_UART_SCR,
++	AWA_maskb = BFIN_UART_GCTL,
++	AWA_maskb_clear = BFIN_UART_GCTL,
++	AWA_maskb_set = BFIN_UART_GCTL,
++	AWA_maskb_toggle = BFIN_UART_GCTL,
+ 	AWA_dir = SPORT1_STAT,
+ 	AWA_polar = SPORT1_STAT,
+ 	AWA_edge = SPORT1_STAT,
+@@ -348,11 +348,10 @@ static void portmux_setup(unsigned short per, unsigned short function)
+ 			offset = port_mux_lut[y].offset;
+ 			muxreg = bfin_read_PORT_MUX();
+ 
+-			if (offset != 1) {
++			if (offset != 1)
+ 				muxreg &= ~(1 << offset);
+-			} else {
++			else
+ 				muxreg &= ~(3 << 1);
+-			}
+ 
+ 			muxreg |= (function << offset);
+ 			bfin_write_PORT_MUX(muxreg);
+@@ -396,39 +395,11 @@ inline void portmux_setup(unsigned short portno, unsigned short function)
+ # define portmux_setup(...)  do { } while (0)
+ #endif
+ 
+-#ifndef BF548_FAMILY
+-static void default_gpio(unsigned gpio)
+-{
+-	unsigned short bank, bitmask;
+-	unsigned long flags;
+-
+-	bank = gpio_bank(gpio);
+-	bitmask = gpio_bit(gpio);
+-
+-	local_irq_save(flags);
+-
+-	gpio_bankb[bank]->maska_clear = bitmask;
+-	gpio_bankb[bank]->maskb_clear = bitmask;
+-	SSYNC();
+-	gpio_bankb[bank]->inen &= ~bitmask;
+-	gpio_bankb[bank]->dir &= ~bitmask;
+-	gpio_bankb[bank]->polar &= ~bitmask;
+-	gpio_bankb[bank]->both &= ~bitmask;
+-	gpio_bankb[bank]->edge &= ~bitmask;
+-	AWA_DUMMY_READ(edge);
+-	local_irq_restore(flags);
+-}
+-#else
+-# define default_gpio(...)  do { } while (0)
+-#endif
+-
+ static int __init bfin_gpio_init(void)
+ {
+-
+ 	printk(KERN_INFO "Blackfin GPIO Controller\n");
+ 
+ 	return 0;
+-
+ }
+ arch_initcall(bfin_gpio_init);
+ 
+@@ -821,10 +792,10 @@ int peripheral_request(unsigned short per, const char *label)
+ 	local_irq_save(flags);
+ 
+ 	if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
++		dump_stack();
+ 		printk(KERN_ERR
+ 		    "%s: Peripheral %d is already reserved as GPIO by %s !\n",
+-		       __FUNCTION__, ident, get_label(ident));
+-		dump_stack();
++		       __func__, ident, get_label(ident));
+ 		local_irq_restore(flags);
+ 		return -EBUSY;
+ 	}
+@@ -833,31 +804,31 @@ int peripheral_request(unsigned short per, const char *label)
+ 
+ 		u16 funct = get_portmux(ident);
+ 
+-	/*
+-	 * Pin functions like AMC address strobes my
+-	 * be requested and used by several drivers
+-	 */
++		/*
++		 * Pin functions like AMC address strobes my
++		 * be requested and used by several drivers
++		 */
+ 
+ 		if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
+ 
+-		/*
+-		 * Allow that the identical pin function can
+-		 * be requested from the same driver twice
+-		 */
++			/*
++			 * Allow that the identical pin function can
++			 * be requested from the same driver twice
++			 */
+ 
+-		if (cmp_label(ident, label) == 0)
+-			goto anyway;
++			if (cmp_label(ident, label) == 0)
++				goto anyway;
+ 
++			dump_stack();
+ 			printk(KERN_ERR
+ 			       "%s: Peripheral %d function %d is already reserved by %s !\n",
+-			       __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident));
+-			dump_stack();
++			       __func__, ident, P_FUNCT2MUX(per), get_label(ident));
+ 			local_irq_restore(flags);
+ 			return -EBUSY;
+ 		}
+ 	}
+ 
+-anyway:
++ anyway:
+ 	reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
+ 
+ 	portmux_setup(ident, P_FUNCT2MUX(per));
+@@ -890,47 +861,47 @@ int peripheral_request(unsigned short per, const char *label)
+ 
+ 	if (!check_gpio(ident)) {
+ 
+-	if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
+-		printk(KERN_ERR
+-		       "%s: Peripheral %d is already reserved as GPIO by %s !\n",
+-		       __FUNCTION__, ident, get_label(ident));
+-		dump_stack();
+-		local_irq_restore(flags);
+-		return -EBUSY;
+-	}
++		if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
++			dump_stack();
++			printk(KERN_ERR
++			       "%s: Peripheral %d is already reserved as GPIO by %s !\n",
++			       __func__, ident, get_label(ident));
++			local_irq_restore(flags);
++			return -EBUSY;
++		}
+ 
+ 	}
+ 
+ 	if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
+ 
+-	/*
+-	 * Pin functions like AMC address strobes my
+-	 * be requested and used by several drivers
+-	 */
++		/*
++		 * Pin functions like AMC address strobes my
++		 * be requested and used by several drivers
++		 */
+ 
+-	if (!(per & P_MAYSHARE)) {
++		if (!(per & P_MAYSHARE)) {
+ 
+-	/*
+-	 * Allow that the identical pin function can
+-	 * be requested from the same driver twice
+-	 */
++			/*
++			 * Allow that the identical pin function can
++			 * be requested from the same driver twice
++			 */
+ 
+-		if (cmp_label(ident, label) == 0)
+-			goto anyway;
++			if (cmp_label(ident, label) == 0)
++				goto anyway;
+ 
++			dump_stack();
+ 			printk(KERN_ERR
+ 			       "%s: Peripheral %d function %d is already"
+ 			       " reserved by %s !\n",
+-			       __FUNCTION__, ident, P_FUNCT2MUX(per),
++			       __func__, ident, P_FUNCT2MUX(per),
+ 				get_label(ident));
+-			dump_stack();
+ 			local_irq_restore(flags);
+ 			return -EBUSY;
+ 		}
+ 
+ 	}
+ 
+-anyway:
++ anyway:
+ 	portmux_setup(per, P_FUNCT2MUX(per));
+ 
+ 	port_setup(ident, PERIPHERAL_USAGE);
+@@ -944,7 +915,7 @@ anyway:
+ EXPORT_SYMBOL(peripheral_request);
+ #endif
+ 
+-int peripheral_request_list(unsigned short per[], const char *label)
++int peripheral_request_list(const unsigned short per[], const char *label)
+ {
+ 	u16 cnt;
+ 	int ret;
+@@ -954,10 +925,10 @@ int peripheral_request_list(unsigned short per[], const char *label)
+ 		ret = peripheral_request(per[cnt], label);
+ 
+ 		if (ret < 0) {
+-			for ( ; cnt > 0; cnt--) {
++			for ( ; cnt > 0; cnt--)
+ 				peripheral_free(per[cnt - 1]);
+-			}
+-		return ret;
++
++			return ret;
+ 		}
+ 	}
+ 
+@@ -981,15 +952,13 @@ void peripheral_free(unsigned short per)
+ 
+ 	local_irq_save(flags);
+ 
+-	if (unlikely(!(reserved_peri_map[gpio_bank(ident)]
+-			 & gpio_bit(ident)))) {
++	if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
+ 		local_irq_restore(flags);
+ 		return;
+ 	}
+ 
+-	if (!(per & P_MAYSHARE)) {
++	if (!(per & P_MAYSHARE))
+ 		port_setup(ident, GPIO_USAGE);
+-	}
+ 
+ 	reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
+ 
+@@ -999,14 +968,11 @@ void peripheral_free(unsigned short per)
+ }
+ EXPORT_SYMBOL(peripheral_free);
+ 
+-void peripheral_free_list(unsigned short per[])
++void peripheral_free_list(const unsigned short per[])
+ {
+ 	u16 cnt;
+-
+-	for (cnt = 0; per[cnt] != 0; cnt++) {
++	for (cnt = 0; per[cnt] != 0; cnt++)
+ 		peripheral_free(per[cnt]);
+-	}
+-
+ }
+ EXPORT_SYMBOL(peripheral_free_list);
+ 
+@@ -1046,17 +1012,17 @@ int gpio_request(unsigned gpio, const char *label)
+ 	}
+ 
+ 	if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
++		dump_stack();
+ 		printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
+ 			 gpio, get_label(gpio));
+-		dump_stack();
+ 		local_irq_restore(flags);
+ 		return -EBUSY;
+ 	}
+ 	if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
++		dump_stack();
+ 		printk(KERN_ERR
+ 		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
+ 		       gpio, get_label(gpio));
+-		dump_stack();
+ 		local_irq_restore(flags);
+ 		return -EBUSY;
+ 	}
+@@ -1082,14 +1048,12 @@ void gpio_free(unsigned gpio)
+ 	local_irq_save(flags);
+ 
+ 	if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+-		gpio_error(gpio);
+ 		dump_stack();
++		gpio_error(gpio);
+ 		local_irq_restore(flags);
+ 		return;
+ 	}
+ 
+-	default_gpio(gpio);
+-
+ 	reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+ 
+ 	set_label(gpio, "free");
+@@ -1152,6 +1116,18 @@ int gpio_get_value(unsigned gpio)
+ }
+ EXPORT_SYMBOL(gpio_get_value);
+ 
++void bfin_gpio_irq_prepare(unsigned gpio)
++{
++	unsigned long flags;
++
++	port_setup(gpio, GPIO_USAGE);
++
++	local_irq_save(flags);
++	gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
++	gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
++	local_irq_restore(flags);
++}
++
+ #else
+ 
+ int gpio_direction_input(unsigned gpio)
+@@ -1218,6 +1194,11 @@ void bfin_gpio_reset_spi0_ssel1(void)
+ 	udelay(1);
+ }
+ 
++void bfin_gpio_irq_prepare(unsigned gpio)
++{
++	port_setup(gpio, GPIO_USAGE);
++}
++
+ #endif /*BF548_FAMILY */
+ 
+ #if defined(CONFIG_PROC_FS)
+diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c
+index 0bfbb26..053edff 100644
+--- a/arch/blackfin/kernel/bfin_ksyms.c
++++ b/arch/blackfin/kernel/bfin_ksyms.c
+@@ -42,11 +42,6 @@ EXPORT_SYMBOL(ip_fast_csum);
+ 
+ EXPORT_SYMBOL(kernel_thread);
+ 
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__down_interruptible);
+-
+ EXPORT_SYMBOL(is_in_rom);
+ EXPORT_SYMBOL(bfin_return_from_exception);
+ 
+diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
+index bd07229..822beef 100644
+--- a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
++++ b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
+@@ -39,14 +39,6 @@
+ #include <asm/cplbinit.h>
+ #include <asm/blackfin.h>
+ 
+-#define CPLB_I 1
+-#define CPLB_D 2
+-
+-#define SYNC_SYS    SSYNC()
+-#define SYNC_CORE   CSYNC()
+-
+-#define CPLB_BIT_PAGESIZE 0x30000
+-
+ static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" };
+ 
+ static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched)
+diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
+index dc6e8a7..4806010 100644
+--- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c
++++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
+@@ -43,13 +43,15 @@ void __init generate_cpl_tables(void)
+ 	unsigned long d_data, i_data;
+ 	unsigned long d_cache = 0, i_cache = 0;
+ 
++	printk(KERN_INFO "MPU: setting up cplb tables with memory protection\n");
++
+ #ifdef CONFIG_BFIN_ICACHE
+ 	i_cache = CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+ #endif
+ 
+ #ifdef CONFIG_BFIN_DCACHE
+ 	d_cache = CPLB_L1_CHBL;
+-#ifdef CONFIG_BLKFIN_WT
++#ifdef CONFIG_BFIN_WT
+ 	d_cache |= CPLB_L1_AOW | CPLB_WT;
+ #endif
+ #endif
+diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+index c426a22..99f2831 100644
+--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
++++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+@@ -24,8 +24,6 @@
+ #include <asm/cplbinit.h>
+ #include <asm/mmu_context.h>
+ 
+-#ifdef CONFIG_BFIN_ICACHE
+-
+ #define FAULT_RW	(1 << 16)
+ #define FAULT_USERSUPV	(1 << 17)
+ 
+@@ -143,30 +141,48 @@ static noinline int dcplb_miss(void)
+ 	unsigned long d_data;
+ 
+ 	nr_dcplb_miss++;
+-	if (addr >= _ramend)
+-		return CPLB_PROT_VIOL;
+ 
+ 	d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
+ #ifdef CONFIG_BFIN_DCACHE
+-	d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+-#ifdef CONFIG_BLKFIN_WT
+-	d_data |= CPLB_L1_AOW | CPLB_WT;
+-#endif
++	if (addr < _ramend - DMA_UNCACHED_REGION ||
++	    (reserved_mem_dcache_on && addr >= _ramend &&
++	     addr < physical_mem_end)) {
++		d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
++#ifdef CONFIG_BFIN_WT
++		d_data |= CPLB_L1_AOW | CPLB_WT;
+ #endif
+-	mask = current_rwx_mask;
+-	if (mask) {
+-		int page = addr >> PAGE_SHIFT;
+-		int offs = page >> 5;
+-		int bit = 1 << (page & 31);
+-
+-		if (mask[offs] & bit)
+-			d_data |= CPLB_USER_RD;
+-
+-		mask += page_mask_nelts;
+-		if (mask[offs] & bit)
+-			d_data |= CPLB_USER_WR;
+ 	}
++#endif
++	if (addr >= physical_mem_end) {
++		if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE
++		    && (status & FAULT_USERSUPV)) {
++			addr &= ~0x3fffff;
++			d_data &= ~PAGE_SIZE_4KB;
++			d_data |= PAGE_SIZE_4MB;
++		} else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
++		    && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) {
++			addr &= ~(1 * 1024 * 1024 - 1);
++			d_data &= ~PAGE_SIZE_4KB;
++			d_data |= PAGE_SIZE_1MB;
++		} else
++			return CPLB_PROT_VIOL;
++	} else if (addr >= _ramend) {
++	    d_data |= CPLB_USER_RD | CPLB_USER_WR;
++	} else {
++		mask = current_rwx_mask;
++		if (mask) {
++			int page = addr >> PAGE_SHIFT;
++			int offs = page >> 5;
++			int bit = 1 << (page & 31);
++
++			if (mask[offs] & bit)
++				d_data |= CPLB_USER_RD;
+ 
++			mask += page_mask_nelts;
++			if (mask[offs] & bit)
++				d_data |= CPLB_USER_WR;
++		}
++	}
+ 	idx = evict_one_dcplb();
+ 
+ 	addr &= PAGE_MASK;
+@@ -189,12 +205,14 @@ static noinline int icplb_miss(void)
+ 	unsigned long i_data;
+ 
+ 	nr_icplb_miss++;
+-	if (status & FAULT_USERSUPV)
+-		nr_icplb_supv_miss++;
+ 
+-	if (addr >= _ramend)
++	/* If inside the uncached DMA region, fault.  */
++	if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend)
+ 		return CPLB_PROT_VIOL;
+ 
++	if (status & FAULT_USERSUPV)
++		nr_icplb_supv_miss++;
++
+ 	/*
+ 	 * First, try to find a CPLB that matches this address.  If we
+ 	 * find one, then the fact that we're in the miss handler means
+@@ -211,30 +229,48 @@ static noinline int icplb_miss(void)
+ 	}
+ 
+ 	i_data = CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4KB;
+-#ifdef CONFIG_BFIN_ICACHE
+-	i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+-#endif
+ 
++#ifdef CONFIG_BFIN_ICACHE
+ 	/*
+-	 * Two cases to distinguish - a supervisor access must necessarily
+-	 * be for a module page; we grant it unconditionally (could do better
+-	 * here in the future).  Otherwise, check the x bitmap of the current
+-	 * process.
++	 * Normal RAM, and possibly the reserved memory area, are
++	 * cacheable.
+ 	 */
+-	if (!(status & FAULT_USERSUPV)) {
+-		unsigned long *mask = current_rwx_mask;
+-
+-		if (mask) {
+-			int page = addr >> PAGE_SHIFT;
+-			int offs = page >> 5;
+-			int bit = 1 << (page & 31);
++	if (addr < _ramend ||
++	    (addr < physical_mem_end && reserved_mem_icache_on))
++		i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
++#endif
+ 
+-			mask += 2 * page_mask_nelts;
+-			if (mask[offs] & bit)
+-				i_data |= CPLB_USER_RD;
++	if (addr >= physical_mem_end) {
++		if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
++		    && (status & FAULT_USERSUPV)) {
++			addr &= ~(1 * 1024 * 1024 - 1);
++			i_data &= ~PAGE_SIZE_4KB;
++			i_data |= PAGE_SIZE_1MB;
++		} else
++		    return CPLB_PROT_VIOL;
++	} else if (addr >= _ramend) {
++		i_data |= CPLB_USER_RD;
++	} else {
++		/*
++		 * Two cases to distinguish - a supervisor access must
++		 * necessarily be for a module page; we grant it
++		 * unconditionally (could do better here in the future).
++		 * Otherwise, check the x bitmap of the current process.
++		 */
++		if (!(status & FAULT_USERSUPV)) {
++			unsigned long *mask = current_rwx_mask;
++
++			if (mask) {
++				int page = addr >> PAGE_SHIFT;
++				int offs = page >> 5;
++				int bit = 1 << (page & 31);
++
++				mask += 2 * page_mask_nelts;
++				if (mask[offs] & bit)
++					i_data |= CPLB_USER_RD;
++			}
+ 		}
+ 	}
+-
+ 	idx = evict_one_icplb();
+ 	addr &= PAGE_MASK;
+ 	icplb_tbl[idx].addr = addr;
+@@ -250,7 +286,6 @@ static noinline int icplb_miss(void)
+ 
+ static noinline int dcplb_protection_fault(void)
+ {
+-	unsigned long addr = bfin_read_DCPLB_FAULT_ADDR();
+ 	int status = bfin_read_DCPLB_STATUS();
+ 
+ 	nr_dcplb_prot++;
+@@ -280,8 +315,7 @@ int cplb_hdr(int seqstat, struct pt_regs *regs)
+ 	case 0x26:
+ 		return dcplb_miss();
+ 	default:
+-	    return 1;
+-		panic_cplb_error(seqstat, regs);
++		return 1;
+ 	}
+ }
+ 
+@@ -299,7 +333,7 @@ void flush_switched_cplbs(void)
+ 	enable_icplb();
+ 
+ 	disable_dcplb();
+-	for (i = first_mask_dcplb; i < MAX_CPLBS; i++) {
++	for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
+ 		dcplb_tbl[i].data = 0;
+ 		bfin_write32(DCPLB_DATA0 + i * 4, 0);
+ 	}
+@@ -319,7 +353,7 @@ void set_mask_dcplbs(unsigned long *masks)
+ 	d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
+ #ifdef CONFIG_BFIN_DCACHE
+ 	d_data |= CPLB_L1_CHBL;
+-#ifdef CONFIG_BLKFIN_WT
++#ifdef CONFIG_BFIN_WT
+ 	d_data |= CPLB_L1_AOW | CPLB_WT;
+ #endif
+ #endif
+@@ -334,5 +368,3 @@ void set_mask_dcplbs(unsigned long *masks)
+ 	}
+ 	enable_dcplb();
+ }
+-
+-#endif
+diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c b/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
+index a4f0b42..1e74f0b 100644
+--- a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
++++ b/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
+@@ -33,9 +33,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/uaccess.h>
+ 
+-#include <asm/current.h>
+-#include <asm/system.h>
+-#include <asm/cplb.h>
++#include <asm/cplbinit.h>
+ #include <asm/blackfin.h>
+ 
+ #define CPLB_I 1
+@@ -174,16 +172,6 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
+ 	return len;
+ }
+ 
+-static int cplbinfo_write_proc(struct file *file, const char __user *buffer,
+-			       unsigned long count, void *data)
+-{
+-	printk(KERN_INFO "Reset the CPLB swap in/out counts.\n");
+-	memset(ipdt_swapcount_table, 0, MAX_SWITCH_I_CPLBS * sizeof(unsigned long));
+-	memset(dpdt_swapcount_table, 0, MAX_SWITCH_D_CPLBS * sizeof(unsigned long));
+-
+-	return count;
+-}
+-
+ static int __init cplbinfo_init(void)
+ {
+ 	struct proc_dir_entry *entry;
+@@ -193,7 +181,6 @@ static int __init cplbinfo_init(void)
+ 		return -ENOMEM;
+ 
+ 	entry->read_proc = cplbinfo_read_proc;
+-	entry->write_proc = cplbinfo_write_proc;
+ 	entry->data = NULL;
+ 
+ 	return 0;
+diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+index 6320bc4..917325b 100644
+--- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c
++++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+@@ -26,6 +26,35 @@
+ #include <asm/cplb.h>
+ #include <asm/cplbinit.h>
+ 
++#ifdef CONFIG_MAX_MEM_SIZE
++# define CPLB_MEM CONFIG_MAX_MEM_SIZE
++#else
++# define CPLB_MEM CONFIG_MEM_SIZE
++#endif
++
++/*
++* Number of required data CPLB switchtable entries
++* MEMSIZE / 4 (we mostly install 4M page size CPLBs
++* approx 16 for smaller 1MB page size CPLBs for allignment purposes
++* 1 for L1 Data Memory
++* possibly 1 for L2 Data Memory
++* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
++* 1 for ASYNC Memory
++*/
++#define MAX_SWITCH_D_CPLBS (((CPLB_MEM / 4) + 16 + 1 + 1 + 1 \
++				 + ASYNC_MEMORY_CPLB_COVERAGE) * 2)
++
++/*
++* Number of required instruction CPLB switchtable entries
++* MEMSIZE / 4 (we mostly install 4M page size CPLBs
++* approx 12 for smaller 1MB page size CPLBs for allignment purposes
++* 1 for L1 Instruction Memory
++* possibly 1 for L2 Instruction Memory
++* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
++*/
++#define MAX_SWITCH_I_CPLBS (((CPLB_MEM / 4) + 12 + 1 + 1 + 1) * 2)
++
++
+ u_long icplb_table[MAX_CPLBS + 1];
+ u_long dcplb_table[MAX_CPLBS + 1];
+ 
+@@ -295,6 +324,8 @@ void __init generate_cpl_tables(void)
+ 	struct cplb_tab *t_d = NULL;
+ 	struct s_cplb cplb;
+ 
++	printk(KERN_INFO "NOMPU: setting up cplb tables for global access\n");
++
+ 	cplb.init_i.size = MAX_CPLBS;
+ 	cplb.init_d.size = MAX_CPLBS;
+ 	cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
+diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c
+index d6b61d5..2f62a9f 100644
+--- a/arch/blackfin/kernel/dma-mapping.c
++++ b/arch/blackfin/kernel/dma-mapping.c
+@@ -59,7 +59,7 @@ void dma_alloc_init(unsigned long start, unsigned long end)
+ 	memset((void *)dma_base, 0, DMA_UNCACHED_REGION);
+ 	dma_initialized = 1;
+ 
+-	printk(KERN_INFO "%s: dma_page @ 0x%p - %d pages at 0x%08lx\n", __FUNCTION__,
++	printk(KERN_INFO "%s: dma_page @ 0x%p - %d pages at 0x%08lx\n", __func__,
+ 	       dma_page, dma_pages, dma_base);
+ }
+ 
+@@ -100,7 +100,7 @@ static void __free_dma_pages(unsigned long addr, unsigned int pages)
+ 	int i;
+ 
+ 	if ((page + pages) > dma_pages) {
+-		printk(KERN_ERR "%s: freeing outside range.\n", __FUNCTION__);
++		printk(KERN_ERR "%s: freeing outside range.\n", __func__);
+ 		BUG();
+ 	}
+ 
+diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c
+index 1904d8b..e698554 100644
+--- a/arch/blackfin/kernel/gptimers.c
++++ b/arch/blackfin/kernel/gptimers.c
+@@ -52,12 +52,14 @@ static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] =
+ 	(GPTIMER_timer_regs *)TIMER5_CONFIG,
+ 	(GPTIMER_timer_regs *)TIMER6_CONFIG,
+ 	(GPTIMER_timer_regs *)TIMER7_CONFIG,
+-#endif
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
++# if (MAX_BLACKFIN_GPTIMERS > 8)
+ 	(GPTIMER_timer_regs *)TIMER8_CONFIG,
+ 	(GPTIMER_timer_regs *)TIMER9_CONFIG,
+ 	(GPTIMER_timer_regs *)TIMER10_CONFIG,
++#  if (MAX_BLACKFIN_GPTIMERS > 11)
+ 	(GPTIMER_timer_regs *)TIMER11_CONFIG,
++#  endif
++# endif
+ #endif
+ };
+ 
+@@ -80,12 +82,14 @@ static uint32_t const trun_mask[MAX_BLACKFIN_GPTIMERS] =
+ 	TIMER_STATUS_TRUN5,
+ 	TIMER_STATUS_TRUN6,
+ 	TIMER_STATUS_TRUN7,
+-#endif
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
++# if (MAX_BLACKFIN_GPTIMERS > 8)
+ 	TIMER_STATUS_TRUN8,
+ 	TIMER_STATUS_TRUN9,
+ 	TIMER_STATUS_TRUN10,
++#  if (MAX_BLACKFIN_GPTIMERS > 11)
+ 	TIMER_STATUS_TRUN11,
++#  endif
++# endif
+ #endif
+ };
+ 
+@@ -100,12 +104,14 @@ static uint32_t const tovf_mask[MAX_BLACKFIN_GPTIMERS] =
+ 	TIMER_STATUS_TOVF5,
+ 	TIMER_STATUS_TOVF6,
+ 	TIMER_STATUS_TOVF7,
+-#endif
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
++# if (MAX_BLACKFIN_GPTIMERS > 8)
+ 	TIMER_STATUS_TOVF8,
+ 	TIMER_STATUS_TOVF9,
+ 	TIMER_STATUS_TOVF10,
++#  if (MAX_BLACKFIN_GPTIMERS > 11)
+ 	TIMER_STATUS_TOVF11,
++#  endif
++# endif
+ #endif
+ };
+ 
+@@ -120,12 +126,14 @@ static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] =
+ 	TIMER_STATUS_TIMIL5,
+ 	TIMER_STATUS_TIMIL6,
+ 	TIMER_STATUS_TIMIL7,
+-#endif
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
++# if (MAX_BLACKFIN_GPTIMERS > 8)
+ 	TIMER_STATUS_TIMIL8,
+ 	TIMER_STATUS_TIMIL9,
+ 	TIMER_STATUS_TIMIL10,
++#  if (MAX_BLACKFIN_GPTIMERS > 11)
+ 	TIMER_STATUS_TIMIL11,
++#  endif
++# endif
+ #endif
+ };
+ 
+diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
+index 6b8459c..be9fdd0 100644
+--- a/arch/blackfin/kernel/process.c
++++ b/arch/blackfin/kernel/process.c
+@@ -32,6 +32,8 @@
+ #include <linux/unistd.h>
+ #include <linux/user.h>
+ #include <linux/uaccess.h>
++#include <linux/sched.h>
++#include <linux/tick.h>
+ #include <linux/fs.h>
+ #include <linux/err.h>
+ 
+@@ -69,33 +71,44 @@ EXPORT_SYMBOL(pm_power_off);
+  * The idle loop on BFIN
+  */
+ #ifdef CONFIG_IDLE_L1
+-void default_idle(void)__attribute__((l1_text));
++static void default_idle(void)__attribute__((l1_text));
+ void cpu_idle(void)__attribute__((l1_text));
+ #endif
+ 
+-void default_idle(void)
++/*
++ * This is our default idle handler.  We need to disable
++ * interrupts here to ensure we don't miss a wakeup call.
++ */
++static void default_idle(void)
+ {
+-	while (!need_resched()) {
+-		local_irq_disable();
+-		if (likely(!need_resched()))
+-			idle_with_irq_disabled();
+-		local_irq_enable();
+-	}
+-}
++	local_irq_disable();
++	if (!need_resched())
++		idle_with_irq_disabled();
+ 
+-void (*idle)(void) = default_idle;
++	local_irq_enable();
++}
+ 
+ /*
+- * The idle thread. There's no useful work to be
+- * done, so just try to conserve power and have a
+- * low exit latency (ie sit in a loop waiting for
+- * somebody to say that they'd like to reschedule)
++ * The idle thread.  We try to conserve power, while trying to keep
++ * overall latency low.  The architecture specific idle is passed
++ * a value to indicate the level of "idleness" of the system.
+  */
+ void cpu_idle(void)
+ {
+ 	/* endless idle loop with no priority at all */
+ 	while (1) {
+-		idle();
++		void (*idle)(void) = pm_idle;
++
++#ifdef CONFIG_HOTPLUG_CPU
++		if (cpu_is_offline(smp_processor_id()))
++			cpu_die();
++#endif
++		if (!idle)
++			idle = default_idle;
++		tick_nohz_stop_sched_tick();
++		while (!need_resched())
++			idle();
++		tick_nohz_restart_sched_tick();
+ 		preempt_enable_no_resched();
+ 		schedule();
+ 		preempt_disable();
+@@ -189,7 +202,7 @@ copy_thread(int nr, unsigned long clone_flags,
+  * sys_execve() executes a new program.
+  */
+ 
+-asmlinkage int sys_execve(char *name, char **argv, char **envp)
++asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
+ {
+ 	int error;
+ 	char *filename;
+@@ -232,23 +245,25 @@ unsigned long get_wchan(struct task_struct *p)
+ 
+ void finish_atomic_sections (struct pt_regs *regs)
+ {
++	int __user *up0 = (int __user *)&regs->p0;
++
+ 	if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END)
+ 		return;
+ 
+ 	switch (regs->pc) {
+ 	case ATOMIC_XCHG32 + 2:
+-		put_user(regs->r1, (int *)regs->p0);
++		put_user(regs->r1, up0);
+ 		regs->pc += 2;
+ 		break;
+ 
+ 	case ATOMIC_CAS32 + 2:
+ 	case ATOMIC_CAS32 + 4:
+ 		if (regs->r0 == regs->r1)
+-			put_user(regs->r2, (int *)regs->p0);
++			put_user(regs->r2, up0);
+ 		regs->pc = ATOMIC_CAS32 + 8;
+ 		break;
+ 	case ATOMIC_CAS32 + 6:
+-		put_user(regs->r2, (int *)regs->p0);
++		put_user(regs->r2, up0);
+ 		regs->pc += 2;
+ 		break;
+ 
+@@ -256,7 +271,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ 		regs->r0 = regs->r1 + regs->r0;
+ 		/* fall through */
+ 	case ATOMIC_ADD32 + 4:
+-		put_user(regs->r0, (int *)regs->p0);
++		put_user(regs->r0, up0);
+ 		regs->pc = ATOMIC_ADD32 + 6;
+ 		break;
+ 
+@@ -264,7 +279,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ 		regs->r0 = regs->r1 - regs->r0;
+ 		/* fall through */
+ 	case ATOMIC_SUB32 + 4:
+-		put_user(regs->r0, (int *)regs->p0);
++		put_user(regs->r0, up0);
+ 		regs->pc = ATOMIC_SUB32 + 6;
+ 		break;
+ 
+@@ -272,7 +287,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ 		regs->r0 = regs->r1 | regs->r0;
+ 		/* fall through */
+ 	case ATOMIC_IOR32 + 4:
+-		put_user(regs->r0, (int *)regs->p0);
++		put_user(regs->r0, up0);
+ 		regs->pc = ATOMIC_IOR32 + 6;
+ 		break;
+ 
+@@ -280,7 +295,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ 		regs->r0 = regs->r1 & regs->r0;
+ 		/* fall through */
+ 	case ATOMIC_AND32 + 4:
+-		put_user(regs->r0, (int *)regs->p0);
++		put_user(regs->r0, up0);
+ 		regs->pc = ATOMIC_AND32 + 6;
+ 		break;
+ 
+@@ -288,7 +303,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ 		regs->r0 = regs->r1 ^ regs->r0;
+ 		/* fall through */
+ 	case ATOMIC_XOR32 + 4:
+-		put_user(regs->r0, (int *)regs->p0);
++		put_user(regs->r0, up0);
+ 		regs->pc = ATOMIC_XOR32 + 6;
+ 		break;
+ 	}
+@@ -309,6 +324,12 @@ int _access_ok(unsigned long addr, unsigned long size)
+ 		return 1;
+ 	if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end)
+ 		return 1;
++
++#ifdef CONFIG_ROMFS_MTD_FS
++	/* For XIP, allow user space to use pointers within the ROMFS.  */
++	if (addr >= memory_mtd_start && (addr + size) <= memory_mtd_end)
++		return 1;
++#endif
+ #else
+ 	if (addr >= memory_start && (addr + size) <= physical_mem_end)
+ 		return 1;
+diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
+index 85caf9b..b4f062c 100644
+--- a/arch/blackfin/kernel/ptrace.c
++++ b/arch/blackfin/kernel/ptrace.c
+@@ -193,6 +193,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ {
+ 	int ret;
+ 	int add = 0;
++	unsigned long __user *datap = (unsigned long __user *)data;
+ 
+ 	switch (request) {
+ 		/* when I and D space are separate, these will need to be fixed. */
+@@ -229,7 +230,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ 			pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp);
+ 			if (copied != sizeof(tmp))
+ 				break;
+-			ret = put_user(tmp, (unsigned long *)data);
++			ret = put_user(tmp, datap);
+ 			break;
+ 		}
+ 
+@@ -263,7 +264,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ 			} else {
+ 				tmp = get_reg(child, addr);
+ 			}
+-			ret = put_user(tmp, (unsigned long *)data);
++			ret = put_user(tmp, datap);
+ 			break;
+ 		}
+ 
+@@ -389,7 +390,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ 		{
+ 
+ 			/* Get all gp regs from the child. */
+-			ret = ptrace_getregs(child, (void __user *)data);
++			ret = ptrace_getregs(child, datap);
+ 			break;
+ 		}
+ 
+diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c
+index 483f93d..367e2dc 100644
+--- a/arch/blackfin/kernel/reboot.c
++++ b/arch/blackfin/kernel/reboot.c
+@@ -11,45 +11,56 @@
+ #include <asm/reboot.h>
+ #include <asm/system.h>
+ 
+-#if defined(BF537_FAMILY) || defined(BF533_FAMILY) || defined(BF527_FAMILY)
+-#define SYSCR_VAL 	0x0
+-#elif defined(BF561_FAMILY)
+-#define SYSCR_VAL 	0x20
+-#elif defined(BF548_FAMILY)
+-#define SYSCR_VAL 	0x10
+-#endif
+-
+-/*
+- * Delay min 5 SCLK cycles using worst case CCLK/SCLK ratio (15)
+- */
+-#define SWRST_DELAY	(5 * 15)
+-
+-/* A system soft reset makes external memory unusable
+- * so force this function into L1.
++/* A system soft reset makes external memory unusable so force
++ * this function into L1.  We use the compiler ssync here rather
++ * than SSYNC() because it's safe (no interrupts and such) and
++ * we save some L1.  We do not need to force sanity in the SYSCR
++ * register as the BMODE selection bit is cleared by the soft
++ * reset while the Core B bit (on dual core parts) is cleared by
++ * the core reset.
+  */
+ __attribute__((l1_text))
+ void bfin_reset(void)
+ {
+-	/* force BMODE and disable Core B (as needed) */
+-	bfin_write_SYSCR(SYSCR_VAL);
+-
+-	/* we use asm ssync here because it's save and we save some L1 */
+-	asm("ssync;");
++	/* Wait for completion of "system" events such as cache line
++	 * line fills so that we avoid infinite stalls later on as
++	 * much as possible.  This code is in L1, so it won't trigger
++	 * any such event after this point in time.
++	 */
++	__builtin_bfin_ssync();
+ 
+ 	while (1) {
+-		/* initiate system soft reset with magic 0x7 */
++		/* Initiate System software reset. */
+ 		bfin_write_SWRST(0x7);
+ 
+-		/* Wait for System reset to actually reset, needs to be 5 SCLKs, */
+-		/* Assume CCLK / SCLK ratio is worst case (15), and use 5*15     */
+-
+-		asm("LSETUP(.Lfoo,.Lfoo) LC0 = %0\n .Lfoo: NOP;\n"
+-		 : : "a" (SWRST_DELAY) : "LC0", "LT0", "LB0");
++		/* Due to the way reset is handled in the hardware, we need
++		 * to delay for 7 SCLKS.  The only reliable way to do this is
++		 * to calculate the CCLK/SCLK ratio and multiply 7.  For now,
++		 * we'll assume worse case which is a 1:15 ratio.
++		 */
++		asm(
++			"LSETUP (1f, 1f) LC0 = %0\n"
++			"1: nop;"
++			:
++			: "a" (15 * 7)
++			: "LC0", "LB0", "LT0"
++		);
+ 
+-		/* clear system soft reset */
++		/* Clear System software reset */
+ 		bfin_write_SWRST(0);
+-		asm("ssync;");
+-		/* issue core reset */
++
++		/* Wait for the SWRST write to complete.  Cannot rely on SSYNC
++		 * though as the System state is all reset now.
++		 */
++		asm(
++			"LSETUP (1f, 1f) LC1 = %0\n"
++			"1: nop;"
++			:
++			: "a" (15 * 1)
++			: "LC1", "LB1", "LT1"
++		);
++
++		/* Issue core reset */
+ 		asm("raise 1");
+ 	}
+ }
+diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
+index 2255c28..8efea00 100644
+--- a/arch/blackfin/kernel/setup.c
++++ b/arch/blackfin/kernel/setup.c
+@@ -35,6 +35,7 @@ u16 _bfin_swrst;
+ EXPORT_SYMBOL(_bfin_swrst);
+ 
+ unsigned long memory_start, memory_end, physical_mem_end;
++unsigned long _rambase, _ramstart, _ramend;
+ unsigned long reserved_mem_dcache_on;
+ unsigned long reserved_mem_icache_on;
+ EXPORT_SYMBOL(memory_start);
+@@ -106,7 +107,7 @@ void __init bf53x_relocate_l1_mem(void)
+ 
+ 	l1_code_length = _etext_l1 - _stext_l1;
+ 	if (l1_code_length > L1_CODE_LENGTH)
+-		l1_code_length = L1_CODE_LENGTH;
++		panic("L1 Instruction SRAM Overflow\n");
+ 	/* cannot complain as printk is not available as yet.
+ 	 * But we can continue booting and complain later!
+ 	 */
+@@ -116,19 +117,18 @@ void __init bf53x_relocate_l1_mem(void)
+ 
+ 	l1_data_a_length = _ebss_l1 - _sdata_l1;
+ 	if (l1_data_a_length > L1_DATA_A_LENGTH)
+-		l1_data_a_length = L1_DATA_A_LENGTH;
++		panic("L1 Data SRAM Bank A Overflow\n");
+ 
+ 	/* Copy _sdata_l1 to _ebss_l1 to L1 data bank A SRAM */
+ 	dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
+ 
+ 	l1_data_b_length = _ebss_b_l1 - _sdata_b_l1;
+ 	if (l1_data_b_length > L1_DATA_B_LENGTH)
+-		l1_data_b_length = L1_DATA_B_LENGTH;
++		panic("L1 Data SRAM Bank B Overflow\n");
+ 
+ 	/* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */
+ 	dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
+ 			l1_data_a_length, l1_data_b_length);
+-
+ }
+ 
+ /* add_memory_region to memmap */
+@@ -547,11 +547,38 @@ static __init void  memory_setup(void)
+ 		);
+ }
+ 
++/*
++ * Find the lowest, highest page frame number we have available
++ */
++void __init find_min_max_pfn(void)
++{
++	int i;
++
++	max_pfn = 0;
++	min_low_pfn = memory_end;
++
++	for (i = 0; i < bfin_memmap.nr_map; i++) {
++		unsigned long start, end;
++		/* RAM? */
++		if (bfin_memmap.map[i].type != BFIN_MEMMAP_RAM)
++			continue;
++		start = PFN_UP(bfin_memmap.map[i].addr);
++		end = PFN_DOWN(bfin_memmap.map[i].addr +
++				bfin_memmap.map[i].size);
++		if (start >= end)
++			continue;
++		if (end > max_pfn)
++			max_pfn = end;
++		if (start < min_low_pfn)
++			min_low_pfn = start;
++	}
++}
++
+ static __init void setup_bootmem_allocator(void)
+ {
+ 	int bootmap_size;
+ 	int i;
+-	unsigned long min_pfn, max_pfn;
++	unsigned long start_pfn, end_pfn;
+ 	unsigned long curr_pfn, last_pfn, size;
+ 
+ 	/* mark memory between memory_start and memory_end usable */
+@@ -561,8 +588,19 @@ static __init void setup_bootmem_allocator(void)
+ 	sanitize_memmap(bfin_memmap.map, &bfin_memmap.nr_map);
+ 	print_memory_map("boot memmap");
+ 
+-	min_pfn = PAGE_OFFSET >> PAGE_SHIFT;
+-	max_pfn = memory_end >> PAGE_SHIFT;
++	/* intialize globals in linux/bootmem.h */
++	find_min_max_pfn();
++	/* pfn of the last usable page frame */
++	if (max_pfn > memory_end >> PAGE_SHIFT)
++		max_pfn = memory_end >> PAGE_SHIFT;
++	/* pfn of last page frame directly mapped by kernel */
++	max_low_pfn = max_pfn;
++	/* pfn of the first usable page frame after kernel image*/
++	if (min_low_pfn < memory_start >> PAGE_SHIFT)
++		min_low_pfn = memory_start >> PAGE_SHIFT;
++
++	start_pfn = PAGE_OFFSET >> PAGE_SHIFT;
++	end_pfn = memory_end >> PAGE_SHIFT;
+ 
+ 	/*
+ 	 * give all the memory to the bootmap allocator,  tell it to put the
+@@ -570,7 +608,7 @@ static __init void setup_bootmem_allocator(void)
+ 	 */
+ 	bootmap_size = init_bootmem_node(NODE_DATA(0),
+ 			memory_start >> PAGE_SHIFT,	/* map goes here */
+-			min_pfn, max_pfn);
++			start_pfn, end_pfn);
+ 
+ 	/* register the memmap regions with the bootmem allocator */
+ 	for (i = 0; i < bfin_memmap.nr_map; i++) {
+@@ -583,7 +621,7 @@ static __init void setup_bootmem_allocator(void)
+ 		 * We are rounding up the start address of usable memory:
+ 		 */
+ 		curr_pfn = PFN_UP(bfin_memmap.map[i].addr);
+-		if (curr_pfn >= max_pfn)
++		if (curr_pfn >= end_pfn)
+ 			continue;
+ 		/*
+ 		 * ... and at the end of the usable range downwards:
+@@ -591,8 +629,8 @@ static __init void setup_bootmem_allocator(void)
+ 		last_pfn = PFN_DOWN(bfin_memmap.map[i].addr +
+ 					 bfin_memmap.map[i].size);
+ 
+-		if (last_pfn > max_pfn)
+-			last_pfn = max_pfn;
++		if (last_pfn > end_pfn)
++			last_pfn = end_pfn;
+ 
+ 		/*
+ 		 * .. finally, did all the rounding and playing
+@@ -611,9 +649,59 @@ static __init void setup_bootmem_allocator(void)
+ 		BOOTMEM_DEFAULT);
+ }
+ 
++#define EBSZ_TO_MEG(ebsz) \
++({ \
++	int meg = 0; \
++	switch (ebsz & 0xf) { \
++		case 0x1: meg =  16; break; \
++		case 0x3: meg =  32; break; \
++		case 0x5: meg =  64; break; \
++		case 0x7: meg = 128; break; \
++		case 0x9: meg = 256; break; \
++		case 0xb: meg = 512; break; \
++	} \
++	meg; \
++})
++static inline int __init get_mem_size(void)
++{
++#ifdef CONFIG_MEM_SIZE
++	return CONFIG_MEM_SIZE;
++#else
++# if defined(EBIU_SDBCTL)
++#  if defined(BF561_FAMILY)
++	int ret = 0;
++	u32 sdbctl = bfin_read_EBIU_SDBCTL();
++	ret += EBSZ_TO_MEG(sdbctl >>  0);
++	ret += EBSZ_TO_MEG(sdbctl >>  8);
++	ret += EBSZ_TO_MEG(sdbctl >> 16);
++	ret += EBSZ_TO_MEG(sdbctl >> 24);
++	return ret;
++#  else
++	return EBSZ_TO_MEG(bfin_read_EBIU_SDBCTL());
++#  endif
++# elif defined(EBIU_DDRCTL1)
++	u32 ddrctl = bfin_read_EBIU_DDRCTL1();
++	int ret = 0;
++	switch (ddrctl & 0xc0000) {
++		case DEVSZ_64:  ret = 64 / 8;
++		case DEVSZ_128: ret = 128 / 8;
++		case DEVSZ_256: ret = 256 / 8;
++		case DEVSZ_512: ret = 512 / 8;
++	}
++	switch (ddrctl & 0x30000) {
++		case DEVWD_4:  ret *= 2;
++		case DEVWD_8:  ret *= 2;
++		case DEVWD_16: break;
++	}
++	return ret;
++# endif
++#endif
++	BUG();
++}
++
+ void __init setup_arch(char **cmdline_p)
+ {
+-	unsigned long l1_length, sclk, cclk;
++	unsigned long sclk, cclk;
+ 
+ #ifdef CONFIG_DUMMY_CONSOLE
+ 	conswitchp = &dummy_con;
+@@ -631,7 +719,7 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	/* setup memory defaults from the user config */
+ 	physical_mem_end = 0;
+-	_ramend = CONFIG_MEM_SIZE * 1024 * 1024;
++	_ramend = get_mem_size() * 1024 * 1024;
+ 
+ 	memset(&bfin_memmap, 0, sizeof(bfin_memmap));
+ 
+@@ -712,15 +800,6 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	paging_init();
+ 
+-	/* check the size of the l1 area */
+-	l1_length = _etext_l1 - _stext_l1;
+-	if (l1_length > L1_CODE_LENGTH)
+-		panic("L1 code memory overflow\n");
+-
+-	l1_length = _ebss_l1 - _sdata_l1;
+-	if (l1_length > L1_DATA_A_LENGTH)
+-		panic("L1 data memory overflow\n");
+-
+ 	/* Copy atomic sequences to their fixed location, and sanity check that
+ 	   these locations are the ones that we advertise to userspace.  */
+ 	memcpy((void *)FIXED_CODE_START, &fixed_code_start,
+@@ -859,12 +938,17 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ 	seq_printf(m, "processor\t: %d\n"
+ 		"vendor_id\t: %s\n"
+ 		"cpu family\t: 0x%x\n"
+-		"model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK)\n"
++		"model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n"
+ 		"stepping\t: %d\n",
+ 		0,
+ 		vendor,
+ 		(bfin_read_CHIPID() & CHIPID_FAMILY),
+ 		cpu, cclk/1000000, sclk/1000000,
++#ifdef CONFIG_MPU
++		"mpu on",
++#else
++		"mpu off",
++#endif
+ 		revid);
+ 
+ 	seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n",
+@@ -973,7 +1057,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ 		seq_printf(m, "No Ways are locked\n");
+ 	}
+ #endif
+-
+ 	seq_printf(m, "board name\t: %s\n", bfin_board_name);
+ 	seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n",
+ 		 physical_mem_end >> 10, (void *)0, (void *)physical_mem_end);
+diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
+index 5564c95..d1fa244 100644
+--- a/arch/blackfin/kernel/signal.c
++++ b/arch/blackfin/kernel/signal.c
+@@ -38,6 +38,7 @@
+ 
+ #include <asm/cacheflush.h>
+ #include <asm/ucontext.h>
++#include <asm/fixed_code.h>
+ 
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+ 
+@@ -50,18 +51,20 @@ struct rt_sigframe {
+ 	int sig;
+ 	struct siginfo *pinfo;
+ 	void *puc;
++	/* This is no longer needed by the kernel, but unfortunately userspace
++	 * code expects it to be there.  */
+ 	char retcode[8];
+ 	struct siginfo info;
+ 	struct ucontext uc;
+ };
+ 
+-asmlinkage int sys_sigaltstack(const stack_t * uss, stack_t * uoss)
++asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+ {
+ 	return do_sigaltstack(uss, uoss, rdusp());
+ }
+ 
+ static inline int
+-rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *pr0)
++rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *pr0)
+ {
+ 	unsigned long usp = 0;
+ 	int err = 0;
+@@ -159,11 +162,6 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg
+ 	return err;
+ }
+ 
+-static inline void push_cache(unsigned long vaddr, unsigned int len)
+-{
+-	flush_icache_range(vaddr, vaddr + len);
+-}
+-
+ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ 				 size_t frame_size)
+ {
+@@ -209,19 +207,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
+ 	err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs);
+ 	err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ 
+-	/* Set up to return from userspace.  */
+-	err |= __put_user(0x28, &(frame->retcode[0]));
+-	err |= __put_user(0xe1, &(frame->retcode[1]));
+-	err |= __put_user(0xad, &(frame->retcode[2]));
+-	err |= __put_user(0x00, &(frame->retcode[3]));
+-	err |= __put_user(0xa0, &(frame->retcode[4]));
+-	err |= __put_user(0x00, &(frame->retcode[5]));
+-
+ 	if (err)
+ 		goto give_sigsegv;
+ 
+-	push_cache((unsigned long)&frame->retcode, sizeof(frame->retcode));
+-
+ 	/* Set up registers for signal handler */
+ 	wrusp((unsigned long)frame);
+ 	if (get_personality & FDPIC_FUNCPTRS) {
+@@ -231,7 +219,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
+ 		__get_user(regs->p3, &funcptr->GOT);
+ 	} else
+ 		regs->pc = (unsigned long)ka->sa.sa_handler;
+-	regs->rets = (unsigned long)(frame->retcode);
++	regs->rets = SIGRETURN_STUB;
+ 
+ 	regs->r0 = frame->sig;
+ 	regs->r1 = (unsigned long)(&frame->info);
+diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c
+index abcd148..efb7b25 100644
+--- a/arch/blackfin/kernel/sys_bfin.c
++++ b/arch/blackfin/kernel/sys_bfin.c
+@@ -49,7 +49,7 @@
+  * sys_pipe() is the normal C calling standard for creating
+  * a pipe. It's not the way unix traditionally does this, though.
+  */
+-asmlinkage int sys_pipe(unsigned long *fildes)
++asmlinkage int sys_pipe(unsigned long __user *fildes)
+ {
+ 	int fd[2];
+ 	int error;
+diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
+new file mode 100644
+index 0000000..4482c47
+--- /dev/null
++++ b/arch/blackfin/kernel/time-ts.c
+@@ -0,0 +1,219 @@
++/*
++ * linux/arch/kernel/time-ts.c
++ *
++ * Based on arm clockevents implementation and old bfin time tick.
++ *
++ * Copyright(C) 2008, GeoTechnologies, Vitja Makarov
++ *
++ * This code is licenced under the GPL version 2. For details see
++ * kernel-base/COPYING.
++ */
++#include <linux/module.h>
++#include <linux/profile.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/timex.h>
++#include <linux/irq.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++#include <linux/cpufreq.h>
++
++#include <asm/blackfin.h>
++#include <asm/time.h>
++
++#ifdef CONFIG_CYCLES_CLOCKSOURCE
++
++/* Accelerators for sched_clock()
++ * convert from cycles(64bits) => nanoseconds (64bits)
++ *  basic equation:
++ *		ns = cycles / (freq / ns_per_sec)
++ *		ns = cycles * (ns_per_sec / freq)
++ *		ns = cycles * (10^9 / (cpu_khz * 10^3))
++ *		ns = cycles * (10^6 / cpu_khz)
++ *
++ *	Then we use scaling math (suggested by george at mvista.com) to get:
++ *		ns = cycles * (10^6 * SC / cpu_khz) / SC
++ *		ns = cycles * cyc2ns_scale / SC
++ *
++ *	And since SC is a constant power of two, we can convert the div
++ *  into a shift.
++ *
++ *  We can use khz divisor instead of mhz to keep a better precision, since
++ *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
++ *  (mathieu.desnoyers at polymtl.ca)
++ *
++ *			-johnstul at us.ibm.com "math is hard, lets go shopping!"
++ */
++
++static unsigned long cyc2ns_scale;
++#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
++
++static inline void set_cyc2ns_scale(unsigned long cpu_khz)
++{
++	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR) / cpu_khz;
++}
++
++static inline unsigned long long cycles_2_ns(cycle_t cyc)
++{
++	return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
++}
++
++static cycle_t read_cycles(void)
++{
++	return get_cycles();
++}
++
++unsigned long long sched_clock(void)
++{
++	return cycles_2_ns(read_cycles());
++}
++
++static struct clocksource clocksource_bfin = {
++	.name		= "bfin_cycles",
++	.rating		= 350,
++	.read		= read_cycles,
++	.mask		= CLOCKSOURCE_MASK(64),
++	.shift		= 22,
++	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++static int __init bfin_clocksource_init(void)
++{
++	set_cyc2ns_scale(get_cclk() / 1000);
++
++	clocksource_bfin.mult = clocksource_hz2mult(get_cclk(), clocksource_bfin.shift);
++
++	if (clocksource_register(&clocksource_bfin))
++		panic("failed to register clocksource");
++
++	return 0;
++}
++
++#else
++# define bfin_clocksource_init()
++#endif
++
++static int bfin_timer_set_next_event(unsigned long cycles,
++                                     struct clock_event_device *evt)
++{
++	bfin_write_TCOUNT(cycles);
++	CSYNC();
++	return 0;
++}
++
++static void bfin_timer_set_mode(enum clock_event_mode mode,
++                                struct clock_event_device *evt)
++{
++	switch (mode) {
++	case CLOCK_EVT_MODE_PERIODIC: {
++		unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
++		bfin_write_TCNTL(TMPWR);
++		bfin_write_TSCALE(TIME_SCALE - 1);
++		CSYNC();
++		bfin_write_TPERIOD(tcount);
++		bfin_write_TCOUNT(tcount);
++		bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD);
++		CSYNC();
++		break;
++	}
++	case CLOCK_EVT_MODE_ONESHOT:
++		bfin_write_TSCALE(0);
++		bfin_write_TCOUNT(0);
++		bfin_write_TCNTL(TMPWR | TMREN);
++		CSYNC();
++		break;
++	case CLOCK_EVT_MODE_UNUSED:
++	case CLOCK_EVT_MODE_SHUTDOWN:
++		bfin_write_TCNTL(0);
++		CSYNC();
++		break;
++	case CLOCK_EVT_MODE_RESUME:
++		break;
++	}
++}
++
++static void __init bfin_timer_init(void)
++{
++	/* power up the timer, but don't enable it just yet */
++	bfin_write_TCNTL(TMPWR);
++	CSYNC();
++
++	/*
++	 * the TSCALE prescaler counter.
++	 */
++	bfin_write_TSCALE(TIME_SCALE - 1);
++	bfin_write_TPERIOD(0);
++	bfin_write_TCOUNT(0);
++
++	/* now enable the timer */
++	CSYNC();
++}
++
++/*
++ * timer_interrupt() needs to keep up the real-time clock,
++ * as well as call the "do_timer()" routine every clocktick
++ */
++#ifdef CONFIG_CORE_TIMER_IRQ_L1
++__attribute__((l1_text))
++#endif
++irqreturn_t timer_interrupt(int irq, void *dev_id);
++
++static struct clock_event_device clockevent_bfin = {
++	.name		= "bfin_core_timer",
++	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++	.shift		= 32,
++	.cpumask	= CPU_MASK_CPU0,
++	.set_next_event = bfin_timer_set_next_event,
++	.set_mode	= bfin_timer_set_mode,
++};
++
++static struct irqaction bfin_timer_irq = {
++	.name		= "Blackfin Core Timer",
++	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++	.handler	= timer_interrupt,
++	.dev_id		= &clockevent_bfin,
++};
++
++irqreturn_t timer_interrupt(int irq, void *dev_id)
++{
++	struct clock_event_device *evt = dev_id;
++	evt->event_handler(evt);
++	return IRQ_HANDLED;
++}
++
++static int __init bfin_clockevent_init(void)
++{
++	setup_irq(IRQ_CORETMR, &bfin_timer_irq);
++	bfin_timer_init();
++
++	clockevent_bfin.mult = div_sc(get_cclk(), NSEC_PER_SEC, clockevent_bfin.shift);
++	clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
++	clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
++	clockevents_register_device(&clockevent_bfin);
++
++	return 0;
++}
++
++void __init time_init(void)
++{
++	time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60;	/* 1 Jan 2007 */
++
++#ifdef CONFIG_RTC_DRV_BFIN
++	/* [#2663] hack to filter junk RTC values that would cause
++	 * userspace to have to deal with time values greater than
++	 * 2^31 seconds (which uClibc cannot cope with yet)
++	 */
++	if ((bfin_read_RTC_STAT() & 0xC0000000) == 0xC0000000) {
++		printk(KERN_NOTICE "bfin-rtc: invalid date; resetting\n");
++		bfin_write_RTC_STAT(0);
++	}
++#endif
++
++	/* Initialize xtime. From now on, xtime is updated with timer interrupts */
++	xtime.tv_sec = secs_since_1970;
++	xtime.tv_nsec = 0;
++	set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
++
++	bfin_clocksource_init();
++	bfin_clockevent_init();
++}
+diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
+index 9bdc8f9..eb23523 100644
+--- a/arch/blackfin/kernel/time.c
++++ b/arch/blackfin/kernel/time.c
+@@ -6,9 +6,10 @@
+  * Created:
+  * Description:  This file contains the bfin-specific time handling details.
+  *               Most of the stuff is located in the machine specific files.
++ *		 FIXME: (This file is subject for removal)
+  *
+  * Modified:
+- *               Copyright 2004-2006 Analog Devices Inc.
++ *               Copyright 2004-2008 Analog Devices Inc.
+  *
+  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+  *
+@@ -35,12 +36,12 @@
+ #include <linux/irq.h>
+ 
+ #include <asm/blackfin.h>
++#include <asm/time.h>
+ 
+ /* This is an NTP setting */
+ #define	TICK_SIZE (tick_nsec / 1000)
+ 
+-static void time_sched_init(irqreturn_t(*timer_routine)
+-			(int, void *));
++static void time_sched_init(irq_handler_t timer_routine);
+ static unsigned long gettimeoffset(void);
+ 
+ static struct irqaction bfin_timer_irq = {
+@@ -48,23 +49,8 @@ static struct irqaction bfin_timer_irq = {
+ 	.flags = IRQF_DISABLED
+ };
+ 
+-/*
+- * The way that the Blackfin core timer works is:
+- *  - CCLK is divided by a programmable 8-bit pre-scaler (TSCALE)
+- *  - Every time TSCALE ticks, a 32bit is counted down (TCOUNT)
+- *
+- * If you take the fastest clock (1ns, or 1GHz to make the math work easier)
+- *    10ms is 10,000,000 clock ticks, which fits easy into a 32-bit counter
+- *    (32 bit counter is 4,294,967,296ns or 4.2 seconds) so, we don't need
+- *    to use TSCALE, and program it to zero (which is pass CCLK through).
+- *    If you feel like using it, try to keep HZ * TIMESCALE to some
+- *    value that divides easy (like power of 2).
+- */
+-
+-#define TIME_SCALE 1
+-
+ static void
+-time_sched_init(irqreturn_t(*timer_routine) (int, void *))
++time_sched_init(irq_handler_t timer_routine)
+ {
+ 	u32 tcount;
+ 
+diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
+index 56a67ab..5b84707 100644
+--- a/arch/blackfin/kernel/traps.c
++++ b/arch/blackfin/kernel/traps.c
+@@ -67,6 +67,8 @@ void __init trap_init(void)
+ 	CSYNC();
+ }
+ 
++void *saved_icplb_fault_addr, *saved_dcplb_fault_addr;
++
+ int kstack_depth_to_print = 48;
+ 
+ static void decode_address(char *buf, unsigned long address)
+@@ -75,7 +77,7 @@ static void decode_address(char *buf, unsigned long address)
+ 	struct task_struct *p;
+ 	struct mm_struct *mm;
+ 	unsigned long flags, offset;
+-	unsigned int in_exception = bfin_read_IPEND() & 0x10;
++	unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
+ 
+ #ifdef CONFIG_KALLSYMS
+ 	unsigned long symsize;
+@@ -117,7 +119,7 @@ static void decode_address(char *buf, unsigned long address)
+ 	 */
+ 	write_lock_irqsave(&tasklist_lock, flags);
+ 	for_each_process(p) {
+-		mm = (in_exception ? p->mm : get_task_mm(p));
++		mm = (in_atomic ? p->mm : get_task_mm(p));
+ 		if (!mm)
+ 			continue;
+ 
+@@ -137,23 +139,36 @@ static void decode_address(char *buf, unsigned long address)
+ 				/* FLAT does not have its text aligned to the start of
+ 				 * the map while FDPIC ELF does ...
+ 				 */
+-				if (current->mm &&
+-				    (address > current->mm->start_code) &&
+-				    (address < current->mm->end_code))
+-					offset = address - current->mm->start_code;
+-				else
+-					offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+-
+-				sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
+-					(void *)address, name, offset);
+-				if (!in_exception)
++
++				/* before we can check flat/fdpic, we need to
++				 * make sure current is valid
++				 */
++				if ((unsigned long)current >= FIXED_CODE_START &&
++				    !((unsigned long)current & 0x3)) {
++					if (current->mm &&
++					    (address > current->mm->start_code) &&
++					    (address < current->mm->end_code))
++						offset = address - current->mm->start_code;
++					else
++						offset = (address - vma->vm_start) +
++							 (vma->vm_pgoff << PAGE_SHIFT);
++
++					sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
++						(void *)address, name, offset);
++				} else
++					sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
++						(void *)address, name,
++						vma->vm_start, vma->vm_end);
++
++				if (!in_atomic)
+ 					mmput(mm);
++
+ 				goto done;
+ 			}
+ 
+ 			vml = vml->next;
+ 		}
+-		if (!in_exception)
++		if (!in_atomic)
+ 			mmput(mm);
+ 	}
+ 
+@@ -506,7 +521,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
+ 
+ 	info.si_signo = sig;
+ 	info.si_errno = 0;
+-	info.si_addr = (void *)fp->pc;
++	info.si_addr = (void __user *)fp->pc;
+ 	force_sig_info(sig, &info, current);
+ 
+ 	trace_buffer_restore(j);
+@@ -655,21 +670,31 @@ void dump_bfin_process(struct pt_regs *fp)
+ 	else if (context & 0x8000)
+ 		printk(KERN_NOTICE "Kernel process context\n");
+ 
+-	if (current->pid && current->mm) {
++	/* Because we are crashing, and pointers could be bad, we check things
++	 * pretty closely before we use them
++	 */
++	if ((unsigned long)current >= FIXED_CODE_START &&
++	    !((unsigned long)current & 0x3) && current->pid) {
+ 		printk(KERN_NOTICE "CURRENT PROCESS:\n");
+-		printk(KERN_NOTICE "COMM=%s PID=%d\n",
+-			current->comm, current->pid);
+-
+-		printk(KERN_NOTICE "TEXT = 0x%p-0x%p  DATA = 0x%p-0x%p\n"
+-			KERN_NOTICE "BSS = 0x%p-0x%p   USER-STACK = 0x%p\n"
+-			KERN_NOTICE "\n",
+-			(void *)current->mm->start_code,
+-			(void *)current->mm->end_code,
+-			(void *)current->mm->start_data,
+-			(void *)current->mm->end_data,
+-			(void *)current->mm->end_data,
+-			(void *)current->mm->brk,
+-			(void *)current->mm->start_stack);
++		if (current->comm >= (char *)FIXED_CODE_START)
++			printk(KERN_NOTICE "COMM=%s PID=%d\n",
++				current->comm, current->pid);
++		else
++			printk(KERN_NOTICE "COMM= invalid\n");
++
++		if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
++			printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
++				KERN_NOTICE " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n"
++				KERN_NOTICE "\n",
++				(void *)current->mm->start_code,
++				(void *)current->mm->end_code,
++				(void *)current->mm->start_data,
++				(void *)current->mm->end_data,
++				(void *)current->mm->end_data,
++				(void *)current->mm->brk,
++				(void *)current->mm->start_stack);
++		else
++			printk(KERN_NOTICE "invalid mm\n");
+ 	} else
+ 		printk(KERN_NOTICE "\n" KERN_NOTICE
+ 		     "No Valid process in current context\n");
+@@ -680,10 +705,7 @@ void dump_bfin_mem(struct pt_regs *fp)
+ 	unsigned short *addr, *erraddr, val = 0, err = 0;
+ 	char sti = 0, buf[6];
+ 
+-	if (unlikely((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR))
+-		erraddr = (void *)fp->pc;
+-	else
+-		erraddr = (void *)fp->retx;
++	erraddr = (void *)fp->pc;
+ 
+ 	printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
+ 
+@@ -807,9 +829,9 @@ unlock:
+ 
+ 	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
+ 	    (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
+-		decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
++		decode_address(buf, saved_dcplb_fault_addr);
+ 		printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
+-		decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());
++		decode_address(buf, saved_icplb_fault_addr);
+ 		printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
+ 	}
+ 
+@@ -917,8 +939,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
+ 
+ 	oops_in_progress = 1;
+ 
+-	printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
+-	printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
++	printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", saved_dcplb_fault_addr);
++	printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", saved_icplb_fault_addr);
+ 	dump_bfin_process(fp);
+ 	dump_bfin_mem(fp);
+ 	show_regs(fp);
+diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
+index cb01a9d..3ecc64c 100644
+--- a/arch/blackfin/kernel/vmlinux.lds.S
++++ b/arch/blackfin/kernel/vmlinux.lds.S
+@@ -56,6 +56,10 @@ SECTIONS
+ 		*(.text.*)
+ 		*(.fixup)
+ 
++#if !L1_CODE_LENGTH
++		*(.l1.text)
++#endif
++
+ 		. = ALIGN(16);
+ 		___start___ex_table = .;
+ 		*(__ex_table)
+@@ -73,6 +77,12 @@ SECTIONS
+ 		___bss_start = .;
+ 		*(.bss .bss.*)
+ 		*(COMMON)
++#if !L1_DATA_A_LENGTH
++		*(.l1.bss)
++#endif
++#if !L1_DATA_B_LENGTH
++		*(.l1.bss.B)
++#endif
+ 		___bss_stop = .;
+ 	}
+ 
+@@ -83,6 +93,15 @@ SECTIONS
+ 		. = ALIGN(32);
+ 		*(.data.cacheline_aligned)
+ 
++#if !L1_DATA_A_LENGTH
++		. = ALIGN(32);
++		*(.data_l1.cacheline_aligned)
++		*(.l1.data)
++#endif
++#if !L1_DATA_B_LENGTH
++		*(.l1.data.B)
++#endif
++
+ 		DATA_DATA
+ 		*(.data.*)
+ 		CONSTRUCTORS
+@@ -147,64 +166,43 @@ SECTIONS
+ 
+ 	__l1_lma_start = .;
+ 
+-#if L1_CODE_LENGTH
+-# define LDS_L1_CODE *(.l1.text)
+-#else
+-# define LDS_L1_CODE
+-#endif
+ 	.text_l1 L1_CODE_START : AT(LOADADDR(.init.ramfs) + SIZEOF(.init.ramfs))
+ 	{
+ 		. = ALIGN(4);
+ 		__stext_l1 = .;
+-		LDS_L1_CODE
++		*(.l1.text)
+ 		. = ALIGN(4);
+ 		__etext_l1 = .;
+ 	}
+ 
+-#if L1_DATA_A_LENGTH
+-# define LDS_L1_A_DATA  *(.l1.data)
+-# define LDS_L1_A_BSS   *(.l1.bss)
+-# define LDS_L1_A_CACHE *(.data_l1.cacheline_aligned)
+-#else
+-# define LDS_L1_A_DATA
+-# define LDS_L1_A_BSS
+-# define LDS_L1_A_CACHE
+-#endif
+ 	.data_l1 L1_DATA_A_START : AT(LOADADDR(.text_l1) + SIZEOF(.text_l1))
+ 	{
+ 		. = ALIGN(4);
+ 		__sdata_l1 = .;
+-		LDS_L1_A_DATA
++		*(.l1.data)
+ 		__edata_l1 = .;
+ 
+ 		. = ALIGN(4);
+ 		__sbss_l1 = .;
+-		LDS_L1_A_BSS
++		*(.l1.bss)
+ 
+ 		. = ALIGN(32);
+-		LDS_L1_A_CACHE
++		*(.data_l1.cacheline_aligned)
+ 
+ 		. = ALIGN(4);
+ 		__ebss_l1 = .;
+ 	}
+ 
+-#if L1_DATA_B_LENGTH
+-# define LDS_L1_B_DATA  *(.l1.data.B)
+-# define LDS_L1_B_BSS   *(.l1.bss.B)
+-#else
+-# define LDS_L1_B_DATA
+-# define LDS_L1_B_BSS
+-#endif
+ 	.data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
+ 	{
+ 		. = ALIGN(4);
+ 		__sdata_b_l1 = .;
+-		LDS_L1_B_DATA
++		*(.l1.data.B)
+ 		__edata_b_l1 = .;
+ 
+ 		. = ALIGN(4);
+ 		__sbss_b_l1 = .;
+-		LDS_L1_B_BSS
++		*(.l1.bss.B)
+ 
+ 		. = ALIGN(4);
+ 		__ebss_b_l1 = .;
+@@ -223,8 +221,6 @@ SECTIONS
+ 
+ 	DWARF_DEBUG
+ 
+-	NOTES
+-
+ 	/DISCARD/ :
+ 	{
+ 		EXIT_TEXT
+diff --git a/arch/blackfin/mach-bf527/Makefile b/arch/blackfin/mach-bf527/Makefile
+index 9f99f5d..4eddb58 100644
+--- a/arch/blackfin/mach-bf527/Makefile
++++ b/arch/blackfin/mach-bf527/Makefile
+@@ -5,5 +5,3 @@
+ extra-y := head.o
+ 
+ obj-y := ints-priority.o dma.o
+-
+-obj-$(CONFIG_CPU_FREQ)   += cpu.o
+diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
+index cf4bc0d..583d538 100644
+--- a/arch/blackfin/mach-bf527/boards/ezkit.c
++++ b/arch/blackfin/mach-bf527/boards/ezkit.c
+@@ -94,7 +94,7 @@ int __init bfin_isp1761_init(void)
+ {
+ 	unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+ 
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+ 
+ 	return platform_add_devices(bfin_isp1761_devices, num_devices);
+@@ -416,7 +416,7 @@ static struct platform_device net2272_bfin_device = {
+ static struct mtd_partition bfin_spi_flash_partitions[] = {
+ 	{
+ 		.name = "bootloader",
+-		.size = 0x00020000,
++		.size = 0x00040000,
+ 		.offset = 0,
+ 		.mask_flags = MTD_CAP_ROM
+ 	}, {
+@@ -707,6 +707,32 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++		.start = 0xFFC02000,
++		.end = 0xFFC020FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ static struct resource bfin_twi0_resource[] = {
+ 	[0] = {
+@@ -874,6 +900,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ 	&i2c_bfin_twi_device,
+ #endif
+@@ -896,7 +926,7 @@ static struct platform_device *stamp_devices[] __initdata = {
+ 
+ static int __init stamp_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info,
+diff --git a/arch/blackfin/mach-bf527/cpu.c b/arch/blackfin/mach-bf527/cpu.c
+deleted file mode 100644
+index 1975402..0000000
+--- a/arch/blackfin/mach-bf527/cpu.c
++++ /dev/null
+@@ -1,161 +0,0 @@
+-/*
+- * File:         arch/blackfin/mach-bf527/cpu.c
+- * Based on:	arch/blackfin/mach-bf537/cpu.c
+- * Author:       michael.kang at analog.com
+- *
+- * Created:
+- * Description:  clock scaling for the bf527
+- *
+- * Modified:
+- *               Copyright 2004-2007 Analog Devices Inc.
+- *
+- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/cpufreq.h>
+-#include <asm/dpmc.h>
+-#include <linux/fs.h>
+-#include <asm/bfin-global.h>
+-
+-/* CONFIG_CLKIN_HZ=11059200 */
+-#define VCO5 (CONFIG_CLKIN_HZ*45)	/*497664000 */
+-#define VCO4 (CONFIG_CLKIN_HZ*36)	/*398131200 */
+-#define VCO3 (CONFIG_CLKIN_HZ*27)	/*298598400 */
+-#define VCO2 (CONFIG_CLKIN_HZ*18)	/*199065600 */
+-#define VCO1 (CONFIG_CLKIN_HZ*9)	/*99532800 */
+-#define VCO(x) VCO##x
+-
+-#define MFREQ(x) {VCO(x), VCO(x)/4}, {VCO(x), VCO(x)/2}, {VCO(x), VCO(x)}
+-/* frequency */
+-static struct cpufreq_frequency_table bf527_freq_table[] = {
+-	MFREQ(1),
+-	MFREQ(3),
+-	{VCO4, VCO4 / 2}, {VCO4, VCO4},
+-	MFREQ(5),
+-	{0, CPUFREQ_TABLE_END},
+-};
+-
+-/*
+- * dpmc_fops->ioctl()
+- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+- */
+-static int bf527_getfreq(unsigned int cpu)
+-{
+-	unsigned long cclk_mhz;
+-
+-	/* The driver only support single cpu */
+-	if (cpu == 0)
+-		dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+-	else
+-		cclk_mhz = -1;
+-
+-	return cclk_mhz;
+-}
+-
+-static int bf527_target(struct cpufreq_policy *policy,
+-			unsigned int target_freq, unsigned int relation)
+-{
+-	unsigned long cclk_mhz;
+-	unsigned long vco_mhz;
+-	unsigned long flags;
+-	unsigned int index;
+-	struct cpufreq_freqs freqs;
+-
+-	if (cpufreq_frequency_table_target
+-	    (policy, bf527_freq_table, target_freq, relation, &index))
+-		return -EINVAL;
+-
+-	cclk_mhz = bf527_freq_table[index].frequency;
+-	vco_mhz = bf527_freq_table[index].index;
+-
+-	dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+-	freqs.old = bf527_getfreq(0);
+-	freqs.new = cclk_mhz;
+-	freqs.cpu = 0;
+-
+-	pr_debug
+-	    ("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+-	     cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+-
+-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+-	local_irq_save(flags);
+-	dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+-	local_irq_restore(flags);
+-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+-
+-	vco_mhz = get_vco();
+-	cclk_mhz = get_cclk();
+-	return 0;
+-}
+-
+-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+- * this platform, anyway.
+- */
+-static int bf527_verify_speed(struct cpufreq_policy *policy)
+-{
+-	return cpufreq_frequency_table_verify(policy, &bf527_freq_table);
+-}
+-
+-static int __init __bf527_cpu_init(struct cpufreq_policy *policy)
+-{
+-	if (policy->cpu != 0)
+-		return -EINVAL;
+-
+-	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+-
+-	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+-	/*Now ,only support one cpu */
+-	policy->cur = bf527_getfreq(0);
+-	cpufreq_frequency_table_get_attr(bf527_freq_table, policy->cpu);
+-	return cpufreq_frequency_table_cpuinfo(policy, bf527_freq_table);
+-}
+-
+-static struct freq_attr *bf527_freq_attr[] = {
+-	&cpufreq_freq_attr_scaling_available_freqs,
+-	NULL,
+-};
+-
+-static struct cpufreq_driver bf527_driver = {
+-	.verify = bf527_verify_speed,
+-	.target = bf527_target,
+-	.get = bf527_getfreq,
+-	.init = __bf527_cpu_init,
+-	.name = "bf527",
+-	.owner = THIS_MODULE,
+-	.attr = bf527_freq_attr,
+-};
+-
+-static int __init bf527_cpu_init(void)
+-{
+-	return cpufreq_register_driver(&bf527_driver);
+-}
+-
+-static void __exit bf527_cpu_exit(void)
+-{
+-	cpufreq_unregister_driver(&bf527_driver);
+-}
+-
+-MODULE_AUTHOR("Mickael Kang");
+-MODULE_DESCRIPTION("cpufreq driver for bf527 CPU");
+-MODULE_LICENSE("GPL");
+-
+-module_init(bf527_cpu_init);
+-module_exit(bf527_cpu_exit);
+diff --git a/arch/blackfin/mach-bf527/dma.c b/arch/blackfin/mach-bf527/dma.c
+index 522de24..dfd080c 100644
+--- a/arch/blackfin/mach-bf527/dma.c
++++ b/arch/blackfin/mach-bf527/dma.c
+@@ -26,10 +26,12 @@
+  * to the Free Software Foundation, Inc.,
+  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+  */
++#include <linux/module.h>
++
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+ 
+-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
+@@ -47,6 +49,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ 	(struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ 	(struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+ };
++EXPORT_SYMBOL(dma_io_base_addr);
+ 
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf527/head.S b/arch/blackfin/mach-bf527/head.S
+index cdb00a0..57bdb3b 100644
+--- a/arch/blackfin/mach-bf527/head.S
++++ b/arch/blackfin/mach-bf527/head.S
+@@ -37,9 +37,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+ 
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -439,18 +436,3 @@ ENTRY(_start_dma_code)
+ 	RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long   0
+-__ramstart:
+-.long   0
+-__ramend:
+-.long   0
+diff --git a/arch/blackfin/mach-bf533/Makefile b/arch/blackfin/mach-bf533/Makefile
+index 8cce173..aa9f264 100644
+--- a/arch/blackfin/mach-bf533/Makefile
++++ b/arch/blackfin/mach-bf533/Makefile
+@@ -5,5 +5,3 @@
+ extra-y := head.o
+ 
+ obj-y := ints-priority.o dma.o
+-
+-obj-$(CONFIG_CPU_FREQ)   += cpu.o
+diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
+index 97378b0..7cc4864 100644
+--- a/arch/blackfin/mach-bf533/boards/H8606.c
++++ b/arch/blackfin/mach-bf533/boards/H8606.c
+@@ -304,6 +304,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+ 
+ #include <linux/serial_8250.h>
+@@ -403,6 +422,10 @@ static struct platform_device *h8606_devices[] __initdata = {
+ 	&serial8250_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_KEYBOARD_OPENCORES) || defined(CONFIG_KEYBOARD_OPENCORES_MODULE)
+ 	&opencores_kbd_device,
+ #endif
+@@ -411,7 +434,7 @@ static struct platform_device *h8606_devices[] __initdata = {
+ static int __init H8606_init(void)
+ {
+ 	printk(KERN_INFO "HV Sistemas H8606 board support by http://www.hvsistemas.com\n");
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	platform_add_devices(h8606_devices, ARRAY_SIZE(h8606_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf533/boards/Kconfig b/arch/blackfin/mach-bf533/boards/Kconfig
+index 751de51..8400592 100644
+--- a/arch/blackfin/mach-bf533/boards/Kconfig
++++ b/arch/blackfin/mach-bf533/boards/Kconfig
+@@ -26,6 +26,12 @@ config H8606_HVSISTEMAS
+ 	help
+ 	  HV Sistemas H8606 board support.
+ 
++config BFIN532_IP0X
++	bool "IP04/IP08 IP-PBX"
++	depends on (BF532)
++	help
++	  Core support for IP04/IP04 open hardware IP-PBX.
++
+ config GENERIC_BF533_BOARD
+ 	bool "Generic"
+ 	help
+diff --git a/arch/blackfin/mach-bf533/boards/Makefile b/arch/blackfin/mach-bf533/boards/Makefile
+index 54f57fb..b7a1a1d 100644
+--- a/arch/blackfin/mach-bf533/boards/Makefile
++++ b/arch/blackfin/mach-bf533/boards/Makefile
+@@ -4,6 +4,7 @@
+ 
+ obj-$(CONFIG_GENERIC_BF533_BOARD)      += generic_board.o
+ obj-$(CONFIG_BFIN533_STAMP)            += stamp.o
++obj-$(CONFIG_BFIN532_IP0X)             += ip0x.o
+ obj-$(CONFIG_BFIN533_EZKIT)            += ezkit.o
+ obj-$(CONFIG_BFIN533_BLUETECHNIX_CM)   += cm_bf533.o
+ obj-$(CONFIG_H8606_HVSISTEMAS)         += H8606.o
+diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
+index 886f260..a03149c 100644
+--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
++++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
+@@ -234,6 +234,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ static struct platform_device bfin_sport0_uart_device = {
+ 	.name = "bfin-sport-uart",
+@@ -327,6 +346,10 @@ static struct platform_device *cm_bf533_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ 	&bfin_sport0_uart_device,
+ 	&bfin_sport1_uart_device,
+@@ -355,7 +378,7 @@ static struct platform_device *cm_bf533_devices[] __initdata = {
+ 
+ static int __init cm_bf533_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	platform_add_devices(cm_bf533_devices, ARRAY_SIZE(cm_bf533_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
+index 241b5a2..08a7943 100644
+--- a/arch/blackfin/mach-bf533/boards/ezkit.c
++++ b/arch/blackfin/mach-bf533/boards/ezkit.c
+@@ -237,6 +237,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ #define PATA_INT	55
+ 
+@@ -352,6 +371,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ 	&bfin_pata_device,
+ #endif
+@@ -369,7 +392,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ 
+ static int __init ezkit_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c
+index e359a0d..82b1f6a 100644
+--- a/arch/blackfin/mach-bf533/boards/generic_board.c
++++ b/arch/blackfin/mach-bf533/boards/generic_board.c
+@@ -84,7 +84,7 @@ static struct platform_device *generic_board_devices[] __initdata = {
+ 
+ static int __init generic_board_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	return platform_add_devices(generic_board_devices, ARRAY_SIZE(generic_board_devices));
+ }
+ 
+diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
+new file mode 100644
+index 0000000..5864892
+--- /dev/null
++++ b/arch/blackfin/mach-bf533/boards/ip0x.c
+@@ -0,0 +1,303 @@
++/*
++ * File:         arch/blackfin/mach-bf533/ip0x.c
++ * Based on:     arch/blackfin/mach-bf533/bf1.c
++ * Based on:     arch/blackfin/mach-bf533/stamp.c
++ * Author:       Ivan Danov <idanov at gmail.com>
++ *               Modified for IP0X David Rowe
++ *
++ * Created:      2007
++ * Description:  Board info file for the IP04/IP08 boards, which
++ *               are derived from the BlackfinOne V2.0 boards.
++ *
++ * Modified:
++ *               COpyright 2007 David Rowe
++ *               Copyright 2006 Intratrade Ltd.
++ *               Copyright 2005 National ICT Australia (NICTA)
++ *               Copyright 2004-2006 Analog Devices Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see the file COPYING, or write
++ * to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ */
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
++#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
++#include <linux/usb/isp1362.h>
++#endif
++#include <asm/irq.h>
++#include <asm/bfin5xx_spi.h>
++
++/*
++ * Name the Board for the /proc/cpuinfo
++ */
++const char bfin_board_name[] = "IP04/IP08";
++
++/*
++ *  Driver needs to know address, irq and flag pin.
++ */
++#if defined(CONFIG_BFIN532_IP0X)
++#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
++
++#include <linux/dm9000.h>
++
++static struct resource dm9000_resource1[] = {
++	{
++		.start = 0x20100000,
++		.end   = 0x20100000 + 1,
++		.flags = IORESOURCE_MEM
++	},{
++		.start = 0x20100000 + 2,
++		.end   = 0x20100000 + 3,
++		.flags = IORESOURCE_MEM
++	},{
++		.start = IRQ_PF15,
++		.end   = IRQ_PF15,
++		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE
++	}
++};
++
++static struct resource dm9000_resource2[] = {
++	{
++		.start = 0x20200000,
++		.end   = 0x20200000 + 1,
++		.flags = IORESOURCE_MEM
++	},{
++		.start = 0x20200000 + 2,
++		.end   = 0x20200000 + 3,
++		.flags = IORESOURCE_MEM
++	},{
++		.start = IRQ_PF14,
++		.end   = IRQ_PF14,
++		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE
++	}
++};
++
++/*
++* for the moment we limit ourselves to 16bit IO until some
++* better IO routines can be written and tested
++*/
++static struct dm9000_plat_data dm9000_platdata1 = {
++	.flags          = DM9000_PLATF_16BITONLY,
++};
++
++static struct platform_device dm9000_device1 = {
++	.name           = "dm9000",
++	.id             = 0,
++	.num_resources  = ARRAY_SIZE(dm9000_resource1),
++	.resource       = dm9000_resource1,
++	.dev            = {
++		.platform_data = &dm9000_platdata1,
++	}
++};
++
++static struct dm9000_plat_data dm9000_platdata2 = {
++	.flags          = DM9000_PLATF_16BITONLY,
++};
++
++static struct platform_device dm9000_device2 = {
++	.name           = "dm9000",
++	.id             = 1,
++	.num_resources  = ARRAY_SIZE(dm9000_resource2),
++	.resource       = dm9000_resource2,
++	.dev            = {
++		.platform_data = &dm9000_platdata2,
++	}
++};
++
++#endif
++#endif
++
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++/* all SPI peripherals info goes here */
++
++#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
++static struct bfin5xx_spi_chip spi_mmc_chip_info = {
++/*
++ * CPOL (Clock Polarity)
++ *  0 - Active high SCK
++ *  1 - Active low SCK
++ *  CPHA (Clock Phase) Selects transfer format and operation mode
++ *  0 - SCLK toggles from middle of the first data bit, slave select
++ *      pins controlled by hardware.
++ *  1 - SCLK toggles from beginning of first data bit, slave select
++ *      pins controller by user software.
++ * 	.ctl_reg = 0x1c00,		 *  CPOL=1,CPHA=1,Sandisk 1G work
++ * NO NO	.ctl_reg = 0x1800,		 *  CPOL=1,CPHA=0
++ * NO NO	.ctl_reg = 0x1400,		 *  CPOL=0,CPHA=1
++ */
++	.ctl_reg = 0x1000,		/* CPOL=0,CPHA=0,Sandisk 1G work */
++	.enable_dma = 0,		/* if 1 - block!!! */
++	.bits_per_word = 8,
++	.cs_change_per_word = 0,
++};
++#endif
++
++/* Notice: for blackfin, the speed_hz is the value of register
++ * SPI_BAUD, not the real baudrate */
++static struct spi_board_info bfin_spi_board_info[] __initdata = {
++#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
++	{
++		.modalias = "spi_mmc",
++		.max_speed_hz = 2,
++		.bus_num = 1,
++		.chip_select = CONFIG_SPI_MMC_CS_CHAN,
++		.platform_data = NULL,
++		.controller_data = &spi_mmc_chip_info,
++	},
++#endif
++};
++
++/* SPI controller data */
++static struct bfin5xx_spi_master spi_bfin_master_info = {
++	.num_chipselect = 8,
++	.enable_dma = 1,  /* master has the ability to do dma transfer */
++};
++
++static struct platform_device spi_bfin_master_device = {
++	.name = "bfin-spi-master",
++	.id = 1, /* Bus number */
++	.dev = {
++		.platform_data = &spi_bfin_master_info, /* Passed to driver */
++	},
++};
++#endif  /* spi master and devices */
++
++#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
++static struct resource bfin_uart_resources[] = {
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++};
++
++static struct platform_device bfin_uart_device = {
++	.name = "bfin-uart",
++	.id = 1,
++	.num_resources = ARRAY_SIZE(bfin_uart_resources),
++	.resource = bfin_uart_resources,
++};
++#endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
++#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
++static struct resource isp1362_hcd_resources[] = {
++	{
++		.start = 0x20300000,
++		.end   = 0x20300000 + 1,
++		.flags = IORESOURCE_MEM,
++	},{
++		.start = 0x20300000 + 2,
++		.end   = 0x20300000 + 3,
++		.flags = IORESOURCE_MEM,
++	},{
++		.start = IRQ_PF11,
++		.end   = IRQ_PF11,
++		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
++	},
++};
++
++static struct isp1362_platform_data isp1362_priv = {
++	.sel15Kres = 1,
++	.clknotstop = 0,
++	.oc_enable = 0,		/* external OC */
++	.int_act_high = 0,
++	.int_edge_triggered = 0,
++	.remote_wakeup_connected = 0,
++	.no_power_switching = 1,
++	.power_switching_mode = 0,
++};
++
++static struct platform_device isp1362_hcd_device = {
++	.name = "isp1362-hcd",
++	.id = 0,
++	.dev = {
++		.platform_data = &isp1362_priv,
++	},
++	.num_resources = ARRAY_SIZE(isp1362_hcd_resources),
++	.resource = isp1362_hcd_resources,
++};
++#endif
++
++
++static struct platform_device *ip0x_devices[] __initdata = {
++#if defined(CONFIG_BFIN532_IP0X)
++#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
++	&dm9000_device1,
++	&dm9000_device2,
++#endif
++#endif
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++	&spi_bfin_master_device,
++#endif
++
++#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
++	&bfin_uart_device,
++#endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
++#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
++	&isp1362_hcd_device,
++#endif
++};
++
++static int __init ip0x_init(void)
++{
++	int i;
++
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
++	platform_add_devices(ip0x_devices, ARRAY_SIZE(ip0x_devices));
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++	for (i = 0; i < ARRAY_SIZE(bfin_spi_board_info); ++i) {
++		int j = 1 << bfin_spi_board_info[i].chip_select;
++		/* set spi cs to 1 */
++		bfin_write_FIO_DIR(bfin_read_FIO_DIR() | j);
++		bfin_write_FIO_FLAG_S(j);
++	}
++	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
++#endif
++
++	return 0;
++}
++
++arch_initcall(ip0x_init);
+diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
+index b2ac481..fddce32 100644
+--- a/arch/blackfin/mach-bf533/boards/stamp.c
++++ b/arch/blackfin/mach-bf533/boards/stamp.c
+@@ -40,6 +40,7 @@
+ #endif
+ #include <linux/ata_platform.h>
+ #include <linux/irq.h>
++#include <linux/i2c.h>
+ #include <asm/dma.h>
+ #include <asm/bfin5xx_spi.h>
+ #include <asm/reboot.h>
+@@ -109,6 +110,7 @@ static struct platform_device net2272_bfin_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_MTD_BF5xx) || defined(CONFIG_MTD_BF5xx_MODULE)
+ static struct mtd_partition stamp_partitions[] = {
+ 	{
+ 		.name   = "Bootloader",
+@@ -152,6 +154,7 @@ static struct platform_device stamp_flash_device = {
+ 	.num_resources = ARRAY_SIZE(stamp_flash_resource),
+ 	.resource      = stamp_flash_resource,
+ };
++#endif
+ 
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ /* all SPI peripherals info goes here */
+@@ -367,6 +370,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ static struct platform_device bfin_sport0_uart_device = {
+ 	.name = "bfin-sport-uart",
+@@ -472,6 +494,31 @@ static struct platform_device i2c_gpio_device = {
+ };
+ #endif
+ 
++#ifdef CONFIG_I2C_BOARDINFO
++static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
++#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
++	{
++		I2C_BOARD_INFO("ad7142_joystick", 0x2C),
++		.type = "ad7142_joystick",
++		.irq = 39,
++	},
++#endif
++#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
++	{
++		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
++		.type = "pcf8574_lcd",
++	},
++#endif
++#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
++	{
++		I2C_BOARD_INFO("pcf8574_keypad", 0x27),
++		.type = "pcf8574_keypad",
++		.irq = 39,
++	},
++#endif
++};
++#endif
++
+ static struct platform_device *stamp_devices[] __initdata = {
+ #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ 	&rtc_device,
+@@ -497,6 +544,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ 	&bfin_sport0_uart_device,
+ 	&bfin_sport1_uart_device,
+@@ -515,14 +566,23 @@ static struct platform_device *stamp_devices[] __initdata = {
+ #endif
+ 
+ 	&bfin_gpios_device,
++
++#if defined(CONFIG_MTD_BF5xx) || defined(CONFIG_MTD_BF5xx_MODULE)
+ 	&stamp_flash_device,
++#endif
+ };
+ 
+ static int __init stamp_init(void)
+ {
+ 	int ret;
+ 
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
++
++#ifdef CONFIG_I2C_BOARDINFO
++	i2c_register_board_info(0, bfin_i2c_board_info,
++				ARRAY_SIZE(bfin_i2c_board_info));
++#endif
++
+ 	ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ 	if (ret < 0)
+ 		return ret;
+diff --git a/arch/blackfin/mach-bf533/cpu.c b/arch/blackfin/mach-bf533/cpu.c
+deleted file mode 100644
+index b7a0e0f..0000000
+--- a/arch/blackfin/mach-bf533/cpu.c
++++ /dev/null
+@@ -1,158 +0,0 @@
+-/*
+- * File:         arch/blackfin/mach-bf533/cpu.c
+- * Based on:
+- * Author:       michael.kang at analog.com
+- *
+- * Created:
+- * Description:  clock scaling for the bf533
+- *
+- * Modified:
+- *               Copyright 2004-2006 Analog Devices Inc.
+- *
+- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/cpufreq.h>
+-#include <asm/dpmc.h>
+-#include <linux/fs.h>
+-#include <asm/bfin-global.h>
+-
+-/* CONFIG_CLKIN_HZ=11059200 */
+-#define VCO5 (CONFIG_CLKIN_HZ*45)	/*497664000 */
+-#define VCO4 (CONFIG_CLKIN_HZ*36)	/*398131200 */
+-#define VCO3 (CONFIG_CLKIN_HZ*27)	/*298598400 */
+-#define VCO2 (CONFIG_CLKIN_HZ*18)	/*199065600 */
+-#define VCO1 (CONFIG_CLKIN_HZ*9)	/*99532800 */
+-#define VCO(x) VCO##x
+-
+-#define FREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+-/* frequency */
+-static struct cpufreq_frequency_table bf533_freq_table[] = {
+-	FREQ(1),
+-	FREQ(3),
+-	{VCO4, VCO4 / 2}, {VCO4, VCO4},
+-	FREQ(5),
+-	{0, CPUFREQ_TABLE_END},
+-};
+-
+-/*
+- * dpmc_fops->ioctl()
+- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+- */
+-static int bf533_getfreq(unsigned int cpu)
+-{
+-	unsigned long cclk_mhz, vco_mhz;
+-
+-	/* The driver only support single cpu */
+-	if (cpu == 0)
+-		dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+-	else
+-		cclk_mhz = -1;
+-	return cclk_mhz;
+-}
+-
+-static int bf533_target(struct cpufreq_policy *policy,
+-			    unsigned int target_freq, unsigned int relation)
+-{
+-	unsigned long cclk_mhz;
+-	unsigned long vco_mhz;
+-	unsigned long flags;
+-	unsigned int index, vco_index;
+-	int i;
+-
+-	struct cpufreq_freqs freqs;
+-	if (cpufreq_frequency_table_target(policy, bf533_freq_table, target_freq, relation, &index))
+-		return -EINVAL;
+-	cclk_mhz = bf533_freq_table[index].frequency;
+-	vco_mhz = bf533_freq_table[index].index;
+-
+-	dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+-	freqs.old = bf533_getfreq(0);
+-	freqs.new = cclk_mhz;
+-	freqs.cpu = 0;
+-
+-	pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+-	         cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+-
+-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+-	local_irq_save(flags);
+-	dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+-	local_irq_restore(flags);
+-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+-
+-	vco_mhz = get_vco();
+-	cclk_mhz = get_cclk();
+-	return 0;
+-}
+-
+-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+- * this platform, anyway.
+- */
+-static int bf533_verify_speed(struct cpufreq_policy *policy)
+-{
+-	return cpufreq_frequency_table_verify(policy, &bf533_freq_table);
+-}
+-
+-static int __init __bf533_cpu_init(struct cpufreq_policy *policy)
+-{
+-	int result;
+-
+-	if (policy->cpu != 0)
+-		return -EINVAL;
+-
+-	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+-	/*Now ,only support one cpu */
+-	policy->cur = bf533_getfreq(0);
+-	cpufreq_frequency_table_get_attr(bf533_freq_table, policy->cpu);
+-	return cpufreq_frequency_table_cpuinfo(policy, bf533_freq_table);
+-}
+-
+-static struct freq_attr *bf533_freq_attr[] = {
+-	&cpufreq_freq_attr_scaling_available_freqs,
+-	NULL,
+-};
+-
+-static struct cpufreq_driver bf533_driver = {
+-	.verify = bf533_verify_speed,
+-	.target = bf533_target,
+-	.get = bf533_getfreq,
+-	.init = __bf533_cpu_init,
+-	.name = "bf533",
+-	.owner = THIS_MODULE,
+-	.attr = bf533_freq_attr,
+-};
+-
+-static int __init bf533_cpu_init(void)
+-{
+-	return cpufreq_register_driver(&bf533_driver);
+-}
+-
+-static void __exit bf533_cpu_exit(void)
+-{
+-	cpufreq_unregister_driver(&bf533_driver);
+-}
+-
+-MODULE_AUTHOR("Mickael Kang");
+-MODULE_DESCRIPTION("cpufreq driver for BF533 CPU");
+-MODULE_LICENSE("GPL");
+-
+-module_init(bf533_cpu_init);
+-module_exit(bf533_cpu_exit);
+diff --git a/arch/blackfin/mach-bf533/dma.c b/arch/blackfin/mach-bf533/dma.c
+index 6c909cf..28655c1 100644
+--- a/arch/blackfin/mach-bf533/dma.c
++++ b/arch/blackfin/mach-bf533/dma.c
+@@ -26,10 +26,12 @@
+  * to the Free Software Foundation, Inc.,
+  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+  */
++#include <linux/module.h>
++
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+ 
+-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
+@@ -43,6 +45,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ 	(struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ 	(struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+ };
++EXPORT_SYMBOL(dma_io_base_addr);
+ 
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf533/head.S b/arch/blackfin/mach-bf533/head.S
+index 1ded945..1295dea 100644
+--- a/arch/blackfin/mach-bf533/head.S
++++ b/arch/blackfin/mach-bf533/head.S
+@@ -36,9 +36,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+ 
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -151,26 +148,26 @@ ENTRY(__start)
+ 
+ 	/* Initialise UART - when booting from u-boot, the UART is not disabled
+ 	 * so if we dont initalize here, our serial console gets hosed */
+-	p0.h = hi(UART_LCR);
+-	p0.l = lo(UART_LCR);
++	p0.h = hi(BFIN_UART_LCR);
++	p0.l = lo(BFIN_UART_LCR);
+ 	r0 = 0x0(Z);
+ 	w[p0] = r0.L;	/* To enable DLL writes */
+ 	ssync;
+ 
+-	p0.h = hi(UART_DLL);
+-	p0.l = lo(UART_DLL);
++	p0.h = hi(BFIN_UART_DLL);
++	p0.l = lo(BFIN_UART_DLL);
+ 	r0 = 0x0(Z);
+ 	w[p0] = r0.L;
+ 	ssync;
+ 
+-	p0.h = hi(UART_DLH);
+-	p0.l = lo(UART_DLH);
++	p0.h = hi(BFIN_UART_DLH);
++	p0.l = lo(BFIN_UART_DLH);
+ 	r0 = 0x00(Z);
+ 	w[p0] = r0.L;
+ 	ssync;
+ 
+-	p0.h = hi(UART_GCTL);
+-	p0.l = lo(UART_GCTL);
++	p0.h = hi(BFIN_UART_GCTL);
++	p0.l = lo(BFIN_UART_GCTL);
+ 	r0 = 0x0(Z);
+ 	w[p0] = r0.L;	/* To enable UART clock */
+ 	ssync;
+@@ -431,18 +428,3 @@ ENTRY(_start_dma_code)
+ 	RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long   0
+-__ramstart:
+-.long   0
+-__ramend:
+-.long   0
+diff --git a/arch/blackfin/mach-bf537/Makefile b/arch/blackfin/mach-bf537/Makefile
+index 7e7c9c8..68e5478 100644
+--- a/arch/blackfin/mach-bf537/Makefile
++++ b/arch/blackfin/mach-bf537/Makefile
+@@ -5,5 +5,3 @@
+ extra-y := head.o
+ 
+ obj-y := ints-priority.o dma.o
+-
+-obj-$(CONFIG_CPU_FREQ)   += cpu.o
+diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
+index f7c1f96..d8a23cd 100644
+--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
++++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
+@@ -325,6 +325,54 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++		.start = 0xFFC02000,
++		.end = 0xFFC020FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#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
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ static struct platform_device bfin_sport0_uart_device = {
+ 	.name = "bfin-sport-uart",
+@@ -393,6 +441,14 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#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)
+ 	&bfin_sport0_uart_device,
+ 	&bfin_sport1_uart_device,
+@@ -425,7 +481,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
+ 
+ static int __init cm_bf537_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	platform_add_devices(cm_bf537_devices, ARRAY_SIZE(cm_bf537_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
+index c95395b..7d25082 100644
+--- a/arch/blackfin/mach-bf537/boards/generic_board.c
++++ b/arch/blackfin/mach-bf537/boards/generic_board.c
+@@ -90,7 +90,7 @@ int __init bfin_isp1761_init(void)
+ {
+ 	unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+ 
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+ 
+ 	return platform_add_devices(bfin_isp1761_devices, num_devices);
+@@ -554,6 +554,32 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++		.start = 0xFFC02000,
++		.end = 0xFFC020FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ static struct resource bfin_twi0_resource[] = {
+ 	[0] = {
+@@ -674,6 +700,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ 	&i2c_bfin_twi_device,
+ #endif
+@@ -690,7 +720,7 @@ static struct platform_device *stamp_devices[] __initdata = {
+ 
+ static int __init stamp_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info,
+diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
+index d71e0be..18ddf7a 100644
+--- a/arch/blackfin/mach-bf537/boards/minotaur.c
++++ b/arch/blackfin/mach-bf537/boards/minotaur.c
+@@ -8,12 +8,12 @@
+ #include <linux/spi/spi.h>
+ #include <linux/spi/flash.h>
+ #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+-#include <linux/usb_isp1362.h>
++#include <linux/usb/isp1362.h>
+ #endif
+ #include <linux/ata_platform.h>
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
+-#include <linux/usb_sl811.h>
++#include <linux/usb/sl811.h>
+ #include <asm/dma.h>
+ #include <asm/bfin5xx_spi.h>
+ #include <asm/reboot.h>
+@@ -225,6 +225,32 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++		.start = 0xFFC02000,
++		.end = 0xFFC020FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ static struct resource bfin_twi0_resource[] = {
+ 	[0] = {
+@@ -284,6 +310,10 @@ static struct platform_device *minotaur_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ 	&i2c_bfin_twi_device,
+ #endif
+@@ -297,7 +327,7 @@ static struct platform_device *minotaur_devices[] __initdata = {
+ 
+ static int __init minotaur_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	platform_add_devices(minotaur_devices, ARRAY_SIZE(minotaur_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info,
+diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
+index 509a8a2..51c3bab 100644
+--- a/arch/blackfin/mach-bf537/boards/pnav10.c
++++ b/arch/blackfin/mach-bf537/boards/pnav10.c
+@@ -452,6 +452,31 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++		.start = 0xFFC02000,
++		.end = 0xFFC020FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
+ 
+ static struct platform_device *stamp_devices[] __initdata = {
+ #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+@@ -493,11 +518,15 @@ static struct platform_device *stamp_devices[] __initdata = {
+ #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+ 	&bfin_uart_device,
+ #endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
+ };
+ 
+ static int __init stamp_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info,
+diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
+index ea83148..0cec14b 100644
+--- a/arch/blackfin/mach-bf537/boards/stamp.c
++++ b/arch/blackfin/mach-bf537/boards/stamp.c
+@@ -41,6 +41,7 @@
+ #include <linux/ata_platform.h>
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
++#include <linux/i2c.h>
+ #include <linux/usb/sl811.h>
+ #include <asm/dma.h>
+ #include <asm/bfin5xx_spi.h>
+@@ -90,7 +91,7 @@ int __init bfin_isp1761_init(void)
+ {
+ 	unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+ 
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+ 
+ 	return platform_add_devices(bfin_isp1761_devices, num_devices);
+@@ -353,6 +354,7 @@ static struct platform_device net2272_bfin_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ static struct mtd_partition stamp_partitions[] = {
+ 	{
+ 		.name       = "Bootloader",
+@@ -395,6 +397,7 @@ static struct platform_device stamp_flash_device = {
+ 	.num_resources = 1,
+ 	.resource      = &stamp_flash_resource,
+ };
++#endif
+ 
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ /* all SPI peripherals info goes here */
+@@ -500,6 +503,15 @@ static struct bfin5xx_spi_chip spidev_chip_info = {
+ };
+ #endif
+ 
++#if defined(CONFIG_MTD_DATAFLASH) \
++	|| defined(CONFIG_MTD_DATAFLASH_MODULE)
++/* DataFlash chip */
++static struct bfin5xx_spi_chip data_flash_chip_info = {
++	.enable_dma = 0,         /* use dma transfer with this chip*/
++	.bits_per_word = 8,
++};
++#endif
++
+ static struct spi_board_info bfin_spi_board_info[] __initdata = {
+ #if defined(CONFIG_MTD_M25P80) \
+ 	|| defined(CONFIG_MTD_M25P80_MODULE)
+@@ -514,7 +526,17 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
+ 		.mode = SPI_MODE_3,
+ 	},
+ #endif
+-
++#if defined(CONFIG_MTD_DATAFLASH) \
++	|| defined(CONFIG_MTD_DATAFLASH_MODULE)
++	{	/* DataFlash chip */
++		.modalias = "mtd_dataflash",
++		.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*/
++		.controller_data = &data_flash_chip_info,
++		.mode = SPI_MODE_3,
++	},
++#endif
+ #if defined(CONFIG_SPI_ADC_BF533) \
+ 	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+ 	{
+@@ -676,6 +698,32 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++		.start = 0xFFC02000,
++		.end = 0xFFC020FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ static struct resource bfin_twi0_resource[] = {
+ 	[0] = {
+@@ -698,6 +746,31 @@ static struct platform_device i2c_bfin_twi_device = {
+ };
+ #endif
+ 
++#ifdef CONFIG_I2C_BOARDINFO
++static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
++#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
++	{
++		I2C_BOARD_INFO("ad7142_joystick", 0x2C),
++		.type = "ad7142_joystick",
++		.irq = 55,
++	},
++#endif
++#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
++	{
++		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
++		.type = "pcf8574_lcd",
++	},
++#endif
++#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
++	{
++		I2C_BOARD_INFO("pcf8574_keypad", 0x27),
++		.type = "pcf8574_keypad",
++		.irq = 72,
++	},
++#endif
++};
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ static struct platform_device bfin_sport0_uart_device = {
+ 	.name = "bfin-sport-uart",
+@@ -800,6 +873,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ 	&i2c_bfin_twi_device,
+ #endif
+@@ -818,12 +895,21 @@ static struct platform_device *stamp_devices[] __initdata = {
+ #endif
+ 
+ 	&bfin_gpios_device,
++
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ 	&stamp_flash_device,
++#endif
+ };
+ 
+ static int __init stamp_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
++
++#ifdef CONFIG_I2C_BOARDINFO
++	i2c_register_board_info(0, bfin_i2c_board_info,
++				ARRAY_SIZE(bfin_i2c_board_info));
++#endif
++
+ 	platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info,
+@@ -833,6 +919,7 @@ static int __init stamp_init(void)
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ 	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+ #endif
++
+ 	return 0;
+ }
+ 
+diff --git a/arch/blackfin/mach-bf537/cpu.c b/arch/blackfin/mach-bf537/cpu.c
+deleted file mode 100644
+index 0442c4c..0000000
+--- a/arch/blackfin/mach-bf537/cpu.c
++++ /dev/null
+@@ -1,159 +0,0 @@
+-/*
+- * File:         arch/blackfin/mach-bf537/cpu.c
+- * Based on:
+- * Author:       michael.kang at analog.com
+- *
+- * Created:
+- * Description:  clock scaling for the bf537
+- *
+- * Modified:
+- *               Copyright 2004-2006 Analog Devices Inc.
+- *
+- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/cpufreq.h>
+-#include <asm/dpmc.h>
+-#include <linux/fs.h>
+-#include <asm/bfin-global.h>
+-
+-/* CONFIG_CLKIN_HZ=11059200 */
+-#define VCO5 (CONFIG_CLKIN_HZ*45)	/*497664000 */
+-#define VCO4 (CONFIG_CLKIN_HZ*36)	/*398131200 */
+-#define VCO3 (CONFIG_CLKIN_HZ*27)	/*298598400 */
+-#define VCO2 (CONFIG_CLKIN_HZ*18)	/*199065600 */
+-#define VCO1 (CONFIG_CLKIN_HZ*9)	/*99532800 */
+-#define VCO(x) VCO##x
+-
+-#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+-/* frequency */
+-static struct cpufreq_frequency_table bf537_freq_table[] = {
+-	MFREQ(1),
+-	MFREQ(3),
+-	{VCO4, VCO4 / 2}, {VCO4, VCO4},
+-	MFREQ(5),
+-	{0, CPUFREQ_TABLE_END},
+-};
+-
+-/*
+- * dpmc_fops->ioctl()
+- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+- */
+-static int bf537_getfreq(unsigned int cpu)
+-{
+-	unsigned long cclk_mhz;
+-
+-	/* The driver only support single cpu */
+-	if (cpu == 0)
+-		dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+-	else
+-		cclk_mhz = -1;
+-
+-	return cclk_mhz;
+-}
+-
+-static int bf537_target(struct cpufreq_policy *policy,
+-			    unsigned int target_freq, unsigned int relation)
+-{
+-	unsigned long cclk_mhz;
+-	unsigned long vco_mhz;
+-	unsigned long flags;
+-	unsigned int index;
+-	struct cpufreq_freqs freqs;
+-
+-	if (cpufreq_frequency_table_target(policy, bf537_freq_table, target_freq, relation, &index))
+-		return -EINVAL;
+-
+-	cclk_mhz = bf537_freq_table[index].frequency;
+-	vco_mhz = bf537_freq_table[index].index;
+-
+-	dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+-	freqs.old = bf537_getfreq(0);
+-	freqs.new = cclk_mhz;
+-	freqs.cpu = 0;
+-
+-	pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+-	         cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+-
+-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+-	local_irq_save(flags);
+-	dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+-	local_irq_restore(flags);
+-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+-
+-	vco_mhz = get_vco();
+-	cclk_mhz = get_cclk();
+-	return 0;
+-}
+-
+-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+- * this platform, anyway.
+- */
+-static int bf537_verify_speed(struct cpufreq_policy *policy)
+-{
+-	return cpufreq_frequency_table_verify(policy, &bf537_freq_table);
+-}
+-
+-static int __init __bf537_cpu_init(struct cpufreq_policy *policy)
+-{
+-	if (policy->cpu != 0)
+-		return -EINVAL;
+-
+-	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+-
+-	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+-	/*Now ,only support one cpu */
+-	policy->cur = bf537_getfreq(0);
+-	cpufreq_frequency_table_get_attr(bf537_freq_table, policy->cpu);
+-	return cpufreq_frequency_table_cpuinfo(policy, bf537_freq_table);
+-}
+-
+-static struct freq_attr *bf537_freq_attr[] = {
+-	&cpufreq_freq_attr_scaling_available_freqs,
+-	NULL,
+-};
+-
+-static struct cpufreq_driver bf537_driver = {
+-	.verify = bf537_verify_speed,
+-	.target = bf537_target,
+-	.get = bf537_getfreq,
+-	.init = __bf537_cpu_init,
+-	.name = "bf537",
+-	.owner = THIS_MODULE,
+-	.attr = bf537_freq_attr,
+-};
+-
+-static int __init bf537_cpu_init(void)
+-{
+-	return cpufreq_register_driver(&bf537_driver);
+-}
+-
+-static void __exit bf537_cpu_exit(void)
+-{
+-	cpufreq_unregister_driver(&bf537_driver);
+-}
+-
+-MODULE_AUTHOR("Mickael Kang");
+-MODULE_DESCRIPTION("cpufreq driver for BF537 CPU");
+-MODULE_LICENSE("GPL");
+-
+-module_init(bf537_cpu_init);
+-module_exit(bf537_cpu_exit);
+diff --git a/arch/blackfin/mach-bf537/dma.c b/arch/blackfin/mach-bf537/dma.c
+index 706cb97..4edb363 100644
+--- a/arch/blackfin/mach-bf537/dma.c
++++ b/arch/blackfin/mach-bf537/dma.c
+@@ -26,10 +26,12 @@
+  * to the Free Software Foundation, Inc.,
+  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+  */
++#include <linux/module.h>
++
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+ 
+-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
+@@ -47,6 +49,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ 	(struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ 	(struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+ };
++EXPORT_SYMBOL(dma_io_base_addr);
+ 
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf537/head.S b/arch/blackfin/mach-bf537/head.S
+index 3014fe8..48cd58a 100644
+--- a/arch/blackfin/mach-bf537/head.S
++++ b/arch/blackfin/mach-bf537/head.S
+@@ -37,9 +37,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+ 
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -180,40 +177,28 @@ ENTRY(__start)
+ 	SSYNC;
+ #endif
+ 
+-#ifdef CONFIG_BF537_PORT_H
+-	p0.h = hi(PORTH_FER);
+-	p0.l = lo(PORTH_FER);
+-	R0.L = W[P0]; /* Read */
+-	SSYNC;
+-	R0 = 0x0000;
+-	W[P0] = R0.L; /* Write */
+-	SSYNC;
+-	W[P0] = R0.L; /* Disable peripheral function of PORTH */
+-	SSYNC;
+-#endif
+-
+ 	/* Initialise UART - when booting from u-boot, the UART is not disabled
+ 	 * so if we dont initalize here, our serial console gets hosed */
+-	p0.h = hi(UART_LCR);
+-	p0.l = lo(UART_LCR);
++	p0.h = hi(BFIN_UART_LCR);
++	p0.l = lo(BFIN_UART_LCR);
+ 	r0 = 0x0(Z);
+ 	w[p0] = r0.L;	/* To enable DLL writes */
+ 	ssync;
+ 
+-	p0.h = hi(UART_DLL);
+-	p0.l = lo(UART_DLL);
++	p0.h = hi(BFIN_UART_DLL);
++	p0.l = lo(BFIN_UART_DLL);
+ 	r0 = 0x0(Z);
+ 	w[p0] = r0.L;
+ 	ssync;
+ 
+-	p0.h = hi(UART_DLH);
+-	p0.l = lo(UART_DLH);
++	p0.h = hi(BFIN_UART_DLH);
++	p0.l = lo(BFIN_UART_DLH);
+ 	r0 = 0x00(Z);
+ 	w[p0] = r0.L;
+ 	ssync;
+ 
+-	p0.h = hi(UART_GCTL);
+-	p0.l = lo(UART_GCTL);
++	p0.h = hi(BFIN_UART_GCTL);
++	p0.l = lo(BFIN_UART_GCTL);
+ 	r0 = 0x0(Z);
+ 	w[p0] = r0.L;	/* To enable UART clock */
+ 	ssync;
+@@ -483,18 +468,3 @@ ENTRY(_start_dma_code)
+ 	RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long   0
+-__ramstart:
+-.long   0
+-__ramend:
+-.long   0
+diff --git a/arch/blackfin/mach-bf548/Makefile b/arch/blackfin/mach-bf548/Makefile
+index 7e7c9c8..68e5478 100644
+--- a/arch/blackfin/mach-bf548/Makefile
++++ b/arch/blackfin/mach-bf548/Makefile
+@@ -5,5 +5,3 @@
+ extra-y := head.o
+ 
+ obj-y := ints-priority.o dma.o
+-
+-obj-$(CONFIG_CPU_FREQ)   += cpu.o
+diff --git a/arch/blackfin/mach-bf548/boards/Kconfig b/arch/blackfin/mach-bf548/boards/Kconfig
+index 0571290..d38e526 100644
+--- a/arch/blackfin/mach-bf548/boards/Kconfig
++++ b/arch/blackfin/mach-bf548/boards/Kconfig
+@@ -8,5 +8,11 @@ config BFIN548_EZKIT
+ 	bool "BF548-EZKIT"
+ 	help
+ 	  BFIN548-EZKIT board support.
++	  
++config BFIN548_BLUETECHNIX_CM
++	bool "Bluetechnix CM-BF548"
++	depends on (BF548)
++	help
++	  CM-BF548 support for DEV-Board.	  
+ 
+ endchoice
+diff --git a/arch/blackfin/mach-bf548/boards/Makefile b/arch/blackfin/mach-bf548/boards/Makefile
+index a444cc7..eed161d 100644
+--- a/arch/blackfin/mach-bf548/boards/Makefile
++++ b/arch/blackfin/mach-bf548/boards/Makefile
+@@ -3,3 +3,4 @@
+ #
+ 
+ obj-$(CONFIG_BFIN548_EZKIT)            += ezkit.o led.o
++obj-$(CONFIG_BFIN548_BLUETECHNIX_CM)   += cm_bf548.o
+diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
+new file mode 100644
+index 0000000..e3e8479
+--- /dev/null
++++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
+@@ -0,0 +1,664 @@
++/*
++ * File:         arch/blackfin/mach-bf548/boards/cm_bf548.c
++ * Based on:     arch/blackfin/mach-bf537/boards/ezkit.c
++ * Author:       Aidan Williams <aidan at nicta.com.au>
++ *
++ * Created:
++ * Description:
++ *
++ * Modified:
++ *               Copyright 2005 National ICT Australia (NICTA)
++ *               Copyright 2004-2008 Analog Devices Inc.
++ *
++ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see the file COPYING, or write
++ * to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ */
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/usb/musb.h>
++#include <asm/bfin5xx_spi.h>
++#include <asm/cplb.h>
++#include <asm/dma.h>
++#include <asm/gpio.h>
++#include <asm/nand.h>
++#include <asm/portmux.h>
++#include <asm/mach/bf54x_keys.h>
++#include <linux/input.h>
++#include <linux/spi/ad7877.h>
++
++/*
++ * Name the Board for the /proc/cpuinfo
++ */
++const char bfin_board_name[] = "Bluetechnix CM-BF548";
++
++/*
++ *  Driver needs to know address, irq and flag pin.
++ */
++
++#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
++
++#include <asm/mach/bf54x-lq043.h>
++
++static struct bfin_bf54xfb_mach_info bf54x_lq043_data = {
++	.width =	480,
++	.height =	272,
++	.xres =		{480, 480, 480},
++	.yres =		{272, 272, 272},
++	.bpp =		{24, 24, 24},
++	.disp =		GPIO_PE3,
++};
++
++static struct resource bf54x_lq043_resources[] = {
++	{
++		.start = IRQ_EPPI0_ERR,
++		.end = IRQ_EPPI0_ERR,
++		.flags = IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device bf54x_lq043_device = {
++	.name		= "bf54x-lq043",
++	.id		= -1,
++	.num_resources 	= ARRAY_SIZE(bf54x_lq043_resources),
++	.resource 	= bf54x_lq043_resources,
++	.dev		= {
++		.platform_data = &bf54x_lq043_data,
++	},
++};
++#endif
++
++#if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE)
++static unsigned int bf548_keymap[] = {
++	KEYVAL(0, 0, KEY_ENTER),
++	KEYVAL(0, 1, KEY_HELP),
++	KEYVAL(0, 2, KEY_0),
++	KEYVAL(0, 3, KEY_BACKSPACE),
++	KEYVAL(1, 0, KEY_TAB),
++	KEYVAL(1, 1, KEY_9),
++	KEYVAL(1, 2, KEY_8),
++	KEYVAL(1, 3, KEY_7),
++	KEYVAL(2, 0, KEY_DOWN),
++	KEYVAL(2, 1, KEY_6),
++	KEYVAL(2, 2, KEY_5),
++	KEYVAL(2, 3, KEY_4),
++	KEYVAL(3, 0, KEY_UP),
++	KEYVAL(3, 1, KEY_3),
++	KEYVAL(3, 2, KEY_2),
++	KEYVAL(3, 3, KEY_1),
++};
++
++static struct bfin_kpad_platform_data bf54x_kpad_data = {
++	.rows			= 4,
++	.cols			= 4,
++	.keymap 		= bf548_keymap,
++	.keymapsize 		= ARRAY_SIZE(bf548_keymap),
++	.repeat			= 0,
++	.debounce_time		= 5000,	/* ns (5ms) */
++	.coldrive_time		= 1000, /* ns (1ms) */
++	.keyup_test_interval	= 50, /* ms (50ms) */
++};
++
++static struct resource bf54x_kpad_resources[] = {
++	{
++		.start = IRQ_KEY,
++		.end = IRQ_KEY,
++		.flags = IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device bf54x_kpad_device = {
++	.name		= "bf54x-keys",
++	.id		= -1,
++	.num_resources 	= ARRAY_SIZE(bf54x_kpad_resources),
++	.resource 	= bf54x_kpad_resources,
++	.dev		= {
++		.platform_data = &bf54x_kpad_data,
++	},
++};
++#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_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
++static struct resource bfin_uart_resources[] = {
++#ifdef CONFIG_SERIAL_BFIN_UART0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_SERIAL_BFIN_UART1
++	{
++		.start = 0xFFC02000,
++		.end = 0xFFC020FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_SERIAL_BFIN_UART2
++	{
++		.start = 0xFFC02100,
++		.end = 0xFFC021FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_SERIAL_BFIN_UART3
++	{
++		.start = 0xFFC03100,
++		.end = 0xFFC031FF,
++	},
++#endif
++};
++
++static struct platform_device bfin_uart_device = {
++	.name = "bfin-uart",
++	.id = 1,
++	.num_resources = ARRAY_SIZE(bfin_uart_resources),
++	.resource = bfin_uart_resources,
++};
++#endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++		.start = 0xFFC02000,
++		.end = 0xFFC020FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR2
++	{
++		.start = 0xFFC02100,
++		.end = 0xFFC021FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR3
++	{
++		.start = 0xFFC03100,
++		.end = 0xFFC031FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
++#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
++static struct resource smsc911x_resources[] = {
++	{
++		.name = "smsc911x-memory",
++		.start = 0x24000000,
++		.end = 0x24000000 + 0xFF,
++		.flags = IORESOURCE_MEM,
++	},
++	{
++		.start = IRQ_PE6,
++		.end = IRQ_PE6,
++		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
++	},
++};
++static struct platform_device smsc911x_device = {
++	.name = "smsc911x",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(smsc911x_resources),
++	.resource = smsc911x_resources,
++};
++#endif
++
++#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
++static struct resource musb_resources[] = {
++	[0] = {
++		.start	= 0xFFC03C00,
++		.end	= 0xFFC040FF,
++		.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_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
++	.multipoint	= 0,
++};
++
++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_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
++static struct resource bfin_atapi_resources[] = {
++	{
++		.start = 0xFFC03800,
++		.end = 0xFFC0386F,
++		.flags = IORESOURCE_MEM,
++	},
++	{
++		.start = IRQ_ATAPI_ERR,
++		.end = IRQ_ATAPI_ERR,
++		.flags = IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device bfin_atapi_device = {
++	.name = "pata-bf54x",
++	.id = -1,
++	.num_resources = ARRAY_SIZE(bfin_atapi_resources),
++	.resource = bfin_atapi_resources,
++};
++#endif
++
++#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
++static struct mtd_partition partition_info[] = {
++	{
++		.name = "Linux Kernel",
++		.offset = 0,
++		.size = 4 * SIZE_1M,
++	},
++	{
++		.name = "File System",
++		.offset = 4 * SIZE_1M,
++		.size = (256 - 4) * SIZE_1M,
++	},
++};
++
++static struct bf5xx_nand_platform bf5xx_nand_platform = {
++	.page_size = NFC_PG_SIZE_256,
++	.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 = 0xFFC03B00,
++		.end = 0xFFC03B4F,
++		.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_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
++static struct platform_device bf54x_sdh_device = {
++	.name = "bfin-sdh",
++	.id = 0,
++};
++#endif
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++/* all SPI peripherals info goes here */
++#if defined(CONFIG_MTD_M25P80) \
++	|| defined(CONFIG_MTD_M25P80_MODULE)
++/* SPI flash chip (m25p16) */
++static struct mtd_partition bfin_spi_flash_partitions[] = {
++	{
++		.name = "bootloader",
++		.size = 0x00040000,
++		.offset = 0,
++		.mask_flags = MTD_CAP_ROM
++	}, {
++		.name = "linux kernel",
++		.size = 0x1c0000,
++		.offset = 0x40000
++	}
++};
++
++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",
++};
++
++static struct bfin5xx_spi_chip spi_flash_chip_info = {
++	.enable_dma = 0,         /* use dma transfer with this chip*/
++	.bits_per_word = 8,
++	.cs_change_per_word = 0,
++};
++#endif
++
++#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
++static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
++	.cs_change_per_word = 0,
++	.enable_dma = 0,
++	.bits_per_word = 16,
++};
++
++static const struct ad7877_platform_data bfin_ad7877_ts_info = {
++	.model			= 7877,
++	.vref_delay_usecs	= 50,	/* internal, no capacitor */
++	.x_plate_ohms		= 419,
++	.y_plate_ohms		= 486,
++	.pressure_max		= 1000,
++	.pressure_min		= 0,
++	.stopacq_polarity 	= 1,
++	.first_conversion_delay = 3,
++	.acquisition_time 	= 1,
++	.averaging 		= 1,
++	.pen_down_acc_interval 	= 1,
++};
++#endif
++
++#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
++static struct bfin5xx_spi_chip spidev_chip_info = {
++	.enable_dma = 0,
++	.bits_per_word = 8,
++};
++#endif
++
++static struct spi_board_info bf54x_spi_board_info[] __initdata = {
++#if defined(CONFIG_MTD_M25P80) \
++	|| defined(CONFIG_MTD_M25P80_MODULE)
++	{
++		/* 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, /* SPI_SSEL1*/
++		.platform_data = &bfin_spi_flash_data,
++		.controller_data = &spi_flash_chip_info,
++		.mode = SPI_MODE_3,
++	},
++#endif
++#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
++{
++	.modalias		= "ad7877",
++	.platform_data		= &bfin_ad7877_ts_info,
++	.irq			= IRQ_PJ11,
++	.max_speed_hz		= 12500000,     /* max spi clock (SCK) speed in HZ */
++	.bus_num		= 0,
++	.chip_select  		= 2,
++	.controller_data = &spi_ad7877_chip_info,
++},
++#endif
++#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
++	{
++		.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
++};
++
++/* SPI (0) */
++static struct resource bfin_spi0_resource[] = {
++	[0] = {
++		.start = SPI0_REGBASE,
++		.end   = SPI0_REGBASE + 0xFF,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = CH_SPI0,
++		.end   = CH_SPI0,
++		.flags = IORESOURCE_IRQ,
++	}
++};
++
++/* SPI (1) */
++static struct resource bfin_spi1_resource[] = {
++	[0] = {
++		.start = SPI1_REGBASE,
++		.end   = SPI1_REGBASE + 0xFF,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = CH_SPI1,
++		.end   = CH_SPI1,
++		.flags = IORESOURCE_IRQ,
++	}
++};
++
++/* SPI controller data */
++static struct bfin5xx_spi_master bf54x_spi_master_info0 = {
++	.num_chipselect = 8,
++	.enable_dma = 1,  /* master has the ability to do dma transfer */
++	.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
++};
++
++static struct platform_device bf54x_spi_master0 = {
++	.name = "bfin-spi",
++	.id = 0, /* Bus number */
++	.num_resources = ARRAY_SIZE(bfin_spi0_resource),
++	.resource = bfin_spi0_resource,
++	.dev = {
++		.platform_data = &bf54x_spi_master_info0, /* Passed to driver */
++		},
++};
++
++static struct bfin5xx_spi_master bf54x_spi_master_info1 = {
++	.num_chipselect = 8,
++	.enable_dma = 1,  /* master has the ability to do dma transfer */
++	.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
++};
++
++static struct platform_device bf54x_spi_master1 = {
++	.name = "bfin-spi",
++	.id = 1, /* Bus number */
++	.num_resources = ARRAY_SIZE(bfin_spi1_resource),
++	.resource = bfin_spi1_resource,
++	.dev = {
++		.platform_data = &bf54x_spi_master_info1, /* Passed to driver */
++		},
++};
++#endif  /* spi master and devices */
++
++#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 + 0xFF,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = IRQ_TWI0,
++		.end   = IRQ_TWI0,
++		.flags = IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device i2c_bfin_twi0_device = {
++	.name = "i2c-bfin-twi",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_twi0_resource),
++	.resource = bfin_twi0_resource,
++};
++
++#if !defined(CONFIG_BF542)	/* The BF542 only has 1 TWI */
++static struct resource bfin_twi1_resource[] = {
++	[0] = {
++		.start = TWI1_REGBASE,
++		.end   = TWI1_REGBASE + 0xFF,
++		.flags = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start = IRQ_TWI1,
++		.end   = IRQ_TWI1,
++		.flags = IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device i2c_bfin_twi1_device = {
++	.name = "i2c-bfin-twi",
++	.id = 1,
++	.num_resources = ARRAY_SIZE(bfin_twi1_resource),
++	.resource = bfin_twi1_resource,
++};
++#endif
++#endif
++
++#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
++#include <linux/gpio_keys.h>
++
++static struct gpio_keys_button bfin_gpio_keys_table[] = {
++	{BTN_0, GPIO_PH7, 1, "gpio-keys: BTN0"},
++};
++
++static struct gpio_keys_platform_data bfin_gpio_keys_data = {
++	.buttons        = bfin_gpio_keys_table,
++	.nbuttons       = ARRAY_SIZE(bfin_gpio_keys_table),
++};
++
++static struct platform_device bfin_device_gpiokeys = {
++	.name      = "gpio-keys",
++	.dev = {
++		.platform_data = &bfin_gpio_keys_data,
++	},
++};
++#endif
++
++static struct platform_device *cm_bf548_devices[] __initdata = {
++#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
++	&rtc_device,
++#endif
++
++#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
++	&bfin_uart_device,
++#endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
++#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
++	&bf54x_lq043_device,
++#endif
++
++#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
++	&smsc911x_device,
++#endif
++
++#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
++	&musb_device,
++#endif
++
++#if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
++	&bfin_atapi_device,
++#endif
++
++#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
++	&bf5xx_nand_device,
++#endif
++
++#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
++	&bf54x_sdh_device,
++#endif
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++	&bf54x_spi_master0,
++	&bf54x_spi_master1,
++#endif
++
++#if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE)
++	&bf54x_kpad_device,
++#endif
++
++#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
++/*	&i2c_bfin_twi0_device, */
++#if !defined(CONFIG_BF542)
++	&i2c_bfin_twi1_device,
++#endif
++#endif
++
++#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
++	&bfin_device_gpiokeys,
++#endif
++};
++
++static int __init cm_bf548_init(void)
++{
++	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	platform_add_devices(cm_bf548_devices, ARRAY_SIZE(cm_bf548_devices));
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++	spi_register_board_info(bf54x_spi_board_info,
++			ARRAY_SIZE(bf54x_spi_board_info));
++#endif
++
++	return 0;
++}
++
++arch_initcall(cm_bf548_init);
+diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
+index 40846aa..231dfbd 100644
+--- a/arch/blackfin/mach-bf548/boards/ezkit.c
++++ b/arch/blackfin/mach-bf548/boards/ezkit.c
+@@ -36,6 +36,7 @@
+ #include <linux/spi/spi.h>
+ #include <linux/spi/flash.h>
+ #include <linux/irq.h>
++#include <linux/i2c.h>
+ #include <linux/interrupt.h>
+ #if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+ #include <linux/usb/musb.h>
+@@ -187,6 +188,46 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++		.start = 0xFFC02000,
++		.end = 0xFFC020FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR2
++	{
++		.start = 0xFFC02100,
++		.end = 0xFFC021FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR3
++	{
++		.start = 0xFFC03100,
++		.end = 0xFFC031FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+ static struct resource smsc911x_resources[] = {
+ 	{
+@@ -330,6 +371,7 @@ static struct platform_device bf54x_sdh_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ static struct mtd_partition ezkit_partitions[] = {
+ 	{
+ 		.name       = "Bootloader",
+@@ -337,7 +379,7 @@ static struct mtd_partition ezkit_partitions[] = {
+ 		.offset     = 0,
+ 	}, {
+ 		.name       = "Kernel",
+-		.size       = 0xE0000,
++		.size       = 0x1C0000,
+ 		.offset     = MTDPART_OFS_APPEND,
+ 	}, {
+ 		.name       = "RootFS",
+@@ -367,6 +409,7 @@ static struct platform_device ezkit_flash_device = {
+ 	.num_resources = 1,
+ 	.resource      = &ezkit_flash_resource,
+ };
++#endif
+ 
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ /* all SPI peripherals info goes here */
+@@ -400,6 +443,14 @@ static struct bfin5xx_spi_chip spi_flash_chip_info = {
+ };
+ #endif
+ 
++#if defined(CONFIG_SND_BLACKFIN_AD1836) \
++	|| defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
++static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
++	.enable_dma = 0,
++	.bits_per_word = 16,
++};
++#endif
++
+ #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+ static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
+ 	.cs_change_per_word = 0,
+@@ -443,6 +494,16 @@ static struct spi_board_info bf54x_spi_board_info[] __initdata = {
+ 		.mode = SPI_MODE_3,
+ 	},
+ #endif
++#if defined(CONFIG_SND_BLACKFIN_AD1836) \
++	|| defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
++	{
++		.modalias = "ad1836-spi",
++		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
++		.bus_num = 1,
++		.chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
++		.controller_data = &ad1836_spi_chip_info,
++	},
++#endif
+ #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+ {
+ 	.modalias		= "ad7877",
+@@ -571,6 +632,29 @@ static struct platform_device i2c_bfin_twi1_device = {
+ #endif
+ #endif
+ 
++#ifdef CONFIG_I2C_BOARDINFO
++static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
++};
++
++#if !defined(CONFIG_BF542)	/* The BF542 only has 1 TWI */
++static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
++#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
++	{
++		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
++		.type = "pcf8574_lcd",
++	},
++#endif
++#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
++	{
++		I2C_BOARD_INFO("pcf8574_keypad", 0x27),
++		.type = "pcf8574_keypad",
++		.irq = 212,
++	},
++#endif
++};
++#endif
++#endif
++
+ #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+ #include <linux/gpio_keys.h>
+ 
+@@ -616,6 +700,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
+ 	&bf54x_lq043_device,
+ #endif
+@@ -661,12 +749,25 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ #endif
+ 
+ 	&bfin_gpios_device,
++
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ 	&ezkit_flash_device,
++#endif
+ };
+ 
+ static int __init ezkit_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
++
++#ifdef CONFIG_I2C_BOARDINFO
++	i2c_register_board_info(0, bfin_i2c_board_info0,
++				ARRAY_SIZE(bfin_i2c_board_info0));
++#if !defined(CONFIG_BF542)	/* The BF542 only has 1 TWI */
++	i2c_register_board_info(1, bfin_i2c_board_info1,
++				ARRAY_SIZE(bfin_i2c_board_info1));
++#endif
++#endif
++
+ 	platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
+ 
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+diff --git a/arch/blackfin/mach-bf548/cpu.c b/arch/blackfin/mach-bf548/cpu.c
+deleted file mode 100644
+index 4298a3c..0000000
+--- a/arch/blackfin/mach-bf548/cpu.c
++++ /dev/null
+@@ -1,159 +0,0 @@
+-/*
+- * File:         arch/blackfin/mach-bf548/cpu.c
+- * Based on:
+- * Author:
+- *
+- * Created:
+- * Description:  clock scaling for the bf54x
+- *
+- * Modified:
+- *               Copyright 2004-2007 Analog Devices Inc.
+- *
+- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/cpufreq.h>
+-#include <asm/dpmc.h>
+-#include <linux/fs.h>
+-#include <asm/bfin-global.h>
+-
+-/* CONFIG_CLKIN_HZ=25000000 */
+-#define VCO5 (CONFIG_CLKIN_HZ*45)
+-#define VCO4 (CONFIG_CLKIN_HZ*36)
+-#define VCO3 (CONFIG_CLKIN_HZ*27)
+-#define VCO2 (CONFIG_CLKIN_HZ*18)
+-#define VCO1 (CONFIG_CLKIN_HZ*9)
+-#define VCO(x) VCO##x
+-
+-#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+-/* frequency */
+-static struct cpufreq_frequency_table bf548_freq_table[] = {
+-	MFREQ(1),
+-	MFREQ(3),
+-	{VCO4, VCO4 / 2}, {VCO4, VCO4},
+-	MFREQ(5),
+-	{0, CPUFREQ_TABLE_END},
+-};
+-
+-/*
+- * dpmc_fops->ioctl()
+- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+- */
+-static int bf548_getfreq(unsigned int cpu)
+-{
+-	unsigned long cclk_mhz;
+-
+-	/* The driver only support single cpu */
+-	if (cpu == 0)
+-		dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+-	else
+-		cclk_mhz = -1;
+-
+-	return cclk_mhz;
+-}
+-
+-static int bf548_target(struct cpufreq_policy *policy,
+-			    unsigned int target_freq, unsigned int relation)
+-{
+-	unsigned long cclk_mhz;
+-	unsigned long vco_mhz;
+-	unsigned long flags;
+-	unsigned int index;
+-	struct cpufreq_freqs freqs;
+-
+-	if (cpufreq_frequency_table_target(policy, bf548_freq_table, target_freq, relation, &index))
+-		return -EINVAL;
+-
+-	cclk_mhz = bf548_freq_table[index].frequency;
+-	vco_mhz = bf548_freq_table[index].index;
+-
+-	dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+-	freqs.old = bf548_getfreq(0);
+-	freqs.new = cclk_mhz;
+-	freqs.cpu = 0;
+-
+-	pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+-	         cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+-
+-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+-	local_irq_save(flags);
+-	dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+-	local_irq_restore(flags);
+-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+-
+-	vco_mhz = get_vco();
+-	cclk_mhz = get_cclk();
+-	return 0;
+-}
+-
+-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+- * this platform, anyway.
+- */
+-static int bf548_verify_speed(struct cpufreq_policy *policy)
+-{
+-	return cpufreq_frequency_table_verify(policy, &bf548_freq_table);
+-}
+-
+-static int __init __bf548_cpu_init(struct cpufreq_policy *policy)
+-{
+-	if (policy->cpu != 0)
+-		return -EINVAL;
+-
+-	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+-
+-	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+-	/*Now ,only support one cpu */
+-	policy->cur = bf548_getfreq(0);
+-	cpufreq_frequency_table_get_attr(bf548_freq_table, policy->cpu);
+-	return cpufreq_frequency_table_cpuinfo(policy, bf548_freq_table);
+-}
+-
+-static struct freq_attr *bf548_freq_attr[] = {
+-	&cpufreq_freq_attr_scaling_available_freqs,
+-	NULL,
+-};
+-
+-static struct cpufreq_driver bf548_driver = {
+-	.verify = bf548_verify_speed,
+-	.target = bf548_target,
+-	.get = bf548_getfreq,
+-	.init = __bf548_cpu_init,
+-	.name = "bf548",
+-	.owner = THIS_MODULE,
+-	.attr = bf548_freq_attr,
+-};
+-
+-static int __init bf548_cpu_init(void)
+-{
+-	return cpufreq_register_driver(&bf548_driver);
+-}
+-
+-static void __exit bf548_cpu_exit(void)
+-{
+-	cpufreq_unregister_driver(&bf548_driver);
+-}
+-
+-MODULE_AUTHOR("Mickael Kang");
+-MODULE_DESCRIPTION("cpufreq driver for BF548 CPU");
+-MODULE_LICENSE("GPL");
+-
+-module_init(bf548_cpu_init);
+-module_exit(bf548_cpu_exit);
+diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
+index f547929..74730eb 100644
+--- a/arch/blackfin/mach-bf548/dma.c
++++ b/arch/blackfin/mach-bf548/dma.c
+@@ -32,7 +32,7 @@
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+ 
+- struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ 	(struct dma_register *) DMA0_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA1_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA2_NEXT_DESC_PTR,
+@@ -66,7 +66,7 @@
+ 	(struct dma_register *) MDMA_D3_NEXT_DESC_PTR,
+ 	(struct dma_register *) MDMA_S3_NEXT_DESC_PTR,
+ };
+-EXPORT_SYMBOL(base_addr);
++EXPORT_SYMBOL(dma_io_base_addr);
+ 
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S
+index 46222a7..f719114 100644
+--- a/arch/blackfin/mach-bf548/head.S
++++ b/arch/blackfin/mach-bf548/head.S
+@@ -36,9 +36,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+ 
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -456,18 +453,3 @@ ENTRY(_start_dma_code)
+ 	RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long   0
+-__ramstart:
+-.long   0
+-__ramend:
+-.long   0
+diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
+index bf9e738..9fd5809 100644
+--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
++++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
+@@ -283,6 +283,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ #define PATA_INT	119
+ 
+@@ -330,6 +349,10 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+ 	&isp1362_hcd_device,
+ #endif
+@@ -349,7 +372,7 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
+ 
+ static int __init cm_bf561_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	platform_add_devices(cm_bf561_devices, ARRAY_SIZE(cm_bf561_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
+index d357f64..0d74b7d 100644
+--- a/arch/blackfin/mach-bf561/boards/ezkit.c
++++ b/arch/blackfin/mach-bf561/boards/ezkit.c
+@@ -78,7 +78,7 @@ int __init bfin_isp1761_init(void)
+ {
+ 	unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+ 
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+ 
+ 	return platform_add_devices(bfin_isp1761_devices, num_devices);
+@@ -220,6 +220,26 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++		.start = 0xFFC00400,
++		.end = 0xFFC004FF,
++		.flags = IORESOURCE_MEM,
++	},
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++	.name = "bfin_sir",
++	.id = 0,
++	.num_resources = ARRAY_SIZE(bfin_sir_resources),
++	.resource = bfin_sir_resources,
++};
++#endif
++
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ static struct mtd_partition ezkit_partitions[] = {
+ 	{
+ 		.name       = "Bootloader",
+@@ -227,7 +247,7 @@ static struct mtd_partition ezkit_partitions[] = {
+ 		.offset     = 0,
+ 	}, {
+ 		.name       = "Kernel",
+-		.size       = 0xE0000,
++		.size       = 0x1C0000,
+ 		.offset     = MTDPART_OFS_APPEND,
+ 	}, {
+ 		.name       = "RootFS",
+@@ -257,6 +277,7 @@ static struct platform_device ezkit_flash_device = {
+ 	.num_resources = 1,
+ 	.resource      = &ezkit_flash_resource,
+ };
++#endif
+ 
+ #ifdef CONFIG_SPI_BFIN
+ #if defined(CONFIG_SND_BLACKFIN_AD1836) \
+@@ -443,6 +464,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ 	&bfin_uart_device,
+ #endif
+ 
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++	&bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ 	&bfin_pata_device,
+ #endif
+@@ -460,7 +485,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ #endif
+ 
+ 	&bfin_gpios_device,
++
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ 	&ezkit_flash_device,
++#endif
+ };
+ 
+ static int __init ezkit_init(void)
+diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c
+index fc80c5d..2faa007 100644
+--- a/arch/blackfin/mach-bf561/boards/generic_board.c
++++ b/arch/blackfin/mach-bf561/boards/generic_board.c
+@@ -70,7 +70,7 @@ static struct platform_device *generic_board_devices[] __initdata = {
+ 
+ static int __init generic_board_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	return platform_add_devices(generic_board_devices,
+ 				    ARRAY_SIZE(generic_board_devices));
+ }
+diff --git a/arch/blackfin/mach-bf561/boards/tepla.c b/arch/blackfin/mach-bf561/boards/tepla.c
+index ec6a220..c9174b3 100644
+--- a/arch/blackfin/mach-bf561/boards/tepla.c
++++ b/arch/blackfin/mach-bf561/boards/tepla.c
+@@ -50,7 +50,7 @@ static struct platform_device *tepla_devices[] __initdata = {
+ 
+ static int __init tepla_init(void)
+ {
+-	printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ 	return platform_add_devices(tepla_devices, ARRAY_SIZE(tepla_devices));
+ }
+ 
+diff --git a/arch/blackfin/mach-bf561/dma.c b/arch/blackfin/mach-bf561/dma.c
+index 89c65bb..24415eb 100644
+--- a/arch/blackfin/mach-bf561/dma.c
++++ b/arch/blackfin/mach-bf561/dma.c
+@@ -26,10 +26,12 @@
+  * to the Free Software Foundation, Inc.,
+  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+  */
++#include <linux/module.h>
++
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+ 
+-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ 	(struct dma_register *) DMA1_0_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA1_1_NEXT_DESC_PTR,
+ 	(struct dma_register *) DMA1_2_NEXT_DESC_PTR,
+@@ -67,6 +69,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ 	(struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
+ 	(struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
+ };
++EXPORT_SYMBOL(dma_io_base_addr);
+ 
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf561/head.S b/arch/blackfin/mach-bf561/head.S
+index 96a3d45..5b8bd40 100644
+--- a/arch/blackfin/mach-bf561/head.S
++++ b/arch/blackfin/mach-bf561/head.S
+@@ -37,9 +37,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+ 
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -139,26 +136,26 @@ ENTRY(__start)
+ 
+ 	/* Initialise UART - when booting from u-boot, the UART is not disabled
+ 	 * so if we dont initalize here, our serial console gets hosed */
+-	p0.h = hi(UART_LCR);
+-	p0.l = lo(UART_LCR);
++	p0.h = hi(BFIN_UART_LCR);
++	p0.l = lo(BFIN_UART_LCR);
+ 	r0 = 0x0(Z);
+ 	w[p0] = r0.L;	/* To enable DLL writes */
+ 	ssync;
+ 
+-	p0.h = hi(UART_DLL);
+-	p0.l = lo(UART_DLL);
++	p0.h = hi(BFIN_UART_DLL);
++	p0.l = lo(BFIN_UART_DLL);
+ 	r0 = 0x0(Z);
+ 	w[p0] = r0.L;
+ 	ssync;
+ 
+-	p0.h = hi(UART_DLH);
+-	p0.l = lo(UART_DLH);
++	p0.h = hi(BFIN_UART_DLH);
++	p0.l = lo(BFIN_UART_DLH);
+ 	r0 = 0x00(Z);
+ 	w[p0] = r0.L;
+ 	ssync;
+ 
+-	p0.h = hi(UART_GCTL);
+-	p0.l = lo(UART_GCTL);
++	p0.h = hi(BFIN_UART_GCTL);
++	p0.l = lo(BFIN_UART_GCTL);
+ 	r0 = 0x0(Z);
+ 	w[p0] = r0.L;	/* To enable UART clock */
+ 	ssync;
+@@ -411,18 +408,3 @@ ENTRY(_start_dma_code)
+ 	RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long   0
+-__ramstart:
+-.long   0
+-__ramend:
+-.long   0
+diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
+index 15e33ca..393081e 100644
+--- a/arch/blackfin/mach-common/Makefile
++++ b/arch/blackfin/mach-common/Makefile
+@@ -6,4 +6,5 @@ obj-y := \
+ 	cache.o cacheinit.o entry.o \
+ 	interrupt.o lock.o irqpanic.o arch_checks.o ints-priority.o
+ 
+-obj-$(CONFIG_PM)                 += pm.o dpmc.o
++obj-$(CONFIG_PM)         += pm.o dpmc.o
++obj-$(CONFIG_CPU_FREQ)   += cpufreq.o
+diff --git a/arch/blackfin/mach-common/arch_checks.c b/arch/blackfin/mach-common/arch_checks.c
+index 2f6ce39..caaab49 100644
+--- a/arch/blackfin/mach-common/arch_checks.c
++++ b/arch/blackfin/mach-common/arch_checks.c
+@@ -54,7 +54,8 @@
+ 
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+ 
++#ifdef CONFIG_MEM_SIZE
+ #if (CONFIG_MEM_SIZE % 4)
+ #error "SDRAM mem size must be multible of 4MB"
+ #endif
+-
++#endif
+diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
+new file mode 100644
+index 0000000..ed81e00
+--- /dev/null
++++ b/arch/blackfin/mach-common/cpufreq.c
+@@ -0,0 +1,194 @@
++/*
++ * File:	 arch/blackfin/mach-common/cpufreq.c
++ * Based on:
++ * Author:
++ *
++ * Created:
++ * Description:	 Blackfin core clock scaling
++ *
++ * Modified:
++ *		 Copyright 2004-2008 Analog Devices Inc.
++ *
++ * Bugs:	 Enter bugs at http://blackfin.uclinux.org/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see the file COPYING, or write
++ * to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA	02110-1301	USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/cpufreq.h>
++#include <linux/fs.h>
++#include <asm/blackfin.h>
++#include <asm/time.h>
++
++
++/* this is the table of CCLK frequencies, in Hz */
++/* .index is the entry in the auxillary dpm_state_table[] */
++static struct cpufreq_frequency_table bfin_freq_table[] = {
++	{
++		.frequency = CPUFREQ_TABLE_END,
++		.index = 0,
++	},
++	{
++		.frequency = CPUFREQ_TABLE_END,
++		.index = 1,
++	},
++	{
++		.frequency = CPUFREQ_TABLE_END,
++		.index = 2,
++	},
++	{
++		.frequency = CPUFREQ_TABLE_END,
++		.index = 0,
++	},
++};
++
++static struct bfin_dpm_state {
++	unsigned int csel; /* system clock divider */
++	unsigned int tscale; /* change the divider on the core timer interrupt */
++} dpm_state_table[3];
++
++/**************************************************************************/
++
++static unsigned int bfin_getfreq(unsigned int cpu)
++{
++	/* The driver only support single cpu */
++	if (cpu != 0)
++		return -1;
++
++	return get_cclk();
++}
++
++
++static int bfin_target(struct cpufreq_policy *policy,
++			unsigned int target_freq, unsigned int relation)
++{
++	unsigned int index, plldiv, tscale;
++	unsigned long flags, cclk_hz;
++	struct cpufreq_freqs freqs;
++
++	if (cpufreq_frequency_table_target(policy, bfin_freq_table,
++		 target_freq, relation, &index))
++		return -EINVAL;
++
++	cclk_hz = bfin_freq_table[index].frequency;
++
++	freqs.old = bfin_getfreq(0);
++	freqs.new = cclk_hz;
++	freqs.cpu = 0;
++
++	pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n",
++		 cclk_hz, target_freq, freqs.old);
++
++	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
++	local_irq_save(flags);
++		plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel;
++		tscale = dpm_state_table[index].tscale;
++		bfin_write_PLL_DIV(plldiv);
++		/* we have to adjust the core timer, because it is using cclk */
++		bfin_write_TSCALE(tscale);
++		SSYNC();
++	local_irq_restore(flags);
++	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
++
++	return 0;
++}
++
++static int bfin_verify_speed(struct cpufreq_policy *policy)
++{
++	return cpufreq_frequency_table_verify(policy, bfin_freq_table);
++}
++
++static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
++{
++
++	unsigned long cclk, sclk, csel, min_cclk;
++	int index;
++
++#ifdef CONFIG_CYCLES_CLOCKSOURCE
++/*
++ * Clocksource CYCLES is still CONTINUOUS but not longer MONOTONIC in case we enable
++ * CPU frequency scaling, since CYCLES runs off Core Clock.
++ */
++	printk(KERN_WARNING "CPU frequency scaling not supported: Clocksource not suitable\n"
++		return -ENODEV;
++#endif
++
++	if (policy->cpu != 0)
++		return -EINVAL;
++
++	cclk = get_cclk();
++	sclk = get_sclk();
++
++#if ANOMALY_05000273
++	min_cclk = sclk * 2;
++#else
++	min_cclk = sclk;
++#endif
++	csel = ((bfin_read_PLL_DIV() & CSEL) >> 4);
++
++	for (index = 0;  (cclk >> index) >= min_cclk && csel <= 3; index++, csel++) {
++		bfin_freq_table[index].frequency = cclk >> index;
++		dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */
++		dpm_state_table[index].tscale =  (TIME_SCALE / (1 << csel)) - 1;
++
++		pr_debug("cpufreq: freq:%d csel:%d tscale:%d\n",
++						 bfin_freq_table[index].frequency,
++						 dpm_state_table[index].csel,
++						 dpm_state_table[index].tscale);
++	}
++
++	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
++
++	policy->cpuinfo.transition_latency = (bfin_read_PLL_LOCKCNT() / (sclk / 1000000)) * 1000;
++	/*Now ,only support one cpu */
++	policy->cur = cclk;
++	cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu);
++	return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table);
++}
++
++static struct freq_attr *bfin_freq_attr[] = {
++	&cpufreq_freq_attr_scaling_available_freqs,
++	NULL,
++};
++
++static struct cpufreq_driver bfin_driver = {
++	.verify = bfin_verify_speed,
++	.target = bfin_target,
++	.get = bfin_getfreq,
++	.init = __bfin_cpu_init,
++	.name = "bfin cpufreq",
++	.owner = THIS_MODULE,
++	.attr = bfin_freq_attr,
++};
++
++static int __init bfin_cpu_init(void)
++{
++	return cpufreq_register_driver(&bfin_driver);
++}
++
++static void __exit bfin_cpu_exit(void)
++{
++	cpufreq_unregister_driver(&bfin_driver);
++}
++
++MODULE_AUTHOR("Michael Hennerich <hennerich at blackfin.uclinux.org>");
++MODULE_DESCRIPTION("cpufreq driver for Blackfin");
++MODULE_LICENSE("GPL");
++
++module_init(bfin_cpu_init);
++module_exit(bfin_cpu_exit);
+diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
+index cee54ce..f2fb87e 100644
+--- a/arch/blackfin/mach-common/entry.S
++++ b/arch/blackfin/mach-common/entry.S
+@@ -38,6 +38,7 @@
+ #include <linux/unistd.h>
+ #include <asm/blackfin.h>
+ #include <asm/errno.h>
++#include <asm/fixed_code.h>
+ #include <asm/thread_info.h>  /* TIF_NEED_RESCHED */
+ #include <asm/asm-offsets.h>
+ #include <asm/trace.h>
+@@ -52,15 +53,6 @@
+ # define EX_SCRATCH_REG CYCLES
+ #endif
+ 
+-#if ANOMALY_05000281
+-ENTRY(_safe_speculative_execution)
+-	NOP;
+-	NOP;
+-	NOP;
+-	jump _safe_speculative_execution;
+-ENDPROC(_safe_speculative_execution)
+-#endif
+-
+ #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
+ .section .l1.text
+ #else
+@@ -121,10 +113,14 @@ ENTRY(_ex_icplb_miss)
+ 	(R7:6,P5:4) = [sp++];
+ 	ASTAT = [sp++];
+ 	SAVE_ALL_SYS
+-	DEBUG_HWTRACE_SAVE(p5, r7)
+ #ifdef CONFIG_MPU
++	/* We must load R1 here, _before_ DEBUG_HWTRACE_SAVE, since that
++	 * will change the stack pointer.  */
+ 	R0 = SEQSTAT;
+ 	R1 = SP;
++#endif
++	DEBUG_HWTRACE_SAVE(p5, r7)
++#ifdef CONFIG_MPU
+ 	sp += -12;
+ 	call _cplb_hdr;
+ 	sp += 12;
+@@ -191,6 +187,7 @@ ENTRY(_bfin_return_from_exception)
+ ENDPROC(_bfin_return_from_exception)
+ 
+ ENTRY(_handle_bad_cplb)
++	DEBUG_HWTRACE_RESTORE(p5, r7)
+ 	/* To get here, we just tried and failed to change a CPLB
+ 	 * so, handle things in trap_c (C code), by lowering to
+ 	 * IRQ5, just like we normally do. Since this is not a
+@@ -225,6 +222,26 @@ ENTRY(_ex_trap_c)
+ 	[p4] = p5;
+ 	csync;
+ 
++	p4.l = lo(DCPLB_FAULT_ADDR);
++	p4.h = hi(DCPLB_FAULT_ADDR);
++	r7 = [p4];
++	p5.h = _saved_dcplb_fault_addr;
++	p5.l = _saved_dcplb_fault_addr;
++	[p5] = r7;
++
++	r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
++	p5.h = _saved_icplb_fault_addr;
++	p5.l = _saved_icplb_fault_addr;
++	[p5] = r7;
++
++	p4.l = __retx;
++	p4.h = __retx;
++	r6 = retx;
++	[p4] = r6;
++	p4.l = lo(SAFE_USER_INSTRUCTION);
++	p4.h = hi(SAFE_USER_INSTRUCTION);
++	retx = p4;
++
+ 	/* Disable all interrupts, but make sure level 5 is enabled so
+ 	 * we can switch to that level.  Save the old mask.  */
+ 	cli r6;
+@@ -234,23 +251,6 @@ ENTRY(_ex_trap_c)
+ 	r6 = 0x3f;
+ 	sti r6;
+ 
+-	/* Save the excause into a circular buffer, in case the instruction
+-	 * which caused this excecptions causes others.
+-	 */
+-	P5.l = _in_ptr_excause;
+-	P5.h = _in_ptr_excause;
+-	R7 = [P5];
+-	R7 += 4;
+-	R6 = 0xF;
+-	R7 = R7 & R6;
+-	[P5] = R7;
+-	R6.l = _excause_circ_buf;
+-	R6.h = _excause_circ_buf;
+-	R7 = R7 + R6;
+-	p5 = R7;
+-	R6 = SEQSTAT;
+-	[P5] = R6;
+-
+ 	(R7:6,P5:4) = [sp++];
+ 	ASTAT = [sp++];
+ 	SP = EX_SCRATCH_REG;
+@@ -307,6 +307,11 @@ ENDPROC(_double_fault)
+ ENTRY(_exception_to_level5)
+ 	SAVE_ALL_SYS
+ 
++	p4.l = __retx;
++	p4.h = __retx;
++	r6 = [p4];
++	[sp + PT_PC] = r6;
++
+ 	/* Restore interrupt mask.  We haven't pushed RETI, so this
+ 	 * doesn't enable interrupts until we return from this handler.  */
+ 	p4.l = _excpt_saved_imask;
+@@ -328,42 +333,11 @@ ENTRY(_exception_to_level5)
+ 	r0 = [p2];              /* Read current IPEND */
+ 	[sp + PT_IPEND] = r0;   /* Store IPEND */
+ 
+-	/* Pop the excause from the circular buffer and push it on the stack
+-	 * (in the right place - if you change the location of SEQSTAT, you
+-	 * must change this offset.
+-	 */
+-.L_excep_to_5_again:
+-	P5.l = _out_ptr_excause;
+-	P5.h = _out_ptr_excause;
+-	R7 = [P5];
+-	R7 += 4;
+-	R6 = 0xF;
+-	R7 = R7 & R6;
+-	[P5] = R7;
+-	R6.l = _excause_circ_buf;
+-	R6.h = _excause_circ_buf;
+-	R7 = R7 + R6;
+-	P5 = R7;
+-	R1 = [P5];
+-	[SP + PT_SEQSTAT] = r1;
+-
+ 	r0 = sp; 	/* stack frame pt_regs pointer argument ==> r0 */
+ 	SP += -12;
+ 	call _trap_c;
+ 	SP += 12;
+ 
+-	/* See if anything else is in the exception buffer
+-	 * if there is, process it
+-	 */
+-	P5.l = _out_ptr_excause;
+-	P5.h = _out_ptr_excause;
+-	P4.l = _in_ptr_excause;
+-	P4.h = _in_ptr_excause;
+-	R6 = [P5];
+-	R7 = [P4];
+-	CC = R6 == R7;
+-	if ! CC JUMP .L_excep_to_5_again
+-
+ 	call _ret_from_exception;
+ 	RESTORE_ALL_SYS
+ 	rti;
+@@ -727,8 +701,8 @@ ENTRY(_return_from_int)
+ 	[p0] = p1;
+ 	csync;
+ #if ANOMALY_05000281
+-	r0.l = _safe_speculative_execution;
+-	r0.h = _safe_speculative_execution;
++	r0.l = lo(SAFE_USER_INSTRUCTION);
++	r0.h = hi(SAFE_USER_INSTRUCTION);
+ 	reti = r0;
+ #endif
+ 	r0 = 0x801f (z);
+@@ -741,8 +715,8 @@ ENDPROC(_return_from_int)
+ 
+ ENTRY(_lower_to_irq14)
+ #if ANOMALY_05000281
+-	r0.l = _safe_speculative_execution;
+-	r0.h = _safe_speculative_execution;
++	r0.l = lo(SAFE_USER_INSTRUCTION);
++	r0.h = hi(SAFE_USER_INSTRUCTION);
+ 	reti = r0;
+ #endif
+ 	r0 = 0x401f;
+@@ -809,20 +783,6 @@ _schedule_and_signal:
+ 	rti;
+ ENDPROC(_lower_to_irq14)
+ 
+-/* Make sure when we start, that the circular buffer is initialized properly
+- * R0 and P0 are call clobbered, so we can use them here.
+- */
+-ENTRY(_init_exception_buff)
+-	r0 = 0;
+-	p0.h = _in_ptr_excause;
+-	p0.l = _in_ptr_excause;
+-	[p0] = r0;
+-	p0.h = _out_ptr_excause;
+-	p0.l = _out_ptr_excause;
+-	[p0] = r0;
+-	rts;
+-ENDPROC(_init_exception_buff)
+-
+ /* We handle this 100% in exception space - to reduce overhead
+  * Only potiential problem is if the software buffer gets swapped out of the
+  * CPLB table - then double fault. - so we don't let this happen in other places
+@@ -1398,17 +1358,7 @@ _exception_stack_top:
+ _last_cplb_fault_retx:
+ 	.long 0;
+ #endif
+-/*
+- * Single instructions can have multiple faults, which need to be
+- * handled by traps.c, in irq5. We store the exception cause to ensure
+- * we don't miss a double fault condition
+- */
+-ENTRY(_in_ptr_excause)
++	/* Used to save the real RETX when temporarily storing a safe
++	 * return address.  */
++__retx:
+ 	.long 0;
+-ENTRY(_out_ptr_excause)
+-	.long 0;
+-ALIGN
+-ENTRY(_excause_circ_buf)
+-	.rept 4
+-	.long 0
+-	.endr
+diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
+index 225ef14..f5fd768 100644
+--- a/arch/blackfin/mach-common/ints-priority.c
++++ b/arch/blackfin/mach-common/ints-priority.c
+@@ -316,7 +316,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
+ 		printk(KERN_ERR
+ 		       "%s : %s : LINE %d :\nIRQ ?: PERIPHERAL ERROR"
+ 		       " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
+-		       __FUNCTION__, __FILE__, __LINE__);
++		       __func__, __FILE__, __LINE__);
+ 
+ }
+ #endif				/* BF537_GENERIC_ERROR_INT_DEMUX */
+@@ -326,6 +326,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
+ static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
+ static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
+ 
++extern void bfin_gpio_irq_prepare(unsigned gpio);
+ 
+ static void bfin_gpio_ack_irq(unsigned int irq)
+ {
+@@ -364,35 +365,25 @@ static void bfin_gpio_unmask_irq(unsigned int irq)
+ 
+ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+ {
+-	unsigned int ret;
+ 	u16 gpionr = irq - IRQ_PF0;
+-	char buf[8];
+ 
+-	if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+-		snprintf(buf, sizeof buf, "IRQ %d", irq);
+-		ret = gpio_request(gpionr, buf);
+-		if (ret)
+-			return ret;
+-	}
++	if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
++		bfin_gpio_irq_prepare(gpionr);
+ 
+ 	gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ 	bfin_gpio_unmask_irq(irq);
+ 
+-	return ret;
++	return 0;
+ }
+ 
+ static void bfin_gpio_irq_shutdown(unsigned int irq)
+ {
+ 	bfin_gpio_mask_irq(irq);
+-	gpio_free(irq - IRQ_PF0);
+ 	gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0);
+ }
+ 
+ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+ {
+-
+-	unsigned int ret;
+-	char buf[8];
+ 	u16 gpionr = irq - IRQ_PF0;
+ 
+ 	if (type == IRQ_TYPE_PROBE) {
+@@ -404,12 +395,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+ 
+ 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+ 		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+-		if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+-			snprintf(buf, sizeof buf, "IRQ %d", irq);
+-			ret = gpio_request(gpionr, buf);
+-			if (ret)
+-				return ret;
+-		}
++		if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
++			bfin_gpio_irq_prepare(gpionr);
+ 
+ 		gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ 	} else {
+@@ -595,6 +582,8 @@ static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
+ 	(struct pin_int_t *)PINT3_MASK_SET,
+ };
+ 
++extern void bfin_gpio_irq_prepare(unsigned gpio);
++
+ inline unsigned short get_irq_base(u8 bank, u8 bmap)
+ {
+ 
+@@ -697,8 +686,6 @@ static void bfin_gpio_unmask_irq(unsigned int irq)
+ 
+ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+ {
+-	unsigned int ret;
+-	char buf[8];
+ 	u16 gpionr = irq_to_gpio(irq);
+ 	u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ 
+@@ -709,17 +696,13 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+ 		return -ENODEV;
+ 	}
+ 
+-	if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+-		snprintf(buf, sizeof buf, "IRQ %d", irq);
+-		ret = gpio_request(gpionr, buf);
+-		if (ret)
+-			return ret;
+-	}
++	if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
++		bfin_gpio_irq_prepare(gpionr);
+ 
+ 	gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ 	bfin_gpio_unmask_irq(irq);
+ 
+-	return ret;
++	return 0;
+ }
+ 
+ static void bfin_gpio_irq_shutdown(unsigned int irq)
+@@ -727,15 +710,12 @@ static void bfin_gpio_irq_shutdown(unsigned int irq)
+ 	u16 gpionr = irq_to_gpio(irq);
+ 
+ 	bfin_gpio_mask_irq(irq);
+-	gpio_free(gpionr);
+ 	gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+ }
+ 
+ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+ {
+ 
+-	unsigned int ret;
+-	char buf[8];
+ 	u16 gpionr = irq_to_gpio(irq);
+ 	u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ 	u32 pintbit = PINT_BIT(pint_val);
+@@ -753,12 +733,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+ 
+ 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+ 		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+-		if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+-			snprintf(buf, sizeof buf, "IRQ %d", irq);
+-			ret = gpio_request(gpionr, buf);
+-			if (ret)
+-				return ret;
+-		}
++		if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
++			bfin_gpio_irq_prepare(gpionr);
+ 
+ 		gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ 	} else {
+@@ -766,8 +742,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+ 		return 0;
+ 	}
+ 
+-	gpio_direction_input(gpionr);
+-
+ 	if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
+ 		pint[bank]->invert_set = pintbit;	/* low or falling edge denoted by one */
+ 	else
+@@ -965,8 +939,6 @@ int __init init_arch_irq(void)
+ 
+ 	local_irq_disable();
+ 
+-	init_exception_buff();
+-
+ #ifdef CONFIG_BF54x
+ # ifdef CONFIG_PINTx_REASSIGN
+ 	pint[0]->assign = CONFIG_PINT0_ASSIGN;
+diff --git a/arch/blackfin/mach-common/lock.S b/arch/blackfin/mach-common/lock.S
+index 28b87fe..30b887e 100644
+--- a/arch/blackfin/mach-common/lock.S
++++ b/arch/blackfin/mach-common/lock.S
+@@ -174,7 +174,7 @@ ENTRY(_cache_lock)
+ 	CLI R3;
+ 
+ 	R7 = [P1];
+-	R2 = 0xFFFFFF87 (X);
++	R2 = ~(0x78) (X);	/* mask out ILOC */
+ 	R7 = R7 & R2;
+ 	R0 = R0 << 3;
+ 	R7 = R0 | R7;
+diff --git a/arch/blackfin/mm/blackfin_sram.c b/arch/blackfin/mm/blackfin_sram.c
+index e41f0e8..3246f91 100644
+--- a/arch/blackfin/mm/blackfin_sram.c
++++ b/arch/blackfin/mm/blackfin_sram.c
+@@ -401,7 +401,7 @@ EXPORT_SYMBOL(l1_data_sram_free);
+ 
+ void *l1_inst_sram_alloc(size_t size)
+ {
+-#if L1_DATA_A_LENGTH != 0
++#if L1_CODE_LENGTH != 0
+ 	unsigned flags;
+ 	void *addr;
+ 
+diff --git a/arch/blackfin/oprofile/common.c b/arch/blackfin/oprofile/common.c
+index cb8b8d5..0f6d303 100644
+--- a/arch/blackfin/oprofile/common.c
++++ b/arch/blackfin/oprofile/common.c
+@@ -75,7 +75,7 @@ static int op_bfin_start(void)
+ {
+ 	int ret = -EBUSY;
+ 
+-	printk(KERN_INFO "KSDBG:in %s\n", __FUNCTION__);
++	printk(KERN_INFO "KSDBG:in %s\n", __func__);
+ 	mutex_lock(&pfmon_lock);
+ 	if (!pfmon_enabled) {
+ 		ret = model->start(ctr);
+diff --git a/arch/blackfin/oprofile/op_model_bf533.c b/arch/blackfin/oprofile/op_model_bf533.c
+index 872dffe..d1c698b 100644
+--- a/arch/blackfin/oprofile/op_model_bf533.c
++++ b/arch/blackfin/oprofile/op_model_bf533.c
+@@ -125,7 +125,7 @@ int pm_overflow_handler(int irq, struct pt_regs *regs)
+ 	unsigned int pc, pfctl;
+ 	unsigned int count[2];
+ 
+-	pr_debug("get interrupt in %s\n", __FUNCTION__);
++	pr_debug("get interrupt in %s\n", __func__);
+ 	if (oprofile_running == 0) {
+ 		pr_debug("error: entering interrupt when oprofile is stopped.\n\r");
+ 		return -1;
+diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
+index c8e8ea5..ee7bcd4 100644
+--- a/arch/cris/kernel/Makefile
++++ b/arch/cris/kernel/Makefile
+@@ -5,8 +5,7 @@
+ 
+ extra-y	:= vmlinux.lds
+ 
+-obj-y   := process.o traps.o irq.o ptrace.o setup.o \
+-	   time.o sys_cris.o semaphore.o
++obj-y   := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o
+ 
+ obj-$(CONFIG_MODULES)    += crisksyms.o
+ obj-$(CONFIG_MODULES)	 += module.o
+diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
+index 62f0e75..7ac000f 100644
+--- a/arch/cris/kernel/crisksyms.c
++++ b/arch/cris/kernel/crisksyms.c
+@@ -9,7 +9,6 @@
+ #include <linux/string.h>
+ #include <linux/tty.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+@@ -49,12 +48,6 @@ EXPORT_SYMBOL(__negdi2);
+ EXPORT_SYMBOL(__ioremap);
+ EXPORT_SYMBOL(iounmap);
+ 
+-/* Semaphore functions */
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down_trylock);
+-
+ /* Userspace access functions */
+ EXPORT_SYMBOL(__copy_user_zeroing);
+ EXPORT_SYMBOL(__copy_user);
+diff --git a/arch/cris/kernel/semaphore.c b/arch/cris/kernel/semaphore.c
+deleted file mode 100644
+index f137a43..0000000
+--- a/arch/cris/kernel/semaphore.c
++++ /dev/null
+@@ -1,129 +0,0 @@
+-/*
+- *  Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/sched.h>
+-#include <asm/semaphore-helper.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit.  ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore.  The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+-	wake_one_more(sem);
+-	wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function.  Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible.  This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return.  If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-#define DOWN_VAR				\
+-	struct task_struct *tsk = current;	\
+-	wait_queue_t wait;			\
+-	init_waitqueue_entry(&wait, tsk);
+-
+-#define DOWN_HEAD(task_state)						\
+-									\
+-									\
+-	tsk->state = (task_state);					\
+-	add_wait_queue(&sem->wait, &wait);				\
+-									\
+-	/*								\
+-	 * Ok, we're set up.  sem->count is known to be less than zero	\
+-	 * so we must wait.						\
+-	 *								\
+-	 * We can let go the lock for purposes of waiting.		\
+-	 * We re-acquire it after awaking so as to protect		\
+-	 * all semaphore operations.					\
+-	 *								\
+-	 * If "up()" is called before we call waking_non_zero() then	\
+-	 * we will catch it right away.  If it is called later then	\
+-	 * we will have to go through a wakeup cycle to catch it.	\
+-	 *								\
+-	 * Multiple waiters contend for the semaphore lock to see	\
+-	 * who gets to gate through and who has to wait some more.	\
+-	 */								\
+-	for (;;) {
+-
+-#define DOWN_TAIL(task_state)			\
+-		tsk->state = (task_state);	\
+-	}					\
+-	tsk->state = TASK_RUNNING;		\
+-	remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	DOWN_VAR
+-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+-	if (waking_non_zero(sem))
+-		break;
+-	schedule();
+-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-	DOWN_VAR
+-	DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+-	ret = waking_non_zero_interruptible(sem, tsk);
+-	if (ret)
+-	{
+-		if (ret == 1)
+-			/* ret != 0 only if we get interrupted -arca */
+-			ret = 0;
+-		break;
+-	}
+-	schedule();
+-	DOWN_TAIL(TASK_INTERRUPTIBLE)
+-	return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+-	return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
+index e8f73ed..c36f70b 100644
+--- a/arch/frv/kernel/Makefile
++++ b/arch/frv/kernel/Makefile
+@@ -9,7 +9,7 @@ extra-y:= head.o init_task.o vmlinux.lds
+ 
+ obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
+ 	 kernel_execve.o process.o traps.o ptrace.o signal.o dma.o \
+-	 sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \
++	 sys_frv.o time.o setup.o frv_ksyms.o \
+ 	 debug-stub.o irq.o sleep.o uaccess.o
+ 
+ obj-$(CONFIG_GDBSTUB)		+= gdb-stub.o gdb-io.o
+diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
+index f772704..0316b3c 100644
+--- a/arch/frv/kernel/frv_ksyms.c
++++ b/arch/frv/kernel/frv_ksyms.c
+@@ -12,7 +12,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/hardirq.h>
+ #include <asm/cacheflush.h>
+diff --git a/arch/frv/kernel/semaphore.c b/arch/frv/kernel/semaphore.c
+deleted file mode 100644
+index 7ee3a14..0000000
+--- a/arch/frv/kernel/semaphore.c
++++ /dev/null
+@@ -1,155 +0,0 @@
+-/* semaphore.c: FR-V semaphores
+- *
+- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.com)
+- * - Derived from lib/rwsem-spinlock.c
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/module.h>
+-#include <asm/semaphore.h>
+-
+-struct sem_waiter {
+-	struct list_head	list;
+-	struct task_struct	*task;
+-};
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-void semtrace(struct semaphore *sem, const char *str)
+-{
+-	if (sem->debug)
+-		printk("[%d] %s({%d,%d})\n",
+-		       current->pid,
+-		       str,
+-		       sem->counter,
+-		       list_empty(&sem->wait_list) ? 0 : 1);
+-}
+-#else
+-#define semtrace(SEM,STR) do { } while(0)
+-#endif
+-
+-/*
+- * wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __down(struct semaphore *sem, unsigned long flags)
+-{
+-	struct task_struct *tsk = current;
+-	struct sem_waiter waiter;
+-
+-	semtrace(sem, "Entering __down");
+-
+-	/* set up my own style of waitqueue */
+-	waiter.task = tsk;
+-	get_task_struct(tsk);
+-
+-	list_add_tail(&waiter.list, &sem->wait_list);
+-
+-	/* we don't need to touch the semaphore struct anymore */
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+-	/* wait to be given the semaphore */
+-	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-
+-	for (;;) {
+-		if (list_empty(&waiter.list))
+-			break;
+-		schedule();
+-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-	}
+-
+-	tsk->state = TASK_RUNNING;
+-	semtrace(sem, "Leaving __down");
+-}
+-
+-EXPORT_SYMBOL(__down);
+-
+-/*
+- * interruptibly wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-int __down_interruptible(struct semaphore *sem, unsigned long flags)
+-{
+-	struct task_struct *tsk = current;
+-	struct sem_waiter waiter;
+-	int ret;
+-
+-	semtrace(sem,"Entering __down_interruptible");
+-
+-	/* set up my own style of waitqueue */
+-	waiter.task = tsk;
+-	get_task_struct(tsk);
+-
+-	list_add_tail(&waiter.list, &sem->wait_list);
+-
+-	/* we don't need to touch the semaphore struct anymore */
+-	set_task_state(tsk, TASK_INTERRUPTIBLE);
+-
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+-	/* wait to be given the semaphore */
+-	ret = 0;
+-	for (;;) {
+-		if (list_empty(&waiter.list))
+-			break;
+-		if (unlikely(signal_pending(current)))
+-			goto interrupted;
+-		schedule();
+-		set_task_state(tsk, TASK_INTERRUPTIBLE);
+-	}
+-
+- out:
+-	tsk->state = TASK_RUNNING;
+-	semtrace(sem, "Leaving __down_interruptible");
+-	return ret;
+-
+- interrupted:
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-
+-	if (!list_empty(&waiter.list)) {
+-		list_del(&waiter.list);
+-		ret = -EINTR;
+-	}
+-
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-	if (ret == -EINTR)
+-		put_task_struct(current);
+-	goto out;
+-}
+-
+-EXPORT_SYMBOL(__down_interruptible);
+-
+-/*
+- * release a single token back to a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __up(struct semaphore *sem)
+-{
+-	struct task_struct *tsk;
+-	struct sem_waiter *waiter;
+-
+-	semtrace(sem,"Entering __up");
+-
+-	/* grant the token to the process at the front of the queue */
+-	waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
+-
+-	/* We must be careful not to touch 'waiter' after we set ->task = NULL.
+-	 * It is allocated on the waiter's stack and may become invalid at
+-	 * any time after that point (due to a wakeup from another source).
+-	 */
+-	list_del_init(&waiter->list);
+-	tsk = waiter->task;
+-	mb();
+-	waiter->task = NULL;
+-	wake_up_process(tsk);
+-	put_task_struct(tsk);
+-
+-	semtrace(sem,"Leaving __up");
+-}
+-
+-EXPORT_SYMBOL(__up);
+diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h
+index 7481797..0c7bf39 100644
+--- a/arch/frv/mb93090-mb00/pci-frv.h
++++ b/arch/frv/mb93090-mb00/pci-frv.h
+@@ -17,8 +17,6 @@
+ #define PCI_PROBE_BIOS		0x0001
+ #define PCI_PROBE_CONF1		0x0002
+ #define PCI_PROBE_CONF2		0x0004
+-#define PCI_NO_SORT		0x0100
+-#define PCI_BIOS_SORT		0x0200
+ #define PCI_NO_CHECKS		0x0400
+ #define PCI_ASSIGN_ROMS		0x1000
+ #define PCI_BIOS_IRQ_SCAN	0x2000
+diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
+index 6d51f13..f003cfa 100644
+--- a/arch/frv/mb93090-mb00/pci-vdk.c
++++ b/arch/frv/mb93090-mb00/pci-vdk.c
+@@ -199,58 +199,6 @@ static struct pci_ops * __init pci_check_direct(void)
+ }
+ 
+ /*
+- * Several buggy motherboards address only 16 devices and mirror
+- * them to next 16 IDs. We try to detect this `feature' on all
+- * primary buses (those containing host bridges as they are
+- * expected to be unique) and remove the ghost devices.
+- */
+-
+-static void __init pcibios_fixup_ghosts(struct pci_bus *b)
+-{
+-	struct list_head *ln, *mn;
+-	struct pci_dev *d, *e;
+-	int mirror = PCI_DEVFN(16,0);
+-	int seen_host_bridge = 0;
+-	int i;
+-
+-	for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
+-		d = pci_dev_b(ln);
+-		if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+-			seen_host_bridge++;
+-		for (mn=ln->next; mn != &b->devices; mn=mn->next) {
+-			e = pci_dev_b(mn);
+-			if (e->devfn != d->devfn + mirror ||
+-			    e->vendor != d->vendor ||
+-			    e->device != d->device ||
+-			    e->class != d->class)
+-				continue;
+-			for(i=0; i<PCI_NUM_RESOURCES; i++)
+-				if (e->resource[i].start != d->resource[i].start ||
+-				    e->resource[i].end != d->resource[i].end ||
+-				    e->resource[i].flags != d->resource[i].flags)
+-					continue;
+-			break;
+-		}
+-		if (mn == &b->devices)
+-			return;
+-	}
+-	if (!seen_host_bridge)
+-		return;
+-	printk("PCI: Ignoring ghost devices on bus %02x\n", b->number);
+-
+-	ln = &b->devices;
+-	while (ln->next != &b->devices) {
+-		d = pci_dev_b(ln->next);
+-		if (d->devfn >= mirror) {
+-			list_del(&d->global_list);
+-			list_del(&d->bus_list);
+-			kfree(d);
+-		} else
+-			ln = ln->next;
+-	}
+-}
+-
+-/*
+  * Discover remaining PCI buses in case there are peer host bridges.
+  * We use the number of last PCI bus provided by the PCI BIOS.
+  */
+@@ -356,7 +304,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
+ #if 0
+ 	printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
+ #endif
+-	pcibios_fixup_ghosts(bus);
+ 	pci_read_bridge_bases(bus);
+ 
+ 	if (bus->number == 0) {
+diff --git a/arch/frv/mm/highmem.c b/arch/frv/mm/highmem.c
+index 7f77db7..eadd076 100644
+--- a/arch/frv/mm/highmem.c
++++ b/arch/frv/mm/highmem.c
+@@ -36,6 +36,3 @@ struct page *kmap_atomic_to_page(void *ptr)
+ {
+ 	return virt_to_page(ptr);
+ }
+-
+-
+-EXPORT_SYMBOL(kmap_atomic_to_page);
+diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
+index 874f6ae..6c248c3 100644
+--- a/arch/h8300/kernel/Makefile
++++ b/arch/h8300/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y := vmlinux.lds
+ 
+ obj-y := process.o traps.o ptrace.o irq.o \
+-	 sys_h8300.o time.o semaphore.o signal.o \
++	 sys_h8300.o time.o signal.o \
+          setup.o gpio.o init_task.o syscalls.o \
+ 	 entry.o
+ 
+diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
+index d1b1526..6866bd9 100644
+--- a/arch/h8300/kernel/h8300_ksyms.c
++++ b/arch/h8300/kernel/h8300_ksyms.c
+@@ -12,7 +12,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/current.h>
+ #include <asm/gpio.h>
+diff --git a/arch/h8300/kernel/semaphore.c b/arch/h8300/kernel/semaphore.c
+deleted file mode 100644
+index d12cbbf..0000000
+--- a/arch/h8300/kernel/semaphore.c
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/*
+- *  Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <asm/semaphore-helper.h>
+-
+-#ifndef CONFIG_RMW_INSNS
+-spinlock_t semaphore_wake_lock;
+-#endif
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit.  ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore.  The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+-	wake_one_more(sem);
+-	wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function.  Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible.  This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return.  If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-
+-#define DOWN_HEAD(task_state)						\
+-									\
+-									\
+-	current->state = (task_state);					\
+-	add_wait_queue(&sem->wait, &wait);				\
+-									\
+-	/*								\
+-	 * Ok, we're set up.  sem->count is known to be less than zero	\
+-	 * so we must wait.						\
+-	 *								\
+-	 * We can let go the lock for purposes of waiting.		\
+-	 * We re-acquire it after awaking so as to protect		\
+-	 * all semaphore operations.					\
+-	 *								\
+-	 * If "up()" is called before we call waking_non_zero() then	\
+-	 * we will catch it right away.  If it is called later then	\
+-	 * we will have to go through a wakeup cycle to catch it.	\
+-	 *								\
+-	 * Multiple waiters contend for the semaphore lock to see	\
+-	 * who gets to gate through and who has to wait some more.	\
+-	 */								\
+-	for (;;) {
+-
+-#define DOWN_TAIL(task_state)			\
+-		current->state = (task_state);	\
+-	}					\
+-	current->state = TASK_RUNNING;		\
+-	remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	DECLARE_WAITQUEUE(wait, current);
+-
+-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+-	if (waking_non_zero(sem))
+-		break;
+-	schedule();
+-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	DECLARE_WAITQUEUE(wait, current);
+-	int ret = 0;
+-
+-	DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+-	ret = waking_non_zero_interruptible(sem, current);
+-	if (ret)
+-	{
+-		if (ret == 1)
+-			/* ret != 0 only if we get interrupted -arca */
+-			ret = 0;
+-		break;
+-	}
+-	schedule();
+-	DOWN_TAIL(TASK_INTERRUPTIBLE)
+-	return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+-	return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
+index 8fa3faf..cd13e13 100644
+--- a/arch/ia64/Kconfig
++++ b/arch/ia64/Kconfig
+@@ -266,23 +266,23 @@ config IOSAPIC
+ 	depends on !IA64_HP_SIM
+ 	default y
+ 
+-config IA64_SGI_SN_XP
+-	tristate "Support communication between SGI SSIs"
+-	depends on IA64_GENERIC || IA64_SGI_SN2
+-	select IA64_UNCACHED_ALLOCATOR
+-	help
+-	  An SGI machine can be divided into multiple Single System
+-	  Images which act independently of each other and have
+-	  hardware based memory protection from the others.  Enabling
+-	  this feature will allow for direct communication between SSIs
+-	  based on a network adapter and DMA messaging.
+-
+ config FORCE_MAX_ZONEORDER
+ 	int "MAX_ORDER (11 - 17)"  if !HUGETLB_PAGE
+ 	range 11 17  if !HUGETLB_PAGE
+ 	default "17" if HUGETLB_PAGE
+ 	default "11"
+ 
++config VIRT_CPU_ACCOUNTING
++	bool "Deterministic task and CPU time accounting"
++	default n
++	help
++	  Select this option to enable more accurate task and CPU time
++	  accounting.  This is done by reading a CPU counter on each
++	  kernel entry and exit and on transitions within the kernel
++	  between system, softirq and hardirq state, so there is a
++	  small performance impact.
++	  If in doubt, say N here.
++
+ config SMP
+ 	bool "Symmetric multi-processing support"
+ 	help
+@@ -611,6 +611,9 @@ config IRQ_PER_CPU
+ 	bool
+ 	default y
+ 
++config IOMMU_HELPER
++	def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC)
++
+ source "arch/ia64/hp/sim/Kconfig"
+ 
+ source "arch/ia64/Kconfig.debug"
+diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
+index 523eae6..9409de5 100644
+--- a/arch/ia64/hp/common/sba_iommu.c
++++ b/arch/ia64/hp/common/sba_iommu.c
+@@ -35,6 +35,7 @@
+ #include <linux/nodemask.h>
+ #include <linux/bitops.h>         /* hweight64() */
+ #include <linux/crash_dump.h>
++#include <linux/iommu-helper.h>
+ 
+ #include <asm/delay.h>		/* ia64_get_itc() */
+ #include <asm/io.h>
+@@ -460,6 +461,13 @@ get_iovp_order (unsigned long size)
+ 	return order;
+ }
+ 
++static unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr,
++				 unsigned int bitshiftcnt)
++{
++	return (((unsigned long)res_ptr - (unsigned long)ioc->res_map) << 3)
++		+ bitshiftcnt;
++}
++
+ /**
+  * sba_search_bitmap - find free space in IO PDIR resource bitmap
+  * @ioc: IO MMU structure which owns the pdir we are interested in.
+@@ -471,15 +479,25 @@ get_iovp_order (unsigned long size)
+  * Cool perf optimization: search for log2(size) bits at a time.
+  */
+ static SBA_INLINE unsigned long
+-sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
++sba_search_bitmap(struct ioc *ioc, struct device *dev,
++		  unsigned long bits_wanted, int use_hint)
+ {
+ 	unsigned long *res_ptr;
+ 	unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
+-	unsigned long flags, pide = ~0UL;
++	unsigned long flags, pide = ~0UL, tpide;
++	unsigned long boundary_size;
++	unsigned long shift;
++	int ret;
+ 
+ 	ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
+ 	ASSERT(res_ptr < res_end);
+ 
++	boundary_size = (unsigned long long)dma_get_seg_boundary(dev) + 1;
++	boundary_size = ALIGN(boundary_size, 1ULL << iovp_shift) >> iovp_shift;
++
++	BUG_ON(ioc->ibase & ~iovp_mask);
++	shift = ioc->ibase >> iovp_shift;
++
+ 	spin_lock_irqsave(&ioc->res_lock, flags);
+ 
+ 	/* Allow caller to force a search through the entire resource space */
+@@ -504,9 +522,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
+ 			if (likely(*res_ptr != ~0UL)) {
+ 				bitshiftcnt = ffz(*res_ptr);
+ 				*res_ptr |= (1UL << bitshiftcnt);
+-				pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+-				pide <<= 3;	/* convert to bit address */
+-				pide += bitshiftcnt;
++				pide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
+ 				ioc->res_bitshift = bitshiftcnt + bits_wanted;
+ 				goto found_it;
+ 			}
+@@ -535,11 +551,13 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
+ 			DBG_RES("    %p %lx %lx\n", res_ptr, mask, *res_ptr);
+ 			ASSERT(0 != mask);
+ 			for (; mask ; mask <<= o, bitshiftcnt += o) {
+-				if(0 == ((*res_ptr) & mask)) {
++				tpide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
++				ret = iommu_is_span_boundary(tpide, bits_wanted,
++							     shift,
++							     boundary_size);
++				if ((0 == ((*res_ptr) & mask)) && !ret) {
+ 					*res_ptr |= mask;     /* mark resources busy! */
+-					pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+-					pide <<= 3;	/* convert to bit address */
+-					pide += bitshiftcnt;
++					pide = tpide;
+ 					ioc->res_bitshift = bitshiftcnt + bits_wanted;
+ 					goto found_it;
+ 				}
+@@ -560,6 +578,11 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
+ 		end = res_end - qwords;
+ 
+ 		for (; res_ptr < end; res_ptr++) {
++			tpide = ptr_to_pide(ioc, res_ptr, 0);
++			ret = iommu_is_span_boundary(tpide, bits_wanted,
++						     shift, boundary_size);
++			if (ret)
++				goto next_ptr;
+ 			for (i = 0 ; i < qwords ; i++) {
+ 				if (res_ptr[i] != 0)
+ 					goto next_ptr;
+@@ -572,8 +595,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
+ 				res_ptr[i] = ~0UL;
+ 			res_ptr[i] |= RESMAP_MASK(bits);
+ 
+-			pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+-			pide <<= 3;	/* convert to bit address */
++			pide = tpide;
+ 			res_ptr += qwords;
+ 			ioc->res_bitshift = bits;
+ 			goto found_it;
+@@ -605,7 +627,7 @@ found_it:
+  * resource bit map.
+  */
+ static int
+-sba_alloc_range(struct ioc *ioc, size_t size)
++sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
+ {
+ 	unsigned int pages_needed = size >> iovp_shift;
+ #ifdef PDIR_SEARCH_TIMING
+@@ -622,9 +644,9 @@ sba_alloc_range(struct ioc *ioc, size_t size)
+ 	/*
+ 	** "seek and ye shall find"...praying never hurts either...
+ 	*/
+-	pide = sba_search_bitmap(ioc, pages_needed, 1);
++	pide = sba_search_bitmap(ioc, dev, pages_needed, 1);
+ 	if (unlikely(pide >= (ioc->res_size << 3))) {
+-		pide = sba_search_bitmap(ioc, pages_needed, 0);
++		pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
+ 		if (unlikely(pide >= (ioc->res_size << 3))) {
+ #if DELAYED_RESOURCE_CNT > 0
+ 			unsigned long flags;
+@@ -653,7 +675,7 @@ sba_alloc_range(struct ioc *ioc, size_t size)
+ 			}
+ 			spin_unlock_irqrestore(&ioc->saved_lock, flags);
+ 
+-			pide = sba_search_bitmap(ioc, pages_needed, 0);
++			pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
+ 			if (unlikely(pide >= (ioc->res_size << 3)))
+ 				panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
+ 				      ioc->ioc_hpa);
+@@ -936,7 +958,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
+ 	spin_unlock_irqrestore(&ioc->res_lock, flags);
+ #endif
+ 
+-	pide = sba_alloc_range(ioc, size);
++	pide = sba_alloc_range(ioc, dev, size);
+ 
+ 	iovp = (dma_addr_t) pide << iovp_shift;
+ 
+@@ -1373,7 +1395,7 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
+ 		dma_len = (dma_len + dma_offset + ~iovp_mask) & iovp_mask;
+ 		ASSERT(dma_len <= DMA_CHUNK_SIZE);
+ 		dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG
+-			| (sba_alloc_range(ioc, dma_len) << iovp_shift)
++			| (sba_alloc_range(ioc, dev, dma_len) << iovp_shift)
+ 			| dma_offset);
+ 		n_mappings++;
+ 	}
+diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
+index 969fe9f..3d47839 100644
+--- a/arch/ia64/hp/sim/simeth.c
++++ b/arch/ia64/hp/sim/simeth.c
+@@ -294,7 +294,7 @@ simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
+ 		return NOTIFY_DONE;
+ 	}
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
+diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
+index 7661bb0..3a078ad 100644
+--- a/arch/ia64/hp/sim/simscsi.c
++++ b/arch/ia64/hp/sim/simscsi.c
+@@ -201,22 +201,6 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
+ 	simscsi_sg_readwrite(sc, mode, offset);
+ }
+ 
+-static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len)
+-{
+-
+-	int i;
+-	unsigned thislen;
+-	struct scatterlist *slp;
+-
+-	scsi_for_each_sg(sc, slp, scsi_sg_count(sc), i) {
+-		if (!len)
+-			break;
+-		thislen = min(len, slp->length);
+-		memcpy(sg_virt(slp), buf, thislen);
+-		len -= thislen;
+-	}
+-}
+-
+ static int
+ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ {
+@@ -258,7 +242,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			buf[6] = 0;	/* reserved */
+ 			buf[7] = 0;	/* various flags */
+ 			memcpy(buf + 8, "HP      SIMULATED DISK  0.00",  28);
+-			simscsi_fillresult(sc, buf, 36);
++			scsi_sg_copy_from_buffer(sc, buf, 36);
+ 			sc->result = GOOD;
+ 			break;
+ 
+@@ -306,14 +290,15 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ 			buf[5] = 0;
+ 			buf[6] = 2;
+ 			buf[7] = 0;
+-			simscsi_fillresult(sc, buf, 8);
++			scsi_sg_copy_from_buffer(sc, buf, 8);
+ 			sc->result = GOOD;
+ 			break;
+ 
+ 		      case MODE_SENSE:
+ 		      case MODE_SENSE_10:
+ 			/* sd.c uses this to determine whether disk does write-caching. */
+-			simscsi_fillresult(sc, (char *)empty_zero_page, scsi_bufflen(sc));
++			scsi_sg_copy_from_buffer(sc, (char *)empty_zero_page,
++						 PAGE_SIZE);
+ 			sc->result = GOOD;
+ 			break;
+ 
+diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h
+index 446c9aa..9a3abf5 100644
+--- a/arch/ia64/ia32/elfcore32.h
++++ b/arch/ia64/ia32/elfcore32.h
+@@ -30,7 +30,19 @@ struct elf_siginfo
+ 	int	si_errno;			/* errno */
+ };
+ 
+-#define jiffies_to_timeval(a,b) do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; }while(0)
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++/*
++ * Hacks are here since types between compat_timeval (= pair of s32) and
++ * ia64-native timeval (= pair of s64) are not compatible, at least a file
++ * arch/ia64/ia32/../../../fs/binfmt_elf.c will get warnings from compiler on
++ * use of cputime_to_timeval(), which usually an alias of jiffies_to_timeval().
++ */
++#define cputime_to_timeval(a,b) \
++	do { (b)->tv_usec = 0; (b)->tv_sec = (a)/NSEC_PER_SEC; } while(0)
++#else
++#define jiffies_to_timeval(a,b) \
++	do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; } while(0)
++#endif
+ 
+ struct elf_prstatus
+ {
+diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
+index b1bf51f..7e028ce 100644
+--- a/arch/ia64/ia32/sys_ia32.c
++++ b/arch/ia64/ia32/sys_ia32.c
+@@ -38,6 +38,7 @@
+ #include <linux/eventpoll.h>
+ #include <linux/personality.h>
+ #include <linux/ptrace.h>
++#include <linux/regset.h>
+ #include <linux/stat.h>
+ #include <linux/ipc.h>
+ #include <linux/capability.h>
+@@ -2387,16 +2388,45 @@ get_free_idx (void)
+ 	return -ESRCH;
+ }
+ 
++static void set_tls_desc(struct task_struct *p, int idx,
++		const struct ia32_user_desc *info, int n)
++{
++	struct thread_struct *t = &p->thread;
++	struct desc_struct *desc = &t->tls_array[idx - GDT_ENTRY_TLS_MIN];
++	int cpu;
++
++	/*
++	 * We must not get preempted while modifying the TLS.
++	 */
++	cpu = get_cpu();
++
++	while (n-- > 0) {
++		if (LDT_empty(info)) {
++			desc->a = 0;
++			desc->b = 0;
++		} else {
++			desc->a = LDT_entry_a(info);
++			desc->b = LDT_entry_b(info);
++		}
++
++		++info;
++		++desc;
++	}
++
++	if (t == &current->thread)
++		load_TLS(t, cpu);
++
++	put_cpu();
++}
++
+ /*
+  * Set a given TLS descriptor:
+  */
+ asmlinkage int
+ sys32_set_thread_area (struct ia32_user_desc __user *u_info)
+ {
+-	struct thread_struct *t = &current->thread;
+ 	struct ia32_user_desc info;
+-	struct desc_struct *desc;
+-	int cpu, idx;
++	int idx;
+ 
+ 	if (copy_from_user(&info, u_info, sizeof(info)))
+ 		return -EFAULT;
+@@ -2416,18 +2446,7 @@ sys32_set_thread_area (struct ia32_user_desc __user *u_info)
+ 	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+ 		return -EINVAL;
+ 
+-	desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
+-
+-	cpu = smp_processor_id();
+-
+-	if (LDT_empty(&info)) {
+-		desc->a = 0;
+-		desc->b = 0;
+-	} else {
+-		desc->a = LDT_entry_a(&info);
+-		desc->b = LDT_entry_b(&info);
+-	}
+-	load_TLS(t, cpu);
++	set_tls_desc(current, idx, &info, 1);
+ 	return 0;
+ }
+ 
+@@ -2451,6 +2470,20 @@ sys32_set_thread_area (struct ia32_user_desc __user *u_info)
+ #define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
+ #define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
+ 
++static void fill_user_desc(struct ia32_user_desc *info, int idx,
++		const struct desc_struct *desc)
++{
++	info->entry_number = idx;
++	info->base_addr = GET_BASE(desc);
++	info->limit = GET_LIMIT(desc);
++	info->seg_32bit = GET_32BIT(desc);
++	info->contents = GET_CONTENTS(desc);
++	info->read_exec_only = !GET_WRITABLE(desc);
++	info->limit_in_pages = GET_LIMIT_PAGES(desc);
++	info->seg_not_present = !GET_PRESENT(desc);
++	info->useable = GET_USEABLE(desc);
++}
++
+ asmlinkage int
+ sys32_get_thread_area (struct ia32_user_desc __user *u_info)
+ {
+@@ -2464,22 +2497,588 @@ sys32_get_thread_area (struct ia32_user_desc __user *u_info)
+ 		return -EINVAL;
+ 
+ 	desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
+-
+-	info.entry_number = idx;
+-	info.base_addr = GET_BASE(desc);
+-	info.limit = GET_LIMIT(desc);
+-	info.seg_32bit = GET_32BIT(desc);
+-	info.contents = GET_CONTENTS(desc);
+-	info.read_exec_only = !GET_WRITABLE(desc);
+-	info.limit_in_pages = GET_LIMIT_PAGES(desc);
+-	info.seg_not_present = !GET_PRESENT(desc);
+-	info.useable = GET_USEABLE(desc);
++	fill_user_desc(&info, idx, desc);
+ 
+ 	if (copy_to_user(u_info, &info, sizeof(info)))
+ 		return -EFAULT;
+ 	return 0;
+ }
+ 
++struct regset_get {
++	void *kbuf;
++	void __user *ubuf;
++};
++
++struct regset_set {
++	const void *kbuf;
++	const void __user *ubuf;
++};
++
++struct regset_getset {
++	struct task_struct *target;
++	const struct user_regset *regset;
++	union {
++		struct regset_get get;
++		struct regset_set set;
++	} u;
++	unsigned int pos;
++	unsigned int count;
++	int ret;
++};
++
++static void getfpreg(struct task_struct *task, int regno, int *val)
++{
++	switch (regno / sizeof(int)) {
++	case 0:
++		*val = task->thread.fcr & 0xffff;
++		break;
++	case 1:
++		*val = task->thread.fsr & 0xffff;
++		break;
++	case 2:
++		*val = (task->thread.fsr>>16) & 0xffff;
++		break;
++	case 3:
++		*val = task->thread.fir;
++		break;
++	case 4:
++		*val = (task->thread.fir>>32) & 0xffff;
++		break;
++	case 5:
++		*val = task->thread.fdr;
++		break;
++	case 6:
++		*val = (task->thread.fdr >> 32) & 0xffff;
++		break;
++	}
++}
++
++static void setfpreg(struct task_struct *task, int regno, int val)
++{
++	switch (regno / sizeof(int)) {
++	case 0:
++		task->thread.fcr = (task->thread.fcr & (~0x1f3f))
++			| (val & 0x1f3f);
++		break;
++	case 1:
++		task->thread.fsr = (task->thread.fsr & (~0xffff)) | val;
++		break;
++	case 2:
++		task->thread.fsr = (task->thread.fsr & (~0xffff0000))
++			| (val << 16);
++		break;
++	case 3:
++		task->thread.fir = (task->thread.fir & (~0xffffffff)) | val;
++		break;
++	case 5:
++		task->thread.fdr = (task->thread.fdr & (~0xffffffff)) | val;
++		break;
++	}
++}
++
++static void access_fpreg_ia32(int regno, void *reg,
++		struct pt_regs *pt, struct switch_stack *sw,
++		int tos, int write)
++{
++	void *f;
++
++	if ((regno += tos) >= 8)
++		regno -= 8;
++	if (regno < 4)
++		f = &pt->f8 + regno;
++	else if (regno <= 7)
++		f = &sw->f12 + (regno - 4);
++	else {
++		printk(KERN_ERR "regno must be less than 7 \n");
++		 return;
++	}
++
++	if (write)
++		memcpy(f, reg, sizeof(struct _fpreg_ia32));
++	else
++		memcpy(reg, f, sizeof(struct _fpreg_ia32));
++}
++
++static void do_fpregs_get(struct unw_frame_info *info, void *arg)
++{
++	struct regset_getset *dst = arg;
++	struct task_struct *task = dst->target;
++	struct pt_regs *pt;
++	int start, end, tos;
++	char buf[80];
++
++	if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++		return;
++	if (dst->pos < 7 * sizeof(int)) {
++		end = min((dst->pos + dst->count),
++			(unsigned int)(7 * sizeof(int)));
++		for (start = dst->pos; start < end; start += sizeof(int))
++			getfpreg(task, start, (int *)(buf + start));
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf, buf,
++				0, 7 * sizeof(int));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++	if (dst->pos < sizeof(struct ia32_user_i387_struct)) {
++		pt = task_pt_regs(task);
++		tos = (task->thread.fsr >> 11) & 7;
++		end = min(dst->pos + dst->count,
++			(unsigned int)(sizeof(struct ia32_user_i387_struct)));
++		start = (dst->pos - 7 * sizeof(int)) /
++			sizeof(struct _fpreg_ia32);
++		end = (end - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
++		for (; start < end; start++)
++			access_fpreg_ia32(start,
++				(struct _fpreg_ia32 *)buf + start,
++				pt, info->sw, tos, 0);
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf,
++				buf, 7 * sizeof(int),
++				sizeof(struct ia32_user_i387_struct));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++}
++
++static void do_fpregs_set(struct unw_frame_info *info, void *arg)
++{
++	struct regset_getset *dst = arg;
++	struct task_struct *task = dst->target;
++	struct pt_regs *pt;
++	char buf[80];
++	int end, start, tos;
++
++	if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++		return;
++
++	if (dst->pos < 7 * sizeof(int)) {
++		start = dst->pos;
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf, buf,
++				0, 7 * sizeof(int));
++		if (dst->ret)
++			return;
++		for (; start < dst->pos; start += sizeof(int))
++			setfpreg(task, start, *((int *)(buf + start)));
++		if (dst->count == 0)
++			return;
++	}
++	if (dst->pos < sizeof(struct ia32_user_i387_struct)) {
++		start = (dst->pos - 7 * sizeof(int)) /
++			sizeof(struct _fpreg_ia32);
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf,
++				buf, 7 * sizeof(int),
++				sizeof(struct ia32_user_i387_struct));
++		if (dst->ret)
++			return;
++		pt = task_pt_regs(task);
++		tos = (task->thread.fsr >> 11) & 7;
++		end = (dst->pos - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
++		for (; start < end; start++)
++			access_fpreg_ia32(start,
++				(struct _fpreg_ia32 *)buf + start,
++				pt, info->sw, tos, 1);
++		if (dst->count == 0)
++			return;
++	}
++}
++
++#define OFFSET(member) ((int)(offsetof(struct ia32_user_fxsr_struct, member)))
++static void getfpxreg(struct task_struct *task, int start, int end, char *buf)
++{
++	int min_val;
++
++	min_val = min(end, OFFSET(fop));
++	while (start < min_val) {
++		if (start == OFFSET(cwd))
++			*((short *)buf) = task->thread.fcr & 0xffff;
++		else if (start == OFFSET(swd))
++			*((short *)buf) = task->thread.fsr & 0xffff;
++		else if (start == OFFSET(twd))
++			*((short *)buf) = (task->thread.fsr>>16) & 0xffff;
++		buf += 2;
++		start += 2;
++	}
++	/* skip fop element */
++	if (start == OFFSET(fop)) {
++		start += 2;
++		buf += 2;
++	}
++	while (start < end) {
++		if (start == OFFSET(fip))
++			*((int *)buf) = task->thread.fir;
++		else if (start == OFFSET(fcs))
++			*((int *)buf) = (task->thread.fir>>32) & 0xffff;
++		else if (start == OFFSET(foo))
++			*((int *)buf) = task->thread.fdr;
++		else if (start == OFFSET(fos))
++			*((int *)buf) = (task->thread.fdr>>32) & 0xffff;
++		else if (start == OFFSET(mxcsr))
++			*((int *)buf) = ((task->thread.fcr>>32) & 0xff80)
++					 | ((task->thread.fsr>>32) & 0x3f);
++		buf += 4;
++		start += 4;
++	}
++}
++
++static void setfpxreg(struct task_struct *task, int start, int end, char *buf)
++{
++	int min_val, num32;
++	short num;
++	unsigned long num64;
++
++	min_val = min(end, OFFSET(fop));
++	while (start < min_val) {
++		num = *((short *)buf);
++		if (start == OFFSET(cwd)) {
++			task->thread.fcr = (task->thread.fcr & (~0x1f3f))
++						| (num & 0x1f3f);
++		} else if (start == OFFSET(swd)) {
++			task->thread.fsr = (task->thread.fsr & (~0xffff)) | num;
++		} else if (start == OFFSET(twd)) {
++			task->thread.fsr = (task->thread.fsr & (~0xffff0000))
++				| (((int)num) << 16);
++		}
++		buf += 2;
++		start += 2;
++	}
++	/* skip fop element */
++	if (start == OFFSET(fop)) {
++		start += 2;
++		buf += 2;
++	}
++	while (start < end) {
++		num32 = *((int *)buf);
++		if (start == OFFSET(fip))
++			task->thread.fir = (task->thread.fir & (~0xffffffff))
++						 | num32;
++		else if (start == OFFSET(foo))
++			task->thread.fdr = (task->thread.fdr & (~0xffffffff))
++						 | num32;
++		else if (start == OFFSET(mxcsr)) {
++			num64 = num32 & 0xff10;
++			task->thread.fcr = (task->thread.fcr &
++				(~0xff1000000000UL)) | (num64<<32);
++			num64 = num32 & 0x3f;
++			task->thread.fsr = (task->thread.fsr &
++				(~0x3f00000000UL)) | (num64<<32);
++		}
++		buf += 4;
++		start += 4;
++	}
++}
++
++static void do_fpxregs_get(struct unw_frame_info *info, void *arg)
++{
++	struct regset_getset *dst = arg;
++	struct task_struct *task = dst->target;
++	struct pt_regs *pt;
++	char buf[128];
++	int start, end, tos;
++
++	if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++		return;
++	if (dst->pos < OFFSET(st_space[0])) {
++		end = min(dst->pos + dst->count, (unsigned int)32);
++		getfpxreg(task, dst->pos, end, buf);
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf, buf,
++				0, OFFSET(st_space[0]));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++	if (dst->pos < OFFSET(xmm_space[0])) {
++		pt = task_pt_regs(task);
++		tos = (task->thread.fsr >> 11) & 7;
++		end = min(dst->pos + dst->count,
++				(unsigned int)OFFSET(xmm_space[0]));
++		start = (dst->pos - OFFSET(st_space[0])) / 16;
++		end = (end - OFFSET(st_space[0])) / 16;
++		for (; start < end; start++)
++			access_fpreg_ia32(start, buf + 16 * start, pt,
++						info->sw, tos, 0);
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf,
++				buf, OFFSET(st_space[0]), OFFSET(xmm_space[0]));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++	if (dst->pos < OFFSET(padding[0]))
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf,
++				&info->sw->f16, OFFSET(xmm_space[0]),
++				OFFSET(padding[0]));
++}
++
++static void do_fpxregs_set(struct unw_frame_info *info, void *arg)
++{
++	struct regset_getset *dst = arg;
++	struct task_struct *task = dst->target;
++	char buf[128];
++	int start, end;
++
++	if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++		return;
++
++	if (dst->pos < OFFSET(st_space[0])) {
++		start = dst->pos;
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf,
++				buf, 0, OFFSET(st_space[0]));
++		if (dst->ret)
++			return;
++		setfpxreg(task, start, dst->pos, buf);
++		if (dst->count == 0)
++			return;
++	}
++	if (dst->pos < OFFSET(xmm_space[0])) {
++		struct pt_regs *pt;
++		int tos;
++		pt = task_pt_regs(task);
++		tos = (task->thread.fsr >> 11) & 7;
++		start = (dst->pos - OFFSET(st_space[0])) / 16;
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf,
++				buf, OFFSET(st_space[0]), OFFSET(xmm_space[0]));
++		if (dst->ret)
++			return;
++		end = (dst->pos - OFFSET(st_space[0])) / 16;
++		for (; start < end; start++)
++			access_fpreg_ia32(start, buf + 16 * start, pt, info->sw,
++						 tos, 1);
++		if (dst->count == 0)
++			return;
++	}
++	if (dst->pos < OFFSET(padding[0]))
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf,
++				&info->sw->f16, OFFSET(xmm_space[0]),
++				 OFFSET(padding[0]));
++}
++#undef OFFSET
++
++static int do_regset_call(void (*call)(struct unw_frame_info *, void *),
++		struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	struct regset_getset info = { .target = target, .regset = regset,
++		.pos = pos, .count = count,
++		.u.set = { .kbuf = kbuf, .ubuf = ubuf },
++		.ret = 0 };
++
++	if (target == current)
++		unw_init_running(call, &info);
++	else {
++		struct unw_frame_info ufi;
++		memset(&ufi, 0, sizeof(ufi));
++		unw_init_from_blocked_task(&ufi, target);
++		(*call)(&ufi, &info);
++	}
++
++	return info.ret;
++}
++
++static int ia32_fpregs_get(struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		void *kbuf, void __user *ubuf)
++{
++	return do_regset_call(do_fpregs_get, target, regset, pos, count,
++		kbuf, ubuf);
++}
++
++static int ia32_fpregs_set(struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	return do_regset_call(do_fpregs_set, target, regset, pos, count,
++		kbuf, ubuf);
++}
++
++static int ia32_fpxregs_get(struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		void *kbuf, void __user *ubuf)
++{
++	return do_regset_call(do_fpxregs_get, target, regset, pos, count,
++		kbuf, ubuf);
++}
++
++static int ia32_fpxregs_set(struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	return do_regset_call(do_fpxregs_set, target, regset, pos, count,
++		kbuf, ubuf);
++}
++
++static int ia32_genregs_get(struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		void *kbuf, void __user *ubuf)
++{
++	if (kbuf) {
++		u32 *kp = kbuf;
++		while (count > 0) {
++			*kp++ = getreg(target, pos);
++			pos += 4;
++			count -= 4;
++		}
++	} else {
++		u32 __user *up = ubuf;
++		while (count > 0) {
++			if (__put_user(getreg(target, pos), up++))
++				return -EFAULT;
++			pos += 4;
++			count -= 4;
++		}
++	}
++	return 0;
++}
++
++static int ia32_genregs_set(struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	int ret = 0;
++
++	if (kbuf) {
++		const u32 *kp = kbuf;
++		while (!ret && count > 0) {
++			putreg(target, pos, *kp++);
++			pos += 4;
++			count -= 4;
++		}
++	} else {
++		const u32 __user *up = ubuf;
++		u32 val;
++		while (!ret && count > 0) {
++			ret = __get_user(val, up++);
++			if (!ret)
++				putreg(target, pos, val);
++			pos += 4;
++			count -= 4;
++		}
++	}
++	return ret;
++}
++
++static int ia32_tls_active(struct task_struct *target,
++		const struct user_regset *regset)
++{
++	struct thread_struct *t = &target->thread;
++	int n = GDT_ENTRY_TLS_ENTRIES;
++	while (n > 0 && desc_empty(&t->tls_array[n -1]))
++		--n;
++	return n;
++}
++
++static int ia32_tls_get(struct task_struct *target,
++		const struct user_regset *regset, unsigned int pos,
++		unsigned int count, void *kbuf, void __user *ubuf)
++{
++	const struct desc_struct *tls;
++
++	if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct ia32_user_desc) ||
++			(pos % sizeof(struct ia32_user_desc)) != 0 ||
++			(count % sizeof(struct ia32_user_desc)) != 0)
++		return -EINVAL;
++
++	pos /= sizeof(struct ia32_user_desc);
++	count /= sizeof(struct ia32_user_desc);
++
++	tls = &target->thread.tls_array[pos];
++
++	if (kbuf) {
++		struct ia32_user_desc *info = kbuf;
++		while (count-- > 0)
++			fill_user_desc(info++, GDT_ENTRY_TLS_MIN + pos++,
++					tls++);
++	} else {
++		struct ia32_user_desc __user *u_info = ubuf;
++		while (count-- > 0) {
++			struct ia32_user_desc info;
++			fill_user_desc(&info, GDT_ENTRY_TLS_MIN + pos++, tls++);
++			if (__copy_to_user(u_info++, &info, sizeof(info)))
++				return -EFAULT;
++		}
++	}
++
++	return 0;
++}
++
++static int ia32_tls_set(struct task_struct *target,
++		const struct user_regset *regset, unsigned int pos,
++		unsigned int count, const void *kbuf, const void __user *ubuf)
++{
++	struct ia32_user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
++	const struct ia32_user_desc *info;
++
++	if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct ia32_user_desc) ||
++			(pos % sizeof(struct ia32_user_desc)) != 0 ||
++			(count % sizeof(struct ia32_user_desc)) != 0)
++		return -EINVAL;
++
++	if (kbuf)
++		info = kbuf;
++	else if (__copy_from_user(infobuf, ubuf, count))
++		return -EFAULT;
++	else
++		info = infobuf;
++
++	set_tls_desc(target,
++		GDT_ENTRY_TLS_MIN + (pos / sizeof(struct ia32_user_desc)),
++		info, count / sizeof(struct ia32_user_desc));
++
++	return 0;
++}
++
++/*
++ * This should match arch/i386/kernel/ptrace.c:native_regsets.
++ * XXX ioperm? vm86?
++ */
++static const struct user_regset ia32_regsets[] = {
++	{
++		.core_note_type = NT_PRSTATUS,
++		.n = sizeof(struct user_regs_struct32)/4,
++		.size = 4, .align = 4,
++		.get = ia32_genregs_get, .set = ia32_genregs_set
++	},
++	{
++		.core_note_type = NT_PRFPREG,
++		.n = sizeof(struct ia32_user_i387_struct) / 4,
++		.size = 4, .align = 4,
++		.get = ia32_fpregs_get, .set = ia32_fpregs_set
++	},
++	{
++		.core_note_type = NT_PRXFPREG,
++		.n = sizeof(struct ia32_user_fxsr_struct) / 4,
++		.size = 4, .align = 4,
++		.get = ia32_fpxregs_get, .set = ia32_fpxregs_set
++	},
++	{
++		.core_note_type = NT_386_TLS,
++		.n = GDT_ENTRY_TLS_ENTRIES,
++		.bias = GDT_ENTRY_TLS_MIN,
++		.size = sizeof(struct ia32_user_desc),
++		.align = sizeof(struct ia32_user_desc),
++		.active = ia32_tls_active,
++		.get = ia32_tls_get, .set = ia32_tls_set,
++	},
++};
++
++const struct user_regset_view user_ia32_view = {
++	.name = "i386", .e_machine = EM_386,
++	.regsets = ia32_regsets, .n = ARRAY_SIZE(ia32_regsets)
++};
++
+ long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, 
+ 			__u32 len_low, __u32 len_high, int advice)
+ { 
+diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
+index 33e5a59..13fd10e 100644
+--- a/arch/ia64/kernel/Makefile
++++ b/arch/ia64/kernel/Makefile
+@@ -6,7 +6,7 @@ extra-y	:= head.o init_task.o vmlinux.lds
+ 
+ obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o	\
+ 	 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o		\
+-	 salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
++	 salinfo.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
+ 	 unwind.o mca.o mca_asm.o topology.o
+ 
+ obj-$(CONFIG_IA64_BRL_EMU)	+= brl_emu.o
+diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
+index 78f28d8..c7467f8 100644
+--- a/arch/ia64/kernel/acpi.c
++++ b/arch/ia64/kernel/acpi.c
+@@ -423,6 +423,7 @@ static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
+ #define pxm_bit_set(bit)	(set_bit(bit,(void *)pxm_flag))
+ #define pxm_bit_test(bit)	(test_bit(bit,(void *)pxm_flag))
+ static struct acpi_table_slit __initdata *slit_table;
++cpumask_t early_cpu_possible_map = CPU_MASK_NONE;
+ 
+ static int get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
+ {
+@@ -482,6 +483,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
+ 	    (pa->apic_id << 8) | (pa->local_sapic_eid);
+ 	/* nid should be overridden as logical node id later */
+ 	node_cpuid[srat_num_cpus].nid = pxm;
++	cpu_set(srat_num_cpus, early_cpu_possible_map);
+ 	srat_num_cpus++;
+ }
+ 
+@@ -559,7 +561,7 @@ void __init acpi_numa_arch_fixup(void)
+ 	}
+ 
+ 	/* set logical node id in cpu structure */
+-	for (i = 0; i < srat_num_cpus; i++)
++	for_each_possible_early_cpu(i)
+ 		node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid);
+ 
+ 	printk(KERN_INFO "Number of logical nodes in system = %d\n",
+diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
+index 0aebc6f..230a6f9 100644
+--- a/arch/ia64/kernel/asm-offsets.c
++++ b/arch/ia64/kernel/asm-offsets.c
+@@ -7,6 +7,7 @@
+ #define ASM_OFFSETS_C 1
+ 
+ #include <linux/sched.h>
++#include <linux/pid.h>
+ #include <linux/clocksource.h>
+ 
+ #include <asm-ia64/processor.h>
+@@ -34,17 +35,29 @@ void foo(void)
+ 	DEFINE(SIGFRAME_SIZE, sizeof (struct sigframe));
+ 	DEFINE(UNW_FRAME_INFO_SIZE, sizeof (struct unw_frame_info));
+ 
++	BUILD_BUG_ON(sizeof(struct upid) != 32);
++	DEFINE(IA64_UPID_SHIFT, 5);
++
+ 	BLANK();
+ 
+ 	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+ 	DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	DEFINE(TI_AC_STAMP, offsetof(struct thread_info, ac_stamp));
++	DEFINE(TI_AC_LEAVE, offsetof(struct thread_info, ac_leave));
++	DEFINE(TI_AC_STIME, offsetof(struct thread_info, ac_stime));
++	DEFINE(TI_AC_UTIME, offsetof(struct thread_info, ac_utime));
++#endif
+ 
+ 	BLANK();
+ 
+ 	DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked));
+ 	DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid));
+ 	DEFINE(IA64_TASK_GROUP_LEADER_OFFSET, offsetof (struct task_struct, group_leader));
++	DEFINE(IA64_TASK_TGIDLINK_OFFSET, offsetof (struct task_struct, pids[PIDTYPE_PID].pid));
++	DEFINE(IA64_PID_LEVEL_OFFSET, offsetof (struct pid, level));
++	DEFINE(IA64_PID_UPID_OFFSET, offsetof (struct pid, numbers[0]));
+ 	DEFINE(IA64_TASK_PENDING_OFFSET,offsetof (struct task_struct, pending));
+ 	DEFINE(IA64_TASK_PID_OFFSET, offsetof (struct task_struct, pid));
+ 	DEFINE(IA64_TASK_REAL_PARENT_OFFSET, offsetof (struct task_struct, real_parent));
+diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
+index fbe742a..f065093 100644
+--- a/arch/ia64/kernel/crash.c
++++ b/arch/ia64/kernel/crash.c
+@@ -24,6 +24,7 @@ int kdump_status[NR_CPUS];
+ static atomic_t kdump_cpu_frozen;
+ atomic_t kdump_in_progress;
+ static int kdump_on_init = 1;
++static int kdump_on_fatal_mca = 1;
+ 
+ static inline Elf64_Word
+ *append_elf_note(Elf64_Word *buf, char *name, unsigned type, void *data,
+@@ -118,6 +119,7 @@ machine_crash_shutdown(struct pt_regs *pt)
+ static void
+ machine_kdump_on_init(void)
+ {
++	crash_save_vmcoreinfo();
+ 	local_irq_disable();
+ 	kexec_disable_iosapic();
+ 	machine_kexec(ia64_kimage);
+@@ -148,7 +150,7 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
+ 	struct ia64_mca_notify_die *nd;
+ 	struct die_args *args = data;
+ 
+-	if (!kdump_on_init)
++	if (!kdump_on_init && !kdump_on_fatal_mca)
+ 		return NOTIFY_DONE;
+ 
+ 	if (!ia64_kimage) {
+@@ -173,32 +175,38 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
+ 		return NOTIFY_DONE;
+ 
+ 	switch (val) {
+-		case DIE_INIT_MONARCH_PROCESS:
++	case DIE_INIT_MONARCH_PROCESS:
++		if (kdump_on_init) {
+ 			atomic_set(&kdump_in_progress, 1);
+ 			*(nd->monarch_cpu) = -1;
+-			break;
+-		case DIE_INIT_MONARCH_LEAVE:
++		}
++		break;
++	case DIE_INIT_MONARCH_LEAVE:
++		if (kdump_on_init)
+ 			machine_kdump_on_init();
+-			break;
+-		case DIE_INIT_SLAVE_LEAVE:
+-			if (atomic_read(&kdump_in_progress))
+-				unw_init_running(kdump_cpu_freeze, NULL);
+-			break;
+-		case DIE_MCA_RENDZVOUS_LEAVE:
+-			if (atomic_read(&kdump_in_progress))
+-				unw_init_running(kdump_cpu_freeze, NULL);
+-			break;
+-		case DIE_MCA_MONARCH_LEAVE:
+-		     /* die_register->signr indicate if MCA is recoverable */
+-			if (!args->signr)
+-				machine_kdump_on_init();
+-			break;
++		break;
++	case DIE_INIT_SLAVE_LEAVE:
++		if (atomic_read(&kdump_in_progress))
++			unw_init_running(kdump_cpu_freeze, NULL);
++		break;
++	case DIE_MCA_RENDZVOUS_LEAVE:
++		if (atomic_read(&kdump_in_progress))
++			unw_init_running(kdump_cpu_freeze, NULL);
++		break;
++	case DIE_MCA_MONARCH_LEAVE:
++		/* *(nd->data) indicate if MCA is recoverable */
++		if (kdump_on_fatal_mca && !(*(nd->data))) {
++			atomic_set(&kdump_in_progress, 1);
++			*(nd->monarch_cpu) = -1;
++			machine_kdump_on_init();
++		}
++		break;
+ 	}
+ 	return NOTIFY_DONE;
+ }
+ 
+ #ifdef CONFIG_SYSCTL
+-static ctl_table kdump_on_init_table[] = {
++static ctl_table kdump_ctl_table[] = {
+ 	{
+ 		.ctl_name = CTL_UNNUMBERED,
+ 		.procname = "kdump_on_init",
+@@ -207,6 +215,14 @@ static ctl_table kdump_on_init_table[] = {
+ 		.mode = 0644,
+ 		.proc_handler = &proc_dointvec,
+ 	},
++	{
++		.ctl_name = CTL_UNNUMBERED,
++		.procname = "kdump_on_fatal_mca",
++		.data = &kdump_on_fatal_mca,
++		.maxlen = sizeof(int),
++		.mode = 0644,
++		.proc_handler = &proc_dointvec,
++	},
+ 	{ .ctl_name = 0 }
+ };
+ 
+@@ -215,7 +231,7 @@ static ctl_table sys_table[] = {
+ 	  .ctl_name = CTL_KERN,
+ 	  .procname = "kernel",
+ 	  .mode = 0555,
+-	  .child = kdump_on_init_table,
++	  .child = kdump_ctl_table,
+ 	},
+ 	{ .ctl_name = 0 }
+ };
+diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
+index 728d724..d45f215 100644
+--- a/arch/ia64/kernel/efi.c
++++ b/arch/ia64/kernel/efi.c
+@@ -37,6 +37,7 @@
+ #include <asm/pgtable.h>
+ #include <asm/processor.h>
+ #include <asm/mca.h>
++#include <asm/tlbflush.h>
+ 
+ #define EFI_DEBUG	0
+ 
+@@ -403,6 +404,41 @@ efi_get_pal_addr (void)
+ 	return NULL;
+ }
+ 
++
++static u8 __init palo_checksum(u8 *buffer, u32 length)
++{
++	u8 sum = 0;
++	u8 *end = buffer + length;
++
++	while (buffer < end)
++		sum = (u8) (sum + *(buffer++));
++
++	return sum;
++}
++
++/*
++ * Parse and handle PALO table which is published at:
++ * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf
++ */
++static void __init handle_palo(unsigned long palo_phys)
++{
++	struct palo_table *palo = __va(palo_phys);
++	u8  checksum;
++
++	if (strncmp(palo->signature, PALO_SIG, sizeof(PALO_SIG) - 1)) {
++		printk(KERN_INFO "PALO signature incorrect.\n");
++		return;
++	}
++
++	checksum = palo_checksum((u8 *)palo, palo->length);
++	if (checksum) {
++		printk(KERN_INFO "PALO checksum incorrect.\n");
++		return;
++	}
++
++	setup_ptcg_sem(palo->max_tlb_purges, NPTCG_FROM_PALO);
++}
++
+ void
+ efi_map_pal_code (void)
+ {
+@@ -432,6 +468,7 @@ efi_init (void)
+ 	u64 efi_desc_size;
+ 	char *cp, vendor[100] = "unknown";
+ 	int i;
++	unsigned long palo_phys;
+ 
+ 	/*
+ 	 * It's too early to be able to use the standard kernel command line
+@@ -496,6 +533,8 @@ efi_init (void)
+ 	efi.hcdp       = EFI_INVALID_TABLE_ADDR;
+ 	efi.uga        = EFI_INVALID_TABLE_ADDR;
+ 
++	palo_phys      = EFI_INVALID_TABLE_ADDR;
++
+ 	for (i = 0; i < (int) efi.systab->nr_tables; i++) {
+ 		if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
+ 			efi.mps = config_tables[i].table;
+@@ -515,10 +554,17 @@ efi_init (void)
+ 		} else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
+ 			efi.hcdp = config_tables[i].table;
+ 			printk(" HCDP=0x%lx", config_tables[i].table);
++		} else if (efi_guidcmp(config_tables[i].guid,
++			 PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID) == 0) {
++			palo_phys = config_tables[i].table;
++			printk(" PALO=0x%lx", config_tables[i].table);
+ 		}
+ 	}
+ 	printk("\n");
+ 
++	if (palo_phys != EFI_INVALID_TABLE_ADDR)
++		handle_palo(palo_phys);
++
+ 	runtime = __va(efi.systab->runtime);
+ 	efi.get_time = phys_get_time;
+ 	efi.set_time = phys_set_time;
+diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
+index 3c331c4..e49ad8c 100644
+--- a/arch/ia64/kernel/entry.S
++++ b/arch/ia64/kernel/entry.S
+@@ -570,6 +570,7 @@ GLOBAL_ENTRY(ia64_trace_syscall)
+ 	br.call.sptk.many rp=syscall_trace_leave // give parent a chance to catch return value
+ .ret3:
+ (pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
++(pUStk)	rsm psr.i				// disable interrupts
+ 	br.cond.sptk .work_pending_syscall_end
+ 
+ strace_error:
+@@ -710,6 +711,16 @@ ENTRY(ia64_leave_syscall)
+ (pUStk)	cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
+ #endif
+ .work_processed_syscall:
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	adds r2=PT(LOADRS)+16,r12
++(pUStk)	mov.m r22=ar.itc			// fetch time at leave
++	adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
++	;;
++(p6)	ld4 r31=[r18]				// load current_thread_info()->flags
++	ld8 r19=[r2],PT(B6)-PT(LOADRS)		// load ar.rsc value for "loadrs"
++	adds r3=PT(AR_BSPSTORE)+16,r12		// deferred
++	;;
++#else
+ 	adds r2=PT(LOADRS)+16,r12
+ 	adds r3=PT(AR_BSPSTORE)+16,r12
+ 	adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
+@@ -718,6 +729,7 @@ ENTRY(ia64_leave_syscall)
+ 	ld8 r19=[r2],PT(B6)-PT(LOADRS)		// load ar.rsc value for "loadrs"
+ 	nop.i 0
+ 	;;
++#endif
+ 	mov r16=ar.bsp				// M2  get existing backing store pointer
+ 	ld8 r18=[r2],PT(R9)-PT(B6)		// load b6
+ (p6)	and r15=TIF_WORK_MASK,r31		// any work other than TIF_SYSCALL_TRACE?
+@@ -737,12 +749,21 @@ ENTRY(ia64_leave_syscall)
+ 
+ 	ld8 r29=[r2],16		// M0|1 load cr.ipsr
+ 	ld8 r28=[r3],16		// M0|1 load cr.iip
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++(pUStk) add r14=TI_AC_LEAVE+IA64_TASK_SIZE,r13
++	;;
++	ld8 r30=[r2],16		// M0|1 load cr.ifs
++	ld8 r25=[r3],16		// M0|1 load ar.unat
++(pUStk) add r15=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
++	;;
++#else
+ 	mov r22=r0		// A    clear r22
+ 	;;
+ 	ld8 r30=[r2],16		// M0|1 load cr.ifs
+ 	ld8 r25=[r3],16		// M0|1 load ar.unat
+ (pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
+ 	;;
++#endif
+ 	ld8 r26=[r2],PT(B0)-PT(AR_PFS)	// M0|1 load ar.pfs
+ (pKStk)	mov r22=psr			// M2   read PSR now that interrupts are disabled
+ 	nop 0
+@@ -759,7 +780,11 @@ ENTRY(ia64_leave_syscall)
+ 	ld8.fill r1=[r3],16			// M0|1 load r1
+ (pUStk) mov r17=1				// A
+ 	;;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++(pUStk) st1 [r15]=r17				// M2|3
++#else
+ (pUStk) st1 [r14]=r17				// M2|3
++#endif
+ 	ld8.fill r13=[r3],16			// M0|1
+ 	mov f8=f0				// F    clear f8
+ 	;;
+@@ -775,12 +800,22 @@ ENTRY(ia64_leave_syscall)
+ 	shr.u r18=r19,16		// I0|1 get byte size of existing "dirty" partition
+ 	cover				// B    add current frame into dirty partition & set cr.ifs
+ 	;;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	mov r19=ar.bsp			// M2   get new backing store pointer
++	st8 [r14]=r22			// M	save time at leave
++	mov f10=f0			// F    clear f10
++
++	mov r22=r0			// A	clear r22
++	movl r14=__kernel_syscall_via_epc // X
++	;;
++#else
+ 	mov r19=ar.bsp			// M2   get new backing store pointer
+ 	mov f10=f0			// F    clear f10
+ 
+ 	nop.m 0
+ 	movl r14=__kernel_syscall_via_epc // X
+ 	;;
++#endif
+ 	mov.m ar.csd=r0			// M2   clear ar.csd
+ 	mov.m ar.ccv=r0			// M2   clear ar.ccv
+ 	mov b7=r14			// I0   clear b7 (hint with __kernel_syscall_via_epc)
+@@ -913,10 +948,18 @@ GLOBAL_ENTRY(ia64_leave_kernel)
+ 	adds r16=PT(CR_IPSR)+16,r12
+ 	adds r17=PT(CR_IIP)+16,r12
+ 
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	.pred.rel.mutex pUStk,pKStk
++(pKStk)	mov r22=psr		// M2 read PSR now that interrupts are disabled
++(pUStk)	mov.m r22=ar.itc	// M  fetch time at leave
++	nop.i 0
++	;;
++#else
+ (pKStk)	mov r22=psr		// M2 read PSR now that interrupts are disabled
+ 	nop.i 0
+ 	nop.i 0
+ 	;;
++#endif
+ 	ld8 r29=[r16],16	// load cr.ipsr
+ 	ld8 r28=[r17],16	// load cr.iip
+ 	;;
+@@ -938,15 +981,37 @@ GLOBAL_ENTRY(ia64_leave_kernel)
+ 	;;
+ 	ld8.fill r12=[r16],16
+ 	ld8.fill r13=[r17],16
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++(pUStk)	adds r3=TI_AC_LEAVE+IA64_TASK_SIZE,r18
++#else
+ (pUStk)	adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
++#endif
+ 	;;
+ 	ld8 r20=[r16],16	// ar.fpsr
+ 	ld8.fill r15=[r17],16
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++(pUStk)	adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18	// deferred
++#endif
+ 	;;
+ 	ld8.fill r14=[r16],16
+ 	ld8.fill r2=[r17]
+ (pUStk)	mov r17=1
+ 	;;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	//  mmi_ :  ld8 st1 shr;;         mmi_ : st8 st1 shr;;
++	//  mib  :  mov add br        ->  mib  : ld8 add br
++	//  bbb_ :  br  nop cover;;       mbb_ : mov br  cover;;
++	//
++	//  no one require bsp in r16 if (pKStk) branch is selected.
++(pUStk)	st8 [r3]=r22		// save time at leave
++(pUStk)	st1 [r18]=r17		// restore current->thread.on_ustack
++	shr.u r18=r19,16	// get byte size of existing "dirty" partition
++	;;
++	ld8.fill r3=[r16]	// deferred
++	LOAD_PHYS_STACK_REG_SIZE(r17)
++(pKStk)	br.cond.dpnt skip_rbs_switch
++	mov r16=ar.bsp		// get existing backing store pointer
++#else
+ 	ld8.fill r3=[r16]
+ (pUStk)	st1 [r18]=r17		// restore current->thread.on_ustack
+ 	shr.u r18=r19,16	// get byte size of existing "dirty" partition
+@@ -954,6 +1019,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
+ 	mov r16=ar.bsp		// get existing backing store pointer
+ 	LOAD_PHYS_STACK_REG_SIZE(r17)
+ (pKStk)	br.cond.dpnt skip_rbs_switch
++#endif
+ 
+ 	/*
+ 	 * Restore user backing store.
+diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
+index 4484197..c1625c7 100644
+--- a/arch/ia64/kernel/fsys.S
++++ b/arch/ia64/kernel/fsys.S
+@@ -61,13 +61,29 @@ ENTRY(fsys_getpid)
+ 	.prologue
+ 	.altrp b6
+ 	.body
++	add r17=IA64_TASK_GROUP_LEADER_OFFSET,r16
++	;;
++	ld8 r17=[r17]				// r17 = current->group_leader
+ 	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
+ 	;;
+ 	ld4 r9=[r9]
+-	add r8=IA64_TASK_TGID_OFFSET,r16
++	add r17=IA64_TASK_TGIDLINK_OFFSET,r17
+ 	;;
+ 	and r9=TIF_ALLWORK_MASK,r9
+-	ld4 r8=[r8]				// r8 = current->tgid
++	ld8 r17=[r17]				// r17 = current->group_leader->pids[PIDTYPE_PID].pid
++	;;
++	add r8=IA64_PID_LEVEL_OFFSET,r17
++	;;
++	ld4 r8=[r8]				// r8 = pid->level
++	add r17=IA64_PID_UPID_OFFSET,r17	// r17 = &pid->numbers[0]
++	;;
++	shl r8=r8,IA64_UPID_SHIFT
++	;;
++	add r17=r17,r8				// r17 = &pid->numbers[pid->level]
++	;;
++	ld4 r8=[r17]				// r8 = pid->numbers[pid->level].nr
++	;;
++	mov r17=0
+ 	;;
+ 	cmp.ne p8,p0=0,r9
+ (p8)	br.spnt.many fsys_fallback_syscall
+@@ -126,15 +142,25 @@ ENTRY(fsys_set_tid_address)
+ 	.altrp b6
+ 	.body
+ 	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
++	add r17=IA64_TASK_TGIDLINK_OFFSET,r16
+ 	;;
+ 	ld4 r9=[r9]
+ 	tnat.z p6,p7=r32		// check argument register for being NaT
++	ld8 r17=[r17]				// r17 = current->pids[PIDTYPE_PID].pid
+ 	;;
+ 	and r9=TIF_ALLWORK_MASK,r9
+-	add r8=IA64_TASK_PID_OFFSET,r16
++	add r8=IA64_PID_LEVEL_OFFSET,r17
+ 	add r18=IA64_TASK_CLEAR_CHILD_TID_OFFSET,r16
+ 	;;
+-	ld4 r8=[r8]
++	ld4 r8=[r8]				// r8 = pid->level
++	add r17=IA64_PID_UPID_OFFSET,r17	// r17 = &pid->numbers[0]
++	;;
++	shl r8=r8,IA64_UPID_SHIFT
++	;;
++	add r17=r17,r8				// r17 = &pid->numbers[pid->level]
++	;;
++	ld4 r8=[r17]				// r8 = pid->numbers[pid->level].nr
++	;;
+ 	cmp.ne p8,p0=0,r9
+ 	mov r17=-1
+ 	;;
+@@ -210,27 +236,25 @@ ENTRY(fsys_gettimeofday)
+ 	// Note that instructions are optimized for McKinley. McKinley can
+ 	// process two bundles simultaneously and therefore we continuously
+ 	// try to feed the CPU two bundles and then a stop.
+-	//
+-	// Additional note that code has changed a lot. Optimization is TBD.
+-	// Comments begin with "?" are maybe outdated.
+-	tnat.nz p6,p0 = r31	// ? branch deferred to fit later bundle
+-	mov pr = r30,0xc000	// Set predicates according to function
++
+ 	add r2 = TI_FLAGS+IA64_TASK_SIZE,r16
++	tnat.nz p6,p0 = r31		// guard against Nat argument
++(p6)	br.cond.spnt.few .fail_einval
+ 	movl r20 = fsyscall_gtod_data // load fsyscall gettimeofday data address
+ 	;;
++	ld4 r2 = [r2]			// process work pending flags
+ 	movl r29 = itc_jitter_data	// itc_jitter
+ 	add r22 = IA64_GTOD_WALL_TIME_OFFSET,r20	// wall_time
+-	ld4 r2 = [r2]		// process work pending flags
+-	;;
+-(p15)	add r22 = IA64_GTOD_MONO_TIME_OFFSET,r20	// monotonic_time
+ 	add r21 = IA64_CLKSRC_MMIO_OFFSET,r20
+-	add r19 = IA64_ITC_LASTCYCLE_OFFSET,r29
++	mov pr = r30,0xc000	// Set predicates according to function
++	;;
+ 	and r2 = TIF_ALLWORK_MASK,r2
+-(p6)    br.cond.spnt.few .fail_einval	// ? deferred branch
++	add r19 = IA64_ITC_LASTCYCLE_OFFSET,r29
++(p15)	add r22 = IA64_GTOD_MONO_TIME_OFFSET,r20	// monotonic_time
+ 	;;
+-	add r26 = IA64_CLKSRC_CYCLE_LAST_OFFSET,r20 // clksrc_cycle_last
++	add r26 = IA64_CLKSRC_CYCLE_LAST_OFFSET,r20	// clksrc_cycle_last
+ 	cmp.ne p6, p0 = 0, r2	// Fallback if work is scheduled
+-(p6)    br.cond.spnt.many fsys_fallback_syscall
++(p6)	br.cond.spnt.many fsys_fallback_syscall
+ 	;;
+ 	// Begin critical section
+ .time_redo:
+@@ -258,7 +282,6 @@ ENTRY(fsys_gettimeofday)
+ (p8)	mov r2 = ar.itc		// CPU_TIMER. 36 clocks latency!!!
+ (p9)	ld8 r2 = [r30]		// MMIO_TIMER. Could also have latency issues..
+ (p13)	ld8 r25 = [r19]		// get itc_lastcycle value
+-	;;		// ? could be removed by moving the last add upward
+ 	ld8 r9 = [r22],IA64_TIMESPEC_TV_NSEC_OFFSET	// tv_sec
+ 	;;
+ 	ld8 r8 = [r22],-IA64_TIMESPEC_TV_NSEC_OFFSET	// tv_nsec
+@@ -285,13 +308,12 @@ ENTRY(fsys_gettimeofday)
+ EX(.fail_efault, probe.w.fault r31, 3)
+ 	xmpy.l f8 = f8,f7	// nsec_per_cyc*(counter-last_counter)
+ 	;;
+-	// ? simulate tbit.nz.or p7,p0 = r28,0
+ 	getf.sig r2 = f8
+ 	mf
+ 	;;
+ 	ld4 r10 = [r20]		// gtod_lock.sequence
+ 	shr.u r2 = r2,r23	// shift by factor
+-	;;		// ? overloaded 3 bundles!
++	;;
+ 	add r8 = r8,r2		// Add xtime.nsecs
+ 	cmp4.ne p7,p0 = r28,r10
+ (p7)	br.cond.dpnt.few .time_redo	// sequence number changed, redo
+@@ -319,9 +341,9 @@ EX(.fail_efault, probe.w.fault r31, 3)
+ EX(.fail_efault, probe.w.fault r23, 3)	// This also costs 5 cycles
+ (p14)	xmpy.hu f8 = f8, f7		// xmpy has 5 cycles latency so use it
+ 	;;
+-	mov r8 = r0
+ (p14)	getf.sig r2 = f8
+ 	;;
++	mov r8 = r0
+ (p14)	shr.u r21 = r2, 4
+ 	;;
+ EX(.fail_efault, st8 [r31] = r9)
+@@ -660,7 +682,11 @@ GLOBAL_ENTRY(fsys_bubble_down)
+ 	nop.i 0
+ 	;;
+ 	mov ar.rsc=0				// M2   set enforced lazy mode, pl 0, LE, loadrs=0
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	mov.m r30=ar.itc			// M    get cycle for accounting
++#else
+ 	nop.m 0
++#endif
+ 	nop.i 0
+ 	;;
+ 	mov r23=ar.bspstore			// M2 (12 cyc) save ar.bspstore
+@@ -682,6 +708,28 @@ GLOBAL_ENTRY(fsys_bubble_down)
+ 	cmp.ne pKStk,pUStk=r0,r0		// A    set pKStk <- 0, pUStk <- 1
+ 	br.call.sptk.many b7=ia64_syscall_setup	// B
+ 	;;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	// mov.m r30=ar.itc is called in advance
++	add r16=TI_AC_STAMP+IA64_TASK_SIZE,r2
++	add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r2
++	;;
++	ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP	// time at last check in kernel
++	ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE	// time at leave kernel
++	;;
++	ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME	// cumulated stime
++	ld8 r21=[r17]				// cumulated utime
++	sub r22=r19,r18				// stime before leave kernel
++	;;
++	st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP	// update stamp
++	sub r18=r30,r19				// elapsed time in user mode
++	;;
++	add r20=r20,r22				// sum stime
++	add r21=r21,r18				// sum utime
++	;;
++	st8 [r16]=r20				// update stime
++	st8 [r17]=r21				// update utime
++	;;
++#endif
+ 	mov ar.rsc=0x3				// M2   set eager mode, pl 0, LE, loadrs=0
+ 	mov rp=r14				// I0   set the real return addr
+ 	and r3=_TIF_SYSCALL_TRACEAUDIT,r3	// A
+diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
+index d3a41d5..ddeab4e 100644
+--- a/arch/ia64/kernel/head.S
++++ b/arch/ia64/kernel/head.S
+@@ -1002,6 +1002,26 @@ GLOBAL_ENTRY(sched_clock)
+ 	br.ret.sptk.many rp
+ END(sched_clock)
+ 
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++GLOBAL_ENTRY(cycle_to_cputime)
++	alloc r16=ar.pfs,1,0,0,0
++	addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
++	;;
++	ldf8 f8=[r8]
++	;;
++	setf.sig f9=r32
++	;;
++	xmpy.lu f10=f9,f8	// calculate low 64 bits of 128-bit product	(4 cyc)
++	xmpy.hu f11=f9,f8	// calculate high 64 bits of 128-bit product
++	;;
++	getf.sig r8=f10		//						(5 cyc)
++	getf.sig r9=f11
++	;;
++	shrp r8=r9,r8,IA64_NSEC_PER_CYC_SHIFT
++	br.ret.sptk.many rp
++END(cycle_to_cputime)
++#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
++
+ GLOBAL_ENTRY(start_kernel_thread)
+ 	.prologue
+ 	.save rp, r0				// this is the end of the call-chain
+diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
+index 8e7193d..6da1f20 100644
+--- a/arch/ia64/kernel/ia64_ksyms.c
++++ b/arch/ia64/kernel/ia64_ksyms.c
+@@ -19,12 +19,6 @@ EXPORT_SYMBOL_GPL(empty_zero_page);
+ EXPORT_SYMBOL(ip_fast_csum);		/* hand-coded assembly */
+ EXPORT_SYMBOL(csum_ipv6_magic);
+ 
+-#include <asm/semaphore.h>
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__up);
+-
+ #include <asm/page.h>
+ EXPORT_SYMBOL(clear_page);
+ 
+diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
+index d8be23f..5538471 100644
+--- a/arch/ia64/kernel/irq_ia64.c
++++ b/arch/ia64/kernel/irq_ia64.c
+@@ -472,7 +472,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
+ 			static unsigned char count;
+ 			static long last_time;
+ 
+-			if (jiffies - last_time > 5*HZ)
++			if (time_after(jiffies, last_time + 5 * HZ))
+ 				count = 0;
+ 			if (++count < 5) {
+ 				last_time = jiffies;
+diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
+index 34f44d8..6678c49 100644
+--- a/arch/ia64/kernel/ivt.S
++++ b/arch/ia64/kernel/ivt.S
+@@ -805,8 +805,13 @@ ENTRY(break_fault)
+ 
+ (p8)	adds r28=16,r28				// A    switch cr.iip to next bundle
+ (p9)	adds r8=1,r8				// A    increment ei to next slot
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	;;
++	mov b6=r30				// I0   setup syscall handler branch reg early
++#else
+ 	nop.i 0
+ 	;;
++#endif
+ 
+ 	mov.m r25=ar.unat			// M2 (5 cyc)
+ 	dep r29=r8,r29,41,2			// I0   insert new ei into cr.ipsr
+@@ -817,7 +822,11 @@ ENTRY(break_fault)
+ 	//
+ ///////////////////////////////////////////////////////////////////////
+ 	st1 [r16]=r0				// M2|3 clear current->thread.on_ustack flag
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	mov.m r30=ar.itc			// M    get cycle for accounting
++#else
+ 	mov b6=r30				// I0   setup syscall handler branch reg early
++#endif
+ 	cmp.eq pKStk,pUStk=r0,r17		// A    were we on kernel stacks already?
+ 
+ 	and r9=_TIF_SYSCALL_TRACEAUDIT,r9	// A    mask trace or audit
+@@ -829,6 +838,30 @@ ENTRY(break_fault)
+ 	cmp.eq p14,p0=r9,r0			// A    are syscalls being traced/audited?
+ 	br.call.sptk.many b7=ia64_syscall_setup	// B
+ 1:
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	// mov.m r30=ar.itc is called in advance, and r13 is current
++	add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13	// A
++	add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13	// A
++(pKStk)	br.cond.spnt .skip_accounting		// B	unlikely skip
++	;;
++	ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP	// M  get last stamp
++	ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE	// M  time at leave
++	;;
++	ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME	// M  cumulated stime
++	ld8 r21=[r17]				// M  cumulated utime
++	sub r22=r19,r18				// A  stime before leave
++	;;
++	st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP	// M  update stamp
++	sub r18=r30,r19				// A  elapsed time in user
++	;;
++	add r20=r20,r22				// A  sum stime
++	add r21=r21,r18				// A  sum utime
++	;;
++	st8 [r16]=r20				// M  update stime
++	st8 [r17]=r21				// M  update utime
++	;;
++.skip_accounting:
++#endif
+ 	mov ar.rsc=0x3				// M2   set eager mode, pl 0, LE, loadrs=0
+ 	nop 0
+ 	bsw.1					// B (6 cyc) regs are saved, switch to bank 1
+@@ -928,6 +961,7 @@ END(interrupt)
+ 	 *	- r27: saved ar.rsc
+ 	 *	- r28: saved cr.iip
+ 	 *	- r29: saved cr.ipsr
++	 *	- r30: ar.itc for accounting (don't touch)
+ 	 *	- r31: saved pr
+ 	 *	-  b0: original contents (to be saved)
+ 	 * On exit:
+@@ -1090,6 +1124,41 @@ END(dispatch_illegal_op_fault)
+ 	DBG_FAULT(16)
+ 	FAULT(16)
+ 
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	/*
++	 * There is no particular reason for this code to be here, other than
++	 * that there happens to be space here that would go unused otherwise.
++	 * If this fault ever gets "unreserved", simply moved the following
++	 * code to a more suitable spot...
++	 *
++	 * account_sys_enter is called from SAVE_MIN* macros if accounting is
++	 * enabled and if the macro is entered from user mode.
++	 */
++ENTRY(account_sys_enter)
++	// mov.m r20=ar.itc is called in advance, and r13 is current
++	add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13
++	add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13
++	;;
++	ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP	// time at last check in kernel
++	ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE	// time at left from kernel
++        ;;
++	ld8 r23=[r16],TI_AC_STAMP-TI_AC_STIME	// cumulated stime
++	ld8 r21=[r17]				// cumulated utime
++	sub r22=r19,r18				// stime before leave kernel
++	;;
++	st8 [r16]=r20,TI_AC_STIME-TI_AC_STAMP	// update stamp
++	sub r18=r20,r19				// elapsed time in user mode
++	;;
++	add r23=r23,r22				// sum stime
++	add r21=r21,r18				// sum utime
++	;;
++	st8 [r16]=r23				// update stime
++	st8 [r17]=r21				// update utime
++	;;
++	br.ret.sptk.many rp
++END(account_sys_enter)
++#endif
++
+ 	.org ia64_ivt+0x4400
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // 0x4400 Entry 17 (size 64 bundles) Reserved
+diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
+index 8d9a446..233434f 100644
+--- a/arch/ia64/kernel/kprobes.c
++++ b/arch/ia64/kernel/kprobes.c
+@@ -78,6 +78,20 @@ static enum instruction_type bundle_encoding[32][3] = {
+   { u, u, u },  			/* 1F */
+ };
+ 
++/* Insert a long branch code */
++static void __kprobes set_brl_inst(void *from, void *to)
++{
++	s64 rel = ((s64) to - (s64) from) >> 4;
++	bundle_t *brl;
++	brl = (bundle_t *) ((u64) from & ~0xf);
++	brl->quad0.template = 0x05;	/* [MLX](stop) */
++	brl->quad0.slot0 = NOP_M_INST;	/* nop.m 0x0 */
++	brl->quad0.slot1_p0 = ((rel >> 20) & 0x7fffffffff) << 2;
++	brl->quad1.slot1_p1 = (((rel >> 20) & 0x7fffffffff) << 2) >> (64 - 46);
++	/* brl.cond.sptk.many.clr rel<<4 (qp=0) */
++	brl->quad1.slot2 = BRL_INST(rel >> 59, rel & 0xfffff);
++}
++
+ /*
+  * In this function we check to see if the instruction
+  * is IP relative instruction and update the kprobe
+@@ -496,6 +510,77 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
+ 	regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;
+ }
+ 
++/* Check the instruction in the slot is break */
++static int __kprobes __is_ia64_break_inst(bundle_t *bundle, uint slot)
++{
++	unsigned int major_opcode;
++	unsigned int template = bundle->quad0.template;
++	unsigned long kprobe_inst;
++
++	/* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
++	if (slot == 1 && bundle_encoding[template][1] == L)
++		slot++;
++
++	/* Get Kprobe probe instruction at given slot*/
++	get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
++
++	/* For break instruction,
++	 * Bits 37:40 Major opcode to be zero
++	 * Bits 27:32 X6 to be zero
++	 * Bits 32:35 X3 to be zero
++	 */
++	if (major_opcode || ((kprobe_inst >> 27) & 0x1FF)) {
++		/* Not a break instruction */
++		return 0;
++	}
++
++	/* Is a break instruction */
++	return 1;
++}
++
++/*
++ * In this function, we check whether the target bundle modifies IP or
++ * it triggers an exception. If so, it cannot be boostable.
++ */
++static int __kprobes can_boost(bundle_t *bundle, uint slot,
++			       unsigned long bundle_addr)
++{
++	unsigned int template = bundle->quad0.template;
++
++	do {
++		if (search_exception_tables(bundle_addr + slot) ||
++		    __is_ia64_break_inst(bundle, slot))
++			return 0;	/* exception may occur in this bundle*/
++	} while ((++slot) < 3);
++	template &= 0x1e;
++	if (template >= 0x10 /* including B unit */ ||
++	    template == 0x04 /* including X unit */ ||
++	    template == 0x06) /* undefined */
++		return 0;
++
++	return 1;
++}
++
++/* Prepare long jump bundle and disables other boosters if need */
++static void __kprobes prepare_booster(struct kprobe *p)
++{
++	unsigned long addr = (unsigned long)p->addr & ~0xFULL;
++	unsigned int slot = (unsigned long)p->addr & 0xf;
++	struct kprobe *other_kp;
++
++	if (can_boost(&p->ainsn.insn[0].bundle, slot, addr)) {
++		set_brl_inst(&p->ainsn.insn[1].bundle, (bundle_t *)addr + 1);
++		p->ainsn.inst_flag |= INST_FLAG_BOOSTABLE;
++	}
++
++	/* disables boosters in previous slots */
++	for (; addr < (unsigned long)p->addr; addr++) {
++		other_kp = get_kprobe((void *)addr);
++		if (other_kp)
++			other_kp->ainsn.inst_flag &= ~INST_FLAG_BOOSTABLE;
++	}
++}
++
+ int __kprobes arch_prepare_kprobe(struct kprobe *p)
+ {
+ 	unsigned long addr = (unsigned long) p->addr;
+@@ -530,6 +615,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
+ 
+ 	prepare_break_inst(template, slot, major_opcode, kprobe_inst, p, qp);
+ 
++	prepare_booster(p);
++
+ 	return 0;
+ }
+ 
+@@ -543,7 +630,9 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
+ 	src = &p->opcode.bundle;
+ 
+ 	flush_icache_range((unsigned long)p->ainsn.insn,
+-			(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
++			   (unsigned long)p->ainsn.insn +
++			   sizeof(kprobe_opcode_t) * MAX_INSN_SIZE);
++
+ 	switch (p->ainsn.slot) {
+ 		case 0:
+ 			dest->quad0.slot0 = src->quad0.slot0;
+@@ -584,13 +673,13 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
+ void __kprobes arch_remove_kprobe(struct kprobe *p)
+ {
+ 	mutex_lock(&kprobe_mutex);
+-	free_insn_slot(p->ainsn.insn, 0);
++	free_insn_slot(p->ainsn.insn, p->ainsn.inst_flag & INST_FLAG_BOOSTABLE);
+ 	mutex_unlock(&kprobe_mutex);
+ }
+ /*
+  * We are resuming execution after a single step fault, so the pt_regs
+  * structure reflects the register state after we executed the instruction
+- * located in the kprobe (p->ainsn.insn.bundle).  We still need to adjust
++ * located in the kprobe (p->ainsn.insn->bundle).  We still need to adjust
+  * the ip to point back to the original stack address. To set the IP address
+  * to original stack address, handle the case where we need to fixup the
+  * relative IP address and/or fixup branch register.
+@@ -607,7 +696,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+ 	if (slot == 1 && bundle_encoding[template][1] == L)
+ 		slot = 2;
+ 
+-	if (p->ainsn.inst_flag) {
++	if (p->ainsn.inst_flag & ~INST_FLAG_BOOSTABLE) {
+ 
+ 		if (p->ainsn.inst_flag & INST_FLAG_FIX_RELATIVE_IP_ADDR) {
+ 			/* Fix relative IP address */
+@@ -686,33 +775,12 @@ static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
+ static int __kprobes is_ia64_break_inst(struct pt_regs *regs)
+ {
+ 	unsigned int slot = ia64_psr(regs)->ri;
+-	unsigned int template, major_opcode;
+-	unsigned long kprobe_inst;
+ 	unsigned long *kprobe_addr = (unsigned long *)regs->cr_iip;
+ 	bundle_t bundle;
+ 
+ 	memcpy(&bundle, kprobe_addr, sizeof(bundle_t));
+-	template = bundle.quad0.template;
+-
+-	/* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
+-	if (slot == 1 && bundle_encoding[template][1] == L)
+-		slot++;
+ 
+-	/* Get Kprobe probe instruction at given slot*/
+-	get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode);
+-
+-	/* For break instruction,
+-	 * Bits 37:40 Major opcode to be zero
+-	 * Bits 27:32 X6 to be zero
+-	 * Bits 32:35 X3 to be zero
+-	 */
+-	if (major_opcode || ((kprobe_inst >> 27) & 0x1FF) ) {
+-		/* Not a break instruction */
+-		return 0;
+-	}
+-
+-	/* Is a break instruction */
+-	return 1;
++	return __is_ia64_break_inst(&bundle, slot);
+ }
+ 
+ static int __kprobes pre_kprobes_handler(struct die_args *args)
+@@ -802,6 +870,19 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
+ 		return 1;
+ 
+ ss_probe:
++#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
++	if (p->ainsn.inst_flag == INST_FLAG_BOOSTABLE && !p->post_handler) {
++		/* Boost up -- we can execute copied instructions directly */
++		ia64_psr(regs)->ri = p->ainsn.slot;
++		regs->cr_iip = (unsigned long)&p->ainsn.insn->bundle & ~0xFULL;
++		/* turn single stepping off */
++		ia64_psr(regs)->ss = 0;
++
++		reset_current_kprobe();
++		preempt_enable_no_resched();
++		return 1;
++	}
++#endif
+ 	prepare_ss(p, regs);
+ 	kcb->kprobe_status = KPROBE_HIT_SS;
+ 	return 1;
+diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
+index 6c18221..705176b 100644
+--- a/arch/ia64/kernel/mca.c
++++ b/arch/ia64/kernel/mca.c
+@@ -69,6 +69,7 @@
+  * 2007-04-27 Russ Anderson <rja at sgi.com>
+  *	      Support multiple cpus going through OS_MCA in the same event.
+  */
++#include <linux/jiffies.h>
+ #include <linux/types.h>
+ #include <linux/init.h>
+ #include <linux/sched.h>
+@@ -97,6 +98,7 @@
+ 
+ #include <asm/irq.h>
+ #include <asm/hw_irq.h>
++#include <asm/tlb.h>
+ 
+ #include "mca_drv.h"
+ #include "entry.h"
+@@ -107,11 +109,26 @@
+ # define IA64_MCA_DEBUG(fmt...)
+ #endif
+ 
++#define NOTIFY_INIT(event, regs, arg, spin)				\
++do {									\
++	if ((notify_die((event), "INIT", (regs), (arg), 0, 0)		\
++			== NOTIFY_STOP) && ((spin) == 1))		\
++		ia64_mca_spin(__func__);				\
++} while (0)
++
++#define NOTIFY_MCA(event, regs, arg, spin)				\
++do {									\
++	if ((notify_die((event), "MCA", (regs), (arg), 0, 0)		\
++			== NOTIFY_STOP) && ((spin) == 1))		\
++		ia64_mca_spin(__func__);				\
++} while (0)
++
+ /* Used by mca_asm.S */
+ DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
+ DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */
+ DEFINE_PER_CPU(u64, ia64_mca_pal_pte);	    /* PTE to map PAL code */
+ DEFINE_PER_CPU(u64, ia64_mca_pal_base);    /* vaddr PAL code granule */
++DEFINE_PER_CPU(u64, ia64_mca_tr_reload);   /* Flag for TR reload */
+ 
+ unsigned long __per_cpu_mca[NR_CPUS];
+ 
+@@ -293,7 +310,8 @@ static void ia64_mlogbuf_dump_from_init(void)
+ 	if (mlogbuf_finished)
+ 		return;
+ 
+-	if (mlogbuf_timestamp && (mlogbuf_timestamp + 30*HZ > jiffies)) {
++	if (mlogbuf_timestamp &&
++			time_before(jiffies, mlogbuf_timestamp + 30 * HZ)) {
+ 		printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT "
+ 			" and the system seems to be messed up.\n");
+ 		ia64_mlogbuf_finish(0);
+@@ -762,9 +780,8 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg)
+ 
+ 	/* Mask all interrupts */
+ 	local_irq_save(flags);
+-	if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", get_irq_regs(),
+-		       (long)&nd, 0, 0) == NOTIFY_STOP)
+-		ia64_mca_spin(__func__);
++
++	NOTIFY_MCA(DIE_MCA_RENDZVOUS_ENTER, get_irq_regs(), (long)&nd, 1);
+ 
+ 	ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE;
+ 	/* Register with the SAL monarch that the slave has
+@@ -772,17 +789,13 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg)
+ 	 */
+ 	ia64_sal_mc_rendez();
+ 
+-	if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", get_irq_regs(),
+-		       (long)&nd, 0, 0) == NOTIFY_STOP)
+-		ia64_mca_spin(__func__);
++	NOTIFY_MCA(DIE_MCA_RENDZVOUS_PROCESS, get_irq_regs(), (long)&nd, 1);
+ 
+ 	/* Wait for the monarch cpu to exit. */
+ 	while (monarch_cpu != -1)
+ 	       cpu_relax();	/* spin until monarch leaves */
+ 
+-	if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", get_irq_regs(),
+-		       (long)&nd, 0, 0) == NOTIFY_STOP)
+-		ia64_mca_spin(__func__);
++	NOTIFY_MCA(DIE_MCA_RENDZVOUS_LEAVE, get_irq_regs(), (long)&nd, 1);
+ 
+ 	ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+ 	/* Enable all interrupts */
+@@ -1182,6 +1195,49 @@ all_in:
+ 	return;
+ }
+ 
++/*  mca_insert_tr
++ *
++ *  Switch rid when TR reload and needed!
++ *  iord: 1: itr, 2: itr;
++ *
++*/
++static void mca_insert_tr(u64 iord)
++{
++
++	int i;
++	u64 old_rr;
++	struct ia64_tr_entry *p;
++	unsigned long psr;
++	int cpu = smp_processor_id();
++
++	psr = ia64_clear_ic();
++	for (i = IA64_TR_ALLOC_BASE; i < IA64_TR_ALLOC_MAX; i++) {
++		p = &__per_cpu_idtrs[cpu][iord-1][i];
++		if (p->pte & 0x1) {
++			old_rr = ia64_get_rr(p->ifa);
++			if (old_rr != p->rr) {
++				ia64_set_rr(p->ifa, p->rr);
++				ia64_srlz_d();
++			}
++			ia64_ptr(iord, p->ifa, p->itir >> 2);
++			ia64_srlz_i();
++			if (iord & 0x1) {
++				ia64_itr(0x1, i, p->ifa, p->pte, p->itir >> 2);
++				ia64_srlz_i();
++			}
++			if (iord & 0x2) {
++				ia64_itr(0x2, i, p->ifa, p->pte, p->itir >> 2);
++				ia64_srlz_i();
++			}
++			if (old_rr != p->rr) {
++				ia64_set_rr(p->ifa, old_rr);
++				ia64_srlz_d();
++			}
++		}
++	}
++	ia64_set_psr(psr);
++}
++
+ /*
+  * ia64_mca_handler
+  *
+@@ -1209,7 +1265,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+ 	int recover, cpu = smp_processor_id();
+ 	struct task_struct *previous_current;
+ 	struct ia64_mca_notify_die nd =
+-		{ .sos = sos, .monarch_cpu = &monarch_cpu };
++		{ .sos = sos, .monarch_cpu = &monarch_cpu, .data = &recover };
+ 	static atomic_t mca_count;
+ 	static cpumask_t mca_cpu;
+ 
+@@ -1225,9 +1281,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+ 
+ 	previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
+ 
+-	if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0)
+-			== NOTIFY_STOP)
+-		ia64_mca_spin(__func__);
++	NOTIFY_MCA(DIE_MCA_MONARCH_ENTER, regs, (long)&nd, 1);
+ 
+ 	ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA;
+ 	if (sos->monarch) {
+@@ -1241,13 +1295,12 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+ 		 * does not work.
+ 		 */
+ 		ia64_mca_wakeup_all();
+-		if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0)
+-				== NOTIFY_STOP)
+-			ia64_mca_spin(__func__);
+ 	} else {
+ 		while (cpu_isset(cpu, mca_cpu))
+ 			cpu_relax();	/* spin until monarch wakes us */
+-        }
++	}
++
++	NOTIFY_MCA(DIE_MCA_MONARCH_PROCESS, regs, (long)&nd, 1);
+ 
+ 	/* Get the MCA error record and log it */
+ 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
+@@ -1266,15 +1319,14 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+ 	} else {
+ 		/* Dump buffered message to console */
+ 		ia64_mlogbuf_finish(1);
+-#ifdef CONFIG_KEXEC
+-		atomic_set(&kdump_in_progress, 1);
+-		monarch_cpu = -1;
+-#endif
+ 	}
+-	if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
+-			== NOTIFY_STOP)
+-		ia64_mca_spin(__func__);
+ 
++	if (__get_cpu_var(ia64_mca_tr_reload)) {
++		mca_insert_tr(0x1); /*Reload dynamic itrs*/
++		mca_insert_tr(0x2); /*Reload dynamic itrs*/
++	}
++
++	NOTIFY_MCA(DIE_MCA_MONARCH_LEAVE, regs, (long)&nd, 1);
+ 
+ 	if (atomic_dec_return(&mca_count) > 0) {
+ 		int i;
+@@ -1595,7 +1647,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+ 	struct ia64_mca_notify_die nd =
+ 		{ .sos = sos, .monarch_cpu = &monarch_cpu };
+ 
+-	(void) notify_die(DIE_INIT_ENTER, "INIT", regs, (long)&nd, 0, 0);
++	NOTIFY_INIT(DIE_INIT_ENTER, regs, (long)&nd, 0);
+ 
+ 	mprintk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
+ 		sos->proc_state_param, cpu, sos->monarch);
+@@ -1632,17 +1684,15 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+ 		ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
+ 		while (monarch_cpu == -1)
+ 		       cpu_relax();	/* spin until monarch enters */
+-		if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, (long)&nd, 0, 0)
+-				== NOTIFY_STOP)
+-			ia64_mca_spin(__func__);
+-		if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, (long)&nd, 0, 0)
+-				== NOTIFY_STOP)
+-			ia64_mca_spin(__func__);
++
++		NOTIFY_INIT(DIE_INIT_SLAVE_ENTER, regs, (long)&nd, 1);
++		NOTIFY_INIT(DIE_INIT_SLAVE_PROCESS, regs, (long)&nd, 1);
++
+ 		while (monarch_cpu != -1)
+ 		       cpu_relax();	/* spin until monarch leaves */
+-		if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, (long)&nd, 0, 0)
+-				== NOTIFY_STOP)
+-			ia64_mca_spin(__func__);
++
++		NOTIFY_INIT(DIE_INIT_SLAVE_LEAVE, regs, (long)&nd, 1);
++
+ 		mprintk("Slave on cpu %d returning to normal service.\n", cpu);
+ 		set_curr_task(cpu, previous_current);
+ 		ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+@@ -1651,9 +1701,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+ 	}
+ 
+ 	monarch_cpu = cpu;
+-	if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, (long)&nd, 0, 0)
+-			== NOTIFY_STOP)
+-		ia64_mca_spin(__func__);
++	NOTIFY_INIT(DIE_INIT_MONARCH_ENTER, regs, (long)&nd, 1);
+ 
+ 	/*
+ 	 * Wait for a bit.  On some machines (e.g., HP's zx2000 and zx6000, INIT can be
+@@ -1668,12 +1716,9 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+ 	 * to default_monarch_init_process() above and just print all the
+ 	 * tasks.
+ 	 */
+-	if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, (long)&nd, 0, 0)
+-			== NOTIFY_STOP)
+-		ia64_mca_spin(__func__);
+-	if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, (long)&nd, 0, 0)
+-			== NOTIFY_STOP)
+-		ia64_mca_spin(__func__);
++	NOTIFY_INIT(DIE_INIT_MONARCH_PROCESS, regs, (long)&nd, 1);
++	NOTIFY_INIT(DIE_INIT_MONARCH_LEAVE, regs, (long)&nd, 1);
++
+ 	mprintk("\nINIT dump complete.  Monarch on cpu %d returning to normal service.\n", cpu);
+ 	atomic_dec(&monarchs);
+ 	set_curr_task(cpu, previous_current);
+@@ -1905,7 +1950,7 @@ ia64_mca_init(void)
+ 			printk(KERN_INFO "Increasing MCA rendezvous timeout from "
+ 				"%ld to %ld milliseconds\n", timeout, isrv.v0);
+ 			timeout = isrv.v0;
+-			(void) notify_die(DIE_MCA_NEW_TIMEOUT, "MCA", NULL, timeout, 0, 0);
++			NOTIFY_MCA(DIE_MCA_NEW_TIMEOUT, NULL, timeout, 0);
+ 			continue;
+ 		}
+ 		printk(KERN_ERR "Failed to register rendezvous interrupt "
+diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
+index 8bc7d25..a06d465 100644
+--- a/arch/ia64/kernel/mca_asm.S
++++ b/arch/ia64/kernel/mca_asm.S
+@@ -219,8 +219,13 @@ ia64_reload_tr:
+ 	mov r20=IA64_TR_CURRENT_STACK
+ 	;;
+ 	itr.d dtr[r20]=r16
++	GET_THIS_PADDR(r2, ia64_mca_tr_reload)
++	mov r18 = 1
+ 	;;
+ 	srlz.d
++	;;
++	st8 [r2] =r18
++	;;
+ 
+ done_tlb_purge_and_reload:
+ 
+diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
+index c9ac8ba..7c548ac 100644
+--- a/arch/ia64/kernel/minstate.h
++++ b/arch/ia64/kernel/minstate.h
+@@ -3,6 +3,18 @@
+ 
+ #include "entry.h"
+ 
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++/* read ar.itc in advance, and use it before leaving bank 0 */
++#define ACCOUNT_GET_STAMP				\
++(pUStk) mov.m r20=ar.itc;
++#define ACCOUNT_SYS_ENTER				\
++(pUStk) br.call.spnt rp=account_sys_enter		\
++	;;
++#else
++#define ACCOUNT_GET_STAMP
++#define ACCOUNT_SYS_ENTER
++#endif
++
+ /*
+  * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
+  * the minimum state necessary that allows us to turn psr.ic back
+@@ -122,11 +134,13 @@
+ 	;;											\
+ .mem.offset 0,0; st8.spill [r16]=r2,16;								\
+ .mem.offset 8,0; st8.spill [r17]=r3,16;								\
++	ACCOUNT_GET_STAMP									\
+ 	adds r2=IA64_PT_REGS_R16_OFFSET,r1;							\
+ 	;;											\
+ 	EXTRA;											\
+ 	movl r1=__gp;		/* establish kernel global pointer */				\
+ 	;;											\
++	ACCOUNT_SYS_ENTER									\
+ 	bsw.1;			/* switch back to bank 1 (must be last in insn group) */	\
+ 	;;
+ 
+diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c
+index a78b45f..c93420c 100644
+--- a/arch/ia64/kernel/numa.c
++++ b/arch/ia64/kernel/numa.c
+@@ -73,7 +73,7 @@ void __init build_cpu_to_node_map(void)
+ 	for(node=0; node < MAX_NUMNODES; node++)
+ 		cpus_clear(node_to_cpu_mask[node]);
+ 
+-	for(cpu = 0; cpu < NR_CPUS; ++cpu) {
++	for_each_possible_early_cpu(cpu) {
+ 		node = -1;
+ 		for (i = 0; i < NR_CPUS; ++i)
+ 			if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) {
+diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
+index 2cb9425..e0dca87 100644
+--- a/arch/ia64/kernel/patch.c
++++ b/arch/ia64/kernel/patch.c
+@@ -135,10 +135,10 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end)
+ 
+ 	while (offp < (s32 *) end) {
+ 		wp = (u64 *) ia64_imva((char *) offp + *offp);
+-		wp[0] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */
+-		wp[1] = 0x0004000000000200UL;
+-		wp[2] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
+-		wp[3] = 0x0084006880000200UL;
++		wp[0] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
++		wp[1] = 0x0084006880000200UL;
++		wp[2] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */
++		wp[3] = 0x0004000000000200UL;
+ 		ia64_fc(wp); ia64_fc(wp + 2);
+ 		++offp;
+ 	}
+diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
+index a2aabfd..c8e4037 100644
+--- a/arch/ia64/kernel/perfmon.c
++++ b/arch/ia64/kernel/perfmon.c
+@@ -4204,10 +4204,10 @@ pfm_check_task_exist(pfm_context_t *ctx)
+ 	do_each_thread (g, t) {
+ 		if (t->thread.pfm_context == ctx) {
+ 			ret = 0;
+-			break;
++			goto out;
+ 		}
+ 	} while_each_thread (g, t);
+-
++out:
+ 	read_unlock(&tasklist_lock);
+ 
+ 	DPRINT(("pfm_check_task_exist: ret=%d ctx=%p\n", ret, ctx));
+@@ -5511,7 +5511,7 @@ stop_monitoring:
+ }
+ 
+ static int
+-pfm_do_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
++pfm_do_interrupt_handler(void *arg, struct pt_regs *regs)
+ {
+ 	struct task_struct *task;
+ 	pfm_context_t *ctx;
+@@ -5591,7 +5591,7 @@ pfm_interrupt_handler(int irq, void *arg)
+ 
+ 		start_cycles = ia64_get_itc();
+ 
+-		ret = pfm_do_interrupt_handler(irq, arg, regs);
++		ret = pfm_do_interrupt_handler(arg, regs);
+ 
+ 		total_cycles = ia64_get_itc();
+ 
+diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
+index 49937a3..a5ea817 100644
+--- a/arch/ia64/kernel/process.c
++++ b/arch/ia64/kernel/process.c
+@@ -625,21 +625,6 @@ do_dump_fpu (struct unw_frame_info *info, void *arg)
+ 	do_dump_task_fpu(current, info, arg);
+ }
+ 
+-int
+-dump_task_regs(struct task_struct *task, elf_gregset_t *regs)
+-{
+-	struct unw_frame_info tcore_info;
+-
+-	if (current == task) {
+-		unw_init_running(do_copy_regs, regs);
+-	} else {
+-		memset(&tcore_info, 0, sizeof(tcore_info));
+-		unw_init_from_blocked_task(&tcore_info, task);
+-		do_copy_task_regs(task, &tcore_info, regs);
+-	}
+-	return 1;
+-}
+-
+ void
+ ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
+ {
+@@ -647,21 +632,6 @@ ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
+ }
+ 
+ int
+-dump_task_fpu (struct task_struct *task, elf_fpregset_t *dst)
+-{
+-	struct unw_frame_info tcore_info;
+-
+-	if (current == task) {
+-		unw_init_running(do_dump_fpu, dst);
+-	} else {
+-		memset(&tcore_info, 0, sizeof(tcore_info));
+-		unw_init_from_blocked_task(&tcore_info, task);
+-		do_dump_task_fpu(task, &tcore_info, dst);
+-	}
+-	return 1;
+-}
+-
+-int
+ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
+ {
+ 	unw_init_running(do_dump_fpu, dst);
+diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
+index ab784ec..2a9943b 100644
+--- a/arch/ia64/kernel/ptrace.c
++++ b/arch/ia64/kernel/ptrace.c
+@@ -3,6 +3,9 @@
+  *
+  * Copyright (C) 1999-2005 Hewlett-Packard Co
+  *	David Mosberger-Tang <davidm at hpl.hp.com>
++ * Copyright (C) 2006 Intel Co
++ *  2006-08-12	- IA64 Native Utrace implementation support added by
++ *	Anil S Keshavamurthy <anil.s.keshavamurthy at intel.com>
+  *
+  * Derived from the x86 and Alpha versions.
+  */
+@@ -17,6 +20,8 @@
+ #include <linux/security.h>
+ #include <linux/audit.h>
+ #include <linux/signal.h>
++#include <linux/regset.h>
++#include <linux/elf.h>
+ 
+ #include <asm/pgtable.h>
+ #include <asm/processor.h>
+@@ -740,25 +745,6 @@ ia64_sync_fph (struct task_struct *task)
+ 	psr->dfh = 1;
+ }
+ 
+-static int
+-access_fr (struct unw_frame_info *info, int regnum, int hi,
+-	   unsigned long *data, int write_access)
+-{
+-	struct ia64_fpreg fpval;
+-	int ret;
+-
+-	ret = unw_get_fr(info, regnum, &fpval);
+-	if (ret < 0)
+-		return ret;
+-
+-	if (write_access) {
+-		fpval.u.bits[hi] = *data;
+-		ret = unw_set_fr(info, regnum, fpval);
+-	} else
+-		*data = fpval.u.bits[hi];
+-	return ret;
+-}
+-
+ /*
+  * Change the machine-state of CHILD such that it will return via the normal
+  * kernel exit-path, rather than the syscall-exit path.
+@@ -860,309 +846,7 @@ access_nat_bits (struct task_struct *child, struct pt_regs *pt,
+ 
+ static int
+ access_uarea (struct task_struct *child, unsigned long addr,
+-	      unsigned long *data, int write_access)
+-{
+-	unsigned long *ptr, regnum, urbs_end, cfm;
+-	struct switch_stack *sw;
+-	struct pt_regs *pt;
+-#	define pt_reg_addr(pt, reg)	((void *)			    \
+-					 ((unsigned long) (pt)		    \
+-					  + offsetof(struct pt_regs, reg)))
+-
+-
+-	pt = task_pt_regs(child);
+-	sw = (struct switch_stack *) (child->thread.ksp + 16);
+-
+-	if ((addr & 0x7) != 0) {
+-		dprintk("ptrace: unaligned register address 0x%lx\n", addr);
+-		return -1;
+-	}
+-
+-	if (addr < PT_F127 + 16) {
+-		/* accessing fph */
+-		if (write_access)
+-			ia64_sync_fph(child);
+-		else
+-			ia64_flush_fph(child);
+-		ptr = (unsigned long *)
+-			((unsigned long) &child->thread.fph + addr);
+-	} else if ((addr >= PT_F10) && (addr < PT_F11 + 16)) {
+-		/* scratch registers untouched by kernel (saved in pt_regs) */
+-		ptr = pt_reg_addr(pt, f10) + (addr - PT_F10);
+-	} else if (addr >= PT_F12 && addr < PT_F15 + 16) {
+-		/*
+-		 * Scratch registers untouched by kernel (saved in
+-		 * switch_stack).
+-		 */
+-		ptr = (unsigned long *) ((long) sw
+-					 + (addr - PT_NAT_BITS - 32));
+-	} else if (addr < PT_AR_LC + 8) {
+-		/* preserved state: */
+-		struct unw_frame_info info;
+-		char nat = 0;
+-		int ret;
+-
+-		unw_init_from_blocked_task(&info, child);
+-		if (unw_unwind_to_user(&info) < 0)
+-			return -1;
+-
+-		switch (addr) {
+-		      case PT_NAT_BITS:
+-			return access_nat_bits(child, pt, &info,
+-					       data, write_access);
+-
+-		      case PT_R4: case PT_R5: case PT_R6: case PT_R7:
+-			if (write_access) {
+-				/* read NaT bit first: */
+-				unsigned long dummy;
+-
+-				ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4,
+-						 &dummy, &nat);
+-				if (ret < 0)
+-					return ret;
+-			}
+-			return unw_access_gr(&info, (addr - PT_R4)/8 + 4, data,
+-					     &nat, write_access);
+-
+-		      case PT_B1: case PT_B2: case PT_B3:
+-		      case PT_B4: case PT_B5:
+-			return unw_access_br(&info, (addr - PT_B1)/8 + 1, data,
+-					     write_access);
+-
+-		      case PT_AR_EC:
+-			return unw_access_ar(&info, UNW_AR_EC, data,
+-					     write_access);
+-
+-		      case PT_AR_LC:
+-			return unw_access_ar(&info, UNW_AR_LC, data,
+-					     write_access);
+-
+-		      default:
+-			if (addr >= PT_F2 && addr < PT_F5 + 16)
+-				return access_fr(&info, (addr - PT_F2)/16 + 2,
+-						 (addr & 8) != 0, data,
+-						 write_access);
+-			else if (addr >= PT_F16 && addr < PT_F31 + 16)
+-				return access_fr(&info,
+-						 (addr - PT_F16)/16 + 16,
+-						 (addr & 8) != 0,
+-						 data, write_access);
+-			else {
+-				dprintk("ptrace: rejecting access to register "
+-					"address 0x%lx\n", addr);
+-				return -1;
+-			}
+-		}
+-	} else if (addr < PT_F9+16) {
+-		/* scratch state */
+-		switch (addr) {
+-		      case PT_AR_BSP:
+-			/*
+-			 * By convention, we use PT_AR_BSP to refer to
+-			 * the end of the user-level backing store.
+-			 * Use ia64_rse_skip_regs(PT_AR_BSP, -CFM.sof)
+-			 * to get the real value of ar.bsp at the time
+-			 * the kernel was entered.
+-			 *
+-			 * Furthermore, when changing the contents of
+-			 * PT_AR_BSP (or PT_CFM) while the task is
+-			 * blocked in a system call, convert the state
+-			 * so that the non-system-call exit
+-			 * path is used.  This ensures that the proper
+-			 * state will be picked up when resuming
+-			 * execution.  However, it *also* means that
+-			 * once we write PT_AR_BSP/PT_CFM, it won't be
+-			 * possible to modify the syscall arguments of
+-			 * the pending system call any longer.  This
+-			 * shouldn't be an issue because modifying
+-			 * PT_AR_BSP/PT_CFM generally implies that
+-			 * we're either abandoning the pending system
+-			 * call or that we defer it's re-execution
+-			 * (e.g., due to GDB doing an inferior
+-			 * function call).
+-			 */
+-			urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);
+-			if (write_access) {
+-				if (*data != urbs_end) {
+-					if (in_syscall(pt))
+-						convert_to_non_syscall(child,
+-								       pt,
+-								       cfm);
+-					/*
+-					 * Simulate user-level write
+-					 * of ar.bsp:
+-					 */
+-					pt->loadrs = 0;
+-					pt->ar_bspstore = *data;
+-				}
+-			} else
+-				*data = urbs_end;
+-			return 0;
+-
+-		      case PT_CFM:
+-			urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);
+-			if (write_access) {
+-				if (((cfm ^ *data) & PFM_MASK) != 0) {
+-					if (in_syscall(pt))
+-						convert_to_non_syscall(child,
+-								       pt,
+-								       cfm);
+-					pt->cr_ifs = ((pt->cr_ifs & ~PFM_MASK)
+-						      | (*data & PFM_MASK));
+-				}
+-			} else
+-				*data = cfm;
+-			return 0;
+-
+-		      case PT_CR_IPSR:
+-			if (write_access) {
+-				unsigned long tmp = *data;
+-				/* psr.ri==3 is a reserved value: SDM 2:25 */
+-				if ((tmp & IA64_PSR_RI) == IA64_PSR_RI)
+-					tmp &= ~IA64_PSR_RI;
+-				pt->cr_ipsr = ((tmp & IPSR_MASK)
+-					       | (pt->cr_ipsr & ~IPSR_MASK));
+-			} else
+-				*data = (pt->cr_ipsr & IPSR_MASK);
+-			return 0;
+-
+-		      case PT_AR_RSC:
+-			if (write_access)
+-				pt->ar_rsc = *data | (3 << 2); /* force PL3 */
+-			else
+-				*data = pt->ar_rsc;
+-			return 0;
+-
+-		      case PT_AR_RNAT:
+-			ptr = pt_reg_addr(pt, ar_rnat);
+-			break;
+-		      case PT_R1:
+-			ptr = pt_reg_addr(pt, r1);
+-			break;
+-		      case PT_R2:  case PT_R3:
+-			ptr = pt_reg_addr(pt, r2) + (addr - PT_R2);
+-			break;
+-		      case PT_R8:  case PT_R9:  case PT_R10: case PT_R11:
+-			ptr = pt_reg_addr(pt, r8) + (addr - PT_R8);
+-			break;
+-		      case PT_R12: case PT_R13:
+-			ptr = pt_reg_addr(pt, r12) + (addr - PT_R12);
+-			break;
+-		      case PT_R14:
+-			ptr = pt_reg_addr(pt, r14);
+-			break;
+-		      case PT_R15:
+-			ptr = pt_reg_addr(pt, r15);
+-			break;
+-		      case PT_R16: case PT_R17: case PT_R18: case PT_R19:
+-		      case PT_R20: case PT_R21: case PT_R22: case PT_R23:
+-		      case PT_R24: case PT_R25: case PT_R26: case PT_R27:
+-		      case PT_R28: case PT_R29: case PT_R30: case PT_R31:
+-			ptr = pt_reg_addr(pt, r16) + (addr - PT_R16);
+-			break;
+-		      case PT_B0:
+-			ptr = pt_reg_addr(pt, b0);
+-			break;
+-		      case PT_B6:
+-			ptr = pt_reg_addr(pt, b6);
+-			break;
+-		      case PT_B7:
+-			ptr = pt_reg_addr(pt, b7);
+-			break;
+-		      case PT_F6:  case PT_F6+8: case PT_F7: case PT_F7+8:
+-		      case PT_F8:  case PT_F8+8: case PT_F9: case PT_F9+8:
+-			ptr = pt_reg_addr(pt, f6) + (addr - PT_F6);
+-			break;
+-		      case PT_AR_BSPSTORE:
+-			ptr = pt_reg_addr(pt, ar_bspstore);
+-			break;
+-		      case PT_AR_UNAT:
+-			ptr = pt_reg_addr(pt, ar_unat);
+-			break;
+-		      case PT_AR_PFS:
+-			ptr = pt_reg_addr(pt, ar_pfs);
+-			break;
+-		      case PT_AR_CCV:
+-			ptr = pt_reg_addr(pt, ar_ccv);
+-			break;
+-		      case PT_AR_FPSR:
+-			ptr = pt_reg_addr(pt, ar_fpsr);
+-			break;
+-		      case PT_CR_IIP:
+-			ptr = pt_reg_addr(pt, cr_iip);
+-			break;
+-		      case PT_PR:
+-			ptr = pt_reg_addr(pt, pr);
+-			break;
+-			/* scratch register */
+-
+-		      default:
+-			/* disallow accessing anything else... */
+-			dprintk("ptrace: rejecting access to register "
+-				"address 0x%lx\n", addr);
+-			return -1;
+-		}
+-	} else if (addr <= PT_AR_SSD) {
+-		ptr = pt_reg_addr(pt, ar_csd) + (addr - PT_AR_CSD);
+-	} else {
+-		/* access debug registers */
+-
+-		if (addr >= PT_IBR) {
+-			regnum = (addr - PT_IBR) >> 3;
+-			ptr = &child->thread.ibr[0];
+-		} else {
+-			regnum = (addr - PT_DBR) >> 3;
+-			ptr = &child->thread.dbr[0];
+-		}
+-
+-		if (regnum >= 8) {
+-			dprintk("ptrace: rejecting access to register "
+-				"address 0x%lx\n", addr);
+-			return -1;
+-		}
+-#ifdef CONFIG_PERFMON
+-		/*
+-		 * Check if debug registers are used by perfmon. This
+-		 * test must be done once we know that we can do the
+-		 * operation, i.e. the arguments are all valid, but
+-		 * before we start modifying the state.
+-		 *
+-		 * Perfmon needs to keep a count of how many processes
+-		 * are trying to modify the debug registers for system
+-		 * wide monitoring sessions.
+-		 *
+-		 * We also include read access here, because they may
+-		 * cause the PMU-installed debug register state
+-		 * (dbr[], ibr[]) to be reset. The two arrays are also
+-		 * used by perfmon, but we do not use
+-		 * IA64_THREAD_DBG_VALID. The registers are restored
+-		 * by the PMU context switch code.
+-		 */
+-		if (pfm_use_debug_registers(child)) return -1;
+-#endif
+-
+-		if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
+-			child->thread.flags |= IA64_THREAD_DBG_VALID;
+-			memset(child->thread.dbr, 0,
+-			       sizeof(child->thread.dbr));
+-			memset(child->thread.ibr, 0,
+-			       sizeof(child->thread.ibr));
+-		}
+-
+-		ptr += regnum;
+-
+-		if ((regnum & 1) && write_access) {
+-			/* don't let the user set kernel-level breakpoints: */
+-			*ptr = *data & ~(7UL << 56);
+-			return 0;
+-		}
+-	}
+-	if (write_access)
+-		*ptr = *data;
+-	else
+-		*data = *ptr;
+-	return 0;
+-}
++	      unsigned long *data, int write_access);
+ 
+ static long
+ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
+@@ -1626,3 +1310,892 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
+ 	if (test_thread_flag(TIF_RESTORE_RSE))
+ 		ia64_sync_krbs();
+ }
++
++/* Utrace implementation starts here */
++struct regset_get {
++	void *kbuf;
++	void __user *ubuf;
++};
++
++struct regset_set {
++	const void *kbuf;
++	const void __user *ubuf;
++};
++
++struct regset_getset {
++	struct task_struct *target;
++	const struct user_regset *regset;
++	union {
++		struct regset_get get;
++		struct regset_set set;
++	} u;
++	unsigned int pos;
++	unsigned int count;
++	int ret;
++};
++
++static int
++access_elf_gpreg(struct task_struct *target, struct unw_frame_info *info,
++		unsigned long addr, unsigned long *data, int write_access)
++{
++	struct pt_regs *pt;
++	unsigned long *ptr = NULL;
++	int ret;
++	char nat = 0;
++
++	pt = task_pt_regs(target);
++	switch (addr) {
++	case ELF_GR_OFFSET(1):
++		ptr = &pt->r1;
++		break;
++	case ELF_GR_OFFSET(2):
++	case ELF_GR_OFFSET(3):
++		ptr = (void *)&pt->r2 + (addr - ELF_GR_OFFSET(2));
++		break;
++	case ELF_GR_OFFSET(4) ... ELF_GR_OFFSET(7):
++		if (write_access) {
++			/* read NaT bit first: */
++			unsigned long dummy;
++
++			ret = unw_get_gr(info, addr/8, &dummy, &nat);
++			if (ret < 0)
++				return ret;
++		}
++		return unw_access_gr(info, addr/8, data, &nat, write_access);
++	case ELF_GR_OFFSET(8) ... ELF_GR_OFFSET(11):
++		ptr = (void *)&pt->r8 + addr - ELF_GR_OFFSET(8);
++		break;
++	case ELF_GR_OFFSET(12):
++	case ELF_GR_OFFSET(13):
++		ptr = (void *)&pt->r12 + addr - ELF_GR_OFFSET(12);
++		break;
++	case ELF_GR_OFFSET(14):
++		ptr = &pt->r14;
++		break;
++	case ELF_GR_OFFSET(15):
++		ptr = &pt->r15;
++	}
++	if (write_access)
++		*ptr = *data;
++	else
++		*data = *ptr;
++	return 0;
++}
++
++static int
++access_elf_breg(struct task_struct *target, struct unw_frame_info *info,
++		unsigned long addr, unsigned long *data, int write_access)
++{
++	struct pt_regs *pt;
++	unsigned long *ptr = NULL;
++
++	pt = task_pt_regs(target);
++	switch (addr) {
++	case ELF_BR_OFFSET(0):
++		ptr = &pt->b0;
++		break;
++	case ELF_BR_OFFSET(1) ... ELF_BR_OFFSET(5):
++		return unw_access_br(info, (addr - ELF_BR_OFFSET(0))/8,
++				     data, write_access);
++	case ELF_BR_OFFSET(6):
++		ptr = &pt->b6;
++		break;
++	case ELF_BR_OFFSET(7):
++		ptr = &pt->b7;
++	}
++	if (write_access)
++		*ptr = *data;
++	else
++		*data = *ptr;
++	return 0;
++}
++
++static int
++access_elf_areg(struct task_struct *target, struct unw_frame_info *info,
++		unsigned long addr, unsigned long *data, int write_access)
++{
++	struct pt_regs *pt;
++	unsigned long cfm, urbs_end;
++	unsigned long *ptr = NULL;
++
++	pt = task_pt_regs(target);
++	if (addr >= ELF_AR_RSC_OFFSET && addr <= ELF_AR_SSD_OFFSET) {
++		switch (addr) {
++		case ELF_AR_RSC_OFFSET:
++			/* force PL3 */
++			if (write_access)
++				pt->ar_rsc = *data | (3 << 2);
++			else
++				*data = pt->ar_rsc;
++			return 0;
++		case ELF_AR_BSP_OFFSET:
++			/*
++			 * By convention, we use PT_AR_BSP to refer to
++			 * the end of the user-level backing store.
++			 * Use ia64_rse_skip_regs(PT_AR_BSP, -CFM.sof)
++			 * to get the real value of ar.bsp at the time
++			 * the kernel was entered.
++			 *
++			 * Furthermore, when changing the contents of
++			 * PT_AR_BSP (or PT_CFM) while the task is
++			 * blocked in a system call, convert the state
++			 * so that the non-system-call exit
++			 * path is used.  This ensures that the proper
++			 * state will be picked up when resuming
++			 * execution.  However, it *also* means that
++			 * once we write PT_AR_BSP/PT_CFM, it won't be
++			 * possible to modify the syscall arguments of
++			 * the pending system call any longer.  This
++			 * shouldn't be an issue because modifying
++			 * PT_AR_BSP/PT_CFM generally implies that
++			 * we're either abandoning the pending system
++			 * call or that we defer it's re-execution
++			 * (e.g., due to GDB doing an inferior
++			 * function call).
++			 */
++			urbs_end = ia64_get_user_rbs_end(target, pt, &cfm);
++			if (write_access) {
++				if (*data != urbs_end) {
++					if (in_syscall(pt))
++						convert_to_non_syscall(target,
++								       pt,
++								       cfm);
++					/*
++					 * Simulate user-level write
++					 * of ar.bsp:
++					 */
++					pt->loadrs = 0;
++					pt->ar_bspstore = *data;
++				}
++			} else
++				*data = urbs_end;
++			return 0;
++		case ELF_AR_BSPSTORE_OFFSET:
++			ptr = &pt->ar_bspstore;
++			break;
++		case ELF_AR_RNAT_OFFSET:
++			ptr = &pt->ar_rnat;
++			break;
++		case ELF_AR_CCV_OFFSET:
++			ptr = &pt->ar_ccv;
++			break;
++		case ELF_AR_UNAT_OFFSET:
++			ptr = &pt->ar_unat;
++			break;
++		case ELF_AR_FPSR_OFFSET:
++			ptr = &pt->ar_fpsr;
++			break;
++		case ELF_AR_PFS_OFFSET:
++			ptr = &pt->ar_pfs;
++			break;
++		case ELF_AR_LC_OFFSET:
++			return unw_access_ar(info, UNW_AR_LC, data,
++					     write_access);
++		case ELF_AR_EC_OFFSET:
++			return unw_access_ar(info, UNW_AR_EC, data,
++					     write_access);
++		case ELF_AR_CSD_OFFSET:
++			ptr = &pt->ar_csd;
++			break;
++		case ELF_AR_SSD_OFFSET:
++			ptr = &pt->ar_ssd;
++		}
++	} else if (addr >= ELF_CR_IIP_OFFSET && addr <= ELF_CR_IPSR_OFFSET) {
++		switch (addr) {
++		case ELF_CR_IIP_OFFSET:
++			ptr = &pt->cr_iip;
++			break;
++		case ELF_CFM_OFFSET:
++			urbs_end = ia64_get_user_rbs_end(target, pt, &cfm);
++			if (write_access) {
++				if (((cfm ^ *data) & PFM_MASK) != 0) {
++					if (in_syscall(pt))
++						convert_to_non_syscall(target,
++								       pt,
++								       cfm);
++					pt->cr_ifs = ((pt->cr_ifs & ~PFM_MASK)
++						      | (*data & PFM_MASK));
++				}
++			} else
++				*data = cfm;
++			return 0;
++		case ELF_CR_IPSR_OFFSET:
++			if (write_access) {
++				unsigned long tmp = *data;
++				/* psr.ri==3 is a reserved value: SDM 2:25 */
++				if ((tmp & IA64_PSR_RI) == IA64_PSR_RI)
++					tmp &= ~IA64_PSR_RI;
++				pt->cr_ipsr = ((tmp & IPSR_MASK)
++					       | (pt->cr_ipsr & ~IPSR_MASK));
++			} else
++				*data = (pt->cr_ipsr & IPSR_MASK);
++			return 0;
++		}
++	} else if (addr == ELF_NAT_OFFSET)
++		return access_nat_bits(target, pt, info,
++				       data, write_access);
++	else if (addr == ELF_PR_OFFSET)
++		ptr = &pt->pr;
++	else
++		return -1;
++
++	if (write_access)
++		*ptr = *data;
++	else
++		*data = *ptr;
++
++	return 0;
++}
++
++static int
++access_elf_reg(struct task_struct *target, struct unw_frame_info *info,
++		unsigned long addr, unsigned long *data, int write_access)
++{
++	if (addr >= ELF_GR_OFFSET(1) && addr <= ELF_GR_OFFSET(15))
++		return access_elf_gpreg(target, info, addr, data, write_access);
++	else if (addr >= ELF_BR_OFFSET(0) && addr <= ELF_BR_OFFSET(7))
++		return access_elf_breg(target, info, addr, data, write_access);
++	else
++		return access_elf_areg(target, info, addr, data, write_access);
++}
++
++void do_gpregs_get(struct unw_frame_info *info, void *arg)
++{
++	struct pt_regs *pt;
++	struct regset_getset *dst = arg;
++	elf_greg_t tmp[16];
++	unsigned int i, index, min_copy;
++
++	if (unw_unwind_to_user(info) < 0)
++		return;
++
++	/*
++	 * coredump format:
++	 *      r0-r31
++	 *      NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
++	 *      predicate registers (p0-p63)
++	 *      b0-b7
++	 *      ip cfm user-mask
++	 *      ar.rsc ar.bsp ar.bspstore ar.rnat
++	 *      ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
++	 */
++
++
++	/* Skip r0 */
++	if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(1)) {
++		dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count,
++						      &dst->u.get.kbuf,
++						      &dst->u.get.ubuf,
++						      0, ELF_GR_OFFSET(1));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++
++	/* gr1 - gr15 */
++	if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(16)) {
++		index = (dst->pos - ELF_GR_OFFSET(1)) / sizeof(elf_greg_t);
++		min_copy = ELF_GR_OFFSET(16) > (dst->pos + dst->count) ?
++			 (dst->pos + dst->count) : ELF_GR_OFFSET(16);
++		for (i = dst->pos; i < min_copy; i += sizeof(elf_greg_t),
++				index++)
++			if (access_elf_reg(dst->target, info, i,
++						&tmp[index], 0) < 0) {
++				dst->ret = -EIO;
++				return;
++			}
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
++				ELF_GR_OFFSET(1), ELF_GR_OFFSET(16));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++
++	/* r16-r31 */
++	if (dst->count > 0 && dst->pos < ELF_NAT_OFFSET) {
++		pt = task_pt_regs(dst->target);
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf, &pt->r16,
++				ELF_GR_OFFSET(16), ELF_NAT_OFFSET);
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++
++	/* nat, pr, b0 - b7 */
++	if (dst->count > 0 && dst->pos < ELF_CR_IIP_OFFSET) {
++		index = (dst->pos - ELF_NAT_OFFSET) / sizeof(elf_greg_t);
++		min_copy = ELF_CR_IIP_OFFSET > (dst->pos + dst->count) ?
++			 (dst->pos + dst->count) : ELF_CR_IIP_OFFSET;
++		for (i = dst->pos; i < min_copy; i += sizeof(elf_greg_t),
++				index++)
++			if (access_elf_reg(dst->target, info, i,
++						&tmp[index], 0) < 0) {
++				dst->ret = -EIO;
++				return;
++			}
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
++				ELF_NAT_OFFSET, ELF_CR_IIP_OFFSET);
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++
++	/* ip cfm psr ar.rsc ar.bsp ar.bspstore ar.rnat
++	 * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
++	 */
++	if (dst->count > 0 && dst->pos < (ELF_AR_END_OFFSET)) {
++		index = (dst->pos - ELF_CR_IIP_OFFSET) / sizeof(elf_greg_t);
++		min_copy = ELF_AR_END_OFFSET > (dst->pos + dst->count) ?
++			 (dst->pos + dst->count) : ELF_AR_END_OFFSET;
++		for (i = dst->pos; i < min_copy; i += sizeof(elf_greg_t),
++				index++)
++			if (access_elf_reg(dst->target, info, i,
++						&tmp[index], 0) < 0) {
++				dst->ret = -EIO;
++				return;
++			}
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
++				ELF_CR_IIP_OFFSET, ELF_AR_END_OFFSET);
++	}
++}
++
++void do_gpregs_set(struct unw_frame_info *info, void *arg)
++{
++	struct pt_regs *pt;
++	struct regset_getset *dst = arg;
++	elf_greg_t tmp[16];
++	unsigned int i, index;
++
++	if (unw_unwind_to_user(info) < 0)
++		return;
++
++	/* Skip r0 */
++	if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(1)) {
++		dst->ret = user_regset_copyin_ignore(&dst->pos, &dst->count,
++						       &dst->u.set.kbuf,
++						       &dst->u.set.ubuf,
++						       0, ELF_GR_OFFSET(1));
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++
++	/* gr1-gr15 */
++	if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(16)) {
++		i = dst->pos;
++		index = (dst->pos - ELF_GR_OFFSET(1)) / sizeof(elf_greg_t);
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
++				ELF_GR_OFFSET(1), ELF_GR_OFFSET(16));
++		if (dst->ret)
++			return;
++		for ( ; i < dst->pos; i += sizeof(elf_greg_t), index++)
++			if (access_elf_reg(dst->target, info, i,
++						&tmp[index], 1) < 0) {
++				dst->ret = -EIO;
++				return;
++			}
++		if (dst->count == 0)
++			return;
++	}
++
++	/* gr16-gr31 */
++	if (dst->count > 0 && dst->pos < ELF_NAT_OFFSET) {
++		pt = task_pt_regs(dst->target);
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf, &pt->r16,
++				ELF_GR_OFFSET(16), ELF_NAT_OFFSET);
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++
++	/* nat, pr, b0 - b7 */
++	if (dst->count > 0 && dst->pos < ELF_CR_IIP_OFFSET) {
++		i = dst->pos;
++		index = (dst->pos - ELF_NAT_OFFSET) / sizeof(elf_greg_t);
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
++				ELF_NAT_OFFSET, ELF_CR_IIP_OFFSET);
++		if (dst->ret)
++			return;
++		for (; i < dst->pos; i += sizeof(elf_greg_t), index++)
++			if (access_elf_reg(dst->target, info, i,
++						&tmp[index], 1) < 0) {
++				dst->ret = -EIO;
++				return;
++			}
++		if (dst->count == 0)
++			return;
++	}
++
++	/* ip cfm psr ar.rsc ar.bsp ar.bspstore ar.rnat
++	 * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
++	 */
++	if (dst->count > 0 && dst->pos < (ELF_AR_END_OFFSET)) {
++		i = dst->pos;
++		index = (dst->pos - ELF_CR_IIP_OFFSET) / sizeof(elf_greg_t);
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
++				ELF_CR_IIP_OFFSET, ELF_AR_END_OFFSET);
++		if (dst->ret)
++			return;
++		for ( ; i < dst->pos; i += sizeof(elf_greg_t), index++)
++			if (access_elf_reg(dst->target, info, i,
++						&tmp[index], 1) < 0) {
++				dst->ret = -EIO;
++				return;
++			}
++	}
++}
++
++#define ELF_FP_OFFSET(i)	(i * sizeof(elf_fpreg_t))
++
++void do_fpregs_get(struct unw_frame_info *info, void *arg)
++{
++	struct regset_getset *dst = arg;
++	struct task_struct *task = dst->target;
++	elf_fpreg_t tmp[30];
++	int index, min_copy, i;
++
++	if (unw_unwind_to_user(info) < 0)
++		return;
++
++	/* Skip pos 0 and 1 */
++	if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) {
++		dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count,
++						      &dst->u.get.kbuf,
++						      &dst->u.get.ubuf,
++						      0, ELF_FP_OFFSET(2));
++		if (dst->count == 0 || dst->ret)
++			return;
++	}
++
++	/* fr2-fr31 */
++	if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) {
++		index = (dst->pos - ELF_FP_OFFSET(2)) / sizeof(elf_fpreg_t);
++
++		min_copy = min(((unsigned int)ELF_FP_OFFSET(32)),
++				dst->pos + dst->count);
++		for (i = dst->pos; i < min_copy; i += sizeof(elf_fpreg_t),
++				index++)
++			if (unw_get_fr(info, i / sizeof(elf_fpreg_t),
++					 &tmp[index])) {
++				dst->ret = -EIO;
++				return;
++			}
++		dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
++				ELF_FP_OFFSET(2), ELF_FP_OFFSET(32));
++		if (dst->count == 0 || dst->ret)
++			return;
++	}
++
++	/* fph */
++	if (dst->count > 0) {
++		ia64_flush_fph(dst->target);
++		if (task->thread.flags & IA64_THREAD_FPH_VALID)
++			dst->ret = user_regset_copyout(
++				&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf,
++				&dst->target->thread.fph,
++				ELF_FP_OFFSET(32), -1);
++		else
++			/* Zero fill instead.  */
++			dst->ret = user_regset_copyout_zero(
++				&dst->pos, &dst->count,
++				&dst->u.get.kbuf, &dst->u.get.ubuf,
++				ELF_FP_OFFSET(32), -1);
++	}
++}
++
++void do_fpregs_set(struct unw_frame_info *info, void *arg)
++{
++	struct regset_getset *dst = arg;
++	elf_fpreg_t fpreg, tmp[30];
++	int index, start, end;
++
++	if (unw_unwind_to_user(info) < 0)
++		return;
++
++	/* Skip pos 0 and 1 */
++	if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) {
++		dst->ret = user_regset_copyin_ignore(&dst->pos, &dst->count,
++						       &dst->u.set.kbuf,
++						       &dst->u.set.ubuf,
++						       0, ELF_FP_OFFSET(2));
++		if (dst->count == 0 || dst->ret)
++			return;
++	}
++
++	/* fr2-fr31 */
++	if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) {
++		start = dst->pos;
++		end = min(((unsigned int)ELF_FP_OFFSET(32)),
++			 dst->pos + dst->count);
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++				&dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
++				ELF_FP_OFFSET(2), ELF_FP_OFFSET(32));
++		if (dst->ret)
++			return;
++
++		if (start & 0xF) { /* only write high part */
++			if (unw_get_fr(info, start / sizeof(elf_fpreg_t),
++					 &fpreg)) {
++				dst->ret = -EIO;
++				return;
++			}
++			tmp[start / sizeof(elf_fpreg_t) - 2].u.bits[0]
++				= fpreg.u.bits[0];
++			start &= ~0xFUL;
++		}
++		if (end & 0xF) { /* only write low part */
++			if (unw_get_fr(info, end / sizeof(elf_fpreg_t),
++					&fpreg)) {
++				dst->ret = -EIO;
++				return;
++			}
++			tmp[end / sizeof(elf_fpreg_t) - 2].u.bits[1]
++				= fpreg.u.bits[1];
++			end = (end + 0xF) & ~0xFUL;
++		}
++
++		for ( ;	start < end ; start += sizeof(elf_fpreg_t)) {
++			index = start / sizeof(elf_fpreg_t);
++			if (unw_set_fr(info, index, tmp[index - 2])) {
++				dst->ret = -EIO;
++				return;
++			}
++		}
++		if (dst->ret || dst->count == 0)
++			return;
++	}
++
++	/* fph */
++	if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(128)) {
++		ia64_sync_fph(dst->target);
++		dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++						&dst->u.set.kbuf,
++						&dst->u.set.ubuf,
++						&dst->target->thread.fph,
++						ELF_FP_OFFSET(32), -1);
++	}
++}
++
++static int
++do_regset_call(void (*call)(struct unw_frame_info *, void *),
++	       struct task_struct *target,
++	       const struct user_regset *regset,
++	       unsigned int pos, unsigned int count,
++	       const void *kbuf, const void __user *ubuf)
++{
++	struct regset_getset info = { .target = target, .regset = regset,
++				 .pos = pos, .count = count,
++				 .u.set = { .kbuf = kbuf, .ubuf = ubuf },
++				 .ret = 0 };
++
++	if (target == current)
++		unw_init_running(call, &info);
++	else {
++		struct unw_frame_info ufi;
++		memset(&ufi, 0, sizeof(ufi));
++		unw_init_from_blocked_task(&ufi, target);
++		(*call)(&ufi, &info);
++	}
++
++	return info.ret;
++}
++
++static int
++gpregs_get(struct task_struct *target,
++	   const struct user_regset *regset,
++	   unsigned int pos, unsigned int count,
++	   void *kbuf, void __user *ubuf)
++{
++	return do_regset_call(do_gpregs_get, target, regset, pos, count,
++		kbuf, ubuf);
++}
++
++static int gpregs_set(struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	return do_regset_call(do_gpregs_set, target, regset, pos, count,
++		kbuf, ubuf);
++}
++
++static void do_gpregs_writeback(struct unw_frame_info *info, void *arg)
++{
++	do_sync_rbs(info, ia64_sync_user_rbs);
++}
++
++/*
++ * This is called to write back the register backing store.
++ * ptrace does this before it stops, so that a tracer reading the user
++ * memory after the thread stops will get the current register data.
++ */
++static int
++gpregs_writeback(struct task_struct *target,
++		 const struct user_regset *regset,
++		 int now)
++{
++	if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE))
++		return 0;
++	tsk_set_notify_resume(target);
++	return do_regset_call(do_gpregs_writeback, target, regset, 0, 0,
++		NULL, NULL);
++}
++
++static int
++fpregs_active(struct task_struct *target, const struct user_regset *regset)
++{
++	return (target->thread.flags & IA64_THREAD_FPH_VALID) ? 128 : 32;
++}
++
++static int fpregs_get(struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		void *kbuf, void __user *ubuf)
++{
++	return do_regset_call(do_fpregs_get, target, regset, pos, count,
++		kbuf, ubuf);
++}
++
++static int fpregs_set(struct task_struct *target,
++		const struct user_regset *regset,
++		unsigned int pos, unsigned int count,
++		const void *kbuf, const void __user *ubuf)
++{
++	return do_regset_call(do_fpregs_set, target, regset, pos, count,
++		kbuf, ubuf);
++}
++
++static int
++access_uarea(struct task_struct *child, unsigned long addr,
++	      unsigned long *data, int write_access)
++{
++	unsigned int pos = -1; /* an invalid value */
++	int ret;
++	unsigned long *ptr, regnum;
++
++	if ((addr & 0x7) != 0) {
++		dprintk("ptrace: unaligned register address 0x%lx\n", addr);
++		return -1;
++	}
++	if ((addr >= PT_NAT_BITS + 8 && addr < PT_F2) ||
++		(addr >= PT_R7 + 8 && addr < PT_B1) ||
++		(addr >= PT_AR_LC + 8 && addr < PT_CR_IPSR) ||
++		(addr >= PT_AR_SSD + 8 && addr < PT_DBR)) {
++		dprintk("ptrace: rejecting access to register "
++					"address 0x%lx\n", addr);
++		return -1;
++	}
++
++	switch (addr) {
++	case PT_F32 ... (PT_F127 + 15):
++		pos = addr - PT_F32 + ELF_FP_OFFSET(32);
++		break;
++	case PT_F2 ... (PT_F5 + 15):
++		pos = addr - PT_F2 + ELF_FP_OFFSET(2);
++		break;
++	case PT_F10 ... (PT_F31 + 15):
++		pos = addr - PT_F10 + ELF_FP_OFFSET(10);
++		break;
++	case PT_F6 ... (PT_F9 + 15):
++		pos = addr - PT_F6 + ELF_FP_OFFSET(6);
++		break;
++	}
++
++	if (pos != -1) {
++		if (write_access)
++			ret = fpregs_set(child, NULL, pos,
++				sizeof(unsigned long), data, NULL);
++		else
++			ret = fpregs_get(child, NULL, pos,
++				sizeof(unsigned long), data, NULL);
++		if (ret != 0)
++			return -1;
++		return 0;
++	}
++
++	switch (addr) {
++	case PT_NAT_BITS:
++		pos = ELF_NAT_OFFSET;
++		break;
++	case PT_R4 ... PT_R7:
++		pos = addr - PT_R4 + ELF_GR_OFFSET(4);
++		break;
++	case PT_B1 ... PT_B5:
++		pos = addr - PT_B1 + ELF_BR_OFFSET(1);
++		break;
++	case PT_AR_EC:
++		pos = ELF_AR_EC_OFFSET;
++		break;
++	case PT_AR_LC:
++		pos = ELF_AR_LC_OFFSET;
++		break;
++	case PT_CR_IPSR:
++		pos = ELF_CR_IPSR_OFFSET;
++		break;
++	case PT_CR_IIP:
++		pos = ELF_CR_IIP_OFFSET;
++		break;
++	case PT_CFM:
++		pos = ELF_CFM_OFFSET;
++		break;
++	case PT_AR_UNAT:
++		pos = ELF_AR_UNAT_OFFSET;
++		break;
++	case PT_AR_PFS:
++		pos = ELF_AR_PFS_OFFSET;
++		break;
++	case PT_AR_RSC:
++		pos = ELF_AR_RSC_OFFSET;
++		break;
++	case PT_AR_RNAT:
++		pos = ELF_AR_RNAT_OFFSET;
++		break;
++	case PT_AR_BSPSTORE:
++		pos = ELF_AR_BSPSTORE_OFFSET;
++		break;
++	case PT_PR:
++		pos = ELF_PR_OFFSET;
++		break;
++	case PT_B6:
++		pos = ELF_BR_OFFSET(6);
++		break;
++	case PT_AR_BSP:
++		pos = ELF_AR_BSP_OFFSET;
++		break;
++	case PT_R1 ... PT_R3:
++		pos = addr - PT_R1 + ELF_GR_OFFSET(1);
++		break;
++	case PT_R12 ... PT_R15:
++		pos = addr - PT_R12 + ELF_GR_OFFSET(12);
++		break;
++	case PT_R8 ... PT_R11:
++		pos = addr - PT_R8 + ELF_GR_OFFSET(8);
++		break;
++	case PT_R16 ... PT_R31:
++		pos = addr - PT_R16 + ELF_GR_OFFSET(16);
++		break;
++	case PT_AR_CCV:
++		pos = ELF_AR_CCV_OFFSET;
++		break;
++	case PT_AR_FPSR:
++		pos = ELF_AR_FPSR_OFFSET;
++		break;
++	case PT_B0:
++		pos = ELF_BR_OFFSET(0);
++		break;
++	case PT_B7:
++		pos = ELF_BR_OFFSET(7);
++		break;
++	case PT_AR_CSD:
++		pos = ELF_AR_CSD_OFFSET;
++		break;
++	case PT_AR_SSD:
++		pos = ELF_AR_SSD_OFFSET;
++		break;
++	}
++
++	if (pos != -1) {
++		if (write_access)
++			ret = gpregs_set(child, NULL, pos,
++				sizeof(unsigned long), data, NULL);
++		else
++			ret = gpregs_get(child, NULL, pos,
++				sizeof(unsigned long), data, NULL);
++		if (ret != 0)
++			return -1;
++		return 0;
++	}
++
++	/* access debug registers */
++	if (addr >= PT_IBR) {
++		regnum = (addr - PT_IBR) >> 3;
++		ptr = &child->thread.ibr[0];
++	} else {
++		regnum = (addr - PT_DBR) >> 3;
++		ptr = &child->thread.dbr[0];
++	}
++
++	if (regnum >= 8) {
++		dprintk("ptrace: rejecting access to register "
++				"address 0x%lx\n", addr);
++		return -1;
++	}
++#ifdef CONFIG_PERFMON
++	/*
++	 * Check if debug registers are used by perfmon. This
++	 * test must be done once we know that we can do the
++	 * operation, i.e. the arguments are all valid, but
++	 * before we start modifying the state.
++	 *
++	 * Perfmon needs to keep a count of how many processes
++	 * are trying to modify the debug registers for system
++	 * wide monitoring sessions.
++	 *
++	 * We also include read access here, because they may
++	 * cause the PMU-installed debug register state
++	 * (dbr[], ibr[]) to be reset. The two arrays are also
++	 * used by perfmon, but we do not use
++	 * IA64_THREAD_DBG_VALID. The registers are restored
++	 * by the PMU context switch code.
++	 */
++	if (pfm_use_debug_registers(child))
++		return -1;
++#endif
++
++	if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
++		child->thread.flags |= IA64_THREAD_DBG_VALID;
++		memset(child->thread.dbr, 0,
++				sizeof(child->thread.dbr));
++		memset(child->thread.ibr, 0,
++				sizeof(child->thread.ibr));
++	}
++
++	ptr += regnum;
++
++	if ((regnum & 1) && write_access) {
++		/* don't let the user set kernel-level breakpoints: */
++		*ptr = *data & ~(7UL << 56);
++		return 0;
++	}
++	if (write_access)
++		*ptr = *data;
++	else
++		*data = *ptr;
++	return 0;
++}
++
++static const struct user_regset native_regsets[] = {
++	{
++		.core_note_type = NT_PRSTATUS,
++		.n = ELF_NGREG,
++		.size = sizeof(elf_greg_t), .align = sizeof(elf_greg_t),
++		.get = gpregs_get, .set = gpregs_set,
++		.writeback = gpregs_writeback
++	},
++	{
++		.core_note_type = NT_PRFPREG,
++		.n = ELF_NFPREG,
++		.size = sizeof(elf_fpreg_t), .align = sizeof(elf_fpreg_t),
++		.get = fpregs_get, .set = fpregs_set, .active = fpregs_active
++	},
++};
++
++static const struct user_regset_view user_ia64_view = {
++	.name = "ia64",
++	.e_machine = EM_IA_64,
++	.regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
++};
++
++const struct user_regset_view *task_user_regset_view(struct task_struct *tsk)
++{
++#ifdef CONFIG_IA32_SUPPORT
++	extern const struct user_regset_view user_ia32_view;
++	if (IS_IA32_PROCESS(task_pt_regs(tsk)))
++		return &user_ia32_view;
++#endif
++	return &user_ia64_view;
++}
+diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
+index 779c3cc..b11bb50 100644
+--- a/arch/ia64/kernel/salinfo.c
++++ b/arch/ia64/kernel/salinfo.c
+@@ -44,8 +44,8 @@
+ #include <linux/smp.h>
+ #include <linux/timer.h>
+ #include <linux/vmalloc.h>
++#include <linux/semaphore.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/sal.h>
+ #include <asm/uaccess.h>
+ 
+diff --git a/arch/ia64/kernel/semaphore.c b/arch/ia64/kernel/semaphore.c
+deleted file mode 100644
+index 2724ef3..0000000
+--- a/arch/ia64/kernel/semaphore.c
++++ /dev/null
+@@ -1,165 +0,0 @@
+-/*
+- * IA-64 semaphore implementation (derived from x86 version).
+- *
+- * Copyright (C) 1999-2000, 2002 Hewlett-Packard Co
+- *	David Mosberger-Tang <davidm at hpl.hp.com>
+- */
+-
+-/*
+- * Semaphores are implemented using a two-way counter: The "count"
+- * variable is decremented for each process that tries to acquire the
+- * semaphore, while the "sleepers" variable is a count of such
+- * acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can efficiently
+- * test if they need to do any extra work (up needs to do something
+- * only if count was negative before the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is protected
+- * by the spinlock in the semaphore's waitqueue head.
+- *
+- * Note that these functions are only called when there is contention
+- * on the lock, and as such all this is the "non-critical" part of the
+- * whole semaphore business. The critical part is the inline stuff in
+- * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
+- */
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-
+-#include <asm/errno.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * Logic:
+- *  - Only on a boundary condition do we need to care. When we go
+- *    from a negative count to a non-negative, we wake people up.
+- *  - When we go from a non-negative count to a negative do we
+- *    (a) synchronize with the "sleepers" count and (b) make sure
+- *    that we're on the wakeup list before we synchronize so that
+- *    we cannot lose wakeup events.
+- */
+-
+-void
+-__up (struct semaphore *sem)
+-{
+-	wake_up(&sem->wait);
+-}
+-
+-void __sched __down (struct semaphore *sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	unsigned long flags;
+-
+-	tsk->state = TASK_UNINTERRUPTIBLE;
+-	spin_lock_irqsave(&sem->wait.lock, flags);
+-	add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+-	sem->sleepers++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock in
+-		 * the wait_queue_head.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-		schedule();
+-
+-		spin_lock_irqsave(&sem->wait.lock, flags);
+-		tsk->state = TASK_UNINTERRUPTIBLE;
+-	}
+-	remove_wait_queue_locked(&sem->wait, &wait);
+-	wake_up_locked(&sem->wait);
+-	spin_unlock_irqrestore(&sem->wait.lock, flags);
+-	tsk->state = TASK_RUNNING;
+-}
+-
+-int __sched __down_interruptible (struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	unsigned long flags;
+-
+-	tsk->state = TASK_INTERRUPTIBLE;
+-	spin_lock_irqsave(&sem->wait.lock, flags);
+-	add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+-	sem->sleepers ++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * With signals pending, this turns into
+-		 * the trylock failure case - we won't be
+-		 * sleeping, and we* can't get the lock as
+-		 * it has contention. Just correct the count
+-		 * and exit.
+-		 */
+-		if (signal_pending(current)) {
+-			retval = -EINTR;
+-			sem->sleepers = 0;
+-			atomic_add(sleepers, &sem->count);
+-			break;
+-		}
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock in
+-		 * wait_queue_head. The "-1" is because we're
+-		 * still hoping to get the semaphore.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-		schedule();
+-
+-		spin_lock_irqsave(&sem->wait.lock, flags);
+-		tsk->state = TASK_INTERRUPTIBLE;
+-	}
+-	remove_wait_queue_locked(&sem->wait, &wait);
+-	wake_up_locked(&sem->wait);
+-	spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-	tsk->state = TASK_RUNNING;
+-	return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for having decremented the
+- * count.
+- */
+-int
+-__down_trylock (struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int sleepers;
+-
+-	spin_lock_irqsave(&sem->wait.lock, flags);
+-	sleepers = sem->sleepers + 1;
+-	sem->sleepers = 0;
+-
+-	/*
+-	 * Add "everybody else" and us into it. They aren't
+-	 * playing, because we own the spinlock in the
+-	 * wait_queue_head.
+-	 */
+-	if (!atomic_add_negative(sleepers, &sem->count)) {
+-		wake_up_locked(&sem->wait);
+-	}
+-
+-	spin_unlock_irqrestore(&sem->wait.lock, flags);
+-	return 1;
+-}
+diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
+index 4aa9eae..5015ca1 100644
+--- a/arch/ia64/kernel/setup.c
++++ b/arch/ia64/kernel/setup.c
+@@ -59,6 +59,7 @@
+ #include <asm/setup.h>
+ #include <asm/smp.h>
+ #include <asm/system.h>
++#include <asm/tlbflush.h>
+ #include <asm/unistd.h>
+ #include <asm/hpsim.h>
+ 
+@@ -176,6 +177,29 @@ filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
+ 	return 0;
+ }
+ 
++/*
++ * Similar to "filter_rsvd_memory()", but the reserved memory ranges
++ * are not filtered out.
++ */
++int __init
++filter_memory(unsigned long start, unsigned long end, void *arg)
++{
++	void (*func)(unsigned long, unsigned long, int);
++
++#if IGNORE_PFN0
++	if (start == PAGE_OFFSET) {
++		printk(KERN_WARNING "warning: skipping physical page 0\n");
++		start += PAGE_SIZE;
++		if (start >= end)
++			return 0;
++	}
++#endif
++	func = arg;
++	if (start < end)
++		call_pernode_memory(__pa(start), end - start, func);
++	return 0;
++}
++
+ static void __init
+ sort_regions (struct rsvd_region *rsvd_region, int max)
+ {
+@@ -493,6 +517,8 @@ setup_arch (char **cmdline_p)
+ 	acpi_table_init();
+ # ifdef CONFIG_ACPI_NUMA
+ 	acpi_numa_init();
++	per_cpu_scan_finalize((cpus_weight(early_cpu_possible_map) == 0 ?
++		32 : cpus_weight(early_cpu_possible_map)), additional_cpus);
+ # endif
+ #else
+ # ifdef CONFIG_SMP
+@@ -946,9 +972,10 @@ cpu_init (void)
+ #endif
+ 
+ 	/* set ia64_ctx.max_rid to the maximum RID that is supported by all CPUs: */
+-	if (ia64_pal_vm_summary(NULL, &vmi) == 0)
++	if (ia64_pal_vm_summary(NULL, &vmi) == 0) {
+ 		max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1;
+-	else {
++		setup_ptcg_sem(vmi.pal_vm_info_2_s.max_purges, NPTCG_FROM_PAL);
++	} else {
+ 		printk(KERN_WARNING "cpu_init: PAL VM summary failed, assuming 18 RID bits\n");
+ 		max_ctx = (1U << 15) - 1;	/* use architected minimum */
+ 	}
+diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
+index 4e446aa..9a9d4c4 100644
+--- a/arch/ia64/kernel/smp.c
++++ b/arch/ia64/kernel/smp.c
+@@ -213,6 +213,19 @@ send_IPI_allbutself (int op)
+  * Called with preemption disabled.
+  */
+ static inline void
++send_IPI_mask(cpumask_t mask, int op)
++{
++	unsigned int cpu;
++
++	for_each_cpu_mask(cpu, mask) {
++			send_IPI_single(cpu, op);
++	}
++}
++
++/*
++ * Called with preemption disabled.
++ */
++static inline void
+ send_IPI_all (int op)
+ {
+ 	int i;
+@@ -401,6 +414,75 @@ smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int
+ }
+ EXPORT_SYMBOL(smp_call_function_single);
+ 
++/**
++ * smp_call_function_mask(): Run a function on a set of other CPUs.
++ * <mask>	The set of cpus to run on.  Must not include the current cpu.
++ * <func> 	The function to run. This must be fast and non-blocking.
++ * <info>	An arbitrary pointer to pass to the function.
++ * <wait>	If true, wait (atomically) until function
++ *		has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++int smp_call_function_mask(cpumask_t mask,
++			   void (*func)(void *), void *info,
++			   int wait)
++{
++	struct call_data_struct data;
++	cpumask_t allbutself;
++	int cpus;
++
++	spin_lock(&call_lock);
++	allbutself = cpu_online_map;
++	cpu_clear(smp_processor_id(), allbutself);
++
++	cpus_and(mask, mask, allbutself);
++	cpus = cpus_weight(mask);
++	if (!cpus) {
++		spin_unlock(&call_lock);
++		return 0;
++	}
++
++	/* Can deadlock when called with interrupts disabled */
++	WARN_ON(irqs_disabled());
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC*/
++
++	/* Send a message to other CPUs */
++	if (cpus_equal(mask, allbutself))
++		send_IPI_allbutself(IPI_CALL_FUNC);
++	else
++		send_IPI_mask(mask, IPI_CALL_FUNC);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (wait)
++		while (atomic_read(&data.finished) != cpus)
++			cpu_relax();
++	call_data = NULL;
++
++	spin_unlock(&call_lock);
++	return 0;
++
++}
++EXPORT_SYMBOL(smp_call_function_mask);
++
+ /*
+  * this function sends a 'generic call function' IPI to all other CPUs
+  * in the system.
+diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
+index 32ee597..16483be 100644
+--- a/arch/ia64/kernel/smpboot.c
++++ b/arch/ia64/kernel/smpboot.c
+@@ -400,9 +400,9 @@ smp_callin (void)
+ 	/* Setup the per cpu irq handling data structures */
+ 	__setup_vector_irq(cpuid);
+ 	cpu_set(cpuid, cpu_online_map);
+-	unlock_ipi_calllock();
+ 	per_cpu(cpu_state, cpuid) = CPU_ONLINE;
+ 	spin_unlock(&vector_lock);
++	unlock_ipi_calllock();
+ 
+ 	smp_setup_percpu_timer();
+ 
+diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
+index 17fda52..48e15a5 100644
+--- a/arch/ia64/kernel/time.c
++++ b/arch/ia64/kernel/time.c
+@@ -59,6 +59,84 @@ static struct clocksource clocksource_itc = {
+ };
+ static struct clocksource *itc_clocksource;
+ 
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++
++#include <linux/kernel_stat.h>
++
++extern cputime_t cycle_to_cputime(u64 cyc);
++
++/*
++ * Called from the context switch with interrupts disabled, to charge all
++ * accumulated times to the current process, and to prepare accounting on
++ * the next process.
++ */
++void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next)
++{
++	struct thread_info *pi = task_thread_info(prev);
++	struct thread_info *ni = task_thread_info(next);
++	cputime_t delta_stime, delta_utime;
++	__u64 now;
++
++	now = ia64_get_itc();
++
++	delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp));
++	account_system_time(prev, 0, delta_stime);
++	account_system_time_scaled(prev, delta_stime);
++
++	if (pi->ac_utime) {
++		delta_utime = cycle_to_cputime(pi->ac_utime);
++		account_user_time(prev, delta_utime);
++		account_user_time_scaled(prev, delta_utime);
++	}
++
++	pi->ac_stamp = ni->ac_stamp = now;
++	ni->ac_stime = ni->ac_utime = 0;
++}
++
++/*
++ * Account time for a transition between system, hard irq or soft irq state.
++ * Note that this function is called with interrupts enabled.
++ */
++void account_system_vtime(struct task_struct *tsk)
++{
++	struct thread_info *ti = task_thread_info(tsk);
++	unsigned long flags;
++	cputime_t delta_stime;
++	__u64 now;
++
++	local_irq_save(flags);
++
++	now = ia64_get_itc();
++
++	delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
++	account_system_time(tsk, 0, delta_stime);
++	account_system_time_scaled(tsk, delta_stime);
++	ti->ac_stime = 0;
++
++	ti->ac_stamp = now;
++
++	local_irq_restore(flags);
++}
++
++/*
++ * Called from the timer interrupt handler to charge accumulated user time
++ * to the current process.  Must be called with interrupts disabled.
++ */
++void account_process_tick(struct task_struct *p, int user_tick)
++{
++	struct thread_info *ti = task_thread_info(p);
++	cputime_t delta_utime;
++
++	if (ti->ac_utime) {
++		delta_utime = cycle_to_cputime(ti->ac_utime);
++		account_user_time(p, delta_utime);
++		account_user_time_scaled(p, delta_utime);
++		ti->ac_utime = 0;
++	}
++}
++
++#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
++
+ static irqreturn_t
+ timer_interrupt (int irq, void *dev_id)
+ {
+diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
+index 6903361..ff0e7c1 100644
+--- a/arch/ia64/kernel/unaligned.c
++++ b/arch/ia64/kernel/unaligned.c
+@@ -13,6 +13,7 @@
+  * 2001/08/13	Correct size of extended floats (float_fsz) from 16 to 10 bytes.
+  * 2001/01/17	Add support emulation of unaligned kernel accesses.
+  */
++#include <linux/jiffies.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/tty.h>
+@@ -1290,7 +1291,7 @@ within_logging_rate_limit (void)
+ {
+ 	static unsigned long count, last_time;
+ 
+-	if (jiffies - last_time > 5*HZ)
++	if (time_after(jiffies, last_time + 5 * HZ))
+ 		count = 0;
+ 	if (count < 5) {
+ 		last_time = jiffies;
+diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
+index 344f64e..798bf98 100644
+--- a/arch/ia64/mm/contig.c
++++ b/arch/ia64/mm/contig.c
+@@ -45,8 +45,6 @@ void show_mem(void)
+ 
+ 	printk(KERN_INFO "Mem-info:\n");
+ 	show_free_areas();
+-	printk(KERN_INFO "Free swap:       %6ldkB\n",
+-	       nr_swap_pages<<(PAGE_SHIFT-10));
+ 	printk(KERN_INFO "Node memory in pages:\n");
+ 	for_each_online_pgdat(pgdat) {
+ 		unsigned long present;
+@@ -255,7 +253,7 @@ paging_init (void)
+ 	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
+ 
+ #ifdef CONFIG_VIRTUAL_MEM_MAP
+-	efi_memmap_walk(register_active_ranges, NULL);
++	efi_memmap_walk(filter_memory, register_active_ranges);
+ 	efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
+ 	if (max_gap < LARGE_GAP) {
+ 		vmem_map = (struct page *) 0;
+diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
+index ee5e68b..544dc42 100644
+--- a/arch/ia64/mm/discontig.c
++++ b/arch/ia64/mm/discontig.c
+@@ -104,7 +104,7 @@ static int __meminit early_nr_cpus_node(int node)
+ {
+ 	int cpu, n = 0;
+ 
+-	for (cpu = 0; cpu < NR_CPUS; cpu++)
++	for_each_possible_early_cpu(cpu)
+ 		if (node == node_cpuid[cpu].nid)
+ 			n++;
+ 
+@@ -124,6 +124,7 @@ static unsigned long __meminit compute_pernodesize(int node)
+ 	pernodesize += node * L1_CACHE_BYTES;
+ 	pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
+ 	pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
++	pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
+ 	pernodesize = PAGE_ALIGN(pernodesize);
+ 	return pernodesize;
+ }
+@@ -142,7 +143,7 @@ static void *per_cpu_node_setup(void *cpu_data, int node)
+ #ifdef CONFIG_SMP
+ 	int cpu;
+ 
+-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
++	for_each_possible_early_cpu(cpu) {
+ 		if (node == node_cpuid[cpu].nid) {
+ 			memcpy(__va(cpu_data), __phys_per_cpu_start,
+ 			       __per_cpu_end - __per_cpu_start);
+@@ -345,7 +346,7 @@ static void __init initialize_pernode_data(void)
+ 
+ #ifdef CONFIG_SMP
+ 	/* Set the node_data pointer for each per-cpu struct */
+-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
++	for_each_possible_early_cpu(cpu) {
+ 		node = node_cpuid[cpu].nid;
+ 		per_cpu(cpu_info, cpu).node_data = mem_data[node].node_data;
+ 	}
+@@ -444,7 +445,7 @@ void __init find_memory(void)
+ 			mem_data[node].min_pfn = ~0UL;
+ 		}
+ 
+-	efi_memmap_walk(register_active_ranges, NULL);
++	efi_memmap_walk(filter_memory, register_active_ranges);
+ 
+ 	/*
+ 	 * Initialize the boot memory maps in reverse order since that's
+@@ -493,13 +494,9 @@ void __cpuinit *per_cpu_init(void)
+ 	int cpu;
+ 	static int first_time = 1;
+ 
+-
+-	if (smp_processor_id() != 0)
+-		return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
+-
+ 	if (first_time) {
+ 		first_time = 0;
+-		for (cpu = 0; cpu < NR_CPUS; cpu++)
++		for_each_possible_early_cpu(cpu)
+ 			per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
+ 	}
+ 
+@@ -522,8 +519,6 @@ void show_mem(void)
+ 
+ 	printk(KERN_INFO "Mem-info:\n");
+ 	show_free_areas();
+-	printk(KERN_INFO "Free swap:       %6ldkB\n",
+-	       nr_swap_pages<<(PAGE_SHIFT-10));
+ 	printk(KERN_INFO "Node memory in pages:\n");
+ 	for_each_online_pgdat(pgdat) {
+ 		unsigned long present;
+diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
+index a4ca657..5c1de53 100644
+--- a/arch/ia64/mm/init.c
++++ b/arch/ia64/mm/init.c
+@@ -58,7 +58,6 @@ __ia64_sync_icache_dcache (pte_t pte)
+ {
+ 	unsigned long addr;
+ 	struct page *page;
+-	unsigned long order;
+ 
+ 	page = pte_page(pte);
+ 	addr = (unsigned long) page_address(page);
+@@ -66,12 +65,7 @@ __ia64_sync_icache_dcache (pte_t pte)
+ 	if (test_bit(PG_arch_1, &page->flags))
+ 		return;				/* i-cache is already coherent with d-cache */
+ 
+-	if (PageCompound(page)) {
+-		order = compound_order(page);
+-		flush_icache_range(addr, addr + (1UL << order << PAGE_SHIFT));
+-	}
+-	else
+-		flush_icache_range(addr, addr + PAGE_SIZE);
++	flush_icache_range(addr, addr + (PAGE_SIZE << compound_order(page)));
+ 	set_bit(PG_arch_1, &page->flags);	/* mark page as clean */
+ }
+ 
+@@ -553,12 +547,10 @@ find_largest_hole (u64 start, u64 end, void *arg)
+ #endif /* CONFIG_VIRTUAL_MEM_MAP */
+ 
+ int __init
+-register_active_ranges(u64 start, u64 end, void *arg)
++register_active_ranges(u64 start, u64 len, int nid)
+ {
+-	int nid = paddr_to_nid(__pa(start));
++	u64 end = start + len;
+ 
+-	if (nid < 0)
+-		nid = 0;
+ #ifdef CONFIG_KEXEC
+ 	if (start > crashk_res.start && start < crashk_res.end)
+ 		start = crashk_res.end;
+diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c
+index 7807fc5..b73bf18 100644
+--- a/arch/ia64/mm/numa.c
++++ b/arch/ia64/mm/numa.c
+@@ -27,7 +27,9 @@
+  */
+ int num_node_memblks;
+ struct node_memblk_s node_memblk[NR_NODE_MEMBLKS];
+-struct node_cpuid_s node_cpuid[NR_CPUS];
++struct node_cpuid_s node_cpuid[NR_CPUS] =
++	{ [0 ... NR_CPUS-1] = { .phys_id = 0, .nid = NUMA_NO_NODE } };
++
+ /*
+  * This is a matrix with "distances" between nodes, they should be
+  * proportional to the memory access latency ratios.
+diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
+index 655da24..d52ec4e 100644
+--- a/arch/ia64/mm/tlb.c
++++ b/arch/ia64/mm/tlb.c
+@@ -11,6 +11,9 @@
+  * Rohit Seth <rohit.seth at intel.com>
+  * Ken Chen <kenneth.w.chen at intel.com>
+  * Christophe de Dinechin <ddd at hp.com>: Avoid ptc.e on memory allocation
++ * Copyright (C) 2007 Intel Corp
++ *	Fenghua Yu <fenghua.yu at intel.com>
++ *	Add multiple ptc.g/ptc.ga instruction support in global tlb purge.
+  */
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -26,6 +29,9 @@
+ #include <asm/pal.h>
+ #include <asm/tlbflush.h>
+ #include <asm/dma.h>
++#include <asm/processor.h>
++#include <asm/sal.h>
++#include <asm/tlb.h>
+ 
+ static struct {
+ 	unsigned long mask;	/* mask of supported purge page-sizes */
+@@ -39,6 +45,10 @@ struct ia64_ctx ia64_ctx = {
+ };
+ 
+ DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
++DEFINE_PER_CPU(u8, ia64_tr_num);  /*Number of TR slots in current processor*/
++DEFINE_PER_CPU(u8, ia64_tr_used); /*Max Slot number used by kernel*/
++
++struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX];
+ 
+ /*
+  * Initializes the ia64_ctx.bitmap array based on max_ctx+1.
+@@ -84,14 +94,140 @@ wrap_mmu_context (struct mm_struct *mm)
+ 	local_flush_tlb_all();
+ }
+ 
++/*
++ * Implement "spinaphores" ... like counting semaphores, but they
++ * spin instead of sleeping.  If there are ever any other users for
++ * this primitive it can be moved up to a spinaphore.h header.
++ */
++struct spinaphore {
++	atomic_t	cur;
++};
++
++static inline void spinaphore_init(struct spinaphore *ss, int val)
++{
++	atomic_set(&ss->cur, val);
++}
++
++static inline void down_spin(struct spinaphore *ss)
++{
++	while (unlikely(!atomic_add_unless(&ss->cur, -1, 0)))
++		while (atomic_read(&ss->cur) == 0)
++			cpu_relax();
++}
++
++static inline void up_spin(struct spinaphore *ss)
++{
++	atomic_add(1, &ss->cur);
++}
++
++static struct spinaphore ptcg_sem;
++static u16 nptcg = 1;
++static int need_ptcg_sem = 1;
++static int toolatetochangeptcgsem = 0;
++
++/*
++ * Kernel parameter "nptcg=" overrides max number of concurrent global TLB
++ * purges which is reported from either PAL or SAL PALO.
++ *
++ * We don't have sanity checking for nptcg value. It's the user's responsibility
++ * for valid nptcg value on the platform. Otherwise, kernel may hang in some
++ * cases.
++ */
++static int __init
++set_nptcg(char *str)
++{
++	int value = 0;
++
++	get_option(&str, &value);
++	setup_ptcg_sem(value, NPTCG_FROM_KERNEL_PARAMETER);
++
++	return 1;
++}
++
++__setup("nptcg=", set_nptcg);
++
++/*
++ * Maximum number of simultaneous ptc.g purges in the system can
++ * be defined by PAL_VM_SUMMARY (in which case we should take
++ * the smallest value for any cpu in the system) or by the PAL
++ * override table (in which case we should ignore the value from
++ * PAL_VM_SUMMARY).
++ *
++ * Kernel parameter "nptcg=" overrides maximum number of simultanesous ptc.g
++ * purges defined in either PAL_VM_SUMMARY or PAL override table. In this case,
++ * we should ignore the value from either PAL_VM_SUMMARY or PAL override table.
++ *
++ * Complicating the logic here is the fact that num_possible_cpus()
++ * isn't fully setup until we start bringing cpus online.
++ */
++void
++setup_ptcg_sem(int max_purges, int nptcg_from)
++{
++	static int kp_override;
++	static int palo_override;
++	static int firstcpu = 1;
++
++	if (toolatetochangeptcgsem) {
++		BUG_ON(max_purges < nptcg);
++		return;
++	}
++
++	if (nptcg_from == NPTCG_FROM_KERNEL_PARAMETER) {
++		kp_override = 1;
++		nptcg = max_purges;
++		goto resetsema;
++	}
++	if (kp_override) {
++		need_ptcg_sem = num_possible_cpus() > nptcg;
++		return;
++	}
++
++	if (nptcg_from == NPTCG_FROM_PALO) {
++		palo_override = 1;
++
++		/* In PALO max_purges == 0 really means it! */
++		if (max_purges == 0)
++			panic("Whoa! Platform does not support global TLB purges.\n");
++		nptcg = max_purges;
++		if (nptcg == PALO_MAX_TLB_PURGES) {
++			need_ptcg_sem = 0;
++			return;
++		}
++		goto resetsema;
++	}
++	if (palo_override) {
++		if (nptcg != PALO_MAX_TLB_PURGES)
++			need_ptcg_sem = (num_possible_cpus() > nptcg);
++		return;
++	}
++
++	/* In PAL_VM_SUMMARY max_purges == 0 actually means 1 */
++	if (max_purges == 0) max_purges = 1;
++
++	if (firstcpu) {
++		nptcg = max_purges;
++		firstcpu = 0;
++	}
++	if (max_purges < nptcg)
++		nptcg = max_purges;
++	if (nptcg == PAL_MAX_PURGES) {
++		need_ptcg_sem = 0;
++		return;
++	} else
++		need_ptcg_sem = (num_possible_cpus() > nptcg);
++
++resetsema:
++	spinaphore_init(&ptcg_sem, max_purges);
++}
++
+ void
+ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
+ 		       unsigned long end, unsigned long nbits)
+ {
+-	static DEFINE_SPINLOCK(ptcg_lock);
+-
+ 	struct mm_struct *active_mm = current->active_mm;
+ 
++	toolatetochangeptcgsem = 1;
++
+ 	if (mm != active_mm) {
+ 		/* Restore region IDs for mm */
+ 		if (mm && active_mm) {
+@@ -102,19 +238,20 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
+ 		}
+ 	}
+ 
+-	/* HW requires global serialization of ptc.ga.  */
+-	spin_lock(&ptcg_lock);
+-	{
+-		do {
+-			/*
+-			 * Flush ALAT entries also.
+-			 */
+-			ia64_ptcga(start, (nbits<<2));
+-			ia64_srlz_i();
+-			start += (1UL << nbits);
+-		} while (start < end);
+-	}
+-	spin_unlock(&ptcg_lock);
++	if (need_ptcg_sem)
++		down_spin(&ptcg_sem);
++
++	do {
++		/*
++		 * Flush ALAT entries also.
++		 */
++		ia64_ptcga(start, (nbits << 2));
++		ia64_srlz_i();
++		start += (1UL << nbits);
++	} while (start < end);
++
++	if (need_ptcg_sem)
++		up_spin(&ptcg_sem);
+ 
+         if (mm != active_mm) {
+                 activate_context(active_mm);
+@@ -190,6 +327,9 @@ ia64_tlb_init (void)
+ 	ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
+ 	unsigned long tr_pgbits;
+ 	long status;
++	pal_vm_info_1_u_t vm_info_1;
++	pal_vm_info_2_u_t vm_info_2;
++	int cpu = smp_processor_id();
+ 
+ 	if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
+ 		printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld; "
+@@ -206,4 +346,191 @@ ia64_tlb_init (void)
+ 	local_cpu_data->ptce_stride[1] = ptce_info.stride[1];
+ 
+ 	local_flush_tlb_all();	/* nuke left overs from bootstrapping... */
++	status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2);
++
++	if (status) {
++		printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
++		per_cpu(ia64_tr_num, cpu) = 8;
++		return;
++	}
++	per_cpu(ia64_tr_num, cpu) = vm_info_1.pal_vm_info_1_s.max_itr_entry+1;
++	if (per_cpu(ia64_tr_num, cpu) >
++				(vm_info_1.pal_vm_info_1_s.max_dtr_entry+1))
++		per_cpu(ia64_tr_num, cpu) =
++				vm_info_1.pal_vm_info_1_s.max_dtr_entry+1;
++	if (per_cpu(ia64_tr_num, cpu) > IA64_TR_ALLOC_MAX) {
++		per_cpu(ia64_tr_num, cpu) = IA64_TR_ALLOC_MAX;
++		printk(KERN_DEBUG "TR register number exceeds IA64_TR_ALLOC_MAX!"
++			"IA64_TR_ALLOC_MAX should be extended\n");
++	}
++}
++
++/*
++ * is_tr_overlap
++ *
++ * Check overlap with inserted TRs.
++ */
++static int is_tr_overlap(struct ia64_tr_entry *p, u64 va, u64 log_size)
++{
++	u64 tr_log_size;
++	u64 tr_end;
++	u64 va_rr = ia64_get_rr(va);
++	u64 va_rid = RR_TO_RID(va_rr);
++	u64 va_end = va + (1<<log_size) - 1;
++
++	if (va_rid != RR_TO_RID(p->rr))
++		return 0;
++	tr_log_size = (p->itir & 0xff) >> 2;
++	tr_end = p->ifa + (1<<tr_log_size) - 1;
++
++	if (va > tr_end || p->ifa > va_end)
++		return 0;
++	return 1;
++
++}
++
++/*
++ * ia64_insert_tr in virtual mode. Allocate a TR slot
++ *
++ * target_mask : 0x1 : itr, 0x2 : dtr, 0x3 : idtr
++ *
++ * va 	: virtual address.
++ * pte 	: pte entries inserted.
++ * log_size: range to be covered.
++ *
++ * Return value:  <0 :  error No.
++ *
++ *		  >=0 : slot number allocated for TR.
++ * Must be called with preemption disabled.
++ */
++int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size)
++{
++	int i, r;
++	unsigned long psr;
++	struct ia64_tr_entry *p;
++	int cpu = smp_processor_id();
++
++	r = -EINVAL;
++	/*Check overlap with existing TR entries*/
++	if (target_mask & 0x1) {
++		p = &__per_cpu_idtrs[cpu][0][0];
++		for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
++								i++, p++) {
++			if (p->pte & 0x1)
++				if (is_tr_overlap(p, va, log_size)) {
++					printk(KERN_DEBUG "Overlapped Entry"
++						"Inserted for TR Reigster!!\n");
++					goto out;
++			}
++		}
++	}
++	if (target_mask & 0x2) {
++		p = &__per_cpu_idtrs[cpu][1][0];
++		for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
++								i++, p++) {
++			if (p->pte & 0x1)
++				if (is_tr_overlap(p, va, log_size)) {
++					printk(KERN_DEBUG "Overlapped Entry"
++						"Inserted for TR Reigster!!\n");
++					goto out;
++				}
++		}
++	}
++
++	for (i = IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_num, cpu); i++) {
++		switch (target_mask & 0x3) {
++		case 1:
++			if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1))
++				goto found;
++			continue;
++		case 2:
++			if (!(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
++				goto found;
++			continue;
++		case 3:
++			if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1) &&
++				!(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
++				goto found;
++			continue;
++		default:
++			r = -EINVAL;
++			goto out;
++		}
++	}
++found:
++	if (i >= per_cpu(ia64_tr_num, cpu))
++		return -EBUSY;
++
++	/*Record tr info for mca hander use!*/
++	if (i > per_cpu(ia64_tr_used, cpu))
++		per_cpu(ia64_tr_used, cpu) = i;
++
++	psr = ia64_clear_ic();
++	if (target_mask & 0x1) {
++		ia64_itr(0x1, i, va, pte, log_size);
++		ia64_srlz_i();
++		p = &__per_cpu_idtrs[cpu][0][i];
++		p->ifa = va;
++		p->pte = pte;
++		p->itir = log_size << 2;
++		p->rr = ia64_get_rr(va);
++	}
++	if (target_mask & 0x2) {
++		ia64_itr(0x2, i, va, pte, log_size);
++		ia64_srlz_i();
++		p = &__per_cpu_idtrs[cpu][1][i];
++		p->ifa = va;
++		p->pte = pte;
++		p->itir = log_size << 2;
++		p->rr = ia64_get_rr(va);
++	}
++	ia64_set_psr(psr);
++	r = i;
++out:
++	return r;
++}
++EXPORT_SYMBOL_GPL(ia64_itr_entry);
++
++/*
++ * ia64_purge_tr
++ *
++ * target_mask: 0x1: purge itr, 0x2 : purge dtr, 0x3 purge idtr.
++ * slot: slot number to be freed.
++ *
++ * Must be called with preemption disabled.
++ */
++void ia64_ptr_entry(u64 target_mask, int slot)
++{
++	int cpu = smp_processor_id();
++	int i;
++	struct ia64_tr_entry *p;
++
++	if (slot < IA64_TR_ALLOC_BASE || slot >= per_cpu(ia64_tr_num, cpu))
++		return;
++
++	if (target_mask & 0x1) {
++		p = &__per_cpu_idtrs[cpu][0][slot];
++		if ((p->pte&0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
++			p->pte = 0;
++			ia64_ptr(0x1, p->ifa, p->itir>>2);
++			ia64_srlz_i();
++		}
++	}
++
++	if (target_mask & 0x2) {
++		p = &__per_cpu_idtrs[cpu][1][slot];
++		if ((p->pte & 0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
++			p->pte = 0;
++			ia64_ptr(0x2, p->ifa, p->itir>>2);
++			ia64_srlz_i();
++		}
++	}
++
++	for (i = per_cpu(ia64_tr_used, cpu); i >= IA64_TR_ALLOC_BASE; i--) {
++		if ((__per_cpu_idtrs[cpu][0][i].pte & 0x1) ||
++				(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
++			break;
++	}
++	per_cpu(ia64_tr_used, cpu) = i;
+ }
++EXPORT_SYMBOL_GPL(ia64_ptr_entry);
+diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
+index 53d0a8e..77b15f8 100644
+--- a/arch/ia64/pci/pci.c
++++ b/arch/ia64/pci/pci.c
+@@ -504,54 +504,12 @@ pcibios_update_irq (struct pci_dev *dev, int irq)
+ 	/* ??? FIXME -- record old value for shutdown.  */
+ }
+ 
+-static inline int
+-pcibios_enable_resources (struct pci_dev *dev, int mask)
+-{
+-	u16 cmd, old_cmd;
+-	int idx;
+-	struct resource *r;
+-	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
+-
+-	if (!dev)
+-		return -EINVAL;
+-
+-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+-	old_cmd = cmd;
+-	for (idx=0; idx<PCI_NUM_RESOURCES; idx++) {
+-		/* Only set up the desired resources.  */
+-		if (!(mask & (1 << idx)))
+-			continue;
+-
+-		r = &dev->resource[idx];
+-		if (!(r->flags & type_mask))
+-			continue;
+-		if ((idx == PCI_ROM_RESOURCE) &&
+-				(!(r->flags & IORESOURCE_ROM_ENABLE)))
+-			continue;
+-		if (!r->start && r->end) {
+-			printk(KERN_ERR
+-			       "PCI: Device %s not available because of resource collisions\n",
+-			       pci_name(dev));
+-			return -EINVAL;
+-		}
+-		if (r->flags & IORESOURCE_IO)
+-			cmd |= PCI_COMMAND_IO;
+-		if (r->flags & IORESOURCE_MEM)
+-			cmd |= PCI_COMMAND_MEMORY;
+-	}
+-	if (cmd != old_cmd) {
+-		printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+-		pci_write_config_word(dev, PCI_COMMAND, cmd);
+-	}
+-	return 0;
+-}
+-
+ int
+ pcibios_enable_device (struct pci_dev *dev, int mask)
+ {
+ 	int ret;
+ 
+-	ret = pcibios_enable_resources(dev, mask);
++	ret = pci_enable_resources(dev, mask);
+ 	if (ret < 0)
+ 		return ret;
+ 
+diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
+index 688a3c2..0591038 100644
+--- a/arch/ia64/sn/kernel/Makefile
++++ b/arch/ia64/sn/kernel/Makefile
+@@ -4,7 +4,7 @@
+ # License.  See the file "COPYING" in the main directory of this archive
+ # for more details.
+ #
+-# Copyright (C) 1999,2001-2006 Silicon Graphics, Inc.  All Rights Reserved.
++# Copyright (C) 1999,2001-2006,2008 Silicon Graphics, Inc.  All Rights Reserved.
+ #
+ 
+ EXTRA_CFLAGS += -Iarch/ia64/sn/include
+@@ -15,9 +15,4 @@ obj-y				+= setup.o bte.o bte_error.o irq.o mca.o idle.o \
+ 				   sn2/
+ obj-$(CONFIG_IA64_GENERIC)      += machvec.o
+ obj-$(CONFIG_SGI_TIOCX)		+= tiocx.o
+-obj-$(CONFIG_IA64_SGI_SN_XP)	+= xp.o
+-xp-y				:= xp_main.o xp_nofault.o
+-obj-$(CONFIG_IA64_SGI_SN_XP)	+= xpc.o
+-xpc-y				:= xpc_main.o xpc_channel.o xpc_partition.o
+-obj-$(CONFIG_IA64_SGI_SN_XP)	+= xpnet.o
+ obj-$(CONFIG_PCI_MSI)		+= msi_sn.o
+diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
+index 0101c79..08b0d9b 100644
+--- a/arch/ia64/sn/kernel/huberror.c
++++ b/arch/ia64/sn/kernel/huberror.c
+@@ -187,8 +187,8 @@ void hub_error_init(struct hubdev_info *hubdev_info)
+ {
+ 
+ 	if (request_irq(SGI_II_ERROR, hub_eint_handler, IRQF_SHARED,
+-			"SN_hub_error", (void *)hubdev_info)) {
+-		printk("hub_error_init: Failed to request_irq for 0x%p\n",
++			"SN_hub_error", hubdev_info)) {
++		printk(KERN_ERR "hub_error_init: Failed to request_irq for 0x%p\n",
+ 		    hubdev_info);
+ 		return;
+ 	}
+diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+index 4b0d153..8cc0c47 100644
+--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
++++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+@@ -37,7 +37,6 @@
+ 
+ #include <asm/processor.h>
+ #include <asm/topology.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <asm/sal.h>
+ #include <asm/sn/io.h>
+diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c
+deleted file mode 100644
+index b7ea466..0000000
+--- a/arch/ia64/sn/kernel/xp_main.c
++++ /dev/null
+@@ -1,290 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition (XP) base.
+- *
+- *	XP provides a base from which its users can interact
+- *	with XPC, yet not be dependent on XPC.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/interrupt.h>
+-#include <linux/module.h>
+-#include <linux/mutex.h>
+-#include <asm/sn/intr.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/sn/xp.h>
+-
+-
+-/*
+- * Target of nofault PIO read.
+- */
+-u64 xp_nofault_PIOR_target;
+-
+-
+-/*
+- * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
+- * users of XPC.
+- */
+-struct xpc_registration xpc_registrations[XPC_NCHANNELS];
+-
+-
+-/*
+- * Initialize the XPC interface to indicate that XPC isn't loaded.
+- */
+-static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }
+-
+-struct xpc_interface xpc_interface = {
+-	(void (*)(int)) xpc_notloaded,
+-	(void (*)(int)) xpc_notloaded,
+-	(enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,
+-	(enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,
+-	(enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))
+-							xpc_notloaded,
+-	(void (*)(partid_t, int, void *)) xpc_notloaded,
+-	(enum xpc_retval (*)(partid_t, void *)) xpc_notloaded
+-};
+-
+-
+-/*
+- * XPC calls this when it (the XPC module) has been loaded.
+- */
+-void
+-xpc_set_interface(void (*connect)(int),
+-		void (*disconnect)(int),
+-		enum xpc_retval (*allocate)(partid_t, int, u32, void **),
+-		enum xpc_retval (*send)(partid_t, int, void *),
+-		enum xpc_retval (*send_notify)(partid_t, int, void *,
+-						xpc_notify_func, void *),
+-		void (*received)(partid_t, int, void *),
+-		enum xpc_retval (*partid_to_nasids)(partid_t, void *))
+-{
+-	xpc_interface.connect = connect;
+-	xpc_interface.disconnect = disconnect;
+-	xpc_interface.allocate = allocate;
+-	xpc_interface.send = send;
+-	xpc_interface.send_notify = send_notify;
+-	xpc_interface.received = received;
+-	xpc_interface.partid_to_nasids = partid_to_nasids;
+-}
+-
+-
+-/*
+- * XPC calls this when it (the XPC module) is being unloaded.
+- */
+-void
+-xpc_clear_interface(void)
+-{
+-	xpc_interface.connect = (void (*)(int)) xpc_notloaded;
+-	xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;
+-	xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,
+-					void **)) xpc_notloaded;
+-	xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))
+-					xpc_notloaded;
+-	xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,
+-				    xpc_notify_func, void *)) xpc_notloaded;
+-	xpc_interface.received = (void (*)(partid_t, int, void *))
+-					xpc_notloaded;
+-	xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))
+-					xpc_notloaded;
+-}
+-
+-
+-/*
+- * Register for automatic establishment of a channel connection whenever
+- * a partition comes up.
+- *
+- * Arguments:
+- *
+- *	ch_number - channel # to register for connection.
+- *	func - function to call for asynchronous notification of channel
+- *	       state changes (i.e., connection, disconnection, error) and
+- *	       the arrival of incoming messages.
+- *      key - pointer to optional user-defined value that gets passed back
+- *	      to the user on any callouts made to func.
+- *	payload_size - size in bytes of the XPC message's payload area which
+- *		       contains a user-defined message. The user should make
+- *		       this large enough to hold their largest message.
+- *	nentries - max #of XPC message entries a message queue can contain.
+- *		   The actual number, which is determined when a connection
+- * 		   is established and may be less then requested, will be
+- *		   passed to the user via the xpcConnected callout.
+- *	assigned_limit - max number of kthreads allowed to be processing
+- * 			 messages (per connection) at any given instant.
+- *	idle_limit - max number of kthreads allowed to be idle at any given
+- * 		     instant.
+- */
+-enum xpc_retval
+-xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
+-		u16 nentries, u32 assigned_limit, u32 idle_limit)
+-{
+-	struct xpc_registration *registration;
+-
+-
+-	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+-	DBUG_ON(payload_size == 0 || nentries == 0);
+-	DBUG_ON(func == NULL);
+-	DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
+-
+-	registration = &xpc_registrations[ch_number];
+-
+-	if (mutex_lock_interruptible(&registration->mutex) != 0) {
+-		return xpcInterrupted;
+-	}
+-
+-	/* if XPC_CHANNEL_REGISTERED(ch_number) */
+-	if (registration->func != NULL) {
+-		mutex_unlock(&registration->mutex);
+-		return xpcAlreadyRegistered;
+-	}
+-
+-	/* register the channel for connection */
+-	registration->msg_size = XPC_MSG_SIZE(payload_size);
+-	registration->nentries = nentries;
+-	registration->assigned_limit = assigned_limit;
+-	registration->idle_limit = idle_limit;
+-	registration->key = key;
+-	registration->func = func;
+-
+-	mutex_unlock(&registration->mutex);
+-
+-	xpc_interface.connect(ch_number);
+-
+-	return xpcSuccess;
+-}
+-
+-
+-/*
+- * Remove the registration for automatic connection of the specified channel
+- * when a partition comes up.
+- *
+- * Before returning this xpc_disconnect() will wait for all connections on the
+- * specified channel have been closed/torndown. So the caller can be assured
+- * that they will not be receiving any more callouts from XPC to their
+- * function registered via xpc_connect().
+- *
+- * Arguments:
+- *
+- *	ch_number - channel # to unregister.
+- */
+-void
+-xpc_disconnect(int ch_number)
+-{
+-	struct xpc_registration *registration;
+-
+-
+-	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+-
+-	registration = &xpc_registrations[ch_number];
+-
+-	/*
+-	 * We've decided not to make this a down_interruptible(), since we
+-	 * figured XPC's users will just turn around and call xpc_disconnect()
+-	 * again anyways, so we might as well wait, if need be.
+-	 */
+-	mutex_lock(&registration->mutex);
+-
+-	/* if !XPC_CHANNEL_REGISTERED(ch_number) */
+-	if (registration->func == NULL) {
+-		mutex_unlock(&registration->mutex);
+-		return;
+-	}
+-
+-	/* remove the connection registration for the specified channel */
+-	registration->func = NULL;
+-	registration->key = NULL;
+-	registration->nentries = 0;
+-	registration->msg_size = 0;
+-	registration->assigned_limit = 0;
+-	registration->idle_limit = 0;
+-
+-	xpc_interface.disconnect(ch_number);
+-
+-	mutex_unlock(&registration->mutex);
+-
+-	return;
+-}
+-
+-
+-int __init
+-xp_init(void)
+-{
+-	int ret, ch_number;
+-	u64 func_addr = *(u64 *) xp_nofault_PIOR;
+-	u64 err_func_addr = *(u64 *) xp_error_PIOR;
+-
+-
+-	if (!ia64_platform_is("sn2")) {
+-		return -ENODEV;
+-	}
+-
+-	/*
+-	 * Register a nofault code region which performs a cross-partition
+-	 * PIO read. If the PIO read times out, the MCA handler will consume
+-	 * the error and return to a kernel-provided instruction to indicate
+-	 * an error. This PIO read exists because it is guaranteed to timeout
+-	 * if the destination is down (AMO operations do not timeout on at
+-	 * least some CPUs on Shubs <= v1.2, which unfortunately we have to
+-	 * work around).
+-	 */
+-	if ((ret = sn_register_nofault_code(func_addr, err_func_addr,
+-						err_func_addr, 1, 1)) != 0) {
+-		printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
+-			ret);
+-	}
+-	/*
+-	 * Setup the nofault PIO read target. (There is no special reason why
+-	 * SH_IPI_ACCESS was selected.)
+-	 */
+-	if (is_shub2()) {
+-		xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
+-	} else {
+-		xp_nofault_PIOR_target = SH1_IPI_ACCESS;
+-	}
+-
+-	/* initialize the connection registration mutex */
+-	for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
+-		mutex_init(&xpc_registrations[ch_number].mutex);
+-	}
+-
+-	return 0;
+-}
+-module_init(xp_init);
+-
+-
+-void __exit
+-xp_exit(void)
+-{
+-	u64 func_addr = *(u64 *) xp_nofault_PIOR;
+-	u64 err_func_addr = *(u64 *) xp_error_PIOR;
+-
+-
+-	/* unregister the PIO read nofault code region */
+-	(void) sn_register_nofault_code(func_addr, err_func_addr,
+-					err_func_addr, 1, 0);
+-}
+-module_exit(xp_exit);
+-
+-
+-MODULE_AUTHOR("Silicon Graphics, Inc.");
+-MODULE_DESCRIPTION("Cross Partition (XP) base");
+-MODULE_LICENSE("GPL");
+-
+-EXPORT_SYMBOL(xp_nofault_PIOR);
+-EXPORT_SYMBOL(xp_nofault_PIOR_target);
+-EXPORT_SYMBOL(xpc_registrations);
+-EXPORT_SYMBOL(xpc_interface);
+-EXPORT_SYMBOL(xpc_clear_interface);
+-EXPORT_SYMBOL(xpc_set_interface);
+-EXPORT_SYMBOL(xpc_connect);
+-EXPORT_SYMBOL(xpc_disconnect);
+-
+diff --git a/arch/ia64/sn/kernel/xp_nofault.S b/arch/ia64/sn/kernel/xp_nofault.S
+deleted file mode 100644
+index 98e7c7d..0000000
+--- a/arch/ia64/sn/kernel/xp_nofault.S
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2007 Silicon Graphics, Inc.  All Rights Reserved.
+- */
+-
+-
+-/*
+- * The xp_nofault_PIOR function takes a pointer to a remote PIO register
+- * and attempts to load and consume a value from it.  This function
+- * will be registered as a nofault code block.  In the event that the
+- * PIO read fails, the MCA handler will force the error to look
+- * corrected and vector to the xp_error_PIOR which will return an error.
+- *
+- * The definition of "consumption" and the time it takes for an MCA
+- * to surface is processor implementation specific.  This code
+- * is sufficient on Itanium through the Montvale processor family.
+- * It may need to be adjusted for future processor implementations.
+- *
+- *	extern int xp_nofault_PIOR(void *remote_register);
+- */
+-
+-	.global xp_nofault_PIOR
+-xp_nofault_PIOR:
+-	mov	r8=r0			// Stage a success return value
+-	ld8.acq	r9=[r32];;		// PIO Read the specified register
+-	adds	r9=1,r9;;		// Add to force consumption
+-	srlz.i;;			// Allow time for MCA to surface
+-	br.ret.sptk.many b0;;		// Return success
+-
+-	.global xp_error_PIOR
+-xp_error_PIOR:
+-	mov	r8=1			// Return value of 1
+-	br.ret.sptk.many b0;;		// Return failure
+diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
+deleted file mode 100644
+index 44ccc0d..0000000
+--- a/arch/ia64/sn/kernel/xpc_channel.c
++++ /dev/null
+@@ -1,2379 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2006 Silicon Graphics, Inc.  All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Communication (XPC) channel support.
+- *
+- *	This is the part of XPC that manages the channels and
+- *	sends/receives messages across them to/from other partitions.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/cache.h>
+-#include <linux/interrupt.h>
+-#include <linux/mutex.h>
+-#include <linux/completion.h>
+-#include <asm/sn/bte.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/sn/xpc.h>
+-
+-
+-/*
+- * Guarantee that the kzalloc'd memory is cacheline aligned.
+- */
+-static void *
+-xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+-{
+-	/* see if kzalloc will give us cachline aligned memory by default */
+-	*base = kzalloc(size, flags);
+-	if (*base == NULL) {
+-		return NULL;
+-	}
+-	if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+-		return *base;
+-	}
+-	kfree(*base);
+-
+-	/* nope, we'll have to do it ourselves */
+-	*base = kzalloc(size + L1_CACHE_BYTES, flags);
+-	if (*base == NULL) {
+-		return NULL;
+-	}
+-	return (void *) L1_CACHE_ALIGN((u64) *base);
+-}
+-
+-
+-/*
+- * Set up the initial values for the XPartition Communication channels.
+- */
+-static void
+-xpc_initialize_channels(struct xpc_partition *part, partid_t partid)
+-{
+-	int ch_number;
+-	struct xpc_channel *ch;
+-
+-
+-	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+-		ch = &part->channels[ch_number];
+-
+-		ch->partid = partid;
+-		ch->number = ch_number;
+-		ch->flags = XPC_C_DISCONNECTED;
+-
+-		ch->local_GP = &part->local_GPs[ch_number];
+-		ch->local_openclose_args =
+-					&part->local_openclose_args[ch_number];
+-
+-		atomic_set(&ch->kthreads_assigned, 0);
+-		atomic_set(&ch->kthreads_idle, 0);
+-		atomic_set(&ch->kthreads_active, 0);
+-
+-		atomic_set(&ch->references, 0);
+-		atomic_set(&ch->n_to_notify, 0);
+-
+-		spin_lock_init(&ch->lock);
+-		mutex_init(&ch->msg_to_pull_mutex);
+-		init_completion(&ch->wdisconnect_wait);
+-
+-		atomic_set(&ch->n_on_msg_allocate_wq, 0);
+-		init_waitqueue_head(&ch->msg_allocate_wq);
+-		init_waitqueue_head(&ch->idle_wq);
+-	}
+-}
+-
+-
+-/*
+- * Setup the infrastructure necessary to support XPartition Communication
+- * between the specified remote partition and the local one.
+- */
+-enum xpc_retval
+-xpc_setup_infrastructure(struct xpc_partition *part)
+-{
+-	int ret, cpuid;
+-	struct timer_list *timer;
+-	partid_t partid = XPC_PARTID(part);
+-
+-
+-	/*
+-	 * Zero out MOST of the entry for this partition. Only the fields
+-	 * starting with `nchannels' will be zeroed. The preceding fields must
+-	 * remain `viable' across partition ups and downs, since they may be
+-	 * referenced during this memset() operation.
+-	 */
+-	memset(&part->nchannels, 0, sizeof(struct xpc_partition) -
+-				offsetof(struct xpc_partition, nchannels));
+-
+-	/*
+-	 * Allocate all of the channel structures as a contiguous chunk of
+-	 * memory.
+-	 */
+-	part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
+-								GFP_KERNEL);
+-	if (part->channels == NULL) {
+-		dev_err(xpc_chan, "can't get memory for channels\n");
+-		return xpcNoMemory;
+-	}
+-
+-	part->nchannels = XPC_NCHANNELS;
+-
+-
+-	/* allocate all the required GET/PUT values */
+-
+-	part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
+-					GFP_KERNEL, &part->local_GPs_base);
+-	if (part->local_GPs == NULL) {
+-		kfree(part->channels);
+-		part->channels = NULL;
+-		dev_err(xpc_chan, "can't get memory for local get/put "
+-			"values\n");
+-		return xpcNoMemory;
+-	}
+-
+-	part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
+-					GFP_KERNEL, &part->remote_GPs_base);
+-	if (part->remote_GPs == NULL) {
+-		dev_err(xpc_chan, "can't get memory for remote get/put "
+-			"values\n");
+-		kfree(part->local_GPs_base);
+-		part->local_GPs = NULL;
+-		kfree(part->channels);
+-		part->channels = NULL;
+-		return xpcNoMemory;
+-	}
+-
+-
+-	/* allocate all the required open and close args */
+-
+-	part->local_openclose_args = xpc_kzalloc_cacheline_aligned(
+-					XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
+-					&part->local_openclose_args_base);
+-	if (part->local_openclose_args == NULL) {
+-		dev_err(xpc_chan, "can't get memory for local connect args\n");
+-		kfree(part->remote_GPs_base);
+-		part->remote_GPs = NULL;
+-		kfree(part->local_GPs_base);
+-		part->local_GPs = NULL;
+-		kfree(part->channels);
+-		part->channels = NULL;
+-		return xpcNoMemory;
+-	}
+-
+-	part->remote_openclose_args = xpc_kzalloc_cacheline_aligned(
+-					XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
+-					&part->remote_openclose_args_base);
+-	if (part->remote_openclose_args == NULL) {
+-		dev_err(xpc_chan, "can't get memory for remote connect args\n");
+-		kfree(part->local_openclose_args_base);
+-		part->local_openclose_args = NULL;
+-		kfree(part->remote_GPs_base);
+-		part->remote_GPs = NULL;
+-		kfree(part->local_GPs_base);
+-		part->local_GPs = NULL;
+-		kfree(part->channels);
+-		part->channels = NULL;
+-		return xpcNoMemory;
+-	}
+-
+-
+-	xpc_initialize_channels(part, partid);
+-
+-	atomic_set(&part->nchannels_active, 0);
+-	atomic_set(&part->nchannels_engaged, 0);
+-
+-
+-	/* local_IPI_amo were set to 0 by an earlier memset() */
+-
+-	/* Initialize this partitions AMO_t structure */
+-	part->local_IPI_amo_va = xpc_IPI_init(partid);
+-
+-	spin_lock_init(&part->IPI_lock);
+-
+-	atomic_set(&part->channel_mgr_requests, 1);
+-	init_waitqueue_head(&part->channel_mgr_wq);
+-
+-	sprintf(part->IPI_owner, "xpc%02d", partid);
+-	ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, IRQF_SHARED,
+-				part->IPI_owner, (void *) (u64) partid);
+-	if (ret != 0) {
+-		dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
+-			"errno=%d\n", -ret);
+-		kfree(part->remote_openclose_args_base);
+-		part->remote_openclose_args = NULL;
+-		kfree(part->local_openclose_args_base);
+-		part->local_openclose_args = NULL;
+-		kfree(part->remote_GPs_base);
+-		part->remote_GPs = NULL;
+-		kfree(part->local_GPs_base);
+-		part->local_GPs = NULL;
+-		kfree(part->channels);
+-		part->channels = NULL;
+-		return xpcLackOfResources;
+-	}
+-
+-	/* Setup a timer to check for dropped IPIs */
+-	timer = &part->dropped_IPI_timer;
+-	init_timer(timer);
+-	timer->function = (void (*)(unsigned long)) xpc_dropped_IPI_check;
+-	timer->data = (unsigned long) part;
+-	timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT;
+-	add_timer(timer);
+-
+-	/*
+-	 * With the setting of the partition setup_state to XPC_P_SETUP, we're
+-	 * declaring that this partition is ready to go.
+-	 */
+-	part->setup_state = XPC_P_SETUP;
+-
+-
+-	/*
+-	 * Setup the per partition specific variables required by the
+-	 * remote partition to establish channel connections with us.
+-	 *
+-	 * The setting of the magic # indicates that these per partition
+-	 * specific variables are ready to be used.
+-	 */
+-	xpc_vars_part[partid].GPs_pa = __pa(part->local_GPs);
+-	xpc_vars_part[partid].openclose_args_pa =
+-					__pa(part->local_openclose_args);
+-	xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va);
+-	cpuid = raw_smp_processor_id();	/* any CPU in this partition will do */
+-	xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(cpuid);
+-	xpc_vars_part[partid].IPI_phys_cpuid = cpu_physical_id(cpuid);
+-	xpc_vars_part[partid].nchannels = part->nchannels;
+-	xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
+-
+-	return xpcSuccess;
+-}
+-
+-
+-/*
+- * Create a wrapper that hides the underlying mechanism for pulling a cacheline
+- * (or multiple cachelines) from a remote partition.
+- *
+- * src must be a cacheline aligned physical address on the remote partition.
+- * dst must be a cacheline aligned virtual address on this partition.
+- * cnt must be an cacheline sized
+- */
+-static enum xpc_retval
+-xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst,
+-				const void *src, size_t cnt)
+-{
+-	bte_result_t bte_ret;
+-
+-
+-	DBUG_ON((u64) src != L1_CACHE_ALIGN((u64) src));
+-	DBUG_ON((u64) dst != L1_CACHE_ALIGN((u64) dst));
+-	DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
+-
+-	if (part->act_state == XPC_P_DEACTIVATING) {
+-		return part->reason;
+-	}
+-
+-	bte_ret = xp_bte_copy((u64) src, (u64) dst, (u64) cnt,
+-					(BTE_NORMAL | BTE_WACQUIRE), NULL);
+-	if (bte_ret == BTE_SUCCESS) {
+-		return xpcSuccess;
+-	}
+-
+-	dev_dbg(xpc_chan, "xp_bte_copy() from partition %d failed, ret=%d\n",
+-		XPC_PARTID(part), bte_ret);
+-
+-	return xpc_map_bte_errors(bte_ret);
+-}
+-
+-
+-/*
+- * Pull the remote per partition specific variables from the specified
+- * partition.
+- */
+-enum xpc_retval
+-xpc_pull_remote_vars_part(struct xpc_partition *part)
+-{
+-	u8 buffer[L1_CACHE_BYTES * 2];
+-	struct xpc_vars_part *pulled_entry_cacheline =
+-			(struct xpc_vars_part *) L1_CACHE_ALIGN((u64) buffer);
+-	struct xpc_vars_part *pulled_entry;
+-	u64 remote_entry_cacheline_pa, remote_entry_pa;
+-	partid_t partid = XPC_PARTID(part);
+-	enum xpc_retval ret;
+-
+-
+-	/* pull the cacheline that contains the variables we're interested in */
+-
+-	DBUG_ON(part->remote_vars_part_pa !=
+-				L1_CACHE_ALIGN(part->remote_vars_part_pa));
+-	DBUG_ON(sizeof(struct xpc_vars_part) != L1_CACHE_BYTES / 2);
+-
+-	remote_entry_pa = part->remote_vars_part_pa +
+-			sn_partition_id * sizeof(struct xpc_vars_part);
+-
+-	remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
+-
+-	pulled_entry = (struct xpc_vars_part *) ((u64) pulled_entry_cacheline +
+-				(remote_entry_pa & (L1_CACHE_BYTES - 1)));
+-
+-	ret = xpc_pull_remote_cachelines(part, pulled_entry_cacheline,
+-					(void *) remote_entry_cacheline_pa,
+-					L1_CACHE_BYTES);
+-	if (ret != xpcSuccess) {
+-		dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
+-			"partition %d, ret=%d\n", partid, ret);
+-		return ret;
+-	}
+-
+-
+-	/* see if they've been set up yet */
+-
+-	if (pulled_entry->magic != XPC_VP_MAGIC1 &&
+-				pulled_entry->magic != XPC_VP_MAGIC2) {
+-
+-		if (pulled_entry->magic != 0) {
+-			dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
+-				"partition %d has bad magic value (=0x%lx)\n",
+-				partid, sn_partition_id, pulled_entry->magic);
+-			return xpcBadMagic;
+-		}
+-
+-		/* they've not been initialized yet */
+-		return xpcRetry;
+-	}
+-
+-	if (xpc_vars_part[partid].magic == XPC_VP_MAGIC1) {
+-
+-		/* validate the variables */
+-
+-		if (pulled_entry->GPs_pa == 0 ||
+-				pulled_entry->openclose_args_pa == 0 ||
+-					pulled_entry->IPI_amo_pa == 0) {
+-
+-			dev_err(xpc_chan, "partition %d's XPC vars_part for "
+-				"partition %d are not valid\n", partid,
+-				sn_partition_id);
+-			return xpcInvalidAddress;
+-		}
+-
+-		/* the variables we imported look to be valid */
+-
+-		part->remote_GPs_pa = pulled_entry->GPs_pa;
+-		part->remote_openclose_args_pa =
+-					pulled_entry->openclose_args_pa;
+-		part->remote_IPI_amo_va =
+-				      (AMO_t *) __va(pulled_entry->IPI_amo_pa);
+-		part->remote_IPI_nasid = pulled_entry->IPI_nasid;
+-		part->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid;
+-
+-		if (part->nchannels > pulled_entry->nchannels) {
+-			part->nchannels = pulled_entry->nchannels;
+-		}
+-
+-		/* let the other side know that we've pulled their variables */
+-
+-		xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
+-	}
+-
+-	if (pulled_entry->magic == XPC_VP_MAGIC1) {
+-		return xpcRetry;
+-	}
+-
+-	return xpcSuccess;
+-}
+-
+-
+-/*
+- * Get the IPI flags and pull the openclose args and/or remote GPs as needed.
+- */
+-static u64
+-xpc_get_IPI_flags(struct xpc_partition *part)
+-{
+-	unsigned long irq_flags;
+-	u64 IPI_amo;
+-	enum xpc_retval ret;
+-
+-
+-	/*
+-	 * See if there are any IPI flags to be handled.
+-	 */
+-
+-	spin_lock_irqsave(&part->IPI_lock, irq_flags);
+-	if ((IPI_amo = part->local_IPI_amo) != 0) {
+-		part->local_IPI_amo = 0;
+-	}
+-	spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
+-
+-
+-	if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) {
+-		ret = xpc_pull_remote_cachelines(part,
+-					part->remote_openclose_args,
+-					(void *) part->remote_openclose_args_pa,
+-					XPC_OPENCLOSE_ARGS_SIZE);
+-		if (ret != xpcSuccess) {
+-			XPC_DEACTIVATE_PARTITION(part, ret);
+-
+-			dev_dbg(xpc_chan, "failed to pull openclose args from "
+-				"partition %d, ret=%d\n", XPC_PARTID(part),
+-				ret);
+-
+-			/* don't bother processing IPIs anymore */
+-			IPI_amo = 0;
+-		}
+-	}
+-
+-	if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) {
+-		ret = xpc_pull_remote_cachelines(part, part->remote_GPs,
+-						(void *) part->remote_GPs_pa,
+-						XPC_GP_SIZE);
+-		if (ret != xpcSuccess) {
+-			XPC_DEACTIVATE_PARTITION(part, ret);
+-
+-			dev_dbg(xpc_chan, "failed to pull GPs from partition "
+-				"%d, ret=%d\n", XPC_PARTID(part), ret);
+-
+-			/* don't bother processing IPIs anymore */
+-			IPI_amo = 0;
+-		}
+-	}
+-
+-	return IPI_amo;
+-}
+-
+-
+-/*
+- * Allocate the local message queue and the notify queue.
+- */
+-static enum xpc_retval
+-xpc_allocate_local_msgqueue(struct xpc_channel *ch)
+-{
+-	unsigned long irq_flags;
+-	int nentries;
+-	size_t nbytes;
+-
+-
+-	// >>> may want to check for ch->flags & XPC_C_DISCONNECTING between
+-	// >>> iterations of the for-loop, bail if set?
+-
+-	// >>> should we impose a minimum #of entries? like 4 or 8?
+-	for (nentries = ch->local_nentries; nentries > 0; nentries--) {
+-
+-		nbytes = nentries * ch->msg_size;
+-		ch->local_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
+-						GFP_KERNEL,
+-						&ch->local_msgqueue_base);
+-		if (ch->local_msgqueue == NULL) {
+-			continue;
+-		}
+-
+-		nbytes = nentries * sizeof(struct xpc_notify);
+-		ch->notify_queue = kzalloc(nbytes, GFP_KERNEL);
+-		if (ch->notify_queue == NULL) {
+-			kfree(ch->local_msgqueue_base);
+-			ch->local_msgqueue = NULL;
+-			continue;
+-		}
+-
+-		spin_lock_irqsave(&ch->lock, irq_flags);
+-		if (nentries < ch->local_nentries) {
+-			dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
+-				"partid=%d, channel=%d\n", nentries,
+-				ch->local_nentries, ch->partid, ch->number);
+-
+-			ch->local_nentries = nentries;
+-		}
+-		spin_unlock_irqrestore(&ch->lock, irq_flags);
+-		return xpcSuccess;
+-	}
+-
+-	dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
+-		"queue, partid=%d, channel=%d\n", ch->partid, ch->number);
+-	return xpcNoMemory;
+-}
+-
+-
+-/*
+- * Allocate the cached remote message queue.
+- */
+-static enum xpc_retval
+-xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
+-{
+-	unsigned long irq_flags;
+-	int nentries;
+-	size_t nbytes;
+-
+-
+-	DBUG_ON(ch->remote_nentries <= 0);
+-
+-	// >>> may want to check for ch->flags & XPC_C_DISCONNECTING between
+-	// >>> iterations of the for-loop, bail if set?
+-
+-	// >>> should we impose a minimum #of entries? like 4 or 8?
+-	for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
+-
+-		nbytes = nentries * ch->msg_size;
+-		ch->remote_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
+-						GFP_KERNEL,
+-						&ch->remote_msgqueue_base);
+-		if (ch->remote_msgqueue == NULL) {
+-			continue;
+-		}
+-
+-		spin_lock_irqsave(&ch->lock, irq_flags);
+-		if (nentries < ch->remote_nentries) {
+-			dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
+-				"partid=%d, channel=%d\n", nentries,
+-				ch->remote_nentries, ch->partid, ch->number);
+-
+-			ch->remote_nentries = nentries;
+-		}
+-		spin_unlock_irqrestore(&ch->lock, irq_flags);
+-		return xpcSuccess;
+-	}
+-
+-	dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
+-		"partid=%d, channel=%d\n", ch->partid, ch->number);
+-	return xpcNoMemory;
+-}
+-
+-
+-/*
+- * Allocate message queues and other stuff associated with a channel.
+- *
+- * Note: Assumes all of the channel sizes are filled in.
+- */
+-static enum xpc_retval
+-xpc_allocate_msgqueues(struct xpc_channel *ch)
+-{
+-	unsigned long irq_flags;
+-	enum xpc_retval ret;
+-
+-
+-	DBUG_ON(ch->flags & XPC_C_SETUP);
+-
+-	if ((ret = xpc_allocate_local_msgqueue(ch)) != xpcSuccess) {
+-		return ret;
+-	}
+-
+-	if ((ret = xpc_allocate_remote_msgqueue(ch)) != xpcSuccess) {
+-		kfree(ch->local_msgqueue_base);
+-		ch->local_msgqueue = NULL;
+-		kfree(ch->notify_queue);
+-		ch->notify_queue = NULL;
+-		return ret;
+-	}
+-
+-	spin_lock_irqsave(&ch->lock, irq_flags);
+-	ch->flags |= XPC_C_SETUP;
+-	spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+-	return xpcSuccess;
+-}
+-
+-
+-/*
+- * Process a connect message from a remote partition.
+- *
+- * Note: xpc_process_connect() is expecting to be called with the
+- * spin_lock_irqsave held and will leave it locked upon return.
+- */
+-static void
+-xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+-	enum xpc_retval ret;
+-
+-
+-	DBUG_ON(!spin_is_locked(&ch->lock));
+-
+-	if (!(ch->flags & XPC_C_OPENREQUEST) ||
+-				!(ch->flags & XPC_C_ROPENREQUEST)) {
+-		/* nothing more to do for now */
+-		return;
+-	}
+-	DBUG_ON(!(ch->flags & XPC_C_CONNECTING));
+-
+-	if (!(ch->flags & XPC_C_SETUP)) {
+-		spin_unlock_irqrestore(&ch->lock, *irq_flags);
+-		ret = xpc_allocate_msgqueues(ch);
+-		spin_lock_irqsave(&ch->lock, *irq_flags);
+-
+-		if (ret != xpcSuccess) {
+-			XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);
+-		}
+-		if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) {
+-			return;
+-		}
+-
+-		DBUG_ON(!(ch->flags & XPC_C_SETUP));
+-		DBUG_ON(ch->local_msgqueue == NULL);
+-		DBUG_ON(ch->remote_msgqueue == NULL);
+-	}
+-
+-	if (!(ch->flags & XPC_C_OPENREPLY)) {
+-		ch->flags |= XPC_C_OPENREPLY;
+-		xpc_IPI_send_openreply(ch, irq_flags);
+-	}
+-
+-	if (!(ch->flags & XPC_C_ROPENREPLY)) {
+-		return;
+-	}
+-
+-	DBUG_ON(ch->remote_msgqueue_pa == 0);
+-
+-	ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP);	/* clear all else */
+-
+-	dev_info(xpc_chan, "channel %d to partition %d connected\n",
+-		ch->number, ch->partid);
+-
+-	spin_unlock_irqrestore(&ch->lock, *irq_flags);
+-	xpc_create_kthreads(ch, 1, 0);
+-	spin_lock_irqsave(&ch->lock, *irq_flags);
+-}
+-
+-
+-/*
+- * Notify those who wanted to be notified upon delivery of their message.
+- */
+-static void
+-xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
+-{
+-	struct xpc_notify *notify;
+-	u8 notify_type;
+-	s64 get = ch->w_remote_GP.get - 1;
+-
+-
+-	while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
+-
+-		notify = &ch->notify_queue[get % ch->local_nentries];
+-
+-		/*
+-		 * See if the notify entry indicates it was associated with
+-		 * a message who's sender wants to be notified. It is possible
+-		 * that it is, but someone else is doing or has done the
+-		 * notification.
+-		 */
+-		notify_type = notify->type;
+-		if (notify_type == 0 ||
+-				cmpxchg(&notify->type, notify_type, 0) !=
+-								notify_type) {
+-			continue;
+-		}
+-
+-		DBUG_ON(notify_type != XPC_N_CALL);
+-
+-		atomic_dec(&ch->n_to_notify);
+-
+-		if (notify->func != NULL) {
+-			dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
+-				"msg_number=%ld, partid=%d, channel=%d\n",
+-				(void *) notify, get, ch->partid, ch->number);
+-
+-			notify->func(reason, ch->partid, ch->number,
+-								notify->key);
+-
+-			dev_dbg(xpc_chan, "notify->func() returned, "
+-				"notify=0x%p, msg_number=%ld, partid=%d, "
+-				"channel=%d\n", (void *) notify, get,
+-				ch->partid, ch->number);
+-		}
+-	}
+-}
+-
+-
+-/*
+- * Free up message queues and other stuff that were allocated for the specified
+- * channel.
+- *
+- * Note: ch->reason and ch->reason_line are left set for debugging purposes,
+- * they're cleared when XPC_C_DISCONNECTED is cleared.
+- */
+-static void
+-xpc_free_msgqueues(struct xpc_channel *ch)
+-{
+-	DBUG_ON(!spin_is_locked(&ch->lock));
+-	DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
+-
+-	ch->remote_msgqueue_pa = 0;
+-	ch->func = NULL;
+-	ch->key = NULL;
+-	ch->msg_size = 0;
+-	ch->local_nentries = 0;
+-	ch->remote_nentries = 0;
+-	ch->kthreads_assigned_limit = 0;
+-	ch->kthreads_idle_limit = 0;
+-
+-	ch->local_GP->get = 0;
+-	ch->local_GP->put = 0;
+-	ch->remote_GP.get = 0;
+-	ch->remote_GP.put = 0;
+-	ch->w_local_GP.get = 0;
+-	ch->w_local_GP.put = 0;
+-	ch->w_remote_GP.get = 0;
+-	ch->w_remote_GP.put = 0;
+-	ch->next_msg_to_pull = 0;
+-
+-	if (ch->flags & XPC_C_SETUP) {
+-		ch->flags &= ~XPC_C_SETUP;
+-
+-		dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
+-			ch->flags, ch->partid, ch->number);
+-
+-		kfree(ch->local_msgqueue_base);
+-		ch->local_msgqueue = NULL;
+-		kfree(ch->remote_msgqueue_base);
+-		ch->remote_msgqueue = NULL;
+-		kfree(ch->notify_queue);
+-		ch->notify_queue = NULL;
+-	}
+-}
+-
+-
+-/*
+- * spin_lock_irqsave() is expected to be held on entry.
+- */
+-static void
+-xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+-	struct xpc_partition *part = &xpc_partitions[ch->partid];
+-	u32 channel_was_connected = (ch->flags & XPC_C_WASCONNECTED);
+-
+-
+-	DBUG_ON(!spin_is_locked(&ch->lock));
+-
+-	if (!(ch->flags & XPC_C_DISCONNECTING)) {
+-		return;
+-	}
+-
+-	DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+-
+-	/* make sure all activity has settled down first */
+-
+-	if (atomic_read(&ch->kthreads_assigned) > 0 ||
+-				atomic_read(&ch->references) > 0) {
+-		return;
+-	}
+-	DBUG_ON((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+-			!(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE));
+-
+-	if (part->act_state == XPC_P_DEACTIVATING) {
+-		/* can't proceed until the other side disengages from us */
+-		if (xpc_partition_engaged(1UL << ch->partid)) {
+-			return;
+-		}
+-
+-	} else {
+-
+-		/* as long as the other side is up do the full protocol */
+-
+-		if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
+-			return;
+-		}
+-
+-		if (!(ch->flags & XPC_C_CLOSEREPLY)) {
+-			ch->flags |= XPC_C_CLOSEREPLY;
+-			xpc_IPI_send_closereply(ch, irq_flags);
+-		}
+-
+-		if (!(ch->flags & XPC_C_RCLOSEREPLY)) {
+-			return;
+-		}
+-	}
+-
+-	/* wake those waiting for notify completion */
+-	if (atomic_read(&ch->n_to_notify) > 0) {
+-		/* >>> we do callout while holding ch->lock */
+-		xpc_notify_senders(ch, ch->reason, ch->w_local_GP.put);
+-	}
+-
+-	/* both sides are disconnected now */
+-
+-	if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) {
+-		spin_unlock_irqrestore(&ch->lock, *irq_flags);
+-		xpc_disconnect_callout(ch, xpcDisconnected);
+-		spin_lock_irqsave(&ch->lock, *irq_flags);
+-	}
+-
+-	/* it's now safe to free the channel's message queues */
+-	xpc_free_msgqueues(ch);
+-
+-	/* mark disconnected, clear all other flags except XPC_C_WDISCONNECT */
+-	ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT));
+-
+-	atomic_dec(&part->nchannels_active);
+-
+-	if (channel_was_connected) {
+-		dev_info(xpc_chan, "channel %d to partition %d disconnected, "
+-			"reason=%d\n", ch->number, ch->partid, ch->reason);
+-	}
+-
+-	if (ch->flags & XPC_C_WDISCONNECT) {
+-		/* we won't lose the CPU since we're holding ch->lock */
+-		complete(&ch->wdisconnect_wait);
+-	} else if (ch->delayed_IPI_flags) {
+-		if (part->act_state != XPC_P_DEACTIVATING) {
+-			/* time to take action on any delayed IPI flags */
+-			spin_lock(&part->IPI_lock);
+-			XPC_SET_IPI_FLAGS(part->local_IPI_amo, ch->number,
+-							ch->delayed_IPI_flags);
+-			spin_unlock(&part->IPI_lock);
+-		}
+-		ch->delayed_IPI_flags = 0;
+-	}
+-}
+-
+-
+-/*
+- * Process a change in the channel's remote connection state.
+- */
+-static void
+-xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
+-				u8 IPI_flags)
+-{
+-	unsigned long irq_flags;
+-	struct xpc_openclose_args *args =
+-				&part->remote_openclose_args[ch_number];
+-	struct xpc_channel *ch = &part->channels[ch_number];
+-	enum xpc_retval reason;
+-
+-
+-
+-	spin_lock_irqsave(&ch->lock, irq_flags);
+-
+-again:
+-
+-	if ((ch->flags & XPC_C_DISCONNECTED) &&
+-					(ch->flags & XPC_C_WDISCONNECT)) {
+-		/*
+-		 * Delay processing IPI flags until thread waiting disconnect
+-		 * has had a chance to see that the channel is disconnected.
+-		 */
+-		ch->delayed_IPI_flags |= IPI_flags;
+-		spin_unlock_irqrestore(&ch->lock, irq_flags);
+-		return;
+-	}
+-
+-
+-	if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
+-
+-		dev_dbg(xpc_chan, "XPC_IPI_CLOSEREQUEST (reason=%d) received "
+-			"from partid=%d, channel=%d\n", args->reason,
+-			ch->partid, ch->number);
+-
+-		/*
+-		 * If RCLOSEREQUEST is set, we're probably waiting for
+-		 * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
+-		 * with this RCLOSEREQUEST in the IPI_flags.
+-		 */
+-
+-		if (ch->flags & XPC_C_RCLOSEREQUEST) {
+-			DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
+-			DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+-			DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));
+-			DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);
+-
+-			DBUG_ON(!(IPI_flags & XPC_IPI_CLOSEREPLY));
+-			IPI_flags &= ~XPC_IPI_CLOSEREPLY;
+-			ch->flags |= XPC_C_RCLOSEREPLY;
+-
+-			/* both sides have finished disconnecting */
+-			xpc_process_disconnect(ch, &irq_flags);
+-			DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
+-			goto again;
+-		}
+-
+-		if (ch->flags & XPC_C_DISCONNECTED) {
+-			if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
+-				if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo,
+-					 ch_number) & XPC_IPI_OPENREQUEST)) {
+-
+-					DBUG_ON(ch->delayed_IPI_flags != 0);
+-					spin_lock(&part->IPI_lock);
+-					XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+-							ch_number,
+-							XPC_IPI_CLOSEREQUEST);
+-					spin_unlock(&part->IPI_lock);
+-				}
+-				spin_unlock_irqrestore(&ch->lock, irq_flags);
+-				return;
+-			}
+-
+-			XPC_SET_REASON(ch, 0, 0);
+-			ch->flags &= ~XPC_C_DISCONNECTED;
+-
+-			atomic_inc(&part->nchannels_active);
+-			ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
+-		}
+-
+-		IPI_flags &= ~(XPC_IPI_OPENREQUEST | XPC_IPI_OPENREPLY);
+-
+-		/*
+-		 * The meaningful CLOSEREQUEST connection state fields are:
+-		 *      reason = reason connection is to be closed
+-		 */
+-
+-		ch->flags |= XPC_C_RCLOSEREQUEST;
+-
+-		if (!(ch->flags & XPC_C_DISCONNECTING)) {
+-			reason = args->reason;
+-			if (reason <= xpcSuccess || reason > xpcUnknownReason) {
+-				reason = xpcUnknownReason;
+-			} else if (reason == xpcUnregistering) {
+-				reason = xpcOtherUnregistering;
+-			}
+-
+-			XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
+-
+-			DBUG_ON(IPI_flags & XPC_IPI_CLOSEREPLY);
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			return;
+-		}
+-
+-		xpc_process_disconnect(ch, &irq_flags);
+-	}
+-
+-
+-	if (IPI_flags & XPC_IPI_CLOSEREPLY) {
+-
+-		dev_dbg(xpc_chan, "XPC_IPI_CLOSEREPLY received from partid=%d,"
+-			" channel=%d\n", ch->partid, ch->number);
+-
+-		if (ch->flags & XPC_C_DISCONNECTED) {
+-			DBUG_ON(part->act_state != XPC_P_DEACTIVATING);
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			return;
+-		}
+-
+-		DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+-
+-		if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
+-			if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo, ch_number)
+-						& XPC_IPI_CLOSEREQUEST)) {
+-
+-				DBUG_ON(ch->delayed_IPI_flags != 0);
+-				spin_lock(&part->IPI_lock);
+-				XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+-						ch_number, XPC_IPI_CLOSEREPLY);
+-				spin_unlock(&part->IPI_lock);
+-			}
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			return;
+-		}
+-
+-		ch->flags |= XPC_C_RCLOSEREPLY;
+-
+-		if (ch->flags & XPC_C_CLOSEREPLY) {
+-			/* both sides have finished disconnecting */
+-			xpc_process_disconnect(ch, &irq_flags);
+-		}
+-	}
+-
+-
+-	if (IPI_flags & XPC_IPI_OPENREQUEST) {
+-
+-		dev_dbg(xpc_chan, "XPC_IPI_OPENREQUEST (msg_size=%d, "
+-			"local_nentries=%d) received from partid=%d, "
+-			"channel=%d\n", args->msg_size, args->local_nentries,
+-			ch->partid, ch->number);
+-
+-		if (part->act_state == XPC_P_DEACTIVATING ||
+-					(ch->flags & XPC_C_ROPENREQUEST)) {
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			return;
+-		}
+-
+-		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
+-			ch->delayed_IPI_flags |= XPC_IPI_OPENREQUEST;
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			return;
+-		}
+-		DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |
+-							XPC_C_OPENREQUEST)));
+-		DBUG_ON(ch->flags & (XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
+-					XPC_C_OPENREPLY | XPC_C_CONNECTED));
+-
+-		/*
+-		 * The meaningful OPENREQUEST connection state fields are:
+-		 *      msg_size = size of channel's messages in bytes
+-		 *      local_nentries = remote partition's local_nentries
+-		 */
+-		if (args->msg_size == 0 || args->local_nentries == 0) {
+-			/* assume OPENREQUEST was delayed by mistake */
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			return;
+-		}
+-
+-		ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
+-		ch->remote_nentries = args->local_nentries;
+-
+-
+-		if (ch->flags & XPC_C_OPENREQUEST) {
+-			if (args->msg_size != ch->msg_size) {
+-				XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
+-								&irq_flags);
+-				spin_unlock_irqrestore(&ch->lock, irq_flags);
+-				return;
+-			}
+-		} else {
+-			ch->msg_size = args->msg_size;
+-
+-			XPC_SET_REASON(ch, 0, 0);
+-			ch->flags &= ~XPC_C_DISCONNECTED;
+-
+-			atomic_inc(&part->nchannels_active);
+-		}
+-
+-		xpc_process_connect(ch, &irq_flags);
+-	}
+-
+-
+-	if (IPI_flags & XPC_IPI_OPENREPLY) {
+-
+-		dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY (local_msgqueue_pa=0x%lx, "
+-			"local_nentries=%d, remote_nentries=%d) received from "
+-			"partid=%d, channel=%d\n", args->local_msgqueue_pa,
+-			args->local_nentries, args->remote_nentries,
+-			ch->partid, ch->number);
+-
+-		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			return;
+-		}
+-		if (!(ch->flags & XPC_C_OPENREQUEST)) {
+-			XPC_DISCONNECT_CHANNEL(ch, xpcOpenCloseError,
+-								&irq_flags);
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			return;
+-		}
+-
+-		DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
+-		DBUG_ON(ch->flags & XPC_C_CONNECTED);
+-
+-		/*
+-		 * The meaningful OPENREPLY connection state fields are:
+-		 *      local_msgqueue_pa = physical address of remote
+-		 *			    partition's local_msgqueue
+-		 *      local_nentries = remote partition's local_nentries
+-		 *      remote_nentries = remote partition's remote_nentries
+-		 */
+-		DBUG_ON(args->local_msgqueue_pa == 0);
+-		DBUG_ON(args->local_nentries == 0);
+-		DBUG_ON(args->remote_nentries == 0);
+-
+-		ch->flags |= XPC_C_ROPENREPLY;
+-		ch->remote_msgqueue_pa = args->local_msgqueue_pa;
+-
+-		if (args->local_nentries < ch->remote_nentries) {
+-			dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
+-				"remote_nentries=%d, old remote_nentries=%d, "
+-				"partid=%d, channel=%d\n",
+-				args->local_nentries, ch->remote_nentries,
+-				ch->partid, ch->number);
+-
+-			ch->remote_nentries = args->local_nentries;
+-		}
+-		if (args->remote_nentries < ch->local_nentries) {
+-			dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
+-				"local_nentries=%d, old local_nentries=%d, "
+-				"partid=%d, channel=%d\n",
+-				args->remote_nentries, ch->local_nentries,
+-				ch->partid, ch->number);
+-
+-			ch->local_nentries = args->remote_nentries;
+-		}
+-
+-		xpc_process_connect(ch, &irq_flags);
+-	}
+-
+-	spin_unlock_irqrestore(&ch->lock, irq_flags);
+-}
+-
+-
+-/*
+- * Attempt to establish a channel connection to a remote partition.
+- */
+-static enum xpc_retval
+-xpc_connect_channel(struct xpc_channel *ch)
+-{
+-	unsigned long irq_flags;
+-	struct xpc_registration *registration = &xpc_registrations[ch->number];
+-
+-
+-	if (mutex_trylock(&registration->mutex) == 0) {
+-		return xpcRetry;
+-	}
+-
+-	if (!XPC_CHANNEL_REGISTERED(ch->number)) {
+-		mutex_unlock(&registration->mutex);
+-		return xpcUnregistered;
+-	}
+-
+-	spin_lock_irqsave(&ch->lock, irq_flags);
+-
+-	DBUG_ON(ch->flags & XPC_C_CONNECTED);
+-	DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
+-
+-	if (ch->flags & XPC_C_DISCONNECTING) {
+-		spin_unlock_irqrestore(&ch->lock, irq_flags);
+-		mutex_unlock(&registration->mutex);
+-		return ch->reason;
+-	}
+-
+-
+-	/* add info from the channel connect registration to the channel */
+-
+-	ch->kthreads_assigned_limit = registration->assigned_limit;
+-	ch->kthreads_idle_limit = registration->idle_limit;
+-	DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
+-	DBUG_ON(atomic_read(&ch->kthreads_idle) != 0);
+-	DBUG_ON(atomic_read(&ch->kthreads_active) != 0);
+-
+-	ch->func = registration->func;
+-	DBUG_ON(registration->func == NULL);
+-	ch->key = registration->key;
+-
+-	ch->local_nentries = registration->nentries;
+-
+-	if (ch->flags & XPC_C_ROPENREQUEST) {
+-		if (registration->msg_size != ch->msg_size) {
+-			/* the local and remote sides aren't the same */
+-
+-			/*
+-			 * Because XPC_DISCONNECT_CHANNEL() can block we're
+-			 * forced to up the registration sema before we unlock
+-			 * the channel lock. But that's okay here because we're
+-			 * done with the part that required the registration
+-			 * sema. XPC_DISCONNECT_CHANNEL() requires that the
+-			 * channel lock be locked and will unlock and relock
+-			 * the channel lock as needed.
+-			 */
+-			mutex_unlock(&registration->mutex);
+-			XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
+-								&irq_flags);
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			return xpcUnequalMsgSizes;
+-		}
+-	} else {
+-		ch->msg_size = registration->msg_size;
+-
+-		XPC_SET_REASON(ch, 0, 0);
+-		ch->flags &= ~XPC_C_DISCONNECTED;
+-
+-		atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
+-	}
+-
+-	mutex_unlock(&registration->mutex);
+-
+-
+-	/* initiate the connection */
+-
+-	ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
+-	xpc_IPI_send_openrequest(ch, &irq_flags);
+-
+-	xpc_process_connect(ch, &irq_flags);
+-
+-	spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+-	return xpcSuccess;
+-}
+-
+-
+-/*
+- * Clear some of the msg flags in the local message queue.
+- */
+-static inline void
+-xpc_clear_local_msgqueue_flags(struct xpc_channel *ch)
+-{
+-	struct xpc_msg *msg;
+-	s64 get;
+-
+-
+-	get = ch->w_remote_GP.get;
+-	do {
+-		msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+-				(get % ch->local_nentries) * ch->msg_size);
+-		msg->flags = 0;
+-	} while (++get < (volatile s64) ch->remote_GP.get);
+-}
+-
+-
+-/*
+- * Clear some of the msg flags in the remote message queue.
+- */
+-static inline void
+-xpc_clear_remote_msgqueue_flags(struct xpc_channel *ch)
+-{
+-	struct xpc_msg *msg;
+-	s64 put;
+-
+-
+-	put = ch->w_remote_GP.put;
+-	do {
+-		msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+-				(put % ch->remote_nentries) * ch->msg_size);
+-		msg->flags = 0;
+-	} while (++put < (volatile s64) ch->remote_GP.put);
+-}
+-
+-
+-static void
+-xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
+-{
+-	struct xpc_channel *ch = &part->channels[ch_number];
+-	int nmsgs_sent;
+-
+-
+-	ch->remote_GP = part->remote_GPs[ch_number];
+-
+-
+-	/* See what, if anything, has changed for each connected channel */
+-
+-	xpc_msgqueue_ref(ch);
+-
+-	if (ch->w_remote_GP.get == ch->remote_GP.get &&
+-				ch->w_remote_GP.put == ch->remote_GP.put) {
+-		/* nothing changed since GPs were last pulled */
+-		xpc_msgqueue_deref(ch);
+-		return;
+-	}
+-
+-	if (!(ch->flags & XPC_C_CONNECTED)){
+-		xpc_msgqueue_deref(ch);
+-		return;
+-	}
+-
+-
+-	/*
+-	 * First check to see if messages recently sent by us have been
+-	 * received by the other side. (The remote GET value will have
+-	 * changed since we last looked at it.)
+-	 */
+-
+-	if (ch->w_remote_GP.get != ch->remote_GP.get) {
+-
+-		/*
+-		 * We need to notify any senders that want to be notified
+-		 * that their sent messages have been received by their
+-		 * intended recipients. We need to do this before updating
+-		 * w_remote_GP.get so that we don't allocate the same message
+-		 * queue entries prematurely (see xpc_allocate_msg()).
+-		 */
+-		if (atomic_read(&ch->n_to_notify) > 0) {
+-			/*
+-			 * Notify senders that messages sent have been
+-			 * received and delivered by the other side.
+-			 */
+-			xpc_notify_senders(ch, xpcMsgDelivered,
+-							ch->remote_GP.get);
+-		}
+-
+-		/*
+-		 * Clear msg->flags in previously sent messages, so that
+-		 * they're ready for xpc_allocate_msg().
+-		 */
+-		xpc_clear_local_msgqueue_flags(ch);
+-
+-		ch->w_remote_GP.get = ch->remote_GP.get;
+-
+-		dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
+-			"channel=%d\n", ch->w_remote_GP.get, ch->partid,
+-			ch->number);
+-
+-		/*
+-		 * If anyone was waiting for message queue entries to become
+-		 * available, wake them up.
+-		 */
+-		if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+-			wake_up(&ch->msg_allocate_wq);
+-		}
+-	}
+-
+-
+-	/*
+-	 * Now check for newly sent messages by the other side. (The remote
+-	 * PUT value will have changed since we last looked at it.)
+-	 */
+-
+-	if (ch->w_remote_GP.put != ch->remote_GP.put) {
+-		/*
+-		 * Clear msg->flags in previously received messages, so that
+-		 * they're ready for xpc_get_deliverable_msg().
+-		 */
+-		xpc_clear_remote_msgqueue_flags(ch);
+-
+-		ch->w_remote_GP.put = ch->remote_GP.put;
+-
+-		dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
+-			"channel=%d\n", ch->w_remote_GP.put, ch->partid,
+-			ch->number);
+-
+-		nmsgs_sent = ch->w_remote_GP.put - ch->w_local_GP.get;
+-		if (nmsgs_sent > 0) {
+-			dev_dbg(xpc_chan, "msgs waiting to be copied and "
+-				"delivered=%d, partid=%d, channel=%d\n",
+-				nmsgs_sent, ch->partid, ch->number);
+-
+-			if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) {
+-				xpc_activate_kthreads(ch, nmsgs_sent);
+-			}
+-		}
+-	}
+-
+-	xpc_msgqueue_deref(ch);
+-}
+-
+-
+-void
+-xpc_process_channel_activity(struct xpc_partition *part)
+-{
+-	unsigned long irq_flags;
+-	u64 IPI_amo, IPI_flags;
+-	struct xpc_channel *ch;
+-	int ch_number;
+-	u32 ch_flags;
+-
+-
+-	IPI_amo = xpc_get_IPI_flags(part);
+-
+-	/*
+-	 * Initiate channel connections for registered channels.
+-	 *
+-	 * For each connected channel that has pending messages activate idle
+-	 * kthreads and/or create new kthreads as needed.
+-	 */
+-
+-	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+-		ch = &part->channels[ch_number];
+-
+-
+-		/*
+-		 * Process any open or close related IPI flags, and then deal
+-		 * with connecting or disconnecting the channel as required.
+-		 */
+-
+-		IPI_flags = XPC_GET_IPI_FLAGS(IPI_amo, ch_number);
+-
+-		if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_flags)) {
+-			xpc_process_openclose_IPI(part, ch_number, IPI_flags);
+-		}
+-
+-		ch_flags = ch->flags;	/* need an atomic snapshot of flags */
+-
+-		if (ch_flags & XPC_C_DISCONNECTING) {
+-			spin_lock_irqsave(&ch->lock, irq_flags);
+-			xpc_process_disconnect(ch, &irq_flags);
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			continue;
+-		}
+-
+-		if (part->act_state == XPC_P_DEACTIVATING) {
+-			continue;
+-		}
+-
+-		if (!(ch_flags & XPC_C_CONNECTED)) {
+-			if (!(ch_flags & XPC_C_OPENREQUEST)) {
+-				DBUG_ON(ch_flags & XPC_C_SETUP);
+-				(void) xpc_connect_channel(ch);
+-			} else {
+-				spin_lock_irqsave(&ch->lock, irq_flags);
+-				xpc_process_connect(ch, &irq_flags);
+-				spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			}
+-			continue;
+-		}
+-
+-
+-		/*
+-		 * Process any message related IPI flags, this may involve the
+-		 * activation of kthreads to deliver any pending messages sent
+-		 * from the other partition.
+-		 */
+-
+-		if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_flags)) {
+-			xpc_process_msg_IPI(part, ch_number);
+-		}
+-	}
+-}
+-
+-
+-/*
+- * XPC's heartbeat code calls this function to inform XPC that a partition is
+- * going down.  XPC responds by tearing down the XPartition Communication
+- * infrastructure used for the just downed partition.
+- *
+- * XPC's heartbeat code will never call this function and xpc_partition_up()
+- * at the same time. Nor will it ever make multiple calls to either function
+- * at the same time.
+- */
+-void
+-xpc_partition_going_down(struct xpc_partition *part, enum xpc_retval reason)
+-{
+-	unsigned long irq_flags;
+-	int ch_number;
+-	struct xpc_channel *ch;
+-
+-
+-	dev_dbg(xpc_chan, "deactivating partition %d, reason=%d\n",
+-		XPC_PARTID(part), reason);
+-
+-	if (!xpc_part_ref(part)) {
+-		/* infrastructure for this partition isn't currently set up */
+-		return;
+-	}
+-
+-
+-	/* disconnect channels associated with the partition going down */
+-
+-	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+-		ch = &part->channels[ch_number];
+-
+-		xpc_msgqueue_ref(ch);
+-		spin_lock_irqsave(&ch->lock, irq_flags);
+-
+-		XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
+-
+-		spin_unlock_irqrestore(&ch->lock, irq_flags);
+-		xpc_msgqueue_deref(ch);
+-	}
+-
+-	xpc_wakeup_channel_mgr(part);
+-
+-	xpc_part_deref(part);
+-}
+-
+-
+-/*
+- * Teardown the infrastructure necessary to support XPartition Communication
+- * between the specified remote partition and the local one.
+- */
+-void
+-xpc_teardown_infrastructure(struct xpc_partition *part)
+-{
+-	partid_t partid = XPC_PARTID(part);
+-
+-
+-	/*
+-	 * We start off by making this partition inaccessible to local
+-	 * processes by marking it as no longer setup. Then we make it
+-	 * inaccessible to remote processes by clearing the XPC per partition
+-	 * specific variable's magic # (which indicates that these variables
+-	 * are no longer valid) and by ignoring all XPC notify IPIs sent to
+-	 * this partition.
+-	 */
+-
+-	DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
+-	DBUG_ON(atomic_read(&part->nchannels_active) != 0);
+-	DBUG_ON(part->setup_state != XPC_P_SETUP);
+-	part->setup_state = XPC_P_WTEARDOWN;
+-
+-	xpc_vars_part[partid].magic = 0;
+-
+-
+-	free_irq(SGI_XPC_NOTIFY, (void *) (u64) partid);
+-
+-
+-	/*
+-	 * Before proceeding with the teardown we have to wait until all
+-	 * existing references cease.
+-	 */
+-	wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
+-
+-
+-	/* now we can begin tearing down the infrastructure */
+-
+-	part->setup_state = XPC_P_TORNDOWN;
+-
+-	/* in case we've still got outstanding timers registered... */
+-	del_timer_sync(&part->dropped_IPI_timer);
+-
+-	kfree(part->remote_openclose_args_base);
+-	part->remote_openclose_args = NULL;
+-	kfree(part->local_openclose_args_base);
+-	part->local_openclose_args = NULL;
+-	kfree(part->remote_GPs_base);
+-	part->remote_GPs = NULL;
+-	kfree(part->local_GPs_base);
+-	part->local_GPs = NULL;
+-	kfree(part->channels);
+-	part->channels = NULL;
+-	part->local_IPI_amo_va = NULL;
+-}
+-
+-
+-/*
+- * Called by XP at the time of channel connection registration to cause
+- * XPC to establish connections to all currently active partitions.
+- */
+-void
+-xpc_initiate_connect(int ch_number)
+-{
+-	partid_t partid;
+-	struct xpc_partition *part;
+-	struct xpc_channel *ch;
+-
+-
+-	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+-
+-	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+-		part = &xpc_partitions[partid];
+-
+-		if (xpc_part_ref(part)) {
+-			ch = &part->channels[ch_number];
+-
+-			/*
+-			 * Initiate the establishment of a connection on the
+-			 * newly registered channel to the remote partition.
+-			 */
+-			xpc_wakeup_channel_mgr(part);
+-			xpc_part_deref(part);
+-		}
+-	}
+-}
+-
+-
+-void
+-xpc_connected_callout(struct xpc_channel *ch)
+-{
+-	/* let the registerer know that a connection has been established */
+-
+-	if (ch->func != NULL) {
+-		dev_dbg(xpc_chan, "ch->func() called, reason=xpcConnected, "
+-			"partid=%d, channel=%d\n", ch->partid, ch->number);
+-
+-		ch->func(xpcConnected, ch->partid, ch->number,
+-				(void *) (u64) ch->local_nentries, ch->key);
+-
+-		dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "
+-			"partid=%d, channel=%d\n", ch->partid, ch->number);
+-	}
+-}
+-
+-
+-/*
+- * Called by XP at the time of channel connection unregistration to cause
+- * XPC to teardown all current connections for the specified channel.
+- *
+- * Before returning xpc_initiate_disconnect() will wait until all connections
+- * on the specified channel have been closed/torndown. So the caller can be
+- * assured that they will not be receiving any more callouts from XPC to the
+- * function they registered via xpc_connect().
+- *
+- * Arguments:
+- *
+- *	ch_number - channel # to unregister.
+- */
+-void
+-xpc_initiate_disconnect(int ch_number)
+-{
+-	unsigned long irq_flags;
+-	partid_t partid;
+-	struct xpc_partition *part;
+-	struct xpc_channel *ch;
+-
+-
+-	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+-
+-	/* initiate the channel disconnect for every active partition */
+-	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+-		part = &xpc_partitions[partid];
+-
+-		if (xpc_part_ref(part)) {
+-			ch = &part->channels[ch_number];
+-			xpc_msgqueue_ref(ch);
+-
+-			spin_lock_irqsave(&ch->lock, irq_flags);
+-
+-			if (!(ch->flags & XPC_C_DISCONNECTED)) {
+-				ch->flags |= XPC_C_WDISCONNECT;
+-
+-				XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
+-								&irq_flags);
+-			}
+-
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+-			xpc_msgqueue_deref(ch);
+-			xpc_part_deref(part);
+-		}
+-	}
+-
+-	xpc_disconnect_wait(ch_number);
+-}
+-
+-
+-/*
+- * To disconnect a channel, and reflect it back to all who may be waiting.
+- *
+- * An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
+- * xpc_process_disconnect(), and if set, XPC_C_WDISCONNECT is cleared by
+- * xpc_disconnect_wait().
+- *
+- * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON RETURN.
+- */
+-void
+-xpc_disconnect_channel(const int line, struct xpc_channel *ch,
+-			enum xpc_retval reason, unsigned long *irq_flags)
+-{
+-	u32 channel_was_connected = (ch->flags & XPC_C_CONNECTED);
+-
+-
+-	DBUG_ON(!spin_is_locked(&ch->lock));
+-
+-	if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
+-		return;
+-	}
+-	DBUG_ON(!(ch->flags & (XPC_C_CONNECTING | XPC_C_CONNECTED)));
+-
+-	dev_dbg(xpc_chan, "reason=%d, line=%d, partid=%d, channel=%d\n",
+-		reason, line, ch->partid, ch->number);
+-
+-	XPC_SET_REASON(ch, reason, line);
+-
+-	ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
+-	/* some of these may not have been set */
+-	ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |
+-			XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
+-			XPC_C_CONNECTING | XPC_C_CONNECTED);
+-
+-	xpc_IPI_send_closerequest(ch, irq_flags);
+-
+-	if (channel_was_connected) {
+-		ch->flags |= XPC_C_WASCONNECTED;
+-	}
+-
+-	spin_unlock_irqrestore(&ch->lock, *irq_flags);
+-
+-	/* wake all idle kthreads so they can exit */
+-	if (atomic_read(&ch->kthreads_idle) > 0) {
+-		wake_up_all(&ch->idle_wq);
+-
+-	} else if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+-			!(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
+-		/* start a kthread that will do the xpcDisconnecting callout */
+-		xpc_create_kthreads(ch, 1, 1);
+-	}
+-
+-	/* wake those waiting to allocate an entry from the local msg queue */
+-	if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+-		wake_up(&ch->msg_allocate_wq);
+-	}
+-
+-	spin_lock_irqsave(&ch->lock, *irq_flags);
+-}
+-
+-
+-void
+-xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason)
+-{
+-	/*
+-	 * Let the channel's registerer know that the channel is being
+-	 * disconnected. We don't want to do this if the registerer was never
+-	 * informed of a connection being made.
+-	 */
+-
+-	if (ch->func != NULL) {
+-		dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
+-			"channel=%d\n", reason, ch->partid, ch->number);
+-
+-		ch->func(reason, ch->partid, ch->number, NULL, ch->key);
+-
+-		dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
+-			"channel=%d\n", reason, ch->partid, ch->number);
+-	}
+-}
+-
+-
+-/*
+- * Wait for a message entry to become available for the specified channel,
+- * but don't wait any longer than 1 jiffy.
+- */
+-static enum xpc_retval
+-xpc_allocate_msg_wait(struct xpc_channel *ch)
+-{
+-	enum xpc_retval ret;
+-
+-
+-	if (ch->flags & XPC_C_DISCONNECTING) {
+-		DBUG_ON(ch->reason == xpcInterrupted);  // >>> Is this true?
+-		return ch->reason;
+-	}
+-
+-	atomic_inc(&ch->n_on_msg_allocate_wq);
+-	ret = interruptible_sleep_on_timeout(&ch->msg_allocate_wq, 1);
+-	atomic_dec(&ch->n_on_msg_allocate_wq);
+-
+-	if (ch->flags & XPC_C_DISCONNECTING) {
+-		ret = ch->reason;
+-		DBUG_ON(ch->reason == xpcInterrupted);  // >>> Is this true?
+-	} else if (ret == 0) {
+-		ret = xpcTimeout;
+-	} else {
+-		ret = xpcInterrupted;
+-	}
+-
+-	return ret;
+-}
+-
+-
+-/*
+- * Allocate an entry for a message from the message queue associated with the
+- * specified channel.
+- */
+-static enum xpc_retval
+-xpc_allocate_msg(struct xpc_channel *ch, u32 flags,
+-			struct xpc_msg **address_of_msg)
+-{
+-	struct xpc_msg *msg;
+-	enum xpc_retval ret;
+-	s64 put;
+-
+-
+-	/* this reference will be dropped in xpc_send_msg() */
+-	xpc_msgqueue_ref(ch);
+-
+-	if (ch->flags & XPC_C_DISCONNECTING) {
+-		xpc_msgqueue_deref(ch);
+-		return ch->reason;
+-	}
+-	if (!(ch->flags & XPC_C_CONNECTED)) {
+-		xpc_msgqueue_deref(ch);
+-		return xpcNotConnected;
+-	}
+-
+-
+-	/*
+-	 * Get the next available message entry from the local message queue.
+-	 * If none are available, we'll make sure that we grab the latest
+-	 * GP values.
+-	 */
+-	ret = xpcTimeout;
+-
+-	while (1) {
+-
+-		put = (volatile s64) ch->w_local_GP.put;
+-		if (put - (volatile s64) ch->w_remote_GP.get <
+-							ch->local_nentries) {
+-
+-			/* There are available message entries. We need to try
+-			 * to secure one for ourselves. We'll do this by trying
+-			 * to increment w_local_GP.put as long as someone else
+-			 * doesn't beat us to it. If they do, we'll have to
+-			 * try again.
+-		 	 */
+-			if (cmpxchg(&ch->w_local_GP.put, put, put + 1) ==
+-									put) {
+-				/* we got the entry referenced by put */
+-				break;
+-			}
+-			continue;	/* try again */
+-		}
+-
+-
+-		/*
+-		 * There aren't any available msg entries at this time.
+-		 *
+-		 * In waiting for a message entry to become available,
+-		 * we set a timeout in case the other side is not
+-		 * sending completion IPIs. This lets us fake an IPI
+-		 * that will cause the IPI handler to fetch the latest
+-		 * GP values as if an IPI was sent by the other side.
+-		 */
+-		if (ret == xpcTimeout) {
+-			xpc_IPI_send_local_msgrequest(ch);
+-		}
+-
+-		if (flags & XPC_NOWAIT) {
+-			xpc_msgqueue_deref(ch);
+-			return xpcNoWait;
+-		}
+-
+-		ret = xpc_allocate_msg_wait(ch);
+-		if (ret != xpcInterrupted && ret != xpcTimeout) {
+-			xpc_msgqueue_deref(ch);
+-			return ret;
+-		}
+-	}
+-
+-
+-	/* get the message's address and initialize it */
+-	msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+-				(put % ch->local_nentries) * ch->msg_size);
+-
+-
+-	DBUG_ON(msg->flags != 0);
+-	msg->number = put;
+-
+-	dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "
+-		"msg_number=%ld, partid=%d, channel=%d\n", put + 1,
+-		(void *) msg, msg->number, ch->partid, ch->number);
+-
+-	*address_of_msg = msg;
+-
+-	return xpcSuccess;
+-}
+-
+-
+-/*
+- * Allocate an entry for a message from the message queue associated with the
+- * specified channel. NOTE that this routine can sleep waiting for a message
+- * entry to become available. To not sleep, pass in the XPC_NOWAIT flag.
+- *
+- * Arguments:
+- *
+- *	partid - ID of partition to which the channel is connected.
+- *	ch_number - channel #.
+- *	flags - see xpc.h for valid flags.
+- *	payload - address of the allocated payload area pointer (filled in on
+- * 	          return) in which the user-defined message is constructed.
+- */
+-enum xpc_retval
+-xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
+-{
+-	struct xpc_partition *part = &xpc_partitions[partid];
+-	enum xpc_retval ret = xpcUnknownReason;
+-	struct xpc_msg *msg = NULL;
+-
+-
+-	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+-	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+-
+-	*payload = NULL;
+-
+-	if (xpc_part_ref(part)) {
+-		ret = xpc_allocate_msg(&part->channels[ch_number], flags, &msg);
+-		xpc_part_deref(part);
+-
+-		if (msg != NULL) {
+-			*payload = &msg->payload;
+-		}
+-	}
+-
+-	return ret;
+-}
+-
+-
+-/*
+- * Now we actually send the messages that are ready to be sent by advancing
+- * the local message queue's Put value and then send an IPI to the recipient
+- * partition.
+- */
+-static void
+-xpc_send_msgs(struct xpc_channel *ch, s64 initial_put)
+-{
+-	struct xpc_msg *msg;
+-	s64 put = initial_put + 1;
+-	int send_IPI = 0;
+-
+-
+-	while (1) {
+-
+-		while (1) {
+-			if (put == (volatile s64) ch->w_local_GP.put) {
+-				break;
+-			}
+-
+-			msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+-			       (put % ch->local_nentries) * ch->msg_size);
+-
+-			if (!(msg->flags & XPC_M_READY)) {
+-				break;
+-			}
+-
+-			put++;
+-		}
+-
+-		if (put == initial_put) {
+-			/* nothing's changed */
+-			break;
+-		}
+-
+-		if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) !=
+-								initial_put) {
+-			/* someone else beat us to it */
+-			DBUG_ON((volatile s64) ch->local_GP->put < initial_put);
+-			break;
+-		}
+-
+-		/* we just set the new value of local_GP->put */
+-
+-		dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "
+-			"channel=%d\n", put, ch->partid, ch->number);
+-
+-		send_IPI = 1;
+-
+-		/*
+-		 * We need to ensure that the message referenced by
+-		 * local_GP->put is not XPC_M_READY or that local_GP->put
+-		 * equals w_local_GP.put, so we'll go have a look.
+-		 */
+-		initial_put = put;
+-	}
+-
+-	if (send_IPI) {
+-		xpc_IPI_send_msgrequest(ch);
+-	}
+-}
+-
+-
+-/*
+- * Common code that does the actual sending of the message by advancing the
+- * local message queue's Put value and sends an IPI to the partition the
+- * message is being sent to.
+- */
+-static enum xpc_retval
+-xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,
+-			xpc_notify_func func, void *key)
+-{
+-	enum xpc_retval ret = xpcSuccess;
+-	struct xpc_notify *notify = notify;
+-	s64 put, msg_number = msg->number;
+-
+-
+-	DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
+-	DBUG_ON((((u64) msg - (u64) ch->local_msgqueue) / ch->msg_size) !=
+-					msg_number % ch->local_nentries);
+-	DBUG_ON(msg->flags & XPC_M_READY);
+-
+-	if (ch->flags & XPC_C_DISCONNECTING) {
+-		/* drop the reference grabbed in xpc_allocate_msg() */
+-		xpc_msgqueue_deref(ch);
+-		return ch->reason;
+-	}
+-
+-	if (notify_type != 0) {
+-		/*
+-		 * Tell the remote side to send an ACK interrupt when the
+-		 * message has been delivered.
+-		 */
+-		msg->flags |= XPC_M_INTERRUPT;
+-
+-		atomic_inc(&ch->n_to_notify);
+-
+-		notify = &ch->notify_queue[msg_number % ch->local_nentries];
+-		notify->func = func;
+-		notify->key = key;
+-		notify->type = notify_type;
+-
+-		// >>> is a mb() needed here?
+-
+-		if (ch->flags & XPC_C_DISCONNECTING) {
+-			/*
+-			 * An error occurred between our last error check and
+-			 * this one. We will try to clear the type field from
+-			 * the notify entry. If we succeed then
+-			 * xpc_disconnect_channel() didn't already process
+-			 * the notify entry.
+-			 */
+-			if (cmpxchg(&notify->type, notify_type, 0) ==
+-								notify_type) {
+-				atomic_dec(&ch->n_to_notify);
+-				ret = ch->reason;
+-			}
+-
+-			/* drop the reference grabbed in xpc_allocate_msg() */
+-			xpc_msgqueue_deref(ch);
+-			return ret;
+-		}
+-	}
+-
+-	msg->flags |= XPC_M_READY;
+-
+-	/*
+-	 * The preceding store of msg->flags must occur before the following
+-	 * load of ch->local_GP->put.
+-	 */
+-	mb();
+-
+-	/* see if the message is next in line to be sent, if so send it */
+-
+-	put = ch->local_GP->put;
+-	if (put == msg_number) {
+-		xpc_send_msgs(ch, put);
+-	}
+-
+-	/* drop the reference grabbed in xpc_allocate_msg() */
+-	xpc_msgqueue_deref(ch);
+-	return ret;
+-}
+-
+-
+-/*
+- * Send a message previously allocated using xpc_initiate_allocate() on the
+- * specified channel connected to the specified partition.
+- *
+- * This routine will not wait for the message to be received, nor will
+- * notification be given when it does happen. Once this routine has returned
+- * the message entry allocated via xpc_initiate_allocate() is no longer
+- * accessable to the caller.
+- *
+- * This routine, although called by users, does not call xpc_part_ref() to
+- * ensure that the partition infrastructure is in place. It relies on the
+- * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
+- *
+- * Arguments:
+- *
+- *	partid - ID of partition to which the channel is connected.
+- *	ch_number - channel # to send message on.
+- *	payload - pointer to the payload area allocated via
+- *			xpc_initiate_allocate().
+- */
+-enum xpc_retval
+-xpc_initiate_send(partid_t partid, int ch_number, void *payload)
+-{
+-	struct xpc_partition *part = &xpc_partitions[partid];
+-	struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+-	enum xpc_retval ret;
+-
+-
+-	dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,
+-		partid, ch_number);
+-
+-	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+-	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+-	DBUG_ON(msg == NULL);
+-
+-	ret = xpc_send_msg(&part->channels[ch_number], msg, 0, NULL, NULL);
+-
+-	return ret;
+-}
+-
+-
+-/*
+- * Send a message previously allocated using xpc_initiate_allocate on the
+- * specified channel connected to the specified partition.
+- *
+- * This routine will not wait for the message to be sent. Once this routine
+- * has returned the message entry allocated via xpc_initiate_allocate() is no
+- * longer accessable to the caller.
+- *
+- * Once the remote end of the channel has received the message, the function
+- * passed as an argument to xpc_initiate_send_notify() will be called. This
+- * allows the sender to free up or re-use any buffers referenced by the
+- * message, but does NOT mean the message has been processed at the remote
+- * end by a receiver.
+- *
+- * If this routine returns an error, the caller's function will NOT be called.
+- *
+- * This routine, although called by users, does not call xpc_part_ref() to
+- * ensure that the partition infrastructure is in place. It relies on the
+- * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
+- *
+- * Arguments:
+- *
+- *	partid - ID of partition to which the channel is connected.
+- *	ch_number - channel # to send message on.
+- *	payload - pointer to the payload area allocated via
+- *			xpc_initiate_allocate().
+- *	func - function to call with asynchronous notification of message
+- *		  receipt. THIS FUNCTION MUST BE NON-BLOCKING.
+- *	key - user-defined key to be passed to the function when it's called.
+- */
+-enum xpc_retval
+-xpc_initiate_send_notify(partid_t partid, int ch_number, void *payload,
+-				xpc_notify_func func, void *key)
+-{
+-	struct xpc_partition *part = &xpc_partitions[partid];
+-	struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+-	enum xpc_retval ret;
+-
+-
+-	dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,
+-		partid, ch_number);
+-
+-	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+-	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+-	DBUG_ON(msg == NULL);
+-	DBUG_ON(func == NULL);
+-
+-	ret = xpc_send_msg(&part->channels[ch_number], msg, XPC_N_CALL,
+-								func, key);
+-	return ret;
+-}
+-
+-
+-static struct xpc_msg *
+-xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
+-{
+-	struct xpc_partition *part = &xpc_partitions[ch->partid];
+-	struct xpc_msg *remote_msg, *msg;
+-	u32 msg_index, nmsgs;
+-	u64 msg_offset;
+-	enum xpc_retval ret;
+-
+-
+-	if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) {
+-		/* we were interrupted by a signal */
+-		return NULL;
+-	}
+-
+-	while (get >= ch->next_msg_to_pull) {
+-
+-		/* pull as many messages as are ready and able to be pulled */
+-
+-		msg_index = ch->next_msg_to_pull % ch->remote_nentries;
+-
+-		DBUG_ON(ch->next_msg_to_pull >=
+-					(volatile s64) ch->w_remote_GP.put);
+-		nmsgs =  (volatile s64) ch->w_remote_GP.put -
+-						ch->next_msg_to_pull;
+-		if (msg_index + nmsgs > ch->remote_nentries) {
+-			/* ignore the ones that wrap the msg queue for now */
+-			nmsgs = ch->remote_nentries - msg_index;
+-		}
+-
+-		msg_offset = msg_index * ch->msg_size;
+-		msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+-								msg_offset);
+-		remote_msg = (struct xpc_msg *) (ch->remote_msgqueue_pa +
+-								msg_offset);
+-
+-		if ((ret = xpc_pull_remote_cachelines(part, msg, remote_msg,
+-				nmsgs * ch->msg_size)) != xpcSuccess) {
+-
+-			dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
+-				" msg %ld from partition %d, channel=%d, "
+-				"ret=%d\n", nmsgs, ch->next_msg_to_pull,
+-				ch->partid, ch->number, ret);
+-
+-			XPC_DEACTIVATE_PARTITION(part, ret);
+-
+-			mutex_unlock(&ch->msg_to_pull_mutex);
+-			return NULL;
+-		}
+-
+-		mb();	/* >>> this may not be needed, we're not sure */
+-
+-		ch->next_msg_to_pull += nmsgs;
+-	}
+-
+-	mutex_unlock(&ch->msg_to_pull_mutex);
+-
+-	/* return the message we were looking for */
+-	msg_offset = (get % ch->remote_nentries) * ch->msg_size;
+-	msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue + msg_offset);
+-
+-	return msg;
+-}
+-
+-
+-/*
+- * Get a message to be delivered.
+- */
+-static struct xpc_msg *
+-xpc_get_deliverable_msg(struct xpc_channel *ch)
+-{
+-	struct xpc_msg *msg = NULL;
+-	s64 get;
+-
+-
+-	do {
+-		if ((volatile u32) ch->flags & XPC_C_DISCONNECTING) {
+-			break;
+-		}
+-
+-		get = (volatile s64) ch->w_local_GP.get;
+-		if (get == (volatile s64) ch->w_remote_GP.put) {
+-			break;
+-		}
+-
+-		/* There are messages waiting to be pulled and delivered.
+-		 * We need to try to secure one for ourselves. We'll do this
+-		 * by trying to increment w_local_GP.get and hope that no one
+-		 * else beats us to it. If they do, we'll we'll simply have
+-		 * to try again for the next one.
+-	 	 */
+-
+-		if (cmpxchg(&ch->w_local_GP.get, get, get + 1) == get) {
+-			/* we got the entry referenced by get */
+-
+-			dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "
+-				"partid=%d, channel=%d\n", get + 1,
+-				ch->partid, ch->number);
+-
+-			/* pull the message from the remote partition */
+-
+-			msg = xpc_pull_remote_msg(ch, get);
+-
+-			DBUG_ON(msg != NULL && msg->number != get);
+-			DBUG_ON(msg != NULL && (msg->flags & XPC_M_DONE));
+-			DBUG_ON(msg != NULL && !(msg->flags & XPC_M_READY));
+-
+-			break;
+-		}
+-
+-	} while (1);
+-
+-	return msg;
+-}
+-
+-
+-/*
+- * Deliver a message to its intended recipient.
+- */
+-void
+-xpc_deliver_msg(struct xpc_channel *ch)
+-{
+-	struct xpc_msg *msg;
+-
+-
+-	if ((msg = xpc_get_deliverable_msg(ch)) != NULL) {
+-
+-		/*
+-		 * This ref is taken to protect the payload itself from being
+-		 * freed before the user is finished with it, which the user
+-		 * indicates by calling xpc_initiate_received().
+-		 */
+-		xpc_msgqueue_ref(ch);
+-
+-		atomic_inc(&ch->kthreads_active);
+-
+-		if (ch->func != NULL) {
+-			dev_dbg(xpc_chan, "ch->func() called, msg=0x%p, "
+-				"msg_number=%ld, partid=%d, channel=%d\n",
+-				(void *) msg, msg->number, ch->partid,
+-				ch->number);
+-
+-			/* deliver the message to its intended recipient */
+-			ch->func(xpcMsgReceived, ch->partid, ch->number,
+-					&msg->payload, ch->key);
+-
+-			dev_dbg(xpc_chan, "ch->func() returned, msg=0x%p, "
+-				"msg_number=%ld, partid=%d, channel=%d\n",
+-				(void *) msg, msg->number, ch->partid,
+-				ch->number);
+-		}
+-
+-		atomic_dec(&ch->kthreads_active);
+-	}
+-}
+-
+-
+-/*
+- * Now we actually acknowledge the messages that have been delivered and ack'd
+- * by advancing the cached remote message queue's Get value and if requested
+- * send an IPI to the message sender's partition.
+- */
+-static void
+-xpc_acknowledge_msgs(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
+-{
+-	struct xpc_msg *msg;
+-	s64 get = initial_get + 1;
+-	int send_IPI = 0;
+-
+-
+-	while (1) {
+-
+-		while (1) {
+-			if (get == (volatile s64) ch->w_local_GP.get) {
+-				break;
+-			}
+-
+-			msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+-			       (get % ch->remote_nentries) * ch->msg_size);
+-
+-			if (!(msg->flags & XPC_M_DONE)) {
+-				break;
+-			}
+-
+-			msg_flags |= msg->flags;
+-			get++;
+-		}
+-
+-		if (get == initial_get) {
+-			/* nothing's changed */
+-			break;
+-		}
+-
+-		if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) !=
+-								initial_get) {
+-			/* someone else beat us to it */
+-			DBUG_ON((volatile s64) ch->local_GP->get <=
+-								initial_get);
+-			break;
+-		}
+-
+-		/* we just set the new value of local_GP->get */
+-
+-		dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
+-			"channel=%d\n", get, ch->partid, ch->number);
+-
+-		send_IPI = (msg_flags & XPC_M_INTERRUPT);
+-
+-		/*
+-		 * We need to ensure that the message referenced by
+-		 * local_GP->get is not XPC_M_DONE or that local_GP->get
+-		 * equals w_local_GP.get, so we'll go have a look.
+-		 */
+-		initial_get = get;
+-	}
+-
+-	if (send_IPI) {
+-		xpc_IPI_send_msgrequest(ch);
+-	}
+-}
+-
+-
+-/*
+- * Acknowledge receipt of a delivered message.
+- *
+- * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition
+- * that sent the message.
+- *
+- * This function, although called by users, does not call xpc_part_ref() to
+- * ensure that the partition infrastructure is in place. It relies on the
+- * fact that we called xpc_msgqueue_ref() in xpc_deliver_msg().
+- *
+- * Arguments:
+- *
+- *	partid - ID of partition to which the channel is connected.
+- *	ch_number - channel # message received on.
+- *	payload - pointer to the payload area allocated via
+- *			xpc_initiate_allocate().
+- */
+-void
+-xpc_initiate_received(partid_t partid, int ch_number, void *payload)
+-{
+-	struct xpc_partition *part = &xpc_partitions[partid];
+-	struct xpc_channel *ch;
+-	struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+-	s64 get, msg_number = msg->number;
+-
+-
+-	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+-	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+-
+-	ch = &part->channels[ch_number];
+-
+-	dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
+-		(void *) msg, msg_number, ch->partid, ch->number);
+-
+-	DBUG_ON((((u64) msg - (u64) ch->remote_msgqueue) / ch->msg_size) !=
+-					msg_number % ch->remote_nentries);
+-	DBUG_ON(msg->flags & XPC_M_DONE);
+-
+-	msg->flags |= XPC_M_DONE;
+-
+-	/*
+-	 * The preceding store of msg->flags must occur before the following
+-	 * load of ch->local_GP->get.
+-	 */
+-	mb();
+-
+-	/*
+-	 * See if this message is next in line to be acknowledged as having
+-	 * been delivered.
+-	 */
+-	get = ch->local_GP->get;
+-	if (get == msg_number) {
+-		xpc_acknowledge_msgs(ch, get, msg->flags);
+-	}
+-
+-	/* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg()  */
+-	xpc_msgqueue_deref(ch);
+-}
+-
+diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
+deleted file mode 100644
+index 81785b7..0000000
+--- a/arch/ia64/sn/kernel/xpc_main.c
++++ /dev/null
+@@ -1,1431 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2007 Silicon Graphics, Inc.  All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Communication (XPC) support - standard version.
+- *
+- *	XPC provides a message passing capability that crosses partition
+- *	boundaries. This module is made up of two parts:
+- *
+- *	    partition	This part detects the presence/absence of other
+- *			partitions. It provides a heartbeat and monitors
+- *			the heartbeats of other partitions.
+- *
+- *	    channel	This part manages the channels and sends/receives
+- *			messages across them to/from other partitions.
+- *
+- *	There are a couple of additional functions residing in XP, which
+- *	provide an interface to XPC for its users.
+- *
+- *
+- *	Caveats:
+- *
+- *	  . We currently have no way to determine which nasid an IPI came
+- *	    from. Thus, xpc_IPI_send() does a remote AMO write followed by
+- *	    an IPI. The AMO indicates where data is to be pulled from, so
+- *	    after the IPI arrives, the remote partition checks the AMO word.
+- *	    The IPI can actually arrive before the AMO however, so other code
+- *	    must periodically check for this case. Also, remote AMO operations
+- *	    do not reliably time out. Thus we do a remote PIO read solely to
+- *	    know whether the remote partition is down and whether we should
+- *	    stop sending IPIs to it. This remote PIO read operation is set up
+- *	    in a special nofault region so SAL knows to ignore (and cleanup)
+- *	    any errors due to the remote AMO write, PIO read, and/or PIO
+- *	    write operations.
+- *
+- *	    If/when new hardware solves this IPI problem, we should abandon
+- *	    the current approach.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/syscalls.h>
+-#include <linux/cache.h>
+-#include <linux/interrupt.h>
+-#include <linux/delay.h>
+-#include <linux/reboot.h>
+-#include <linux/completion.h>
+-#include <linux/kdebug.h>
+-#include <asm/sn/intr.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/uaccess.h>
+-#include <asm/sn/xpc.h>
+-
+-
+-/* define two XPC debug device structures to be used with dev_dbg() et al */
+-
+-struct device_driver xpc_dbg_name = {
+-	.name = "xpc"
+-};
+-
+-struct device xpc_part_dbg_subname = {
+-	.bus_id = {0},		/* set to "part" at xpc_init() time */
+-	.driver = &xpc_dbg_name
+-};
+-
+-struct device xpc_chan_dbg_subname = {
+-	.bus_id = {0},		/* set to "chan" at xpc_init() time */
+-	.driver = &xpc_dbg_name
+-};
+-
+-struct device *xpc_part = &xpc_part_dbg_subname;
+-struct device *xpc_chan = &xpc_chan_dbg_subname;
+-
+-
+-static int xpc_kdebug_ignore;
+-
+-
+-/* systune related variables for /proc/sys directories */
+-
+-static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
+-static int xpc_hb_min_interval = 1;
+-static int xpc_hb_max_interval = 10;
+-
+-static int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_INTERVAL;
+-static int xpc_hb_check_min_interval = 10;
+-static int xpc_hb_check_max_interval = 120;
+-
+-int xpc_disengage_request_timelimit = XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT;
+-static int xpc_disengage_request_min_timelimit = 0;
+-static int xpc_disengage_request_max_timelimit = 120;
+-
+-static ctl_table xpc_sys_xpc_hb_dir[] = {
+-	{
+-		.ctl_name 	= CTL_UNNUMBERED,
+-		.procname	= "hb_interval",
+-		.data		= &xpc_hb_interval,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec_minmax,
+-		.strategy	= &sysctl_intvec,
+-		.extra1		= &xpc_hb_min_interval,
+-		.extra2		= &xpc_hb_max_interval
+-	},
+-	{
+-		.ctl_name	= CTL_UNNUMBERED,
+-		.procname	= "hb_check_interval",
+-		.data		= &xpc_hb_check_interval,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec_minmax,
+-		.strategy	= &sysctl_intvec,
+-		.extra1		= &xpc_hb_check_min_interval,
+-		.extra2		= &xpc_hb_check_max_interval
+-	},
+-	{}
+-};
+-static ctl_table xpc_sys_xpc_dir[] = {
+-	{
+-		.ctl_name	= CTL_UNNUMBERED,
+-		.procname	= "hb",
+-		.mode		= 0555,
+-		.child		= xpc_sys_xpc_hb_dir
+-	},
+-	{
+-		.ctl_name	= CTL_UNNUMBERED,
+-		.procname	= "disengage_request_timelimit",
+-		.data		= &xpc_disengage_request_timelimit,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec_minmax,
+-		.strategy	= &sysctl_intvec,
+-		.extra1		= &xpc_disengage_request_min_timelimit,
+-		.extra2		= &xpc_disengage_request_max_timelimit
+-	},
+-	{}
+-};
+-static ctl_table xpc_sys_dir[] = {
+-	{
+-		.ctl_name	= CTL_UNNUMBERED,
+-		.procname	= "xpc",
+-		.mode		= 0555,
+-		.child		= xpc_sys_xpc_dir
+-	},
+-	{}
+-};
+-static struct ctl_table_header *xpc_sysctl;
+-
+-/* non-zero if any remote partition disengage request was timed out */
+-int xpc_disengage_request_timedout;
+-
+-/* #of IRQs received */
+-static atomic_t xpc_act_IRQ_rcvd;
+-
+-/* IRQ handler notifies this wait queue on receipt of an IRQ */
+-static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);
+-
+-static unsigned long xpc_hb_check_timeout;
+-
+-/* notification that the xpc_hb_checker thread has exited */
+-static DECLARE_COMPLETION(xpc_hb_checker_exited);
+-
+-/* notification that the xpc_discovery thread has exited */
+-static DECLARE_COMPLETION(xpc_discovery_exited);
+-
+-
+-static struct timer_list xpc_hb_timer;
+-
+-
+-static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);
+-
+-
+-static int xpc_system_reboot(struct notifier_block *, unsigned long, void *);
+-static struct notifier_block xpc_reboot_notifier = {
+-	.notifier_call = xpc_system_reboot,
+-};
+-
+-static int xpc_system_die(struct notifier_block *, unsigned long, void *);
+-static struct notifier_block xpc_die_notifier = {
+-	.notifier_call = xpc_system_die,
+-};
+-
+-
+-/*
+- * Timer function to enforce the timelimit on the partition disengage request.
+- */
+-static void
+-xpc_timeout_partition_disengage_request(unsigned long data)
+-{
+-	struct xpc_partition *part = (struct xpc_partition *) data;
+-
+-
+-	DBUG_ON(jiffies < part->disengage_request_timeout);
+-
+-	(void) xpc_partition_disengaged(part);
+-
+-	DBUG_ON(part->disengage_request_timeout != 0);
+-	DBUG_ON(xpc_partition_engaged(1UL << XPC_PARTID(part)) != 0);
+-}
+-
+-
+-/*
+- * Notify the heartbeat check thread that an IRQ has been received.
+- */
+-static irqreturn_t
+-xpc_act_IRQ_handler(int irq, void *dev_id)
+-{
+-	atomic_inc(&xpc_act_IRQ_rcvd);
+-	wake_up_interruptible(&xpc_act_IRQ_wq);
+-	return IRQ_HANDLED;
+-}
+-
+-
+-/*
+- * Timer to produce the heartbeat.  The timer structures function is
+- * already set when this is initially called.  A tunable is used to
+- * specify when the next timeout should occur.
+- */
+-static void
+-xpc_hb_beater(unsigned long dummy)
+-{
+-	xpc_vars->heartbeat++;
+-
+-	if (jiffies >= xpc_hb_check_timeout) {
+-		wake_up_interruptible(&xpc_act_IRQ_wq);
+-	}
+-
+-	xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ);
+-	add_timer(&xpc_hb_timer);
+-}
+-
+-
+-/*
+- * This thread is responsible for nearly all of the partition
+- * activation/deactivation.
+- */
+-static int
+-xpc_hb_checker(void *ignore)
+-{
+-	int last_IRQ_count = 0;
+-	int new_IRQ_count;
+-	int force_IRQ=0;
+-
+-
+-	/* this thread was marked active by xpc_hb_init() */
+-
+-	daemonize(XPC_HB_CHECK_THREAD_NAME);
+-
+-	set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));
+-
+-	/* set our heartbeating to other partitions into motion */
+-	xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
+-	xpc_hb_beater(0);
+-
+-	while (!(volatile int) xpc_exiting) {
+-
+-		dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
+-			"been received\n",
+-			(int) (xpc_hb_check_timeout - jiffies),
+-			atomic_read(&xpc_act_IRQ_rcvd) - last_IRQ_count);
+-
+-
+-		/* checking of remote heartbeats is skewed by IRQ handling */
+-		if (jiffies >= xpc_hb_check_timeout) {
+-			dev_dbg(xpc_part, "checking remote heartbeats\n");
+-			xpc_check_remote_hb();
+-
+-			/*
+-			 * We need to periodically recheck to ensure no
+-			 * IPI/AMO pairs have been missed.  That check
+-			 * must always reset xpc_hb_check_timeout.
+-			 */
+-			force_IRQ = 1;
+-		}
+-
+-
+-		/* check for outstanding IRQs */
+-		new_IRQ_count = atomic_read(&xpc_act_IRQ_rcvd);
+-		if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {
+-			force_IRQ = 0;
+-
+-			dev_dbg(xpc_part, "found an IRQ to process; will be "
+-				"resetting xpc_hb_check_timeout\n");
+-
+-			last_IRQ_count += xpc_identify_act_IRQ_sender();
+-			if (last_IRQ_count < new_IRQ_count) {
+-				/* retry once to help avoid missing AMO */
+-				(void) xpc_identify_act_IRQ_sender();
+-			}
+-			last_IRQ_count = new_IRQ_count;
+-
+-			xpc_hb_check_timeout = jiffies +
+-					   (xpc_hb_check_interval * HZ);
+-		}
+-
+-		/* wait for IRQ or timeout */
+-		(void) wait_event_interruptible(xpc_act_IRQ_wq,
+-			    (last_IRQ_count < atomic_read(&xpc_act_IRQ_rcvd) ||
+-					jiffies >= xpc_hb_check_timeout ||
+-						(volatile int) xpc_exiting));
+-	}
+-
+-	dev_dbg(xpc_part, "heartbeat checker is exiting\n");
+-
+-
+-	/* mark this thread as having exited */
+-	complete(&xpc_hb_checker_exited);
+-	return 0;
+-}
+-
+-
+-/*
+- * This thread will attempt to discover other partitions to activate
+- * based on info provided by SAL. This new thread is short lived and
+- * will exit once discovery is complete.
+- */
+-static int
+-xpc_initiate_discovery(void *ignore)
+-{
+-	daemonize(XPC_DISCOVERY_THREAD_NAME);
+-
+-	xpc_discovery();
+-
+-	dev_dbg(xpc_part, "discovery thread is exiting\n");
+-
+-	/* mark this thread as having exited */
+-	complete(&xpc_discovery_exited);
+-	return 0;
+-}
+-
+-
+-/*
+- * Establish first contact with the remote partititon. This involves pulling
+- * the XPC per partition variables from the remote partition and waiting for
+- * the remote partition to pull ours.
+- */
+-static enum xpc_retval
+-xpc_make_first_contact(struct xpc_partition *part)
+-{
+-	enum xpc_retval ret;
+-
+-
+-	while ((ret = xpc_pull_remote_vars_part(part)) != xpcSuccess) {
+-		if (ret != xpcRetry) {
+-			XPC_DEACTIVATE_PARTITION(part, ret);
+-			return ret;
+-		}
+-
+-		dev_dbg(xpc_chan, "waiting to make first contact with "
+-			"partition %d\n", XPC_PARTID(part));
+-
+-		/* wait a 1/4 of a second or so */
+-		(void) msleep_interruptible(250);
+-
+-		if (part->act_state == XPC_P_DEACTIVATING) {
+-			return part->reason;
+-		}
+-	}
+-
+-	return xpc_mark_partition_active(part);
+-}
+-
+-
+-/*
+- * The first kthread assigned to a newly activated partition is the one
+- * created by XPC HB with which it calls xpc_partition_up(). XPC hangs on to
+- * that kthread until the partition is brought down, at which time that kthread
+- * returns back to XPC HB. (The return of that kthread will signify to XPC HB
+- * that XPC has dismantled all communication infrastructure for the associated
+- * partition.) This kthread becomes the channel manager for that partition.
+- *
+- * Each active partition has a channel manager, who, besides connecting and
+- * disconnecting channels, will ensure that each of the partition's connected
+- * channels has the required number of assigned kthreads to get the work done.
+- */
+-static void
+-xpc_channel_mgr(struct xpc_partition *part)
+-{
+-	while (part->act_state != XPC_P_DEACTIVATING ||
+-			atomic_read(&part->nchannels_active) > 0 ||
+-					!xpc_partition_disengaged(part)) {
+-
+-		xpc_process_channel_activity(part);
+-
+-
+-		/*
+-		 * Wait until we've been requested to activate kthreads or
+-		 * all of the channel's message queues have been torn down or
+-		 * a signal is pending.
+-		 *
+-		 * The channel_mgr_requests is set to 1 after being awakened,
+-		 * This is done to prevent the channel mgr from making one pass
+-		 * through the loop for each request, since he will
+-		 * be servicing all the requests in one pass. The reason it's
+-		 * set to 1 instead of 0 is so that other kthreads will know
+-		 * that the channel mgr is running and won't bother trying to
+-		 * wake him up.
+-		 */
+-		atomic_dec(&part->channel_mgr_requests);
+-		(void) wait_event_interruptible(part->channel_mgr_wq,
+-				(atomic_read(&part->channel_mgr_requests) > 0 ||
+-				(volatile u64) part->local_IPI_amo != 0 ||
+-				((volatile u8) part->act_state ==
+-							XPC_P_DEACTIVATING &&
+-				atomic_read(&part->nchannels_active) == 0 &&
+-				xpc_partition_disengaged(part))));
+-		atomic_set(&part->channel_mgr_requests, 1);
+-
+-		// >>> Does it need to wakeup periodically as well? In case we
+-		// >>> miscalculated the #of kthreads to wakeup or create?
+-	}
+-}
+-
+-
+-/*
+- * When XPC HB determines that a partition has come up, it will create a new
+- * kthread and that kthread will call this function to attempt to set up the
+- * basic infrastructure used for Cross Partition Communication with the newly
+- * upped partition.
+- *
+- * The kthread that was created by XPC HB and which setup the XPC
+- * infrastructure will remain assigned to the partition until the partition
+- * goes down. At which time the kthread will teardown the XPC infrastructure
+- * and then exit.
+- *
+- * XPC HB will put the remote partition's XPC per partition specific variables
+- * physical address into xpc_partitions[partid].remote_vars_part_pa prior to
+- * calling xpc_partition_up().
+- */
+-static void
+-xpc_partition_up(struct xpc_partition *part)
+-{
+-	DBUG_ON(part->channels != NULL);
+-
+-	dev_dbg(xpc_chan, "activating partition %d\n", XPC_PARTID(part));
+-
+-	if (xpc_setup_infrastructure(part) != xpcSuccess) {
+-		return;
+-	}
+-
+-	/*
+-	 * The kthread that XPC HB called us with will become the
+-	 * channel manager for this partition. It will not return
+-	 * back to XPC HB until the partition's XPC infrastructure
+-	 * has been dismantled.
+-	 */
+-
+-	(void) xpc_part_ref(part);	/* this will always succeed */
+-
+-	if (xpc_make_first_contact(part) == xpcSuccess) {
+-		xpc_channel_mgr(part);
+-	}
+-
+-	xpc_part_deref(part);
+-
+-	xpc_teardown_infrastructure(part);
+-}
+-
+-
+-static int
+-xpc_activating(void *__partid)
+-{
+-	partid_t partid = (u64) __partid;
+-	struct xpc_partition *part = &xpc_partitions[partid];
+-	unsigned long irq_flags;
+-	struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+-	int ret;
+-
+-
+-	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+-
+-	spin_lock_irqsave(&part->act_lock, irq_flags);
+-
+-	if (part->act_state == XPC_P_DEACTIVATING) {
+-		part->act_state = XPC_P_INACTIVE;
+-		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-		part->remote_rp_pa = 0;
+-		return 0;
+-	}
+-
+-	/* indicate the thread is activating */
+-	DBUG_ON(part->act_state != XPC_P_ACTIVATION_REQ);
+-	part->act_state = XPC_P_ACTIVATING;
+-
+-	XPC_SET_REASON(part, 0, 0);
+-	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-
+-	dev_dbg(xpc_part, "bringing partition %d up\n", partid);
+-
+-	daemonize("xpc%02d", partid);
+-
+-	/*
+-	 * This thread needs to run at a realtime priority to prevent a
+-	 * significant performance degradation.
+-	 */
+-	ret = sched_setscheduler(current, SCHED_FIFO, &param);
+-	if (ret != 0) {
+-		dev_warn(xpc_part, "unable to set pid %d to a realtime "
+-			"priority, ret=%d\n", current->pid, ret);
+-	}
+-
+-	/* allow this thread and its children to run on any CPU */
+-	set_cpus_allowed(current, CPU_MASK_ALL);
+-
+-	/*
+-	 * Register the remote partition's AMOs with SAL so it can handle
+-	 * and cleanup errors within that address range should the remote
+-	 * partition go down. We don't unregister this range because it is
+-	 * difficult to tell when outstanding writes to the remote partition
+-	 * are finished and thus when it is safe to unregister. This should
+-	 * not result in wasted space in the SAL xp_addr_region table because
+-	 * we should get the same page for remote_amos_page_pa after module
+-	 * reloads and system reboots.
+-	 */
+-	if (sn_register_xp_addr_region(part->remote_amos_page_pa,
+-							PAGE_SIZE, 1) < 0) {
+-		dev_warn(xpc_part, "xpc_partition_up(%d) failed to register "
+-			"xp_addr region\n", partid);
+-
+-		spin_lock_irqsave(&part->act_lock, irq_flags);
+-		part->act_state = XPC_P_INACTIVE;
+-		XPC_SET_REASON(part, xpcPhysAddrRegFailed, __LINE__);
+-		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-		part->remote_rp_pa = 0;
+-		return 0;
+-	}
+-
+-	xpc_allow_hb(partid, xpc_vars);
+-	xpc_IPI_send_activated(part);
+-
+-
+-	/*
+-	 * xpc_partition_up() holds this thread and marks this partition as
+-	 * XPC_P_ACTIVE by calling xpc_hb_mark_active().
+-	 */
+-	(void) xpc_partition_up(part);
+-
+-	xpc_disallow_hb(partid, xpc_vars);
+-	xpc_mark_partition_inactive(part);
+-
+-	if (part->reason == xpcReactivating) {
+-		/* interrupting ourselves results in activating partition */
+-		xpc_IPI_send_reactivate(part);
+-	}
+-
+-	return 0;
+-}
+-
+-
+-void
+-xpc_activate_partition(struct xpc_partition *part)
+-{
+-	partid_t partid = XPC_PARTID(part);
+-	unsigned long irq_flags;
+-	pid_t pid;
+-
+-
+-	spin_lock_irqsave(&part->act_lock, irq_flags);
+-
+-	DBUG_ON(part->act_state != XPC_P_INACTIVE);
+-
+-	part->act_state = XPC_P_ACTIVATION_REQ;
+-	XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
+-
+-	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-
+-	pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0);
+-
+-	if (unlikely(pid <= 0)) {
+-		spin_lock_irqsave(&part->act_lock, irq_flags);
+-		part->act_state = XPC_P_INACTIVE;
+-		XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
+-		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-	}
+-}
+-
+-
+-/*
+- * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
+- * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
+- * than one partition, we use an AMO_t structure per partition to indicate
+- * whether a partition has sent an IPI or not.  >>> If it has, then wake up the
+- * associated kthread to handle it.
+- *
+- * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IPIs sent by XPC
+- * running on other partitions.
+- *
+- * Noteworthy Arguments:
+- *
+- *	irq - Interrupt ReQuest number. NOT USED.
+- *
+- *	dev_id - partid of IPI's potential sender.
+- */
+-irqreturn_t
+-xpc_notify_IRQ_handler(int irq, void *dev_id)
+-{
+-	partid_t partid = (partid_t) (u64) dev_id;
+-	struct xpc_partition *part = &xpc_partitions[partid];
+-
+-
+-	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+-
+-	if (xpc_part_ref(part)) {
+-		xpc_check_for_channel_activity(part);
+-
+-		xpc_part_deref(part);
+-	}
+-	return IRQ_HANDLED;
+-}
+-
+-
+-/*
+- * Check to see if xpc_notify_IRQ_handler() dropped any IPIs on the floor
+- * because the write to their associated IPI amo completed after the IRQ/IPI
+- * was received.
+- */
+-void
+-xpc_dropped_IPI_check(struct xpc_partition *part)
+-{
+-	if (xpc_part_ref(part)) {
+-		xpc_check_for_channel_activity(part);
+-
+-		part->dropped_IPI_timer.expires = jiffies +
+-							XPC_P_DROPPED_IPI_WAIT;
+-		add_timer(&part->dropped_IPI_timer);
+-		xpc_part_deref(part);
+-	}
+-}
+-
+-
+-void
+-xpc_activate_kthreads(struct xpc_channel *ch, int needed)
+-{
+-	int idle = atomic_read(&ch->kthreads_idle);
+-	int assigned = atomic_read(&ch->kthreads_assigned);
+-	int wakeup;
+-
+-
+-	DBUG_ON(needed <= 0);
+-
+-	if (idle > 0) {
+-		wakeup = (needed > idle) ? idle : needed;
+-		needed -= wakeup;
+-
+-		dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, "
+-			"channel=%d\n", wakeup, ch->partid, ch->number);
+-
+-		/* only wakeup the requested number of kthreads */
+-		wake_up_nr(&ch->idle_wq, wakeup);
+-	}
+-
+-	if (needed <= 0) {
+-		return;
+-	}
+-
+-	if (needed + assigned > ch->kthreads_assigned_limit) {
+-		needed = ch->kthreads_assigned_limit - assigned;
+-		// >>>should never be less than 0
+-		if (needed <= 0) {
+-			return;
+-		}
+-	}
+-
+-	dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",
+-		needed, ch->partid, ch->number);
+-
+-	xpc_create_kthreads(ch, needed, 0);
+-}
+-
+-
+-/*
+- * This function is where XPC's kthreads wait for messages to deliver.
+- */
+-static void
+-xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
+-{
+-	do {
+-		/* deliver messages to their intended recipients */
+-
+-		while ((volatile s64) ch->w_local_GP.get <
+-				(volatile s64) ch->w_remote_GP.put &&
+-					!((volatile u32) ch->flags &
+-						XPC_C_DISCONNECTING)) {
+-			xpc_deliver_msg(ch);
+-		}
+-
+-		if (atomic_inc_return(&ch->kthreads_idle) >
+-						ch->kthreads_idle_limit) {
+-			/* too many idle kthreads on this channel */
+-			atomic_dec(&ch->kthreads_idle);
+-			break;
+-		}
+-
+-		dev_dbg(xpc_chan, "idle kthread calling "
+-			"wait_event_interruptible_exclusive()\n");
+-
+-		(void) wait_event_interruptible_exclusive(ch->idle_wq,
+-				((volatile s64) ch->w_local_GP.get <
+-					(volatile s64) ch->w_remote_GP.put ||
+-				((volatile u32) ch->flags &
+-						XPC_C_DISCONNECTING)));
+-
+-		atomic_dec(&ch->kthreads_idle);
+-
+-	} while (!((volatile u32) ch->flags & XPC_C_DISCONNECTING));
+-}
+-
+-
+-static int
+-xpc_daemonize_kthread(void *args)
+-{
+-	partid_t partid = XPC_UNPACK_ARG1(args);
+-	u16 ch_number = XPC_UNPACK_ARG2(args);
+-	struct xpc_partition *part = &xpc_partitions[partid];
+-	struct xpc_channel *ch;
+-	int n_needed;
+-	unsigned long irq_flags;
+-
+-
+-	daemonize("xpc%02dc%d", partid, ch_number);
+-
+-	dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n",
+-		partid, ch_number);
+-
+-	ch = &part->channels[ch_number];
+-
+-	if (!(ch->flags & XPC_C_DISCONNECTING)) {
+-
+-		/* let registerer know that connection has been established */
+-
+-		spin_lock_irqsave(&ch->lock, irq_flags);
+-		if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) {
+-			ch->flags |= XPC_C_CONNECTEDCALLOUT;
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+-			xpc_connected_callout(ch);
+-
+-			spin_lock_irqsave(&ch->lock, irq_flags);
+-			ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE;
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+-			/*
+-			 * It is possible that while the callout was being
+-			 * made that the remote partition sent some messages.
+-			 * If that is the case, we may need to activate
+-			 * additional kthreads to help deliver them. We only
+-			 * need one less than total #of messages to deliver.
+-			 */
+-			n_needed = ch->w_remote_GP.put - ch->w_local_GP.get - 1;
+-			if (n_needed > 0 &&
+-					!(ch->flags & XPC_C_DISCONNECTING)) {
+-				xpc_activate_kthreads(ch, n_needed);
+-			}
+-		} else {
+-			spin_unlock_irqrestore(&ch->lock, irq_flags);
+-		}
+-
+-		xpc_kthread_waitmsgs(part, ch);
+-	}
+-
+-	/* let registerer know that connection is disconnecting */
+-
+-	spin_lock_irqsave(&ch->lock, irq_flags);
+-	if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+-			!(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
+-		ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
+-		spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+-		xpc_disconnect_callout(ch, xpcDisconnecting);
+-
+-		spin_lock_irqsave(&ch->lock, irq_flags);
+-		ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
+-	}
+-	spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+-	if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
+-		if (atomic_dec_return(&part->nchannels_engaged) == 0) {
+-			xpc_mark_partition_disengaged(part);
+-			xpc_IPI_send_disengage(part);
+-		}
+-	}
+-
+-	xpc_msgqueue_deref(ch);
+-
+-	dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",
+-		partid, ch_number);
+-
+-	xpc_part_deref(part);
+-	return 0;
+-}
+-
+-
+-/*
+- * For each partition that XPC has established communications with, there is
+- * a minimum of one kernel thread assigned to perform any operation that
+- * may potentially sleep or block (basically the callouts to the asynchronous
+- * functions registered via xpc_connect()).
+- *
+- * Additional kthreads are created and destroyed by XPC as the workload
+- * demands.
+- *
+- * A kthread is assigned to one of the active channels that exists for a given
+- * partition.
+- */
+-void
+-xpc_create_kthreads(struct xpc_channel *ch, int needed,
+-			int ignore_disconnecting)
+-{
+-	unsigned long irq_flags;
+-	pid_t pid;
+-	u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
+-	struct xpc_partition *part = &xpc_partitions[ch->partid];
+-
+-
+-	while (needed-- > 0) {
+-
+-		/*
+-		 * The following is done on behalf of the newly created
+-		 * kthread. That kthread is responsible for doing the
+-		 * counterpart to the following before it exits.
+-		 */
+-		if (ignore_disconnecting) {
+-			if (!atomic_inc_not_zero(&ch->kthreads_assigned)) {
+-				/* kthreads assigned had gone to zero */
+-				BUG_ON(!(ch->flags &
+-					XPC_C_DISCONNECTINGCALLOUT_MADE));
+-				break;
+-			}
+-
+-		} else if (ch->flags & XPC_C_DISCONNECTING) {
+-			break;
+-
+-		} else if (atomic_inc_return(&ch->kthreads_assigned) == 1) {
+-			if (atomic_inc_return(&part->nchannels_engaged) == 1)
+-				xpc_mark_partition_engaged(part);
+-		}
+-		(void) xpc_part_ref(part);
+-		xpc_msgqueue_ref(ch);
+-
+-		pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0);
+-		if (pid < 0) {
+-			/* the fork failed */
+-
+-			/*
+-			 * NOTE: if (ignore_disconnecting &&
+-			 * !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true,
+-			 * then we'll deadlock if all other kthreads assigned
+-			 * to this channel are blocked in the channel's
+-			 * registerer, because the only thing that will unblock
+-			 * them is the xpcDisconnecting callout that this
+-			 * failed kernel_thread would have made.
+-			 */
+-
+-			if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
+-			    atomic_dec_return(&part->nchannels_engaged) == 0) {
+-				xpc_mark_partition_disengaged(part);
+-				xpc_IPI_send_disengage(part);
+-			}
+-			xpc_msgqueue_deref(ch);
+-			xpc_part_deref(part);
+-
+-			if (atomic_read(&ch->kthreads_assigned) <
+-						ch->kthreads_idle_limit) {
+-				/*
+-				 * Flag this as an error only if we have an
+-				 * insufficient #of kthreads for the channel
+-				 * to function.
+-				 */
+-				spin_lock_irqsave(&ch->lock, irq_flags);
+-				XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources,
+-								&irq_flags);
+-				spin_unlock_irqrestore(&ch->lock, irq_flags);
+-			}
+-			break;
+-		}
+-
+-		ch->kthreads_created++;	// >>> temporary debug only!!!
+-	}
+-}
+-
+-
+-void
+-xpc_disconnect_wait(int ch_number)
+-{
+-	unsigned long irq_flags;
+-	partid_t partid;
+-	struct xpc_partition *part;
+-	struct xpc_channel *ch;
+-	int wakeup_channel_mgr;
+-
+-
+-	/* now wait for all callouts to the caller's function to cease */
+-	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+-		part = &xpc_partitions[partid];
+-
+-		if (!xpc_part_ref(part)) {
+-			continue;
+-		}
+-
+-		ch = &part->channels[ch_number];
+-
+-		if (!(ch->flags & XPC_C_WDISCONNECT)) {
+-			xpc_part_deref(part);
+-			continue;
+-		}
+-
+-		wait_for_completion(&ch->wdisconnect_wait);
+-
+-		spin_lock_irqsave(&ch->lock, irq_flags);
+-		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
+-		wakeup_channel_mgr = 0;
+-
+-		if (ch->delayed_IPI_flags) {
+-			if (part->act_state != XPC_P_DEACTIVATING) {
+-				spin_lock(&part->IPI_lock);
+-				XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+-					ch->number, ch->delayed_IPI_flags);
+-				spin_unlock(&part->IPI_lock);
+-				wakeup_channel_mgr = 1;
+-			}
+-			ch->delayed_IPI_flags = 0;
+-		}
+-
+-		ch->flags &= ~XPC_C_WDISCONNECT;
+-		spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+-		if (wakeup_channel_mgr) {
+-			xpc_wakeup_channel_mgr(part);
+-		}
+-
+-		xpc_part_deref(part);
+-	}
+-}
+-
+-
+-static void
+-xpc_do_exit(enum xpc_retval reason)
+-{
+-	partid_t partid;
+-	int active_part_count, printed_waiting_msg = 0;
+-	struct xpc_partition *part;
+-	unsigned long printmsg_time, disengage_request_timeout = 0;
+-
+-
+-	/* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
+-	DBUG_ON(xpc_exiting == 1);
+-
+-	/*
+-	 * Let the heartbeat checker thread and the discovery thread
+-	 * (if one is running) know that they should exit. Also wake up
+-	 * the heartbeat checker thread in case it's sleeping.
+-	 */
+-	xpc_exiting = 1;
+-	wake_up_interruptible(&xpc_act_IRQ_wq);
+-
+-	/* ignore all incoming interrupts */
+-	free_irq(SGI_XPC_ACTIVATE, NULL);
+-
+-	/* wait for the discovery thread to exit */
+-	wait_for_completion(&xpc_discovery_exited);
+-
+-	/* wait for the heartbeat checker thread to exit */
+-	wait_for_completion(&xpc_hb_checker_exited);
+-
+-
+-	/* sleep for a 1/3 of a second or so */
+-	(void) msleep_interruptible(300);
+-
+-
+-	/* wait for all partitions to become inactive */
+-
+-	printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
+-	xpc_disengage_request_timedout = 0;
+-
+-	do {
+-		active_part_count = 0;
+-
+-		for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+-			part = &xpc_partitions[partid];
+-
+-			if (xpc_partition_disengaged(part) &&
+-					part->act_state == XPC_P_INACTIVE) {
+-				continue;
+-			}
+-
+-			active_part_count++;
+-
+-			XPC_DEACTIVATE_PARTITION(part, reason);
+-
+-			if (part->disengage_request_timeout >
+-						disengage_request_timeout) {
+-				disengage_request_timeout =
+-						part->disengage_request_timeout;
+-			}
+-		}
+-
+-		if (xpc_partition_engaged(-1UL)) {
+-			if (time_after(jiffies, printmsg_time)) {
+-				dev_info(xpc_part, "waiting for remote "
+-					"partitions to disengage, timeout in "
+-					"%ld seconds\n",
+-					(disengage_request_timeout - jiffies)
+-									/ HZ);
+-				printmsg_time = jiffies +
+-					(XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
+-				printed_waiting_msg = 1;
+-			}
+-
+-		} else if (active_part_count > 0) {
+-			if (printed_waiting_msg) {
+-				dev_info(xpc_part, "waiting for local partition"
+-					" to disengage\n");
+-				printed_waiting_msg = 0;
+-			}
+-
+-		} else {
+-			if (!xpc_disengage_request_timedout) {
+-				dev_info(xpc_part, "all partitions have "
+-					"disengaged\n");
+-			}
+-			break;
+-		}
+-
+-		/* sleep for a 1/3 of a second or so */
+-		(void) msleep_interruptible(300);
+-
+-	} while (1);
+-
+-	DBUG_ON(xpc_partition_engaged(-1UL));
+-
+-
+-	/* indicate to others that our reserved page is uninitialized */
+-	xpc_rsvd_page->vars_pa = 0;
+-
+-	/* now it's time to eliminate our heartbeat */
+-	del_timer_sync(&xpc_hb_timer);
+-	DBUG_ON(xpc_vars->heartbeating_to_mask != 0);
+-
+-	if (reason == xpcUnloading) {
+-		/* take ourselves off of the reboot_notifier_list */
+-		(void) unregister_reboot_notifier(&xpc_reboot_notifier);
+-
+-		/* take ourselves off of the die_notifier list */
+-		(void) unregister_die_notifier(&xpc_die_notifier);
+-	}
+-
+-	/* close down protections for IPI operations */
+-	xpc_restrict_IPI_ops();
+-
+-
+-	/* clear the interface to XPC's functions */
+-	xpc_clear_interface();
+-
+-	if (xpc_sysctl) {
+-		unregister_sysctl_table(xpc_sysctl);
+-	}
+-
+-	kfree(xpc_remote_copy_buffer_base);
+-}
+-
+-
+-/*
+- * This function is called when the system is being rebooted.
+- */
+-static int
+-xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
+-{
+-	enum xpc_retval reason;
+-
+-
+-	switch (event) {
+-	case SYS_RESTART:
+-		reason = xpcSystemReboot;
+-		break;
+-	case SYS_HALT:
+-		reason = xpcSystemHalt;
+-		break;
+-	case SYS_POWER_OFF:
+-		reason = xpcSystemPoweroff;
+-		break;
+-	default:
+-		reason = xpcSystemGoingDown;
+-	}
+-
+-	xpc_do_exit(reason);
+-	return NOTIFY_DONE;
+-}
+-
+-
+-/*
+- * Notify other partitions to disengage from all references to our memory.
+- */
+-static void
+-xpc_die_disengage(void)
+-{
+-	struct xpc_partition *part;
+-	partid_t partid;
+-	unsigned long engaged;
+-	long time, printmsg_time, disengage_request_timeout;
+-
+-
+-	/* keep xpc_hb_checker thread from doing anything (just in case) */
+-	xpc_exiting = 1;
+-
+-	xpc_vars->heartbeating_to_mask = 0;  /* indicate we're deactivated */
+-
+-	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+-		part = &xpc_partitions[partid];
+-
+-		if (!XPC_SUPPORTS_DISENGAGE_REQUEST(part->
+-							remote_vars_version)) {
+-
+-			/* just in case it was left set by an earlier XPC */
+-			xpc_clear_partition_engaged(1UL << partid);
+-			continue;
+-		}
+-
+-		if (xpc_partition_engaged(1UL << partid) ||
+-					part->act_state != XPC_P_INACTIVE) {
+-			xpc_request_partition_disengage(part);
+-			xpc_mark_partition_disengaged(part);
+-			xpc_IPI_send_disengage(part);
+-		}
+-	}
+-
+-	time = rtc_time();
+-	printmsg_time = time +
+-		(XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second);
+-	disengage_request_timeout = time +
+-		(xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);
+-
+-	/* wait for all other partitions to disengage from us */
+-
+-	while (1) {
+-		engaged = xpc_partition_engaged(-1UL);
+-		if (!engaged) {
+-			dev_info(xpc_part, "all partitions have disengaged\n");
+-			break;
+-		}
+-
+-		time = rtc_time();
+-		if (time >= disengage_request_timeout) {
+-			for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+-				if (engaged & (1UL << partid)) {
+-					dev_info(xpc_part, "disengage from "
+-						"remote partition %d timed "
+-						"out\n", partid);
+-				}
+-			}
+-			break;
+-		}
+-
+-		if (time >= printmsg_time) {
+-			dev_info(xpc_part, "waiting for remote partitions to "
+-				"disengage, timeout in %ld seconds\n",
+-				(disengage_request_timeout - time) /
+-						sn_rtc_cycles_per_second);
+-			printmsg_time = time +
+-					(XPC_DISENGAGE_PRINTMSG_INTERVAL *
+-						sn_rtc_cycles_per_second);
+-		}
+-	}
+-}
+-
+-
+-/*
+- * This function is called when the system is being restarted or halted due
+- * to some sort of system failure. If this is the case we need to notify the
+- * other partitions to disengage from all references to our memory.
+- * This function can also be called when our heartbeater could be offlined
+- * for a time. In this case we need to notify other partitions to not worry
+- * about the lack of a heartbeat.
+- */
+-static int
+-xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
+-{
+-	switch (event) {
+-	case DIE_MACHINE_RESTART:
+-	case DIE_MACHINE_HALT:
+-		xpc_die_disengage();
+-		break;
+-
+-	case DIE_KDEBUG_ENTER:
+-		/* Should lack of heartbeat be ignored by other partitions? */
+-		if (!xpc_kdebug_ignore) {
+-			break;
+-		}
+-		/* fall through */
+-	case DIE_MCA_MONARCH_ENTER:
+-	case DIE_INIT_MONARCH_ENTER:
+-		xpc_vars->heartbeat++;
+-		xpc_vars->heartbeat_offline = 1;
+-		break;
+-
+-	case DIE_KDEBUG_LEAVE:
+-		/* Is lack of heartbeat being ignored by other partitions? */
+-		if (!xpc_kdebug_ignore) {
+-			break;
+-		}
+-		/* fall through */
+-	case DIE_MCA_MONARCH_LEAVE:
+-	case DIE_INIT_MONARCH_LEAVE:
+-		xpc_vars->heartbeat++;
+-		xpc_vars->heartbeat_offline = 0;
+-		break;
+-	}
+-
+-	return NOTIFY_DONE;
+-}
+-
+-
+-int __init
+-xpc_init(void)
+-{
+-	int ret;
+-	partid_t partid;
+-	struct xpc_partition *part;
+-	pid_t pid;
+-	size_t buf_size;
+-
+-
+-	if (!ia64_platform_is("sn2")) {
+-		return -ENODEV;
+-	}
+-
+-
+-	buf_size = max(XPC_RP_VARS_SIZE,
+-				XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES);
+-	xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size,
+-				     GFP_KERNEL, &xpc_remote_copy_buffer_base);
+-	if (xpc_remote_copy_buffer == NULL)
+-		return -ENOMEM;
+-
+-	snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
+-	snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
+-
+-	xpc_sysctl = register_sysctl_table(xpc_sys_dir);
+-
+-	/*
+-	 * The first few fields of each entry of xpc_partitions[] need to
+-	 * be initialized now so that calls to xpc_connect() and
+-	 * xpc_disconnect() can be made prior to the activation of any remote
+-	 * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
+-	 * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
+-	 * PARTITION HAS BEEN ACTIVATED.
+-	 */
+-	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+-		part = &xpc_partitions[partid];
+-
+-		DBUG_ON((u64) part != L1_CACHE_ALIGN((u64) part));
+-
+-		part->act_IRQ_rcvd = 0;
+-		spin_lock_init(&part->act_lock);
+-		part->act_state = XPC_P_INACTIVE;
+-		XPC_SET_REASON(part, 0, 0);
+-
+-		init_timer(&part->disengage_request_timer);
+-		part->disengage_request_timer.function =
+-				xpc_timeout_partition_disengage_request;
+-		part->disengage_request_timer.data = (unsigned long) part;
+-
+-		part->setup_state = XPC_P_UNSET;
+-		init_waitqueue_head(&part->teardown_wq);
+-		atomic_set(&part->references, 0);
+-	}
+-
+-	/*
+-	 * Open up protections for IPI operations (and AMO operations on
+-	 * Shub 1.1 systems).
+-	 */
+-	xpc_allow_IPI_ops();
+-
+-	/*
+-	 * Interrupts being processed will increment this atomic variable and
+-	 * awaken the heartbeat thread which will process the interrupts.
+-	 */
+-	atomic_set(&xpc_act_IRQ_rcvd, 0);
+-
+-	/*
+-	 * This is safe to do before the xpc_hb_checker thread has started
+-	 * because the handler releases a wait queue.  If an interrupt is
+-	 * received before the thread is waiting, it will not go to sleep,
+-	 * but rather immediately process the interrupt.
+-	 */
+-	ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0,
+-							"xpc hb", NULL);
+-	if (ret != 0) {
+-		dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
+-			"errno=%d\n", -ret);
+-
+-		xpc_restrict_IPI_ops();
+-
+-		if (xpc_sysctl) {
+-			unregister_sysctl_table(xpc_sysctl);
+-		}
+-
+-		kfree(xpc_remote_copy_buffer_base);
+-		return -EBUSY;
+-	}
+-
+-	/*
+-	 * Fill the partition reserved page with the information needed by
+-	 * other partitions to discover we are alive and establish initial
+-	 * communications.
+-	 */
+-	xpc_rsvd_page = xpc_rsvd_page_init();
+-	if (xpc_rsvd_page == NULL) {
+-		dev_err(xpc_part, "could not setup our reserved page\n");
+-
+-		free_irq(SGI_XPC_ACTIVATE, NULL);
+-		xpc_restrict_IPI_ops();
+-
+-		if (xpc_sysctl) {
+-			unregister_sysctl_table(xpc_sysctl);
+-		}
+-
+-		kfree(xpc_remote_copy_buffer_base);
+-		return -EBUSY;
+-	}
+-
+-
+-	/* add ourselves to the reboot_notifier_list */
+-	ret = register_reboot_notifier(&xpc_reboot_notifier);
+-	if (ret != 0) {
+-		dev_warn(xpc_part, "can't register reboot notifier\n");
+-	}
+-
+-	/* add ourselves to the die_notifier list */
+-	ret = register_die_notifier(&xpc_die_notifier);
+-	if (ret != 0) {
+-		dev_warn(xpc_part, "can't register die notifier\n");
+-	}
+-
+-	init_timer(&xpc_hb_timer);
+-	xpc_hb_timer.function = xpc_hb_beater;
+-
+-	/*
+-	 * The real work-horse behind xpc.  This processes incoming
+-	 * interrupts and monitors remote heartbeats.
+-	 */
+-	pid = kernel_thread(xpc_hb_checker, NULL, 0);
+-	if (pid < 0) {
+-		dev_err(xpc_part, "failed while forking hb check thread\n");
+-
+-		/* indicate to others that our reserved page is uninitialized */
+-		xpc_rsvd_page->vars_pa = 0;
+-
+-		/* take ourselves off of the reboot_notifier_list */
+-		(void) unregister_reboot_notifier(&xpc_reboot_notifier);
+-
+-		/* take ourselves off of the die_notifier list */
+-		(void) unregister_die_notifier(&xpc_die_notifier);
+-
+-		del_timer_sync(&xpc_hb_timer);
+-		free_irq(SGI_XPC_ACTIVATE, NULL);
+-		xpc_restrict_IPI_ops();
+-
+-		if (xpc_sysctl) {
+-			unregister_sysctl_table(xpc_sysctl);
+-		}
+-
+-		kfree(xpc_remote_copy_buffer_base);
+-		return -EBUSY;
+-	}
+-
+-
+-	/*
+-	 * Startup a thread that will attempt to discover other partitions to
+-	 * activate based on info provided by SAL. This new thread is short
+-	 * lived and will exit once discovery is complete.
+-	 */
+-	pid = kernel_thread(xpc_initiate_discovery, NULL, 0);
+-	if (pid < 0) {
+-		dev_err(xpc_part, "failed while forking discovery thread\n");
+-
+-		/* mark this new thread as a non-starter */
+-		complete(&xpc_discovery_exited);
+-
+-		xpc_do_exit(xpcUnloading);
+-		return -EBUSY;
+-	}
+-
+-
+-	/* set the interface to point at XPC's functions */
+-	xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,
+-			  xpc_initiate_allocate, xpc_initiate_send,
+-			  xpc_initiate_send_notify, xpc_initiate_received,
+-			  xpc_initiate_partid_to_nasids);
+-
+-	return 0;
+-}
+-module_init(xpc_init);
+-
+-
+-void __exit
+-xpc_exit(void)
+-{
+-	xpc_do_exit(xpcUnloading);
+-}
+-module_exit(xpc_exit);
+-
+-
+-MODULE_AUTHOR("Silicon Graphics, Inc.");
+-MODULE_DESCRIPTION("Cross Partition Communication (XPC) support");
+-MODULE_LICENSE("GPL");
+-
+-module_param(xpc_hb_interval, int, 0);
+-MODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between "
+-		"heartbeat increments.");
+-
+-module_param(xpc_hb_check_interval, int, 0);
+-MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "
+-		"heartbeat checks.");
+-
+-module_param(xpc_disengage_request_timelimit, int, 0);
+-MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "
+-		"for disengage request to complete.");
+-
+-module_param(xpc_kdebug_ignore, int, 0);
+-MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by "
+-		"other partitions when dropping into kdebug.");
+-
+diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
+deleted file mode 100644
+index 7ba4032..0000000
+--- a/arch/ia64/sn/kernel/xpc_partition.c
++++ /dev/null
+@@ -1,1239 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2006 Silicon Graphics, Inc.  All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Communication (XPC) partition support.
+- *
+- *	This is the part of XPC that detects the presence/absence of
+- *	other partitions. It provides a heartbeat and monitors the
+- *	heartbeats of other partitions.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/sysctl.h>
+-#include <linux/cache.h>
+-#include <linux/mmzone.h>
+-#include <linux/nodemask.h>
+-#include <asm/uncached.h>
+-#include <asm/sn/bte.h>
+-#include <asm/sn/intr.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/sn/nodepda.h>
+-#include <asm/sn/addrs.h>
+-#include <asm/sn/xpc.h>
+-
+-
+-/* XPC is exiting flag */
+-int xpc_exiting;
+-
+-
+-/* SH_IPI_ACCESS shub register value on startup */
+-static u64 xpc_sh1_IPI_access;
+-static u64 xpc_sh2_IPI_access0;
+-static u64 xpc_sh2_IPI_access1;
+-static u64 xpc_sh2_IPI_access2;
+-static u64 xpc_sh2_IPI_access3;
+-
+-
+-/* original protection values for each node */
+-u64 xpc_prot_vec[MAX_NUMNODES];
+-
+-
+-/* this partition's reserved page pointers */
+-struct xpc_rsvd_page *xpc_rsvd_page;
+-static u64 *xpc_part_nasids;
+-static u64 *xpc_mach_nasids;
+-struct xpc_vars *xpc_vars;
+-struct xpc_vars_part *xpc_vars_part;
+-
+-static int xp_nasid_mask_bytes;	/* actual size in bytes of nasid mask */
+-static int xp_nasid_mask_words;	/* actual size in words of nasid mask */
+-
+-
+-/*
+- * For performance reasons, each entry of xpc_partitions[] is cacheline
+- * aligned. And xpc_partitions[] is padded with an additional entry at the
+- * end so that the last legitimate entry doesn't share its cacheline with
+- * another variable.
+- */
+-struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
+-
+-
+-/*
+- * Generic buffer used to store a local copy of portions of a remote
+- * partition's reserved page (either its header and part_nasids mask,
+- * or its vars).
+- */
+-char *xpc_remote_copy_buffer;
+-void *xpc_remote_copy_buffer_base;
+-
+-
+-/*
+- * Guarantee that the kmalloc'd memory is cacheline aligned.
+- */
+-void *
+-xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+-{
+-	/* see if kmalloc will give us cachline aligned memory by default */
+-	*base = kmalloc(size, flags);
+-	if (*base == NULL) {
+-		return NULL;
+-	}
+-	if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+-		return *base;
+-	}
+-	kfree(*base);
+-
+-	/* nope, we'll have to do it ourselves */
+-	*base = kmalloc(size + L1_CACHE_BYTES, flags);
+-	if (*base == NULL) {
+-		return NULL;
+-	}
+-	return (void *) L1_CACHE_ALIGN((u64) *base);
+-}
+-
+-
+-/*
+- * Given a nasid, get the physical address of the  partition's reserved page
+- * for that nasid. This function returns 0 on any error.
+- */
+-static u64
+-xpc_get_rsvd_page_pa(int nasid)
+-{
+-	bte_result_t bte_res;
+-	s64 status;
+-	u64 cookie = 0;
+-	u64 rp_pa = nasid;	/* seed with nasid */
+-	u64 len = 0;
+-	u64 buf = buf;
+-	u64 buf_len = 0;
+-	void *buf_base = NULL;
+-
+-
+-	while (1) {
+-
+-		status = sn_partition_reserved_page_pa(buf, &cookie, &rp_pa,
+-								&len);
+-
+-		dev_dbg(xpc_part, "SAL returned with status=%li, cookie="
+-			"0x%016lx, address=0x%016lx, len=0x%016lx\n",
+-			status, cookie, rp_pa, len);
+-
+-		if (status != SALRET_MORE_PASSES) {
+-			break;
+-		}
+-
+-		if (L1_CACHE_ALIGN(len) > buf_len) {
+-			kfree(buf_base);
+-			buf_len = L1_CACHE_ALIGN(len);
+-			buf = (u64) xpc_kmalloc_cacheline_aligned(buf_len,
+-							GFP_KERNEL, &buf_base);
+-			if (buf_base == NULL) {
+-				dev_err(xpc_part, "unable to kmalloc "
+-					"len=0x%016lx\n", buf_len);
+-				status = SALRET_ERROR;
+-				break;
+-			}
+-		}
+-
+-		bte_res = xp_bte_copy(rp_pa, buf, buf_len,
+-					(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+-		if (bte_res != BTE_SUCCESS) {
+-			dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
+-			status = SALRET_ERROR;
+-			break;
+-		}
+-	}
+-
+-	kfree(buf_base);
+-
+-	if (status != SALRET_OK) {
+-		rp_pa = 0;
+-	}
+-	dev_dbg(xpc_part, "reserved page at phys address 0x%016lx\n", rp_pa);
+-	return rp_pa;
+-}
+-
+-
+-/*
+- * Fill the partition reserved page with the information needed by
+- * other partitions to discover we are alive and establish initial
+- * communications.
+- */
+-struct xpc_rsvd_page *
+-xpc_rsvd_page_init(void)
+-{
+-	struct xpc_rsvd_page *rp;
+-	AMO_t *amos_page;
+-	u64 rp_pa, nasid_array = 0;
+-	int i, ret;
+-
+-
+-	/* get the local reserved page's address */
+-
+-	preempt_disable();
+-	rp_pa = xpc_get_rsvd_page_pa(cpuid_to_nasid(smp_processor_id()));
+-	preempt_enable();
+-	if (rp_pa == 0) {
+-		dev_err(xpc_part, "SAL failed to locate the reserved page\n");
+-		return NULL;
+-	}
+-	rp = (struct xpc_rsvd_page *) __va(rp_pa);
+-
+-	if (rp->partid != sn_partition_id) {
+-		dev_err(xpc_part, "the reserved page's partid of %d should be "
+-			"%d\n", rp->partid, sn_partition_id);
+-		return NULL;
+-	}
+-
+-	rp->version = XPC_RP_VERSION;
+-
+-	/* establish the actual sizes of the nasid masks */
+-	if (rp->SAL_version == 1) {
+-		/* SAL_version 1 didn't set the nasids_size field */
+-		rp->nasids_size = 128;
+-	}
+-	xp_nasid_mask_bytes = rp->nasids_size;
+-	xp_nasid_mask_words = xp_nasid_mask_bytes / 8;
+-
+-	/* setup the pointers to the various items in the reserved page */
+-	xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
+-	xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
+-	xpc_vars = XPC_RP_VARS(rp);
+-	xpc_vars_part = XPC_RP_VARS_PART(rp);
+-
+-	/*
+-	 * Before clearing xpc_vars, see if a page of AMOs had been previously
+-	 * allocated. If not we'll need to allocate one and set permissions
+-	 * so that cross-partition AMOs are allowed.
+-	 *
+-	 * The allocated AMO page needs MCA reporting to remain disabled after
+-	 * XPC has unloaded.  To make this work, we keep a copy of the pointer
+-	 * to this page (i.e., amos_page) in the struct xpc_vars structure,
+-	 * which is pointed to by the reserved page, and re-use that saved copy
+-	 * on subsequent loads of XPC. This AMO page is never freed, and its
+-	 * memory protections are never restricted.
+-	 */
+-	if ((amos_page = xpc_vars->amos_page) == NULL) {
+-		amos_page = (AMO_t *) TO_AMO(uncached_alloc_page(0));
+-		if (amos_page == NULL) {
+-			dev_err(xpc_part, "can't allocate page of AMOs\n");
+-			return NULL;
+-		}
+-
+-		/*
+-		 * Open up AMO-R/W to cpu.  This is done for Shub 1.1 systems
+-		 * when xpc_allow_IPI_ops() is called via xpc_hb_init().
+-		 */
+-		if (!enable_shub_wars_1_1()) {
+-			ret = sn_change_memprotect(ia64_tpa((u64) amos_page),
+-					PAGE_SIZE, SN_MEMPROT_ACCESS_CLASS_1,
+-					&nasid_array);
+-			if (ret != 0) {
+-				dev_err(xpc_part, "can't change memory "
+-					"protections\n");
+-				uncached_free_page(__IA64_UNCACHED_OFFSET |
+-						   TO_PHYS((u64) amos_page));
+-				return NULL;
+-			}
+-		}
+-	} else if (!IS_AMO_ADDRESS((u64) amos_page)) {
+-		/*
+-		 * EFI's XPBOOT can also set amos_page in the reserved page,
+-		 * but it happens to leave it as an uncached physical address
+-		 * and we need it to be an uncached virtual, so we'll have to
+-		 * convert it.
+-		 */
+-		if (!IS_AMO_PHYS_ADDRESS((u64) amos_page)) {
+-			dev_err(xpc_part, "previously used amos_page address "
+-				"is bad = 0x%p\n", (void *) amos_page);
+-			return NULL;
+-		}
+-		amos_page = (AMO_t *) TO_AMO((u64) amos_page);
+-	}
+-
+-	/* clear xpc_vars */
+-	memset(xpc_vars, 0, sizeof(struct xpc_vars));
+-
+-	xpc_vars->version = XPC_V_VERSION;
+-	xpc_vars->act_nasid = cpuid_to_nasid(0);
+-	xpc_vars->act_phys_cpuid = cpu_physical_id(0);
+-	xpc_vars->vars_part_pa = __pa(xpc_vars_part);
+-	xpc_vars->amos_page_pa = ia64_tpa((u64) amos_page);
+-	xpc_vars->amos_page = amos_page;  /* save for next load of XPC */
+-
+-
+-	/* clear xpc_vars_part */
+-	memset((u64 *) xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
+-							XP_MAX_PARTITIONS);
+-
+-	/* initialize the activate IRQ related AMO variables */
+-	for (i = 0; i < xp_nasid_mask_words; i++) {
+-		(void) xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
+-	}
+-
+-	/* initialize the engaged remote partitions related AMO variables */
+-	(void) xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
+-	(void) xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
+-
+-	/* timestamp of when reserved page was setup by XPC */
+-	rp->stamp = CURRENT_TIME;
+-
+-	/*
+-	 * This signifies to the remote partition that our reserved
+-	 * page is initialized.
+-	 */
+-	rp->vars_pa = __pa(xpc_vars);
+-
+-	return rp;
+-}
+-
+-
+-/*
+- * Change protections to allow IPI operations (and AMO operations on
+- * Shub 1.1 systems).
+- */
+-void
+-xpc_allow_IPI_ops(void)
+-{
+-	int node;
+-	int nasid;
+-
+-
+-	// >>> Change SH_IPI_ACCESS code to use SAL call once it is available.
+-
+-	if (is_shub2()) {
+-		xpc_sh2_IPI_access0 =
+-			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
+-		xpc_sh2_IPI_access1 =
+-			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
+-		xpc_sh2_IPI_access2 =
+-			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
+-		xpc_sh2_IPI_access3 =
+-			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
+-
+-		for_each_online_node(node) {
+-			nasid = cnodeid_to_nasid(node);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
+-								-1UL);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
+-								-1UL);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
+-								-1UL);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
+-								-1UL);
+-		}
+-
+-	} else {
+-		xpc_sh1_IPI_access =
+-			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
+-
+-		for_each_online_node(node) {
+-			nasid = cnodeid_to_nasid(node);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
+-								-1UL);
+-
+-			/*
+-			 * Since the BIST collides with memory operations on
+-			 * SHUB 1.1 sn_change_memprotect() cannot be used.
+-			 */
+-			if (enable_shub_wars_1_1()) {
+-				/* open up everything */
+-				xpc_prot_vec[node] = (u64) HUB_L((u64 *)
+-						GLOBAL_MMR_ADDR(nasid,
+-						SH1_MD_DQLP_MMR_DIR_PRIVEC0));
+-				HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+-						SH1_MD_DQLP_MMR_DIR_PRIVEC0),
+-								-1UL);
+-				HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+-						SH1_MD_DQRP_MMR_DIR_PRIVEC0),
+-								-1UL);
+-			}
+-		}
+-	}
+-}
+-
+-
+-/*
+- * Restrict protections to disallow IPI operations (and AMO operations on
+- * Shub 1.1 systems).
+- */
+-void
+-xpc_restrict_IPI_ops(void)
+-{
+-	int node;
+-	int nasid;
+-
+-
+-	// >>> Change SH_IPI_ACCESS code to use SAL call once it is available.
+-
+-	if (is_shub2()) {
+-
+-		for_each_online_node(node) {
+-			nasid = cnodeid_to_nasid(node);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
+-							xpc_sh2_IPI_access0);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
+-							xpc_sh2_IPI_access1);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
+-							xpc_sh2_IPI_access2);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
+-							xpc_sh2_IPI_access3);
+-		}
+-
+-	} else {
+-
+-		for_each_online_node(node) {
+-			nasid = cnodeid_to_nasid(node);
+-			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
+-							xpc_sh1_IPI_access);
+-
+-			if (enable_shub_wars_1_1()) {
+-				HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+-						SH1_MD_DQLP_MMR_DIR_PRIVEC0),
+-							xpc_prot_vec[node]);
+-				HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+-						SH1_MD_DQRP_MMR_DIR_PRIVEC0),
+-							xpc_prot_vec[node]);
+-			}
+-		}
+-	}
+-}
+-
+-
+-/*
+- * At periodic intervals, scan through all active partitions and ensure
+- * their heartbeat is still active.  If not, the partition is deactivated.
+- */
+-void
+-xpc_check_remote_hb(void)
+-{
+-	struct xpc_vars *remote_vars;
+-	struct xpc_partition *part;
+-	partid_t partid;
+-	bte_result_t bres;
+-
+-
+-	remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
+-
+-	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+-
+-		if (xpc_exiting) {
+-			break;
+-		}
+-
+-		if (partid == sn_partition_id) {
+-			continue;
+-		}
+-
+-		part = &xpc_partitions[partid];
+-
+-		if (part->act_state == XPC_P_INACTIVE ||
+-				part->act_state == XPC_P_DEACTIVATING) {
+-			continue;
+-		}
+-
+-		/* pull the remote_hb cache line */
+-		bres = xp_bte_copy(part->remote_vars_pa,
+-					(u64) remote_vars,
+-					XPC_RP_VARS_SIZE,
+-					(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+-		if (bres != BTE_SUCCESS) {
+-			XPC_DEACTIVATE_PARTITION(part,
+-						xpc_map_bte_errors(bres));
+-			continue;
+-		}
+-
+-		dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
+-			" = %ld, heartbeat_offline = %ld, HB_mask = 0x%lx\n",
+-			partid, remote_vars->heartbeat, part->last_heartbeat,
+-			remote_vars->heartbeat_offline,
+-			remote_vars->heartbeating_to_mask);
+-
+-		if (((remote_vars->heartbeat == part->last_heartbeat) &&
+-			(remote_vars->heartbeat_offline == 0)) ||
+-			     !xpc_hb_allowed(sn_partition_id, remote_vars)) {
+-
+-			XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);
+-			continue;
+-		}
+-
+-		part->last_heartbeat = remote_vars->heartbeat;
+-	}
+-}
+-
+-
+-/*
+- * Get a copy of a portion of the remote partition's rsvd page.
+- *
+- * remote_rp points to a buffer that is cacheline aligned for BTE copies and
+- * is large enough to contain a copy of their reserved page header and
+- * part_nasids mask.
+- */
+-static enum xpc_retval
+-xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
+-		struct xpc_rsvd_page *remote_rp, u64 *remote_rp_pa)
+-{
+-	int bres, i;
+-
+-
+-	/* get the reserved page's physical address */
+-
+-	*remote_rp_pa = xpc_get_rsvd_page_pa(nasid);
+-	if (*remote_rp_pa == 0) {
+-		return xpcNoRsvdPageAddr;
+-	}
+-
+-
+-	/* pull over the reserved page header and part_nasids mask */
+-	bres = xp_bte_copy(*remote_rp_pa, (u64) remote_rp,
+-				XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
+-				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+-	if (bres != BTE_SUCCESS) {
+-		return xpc_map_bte_errors(bres);
+-	}
+-
+-
+-	if (discovered_nasids != NULL) {
+-		u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp);
+-
+-
+-		for (i = 0; i < xp_nasid_mask_words; i++) {
+-			discovered_nasids[i] |= remote_part_nasids[i];
+-		}
+-	}
+-
+-
+-	/* check that the partid is for another partition */
+-
+-	if (remote_rp->partid < 1 ||
+-				remote_rp->partid > (XP_MAX_PARTITIONS - 1)) {
+-		return xpcInvalidPartid;
+-	}
+-
+-	if (remote_rp->partid == sn_partition_id) {
+-		return xpcLocalPartid;
+-	}
+-
+-
+-	if (XPC_VERSION_MAJOR(remote_rp->version) !=
+-					XPC_VERSION_MAJOR(XPC_RP_VERSION)) {
+-		return xpcBadVersion;
+-	}
+-
+-	return xpcSuccess;
+-}
+-
+-
+-/*
+- * Get a copy of the remote partition's XPC variables from the reserved page.
+- *
+- * remote_vars points to a buffer that is cacheline aligned for BTE copies and
+- * assumed to be of size XPC_RP_VARS_SIZE.
+- */
+-static enum xpc_retval
+-xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
+-{
+-	int bres;
+-
+-
+-	if (remote_vars_pa == 0) {
+-		return xpcVarsNotSet;
+-	}
+-
+-	/* pull over the cross partition variables */
+-	bres = xp_bte_copy(remote_vars_pa, (u64) remote_vars, XPC_RP_VARS_SIZE,
+-				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+-	if (bres != BTE_SUCCESS) {
+-		return xpc_map_bte_errors(bres);
+-	}
+-
+-	if (XPC_VERSION_MAJOR(remote_vars->version) !=
+-					XPC_VERSION_MAJOR(XPC_V_VERSION)) {
+-		return xpcBadVersion;
+-	}
+-
+-	return xpcSuccess;
+-}
+-
+-
+-/*
+- * Update the remote partition's info.
+- */
+-static void
+-xpc_update_partition_info(struct xpc_partition *part, u8 remote_rp_version,
+-		struct timespec *remote_rp_stamp, u64 remote_rp_pa,
+-		u64 remote_vars_pa, struct xpc_vars *remote_vars)
+-{
+-	part->remote_rp_version = remote_rp_version;
+-	dev_dbg(xpc_part, "  remote_rp_version = 0x%016x\n",
+-		part->remote_rp_version);
+-
+-	part->remote_rp_stamp = *remote_rp_stamp;
+-	dev_dbg(xpc_part, "  remote_rp_stamp (tv_sec = 0x%lx tv_nsec = 0x%lx\n",
+-		part->remote_rp_stamp.tv_sec, part->remote_rp_stamp.tv_nsec);
+-
+-	part->remote_rp_pa = remote_rp_pa;
+-	dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
+-
+-	part->remote_vars_pa = remote_vars_pa;
+-	dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
+-		part->remote_vars_pa);
+-
+-	part->last_heartbeat = remote_vars->heartbeat;
+-	dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
+-		part->last_heartbeat);
+-
+-	part->remote_vars_part_pa = remote_vars->vars_part_pa;
+-	dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
+-		part->remote_vars_part_pa);
+-
+-	part->remote_act_nasid = remote_vars->act_nasid;
+-	dev_dbg(xpc_part, "  remote_act_nasid = 0x%x\n",
+-		part->remote_act_nasid);
+-
+-	part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
+-	dev_dbg(xpc_part, "  remote_act_phys_cpuid = 0x%x\n",
+-		part->remote_act_phys_cpuid);
+-
+-	part->remote_amos_page_pa = remote_vars->amos_page_pa;
+-	dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
+-		part->remote_amos_page_pa);
+-
+-	part->remote_vars_version = remote_vars->version;
+-	dev_dbg(xpc_part, "  remote_vars_version = 0x%x\n",
+-		part->remote_vars_version);
+-}
+-
+-
+-/*
+- * Prior code has determined the nasid which generated an IPI.  Inspect
+- * that nasid to determine if its partition needs to be activated or
+- * deactivated.
+- *
+- * A partition is consider "awaiting activation" if our partition
+- * flags indicate it is not active and it has a heartbeat.  A
+- * partition is considered "awaiting deactivation" if our partition
+- * flags indicate it is active but it has no heartbeat or it is not
+- * sending its heartbeat to us.
+- *
+- * To determine the heartbeat, the remote nasid must have a properly
+- * initialized reserved page.
+- */
+-static void
+-xpc_identify_act_IRQ_req(int nasid)
+-{
+-	struct xpc_rsvd_page *remote_rp;
+-	struct xpc_vars *remote_vars;
+-	u64 remote_rp_pa;
+-	u64 remote_vars_pa;
+-	int remote_rp_version;
+-	int reactivate = 0;
+-	int stamp_diff;
+-	struct timespec remote_rp_stamp = { 0, 0 };
+-	partid_t partid;
+-	struct xpc_partition *part;
+-	enum xpc_retval ret;
+-
+-
+-	/* pull over the reserved page structure */
+-
+-	remote_rp = (struct xpc_rsvd_page *) xpc_remote_copy_buffer;
+-
+-	ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
+-	if (ret != xpcSuccess) {
+-		dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
+-			"which sent interrupt, reason=%d\n", nasid, ret);
+-		return;
+-	}
+-
+-	remote_vars_pa = remote_rp->vars_pa;
+-	remote_rp_version = remote_rp->version;
+-	if (XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+-		remote_rp_stamp = remote_rp->stamp;
+-	}
+-	partid = remote_rp->partid;
+-	part = &xpc_partitions[partid];
+-
+-
+-	/* pull over the cross partition variables */
+-
+-	remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
+-
+-	ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
+-	if (ret != xpcSuccess) {
+-
+-		dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
+-			"which sent interrupt, reason=%d\n", nasid, ret);
+-
+-		XPC_DEACTIVATE_PARTITION(part, ret);
+-		return;
+-	}
+-
+-
+-	part->act_IRQ_rcvd++;
+-
+-	dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
+-		"%ld:0x%lx\n", (int) nasid, (int) partid, part->act_IRQ_rcvd,
+-		remote_vars->heartbeat, remote_vars->heartbeating_to_mask);
+-
+-	if (xpc_partition_disengaged(part) &&
+-					part->act_state == XPC_P_INACTIVE) {
+-
+-		xpc_update_partition_info(part, remote_rp_version,
+-					&remote_rp_stamp, remote_rp_pa,
+-					remote_vars_pa, remote_vars);
+-
+-		if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+-			if (xpc_partition_disengage_requested(1UL << partid)) {
+-				/*
+-				 * Other side is waiting on us to disengage,
+-				 * even though we already have.
+-				 */
+-				return;
+-			}
+-		} else {
+-			/* other side doesn't support disengage requests */
+-			xpc_clear_partition_disengage_request(1UL << partid);
+-		}
+-
+-		xpc_activate_partition(part);
+-		return;
+-	}
+-
+-	DBUG_ON(part->remote_rp_version == 0);
+-	DBUG_ON(part->remote_vars_version == 0);
+-
+-	if (!XPC_SUPPORTS_RP_STAMP(part->remote_rp_version)) {
+-		DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(part->
+-							remote_vars_version));
+-
+-		if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+-			DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
+-								version));
+-			/* see if the other side rebooted */
+-			if (part->remote_amos_page_pa ==
+-				remote_vars->amos_page_pa &&
+-					xpc_hb_allowed(sn_partition_id,
+-								remote_vars)) {
+-				/* doesn't look that way, so ignore the IPI */
+-				return;
+-			}
+-		}
+-
+-		/*
+-		 * Other side rebooted and previous XPC didn't support the
+-		 * disengage request, so we don't need to do anything special.
+-		 */
+-
+-		xpc_update_partition_info(part, remote_rp_version,
+-						&remote_rp_stamp, remote_rp_pa,
+-						remote_vars_pa, remote_vars);
+-		part->reactivate_nasid = nasid;
+-		XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+-		return;
+-	}
+-
+-	DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version));
+-
+-	if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+-		DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
+-
+-		/*
+-		 * Other side rebooted and previous XPC did support the
+-		 * disengage request, but the new one doesn't.
+-		 */
+-
+-		xpc_clear_partition_engaged(1UL << partid);
+-		xpc_clear_partition_disengage_request(1UL << partid);
+-
+-		xpc_update_partition_info(part, remote_rp_version,
+-						&remote_rp_stamp, remote_rp_pa,
+-						remote_vars_pa, remote_vars);
+-		reactivate = 1;
+-
+-	} else {
+-		DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
+-
+-		stamp_diff = xpc_compare_stamps(&part->remote_rp_stamp,
+-							&remote_rp_stamp);
+-		if (stamp_diff != 0) {
+-			DBUG_ON(stamp_diff >= 0);
+-
+-			/*
+-			 * Other side rebooted and the previous XPC did support
+-			 * the disengage request, as does the new one.
+-			 */
+-
+-			DBUG_ON(xpc_partition_engaged(1UL << partid));
+-			DBUG_ON(xpc_partition_disengage_requested(1UL <<
+-								partid));
+-
+-			xpc_update_partition_info(part, remote_rp_version,
+-						&remote_rp_stamp, remote_rp_pa,
+-						remote_vars_pa, remote_vars);
+-			reactivate = 1;
+-		}
+-	}
+-
+-	if (part->disengage_request_timeout > 0 &&
+-					!xpc_partition_disengaged(part)) {
+-		/* still waiting on other side to disengage from us */
+-		return;
+-	}
+-
+-	if (reactivate) {
+-		part->reactivate_nasid = nasid;
+-		XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+-
+-	} else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) &&
+-			xpc_partition_disengage_requested(1UL << partid)) {
+-		XPC_DEACTIVATE_PARTITION(part, xpcOtherGoingDown);
+-	}
+-}
+-
+-
+-/*
+- * Loop through the activation AMO variables and process any bits
+- * which are set.  Each bit indicates a nasid sending a partition
+- * activation or deactivation request.
+- *
+- * Return #of IRQs detected.
+- */
+-int
+-xpc_identify_act_IRQ_sender(void)
+-{
+-	int word, bit;
+-	u64 nasid_mask;
+-	u64 nasid;			/* remote nasid */
+-	int n_IRQs_detected = 0;
+-	AMO_t *act_amos;
+-
+-
+-	act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
+-
+-
+-	/* scan through act AMO variable looking for non-zero entries */
+-	for (word = 0; word < xp_nasid_mask_words; word++) {
+-
+-		if (xpc_exiting) {
+-			break;
+-		}
+-
+-		nasid_mask = xpc_IPI_receive(&act_amos[word]);
+-		if (nasid_mask == 0) {
+-			/* no IRQs from nasids in this variable */
+-			continue;
+-		}
+-
+-		dev_dbg(xpc_part, "AMO[%d] gave back 0x%lx\n", word,
+-			nasid_mask);
+-
+-
+-		/*
+-		 * If this nasid has been added to the machine since
+-		 * our partition was reset, this will retain the
+-		 * remote nasid in our reserved pages machine mask.
+-		 * This is used in the event of module reload.
+-		 */
+-		xpc_mach_nasids[word] |= nasid_mask;
+-
+-
+-		/* locate the nasid(s) which sent interrupts */
+-
+-		for (bit = 0; bit < (8 * sizeof(u64)); bit++) {
+-			if (nasid_mask & (1UL << bit)) {
+-				n_IRQs_detected++;
+-				nasid = XPC_NASID_FROM_W_B(word, bit);
+-				dev_dbg(xpc_part, "interrupt from nasid %ld\n",
+-					nasid);
+-				xpc_identify_act_IRQ_req(nasid);
+-			}
+-		}
+-	}
+-	return n_IRQs_detected;
+-}
+-
+-
+-/*
+- * See if the other side has responded to a partition disengage request
+- * from us.
+- */
+-int
+-xpc_partition_disengaged(struct xpc_partition *part)
+-{
+-	partid_t partid = XPC_PARTID(part);
+-	int disengaged;
+-
+-
+-	disengaged = (xpc_partition_engaged(1UL << partid) == 0);
+-	if (part->disengage_request_timeout) {
+-		if (!disengaged) {
+-			if (jiffies < part->disengage_request_timeout) {
+-				/* timelimit hasn't been reached yet */
+-				return 0;
+-			}
+-
+-			/*
+-			 * Other side hasn't responded to our disengage
+-			 * request in a timely fashion, so assume it's dead.
+-			 */
+-
+-			dev_info(xpc_part, "disengage from remote partition %d "
+-				"timed out\n", partid);
+-			xpc_disengage_request_timedout = 1;
+-			xpc_clear_partition_engaged(1UL << partid);
+-			disengaged = 1;
+-		}
+-		part->disengage_request_timeout = 0;
+-
+-		/* cancel the timer function, provided it's not us */
+-		if (!in_interrupt()) {
+-			del_singleshot_timer_sync(&part->
+-						      disengage_request_timer);
+-		}
+-
+-		DBUG_ON(part->act_state != XPC_P_DEACTIVATING &&
+-					part->act_state != XPC_P_INACTIVE);
+-		if (part->act_state != XPC_P_INACTIVE) {
+-			xpc_wakeup_channel_mgr(part);
+-		}
+-
+-		if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+-			xpc_cancel_partition_disengage_request(part);
+-		}
+-	}
+-	return disengaged;
+-}
+-
+-
+-/*
+- * Mark specified partition as active.
+- */
+-enum xpc_retval
+-xpc_mark_partition_active(struct xpc_partition *part)
+-{
+-	unsigned long irq_flags;
+-	enum xpc_retval ret;
+-
+-
+-	dev_dbg(xpc_part, "setting partition %d to ACTIVE\n", XPC_PARTID(part));
+-
+-	spin_lock_irqsave(&part->act_lock, irq_flags);
+-	if (part->act_state == XPC_P_ACTIVATING) {
+-		part->act_state = XPC_P_ACTIVE;
+-		ret = xpcSuccess;
+-	} else {
+-		DBUG_ON(part->reason == xpcSuccess);
+-		ret = part->reason;
+-	}
+-	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-
+-	return ret;
+-}
+-
+-
+-/*
+- * Notify XPC that the partition is down.
+- */
+-void
+-xpc_deactivate_partition(const int line, struct xpc_partition *part,
+-				enum xpc_retval reason)
+-{
+-	unsigned long irq_flags;
+-
+-
+-	spin_lock_irqsave(&part->act_lock, irq_flags);
+-
+-	if (part->act_state == XPC_P_INACTIVE) {
+-		XPC_SET_REASON(part, reason, line);
+-		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-		if (reason == xpcReactivating) {
+-			/* we interrupt ourselves to reactivate partition */
+-			xpc_IPI_send_reactivate(part);
+-		}
+-		return;
+-	}
+-	if (part->act_state == XPC_P_DEACTIVATING) {
+-		if ((part->reason == xpcUnloading && reason != xpcUnloading) ||
+-					reason == xpcReactivating) {
+-			XPC_SET_REASON(part, reason, line);
+-		}
+-		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-		return;
+-	}
+-
+-	part->act_state = XPC_P_DEACTIVATING;
+-	XPC_SET_REASON(part, reason, line);
+-
+-	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-
+-	if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+-		xpc_request_partition_disengage(part);
+-		xpc_IPI_send_disengage(part);
+-
+-		/* set a timelimit on the disengage request */
+-		part->disengage_request_timeout = jiffies +
+-					(xpc_disengage_request_timelimit * HZ);
+-		part->disengage_request_timer.expires =
+-					part->disengage_request_timeout;
+-		add_timer(&part->disengage_request_timer);
+-	}
+-
+-	dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
+-		XPC_PARTID(part), reason);
+-
+-	xpc_partition_going_down(part, reason);
+-}
+-
+-
+-/*
+- * Mark specified partition as inactive.
+- */
+-void
+-xpc_mark_partition_inactive(struct xpc_partition *part)
+-{
+-	unsigned long irq_flags;
+-
+-
+-	dev_dbg(xpc_part, "setting partition %d to INACTIVE\n",
+-		XPC_PARTID(part));
+-
+-	spin_lock_irqsave(&part->act_lock, irq_flags);
+-	part->act_state = XPC_P_INACTIVE;
+-	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-	part->remote_rp_pa = 0;
+-}
+-
+-
+-/*
+- * SAL has provided a partition and machine mask.  The partition mask
+- * contains a bit for each even nasid in our partition.  The machine
+- * mask contains a bit for each even nasid in the entire machine.
+- *
+- * Using those two bit arrays, we can determine which nasids are
+- * known in the machine.  Each should also have a reserved page
+- * initialized if they are available for partitioning.
+- */
+-void
+-xpc_discovery(void)
+-{
+-	void *remote_rp_base;
+-	struct xpc_rsvd_page *remote_rp;
+-	struct xpc_vars *remote_vars;
+-	u64 remote_rp_pa;
+-	u64 remote_vars_pa;
+-	int region;
+-	int region_size;
+-	int max_regions;
+-	int nasid;
+-	struct xpc_rsvd_page *rp;
+-	partid_t partid;
+-	struct xpc_partition *part;
+-	u64 *discovered_nasids;
+-	enum xpc_retval ret;
+-
+-
+-	remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
+-						xp_nasid_mask_bytes,
+-						GFP_KERNEL, &remote_rp_base);
+-	if (remote_rp == NULL) {
+-		return;
+-	}
+-	remote_vars = (struct xpc_vars *) remote_rp;
+-
+-
+-	discovered_nasids = kzalloc(sizeof(u64) * xp_nasid_mask_words,
+-							GFP_KERNEL);
+-	if (discovered_nasids == NULL) {
+-		kfree(remote_rp_base);
+-		return;
+-	}
+-
+-	rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
+-
+-	/*
+-	 * The term 'region' in this context refers to the minimum number of
+-	 * nodes that can comprise an access protection grouping. The access
+-	 * protection is in regards to memory, IOI and IPI.
+-	 */
+-	max_regions = 64;
+-	region_size = sn_region_size;
+-
+-	switch (region_size) {
+-	case 128:
+-		max_regions *= 2;
+-	case 64:
+-		max_regions *= 2;
+-	case 32:
+-		max_regions *= 2;
+-		region_size = 16;
+-		DBUG_ON(!is_shub2());
+-	}
+-
+-	for (region = 0; region < max_regions; region++) {
+-
+-		if ((volatile int) xpc_exiting) {
+-			break;
+-		}
+-
+-		dev_dbg(xpc_part, "searching region %d\n", region);
+-
+-		for (nasid = (region * region_size * 2);
+-		     nasid < ((region + 1) * region_size * 2);
+-		     nasid += 2) {
+-
+-			if ((volatile int) xpc_exiting) {
+-				break;
+-			}
+-
+-			dev_dbg(xpc_part, "checking nasid %d\n", nasid);
+-
+-
+-			if (XPC_NASID_IN_ARRAY(nasid, xpc_part_nasids)) {
+-				dev_dbg(xpc_part, "PROM indicates Nasid %d is "
+-					"part of the local partition; skipping "
+-					"region\n", nasid);
+-				break;
+-			}
+-
+-			if (!(XPC_NASID_IN_ARRAY(nasid, xpc_mach_nasids))) {
+-				dev_dbg(xpc_part, "PROM indicates Nasid %d was "
+-					"not on Numa-Link network at reset\n",
+-					nasid);
+-				continue;
+-			}
+-
+-			if (XPC_NASID_IN_ARRAY(nasid, discovered_nasids)) {
+-				dev_dbg(xpc_part, "Nasid %d is part of a "
+-					"partition which was previously "
+-					"discovered\n", nasid);
+-				continue;
+-			}
+-
+-
+-			/* pull over the reserved page structure */
+-
+-			ret = xpc_get_remote_rp(nasid, discovered_nasids,
+-					      remote_rp, &remote_rp_pa);
+-			if (ret != xpcSuccess) {
+-				dev_dbg(xpc_part, "unable to get reserved page "
+-					"from nasid %d, reason=%d\n", nasid,
+-					ret);
+-
+-				if (ret == xpcLocalPartid) {
+-					break;
+-				}
+-				continue;
+-			}
+-
+-			remote_vars_pa = remote_rp->vars_pa;
+-
+-			partid = remote_rp->partid;
+-			part = &xpc_partitions[partid];
+-
+-
+-			/* pull over the cross partition variables */
+-
+-			ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
+-			if (ret != xpcSuccess) {
+-				dev_dbg(xpc_part, "unable to get XPC variables "
+-					"from nasid %d, reason=%d\n", nasid,
+-					ret);
+-
+-				XPC_DEACTIVATE_PARTITION(part, ret);
+-				continue;
+-			}
+-
+-			if (part->act_state != XPC_P_INACTIVE) {
+-				dev_dbg(xpc_part, "partition %d on nasid %d is "
+-					"already activating\n", partid, nasid);
+-				break;
+-			}
+-
+-			/*
+-			 * Register the remote partition's AMOs with SAL so it
+-			 * can handle and cleanup errors within that address
+-			 * range should the remote partition go down. We don't
+-			 * unregister this range because it is difficult to
+-			 * tell when outstanding writes to the remote partition
+-			 * are finished and thus when it is thus safe to
+-			 * unregister. This should not result in wasted space
+-			 * in the SAL xp_addr_region table because we should
+-			 * get the same page for remote_act_amos_pa after
+-			 * module reloads and system reboots.
+-			 */
+-			if (sn_register_xp_addr_region(
+-					    remote_vars->amos_page_pa,
+-							PAGE_SIZE, 1) < 0) {
+-				dev_dbg(xpc_part, "partition %d failed to "
+-					"register xp_addr region 0x%016lx\n",
+-					partid, remote_vars->amos_page_pa);
+-
+-				XPC_SET_REASON(part, xpcPhysAddrRegFailed,
+-						__LINE__);
+-				break;
+-			}
+-
+-			/*
+-			 * The remote nasid is valid and available.
+-			 * Send an interrupt to that nasid to notify
+-			 * it that we are ready to begin activation.
+-			 */
+-			dev_dbg(xpc_part, "sending an interrupt to AMO 0x%lx, "
+-				"nasid %d, phys_cpuid 0x%x\n",
+-				remote_vars->amos_page_pa,
+-				remote_vars->act_nasid,
+-				remote_vars->act_phys_cpuid);
+-
+-			if (XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
+-								version)) {
+-				part->remote_amos_page_pa =
+-						remote_vars->amos_page_pa;
+-				xpc_mark_partition_disengaged(part);
+-				xpc_cancel_partition_disengage_request(part);
+-			}
+-			xpc_IPI_send_activate(remote_vars);
+-		}
+-	}
+-
+-	kfree(discovered_nasids);
+-	kfree(remote_rp_base);
+-}
+-
+-
+-/*
+- * Given a partid, get the nasids owned by that partition from the
+- * remote partition's reserved page.
+- */
+-enum xpc_retval
+-xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
+-{
+-	struct xpc_partition *part;
+-	u64 part_nasid_pa;
+-	int bte_res;
+-
+-
+-	part = &xpc_partitions[partid];
+-	if (part->remote_rp_pa == 0) {
+-		return xpcPartitionDown;
+-	}
+-
+-	memset(nasid_mask, 0, XP_NASID_MASK_BYTES);
+-
+-	part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa);
+-
+-	bte_res = xp_bte_copy(part_nasid_pa, (u64) nasid_mask,
+-			xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+-
+-	return xpc_map_bte_errors(bte_res);
+-}
+-
+diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c
+deleted file mode 100644
+index a5df672..0000000
+--- a/arch/ia64/sn/kernel/xpnet.c
++++ /dev/null
+@@ -1,718 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Network Interface (XPNET) support
+- *
+- *	XPNET provides a virtual network layered on top of the Cross
+- *	Partition communication layer.
+- *
+- *	XPNET provides direct point-to-point and broadcast-like support
+- *	for an ethernet-like device.  The ethernet broadcast medium is
+- *	replaced with a point-to-point message structure which passes
+- *	pointers to a DMA-capable block that a remote partition should
+- *	retrieve and pass to the upper level networking layer.
+- *
+- */
+-
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/ioport.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/delay.h>
+-#include <linux/ethtool.h>
+-#include <linux/mii.h>
+-#include <linux/smp.h>
+-#include <linux/string.h>
+-#include <asm/sn/bte.h>
+-#include <asm/sn/io.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/types.h>
+-#include <asm/atomic.h>
+-#include <asm/sn/xp.h>
+-
+-
+-/*
+- * The message payload transferred by XPC.
+- *
+- * buf_pa is the physical address where the DMA should pull from.
+- *
+- * NOTE: for performance reasons, buf_pa should _ALWAYS_ begin on a
+- * cacheline boundary.  To accomplish this, we record the number of
+- * bytes from the beginning of the first cacheline to the first useful
+- * byte of the skb (leadin_ignore) and the number of bytes from the
+- * last useful byte of the skb to the end of the last cacheline
+- * (tailout_ignore).
+- *
+- * size is the number of bytes to transfer which includes the skb->len
+- * (useful bytes of the senders skb) plus the leadin and tailout
+- */
+-struct xpnet_message {
+-	u16 version;		/* Version for this message */
+-	u16 embedded_bytes;	/* #of bytes embedded in XPC message */
+-	u32 magic;		/* Special number indicating this is xpnet */
+-	u64 buf_pa;		/* phys address of buffer to retrieve */
+-	u32 size;		/* #of bytes in buffer */
+-	u8 leadin_ignore;	/* #of bytes to ignore at the beginning */
+-	u8 tailout_ignore;	/* #of bytes to ignore at the end */
+-	unsigned char data;	/* body of small packets */
+-};
+-
+-/*
+- * Determine the size of our message, the cacheline aligned size,
+- * and then the number of message will request from XPC.
+- *
+- * XPC expects each message to exist in an individual cacheline.
+- */
+-#define XPNET_MSG_SIZE		(L1_CACHE_BYTES - XPC_MSG_PAYLOAD_OFFSET)
+-#define XPNET_MSG_DATA_MAX	\
+-		(XPNET_MSG_SIZE - (u64)(&((struct xpnet_message *)0)->data))
+-#define XPNET_MSG_ALIGNED_SIZE	(L1_CACHE_ALIGN(XPNET_MSG_SIZE))
+-#define XPNET_MSG_NENTRIES	(PAGE_SIZE / XPNET_MSG_ALIGNED_SIZE)
+-
+-
+-#define XPNET_MAX_KTHREADS	(XPNET_MSG_NENTRIES + 1)
+-#define XPNET_MAX_IDLE_KTHREADS	(XPNET_MSG_NENTRIES + 1)
+-
+-/*
+- * Version number of XPNET implementation. XPNET can always talk to versions
+- * with same major #, and never talk to versions with a different version.
+- */
+-#define _XPNET_VERSION(_major, _minor)	(((_major) << 4) | (_minor))
+-#define XPNET_VERSION_MAJOR(_v)		((_v) >> 4)
+-#define XPNET_VERSION_MINOR(_v)		((_v) & 0xf)
+-
+-#define	XPNET_VERSION _XPNET_VERSION(1,0)		/* version 1.0 */
+-#define	XPNET_VERSION_EMBED _XPNET_VERSION(1,1)		/* version 1.1 */
+-#define XPNET_MAGIC	0x88786984 /* "XNET" */
+-
+-#define XPNET_VALID_MSG(_m)						     \
+-   ((XPNET_VERSION_MAJOR(_m->version) == XPNET_VERSION_MAJOR(XPNET_VERSION)) \
+-    && (msg->magic == XPNET_MAGIC))
+-
+-#define XPNET_DEVICE_NAME		"xp0"
+-
+-
+-/*
+- * When messages are queued with xpc_send_notify, a kmalloc'd buffer
+- * of the following type is passed as a notification cookie.  When the
+- * notification function is called, we use the cookie to decide
+- * whether all outstanding message sends have completed.  The skb can
+- * then be released.
+- */
+-struct xpnet_pending_msg {
+-	struct list_head free_list;
+-	struct sk_buff *skb;
+-	atomic_t use_count;
+-};
+-
+-/* driver specific structure pointed to by the device structure */
+-struct xpnet_dev_private {
+-	struct net_device_stats stats;
+-};
+-
+-struct net_device *xpnet_device;
+-
+-/*
+- * When we are notified of other partitions activating, we add them to
+- * our bitmask of partitions to which we broadcast.
+- */
+-static u64 xpnet_broadcast_partitions;
+-/* protect above */
+-static DEFINE_SPINLOCK(xpnet_broadcast_lock);
+-
+-/*
+- * Since the Block Transfer Engine (BTE) is being used for the transfer
+- * and it relies upon cache-line size transfers, we need to reserve at
+- * least one cache-line for head and tail alignment.  The BTE is
+- * limited to 8MB transfers.
+- *
+- * Testing has shown that changing MTU to greater than 64KB has no effect
+- * on TCP as the two sides negotiate a Max Segment Size that is limited
+- * to 64K.  Other protocols May use packets greater than this, but for
+- * now, the default is 64KB.
+- */
+-#define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
+-/* 32KB has been determined to be the ideal */
+-#define XPNET_DEF_MTU (0x8000UL)
+-
+-
+-/*
+- * The partition id is encapsulated in the MAC address.  The following
+- * define locates the octet the partid is in.
+- */
+-#define XPNET_PARTID_OCTET	1
+-#define XPNET_LICENSE_OCTET	2
+-
+-
+-/*
+- * Define the XPNET debug device structure that is to be used with dev_dbg(),
+- * dev_err(), dev_warn(), and dev_info().
+- */
+-struct device_driver xpnet_dbg_name = {
+-	.name = "xpnet"
+-};
+-
+-struct device xpnet_dbg_subname = {
+-	.bus_id = {0},			/* set to "" */
+-	.driver = &xpnet_dbg_name
+-};
+-
+-struct device *xpnet = &xpnet_dbg_subname;
+-
+-/*
+- * Packet was recevied by XPC and forwarded to us.
+- */
+-static void
+-xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg)
+-{
+-	struct sk_buff *skb;
+-	bte_result_t bret;
+-	struct xpnet_dev_private *priv =
+-		(struct xpnet_dev_private *) xpnet_device->priv;
+-
+-
+-	if (!XPNET_VALID_MSG(msg)) {
+-		/*
+-		 * Packet with a different XPC version.  Ignore.
+-		 */
+-		xpc_received(partid, channel, (void *) msg);
+-
+-		priv->stats.rx_errors++;
+-
+-		return;
+-	}
+-	dev_dbg(xpnet, "received 0x%lx, %d, %d, %d\n", msg->buf_pa, msg->size,
+-		msg->leadin_ignore, msg->tailout_ignore);
+-
+-
+-	/* reserve an extra cache line */
+-	skb = dev_alloc_skb(msg->size + L1_CACHE_BYTES);
+-	if (!skb) {
+-		dev_err(xpnet, "failed on dev_alloc_skb(%d)\n",
+-			msg->size + L1_CACHE_BYTES);
+-
+-		xpc_received(partid, channel, (void *) msg);
+-
+-		priv->stats.rx_errors++;
+-
+-		return;
+-	}
+-
+-	/*
+-	 * The allocated skb has some reserved space.
+-	 * In order to use bte_copy, we need to get the
+-	 * skb->data pointer moved forward.
+-	 */
+-	skb_reserve(skb, (L1_CACHE_BYTES - ((u64)skb->data &
+-					    (L1_CACHE_BYTES - 1)) +
+-			  msg->leadin_ignore));
+-
+-	/*
+-	 * Update the tail pointer to indicate data actually
+-	 * transferred.
+-	 */
+-	skb_put(skb, (msg->size - msg->leadin_ignore - msg->tailout_ignore));
+-
+-	/*
+-	 * Move the data over from the other side.
+-	 */
+-	if ((XPNET_VERSION_MINOR(msg->version) == 1) &&
+-						(msg->embedded_bytes != 0)) {
+-		dev_dbg(xpnet, "copying embedded message. memcpy(0x%p, 0x%p, "
+-			"%lu)\n", skb->data, &msg->data,
+-			(size_t) msg->embedded_bytes);
+-
+-		skb_copy_to_linear_data(skb, &msg->data, (size_t)msg->embedded_bytes);
+-	} else {
+-		dev_dbg(xpnet, "transferring buffer to the skb->data area;\n\t"
+-			"bte_copy(0x%p, 0x%p, %hu)\n", (void *)msg->buf_pa,
+-			(void *)__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
+-			msg->size);
+-
+-		bret = bte_copy(msg->buf_pa,
+-				__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
+-				msg->size, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+-
+-		if (bret != BTE_SUCCESS) {
+-			// >>> Need better way of cleaning skb.  Currently skb
+-			// >>> appears in_use and we can't just call
+-			// >>> dev_kfree_skb.
+-			dev_err(xpnet, "bte_copy(0x%p, 0x%p, 0x%hx) returned "
+-				"error=0x%x\n", (void *)msg->buf_pa,
+-				(void *)__pa((u64)skb->data &
+-							~(L1_CACHE_BYTES - 1)),
+-				msg->size, bret);
+-
+-			xpc_received(partid, channel, (void *) msg);
+-
+-			priv->stats.rx_errors++;
+-
+-			return;
+-		}
+-	}
+-
+-	dev_dbg(xpnet, "<skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+-		"skb->end=0x%p skb->len=%d\n", (void *) skb->head,
+-		(void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
+-		skb->len);
+-
+-	skb->protocol = eth_type_trans(skb, xpnet_device);
+-	skb->ip_summed = CHECKSUM_UNNECESSARY;
+-
+-	dev_dbg(xpnet, "passing skb to network layer\n"
+-		KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+-		"skb->end=0x%p skb->len=%d\n",
+-		(void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
+-		skb_end_pointer(skb), skb->len);
+-
+-
+-	xpnet_device->last_rx = jiffies;
+-	priv->stats.rx_packets++;
+-	priv->stats.rx_bytes += skb->len + ETH_HLEN;
+-
+-	netif_rx_ni(skb);
+-	xpc_received(partid, channel, (void *) msg);
+-}
+-
+-
+-/*
+- * This is the handler which XPC calls during any sort of change in
+- * state or message reception on a connection.
+- */
+-static void
+-xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel,
+-			  void *data, void *key)
+-{
+-	long bp;
+-
+-
+-	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+-	DBUG_ON(channel != XPC_NET_CHANNEL);
+-
+-	switch(reason) {
+-	case xpcMsgReceived:	/* message received */
+-		DBUG_ON(data == NULL);
+-
+-		xpnet_receive(partid, channel, (struct xpnet_message *) data);
+-		break;
+-
+-	case xpcConnected:	/* connection completed to a partition */
+-		spin_lock_bh(&xpnet_broadcast_lock);
+-		xpnet_broadcast_partitions |= 1UL << (partid -1 );
+-		bp = xpnet_broadcast_partitions;
+-		spin_unlock_bh(&xpnet_broadcast_lock);
+-
+-		netif_carrier_on(xpnet_device);
+-
+-		dev_dbg(xpnet, "%s connection created to partition %d; "
+-			"xpnet_broadcast_partitions=0x%lx\n",
+-			xpnet_device->name, partid, bp);
+-		break;
+-
+-	default:
+-		spin_lock_bh(&xpnet_broadcast_lock);
+-		xpnet_broadcast_partitions &= ~(1UL << (partid -1 ));
+-		bp = xpnet_broadcast_partitions;
+-		spin_unlock_bh(&xpnet_broadcast_lock);
+-
+-		if (bp == 0) {
+-			netif_carrier_off(xpnet_device);
+-		}
+-
+-		dev_dbg(xpnet, "%s disconnected from partition %d; "
+-			"xpnet_broadcast_partitions=0x%lx\n",
+-			xpnet_device->name, partid, bp);
+-		break;
+-
+-	}
+-}
+-
+-
+-static int
+-xpnet_dev_open(struct net_device *dev)
+-{
+-	enum xpc_retval ret;
+-
+-
+-	dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %ld, "
+-		"%ld)\n", XPC_NET_CHANNEL, xpnet_connection_activity,
+-		XPNET_MSG_SIZE, XPNET_MSG_NENTRIES, XPNET_MAX_KTHREADS,
+-		XPNET_MAX_IDLE_KTHREADS);
+-
+-	ret = xpc_connect(XPC_NET_CHANNEL, xpnet_connection_activity, NULL,
+-			  XPNET_MSG_SIZE, XPNET_MSG_NENTRIES,
+-			  XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS);
+-	if (ret != xpcSuccess) {
+-		dev_err(xpnet, "ifconfig up of %s failed on XPC connect, "
+-			"ret=%d\n", dev->name, ret);
+-
+-		return -ENOMEM;
+-	}
+-
+-	dev_dbg(xpnet, "ifconfig up of %s; XPC connected\n", dev->name);
+-
+-	return 0;
+-}
+-
+-
+-static int
+-xpnet_dev_stop(struct net_device *dev)
+-{
+-	xpc_disconnect(XPC_NET_CHANNEL);
+-
+-	dev_dbg(xpnet, "ifconfig down of %s; XPC disconnected\n", dev->name);
+-
+-	return 0;
+-}
+-
+-
+-static int
+-xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
+-{
+-	/* 68 comes from min TCP+IP+MAC header */
+-	if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {
+-		dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "
+-			"between 68 and %ld\n", dev->name, new_mtu,
+-			XPNET_MAX_MTU);
+-		return -EINVAL;
+-	}
+-
+-	dev->mtu = new_mtu;
+-	dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);
+-	return 0;
+-}
+-
+-
+-/*
+- * Required for the net_device structure.
+- */
+-static int
+-xpnet_dev_set_config(struct net_device *dev, struct ifmap *new_map)
+-{
+-	return 0;
+-}
+-
+-
+-/*
+- * Return statistics to the caller.
+- */
+-static struct net_device_stats *
+-xpnet_dev_get_stats(struct net_device *dev)
+-{
+-	struct xpnet_dev_private *priv;
+-
+-
+-	priv = (struct xpnet_dev_private *) dev->priv;
+-
+-	return &priv->stats;
+-}
+-
+-
+-/*
+- * Notification that the other end has received the message and
+- * DMA'd the skb information.  At this point, they are done with
+- * our side.  When all recipients are done processing, we
+- * release the skb and then release our pending message structure.
+- */
+-static void
+-xpnet_send_completed(enum xpc_retval reason, partid_t partid, int channel,
+-			void *__qm)
+-{
+-	struct xpnet_pending_msg *queued_msg =
+-		(struct xpnet_pending_msg *) __qm;
+-
+-
+-	DBUG_ON(queued_msg == NULL);
+-
+-	dev_dbg(xpnet, "message to %d notified with reason %d\n",
+-		partid, reason);
+-
+-	if (atomic_dec_return(&queued_msg->use_count) == 0) {
+-		dev_dbg(xpnet, "all acks for skb->head=-x%p\n",
+-			(void *) queued_msg->skb->head);
+-
+-		dev_kfree_skb_any(queued_msg->skb);
+-		kfree(queued_msg);
+-	}
+-}
+-
+-
+-/*
+- * Network layer has formatted a packet (skb) and is ready to place it
+- * "on the wire".  Prepare and send an xpnet_message to all partitions
+- * which have connected with us and are targets of this packet.
+- *
+- * MAC-NOTE:  For the XPNET driver, the MAC address contains the
+- * destination partition_id.  If the destination partition id word
+- * is 0xff, this packet is to broadcast to all partitions.
+- */
+-static int
+-xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+-{
+-	struct xpnet_pending_msg *queued_msg;
+-	enum xpc_retval ret;
+-	struct xpnet_message *msg;
+-	u64 start_addr, end_addr;
+-	long dp;
+-	u8 second_mac_octet;
+-	partid_t dest_partid;
+-	struct xpnet_dev_private *priv;
+-	u16 embedded_bytes;
+-
+-
+-	priv = (struct xpnet_dev_private *) dev->priv;
+-
+-
+-	dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+-		"skb->end=0x%p skb->len=%d\n", (void *) skb->head,
+-		(void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
+-		skb->len);
+-
+-
+-	/*
+-	 * The xpnet_pending_msg tracks how many outstanding
+-	 * xpc_send_notifies are relying on this skb.  When none
+-	 * remain, release the skb.
+-	 */
+-	queued_msg = kmalloc(sizeof(struct xpnet_pending_msg), GFP_ATOMIC);
+-	if (queued_msg == NULL) {
+-		dev_warn(xpnet, "failed to kmalloc %ld bytes; dropping "
+-			"packet\n", sizeof(struct xpnet_pending_msg));
+-
+-		priv->stats.tx_errors++;
+-
+-		return -ENOMEM;
+-	}
+-
+-
+-	/* get the beginning of the first cacheline and end of last */
+-	start_addr = ((u64) skb->data & ~(L1_CACHE_BYTES - 1));
+-	end_addr = L1_CACHE_ALIGN((u64)skb_tail_pointer(skb));
+-
+-	/* calculate how many bytes to embed in the XPC message */
+-	embedded_bytes = 0;
+-	if (unlikely(skb->len <= XPNET_MSG_DATA_MAX)) {
+-		/* skb->data does fit so embed */
+-		embedded_bytes = skb->len;
+-	}
+-
+-
+-	/*
+-	 * Since the send occurs asynchronously, we set the count to one
+-	 * and begin sending.  Any sends that happen to complete before
+-	 * we are done sending will not free the skb.  We will be left
+-	 * with that task during exit.  This also handles the case of
+-	 * a packet destined for a partition which is no longer up.
+-	 */
+-	atomic_set(&queued_msg->use_count, 1);
+-	queued_msg->skb = skb;
+-
+-
+-	second_mac_octet = skb->data[XPNET_PARTID_OCTET];
+-	if (second_mac_octet == 0xff) {
+-		/* we are being asked to broadcast to all partitions */
+-		dp = xpnet_broadcast_partitions;
+-	} else if (second_mac_octet != 0) {
+-		dp = xpnet_broadcast_partitions &
+-					(1UL << (second_mac_octet - 1));
+-	} else {
+-		/* 0 is an invalid partid.  Ignore */
+-		dp = 0;
+-	}
+-	dev_dbg(xpnet, "destination Partitions mask (dp) = 0x%lx\n", dp);
+-
+-	/*
+-	 * If we wanted to allow promiscuous mode to work like an
+-	 * unswitched network, this would be a good point to OR in a
+-	 * mask of partitions which should be receiving all packets.
+-	 */
+-
+-	/*
+-	 * Main send loop.
+-	 */
+-	for (dest_partid = 1; dp && dest_partid < XP_MAX_PARTITIONS;
+-	     dest_partid++) {
+-
+-
+-		if (!(dp & (1UL << (dest_partid - 1)))) {
+-			/* not destined for this partition */
+-			continue;
+-		}
+-
+-		/* remove this partition from the destinations mask */
+-		dp &= ~(1UL << (dest_partid - 1));
+-
+-
+-		/* found a partition to send to */
+-
+-		ret = xpc_allocate(dest_partid, XPC_NET_CHANNEL,
+-				   XPC_NOWAIT, (void **)&msg);
+-		if (unlikely(ret != xpcSuccess)) {
+-			continue;
+-		}
+-
+-		msg->embedded_bytes = embedded_bytes;
+-		if (unlikely(embedded_bytes != 0)) {
+-			msg->version = XPNET_VERSION_EMBED;
+-			dev_dbg(xpnet, "calling memcpy(0x%p, 0x%p, 0x%lx)\n",
+-				&msg->data, skb->data, (size_t) embedded_bytes);
+-			skb_copy_from_linear_data(skb, &msg->data,
+-						  (size_t)embedded_bytes);
+-		} else {
+-			msg->version = XPNET_VERSION;
+-		}
+-		msg->magic = XPNET_MAGIC;
+-		msg->size = end_addr - start_addr;
+-		msg->leadin_ignore = (u64) skb->data - start_addr;
+-		msg->tailout_ignore = end_addr - (u64)skb_tail_pointer(skb);
+-		msg->buf_pa = __pa(start_addr);
+-
+-		dev_dbg(xpnet, "sending XPC message to %d:%d\n"
+-			KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, "
+-			"msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
+-			dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
+-			msg->leadin_ignore, msg->tailout_ignore);
+-
+-
+-		atomic_inc(&queued_msg->use_count);
+-
+-		ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, msg,
+-				      xpnet_send_completed, queued_msg);
+-		if (unlikely(ret != xpcSuccess)) {
+-			atomic_dec(&queued_msg->use_count);
+-			continue;
+-		}
+-
+-	}
+-
+-	if (atomic_dec_return(&queued_msg->use_count) == 0) {
+-		dev_dbg(xpnet, "no partitions to receive packet destined for "
+-			"%d\n", dest_partid);
+-
+-
+-		dev_kfree_skb(skb);
+-		kfree(queued_msg);
+-	}
+-
+-	priv->stats.tx_packets++;
+-	priv->stats.tx_bytes += skb->len;
+-
+-	return 0;
+-}
+-
+-
+-/*
+- * Deal with transmit timeouts coming from the network layer.
+- */
+-static void
+-xpnet_dev_tx_timeout (struct net_device *dev)
+-{
+-	struct xpnet_dev_private *priv;
+-
+-
+-	priv = (struct xpnet_dev_private *) dev->priv;
+-
+-	priv->stats.tx_errors++;
+-	return;
+-}
+-
+-
+-static int __init
+-xpnet_init(void)
+-{
+-	int i;
+-	u32 license_num;
+-	int result = -ENOMEM;
+-
+-
+-	if (!ia64_platform_is("sn2")) {
+-		return -ENODEV;
+-	}
+-
+-	dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
+-
+-	/*
+-	 * use ether_setup() to init the majority of our device
+-	 * structure and then override the necessary pieces.
+-	 */
+-	xpnet_device = alloc_netdev(sizeof(struct xpnet_dev_private),
+-				    XPNET_DEVICE_NAME, ether_setup);
+-	if (xpnet_device == NULL) {
+-		return -ENOMEM;
+-	}
+-
+-	netif_carrier_off(xpnet_device);
+-
+-	xpnet_device->mtu = XPNET_DEF_MTU;
+-	xpnet_device->change_mtu = xpnet_dev_change_mtu;
+-	xpnet_device->open = xpnet_dev_open;
+-	xpnet_device->get_stats = xpnet_dev_get_stats;
+-	xpnet_device->stop = xpnet_dev_stop;
+-	xpnet_device->hard_start_xmit = xpnet_dev_hard_start_xmit;
+-	xpnet_device->tx_timeout = xpnet_dev_tx_timeout;
+-	xpnet_device->set_config = xpnet_dev_set_config;
+-
+-	/*
+-	 * Multicast assumes the LSB of the first octet is set for multicast
+-	 * MAC addresses.  We chose the first octet of the MAC to be unlikely
+-	 * to collide with any vendor's officially issued MAC.
+-	 */
+-	xpnet_device->dev_addr[0] = 0xfe;
+-	xpnet_device->dev_addr[XPNET_PARTID_OCTET] = sn_partition_id;
+-	license_num = sn_partition_serial_number_val();
+-	for (i = 3; i >= 0; i--) {
+-		xpnet_device->dev_addr[XPNET_LICENSE_OCTET + i] =
+-							license_num & 0xff;
+-		license_num = license_num >> 8;
+-	}
+-
+-	/*
+-	 * ether_setup() sets this to a multicast device.  We are
+-	 * really not supporting multicast at this time.
+-	 */
+-	xpnet_device->flags &= ~IFF_MULTICAST;
+-
+-	/*
+-	 * No need to checksum as it is a DMA transfer.  The BTE will
+-	 * report an error if the data is not retrievable and the
+-	 * packet will be dropped.
+-	 */
+-	xpnet_device->features = NETIF_F_NO_CSUM;
+-
+-	result = register_netdev(xpnet_device);
+-	if (result != 0) {
+-		free_netdev(xpnet_device);
+-	}
+-
+-	return result;
+-}
+-module_init(xpnet_init);
+-
+-
+-static void __exit
+-xpnet_exit(void)
+-{
+-	dev_info(xpnet, "unregistering network device %s\n",
+-		xpnet_device[0].name);
+-
+-	unregister_netdev(xpnet_device);
+-
+-	free_netdev(xpnet_device);
+-}
+-module_exit(xpnet_exit);
+-
+-
+-MODULE_AUTHOR("Silicon Graphics, Inc.");
+-MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");
+-MODULE_LICENSE("GPL");
+-
+diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
+index 9b3c113..94e5845 100644
+--- a/arch/ia64/sn/pci/tioce_provider.c
++++ b/arch/ia64/sn/pci/tioce_provider.c
+@@ -655,7 +655,8 @@ tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+  *
+  * Simply call tioce_do_dma_map() to create a map with the barrier bit set
+  * in the address.
+- */ static u64
++ */
++static u64
+ tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+ {
+ 	return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags);
+@@ -668,7 +669,8 @@ tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma
+  *
+  * Handle a CE error interrupt.  Simply a wrapper around a SAL call which
+  * defers processing to the SGI prom.
+- */ static irqreturn_t
++ */
++static irqreturn_t
+ tioce_error_intr_handler(int irq, void *arg)
+ {
+ 	struct tioce_common *soft = arg;
+diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
+index e97e26e..09200d4 100644
+--- a/arch/m32r/kernel/Makefile
++++ b/arch/m32r/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y	:= head.o init_task.o vmlinux.lds
+ 
+ obj-y	:= process.o entry.o traps.o align.o irq.o setup.o time.o \
+-	m32r_ksyms.o sys_m32r.o semaphore.o signal.o ptrace.o
++	m32r_ksyms.o sys_m32r.o signal.o ptrace.o
+ 
+ obj-$(CONFIG_SMP)		+= smp.o smpboot.o
+ obj-$(CONFIG_MODULES)		+= module.o
+diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
+index 41a4c95..e6709fe 100644
+--- a/arch/m32r/kernel/m32r_ksyms.c
++++ b/arch/m32r/kernel/m32r_ksyms.c
+@@ -7,7 +7,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/string.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+@@ -22,10 +21,6 @@ EXPORT_SYMBOL(dump_fpu);
+ EXPORT_SYMBOL(__ioremap);
+ EXPORT_SYMBOL(iounmap);
+ EXPORT_SYMBOL(kernel_thread);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down_trylock);
+ 
+ /* Networking helper routines. */
+ /* Delay loops */
+diff --git a/arch/m32r/kernel/semaphore.c b/arch/m32r/kernel/semaphore.c
+deleted file mode 100644
+index 940c2d3..0000000
+--- a/arch/m32r/kernel/semaphore.c
++++ /dev/null
+@@ -1,185 +0,0 @@
+-/*
+- *  linux/arch/m32r/semaphore.c
+- *    orig : i386 2.6.4
+- *
+- *  M32R semaphore implementation.
+- *
+- *	Copyright (c) 2002 - 2004 Hitoshi Yamamoto
+- */
+-
+-/*
+- * i386 semaphore implementation.
+- *
+- * (C) Copyright 1999 Linus Torvalds
+- *
+- * Portions Copyright 1999 Red Hat, Inc.
+- *
+- *	This program is free software; you can redistribute it and/or
+- *	modify it under the terms of the GNU General Public License
+- *	as published by the Free Software Foundation; either version
+- *	2 of the License, or (at your option) any later version.
+- *
+- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl at kvack.org>
+- */
+-#include <linux/sched.h>
+-#include <linux/err.h>
+-#include <linux/init.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is protected
+- * by the spinlock in the semaphore's waitqueue head.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- *  - only on a boundary condition do we need to care. When we go
+- *    from a negative count to a non-negative, we wake people up.
+- *  - when we go from a non-negative count to a negative do we
+- *    (a) synchronize with the "sleeper" count and (b) make sure
+- *    that we're on the wakeup list before we synchronize so that
+- *    we cannot lose wakeup events.
+- */
+-
+-asmlinkage void __up(struct semaphore *sem)
+-{
+-	wake_up(&sem->wait);
+-}
+-
+-asmlinkage void __sched __down(struct semaphore * sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	unsigned long flags;
+-
+-	tsk->state = TASK_UNINTERRUPTIBLE;
+-	spin_lock_irqsave(&sem->wait.lock, flags);
+-	add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+-	sem->sleepers++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock in
+-		 * the wait_queue_head.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-		schedule();
+-
+-		spin_lock_irqsave(&sem->wait.lock, flags);
+-		tsk->state = TASK_UNINTERRUPTIBLE;
+-	}
+-	remove_wait_queue_locked(&sem->wait, &wait);
+-	wake_up_locked(&sem->wait);
+-	spin_unlock_irqrestore(&sem->wait.lock, flags);
+-	tsk->state = TASK_RUNNING;
+-}
+-
+-asmlinkage int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	unsigned long flags;
+-
+-	tsk->state = TASK_INTERRUPTIBLE;
+-	spin_lock_irqsave(&sem->wait.lock, flags);
+-	add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+-	sem->sleepers++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * With signals pending, this turns into
+-		 * the trylock failure case - we won't be
+-		 * sleeping, and we* can't get the lock as
+-		 * it has contention. Just correct the count
+-		 * and exit.
+-		 */
+-		if (signal_pending(current)) {
+-			retval = -EINTR;
+-			sem->sleepers = 0;
+-			atomic_add(sleepers, &sem->count);
+-			break;
+-		}
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock in
+-		 * wait_queue_head. The "-1" is because we're
+-		 * still hoping to get the semaphore.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-		schedule();
+-
+-		spin_lock_irqsave(&sem->wait.lock, flags);
+-		tsk->state = TASK_INTERRUPTIBLE;
+-	}
+-	remove_wait_queue_locked(&sem->wait, &wait);
+-	wake_up_locked(&sem->wait);
+-	spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-	tsk->state = TASK_RUNNING;
+-	return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- *
+- * We could have done the trylock with a
+- * single "cmpxchg" without failure cases,
+- * but then it wouldn't work on a 386.
+- */
+-asmlinkage int __down_trylock(struct semaphore * sem)
+-{
+-	int sleepers;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&sem->wait.lock, flags);
+-	sleepers = sem->sleepers + 1;
+-	sem->sleepers = 0;
+-
+-	/*
+-	 * Add "everybody else" and us into it. They aren't
+-	 * playing, because we own the spinlock in the
+-	 * wait_queue_head.
+-	 */
+-	if (!atomic_add_negative(sleepers, &sem->count)) {
+-		wake_up_locked(&sem->wait);
+-	}
+-
+-	spin_unlock_irqrestore(&sem->wait.lock, flags);
+-	return 1;
+-}
+diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
+index 0055a6c..04c69ff 100644
+--- a/arch/m68k/atari/stram.c
++++ b/arch/m68k/atari/stram.c
+@@ -29,7 +29,6 @@
+ #include <asm/atarihw.h>
+ #include <asm/atari_stram.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ 
+ #undef DEBUG
+ 
+diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
+index a806208..7a62a71 100644
+--- a/arch/m68k/kernel/Makefile
++++ b/arch/m68k/kernel/Makefile
+@@ -10,7 +10,7 @@ endif
+ extra-y	+= vmlinux.lds
+ 
+ obj-y	:= entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
+-	   sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o
++	   sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
+ 
+ devres-y = ../../../kernel/irq/devres.o
+ 
+diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
+index 6fc69c7..d900e77 100644
+--- a/arch/m68k/kernel/m68k_ksyms.c
++++ b/arch/m68k/kernel/m68k_ksyms.c
+@@ -1,5 +1,4 @@
+ #include <linux/module.h>
+-#include <asm/semaphore.h>
+ 
+ asmlinkage long long __ashldi3 (long long, int);
+ asmlinkage long long __ashrdi3 (long long, int);
+@@ -15,8 +14,3 @@ EXPORT_SYMBOL(__ashrdi3);
+ EXPORT_SYMBOL(__lshrdi3);
+ EXPORT_SYMBOL(__muldi3);
+ 
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+-
+diff --git a/arch/m68k/kernel/semaphore.c b/arch/m68k/kernel/semaphore.c
+deleted file mode 100644
+index d12cbbf..0000000
+--- a/arch/m68k/kernel/semaphore.c
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/*
+- *  Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <asm/semaphore-helper.h>
+-
+-#ifndef CONFIG_RMW_INSNS
+-spinlock_t semaphore_wake_lock;
+-#endif
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit.  ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore.  The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+-	wake_one_more(sem);
+-	wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function.  Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible.  This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return.  If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-
+-#define DOWN_HEAD(task_state)						\
+-									\
+-									\
+-	current->state = (task_state);					\
+-	add_wait_queue(&sem->wait, &wait);				\
+-									\
+-	/*								\
+-	 * Ok, we're set up.  sem->count is known to be less than zero	\
+-	 * so we must wait.						\
+-	 *								\
+-	 * We can let go the lock for purposes of waiting.		\
+-	 * We re-acquire it after awaking so as to protect		\
+-	 * all semaphore operations.					\
+-	 *								\
+-	 * If "up()" is called before we call waking_non_zero() then	\
+-	 * we will catch it right away.  If it is called later then	\
+-	 * we will have to go through a wakeup cycle to catch it.	\
+-	 *								\
+-	 * Multiple waiters contend for the semaphore lock to see	\
+-	 * who gets to gate through and who has to wait some more.	\
+-	 */								\
+-	for (;;) {
+-
+-#define DOWN_TAIL(task_state)			\
+-		current->state = (task_state);	\
+-	}					\
+-	current->state = TASK_RUNNING;		\
+-	remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	DECLARE_WAITQUEUE(wait, current);
+-
+-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+-	if (waking_non_zero(sem))
+-		break;
+-	schedule();
+-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	DECLARE_WAITQUEUE(wait, current);
+-	int ret = 0;
+-
+-	DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+-	ret = waking_non_zero_interruptible(sem, current);
+-	if (ret)
+-	{
+-		if (ret == 1)
+-			/* ret != 0 only if we get interrupted -arca */
+-			ret = 0;
+-		break;
+-	}
+-	schedule();
+-	DOWN_TAIL(TASK_INTERRUPTIBLE)
+-	return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+-	return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
+index 6bbf19f..a18af09 100644
+--- a/arch/m68k/lib/Makefile
++++ b/arch/m68k/lib/Makefile
+@@ -5,4 +5,4 @@
+ EXTRA_AFLAGS := -traditional
+ 
+ lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
+-	   checksum.o string.o semaphore.o uaccess.o
++	   checksum.o string.o uaccess.o
+diff --git a/arch/m68k/lib/semaphore.S b/arch/m68k/lib/semaphore.S
+deleted file mode 100644
+index 0215624..0000000
+--- a/arch/m68k/lib/semaphore.S
++++ /dev/null
+@@ -1,53 +0,0 @@
+-/*
+- *  linux/arch/m68k/lib/semaphore.S
+- *
+- *  Copyright (C) 1996  Linus Torvalds
+- *
+- *  m68k version by Andreas Schwab
+- */
+-
+-#include <linux/linkage.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * The semaphore operations have a special calling sequence that
+- * allow us to do a simpler in-line version of them. These routines
+- * need to convert that sequence back into the C sequence when
+- * there is contention on the semaphore.
+- */
+-ENTRY(__down_failed)
+-	moveml %a0/%d0/%d1,-(%sp)
+-	movel %a1,-(%sp)
+-	jbsr __down
+-	movel (%sp)+,%a1
+-	moveml (%sp)+,%a0/%d0/%d1
+-	rts
+-
+-ENTRY(__down_failed_interruptible)
+-	movel %a0,-(%sp)
+-	movel %d1,-(%sp)
+-	movel %a1,-(%sp)
+-	jbsr __down_interruptible
+-	movel (%sp)+,%a1
+-	movel (%sp)+,%d1
+-	movel (%sp)+,%a0
+-	rts
+-
+-ENTRY(__down_failed_trylock)
+-	movel %a0,-(%sp)
+-	movel %d1,-(%sp)
+-	movel %a1,-(%sp)
+-	jbsr __down_trylock
+-	movel (%sp)+,%a1
+-	movel (%sp)+,%d1
+-	movel (%sp)+,%a0
+-	rts
+-
+-ENTRY(__up_wakeup)
+-	moveml %a0/%d0/%d1,-(%sp)
+-	movel %a1,-(%sp)
+-	jbsr __up
+-	movel (%sp)+,%a1
+-	moveml (%sp)+,%a0/%d0/%d1
+-	rts
+-
+diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
+index db359d7..0116d20 100644
+--- a/arch/m68k/sun3/intersil.c
++++ b/arch/m68k/sun3/intersil.c
+@@ -15,7 +15,6 @@
+ 
+ #include <asm/errno.h>
+ #include <asm/system.h>
+-#include <asm/semaphore.h>
+ #include <asm/rtc.h>
+ #include <asm/intersil.h>
+ 
+diff --git a/arch/m68knommu/kernel/Makefile b/arch/m68knommu/kernel/Makefile
+index 1524b39..f0eab3d 100644
+--- a/arch/m68knommu/kernel/Makefile
++++ b/arch/m68knommu/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y := vmlinux.lds
+ 
+ obj-y += dma.o entry.o init_task.o irq.o m68k_ksyms.o process.o ptrace.o \
+-	 semaphore.o setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
++	 setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
+ 
+ obj-$(CONFIG_MODULES)	+= module.o
+ obj-$(CONFIG_COMEMPCI)	+= comempci.o
+diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
+index 53fad14..39fe0a7 100644
+--- a/arch/m68knommu/kernel/m68k_ksyms.c
++++ b/arch/m68knommu/kernel/m68k_ksyms.c
+@@ -13,7 +13,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/current.h>
+ 
+@@ -39,11 +38,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
+ EXPORT_SYMBOL(memcpy);
+ EXPORT_SYMBOL(memset);
+ 
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+-
+ /*
+  * libgcc functions - functions that are used internally by the
+  * compiler...  (prototypes are not correct though, but that
+diff --git a/arch/m68knommu/kernel/semaphore.c b/arch/m68knommu/kernel/semaphore.c
+deleted file mode 100644
+index bce2bc7..0000000
+--- a/arch/m68knommu/kernel/semaphore.c
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/*
+- *  Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/err.h>
+-#include <linux/init.h>
+-#include <asm/semaphore-helper.h>
+-
+-#ifndef CONFIG_RMW_INSNS
+-spinlock_t semaphore_wake_lock;
+-#endif
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit.  ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore.  The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+-	wake_one_more(sem);
+-	wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function.  Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible.  This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return.  If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-
+-#define DOWN_HEAD(task_state)						\
+-									\
+-									\
+-	current->state = (task_state);					\
+-	add_wait_queue(&sem->wait, &wait);				\
+-									\
+-	/*								\
+-	 * Ok, we're set up.  sem->count is known to be less than zero	\
+-	 * so we must wait.						\
+-	 *								\
+-	 * We can let go the lock for purposes of waiting.		\
+-	 * We re-acquire it after awaking so as to protect		\
+-	 * all semaphore operations.					\
+-	 *								\
+-	 * If "up()" is called before we call waking_non_zero() then	\
+-	 * we will catch it right away.  If it is called later then	\
+-	 * we will have to go through a wakeup cycle to catch it.	\
+-	 *								\
+-	 * Multiple waiters contend for the semaphore lock to see	\
+-	 * who gets to gate through and who has to wait some more.	\
+-	 */								\
+-	for (;;) {
+-
+-#define DOWN_TAIL(task_state)			\
+-		current->state = (task_state);	\
+-	}					\
+-	current->state = TASK_RUNNING;		\
+-	remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	DECLARE_WAITQUEUE(wait, current);
+-
+-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+-	if (waking_non_zero(sem))
+-		break;
+-	schedule();
+-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	DECLARE_WAITQUEUE(wait, current);
+-	int ret = 0;
+-
+-	DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+-	ret = waking_non_zero_interruptible(sem, current);
+-	if (ret)
+-	{
+-		if (ret == 1)
+-			/* ret != 0 only if we get interrupted -arca */
+-			ret = 0;
+-		break;
+-	}
+-	schedule();
+-	DOWN_TAIL(TASK_INTERRUPTIBLE)
+-	return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+-	return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/m68knommu/lib/Makefile b/arch/m68knommu/lib/Makefile
+index e051a79..d94d709 100644
+--- a/arch/m68knommu/lib/Makefile
++++ b/arch/m68knommu/lib/Makefile
+@@ -4,4 +4,4 @@
+ 
+ lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o \
+ 	   muldi3.o mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \
+-	   checksum.o semaphore.o memcpy.o memset.o delay.o
++	   checksum.o memcpy.o memset.o delay.o
+diff --git a/arch/m68knommu/lib/semaphore.S b/arch/m68knommu/lib/semaphore.S
+deleted file mode 100644
+index 87c7460..0000000
+--- a/arch/m68knommu/lib/semaphore.S
++++ /dev/null
+@@ -1,66 +0,0 @@
+-/*
+- *  linux/arch/m68k/lib/semaphore.S
+- *
+- *  Copyright (C) 1996  Linus Torvalds
+- *
+- *  m68k version by Andreas Schwab
+- *
+- *  MAR/1999 -- modified to support ColdFire (gerg at snapgear.com)
+- */
+-
+-#include <linux/linkage.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * "down_failed" is called with the eventual return address
+- * in %a0, and the address of the semaphore in %a1. We need
+- * to increment the number of waiters on the semaphore,
+- * call "__down()", and then eventually return to try again.
+- */
+-ENTRY(__down_failed)
+-#ifdef CONFIG_COLDFIRE
+-	subl #12,%sp
+-	moveml %a0/%d0/%d1,(%sp)
+-#else
+-	moveml %a0/%d0/%d1,-(%sp)
+-#endif
+-	movel %a1,-(%sp)
+-	jbsr __down
+-	movel (%sp)+,%a1
+-	movel (%sp)+,%d0
+-	movel (%sp)+,%d1
+-	rts
+-
+-ENTRY(__down_failed_interruptible)
+-	movel %a0,-(%sp)
+-	movel %d1,-(%sp)
+-	movel %a1,-(%sp)
+-	jbsr __down_interruptible
+-	movel (%sp)+,%a1
+-	movel (%sp)+,%d1
+-	rts
+-
+-ENTRY(__up_wakeup)
+-#ifdef CONFIG_COLDFIRE
+-	subl #12,%sp
+-	moveml %a0/%d0/%d1,(%sp)
+-#else
+-	moveml %a0/%d0/%d1,-(%sp)
+-#endif
+-	movel %a1,-(%sp)
+-	jbsr __up
+-	movel (%sp)+,%a1
+-	movel (%sp)+,%d0
+-	movel (%sp)+,%d1
+-	rts
+-
+-ENTRY(__down_failed_trylock)
+-	movel %a0,-(%sp)
+-	movel %d1,-(%sp)
+-	movel %a1,-(%sp)
+-	jbsr __down_trylock
+-	movel (%sp)+,%a1
+-	movel (%sp)+,%d1
+-	movel (%sp)+,%a0
+-	rts
+-
+diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
+index 9e78e1a..6fcdb6f 100644
+--- a/arch/mips/kernel/Makefile
++++ b/arch/mips/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y		:= head.o init_task.o vmlinux.lds
+ 
+ obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
+-		   ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
++		   ptrace.o reset.o setup.o signal.o syscall.o \
+ 		   time.o topology.o traps.o unaligned.o
+ 
+ obj-$(CONFIG_CEVT_BCM1480)	+= cevt-bcm1480.o
+diff --git a/arch/mips/kernel/semaphore.c b/arch/mips/kernel/semaphore.c
+deleted file mode 100644
+index 1265358..0000000
+--- a/arch/mips/kernel/semaphore.c
++++ /dev/null
+@@ -1,168 +0,0 @@
+-/*
+- * MIPS-specific semaphore code.
+- *
+- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
+- * Copyright (C) 2004 Ralf Baechle <ralf at linux-mips.org>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * April 2001 - Reworked by Paul Mackerras <paulus at samba.org>
+- * to eliminate the SMP races in the old version between the updates
+- * of `count' and `waking'.  Now we use negative `count' values to
+- * indicate that some process(es) are waiting for the semaphore.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <asm/atomic.h>
+-#include <asm/cpu-features.h>
+-#include <asm/errno.h>
+-#include <asm/semaphore.h>
+-#include <asm/war.h>
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- *	old_count = sem->count;
+- *	tmp = MAX(old_count, 0) + incr;
+- *	sem->count = tmp;
+- *	return old_count;
+- *
+- * On machines without lld/scd we need a spinlock to make the manipulation of
+- * sem->count and sem->waking atomic.  Scalability isn't an issue because
+- * this lock is used on UP only so it's just an empty variable.
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+-	int old_count, tmp;
+-
+-	if (cpu_has_llsc && R10000_LLSC_WAR) {
+-		__asm__ __volatile__(
+-		"	.set	mips3					\n"
+-		"1:	ll	%0, %2		# __sem_update_count	\n"
+-		"	sra	%1, %0, 31				\n"
+-		"	not	%1					\n"
+-		"	and	%1, %0, %1				\n"
+-		"	addu	%1, %1, %3				\n"
+-		"	sc	%1, %2					\n"
+-		"	beqzl	%1, 1b					\n"
+-		"	.set	mips0					\n"
+-		: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+-		: "r" (incr), "m" (sem->count));
+-	} else if (cpu_has_llsc) {
+-		__asm__ __volatile__(
+-		"	.set	mips3					\n"
+-		"1:	ll	%0, %2		# __sem_update_count	\n"
+-		"	sra	%1, %0, 31				\n"
+-		"	not	%1					\n"
+-		"	and	%1, %0, %1				\n"
+-		"	addu	%1, %1, %3				\n"
+-		"	sc	%1, %2					\n"
+-		"	beqz	%1, 1b					\n"
+-		"	.set	mips0					\n"
+-		: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+-		: "r" (incr), "m" (sem->count));
+-	} else {
+-		static DEFINE_SPINLOCK(semaphore_lock);
+-		unsigned long flags;
+-
+-		spin_lock_irqsave(&semaphore_lock, flags);
+-		old_count = atomic_read(&sem->count);
+-		tmp = max_t(int, old_count, 0) + incr;
+-		atomic_set(&sem->count, tmp);
+-		spin_unlock_irqrestore(&semaphore_lock, flags);
+-	}
+-
+-	return old_count;
+-}
+-
+-void __up(struct semaphore *sem)
+-{
+-	/*
+-	 * Note that we incremented count in up() before we came here,
+-	 * but that was ineffective since the result was <= 0, and
+-	 * any negative value of count is equivalent to 0.
+-	 * This ends up setting count to 1, unless count is now > 0
+-	 * (i.e. because some other cpu has called up() in the meantime),
+-	 * in which case we just increment count.
+-	 */
+-	__sem_update_count(sem, 1);
+-	wake_up(&sem->wait);
+-}
+-
+-EXPORT_SYMBOL(__up);
+-
+-/*
+- * Note that when we come in to __down or __down_interruptible,
+- * we have already decremented count, but that decrement was
+- * ineffective since the result was < 0, and any negative value
+- * of count is equivalent to 0.
+- * Thus it is only when we decrement count from some value > 0
+- * that we have actually got the semaphore.
+- */
+-void __sched __down(struct semaphore *sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	/*
+-	 * Try to get the semaphore.  If the count is > 0, then we've
+-	 * got the semaphore; we decrement count and exit the loop.
+-	 * If the count is 0 or negative, we set it to -1, indicating
+-	 * that we are asleep, and then sleep.
+-	 */
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		schedule();
+-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-	}
+-	remove_wait_queue(&sem->wait, &wait);
+-	__set_task_state(tsk, TASK_RUNNING);
+-
+-	/*
+-	 * If there are any more sleepers, wake one of them up so
+-	 * that it can either get the semaphore, or set count to -1
+-	 * indicating that there are still processes sleeping.
+-	 */
+-	wake_up(&sem->wait);
+-}
+-
+-EXPORT_SYMBOL(__down);
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	__set_task_state(tsk, TASK_INTERRUPTIBLE);
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		if (signal_pending(current)) {
+-			/*
+-			 * A signal is pending - give up trying.
+-			 * Set sem->count to 0 if it is negative,
+-			 * since we are no longer sleeping.
+-			 */
+-			__sem_update_count(sem, 0);
+-			retval = -EINTR;
+-			break;
+-		}
+-		schedule();
+-		set_task_state(tsk, TASK_INTERRUPTIBLE);
+-	}
+-	remove_wait_queue(&sem->wait, &wait);
+-	__set_task_state(tsk, TASK_RUNNING);
+-
+-	wake_up(&sem->wait);
+-	return retval;
+-}
+-
+-EXPORT_SYMBOL(__down_interruptible);
+diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
+index 3ba8306..984e561 100644
+--- a/arch/mips/sgi-ip27/ip27-console.c
++++ b/arch/mips/sgi-ip27/ip27-console.c
+@@ -8,7 +8,6 @@
+ #include <linux/init.h>
+ 
+ #include <asm/page.h>
+-#include <asm/semaphore.h>
+ #include <asm/sn/addrs.h>
+ #include <asm/sn/sn0/hub.h>
+ #include <asm/sn/klconfig.h>
+diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
+index ef07c95..23f2ab6 100644
+--- a/arch/mn10300/kernel/Makefile
++++ b/arch/mn10300/kernel/Makefile
+@@ -3,7 +3,7 @@
+ #
+ extra-y := head.o init_task.o vmlinux.lds
+ 
+-obj-y   := process.o semaphore.o signal.o entry.o fpu.o traps.o irq.o \
++obj-y   := process.o signal.o entry.o fpu.o traps.o irq.o \
+ 	   ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
+ 	   switch_to.o mn10300_ksyms.o kernel_execve.o
+ 
+diff --git a/arch/mn10300/kernel/semaphore.c b/arch/mn10300/kernel/semaphore.c
+deleted file mode 100644
+index 9153c40..0000000
+--- a/arch/mn10300/kernel/semaphore.c
++++ /dev/null
+@@ -1,149 +0,0 @@
+-/* MN10300 Semaphore implementation
+- *
+- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at 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/sched.h>
+-#include <linux/module.h>
+-#include <asm/semaphore.h>
+-
+-struct sem_waiter {
+-	struct list_head	list;
+-	struct task_struct	*task;
+-};
+-
+-#if SEMAPHORE_DEBUG
+-void semtrace(struct semaphore *sem, const char *str)
+-{
+-	if (sem->debug)
+-		printk(KERN_DEBUG "[%d] %s({%d,%d})\n",
+-		       current->pid,
+-		       str,
+-		       atomic_read(&sem->count),
+-		       list_empty(&sem->wait_list) ? 0 : 1);
+-}
+-#else
+-#define semtrace(SEM, STR) do { } while (0)
+-#endif
+-
+-/*
+- * wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __down(struct semaphore *sem, unsigned long flags)
+-{
+-	struct task_struct *tsk = current;
+-	struct sem_waiter waiter;
+-
+-	semtrace(sem, "Entering __down");
+-
+-	/* set up my own style of waitqueue */
+-	waiter.task = tsk;
+-	get_task_struct(tsk);
+-
+-	list_add_tail(&waiter.list, &sem->wait_list);
+-
+-	/* we don't need to touch the semaphore struct anymore */
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+-	/* wait to be given the semaphore */
+-	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-
+-	for (;;) {
+-		if (!waiter.task)
+-			break;
+-		schedule();
+-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-	}
+-
+-	tsk->state = TASK_RUNNING;
+-	semtrace(sem, "Leaving __down");
+-}
+-EXPORT_SYMBOL(__down);
+-
+-/*
+- * interruptibly wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-int __down_interruptible(struct semaphore *sem, unsigned long flags)
+-{
+-	struct task_struct *tsk = current;
+-	struct sem_waiter waiter;
+-	int ret;
+-
+-	semtrace(sem, "Entering __down_interruptible");
+-
+-	/* set up my own style of waitqueue */
+-	waiter.task = tsk;
+-	get_task_struct(tsk);
+-
+-	list_add_tail(&waiter.list, &sem->wait_list);
+-
+-	/* we don't need to touch the semaphore struct anymore */
+-	set_task_state(tsk, TASK_INTERRUPTIBLE);
+-
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+-	/* wait to be given the semaphore */
+-	ret = 0;
+-	for (;;) {
+-		if (!waiter.task)
+-			break;
+-		if (unlikely(signal_pending(current)))
+-			goto interrupted;
+-		schedule();
+-		set_task_state(tsk, TASK_INTERRUPTIBLE);
+-	}
+-
+- out:
+-	tsk->state = TASK_RUNNING;
+-	semtrace(sem, "Leaving __down_interruptible");
+-	return ret;
+-
+- interrupted:
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-	list_del(&waiter.list);
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+-	ret = 0;
+-	if (!waiter.task) {
+-		put_task_struct(current);
+-		ret = -EINTR;
+-	}
+-	goto out;
+-}
+-EXPORT_SYMBOL(__down_interruptible);
+-
+-/*
+- * release a single token back to a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __up(struct semaphore *sem)
+-{
+-	struct task_struct *tsk;
+-	struct sem_waiter *waiter;
+-
+-	semtrace(sem, "Entering __up");
+-
+-	/* grant the token to the process at the front of the queue */
+-	waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
+-
+-	/* We must be careful not to touch 'waiter' after we set ->task = NULL.
+-	 * It is an allocated on the waiter's stack and may become invalid at
+-	 * any time after that point (due to a wakeup from another source).
+-	 */
+-	list_del_init(&waiter->list);
+-	tsk = waiter->task;
+-	smp_mb();
+-	waiter->task = NULL;
+-	wake_up_process(tsk);
+-	put_task_struct(tsk);
+-
+-	semtrace(sem, "Leaving __up");
+-}
+-EXPORT_SYMBOL(__up);
+diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h
+index 84634fa..9763d1c 100644
+--- a/arch/mn10300/unit-asb2305/pci-asb2305.h
++++ b/arch/mn10300/unit-asb2305/pci-asb2305.h
+@@ -23,8 +23,6 @@
+ #define PCI_PROBE_BIOS 1
+ #define PCI_PROBE_CONF1 2
+ #define PCI_PROBE_CONF2 4
+-#define PCI_NO_SORT 0x100
+-#define PCI_BIOS_SORT 0x200
+ #define PCI_NO_CHECKS 0x400
+ #define PCI_ASSIGN_ROMS 0x1000
+ #define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
+index 27827bc..1f6585a 100644
+--- a/arch/parisc/kernel/Makefile
++++ b/arch/parisc/kernel/Makefile
+@@ -9,7 +9,7 @@ AFLAGS_pacache.o := -traditional
+ 
+ obj-y	     	:= cache.o pacache.o setup.o traps.o time.o irq.o \
+ 		   pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
+-		   ptrace.o hardware.o inventory.o drivers.o semaphore.o \
++		   ptrace.o hardware.o inventory.o drivers.o \
+ 		   signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
+ 		   process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \
+ 		   topology.o
+diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
+index 7aca704..5b7fc4a 100644
+--- a/arch/parisc/kernel/parisc_ksyms.c
++++ b/arch/parisc/kernel/parisc_ksyms.c
+@@ -69,11 +69,6 @@ EXPORT_SYMBOL(memcpy_toio);
+ EXPORT_SYMBOL(memcpy_fromio);
+ EXPORT_SYMBOL(memset_io);
+ 
+-#include <asm/semaphore.h>
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down);
+-
+ extern void $$divI(void);
+ extern void $$divU(void);
+ extern void $$remI(void);
+diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
+index 507d0ac..6936386 100644
+--- a/arch/parisc/kernel/pci.c
++++ b/arch/parisc/kernel/pci.c
+@@ -287,23 +287,15 @@ void pcibios_align_resource(void *data, struct resource *res,
+  */
+ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+-	u16 cmd;
+-	int idx;
++	int err;
++	u16 cmd, old_cmd;
+ 
+-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+-
+-	for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
+-		struct resource *r = &dev->resource[idx];
++	err = pci_enable_resources(dev, mask);
++	if (err < 0)
++		return err;
+ 
+-		/* only setup requested resources */
+-		if (!(mask & (1<<idx)))
+-			continue;
+-
+-		if (r->flags & IORESOURCE_IO)
+-			cmd |= PCI_COMMAND_IO;
+-		if (r->flags & IORESOURCE_MEM)
+-			cmd |= PCI_COMMAND_MEMORY;
+-	}
++	pci_read_config_word(dev, PCI_COMMAND, &cmd);
++	old_cmd = cmd;
+ 
+ 	cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+ 
+@@ -312,8 +304,12 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ 	if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK)
+ 		cmd |= PCI_COMMAND_FAST_BACK;
+ #endif
+-	DBGC("PCIBIOS: Enabling device %s cmd 0x%04x\n", pci_name(dev), cmd);
+-	pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++	if (cmd != old_cmd) {
++		dev_info(&dev->dev, "enabling SERR and PARITY (%04x -> %04x)\n",
++			old_cmd, cmd);
++		pci_write_config_word(dev, PCI_COMMAND, cmd);
++	}
+ 	return 0;
+ }
+ 
+diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c
+deleted file mode 100644
+index ee806bc..0000000
+--- a/arch/parisc/kernel/semaphore.c
++++ /dev/null
+@@ -1,102 +0,0 @@
+-/*
+- * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/spinlock.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-/*
+- * Semaphores are complex as we wish to avoid using two variables.
+- * `count' has multiple roles, depending on its value.  If it is positive
+- * or zero, there are no waiters.  The functions here will never be
+- * called; see <asm/semaphore.h>
+- *
+- * When count is -1 it indicates there is at least one task waiting
+- * for the semaphore.
+- *
+- * When count is less than that, there are '- count - 1' wakeups
+- * pending.  ie if it has value -3, there are 2 wakeups pending.
+- *
+- * Note that these functions are only called when there is contention
+- * on the lock, and as such all this is the "non-critical" part of the
+- * whole semaphore business. The critical part is the inline stuff in
+- * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+-	sem->count--;
+-	wake_up(&sem->wait);
+-}
+-
+-#define wakers(count) (-1 - count)
+-
+-#define DOWN_HEAD							\
+-	int ret = 0;							\
+-	DECLARE_WAITQUEUE(wait, current);				\
+-									\
+-	/* Note that someone is waiting */				\
+-	if (sem->count == 0)						\
+-		sem->count = -1;					\
+-									\
+-	/* protected by the sentry still -- use unlocked version */	\
+-	wait.flags = WQ_FLAG_EXCLUSIVE;					\
+-	__add_wait_queue_tail(&sem->wait, &wait);			\
+- lost_race:								\
+-	spin_unlock_irq(&sem->sentry);					\
+-
+-#define DOWN_TAIL							\
+-	spin_lock_irq(&sem->sentry);					\
+-	if (wakers(sem->count) == 0 && ret == 0)			\
+-		goto lost_race;	/* Someone stole our wakeup */		\
+-	__remove_wait_queue(&sem->wait, &wait);				\
+-	current->state = TASK_RUNNING;					\
+-	if (!waitqueue_active(&sem->wait) && (sem->count < 0))		\
+-		sem->count = wakers(sem->count);
+-
+-#define UPDATE_COUNT							\
+-	sem->count += (sem->count < 0) ? 1 : - 1;
+-	
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	DOWN_HEAD
+-
+-	for(;;) {
+-		set_task_state(current, TASK_UNINTERRUPTIBLE);
+-		/* we can _read_ this without the sentry */
+-		if (sem->count != -1)
+-			break;
+- 		schedule();
+- 	}
+-
+-	DOWN_TAIL
+-	UPDATE_COUNT
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	DOWN_HEAD
+-
+-	for(;;) {
+-		set_task_state(current, TASK_INTERRUPTIBLE);
+-		/* we can _read_ this without the sentry */
+-		if (sem->count != -1)
+-			break;
+-
+-		if (signal_pending(current)) {
+-			ret = -EINTR;
+-			break;
+-		}
+-		schedule();
+-	}
+-
+-	DOWN_TAIL
+-
+-	if (!ret) {
+-		UPDATE_COUNT
+-	}
+-
+-	return ret;
+-}
+diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
+index 50bbf33..71efd6a 100644
+--- a/arch/parisc/kernel/sys_parisc32.c
++++ b/arch/parisc/kernel/sys_parisc32.c
+@@ -49,7 +49,6 @@
+ 
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/mmu_context.h>
+ 
+ #include "sys32.h"
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index 1189d8d..20f45a8 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -49,6 +49,19 @@ config IRQ_PER_CPU
+ 	bool
+ 	default y
+ 
++config STACKTRACE_SUPPORT
++	bool
++	default y
++
++config TRACE_IRQFLAGS_SUPPORT
++	bool
++	depends on PPC64
++	default y
++
++config LOCKDEP_SUPPORT
++	bool
++	default y
++
+ config RWSEM_GENERIC_SPINLOCK
+ 	bool
+ 
+@@ -81,6 +94,11 @@ config GENERIC_FIND_NEXT_BIT
+ 	bool
+ 	default y
+ 
++config GENERIC_GPIO
++	bool
++	help
++	  Generic GPIO API support
++
+ config ARCH_NO_VIRT_TO_BUS
+ 	def_bool PPC64
+ 
+@@ -91,6 +109,7 @@ config PPC
+ 	select HAVE_OPROFILE
+ 	select HAVE_KPROBES
+ 	select HAVE_KRETPROBES
++	select HAVE_LMB
+ 
+ config EARLY_PRINTK
+ 	bool
+@@ -210,15 +229,6 @@ source kernel/Kconfig.hz
+ source kernel/Kconfig.preempt
+ source "fs/Kconfig.binfmt"
+ 
+-# We optimistically allocate largepages from the VM, so make the limit
+-# large enough (16MB). This badly named config option is actually
+-# max order + 1
+-config FORCE_MAX_ZONEORDER
+-	int
+-	depends on PPC64
+-	default "9" if PPC_64K_PAGES
+-	default "13"
+-
+ config HUGETLB_PAGE_SIZE_VARIABLE
+ 	bool
+ 	depends on HUGETLB_PAGE
+@@ -307,6 +317,16 @@ config CRASH_DUMP
+ 
+ 	  Don't change this unless you know what you are doing.
+ 
++config PHYP_DUMP
++	bool "Hypervisor-assisted dump (EXPERIMENTAL)"
++	depends on PPC_PSERIES && EXPERIMENTAL
++	help
++	  Hypervisor-assisted dump is meant to be a kdump replacement
++	  offering robustness and speed not possible without system
++	  hypervisor assistence.
++
++	  If unsure, say "N"
++
+ config PPCBUG_NVRAM
+ 	bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
+ 	default y if PPC_PREP
+@@ -381,6 +401,26 @@ config PPC_64K_PAGES
+ 	  while on hardware with such support, it will be used to map
+ 	  normal application pages.
+ 
++config FORCE_MAX_ZONEORDER
++	int "Maximum zone order"
++	default "9" if PPC_64K_PAGES
++	default "13" if PPC64 && !PPC_64K_PAGES
++	default "11"
++	help
++	  The kernel memory allocator divides physically contiguous memory
++	  blocks into "zones", where each zone is a power of two number of
++	  pages.  This option selects the largest power of two that the kernel
++	  keeps in the memory allocator.  If you need to allocate very large
++	  blocks of physically contiguous memory, then you may need to
++	  increase this value.
++
++	  This config option is actually maximum order plus one. For example,
++	  a value of 11 means that the largest free memory block is 2^10 pages.
++
++	  The page size is not necessarily 4KB.  For example, on 64-bit
++	  systems, 64KB pages can be enabled via CONFIG_PPC_64K_PAGES.  Keep
++	  this in mind when choosing a value for this option.
++
+ config PPC_SUBPAGE_PROT
+ 	bool "Support setting protections for 4k subpages"
+ 	depends on PPC_64K_PAGES
+@@ -490,6 +530,14 @@ config FSL_PCI
+  	bool
+ 	select PPC_INDIRECT_PCI
+ 
++config 4xx_SOC
++	bool
++
++config FSL_LBC
++	bool
++	help
++	  Freescale Localbus support
++
+ # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
+ config MCA
+ 	bool
+@@ -578,20 +626,6 @@ config ADVANCED_OPTIONS
+ comment "Default settings for advanced configuration options are used"
+ 	depends on !ADVANCED_OPTIONS
+ 
+-config HIGHMEM_START_BOOL
+-	bool "Set high memory pool address"
+-	depends on ADVANCED_OPTIONS && HIGHMEM
+-	help
+-	  This option allows you to set the base address of the kernel virtual
+-	  area used to map high memory pages.  This can be useful in
+-	  optimizing the layout of kernel virtual memory.
+-
+-	  Say N here unless you know what you are doing.
+-
+-config HIGHMEM_START
+-	hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
+-	default "0xfe000000"
+-
+ config LOWMEM_SIZE_BOOL
+ 	bool "Set maximum low memory"
+ 	depends on ADVANCED_OPTIONS
+@@ -608,21 +642,76 @@ config LOWMEM_SIZE
+ 	hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
+ 	default "0x30000000"
+ 
++config RELOCATABLE
++	bool "Build a relocatable kernel (EXPERIMENTAL)"
++	depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
++	help
++	  This builds a kernel image that is capable of running at the
++	  location the kernel is loaded at (some alignment restrictions may
++	  exist).
++
++	  One use is for the kexec on panic case where the recovery kernel
++	  must live at a different physical address than the primary
++	  kernel.
++
++	  Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
++	  it has been loaded at and the compile time physical addresses
++	  CONFIG_PHYSICAL_START is ignored.  However CONFIG_PHYSICAL_START
++	  setting can still be useful to bootwrappers that need to know the
++	  load location of the kernel (eg. u-boot/mkimage).
++
++config PAGE_OFFSET_BOOL
++	bool "Set custom page offset address"
++	depends on ADVANCED_OPTIONS
++	help
++	  This option allows you to set the kernel virtual address at which
++	  the kernel will map low memory.  This can be useful in optimizing
++	  the virtual memory layout of the system.
++
++	  Say N here unless you know what you are doing.
++
++config PAGE_OFFSET
++	hex "Virtual address of memory base" if PAGE_OFFSET_BOOL
++	default "0xc0000000"
++
+ config KERNEL_START_BOOL
+ 	bool "Set custom kernel base address"
+ 	depends on ADVANCED_OPTIONS
+ 	help
+ 	  This option allows you to set the kernel virtual address at which
+-	  the kernel will map low memory (the kernel image will be linked at
+-	  this address).  This can be useful in optimizing the virtual memory
+-	  layout of the system.
++	  the kernel will be loaded.  Normally this should match PAGE_OFFSET
++	  however there are times (like kdump) that one might not want them
++	  to be the same.
+ 
+ 	  Say N here unless you know what you are doing.
+ 
+ config KERNEL_START
+ 	hex "Virtual address of kernel base" if KERNEL_START_BOOL
++	default PAGE_OFFSET if PAGE_OFFSET_BOOL
++	default "0xc2000000" if CRASH_DUMP
+ 	default "0xc0000000"
+ 
++config PHYSICAL_START_BOOL
++	bool "Set physical address where the kernel is loaded"
++	depends on ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
++	help
++	  This gives the physical address where the kernel is loaded.
++
++	  Say N here unless you know what you are doing.
++
++config PHYSICAL_START
++	hex "Physical address where the kernel is loaded" if PHYSICAL_START_BOOL
++	default "0x02000000" if PPC_STD_MMU && CRASH_DUMP
++	default "0x00000000"
++
++config PHYSICAL_ALIGN
++	hex
++	default "0x10000000" if FSL_BOOKE
++	help
++	  This value puts the alignment restrictions on physical address
++	  where kernel is loaded and run from. Kernel is compiled for an
++	  address which meets above alignment restriction.
++
+ config TASK_SIZE_BOOL
+ 	bool "Set custom user task size"
+ 	depends on ADVANCED_OPTIONS
+@@ -663,31 +752,23 @@ config CONSISTENT_SIZE
+ 	hex "Size of consistent memory pool" if CONSISTENT_SIZE_BOOL
+ 	default "0x00200000" if NOT_COHERENT_CACHE
+ 
+-config BOOT_LOAD_BOOL
+-	bool "Set the boot link/load address"
+-	depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
+-	help
+-	  This option allows you to set the initial load address of the zImage
+-	  or zImage.initrd file.  This can be useful if you are on a board
+-	  which has a small amount of memory.
+-
+-	  Say N here unless you know what you are doing.
+-
+-config BOOT_LOAD
+-	hex "Link/load address for booting" if BOOT_LOAD_BOOL
+-	default "0x00400000" if 40x || 8xx || 8260
+-	default "0x01000000" if 44x
+-	default "0x00800000"
+-
+ config PIN_TLB
+ 	bool "Pinned Kernel TLBs (860 ONLY)"
+ 	depends on ADVANCED_OPTIONS && 8xx
+ endmenu
+ 
+ if PPC64
++config PAGE_OFFSET
++	hex
++	default "0xc000000000000000"
+ config KERNEL_START
+ 	hex
++	default "0xc000000002000000" if CRASH_DUMP
+ 	default "0xc000000000000000"
++config PHYSICAL_START
++	hex
++	default "0x02000000" if CRASH_DUMP
++	default "0x00000000"
+ endif
+ 
+ source "net/Kconfig"
+diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
+index db7cc34..a86d8d8 100644
+--- a/arch/powerpc/Kconfig.debug
++++ b/arch/powerpc/Kconfig.debug
+@@ -269,7 +269,7 @@ config PPC_EARLY_DEBUG_CPM_ADDR
+ 	hex "CPM UART early debug transmit descriptor address"
+ 	depends on PPC_EARLY_DEBUG_CPM
+ 	default "0xfa202008" if PPC_EP88XC
+-	default "0xf0000008" if CPM2
++	default "0xf0001ff8" if CPM2
+ 	default "0xff002008" if CPM1
+ 	help
+ 	  This specifies the address of the transmit descriptor
+diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
+index ab5cfe8..e2ec4a9 100644
+--- a/arch/powerpc/Makefile
++++ b/arch/powerpc/Makefile
+@@ -71,13 +71,11 @@ endif
+ 
+ LDFLAGS_vmlinux	:= -Bstatic
+ 
+-CPPFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
+-AFLAGS-$(CONFIG_PPC32)	:= -Iarch/$(ARCH)
+ CFLAGS-$(CONFIG_PPC64)	:= -mminimal-toc -mtraceback=none  -mcall-aixdesc
+-CFLAGS-$(CONFIG_PPC32)	:= -Iarch/$(ARCH) -ffixed-r2 -mmultiple
+-KBUILD_CPPFLAGS	+= $(CPPFLAGS-y)
+-KBUILD_AFLAGS	+= $(AFLAGS-y)
+-KBUILD_CFLAGS	+= -msoft-float -pipe $(CFLAGS-y)
++CFLAGS-$(CONFIG_PPC32)	:= -ffixed-r2 -mmultiple
++KBUILD_CPPFLAGS	+= -Iarch/$(ARCH)
++KBUILD_AFLAGS	+= -Iarch/$(ARCH)
++KBUILD_CFLAGS	+= -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y)
+ CPP		= $(CC) -E $(KBUILD_CFLAGS)
+ 
+ CHECKFLAGS	+= -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
+@@ -164,7 +162,7 @@ boot := arch/$(ARCH)/boot
+ $(BOOT_TARGETS): vmlinux
+ 	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+ 
+-bootwrapper_install:
++bootwrapper_install %.dtb:
+ 	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+ 
+ define archhelp
+diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
+index 5ef2bdf..2347294 100644
+--- a/arch/powerpc/boot/.gitignore
++++ b/arch/powerpc/boot/.gitignore
+@@ -27,6 +27,7 @@ zImage.chrp
+ zImage.coff
+ zImage.coff.lds
+ zImage.ep*
++zImage.iseries
+ zImage.*lds
+ zImage.miboot
+ zImage.pmac
+diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
+index 1aded8f..7822d25 100644
+--- a/arch/powerpc/boot/Makefile
++++ b/arch/powerpc/boot/Makefile
+@@ -40,6 +40,7 @@ $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
+ $(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
+ $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
+ $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
++$(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
+ 
+ 
+ zlib       := inffast.c inflate.c inftrees.c
+@@ -64,7 +65,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
+ 		cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
+ 		fixed-head.S ep88xc.c ep405.c \
+ 		cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
+-		cuboot-warp.c cuboot-85xx-cpm2.c
++		cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
++		virtex405-head.S
+ src-boot := $(src-wlib) $(src-plat) empty.c
+ 
+ src-boot := $(addprefix $(obj)/, $(src-boot))
+@@ -192,7 +194,7 @@ image-$(CONFIG_PPC_CHRP)		+= zImage.chrp
+ image-$(CONFIG_PPC_EFIKA)		+= zImage.chrp
+ image-$(CONFIG_PPC_PMAC)		+= zImage.pmac
+ image-$(CONFIG_PPC_HOLLY)		+= zImage.holly
+-image-$(CONFIG_PPC_PRPMC2800)		+= zImage.prpmc2800
++image-$(CONFIG_PPC_PRPMC2800)		+= dtbImage.prpmc2800
+ image-$(CONFIG_PPC_ISERIES)		+= zImage.iseries
+ image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage
+ 
+@@ -216,6 +218,7 @@ image-$(CONFIG_RAINIER)			+= cuImage.rainier
+ image-$(CONFIG_TAISHAN)			+= cuImage.taishan
+ image-$(CONFIG_KATMAI)			+= cuImage.katmai
+ image-$(CONFIG_WARP)			+= cuImage.warp
++image-$(CONFIG_YOSEMITE)		+= cuImage.yosemite
+ 
+ # Board ports in arch/powerpc/platform/8xx/Kconfig
+ image-$(CONFIG_PPC_MPC86XADS)		+= cuImage.mpc866ads
+@@ -255,6 +258,7 @@ image-$(CONFIG_TQM8555)			+= cuImage.tqm8555
+ image-$(CONFIG_TQM8560)			+= cuImage.tqm8560
+ image-$(CONFIG_SBC8548)			+= cuImage.sbc8548
+ image-$(CONFIG_SBC8560)			+= cuImage.sbc8560
++image-$(CONFIG_KSI8560)			+= cuImage.ksi8560
+ 
+ # Board ports in arch/powerpc/platform/embedded6xx/Kconfig
+ image-$(CONFIG_STORCENTER)		+= cuImage.storcenter
+@@ -285,11 +289,11 @@ $(obj)/zImage.%: vmlinux $(wrapperbits)
+ 	$(call if_changed,wrap,$*)
+ 
+ # dtbImage% - a dtbImage is a zImage with an embedded device tree blob
+-$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
+-	$(call if_changed,wrap,$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
++$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/%.dtb
++	$(call if_changed,wrap,$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
+ 
+-$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
+-	$(call if_changed,wrap,$*,$(dtstree)/$*.dts)
++$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
++	$(call if_changed,wrap,$*,,$(obj)/$*.dtb)
+ 
+ # This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
+ # prefix
+@@ -302,14 +306,24 @@ $(obj)/zImage.iseries: vmlinux
+ $(obj)/uImage: vmlinux $(wrapperbits)
+ 	$(call if_changed,wrap,uboot)
+ 
+-$(obj)/cuImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+-	$(call if_changed,wrap,cuboot-$*,$(dtstree)/$*.dts)
++$(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++	$(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb)
+ 
+-$(obj)/treeImage.initrd.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+-	$(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
++$(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++	$(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
+ 
+-$(obj)/treeImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+-	$(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts)
++$(obj)/simpleImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++	$(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb)
++
++$(obj)/treeImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++	$(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
++
++$(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++	$(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
++
++# Rule to build device tree blobs
++$(obj)/%.dtb: $(dtstree)/%.dts $(obj)/dtc
++	$(obj)/dtc -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts
+ 
+ # If there isn't a platform selected then just strip the vmlinux.
+ ifeq (,$(image-y))
+@@ -326,7 +340,7 @@ install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
+ 
+ # anything not in $(targets)
+ clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
+-	otheros.bld
++	otheros.bld *.dtb
+ 
+ # clean up files cached by wrapper
+ clean-kernel := vmlinux.strip vmlinux.bin
+diff --git a/arch/powerpc/boot/bamboo.c b/arch/powerpc/boot/bamboo.c
+index 54b33f1..b82cacb 100644
+--- a/arch/powerpc/boot/bamboo.c
++++ b/arch/powerpc/boot/bamboo.c
+@@ -33,7 +33,8 @@ static void bamboo_fixups(void)
+ 	ibm440ep_fixup_clocks(sysclk, 11059200, 25000000);
+ 	ibm4xx_sdram_fixup_memsize();
+ 	ibm4xx_quiesce_eth((u32 *)0xef600e00, (u32 *)0xef600f00);
+-	dt_fixup_mac_addresses(bamboo_mac0, bamboo_mac1);
++	dt_fixup_mac_address_by_alias("ethernet0", bamboo_mac0);
++	dt_fixup_mac_address_by_alias("ethernet1", bamboo_mac1);
+ }
+ 
+ void bamboo_init(void *mac0, void *mac1)
+diff --git a/arch/powerpc/boot/cpm-serial.c b/arch/powerpc/boot/cpm-serial.c
+index 28296fa..19dc15a 100644
+--- a/arch/powerpc/boot/cpm-serial.c
++++ b/arch/powerpc/boot/cpm-serial.c
+@@ -11,6 +11,7 @@
+ #include "types.h"
+ #include "io.h"
+ #include "ops.h"
++#include "page.h"
+ 
+ struct cpm_scc {
+ 	u32 gsmrl;
+@@ -42,6 +43,22 @@ struct cpm_param {
+ 	u16 tbase;
+ 	u8 rfcr;
+ 	u8 tfcr;
++	u16 mrblr;
++	u32 rstate;
++	u8 res1[4];
++	u16 rbptr;
++	u8 res2[6];
++	u32 tstate;
++	u8 res3[4];
++	u16 tbptr;
++	u8 res4[6];
++	u16 maxidl;
++	u16 idlc;
++	u16 brkln;
++	u16 brkec;
++	u16 brkcr;
++	u16 rmask;
++	u8 res5[4];
+ };
+ 
+ struct cpm_bd {
+@@ -54,10 +71,10 @@ static void *cpcr;
+ static struct cpm_param *param;
+ static struct cpm_smc *smc;
+ static struct cpm_scc *scc;
+-struct cpm_bd *tbdf, *rbdf;
++static struct cpm_bd *tbdf, *rbdf;
+ static u32 cpm_cmd;
+-static u8 *muram_start;
+-static u32 muram_offset;
++static void *cbd_addr;
++static u32 cbd_offset;
+ 
+ static void (*do_cmd)(int op);
+ static void (*enable_port)(void);
+@@ -119,20 +136,25 @@ static int cpm_serial_open(void)
+ 
+ 	out_8(&param->rfcr, 0x10);
+ 	out_8(&param->tfcr, 0x10);
+-
+-	rbdf = (struct cpm_bd *)muram_start;
+-	rbdf->addr = (u8 *)(rbdf + 2);
++	out_be16(&param->mrblr, 1);
++	out_be16(&param->maxidl, 0);
++	out_be16(&param->brkec, 0);
++	out_be16(&param->brkln, 0);
++	out_be16(&param->brkcr, 0);
++
++	rbdf = cbd_addr;
++	rbdf->addr = (u8 *)rbdf - 1;
+ 	rbdf->sc = 0xa000;
+ 	rbdf->len = 1;
+ 
+ 	tbdf = rbdf + 1;
+-	tbdf->addr = (u8 *)(rbdf + 2) + 1;
++	tbdf->addr = (u8 *)rbdf - 2;
+ 	tbdf->sc = 0x2000;
+ 	tbdf->len = 1;
+ 
+ 	sync();
+-	out_be16(&param->rbase, muram_offset);
+-	out_be16(&param->tbase, muram_offset + sizeof(struct cpm_bd));
++	out_be16(&param->rbase, cbd_offset);
++	out_be16(&param->tbase, cbd_offset + sizeof(struct cpm_bd));
+ 
+ 	do_cmd(CPM_CMD_INIT_RX_TX);
+ 
+@@ -175,10 +197,12 @@ static unsigned char cpm_serial_getc(void)
+ 
+ int cpm_console_init(void *devp, struct serial_console_data *scdp)
+ {
+-	void *reg_virt[2];
+-	int is_smc = 0, is_cpm2 = 0, n;
+-	unsigned long reg_phys;
++	void *vreg[2];
++	u32 reg[2];
++	int is_smc = 0, is_cpm2 = 0;
+ 	void *parent, *muram;
++	void *muram_addr;
++	unsigned long muram_offset, muram_size;
+ 
+ 	if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) {
+ 		is_smc = 1;
+@@ -202,63 +226,64 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp)
+ 	else
+ 		do_cmd = cpm1_cmd;
+ 
+-	n = getprop(devp, "fsl,cpm-command", &cpm_cmd, 4);
+-	if (n < 4)
++	if (getprop(devp, "fsl,cpm-command", &cpm_cmd, 4) < 4)
+ 		return -1;
+ 
+-	n = getprop(devp, "virtual-reg", reg_virt, sizeof(reg_virt));
+-	if (n < (int)sizeof(reg_virt)) {
+-		for (n = 0; n < 2; n++) {
+-			if (!dt_xlate_reg(devp, n, &reg_phys, NULL))
+-				return -1;
+-
+-			reg_virt[n] = (void *)reg_phys;
+-		}
+-	}
++	if (dt_get_virtual_reg(devp, vreg, 2) < 2)
++		return -1;
+ 
+ 	if (is_smc)
+-		smc = reg_virt[0];
++		smc = vreg[0];
+ 	else
+-		scc = reg_virt[0];
++		scc = vreg[0];
+ 
+-	param = reg_virt[1];
++	param = vreg[1];
+ 
+ 	parent = get_parent(devp);
+ 	if (!parent)
+ 		return -1;
+ 
+-	n = getprop(parent, "virtual-reg", reg_virt, sizeof(reg_virt));
+-	if (n < (int)sizeof(reg_virt)) {
+-		if (!dt_xlate_reg(parent, 0, &reg_phys, NULL))
+-			return -1;
+-
+-		reg_virt[0] = (void *)reg_phys;
+-	}
+-
+-	cpcr = reg_virt[0];
++	if (dt_get_virtual_reg(parent, &cpcr, 1) < 1)
++		return -1;
+ 
+ 	muram = finddevice("/soc/cpm/muram/data");
+ 	if (!muram)
+ 		return -1;
+ 
+ 	/* For bootwrapper-compatible device trees, we assume that the first
+-	 * entry has at least 18 bytes, and that #address-cells/#data-cells
++	 * entry has at least 128 bytes, and that #address-cells/#data-cells
+ 	 * is one for both parent and child.
+ 	 */
+ 
+-	n = getprop(muram, "virtual-reg", reg_virt, sizeof(reg_virt));
+-	if (n < (int)sizeof(reg_virt)) {
+-		if (!dt_xlate_reg(muram, 0, &reg_phys, NULL))
+-			return -1;
++	if (dt_get_virtual_reg(muram, &muram_addr, 1) < 1)
++		return -1;
+ 
+-		reg_virt[0] = (void *)reg_phys;
+-	}
++	if (getprop(muram, "reg", reg, 8) < 8)
++		return -1;
+ 
+-	muram_start = reg_virt[0];
++	muram_offset = reg[0];
++	muram_size = reg[1];
+ 
+-	n = getprop(muram, "reg", &muram_offset, 4);
+-	if (n < 4)
+-		return -1;
++	/* Store the buffer descriptors at the end of the first muram chunk.
++	 * For SMC ports on CPM2-based platforms, relocate the parameter RAM
++	 * just before the buffer descriptors.
++	 */
++
++	cbd_offset = muram_offset + muram_size - 2 * sizeof(struct cpm_bd);
++
++	if (is_cpm2 && is_smc) {
++		u16 *smc_base = (u16 *)param;
++		u16 pram_offset;
++
++		pram_offset = cbd_offset - 64;
++		pram_offset = _ALIGN_DOWN(pram_offset, 64);
++
++		disable_port();
++		out_be16(smc_base, pram_offset);
++		param = muram_addr - muram_offset + pram_offset;
++	}
++
++	cbd_addr = muram_addr - muram_offset + cbd_offset;
+ 
+ 	scdp->open = cpm_serial_open;
+ 	scdp->putc = cpm_serial_putc;
+diff --git a/arch/powerpc/boot/cuboot-pq2.c b/arch/powerpc/boot/cuboot-pq2.c
+index f56ac6c..9c7d134 100644
+--- a/arch/powerpc/boot/cuboot-pq2.c
++++ b/arch/powerpc/boot/cuboot-pq2.c
+@@ -128,7 +128,7 @@ static void fixup_pci(void)
+ 	u8 *soc_regs;
+ 	int i, len;
+ 	void *node, *parent_node;
+-	u32 naddr, nsize, mem_log2;
++	u32 naddr, nsize, mem_pow2, mem_mask;
+ 
+ 	node = finddevice("/pci");
+ 	if (!node || !dt_is_compatible(node, "fsl,pq2-pci"))
+@@ -141,7 +141,7 @@ static void fixup_pci(void)
+ 
+ 	soc_regs = (u8 *)fsl_get_immr();
+ 	if (!soc_regs)
+-		goto err;
++		goto unhandled;
+ 
+ 	dt_get_reg_format(node, &naddr, &nsize);
+ 	if (naddr != 3 || nsize != 2)
+@@ -153,7 +153,7 @@ static void fixup_pci(void)
+ 
+ 	dt_get_reg_format(parent_node, &naddr, &nsize);
+ 	if (naddr != 1 || nsize != 1)
+-		goto err;
++		goto unhandled;
+ 
+ 	len = getprop(node, "ranges", pci_ranges_buf,
+ 	              sizeof(pci_ranges_buf));
+@@ -170,14 +170,20 @@ static void fixup_pci(void)
+ 	}
+ 
+ 	if (!mem || !mmio || !io)
+-		goto err;
++		goto unhandled;
++	if (mem->size[1] != mmio->size[1])
++		goto unhandled;
++	if (mem->size[1] & (mem->size[1] - 1))
++		goto unhandled;
++	if (io->size[1] & (io->size[1] - 1))
++		goto unhandled;
+ 
+ 	if (mem->phys_addr + mem->size[1] == mmio->phys_addr)
+ 		mem_base = mem;
+ 	else if (mmio->phys_addr + mmio->size[1] == mem->phys_addr)
+ 		mem_base = mmio;
+ 	else
+-		goto err;
++		goto unhandled;
+ 
+ 	out_be32(&pci_regs[1][0], mem_base->phys_addr | 1);
+ 	out_be32(&pci_regs[2][0], ~(mem->size[1] + mmio->size[1] - 1));
+@@ -201,8 +207,9 @@ static void fixup_pci(void)
+ 	out_le32(&pci_regs[0][58], 0);
+ 	out_le32(&pci_regs[0][60], 0);
+ 
+-	mem_log2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1);
+-	out_le32(&pci_regs[0][62], 0xa0000000 | ~((1 << (mem_log2 - 12)) - 1));
++	mem_pow2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1);
++	mem_mask = ~(mem_pow2 - 1) >> 12;
++	out_le32(&pci_regs[0][62], 0xa0000000 | mem_mask);
+ 
+ 	/* If PCI is disabled, drive RST high to enable. */
+ 	if (!(in_le32(&pci_regs[0][32]) & 1)) {
+@@ -228,7 +235,11 @@ static void fixup_pci(void)
+ 	return;
+ 
+ err:
+-	printf("Bad PCI node\r\n");
++	printf("Bad PCI node -- using existing firmware setup.\r\n");
++	return;
++
++unhandled:
++	printf("Unsupported PCI node -- using existing firmware setup.\r\n");
+ }
+ 
+ static void pq2_platform_fixups(void)
+diff --git a/arch/powerpc/boot/cuboot-rainier.c b/arch/powerpc/boot/cuboot-rainier.c
+index cf452b6..0a3fdde 100644
+--- a/arch/powerpc/boot/cuboot-rainier.c
++++ b/arch/powerpc/boot/cuboot-rainier.c
+@@ -42,7 +42,8 @@ static void rainier_fixups(void)
+ 	ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+ 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ 	ibm4xx_denali_fixup_memsize();
+-	dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
++	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++	dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+ }
+ 
+ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+diff --git a/arch/powerpc/boot/cuboot-sequoia.c b/arch/powerpc/boot/cuboot-sequoia.c
+index f555575..caf8f2e 100644
+--- a/arch/powerpc/boot/cuboot-sequoia.c
++++ b/arch/powerpc/boot/cuboot-sequoia.c
+@@ -42,7 +42,8 @@ static void sequoia_fixups(void)
+ 	ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+ 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ 	ibm4xx_denali_fixup_memsize();
+-	dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
++	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++	dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+ }
+ 
+ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+diff --git a/arch/powerpc/boot/cuboot-taishan.c b/arch/powerpc/boot/cuboot-taishan.c
+index b55b804..9bc906a 100644
+--- a/arch/powerpc/boot/cuboot-taishan.c
++++ b/arch/powerpc/boot/cuboot-taishan.c
+@@ -40,7 +40,8 @@ static void taishan_fixups(void)
+ 
+ 	ibm4xx_sdram_fixup_memsize();
+ 
+-	dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr);
++	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++	dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+ 
+ 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ }
+diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
+index 3db93e8..eb108a8 100644
+--- a/arch/powerpc/boot/cuboot-warp.c
++++ b/arch/powerpc/boot/cuboot-warp.c
+@@ -24,7 +24,7 @@ static void warp_fixups(void)
+ 	ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+ 	ibm4xx_sdram_fixup_memsize();
+ 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+-	dt_fixup_mac_addresses(&bd.bi_enetaddr);
++	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+ }
+ 
+ 
+diff --git a/arch/powerpc/boot/cuboot-yosemite.c b/arch/powerpc/boot/cuboot-yosemite.c
+new file mode 100644
+index 0000000..cc6e338
+--- /dev/null
++++ b/arch/powerpc/boot/cuboot-yosemite.c
+@@ -0,0 +1,44 @@
++/*
++ * Old U-boot compatibility for Yosemite
++ *
++ * Author: Josh Boyer <jwboyer at linux.vnet.ibm.com>
++ *
++ * Copyright 2008 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 "ops.h"
++#include "stdio.h"
++#include "4xx.h"
++#include "44x.h"
++#include "cuboot.h"
++
++#define TARGET_4xx
++#define TARGET_44x
++#include "ppcboot.h"
++
++static bd_t bd;
++
++static void yosemite_fixups(void)
++{
++	unsigned long sysclk = 66666666;
++
++	ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
++	ibm4xx_sdram_fixup_memsize();
++	ibm4xx_quiesce_eth((u32 *)0xef600e00, (u32 *)0xef600f00);
++	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++	dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
++}
++
++void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
++		unsigned long r6, unsigned long r7)
++{
++	CUBOOT_INIT();
++	platform_ops.fixups = yosemite_fixups;
++	platform_ops.exit = ibm44x_dbcr_reset;
++	fdt_init(_dtb_start);
++	serial_console_init();
++}
+diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
+index 60f561e..5d12336 100644
+--- a/arch/powerpc/boot/devtree.c
++++ b/arch/powerpc/boot/devtree.c
+@@ -350,3 +350,23 @@ int dt_is_compatible(void *node, const char *compat)
+ 
+ 	return 0;
+ }
++
++int dt_get_virtual_reg(void *node, void **addr, int nres)
++{
++	unsigned long xaddr;
++	int n;
++
++	n = getprop(node, "virtual-reg", addr, nres * 4);
++	if (n > 0)
++		return n / 4;
++
++	for (n = 0; n < nres; n++) {
++		if (!dt_xlate_reg(node, n, &xaddr, NULL))
++			break;
++
++		addr[n] = (void *)xaddr;
++	}
++
++	return n;
++}
++
+diff --git a/arch/powerpc/boot/dts/bamboo.dts b/arch/powerpc/boot/dts/bamboo.dts
+index 7dc37c9..ba2521b 100644
+--- a/arch/powerpc/boot/dts/bamboo.dts
++++ b/arch/powerpc/boot/dts/bamboo.dts
+@@ -204,7 +204,6 @@
+ 			};
+ 
+ 			EMAC0: ethernet at ef600e00 {
+-				linux,network-index = <0>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+ 				interrupt-parent = <&UIC1>;
+@@ -225,7 +224,6 @@
+ 			};
+ 
+ 			EMAC1: ethernet at ef600f00 {
+-				linux,network-index = <1>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+ 				interrupt-parent = <&UIC1>;
+diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
+new file mode 100644
+index 0000000..3963412
+--- /dev/null
++++ b/arch/powerpc/boot/dts/canyonlands.dts
+@@ -0,0 +1,439 @@
++/*
++ * Device Tree Source for AMCC Canyonlands (460EX)
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without
++ * any warranty of any kind, whether express or implied.
++ */
++
++/ {
++	#address-cells = <2>;
++	#size-cells = <1>;
++	model = "amcc,canyonlands";
++	compatible = "amcc,canyonlands";
++	dcr-parent = <&/cpus/cpu at 0>;
++
++	aliases {
++		ethernet0 = &EMAC0;
++		ethernet1 = &EMAC1;
++		serial0 = &UART0;
++		serial1 = &UART1;
++	};
++
++	cpus {
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		cpu at 0 {
++			device_type = "cpu";
++			model = "PowerPC,460EX";
++			reg = <0>;
++			clock-frequency = <0>; /* Filled in by U-Boot */
++			timebase-frequency = <0>; /* Filled in by U-Boot */
++			i-cache-line-size = <20>;
++			d-cache-line-size = <20>;
++			i-cache-size = <8000>;
++			d-cache-size = <8000>;
++			dcr-controller;
++			dcr-access-method = "native";
++		};
++	};
++
++	memory {
++		device_type = "memory";
++		reg = <0 0 0>; /* Filled in by U-Boot */
++	};
++
++	UIC0: interrupt-controller0 {
++		compatible = "ibm,uic-460ex","ibm,uic";
++		interrupt-controller;
++		cell-index = <0>;
++		dcr-reg = <0c0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++	};
++
++	UIC1: interrupt-controller1 {
++		compatible = "ibm,uic-460ex","ibm,uic";
++		interrupt-controller;
++		cell-index = <1>;
++		dcr-reg = <0d0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++		interrupts = <1e 4 1f 4>; /* cascade */
++		interrupt-parent = <&UIC0>;
++	};
++
++	UIC2: interrupt-controller2 {
++		compatible = "ibm,uic-460ex","ibm,uic";
++		interrupt-controller;
++		cell-index = <2>;
++		dcr-reg = <0e0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++		interrupts = <a 4 b 4>; /* cascade */
++		interrupt-parent = <&UIC0>;
++	};
++
++	UIC3: interrupt-controller3 {
++		compatible = "ibm,uic-460ex","ibm,uic";
++		interrupt-controller;
++		cell-index = <3>;
++		dcr-reg = <0f0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++		interrupts = <10 4 11 4>; /* cascade */
++		interrupt-parent = <&UIC0>;
++	};
++
++	SDR0: sdr {
++		compatible = "ibm,sdr-460ex";
++		dcr-reg = <00e 002>;
++	};
++
++	CPR0: cpr {
++		compatible = "ibm,cpr-460ex";
++		dcr-reg = <00c 002>;
++	};
++
++	plb {
++		compatible = "ibm,plb-460ex", "ibm,plb4";
++		#address-cells = <2>;
++		#size-cells = <1>;
++		ranges;
++		clock-frequency = <0>; /* Filled in by U-Boot */
++
++		SDRAM0: sdram {
++			compatible = "ibm,sdram-460ex", "ibm,sdram-405gp";
++			dcr-reg = <010 2>;
++		};
++
++		MAL0: mcmal {
++			compatible = "ibm,mcmal-460ex", "ibm,mcmal2";
++			dcr-reg = <180 62>;
++			num-tx-chans = <2>;
++			num-rx-chans = <10>;
++			#address-cells = <0>;
++			#size-cells = <0>;
++			interrupt-parent = <&UIC2>;
++			interrupts = <	/*TXEOB*/ 6 4
++					/*RXEOB*/ 7 4
++					/*SERR*/  3 4
++					/*TXDE*/  4 4
++					/*RXDE*/  5 4>;
++		};
++
++		POB0: opb {
++			compatible = "ibm,opb-460ex", "ibm,opb";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			ranges = <b0000000 4 b0000000 50000000>;
++			clock-frequency = <0>; /* Filled in by U-Boot */
++
++			EBC0: ebc {
++				compatible = "ibm,ebc-460ex", "ibm,ebc";
++				dcr-reg = <012 2>;
++				#address-cells = <2>;
++				#size-cells = <1>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				/* ranges property is supplied by U-Boot */
++				interrupts = <6 4>;
++				interrupt-parent = <&UIC1>;
++
++				nor_flash at 0,0 {
++					compatible = "amd,s29gl512n", "cfi-flash";
++					bank-width = <2>;
++					reg = <0 000000 4000000>;
++					#address-cells = <1>;
++					#size-cells = <1>;
++					partition at 0 {
++						label = "kernel";
++						reg = <0 1e0000>;
++					};
++					partition at 1e0000 {
++						label = "dtb";
++						reg = <1e0000 20000>;
++					};
++					partition at 200000 {
++						label = "ramdisk";
++						reg = <200000 1400000>;
++					};
++					partition at 1600000 {
++						label = "jffs2";
++						reg = <1600000 400000>;
++					};
++					partition at 1a00000 {
++						label = "user";
++						reg = <1a00000 2560000>;
++					};
++					partition at 3f60000 {
++						label = "env";
++						reg = <3f60000 40000>;
++					};
++					partition at 3fa0000 {
++						label = "u-boot";
++						reg = <3fa0000 60000>;
++					};
++				};
++			};
++
++			UART0: serial at ef600300 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600300 8>;
++				virtual-reg = <ef600300>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				current-speed = <0>; /* Filled in by U-Boot */
++				interrupt-parent = <&UIC1>;
++				interrupts = <1 4>;
++			};
++
++			UART1: serial at ef600400 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600400 8>;
++				virtual-reg = <ef600400>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				current-speed = <0>; /* Filled in by U-Boot */
++				interrupt-parent = <&UIC0>;
++				interrupts = <1 4>;
++			};
++
++			UART2: serial at ef600500 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600500 8>;
++				virtual-reg = <ef600500>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				current-speed = <0>; /* Filled in by U-Boot */
++				interrupt-parent = <&UIC1>;
++				interrupts = <1d 4>;
++			};
++
++			UART3: serial at ef600600 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600600 8>;
++				virtual-reg = <ef600600>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				current-speed = <0>; /* Filled in by U-Boot */
++				interrupt-parent = <&UIC1>;
++				interrupts = <1e 4>;
++			};
++
++			IIC0: i2c at ef600700 {
++				compatible = "ibm,iic-460ex", "ibm,iic";
++				reg = <ef600700 14>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <2 4>;
++			};
++
++			IIC1: i2c at ef600800 {
++				compatible = "ibm,iic-460ex", "ibm,iic";
++				reg = <ef600800 14>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <3 4>;
++			};
++
++			ZMII0: emac-zmii at ef600d00 {
++				compatible = "ibm,zmii-460ex", "ibm,zmii";
++				reg = <ef600d00 c>;
++			};
++
++			RGMII0: emac-rgmii at ef601500 {
++				compatible = "ibm,rgmii-460ex", "ibm,rgmii";
++				reg = <ef601500 8>;
++				has-mdio;
++			};
++
++			TAH0: emac-tah at ef601350 {
++				compatible = "ibm,tah-460ex", "ibm,tah";
++				reg = <ef601350 30>;
++			};
++
++			TAH1: emac-tah at ef601450 {
++				compatible = "ibm,tah-460ex", "ibm,tah";
++				reg = <ef601450 30>;
++			};
++
++			EMAC0: ethernet at ef600e00 {
++				device_type = "network";
++				compatible = "ibm,emac-460ex", "ibm,emac4";
++				interrupt-parent = <&EMAC0>;
++				interrupts = <0 1>;
++				#interrupt-cells = <1>;
++				#address-cells = <0>;
++				#size-cells = <0>;
++				interrupt-map = </*Status*/ 0 &UIC2 10 4
++						 /*Wake*/   1 &UIC2 14 4>;
++				reg = <ef600e00 70>;
++				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 = <2328>;
++				rx-fifo-size = <1000>;
++				tx-fifo-size = <800>;
++				phy-mode = "rgmii";
++				phy-map = <00000000>;
++				rgmii-device = <&RGMII0>;
++				rgmii-channel = <0>;
++				tah-device = <&TAH0>;
++				tah-channel = <0>;
++				has-inverted-stacr-oc;
++				has-new-stacr-staopc;
++			};
++
++			EMAC1: ethernet at ef600f00 {
++				device_type = "network";
++				compatible = "ibm,emac-460ex", "ibm,emac4";
++				interrupt-parent = <&EMAC1>;
++				interrupts = <0 1>;
++				#interrupt-cells = <1>;
++				#address-cells = <0>;
++				#size-cells = <0>;
++				interrupt-map = </*Status*/ 0 &UIC2 11 4
++						 /*Wake*/   1 &UIC2 15 4>;
++				reg = <ef600f00 70>;
++				local-mac-address = [000000000000]; /* Filled in by U-Boot */
++				mal-device = <&MAL0>;
++				mal-tx-channel = <1>;
++				mal-rx-channel = <8>;
++				cell-index = <1>;
++				max-frame-size = <2328>;
++				rx-fifo-size = <1000>;
++				tx-fifo-size = <800>;
++				phy-mode = "rgmii";
++				phy-map = <00000000>;
++				rgmii-device = <&RGMII0>;
++				rgmii-channel = <1>;
++				tah-device = <&TAH1>;
++				tah-channel = <1>;
++				has-inverted-stacr-oc;
++				has-new-stacr-staopc;
++				mdio-device = <&EMAC0>;
++			};
++		};
++
++		PCIX0: pci at c0ec00000 {
++			device_type = "pci";
++			#interrupt-cells = <1>;
++			#size-cells = <2>;
++			#address-cells = <3>;
++			compatible = "ibm,plb-pcix-460ex", "ibm,plb-pcix";
++			primary;
++			large-inbound-windows;
++			enable-msi-hole;
++			reg = <c 0ec00000   8	/* Config space access */
++			       0 0 0		/* no IACK cycles */
++			       c 0ed00000   4   /* Special cycles */
++			       c 0ec80000 100	/* Internal registers */
++			       c 0ec80100  fc>;	/* Internal messaging registers */
++
++			/* Outbound ranges, one memory and one IO,
++			 * later cannot be changed
++			 */
++			ranges = <02000000 0 80000000 0000000d 80000000 0 80000000
++				  01000000 0 00000000 0000000c 08000000 0 00010000>;
++
++			/* Inbound 2GB range starting at 0 */
++			dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++			/* This drives busses 0 to 0x3f */
++			bus-range = <0 3f>;
++
++			/* All PCI interrupts are routed to ext IRQ 2 -> UIC1-0 */
++			interrupt-map-mask = <0000 0 0 0>;
++			interrupt-map = < 0000 0 0 0 &UIC1 0 8 >;
++		};
++
++		PCIE0: pciex at d00000000 {
++			device_type = "pci";
++			#interrupt-cells = <1>;
++			#size-cells = <2>;
++			#address-cells = <3>;
++			compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++			primary;
++			port = <0>; /* port number */
++			reg = <d 00000000 20000000	/* Config space access */
++			       c 08010000 00001000>;	/* Registers */
++			dcr-reg = <100 020>;
++			sdr-base = <300>;
++
++			/* Outbound ranges, one memory and one IO,
++			 * later cannot be changed
++			 */
++			ranges = <02000000 0 80000000 0000000e 00000000 0 80000000
++				  01000000 0 00000000 0000000f 80000000 0 00010000>;
++
++			/* Inbound 2GB range starting at 0 */
++			dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++			/* This drives busses 40 to 0x7f */
++			bus-range = <40 7f>;
++
++			/* Legacy interrupts (note the weird polarity, the bridge seems
++			 * to invert PCIe legacy interrupts).
++			 * We are de-swizzling here because the numbers are actually for
++			 * port of the root complex virtual P2P bridge. But I want
++			 * to avoid putting a node for it in the tree, so the numbers
++			 * below are basically de-swizzled numbers.
++			 * The real slot is on idsel 0, so the swizzling is 1:1
++			 */
++			interrupt-map-mask = <0000 0 0 7>;
++			interrupt-map = <
++				0000 0 0 1 &UIC3 c 4 /* swizzled int A */
++				0000 0 0 2 &UIC3 d 4 /* swizzled int B */
++				0000 0 0 3 &UIC3 e 4 /* swizzled int C */
++				0000 0 0 4 &UIC3 f 4 /* swizzled int D */>;
++		};
++
++		PCIE1: pciex at d20000000 {
++			device_type = "pci";
++			#interrupt-cells = <1>;
++			#size-cells = <2>;
++			#address-cells = <3>;
++			compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++			primary;
++			port = <1>; /* port number */
++			reg = <d 20000000 20000000	/* Config space access */
++			       c 08011000 00001000>;	/* Registers */
++			dcr-reg = <120 020>;
++			sdr-base = <340>;
++
++			/* Outbound ranges, one memory and one IO,
++			 * later cannot be changed
++			 */
++			ranges = <02000000 0 80000000 0000000e 80000000 0 80000000
++				  01000000 0 00000000 0000000f 80010000 0 00010000>;
++
++			/* Inbound 2GB range starting at 0 */
++			dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++			/* This drives busses 80 to 0xbf */
++			bus-range = <80 bf>;
++
++			/* Legacy interrupts (note the weird polarity, the bridge seems
++			 * to invert PCIe legacy interrupts).
++			 * We are de-swizzling here because the numbers are actually for
++			 * port of the root complex virtual P2P bridge. But I want
++			 * to avoid putting a node for it in the tree, so the numbers
++			 * below are basically de-swizzled numbers.
++			 * The real slot is on idsel 0, so the swizzling is 1:1
++			 */
++			interrupt-map-mask = <0000 0 0 7>;
++			interrupt-map = <
++				0000 0 0 1 &UIC3 10 4 /* swizzled int A */
++				0000 0 0 2 &UIC3 11 4 /* swizzled int B */
++				0000 0 0 3 &UIC3 12 4 /* swizzled int C */
++				0000 0 0 4 &UIC3 13 4 /* swizzled int D */>;
++		};
++	};
++};
+diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts
+index 0b000cb..5079dc8 100644
+--- a/arch/powerpc/boot/dts/ebony.dts
++++ b/arch/powerpc/boot/dts/ebony.dts
+@@ -241,7 +241,6 @@
+ 			};
+ 
+ 			EMAC0: ethernet at 40000800 {
+-				linux,network-index = <0>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440gp", "ibm,emac";
+ 				interrupt-parent = <&UIC1>;
+@@ -261,7 +260,6 @@
+ 				zmii-channel = <0>;
+ 			};
+ 			EMAC1: ethernet at 40000900 {
+-				linux,network-index = <1>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440gp", "ibm,emac";
+ 				interrupt-parent = <&UIC1>;
+diff --git a/arch/powerpc/boot/dts/ep8248e.dts b/arch/powerpc/boot/dts/ep8248e.dts
+index 5d2fb76..756758f 100644
+--- a/arch/powerpc/boot/dts/ep8248e.dts
++++ b/arch/powerpc/boot/dts/ep8248e.dts
+@@ -121,8 +121,7 @@
+ 
+ 				data at 0 {
+ 					compatible = "fsl,cpm-muram-data";
+-					reg = <0 0x1100 0x1140
+-					       0xec0 0x9800 0x800>;
++					reg = <0 0x2000 0x9800 0x800>;
+ 				};
+ 			};
+ 
+@@ -138,7 +137,7 @@
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc8248-smc-uart",
+ 				             "fsl,cpm2-smc-uart";
+-				reg = <0x11a80 0x20 0x1100 0x40>;
++				reg = <0x11a80 0x20 0x87fc 2>;
+ 				interrupts = <4 8>;
+ 				interrupt-parent = <&PIC>;
+ 				fsl,cpm-brg = <7>;
+diff --git a/arch/powerpc/boot/dts/ep88xc.dts b/arch/powerpc/boot/dts/ep88xc.dts
+index 02705f2..ae57d62 100644
+--- a/arch/powerpc/boot/dts/ep88xc.dts
++++ b/arch/powerpc/boot/dts/ep88xc.dts
+@@ -2,7 +2,7 @@
+  * EP88xC Device Tree Source
+  *
+  * Copyright 2006 MontaVista Software, Inc.
+- * Copyright 2007 Freescale Semiconductor, Inc.
++ * Copyright 2007,2008 Freescale Semiconductor, Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -10,6 +10,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ 
+ / {
+ 	model = "EP88xC";
+@@ -23,44 +24,44 @@
+ 
+ 		PowerPC,885 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <d#16>;
+-			i-cache-line-size = <d#16>;
+-			d-cache-size = <d#8192>;
+-			i-cache-size = <d#8192>;
++			reg = <0x0>;
++			d-cache-line-size = <16>;
++			i-cache-line-size = <16>;
++			d-cache-size = <8192>;
++			i-cache-size = <8192>;
+ 			timebase-frequency = <0>;
+ 			bus-frequency = <0>;
+ 			clock-frequency = <0>;
+-			interrupts = <f 2>;	// decrementer interrupt
++			interrupts = <15 2>;	// decrementer interrupt
+ 			interrupt-parent = <&PIC>;
+ 		};
+ 	};
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <0 0>;
++		reg = <0x0 0x0>;
+ 	};
+ 
+ 	localbus at fa200100 {
+ 		compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus";
+ 		#address-cells = <2>;
+ 		#size-cells = <1>;
+-		reg = <fa200100 40>;
++		reg = <0xfa200100 0x40>;
+ 
+ 		ranges = <
+-			0 0 fc000000 04000000
+-			3 0 fa000000 01000000
++			0x0 0x0 0xfc000000 0x4000000
++			0x3 0x0 0xfa000000 0x1000000
+ 		>;
+ 
+ 		flash at 0,2000000 {
+ 			compatible = "cfi-flash";
+-			reg = <0 2000000 2000000>;
++			reg = <0x0 0x2000000 0x2000000>;
+ 			bank-width = <4>;
+ 			device-width = <2>;
+ 		};
+ 
+ 		board-control at 3,400000 {
+-			reg = <3 400000 10>;
++			reg = <0x3 0x400000 0x10>;
+ 			compatible = "fsl,ep88xc-bcsr";
+ 		};
+ 	};
+@@ -70,25 +71,25 @@
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <0 fa200000 00004000>;
++		ranges = <0x0 0xfa200000 0x4000>;
+ 		bus-frequency = <0>;
+ 
+ 		// Temporary -- will go away once kernel uses ranges for get_immrbase().
+-		reg = <fa200000 4000>;
++		reg = <0xfa200000 0x4000>;
+ 
+ 		mdio at e00 {
+ 			compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio";
+-			reg = <e00 188>;
++			reg = <0xe00 0x188>;
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 
+ 			PHY0: ethernet-phy at 0 {
+-				reg = <0>;
++				reg = <0x0>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 
+ 			PHY1: ethernet-phy at 1 {
+-				reg = <1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -97,7 +98,7 @@
+ 			device_type = "network";
+ 			compatible = "fsl,mpc885-fec-enet",
+ 			             "fsl,pq1-fec-enet";
+-			reg = <e00 188>;
++			reg = <0xe00 0x188>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			interrupts = <3 1>;
+ 			interrupt-parent = <&PIC>;
+@@ -109,7 +110,7 @@
+ 			device_type = "network";
+ 			compatible = "fsl,mpc885-fec-enet",
+ 			             "fsl,pq1-fec-enet";
+-			reg = <1e00 188>;
++			reg = <0x1e00 0x188>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			interrupts = <7 1>;
+ 			interrupt-parent = <&PIC>;
+@@ -120,7 +121,7 @@
+ 		PIC: interrupt-controller at 0 {
+ 			interrupt-controller;
+ 			#interrupt-cells = <2>;
+-			reg = <0 24>;
++			reg = <0x0 0x24>;
+ 			compatible = "fsl,mpc885-pic", "fsl,pq1-pic";
+ 		};
+ 
+@@ -130,29 +131,29 @@
+ 			#size-cells = <2>;
+ 			compatible = "fsl,pq-pcmcia";
+ 			device_type = "pcmcia";
+-			reg = <80 80>;
++			reg = <0x80 0x80>;
+ 			interrupt-parent = <&PIC>;
+-			interrupts = <d 1>;
++			interrupts = <13 1>;
+ 		};
+ 
+ 		cpm at 9c0 {
+ 			#address-cells = <1>;
+ 			#size-cells = <1>;
+ 			compatible = "fsl,mpc885-cpm", "fsl,cpm1";
+-			command-proc = <9c0>;
++			command-proc = <0x9c0>;
+ 			interrupts = <0>;	// cpm error interrupt
+ 			interrupt-parent = <&CPM_PIC>;
+-			reg = <9c0 40>;
++			reg = <0x9c0 0x40>;
+ 			ranges;
+ 
+ 			muram at 2000 {
+ 				#address-cells = <1>;
+ 				#size-cells = <1>;
+-				ranges = <0 2000 2000>;
++				ranges = <0x0 0x2000 0x2000>;
+ 
+ 				data at 0 {
+ 					compatible = "fsl,cpm-muram-data";
+-					reg = <0 1c00>;
++					reg = <0x0 0x1c00>;
+ 				};
+ 			};
+ 
+@@ -160,7 +161,7 @@
+ 				compatible = "fsl,mpc885-brg",
+ 				             "fsl,cpm1-brg",
+ 				             "fsl,cpm-brg";
+-				reg = <9f0 10>;
++				reg = <0x9f0 0x10>;
+ 			};
+ 
+ 			CPM_PIC: interrupt-controller at 930 {
+@@ -168,7 +169,7 @@
+ 				#interrupt-cells = <1>;
+ 				interrupts = <5 2 0 2>;
+ 				interrupt-parent = <&PIC>;
+-				reg = <930 20>;
++				reg = <0x930 0x20>;
+ 				compatible = "fsl,mpc885-cpm-pic",
+ 				             "fsl,cpm1-pic";
+ 			};
+@@ -178,11 +179,11 @@
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc885-smc-uart",
+ 				             "fsl,cpm1-smc-uart";
+-				reg = <a80 10 3e80 40>;
++				reg = <0xa80 0x10 0x3e80 0x40>;
+ 				interrupts = <4>;
+ 				interrupt-parent = <&CPM_PIC>;
+ 				fsl,cpm-brg = <1>;
+-				fsl,cpm-command = <0090>;
++				fsl,cpm-command = <0x90>;
+ 				linux,planetcore-label = "SMC1";
+ 			};
+ 
+@@ -191,11 +192,11 @@
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc885-scc-uart",
+ 				             "fsl,cpm1-scc-uart";
+-				reg = <a20 20 3d00 80>;
+-				interrupts = <1d>;
++				reg = <0xa20 0x20 0x3d00 0x80>;
++				interrupts = <29>;
+ 				interrupt-parent = <&CPM_PIC>;
+ 				fsl,cpm-brg = <2>;
+-				fsl,cpm-command = <0040>;
++				fsl,cpm-command = <0x40>;
+ 				linux,planetcore-label = "SCC2";
+ 			};
+ 
+@@ -204,9 +205,9 @@
+ 				#size-cells = <0>;
+ 				compatible = "fsl,mpc885-usb",
+ 				             "fsl,cpm1-usb";
+-				reg = <a00 18 1c00 80>;
++				reg = <0xa00 0x18 0x1c00 0x80>;
+ 				interrupt-parent = <&CPM_PIC>;
+-				interrupts = <1e>;
++				interrupts = <30>;
+ 				fsl,cpm-command = <0000>;
+ 			};
+ 		};
+diff --git a/arch/powerpc/boot/dts/glacier.dts b/arch/powerpc/boot/dts/glacier.dts
+new file mode 100644
+index 0000000..0f2fc07
+--- /dev/null
++++ b/arch/powerpc/boot/dts/glacier.dts
+@@ -0,0 +1,504 @@
++/*
++ * Device Tree Source for AMCC Glacier (460GT)
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without
++ * any warranty of any kind, whether express or implied.
++ */
++
++/ {
++	#address-cells = <2>;
++	#size-cells = <1>;
++	model = "amcc,glacier";
++	compatible = "amcc,glacier", "amcc,canyonlands";
++	dcr-parent = <&/cpus/cpu at 0>;
++
++	aliases {
++		ethernet0 = &EMAC0;
++		ethernet1 = &EMAC1;
++		ethernet2 = &EMAC2;
++		ethernet3 = &EMAC3;
++		serial0 = &UART0;
++		serial1 = &UART1;
++	};
++
++	cpus {
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		cpu at 0 {
++			device_type = "cpu";
++			model = "PowerPC,460GT";
++			reg = <0>;
++			clock-frequency = <0>; /* Filled in by U-Boot */
++			timebase-frequency = <0>; /* Filled in by U-Boot */
++			i-cache-line-size = <20>;
++			d-cache-line-size = <20>;
++			i-cache-size = <8000>;
++			d-cache-size = <8000>;
++			dcr-controller;
++			dcr-access-method = "native";
++		};
++	};
++
++	memory {
++		device_type = "memory";
++		reg = <0 0 0>; /* Filled in by U-Boot */
++	};
++
++	UIC0: interrupt-controller0 {
++		compatible = "ibm,uic-460gt","ibm,uic";
++		interrupt-controller;
++		cell-index = <0>;
++		dcr-reg = <0c0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++	};
++
++	UIC1: interrupt-controller1 {
++		compatible = "ibm,uic-460gt","ibm,uic";
++		interrupt-controller;
++		cell-index = <1>;
++		dcr-reg = <0d0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++		interrupts = <1e 4 1f 4>; /* cascade */
++		interrupt-parent = <&UIC0>;
++	};
++
++	UIC2: interrupt-controller2 {
++		compatible = "ibm,uic-460gt","ibm,uic";
++		interrupt-controller;
++		cell-index = <2>;
++		dcr-reg = <0e0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++		interrupts = <a 4 b 4>; /* cascade */
++		interrupt-parent = <&UIC0>;
++	};
++
++	UIC3: interrupt-controller3 {
++		compatible = "ibm,uic-460gt","ibm,uic";
++		interrupt-controller;
++		cell-index = <3>;
++		dcr-reg = <0f0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++		interrupts = <10 4 11 4>; /* cascade */
++		interrupt-parent = <&UIC0>;
++	};
++
++	SDR0: sdr {
++		compatible = "ibm,sdr-460gt";
++		dcr-reg = <00e 002>;
++	};
++
++	CPR0: cpr {
++		compatible = "ibm,cpr-460gt";
++		dcr-reg = <00c 002>;
++	};
++
++	plb {
++		compatible = "ibm,plb-460gt", "ibm,plb4";
++		#address-cells = <2>;
++		#size-cells = <1>;
++		ranges;
++		clock-frequency = <0>; /* Filled in by U-Boot */
++
++		SDRAM0: sdram {
++			compatible = "ibm,sdram-460gt", "ibm,sdram-405gp";
++			dcr-reg = <010 2>;
++		};
++
++		MAL0: mcmal {
++			compatible = "ibm,mcmal-460gt", "ibm,mcmal2";
++			dcr-reg = <180 62>;
++			num-tx-chans = <4>;
++			num-rx-chans = <20>;
++			#address-cells = <0>;
++			#size-cells = <0>;
++			interrupt-parent = <&UIC2>;
++			interrupts = <	/*TXEOB*/ 6 4
++					/*RXEOB*/ 7 4
++					/*SERR*/  3 4
++					/*TXDE*/  4 4
++					/*RXDE*/  5 4>;
++			desc-base-addr-high = <8>;
++		};
++
++		POB0: opb {
++			compatible = "ibm,opb-460gt", "ibm,opb";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			ranges = <b0000000 4 b0000000 50000000>;
++			clock-frequency = <0>; /* Filled in by U-Boot */
++
++			EBC0: ebc {
++				compatible = "ibm,ebc-460gt", "ibm,ebc";
++				dcr-reg = <012 2>;
++				#address-cells = <2>;
++				#size-cells = <1>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				/* ranges property is supplied by U-Boot */
++				interrupts = <6 4>;
++				interrupt-parent = <&UIC1>;
++
++				nor_flash at 0,0 {
++					compatible = "amd,s29gl512n", "cfi-flash";
++					bank-width = <2>;
++					reg = <0 000000 4000000>;
++					#address-cells = <1>;
++					#size-cells = <1>;
++					partition at 0 {
++						label = "kernel";
++						reg = <0 1e0000>;
++					};
++					partition at 1e0000 {
++						label = "dtb";
++						reg = <1e0000 20000>;
++					};
++					partition at 200000 {
++						label = "ramdisk";
++						reg = <200000 1400000>;
++					};
++					partition at 1600000 {
++						label = "jffs2";
++						reg = <1600000 400000>;
++					};
++					partition at 1a00000 {
++						label = "user";
++						reg = <1a00000 2560000>;
++					};
++					partition at 3f60000 {
++						label = "env";
++						reg = <3f60000 40000>;
++					};
++					partition at 3fa0000 {
++						label = "u-boot";
++						reg = <3fa0000 60000>;
++					};
++				};
++			};
++
++			UART0: serial at ef600300 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600300 8>;
++				virtual-reg = <ef600300>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				current-speed = <0>; /* Filled in by U-Boot */
++				interrupt-parent = <&UIC1>;
++				interrupts = <1 4>;
++			};
++
++			UART1: serial at ef600400 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600400 8>;
++				virtual-reg = <ef600400>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				current-speed = <0>; /* Filled in by U-Boot */
++				interrupt-parent = <&UIC0>;
++				interrupts = <1 4>;
++			};
++
++			UART2: serial at ef600500 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600500 8>;
++				virtual-reg = <ef600500>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				current-speed = <0>; /* Filled in by U-Boot */
++				interrupt-parent = <&UIC1>;
++				interrupts = <1d 4>;
++			};
++
++			UART3: serial at ef600600 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600600 8>;
++				virtual-reg = <ef600600>;
++				clock-frequency = <0>; /* Filled in by U-Boot */
++				current-speed = <0>; /* Filled in by U-Boot */
++				interrupt-parent = <&UIC1>;
++				interrupts = <1e 4>;
++			};
++
++			IIC0: i2c at ef600700 {
++				compatible = "ibm,iic-460gt", "ibm,iic";
++				reg = <ef600700 14>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <2 4>;
++			};
++
++			IIC1: i2c at ef600800 {
++				compatible = "ibm,iic-460gt", "ibm,iic";
++				reg = <ef600800 14>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <3 4>;
++			};
++
++			ZMII0: emac-zmii at ef600d00 {
++				compatible = "ibm,zmii-460gt", "ibm,zmii";
++				reg = <ef600d00 c>;
++			};
++
++			RGMII0: emac-rgmii at ef601500 {
++				compatible = "ibm,rgmii-460gt", "ibm,rgmii";
++				reg = <ef601500 8>;
++				has-mdio;
++			};
++
++			RGMII1: emac-rgmii at ef601600 {
++				compatible = "ibm,rgmii-460gt", "ibm,rgmii";
++				reg = <ef601600 8>;
++				has-mdio;
++			};
++
++			TAH0: emac-tah at ef601350 {
++				compatible = "ibm,tah-460gt", "ibm,tah";
++				reg = <ef601350 30>;
++			};
++
++			TAH1: emac-tah at ef601450 {
++				compatible = "ibm,tah-460gt", "ibm,tah";
++				reg = <ef601450 30>;
++			};
++
++			EMAC0: ethernet at ef600e00 {
++				device_type = "network";
++				compatible = "ibm,emac-460gt", "ibm,emac4";
++				interrupt-parent = <&EMAC0>;
++				interrupts = <0 1>;
++				#interrupt-cells = <1>;
++				#address-cells = <0>;
++				#size-cells = <0>;
++				interrupt-map = </*Status*/ 0 &UIC2 10 4
++						 /*Wake*/   1 &UIC2 14 4>;
++				reg = <ef600e00 70>;
++				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 = <2328>;
++				rx-fifo-size = <1000>;
++				tx-fifo-size = <800>;
++				phy-mode = "rgmii";
++				phy-map = <00000000>;
++				rgmii-device = <&RGMII0>;
++				rgmii-channel = <0>;
++				tah-device = <&TAH0>;
++				tah-channel = <0>;
++				has-inverted-stacr-oc;
++				has-new-stacr-staopc;
++			};
++
++			EMAC1: ethernet at ef600f00 {
++				device_type = "network";
++				compatible = "ibm,emac-460gt", "ibm,emac4";
++				interrupt-parent = <&EMAC1>;
++				interrupts = <0 1>;
++				#interrupt-cells = <1>;
++				#address-cells = <0>;
++				#size-cells = <0>;
++				interrupt-map = </*Status*/ 0 &UIC2 11 4
++						 /*Wake*/   1 &UIC2 15 4>;
++				reg = <ef600f00 70>;
++				local-mac-address = [000000000000]; /* Filled in by U-Boot */
++				mal-device = <&MAL0>;
++				mal-tx-channel = <1>;
++				mal-rx-channel = <8>;
++				cell-index = <1>;
++				max-frame-size = <2328>;
++				rx-fifo-size = <1000>;
++				tx-fifo-size = <800>;
++				phy-mode = "rgmii";
++				phy-map = <00000000>;
++				rgmii-device = <&RGMII0>;
++				rgmii-channel = <1>;
++				tah-device = <&TAH1>;
++				tah-channel = <1>;
++				has-inverted-stacr-oc;
++				has-new-stacr-staopc;
++				mdio-device = <&EMAC0>;
++			};
++
++			EMAC2: ethernet at ef601100 {
++				device_type = "network";
++				compatible = "ibm,emac-460gt", "ibm,emac4";
++				interrupt-parent = <&EMAC2>;
++				interrupts = <0 1>;
++				#interrupt-cells = <1>;
++				#address-cells = <0>;
++				#size-cells = <0>;
++				interrupt-map = </*Status*/ 0 &UIC2 12 4
++						 /*Wake*/   1 &UIC2 16 4>;
++				reg = <ef601100 70>;
++				local-mac-address = [000000000000]; /* Filled in by U-Boot */
++				mal-device = <&MAL0>;
++				mal-tx-channel = <2>;
++				mal-rx-channel = <10>;
++				cell-index = <2>;
++				max-frame-size = <2328>;
++				rx-fifo-size = <1000>;
++				tx-fifo-size = <800>;
++				phy-mode = "rgmii";
++				phy-map = <00000000>;
++				rgmii-device = <&RGMII1>;
++				rgmii-channel = <0>;
++				has-inverted-stacr-oc;
++				has-new-stacr-staopc;
++				mdio-device = <&EMAC0>;
++			};
++
++			EMAC3: ethernet at ef601200 {
++				device_type = "network";
++				compatible = "ibm,emac-460gt", "ibm,emac4";
++				interrupt-parent = <&EMAC3>;
++				interrupts = <0 1>;
++				#interrupt-cells = <1>;
++				#address-cells = <0>;
++				#size-cells = <0>;
++				interrupt-map = </*Status*/ 0 &UIC2 13 4
++						 /*Wake*/   1 &UIC2 17 4>;
++				reg = <ef601200 70>;
++				local-mac-address = [000000000000]; /* Filled in by U-Boot */
++				mal-device = <&MAL0>;
++				mal-tx-channel = <3>;
++				mal-rx-channel = <18>;
++				cell-index = <3>;
++				max-frame-size = <2328>;
++				rx-fifo-size = <1000>;
++				tx-fifo-size = <800>;
++				phy-mode = "rgmii";
++				phy-map = <00000000>;
++				rgmii-device = <&RGMII1>;
++				rgmii-channel = <1>;
++				has-inverted-stacr-oc;
++				has-new-stacr-staopc;
++				mdio-device = <&EMAC0>;
++			};
++		};
++
++		PCIX0: pci at c0ec00000 {
++			device_type = "pci";
++			#interrupt-cells = <1>;
++			#size-cells = <2>;
++			#address-cells = <3>;
++			compatible = "ibm,plb-pcix-460gt", "ibm,plb-pcix";
++			primary;
++			large-inbound-windows;
++			enable-msi-hole;
++			reg = <c 0ec00000   8	/* Config space access */
++			       0 0 0		/* no IACK cycles */
++			       c 0ed00000   4   /* Special cycles */
++			       c 0ec80000 100	/* Internal registers */
++			       c 0ec80100  fc>;	/* Internal messaging registers */
++
++			/* Outbound ranges, one memory and one IO,
++			 * later cannot be changed
++			 */
++			ranges = <02000000 0 80000000 0000000d 80000000 0 80000000
++				  01000000 0 00000000 0000000c 08000000 0 00010000>;
++
++			/* Inbound 2GB range starting at 0 */
++			dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++			/* This drives busses 0 to 0x3f */
++			bus-range = <0 3f>;
++
++			/* All PCI interrupts are routed to ext IRQ 2 -> UIC1-0 */
++			interrupt-map-mask = <0000 0 0 0>;
++			interrupt-map = < 0000 0 0 0 &UIC1 0 8 >;
++		};
++
++		PCIE0: pciex at d00000000 {
++			device_type = "pci";
++			#interrupt-cells = <1>;
++			#size-cells = <2>;
++			#address-cells = <3>;
++			compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++			primary;
++			port = <0>; /* port number */
++			reg = <d 00000000 20000000	/* Config space access */
++			       c 08010000 00001000>;	/* Registers */
++			dcr-reg = <100 020>;
++			sdr-base = <300>;
++
++			/* Outbound ranges, one memory and one IO,
++			 * later cannot be changed
++			 */
++			ranges = <02000000 0 80000000 0000000e 00000000 0 80000000
++				  01000000 0 00000000 0000000f 80000000 0 00010000>;
++
++			/* Inbound 2GB range starting at 0 */
++			dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++			/* This drives busses 40 to 0x7f */
++			bus-range = <40 7f>;
++
++			/* Legacy interrupts (note the weird polarity, the bridge seems
++			 * to invert PCIe legacy interrupts).
++			 * We are de-swizzling here because the numbers are actually for
++			 * port of the root complex virtual P2P bridge. But I want
++			 * to avoid putting a node for it in the tree, so the numbers
++			 * below are basically de-swizzled numbers.
++			 * The real slot is on idsel 0, so the swizzling is 1:1
++			 */
++			interrupt-map-mask = <0000 0 0 7>;
++			interrupt-map = <
++				0000 0 0 1 &UIC3 c 4 /* swizzled int A */
++				0000 0 0 2 &UIC3 d 4 /* swizzled int B */
++				0000 0 0 3 &UIC3 e 4 /* swizzled int C */
++				0000 0 0 4 &UIC3 f 4 /* swizzled int D */>;
++		};
++
++		PCIE1: pciex at d20000000 {
++			device_type = "pci";
++			#interrupt-cells = <1>;
++			#size-cells = <2>;
++			#address-cells = <3>;
++			compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++			primary;
++			port = <1>; /* port number */
++			reg = <d 20000000 20000000	/* Config space access */
++			       c 08011000 00001000>;	/* Registers */
++			dcr-reg = <120 020>;
++			sdr-base = <340>;
++
++			/* Outbound ranges, one memory and one IO,
++			 * later cannot be changed
++			 */
++			ranges = <02000000 0 80000000 0000000e 80000000 0 80000000
++				  01000000 0 00000000 0000000f 80010000 0 00010000>;
++
++			/* Inbound 2GB range starting at 0 */
++			dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++			/* This drives busses 80 to 0xbf */
++			bus-range = <80 bf>;
++
++			/* Legacy interrupts (note the weird polarity, the bridge seems
++			 * to invert PCIe legacy interrupts).
++			 * We are de-swizzling here because the numbers are actually for
++			 * port of the root complex virtual P2P bridge. But I want
++			 * to avoid putting a node for it in the tree, so the numbers
++			 * below are basically de-swizzled numbers.
++			 * The real slot is on idsel 0, so the swizzling is 1:1
++			 */
++			interrupt-map-mask = <0000 0 0 7>;
++			interrupt-map = <
++				0000 0 0 1 &UIC3 10 4 /* swizzled int A */
++				0000 0 0 2 &UIC3 11 4 /* swizzled int B */
++				0000 0 0 3 &UIC3 12 4 /* swizzled int C */
++				0000 0 0 4 &UIC3 13 4 /* swizzled int D */>;
++		};
++	};
++};
+diff --git a/arch/powerpc/boot/dts/haleakala.dts b/arch/powerpc/boot/dts/haleakala.dts
+index ae68fef..b5d95ac 100644
+--- a/arch/powerpc/boot/dts/haleakala.dts
++++ b/arch/powerpc/boot/dts/haleakala.dts
+@@ -12,7 +12,7 @@
+ 	#address-cells = <1>;
+ 	#size-cells = <1>;
+ 	model = "amcc,haleakala";
+-	compatible = "amcc,kilauea";
++	compatible = "amcc,haleakala", "amcc,kilauea";
+ 	dcr-parent = <&/cpus/cpu at 0>;
+ 
+ 	aliases {
+@@ -218,7 +218,7 @@
+ 				mal-tx-channel = <0>;
+ 				mal-rx-channel = <0>;
+ 				cell-index = <0>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/katmai.dts b/arch/powerpc/boot/dts/katmai.dts
+index fc86e5a..cc2873a 100644
+--- a/arch/powerpc/boot/dts/katmai.dts
++++ b/arch/powerpc/boot/dts/katmai.dts
+@@ -212,7 +212,7 @@
+ 				mal-tx-channel = <0>;
+ 				mal-rx-channel = <0>;
+ 				cell-index = <0>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "gmii";
+diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts
+index 8baef61..48c9a6e 100644
+--- a/arch/powerpc/boot/dts/kilauea.dts
++++ b/arch/powerpc/boot/dts/kilauea.dts
+@@ -219,7 +219,7 @@
+ 				mal-tx-channel = <0>;
+ 				mal-rx-channel = <0>;
+ 				cell-index = <0>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+@@ -247,7 +247,7 @@
+ 				mal-tx-channel = <1>;
+ 				mal-rx-channel = <1>;
+ 				cell-index = <1>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/ksi8560.dts b/arch/powerpc/boot/dts/ksi8560.dts
+new file mode 100644
+index 0000000..f869ce3
+--- /dev/null
++++ b/arch/powerpc/boot/dts/ksi8560.dts
+@@ -0,0 +1,267 @@
++/*
++ * Device Tree Source for Emerson KSI8560
++ *
++ * Author: Alexandr Smirnov <asmirnov at ru.mvista.com>
++ *
++ * Based on mpc8560ads.dts
++ *
++ * 2008 (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.
++ *
++ */
++
++/dts-v1/;
++
++/ {
++	model = "KSI8560";
++	compatible = "emerson,KSI8560";
++	#address-cells = <1>;
++	#size-cells = <1>;
++
++	aliases {
++		ethernet0 = &enet0;
++		ethernet1 = &enet1;
++		ethernet2 = &enet2;
++	};
++
++	cpus {
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		PowerPC,8560 at 0 {
++			device_type = "cpu";
++			reg = <0>;
++			d-cache-line-size = <32>;
++			i-cache-line-size = <32>;
++			d-cache-size = <0x8000>;		/* L1, 32K */
++			i-cache-size = <0x8000>;		/* L1, 32K */
++			timebase-frequency = <0>;		/* From U-boot */
++			bus-frequency = <0>;			/* From U-boot */
++			clock-frequency = <0>;			/* From U-boot */
++		};
++	};
++
++	memory {
++		device_type = "memory";
++		reg = <0x00000000 0x10000000>;			/* Fixed by bootwrapper */
++	};
++
++	soc at fdf00000 {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		device_type = "soc";
++		ranges = <0x00000000 0xfdf00000 0x00100000>;
++		bus-frequency = <0>;				/* Fixed by bootwrapper */
++
++		memory-controller at 2000 {
++			compatible = "fsl,8540-memory-controller";
++			reg = <0x2000 0x1000>;
++			interrupt-parent = <&MPIC>;
++			interrupts = <0x12 0x2>;
++		};
++
++		l2-cache-controller at 20000 {
++			compatible = "fsl,8540-l2-cache-controller";
++			reg = <0x20000 0x1000>;
++			cache-line-size = <0x20>;		/* 32 bytes */
++			cache-size = <0x40000>;			/* L2, 256K */
++			interrupt-parent = <&MPIC>;
++			interrupts = <0x10 0x2>;
++		};
++
++		i2c at 3000 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			cell-index = <0>;
++			compatible = "fsl-i2c";
++			reg = <0x3000 0x100>;
++			interrupts = <0x2b 0x2>;
++			interrupt-parent = <&MPIC>;
++			dfsrr;
++		};
++
++		mdio at 24520 {					/* For TSECs */
++			#address-cells = <1>;
++			#size-cells = <0>;
++			compatible = "fsl,gianfar-mdio";
++			reg = <0x24520 0x20>;
++
++			PHY1: ethernet-phy at 1 {
++				interrupt-parent = <&MPIC>;
++				reg = <0x1>;
++				device_type = "ethernet-phy";
++			};
++
++			PHY2: ethernet-phy at 2 {
++				interrupt-parent = <&MPIC>;
++				reg = <0x2>;
++				device_type = "ethernet-phy";
++			};
++		};
++
++		enet0: ethernet at 24000 {
++			device_type = "network";
++			model = "TSEC";
++			compatible = "gianfar";
++			reg = <0x24000 0x1000>;
++			/* Mac address filled in by bootwrapper */
++			local-mac-address = [ 00 00 00 00 00 00 ];
++			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
++			interrupt-parent = <&MPIC>;
++			phy-handle = <&PHY1>;
++		};
++
++		enet1: ethernet at 25000 {
++			device_type = "network";
++			model = "TSEC";
++			compatible = "gianfar";
++			reg = <0x25000 0x1000>;
++			/* Mac address filled in by bootwrapper */
++			local-mac-address = [ 00 00 00 00 00 00 ];
++			interrupts = <0x23 0x2 0x24 0x2 0x28 0x2>;
++			interrupt-parent = <&MPIC>;
++			phy-handle = <&PHY2>;
++		};
++
++		MPIC: pic at 40000 {
++			#address-cells = <0>;
++			#interrupt-cells = <2>;
++			interrupt-controller;
++			reg = <0x40000 0x40000>;
++			device_type = "open-pic";
++		};
++
++		cpm at 919c0 {
++			#address-cells = <1>;
++			#size-cells = <1>;
++			compatible = "fsl,mpc8560-cpm", "fsl,cpm2";
++			reg = <0x919c0 0x30>;
++			ranges;
++
++			muram at 80000 {
++				#address-cells = <1>;
++				#size-cells = <1>;
++				ranges = <0x0 0x80000 0x10000>;
++
++				data at 0 {
++					compatible = "fsl,cpm-muram-data";
++					reg = <0x0 0x4000 0x9000 0x2000>;
++				};
++			};
++
++			brg at 919f0 {
++				compatible = "fsl,mpc8560-brg",
++					     "fsl,cpm2-brg",
++					     "fsl,cpm-brg";
++				reg = <0x919f0 0x10 0x915f0 0x10>;
++				clock-frequency = <165000000>;	/* 166MHz */
++			};
++
++			CPMPIC: pic at 90c00 {
++				#address-cells = <0>;
++				#interrupt-cells = <2>;
++				interrupt-controller;
++				interrupts = <0x2e 0x2>;
++				interrupt-parent = <&MPIC>;
++				reg = <0x90c00 0x80>;
++				compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
++			};
++
++			serial at 91a00 {
++				device_type = "serial";
++				compatible = "fsl,mpc8560-scc-uart",
++					     "fsl,cpm2-scc-uart";
++				reg = <0x91a00 0x20 0x88000 0x100>;
++				fsl,cpm-brg = <1>;
++				fsl,cpm-command = <0x800000>;
++				current-speed = <0x1c200>;
++				interrupts = <0x28 0x8>;
++				interrupt-parent = <&CPMPIC>;
++			};
++
++			serial at 91a20 {
++				device_type = "serial";
++				compatible = "fsl,mpc8560-scc-uart",
++					     "fsl,cpm2-scc-uart";
++				reg = <0x91a20 0x20 0x88100 0x100>;
++				fsl,cpm-brg = <2>;
++				fsl,cpm-command = <0x4a00000>;
++				current-speed = <0x1c200>;
++				interrupts = <0x29 0x8>;
++				interrupt-parent = <&CPMPIC>;
++			};
++
++			mdio at 90d00 {				/* For FCCs */
++				#address-cells = <1>;
++				#size-cells = <0>;
++				compatible = "fsl,cpm2-mdio-bitbang";
++				reg = <0x90d00 0x14>;
++				fsl,mdio-pin = <24>;
++				fsl,mdc-pin = <25>;
++
++				PHY0: ethernet-phy at 0 {
++					interrupt-parent = <&MPIC>;
++					reg = <0x0>;
++					device_type = "ethernet-phy";
++				};
++			};
++
++			enet2: ethernet at 91300 {
++				device_type = "network";
++				compatible = "fsl,mpc8560-fcc-enet",
++					     "fsl,cpm2-fcc-enet";
++				reg = <0x91300 0x20 0x88400 0x100 0x91390 0x1>;
++				/* Mac address filled in by bootwrapper */
++				local-mac-address = [ 00 00 00 00 00 00 ];
++				fsl,cpm-command = <0x12000300>;
++				interrupts = <0x20 0x8>;
++				interrupt-parent = <&CPMPIC>;
++				phy-handle = <&PHY0>;
++			};
++		};
++	};
++
++	localbus at fdf05000 {
++		#address-cells = <2>;
++		#size-cells = <1>;
++		compatible = "fsl,mpc8560-localbus";
++		reg = <0xfdf05000 0x68>;
++
++		ranges = <0x0 0x0 0xe0000000 0x00800000
++			  0x4 0x0 0xe8080000 0x00080000>;
++
++		flash at 0,0 {
++			#address-cells = <1>;
++			#size-cells = <1>;
++			compatible = "jedec-flash";
++			reg = <0x0 0x0 0x800000>;
++			bank-width = <0x2>;
++
++			partition at 0 {
++				label = "Primary Kernel";
++				reg = <0x0 0x180000>;
++			};
++			partition at 180000 {
++				label = "Primary Filesystem";
++				reg = <0x180000 0x580000>;
++			};
++			partition at 700000 {
++				label = "Monitor";
++				reg = <0x300000 0x100000>;
++				read-only;
++			};
++		};
++
++		cpld at 4,0 {
++			compatible = "emerson,KSI8560-cpld";
++			reg = <0x4 0x0 0x80000>;
++		};
++	};
++
++
++	chosen {
++		linux,stdout-path = "/soc/cpm/serial at 91a00";
++	};
++};
+diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts
+index 4469588..2e5a1a1 100644
+--- a/arch/powerpc/boot/dts/kuroboxHD.dts
++++ b/arch/powerpc/boot/dts/kuroboxHD.dts
+@@ -7,6 +7,7 @@
+  * Based on sandpoint.dts
+  *
+  * 2006 (c) G. Liakhovetski <g.liakhovetski at gmx.de>
++ * Copyright 2008 Freescale Semiconductor, Inc.
+  *
+  * This file is licensed under
+  * the terms of the GNU General Public License version 2.  This program
+@@ -17,6 +18,8 @@ XXXX add flash parts, rtc, ??
+ 
+  */
+ 
++/dts-v1/;
++
+ / {
+ 	model = "KuroboxHD";
+ 	compatible = "linkstation";
+@@ -35,19 +38,19 @@ XXXX add flash parts, rtc, ??
+ 
+ 		PowerPC,603e { /* Really 8241 */
+ 			device_type = "cpu";
+-			reg = <0>;
+-			clock-frequency = <bebc200>;	/* Fixed by bootloader */
+-			timebase-frequency = <1743000>; /* Fixed by bootloader */
++			reg = <0x0>;
++			clock-frequency = <200000000>;	/* Fixed by bootloader */
++			timebase-frequency = <24391680>; /* Fixed by bootloader */
+ 			bus-frequency = <0>;		/* Fixed by bootloader */
+ 			/* Following required by dtc but not used */
+-			i-cache-size = <4000>;
+-			d-cache-size = <4000>;
++			i-cache-size = <0x4000>;
++			d-cache-size = <0x4000>;
+ 		};
+ 	};
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 04000000>;
++		reg = <0x0 0x4000000>;
+ 	};
+ 
+ 	soc10x { /* AFAICT need to make soc for 8245's uarts to be defined */
+@@ -56,26 +59,26 @@ XXXX add flash parts, rtc, ??
+ 		device_type = "soc";
+ 		compatible = "mpc10x";
+ 		store-gathering = <0>; /* 0 == off, !0 == on */
+-		reg = <80000000 00100000>;
+-		ranges = <80000000 80000000 70000000	/* pci mem space */
+-			  fc000000 fc000000 00100000	/* EUMB */
+-			  fe000000 fe000000 00c00000	/* pci i/o space */
+-			  fec00000 fec00000 00300000	/* pci cfg regs */
+-			  fef00000 fef00000 00100000>;	/* pci iack */
++		reg = <0x80000000 0x100000>;
++		ranges = <0x80000000 0x80000000 0x70000000	/* pci mem space */
++			  0xfc000000 0xfc000000 0x100000	/* EUMB */
++			  0xfe000000 0xfe000000 0xc00000	/* pci i/o space */
++			  0xfec00000 0xfec00000 0x300000	/* pci cfg regs */
++			  0xfef00000 0xfef00000 0x100000>;	/* pci iack */
+ 
+ 		i2c at 80003000 {
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			cell-index = <0>;
+ 			compatible = "fsl-i2c";
+-			reg = <80003000 1000>;
++			reg = <0x80003000 0x1000>;
+ 			interrupts = <5 2>;
+ 			interrupt-parent = <&mpic>;
+ 
+ 			rtc at 32 {
+ 				device_type = "rtc";
+ 				compatible = "ricoh,rs5c372a";
+-				reg = <32>;
++				reg = <0x32>;
+ 			};
+ 		};
+ 
+@@ -83,9 +86,9 @@ XXXX add flash parts, rtc, ??
+ 			cell-index = <0>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <80004500 8>;
+-			clock-frequency = <5d08d88>;
+-			current-speed = <2580>;
++			reg = <0x80004500 0x8>;
++			clock-frequency = <97553800>;
++			current-speed = <9600>;
+ 			interrupts = <9 0>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+@@ -94,10 +97,10 @@ XXXX add flash parts, rtc, ??
+ 			cell-index = <1>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <80004600 8>;
+-			clock-frequency = <5d08d88>;
+-			current-speed = <e100>;
+-			interrupts = <a 0>;
++			reg = <0x80004600 0x8>;
++			clock-frequency = <97553800>;
++			current-speed = <57600>;
++			interrupts = <10 0>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -107,7 +110,7 @@ XXXX add flash parts, rtc, ??
+ 			device_type = "open-pic";
+ 			compatible = "chrp,open-pic";
+ 			interrupt-controller;
+-			reg = <80040000 40000>;
++			reg = <0x80040000 0x40000>;
+ 		};
+ 
+ 		pci0: pci at fec00000 {
+@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ??
+ 			#interrupt-cells = <1>;
+ 			device_type = "pci";
+ 			compatible = "mpc10x-pci";
+-			reg = <fec00000 400000>;
+-			ranges = <01000000 0        0 fe000000 0 00c00000
+-				  02000000 0 80000000 80000000 0 70000000>;
+-			bus-range = <0 ff>;
+-			clock-frequency = <7f28155>;
++			reg = <0xfec00000 0x400000>;
++			ranges = <0x1000000 0x0        0x0 0xfe000000 0x0 0xc00000
++				  0x2000000 0x0 0x80000000 0x80000000 0x0 0x70000000>;
++			bus-range = <0 255>;
++			clock-frequency = <133333333>;
+ 			interrupt-parent = <&mpic>;
+-			interrupt-map-mask = <f800 0 0 7>;
++			interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 			interrupt-map = <
+ 				/* IDSEL 11 - IRQ0 ETH */
+-				5800 0 0 1 &mpic 0 1
+-				5800 0 0 2 &mpic 1 1
+-				5800 0 0 3 &mpic 2 1
+-				5800 0 0 4 &mpic 3 1
++				0x5800 0x0 0x0 0x1 &mpic 0x0 0x1
++				0x5800 0x0 0x0 0x2 &mpic 0x1 0x1
++				0x5800 0x0 0x0 0x3 &mpic 0x2 0x1
++				0x5800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 				/* IDSEL 12 - IRQ1 IDE0 */
+-				6000 0 0 1 &mpic 1 1
+-				6000 0 0 2 &mpic 2 1
+-				6000 0 0 3 &mpic 3 1
+-				6000 0 0 4 &mpic 0 1
++				0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++				0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++				0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++				0x6000 0x0 0x0 0x4 &mpic 0x0 0x1
+ 				/* IDSEL 14 - IRQ3 USB2.0 */
+-				7000 0 0 1 &mpic 3 1
+-				7000 0 0 2 &mpic 3 1
+-				7000 0 0 3 &mpic 3 1
+-				7000 0 0 4 &mpic 3 1
++				0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++				0x7000 0x0 0x0 0x2 &mpic 0x3 0x1
++				0x7000 0x0 0x0 0x3 &mpic 0x3 0x1
++				0x7000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 			>;
+ 		};
+ 	};
+diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts
+index 8443c85..e4916e6 100644
+--- a/arch/powerpc/boot/dts/kuroboxHG.dts
++++ b/arch/powerpc/boot/dts/kuroboxHG.dts
+@@ -7,6 +7,7 @@
+  * Based on sandpoint.dts
+  *
+  * 2006 (c) G. Liakhovetski <g.liakhovetski at gmx.de>
++ * Copyright 2008 Freescale Semiconductor, Inc.
+  *
+  * This file is licensed under
+  * the terms of the GNU General Public License version 2.  This program
+@@ -17,6 +18,8 @@ XXXX add flash parts, rtc, ??
+ 
+  */
+ 
++/dts-v1/;
++
+ / {
+ 	model = "KuroboxHG";
+ 	compatible = "linkstation";
+@@ -35,19 +38,19 @@ XXXX add flash parts, rtc, ??
+ 
+ 		PowerPC,603e { /* Really 8241 */
+ 			device_type = "cpu";
+-			reg = <0>;
+-			clock-frequency = <fdad680>;	/* Fixed by bootloader */
+-			timebase-frequency = <1F04000>; /* Fixed by bootloader */
++			reg = <0x0>;
++			clock-frequency = <266000000>;	/* Fixed by bootloader */
++			timebase-frequency = <32522240>; /* Fixed by bootloader */
+ 			bus-frequency = <0>;		/* Fixed by bootloader */
+ 			/* Following required by dtc but not used */
+-			i-cache-size = <4000>;
+-			d-cache-size = <4000>;
++			i-cache-size = <0x4000>;
++			d-cache-size = <0x4000>;
+ 		};
+ 	};
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 08000000>;
++		reg = <0x0 0x8000000>;
+ 	};
+ 
+ 	soc10x { /* AFAICT need to make soc for 8245's uarts to be defined */
+@@ -56,26 +59,26 @@ XXXX add flash parts, rtc, ??
+ 		device_type = "soc";
+ 		compatible = "mpc10x";
+ 		store-gathering = <0>; /* 0 == off, !0 == on */
+-		reg = <80000000 00100000>;
+-		ranges = <80000000 80000000 70000000	/* pci mem space */
+-			  fc000000 fc000000 00100000	/* EUMB */
+-			  fe000000 fe000000 00c00000	/* pci i/o space */
+-			  fec00000 fec00000 00300000	/* pci cfg regs */
+-			  fef00000 fef00000 00100000>;	/* pci iack */
++		reg = <0x80000000 0x100000>;
++		ranges = <0x80000000 0x80000000 0x70000000	/* pci mem space */
++			  0xfc000000 0xfc000000 0x100000	/* EUMB */
++			  0xfe000000 0xfe000000 0xc00000	/* pci i/o space */
++			  0xfec00000 0xfec00000 0x300000	/* pci cfg regs */
++			  0xfef00000 0xfef00000 0x100000>;	/* pci iack */
+ 
+ 		i2c at 80003000 {
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			cell-index = <0>;
+ 			compatible = "fsl-i2c";
+-			reg = <80003000 1000>;
++			reg = <0x80003000 0x1000>;
+ 			interrupts = <5 2>;
+ 			interrupt-parent = <&mpic>;
+ 
+ 			rtc at 32 {
+ 				device_type = "rtc";
+ 				compatible = "ricoh,rs5c372a";
+-				reg = <32>;
++				reg = <0x32>;
+ 			};
+ 		};
+ 
+@@ -83,9 +86,9 @@ XXXX add flash parts, rtc, ??
+ 			cell-index = <0>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <80004500 8>;
+-			clock-frequency = <7c044a8>;
+-			current-speed = <2580>;
++			reg = <0x80004500 0x8>;
++			clock-frequency = <130041000>;
++			current-speed = <9600>;
+ 			interrupts = <9 0>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+@@ -94,10 +97,10 @@ XXXX add flash parts, rtc, ??
+ 			cell-index = <1>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <80004600 8>;
+-			clock-frequency = <7c044a8>;
+-			current-speed = <e100>;
+-			interrupts = <a 0>;
++			reg = <0x80004600 0x8>;
++			clock-frequency = <130041000>;
++			current-speed = <57600>;
++			interrupts = <10 0>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -107,7 +110,7 @@ XXXX add flash parts, rtc, ??
+ 			device_type = "open-pic";
+ 			compatible = "chrp,open-pic";
+ 			interrupt-controller;
+-			reg = <80040000 40000>;
++			reg = <0x80040000 0x40000>;
+ 		};
+ 
+ 		pci0: pci at fec00000 {
+@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ??
+ 			#interrupt-cells = <1>;
+ 			device_type = "pci";
+ 			compatible = "mpc10x-pci";
+-			reg = <fec00000 400000>;
+-			ranges = <01000000 0        0 fe000000 0 00c00000
+-				  02000000 0 80000000 80000000 0 70000000>;
+-			bus-range = <0 ff>;
+-			clock-frequency = <7f28155>;
++			reg = <0xfec00000 0x400000>;
++			ranges = <0x1000000 0x0        0x0 0xfe000000 0x0 0xc00000
++				  0x2000000 0x0 0x80000000 0x80000000 0x0 0x70000000>;
++			bus-range = <0 255>;
++			clock-frequency = <133333333>;
+ 			interrupt-parent = <&mpic>;
+-			interrupt-map-mask = <f800 0 0 7>;
++			interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 			interrupt-map = <
+ 				/* IDSEL 11 - IRQ0 ETH */
+-				5800 0 0 1 &mpic 0 1
+-				5800 0 0 2 &mpic 1 1
+-				5800 0 0 3 &mpic 2 1
+-				5800 0 0 4 &mpic 3 1
++				0x5800 0x0 0x0 0x1 &mpic 0x0 0x1
++				0x5800 0x0 0x0 0x2 &mpic 0x1 0x1
++				0x5800 0x0 0x0 0x3 &mpic 0x2 0x1
++				0x5800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 				/* IDSEL 12 - IRQ1 IDE0 */
+-				6000 0 0 1 &mpic 1 1
+-				6000 0 0 2 &mpic 2 1
+-				6000 0 0 3 &mpic 3 1
+-				6000 0 0 4 &mpic 0 1
++				0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++				0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++				0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++				0x6000 0x0 0x0 0x4 &mpic 0x0 0x1
+ 				/* IDSEL 14 - IRQ3 USB2.0 */
+-				7000 0 0 1 &mpic 3 1
+-				7000 0 0 2 &mpic 3 1
+-				7000 0 0 3 &mpic 3 1
+-				7000 0 0 4 &mpic 3 1
++				0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++				0x7000 0x0 0x0 0x2 &mpic 0x3 0x1
++				0x7000 0x0 0x0 0x3 &mpic 0x3 0x1
++				0x7000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 			>;
+ 		};
+ 	};
+diff --git a/arch/powerpc/boot/dts/makalu.dts b/arch/powerpc/boot/dts/makalu.dts
+index 710c011..84cc5e7 100644
+--- a/arch/powerpc/boot/dts/makalu.dts
++++ b/arch/powerpc/boot/dts/makalu.dts
+@@ -219,7 +219,7 @@
+ 				mal-tx-channel = <0>;
+ 				mal-rx-channel = <0>;
+ 				cell-index = <0>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+@@ -247,7 +247,7 @@
+ 				mal-tx-channel = <1>;
+ 				mal-rx-channel = <1>;
+ 				cell-index = <1>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
+index 8fb5423..4936349 100644
+--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
++++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC7448HPC2 (Taiga) board Device Tree Source
+  *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+  * 2006 Roy Zang <Roy Zang at freescale.com>.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+@@ -10,6 +10,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ 
+ / {
+ 	model = "mpc7448hpc2";
+@@ -23,11 +24,11 @@
+ 				
+ 		PowerPC,7448 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K bytes
+-			i-cache-size = <8000>;		// L1, 32K bytes
++			reg = <0x0>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K bytes
++			i-cache-size = <0x8000>;		// L1, 32K bytes
+ 			timebase-frequency = <0>;	// 33 MHz, from uboot
+ 			clock-frequency = <0>;		// From U-Boot
+ 			bus-frequency = <0>;		// From U-Boot
+@@ -36,7 +37,7 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 20000000	// DDR2   512M at 0
++		reg = <0x0 0x20000000	// DDR2   512M at 0
+ 		       >;
+ 	};
+ 
+@@ -44,14 +45,14 @@
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "tsi-bridge";
+-		ranges = <00000000 c0000000 00010000>;
+-		reg = <c0000000 00010000>;
++		ranges = <0x0 0xc0000000 0x10000>;
++		reg = <0xc0000000 0x10000>;
+ 		bus-frequency = <0>;
+ 
+ 		i2c at 7000 {
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <E 0>;
+-			reg = <7000 400>;
++			interrupts = <14 0>;
++			reg = <0x7000 0x400>;
+ 			device_type = "i2c";
+ 			compatible  = "tsi108-i2c";
+ 		};
+@@ -59,20 +60,20 @@
+ 		MDIO: mdio at 6000 {
+ 			device_type = "mdio";
+ 			compatible = "tsi108-mdio";
+-			reg = <6000 50>;
++			reg = <0x6000 0x50>;
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 
+ 			phy8: ethernet-phy at 8 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <2 1>;
+-				reg = <8>;
++				reg = <0x8>;
+ 			};
+ 
+ 			phy9: ethernet-phy at 9 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <2 1>;
+-				reg = <9>;
++				reg = <0x9>;
+ 			};
+ 
+ 		};
+@@ -82,9 +83,9 @@
+ 			#size-cells = <0>;
+ 			device_type = "network";
+ 			compatible = "tsi108-ethernet";
+-			reg = <6000 200>;
++			reg = <0x6000 0x200>;
+ 			address = [ 00 06 D2 00 00 01 ];
+-			interrupts = <10 2>;
++			interrupts = <16 2>;
+ 			interrupt-parent = <&mpic>;
+ 			mdio-handle = <&MDIO>;
+ 			phy-handle = <&phy8>;
+@@ -96,9 +97,9 @@
+ 			#size-cells = <0>;
+ 			device_type = "network";
+ 			compatible = "tsi108-ethernet";
+-			reg = <6400 200>;
++			reg = <0x6400 0x200>;
+ 			address = [ 00 06 D2 00 00 02 ];
+-			interrupts = <11 2>;
++			interrupts = <17 2>;
+ 			interrupt-parent = <&mpic>;
+ 			mdio-handle = <&MDIO>;
+ 			phy-handle = <&phy9>;
+@@ -107,18 +108,18 @@
+ 		serial at 7808 {
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <7808 200>;
+-			clock-frequency = <3f6b5a00>;
+-			interrupts = <c 0>;
++			reg = <0x7808 0x200>;
++			clock-frequency = <1064000000>;
++			interrupts = <12 0>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+ 		serial at 7c08 {
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <7c08 200>;
+-			clock-frequency = <3f6b5a00>;
+-			interrupts = <d 0>;
++			reg = <0x7c08 0x200>;
++			clock-frequency = <1064000000>;
++			interrupts = <13 0>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -127,7 +128,7 @@
+ 			interrupt-controller;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+-			reg = <7400 400>;
++			reg = <0x7400 0x400>;
+ 			compatible = "chrp,open-pic";
+ 			device_type = "open-pic";
+                        	big-endian;
+@@ -138,39 +139,39 @@
+ 			#interrupt-cells = <1>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+-			reg = <1000 1000>;
++			reg = <0x1000 0x1000>;
+ 			bus-range = <0 0>;
+-			ranges = <02000000 0 e0000000 e0000000 0 1A000000	
+-				  01000000 0 00000000 fa000000 0 00010000>;
+-			clock-frequency = <7f28154>;
++			ranges = <0x2000000 0x0 0xe0000000 0xe0000000 0x0 0x1a000000	
++				  0x1000000 0x0 0x0 0xfa000000 0x0 0x10000>;
++			clock-frequency = <133333332>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <17 2>;
+-			interrupt-map-mask = <f800 0 0 7>;
++			interrupts = <23 2>;
++			interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 			interrupt-map = <
+ 
+ 				/* IDSEL 0x11 */
+-				0800 0 0 1 &RT0 24 0
+-				0800 0 0 2 &RT0 25 0
+-				0800 0 0 3 &RT0 26 0
+-				0800 0 0 4 &RT0 27 0
++				0x800 0x0 0x0 0x1 &RT0 0x24 0x0
++				0x800 0x0 0x0 0x2 &RT0 0x25 0x0
++				0x800 0x0 0x0 0x3 &RT0 0x26 0x0
++				0x800 0x0 0x0 0x4 &RT0 0x27 0x0
+ 
+ 				/* IDSEL 0x12 */
+-				1000 0 0 1 &RT0 25 0
+-				1000 0 0 2 &RT0 26 0
+-				1000 0 0 3 &RT0 27 0
+-				1000 0 0 4 &RT0 24 0
++				0x1000 0x0 0x0 0x1 &RT0 0x25 0x0
++				0x1000 0x0 0x0 0x2 &RT0 0x26 0x0
++				0x1000 0x0 0x0 0x3 &RT0 0x27 0x0
++				0x1000 0x0 0x0 0x4 &RT0 0x24 0x0
+ 
+ 				/* IDSEL 0x13 */
+-				1800 0 0 1 &RT0 26 0
+-				1800 0 0 2 &RT0 27 0
+-				1800 0 0 3 &RT0 24 0
+-				1800 0 0 4 &RT0 25 0
++				0x1800 0x0 0x0 0x1 &RT0 0x26 0x0
++				0x1800 0x0 0x0 0x2 &RT0 0x27 0x0
++				0x1800 0x0 0x0 0x3 &RT0 0x24 0x0
++				0x1800 0x0 0x0 0x4 &RT0 0x25 0x0
+ 
+ 				/* IDSEL 0x14 */
+-				2000 0 0 1 &RT0 27 0
+-				2000 0 0 2 &RT0 24 0
+-				2000 0 0 3 &RT0 25 0
+-				2000 0 0 4 &RT0 26 0
++				0x2000 0x0 0x0 0x1 &RT0 0x27 0x0
++				0x2000 0x0 0x0 0x2 &RT0 0x24 0x0
++				0x2000 0x0 0x0 0x3 &RT0 0x25 0x0
++				0x2000 0x0 0x0 0x4 &RT0 0x26 0x0
+ 				>;
+ 
+ 			RT0: router at 1180 {
+@@ -180,7 +181,7 @@
+ 				#address-cells = <0>;
+ 				#interrupt-cells = <2>;
+ 				big-endian;
+-				interrupts = <17 2>;
++				interrupts = <23 2>;
+ 				interrupt-parent = <&mpic>;
+ 			};
+ 		};
+diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
+index 7285ca1..46e2da3 100644
+--- a/arch/powerpc/boot/dts/mpc8272ads.dts
++++ b/arch/powerpc/boot/dts/mpc8272ads.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC8272 ADS Device Tree Source
+  *
+- * Copyright 2005 Freescale Semiconductor Inc.
++ * Copyright 2005,2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +9,8 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
++
+ / {
+ 	model = "MPC8272ADS";
+ 	compatible = "fsl,mpc8272ads";
+@@ -21,11 +23,11 @@
+ 
+ 		PowerPC,8272 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <d#32>;
+-			i-cache-line-size = <d#32>;
+-			d-cache-size = <d#16384>;
+-			i-cache-size = <d#16384>;
++			reg = <0x0>;
++			d-cache-line-size = <32>;
++			i-cache-line-size = <32>;
++			d-cache-size = <16384>;
++			i-cache-size = <16384>;
+ 			timebase-frequency = <0>;
+ 			bus-frequency = <0>;
+ 			clock-frequency = <0>;
+@@ -34,7 +36,7 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <0 0>;
++		reg = <0x0 0x0>;
+ 	};
+ 
+ 	localbus at f0010100 {
+@@ -42,21 +44,21 @@
+ 		             "fsl,pq2-localbus";
+ 		#address-cells = <2>;
+ 		#size-cells = <1>;
+-		reg = <f0010100 40>;
++		reg = <0xf0010100 0x40>;
+ 
+-		ranges = <0 0 fe000000 02000000
+-		          1 0 f4500000 00008000
+-		          3 0 f8200000 00008000>;
++		ranges = <0x0 0x0 0xfe000000 0x2000000
++		          0x1 0x0 0xf4500000 0x8000
++		          0x3 0x0 0xf8200000 0x8000>;
+ 
+ 		flash at 0,0 {
+ 			compatible = "jedec-flash";
+-			reg = <0 0 2000000>;
++			reg = <0x0 0x0 0x2000000>;
+ 			bank-width = <4>;
+ 			device-width = <1>;
+ 		};
+ 
+ 		board-control at 1,0 {
+-			reg = <1 0 20>;
++			reg = <0x1 0x0 0x20>;
+ 			compatible = "fsl,mpc8272ads-bcsr";
+ 		};
+ 
+@@ -65,46 +67,46 @@
+ 			             "fsl,pq2ads-pci-pic";
+ 			#interrupt-cells = <1>;
+ 			interrupt-controller;
+-			reg = <3 0 8>;
++			reg = <0x3 0x0 0x8>;
+ 			interrupt-parent = <&PIC>;
+-			interrupts = <14 8>;
++			interrupts = <20 8>;
+ 		};
+ 	};
+ 
+ 
+ 	pci at f0010800 {
+ 		device_type = "pci";
+-		reg = <f0010800 10c f00101ac 8 f00101c4 8>;
++		reg = <0xf0010800 0x10c 0xf00101ac 0x8 0xf00101c4 0x8>;
+ 		compatible = "fsl,mpc8272-pci", "fsl,pq2-pci";
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		clock-frequency = <d#66666666>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		clock-frequency = <66666666>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 		                 /* IDSEL 0x16 */
+-		                 b000 0 0 1 &PCI_PIC 0
+-		                 b000 0 0 2 &PCI_PIC 1
+-		                 b000 0 0 3 &PCI_PIC 2
+-		                 b000 0 0 4 &PCI_PIC 3
++		                 0xb000 0x0 0x0 0x1 &PCI_PIC 0
++		                 0xb000 0x0 0x0 0x2 &PCI_PIC 1
++		                 0xb000 0x0 0x0 0x3 &PCI_PIC 2
++		                 0xb000 0x0 0x0 0x4 &PCI_PIC 3
+ 
+ 		                 /* IDSEL 0x17 */
+-		                 b800 0 0 1 &PCI_PIC 4
+-		                 b800 0 0 2 &PCI_PIC 5
+-		                 b800 0 0 3 &PCI_PIC 6
+-		                 b800 0 0 4 &PCI_PIC 7
++		                 0xb800 0x0 0x0 0x1 &PCI_PIC 4
++		                 0xb800 0x0 0x0 0x2 &PCI_PIC 5
++		                 0xb800 0x0 0x0 0x3 &PCI_PIC 6
++		                 0xb800 0x0 0x0 0x4 &PCI_PIC 7
+ 
+ 		                 /* IDSEL 0x18 */
+-		                 c000 0 0 1 &PCI_PIC 8
+-		                 c000 0 0 2 &PCI_PIC 9
+-		                 c000 0 0 3 &PCI_PIC a
+-		                 c000 0 0 4 &PCI_PIC b>;
++		                 0xc000 0x0 0x0 0x1 &PCI_PIC 8
++		                 0xc000 0x0 0x0 0x2 &PCI_PIC 9
++		                 0xc000 0x0 0x0 0x3 &PCI_PIC 10
++		                 0xc000 0x0 0x0 0x4 &PCI_PIC 11>;
+ 
+ 		interrupt-parent = <&PIC>;
+-		interrupts = <12 8>;
+-		ranges = <42000000 0 80000000 80000000 0 20000000
+-		          02000000 0 a0000000 a0000000 0 20000000
+-		          01000000 0 00000000 f6000000 0 02000000>;
++		interrupts = <18 8>;
++		ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++		          0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++		          0x1000000 0x0 0x0 0xf6000000 0x0 0x2000000>;
+ 	};
+ 
+ 	soc at f0000000 {
+@@ -112,26 +114,26 @@
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+ 		compatible = "fsl,mpc8272", "fsl,pq2-soc";
+-		ranges = <00000000 f0000000 00053000>;
++		ranges = <0x0 0xf0000000 0x53000>;
+ 
+ 		// Temporary -- will go away once kernel uses ranges for get_immrbase().
+-		reg = <f0000000 00053000>;
++		reg = <0xf0000000 0x53000>;
+ 
+ 		cpm at 119c0 {
+ 			#address-cells = <1>;
+ 			#size-cells = <1>;
+ 			compatible = "fsl,mpc8272-cpm", "fsl,cpm2";
+-			reg = <119c0 30>;
++			reg = <0x119c0 0x30>;
+ 			ranges;
+ 
+ 			muram at 0 {
+ 				#address-cells = <1>;
+ 				#size-cells = <1>;
+-				ranges = <0 0 10000>;
++				ranges = <0x0 0x0 0x10000>;
+ 
+ 				data at 0 {
+ 					compatible = "fsl,cpm-muram-data";
+-					reg = <0 2000 9800 800>;
++					reg = <0x0 0x2000 0x9800 0x800>;
+ 				};
+ 			};
+ 
+@@ -139,29 +141,29 @@
+ 				compatible = "fsl,mpc8272-brg",
+ 				             "fsl,cpm2-brg",
+ 				             "fsl,cpm-brg";
+-				reg = <119f0 10 115f0 10>;
++				reg = <0x119f0 0x10 0x115f0 0x10>;
+ 			};
+ 
+ 			serial at 11a00 {
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc8272-scc-uart",
+ 				             "fsl,cpm2-scc-uart";
+-				reg = <11a00 20 8000 100>;
+-				interrupts = <28 8>;
++				reg = <0x11a00 0x20 0x8000 0x100>;
++				interrupts = <40 8>;
+ 				interrupt-parent = <&PIC>;
+ 				fsl,cpm-brg = <1>;
+-				fsl,cpm-command = <00800000>;
++				fsl,cpm-command = <0x800000>;
+ 			};
+ 
+ 			serial at 11a60 {
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc8272-scc-uart",
+ 				             "fsl,cpm2-scc-uart";
+-				reg = <11a60 20 8300 100>;
+-				interrupts = <2b 8>;
++				reg = <0x11a60 0x20 0x8300 0x100>;
++				interrupts = <43 8>;
+ 				interrupt-parent = <&PIC>;
+ 				fsl,cpm-brg = <4>;
+-				fsl,cpm-command = <0ce00000>;
++				fsl,cpm-command = <0xce00000>;
+ 			};
+ 
+ 			mdio at 10d40 {
+@@ -169,23 +171,23 @@
+ 				compatible = "fsl,mpc8272ads-mdio-bitbang",
+ 				             "fsl,mpc8272-mdio-bitbang",
+ 				             "fsl,cpm2-mdio-bitbang";
+-				reg = <10d40 14>;
++				reg = <0x10d40 0x14>;
+ 				#address-cells = <1>;
+ 				#size-cells = <0>;
+-				fsl,mdio-pin = <12>;
+-				fsl,mdc-pin = <13>;
++				fsl,mdio-pin = <18>;
++				fsl,mdc-pin = <19>;
+ 
+ 				PHY0: ethernet-phy at 0 {
+ 					interrupt-parent = <&PIC>;
+-					interrupts = <17 8>;
+-					reg = <0>;
++					interrupts = <23 8>;
++					reg = <0x0>;
+ 					device_type = "ethernet-phy";
+ 				};
+ 
+ 				PHY1: ethernet-phy at 1 {
+ 					interrupt-parent = <&PIC>;
+-					interrupts = <17 8>;
+-					reg = <3>;
++					interrupts = <23 8>;
++					reg = <0x3>;
+ 					device_type = "ethernet-phy";
+ 				};
+ 			};
+@@ -194,33 +196,33 @@
+ 				device_type = "network";
+ 				compatible = "fsl,mpc8272-fcc-enet",
+ 				             "fsl,cpm2-fcc-enet";
+-				reg = <11300 20 8400 100 11390 1>;
++				reg = <0x11300 0x20 0x8400 0x100 0x11390 0x1>;
+ 				local-mac-address = [ 00 00 00 00 00 00 ];
+-				interrupts = <20 8>;
++				interrupts = <32 8>;
+ 				interrupt-parent = <&PIC>;
+ 				phy-handle = <&PHY0>;
+ 				linux,network-index = <0>;
+-				fsl,cpm-command = <12000300>;
++				fsl,cpm-command = <0x12000300>;
+ 			};
+ 
+ 			ethernet at 11320 {
+ 				device_type = "network";
+ 				compatible = "fsl,mpc8272-fcc-enet",
+ 				             "fsl,cpm2-fcc-enet";
+-				reg = <11320 20 8500 100 113b0 1>;
++				reg = <0x11320 0x20 0x8500 0x100 0x113b0 0x1>;
+ 				local-mac-address = [ 00 00 00 00 00 00 ];
+-				interrupts = <21 8>;
++				interrupts = <33 8>;
+ 				interrupt-parent = <&PIC>;
+ 				phy-handle = <&PHY1>;
+ 				linux,network-index = <1>;
+-				fsl,cpm-command = <16200300>;
++				fsl,cpm-command = <0x16200300>;
+ 			};
+ 		};
+ 
+ 		PIC: interrupt-controller at 10c00 {
+ 			#interrupt-cells = <2>;
+ 			interrupt-controller;
+-			reg = <10c00 80>;
++			reg = <0x10c00 0x80>;
+ 			compatible = "fsl,mpc8272-pic", "fsl,cpm2-pic";
+ 		};
+ 
+@@ -232,14 +234,14 @@
+ 			             "fsl,talitos-sec2",
+ 			             "fsl,talitos",
+ 			             "talitos";
+-			reg = <30000 10000>;
+-			interrupts = <b 8>;
++			reg = <0x30000 0x10000>;
++			interrupts = <11 8>;
+ 			interrupt-parent = <&PIC>;
+ 			num-channels = <4>;
+-			channel-fifo-len = <18>;
+-			exec-units-mask = <0000007e>;
++			channel-fifo-len = <24>;
++			exec-units-mask = <0x7e>;
+ /* desc mask is for rev1.x, we need runtime fixup for >=2.x */
+-			descriptor-types-mask = <01010ebf>;
++			descriptor-types-mask = <0x1010ebf>;
+ 		};
+ 	};
+ 
+diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
+index 9bb4083..539e02f 100644
+--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
++++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
+@@ -255,9 +255,7 @@
+ 		enet0: ucc at 2200 {
+ 			device_type = "network";
+ 			compatible = "ucc_geth";
+-			model = "UCC";
+ 			cell-index = <3>;
+-			device-id = <3>;
+ 			reg = <0x2200 0x200>;
+ 			interrupts = <34>;
+ 			interrupt-parent = <&qeic>;
+@@ -271,9 +269,7 @@
+ 		enet1: ucc at 3200 {
+ 			device_type = "network";
+ 			compatible = "ucc_geth";
+-			model = "UCC";
+ 			cell-index = <4>;
+-			device-id = <4>;
+ 			reg = <0x3200 0x200>;
+ 			interrupts = <35>;
+ 			interrupt-parent = <&qeic>;
+@@ -287,8 +283,7 @@
+ 		ucc at 2400 {
+ 			device_type = "serial";
+ 			compatible = "ucc_uart";
+-			model = "UCC";
+-			device-id = <5>;	/* The UCC number, 1-7*/
++			cell-index = <5>;	/* The UCC number, 1-7*/
+ 			port-number = <0>;	/* Which ttyQEx device */
+ 			soft-uart;		/* We need Soft-UART */
+ 			reg = <0x2400 0x200>;
+diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
+index 94f93d2..179c81c 100644
+--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
++++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
+@@ -208,9 +208,7 @@
+ 		enet0: ucc at 3000 {
+ 			device_type = "network";
+ 			compatible = "ucc_geth";
+-			model = "UCC";
+ 			cell-index = <2>;
+-			device-id = <2>;
+ 			reg = <0x3000 0x200>;
+ 			interrupts = <33>;
+ 			interrupt-parent = <&qeic>;
+@@ -224,9 +222,7 @@
+ 		enet1: ucc at 2200 {
+ 			device_type = "network";
+ 			compatible = "ucc_geth";
+-			model = "UCC";
+ 			cell-index = <3>;
+-			device-id = <3>;
+ 			reg = <0x2200 0x200>;
+ 			interrupts = <34>;
+ 			interrupt-parent = <&qeic>;
+diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
+index 55f03e8..8160ff2 100644
+--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
++++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
+@@ -257,9 +257,7 @@
+ 		enet0: ucc at 2000 {
+ 			device_type = "network";
+ 			compatible = "ucc_geth";
+-			model = "UCC";
+ 			cell-index = <1>;
+-			device-id = <1>;
+ 			reg = <0x2000 0x200>;
+ 			interrupts = <32>;
+ 			interrupt-parent = <&qeic>;
+@@ -274,9 +272,7 @@
+ 		enet1: ucc at 3000 {
+ 			device_type = "network";
+ 			compatible = "ucc_geth";
+-			model = "UCC";
+ 			cell-index = <2>;
+-			device-id = <2>;
+ 			reg = <0x3000 0x200>;
+ 			interrupts = <33>;
+ 			interrupt-parent = <&qeic>;
+diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
+index 9752484..18033ed 100644
+--- a/arch/powerpc/boot/dts/mpc8540ads.dts
++++ b/arch/powerpc/boot/dts/mpc8540ads.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC8540 ADS Device Tree Source
+  *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +9,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ 
+ / {
+ 	model = "MPC8540ADS";
+@@ -31,11 +32,11 @@
+ 
+ 		PowerPC,8540 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K
+-			i-cache-size = <8000>;		// L1, 32K
++			reg = <0x0>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K
++			i-cache-size = <0x8000>;		// L1, 32K
+ 			timebase-frequency = <0>;	//  33 MHz, from uboot
+ 			bus-frequency = <0>;	// 166 MHz
+ 			clock-frequency = <0>;	// 825 MHz, from uboot
+@@ -44,31 +45,31 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 08000000>;	// 128M at 0x0
++		reg = <0x0 0x8000000>;	// 128M at 0x0
+ 	};
+ 
+ 	soc8540 at e0000000 {
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <0 e0000000 00100000>;
+-		reg = <e0000000 00100000>;	// CCSRBAR 1M
++		ranges = <0x0 0xe0000000 0x100000>;
++		reg = <0xe0000000 0x100000>;	// CCSRBAR 1M
+ 		bus-frequency = <0>;
+ 
+ 		memory-controller at 2000 {
+ 			compatible = "fsl,8540-memory-controller";
+-			reg = <2000 1000>;
++			reg = <0x2000 0x1000>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <12 2>;
++			interrupts = <18 2>;
+ 		};
+ 
+ 		l2-cache-controller at 20000 {
+ 			compatible = "fsl,8540-l2-cache-controller";
+-			reg = <20000 1000>;
+-			cache-line-size = <20>;	// 32 bytes
+-			cache-size = <40000>;	// L2, 256K
++			reg = <0x20000 0x1000>;
++			cache-line-size = <32>;	// 32 bytes
++			cache-size = <0x40000>;	// L2, 256K
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <10 2>;
++			interrupts = <16 2>;
+ 		};
+ 
+ 		i2c at 3000 {
+@@ -76,8 +77,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <0>;
+ 			compatible = "fsl-i2c";
+-			reg = <3000 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3000 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -86,24 +87,24 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			compatible = "fsl,gianfar-mdio";
+-			reg = <24520 20>;
++			reg = <0x24520 0x20>;
+ 
+ 			phy0: ethernet-phy at 0 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <0>;
++				reg = <0x0>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy1: ethernet-phy at 1 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy3: ethernet-phy at 3 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <7 1>;
+-				reg = <3>;
++				reg = <0x3>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -113,9 +114,9 @@
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <24000 1000>;
++			reg = <0x24000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1d 2 1e 2 22 2>;
++			interrupts = <29 2 30 2 34 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy0>;
+ 		};
+@@ -125,9 +126,9 @@
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <25000 1000>;
++			reg = <0x25000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <23 2 24 2 28 2>;
++			interrupts = <35 2 36 2 40 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy1>;
+ 		};
+@@ -137,9 +138,9 @@
+ 			device_type = "network";
+ 			model = "FEC";
+ 			compatible = "gianfar";
+-			reg = <26000 1000>;
++			reg = <0x26000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <29 2>;
++			interrupts = <41 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy3>;
+ 		};
+@@ -148,9 +149,9 @@
+ 			cell-index = <0>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4500 100>; 	// reg base, size
++			reg = <0x4500 0x100>; 	// reg base, size
+ 			clock-frequency = <0>; 	// should we fill in in uboot?
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -158,9 +159,9 @@
+ 			cell-index = <1>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4600 100>;	// reg base, size
++			reg = <0x4600 0x100>;	// reg base, size
+ 			clock-frequency = <0>; 	// should we fill in in uboot?
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 		mpic: pic at 40000 {
+@@ -168,7 +169,7 @@
+ 			interrupt-controller;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+-			reg = <40000 40000>;
++			reg = <0x40000 0x40000>;
+ 			compatible = "chrp,open-pic";
+ 			device_type = "open-pic";
+ 			big-endian;
+@@ -177,90 +178,90 @@
+ 
+ 	pci0: pci at e0008000 {
+ 		cell-index = <0>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 			/* IDSEL 0x02 */
+-			1000 0 0 1 &mpic 1 1
+-			1000 0 0 2 &mpic 2 1
+-			1000 0 0 3 &mpic 3 1
+-			1000 0 0 4 &mpic 4 1
++			0x1000 0x0 0x0 0x1 &mpic 0x1 0x1
++			0x1000 0x0 0x0 0x2 &mpic 0x2 0x1
++			0x1000 0x0 0x0 0x3 &mpic 0x3 0x1
++			0x1000 0x0 0x0 0x4 &mpic 0x4 0x1
+ 
+ 			/* IDSEL 0x03 */
+-			1800 0 0 1 &mpic 4 1
+-			1800 0 0 2 &mpic 1 1
+-			1800 0 0 3 &mpic 2 1
+-			1800 0 0 4 &mpic 3 1
++			0x1800 0x0 0x0 0x1 &mpic 0x4 0x1
++			0x1800 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x1800 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x1800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x04 */
+-			2000 0 0 1 &mpic 3 1
+-			2000 0 0 2 &mpic 4 1
+-			2000 0 0 3 &mpic 1 1
+-			2000 0 0 4 &mpic 2 1
++			0x2000 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x2000 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x2000 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x2000 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x05 */
+-			2800 0 0 1 &mpic 2 1
+-			2800 0 0 2 &mpic 3 1
+-			2800 0 0 3 &mpic 4 1
+-			2800 0 0 4 &mpic 1 1
++			0x2800 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x2800 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x2800 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x2800 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x0c */
+-			6000 0 0 1 &mpic 1 1
+-			6000 0 0 2 &mpic 2 1
+-			6000 0 0 3 &mpic 3 1
+-			6000 0 0 4 &mpic 4 1
++			0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++			0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++			0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++			0x6000 0x0 0x0 0x4 &mpic 0x4 0x1
+ 
+ 			/* IDSEL 0x0d */
+-			6800 0 0 1 &mpic 4 1
+-			6800 0 0 2 &mpic 1 1
+-			6800 0 0 3 &mpic 2 1
+-			6800 0 0 4 &mpic 3 1
++			0x6800 0x0 0x0 0x1 &mpic 0x4 0x1
++			0x6800 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x6800 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x6800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x0e */
+-			7000 0 0 1 &mpic 3 1
+-			7000 0 0 2 &mpic 4 1
+-			7000 0 0 3 &mpic 1 1
+-			7000 0 0 4 &mpic 2 1
++			0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x7000 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x7000 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x7000 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x0f */
+-			7800 0 0 1 &mpic 2 1
+-			7800 0 0 2 &mpic 3 1
+-			7800 0 0 3 &mpic 4 1
+-			7800 0 0 4 &mpic 1 1
++			0x7800 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x7800 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x7800 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x7800 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x12 */
+-			9000 0 0 1 &mpic 1 1
+-			9000 0 0 2 &mpic 2 1
+-			9000 0 0 3 &mpic 3 1
+-			9000 0 0 4 &mpic 4 1
++			0x9000 0x0 0x0 0x1 &mpic 0x1 0x1
++			0x9000 0x0 0x0 0x2 &mpic 0x2 0x1
++			0x9000 0x0 0x0 0x3 &mpic 0x3 0x1
++			0x9000 0x0 0x0 0x4 &mpic 0x4 0x1
+ 
+ 			/* IDSEL 0x13 */
+-			9800 0 0 1 &mpic 4 1
+-			9800 0 0 2 &mpic 1 1
+-			9800 0 0 3 &mpic 2 1
+-			9800 0 0 4 &mpic 3 1
++			0x9800 0x0 0x0 0x1 &mpic 0x4 0x1
++			0x9800 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x9800 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x9800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x14 */
+-			a000 0 0 1 &mpic 3 1
+-			a000 0 0 2 &mpic 4 1
+-			a000 0 0 3 &mpic 1 1
+-			a000 0 0 4 &mpic 2 1
++			0xa000 0x0 0x0 0x1 &mpic 0x3 0x1
++			0xa000 0x0 0x0 0x2 &mpic 0x4 0x1
++			0xa000 0x0 0x0 0x3 &mpic 0x1 0x1
++			0xa000 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x15 */
+-			a800 0 0 1 &mpic 2 1
+-			a800 0 0 2 &mpic 3 1
+-			a800 0 0 3 &mpic 4 1
+-			a800 0 0 4 &mpic 1 1>;
++			0xa800 0x0 0x0 0x1 &mpic 0x2 0x1
++			0xa800 0x0 0x0 0x2 &mpic 0x3 0x1
++			0xa800 0x0 0x0 0x3 &mpic 0x4 0x1
++			0xa800 0x0 0x0 0x4 &mpic 0x1 0x1>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <18 2>;
++		interrupts = <24 2>;
+ 		bus-range = <0 0>;
+-		ranges = <02000000 0 80000000 80000000 0 20000000
+-			  01000000 0 00000000 e2000000 0 00100000>;
+-		clock-frequency = <3f940aa>;
++		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
++		clock-frequency = <66666666>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0008000 1000>;
++		reg = <0xe0008000 0x1000>;
+ 		compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+ 		device_type = "pci";
+ 	};
+diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
+index fa8d9aa..663c7c5 100644
+--- a/arch/powerpc/boot/dts/mpc8541cds.dts
++++ b/arch/powerpc/boot/dts/mpc8541cds.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC8541 CDS Device Tree Source
+  *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +9,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ 
+ / {
+ 	model = "MPC8541CDS";
+@@ -31,11 +32,11 @@
+ 
+ 		PowerPC,8541 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K
+-			i-cache-size = <8000>;		// L1, 32K
++			reg = <0x0>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K
++			i-cache-size = <0x8000>;		// L1, 32K
+ 			timebase-frequency = <0>;	//  33 MHz, from uboot
+ 			bus-frequency = <0>;	// 166 MHz
+ 			clock-frequency = <0>;	// 825 MHz, from uboot
+@@ -44,31 +45,31 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 08000000>;	// 128M at 0x0
++		reg = <0x0 0x8000000>;	// 128M at 0x0
+ 	};
+ 
+ 	soc8541 at e0000000 {
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <0 e0000000 00100000>;
+-		reg = <e0000000 00001000>;	// CCSRBAR 1M
++		ranges = <0x0 0xe0000000 0x100000>;
++		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
+ 		bus-frequency = <0>;
+ 
+ 		memory-controller at 2000 {
+ 			compatible = "fsl,8541-memory-controller";
+-			reg = <2000 1000>;
++			reg = <0x2000 0x1000>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <12 2>;
++			interrupts = <18 2>;
+ 		};
+ 
+ 		l2-cache-controller at 20000 {
+ 			compatible = "fsl,8541-l2-cache-controller";
+-			reg = <20000 1000>;
+-			cache-line-size = <20>;	// 32 bytes
+-			cache-size = <40000>;	// L2, 256K
++			reg = <0x20000 0x1000>;
++			cache-line-size = <32>;	// 32 bytes
++			cache-size = <0x40000>;	// L2, 256K
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <10 2>;
++			interrupts = <16 2>;
+ 		};
+ 
+ 		i2c at 3000 {
+@@ -76,8 +77,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <0>;
+ 			compatible = "fsl-i2c";
+-			reg = <3000 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3000 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -86,18 +87,18 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			compatible = "fsl,gianfar-mdio";
+-			reg = <24520 20>;
++			reg = <0x24520 0x20>;
+ 
+ 			phy0: ethernet-phy at 0 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <0>;
++				reg = <0x0>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy1: ethernet-phy at 1 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -107,9 +108,9 @@
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <24000 1000>;
++			reg = <0x24000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1d 2 1e 2 22 2>;
++			interrupts = <29 2 30 2 34 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy0>;
+ 		};
+@@ -119,9 +120,9 @@
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <25000 1000>;
++			reg = <0x25000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <23 2 24 2 28 2>;
++			interrupts = <35 2 36 2 40 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy1>;
+ 		};
+@@ -130,9 +131,9 @@
+ 			cell-index = <0>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4500 100>; 	// reg base, size
++			reg = <0x4500 0x100>; 	// reg base, size
+ 			clock-frequency = <0>; 	// should we fill in in uboot?
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -140,9 +141,9 @@
+ 			cell-index = <1>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4600 100>;	// reg base, size
++			reg = <0x4600 0x100>;	// reg base, size
+ 			clock-frequency = <0>; 	// should we fill in in uboot?
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -151,7 +152,7 @@
+ 			interrupt-controller;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+-			reg = <40000 40000>;
++			reg = <0x40000 0x40000>;
+ 			compatible = "chrp,open-pic";
+ 			device_type = "open-pic";
+                         big-endian;
+@@ -161,17 +162,17 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <1>;
+ 			compatible = "fsl,mpc8541-cpm", "fsl,cpm2";
+-			reg = <919c0 30>;
++			reg = <0x919c0 0x30>;
+ 			ranges;
+ 
+ 			muram at 80000 {
+ 				#address-cells = <1>;
+ 				#size-cells = <1>;
+-				ranges = <0 80000 10000>;
++				ranges = <0x0 0x80000 0x10000>;
+ 
+ 				data at 0 {
+ 					compatible = "fsl,cpm-muram-data";
+-					reg = <0 2000 9000 1000>;
++					reg = <0x0 0x2000 0x9000 0x1000>;
+ 				};
+ 			};
+ 
+@@ -179,16 +180,16 @@
+ 				compatible = "fsl,mpc8541-brg",
+ 				             "fsl,cpm2-brg",
+ 				             "fsl,cpm-brg";
+-				reg = <919f0 10 915f0 10>;
++				reg = <0x919f0 0x10 0x915f0 0x10>;
+ 			};
+ 
+ 			cpmpic: pic at 90c00 {
+ 				interrupt-controller;
+ 				#address-cells = <0>;
+ 				#interrupt-cells = <2>;
+-				interrupts = <2e 2>;
++				interrupts = <46 2>;
+ 				interrupt-parent = <&mpic>;
+-				reg = <90c00 80>;
++				reg = <0x90c00 0x80>;
+ 				compatible = "fsl,mpc8541-cpm-pic", "fsl,cpm2-pic";
+ 			};
+ 		};
+@@ -196,68 +197,68 @@
+ 
+ 	pci0: pci at e0008000 {
+ 		cell-index = <0>;
+-		interrupt-map-mask = <1f800 0 0 7>;
++		interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 			/* IDSEL 0x10 */
+-			08000 0 0 1 &mpic 0 1
+-			08000 0 0 2 &mpic 1 1
+-			08000 0 0 3 &mpic 2 1
+-			08000 0 0 4 &mpic 3 1
++			0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x11 */
+-			08800 0 0 1 &mpic 0 1
+-			08800 0 0 2 &mpic 1 1
+-			08800 0 0 3 &mpic 2 1
+-			08800 0 0 4 &mpic 3 1
++			0x8800 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x8800 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x8800 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x8800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x12 (Slot 1) */
+-			09000 0 0 1 &mpic 0 1
+-			09000 0 0 2 &mpic 1 1
+-			09000 0 0 3 &mpic 2 1
+-			09000 0 0 4 &mpic 3 1
++			0x9000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x9000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x9000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x13 (Slot 2) */
+-			09800 0 0 1 &mpic 1 1
+-			09800 0 0 2 &mpic 2 1
+-			09800 0 0 3 &mpic 3 1
+-			09800 0 0 4 &mpic 0 1
++			0x9800 0x0 0x0 0x1 &mpic 0x1 0x1
++			0x9800 0x0 0x0 0x2 &mpic 0x2 0x1
++			0x9800 0x0 0x0 0x3 &mpic 0x3 0x1
++			0x9800 0x0 0x0 0x4 &mpic 0x0 0x1
+ 
+ 			/* IDSEL 0x14 (Slot 3) */
+-			0a000 0 0 1 &mpic 2 1
+-			0a000 0 0 2 &mpic 3 1
+-			0a000 0 0 3 &mpic 0 1
+-			0a000 0 0 4 &mpic 1 1
++			0xa000 0x0 0x0 0x1 &mpic 0x2 0x1
++			0xa000 0x0 0x0 0x2 &mpic 0x3 0x1
++			0xa000 0x0 0x0 0x3 &mpic 0x0 0x1
++			0xa000 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x15 (Slot 4) */
+-			0a800 0 0 1 &mpic 3 1
+-			0a800 0 0 2 &mpic 0 1
+-			0a800 0 0 3 &mpic 1 1
+-			0a800 0 0 4 &mpic 2 1
++			0xa800 0x0 0x0 0x1 &mpic 0x3 0x1
++			0xa800 0x0 0x0 0x2 &mpic 0x0 0x1
++			0xa800 0x0 0x0 0x3 &mpic 0x1 0x1
++			0xa800 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* Bus 1 (Tundra Bridge) */
+ 			/* IDSEL 0x12 (ISA bridge) */
+-			19000 0 0 1 &mpic 0 1
+-			19000 0 0 2 &mpic 1 1
+-			19000 0 0 3 &mpic 2 1
+-			19000 0 0 4 &mpic 3 1>;
++			0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <18 2>;
++		interrupts = <24 2>;
+ 		bus-range = <0 0>;
+-		ranges = <02000000 0 80000000 80000000 0 20000000
+-			  01000000 0 00000000 e2000000 0 00100000>;
+-		clock-frequency = <3f940aa>;
++		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
++		clock-frequency = <66666666>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0008000 1000>;
++		reg = <0xe0008000 0x1000>;
+ 		compatible = "fsl,mpc8540-pci";
+ 		device_type = "pci";
+ 
+ 		i8259 at 19000 {
+ 			interrupt-controller;
+ 			device_type = "interrupt-controller";
+-			reg = <19000 0 0 0 1>;
++			reg = <0x19000 0x0 0x0 0x0 0x1>;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+ 			compatible = "chrp,iic";
+@@ -268,24 +269,24 @@
+ 
+ 	pci1: pci at e0009000 {
+ 		cell-index = <1>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 			/* IDSEL 0x15 */
+-			a800 0 0 1 &mpic b 1
+-			a800 0 0 2 &mpic b 1
+-			a800 0 0 3 &mpic b 1
+-			a800 0 0 4 &mpic b 1>;
++			0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
++			0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
++			0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
++			0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <19 2>;
++		interrupts = <25 2>;
+ 		bus-range = <0 0>;
+-		ranges = <02000000 0 a0000000 a0000000 0 20000000
+-			  01000000 0 00000000 e3000000 0 00100000>;
+-		clock-frequency = <3f940aa>;
++		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
++		clock-frequency = <66666666>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0009000 1000>;
++		reg = <0xe0009000 0x1000>;
+ 		compatible = "fsl,mpc8540-pci";
+ 		device_type = "pci";
+ 	};
+diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
+index 688af9d..6a0d8db 100644
+--- a/arch/powerpc/boot/dts/mpc8544ds.dts
++++ b/arch/powerpc/boot/dts/mpc8544ds.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC8544 DS Device Tree Source
+  *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007, 2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +9,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ / {
+ 	model = "MPC8544DS";
+ 	compatible = "MPC8544DS", "MPC85xxDS";
+@@ -27,17 +28,16 @@
+ 	};
+ 
+ 	cpus {
+-		#cpus = <1>;
+ 		#address-cells = <1>;
+ 		#size-cells = <0>;
+ 
+ 		PowerPC,8544 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K
+-			i-cache-size = <8000>;		// L1, 32K
++			reg = <0x0>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K
++			i-cache-size = <0x8000>;		// L1, 32K
+ 			timebase-frequency = <0>;
+ 			bus-frequency = <0>;
+ 			clock-frequency = <0>;
+@@ -46,7 +46,7 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 00000000>;	// Filled by U-Boot
++		reg = <0x0 0x0>;	// Filled by U-Boot
+ 	};
+ 
+ 	soc8544 at e0000000 {
+@@ -54,24 +54,24 @@
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+ 
+-		ranges = <00000000 e0000000 00100000>;
+-		reg = <e0000000 00001000>;	// CCSRBAR 1M
++		ranges = <0x0 0xe0000000 0x100000>;
++		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
+ 		bus-frequency = <0>;		// Filled out by uboot.
+ 
+ 		memory-controller at 2000 {
+ 			compatible = "fsl,8544-memory-controller";
+-			reg = <2000 1000>;
++			reg = <0x2000 0x1000>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <12 2>;
++			interrupts = <18 2>;
+ 		};
+ 
+ 		l2-cache-controller at 20000 {
+ 			compatible = "fsl,8544-l2-cache-controller";
+-			reg = <20000 1000>;
+-			cache-line-size = <20>;	// 32 bytes
+-			cache-size = <40000>;	// L2, 256K
++			reg = <0x20000 0x1000>;
++			cache-line-size = <32>;	// 32 bytes
++			cache-size = <0x40000>;	// L2, 256K
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <10 2>;
++			interrupts = <16 2>;
+ 		};
+ 
+ 		i2c at 3000 {
+@@ -79,8 +79,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <0>;
+ 			compatible = "fsl-i2c";
+-			reg = <3000 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3000 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -90,8 +90,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <1>;
+ 			compatible = "fsl-i2c";
+-			reg = <3100 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3100 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -100,30 +100,71 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			compatible = "fsl,gianfar-mdio";
+-			reg = <24520 20>;
++			reg = <0x24520 0x20>;
+ 
+ 			phy0: ethernet-phy at 0 {
+ 				interrupt-parent = <&mpic>;
+-				interrupts = <a 1>;
+-				reg = <0>;
++				interrupts = <10 1>;
++				reg = <0x0>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy1: ethernet-phy at 1 {
+ 				interrupt-parent = <&mpic>;
+-				interrupts = <a 1>;
+-				reg = <1>;
++				interrupts = <10 1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+ 
++		dma at 21300 {
++			#address-cells = <1>;
++			#size-cells = <1>;
++			compatible = "fsl,mpc8544-dma", "fsl,eloplus-dma";
++			reg = <0x21300 0x4>;
++			ranges = <0x0 0x21100 0x200>;
++			cell-index = <0>;
++			dma-channel at 0 {
++				compatible = "fsl,mpc8544-dma-channel",
++						"fsl,eloplus-dma-channel";
++				reg = <0x0 0x80>;
++				cell-index = <0>;
++				interrupt-parent = <&mpic>;
++				interrupts = <20 2>;
++			};
++			dma-channel at 80 {
++				compatible = "fsl,mpc8544-dma-channel",
++						"fsl,eloplus-dma-channel";
++				reg = <0x80 0x80>;
++				cell-index = <1>;
++				interrupt-parent = <&mpic>;
++				interrupts = <21 2>;
++			};
++			dma-channel at 100 {
++				compatible = "fsl,mpc8544-dma-channel",
++						"fsl,eloplus-dma-channel";
++				reg = <0x100 0x80>;
++				cell-index = <2>;
++				interrupt-parent = <&mpic>;
++				interrupts = <22 2>;
++			};
++			dma-channel at 180 {
++				compatible = "fsl,mpc8544-dma-channel",
++						"fsl,eloplus-dma-channel";
++				reg = <0x180 0x80>;
++				cell-index = <3>;
++				interrupt-parent = <&mpic>;
++				interrupts = <23 2>;
++			};
++		};
++
+ 		enet0: ethernet at 24000 {
+ 			cell-index = <0>;
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <24000 1000>;
++			reg = <0x24000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1d 2 1e 2 22 2>;
++			interrupts = <29 2 30 2 34 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy0>;
+ 			phy-connection-type = "rgmii-id";
+@@ -134,9 +175,9 @@
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <26000 1000>;
++			reg = <0x26000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1f 2 20 2 21 2>;
++			interrupts = <31 2 32 2 33 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy1>;
+ 			phy-connection-type = "rgmii-id";
+@@ -146,9 +187,9 @@
+ 			cell-index = <0>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4500 100>;
++			reg = <0x4500 0x100>;
+ 			clock-frequency = <0>;
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -156,15 +197,15 @@
+ 			cell-index = <1>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4600 100>;
++			reg = <0x4600 0x100>;
+ 			clock-frequency = <0>;
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+ 		global-utilities at e0000 {	//global utilities block
+ 			compatible = "fsl,mpc8548-guts";
+-			reg = <e0000 1000>;
++			reg = <0xe0000 0x1000>;
+ 			fsl,has-rstcr;
+ 		};
+ 
+@@ -173,7 +214,7 @@
+ 			interrupt-controller;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+-			reg = <40000 40000>;
++			reg = <0x40000 0x40000>;
+ 			compatible = "chrp,open-pic";
+ 			device_type = "open-pic";
+ 			big-endian;
+@@ -184,32 +225,32 @@
+ 		cell-index = <0>;
+ 		compatible = "fsl,mpc8540-pci";
+ 		device_type = "pci";
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 			/* IDSEL 0x11 J17 Slot 1 */
+-			8800 0 0 1 &mpic 2 1
+-			8800 0 0 2 &mpic 3 1
+-			8800 0 0 3 &mpic 4 1
+-			8800 0 0 4 &mpic 1 1
++			0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x12 J16 Slot 2 */
+ 
+-			9000 0 0 1 &mpic 3 1
+-			9000 0 0 2 &mpic 4 1
+-			9000 0 0 3 &mpic 2 1
+-			9000 0 0 4 &mpic 1 1>;
++			0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x9000 0x0 0x0 0x4 &mpic 0x1 0x1>;
+ 
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <18 2>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 c0000000 c0000000 0 20000000
+-			  01000000 0 00000000 e1000000 0 00010000>;
+-		clock-frequency = <3f940aa>;
++		interrupts = <24 2>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe1000000 0x0 0x10000>;
++		clock-frequency = <66666666>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0008000 1000>;
++		reg = <0xe0008000 0x1000>;
+ 	};
+ 
+ 	pci1: pcie at e0009000 {
+@@ -219,33 +260,33 @@
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0009000 1000>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 80000000 80000000 0 20000000
+-			  01000000 0 00000000 e1010000 0 00010000>;
+-		clock-frequency = <1fca055>;
++		reg = <0xe0009000 0x1000>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe1010000 0x0 0x10000>;
++		clock-frequency = <33333333>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <1a 2>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupts = <26 2>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 			/* IDSEL 0x0 */
+-			0000 0 0 1 &mpic 4 1
+-			0000 0 0 2 &mpic 5 1
+-			0000 0 0 3 &mpic 6 1
+-			0000 0 0 4 &mpic 7 1
++			0000 0x0 0x0 0x1 &mpic 0x4 0x1
++			0000 0x0 0x0 0x2 &mpic 0x5 0x1
++			0000 0x0 0x0 0x3 &mpic 0x6 0x1
++			0000 0x0 0x0 0x4 &mpic 0x7 0x1
+ 			>;
+ 		pcie at 0 {
+-			reg = <0 0 0 0 0>;
++			reg = <0x0 0x0 0x0 0x0 0x0>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+ 			device_type = "pci";
+-			ranges = <02000000 0 80000000
+-				  02000000 0 80000000
+-				  0 20000000
++			ranges = <0x2000000 0x0 0x80000000
++				  0x2000000 0x0 0x80000000
++				  0x0 0x20000000
+ 
+-				  01000000 0 00000000
+-				  01000000 0 00000000
+-				  0 00010000>;
++				  0x1000000 0x0 0x0
++				  0x1000000 0x0 0x0
++				  0x0 0x10000>;
+ 		};
+ 	};
+ 
+@@ -256,33 +297,33 @@
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e000a000 1000>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 a0000000 a0000000 0 10000000
+-			  01000000 0 00000000 e1020000 0 00010000>;
+-		clock-frequency = <1fca055>;
++		reg = <0xe000a000 0x1000>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
++			  0x1000000 0x0 0x0 0xe1020000 0x0 0x10000>;
++		clock-frequency = <33333333>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <19 2>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupts = <25 2>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 			/* IDSEL 0x0 */
+-			0000 0 0 1 &mpic 0 1
+-			0000 0 0 2 &mpic 1 1
+-			0000 0 0 3 &mpic 2 1
+-			0000 0 0 4 &mpic 3 1
++			0000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 			>;
+ 		pcie at 0 {
+-			reg = <0 0 0 0 0>;
++			reg = <0x0 0x0 0x0 0x0 0x0>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+ 			device_type = "pci";
+-			ranges = <02000000 0 a0000000
+-				  02000000 0 a0000000
+-				  0 10000000
++			ranges = <0x2000000 0x0 0xa0000000
++				  0x2000000 0x0 0xa0000000
++				  0x0 0x10000000
+ 
+-				  01000000 0 00000000
+-				  01000000 0 00000000
+-				  0 00010000>;
++				  0x1000000 0x0 0x0
++				  0x1000000 0x0 0x0
++				  0x0 0x10000>;
+ 		};
+ 	};
+ 
+@@ -293,72 +334,72 @@
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e000b000 1000>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 b0000000 b0000000 0 00100000
+-			  01000000 0 00000000 b0100000 0 00100000>;
+-		clock-frequency = <1fca055>;
++		reg = <0xe000b000 0x1000>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0xb0000000 0xb0000000 0x0 0x100000
++			  0x1000000 0x0 0x0 0xb0100000 0x0 0x100000>;
++		clock-frequency = <33333333>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <1b 2>;
+-		interrupt-map-mask = <ff00 0 0 1>;
++		interrupts = <27 2>;
++		interrupt-map-mask = <0xff00 0x0 0x0 0x1>;
+ 		interrupt-map = <
+ 			// IDSEL 0x1c  USB
+-			e000 0 0 1 &i8259 c 2
+-			e100 0 0 2 &i8259 9 2
+-			e200 0 0 3 &i8259 a 2
+-			e300 0 0 4 &i8259 b 2
++			0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
++			0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
++			0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
++			0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+ 
+ 			// IDSEL 0x1d  Audio
+-			e800 0 0 1 &i8259 6 2
++			0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+ 
+ 			// IDSEL 0x1e Legacy
+-			f000 0 0 1 &i8259 7 2
+-			f100 0 0 1 &i8259 7 2
++			0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
++			0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+ 
+ 			// IDSEL 0x1f IDE/SATA
+-			f800 0 0 1 &i8259 e 2
+-			f900 0 0 1 &i8259 5 2
++			0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
++			0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+ 		>;
+ 
+ 		pcie at 0 {
+-			reg = <0 0 0 0 0>;
++			reg = <0x0 0x0 0x0 0x0 0x0>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+ 			device_type = "pci";
+-			ranges = <02000000 0 b0000000
+-				  02000000 0 b0000000
+-				  0 00100000
++			ranges = <0x2000000 0x0 0xb0000000
++				  0x2000000 0x0 0xb0000000
++				  0x0 0x100000
+ 
+-				  01000000 0 00000000
+-				  01000000 0 00000000
+-				  0 00100000>;
++				  0x1000000 0x0 0x0
++				  0x1000000 0x0 0x0
++				  0x0 0x100000>;
+ 
+ 			uli1575 at 0 {
+-				reg = <0 0 0 0 0>;
++				reg = <0x0 0x0 0x0 0x0 0x0>;
+ 				#size-cells = <2>;
+ 				#address-cells = <3>;
+-				ranges = <02000000 0 b0000000
+-					  02000000 0 b0000000
+-					  0 00100000
++				ranges = <0x2000000 0x0 0xb0000000
++					  0x2000000 0x0 0xb0000000
++					  0x0 0x100000
+ 
+-					  01000000 0 00000000
+-					  01000000 0 00000000
+-					  0 00100000>;
++					  0x1000000 0x0 0x0
++					  0x1000000 0x0 0x0
++					  0x0 0x100000>;
+ 				isa at 1e {
+ 					device_type = "isa";
+ 					#interrupt-cells = <2>;
+ 					#size-cells = <1>;
+ 					#address-cells = <2>;
+-					reg = <f000 0 0 0 0>;
+-					ranges = <1 0
+-						  01000000 0 0
+-						  00001000>;
++					reg = <0xf000 0x0 0x0 0x0 0x0>;
++					ranges = <0x1 0x0
++						  0x1000000 0x0 0x0
++						  0x1000>;
+ 					interrupt-parent = <&i8259>;
+ 
+ 					i8259: interrupt-controller at 20 {
+-						reg = <1 20 2
+-						       1 a0 2
+-						       1 4d0 2>;
++						reg = <0x1 0x20 0x2
++						       0x1 0xa0 0x2
++						       0x1 0x4d0 0x2>;
+ 						interrupt-controller;
+ 						device_type = "interrupt-controller";
+ 						#address-cells = <0>;
+@@ -371,28 +412,28 @@
+ 					i8042 at 60 {
+ 						#size-cells = <0>;
+ 						#address-cells = <1>;
+-						reg = <1 60 1 1 64 1>;
+-						interrupts = <1 3 c 3>;
++						reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
++						interrupts = <1 3 12 3>;
+ 						interrupt-parent = <&i8259>;
+ 
+ 						keyboard at 0 {
+-							reg = <0>;
++							reg = <0x0>;
+ 							compatible = "pnpPNP,303";
+ 						};
+ 
+ 						mouse at 1 {
+-							reg = <1>;
++							reg = <0x1>;
+ 							compatible = "pnpPNP,f03";
+ 						};
+ 					};
+ 
+ 					rtc at 70 {
+ 						compatible = "pnpPNP,b00";
+-						reg = <1 70 2>;
++						reg = <0x1 0x70 0x2>;
+ 					};
+ 
+ 					gpio at 400 {
+-						reg = <1 400 80>;
++						reg = <0x1 0x400 0x80>;
+ 					};
+ 				};
+ 			};
+diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
+index 1f470c6..fa298a8 100644
+--- a/arch/powerpc/boot/dts/mpc8548cds.dts
++++ b/arch/powerpc/boot/dts/mpc8548cds.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC8548 CDS Device Tree Source
+  *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +9,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ 
+ / {
+ 	model = "MPC8548CDS";
+@@ -36,11 +37,11 @@
+ 
+ 		PowerPC,8548 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K
+-			i-cache-size = <8000>;		// L1, 32K
++			reg = <0x0>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K
++			i-cache-size = <0x8000>;		// L1, 32K
+ 			timebase-frequency = <0>;	//  33 MHz, from uboot
+ 			bus-frequency = <0>;	// 166 MHz
+ 			clock-frequency = <0>;	// 825 MHz, from uboot
+@@ -49,31 +50,31 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 08000000>;	// 128M at 0x0
++		reg = <0x0 0x8000000>;	// 128M at 0x0
+ 	};
+ 
+ 	soc8548 at e0000000 {
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <00000000 e0000000 00100000>;
+-		reg = <e0000000 00001000>;	// CCSRBAR
++		ranges = <0x0 0xe0000000 0x100000>;
++		reg = <0xe0000000 0x1000>;	// CCSRBAR
+ 		bus-frequency = <0>;
+ 
+ 		memory-controller at 2000 {
+ 			compatible = "fsl,8548-memory-controller";
+-			reg = <2000 1000>;
++			reg = <0x2000 0x1000>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <12 2>;
++			interrupts = <18 2>;
+ 		};
+ 
+ 		l2-cache-controller at 20000 {
+ 			compatible = "fsl,8548-l2-cache-controller";
+-			reg = <20000 1000>;
+-			cache-line-size = <20>;	// 32 bytes
+-			cache-size = <80000>;	// L2, 512K
++			reg = <0x20000 0x1000>;
++			cache-line-size = <32>;	// 32 bytes
++			cache-size = <0x80000>;	// L2, 512K
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <10 2>;
++			interrupts = <16 2>;
+ 		};
+ 
+ 		i2c at 3000 {
+@@ -81,8 +82,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <0>;
+ 			compatible = "fsl-i2c";
+-			reg = <3000 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3000 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -92,8 +93,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <1>;
+ 			compatible = "fsl-i2c";
+-			reg = <3100 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3100 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -102,30 +103,30 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			compatible = "fsl,gianfar-mdio";
+-			reg = <24520 20>;
++			reg = <0x24520 0x20>;
+ 
+ 			phy0: ethernet-phy at 0 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <0>;
++				reg = <0x0>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy1: ethernet-phy at 1 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy2: ethernet-phy at 2 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <2>;
++				reg = <0x2>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy3: ethernet-phy at 3 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <3>;
++				reg = <0x3>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -135,9 +136,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <24000 1000>;
++			reg = <0x24000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1d 2 1e 2 22 2>;
++			interrupts = <29 2 30 2 34 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy0>;
+ 		};
+@@ -147,9 +148,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <25000 1000>;
++			reg = <0x25000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <23 2 24 2 28 2>;
++			interrupts = <35 2 36 2 40 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy1>;
+ 		};
+@@ -160,9 +161,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <26000 1000>;
++			reg = <0x26000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1f 2 20 2 21 2>;
++			interrupts = <31 2 32 2 33 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy2>;
+ 		};
+@@ -172,9 +173,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <27000 1000>;
++			reg = <0x27000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <25 2 26 2 27 2>;
++			interrupts = <37 2 38 2 39 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy3>;
+ 		};
+@@ -184,9 +185,9 @@
+ 			cell-index = <0>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4500 100>;	// reg base, size
++			reg = <0x4500 0x100>;	// reg base, size
+ 			clock-frequency = <0>;	// should we fill in in uboot?
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -194,15 +195,15 @@
+ 			cell-index = <1>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4600 100>;	// reg base, size
++			reg = <0x4600 0x100>;	// reg base, size
+ 			clock-frequency = <0>;	// should we fill in in uboot?
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+ 		global-utilities at e0000 {	//global utilities reg
+ 			compatible = "fsl,mpc8548-guts";
+-			reg = <e0000 1000>;
++			reg = <0xe0000 0x1000>;
+ 			fsl,has-rstcr;
+ 		};
+ 
+@@ -211,7 +212,7 @@
+ 			interrupt-controller;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+-			reg = <40000 40000>;
++			reg = <0x40000 0x40000>;
+ 			compatible = "chrp,open-pic";
+ 			device_type = "open-pic";
+                         big-endian;
+@@ -220,139 +221,139 @@
+ 
+ 	pci0: pci at e0008000 {
+ 		cell-index = <0>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 			/* IDSEL 0x4 (PCIX Slot 2) */
+-			02000 0 0 1 &mpic 0 1
+-			02000 0 0 2 &mpic 1 1
+-			02000 0 0 3 &mpic 2 1
+-			02000 0 0 4 &mpic 3 1
++			0x2000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x2000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x2000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x2000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x5 (PCIX Slot 3) */
+-			02800 0 0 1 &mpic 1 1
+-			02800 0 0 2 &mpic 2 1
+-			02800 0 0 3 &mpic 3 1
+-			02800 0 0 4 &mpic 0 1
++			0x2800 0x0 0x0 0x1 &mpic 0x1 0x1
++			0x2800 0x0 0x0 0x2 &mpic 0x2 0x1
++			0x2800 0x0 0x0 0x3 &mpic 0x3 0x1
++			0x2800 0x0 0x0 0x4 &mpic 0x0 0x1
+ 
+ 			/* IDSEL 0x6 (PCIX Slot 4) */
+-			03000 0 0 1 &mpic 2 1
+-			03000 0 0 2 &mpic 3 1
+-			03000 0 0 3 &mpic 0 1
+-			03000 0 0 4 &mpic 1 1
++			0x3000 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x3000 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x3000 0x0 0x0 0x3 &mpic 0x0 0x1
++			0x3000 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x8 (PCIX Slot 5) */
+-			04000 0 0 1 &mpic 0 1
+-			04000 0 0 2 &mpic 1 1
+-			04000 0 0 3 &mpic 2 1
+-			04000 0 0 4 &mpic 3 1
++			0x4000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x4000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x4000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x4000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0xC (Tsi310 bridge) */
+-			06000 0 0 1 &mpic 0 1
+-			06000 0 0 2 &mpic 1 1
+-			06000 0 0 3 &mpic 2 1
+-			06000 0 0 4 &mpic 3 1
++			0x6000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x6000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x6000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x6000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x14 (Slot 2) */
+-			0a000 0 0 1 &mpic 0 1
+-			0a000 0 0 2 &mpic 1 1
+-			0a000 0 0 3 &mpic 2 1
+-			0a000 0 0 4 &mpic 3 1
++			0xa000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0xa000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0xa000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0xa000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x15 (Slot 3) */
+-			0a800 0 0 1 &mpic 1 1
+-			0a800 0 0 2 &mpic 2 1
+-			0a800 0 0 3 &mpic 3 1
+-			0a800 0 0 4 &mpic 0 1
++			0xa800 0x0 0x0 0x1 &mpic 0x1 0x1
++			0xa800 0x0 0x0 0x2 &mpic 0x2 0x1
++			0xa800 0x0 0x0 0x3 &mpic 0x3 0x1
++			0xa800 0x0 0x0 0x4 &mpic 0x0 0x1
+ 
+ 			/* IDSEL 0x16 (Slot 4) */
+-			0b000 0 0 1 &mpic 2 1
+-			0b000 0 0 2 &mpic 3 1
+-			0b000 0 0 3 &mpic 0 1
+-			0b000 0 0 4 &mpic 1 1
++			0xb000 0x0 0x0 0x1 &mpic 0x2 0x1
++			0xb000 0x0 0x0 0x2 &mpic 0x3 0x1
++			0xb000 0x0 0x0 0x3 &mpic 0x0 0x1
++			0xb000 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x18 (Slot 5) */
+-			0c000 0 0 1 &mpic 0 1
+-			0c000 0 0 2 &mpic 1 1
+-			0c000 0 0 3 &mpic 2 1
+-			0c000 0 0 4 &mpic 3 1
++			0xc000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0xc000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0xc000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0xc000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x1C (Tsi310 bridge PCI primary) */
+-			0E000 0 0 1 &mpic 0 1
+-			0E000 0 0 2 &mpic 1 1
+-			0E000 0 0 3 &mpic 2 1
+-			0E000 0 0 4 &mpic 3 1>;
++			0xe000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0xe000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0xe000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0xe000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ 
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <18 2>;
++		interrupts = <24 2>;
+ 		bus-range = <0 0>;
+-		ranges = <02000000 0 80000000 80000000 0 10000000
+-			  01000000 0 00000000 e2000000 0 00800000>;
+-		clock-frequency = <3f940aa>;
++		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x10000000
++			  0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>;
++		clock-frequency = <66666666>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0008000 1000>;
++		reg = <0xe0008000 0x1000>;
+ 		compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+ 		device_type = "pci";
+ 
+ 		pci_bridge at 1c {
+-			interrupt-map-mask = <f800 0 0 7>;
++			interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 			interrupt-map = <
+ 
+ 				/* IDSEL 0x00 (PrPMC Site) */
+-				0000 0 0 1 &mpic 0 1
+-				0000 0 0 2 &mpic 1 1
+-				0000 0 0 3 &mpic 2 1
+-				0000 0 0 4 &mpic 3 1
++				0000 0x0 0x0 0x1 &mpic 0x0 0x1
++				0000 0x0 0x0 0x2 &mpic 0x1 0x1
++				0000 0x0 0x0 0x3 &mpic 0x2 0x1
++				0000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 				/* IDSEL 0x04 (VIA chip) */
+-				2000 0 0 1 &mpic 0 1
+-				2000 0 0 2 &mpic 1 1
+-				2000 0 0 3 &mpic 2 1
+-				2000 0 0 4 &mpic 3 1
++				0x2000 0x0 0x0 0x1 &mpic 0x0 0x1
++				0x2000 0x0 0x0 0x2 &mpic 0x1 0x1
++				0x2000 0x0 0x0 0x3 &mpic 0x2 0x1
++				0x2000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 				/* IDSEL 0x05 (8139) */
+-				2800 0 0 1 &mpic 1 1
++				0x2800 0x0 0x0 0x1 &mpic 0x1 0x1
+ 
+ 				/* IDSEL 0x06 (Slot 6) */
+-				3000 0 0 1 &mpic 2 1
+-				3000 0 0 2 &mpic 3 1
+-				3000 0 0 3 &mpic 0 1
+-				3000 0 0 4 &mpic 1 1
++				0x3000 0x0 0x0 0x1 &mpic 0x2 0x1
++				0x3000 0x0 0x0 0x2 &mpic 0x3 0x1
++				0x3000 0x0 0x0 0x3 &mpic 0x0 0x1
++				0x3000 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 				/* IDESL 0x07 (Slot 7) */
+-				3800 0 0 1 &mpic 3 1
+-				3800 0 0 2 &mpic 0 1
+-				3800 0 0 3 &mpic 1 1
+-				3800 0 0 4 &mpic 2 1>;
++				0x3800 0x0 0x0 0x1 &mpic 0x3 0x1
++				0x3800 0x0 0x0 0x2 &mpic 0x0 0x1
++				0x3800 0x0 0x0 0x3 &mpic 0x1 0x1
++				0x3800 0x0 0x0 0x4 &mpic 0x2 0x1>;
+ 
+-			reg = <e000 0 0 0 0>;
++			reg = <0xe000 0x0 0x0 0x0 0x0>;
+ 			#interrupt-cells = <1>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+-			ranges = <02000000 0 80000000
+-				  02000000 0 80000000
+-				  0 20000000
+-				  01000000 0 00000000
+-				  01000000 0 00000000
+-				  0 00080000>;
+-			clock-frequency = <1fca055>;
++			ranges = <0x2000000 0x0 0x80000000
++				  0x2000000 0x0 0x80000000
++				  0x0 0x20000000
++				  0x1000000 0x0 0x0
++				  0x1000000 0x0 0x0
++				  0x0 0x80000>;
++			clock-frequency = <33333333>;
+ 
+ 			isa at 4 {
+ 				device_type = "isa";
+ 				#interrupt-cells = <2>;
+ 				#size-cells = <1>;
+ 				#address-cells = <2>;
+-				reg = <2000 0 0 0 0>;
+-				ranges = <1 0 01000000 0 0 00001000>;
++				reg = <0x2000 0x0 0x0 0x0 0x0>;
++				ranges = <0x1 0x0 0x1000000 0x0 0x0 0x1000>;
+ 				interrupt-parent = <&i8259>;
+ 
+ 				i8259: interrupt-controller at 20 {
+ 					interrupt-controller;
+ 					device_type = "interrupt-controller";
+-					reg = <1 20 2
+-					       1 a0 2
+-					       1 4d0 2>;
++					reg = <0x1 0x20 0x2
++					       0x1 0xa0 0x2
++					       0x1 0x4d0 0x2>;
+ 					#address-cells = <0>;
+ 					#interrupt-cells = <2>;
+ 					compatible = "chrp,iic";
+@@ -362,7 +363,7 @@
+ 
+ 				rtc at 70 {
+ 					compatible = "pnpPNP,b00";
+-					reg = <1 70 2>;
++					reg = <0x1 0x70 0x2>;
+ 				};
+ 			};
+ 		};
+@@ -370,64 +371,64 @@
+ 
+ 	pci1: pci at e0009000 {
+ 		cell-index = <1>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 			/* IDSEL 0x15 */
+-			a800 0 0 1 &mpic b 1
+-			a800 0 0 2 &mpic 1 1
+-			a800 0 0 3 &mpic 2 1
+-			a800 0 0 4 &mpic 3 1>;
++			0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
++			0xa800 0x0 0x0 0x2 &mpic 0x1 0x1
++			0xa800 0x0 0x0 0x3 &mpic 0x2 0x1
++			0xa800 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ 
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <19 2>;
++		interrupts = <25 2>;
+ 		bus-range = <0 0>;
+-		ranges = <02000000 0 90000000 90000000 0 10000000
+-			  01000000 0 00000000 e2800000 0 00800000>;
+-		clock-frequency = <3f940aa>;
++		ranges = <0x2000000 0x0 0x90000000 0x90000000 0x0 0x10000000
++			  0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>;
++		clock-frequency = <66666666>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0009000 1000>;
++		reg = <0xe0009000 0x1000>;
+ 		compatible = "fsl,mpc8540-pci";
+ 		device_type = "pci";
+ 	};
+ 
+ 	pci2: pcie at e000a000 {
+ 		cell-index = <2>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 			/* IDSEL 0x0 (PEX) */
+-			00000 0 0 1 &mpic 0 1
+-			00000 0 0 2 &mpic 1 1
+-			00000 0 0 3 &mpic 2 1
+-			00000 0 0 4 &mpic 3 1>;
++			00000 0x0 0x0 0x1 &mpic 0x0 0x1
++			00000 0x0 0x0 0x2 &mpic 0x1 0x1
++			00000 0x0 0x0 0x3 &mpic 0x2 0x1
++			00000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ 
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <1a 2>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 a0000000 a0000000 0 20000000
+-			  01000000 0 00000000 e3000000 0 08000000>;
+-		clock-frequency = <1fca055>;
++		interrupts = <26 2>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe3000000 0x0 0x8000000>;
++		clock-frequency = <33333333>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e000a000 1000>;
++		reg = <0xe000a000 0x1000>;
+ 		compatible = "fsl,mpc8548-pcie";
+ 		device_type = "pci";
+ 		pcie at 0 {
+-			reg = <0 0 0 0 0>;
++			reg = <0x0 0x0 0x0 0x0 0x0>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+ 			device_type = "pci";
+-			ranges = <02000000 0 a0000000
+-				  02000000 0 a0000000
+-				  0 20000000
++			ranges = <0x2000000 0x0 0xa0000000
++				  0x2000000 0x0 0xa0000000
++				  0x0 0x20000000
+ 
+-				  01000000 0 00000000
+-				  01000000 0 00000000
+-				  0 08000000>;
++				  0x1000000 0x0 0x0
++				  0x1000000 0x0 0x0
++				  0x0 0x8000000>;
+ 		};
+ 	};
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
+index 4538f3c..b025c56 100644
+--- a/arch/powerpc/boot/dts/mpc8555cds.dts
++++ b/arch/powerpc/boot/dts/mpc8555cds.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC8555 CDS Device Tree Source
+  *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +9,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ 
+ / {
+ 	model = "MPC8555CDS";
+@@ -31,11 +32,11 @@
+ 
+ 		PowerPC,8555 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K
+-			i-cache-size = <8000>;		// L1, 32K
++			reg = <0x0>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K
++			i-cache-size = <0x8000>;		// L1, 32K
+ 			timebase-frequency = <0>;	//  33 MHz, from uboot
+ 			bus-frequency = <0>;	// 166 MHz
+ 			clock-frequency = <0>;	// 825 MHz, from uboot
+@@ -44,31 +45,31 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 08000000>;	// 128M at 0x0
++		reg = <0x0 0x8000000>;	// 128M at 0x0
+ 	};
+ 
+ 	soc8555 at e0000000 {
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <0 e0000000 00100000>;
+-		reg = <e0000000 00001000>;	// CCSRBAR 1M
++		ranges = <0x0 0xe0000000 0x100000>;
++		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
+ 		bus-frequency = <0>;
+ 
+ 		memory-controller at 2000 {
+ 			compatible = "fsl,8555-memory-controller";
+-			reg = <2000 1000>;
++			reg = <0x2000 0x1000>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <12 2>;
++			interrupts = <18 2>;
+ 		};
+ 
+ 		l2-cache-controller at 20000 {
+ 			compatible = "fsl,8555-l2-cache-controller";
+-			reg = <20000 1000>;
+-			cache-line-size = <20>;	// 32 bytes
+-			cache-size = <40000>;	// L2, 256K
++			reg = <0x20000 0x1000>;
++			cache-line-size = <32>;	// 32 bytes
++			cache-size = <0x40000>;	// L2, 256K
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <10 2>;
++			interrupts = <16 2>;
+ 		};
+ 
+ 		i2c at 3000 {
+@@ -76,8 +77,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <0>;
+ 			compatible = "fsl-i2c";
+-			reg = <3000 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3000 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -86,18 +87,18 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			compatible = "fsl,gianfar-mdio";
+-			reg = <24520 20>;
++			reg = <0x24520 0x20>;
+ 
+ 			phy0: ethernet-phy at 0 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <0>;
++				reg = <0x0>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy1: ethernet-phy at 1 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -107,9 +108,9 @@
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <24000 1000>;
++			reg = <0x24000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1d 2 1e 2 22 2>;
++			interrupts = <29 2 30 2 34 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy0>;
+ 		};
+@@ -119,9 +120,9 @@
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <25000 1000>;
++			reg = <0x25000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <23 2 24 2 28 2>;
++			interrupts = <35 2 36 2 40 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy1>;
+ 		};
+@@ -130,9 +131,9 @@
+ 			cell-index = <0>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4500 100>; 	// reg base, size
++			reg = <0x4500 0x100>; 	// reg base, size
+ 			clock-frequency = <0>; 	// should we fill in in uboot?
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -140,9 +141,9 @@
+ 			cell-index = <1>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4600 100>;	// reg base, size
++			reg = <0x4600 0x100>;	// reg base, size
+ 			clock-frequency = <0>; 	// should we fill in in uboot?
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -151,7 +152,7 @@
+ 			interrupt-controller;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+-			reg = <40000 40000>;
++			reg = <0x40000 0x40000>;
+ 			compatible = "chrp,open-pic";
+ 			device_type = "open-pic";
+                         big-endian;
+@@ -161,17 +162,17 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <1>;
+ 			compatible = "fsl,mpc8555-cpm", "fsl,cpm2";
+-			reg = <919c0 30>;
++			reg = <0x919c0 0x30>;
+ 			ranges;
+ 
+ 			muram at 80000 {
+ 				#address-cells = <1>;
+ 				#size-cells = <1>;
+-				ranges = <0 80000 10000>;
++				ranges = <0x0 0x80000 0x10000>;
+ 
+ 				data at 0 {
+ 					compatible = "fsl,cpm-muram-data";
+-					reg = <0 2000 9000 1000>;
++					reg = <0x0 0x2000 0x9000 0x1000>;
+ 				};
+ 			};
+ 
+@@ -179,16 +180,16 @@
+ 				compatible = "fsl,mpc8555-brg",
+ 				             "fsl,cpm2-brg",
+ 				             "fsl,cpm-brg";
+-				reg = <919f0 10 915f0 10>;
++				reg = <0x919f0 0x10 0x915f0 0x10>;
+ 			};
+ 
+ 			cpmpic: pic at 90c00 {
+ 				interrupt-controller;
+ 				#address-cells = <0>;
+ 				#interrupt-cells = <2>;
+-				interrupts = <2e 2>;
++				interrupts = <46 2>;
+ 				interrupt-parent = <&mpic>;
+-				reg = <90c00 80>;
++				reg = <0x90c00 0x80>;
+ 				compatible = "fsl,mpc8555-cpm-pic", "fsl,cpm2-pic";
+ 			};
+ 		};
+@@ -196,68 +197,68 @@
+ 
+ 	pci0: pci at e0008000 {
+ 		cell-index = <0>;
+-		interrupt-map-mask = <1f800 0 0 7>;
++		interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 			/* IDSEL 0x10 */
+-			08000 0 0 1 &mpic 0 1
+-			08000 0 0 2 &mpic 1 1
+-			08000 0 0 3 &mpic 2 1
+-			08000 0 0 4 &mpic 3 1
++			0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x11 */
+-			08800 0 0 1 &mpic 0 1
+-			08800 0 0 2 &mpic 1 1
+-			08800 0 0 3 &mpic 2 1
+-			08800 0 0 4 &mpic 3 1
++			0x8800 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x8800 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x8800 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x8800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x12 (Slot 1) */
+-			09000 0 0 1 &mpic 0 1
+-			09000 0 0 2 &mpic 1 1
+-			09000 0 0 3 &mpic 2 1
+-			09000 0 0 4 &mpic 3 1
++			0x9000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x9000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x9000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 			/* IDSEL 0x13 (Slot 2) */
+-			09800 0 0 1 &mpic 1 1
+-			09800 0 0 2 &mpic 2 1
+-			09800 0 0 3 &mpic 3 1
+-			09800 0 0 4 &mpic 0 1
++			0x9800 0x0 0x0 0x1 &mpic 0x1 0x1
++			0x9800 0x0 0x0 0x2 &mpic 0x2 0x1
++			0x9800 0x0 0x0 0x3 &mpic 0x3 0x1
++			0x9800 0x0 0x0 0x4 &mpic 0x0 0x1
+ 
+ 			/* IDSEL 0x14 (Slot 3) */
+-			0a000 0 0 1 &mpic 2 1
+-			0a000 0 0 2 &mpic 3 1
+-			0a000 0 0 3 &mpic 0 1
+-			0a000 0 0 4 &mpic 1 1
++			0xa000 0x0 0x0 0x1 &mpic 0x2 0x1
++			0xa000 0x0 0x0 0x2 &mpic 0x3 0x1
++			0xa000 0x0 0x0 0x3 &mpic 0x0 0x1
++			0xa000 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x15 (Slot 4) */
+-			0a800 0 0 1 &mpic 3 1
+-			0a800 0 0 2 &mpic 0 1
+-			0a800 0 0 3 &mpic 1 1
+-			0a800 0 0 4 &mpic 2 1
++			0xa800 0x0 0x0 0x1 &mpic 0x3 0x1
++			0xa800 0x0 0x0 0x2 &mpic 0x0 0x1
++			0xa800 0x0 0x0 0x3 &mpic 0x1 0x1
++			0xa800 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* Bus 1 (Tundra Bridge) */
+ 			/* IDSEL 0x12 (ISA bridge) */
+-			19000 0 0 1 &mpic 0 1
+-			19000 0 0 2 &mpic 1 1
+-			19000 0 0 3 &mpic 2 1
+-			19000 0 0 4 &mpic 3 1>;
++			0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <18 2>;
++		interrupts = <24 2>;
+ 		bus-range = <0 0>;
+-		ranges = <02000000 0 80000000 80000000 0 20000000
+-			  01000000 0 00000000 e2000000 0 00100000>;
+-		clock-frequency = <3f940aa>;
++		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
++		clock-frequency = <66666666>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0008000 1000>;
++		reg = <0xe0008000 0x1000>;
+ 		compatible = "fsl,mpc8540-pci";
+ 		device_type = "pci";
+ 
+ 		i8259 at 19000 {
+ 			interrupt-controller;
+ 			device_type = "interrupt-controller";
+-			reg = <19000 0 0 0 1>;
++			reg = <0x19000 0x0 0x0 0x0 0x1>;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+ 			compatible = "chrp,iic";
+@@ -268,24 +269,24 @@
+ 
+ 	pci1: pci at e0009000 {
+ 		cell-index = <1>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 			/* IDSEL 0x15 */
+-			a800 0 0 1 &mpic b 1
+-			a800 0 0 2 &mpic b 1
+-			a800 0 0 3 &mpic b 1
+-			a800 0 0 4 &mpic b 1>;
++			0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
++			0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
++			0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
++			0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <19 2>;
++		interrupts = <25 2>;
+ 		bus-range = <0 0>;
+-		ranges = <02000000 0 a0000000 a0000000 0 20000000
+-			  01000000 0 00000000 e3000000 0 00100000>;
+-		clock-frequency = <3f940aa>;
++		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
++		clock-frequency = <66666666>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0009000 1000>;
++		reg = <0xe0009000 0x1000>;
+ 		compatible = "fsl,mpc8540-pci";
+ 		device_type = "pci";
+ 	};
+diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
+index 639ce8a..0cc16ab 100644
+--- a/arch/powerpc/boot/dts/mpc8560ads.dts
++++ b/arch/powerpc/boot/dts/mpc8560ads.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC8560 ADS Device Tree Source
+  *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +9,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ 
+ / {
+ 	model = "MPC8560ADS";
+@@ -32,74 +33,74 @@
+ 
+ 		PowerPC,8560 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K
+-			i-cache-size = <8000>;		// L1, 32K
+-			timebase-frequency = <04ead9a0>;
+-			bus-frequency = <13ab6680>;
+-			clock-frequency = <312c8040>;
++			reg = <0x0>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K
++			i-cache-size = <0x8000>;		// L1, 32K
++			timebase-frequency = <82500000>;
++			bus-frequency = <330000000>;
++			clock-frequency = <825000000>;
+ 		};
+ 	};
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 10000000>;
++		reg = <0x0 0x10000000>;
+ 	};
+ 
+ 	soc8560 at e0000000 {
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <0 e0000000 00100000>;
+-		reg = <e0000000 00000200>;
+-		bus-frequency = <13ab6680>;
++		ranges = <0x0 0xe0000000 0x100000>;
++		reg = <0xe0000000 0x200>;
++		bus-frequency = <330000000>;
+ 
+ 		memory-controller at 2000 {
+ 			compatible = "fsl,8540-memory-controller";
+-			reg = <2000 1000>;
++			reg = <0x2000 0x1000>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <12 2>;
++			interrupts = <18 2>;
+ 		};
+ 
+ 		l2-cache-controller at 20000 {
+ 			compatible = "fsl,8540-l2-cache-controller";
+-			reg = <20000 1000>;
+-			cache-line-size = <20>;	// 32 bytes
+-			cache-size = <40000>;	// L2, 256K
++			reg = <0x20000 0x1000>;
++			cache-line-size = <32>;	// 32 bytes
++			cache-size = <0x40000>;	// L2, 256K
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <10 2>;
++			interrupts = <16 2>;
+ 		};
+ 
+ 		mdio at 24520 {
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			compatible = "fsl,gianfar-mdio";
+-			reg = <24520 20>;
++			reg = <0x24520 0x20>;
+ 
+ 			phy0: ethernet-phy at 0 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <0>;
++				reg = <0x0>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy1: ethernet-phy at 1 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <5 1>;
+-				reg = <1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy2: ethernet-phy at 2 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <7 1>;
+-				reg = <2>;
++				reg = <0x2>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy3: ethernet-phy at 3 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <7 1>;
+-				reg = <3>;
++				reg = <0x3>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -109,9 +110,9 @@
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <24000 1000>;
++			reg = <0x24000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1d 2 1e 2 22 2>;
++			interrupts = <29 2 30 2 34 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy0>;
+ 		};
+@@ -121,9 +122,9 @@
+ 			device_type = "network";
+ 			model = "TSEC";
+ 			compatible = "gianfar";
+-			reg = <25000 1000>;
++			reg = <0x25000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <23 2 24 2 28 2>;
++			interrupts = <35 2 36 2 40 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy1>;
+ 		};
+@@ -132,7 +133,7 @@
+ 			interrupt-controller;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+-			reg = <40000 40000>;
++			reg = <0x40000 0x40000>;
+ 			device_type = "open-pic";
+ 		};
+ 
+@@ -140,17 +141,17 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <1>;
+ 			compatible = "fsl,mpc8560-cpm", "fsl,cpm2";
+-			reg = <919c0 30>;
++			reg = <0x919c0 0x30>;
+ 			ranges;
+ 
+ 			muram at 80000 {
+ 				#address-cells = <1>;
+ 				#size-cells = <1>;
+-				ranges = <0 80000 10000>;
++				ranges = <0x0 0x80000 0x10000>;
+ 
+ 				data at 0 {
+ 					compatible = "fsl,cpm-muram-data";
+-					reg = <0 4000 9000 2000>;
++					reg = <0x0 0x4000 0x9000 0x2000>;
+ 				};
+ 			};
+ 
+@@ -158,17 +159,17 @@
+ 				compatible = "fsl,mpc8560-brg",
+ 				             "fsl,cpm2-brg",
+ 				             "fsl,cpm-brg";
+-				reg = <919f0 10 915f0 10>;
+-				clock-frequency = <d#165000000>;
++				reg = <0x919f0 0x10 0x915f0 0x10>;
++				clock-frequency = <165000000>;
+ 			};
+ 
+ 			cpmpic: pic at 90c00 {
+ 				interrupt-controller;
+ 				#address-cells = <0>;
+ 				#interrupt-cells = <2>;
+-				interrupts = <2e 2>;
++				interrupts = <46 2>;
+ 				interrupt-parent = <&mpic>;
+-				reg = <90c00 80>;
++				reg = <0x90c00 0x80>;
+ 				compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
+ 			};
+ 
+@@ -176,11 +177,11 @@
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc8560-scc-uart",
+ 				             "fsl,cpm2-scc-uart";
+-				reg = <91a00 20 88000 100>;
++				reg = <0x91a00 0x20 0x88000 0x100>;
+ 				fsl,cpm-brg = <1>;
+-				fsl,cpm-command = <00800000>;
+-				current-speed = <1c200>;
+-				interrupts = <28 8>;
++				fsl,cpm-command = <0x800000>;
++				current-speed = <115200>;
++				interrupts = <40 8>;
+ 				interrupt-parent = <&cpmpic>;
+ 			};
+ 
+@@ -188,11 +189,11 @@
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc8560-scc-uart",
+ 				             "fsl,cpm2-scc-uart";
+-				reg = <91a20 20 88100 100>;
++				reg = <0x91a20 0x20 0x88100 0x100>;
+ 				fsl,cpm-brg = <2>;
+-				fsl,cpm-command = <04a00000>;
+-				current-speed = <1c200>;
+-				interrupts = <29 8>;
++				fsl,cpm-command = <0x4a00000>;
++				current-speed = <115200>;
++				interrupts = <41 8>;
+ 				interrupt-parent = <&cpmpic>;
+ 			};
+ 
+@@ -200,10 +201,10 @@
+ 				device_type = "network";
+ 				compatible = "fsl,mpc8560-fcc-enet",
+ 				             "fsl,cpm2-fcc-enet";
+-				reg = <91320 20 88500 100 913b0 1>;
++				reg = <0x91320 0x20 0x88500 0x100 0x913b0 0x1>;
+ 				local-mac-address = [ 00 00 00 00 00 00 ];
+-				fsl,cpm-command = <16200300>;
+-				interrupts = <21 8>;
++				fsl,cpm-command = <0x16200300>;
++				interrupts = <33 8>;
+ 				interrupt-parent = <&cpmpic>;
+ 				phy-handle = <&phy2>;
+ 			};
+@@ -212,10 +213,10 @@
+ 				device_type = "network";
+ 				compatible = "fsl,mpc8560-fcc-enet",
+ 				             "fsl,cpm2-fcc-enet";
+-				reg = <91340 20 88600 100 913d0 1>;
++				reg = <0x91340 0x20 0x88600 0x100 0x913d0 0x1>;
+ 				local-mac-address = [ 00 00 00 00 00 00 ];
+-				fsl,cpm-command = <1a400300>;
+-				interrupts = <22 8>;
++				fsl,cpm-command = <0x1a400300>;
++				interrupts = <34 8>;
+ 				interrupt-parent = <&cpmpic>;
+ 				phy-handle = <&phy3>;
+ 			};
+@@ -229,87 +230,87 @@
+ 		#address-cells = <3>;
+ 		compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+ 		device_type = "pci";
+-		reg = <e0008000 1000>;
+-		clock-frequency = <3f940aa>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		reg = <0xe0008000 0x1000>;
++		clock-frequency = <66666666>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 				/* IDSEL 0x2 */
+-				 1000 0 0 1 &mpic 1 1
+-				 1000 0 0 2 &mpic 2 1
+-				 1000 0 0 3 &mpic 3 1
+-				 1000 0 0 4 &mpic 4 1
++				 0x1000 0x0 0x0 0x1 &mpic 0x1 0x1
++				 0x1000 0x0 0x0 0x2 &mpic 0x2 0x1
++				 0x1000 0x0 0x0 0x3 &mpic 0x3 0x1
++				 0x1000 0x0 0x0 0x4 &mpic 0x4 0x1
+ 
+ 				/* IDSEL 0x3 */
+-				 1800 0 0 1 &mpic 4 1
+-				 1800 0 0 2 &mpic 1 1
+-				 1800 0 0 3 &mpic 2 1
+-				 1800 0 0 4 &mpic 3 1
++				 0x1800 0x0 0x0 0x1 &mpic 0x4 0x1
++				 0x1800 0x0 0x0 0x2 &mpic 0x1 0x1
++				 0x1800 0x0 0x0 0x3 &mpic 0x2 0x1
++				 0x1800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 				/* IDSEL 0x4 */
+-				 2000 0 0 1 &mpic 3 1
+-				 2000 0 0 2 &mpic 4 1
+-				 2000 0 0 3 &mpic 1 1
+-				 2000 0 0 4 &mpic 2 1
++				 0x2000 0x0 0x0 0x1 &mpic 0x3 0x1
++				 0x2000 0x0 0x0 0x2 &mpic 0x4 0x1
++				 0x2000 0x0 0x0 0x3 &mpic 0x1 0x1
++				 0x2000 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 				/* IDSEL 0x5  */
+-				 2800 0 0 1 &mpic 2 1
+-				 2800 0 0 2 &mpic 3 1
+-				 2800 0 0 3 &mpic 4 1
+-				 2800 0 0 4 &mpic 1 1
++				 0x2800 0x0 0x0 0x1 &mpic 0x2 0x1
++				 0x2800 0x0 0x0 0x2 &mpic 0x3 0x1
++				 0x2800 0x0 0x0 0x3 &mpic 0x4 0x1
++				 0x2800 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 				/* IDSEL 12 */
+-				 6000 0 0 1 &mpic 1 1
+-				 6000 0 0 2 &mpic 2 1
+-				 6000 0 0 3 &mpic 3 1
+-				 6000 0 0 4 &mpic 4 1
++				 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++				 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++				 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++				 0x6000 0x0 0x0 0x4 &mpic 0x4 0x1
+ 
+ 				/* IDSEL 13 */
+-				 6800 0 0 1 &mpic 4 1
+-				 6800 0 0 2 &mpic 1 1
+-				 6800 0 0 3 &mpic 2 1
+-				 6800 0 0 4 &mpic 3 1
++				 0x6800 0x0 0x0 0x1 &mpic 0x4 0x1
++				 0x6800 0x0 0x0 0x2 &mpic 0x1 0x1
++				 0x6800 0x0 0x0 0x3 &mpic 0x2 0x1
++				 0x6800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 				/* IDSEL 14*/
+-				 7000 0 0 1 &mpic 3 1
+-				 7000 0 0 2 &mpic 4 1
+-				 7000 0 0 3 &mpic 1 1
+-				 7000 0 0 4 &mpic 2 1
++				 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++				 0x7000 0x0 0x0 0x2 &mpic 0x4 0x1
++				 0x7000 0x0 0x0 0x3 &mpic 0x1 0x1
++				 0x7000 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 				/* IDSEL 15 */
+-				 7800 0 0 1 &mpic 2 1
+-				 7800 0 0 2 &mpic 3 1
+-				 7800 0 0 3 &mpic 4 1
+-				 7800 0 0 4 &mpic 1 1
++				 0x7800 0x0 0x0 0x1 &mpic 0x2 0x1
++				 0x7800 0x0 0x0 0x2 &mpic 0x3 0x1
++				 0x7800 0x0 0x0 0x3 &mpic 0x4 0x1
++				 0x7800 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 				/* IDSEL 18 */
+-				 9000 0 0 1 &mpic 1 1
+-				 9000 0 0 2 &mpic 2 1
+-				 9000 0 0 3 &mpic 3 1
+-				 9000 0 0 4 &mpic 4 1
++				 0x9000 0x0 0x0 0x1 &mpic 0x1 0x1
++				 0x9000 0x0 0x0 0x2 &mpic 0x2 0x1
++				 0x9000 0x0 0x0 0x3 &mpic 0x3 0x1
++				 0x9000 0x0 0x0 0x4 &mpic 0x4 0x1
+ 
+ 				/* IDSEL 19 */
+-				 9800 0 0 1 &mpic 4 1
+-				 9800 0 0 2 &mpic 1 1
+-				 9800 0 0 3 &mpic 2 1
+-				 9800 0 0 4 &mpic 3 1
++				 0x9800 0x0 0x0 0x1 &mpic 0x4 0x1
++				 0x9800 0x0 0x0 0x2 &mpic 0x1 0x1
++				 0x9800 0x0 0x0 0x3 &mpic 0x2 0x1
++				 0x9800 0x0 0x0 0x4 &mpic 0x3 0x1
+ 
+ 				/* IDSEL 20 */
+-				 a000 0 0 1 &mpic 3 1
+-				 a000 0 0 2 &mpic 4 1
+-				 a000 0 0 3 &mpic 1 1
+-				 a000 0 0 4 &mpic 2 1
++				 0xa000 0x0 0x0 0x1 &mpic 0x3 0x1
++				 0xa000 0x0 0x0 0x2 &mpic 0x4 0x1
++				 0xa000 0x0 0x0 0x3 &mpic 0x1 0x1
++				 0xa000 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 				/* IDSEL 21 */
+-				 a800 0 0 1 &mpic 2 1
+-				 a800 0 0 2 &mpic 3 1
+-				 a800 0 0 3 &mpic 4 1
+-				 a800 0 0 4 &mpic 1 1>;
++				 0xa800 0x0 0x0 0x1 &mpic 0x2 0x1
++				 0xa800 0x0 0x0 0x2 &mpic 0x3 0x1
++				 0xa800 0x0 0x0 0x3 &mpic 0x4 0x1
++				 0xa800 0x0 0x0 0x4 &mpic 0x1 0x1>;
+ 
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <18 2>;
++		interrupts = <24 2>;
+ 		bus-range = <0 0>;
+-		ranges = <02000000 0 80000000 80000000 0 20000000
+-			  01000000 0 00000000 e2000000 0 01000000>;
++		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe2000000 0x0 0x1000000>;
+ 	};
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
+index 97bc048..a025a8e 100644
+--- a/arch/powerpc/boot/dts/mpc8568mds.dts
++++ b/arch/powerpc/boot/dts/mpc8568mds.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC8568E MDS Device Tree Source
+  *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007, 2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,10 +9,7 @@
+  * option) any later version.
+  */
+ 
+-
+-/*
+-/memreserve/	00000000 1000000;
+-*/
++/dts-v1/;
+ 
+ / {
+ 	model = "MPC8568EMDS";
+@@ -37,11 +34,11 @@
+ 
+ 		PowerPC,8568 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K
+-			i-cache-size = <8000>;		// L1, 32K
++			reg = <0x0>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K
++			i-cache-size = <0x8000>;		// L1, 32K
+ 			timebase-frequency = <0>;
+ 			bus-frequency = <0>;
+ 			clock-frequency = <0>;
+@@ -50,36 +47,36 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 10000000>;
++		reg = <0x0 0x10000000>;
+ 	};
+ 
+ 	bcsr at f8000000 {
+ 		device_type = "board-control";
+-		reg = <f8000000 8000>;
++		reg = <0xf8000000 0x8000>;
+ 	};
+ 
+ 	soc8568 at e0000000 {
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <0 e0000000 00100000>;
+-		reg = <e0000000 00001000>;
++		ranges = <0x0 0xe0000000 0x100000>;
++		reg = <0xe0000000 0x1000>;
+ 		bus-frequency = <0>;
+ 
+ 		memory-controller at 2000 {
+ 			compatible = "fsl,8568-memory-controller";
+-			reg = <2000 1000>;
++			reg = <0x2000 0x1000>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <12 2>;
++			interrupts = <18 2>;
+ 		};
+ 
+ 		l2-cache-controller at 20000 {
+ 			compatible = "fsl,8568-l2-cache-controller";
+-			reg = <20000 1000>;
+-			cache-line-size = <20>;	// 32 bytes
+-			cache-size = <80000>;	// L2, 512K
++			reg = <0x20000 0x1000>;
++			cache-line-size = <32>;	// 32 bytes
++			cache-size = <0x80000>;	// L2, 512K
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <10 2>;
++			interrupts = <16 2>;
+ 		};
+ 
+ 		i2c at 3000 {
+@@ -87,14 +84,14 @@
+ 			#size-cells = <0>;
+ 			cell-index = <0>;
+ 			compatible = "fsl-i2c";
+-			reg = <3000 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3000 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 
+ 			rtc at 68 {
+ 				compatible = "dallas,ds1374";
+-				reg = <68>;
++				reg = <0x68>;
+ 			};
+ 		};
+ 
+@@ -103,8 +100,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <1>;
+ 			compatible = "fsl-i2c";
+-			reg = <3100 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3100 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -113,30 +110,30 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			compatible = "fsl,gianfar-mdio";
+-			reg = <24520 20>;
++			reg = <0x24520 0x20>;
+ 
+ 			phy0: ethernet-phy at 7 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <1 1>;
+-				reg = <7>;
++				reg = <0x7>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy1: ethernet-phy at 1 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <2 1>;
+-				reg = <1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy2: ethernet-phy at 2 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <1 1>;
+-				reg = <2>;
++				reg = <0x2>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			phy3: ethernet-phy at 3 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <2 1>;
+-				reg = <3>;
++				reg = <0x3>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -146,9 +143,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <24000 1000>;
++			reg = <0x24000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+- 			interrupts = <1d 2 1e 2 22 2>;
++ 			interrupts = <29 2 30 2 34 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy2>;
+ 		};
+@@ -158,9 +155,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <25000 1000>;
++			reg = <0x25000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+- 			interrupts = <23 2 24 2 28 2>;
++ 			interrupts = <35 2 36 2 40 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy3>;
+ 		};
+@@ -169,15 +166,15 @@
+ 			cell-index = <0>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4500 100>;
++			reg = <0x4500 0x100>;
+ 			clock-frequency = <0>;
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+ 		global-utilities at e0000 {	//global utilities block
+ 			compatible = "fsl,mpc8548-guts";
+-			reg = <e0000 1000>;
++			reg = <0xe0000 0x1000>;
+ 			fsl,has-rstcr;
+ 		};
+ 
+@@ -185,9 +182,9 @@
+ 			cell-index = <1>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4600 100>;
++			reg = <0x4600 0x100>;
+ 			clock-frequency = <0>;
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -195,13 +192,13 @@
+ 			device_type = "crypto";
+ 			model = "SEC2";
+ 			compatible = "talitos";
+-			reg = <30000 f000>;
+-			interrupts = <2d 2>;
++			reg = <0x30000 0xf000>;
++			interrupts = <45 2>;
+ 			interrupt-parent = <&mpic>;
+ 			num-channels = <4>;
+-			channel-fifo-len = <18>;
+-			exec-units-mask = <000000fe>;
+-			descriptor-types-mask = <012b0ebf>;
++			channel-fifo-len = <24>;
++			exec-units-mask = <0xfe>;
++			descriptor-types-mask = <0x12b0ebf>;
+ 		};
+ 
+ 		mpic: pic at 40000 {
+@@ -209,73 +206,73 @@
+ 			interrupt-controller;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+-			reg = <40000 40000>;
++			reg = <0x40000 0x40000>;
+ 			compatible = "chrp,open-pic";
+ 			device_type = "open-pic";
+                         big-endian;
+ 		};
+ 
+ 		par_io at e0100 {
+-			reg = <e0100 100>;
++			reg = <0xe0100 0x100>;
+ 			device_type = "par_io";
+ 			num-ports = <7>;
+ 
+ 			pio1: ucc_pin at 01 {
+ 				pio-map = <
+ 			/* port  pin  dir  open_drain  assignment  has_irq */
+-					4  0a  1  0  2  0 	/* TxD0 */
+-					4  09  1  0  2  0 	/* TxD1 */
+-					4  08  1  0  2  0 	/* TxD2 */
+-					4  07  1  0  2  0 	/* TxD3 */
+-					4  17  1  0  2  0 	/* TxD4 */
+-					4  16  1  0  2  0 	/* TxD5 */
+-					4  15  1  0  2  0 	/* TxD6 */
+-					4  14  1  0  2  0 	/* TxD7 */
+-					4  0f  2  0  2  0 	/* RxD0 */
+-					4  0e  2  0  2  0 	/* RxD1 */
+-					4  0d  2  0  2  0 	/* RxD2 */
+-					4  0c  2  0  2  0 	/* RxD3 */
+-					4  1d  2  0  2  0 	/* RxD4 */
+-					4  1c  2  0  2  0 	/* RxD5 */
+-					4  1b  2  0  2  0 	/* RxD6 */
+-					4  1a  2  0  2  0 	/* RxD7 */
+-					4  0b  1  0  2  0 	/* TX_EN */
+-					4  18  1  0  2  0 	/* TX_ER */
+-					4  10  2  0  2  0 	/* RX_DV */
+-					4  1e  2  0  2  0 	/* RX_ER */
+-					4  11  2  0  2  0 	/* RX_CLK */
+-					4  13  1  0  2  0 	/* GTX_CLK */
+-					1  1f  2  0  3  0>;	/* GTX125 */
++					0x4  0xa  0x1  0x0  0x2  0x0 	/* TxD0 */
++					0x4  0x9  0x1  0x0  0x2  0x0 	/* TxD1 */
++					0x4  0x8  0x1  0x0  0x2  0x0 	/* TxD2 */
++					0x4  0x7  0x1  0x0  0x2  0x0 	/* TxD3 */
++					0x4  0x17  0x1  0x0  0x2  0x0 	/* TxD4 */
++					0x4  0x16  0x1  0x0  0x2  0x0 	/* TxD5 */
++					0x4  0x15  0x1  0x0  0x2  0x0 	/* TxD6 */
++					0x4  0x14  0x1  0x0  0x2  0x0 	/* TxD7 */
++					0x4  0xf  0x2  0x0  0x2  0x0 	/* RxD0 */
++					0x4  0xe  0x2  0x0  0x2  0x0 	/* RxD1 */
++					0x4  0xd  0x2  0x0  0x2  0x0 	/* RxD2 */
++					0x4  0xc  0x2  0x0  0x2  0x0 	/* RxD3 */
++					0x4  0x1d  0x2  0x0  0x2  0x0 	/* RxD4 */
++					0x4  0x1c  0x2  0x0  0x2  0x0 	/* RxD5 */
++					0x4  0x1b  0x2  0x0  0x2  0x0 	/* RxD6 */
++					0x4  0x1a  0x2  0x0  0x2  0x0 	/* RxD7 */
++					0x4  0xb  0x1  0x0  0x2  0x0 	/* TX_EN */
++					0x4  0x18  0x1  0x0  0x2  0x0 	/* TX_ER */
++					0x4  0x10  0x2  0x0  0x2  0x0 	/* RX_DV */
++					0x4  0x1e  0x2  0x0  0x2  0x0 	/* RX_ER */
++					0x4  0x11  0x2  0x0  0x2  0x0 	/* RX_CLK */
++					0x4  0x13  0x1  0x0  0x2  0x0 	/* GTX_CLK */
++					0x1  0x1f  0x2  0x0  0x3  0x0>;	/* GTX125 */
+ 			};
+ 
+ 			pio2: ucc_pin at 02 {
+ 				pio-map = <
+ 			/* port  pin  dir  open_drain  assignment  has_irq */
+-					5  0a 1  0  2  0   /* TxD0 */
+-					5  09 1  0  2  0   /* TxD1 */
+-					5  08 1  0  2  0   /* TxD2 */
+-					5  07 1  0  2  0   /* TxD3 */
+-					5  17 1  0  2  0   /* TxD4 */
+-					5  16 1  0  2  0   /* TxD5 */
+-					5  15 1  0  2  0   /* TxD6 */
+-					5  14 1  0  2  0   /* TxD7 */
+-					5  0f 2  0  2  0   /* RxD0 */
+-					5  0e 2  0  2  0   /* RxD1 */
+-					5  0d 2  0  2  0   /* RxD2 */
+-					5  0c 2  0  2  0   /* RxD3 */
+-					5  1d 2  0  2  0   /* RxD4 */
+-					5  1c 2  0  2  0   /* RxD5 */
+-					5  1b 2  0  2  0   /* RxD6 */
+-					5  1a 2  0  2  0   /* RxD7 */
+-					5  0b 1  0  2  0   /* TX_EN */
+-					5  18 1  0  2  0   /* TX_ER */
+-					5  10 2  0  2  0   /* RX_DV */
+-					5  1e 2  0  2  0   /* RX_ER */
+-					5  11 2  0  2  0   /* RX_CLK */
+-					5  13 1  0  2  0   /* GTX_CLK */
+-					1  1f 2  0  3  0   /* GTX125 */
+-					4  06 3  0  2  0   /* MDIO */
+-					4  05 1  0  2  0>; /* MDC */
++					0x5  0xa 0x1  0x0  0x2  0x0   /* TxD0 */
++					0x5  0x9 0x1  0x0  0x2  0x0   /* TxD1 */
++					0x5  0x8 0x1  0x0  0x2  0x0   /* TxD2 */
++					0x5  0x7 0x1  0x0  0x2  0x0   /* TxD3 */
++					0x5  0x17 0x1  0x0  0x2  0x0   /* TxD4 */
++					0x5  0x16 0x1  0x0  0x2  0x0   /* TxD5 */
++					0x5  0x15 0x1  0x0  0x2  0x0   /* TxD6 */
++					0x5  0x14 0x1  0x0  0x2  0x0   /* TxD7 */
++					0x5  0xf 0x2  0x0  0x2  0x0   /* RxD0 */
++					0x5  0xe 0x2  0x0  0x2  0x0   /* RxD1 */
++					0x5  0xd 0x2  0x0  0x2  0x0   /* RxD2 */
++					0x5  0xc 0x2  0x0  0x2  0x0   /* RxD3 */
++					0x5  0x1d 0x2  0x0  0x2  0x0   /* RxD4 */
++					0x5  0x1c 0x2  0x0  0x2  0x0   /* RxD5 */
++					0x5  0x1b 0x2  0x0  0x2  0x0   /* RxD6 */
++					0x5  0x1a 0x2  0x0  0x2  0x0   /* RxD7 */
++					0x5  0xb 0x1  0x0  0x2  0x0   /* TX_EN */
++					0x5  0x18 0x1  0x0  0x2  0x0   /* TX_ER */
++					0x5  0x10 0x2  0x0  0x2  0x0   /* RX_DV */
++					0x5  0x1e 0x2  0x0  0x2  0x0   /* RX_ER */
++					0x5  0x11 0x2  0x0  0x2  0x0   /* RX_CLK */
++					0x5  0x13 0x1  0x0  0x2  0x0   /* GTX_CLK */
++					0x1  0x1f 0x2  0x0  0x3  0x0   /* GTX125 */
++					0x4  0x6 0x3  0x0  0x2  0x0   /* MDIO */
++					0x4  0x5 0x1  0x0  0x2  0x0>; /* MDC */
+ 			};
+ 		};
+ 	};
+@@ -285,28 +282,28 @@
+ 		#size-cells = <1>;
+ 		device_type = "qe";
+ 		compatible = "fsl,qe";
+-		ranges = <0 e0080000 00040000>;
+-		reg = <e0080000 480>;
++		ranges = <0x0 0xe0080000 0x40000>;
++		reg = <0xe0080000 0x480>;
+ 		brg-frequency = <0>;
+-		bus-frequency = <179A7B00>;
++		bus-frequency = <396000000>;
+ 
+ 		muram at 10000 {
+  			#address-cells = <1>;
+  			#size-cells = <1>;
+ 			compatible = "fsl,qe-muram", "fsl,cpm-muram";
+-			ranges = <0 00010000 0000c000>;
++			ranges = <0x0 0x10000 0x10000>;
+ 
+ 			data-only at 0 {
+ 				compatible = "fsl,qe-muram-data",
+ 					     "fsl,cpm-muram-data";
+-				reg = <0 c000>;
++				reg = <0x0 0x10000>;
+ 			};
+ 		};
+ 
+ 		spi at 4c0 {
+ 			cell-index = <0>;
+ 			compatible = "fsl,spi";
+-			reg = <4c0 40>;
++			reg = <0x4c0 0x40>;
+ 			interrupts = <2>;
+ 			interrupt-parent = <&qeic>;
+ 			mode = "cpu";
+@@ -315,7 +312,7 @@
+ 		spi at 500 {
+ 			cell-index = <1>;
+ 			compatible = "fsl,spi";
+-			reg = <500 40>;
++			reg = <0x500 0x40>;
+ 			interrupts = <1>;
+ 			interrupt-parent = <&qeic>;
+ 			mode = "cpu";
+@@ -324,11 +321,9 @@
+ 		enet2: ucc at 2000 {
+ 			device_type = "network";
+ 			compatible = "ucc_geth";
+-			model = "UCC";
+ 			cell-index = <1>;
+-			device-id = <1>;
+-			reg = <2000 200>;
+-			interrupts = <20>;
++			reg = <0x2000 0x200>;
++			interrupts = <32>;
+ 			interrupt-parent = <&qeic>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			rx-clock-name = "none";
+@@ -341,11 +336,9 @@
+ 		enet3: ucc at 3000 {
+ 			device_type = "network";
+ 			compatible = "ucc_geth";
+-			model = "UCC";
+ 			cell-index = <2>;
+-			device-id = <2>;
+-			reg = <3000 200>;
+-			interrupts = <21>;
++			reg = <0x3000 0x200>;
++			interrupts = <33>;
+ 			interrupt-parent = <&qeic>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			rx-clock-name = "none";
+@@ -358,7 +351,7 @@
+ 		mdio at 2120 {
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+-			reg = <2120 18>;
++			reg = <0x2120 0x18>;
+ 			compatible = "fsl,ucc-mdio";
+ 
+ 			/* These are the same PHYs as on
+@@ -366,25 +359,25 @@
+ 			qe_phy0: ethernet-phy at 07 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <1 1>;
+-				reg = <7>;
++				reg = <0x7>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			qe_phy1: ethernet-phy at 01 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <2 1>;
+-				reg = <1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			qe_phy2: ethernet-phy at 02 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <1 1>;
+-				reg = <2>;
++				reg = <0x2>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 			qe_phy3: ethernet-phy at 03 {
+ 				interrupt-parent = <&mpic>;
+ 				interrupts = <2 1>;
+-				reg = <3>;
++				reg = <0x3>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -394,9 +387,9 @@
+ 			compatible = "fsl,qe-ic";
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <1>;
+-			reg = <80 80>;
++			reg = <0x80 0x80>;
+ 			big-endian;
+-			interrupts = <2e 2 2e 2>; //high:30 low:30
++			interrupts = <46 2 46 2>; //high:30 low:30
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -404,30 +397,30 @@
+ 
+ 	pci0: pci at e0008000 {
+ 		cell-index = <0>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 			/* IDSEL 0x12 AD18 */
+-			9000 0 0 1 &mpic 5 1
+-			9000 0 0 2 &mpic 6 1
+-			9000 0 0 3 &mpic 7 1
+-			9000 0 0 4 &mpic 4 1
++			0x9000 0x0 0x0 0x1 &mpic 0x5 0x1
++			0x9000 0x0 0x0 0x2 &mpic 0x6 0x1
++			0x9000 0x0 0x0 0x3 &mpic 0x7 0x1
++			0x9000 0x0 0x0 0x4 &mpic 0x4 0x1
+ 
+ 			/* IDSEL 0x13 AD19 */
+-			9800 0 0 1 &mpic 6 1
+-			9800 0 0 2 &mpic 7 1
+-			9800 0 0 3 &mpic 4 1
+-			9800 0 0 4 &mpic 5 1>;
++			0x9800 0x0 0x0 0x1 &mpic 0x6 0x1
++			0x9800 0x0 0x0 0x2 &mpic 0x7 0x1
++			0x9800 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x9800 0x0 0x0 0x4 &mpic 0x5 0x1>;
+ 
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <18 2>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 80000000 80000000 0 20000000
+-			  01000000 0 00000000 e2000000 0 00800000>;
+-		clock-frequency = <3f940aa>;
++		interrupts = <24 2>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>;
++		clock-frequency = <66666666>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e0008000 1000>;
++		reg = <0xe0008000 0x1000>;
+ 		compatible = "fsl,mpc8540-pci";
+ 		device_type = "pci";
+ 	};
+@@ -435,39 +428,39 @@
+ 	/* PCI Express */
+ 	pci1: pcie at e000a000 {
+ 		cell-index = <2>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 
+ 			/* IDSEL 0x0 (PEX) */
+-			00000 0 0 1 &mpic 0 1
+-			00000 0 0 2 &mpic 1 1
+-			00000 0 0 3 &mpic 2 1
+-			00000 0 0 4 &mpic 3 1>;
++			00000 0x0 0x0 0x1 &mpic 0x0 0x1
++			00000 0x0 0x0 0x2 &mpic 0x1 0x1
++			00000 0x0 0x0 0x3 &mpic 0x2 0x1
++			00000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ 
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <1a 2>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 a0000000 a0000000 0 10000000
+-			  01000000 0 00000000 e2800000 0 00800000>;
+-		clock-frequency = <1fca055>;
++		interrupts = <26 2>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
++			  0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>;
++		clock-frequency = <33333333>;
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <e000a000 1000>;
++		reg = <0xe000a000 0x1000>;
+ 		compatible = "fsl,mpc8548-pcie";
+ 		device_type = "pci";
+ 		pcie at 0 {
+-			reg = <0 0 0 0 0>;
++			reg = <0x0 0x0 0x0 0x0 0x0>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+ 			device_type = "pci";
+-			ranges = <02000000 0 a0000000
+-				  02000000 0 a0000000
+-				  0 10000000
++			ranges = <0x2000000 0x0 0xa0000000
++				  0x2000000 0x0 0xa0000000
++				  0x0 0x10000000
+ 
+-				  01000000 0 00000000
+-				  01000000 0 00000000
+-				  0 00800000>;
++				  0x1000000 0x0 0x0
++				  0x1000000 0x0 0x0
++				  0x0 0x800000>;
+ 		};
+ 	};
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
+index db37214..66f27ab 100644
+--- a/arch/powerpc/boot/dts/mpc8572ds.dts
++++ b/arch/powerpc/boot/dts/mpc8572ds.dts
+@@ -1,7 +1,7 @@
+ /*
+  * MPC8572 DS Device Tree Source
+  *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007, 2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +9,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ / {
+ 	model = "fsl,MPC8572DS";
+ 	compatible = "fsl,MPC8572DS";
+@@ -33,11 +34,11 @@
+ 
+ 		PowerPC,8572 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K
+-			i-cache-size = <8000>;		// L1, 32K
++			reg = <0x0>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K
++			i-cache-size = <0x8000>;		// L1, 32K
+ 			timebase-frequency = <0>;
+ 			bus-frequency = <0>;
+ 			clock-frequency = <0>;
+@@ -45,11 +46,11 @@
+ 
+ 		PowerPC,8572 at 1 {
+ 			device_type = "cpu";
+-			reg = <1>;
+-			d-cache-line-size = <20>;	// 32 bytes
+-			i-cache-line-size = <20>;	// 32 bytes
+-			d-cache-size = <8000>;		// L1, 32K
+-			i-cache-size = <8000>;		// L1, 32K
++			reg = <0x1>;
++			d-cache-line-size = <32>;	// 32 bytes
++			i-cache-line-size = <32>;	// 32 bytes
++			d-cache-size = <0x8000>;		// L1, 32K
++			i-cache-size = <0x8000>;		// L1, 32K
+ 			timebase-frequency = <0>;
+ 			bus-frequency = <0>;
+ 			clock-frequency = <0>;
+@@ -58,38 +59,38 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 00000000>;	// Filled by U-Boot
++		reg = <0x0 0x0>;	// Filled by U-Boot
+ 	};
+ 
+ 	soc8572 at ffe00000 {
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <00000000 ffe00000 00100000>;
+-		reg = <ffe00000 00001000>;	// CCSRBAR & soc regs, remove once parse code for immrbase fixed
++		ranges = <0x0 0xffe00000 0x100000>;
++		reg = <0xffe00000 0x1000>;	// CCSRBAR & soc regs, remove once parse code for immrbase fixed
+ 		bus-frequency = <0>;		// Filled out by uboot.
+ 
+ 		memory-controller at 2000 {
+ 			compatible = "fsl,mpc8572-memory-controller";
+-			reg = <2000 1000>;
++			reg = <0x2000 0x1000>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <12 2>;
++			interrupts = <18 2>;
+ 		};
+ 
+ 		memory-controller at 6000 {
+ 			compatible = "fsl,mpc8572-memory-controller";
+-			reg = <6000 1000>;
++			reg = <0x6000 0x1000>;
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <12 2>;
++			interrupts = <18 2>;
+ 		};
+ 
+ 		l2-cache-controller at 20000 {
+ 			compatible = "fsl,mpc8572-l2-cache-controller";
+-			reg = <20000 1000>;
+-			cache-line-size = <20>;	// 32 bytes
+-			cache-size = <80000>;	// L2, 512K
++			reg = <0x20000 0x1000>;
++			cache-line-size = <32>;	// 32 bytes
++			cache-size = <0x80000>;	// L2, 512K
+ 			interrupt-parent = <&mpic>;
+-			interrupts = <10 2>;
++			interrupts = <16 2>;
+ 		};
+ 
+ 		i2c at 3000 {
+@@ -97,8 +98,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <0>;
+ 			compatible = "fsl-i2c";
+-			reg = <3000 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3000 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -108,8 +109,8 @@
+ 			#size-cells = <0>;
+ 			cell-index = <1>;
+ 			compatible = "fsl-i2c";
+-			reg = <3100 100>;
+-			interrupts = <2b 2>;
++			reg = <0x3100 0x100>;
++			interrupts = <43 2>;
+ 			interrupt-parent = <&mpic>;
+ 			dfsrr;
+ 		};
+@@ -118,27 +119,27 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			compatible = "fsl,gianfar-mdio";
+-			reg = <24520 20>;
++			reg = <0x24520 0x20>;
+ 
+ 			phy0: ethernet-phy at 0 {
+ 				interrupt-parent = <&mpic>;
+-				interrupts = <a 1>;
+-				reg = <0>;
++				interrupts = <10 1>;
++				reg = <0x0>;
+ 			};
+ 			phy1: ethernet-phy at 1 {
+ 				interrupt-parent = <&mpic>;
+-				interrupts = <a 1>;
+-				reg = <1>;
++				interrupts = <10 1>;
++				reg = <0x1>;
+ 			};
+ 			phy2: ethernet-phy at 2 {
+ 				interrupt-parent = <&mpic>;
+-				interrupts = <a 1>;
+-				reg = <2>;
++				interrupts = <10 1>;
++				reg = <0x2>;
+ 			};
+ 			phy3: ethernet-phy at 3 {
+ 				interrupt-parent = <&mpic>;
+-				interrupts = <a 1>;
+-				reg = <3>;
++				interrupts = <10 1>;
++				reg = <0x3>;
+ 			};
+ 		};
+ 
+@@ -147,9 +148,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <24000 1000>;
++			reg = <0x24000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1d 2 1e 2 22 2>;
++			interrupts = <29 2 30 2 34 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy0>;
+ 			phy-connection-type = "rgmii-id";
+@@ -160,9 +161,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <25000 1000>;
++			reg = <0x25000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <23 2 24 2 28 2>;
++			interrupts = <35 2 36 2 40 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy1>;
+ 			phy-connection-type = "rgmii-id";
+@@ -173,9 +174,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <26000 1000>;
++			reg = <0x26000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <1f 2 20 2 21 2>;
++			interrupts = <31 2 32 2 33 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy2>;
+ 			phy-connection-type = "rgmii-id";
+@@ -186,9 +187,9 @@
+ 			device_type = "network";
+ 			model = "eTSEC";
+ 			compatible = "gianfar";
+-			reg = <27000 1000>;
++			reg = <0x27000 0x1000>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+-			interrupts = <25 2 26 2 27 2>;
++			interrupts = <37 2 38 2 39 2>;
+ 			interrupt-parent = <&mpic>;
+ 			phy-handle = <&phy3>;
+ 			phy-connection-type = "rgmii-id";
+@@ -198,9 +199,9 @@
+ 			cell-index = <0>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4500 100>;
++			reg = <0x4500 0x100>;
+ 			clock-frequency = <0>;
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+@@ -208,15 +209,15 @@
+ 			cell-index = <1>;
+ 			device_type = "serial";
+ 			compatible = "ns16550";
+-			reg = <4600 100>;
++			reg = <0x4600 0x100>;
+ 			clock-frequency = <0>;
+-			interrupts = <2a 2>;
++			interrupts = <42 2>;
+ 			interrupt-parent = <&mpic>;
+ 		};
+ 
+ 		global-utilities at e0000 {	//global utilities block
+ 			compatible = "fsl,mpc8572-guts";
+-			reg = <e0000 1000>;
++			reg = <0xe0000 0x1000>;
+ 			fsl,has-rstcr;
+ 		};
+ 
+@@ -225,7 +226,7 @@
+ 			interrupt-controller;
+ 			#address-cells = <0>;
+ 			#interrupt-cells = <2>;
+-			reg = <40000 40000>;
++			reg = <0x40000 0x40000>;
+ 			compatible = "chrp,open-pic";
+ 			device_type = "open-pic";
+ 			big-endian;
+@@ -239,167 +240,167 @@
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <ffe08000 1000>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 80000000 80000000 0 20000000
+-			  01000000 0 00000000 ffc00000 0 00010000>;
+-		clock-frequency = <1fca055>;
++		reg = <0xffe08000 0x1000>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xffc00000 0x0 0x10000>;
++		clock-frequency = <33333333>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <18 2>;
+-		interrupt-map-mask = <ff00 0 0 7>;
++		interrupts = <24 2>;
++		interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 			/* IDSEL 0x11 func 0 - PCI slot 1 */
+-			8800 0 0 1 &mpic 2 1
+-			8800 0 0 2 &mpic 3 1
+-			8800 0 0 3 &mpic 4 1
+-			8800 0 0 4 &mpic 1 1
++			0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x11 func 1 - PCI slot 1 */
+-			8900 0 0 1 &mpic 2 1
+-			8900 0 0 2 &mpic 3 1
+-			8900 0 0 3 &mpic 4 1
+-			8900 0 0 4 &mpic 1 1
++			0x8900 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x8900 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x8900 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x8900 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x11 func 2 - PCI slot 1 */
+-			8a00 0 0 1 &mpic 2 1
+-			8a00 0 0 2 &mpic 3 1
+-			8a00 0 0 3 &mpic 4 1
+-			8a00 0 0 4 &mpic 1 1
++			0x8a00 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x8a00 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x8a00 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x8a00 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x11 func 3 - PCI slot 1 */
+-			8b00 0 0 1 &mpic 2 1
+-			8b00 0 0 2 &mpic 3 1
+-			8b00 0 0 3 &mpic 4 1
+-			8b00 0 0 4 &mpic 1 1
++			0x8b00 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x8b00 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x8b00 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x8b00 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x11 func 4 - PCI slot 1 */
+-			8c00 0 0 1 &mpic 2 1
+-			8c00 0 0 2 &mpic 3 1
+-			8c00 0 0 3 &mpic 4 1
+-			8c00 0 0 4 &mpic 1 1
++			0x8c00 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x8c00 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x8c00 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x8c00 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x11 func 5 - PCI slot 1 */
+-			8d00 0 0 1 &mpic 2 1
+-			8d00 0 0 2 &mpic 3 1
+-			8d00 0 0 3 &mpic 4 1
+-			8d00 0 0 4 &mpic 1 1
++			0x8d00 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x8d00 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x8d00 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x8d00 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x11 func 6 - PCI slot 1 */
+-			8e00 0 0 1 &mpic 2 1
+-			8e00 0 0 2 &mpic 3 1
+-			8e00 0 0 3 &mpic 4 1
+-			8e00 0 0 4 &mpic 1 1
++			0x8e00 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x8e00 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x8e00 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x8e00 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x11 func 7 - PCI slot 1 */
+-			8f00 0 0 1 &mpic 2 1
+-			8f00 0 0 2 &mpic 3 1
+-			8f00 0 0 3 &mpic 4 1
+-			8f00 0 0 4 &mpic 1 1
++			0x8f00 0x0 0x0 0x1 &mpic 0x2 0x1
++			0x8f00 0x0 0x0 0x2 &mpic 0x3 0x1
++			0x8f00 0x0 0x0 0x3 &mpic 0x4 0x1
++			0x8f00 0x0 0x0 0x4 &mpic 0x1 0x1
+ 
+ 			/* IDSEL 0x12 func 0 - PCI slot 2 */
+-			9000 0 0 1 &mpic 3 1
+-			9000 0 0 2 &mpic 4 1
+-			9000 0 0 3 &mpic 1 1
+-			9000 0 0 4 &mpic 2 1
++			0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x9000 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x9000 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x12 func 1 - PCI slot 2 */
+-			9100 0 0 1 &mpic 3 1
+-			9100 0 0 2 &mpic 4 1
+-			9100 0 0 3 &mpic 1 1
+-			9100 0 0 4 &mpic 2 1
++			0x9100 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x9100 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x9100 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x9100 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x12 func 2 - PCI slot 2 */
+-			9200 0 0 1 &mpic 3 1
+-			9200 0 0 2 &mpic 4 1
+-			9200 0 0 3 &mpic 1 1
+-			9200 0 0 4 &mpic 2 1
++			0x9200 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x9200 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x9200 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x9200 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x12 func 3 - PCI slot 2 */
+-			9300 0 0 1 &mpic 3 1
+-			9300 0 0 2 &mpic 4 1
+-			9300 0 0 3 &mpic 1 1
+-			9300 0 0 4 &mpic 2 1
++			0x9300 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x9300 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x9300 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x9300 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x12 func 4 - PCI slot 2 */
+-			9400 0 0 1 &mpic 3 1
+-			9400 0 0 2 &mpic 4 1
+-			9400 0 0 3 &mpic 1 1
+-			9400 0 0 4 &mpic 2 1
++			0x9400 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x9400 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x9400 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x9400 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x12 func 5 - PCI slot 2 */
+-			9500 0 0 1 &mpic 3 1
+-			9500 0 0 2 &mpic 4 1
+-			9500 0 0 3 &mpic 1 1
+-			9500 0 0 4 &mpic 2 1
++			0x9500 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x9500 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x9500 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x9500 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x12 func 6 - PCI slot 2 */
+-			9600 0 0 1 &mpic 3 1
+-			9600 0 0 2 &mpic 4 1
+-			9600 0 0 3 &mpic 1 1
+-			9600 0 0 4 &mpic 2 1
++			0x9600 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x9600 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x9600 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x9600 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			/* IDSEL 0x12 func 7 - PCI slot 2 */
+-			9700 0 0 1 &mpic 3 1
+-			9700 0 0 2 &mpic 4 1
+-			9700 0 0 3 &mpic 1 1
+-			9700 0 0 4 &mpic 2 1
++			0x9700 0x0 0x0 0x1 &mpic 0x3 0x1
++			0x9700 0x0 0x0 0x2 &mpic 0x4 0x1
++			0x9700 0x0 0x0 0x3 &mpic 0x1 0x1
++			0x9700 0x0 0x0 0x4 &mpic 0x2 0x1
+ 
+ 			// IDSEL 0x1c  USB
+-			e000 0 0 1 &i8259 c 2
+-			e100 0 0 2 &i8259 9 2
+-			e200 0 0 3 &i8259 a 2
+-			e300 0 0 4 &i8259 b 2
++			0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
++			0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
++			0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
++			0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+ 
+ 			// IDSEL 0x1d  Audio
+-			e800 0 0 1 &i8259 6 2
++			0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+ 
+ 			// IDSEL 0x1e Legacy
+-			f000 0 0 1 &i8259 7 2
+-			f100 0 0 1 &i8259 7 2
++			0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
++			0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+ 
+ 			// IDSEL 0x1f IDE/SATA
+-			f800 0 0 1 &i8259 e 2
+-			f900 0 0 1 &i8259 5 2
++			0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
++			0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+ 
+ 			>;
+ 
+ 		pcie at 0 {
+-			reg = <0 0 0 0 0>;
++			reg = <0x0 0x0 0x0 0x0 0x0>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+ 			device_type = "pci";
+-			ranges = <02000000 0 80000000
+-				  02000000 0 80000000
+-				  0 20000000
++			ranges = <0x2000000 0x0 0x80000000
++				  0x2000000 0x0 0x80000000
++				  0x0 0x20000000
+ 
+-				  01000000 0 00000000
+-				  01000000 0 00000000
+-				  0 00100000>;
++				  0x1000000 0x0 0x0
++				  0x1000000 0x0 0x0
++				  0x0 0x100000>;
+ 			uli1575 at 0 {
+-				reg = <0 0 0 0 0>;
++				reg = <0x0 0x0 0x0 0x0 0x0>;
+ 				#size-cells = <2>;
+ 				#address-cells = <3>;
+-				ranges = <02000000 0 80000000
+-					  02000000 0 80000000
+-					  0 20000000
++				ranges = <0x2000000 0x0 0x80000000
++					  0x2000000 0x0 0x80000000
++					  0x0 0x20000000
+ 
+-					  01000000 0 00000000
+-					  01000000 0 00000000
+-					  0 00100000>;
++					  0x1000000 0x0 0x0
++					  0x1000000 0x0 0x0
++					  0x0 0x100000>;
+ 				isa at 1e {
+ 					device_type = "isa";
+ 					#interrupt-cells = <2>;
+ 					#size-cells = <1>;
+ 					#address-cells = <2>;
+-					reg = <f000 0 0 0 0>;
+-					ranges = <1 0 01000000 0 0
+-						  00001000>;
++					reg = <0xf000 0x0 0x0 0x0 0x0>;
++					ranges = <0x1 0x0 0x1000000 0x0 0x0
++						  0x1000>;
+ 					interrupt-parent = <&i8259>;
+ 
+ 					i8259: interrupt-controller at 20 {
+-						reg = <1 20 2
+-						       1 a0 2
+-						       1 4d0 2>;
++						reg = <0x1 0x20 0x2
++						       0x1 0xa0 0x2
++						       0x1 0x4d0 0x2>;
+ 						interrupt-controller;
+ 						device_type = "interrupt-controller";
+ 						#address-cells = <0>;
+@@ -412,29 +413,29 @@
+ 					i8042 at 60 {
+ 						#size-cells = <0>;
+ 						#address-cells = <1>;
+-						reg = <1 60 1 1 64 1>;
+-						interrupts = <1 3 c 3>;
++						reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
++						interrupts = <1 3 12 3>;
+ 						interrupt-parent =
+ 							<&i8259>;
+ 
+ 						keyboard at 0 {
+-							reg = <0>;
++							reg = <0x0>;
+ 							compatible = "pnpPNP,303";
+ 						};
+ 
+ 						mouse at 1 {
+-							reg = <1>;
++							reg = <0x1>;
+ 							compatible = "pnpPNP,f03";
+ 						};
+ 					};
+ 
+ 					rtc at 70 {
+ 						compatible = "pnpPNP,b00";
+-						reg = <1 70 2>;
++						reg = <0x1 0x70 0x2>;
+ 					};
+ 
+ 					gpio at 400 {
+-						reg = <1 400 80>;
++						reg = <0x1 0x400 0x80>;
+ 					};
+ 				};
+ 			};
+@@ -449,33 +450,33 @@
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <ffe09000 1000>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 a0000000 a0000000 0 20000000
+-			  01000000 0 00000000 ffc10000 0 00010000>;
+-		clock-frequency = <1fca055>;
++		reg = <0xffe09000 0x1000>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xffc10000 0x0 0x10000>;
++		clock-frequency = <33333333>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <1a 2>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupts = <26 2>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 			/* IDSEL 0x0 */
+-			0000 0 0 1 &mpic 4 1
+-			0000 0 0 2 &mpic 5 1
+-			0000 0 0 3 &mpic 6 1
+-			0000 0 0 4 &mpic 7 1
++			0000 0x0 0x0 0x1 &mpic 0x4 0x1
++			0000 0x0 0x0 0x2 &mpic 0x5 0x1
++			0000 0x0 0x0 0x3 &mpic 0x6 0x1
++			0000 0x0 0x0 0x4 &mpic 0x7 0x1
+ 			>;
+ 		pcie at 0 {
+-			reg = <0 0 0 0 0>;
++			reg = <0x0 0x0 0x0 0x0 0x0>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+ 			device_type = "pci";
+-			ranges = <02000000 0 a0000000
+-				  02000000 0 a0000000
+-				  0 20000000
++			ranges = <0x2000000 0x0 0xa0000000
++				  0x2000000 0x0 0xa0000000
++				  0x0 0x20000000
+ 
+-				  01000000 0 00000000
+-				  01000000 0 00000000
+-				  0 00100000>;
++				  0x1000000 0x0 0x0
++				  0x1000000 0x0 0x0
++				  0x0 0x100000>;
+ 		};
+ 	};
+ 
+@@ -486,33 +487,33 @@
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		reg = <ffe0a000 1000>;
+-		bus-range = <0 ff>;
+-		ranges = <02000000 0 c0000000 c0000000 0 20000000
+-			  01000000 0 00000000 ffc20000 0 00010000>;
+-		clock-frequency = <1fca055>;
++		reg = <0xffe0a000 0x1000>;
++		bus-range = <0 255>;
++		ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
++			  0x1000000 0x0 0x0 0xffc20000 0x0 0x10000>;
++		clock-frequency = <33333333>;
+ 		interrupt-parent = <&mpic>;
+-		interrupts = <1b 2>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		interrupts = <27 2>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 			/* IDSEL 0x0 */
+-			0000 0 0 1 &mpic 0 1
+-			0000 0 0 2 &mpic 1 1
+-			0000 0 0 3 &mpic 2 1
+-			0000 0 0 4 &mpic 3 1
++			0000 0x0 0x0 0x1 &mpic 0x0 0x1
++			0000 0x0 0x0 0x2 &mpic 0x1 0x1
++			0000 0x0 0x0 0x3 &mpic 0x2 0x1
++			0000 0x0 0x0 0x4 &mpic 0x3 0x1
+ 			>;
+ 		pcie at 0 {
+-			reg = <0 0 0 0 0>;
++			reg = <0x0 0x0 0x0 0x0 0x0>;
+ 			#size-cells = <2>;
+ 			#address-cells = <3>;
+ 			device_type = "pci";
+-			ranges = <02000000 0 c0000000
+-				  02000000 0 c0000000
+-				  0 20000000
++			ranges = <0x2000000 0x0 0xc0000000
++				  0x2000000 0x0 0xc0000000
++				  0x0 0x20000000
+ 
+-				  01000000 0 00000000
+-				  01000000 0 00000000
+-				  0 00100000>;
++				  0x1000000 0x0 0x0
++				  0x1000000 0x0 0x0
++				  0x0 0x100000>;
+ 		};
+ 	};
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+index 79385bc..7f9b999 100644
+--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
++++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+@@ -13,7 +13,7 @@
+ 
+ / {
+ 	model = "MPC8641HPCN";
+-	compatible = "mpc86xx";
++	compatible = "fsl,mpc8641hpcn";
+ 	#address-cells = <1>;
+ 	#size-cells = <1>;
+ 
+diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
+index daf9433..765e43c 100644
+--- a/arch/powerpc/boot/dts/mpc866ads.dts
++++ b/arch/powerpc/boot/dts/mpc866ads.dts
+@@ -2,6 +2,7 @@
+  * MPC866 ADS Device Tree Source
+  *
+  * Copyright 2006 MontaVista Software, Inc.
++ * Copyright 2008 Freescale Semiconductor, Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +10,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ 
+ / {
+ 	model = "MPC866ADS";
+@@ -22,37 +24,37 @@
+ 
+ 		PowerPC,866 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <10>;	// 16 bytes
+-			i-cache-line-size = <10>;	// 16 bytes
+-			d-cache-size = <2000>;		// L1, 8K
+-			i-cache-size = <4000>;		// L1, 16K
++			reg = <0x0>;
++			d-cache-line-size = <16>;	// 16 bytes
++			i-cache-line-size = <16>;	// 16 bytes
++			d-cache-size = <0x2000>;		// L1, 8K
++			i-cache-size = <0x4000>;		// L1, 16K
+ 			timebase-frequency = <0>;
+ 			bus-frequency = <0>;
+ 			clock-frequency = <0>;
+-			interrupts = <f 2>;	// decrementer interrupt
++			interrupts = <15 2>;	// decrementer interrupt
+ 			interrupt-parent = <&PIC>;
+ 		};
+ 	};
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 800000>;
++		reg = <0x0 0x800000>;
+ 	};
+ 
+ 	localbus at ff000100 {
+ 		compatible = "fsl,mpc866-localbus", "fsl,pq1-localbus";
+ 		#address-cells = <2>;
+ 		#size-cells = <1>;
+-		reg = <ff000100 40>;
++		reg = <0xff000100 0x40>;
+ 
+ 		ranges = <
+-			1 0 ff080000 00008000
+-			5 0 ff0a0000 00008000
++			0x1 0x0 0xff080000 0x8000
++			0x5 0x0 0xff0a0000 0x8000
+ 		>;
+ 
+ 		board-control at 1,0 {
+-			reg = <1 0 20 5 300 4>;
++			reg = <0x1 0x0 0x20 0x5 0x300 0x4>;
+ 			compatible = "fsl,mpc866ads-bcsr";
+ 		};
+ 	};
+@@ -61,17 +63,17 @@
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <0 ff000000 00100000>;
+-		reg = <ff000000 00000200>;
++		ranges = <0x0 0xff000000 0x100000>;
++		reg = <0xff000000 0x200>;
+ 		bus-frequency = <0>;
+ 
+ 		mdio at e00 {
+ 			compatible = "fsl,mpc866-fec-mdio", "fsl,pq1-fec-mdio";
+-			reg = <e00 188>;
++			reg = <0xe00 0x188>;
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			PHY: ethernet-phy at f {
+-				reg = <f>;
++				reg = <0xf>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -80,7 +82,7 @@
+ 			device_type = "network";
+ 			compatible = "fsl,mpc866-fec-enet",
+ 			             "fsl,pq1-fec-enet";
+-			reg = <e00 188>;
++			reg = <0xe00 0x188>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			interrupts = <3 1>;
+ 			interrupt-parent = <&PIC>;
+@@ -91,7 +93,7 @@
+ 		PIC: pic at 0 {
+ 			interrupt-controller;
+ 			#interrupt-cells = <2>;
+-			reg = <0 24>;
++			reg = <0x0 0x24>;
+ 			compatible = "fsl,mpc866-pic", "fsl,pq1-pic";
+ 		};
+ 
+@@ -100,7 +102,7 @@
+ 			#size-cells = <1>;
+ 			compatible = "fsl,mpc866-cpm", "fsl,cpm1";
+ 			ranges;
+-			reg = <9c0 40>;
++			reg = <0x9c0 0x40>;
+ 			brg-frequency = <0>;
+ 			interrupts = <0 2>;	// cpm error interrupt
+ 			interrupt-parent = <&CPM_PIC>;
+@@ -108,11 +110,11 @@
+ 			muram at 2000 {
+ 				#address-cells = <1>;
+ 				#size-cells = <1>;
+-				ranges = <0 2000 2000>;
++				ranges = <0x0 0x2000 0x2000>;
+ 
+ 				data at 0 {
+ 					compatible = "fsl,cpm-muram-data";
+-					reg = <0 1c00>;
++					reg = <0x0 0x1c00>;
+ 				};
+ 			};
+ 
+@@ -120,7 +122,7 @@
+ 				compatible = "fsl,mpc866-brg",
+ 					     "fsl,cpm1-brg",
+ 					     "fsl,cpm-brg";
+-				reg = <9f0 10>;
++				reg = <0x9f0 0x10>;
+ 				clock-frequency = <0>;
+ 			};
+ 
+@@ -130,7 +132,7 @@
+ 				#interrupt-cells = <1>;
+ 				interrupts = <5 2 0 2>;
+ 				interrupt-parent = <&PIC>;
+-				reg = <930 20>;
++				reg = <0x930 0x20>;
+ 				compatible = "fsl,mpc866-cpm-pic",
+ 				             "fsl,cpm1-pic";
+ 			};
+@@ -140,31 +142,31 @@
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc866-smc-uart",
+ 				             "fsl,cpm1-smc-uart";
+-				reg = <a80 10 3e80 40>;
++				reg = <0xa80 0x10 0x3e80 0x40>;
+ 				interrupts = <4>;
+ 				interrupt-parent = <&CPM_PIC>;
+ 				fsl,cpm-brg = <1>;
+-				fsl,cpm-command = <0090>;
++				fsl,cpm-command = <0x90>;
+ 			};
+ 
+ 			serial at a90 {
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc866-smc-uart",
+ 				             "fsl,cpm1-smc-uart";
+-				reg = <a90 10 3f80 40>;
++				reg = <0xa90 0x10 0x3f80 0x40>;
+ 				interrupts = <3>;
+ 				interrupt-parent = <&CPM_PIC>;
+ 				fsl,cpm-brg = <2>;
+-				fsl,cpm-command = <00d0>;
++				fsl,cpm-command = <0xd0>;
+ 			};
+ 
+ 			ethernet at a00 {
+ 				device_type = "network";
+ 				compatible = "fsl,mpc866-scc-enet",
+ 				             "fsl,cpm1-scc-enet";
+-				reg = <a00 18 3c00 100>;
++				reg = <0xa00 0x18 0x3c00 0x100>;
+ 				local-mac-address = [ 00 00 00 00 00 00 ];
+-				interrupts = <1e>;
++				interrupts = <30>;
+ 				interrupt-parent = <&CPM_PIC>;
+ 				fsl,cpm-command = <0000>;
+ 				linux,network-index = <1>;
+diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
+index d84a012..9895043 100644
+--- a/arch/powerpc/boot/dts/mpc885ads.dts
++++ b/arch/powerpc/boot/dts/mpc885ads.dts
+@@ -2,7 +2,7 @@
+  * MPC885 ADS Device Tree Source
+  *
+  * Copyright 2006 MontaVista Software, Inc.
+- * Copyright 2007 Freescale Semiconductor, Inc.
++ * Copyright 2007,2008 Freescale Semiconductor, Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -10,6 +10,7 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
+ 
+ / {
+ 	model = "MPC885ADS";
+@@ -23,45 +24,45 @@
+ 
+ 		PowerPC,885 at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <d#16>;
+-			i-cache-line-size = <d#16>;
+-			d-cache-size = <d#8192>;
+-			i-cache-size = <d#8192>;
++			reg = <0x0>;
++			d-cache-line-size = <16>;
++			i-cache-line-size = <16>;
++			d-cache-size = <8192>;
++			i-cache-size = <8192>;
+ 			timebase-frequency = <0>;
+ 			bus-frequency = <0>;
+ 			clock-frequency = <0>;
+-			interrupts = <f 2>;	// decrementer interrupt
++			interrupts = <15 2>;	// decrementer interrupt
+ 			interrupt-parent = <&PIC>;
+ 		};
+ 	};
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <0 0>;
++		reg = <0x0 0x0>;
+ 	};
+ 
+ 	localbus at ff000100 {
+ 		compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus";
+ 		#address-cells = <2>;
+ 		#size-cells = <1>;
+-		reg = <ff000100 40>;
++		reg = <0xff000100 0x40>;
+ 
+ 		ranges = <
+-			0 0 fe000000 00800000
+-			1 0 ff080000 00008000
+-			5 0 ff0a0000 00008000
++			0x0 0x0 0xfe000000 0x800000
++			0x1 0x0 0xff080000 0x8000
++			0x5 0x0 0xff0a0000 0x8000
+ 		>;
+ 
+ 		flash at 0,0 {
+ 			compatible = "jedec-flash";
+-			reg = <0 0 800000>;
++			reg = <0x0 0x0 0x800000>;
+ 			bank-width = <4>;
+ 			device-width = <1>;
+ 		};
+ 
+ 		board-control at 1,0 {
+-			reg = <1 0 20 5 300 4>;
++			reg = <0x1 0x0 0x20 0x5 0x300 0x4>;
+ 			compatible = "fsl,mpc885ads-bcsr";
+ 		};
+ 	};
+@@ -71,30 +72,30 @@
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+-		ranges = <0 ff000000 00004000>;
++		ranges = <0x0 0xff000000 0x4000>;
+ 		bus-frequency = <0>;
+ 
+ 		// Temporary -- will go away once kernel uses ranges for get_immrbase().
+-		reg = <ff000000 4000>;
++		reg = <0xff000000 0x4000>;
+ 
+ 		mdio at e00 {
+ 			compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio";
+-			reg = <e00 188>;
++			reg = <0xe00 0x188>;
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 
+ 			PHY0: ethernet-phy at 0 {
+-				reg = <0>;
++				reg = <0x0>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 
+ 			PHY1: ethernet-phy at 1 {
+-				reg = <1>;
++				reg = <0x1>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 
+ 			PHY2: ethernet-phy at 2 {
+-				reg = <2>;
++				reg = <0x2>;
+ 				device_type = "ethernet-phy";
+ 			};
+ 		};
+@@ -103,7 +104,7 @@
+ 			device_type = "network";
+ 			compatible = "fsl,mpc885-fec-enet",
+ 			             "fsl,pq1-fec-enet";
+-			reg = <e00 188>;
++			reg = <0xe00 0x188>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			interrupts = <3 1>;
+ 			interrupt-parent = <&PIC>;
+@@ -115,7 +116,7 @@
+ 			device_type = "network";
+ 			compatible = "fsl,mpc885-fec-enet",
+ 			             "fsl,pq1-fec-enet";
+-			reg = <1e00 188>;
++			reg = <0x1e00 0x188>;
+ 			local-mac-address = [ 00 00 00 00 00 00 ];
+ 			interrupts = <7 1>;
+ 			interrupt-parent = <&PIC>;
+@@ -126,7 +127,7 @@
+ 		PIC: interrupt-controller at 0 {
+ 			interrupt-controller;
+ 			#interrupt-cells = <2>;
+-			reg = <0 24>;
++			reg = <0x0 0x24>;
+ 			compatible = "fsl,mpc885-pic", "fsl,pq1-pic";
+ 		};
+ 
+@@ -136,29 +137,29 @@
+ 			#size-cells = <2>;
+ 			compatible = "fsl,pq-pcmcia";
+ 			device_type = "pcmcia";
+-			reg = <80 80>;
++			reg = <0x80 0x80>;
+ 			interrupt-parent = <&PIC>;
+-			interrupts = <d 1>;
++			interrupts = <13 1>;
+ 		};
+ 
+ 		cpm at 9c0 {
+ 			#address-cells = <1>;
+ 			#size-cells = <1>;
+ 			compatible = "fsl,mpc885-cpm", "fsl,cpm1";
+-			command-proc = <9c0>;
++			command-proc = <0x9c0>;
+ 			interrupts = <0>;	// cpm error interrupt
+ 			interrupt-parent = <&CPM_PIC>;
+-			reg = <9c0 40>;
++			reg = <0x9c0 0x40>;
+ 			ranges;
+ 
+ 			muram at 2000 {
+ 				#address-cells = <1>;
+ 				#size-cells = <1>;
+-				ranges = <0 2000 2000>;
++				ranges = <0x0 0x2000 0x2000>;
+ 
+ 				data at 0 {
+ 					compatible = "fsl,cpm-muram-data";
+-					reg = <0 1c00>;
++					reg = <0x0 0x1c00>;
+ 				};
+ 			};
+ 
+@@ -167,7 +168,7 @@
+ 				             "fsl,cpm1-brg",
+ 				             "fsl,cpm-brg";
+ 				clock-frequency = <0>;
+-				reg = <9f0 10>;
++				reg = <0x9f0 0x10>;
+ 			};
+ 
+ 			CPM_PIC: interrupt-controller at 930 {
+@@ -175,7 +176,7 @@
+ 				#interrupt-cells = <1>;
+ 				interrupts = <5 2 0 2>;
+ 				interrupt-parent = <&PIC>;
+-				reg = <930 20>;
++				reg = <0x930 0x20>;
+ 				compatible = "fsl,mpc885-cpm-pic",
+ 				             "fsl,cpm1-pic";
+ 			};
+@@ -184,34 +185,34 @@
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc885-smc-uart",
+ 				             "fsl,cpm1-smc-uart";
+-				reg = <a80 10 3e80 40>;
++				reg = <0xa80 0x10 0x3e80 0x40>;
+ 				interrupts = <4>;
+ 				interrupt-parent = <&CPM_PIC>;
+ 				fsl,cpm-brg = <1>;
+-				fsl,cpm-command = <0090>;
++				fsl,cpm-command = <0x90>;
+ 			};
+ 
+ 			serial at a90 {
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc885-smc-uart",
+ 				             "fsl,cpm1-smc-uart";
+-				reg = <a90 10 3f80 40>;
++				reg = <0xa90 0x10 0x3f80 0x40>;
+ 				interrupts = <3>;
+ 				interrupt-parent = <&CPM_PIC>;
+ 				fsl,cpm-brg = <2>;
+-				fsl,cpm-command = <00d0>;
++				fsl,cpm-command = <0xd0>;
+ 			};
+ 
+ 			ethernet at a40 {
+ 				device_type = "network";
+ 				compatible = "fsl,mpc885-scc-enet",
+ 				             "fsl,cpm1-scc-enet";
+-				reg = <a40 18 3e00 100>;
++				reg = <0xa40 0x18 0x3e00 0x100>;
+ 				local-mac-address = [ 00 00 00 00 00 00 ];
+-				interrupts = <1c>;
++				interrupts = <28>;
+ 				interrupt-parent = <&CPM_PIC>;
+ 				phy-handle = <&PHY2>;
+-				fsl,cpm-command = <0080>;
++				fsl,cpm-command = <0x80>;
+ 				linux,network-index = <2>;
+ 			};
+ 		};
+diff --git a/arch/powerpc/boot/dts/pq2fads.dts b/arch/powerpc/boot/dts/pq2fads.dts
+index 2d56492..b2d6109 100644
+--- a/arch/powerpc/boot/dts/pq2fads.dts
++++ b/arch/powerpc/boot/dts/pq2fads.dts
+@@ -1,7 +1,7 @@
+ /*
+  * Device Tree for the PQ2FADS-ZU board with an MPC8280 chip.
+  *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007,2008 Freescale Semiconductor Inc.
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -9,6 +9,8 @@
+  * option) any later version.
+  */
+ 
++/dts-v1/;
++
+ / {
+ 	model = "pq2fads";
+ 	compatible = "fsl,pq2fads";
+@@ -21,11 +23,11 @@
+ 
+ 		cpu at 0 {
+ 			device_type = "cpu";
+-			reg = <0>;
+-			d-cache-line-size = <d#32>;
+-			i-cache-line-size = <d#32>;
+-			d-cache-size = <d#16384>;
+-			i-cache-size = <d#16384>;
++			reg = <0x0>;
++			d-cache-line-size = <32>;
++			i-cache-line-size = <32>;
++			d-cache-size = <16384>;
++			i-cache-size = <16384>;
+ 			timebase-frequency = <0>;
+ 			clock-frequency = <0>;
+ 		};
+@@ -33,7 +35,7 @@
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <0 0>;
++		reg = <0x0 0x0>;
+ 	};
+ 
+ 	localbus at f0010100 {
+@@ -41,67 +43,67 @@
+ 		             "fsl,pq2-localbus";
+ 		#address-cells = <2>;
+ 		#size-cells = <1>;
+-		reg = <f0010100 60>;
++		reg = <0xf0010100 0x60>;
+ 
+-		ranges = <0 0 fe000000 00800000
+-		          1 0 f4500000 00008000
+-		          8 0 f8200000 00008000>;
++		ranges = <0x0 0x0 0xfe000000 0x800000
++		          0x1 0x0 0xf4500000 0x8000
++		          0x8 0x0 0xf8200000 0x8000>;
+ 
+ 		flash at 0,0 {
+ 			compatible = "jedec-flash";
+-			reg = <0 0 800000>;
++			reg = <0x0 0x0 0x800000>;
+ 			bank-width = <4>;
+ 			device-width = <1>;
+ 		};
+ 
+ 		bcsr at 1,0 {
+-			reg = <1 0 20>;
++			reg = <0x1 0x0 0x20>;
+ 			compatible = "fsl,pq2fads-bcsr";
+ 		};
+ 
+ 		PCI_PIC: pic at 8,0 {
+ 			#interrupt-cells = <1>;
+ 			interrupt-controller;
+-			reg = <8 0 8>;
++			reg = <0x8 0x0 0x8>;
+ 			compatible = "fsl,pq2ads-pci-pic";
+ 			interrupt-parent = <&PIC>;
+-			interrupts = <18 8>;
++			interrupts = <24 8>;
+ 		};
+ 	};
+ 
+ 	pci at f0010800 {
+ 		device_type = "pci";
+-		reg = <f0010800 10c f00101ac 8 f00101c4 8>;
++		reg = <0xf0010800 0x10c 0xf00101ac 0x8 0xf00101c4 0x8>;
+ 		compatible = "fsl,mpc8280-pci", "fsl,pq2-pci";
+ 		#interrupt-cells = <1>;
+ 		#size-cells = <2>;
+ 		#address-cells = <3>;
+-		clock-frequency = <d#66000000>;
+-		interrupt-map-mask = <f800 0 0 7>;
++		clock-frequency = <66000000>;
++		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 		interrupt-map = <
+ 		                /* IDSEL 0x16 */
+-		                 b000 0 0 1 &PCI_PIC 0
+-		                 b000 0 0 2 &PCI_PIC 1
+-		                 b000 0 0 3 &PCI_PIC 2
+-		                 b000 0 0 4 &PCI_PIC 3
++		                 0xb000 0x0 0x0 0x1 &PCI_PIC 0
++		                 0xb000 0x0 0x0 0x2 &PCI_PIC 1
++		                 0xb000 0x0 0x0 0x3 &PCI_PIC 2
++		                 0xb000 0x0 0x0 0x4 &PCI_PIC 3
+ 
+ 		                /* IDSEL 0x17 */
+-		                 b800 0 0 1 &PCI_PIC 4
+-		                 b800 0 0 2 &PCI_PIC 5
+-		                 b800 0 0 3 &PCI_PIC 6
+-		                 b800 0 0 4 &PCI_PIC 7
++		                 0xb800 0x0 0x0 0x1 &PCI_PIC 4
++		                 0xb800 0x0 0x0 0x2 &PCI_PIC 5
++		                 0xb800 0x0 0x0 0x3 &PCI_PIC 6
++		                 0xb800 0x0 0x0 0x4 &PCI_PIC 7
+ 
+ 		                /* IDSEL 0x18 */
+-		                 c000 0 0 1 &PCI_PIC 8
+-		                 c000 0 0 2 &PCI_PIC 9
+-		                 c000 0 0 3 &PCI_PIC a
+-		                 c000 0 0 4 &PCI_PIC b>;
++		                 0xc000 0x0 0x0 0x1 &PCI_PIC 8
++		                 0xc000 0x0 0x0 0x2 &PCI_PIC 9
++		                 0xc000 0x0 0x0 0x3 &PCI_PIC 10
++		                 0xc000 0x0 0x0 0x4 &PCI_PIC 11>;
+ 
+ 		interrupt-parent = <&PIC>;
+-		interrupts = <12 8>;
+-		ranges = <42000000 0 80000000 80000000 0 20000000
+-		          02000000 0 a0000000 a0000000 0 20000000
+-		          01000000 0 00000000 f6000000 0 02000000>;
++		interrupts = <18 8>;
++		ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++		          0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++		          0x1000000 0x0 0x0 0xf6000000 0x0 0x2000000>;
+ 	};
+ 
+ 	soc at f0000000 {
+@@ -109,27 +111,27 @@
+ 		#size-cells = <1>;
+ 		device_type = "soc";
+ 		compatible = "fsl,mpc8280", "fsl,pq2-soc";
+-		ranges = <00000000 f0000000 00053000>;
++		ranges = <0x0 0xf0000000 0x53000>;
+ 
+ 		// Temporary -- will go away once kernel uses ranges for get_immrbase().
+-		reg = <f0000000 00053000>;
++		reg = <0xf0000000 0x53000>;
+ 
+ 		cpm at 119c0 {
+ 			#address-cells = <1>;
+ 			#size-cells = <1>;
+ 			#interrupt-cells = <2>;
+ 			compatible = "fsl,mpc8280-cpm", "fsl,cpm2";
+-			reg = <119c0 30>;
++			reg = <0x119c0 0x30>;
+ 			ranges;
+ 
+ 			muram at 0 {
+ 				#address-cells = <1>;
+ 				#size-cells = <1>;
+-				ranges = <0 0 10000>;
++				ranges = <0x0 0x0 0x10000>;
+ 
+ 				data at 0 {
+ 					compatible = "fsl,cpm-muram-data";
+-					reg = <0 2000 9800 800>;
++					reg = <0x0 0x2000 0x9800 0x800>;
+ 				};
+ 			};
+ 
+@@ -137,53 +139,53 @@
+ 				compatible = "fsl,mpc8280-brg",
+ 				             "fsl,cpm2-brg",
+ 				             "fsl,cpm-brg";
+-				reg = <119f0 10 115f0 10>;
++				reg = <0x119f0 0x10 0x115f0 0x10>;
+ 			};
+ 
+ 			serial at 11a00 {
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc8280-scc-uart",
+ 				             "fsl,cpm2-scc-uart";
+-				reg = <11a00 20 8000 100>;
+-				interrupts = <28 8>;
++				reg = <0x11a00 0x20 0x8000 0x100>;
++				interrupts = <40 8>;
+ 				interrupt-parent = <&PIC>;
+ 				fsl,cpm-brg = <1>;
+-				fsl,cpm-command = <00800000>;
++				fsl,cpm-command = <0x800000>;
+ 			};
+ 
+ 			serial at 11a20 {
+ 				device_type = "serial";
+ 				compatible = "fsl,mpc8280-scc-uart",
+ 				             "fsl,cpm2-scc-uart";
+-				reg = <11a20 20 8100 100>;
+-				interrupts = <29 8>;
++				reg = <0x11a20 0x20 0x8100 0x100>;
++				interrupts = <41 8>;
+ 				interrupt-parent = <&PIC>;
+ 				fsl,cpm-brg = <2>;
+-				fsl,cpm-command = <04a00000>;
++				fsl,cpm-command = <0x4a00000>;
+ 			};
+ 
+ 			ethernet at 11320 {
+ 				device_type = "network";
+ 				compatible = "fsl,mpc8280-fcc-enet",
+ 				             "fsl,cpm2-fcc-enet";
+-				reg = <11320 20 8500 100 113b0 1>;
+-				interrupts = <21 8>;
++				reg = <0x11320 0x20 0x8500 0x100 0x113b0 0x1>;
++				interrupts = <33 8>;
+ 				interrupt-parent = <&PIC>;
+ 				phy-handle = <&PHY0>;
+ 				linux,network-index = <0>;
+-				fsl,cpm-command = <16200300>;
++				fsl,cpm-command = <0x16200300>;
+ 			};
+ 
+ 			ethernet at 11340 {
+ 				device_type = "network";
+ 				compatible = "fsl,mpc8280-fcc-enet",
+ 				             "fsl,cpm2-fcc-enet";
+-				reg = <11340 20 8600 100 113d0 1>;
+-				interrupts = <22 8>;
++				reg = <0x11340 0x20 0x8600 0x100 0x113d0 0x1>;
++				interrupts = <34 8>;
+ 				interrupt-parent = <&PIC>;
+ 				phy-handle = <&PHY1>;
+ 				linux,network-index = <1>;
+-				fsl,cpm-command = <1a400300>;
++				fsl,cpm-command = <0x1a400300>;
+ 				local-mac-address = [00 e0 0c 00 79 01];
+ 			};
+ 
+@@ -194,21 +196,21 @@
+ 				             "fsl,cpm2-mdio-bitbang";
+ 				#address-cells = <1>;
+ 				#size-cells = <0>;
+-				reg = <10d40 14>;
++				reg = <0x10d40 0x14>;
+ 				fsl,mdio-pin = <9>;
+-				fsl,mdc-pin = <a>;
++				fsl,mdc-pin = <10>;
+ 
+ 				PHY0: ethernet-phy at 0 {
+ 					interrupt-parent = <&PIC>;
+-					interrupts = <19 2>;
+-					reg = <0>;
++					interrupts = <25 2>;
++					reg = <0x0>;
+ 					device_type = "ethernet-phy";
+ 				};
+ 
+ 				PHY1: ethernet-phy at 1 {
+ 					interrupt-parent = <&PIC>;
+-					interrupts = <19 2>;
+-					reg = <3>;
++					interrupts = <25 2>;
++					reg = <0x3>;
+ 					device_type = "ethernet-phy";
+ 				};
+ 			};
+@@ -218,17 +220,17 @@
+ 				#size-cells = <0>;
+ 				compatible = "fsl,mpc8280-usb",
+ 				             "fsl,cpm2-usb";
+-				reg = <11b60 18 8b00 100>;
++				reg = <0x11b60 0x18 0x8b00 0x100>;
+ 				interrupt-parent = <&PIC>;
+-				interrupts = <b 8>;
+-				fsl,cpm-command = <2e600000>;
++				interrupts = <11 8>;
++				fsl,cpm-command = <0x2e600000>;
+ 			};
+ 		};
+ 
+ 		PIC: interrupt-controller at 10c00 {
+ 			#interrupt-cells = <2>;
+ 			interrupt-controller;
+-			reg = <10c00 80>;
++			reg = <0x10c00 0x80>;
+ 			compatible = "fsl,mpc8280-pic", "fsl,cpm2-pic";
+ 		};
+ 
+diff --git a/arch/powerpc/boot/dts/prpmc2800.dts b/arch/powerpc/boot/dts/prpmc2800.dts
+index 297dfa5..1ee6ff4 100644
+--- a/arch/powerpc/boot/dts/prpmc2800.dts
++++ b/arch/powerpc/boot/dts/prpmc2800.dts
+@@ -11,6 +11,8 @@
+  * if it can determine the exact PrPMC type.
+  */
+ 
++/dts-v1/;
++
+ / {
+ 	#address-cells = <1>;
+ 	#size-cells = <1>;
+@@ -25,46 +27,46 @@
+ 		PowerPC,7447 {
+ 			device_type = "cpu";
+ 			reg = <0>;
+-			clock-frequency = <2bb0b140>;	/* Default (733 MHz) */
+-			bus-frequency = <7f28155>;	/* 133.333333 MHz */
+-			timebase-frequency = <1fca055>;	/* 33.333333 MHz */
+-			i-cache-line-size = <20>;
+-			d-cache-line-size = <20>;
+-			i-cache-size = <8000>;
+-			d-cache-size = <8000>;
++			clock-frequency = <733333333>;	/* Default */
++			bus-frequency = <133333333>;
++			timebase-frequency = <33333333>;
++			i-cache-line-size = <32>;
++			d-cache-line-size = <32>;
++			i-cache-size = <32768>;
++			d-cache-size = <32768>;
+ 		};
+ 	};
+ 
+ 	memory {
+ 		device_type = "memory";
+-		reg = <00000000 20000000>;	/* Default (512MB) */
++		reg = <0x0 0x20000000>;			/* Default (512MB) */
+ 	};
+ 
+-	mv64x60 at f1000000 { /* Marvell Discovery */
++	system-controller at f1000000 { /* Marvell Discovery mv64360 */
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+ 		model = "mv64360";			/* Default */
+-		compatible = "marvell,mv64x60";
+-		clock-frequency = <7f28155>;		/* 133.333333 MHz */
+-		reg = <f1000000 00010000>;
+-		virtual-reg = <f1000000>;
+-		ranges = <88000000 88000000 01000000	/* PCI 0 I/O Space */
+-			  80000000 80000000 08000000	/* PCI 0 MEM Space */
+-			  a0000000 a0000000 04000000	/* User FLASH */
+-			  00000000 f1000000 00010000	/* Bridge's regs */
+-			  f2000000 f2000000 00040000>;	/* Integrated SRAM */
++		compatible = "marvell,mv64360";
++		clock-frequency = <133333333>;
++		reg = <0xf1000000 0x10000>;
++		virtual-reg = <0xf1000000>;
++		ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
++			  0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
++			  0xa0000000 0xa0000000 0x4000000 /* User FLASH */
++			  0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
++			  0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
+ 
+ 		flash at a0000000 {
+ 			device_type = "rom";
+ 			compatible = "direct-mapped";
+-			reg = <a0000000 4000000>; /* Default (64MB) */
++			reg = <0xa0000000 0x4000000>; /* Default (64MB) */
+ 			probe-type = "CFI";
+ 			bank-width = <4>;
+-			partitions = <00000000 00100000 /* RO */
+-				      00100000 00040001 /* RW */
+-				      00140000 00400000 /* RO */
+-				      00540000 039c0000 /* RO */
+-				      03f00000 00100000>; /* RO */
++			partitions = <0x00000000 0x00100000 /* RO */
++				      0x00100000 0x00040001 /* RW */
++				      0x00140000 0x00400000 /* RO */
++				      0x00540000 0x039c0000 /* RO */
++				      0x03f00000 0x00100000>; /* RO */
+ 			partition-names = "FW Image A", "FW Config Data", "Kernel Image", "Filesystem", "FW Image B";
+ 		};
+ 
+@@ -72,171 +74,153 @@
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 			device_type = "mdio";
+-			compatible = "marvell,mv64x60-mdio";
+-			ethernet-phy at 1 {
++			compatible = "marvell,mv64360-mdio";
++			PHY0: ethernet-phy at 1 {
+ 				device_type = "ethernet-phy";
+ 				compatible = "broadcom,bcm5421";
+-				interrupts = <4c>;	/* GPP 12 */
+-				interrupt-parent = <&/mv64x60/pic>;
++				interrupts = <76>;	/* GPP 12 */
++				interrupt-parent = <&PIC>;
+ 				reg = <1>;
+ 			};
+-			ethernet-phy at 3 {
++			PHY1: ethernet-phy at 3 {
+ 				device_type = "ethernet-phy";
+ 				compatible = "broadcom,bcm5421";
+-				interrupts = <4c>;	/* GPP 12 */
+-				interrupt-parent = <&/mv64x60/pic>;
++				interrupts = <76>;	/* GPP 12 */
++				interrupt-parent = <&PIC>;
+ 				reg = <3>;
+ 			};
+ 		};
+ 
+-		ethernet at 2000 {
+-			reg = <2000 2000>;
+-			eth0 {
++		ethernet-group at 2000 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			compatible = "marvell,mv64360-eth-group";
++			reg = <0x2000 0x2000>;
++			ethernet at 0 {
+ 				device_type = "network";
+-				compatible = "marvell,mv64x60-eth";
+-				block-index = <0>;
+-				interrupts = <20>;
+-				interrupt-parent = <&/mv64x60/pic>;
+-				phy = <&/mv64x60/mdio/ethernet-phy at 1>;
++				compatible = "marvell,mv64360-eth";
++				reg = <0>;
++				interrupts = <32>;
++				interrupt-parent = <&PIC>;
++				phy = <&PHY0>;
+ 				local-mac-address = [ 00 00 00 00 00 00 ];
+ 			};
+-			eth1 {
++			ethernet at 1 {
+ 				device_type = "network";
+-				compatible = "marvell,mv64x60-eth";
+-				block-index = <1>;
+-				interrupts = <21>;
+-				interrupt-parent = <&/mv64x60/pic>;
+-				phy = <&/mv64x60/mdio/ethernet-phy at 3>;
++				compatible = "marvell,mv64360-eth";
++				reg = <1>;
++				interrupts = <33>;
++				interrupt-parent = <&PIC>;
++				phy = <&PHY1>;
+ 				local-mac-address = [ 00 00 00 00 00 00 ];
+ 			};
+ 		};
+ 
+-		sdma at 4000 {
+-			device_type = "dma";
+-			compatible = "marvell,mv64x60-sdma";
+-			reg = <4000 c18>;
+-			virtual-reg = <f1004000>;
+-			interrupt-base = <0>;
+-			interrupts = <24>;
+-			interrupt-parent = <&/mv64x60/pic>;
++		SDMA0: sdma at 4000 {
++			compatible = "marvell,mv64360-sdma";
++			reg = <0x4000 0xc18>;
++			virtual-reg = <0xf1004000>;
++			interrupts = <36>;
++			interrupt-parent = <&PIC>;
+ 		};
+ 
+-		sdma at 6000 {
+-			device_type = "dma";
+-			compatible = "marvell,mv64x60-sdma";
+-			reg = <6000 c18>;
+-			virtual-reg = <f1006000>;
+-			interrupt-base = <0>;
+-			interrupts = <26>;
+-			interrupt-parent = <&/mv64x60/pic>;
++		SDMA1: sdma at 6000 {
++			compatible = "marvell,mv64360-sdma";
++			reg = <0x6000 0xc18>;
++			virtual-reg = <0xf1006000>;
++			interrupts = <38>;
++			interrupt-parent = <&PIC>;
+ 		};
+ 
+-		brg at b200 {
+-			compatible = "marvell,mv64x60-brg";
+-			reg = <b200 8>;
++		BRG0: brg at b200 {
++			compatible = "marvell,mv64360-brg";
++			reg = <0xb200 0x8>;
+ 			clock-src = <8>;
+-			clock-frequency = <7ed6b40>;
+-			current-speed = <2580>;
+-			bcr = <0>;
++			clock-frequency = <133333333>;
++			current-speed = <9600>;
+ 		};
+ 
+-		brg at b208 {
+-			compatible = "marvell,mv64x60-brg";
+-			reg = <b208 8>;
++		BRG1: brg at b208 {
++			compatible = "marvell,mv64360-brg";
++			reg = <0xb208 0x8>;
+ 			clock-src = <8>;
+-			clock-frequency = <7ed6b40>;
+-			current-speed = <2580>;
+-			bcr = <0>;
++			clock-frequency = <133333333>;
++			current-speed = <9600>;
+ 		};
+ 
+-		cunit at f200 {
+-			reg = <f200 200>;
++		CUNIT: cunit at f200 {
++			reg = <0xf200 0x200>;
+ 		};
+ 
+-		mpscrouting at b400 {
+-			reg = <b400 c>;
++		MPSCROUTING: mpscrouting at b400 {
++			reg = <0xb400 0xc>;
+ 		};
+ 
+-		mpscintr at b800 {
+-			reg = <b800 100>;
+-			virtual-reg = <f100b800>;
++		MPSCINTR: mpscintr at b800 {
++			reg = <0xb800 0x100>;
++			virtual-reg = <0xf100b800>;
+ 		};
+ 
+-		mpsc at 8000 {
++		MPSC0: mpsc at 8000 {
+ 			device_type = "serial";
+-			compatible = "marvell,mpsc";
+-			reg = <8000 38>;
+-			virtual-reg = <f1008000>;
+-			sdma = <&/mv64x60/sdma at 4000>;
+-			brg = <&/mv64x60/brg at b200>;
+-			cunit = <&/mv64x60/cunit at f200>;
+-			mpscrouting = <&/mv64x60/mpscrouting at b400>;
+-			mpscintr = <&/mv64x60/mpscintr at b800>;
+-			block-index = <0>;
+-			max_idle = <28>;
+-			chr_1 = <0>;
+-			chr_2 = <0>;
+-			chr_10 = <3>;
+-			mpcr = <0>;
+-			interrupts = <28>;
+-			interrupt-parent = <&/mv64x60/pic>;
++			compatible = "marvell,mv64360-mpsc";
++			reg = <0x8000 0x38>;
++			virtual-reg = <0xf1008000>;
++			sdma = <&SDMA0>;
++			brg = <&BRG0>;
++			cunit = <&CUNIT>;
++			mpscrouting = <&MPSCROUTING>;
++			mpscintr = <&MPSCINTR>;
++			cell-index = <0>;
++			interrupts = <40>;
++			interrupt-parent = <&PIC>;
+ 		};
+ 
+-		mpsc at 9000 {
++		MPSC1: mpsc at 9000 {
+ 			device_type = "serial";
+-			compatible = "marvell,mpsc";
+-			reg = <9000 38>;
+-			virtual-reg = <f1009000>;
+-			sdma = <&/mv64x60/sdma at 6000>;
+-			brg = <&/mv64x60/brg at b208>;
+-			cunit = <&/mv64x60/cunit at f200>;
+-			mpscrouting = <&/mv64x60/mpscrouting at b400>;
+-			mpscintr = <&/mv64x60/mpscintr at b800>;
+-			block-index = <1>;
+-			max_idle = <28>;
+-			chr_1 = <0>;
+-			chr_2 = <0>;
+-			chr_10 = <3>;
+-			mpcr = <0>;
+-			interrupts = <2a>;
+-			interrupt-parent = <&/mv64x60/pic>;
++			compatible = "marvell,mv64360-mpsc";
++			reg = <0x9000 0x38>;
++			virtual-reg = <0xf1009000>;
++			sdma = <&SDMA1>;
++			brg = <&BRG1>;
++			cunit = <&CUNIT>;
++			mpscrouting = <&MPSCROUTING>;
++			mpscintr = <&MPSCINTR>;
++			cell-index = <1>;
++			interrupts = <42>;
++			interrupt-parent = <&PIC>;
+ 		};
+ 
+ 		wdt at b410 {			/* watchdog timer */
+-			compatible = "marvell,mv64x60-wdt";
+-			reg = <b410 8>;
+-			timeout = <a>;		/* wdt timeout in seconds */
++			compatible = "marvell,mv64360-wdt";
++			reg = <0xb410 0x8>;
+ 		};
+ 
+ 		i2c at c000 {
+ 			device_type = "i2c";
+-			compatible = "marvell,mv64x60-i2c";
+-			reg = <c000 20>;
+-			virtual-reg = <f100c000>;
+-			freq_m = <8>;
+-			freq_n = <3>;
+-			timeout = <3e8>;		/* 1000 = 1 second */
+-			retries = <1>;
+-			interrupts = <25>;
+-			interrupt-parent = <&/mv64x60/pic>;
++			compatible = "marvell,mv64360-i2c";
++			reg = <0xc000 0x20>;
++			virtual-reg = <0xf100c000>;
++			interrupts = <37>;
++			interrupt-parent = <&PIC>;
+ 		};
+ 
+-		pic {
++		PIC: pic {
+ 			#interrupt-cells = <1>;
+ 			#address-cells = <0>;
+-			compatible = "marvell,mv64x60-pic";
+-			reg = <0000 88>;
++			compatible = "marvell,mv64360-pic";
++			reg = <0x0 0x88>;
+ 			interrupt-controller;
+ 		};
+ 
+ 		mpp at f000 {
+-			compatible = "marvell,mv64x60-mpp";
+-			reg = <f000 10>;
++			compatible = "marvell,mv64360-mpp";
++			reg = <0xf000 0x10>;
+ 		};
+ 
+ 		gpp at f100 {
+-			compatible = "marvell,mv64x60-gpp";
+-			reg = <f100 20>;
++			compatible = "marvell,mv64360-gpp";
++			reg = <0xf100 0x20>;
+ 		};
+ 
+ 		pci at 80000000 {
+@@ -244,73 +228,75 @@
+ 			#size-cells = <2>;
+ 			#interrupt-cells = <1>;
+ 			device_type = "pci";
+-			compatible = "marvell,mv64x60-pci";
+-			reg = <0cf8 8>;
+-			ranges = <01000000 0        0 88000000 0 01000000
+-				  02000000 0 80000000 80000000 0 08000000>;
+-			bus-range = <0 ff>;
+-			clock-frequency = <3EF1480>;
+-			interrupt-pci-iack = <0c34>;
+-			interrupt-parent = <&/mv64x60/pic>;
+-			interrupt-map-mask = <f800 0 0 7>;
++			compatible = "marvell,mv64360-pci";
++			reg = <0xcf8 0x8>;
++			ranges = <0x01000000 0x0        0x0
++					0x88000000 0x0 0x01000000
++				  0x02000000 0x0 0x80000000
++				  	0x80000000 0x0 0x08000000>;
++			bus-range = <0 255>;
++			clock-frequency = <66000000>;
++			interrupt-pci-iack = <0xc34>;
++			interrupt-parent = <&PIC>;
++			interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ 			interrupt-map = <
+ 				/* IDSEL 0x0a */
+-				5000 0 0 1 &/mv64x60/pic 50
+-				5000 0 0 2 &/mv64x60/pic 51
+-				5000 0 0 3 &/mv64x60/pic 5b
+-				5000 0 0 4 &/mv64x60/pic 5d
++				0x5000 0 0 1 &PIC 80
++				0x5000 0 0 2 &PIC 81
++				0x5000 0 0 3 &PIC 91
++				0x5000 0 0 4 &PIC 93
+ 
+ 				/* IDSEL 0x0b */
+-				5800 0 0 1 &/mv64x60/pic 5b
+-				5800 0 0 2 &/mv64x60/pic 5d
+-				5800 0 0 3 &/mv64x60/pic 50
+-				5800 0 0 4 &/mv64x60/pic 51
++				0x5800 0 0 1 &PIC 91
++				0x5800 0 0 2 &PIC 93
++				0x5800 0 0 3 &PIC 80
++				0x5800 0 0 4 &PIC 81
+ 
+ 				/* IDSEL 0x0c */
+-				6000 0 0 1 &/mv64x60/pic 5b
+-				6000 0 0 2 &/mv64x60/pic 5d
+-				6000 0 0 3 &/mv64x60/pic 50
+-				6000 0 0 4 &/mv64x60/pic 51
++				0x6000 0 0 1 &PIC 91
++				0x6000 0 0 2 &PIC 93
++				0x6000 0 0 3 &PIC 80
++				0x6000 0 0 4 &PIC 81
+ 
+ 				/* IDSEL 0x0d */
+-				6800 0 0 1 &/mv64x60/pic 5d
+-				6800 0 0 2 &/mv64x60/pic 50
+-				6800 0 0 3 &/mv64x60/pic 51
+-				6800 0 0 4 &/mv64x60/pic 5b
++				0x6800 0 0 1 &PIC 93
++				0x6800 0 0 2 &PIC 80
++				0x6800 0 0 3 &PIC 81
++				0x6800 0 0 4 &PIC 91
+ 			>;
+ 		};
+ 
+ 		cpu-error at 0070 {
+-			compatible = "marvell,mv64x60-cpu-error";
+-			reg = <0070 10 0128 28>;
+-			interrupts = <03>;
+-			interrupt-parent = <&/mv64x60/pic>;
++			compatible = "marvell,mv64360-cpu-error";
++			reg = <0x70 0x10 0x128 0x28>;
++			interrupts = <3>;
++			interrupt-parent = <&PIC>;
+ 		};
+ 
+ 		sram-ctrl at 0380 {
+-			compatible = "marvell,mv64x60-sram-ctrl";
+-			reg = <0380 80>;
+-			interrupts = <0d>;
+-			interrupt-parent = <&/mv64x60/pic>;
++			compatible = "marvell,mv64360-sram-ctrl";
++			reg = <0x380 0x80>;
++			interrupts = <13>;
++			interrupt-parent = <&PIC>;
+ 		};
+ 
+ 		pci-error at 1d40 {
+-			compatible = "marvell,mv64x60-pci-error";
+-			reg = <1d40 40 0c28 4>;
+-			interrupts = <0c>;
+-			interrupt-parent = <&/mv64x60/pic>;
++			compatible = "marvell,mv64360-pci-error";
++			reg = <0x1d40 0x40 0xc28 0x4>;
++			interrupts = <12>;
++			interrupt-parent = <&PIC>;
+ 		};
+ 
+ 		mem-ctrl at 1400 {
+-			compatible = "marvell,mv64x60-mem-ctrl";
+-			reg = <1400 60>;
+-			interrupts = <11>;
+-			interrupt-parent = <&/mv64x60/pic>;
++			compatible = "marvell,mv64360-mem-ctrl";
++			reg = <0x1400 0x60>;
++			interrupts = <17>;
++			interrupt-parent = <&PIC>;
+ 		};
+ 	};
+ 
+ 	chosen {
+ 		bootargs = "ip=on";
+-		linux,stdout-path = "/mv64x60 at f1000000/mpsc at 8000";
++		linux,stdout-path = &MPSC0;
+ 	};
+ };
+diff --git a/arch/powerpc/boot/dts/rainier.dts b/arch/powerpc/boot/dts/rainier.dts
+index f947c75..6a8fa70 100644
+--- a/arch/powerpc/boot/dts/rainier.dts
++++ b/arch/powerpc/boot/dts/rainier.dts
+@@ -254,7 +254,6 @@
+ 			};
+ 
+ 			EMAC0: ethernet at ef600e00 {
+-				linux,network-index = <0>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440grx", "ibm,emac-440epx", "ibm,emac4";
+ 				interrupt-parent = <&EMAC0>;
+@@ -270,7 +269,7 @@
+ 				mal-tx-channel = <0>;
+ 				mal-rx-channel = <0>;
+ 				cell-index = <0>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+@@ -284,7 +283,6 @@
+ 			};
+ 
+ 			EMAC1: ethernet at ef600f00 {
+-				linux,network-index = <1>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440grx", "ibm,emac-440epx", "ibm,emac4";
+ 				interrupt-parent = <&EMAC1>;
+@@ -300,7 +298,7 @@
+ 				mal-tx-channel = <1>;
+ 				mal-rx-channel = <1>;
+ 				cell-index = <1>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/sbc8641d.dts b/arch/powerpc/boot/dts/sbc8641d.dts
+new file mode 100644
+index 0000000..3eebeec
+--- /dev/null
++++ b/arch/powerpc/boot/dts/sbc8641d.dts
+@@ -0,0 +1,352 @@
++/*
++ * SBC8641D Device Tree Source
++ *
++ * Copyright 2008 Wind River Systems Inc.
++ *
++ * Paul Gortmaker (see MAINTAINERS for contact information)
++ *
++ * Based largely on the mpc8641_hpcn.dts by Freescale Semiconductor Inc.
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++
++/dts-v1/;
++
++/ {
++	model = "SBC8641D";
++	compatible = "wind,sbc8641";
++	#address-cells = <1>;
++	#size-cells = <1>;
++
++	aliases {
++		ethernet0 = &enet0;
++		ethernet1 = &enet1;
++		ethernet2 = &enet2;
++		ethernet3 = &enet3;
++		serial0 = &serial0;
++		serial1 = &serial1;
++		pci0 = &pci0;
++		pci1 = &pci1;
++	};
++
++	cpus {
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		PowerPC,8641 at 0 {
++			device_type = "cpu";
++			reg = <0>;
++			d-cache-line-size = <32>;
++			i-cache-line-size = <32>;
++			d-cache-size = <32768>;		// L1
++			i-cache-size = <32768>;		// L1
++			timebase-frequency = <0>;	// From uboot
++			bus-frequency = <0>;		// From uboot
++			clock-frequency = <0>;		// From uboot
++		};
++		PowerPC,8641 at 1 {
++			device_type = "cpu";
++			reg = <1>;
++			d-cache-line-size = <32>;
++			i-cache-line-size = <32>;
++			d-cache-size = <32768>;
++			i-cache-size = <32768>;
++			timebase-frequency = <0>;	// From uboot
++			bus-frequency = <0>;		// From uboot
++			clock-frequency = <0>;		// From uboot
++		};
++	};
++
++	memory {
++		device_type = "memory";
++		reg = <0x00000000 0x20000000>;	// 512M at 0x0
++	};
++
++	localbus at f8005000 {
++		#address-cells = <2>;
++		#size-cells = <1>;
++		compatible = "fsl,mpc8641-localbus", "simple-bus";
++		reg = <0xf8005000 0x1000>;
++		interrupts = <19 2>;
++		interrupt-parent = <&mpic>;
++
++		ranges = <0 0 0xff000000 0x01000000	// 16MB Boot flash
++			  1 0 0xf0000000 0x00010000	// 64KB EEPROM
++			  2 0 0xf1000000 0x00100000	// EPLD (1MB)
++			  3 0 0xe0000000 0x04000000	// 64MB LB SDRAM (CS3)
++			  4 0 0xe4000000 0x04000000	// 64MB LB SDRAM (CS4)
++			  6 0 0xf4000000 0x00100000	// LCD display (1MB)
++			  7 0 0xe8000000 0x04000000>;	// 64MB OneNAND
++
++		flash at 0,0 {
++			compatible = "cfi-flash";
++			reg = <0 0 0x01000000>;
++			bank-width = <2>;
++			device-width = <2>;
++			#address-cells = <1>;
++			#size-cells = <1>;
++			partition at 0 {
++				label = "dtb";
++				reg = <0x00000000 0x00100000>;
++				read-only;
++			};
++			partition at 300000 {
++				label = "kernel";
++				reg = <0x00100000 0x00400000>;
++				read-only;
++			};
++			partition at 400000 {
++				label = "fs";
++				reg = <0x00500000 0x00a00000>;
++			};
++			partition at 700000 {
++				label = "firmware";
++				reg = <0x00f00000 0x00100000>;
++				read-only;
++			};
++		};
++
++		epld at 2,0 {
++			compatible = "wrs,epld-localbus";
++			#address-cells = <2>;
++			#size-cells = <1>;
++			reg = <2 0 0x100000>;
++			ranges = <0 0 5 0 1	// User switches
++				  1 0 5 1 1	// Board ID/Rev
++				  3 0 5 3 1>;	// LEDs
++		};
++	};
++
++	soc at f8000000 {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		device_type = "soc";
++		compatible = "simple-bus";
++		ranges = <0x00000000 0xf8000000 0x00100000>;
++		reg = <0xf8000000 0x00001000>;	// CCSRBAR
++		bus-frequency = <0>;
++
++		i2c at 3000 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			cell-index = <0>;
++			compatible = "fsl-i2c";
++			reg = <0x3000 0x100>;
++			interrupts = <43 2>;
++			interrupt-parent = <&mpic>;
++			dfsrr;
++		};
++
++		i2c at 3100 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			cell-index = <1>;
++			compatible = "fsl-i2c";
++			reg = <0x3100 0x100>;
++			interrupts = <43 2>;
++			interrupt-parent = <&mpic>;
++			dfsrr;
++		};
++
++		mdio at 24520 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			compatible = "fsl,gianfar-mdio";
++			reg = <0x24520 0x20>;
++
++			phy0: ethernet-phy at 1f {
++				interrupt-parent = <&mpic>;
++				interrupts = <10 1>;
++				reg = <0x1f>;
++				device_type = "ethernet-phy";
++			};
++			phy1: ethernet-phy at 0 {
++				interrupt-parent = <&mpic>;
++				interrupts = <10 1>;
++				reg = <0>;
++				device_type = "ethernet-phy";
++			};
++			phy2: ethernet-phy at 1 {
++				interrupt-parent = <&mpic>;
++				interrupts = <10 1>;
++				reg = <1>;
++				device_type = "ethernet-phy";
++			};
++			phy3: ethernet-phy at 2 {
++				interrupt-parent = <&mpic>;
++				interrupts = <10 1>;
++				reg = <2>;
++				device_type = "ethernet-phy";
++			};
++		};
++
++		enet0: ethernet at 24000 {
++			cell-index = <0>;
++			device_type = "network";
++			model = "TSEC";
++			compatible = "gianfar";
++			reg = <0x24000 0x1000>;
++			local-mac-address = [ 00 00 00 00 00 00 ];
++			interrupts = <29 2 30  2 34 2>;
++			interrupt-parent = <&mpic>;
++			phy-handle = <&phy0>;
++			phy-connection-type = "rgmii-id";
++		};
++
++		enet1: ethernet at 25000 {
++			cell-index = <1>;
++			device_type = "network";
++			model = "TSEC";
++			compatible = "gianfar";
++			reg = <0x25000 0x1000>;
++			local-mac-address = [ 00 00 00 00 00 00 ];
++			interrupts = <35 2 36 2 40 2>;
++			interrupt-parent = <&mpic>;
++			phy-handle = <&phy1>;
++			phy-connection-type = "rgmii-id";
++		};
++
++		enet2: ethernet at 26000 {
++			cell-index = <2>;
++			device_type = "network";
++			model = "TSEC";
++			compatible = "gianfar";
++			reg = <0x26000 0x1000>;
++			local-mac-address = [ 00 00 00 00 00 00 ];
++			interrupts = <31 2 32 2 33 2>;
++			interrupt-parent = <&mpic>;
++			phy-handle = <&phy2>;
++			phy-connection-type = "rgmii-id";
++		};
++
++		enet3: ethernet at 27000 {
++			cell-index = <3>;
++			device_type = "network";
++			model = "TSEC";
++			compatible = "gianfar";
++			reg = <0x27000 0x1000>;
++			local-mac-address = [ 00 00 00 00 00 00 ];
++			interrupts = <37 2 38 2 39 2>;
++			interrupt-parent = <&mpic>;
++			phy-handle = <&phy3>;
++			phy-connection-type = "rgmii-id";
++		};
++
++		serial0: serial at 4500 {
++			cell-index = <0>;
++			device_type = "serial";
++			compatible = "ns16550";
++			reg = <0x4500 0x100>;
++			clock-frequency = <0>;
++			interrupts = <42 2>;
++			interrupt-parent = <&mpic>;
++		};
++
++		serial1: serial at 4600 {
++			cell-index = <1>;
++			device_type = "serial";
++			compatible = "ns16550";
++			reg = <0x4600 0x100>;
++			clock-frequency = <0>;
++			interrupts = <28 2>;
++			interrupt-parent = <&mpic>;
++		};
++
++		mpic: pic at 40000 {
++			clock-frequency = <0>;
++			interrupt-controller;
++			#address-cells = <0>;
++			#interrupt-cells = <2>;
++			reg = <0x40000 0x40000>;
++			compatible = "chrp,open-pic";
++			device_type = "open-pic";
++			big-endian;
++		};
++
++		global-utilities at e0000 {
++			compatible = "fsl,mpc8641-guts";
++			reg = <0xe0000 0x1000>;
++			fsl,has-rstcr;
++		};
++	};
++
++	pci0: pcie at f8008000 {
++		cell-index = <0>;
++		compatible = "fsl,mpc8641-pcie";
++		device_type = "pci";
++		#interrupt-cells = <1>;
++		#size-cells = <2>;
++		#address-cells = <3>;
++		reg = <0xf8008000 0x1000>;
++		bus-range = <0x0 0xff>;
++		ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++			  0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
++		clock-frequency = <33333333>;
++		interrupt-parent = <&mpic>;
++		interrupts = <24 2>;
++		interrupt-map-mask = <0xff00 0 0 7>;
++		interrupt-map = <
++			/* IDSEL 0x0 */
++			0x0000 0 0 1 &mpic 0 1
++			0x0000 0 0 2 &mpic 1 1
++			0x0000 0 0 3 &mpic 2 1
++			0x0000 0 0 4 &mpic 3 1
++			>;
++
++		pcie at 0 {
++			reg = <0 0 0 0 0>;
++			#size-cells = <2>;
++			#address-cells = <3>;
++			device_type = "pci";
++			ranges = <0x02000000 0x0 0x80000000
++				  0x02000000 0x0 0x80000000
++				  0x0 0x20000000
++
++				  0x01000000 0x0 0x00000000
++				  0x01000000 0x0 0x00000000
++				  0x0 0x00100000>;
++		};
++
++	};
++
++	pci1: pcie at f8009000 {
++		cell-index = <1>;
++		compatible = "fsl,mpc8641-pcie";
++		device_type = "pci";
++		#interrupt-cells = <1>;
++		#size-cells = <2>;
++		#address-cells = <3>;
++		reg = <0xf8009000 0x1000>;
++		bus-range = <0 0xff>;
++		ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++			  0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
++		clock-frequency = <33333333>;
++		interrupt-parent = <&mpic>;
++		interrupts = <25 2>;
++		interrupt-map-mask = <0xf800 0 0 7>;
++		interrupt-map = <
++			/* IDSEL 0x0 */
++			0x0000 0 0 1 &mpic 4 1
++			0x0000 0 0 2 &mpic 5 1
++			0x0000 0 0 3 &mpic 6 1
++			0x0000 0 0 4 &mpic 7 1
++			>;
++
++		pcie at 0 {
++			reg = <0 0 0 0 0>;
++			#size-cells = <2>;
++			#address-cells = <3>;
++			device_type = "pci";
++			ranges = <0x02000000 0x0 0xa0000000
++				  0x02000000 0x0 0xa0000000
++				  0x0 0x20000000
++
++				  0x01000000 0x0 0x00000000
++				  0x01000000 0x0 0x00000000
++				  0x0 0x00100000>;
++		};
++	};
++};
+diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts
+index 8db9515..a1ae4d6 100644
+--- a/arch/powerpc/boot/dts/sequoia.dts
++++ b/arch/powerpc/boot/dts/sequoia.dts
+@@ -269,7 +269,6 @@
+ 			};
+ 
+ 			EMAC0: ethernet at ef600e00 {
+-				linux,network-index = <0>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440epx", "ibm,emac4";
+ 				interrupt-parent = <&EMAC0>;
+@@ -285,7 +284,7 @@
+ 				mal-tx-channel = <0>;
+ 				mal-rx-channel = <0>;
+ 				cell-index = <0>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+@@ -299,7 +298,6 @@
+ 			};
+ 
+ 			EMAC1: ethernet at ef600f00 {
+-				linux,network-index = <1>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440epx", "ibm,emac4";
+ 				interrupt-parent = <&EMAC1>;
+@@ -315,7 +313,7 @@
+ 				mal-tx-channel = <1>;
+ 				mal-rx-channel = <1>;
+ 				cell-index = <1>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/taishan.dts b/arch/powerpc/boot/dts/taishan.dts
+index 8278068..e808e1c 100644
+--- a/arch/powerpc/boot/dts/taishan.dts
++++ b/arch/powerpc/boot/dts/taishan.dts
+@@ -104,6 +104,16 @@
+ 		// FIXME: anything else?
+ 	};
+ 
++	L2C0: l2c {
++		compatible = "ibm,l2-cache-440gx", "ibm,l2-cache";
++		dcr-reg = <20 8			/* Internal SRAM DCR's */
++			   30 8>;		/* L2 cache DCR's */
++		cache-line-size = <20>;		/* 32 bytes */
++		cache-size = <40000>;		/* L2, 256K */
++		interrupt-parent = <&UIC2>;
++		interrupts = <17 1>;
++	};
++
+ 	plb {
+ 		compatible = "ibm,plb-440gx", "ibm,plb4";
+ 		#address-cells = <2>;
+@@ -232,10 +242,18 @@
+ 				reg = <40000790 8>;
+ 			};
+ 
++			TAH0: emac-tah at 40000b50 {
++				compatible = "ibm,tah-440gx", "ibm,tah";
++				reg = <40000b50 30>;
++			};
++
++			TAH1: emac-tah at 40000d50 {
++				compatible = "ibm,tah-440gx", "ibm,tah";
++				reg = <40000d50 30>;
++			};
+ 
+ 			EMAC0: ethernet at 40000800 {
+ 				unused = <1>;
+-				linux,network-index = <2>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440gx", "ibm,emac4";
+ 				interrupt-parent = <&UIC1>;
+@@ -256,7 +274,6 @@
+ 			};
+ 		 	EMAC1: ethernet at 40000900 {
+ 				unused = <1>;
+-				linux,network-index = <3>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440gx", "ibm,emac4";
+ 				interrupt-parent = <&UIC1>;
+@@ -277,7 +294,6 @@
+ 			};
+ 
+ 		 	EMAC2: ethernet at 40000c00 {
+-				linux,network-index = <0>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440gx", "ibm,emac4";
+ 				interrupt-parent = <&UIC2>;
+@@ -288,7 +304,7 @@
+ 				mal-tx-channel = <2>;
+ 				mal-rx-channel = <2>;
+ 				cell-index = <2>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+@@ -297,10 +313,11 @@
+ 				rgmii-channel = <0>;
+  				zmii-device = <&ZMII0>;
+ 				zmii-channel = <2>;
++				tah-device = <&TAH0>;
++				tah-channel = <0>;
+ 			};
+ 
+ 		 	EMAC3: ethernet at 40000e00 {
+-				linux,network-index = <1>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440gx", "ibm,emac4";
+ 				interrupt-parent = <&UIC2>;
+@@ -311,7 +328,7 @@
+ 				mal-tx-channel = <3>;
+ 				mal-rx-channel = <3>;
+ 				cell-index = <3>;
+-				max-frame-size = <5dc>;
++				max-frame-size = <2328>;
+ 				rx-fifo-size = <1000>;
+ 				tx-fifo-size = <800>;
+ 				phy-mode = "rgmii";
+@@ -320,6 +337,8 @@
+ 				rgmii-channel = <1>;
+  				zmii-device = <&ZMII0>;
+ 				zmii-channel = <3>;
++				tah-device = <&TAH1>;
++				tah-channel = <0>;
+ 			};
+ 
+ 
+diff --git a/arch/powerpc/boot/dts/walnut.dts b/arch/powerpc/boot/dts/walnut.dts
+index dcc21b0..a328607 100644
+--- a/arch/powerpc/boot/dts/walnut.dts
++++ b/arch/powerpc/boot/dts/walnut.dts
+@@ -125,7 +125,6 @@
+ 			};
+ 
+ 			EMAC: ethernet at ef600800 {
+-				linux,network-index = <0>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-405gp", "ibm,emac";
+ 				interrupt-parent = <&UIC0>;
+diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
+index dc1499d..b04a52e 100644
+--- a/arch/powerpc/boot/dts/warp.dts
++++ b/arch/powerpc/boot/dts/warp.dts
+@@ -204,7 +204,6 @@
+ 			};
+ 
+ 			EMAC0: ethernet at ef600e00 {
+-				linux,network-index = <0>;
+ 				device_type = "network";
+ 				compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+ 				interrupt-parent = <&UIC1>;
+diff --git a/arch/powerpc/boot/dts/yosemite.dts b/arch/powerpc/boot/dts/yosemite.dts
+new file mode 100644
+index 0000000..0d6d332
+--- /dev/null
++++ b/arch/powerpc/boot/dts/yosemite.dts
+@@ -0,0 +1,304 @@
++/*
++ * Device Tree Source for AMCC Yosemite
++ *
++ * Copyright 2008 IBM Corp.
++ * Josh Boyer <jwboyer at linux.vnet.ibm.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.
++ */
++
++/ {
++	#address-cells = <2>;
++	#size-cells = <1>;
++	model = "amcc,yosemite";
++	compatible = "amcc,yosemite","amcc,bamboo";
++	dcr-parent = <&/cpus/cpu at 0>;
++
++	aliases {
++		ethernet0 = &EMAC0;
++		ethernet1 = &EMAC1;
++		serial0 = &UART0;
++		serial1 = &UART1;
++		serial2 = &UART2;
++		serial3 = &UART3;
++	};
++
++	cpus {
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		cpu at 0 {
++			device_type = "cpu";
++			model = "PowerPC,440EP";
++			reg = <0>;
++			clock-frequency = <0>; /* Filled in by zImage */
++			timebase-frequency = <0>; /* Filled in by zImage */
++			i-cache-line-size = <20>;
++			d-cache-line-size = <20>;
++			i-cache-size = <8000>;
++			d-cache-size = <8000>;
++			dcr-controller;
++			dcr-access-method = "native";
++		};
++	};
++
++	memory {
++		device_type = "memory";
++		reg = <0 0 0>; /* Filled in by zImage */
++	};
++
++	UIC0: interrupt-controller0 {
++		compatible = "ibm,uic-440ep","ibm,uic";
++		interrupt-controller;
++		cell-index = <0>;
++		dcr-reg = <0c0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++	};
++
++	UIC1: interrupt-controller1 {
++		compatible = "ibm,uic-440ep","ibm,uic";
++		interrupt-controller;
++		cell-index = <1>;
++		dcr-reg = <0d0 009>;
++		#address-cells = <0>;
++		#size-cells = <0>;
++		#interrupt-cells = <2>;
++		interrupts = <1e 4 1f 4>; /* cascade */
++		interrupt-parent = <&UIC0>;
++	};
++
++	SDR0: sdr {
++		compatible = "ibm,sdr-440ep";
++		dcr-reg = <00e 002>;
++	};
++
++	CPR0: cpr {
++		compatible = "ibm,cpr-440ep";
++		dcr-reg = <00c 002>;
++	};
++
++	plb {
++		compatible = "ibm,plb-440ep", "ibm,plb-440gp", "ibm,plb4";
++		#address-cells = <2>;
++		#size-cells = <1>;
++		ranges;
++		clock-frequency = <0>; /* Filled in by zImage */
++
++		SDRAM0: sdram {
++			compatible = "ibm,sdram-440ep", "ibm,sdram-405gp";
++			dcr-reg = <010 2>;
++		};
++
++		DMA0: dma {
++			compatible = "ibm,dma-440ep", "ibm,dma-440gp";
++			dcr-reg = <100 027>;
++		};
++
++		MAL0: mcmal {
++			compatible = "ibm,mcmal-440ep", "ibm,mcmal-440gp", "ibm,mcmal";
++			dcr-reg = <180 62>;
++			num-tx-chans = <4>;
++			num-rx-chans = <2>;
++			interrupt-parent = <&MAL0>;
++			interrupts = <0 1 2 3 4>;
++			#interrupt-cells = <1>;
++			#address-cells = <0>;
++			#size-cells = <0>;
++			interrupt-map = </*TXEOB*/ 0 &UIC0 a 4
++					/*RXEOB*/ 1 &UIC0 b 4
++					/*SERR*/  2 &UIC1 0 4
++					/*TXDE*/  3 &UIC1 1 4
++					/*RXDE*/  4 &UIC1 2 4>;
++		};
++
++		POB0: opb {
++			compatible = "ibm,opb-440ep", "ibm,opb-440gp", "ibm,opb";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			/* Bamboo is oddball in the 44x world and doesn't use the ERPN
++			 * bits.
++			 */
++			ranges = <00000000 0 00000000 80000000
++			          80000000 0 80000000 80000000>;
++			interrupt-parent = <&UIC1>;
++			interrupts = <7 4>;
++			clock-frequency = <0>; /* Filled in by zImage */
++
++			EBC0: ebc {
++				compatible = "ibm,ebc-440ep", "ibm,ebc-440gp", "ibm,ebc";
++				dcr-reg = <012 2>;
++				#address-cells = <2>;
++				#size-cells = <1>;
++				clock-frequency = <0>; /* Filled in by zImage */
++				interrupts = <5 1>;
++				interrupt-parent = <&UIC1>;
++			};
++
++			UART0: serial at ef600300 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600300 8>;
++				virtual-reg = <ef600300>;
++				clock-frequency = <0>; /* Filled in by zImage */
++				current-speed = <1c200>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <0 4>;
++			};
++
++			UART1: serial at ef600400 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600400 8>;
++				virtual-reg = <ef600400>;
++				clock-frequency = <0>;
++				current-speed = <0>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <1 4>;
++			};
++
++			UART2: serial at ef600500 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600500 8>;
++				virtual-reg = <ef600500>;
++				clock-frequency = <0>;
++				current-speed = <0>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <3 4>;
++				status = "disabled";
++			};
++
++			UART3: serial at ef600600 {
++				device_type = "serial";
++				compatible = "ns16550";
++				reg = <ef600600 8>;
++				virtual-reg = <ef600600>;
++				clock-frequency = <0>;
++				current-speed = <0>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <4 4>;
++				status = "disabled";
++			};
++
++			IIC0: i2c at ef600700 {
++				compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
++				reg = <ef600700 14>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <2 4>;
++			};
++
++			IIC1: i2c at ef600800 {
++				compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
++				reg = <ef600800 14>;
++				interrupt-parent = <&UIC0>;
++				interrupts = <7 4>;
++			};
++
++			spi at ef600900 {
++				compatible = "amcc,spi-440ep";
++				reg = <ef600900 6>;
++				interrupts = <8 4>;
++				interrupt-parent = <&UIC0>;
++			};
++
++			ZMII0: emac-zmii at ef600d00 {
++				compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
++				reg = <ef600d00 c>;
++			};
++
++			EMAC0: ethernet at ef600e00 {
++				device_type = "network";
++				compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
++				interrupt-parent = <&UIC1>;
++				interrupts = <1c 4 1d 4>;
++				reg = <ef600e00 70>;
++				local-mac-address = [000000000000];
++				mal-device = <&MAL0>;
++				mal-tx-channel = <0 1>;
++				mal-rx-channel = <0>;
++				cell-index = <0>;
++				max-frame-size = <5dc>;
++				rx-fifo-size = <1000>;
++				tx-fifo-size = <800>;
++				phy-mode = "rmii";
++				phy-map = <00000000>;
++				zmii-device = <&ZMII0>;
++				zmii-channel = <0>;
++			};
++
++			EMAC1: ethernet at ef600f00 {
++				device_type = "network";
++				compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
++				interrupt-parent = <&UIC1>;
++				interrupts = <1e 4 1f 4>;
++				reg = <ef600f00 70>;
++				local-mac-address = [000000000000];
++				mal-device = <&MAL0>;
++				mal-tx-channel = <2 3>;
++				mal-rx-channel = <1>;
++				cell-index = <1>;
++				max-frame-size = <5dc>;
++				rx-fifo-size = <1000>;
++				tx-fifo-size = <800>;
++				phy-mode = "rmii";
++				phy-map = <00000000>;
++				zmii-device = <&ZMII0>;
++				zmii-channel = <1>;
++			};
++
++			usb at ef601000 {
++				compatible = "ohci-be";
++				reg = <ef601000 80>;
++				interrupts = <8 4 9 4>;
++				interrupt-parent = < &UIC1 >;
++			};
++		};
++
++		PCI0: pci at ec000000 {
++			device_type = "pci";
++			#interrupt-cells = <1>;
++			#size-cells = <2>;
++			#address-cells = <3>;
++			compatible = "ibm,plb440ep-pci", "ibm,plb-pci";
++			primary;
++			reg = <0 eec00000 8	/* Config space access */
++			       0 eed00000 4	/* IACK */
++			       0 eed00000 4	/* Special cycle */
++			       0 ef400000 40>;	/* Internal registers */
++
++			/* Outbound ranges, one memory and one IO,
++			 * later cannot be changed. Chip supports a second
++			 * IO range but we don't use it for now
++			 */
++			ranges = <02000000 0 a0000000 0 a0000000 0 20000000
++				  01000000 0 00000000 0 e8000000 0 00010000>;
++
++			/* Inbound 2GB range starting at 0 */
++			dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++			/* Bamboo has all 4 IRQ pins tied together per slot */
++			interrupt-map-mask = <f800 0 0 0>;
++			interrupt-map = <
++				/* IDSEL 1 */
++				0800 0 0 0 &UIC0 1c 8
++
++				/* IDSEL 2 */
++				1000 0 0 0 &UIC0 1b 8
++
++				/* IDSEL 3 */
++				1800 0 0 0 &UIC0 1a 8
++
++				/* IDSEL 4 */
++				2000 0 0 0 &UIC0 19 8
++			>;
++		};
++	};
++
++	chosen {
++		linux,stdout-path = "/plb/opb/serial at ef600300";
++	};
++};
+diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c
+index f61364c..5532ab3 100644
+--- a/arch/powerpc/boot/ebony.c
++++ b/arch/powerpc/boot/ebony.c
+@@ -75,7 +75,8 @@ static void ebony_fixups(void)
+ 
+ 	ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
+ 	ibm4xx_sdram_fixup_memsize();
+-	dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
++	dt_fixup_mac_address_by_alias("ethernet0", ebony_mac0);
++	dt_fixup_mac_address_by_alias("ethernet1", ebony_mac1);
+ 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ 	ebony_flashsel_fixup();
+ }
+diff --git a/arch/powerpc/boot/libfdt-wrapper.c b/arch/powerpc/boot/libfdt-wrapper.c
+index 59016be..c541fd8 100644
+--- a/arch/powerpc/boot/libfdt-wrapper.c
++++ b/arch/powerpc/boot/libfdt-wrapper.c
+@@ -35,7 +35,7 @@
+ #define check_err(err) \
+ 	({ \
+ 		if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \
+-			printf("%s():%d  %s\n\r", __FUNCTION__, __LINE__, \
++			printf("%s():%d  %s\n\r", __func__, __LINE__, \
+ 			       fdt_strerror(err)); \
+ 		if (BAD_ERROR(err)) \
+ 			exit(); \
+diff --git a/arch/powerpc/boot/mpc52xx-psc.c b/arch/powerpc/boot/mpc52xx-psc.c
+index 1074626..d4cb4e4 100644
+--- a/arch/powerpc/boot/mpc52xx-psc.c
++++ b/arch/powerpc/boot/mpc52xx-psc.c
+@@ -51,14 +51,9 @@ static unsigned char psc_getc(void)
+ 
+ int mpc5200_psc_console_init(void *devp, struct serial_console_data *scdp)
+ {
+-	int n;
+-
+ 	/* Get the base address of the psc registers */
+-	n = getprop(devp, "virtual-reg", &psc, sizeof(psc));
+-	if (n != sizeof(psc)) {
+-		if (!dt_xlate_reg(devp, 0, (void *)&psc, NULL))
+-			return -1;
+-	}
++	if (dt_get_virtual_reg(devp, &psc, 1) < 1)
++		return -1;
+ 
+ 	scdp->open = psc_open;
+ 	scdp->putc = psc_putc;
+diff --git a/arch/powerpc/boot/mpsc.c b/arch/powerpc/boot/mpsc.c
+index 802ea53..425ad88 100644
+--- a/arch/powerpc/boot/mpsc.c
++++ b/arch/powerpc/boot/mpsc.c
+@@ -141,7 +141,7 @@ int mpsc_console_init(void *devp, struct serial_console_data *scdp)
+ 	if (mpscintr_base == NULL)
+ 		goto err_out;
+ 
+-	n = getprop(devp, "block-index", &v, sizeof(v));
++	n = getprop(devp, "cell-index", &v, sizeof(v));
+ 	if (n != sizeof(v))
+ 		goto err_out;
+ 	reg_set = (int)v;
+diff --git a/arch/powerpc/boot/mv64x60.c b/arch/powerpc/boot/mv64x60.c
+index b432594..d9bb302 100644
+--- a/arch/powerpc/boot/mv64x60.c
++++ b/arch/powerpc/boot/mv64x60.c
+@@ -535,7 +535,7 @@ u8 *mv64x60_get_bridge_pbase(void)
+ 	u32 v[2];
+ 	void *devp;
+ 
+-	devp = finddevice("/mv64x60");
++	devp = find_node_by_compatible(NULL, "marvell,mv64360");
+ 	if (devp == NULL)
+ 		goto err_out;
+ 	if (getprop(devp, "reg", v, sizeof(v)) != sizeof(v))
+@@ -553,7 +553,7 @@ u8 *mv64x60_get_bridge_base(void)
+ 	u32 v;
+ 	void *devp;
+ 
+-	devp = finddevice("/mv64x60");
++	devp = find_node_by_compatible(NULL, "marvell,mv64360");
+ 	if (devp == NULL)
+ 		goto err_out;
+ 	if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
+diff --git a/arch/powerpc/boot/mv64x60_i2c.c b/arch/powerpc/boot/mv64x60_i2c.c
+index d085377..52a3212 100644
+--- a/arch/powerpc/boot/mv64x60_i2c.c
++++ b/arch/powerpc/boot/mv64x60_i2c.c
+@@ -185,7 +185,7 @@ int mv64x60_i2c_open(void)
+ 	u32 v;
+ 	void *devp;
+ 
+-	devp = finddevice("/mv64x60/i2c");
++	devp = find_node_by_compatible(NULL, "marvell,mv64360-i2c");
+ 	if (devp == NULL)
+ 		goto err_out;
+ 	if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
+diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
+index f8f1b2f..8c9ead9 100644
+--- a/arch/powerpc/boot/ns16550.c
++++ b/arch/powerpc/boot/ns16550.c
+@@ -55,15 +55,14 @@ static u8 ns16550_tstc(void)
+ int ns16550_console_init(void *devp, struct serial_console_data *scdp)
+ {
+ 	int n;
+-	unsigned long reg_phys;
++	u32 reg_offset;
+ 
+-	n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base));
+-	if (n != sizeof(reg_base)) {
+-		if (!dt_xlate_reg(devp, 0, &reg_phys, NULL))
+-			return -1;
++	if (dt_get_virtual_reg(devp, (void **)&reg_base, 1) < 1)
++		return -1;
+ 
+-		reg_base = (void *)reg_phys;
+-	}
++	n = getprop(devp, "reg-offset", &reg_offset, sizeof(reg_offset));
++	if (n == sizeof(reg_offset))
++		reg_base += reg_offset;
+ 
+ 	n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
+ 	if (n != sizeof(reg_shift))
+diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
+index 4b0544b..321e2f5 100644
+--- a/arch/powerpc/boot/ops.h
++++ b/arch/powerpc/boot/ops.h
+@@ -95,6 +95,7 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);
+ int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr);
+ int dt_is_compatible(void *node, const char *compat);
+ void dt_get_reg_format(void *node, u32 *naddr, u32 *nsize);
++int dt_get_virtual_reg(void *node, void **addr, int nres);
+ 
+ static inline void *finddevice(const char *name)
+ {
+diff --git a/arch/powerpc/boot/prpmc2800.c b/arch/powerpc/boot/prpmc2800.c
+index 05c3245..da31d60 100644
+--- a/arch/powerpc/boot/prpmc2800.c
++++ b/arch/powerpc/boot/prpmc2800.c
+@@ -344,20 +344,20 @@ static void prpmc2800_bridge_setup(u32 mem_size)
+ 			acc_bits);
+ 
+ 	/* Get the cpu -> pci i/o & mem mappings from the device tree */
+-	devp = finddevice("/mv64x60/pci at 80000000");
++	devp = find_node_by_compatible(NULL, "marvell,mv64360-pci");
+ 	if (devp == NULL)
+-		fatal("Error: Missing /mv64x60/pci at 80000000"
++		fatal("Error: Missing marvell,mv64360-pci"
+ 				" device tree node\n\r");
+ 
+ 	rc = getprop(devp, "ranges", v, sizeof(v));
+ 	if (rc != sizeof(v))
+-		fatal("Error: Can't find /mv64x60/pci at 80000000/ranges"
++		fatal("Error: Can't find marvell,mv64360-pci ranges"
+ 				" property\n\r");
+ 
+ 	/* Get the cpu -> pci i/o & mem mappings from the device tree */
+-	devp = finddevice("/mv64x60");
++	devp = find_node_by_compatible(NULL, "marvell,mv64360");
+ 	if (devp == NULL)
+-		fatal("Error: Missing /mv64x60 device tree node\n\r");
++		fatal("Error: Missing marvell,mv64360 device tree node\n\r");
+ 
+ 	enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE));
+ 	enables |= 0x0007fe00; /* Disable all cpu->pci windows */
+@@ -429,9 +429,9 @@ static void prpmc2800_fixups(void)
+ 	setprop(devp, "model", model, l);
+ 
+ 	/* Set /cpus/PowerPC,7447/clock-frequency */
+-	devp = finddevice("/cpus/PowerPC,7447");
++	devp = find_node_by_prop_value_str(NULL, "device_type", "cpu");
+ 	if (devp == NULL)
+-		fatal("Error: Missing proper /cpus device tree node\n\r");
++		fatal("Error: Missing proper cpu device tree node\n\r");
+ 	v[0] = bip->core_speed;
+ 	setprop(devp, "clock-frequency", &v[0], sizeof(v[0]));
+ 
+@@ -443,16 +443,17 @@ static void prpmc2800_fixups(void)
+ 	v[1] = bip->mem_size;
+ 	setprop(devp, "reg", v, sizeof(v));
+ 
+-	/* Update /mv64x60/model, if this is a mv64362 */
++	/* Update model, if this is a mv64362 */
+ 	if (bip->bridge_type == BRIDGE_TYPE_MV64362) {
+-		devp = finddevice("/mv64x60");
++		devp = find_node_by_compatible(NULL, "marvell,mv64360");
+ 		if (devp == NULL)
+-			fatal("Error: Missing /mv64x60 device tree node\n\r");
++			fatal("Error: Missing marvell,mv64360"
++					" device tree node\n\r");
+ 		setprop(devp, "model", "mv64362", strlen("mv64362") + 1);
+ 	}
+ 
+ 	/* Set User FLASH size */
+-	devp = finddevice("/mv64x60/flash at a0000000");
++	devp = find_node_by_compatible(NULL, "direct-mapped");
+ 	if (devp == NULL)
+ 		fatal("Error: Missing User FLASH device tree node\n\r");
+ 	rc = getprop(devp, "reg", v, sizeof(v));
+diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S
+index a55c273..b6fcbaf 100644
+--- a/arch/powerpc/boot/ps3-head.S
++++ b/arch/powerpc/boot/ps3-head.S
+@@ -27,8 +27,9 @@
+ /*
+  * __system_reset_overlay - The PS3 first stage entry.
+  *
+- * The bootwraper build script copies the 0x100 bytes at symbol
+- * __system_reset_overlay to offset 0x100 of the rom image.
++ * The bootwraper build script copies the 512 bytes at symbol
++ * __system_reset_overlay to offset 0x100 of the rom image.  This symbol
++ * must occupy 512 or less bytes.
+  *
+  * The PS3 has a single processor with two threads.
+  */
+@@ -47,8 +48,6 @@ __system_reset_overlay:
+ 
+ 	mfspr	r3, 0x88
+ 	cntlzw.	r3, r3
+-	li	r4, 0
+-	li	r5, 0
+ 	beq	1f
+ 
+ 	/* Secondary goes to __secondary_hold in kernel. */
+@@ -57,8 +56,14 @@ __system_reset_overlay:
+ 	mtctr	r4
+ 	bctr
+ 
+-	/* Primary delays then goes to _zimage_start in wrapper. */
+ 1:
++	/* Save the value at addr zero for a null pointer write check later. */
++
++	li	r4, 0
++	lwz	r3, 0(r4)
++
++	/* Primary delays then goes to _zimage_start in wrapper. */
++
+ 	or	31, 31, 31 /* db16cyc */
+ 	or	31, 31, 31 /* db16cyc */
+ 
+@@ -67,16 +72,18 @@ __system_reset_overlay:
+ 	mtctr	r4
+ 	bctr
+ 
++	. = __system_reset_overlay + 512
++
+ /*
+  * __system_reset_kernel - Place holder for the kernel reset vector.
+  *
+- * The bootwrapper build script copies 0x100 bytes from offset 0x100
++ * The bootwrapper build script copies 512 bytes from offset 0x100
+  * of the rom image to the symbol __system_reset_kernel.  At runtime
+- * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel
+- * to ram address 0x100.  This symbol must occupy 0x100 bytes.
++ * the bootwrapper program copies the 512 bytes at __system_reset_kernel
++ * to ram address 0x100.  This symbol must occupy 512 bytes.
+  */
+ 
+ 	.globl __system_reset_kernel
+ __system_reset_kernel:
+ 
+-	. = __system_reset_kernel + 0x100
++	. = __system_reset_kernel + 512
+diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
+index 3b0ac4d..9954d98 100644
+--- a/arch/powerpc/boot/ps3.c
++++ b/arch/powerpc/boot/ps3.c
+@@ -27,10 +27,10 @@
+ #include "page.h"
+ #include "ops.h"
+ 
+-extern s64 lv1_panic(u64 in_1);
+-extern s64 lv1_get_logical_partition_id(u64 *out_1);
+-extern s64 lv1_get_logical_ppe_id(u64 *out_1);
+-extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
++extern int lv1_panic(u64 in_1);
++extern int lv1_get_logical_partition_id(u64 *out_1);
++extern int lv1_get_logical_ppe_id(u64 *out_1);
++extern int lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
+ 	u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
+ 
+ #ifdef DEBUG
+@@ -46,6 +46,7 @@ BSS_STACK(4096);
+  * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+  * The buffer is put in it's own section so that tools may locate it easier.
+  */
++
+ static char cmdline[COMMAND_LINE_SIZE]
+ 	__attribute__((__section__("__builtin_cmdline")));
+ 
+@@ -75,7 +76,7 @@ static void ps3_exit(void)
+ 
+ static int ps3_repository_read_rm_size(u64 *rm_size)
+ {
+-	s64 result;
++	int result;
+ 	u64 lpar_id;
+ 	u64 ppe_id;
+ 	u64 v2;
+@@ -114,16 +115,17 @@ void ps3_copy_vectors(void)
+ {
+ 	extern char __system_reset_kernel[];
+ 
+-	memcpy((void *)0x100, __system_reset_kernel, 0x100);
+-	flush_cache((void *)0x100, 0x100);
++	memcpy((void *)0x100, __system_reset_kernel, 512);
++	flush_cache((void *)0x100, 512);
+ }
+ 
+-void platform_init(void)
++void platform_init(unsigned long null_check)
+ {
+ 	const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
+ 	void *chosen;
+ 	unsigned long ft_addr;
+ 	u64 rm_size;
++	unsigned long val;
+ 
+ 	console_ops.write = ps3_console_write;
+ 	platform_ops.exit = ps3_exit;
+@@ -151,6 +153,11 @@ void platform_init(void)
+ 
+ 	printf(" flat tree at 0x%lx\n\r", ft_addr);
+ 
++	val = *(unsigned long *)0;
++
++	if (val != null_check)
++		printf("null check failed: %lx != %lx\n\r", val, null_check);
++
+ 	((kernel_entry_t)0)(ft_addr, 0, NULL);
+ 
+ 	ps3_exit();
+diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
+index 9960421..8b3607c 100644
+--- a/arch/powerpc/boot/serial.c
++++ b/arch/powerpc/boot/serial.c
+@@ -119,7 +119,7 @@ int serial_console_init(void)
+ 
+ 	if (dt_is_compatible(devp, "ns16550"))
+ 		rc = ns16550_console_init(devp, &serial_cd);
+-	else if (dt_is_compatible(devp, "marvell,mpsc"))
++	else if (dt_is_compatible(devp, "marvell,mv64360-mpsc"))
+ 		rc = mpsc_console_init(devp, &serial_cd);
+ 	else if (dt_is_compatible(devp, "fsl,cpm1-scc-uart") ||
+ 	         dt_is_compatible(devp, "fsl,cpm1-smc-uart") ||
+diff --git a/arch/powerpc/boot/simpleboot.c b/arch/powerpc/boot/simpleboot.c
+new file mode 100644
+index 0000000..86cd285
+--- /dev/null
++++ b/arch/powerpc/boot/simpleboot.c
+@@ -0,0 +1,84 @@
++/*
++ * The simple platform -- for booting when firmware doesn't supply a device
++ *                        tree or any platform configuration information.
++ *                        All data is extracted from an embedded device tree
++ *                        blob.
++ *
++ * Authors: Scott Wood <scottwood at freescale.com>
++ *          Grant Likely <grant.likely at secretlab.ca>
++ *
++ * Copyright (c) 2007 Freescale Semiconductor, Inc.
++ * Copyright (c) 2008 Secret Lab Technologies Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#include "ops.h"
++#include "types.h"
++#include "io.h"
++#include "stdio.h"
++#include "libfdt/libfdt.h"
++
++BSS_STACK(4*1024);
++
++void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
++		   unsigned long r6, unsigned long r7)
++{
++	const u32 *na, *ns, *reg, *timebase;
++	u64 memsize64;
++	int node, size, i;
++
++	/* Make sure FDT blob is sane */
++	if (fdt_check_header(_dtb_start) != 0)
++		fatal("Invalid device tree blob\n");
++
++	/* Find the #address-cells and #size-cells properties */
++	node = fdt_path_offset(_dtb_start, "/");
++	if (node < 0)
++		fatal("Cannot find root node\n");
++	na = fdt_getprop(_dtb_start, node, "#address-cells", &size);
++	if (!na || (size != 4))
++		fatal("Cannot find #address-cells property");
++	ns = fdt_getprop(_dtb_start, node, "#size-cells", &size);
++	if (!ns || (size != 4))
++		fatal("Cannot find #size-cells property");
++
++	/* Find the memory range */
++	node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
++					     "memory", sizeof("memory"));
++	if (node < 0)
++		fatal("Cannot find memory node\n");
++	reg = fdt_getprop(_dtb_start, node, "reg", &size);
++	if (size < (*na+*ns) * sizeof(u32))
++		fatal("cannot get memory range\n");
++
++	/* Only interested in memory based at 0 */
++	for (i = 0; i < *na; i++)
++		if (*reg++ != 0)
++			fatal("Memory range is not based at address 0\n");
++
++	/* get the memsize and trucate it to under 4G on 32 bit machines */
++	memsize64 = 0;
++	for (i = 0; i < *ns; i++)
++		memsize64 = (memsize64 << 32) | *reg++;
++	if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL)
++		memsize64 = 0xffffffff;
++
++	/* finally, setup the timebase */
++	node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
++					     "cpu", sizeof("cpu"));
++	if (!node)
++		fatal("Cannot find cpu node\n");
++	timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
++	if (timebase && (size == 4))
++		timebase_period_ns = 1000000000 / *timebase;
++
++	/* Now we have the memory size; initialize the heap */
++	simple_alloc_init(_end, memsize64 - (unsigned long)_end, 32, 64);
++
++	/* prepare the device tree and find the console */
++	fdt_init(_dtb_start);
++	serial_console_init();
++}
+diff --git a/arch/powerpc/boot/treeboot-walnut.c b/arch/powerpc/boot/treeboot-walnut.c
+index 472e366..097974e 100644
+--- a/arch/powerpc/boot/treeboot-walnut.c
++++ b/arch/powerpc/boot/treeboot-walnut.c
+@@ -68,7 +68,7 @@ static void walnut_fixups(void)
+ 	ibm4xx_quiesce_eth((u32 *)0xef600800, NULL);
+ 	ibm4xx_fixup_ebc_ranges("/plb/ebc");
+ 	walnut_flashsel_fixup();
+-	dt_fixup_mac_addresses((u8 *) WALNUT_OPENBIOS_MAC_OFF);
++	dt_fixup_mac_address_by_alias("ethernet0", (u8 *) WALNUT_OPENBIOS_MAC_OFF);
+ }
+ 
+ void platform_init(void)
+diff --git a/arch/powerpc/boot/virtex405-head.S b/arch/powerpc/boot/virtex405-head.S
+new file mode 100644
+index 0000000..3edb13f
+--- /dev/null
++++ b/arch/powerpc/boot/virtex405-head.S
+@@ -0,0 +1,30 @@
++#include "ppc_asm.h"
++
++	.text
++	.global _zimage_start
++_zimage_start:
++
++	/* PPC errata 213: needed by Virtex-4 FX */
++	mfccr0  0
++	oris    0,0,0x50000000 at h
++	mtccr0  0
++
++	/*
++	 * Invalidate the data cache if the data cache is turned off.
++	 * - The 405 core does not invalidate the data cache on power-up
++	 *   or reset but does turn off the data cache. We cannot assume
++	 *   that the cache contents are valid.
++	 * - If the data cache is turned on this must have been done by
++	 *   a bootloader and we assume that the cache contents are
++	 *   valid.
++	 */
++	mfdccr	r9
++	cmplwi	r9,0
++	bne	2f
++	lis	r9,0
++	li	r8,256
++	mtctr	r8
++1:	dccci	r0,r9
++	addi	r9,r9,0x20
++	bdnz	1b
++2:	b	_zimage_start_lib
+diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
+index 8f8b849..d6c96d9 100755
+--- a/arch/powerpc/boot/wrapper
++++ b/arch/powerpc/boot/wrapper
+@@ -174,7 +174,7 @@ cuboot*)
+     *-mpc83*)
+         platformo=$object/cuboot-83xx.o
+         ;;
+-    *-tqm8541|*-mpc8560*|*-tqm8560|*-tqm8555)
++    *-tqm8541|*-mpc8560*|*-tqm8560|*-tqm8555|*-ksi8560*)
+         platformo=$object/cuboot-85xx-cpm2.o
+         ;;
+     *-mpc85*|*-tqm8540|*-sbc85*)
+@@ -199,6 +199,10 @@ adder875-redboot)
+     platformo="$object/fixed-head.o $object/redboot-8xx.o"
+     binary=y
+     ;;
++simpleboot-virtex405-*)
++    platformo="$object/virtex405-head.o $object/simpleboot.o"
++    binary=y
++    ;;
+ esac
+ 
+ vmz="$tmpdir/`basename \"$kernel\"`.$ext"
+@@ -226,10 +230,13 @@ if [ -n "$version" ]; then
+     uboot_version="-n Linux-$version"
+ fi
+ 
++# physical offset of kernel image
++membase=`${CROSS}objdump -p "$kernel" | grep -m 1 LOAD | awk '{print $7}'`
++
+ case "$platform" in
+ uboot)
+     rm -f "$ofile"
+-    mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \
++    mkimage -A ppc -O linux -T kernel -C gzip -a $membase -e $membase \
+ 	$uboot_version -d "$vmz" "$ofile"
+     if [ -z "$cacheit" ]; then
+ 	rm -f "$vmz"
+@@ -298,15 +305,16 @@ treeboot*)
+     exit 0
+     ;;
+ ps3)
+-    # The ps3's loader supports loading gzipped binary images from flash
+-    # rom to addr zero. The loader enters the image at addr 0x100.  A
+-    # bootwrapper overlay is use to arrange for the kernel to be loaded
+-    # to addr zero and to have a suitable bootwrapper entry at 0x100.
+-    # To construct the rom image, 0x100 bytes from offset 0x100 in the
+-    # kernel is copied to the bootwrapper symbol __system_reset_kernel.
+-    # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is
+-    # then copied to offset 0x100.  At runtime the bootwrapper program
+-    # copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
++    # The ps3's loader supports loading a gzipped binary image from flash
++    # rom to ram addr zero. The loader then enters the system reset
++    # vector at addr 0x100.  A bootwrapper overlay is used to arrange for
++    # a binary image of the kernel to be at addr zero, and yet have a
++    # suitable bootwrapper entry at 0x100.  To construct the final rom
++    # image 512 bytes from offset 0x100 is copied to the bootwrapper
++    # place holder at symbol __system_reset_kernel.  The 512 bytes of the
++    # bootwrapper entry code at symbol __system_reset_overlay is then
++    # copied to offset 0x100.  At runtime the bootwrapper program copies
++    # the data at __system_reset_kernel back to addr 0x100.
+ 
+     system_reset_overlay=0x`${CROSS}nm "$ofile" \
+         | grep ' __system_reset_overlay$'       \
+@@ -317,7 +325,7 @@ ps3)
+         | cut -d' ' -f1`
+     system_reset_kernel=`printf "%d" $system_reset_kernel`
+     overlay_dest="256"
+-    overlay_size="256"
++    overlay_size="512"
+ 
+     ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
+ 
+diff --git a/arch/powerpc/configs/40x/ep405_defconfig b/arch/powerpc/configs/40x/ep405_defconfig
+new file mode 100644
+index 0000000..e24240a
+--- /dev/null
++++ b/arch/powerpc/configs/40x/ep405_defconfig
+@@ -0,0 +1,968 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:50:09 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_EP405=y
++# CONFIG_KILAUEA is not set
++# CONFIG_MAKALU is not set
++# CONFIG_WALNUT is not set
++# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
++CONFIG_405GP=y
++CONFIG_IBM405_ERR77=y
++CONFIG_IBM405_ERR51=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig
+new file mode 100644
+index 0000000..2f47539
+--- /dev/null
++++ b/arch/powerpc/configs/40x/kilauea_defconfig
+@@ -0,0 +1,839 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:51:43 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_EP405 is not set
++CONFIG_KILAUEA=y
++# CONFIG_MAKALU is not set
++# CONFIG_WALNUT is not set
++# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
++CONFIG_405EX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=256
++CONFIG_IBM_NEW_EMAC_TXB=256
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++CONFIG_IBM_NEW_EMAC_RGMII=y
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/40x/makalu_defconfig b/arch/powerpc/configs/40x/makalu_defconfig
+new file mode 100644
+index 0000000..9ef4d8a
+--- /dev/null
++++ b/arch/powerpc/configs/40x/makalu_defconfig
+@@ -0,0 +1,839 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:52:30 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_EP405 is not set
++# CONFIG_KILAUEA is not set
++CONFIG_MAKALU=y
++# CONFIG_WALNUT is not set
++# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
++CONFIG_405EX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=256
++CONFIG_IBM_NEW_EMAC_TXB=256
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++CONFIG_IBM_NEW_EMAC_RGMII=y
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/40x/walnut_defconfig b/arch/powerpc/configs/40x/walnut_defconfig
+new file mode 100644
+index 0000000..3b2689e
+--- /dev/null
++++ b/arch/powerpc/configs/40x/walnut_defconfig
+@@ -0,0 +1,887 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:54:12 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_EP405 is not set
++# CONFIG_KILAUEA is not set
++# CONFIG_MAKALU is not set
++CONFIG_WALNUT=y
++# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
++CONFIG_405GP=y
++CONFIG_IBM405_ERR77=y
++CONFIG_IBM405_ERR51=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_OF_RTC=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++# CONFIG_PCI_LEGACY is not set
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/bamboo_defconfig b/arch/powerpc/configs/44x/bamboo_defconfig
+new file mode 100644
+index 0000000..c44db55
+--- /dev/null
++++ b/arch/powerpc/configs/44x/bamboo_defconfig
+@@ -0,0 +1,815 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:36:39 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_BAMBOO=y
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_440EP=y
++CONFIG_IBM440EP_ERR42=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig
+new file mode 100644
+index 0000000..a3b763c
+--- /dev/null
++++ b/arch/powerpc/configs/44x/canyonlands_defconfig
+@@ -0,0 +1,721 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc1
++# Thu Feb 21 14:29:28 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++# CONFIG_FAIR_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++# CONFIG_LOGBUFFER is not set
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_CANYONLANDS=y
++CONFIG_460EX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_WANT_DEVICE_TREE=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=256
++CONFIG_IBM_NEW_EMAC_TXB=256
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++CONFIG_IBM_NEW_EMAC_TAH=y
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++# CONFIG_CRYPTO is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/ebony_defconfig b/arch/powerpc/configs/44x/ebony_defconfig
+new file mode 100644
+index 0000000..07c8d4c
+--- /dev/null
++++ b/arch/powerpc/configs/44x/ebony_defconfig
+@@ -0,0 +1,898 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:50:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++CONFIG_EBONY=y
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_440GP=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_OF_RTC=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++# CONFIG_CRYPTO_HW is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/katmai_defconfig b/arch/powerpc/configs/44x/katmai_defconfig
+new file mode 100644
+index 0000000..c8804ec
+--- /dev/null
++++ b/arch/powerpc/configs/44x/katmai_defconfig
+@@ -0,0 +1,790 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24-rc6
++# Mon Dec 24 11:17:43 2007
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC52xx is not set
++# CONFIG_PPC_MPC5200 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++CONFIG_KATMAI=y
++# CONFIG_RAINIER is not set
++CONFIG_440SPe=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_WANT_DEVICE_TREE=y
++CONFIG_DEVICE_TREE="katmai.dts"
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++CONFIG_MACINTOSH_DRIVERS=y
++# CONFIG_MAC_EMUMOUSEBTN is not set
++# CONFIG_WINDFARM is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_IP1000 is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++# CONFIG_UCC_SLOW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_INSTRUMENTATION=y
++# CONFIG_PROFILING is not set
++# CONFIG_KPROBES is not set
++# CONFIG_MARKERS is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/rainier_defconfig b/arch/powerpc/configs/44x/rainier_defconfig
+new file mode 100644
+index 0000000..dec18ca
+--- /dev/null
++++ b/arch/powerpc/configs/44x/rainier_defconfig
+@@ -0,0 +1,899 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:53:10 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++CONFIG_RAINIER=y
++# CONFIG_WARP is not set
++CONFIG_440GRX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++# CONFIG_MTD_BLKDEVS is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++CONFIG_MACINTOSH_DRIVERS=y
++# CONFIG_MAC_EMUMOUSEBTN is not set
++# CONFIG_WINDFARM is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++CONFIG_PPC_EARLY_DEBUG=y
++# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
++# CONFIG_PPC_EARLY_DEBUG_G5 is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
++# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
++# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
++# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
++CONFIG_PPC_EARLY_DEBUG_44x=y
++# CONFIG_PPC_EARLY_DEBUG_40x is not set
++# CONFIG_PPC_EARLY_DEBUG_CPM is not set
++CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
++CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x1
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/sequoia_defconfig b/arch/powerpc/configs/44x/sequoia_defconfig
+new file mode 100644
+index 0000000..dd5d630
+--- /dev/null
++++ b/arch/powerpc/configs/44x/sequoia_defconfig
+@@ -0,0 +1,916 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:53:46 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++CONFIG_SEQUOIA=y
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_440EPX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++# CONFIG_MTD_BLKDEVS is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++CONFIG_PPC_EARLY_DEBUG=y
++# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
++# CONFIG_PPC_EARLY_DEBUG_G5 is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
++# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
++# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
++# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
++CONFIG_PPC_EARLY_DEBUG_44x=y
++# CONFIG_PPC_EARLY_DEBUG_40x is not set
++# CONFIG_PPC_EARLY_DEBUG_CPM is not set
++CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
++CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x1
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/taishan_defconfig b/arch/powerpc/configs/44x/taishan_defconfig
+new file mode 100644
+index 0000000..087aedc
+--- /dev/null
++++ b/arch/powerpc/configs/44x/taishan_defconfig
+@@ -0,0 +1,815 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:40:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++CONFIG_TAISHAN=y
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_440GX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++CONFIG_MACINTOSH_DRIVERS=y
++# CONFIG_MAC_EMUMOUSEBTN is not set
++# CONFIG_WINDFARM is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++CONFIG_IBM_NEW_EMAC_TAH=y
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig
+new file mode 100644
+index 0000000..2313c3e
+--- /dev/null
++++ b/arch/powerpc/configs/44x/warp_defconfig
+@@ -0,0 +1,1110 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:54:43 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION="-pika"
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++CONFIG_WARP=y
++CONFIG_440EP=y
++CONFIG_IBM440EP_ERR42=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++# CONFIG_HZ_250 is not set
++# CONFIG_HZ_300 is not set
++CONFIG_HZ_1000=y
++CONFIG_HZ=1000
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE="ip=on"
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++# CONFIG_NETFILTER_XTABLES is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++CONFIG_VLAN_8021Q=y
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++# CONFIG_STANDALONE is not set
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++CONFIG_MTD_OOPS=m
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++CONFIG_MTD_NAND_ECC_SMC=y
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_NAND_FSL_ELBC is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++# CONFIG_I2C_CHARDEV is not set
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_MPC is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=m
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=m
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++# CONFIG_MMC_WBSD is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++CONFIG_NLS_ISO8859_15=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_SCHED_DEBUG is not set
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++CONFIG_BDI_SWITCH=y
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
+new file mode 100644
+index 0000000..7d18440
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
+@@ -0,0 +1,1395 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Fri Apr 11 11:10:09 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++CONFIG_MPC831x_RDB=y
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC831x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_FORCE_MAX_ZONEORDER=11
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_CAFE is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++CONFIG_MTD_NAND_FSL_ELBC=y
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++CONFIG_MD_LINEAR=y
++CONFIG_MD_RAID0=y
++CONFIG_MD_RAID1=y
++# CONFIG_MD_RAID10 is not set
++# CONFIG_MD_RAID456 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_MD_FAULTY is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++CONFIG_CICADA_PHY=y
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_ENC28J60 is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++CONFIG_USB_GADGET_NET2280=y
++CONFIG_USB_NET2280=y
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
+new file mode 100644
+index 0000000..1f57456
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
+@@ -0,0 +1,1451 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:15 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++CONFIG_MPC831x_RDB=y
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC831x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_CAFE is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_NAND_FSL_ELBC is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++CONFIG_SATA_FSL=y
++# CONFIG_PATA_ALI is not set
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++# CONFIG_PATA_PLATFORM is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++CONFIG_MD_LINEAR=y
++CONFIG_MD_RAID0=y
++CONFIG_MD_RAID1=y
++# CONFIG_MD_RAID10 is not set
++# CONFIG_MD_RAID456 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_MD_FAULTY is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_ENC28J60 is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++CONFIG_USB_GADGET_NET2280=y
++CONFIG_USB_NET2280=y
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc832x_mds_defconfig b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
+new file mode 100644
+index 0000000..50cceda
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
+@@ -0,0 +1,1081 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:36:51 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++CONFIG_MPC832x_MDS=y
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC832x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_QUICC_ENGINE=y
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++CONFIG_DAVICOM_PHY=y
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_GIANFAR is not set
++CONFIG_UCC_GETH=y
++# CONFIG_UGETH_NAPI is not set
++# CONFIG_UGETH_MAGIC_PACKET is not set
++# CONFIG_UGETH_FILTERING is not set
++# CONFIG_UGETH_TX_ON_DEMAND is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++# CONFIG_SERIAL_QE is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++CONFIG_RTC_DRV_DS1374=y
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++CONFIG_UCC_FAST=y
++CONFIG_UCC=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
+new file mode 100644
+index 0000000..ac91302
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
+@@ -0,0 +1,1233 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:16 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++CONFIG_MPC832x_RDB=y
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC832x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_QUICC_ENGINE=y
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++CONFIG_ICPLUS_PHY=y
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_ENC28J60 is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++CONFIG_E1000=y
++# CONFIG_E1000_NAPI is not set
++# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_GIANFAR is not set
++CONFIG_UCC_GETH=y
++CONFIG_UGETH_NAPI=y
++# CONFIG_UGETH_MAGIC_PACKET is not set
++# CONFIG_UGETH_FILTERING is not set
++# CONFIG_UGETH_TX_ON_DEMAND is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++# CONFIG_SERIAL_QE is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_EHCI_FSL is not set
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++# CONFIG_MMC_SDHCI is not set
++# CONFIG_MMC_WBSD is not set
++# CONFIG_MMC_TIFM_SD is not set
++CONFIG_MMC_SPI=y
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++CONFIG_LDM_PARTITION=y
++# CONFIG_LDM_DEBUG is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++CONFIG_NLS_ISO8859_8=y
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++CONFIG_UCC_FAST=y
++CONFIG_UCC=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++CONFIG_CRC_ITU_T=y
++CONFIG_CRC32=y
++CONFIG_CRC7=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
+new file mode 100644
+index 0000000..e1de399
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
+@@ -0,0 +1,1295 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:17 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++CONFIG_MPC834x_ITX=y
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC834x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++# CONFIG_MTD_PARTITIONS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++# CONFIG_MTD_BLKDEVS is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0xfe000000
++CONFIG_MTD_PHYSMAP_LEN=0x1000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++# CONFIG_BLK_DEV_IDE is not set
++# CONFIG_BLK_DEV_HD_ONLY is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++CONFIG_SATA_SIL=y
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_SATA_FSL is not set
++# CONFIG_PATA_ALI is not set
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++CONFIG_PATA_PLATFORM=y
++CONFIG_PATA_OF_PLATFORM=y
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++CONFIG_MD_LINEAR=y
++CONFIG_MD_RAID0=y
++CONFIG_MD_RAID1=y
++# CONFIG_MD_RAID10 is not set
++# CONFIG_MD_RAID456 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_MD_FAULTY is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++CONFIG_CICADA_PHY=y
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++CONFIG_SENSORS_PCF8574=y
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_OHCI_HCD is not set
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
+new file mode 100644
+index 0000000..b4e39cf
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
+@@ -0,0 +1,1222 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:18 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++CONFIG_MPC834x_ITX=y
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC834x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++# CONFIG_MTD_PARTITIONS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++# CONFIG_MTD_BLKDEVS is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0xfe000000
++CONFIG_MTD_PHYSMAP_LEN=0x800000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++CONFIG_CICADA_PHY=y
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++CONFIG_SENSORS_PCF8574=y
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_OHCI_HCD is not set
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc834x_mds_defconfig b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
+new file mode 100644
+index 0000000..b4e82c0
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
+@@ -0,0 +1,1021 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:36:56 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++CONFIG_MPC834x_MDS=y
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC834x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=m
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++# CONFIG_GFAR_NAPI is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++CONFIG_RTC_DRV_DS1374=y
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc836x_mds_defconfig b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
+new file mode 100644
+index 0000000..d50a96e
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
+@@ -0,0 +1,1079 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:36:57 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++CONFIG_MPC836x_MDS=y
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_QUICC_ENGINE=y
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_GIANFAR is not set
++CONFIG_UCC_GETH=y
++# CONFIG_UGETH_NAPI is not set
++# CONFIG_UGETH_MAGIC_PACKET is not set
++# CONFIG_UGETH_FILTERING is not set
++# CONFIG_UGETH_TX_ON_DEMAND is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++# CONFIG_SERIAL_QE is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++CONFIG_RTC_DRV_DS1374=y
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++CONFIG_UCC_FAST=y
++CONFIG_UCC=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/83xx/mpc837x_mds_defconfig b/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
+new file mode 100644
+index 0000000..f377cde
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
+@@ -0,0 +1,899 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:23 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++CONFIG_MPC837x_MDS=y
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC837x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=m
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_MV is not set
++CONFIG_SATA_FSL=y
++# CONFIG_PATA_PLATFORM is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++# CONFIG_GFAR_NAPI is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
+new file mode 100644
+index 0000000..a633176
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
+@@ -0,0 +1,930 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:24 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++CONFIG_MPC837x_RDB=y
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC837x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_MV is not set
++CONFIG_SATA_FSL=y
++# CONFIG_PATA_PLATFORM is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++# CONFIG_MD_LINEAR is not set
++# CONFIG_MD_RAID0 is not set
++CONFIG_MD_RAID1=y
++# CONFIG_MD_RAID10 is not set
++CONFIG_MD_RAID456=y
++CONFIG_MD_RAID5_RESHAPE=y
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_MD_FAULTY is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++# CONFIG_ENABLE_MUST_CHECK is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_XOR_BLOCKS=y
++CONFIG_ASYNC_CORE=y
++CONFIG_ASYNC_MEMCPY=y
++CONFIG_ASYNC_XOR=y
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/sbc834x_defconfig b/arch/powerpc/configs/83xx/sbc834x_defconfig
+new file mode 100644
+index 0000000..1f15182
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/sbc834x_defconfig
+@@ -0,0 +1,828 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:38 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++CONFIG_SBC834x=y
++CONFIG_PPC_MPC834x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=m
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++CONFIG_BROADCOM_PHY=y
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++# CONFIG_GFAR_NAPI is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++# CONFIG_CRYPTO_HW is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/ksi8560_defconfig b/arch/powerpc/configs/85xx/ksi8560_defconfig
+new file mode 100644
+index 0000000..2d0debc
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/ksi8560_defconfig
+@@ -0,0 +1,899 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24
++# Mon Feb 11 16:25:19 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++CONFIG_KSI8560=y
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++CONFIG_HIGHMEM=y
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_WANT_DEVICE_TREE=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++# CONFIG_BLK_DEV_IDEDISK is not set
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++# CONFIG_BLK_DEV_IDEDMA is not set
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++CONFIG_MDIO_BITBANG=y
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_FS_ENET=y
++# CONFIG_FS_ENET_HAS_SCC is not set
++CONFIG_FS_ENET_HAS_FCC=y
++CONFIG_FS_ENET_MDIO_FCC=y
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++# CONFIG_SERIAL_CPM_SCC2 is not set
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++# CONFIG_USB_ARCH_HAS_HCD is not set
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/mpc8540_ads_defconfig b/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
+new file mode 100644
+index 0000000..b998539
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
+@@ -0,0 +1,796 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:25 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++CONFIG_MPC8540_ADS=y
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++# CONFIG_USB_ARCH_HAS_HCD is not set
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
+new file mode 100644
+index 0000000..a9f113b
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
+@@ -0,0 +1,1564 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:37:03 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++CONFIG_AUDIT=y
++# CONFIG_AUDITSYSCALL is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++CONFIG_MPC85xx_DS=y
++# CONFIG_KSI8560 is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++CONFIG_PPC_I8259=y
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++CONFIG_FSL_ULI1575=y
++
++#
++# Kernel options
++#
++CONFIG_HIGHMEM=y
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=m
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=m
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_ASK_IP_FIB_HASH=y
++# CONFIG_IP_FIB_TRIE is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_NET_IPIP=y
++CONFIG_NET_IPGRE=y
++CONFIG_NET_IPGRE_BROADCAST=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++CONFIG_ARPD=y
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=y
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_INET6_XFRM_MODE_TRANSPORT=y
++CONFIG_INET6_XFRM_MODE_TUNNEL=y
++CONFIG_INET6_XFRM_MODE_BEET=y
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++CONFIG_IP_SCTP=m
++# CONFIG_SCTP_DBG_MSG is not set
++# CONFIG_SCTP_DBG_OBJCNT is not set
++# CONFIG_SCTP_HMAC_NONE is not set
++# CONFIG_SCTP_HMAC_SHA1 is not set
++CONFIG_SCTP_HMAC_MD5=y
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=y
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=131072
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++CONFIG_CHR_DEV_ST=y
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=y
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++CONFIG_SATA_AHCI=y
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_SATA_FSL is not set
++CONFIG_PATA_ALI=y
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++# CONFIG_PATA_PLATFORM is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++CONFIG_DUMMY=y
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++CONFIG_VITESSE_PHY=y
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_I8042=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_PCIPS2 is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_MANY_PORTS=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_DETECT_IRQ=y
++CONFIG_SERIAL_8250_RSA=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++# CONFIG_I2C_CHARDEV is not set
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++CONFIG_DVB_CORE=m
++# CONFIG_DVB_CORE_ATTACH is not set
++CONFIG_DVB_CAPTURE_DRIVERS=y
++
++#
++# Supported SAA7146 based PCI Adapters
++#
++# CONFIG_TTPCI_EEPROM is not set
++# CONFIG_DVB_BUDGET_CORE is not set
++
++#
++# Supported USB Adapters
++#
++# CONFIG_DVB_USB is not set
++# CONFIG_DVB_TTUSB_BUDGET is not set
++# CONFIG_DVB_TTUSB_DEC is not set
++# CONFIG_DVB_CINERGYT2 is not set
++
++#
++# Supported FlexCopII (B2C2) Adapters
++#
++# CONFIG_DVB_B2C2_FLEXCOP is not set
++
++#
++# Supported BT878 Adapters
++#
++
++#
++# Supported Pluto2 Adapters
++#
++# CONFIG_DVB_PLUTO2 is not set
++
++#
++# Supported DVB Frontends
++#
++
++#
++# Customise DVB Frontends
++#
++# CONFIG_DVB_FE_CUSTOMISE is not set
++
++#
++# DVB-S (satellite) frontends
++#
++# CONFIG_DVB_STV0299 is not set
++# CONFIG_DVB_CX24110 is not set
++# CONFIG_DVB_CX24123 is not set
++# CONFIG_DVB_TDA8083 is not set
++# CONFIG_DVB_MT312 is not set
++# CONFIG_DVB_VES1X93 is not set
++# CONFIG_DVB_S5H1420 is not set
++# CONFIG_DVB_TDA10086 is not set
++
++#
++# DVB-T (terrestrial) frontends
++#
++# CONFIG_DVB_SP8870 is not set
++# CONFIG_DVB_SP887X is not set
++# CONFIG_DVB_CX22700 is not set
++# CONFIG_DVB_CX22702 is not set
++# CONFIG_DVB_L64781 is not set
++# CONFIG_DVB_TDA1004X is not set
++# CONFIG_DVB_NXT6000 is not set
++# CONFIG_DVB_MT352 is not set
++# CONFIG_DVB_ZL10353 is not set
++# CONFIG_DVB_DIB3000MB is not set
++# CONFIG_DVB_DIB3000MC is not set
++# CONFIG_DVB_DIB7000M is not set
++# CONFIG_DVB_DIB7000P is not set
++
++#
++# DVB-C (cable) frontends
++#
++# CONFIG_DVB_VES1820 is not set
++# CONFIG_DVB_TDA10021 is not set
++# CONFIG_DVB_TDA10023 is not set
++# CONFIG_DVB_STV0297 is not set
++
++#
++# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
++#
++# CONFIG_DVB_NXT200X is not set
++# CONFIG_DVB_OR51211 is not set
++# CONFIG_DVB_OR51132 is not set
++# CONFIG_DVB_BCM3510 is not set
++# CONFIG_DVB_LGDT330X is not set
++# CONFIG_DVB_S5H1409 is not set
++
++#
++# Tuners/PLL support
++#
++# CONFIG_DVB_PLL is not set
++# CONFIG_DVB_TDA826X is not set
++# CONFIG_DVB_TDA827X is not set
++# CONFIG_DVB_TDA18271 is not set
++# CONFIG_DVB_TUNER_QT1010 is not set
++# CONFIG_DVB_TUNER_MT2060 is not set
++# CONFIG_DVB_TUNER_MT2266 is not set
++# CONFIG_DVB_TUNER_MT2131 is not set
++# CONFIG_DVB_TUNER_DIB0070 is not set
++# CONFIG_DVB_TUNER_XC5000 is not set
++
++#
++# Miscellaneous devices
++#
++# CONFIG_DVB_LNBP21 is not set
++# CONFIG_DVB_ISL6421 is not set
++# CONFIG_DVB_TUA6100 is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++CONFIG_VGA_CONSOLE=y
++# CONFIG_VGACON_SOFT_SCROLLBACK is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++# CONFIG_SND_SEQUENCER is not set
++# CONFIG_SND_MIXER_OSS is not set
++# CONFIG_SND_PCM_OSS is not set
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++CONFIG_SND_AC97_CODEC=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# PCI devices
++#
++# CONFIG_SND_AD1889 is not set
++# CONFIG_SND_ALS300 is not set
++# CONFIG_SND_ALS4000 is not set
++# CONFIG_SND_ALI5451 is not set
++# CONFIG_SND_ATIIXP is not set
++# CONFIG_SND_ATIIXP_MODEM is not set
++# CONFIG_SND_AU8810 is not set
++# CONFIG_SND_AU8820 is not set
++# CONFIG_SND_AU8830 is not set
++# CONFIG_SND_AZT3328 is not set
++# CONFIG_SND_BT87X is not set
++# CONFIG_SND_CA0106 is not set
++# CONFIG_SND_CMIPCI is not set
++# CONFIG_SND_OXYGEN is not set
++# CONFIG_SND_CS4281 is not set
++# CONFIG_SND_CS46XX is not set
++# CONFIG_SND_CS5530 is not set
++# CONFIG_SND_DARLA20 is not set
++# CONFIG_SND_GINA20 is not set
++# CONFIG_SND_LAYLA20 is not set
++# CONFIG_SND_DARLA24 is not set
++# CONFIG_SND_GINA24 is not set
++# CONFIG_SND_LAYLA24 is not set
++# CONFIG_SND_MONA is not set
++# CONFIG_SND_MIA is not set
++# CONFIG_SND_ECHO3G is not set
++# CONFIG_SND_INDIGO is not set
++# CONFIG_SND_INDIGOIO is not set
++# CONFIG_SND_INDIGODJ is not set
++# CONFIG_SND_EMU10K1 is not set
++# CONFIG_SND_EMU10K1X is not set
++# CONFIG_SND_ENS1370 is not set
++# CONFIG_SND_ENS1371 is not set
++# CONFIG_SND_ES1938 is not set
++# CONFIG_SND_ES1968 is not set
++# CONFIG_SND_FM801 is not set
++# CONFIG_SND_HDA_INTEL is not set
++# CONFIG_SND_HDSP is not set
++# CONFIG_SND_HDSPM is not set
++# CONFIG_SND_HIFIER is not set
++# CONFIG_SND_ICE1712 is not set
++# CONFIG_SND_ICE1724 is not set
++CONFIG_SND_INTEL8X0=y
++# CONFIG_SND_INTEL8X0M is not set
++# CONFIG_SND_KORG1212 is not set
++# CONFIG_SND_MAESTRO3 is not set
++# CONFIG_SND_MIXART is not set
++# CONFIG_SND_NM256 is not set
++# CONFIG_SND_PCXHR is not set
++# CONFIG_SND_RIPTIDE is not set
++# CONFIG_SND_RME32 is not set
++# CONFIG_SND_RME96 is not set
++# CONFIG_SND_RME9652 is not set
++# CONFIG_SND_SONICVIBES is not set
++# CONFIG_SND_TRIDENT is not set
++# CONFIG_SND_VIA82XX is not set
++# CONFIG_SND_VIA82XX_MODEM is not set
++# CONFIG_SND_VIRTUOSO is not set
++# CONFIG_SND_VX222 is not set
++# CONFIG_SND_YMFPCI is not set
++# CONFIG_SND_AC97_POWER_SAVE is not set
++
++#
++# ALSA PowerMac devices
++#
++
++#
++# ALSA PowerPC devices
++#
++
++#
++# USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++# CONFIG_SND_USB_USX2Y is not set
++# CONFIG_SND_USB_CAIAQ is not set
++
++#
++# System on Chip audio support
++#
++# CONFIG_SND_SOC is not set
++
++#
++# SoC Audio support for SuperH
++#
++
++#
++# ALSA SoC audio for Freescale SOCs
++#
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=y
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_EHCI_FSL is not set
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++CONFIG_RTC_DRV_CMOS=y
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_DMADEVICES=y
++
++#
++# DMA Devices
++#
++CONFIG_FSL_DMA=y
++# CONFIG_FSL_DMA_SELFTEST is not set
++CONFIG_DMA_ENGINE=y
++
++#
++# DMA Clients
++#
++# CONFIG_NET_DMA is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++# CONFIG_NTFS_RW is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++CONFIG_ADFS_FS=m
++# CONFIG_ADFS_FS_RW is not set
++CONFIG_AFFS_FS=m
++CONFIG_HFS_FS=m
++CONFIG_HFSPLUS_FS=m
++CONFIG_BEFS_FS=m
++# CONFIG_BEFS_DEBUG is not set
++CONFIG_BFS_FS=m
++CONFIG_EFS_FS=m
++CONFIG_CRAMFS=y
++CONFIG_VXFS_FS=m
++# CONFIG_MINIX_FS is not set
++CONFIG_HPFS_FS=m
++CONFIG_QNX4FS_FS=m
++# CONFIG_ROMFS_FS is not set
++CONFIG_SYSV_FS=m
++CONFIG_UFS_FS=m
++# CONFIG_UFS_FS_WRITE is not set
++# CONFIG_UFS_DEBUG is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++CONFIG_NFSD=y
++# CONFIG_NFSD_V3 is not set
++CONFIG_NFSD_TCP=y
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_EXPORTFS=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=m
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=m
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/mpc8560_ads_defconfig b/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
+new file mode 100644
+index 0000000..851ac91
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
+@@ -0,0 +1,885 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:27 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++CONFIG_MPC8560_ADS=y
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++CONFIG_PCI_DEBUG=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++CONFIG_DAVICOM_PHY=y
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_FS_ENET=y
++# CONFIG_FS_ENET_HAS_SCC is not set
++CONFIG_FS_ENET_HAS_FCC=y
++# CONFIG_FS_ENET_MDIO_FCC is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++CONFIG_E1000=y
++CONFIG_E1000_NAPI=y
++# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++CONFIG_SERIAL_CPM_SCC2=y
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/mpc8568mds_defconfig b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
+new file mode 100644
+index 0000000..2b866b3
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
+@@ -0,0 +1,1117 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:37:05 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++CONFIG_MPC85xx_MDS=y
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_QUICC_ENGINE=y
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_UCC_GETH is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++# CONFIG_SERIAL_QE is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_BOOKE_WDT is not set
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++CONFIG_RTC_DRV_DS1374=y
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_XMON is not set
++# CONFIG_BDI_SWITCH is not set
++CONFIG_PPC_EARLY_DEBUG=y
++# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
++# CONFIG_PPC_EARLY_DEBUG_G5 is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
++# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
++# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
++# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
++# CONFIG_PPC_EARLY_DEBUG_44x is not set
++# CONFIG_PPC_EARLY_DEBUG_40x is not set
++# CONFIG_PPC_EARLY_DEBUG_CPM is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
+new file mode 100644
+index 0000000..53aa6f3
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
+@@ -0,0 +1,1549 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:37:06 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++CONFIG_AUDIT=y
++# CONFIG_AUDITSYSCALL is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++CONFIG_MPC85xx_DS=y
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++CONFIG_PPC_I8259=y
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++CONFIG_FSL_ULI1575=y
++
++#
++# Kernel options
++#
++CONFIG_HIGHMEM=y
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=m
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=m
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_ASK_IP_FIB_HASH=y
++# CONFIG_IP_FIB_TRIE is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_NET_IPIP=y
++CONFIG_NET_IPGRE=y
++CONFIG_NET_IPGRE_BROADCAST=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++CONFIG_ARPD=y
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=y
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_INET6_XFRM_MODE_TRANSPORT=y
++CONFIG_INET6_XFRM_MODE_TUNNEL=y
++CONFIG_INET6_XFRM_MODE_BEET=y
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++CONFIG_IP_SCTP=m
++# CONFIG_SCTP_DBG_MSG is not set
++# CONFIG_SCTP_DBG_OBJCNT is not set
++# CONFIG_SCTP_HMAC_NONE is not set
++# CONFIG_SCTP_HMAC_SHA1 is not set
++CONFIG_SCTP_HMAC_MD5=y
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=y
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=131072
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++CONFIG_CHR_DEV_ST=y
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=y
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++CONFIG_SATA_AHCI=y
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_SATA_FSL is not set
++CONFIG_PATA_ALI=y
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++# CONFIG_PATA_PLATFORM is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++CONFIG_DUMMY=y
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++CONFIG_VITESSE_PHY=y
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_I8042=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_PCIPS2 is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_MANY_PORTS=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_DETECT_IRQ=y
++CONFIG_SERIAL_8250_RSA=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++# CONFIG_I2C_CHARDEV is not set
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++CONFIG_DVB_CORE=m
++# CONFIG_DVB_CORE_ATTACH is not set
++CONFIG_DVB_CAPTURE_DRIVERS=y
++
++#
++# Supported SAA7146 based PCI Adapters
++#
++# CONFIG_TTPCI_EEPROM is not set
++# CONFIG_DVB_BUDGET_CORE is not set
++
++#
++# Supported USB Adapters
++#
++# CONFIG_DVB_USB is not set
++# CONFIG_DVB_TTUSB_BUDGET is not set
++# CONFIG_DVB_TTUSB_DEC is not set
++# CONFIG_DVB_CINERGYT2 is not set
++
++#
++# Supported FlexCopII (B2C2) Adapters
++#
++# CONFIG_DVB_B2C2_FLEXCOP is not set
++
++#
++# Supported BT878 Adapters
++#
++
++#
++# Supported Pluto2 Adapters
++#
++# CONFIG_DVB_PLUTO2 is not set
++
++#
++# Supported DVB Frontends
++#
++
++#
++# Customise DVB Frontends
++#
++# CONFIG_DVB_FE_CUSTOMISE is not set
++
++#
++# DVB-S (satellite) frontends
++#
++# CONFIG_DVB_STV0299 is not set
++# CONFIG_DVB_CX24110 is not set
++# CONFIG_DVB_CX24123 is not set
++# CONFIG_DVB_TDA8083 is not set
++# CONFIG_DVB_MT312 is not set
++# CONFIG_DVB_VES1X93 is not set
++# CONFIG_DVB_S5H1420 is not set
++# CONFIG_DVB_TDA10086 is not set
++
++#
++# DVB-T (terrestrial) frontends
++#
++# CONFIG_DVB_SP8870 is not set
++# CONFIG_DVB_SP887X is not set
++# CONFIG_DVB_CX22700 is not set
++# CONFIG_DVB_CX22702 is not set
++# CONFIG_DVB_L64781 is not set
++# CONFIG_DVB_TDA1004X is not set
++# CONFIG_DVB_NXT6000 is not set
++# CONFIG_DVB_MT352 is not set
++# CONFIG_DVB_ZL10353 is not set
++# CONFIG_DVB_DIB3000MB is not set
++# CONFIG_DVB_DIB3000MC is not set
++# CONFIG_DVB_DIB7000M is not set
++# CONFIG_DVB_DIB7000P is not set
++
++#
++# DVB-C (cable) frontends
++#
++# CONFIG_DVB_VES1820 is not set
++# CONFIG_DVB_TDA10021 is not set
++# CONFIG_DVB_TDA10023 is not set
++# CONFIG_DVB_STV0297 is not set
++
++#
++# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
++#
++# CONFIG_DVB_NXT200X is not set
++# CONFIG_DVB_OR51211 is not set
++# CONFIG_DVB_OR51132 is not set
++# CONFIG_DVB_BCM3510 is not set
++# CONFIG_DVB_LGDT330X is not set
++# CONFIG_DVB_S5H1409 is not set
++
++#
++# Tuners/PLL support
++#
++# CONFIG_DVB_PLL is not set
++# CONFIG_DVB_TDA826X is not set
++# CONFIG_DVB_TDA827X is not set
++# CONFIG_DVB_TDA18271 is not set
++# CONFIG_DVB_TUNER_QT1010 is not set
++# CONFIG_DVB_TUNER_MT2060 is not set
++# CONFIG_DVB_TUNER_MT2266 is not set
++# CONFIG_DVB_TUNER_MT2131 is not set
++# CONFIG_DVB_TUNER_DIB0070 is not set
++# CONFIG_DVB_TUNER_XC5000 is not set
++
++#
++# Miscellaneous devices
++#
++# CONFIG_DVB_LNBP21 is not set
++# CONFIG_DVB_ISL6421 is not set
++# CONFIG_DVB_TUA6100 is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++CONFIG_VGA_CONSOLE=y
++# CONFIG_VGACON_SOFT_SCROLLBACK is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++# CONFIG_SND_SEQUENCER is not set
++# CONFIG_SND_MIXER_OSS is not set
++# CONFIG_SND_PCM_OSS is not set
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++CONFIG_SND_AC97_CODEC=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# PCI devices
++#
++# CONFIG_SND_AD1889 is not set
++# CONFIG_SND_ALS300 is not set
++# CONFIG_SND_ALS4000 is not set
++# CONFIG_SND_ALI5451 is not set
++# CONFIG_SND_ATIIXP is not set
++# CONFIG_SND_ATIIXP_MODEM is not set
++# CONFIG_SND_AU8810 is not set
++# CONFIG_SND_AU8820 is not set
++# CONFIG_SND_AU8830 is not set
++# CONFIG_SND_AZT3328 is not set
++# CONFIG_SND_BT87X is not set
++# CONFIG_SND_CA0106 is not set
++# CONFIG_SND_CMIPCI is not set
++# CONFIG_SND_OXYGEN is not set
++# CONFIG_SND_CS4281 is not set
++# CONFIG_SND_CS46XX is not set
++# CONFIG_SND_CS5530 is not set
++# CONFIG_SND_DARLA20 is not set
++# CONFIG_SND_GINA20 is not set
++# CONFIG_SND_LAYLA20 is not set
++# CONFIG_SND_DARLA24 is not set
++# CONFIG_SND_GINA24 is not set
++# CONFIG_SND_LAYLA24 is not set
++# CONFIG_SND_MONA is not set
++# CONFIG_SND_MIA is not set
++# CONFIG_SND_ECHO3G is not set
++# CONFIG_SND_INDIGO is not set
++# CONFIG_SND_INDIGOIO is not set
++# CONFIG_SND_INDIGODJ is not set
++# CONFIG_SND_EMU10K1 is not set
++# CONFIG_SND_EMU10K1X is not set
++# CONFIG_SND_ENS1370 is not set
++# CONFIG_SND_ENS1371 is not set
++# CONFIG_SND_ES1938 is not set
++# CONFIG_SND_ES1968 is not set
++# CONFIG_SND_FM801 is not set
++# CONFIG_SND_HDA_INTEL is not set
++# CONFIG_SND_HDSP is not set
++# CONFIG_SND_HDSPM is not set
++# CONFIG_SND_HIFIER is not set
++# CONFIG_SND_ICE1712 is not set
++# CONFIG_SND_ICE1724 is not set
++CONFIG_SND_INTEL8X0=y
++# CONFIG_SND_INTEL8X0M is not set
++# CONFIG_SND_KORG1212 is not set
++# CONFIG_SND_MAESTRO3 is not set
++# CONFIG_SND_MIXART is not set
++# CONFIG_SND_NM256 is not set
++# CONFIG_SND_PCXHR is not set
++# CONFIG_SND_RIPTIDE is not set
++# CONFIG_SND_RME32 is not set
++# CONFIG_SND_RME96 is not set
++# CONFIG_SND_RME9652 is not set
++# CONFIG_SND_SONICVIBES is not set
++# CONFIG_SND_TRIDENT is not set
++# CONFIG_SND_VIA82XX is not set
++# CONFIG_SND_VIA82XX_MODEM is not set
++# CONFIG_SND_VIRTUOSO is not set
++# CONFIG_SND_VX222 is not set
++# CONFIG_SND_YMFPCI is not set
++# CONFIG_SND_AC97_POWER_SAVE is not set
++
++#
++# ALSA PowerMac devices
++#
++
++#
++# ALSA PowerPC devices
++#
++
++#
++# USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++# CONFIG_SND_USB_USX2Y is not set
++# CONFIG_SND_USB_CAIAQ is not set
++
++#
++# System on Chip audio support
++#
++# CONFIG_SND_SOC is not set
++
++#
++# SoC Audio support for SuperH
++#
++
++#
++# ALSA SoC audio for Freescale SOCs
++#
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=y
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_EHCI_FSL is not set
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++CONFIG_RTC_DRV_CMOS=y
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++# CONFIG_NTFS_RW is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++CONFIG_ADFS_FS=m
++# CONFIG_ADFS_FS_RW is not set
++CONFIG_AFFS_FS=m
++CONFIG_HFS_FS=m
++CONFIG_HFSPLUS_FS=m
++CONFIG_BEFS_FS=m
++# CONFIG_BEFS_DEBUG is not set
++CONFIG_BFS_FS=m
++CONFIG_EFS_FS=m
++CONFIG_CRAMFS=y
++CONFIG_VXFS_FS=m
++# CONFIG_MINIX_FS is not set
++CONFIG_HPFS_FS=m
++CONFIG_QNX4FS_FS=m
++# CONFIG_ROMFS_FS is not set
++CONFIG_SYSV_FS=m
++CONFIG_UFS_FS=m
++# CONFIG_UFS_FS_WRITE is not set
++# CONFIG_UFS_DEBUG is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++CONFIG_NFSD=y
++# CONFIG_NFSD_V3 is not set
++CONFIG_NFSD_TCP=y
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_EXPORTFS=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=m
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=m
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig b/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
+new file mode 100644
+index 0000000..a469fe9
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
+@@ -0,0 +1,935 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:30 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++CONFIG_MPC85xx_CDS=y
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++CONFIG_PPC_I8259=y
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++# CONFIG_BLK_DEV_IDEDISK is not set
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++CONFIG_E1000=y
++CONFIG_E1000_NAPI=y
++# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/sbc8548_defconfig b/arch/powerpc/configs/85xx/sbc8548_defconfig
+new file mode 100644
+index 0000000..67f6797
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/sbc8548_defconfig
+@@ -0,0 +1,812 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:39 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++CONFIG_SBC8548=y
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++CONFIG_BROADCOM_PHY=y
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/sbc8560_defconfig b/arch/powerpc/configs/85xx/sbc8560_defconfig
+new file mode 100644
+index 0000000..fef6055
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/sbc8560_defconfig
+@@ -0,0 +1,830 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:39 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++CONFIG_SBC8560=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++CONFIG_BROADCOM_PHY=y
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++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 is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++# CONFIG_USB_ARCH_HAS_HCD is not set
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++CONFIG_RTC_DRV_M48T59=y
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++CONFIG_PPC_EARLY_DEBUG=y
++# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
++# CONFIG_PPC_EARLY_DEBUG_G5 is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
++# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
++# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
++# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
++# CONFIG_PPC_EARLY_DEBUG_44x is not set
++# CONFIG_PPC_EARLY_DEBUG_40x is not set
++# CONFIG_PPC_EARLY_DEBUG_CPM is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/stx_gp3_defconfig b/arch/powerpc/configs/85xx/stx_gp3_defconfig
+new file mode 100644
+index 0000000..1d303c4
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/stx_gp3_defconfig
+@@ -0,0 +1,1253 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:42 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_UNLOAD is not set
++CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++CONFIG_STX_GP3=y
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++CONFIG_HIGHMEM=y
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=m
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++CONFIG_NETFILTER_XTABLES=m
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++# CONFIG_NETFILTER_XT_MATCH_MAC is not set
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_TIME is not set
++# CONFIG_NETFILTER_XT_MATCH_U32 is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_QUEUE is not set
++CONFIG_IP_NF_IPTABLES=m
++# CONFIG_IP_NF_MATCH_RECENT is not set
++# CONFIG_IP_NF_MATCH_ECN is not set
++# CONFIG_IP_NF_MATCH_AH is not set
++# CONFIG_IP_NF_MATCH_TTL is not set
++# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
++CONFIG_IP_NF_FILTER=m
++# CONFIG_IP_NF_TARGET_REJECT is not set
++# CONFIG_IP_NF_TARGET_LOG is not set
++# CONFIG_IP_NF_TARGET_ULOG is not set
++# CONFIG_IP_NF_MANGLE is not set
++# CONFIG_IP_NF_RAW is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++CONFIG_NET_PKTGEN=y
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++CONFIG_PARPORT=m
++CONFIG_PARPORT_PC=m
++# CONFIG_PARPORT_PC_FIFO is not set
++# CONFIG_PARPORT_PC_SUPERIO is not set
++# CONFIG_PARPORT_GSC is not set
++# CONFIG_PARPORT_AX88796 is not set
++# CONFIG_PARPORT_1284 is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_PARIDE is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=m
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++CONFIG_BLK_DEV_IDECD=m
++CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++
++#
++# PCI IDE chipsets support
++#
++# CONFIG_BLK_DEV_GENERIC is not set
++# CONFIG_BLK_DEV_OPTI621 is not set
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++# CONFIG_BLK_DEV_VIA82CXXX is not set
++# CONFIG_BLK_DEV_TC86C001 is not set
++# CONFIG_BLK_DEV_IDEDMA is not set
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=m
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=m
++CONFIG_CHR_DEV_ST=m
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=m
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++CONFIG_SCSI_CONSTANTS=y
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_PPA is not set
++# CONFIG_SCSI_IMM is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++# CONFIG_NET_POCKET is not set
++# CONFIG_FS_ENET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PLIP is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024
++CONFIG_INPUT_JOYDEV=m
++CONFIG_INPUT_EVDEV=m
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_I8042=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_PARKBD is not set
++# CONFIG_SERIO_PCIPS2 is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++# CONFIG_SERIAL_CPM_SCC1 is not set
++CONFIG_SERIAL_CPM_SCC2=y
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++CONFIG_PRINTER=m
++# CONFIG_LP_CONSOLE is not set
++# CONFIG_PPDEV is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=m
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=m
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=m
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++# CONFIG_I2C_MPC is not set
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++CONFIG_AGP=m
++CONFIG_DRM=m
++# CONFIG_DRM_TDFX is not set
++# CONFIG_DRM_R128 is not set
++# CONFIG_DRM_RADEON is not set
++# CONFIG_DRM_MGA is not set
++# CONFIG_DRM_SIS is not set
++# CONFIG_DRM_VIA is not set
++# CONFIG_DRM_SAVAGE is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=m
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++# CONFIG_AUXDISPLAY is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_AUTOFS_FS=m
++CONFIG_AUTOFS4_FS=y
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=m
++# CONFIG_JOLIET is not set
++# CONFIG_ZISOFS is not set
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=m
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_KCORE is not set
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=m
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++CONFIG_SMB_FS=m
++# CONFIG_SMB_NLS_DEFAULT is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_KGDB_CONSOLE is not set
++CONFIG_BDI_SWITCH=y
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/tqm8540_defconfig b/arch/powerpc/configs/85xx/tqm8540_defconfig
+new file mode 100644
+index 0000000..d39ee3b
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/tqm8540_defconfig
+@@ -0,0 +1,1097 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:43 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++CONFIG_TQM8540=y
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++CONFIG_TQM85xx=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++CONFIG_SENSORS_LM75=y
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_HWMON_DEBUG_CHIP=y
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/tqm8541_defconfig b/arch/powerpc/configs/85xx/tqm8541_defconfig
+new file mode 100644
+index 0000000..cbf6ad2
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/tqm8541_defconfig
+@@ -0,0 +1,1109 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++CONFIG_TQM8541=y
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++CONFIG_TQM85xx=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++# CONFIG_FS_ENET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++# CONFIG_SERIAL_CPM_SCC2 is not set
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++CONFIG_SENSORS_LM75=y
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_HWMON_DEBUG_CHIP=y
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/tqm8555_defconfig b/arch/powerpc/configs/85xx/tqm8555_defconfig
+new file mode 100644
+index 0000000..bbff962
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/tqm8555_defconfig
+@@ -0,0 +1,1109 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++CONFIG_TQM8555=y
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++CONFIG_TQM85xx=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++# CONFIG_FS_ENET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++# CONFIG_SERIAL_CPM_SCC2 is not set
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++CONFIG_SENSORS_LM75=y
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_HWMON_DEBUG_CHIP=y
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/tqm8560_defconfig b/arch/powerpc/configs/85xx/tqm8560_defconfig
+new file mode 100644
+index 0000000..63c5ec8
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/tqm8560_defconfig
+@@ -0,0 +1,1109 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:45 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++CONFIG_TQM8560=y
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++CONFIG_TQM85xx=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++# CONFIG_FS_ENET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++# CONFIG_SERIAL_CPM_SCC2 is not set
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++CONFIG_SENSORS_LM75=y
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_HWMON_DEBUG_CHIP=y
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/bamboo_defconfig b/arch/powerpc/configs/bamboo_defconfig
+deleted file mode 100644
+index c44db55..0000000
+--- a/arch/powerpc/configs/bamboo_defconfig
++++ /dev/null
+@@ -1,815 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:36:39 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_BAMBOO=y
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-# CONFIG_WARP is not set
+-CONFIG_440EP=y
+-CONFIG_IBM440EP_ERR42=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
+index 38b85b2..d7fd298 100644
+--- a/arch/powerpc/configs/chrp32_defconfig
++++ b/arch/powerpc/configs/chrp32_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 10:33:36 2008
++# Thu Mar 27 13:55:37 2008
+ #
+ # CONFIG_PPC64 is not set
+ 
+@@ -74,8 +74,6 @@ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=15
+ # CONFIG_CGROUPS is not set
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+@@ -243,7 +241,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ # CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_PCCARD is not set
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -1328,6 +1326,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+ 
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/ebony_defconfig b/arch/powerpc/configs/ebony_defconfig
+deleted file mode 100644
+index 07c8d4c..0000000
+--- a/arch/powerpc/configs/ebony_defconfig
++++ /dev/null
+@@ -1,898 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:50:44 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-CONFIG_EBONY=y
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-# CONFIG_WARP is not set
+-CONFIG_440GP=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_OF_RTC=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-# CONFIG_MTD_CMDLINE_PARTS is not set
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-# CONFIG_CRYPTO_HW is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/ep405_defconfig b/arch/powerpc/configs/ep405_defconfig
+deleted file mode 100644
+index e24240a..0000000
+--- a/arch/powerpc/configs/ep405_defconfig
++++ /dev/null
+@@ -1,968 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:50:09 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-CONFIG_40x=y
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_EP405=y
+-# CONFIG_KILAUEA is not set
+-# CONFIG_MAKALU is not set
+-# CONFIG_WALNUT is not set
+-# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
+-CONFIG_405GP=y
+-CONFIG_IBM405_ERR77=y
+-CONFIG_IBM405_ERR51=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=m
+-CONFIG_MTD_BLOCK=m
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-# CONFIG_USB_EHCI_HCD is not set
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
+index 0f82f66..a20501f 100644
+--- a/arch/powerpc/configs/g5_defconfig
++++ b/arch/powerpc/configs/g5_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 10:36:41 2008
++# Thu Mar 27 13:55:43 2008
+ #
+ CONFIG_PPC64=y
+ 
+@@ -77,8 +77,6 @@ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=17
+ # CONFIG_CGROUPS is not set
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+@@ -276,7 +274,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ CONFIG_PCI_MSI=y
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_PCCARD is not set
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -1596,6 +1594,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+ 
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
+index 8d9a84f..b3128fb 100644
+--- a/arch/powerpc/configs/iseries_defconfig
++++ b/arch/powerpc/configs/iseries_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 10:43:46 2008
++# Thu Mar 27 13:55:45 2008
+ #
+ CONFIG_PPC64=y
+ 
+@@ -77,8 +77,6 @@ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=17
+ # CONFIG_CGROUPS is not set
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+@@ -261,7 +259,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ # CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_PCCARD is not set
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -1065,6 +1063,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+ 
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/katmai_defconfig b/arch/powerpc/configs/katmai_defconfig
+deleted file mode 100644
+index c8804ec..0000000
+--- a/arch/powerpc/configs/katmai_defconfig
++++ /dev/null
+@@ -1,790 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.24-rc6
+-# Mon Dec 24 11:17:43 2007
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_USER_NS is not set
+-# CONFIG_PID_NS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_FAIR_GROUP_SCHED=y
+-CONFIG_FAIR_USER_SCHED=y
+-# CONFIG_FAIR_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_PPC4xx_PCI_EXPRESS=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC52xx is not set
+-# CONFIG_PPC_MPC5200 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-CONFIG_KATMAI=y
+-# CONFIG_RAINIER is not set
+-CONFIG_440SPe=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_WANT_DEVICE_TREE=y
+-CONFIG_DEVICE_TREE="katmai.dts"
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-CONFIG_MACINTOSH_DRIVERS=y
+-# CONFIG_MAC_EMUMOUSEBTN is not set
+-# CONFIG_WINDFARM is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-CONFIG_DNOTIFY=y
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-# CONFIG_UCC_SLOW is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-CONFIG_INSTRUMENTATION=y
+-# CONFIG_PROFILING is not set
+-# CONFIG_KPROBES is not set
+-# CONFIG_MARKERS is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-CONFIG_FORCED_INLINING=y
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/kilauea_defconfig b/arch/powerpc/configs/kilauea_defconfig
+deleted file mode 100644
+index 2f47539..0000000
+--- a/arch/powerpc/configs/kilauea_defconfig
++++ /dev/null
+@@ -1,839 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:51:43 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-CONFIG_40x=y
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-CONFIG_PPC4xx_PCI_EXPRESS=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_EP405 is not set
+-CONFIG_KILAUEA=y
+-# CONFIG_MAKALU is not set
+-# CONFIG_WALNUT is not set
+-# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
+-CONFIG_405EX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=m
+-CONFIG_MTD_BLOCK=m
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-# CONFIG_MISC_DEVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=256
+-CONFIG_IBM_NEW_EMAC_TXB=256
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-# CONFIG_NETDEV_1000 is not set
+-# CONFIG_NETDEV_10000 is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-# CONFIG_USB_SUPPORT is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/makalu_defconfig b/arch/powerpc/configs/makalu_defconfig
+deleted file mode 100644
+index 9ef4d8a..0000000
+--- a/arch/powerpc/configs/makalu_defconfig
++++ /dev/null
+@@ -1,839 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:52:30 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-CONFIG_40x=y
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-CONFIG_PPC4xx_PCI_EXPRESS=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_EP405 is not set
+-# CONFIG_KILAUEA is not set
+-CONFIG_MAKALU=y
+-# CONFIG_WALNUT is not set
+-# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
+-CONFIG_405EX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=m
+-CONFIG_MTD_BLOCK=m
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-# CONFIG_MISC_DEVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=256
+-CONFIG_IBM_NEW_EMAC_TXB=256
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-# CONFIG_NETDEV_1000 is not set
+-# CONFIG_NETDEV_10000 is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-# CONFIG_USB_SUPPORT is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
+index 8b810d0..7a166a3 100644
+--- a/arch/powerpc/configs/maple_defconfig
++++ b/arch/powerpc/configs/maple_defconfig
+@@ -333,7 +333,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
++CONFIG_FW_LOADER=y
+ # CONFIG_DEBUG_DRIVER is not set
+ # CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+@@ -374,6 +374,7 @@ CONFIG_BLK_DEV_IDEDISK=y
+ CONFIG_BLK_DEV_IDECD=y
+ # CONFIG_BLK_DEV_IDETAPE is not set
+ # CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
+ CONFIG_IDE_TASK_IOCTL=y
+ CONFIG_IDE_PROC_FS=y
+ 
+@@ -427,10 +428,129 @@ CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++CONFIG_SCSI_IPR=y
++CONFIG_SCSI_IPR_TRACE=y
++CONFIG_SCSI_IPR_DUMP=y
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++CONFIG_ATA_NONSTANDARD=y
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_PATA_ALI is not set
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
+ # CONFIG_MD is not set
+ # CONFIG_FUSION is not set
+ 
+@@ -536,6 +656,7 @@ CONFIG_USB_PEGASUS=y
+ # CONFIG_HIPPI is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
+ # CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+@@ -783,12 +904,14 @@ CONFIG_USB_UHCI_HCD=y
+ #
+ # may also be needed; see USB_STORAGE Help for more information
+ #
++# CONFIG_USB_STORAGE is not set
+ # CONFIG_USB_LIBUSUAL is not set
+ 
+ #
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
+ CONFIG_USB_MON=y
+ 
+ #
+diff --git a/arch/powerpc/configs/mpc8313_rdb_defconfig b/arch/powerpc/configs/mpc8313_rdb_defconfig
+deleted file mode 100644
+index 7a862a6..0000000
+--- a/arch/powerpc/configs/mpc8313_rdb_defconfig
++++ /dev/null
+@@ -1,1393 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:14 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-CONFIG_MPC831x_RDB=y
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC831x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-# CONFIG_MTD_CMDLINE_PARTS is not set
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_DATAFLASH is not set
+-# CONFIG_MTD_M25P80 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-CONFIG_MTD_NAND=y
+-CONFIG_MTD_NAND_VERIFY_WRITE=y
+-# CONFIG_MTD_NAND_ECC_SMC is not set
+-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+-CONFIG_MTD_NAND_IDS=y
+-# CONFIG_MTD_NAND_DISKONCHIP is not set
+-# CONFIG_MTD_NAND_CAFE is not set
+-# CONFIG_MTD_NAND_NANDSIM is not set
+-# CONFIG_MTD_NAND_PLATFORM is not set
+-# CONFIG_MTD_ALAUDA is not set
+-# CONFIG_MTD_NAND_FSL_ELBC is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-CONFIG_MD=y
+-CONFIG_BLK_DEV_MD=y
+-CONFIG_MD_LINEAR=y
+-CONFIG_MD_RAID0=y
+-CONFIG_MD_RAID1=y
+-# CONFIG_MD_RAID10 is not set
+-# CONFIG_MD_RAID456 is not set
+-# CONFIG_MD_MULTIPATH is not set
+-# CONFIG_MD_FAULTY is not set
+-# CONFIG_BLK_DEV_DM is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-CONFIG_CICADA_PHY=y
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_ENC28J60 is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-# CONFIG_SPI_DEBUG is not set
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM70 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-CONFIG_USB_UHCI_HCD=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-CONFIG_USB_GADGET=y
+-# CONFIG_USB_GADGET_DEBUG is not set
+-# CONFIG_USB_GADGET_DEBUG_FILES is not set
+-CONFIG_USB_GADGET_SELECTED=y
+-# CONFIG_USB_GADGET_AMD5536UDC is not set
+-# CONFIG_USB_GADGET_ATMEL_USBA is not set
+-# CONFIG_USB_GADGET_FSL_USB2 is not set
+-CONFIG_USB_GADGET_NET2280=y
+-CONFIG_USB_NET2280=y
+-# CONFIG_USB_GADGET_PXA2XX is not set
+-# CONFIG_USB_GADGET_M66592 is not set
+-# CONFIG_USB_GADGET_GOKU is not set
+-# CONFIG_USB_GADGET_LH7A40X is not set
+-# CONFIG_USB_GADGET_OMAP is not set
+-# CONFIG_USB_GADGET_S3C2410 is not set
+-# CONFIG_USB_GADGET_AT91 is not set
+-# CONFIG_USB_GADGET_DUMMY_HCD is not set
+-CONFIG_USB_GADGET_DUALSPEED=y
+-# CONFIG_USB_ZERO is not set
+-CONFIG_USB_ETH=y
+-CONFIG_USB_ETH_RNDIS=y
+-# CONFIG_USB_GADGETFS is not set
+-# CONFIG_USB_FILE_STORAGE is not set
+-# CONFIG_USB_G_SERIAL is not set
+-# CONFIG_USB_MIDI_GADGET is not set
+-# CONFIG_USB_G_PRINTER is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-# CONFIG_RTC_DRV_MAX6902 is not set
+-# CONFIG_RTC_DRV_R9701 is not set
+-# CONFIG_RTC_DRV_RS5C348 is not set
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc8315_rdb_defconfig b/arch/powerpc/configs/mpc8315_rdb_defconfig
+deleted file mode 100644
+index 1f57456..0000000
+--- a/arch/powerpc/configs/mpc8315_rdb_defconfig
++++ /dev/null
+@@ -1,1451 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:15 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-CONFIG_MPC831x_RDB=y
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC831x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-# CONFIG_MTD_CMDLINE_PARTS is not set
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_DATAFLASH is not set
+-# CONFIG_MTD_M25P80 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-CONFIG_MTD_NAND=y
+-CONFIG_MTD_NAND_VERIFY_WRITE=y
+-# CONFIG_MTD_NAND_ECC_SMC is not set
+-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+-CONFIG_MTD_NAND_IDS=y
+-# CONFIG_MTD_NAND_DISKONCHIP is not set
+-# CONFIG_MTD_NAND_CAFE is not set
+-# CONFIG_MTD_NAND_NANDSIM is not set
+-# CONFIG_MTD_NAND_PLATFORM is not set
+-# CONFIG_MTD_ALAUDA is not set
+-# CONFIG_MTD_NAND_FSL_ELBC is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_AHCI is not set
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-# CONFIG_SATA_MV is not set
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-# CONFIG_SATA_SIL is not set
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-CONFIG_SATA_FSL=y
+-# CONFIG_PATA_ALI is not set
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-# CONFIG_PATA_PLATFORM is not set
+-CONFIG_MD=y
+-CONFIG_BLK_DEV_MD=y
+-CONFIG_MD_LINEAR=y
+-CONFIG_MD_RAID0=y
+-CONFIG_MD_RAID1=y
+-# CONFIG_MD_RAID10 is not set
+-# CONFIG_MD_RAID456 is not set
+-# CONFIG_MD_MULTIPATH is not set
+-# CONFIG_MD_FAULTY is not set
+-# CONFIG_BLK_DEV_DM is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_ENC28J60 is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-# CONFIG_SPI_DEBUG is not set
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM70 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-CONFIG_USB_UHCI_HCD=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-CONFIG_USB_GADGET=y
+-# CONFIG_USB_GADGET_DEBUG is not set
+-# CONFIG_USB_GADGET_DEBUG_FILES is not set
+-CONFIG_USB_GADGET_SELECTED=y
+-# CONFIG_USB_GADGET_AMD5536UDC is not set
+-# CONFIG_USB_GADGET_ATMEL_USBA is not set
+-# CONFIG_USB_GADGET_FSL_USB2 is not set
+-CONFIG_USB_GADGET_NET2280=y
+-CONFIG_USB_NET2280=y
+-# CONFIG_USB_GADGET_PXA2XX is not set
+-# CONFIG_USB_GADGET_M66592 is not set
+-# CONFIG_USB_GADGET_GOKU is not set
+-# CONFIG_USB_GADGET_LH7A40X is not set
+-# CONFIG_USB_GADGET_OMAP is not set
+-# CONFIG_USB_GADGET_S3C2410 is not set
+-# CONFIG_USB_GADGET_AT91 is not set
+-# CONFIG_USB_GADGET_DUMMY_HCD is not set
+-CONFIG_USB_GADGET_DUALSPEED=y
+-# CONFIG_USB_ZERO is not set
+-CONFIG_USB_ETH=y
+-CONFIG_USB_ETH_RNDIS=y
+-# CONFIG_USB_GADGETFS is not set
+-# CONFIG_USB_FILE_STORAGE is not set
+-# CONFIG_USB_G_SERIAL is not set
+-# CONFIG_USB_MIDI_GADGET is not set
+-# CONFIG_USB_G_PRINTER is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-# CONFIG_RTC_DRV_MAX6902 is not set
+-# CONFIG_RTC_DRV_R9701 is not set
+-# CONFIG_RTC_DRV_RS5C348 is not set
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc832x_mds_defconfig b/arch/powerpc/configs/mpc832x_mds_defconfig
+deleted file mode 100644
+index 50cceda..0000000
+--- a/arch/powerpc/configs/mpc832x_mds_defconfig
++++ /dev/null
+@@ -1,1081 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:36:51 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-CONFIG_MPC832x_MDS=y
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC832x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_QUICC_ENGINE=y
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-CONFIG_DAVICOM_PHY=y
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_GIANFAR is not set
+-CONFIG_UCC_GETH=y
+-# CONFIG_UGETH_NAPI is not set
+-# CONFIG_UGETH_MAGIC_PACKET is not set
+-# CONFIG_UGETH_FILTERING is not set
+-# CONFIG_UGETH_TX_ON_DEMAND is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-# CONFIG_SERIAL_QE is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-CONFIG_RTC_DRV_DS1374=y
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-CONFIG_UCC_FAST=y
+-CONFIG_UCC=y
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc832x_rdb_defconfig b/arch/powerpc/configs/mpc832x_rdb_defconfig
+deleted file mode 100644
+index ac91302..0000000
+--- a/arch/powerpc/configs/mpc832x_rdb_defconfig
++++ /dev/null
+@@ -1,1233 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:16 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-CONFIG_MPC832x_RDB=y
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC832x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_QUICC_ENGINE=y
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-CONFIG_ICPLUS_PHY=y
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_ENC28J60 is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-CONFIG_E1000=y
+-# CONFIG_E1000_NAPI is not set
+-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_GIANFAR is not set
+-CONFIG_UCC_GETH=y
+-CONFIG_UGETH_NAPI=y
+-# CONFIG_UGETH_MAGIC_PACKET is not set
+-# CONFIG_UGETH_FILTERING is not set
+-# CONFIG_UGETH_TX_ON_DEMAND is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-# CONFIG_SERIAL_QE is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM70 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-# CONFIG_USB_EHCI_FSL is not set
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+-# CONFIG_MMC_UNSAFE_RESUME is not set
+-
+-#
+-# MMC/SD Card Drivers
+-#
+-CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_BLOCK_BOUNCE=y
+-# CONFIG_SDIO_UART is not set
+-
+-#
+-# MMC/SD Host Controller Drivers
+-#
+-# CONFIG_MMC_SDHCI is not set
+-# CONFIG_MMC_WBSD is not set
+-# CONFIG_MMC_TIFM_SD is not set
+-CONFIG_MMC_SPI=y
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-CONFIG_LDM_PARTITION=y
+-# CONFIG_LDM_DEBUG is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-CONFIG_NLS_CODEPAGE_437=y
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-CONFIG_NLS_CODEPAGE_932=y
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-CONFIG_NLS_ISO8859_8=y
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-CONFIG_NLS_ISO8859_1=y
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-CONFIG_UCC_FAST=y
+-CONFIG_UCC=y
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-CONFIG_CRC_ITU_T=y
+-CONFIG_CRC32=y
+-CONFIG_CRC7=y
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
+deleted file mode 100644
+index e1de399..0000000
+--- a/arch/powerpc/configs/mpc834x_itx_defconfig
++++ /dev/null
+@@ -1,1295 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:17 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-CONFIG_MPC834x_ITX=y
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC834x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-# CONFIG_MTD_PARTITIONS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-# CONFIG_MTD_BLKDEVS is not set
+-# CONFIG_MTD_BLOCK is not set
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0xfe000000
+-CONFIG_MTD_PHYSMAP_LEN=0x1000000
+-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_DATAFLASH is not set
+-# CONFIG_MTD_M25P80 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-# CONFIG_BLK_DEV_IDE is not set
+-# CONFIG_BLK_DEV_HD_ONLY is not set
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_AHCI is not set
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-# CONFIG_SATA_MV is not set
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-CONFIG_SATA_SIL=y
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-# CONFIG_SATA_FSL is not set
+-# CONFIG_PATA_ALI is not set
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-CONFIG_PATA_PLATFORM=y
+-CONFIG_PATA_OF_PLATFORM=y
+-CONFIG_MD=y
+-CONFIG_BLK_DEV_MD=y
+-CONFIG_MD_LINEAR=y
+-CONFIG_MD_RAID0=y
+-CONFIG_MD_RAID1=y
+-# CONFIG_MD_RAID10 is not set
+-# CONFIG_MD_RAID456 is not set
+-# CONFIG_MD_MULTIPATH is not set
+-# CONFIG_MD_FAULTY is not set
+-# CONFIG_BLK_DEV_DM is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-CONFIG_CICADA_PHY=y
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-# CONFIG_NET_ETHERNET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-CONFIG_SENSORS_PCF8574=y
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-# CONFIG_USB_OHCI_HCD is not set
+-CONFIG_USB_UHCI_HCD=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-# CONFIG_RTC_DRV_MAX6902 is not set
+-# CONFIG_RTC_DRV_R9701 is not set
+-# CONFIG_RTC_DRV_RS5C348 is not set
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-CONFIG_MAC_PARTITION=y
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc834x_itxgp_defconfig b/arch/powerpc/configs/mpc834x_itxgp_defconfig
+deleted file mode 100644
+index b4e39cf..0000000
+--- a/arch/powerpc/configs/mpc834x_itxgp_defconfig
++++ /dev/null
+@@ -1,1222 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:18 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-CONFIG_MPC834x_ITX=y
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC834x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-# CONFIG_MTD_PARTITIONS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-# CONFIG_MTD_BLKDEVS is not set
+-# CONFIG_MTD_BLOCK is not set
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0xfe000000
+-CONFIG_MTD_PHYSMAP_LEN=0x800000
+-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_DATAFLASH is not set
+-# CONFIG_MTD_M25P80 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-CONFIG_CICADA_PHY=y
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-# CONFIG_NET_ETHERNET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-CONFIG_SENSORS_PCF8574=y
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-# CONFIG_USB_DEVICEFS is not set
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-# CONFIG_USB_OHCI_HCD is not set
+-CONFIG_USB_UHCI_HCD=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-# CONFIG_RTC_DRV_MAX6902 is not set
+-# CONFIG_RTC_DRV_R9701 is not set
+-# CONFIG_RTC_DRV_RS5C348 is not set
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-CONFIG_MAC_PARTITION=y
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
+deleted file mode 100644
+index b4e82c0..0000000
+--- a/arch/powerpc/configs/mpc834x_mds_defconfig
++++ /dev/null
+@@ -1,1021 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:36:56 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-CONFIG_MPC834x_MDS=y
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC834x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=m
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-# CONFIG_GFAR_NAPI is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-CONFIG_RTC_DRV_DS1374=y
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc836x_mds_defconfig b/arch/powerpc/configs/mpc836x_mds_defconfig
+deleted file mode 100644
+index d50a96e..0000000
+--- a/arch/powerpc/configs/mpc836x_mds_defconfig
++++ /dev/null
+@@ -1,1079 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:36:57 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-CONFIG_MPC836x_MDS=y
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_QUICC_ENGINE=y
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_GIANFAR is not set
+-CONFIG_UCC_GETH=y
+-# CONFIG_UGETH_NAPI is not set
+-# CONFIG_UGETH_MAGIC_PACKET is not set
+-# CONFIG_UGETH_FILTERING is not set
+-# CONFIG_UGETH_TX_ON_DEMAND is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-# CONFIG_SERIAL_QE is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-CONFIG_RTC_DRV_DS1374=y
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-CONFIG_UCC_FAST=y
+-CONFIG_UCC=y
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc837x_mds_defconfig b/arch/powerpc/configs/mpc837x_mds_defconfig
+deleted file mode 100644
+index f377cde..0000000
+--- a/arch/powerpc/configs/mpc837x_mds_defconfig
++++ /dev/null
+@@ -1,899 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:23 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-CONFIG_MPC837x_MDS=y
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC837x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=m
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_SCSI_DEBUG is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_MV is not set
+-CONFIG_SATA_FSL=y
+-# CONFIG_PATA_PLATFORM is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-# CONFIG_GFAR_NAPI is not set
+-CONFIG_NETDEV_10000=y
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc837x_rdb_defconfig b/arch/powerpc/configs/mpc837x_rdb_defconfig
+deleted file mode 100644
+index a633176..0000000
+--- a/arch/powerpc/configs/mpc837x_rdb_defconfig
++++ /dev/null
+@@ -1,930 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:24 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-CONFIG_MPC837x_RDB=y
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC837x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_SCSI_DEBUG is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_MV is not set
+-CONFIG_SATA_FSL=y
+-# CONFIG_PATA_PLATFORM is not set
+-CONFIG_MD=y
+-CONFIG_BLK_DEV_MD=y
+-# CONFIG_MD_LINEAR is not set
+-# CONFIG_MD_RAID0 is not set
+-CONFIG_MD_RAID1=y
+-# CONFIG_MD_RAID10 is not set
+-CONFIG_MD_RAID456=y
+-CONFIG_MD_RAID5_RESHAPE=y
+-# CONFIG_MD_MULTIPATH is not set
+-# CONFIG_MD_FAULTY is not set
+-# CONFIG_BLK_DEV_DM is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_NETDEV_10000 is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-# CONFIG_USB_DEVICEFS is not set
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-# CONFIG_ENABLE_MUST_CHECK is not set
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_XOR_BLOCKS=y
+-CONFIG_ASYNC_CORE=y
+-CONFIG_ASYNC_MEMCPY=y
+-CONFIG_ASYNC_XOR=y
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig
+index 029d2da..9e0dd82 100644
+--- a/arch/powerpc/configs/mpc83xx_defconfig
++++ b/arch/powerpc/configs/mpc83xx_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:25 2008
++# Linux kernel version: 2.6.25-rc9
++# Tue Apr 15 18:07:36 2008
+ #
+ # CONFIG_PPC64 is not set
+ 
+@@ -201,6 +201,7 @@ CONFIG_PREEMPT_NONE=y
+ # CONFIG_PREEMPT is not set
+ CONFIG_BINFMT_ELF=y
+ # CONFIG_BINFMT_MISC is not set
++CONFIG_FORCE_MAX_ZONEORDER=11
+ CONFIG_MATH_EMULATION=y
+ # CONFIG_IOMMU_HELPER is not set
+ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+@@ -353,7 +354,90 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+ # CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++CONFIG_MTD_NAND_FSL_ELBC=y
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
+ CONFIG_OF_DEVICE=y
+ # CONFIG_PARPORT is not set
+ CONFIG_BLK_DEV=y
+@@ -362,6 +446,7 @@ CONFIG_BLK_DEV=y
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+ # CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=32768
+@@ -469,6 +554,15 @@ CONFIG_NETDEV_10000=y
+ #
+ # CONFIG_WLAN_PRE80211 is not set
+ # CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+@@ -563,6 +657,7 @@ CONFIG_I2C_MPC=y
+ # CONFIG_I2C_SIMTEC is not set
+ # CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
+ 
+ #
+ # Miscellaneous I2C Chip support
+@@ -648,6 +743,11 @@ CONFIG_WATCHDOG=y
+ CONFIG_83xx_WDT=y
+ 
+ #
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
+ # Sonics Silicon Backplane
+ #
+ CONFIG_SSB_POSSIBLE=y
+@@ -664,6 +764,7 @@ CONFIG_SSB_POSSIBLE=y
+ # CONFIG_VIDEO_DEV is not set
+ # CONFIG_DVB_CORE is not set
+ CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
+ 
+ #
+ # Graphics support
+@@ -686,6 +787,14 @@ CONFIG_HID_SUPPORT=y
+ CONFIG_HID=y
+ # CONFIG_HID_DEBUG is not set
+ # CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
+ CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ # CONFIG_USB_ARCH_HAS_OHCI is not set
+@@ -715,8 +824,55 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
+ # CONFIG_USB_R8A66597_HCD is not set
+ 
+ #
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
+ # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+ #
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++# CONFIG_USB_STORAGE is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_GADGET is not set
+ # CONFIG_MMC is not set
+ # CONFIG_MEMSTICK is not set
+@@ -792,6 +948,7 @@ CONFIG_TMPFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
+ # CONFIG_CRAMFS is not set
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_MINIX_FS is not set
+@@ -862,6 +1019,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+ 
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
+deleted file mode 100644
+index b998539..0000000
+--- a/arch/powerpc/configs/mpc8540_ads_defconfig
++++ /dev/null
+@@ -1,796 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:25 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-CONFIG_MPC8540_ADS=y
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-CONFIG_NETDEV_10000=y
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-# CONFIG_USB_ARCH_HAS_HCD is not set
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc8544_ds_defconfig b/arch/powerpc/configs/mpc8544_ds_defconfig
+deleted file mode 100644
+index 418bcdb..0000000
+--- a/arch/powerpc/configs/mpc8544_ds_defconfig
++++ /dev/null
+@@ -1,1549 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:37:03 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-CONFIG_BSD_PROCESS_ACCT=y
+-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+-# CONFIG_TASKSTATS is not set
+-CONFIG_AUDIT=y
+-# CONFIG_AUDITSYSCALL is not set
+-CONFIG_IKCONFIG=y
+-CONFIG_IKCONFIG_PROC=y
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-CONFIG_MODULE_FORCE_UNLOAD=y
+-CONFIG_MODVERSIONS=y
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-CONFIG_MPC85xx_DS=y
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-CONFIG_PPC_I8259=y
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-CONFIG_FSL_ULI1575=y
+-
+-#
+-# Kernel options
+-#
+-CONFIG_HIGHMEM=y
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=m
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-CONFIG_NET_KEY=m
+-# CONFIG_NET_KEY_MIGRATE is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-CONFIG_IP_ADVANCED_ROUTER=y
+-CONFIG_ASK_IP_FIB_HASH=y
+-# CONFIG_IP_FIB_TRIE is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_MULTIPLE_TABLES=y
+-CONFIG_IP_ROUTE_MULTIPATH=y
+-CONFIG_IP_ROUTE_VERBOSE=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-CONFIG_IP_PNP_RARP=y
+-CONFIG_NET_IPIP=y
+-CONFIG_NET_IPGRE=y
+-CONFIG_NET_IPGRE_BROADCAST=y
+-CONFIG_IP_MROUTE=y
+-CONFIG_IP_PIMSM_V1=y
+-CONFIG_IP_PIMSM_V2=y
+-CONFIG_ARPD=y
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-CONFIG_INET_TUNNEL=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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-CONFIG_IPV6=y
+-# CONFIG_IPV6_PRIVACY is not set
+-# CONFIG_IPV6_ROUTER_PREF is not set
+-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+-# CONFIG_INET6_AH is not set
+-# CONFIG_INET6_ESP is not set
+-# CONFIG_INET6_IPCOMP is not set
+-# CONFIG_IPV6_MIP6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET6_XFRM_MODE_TUNNEL=y
+-CONFIG_INET6_XFRM_MODE_BEET=y
+-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+-CONFIG_IPV6_SIT=y
+-# CONFIG_IPV6_TUNNEL is not set
+-# CONFIG_IPV6_MULTIPLE_TABLES is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-CONFIG_IP_SCTP=m
+-# CONFIG_SCTP_DBG_MSG is not set
+-# CONFIG_SCTP_DBG_OBJCNT is not set
+-# CONFIG_SCTP_HMAC_NONE is not set
+-# CONFIG_SCTP_HMAC_SHA1 is not set
+-CONFIG_SCTP_HMAC_MD5=y
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-CONFIG_FIB_RULES=y
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-CONFIG_BLK_DEV_NBD=y
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=131072
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-CONFIG_CHR_DEV_ST=y
+-# CONFIG_CHR_DEV_OSST is not set
+-CONFIG_BLK_DEV_SR=y
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-CONFIG_SCSI_MULTI_LUN=y
+-# CONFIG_SCSI_CONSTANTS is not set
+-CONFIG_SCSI_LOGGING=y
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-CONFIG_SATA_AHCI=y
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-# CONFIG_SATA_MV is not set
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-# CONFIG_SATA_SIL is not set
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-# CONFIG_SATA_FSL is not set
+-CONFIG_PATA_ALI=y
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-# CONFIG_PATA_PLATFORM is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-CONFIG_DUMMY=y
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-CONFIG_VITESSE_PHY=y
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-CONFIG_SERIO=y
+-CONFIG_SERIO_I8042=y
+-CONFIG_SERIO_SERPORT=y
+-# CONFIG_SERIO_PCIPS2 is not set
+-CONFIG_SERIO_LIBPS2=y
+-# CONFIG_SERIO_RAW is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=2
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+-CONFIG_SERIAL_8250_EXTENDED=y
+-CONFIG_SERIAL_8250_MANY_PORTS=y
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-CONFIG_SERIAL_8250_DETECT_IRQ=y
+-CONFIG_SERIAL_8250_RSA=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-CONFIG_NVRAM=y
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-# CONFIG_I2C_CHARDEV is not set
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-CONFIG_SENSORS_EEPROM=y
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-CONFIG_DVB_CORE=m
+-# CONFIG_DVB_CORE_ATTACH is not set
+-CONFIG_DVB_CAPTURE_DRIVERS=y
+-
+-#
+-# Supported SAA7146 based PCI Adapters
+-#
+-# CONFIG_TTPCI_EEPROM is not set
+-# CONFIG_DVB_BUDGET_CORE is not set
+-
+-#
+-# Supported USB Adapters
+-#
+-# CONFIG_DVB_USB is not set
+-# CONFIG_DVB_TTUSB_BUDGET is not set
+-# CONFIG_DVB_TTUSB_DEC is not set
+-# CONFIG_DVB_CINERGYT2 is not set
+-
+-#
+-# Supported FlexCopII (B2C2) Adapters
+-#
+-# CONFIG_DVB_B2C2_FLEXCOP is not set
+-
+-#
+-# Supported BT878 Adapters
+-#
+-
+-#
+-# Supported Pluto2 Adapters
+-#
+-# CONFIG_DVB_PLUTO2 is not set
+-
+-#
+-# Supported DVB Frontends
+-#
+-
+-#
+-# Customise DVB Frontends
+-#
+-# CONFIG_DVB_FE_CUSTOMISE is not set
+-
+-#
+-# DVB-S (satellite) frontends
+-#
+-# CONFIG_DVB_STV0299 is not set
+-# CONFIG_DVB_CX24110 is not set
+-# CONFIG_DVB_CX24123 is not set
+-# CONFIG_DVB_TDA8083 is not set
+-# CONFIG_DVB_MT312 is not set
+-# CONFIG_DVB_VES1X93 is not set
+-# CONFIG_DVB_S5H1420 is not set
+-# CONFIG_DVB_TDA10086 is not set
+-
+-#
+-# DVB-T (terrestrial) frontends
+-#
+-# CONFIG_DVB_SP8870 is not set
+-# CONFIG_DVB_SP887X is not set
+-# CONFIG_DVB_CX22700 is not set
+-# CONFIG_DVB_CX22702 is not set
+-# CONFIG_DVB_L64781 is not set
+-# CONFIG_DVB_TDA1004X is not set
+-# CONFIG_DVB_NXT6000 is not set
+-# CONFIG_DVB_MT352 is not set
+-# CONFIG_DVB_ZL10353 is not set
+-# CONFIG_DVB_DIB3000MB is not set
+-# CONFIG_DVB_DIB3000MC is not set
+-# CONFIG_DVB_DIB7000M is not set
+-# CONFIG_DVB_DIB7000P is not set
+-
+-#
+-# DVB-C (cable) frontends
+-#
+-# CONFIG_DVB_VES1820 is not set
+-# CONFIG_DVB_TDA10021 is not set
+-# CONFIG_DVB_TDA10023 is not set
+-# CONFIG_DVB_STV0297 is not set
+-
+-#
+-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+-#
+-# CONFIG_DVB_NXT200X is not set
+-# CONFIG_DVB_OR51211 is not set
+-# CONFIG_DVB_OR51132 is not set
+-# CONFIG_DVB_BCM3510 is not set
+-# CONFIG_DVB_LGDT330X is not set
+-# CONFIG_DVB_S5H1409 is not set
+-
+-#
+-# Tuners/PLL support
+-#
+-# CONFIG_DVB_PLL is not set
+-# CONFIG_DVB_TDA826X is not set
+-# CONFIG_DVB_TDA827X is not set
+-# CONFIG_DVB_TDA18271 is not set
+-# CONFIG_DVB_TUNER_QT1010 is not set
+-# CONFIG_DVB_TUNER_MT2060 is not set
+-# CONFIG_DVB_TUNER_MT2266 is not set
+-# CONFIG_DVB_TUNER_MT2131 is not set
+-# CONFIG_DVB_TUNER_DIB0070 is not set
+-# CONFIG_DVB_TUNER_XC5000 is not set
+-
+-#
+-# Miscellaneous devices
+-#
+-# CONFIG_DVB_LNBP21 is not set
+-# CONFIG_DVB_ISL6421 is not set
+-# CONFIG_DVB_TUA6100 is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Console display driver support
+-#
+-CONFIG_VGA_CONSOLE=y
+-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+-CONFIG_DUMMY_CONSOLE=y
+-
+-#
+-# Sound
+-#
+-CONFIG_SOUND=y
+-
+-#
+-# Advanced Linux Sound Architecture
+-#
+-CONFIG_SND=y
+-CONFIG_SND_TIMER=y
+-CONFIG_SND_PCM=y
+-# CONFIG_SND_SEQUENCER is not set
+-# CONFIG_SND_MIXER_OSS is not set
+-# CONFIG_SND_PCM_OSS is not set
+-# CONFIG_SND_DYNAMIC_MINORS is not set
+-CONFIG_SND_SUPPORT_OLD_API=y
+-CONFIG_SND_VERBOSE_PROCFS=y
+-# CONFIG_SND_VERBOSE_PRINTK is not set
+-# CONFIG_SND_DEBUG is not set
+-
+-#
+-# Generic devices
+-#
+-CONFIG_SND_AC97_CODEC=y
+-# CONFIG_SND_DUMMY is not set
+-# CONFIG_SND_MTPAV is not set
+-# CONFIG_SND_SERIAL_U16550 is not set
+-# CONFIG_SND_MPU401 is not set
+-
+-#
+-# PCI devices
+-#
+-# CONFIG_SND_AD1889 is not set
+-# CONFIG_SND_ALS300 is not set
+-# CONFIG_SND_ALS4000 is not set
+-# CONFIG_SND_ALI5451 is not set
+-# CONFIG_SND_ATIIXP is not set
+-# CONFIG_SND_ATIIXP_MODEM is not set
+-# CONFIG_SND_AU8810 is not set
+-# CONFIG_SND_AU8820 is not set
+-# CONFIG_SND_AU8830 is not set
+-# CONFIG_SND_AZT3328 is not set
+-# CONFIG_SND_BT87X is not set
+-# CONFIG_SND_CA0106 is not set
+-# CONFIG_SND_CMIPCI is not set
+-# CONFIG_SND_OXYGEN is not set
+-# CONFIG_SND_CS4281 is not set
+-# CONFIG_SND_CS46XX is not set
+-# CONFIG_SND_CS5530 is not set
+-# CONFIG_SND_DARLA20 is not set
+-# CONFIG_SND_GINA20 is not set
+-# CONFIG_SND_LAYLA20 is not set
+-# CONFIG_SND_DARLA24 is not set
+-# CONFIG_SND_GINA24 is not set
+-# CONFIG_SND_LAYLA24 is not set
+-# CONFIG_SND_MONA is not set
+-# CONFIG_SND_MIA is not set
+-# CONFIG_SND_ECHO3G is not set
+-# CONFIG_SND_INDIGO is not set
+-# CONFIG_SND_INDIGOIO is not set
+-# CONFIG_SND_INDIGODJ is not set
+-# CONFIG_SND_EMU10K1 is not set
+-# CONFIG_SND_EMU10K1X is not set
+-# CONFIG_SND_ENS1370 is not set
+-# CONFIG_SND_ENS1371 is not set
+-# CONFIG_SND_ES1938 is not set
+-# CONFIG_SND_ES1968 is not set
+-# CONFIG_SND_FM801 is not set
+-# CONFIG_SND_HDA_INTEL is not set
+-# CONFIG_SND_HDSP is not set
+-# CONFIG_SND_HDSPM is not set
+-# CONFIG_SND_HIFIER is not set
+-# CONFIG_SND_ICE1712 is not set
+-# CONFIG_SND_ICE1724 is not set
+-CONFIG_SND_INTEL8X0=y
+-# CONFIG_SND_INTEL8X0M is not set
+-# CONFIG_SND_KORG1212 is not set
+-# CONFIG_SND_MAESTRO3 is not set
+-# CONFIG_SND_MIXART is not set
+-# CONFIG_SND_NM256 is not set
+-# CONFIG_SND_PCXHR is not set
+-# CONFIG_SND_RIPTIDE is not set
+-# CONFIG_SND_RME32 is not set
+-# CONFIG_SND_RME96 is not set
+-# CONFIG_SND_RME9652 is not set
+-# CONFIG_SND_SONICVIBES is not set
+-# CONFIG_SND_TRIDENT is not set
+-# CONFIG_SND_VIA82XX is not set
+-# CONFIG_SND_VIA82XX_MODEM is not set
+-# CONFIG_SND_VIRTUOSO is not set
+-# CONFIG_SND_VX222 is not set
+-# CONFIG_SND_YMFPCI is not set
+-# CONFIG_SND_AC97_POWER_SAVE is not set
+-
+-#
+-# ALSA PowerMac devices
+-#
+-
+-#
+-# ALSA PowerPC devices
+-#
+-
+-#
+-# USB devices
+-#
+-# CONFIG_SND_USB_AUDIO is not set
+-# CONFIG_SND_USB_USX2Y is not set
+-# CONFIG_SND_USB_CAIAQ is not set
+-
+-#
+-# System on Chip audio support
+-#
+-# CONFIG_SND_SOC is not set
+-
+-#
+-# SoC Audio support for SuperH
+-#
+-
+-#
+-# ALSA SoC audio for Freescale SOCs
+-#
+-
+-#
+-# Open Sound System
+-#
+-# CONFIG_SOUND_PRIME is not set
+-CONFIG_AC97_BUS=y
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-CONFIG_USB_HID=y
+-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+-# CONFIG_HID_FF is not set
+-# CONFIG_USB_HIDDEV is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-# CONFIG_USB_EHCI_FSL is not set
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-CONFIG_RTC_DRV_CMOS=y
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-CONFIG_ISO9660_FS=m
+-CONFIG_JOLIET=y
+-CONFIG_ZISOFS=y
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=m
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-CONFIG_NTFS_FS=y
+-# CONFIG_NTFS_DEBUG is not set
+-# CONFIG_NTFS_RW is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-CONFIG_ADFS_FS=m
+-# CONFIG_ADFS_FS_RW is not set
+-CONFIG_AFFS_FS=m
+-CONFIG_HFS_FS=m
+-CONFIG_HFSPLUS_FS=m
+-CONFIG_BEFS_FS=m
+-# CONFIG_BEFS_DEBUG is not set
+-CONFIG_BFS_FS=m
+-CONFIG_EFS_FS=m
+-CONFIG_CRAMFS=y
+-CONFIG_VXFS_FS=m
+-# CONFIG_MINIX_FS is not set
+-CONFIG_HPFS_FS=m
+-CONFIG_QNX4FS_FS=m
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_SYSV_FS=m
+-CONFIG_UFS_FS=m
+-# CONFIG_UFS_FS_WRITE is not set
+-# CONFIG_UFS_DEBUG is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-CONFIG_NFSD=y
+-# CONFIG_NFSD_V3 is not set
+-CONFIG_NFSD_TCP=y
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_EXPORTFS=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-CONFIG_MAC_PARTITION=y
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-CONFIG_NLS_UTF8=m
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-CONFIG_LIBCRC32C=m
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_HIGHMEM is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-CONFIG_DEBUG_INFO=y
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_HASH=y
+-CONFIG_CRYPTO_MANAGER=y
+-CONFIG_CRYPTO_HMAC=y
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-CONFIG_CRYPTO_SHA1=m
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc8560_ads_defconfig b/arch/powerpc/configs/mpc8560_ads_defconfig
+deleted file mode 100644
+index 851ac91..0000000
+--- a/arch/powerpc/configs/mpc8560_ads_defconfig
++++ /dev/null
+@@ -1,885 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:27 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-CONFIG_MPC8560_ADS=y
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-CONFIG_PCI_DEBUG=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-CONFIG_DAVICOM_PHY=y
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_FS_ENET=y
+-# CONFIG_FS_ENET_HAS_SCC is not set
+-CONFIG_FS_ENET_HAS_FCC=y
+-# CONFIG_FS_ENET_MDIO_FCC is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-CONFIG_E1000=y
+-CONFIG_E1000_NAPI=y
+-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-CONFIG_SERIAL_CPM_SCC2=y
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc8568mds_defconfig b/arch/powerpc/configs/mpc8568mds_defconfig
+deleted file mode 100644
+index 2b866b3..0000000
+--- a/arch/powerpc/configs/mpc8568mds_defconfig
++++ /dev/null
+@@ -1,1117 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:37:05 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-CONFIG_MPC85xx_MDS=y
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_QUICC_ENGINE=y
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_UCC_GETH is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-# CONFIG_SERIAL_QE is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-# CONFIG_BOOKE_WDT is not set
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-CONFIG_RTC_DRV_DS1374=y
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_XMON is not set
+-# CONFIG_BDI_SWITCH is not set
+-CONFIG_PPC_EARLY_DEBUG=y
+-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+-# CONFIG_PPC_EARLY_DEBUG_40x is not set
+-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc8572_ds_defconfig b/arch/powerpc/configs/mpc8572_ds_defconfig
+deleted file mode 100644
+index 53aa6f3..0000000
+--- a/arch/powerpc/configs/mpc8572_ds_defconfig
++++ /dev/null
+@@ -1,1549 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:37:06 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-CONFIG_BSD_PROCESS_ACCT=y
+-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+-# CONFIG_TASKSTATS is not set
+-CONFIG_AUDIT=y
+-# CONFIG_AUDITSYSCALL is not set
+-CONFIG_IKCONFIG=y
+-CONFIG_IKCONFIG_PROC=y
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-CONFIG_MODULE_FORCE_UNLOAD=y
+-CONFIG_MODVERSIONS=y
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-CONFIG_MPC85xx_DS=y
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-CONFIG_PPC_I8259=y
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-CONFIG_FSL_ULI1575=y
+-
+-#
+-# Kernel options
+-#
+-CONFIG_HIGHMEM=y
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=m
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-CONFIG_NET_KEY=m
+-# CONFIG_NET_KEY_MIGRATE is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-CONFIG_IP_ADVANCED_ROUTER=y
+-CONFIG_ASK_IP_FIB_HASH=y
+-# CONFIG_IP_FIB_TRIE is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_MULTIPLE_TABLES=y
+-CONFIG_IP_ROUTE_MULTIPATH=y
+-CONFIG_IP_ROUTE_VERBOSE=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-CONFIG_IP_PNP_RARP=y
+-CONFIG_NET_IPIP=y
+-CONFIG_NET_IPGRE=y
+-CONFIG_NET_IPGRE_BROADCAST=y
+-CONFIG_IP_MROUTE=y
+-CONFIG_IP_PIMSM_V1=y
+-CONFIG_IP_PIMSM_V2=y
+-CONFIG_ARPD=y
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-CONFIG_INET_TUNNEL=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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-CONFIG_IPV6=y
+-# CONFIG_IPV6_PRIVACY is not set
+-# CONFIG_IPV6_ROUTER_PREF is not set
+-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+-# CONFIG_INET6_AH is not set
+-# CONFIG_INET6_ESP is not set
+-# CONFIG_INET6_IPCOMP is not set
+-# CONFIG_IPV6_MIP6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET6_XFRM_MODE_TUNNEL=y
+-CONFIG_INET6_XFRM_MODE_BEET=y
+-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+-CONFIG_IPV6_SIT=y
+-# CONFIG_IPV6_TUNNEL is not set
+-# CONFIG_IPV6_MULTIPLE_TABLES is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-CONFIG_IP_SCTP=m
+-# CONFIG_SCTP_DBG_MSG is not set
+-# CONFIG_SCTP_DBG_OBJCNT is not set
+-# CONFIG_SCTP_HMAC_NONE is not set
+-# CONFIG_SCTP_HMAC_SHA1 is not set
+-CONFIG_SCTP_HMAC_MD5=y
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-CONFIG_FIB_RULES=y
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-CONFIG_BLK_DEV_NBD=y
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=131072
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-CONFIG_CHR_DEV_ST=y
+-# CONFIG_CHR_DEV_OSST is not set
+-CONFIG_BLK_DEV_SR=y
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-CONFIG_SCSI_MULTI_LUN=y
+-# CONFIG_SCSI_CONSTANTS is not set
+-CONFIG_SCSI_LOGGING=y
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-CONFIG_SATA_AHCI=y
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-# CONFIG_SATA_MV is not set
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-# CONFIG_SATA_SIL is not set
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-# CONFIG_SATA_FSL is not set
+-CONFIG_PATA_ALI=y
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-# CONFIG_PATA_PLATFORM is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-CONFIG_DUMMY=y
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-CONFIG_VITESSE_PHY=y
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-CONFIG_SERIO=y
+-CONFIG_SERIO_I8042=y
+-CONFIG_SERIO_SERPORT=y
+-# CONFIG_SERIO_PCIPS2 is not set
+-CONFIG_SERIO_LIBPS2=y
+-# CONFIG_SERIO_RAW is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=2
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+-CONFIG_SERIAL_8250_EXTENDED=y
+-CONFIG_SERIAL_8250_MANY_PORTS=y
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-CONFIG_SERIAL_8250_DETECT_IRQ=y
+-CONFIG_SERIAL_8250_RSA=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-CONFIG_NVRAM=y
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-# CONFIG_I2C_CHARDEV is not set
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-CONFIG_SENSORS_EEPROM=y
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-CONFIG_DVB_CORE=m
+-# CONFIG_DVB_CORE_ATTACH is not set
+-CONFIG_DVB_CAPTURE_DRIVERS=y
+-
+-#
+-# Supported SAA7146 based PCI Adapters
+-#
+-# CONFIG_TTPCI_EEPROM is not set
+-# CONFIG_DVB_BUDGET_CORE is not set
+-
+-#
+-# Supported USB Adapters
+-#
+-# CONFIG_DVB_USB is not set
+-# CONFIG_DVB_TTUSB_BUDGET is not set
+-# CONFIG_DVB_TTUSB_DEC is not set
+-# CONFIG_DVB_CINERGYT2 is not set
+-
+-#
+-# Supported FlexCopII (B2C2) Adapters
+-#
+-# CONFIG_DVB_B2C2_FLEXCOP is not set
+-
+-#
+-# Supported BT878 Adapters
+-#
+-
+-#
+-# Supported Pluto2 Adapters
+-#
+-# CONFIG_DVB_PLUTO2 is not set
+-
+-#
+-# Supported DVB Frontends
+-#
+-
+-#
+-# Customise DVB Frontends
+-#
+-# CONFIG_DVB_FE_CUSTOMISE is not set
+-
+-#
+-# DVB-S (satellite) frontends
+-#
+-# CONFIG_DVB_STV0299 is not set
+-# CONFIG_DVB_CX24110 is not set
+-# CONFIG_DVB_CX24123 is not set
+-# CONFIG_DVB_TDA8083 is not set
+-# CONFIG_DVB_MT312 is not set
+-# CONFIG_DVB_VES1X93 is not set
+-# CONFIG_DVB_S5H1420 is not set
+-# CONFIG_DVB_TDA10086 is not set
+-
+-#
+-# DVB-T (terrestrial) frontends
+-#
+-# CONFIG_DVB_SP8870 is not set
+-# CONFIG_DVB_SP887X is not set
+-# CONFIG_DVB_CX22700 is not set
+-# CONFIG_DVB_CX22702 is not set
+-# CONFIG_DVB_L64781 is not set
+-# CONFIG_DVB_TDA1004X is not set
+-# CONFIG_DVB_NXT6000 is not set
+-# CONFIG_DVB_MT352 is not set
+-# CONFIG_DVB_ZL10353 is not set
+-# CONFIG_DVB_DIB3000MB is not set
+-# CONFIG_DVB_DIB3000MC is not set
+-# CONFIG_DVB_DIB7000M is not set
+-# CONFIG_DVB_DIB7000P is not set
+-
+-#
+-# DVB-C (cable) frontends
+-#
+-# CONFIG_DVB_VES1820 is not set
+-# CONFIG_DVB_TDA10021 is not set
+-# CONFIG_DVB_TDA10023 is not set
+-# CONFIG_DVB_STV0297 is not set
+-
+-#
+-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+-#
+-# CONFIG_DVB_NXT200X is not set
+-# CONFIG_DVB_OR51211 is not set
+-# CONFIG_DVB_OR51132 is not set
+-# CONFIG_DVB_BCM3510 is not set
+-# CONFIG_DVB_LGDT330X is not set
+-# CONFIG_DVB_S5H1409 is not set
+-
+-#
+-# Tuners/PLL support
+-#
+-# CONFIG_DVB_PLL is not set
+-# CONFIG_DVB_TDA826X is not set
+-# CONFIG_DVB_TDA827X is not set
+-# CONFIG_DVB_TDA18271 is not set
+-# CONFIG_DVB_TUNER_QT1010 is not set
+-# CONFIG_DVB_TUNER_MT2060 is not set
+-# CONFIG_DVB_TUNER_MT2266 is not set
+-# CONFIG_DVB_TUNER_MT2131 is not set
+-# CONFIG_DVB_TUNER_DIB0070 is not set
+-# CONFIG_DVB_TUNER_XC5000 is not set
+-
+-#
+-# Miscellaneous devices
+-#
+-# CONFIG_DVB_LNBP21 is not set
+-# CONFIG_DVB_ISL6421 is not set
+-# CONFIG_DVB_TUA6100 is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Console display driver support
+-#
+-CONFIG_VGA_CONSOLE=y
+-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+-CONFIG_DUMMY_CONSOLE=y
+-
+-#
+-# Sound
+-#
+-CONFIG_SOUND=y
+-
+-#
+-# Advanced Linux Sound Architecture
+-#
+-CONFIG_SND=y
+-CONFIG_SND_TIMER=y
+-CONFIG_SND_PCM=y
+-# CONFIG_SND_SEQUENCER is not set
+-# CONFIG_SND_MIXER_OSS is not set
+-# CONFIG_SND_PCM_OSS is not set
+-# CONFIG_SND_DYNAMIC_MINORS is not set
+-CONFIG_SND_SUPPORT_OLD_API=y
+-CONFIG_SND_VERBOSE_PROCFS=y
+-# CONFIG_SND_VERBOSE_PRINTK is not set
+-# CONFIG_SND_DEBUG is not set
+-
+-#
+-# Generic devices
+-#
+-CONFIG_SND_AC97_CODEC=y
+-# CONFIG_SND_DUMMY is not set
+-# CONFIG_SND_MTPAV is not set
+-# CONFIG_SND_SERIAL_U16550 is not set
+-# CONFIG_SND_MPU401 is not set
+-
+-#
+-# PCI devices
+-#
+-# CONFIG_SND_AD1889 is not set
+-# CONFIG_SND_ALS300 is not set
+-# CONFIG_SND_ALS4000 is not set
+-# CONFIG_SND_ALI5451 is not set
+-# CONFIG_SND_ATIIXP is not set
+-# CONFIG_SND_ATIIXP_MODEM is not set
+-# CONFIG_SND_AU8810 is not set
+-# CONFIG_SND_AU8820 is not set
+-# CONFIG_SND_AU8830 is not set
+-# CONFIG_SND_AZT3328 is not set
+-# CONFIG_SND_BT87X is not set
+-# CONFIG_SND_CA0106 is not set
+-# CONFIG_SND_CMIPCI is not set
+-# CONFIG_SND_OXYGEN is not set
+-# CONFIG_SND_CS4281 is not set
+-# CONFIG_SND_CS46XX is not set
+-# CONFIG_SND_CS5530 is not set
+-# CONFIG_SND_DARLA20 is not set
+-# CONFIG_SND_GINA20 is not set
+-# CONFIG_SND_LAYLA20 is not set
+-# CONFIG_SND_DARLA24 is not set
+-# CONFIG_SND_GINA24 is not set
+-# CONFIG_SND_LAYLA24 is not set
+-# CONFIG_SND_MONA is not set
+-# CONFIG_SND_MIA is not set
+-# CONFIG_SND_ECHO3G is not set
+-# CONFIG_SND_INDIGO is not set
+-# CONFIG_SND_INDIGOIO is not set
+-# CONFIG_SND_INDIGODJ is not set
+-# CONFIG_SND_EMU10K1 is not set
+-# CONFIG_SND_EMU10K1X is not set
+-# CONFIG_SND_ENS1370 is not set
+-# CONFIG_SND_ENS1371 is not set
+-# CONFIG_SND_ES1938 is not set
+-# CONFIG_SND_ES1968 is not set
+-# CONFIG_SND_FM801 is not set
+-# CONFIG_SND_HDA_INTEL is not set
+-# CONFIG_SND_HDSP is not set
+-# CONFIG_SND_HDSPM is not set
+-# CONFIG_SND_HIFIER is not set
+-# CONFIG_SND_ICE1712 is not set
+-# CONFIG_SND_ICE1724 is not set
+-CONFIG_SND_INTEL8X0=y
+-# CONFIG_SND_INTEL8X0M is not set
+-# CONFIG_SND_KORG1212 is not set
+-# CONFIG_SND_MAESTRO3 is not set
+-# CONFIG_SND_MIXART is not set
+-# CONFIG_SND_NM256 is not set
+-# CONFIG_SND_PCXHR is not set
+-# CONFIG_SND_RIPTIDE is not set
+-# CONFIG_SND_RME32 is not set
+-# CONFIG_SND_RME96 is not set
+-# CONFIG_SND_RME9652 is not set
+-# CONFIG_SND_SONICVIBES is not set
+-# CONFIG_SND_TRIDENT is not set
+-# CONFIG_SND_VIA82XX is not set
+-# CONFIG_SND_VIA82XX_MODEM is not set
+-# CONFIG_SND_VIRTUOSO is not set
+-# CONFIG_SND_VX222 is not set
+-# CONFIG_SND_YMFPCI is not set
+-# CONFIG_SND_AC97_POWER_SAVE is not set
+-
+-#
+-# ALSA PowerMac devices
+-#
+-
+-#
+-# ALSA PowerPC devices
+-#
+-
+-#
+-# USB devices
+-#
+-# CONFIG_SND_USB_AUDIO is not set
+-# CONFIG_SND_USB_USX2Y is not set
+-# CONFIG_SND_USB_CAIAQ is not set
+-
+-#
+-# System on Chip audio support
+-#
+-# CONFIG_SND_SOC is not set
+-
+-#
+-# SoC Audio support for SuperH
+-#
+-
+-#
+-# ALSA SoC audio for Freescale SOCs
+-#
+-
+-#
+-# Open Sound System
+-#
+-# CONFIG_SOUND_PRIME is not set
+-CONFIG_AC97_BUS=y
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-CONFIG_USB_HID=y
+-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+-# CONFIG_HID_FF is not set
+-# CONFIG_USB_HIDDEV is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-# CONFIG_USB_EHCI_FSL is not set
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-CONFIG_RTC_DRV_CMOS=y
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-CONFIG_ISO9660_FS=m
+-CONFIG_JOLIET=y
+-CONFIG_ZISOFS=y
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=m
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-CONFIG_NTFS_FS=y
+-# CONFIG_NTFS_DEBUG is not set
+-# CONFIG_NTFS_RW is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-CONFIG_ADFS_FS=m
+-# CONFIG_ADFS_FS_RW is not set
+-CONFIG_AFFS_FS=m
+-CONFIG_HFS_FS=m
+-CONFIG_HFSPLUS_FS=m
+-CONFIG_BEFS_FS=m
+-# CONFIG_BEFS_DEBUG is not set
+-CONFIG_BFS_FS=m
+-CONFIG_EFS_FS=m
+-CONFIG_CRAMFS=y
+-CONFIG_VXFS_FS=m
+-# CONFIG_MINIX_FS is not set
+-CONFIG_HPFS_FS=m
+-CONFIG_QNX4FS_FS=m
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_SYSV_FS=m
+-CONFIG_UFS_FS=m
+-# CONFIG_UFS_FS_WRITE is not set
+-# CONFIG_UFS_DEBUG is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-CONFIG_NFSD=y
+-# CONFIG_NFSD_V3 is not set
+-CONFIG_NFSD_TCP=y
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_EXPORTFS=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-CONFIG_MAC_PARTITION=y
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-CONFIG_NLS_UTF8=m
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-CONFIG_LIBCRC32C=m
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_HIGHMEM is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-CONFIG_DEBUG_INFO=y
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_HASH=y
+-CONFIG_CRYPTO_MANAGER=y
+-CONFIG_CRYPTO_HMAC=y
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-CONFIG_CRYPTO_SHA1=m
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
+deleted file mode 100644
+index a469fe9..0000000
+--- a/arch/powerpc/configs/mpc85xx_cds_defconfig
++++ /dev/null
+@@ -1,935 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:30 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-CONFIG_MPC85xx_CDS=y
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-CONFIG_PPC_I8259=y
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-# CONFIG_BLK_DEV_IDEDISK is not set
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-CONFIG_E1000=y
+-CONFIG_E1000_NAPI=y
+-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
+index 558b0d3..fca1142 100644
+--- a/arch/powerpc/configs/pmac32_defconfig
++++ b/arch/powerpc/configs/pmac32_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 11:05:14 2008
++# Thu Mar 27 13:56:21 2008
+ #
+ # CONFIG_PPC64 is not set
+ 
+@@ -77,8 +77,6 @@ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=14
+ # CONFIG_CGROUPS is not set
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+@@ -272,7 +270,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ # CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ CONFIG_PCCARD=m
+ # CONFIG_PCMCIA_DEBUG is not set
+@@ -1895,6 +1893,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+ 
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/ppc40x_defconfig b/arch/powerpc/configs/ppc40x_defconfig
+new file mode 100644
+index 0000000..9d0140e
+--- /dev/null
++++ b/arch/powerpc/configs/ppc40x_defconfig
+@@ -0,0 +1,896 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc9
++# Tue Apr 15 08:46:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_EP405=y
++CONFIG_KILAUEA=y
++CONFIG_MAKALU=y
++CONFIG_WALNUT=y
++CONFIG_XILINX_VIRTEX_GENERIC_BOARD=y
++CONFIG_405GP=y
++CONFIG_405EX=y
++CONFIG_XILINX_VIRTEX=y
++CONFIG_XILINX_VIRTEX_II_PRO=y
++CONFIG_XILINX_VIRTEX_4_FX=y
++CONFIG_IBM405_ERR77=y
++CONFIG_IBM405_ERR51=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_OF_RTC=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_4xx_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++# CONFIG_PCI_LEGACY is not set
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# 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=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++CONFIG_XILINX_HWICAP=m
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
+index 57bd775..12f9b5a 100644
+--- a/arch/powerpc/configs/ppc44x_defconfig
++++ b/arch/powerpc/configs/ppc44x_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:57:35 2008
++# Linux kernel version: 2.6.25-rc6
++# Sat Apr  5 09:35:48 2008
+ #
+ # CONFIG_PPC64 is not set
+ 
+@@ -79,6 +79,7 @@ CONFIG_FAIR_GROUP_SCHED=y
+ CONFIG_USER_SCHED=y
+ # CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+ # CONFIG_NAMESPACES is not set
+ CONFIG_BLK_DEV_INITRD=y
+@@ -113,6 +114,7 @@ CONFIG_SLUB=y
+ CONFIG_HAVE_OPROFILE=y
+ # CONFIG_KPROBES is not set
+ CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
+ CONFIG_PROC_PAGE_MONITOR=y
+ CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+@@ -143,7 +145,6 @@ CONFIG_DEFAULT_AS=y
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+ CONFIG_PPC4xx_PCI_EXPRESS=y
+ 
+ #
+@@ -161,12 +162,15 @@ CONFIG_TAISHAN=y
+ CONFIG_KATMAI=y
+ CONFIG_RAINIER=y
+ CONFIG_WARP=y
++CONFIG_CANYONLANDS=y
++CONFIG_YOSEMITE=y
+ CONFIG_440EP=y
+ CONFIG_440EPX=y
+ CONFIG_440GRX=y
+ CONFIG_440GP=y
+ CONFIG_440GX=y
+ CONFIG_440SPe=y
++CONFIG_460EX=y
+ CONFIG_IBM440EP_ERR42=y
+ # CONFIG_IPIC is not set
+ # CONFIG_MPIC is not set
+@@ -199,7 +203,6 @@ CONFIG_HZ=250
+ CONFIG_PREEMPT_NONE=y
+ # CONFIG_PREEMPT_VOLUNTARY is not set
+ # CONFIG_PREEMPT is not set
+-# CONFIG_RCU_TRACE is not set
+ CONFIG_BINFMT_ELF=y
+ # CONFIG_BINFMT_MISC is not set
+ CONFIG_MATH_EMULATION=y
+@@ -232,6 +235,7 @@ CONFIG_ISA_DMA_API=y
+ #
+ CONFIG_ZONE_DMA=y
+ CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_4xx_SOC=y
+ CONFIG_PCI=y
+ CONFIG_PCI_DOMAINS=y
+ CONFIG_PCI_SYSCALL=y
+@@ -678,6 +682,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y
+ # CONFIG_INFINIBAND is not set
+ # CONFIG_EDAC is not set
+ # CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
+ 
+ #
+ # Userspace I/O
+@@ -805,6 +810,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+ 
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
+index 880ab7a..970282b 100644
+--- a/arch/powerpc/configs/ppc64_defconfig
++++ b/arch/powerpc/configs/ppc64_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 11:06:28 2008
++# Thu Mar 27 13:56:24 2008
+ #
+ CONFIG_PPC64=y
+ 
+@@ -84,8 +84,6 @@ CONFIG_CGROUPS=y
+ # CONFIG_CGROUP_NS is not set
+ CONFIG_CPUSETS=y
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ # CONFIG_CGROUP_CPUACCT is not set
+ # CONFIG_RESOURCE_COUNTERS is not set
+ CONFIG_SYSFS_DEPRECATED=y
+@@ -289,6 +287,7 @@ CONFIG_ARCH_HAS_WALK_MEMORY=y
+ CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+ CONFIG_KEXEC=y
+ # CONFIG_CRASH_DUMP is not set
++# CONFIG_PHYP_DUMP is not set
+ CONFIG_IRQ_ALL_CPUS=y
+ # CONFIG_NUMA is not set
+ CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+@@ -335,7 +334,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ CONFIG_PCI_MSI=y
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ CONFIG_PCCARD=y
+ # CONFIG_PCMCIA_DEBUG is not set
+@@ -1881,6 +1880,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+ 
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
+index 755aca7..3e2593c 100644
+--- a/arch/powerpc/configs/pseries_defconfig
++++ b/arch/powerpc/configs/pseries_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 11:08:01 2008
++# Thu Mar 27 13:56:28 2008
+ #
+ CONFIG_PPC64=y
+ 
+@@ -83,8 +83,6 @@ CONFIG_CGROUPS=y
+ CONFIG_CGROUP_NS=y
+ CONFIG_CPUSETS=y
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_CGROUP_CPUACCT=y
+ # CONFIG_RESOURCE_COUNTERS is not set
+ CONFIG_SYSFS_DEPRECATED=y
+@@ -237,6 +235,7 @@ CONFIG_ARCH_HAS_WALK_MEMORY=y
+ CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+ CONFIG_KEXEC=y
+ # CONFIG_CRASH_DUMP is not set
++# CONFIG_PHYP_DUMP is not set
+ CONFIG_IRQ_ALL_CPUS=y
+ CONFIG_NUMA=y
+ CONFIG_NODES_SHIFT=4
+@@ -283,7 +282,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ CONFIG_PCI_MSI=y
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_PCCARD is not set
+ CONFIG_HOTPLUG_PCI=m
+@@ -1519,6 +1518,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+ 
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/rainier_defconfig b/arch/powerpc/configs/rainier_defconfig
+deleted file mode 100644
+index dec18ca..0000000
+--- a/arch/powerpc/configs/rainier_defconfig
++++ /dev/null
+@@ -1,899 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:53:10 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-CONFIG_RAINIER=y
+-# CONFIG_WARP is not set
+-CONFIG_440GRX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-# CONFIG_MTD_BLKDEVS is not set
+-# CONFIG_MTD_BLOCK is not set
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-CONFIG_MTD_CFI_INTELEXT=y
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-CONFIG_MACINTOSH_DRIVERS=y
+-# CONFIG_MAC_EMUMOUSEBTN is not set
+-# CONFIG_WINDFARM is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_NET_ETHERNET is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-CONFIG_PPC_EARLY_DEBUG=y
+-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+-CONFIG_PPC_EARLY_DEBUG_44x=y
+-# CONFIG_PPC_EARLY_DEBUG_40x is not set
+-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+-CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
+-CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x1
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sbc834x_defconfig b/arch/powerpc/configs/sbc834x_defconfig
+deleted file mode 100644
+index 1f15182..0000000
+--- a/arch/powerpc/configs/sbc834x_defconfig
++++ /dev/null
+@@ -1,828 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:38 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-CONFIG_SBC834x=y
+-CONFIG_PPC_MPC834x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=m
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-CONFIG_BROADCOM_PHY=y
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-# CONFIG_GFAR_NAPI is not set
+-# CONFIG_NETDEV_10000 is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-# CONFIG_USB_SUPPORT is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-# CONFIG_EXT2_FS is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-# CONFIG_CRYPTO_HW is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sbc8548_defconfig b/arch/powerpc/configs/sbc8548_defconfig
+deleted file mode 100644
+index 67f6797..0000000
+--- a/arch/powerpc/configs/sbc8548_defconfig
++++ /dev/null
+@@ -1,812 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:39 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-CONFIG_SBC8548=y
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=4096
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-CONFIG_BROADCOM_PHY=y
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-# CONFIG_HID_SUPPORT is not set
+-# CONFIG_USB_SUPPORT is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-# CONFIG_EXT2_FS is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sbc8560_defconfig b/arch/powerpc/configs/sbc8560_defconfig
+deleted file mode 100644
+index fef6055..0000000
+--- a/arch/powerpc/configs/sbc8560_defconfig
++++ /dev/null
+@@ -1,830 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:39 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-CONFIG_SBC8560=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-CONFIG_BROADCOM_PHY=y
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-CONFIG_NETDEV_10000=y
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-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 is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-# CONFIG_USB_ARCH_HAS_HCD is not set
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-CONFIG_RTC_DRV_M48T59=y
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-# CONFIG_EXT2_FS is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_DEBUG_SLAB is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-CONFIG_PPC_EARLY_DEBUG=y
+-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+-# CONFIG_PPC_EARLY_DEBUG_40x is not set
+-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sbc8641d_defconfig b/arch/powerpc/configs/sbc8641d_defconfig
+new file mode 100644
+index 0000000..3180125
+--- /dev/null
++++ b/arch/powerpc/configs/sbc8641d_defconfig
+@@ -0,0 +1,1342 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Thu Apr 10 18:03:25 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_ALTIVEC=y
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_SMP=y
++CONFIG_NR_CPUS=2
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_GENERIC_LOCKBREAK=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++CONFIG_GENERIC_TBSYNC=y
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++CONFIG_RELAY=y
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_STOP_MACHINE=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++# CONFIG_PPC_83xx is not set
++CONFIG_PPC_86xx=y
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_MPC8641_HPCN is not set
++CONFIG_SBC8641D=y
++# CONFIG_MPC8610_HPCD is not set
++CONFIG_MPC8641=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++# CONFIG_NO_HZ is not set
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++# CONFIG_PREEMPT_NONE is not set
++# CONFIG_PREEMPT_VOLUNTARY is not set
++CONFIG_PREEMPT=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=m
++CONFIG_FORCE_MAX_ZONEORDER=11
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_IRQ_ALL_CPUS=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++CONFIG_PCIEPORTBUS=y
++CONFIG_PCIEAER=y
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=m
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=m
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_ASK_IP_FIB_HASH=y
++# CONFIG_IP_FIB_TRIE is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_NET_IPIP=m
++CONFIG_NET_IPGRE=m
++CONFIG_NET_IPGRE_BROADCAST=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++CONFIG_INET_AH=m
++CONFIG_INET_ESP=m
++CONFIG_INET_IPCOMP=m
++CONFIG_INET_XFRM_TUNNEL=m
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++CONFIG_IPV6=m
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++CONFIG_INET6_AH=m
++CONFIG_INET6_ESP=m
++CONFIG_INET6_IPCOMP=m
++# CONFIG_IPV6_MIP6 is not set
++CONFIG_INET6_XFRM_TUNNEL=m
++CONFIG_INET6_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=m
++CONFIG_IPV6_TUNNEL=m
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++CONFIG_BRIDGE_NETFILTER=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++CONFIG_NETFILTER_XTABLES=m
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
++# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++# CONFIG_NETFILTER_XT_MATCH_MAC is not set
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
++# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_TIME is not set
++# CONFIG_NETFILTER_XT_MATCH_U32 is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
++
++#
++# IP: Netfilter Configuration
++#
++CONFIG_IP_NF_QUEUE=m
++CONFIG_IP_NF_IPTABLES=m
++CONFIG_IP_NF_MATCH_RECENT=m
++CONFIG_IP_NF_MATCH_ECN=m
++# CONFIG_IP_NF_MATCH_AH is not set
++CONFIG_IP_NF_MATCH_TTL=m
++CONFIG_IP_NF_MATCH_ADDRTYPE=m
++CONFIG_IP_NF_FILTER=m
++CONFIG_IP_NF_TARGET_REJECT=m
++CONFIG_IP_NF_TARGET_LOG=m
++CONFIG_IP_NF_TARGET_ULOG=m
++CONFIG_IP_NF_MANGLE=m
++CONFIG_IP_NF_TARGET_ECN=m
++# CONFIG_IP_NF_TARGET_TTL is not set
++CONFIG_IP_NF_RAW=m
++CONFIG_IP_NF_ARPTABLES=m
++CONFIG_IP_NF_ARPFILTER=m
++CONFIG_IP_NF_ARP_MANGLE=m
++
++#
++# IPv6: Netfilter Configuration
++#
++CONFIG_IP6_NF_QUEUE=m
++CONFIG_IP6_NF_IPTABLES=m
++CONFIG_IP6_NF_MATCH_RT=m
++CONFIG_IP6_NF_MATCH_OPTS=m
++CONFIG_IP6_NF_MATCH_FRAG=m
++CONFIG_IP6_NF_MATCH_HL=m
++CONFIG_IP6_NF_MATCH_IPV6HEADER=m
++# CONFIG_IP6_NF_MATCH_AH is not set
++# CONFIG_IP6_NF_MATCH_MH is not set
++CONFIG_IP6_NF_MATCH_EUI64=m
++CONFIG_IP6_NF_FILTER=m
++CONFIG_IP6_NF_TARGET_LOG=m
++# CONFIG_IP6_NF_TARGET_REJECT is not set
++CONFIG_IP6_NF_MANGLE=m
++# CONFIG_IP6_NF_TARGET_HL is not set
++CONFIG_IP6_NF_RAW=m
++
++#
++# Bridge: Netfilter Configuration
++#
++# CONFIG_BRIDGE_NF_EBTABLES is not set
++# CONFIG_IP_DCCP is not set
++CONFIG_IP_SCTP=m
++# CONFIG_SCTP_DBG_MSG is not set
++# CONFIG_SCTP_DBG_OBJCNT is not set
++# CONFIG_SCTP_HMAC_NONE is not set
++# CONFIG_SCTP_HMAC_SHA1 is not set
++CONFIG_SCTP_HMAC_MD5=y
++CONFIG_TIPC=m
++# CONFIG_TIPC_ADVANCED is not set
++# CONFIG_TIPC_DEBUG is not set
++CONFIG_ATM=m
++CONFIG_ATM_CLIP=m
++# CONFIG_ATM_CLIP_NO_ICMP is not set
++CONFIG_ATM_LANE=m
++CONFIG_ATM_MPOA=m
++CONFIG_ATM_BR2684=m
++# CONFIG_ATM_BR2684_IPFILTER is not set
++CONFIG_BRIDGE=m
++CONFIG_VLAN_8021Q=m
++# CONFIG_DECNET is not set
++CONFIG_LLC=m
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=m
++CONFIG_NET_SCHED=y
++
++#
++# Queueing/Scheduling
++#
++CONFIG_NET_SCH_CBQ=m
++CONFIG_NET_SCH_HTB=m
++CONFIG_NET_SCH_HFSC=m
++CONFIG_NET_SCH_ATM=m
++CONFIG_NET_SCH_PRIO=m
++# CONFIG_NET_SCH_RR is not set
++CONFIG_NET_SCH_RED=m
++CONFIG_NET_SCH_SFQ=m
++CONFIG_NET_SCH_TEQL=m
++CONFIG_NET_SCH_TBF=m
++CONFIG_NET_SCH_GRED=m
++CONFIG_NET_SCH_DSMARK=m
++CONFIG_NET_SCH_NETEM=m
++
++#
++# Classification
++#
++CONFIG_NET_CLS=y
++# CONFIG_NET_CLS_BASIC is not set
++CONFIG_NET_CLS_TCINDEX=m
++CONFIG_NET_CLS_ROUTE4=m
++CONFIG_NET_CLS_ROUTE=y
++CONFIG_NET_CLS_FW=m
++CONFIG_NET_CLS_U32=m
++# CONFIG_CLS_U32_PERF is not set
++# CONFIG_CLS_U32_MARK is not set
++CONFIG_NET_CLS_RSVP=m
++CONFIG_NET_CLS_RSVP6=m
++# CONFIG_NET_CLS_FLOW is not set
++# CONFIG_NET_EMATCH is not set
++# CONFIG_NET_CLS_ACT is not set
++# CONFIG_NET_CLS_IND is not set
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++CONFIG_NET_PKTGEN=m
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++# CONFIG_MTD_CFI_NOSWAP is not set
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_LE_BYTE_SWAP=y
++# CONFIG_MTD_CFI_GEOMETRY is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=m
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++CONFIG_MD_LINEAR=y
++CONFIG_MD_RAID0=y
++CONFIG_MD_RAID1=y
++CONFIG_MD_RAID10=y
++# CONFIG_MD_RAID456 is not set
++CONFIG_MD_MULTIPATH=y
++CONFIG_MD_FAULTY=y
++CONFIG_BLK_DEV_DM=y
++# CONFIG_DM_DEBUG is not set
++CONFIG_DM_CRYPT=y
++CONFIG_DM_SNAPSHOT=y
++CONFIG_DM_MIRROR=y
++CONFIG_DM_ZERO=y
++# CONFIG_DM_MULTIPATH is not set
++# CONFIG_DM_DELAY is not set
++# CONFIG_DM_UEVENT is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++CONFIG_DUMMY=m
++CONFIG_BONDING=m
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++CONFIG_TUN=m
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++CONFIG_BROADCOM_PHY=y
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++# CONFIG_GFAR_NAPI is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++CONFIG_ATM_DRIVERS=y
++# CONFIG_ATM_DUMMY is not set
++# CONFIG_ATM_TCP is not set
++# CONFIG_ATM_LANAI is not set
++# CONFIG_ATM_ENI is not set
++# CONFIG_ATM_FIRESTREAM is not set
++# CONFIG_ATM_ZATM is not set
++# CONFIG_ATM_NICSTAR is not set
++# CONFIG_ATM_IDT77252 is not set
++# CONFIG_ATM_AMBASSADOR is not set
++# CONFIG_ATM_HORIZON is not set
++# CONFIG_ATM_IA is not set
++# CONFIG_ATM_FORE200E_MAYBE is not set
++# CONFIG_ATM_HE is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++CONFIG_PPP=m
++CONFIG_PPP_MULTILINK=y
++CONFIG_PPP_FILTER=y
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++# CONFIG_PPP_MPPE is not set
++CONFIG_PPPOE=m
++CONFIG_PPPOATM=m
++# CONFIG_PPPOL2TP is not set
++CONFIG_SLIP=m
++CONFIG_SLIP_COMPRESSED=y
++CONFIG_SLHC=m
++CONFIG_SLIP_SMART=y
++CONFIG_SLIP_MODE_SLIP6=y
++CONFIG_NETCONSOLE=y
++# CONFIG_NETCONSOLE_DYNAMIC is not set
++CONFIG_NETPOLL=y
++CONFIG_NETPOLL_TRAP=y
++CONFIG_NET_POLL_CONTROLLER=y
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++CONFIG_SOFT_WATCHDOG=m
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++CONFIG_VGA_CONSOLE=y
++# CONFIG_VGACON_SOFT_SCROLLBACK is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++CONFIG_EXT3_FS_POSIX_ACL=y
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=m
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++CONFIG_REISERFS_FS_XATTR=y
++CONFIG_REISERFS_FS_POSIX_ACL=y
++# CONFIG_REISERFS_FS_SECURITY is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++CONFIG_OCFS2_FS=m
++CONFIG_OCFS2_DEBUG_MASKLOG=y
++# CONFIG_OCFS2_DEBUG_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_AUTOFS_FS=m
++CONFIG_AUTOFS4_FS=m
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++CONFIG_MINIX_FS=m
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++CONFIG_ROMFS_FS=m
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++CONFIG_NFS_DIRECTIO=y
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++CONFIG_SMB_FS=m
++CONFIG_SMB_NLS_DEFAULT=y
++CONFIG_SMB_NLS_REMOTE="cp437"
++CONFIG_CIFS=m
++# CONFIG_CIFS_STATS is not set
++# CONFIG_CIFS_WEAK_PW_HASH is not set
++CONFIG_CIFS_XATTR=y
++CONFIG_CIFS_POSIX=y
++# CONFIG_CIFS_DEBUG2 is not set
++# CONFIG_CIFS_EXPERIMENTAL is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=m
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=m
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ASCII=m
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_NLS_UTF8=m
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++CONFIG_SECURITY_NETWORK=y
++# CONFIG_SECURITY_NETWORK_XFRM is not set
++CONFIG_SECURITY_CAPABILITIES=y
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++CONFIG_CRYPTO_NULL=m
++CONFIG_CRYPTO_MD4=m
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=m
++CONFIG_CRYPTO_SHA256=m
++CONFIG_CRYPTO_SHA512=m
++CONFIG_CRYPTO_WP512=m
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++CONFIG_CRYPTO_BLOWFISH=m
++CONFIG_CRYPTO_TWOFISH=m
++CONFIG_CRYPTO_TWOFISH_COMMON=m
++CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_AES=m
++CONFIG_CRYPTO_CAST5=m
++CONFIG_CRYPTO_CAST6=m
++CONFIG_CRYPTO_TEA=m
++CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_KHAZAD=m
++CONFIG_CRYPTO_ANUBIS=m
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++CONFIG_CRYPTO_DEFLATE=m
++CONFIG_CRYPTO_MICHAEL_MIC=m
++CONFIG_CRYPTO_CRC32C=m
++# CONFIG_CRYPTO_CAMELLIA is not set
++CONFIG_CRYPTO_TEST=m
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sequoia_defconfig b/arch/powerpc/configs/sequoia_defconfig
+deleted file mode 100644
+index dd5d630..0000000
+--- a/arch/powerpc/configs/sequoia_defconfig
++++ /dev/null
+@@ -1,916 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:53:46 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-CONFIG_SEQUOIA=y
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-# CONFIG_WARP is not set
+-CONFIG_440EPX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-# CONFIG_MTD_BLKDEVS is not set
+-# CONFIG_MTD_BLOCK is not set
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-CONFIG_MTD_CFI_INTELEXT=y
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-CONFIG_PPC_EARLY_DEBUG=y
+-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+-CONFIG_PPC_EARLY_DEBUG_44x=y
+-# CONFIG_PPC_EARLY_DEBUG_40x is not set
+-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+-CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
+-CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x1
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/stx_gp3_defconfig b/arch/powerpc/configs/stx_gp3_defconfig
+deleted file mode 100644
+index 1d303c4..0000000
+--- a/arch/powerpc/configs/stx_gp3_defconfig
++++ /dev/null
+@@ -1,1253 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:42 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-# CONFIG_MODULE_UNLOAD is not set
+-CONFIG_MODVERSIONS=y
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-CONFIG_STX_GP3=y
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-CONFIG_HIGHMEM=y
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=m
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-# CONFIG_IP_PNP_DHCP is not set
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IP_VS is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-CONFIG_NETFILTER=y
+-# CONFIG_NETFILTER_DEBUG is not set
+-CONFIG_NETFILTER_ADVANCED=y
+-
+-#
+-# Core Netfilter Configuration
+-#
+-# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+-# CONFIG_NETFILTER_NETLINK_LOG is not set
+-# CONFIG_NF_CONNTRACK is not set
+-CONFIG_NETFILTER_XTABLES=m
+-# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+-# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+-# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+-# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+-# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+-# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+-# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+-# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+-# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+-# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+-# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+-# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+-# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+-# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+-# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+-# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+-# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+-# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+-# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+-# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+-# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+-# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+-# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+-# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+-# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+-
+-#
+-# IP: Netfilter Configuration
+-#
+-# CONFIG_IP_NF_QUEUE is not set
+-CONFIG_IP_NF_IPTABLES=m
+-# CONFIG_IP_NF_MATCH_RECENT is not set
+-# CONFIG_IP_NF_MATCH_ECN is not set
+-# CONFIG_IP_NF_MATCH_AH is not set
+-# CONFIG_IP_NF_MATCH_TTL is not set
+-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+-CONFIG_IP_NF_FILTER=m
+-# CONFIG_IP_NF_TARGET_REJECT is not set
+-# CONFIG_IP_NF_TARGET_LOG is not set
+-# CONFIG_IP_NF_TARGET_ULOG is not set
+-# CONFIG_IP_NF_MANGLE is not set
+-# CONFIG_IP_NF_RAW is not set
+-# CONFIG_IP_NF_ARPTABLES is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-CONFIG_NET_PKTGEN=y
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-CONFIG_PARPORT=m
+-CONFIG_PARPORT_PC=m
+-# CONFIG_PARPORT_PC_FIFO is not set
+-# CONFIG_PARPORT_PC_SUPERIO is not set
+-# CONFIG_PARPORT_GSC is not set
+-# CONFIG_PARPORT_AX88796 is not set
+-# CONFIG_PARPORT_1284 is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_PARIDE is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=m
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-CONFIG_BLK_DEV_NBD=m
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-CONFIG_BLK_DEV_IDECD=m
+-CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_BLK_DEV_IDESCSI is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-
+-#
+-# PCI IDE chipsets support
+-#
+-# CONFIG_BLK_DEV_GENERIC is not set
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-# CONFIG_BLK_DEV_VIA82CXXX is not set
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-# CONFIG_BLK_DEV_IDEDMA is not set
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=m
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=m
+-CONFIG_CHR_DEV_ST=m
+-# CONFIG_CHR_DEV_OSST is not set
+-CONFIG_BLK_DEV_SR=m
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-CONFIG_CHR_DEV_SG=m
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-CONFIG_SCSI_MULTI_LUN=y
+-CONFIG_SCSI_CONSTANTS=y
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_PPA is not set
+-# CONFIG_SCSI_IMM is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-# CONFIG_NET_POCKET is not set
+-# CONFIG_FS_ENET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PLIP is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-CONFIG_INPUT_MOUSEDEV=y
+-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
+-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024
+-CONFIG_INPUT_JOYDEV=m
+-CONFIG_INPUT_EVDEV=m
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-CONFIG_INPUT_KEYBOARD=y
+-CONFIG_KEYBOARD_ATKBD=y
+-# CONFIG_KEYBOARD_SUNKBD is not set
+-# CONFIG_KEYBOARD_LKKBD is not set
+-# CONFIG_KEYBOARD_XTKBD is not set
+-# CONFIG_KEYBOARD_NEWTON is not set
+-# CONFIG_KEYBOARD_STOWAWAY is not set
+-CONFIG_INPUT_MOUSE=y
+-CONFIG_MOUSE_PS2=y
+-CONFIG_MOUSE_PS2_ALPS=y
+-CONFIG_MOUSE_PS2_LOGIPS2PP=y
+-CONFIG_MOUSE_PS2_SYNAPTICS=y
+-CONFIG_MOUSE_PS2_LIFEBOOK=y
+-CONFIG_MOUSE_PS2_TRACKPOINT=y
+-# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+-# CONFIG_MOUSE_SERIAL is not set
+-# CONFIG_MOUSE_APPLETOUCH is not set
+-# CONFIG_MOUSE_VSXXXAA is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-CONFIG_SERIO=y
+-CONFIG_SERIO_I8042=y
+-CONFIG_SERIO_SERPORT=y
+-# CONFIG_SERIO_PARKBD is not set
+-# CONFIG_SERIO_PCIPS2 is not set
+-CONFIG_SERIO_LIBPS2=y
+-# CONFIG_SERIO_RAW is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-# CONFIG_SERIAL_CPM_SCC1 is not set
+-CONFIG_SERIAL_CPM_SCC2=y
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-CONFIG_PRINTER=m
+-# CONFIG_LP_CONSOLE is not set
+-# CONFIG_PPDEV is not set
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=m
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=m
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=m
+-
+-#
+-# I2C Algorithms
+-#
+-CONFIG_I2C_ALGOBIT=m
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-# CONFIG_I2C_MPC is not set
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-CONFIG_AGP=m
+-CONFIG_DRM=m
+-# CONFIG_DRM_TDFX is not set
+-# CONFIG_DRM_R128 is not set
+-# CONFIG_DRM_RADEON is not set
+-# CONFIG_DRM_MGA is not set
+-# CONFIG_DRM_SIS is not set
+-# CONFIG_DRM_VIA is not set
+-# CONFIG_DRM_SAVAGE is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-CONFIG_SOUND=m
+-
+-#
+-# Advanced Linux Sound Architecture
+-#
+-# CONFIG_SND is not set
+-
+-#
+-# Open Sound System
+-#
+-# CONFIG_SOUND_PRIME is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-# CONFIG_AUXDISPLAY is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-CONFIG_AUTOFS_FS=m
+-CONFIG_AUTOFS4_FS=y
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-CONFIG_ISO9660_FS=m
+-# CONFIG_JOLIET is not set
+-# CONFIG_ZISOFS is not set
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=m
+-CONFIG_MSDOS_FS=m
+-CONFIG_VFAT_FS=m
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-# CONFIG_PROC_KCORE is not set
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_CRAMFS=m
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-CONFIG_SMB_FS=m
+-# CONFIG_SMB_NLS_DEFAULT is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-CONFIG_CRC_CCITT=y
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=m
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_HIGHMEM is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-CONFIG_BDI_SWITCH=y
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/taishan_defconfig b/arch/powerpc/configs/taishan_defconfig
+deleted file mode 100644
+index 087aedc..0000000
+--- a/arch/powerpc/configs/taishan_defconfig
++++ /dev/null
+@@ -1,815 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:40:44 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-CONFIG_TAISHAN=y
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-# CONFIG_WARP is not set
+-CONFIG_440GX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-CONFIG_MACINTOSH_DRIVERS=y
+-# CONFIG_MAC_EMUMOUSEBTN is not set
+-# CONFIG_WINDFARM is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-CONFIG_IBM_NEW_EMAC_TAH=y
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/tqm8540_defconfig b/arch/powerpc/configs/tqm8540_defconfig
+deleted file mode 100644
+index d39ee3b..0000000
+--- a/arch/powerpc/configs/tqm8540_defconfig
++++ /dev/null
+@@ -1,1097 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:43 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-CONFIG_TQM8540=y
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-CONFIG_TQM85xx=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-CONFIG_MTD_CONCAT=y
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-CONFIG_SENSORS_LM75=y
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-CONFIG_HWMON_DEBUG_CHIP=y
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/tqm8541_defconfig b/arch/powerpc/configs/tqm8541_defconfig
+deleted file mode 100644
+index cbf6ad2..0000000
+--- a/arch/powerpc/configs/tqm8541_defconfig
++++ /dev/null
+@@ -1,1109 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:44 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-CONFIG_TQM8541=y
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-CONFIG_TQM85xx=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-CONFIG_MTD_CONCAT=y
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-# CONFIG_FS_ENET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-CONFIG_SENSORS_LM75=y
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-CONFIG_HWMON_DEBUG_CHIP=y
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/tqm8555_defconfig b/arch/powerpc/configs/tqm8555_defconfig
+deleted file mode 100644
+index bbff962..0000000
+--- a/arch/powerpc/configs/tqm8555_defconfig
++++ /dev/null
+@@ -1,1109 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:44 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-CONFIG_TQM8555=y
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-CONFIG_TQM85xx=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-CONFIG_MTD_CONCAT=y
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-# CONFIG_FS_ENET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-CONFIG_SENSORS_LM75=y
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-CONFIG_HWMON_DEBUG_CHIP=y
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/tqm8560_defconfig b/arch/powerpc/configs/tqm8560_defconfig
+deleted file mode 100644
+index 63c5ec8..0000000
+--- a/arch/powerpc/configs/tqm8560_defconfig
++++ /dev/null
+@@ -1,1109 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:45 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-CONFIG_TQM8560=y
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-CONFIG_TQM85xx=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-CONFIG_MTD_CONCAT=y
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-# CONFIG_FS_ENET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-CONFIG_SENSORS_LM75=y
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-CONFIG_HWMON_DEBUG_CHIP=y
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/walnut_defconfig b/arch/powerpc/configs/walnut_defconfig
+deleted file mode 100644
+index 3b2689e..0000000
+--- a/arch/powerpc/configs/walnut_defconfig
++++ /dev/null
+@@ -1,887 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:54:12 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-CONFIG_40x=y
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_EP405 is not set
+-# CONFIG_KILAUEA is not set
+-# CONFIG_MAKALU is not set
+-CONFIG_WALNUT=y
+-# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
+-CONFIG_405GP=y
+-CONFIG_IBM405_ERR77=y
+-CONFIG_IBM405_ERR51=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_OF_RTC=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-# CONFIG_PCI_LEGACY is not set
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# 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=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=m
+-CONFIG_MTD_BLOCK=m
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/warp_defconfig b/arch/powerpc/configs/warp_defconfig
+deleted file mode 100644
+index 2313c3e..0000000
+--- a/arch/powerpc/configs/warp_defconfig
++++ /dev/null
+@@ -1,1110 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:54:43 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION="-pika"
+-# CONFIG_LOCALVERSION_AUTO is not set
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-CONFIG_WARP=y
+-CONFIG_440EP=y
+-CONFIG_IBM440EP_ERR42=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-# CONFIG_HZ_250 is not set
+-# CONFIG_HZ_300 is not set
+-CONFIG_HZ_1000=y
+-CONFIG_HZ=1000
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE="ip=on"
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-# CONFIG_IP_PNP_BOOTP is not set
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IP_VS is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-CONFIG_NETFILTER=y
+-# CONFIG_NETFILTER_DEBUG is not set
+-CONFIG_NETFILTER_ADVANCED=y
+-
+-#
+-# Core Netfilter Configuration
+-#
+-# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+-# CONFIG_NETFILTER_NETLINK_LOG is not set
+-# CONFIG_NF_CONNTRACK is not set
+-# CONFIG_NETFILTER_XTABLES is not set
+-
+-#
+-# IP: Netfilter Configuration
+-#
+-# CONFIG_IP_NF_QUEUE is not set
+-# CONFIG_IP_NF_IPTABLES is not set
+-# CONFIG_IP_NF_ARPTABLES is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-CONFIG_VLAN_8021Q=y
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-# CONFIG_STANDALONE is not set
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-# CONFIG_MTD_CMDLINE_PARTS is not set
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-CONFIG_MTD_OOPS=m
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-CONFIG_MTD_NAND=y
+-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+-CONFIG_MTD_NAND_ECC_SMC=y
+-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+-CONFIG_MTD_NAND_IDS=y
+-# CONFIG_MTD_NAND_DISKONCHIP is not set
+-# CONFIG_MTD_NAND_NANDSIM is not set
+-# CONFIG_MTD_NAND_PLATFORM is not set
+-# CONFIG_MTD_ALAUDA is not set
+-# CONFIG_MTD_NAND_FSL_ELBC is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=4096
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-# CONFIG_SCSI_LOWLEVEL is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-# CONFIG_NETDEV_1000 is not set
+-# CONFIG_NETDEV_10000 is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-# CONFIG_I2C_CHARDEV is not set
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_MPC is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-CONFIG_SENSORS_EEPROM=y
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-# CONFIG_USB_DEVICEFS is not set
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_GADGET is not set
+-CONFIG_MMC=m
+-# CONFIG_MMC_DEBUG is not set
+-# CONFIG_MMC_UNSAFE_RESUME is not set
+-
+-#
+-# MMC/SD Card Drivers
+-#
+-CONFIG_MMC_BLOCK=m
+-CONFIG_MMC_BLOCK_BOUNCE=y
+-# CONFIG_SDIO_UART is not set
+-
+-#
+-# MMC/SD Host Controller Drivers
+-#
+-# CONFIG_MMC_WBSD is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-# CONFIG_TMPFS is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-CONFIG_NLS_CODEPAGE_437=y
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-CONFIG_NLS_CODEPAGE_850=y
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-CONFIG_NLS_ASCII=y
+-CONFIG_NLS_ISO8859_1=y
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-CONFIG_NLS_ISO8859_15=y
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-CONFIG_NLS_UTF8=y
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-CONFIG_CRC_CCITT=y
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-# CONFIG_SCHED_DEBUG is not set
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_DEBUG_SLAB is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-CONFIG_DEBUG_INFO=y
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-CONFIG_BDI_SWITCH=y
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
+index c1baf9d..9177b21 100644
+--- a/arch/powerpc/kernel/Makefile
++++ b/arch/powerpc/kernel/Makefile
+@@ -12,7 +12,7 @@ CFLAGS_prom_init.o      += -fPIC
+ CFLAGS_btext.o		+= -fPIC
+ endif
+ 
+-obj-y				:= semaphore.o cputable.o ptrace.o syscalls.o \
++obj-y				:= cputable.o ptrace.o syscalls.o \
+ 				   irq.o align.o signal_32.o pmc.o vdso.o \
+ 				   init_task.o process.o systbl.o idle.o \
+ 				   signal.o
+@@ -67,6 +67,7 @@ obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
+ obj-$(CONFIG_SMP)		+= smp.o
+ obj-$(CONFIG_KPROBES)		+= kprobes.o
+ obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
++obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
+ 
+ pci64-$(CONFIG_PPC64)		+= pci_dn.o isa-bridge.o
+ obj-$(CONFIG_PCI)		+= pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \
+@@ -105,4 +106,13 @@ PHONY += systbl_chk
+ systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i
+ 	$(call cmd,systbl_chk)
+ 
++$(obj)/built-in.o:		prom_init_check
++
++quiet_cmd_prom_init_check = CALL    $<
++      cmd_prom_init_check = $(CONFIG_SHELL) $< "$(NM)" "$(obj)/prom_init.o"
++
++PHONY += prom_init_check
++prom_init_check: $(src)/prom_init_check.sh $(obj)/prom_init.o
++	$(call cmd,prom_init_check)
++
+ clean-files := vmlinux.lds
+diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
+index 4b749c4..adf1d09 100644
+--- a/arch/powerpc/kernel/asm-offsets.c
++++ b/arch/powerpc/kernel/asm-offsets.c
+@@ -26,8 +26,6 @@
+ #ifdef CONFIG_PPC64
+ #include <linux/time.h>
+ #include <linux/hardirq.h>
+-#else
+-#include <linux/ptrace.h>
+ #endif
+ 
+ #include <asm/io.h>
+@@ -46,6 +44,9 @@
+ #include <asm/mmu.h>
+ #include <asm/hvcall.h>
+ #endif
++#ifdef CONFIG_PPC_ISERIES
++#include <asm/iseries/alpaca.h>
++#endif
+ 
+ #define DEFINE(sym, val) \
+ 	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+@@ -60,7 +61,6 @@ int main(void)
+ 	DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
+ #else
+ 	DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
+-	DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
+ #endif /* CONFIG_PPC64 */
+ 
+ 	DEFINE(KSP, offsetof(struct thread_struct, ksp));
+@@ -80,7 +80,6 @@ int main(void)
+ 	DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
+ #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ 	DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
+-	DEFINE(PT_PTRACED, PT_PTRACED);
+ #endif
+ #ifdef CONFIG_SPE
+ 	DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0]));
+@@ -94,10 +93,7 @@ int main(void)
+ 	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
+ 	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+ 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
+-#ifdef CONFIG_PPC32
+-	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
+ 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+-#endif /* CONFIG_PPC32 */
+ 
+ #ifdef CONFIG_PPC64
+ 	DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size));
+@@ -166,13 +162,9 @@ int main(void)
+ 
+ 	/* Interrupt register frame */
+ 	DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
+-#ifndef CONFIG_PPC64
+-	DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+-#else /* CONFIG_PPC64 */
++	DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
++#ifdef CONFIG_PPC64
+ 	DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+-	/* 288 = # of volatile regs, int & fp, for leaf routines */
+-	/* which do not stack a frame.  See the PPC64 ABI.       */
+-	DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288);
+ 	/* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
+ 	DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
+ 	DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
+@@ -325,6 +317,9 @@ int main(void)
+ 	DEFINE(PAGE_OFFSET_VSID, KERNEL_VSID(PAGE_OFFSET));
+ 	DEFINE(VMALLOC_START_ESID, GET_ESID(VMALLOC_START));
+ 	DEFINE(VMALLOC_START_VSID, KERNEL_VSID(VMALLOC_START));
++
++	/* alpaca */
++	DEFINE(ALPACA_SIZE, sizeof(struct alpaca));
+ #endif
+ 
+ 	DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE);
+diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
+index 80e2eef..9f93777 100644
+--- a/arch/powerpc/kernel/btext.c
++++ b/arch/powerpc/kernel/btext.c
+@@ -7,6 +7,7 @@
+ #include <linux/string.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/sections.h>
+ #include <asm/prom.h>
+@@ -15,7 +16,7 @@
+ #include <asm/mmu.h>
+ #include <asm/pgtable.h>
+ #include <asm/io.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/processor.h>
+ #include <asm/udbg.h>
+ 
+diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S
+index 6250443..e3623e3 100644
+--- a/arch/powerpc/kernel/cpu_setup_44x.S
++++ b/arch/powerpc/kernel/cpu_setup_44x.S
+@@ -3,7 +3,7 @@
+  * Valentine Barshak <vbarshak at ru.mvista.com>
+  * MontaVista Software, Inc (c) 2007
+  *
+- * Based on cpu_setup_6xx code by 
++ * Based on cpu_setup_6xx code by
+  * Benjamin Herrenschmidt <benh at kernel.crashing.org>
+  *
+  * This program is free software; you can redistribute it and/or
+@@ -32,6 +32,8 @@ _GLOBAL(__setup_cpu_440grx)
+ 	bl	__fixup_440A_mcheck
+ 	mtlr	r4
+ 	blr
++_GLOBAL(__setup_cpu_460ex)
++	b	__init_fpu_44x
+ _GLOBAL(__setup_cpu_440gx)
+ _GLOBAL(__setup_cpu_440spe)
+ 	b	__fixup_440A_mcheck
+diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
+index f1ee0b3..72d1d73 100644
+--- a/arch/powerpc/kernel/cpu_setup_6xx.S
++++ b/arch/powerpc/kernel/cpu_setup_6xx.S
+@@ -17,7 +17,13 @@
+ #include <asm/cache.h>
+ 
+ _GLOBAL(__setup_cpu_603)
+-	b	setup_common_caches
++	mflr	r4
++BEGIN_FTR_SECTION
++	bl	__init_fpu_registers
++END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE)
++	bl	setup_common_caches
++	mtlr	r4
++	blr
+ _GLOBAL(__setup_cpu_604)
+ 	mflr	r4
+ 	bl	setup_common_caches
+diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
+index 2a8f5cc..36080d4 100644
+--- a/arch/powerpc/kernel/cputable.c
++++ b/arch/powerpc/kernel/cputable.c
+@@ -36,6 +36,7 @@ extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec);
+ extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
+ extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec);
+ extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_460ex(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);
+@@ -1397,6 +1398,29 @@ static struct cpu_spec __initdata cpu_specs[] = {
+ 		.machine_check		= machine_check_440A,
+ 		.platform		= "ppc440",
+ 	},
++	{ /* 460EX */
++		.pvr_mask		= 0xffff0002,
++		.pvr_value		= 0x13020002,
++		.cpu_name		= "460EX",
++		.cpu_features		= CPU_FTRS_44X,
++		.cpu_user_features	= COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
++		.icache_bsize		= 32,
++		.dcache_bsize		= 32,
++		.cpu_setup		= __setup_cpu_460ex,
++		.machine_check		= machine_check_440A,
++		.platform		= "ppc440",
++	},
++	{ /* 460GT */
++		.pvr_mask		= 0xffff0002,
++		.pvr_value		= 0x13020000,
++		.cpu_name		= "460GT",
++		.cpu_features		= CPU_FTRS_44X,
++		.cpu_user_features	= COMMON_USER_BOOKE,
++		.icache_bsize		= 32,
++		.dcache_bsize		= 32,
++		.machine_check		= machine_check_440A,
++		.platform		= "ppc440",
++	},
+ #endif /* CONFIG_44x */
+ #ifdef CONFIG_FSL_BOOKE
+ #ifdef CONFIG_E200
+@@ -1512,7 +1536,7 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
+ 				*t = *s;
+ 			*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
+ #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
+-			/* ppc64 and booke expect identify_cpu to also call 
++			/* ppc64 and booke expect identify_cpu to also call
+ 			 * setup_cpu for that processor. I will consolidate
+ 			 * that at a later time, for now, just use #ifdef.
+ 			 * we also don't need to PTRRELOC the function pointer
+diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
+index 571132e..eae401d 100644
+--- a/arch/powerpc/kernel/crash.c
++++ b/arch/powerpc/kernel/crash.c
+@@ -24,12 +24,13 @@
+ #include <linux/init.h>
+ #include <linux/irq.h>
+ #include <linux/types.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/machdep.h>
+ #include <asm/kexec.h>
+ #include <asm/kdump.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/firmware.h>
+ #include <asm/smp.h>
+ #include <asm/system.h>
+diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
+index 29ff77c..9ee3c52 100644
+--- a/arch/powerpc/kernel/crash_dump.c
++++ b/arch/powerpc/kernel/crash_dump.c
+@@ -13,8 +13,9 @@
+ 
+ #include <linux/crash_dump.h>
+ #include <linux/bootmem.h>
++#include <linux/lmb.h>
+ #include <asm/kdump.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/firmware.h>
+ #include <asm/uaccess.h>
+ 
+diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
+index 69a91bd..84c8686 100644
+--- a/arch/powerpc/kernel/entry_32.S
++++ b/arch/powerpc/kernel/entry_32.S
+@@ -110,9 +110,9 @@ transfer_to_handler:
+ 	stw	r11,PT_REGS(r12)
+ #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ 	/* Check to see if the dbcr0 register is set up to debug.  Use the
+-	   single-step bit to do this. */
++	   internal debug mode bit to do this. */
+ 	lwz	r12,THREAD_DBCR0(r12)
+-	andis.	r12,r12,DBCR0_IC at h
++	andis.	r12,r12,DBCR0_IDM at h
+ 	beq+	3f
+ 	/* From user and task is ptraced - load up global dbcr0 */
+ 	li	r12,-1			/* clear all pending debug events */
+@@ -120,6 +120,12 @@ transfer_to_handler:
+ 	lis	r11,global_dbcr0 at ha
+ 	tophys(r11,r11)
+ 	addi	r11,r11,global_dbcr0 at l
++#ifdef CONFIG_SMP
++	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
++	lwz	r9,TI_CPU(r9)
++	slwi	r9,r9,3
++	add	r11,r11,r9
++#endif
+ 	lwz	r12,0(r11)
+ 	mtspr	SPRN_DBCR0,r12
+ 	lwz	r12,4(r11)
+@@ -238,10 +244,10 @@ ret_from_syscall:
+ 	stw	r11,_CCR(r1)
+ syscall_exit_cont:
+ #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+-	/* If the process has its own DBCR0 value, load it up.  The single
+-	   step bit tells us that dbcr0 should be loaded. */
++	/* If the process has its own DBCR0 value, load it up.  The internal
++	   debug mode bit tells us that dbcr0 should be loaded. */
+ 	lwz	r0,THREAD+THREAD_DBCR0(r2)
+-	andis.	r10,r0,DBCR0_IC at h
++	andis.	r10,r0,DBCR0_IDM at h
+ 	bnel-	load_dbcr0
+ #endif
+ #ifdef CONFIG_44x
+@@ -666,10 +672,10 @@ user_exc_return:		/* r10 contains MSR_KERNEL here */
+ 
+ restore_user:
+ #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+-	/* Check whether this process has its own DBCR0 value.  The single
+-	   step bit tells us that dbcr0 should be loaded. */
++	/* Check whether this process has its own DBCR0 value.  The internal
++	   debug mode bit tells us that dbcr0 should be loaded. */
+ 	lwz	r0,THREAD+THREAD_DBCR0(r2)
+-	andis.	r10,r0,DBCR0_IC at h
++	andis.	r10,r0,DBCR0_IDM at h
+ 	bnel-	load_dbcr0
+ #endif
+ 
+@@ -879,6 +885,12 @@ load_dbcr0:
+ 	mfspr	r10,SPRN_DBCR0
+ 	lis	r11,global_dbcr0 at ha
+ 	addi	r11,r11,global_dbcr0 at l
++#ifdef CONFIG_SMP
++	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
++	lwz	r9,TI_CPU(r9)
++	slwi	r9,r9,3
++	add	r11,r11,r9
++#endif
+ 	stw	r10,0(r11)
+ 	mtspr	SPRN_DBCR0,r0
+ 	lwz	r10,4(r11)
+@@ -891,7 +903,7 @@ load_dbcr0:
+ 	.section .bss
+ 	.align	4
+ global_dbcr0:
+-	.space	8
++	.space	8*NR_CPUS
+ 	.previous
+ #endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
+ 
+diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
+index 148a354..c0db5b7 100644
+--- a/arch/powerpc/kernel/entry_64.S
++++ b/arch/powerpc/kernel/entry_64.S
+@@ -29,6 +29,8 @@
+ #include <asm/cputable.h>
+ #include <asm/firmware.h>
+ #include <asm/bug.h>
++#include <asm/ptrace.h>
++#include <asm/irqflags.h>
+ 
+ /*
+  * System calls.
+@@ -39,7 +41,7 @@
+ 
+ /* This value is used to mark exception frames on the stack. */
+ exception_marker:
+-	.tc	ID_72656773_68657265[TC],0x7265677368657265
++	.tc	ID_EXC_MARKER[TC],STACK_FRAME_REGS_MARKER
+ 
+ 	.section	".text"
+ 	.align 7
+@@ -88,6 +90,14 @@ system_call_common:
+ 	addi	r9,r1,STACK_FRAME_OVERHEAD
+ 	ld	r11,exception_marker at toc(r2)
+ 	std	r11,-16(r9)		/* "regshere" marker */
++#ifdef CONFIG_TRACE_IRQFLAGS
++	bl	.trace_hardirqs_on
++	REST_GPR(0,r1)
++	REST_4GPRS(3,r1)
++	REST_2GPRS(7,r1)
++	addi	r9,r1,STACK_FRAME_OVERHEAD
++	ld	r12,_MSR(r1)
++#endif /* CONFIG_TRACE_IRQFLAGS */
+ 	li	r10,1
+ 	stb	r10,PACASOFTIRQEN(r13)
+ 	stb	r10,PACAHARDIRQEN(r13)
+@@ -102,7 +112,7 @@ BEGIN_FW_FTR_SECTION
+ 	b	hardware_interrupt_entry
+ 2:
+ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+-#endif
++#endif /* CONFIG_PPC_ISERIES */
+ 	mfmsr	r11
+ 	ori	r11,r11,MSR_EE
+ 	mtmsrd	r11,1
+@@ -504,6 +514,10 @@ BEGIN_FW_FTR_SECTION
+ 
+ 	li	r3,0
+ 	stb	r3,PACASOFTIRQEN(r13)	/* ensure we are soft-disabled */
++#ifdef CONFIG_TRACE_IRQFLAGS
++	bl	.trace_hardirqs_off
++	mfmsr	r10
++#endif
+ 	ori	r10,r10,MSR_EE
+ 	mtmsrd	r10			/* hard-enable again */
+ 	addi	r3,r1,STACK_FRAME_OVERHEAD
+@@ -512,7 +526,7 @@ BEGIN_FW_FTR_SECTION
+ 4:
+ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+ #endif
+-	stb	r5,PACASOFTIRQEN(r13)
++	TRACE_AND_RESTORE_IRQ(r5);
+ 
+ 	/* extract EE bit and use it to restore paca->hard_enabled */
+ 	ld	r3,_MSR(r1)
+@@ -580,6 +594,16 @@ do_work:
+ 	bne	restore
+ 	/* here we are preempting the current task */
+ 1:
++#ifdef CONFIG_TRACE_IRQFLAGS
++	bl	.trace_hardirqs_on
++	/* Note: we just clobbered r10 which used to contain the previous
++	 * MSR before the hard-disabling done by the caller of do_work.
++	 * We don't have that value anymore, but it doesn't matter as
++	 * we will hard-enable unconditionally, we can just reload the
++	 * current MSR into r10
++	 */
++	mfmsr	r10
++#endif /* CONFIG_TRACE_IRQFLAGS */
+ 	li	r0,1
+ 	stb	r0,PACASOFTIRQEN(r13)
+ 	stb	r0,PACAHARDIRQEN(r13)
+diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
+index 0f4fac5..785af9b 100644
+--- a/arch/powerpc/kernel/head_32.S
++++ b/arch/powerpc/kernel/head_32.S
+@@ -30,6 +30,7 @@
+ #include <asm/thread_info.h>
+ #include <asm/ppc_asm.h>
+ #include <asm/asm-offsets.h>
++#include <asm/ptrace.h>
+ 
+ /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
+ #define LOAD_BAT(n, reg, RA, RB)	\
+@@ -268,8 +269,8 @@ __secondary_hold_acknowledge:
+ 	li	r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
+ 	MTMSRD(r10);			/* (except for mach check in rtas) */ \
+ 	stw	r0,GPR0(r11);	\
+-	lis	r10,0x7265;		/* put exception frame marker */ \
+-	addi	r10,r10,0x6773;	\
++	lis	r10,STACK_FRAME_REGS_MARKER at ha; /* exception frame marker */ \
++	addi	r10,r10,STACK_FRAME_REGS_MARKER at l; \
+ 	stw	r10,8(r11);	\
+ 	SAVE_4GPRS(3, r11);	\
+ 	SAVE_2GPRS(7, r11)
+@@ -763,23 +764,6 @@ load_up_altivec:
+ 	b	fast_exception_return
+ 
+ /*
+- * AltiVec unavailable trap from kernel - print a message, but let
+- * the task use AltiVec in the kernel until it returns to user mode.
+- */
+-KernelAltiVec:
+-	lwz	r3,_MSR(r1)
+-	oris	r3,r3,MSR_VEC at h
+-	stw	r3,_MSR(r1)	/* enable use of AltiVec after return */
+-	lis	r3,87f at h
+-	ori	r3,r3,87f at l
+-	mr	r4,r2		/* current */
+-	lwz	r5,_NIP(r1)
+-	bl	printk
+-	b	ret_from_except
+-87:	.string	"AltiVec used in kernel  (task=%p, pc=%x)  \n"
+-	.align	4,0
+-
+-/*
+  * giveup_altivec(tsk)
+  * Disable AltiVec for the task given as the argument,
+  * and save the AltiVec registers in its thread_struct.
+diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
+index ad071a1..b84ec6a 100644
+--- a/arch/powerpc/kernel/head_44x.S
++++ b/arch/powerpc/kernel/head_44x.S
+@@ -211,7 +211,7 @@ skpinv:	addi	r4,r4,1				/* Increment */
+ 	SET_IVOR(12, WatchdogTimer);
+ 	SET_IVOR(13, DataTLBError);
+ 	SET_IVOR(14, InstructionTLBError);
+-	SET_IVOR(15, Debug);
++	SET_IVOR(15, DebugCrit);
+ 
+ 	/* Establish the interrupt vector base */
+ 	lis	r4,interrupt_base at h	/* IVPR only uses the high 16-bits */
+@@ -578,7 +578,7 @@ interrupt_base:
+ 	b	InstructionStorage
+ 
+ 	/* Debug Interrupt */
+-	DEBUG_EXCEPTION
++	DEBUG_CRIT_EXCEPTION
+ 
+ /*
+  * Local functions
+diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
+index d3aee08..215973a 100644
+--- a/arch/powerpc/kernel/head_64.S
++++ b/arch/powerpc/kernel/head_64.S
+@@ -36,8 +36,7 @@
+ #include <asm/firmware.h>
+ #include <asm/page_64.h>
+ #include <asm/exception.h>
+-
+-#define DO_SOFT_DISABLE
++#include <asm/irqflags.h>
+ 
+ /*
+  * We layout physical memory as follows:
+@@ -450,8 +449,8 @@ bad_stack:
+  */
+ fast_exc_return_irq:			/* restores irq state too */
+ 	ld	r3,SOFTE(r1)
++	TRACE_AND_RESTORE_IRQ(r3);
+ 	ld	r12,_MSR(r1)
+-	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
+ 	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
+ 	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
+ 	b	1f
+@@ -621,7 +620,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+ 	mtlr	r10
+ 
+ 	andi.	r10,r12,MSR_RI	/* check for unrecoverable exception */
+-	beq-	unrecov_slb
++	beq-	2f
+ 
+ .machine	push
+ .machine	"power4"
+@@ -643,6 +642,22 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+ 	rfid
+ 	b	.	/* prevent speculative execution */
+ 
++2:
++#ifdef CONFIG_PPC_ISERIES
++BEGIN_FW_FTR_SECTION
++	b	unrecov_slb
++END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
++#endif /* CONFIG_PPC_ISERIES */
++	mfspr	r11,SPRN_SRR0
++	clrrdi	r10,r13,32
++	LOAD_HANDLER(r10,unrecov_slb)
++	mtspr	SPRN_SRR0,r10
++	mfmsr	r10
++	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI
++	mtspr	SPRN_SRR1,r10
++	rfid
++	b	.
++
+ unrecov_slb:
+ 	EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
+ 	DISABLE_INTS
+@@ -808,7 +823,7 @@ _STATIC(load_up_altivec)
+  * Hash table stuff
+  */
+ 	.align	7
+-_GLOBAL(do_hash_page)
++_STATIC(do_hash_page)
+ 	std	r3,_DAR(r1)
+ 	std	r4,_DSISR(r1)
+ 
+@@ -820,6 +835,27 @@ BEGIN_FTR_SECTION
+ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+ 
+ 	/*
++	 * On iSeries, we soft-disable interrupts here, then
++	 * hard-enable interrupts so that the hash_page code can spin on
++	 * the hash_table_lock without problems on a shared processor.
++	 */
++	DISABLE_INTS
++
++	/*
++	 * Currently, trace_hardirqs_off() will be called by DISABLE_INTS
++	 * and will clobber volatile registers when irq tracing is enabled
++	 * so we need to reload them. It may be possible to be smarter here
++	 * and move the irq tracing elsewhere but let's keep it simple for
++	 * now
++	 */
++#ifdef CONFIG_TRACE_IRQFLAGS
++	ld	r3,_DAR(r1)
++	ld	r4,_DSISR(r1)
++	ld	r5,_TRAP(r1)
++	ld	r12,_MSR(r1)
++	clrrdi	r5,r5,4
++#endif /* CONFIG_TRACE_IRQFLAGS */
++	/*
+ 	 * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
+ 	 * accessing a userspace segment (even from the kernel). We assume
+ 	 * kernel addresses always have the high bit set.
+@@ -832,13 +868,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+ 	rlwimi	r4,r5,22+2,31-2,31-2	/* Set _PAGE_EXEC if trap is 0x400 */
+ 
+ 	/*
+-	 * On iSeries, we soft-disable interrupts here, then
+-	 * hard-enable interrupts so that the hash_page code can spin on
+-	 * the hash_table_lock without problems on a shared processor.
+-	 */
+-	DISABLE_INTS
+-
+-	/*
+ 	 * r3 contains the faulting address
+ 	 * r4 contains the required access permissions
+ 	 * r5 contains the trap number
+@@ -848,7 +877,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+ 	bl	.hash_page		/* build HPTE if possible */
+ 	cmpdi	r3,0			/* see if hash_page succeeded */
+ 
+-#ifdef DO_SOFT_DISABLE
+ BEGIN_FW_FTR_SECTION
+ 	/*
+ 	 * If we had interrupts soft-enabled at the point where the
+@@ -860,7 +888,7 @@ BEGIN_FW_FTR_SECTION
+ 	 */
+ 	beq	13f
+ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+-#endif
++
+ BEGIN_FW_FTR_SECTION
+ 	/*
+ 	 * Here we have interrupts hard-disabled, so it is sufficient
+@@ -874,11 +902,12 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
+ 
+ 	/*
+ 	 * hash_page couldn't handle it, set soft interrupt enable back
+-	 * to what it was before the trap.  Note that .local_irq_restore
++	 * to what it was before the trap.  Note that .raw_local_irq_restore
+ 	 * handles any interrupts pending at this point.
+ 	 */
+ 	ld	r3,SOFTE(r1)
+-	bl	.local_irq_restore
++	TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f)
++	bl	.raw_local_irq_restore
+ 	b	11f
+ 
+ /* Here we have a page fault that hash_page can't handle. */
+@@ -1477,6 +1506,10 @@ _INIT_STATIC(start_here_multiplatform)
+ 	addi	r2,r2,0x4000
+ 	add	r2,r2,r26
+ 
++	/* Set initial ptr to current */
++	LOAD_REG_IMMEDIATE(r4, init_task)
++	std	r4,PACACURRENT(r13)
++
+ 	/* Do very early kernel initializations, including initial hash table,
+ 	 * stab and slb setup before we turn on relocation.	*/
+ 
+@@ -1505,10 +1538,6 @@ _INIT_GLOBAL(start_here_common)
+ 	li	r0,0
+ 	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
+ 
+-	/* ptr to current */
+-	LOAD_REG_IMMEDIATE(r4, init_task)
+-	std	r4,PACACURRENT(r13)
+-
+ 	/* Load the TOC */
+ 	ld	r2,PACATOC(r13)
+ 	std	r1,PACAKSAVE(r13)
+diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
+index ba9393f..aefafc6 100644
+--- a/arch/powerpc/kernel/head_booke.h
++++ b/arch/powerpc/kernel/head_booke.h
+@@ -56,8 +56,17 @@
+  * is necessary since the MMU is always on, for Book-E parts, and the stacks
+  * are offset from KERNELBASE.
+  *
++ * There is some space optimization to be had here if desired.  However
++ * to allow for a common kernel with support for debug exceptions either
++ * going to critical or their own debug level we aren't currently
++ * providing configurations that micro-optimize space usage.
+  */
+-#define BOOKE_EXCEPTION_STACK_SIZE	(8192)
++#ifdef CONFIG_44x
++#define NUM_EXCEPTION_LVLS	2
++#else
++#define NUM_EXCEPTION_LVLS	3
++#endif
++#define BOOKE_EXCEPTION_STACK_SIZE	(4096 * NUM_EXCEPTION_LVLS)
+ 
+ /* CRIT_SPRG only used in critical exception handling */
+ #define CRIT_SPRG	SPRN_SPRG2
+@@ -68,7 +77,7 @@
+ #define CRIT_STACK_TOP		(exception_stack_top)
+ 
+ /* only on e200 for now */
+-#define DEBUG_STACK_TOP		(exception_stack_top - 4096)
++#define DEBUG_STACK_TOP		(exception_stack_top - 8192)
+ #define DEBUG_SPRG		SPRN_SPRG6W
+ 
+ #ifdef CONFIG_SMP
+@@ -212,9 +221,8 @@ label:
+  * save (and later restore) the MSR via SPRN_CSRR1, which will still have
+  * the MSR_DE bit set.
+  */
+-#ifdef CONFIG_E200
+-#define DEBUG_EXCEPTION							      \
+-	START_EXCEPTION(Debug);						      \
++#define DEBUG_DEBUG_EXCEPTION						      \
++	START_EXCEPTION(DebugDebug);					      \
+ 	DEBUG_EXCEPTION_PROLOG;						      \
+ 									      \
+ 	/*								      \
+@@ -234,8 +242,8 @@ label:
+ 	cmplw	r12,r10;						      \
+ 	blt+	2f;			/* addr below exception vectors */    \
+ 									      \
+-	lis	r10,Debug at h;						      \
+-	ori	r10,r10,Debug at l;					      \
++	lis	r10,DebugDebug at h;					      \
++	ori	r10,r10,DebugDebug at l;					      \
+ 	cmplw	r12,r10;						      \
+ 	bgt+	2f;			/* addr above exception vectors */    \
+ 									      \
+@@ -265,9 +273,9 @@ label:
+ 2:	mfspr	r4,SPRN_DBSR;						      \
+ 	addi	r3,r1,STACK_FRAME_OVERHEAD;				      \
+ 	EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc)
+-#else
+-#define DEBUG_EXCEPTION							      \
+-	START_EXCEPTION(Debug);						      \
++
++#define DEBUG_CRIT_EXCEPTION						      \
++	START_EXCEPTION(DebugCrit);					      \
+ 	CRITICAL_EXCEPTION_PROLOG;					      \
+ 									      \
+ 	/*								      \
+@@ -287,8 +295,8 @@ label:
+ 	cmplw	r12,r10;						      \
+ 	blt+	2f;			/* addr below exception vectors */    \
+ 									      \
+-	lis	r10,Debug at h;						      \
+-	ori	r10,r10,Debug at l;					      \
++	lis	r10,DebugCrit at h;						      \
++	ori	r10,r10,DebugCrit at l;					      \
+ 	cmplw	r12,r10;						      \
+ 	bgt+	2f;			/* addr above exception vectors */    \
+ 									      \
+@@ -318,7 +326,6 @@ label:
+ 2:	mfspr	r4,SPRN_DBSR;						      \
+ 	addi	r3,r1,STACK_FRAME_OVERHEAD;				      \
+ 	EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+-#endif
+ 
+ #define INSTRUCTION_STORAGE_EXCEPTION					      \
+ 	START_EXCEPTION(InstructionStorage)				      \
+diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
+index d9cc2c2..e581524 100644
+--- a/arch/powerpc/kernel/head_fsl_booke.S
++++ b/arch/powerpc/kernel/head_fsl_booke.S
+@@ -68,7 +68,9 @@ _ENTRY(_start);
+ 	mr	r29,r5
+ 	mr	r28,r6
+ 	mr	r27,r7
++	li	r25,0		/* phys kernel start (low) */
+ 	li	r24,0		/* CPU number */
++	li	r23,0		/* phys kernel start (high) */
+ 
+ /* We try to not make any assumptions about how the boot loader
+  * setup or used the TLBs.  We invalidate all mappings from the
+@@ -167,7 +169,28 @@ skpinv:	addi	r6,r6,1				/* Increment */
+ 	mtspr	SPRN_MAS0,r7
+ 	tlbre
+ 
+-	/* Just modify the entry ID, EPN and RPN for the temp mapping */
++	/* grab and fixup the RPN */
++	mfspr	r6,SPRN_MAS1	/* extract MAS1[SIZE] */
++	rlwinm	r6,r6,25,27,30
++	li	r8,-1
++	addi	r6,r6,10
++	slw	r6,r8,r6	/* convert to mask */
++
++	bl	1f		/* Find our address */
++1:	mflr	r7
++
++	mfspr	r8,SPRN_MAS3
++#ifdef CONFIG_PHYS_64BIT
++	mfspr	r23,SPRN_MAS7
++#endif
++	and	r8,r6,r8
++	subfic	r9,r6,-4096
++	and	r9,r9,r7
++
++	or	r25,r8,r9
++	ori	r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
++
++	/* Just modify the entry ID and EPN for the temp mapping */
+ 	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
+ 	rlwimi	r7,r5,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r5) */
+ 	mtspr	SPRN_MAS0,r7
+@@ -177,12 +200,10 @@ skpinv:	addi	r6,r6,1				/* Increment */
+ 	ori	r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
+ 	mtspr	SPRN_MAS1,r6
+ 	mfspr	r6,SPRN_MAS2
+-	lis	r7,PHYSICAL_START at h
++	li	r7,0		/* temp EPN = 0 */
+ 	rlwimi	r7,r6,0,20,31
+ 	mtspr	SPRN_MAS2,r7
+-	mfspr	r6,SPRN_MAS3
+-	rlwimi	r7,r6,0,20,31
+-	mtspr	SPRN_MAS3,r7
++	mtspr	SPRN_MAS3,r8
+ 	tlbwe
+ 
+ 	xori	r6,r4,1
+@@ -232,8 +253,7 @@ skpinv:	addi	r6,r6,1				/* Increment */
+ 	ori	r6,r6,PAGE_OFFSET at l
+ 	rlwimi	r6,r7,0,20,31
+ 	mtspr	SPRN_MAS2,r6
+-	li	r7,(MAS3_SX|MAS3_SW|MAS3_SR)
+-	mtspr	SPRN_MAS3,r7
++	mtspr	SPRN_MAS3,r8
+ 	tlbwe
+ 
+ /* 7. Jump to KERNELBASE mapping */
+@@ -283,7 +303,10 @@ skpinv:	addi	r6,r6,1				/* Increment */
+ 	SET_IVOR(12, WatchdogTimer);
+ 	SET_IVOR(13, DataTLBError);
+ 	SET_IVOR(14, InstructionTLBError);
+-	SET_IVOR(15, Debug);
++	SET_IVOR(15, DebugDebug);
++#if defined(CONFIG_E500)
++	SET_IVOR(15, DebugCrit);
++#endif
+ 	SET_IVOR(32, SPEUnavailable);
+ 	SET_IVOR(33, SPEFloatingPointData);
+ 	SET_IVOR(34, SPEFloatingPointRound);
+@@ -348,6 +371,17 @@ skpinv:	addi	r6,r6,1				/* Increment */
+ 
+ 	bl	early_init
+ 
++#ifdef CONFIG_RELOCATABLE
++	lis	r3,kernstart_addr at ha
++	la	r3,kernstart_addr at l(r3)
++#ifdef CONFIG_PHYS_64BIT
++	stw	r23,0(r3)
++	stw	r25,4(r3)
++#else
++	stw	r25,0(r3)
++#endif
++#endif
++
+ 	mfspr	r3,SPRN_TLB1CFG
+ 	andi.	r3,r3,0xfff
+ 	lis	r4,num_tlbcam_entries at ha
+@@ -718,7 +752,10 @@ interrupt_base:
+ 
+ 
+ 	/* Debug Interrupt */
+-	DEBUG_EXCEPTION
++	DEBUG_DEBUG_EXCEPTION
++#if defined(CONFIG_E500)
++	DEBUG_CRIT_EXCEPTION
++#endif
+ 
+ /*
+  * Local functions
+diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
+index 2f50bb5..9971159 100644
+--- a/arch/powerpc/kernel/ibmebus.c
++++ b/arch/powerpc/kernel/ibmebus.c
+@@ -183,7 +183,7 @@ static int ibmebus_create_devices(const struct of_device_id *matches)
+ 		ret = ibmebus_create_device(child);
+ 		if (ret) {
+ 			printk(KERN_ERR "%s: failed to create device (%i)",
+-			       __FUNCTION__, ret);
++			       __func__, ret);
+ 			of_node_put(child);
+ 			break;
+ 		}
+@@ -269,7 +269,7 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
+ 	if (bus_find_device(&ibmebus_bus_type, NULL, path,
+ 			    ibmebus_match_path)) {
+ 		printk(KERN_WARNING "%s: %s has already been probed\n",
+-		       __FUNCTION__, path);
++		       __func__, path);
+ 		rc = -EEXIST;
+ 		goto out;
+ 	}
+@@ -279,7 +279,7 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
+ 		of_node_put(dn);
+ 	} else {
+ 		printk(KERN_WARNING "%s: no such device node: %s\n",
+-		       __FUNCTION__, path);
++		       __func__, path);
+ 		rc = -ENODEV;
+ 	}
+ 
+@@ -308,7 +308,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
+ 		return count;
+ 	} else {
+ 		printk(KERN_WARNING "%s: %s not on the bus\n",
+-		       __FUNCTION__, path);
++		       __func__, path);
+ 
+ 		kfree(path);
+ 		return -ENODEV;
+@@ -337,14 +337,14 @@ static int __init ibmebus_bus_init(void)
+ 	err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
+ 	if (err) {
+ 		printk(KERN_ERR "%s: failed to register IBM eBus.\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return err;
+ 	}
+ 
+ 	err = device_register(&ibmebus_bus_device);
+ 	if (err) {
+ 		printk(KERN_WARNING "%s: device_register returned %i\n",
+-		       __FUNCTION__, err);
++		       __func__, err);
+ 		bus_unregister(&ibmebus_bus_type);
+ 
+ 		return err;
+diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
+index 8f1f4e5..0c66366 100644
+--- a/arch/powerpc/kernel/iommu.c
++++ b/arch/powerpc/kernel/iommu.c
+@@ -520,7 +520,7 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
+ 	unsigned int order;
+ 
+ 	if (!tbl || !tbl->it_map) {
+-		printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__,
++		printk(KERN_ERR "%s: expected TCE map for %s\n", __func__,
+ 				node_name);
+ 		return;
+ 	}
+@@ -530,7 +530,7 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
+ 	for (i = 0; i < (tbl->it_size/64); i++) {
+ 		if (tbl->it_map[i] != 0) {
+ 			printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
+-				__FUNCTION__, node_name);
++				__func__, node_name);
+ 			break;
+ 		}
+ 	}
+diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
+index 292163f..425616f 100644
+--- a/arch/powerpc/kernel/irq.c
++++ b/arch/powerpc/kernel/irq.c
+@@ -114,7 +114,7 @@ static inline void set_soft_enabled(unsigned long enable)
+ 	: : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
+ }
+ 
+-void local_irq_restore(unsigned long en)
++void raw_local_irq_restore(unsigned long en)
+ {
+ 	/*
+ 	 * get_paca()->soft_enabled = en;
+@@ -174,6 +174,7 @@ void local_irq_restore(unsigned long en)
+ 
+ 	__hard_irq_enable();
+ }
++EXPORT_SYMBOL(raw_local_irq_restore);
+ #endif /* CONFIG_PPC64 */
+ 
+ int show_interrupts(struct seq_file *p, void *v)
+@@ -310,8 +311,21 @@ void do_IRQ(struct pt_regs *regs)
+ 				handler = &__do_IRQ;
+ 			irqtp->task = curtp->task;
+ 			irqtp->flags = 0;
++
++			/* Copy the softirq bits in preempt_count so that the
++			 * softirq checks work in the hardirq context.
++			 */
++			irqtp->preempt_count =
++				(irqtp->preempt_count & ~SOFTIRQ_MASK) |
++				(curtp->preempt_count & SOFTIRQ_MASK);
++
+ 			call_handle_irq(irq, desc, irqtp, handler);
+ 			irqtp->task = NULL;
++
++
++			/* Set any flag that may have been set on the
++			 * alternate stack
++			 */
+ 			if (irqtp->flags)
+ 				set_bits(irqtp->flags, &curtp->flags);
+ 		} else
+@@ -357,7 +371,7 @@ void irq_ctx_init(void)
+ 		memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
+ 		tp = softirq_ctx[i];
+ 		tp->cpu = i;
+-		tp->preempt_count = SOFTIRQ_OFFSET;
++		tp->preempt_count = 0;
+ 
+ 		memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
+ 		tp = hardirq_ctx[i];
+diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
+index ee172aa..289af34 100644
+--- a/arch/powerpc/kernel/isa-bridge.c
++++ b/arch/powerpc/kernel/isa-bridge.c
+@@ -80,13 +80,13 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
+ 	 *			(size depending on dev->n_addr_cells)
+ 	 *   cell 5:		the size of the range
+ 	 */
+-	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) {
++	if ((range->isa_addr.a_hi & ISA_SPACE_MASK) != ISA_SPACE_IO) {
+ 		range++;
+ 		rlen -= sizeof(struct isa_range);
+ 		if (rlen < sizeof(struct isa_range))
+ 			goto inval_range;
+ 	}
+-	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO)
++	if ((range->isa_addr.a_hi & ISA_SPACE_MASK) != ISA_SPACE_IO)
+ 		goto inval_range;
+ 
+ 	isa_addr = range->isa_addr.a_lo;
+@@ -99,7 +99,7 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
+ 	 */
+ 	if ((pci_addr != 0) || (isa_addr != 0)) {
+ 		printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return;
+ 	}
+ 
+diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
+index dcb89a8..1ffacc6 100644
+--- a/arch/powerpc/kernel/lparcfg.c
++++ b/arch/powerpc/kernel/lparcfg.c
+@@ -226,7 +226,7 @@ static void parse_system_parameter_string(struct seq_file *m)
+ 	unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+ 	if (!local_buffer) {
+ 		printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
+-		       __FILE__, __FUNCTION__, __LINE__);
++		       __FILE__, __func__, __LINE__);
+ 		return;
+ 	}
+ 
+@@ -243,14 +243,14 @@ static void parse_system_parameter_string(struct seq_file *m)
+ 	if (call_status != 0) {
+ 		printk(KERN_INFO
+ 		       "%s %s Error calling get-system-parameter (0x%x)\n",
+-		       __FILE__, __FUNCTION__, call_status);
++		       __FILE__, __func__, call_status);
+ 	} else {
+ 		int splpar_strlen;
+ 		int idx, w_idx;
+ 		char *workbuffer = kzalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+ 		if (!workbuffer) {
+ 			printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
+-			       __FILE__, __FUNCTION__, __LINE__);
++			       __FILE__, __func__, __LINE__);
+ 			kfree(local_buffer);
+ 			return;
+ 		}
+@@ -484,10 +484,10 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
+ 	current_weight = (resource >> 5 * 8) & 0xFF;
+ 
+ 	pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
+-		 __FUNCTION__, current_entitled, current_weight);
++		 __func__, current_entitled, current_weight);
+ 
+ 	pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
+-		 __FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
++		 __func__, *new_entitled_ptr, *new_weight_ptr);
+ 
+ 	retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
+ 				    *new_weight_ptr);
+@@ -502,7 +502,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
+ 		retval = -EINVAL;
+ 	} else {
+ 		printk(KERN_WARNING "%s: received unknown hv return code %ld",
+-		       __FUNCTION__, retval);
++		       __func__, retval);
+ 		retval = -EIO;
+ 	}
+ 
+diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
+index c0c8e8c..2d202f2 100644
+--- a/arch/powerpc/kernel/machine_kexec.c
++++ b/arch/powerpc/kernel/machine_kexec.c
+@@ -12,8 +12,9 @@
+ #include <linux/kexec.h>
+ #include <linux/reboot.h>
+ #include <linux/threads.h>
++#include <linux/lmb.h>
+ #include <asm/machdep.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ 
+ void machine_crash_shutdown(struct pt_regs *regs)
+ {
+diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
+index 9d2c566..92ccc6f 100644
+--- a/arch/powerpc/kernel/misc_32.S
++++ b/arch/powerpc/kernel/misc_32.S
+@@ -152,7 +152,7 @@ _GLOBAL(low_choose_750fx_pll)
+ 	mtspr	SPRN_HID1,r4
+ 
+ 	/* Store new HID1 image */
+-	rlwinm	r6,r1,0,0,18
++	rlwinm	r6,r1,0,0,(31-THREAD_SHIFT)
+ 	lwz	r6,TI_CPU(r6)
+ 	slwi	r6,r6,2
+ 	addis	r6,r6,nap_save_hid1 at ha
+@@ -281,7 +281,7 @@ _GLOBAL(_tlbia)
+ #endif /* CONFIG_SMP */
+ #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
+ #if defined(CONFIG_SMP)
+-	rlwinm	r8,r1,0,0,18
++	rlwinm	r8,r1,0,0,(31-THREAD_SHIFT)
+ 	lwz	r8,TI_CPU(r8)
+ 	oris	r8,r8,10
+ 	mfmsr	r10
+@@ -377,7 +377,7 @@ _GLOBAL(_tlbie)
+ #endif /* CONFIG_SMP */
+ #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
+ #if defined(CONFIG_SMP)
+-	rlwinm	r8,r1,0,0,18
++	rlwinm	r8,r1,0,0,(31-THREAD_SHIFT)
+ 	lwz	r8,TI_CPU(r8)
+ 	oris	r8,r8,11
+ 	mfmsr	r10
+diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
+index a3c491e..942951e 100644
+--- a/arch/powerpc/kernel/misc_64.S
++++ b/arch/powerpc/kernel/misc_64.S
+@@ -27,23 +27,11 @@
+ 
+ 	.text
+ 
+-_GLOBAL(get_msr)
+-	mfmsr	r3
+-	blr
+-
+-_GLOBAL(get_srr0)
+-	mfsrr0  r3
+-	blr
+-
+-_GLOBAL(get_srr1)
+-	mfsrr1  r3
+-	blr
+-
+ #ifdef CONFIG_IRQSTACKS
+ _GLOBAL(call_do_softirq)
+ 	mflr	r0
+ 	std	r0,16(r1)
+-	stdu	r1,THREAD_SIZE-112(r3)
++	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
+ 	mr	r1,r3
+ 	bl	.__do_softirq
+ 	ld	r1,0(r1)
+@@ -56,7 +44,7 @@ _GLOBAL(call_handle_irq)
+ 	mflr	r0
+ 	std	r0,16(r1)
+ 	mtctr	r8
+-	stdu	r1,THREAD_SIZE-112(r5)
++	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
+ 	mr	r1,r5
+ 	bctrl
+ 	ld	r1,0(r1)
+@@ -599,7 +587,7 @@ _GLOBAL(kexec_sequence)
+ 	std	r0,16(r1)
+ 
+ 	/* switch stacks to newstack -- &kexec_stack.stack */
+-	stdu	r1,THREAD_SIZE-112(r3)
++	stdu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
+ 	mr	r1,r3
+ 
+ 	li	r0,0
+@@ -616,7 +604,7 @@ _GLOBAL(kexec_sequence)
+ 	std	r26,-48(r1)
+ 	std	r25,-56(r1)
+ 
+-	stdu	r1,-112-64(r1)
++	stdu	r1,-STACK_FRAME_OVERHEAD-64(r1)
+ 
+ 	/* save args into preserved regs */
+ 	mr	r31,r3			/* newstack (both) */
+diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
+index fb698d4..e79ad8a 100644
+--- a/arch/powerpc/kernel/of_platform.c
++++ b/arch/powerpc/kernel/of_platform.c
+@@ -275,6 +275,8 @@ static int __devinit of_pci_phb_probe(struct of_device *dev,
+ 
+ 	/* Scan the bus */
+ 	scan_phb(phb);
++	if (phb->bus == NULL)
++		return -ENXIO;
+ 
+ 	/* Claim resources. This might need some rework as well depending
+ 	 * wether we are doing probe-only or not, like assigning unassigned
+diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
+index 55f1a25..c9bf17e 100644
+--- a/arch/powerpc/kernel/paca.c
++++ b/arch/powerpc/kernel/paca.c
+@@ -7,31 +7,24 @@
+  *      2 of the License, or (at your option) any later version.
+  */
+ 
+-#include <linux/types.h>
+ #include <linux/threads.h>
+ #include <linux/module.h>
+ 
+-#include <asm/processor.h>
+-#include <asm/ptrace.h>
+-#include <asm/page.h>
+ #include <asm/lppaca.h>
+-#include <asm/iseries/it_lp_reg_save.h>
+ #include <asm/paca.h>
+-#include <asm/mmu.h>
+-
+ 
+ /* This symbol is provided by the linker - let it fill in the paca
+  * field correctly */
+ extern unsigned long __toc_start;
+ 
+ /*
+- * iSeries structure which the hypervisor knows about - this structure
++ * 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
+- * boundary.  The lppaca is also used on POWER5 pSeries boxes.  The
+- * lppaca is 640 bytes long, and cannot readily change since the
+- * hypervisor knows its layout, so a 1kB alignment will suffice to
+- * ensure that it doesn't cross a page boundary.
++ * boundary.  The lppaca is also used on legacy iSeries and POWER5
++ * pSeries boxes.  The lppaca is 640 bytes long, and cannot readily
++ * change since the hypervisor knows its layout, so a 1kB alignment
++ * will suffice to ensure that it doesn't cross a page boundary.
+  */
+ struct lppaca lppaca[] = {
+ 	[0 ... (NR_CPUS-1)] = {
+@@ -66,75 +59,29 @@ struct slb_shadow slb_shadow[] __cacheline_aligned = {
+  * processors.  The processor VPD array needs one entry per physical
+  * processor (not thread).
+  */
+-#define PACA_INIT_COMMON(number)					    \
+-	.lppaca_ptr = &lppaca[number],					    \
+-	.lock_token = 0x8000,						    \
+-	.paca_index = (number),		/* Paca Index */		    \
+-	.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL,		    \
+-	.hw_cpu_id = 0xffff,						    \
+-	.slb_shadow_ptr = &slb_shadow[number],
++struct paca_struct paca[NR_CPUS];
++EXPORT_SYMBOL(paca);
+ 
+-#ifdef CONFIG_PPC_ISERIES
+-#define PACA_INIT_ISERIES(number)					    \
+-	.reg_save_ptr = &iseries_reg_save[number],
++void __init initialise_pacas(void)
++{
++	int cpu;
+ 
+-#define PACA_INIT(number)						    \
+-{									    \
+-	PACA_INIT_COMMON(number)					    \
+-	PACA_INIT_ISERIES(number)					    \
+-}
++	/* The TOC register (GPR2) points 32kB into the TOC, so that 64kB
++	 * of the TOC can be addressed using a single machine instruction.
++	 */
++	unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL;
+ 
+-#else
+-#define PACA_INIT(number)						    \
+-{									    \
+-	PACA_INIT_COMMON(number)					    \
+-}
++	/* Can't use for_each_*_cpu, as they aren't functional yet */
++	for (cpu = 0; cpu < NR_CPUS; cpu++) {
++		struct paca_struct *new_paca = &paca[cpu];
+ 
+-#endif
++		new_paca->lppaca_ptr = &lppaca[cpu];
++		new_paca->lock_token = 0x8000;
++		new_paca->paca_index = cpu;
++		new_paca->kernel_toc = kernel_toc;
++		new_paca->hw_cpu_id = 0xffff;
++		new_paca->slb_shadow_ptr = &slb_shadow[cpu];
++		new_paca->__current = &init_task;
+ 
+-struct paca_struct paca[] = {
+-	PACA_INIT(0),
+-#if NR_CPUS > 1
+-	PACA_INIT(  1), PACA_INIT(  2), PACA_INIT(  3),
+-#if NR_CPUS > 4
+-	PACA_INIT(  4), PACA_INIT(  5), PACA_INIT(  6), PACA_INIT(  7),
+-#if NR_CPUS > 8
+-	PACA_INIT(  8), PACA_INIT(  9), PACA_INIT( 10), PACA_INIT( 11),
+-	PACA_INIT( 12), PACA_INIT( 13), PACA_INIT( 14), PACA_INIT( 15),
+-	PACA_INIT( 16), PACA_INIT( 17), PACA_INIT( 18), PACA_INIT( 19),
+-	PACA_INIT( 20), PACA_INIT( 21), PACA_INIT( 22), PACA_INIT( 23),
+-	PACA_INIT( 24), PACA_INIT( 25), PACA_INIT( 26), PACA_INIT( 27),
+-	PACA_INIT( 28), PACA_INIT( 29), PACA_INIT( 30), PACA_INIT( 31),
+-#if NR_CPUS > 32
+-	PACA_INIT( 32), PACA_INIT( 33), PACA_INIT( 34), PACA_INIT( 35),
+-	PACA_INIT( 36), PACA_INIT( 37), PACA_INIT( 38), PACA_INIT( 39),
+-	PACA_INIT( 40), PACA_INIT( 41), PACA_INIT( 42), PACA_INIT( 43),
+-	PACA_INIT( 44), PACA_INIT( 45), PACA_INIT( 46), PACA_INIT( 47),
+-	PACA_INIT( 48), PACA_INIT( 49), PACA_INIT( 50), PACA_INIT( 51),
+-	PACA_INIT( 52), PACA_INIT( 53), PACA_INIT( 54), PACA_INIT( 55),
+-	PACA_INIT( 56), PACA_INIT( 57), PACA_INIT( 58), PACA_INIT( 59),
+-	PACA_INIT( 60), PACA_INIT( 61), PACA_INIT( 62), PACA_INIT( 63),
+-#if NR_CPUS > 64
+-	PACA_INIT( 64), PACA_INIT( 65), PACA_INIT( 66), PACA_INIT( 67),
+-	PACA_INIT( 68), PACA_INIT( 69), PACA_INIT( 70), PACA_INIT( 71),
+-	PACA_INIT( 72), PACA_INIT( 73), PACA_INIT( 74), PACA_INIT( 75),
+-	PACA_INIT( 76), PACA_INIT( 77), PACA_INIT( 78), PACA_INIT( 79),
+-	PACA_INIT( 80), PACA_INIT( 81), PACA_INIT( 82), PACA_INIT( 83),
+-	PACA_INIT( 84), PACA_INIT( 85), PACA_INIT( 86), PACA_INIT( 87),
+-	PACA_INIT( 88), PACA_INIT( 89), PACA_INIT( 90), PACA_INIT( 91),
+-	PACA_INIT( 92), PACA_INIT( 93), PACA_INIT( 94), PACA_INIT( 95),
+-	PACA_INIT( 96), PACA_INIT( 97), PACA_INIT( 98), PACA_INIT( 99),
+-	PACA_INIT(100), PACA_INIT(101), PACA_INIT(102), PACA_INIT(103),
+-	PACA_INIT(104), PACA_INIT(105), PACA_INIT(106), PACA_INIT(107),
+-	PACA_INIT(108), PACA_INIT(109), PACA_INIT(110), PACA_INIT(111),
+-	PACA_INIT(112), PACA_INIT(113), PACA_INIT(114), PACA_INIT(115),
+-	PACA_INIT(116), PACA_INIT(117), PACA_INIT(118), PACA_INIT(119),
+-	PACA_INIT(120), PACA_INIT(121), PACA_INIT(122), PACA_INIT(123),
+-	PACA_INIT(124), PACA_INIT(125), PACA_INIT(126), PACA_INIT(127),
+-#endif
+-#endif
+-#endif
+-#endif
+-#endif
+-};
+-EXPORT_SYMBOL(paca);
++	}
++}
+diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
+index 89c83cc..063cdd4 100644
+--- a/arch/powerpc/kernel/pci-common.c
++++ b/arch/powerpc/kernel/pci-common.c
+@@ -1161,41 +1161,9 @@ EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
+ 
+ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+-	u16 cmd, old_cmd;
+-	int idx;
+-	struct resource *r;
+-
+ 	if (ppc_md.pcibios_enable_device_hook)
+ 		if (ppc_md.pcibios_enable_device_hook(dev))
+ 			return -EINVAL;
+ 
+-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+-	old_cmd = cmd;
+-	for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+-		/* Only set up the requested stuff */
+-		if (!(mask & (1 << idx)))
+-			continue;
+-		r = &dev->resource[idx];
+-		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+-			continue;
+-		if ((idx == PCI_ROM_RESOURCE) &&
+-				(!(r->flags & IORESOURCE_ROM_ENABLE)))
+-			continue;
+-		if (r->parent == NULL) {
+-			printk(KERN_ERR "PCI: Device %s not available because"
+-			       " of resource collisions\n", pci_name(dev));
+-			return -EINVAL;
+-		}
+-		if (r->flags & IORESOURCE_IO)
+-			cmd |= PCI_COMMAND_IO;
+-		if (r->flags & IORESOURCE_MEM)
+-			cmd |= PCI_COMMAND_MEMORY;
+-	}
+-	if (cmd != old_cmd) {
+-		printk("PCI: Enabling device %s (%04x -> %04x)\n",
+-		       pci_name(dev), old_cmd, cmd);
+-		pci_write_config_word(dev, PCI_COMMAND, cmd);
+-	}
+-	return 0;
++	return pci_enable_resources(dev, mask);
+ }
+-
+diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
+index 9c98424..09fcb50 100644
+--- a/arch/powerpc/kernel/ppc_ksyms.c
++++ b/arch/powerpc/kernel/ppc_ksyms.c
+@@ -15,7 +15,6 @@
+ #include <linux/bitops.h>
+ 
+ #include <asm/page.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/cacheflush.h>
+ #include <asm/uaccess.h>
+@@ -45,10 +44,6 @@
+ #include <asm/signal.h>
+ #include <asm/dcr.h>
+ 
+-#ifdef CONFIG_PPC64
+-EXPORT_SYMBOL(local_irq_restore);
+-#endif
+-
+ #ifdef CONFIG_PPC32
+ extern void transfer_to_handler(void);
+ extern void do_IRQ(struct pt_regs *regs);
+@@ -58,7 +53,6 @@ extern void program_check_exception(struct pt_regs *regs);
+ extern void single_step_exception(struct pt_regs *regs);
+ extern int sys_sigreturn(struct pt_regs *regs);
+ 
+-EXPORT_SYMBOL(empty_zero_page);
+ EXPORT_SYMBOL(clear_pages);
+ EXPORT_SYMBOL(copy_page);
+ EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
+@@ -79,6 +73,7 @@ EXPORT_SYMBOL(strncpy);
+ EXPORT_SYMBOL(strcat);
+ EXPORT_SYMBOL(strlen);
+ EXPORT_SYMBOL(strcmp);
++EXPORT_SYMBOL(strncmp);
+ 
+ EXPORT_SYMBOL(csum_partial);
+ EXPORT_SYMBOL(csum_partial_copy_generic);
+@@ -192,3 +187,4 @@ EXPORT_SYMBOL(intercept_table);
+ EXPORT_SYMBOL(__mtdcr);
+ EXPORT_SYMBOL(__mfdcr);
+ #endif
++EXPORT_SYMBOL(empty_zero_page);
+diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
+index 4ec6055..6caad17 100644
+--- a/arch/powerpc/kernel/process.c
++++ b/arch/powerpc/kernel/process.c
+@@ -868,11 +868,6 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+ 	flush_spe_to_thread(current);
+ 	error = do_execve(filename, (char __user * __user *) a1,
+ 			  (char __user * __user *) a2, regs);
+-	if (error == 0) {
+-		task_lock(current);
+-		current->ptrace &= ~PT_DTRACE;
+-		task_unlock(current);
+-	}
+ 	putname(filename);
+ out:
+ 	return error;
+@@ -919,20 +914,6 @@ int validate_sp(unsigned long sp, struct task_struct *p,
+ 	return valid_irq_stack(sp, p, nbytes);
+ }
+ 
+-#ifdef CONFIG_PPC64
+-#define MIN_STACK_FRAME	112	/* same as STACK_FRAME_OVERHEAD, in fact */
+-#define FRAME_LR_SAVE	2
+-#define INT_FRAME_SIZE	(sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD + 288)
+-#define REGS_MARKER	0x7265677368657265ul
+-#define FRAME_MARKER	12
+-#else
+-#define MIN_STACK_FRAME	16
+-#define FRAME_LR_SAVE	1
+-#define INT_FRAME_SIZE	(sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
+-#define REGS_MARKER	0x72656773ul
+-#define FRAME_MARKER	2
+-#endif
+-
+ EXPORT_SYMBOL(validate_sp);
+ 
+ unsigned long get_wchan(struct task_struct *p)
+@@ -944,15 +925,15 @@ unsigned long get_wchan(struct task_struct *p)
+ 		return 0;
+ 
+ 	sp = p->thread.ksp;
+-	if (!validate_sp(sp, p, MIN_STACK_FRAME))
++	if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD))
+ 		return 0;
+ 
+ 	do {
+ 		sp = *(unsigned long *)sp;
+-		if (!validate_sp(sp, p, MIN_STACK_FRAME))
++		if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD))
+ 			return 0;
+ 		if (count > 0) {
+-			ip = ((unsigned long *)sp)[FRAME_LR_SAVE];
++			ip = ((unsigned long *)sp)[STACK_FRAME_LR_SAVE];
+ 			if (!in_sched_functions(ip))
+ 				return ip;
+ 		}
+@@ -981,12 +962,12 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
+ 	lr = 0;
+ 	printk("Call Trace:\n");
+ 	do {
+-		if (!validate_sp(sp, tsk, MIN_STACK_FRAME))
++		if (!validate_sp(sp, tsk, STACK_FRAME_OVERHEAD))
+ 			return;
+ 
+ 		stack = (unsigned long *) sp;
+ 		newsp = stack[0];
+-		ip = stack[FRAME_LR_SAVE];
++		ip = stack[STACK_FRAME_LR_SAVE];
+ 		if (!firstframe || ip != lr) {
+ 			printk("["REG"] ["REG"] ", sp, ip);
+ 			print_symbol("%s", ip);
+@@ -1000,8 +981,8 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
+ 		 * See if this is an exception frame.
+ 		 * We look for the "regshere" marker in the current frame.
+ 		 */
+-		if (validate_sp(sp, tsk, INT_FRAME_SIZE)
+-		    && stack[FRAME_MARKER] == REGS_MARKER) {
++		if (validate_sp(sp, tsk, STACK_INT_FRAME_SIZE)
++		    && stack[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) {
+ 			struct pt_regs *regs = (struct pt_regs *)
+ 				(sp + STACK_FRAME_OVERHEAD);
+ 			printk("--- Exception: %lx", regs->trap);
+@@ -1052,3 +1033,34 @@ void ppc64_runlatch_off(void)
+ 	}
+ }
+ #endif
++
++#if THREAD_SHIFT < PAGE_SHIFT
++
++static struct kmem_cache *thread_info_cache;
++
++struct thread_info *alloc_thread_info(struct task_struct *tsk)
++{
++	struct thread_info *ti;
++
++	ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
++	if (unlikely(ti == NULL))
++		return NULL;
++#ifdef CONFIG_DEBUG_STACK_USAGE
++	memset(ti, 0, THREAD_SIZE);
++#endif
++	return ti;
++}
++
++void free_thread_info(struct thread_info *ti)
++{
++	kmem_cache_free(thread_info_cache, ti);
++}
++
++void thread_info_cache_init(void)
++{
++	thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
++					      THREAD_SIZE, 0, NULL);
++	BUG_ON(thread_info_cache == NULL);
++}
++
++#endif /* THREAD_SHIFT < PAGE_SHIFT */
+diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
+index eac97f4..2aefe2a 100644
+--- a/arch/powerpc/kernel/prom.c
++++ b/arch/powerpc/kernel/prom.c
+@@ -31,10 +31,10 @@
+ #include <linux/kexec.h>
+ #include <linux/debugfs.h>
+ #include <linux/irq.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/prom.h>
+ #include <asm/rtas.h>
+-#include <asm/lmb.h>
+ #include <asm/page.h>
+ #include <asm/processor.h>
+ #include <asm/irq.h>
+@@ -51,7 +51,9 @@
+ #include <asm/machdep.h>
+ #include <asm/pSeries_reconfig.h>
+ #include <asm/pci-bridge.h>
++#include <asm/phyp_dump.h>
+ #include <asm/kexec.h>
++#include <mm/mmu_decl.h>
+ 
+ #ifdef DEBUG
+ #define DBG(fmt...) printk(KERN_ERR fmt)
+@@ -436,7 +438,7 @@ early_param("mem", early_parse_mem);
+  * The device tree may be allocated beyond our memory limit, or inside the
+  * crash kernel region for kdump. If so, move it out of the way.
+  */
+-static void move_device_tree(void)
++static void __init move_device_tree(void)
+ {
+ 	unsigned long start, size;
+ 	void *p;
+@@ -977,7 +979,10 @@ static int __init early_init_dt_scan_memory(unsigned long node,
+ 		}
+ #endif
+ 		lmb_add(base, size);
++
++		memstart_addr = min((u64)memstart_addr, base);
+ 	}
++
+ 	return 0;
+ }
+ 
+@@ -1040,6 +1045,87 @@ static void __init early_reserve_mem(void)
+ #endif
+ }
+ 
++#ifdef CONFIG_PHYP_DUMP
++/**
++ * phyp_dump_calculate_reserve_size() - reserve variable boot area 5% or arg
++ *
++ * Function to find the largest size we need to reserve
++ * during early boot process.
++ *
++ * It either looks for boot param and returns that OR
++ * returns larger of 256 or 5% rounded down to multiples of 256MB.
++ *
++ */
++static inline unsigned long phyp_dump_calculate_reserve_size(void)
++{
++	unsigned long tmp;
++
++	if (phyp_dump_info->reserve_bootvar)
++		return phyp_dump_info->reserve_bootvar;
++
++	/* divide by 20 to get 5% of value */
++	tmp = lmb_end_of_DRAM();
++	do_div(tmp, 20);
++
++	/* round it down in multiples of 256 */
++	tmp = tmp & ~0x0FFFFFFFUL;
++
++	return (tmp > PHYP_DUMP_RMR_END ? tmp : PHYP_DUMP_RMR_END);
++}
++
++/**
++ * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory
++ *
++ * This routine may reserve memory regions in the kernel only
++ * if the system is supported and a dump was taken in last
++ * boot instance or if the hardware is supported and the
++ * scratch area needs to be setup. In other instances it returns
++ * without reserving anything. The memory in case of dump being
++ * active is freed when the dump is collected (by userland tools).
++ */
++static void __init phyp_dump_reserve_mem(void)
++{
++	unsigned long base, size;
++	unsigned long variable_reserve_size;
++
++	if (!phyp_dump_info->phyp_dump_configured) {
++		printk(KERN_ERR "Phyp-dump not supported on this hardware\n");
++		return;
++	}
++
++	if (!phyp_dump_info->phyp_dump_at_boot) {
++		printk(KERN_INFO "Phyp-dump disabled at boot time\n");
++		return;
++	}
++
++	variable_reserve_size = phyp_dump_calculate_reserve_size();
++
++	if (phyp_dump_info->phyp_dump_is_active) {
++		/* Reserve *everything* above RMR.Area freed by userland tools*/
++		base = variable_reserve_size;
++		size = lmb_end_of_DRAM() - base;
++
++		/* XXX crashed_ram_end is wrong, since it may be beyond
++		 * the memory_limit, it will need to be adjusted. */
++		lmb_reserve(base, size);
++
++		phyp_dump_info->init_reserve_start = base;
++		phyp_dump_info->init_reserve_size = size;
++	} else {
++		size = phyp_dump_info->cpu_state_size +
++			phyp_dump_info->hpte_region_size +
++			variable_reserve_size;
++		base = lmb_end_of_DRAM() - size;
++		lmb_reserve(base, size);
++		phyp_dump_info->init_reserve_start = base;
++		phyp_dump_info->init_reserve_size = size;
++	}
++}
++#else
++static inline void __init phyp_dump_reserve_mem(void) {}
++#endif /* CONFIG_PHYP_DUMP  && CONFIG_PPC_RTAS */
++
++
+ void __init early_init_devtree(void *params)
+ {
+ 	DBG(" -> early_init_devtree(%p)\n", params);
+@@ -1052,6 +1138,11 @@ void __init early_init_devtree(void *params)
+ 	of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
+ #endif
+ 
++#ifdef CONFIG_PHYP_DUMP
++	/* scan tree to see if dump occured during last boot */
++	of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
++#endif
++
+ 	/* Retrieve various informations from the /chosen node of the
+ 	 * device-tree, including the platform type, initrd location and
+ 	 * size, TCE reserve, and more ...
+@@ -1072,6 +1163,7 @@ void __init early_init_devtree(void *params)
+ 	reserve_kdump_trampoline();
+ 	reserve_crashkernel();
+ 	early_reserve_mem();
++	phyp_dump_reserve_mem();
+ 
+ 	lmb_enforce_memory_limit(memory_limit);
+ 	lmb_analyze();
+@@ -1244,12 +1336,14 @@ EXPORT_SYMBOL(of_node_put);
+  */
+ void of_attach_node(struct device_node *np)
+ {
+-	write_lock(&devtree_lock);
++	unsigned long flags;
++
++	write_lock_irqsave(&devtree_lock, flags);
+ 	np->sibling = np->parent->child;
+ 	np->allnext = allnodes;
+ 	np->parent->child = np;
+ 	allnodes = np;
+-	write_unlock(&devtree_lock);
++	write_unlock_irqrestore(&devtree_lock, flags);
+ }
+ 
+ /*
+@@ -1260,8 +1354,9 @@ void of_attach_node(struct device_node *np)
+ void of_detach_node(struct device_node *np)
+ {
+ 	struct device_node *parent;
++	unsigned long flags;
+ 
+-	write_lock(&devtree_lock);
++	write_lock_irqsave(&devtree_lock, flags);
+ 
+ 	parent = np->parent;
+ 	if (!parent)
+@@ -1292,7 +1387,7 @@ void of_detach_node(struct device_node *np)
+ 	of_node_set_flag(np, OF_DETACHED);
+ 
+ out_unlock:
+-	write_unlock(&devtree_lock);
++	write_unlock_irqrestore(&devtree_lock, flags);
+ }
+ 
+ #ifdef CONFIG_PPC_PSERIES
+@@ -1373,20 +1468,21 @@ __initcall(prom_reconfig_setup);
+ int prom_add_property(struct device_node* np, struct property* prop)
+ {
+ 	struct property **next;
++	unsigned long flags;
+ 
+ 	prop->next = NULL;	
+-	write_lock(&devtree_lock);
++	write_lock_irqsave(&devtree_lock, flags);
+ 	next = &np->properties;
+ 	while (*next) {
+ 		if (strcmp(prop->name, (*next)->name) == 0) {
+ 			/* duplicate ! don't insert it */
+-			write_unlock(&devtree_lock);
++			write_unlock_irqrestore(&devtree_lock, flags);
+ 			return -1;
+ 		}
+ 		next = &(*next)->next;
+ 	}
+ 	*next = prop;
+-	write_unlock(&devtree_lock);
++	write_unlock_irqrestore(&devtree_lock, flags);
+ 
+ #ifdef CONFIG_PROC_DEVICETREE
+ 	/* try to add to proc as well if it was initialized */
+@@ -1406,9 +1502,10 @@ int prom_add_property(struct device_node* np, struct property* prop)
+ int prom_remove_property(struct device_node *np, struct property *prop)
+ {
+ 	struct property **next;
++	unsigned long flags;
+ 	int found = 0;
+ 
+-	write_lock(&devtree_lock);
++	write_lock_irqsave(&devtree_lock, flags);
+ 	next = &np->properties;
+ 	while (*next) {
+ 		if (*next == prop) {
+@@ -1421,7 +1518,7 @@ int prom_remove_property(struct device_node *np, struct property *prop)
+ 		}
+ 		next = &(*next)->next;
+ 	}
+-	write_unlock(&devtree_lock);
++	write_unlock_irqrestore(&devtree_lock, flags);
+ 
+ 	if (!found)
+ 		return -ENODEV;
+@@ -1447,9 +1544,10 @@ int prom_update_property(struct device_node *np,
+ 			 struct property *oldprop)
+ {
+ 	struct property **next;
++	unsigned long flags;
+ 	int found = 0;
+ 
+-	write_lock(&devtree_lock);
++	write_lock_irqsave(&devtree_lock, flags);
+ 	next = &np->properties;
+ 	while (*next) {
+ 		if (*next == oldprop) {
+@@ -1463,7 +1561,7 @@ int prom_update_property(struct device_node *np,
+ 		}
+ 		next = &(*next)->next;
+ 	}
+-	write_unlock(&devtree_lock);
++	write_unlock_irqrestore(&devtree_lock, flags);
+ 
+ 	if (!found)
+ 		return -ENODEV;
+diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
+index 5ab4c84..6d6df1e 100644
+--- a/arch/powerpc/kernel/prom_init.c
++++ b/arch/powerpc/kernel/prom_init.c
+@@ -2240,6 +2240,14 @@ static void __init fixup_device_tree_efika(void)
+ 	if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
+ 		prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
+ 
++	/* CODEGEN,description is exposed in /proc/cpuinfo so
++	   fix that too */
++	rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
++	if (rv != PROM_ERROR && (strstr(prop, "CHRP")))
++		prom_setprop(node, "/", "CODEGEN,description",
++			     "Efika 5200B PowerPC System",
++			     sizeof("Efika 5200B PowerPC System"));
++
+ 	/* Fixup bestcomm interrupts property */
+ 	node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
+ 	if (PHANDLE_VALID(node)) {
+diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
+new file mode 100644
+index 0000000..8e24fc1
+--- /dev/null
++++ b/arch/powerpc/kernel/prom_init_check.sh
+@@ -0,0 +1,58 @@
++#!/bin/sh
++#
++# Copyright © 2008 IBM Corporation
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License
++# as published by the Free Software Foundation; either version
++# 2 of the License, or (at your option) any later version.
++
++# This script checks prom_init.o to see what external symbols it
++# is using, if it finds symbols not in the whitelist it returns
++# an error. The point of this is to discourage people from
++# intentionally or accidentally adding new code to prom_init.c
++# which has side effects on other parts of the kernel.
++
++# If you really need to reference something from prom_init.o add
++# it to the list below:
++
++WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush
++_end enter_prom memcpy memset reloc_offset __secondary_hold
++__secondary_hold_acknowledge __secondary_hold_spinloop __start
++strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
++reloc_got2"
++
++NM="$1"
++OBJ="$2"
++
++ERROR=0
++
++for UNDEF in $($NM -u $OBJ | awk '{print $2}')
++do
++	# On 64-bit nm gives us the function descriptors, which have
++	# a leading . on the name, so strip it off here.
++	UNDEF="${UNDEF#.}"
++
++	if [ $KBUILD_VERBOSE ]; then
++		if [ $KBUILD_VERBOSE -ne 0 ]; then
++			echo "Checking prom_init.o symbol '$UNDEF'"
++		fi
++	fi
++
++	OK=0
++	for WHITE in $WHITELIST
++	do
++		if [ "$UNDEF" = "$WHITE" ]; then
++			OK=1
++			break
++		fi
++	done
++
++	if [ $OK -eq 0 ]; then
++		ERROR=1
++		echo "Error: External symbol '$UNDEF' referenced" \
++		     "from prom_init.c" >&2
++	fi
++done
++
++exit $ERROR
+diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
+index 52e95c2..34843c3 100644
+--- a/arch/powerpc/kernel/rtas.c
++++ b/arch/powerpc/kernel/rtas.c
+@@ -22,11 +22,11 @@
+ #include <linux/smp.h>
+ #include <linux/completion.h>
+ #include <linux/cpumask.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/prom.h>
+ #include <asm/rtas.h>
+ #include <asm/hvcall.h>
+-#include <asm/semaphore.h>
+ #include <asm/machdep.h>
+ #include <asm/firmware.h>
+ #include <asm/page.h>
+@@ -34,7 +34,6 @@
+ #include <asm/system.h>
+ #include <asm/delay.h>
+ #include <asm/uaccess.h>
+-#include <asm/lmb.h>
+ #include <asm/udbg.h>
+ #include <asm/syscalls.h>
+ #include <asm/smp.h>
+@@ -507,7 +506,7 @@ int rtas_error_rc(int rtas_rc)
+ 			break;
+ 		default:
+ 			printk(KERN_ERR "%s: unexpected RTAS error %d\n",
+-					__FUNCTION__, rtas_rc);
++					__func__, rtas_rc);
+ 			rc = -ERANGE;
+ 			break;
+ 	}
+diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
+index 538baf4..627f126 100644
+--- a/arch/powerpc/kernel/rtas_flash.c
++++ b/arch/powerpc/kernel/rtas_flash.c
+@@ -807,7 +807,7 @@ int __init rtas_flash_init(void)
+ 				rtas_block_ctor);
+ 	if (!flash_block_cache) {
+ 		printk(KERN_ERR "%s: failed to create block cache\n",
+-				__FUNCTION__);
++				__func__);
+ 		rc = -ENOMEM;
+ 		goto cleanup;
+ 	}
+diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
+index 433a0a0..3ab88a9 100644
+--- a/arch/powerpc/kernel/rtas_pci.c
++++ b/arch/powerpc/kernel/rtas_pci.c
+@@ -56,21 +56,6 @@ static inline int config_access_valid(struct pci_dn *dn, int where)
+ 	return 0;
+ }
+ 
+-static int of_device_available(struct device_node * dn)
+-{
+-        const char *status;
+-
+-        status = of_get_property(dn, "status", NULL);
+-
+-        if (!status)
+-                return 1;
+-
+-        if (!strcmp(status, "okay"))
+-                return 1;
+-
+-        return 0;
+-}
+-
+ int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
+ {
+ 	int returnval = -1;
+@@ -117,7 +102,7 @@ static int rtas_pci_read_config(struct pci_bus *bus,
+ 	for (dn = busdn->child; dn; dn = dn->sibling) {
+ 		struct pci_dn *pdn = PCI_DN(dn);
+ 		if (pdn && pdn->devfn == devfn
+-		    && of_device_available(dn))
++		    && of_device_is_available(dn))
+ 			return rtas_read_config(pdn, where, size, val);
+ 	}
+ 
+@@ -164,7 +149,7 @@ static int rtas_pci_write_config(struct pci_bus *bus,
+ 	for (dn = busdn->child; dn; dn = dn->sibling) {
+ 		struct pci_dn *pdn = PCI_DN(dn);
+ 		if (pdn && pdn->devfn == devfn
+-		    && of_device_available(dn))
++		    && of_device_is_available(dn))
+ 			return rtas_write_config(pdn, where, size, val);
+ 	}
+ 	return PCIBIOS_DEVICE_NOT_FOUND;
+@@ -326,7 +311,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
+ 
+ 	res = b->resource[0];
+ 	if (!res->flags) {
+-		printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__,
++		printk(KERN_ERR "%s: no IO resource for PHB %s\n", __func__,
+ 				b->name);
+ 		return 1;
+ 	}
+@@ -334,13 +319,13 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
+ 	rc = pcibios_unmap_io_space(b);
+ 	if (rc) {
+ 		printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
+-			__FUNCTION__, b->name);
++			__func__, b->name);
+ 		return 1;
+ 	}
+ 
+ 	if (release_resource(res)) {
+ 		printk(KERN_ERR "%s: failed to release IO on bus %s\n",
+-				__FUNCTION__, b->name);
++				__func__, b->name);
+ 		return 1;
+ 	}
+ 
+@@ -348,13 +333,13 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
+ 		res = b->resource[i];
+ 		if (!res->flags && i == 0) {
+ 			printk(KERN_ERR "%s: no MEM resource for PHB %s\n",
+-				__FUNCTION__, b->name);
++				__func__, b->name);
+ 			return 1;
+ 		}
+ 		if (res->flags && release_resource(res)) {
+ 			printk(KERN_ERR
+ 			       "%s: failed to release IO %d on bus %s\n",
+-				__FUNCTION__, i, b->name);
++				__func__, i, b->name);
+ 			return 1;
+ 		}
+ 	}
+diff --git a/arch/powerpc/kernel/semaphore.c b/arch/powerpc/kernel/semaphore.c
+deleted file mode 100644
+index 2f8c3c9..0000000
+--- a/arch/powerpc/kernel/semaphore.c
++++ /dev/null
+@@ -1,135 +0,0 @@
+-/*
+- * PowerPC-specific semaphore code.
+- *
+- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * April 2001 - Reworked by Paul Mackerras <paulus at samba.org>
+- * to eliminate the SMP races in the old version between the updates
+- * of `count' and `waking'.  Now we use negative `count' values to
+- * indicate that some process(es) are waiting for the semaphore.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-
+-#include <asm/atomic.h>
+-#include <asm/semaphore.h>
+-#include <asm/errno.h>
+-
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- *	old_count = sem->count;
+- *	tmp = MAX(old_count, 0) + incr;
+- *	sem->count = tmp;
+- *	return old_count;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+-	int old_count, tmp;
+-
+-	__asm__ __volatile__("\n"
+-"1:	lwarx	%0,0,%3\n"
+-"	srawi	%1,%0,31\n"
+-"	andc	%1,%0,%1\n"
+-"	add	%1,%1,%4\n"
+-	PPC405_ERR77(0,%3)
+-"	stwcx.	%1,0,%3\n"
+-"	bne	1b"
+-	: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+-	: "r" (&sem->count), "r" (incr), "m" (sem->count)
+-	: "cc");
+-
+-	return old_count;
+-}
+-
+-void __up(struct semaphore *sem)
+-{
+-	/*
+-	 * Note that we incremented count in up() before we came here,
+-	 * but that was ineffective since the result was <= 0, and
+-	 * any negative value of count is equivalent to 0.
+-	 * This ends up setting count to 1, unless count is now > 0
+-	 * (i.e. because some other cpu has called up() in the meantime),
+-	 * in which case we just increment count.
+-	 */
+-	__sem_update_count(sem, 1);
+-	wake_up(&sem->wait);
+-}
+-EXPORT_SYMBOL(__up);
+-
+-/*
+- * Note that when we come in to __down or __down_interruptible,
+- * we have already decremented count, but that decrement was
+- * ineffective since the result was < 0, and any negative value
+- * of count is equivalent to 0.
+- * Thus it is only when we decrement count from some value > 0
+- * that we have actually got the semaphore.
+- */
+-void __sched __down(struct semaphore *sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	/*
+-	 * Try to get the semaphore.  If the count is > 0, then we've
+-	 * got the semaphore; we decrement count and exit the loop.
+-	 * If the count is 0 or negative, we set it to -1, indicating
+-	 * that we are asleep, and then sleep.
+-	 */
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		schedule();
+-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-	}
+-	remove_wait_queue(&sem->wait, &wait);
+-	__set_task_state(tsk, TASK_RUNNING);
+-
+-	/*
+-	 * If there are any more sleepers, wake one of them up so
+-	 * that it can either get the semaphore, or set count to -1
+-	 * indicating that there are still processes sleeping.
+-	 */
+-	wake_up(&sem->wait);
+-}
+-EXPORT_SYMBOL(__down);
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	__set_task_state(tsk, TASK_INTERRUPTIBLE);
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		if (signal_pending(current)) {
+-			/*
+-			 * A signal is pending - give up trying.
+-			 * Set sem->count to 0 if it is negative,
+-			 * since we are no longer sleeping.
+-			 */
+-			__sem_update_count(sem, 0);
+-			retval = -EINTR;
+-			break;
+-		}
+-		schedule();
+-		set_task_state(tsk, TASK_INTERRUPTIBLE);
+-	}
+-	remove_wait_queue(&sem->wait, &wait);
+-	__set_task_state(tsk, TASK_RUNNING);
+-
+-	wake_up(&sem->wait);
+-	return retval;
+-}
+-EXPORT_SYMBOL(__down_interruptible);
+diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
+index 6adb5a1..db540ea 100644
+--- a/arch/powerpc/kernel/setup-common.c
++++ b/arch/powerpc/kernel/setup-common.c
+@@ -34,6 +34,7 @@
+ #include <linux/serial_8250.h>
+ #include <linux/debugfs.h>
+ #include <linux/percpu.h>
++#include <linux/lmb.h>
+ #include <asm/io.h>
+ #include <asm/prom.h>
+ #include <asm/processor.h>
+@@ -56,7 +57,6 @@
+ #include <asm/cache.h>
+ #include <asm/page.h>
+ #include <asm/mmu.h>
+-#include <asm/lmb.h>
+ #include <asm/xmon.h>
+ #include <asm/cputhreads.h>
+ 
+@@ -167,6 +167,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ 	unsigned short min;
+ 
+ 	if (cpu_id == NR_CPUS) {
++		struct device_node *root;
++		const char *model = NULL;
+ #if defined(CONFIG_SMP) && defined(CONFIG_PPC32)
+ 		unsigned long bogosum = 0;
+ 		int i;
+@@ -178,6 +180,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ 		seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
+ 		if (ppc_md.name)
+ 			seq_printf(m, "platform\t: %s\n", ppc_md.name);
++		root = of_find_node_by_path("/");
++		if (root)
++			model = of_get_property(root, "model", NULL);
++		if (model)
++			seq_printf(m, "model\t\t: %s\n", model);
++		of_node_put(root);
++
+ 		if (ppc_md.show_cpuinfo != NULL)
+ 			ppc_md.show_cpuinfo(m);
+ 
+diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
+index cd870a8..36f6779 100644
+--- a/arch/powerpc/kernel/setup_32.c
++++ b/arch/powerpc/kernel/setup_32.c
+@@ -10,9 +10,6 @@
+ #include <linux/reboot.h>
+ #include <linux/delay.h>
+ #include <linux/initrd.h>
+-#if defined(CONFIG_IDE) || defined(CONFIG_IDE_MODULE)
+-#include <linux/ide.h>
+-#endif
+ #include <linux/tty.h>
+ #include <linux/bootmem.h>
+ #include <linux/seq_file.h>
+@@ -51,11 +48,6 @@
+ 
+ extern void bootx_init(unsigned long r4, unsigned long phys);
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-struct ide_machdep_calls ppc_ide_md;
+-EXPORT_SYMBOL(ppc_ide_md);
+-#endif
+-
+ int boot_cpuid;
+ EXPORT_SYMBOL_GPL(boot_cpuid);
+ int boot_cpuid_phys;
+@@ -172,6 +164,18 @@ int __init ppc_setup_l2cr(char *str)
+ }
+ __setup("l2cr=", ppc_setup_l2cr);
+ 
++/* Checks "l3cr=xxxx" command-line option */
++int __init ppc_setup_l3cr(char *str)
++{
++	if (cpu_has_feature(CPU_FTR_L3CR)) {
++		unsigned long val = simple_strtoul(str, NULL, 0);
++		printk(KERN_INFO "l3cr set to %lx\n", val);
++		_set_L3CR(val);		/* and enable it */
++	}
++	return 1;
++}
++__setup("l3cr=", ppc_setup_l3cr);
++
+ #ifdef CONFIG_GENERIC_NVRAM
+ 
+ /* Generic nvram hooks used by drivers/char/gen_nvram.c */
+@@ -277,7 +281,7 @@ void __init setup_arch(char **cmdline_p)
+ 	if (ppc_md.panic)
+ 		setup_panic();
+ 
+-	init_mm.start_code = PAGE_OFFSET;
++	init_mm.start_code = (unsigned long)_stext;
+ 	init_mm.end_code = (unsigned long) _etext;
+ 	init_mm.end_data = (unsigned long) _edata;
+ 	init_mm.brk = klimit;
+diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
+index 3b1529c..dff6308 100644
+--- a/arch/powerpc/kernel/setup_64.c
++++ b/arch/powerpc/kernel/setup_64.c
+@@ -33,6 +33,8 @@
+ #include <linux/serial_8250.h>
+ #include <linux/bootmem.h>
+ #include <linux/pci.h>
++#include <linux/lockdep.h>
++#include <linux/lmb.h>
+ #include <asm/io.h>
+ #include <asm/kdump.h>
+ #include <asm/prom.h>
+@@ -55,7 +57,6 @@
+ #include <asm/cache.h>
+ #include <asm/page.h>
+ #include <asm/mmu.h>
+-#include <asm/lmb.h>
+ #include <asm/firmware.h>
+ #include <asm/xmon.h>
+ #include <asm/udbg.h>
+@@ -169,6 +170,9 @@ void __init setup_paca(int cpu)
+ 
+ void __init early_setup(unsigned long dt_ptr)
+ {
++	/* Fill in any unititialised pacas */
++	initialise_pacas();
++
+ 	/* Identify CPU type */
+ 	identify_cpu(0, mfspr(SPRN_PVR));
+ 
+@@ -178,6 +182,9 @@ void __init early_setup(unsigned long dt_ptr)
+ 	/* Enable early debugging if any specified (see udbg.h) */
+ 	udbg_early_init();
+ 
++	/* Initialize lockdep early or else spinlocks will blow */
++	lockdep_init();
++
+  	DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr);
+ 
+ 	/*
+@@ -431,7 +438,7 @@ void __init setup_system(void)
+ 		printk("htab_address                  = 0x%p\n", htab_address);
+ 	printk("htab_hash_mask                = 0x%lx\n", htab_hash_mask);
+ #if PHYSICAL_START > 0
+-	printk("physical_start                = 0x%x\n", PHYSICAL_START);
++	printk("physical_start                = 0x%lx\n", PHYSICAL_START);
+ #endif
+ 	printk("-----------------------------------------------------\n");
+ 
+@@ -510,7 +517,7 @@ void __init setup_arch(char **cmdline_p)
+ 	if (ppc_md.panic)
+ 		setup_panic();
+ 
+-	init_mm.start_code = PAGE_OFFSET;
++	init_mm.start_code = (unsigned long)_stext;
+ 	init_mm.end_code = (unsigned long) _etext;
+ 	init_mm.end_data = (unsigned long) _edata;
+ 	init_mm.brk = klimit;
+diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
+index d840bc7..ad69434 100644
+--- a/arch/powerpc/kernel/signal_32.c
++++ b/arch/powerpc/kernel/signal_32.c
+@@ -621,6 +621,18 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
+ 
+ #define copy_siginfo_to_user	copy_siginfo_to_user32
+ 
++int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
++{
++	memset(to, 0, sizeof *to);
++
++	if (copy_from_user(to, from, 3*sizeof(int)) ||
++	    copy_from_user(to->_sifields._pad,
++			   from->_sifields._pad, SI_PAD_SIZE32))
++		return -EFAULT;
++
++	return 0;
++}
++
+ /*
+  * Note: it is necessary to treat pid and sig as unsigned ints, with the
+  * corresponding cast to a signed int to insure that the proper conversion
+@@ -634,9 +646,10 @@ long compat_sys_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo
+ 	int ret;
+ 	mm_segment_t old_fs = get_fs();
+ 
+-	if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
+-	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE32))
+-		return -EFAULT;
++	ret = copy_siginfo_from_user32(&info, uinfo);
++	if (unlikely(ret))
++		return ret;
++
+ 	set_fs (KERNEL_DS);
+ 	/* The __user pointer cast is valid becasuse of the set_fs() */
+ 	ret = sys_rt_sigqueueinfo((int)pid, (int)sig, (siginfo_t __user *) &info);
+diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
+new file mode 100644
+index 0000000..9629440
+--- /dev/null
++++ b/arch/powerpc/kernel/stacktrace.c
+@@ -0,0 +1,46 @@
++/*
++ * Stack trace utility
++ *
++ * Copyright 2008 Christoph Hellwig, IBM Corp.
++ *
++ *
++ *      This program is free software; you can redistribute it and/or
++ *      modify it under the terms of the GNU General Public License
++ *      as published by the Free Software Foundation; either version
++ *      2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/sched.h>
++#include <linux/stacktrace.h>
++#include <asm/ptrace.h>
++
++/*
++ * Save stack-backtrace addresses into a stack_trace buffer.
++ */
++void save_stack_trace(struct stack_trace *trace)
++{
++	unsigned long sp;
++
++	asm("mr %0,1" : "=r" (sp));
++
++	for (;;) {
++		unsigned long *stack = (unsigned long *) sp;
++		unsigned long newsp, ip;
++
++		if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
++			return;
++
++		newsp = stack[0];
++		ip = stack[STACK_FRAME_LR_SAVE];
++
++		if (!trace->skip)
++			trace->entries[trace->nr_entries++] = ip;
++		else
++			trace->skip--;
++
++		if (trace->nr_entries >= trace->max_entries)
++			return;
++
++		sp = newsp;
++	}
++}
+diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
+index 4a4f5c6..709f8cb 100644
+--- a/arch/powerpc/kernel/sys_ppc32.c
++++ b/arch/powerpc/kernel/sys_ppc32.c
+@@ -47,7 +47,6 @@
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
+-#include <asm/semaphore.h>
+ #include <asm/time.h>
+ #include <asm/mmu_context.h>
+ #include <asm/ppc-pci.h>
+@@ -368,11 +367,6 @@ long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+ 
+ 	error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
+ 
+-	if (error == 0) {
+-		task_lock(current);
+-		current->ptrace &= ~PT_DTRACE;
+-		task_unlock(current);
+-	}
+ 	putname(filename);
+ 
+ out:
+diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
+index 3b1d5dd..e722a4e 100644
+--- a/arch/powerpc/kernel/syscalls.c
++++ b/arch/powerpc/kernel/syscalls.c
+@@ -38,7 +38,6 @@
+ #include <linux/personality.h>
+ 
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/syscalls.h>
+ #include <asm/time.h>
+ #include <asm/unistd.h>
+diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
+index 7aad620..7d6c9bb 100644
+--- a/arch/powerpc/kernel/udbg.c
++++ b/arch/powerpc/kernel/udbg.c
+@@ -154,8 +154,8 @@ static void udbg_console_write(struct console *con, const char *s,
+ static struct console udbg_console = {
+ 	.name	= "udbg",
+ 	.write	= udbg_console_write,
+-	.flags	= CON_PRINTBUFFER | CON_ENABLED | CON_BOOT,
+-	.index	= -1,
++	.flags	= CON_PRINTBUFFER | CON_ENABLED | CON_BOOT | CON_ANYTIME,
++	.index	= 0,
+ };
+ 
+ static int early_console_initialized;
+diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
+index d3437c4..c21a626 100644
+--- a/arch/powerpc/kernel/vdso.c
++++ b/arch/powerpc/kernel/vdso.c
+@@ -21,13 +21,14 @@
+ #include <linux/elf.h>
+ #include <linux/security.h>
+ #include <linux/bootmem.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+ #include <asm/processor.h>
+ #include <asm/mmu.h>
+ #include <asm/mmu_context.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/machdep.h>
+ #include <asm/cputable.h>
+ #include <asm/sections.h>
+diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
+index f988672..b77f8af 100644
+--- a/arch/powerpc/kernel/vio.c
++++ b/arch/powerpc/kernel/vio.c
+@@ -139,7 +139,7 @@ static int vio_bus_remove(struct device *dev)
+  */
+ int vio_register_driver(struct vio_driver *viodrv)
+ {
+-	printk(KERN_DEBUG "%s: driver %s registering\n", __FUNCTION__,
++	printk(KERN_DEBUG "%s: driver %s registering\n", __func__,
+ 		viodrv->driver.name);
+ 
+ 	/* fill in 'struct driver' fields */
+@@ -184,7 +184,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
+ 	/* we need the 'device_type' property, in order to match with drivers */
+ 	if (of_node->type == NULL) {
+ 		printk(KERN_WARNING "%s: node %s missing 'device_type'\n",
+-				__FUNCTION__,
++				__func__,
+ 				of_node->name ? of_node->name : "<unknown>");
+ 		return NULL;
+ 	}
+@@ -192,7 +192,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
+ 	unit_address = of_get_property(of_node, "reg", NULL);
+ 	if (unit_address == NULL) {
+ 		printk(KERN_WARNING "%s: node %s missing 'reg'\n",
+-				__FUNCTION__,
++				__func__,
+ 				of_node->name ? of_node->name : "<unknown>");
+ 		return NULL;
+ 	}
+@@ -227,7 +227,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
+ 	/* register with generic device framework */
+ 	if (device_register(&viodev->dev)) {
+ 		printk(KERN_ERR "%s: failed to register device %s\n",
+-				__FUNCTION__, viodev->dev.bus_id);
++				__func__, viodev->dev.bus_id);
+ 		/* XXX free TCE table */
+ 		kfree(viodev);
+ 		return NULL;
+@@ -258,7 +258,7 @@ static int __init vio_bus_init(void)
+ 	err = device_register(&vio_bus_device.dev);
+ 	if (err) {
+ 		printk(KERN_WARNING "%s: device_register returned %i\n",
+-				__FUNCTION__, err);
++				__func__, err);
+ 		return err;
+ 	}
+ 
+diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
+index 0afb9e3..0c3000b 100644
+--- a/arch/powerpc/kernel/vmlinux.lds.S
++++ b/arch/powerpc/kernel/vmlinux.lds.S
+@@ -1,11 +1,9 @@
+ #ifdef CONFIG_PPC64
+-#include <asm/page.h>
+ #define PROVIDE32(x)	PROVIDE(__unused__##x)
+ #else
+-#define PAGE_SIZE	4096
+-#define KERNELBASE	CONFIG_KERNEL_START
+ #define PROVIDE32(x)	PROVIDE(x)
+ #endif
++#include <asm/page.h>
+ #include <asm-generic/vmlinux.lds.h>
+ #include <asm/cache.h>
+ 
+@@ -33,7 +31,7 @@ SECTIONS
+  */
+ 
+ 	/* Text and gots */
+-	.text : {
++	.text : AT(ADDR(.text) - LOAD_OFFSET) {
+ 		ALIGN_FUNCTION();
+ 		*(.text.head)
+ 		_text = .;
+@@ -58,7 +56,7 @@ SECTIONS
+ 	RODATA
+ 
+ 	/* Exception & bug tables */
+-	__ex_table : {
++	__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+ 		__start___ex_table = .;
+ 		*(__ex_table)
+ 		__stop___ex_table = .;
+@@ -74,7 +72,7 @@ SECTIONS
+ 	. = ALIGN(PAGE_SIZE);
+ 	__init_begin = .;
+ 
+-	.init.text : {
++	.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
+ 		_sinittext = .;
+ 		INIT_TEXT
+ 		_einittext = .;
+@@ -83,11 +81,11 @@ SECTIONS
+ 	/* .exit.text is discarded at runtime, not link time,
+ 	 * to deal with references from __bug_table
+ 	 */
+-	.exit.text : {
++	.exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
+ 		EXIT_TEXT
+ 	}
+ 
+-	.init.data : {
++	.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
+ 		INIT_DATA
+ 		__vtop_table_begin = .;
+ 		*(.vtop_fixup);
+@@ -103,19 +101,19 @@ SECTIONS
+ 	}
+ 
+ 	. = ALIGN(16);
+-	.init.setup : {
++	.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
+ 		__setup_start = .;
+ 		*(.init.setup)
+ 		__setup_end = .;
+ 	}
+ 
+-	.initcall.init : {
++	.initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
+ 		__initcall_start = .;
+ 		INITCALLS
+ 		__initcall_end = .;
+ 		}
+ 
+-	.con_initcall.init : {
++	.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+ 		__con_initcall_start = .;
+ 		*(.con_initcall.init)
+ 		__con_initcall_end = .;
+@@ -124,14 +122,14 @@ SECTIONS
+ 	SECURITY_INIT
+ 
+ 	. = ALIGN(8);
+-	__ftr_fixup : {
++	__ftr_fixup : AT(ADDR(__ftr_fixup) - LOAD_OFFSET) {
+ 		__start___ftr_fixup = .;
+ 		*(__ftr_fixup)
+ 		__stop___ftr_fixup = .;
+ 	}
+ #ifdef CONFIG_PPC64
+ 	. = ALIGN(8);
+-	__fw_ftr_fixup : {
++	__fw_ftr_fixup : AT(ADDR(__fw_ftr_fixup) - LOAD_OFFSET) {
+ 		__start___fw_ftr_fixup = .;
+ 		*(__fw_ftr_fixup)
+ 		__stop___fw_ftr_fixup = .;
+@@ -139,14 +137,14 @@ SECTIONS
+ #endif
+ #ifdef CONFIG_BLK_DEV_INITRD
+ 	. = ALIGN(PAGE_SIZE);
+-	.init.ramfs : {
++	.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+ 		__initramfs_start = .;
+ 		*(.init.ramfs)
+ 		__initramfs_end = .;
+ 	}
+ #endif
+ 	. = ALIGN(PAGE_SIZE);
+-	.data.percpu : {
++	.data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) {
+ 		__per_cpu_start = .;
+ 		*(.data.percpu)
+ 		*(.data.percpu.shared_aligned)
+@@ -154,7 +152,7 @@ SECTIONS
+ 	}
+ 
+ 	. = ALIGN(8);
+-	.machine.desc : {
++	.machine.desc : AT(ADDR(.machine.desc) - LOAD_OFFSET) {
+ 		__machine_desc_start = . ;
+ 		*(.machine.desc)
+ 		__machine_desc_end = . ;
+@@ -172,25 +170,24 @@ SECTIONS
+ 	_sdata = .;
+ 
+ #ifdef CONFIG_PPC32
+-	.data    :
+-	{
++	.data : AT(ADDR(.data) - LOAD_OFFSET) {
+ 		DATA_DATA
+ 		*(.sdata)
+ 		*(.got.plt) *(.got)
+ 	}
+ #else
+-	.data : {
++	.data : AT(ADDR(.data) - LOAD_OFFSET) {
+ 		DATA_DATA
+ 		*(.data.rel*)
+ 		*(.toc1)
+ 		*(.branch_lt)
+ 	}
+ 
+-	.opd : {
++	.opd : AT(ADDR(.opd) - LOAD_OFFSET) {
+ 		*(.opd)
+ 	}
+ 
+-	.got : {
++	.got : AT(ADDR(.got) - LOAD_OFFSET) {
+ 		__toc_start = .;
+ 		*(.got)
+ 		*(.toc)
+@@ -207,26 +204,26 @@ SECTIONS
+ #else
+ 	. = ALIGN(16384);
+ #endif
+-	.data.init_task : {
++	.data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+ 		*(.data.init_task)
+ 	}
+ 
+ 	. = ALIGN(PAGE_SIZE);
+-	.data.page_aligned : {
++	.data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+ 		*(.data.page_aligned)
+ 	}
+ 
+-	.data.cacheline_aligned : {
++	.data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+ 		*(.data.cacheline_aligned)
+ 	}
+ 
+ 	. = ALIGN(L1_CACHE_BYTES);
+-	.data.read_mostly : {
++	.data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
+ 		*(.data.read_mostly)
+ 	}
+ 
+ 	. = ALIGN(PAGE_SIZE);
+-	__data_nosave : {
++	.data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
+ 		__nosave_begin = .;
+ 		*(.data.nosave)
+ 		. = ALIGN(PAGE_SIZE);
+@@ -237,7 +234,7 @@ SECTIONS
+  * And finally the bss
+  */
+ 
+-	.bss : {
++	.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+ 		__bss_start = .;
+ 		*(.sbss) *(.scommon)
+ 		*(.dynbss)
+diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
+index 22c3b4f..29b2941 100644
+--- a/arch/powerpc/lib/rheap.c
++++ b/arch/powerpc/lib/rheap.c
+@@ -54,7 +54,7 @@ static int grow(rh_info_t * info, int max_blocks)
+ 
+ 	new_blocks = max_blocks - info->max_blocks;
+ 
+-	block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_KERNEL);
++	block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_ATOMIC);
+ 	if (block == NULL)
+ 		return -ENOMEM;
+ 
+@@ -258,7 +258,7 @@ rh_info_t *rh_create(unsigned int alignment)
+ 	if ((alignment & (alignment - 1)) != 0)
+ 		return ERR_PTR(-EINVAL);
+ 
+-	info = kmalloc(sizeof(*info), GFP_KERNEL);
++	info = kmalloc(sizeof(*info), GFP_ATOMIC);
+ 	if (info == NULL)
+ 		return ERR_PTR(-ENOMEM);
+ 
+diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S
+index c4c622d..49eb1f1 100644
+--- a/arch/powerpc/lib/string.S
++++ b/arch/powerpc/lib/string.S
+@@ -75,6 +75,20 @@ _GLOBAL(strcmp)
+ 	beq	1b
+ 	blr
+ 
++_GLOBAL(strncmp)
++	PPC_LCMPI r5,0
++	beqlr
++	mtctr	r5
++	addi	r5,r3,-1
++	addi	r4,r4,-1
++1:	lbzu	r3,1(r5)
++	cmpwi	1,r3,0
++	lbzu	r0,1(r4)
++	subf.	r3,r0,r3
++	beqlr	1
++	bdnzt	eq,1b
++	blr
++
+ _GLOBAL(strlen)
+ 	addi	r4,r3,-1
+ 1:	lbzu	r0,1(r4)
+diff --git a/arch/powerpc/math-emu/fabs.c b/arch/powerpc/math-emu/fabs.c
+index 41f0617..549baba 100644
+--- a/arch/powerpc/math-emu/fabs.c
++++ b/arch/powerpc/math-emu/fabs.c
+@@ -9,7 +9,7 @@ fabs(u32 *frD, u32 *frB)
+ 	frD[1] = frB[1];
+ 
+ #ifdef DEBUG
+-	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++	printk("%s: D %p, B %p: ", __func__, frD, frB);
+ 	dump_double(frD);
+ 	printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fadd.c b/arch/powerpc/math-emu/fadd.c
+index fc88364..7befbbf 100644
+--- a/arch/powerpc/math-emu/fadd.c
++++ b/arch/powerpc/math-emu/fadd.c
+@@ -14,7 +14,7 @@ fadd(void *frD, void *frA, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++	printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fadds.c b/arch/powerpc/math-emu/fadds.c
+index 93025b6..2b346b3 100644
+--- a/arch/powerpc/math-emu/fadds.c
++++ b/arch/powerpc/math-emu/fadds.c
+@@ -15,7 +15,7 @@ fadds(void *frD, void *frA, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++	printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fcmpo.c b/arch/powerpc/math-emu/fcmpo.c
+index 4efac39..36d6890 100644
+--- a/arch/powerpc/math-emu/fcmpo.c
++++ b/arch/powerpc/math-emu/fcmpo.c
+@@ -15,7 +15,7 @@ fcmpo(u32 *ccr, int crfD, void *frA, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB);
++	printk("%s: %p (%08x) %d %p %p\n", __func__, ccr, *ccr, crfD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fcmpu.c b/arch/powerpc/math-emu/fcmpu.c
+index b7e3317..53d9389 100644
+--- a/arch/powerpc/math-emu/fcmpu.c
++++ b/arch/powerpc/math-emu/fcmpu.c
+@@ -14,7 +14,7 @@ fcmpu(u32 *ccr, int crfD, void *frA, void *frB)
+ 	long cmp;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB);
++	printk("%s: %p (%08x) %d %p %p\n", __func__, ccr, *ccr, crfD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fctiw.c b/arch/powerpc/math-emu/fctiw.c
+index 3b3c98b..fcd7a95 100644
+--- a/arch/powerpc/math-emu/fctiw.c
++++ b/arch/powerpc/math-emu/fctiw.c
+@@ -16,7 +16,7 @@ fctiw(u32 *frD, void *frB)
+ 	frD[1] = r;
+ 
+ #ifdef DEBUG
+-	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++	printk("%s: D %p, B %p: ", __func__, frD, frB);
+ 	dump_double(frD);
+ 	printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fctiwz.c b/arch/powerpc/math-emu/fctiwz.c
+index 7717eb6..1514d59 100644
+--- a/arch/powerpc/math-emu/fctiwz.c
++++ b/arch/powerpc/math-emu/fctiwz.c
+@@ -23,7 +23,7 @@ fctiwz(u32 *frD, void *frB)
+ 	__FPU_FPSCR = fpscr;
+ 
+ #ifdef DEBUG
+-	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++	printk("%s: D %p, B %p: ", __func__, frD, frB);
+ 	dump_double(frD);
+ 	printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fdiv.c b/arch/powerpc/math-emu/fdiv.c
+index f2fba82..18a20fe 100644
+--- a/arch/powerpc/math-emu/fdiv.c
++++ b/arch/powerpc/math-emu/fdiv.c
+@@ -14,7 +14,7 @@ fdiv(void *frD, void *frA, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++	printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+@@ -28,13 +28,13 @@ fdiv(void *frD, void *frA, void *frB)
+ 	if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
+ 		ret |= EFLAG_VXZDZ;
+ #ifdef DEBUG
+-		printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__);
++		printk("%s: FPSCR_VXZDZ raised\n", __func__);
+ #endif
+ 	}
+ 	if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
+ 		ret |= EFLAG_VXIDI;
+ #ifdef DEBUG
+-		printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__);
++		printk("%s: FPSCR_VXIDI raised\n", __func__);
+ #endif
+ 	}
+ 
+diff --git a/arch/powerpc/math-emu/fdivs.c b/arch/powerpc/math-emu/fdivs.c
+index b971196..24feed6 100644
+--- a/arch/powerpc/math-emu/fdivs.c
++++ b/arch/powerpc/math-emu/fdivs.c
+@@ -15,7 +15,7 @@ fdivs(void *frD, void *frA, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++	printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+@@ -29,13 +29,13 @@ fdivs(void *frD, void *frA, void *frB)
+ 	if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
+ 		ret |= EFLAG_VXZDZ;
+ #ifdef DEBUG
+-		printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__);
++		printk("%s: FPSCR_VXZDZ raised\n", __func__);
+ #endif
+ 	}
+ 	if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
+ 		ret |= EFLAG_VXIDI;
+ #ifdef DEBUG
+-		printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__);
++		printk("%s: FPSCR_VXIDI raised\n", __func__);
+ #endif
+ 	}
+ 
+diff --git a/arch/powerpc/math-emu/fmadd.c b/arch/powerpc/math-emu/fmadd.c
+index 0a1dbce..dedb465 100644
+--- a/arch/powerpc/math-emu/fmadd.c
++++ b/arch/powerpc/math-emu/fmadd.c
+@@ -16,7 +16,7 @@ fmadd(void *frD, void *frA, void *frB, void *frC)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++	printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmadds.c b/arch/powerpc/math-emu/fmadds.c
+index 0f70bba..6bbb56d 100644
+--- a/arch/powerpc/math-emu/fmadds.c
++++ b/arch/powerpc/math-emu/fmadds.c
+@@ -17,7 +17,7 @@ fmadds(void *frD, void *frA, void *frB, void *frC)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++	printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmr.c b/arch/powerpc/math-emu/fmr.c
+index 28df700..bd55384 100644
+--- a/arch/powerpc/math-emu/fmr.c
++++ b/arch/powerpc/math-emu/fmr.c
+@@ -9,7 +9,7 @@ fmr(u32 *frD, u32 *frB)
+ 	frD[1] = frB[1];
+ 
+ #ifdef DEBUG
+-	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++	printk("%s: D %p, B %p: ", __func__, frD, frB);
+ 	dump_double(frD);
+ 	printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fmsub.c b/arch/powerpc/math-emu/fmsub.c
+index 203fd48..f311e2c 100644
+--- a/arch/powerpc/math-emu/fmsub.c
++++ b/arch/powerpc/math-emu/fmsub.c
+@@ -16,7 +16,7 @@ fmsub(void *frD, void *frA, void *frB, void *frC)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++	printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmsubs.c b/arch/powerpc/math-emu/fmsubs.c
+index 8ce6862..81a716d 100644
+--- a/arch/powerpc/math-emu/fmsubs.c
++++ b/arch/powerpc/math-emu/fmsubs.c
+@@ -17,7 +17,7 @@ fmsubs(void *frD, void *frA, void *frB, void *frC)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++	printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmul.c b/arch/powerpc/math-emu/fmul.c
+index 66c7e79..2f3d327 100644
+--- a/arch/powerpc/math-emu/fmul.c
++++ b/arch/powerpc/math-emu/fmul.c
+@@ -14,7 +14,7 @@ fmul(void *frD, void *frA, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++	printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmuls.c b/arch/powerpc/math-emu/fmuls.c
+index 26bc427..962b588 100644
+--- a/arch/powerpc/math-emu/fmuls.c
++++ b/arch/powerpc/math-emu/fmuls.c
+@@ -15,7 +15,7 @@ fmuls(void *frD, void *frA, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++	printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fnabs.c b/arch/powerpc/math-emu/fnabs.c
+index c6b913d..a7d34f3 100644
+--- a/arch/powerpc/math-emu/fnabs.c
++++ b/arch/powerpc/math-emu/fnabs.c
+@@ -9,7 +9,7 @@ fnabs(u32 *frD, u32 *frB)
+ 	frD[1] = frB[1];
+ 
+ #ifdef DEBUG
+-	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++	printk("%s: D %p, B %p: ", __func__, frD, frB);
+ 	dump_double(frD);
+ 	printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fneg.c b/arch/powerpc/math-emu/fneg.c
+index fe9a98d..1e988cd 100644
+--- a/arch/powerpc/math-emu/fneg.c
++++ b/arch/powerpc/math-emu/fneg.c
+@@ -9,7 +9,7 @@ fneg(u32 *frD, u32 *frB)
+ 	frD[1] = frB[1];
+ 
+ #ifdef DEBUG
+-	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++	printk("%s: D %p, B %p: ", __func__, frD, frB);
+ 	dump_double(frD);
+ 	printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fnmadd.c b/arch/powerpc/math-emu/fnmadd.c
+index 7f31227..8cf7827 100644
+--- a/arch/powerpc/math-emu/fnmadd.c
++++ b/arch/powerpc/math-emu/fnmadd.c
+@@ -16,7 +16,7 @@ fnmadd(void *frD, void *frA, void *frB, void *frC)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++	printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fnmadds.c b/arch/powerpc/math-emu/fnmadds.c
+index 65454c9..f1c4f0f 100644
+--- a/arch/powerpc/math-emu/fnmadds.c
++++ b/arch/powerpc/math-emu/fnmadds.c
+@@ -17,7 +17,7 @@ fnmadds(void *frD, void *frA, void *frB, void *frC)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++	printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fnmsub.c b/arch/powerpc/math-emu/fnmsub.c
+index f1ca748..98944e6 100644
+--- a/arch/powerpc/math-emu/fnmsub.c
++++ b/arch/powerpc/math-emu/fnmsub.c
+@@ -16,7 +16,7 @@ fnmsub(void *frD, void *frA, void *frB, void *frC)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++	printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fnmsubs.c b/arch/powerpc/math-emu/fnmsubs.c
+index 5c9a09a..b20f4eb 100644
+--- a/arch/powerpc/math-emu/fnmsubs.c
++++ b/arch/powerpc/math-emu/fnmsubs.c
+@@ -17,7 +17,7 @@ fnmsubs(void *frD, void *frA, void *frB, void *frC)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++	printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fres.c b/arch/powerpc/math-emu/fres.c
+index ec11e46..10ecbd0 100644
+--- a/arch/powerpc/math-emu/fres.c
++++ b/arch/powerpc/math-emu/fres.c
+@@ -6,7 +6,7 @@ int
+ fres(void *frD, void *frB)
+ {
+ #ifdef DEBUG
+-	printk("%s: %p %p\n", __FUNCTION__, frD, frB);
++	printk("%s: %p %p\n", __func__, frD, frB);
+ #endif
+ 	return -ENOSYS;
+ }
+diff --git a/arch/powerpc/math-emu/frsp.c b/arch/powerpc/math-emu/frsp.c
+index d879b2a..724ccbc 100644
+--- a/arch/powerpc/math-emu/frsp.c
++++ b/arch/powerpc/math-emu/frsp.c
+@@ -12,7 +12,7 @@ frsp(void *frD, void *frB)
+ 	FP_DECL_D(B);
+ 
+ #ifdef DEBUG
+-	printk("%s: D %p, B %p\n", __FUNCTION__, frD, frB);
++	printk("%s: D %p, B %p\n", __func__, frD, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(B, frB);
+diff --git a/arch/powerpc/math-emu/frsqrte.c b/arch/powerpc/math-emu/frsqrte.c
+index a11ae18..1d0a3a0 100644
+--- a/arch/powerpc/math-emu/frsqrte.c
++++ b/arch/powerpc/math-emu/frsqrte.c
+@@ -6,7 +6,7 @@ int
+ frsqrte(void *frD, void *frB)
+ {
+ #ifdef DEBUG
+-	printk("%s: %p %p\n", __FUNCTION__, frD, frB);
++	printk("%s: %p %p\n", __func__, frD, frB);
+ #endif
+ 	return 0;
+ }
+diff --git a/arch/powerpc/math-emu/fsel.c b/arch/powerpc/math-emu/fsel.c
+index e36e6e7..ecb5f28 100644
+--- a/arch/powerpc/math-emu/fsel.c
++++ b/arch/powerpc/math-emu/fsel.c
+@@ -11,7 +11,7 @@ fsel(u32 *frD, void *frA, u32 *frB, u32 *frC)
+ 	FP_DECL_D(A);
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++	printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fsqrt.c b/arch/powerpc/math-emu/fsqrt.c
+index 6f8319f..38ec2b7 100644
+--- a/arch/powerpc/math-emu/fsqrt.c
++++ b/arch/powerpc/math-emu/fsqrt.c
+@@ -13,7 +13,7 @@ fsqrt(void *frD, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB);
++	printk("%s: %p %p %p %p\n", __func__, frD, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(B, frB);
+diff --git a/arch/powerpc/math-emu/fsqrts.c b/arch/powerpc/math-emu/fsqrts.c
+index 3b2b1cf..335263e 100644
+--- a/arch/powerpc/math-emu/fsqrts.c
++++ b/arch/powerpc/math-emu/fsqrts.c
+@@ -14,7 +14,7 @@ fsqrts(void *frD, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB);
++	printk("%s: %p %p %p %p\n", __func__, frD, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(B, frB);
+diff --git a/arch/powerpc/math-emu/fsub.c b/arch/powerpc/math-emu/fsub.c
+index 9566790..208d20f 100644
+--- a/arch/powerpc/math-emu/fsub.c
++++ b/arch/powerpc/math-emu/fsub.c
+@@ -14,7 +14,7 @@ fsub(void *frD, void *frA, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++	printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fsubs.c b/arch/powerpc/math-emu/fsubs.c
+index 3428117..0e61b80 100644
+--- a/arch/powerpc/math-emu/fsubs.c
++++ b/arch/powerpc/math-emu/fsubs.c
+@@ -15,7 +15,7 @@ fsubs(void *frD, void *frA, void *frB)
+ 	int ret = 0;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++	printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/lfd.c b/arch/powerpc/math-emu/lfd.c
+index 7d38101..6ec90b5 100644
+--- a/arch/powerpc/math-emu/lfd.c
++++ b/arch/powerpc/math-emu/lfd.c
+@@ -11,7 +11,7 @@ lfd(void *frD, void *ea)
+ 	if (copy_from_user(frD, ea, sizeof(double)))
+ 		return -EFAULT;
+ #ifdef DEBUG
+-	printk("%s: D %p, ea %p: ", __FUNCTION__, frD, ea);
++	printk("%s: D %p, ea %p: ", __func__, frD, ea);
+ 	dump_double(frD);
+ 	printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/lfs.c b/arch/powerpc/math-emu/lfs.c
+index c86dee3..6f18ebe 100644
+--- a/arch/powerpc/math-emu/lfs.c
++++ b/arch/powerpc/math-emu/lfs.c
+@@ -14,7 +14,7 @@ lfs(void *frD, void *ea)
+ 	float f;
+ 
+ #ifdef DEBUG
+-	printk("%s: D %p, ea %p\n", __FUNCTION__, frD, ea);
++	printk("%s: D %p, ea %p\n", __func__, frD, ea);
+ #endif
+ 
+ 	if (copy_from_user(&f, ea, sizeof(float)))
+diff --git a/arch/powerpc/math-emu/mcrfs.c b/arch/powerpc/math-emu/mcrfs.c
+index 106dd91..41ba247 100644
+--- a/arch/powerpc/math-emu/mcrfs.c
++++ b/arch/powerpc/math-emu/mcrfs.c
+@@ -10,7 +10,7 @@ mcrfs(u32 *ccr, u32 crfD, u32 crfS)
+ 	u32 value, clear;
+ 
+ #ifdef DEBUG
+-	printk("%s: %p (%08x) %d %d\n", __FUNCTION__, ccr, *ccr, crfD, crfS);
++	printk("%s: %p (%08x) %d %d\n", __func__, ccr, *ccr, crfD, crfS);
+ #endif
+ 
+ 	clear = 15 << ((7 - crfS) << 2);
+@@ -24,7 +24,7 @@ mcrfs(u32 *ccr, u32 crfD, u32 crfS)
+ 	*ccr |= (value << ((7 - crfD) << 2));
+ 
+ #ifdef DEBUG
+-	printk("CR: %08x\n", __FUNCTION__, *ccr);
++	printk("CR: %08x\n", __func__, *ccr);
+ #endif
+ 
+ 	return 0;
+diff --git a/arch/powerpc/math-emu/mffs.c b/arch/powerpc/math-emu/mffs.c
+index f477c91..b0e2106 100644
+--- a/arch/powerpc/math-emu/mffs.c
++++ b/arch/powerpc/math-emu/mffs.c
+@@ -10,7 +10,7 @@ mffs(u32 *frD)
+ 	frD[1] = __FPU_FPSCR;
+ 
+ #ifdef DEBUG
+-	printk("%s: frD %p: %08x.%08x\n", __FUNCTION__, frD, frD[0], frD[1]);
++	printk("%s: frD %p: %08x.%08x\n", __func__, frD, frD[0], frD[1]);
+ #endif
+ 
+ 	return 0;
+diff --git a/arch/powerpc/math-emu/mtfsb0.c b/arch/powerpc/math-emu/mtfsb0.c
+index 99bfd80..d306235 100644
+--- a/arch/powerpc/math-emu/mtfsb0.c
++++ b/arch/powerpc/math-emu/mtfsb0.c
+@@ -11,7 +11,7 @@ mtfsb0(int crbD)
+ 		__FPU_FPSCR &= ~(1 << (31 - crbD));
+ 
+ #ifdef DEBUG
+-	printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR);
++	printk("%s: %d %08lx\n", __func__, crbD, __FPU_FPSCR);
+ #endif
+ 
+ 	return 0;
+diff --git a/arch/powerpc/math-emu/mtfsb1.c b/arch/powerpc/math-emu/mtfsb1.c
+index 3d9e7ed..2e94870 100644
+--- a/arch/powerpc/math-emu/mtfsb1.c
++++ b/arch/powerpc/math-emu/mtfsb1.c
+@@ -11,7 +11,7 @@ mtfsb1(int crbD)
+ 		__FPU_FPSCR |= (1 << (31 - crbD));
+ 
+ #ifdef DEBUG
+-	printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR);
++	printk("%s: %d %08lx\n", __func__, crbD, __FPU_FPSCR);
+ #endif
+ 
+ 	return 0;
+diff --git a/arch/powerpc/math-emu/mtfsf.c b/arch/powerpc/math-emu/mtfsf.c
+index d70cf71..48014d8 100644
+--- a/arch/powerpc/math-emu/mtfsf.c
++++ b/arch/powerpc/math-emu/mtfsf.c
+@@ -38,7 +38,7 @@ mtfsf(unsigned int FM, u32 *frB)
+ 	__FPU_FPSCR |= (frB[1] & mask);
+ 
+ #ifdef DEBUG
+-	printk("%s: %02x %p: %08lx\n", __FUNCTION__, FM, frB, __FPU_FPSCR);
++	printk("%s: %02x %p: %08lx\n", __func__, FM, frB, __FPU_FPSCR);
+ #endif
+ 
+ 	return 0;
+diff --git a/arch/powerpc/math-emu/mtfsfi.c b/arch/powerpc/math-emu/mtfsfi.c
+index 71df854..031e200 100644
+--- a/arch/powerpc/math-emu/mtfsfi.c
++++ b/arch/powerpc/math-emu/mtfsfi.c
+@@ -16,7 +16,7 @@ mtfsfi(unsigned int crfD, unsigned int IMM)
+ 	__FPU_FPSCR |= (IMM & 0xf) << ((7 - crfD) << 2);
+ 
+ #ifdef DEBUG
+-	printk("%s: %d %x: %08lx\n", __FUNCTION__, crfD, IMM, __FPU_FPSCR);
++	printk("%s: %d %x: %08lx\n", __func__, crfD, IMM, __FPU_FPSCR);
+ #endif
+ 
+ 	return 0;
+diff --git a/arch/powerpc/math-emu/stfd.c b/arch/powerpc/math-emu/stfd.c
+index 3f8c255..33a165c 100644
+--- a/arch/powerpc/math-emu/stfd.c
++++ b/arch/powerpc/math-emu/stfd.c
+@@ -7,7 +7,7 @@ stfd(void *frS, void *ea)
+ {
+ #if 0
+ #ifdef DEBUG
+-	printk("%s: S %p, ea %p: ", __FUNCTION__, frS, ea);
++	printk("%s: S %p, ea %p: ", __func__, frS, ea);
+ 	dump_double(frS);
+ 	printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/stfiwx.c b/arch/powerpc/math-emu/stfiwx.c
+index 95caaee..f15a35f 100644
+--- a/arch/powerpc/math-emu/stfiwx.c
++++ b/arch/powerpc/math-emu/stfiwx.c
+@@ -6,7 +6,7 @@ int
+ stfiwx(u32 *frS, void *ea)
+ {
+ #ifdef DEBUG
+-	printk("%s: %p %p\n", __FUNCTION__, frS, ea);
++	printk("%s: %p %p\n", __func__, frS, ea);
+ #endif
+ 
+ 	if (copy_to_user(ea, &frS[1], sizeof(frS[1])))
+diff --git a/arch/powerpc/math-emu/stfs.c b/arch/powerpc/math-emu/stfs.c
+index e87ca23..8689aa4 100644
+--- a/arch/powerpc/math-emu/stfs.c
++++ b/arch/powerpc/math-emu/stfs.c
+@@ -15,7 +15,7 @@ stfs(void *frS, void *ea)
+ 	int err;
+ 
+ #ifdef DEBUG
+-	printk("%s: S %p, ea %p\n", __FUNCTION__, frS, ea);
++	printk("%s: S %p, ea %p\n", __func__, frS, ea);
+ #endif
+ 
+ 	__FP_UNPACK_D(A, frS);
+diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c
+index 3899ea9..cecbbc7 100644
+--- a/arch/powerpc/mm/40x_mmu.c
++++ b/arch/powerpc/mm/40x_mmu.c
+@@ -97,7 +97,7 @@ unsigned long __init mmu_mapin_ram(void)
+ 	phys_addr_t p;
+ 
+ 	v = KERNELBASE;
+-	p = PPC_MEMSTART;
++	p = 0;
+ 	s = total_lowmem;
+ 
+ 	if (__map_without_ltlbs)
+diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
+index 04dc087..953fb91 100644
+--- a/arch/powerpc/mm/44x_mmu.c
++++ b/arch/powerpc/mm/44x_mmu.c
+@@ -67,7 +67,7 @@ unsigned long __init mmu_mapin_ram(void)
+ 
+ 	/* Pin in enough TLBs to cover any lowmem not covered by the
+ 	 * initial 256M mapping established in head_44x.S */
+-	for (addr = PPC_PIN_SIZE; addr < total_lowmem;
++	for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr;
+ 	     addr += PPC_PIN_SIZE)
+ 		ppc44x_pin_tlb(addr + PAGE_OFFSET, addr);
+ 
+diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
+index 41649a5..1c00e01 100644
+--- a/arch/powerpc/mm/Makefile
++++ b/arch/powerpc/mm/Makefile
+@@ -6,7 +6,7 @@ ifeq ($(CONFIG_PPC64),y)
+ EXTRA_CFLAGS	+= -mno-minimal-toc
+ endif
+ 
+-obj-y				:= fault.o mem.o lmb.o \
++obj-y				:= fault.o mem.o \
+ 				   init_$(CONFIG_WORD_SIZE).o \
+ 				   pgtable_$(CONFIG_WORD_SIZE).o \
+ 				   mmu_context_$(CONFIG_WORD_SIZE).o
+diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
+index c93a966..ce10e2b 100644
+--- a/arch/powerpc/mm/fsl_booke_mmu.c
++++ b/arch/powerpc/mm/fsl_booke_mmu.c
+@@ -49,18 +49,15 @@
+ #include <asm/mmu.h>
+ #include <asm/uaccess.h>
+ #include <asm/smp.h>
+-#include <asm/bootx.h>
+ #include <asm/machdep.h>
+ #include <asm/setup.h>
+ 
++#include "mmu_decl.h"
++
+ extern void loadcam_entry(unsigned int index);
+ unsigned int tlbcam_index;
+ unsigned int num_tlbcam_entries;
+ static unsigned long __cam0, __cam1, __cam2;
+-extern unsigned long total_lowmem;
+-extern unsigned long __max_low_memory;
+-extern unsigned long __initial_memory_limit;
+-#define MAX_LOW_MEM	CONFIG_LOWMEM_SIZE
+ 
+ #define NUM_TLBCAMS	(16)
+ 
+@@ -165,15 +162,15 @@ void invalidate_tlbcam_entry(int index)
+ void __init cam_mapin_ram(unsigned long cam0, unsigned long cam1,
+ 		unsigned long cam2)
+ {
+-	settlbcam(0, PAGE_OFFSET, PPC_MEMSTART, cam0, _PAGE_KERNEL, 0);
++	settlbcam(0, PAGE_OFFSET, memstart_addr, cam0, _PAGE_KERNEL, 0);
+ 	tlbcam_index++;
+ 	if (cam1) {
+ 		tlbcam_index++;
+-		settlbcam(1, PAGE_OFFSET+cam0, PPC_MEMSTART+cam0, cam1, _PAGE_KERNEL, 0);
++		settlbcam(1, PAGE_OFFSET+cam0, memstart_addr+cam0, cam1, _PAGE_KERNEL, 0);
+ 	}
+ 	if (cam2) {
+ 		tlbcam_index++;
+-		settlbcam(2, PAGE_OFFSET+cam0+cam1, PPC_MEMSTART+cam0+cam1, cam2, _PAGE_KERNEL, 0);
++		settlbcam(2, PAGE_OFFSET+cam0+cam1, memstart_addr+cam0+cam1, cam2, _PAGE_KERNEL, 0);
+ 	}
+ }
+ 
+@@ -196,35 +193,32 @@ unsigned long __init mmu_mapin_ram(void)
+ void __init
+ adjust_total_lowmem(void)
+ {
+-	unsigned long max_low_mem = MAX_LOW_MEM;
+-	unsigned long cam_max = 0x10000000;
+-	unsigned long ram;
++	phys_addr_t max_lowmem_size = __max_low_memory;
++	phys_addr_t cam_max_size = 0x10000000;
++	phys_addr_t ram;
+ 
+-	/* adjust CAM size to max_low_mem */
+-	if (max_low_mem < cam_max)
+-		cam_max = max_low_mem;
++	/* adjust CAM size to max_lowmem_size */
++	if (max_lowmem_size < cam_max_size)
++		cam_max_size = max_lowmem_size;
+ 
+-	/* adjust lowmem size to max_low_mem */
+-	if (max_low_mem < total_lowmem)
+-		ram = max_low_mem;
+-	else
+-		ram = total_lowmem;
++	/* adjust lowmem size to max_lowmem_size */
++	ram = min(max_lowmem_size, (phys_addr_t)total_lowmem);
+ 
+ 	/* Calculate CAM values */
+ 	__cam0 = 1UL << 2 * (__ilog2(ram) / 2);
+-	if (__cam0 > cam_max)
+-		__cam0 = cam_max;
++	if (__cam0 > cam_max_size)
++		__cam0 = cam_max_size;
+ 	ram -= __cam0;
+ 	if (ram) {
+ 		__cam1 = 1UL << 2 * (__ilog2(ram) / 2);
+-		if (__cam1 > cam_max)
+-			__cam1 = cam_max;
++		if (__cam1 > cam_max_size)
++			__cam1 = cam_max_size;
+ 		ram -= __cam1;
+ 	}
+ 	if (ram) {
+ 		__cam2 = 1UL << 2 * (__ilog2(ram) / 2);
+-		if (__cam2 > cam_max)
+-			__cam2 = cam_max;
++		if (__cam2 > cam_max_size)
++			__cam2 = cam_max_size;
+ 		ram -= __cam2;
+ 	}
+ 
+@@ -232,6 +226,6 @@ adjust_total_lowmem(void)
+ 			" CAM2=%ldMb residual: %ldMb\n",
+ 			__cam0 >> 20, __cam1 >> 20, __cam2 >> 20,
+ 			(total_lowmem - __cam0 - __cam1 - __cam2) >> 20);
+-	__max_low_memory = max_low_mem = __cam0 + __cam1 + __cam2;
+-	__initial_memory_limit = __max_low_memory;
++	__max_low_memory = __cam0 + __cam1 + __cam2;
++	__initial_memory_limit_addr = memstart_addr + __max_low_memory;
+ }
+diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S
+index e10d76a..ddeaf9e 100644
+--- a/arch/powerpc/mm/hash_low_32.S
++++ b/arch/powerpc/mm/hash_low_32.S
+@@ -191,7 +191,7 @@ _GLOBAL(add_hash_page)
+ 	add	r3,r3,r0		/* note create_hpte trims to 24 bits */
+ 
+ #ifdef CONFIG_SMP
+-	rlwinm	r8,r1,0,0,18		/* use cpu number to make tag */
++	rlwinm	r8,r1,0,0,(31-THREAD_SHIFT) /* use cpu number to make tag */
+ 	lwz	r8,TI_CPU(r8)		/* to go in mmu_hash_lock */
+ 	oris	r8,r8,12
+ #endif /* CONFIG_SMP */
+@@ -526,7 +526,7 @@ _GLOBAL(flush_hash_pages)
+ #ifdef CONFIG_SMP
+ 	addis	r9,r7,mmu_hash_lock at ha
+ 	addi	r9,r9,mmu_hash_lock at l
+-	rlwinm	r8,r1,0,0,18
++	rlwinm	r8,r1,0,0,(31-THREAD_SHIFT)
+ 	add	r8,r8,r7
+ 	lwz	r8,TI_CPU(r8)
+ 	oris	r8,r8,9
+diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
+index a83dfa3..2b5a399 100644
+--- a/arch/powerpc/mm/hash_utils_64.c
++++ b/arch/powerpc/mm/hash_utils_64.c
+@@ -31,6 +31,7 @@
+ #include <linux/cache.h>
+ #include <linux/init.h>
+ #include <linux/signal.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/pgtable.h>
+@@ -41,7 +42,7 @@
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/machdep.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/abs_addr.h>
+ #include <asm/tlbflush.h>
+ #include <asm/io.h>
+@@ -191,6 +192,29 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
+ 	return ret < 0 ? ret : 0;
+ }
+ 
++#ifdef CONFIG_MEMORY_HOTPLUG
++static int htab_remove_mapping(unsigned long vstart, unsigned long vend,
++		      int psize, int ssize)
++{
++	unsigned long vaddr;
++	unsigned int step, shift;
++
++	shift = mmu_psize_defs[psize].shift;
++	step = 1 << shift;
++
++	if (!ppc_md.hpte_removebolted) {
++		printk(KERN_WARNING "Platform doesn't implement "
++				"hpte_removebolted\n");
++		return -EINVAL;
++	}
++
++	for (vaddr = vstart; vaddr < vend; vaddr += step)
++		ppc_md.hpte_removebolted(vaddr, psize, ssize);
++
++	return 0;
++}
++#endif /* CONFIG_MEMORY_HOTPLUG */
++
+ static int __init htab_dt_scan_seg_sizes(unsigned long node,
+ 					 const char *uname, int depth,
+ 					 void *data)
+@@ -434,6 +458,12 @@ void create_section_mapping(unsigned long start, unsigned long end)
+ 			_PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX,
+ 			mmu_linear_psize, mmu_kernel_ssize));
+ }
++
++int remove_section_mapping(unsigned long start, unsigned long end)
++{
++	return htab_remove_mapping(start, end, mmu_linear_psize,
++			mmu_kernel_ssize);
++}
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+ 
+ static inline void make_bl(unsigned int *insn_addr, void *func)
+diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
+index 977cb1e..1952b4d 100644
+--- a/arch/powerpc/mm/init_32.c
++++ b/arch/powerpc/mm/init_32.c
+@@ -30,6 +30,7 @@
+ #include <linux/highmem.h>
+ #include <linux/initrd.h>
+ #include <linux/pagemap.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/pgalloc.h>
+ #include <asm/prom.h>
+@@ -41,7 +42,6 @@
+ #include <asm/machdep.h>
+ #include <asm/btext.h>
+ #include <asm/tlb.h>
+-#include <asm/lmb.h>
+ #include <asm/sections.h>
+ 
+ #include "mmu_decl.h"
+@@ -59,8 +59,11 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ unsigned long total_memory;
+ unsigned long total_lowmem;
+ 
+-unsigned long ppc_memstart;
+-unsigned long ppc_memoffset = PAGE_OFFSET;
++phys_addr_t memstart_addr = (phys_addr_t)~0ull;
++EXPORT_SYMBOL(memstart_addr);
++phys_addr_t kernstart_addr;
++EXPORT_SYMBOL(kernstart_addr);
++phys_addr_t lowmem_end_addr;
+ 
+ int boot_mapsize;
+ #ifdef CONFIG_PPC_PMAC
+@@ -68,14 +71,6 @@ unsigned long agp_special_page;
+ EXPORT_SYMBOL(agp_special_page);
+ #endif
+ 
+-#ifdef CONFIG_HIGHMEM
+-pte_t *kmap_pte;
+-pgprot_t kmap_prot;
+-
+-EXPORT_SYMBOL(kmap_prot);
+-EXPORT_SYMBOL(kmap_pte);
+-#endif
+-
+ void MMU_init(void);
+ 
+ /* XXX should be in current.h  -- paulus */
+@@ -95,10 +90,10 @@ int __map_without_ltlbs;
+ unsigned long __max_low_memory = MAX_LOW_MEM;
+ 
+ /*
+- * limit of what is accessible with initial MMU setup -
++ * address of the limit of what is accessible with initial MMU setup -
+  * 256MB usually, but only 16MB on 601.
+  */
+-unsigned long __initial_memory_limit = 0x10000000;
++phys_addr_t __initial_memory_limit_addr = (phys_addr_t)0x10000000;
+ 
+ /*
+  * Check for command-line options that affect what MMU_init will do.
+@@ -131,10 +126,10 @@ void __init MMU_init(void)
+ 
+ 	/* 601 can only access 16MB at the moment */
+ 	if (PVR_VER(mfspr(SPRN_PVR)) == 1)
+-		__initial_memory_limit = 0x01000000;
++		__initial_memory_limit_addr = 0x01000000;
+ 	/* 8xx can only access 8MB at the moment */
+ 	if (PVR_VER(mfspr(SPRN_PVR)) == 0x50)
+-		__initial_memory_limit = 0x00800000;
++		__initial_memory_limit_addr = 0x00800000;
+ 
+ 	/* parse args from command line */
+ 	MMU_setup();
+@@ -145,8 +140,8 @@ void __init MMU_init(void)
+ 		printk(KERN_WARNING "Only using first contiguous memory region");
+ 	}
+ 
+-	total_memory = lmb_end_of_DRAM();
+-	total_lowmem = total_memory;
++	total_lowmem = total_memory = lmb_end_of_DRAM() - memstart_addr;
++	lowmem_end_addr = memstart_addr + total_lowmem;
+ 
+ #ifdef CONFIG_FSL_BOOKE
+ 	/* Freescale Book-E parts expect lowmem to be mapped by fixed TLB
+@@ -157,9 +152,10 @@ void __init MMU_init(void)
+ 
+ 	if (total_lowmem > __max_low_memory) {
+ 		total_lowmem = __max_low_memory;
++		lowmem_end_addr = memstart_addr + total_lowmem;
+ #ifndef CONFIG_HIGHMEM
+ 		total_memory = total_lowmem;
+-		lmb_enforce_memory_limit(total_lowmem);
++		lmb_enforce_memory_limit(lowmem_end_addr);
+ 		lmb_analyze();
+ #endif /* CONFIG_HIGHMEM */
+ 	}
+@@ -184,8 +180,6 @@ void __init MMU_init(void)
+ 	/* Map in I/O resources */
+ 	if (ppc_md.progress)
+ 		ppc_md.progress("MMU:setio", 0x302);
+-	if (ppc_md.setup_io_mappings)
+-		ppc_md.setup_io_mappings();
+ 
+ 	/* Initialize the context management stuff */
+ 	mmu_context_init();
+@@ -208,7 +202,7 @@ void __init *early_get_page(void)
+ 		p = alloc_bootmem_pages(PAGE_SIZE);
+ 	} else {
+ 		p = __va(lmb_alloc_base(PAGE_SIZE, PAGE_SIZE,
+-					__initial_memory_limit));
++					__initial_memory_limit_addr));
+ 	}
+ 	return p;
+ }
+@@ -276,7 +270,7 @@ static int __init setup_kcore(void)
+ 
+ 		kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC);
+ 		if (!kcore_mem)
+-			panic("%s: kmalloc failed\n", __FUNCTION__);
++			panic("%s: kmalloc failed\n", __func__);
+ 
+ 		/* must stay under 32 bits */
+ 		if ( 0xfffffffful - (unsigned long)__va(base) < size) {
+diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
+index c0f5cff..c5ac532 100644
+--- a/arch/powerpc/mm/init_64.c
++++ b/arch/powerpc/mm/init_64.c
+@@ -38,11 +38,11 @@
+ #include <linux/nodemask.h>
+ #include <linux/module.h>
+ #include <linux/poison.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/pgalloc.h>
+ #include <asm/page.h>
+ #include <asm/prom.h>
+-#include <asm/lmb.h>
+ #include <asm/rtas.h>
+ #include <asm/io.h>
+ #include <asm/mmu_context.h>
+@@ -72,8 +72,8 @@
+ #warning TASK_SIZE is smaller than it needs to be.
+ #endif
+ 
+-/* max amount of RAM to use */
+-unsigned long __max_memory;
++phys_addr_t memstart_addr = ~0;
++phys_addr_t kernstart_addr;
+ 
+ void free_initmem(void)
+ {
+@@ -122,7 +122,7 @@ static int __init setup_kcore(void)
+ 		/* GFP_ATOMIC to avoid might_sleep warnings during boot */
+ 		kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC);
+ 		if (!kcore_mem)
+-			panic("%s: kmalloc failed\n", __FUNCTION__);
++			panic("%s: kmalloc failed\n", __func__);
+ 
+ 		kclist_add(kcore_mem, __va(base), size);
+ 	}
+diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c
+deleted file mode 100644
+index 4ce23bc..0000000
+--- a/arch/powerpc/mm/lmb.c
++++ /dev/null
+@@ -1,357 +0,0 @@
+-/*
+- * Procedures for maintaining information about logical memory blocks.
+- *
+- * Peter Bergner, IBM Corp.	June 2001.
+- * Copyright (C) 2001 Peter Bergner.
+- * 
+- *      This program is free software; you can redistribute it and/or
+- *      modify it under the terms of the GNU General Public License
+- *      as published by the Free Software Foundation; either version
+- *      2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/bitops.h>
+-#include <asm/types.h>
+-#include <asm/page.h>
+-#include <asm/prom.h>
+-#include <asm/lmb.h>
+-#ifdef CONFIG_PPC32
+-#include "mmu_decl.h"		/* for __max_low_memory */
+-#endif
+-
+-#undef DEBUG
+-
+-#ifdef DEBUG
+-#include <asm/udbg.h>
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-#define LMB_ALLOC_ANYWHERE	0
+-
+-struct lmb lmb;
+-
+-void lmb_dump_all(void)
+-{
+-#ifdef DEBUG
+-	unsigned long i;
+-
+-	DBG("lmb_dump_all:\n");
+-	DBG("    memory.cnt		  = 0x%lx\n", lmb.memory.cnt);
+-	DBG("    memory.size		  = 0x%lx\n", lmb.memory.size);
+-	for (i=0; i < lmb.memory.cnt ;i++) {
+-		DBG("    memory.region[0x%x].base       = 0x%lx\n",
+-			    i, lmb.memory.region[i].base);
+-		DBG("		      .size     = 0x%lx\n",
+-			    lmb.memory.region[i].size);
+-	}
+-
+-	DBG("\n    reserved.cnt	  = 0x%lx\n", lmb.reserved.cnt);
+-	DBG("    reserved.size	  = 0x%lx\n", lmb.reserved.size);
+-	for (i=0; i < lmb.reserved.cnt ;i++) {
+-		DBG("    reserved.region[0x%x].base       = 0x%lx\n",
+-			    i, lmb.reserved.region[i].base);
+-		DBG("		      .size     = 0x%lx\n",
+-			    lmb.reserved.region[i].size);
+-	}
+-#endif /* DEBUG */
+-}
+-
+-static unsigned long __init lmb_addrs_overlap(unsigned long base1,
+-		unsigned long size1, unsigned long base2, unsigned long size2)
+-{
+-	return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
+-}
+-
+-static long __init lmb_addrs_adjacent(unsigned long base1, unsigned long size1,
+-		unsigned long base2, unsigned long size2)
+-{
+-	if (base2 == base1 + size1)
+-		return 1;
+-	else if (base1 == base2 + size2)
+-		return -1;
+-
+-	return 0;
+-}
+-
+-static long __init lmb_regions_adjacent(struct lmb_region *rgn,
+-		unsigned long r1, unsigned long r2)
+-{
+-	unsigned long base1 = rgn->region[r1].base;
+-	unsigned long size1 = rgn->region[r1].size;
+-	unsigned long base2 = rgn->region[r2].base;
+-	unsigned long size2 = rgn->region[r2].size;
+-
+-	return lmb_addrs_adjacent(base1, size1, base2, size2);
+-}
+-
+-static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
+-{
+-	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;
+-	}
+-	rgn->cnt--;
+-}
+-
+-/* Assumption: base addr of region 1 < base addr of region 2 */
+-static void __init lmb_coalesce_regions(struct lmb_region *rgn,
+-		unsigned long r1, unsigned long r2)
+-{
+-	rgn->region[r1].size += rgn->region[r2].size;
+-	lmb_remove_region(rgn, r2);
+-}
+-
+-/* This routine called with relocation disabled. */
+-void __init lmb_init(void)
+-{
+-	/* Create a dummy zero size LMB which will get coalesced away later.
+-	 * This simplifies the lmb_add() code below...
+-	 */
+-	lmb.memory.region[0].base = 0;
+-	lmb.memory.region[0].size = 0;
+-	lmb.memory.cnt = 1;
+-
+-	/* Ditto. */
+-	lmb.reserved.region[0].base = 0;
+-	lmb.reserved.region[0].size = 0;
+-	lmb.reserved.cnt = 1;
+-}
+-
+-/* This routine may be called with relocation disabled. */
+-void __init lmb_analyze(void)
+-{
+-	int i;
+-
+-	lmb.memory.size = 0;
+-
+-	for (i = 0; i < lmb.memory.cnt; i++)
+-		lmb.memory.size += lmb.memory.region[i].size;
+-}
+-
+-/* This routine called with relocation disabled. */
+-static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base,
+-				  unsigned long size)
+-{
+-	unsigned long coalesced = 0;
+-	long adjacent, i;
+-
+-	/* First try and coalesce this LMB with another. */
+-	for (i=0; i < rgn->cnt; i++) {
+-		unsigned long rgnbase = rgn->region[i].base;
+-		unsigned long rgnsize = rgn->region[i].size;
+-
+-		if ((rgnbase == base) && (rgnsize == size))
+-			/* Already have this region, so we're done */
+-			return 0;
+-
+-		adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);
+-		if ( adjacent > 0 ) {
+-			rgn->region[i].base -= size;
+-			rgn->region[i].size += size;
+-			coalesced++;
+-			break;
+-		}
+-		else if ( adjacent < 0 ) {
+-			rgn->region[i].size += size;
+-			coalesced++;
+-			break;
+-		}
+-	}
+-
+-	if ((i < rgn->cnt-1) && lmb_regions_adjacent(rgn, i, i+1) ) {
+-		lmb_coalesce_regions(rgn, i, i+1);
+-		coalesced++;
+-	}
+-
+-	if (coalesced)
+-		return coalesced;
+-	if (rgn->cnt >= MAX_LMB_REGIONS)
+-		return -1;
+-
+-	/* Couldn't coalesce the LMB, 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;
+-		} else {
+-			rgn->region[i+1].base = base;
+-			rgn->region[i+1].size = size;
+-			break;
+-		}
+-	}
+-	rgn->cnt++;
+-
+-	return 0;
+-}
+-
+-/* This routine may be called with relocation disabled. */
+-long __init lmb_add(unsigned long base, unsigned long size)
+-{
+-	struct lmb_region *_rgn = &(lmb.memory);
+-
+-	/* On pSeries LPAR systems, the first LMB is our RMO region. */
+-	if (base == 0)
+-		lmb.rmo_size = size;
+-
+-	return lmb_add_region(_rgn, base, size);
+-
+-}
+-
+-long __init lmb_reserve(unsigned long base, unsigned long size)
+-{
+-	struct lmb_region *_rgn = &(lmb.reserved);
+-
+-	BUG_ON(0 == size);
+-
+-	return lmb_add_region(_rgn, base, size);
+-}
+-
+-long __init lmb_overlaps_region(struct lmb_region *rgn, unsigned long base,
+-				unsigned long size)
+-{
+-	unsigned long i;
+-
+-	for (i=0; i < rgn->cnt; i++) {
+-		unsigned long rgnbase = rgn->region[i].base;
+-		unsigned long rgnsize = rgn->region[i].size;
+-		if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) {
+-			break;
+-		}
+-	}
+-
+-	return (i < rgn->cnt) ? i : -1;
+-}
+-
+-unsigned long __init lmb_alloc(unsigned long size, unsigned long align)
+-{
+-	return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
+-}
+-
+-unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align,
+-				    unsigned long max_addr)
+-{
+-	unsigned long alloc;
+-
+-	alloc = __lmb_alloc_base(size, align, max_addr);
+-
+-	if (alloc == 0)
+-		panic("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n",
+-				size, max_addr);
+-
+-	return alloc;
+-}
+-
+-unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align,
+-				    unsigned long max_addr)
+-{
+-	long i, j;
+-	unsigned long base = 0;
+-
+-	BUG_ON(0 == size);
+-
+-#ifdef CONFIG_PPC32
+-	/* On 32-bit, make sure we allocate lowmem */
+-	if (max_addr == LMB_ALLOC_ANYWHERE)
+-		max_addr = __max_low_memory;
+-#endif
+-	for (i = lmb.memory.cnt-1; i >= 0; i--) {
+-		unsigned long lmbbase = lmb.memory.region[i].base;
+-		unsigned long lmbsize = lmb.memory.region[i].size;
+-
+-		if (max_addr == LMB_ALLOC_ANYWHERE)
+-			base = _ALIGN_DOWN(lmbbase + lmbsize - size, align);
+-		else if (lmbbase < max_addr) {
+-			base = min(lmbbase + lmbsize, max_addr);
+-			base = _ALIGN_DOWN(base - size, align);
+-		} else
+-			continue;
+-
+-		while ((lmbbase <= base) &&
+-		       ((j = lmb_overlaps_region(&lmb.reserved, base, size)) >= 0) )
+-			base = _ALIGN_DOWN(lmb.reserved.region[j].base - size,
+-					   align);
+-
+-		if ((base != 0) && (lmbbase <= base))
+-			break;
+-	}
+-
+-	if (i < 0)
+-		return 0;
+-
+-	lmb_add_region(&lmb.reserved, base, size);
+-
+-	return base;
+-}
+-
+-/* You must call lmb_analyze() before this. */
+-unsigned long __init lmb_phys_mem_size(void)
+-{
+-	return lmb.memory.size;
+-}
+-
+-unsigned long __init lmb_end_of_DRAM(void)
+-{
+-	int idx = lmb.memory.cnt - 1;
+-
+-	return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
+-}
+-
+-/* You must call lmb_analyze() after this. */
+-void __init lmb_enforce_memory_limit(unsigned long memory_limit)
+-{
+-	unsigned long i, limit;
+-	struct lmb_property *p;
+-
+-	if (! memory_limit)
+-		return;
+-
+-	/* Truncate the lmb regions to satisfy the memory limit. */
+-	limit = memory_limit;
+-	for (i = 0; i < lmb.memory.cnt; i++) {
+-		if (limit > lmb.memory.region[i].size) {
+-			limit -= lmb.memory.region[i].size;
+-			continue;
+-		}
+-
+-		lmb.memory.region[i].size = limit;
+-		lmb.memory.cnt = i + 1;
+-		break;
+-	}
+-
+-	if (lmb.memory.region[0].size < lmb.rmo_size)
+-		lmb.rmo_size = lmb.memory.region[0].size;
+-
+-	/* And truncate any reserves above the limit also. */
+-	for (i = 0; i < lmb.reserved.cnt; i++) {
+-		p = &lmb.reserved.region[i];
+-
+-		if (p->base > memory_limit)
+-			p->size = 0;
+-		else if ((p->base + p->size) > memory_limit)
+-			p->size = memory_limit - p->base;
+-
+-		if (p->size == 0) {
+-			lmb_remove_region(&lmb.reserved, i);
+-			i--;
+-		}
+-	}
+-}
+-
+-int __init lmb_is_reserved(unsigned long addr)
+-{
+-	int i;
+-
+-	for (i = 0; i < lmb.reserved.cnt; i++) {
+-		unsigned long upper = lmb.reserved.region[i].base +
+-				      lmb.reserved.region[i].size - 1;
+-		if ((addr >= lmb.reserved.region[i].base) && (addr <= upper))
+-			return 1;
+-	}
+-	return 0;
+-}
+diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
+index be5c506..5ccb579 100644
+--- a/arch/powerpc/mm/mem.c
++++ b/arch/powerpc/mm/mem.c
+@@ -31,6 +31,7 @@
+ #include <linux/initrd.h>
+ #include <linux/pagemap.h>
+ #include <linux/suspend.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/pgalloc.h>
+ #include <asm/prom.h>
+@@ -42,9 +43,9 @@
+ #include <asm/machdep.h>
+ #include <asm/btext.h>
+ #include <asm/tlb.h>
+-#include <asm/lmb.h>
+ #include <asm/sections.h>
+ #include <asm/vdso.h>
++#include <asm/fixmap.h>
+ 
+ #include "mmu_decl.h"
+ 
+@@ -57,6 +58,20 @@ int init_bootmem_done;
+ int mem_init_done;
+ unsigned long memory_limit;
+ 
++#ifdef CONFIG_HIGHMEM
++pte_t *kmap_pte;
++pgprot_t kmap_prot;
++
++EXPORT_SYMBOL(kmap_prot);
++EXPORT_SYMBOL(kmap_pte);
++
++static inline pte_t *virt_to_kpte(unsigned long vaddr)
++{
++	return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr),
++			vaddr), vaddr), vaddr);
++}
++#endif
++
+ int page_is_ram(unsigned long pfn)
+ {
+ 	unsigned long paddr = (pfn << PAGE_SHIFT);
+@@ -111,7 +126,7 @@ int memory_add_physaddr_to_nid(u64 start)
+ }
+ #endif
+ 
+-int __devinit arch_add_memory(int nid, u64 start, u64 size)
++int arch_add_memory(int nid, u64 start, u64 size)
+ {
+ 	struct pglist_data *pgdata;
+ 	struct zone *zone;
+@@ -175,7 +190,6 @@ void show_mem(void)
+ 
+ 	printk("Mem-info:\n");
+ 	show_free_areas();
+-	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ 	for_each_online_pgdat(pgdat) {
+ 		unsigned long flags;
+ 		pgdat_resize_lock(pgdat, &flags);
+@@ -217,9 +231,11 @@ void __init do_init_bootmem(void)
+ 	unsigned long total_pages;
+ 	int boot_mapsize;
+ 
+-	max_pfn = total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT;
++	max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
++	total_pages = (lmb_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT;
+ #ifdef CONFIG_HIGHMEM
+ 	total_pages = total_lowmem >> PAGE_SHIFT;
++	max_low_pfn = lowmem_end_addr >> PAGE_SHIFT;
+ #endif
+ 
+ 	/*
+@@ -231,7 +247,8 @@ void __init do_init_bootmem(void)
+ 
+ 	start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
+ 
+-	boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
++	min_low_pfn = MEMORY_START >> PAGE_SHIFT;
++	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 < lmb.memory.cnt; i++) {
+@@ -245,18 +262,18 @@ void __init do_init_bootmem(void)
+ 	 * present.
+ 	 */
+ #ifdef CONFIG_HIGHMEM
+-	free_bootmem_with_active_regions(0, total_lowmem >> PAGE_SHIFT);
++	free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT);
+ 
+ 	/* reserve the sections we're already using */
+ 	for (i = 0; i < lmb.reserved.cnt; i++) {
+ 		unsigned long addr = lmb.reserved.region[i].base +
+ 				     lmb_size_bytes(&lmb.reserved, i) - 1;
+-		if (addr < total_lowmem)
++		if (addr < lowmem_end_addr)
+ 			reserve_bootmem(lmb.reserved.region[i].base,
+ 					lmb_size_bytes(&lmb.reserved, i),
+ 					BOOTMEM_DEFAULT);
+-		else if (lmb.reserved.region[i].base < total_lowmem) {
+-			unsigned long adjusted_size = total_lowmem -
++		else if (lmb.reserved.region[i].base < lowmem_end_addr) {
++			unsigned long adjusted_size = lowmem_end_addr -
+ 				      lmb.reserved.region[i].base;
+ 			reserve_bootmem(lmb.reserved.region[i].base,
+ 					adjusted_size, BOOTMEM_DEFAULT);
+@@ -309,14 +326,19 @@ void __init paging_init(void)
+ 	unsigned long top_of_ram = lmb_end_of_DRAM();
+ 	unsigned long max_zone_pfns[MAX_NR_ZONES];
+ 
++#ifdef CONFIG_PPC32
++	unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
++	unsigned long end = __fix_to_virt(FIX_HOLE);
++
++	for (; v < end; v += PAGE_SIZE)
++		map_page(v, 0, 0); /* XXX gross */
++#endif
++
+ #ifdef CONFIG_HIGHMEM
+ 	map_page(PKMAP_BASE, 0, 0);	/* XXX gross */
+-	pkmap_page_table = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
+-			(PKMAP_BASE), PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
+-	map_page(KMAP_FIX_BEGIN, 0, 0);	/* XXX gross */
+-	kmap_pte = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
+-			(KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN),
+-			 KMAP_FIX_BEGIN);
++	pkmap_page_table = virt_to_kpte(PKMAP_BASE);
++
++	kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
+ 	kmap_prot = PAGE_KERNEL;
+ #endif /* CONFIG_HIGHMEM */
+ 
+@@ -326,7 +348,7 @@ void __init paging_init(void)
+ 	       (top_of_ram - total_ram) >> 20);
+ 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ #ifdef CONFIG_HIGHMEM
+-	max_zone_pfns[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
++	max_zone_pfns[ZONE_DMA] = lowmem_end_addr >> PAGE_SHIFT;
+ 	max_zone_pfns[ZONE_HIGHMEM] = top_of_ram >> PAGE_SHIFT;
+ #else
+ 	max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
+@@ -381,7 +403,7 @@ void __init mem_init(void)
+ 	{
+ 		unsigned long pfn, highmem_mapnr;
+ 
+-		highmem_mapnr = total_lowmem >> PAGE_SHIFT;
++		highmem_mapnr = lowmem_end_addr >> PAGE_SHIFT;
+ 		for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
+ 			struct page *page = pfn_to_page(pfn);
+ 			if (lmb_is_reserved(pfn << PAGE_SHIFT))
+diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
+index ebfd13d..0480225 100644
+--- a/arch/powerpc/mm/mmu_decl.h
++++ b/arch/powerpc/mm/mmu_decl.h
+@@ -48,9 +48,11 @@ extern unsigned int num_tlbcam_entries;
+ 
+ extern unsigned long ioremap_bot;
+ extern unsigned long __max_low_memory;
+-extern unsigned long __initial_memory_limit;
++extern phys_addr_t __initial_memory_limit_addr;
+ extern unsigned long total_memory;
+ extern unsigned long total_lowmem;
++extern phys_addr_t memstart_addr;
++extern phys_addr_t lowmem_end_addr;
+ 
+ /* ...and now those things that may be slightly different between processor
+  * architectures.  -- Dan
+diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
+index a300d25..dc704da 100644
+--- a/arch/powerpc/mm/numa.c
++++ b/arch/powerpc/mm/numa.c
+@@ -17,8 +17,10 @@
+ #include <linux/nodemask.h>
+ #include <linux/cpu.h>
+ #include <linux/notifier.h>
++#include <linux/lmb.h>
++#include <linux/of.h>
+ #include <asm/sparsemem.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/system.h>
+ #include <asm/smp.h>
+ 
+diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
+index ac3390f..80d1bab 100644
+--- a/arch/powerpc/mm/pgtable_32.c
++++ b/arch/powerpc/mm/pgtable_32.c
+@@ -29,6 +29,7 @@
+ 
+ #include <asm/pgtable.h>
+ #include <asm/pgalloc.h>
++#include <asm/fixmap.h>
+ #include <asm/io.h>
+ 
+ #include "mmu_decl.h"
+@@ -281,12 +282,13 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
+  */
+ void __init mapin_ram(void)
+ {
+-	unsigned long v, p, s, f;
++	unsigned long v, s, f;
++	phys_addr_t p;
+ 	int ktext;
+ 
+ 	s = mmu_mapin_ram();
+ 	v = KERNELBASE + s;
+-	p = PPC_MEMSTART + s;
++	p = memstart_addr + s;
+ 	for (; s < total_lowmem; s += PAGE_SIZE) {
+ 		ktext = ((char *) v >= _stext && (char *) v < etext);
+ 		f = ktext ?_PAGE_RAM_TEXT : _PAGE_RAM;
+@@ -386,3 +388,25 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
+ 	change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
+ }
+ #endif /* CONFIG_DEBUG_PAGEALLOC */
++
++static int fixmaps;
++unsigned long FIXADDR_TOP = 0xfffff000;
++EXPORT_SYMBOL(FIXADDR_TOP);
++
++void __set_fixmap (enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
++{
++	unsigned long address = __fix_to_virt(idx);
++
++	if (idx >= __end_of_fixed_addresses) {
++		BUG();
++		return;
++	}
++
++	map_page(address, phys, flags);
++	fixmaps++;
++}
++
++void __this_fixmap_does_not_exist(void)
++{
++	WARN_ON(1);
++}
+diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
+index 5c45d47..cef9f15 100644
+--- a/arch/powerpc/mm/ppc_mmu_32.c
++++ b/arch/powerpc/mm/ppc_mmu_32.c
+@@ -26,11 +26,11 @@
+ #include <linux/mm.h>
+ #include <linux/init.h>
+ #include <linux/highmem.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/prom.h>
+ #include <asm/mmu.h>
+ #include <asm/machdep.h>
+-#include <asm/lmb.h>
+ 
+ #include "mmu_decl.h"
+ 
+@@ -82,7 +82,6 @@ unsigned long __init mmu_mapin_ram(void)
+ #else
+ 	unsigned long tot, bl, done;
+ 	unsigned long max_size = (256<<20);
+-	unsigned long align;
+ 
+ 	if (__map_without_bats) {
+ 		printk(KERN_DEBUG "RAM mapped without BATs\n");
+@@ -93,19 +92,13 @@ unsigned long __init mmu_mapin_ram(void)
+ 
+ 	/* Make sure we don't map a block larger than the
+ 	   smallest alignment of the physical address. */
+-	/* alignment of PPC_MEMSTART */
+-	align = ~(PPC_MEMSTART-1) & PPC_MEMSTART;
+-	/* set BAT block size to MIN(max_size, align) */
+-	if (align && align < max_size)
+-		max_size = align;
+-
+ 	tot = total_lowmem;
+ 	for (bl = 128<<10; bl < max_size; bl <<= 1) {
+ 		if (bl * 2 > tot)
+ 			break;
+ 	}
+ 
+-	setbat(2, KERNELBASE, PPC_MEMSTART, bl, _PAGE_RAM);
++	setbat(2, KERNELBASE, 0, bl, _PAGE_RAM);
+ 	done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
+ 	if ((done < tot) && !bat_addrs[3].limit) {
+ 		/* use BAT3 to cover a bit more */
+@@ -113,7 +106,7 @@ unsigned long __init mmu_mapin_ram(void)
+ 		for (bl = 128<<10; bl < max_size; bl <<= 1)
+ 			if (bl * 2 > tot)
+ 				break;
+-		setbat(3, KERNELBASE+done, PPC_MEMSTART+done, bl, _PAGE_RAM);
++		setbat(3, KERNELBASE+done, done, bl, _PAGE_RAM);
+ 		done = (unsigned long)bat_addrs[3].limit - KERNELBASE + 1;
+ 	}
+ 
+@@ -240,7 +233,7 @@ void __init MMU_init_hw(void)
+ 	 */
+ 	if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
+ 	Hash = __va(lmb_alloc_base(Hash_size, Hash_size,
+-				   __initial_memory_limit));
++				   __initial_memory_limit_addr));
+ 	cacheable_memzero(Hash, Hash_size);
+ 	_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
+ 
+diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
+index 50448d5..efbbd13 100644
+--- a/arch/powerpc/mm/stab.c
++++ b/arch/powerpc/mm/stab.c
+@@ -12,12 +12,14 @@
+  *      2 of the License, or (at your option) any later version.
+  */
+ 
++#include <linux/lmb.h>
++
+ #include <asm/pgtable.h>
+ #include <asm/mmu.h>
+ #include <asm/mmu_context.h>
+ #include <asm/paca.h>
+ #include <asm/cputable.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/abs_addr.h>
+ #include <asm/firmware.h>
+ #include <asm/iseries/hv_call.h>
+diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c
+index 257b13c..2a9b4a0 100644
+--- a/arch/powerpc/oprofile/cell/spu_task_sync.c
++++ b/arch/powerpc/oprofile/cell/spu_task_sync.c
+@@ -68,7 +68,7 @@ static struct cached_info *get_cached_info(struct spu *the_spu, int spu_num)
+ 	if (spu_num >= num_spu_nodes) {
+ 		printk(KERN_ERR "SPU_PROF: "
+ 		       "%s, line %d: Invalid index %d into spu info cache\n",
+-		       __FUNCTION__, __LINE__, spu_num);
++		       __func__, __LINE__, spu_num);
+ 		ret_info = NULL;
+ 		goto out;
+ 	}
+@@ -115,7 +115,7 @@ prepare_cached_spu_info(struct spu *spu, unsigned long objectId)
+ 	if (!info) {
+ 		printk(KERN_ERR "SPU_PROF: "
+ 		       "%s, line %d: create vma_map failed\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		retval = -ENOMEM;
+ 		goto err_alloc;
+ 	}
+@@ -123,7 +123,7 @@ prepare_cached_spu_info(struct spu *spu, unsigned long objectId)
+ 	if (!new_map) {
+ 		printk(KERN_ERR "SPU_PROF: "
+ 		       "%s, line %d: create vma_map failed\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		retval = -ENOMEM;
+ 		goto err_alloc;
+ 	}
+@@ -171,7 +171,7 @@ static int release_cached_info(int spu_index)
+ 			printk(KERN_ERR "SPU_PROF: "
+ 				"%s, line %d: "
+ 				"Invalid index %d into spu info cache\n",
+-				__FUNCTION__, __LINE__, spu_index);
++				__func__, __LINE__, spu_index);
+ 			goto out;
+ 		}
+ 		end = spu_index + 1;
+@@ -273,7 +273,7 @@ fail_no_image_cookie:
+ 
+ 	printk(KERN_ERR "SPU_PROF: "
+ 		"%s, line %d: Cannot find dcookie for SPU binary\n",
+-		__FUNCTION__, __LINE__);
++		__func__, __LINE__);
+ 	goto out;
+ }
+ 
+@@ -467,7 +467,7 @@ int spu_sync_stop(void)
+ 	if (ret) {
+ 		printk(KERN_ERR "SPU_PROF: "
+ 			"%s, line %d: spu_switch_event_unregister returned %d\n",
+-			__FUNCTION__, __LINE__, ret);
++			__func__, __LINE__, ret);
+ 		goto out;
+ 	}
+ 
+diff --git a/arch/powerpc/oprofile/cell/vma_map.c b/arch/powerpc/oprofile/cell/vma_map.c
+index 9a93217..fff6666 100644
+--- a/arch/powerpc/oprofile/cell/vma_map.c
++++ b/arch/powerpc/oprofile/cell/vma_map.c
+@@ -72,7 +72,7 @@ vma_map_add(struct vma_to_fileoffset_map *map, unsigned int vma,
+ 		kzalloc(sizeof(struct vma_to_fileoffset_map), GFP_KERNEL);
+ 	if (!new) {
+ 		printk(KERN_ERR "SPU_PROF: %s, line %d: malloc failed\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		vma_map_free(map);
+ 		return NULL;
+ 	}
+@@ -134,19 +134,19 @@ struct vma_to_fileoffset_map *create_vma_map(const struct spu *aSpu,
+ 	if (memcmp(ehdr.e_ident, expected, EI_PAD) != 0) {
+ 		printk(KERN_ERR "SPU_PROF: "
+ 		       "%s, line %d: Unexpected e_ident parsing SPU ELF\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		goto fail;
+ 	}
+ 	if (ehdr.e_machine != EM_SPU) {
+ 		printk(KERN_ERR "SPU_PROF: "
+ 		       "%s, line %d: Unexpected e_machine parsing SPU ELF\n",
+-		       __FUNCTION__,  __LINE__);
++		       __func__,  __LINE__);
+ 		goto fail;
+ 	}
+ 	if (ehdr.e_type != ET_EXEC) {
+ 		printk(KERN_ERR "SPU_PROF: "
+ 		       "%s, line %d: Unexpected e_type parsing SPU ELF\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		goto fail;
+ 	}
+ 	phdr_start = spu_elf_start + ehdr.e_phoff;
+@@ -232,7 +232,7 @@ struct vma_to_fileoffset_map *create_vma_map(const struct spu *aSpu,
+ 	if (overlay_tbl_offset < 0) {
+ 		printk(KERN_ERR "SPU_PROF: "
+ 		       "%s, line %d: Error finding SPU overlay table\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		goto fail;
+ 	}
+ 	ovly_table = spu_elf_start + overlay_tbl_offset;
+diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
+index 9eed1f6..5ff4de3 100644
+--- a/arch/powerpc/oprofile/op_model_cell.c
++++ b/arch/powerpc/oprofile/op_model_cell.c
+@@ -216,7 +216,7 @@ static void pm_rtas_reset_signals(u32 node)
+ 		 * failure to stop OProfile.
+ 		 */
+ 		printk(KERN_WARNING "%s: rtas returned: %d\n",
+-		       __FUNCTION__, ret);
++		       __func__, ret);
+ }
+ 
+ static int pm_rtas_activate_signals(u32 node, u32 count)
+@@ -255,7 +255,7 @@ static int pm_rtas_activate_signals(u32 node, u32 count)
+ 
+ 		if (unlikely(ret)) {
+ 			printk(KERN_WARNING "%s: rtas returned: %d\n",
+-			       __FUNCTION__, ret);
++			       __func__, ret);
+ 			return -EIO;
+ 		}
+ 	}
+@@ -560,7 +560,7 @@ static int cell_reg_setup(struct op_counter_config *ctr,
+ 		if (unlikely(spu_rtas_token == RTAS_UNKNOWN_SERVICE)) {
+ 			printk(KERN_ERR
+ 			       "%s: rtas token ibm,cbe-spu-perftools unknown\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			return -EIO;
+ 		}
+ 	}
+@@ -576,7 +576,7 @@ static int cell_reg_setup(struct op_counter_config *ctr,
+ 	if (unlikely(pm_rtas_token == RTAS_UNKNOWN_SERVICE)) {
+ 		printk(KERN_ERR
+ 		       "%s: rtas token ibm,cbe-perftools unknown\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return -EIO;
+ 	}
+ 
+@@ -853,7 +853,7 @@ static int pm_rtas_activate_spu_profiling(u32 node)
+ 
+ 	if (unlikely(ret)) {
+ 		printk(KERN_WARNING "%s: rtas returned: %d\n",
+-		       __FUNCTION__, ret);
++		       __func__, ret);
+ 		return -EIO;
+ 	}
+ 
+@@ -949,7 +949,7 @@ static int cell_global_start_spu(struct op_counter_config *ctr)
+ 		if (unlikely(ret != 0)) {
+ 			printk(KERN_ERR
+ 			       "%s: rtas call ibm,cbe-spu-perftools failed, return = %d\n",
+-			       __FUNCTION__, ret);
++			       __func__, ret);
+ 			rtas_error = -EIO;
+ 			goto out;
+ 		}
+@@ -1061,7 +1061,7 @@ static void cell_global_stop_spu(void)
+ 		if (unlikely(rtn_value != 0)) {
+ 			printk(KERN_ERR
+ 			       "%s: rtas call ibm,cbe-spu-perftools failed, return = %d\n",
+-			       __FUNCTION__, rtn_value);
++			       __func__, rtn_value);
+ 		}
+ 
+ 		/* Deactivate the signals */
+diff --git a/arch/powerpc/platforms/40x/ep405.c b/arch/powerpc/platforms/40x/ep405.c
+index 13d1345..ae2e7f6 100644
+--- a/arch/powerpc/platforms/40x/ep405.c
++++ b/arch/powerpc/platforms/40x/ep405.c
+@@ -29,6 +29,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
+ 
+ static struct device_node *bcsr_node;
+ static void __iomem *bcsr_regs;
+@@ -119,5 +120,6 @@ define_machine(ep405) {
+ 	.progress		= udbg_progress,
+ 	.init_IRQ		= uic_init_tree,
+ 	.get_irq		= uic_get_irq,
++	.restart		= ppc4xx_reset_system,
+ 	.calibrate_decr		= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/40x/kilauea.c b/arch/powerpc/platforms/40x/kilauea.c
+index f9206a7..1dd24ff 100644
+--- a/arch/powerpc/platforms/40x/kilauea.c
++++ b/arch/powerpc/platforms/40x/kilauea.c
+@@ -1,7 +1,7 @@
+ /*
+  * Kilauea board specific routines
+  *
+- * Copyright 2007 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ * Copyright 2007-2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
+  *
+  * Based on the Walnut code by
+  * Josh Boyer <jwboyer at linux.vnet.ibm.com>
+@@ -20,6 +20,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id kilauea_of_bus[] = {
+ 	{ .compatible = "ibm,plb4", },
+@@ -54,5 +55,6 @@ define_machine(kilauea) {
+ 	.progress 			= udbg_progress,
+ 	.init_IRQ 			= uic_init_tree,
+ 	.get_irq 			= uic_get_irq,
++	.restart			= ppc4xx_reset_system,
+ 	.calibrate_decr			= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/40x/makalu.c b/arch/powerpc/platforms/40x/makalu.c
+index 4e4df72..a6a1d60 100644
+--- a/arch/powerpc/platforms/40x/makalu.c
++++ b/arch/powerpc/platforms/40x/makalu.c
+@@ -20,6 +20,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id makalu_of_bus[] = {
+ 	{ .compatible = "ibm,plb4", },
+@@ -54,5 +55,6 @@ define_machine(makalu) {
+ 	.progress 			= udbg_progress,
+ 	.init_IRQ 			= uic_init_tree,
+ 	.get_irq 			= uic_get_irq,
++	.restart			= ppc4xx_reset_system,
+ 	.calibrate_decr			= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c
+index 0422590..fc7fb00 100644
+--- a/arch/powerpc/platforms/40x/virtex.c
++++ b/arch/powerpc/platforms/40x/virtex.c
+@@ -14,6 +14,7 @@
+ #include <asm/prom.h>
+ #include <asm/time.h>
+ #include <asm/xilinx_intc.h>
++#include <asm/ppc4xx.h>
+ 
+ static struct of_device_id xilinx_of_bus_ids[] __initdata = {
+ 	{ .compatible = "xlnx,plb-v46-1.00.a", },
+@@ -48,5 +49,6 @@ define_machine(virtex) {
+ 	.probe			= virtex_probe,
+ 	.init_IRQ		= xilinx_intc_init_tree,
+ 	.get_irq		= xilinx_intc_get_irq,
++	.restart		= ppc4xx_reset_system,
+ 	.calibrate_decr		= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
+index b8b257e..335df91 100644
+--- a/arch/powerpc/platforms/40x/walnut.c
++++ b/arch/powerpc/platforms/40x/walnut.c
+@@ -26,6 +26,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id walnut_of_bus[] = {
+ 	{ .compatible = "ibm,plb3", },
+@@ -61,5 +62,6 @@ define_machine(walnut) {
+ 	.progress		= udbg_progress,
+ 	.init_IRQ		= uic_init_tree,
+ 	.get_irq		= uic_get_irq,
+-	.calibrate_decr	= generic_calibrate_decr,
++	.restart		= ppc4xx_reset_system,
++	.calibrate_decr		= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/44x.h b/arch/powerpc/platforms/44x/44x.h
+index 42eabf8..dbc4d2b 100644
+--- a/arch/powerpc/platforms/44x/44x.h
++++ b/arch/powerpc/platforms/44x/44x.h
+@@ -3,6 +3,5 @@
+ 
+ extern u8 as1_readb(volatile u8 __iomem  *addr);
+ extern void as1_writeb(u8 data, volatile u8 __iomem *addr);
+-extern void ppc44x_reset_system(char *cmd);
+ 
+ #endif /* __POWERPC_PLATFORMS_44X_44X_H */
+diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
+index 1bfb219..6abe913 100644
+--- a/arch/powerpc/platforms/44x/Kconfig
++++ b/arch/powerpc/platforms/44x/Kconfig
+@@ -67,6 +67,25 @@ config WARP
+ 	  See http://www.pikatechnologies.com/ and follow the "PIKA for Computer
+ 	  Telephony Developers" link for more information.
+ 
++config CANYONLANDS
++	bool "Canyonlands"
++	depends on 44x
++	default n
++	select 460EX
++	select PCI
++	select PPC4xx_PCI_EXPRESS
++	help
++	  This option enables support for the AMCC PPC460EX evaluation board.
++
++config YOSEMITE
++	bool "Yosemite"
++	depends on 44x
++	default n
++	select 440EP
++	select PCI
++	help
++	  This option enables support for the AMCC PPC440EP evaluation board.
++
+ #config LUAN
+ #	bool "Luan"
+ #	depends on 44x
+@@ -122,6 +141,14 @@ config 440SPe
+ 	bool
+ 	select IBM_NEW_EMAC_EMAC4
+ 
++config 460EX
++	bool
++	select PPC_FPU
++	select IBM_NEW_EMAC_EMAC4
++	select IBM_NEW_EMAC_RGMII
++	select IBM_NEW_EMAC_ZMII
++	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/Makefile b/arch/powerpc/platforms/44x/Makefile
+index 0864d4f..774165f 100644
+--- a/arch/powerpc/platforms/44x/Makefile
++++ b/arch/powerpc/platforms/44x/Makefile
+@@ -1,9 +1,11 @@
+-obj-$(CONFIG_44x)	:= misc_44x.o
++obj-$(CONFIG_44x)	:= misc_44x.o idle.o
+ obj-$(CONFIG_EBONY)	+= ebony.o
+ obj-$(CONFIG_TAISHAN)	+= taishan.o
+ obj-$(CONFIG_BAMBOO)	+= bamboo.o
++obj-$(CONFIG_YOSEMITE)	+= bamboo.o
+ obj-$(CONFIG_SEQUOIA)	+= sequoia.o
+ obj-$(CONFIG_KATMAI)	+= katmai.o
+ obj-$(CONFIG_RAINIER)	+= rainier.o
+ obj-$(CONFIG_WARP)	+= warp.o
+ obj-$(CONFIG_WARP)	+= warp-nand.o
++obj-$(CONFIG_CANYONLANDS) += canyonlands.o
+diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c
+index fb9a22a..cef169e 100644
+--- a/arch/powerpc/platforms/44x/bamboo.c
++++ b/arch/powerpc/platforms/44x/bamboo.c
+@@ -22,8 +22,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id bamboo_of_bus[] = {
+ 	{ .compatible = "ibm,plb4", },
+@@ -53,11 +52,11 @@ static int __init bamboo_probe(void)
+ }
+ 
+ define_machine(bamboo) {
+-	.name 				= "Bamboo",
+-	.probe 				= bamboo_probe,
+-	.progress 			= udbg_progress,
+-	.init_IRQ 			= uic_init_tree,
+-	.get_irq 			= uic_get_irq,
+-	.restart			= ppc44x_reset_system,
++	.name 			= "Bamboo",
++	.probe 			= bamboo_probe,
++	.progress 		= udbg_progress,
++	.init_IRQ 		= uic_init_tree,
++	.get_irq 		= uic_get_irq,
++	.restart		= ppc4xx_reset_system,
+ 	.calibrate_decr 	= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c
+new file mode 100644
+index 0000000..3949289
+--- /dev/null
++++ b/arch/powerpc/platforms/44x/canyonlands.c
+@@ -0,0 +1,63 @@
++/*
++ * Canyonlands board specific routines
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * Based on the Katmai code by
++ * Benjamin Herrenschmidt <benh at kernel.crashing.org>
++ * Copyright 2007 IBM Corp.
++ * Josh Boyer <jwboyer at linux.vnet.ibm.com>
++ * Copyright 2007 IBM Corporation
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++#include <linux/init.h>
++#include <linux/of_platform.h>
++
++#include <asm/machdep.h>
++#include <asm/prom.h>
++#include <asm/udbg.h>
++#include <asm/time.h>
++#include <asm/uic.h>
++#include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
++
++static __initdata struct of_device_id canyonlands_of_bus[] = {
++	{ .compatible = "ibm,plb4", },
++	{ .compatible = "ibm,opb", },
++	{ .compatible = "ibm,ebc", },
++	{},
++};
++
++static int __init canyonlands_device_probe(void)
++{
++	of_platform_bus_probe(NULL, canyonlands_of_bus, NULL);
++
++	return 0;
++}
++machine_device_initcall(canyonlands, canyonlands_device_probe);
++
++static int __init canyonlands_probe(void)
++{
++	unsigned long root = of_get_flat_dt_root();
++
++	if (!of_flat_dt_is_compatible(root, "amcc,canyonlands"))
++		return 0;
++
++	ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
++
++	return 1;
++}
++
++define_machine(canyonlands) {
++	.name 				= "Canyonlands",
++	.probe 				= canyonlands_probe,
++	.progress 			= udbg_progress,
++	.init_IRQ 			= uic_init_tree,
++	.get_irq 			= uic_get_irq,
++	.restart			= ppc4xx_reset_system,
++	.calibrate_decr			= generic_calibrate_decr,
++};
+diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
+index 1a8d467..a0e8fe4 100644
+--- a/arch/powerpc/platforms/44x/ebony.c
++++ b/arch/powerpc/platforms/44x/ebony.c
+@@ -26,8 +26,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id ebony_of_bus[] = {
+ 	{ .compatible = "ibm,plb4", },
+@@ -66,6 +65,6 @@ define_machine(ebony) {
+ 	.progress		= udbg_progress,
+ 	.init_IRQ		= uic_init_tree,
+ 	.get_irq		= uic_get_irq,
+-	.restart		= ppc44x_reset_system,
++	.restart		= ppc4xx_reset_system,
+ 	.calibrate_decr		= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/idle.c b/arch/powerpc/platforms/44x/idle.c
+new file mode 100644
+index 0000000..7a81f92
+--- /dev/null
++++ b/arch/powerpc/platforms/44x/idle.c
+@@ -0,0 +1,67 @@
++/*
++ * Copyright 2008 IBM Corp. 
++ *
++ * Based on arch/powerpc/platforms/pasemi/idle.c: 
++ * Copyright (C) 2006-2007 PA Semi, Inc
++ *
++ * Added by: Jerone Young <jyoung5 at us.ibm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
++ *
++ */
++
++#include <linux/of.h>
++#include <linux/kernel.h>
++#include <asm/machdep.h>
++
++static int mode_spin;
++
++static void ppc44x_idle(void)
++{
++	unsigned long msr_save;
++
++	msr_save = mfmsr();
++	/* set wait state MSR */
++	mtmsr(msr_save|MSR_WE|MSR_EE|MSR_CE|MSR_DE);
++	isync();
++	/* return to initial state */
++	mtmsr(msr_save);
++	isync();
++}
++
++int __init ppc44x_idle_init(void)
++{
++	if (!mode_spin) {
++		/* If we are not setting spin mode 
++                   then we set to wait mode */
++		ppc_md.power_save = &ppc44x_idle;
++	}
++
++	return 0;
++}
++
++arch_initcall(ppc44x_idle_init);
++
++static int __init idle_param(char *p)
++{ 
++
++	if (!strcmp("spin", p)) {
++		mode_spin = 1;
++		ppc_md.power_save = NULL;
++	}
++
++	return 0;
++}
++
++early_param("idle", idle_param);
+diff --git a/arch/powerpc/platforms/44x/katmai.c b/arch/powerpc/platforms/44x/katmai.c
+index 1113412..44f4b3a 100644
+--- a/arch/powerpc/platforms/44x/katmai.c
++++ b/arch/powerpc/platforms/44x/katmai.c
+@@ -22,8 +22,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id katmai_of_bus[] = {
+ 	{ .compatible = "ibm,plb4", },
+@@ -58,6 +57,6 @@ define_machine(katmai) {
+ 	.progress 			= udbg_progress,
+ 	.init_IRQ 			= uic_init_tree,
+ 	.get_irq 			= uic_get_irq,
+-	.restart			= ppc44x_reset_system,
++	.restart			= ppc4xx_reset_system,
+ 	.calibrate_decr			= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/misc_44x.S b/arch/powerpc/platforms/44x/misc_44x.S
+index 3bce71d..dc12b80 100644
+--- a/arch/powerpc/platforms/44x/misc_44x.S
++++ b/arch/powerpc/platforms/44x/misc_44x.S
+@@ -44,14 +44,3 @@ _GLOBAL(as1_writeb)
+ 	sync
+ 	isync
+ 	blr
+-
+-/*
+- * void ppc44x_reset_system(char *cmd)
+- *
+- * At present, this routine just applies a system reset.
+- */
+-_GLOBAL(ppc44x_reset_system)
+-	mfspr	r13,SPRN_DBCR0
+-	oris	r13,r13,DBCR0_RST_SYSTEM at h
+-	mtspr	SPRN_DBCR0,r13
+-	b	.			/* Just in case the reset doesn't work */
+diff --git a/arch/powerpc/platforms/44x/rainier.c b/arch/powerpc/platforms/44x/rainier.c
+index a7fae1c..4f1ff84 100644
+--- a/arch/powerpc/platforms/44x/rainier.c
++++ b/arch/powerpc/platforms/44x/rainier.c
+@@ -22,7 +22,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id rainier_of_bus[] = {
+ 	{ .compatible = "ibm,plb4", },
+@@ -57,6 +57,6 @@ define_machine(rainier) {
+ 	.progress 			= udbg_progress,
+ 	.init_IRQ 			= uic_init_tree,
+ 	.get_irq 			= uic_get_irq,
+-	.restart			= ppc44x_reset_system,
++	.restart			= ppc4xx_reset_system,
+ 	.calibrate_decr			= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c
+index d279db4..49eb73d 100644
+--- a/arch/powerpc/platforms/44x/sequoia.c
++++ b/arch/powerpc/platforms/44x/sequoia.c
+@@ -23,7 +23,7 @@
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+ 
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id sequoia_of_bus[] = {
+ 	{ .compatible = "ibm,plb4", },
+@@ -58,6 +58,6 @@ define_machine(sequoia) {
+ 	.progress 			= udbg_progress,
+ 	.init_IRQ 			= uic_init_tree,
+ 	.get_irq 			= uic_get_irq,
+-	.restart			= ppc44x_reset_system,
++	.restart			= ppc4xx_reset_system,
+ 	.calibrate_decr			= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/taishan.c b/arch/powerpc/platforms/44x/taishan.c
+index 28ab7e2..49c78b2 100644
+--- a/arch/powerpc/platforms/44x/taishan.c
++++ b/arch/powerpc/platforms/44x/taishan.c
+@@ -29,8 +29,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id taishan_of_bus[] = {
+ 	{ .compatible = "ibm,plb4", },
+@@ -68,6 +67,6 @@ define_machine(taishan) {
+ 	.progress		= udbg_progress,
+ 	.init_IRQ		= uic_init_tree,
+ 	.get_irq		= uic_get_irq,
+-	.restart		= ppc44x_reset_system,
++	.restart		= ppc4xx_reset_system,
+ 	.calibrate_decr		= generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
+index 84ab78f..9150318 100644
+--- a/arch/powerpc/platforms/44x/warp-nand.c
++++ b/arch/powerpc/platforms/44x/warp-nand.c
+@@ -11,6 +11,7 @@
+ #include <linux/mtd/partitions.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/mtd/ndfc.h>
++#include <asm/machdep.h>
+ 
+ #ifdef CONFIG_MTD_NAND_NDFC
+ 
+@@ -100,6 +101,6 @@ static int warp_setup_nand_flash(void)
+ 
+ 	return 0;
+ }
+-device_initcall(warp_setup_nand_flash);
++machine_device_initcall(warp, warp_setup_nand_flash);
+ 
+ #endif
+diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
+index da5b7b7..39cf615 100644
+--- a/arch/powerpc/platforms/44x/warp.c
++++ b/arch/powerpc/platforms/44x/warp.c
+@@ -18,9 +18,7 @@
+ #include <asm/udbg.h>
+ #include <asm/time.h>
+ #include <asm/uic.h>
+-
+-#include "44x.h"
+-
++#include <asm/ppc4xx.h>
+ 
+ static __initdata struct of_device_id warp_of_bus[] = {
+ 	{ .compatible = "ibm,plb4", },
+@@ -49,7 +47,7 @@ define_machine(warp) {
+ 	.progress 	= udbg_progress,
+ 	.init_IRQ 	= uic_init_tree,
+ 	.get_irq 	= uic_get_irq,
+-	.restart	= ppc44x_reset_system,
++	.restart	= ppc4xx_reset_system,
+ 	.calibrate_decr = generic_calibrate_decr,
+ };
+ 
+diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
+index 956f459..6d584f4 100644
+--- a/arch/powerpc/platforms/52xx/lite5200.c
++++ b/arch/powerpc/platforms/52xx/lite5200.c
+@@ -63,7 +63,7 @@ lite5200_fix_clock_config(void)
+ 	of_node_put(np);
+ 	if (!cdm) {
+ 		printk(KERN_ERR "%s() failed; expect abnormal behaviour\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return;
+ 	}
+ 
+@@ -98,7 +98,7 @@ lite5200_fix_port_config(void)
+ 	of_node_put(np);
+ 	if (!gpio) {
+ 		printk(KERN_ERR "%s() failed. expect abnormal behavior\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return;
+ 	}
+ 
+diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
+index 4fad6c7..917ac88 100644
+--- a/arch/powerpc/platforms/82xx/Kconfig
++++ b/arch/powerpc/platforms/82xx/Kconfig
+@@ -11,7 +11,6 @@ config MPC8272_ADS
+ 	select 8260
+ 	select FSL_SOC
+ 	select PQ2_ADS_PCI_PIC if PCI
+-	select PPC_CPM_NEW_BINDING
+ 	help
+ 	  This option enables support for the MPC8272 ADS board
+ 
+@@ -22,7 +21,6 @@ config PQ2FADS
+ 	select 8260
+ 	select FSL_SOC
+ 	select PQ2_ADS_PCI_PIC if PCI
+-	select PPC_CPM_NEW_BINDING
+ 	help
+ 	  This option enables support for the PQ2FADS board
+ 
+@@ -31,7 +29,6 @@ config EP8248E
+ 	select 8272
+ 	select 8260
+ 	select FSL_SOC
+-	select PPC_CPM_NEW_BINDING
+ 	select MDIO_BITBANG
+ 	help
+ 	  This enables support for the Embedded Planet EP8248E board.
+diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c
+index ba93d8a..d5770fd 100644
+--- a/arch/powerpc/platforms/82xx/ep8248e.c
++++ b/arch/powerpc/platforms/82xx/ep8248e.c
+@@ -138,7 +138,7 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev,
+ 
+ 	bus->name = "ep8248e-mdio-bitbang";
+ 	bus->dev = &ofdev->dev;
+-	bus->id = res.start;
++	snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ 
+ 	return mdiobus_register(bus);
+ }
+diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+index 2293ae5..c00356b 100644
+--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
++++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+@@ -46,6 +46,7 @@ static void __init mpc837x_rdb_setup_arch(void)
+ static struct of_device_id mpc837x_ids[] = {
+ 	{ .type = "soc", },
+ 	{ .compatible = "soc", },
++	{ .compatible = "simple-bus", },
+ 	{},
+ };
+ 
+diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
+index 68065e6..88a3b5c 100644
+--- a/arch/powerpc/platforms/83xx/mpc83xx.h
++++ b/arch/powerpc/platforms/83xx/mpc83xx.h
+@@ -16,6 +16,7 @@
+ #define MPC83XX_SCCR_USB_DRCM_10   0x00200000
+ #define MPC8315_SCCR_USB_MASK      0x00c00000
+ #define MPC8315_SCCR_USB_DRCM_11   0x00c00000
++#define MPC8315_SCCR_USB_DRCM_01   0x00400000
+ #define MPC837X_SCCR_USB_DRCM_11   0x00c00000
+ 
+ /* system i/o configuration register low */
+@@ -37,6 +38,7 @@
+ /* USB Control Register */
+ #define FSL_USB2_CONTROL_OFFS      0x500
+ #define CONTROL_UTMI_PHY_EN        0x00000200
++#define CONTROL_REFSEL_24MHZ       0x00000040
+ #define CONTROL_REFSEL_48MHZ       0x00000080
+ #define CONTROL_PHY_CLK_SEL_ULPI   0x00000400
+ #define CONTROL_OTG_PORT           0x00000020
+diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
+index 471fdd8..64bcf0a 100644
+--- a/arch/powerpc/platforms/83xx/usb.c
++++ b/arch/powerpc/platforms/83xx/usb.c
+@@ -129,7 +129,7 @@ int mpc831x_usb_cfg(void)
+ 	if (immr_node && of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
+ 		clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
+ 		                MPC8315_SCCR_USB_MASK,
+-		                MPC8315_SCCR_USB_DRCM_11);
++		                MPC8315_SCCR_USB_DRCM_01);
+ 	else
+ 		clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
+ 		                MPC83XX_SCCR_USB_MASK,
+@@ -164,9 +164,15 @@ int mpc831x_usb_cfg(void)
+ 	/* Using on-chip PHY */
+ 	if (prop && (!strcmp(prop, "utmi_wide") ||
+ 		     !strcmp(prop, "utmi"))) {
+-		/* Set UTMI_PHY_EN, REFSEL to 48MHZ */
++		u32 refsel;
++
++		if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
++			refsel = CONTROL_REFSEL_24MHZ;
++		else
++			refsel = CONTROL_REFSEL_48MHZ;
++		/* Set UTMI_PHY_EN and REFSEL */
+ 		out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
+-				CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ);
++				CONTROL_UTMI_PHY_EN | refsel);
+ 	/* Using external UPLI PHY */
+ 	} else if (prop && !strcmp(prop, "ulpi")) {
+ 		/* Set PHY_CLK_SEL to ULPI */
+diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
+index 7e76ddb..7ff29d5 100644
+--- a/arch/powerpc/platforms/85xx/Kconfig
++++ b/arch/powerpc/platforms/85xx/Kconfig
+@@ -19,7 +19,6 @@ config MPC8540_ADS
+ config MPC8560_ADS
+ 	bool "Freescale MPC8560 ADS"
+ 	select DEFAULT_UIMAGE
+-	select PPC_CPM_NEW_BINDING
+ 	select CPM2
+ 	help
+ 	  This option enables support for the MPC 8560 ADS board
+@@ -46,6 +45,12 @@ config MPC85xx_DS
+ 	help
+ 	  This option enables support for the MPC85xx DS (MPC8544 DS) board
+ 
++config KSI8560
++        bool "Emerson KSI8560"
++        select DEFAULT_UIMAGE
++        help
++          This option enables support for the Emerson KSI8560 board
++
+ config STX_GP3
+ 	bool "Silicon Turnkey Express GP3"
+ 	help
+@@ -53,14 +58,12 @@ config STX_GP3
+ 	  board.
+ 	select CPM2
+ 	select DEFAULT_UIMAGE
+-	select PPC_CPM_NEW_BINDING
+ 
+ config TQM8540
+ 	bool "TQ Components TQM8540"
+ 	help
+ 	  This option enables support for the TQ Components TQM8540 board.
+ 	select DEFAULT_UIMAGE
+-	select PPC_CPM_NEW_BINDING
+ 	select TQM85xx
+ 
+ config TQM8541
+@@ -68,7 +71,6 @@ config TQM8541
+ 	help
+ 	  This option enables support for the TQ Components TQM8541 board.
+ 	select DEFAULT_UIMAGE
+-	select PPC_CPM_NEW_BINDING
+ 	select TQM85xx
+ 	select CPM2
+ 
+@@ -77,7 +79,6 @@ config TQM8555
+ 	help
+ 	  This option enables support for the TQ Components TQM8555 board.
+ 	select DEFAULT_UIMAGE
+-	select PPC_CPM_NEW_BINDING
+ 	select TQM85xx
+ 	select CPM2
+ 
+@@ -86,7 +87,6 @@ config TQM8560
+ 	help
+ 	  This option enables support for the TQ Components TQM8560 board.
+ 	select DEFAULT_UIMAGE
+-	select PPC_CPM_NEW_BINDING
+ 	select TQM85xx
+ 	select CPM2
+ 
+@@ -99,7 +99,6 @@ config SBC8548
+ config SBC8560
+ 	bool "Wind River SBC8560"
+ 	select DEFAULT_UIMAGE
+-	select PPC_CPM_NEW_BINDING if CPM2
+ 	help
+ 	  This option enables support for the Wind River SBC8560 board
+ 
+diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
+index cb7af4e..6cea185 100644
+--- a/arch/powerpc/platforms/85xx/Makefile
++++ b/arch/powerpc/platforms/85xx/Makefile
+@@ -10,3 +10,4 @@ obj-$(CONFIG_STX_GP3)	  += stx_gp3.o
+ obj-$(CONFIG_TQM85xx)	  += tqm85xx.o
+ obj-$(CONFIG_SBC8560)     += sbc8560.o
+ obj-$(CONFIG_SBC8548)     += sbc8548.o
++obj-$(CONFIG_KSI8560)	  += ksi8560.o
+diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c
+new file mode 100644
+index 0000000..2145ade
+--- /dev/null
++++ b/arch/powerpc/platforms/85xx/ksi8560.c
+@@ -0,0 +1,257 @@
++/*
++ * Board setup routines for the Emerson KSI8560
++ *
++ * Author: Alexandr Smirnov <asmirnov at ru.mvista.com>
++ *
++ * Based on mpc85xx_ads.c maintained by Kumar Gala
++ *
++ * 2008 (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.
++ *
++ */
++
++#include <linux/stddef.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/kdev_t.h>
++#include <linux/delay.h>
++#include <linux/seq_file.h>
++#include <linux/of_platform.h>
++
++#include <asm/system.h>
++#include <asm/time.h>
++#include <asm/machdep.h>
++#include <asm/pci-bridge.h>
++#include <asm/mpic.h>
++#include <mm/mmu_decl.h>
++#include <asm/udbg.h>
++#include <asm/prom.h>
++
++#include <sysdev/fsl_soc.h>
++#include <sysdev/fsl_pci.h>
++
++#include <asm/cpm2.h>
++#include <sysdev/cpm2_pic.h>
++
++
++#define KSI8560_CPLD_HVR		0x04 /* Hardware Version Register */
++#define KSI8560_CPLD_PVR		0x08 /* PLD Version Register */
++#define KSI8560_CPLD_RCR1		0x30 /* Reset Command Register 1 */
++
++#define KSI8560_CPLD_RCR1_CPUHR		0x80 /* CPU Hard Reset */
++
++static void __iomem *cpld_base = NULL;
++
++static void machine_restart(char *cmd)
++{
++	if (cpld_base)
++		out_8(cpld_base + KSI8560_CPLD_RCR1, KSI8560_CPLD_RCR1_CPUHR);
++	else
++		printk(KERN_ERR "Can't find CPLD base, hang forever\n");
++
++	for (;;);
++}
++
++static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
++{
++	int cascade_irq;
++
++	while ((cascade_irq = cpm2_get_irq()) >= 0)
++		generic_handle_irq(cascade_irq);
++
++	desc->chip->eoi(irq);
++}
++
++static void __init ksi8560_pic_init(void)
++{
++	struct mpic *mpic;
++	struct resource r;
++	struct device_node *np;
++#ifdef CONFIG_CPM2
++	int irq;
++#endif
++
++	np = of_find_node_by_type(NULL, "open-pic");
++
++	if (np == NULL) {
++		printk(KERN_ERR "Could not find open-pic node\n");
++		return;
++	}
++
++	if (of_address_to_resource(np, 0, &r)) {
++		printk(KERN_ERR "Could not map mpic register space\n");
++		of_node_put(np);
++		return;
++	}
++
++	mpic = mpic_alloc(np, r.start,
++			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
++			0, 256, " OpenPIC  ");
++	BUG_ON(mpic == NULL);
++	of_node_put(np);
++
++	mpic_init(mpic);
++
++#ifdef CONFIG_CPM2
++	/* Setup CPM2 PIC */
++	np = of_find_compatible_node(NULL, NULL, "fsl,cpm2-pic");
++	if (np == NULL) {
++		printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n");
++		return;
++	}
++	irq = irq_of_parse_and_map(np, 0);
++
++	cpm2_pic_init(np);
++	of_node_put(np);
++	set_irq_chained_handler(irq, cpm2_cascade);
++
++	setup_irq(0, NULL);
++#endif
++}
++
++#ifdef CONFIG_CPM2
++/*
++ * Setup I/O ports
++ */
++struct cpm_pin {
++	int port, pin, flags;
++};
++
++static struct cpm_pin __initdata ksi8560_pins[] = {
++	/* SCC1 */
++	{3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++	{3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
++	{3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++
++	/* SCC2 */
++	{3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++	{3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++	{3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++
++	/* FCC1 */
++	{0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++	{0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++	{0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++	{0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++	{0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++	{0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++	{0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++	{0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++	{0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
++	{0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
++	{0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
++	{0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
++	{0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
++	{0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
++	{2, 23, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK9 */
++	{2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK10 */
++
++};
++
++static void __init init_ioports(void)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(ksi8560_pins); i++) {
++		struct cpm_pin *pin = &ksi8560_pins[i];
++		cpm2_set_pin(pin->port, pin->pin, pin->flags);
++	}
++
++	cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX);
++	cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX);
++	cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX);
++	cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX);
++	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK9, CPM_CLK_RX);
++	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_TX);
++}
++#endif
++
++/*
++ * Setup the architecture
++ */
++static void __init ksi8560_setup_arch(void)
++{
++	struct device_node *cpld;
++
++	cpld = of_find_compatible_node(NULL, NULL, "emerson,KSI8560-cpld");
++	if (cpld)
++		cpld_base = of_iomap(cpld, 0);
++	else
++		printk(KERN_ERR "Can't find CPLD in device tree\n");
++
++	if (ppc_md.progress)
++		ppc_md.progress("ksi8560_setup_arch()", 0);
++
++#ifdef CONFIG_CPM2
++	cpm2_reset();
++	init_ioports();
++#endif
++}
++
++static void ksi8560_show_cpuinfo(struct seq_file *m)
++{
++	uint pvid, svid, phid1;
++	uint memsize = total_memory;
++
++	pvid = mfspr(SPRN_PVR);
++	svid = mfspr(SPRN_SVR);
++
++	seq_printf(m, "Vendor\t\t: Emerson Network Power\n");
++	seq_printf(m, "Board\t\t: KSI8560\n");
++
++	if (cpld_base) {
++		seq_printf(m, "Hardware rev\t: %d\n",
++					in_8(cpld_base + KSI8560_CPLD_HVR));
++		seq_printf(m, "CPLD rev\t: %d\n",
++					in_8(cpld_base + KSI8560_CPLD_PVR));
++	} else
++		seq_printf(m, "Unknown Hardware and CPLD revs\n");
++
++	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
++	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
++
++	/* Display cpu Pll setting */
++	phid1 = mfspr(SPRN_HID1);
++	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
++
++	/* Display the amount of memory */
++	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
++}
++
++static struct of_device_id __initdata of_bus_ids[] = {
++	{ .type = "soc", },
++	{ .name = "cpm", },
++	{ .name = "localbus", },
++	{},
++};
++
++static int __init declare_of_platform_devices(void)
++{
++	of_platform_bus_probe(NULL, of_bus_ids, NULL);
++
++	return 0;
++}
++machine_device_initcall(ksi8560, declare_of_platform_devices);
++
++/*
++ * Called very early, device-tree isn't unflattened
++ */
++static int __init ksi8560_probe(void)
++{
++	unsigned long root = of_get_flat_dt_root();
++
++	return of_flat_dt_is_compatible(root, "emerson,KSI8560");
++}
++
++define_machine(ksi8560) {
++	.name			= "KSI8560",
++	.probe			= ksi8560_probe,
++	.setup_arch		= ksi8560_setup_arch,
++	.init_IRQ		= ksi8560_pic_init,
++	.show_cpuinfo		= ksi8560_show_cpuinfo,
++	.get_irq		= mpic_get_irq,
++	.restart		= machine_restart,
++	.calibrate_decr		= generic_calibrate_decr,
++};
+diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+index 4e03050..3582c84 100644
+--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
++++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+@@ -165,7 +165,7 @@ static void __init init_ioports(void)
+ 	int i;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(mpc8560_ads_pins); i++) {
+-		struct cpm_pin *pin = &mpc8560_ads_pins[i];
++		const struct cpm_pin *pin = &mpc8560_ads_pins[i];
+ 		cpm2_set_pin(pin->port, pin->pin, pin->flags);
+ 	}
+ 
+diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+index bdb3d0b..dfd8b4a 100644
+--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
++++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+@@ -19,6 +19,7 @@
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+ #include <linux/interrupt.h>
++#include <linux/of_platform.h>
+ 
+ #include <asm/system.h>
+ #include <asm/time.h>
+@@ -36,7 +37,7 @@
+ #undef DEBUG
+ 
+ #ifdef DEBUG
+-#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
+ #else
+ #define DBG(fmt, args...)
+ #endif
+@@ -183,6 +184,18 @@ static int __init mpc8544_ds_probe(void)
+ 	}
+ }
+ 
++static struct of_device_id mpc85xxds_ids[] = {
++	{ .type = "soc", },
++	{ .compatible = "soc", },
++	{},
++};
++
++static int __init mpc85xxds_publish_devices(void)
++{
++	return of_platform_bus_probe(NULL, mpc85xxds_ids, NULL);
++}
++machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices);
++
+ /*
+  * Called very early, device-tree isn't unflattened
+  */
+diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
+index 21d1135..7442c58 100644
+--- a/arch/powerpc/platforms/86xx/Kconfig
++++ b/arch/powerpc/platforms/86xx/Kconfig
+@@ -11,6 +11,12 @@ config MPC8641_HPCN
+ 	help
+ 	  This option enables support for the MPC8641 HPCN board.
+ 
++config SBC8641D
++	bool "Wind River SBC8641D"
++	select DEFAULT_UIMAGE
++	help
++	  This option enables support for the WRS SBC8641D board.
++
+ config MPC8610_HPCD
+ 	bool "Freescale MPC8610 HPCD"
+ 	select DEFAULT_UIMAGE
+@@ -24,7 +30,7 @@ config MPC8641
+ 	select FSL_PCI if PCI
+ 	select PPC_UDBG_16550
+ 	select MPIC
+-	default y if MPC8641_HPCN
++	default y if MPC8641_HPCN || SBC8641D
+ 
+ config MPC8610
+ 	bool
+diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
+index c967063..1b9b4a9 100644
+--- a/arch/powerpc/platforms/86xx/Makefile
++++ b/arch/powerpc/platforms/86xx/Makefile
+@@ -4,4 +4,5 @@
+ 
+ obj-$(CONFIG_SMP)		+= mpc86xx_smp.o
+ obj-$(CONFIG_MPC8641_HPCN)	+= mpc86xx_hpcn.o
++obj-$(CONFIG_SBC8641D)		+= sbc8641d.o
+ obj-$(CONFIG_MPC8610_HPCD)	+= mpc8610_hpcd.o
+diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+index 0b07485..18b8ebe 100644
+--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
++++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+@@ -52,7 +52,7 @@ static int __init mpc8610_declare_of_platform_devices(void)
+ }
+ machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
+ 
+-void __init
++static void __init
+ mpc86xx_hpcd_init_irq(void)
+ {
+ 	struct mpic *mpic1;
+@@ -200,7 +200,7 @@ static int __init mpc86xx_hpcd_probe(void)
+ 	return 0;
+ }
+ 
+-long __init
++static long __init
+ mpc86xx_time_init(void)
+ {
+ 	unsigned int temp;
+diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+index cfbe8c5..f947f55 100644
+--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
++++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+@@ -55,7 +55,7 @@ static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
+ }
+ #endif	/* CONFIG_PCI */
+ 
+-void __init
++static void __init
+ mpc86xx_hpcn_init_irq(void)
+ {
+ 	struct mpic *mpic1;
+@@ -162,7 +162,7 @@ mpc86xx_hpcn_setup_arch(void)
+ }
+ 
+ 
+-void
++static void
+ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
+ {
+ 	struct device_node *root;
+@@ -190,13 +190,19 @@ static int __init mpc86xx_hpcn_probe(void)
+ {
+ 	unsigned long root = of_get_flat_dt_root();
+ 
+-	if (of_flat_dt_is_compatible(root, "mpc86xx"))
++	if (of_flat_dt_is_compatible(root, "fsl,mpc8641hpcn"))
+ 		return 1;	/* Looks good */
+ 
++	/* Be nice and don't give silent boot death.  Delete this in 2.6.27 */
++	if (of_flat_dt_is_compatible(root, "mpc86xx")) {
++		pr_warning("WARNING: your dts/dtb is old. You must update before the next kernel release\n");
++		return 1;
++	}
++
+ 	return 0;
+ }
+ 
+-long __init
++static long __init
+ mpc86xx_time_init(void)
+ {
+ 	unsigned int temp;
+diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
+new file mode 100644
+index 0000000..510a06e
+--- /dev/null
++++ b/arch/powerpc/platforms/86xx/sbc8641d.c
+@@ -0,0 +1,164 @@
++/*
++ * SBC8641D board specific routines
++ *
++ * Copyright 2008 Wind River Systems Inc.
++ *
++ * By Paul Gortmaker (see MAINTAINERS for contact information)
++ *
++ * Based largely on the 8641 HPCN support by Freescale Semiconductor Inc.
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/stddef.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/kdev_t.h>
++#include <linux/delay.h>
++#include <linux/seq_file.h>
++#include <linux/of_platform.h>
++
++#include <asm/system.h>
++#include <asm/time.h>
++#include <asm/machdep.h>
++#include <asm/pci-bridge.h>
++#include <asm/mpc86xx.h>
++#include <asm/prom.h>
++#include <mm/mmu_decl.h>
++#include <asm/udbg.h>
++
++#include <asm/mpic.h>
++
++#include <sysdev/fsl_pci.h>
++#include <sysdev/fsl_soc.h>
++
++#include "mpc86xx.h"
++
++static void __init
++sbc8641_init_irq(void)
++{
++	struct mpic *mpic1;
++	struct device_node *np;
++	struct resource res;
++
++	/* Determine PIC address. */
++	np = of_find_node_by_type(NULL, "open-pic");
++	if (np == NULL)
++		return;
++	of_address_to_resource(np, 0, &res);
++
++	/* Alloc mpic structure and per isu has 16 INT entries. */
++	mpic1 = mpic_alloc(np, res.start,
++			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
++			0, 256, " MPIC     ");
++	of_node_put(np);
++	BUG_ON(mpic1 == NULL);
++
++	mpic_init(mpic1);
++}
++
++static void __init
++sbc8641_setup_arch(void)
++{
++#ifdef CONFIG_PCI
++	struct device_node *np;
++#endif
++
++	if (ppc_md.progress)
++		ppc_md.progress("sbc8641_setup_arch()", 0);
++
++#ifdef CONFIG_PCI
++	for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie")
++		fsl_add_bridge(np, 0);
++#endif
++
++	printk("SBC8641 board from Wind River\n");
++
++#ifdef CONFIG_SMP
++	mpc86xx_smp_init();
++#endif
++}
++
++
++static void
++sbc8641_show_cpuinfo(struct seq_file *m)
++{
++	struct device_node *root;
++	uint memsize = total_memory;
++	const char *model = "";
++	uint svid = mfspr(SPRN_SVR);
++
++	seq_printf(m, "Vendor\t\t: Wind River Systems\n");
++
++	root = of_find_node_by_path("/");
++	if (root)
++		model = of_get_property(root, "model", NULL);
++	seq_printf(m, "Machine\t\t: %s\n", model);
++	of_node_put(root);
++
++	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
++	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
++}
++
++
++/*
++ * Called very early, device-tree isn't unflattened
++ */
++static int __init sbc8641_probe(void)
++{
++	unsigned long root = of_get_flat_dt_root();
++
++	if (of_flat_dt_is_compatible(root, "wind,sbc8641"))
++		return 1;	/* Looks good */
++
++	return 0;
++}
++
++static long __init
++mpc86xx_time_init(void)
++{
++	unsigned int temp;
++
++	/* Set the time base to zero */
++	mtspr(SPRN_TBWL, 0);
++	mtspr(SPRN_TBWU, 0);
++
++	temp = mfspr(SPRN_HID0);
++	temp |= HID0_TBEN;
++	mtspr(SPRN_HID0, temp);
++	asm volatile("isync");
++
++	return 0;
++}
++
++static __initdata struct of_device_id of_bus_ids[] = {
++	{ .compatible = "simple-bus", },
++	{},
++};
++
++static int __init declare_of_platform_devices(void)
++{
++	of_platform_bus_probe(NULL, of_bus_ids, NULL);
++
++	return 0;
++}
++machine_device_initcall(sbc8641, declare_of_platform_devices);
++
++define_machine(sbc8641) {
++	.name			= "SBC8641D",
++	.probe			= sbc8641_probe,
++	.setup_arch		= sbc8641_setup_arch,
++	.init_IRQ		= sbc8641_init_irq,
++	.show_cpuinfo		= sbc8641_show_cpuinfo,
++	.get_irq		= mpic_get_irq,
++	.restart		= fsl_rstcr_restart,
++	.time_init		= mpc86xx_time_init,
++	.calibrate_decr		= generic_calibrate_decr,
++	.progress		= udbg_progress,
++#ifdef CONFIG_PCI
++	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
++#endif
++};
+diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
+index 7fd224c..6fc849e 100644
+--- a/arch/powerpc/platforms/8xx/Kconfig
++++ b/arch/powerpc/platforms/8xx/Kconfig
+@@ -18,7 +18,6 @@ config MPC8XXFADS
+ config MPC86XADS
+ 	bool "MPC86XADS"
+ 	select CPM1
+-	select PPC_CPM_NEW_BINDING
+ 	help
+ 	  MPC86x Application Development System by Freescale Semiconductor.
+ 	  The MPC86xADS is meant to serve as a platform for s/w and h/w
+@@ -27,7 +26,6 @@ config MPC86XADS
+ config MPC885ADS
+ 	bool "MPC885ADS"
+ 	select CPM1
+-	select PPC_CPM_NEW_BINDING
+ 	help
+ 	  Freescale Semiconductor MPC885 Application Development System (ADS).
+ 	  Also known as DUET.
+@@ -37,7 +35,6 @@ config MPC885ADS
+ config PPC_EP88XC
+ 	bool "Embedded Planet EP88xC (a.k.a. CWH-PPC-885XN-VE)"
+ 	select CPM1
+-	select PPC_CPM_NEW_BINDING
+ 	help
+ 	  This enables support for the Embedded Planet EP88xC board.
+ 
+@@ -47,7 +44,6 @@ config PPC_EP88XC
+ config PPC_ADDER875
+ 	bool "Analogue & Micro Adder 875"
+ 	select CPM1
+-	select PPC_CPM_NEW_BINDING
+ 	select REDBOOT
+ 	help
+ 	  This enables support for the Analogue & Micro Adder 875
+diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
+index 184f998..0d9f75c 100644
+--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
++++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
+@@ -111,17 +111,12 @@ void __init mpc8xx_calibrate_decr(void)
+ 
+ 	/* Processor frequency is MHz.
+ 	 */
+-	ppc_tb_freq = 50000000;
+-	if (!get_freq("bus-frequency", &ppc_tb_freq)) {
+-		printk(KERN_ERR "WARNING: Estimating decrementer frequency "
+-		                "(not found)\n");
+-	}
+-	ppc_tb_freq /= 16;
+ 	ppc_proc_freq = 50000000;
+ 	if (!get_freq("clock-frequency", &ppc_proc_freq))
+ 		printk(KERN_ERR "WARNING: Estimating processor frequency "
+ 		                "(not found)\n");
+ 
++	ppc_tb_freq = ppc_proc_freq / 16;
+ 	printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);
+ 
+ 	/* Perform some more timer/timebase initialization.  This used
+diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
+index a578b96..87454c5 100644
+--- a/arch/powerpc/platforms/Kconfig
++++ b/arch/powerpc/platforms/Kconfig
+@@ -45,7 +45,6 @@ source "arch/powerpc/platforms/powermac/Kconfig"
+ source "arch/powerpc/platforms/prep/Kconfig"
+ source "arch/powerpc/platforms/maple/Kconfig"
+ source "arch/powerpc/platforms/pasemi/Kconfig"
+-source "arch/powerpc/platforms/celleb/Kconfig"
+ source "arch/powerpc/platforms/ps3/Kconfig"
+ source "arch/powerpc/platforms/cell/Kconfig"
+ source "arch/powerpc/platforms/8xx/Kconfig"
+@@ -290,13 +289,7 @@ config CPM2
+ config PPC_CPM_NEW_BINDING
+ 	bool
+ 	depends on CPM1 || CPM2
+-	help
+-	  Select this if your board has been converted to use the new
+-	  device tree bindings for CPM, and no longer needs the
+-	  ioport callbacks or the platform device glue code.
+-
+-	  The fs_enet and cpm_uart drivers will be built as
+-	  of_platform devices.
++	default y
+ 
+ config AXON_RAM
+ 	tristate "Axon DDR2 memory device driver"
+diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
+index 0c3face..f7efaa9 100644
+--- a/arch/powerpc/platforms/Kconfig.cputype
++++ b/arch/powerpc/platforms/Kconfig.cputype
+@@ -41,11 +41,13 @@ config 40x
+ 	bool "AMCC 40x"
+ 	select PPC_DCR_NATIVE
+ 	select PPC_UDBG_16550
++	select 4xx_SOC
+ 
+ config 44x
+ 	bool "AMCC 44x"
+ 	select PPC_DCR_NATIVE
+ 	select PPC_UDBG_16550
++	select 4xx_SOC
+ 
+ config E200
+ 	bool "Freescale e200"
+@@ -218,8 +220,8 @@ config SMP
+ 	  If you don't know what to do here, say N.
+ 
+ config NR_CPUS
+-	int "Maximum number of CPUs (2-128)"
+-	range 2 128
++	int "Maximum number of CPUs (2-1024)"
++	range 2 1024
+ 	depends on SMP
+ 	default "32" if PPC64
+ 	default "4"
+diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
+index a984894..423a023 100644
+--- a/arch/powerpc/platforms/Makefile
++++ b/arch/powerpc/platforms/Makefile
+@@ -24,5 +24,4 @@ obj-$(CONFIG_PPC_MAPLE)		+= maple/
+ obj-$(CONFIG_PPC_PASEMI)	+= pasemi/
+ obj-$(CONFIG_PPC_CELL)		+= cell/
+ obj-$(CONFIG_PPC_PS3)		+= ps3/
+-obj-$(CONFIG_PPC_CELLEB)	+= celleb/
+ obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
+diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
+index 2f16999..3959fcf 100644
+--- a/arch/powerpc/platforms/cell/Kconfig
++++ b/arch/powerpc/platforms/cell/Kconfig
+@@ -25,6 +25,19 @@ config PPC_IBM_CELL_BLADE
+ 	select PPC_UDBG_16550
+ 	select UDBG_RTAS_CONSOLE
+ 
++config PPC_CELLEB
++	bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
++	depends on PPC_MULTIPLATFORM && PPC64
++	select PPC_CELL
++	select PPC_CELL_NATIVE
++	select PPC_RTAS
++	select PPC_INDIRECT_IO
++	select PPC_OF_PLATFORM_PCI
++	select HAS_TXX9_SERIAL
++	select PPC_UDBG_BEAT
++	select USB_OHCI_BIG_ENDIAN_MMIO
++	select USB_EHCI_BIG_ENDIAN_MMIO
++
+ menu "Cell Broadband Engine options"
+ 	depends on PPC_CELL
+ 
+diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
+index c89964c..c2a7e4e 100644
+--- a/arch/powerpc/platforms/cell/Makefile
++++ b/arch/powerpc/platforms/cell/Makefile
+@@ -1,6 +1,7 @@
+ obj-$(CONFIG_PPC_CELL_NATIVE)		+= interrupt.o iommu.o setup.o \
+ 					   cbe_regs.o spider-pic.o \
+-					   pervasive.o pmu.o io-workarounds.o
++					   pervasive.o pmu.o io-workarounds.o \
++					   spider-pci.o
+ obj-$(CONFIG_CBE_RAS)			+= ras.o
+ 
+ obj-$(CONFIG_CBE_THERM)			+= cbe_thermal.o
+@@ -26,3 +27,20 @@ obj-$(CONFIG_SPU_BASE)			+= spu_callbacks.o spu_base.o \
+ 					   spufs/
+ 
+ obj-$(CONFIG_PCI_MSI)			+= axon_msi.o
++
++
++# celleb stuff
++ifeq ($(CONFIG_PPC_CELLEB),y)
++obj-y					+= celleb_setup.o \
++					   celleb_pci.o celleb_scc_epci.o \
++					   celleb_scc_pciex.o \
++					   celleb_scc_uhc.o \
++					   io-workarounds.o spider-pci.o \
++					   beat.o beat_htab.o beat_hvCall.o \
++					   beat_interrupt.o beat_iommu.o
++
++obj-$(CONFIG_SMP)			+= beat_smp.o
++obj-$(CONFIG_PPC_UDBG_BEAT)		+= beat_udbg.o
++obj-$(CONFIG_SERIAL_TXX9)		+= celleb_scc_sio.o
++obj-$(CONFIG_SPU_BASE)			+= beat_spu_priv1.o
++endif
+diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
+index d95e71d..c39f5c2 100644
+--- a/arch/powerpc/platforms/cell/axon_msi.c
++++ b/arch/powerpc/platforms/cell/axon_msi.c
+@@ -123,7 +123,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
+ 		return NULL;
+ 	}
+ 
+-	for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
++	for (; dn; dn = of_get_next_parent(dn)) {
+ 		ph = of_get_property(dn, "msi-translator", NULL);
+ 		if (ph)
+ 			break;
+@@ -169,7 +169,7 @@ static int axon_msi_check_device(struct pci_dev *dev, int nvec, int type)
+ 
+ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
+ {
+-	struct device_node *dn, *tmp;
++	struct device_node *dn;
+ 	struct msi_desc *entry;
+ 	int len;
+ 	const u32 *prop;
+@@ -182,7 +182,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
+ 
+ 	entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
+ 
+-	for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
++	for (; dn; dn = of_get_next_parent(dn)) {
+ 		if (entry->msi_attrib.is_64) {
+ 			prop = of_get_property(dn, "msi-address-64", &len);
+ 			if (prop)
+diff --git a/arch/powerpc/platforms/cell/beat.c b/arch/powerpc/platforms/cell/beat.c
+new file mode 100644
+index 0000000..48c690e
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat.c
+@@ -0,0 +1,264 @@
++/*
++ * Simple routines for Celleb/Beat
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/rtc.h>
++#include <linux/interrupt.h>
++#include <linux/irqreturn.h>
++#include <linux/reboot.h>
++
++#include <asm/hvconsole.h>
++#include <asm/time.h>
++#include <asm/machdep.h>
++#include <asm/firmware.h>
++
++#include "beat_wrapper.h"
++#include "beat.h"
++#include "beat_interrupt.h"
++
++static int beat_pm_poweroff_flag;
++
++void beat_restart(char *cmd)
++{
++	beat_shutdown_logical_partition(!beat_pm_poweroff_flag);
++}
++
++void beat_power_off(void)
++{
++	beat_shutdown_logical_partition(0);
++}
++
++u64 beat_halt_code = 0x1000000000000000UL;
++EXPORT_SYMBOL(beat_halt_code);
++
++void beat_halt(void)
++{
++	beat_shutdown_logical_partition(beat_halt_code);
++}
++
++int beat_set_rtc_time(struct rtc_time *rtc_time)
++{
++	u64 tim;
++	tim = mktime(rtc_time->tm_year+1900,
++		     rtc_time->tm_mon+1, rtc_time->tm_mday,
++		     rtc_time->tm_hour, rtc_time->tm_min, rtc_time->tm_sec);
++	if (beat_rtc_write(tim))
++		return -1;
++	return 0;
++}
++
++void beat_get_rtc_time(struct rtc_time *rtc_time)
++{
++	u64 tim;
++
++	if (beat_rtc_read(&tim))
++		tim = 0;
++	to_tm(tim, rtc_time);
++	rtc_time->tm_year -= 1900;
++	rtc_time->tm_mon -= 1;
++}
++
++#define	BEAT_NVRAM_SIZE	4096
++
++ssize_t beat_nvram_read(char *buf, size_t count, loff_t *index)
++{
++	unsigned int i;
++	unsigned long len;
++	char *p = buf;
++
++	if (*index >= BEAT_NVRAM_SIZE)
++		return -ENODEV;
++	i = *index;
++	if (i + count > BEAT_NVRAM_SIZE)
++		count = BEAT_NVRAM_SIZE - i;
++
++	for (; count != 0; count -= len) {
++		len = count;
++		if (len > BEAT_NVRW_CNT)
++			len = BEAT_NVRW_CNT;
++		if (beat_eeprom_read(i, len, p))
++			return -EIO;
++
++		p += len;
++		i += len;
++	}
++	*index = i;
++	return p - buf;
++}
++
++ssize_t beat_nvram_write(char *buf, size_t count, loff_t *index)
++{
++	unsigned int i;
++	unsigned long len;
++	char *p = buf;
++
++	if (*index >= BEAT_NVRAM_SIZE)
++		return -ENODEV;
++	i = *index;
++	if (i + count > BEAT_NVRAM_SIZE)
++		count = BEAT_NVRAM_SIZE - i;
++
++	for (; count != 0; count -= len) {
++		len = count;
++		if (len > BEAT_NVRW_CNT)
++			len = BEAT_NVRW_CNT;
++		if (beat_eeprom_write(i, len, p))
++			return -EIO;
++
++		p += len;
++		i += len;
++	}
++	*index = i;
++	return p - buf;
++}
++
++ssize_t beat_nvram_get_size(void)
++{
++	return BEAT_NVRAM_SIZE;
++}
++
++int beat_set_xdabr(unsigned long dabr)
++{
++	if (beat_set_dabr(dabr, DABRX_KERNEL | DABRX_USER))
++		return -1;
++	return 0;
++}
++
++int64_t beat_get_term_char(u64 vterm, u64 *len, u64 *t1, u64 *t2)
++{
++	u64 db[2];
++	s64 ret;
++
++	ret = beat_get_characters_from_console(vterm, len, (u8 *)db);
++	if (ret == 0) {
++		*t1 = db[0];
++		*t2 = db[1];
++	}
++	return ret;
++}
++EXPORT_SYMBOL(beat_get_term_char);
++
++int64_t beat_put_term_char(u64 vterm, u64 len, u64 t1, u64 t2)
++{
++	u64 db[2];
++
++	db[0] = t1;
++	db[1] = t2;
++	return beat_put_characters_to_console(vterm, len, (u8 *)db);
++}
++EXPORT_SYMBOL(beat_put_term_char);
++
++void beat_power_save(void)
++{
++	beat_pause(0);
++}
++
++#ifdef CONFIG_KEXEC
++void beat_kexec_cpu_down(int crash, int secondary)
++{
++	beatic_deinit_IRQ();
++}
++#endif
++
++static irqreturn_t beat_power_event(int virq, void *arg)
++{
++	printk(KERN_DEBUG "Beat: power button pressed\n");
++	beat_pm_poweroff_flag = 1;
++	ctrl_alt_del();
++	return IRQ_HANDLED;
++}
++
++static irqreturn_t beat_reset_event(int virq, void *arg)
++{
++	printk(KERN_DEBUG "Beat: reset button pressed\n");
++	beat_pm_poweroff_flag = 0;
++	ctrl_alt_del();
++	return IRQ_HANDLED;
++}
++
++static struct beat_event_list {
++	const char *typecode;
++	irq_handler_t handler;
++	unsigned int virq;
++} beat_event_list[] = {
++	{ "power", beat_power_event, 0 },
++	{ "reset", beat_reset_event, 0 },
++};
++
++static int __init beat_register_event(void)
++{
++	u64 path[4], data[2];
++	int rc, i;
++	unsigned int virq;
++
++	for (i = 0; i < ARRAY_SIZE(beat_event_list); i++) {
++		struct beat_event_list *ev = &beat_event_list[i];
++
++		if (beat_construct_event_receive_port(data) != 0) {
++			printk(KERN_ERR "Beat: "
++			       "cannot construct event receive port for %s\n",
++			       ev->typecode);
++			return -EINVAL;
++		}
++
++		virq = irq_create_mapping(NULL, data[0]);
++		if (virq == NO_IRQ) {
++			printk(KERN_ERR "Beat: failed to get virtual IRQ"
++			       " for event receive port for %s\n",
++			       ev->typecode);
++			beat_destruct_event_receive_port(data[0]);
++			return -EIO;
++		}
++		ev->virq = virq;
++
++		rc = request_irq(virq, ev->handler, IRQF_DISABLED,
++				      ev->typecode, NULL);
++		if (rc != 0) {
++			printk(KERN_ERR "Beat: failed to request virtual IRQ"
++			       " for event receive port for %s\n",
++			       ev->typecode);
++			beat_destruct_event_receive_port(data[0]);
++			return rc;
++		}
++
++		path[0] = 0x1000000065780000ul;	/* 1,ex */
++		path[1] = 0x627574746f6e0000ul;	/* button */
++		path[2] = 0;
++		strncpy((char *)&path[2], ev->typecode, 8);
++		path[3] = 0;
++		data[1] = 0;
++
++		beat_create_repository_node(path, data);
++	}
++	return 0;
++}
++
++static int __init beat_event_init(void)
++{
++	if (!firmware_has_feature(FW_FEATURE_BEAT))
++		return -EINVAL;
++
++	beat_pm_poweroff_flag = 0;
++	return beat_register_event();
++}
++
++device_initcall(beat_event_init);
+diff --git a/arch/powerpc/platforms/cell/beat.h b/arch/powerpc/platforms/cell/beat.h
+new file mode 100644
+index 0000000..32c8efc
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat.h
+@@ -0,0 +1,39 @@
++/*
++ * Guest OS Interfaces.
++ *
++ * (C) Copyright 2006 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef _CELLEB_BEAT_H
++#define _CELLEB_BEAT_H
++
++int64_t beat_get_term_char(uint64_t, uint64_t *, uint64_t *, uint64_t *);
++int64_t beat_put_term_char(uint64_t, uint64_t, uint64_t, uint64_t);
++int64_t beat_repository_encode(int, const char *, uint64_t[4]);
++void beat_restart(char *);
++void beat_power_off(void);
++void beat_halt(void);
++int beat_set_rtc_time(struct rtc_time *);
++void beat_get_rtc_time(struct rtc_time *);
++ssize_t beat_nvram_get_size(void);
++ssize_t beat_nvram_read(char *, size_t, loff_t *);
++ssize_t beat_nvram_write(char *, size_t, loff_t *);
++int beat_set_xdabr(unsigned long);
++void beat_power_save(void);
++void beat_kexec_cpu_down(int, int);
++
++#endif /* _CELLEB_BEAT_H */
+diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c
+new file mode 100644
+index 0000000..81467ff
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_htab.c
+@@ -0,0 +1,441 @@
++/*
++ * "Cell Reference Set" HTAB support.
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/pseries/lpar.c:
++ *  Copyright (C) 2001 Todd Inglett, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU 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.
++ */
++
++#undef DEBUG_LOW
++
++#include <linux/kernel.h>
++#include <linux/spinlock.h>
++
++#include <asm/mmu.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/machdep.h>
++#include <asm/udbg.h>
++
++#include "beat_wrapper.h"
++
++#ifdef DEBUG_LOW
++#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while (0)
++#else
++#define DBG_LOW(fmt...) do { } while (0)
++#endif
++
++static DEFINE_SPINLOCK(beat_htab_lock);
++
++static inline unsigned int beat_read_mask(unsigned hpte_group)
++{
++	unsigned long hpte_v[5];
++	unsigned long rmask = 0;
++
++	beat_read_htab_entries(0, hpte_group + 0, hpte_v);
++	if (!(hpte_v[0] & HPTE_V_BOLTED))
++		rmask |= 0x8000;
++	if (!(hpte_v[1] & HPTE_V_BOLTED))
++		rmask |= 0x4000;
++	if (!(hpte_v[2] & HPTE_V_BOLTED))
++		rmask |= 0x2000;
++	if (!(hpte_v[3] & HPTE_V_BOLTED))
++		rmask |= 0x1000;
++	beat_read_htab_entries(0, hpte_group + 4, hpte_v);
++	if (!(hpte_v[0] & HPTE_V_BOLTED))
++		rmask |= 0x0800;
++	if (!(hpte_v[1] & HPTE_V_BOLTED))
++		rmask |= 0x0400;
++	if (!(hpte_v[2] & HPTE_V_BOLTED))
++		rmask |= 0x0200;
++	if (!(hpte_v[3] & HPTE_V_BOLTED))
++		rmask |= 0x0100;
++	hpte_group = ~hpte_group & (htab_hash_mask * HPTES_PER_GROUP);
++	beat_read_htab_entries(0, hpte_group + 0, hpte_v);
++	if (!(hpte_v[0] & HPTE_V_BOLTED))
++		rmask |= 0x80;
++	if (!(hpte_v[1] & HPTE_V_BOLTED))
++		rmask |= 0x40;
++	if (!(hpte_v[2] & HPTE_V_BOLTED))
++		rmask |= 0x20;
++	if (!(hpte_v[3] & HPTE_V_BOLTED))
++		rmask |= 0x10;
++	beat_read_htab_entries(0, hpte_group + 4, hpte_v);
++	if (!(hpte_v[0] & HPTE_V_BOLTED))
++		rmask |= 0x08;
++	if (!(hpte_v[1] & HPTE_V_BOLTED))
++		rmask |= 0x04;
++	if (!(hpte_v[2] & HPTE_V_BOLTED))
++		rmask |= 0x02;
++	if (!(hpte_v[3] & HPTE_V_BOLTED))
++		rmask |= 0x01;
++	return rmask;
++}
++
++static long beat_lpar_hpte_insert(unsigned long hpte_group,
++				  unsigned long va, unsigned long pa,
++				  unsigned long rflags, unsigned long vflags,
++				  int psize, int ssize)
++{
++	unsigned long lpar_rc;
++	unsigned long slot;
++	unsigned long hpte_v, hpte_r;
++
++	/* same as iseries */
++	if (vflags & HPTE_V_SECONDARY)
++		return -1;
++
++	if (!(vflags & HPTE_V_BOLTED))
++		DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
++			"rflags=%lx, vflags=%lx, psize=%d)\n",
++		hpte_group, va, pa, rflags, vflags, psize);
++
++	hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
++		vflags | HPTE_V_VALID;
++	hpte_r = hpte_encode_r(pa, psize) | rflags;
++
++	if (!(vflags & HPTE_V_BOLTED))
++		DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
++
++	if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
++		hpte_r &= ~_PAGE_COHERENT;
++
++	spin_lock(&beat_htab_lock);
++	lpar_rc = beat_read_mask(hpte_group);
++	if (lpar_rc == 0) {
++		if (!(vflags & HPTE_V_BOLTED))
++			DBG_LOW(" full\n");
++		spin_unlock(&beat_htab_lock);
++		return -1;
++	}
++
++	lpar_rc = beat_insert_htab_entry(0, hpte_group, lpar_rc << 48,
++		hpte_v, hpte_r, &slot);
++	spin_unlock(&beat_htab_lock);
++
++	/*
++	 * Since we try and ioremap PHBs we don't own, the pte insert
++	 * will fail. However we must catch the failure in hash_page
++	 * or we will loop forever, so return -2 in this case.
++	 */
++	if (unlikely(lpar_rc != 0)) {
++		if (!(vflags & HPTE_V_BOLTED))
++			DBG_LOW(" lpar err %lx\n", lpar_rc);
++		return -2;
++	}
++	if (!(vflags & HPTE_V_BOLTED))
++		DBG_LOW(" -> slot: %lx\n", slot);
++
++	/* We have to pass down the secondary bucket bit here as well */
++	return (slot ^ hpte_group) & 15;
++}
++
++static long beat_lpar_hpte_remove(unsigned long hpte_group)
++{
++	DBG_LOW("hpte_remove(group=%lx)\n", hpte_group);
++	return -1;
++}
++
++static unsigned long beat_lpar_hpte_getword0(unsigned long slot)
++{
++	unsigned long dword0, dword[5];
++	unsigned long lpar_rc;
++
++	lpar_rc = beat_read_htab_entries(0, slot & ~3UL, dword);
++
++	dword0 = dword[slot&3];
++
++	BUG_ON(lpar_rc != 0);
++
++	return dword0;
++}
++
++static void beat_lpar_hptab_clear(void)
++{
++	unsigned long size_bytes = 1UL << ppc64_pft_size;
++	unsigned long hpte_count = size_bytes >> 4;
++	int i;
++	unsigned long dummy0, dummy1;
++
++	/* TODO: Use bulk call */
++	for (i = 0; i < hpte_count; i++)
++		beat_write_htab_entry(0, i, 0, 0, -1UL, -1UL, &dummy0, &dummy1);
++}
++
++/*
++ * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
++ * the low 3 bits of flags happen to line up.  So no transform is needed.
++ * We can probably optimize here and assume the high bits of newpp are
++ * already zero.  For now I am paranoid.
++ */
++static long beat_lpar_hpte_updatepp(unsigned long slot,
++				    unsigned long newpp,
++				    unsigned long va,
++				    int psize, int ssize, int local)
++{
++	unsigned long lpar_rc;
++	unsigned long dummy0, dummy1, want_v;
++
++	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++
++	DBG_LOW("    update: "
++		"avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
++		want_v & HPTE_V_AVPN, slot, psize, newpp);
++
++	spin_lock(&beat_htab_lock);
++	dummy0 = beat_lpar_hpte_getword0(slot);
++	if ((dummy0 & ~0x7FUL) != (want_v & ~0x7FUL)) {
++		DBG_LOW("not found !\n");
++		spin_unlock(&beat_htab_lock);
++		return -1;
++	}
++
++	lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7, &dummy0,
++					&dummy1);
++	spin_unlock(&beat_htab_lock);
++	if (lpar_rc != 0 || dummy0 == 0) {
++		DBG_LOW("not found !\n");
++		return -1;
++	}
++
++	DBG_LOW("ok %lx %lx\n", dummy0, dummy1);
++
++	BUG_ON(lpar_rc != 0);
++
++	return 0;
++}
++
++static long beat_lpar_hpte_find(unsigned long va, int psize)
++{
++	unsigned long hash;
++	unsigned long i, j;
++	long slot;
++	unsigned long want_v, hpte_v;
++
++	hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
++	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++
++	for (j = 0; j < 2; j++) {
++		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
++		for (i = 0; i < HPTES_PER_GROUP; i++) {
++			hpte_v = beat_lpar_hpte_getword0(slot);
++
++			if (HPTE_V_COMPARE(hpte_v, want_v)
++			    && (hpte_v & HPTE_V_VALID)
++			    && (!!(hpte_v & HPTE_V_SECONDARY) == j)) {
++				/* HPTE matches */
++				if (j)
++					slot = -slot;
++				return slot;
++			}
++			++slot;
++		}
++		hash = ~hash;
++	}
++
++	return -1;
++}
++
++static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
++					  unsigned long ea,
++					  int psize, int ssize)
++{
++	unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1;
++
++	vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
++	va = (vsid << 28) | (ea & 0x0fffffff);
++
++	spin_lock(&beat_htab_lock);
++	slot = beat_lpar_hpte_find(va, psize);
++	BUG_ON(slot == -1);
++
++	lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
++		&dummy0, &dummy1);
++	spin_unlock(&beat_htab_lock);
++
++	BUG_ON(lpar_rc != 0);
++}
++
++static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
++					 int psize, int ssize, int local)
++{
++	unsigned long want_v;
++	unsigned long lpar_rc;
++	unsigned long dummy1, dummy2;
++	unsigned long flags;
++
++	DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
++		slot, va, psize, local);
++	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++
++	spin_lock_irqsave(&beat_htab_lock, flags);
++	dummy1 = beat_lpar_hpte_getword0(slot);
++
++	if ((dummy1 & ~0x7FUL) != (want_v & ~0x7FUL)) {
++		DBG_LOW("not found !\n");
++		spin_unlock_irqrestore(&beat_htab_lock, flags);
++		return;
++	}
++
++	lpar_rc = beat_write_htab_entry(0, slot, 0, 0, HPTE_V_VALID, 0,
++		&dummy1, &dummy2);
++	spin_unlock_irqrestore(&beat_htab_lock, flags);
++
++	BUG_ON(lpar_rc != 0);
++}
++
++void __init hpte_init_beat(void)
++{
++	ppc_md.hpte_invalidate	= beat_lpar_hpte_invalidate;
++	ppc_md.hpte_updatepp	= beat_lpar_hpte_updatepp;
++	ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
++	ppc_md.hpte_insert	= beat_lpar_hpte_insert;
++	ppc_md.hpte_remove	= beat_lpar_hpte_remove;
++	ppc_md.hpte_clear_all	= beat_lpar_hptab_clear;
++}
++
++static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
++				  unsigned long va, unsigned long pa,
++				  unsigned long rflags, unsigned long vflags,
++				  int psize, int ssize)
++{
++	unsigned long lpar_rc;
++	unsigned long slot;
++	unsigned long hpte_v, hpte_r;
++
++	/* same as iseries */
++	if (vflags & HPTE_V_SECONDARY)
++		return -1;
++
++	if (!(vflags & HPTE_V_BOLTED))
++		DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
++			"rflags=%lx, vflags=%lx, psize=%d)\n",
++		hpte_group, va, pa, rflags, vflags, psize);
++
++	hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
++		vflags | HPTE_V_VALID;
++	hpte_r = hpte_encode_r(pa, psize) | rflags;
++
++	if (!(vflags & HPTE_V_BOLTED))
++		DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
++
++	if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
++		hpte_r &= ~_PAGE_COHERENT;
++
++	/* insert into not-volted entry */
++	lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r,
++		HPTE_V_BOLTED, 0, &slot);
++	/*
++	 * Since we try and ioremap PHBs we don't own, the pte insert
++	 * will fail. However we must catch the failure in hash_page
++	 * or we will loop forever, so return -2 in this case.
++	 */
++	if (unlikely(lpar_rc != 0)) {
++		if (!(vflags & HPTE_V_BOLTED))
++			DBG_LOW(" lpar err %lx\n", lpar_rc);
++		return -2;
++	}
++	if (!(vflags & HPTE_V_BOLTED))
++		DBG_LOW(" -> slot: %lx\n", slot);
++
++	/* We have to pass down the secondary bucket bit here as well */
++	return (slot ^ hpte_group) & 15;
++}
++
++/*
++ * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
++ * the low 3 bits of flags happen to line up.  So no transform is needed.
++ * We can probably optimize here and assume the high bits of newpp are
++ * already zero.  For now I am paranoid.
++ */
++static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
++				    unsigned long newpp,
++				    unsigned long va,
++				    int psize, int ssize, int local)
++{
++	unsigned long lpar_rc;
++	unsigned long want_v;
++	unsigned long pss;
++
++	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++	pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
++
++	DBG_LOW("    update: "
++		"avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
++		want_v & HPTE_V_AVPN, slot, psize, newpp);
++
++	lpar_rc = beat_update_htab_permission3(0, slot, want_v, pss, 7, newpp);
++
++	if (lpar_rc == 0xfffffff7) {
++		DBG_LOW("not found !\n");
++		return -1;
++	}
++
++	DBG_LOW("ok\n");
++
++	BUG_ON(lpar_rc != 0);
++
++	return 0;
++}
++
++static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
++					 int psize, int ssize, int local)
++{
++	unsigned long want_v;
++	unsigned long lpar_rc;
++	unsigned long pss;
++
++	DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
++		slot, va, psize, local);
++	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++	pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
++
++	lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
++
++	/* E_busy can be valid output: page may be already replaced */
++	BUG_ON(lpar_rc != 0 && lpar_rc != 0xfffffff7);
++}
++
++static int64_t _beat_lpar_hptab_clear_v3(void)
++{
++	return beat_clear_htab3(0);
++}
++
++static void beat_lpar_hptab_clear_v3(void)
++{
++	_beat_lpar_hptab_clear_v3();
++}
++
++void __init hpte_init_beat_v3(void)
++{
++	if (_beat_lpar_hptab_clear_v3() == 0) {
++		ppc_md.hpte_invalidate	= beat_lpar_hpte_invalidate_v3;
++		ppc_md.hpte_updatepp	= beat_lpar_hpte_updatepp_v3;
++		ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
++		ppc_md.hpte_insert	= beat_lpar_hpte_insert_v3;
++		ppc_md.hpte_remove	= beat_lpar_hpte_remove;
++		ppc_md.hpte_clear_all	= beat_lpar_hptab_clear_v3;
++	} else {
++		ppc_md.hpte_invalidate	= beat_lpar_hpte_invalidate;
++		ppc_md.hpte_updatepp	= beat_lpar_hpte_updatepp;
++		ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
++		ppc_md.hpte_insert	= beat_lpar_hpte_insert;
++		ppc_md.hpte_remove	= beat_lpar_hpte_remove;
++		ppc_md.hpte_clear_all	= beat_lpar_hptab_clear;
++	}
++}
+diff --git a/arch/powerpc/platforms/cell/beat_hvCall.S b/arch/powerpc/platforms/cell/beat_hvCall.S
+new file mode 100644
+index 0000000..74c8174
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_hvCall.S
+@@ -0,0 +1,287 @@
++/*
++ * Beat hypervisor call I/F
++ *
++ * (C) Copyright 2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/pseries/hvCall.S.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU 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 <asm/ppc_asm.h>
++
++#define	STK_PARM(i)	(48 + ((i)-3)*8)
++
++/* Not implemented on Beat, now */
++#define	HCALL_INST_PRECALL
++#define	HCALL_INST_POSTCALL
++
++	.text
++
++#define	HVSC	.long	0x44000022
++
++/* Note: takes only 7 input parameters at maximum */
++_GLOBAL(beat_hcall_norets)
++	HMT_MEDIUM
++
++	mfcr	r0
++	stw	r0,8(r1)
++
++	HCALL_INST_PRECALL
++
++	mr	r11,r3
++	mr	r3,r4
++	mr	r4,r5
++	mr	r5,r6
++	mr	r6,r7
++	mr	r7,r8
++	mr	r8,r9
++
++	HVSC				/* invoke the hypervisor */
++
++	HCALL_INST_POSTCALL
++
++	lwz	r0,8(r1)
++	mtcrf	0xff,r0
++
++	blr				/* return r3 = status */
++
++/* Note: takes 8 input parameters at maximum */
++_GLOBAL(beat_hcall_norets8)
++	HMT_MEDIUM
++
++	mfcr	r0
++	stw	r0,8(r1)
++
++	HCALL_INST_PRECALL
++
++	mr	r11,r3
++	mr	r3,r4
++	mr	r4,r5
++	mr	r5,r6
++	mr	r6,r7
++	mr	r7,r8
++	mr	r8,r9
++	ld	r10,STK_PARM(r10)(r1)
++
++	HVSC				/* invoke the hypervisor */
++
++	HCALL_INST_POSTCALL
++
++	lwz	r0,8(r1)
++	mtcrf	0xff,r0
++
++	blr				/* return r3 = status */
++
++/* Note: takes only 6 input parameters, 1 output parameters at maximum */
++_GLOBAL(beat_hcall1)
++	HMT_MEDIUM
++
++	mfcr	r0
++	stw	r0,8(r1)
++
++	HCALL_INST_PRECALL
++
++	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
++
++	mr	r11,r3
++	mr	r3,r5
++	mr	r4,r6
++	mr	r5,r7
++	mr	r6,r8
++	mr	r7,r9
++	mr	r8,r10
++
++	HVSC				/* invoke the hypervisor */
++
++	HCALL_INST_POSTCALL
++
++	ld	r12,STK_PARM(r4)(r1)
++	std	r4,  0(r12)
++
++	lwz	r0,8(r1)
++	mtcrf	0xff,r0
++
++	blr				/* return r3 = status */
++
++/* Note: takes only 6 input parameters, 2 output parameters at maximum */
++_GLOBAL(beat_hcall2)
++	HMT_MEDIUM
++
++	mfcr	r0
++	stw	r0,8(r1)
++
++	HCALL_INST_PRECALL
++
++	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
++
++	mr	r11,r3
++	mr	r3,r5
++	mr	r4,r6
++	mr	r5,r7
++	mr	r6,r8
++	mr	r7,r9
++	mr	r8,r10
++
++	HVSC				/* invoke the hypervisor */
++
++	HCALL_INST_POSTCALL
++
++	ld	r12,STK_PARM(r4)(r1)
++	std	r4,  0(r12)
++	std	r5,  8(r12)
++
++	lwz	r0,8(r1)
++	mtcrf	0xff,r0
++
++	blr				/* return r3 = status */
++
++/* Note: takes only 6 input parameters, 3 output parameters at maximum */
++_GLOBAL(beat_hcall3)
++	HMT_MEDIUM
++
++	mfcr	r0
++	stw	r0,8(r1)
++
++	HCALL_INST_PRECALL
++
++	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
++
++	mr	r11,r3
++	mr	r3,r5
++	mr	r4,r6
++	mr	r5,r7
++	mr	r6,r8
++	mr	r7,r9
++	mr	r8,r10
++
++	HVSC				/* invoke the hypervisor */
++
++	HCALL_INST_POSTCALL
++
++	ld	r12,STK_PARM(r4)(r1)
++	std	r4,  0(r12)
++	std	r5,  8(r12)
++	std	r6, 16(r12)
++
++	lwz	r0,8(r1)
++	mtcrf	0xff,r0
++
++	blr				/* return r3 = status */
++
++/* Note: takes only 6 input parameters, 4 output parameters at maximum */
++_GLOBAL(beat_hcall4)
++	HMT_MEDIUM
++
++	mfcr	r0
++	stw	r0,8(r1)
++
++	HCALL_INST_PRECALL
++
++	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
++
++	mr	r11,r3
++	mr	r3,r5
++	mr	r4,r6
++	mr	r5,r7
++	mr	r6,r8
++	mr	r7,r9
++	mr	r8,r10
++
++	HVSC				/* invoke the hypervisor */
++
++	HCALL_INST_POSTCALL
++
++	ld	r12,STK_PARM(r4)(r1)
++	std	r4,  0(r12)
++	std	r5,  8(r12)
++	std	r6, 16(r12)
++	std	r7, 24(r12)
++
++	lwz	r0,8(r1)
++	mtcrf	0xff,r0
++
++	blr				/* return r3 = status */
++
++/* Note: takes only 6 input parameters, 5 output parameters at maximum */
++_GLOBAL(beat_hcall5)
++	HMT_MEDIUM
++
++	mfcr	r0
++	stw	r0,8(r1)
++
++	HCALL_INST_PRECALL
++
++	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
++
++	mr	r11,r3
++	mr	r3,r5
++	mr	r4,r6
++	mr	r5,r7
++	mr	r6,r8
++	mr	r7,r9
++	mr	r8,r10
++
++	HVSC				/* invoke the hypervisor */
++
++	HCALL_INST_POSTCALL
++
++	ld	r12,STK_PARM(r4)(r1)
++	std	r4,  0(r12)
++	std	r5,  8(r12)
++	std	r6, 16(r12)
++	std	r7, 24(r12)
++	std	r8, 32(r12)
++
++	lwz	r0,8(r1)
++	mtcrf	0xff,r0
++
++	blr				/* return r3 = status */
++
++/* Note: takes only 6 input parameters, 6 output parameters at maximum */
++_GLOBAL(beat_hcall6)
++	HMT_MEDIUM
++
++	mfcr	r0
++	stw	r0,8(r1)
++
++	HCALL_INST_PRECALL
++
++	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
++
++	mr	r11,r3
++	mr	r3,r5
++	mr	r4,r6
++	mr	r5,r7
++	mr	r6,r8
++	mr	r7,r9
++	mr	r8,r10
++
++	HVSC				/* invoke the hypervisor */
++
++	HCALL_INST_POSTCALL
++
++	ld	r12,STK_PARM(r4)(r1)
++	std	r4,  0(r12)
++	std	r5,  8(r12)
++	std	r6, 16(r12)
++	std	r7, 24(r12)
++	std	r8, 32(r12)
++	std	r9, 40(r12)
++
++	lwz	r0,8(r1)
++	mtcrf	0xff,r0
++
++	blr				/* return r3 = status */
+diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c
+new file mode 100644
+index 0000000..192a935
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_interrupt.c
+@@ -0,0 +1,283 @@
++/*
++ * Celleb/Beat Interrupt controller
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/percpu.h>
++#include <linux/types.h>
++
++#include <asm/machdep.h>
++
++#include "beat_interrupt.h"
++#include "beat_wrapper.h"
++
++#define	MAX_IRQS	NR_IRQS
++static DEFINE_SPINLOCK(beatic_irq_mask_lock);
++static uint64_t	beatic_irq_mask_enable[(MAX_IRQS+255)/64];
++static uint64_t	beatic_irq_mask_ack[(MAX_IRQS+255)/64];
++
++static struct irq_host *beatic_host;
++
++/*
++ * In this implementation, "virq" == "IRQ plug number",
++ * "(irq_hw_number_t)hwirq" == "IRQ outlet number".
++ */
++
++/* assumption: locked */
++static inline void beatic_update_irq_mask(unsigned int irq_plug)
++{
++	int off;
++	unsigned long masks[4];
++
++	off = (irq_plug / 256) * 4;
++	masks[0] = beatic_irq_mask_enable[off + 0]
++		& beatic_irq_mask_ack[off + 0];
++	masks[1] = beatic_irq_mask_enable[off + 1]
++		& beatic_irq_mask_ack[off + 1];
++	masks[2] = beatic_irq_mask_enable[off + 2]
++		& beatic_irq_mask_ack[off + 2];
++	masks[3] = beatic_irq_mask_enable[off + 3]
++		& beatic_irq_mask_ack[off + 3];
++	if (beat_set_interrupt_mask(irq_plug&~255UL,
++		masks[0], masks[1], masks[2], masks[3]) != 0)
++		panic("Failed to set mask IRQ!");
++}
++
++static void beatic_mask_irq(unsigned int irq_plug)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&beatic_irq_mask_lock, flags);
++	beatic_irq_mask_enable[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
++	beatic_update_irq_mask(irq_plug);
++	spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
++}
++
++static void beatic_unmask_irq(unsigned int irq_plug)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&beatic_irq_mask_lock, flags);
++	beatic_irq_mask_enable[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
++	beatic_update_irq_mask(irq_plug);
++	spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
++}
++
++static void beatic_ack_irq(unsigned int irq_plug)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&beatic_irq_mask_lock, flags);
++	beatic_irq_mask_ack[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
++	beatic_update_irq_mask(irq_plug);
++	spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
++}
++
++static void beatic_end_irq(unsigned int irq_plug)
++{
++	s64 err;
++	unsigned long flags;
++
++	err = beat_downcount_of_interrupt(irq_plug);
++	if (err != 0) {
++		if ((err & 0xFFFFFFFF) != 0xFFFFFFF5) /* -11: wrong state */
++			panic("Failed to downcount IRQ! Error = %16lx", err);
++
++		printk(KERN_ERR "IRQ over-downcounted, plug %d\n", irq_plug);
++	}
++	spin_lock_irqsave(&beatic_irq_mask_lock, flags);
++	beatic_irq_mask_ack[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
++	beatic_update_irq_mask(irq_plug);
++	spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
++}
++
++static struct irq_chip beatic_pic = {
++	.typename = " CELL-BEAT ",
++	.unmask = beatic_unmask_irq,
++	.mask = beatic_mask_irq,
++	.eoi = beatic_end_irq,
++};
++
++/*
++ * Dispose binding hardware IRQ number (hw) and Virtuql IRQ number (virq),
++ * update flags.
++ *
++ * Note that the number (virq) is already assigned at upper layer.
++ */
++static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq)
++{
++	beat_destruct_irq_plug(virq);
++}
++
++/*
++ * Create or update binding hardware IRQ number (hw) and Virtuql
++ * IRQ number (virq). This is called only once for a given mapping.
++ *
++ * Note that the number (virq) is already assigned at upper layer.
++ */
++static int beatic_pic_host_map(struct irq_host *h, unsigned int virq,
++			       irq_hw_number_t hw)
++{
++	struct irq_desc *desc = get_irq_desc(virq);
++	int64_t	err;
++
++	err = beat_construct_and_connect_irq_plug(virq, hw);
++	if (err < 0)
++		return -EIO;
++
++	desc->status |= IRQ_LEVEL;
++	set_irq_chip_and_handler(virq, &beatic_pic, handle_fasteoi_irq);
++	return 0;
++}
++
++/*
++ * Update binding hardware IRQ number (hw) and Virtuql
++ * IRQ number (virq). This is called only once for a given mapping.
++ */
++static void beatic_pic_host_remap(struct irq_host *h, unsigned int virq,
++			       irq_hw_number_t hw)
++{
++	beat_construct_and_connect_irq_plug(virq, hw);
++}
++
++/*
++ * Translate device-tree interrupt spec to irq_hw_number_t style (ulong),
++ * to pass away to irq_create_mapping().
++ *
++ * Called from irq_create_of_mapping() only.
++ * Note: We have only 1 entry to translate.
++ */
++static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct,
++				 u32 *intspec, unsigned int intsize,
++				 irq_hw_number_t *out_hwirq,
++				 unsigned int *out_flags)
++{
++	u64 *intspec2 = (u64 *)intspec;
++
++	*out_hwirq = *intspec2;
++	*out_flags |= IRQ_TYPE_LEVEL_LOW;
++	return 0;
++}
++
++static int beatic_pic_host_match(struct irq_host *h, struct device_node *np)
++{
++	/* Match all */
++	return 1;
++}
++
++static struct irq_host_ops beatic_pic_host_ops = {
++	.map = beatic_pic_host_map,
++	.remap = beatic_pic_host_remap,
++	.unmap = beatic_pic_host_unmap,
++	.xlate = beatic_pic_host_xlate,
++	.match = beatic_pic_host_match,
++};
++
++/*
++ * Get an IRQ number
++ * Note: returns VIRQ
++ */
++static inline unsigned int beatic_get_irq_plug(void)
++{
++	int i;
++	uint64_t	pending[4], ub;
++
++	for (i = 0; i < MAX_IRQS; i += 256) {
++		beat_detect_pending_interrupts(i, pending);
++		__asm__ ("cntlzd %0,%1":"=r"(ub):
++			"r"(pending[0] & beatic_irq_mask_enable[i/64+0]
++				       & beatic_irq_mask_ack[i/64+0]));
++		if (ub != 64)
++			return i + ub + 0;
++		__asm__ ("cntlzd %0,%1":"=r"(ub):
++			"r"(pending[1] & beatic_irq_mask_enable[i/64+1]
++				       & beatic_irq_mask_ack[i/64+1]));
++		if (ub != 64)
++			return i + ub + 64;
++		__asm__ ("cntlzd %0,%1":"=r"(ub):
++			"r"(pending[2] & beatic_irq_mask_enable[i/64+2]
++				       & beatic_irq_mask_ack[i/64+2]));
++		if (ub != 64)
++			return i + ub + 128;
++		__asm__ ("cntlzd %0,%1":"=r"(ub):
++			"r"(pending[3] & beatic_irq_mask_enable[i/64+3]
++				       & beatic_irq_mask_ack[i/64+3]));
++		if (ub != 64)
++			return i + ub + 192;
++	}
++
++	return NO_IRQ;
++}
++unsigned int beatic_get_irq(void)
++{
++	unsigned int ret;
++
++	ret = beatic_get_irq_plug();
++	if (ret != NO_IRQ)
++		beatic_ack_irq(ret);
++	return ret;
++}
++
++/*
++ */
++void __init beatic_init_IRQ(void)
++{
++	int	i;
++
++	memset(beatic_irq_mask_enable, 0, sizeof(beatic_irq_mask_enable));
++	memset(beatic_irq_mask_ack, 255, sizeof(beatic_irq_mask_ack));
++	for (i = 0; i < MAX_IRQS; i += 256)
++		beat_set_interrupt_mask(i, 0L, 0L, 0L, 0L);
++
++	/* Set out get_irq function */
++	ppc_md.get_irq = beatic_get_irq;
++
++	/* Allocate an irq host */
++	beatic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0,
++				     &beatic_pic_host_ops,
++					 0);
++	BUG_ON(beatic_host == NULL);
++	irq_set_default_host(beatic_host);
++}
++
++#ifdef CONFIG_SMP
++
++/* Nullified to compile with SMP mode */
++void beatic_setup_cpu(int cpu)
++{
++}
++
++void beatic_cause_IPI(int cpu, int mesg)
++{
++}
++
++void beatic_request_IPIs(void)
++{
++}
++#endif /* CONFIG_SMP */
++
++void beatic_deinit_IRQ(void)
++{
++	int	i;
++
++	for (i = 1; i < NR_IRQS; i++)
++		beat_destruct_irq_plug(i);
++}
+diff --git a/arch/powerpc/platforms/cell/beat_interrupt.h b/arch/powerpc/platforms/cell/beat_interrupt.h
+new file mode 100644
+index 0000000..b470fd0
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_interrupt.h
+@@ -0,0 +1,33 @@
++/*
++ * Celleb/Beat Interrupt controller
++ *
++ * (C) Copyright 2006 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef ASM_BEAT_PIC_H
++#define ASM_BEAT_PIC_H
++#ifdef __KERNEL__
++
++extern void beatic_init_IRQ(void);
++extern unsigned int beatic_get_irq(void);
++extern void beatic_cause_IPI(int cpu, int mesg);
++extern void beatic_request_IPIs(void);
++extern void beatic_setup_cpu(int);
++extern void beatic_deinit_IRQ(void);
++
++#endif
++#endif /* ASM_BEAT_PIC_H */
+diff --git a/arch/powerpc/platforms/cell/beat_iommu.c b/arch/powerpc/platforms/cell/beat_iommu.c
+new file mode 100644
+index 0000000..93b0efd
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_iommu.c
+@@ -0,0 +1,116 @@
++/*
++ * Support for IOMMU on Celleb platform.
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/dma-mapping.h>
++#include <linux/pci.h>
++#include <linux/of_platform.h>
++
++#include <asm/machdep.h>
++
++#include "beat_wrapper.h"
++
++#define DMA_FLAGS 0xf800000000000000UL	/* r/w permitted, coherency required,
++					   strongest order */
++
++static int __init find_dma_window(u64 *io_space_id, u64 *ioid,
++				  u64 *base, u64 *size, u64 *io_page_size)
++{
++	struct device_node *dn;
++	const unsigned long *dma_window;
++
++	for_each_node_by_type(dn, "ioif") {
++		dma_window = of_get_property(dn, "toshiba,dma-window", NULL);
++		if (dma_window) {
++			*io_space_id = (dma_window[0] >> 32) & 0xffffffffUL;
++			*ioid = dma_window[0] & 0x7ffUL;
++			*base = dma_window[1];
++			*size = dma_window[2];
++			*io_page_size = 1 << dma_window[3];
++			of_node_put(dn);
++			return 1;
++		}
++	}
++	return 0;
++}
++
++static unsigned long celleb_dma_direct_offset;
++
++static void __init celleb_init_direct_mapping(void)
++{
++	u64 lpar_addr, io_addr;
++	u64 io_space_id, ioid, dma_base, dma_size, io_page_size;
++
++	if (!find_dma_window(&io_space_id, &ioid, &dma_base, &dma_size,
++			     &io_page_size)) {
++		pr_info("No dma window found !\n");
++		return;
++	}
++
++	for (lpar_addr = 0; lpar_addr < dma_size; lpar_addr += io_page_size) {
++		io_addr = lpar_addr + dma_base;
++		(void)beat_put_iopte(io_space_id, io_addr, lpar_addr,
++				     ioid, DMA_FLAGS);
++	}
++
++	celleb_dma_direct_offset = dma_base;
++}
++
++static void celleb_dma_dev_setup(struct device *dev)
++{
++	dev->archdata.dma_ops = get_pci_dma_ops();
++	dev->archdata.dma_data = (void *)celleb_dma_direct_offset;
++}
++
++static void celleb_pci_dma_dev_setup(struct pci_dev *pdev)
++{
++	celleb_dma_dev_setup(&pdev->dev);
++}
++
++static int celleb_of_bus_notify(struct notifier_block *nb,
++				unsigned long action, void *data)
++{
++	struct device *dev = data;
++
++	/* We are only intereted in device addition */
++	if (action != BUS_NOTIFY_ADD_DEVICE)
++		return 0;
++
++	celleb_dma_dev_setup(dev);
++
++	return 0;
++}
++
++static struct notifier_block celleb_of_bus_notifier = {
++	.notifier_call = celleb_of_bus_notify
++};
++
++static int __init celleb_init_iommu(void)
++{
++	celleb_init_direct_mapping();
++	set_pci_dma_ops(&dma_direct_ops);
++	ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup;
++	bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier);
++
++	return 0;
++}
++
++machine_arch_initcall(celleb_beat, celleb_init_iommu);
+diff --git a/arch/powerpc/platforms/cell/beat_smp.c b/arch/powerpc/platforms/cell/beat_smp.c
+new file mode 100644
+index 0000000..26efc20
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_smp.c
+@@ -0,0 +1,124 @@
++/*
++ * SMP support for Celleb platform. (Incomplete)
++ *
++ * (C) Copyright 2006 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/cell/smp.c:
++ * Dave Engebretsen, Peter Bergner, and
++ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
++ * Plus various changes from other IBM teams...
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU 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.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/smp.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/threads.h>
++#include <linux/cpu.h>
++
++#include <asm/irq.h>
++#include <asm/smp.h>
++#include <asm/machdep.h>
++#include <asm/udbg.h>
++
++#include "beat_interrupt.h"
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++/*
++ * The primary thread of each non-boot processor is recorded here before
++ * smp init.
++ */
++/* static cpumask_t of_spin_map; */
++
++/**
++ * smp_startup_cpu() - start the given cpu
++ *
++ * At boot time, there is nothing to do for primary threads which were
++ * started from Open Firmware.  For anything else, call RTAS with the
++ * appropriate start location.
++ *
++ * Returns:
++ *	0	- failure
++ *	1	- success
++ */
++static inline int __devinit smp_startup_cpu(unsigned int lcpu)
++{
++	return 0;
++}
++
++static void smp_beatic_message_pass(int target, int msg)
++{
++	unsigned int i;
++
++	if (target < NR_CPUS) {
++		beatic_cause_IPI(target, msg);
++	} else {
++		for_each_online_cpu(i) {
++			if (target == MSG_ALL_BUT_SELF
++			    && i == smp_processor_id())
++				continue;
++			beatic_cause_IPI(i, msg);
++		}
++	}
++}
++
++static int __init smp_beatic_probe(void)
++{
++	return cpus_weight(cpu_possible_map);
++}
++
++static void __devinit smp_beatic_setup_cpu(int cpu)
++{
++	beatic_setup_cpu(cpu);
++}
++
++static void __devinit smp_celleb_kick_cpu(int nr)
++{
++	BUG_ON(nr < 0 || nr >= NR_CPUS);
++
++	if (!smp_startup_cpu(nr))
++		return;
++}
++
++static int smp_celleb_cpu_bootable(unsigned int nr)
++{
++	return 1;
++}
++static struct smp_ops_t bpa_beatic_smp_ops = {
++	.message_pass	= smp_beatic_message_pass,
++	.probe		= smp_beatic_probe,
++	.kick_cpu	= smp_celleb_kick_cpu,
++	.setup_cpu	= smp_beatic_setup_cpu,
++	.cpu_bootable	= smp_celleb_cpu_bootable,
++};
++
++/* This is called very early */
++void __init smp_init_celleb(void)
++{
++	DBG(" -> smp_init_celleb()\n");
++
++	smp_ops = &bpa_beatic_smp_ops;
++
++	DBG(" <- smp_init_celleb()\n");
++}
+diff --git a/arch/powerpc/platforms/cell/beat_spu_priv1.c b/arch/powerpc/platforms/cell/beat_spu_priv1.c
+new file mode 100644
+index 0000000..bcc17f7
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_spu_priv1.c
+@@ -0,0 +1,207 @@
++/*
++ * spu hypervisor abstraction for Beat
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/module.h>
++
++#include <asm/types.h>
++#include <asm/spu.h>
++#include <asm/spu_priv1.h>
++
++#include "beat_wrapper.h"
++
++static inline void _int_mask_set(struct spu *spu, int class, u64 mask)
++{
++	spu->shadow_int_mask_RW[class] = mask;
++	beat_set_irq_mask_for_spe(spu->spe_id, class, mask);
++}
++
++static inline u64 _int_mask_get(struct spu *spu, int class)
++{
++	return spu->shadow_int_mask_RW[class];
++}
++
++static void int_mask_set(struct spu *spu, int class, u64 mask)
++{
++	_int_mask_set(spu, class, mask);
++}
++
++static u64 int_mask_get(struct spu *spu, int class)
++{
++	return _int_mask_get(spu, class);
++}
++
++static void int_mask_and(struct spu *spu, int class, u64 mask)
++{
++	u64 old_mask;
++	old_mask = _int_mask_get(spu, class);
++	_int_mask_set(spu, class, old_mask & mask);
++}
++
++static void int_mask_or(struct spu *spu, int class, u64 mask)
++{
++	u64 old_mask;
++	old_mask = _int_mask_get(spu, class);
++	_int_mask_set(spu, class, old_mask | mask);
++}
++
++static void int_stat_clear(struct spu *spu, int class, u64 stat)
++{
++	beat_clear_interrupt_status_of_spe(spu->spe_id, class, stat);
++}
++
++static u64 int_stat_get(struct spu *spu, int class)
++{
++	u64 int_stat;
++	beat_get_interrupt_status_of_spe(spu->spe_id, class, &int_stat);
++	return int_stat;
++}
++
++static void cpu_affinity_set(struct spu *spu, int cpu)
++{
++	return;
++}
++
++static u64 mfc_dar_get(struct spu *spu)
++{
++	u64 dar;
++	beat_get_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, mfc_dar_RW), &dar);
++	return dar;
++}
++
++static u64 mfc_dsisr_get(struct spu *spu)
++{
++	u64 dsisr;
++	beat_get_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, mfc_dsisr_RW), &dsisr);
++	return dsisr;
++}
++
++static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
++{
++	beat_set_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, mfc_dsisr_RW), dsisr);
++}
++
++static void mfc_sdr_setup(struct spu *spu)
++{
++	return;
++}
++
++static void mfc_sr1_set(struct spu *spu, u64 sr1)
++{
++	beat_set_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, mfc_sr1_RW), sr1);
++}
++
++static u64 mfc_sr1_get(struct spu *spu)
++{
++	u64 sr1;
++	beat_get_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, mfc_sr1_RW), &sr1);
++	return sr1;
++}
++
++static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
++{
++	beat_set_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, mfc_tclass_id_RW), tclass_id);
++}
++
++static u64 mfc_tclass_id_get(struct spu *spu)
++{
++	u64 tclass_id;
++	beat_get_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, mfc_tclass_id_RW), &tclass_id);
++	return tclass_id;
++}
++
++static void tlb_invalidate(struct spu *spu)
++{
++	beat_set_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, tlb_invalidate_entry_W), 0ul);
++}
++
++static void resource_allocation_groupID_set(struct spu *spu, u64 id)
++{
++	beat_set_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, resource_allocation_groupID_RW),
++		id);
++}
++
++static u64 resource_allocation_groupID_get(struct spu *spu)
++{
++	u64 id;
++	beat_get_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, resource_allocation_groupID_RW),
++		&id);
++	return id;
++}
++
++static void resource_allocation_enable_set(struct spu *spu, u64 enable)
++{
++	beat_set_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, resource_allocation_enable_RW),
++		enable);
++}
++
++static u64 resource_allocation_enable_get(struct spu *spu)
++{
++	u64 enable;
++	beat_get_spe_privileged_state_1_registers(
++		spu->spe_id,
++		offsetof(struct spu_priv1, resource_allocation_enable_RW),
++		&enable);
++	return enable;
++}
++
++const struct spu_priv1_ops spu_priv1_beat_ops = {
++	.int_mask_and = int_mask_and,
++	.int_mask_or = int_mask_or,
++	.int_mask_set = int_mask_set,
++	.int_mask_get = int_mask_get,
++	.int_stat_clear = int_stat_clear,
++	.int_stat_get = int_stat_get,
++	.cpu_affinity_set = cpu_affinity_set,
++	.mfc_dar_get = mfc_dar_get,
++	.mfc_dsisr_get = mfc_dsisr_get,
++	.mfc_dsisr_set = mfc_dsisr_set,
++	.mfc_sdr_setup = mfc_sdr_setup,
++	.mfc_sr1_set = mfc_sr1_set,
++	.mfc_sr1_get = mfc_sr1_get,
++	.mfc_tclass_id_set = mfc_tclass_id_set,
++	.mfc_tclass_id_get = mfc_tclass_id_get,
++	.tlb_invalidate = tlb_invalidate,
++	.resource_allocation_groupID_set = resource_allocation_groupID_set,
++	.resource_allocation_groupID_get = resource_allocation_groupID_get,
++	.resource_allocation_enable_set = resource_allocation_enable_set,
++	.resource_allocation_enable_get = resource_allocation_enable_get,
++};
+diff --git a/arch/powerpc/platforms/cell/beat_syscall.h b/arch/powerpc/platforms/cell/beat_syscall.h
+new file mode 100644
+index 0000000..8580dc7
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_syscall.h
+@@ -0,0 +1,164 @@
++/*
++ * Beat hypervisor call numbers
++ *
++ * (C) Copyright 2004-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef BEAT_BEAT_syscall_H
++#define BEAT_BEAT_syscall_H
++
++#ifdef	__ASSEMBLY__
++#define	__BEAT_ADD_VENDOR_ID(__x, __v)	((__v)<<60|(__x))
++#else
++#define	__BEAT_ADD_VENDOR_ID(__x, __v)	((u64)(__v)<<60|(__x))
++#endif
++#define HV_allocate_memory __BEAT_ADD_VENDOR_ID(0, 0)
++#define HV_construct_virtual_address_space __BEAT_ADD_VENDOR_ID(2, 0)
++#define HV_destruct_virtual_address_space __BEAT_ADD_VENDOR_ID(10, 0)
++#define HV_get_virtual_address_space_id_of_ppe __BEAT_ADD_VENDOR_ID(4, 0)
++#define HV_query_logical_partition_address_region_info 			\
++						__BEAT_ADD_VENDOR_ID(6, 0)
++#define HV_release_memory __BEAT_ADD_VENDOR_ID(13, 0)
++#define HV_select_virtual_address_space __BEAT_ADD_VENDOR_ID(7, 0)
++#define HV_load_range_registers __BEAT_ADD_VENDOR_ID(68, 0)
++#define HV_set_ppe_l2cache_rmt_entry __BEAT_ADD_VENDOR_ID(70, 0)
++#define HV_set_ppe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(71, 0)
++#define HV_set_spe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(72, 0)
++#define HV_get_io_address_translation_fault_info __BEAT_ADD_VENDOR_ID(14, 0)
++#define HV_get_iopte __BEAT_ADD_VENDOR_ID(16, 0)
++#define HV_preload_iopt_cache __BEAT_ADD_VENDOR_ID(17, 0)
++#define HV_put_iopte __BEAT_ADD_VENDOR_ID(15, 0)
++#define HV_connect_event_ports __BEAT_ADD_VENDOR_ID(21, 0)
++#define HV_construct_event_receive_port __BEAT_ADD_VENDOR_ID(18, 0)
++#define HV_destruct_event_receive_port __BEAT_ADD_VENDOR_ID(19, 0)
++#define HV_destruct_event_send_port __BEAT_ADD_VENDOR_ID(22, 0)
++#define HV_get_state_of_event_send_port __BEAT_ADD_VENDOR_ID(25, 0)
++#define HV_request_to_connect_event_ports __BEAT_ADD_VENDOR_ID(20, 0)
++#define HV_send_event_externally __BEAT_ADD_VENDOR_ID(23, 0)
++#define HV_send_event_locally __BEAT_ADD_VENDOR_ID(24, 0)
++#define HV_construct_and_connect_irq_plug __BEAT_ADD_VENDOR_ID(28, 0)
++#define HV_destruct_irq_plug __BEAT_ADD_VENDOR_ID(29, 0)
++#define HV_detect_pending_interrupts __BEAT_ADD_VENDOR_ID(26, 0)
++#define HV_end_of_interrupt __BEAT_ADD_VENDOR_ID(27, 0)
++#define HV_assign_control_signal_notification_port __BEAT_ADD_VENDOR_ID(45, 0)
++#define HV_end_of_control_signal_processing __BEAT_ADD_VENDOR_ID(48, 0)
++#define HV_get_control_signal __BEAT_ADD_VENDOR_ID(46, 0)
++#define HV_set_irq_mask_for_spe __BEAT_ADD_VENDOR_ID(61, 0)
++#define HV_shutdown_logical_partition __BEAT_ADD_VENDOR_ID(44, 0)
++#define HV_connect_message_ports __BEAT_ADD_VENDOR_ID(35, 0)
++#define HV_destruct_message_port __BEAT_ADD_VENDOR_ID(36, 0)
++#define HV_receive_message __BEAT_ADD_VENDOR_ID(37, 0)
++#define HV_get_message_port_info __BEAT_ADD_VENDOR_ID(34, 0)
++#define HV_request_to_connect_message_ports __BEAT_ADD_VENDOR_ID(33, 0)
++#define HV_send_message __BEAT_ADD_VENDOR_ID(32, 0)
++#define HV_get_logical_ppe_id __BEAT_ADD_VENDOR_ID(69, 0)
++#define HV_pause __BEAT_ADD_VENDOR_ID(9, 0)
++#define HV_destruct_shared_memory_handle __BEAT_ADD_VENDOR_ID(51, 0)
++#define HV_get_shared_memory_info __BEAT_ADD_VENDOR_ID(52, 0)
++#define HV_permit_sharing_memory __BEAT_ADD_VENDOR_ID(50, 0)
++#define HV_request_to_attach_shared_memory __BEAT_ADD_VENDOR_ID(49, 0)
++#define HV_enable_logical_spe_execution __BEAT_ADD_VENDOR_ID(55, 0)
++#define HV_construct_logical_spe __BEAT_ADD_VENDOR_ID(53, 0)
++#define HV_disable_logical_spe_execution __BEAT_ADD_VENDOR_ID(56, 0)
++#define HV_destruct_logical_spe __BEAT_ADD_VENDOR_ID(54, 0)
++#define HV_sense_spe_execution_status __BEAT_ADD_VENDOR_ID(58, 0)
++#define HV_insert_htab_entry __BEAT_ADD_VENDOR_ID(101, 0)
++#define HV_read_htab_entries __BEAT_ADD_VENDOR_ID(95, 0)
++#define HV_write_htab_entry __BEAT_ADD_VENDOR_ID(94, 0)
++#define HV_assign_io_address_translation_fault_port 			\
++						__BEAT_ADD_VENDOR_ID(100, 0)
++#define HV_set_interrupt_mask __BEAT_ADD_VENDOR_ID(73, 0)
++#define HV_get_logical_partition_id __BEAT_ADD_VENDOR_ID(74, 0)
++#define HV_create_repository_node2 __BEAT_ADD_VENDOR_ID(90, 0)
++#define HV_create_repository_node __BEAT_ADD_VENDOR_ID(90, 0) /* alias */
++#define HV_get_repository_node_value2 __BEAT_ADD_VENDOR_ID(91, 0)
++#define HV_get_repository_node_value __BEAT_ADD_VENDOR_ID(91, 0) /* alias */
++#define HV_modify_repository_node_value2 __BEAT_ADD_VENDOR_ID(92, 0)
++#define HV_modify_repository_node_value __BEAT_ADD_VENDOR_ID(92, 0) /* alias */
++#define HV_remove_repository_node2 __BEAT_ADD_VENDOR_ID(93, 0)
++#define HV_remove_repository_node __BEAT_ADD_VENDOR_ID(93, 0) /* alias */
++#define HV_cancel_shared_memory __BEAT_ADD_VENDOR_ID(104, 0)
++#define HV_clear_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(206, 0)
++#define HV_construct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(80, 0)
++#define HV_destruct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(81, 0)
++#define HV_disconnect_ipspc_service __BEAT_ADD_VENDOR_ID(88, 0)
++#define HV_execute_ipspc_command __BEAT_ADD_VENDOR_ID(86, 0)
++#define HV_get_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(205, 0)
++#define HV_get_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(208, 0)
++#define HV_permit_use_of_ipspc_service __BEAT_ADD_VENDOR_ID(85, 0)
++#define HV_reinitialize_logical_spe __BEAT_ADD_VENDOR_ID(82, 0)
++#define HV_request_ipspc_service __BEAT_ADD_VENDOR_ID(84, 0)
++#define HV_stop_ipspc_command __BEAT_ADD_VENDOR_ID(87, 0)
++#define HV_set_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(204, 0)
++#define HV_get_status_of_ipspc_service __BEAT_ADD_VENDOR_ID(203, 0)
++#define HV_put_characters_to_console __BEAT_ADD_VENDOR_ID(0x101, 1)
++#define HV_get_characters_from_console __BEAT_ADD_VENDOR_ID(0x102, 1)
++#define HV_get_base_clock __BEAT_ADD_VENDOR_ID(0x111, 1)
++#define HV_set_base_clock __BEAT_ADD_VENDOR_ID(0x112, 1)
++#define HV_get_frame_cycle __BEAT_ADD_VENDOR_ID(0x114, 1)
++#define HV_disable_console __BEAT_ADD_VENDOR_ID(0x115, 1)
++#define HV_disable_all_console __BEAT_ADD_VENDOR_ID(0x116, 1)
++#define HV_oneshot_timer __BEAT_ADD_VENDOR_ID(0x117, 1)
++#define HV_set_dabr __BEAT_ADD_VENDOR_ID(0x118, 1)
++#define HV_get_dabr __BEAT_ADD_VENDOR_ID(0x119, 1)
++#define HV_start_hv_stats __BEAT_ADD_VENDOR_ID(0x21c, 1)
++#define HV_stop_hv_stats __BEAT_ADD_VENDOR_ID(0x21d, 1)
++#define HV_get_hv_stats __BEAT_ADD_VENDOR_ID(0x21e, 1)
++#define HV_get_hv_error_stats __BEAT_ADD_VENDOR_ID(0x221, 1)
++#define HV_get_stats __BEAT_ADD_VENDOR_ID(0x224, 1)
++#define HV_get_heap_stats __BEAT_ADD_VENDOR_ID(0x225, 1)
++#define HV_get_memory_stats __BEAT_ADD_VENDOR_ID(0x227, 1)
++#define HV_get_memory_detail __BEAT_ADD_VENDOR_ID(0x228, 1)
++#define HV_set_priority_of_irq_outlet __BEAT_ADD_VENDOR_ID(0x122, 1)
++#define HV_get_physical_spe_by_reservation_id __BEAT_ADD_VENDOR_ID(0x128, 1)
++#define HV_get_spe_context __BEAT_ADD_VENDOR_ID(0x129, 1)
++#define HV_set_spe_context __BEAT_ADD_VENDOR_ID(0x12a, 1)
++#define HV_downcount_of_interrupt __BEAT_ADD_VENDOR_ID(0x12e, 1)
++#define HV_peek_spe_context __BEAT_ADD_VENDOR_ID(0x12f, 1)
++#define HV_read_bpa_register __BEAT_ADD_VENDOR_ID(0x131, 1)
++#define HV_write_bpa_register __BEAT_ADD_VENDOR_ID(0x132, 1)
++#define HV_map_context_table_of_spe __BEAT_ADD_VENDOR_ID(0x137, 1)
++#define HV_get_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x138, 1)
++#define HV_set_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x139, 1)
++#define HV_init_pm __BEAT_ADD_VENDOR_ID(0x150, 1)
++#define HV_set_pm_signal __BEAT_ADD_VENDOR_ID(0x151, 1)
++#define HV_get_pm_signal __BEAT_ADD_VENDOR_ID(0x152, 1)
++#define HV_set_pm_config __BEAT_ADD_VENDOR_ID(0x153, 1)
++#define HV_get_pm_config __BEAT_ADD_VENDOR_ID(0x154, 1)
++#define HV_get_inner_trace_data __BEAT_ADD_VENDOR_ID(0x155, 1)
++#define HV_set_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x156, 1)
++#define HV_get_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x157, 1)
++#define HV_set_pm_interrupt __BEAT_ADD_VENDOR_ID(0x158, 1)
++#define HV_get_pm_interrupt __BEAT_ADD_VENDOR_ID(0x159, 1)
++#define HV_kick_pm __BEAT_ADD_VENDOR_ID(0x160, 1)
++#define HV_construct_pm_context __BEAT_ADD_VENDOR_ID(0x164, 1)
++#define HV_destruct_pm_context __BEAT_ADD_VENDOR_ID(0x165, 1)
++#define HV_be_slow __BEAT_ADD_VENDOR_ID(0x170, 1)
++#define HV_assign_ipspc_server_connection_status_notification_port 	\
++						__BEAT_ADD_VENDOR_ID(0x173, 1)
++#define HV_get_raid_of_physical_spe __BEAT_ADD_VENDOR_ID(0x174, 1)
++#define HV_set_physical_spe_to_rag __BEAT_ADD_VENDOR_ID(0x175, 1)
++#define HV_release_physical_spe_from_rag __BEAT_ADD_VENDOR_ID(0x176, 1)
++#define HV_rtc_read __BEAT_ADD_VENDOR_ID(0x190, 1)
++#define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1)
++#define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1)
++#define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1)
++#define HV_insert_htab_entry3 __BEAT_ADD_VENDOR_ID(0x104, 1)
++#define HV_invalidate_htab_entry3 __BEAT_ADD_VENDOR_ID(0x105, 1)
++#define HV_update_htab_permission3 __BEAT_ADD_VENDOR_ID(0x106, 1)
++#define HV_clear_htab3 __BEAT_ADD_VENDOR_ID(0x107, 1)
++#endif
+diff --git a/arch/powerpc/platforms/cell/beat_udbg.c b/arch/powerpc/platforms/cell/beat_udbg.c
+new file mode 100644
+index 0000000..6b418f6
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_udbg.c
+@@ -0,0 +1,98 @@
++/*
++ * udbg function for Beat
++ *
++ * (C) Copyright 2006 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/console.h>
++
++#include <asm/machdep.h>
++#include <asm/prom.h>
++#include <asm/udbg.h>
++
++#include "beat.h"
++
++#define	celleb_vtermno	0
++
++static void udbg_putc_beat(char c)
++{
++	unsigned long rc;
++
++	if (c == '\n')
++		udbg_putc_beat('\r');
++
++	rc = beat_put_term_char(celleb_vtermno, 1, (uint64_t)c << 56, 0);
++}
++
++/* Buffered chars getc */
++static long inbuflen;
++static long inbuf[2];	/* must be 2 longs */
++
++static int udbg_getc_poll_beat(void)
++{
++	/* The interface is tricky because it may return up to 16 chars.
++	 * We save them statically for future calls to udbg_getc().
++	 */
++	char ch, *buf = (char *)inbuf;
++	int i;
++	long rc;
++	if (inbuflen == 0) {
++		/* get some more chars. */
++		inbuflen = 0;
++		rc = beat_get_term_char(celleb_vtermno, &inbuflen,
++					inbuf+0, inbuf+1);
++		if (rc != 0)
++			inbuflen = 0;	/* otherwise inbuflen is garbage */
++	}
++	if (inbuflen <= 0 || inbuflen > 16) {
++		/* Catch error case as well as other oddities (corruption) */
++		inbuflen = 0;
++		return -1;
++	}
++	ch = buf[0];
++	for (i = 1; i < inbuflen; i++)	/* shuffle them down. */
++		buf[i-1] = buf[i];
++	inbuflen--;
++	return ch;
++}
++
++static int udbg_getc_beat(void)
++{
++	int ch;
++	for (;;) {
++		ch = udbg_getc_poll_beat();
++		if (ch == -1) {
++			/* This shouldn't be needed...but... */
++			volatile unsigned long delay;
++			for (delay = 0; delay < 2000000; delay++)
++				;
++		} else {
++			return ch;
++		}
++	}
++}
++
++/* call this from early_init() for a working debug console on
++ * vterm capable LPAR machines
++ */
++void __init udbg_init_debug_beat(void)
++{
++	udbg_putc = udbg_putc_beat;
++	udbg_getc = udbg_getc_beat;
++	udbg_getc_poll = udbg_getc_poll_beat;
++}
+diff --git a/arch/powerpc/platforms/cell/beat_wrapper.h b/arch/powerpc/platforms/cell/beat_wrapper.h
+new file mode 100644
+index 0000000..b47dfda
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_wrapper.h
+@@ -0,0 +1,289 @@
++/*
++ * Beat hypervisor call I/F
++ *
++ * (C) Copyright 2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/pseries/plpar_wrapper.h.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU 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 BEAT_HCALL
++#include "beat_syscall.h"
++
++/* defined in hvCall.S */
++extern s64 beat_hcall_norets(u64 opcode, ...);
++extern s64 beat_hcall_norets8(u64 opcode, u64 arg1, u64 arg2, u64 arg3,
++	u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8);
++extern s64 beat_hcall1(u64 opcode, u64 retbuf[1], ...);
++extern s64 beat_hcall2(u64 opcode, u64 retbuf[2], ...);
++extern s64 beat_hcall3(u64 opcode, u64 retbuf[3], ...);
++extern s64 beat_hcall4(u64 opcode, u64 retbuf[4], ...);
++extern s64 beat_hcall5(u64 opcode, u64 retbuf[5], ...);
++extern s64 beat_hcall6(u64 opcode, u64 retbuf[6], ...);
++
++static inline s64 beat_downcount_of_interrupt(u64 plug_id)
++{
++	return beat_hcall_norets(HV_downcount_of_interrupt, plug_id);
++}
++
++static inline s64 beat_set_interrupt_mask(u64 index,
++	u64 val0, u64 val1, u64 val2, u64 val3)
++{
++	return beat_hcall_norets(HV_set_interrupt_mask, index,
++	       val0, val1, val2, val3);
++}
++
++static inline s64 beat_destruct_irq_plug(u64 plug_id)
++{
++	return beat_hcall_norets(HV_destruct_irq_plug, plug_id);
++}
++
++static inline s64 beat_construct_and_connect_irq_plug(u64 plug_id,
++	u64 outlet_id)
++{
++	return beat_hcall_norets(HV_construct_and_connect_irq_plug, plug_id,
++	       outlet_id);
++}
++
++static inline s64 beat_detect_pending_interrupts(u64 index, u64 *retbuf)
++{
++	return beat_hcall4(HV_detect_pending_interrupts, retbuf, index);
++}
++
++static inline s64 beat_pause(u64 style)
++{
++	return beat_hcall_norets(HV_pause, style);
++}
++
++static inline s64 beat_read_htab_entries(u64 htab_id, u64 index, u64 *retbuf)
++{
++	return beat_hcall5(HV_read_htab_entries, retbuf, htab_id, index);
++}
++
++static inline s64 beat_insert_htab_entry(u64 htab_id, u64 group,
++	u64 bitmask, u64 hpte_v, u64 hpte_r, u64 *slot)
++{
++	u64 dummy[3];
++	s64 ret;
++
++	ret = beat_hcall3(HV_insert_htab_entry, dummy, htab_id, group,
++		bitmask, hpte_v, hpte_r);
++	*slot = dummy[0];
++	return ret;
++}
++
++static inline s64 beat_write_htab_entry(u64 htab_id, u64 slot,
++	u64 hpte_v, u64 hpte_r, u64 mask_v, u64 mask_r,
++	u64 *ret_v, u64 *ret_r)
++{
++	u64 dummy[2];
++	s64 ret;
++
++	ret = beat_hcall2(HV_write_htab_entry, dummy, htab_id, slot,
++		hpte_v, hpte_r, mask_v, mask_r);
++	*ret_v = dummy[0];
++	*ret_r = dummy[1];
++	return ret;
++}
++
++static inline s64 beat_insert_htab_entry3(u64 htab_id, u64 group,
++	u64 hpte_v, u64 hpte_r, u64 mask_v, u64 value_v, u64 *slot)
++{
++	u64 dummy[1];
++	s64 ret;
++
++	ret = beat_hcall1(HV_insert_htab_entry3, dummy, htab_id, group,
++		hpte_v, hpte_r, mask_v, value_v);
++	*slot = dummy[0];
++	return ret;
++}
++
++static inline s64 beat_invalidate_htab_entry3(u64 htab_id, u64 group,
++	u64 va, u64 pss)
++{
++	return beat_hcall_norets(HV_invalidate_htab_entry3,
++		htab_id, group, va, pss);
++}
++
++static inline s64 beat_update_htab_permission3(u64 htab_id, u64 group,
++	u64 va, u64 pss, u64 ptel_mask, u64 ptel_value)
++{
++	return beat_hcall_norets(HV_update_htab_permission3,
++		htab_id, group, va, pss, ptel_mask, ptel_value);
++}
++
++static inline s64 beat_clear_htab3(u64 htab_id)
++{
++	return beat_hcall_norets(HV_clear_htab3, htab_id);
++}
++
++static inline void beat_shutdown_logical_partition(u64 code)
++{
++	(void)beat_hcall_norets(HV_shutdown_logical_partition, code);
++}
++
++static inline s64 beat_rtc_write(u64 time_from_epoch)
++{
++	return beat_hcall_norets(HV_rtc_write, time_from_epoch);
++}
++
++static inline s64 beat_rtc_read(u64 *time_from_epoch)
++{
++	u64 dummy[1];
++	s64 ret;
++
++	ret = beat_hcall1(HV_rtc_read, dummy);
++	*time_from_epoch = dummy[0];
++	return ret;
++}
++
++#define	BEAT_NVRW_CNT	(sizeof(u64) * 6)
++
++static inline s64 beat_eeprom_write(u64 index, u64 length, u8 *buffer)
++{
++	u64	b[6];
++
++	if (length > BEAT_NVRW_CNT)
++		return -1;
++	memcpy(b, buffer, sizeof(b));
++	return beat_hcall_norets8(HV_eeprom_write, index, length,
++		b[0], b[1], b[2], b[3], b[4], b[5]);
++}
++
++static inline s64 beat_eeprom_read(u64 index, u64 length, u8 *buffer)
++{
++	u64	b[6];
++	s64	ret;
++
++	if (length > BEAT_NVRW_CNT)
++		return -1;
++	ret = beat_hcall6(HV_eeprom_read, b, index, length);
++	memcpy(buffer, b, length);
++	return ret;
++}
++
++static inline s64 beat_set_dabr(u64 value, u64 style)
++{
++	return beat_hcall_norets(HV_set_dabr, value, style);
++}
++
++static inline s64 beat_get_characters_from_console(u64 termno, u64 *len,
++	u8 *buffer)
++{
++	u64 dummy[3];
++	s64 ret;
++
++	ret = beat_hcall3(HV_get_characters_from_console, dummy, termno, len);
++	*len = dummy[0];
++	memcpy(buffer, dummy + 1, *len);
++	return ret;
++}
++
++static inline s64 beat_put_characters_to_console(u64 termno, u64 len,
++	u8 *buffer)
++{
++	u64 b[2];
++
++	memcpy(b, buffer, len);
++	return beat_hcall_norets(HV_put_characters_to_console, termno, len,
++		b[0], b[1]);
++}
++
++static inline s64 beat_get_spe_privileged_state_1_registers(
++		u64 id, u64 offsetof, u64 *value)
++{
++	u64 dummy[1];
++	s64 ret;
++
++	ret = beat_hcall1(HV_get_spe_privileged_state_1_registers, dummy, id,
++		offsetof);
++	*value = dummy[0];
++	return ret;
++}
++
++static inline s64 beat_set_irq_mask_for_spe(u64 id, u64 class, u64 mask)
++{
++	return beat_hcall_norets(HV_set_irq_mask_for_spe, id, class, mask);
++}
++
++static inline s64 beat_clear_interrupt_status_of_spe(u64 id, u64 class,
++	u64 mask)
++{
++	return beat_hcall_norets(HV_clear_interrupt_status_of_spe,
++		id, class, mask);
++}
++
++static inline s64 beat_set_spe_privileged_state_1_registers(
++		u64 id, u64 offsetof, u64 value)
++{
++	return beat_hcall_norets(HV_set_spe_privileged_state_1_registers,
++		id, offsetof, value);
++}
++
++static inline s64 beat_get_interrupt_status_of_spe(u64 id, u64 class, u64 *val)
++{
++	u64 dummy[1];
++	s64 ret;
++
++	ret = beat_hcall1(HV_get_interrupt_status_of_spe, dummy, id, class);
++	*val = dummy[0];
++	return ret;
++}
++
++static inline s64 beat_put_iopte(u64 ioas_id, u64 io_addr, u64 real_addr,
++	u64 ioid, u64 flags)
++{
++	return beat_hcall_norets(HV_put_iopte, ioas_id, io_addr, real_addr,
++		ioid, flags);
++}
++
++static inline s64 beat_construct_event_receive_port(u64 *port)
++{
++	u64 dummy[1];
++	s64 ret;
++
++	ret = beat_hcall1(HV_construct_event_receive_port, dummy);
++	*port = dummy[0];
++	return ret;
++}
++
++static inline s64 beat_destruct_event_receive_port(u64 port)
++{
++	s64 ret;
++
++	ret = beat_hcall_norets(HV_destruct_event_receive_port, port);
++	return ret;
++}
++
++static inline s64 beat_create_repository_node(u64 path[4], u64 data[2])
++{
++	s64 ret;
++
++	ret = beat_hcall_norets(HV_create_repository_node2,
++		path[0], path[1], path[2], path[3], data[0], data[1]);
++	return ret;
++}
++
++static inline s64 beat_get_repository_node_value(u64 lpid, u64 path[4],
++	u64 data[2])
++{
++	s64 ret;
++
++	ret = beat_hcall2(HV_get_repository_node_value2, data,
++		lpid, path[0], path[1], path[2], path[3]);
++	return ret;
++}
++
++#endif
+diff --git a/arch/powerpc/platforms/cell/celleb_pci.c b/arch/powerpc/platforms/cell/celleb_pci.c
+new file mode 100644
+index 0000000..f39a3b2
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_pci.c
+@@ -0,0 +1,514 @@
++/*
++ * Support for PCI on Celleb platform.
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/kernel/rtas_pci.c:
++ *  Copyright (C) 2001 Dave Engebretsen, IBM Corporation
++ *  Copyright (C) 2003 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU 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.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/threads.h>
++#include <linux/pci.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/pci_regs.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/prom.h>
++#include <asm/pci-bridge.h>
++#include <asm/ppc-pci.h>
++
++#include "io-workarounds.h"
++#include "celleb_pci.h"
++
++#define MAX_PCI_DEVICES    32
++#define MAX_PCI_FUNCTIONS   8
++#define MAX_PCI_BASE_ADDRS  3 /* use 64 bit address */
++
++/* definition for fake pci configuration area for GbE, .... ,and etc. */
++
++struct celleb_pci_resource {
++	struct resource r[MAX_PCI_BASE_ADDRS];
++};
++
++struct celleb_pci_private {
++	unsigned char *fake_config[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
++	struct celleb_pci_resource *res[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
++};
++
++static inline u8 celleb_fake_config_readb(void *addr)
++{
++	u8 *p = addr;
++	return *p;
++}
++
++static inline u16 celleb_fake_config_readw(void *addr)
++{
++	__le16 *p = addr;
++	return le16_to_cpu(*p);
++}
++
++static inline u32 celleb_fake_config_readl(void *addr)
++{
++	__le32 *p = addr;
++	return le32_to_cpu(*p);
++}
++
++static inline void celleb_fake_config_writeb(u32 val, void *addr)
++{
++	u8 *p = addr;
++	*p = val;
++}
++
++static inline void celleb_fake_config_writew(u32 val, void *addr)
++{
++	__le16 val16;
++	__le16 *p = addr;
++	val16 = cpu_to_le16(val);
++	*p = val16;
++}
++
++static inline void celleb_fake_config_writel(u32 val, void *addr)
++{
++	__le32 val32;
++	__le32 *p = addr;
++	val32 = cpu_to_le32(val);
++	*p = val32;
++}
++
++static unsigned char *get_fake_config_start(struct pci_controller *hose,
++					    int devno, int fn)
++{
++	struct celleb_pci_private *private = hose->private_data;
++
++	if (private == NULL)
++		return NULL;
++
++	return private->fake_config[devno][fn];
++}
++
++static struct celleb_pci_resource *get_resource_start(
++				struct pci_controller *hose,
++				int devno, int fn)
++{
++	struct celleb_pci_private *private = hose->private_data;
++
++	if (private == NULL)
++		return NULL;
++
++	return private->res[devno][fn];
++}
++
++
++static void celleb_config_read_fake(unsigned char *config, int where,
++				    int size, u32 *val)
++{
++	char *p = config + where;
++
++	switch (size) {
++	case 1:
++		*val = celleb_fake_config_readb(p);
++		break;
++	case 2:
++		*val = celleb_fake_config_readw(p);
++		break;
++	case 4:
++		*val = celleb_fake_config_readl(p);
++		break;
++	}
++}
++
++static void celleb_config_write_fake(unsigned char *config, int where,
++				     int size, u32 val)
++{
++	char *p = config + where;
++
++	switch (size) {
++	case 1:
++		celleb_fake_config_writeb(val, p);
++		break;
++	case 2:
++		celleb_fake_config_writew(val, p);
++		break;
++	case 4:
++		celleb_fake_config_writel(val, p);
++		break;
++	}
++}
++
++static int celleb_fake_pci_read_config(struct pci_bus *bus,
++		unsigned int devfn, int where, int size, u32 *val)
++{
++	char *config;
++	struct device_node *node;
++	struct pci_controller *hose;
++	unsigned int devno = devfn >> 3;
++	unsigned int fn = devfn & 0x7;
++
++	/* allignment check */
++	BUG_ON(where % size);
++
++	pr_debug("    fake read: bus=0x%x, ", bus->number);
++	node = (struct device_node *)bus->sysdata;
++	hose = pci_find_hose_for_OF_device(node);
++	config = get_fake_config_start(hose, devno, fn);
++
++	pr_debug("devno=0x%x, where=0x%x, size=0x%x, ", devno, where, size);
++	if (!config) {
++		pr_debug("failed\n");
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	}
++
++	celleb_config_read_fake(config, where, size, val);
++	pr_debug("val=0x%x\n", *val);
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++
++static int celleb_fake_pci_write_config(struct pci_bus *bus,
++		unsigned int devfn, int where, int size, u32 val)
++{
++	char *config;
++	struct device_node *node;
++	struct pci_controller *hose;
++	struct celleb_pci_resource *res;
++	unsigned int devno = devfn >> 3;
++	unsigned int fn = devfn & 0x7;
++
++	/* allignment check */
++	BUG_ON(where % size);
++
++	node = (struct device_node *)bus->sysdata;
++	hose = pci_find_hose_for_OF_device(node);
++	config = get_fake_config_start(hose, devno, fn);
++
++	if (!config)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	if (val == ~0) {
++		int i = (where - PCI_BASE_ADDRESS_0) >> 3;
++
++		switch (where) {
++		case PCI_BASE_ADDRESS_0:
++		case PCI_BASE_ADDRESS_2:
++			if (size != 4)
++				return PCIBIOS_DEVICE_NOT_FOUND;
++			res = get_resource_start(hose, devno, fn);
++			if (!res)
++				return PCIBIOS_DEVICE_NOT_FOUND;
++			celleb_config_write_fake(config, where, size,
++					(res->r[i].end - res->r[i].start));
++			return PCIBIOS_SUCCESSFUL;
++		case PCI_BASE_ADDRESS_1:
++		case PCI_BASE_ADDRESS_3:
++		case PCI_BASE_ADDRESS_4:
++		case PCI_BASE_ADDRESS_5:
++			break;
++		default:
++			break;
++		}
++	}
++
++	celleb_config_write_fake(config, where, size, val);
++	pr_debug("    fake write: where=%x, size=%d, val=%x\n",
++		 where, size, val);
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops celleb_fake_pci_ops = {
++	.read = celleb_fake_pci_read_config,
++	.write = celleb_fake_pci_write_config,
++};
++
++static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose,
++					unsigned int devno, unsigned int fn,
++					unsigned int num_base_addr)
++{
++	u32 val;
++	unsigned char *config;
++	struct celleb_pci_resource *res;
++
++	config = get_fake_config_start(hose, devno, fn);
++	res = get_resource_start(hose, devno, fn);
++
++	if (!config || !res)
++		return;
++
++	switch (num_base_addr) {
++	case 3:
++		val = (res->r[2].start & 0xfffffff0)
++		    | PCI_BASE_ADDRESS_MEM_TYPE_64;
++		celleb_config_write_fake(config, PCI_BASE_ADDRESS_4, 4, val);
++		val = res->r[2].start >> 32;
++		celleb_config_write_fake(config, PCI_BASE_ADDRESS_5, 4, val);
++		/* FALLTHROUGH */
++	case 2:
++		val = (res->r[1].start & 0xfffffff0)
++		    | PCI_BASE_ADDRESS_MEM_TYPE_64;
++		celleb_config_write_fake(config, PCI_BASE_ADDRESS_2, 4, val);
++		val = res->r[1].start >> 32;
++		celleb_config_write_fake(config, PCI_BASE_ADDRESS_3, 4, val);
++		/* FALLTHROUGH */
++	case 1:
++		val = (res->r[0].start & 0xfffffff0)
++		    | PCI_BASE_ADDRESS_MEM_TYPE_64;
++		celleb_config_write_fake(config, PCI_BASE_ADDRESS_0, 4, val);
++		val = res->r[0].start >> 32;
++		celleb_config_write_fake(config, PCI_BASE_ADDRESS_1, 4, val);
++		break;
++	}
++
++	val = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
++	celleb_config_write_fake(config, PCI_COMMAND, 2, val);
++}
++
++static int __init celleb_setup_fake_pci_device(struct device_node *node,
++					       struct pci_controller *hose)
++{
++	unsigned int rlen;
++	int num_base_addr = 0;
++	u32 val;
++	const u32 *wi0, *wi1, *wi2, *wi3, *wi4;
++	unsigned int devno, fn;
++	struct celleb_pci_private *private = hose->private_data;
++	unsigned char **config = NULL;
++	struct celleb_pci_resource **res = NULL;
++	const char *name;
++	const unsigned long *li;
++	int size, result;
++
++	if (private == NULL) {
++		printk(KERN_ERR "PCI: "
++		       "memory space for pci controller is not assigned\n");
++		goto error;
++	}
++
++	name = of_get_property(node, "model", &rlen);
++	if (!name) {
++		printk(KERN_ERR "PCI: model property not found.\n");
++		goto error;
++	}
++
++	wi4 = of_get_property(node, "reg", &rlen);
++	if (wi4 == NULL)
++		goto error;
++
++	devno = ((wi4[0] >> 8) & 0xff) >> 3;
++	fn = (wi4[0] >> 8) & 0x7;
++
++	pr_debug("PCI: celleb_setup_fake_pci() %s devno=%x fn=%x\n", name,
++		 devno, fn);
++
++	size = 256;
++	config = &private->fake_config[devno][fn];
++	*config = alloc_maybe_bootmem(size, GFP_KERNEL);
++	if (*config == NULL) {
++		printk(KERN_ERR "PCI: "
++		       "not enough memory for fake configuration space\n");
++		goto error;
++	}
++	pr_debug("PCI: fake config area assigned 0x%016lx\n",
++		 (unsigned long)*config);
++
++	size = sizeof(struct celleb_pci_resource);
++	res = &private->res[devno][fn];
++	*res = alloc_maybe_bootmem(size, GFP_KERNEL);
++	if (*res == NULL) {
++		printk(KERN_ERR
++		       "PCI: not enough memory for resource data space\n");
++		goto error;
++	}
++	pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res);
++
++	wi0 = of_get_property(node, "device-id", NULL);
++	wi1 = of_get_property(node, "vendor-id", NULL);
++	wi2 = of_get_property(node, "class-code", NULL);
++	wi3 = of_get_property(node, "revision-id", NULL);
++	if (!wi0 || !wi1 || !wi2 || !wi3) {
++		printk(KERN_ERR "PCI: Missing device tree properties.\n");
++		goto error;
++	}
++
++	celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff);
++	celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff);
++	pr_debug("class-code = 0x%08x\n", wi2[0]);
++
++	celleb_config_write_fake(*config, PCI_CLASS_PROG, 1, wi2[0] & 0xff);
++	celleb_config_write_fake(*config, PCI_CLASS_DEVICE, 2,
++				 (wi2[0] >> 8) & 0xffff);
++	celleb_config_write_fake(*config, PCI_REVISION_ID, 1, wi3[0]);
++
++	while (num_base_addr < MAX_PCI_BASE_ADDRS) {
++		result = of_address_to_resource(node,
++				num_base_addr, &(*res)->r[num_base_addr]);
++		if (result)
++			break;
++		num_base_addr++;
++	}
++
++	celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr);
++
++	li = of_get_property(node, "interrupts", &rlen);
++	if (!li) {
++		printk(KERN_ERR "PCI: interrupts not found.\n");
++		goto error;
++	}
++	val = li[0];
++	celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1);
++	celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val);
++
++#ifdef DEBUG
++	pr_debug("PCI: %s irq=%ld\n", name, li[0]);
++	for (i = 0; i < 6; i++) {
++		celleb_config_read_fake(*config,
++					PCI_BASE_ADDRESS_0 + 0x4 * i, 4,
++					&val);
++		pr_debug("PCI: %s fn=%d base_address_%d=0x%x\n",
++			 name, fn, i, val);
++	}
++#endif
++
++	celleb_config_write_fake(*config, PCI_HEADER_TYPE, 1,
++				 PCI_HEADER_TYPE_NORMAL);
++
++	return 0;
++
++error:
++	if (mem_init_done) {
++		if (config && *config)
++			kfree(*config);
++		if (res && *res)
++			kfree(*res);
++
++	} else {
++		if (config && *config) {
++			size = 256;
++			free_bootmem((unsigned long)(*config), size);
++		}
++		if (res && *res) {
++			size = sizeof(struct celleb_pci_resource);
++			free_bootmem((unsigned long)(*res), size);
++		}
++	}
++
++	return 1;
++}
++
++static int __init phb_set_bus_ranges(struct device_node *dev,
++				     struct pci_controller *phb)
++{
++	const int *bus_range;
++	unsigned int len;
++
++	bus_range = of_get_property(dev, "bus-range", &len);
++	if (bus_range == NULL || len < 2 * sizeof(int))
++		return 1;
++
++	phb->first_busno = bus_range[0];
++	phb->last_busno = bus_range[1];
++
++	return 0;
++}
++
++static void __init celleb_alloc_private_mem(struct pci_controller *hose)
++{
++	hose->private_data =
++		alloc_maybe_bootmem(sizeof(struct celleb_pci_private),
++			GFP_KERNEL);
++}
++
++static int __init celleb_setup_fake_pci(struct device_node *dev,
++					struct pci_controller *phb)
++{
++	struct device_node *node;
++
++	phb->ops = &celleb_fake_pci_ops;
++	celleb_alloc_private_mem(phb);
++
++	for (node = of_get_next_child(dev, NULL);
++	     node != NULL; node = of_get_next_child(dev, node))
++		celleb_setup_fake_pci_device(node, phb);
++
++	return 0;
++}
++
++static struct celleb_phb_spec celleb_fake_pci_spec __initdata = {
++	.setup = celleb_setup_fake_pci,
++};
++
++static struct of_device_id celleb_phb_match[] __initdata = {
++	{
++		.name = "pci-pseudo",
++		.data = &celleb_fake_pci_spec,
++	}, {
++		.name = "epci",
++		.data = &celleb_epci_spec,
++	}, {
++		.name = "pcie",
++		.data = &celleb_pciex_spec,
++	}, {
++	},
++};
++
++static int __init celleb_io_workaround_init(struct pci_controller *phb,
++					    struct celleb_phb_spec *phb_spec)
++{
++	if (phb_spec->ops) {
++		iowa_register_bus(phb, phb_spec->ops, phb_spec->iowa_init,
++				  phb_spec->iowa_data);
++		io_workaround_init();
++	}
++
++	return 0;
++}
++
++int __init celleb_setup_phb(struct pci_controller *phb)
++{
++	struct device_node *dev = phb->dn;
++	const struct of_device_id *match;
++	struct celleb_phb_spec *phb_spec;
++	int rc;
++
++	match = of_match_node(celleb_phb_match, dev);
++	if (!match)
++		return 1;
++
++	phb_set_bus_ranges(dev, phb);
++	phb->buid = 1;
++
++	phb_spec = match->data;
++	rc = (*phb_spec->setup)(dev, phb);
++	if (rc)
++		return 1;
++
++	return celleb_io_workaround_init(phb, phb_spec);
++}
++
++int celleb_pci_probe_mode(struct pci_bus *bus)
++{
++	return PCI_PROBE_DEVTREE;
++}
+diff --git a/arch/powerpc/platforms/cell/celleb_pci.h b/arch/powerpc/platforms/cell/celleb_pci.h
+new file mode 100644
+index 0000000..4cba152
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_pci.h
+@@ -0,0 +1,45 @@
++/*
++ * pci prototypes for Celleb platform
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef _CELLEB_PCI_H
++#define _CELLEB_PCI_H
++
++#include <linux/pci.h>
++
++#include <asm/pci-bridge.h>
++#include <asm/prom.h>
++#include <asm/ppc-pci.h>
++
++#include "io-workarounds.h"
++
++struct celleb_phb_spec {
++	int (*setup)(struct device_node *, struct pci_controller *);
++	struct ppc_pci_io *ops;
++	int (*iowa_init)(struct iowa_bus *, void *);
++	void *iowa_data;
++};
++
++extern int celleb_setup_phb(struct pci_controller *);
++extern int celleb_pci_probe_mode(struct pci_bus *);
++
++extern struct celleb_phb_spec celleb_epci_spec;
++extern struct celleb_phb_spec celleb_pciex_spec;
++
++#endif /* _CELLEB_PCI_H */
+diff --git a/arch/powerpc/platforms/cell/celleb_scc.h b/arch/powerpc/platforms/cell/celleb_scc.h
+new file mode 100644
+index 0000000..b596a71
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc.h
+@@ -0,0 +1,232 @@
++/*
++ * SCC (Super Companion Chip) definitions
++ *
++ * (C) Copyright 2004-2006 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef _CELLEB_SCC_H
++#define _CELLEB_SCC_H
++
++#define PCI_VENDOR_ID_TOSHIBA_2                 0x102f
++#define PCI_DEVICE_ID_TOSHIBA_SCC_PCIEXC_BRIDGE 0x01b0
++#define PCI_DEVICE_ID_TOSHIBA_SCC_EPCI_BRIDGE   0x01b1
++#define PCI_DEVICE_ID_TOSHIBA_SCC_BRIDGE        0x01b2
++#define PCI_DEVICE_ID_TOSHIBA_SCC_GBE           0x01b3
++#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA           0x01b4
++#define PCI_DEVICE_ID_TOSHIBA_SCC_USB2          0x01b5
++#define PCI_DEVICE_ID_TOSHIBA_SCC_USB           0x01b6
++#define PCI_DEVICE_ID_TOSHIBA_SCC_ENCDEC        0x01b7
++
++#define SCC_EPCI_REG            0x0000d000
++
++/* EPCI registers */
++#define SCC_EPCI_CNF10_REG      0x010
++#define SCC_EPCI_CNF14_REG      0x014
++#define SCC_EPCI_CNF18_REG      0x018
++#define SCC_EPCI_PVBAT          0x100
++#define SCC_EPCI_VPMBAT         0x104
++#define SCC_EPCI_VPIBAT         0x108
++#define SCC_EPCI_VCSR           0x110
++#define SCC_EPCI_VIENAB         0x114
++#define SCC_EPCI_VISTAT         0x118
++#define SCC_EPCI_VRDCOUNT       0x124
++#define SCC_EPCI_BAM0           0x12c
++#define SCC_EPCI_BAM1           0x134
++#define SCC_EPCI_BAM2           0x13c
++#define SCC_EPCI_IADR           0x164
++#define SCC_EPCI_CLKRST         0x800
++#define SCC_EPCI_INTSET         0x804
++#define SCC_EPCI_STATUS         0x808
++#define SCC_EPCI_ABTSET         0x80c
++#define SCC_EPCI_WATRP          0x810
++#define SCC_EPCI_DUMYRADR       0x814
++#define SCC_EPCI_SWRESP         0x818
++#define SCC_EPCI_CNTOPT         0x81c
++#define SCC_EPCI_ECMODE         0xf00
++#define SCC_EPCI_IOM_AC_NUM     5
++#define SCC_EPCI_IOM_ACTE(n)    (0xf10 + (n) * 4)
++#define SCC_EPCI_IOT_AC_NUM     4
++#define SCC_EPCI_IOT_ACTE(n)    (0xf30 + (n) * 4)
++#define SCC_EPCI_MAEA           0xf50
++#define SCC_EPCI_MAEC           0xf54
++#define SCC_EPCI_CKCTRL         0xff0
++
++/* bits for SCC_EPCI_VCSR */
++#define SCC_EPCI_VCSR_FRE       0x00020000
++#define SCC_EPCI_VCSR_FWE       0x00010000
++#define SCC_EPCI_VCSR_DR        0x00000400
++#define SCC_EPCI_VCSR_SR        0x00000008
++#define SCC_EPCI_VCSR_AT        0x00000004
++
++/* bits for SCC_EPCI_VIENAB/SCC_EPCI_VISTAT */
++#define SCC_EPCI_VISTAT_PMPE    0x00000008
++#define SCC_EPCI_VISTAT_PMFE    0x00000004
++#define SCC_EPCI_VISTAT_PRA     0x00000002
++#define SCC_EPCI_VISTAT_PRD     0x00000001
++#define SCC_EPCI_VISTAT_ALL     0x0000000f
++
++#define SCC_EPCI_VIENAB_PMPEE   0x00000008
++#define SCC_EPCI_VIENAB_PMFEE   0x00000004
++#define SCC_EPCI_VIENAB_PRA     0x00000002
++#define SCC_EPCI_VIENAB_PRD     0x00000001
++#define SCC_EPCI_VIENAB_ALL     0x0000000f
++
++/* bits for SCC_EPCI_CLKRST */
++#define SCC_EPCI_CLKRST_CKS_MASK 0x00030000
++#define SCC_EPCI_CLKRST_CKS_2   0x00000000
++#define SCC_EPCI_CLKRST_CKS_4   0x00010000
++#define SCC_EPCI_CLKRST_CKS_8   0x00020000
++#define SCC_EPCI_CLKRST_PCICRST 0x00000400
++#define SCC_EPCI_CLKRST_BC      0x00000200
++#define SCC_EPCI_CLKRST_PCIRST  0x00000100
++#define SCC_EPCI_CLKRST_PCKEN   0x00000001
++
++/* bits for SCC_EPCI_INTSET/SCC_EPCI_STATUS */
++#define SCC_EPCI_INT_2M         0x01000000
++#define SCC_EPCI_INT_RERR       0x00200000
++#define SCC_EPCI_INT_SERR       0x00100000
++#define SCC_EPCI_INT_PRTER      0x00080000
++#define SCC_EPCI_INT_SER        0x00040000
++#define SCC_EPCI_INT_PER        0x00020000
++#define SCC_EPCI_INT_PAI        0x00010000
++#define SCC_EPCI_INT_1M         0x00000100
++#define SCC_EPCI_INT_PME        0x00000010
++#define SCC_EPCI_INT_INTD       0x00000008
++#define SCC_EPCI_INT_INTC       0x00000004
++#define SCC_EPCI_INT_INTB       0x00000002
++#define SCC_EPCI_INT_INTA       0x00000001
++#define SCC_EPCI_INT_DEVINT     0x0000000f
++#define SCC_EPCI_INT_ALL        0x003f001f
++#define SCC_EPCI_INT_ALLERR     0x003f0000
++
++/* bits for SCC_EPCI_CKCTRL */
++#define SCC_EPCI_CKCTRL_CRST0   0x00010000
++#define SCC_EPCI_CKCTRL_CRST1   0x00020000
++#define SCC_EPCI_CKCTRL_OCLKEN  0x00000100
++#define SCC_EPCI_CKCTRL_LCLKEN  0x00000001
++
++#define SCC_EPCI_IDSEL_AD_TO_SLOT(ad)       ((ad) - 10)
++#define SCC_EPCI_MAX_DEVNU      SCC_EPCI_IDSEL_AD_TO_SLOT(32)
++
++/* bits for SCC_EPCI_CNTOPT */
++#define SCC_EPCI_CNTOPT_O2PMB   0x00000002
++
++/* SCC PCIEXC SMMIO registers */
++#define PEXCADRS		0x000
++#define PEXCWDATA		0x004
++#define PEXCRDATA		0x008
++#define PEXDADRS		0x010
++#define PEXDCMND		0x014
++#define PEXDWDATA		0x018
++#define PEXDRDATA		0x01c
++#define PEXREQID		0x020
++#define PEXTIDMAP		0x024
++#define PEXINTMASK		0x028
++#define PEXINTSTS		0x02c
++#define PEXAERRMASK		0x030
++#define PEXAERRSTS		0x034
++#define PEXPRERRMASK		0x040
++#define PEXPRERRSTS		0x044
++#define PEXPRERRID01		0x048
++#define PEXPRERRID23		0x04c
++#define PEXVDMASK		0x050
++#define PEXVDSTS		0x054
++#define PEXRCVCPLIDA		0x060
++#define PEXLENERRIDA		0x068
++#define PEXPHYPLLST		0x070
++#define PEXDMRDEN0		0x100
++#define PEXDMRDADR0		0x104
++#define PEXDMRDENX		0x110
++#define PEXDMRDADRX		0x114
++#define PEXECMODE		0xf00
++#define PEXMAEA(n)		(0xf50 + (8 * n))
++#define PEXMAEC(n)		(0xf54 + (8 * n))
++#define PEXCCRCTRL		0xff0
++
++/* SCC PCIEXC bits and shifts for PEXCADRS */
++#define PEXCADRS_BYTE_EN_SHIFT		20
++#define PEXCADRS_CMD_SHIFT		16
++#define PEXCADRS_CMD_READ		(0xa << PEXCADRS_CMD_SHIFT)
++#define PEXCADRS_CMD_WRITE		(0xb << PEXCADRS_CMD_SHIFT)
++
++/* SCC PCIEXC shifts for PEXDADRS */
++#define PEXDADRS_BUSNO_SHIFT		20
++#define PEXDADRS_DEVNO_SHIFT		15
++#define PEXDADRS_FUNCNO_SHIFT		12
++
++/* SCC PCIEXC bits and shifts for PEXDCMND */
++#define PEXDCMND_BYTE_EN_SHIFT		4
++#define PEXDCMND_IO_READ		0x2
++#define PEXDCMND_IO_WRITE		0x3
++#define PEXDCMND_CONFIG_READ		0xa
++#define PEXDCMND_CONFIG_WRITE		0xb
++
++/* SCC PCIEXC bits for PEXPHYPLLST */
++#define PEXPHYPLLST_PEXPHYAPLLST	0x00000001
++
++/* SCC PCIEXC bits for PEXECMODE */
++#define PEXECMODE_ALL_THROUGH		0x00000000
++#define PEXECMODE_ALL_8BIT		0x00550155
++#define PEXECMODE_ALL_16BIT		0x00aa02aa
++
++/* SCC PCIEXC bits for PEXCCRCTRL */
++#define PEXCCRCTRL_PEXIPCOREEN		0x00040000
++#define PEXCCRCTRL_PEXIPCONTEN		0x00020000
++#define PEXCCRCTRL_PEXPHYPLLEN		0x00010000
++#define PEXCCRCTRL_PCIEXCAOCKEN		0x00000100
++
++/* SCC PCIEXC port configuration registers */
++#define PEXTCERRCHK		0x21c
++#define PEXTAMAPB0		0x220
++#define PEXTAMAPL0		0x224
++#define PEXTAMAPB(n)		(PEXTAMAPB0 + 8 * (n))
++#define PEXTAMAPL(n)		(PEXTAMAPL0 + 8 * (n))
++#define PEXCHVC0P		0x500
++#define PEXCHVC0NP		0x504
++#define PEXCHVC0C		0x508
++#define PEXCDVC0P		0x50c
++#define PEXCDVC0NP		0x510
++#define PEXCDVC0C		0x514
++#define PEXCHVCXP		0x518
++#define PEXCHVCXNP		0x51c
++#define PEXCHVCXC		0x520
++#define PEXCDVCXP		0x524
++#define PEXCDVCXNP		0x528
++#define PEXCDVCXC		0x52c
++#define PEXCTTRG		0x530
++#define PEXTSCTRL		0x700
++#define PEXTSSTS		0x704
++#define PEXSKPCTRL		0x708
++
++/* UHC registers */
++#define SCC_UHC_CKRCTRL         0xff0
++#define SCC_UHC_ECMODE          0xf00
++
++/* bits for SCC_UHC_CKRCTRL */
++#define SCC_UHC_F48MCKLEN       0x00000001
++#define SCC_UHC_P_SUSPEND       0x00000002
++#define SCC_UHC_PHY_SUSPEND_SEL 0x00000004
++#define SCC_UHC_HCLKEN          0x00000100
++#define SCC_UHC_USBEN           0x00010000
++#define SCC_UHC_USBCEN          0x00020000
++#define SCC_UHC_PHYEN           0x00040000
++
++/* bits for SCC_UHC_ECMODE */
++#define SCC_UHC_ECMODE_BY_BYTE  0x00000555
++#define SCC_UHC_ECMODE_BY_WORD  0x00000aaa
++
++#endif /* _CELLEB_SCC_H */
+diff --git a/arch/powerpc/platforms/cell/celleb_scc_epci.c b/arch/powerpc/platforms/cell/celleb_scc_epci.c
+new file mode 100644
+index 0000000..08c285b
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc_epci.c
+@@ -0,0 +1,438 @@
++/*
++ * Support for SCC external PCI
++ *
++ * (C) Copyright 2004-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/threads.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/pci_regs.h>
++#include <linux/bootmem.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/prom.h>
++#include <asm/pci-bridge.h>
++#include <asm/ppc-pci.h>
++
++#include "celleb_scc.h"
++#include "celleb_pci.h"
++
++#define MAX_PCI_DEVICES   32
++#define MAX_PCI_FUNCTIONS  8
++
++#define iob()  __asm__ __volatile__("eieio; sync":::"memory")
++
++static inline PCI_IO_ADDR celleb_epci_get_epci_base(
++					struct pci_controller *hose)
++{
++	/*
++	 * Note:
++	 * Celleb epci uses cfg_addr as a base address for
++	 * epci control registers.
++	 */
++
++	return hose->cfg_addr;
++}
++
++static inline PCI_IO_ADDR celleb_epci_get_epci_cfg(
++					struct pci_controller *hose)
++{
++	/*
++	 * Note:
++	 * Celleb epci uses cfg_data as a base address for
++	 * configuration area for epci devices.
++	 */
++
++	return hose->cfg_data;
++}
++
++static inline void clear_and_disable_master_abort_interrupt(
++					struct pci_controller *hose)
++{
++	PCI_IO_ADDR epci_base;
++	PCI_IO_ADDR reg;
++	epci_base = celleb_epci_get_epci_base(hose);
++	reg = epci_base + PCI_COMMAND;
++	out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16));
++}
++
++static int celleb_epci_check_abort(struct pci_controller *hose,
++				   PCI_IO_ADDR addr)
++{
++	PCI_IO_ADDR reg;
++	PCI_IO_ADDR epci_base;
++	u32 val;
++
++	iob();
++	epci_base = celleb_epci_get_epci_base(hose);
++
++	reg = epci_base + PCI_COMMAND;
++	val = in_be32(reg);
++
++	if (val & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
++		out_be32(reg,
++			 (val & 0xffff) | (PCI_STATUS_REC_MASTER_ABORT << 16));
++
++		/* clear PCI Controller error, FRE, PMFE */
++		reg = epci_base + SCC_EPCI_STATUS;
++		out_be32(reg, SCC_EPCI_INT_PAI);
++
++		reg = epci_base + SCC_EPCI_VCSR;
++		val = in_be32(reg) & 0xffff;
++		val |= SCC_EPCI_VCSR_FRE;
++		out_be32(reg, val);
++
++		reg = epci_base + SCC_EPCI_VISTAT;
++		out_be32(reg, SCC_EPCI_VISTAT_PMFE);
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	}
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static PCI_IO_ADDR celleb_epci_make_config_addr(struct pci_bus *bus,
++		struct pci_controller *hose, unsigned int devfn, int where)
++{
++	PCI_IO_ADDR addr;
++
++	if (bus != hose->bus)
++		addr = celleb_epci_get_epci_cfg(hose) +
++		       (((bus->number & 0xff) << 16)
++			| ((devfn & 0xff) << 8)
++			| (where & 0xff)
++			| 0x01000000);
++	else
++		addr = celleb_epci_get_epci_cfg(hose) +
++		       (((devfn & 0xff) << 8) | (where & 0xff));
++
++	pr_debug("EPCI: config_addr = 0x%p\n", addr);
++
++	return addr;
++}
++
++static int celleb_epci_read_config(struct pci_bus *bus,
++			unsigned int devfn, int where, int size, u32 *val)
++{
++	PCI_IO_ADDR epci_base;
++	PCI_IO_ADDR addr;
++	struct device_node *node;
++	struct pci_controller *hose;
++
++	/* allignment check */
++	BUG_ON(where % size);
++
++	node = (struct device_node *)bus->sysdata;
++	hose = pci_find_hose_for_OF_device(node);
++
++	if (!celleb_epci_get_epci_cfg(hose))
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	if (bus->number == hose->first_busno && devfn == 0) {
++		/* EPCI controller self */
++
++		epci_base = celleb_epci_get_epci_base(hose);
++		addr = epci_base + where;
++
++		switch (size) {
++		case 1:
++			*val = in_8(addr);
++			break;
++		case 2:
++			*val = in_be16(addr);
++			break;
++		case 4:
++			*val = in_be32(addr);
++			break;
++		default:
++			return PCIBIOS_DEVICE_NOT_FOUND;
++		}
++
++	} else {
++
++		clear_and_disable_master_abort_interrupt(hose);
++		addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
++
++		switch (size) {
++		case 1:
++			*val = in_8(addr);
++			break;
++		case 2:
++			*val = in_le16(addr);
++			break;
++		case 4:
++			*val = in_le32(addr);
++			break;
++		default:
++			return PCIBIOS_DEVICE_NOT_FOUND;
++		}
++	}
++
++	pr_debug("EPCI: "
++		 "addr=0x%p, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
++		 addr, devfn, where, size, *val);
++
++	return celleb_epci_check_abort(hose, NULL);
++}
++
++static int celleb_epci_write_config(struct pci_bus *bus,
++			unsigned int devfn, int where, int size, u32 val)
++{
++	PCI_IO_ADDR epci_base;
++	PCI_IO_ADDR addr;
++	struct device_node *node;
++	struct pci_controller *hose;
++
++	/* allignment check */
++	BUG_ON(where % size);
++
++	node = (struct device_node *)bus->sysdata;
++	hose = pci_find_hose_for_OF_device(node);
++
++
++	if (!celleb_epci_get_epci_cfg(hose))
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	if (bus->number == hose->first_busno && devfn == 0) {
++		/* EPCI controller self */
++
++		epci_base = celleb_epci_get_epci_base(hose);
++		addr = epci_base + where;
++
++		switch (size) {
++		case 1:
++			out_8(addr, val);
++			break;
++		case 2:
++			out_be16(addr, val);
++			break;
++		case 4:
++			out_be32(addr, val);
++			break;
++		default:
++			return PCIBIOS_DEVICE_NOT_FOUND;
++		}
++
++	} else {
++
++		clear_and_disable_master_abort_interrupt(hose);
++		addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
++
++		switch (size) {
++		case 1:
++			out_8(addr, val);
++			break;
++		case 2:
++			out_le16(addr, val);
++			break;
++		case 4:
++			out_le32(addr, val);
++			break;
++		default:
++			return PCIBIOS_DEVICE_NOT_FOUND;
++		}
++	}
++
++	return celleb_epci_check_abort(hose, addr);
++}
++
++struct pci_ops celleb_epci_ops = {
++	.read = celleb_epci_read_config,
++	.write = celleb_epci_write_config,
++};
++
++/* to be moved in FW */
++static int __init celleb_epci_init(struct pci_controller *hose)
++{
++	u32 val;
++	PCI_IO_ADDR reg;
++	PCI_IO_ADDR epci_base;
++	int hwres = 0;
++
++	epci_base = celleb_epci_get_epci_base(hose);
++
++	/* PCI core reset(Internal bus and PCI clock) */
++	reg = epci_base + SCC_EPCI_CKCTRL;
++	val = in_be32(reg);
++	if (val == 0x00030101)
++		hwres = 1;
++	else {
++		val &= ~(SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
++		out_be32(reg, val);
++
++		/* set PCI core clock */
++		val = in_be32(reg);
++		val |= (SCC_EPCI_CKCTRL_OCLKEN | SCC_EPCI_CKCTRL_LCLKEN);
++		out_be32(reg, val);
++
++		/* release PCI core reset (internal bus) */
++		val = in_be32(reg);
++		val |= SCC_EPCI_CKCTRL_CRST0;
++		out_be32(reg, val);
++
++		/* set PCI clock select */
++		reg = epci_base + SCC_EPCI_CLKRST;
++		val = in_be32(reg);
++		val &= ~SCC_EPCI_CLKRST_CKS_MASK;
++		val |= SCC_EPCI_CLKRST_CKS_2;
++		out_be32(reg, val);
++
++		/* set arbiter */
++		reg = epci_base + SCC_EPCI_ABTSET;
++		out_be32(reg, 0x0f1f001f);	/* temporary value */
++
++		/* buffer on */
++		reg = epci_base + SCC_EPCI_CLKRST;
++		val = in_be32(reg);
++		val |= SCC_EPCI_CLKRST_BC;
++		out_be32(reg, val);
++
++		/* PCI clock enable */
++		val = in_be32(reg);
++		val |= SCC_EPCI_CLKRST_PCKEN;
++		out_be32(reg, val);
++
++		/* release PCI core reset (all) */
++		reg = epci_base + SCC_EPCI_CKCTRL;
++		val = in_be32(reg);
++		val |= (SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
++		out_be32(reg, val);
++
++		/* set base translation registers. (already set by Beat) */
++
++		/* set base address masks. (already set by Beat) */
++	}
++
++	/* release interrupt masks and clear all interrupts */
++	reg = epci_base + SCC_EPCI_INTSET;
++	out_be32(reg, 0x013f011f);	/* all interrupts enable */
++	reg = epci_base + SCC_EPCI_VIENAB;
++	val = SCC_EPCI_VIENAB_PMPEE | SCC_EPCI_VIENAB_PMFEE;
++	out_be32(reg, val);
++	reg = epci_base + SCC_EPCI_STATUS;
++	out_be32(reg, 0xffffffff);
++	reg = epci_base + SCC_EPCI_VISTAT;
++	out_be32(reg, 0xffffffff);
++
++	/* disable PCI->IB address translation */
++	reg = epci_base + SCC_EPCI_VCSR;
++	val = in_be32(reg);
++	val &= ~(SCC_EPCI_VCSR_DR | SCC_EPCI_VCSR_AT);
++	out_be32(reg, val);
++
++	/* set base addresses. (no need to set?) */
++
++	/* memory space, bus master enable */
++	reg = epci_base + PCI_COMMAND;
++	val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
++	out_be32(reg, val);
++
++	/* endian mode setup */
++	reg = epci_base + SCC_EPCI_ECMODE;
++	val = 0x00550155;
++	out_be32(reg, val);
++
++	/* set control option */
++	reg = epci_base + SCC_EPCI_CNTOPT;
++	val = in_be32(reg);
++	val |= SCC_EPCI_CNTOPT_O2PMB;
++	out_be32(reg, val);
++
++	/* XXX: temporay: set registers for address conversion setup */
++	reg = epci_base + SCC_EPCI_CNF10_REG;
++	out_be32(reg, 0x80000008);
++	reg = epci_base + SCC_EPCI_CNF14_REG;
++	out_be32(reg, 0x40000008);
++
++	reg = epci_base + SCC_EPCI_BAM0;
++	out_be32(reg, 0x80000000);
++	reg = epci_base + SCC_EPCI_BAM1;
++	out_be32(reg, 0xe0000000);
++
++	reg = epci_base + SCC_EPCI_PVBAT;
++	out_be32(reg, 0x80000000);
++
++	if (!hwres) {
++		/* release external PCI reset */
++		reg = epci_base + SCC_EPCI_CLKRST;
++		val = in_be32(reg);
++		val |= SCC_EPCI_CLKRST_PCIRST;
++		out_be32(reg, val);
++	}
++
++	return 0;
++}
++
++static int __init celleb_setup_epci(struct device_node *node,
++				    struct pci_controller *hose)
++{
++	struct resource r;
++
++	pr_debug("PCI: celleb_setup_epci()\n");
++
++	/*
++	 * Note:
++	 * Celleb epci uses cfg_addr and cfg_data member of
++	 * pci_controller structure in irregular way.
++	 *
++	 * cfg_addr is used to map for control registers of
++	 * celleb epci.
++	 *
++	 * cfg_data is used for configuration area of devices
++	 * on Celleb epci buses.
++	 */
++
++	if (of_address_to_resource(node, 0, &r))
++		goto error;
++	hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1));
++	if (!hose->cfg_addr)
++		goto error;
++	pr_debug("EPCI: cfg_addr map 0x%016lx->0x%016lx + 0x%016lx\n",
++		 r.start, (unsigned long)hose->cfg_addr, (r.end - r.start + 1));
++
++	if (of_address_to_resource(node, 2, &r))
++		goto error;
++	hose->cfg_data = ioremap(r.start, (r.end - r.start + 1));
++	if (!hose->cfg_data)
++		goto error;
++	pr_debug("EPCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n",
++		 r.start, (unsigned long)hose->cfg_data, (r.end - r.start + 1));
++
++	hose->ops = &celleb_epci_ops;
++	celleb_epci_init(hose);
++
++	return 0;
++
++error:
++	if (hose->cfg_addr)
++		iounmap(hose->cfg_addr);
++
++	if (hose->cfg_data)
++		iounmap(hose->cfg_data);
++	return 1;
++}
++
++struct celleb_phb_spec celleb_epci_spec __initdata = {
++	.setup = celleb_setup_epci,
++	.ops = &spiderpci_ops,
++	.iowa_init = &spiderpci_iowa_init,
++	.iowa_data = (void *)0,
++};
+diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+new file mode 100644
+index 0000000..ab24d94
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+@@ -0,0 +1,547 @@
++/*
++ * Support for Celleb PCI-Express.
++ *
++ * (C) Copyright 2007-2008 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/iommu.h>
++#include <asm/byteorder.h>
++
++#include "celleb_scc.h"
++#include "celleb_pci.h"
++
++#define PEX_IN(base, off)	in_be32((void *)(base) + (off))
++#define PEX_OUT(base, off, data) out_be32((void *)(base) + (off), (data))
++
++static void scc_pciex_io_flush(struct iowa_bus *bus)
++{
++	(void)PEX_IN(bus->phb->cfg_addr, PEXDMRDEN0);
++}
++
++/*
++ * Memory space access to device on PCIEX
++ */
++#define PCIEX_MMIO_READ(name, ret)					\
++static ret scc_pciex_##name(const PCI_IO_ADDR addr)			\
++{									\
++	ret val = __do_##name(addr);					\
++	scc_pciex_io_flush(iowa_mem_find_bus(addr));			\
++	return val;							\
++}
++
++#define PCIEX_MMIO_READ_STR(name)					\
++static void scc_pciex_##name(const PCI_IO_ADDR addr, void *buf,		\
++			     unsigned long count)			\
++{									\
++	__do_##name(addr, buf, count);					\
++	scc_pciex_io_flush(iowa_mem_find_bus(addr));			\
++}
++
++PCIEX_MMIO_READ(readb, u8)
++PCIEX_MMIO_READ(readw, u16)
++PCIEX_MMIO_READ(readl, u32)
++PCIEX_MMIO_READ(readq, u64)
++PCIEX_MMIO_READ(readw_be, u16)
++PCIEX_MMIO_READ(readl_be, u32)
++PCIEX_MMIO_READ(readq_be, u64)
++PCIEX_MMIO_READ_STR(readsb)
++PCIEX_MMIO_READ_STR(readsw)
++PCIEX_MMIO_READ_STR(readsl)
++
++static void scc_pciex_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
++				    unsigned long n)
++{
++	__do_memcpy_fromio(dest, src, n);
++	scc_pciex_io_flush(iowa_mem_find_bus(src));
++}
++
++/*
++ * I/O port access to devices on PCIEX.
++ */
++
++static inline unsigned long get_bus_address(struct pci_controller *phb,
++					    unsigned long port)
++{
++	return port - ((unsigned long)(phb->io_base_virt) - _IO_BASE);
++}
++
++static u32 scc_pciex_read_port(struct pci_controller *phb,
++			       unsigned long port, int size)
++{
++	unsigned int byte_enable;
++	unsigned int cmd, shift;
++	unsigned long addr;
++	u32 data, ret;
++
++	BUG_ON(((port & 0x3ul) + size) > 4);
++
++	addr = get_bus_address(phb, port);
++	shift = addr & 0x3ul;
++	byte_enable = ((1 << size) - 1) << shift;
++	cmd = PEXDCMND_IO_READ | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
++	PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
++	PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
++	data = PEX_IN(phb->cfg_addr, PEXDRDATA);
++	ret = (data >> (shift * 8)) & (0xFFFFFFFF >> ((4 - size) * 8));
++
++	pr_debug("PCIEX:PIO READ:port=0x%lx, addr=0x%lx, size=%d, be=%x,"
++		 " cmd=%x, data=%x, ret=%x\n", port, addr, size, byte_enable,
++		 cmd, data, ret);
++
++	return ret;
++}
++
++static void scc_pciex_write_port(struct pci_controller *phb,
++				 unsigned long port, int size, u32 val)
++{
++	unsigned int byte_enable;
++	unsigned int cmd, shift;
++	unsigned long addr;
++	u32 data;
++
++	BUG_ON(((port & 0x3ul) + size) > 4);
++
++	addr = get_bus_address(phb, port);
++	shift = addr & 0x3ul;
++	byte_enable = ((1 << size) - 1) << shift;
++	cmd = PEXDCMND_IO_WRITE | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
++	data = (val & (0xFFFFFFFF >> (4 - size) * 8)) << (shift * 8);
++	PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
++	PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
++	PEX_OUT(phb->cfg_addr, PEXDWDATA, data);
++
++	pr_debug("PCIEX:PIO WRITE:port=0x%lx, addr=%lx, size=%d, val=%x,"
++		 " be=%x, cmd=%x, data=%x\n", port, addr, size, val,
++		 byte_enable, cmd, data);
++}
++
++static u8 __scc_pciex_inb(struct pci_controller *phb, unsigned long port)
++{
++	return (u8)scc_pciex_read_port(phb, port, 1);
++}
++
++static u16 __scc_pciex_inw(struct pci_controller *phb, unsigned long port)
++{
++	u32 data;
++	if ((port & 0x3ul) < 3)
++		data = scc_pciex_read_port(phb, port, 2);
++	else {
++		u32 d1 = scc_pciex_read_port(phb, port, 1);
++		u32 d2 = scc_pciex_read_port(phb, port + 1, 1);
++		data = d1 | (d2 << 8);
++	}
++	return (u16)data;
++}
++
++static u32 __scc_pciex_inl(struct pci_controller *phb, unsigned long port)
++{
++	unsigned int mod = port & 0x3ul;
++	u32 data;
++	if (mod == 0)
++		data = scc_pciex_read_port(phb, port, 4);
++	else {
++		u32 d1 = scc_pciex_read_port(phb, port, 4 - mod);
++		u32 d2 = scc_pciex_read_port(phb, port + 1, mod);
++		data = d1 | (d2 << (mod * 8));
++	}
++	return data;
++}
++
++static void __scc_pciex_outb(struct pci_controller *phb,
++			     u8 val, unsigned long port)
++{
++	scc_pciex_write_port(phb, port, 1, (u32)val);
++}
++
++static void __scc_pciex_outw(struct pci_controller *phb,
++			     u16 val, unsigned long port)
++{
++	if ((port & 0x3ul) < 3)
++		scc_pciex_write_port(phb, port, 2, (u32)val);
++	else {
++		u32 d1 = val & 0x000000FF;
++		u32 d2 = (val & 0x0000FF00) >> 8;
++		scc_pciex_write_port(phb, port, 1, d1);
++		scc_pciex_write_port(phb, port + 1, 1, d2);
++	}
++}
++
++static void __scc_pciex_outl(struct pci_controller *phb,
++			     u32 val, unsigned long port)
++{
++	unsigned int mod = port & 0x3ul;
++	if (mod == 0)
++		scc_pciex_write_port(phb, port, 4, val);
++	else {
++		u32 d1 = val & (0xFFFFFFFFul >> (mod * 8));
++		u32 d2 = val >> ((4 - mod) * 8);
++		scc_pciex_write_port(phb, port, 4 - mod, d1);
++		scc_pciex_write_port(phb, port + 1, mod, d2);
++	}
++}
++
++#define PCIEX_PIO_FUNC(size, name)					\
++static u##size scc_pciex_in##name(unsigned long port)			\
++{									\
++	struct iowa_bus *bus = iowa_pio_find_bus(port);			\
++	u##size data = __scc_pciex_in##name(bus->phb, port);		\
++	scc_pciex_io_flush(bus);					\
++	return data;							\
++}									\
++static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \
++{									\
++	struct iowa_bus *bus = iowa_pio_find_bus(p);			\
++	u##size *dst = b;						\
++	for (; c != 0; c--, dst++)					\
++		*dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \
++	scc_pciex_io_flush(bus);					\
++}									\
++static void scc_pciex_out##name(u##size val, unsigned long port)	\
++{									\
++	struct iowa_bus *bus = iowa_pio_find_bus(port);			\
++	__scc_pciex_out##name(bus->phb, val, port);			\
++}									\
++static void scc_pciex_outs##name(unsigned long p, const void *b,	\
++				 unsigned long c)			\
++{									\
++	struct iowa_bus *bus = iowa_pio_find_bus(p);			\
++	const u##size *src = b;						\
++	for (; c != 0; c--, src++)					\
++		__scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \
++}
++#define cpu_to_le8(x) (x)
++#define le8_to_cpu(x) (x)
++PCIEX_PIO_FUNC(8, b)
++PCIEX_PIO_FUNC(16, w)
++PCIEX_PIO_FUNC(32, l)
++
++static struct ppc_pci_io scc_pciex_ops = {
++	.readb = scc_pciex_readb,
++	.readw = scc_pciex_readw,
++	.readl = scc_pciex_readl,
++	.readq = scc_pciex_readq,
++	.readw_be = scc_pciex_readw_be,
++	.readl_be = scc_pciex_readl_be,
++	.readq_be = scc_pciex_readq_be,
++	.readsb = scc_pciex_readsb,
++	.readsw = scc_pciex_readsw,
++	.readsl = scc_pciex_readsl,
++	.memcpy_fromio = scc_pciex_memcpy_fromio,
++	.inb = scc_pciex_inb,
++	.inw = scc_pciex_inw,
++	.inl = scc_pciex_inl,
++	.outb = scc_pciex_outb,
++	.outw = scc_pciex_outw,
++	.outl = scc_pciex_outl,
++	.insb = scc_pciex_insb,
++	.insw = scc_pciex_insw,
++	.insl = scc_pciex_insl,
++	.outsb = scc_pciex_outsb,
++	.outsw = scc_pciex_outsw,
++	.outsl = scc_pciex_outsl,
++};
++
++static int __init scc_pciex_iowa_init(struct iowa_bus *bus, void *data)
++{
++	dma_addr_t dummy_page_da;
++	void *dummy_page_va;
++
++	dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
++	if (!dummy_page_va) {
++		pr_err("PCIEX:Alloc dummy_page_va failed\n");
++		return -1;
++	}
++
++	dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va,
++				       PAGE_SIZE, DMA_FROM_DEVICE);
++	if (dma_mapping_error(dummy_page_da)) {
++		pr_err("PCIEX:Map dummy page failed.\n");
++		kfree(dummy_page_va);
++		return -1;
++	}
++
++	PEX_OUT(bus->phb->cfg_addr, PEXDMRDADR0, dummy_page_da);
++
++	return 0;
++}
++
++/*
++ * config space access
++ */
++#define MK_PEXDADRS(bus_no, dev_no, func_no, addr) \
++	((uint32_t)(((addr) & ~0x3UL) | \
++	((bus_no) << PEXDADRS_BUSNO_SHIFT) | \
++	((dev_no)  << PEXDADRS_DEVNO_SHIFT) | \
++	((func_no) << PEXDADRS_FUNCNO_SHIFT)))
++
++#define MK_PEXDCMND_BYTE_EN(addr, size) \
++	((((0x1 << (size))-1) << ((addr) & 0x3)) << PEXDCMND_BYTE_EN_SHIFT)
++#define MK_PEXDCMND(cmd, addr, size) ((cmd) | MK_PEXDCMND_BYTE_EN(addr, size))
++
++static uint32_t config_read_pciex_dev(unsigned int *base,
++		uint64_t bus_no, uint64_t dev_no, uint64_t func_no,
++		uint64_t off, uint64_t size)
++{
++	uint32_t ret;
++	uint32_t addr, cmd;
++
++	addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
++	cmd = MK_PEXDCMND(PEXDCMND_CONFIG_READ, off, size);
++	PEX_OUT(base, PEXDADRS, addr);
++	PEX_OUT(base, PEXDCMND, cmd);
++	ret = (PEX_IN(base, PEXDRDATA)
++		>> ((off & (4-size)) * 8)) & ((0x1 << (size * 8)) - 1);
++	return ret;
++}
++
++static void config_write_pciex_dev(unsigned int *base, uint64_t bus_no,
++	uint64_t dev_no, uint64_t func_no, uint64_t off, uint64_t size,
++	uint32_t data)
++{
++	uint32_t addr, cmd;
++
++	addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
++	cmd = MK_PEXDCMND(PEXDCMND_CONFIG_WRITE, off, size);
++	PEX_OUT(base, PEXDADRS, addr);
++	PEX_OUT(base, PEXDCMND, cmd);
++	PEX_OUT(base, PEXDWDATA,
++		(data & ((0x1 << (size * 8)) - 1)) << ((off & (4-size)) * 8));
++}
++
++#define MK_PEXCADRS_BYTE_EN(off, len) \
++	((((0x1 << (len)) - 1) << ((off) & 0x3)) << PEXCADRS_BYTE_EN_SHIFT)
++#define MK_PEXCADRS(cmd, addr, size) \
++	((cmd) | MK_PEXCADRS_BYTE_EN(addr, size) | ((addr) & ~0x3))
++static uint32_t config_read_pciex_rc(unsigned int *base,
++				     uint32_t where, uint32_t size)
++{
++	PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_READ, where, size));
++	return (PEX_IN(base, PEXCRDATA)
++		>> ((where & (4 - size)) * 8)) & ((0x1 << (size * 8)) - 1);
++}
++
++static void config_write_pciex_rc(unsigned int *base, uint32_t where,
++				  uint32_t size, uint32_t val)
++{
++	uint32_t data;
++
++	data = (val & ((0x1 << (size * 8)) - 1)) << ((where & (4 - size)) * 8);
++	PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_WRITE, where, size));
++	PEX_OUT(base, PEXCWDATA, data);
++}
++
++/* Interfaces */
++/* Note: Work-around
++ *  On SCC PCIEXC, one device is seen on all 32 dev_no.
++ *  As SCC PCIEXC can have only one device on the bus, we look only one dev_no.
++ * (dev_no = 1)
++ */
++static int scc_pciex_read_config(struct pci_bus *bus, unsigned int devfn,
++				 int where, int size, unsigned int *val)
++{
++	struct device_node *dn;
++	struct pci_controller *phb;
++
++	dn = bus->sysdata;
++	phb = pci_find_hose_for_OF_device(dn);
++
++	if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) {
++		*val = ~0;
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	}
++
++	if (bus->number == 0 && PCI_SLOT(devfn) == 0)
++		*val = config_read_pciex_rc(phb->cfg_addr, where, size);
++	else
++		*val = config_read_pciex_dev(phb->cfg_addr, bus->number,
++				PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
++				  int where, int size, unsigned int val)
++{
++	struct device_node *dn;
++	struct pci_controller *phb;
++
++	dn = bus->sysdata;
++	phb = pci_find_hose_for_OF_device(dn);
++
++	if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	if (bus->number == 0 && PCI_SLOT(devfn) == 0)
++		config_write_pciex_rc(phb->cfg_addr, where, size, val);
++	else
++		config_write_pciex_dev(phb->cfg_addr, bus->number,
++			PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops scc_pciex_pci_ops = {
++	scc_pciex_read_config,
++	scc_pciex_write_config,
++};
++
++static void pciex_clear_intr_all(unsigned int *base)
++{
++	PEX_OUT(base, PEXAERRSTS, 0xffffffff);
++	PEX_OUT(base, PEXPRERRSTS, 0xffffffff);
++	PEX_OUT(base, PEXINTSTS, 0xffffffff);
++}
++
++#if 0
++static void pciex_disable_intr_all(unsigned int *base)
++{
++	PEX_OUT(base, PEXINTMASK,   0x0);
++	PEX_OUT(base, PEXAERRMASK,  0x0);
++	PEX_OUT(base, PEXPRERRMASK, 0x0);
++	PEX_OUT(base, PEXVDMASK,    0x0);
++}
++#endif
++
++static void pciex_enable_intr_all(unsigned int *base)
++{
++	PEX_OUT(base, PEXINTMASK, 0x0000e7f1);
++	PEX_OUT(base, PEXAERRMASK, 0x03ff01ff);
++	PEX_OUT(base, PEXPRERRMASK, 0x0001010f);
++	PEX_OUT(base, PEXVDMASK, 0x00000001);
++}
++
++static void pciex_check_status(unsigned int *base)
++{
++	uint32_t err = 0;
++	uint32_t intsts, aerr, prerr, rcvcp, lenerr;
++	uint32_t maea, maec;
++
++	intsts = PEX_IN(base, PEXINTSTS);
++	aerr = PEX_IN(base, PEXAERRSTS);
++	prerr = PEX_IN(base, PEXPRERRSTS);
++	rcvcp = PEX_IN(base, PEXRCVCPLIDA);
++	lenerr = PEX_IN(base, PEXLENERRIDA);
++
++	if (intsts || aerr || prerr || rcvcp || lenerr)
++		err = 1;
++
++	pr_info("PCEXC interrupt!!\n");
++	pr_info("PEXINTSTS    :0x%08x\n", intsts);
++	pr_info("PEXAERRSTS   :0x%08x\n", aerr);
++	pr_info("PEXPRERRSTS  :0x%08x\n", prerr);
++	pr_info("PEXRCVCPLIDA :0x%08x\n", rcvcp);
++	pr_info("PEXLENERRIDA :0x%08x\n", lenerr);
++
++	/* print detail of Protection Error */
++	if (intsts & 0x00004000) {
++		uint32_t i, n;
++		for (i = 0; i < 4; i++) {
++			n = 1 << i;
++			if (prerr & n) {
++				maea = PEX_IN(base, PEXMAEA(i));
++				maec = PEX_IN(base, PEXMAEC(i));
++				pr_info("PEXMAEC%d     :0x%08x\n", i, maec);
++				pr_info("PEXMAEA%d     :0x%08x\n", i, maea);
++			}
++		}
++	}
++
++	if (err)
++		pciex_clear_intr_all(base);
++}
++
++static irqreturn_t pciex_handle_internal_irq(int irq, void *dev_id)
++{
++	struct pci_controller *phb = dev_id;
++
++	pr_debug("PCIEX:pciex_handle_internal_irq(irq=%d)\n", irq);
++
++	BUG_ON(phb->cfg_addr == NULL);
++
++	pciex_check_status(phb->cfg_addr);
++
++	return IRQ_HANDLED;
++}
++
++static __init int celleb_setup_pciex(struct device_node *node,
++				     struct pci_controller *phb)
++{
++	struct resource	r;
++	struct of_irq oirq;
++	int virq;
++
++	/* SMMIO registers; used inside this file */
++	if (of_address_to_resource(node, 0, &r)) {
++		pr_err("PCIEXC:Failed to get config resource.\n");
++		return 1;
++	}
++	phb->cfg_addr = ioremap(r.start, r.end - r.start + 1);
++	if (!phb->cfg_addr) {
++		pr_err("PCIEXC:Failed to remap SMMIO region.\n");
++		return 1;
++	}
++
++	/* Not use cfg_data,  cmd and data regs are near address reg */
++	phb->cfg_data = NULL;
++
++	/* set pci_ops */
++	phb->ops = &scc_pciex_pci_ops;
++
++	/* internal interrupt handler */
++	if (of_irq_map_one(node, 1, &oirq)) {
++		pr_err("PCIEXC:Failed to map irq\n");
++		goto error;
++	}
++	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
++				     oirq.size);
++	if (request_irq(virq, pciex_handle_internal_irq,
++			IRQF_DISABLED, "pciex", (void *)phb)) {
++		pr_err("PCIEXC:Failed to request irq\n");
++		goto error;
++	}
++
++	/* enable all interrupts */
++	pciex_clear_intr_all(phb->cfg_addr);
++	pciex_enable_intr_all(phb->cfg_addr);
++	/* MSI: TBD */
++
++	return 0;
++
++error:
++	phb->cfg_data = NULL;
++	if (phb->cfg_addr)
++		iounmap(phb->cfg_addr);
++	phb->cfg_addr = NULL;
++	return 1;
++}
++
++struct celleb_phb_spec celleb_pciex_spec __initdata = {
++	.setup = celleb_setup_pciex,
++	.ops = &scc_pciex_ops,
++	.iowa_init = &scc_pciex_iowa_init,
++};
+diff --git a/arch/powerpc/platforms/cell/celleb_scc_sio.c b/arch/powerpc/platforms/cell/celleb_scc_sio.c
+new file mode 100644
+index 0000000..3a16c5b
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc_sio.c
+@@ -0,0 +1,101 @@
++/*
++ * setup serial port in SCC
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/tty.h>
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++#include <linux/console.h>
++
++#include <asm/io.h>
++#include <asm/prom.h>
++
++/* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024
++    mmio=0xfff000-0x1000,0xff2000-0x1000 */
++static int txx9_serial_bitmap __initdata;
++
++static struct {
++	uint32_t offset;
++	uint32_t index;
++} txx9_scc_tab[3] __initdata = {
++	{ 0x300, 0 },	/* 0xFFF300 */
++	{ 0x400, 0 },	/* 0xFFF400 */
++	{ 0x800, 1 }	/* 0xFF2800 */
++};
++
++static int __init txx9_serial_init(void)
++{
++	extern int early_serial_txx9_setup(struct uart_port *port);
++	struct device_node *node = NULL;
++	int i;
++	struct uart_port req;
++	struct of_irq irq;
++	struct resource res;
++
++	while ((node = of_find_compatible_node(node,
++				"serial", "toshiba,sio-scc")) != NULL) {
++		for (i = 0; i < ARRAY_SIZE(txx9_scc_tab); i++) {
++			if (!(txx9_serial_bitmap & (1<<i)))
++				continue;
++
++			if (of_irq_map_one(node, i, &irq))
++				continue;
++			if (of_address_to_resource(node,
++				txx9_scc_tab[i].index, &res))
++				continue;
++
++			memset(&req, 0, sizeof(req));
++			req.line = i;
++			req.iotype = UPIO_MEM;
++			req.mapbase = res.start + txx9_scc_tab[i].offset;
++#ifdef CONFIG_SERIAL_TXX9_CONSOLE
++			req.membase = ioremap(req.mapbase, 0x24);
++#endif
++			req.irq = irq_create_of_mapping(irq.controller,
++				irq.specifier, irq.size);
++			req.flags |= UPF_IOREMAP | UPF_BUGGY_UART
++				/*HAVE_CTS_LINE*/;
++			req.uartclk = 83300000;
++			early_serial_txx9_setup(&req);
++		}
++	}
++
++	return 0;
++}
++
++static int __init txx9_serial_config(char *ptr)
++{
++	int	i;
++
++	for (;;) {
++		switch (get_option(&ptr, &i)) {
++		default:
++			return 0;
++		case 2:
++			txx9_serial_bitmap |= 1 << i;
++			break;
++		case 1:
++			txx9_serial_bitmap |= 1 << i;
++			return 0;
++		}
++	}
++}
++__setup("txx9_serial=", txx9_serial_config);
++
++console_initcall(txx9_serial_init);
+diff --git a/arch/powerpc/platforms/cell/celleb_scc_uhc.c b/arch/powerpc/platforms/cell/celleb_scc_uhc.c
+new file mode 100644
+index 0000000..d63b720
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc_uhc.c
+@@ -0,0 +1,95 @@
++/*
++ * SCC (Super Companion Chip) UHC setup
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++
++#include <asm/delay.h>
++#include <asm/io.h>
++#include <asm/machdep.h>
++
++#include "celleb_scc.h"
++
++#define UHC_RESET_WAIT_MAX 10000
++
++static inline int uhc_clkctrl_ready(u32 val)
++{
++	const u32 mask = SCC_UHC_USBCEN | SCC_UHC_USBCEN;
++	return((val & mask) == mask);
++}
++
++/*
++ * UHC(usb host controller) enable function.
++ * affect to both of OHCI and EHCI core module.
++ */
++static void enable_scc_uhc(struct pci_dev *dev)
++{
++	void __iomem *uhc_base;
++	u32 __iomem *uhc_clkctrl;
++	u32 __iomem *uhc_ecmode;
++	u32 val = 0;
++	int i;
++
++	if (!machine_is(celleb_beat) &&
++	    !machine_is(celleb_native))
++		return;
++
++	uhc_base = ioremap(pci_resource_start(dev, 0),
++			   pci_resource_len(dev, 0));
++	if (!uhc_base) {
++		printk(KERN_ERR "failed to map UHC register base.\n");
++		return;
++	}
++	uhc_clkctrl = uhc_base + SCC_UHC_CKRCTRL;
++	uhc_ecmode  = uhc_base + SCC_UHC_ECMODE;
++
++	/* setup for normal mode */
++	val |= SCC_UHC_F48MCKLEN;
++	out_be32(uhc_clkctrl, val);
++	val |= SCC_UHC_PHY_SUSPEND_SEL;
++	out_be32(uhc_clkctrl, val);
++	udelay(10);
++	val |= SCC_UHC_PHYEN;
++	out_be32(uhc_clkctrl, val);
++	udelay(50);
++
++	/* disable reset */
++	val |= SCC_UHC_HCLKEN;
++	out_be32(uhc_clkctrl, val);
++	val |= (SCC_UHC_USBCEN | SCC_UHC_USBEN);
++	out_be32(uhc_clkctrl, val);
++	i = 0;
++	while (!uhc_clkctrl_ready(in_be32(uhc_clkctrl))) {
++		udelay(10);
++		if (i++ > UHC_RESET_WAIT_MAX) {
++			printk(KERN_ERR "Failed to disable UHC reset %x\n",
++			       in_be32(uhc_clkctrl));
++			break;
++		}
++	}
++
++	/* Endian Conversion Mode for Master ALL area */
++	out_be32(uhc_ecmode, SCC_UHC_ECMODE_BY_BYTE);
++
++	iounmap(uhc_base);
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
++		 PCI_DEVICE_ID_TOSHIBA_SCC_USB, enable_scc_uhc);
+diff --git a/arch/powerpc/platforms/cell/celleb_setup.c b/arch/powerpc/platforms/cell/celleb_setup.c
+new file mode 100644
+index 0000000..b11cb30
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_setup.c
+@@ -0,0 +1,256 @@
++/*
++ * Celleb setup code
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/cell/setup.c:
++ *  Copyright (C) 1995  Linus Torvalds
++ *  Adapted from 'alpha' version by Gary Thomas
++ *  Modified by Cort Dougan (cort at cs.nmt.edu)
++ *  Modified by PPC64 Team, IBM Corp
++ *  Modified by Cell Team, IBM Deutschland Entwicklung GmbH
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/cpu.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/reboot.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/seq_file.h>
++#include <linux/root_dev.h>
++#include <linux/console.h>
++#include <linux/of_platform.h>
++
++#include <asm/mmu.h>
++#include <asm/processor.h>
++#include <asm/io.h>
++#include <asm/kexec.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/cputable.h>
++#include <asm/irq.h>
++#include <asm/time.h>
++#include <asm/spu_priv1.h>
++#include <asm/firmware.h>
++#include <asm/rtas.h>
++#include <asm/cell-regs.h>
++
++#include "beat_interrupt.h"
++#include "beat_wrapper.h"
++#include "beat.h"
++#include "celleb_pci.h"
++#include "interrupt.h"
++#include "pervasive.h"
++#include "ras.h"
++
++static char celleb_machine_type[128] = "Celleb";
++
++static void celleb_show_cpuinfo(struct seq_file *m)
++{
++	struct device_node *root;
++	const char *model = "";
++
++	root = of_find_node_by_path("/");
++	if (root)
++		model = of_get_property(root, "model", NULL);
++	/* using "CHRP" is to trick anaconda into installing FCx into Celleb */
++	seq_printf(m, "machine\t\t: %s %s\n", celleb_machine_type, model);
++	of_node_put(root);
++}
++
++static int __init celleb_machine_type_hack(char *ptr)
++{
++	strncpy(celleb_machine_type, ptr, sizeof(celleb_machine_type));
++	celleb_machine_type[sizeof(celleb_machine_type)-1] = 0;
++	return 0;
++}
++
++__setup("celleb_machine_type_hack=", celleb_machine_type_hack);
++
++static void celleb_progress(char *s, unsigned short hex)
++{
++	printk("*** %04x : %s\n", hex, s ? s : "");
++}
++
++static void __init celleb_setup_arch_common(void)
++{
++	/* init to some ~sane value until calibrate_delay() runs */
++	loops_per_jiffy = 50000000;
++
++#ifdef CONFIG_DUMMY_CONSOLE
++	conswitchp = &dummy_con;
++#endif
++}
++
++static struct of_device_id celleb_bus_ids[] __initdata = {
++	{ .type = "scc", },
++	{ .type = "ioif", },	/* old style */
++	{},
++};
++
++static int __init celleb_publish_devices(void)
++{
++	/* Publish OF platform devices for southbridge IOs */
++	of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
++
++	return 0;
++}
++machine_device_initcall(celleb_beat, celleb_publish_devices);
++machine_device_initcall(celleb_native, celleb_publish_devices);
++
++
++/*
++ * functions for Celleb-Beat
++ */
++static void __init celleb_setup_arch_beat(void)
++{
++#ifdef CONFIG_SPU_BASE
++	spu_priv1_ops		= &spu_priv1_beat_ops;
++	spu_management_ops	= &spu_management_of_ops;
++#endif
++
++#ifdef CONFIG_SMP
++	smp_init_celleb();
++#endif
++
++	celleb_setup_arch_common();
++}
++
++static int __init celleb_probe_beat(void)
++{
++	unsigned long root = of_get_flat_dt_root();
++
++	if (!of_flat_dt_is_compatible(root, "Beat"))
++		return 0;
++
++	powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
++		| FW_FEATURE_BEAT | FW_FEATURE_LPAR;
++	hpte_init_beat_v3();
++
++	return 1;
++}
++
++
++/*
++ * functions for Celleb-native
++ */
++static void __init celleb_init_IRQ_native(void)
++{
++	iic_init_IRQ();
++	spider_init_IRQ();
++}
++
++static void __init celleb_setup_arch_native(void)
++{
++#ifdef CONFIG_SPU_BASE
++	spu_priv1_ops		= &spu_priv1_mmio_ops;
++	spu_management_ops	= &spu_management_of_ops;
++#endif
++
++	cbe_regs_init();
++
++#ifdef CONFIG_CBE_RAS
++	cbe_ras_init();
++#endif
++
++#ifdef CONFIG_SMP
++	smp_init_cell();
++#endif
++
++	cbe_pervasive_init();
++
++	/* XXX: nvram initialization should be added */
++
++	celleb_setup_arch_common();
++}
++
++static int __init celleb_probe_native(void)
++{
++	unsigned long root = of_get_flat_dt_root();
++
++	if (of_flat_dt_is_compatible(root, "Beat") ||
++	    !of_flat_dt_is_compatible(root, "TOSHIBA,Celleb"))
++		return 0;
++
++	powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
++	hpte_init_native();
++
++	return 1;
++}
++
++
++/*
++ * machine definitions
++ */
++define_machine(celleb_beat) {
++	.name			= "Cell Reference Set (Beat)",
++	.probe			= celleb_probe_beat,
++	.setup_arch		= celleb_setup_arch_beat,
++	.show_cpuinfo		= celleb_show_cpuinfo,
++	.restart		= beat_restart,
++	.power_off		= beat_power_off,
++	.halt			= beat_halt,
++	.get_rtc_time		= beat_get_rtc_time,
++	.set_rtc_time		= beat_set_rtc_time,
++	.calibrate_decr		= generic_calibrate_decr,
++	.progress		= celleb_progress,
++	.power_save		= beat_power_save,
++	.nvram_size		= beat_nvram_get_size,
++	.nvram_read		= beat_nvram_read,
++	.nvram_write		= beat_nvram_write,
++	.set_dabr		= beat_set_xdabr,
++	.init_IRQ		= beatic_init_IRQ,
++	.get_irq		= beatic_get_irq,
++	.pci_probe_mode 	= celleb_pci_probe_mode,
++	.pci_setup_phb		= celleb_setup_phb,
++#ifdef CONFIG_KEXEC
++	.kexec_cpu_down		= beat_kexec_cpu_down,
++	.machine_kexec		= default_machine_kexec,
++	.machine_kexec_prepare	= default_machine_kexec_prepare,
++	.machine_crash_shutdown	= default_machine_crash_shutdown,
++#endif
++};
++
++define_machine(celleb_native) {
++	.name			= "Cell Reference Set (native)",
++	.probe			= celleb_probe_native,
++	.setup_arch		= celleb_setup_arch_native,
++	.show_cpuinfo		= celleb_show_cpuinfo,
++	.restart		= rtas_restart,
++	.power_off		= rtas_power_off,
++	.halt			= rtas_halt,
++	.get_boot_time		= rtas_get_boot_time,
++	.get_rtc_time		= rtas_get_rtc_time,
++	.set_rtc_time		= rtas_set_rtc_time,
++	.calibrate_decr		= generic_calibrate_decr,
++	.progress		= celleb_progress,
++	.pci_probe_mode 	= celleb_pci_probe_mode,
++	.pci_setup_phb		= celleb_setup_phb,
++	.init_IRQ		= celleb_init_IRQ_native,
++#ifdef CONFIG_KEXEC
++	.machine_kexec		= default_machine_kexec,
++	.machine_kexec_prepare	= default_machine_kexec_prepare,
++	.machine_crash_shutdown	= default_machine_crash_shutdown,
++#endif
++};
+diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
+index 979d4b6..3b84e8b 100644
+--- a/arch/powerpc/platforms/cell/io-workarounds.c
++++ b/arch/powerpc/platforms/cell/io-workarounds.c
+@@ -1,6 +1,9 @@
+ /*
++ * Support PCI IO workaround
++ *
+  *  Copyright (C) 2006 Benjamin Herrenschmidt <benh at kernel.crashing.org>
+  *		       IBM, Corp.
++ *  (C) Copyright 2007-2008 TOSHIBA 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
+@@ -9,335 +12,174 @@
+ #undef DEBUG
+ 
+ #include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/pci.h>
++
+ #include <asm/io.h>
+ #include <asm/machdep.h>
+-#include <asm/pci-bridge.h>
++#include <asm/pgtable.h>
+ #include <asm/ppc-pci.h>
+ 
++#include "io-workarounds.h"
+ 
+-#define SPIDER_PCI_REG_BASE		0xd000
+-#define SPIDER_PCI_VCI_CNTL_STAT	0x0110
+-#define SPIDER_PCI_DUMMY_READ		0x0810
+-#define SPIDER_PCI_DUMMY_READ_BASE	0x0814
++#define IOWA_MAX_BUS	8
+ 
+-/* Undefine that to re-enable bogus prefetch
+- *
+- * Without that workaround, the chip will do bogus prefetch past
+- * page boundary from system memory. This setting will disable that,
+- * though the documentation is unclear as to the consequences of doing
+- * so, either purely performances, or possible misbehaviour... It's not
+- * clear wether the chip can handle unaligned accesses at all without
+- * prefetching enabled.
+- *
+- * For now, things appear to be behaving properly with that prefetching
+- * disabled and IDE, possibly because IDE isn't doing any unaligned
+- * access.
+- */
+-#define SPIDER_DISABLE_PREFETCH
++static struct iowa_bus iowa_busses[IOWA_MAX_BUS];
++static unsigned int iowa_bus_count;
+ 
+-#define MAX_SPIDERS	3
++static struct iowa_bus *iowa_pci_find(unsigned long vaddr, unsigned long paddr)
++{
++	int i, j;
++	struct resource *res;
++	unsigned long vstart, vend;
+ 
+-static struct spider_pci_bus {
+-	void __iomem	*regs;
+-	unsigned long	mmio_start;
+-	unsigned long	mmio_end;
+-	unsigned long	pio_vstart;
+-	unsigned long	pio_vend;
+-} spider_pci_busses[MAX_SPIDERS];
+-static int spider_pci_count;
++	for (i = 0; i < iowa_bus_count; i++) {
++		struct iowa_bus *bus = &iowa_busses[i];
++		struct pci_controller *phb = bus->phb;
+ 
+-static struct spider_pci_bus *spider_pci_find(unsigned long vaddr,
+-					      unsigned long paddr)
+-{
+-	int i;
+-
+-	for (i = 0; i < spider_pci_count; i++) {
+-		struct spider_pci_bus *bus = &spider_pci_busses[i];
+-		if (paddr && paddr >= bus->mmio_start && paddr < bus->mmio_end)
+-			return bus;
+-		if (vaddr && vaddr >= bus->pio_vstart && vaddr < bus->pio_vend)
+-			return bus;
++		if (vaddr) {
++			vstart = (unsigned long)phb->io_base_virt;
++			vend = vstart + phb->pci_io_size - 1;
++			if ((vaddr >= vstart) && (vaddr <= vend))
++				return bus;
++		}
++
++		if (paddr)
++			for (j = 0; j < 3; j++) {
++				res = &phb->mem_resources[j];
++				if (paddr >= res->start && paddr <= res->end)
++					return bus;
++			}
+ 	}
++
+ 	return NULL;
+ }
+ 
+-static void spider_io_flush(const volatile void __iomem *addr)
++struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR addr)
+ {
+-	struct spider_pci_bus *bus;
++	struct iowa_bus *bus;
+ 	int token;
+ 
+-	/* Get platform token (set by ioremap) from address */
+ 	token = PCI_GET_ADDR_TOKEN(addr);
+ 
+-	/* Fast path if we have a non-0 token, it indicates which bus we
+-	 * are on.
+-	 *
+-	 * If the token is 0, that means either that the ioremap was done
+-	 * before we initialized this layer, or it's a PIO operation. We
+-	 * fallback to a low path in this case. Hopefully, internal devices
+-	 * which are ioremap'ed early should use in_XX/out_XX functions
+-	 * instead of the PCI ones and thus not suffer from the slowdown.
+-	 *
+-	 * Also note that currently, the workaround will not work for areas
+-	 * that are not mapped with PTEs (bolted in the hash table). This
+-	 * is the case for ioremaps done very early at boot (before
+-	 * mem_init_done) and includes the mapping of the ISA IO space.
+-	 *
+-	 * Fortunately, none of the affected devices is expected to do DMA
+-	 * and thus there should be no problem in practice.
+-	 *
+-	 * In order to improve performances, we only do the PTE search for
+-	 * addresses falling in the PHB IO space area. That means it will
+-	 * not work for hotplug'ed PHBs but those don't exist with Spider.
+-	 */
+-	if (token && token <= spider_pci_count)
+-		bus = &spider_pci_busses[token - 1];
++	if (token && token <= iowa_bus_count)
++		bus = &iowa_busses[token - 1];
+ 	else {
+ 		unsigned long vaddr, paddr;
+ 		pte_t *ptep;
+ 
+-		/* Fixup physical address */
+ 		vaddr = (unsigned long)PCI_FIX_ADDR(addr);
++		if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
++			return NULL;
+ 
+-		/* Check if it's in allowed range for  PIO */
+-		if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
+-			return;
+-
+-		/* Try to find a PTE. If not, clear the paddr, we'll do
+-		 * a vaddr only lookup (PIO only)
+-		 */
+ 		ptep = find_linux_pte(init_mm.pgd, vaddr);
+ 		if (ptep == NULL)
+ 			paddr = 0;
+ 		else
+ 			paddr = pte_pfn(*ptep) << PAGE_SHIFT;
++		bus = iowa_pci_find(vaddr, paddr);
+ 
+-		bus = spider_pci_find(vaddr, paddr);
+ 		if (bus == NULL)
+-			return;
++			return NULL;
+ 	}
+ 
+-	/* Now do the workaround
+-	 */
+-	(void)in_be32(bus->regs + SPIDER_PCI_DUMMY_READ);
++	return bus;
+ }
+ 
+-static u8 spider_readb(const volatile void __iomem *addr)
++struct iowa_bus *iowa_pio_find_bus(unsigned long port)
+ {
+-	u8 val = __do_readb(addr);
+-	spider_io_flush(addr);
+-	return val;
++	unsigned long vaddr = (unsigned long)pci_io_base + port;
++	return iowa_pci_find(vaddr, 0);
+ }
+ 
+-static u16 spider_readw(const volatile void __iomem *addr)
+-{
+-	u16 val = __do_readw(addr);
+-	spider_io_flush(addr);
+-	return val;
+-}
+ 
+-static u32 spider_readl(const volatile void __iomem *addr)
+-{
+-	u32 val = __do_readl(addr);
+-	spider_io_flush(addr);
+-	return val;
++#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)		\
++static ret iowa_##name at					\
++{								\
++	struct iowa_bus *bus;					\
++	bus = iowa_##space##_find_bus(aa);			\
++	if (bus && bus->ops && bus->ops->name)			\
++		return bus->ops->name al;			\
++	return __do_##name al;					\
+ }
+ 
+-static u64 spider_readq(const volatile void __iomem *addr)
+-{
+-	u64 val = __do_readq(addr);
+-	spider_io_flush(addr);
+-	return val;
++#define DEF_PCI_AC_NORET(name, at, al, space, aa)		\
++static void iowa_##name at					\
++{								\
++	struct iowa_bus *bus;					\
++	bus = iowa_##space##_find_bus(aa);			\
++	if (bus && bus->ops && bus->ops->name) {		\
++		bus->ops->name al;				\
++		return;						\
++	}							\
++	__do_##name al;						\
+ }
+ 
+-static u16 spider_readw_be(const volatile void __iomem *addr)
+-{
+-	u16 val = __do_readw_be(addr);
+-	spider_io_flush(addr);
+-	return val;
+-}
++#include <asm/io-defs.h>
+ 
+-static u32 spider_readl_be(const volatile void __iomem *addr)
+-{
+-	u32 val = __do_readl_be(addr);
+-	spider_io_flush(addr);
+-	return val;
+-}
++#undef DEF_PCI_AC_RET
++#undef DEF_PCI_AC_NORET
+ 
+-static u64 spider_readq_be(const volatile void __iomem *addr)
+-{
+-	u64 val = __do_readq_be(addr);
+-	spider_io_flush(addr);
+-	return val;
+-}
++static struct ppc_pci_io __initdata iowa_pci_io = {
+ 
+-static void spider_readsb(const volatile void __iomem *addr, void *buf,
+-			  unsigned long count)
+-{
+-	__do_readsb(addr, buf, count);
+-	spider_io_flush(addr);
+-}
++#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)	.name = iowa_##name,
++#define DEF_PCI_AC_NORET(name, at, al, space, aa)	.name = iowa_##name,
+ 
+-static void spider_readsw(const volatile void __iomem *addr, void *buf,
+-			  unsigned long count)
+-{
+-	__do_readsw(addr, buf, count);
+-	spider_io_flush(addr);
+-}
++#include <asm/io-defs.h>
+ 
+-static void spider_readsl(const volatile void __iomem *addr, void *buf,
+-			  unsigned long count)
+-{
+-	__do_readsl(addr, buf, count);
+-	spider_io_flush(addr);
+-}
+-
+-static void spider_memcpy_fromio(void *dest, const volatile void __iomem *src,
+-				 unsigned long n)
+-{
+-	__do_memcpy_fromio(dest, src, n);
+-	spider_io_flush(src);
+-}
++#undef DEF_PCI_AC_RET
++#undef DEF_PCI_AC_NORET
+ 
++};
+ 
+-static void __iomem * spider_ioremap(unsigned long addr, unsigned long size,
+-				     unsigned long flags)
++static void __iomem *iowa_ioremap(unsigned long addr, unsigned long size,
++						unsigned long flags)
+ {
+-	struct spider_pci_bus *bus;
++	struct iowa_bus *bus;
+ 	void __iomem *res = __ioremap(addr, size, flags);
+ 	int busno;
+ 
+-	pr_debug("spider_ioremap(0x%lx, 0x%lx, 0x%lx) -> 0x%p\n",
+-		 addr, size, flags, res);
+-
+-	bus = spider_pci_find(0, addr);
++	bus = iowa_pci_find(0, addr);
+ 	if (bus != NULL) {
+-		busno = bus - spider_pci_busses;
+-		pr_debug(" found bus %d, setting token\n", busno);
++		busno = bus - iowa_busses;
+ 		PCI_SET_ADDR_TOKEN(res, busno + 1);
+ 	}
+-	pr_debug(" result=0x%p\n", res);
+-
+ 	return res;
+ }
+ 
+-static void __init spider_pci_setup_chip(struct spider_pci_bus *bus)
+-{
+-#ifdef SPIDER_DISABLE_PREFETCH
+-	u32 val = in_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT);
+-	pr_debug(" PVCI_Control_Status was 0x%08x\n", val);
+-	out_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8);
+-#endif
+-
+-	/* Configure the dummy address for the workaround */
+-	out_be32(bus->regs + SPIDER_PCI_DUMMY_READ_BASE, 0x80000000);
+-}
+-
+-static void __init spider_pci_add_one(struct pci_controller *phb)
++/* Regist new bus to support workaround */
++void __init iowa_register_bus(struct pci_controller *phb,
++			struct ppc_pci_io *ops,
++			int (*initfunc)(struct iowa_bus *, void *), void *data)
+ {
+-	struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count];
++	struct iowa_bus *bus;
+ 	struct device_node *np = phb->dn;
+-	struct resource rsrc;
+-	void __iomem *regs;
+ 
+-	if (spider_pci_count >= MAX_SPIDERS) {
+-		printk(KERN_ERR "Too many spider bridges, workarounds"
+-		       " disabled for %s\n", np->full_name);
++	if (iowa_bus_count >= IOWA_MAX_BUS) {
++		pr_err("IOWA:Too many pci bridges, "
++		       "workarounds disabled for %s\n", np->full_name);
+ 		return;
+ 	}
+ 
+-	/* Get the registers for the beast */
+-	if (of_address_to_resource(np, 0, &rsrc)) {
+-		printk(KERN_ERR "Failed to get registers for spider %s"
+-		       " workarounds disabled\n", np->full_name);
+-		return;
+-	}
++	bus = &iowa_busses[iowa_bus_count];
++	bus->phb = phb;
++	bus->ops = ops;
+ 
+-	/* Mask out some useless bits in there to get to the base of the
+-	 * spider chip
+-	 */
+-	rsrc.start &= ~0xfffffffful;
+-
+-	/* Map them */
+-	regs = ioremap(rsrc.start + SPIDER_PCI_REG_BASE, 0x1000);
+-	if (regs == NULL) {
+-		printk(KERN_ERR "Failed to map registers for spider %s"
+-		       " workarounds disabled\n", np->full_name);
+-		return;
+-	}
+-
+-	spider_pci_count++;
+-
+-	/* We assume spiders only have one MMIO resource */
+-	bus->mmio_start = phb->mem_resources[0].start;
+-	bus->mmio_end = phb->mem_resources[0].end + 1;
+-
+-	bus->pio_vstart = (unsigned long)phb->io_base_virt;
+-	bus->pio_vend = bus->pio_vstart + phb->pci_io_size;
+-
+-	bus->regs = regs;
+-
+-	printk(KERN_INFO "PCI: Spider MMIO workaround for %s\n",np->full_name);
++	if (initfunc)
++		if ((*initfunc)(bus, data))
++			return;
+ 
+-	pr_debug(" mmio (P) = 0x%016lx..0x%016lx\n",
+-		 bus->mmio_start, bus->mmio_end);
+-	pr_debug("  pio (V) = 0x%016lx..0x%016lx\n",
+-		 bus->pio_vstart, bus->pio_vend);
+-	pr_debug(" regs (P) = 0x%016lx (V) = 0x%p\n",
+-		 rsrc.start + SPIDER_PCI_REG_BASE, bus->regs);
++	iowa_bus_count++;
+ 
+-	spider_pci_setup_chip(bus);
++	pr_debug("IOWA:[%d]Add bus, %s.\n", iowa_bus_count-1, np->full_name);
+ }
+ 
+-static struct ppc_pci_io __initdata spider_pci_io = {
+-	.readb = spider_readb,
+-	.readw = spider_readw,
+-	.readl = spider_readl,
+-	.readq = spider_readq,
+-	.readw_be = spider_readw_be,
+-	.readl_be = spider_readl_be,
+-	.readq_be = spider_readq_be,
+-	.readsb = spider_readsb,
+-	.readsw = spider_readsw,
+-	.readsl = spider_readsl,
+-	.memcpy_fromio = spider_memcpy_fromio,
+-};
+-
+-static int __init spider_pci_workaround_init(void)
++/* enable IO workaround */
++void __init io_workaround_init(void)
+ {
+-	struct pci_controller *phb;
+-
+-	/* Find spider bridges. We assume they have been all probed
+-	 * in setup_arch(). If that was to change, we would need to
+-	 * update this code to cope with dynamically added busses
+-	 */
+-	list_for_each_entry(phb, &hose_list, list_node) {
+-		struct device_node *np = phb->dn;
+-		const char *model = of_get_property(np, "model", NULL);
+-
+-		/* If no model property or name isn't exactly "pci", skip */
+-		if (model == NULL || strcmp(np->name, "pci"))
+-			continue;
+-		/* If model is not "Spider", skip */
+-		if (strcmp(model, "Spider"))
+-			continue;
+-		spider_pci_add_one(phb);
+-	}
+-
+-	/* No Spider PCI found, exit */
+-	if (spider_pci_count == 0)
+-		return 0;
++	static int io_workaround_inited;
+ 
+-	/* Setup IO callbacks. We only setup MMIO reads. PIO reads will
+-	 * fallback to MMIO reads (though without a token, thus slower)
+-	 */
+-	ppc_pci_io = spider_pci_io;
+-
+-	/* Setup ioremap callback */
+-	ppc_md.ioremap = spider_ioremap;
+-
+-	return 0;
++	if (io_workaround_inited)
++		return;
++	ppc_pci_io = iowa_pci_io;
++	ppc_md.ioremap = iowa_ioremap;
++	io_workaround_inited = 1;
+ }
+-machine_arch_initcall(cell, spider_pci_workaround_init);
+diff --git a/arch/powerpc/platforms/cell/io-workarounds.h b/arch/powerpc/platforms/cell/io-workarounds.h
+new file mode 100644
+index 0000000..79d8ed3
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/io-workarounds.h
+@@ -0,0 +1,49 @@
++/*
++ * Support PCI IO workaround
++ *
++ * (C) Copyright 2007-2008 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef _IO_WORKAROUNDS_H
++#define _IO_WORKAROUNDS_H
++
++#include <linux/io.h>
++#include <asm/pci-bridge.h>
++
++/* Bus info */
++struct iowa_bus {
++	struct pci_controller *phb;
++	struct ppc_pci_io *ops;
++	void   *private;
++};
++
++void __init io_workaround_init(void);
++void __init iowa_register_bus(struct pci_controller *, struct ppc_pci_io *,
++			      int (*)(struct iowa_bus *, void *), void *);
++struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR);
++struct iowa_bus *iowa_pio_find_bus(unsigned long);
++
++extern struct ppc_pci_io spiderpci_ops;
++extern int spiderpci_iowa_init(struct iowa_bus *, void *);
++
++#define SPIDER_PCI_REG_BASE		0xd000
++#define SPIDER_PCI_REG_SIZE		0x1000
++#define SPIDER_PCI_VCI_CNTL_STAT	0x0110
++#define SPIDER_PCI_DUMMY_READ		0x0810
++#define SPIDER_PCI_DUMMY_READ_BASE	0x0814
++
++#endif /* _IO_WORKAROUNDS_H */
+diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
+index d75ccde..45646b2 100644
+--- a/arch/powerpc/platforms/cell/iommu.c
++++ b/arch/powerpc/platforms/cell/iommu.c
+@@ -28,13 +28,13 @@
+ #include <linux/notifier.h>
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/prom.h>
+ #include <asm/iommu.h>
+ #include <asm/machdep.h>
+ #include <asm/pci-bridge.h>
+ #include <asm/udbg.h>
+-#include <asm/lmb.h>
+ #include <asm/firmware.h>
+ #include <asm/cell-regs.h>
+ 
+@@ -316,7 +316,7 @@ static void cell_iommu_setup_stab(struct cbe_iommu *iommu,
+ 	segments = max(dbase + dsize, fbase + fsize) >> IO_SEGMENT_SHIFT;
+ 
+ 	pr_debug("%s: iommu[%d]: segments: %lu\n",
+-			__FUNCTION__, iommu->nid, segments);
++			__func__, iommu->nid, segments);
+ 
+ 	/* set up the segment table */
+ 	stab_size = segments * sizeof(unsigned long);
+@@ -343,7 +343,7 @@ static unsigned long *cell_iommu_alloc_ptab(struct cbe_iommu *iommu,
+ 				(1 << 12) / sizeof(unsigned long));
+ 
+ 	ptab_size = segments * pages_per_segment * sizeof(unsigned long);
+-	pr_debug("%s: iommu[%d]: ptab_size: %lu, order: %d\n", __FUNCTION__,
++	pr_debug("%s: iommu[%d]: ptab_size: %lu, order: %d\n", __func__,
+ 			iommu->nid, ptab_size, get_order(ptab_size));
+ 	page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(ptab_size));
+ 	BUG_ON(!page);
+@@ -355,7 +355,7 @@ static unsigned long *cell_iommu_alloc_ptab(struct cbe_iommu *iommu,
+ 	n_pte_pages = (pages_per_segment * sizeof(unsigned long)) >> 12;
+ 
+ 	pr_debug("%s: iommu[%d]: stab at %p, ptab at %p, n_pte_pages: %lu\n",
+-			__FUNCTION__, iommu->nid, iommu->stab, ptab,
++			__func__, iommu->nid, iommu->stab, ptab,
+ 			n_pte_pages);
+ 
+ 	/* initialise the STEs */
+@@ -394,7 +394,7 @@ static void cell_iommu_enable_hardware(struct cbe_iommu *iommu)
+ 
+ 	if (cell_iommu_find_ioc(iommu->nid, &xlate_base))
+ 		panic("%s: missing IOC register mappings for node %d\n",
+-		      __FUNCTION__, iommu->nid);
++		      __func__, iommu->nid);
+ 
+ 	iommu->xlate_regs = ioremap(xlate_base, IOC_Reg_Size);
+ 	iommu->cmd_regs = iommu->xlate_regs + IOC_IOCmd_Offset;
+diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
+index 0304589..8a3631c 100644
+--- a/arch/powerpc/platforms/cell/pervasive.c
++++ b/arch/powerpc/platforms/cell/pervasive.c
+@@ -65,7 +65,7 @@ static void cbe_power_save(void)
+ 		break;
+ 	default:
+ 		printk(KERN_WARNING "%s: unknown configuration\n",
+-			__FUNCTION__);
++			__func__);
+ 		break;
+ 	}
+ 	mtspr(SPRN_TSC_CELL, thread_switch_control);
+diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
+index e43024c..655704a 100644
+--- a/arch/powerpc/platforms/cell/ras.c
++++ b/arch/powerpc/platforms/cell/ras.c
+@@ -132,7 +132,7 @@ static int __init cbe_ptcal_enable_on_node(int nid, int order)
+ 				(unsigned int)(addr >> 32),
+ 				(unsigned int)(addr & 0xffffffff))) {
+ 		printk(KERN_ERR "%s: error enabling PTCAL on node %d!\n",
+-				__FUNCTION__, nid);
++				__func__, nid);
+ 		goto out_free_pages;
+ 	}
+ 
+@@ -162,7 +162,7 @@ static int __init cbe_ptcal_enable(void)
+ 	if (!size)
+ 		return -ENODEV;
+ 
+-	pr_debug("%s: enabling PTCAL, size = 0x%x\n", __FUNCTION__, *size);
++	pr_debug("%s: enabling PTCAL, size = 0x%x\n", __func__, *size);
+ 	order = get_order(*size);
+ 	of_node_put(np);
+ 
+@@ -180,7 +180,7 @@ static int __init cbe_ptcal_enable(void)
+ 		const u32 *nid = of_get_property(np, "node-id", NULL);
+ 		if (!nid) {
+ 			printk(KERN_ERR "%s: node %s is missing node-id?\n",
+-					__FUNCTION__, np->full_name);
++					__func__, np->full_name);
+ 			continue;
+ 		}
+ 		cbe_ptcal_enable_on_node(*nid, order);
+@@ -195,13 +195,13 @@ static int cbe_ptcal_disable(void)
+ 	struct ptcal_area *area, *tmp;
+ 	int ret = 0;
+ 
+-	pr_debug("%s: disabling PTCAL\n", __FUNCTION__);
++	pr_debug("%s: disabling PTCAL\n", __func__);
+ 
+ 	list_for_each_entry_safe(area, tmp, &ptcal_list, list) {
+ 		/* disable ptcal on this node */
+ 		if (rtas_call(ptcal_stop_tok, 1, 1, NULL, area->nid)) {
+ 			printk(KERN_ERR "%s: error disabling PTCAL "
+-					"on node %d!\n", __FUNCTION__,
++					"on node %d!\n", __func__,
+ 					area->nid);
+ 			ret = -EIO;
+ 			continue;
+diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
+index 5c531e8..ab721b5 100644
+--- a/arch/powerpc/platforms/cell/setup.c
++++ b/arch/powerpc/platforms/cell/setup.c
+@@ -57,6 +57,7 @@
+ #include "interrupt.h"
+ #include "pervasive.h"
+ #include "ras.h"
++#include "io-workarounds.h"
+ 
+ #ifdef DEBUG
+ #define DBG(fmt...) udbg_printf(fmt)
+@@ -117,13 +118,50 @@ static void cell_fixup_pcie_rootcomplex(struct pci_dev *dev)
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex);
+ 
++static int __devinit cell_setup_phb(struct pci_controller *phb)
++{
++	const char *model;
++	struct device_node *np;
++
++	int rc = rtas_setup_phb(phb);
++	if (rc)
++		return rc;
++
++	np = phb->dn;
++	model = of_get_property(np, "model", NULL);
++	if (model == NULL || strcmp(np->name, "pci"))
++		return 0;
++
++	/* Setup workarounds for spider */
++	if (strcmp(model, "Spider"))
++		return 0;
++
++	iowa_register_bus(phb, &spiderpci_ops, &spiderpci_iowa_init,
++				  (void *)SPIDER_PCI_REG_BASE);
++	io_workaround_init();
++
++	return 0;
++}
++
+ static int __init cell_publish_devices(void)
+ {
++	struct device_node *root = of_find_node_by_path("/");
++	struct device_node *np;
+ 	int node;
+ 
+ 	/* Publish OF platform devices for southbridge IOs */
+ 	of_platform_bus_probe(NULL, NULL, NULL);
+ 
++	/* On spider based blades, we need to manually create the OF
++	 * platform devices for the PCI host bridges
++	 */
++	for_each_child_of_node(root, np) {
++		if (np->type == NULL || (strcmp(np->type, "pci") != 0 &&
++					 strcmp(np->type, "pciex") != 0))
++			continue;
++		of_platform_device_create(np, NULL, NULL);
++	}
++
+ 	/* There is no device for the MIC memory controller, thus we create
+ 	 * a platform device for it to attach the EDAC driver to.
+ 	 */
+@@ -132,6 +170,7 @@ static int __init cell_publish_devices(void)
+ 			continue;
+ 		platform_device_register_simple("cbe-mic", node, NULL, 0);
+ 	}
++
+ 	return 0;
+ }
+ machine_subsys_initcall(cell, cell_publish_devices);
+@@ -213,7 +252,7 @@ static void __init cell_setup_arch(void)
+ 
+ 	/* Find and initialize PCI host bridges */
+ 	init_pci_config_tokens();
+-	find_and_init_phbs();
++
+ 	cbe_pervasive_init();
+ #ifdef CONFIG_DUMMY_CONSOLE
+ 	conswitchp = &dummy_con;
+@@ -249,7 +288,7 @@ define_machine(cell) {
+ 	.calibrate_decr		= generic_calibrate_decr,
+ 	.progress		= cell_progress,
+ 	.init_IRQ       	= cell_init_irq,
+-	.pci_setup_phb		= rtas_setup_phb,
++	.pci_setup_phb		= cell_setup_phb,
+ #ifdef CONFIG_KEXEC
+ 	.machine_kexec		= default_machine_kexec,
+ 	.machine_kexec_prepare	= default_machine_kexec_prepare,
+diff --git a/arch/powerpc/platforms/cell/spider-pci.c b/arch/powerpc/platforms/cell/spider-pci.c
+new file mode 100644
+index 0000000..418b605
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/spider-pci.c
+@@ -0,0 +1,184 @@
++/*
++ * IO workarounds for PCI on Celleb/Cell platform
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/of_platform.h>
++#include <linux/io.h>
++
++#include <asm/ppc-pci.h>
++#include <asm/pci-bridge.h>
++
++#include "io-workarounds.h"
++
++#define SPIDER_PCI_DISABLE_PREFETCH
++
++struct spiderpci_iowa_private {
++	void __iomem *regs;
++};
++
++static void spiderpci_io_flush(struct iowa_bus *bus)
++{
++	struct spiderpci_iowa_private *priv;
++	u32 val;
++
++	priv = bus->private;
++	val = in_be32(priv->regs + SPIDER_PCI_DUMMY_READ);
++	iosync();
++}
++
++#define SPIDER_PCI_MMIO_READ(name, ret)					\
++static ret spiderpci_##name(const PCI_IO_ADDR addr)			\
++{									\
++	ret val = __do_##name(addr);					\
++	spiderpci_io_flush(iowa_mem_find_bus(addr));			\
++	return val;							\
++}
++
++#define SPIDER_PCI_MMIO_READ_STR(name)					\
++static void spiderpci_##name(const PCI_IO_ADDR addr, void *buf, 	\
++			     unsigned long count)			\
++{									\
++	__do_##name(addr, buf, count);					\
++	spiderpci_io_flush(iowa_mem_find_bus(addr));			\
++}
++
++SPIDER_PCI_MMIO_READ(readb, u8)
++SPIDER_PCI_MMIO_READ(readw, u16)
++SPIDER_PCI_MMIO_READ(readl, u32)
++SPIDER_PCI_MMIO_READ(readq, u64)
++SPIDER_PCI_MMIO_READ(readw_be, u16)
++SPIDER_PCI_MMIO_READ(readl_be, u32)
++SPIDER_PCI_MMIO_READ(readq_be, u64)
++SPIDER_PCI_MMIO_READ_STR(readsb)
++SPIDER_PCI_MMIO_READ_STR(readsw)
++SPIDER_PCI_MMIO_READ_STR(readsl)
++
++static void spiderpci_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
++				    unsigned long n)
++{
++	__do_memcpy_fromio(dest, src, n);
++	spiderpci_io_flush(iowa_mem_find_bus(src));
++}
++
++static int __init spiderpci_pci_setup_chip(struct pci_controller *phb,
++					   void __iomem *regs)
++{
++	void *dummy_page_va;
++	dma_addr_t dummy_page_da;
++
++#ifdef SPIDER_PCI_DISABLE_PREFETCH
++	u32 val = in_be32(regs + SPIDER_PCI_VCI_CNTL_STAT);
++	pr_debug("SPIDER_IOWA:PVCI_Control_Status was 0x%08x\n", val);
++	out_be32(regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8);
++#endif /* SPIDER_PCI_DISABLE_PREFETCH */
++
++	/* setup dummy read */
++	/*
++	 * On CellBlade, we can't know that which XDR memory is used by
++	 * kmalloc() to allocate dummy_page_va.
++	 * In order to imporve the performance, the XDR which is used to
++	 * allocate dummy_page_va is the nearest the spider-pci.
++	 * We have to select the CBE which is the nearest the spider-pci
++	 * to allocate memory from the best XDR, but I don't know that
++	 * how to do.
++	 *
++	 * Celleb does not have this problem, because it has only one XDR.
++	 */
++	dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
++	if (!dummy_page_va) {
++		pr_err("SPIDERPCI-IOWA:Alloc dummy_page_va failed.\n");
++		return -1;
++	}
++
++	dummy_page_da = dma_map_single(phb->parent, dummy_page_va,
++				       PAGE_SIZE, DMA_FROM_DEVICE);
++	if (dma_mapping_error(dummy_page_da)) {
++		pr_err("SPIDER-IOWA:Map dummy page filed.\n");
++		kfree(dummy_page_va);
++		return -1;
++	}
++
++	out_be32(regs + SPIDER_PCI_DUMMY_READ_BASE, dummy_page_da);
++
++	return 0;
++}
++
++int __init spiderpci_iowa_init(struct iowa_bus *bus, void *data)
++{
++	void __iomem *regs = NULL;
++	struct spiderpci_iowa_private *priv;
++	struct device_node *np = bus->phb->dn;
++	struct resource r;
++	unsigned long offset = (unsigned long)data;
++
++	pr_debug("SPIDERPCI-IOWA:Bus initialize for spider(%s)\n",
++		 np->full_name);
++
++	priv = kzalloc(sizeof(struct spiderpci_iowa_private), GFP_KERNEL);
++	if (!priv) {
++		pr_err("SPIDERPCI-IOWA:"
++		       "Can't allocate struct spiderpci_iowa_private");
++		return -1;
++	}
++
++	if (of_address_to_resource(np, 0, &r)) {
++		pr_err("SPIDERPCI-IOWA:Can't get resource.\n");
++		goto error;
++	}
++
++	regs = ioremap(r.start + offset, SPIDER_PCI_REG_SIZE);
++	if (!regs) {
++		pr_err("SPIDERPCI-IOWA:ioremap failed.\n");
++		goto error;
++	}
++	priv->regs = regs;
++	bus->private = priv;
++
++	if (spiderpci_pci_setup_chip(bus->phb, regs))
++		goto error;
++
++	return 0;
++
++error:
++	kfree(priv);
++	bus->private = NULL;
++
++	if (regs)
++		iounmap(regs);
++
++	return -1;
++}
++
++struct ppc_pci_io spiderpci_ops = {
++	.readb = spiderpci_readb,
++	.readw = spiderpci_readw,
++	.readl = spiderpci_readl,
++	.readq = spiderpci_readq,
++	.readw_be = spiderpci_readw_be,
++	.readl_be = spiderpci_readl_be,
++	.readq_be = spiderpci_readq_be,
++	.readsb = spiderpci_readsb,
++	.readsw = spiderpci_readsw,
++	.readsl = spiderpci_readsl,
++	.memcpy_fromio = spiderpci_memcpy_fromio,
++};
++
+diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
+index 712001f..6bab44b 100644
+--- a/arch/powerpc/platforms/cell/spu_base.c
++++ b/arch/powerpc/platforms/cell/spu_base.c
+@@ -165,7 +165,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
+ 	struct spu_slb slb;
+ 	int psize;
+ 
+-	pr_debug("%s\n", __FUNCTION__);
++	pr_debug("%s\n", __func__);
+ 
+ 	slb.esid = (ea & ESID_MASK) | SLB_ESID_V;
+ 
+@@ -215,7 +215,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
+ extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX
+ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
+ {
+-	pr_debug("%s, %lx, %lx\n", __FUNCTION__, dsisr, ea);
++	pr_debug("%s, %lx, %lx\n", __func__, dsisr, ea);
+ 
+ 	/* Handle kernel space hash faults immediately.
+ 	   User hash faults need to be deferred to process context. */
+@@ -351,7 +351,7 @@ spu_irq_class_1(int irq, void *data)
+ 		__spu_trap_data_seg(spu, dar);
+ 
+ 	spin_unlock(&spu->register_lock);
+-	pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
++	pr_debug("%s: %lx %lx %lx %lx\n", __func__, mask, stat,
+ 			dar, dsisr);
+ 
+ 	if (stat & CLASS1_STORAGE_FAULT_INTR)
+@@ -726,7 +726,7 @@ static int __init init_spu_base(void)
+ 
+ 	if (ret < 0) {
+ 		printk(KERN_WARNING "%s: Error initializing spus\n",
+-			__FUNCTION__);
++			__func__);
+ 		goto out_unregister_sysdev_class;
+ 	}
+ 
+diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
+index dceb8b6..19f6bfd 100644
+--- a/arch/powerpc/platforms/cell/spu_callbacks.c
++++ b/arch/powerpc/platforms/cell/spu_callbacks.c
+@@ -54,7 +54,7 @@ long spu_sys_callback(struct spu_syscall_block *s)
+ 	long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
+ 
+ 	if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
+-		pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret);
++		pr_debug("%s: invalid syscall #%ld", __func__, s->nr_ret);
+ 		return -ENOSYS;
+ 	}
+ 
+diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
+index d351bde..4c506c1 100644
+--- a/arch/powerpc/platforms/cell/spu_manage.c
++++ b/arch/powerpc/platforms/cell/spu_manage.c
+@@ -92,7 +92,7 @@ static int __init spu_map_interrupts_old(struct spu *spu,
+ 
+ 	tmp = of_get_property(np->parent->parent, "node-id", NULL);
+ 	if (!tmp) {
+-		printk(KERN_WARNING "%s: can't find node-id\n", __FUNCTION__);
++		printk(KERN_WARNING "%s: can't find node-id\n", __func__);
+ 		nid = spu->node;
+ 	} else
+ 		nid = tmp[0];
+@@ -296,7 +296,7 @@ static int __init of_enumerate_spus(int (*fn)(void *data))
+ 		ret = fn(node);
+ 		if (ret) {
+ 			printk(KERN_WARNING "%s: Error initializing %s\n",
+-				__FUNCTION__, node->name);
++				__func__, node->name);
+ 			break;
+ 		}
+ 		n++;
+@@ -327,7 +327,7 @@ static int __init of_create_spu(struct spu *spu, void *data)
+ 		if (!legacy_map) {
+ 			legacy_map = 1;
+ 			printk(KERN_WARNING "%s: Legacy device tree found, "
+-				"trying to map old style\n", __FUNCTION__);
++				"trying to map old style\n", __func__);
+ 		}
+ 		ret = spu_map_device_old(spu);
+ 		if (ret) {
+@@ -342,7 +342,7 @@ static int __init of_create_spu(struct spu *spu, void *data)
+ 		if (!legacy_irq) {
+ 			legacy_irq = 1;
+ 			printk(KERN_WARNING "%s: Legacy device tree found, "
+-				"trying old style irq\n", __FUNCTION__);
++				"trying old style irq\n", __func__);
+ 		}
+ 		ret = spu_map_interrupts_old(spu, spe);
+ 		if (ret) {
+diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
+index 0c6a96b..b962c3a 100644
+--- a/arch/powerpc/platforms/cell/spufs/coredump.c
++++ b/arch/powerpc/platforms/cell/spufs/coredump.c
+@@ -133,8 +133,6 @@ static struct spu_context *coredump_next_context(int *fd)
+ 		if (ctx->flags & SPU_CREATE_NOSCHED)
+ 			continue;
+ 
+-		/* start searching the next fd next time we're called */
+-		(*fd)++;
+ 		break;
+ 	}
+ 
+@@ -157,6 +155,9 @@ int spufs_coredump_extra_notes_size(void)
+ 			break;
+ 
+ 		size += rc;
++
++		/* start searching the next fd next time */
++		fd++;
+ 	}
+ 
+ 	return size;
+@@ -239,6 +240,9 @@ int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
+ 		}
+ 
+ 		spu_release_saved(ctx);
++
++		/* start searching the next fd next time */
++		fd++;
+ 	}
+ 
+ 	return 0;
+diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
+index f7a7e86..08f44d1 100644
+--- a/arch/powerpc/platforms/cell/spufs/file.c
++++ b/arch/powerpc/platforms/cell/spufs/file.c
+@@ -32,7 +32,6 @@
+ #include <linux/marker.h>
+ 
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/spu.h>
+ #include <asm/spu_info.h>
+ #include <asm/uaccess.h>
+@@ -1337,7 +1336,7 @@ static u64 spufs_signal1_type_get(struct spu_context *ctx)
+ 	return ctx->ops->signal1_type_get(ctx);
+ }
+ DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
+-		       spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE);
++		       spufs_signal1_type_set, "%llu\n", SPU_ATTR_ACQUIRE);
+ 
+ 
+ static int spufs_signal2_type_set(void *data, u64 val)
+@@ -1359,7 +1358,7 @@ static u64 spufs_signal2_type_get(struct spu_context *ctx)
+ 	return ctx->ops->signal2_type_get(ctx);
+ }
+ DEFINE_SPUFS_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
+-		       spufs_signal2_type_set, "%llu", SPU_ATTR_ACQUIRE);
++		       spufs_signal2_type_set, "%llu\n", SPU_ATTR_ACQUIRE);
+ 
+ #if SPUFS_MMAP_4K
+ static unsigned long spufs_mss_mmap_nopfn(struct vm_area_struct *vma,
+@@ -1556,7 +1555,7 @@ void spufs_mfc_callback(struct spu *spu)
+ 
+ 	wake_up_all(&ctx->mfc_wq);
+ 
+-	pr_debug("%s %s\n", __FUNCTION__, spu->name);
++	pr_debug("%s %s\n", __func__, spu->name);
+ 	if (ctx->mfc_fasync) {
+ 		u32 free_elements, tagstatus;
+ 		unsigned int mask;
+@@ -1790,7 +1789,7 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
+ 	if (tagstatus & ctx->tagwait)
+ 		mask |= POLLIN | POLLRDNORM;
+ 
+-	pr_debug("%s: free %d tagstatus %d tagwait %d\n", __FUNCTION__,
++	pr_debug("%s: free %d tagstatus %d tagwait %d\n", __func__,
+ 		free_elements, tagstatus, ctx->tagwait);
+ 
+ 	return mask;
+diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
+index 6d1228c..0c32a05 100644
+--- a/arch/powerpc/platforms/cell/spufs/inode.c
++++ b/arch/powerpc/platforms/cell/spufs/inode.c
+@@ -35,7 +35,6 @@
+ #include <linux/parser.h>
+ 
+ #include <asm/prom.h>
+-#include <asm/semaphore.h>
+ #include <asm/spu.h>
+ #include <asm/spu_priv1.h>
+ #include <asm/uaccess.h>
+diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
+index cac69e1..96bf7c2 100644
+--- a/arch/powerpc/platforms/cell/spufs/run.c
++++ b/arch/powerpc/platforms/cell/spufs/run.c
+@@ -98,7 +98,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
+ 			!= MFC_CNTL_PURGE_DMA_COMPLETE) {
+ 		if (time_after(jiffies, timeout)) {
+ 			printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
+-					__FUNCTION__);
++					__func__);
+ 			ret = -EIO;
+ 			goto out;
+ 		}
+@@ -124,7 +124,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
+ 				status_loading) {
+ 		if (time_after(jiffies, timeout)) {
+ 			printk(KERN_ERR "%s: timeout waiting for loader\n",
+-					__FUNCTION__);
++					__func__);
+ 			ret = -EIO;
+ 			goto out_drop_priv;
+ 		}
+@@ -134,7 +134,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
+ 	if (!(status & SPU_STATUS_RUNNING)) {
+ 		/* If isolated LOAD has failed: run SPU, we will get a stop-and
+ 		 * signal later. */
+-		pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
++		pr_debug("%s: isolated LOAD failed\n", __func__);
+ 		ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+ 		ret = -EACCES;
+ 		goto out_drop_priv;
+@@ -142,7 +142,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
+ 
+ 	if (!(status & SPU_STATUS_ISOLATED_STATE)) {
+ 		/* This isn't allowed by the CBEA, but check anyway */
+-		pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
++		pr_debug("%s: SPU fell out of isolated mode?\n", __func__);
+ 		ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
+ 		ret = -EINVAL;
+ 		goto out_drop_priv;
+@@ -282,7 +282,7 @@ static int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret,
+ 		break;
+ 	default:
+ 		printk(KERN_WARNING "%s: unexpected return code %ld\n",
+-			__FUNCTION__, *spu_ret);
++			__func__, *spu_ret);
+ 		ret = 0;
+ 	}
+ 	return ret;
+@@ -323,6 +323,10 @@ static int spu_process_callback(struct spu_context *ctx)
+ 			return -EINTR;
+ 	}
+ 
++	/* need to re-get the ls, as it may have changed when we released the
++	 * spu */
++	ls = (void __iomem *)ctx->ops->get_ls(ctx);
++
+ 	/* write result, jump over indirect pointer */
+ 	memcpy_toio(ls + ls_pointer, &spu_ret, sizeof(spu_ret));
+ 	ctx->ops->npc_write(ctx, npc);
+diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
+index e9dc7a5..d2a1249 100644
+--- a/arch/powerpc/platforms/cell/spufs/switch.c
++++ b/arch/powerpc/platforms/cell/spufs/switch.c
+@@ -1815,6 +1815,7 @@ static void save_csa(struct spu_state *prev, struct spu *spu)
+ 	save_mfc_csr_ato(prev, spu);	/* Step 24. */
+ 	save_mfc_tclass_id(prev, spu);	/* Step 25. */
+ 	set_mfc_tclass_id(prev, spu);	/* Step 26. */
++	save_mfc_cmd(prev, spu);	/* Step 26a - moved from 44. */
+ 	purge_mfc_queue(prev, spu);	/* Step 27. */
+ 	wait_purge_complete(prev, spu);	/* Step 28. */
+ 	setup_mfc_sr1(prev, spu);	/* Step 30. */
+@@ -1831,7 +1832,6 @@ static void save_csa(struct spu_state *prev, struct spu *spu)
+ 	save_ppuint_mb(prev, spu);	/* Step 41. */
+ 	save_ch_part1(prev, spu);	/* Step 42. */
+ 	save_spu_mb(prev, spu);	        /* Step 43. */
+-	save_mfc_cmd(prev, spu);	/* Step 44. */
+ 	reset_ch(prev, spu);	        /* Step 45. */
+ }
+ 
+diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig
+deleted file mode 100644
+index 372891e..0000000
+--- a/arch/powerpc/platforms/celleb/Kconfig
++++ /dev/null
+@@ -1,12 +0,0 @@
+-config PPC_CELLEB
+-	bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
+-	depends on PPC_MULTIPLATFORM && PPC64
+-	select PPC_CELL
+-	select PPC_CELL_NATIVE
+-	select PPC_RTAS
+-	select PPC_INDIRECT_IO
+-	select PPC_OF_PLATFORM_PCI
+-	select HAS_TXX9_SERIAL
+-	select PPC_UDBG_BEAT
+-	select USB_OHCI_BIG_ENDIAN_MMIO
+-	select USB_EHCI_BIG_ENDIAN_MMIO
+diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile
+deleted file mode 100644
+index 889d43f..0000000
+--- a/arch/powerpc/platforms/celleb/Makefile
++++ /dev/null
+@@ -1,9 +0,0 @@
+-obj-y				+= interrupt.o iommu.o setup.o \
+-				   htab.o beat.o hvCall.o pci.o \
+-				   scc_epci.o scc_uhc.o \
+-				   io-workarounds.o
+-
+-obj-$(CONFIG_SMP)		+= smp.o
+-obj-$(CONFIG_PPC_UDBG_BEAT)	+= udbg_beat.o
+-obj-$(CONFIG_SERIAL_TXX9)	+= scc_sio.o
+-obj-$(CONFIG_SPU_BASE)		+= spu_priv1.o
+diff --git a/arch/powerpc/platforms/celleb/beat.c b/arch/powerpc/platforms/celleb/beat.c
+deleted file mode 100644
+index 93ebb7d..0000000
+--- a/arch/powerpc/platforms/celleb/beat.c
++++ /dev/null
+@@ -1,267 +0,0 @@
+-/*
+- * Simple routines for Celleb/Beat
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/err.h>
+-#include <linux/rtc.h>
+-#include <linux/interrupt.h>
+-#include <linux/irqreturn.h>
+-#include <linux/reboot.h>
+-
+-#include <asm/hvconsole.h>
+-#include <asm/time.h>
+-#include <asm/machdep.h>
+-#include <asm/firmware.h>
+-
+-#include "beat_wrapper.h"
+-#include "beat.h"
+-#include "interrupt.h"
+-
+-static int beat_pm_poweroff_flag;
+-
+-void beat_restart(char *cmd)
+-{
+-	beat_shutdown_logical_partition(!beat_pm_poweroff_flag);
+-}
+-
+-void beat_power_off(void)
+-{
+-	beat_shutdown_logical_partition(0);
+-}
+-
+-u64 beat_halt_code = 0x1000000000000000UL;
+-
+-void beat_halt(void)
+-{
+-	beat_shutdown_logical_partition(beat_halt_code);
+-}
+-
+-int beat_set_rtc_time(struct rtc_time *rtc_time)
+-{
+-	u64 tim;
+-	tim = mktime(rtc_time->tm_year+1900,
+-		     rtc_time->tm_mon+1, rtc_time->tm_mday,
+-		     rtc_time->tm_hour, rtc_time->tm_min, rtc_time->tm_sec);
+-	if (beat_rtc_write(tim))
+-		return -1;
+-	return 0;
+-}
+-
+-void beat_get_rtc_time(struct rtc_time *rtc_time)
+-{
+-	u64 tim;
+-
+-	if (beat_rtc_read(&tim))
+-		tim = 0;
+-	to_tm(tim, rtc_time);
+-	rtc_time->tm_year -= 1900;
+-	rtc_time->tm_mon -= 1;
+-}
+-
+-#define	BEAT_NVRAM_SIZE	4096
+-
+-ssize_t beat_nvram_read(char *buf, size_t count, loff_t *index)
+-{
+-	unsigned int i;
+-	unsigned long len;
+-	char *p = buf;
+-
+-	if (*index >= BEAT_NVRAM_SIZE)
+-		return -ENODEV;
+-	i = *index;
+-	if (i + count > BEAT_NVRAM_SIZE)
+-		count = BEAT_NVRAM_SIZE - i;
+-
+-	for (; count != 0; count -= len) {
+-		len = count;
+-		if (len > BEAT_NVRW_CNT)
+-			len = BEAT_NVRW_CNT;
+-		if (beat_eeprom_read(i, len, p)) {
+-			return -EIO;
+-		}
+-
+-		p += len;
+-		i += len;
+-	}
+-	*index = i;
+-	return p - buf;
+-}
+-
+-ssize_t beat_nvram_write(char *buf, size_t count, loff_t *index)
+-{
+-	unsigned int i;
+-	unsigned long len;
+-	char *p = buf;
+-
+-	if (*index >= BEAT_NVRAM_SIZE)
+-		return -ENODEV;
+-	i = *index;
+-	if (i + count > BEAT_NVRAM_SIZE)
+-		count = BEAT_NVRAM_SIZE - i;
+-
+-	for (; count != 0; count -= len) {
+-		len = count;
+-		if (len > BEAT_NVRW_CNT)
+-			len = BEAT_NVRW_CNT;
+-		if (beat_eeprom_write(i, len, p)) {
+-			return -EIO;
+-		}
+-
+-		p += len;
+-		i += len;
+-	}
+-	*index = i;
+-	return p - buf;
+-}
+-
+-ssize_t beat_nvram_get_size(void)
+-{
+-	return BEAT_NVRAM_SIZE;
+-}
+-
+-int beat_set_xdabr(unsigned long dabr)
+-{
+-	if (beat_set_dabr(dabr, DABRX_KERNEL | DABRX_USER))
+-		return -1;
+-	return 0;
+-}
+-
+-int64_t beat_get_term_char(u64 vterm, u64 *len, u64 *t1, u64 *t2)
+-{
+-	u64 db[2];
+-	s64 ret;
+-
+-	ret = beat_get_characters_from_console(vterm, len, (u8*)db);
+-	if (ret == 0) {
+-		*t1 = db[0];
+-		*t2 = db[1];
+-	}
+-	return ret;
+-}
+-
+-int64_t beat_put_term_char(u64 vterm, u64 len, u64 t1, u64 t2)
+-{
+-	u64 db[2];
+-
+-	db[0] = t1;
+-	db[1] = t2;
+-	return beat_put_characters_to_console(vterm, len, (u8*)db);
+-}
+-
+-void beat_power_save(void)
+-{
+-	beat_pause(0);
+-}
+-
+-#ifdef CONFIG_KEXEC
+-void beat_kexec_cpu_down(int crash, int secondary)
+-{
+-	beatic_deinit_IRQ();
+-}
+-#endif
+-
+-static irqreturn_t beat_power_event(int virq, void *arg)
+-{
+-	printk(KERN_DEBUG "Beat: power button pressed\n");
+-	beat_pm_poweroff_flag = 1;
+-	ctrl_alt_del();
+-	return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t beat_reset_event(int virq, void *arg)
+-{
+-	printk(KERN_DEBUG "Beat: reset button pressed\n");
+-	beat_pm_poweroff_flag = 0;
+-	ctrl_alt_del();
+-	return IRQ_HANDLED;
+-}
+-
+-static struct beat_event_list {
+-	const char *typecode;
+-	irq_handler_t handler;
+-	unsigned int virq;
+-} beat_event_list[] = {
+-	{ "power", beat_power_event, 0 },
+-	{ "reset", beat_reset_event, 0 },
+-};
+-
+-static int __init beat_register_event(void)
+-{
+-	u64 path[4], data[2];
+-	int rc, i;
+-	unsigned int virq;
+-
+-	for (i = 0; i < ARRAY_SIZE(beat_event_list); i++) {
+-		struct beat_event_list *ev = &beat_event_list[i];
+-
+-		if (beat_construct_event_receive_port(data) != 0) {
+-			printk(KERN_ERR "Beat: "
+-			       "cannot construct event receive port for %s\n",
+-			       ev->typecode);
+-			return -EINVAL;
+-		}
+-
+-		virq = irq_create_mapping(NULL, data[0]);
+-		if (virq == NO_IRQ) {
+-			printk(KERN_ERR "Beat: failed to get virtual IRQ"
+-			       " for event receive port for %s\n",
+-			       ev->typecode);
+-			beat_destruct_event_receive_port(data[0]);
+-			return -EIO;
+-		}
+-		ev->virq = virq;
+-
+-		rc = request_irq(virq, ev->handler, IRQF_DISABLED,
+-				      ev->typecode, NULL);
+-		if (rc != 0) {
+-			printk(KERN_ERR "Beat: failed to request virtual IRQ"
+-			       " for event receive port for %s\n",
+-			       ev->typecode);
+-			beat_destruct_event_receive_port(data[0]);
+-			return rc;
+-		}
+-
+-		path[0] = 0x1000000065780000ul;	/* 1,ex */
+-		path[1] = 0x627574746f6e0000ul;	/* button */
+-		path[2] = 0;
+-		strncpy((char *)&path[2], ev->typecode, 8);
+-		path[3] = 0;
+-		data[1] = 0;
+-
+-		beat_create_repository_node(path, data);
+-	}
+-	return 0;
+-}
+-
+-static int __init beat_event_init(void)
+-{
+-	if (!firmware_has_feature(FW_FEATURE_BEAT))
+-		return -EINVAL;
+-
+-	beat_pm_poweroff_flag = 0;
+-	return beat_register_event();
+-}
+-
+-device_initcall(beat_event_init);
+-
+-EXPORT_SYMBOL(beat_get_term_char);
+-EXPORT_SYMBOL(beat_put_term_char);
+-EXPORT_SYMBOL(beat_halt_code);
+diff --git a/arch/powerpc/platforms/celleb/beat.h b/arch/powerpc/platforms/celleb/beat.h
+deleted file mode 100644
+index ac82ac3..0000000
+--- a/arch/powerpc/platforms/celleb/beat.h
++++ /dev/null
+@@ -1,39 +0,0 @@
+-/*
+- * Guest OS Interfaces.
+- *
+- * (C) Copyright 2006 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef _CELLEB_BEAT_H
+-#define _CELLEB_BEAT_H
+-
+-int64_t beat_get_term_char(uint64_t,uint64_t*,uint64_t*,uint64_t*);
+-int64_t beat_put_term_char(uint64_t,uint64_t,uint64_t,uint64_t);
+-int64_t beat_repository_encode(int, const char *, uint64_t[4]);
+-void beat_restart(char *);
+-void beat_power_off(void);
+-void beat_halt(void);
+-int beat_set_rtc_time(struct rtc_time *);
+-void beat_get_rtc_time(struct rtc_time *);
+-ssize_t beat_nvram_get_size(void);
+-ssize_t beat_nvram_read(char *, size_t, loff_t *);
+-ssize_t beat_nvram_write(char *, size_t, loff_t *);
+-int beat_set_xdabr(unsigned long);
+-void beat_power_save(void);
+-void beat_kexec_cpu_down(int, int);
+-
+-#endif /* _CELLEB_BEAT_H */
+diff --git a/arch/powerpc/platforms/celleb/beat_syscall.h b/arch/powerpc/platforms/celleb/beat_syscall.h
+deleted file mode 100644
+index 8580dc7..0000000
+--- a/arch/powerpc/platforms/celleb/beat_syscall.h
++++ /dev/null
+@@ -1,164 +0,0 @@
+-/*
+- * Beat hypervisor call numbers
+- *
+- * (C) Copyright 2004-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef BEAT_BEAT_syscall_H
+-#define BEAT_BEAT_syscall_H
+-
+-#ifdef	__ASSEMBLY__
+-#define	__BEAT_ADD_VENDOR_ID(__x, __v)	((__v)<<60|(__x))
+-#else
+-#define	__BEAT_ADD_VENDOR_ID(__x, __v)	((u64)(__v)<<60|(__x))
+-#endif
+-#define HV_allocate_memory __BEAT_ADD_VENDOR_ID(0, 0)
+-#define HV_construct_virtual_address_space __BEAT_ADD_VENDOR_ID(2, 0)
+-#define HV_destruct_virtual_address_space __BEAT_ADD_VENDOR_ID(10, 0)
+-#define HV_get_virtual_address_space_id_of_ppe __BEAT_ADD_VENDOR_ID(4, 0)
+-#define HV_query_logical_partition_address_region_info 			\
+-						__BEAT_ADD_VENDOR_ID(6, 0)
+-#define HV_release_memory __BEAT_ADD_VENDOR_ID(13, 0)
+-#define HV_select_virtual_address_space __BEAT_ADD_VENDOR_ID(7, 0)
+-#define HV_load_range_registers __BEAT_ADD_VENDOR_ID(68, 0)
+-#define HV_set_ppe_l2cache_rmt_entry __BEAT_ADD_VENDOR_ID(70, 0)
+-#define HV_set_ppe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(71, 0)
+-#define HV_set_spe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(72, 0)
+-#define HV_get_io_address_translation_fault_info __BEAT_ADD_VENDOR_ID(14, 0)
+-#define HV_get_iopte __BEAT_ADD_VENDOR_ID(16, 0)
+-#define HV_preload_iopt_cache __BEAT_ADD_VENDOR_ID(17, 0)
+-#define HV_put_iopte __BEAT_ADD_VENDOR_ID(15, 0)
+-#define HV_connect_event_ports __BEAT_ADD_VENDOR_ID(21, 0)
+-#define HV_construct_event_receive_port __BEAT_ADD_VENDOR_ID(18, 0)
+-#define HV_destruct_event_receive_port __BEAT_ADD_VENDOR_ID(19, 0)
+-#define HV_destruct_event_send_port __BEAT_ADD_VENDOR_ID(22, 0)
+-#define HV_get_state_of_event_send_port __BEAT_ADD_VENDOR_ID(25, 0)
+-#define HV_request_to_connect_event_ports __BEAT_ADD_VENDOR_ID(20, 0)
+-#define HV_send_event_externally __BEAT_ADD_VENDOR_ID(23, 0)
+-#define HV_send_event_locally __BEAT_ADD_VENDOR_ID(24, 0)
+-#define HV_construct_and_connect_irq_plug __BEAT_ADD_VENDOR_ID(28, 0)
+-#define HV_destruct_irq_plug __BEAT_ADD_VENDOR_ID(29, 0)
+-#define HV_detect_pending_interrupts __BEAT_ADD_VENDOR_ID(26, 0)
+-#define HV_end_of_interrupt __BEAT_ADD_VENDOR_ID(27, 0)
+-#define HV_assign_control_signal_notification_port __BEAT_ADD_VENDOR_ID(45, 0)
+-#define HV_end_of_control_signal_processing __BEAT_ADD_VENDOR_ID(48, 0)
+-#define HV_get_control_signal __BEAT_ADD_VENDOR_ID(46, 0)
+-#define HV_set_irq_mask_for_spe __BEAT_ADD_VENDOR_ID(61, 0)
+-#define HV_shutdown_logical_partition __BEAT_ADD_VENDOR_ID(44, 0)
+-#define HV_connect_message_ports __BEAT_ADD_VENDOR_ID(35, 0)
+-#define HV_destruct_message_port __BEAT_ADD_VENDOR_ID(36, 0)
+-#define HV_receive_message __BEAT_ADD_VENDOR_ID(37, 0)
+-#define HV_get_message_port_info __BEAT_ADD_VENDOR_ID(34, 0)
+-#define HV_request_to_connect_message_ports __BEAT_ADD_VENDOR_ID(33, 0)
+-#define HV_send_message __BEAT_ADD_VENDOR_ID(32, 0)
+-#define HV_get_logical_ppe_id __BEAT_ADD_VENDOR_ID(69, 0)
+-#define HV_pause __BEAT_ADD_VENDOR_ID(9, 0)
+-#define HV_destruct_shared_memory_handle __BEAT_ADD_VENDOR_ID(51, 0)
+-#define HV_get_shared_memory_info __BEAT_ADD_VENDOR_ID(52, 0)
+-#define HV_permit_sharing_memory __BEAT_ADD_VENDOR_ID(50, 0)
+-#define HV_request_to_attach_shared_memory __BEAT_ADD_VENDOR_ID(49, 0)
+-#define HV_enable_logical_spe_execution __BEAT_ADD_VENDOR_ID(55, 0)
+-#define HV_construct_logical_spe __BEAT_ADD_VENDOR_ID(53, 0)
+-#define HV_disable_logical_spe_execution __BEAT_ADD_VENDOR_ID(56, 0)
+-#define HV_destruct_logical_spe __BEAT_ADD_VENDOR_ID(54, 0)
+-#define HV_sense_spe_execution_status __BEAT_ADD_VENDOR_ID(58, 0)
+-#define HV_insert_htab_entry __BEAT_ADD_VENDOR_ID(101, 0)
+-#define HV_read_htab_entries __BEAT_ADD_VENDOR_ID(95, 0)
+-#define HV_write_htab_entry __BEAT_ADD_VENDOR_ID(94, 0)
+-#define HV_assign_io_address_translation_fault_port 			\
+-						__BEAT_ADD_VENDOR_ID(100, 0)
+-#define HV_set_interrupt_mask __BEAT_ADD_VENDOR_ID(73, 0)
+-#define HV_get_logical_partition_id __BEAT_ADD_VENDOR_ID(74, 0)
+-#define HV_create_repository_node2 __BEAT_ADD_VENDOR_ID(90, 0)
+-#define HV_create_repository_node __BEAT_ADD_VENDOR_ID(90, 0) /* alias */
+-#define HV_get_repository_node_value2 __BEAT_ADD_VENDOR_ID(91, 0)
+-#define HV_get_repository_node_value __BEAT_ADD_VENDOR_ID(91, 0) /* alias */
+-#define HV_modify_repository_node_value2 __BEAT_ADD_VENDOR_ID(92, 0)
+-#define HV_modify_repository_node_value __BEAT_ADD_VENDOR_ID(92, 0) /* alias */
+-#define HV_remove_repository_node2 __BEAT_ADD_VENDOR_ID(93, 0)
+-#define HV_remove_repository_node __BEAT_ADD_VENDOR_ID(93, 0) /* alias */
+-#define HV_cancel_shared_memory __BEAT_ADD_VENDOR_ID(104, 0)
+-#define HV_clear_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(206, 0)
+-#define HV_construct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(80, 0)
+-#define HV_destruct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(81, 0)
+-#define HV_disconnect_ipspc_service __BEAT_ADD_VENDOR_ID(88, 0)
+-#define HV_execute_ipspc_command __BEAT_ADD_VENDOR_ID(86, 0)
+-#define HV_get_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(205, 0)
+-#define HV_get_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(208, 0)
+-#define HV_permit_use_of_ipspc_service __BEAT_ADD_VENDOR_ID(85, 0)
+-#define HV_reinitialize_logical_spe __BEAT_ADD_VENDOR_ID(82, 0)
+-#define HV_request_ipspc_service __BEAT_ADD_VENDOR_ID(84, 0)
+-#define HV_stop_ipspc_command __BEAT_ADD_VENDOR_ID(87, 0)
+-#define HV_set_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(204, 0)
+-#define HV_get_status_of_ipspc_service __BEAT_ADD_VENDOR_ID(203, 0)
+-#define HV_put_characters_to_console __BEAT_ADD_VENDOR_ID(0x101, 1)
+-#define HV_get_characters_from_console __BEAT_ADD_VENDOR_ID(0x102, 1)
+-#define HV_get_base_clock __BEAT_ADD_VENDOR_ID(0x111, 1)
+-#define HV_set_base_clock __BEAT_ADD_VENDOR_ID(0x112, 1)
+-#define HV_get_frame_cycle __BEAT_ADD_VENDOR_ID(0x114, 1)
+-#define HV_disable_console __BEAT_ADD_VENDOR_ID(0x115, 1)
+-#define HV_disable_all_console __BEAT_ADD_VENDOR_ID(0x116, 1)
+-#define HV_oneshot_timer __BEAT_ADD_VENDOR_ID(0x117, 1)
+-#define HV_set_dabr __BEAT_ADD_VENDOR_ID(0x118, 1)
+-#define HV_get_dabr __BEAT_ADD_VENDOR_ID(0x119, 1)
+-#define HV_start_hv_stats __BEAT_ADD_VENDOR_ID(0x21c, 1)
+-#define HV_stop_hv_stats __BEAT_ADD_VENDOR_ID(0x21d, 1)
+-#define HV_get_hv_stats __BEAT_ADD_VENDOR_ID(0x21e, 1)
+-#define HV_get_hv_error_stats __BEAT_ADD_VENDOR_ID(0x221, 1)
+-#define HV_get_stats __BEAT_ADD_VENDOR_ID(0x224, 1)
+-#define HV_get_heap_stats __BEAT_ADD_VENDOR_ID(0x225, 1)
+-#define HV_get_memory_stats __BEAT_ADD_VENDOR_ID(0x227, 1)
+-#define HV_get_memory_detail __BEAT_ADD_VENDOR_ID(0x228, 1)
+-#define HV_set_priority_of_irq_outlet __BEAT_ADD_VENDOR_ID(0x122, 1)
+-#define HV_get_physical_spe_by_reservation_id __BEAT_ADD_VENDOR_ID(0x128, 1)
+-#define HV_get_spe_context __BEAT_ADD_VENDOR_ID(0x129, 1)
+-#define HV_set_spe_context __BEAT_ADD_VENDOR_ID(0x12a, 1)
+-#define HV_downcount_of_interrupt __BEAT_ADD_VENDOR_ID(0x12e, 1)
+-#define HV_peek_spe_context __BEAT_ADD_VENDOR_ID(0x12f, 1)
+-#define HV_read_bpa_register __BEAT_ADD_VENDOR_ID(0x131, 1)
+-#define HV_write_bpa_register __BEAT_ADD_VENDOR_ID(0x132, 1)
+-#define HV_map_context_table_of_spe __BEAT_ADD_VENDOR_ID(0x137, 1)
+-#define HV_get_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x138, 1)
+-#define HV_set_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x139, 1)
+-#define HV_init_pm __BEAT_ADD_VENDOR_ID(0x150, 1)
+-#define HV_set_pm_signal __BEAT_ADD_VENDOR_ID(0x151, 1)
+-#define HV_get_pm_signal __BEAT_ADD_VENDOR_ID(0x152, 1)
+-#define HV_set_pm_config __BEAT_ADD_VENDOR_ID(0x153, 1)
+-#define HV_get_pm_config __BEAT_ADD_VENDOR_ID(0x154, 1)
+-#define HV_get_inner_trace_data __BEAT_ADD_VENDOR_ID(0x155, 1)
+-#define HV_set_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x156, 1)
+-#define HV_get_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x157, 1)
+-#define HV_set_pm_interrupt __BEAT_ADD_VENDOR_ID(0x158, 1)
+-#define HV_get_pm_interrupt __BEAT_ADD_VENDOR_ID(0x159, 1)
+-#define HV_kick_pm __BEAT_ADD_VENDOR_ID(0x160, 1)
+-#define HV_construct_pm_context __BEAT_ADD_VENDOR_ID(0x164, 1)
+-#define HV_destruct_pm_context __BEAT_ADD_VENDOR_ID(0x165, 1)
+-#define HV_be_slow __BEAT_ADD_VENDOR_ID(0x170, 1)
+-#define HV_assign_ipspc_server_connection_status_notification_port 	\
+-						__BEAT_ADD_VENDOR_ID(0x173, 1)
+-#define HV_get_raid_of_physical_spe __BEAT_ADD_VENDOR_ID(0x174, 1)
+-#define HV_set_physical_spe_to_rag __BEAT_ADD_VENDOR_ID(0x175, 1)
+-#define HV_release_physical_spe_from_rag __BEAT_ADD_VENDOR_ID(0x176, 1)
+-#define HV_rtc_read __BEAT_ADD_VENDOR_ID(0x190, 1)
+-#define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1)
+-#define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1)
+-#define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1)
+-#define HV_insert_htab_entry3 __BEAT_ADD_VENDOR_ID(0x104, 1)
+-#define HV_invalidate_htab_entry3 __BEAT_ADD_VENDOR_ID(0x105, 1)
+-#define HV_update_htab_permission3 __BEAT_ADD_VENDOR_ID(0x106, 1)
+-#define HV_clear_htab3 __BEAT_ADD_VENDOR_ID(0x107, 1)
+-#endif
+diff --git a/arch/powerpc/platforms/celleb/beat_wrapper.h b/arch/powerpc/platforms/celleb/beat_wrapper.h
+deleted file mode 100644
+index cbc1487..0000000
+--- a/arch/powerpc/platforms/celleb/beat_wrapper.h
++++ /dev/null
+@@ -1,288 +0,0 @@
+-/*
+- * Beat hypervisor call I/F
+- *
+- * (C) Copyright 2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/pseries/plpar_wrapper.h.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU 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 BEAT_HCALL
+-#include "beat_syscall.h"
+-
+-/* defined in hvCall.S */
+-extern s64 beat_hcall_norets(u64 opcode, ...);
+-extern s64 beat_hcall_norets8(u64 opcode, u64 arg1, u64 arg2, u64 arg3,
+-	u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8);
+-extern s64 beat_hcall1(u64 opcode, u64 retbuf[1], ...);
+-extern s64 beat_hcall2(u64 opcode, u64 retbuf[2], ...);
+-extern s64 beat_hcall3(u64 opcode, u64 retbuf[3], ...);
+-extern s64 beat_hcall4(u64 opcode, u64 retbuf[4], ...);
+-extern s64 beat_hcall5(u64 opcode, u64 retbuf[5], ...);
+-extern s64 beat_hcall6(u64 opcode, u64 retbuf[6], ...);
+-
+-static inline s64 beat_downcount_of_interrupt(u64 plug_id)
+-{
+-	return beat_hcall_norets(HV_downcount_of_interrupt, plug_id);
+-}
+-
+-static inline s64 beat_set_interrupt_mask(u64 index,
+-	u64 val0, u64 val1, u64 val2, u64 val3)
+-{
+-	return beat_hcall_norets(HV_set_interrupt_mask, index,
+-	       val0, val1, val2, val3);
+-}
+-
+-static inline s64 beat_destruct_irq_plug(u64 plug_id)
+-{
+-	return beat_hcall_norets(HV_destruct_irq_plug, plug_id);
+-}
+-
+-static inline s64 beat_construct_and_connect_irq_plug(u64 plug_id,
+-	u64 outlet_id)
+-{
+-	return beat_hcall_norets(HV_construct_and_connect_irq_plug, plug_id,
+-	       outlet_id);
+-}
+-
+-static inline s64 beat_detect_pending_interrupts(u64 index, u64 *retbuf)
+-{
+-	return beat_hcall4(HV_detect_pending_interrupts, retbuf, index);
+-}
+-
+-static inline s64 beat_pause(u64 style)
+-{
+-	return beat_hcall_norets(HV_pause, style);
+-}
+-
+-static inline s64 beat_read_htab_entries(u64 htab_id, u64 index, u64 *retbuf)
+-{
+-	return beat_hcall5(HV_read_htab_entries, retbuf, htab_id, index);
+-}
+-
+-static inline s64 beat_insert_htab_entry(u64 htab_id, u64 group,
+-	u64 bitmask, u64 hpte_v, u64 hpte_r, u64 *slot)
+-{
+-	u64 dummy[3];
+-	s64 ret;
+-
+-	ret = beat_hcall3(HV_insert_htab_entry, dummy, htab_id, group,
+-		bitmask, hpte_v, hpte_r);
+-	*slot = dummy[0];
+-	return ret;
+-}
+-
+-static inline s64 beat_write_htab_entry(u64 htab_id, u64 slot,
+-	u64 hpte_v, u64 hpte_r, u64 mask_v, u64 mask_r,
+-	u64 *ret_v, u64 *ret_r)
+-{
+-	u64 dummy[2];
+-	s64 ret;
+-
+-	ret = beat_hcall2(HV_write_htab_entry, dummy, htab_id, slot,
+-		hpte_v, hpte_r, mask_v, mask_r);
+-	*ret_v = dummy[0];
+-	*ret_r = dummy[1];
+-	return ret;
+-}
+-
+-static inline s64 beat_insert_htab_entry3(u64 htab_id, u64 group,
+-	u64 hpte_v, u64 hpte_r, u64 mask_v, u64 value_v, u64 *slot)
+-{
+-	u64 dummy[1];
+-	s64 ret;
+-
+-	ret = beat_hcall1(HV_insert_htab_entry3, dummy, htab_id, group,
+-		hpte_v, hpte_r, mask_v, value_v);
+-	*slot = dummy[0];
+-	return ret;
+-}
+-
+-static inline s64 beat_invalidate_htab_entry3(u64 htab_id, u64 group,
+-	u64 va, u64 pss)
+-{
+-	return beat_hcall_norets(HV_invalidate_htab_entry3,
+-		htab_id, group, va, pss);
+-}
+-
+-static inline s64 beat_update_htab_permission3(u64 htab_id, u64 group,
+-	u64 va, u64 pss, u64 ptel_mask, u64 ptel_value)
+-{
+-	return beat_hcall_norets(HV_update_htab_permission3,
+-		htab_id, group, va, pss, ptel_mask, ptel_value);
+-}
+-
+-static inline s64 beat_clear_htab3(u64 htab_id)
+-{
+-	return beat_hcall_norets(HV_clear_htab3, htab_id);
+-}
+-
+-static inline void beat_shutdown_logical_partition(u64 code)
+-{
+-	(void)beat_hcall_norets(HV_shutdown_logical_partition, code);
+-}
+-
+-static inline s64 beat_rtc_write(u64 time_from_epoch)
+-{
+-	return beat_hcall_norets(HV_rtc_write, time_from_epoch);
+-}
+-
+-static inline s64 beat_rtc_read(u64 *time_from_epoch)
+-{
+-	u64 dummy[1];
+-	s64 ret;
+-
+-	ret = beat_hcall1(HV_rtc_read, dummy);
+-	*time_from_epoch = dummy[0];
+-	return ret;
+-}
+-
+-#define	BEAT_NVRW_CNT	(sizeof(u64) * 6)
+-
+-static inline s64 beat_eeprom_write(u64 index, u64 length, u8 *buffer)
+-{
+-	u64	b[6];
+-
+-	if (length > BEAT_NVRW_CNT)
+-		return -1;
+-	memcpy(b, buffer, sizeof(b));
+-	return beat_hcall_norets8(HV_eeprom_write, index, length,
+-		b[0], b[1], b[2], b[3], b[4], b[5]);
+-}
+-
+-static inline s64 beat_eeprom_read(u64 index, u64 length, u8 *buffer)
+-{
+-	u64	b[6];
+-	s64	ret;
+-
+-	if (length > BEAT_NVRW_CNT)
+-		return -1;
+-	ret = beat_hcall6(HV_eeprom_read, b, index, length);
+-	memcpy(buffer, b, length);
+-	return ret;
+-}
+-
+-static inline s64 beat_set_dabr(u64 value, u64 style)
+-{
+-	return beat_hcall_norets(HV_set_dabr, value, style);
+-}
+-
+-static inline s64 beat_get_characters_from_console(u64 termno, u64 *len,
+-	u8 *buffer)
+-{
+-	u64 dummy[3];
+-	s64 ret;
+-
+-	ret = beat_hcall3(HV_get_characters_from_console, dummy, termno, len);
+-	*len = dummy[0];
+-	memcpy(buffer, dummy + 1, *len);
+-	return ret;
+-}
+-
+-static inline s64 beat_put_characters_to_console(u64 termno, u64 len,
+-	u8 *buffer)
+-{
+-	u64 b[2];
+-
+-	memcpy(b, buffer, len);
+-	return beat_hcall_norets(HV_put_characters_to_console, termno, len,					 b[0], b[1]);
+-}
+-
+-static inline s64 beat_get_spe_privileged_state_1_registers(
+-		u64 id, u64 offsetof, u64 *value)
+-{
+-	u64 dummy[1];
+-	s64 ret;
+-
+-	ret = beat_hcall1(HV_get_spe_privileged_state_1_registers, dummy, id,
+-		offsetof);
+-	*value = dummy[0];
+-	return ret;
+-}
+-
+-static inline s64 beat_set_irq_mask_for_spe(u64 id, u64 class, u64 mask)
+-{
+-	return beat_hcall_norets(HV_set_irq_mask_for_spe, id, class, mask);
+-}
+-
+-static inline s64 beat_clear_interrupt_status_of_spe(u64 id, u64 class,
+-	u64 mask)
+-{
+-	return beat_hcall_norets(HV_clear_interrupt_status_of_spe,
+-		id, class, mask);
+-}
+-
+-static inline s64 beat_set_spe_privileged_state_1_registers(
+-		u64 id, u64 offsetof, u64 value)
+-{
+-	return beat_hcall_norets(HV_set_spe_privileged_state_1_registers,
+-		id, offsetof, value);
+-}
+-
+-static inline s64 beat_get_interrupt_status_of_spe(u64 id, u64 class, u64 *val)
+-{
+-	u64 dummy[1];
+-	s64 ret;
+-
+-	ret = beat_hcall1(HV_get_interrupt_status_of_spe, dummy, id, class);
+-	*val = dummy[0];
+-	return ret;
+-}
+-
+-static inline s64 beat_put_iopte(u64 ioas_id, u64 io_addr, u64 real_addr,
+-	u64 ioid, u64 flags)
+-{
+-	return beat_hcall_norets(HV_put_iopte, ioas_id, io_addr, real_addr,
+-		ioid, flags);
+-}
+-
+-static inline s64 beat_construct_event_receive_port(u64 *port)
+-{
+-	u64 dummy[1];
+-	s64 ret;
+-
+-	ret = beat_hcall1(HV_construct_event_receive_port, dummy);
+-	*port = dummy[0];
+-	return ret;
+-}
+-
+-static inline s64 beat_destruct_event_receive_port(u64 port)
+-{
+-	s64 ret;
+-
+-	ret = beat_hcall_norets(HV_destruct_event_receive_port, port);
+-	return ret;
+-}
+-
+-static inline s64 beat_create_repository_node(u64 path[4], u64 data[2])
+-{
+-	s64 ret;
+-
+-	ret = beat_hcall_norets(HV_create_repository_node2,
+-		path[0], path[1], path[2], path[3], data[0], data[1]);
+-	return ret;
+-}
+-
+-static inline s64 beat_get_repository_node_value(u64 lpid, u64 path[4],
+-	u64 data[2])
+-{
+-	s64 ret;
+-
+-	ret = beat_hcall2(HV_get_repository_node_value2, data,
+-		lpid, path[0], path[1], path[2], path[3]);
+-	return ret;
+-}
+-
+-#endif
+diff --git a/arch/powerpc/platforms/celleb/htab.c b/arch/powerpc/platforms/celleb/htab.c
+deleted file mode 100644
+index fbf27c7..0000000
+--- a/arch/powerpc/platforms/celleb/htab.c
++++ /dev/null
+@@ -1,440 +0,0 @@
+-/*
+- * "Cell Reference Set" HTAB support.
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/pseries/lpar.c:
+- *  Copyright (C) 2001 Todd Inglett, IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU 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.
+- */
+-
+-#undef DEBUG_LOW
+-
+-#include <linux/kernel.h>
+-#include <linux/spinlock.h>
+-
+-#include <asm/mmu.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/machdep.h>
+-#include <asm/udbg.h>
+-
+-#include "beat_wrapper.h"
+-
+-#ifdef DEBUG_LOW
+-#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0)
+-#else
+-#define DBG_LOW(fmt...) do { } while(0)
+-#endif
+-
+-static DEFINE_SPINLOCK(beat_htab_lock);
+-
+-static inline unsigned int beat_read_mask(unsigned hpte_group)
+-{
+-	unsigned long hpte_v[5];
+-	unsigned long rmask = 0;
+-
+-	beat_read_htab_entries(0, hpte_group + 0, hpte_v);
+-	if (!(hpte_v[0] & HPTE_V_BOLTED))
+-		rmask |= 0x8000;
+-	if (!(hpte_v[1] & HPTE_V_BOLTED))
+-		rmask |= 0x4000;
+-	if (!(hpte_v[2] & HPTE_V_BOLTED))
+-		rmask |= 0x2000;
+-	if (!(hpte_v[3] & HPTE_V_BOLTED))
+-		rmask |= 0x1000;
+-	beat_read_htab_entries(0, hpte_group + 4, hpte_v);
+-	if (!(hpte_v[0] & HPTE_V_BOLTED))
+-		rmask |= 0x0800;
+-	if (!(hpte_v[1] & HPTE_V_BOLTED))
+-		rmask |= 0x0400;
+-	if (!(hpte_v[2] & HPTE_V_BOLTED))
+-		rmask |= 0x0200;
+-	if (!(hpte_v[3] & HPTE_V_BOLTED))
+-		rmask |= 0x0100;
+-	hpte_group = ~hpte_group & (htab_hash_mask * HPTES_PER_GROUP);
+-	beat_read_htab_entries(0, hpte_group + 0, hpte_v);
+-	if (!(hpte_v[0] & HPTE_V_BOLTED))
+-		rmask |= 0x80;
+-	if (!(hpte_v[1] & HPTE_V_BOLTED))
+-		rmask |= 0x40;
+-	if (!(hpte_v[2] & HPTE_V_BOLTED))
+-		rmask |= 0x20;
+-	if (!(hpte_v[3] & HPTE_V_BOLTED))
+-		rmask |= 0x10;
+-	beat_read_htab_entries(0, hpte_group + 4, hpte_v);
+-	if (!(hpte_v[0] & HPTE_V_BOLTED))
+-		rmask |= 0x08;
+-	if (!(hpte_v[1] & HPTE_V_BOLTED))
+-		rmask |= 0x04;
+-	if (!(hpte_v[2] & HPTE_V_BOLTED))
+-		rmask |= 0x02;
+-	if (!(hpte_v[3] & HPTE_V_BOLTED))
+-		rmask |= 0x01;
+-	return rmask;
+-}
+-
+-static long beat_lpar_hpte_insert(unsigned long hpte_group,
+-				  unsigned long va, unsigned long pa,
+-				  unsigned long rflags, unsigned long vflags,
+-				  int psize, int ssize)
+-{
+-	unsigned long lpar_rc;
+-	unsigned long slot;
+-	unsigned long hpte_v, hpte_r;
+-
+-	/* same as iseries */
+-	if (vflags & HPTE_V_SECONDARY)
+-		return -1;
+-
+-	if (!(vflags & HPTE_V_BOLTED))
+-		DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+-			"rflags=%lx, vflags=%lx, psize=%d)\n",
+-		hpte_group, va, pa, rflags, vflags, psize);
+-
+-	hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+-		vflags | HPTE_V_VALID;
+-	hpte_r = hpte_encode_r(pa, psize) | rflags;
+-
+-	if (!(vflags & HPTE_V_BOLTED))
+-		DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+-
+-	if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
+-		hpte_r &= ~_PAGE_COHERENT;
+-
+-	spin_lock(&beat_htab_lock);
+-	if ((lpar_rc = beat_read_mask(hpte_group)) == 0) {
+-		if (!(vflags & HPTE_V_BOLTED))
+-			DBG_LOW(" full\n");
+-		spin_unlock(&beat_htab_lock);
+-		return -1;
+-	}
+-
+-	lpar_rc = beat_insert_htab_entry(0, hpte_group, lpar_rc << 48,
+-		hpte_v, hpte_r, &slot);
+-	spin_unlock(&beat_htab_lock);
+-
+-	/*
+-	 * Since we try and ioremap PHBs we don't own, the pte insert
+-	 * will fail. However we must catch the failure in hash_page
+-	 * or we will loop forever, so return -2 in this case.
+-	 */
+-	if (unlikely(lpar_rc != 0)) {
+-		if (!(vflags & HPTE_V_BOLTED))
+-			DBG_LOW(" lpar err %lx\n", lpar_rc);
+-		return -2;
+-	}
+-	if (!(vflags & HPTE_V_BOLTED))
+-		DBG_LOW(" -> slot: %lx\n", slot);
+-
+-	/* We have to pass down the secondary bucket bit here as well */
+-	return (slot ^ hpte_group) & 15;
+-}
+-
+-static long beat_lpar_hpte_remove(unsigned long hpte_group)
+-{
+-	DBG_LOW("hpte_remove(group=%lx)\n", hpte_group);
+-	return -1;
+-}
+-
+-static unsigned long beat_lpar_hpte_getword0(unsigned long slot)
+-{
+-	unsigned long dword0, dword[5];
+-	unsigned long lpar_rc;
+-
+-	lpar_rc = beat_read_htab_entries(0, slot & ~3UL, dword);
+-
+-	dword0 = dword[slot&3];
+-
+-	BUG_ON(lpar_rc != 0);
+-
+-	return dword0;
+-}
+-
+-static void beat_lpar_hptab_clear(void)
+-{
+-	unsigned long size_bytes = 1UL << ppc64_pft_size;
+-	unsigned long hpte_count = size_bytes >> 4;
+-	int i;
+-	unsigned long dummy0, dummy1;
+-
+-	/* TODO: Use bulk call */
+-	for (i = 0; i < hpte_count; i++)
+-		beat_write_htab_entry(0, i, 0, 0, -1UL, -1UL, &dummy0, &dummy1);
+-}
+-
+-/*
+- * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
+- * the low 3 bits of flags happen to line up.  So no transform is needed.
+- * We can probably optimize here and assume the high bits of newpp are
+- * already zero.  For now I am paranoid.
+- */
+-static long beat_lpar_hpte_updatepp(unsigned long slot,
+-				    unsigned long newpp,
+-				    unsigned long va,
+-				    int psize, int ssize, int local)
+-{
+-	unsigned long lpar_rc;
+-	unsigned long dummy0, dummy1, want_v;
+-
+-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+-
+-	DBG_LOW("    update: "
+-		"avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
+-		want_v & HPTE_V_AVPN, slot, psize, newpp);
+-
+-	spin_lock(&beat_htab_lock);
+-	dummy0 = beat_lpar_hpte_getword0(slot);
+-	if ((dummy0 & ~0x7FUL) != (want_v & ~0x7FUL)) {
+-		DBG_LOW("not found !\n");
+-		spin_unlock(&beat_htab_lock);
+-		return -1;
+-	}
+-
+-	lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7, &dummy0,
+-					&dummy1);
+-	spin_unlock(&beat_htab_lock);
+-	if (lpar_rc != 0 || dummy0 == 0) {
+-		DBG_LOW("not found !\n");
+-		return -1;
+-	}
+-
+-	DBG_LOW("ok %lx %lx\n", dummy0, dummy1);
+-
+-	BUG_ON(lpar_rc != 0);
+-
+-	return 0;
+-}
+-
+-static long beat_lpar_hpte_find(unsigned long va, int psize)
+-{
+-	unsigned long hash;
+-	unsigned long i, j;
+-	long slot;
+-	unsigned long want_v, hpte_v;
+-
+-	hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
+-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+-
+-	for (j = 0; j < 2; j++) {
+-		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+-		for (i = 0; i < HPTES_PER_GROUP; i++) {
+-			hpte_v = beat_lpar_hpte_getword0(slot);
+-
+-			if (HPTE_V_COMPARE(hpte_v, want_v)
+-			    && (hpte_v & HPTE_V_VALID)
+-			    && (!!(hpte_v & HPTE_V_SECONDARY) == j)) {
+-				/* HPTE matches */
+-				if (j)
+-					slot = -slot;
+-				return slot;
+-			}
+-			++slot;
+-		}
+-		hash = ~hash;
+-	}
+-
+-	return -1;
+-}
+-
+-static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
+-					  unsigned long ea,
+-					  int psize, int ssize)
+-{
+-	unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1;
+-
+-	vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
+-	va = (vsid << 28) | (ea & 0x0fffffff);
+-
+-	spin_lock(&beat_htab_lock);
+-	slot = beat_lpar_hpte_find(va, psize);
+-	BUG_ON(slot == -1);
+-
+-	lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
+-		&dummy0, &dummy1);
+-	spin_unlock(&beat_htab_lock);
+-
+-	BUG_ON(lpar_rc != 0);
+-}
+-
+-static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+-					 int psize, int ssize, int local)
+-{
+-	unsigned long want_v;
+-	unsigned long lpar_rc;
+-	unsigned long dummy1, dummy2;
+-	unsigned long flags;
+-
+-	DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
+-		slot, va, psize, local);
+-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+-
+-	spin_lock_irqsave(&beat_htab_lock, flags);
+-	dummy1 = beat_lpar_hpte_getword0(slot);
+-
+-	if ((dummy1 & ~0x7FUL) != (want_v & ~0x7FUL)) {
+-		DBG_LOW("not found !\n");
+-		spin_unlock_irqrestore(&beat_htab_lock, flags);
+-		return;
+-	}
+-
+-	lpar_rc = beat_write_htab_entry(0, slot, 0, 0, HPTE_V_VALID, 0,
+-		&dummy1, &dummy2);
+-	spin_unlock_irqrestore(&beat_htab_lock, flags);
+-
+-	BUG_ON(lpar_rc != 0);
+-}
+-
+-void __init hpte_init_beat(void)
+-{
+-	ppc_md.hpte_invalidate	= beat_lpar_hpte_invalidate;
+-	ppc_md.hpte_updatepp	= beat_lpar_hpte_updatepp;
+-	ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
+-	ppc_md.hpte_insert	= beat_lpar_hpte_insert;
+-	ppc_md.hpte_remove	= beat_lpar_hpte_remove;
+-	ppc_md.hpte_clear_all	= beat_lpar_hptab_clear;
+-}
+-
+-static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
+-				  unsigned long va, unsigned long pa,
+-				  unsigned long rflags, unsigned long vflags,
+-				  int psize, int ssize)
+-{
+-	unsigned long lpar_rc;
+-	unsigned long slot;
+-	unsigned long hpte_v, hpte_r;
+-
+-	/* same as iseries */
+-	if (vflags & HPTE_V_SECONDARY)
+-		return -1;
+-
+-	if (!(vflags & HPTE_V_BOLTED))
+-		DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+-			"rflags=%lx, vflags=%lx, psize=%d)\n",
+-		hpte_group, va, pa, rflags, vflags, psize);
+-
+-	hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+-		vflags | HPTE_V_VALID;
+-	hpte_r = hpte_encode_r(pa, psize) | rflags;
+-
+-	if (!(vflags & HPTE_V_BOLTED))
+-		DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+-
+-	if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
+-		hpte_r &= ~_PAGE_COHERENT;
+-
+-	/* insert into not-volted entry */
+-	lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r,
+-		HPTE_V_BOLTED, 0, &slot);
+-	/*
+-	 * Since we try and ioremap PHBs we don't own, the pte insert
+-	 * will fail. However we must catch the failure in hash_page
+-	 * or we will loop forever, so return -2 in this case.
+-	 */
+-	if (unlikely(lpar_rc != 0)) {
+-		if (!(vflags & HPTE_V_BOLTED))
+-			DBG_LOW(" lpar err %lx\n", lpar_rc);
+-		return -2;
+-	}
+-	if (!(vflags & HPTE_V_BOLTED))
+-		DBG_LOW(" -> slot: %lx\n", slot);
+-
+-	/* We have to pass down the secondary bucket bit here as well */
+-	return (slot ^ hpte_group) & 15;
+-}
+-
+-/*
+- * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
+- * the low 3 bits of flags happen to line up.  So no transform is needed.
+- * We can probably optimize here and assume the high bits of newpp are
+- * already zero.  For now I am paranoid.
+- */
+-static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
+-				    unsigned long newpp,
+-				    unsigned long va,
+-				    int psize, int ssize, int local)
+-{
+-	unsigned long lpar_rc;
+-	unsigned long want_v;
+-	unsigned long pss;
+-
+-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+-	pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
+-
+-	DBG_LOW("    update: "
+-		"avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
+-		want_v & HPTE_V_AVPN, slot, psize, newpp);
+-
+-	lpar_rc = beat_update_htab_permission3(0, slot, want_v, pss, 7, newpp);
+-
+-	if (lpar_rc == 0xfffffff7) {
+-		DBG_LOW("not found !\n");
+-		return -1;
+-	}
+-
+-	DBG_LOW("ok\n");
+-
+-	BUG_ON(lpar_rc != 0);
+-
+-	return 0;
+-}
+-
+-static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
+-					 int psize, int ssize, int local)
+-{
+-	unsigned long want_v;
+-	unsigned long lpar_rc;
+-	unsigned long pss;
+-
+-	DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
+-		slot, va, psize, local);
+-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+-	pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
+-
+-	lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
+-
+-	/* E_busy can be valid output: page may be already replaced */
+-	BUG_ON(lpar_rc != 0 && lpar_rc != 0xfffffff7);
+-}
+-
+-static int64_t _beat_lpar_hptab_clear_v3(void)
+-{
+-	return beat_clear_htab3(0);
+-}
+-
+-static void beat_lpar_hptab_clear_v3(void)
+-{
+-	_beat_lpar_hptab_clear_v3();
+-}
+-
+-void __init hpte_init_beat_v3(void)
+-{
+-	if (_beat_lpar_hptab_clear_v3() == 0) {
+-		ppc_md.hpte_invalidate	= beat_lpar_hpte_invalidate_v3;
+-		ppc_md.hpte_updatepp	= beat_lpar_hpte_updatepp_v3;
+-		ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
+-		ppc_md.hpte_insert	= beat_lpar_hpte_insert_v3;
+-		ppc_md.hpte_remove	= beat_lpar_hpte_remove;
+-		ppc_md.hpte_clear_all	= beat_lpar_hptab_clear_v3;
+-	} else {
+-		ppc_md.hpte_invalidate	= beat_lpar_hpte_invalidate;
+-		ppc_md.hpte_updatepp	= beat_lpar_hpte_updatepp;
+-		ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
+-		ppc_md.hpte_insert	= beat_lpar_hpte_insert;
+-		ppc_md.hpte_remove	= beat_lpar_hpte_remove;
+-		ppc_md.hpte_clear_all	= beat_lpar_hptab_clear;
+-	}
+-}
+diff --git a/arch/powerpc/platforms/celleb/hvCall.S b/arch/powerpc/platforms/celleb/hvCall.S
+deleted file mode 100644
+index 74c8174..0000000
+--- a/arch/powerpc/platforms/celleb/hvCall.S
++++ /dev/null
+@@ -1,287 +0,0 @@
+-/*
+- * Beat hypervisor call I/F
+- *
+- * (C) Copyright 2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/pseries/hvCall.S.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU 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 <asm/ppc_asm.h>
+-
+-#define	STK_PARM(i)	(48 + ((i)-3)*8)
+-
+-/* Not implemented on Beat, now */
+-#define	HCALL_INST_PRECALL
+-#define	HCALL_INST_POSTCALL
+-
+-	.text
+-
+-#define	HVSC	.long	0x44000022
+-
+-/* Note: takes only 7 input parameters at maximum */
+-_GLOBAL(beat_hcall_norets)
+-	HMT_MEDIUM
+-
+-	mfcr	r0
+-	stw	r0,8(r1)
+-
+-	HCALL_INST_PRECALL
+-
+-	mr	r11,r3
+-	mr	r3,r4
+-	mr	r4,r5
+-	mr	r5,r6
+-	mr	r6,r7
+-	mr	r7,r8
+-	mr	r8,r9
+-
+-	HVSC				/* invoke the hypervisor */
+-
+-	HCALL_INST_POSTCALL
+-
+-	lwz	r0,8(r1)
+-	mtcrf	0xff,r0
+-
+-	blr				/* return r3 = status */
+-
+-/* Note: takes 8 input parameters at maximum */
+-_GLOBAL(beat_hcall_norets8)
+-	HMT_MEDIUM
+-
+-	mfcr	r0
+-	stw	r0,8(r1)
+-
+-	HCALL_INST_PRECALL
+-
+-	mr	r11,r3
+-	mr	r3,r4
+-	mr	r4,r5
+-	mr	r5,r6
+-	mr	r6,r7
+-	mr	r7,r8
+-	mr	r8,r9
+-	ld	r10,STK_PARM(r10)(r1)
+-
+-	HVSC				/* invoke the hypervisor */
+-
+-	HCALL_INST_POSTCALL
+-
+-	lwz	r0,8(r1)
+-	mtcrf	0xff,r0
+-
+-	blr				/* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 1 output parameters at maximum */
+-_GLOBAL(beat_hcall1)
+-	HMT_MEDIUM
+-
+-	mfcr	r0
+-	stw	r0,8(r1)
+-
+-	HCALL_INST_PRECALL
+-
+-	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
+-
+-	mr	r11,r3
+-	mr	r3,r5
+-	mr	r4,r6
+-	mr	r5,r7
+-	mr	r6,r8
+-	mr	r7,r9
+-	mr	r8,r10
+-
+-	HVSC				/* invoke the hypervisor */
+-
+-	HCALL_INST_POSTCALL
+-
+-	ld	r12,STK_PARM(r4)(r1)
+-	std	r4,  0(r12)
+-
+-	lwz	r0,8(r1)
+-	mtcrf	0xff,r0
+-
+-	blr				/* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 2 output parameters at maximum */
+-_GLOBAL(beat_hcall2)
+-	HMT_MEDIUM
+-
+-	mfcr	r0
+-	stw	r0,8(r1)
+-
+-	HCALL_INST_PRECALL
+-
+-	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
+-
+-	mr	r11,r3
+-	mr	r3,r5
+-	mr	r4,r6
+-	mr	r5,r7
+-	mr	r6,r8
+-	mr	r7,r9
+-	mr	r8,r10
+-
+-	HVSC				/* invoke the hypervisor */
+-
+-	HCALL_INST_POSTCALL
+-
+-	ld	r12,STK_PARM(r4)(r1)
+-	std	r4,  0(r12)
+-	std	r5,  8(r12)
+-
+-	lwz	r0,8(r1)
+-	mtcrf	0xff,r0
+-
+-	blr				/* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 3 output parameters at maximum */
+-_GLOBAL(beat_hcall3)
+-	HMT_MEDIUM
+-
+-	mfcr	r0
+-	stw	r0,8(r1)
+-
+-	HCALL_INST_PRECALL
+-
+-	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
+-
+-	mr	r11,r3
+-	mr	r3,r5
+-	mr	r4,r6
+-	mr	r5,r7
+-	mr	r6,r8
+-	mr	r7,r9
+-	mr	r8,r10
+-
+-	HVSC				/* invoke the hypervisor */
+-
+-	HCALL_INST_POSTCALL
+-
+-	ld	r12,STK_PARM(r4)(r1)
+-	std	r4,  0(r12)
+-	std	r5,  8(r12)
+-	std	r6, 16(r12)
+-
+-	lwz	r0,8(r1)
+-	mtcrf	0xff,r0
+-
+-	blr				/* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 4 output parameters at maximum */
+-_GLOBAL(beat_hcall4)
+-	HMT_MEDIUM
+-
+-	mfcr	r0
+-	stw	r0,8(r1)
+-
+-	HCALL_INST_PRECALL
+-
+-	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
+-
+-	mr	r11,r3
+-	mr	r3,r5
+-	mr	r4,r6
+-	mr	r5,r7
+-	mr	r6,r8
+-	mr	r7,r9
+-	mr	r8,r10
+-
+-	HVSC				/* invoke the hypervisor */
+-
+-	HCALL_INST_POSTCALL
+-
+-	ld	r12,STK_PARM(r4)(r1)
+-	std	r4,  0(r12)
+-	std	r5,  8(r12)
+-	std	r6, 16(r12)
+-	std	r7, 24(r12)
+-
+-	lwz	r0,8(r1)
+-	mtcrf	0xff,r0
+-
+-	blr				/* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 5 output parameters at maximum */
+-_GLOBAL(beat_hcall5)
+-	HMT_MEDIUM
+-
+-	mfcr	r0
+-	stw	r0,8(r1)
+-
+-	HCALL_INST_PRECALL
+-
+-	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
+-
+-	mr	r11,r3
+-	mr	r3,r5
+-	mr	r4,r6
+-	mr	r5,r7
+-	mr	r6,r8
+-	mr	r7,r9
+-	mr	r8,r10
+-
+-	HVSC				/* invoke the hypervisor */
+-
+-	HCALL_INST_POSTCALL
+-
+-	ld	r12,STK_PARM(r4)(r1)
+-	std	r4,  0(r12)
+-	std	r5,  8(r12)
+-	std	r6, 16(r12)
+-	std	r7, 24(r12)
+-	std	r8, 32(r12)
+-
+-	lwz	r0,8(r1)
+-	mtcrf	0xff,r0
+-
+-	blr				/* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 6 output parameters at maximum */
+-_GLOBAL(beat_hcall6)
+-	HMT_MEDIUM
+-
+-	mfcr	r0
+-	stw	r0,8(r1)
+-
+-	HCALL_INST_PRECALL
+-
+-	std	r4,STK_PARM(r4)(r1)	/* save ret buffer */
+-
+-	mr	r11,r3
+-	mr	r3,r5
+-	mr	r4,r6
+-	mr	r5,r7
+-	mr	r6,r8
+-	mr	r7,r9
+-	mr	r8,r10
+-
+-	HVSC				/* invoke the hypervisor */
+-
+-	HCALL_INST_POSTCALL
+-
+-	ld	r12,STK_PARM(r4)(r1)
+-	std	r4,  0(r12)
+-	std	r5,  8(r12)
+-	std	r6, 16(r12)
+-	std	r7, 24(r12)
+-	std	r8, 32(r12)
+-	std	r9, 40(r12)
+-
+-	lwz	r0,8(r1)
+-	mtcrf	0xff,r0
+-
+-	blr				/* return r3 = status */
+diff --git a/arch/powerpc/platforms/celleb/interrupt.c b/arch/powerpc/platforms/celleb/interrupt.c
+deleted file mode 100644
+index c7c68ca..0000000
+--- a/arch/powerpc/platforms/celleb/interrupt.c
++++ /dev/null
+@@ -1,281 +0,0 @@
+-/*
+- * Celleb/Beat Interrupt controller
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/percpu.h>
+-#include <linux/types.h>
+-
+-#include <asm/machdep.h>
+-
+-#include "interrupt.h"
+-#include "beat_wrapper.h"
+-
+-#define	MAX_IRQS	NR_IRQS
+-static DEFINE_SPINLOCK(beatic_irq_mask_lock);
+-static uint64_t	beatic_irq_mask_enable[(MAX_IRQS+255)/64];
+-static uint64_t	beatic_irq_mask_ack[(MAX_IRQS+255)/64];
+-
+-static struct irq_host *beatic_host = NULL;
+-
+-/*
+- * In this implementation, "virq" == "IRQ plug number",
+- * "(irq_hw_number_t)hwirq" == "IRQ outlet number".
+- */
+-
+-/* assumption: locked */
+-static inline void beatic_update_irq_mask(unsigned int irq_plug)
+-{
+-	int off;
+-	unsigned long masks[4];
+-
+-	off = (irq_plug / 256) * 4;
+-	masks[0] = beatic_irq_mask_enable[off + 0]
+-	           & beatic_irq_mask_ack[off + 0];
+-	masks[1] = beatic_irq_mask_enable[off + 1]
+-	           & beatic_irq_mask_ack[off + 1];
+-	masks[2] = beatic_irq_mask_enable[off + 2]
+-	           & beatic_irq_mask_ack[off + 2];
+-	masks[3] = beatic_irq_mask_enable[off + 3]
+-	           & beatic_irq_mask_ack[off + 3];
+-	if (beat_set_interrupt_mask(irq_plug&~255UL,
+-		masks[0], masks[1], masks[2], masks[3]) != 0)
+-		panic("Failed to set mask IRQ!");
+-}
+-
+-static void beatic_mask_irq(unsigned int irq_plug)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&beatic_irq_mask_lock, flags);
+-	beatic_irq_mask_enable[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
+-	beatic_update_irq_mask(irq_plug);
+-	spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
+-}
+-
+-static void beatic_unmask_irq(unsigned int irq_plug)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&beatic_irq_mask_lock, flags);
+-	beatic_irq_mask_enable[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
+-	beatic_update_irq_mask(irq_plug);
+-	spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
+-}
+-
+-static void beatic_ack_irq(unsigned int irq_plug)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&beatic_irq_mask_lock, flags);
+-	beatic_irq_mask_ack[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
+-	beatic_update_irq_mask(irq_plug);
+-	spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
+-}
+-
+-static void beatic_end_irq(unsigned int irq_plug)
+-{
+-	s64 err;
+-	unsigned long flags;
+-
+-	if ((err = beat_downcount_of_interrupt(irq_plug)) != 0) {
+-		if ((err & 0xFFFFFFFF) != 0xFFFFFFF5) /* -11: wrong state */
+-			panic("Failed to downcount IRQ! Error = %16lx", err);
+-
+-		printk(KERN_ERR "IRQ over-downcounted, plug %d\n", irq_plug);
+-	}
+-	spin_lock_irqsave(&beatic_irq_mask_lock, flags);
+-	beatic_irq_mask_ack[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
+-	beatic_update_irq_mask(irq_plug);
+-	spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
+-}
+-
+-static struct irq_chip beatic_pic = {
+-	.typename = " CELL-BEAT ",
+-	.unmask = beatic_unmask_irq,
+-	.mask = beatic_mask_irq,
+-	.eoi = beatic_end_irq,
+-};
+-
+-/*
+- * Dispose binding hardware IRQ number (hw) and Virtuql IRQ number (virq),
+- * update flags.
+- *
+- * Note that the number (virq) is already assigned at upper layer.
+- */
+-static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq)
+-{
+-	beat_destruct_irq_plug(virq);
+-}
+-
+-/*
+- * Create or update binding hardware IRQ number (hw) and Virtuql
+- * IRQ number (virq). This is called only once for a given mapping.
+- *
+- * Note that the number (virq) is already assigned at upper layer.
+- */
+-static int beatic_pic_host_map(struct irq_host *h, unsigned int virq,
+-			       irq_hw_number_t hw)
+-{
+-	struct irq_desc *desc = get_irq_desc(virq);
+-	int64_t	err;
+-
+-	if ((err = beat_construct_and_connect_irq_plug(virq, hw)) < 0)
+-		return -EIO;
+-
+-	desc->status |= IRQ_LEVEL;
+-	set_irq_chip_and_handler(virq, &beatic_pic, handle_fasteoi_irq);
+-	return 0;
+-}
+-
+-/*
+- * Update binding hardware IRQ number (hw) and Virtuql
+- * IRQ number (virq). This is called only once for a given mapping.
+- */
+-static void beatic_pic_host_remap(struct irq_host *h, unsigned int virq,
+-			       irq_hw_number_t hw)
+-{
+-	beat_construct_and_connect_irq_plug(virq, hw);
+-}
+-
+-/*
+- * Translate device-tree interrupt spec to irq_hw_number_t style (ulong),
+- * to pass away to irq_create_mapping().
+- *
+- * Called from irq_create_of_mapping() only.
+- * Note: We have only 1 entry to translate.
+- */
+-static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+-				 u32 *intspec, unsigned int intsize,
+-				 irq_hw_number_t *out_hwirq,
+-				 unsigned int *out_flags)
+-{
+-	u64 *intspec2 = (u64 *)intspec;
+-
+-	*out_hwirq = *intspec2;
+-	*out_flags |= IRQ_TYPE_LEVEL_LOW;
+-	return 0;
+-}
+-
+-static int beatic_pic_host_match(struct irq_host *h, struct device_node *np)
+-{
+-	/* Match all */
+-	return 1;
+-}
+-
+-static struct irq_host_ops beatic_pic_host_ops = {
+-	.map = beatic_pic_host_map,
+-	.remap = beatic_pic_host_remap,
+-	.unmap = beatic_pic_host_unmap,
+-	.xlate = beatic_pic_host_xlate,
+-	.match = beatic_pic_host_match,
+-};
+-
+-/*
+- * Get an IRQ number
+- * Note: returns VIRQ
+- */
+-static inline unsigned int beatic_get_irq_plug(void)
+-{
+-	int i;
+-	uint64_t	pending[4], ub;
+-
+-	for (i = 0; i < MAX_IRQS; i += 256) {
+-		beat_detect_pending_interrupts(i, pending);
+-		__asm__ ("cntlzd %0,%1":"=r"(ub):
+-			"r"(pending[0] & beatic_irq_mask_enable[i/64+0]
+-			               & beatic_irq_mask_ack[i/64+0]));
+-		if (ub != 64)
+-			return i + ub + 0;
+-		__asm__ ("cntlzd %0,%1":"=r"(ub):
+-			"r"(pending[1] & beatic_irq_mask_enable[i/64+1]
+-			               & beatic_irq_mask_ack[i/64+1]));
+-		if (ub != 64)
+-			return i + ub + 64;
+-		__asm__ ("cntlzd %0,%1":"=r"(ub):
+-			"r"(pending[2] & beatic_irq_mask_enable[i/64+2]
+-			               & beatic_irq_mask_ack[i/64+2]));
+-		if (ub != 64)
+-			return i + ub + 128;
+-		__asm__ ("cntlzd %0,%1":"=r"(ub):
+-			"r"(pending[3] & beatic_irq_mask_enable[i/64+3]
+-			               & beatic_irq_mask_ack[i/64+3]));
+-		if (ub != 64)
+-			return i + ub + 192;
+-	}
+-
+-	return NO_IRQ;
+-}
+-unsigned int beatic_get_irq(void)
+-{
+-	unsigned int ret;
+-
+-	ret = beatic_get_irq_plug();
+-	if (ret != NO_IRQ)
+-		beatic_ack_irq(ret);
+-	return ret;
+-}
+-
+-/*
+- */
+-void __init beatic_init_IRQ(void)
+-{
+-	int	i;
+-
+-	memset(beatic_irq_mask_enable, 0, sizeof(beatic_irq_mask_enable));
+-	memset(beatic_irq_mask_ack, 255, sizeof(beatic_irq_mask_ack));
+-	for (i = 0; i < MAX_IRQS; i += 256)
+-		beat_set_interrupt_mask(i, 0L, 0L, 0L, 0L);
+-
+-	/* Set out get_irq function */
+-	ppc_md.get_irq = beatic_get_irq;
+-
+-	/* Allocate an irq host */
+-	beatic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0,
+-					 &beatic_pic_host_ops,
+-					 0);
+-	BUG_ON(beatic_host == NULL);
+-	irq_set_default_host(beatic_host);
+-}
+-
+-#ifdef CONFIG_SMP
+-
+-/* Nullified to compile with SMP mode */
+-void beatic_setup_cpu(int cpu)
+-{
+-}
+-
+-void beatic_cause_IPI(int cpu, int mesg)
+-{
+-}
+-
+-void beatic_request_IPIs(void)
+-{
+-}
+-#endif /* CONFIG_SMP */
+-
+-void beatic_deinit_IRQ(void)
+-{
+-	int	i;
+-
+-	for (i = 1; i < NR_IRQS; i++)
+-		beat_destruct_irq_plug(i);
+-}
+diff --git a/arch/powerpc/platforms/celleb/interrupt.h b/arch/powerpc/platforms/celleb/interrupt.h
+deleted file mode 100644
+index b470fd0..0000000
+--- a/arch/powerpc/platforms/celleb/interrupt.h
++++ /dev/null
+@@ -1,33 +0,0 @@
+-/*
+- * Celleb/Beat Interrupt controller
+- *
+- * (C) Copyright 2006 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef ASM_BEAT_PIC_H
+-#define ASM_BEAT_PIC_H
+-#ifdef __KERNEL__
+-
+-extern void beatic_init_IRQ(void);
+-extern unsigned int beatic_get_irq(void);
+-extern void beatic_cause_IPI(int cpu, int mesg);
+-extern void beatic_request_IPIs(void);
+-extern void beatic_setup_cpu(int);
+-extern void beatic_deinit_IRQ(void);
+-
+-#endif
+-#endif /* ASM_BEAT_PIC_H */
+diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c
+deleted file mode 100644
+index 423339b..0000000
+--- a/arch/powerpc/platforms/celleb/io-workarounds.c
++++ /dev/null
+@@ -1,280 +0,0 @@
+-/*
+- * Support for Celleb io workarounds
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This file is based to arch/powerpc/platform/cell/io-workarounds.c
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/of.h>
+-#include <linux/of_device.h>
+-#include <linux/irq.h>
+-
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/ppc-pci.h>
+-
+-#include "pci.h"
+-
+-#define MAX_CELLEB_PCI_BUS	4
+-
+-void *celleb_dummy_page_va;
+-
+-static struct celleb_pci_bus {
+-	struct pci_controller *phb;
+-	void (*dummy_read)(struct pci_controller *);
+-} celleb_pci_busses[MAX_CELLEB_PCI_BUS];
+-
+-static int celleb_pci_count = 0;
+-
+-static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr,
+-					      unsigned long paddr)
+-{
+-	int i, j;
+-	struct resource *res;
+-
+-	for (i = 0; i < celleb_pci_count; i++) {
+-		struct celleb_pci_bus *bus = &celleb_pci_busses[i];
+-		struct pci_controller *phb = bus->phb;
+-		if (paddr)
+-			for (j = 0; j < 3; j++) {
+-				res = &phb->mem_resources[j];
+-				if (paddr >= res->start && paddr <= res->end)
+-					return bus;
+-			}
+-		res = &phb->io_resource;
+-		if (vaddr && vaddr >= res->start && vaddr <= res->end)
+-			return bus;
+-	}
+-	return NULL;
+-}
+-
+-static void celleb_io_flush(const PCI_IO_ADDR addr)
+-{
+-	struct celleb_pci_bus *bus;
+-	int token;
+-
+-	token = PCI_GET_ADDR_TOKEN(addr);
+-
+-	if (token && token <= celleb_pci_count)
+-		bus = &celleb_pci_busses[token - 1];
+-	else {
+-		unsigned long vaddr, paddr;
+-		pte_t *ptep;
+-
+-		vaddr = (unsigned long)PCI_FIX_ADDR(addr);
+-		if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
+-			return;
+-
+-		ptep = find_linux_pte(init_mm.pgd, vaddr);
+-		if (ptep == NULL)
+-			paddr = 0;
+-		else
+-			paddr = pte_pfn(*ptep) << PAGE_SHIFT;
+-		bus = celleb_pci_find(vaddr, paddr);
+-
+-		if (bus == NULL)
+-			return;
+-	}
+-
+-	if (bus->dummy_read)
+-		bus->dummy_read(bus->phb);
+-}
+-
+-static u8 celleb_readb(const PCI_IO_ADDR addr)
+-{
+-	u8 val;
+-	val = __do_readb(addr);
+-	celleb_io_flush(addr);
+-	return val;
+-}
+-
+-static u16 celleb_readw(const PCI_IO_ADDR addr)
+-{
+-	u16 val;
+-	val = __do_readw(addr);
+-	celleb_io_flush(addr);
+-	return val;
+-}
+-
+-static u32 celleb_readl(const PCI_IO_ADDR addr)
+-{
+-	u32 val;
+-	val = __do_readl(addr);
+-	celleb_io_flush(addr);
+-	return val;
+-}
+-
+-static u64 celleb_readq(const PCI_IO_ADDR addr)
+-{
+-	u64 val;
+-	val = __do_readq(addr);
+-	celleb_io_flush(addr);
+-	return val;
+-}
+-
+-static u16 celleb_readw_be(const PCI_IO_ADDR addr)
+-{
+-	u16 val;
+-	val = __do_readw_be(addr);
+-	celleb_io_flush(addr);
+-	return val;
+-}
+-
+-static u32 celleb_readl_be(const PCI_IO_ADDR addr)
+-{
+-	u32 val;
+-	val = __do_readl_be(addr);
+-	celleb_io_flush(addr);
+-	return val;
+-}
+-
+-static u64 celleb_readq_be(const PCI_IO_ADDR addr)
+-{
+-	u64 val;
+-	val = __do_readq_be(addr);
+-	celleb_io_flush(addr);
+-	return val;
+-}
+-
+-static void celleb_readsb(const PCI_IO_ADDR addr,
+-			  void *buf, unsigned long count)
+-{
+-	__do_readsb(addr, buf, count);
+-	celleb_io_flush(addr);
+-}
+-
+-static void celleb_readsw(const PCI_IO_ADDR addr,
+-			  void *buf, unsigned long count)
+-{
+-	__do_readsw(addr, buf, count);
+-	celleb_io_flush(addr);
+-}
+-
+-static void celleb_readsl(const PCI_IO_ADDR addr,
+-			  void *buf, unsigned long count)
+-{
+-	__do_readsl(addr, buf, count);
+-	celleb_io_flush(addr);
+-}
+-
+-static void celleb_memcpy_fromio(void *dest,
+-				 const PCI_IO_ADDR src,
+-				 unsigned long n)
+-{
+-	__do_memcpy_fromio(dest, src, n);
+-	celleb_io_flush(src);
+-}
+-
+-static void __iomem *celleb_ioremap(unsigned long addr,
+-				     unsigned long size,
+-				     unsigned long flags)
+-{
+-	struct celleb_pci_bus *bus;
+-	void __iomem *res = __ioremap(addr, size, flags);
+-	int busno;
+-
+-	bus = celleb_pci_find(0, addr);
+-	if (bus != NULL) {
+-		busno = bus - celleb_pci_busses;
+-		PCI_SET_ADDR_TOKEN(res, busno + 1);
+-	}
+-	return res;
+-}
+-
+-static void celleb_iounmap(volatile void __iomem *addr)
+-{
+-	return __iounmap(PCI_FIX_ADDR(addr));
+-}
+-
+-static struct ppc_pci_io celleb_pci_io __initdata = {
+-	.readb = celleb_readb,
+-	.readw = celleb_readw,
+-	.readl = celleb_readl,
+-	.readq = celleb_readq,
+-	.readw_be = celleb_readw_be,
+-	.readl_be = celleb_readl_be,
+-	.readq_be = celleb_readq_be,
+-	.readsb = celleb_readsb,
+-	.readsw = celleb_readsw,
+-	.readsl = celleb_readsl,
+-	.memcpy_fromio = celleb_memcpy_fromio,
+-};
+-
+-void __init celleb_pci_add_one(struct pci_controller *phb,
+-			       void (*dummy_read)(struct pci_controller *))
+-{
+-	struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count];
+-	struct device_node *np = phb->dn;
+-
+-	if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) {
+-		printk(KERN_ERR "Too many pci bridges, workarounds"
+-		       " disabled for %s\n", np->full_name);
+-		return;
+-	}
+-
+-	celleb_pci_count++;
+-
+-	bus->phb = phb;
+-	bus->dummy_read = dummy_read;
+-}
+-
+-static struct of_device_id celleb_pci_workaround_match[] __initdata = {
+-	{
+-		.name = "pci-pseudo",
+-		.data = fake_pci_workaround_init,
+-	}, {
+-		.name = "epci",
+-		.data = epci_workaround_init,
+-	}, {
+-	},
+-};
+-
+-int __init celleb_pci_workaround_init(void)
+-{
+-	struct pci_controller *phb;
+-	struct device_node *node;
+-	const struct  of_device_id *match;
+-	void (*init_func)(struct pci_controller *);
+-
+-	celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
+-	if (!celleb_dummy_page_va) {
+-		printk(KERN_ERR "Celleb: dummy read disabled. "
+-			"Alloc celleb_dummy_page_va failed\n");
+-		return 1;
+-	}
+-
+-	list_for_each_entry(phb, &hose_list, list_node) {
+-		node = phb->dn;
+-		match = of_match_node(celleb_pci_workaround_match, node);
+-
+-		if (match) {
+-			init_func = match->data;
+-			(*init_func)(phb);
+-		}
+-	}
+-
+-	ppc_pci_io = celleb_pci_io;
+-	ppc_md.ioremap = celleb_ioremap;
+-	ppc_md.iounmap = celleb_iounmap;
+-
+-	return 0;
+-}
+diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c
+deleted file mode 100644
+index 93b0efd..0000000
+--- a/arch/powerpc/platforms/celleb/iommu.c
++++ /dev/null
+@@ -1,116 +0,0 @@
+-/*
+- * Support for IOMMU on Celleb platform.
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/pci.h>
+-#include <linux/of_platform.h>
+-
+-#include <asm/machdep.h>
+-
+-#include "beat_wrapper.h"
+-
+-#define DMA_FLAGS 0xf800000000000000UL	/* r/w permitted, coherency required,
+-					   strongest order */
+-
+-static int __init find_dma_window(u64 *io_space_id, u64 *ioid,
+-				  u64 *base, u64 *size, u64 *io_page_size)
+-{
+-	struct device_node *dn;
+-	const unsigned long *dma_window;
+-
+-	for_each_node_by_type(dn, "ioif") {
+-		dma_window = of_get_property(dn, "toshiba,dma-window", NULL);
+-		if (dma_window) {
+-			*io_space_id = (dma_window[0] >> 32) & 0xffffffffUL;
+-			*ioid = dma_window[0] & 0x7ffUL;
+-			*base = dma_window[1];
+-			*size = dma_window[2];
+-			*io_page_size = 1 << dma_window[3];
+-			of_node_put(dn);
+-			return 1;
+-		}
+-	}
+-	return 0;
+-}
+-
+-static unsigned long celleb_dma_direct_offset;
+-
+-static void __init celleb_init_direct_mapping(void)
+-{
+-	u64 lpar_addr, io_addr;
+-	u64 io_space_id, ioid, dma_base, dma_size, io_page_size;
+-
+-	if (!find_dma_window(&io_space_id, &ioid, &dma_base, &dma_size,
+-			     &io_page_size)) {
+-		pr_info("No dma window found !\n");
+-		return;
+-	}
+-
+-	for (lpar_addr = 0; lpar_addr < dma_size; lpar_addr += io_page_size) {
+-		io_addr = lpar_addr + dma_base;
+-		(void)beat_put_iopte(io_space_id, io_addr, lpar_addr,
+-				     ioid, DMA_FLAGS);
+-	}
+-
+-	celleb_dma_direct_offset = dma_base;
+-}
+-
+-static void celleb_dma_dev_setup(struct device *dev)
+-{
+-	dev->archdata.dma_ops = get_pci_dma_ops();
+-	dev->archdata.dma_data = (void *)celleb_dma_direct_offset;
+-}
+-
+-static void celleb_pci_dma_dev_setup(struct pci_dev *pdev)
+-{
+-	celleb_dma_dev_setup(&pdev->dev);
+-}
+-
+-static int celleb_of_bus_notify(struct notifier_block *nb,
+-				unsigned long action, void *data)
+-{
+-	struct device *dev = data;
+-
+-	/* We are only intereted in device addition */
+-	if (action != BUS_NOTIFY_ADD_DEVICE)
+-		return 0;
+-
+-	celleb_dma_dev_setup(dev);
+-
+-	return 0;
+-}
+-
+-static struct notifier_block celleb_of_bus_notifier = {
+-	.notifier_call = celleb_of_bus_notify
+-};
+-
+-static int __init celleb_init_iommu(void)
+-{
+-	celleb_init_direct_mapping();
+-	set_pci_dma_ops(&dma_direct_ops);
+-	ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup;
+-	bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier);
+-
+-	return 0;
+-}
+-
+-machine_arch_initcall(celleb_beat, celleb_init_iommu);
+diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c
+deleted file mode 100644
+index 51b390d..0000000
+--- a/arch/powerpc/platforms/celleb/pci.c
++++ /dev/null
+@@ -1,502 +0,0 @@
+-/*
+- * Support for PCI on Celleb platform.
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/kernel/rtas_pci.c:
+- *  Copyright (C) 2001 Dave Engebretsen, IBM Corporation
+- *  Copyright (C) 2003 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU 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.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/kernel.h>
+-#include <linux/threads.h>
+-#include <linux/pci.h>
+-#include <linux/string.h>
+-#include <linux/init.h>
+-#include <linux/bootmem.h>
+-#include <linux/pci_regs.h>
+-#include <linux/of.h>
+-#include <linux/of_device.h>
+-
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/ppc-pci.h>
+-
+-#include "pci.h"
+-#include "interrupt.h"
+-
+-#define MAX_PCI_DEVICES    32
+-#define MAX_PCI_FUNCTIONS   8
+-#define MAX_PCI_BASE_ADDRS  3 /* use 64 bit address */
+-
+-/* definition for fake pci configuration area for GbE, .... ,and etc. */
+-
+-struct celleb_pci_resource {
+-	struct resource r[MAX_PCI_BASE_ADDRS];
+-};
+-
+-struct celleb_pci_private {
+-	unsigned char *fake_config[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
+-	struct celleb_pci_resource *res[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
+-};
+-
+-static inline u8 celleb_fake_config_readb(void *addr)
+-{
+-	u8 *p = addr;
+-	return *p;
+-}
+-
+-static inline u16 celleb_fake_config_readw(void *addr)
+-{
+-	__le16 *p = addr;
+-	return le16_to_cpu(*p);
+-}
+-
+-static inline u32 celleb_fake_config_readl(void *addr)
+-{
+-	__le32 *p = addr;
+-	return le32_to_cpu(*p);
+-}
+-
+-static inline void celleb_fake_config_writeb(u32 val, void *addr)
+-{
+-	u8 *p = addr;
+-	*p = val;
+-}
+-
+-static inline void celleb_fake_config_writew(u32 val, void *addr)
+-{
+-	__le16 val16;
+-	__le16 *p = addr;
+-	val16 = cpu_to_le16(val);
+-	*p = val16;
+-}
+-
+-static inline void celleb_fake_config_writel(u32 val, void *addr)
+-{
+-	__le32 val32;
+-	__le32 *p = addr;
+-	val32 = cpu_to_le32(val);
+-	*p = val32;
+-}
+-
+-static unsigned char *get_fake_config_start(struct pci_controller *hose,
+-					    int devno, int fn)
+-{
+-	struct celleb_pci_private *private = hose->private_data;
+-
+-	if (private == NULL)
+-		return NULL;
+-
+-	return private->fake_config[devno][fn];
+-}
+-
+-static struct celleb_pci_resource *get_resource_start(
+-				struct pci_controller *hose,
+-				int devno, int fn)
+-{
+-	struct celleb_pci_private *private = hose->private_data;
+-
+-	if (private == NULL)
+-		return NULL;
+-
+-	return private->res[devno][fn];
+-}
+-
+-
+-static void celleb_config_read_fake(unsigned char *config, int where,
+-				    int size, u32 *val)
+-{
+-	char *p = config + where;
+-
+-	switch (size) {
+-	case 1:
+-		*val = celleb_fake_config_readb(p);
+-		break;
+-	case 2:
+-		*val = celleb_fake_config_readw(p);
+-		break;
+-	case 4:
+-		*val = celleb_fake_config_readl(p);
+-		break;
+-	}
+-}
+-
+-static void celleb_config_write_fake(unsigned char *config, int where,
+-				     int size, u32 val)
+-{
+-	char *p = config + where;
+-
+-	switch (size) {
+-	case 1:
+-		celleb_fake_config_writeb(val, p);
+-		break;
+-	case 2:
+-		celleb_fake_config_writew(val, p);
+-		break;
+-	case 4:
+-		celleb_fake_config_writel(val, p);
+-		break;
+-	}
+-}
+-
+-static int celleb_fake_pci_read_config(struct pci_bus *bus,
+-		unsigned int devfn, int where, int size, u32 *val)
+-{
+-	char *config;
+-	struct device_node *node;
+-	struct pci_controller *hose;
+-	unsigned int devno = devfn >> 3;
+-	unsigned int fn = devfn & 0x7;
+-
+-	/* allignment check */
+-	BUG_ON(where % size);
+-
+-	pr_debug("    fake read: bus=0x%x, ", bus->number);
+-	node = (struct device_node *)bus->sysdata;
+-	hose = pci_find_hose_for_OF_device(node);
+-	config = get_fake_config_start(hose, devno, fn);
+-
+-	pr_debug("devno=0x%x, where=0x%x, size=0x%x, ", devno, where, size);
+-	if (!config) {
+-		pr_debug("failed\n");
+-		return PCIBIOS_DEVICE_NOT_FOUND;
+-	}
+-
+-	celleb_config_read_fake(config, where, size, val);
+-	pr_debug("val=0x%x\n", *val);
+-
+-	return PCIBIOS_SUCCESSFUL;
+-}
+-
+-
+-static int celleb_fake_pci_write_config(struct pci_bus *bus,
+-		 unsigned int devfn, int where, int size, u32 val)
+-{
+-	char *config;
+-	struct device_node *node;
+-	struct pci_controller *hose;
+-	struct celleb_pci_resource *res;
+-	unsigned int devno = devfn >> 3;
+-	unsigned int fn = devfn & 0x7;
+-
+-	/* allignment check */
+-	BUG_ON(where % size);
+-
+-	node = (struct device_node *)bus->sysdata;
+-	hose = pci_find_hose_for_OF_device(node);
+-	config = get_fake_config_start(hose, devno, fn);
+-
+-	if (!config)
+-		return PCIBIOS_DEVICE_NOT_FOUND;
+-
+-	if (val == ~0) {
+-		int i = (where - PCI_BASE_ADDRESS_0) >> 3;
+-
+-		switch (where) {
+-		case PCI_BASE_ADDRESS_0:
+-		case PCI_BASE_ADDRESS_2:
+-			if (size != 4)
+-				return PCIBIOS_DEVICE_NOT_FOUND;
+-			res = get_resource_start(hose, devno, fn);
+-			if (!res)
+-				return PCIBIOS_DEVICE_NOT_FOUND;
+-			celleb_config_write_fake(config, where, size,
+-					(res->r[i].end - res->r[i].start));
+-			return PCIBIOS_SUCCESSFUL;
+-		case PCI_BASE_ADDRESS_1:
+-		case PCI_BASE_ADDRESS_3:
+-		case PCI_BASE_ADDRESS_4:
+-		case PCI_BASE_ADDRESS_5:
+-			break;
+-		default:
+-			break;
+-		}
+-	}
+-
+-	celleb_config_write_fake(config, where, size, val);
+-	pr_debug("    fake write: where=%x, size=%d, val=%x\n",
+-		 where, size, val);
+-
+-	return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static struct pci_ops celleb_fake_pci_ops = {
+-	.read = celleb_fake_pci_read_config,
+-	.write = celleb_fake_pci_write_config,
+-};
+-
+-static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose,
+-					unsigned int devno, unsigned int fn,
+-					unsigned int num_base_addr)
+-{
+-	u32 val;
+-	unsigned char *config;
+-	struct celleb_pci_resource *res;
+-
+-	config = get_fake_config_start(hose, devno, fn);
+-	res = get_resource_start(hose, devno, fn);
+-
+-	if (!config || !res)
+-		return;
+-
+-	switch (num_base_addr) {
+-	case 3:
+-		val = (res->r[2].start & 0xfffffff0)
+-		    | PCI_BASE_ADDRESS_MEM_TYPE_64;
+-		celleb_config_write_fake(config, PCI_BASE_ADDRESS_4, 4, val);
+-		val = res->r[2].start >> 32;
+-		celleb_config_write_fake(config, PCI_BASE_ADDRESS_5, 4, val);
+-		/* FALLTHROUGH */
+-	case 2:
+-		val = (res->r[1].start & 0xfffffff0)
+-		    | PCI_BASE_ADDRESS_MEM_TYPE_64;
+-		celleb_config_write_fake(config, PCI_BASE_ADDRESS_2, 4, val);
+-		val = res->r[1].start >> 32;
+-		celleb_config_write_fake(config, PCI_BASE_ADDRESS_3, 4, val);
+-		/* FALLTHROUGH */
+-	case 1:
+-		val = (res->r[0].start & 0xfffffff0)
+-		    | PCI_BASE_ADDRESS_MEM_TYPE_64;
+-		celleb_config_write_fake(config, PCI_BASE_ADDRESS_0, 4, val);
+-		val = res->r[0].start >> 32;
+-		celleb_config_write_fake(config, PCI_BASE_ADDRESS_1, 4, val);
+-		break;
+-	}
+-
+-	val = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+-	celleb_config_write_fake(config, PCI_COMMAND, 2, val);
+-}
+-
+-static int __init celleb_setup_fake_pci_device(struct device_node *node,
+-					       struct pci_controller *hose)
+-{
+-	unsigned int rlen;
+-	int num_base_addr = 0;
+-	u32 val;
+-	const u32 *wi0, *wi1, *wi2, *wi3, *wi4;
+-	unsigned int devno, fn;
+-	struct celleb_pci_private *private = hose->private_data;
+-	unsigned char **config = NULL;
+-	struct celleb_pci_resource **res = NULL;
+-	const char *name;
+-	const unsigned long *li;
+-	int size, result;
+-
+-	if (private == NULL) {
+-		printk(KERN_ERR "PCI: "
+-		       "memory space for pci controller is not assigned\n");
+-		goto error;
+-	}
+-
+-	name = of_get_property(node, "model", &rlen);
+-	if (!name) {
+-		printk(KERN_ERR "PCI: model property not found.\n");
+-		goto error;
+-	}
+-
+-	wi4 = of_get_property(node, "reg", &rlen);
+-	if (wi4 == NULL)
+-		goto error;
+-
+-	devno = ((wi4[0] >> 8) & 0xff) >> 3;
+-	fn = (wi4[0] >> 8) & 0x7;
+-
+-	pr_debug("PCI: celleb_setup_fake_pci() %s devno=%x fn=%x\n", name,
+-		 devno, fn);
+-
+-	size = 256;
+-	config = &private->fake_config[devno][fn];
+-	*config = alloc_maybe_bootmem(size, GFP_KERNEL);
+-	if (*config == NULL) {
+-		printk(KERN_ERR "PCI: "
+-		       "not enough memory for fake configuration space\n");
+-		goto error;
+-	}
+-	pr_debug("PCI: fake config area assigned 0x%016lx\n",
+-		 (unsigned long)*config);
+-
+-	size = sizeof(struct celleb_pci_resource);
+-	res = &private->res[devno][fn];
+-	*res = alloc_maybe_bootmem(size, GFP_KERNEL);
+-	if (*res == NULL) {
+-		printk(KERN_ERR
+-		       "PCI: not enough memory for resource data space\n");
+-		goto error;
+-	}
+-	pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res);
+-
+-	wi0 = of_get_property(node, "device-id", NULL);
+-	wi1 = of_get_property(node, "vendor-id", NULL);
+-	wi2 = of_get_property(node, "class-code", NULL);
+-	wi3 = of_get_property(node, "revision-id", NULL);
+-	if (!wi0 || !wi1 || !wi2 || !wi3) {
+-		printk(KERN_ERR "PCI: Missing device tree properties.\n");
+-		goto error;
+-	}
+-
+-	celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff);
+-	celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff);
+-	pr_debug("class-code = 0x%08x\n", wi2[0]);
+-
+-	celleb_config_write_fake(*config, PCI_CLASS_PROG, 1, wi2[0] & 0xff);
+-	celleb_config_write_fake(*config, PCI_CLASS_DEVICE, 2,
+-				 (wi2[0] >> 8) & 0xffff);
+-	celleb_config_write_fake(*config, PCI_REVISION_ID, 1, wi3[0]);
+-
+-	while (num_base_addr < MAX_PCI_BASE_ADDRS) {
+-		result = of_address_to_resource(node,
+-				num_base_addr, &(*res)->r[num_base_addr]);
+-		if (result)
+-			break;
+-		num_base_addr++;
+-	}
+-
+-	celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr);
+-
+-	li = of_get_property(node, "interrupts", &rlen);
+-	if (!li) {
+-		printk(KERN_ERR "PCI: interrupts not found.\n");
+-		goto error;
+-	}
+-	val = li[0];
+-	celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1);
+-	celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val);
+-
+-#ifdef DEBUG
+-	pr_debug("PCI: %s irq=%ld\n", name, li[0]);
+-	for (i = 0; i < 6; i++) {
+-		celleb_config_read_fake(*config,
+-					PCI_BASE_ADDRESS_0 + 0x4 * i, 4,
+-					&val);
+-		pr_debug("PCI: %s fn=%d base_address_%d=0x%x\n",
+-			 name, fn, i, val);
+-	}
+-#endif
+-
+-	celleb_config_write_fake(*config, PCI_HEADER_TYPE, 1,
+-				 PCI_HEADER_TYPE_NORMAL);
+-
+-	return 0;
+-
+-error:
+-	if (mem_init_done) {
+-		if (config && *config)
+-			kfree(*config);
+-		if (res && *res)
+-			kfree(*res);
+-
+-	} else {
+-		if (config && *config) {
+-			size = 256;
+-			free_bootmem((unsigned long)(*config), size);
+-		}
+-		if (res && *res) {
+-			size = sizeof(struct celleb_pci_resource);
+-			free_bootmem((unsigned long)(*res), size);
+-		}
+-	}
+-
+-	return 1;
+-}
+-
+-static int __init phb_set_bus_ranges(struct device_node *dev,
+-				     struct pci_controller *phb)
+-{
+-	const int *bus_range;
+-	unsigned int len;
+-
+-	bus_range = of_get_property(dev, "bus-range", &len);
+-	if (bus_range == NULL || len < 2 * sizeof(int))
+-		return 1;
+-
+-	phb->first_busno = bus_range[0];
+-	phb->last_busno = bus_range[1];
+-
+-	return 0;
+-}
+-
+-static void __init celleb_alloc_private_mem(struct pci_controller *hose)
+-{
+-	hose->private_data =
+-		alloc_maybe_bootmem(sizeof(struct celleb_pci_private),
+-			GFP_KERNEL);
+-}
+-
+-static int __init celleb_setup_fake_pci(struct device_node *dev,
+-					struct pci_controller *phb)
+-{
+-	struct device_node *node;
+-
+-	phb->ops = &celleb_fake_pci_ops;
+-	celleb_alloc_private_mem(phb);
+-
+-	for (node = of_get_next_child(dev, NULL);
+-	     node != NULL; node = of_get_next_child(dev, node))
+-		celleb_setup_fake_pci_device(node, phb);
+-
+-	return 0;
+-}
+-
+-void __init fake_pci_workaround_init(struct pci_controller *phb)
+-{
+-	/**
+-	 *  We will add fake pci bus to scc_pci_bus for the purpose to improve
+-	 *  I/O Macro performance. But device-tree and device drivers
+-	 *  are not ready to use address with a token.
+-	 */
+-
+-	/* celleb_pci_add_one(phb, NULL); */
+-}
+-
+-static struct of_device_id celleb_phb_match[] __initdata = {
+-	{
+-		.name = "pci-pseudo",
+-		.data = celleb_setup_fake_pci,
+-	}, {
+-		.name = "epci",
+-		.data = celleb_setup_epci,
+-	}, {
+-	},
+-};
+-
+-int __init celleb_setup_phb(struct pci_controller *phb)
+-{
+-	struct device_node *dev = phb->dn;
+-	const struct of_device_id *match;
+-	int (*setup_func)(struct device_node *, struct pci_controller *);
+-
+-	match = of_match_node(celleb_phb_match, dev);
+-	if (!match)
+-		return 1;
+-
+-	phb_set_bus_ranges(dev, phb);
+-	phb->buid = 1;
+-
+-	setup_func = match->data;
+-	return (*setup_func)(dev, phb);
+-}
+-
+-int celleb_pci_probe_mode(struct pci_bus *bus)
+-{
+-	return PCI_PROBE_DEVTREE;
+-}
+diff --git a/arch/powerpc/platforms/celleb/pci.h b/arch/powerpc/platforms/celleb/pci.h
+deleted file mode 100644
+index 5d5544f..0000000
+--- a/arch/powerpc/platforms/celleb/pci.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-/*
+- * pci prototypes for Celleb platform
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef _CELLEB_PCI_H
+-#define _CELLEB_PCI_H
+-
+-#include <linux/pci.h>
+-
+-#include <asm/pci-bridge.h>
+-#include <asm/prom.h>
+-#include <asm/ppc-pci.h>
+-
+-extern int celleb_setup_phb(struct pci_controller *);
+-extern int celleb_pci_probe_mode(struct pci_bus *);
+-
+-extern int celleb_setup_epci(struct device_node *, struct pci_controller *);
+-
+-extern void *celleb_dummy_page_va;
+-extern int __init celleb_pci_workaround_init(void);
+-extern void __init celleb_pci_add_one(struct pci_controller *,
+-				      void (*)(struct pci_controller *));
+-extern void fake_pci_workaround_init(struct pci_controller *);
+-extern void epci_workaround_init(struct pci_controller *);
+-
+-#endif /* _CELLEB_PCI_H */
+diff --git a/arch/powerpc/platforms/celleb/scc.h b/arch/powerpc/platforms/celleb/scc.h
+deleted file mode 100644
+index 6be1542..0000000
+--- a/arch/powerpc/platforms/celleb/scc.h
++++ /dev/null
+@@ -1,145 +0,0 @@
+-/*
+- * SCC (Super Companion Chip) definitions
+- *
+- * (C) Copyright 2004-2006 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef _CELLEB_SCC_H
+-#define _CELLEB_SCC_H
+-
+-#define PCI_VENDOR_ID_TOSHIBA_2                 0x102f
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_PCIEXC_BRIDGE 0x01b0
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_EPCI_BRIDGE   0x01b1
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_BRIDGE        0x01b2
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_GBE           0x01b3
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA           0x01b4
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_USB2          0x01b5
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_USB           0x01b6
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_ENCDEC        0x01b7
+-
+-#define SCC_EPCI_REG            0x0000d000
+-
+-/* EPCI registers */
+-#define SCC_EPCI_CNF10_REG      0x010
+-#define SCC_EPCI_CNF14_REG      0x014
+-#define SCC_EPCI_CNF18_REG      0x018
+-#define SCC_EPCI_PVBAT          0x100
+-#define SCC_EPCI_VPMBAT         0x104
+-#define SCC_EPCI_VPIBAT         0x108
+-#define SCC_EPCI_VCSR           0x110
+-#define SCC_EPCI_VIENAB         0x114
+-#define SCC_EPCI_VISTAT         0x118
+-#define SCC_EPCI_VRDCOUNT       0x124
+-#define SCC_EPCI_BAM0           0x12c
+-#define SCC_EPCI_BAM1           0x134
+-#define SCC_EPCI_BAM2           0x13c
+-#define SCC_EPCI_IADR           0x164
+-#define SCC_EPCI_CLKRST         0x800
+-#define SCC_EPCI_INTSET         0x804
+-#define SCC_EPCI_STATUS         0x808
+-#define SCC_EPCI_ABTSET         0x80c
+-#define SCC_EPCI_WATRP          0x810
+-#define SCC_EPCI_DUMYRADR       0x814
+-#define SCC_EPCI_SWRESP         0x818
+-#define SCC_EPCI_CNTOPT         0x81c
+-#define SCC_EPCI_ECMODE         0xf00
+-#define SCC_EPCI_IOM_AC_NUM     5
+-#define SCC_EPCI_IOM_ACTE(n)    (0xf10 + (n) * 4)
+-#define SCC_EPCI_IOT_AC_NUM     4
+-#define SCC_EPCI_IOT_ACTE(n)    (0xf30 + (n) * 4)
+-#define SCC_EPCI_MAEA           0xf50
+-#define SCC_EPCI_MAEC           0xf54
+-#define SCC_EPCI_CKCTRL         0xff0
+-
+-/* bits for SCC_EPCI_VCSR */
+-#define SCC_EPCI_VCSR_FRE       0x00020000
+-#define SCC_EPCI_VCSR_FWE       0x00010000
+-#define SCC_EPCI_VCSR_DR        0x00000400
+-#define SCC_EPCI_VCSR_SR        0x00000008
+-#define SCC_EPCI_VCSR_AT        0x00000004
+-
+-/* bits for SCC_EPCI_VIENAB/SCC_EPCI_VISTAT */
+-#define SCC_EPCI_VISTAT_PMPE    0x00000008
+-#define SCC_EPCI_VISTAT_PMFE    0x00000004
+-#define SCC_EPCI_VISTAT_PRA     0x00000002
+-#define SCC_EPCI_VISTAT_PRD     0x00000001
+-#define SCC_EPCI_VISTAT_ALL     0x0000000f
+-
+-#define SCC_EPCI_VIENAB_PMPEE   0x00000008
+-#define SCC_EPCI_VIENAB_PMFEE   0x00000004
+-#define SCC_EPCI_VIENAB_PRA     0x00000002
+-#define SCC_EPCI_VIENAB_PRD     0x00000001
+-#define SCC_EPCI_VIENAB_ALL     0x0000000f
+-
+-/* bits for SCC_EPCI_CLKRST */
+-#define SCC_EPCI_CLKRST_CKS_MASK 0x00030000
+-#define SCC_EPCI_CLKRST_CKS_2   0x00000000
+-#define SCC_EPCI_CLKRST_CKS_4   0x00010000
+-#define SCC_EPCI_CLKRST_CKS_8   0x00020000
+-#define SCC_EPCI_CLKRST_PCICRST 0x00000400
+-#define SCC_EPCI_CLKRST_BC      0x00000200
+-#define SCC_EPCI_CLKRST_PCIRST  0x00000100
+-#define SCC_EPCI_CLKRST_PCKEN   0x00000001
+-
+-/* bits for SCC_EPCI_INTSET/SCC_EPCI_STATUS */
+-#define SCC_EPCI_INT_2M         0x01000000
+-#define SCC_EPCI_INT_RERR       0x00200000
+-#define SCC_EPCI_INT_SERR       0x00100000
+-#define SCC_EPCI_INT_PRTER      0x00080000
+-#define SCC_EPCI_INT_SER        0x00040000
+-#define SCC_EPCI_INT_PER        0x00020000
+-#define SCC_EPCI_INT_PAI        0x00010000
+-#define SCC_EPCI_INT_1M         0x00000100
+-#define SCC_EPCI_INT_PME        0x00000010
+-#define SCC_EPCI_INT_INTD       0x00000008
+-#define SCC_EPCI_INT_INTC       0x00000004
+-#define SCC_EPCI_INT_INTB       0x00000002
+-#define SCC_EPCI_INT_INTA       0x00000001
+-#define SCC_EPCI_INT_DEVINT     0x0000000f
+-#define SCC_EPCI_INT_ALL        0x003f001f
+-#define SCC_EPCI_INT_ALLERR     0x003f0000
+-
+-/* bits for SCC_EPCI_CKCTRL */
+-#define SCC_EPCI_CKCTRL_CRST0   0x00010000
+-#define SCC_EPCI_CKCTRL_CRST1   0x00020000
+-#define SCC_EPCI_CKCTRL_OCLKEN  0x00000100
+-#define SCC_EPCI_CKCTRL_LCLKEN  0x00000001
+-
+-#define SCC_EPCI_IDSEL_AD_TO_SLOT(ad)       ((ad) - 10)
+-#define SCC_EPCI_MAX_DEVNU      SCC_EPCI_IDSEL_AD_TO_SLOT(32)
+-
+-/* bits for SCC_EPCI_CNTOPT */
+-#define SCC_EPCI_CNTOPT_O2PMB   0x00000002
+-
+-/* UHC registers */
+-#define SCC_UHC_CKRCTRL         0xff0
+-#define SCC_UHC_ECMODE          0xf00
+-
+-/* bits for SCC_UHC_CKRCTRL */
+-#define SCC_UHC_F48MCKLEN       0x00000001
+-#define SCC_UHC_P_SUSPEND       0x00000002
+-#define SCC_UHC_PHY_SUSPEND_SEL 0x00000004
+-#define SCC_UHC_HCLKEN          0x00000100
+-#define SCC_UHC_USBEN           0x00010000
+-#define SCC_UHC_USBCEN          0x00020000
+-#define SCC_UHC_PHYEN           0x00040000
+-
+-/* bits for SCC_UHC_ECMODE */
+-#define SCC_UHC_ECMODE_BY_BYTE  0x00000555
+-#define SCC_UHC_ECMODE_BY_WORD  0x00000aaa
+-
+-#endif /* _CELLEB_SCC_H */
+diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c
+deleted file mode 100644
+index a3c7cfb..0000000
+--- a/arch/powerpc/platforms/celleb/scc_epci.c
++++ /dev/null
+@@ -1,485 +0,0 @@
+-/*
+- * Support for SCC external PCI
+- *
+- * (C) Copyright 2004-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/kernel.h>
+-#include <linux/threads.h>
+-#include <linux/pci.h>
+-#include <linux/init.h>
+-#include <linux/pci_regs.h>
+-#include <linux/bootmem.h>
+-
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/ppc-pci.h>
+-
+-#include "scc.h"
+-#include "pci.h"
+-#include "interrupt.h"
+-
+-#define MAX_PCI_DEVICES   32
+-#define MAX_PCI_FUNCTIONS  8
+-
+-#define iob()  __asm__ __volatile__("eieio; sync":::"memory")
+-
+-struct epci_private {
+-	dma_addr_t	dummy_page_da;
+-};
+-
+-static inline PCI_IO_ADDR celleb_epci_get_epci_base(
+-					struct pci_controller *hose)
+-{
+-	/*
+-	 * Note:
+-	 * Celleb epci uses cfg_addr as a base address for
+-	 * epci control registers.
+-	 */
+-
+-	return hose->cfg_addr;
+-}
+-
+-static inline PCI_IO_ADDR celleb_epci_get_epci_cfg(
+-					struct pci_controller *hose)
+-{
+-	/*
+-	 * Note:
+-	 * Celleb epci uses cfg_data as a base address for
+-	 * configuration area for epci devices.
+-	 */
+-
+-	return hose->cfg_data;
+-}
+-
+-static void scc_epci_dummy_read(struct pci_controller *hose)
+-{
+-	PCI_IO_ADDR epci_base;
+-	u32 val;
+-
+-	epci_base = celleb_epci_get_epci_base(hose);
+-
+-	val = in_be32(epci_base + SCC_EPCI_WATRP);
+-	iosync();
+-
+-	return;
+-}
+-
+-void __init epci_workaround_init(struct pci_controller *hose)
+-{
+-	PCI_IO_ADDR epci_base;
+-	PCI_IO_ADDR reg;
+-	struct epci_private *private = hose->private_data;
+-
+-	BUG_ON(!private);
+-
+-	private->dummy_page_da = dma_map_single(hose->parent,
+-		celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE);
+-	if (private->dummy_page_da == DMA_ERROR_CODE) {
+-		printk(KERN_ERR "EPCI: dummy read disabled. "
+-		       "Map dummy page failed.\n");
+-		return;
+-	}
+-
+-	celleb_pci_add_one(hose, scc_epci_dummy_read);
+-	epci_base = celleb_epci_get_epci_base(hose);
+-
+-	reg = epci_base + SCC_EPCI_DUMYRADR;
+-	out_be32(reg, private->dummy_page_da);
+-}
+-
+-static inline void clear_and_disable_master_abort_interrupt(
+-					struct pci_controller *hose)
+-{
+-	PCI_IO_ADDR epci_base;
+-	PCI_IO_ADDR reg;
+-	epci_base = celleb_epci_get_epci_base(hose);
+-	reg = epci_base + PCI_COMMAND;
+-	out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16));
+-}
+-
+-static int celleb_epci_check_abort(struct pci_controller *hose,
+-				   PCI_IO_ADDR addr)
+-{
+-	PCI_IO_ADDR reg;
+-	PCI_IO_ADDR epci_base;
+-	u32 val;
+-
+-	iob();
+-	epci_base = celleb_epci_get_epci_base(hose);
+-
+-	reg = epci_base + PCI_COMMAND;
+-	val = in_be32(reg);
+-
+-	if (val & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+-		out_be32(reg,
+-			 (val & 0xffff) | (PCI_STATUS_REC_MASTER_ABORT << 16));
+-
+-		/* clear PCI Controller error, FRE, PMFE */
+-		reg = epci_base + SCC_EPCI_STATUS;
+-		out_be32(reg, SCC_EPCI_INT_PAI);
+-
+-		reg = epci_base + SCC_EPCI_VCSR;
+-		val = in_be32(reg) & 0xffff;
+-		val |= SCC_EPCI_VCSR_FRE;
+-		out_be32(reg, val);
+-
+-		reg = epci_base + SCC_EPCI_VISTAT;
+-		out_be32(reg, SCC_EPCI_VISTAT_PMFE);
+-		return PCIBIOS_DEVICE_NOT_FOUND;
+-	}
+-
+-	return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static PCI_IO_ADDR celleb_epci_make_config_addr(
+-					struct pci_bus *bus,
+-					struct pci_controller *hose,
+-					unsigned int devfn, int where)
+-{
+-	PCI_IO_ADDR addr;
+-
+-	if (bus != hose->bus)
+-		addr = celleb_epci_get_epci_cfg(hose) +
+-		       (((bus->number & 0xff) << 16)
+-		        | ((devfn & 0xff) << 8)
+-		        | (where & 0xff)
+-		        | 0x01000000);
+-	else
+-		addr = celleb_epci_get_epci_cfg(hose) +
+-		       (((devfn & 0xff) << 8) | (where & 0xff));
+-
+-	pr_debug("EPCI: config_addr = 0x%p\n", addr);
+-
+-	return addr;
+-}
+-
+-static int celleb_epci_read_config(struct pci_bus *bus,
+-			unsigned int devfn, int where, int size, u32 * val)
+-{
+-	PCI_IO_ADDR epci_base;
+-	PCI_IO_ADDR addr;
+-	struct device_node *node;
+-	struct pci_controller *hose;
+-
+-	/* allignment check */
+-	BUG_ON(where % size);
+-
+-	node = (struct device_node *)bus->sysdata;
+-	hose = pci_find_hose_for_OF_device(node);
+-
+-	if (!celleb_epci_get_epci_cfg(hose))
+-		return PCIBIOS_DEVICE_NOT_FOUND;
+-
+-	if (bus->number == hose->first_busno && devfn == 0) {
+-		/* EPCI controller self */
+-
+-		epci_base = celleb_epci_get_epci_base(hose);
+-		addr = epci_base + where;
+-
+-		switch (size) {
+-		case 1:
+-			*val = in_8(addr);
+-			break;
+-		case 2:
+-			*val = in_be16(addr);
+-			break;
+-		case 4:
+-			*val = in_be32(addr);
+-			break;
+-		default:
+-			return PCIBIOS_DEVICE_NOT_FOUND;
+-		}
+-
+-	} else {
+-
+-		clear_and_disable_master_abort_interrupt(hose);
+-		addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
+-
+-		switch (size) {
+-		case 1:
+-			*val = in_8(addr);
+-			break;
+-		case 2:
+-			*val = in_le16(addr);
+-			break;
+-		case 4:
+-			*val = in_le32(addr);
+-			break;
+-		default:
+-			return PCIBIOS_DEVICE_NOT_FOUND;
+-		}
+-	}
+-
+-	pr_debug("EPCI: "
+-		 "addr=0x%p, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
+-		 addr, devfn, where, size, *val);
+-
+-	return celleb_epci_check_abort(hose, NULL);
+-}
+-
+-static int celleb_epci_write_config(struct pci_bus *bus,
+-			unsigned int devfn, int where, int size, u32 val)
+-{
+-	PCI_IO_ADDR epci_base;
+-	PCI_IO_ADDR addr;
+-	struct device_node *node;
+-	struct pci_controller *hose;
+-
+-	/* allignment check */
+-	BUG_ON(where % size);
+-
+-	node = (struct device_node *)bus->sysdata;
+-	hose = pci_find_hose_for_OF_device(node);
+-
+-
+-	if (!celleb_epci_get_epci_cfg(hose))
+-		return PCIBIOS_DEVICE_NOT_FOUND;
+-
+-	if (bus->number == hose->first_busno && devfn == 0) {
+-		/* EPCI controller self */
+-
+-		epci_base = celleb_epci_get_epci_base(hose);
+-		addr = epci_base + where;
+-
+-		switch (size) {
+-		case 1:
+-			out_8(addr, val);
+-			break;
+-		case 2:
+-			out_be16(addr, val);
+-			break;
+-		case 4:
+-			out_be32(addr, val);
+-			break;
+-		default:
+-			return PCIBIOS_DEVICE_NOT_FOUND;
+-		}
+-
+-	} else {
+-
+-		clear_and_disable_master_abort_interrupt(hose);
+-		addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
+-
+-		switch (size) {
+-		case 1:
+-			out_8(addr, val);
+-			break;
+-		case 2:
+-			out_le16(addr, val);
+-			break;
+-		case 4:
+-			out_le32(addr, val);
+-			break;
+-		default:
+-			return PCIBIOS_DEVICE_NOT_FOUND;
+-		}
+-	}
+-
+-	return celleb_epci_check_abort(hose, addr);
+-}
+-
+-struct pci_ops celleb_epci_ops = {
+-	.read = celleb_epci_read_config,
+-	.write = celleb_epci_write_config,
+-};
+-
+-/* to be moved in FW */
+-static int __init celleb_epci_init(struct pci_controller *hose)
+-{
+-	u32 val;
+-	PCI_IO_ADDR reg;
+-	PCI_IO_ADDR epci_base;
+-	int hwres = 0;
+-
+-	epci_base = celleb_epci_get_epci_base(hose);
+-
+-	/* PCI core reset(Internal bus and PCI clock) */
+-	reg = epci_base + SCC_EPCI_CKCTRL;
+-	val = in_be32(reg);
+-	if (val == 0x00030101)
+-		hwres = 1;
+-	else {
+-		val &= ~(SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
+-		out_be32(reg, val);
+-
+-		/* set PCI core clock */
+-		val = in_be32(reg);
+-		val |= (SCC_EPCI_CKCTRL_OCLKEN | SCC_EPCI_CKCTRL_LCLKEN);
+-		out_be32(reg, val);
+-
+-		/* release PCI core reset (internal bus) */
+-		val = in_be32(reg);
+-		val |= SCC_EPCI_CKCTRL_CRST0;
+-		out_be32(reg, val);
+-
+-		/* set PCI clock select */
+-		reg = epci_base + SCC_EPCI_CLKRST;
+-		val = in_be32(reg);
+-		val &= ~SCC_EPCI_CLKRST_CKS_MASK;
+-		val |= SCC_EPCI_CLKRST_CKS_2;
+-		out_be32(reg, val);
+-
+-		/* set arbiter */
+-		reg = epci_base + SCC_EPCI_ABTSET;
+-		out_be32(reg, 0x0f1f001f);	/* temporary value */
+-
+-		/* buffer on */
+-		reg = epci_base + SCC_EPCI_CLKRST;
+-		val = in_be32(reg);
+-		val |= SCC_EPCI_CLKRST_BC;
+-		out_be32(reg, val);
+-
+-		/* PCI clock enable */
+-		val = in_be32(reg);
+-		val |= SCC_EPCI_CLKRST_PCKEN;
+-		out_be32(reg, val);
+-
+-		/* release PCI core reset (all) */
+-		reg = epci_base + SCC_EPCI_CKCTRL;
+-		val = in_be32(reg);
+-		val |= (SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
+-		out_be32(reg, val);
+-
+-		/* set base translation registers. (already set by Beat) */
+-
+-		/* set base address masks. (already set by Beat) */
+-	}
+-
+-	/* release interrupt masks and clear all interrupts */
+-	reg = epci_base + SCC_EPCI_INTSET;
+-	out_be32(reg, 0x013f011f);	/* all interrupts enable */
+-	reg = epci_base + SCC_EPCI_VIENAB;
+-	val = SCC_EPCI_VIENAB_PMPEE | SCC_EPCI_VIENAB_PMFEE;
+-	out_be32(reg, val);
+-	reg = epci_base + SCC_EPCI_STATUS;
+-	out_be32(reg, 0xffffffff);
+-	reg = epci_base + SCC_EPCI_VISTAT;
+-	out_be32(reg, 0xffffffff);
+-
+-	/* disable PCI->IB address translation */
+-	reg = epci_base + SCC_EPCI_VCSR;
+-	val = in_be32(reg);
+-	val &= ~(SCC_EPCI_VCSR_DR | SCC_EPCI_VCSR_AT);
+-	out_be32(reg, val);
+-
+-	/* set base addresses. (no need to set?) */
+-
+-	/* memory space, bus master enable */
+-	reg = epci_base + PCI_COMMAND;
+-	val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+-	out_be32(reg, val);
+-
+-	/* endian mode setup */
+-	reg = epci_base + SCC_EPCI_ECMODE;
+-	val = 0x00550155;
+-	out_be32(reg, val);
+-
+-	/* set control option */
+-	reg = epci_base + SCC_EPCI_CNTOPT;
+-	val = in_be32(reg);
+-	val |= SCC_EPCI_CNTOPT_O2PMB;
+-	out_be32(reg, val);
+-
+-	/* XXX: temporay: set registers for address conversion setup */
+-	reg = epci_base + SCC_EPCI_CNF10_REG;
+-	out_be32(reg, 0x80000008);
+-	reg = epci_base + SCC_EPCI_CNF14_REG;
+-	out_be32(reg, 0x40000008);
+-
+-	reg = epci_base + SCC_EPCI_BAM0;
+-	out_be32(reg, 0x80000000);
+-	reg = epci_base + SCC_EPCI_BAM1;
+-	out_be32(reg, 0xe0000000);
+-
+-	reg = epci_base + SCC_EPCI_PVBAT;
+-	out_be32(reg, 0x80000000);
+-
+-	if (!hwres) {
+-		/* release external PCI reset */
+-		reg = epci_base + SCC_EPCI_CLKRST;
+-		val = in_be32(reg);
+-		val |= SCC_EPCI_CLKRST_PCIRST;
+-		out_be32(reg, val);
+-	}
+-
+-	return 0;
+-}
+-
+-int __init celleb_setup_epci(struct device_node *node,
+-				struct pci_controller *hose)
+-{
+-	struct resource r;
+-
+-	pr_debug("PCI: celleb_setup_epci()\n");
+-
+-	/*
+-	 * Note:
+-	 * Celleb epci uses cfg_addr and cfg_data member of
+-	 * pci_controller structure in irregular way.
+-	 *
+-	 * cfg_addr is used to map for control registers of
+-	 * celleb epci.
+-	 *
+-	 * cfg_data is used for configuration area of devices
+-	 * on Celleb epci buses.
+-	 */
+-
+-	if (of_address_to_resource(node, 0, &r))
+-		goto error;
+-	hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1));
+-	if (!hose->cfg_addr)
+-		goto error;
+-	pr_debug("EPCI: cfg_addr map 0x%016lx->0x%016lx + 0x%016lx\n",
+-		 r.start, (unsigned long)hose->cfg_addr,
+-		(r.end - r.start + 1));
+-
+-	if (of_address_to_resource(node, 2, &r))
+-		goto error;
+-	hose->cfg_data = ioremap(r.start, (r.end - r.start + 1));
+-	if (!hose->cfg_data)
+-		goto error;
+-	pr_debug("EPCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n",
+-		 r.start, (unsigned long)hose->cfg_data,
+-		(r.end - r.start + 1));
+-
+-	hose->private_data = kzalloc(sizeof(struct epci_private), GFP_KERNEL);
+-	if (hose->private_data == NULL) {
+-		printk(KERN_ERR "EPCI: no memory for private data.\n");
+-		goto error;
+-	}
+-
+-	hose->ops = &celleb_epci_ops;
+-	celleb_epci_init(hose);
+-
+-	return 0;
+-
+-error:
+-	kfree(hose->private_data);
+-
+-	if (hose->cfg_addr)
+-		iounmap(hose->cfg_addr);
+-
+-	if (hose->cfg_data)
+-		iounmap(hose->cfg_data);
+-	return 1;
+-}
+diff --git a/arch/powerpc/platforms/celleb/scc_sio.c b/arch/powerpc/platforms/celleb/scc_sio.c
+deleted file mode 100644
+index 6100082..0000000
+--- a/arch/powerpc/platforms/celleb/scc_sio.c
++++ /dev/null
+@@ -1,101 +0,0 @@
+-/*
+- * setup serial port in SCC
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/tty.h>
+-#include <linux/serial.h>
+-#include <linux/serial_core.h>
+-#include <linux/console.h>
+-
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-
+-/* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024
+-    mmio=0xfff000-0x1000,0xff2000-0x1000 */
+-static int txx9_serial_bitmap __initdata = 0;
+-
+-static struct {
+-	uint32_t offset;
+-	uint32_t index;
+-} txx9_scc_tab[3] __initdata = {
+-	{ 0x300, 0 },	/* 0xFFF300 */
+-	{ 0x400, 0 },	/* 0xFFF400 */
+-	{ 0x800, 1 }	/* 0xFF2800 */
+-};
+-
+-static int __init txx9_serial_init(void)
+-{
+-	extern int early_serial_txx9_setup(struct uart_port *port);
+-	struct device_node *node = NULL;
+-	int i;
+-	struct uart_port req;
+-	struct of_irq irq;
+-	struct resource res;
+-
+-	while ((node = of_find_compatible_node(node,
+-				"serial", "toshiba,sio-scc")) != NULL) {
+-		for (i = 0; i < ARRAY_SIZE(txx9_scc_tab); i++) {
+-			if (!(txx9_serial_bitmap & (1<<i)))
+-				continue;
+-
+-			if (of_irq_map_one(node, i, &irq))
+-				continue;
+-			if (of_address_to_resource(node,
+-				txx9_scc_tab[i].index, &res))
+-				continue;
+-
+-			memset(&req, 0, sizeof(req));
+-			req.line = i;
+-			req.iotype = UPIO_MEM;
+-			req.mapbase = res.start + txx9_scc_tab[i].offset;
+-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
+-			req.membase = ioremap(req.mapbase, 0x24);
+-#endif
+-			req.irq = irq_create_of_mapping(irq.controller,
+-				irq.specifier, irq.size);
+-			req.flags |= UPF_IOREMAP | UPF_BUGGY_UART
+-				/*HAVE_CTS_LINE*/;
+-			req.uartclk = 83300000;
+-			early_serial_txx9_setup(&req);
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-static int __init txx9_serial_config(char *ptr)
+-{
+-	int	i;
+-
+-	for (;;) {
+-		switch(get_option(&ptr, &i)) {
+-		default:
+-			return 0;
+-		case 2:
+-			txx9_serial_bitmap |= 1 << i;
+-			break;
+-		case 1:
+-			txx9_serial_bitmap |= 1 << i;
+-			return 0;
+-		}
+-	}
+-}
+-__setup("txx9_serial=", txx9_serial_config);
+-
+-console_initcall(txx9_serial_init);
+diff --git a/arch/powerpc/platforms/celleb/scc_uhc.c b/arch/powerpc/platforms/celleb/scc_uhc.c
+deleted file mode 100644
+index cb43079..0000000
+--- a/arch/powerpc/platforms/celleb/scc_uhc.c
++++ /dev/null
+@@ -1,95 +0,0 @@
+-/*
+- * SCC (Super Companion Chip) UHC setup
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/pci.h>
+-
+-#include <asm/delay.h>
+-#include <asm/io.h>
+-#include <asm/machdep.h>
+-
+-#include "scc.h"
+-
+-#define UHC_RESET_WAIT_MAX 10000
+-
+-static inline int uhc_clkctrl_ready(u32 val)
+-{
+-	const u32 mask = SCC_UHC_USBCEN | SCC_UHC_USBCEN;
+-	return((val & mask) == mask);
+-}
+-
+-/*
+- * UHC(usb host controller) enable function.
+- * affect to both of OHCI and EHCI core module.
+- */
+-static void enable_scc_uhc(struct pci_dev *dev)
+-{
+-	void __iomem *uhc_base;
+-	u32 __iomem *uhc_clkctrl;
+-	u32 __iomem *uhc_ecmode;
+-	u32 val = 0;
+-	int i;
+-
+-	if (!machine_is(celleb_beat) &&
+-	    !machine_is(celleb_native))
+-		return;
+-
+-	uhc_base = ioremap(pci_resource_start(dev, 0),
+-			   pci_resource_len(dev, 0));
+-	if (!uhc_base) {
+-		printk(KERN_ERR "failed to map UHC register base.\n");
+-		return;
+-	}
+-	uhc_clkctrl = uhc_base + SCC_UHC_CKRCTRL;
+-	uhc_ecmode  = uhc_base + SCC_UHC_ECMODE;
+-
+-	/* setup for normal mode */
+-	val |= SCC_UHC_F48MCKLEN;
+-	out_be32(uhc_clkctrl, val);
+-	val |= SCC_UHC_PHY_SUSPEND_SEL;
+-	out_be32(uhc_clkctrl, val);
+-	udelay(10);
+-	val |= SCC_UHC_PHYEN;
+-	out_be32(uhc_clkctrl, val);
+-	udelay(50);
+-
+-	/* disable reset */
+-	val |= SCC_UHC_HCLKEN;
+-	out_be32(uhc_clkctrl, val);
+-	val |= (SCC_UHC_USBCEN | SCC_UHC_USBEN);
+-	out_be32(uhc_clkctrl, val);
+-	i = 0;
+-	while (!uhc_clkctrl_ready(in_be32(uhc_clkctrl))) {
+-		udelay(10);
+-		if (i++ > UHC_RESET_WAIT_MAX) {
+-			printk(KERN_ERR "Failed to disable UHC reset %x\n",
+-			       in_be32(uhc_clkctrl));
+-			break;
+-		}
+-	}
+-
+-	/* Endian Conversion Mode for Master ALL area */
+-	out_be32(uhc_ecmode, SCC_UHC_ECMODE_BY_BYTE);
+-
+-	iounmap(uhc_base);
+-}
+-
+-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
+-		 PCI_DEVICE_ID_TOSHIBA_SCC_USB, enable_scc_uhc);
+diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
+deleted file mode 100644
+index f27ae1e..0000000
+--- a/arch/powerpc/platforms/celleb/setup.c
++++ /dev/null
+@@ -1,258 +0,0 @@
+-/*
+- * Celleb setup code
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/cell/setup.c:
+- *  Copyright (C) 1995  Linus Torvalds
+- *  Adapted from 'alpha' version by Gary Thomas
+- *  Modified by Cort Dougan (cort at cs.nmt.edu)
+- *  Modified by PPC64 Team, IBM Corp
+- *  Modified by Cell Team, IBM Deutschland Entwicklung GmbH
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/cpu.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/stddef.h>
+-#include <linux/unistd.h>
+-#include <linux/reboot.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/irq.h>
+-#include <linux/seq_file.h>
+-#include <linux/root_dev.h>
+-#include <linux/console.h>
+-#include <linux/of_platform.h>
+-
+-#include <asm/mmu.h>
+-#include <asm/processor.h>
+-#include <asm/io.h>
+-#include <asm/kexec.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/cputable.h>
+-#include <asm/irq.h>
+-#include <asm/time.h>
+-#include <asm/spu_priv1.h>
+-#include <asm/firmware.h>
+-#include <asm/rtas.h>
+-#include <asm/cell-regs.h>
+-
+-#include "interrupt.h"
+-#include "beat_wrapper.h"
+-#include "beat.h"
+-#include "pci.h"
+-#include "../cell/interrupt.h"
+-#include "../cell/pervasive.h"
+-#include "../cell/ras.h"
+-
+-static char celleb_machine_type[128] = "Celleb";
+-
+-static void celleb_show_cpuinfo(struct seq_file *m)
+-{
+-	struct device_node *root;
+-	const char *model = "";
+-
+-	root = of_find_node_by_path("/");
+-	if (root)
+-		model = of_get_property(root, "model", NULL);
+-	/* using "CHRP" is to trick anaconda into installing FCx into Celleb */
+-	seq_printf(m, "machine\t\t: %s %s\n", celleb_machine_type, model);
+-	of_node_put(root);
+-}
+-
+-static int __init celleb_machine_type_hack(char *ptr)
+-{
+-	strncpy(celleb_machine_type, ptr, sizeof(celleb_machine_type));
+-	celleb_machine_type[sizeof(celleb_machine_type)-1] = 0;
+-	return 0;
+-}
+-
+-__setup("celleb_machine_type_hack=", celleb_machine_type_hack);
+-
+-static void celleb_progress(char *s, unsigned short hex)
+-{
+-	printk("*** %04x : %s\n", hex, s ? s : "");
+-}
+-
+-static void __init celleb_setup_arch_common(void)
+-{
+-	/* init to some ~sane value until calibrate_delay() runs */
+-	loops_per_jiffy = 50000000;
+-
+-#ifdef CONFIG_DUMMY_CONSOLE
+-	conswitchp = &dummy_con;
+-#endif
+-}
+-
+-static struct of_device_id celleb_bus_ids[] __initdata = {
+-	{ .type = "scc", },
+-	{ .type = "ioif", },	/* old style */
+-	{},
+-};
+-
+-static int __init celleb_publish_devices(void)
+-{
+-	/* Publish OF platform devices for southbridge IOs */
+-	of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
+-
+-	celleb_pci_workaround_init();
+-
+-	return 0;
+-}
+-machine_device_initcall(celleb_beat, celleb_publish_devices);
+-machine_device_initcall(celleb_native, celleb_publish_devices);
+-
+-
+-/*
+- * functions for Celleb-Beat
+- */
+-static void __init celleb_setup_arch_beat(void)
+-{
+-#ifdef CONFIG_SPU_BASE
+-	spu_priv1_ops		= &spu_priv1_beat_ops;
+-	spu_management_ops	= &spu_management_of_ops;
+-#endif
+-
+-#ifdef CONFIG_SMP
+-	smp_init_celleb();
+-#endif
+-
+-	celleb_setup_arch_common();
+-}
+-
+-static int __init celleb_probe_beat(void)
+-{
+-	unsigned long root = of_get_flat_dt_root();
+-
+-	if (!of_flat_dt_is_compatible(root, "Beat"))
+-		return 0;
+-
+-	powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
+-		| FW_FEATURE_BEAT | FW_FEATURE_LPAR;
+-	hpte_init_beat_v3();
+-
+-	return 1;
+-}
+-
+-
+-/*
+- * functions for Celleb-native
+- */
+-static void __init celleb_init_IRQ_native(void)
+-{
+-	iic_init_IRQ();
+-	spider_init_IRQ();
+-}
+-
+-static void __init celleb_setup_arch_native(void)
+-{
+-#ifdef CONFIG_SPU_BASE
+-	spu_priv1_ops		= &spu_priv1_mmio_ops;
+-	spu_management_ops	= &spu_management_of_ops;
+-#endif
+-
+-	cbe_regs_init();
+-
+-#ifdef CONFIG_CBE_RAS
+-	cbe_ras_init();
+-#endif
+-
+-#ifdef CONFIG_SMP
+-	smp_init_cell();
+-#endif
+-
+-	cbe_pervasive_init();
+-
+-	/* XXX: nvram initialization should be added */
+-
+-	celleb_setup_arch_common();
+-}
+-
+-static int __init celleb_probe_native(void)
+-{
+-	unsigned long root = of_get_flat_dt_root();
+-
+-	if (of_flat_dt_is_compatible(root, "Beat") ||
+-	    !of_flat_dt_is_compatible(root, "TOSHIBA,Celleb"))
+-		return 0;
+-
+-	powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
+-	hpte_init_native();
+-
+-	return 1;
+-}
+-
+-
+-/*
+- * machine definitions
+- */
+-define_machine(celleb_beat) {
+-	.name			= "Cell Reference Set (Beat)",
+-	.probe			= celleb_probe_beat,
+-	.setup_arch		= celleb_setup_arch_beat,
+-	.show_cpuinfo		= celleb_show_cpuinfo,
+-	.restart		= beat_restart,
+-	.power_off		= beat_power_off,
+-	.halt			= beat_halt,
+-	.get_rtc_time		= beat_get_rtc_time,
+-	.set_rtc_time		= beat_set_rtc_time,
+-	.calibrate_decr		= generic_calibrate_decr,
+-	.progress		= celleb_progress,
+-	.power_save		= beat_power_save,
+-	.nvram_size		= beat_nvram_get_size,
+-	.nvram_read		= beat_nvram_read,
+-	.nvram_write		= beat_nvram_write,
+-	.set_dabr		= beat_set_xdabr,
+-	.init_IRQ		= beatic_init_IRQ,
+-	.get_irq		= beatic_get_irq,
+-	.pci_probe_mode 	= celleb_pci_probe_mode,
+-	.pci_setup_phb		= celleb_setup_phb,
+-#ifdef CONFIG_KEXEC
+-	.kexec_cpu_down		= beat_kexec_cpu_down,
+-	.machine_kexec		= default_machine_kexec,
+-	.machine_kexec_prepare	= default_machine_kexec_prepare,
+-	.machine_crash_shutdown	= default_machine_crash_shutdown,
+-#endif
+-};
+-
+-define_machine(celleb_native) {
+-	.name			= "Cell Reference Set (native)",
+-	.probe			= celleb_probe_native,
+-	.setup_arch		= celleb_setup_arch_native,
+-	.show_cpuinfo		= celleb_show_cpuinfo,
+-	.restart		= rtas_restart,
+-	.power_off		= rtas_power_off,
+-	.halt			= rtas_halt,
+-	.get_boot_time		= rtas_get_boot_time,
+-	.get_rtc_time		= rtas_get_rtc_time,
+-	.set_rtc_time		= rtas_set_rtc_time,
+-	.calibrate_decr		= generic_calibrate_decr,
+-	.progress		= celleb_progress,
+-	.pci_probe_mode 	= celleb_pci_probe_mode,
+-	.pci_setup_phb		= celleb_setup_phb,
+-	.init_IRQ		= celleb_init_IRQ_native,
+-#ifdef CONFIG_KEXEC
+-	.machine_kexec		= default_machine_kexec,
+-	.machine_kexec_prepare	= default_machine_kexec_prepare,
+-	.machine_crash_shutdown	= default_machine_crash_shutdown,
+-#endif
+-};
+diff --git a/arch/powerpc/platforms/celleb/smp.c b/arch/powerpc/platforms/celleb/smp.c
+deleted file mode 100644
+index a763125..0000000
+--- a/arch/powerpc/platforms/celleb/smp.c
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/*
+- * SMP support for Celleb platform. (Incomplete)
+- *
+- * (C) Copyright 2006 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/cell/smp.c:
+- * Dave Engebretsen, Peter Bergner, and
+- * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+- * Plus various changes from other IBM teams...
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU 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.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/kernel.h>
+-#include <linux/smp.h>
+-#include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/threads.h>
+-#include <linux/cpu.h>
+-
+-#include <asm/irq.h>
+-#include <asm/smp.h>
+-#include <asm/machdep.h>
+-#include <asm/udbg.h>
+-
+-#include "interrupt.h"
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/*
+- * The primary thread of each non-boot processor is recorded here before
+- * smp init.
+- */
+-/* static cpumask_t of_spin_map; */
+-
+-/**
+- * smp_startup_cpu() - start the given cpu
+- *
+- * At boot time, there is nothing to do for primary threads which were
+- * started from Open Firmware.  For anything else, call RTAS with the
+- * appropriate start location.
+- *
+- * Returns:
+- *	0	- failure
+- *	1	- success
+- */
+-static inline int __devinit smp_startup_cpu(unsigned int lcpu)
+-{
+-	return 0;
+-}
+-
+-static void smp_beatic_message_pass(int target, int msg)
+-{
+-	unsigned int i;
+-
+-	if (target < NR_CPUS) {
+-		beatic_cause_IPI(target, msg);
+-	} else {
+-		for_each_online_cpu(i) {
+-			if (target == MSG_ALL_BUT_SELF
+-			    && i == smp_processor_id())
+-				continue;
+-			beatic_cause_IPI(i, msg);
+-		}
+-	}
+-}
+-
+-static int __init smp_beatic_probe(void)
+-{
+-	return cpus_weight(cpu_possible_map);
+-}
+-
+-static void __devinit smp_beatic_setup_cpu(int cpu)
+-{
+-	beatic_setup_cpu(cpu);
+-}
+-
+-static void __devinit smp_celleb_kick_cpu(int nr)
+-{
+-	BUG_ON(nr < 0 || nr >= NR_CPUS);
+-
+-	if (!smp_startup_cpu(nr))
+-		return;
+-}
+-
+-static int smp_celleb_cpu_bootable(unsigned int nr)
+-{
+-	return 1;
+-}
+-static struct smp_ops_t bpa_beatic_smp_ops = {
+-	.message_pass	= smp_beatic_message_pass,
+-	.probe		= smp_beatic_probe,
+-	.kick_cpu	= smp_celleb_kick_cpu,
+-	.setup_cpu	= smp_beatic_setup_cpu,
+-	.cpu_bootable	= smp_celleb_cpu_bootable,
+-};
+-
+-/* This is called very early */
+-void __init smp_init_celleb(void)
+-{
+-	DBG(" -> smp_init_celleb()\n");
+-
+-	smp_ops = &bpa_beatic_smp_ops;
+-
+-	DBG(" <- smp_init_celleb()\n");
+-}
+diff --git a/arch/powerpc/platforms/celleb/spu_priv1.c b/arch/powerpc/platforms/celleb/spu_priv1.c
+deleted file mode 100644
+index 2bf6700..0000000
+--- a/arch/powerpc/platforms/celleb/spu_priv1.c
++++ /dev/null
+@@ -1,208 +0,0 @@
+-/*
+- * spu hypervisor abstraction for Beat
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/module.h>
+-
+-#include <asm/types.h>
+-#include <asm/spu.h>
+-#include <asm/spu_priv1.h>
+-
+-#include "beat_wrapper.h"
+-
+-static inline void _int_mask_set(struct spu *spu, int class, u64 mask)
+-{
+-	spu->shadow_int_mask_RW[class] = mask;
+-	beat_set_irq_mask_for_spe(spu->spe_id, class, mask);
+-}
+-
+-static inline u64 _int_mask_get(struct spu *spu, int class)
+-{
+-	return spu->shadow_int_mask_RW[class];
+-}
+-
+-static void int_mask_set(struct spu *spu, int class, u64 mask)
+-{
+-	_int_mask_set(spu, class, mask);
+-}
+-
+-static u64 int_mask_get(struct spu *spu, int class)
+-{
+-	return _int_mask_get(spu, class);
+-}
+-
+-static void int_mask_and(struct spu *spu, int class, u64 mask)
+-{
+-	u64 old_mask;
+-	old_mask = _int_mask_get(spu, class);
+-	_int_mask_set(spu, class, old_mask & mask);
+-}
+-
+-static void int_mask_or(struct spu *spu, int class, u64 mask)
+-{
+-	u64 old_mask;
+-	old_mask = _int_mask_get(spu, class);
+-	_int_mask_set(spu, class, old_mask | mask);
+-}
+-
+-static void int_stat_clear(struct spu *spu, int class, u64 stat)
+-{
+-	beat_clear_interrupt_status_of_spe(spu->spe_id, class, stat);
+-}
+-
+-static u64 int_stat_get(struct spu *spu, int class)
+-{
+-	u64 int_stat;
+-	beat_get_interrupt_status_of_spe(spu->spe_id, class, &int_stat);
+-	return int_stat;
+-}
+-
+-static void cpu_affinity_set(struct spu *spu, int cpu)
+-{
+-	return;
+-}
+-
+-static u64 mfc_dar_get(struct spu *spu)
+-{
+-	u64 dar;
+-	beat_get_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, mfc_dar_RW), &dar);
+-	return dar;
+-}
+-
+-static u64 mfc_dsisr_get(struct spu *spu)
+-{
+-	u64 dsisr;
+-	beat_get_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, mfc_dsisr_RW), &dsisr);
+-	return dsisr;
+-}
+-
+-static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
+-{
+-	beat_set_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, mfc_dsisr_RW), dsisr);
+-}
+-
+-static void mfc_sdr_setup(struct spu *spu)
+-{
+-	return;
+-}
+-
+-static void mfc_sr1_set(struct spu *spu, u64 sr1)
+-{
+-	beat_set_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, mfc_sr1_RW), sr1);
+-}
+-
+-static u64 mfc_sr1_get(struct spu *spu)
+-{
+-	u64 sr1;
+-	beat_get_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, mfc_sr1_RW), &sr1);
+-	return sr1;
+-}
+-
+-static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
+-{
+-	beat_set_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, mfc_tclass_id_RW), tclass_id);
+-}
+-
+-static u64 mfc_tclass_id_get(struct spu *spu)
+-{
+-	u64 tclass_id;
+-	beat_get_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, mfc_tclass_id_RW), &tclass_id);
+-	return tclass_id;
+-}
+-
+-static void tlb_invalidate(struct spu *spu)
+-{
+-	beat_set_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, tlb_invalidate_entry_W), 0ul);
+-}
+-
+-static void resource_allocation_groupID_set(struct spu *spu, u64 id)
+-{
+-	beat_set_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, resource_allocation_groupID_RW),
+-		id);
+-}
+-
+-static u64 resource_allocation_groupID_get(struct spu *spu)
+-{
+-	u64 id;
+-	beat_get_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, resource_allocation_groupID_RW),
+-		&id);
+-	return id;
+-}
+-
+-static void resource_allocation_enable_set(struct spu *spu, u64 enable)
+-{
+-	beat_set_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, resource_allocation_enable_RW),
+-		enable);
+-}
+-
+-static u64 resource_allocation_enable_get(struct spu *spu)
+-{
+-	u64 enable;
+-	beat_get_spe_privileged_state_1_registers(
+-		spu->spe_id,
+-		offsetof(struct spu_priv1, resource_allocation_enable_RW),
+-		&enable);
+-	return enable;
+-}
+-
+-const struct spu_priv1_ops spu_priv1_beat_ops =
+-{
+-	.int_mask_and = int_mask_and,
+-	.int_mask_or = int_mask_or,
+-	.int_mask_set = int_mask_set,
+-	.int_mask_get = int_mask_get,
+-	.int_stat_clear = int_stat_clear,
+-	.int_stat_get = int_stat_get,
+-	.cpu_affinity_set = cpu_affinity_set,
+-	.mfc_dar_get = mfc_dar_get,
+-	.mfc_dsisr_get = mfc_dsisr_get,
+-	.mfc_dsisr_set = mfc_dsisr_set,
+-	.mfc_sdr_setup = mfc_sdr_setup,
+-	.mfc_sr1_set = mfc_sr1_set,
+-	.mfc_sr1_get = mfc_sr1_get,
+-	.mfc_tclass_id_set = mfc_tclass_id_set,
+-	.mfc_tclass_id_get = mfc_tclass_id_get,
+-	.tlb_invalidate = tlb_invalidate,
+-	.resource_allocation_groupID_set = resource_allocation_groupID_set,
+-	.resource_allocation_groupID_get = resource_allocation_groupID_get,
+-	.resource_allocation_enable_set = resource_allocation_enable_set,
+-	.resource_allocation_enable_get = resource_allocation_enable_get,
+-};
+diff --git a/arch/powerpc/platforms/celleb/udbg_beat.c b/arch/powerpc/platforms/celleb/udbg_beat.c
+deleted file mode 100644
+index d888c46..0000000
+--- a/arch/powerpc/platforms/celleb/udbg_beat.c
++++ /dev/null
+@@ -1,97 +0,0 @@
+-/*
+- * udbg function for Beat
+- *
+- * (C) Copyright 2006 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/console.h>
+-
+-#include <asm/machdep.h>
+-#include <asm/prom.h>
+-#include <asm/udbg.h>
+-
+-#include "beat.h"
+-
+-#define	celleb_vtermno	0
+-
+-static void udbg_putc_beat(char c)
+-{
+-	unsigned long rc;
+-
+-	if (c == '\n')
+-		udbg_putc_beat('\r');
+-
+-	rc = beat_put_term_char(celleb_vtermno, 1, (uint64_t)c << 56, 0);
+-}
+-
+-/* Buffered chars getc */
+-static long inbuflen;
+-static long inbuf[2];	/* must be 2 longs */
+-
+-static int udbg_getc_poll_beat(void)
+-{
+-	/* The interface is tricky because it may return up to 16 chars.
+-	 * We save them statically for future calls to udbg_getc().
+-	 */
+-	char ch, *buf = (char *)inbuf;
+-	int i;
+-	long rc;
+-	if (inbuflen == 0) {
+-		/* get some more chars. */
+-		inbuflen = 0;
+-		rc = beat_get_term_char(celleb_vtermno, &inbuflen, inbuf+0, inbuf+1);
+-		if (rc != 0)
+-			inbuflen = 0;	/* otherwise inbuflen is garbage */
+-	}
+-	if (inbuflen <= 0 || inbuflen > 16) {
+-		/* Catch error case as well as other oddities (corruption) */
+-		inbuflen = 0;
+-		return -1;
+-	}
+-	ch = buf[0];
+-	for (i = 1; i < inbuflen; i++)	/* shuffle them down. */
+-		buf[i-1] = buf[i];
+-	inbuflen--;
+-	return ch;
+-}
+-
+-static int udbg_getc_beat(void)
+-{
+-	int ch;
+-	for (;;) {
+-		ch = udbg_getc_poll_beat();
+-		if (ch == -1) {
+-			/* This shouldn't be needed...but... */
+-			volatile unsigned long delay;
+-			for (delay=0; delay < 2000000; delay++)
+-				;
+-		} else {
+-			return ch;
+-		}
+-	}
+-}
+-
+-/* call this from early_init() for a working debug console on
+- * vterm capable LPAR machines
+- */
+-void __init udbg_init_debug_beat(void)
+-{
+-	udbg_putc = udbg_putc_beat;
+-	udbg_getc = udbg_getc_beat;
+-	udbg_getc_poll = udbg_getc_poll_beat;
+-}
+diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+index d4f8bf5..84e2d78 100644
+--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
++++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+@@ -117,11 +117,11 @@ static void __init mpc7448_hpc2_init_IRQ(void)
+ 	}
+ 
+ 	if (mpic_paddr == 0) {
+-		printk("%s: No tsi108 PIC found !\n", __FUNCTION__);
++		printk("%s: No tsi108 PIC found !\n", __func__);
+ 		return;
+ 	}
+ 
+-	DBG("%s: tsi108 pic phys_addr = 0x%x\n", __FUNCTION__,
++	DBG("%s: tsi108 pic phys_addr = 0x%x\n", __func__,
+ 	    (u32) mpic_paddr);
+ 
+ 	mpic = mpic_alloc(tsi_pic, mpic_paddr,
+@@ -140,17 +140,17 @@ static void __init mpc7448_hpc2_init_IRQ(void)
+ #ifdef CONFIG_PCI
+ 	tsi_pci = of_find_node_by_type(NULL, "pci");
+ 	if (tsi_pci == NULL) {
+-		printk("%s: No tsi108 pci node found !\n", __FUNCTION__);
++		printk("%s: No tsi108 pci node found !\n", __func__);
+ 		return;
+ 	}
+ 	cascade_node = of_find_node_by_type(NULL, "pic-router");
+ 	if (cascade_node == NULL) {
+-		printk("%s: No tsi108 pci cascade node found !\n", __FUNCTION__);
++		printk("%s: No tsi108 pci cascade node found !\n", __func__);
+ 		return;
+ 	}
+ 
+ 	cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
+-	DBG("%s: tsi108 cascade_pci_irq = 0x%x\n", __FUNCTION__,
++	DBG("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__,
+ 	    (u32) cascade_pci_irq);
+ 	tsi108_pci_int_init(cascade_node);
+ 	set_irq_data(cascade_pci_irq, mpic);
+diff --git a/arch/powerpc/platforms/embedded6xx/prpmc2800.c b/arch/powerpc/platforms/embedded6xx/prpmc2800.c
+index 653a5eb..5a19b9a 100644
+--- a/arch/powerpc/platforms/embedded6xx/prpmc2800.c
++++ b/arch/powerpc/platforms/embedded6xx/prpmc2800.c
+@@ -49,13 +49,13 @@ static void __init prpmc2800_setup_arch(void)
+ 	 * ioremap mpp and gpp registers in case they are later
+ 	 * needed by prpmc2800_reset_board().
+ 	 */
+-	np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-mpp");
++	np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-mpp");
+ 	reg = of_get_property(np, "reg", NULL);
+ 	paddr = of_translate_address(np, reg);
+ 	of_node_put(np);
+ 	mv64x60_mpp_reg_base = ioremap(paddr, reg[1]);
+ 
+-	np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-gpp");
++	np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-gpp");
+ 	reg = of_get_property(np, "reg", NULL);
+ 	paddr = of_translate_address(np, reg);
+ 	of_node_put(np);
+diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S
+index 5381038..8ff330d 100644
+--- a/arch/powerpc/platforms/iseries/exception.S
++++ b/arch/powerpc/platforms/iseries/exception.S
+@@ -38,11 +38,19 @@
+ 
+ 	.globl system_reset_iSeries
+ system_reset_iSeries:
+-	mfspr	r13,SPRN_SPRG3		/* Get paca address */
++	mfspr	r13,SPRN_SPRG3		/* Get alpaca address */
++	LOAD_REG_IMMEDIATE(r23, alpaca)
++	li	r0,ALPACA_SIZE
++	sub	r23,r13,r23
++	divdu	r23,r23,r0		/* r23 has cpu number */
++	LOAD_REG_IMMEDIATE(r13, paca)
++	mulli	r0,r23,PACA_SIZE
++	add	r13,r13,r0
++	mtspr	SPRN_SPRG3,r13		/* Save it away for the future */
+ 	mfmsr	r24
+ 	ori	r24,r24,MSR_RI
+ 	mtmsrd	r24			/* RI on */
+-	lhz	r24,PACAPACAINDEX(r13)	/* Get processor # */
++	mr	r24,r23
+ 	cmpwi	0,r24,0			/* Are we processor 0? */
+ 	bne	1f
+ 	b	.__start_initialization_iSeries	/* Start up the first processor */
+@@ -51,8 +59,33 @@ system_reset_iSeries:
+ 	andc	r4,r4,r5
+ 	mtspr	SPRN_CTRLT,r4
+ 
++/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
++/* In the UP case we'll yeild() later, and we will not access the paca anyway */
++#ifdef CONFIG_SMP
+ 1:
+ 	HMT_LOW
++	LOAD_REG_IMMEDIATE(r23, __secondary_hold_spinloop)
++	ld	r23,0(r23)
++	sync
++	LOAD_REG_IMMEDIATE(r3,current_set)
++	sldi	r28,r24,3		/* get current_set[cpu#] */
++	ldx	r3,r3,r28
++	addi	r1,r3,THREAD_SIZE
++	subi	r1,r1,STACK_FRAME_OVERHEAD
++
++	cmpwi	0,r23,0			/* Keep poking the Hypervisor until */
++	bne	2f			/* we're released */
++	/* Let the Hypervisor know we are alive */
++	/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
++	lis	r3,0x8002
++	rldicr	r3,r3,32,15		/* r0 = (r3 << 32) & 0xffff000000000000 */
++	li	r0,-1			/* r0=-1 indicates a Hypervisor call */
++	sc				/* Invoke the hypervisor via a system call */
++	b	1b
++#endif
++
++2:
++	HMT_LOW
+ #ifdef CONFIG_SMP
+ 	lbz	r23,PACAPROCSTART(r13)	/* Test if this processor
+ 					 * should start */
+@@ -83,7 +116,7 @@ iSeries_secondary_smp_loop:
+ 	li	r0,-1			/* r0=-1 indicates a Hypervisor call */
+ 	sc				/* Invoke the hypervisor via a system call */
+ 	mfspr	r13,SPRN_SPRG3		/* Put r13 back ???? */
+-	b	1b			/* If SMP not configured, secondaries
++	b	2b			/* If SMP not configured, secondaries
+ 					 * loop forever */
+ 
+ /***  ISeries-LPAR interrupt handlers ***/
+diff --git a/arch/powerpc/platforms/iseries/ipl_parms.h b/arch/powerpc/platforms/iseries/ipl_parms.h
+index 77c135d..83e4ca4 100644
+--- a/arch/powerpc/platforms/iseries/ipl_parms.h
++++ b/arch/powerpc/platforms/iseries/ipl_parms.h
+@@ -65,6 +65,4 @@ struct ItIplParmsReal {
+ 	u64	xRsvd13;		// Reserved			x38-x3F
+ };
+ 
+-extern struct ItIplParmsReal	xItIplParmsReal;
+-
+ #endif /* _ISERIES_IPL_PARMS_H */
+diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c
+index 8162049..98bd2d3 100644
+--- a/arch/powerpc/platforms/iseries/lpardata.c
++++ b/arch/powerpc/platforms/iseries/lpardata.c
+@@ -14,10 +14,10 @@
+ #include <asm/ptrace.h>
+ #include <asm/abs_addr.h>
+ #include <asm/lppaca.h>
+-#include <asm/iseries/it_lp_reg_save.h>
+ #include <asm/paca.h>
+ #include <asm/iseries/lpar_map.h>
+ #include <asm/iseries/it_lp_queue.h>
++#include <asm/iseries/alpaca.h>
+ 
+ #include "naca.h"
+ #include "vpd_areas.h"
+@@ -31,7 +31,7 @@
+ /* The HvReleaseData is the root of the information shared between
+  * the hypervisor and Linux.
+  */
+-struct HvReleaseData hvReleaseData = {
++const struct HvReleaseData hvReleaseData = {
+ 	.xDesc = 0xc8a5d9c4,	/* "HvRD" ebcdic */
+ 	.xSize = sizeof(struct HvReleaseData),
+ 	.xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
+@@ -61,6 +61,63 @@ struct naca_struct naca = {
+ 	.xRamDiskSize = 0,
+ };
+ 
++struct ItLpRegSave {
++	u32	xDesc;		// Eye catcher  "LpRS" ebcdic	000-003
++	u16	xSize;		// Size of this class		004-005
++	u8	xInUse;         // Area is live                 006-007
++	u8	xRsvd1[9];	// Reserved			007-00F
++
++	u8      xFixedRegSave[352]; // Fixed Register Save Area 010-16F
++	u32	xCTRL;		// Control Register		170-173
++	u32	xDEC;		// Decrementer			174-177
++	u32	xFPSCR;		// FP Status and Control Reg	178-17B
++	u32	xPVR;		// Processor Version Number	17C-17F
++
++	u64	xMMCR0;		// Monitor Mode Control Reg 0	180-187
++	u32	xPMC1;		// Perf Monitor Counter 1	188-18B
++	u32	xPMC2;		// Perf Monitor Counter 2	18C-18F
++	u32	xPMC3;		// Perf Monitor Counter 3	190-193
++	u32	xPMC4;		// Perf Monitor Counter 4	194-197
++	u32	xPIR;		// Processor ID Reg		198-19B
++
++	u32	xMMCR1;		// Monitor Mode Control Reg 1	19C-19F
++	u32	xMMCRA;		// Monitor Mode Control Reg A	1A0-1A3
++	u32	xPMC5;		// Perf Monitor Counter 5	1A4-1A7
++	u32	xPMC6;		// Perf Monitor Counter 6	1A8-1AB
++	u32	xPMC7;		// Perf Monitor Counter 7	1AC-1AF
++	u32	xPMC8;		// Perf Monitor Counter 8	1B0-1B3
++	u32	xTSC;		// Thread Switch Control	1B4-1B7
++	u32	xTST;		// Thread Switch Timeout	1B8-1BB
++	u32	xRsvd;          // Reserved                     1BC-1BF
++
++	u64	xACCR;		// Address Compare Control Reg	1C0-1C7
++	u64	xIMR;		// Instruction Match Register	1C8-1CF
++	u64	xSDR1;		// Storage Description Reg 1	1D0-1D7
++	u64	xSPRG0;		// Special Purpose Reg General0	1D8-1DF
++	u64	xSPRG1;		// Special Purpose Reg General1	1E0-1E7
++	u64	xSPRG2;		// Special Purpose Reg General2	1E8-1EF
++	u64	xSPRG3;		// Special Purpose Reg General3	1F0-1F7
++	u64	xTB;		// Time Base Register		1F8-1FF
++
++	u64	xFPR[32];	// Floating Point Registers	200-2FF
++
++	u64	xMSR;		// Machine State Register	300-307
++	u64	xNIA;		// Next Instruction Address	308-30F
++
++	u64	xDABR;		// Data Address Breakpoint Reg	310-317
++	u64	xIABR;		// Inst Address Breakpoint Reg	318-31F
++
++	u64	xHID0;		// HW Implementation Dependent0	320-327
++
++	u64	xHID4;		// HW Implementation Dependent4	328-32F
++	u64	xSCOMd;		// SCON Data Reg (SPRG4)	330-337
++	u64	xSCOMc;		// SCON Command Reg (SPRG5)	338-33F
++	u64	xSDAR;		// Sample Data Address Register	340-347
++	u64	xSIAR;		// Sample Inst Address Register	348-34F
++
++	u8	xRsvd3[176];	// Reserved			350-3FF
++};
++
+ extern void system_reset_iSeries(void);
+ extern void machine_check_iSeries(void);
+ extern void data_access_iSeries(void);
+@@ -129,7 +186,7 @@ struct ItLpNaca itLpNaca = {
+ };
+ 
+ /* May be filled in by the hypervisor so cannot end up in the BSS */
+-struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data")));
++static struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data")));
+ 
+ /* May be filled in by the hypervisor so cannot end up in the BSS */
+ struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data")));
+@@ -152,13 +209,54 @@ u64    xMsVpd[3400] __attribute__((__section__(".data")));
+ 
+ /* Space for Recovery Log Buffer */
+ /* May be filled in by the hypervisor so cannot end up in the BSS */
+-u64    xRecoveryLogBuffer[32] __attribute__((__section__(".data")));
++static u64    xRecoveryLogBuffer[32] __attribute__((__section__(".data")));
+ 
+-struct SpCommArea xSpCommArea = {
++static const struct SpCommArea xSpCommArea = {
+ 	.xDesc = 0xE2D7C3C2,
+ 	.xFormat = 1,
+ };
+ 
++static const struct ItLpRegSave iseries_reg_save[] = {
++	[0 ... (NR_CPUS-1)] = {
++		.xDesc = 0xd397d9e2,	/* "LpRS" */
++		.xSize = sizeof(struct ItLpRegSave),
++	},
++};
++
++#define ALPACA_INIT(number)						\
++{									\
++	.lppaca_ptr = &lppaca[number],					\
++	.reg_save_ptr = &iseries_reg_save[number],			\
++}
++
++const struct alpaca alpaca[] = {
++	ALPACA_INIT( 0),
++#if NR_CPUS > 1
++	ALPACA_INIT( 1), ALPACA_INIT( 2), ALPACA_INIT( 3),
++#if NR_CPUS > 4
++	ALPACA_INIT( 4), ALPACA_INIT( 5), ALPACA_INIT( 6), ALPACA_INIT( 7),
++#if NR_CPUS > 8
++	ALPACA_INIT( 8), ALPACA_INIT( 9), ALPACA_INIT(10), ALPACA_INIT(11),
++	ALPACA_INIT(12), ALPACA_INIT(13), ALPACA_INIT(14), ALPACA_INIT(15),
++	ALPACA_INIT(16), ALPACA_INIT(17), ALPACA_INIT(18), ALPACA_INIT(19),
++	ALPACA_INIT(20), ALPACA_INIT(21), ALPACA_INIT(22), ALPACA_INIT(23),
++	ALPACA_INIT(24), ALPACA_INIT(25), ALPACA_INIT(26), ALPACA_INIT(27),
++	ALPACA_INIT(28), ALPACA_INIT(29), ALPACA_INIT(30), ALPACA_INIT(31),
++#if NR_CPUS > 32
++	ALPACA_INIT(32), ALPACA_INIT(33), ALPACA_INIT(34), ALPACA_INIT(35),
++	ALPACA_INIT(36), ALPACA_INIT(37), ALPACA_INIT(38), ALPACA_INIT(39),
++	ALPACA_INIT(40), ALPACA_INIT(41), ALPACA_INIT(42), ALPACA_INIT(43),
++	ALPACA_INIT(44), ALPACA_INIT(45), ALPACA_INIT(46), ALPACA_INIT(47),
++	ALPACA_INIT(48), ALPACA_INIT(49), ALPACA_INIT(50), ALPACA_INIT(51),
++	ALPACA_INIT(52), ALPACA_INIT(53), ALPACA_INIT(54), ALPACA_INIT(55),
++	ALPACA_INIT(56), ALPACA_INIT(57), ALPACA_INIT(58), ALPACA_INIT(59),
++	ALPACA_INIT(60), ALPACA_INIT(61), ALPACA_INIT(62), ALPACA_INIT(63),
++#endif
++#endif
++#endif
++#endif
++};
++
+ /* The LparMap data is now located at offset 0x6000 in head.S
+  * It was put there so that the HvReleaseData could address it
+  * with a 32-bit offset as required by the iSeries hypervisor
+@@ -167,7 +265,7 @@ struct SpCommArea xSpCommArea = {
+  * the Naca via the HvReleaseData area.  The HvReleaseData has the
+  * offset into the Naca of the pointer to the ItVpdAreas.
+  */
+-struct ItVpdAreas itVpdAreas = {
++const struct ItVpdAreas itVpdAreas = {
+ 	.xSlicDesc = 0xc9a3e5c1,		/* "ItVA" */
+ 	.xSlicSize = sizeof(struct ItVpdAreas),
+ 	.xSlicVpdEntries = ItVpdMaxEntries,	/* # VPD array entries */
+@@ -185,7 +283,7 @@ struct ItVpdAreas itVpdAreas = {
+ 	.xSlicVpdLens = {			/* VPD lengths */
+ 	        0,0,0,		        /*  0 - 2 */
+ 		sizeof(xItExtVpdPanel), /*       3 Extended VPD   */
+-		sizeof(struct paca_struct),	/*       4 length of Paca  */
++		sizeof(struct alpaca),	/*       4 length of (fake) Paca  */
+ 		0,			/*       5 */
+ 		sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */
+ 		26992,			/*	 7 length of MS VPD */
+@@ -203,7 +301,7 @@ struct ItVpdAreas itVpdAreas = {
+ 	.xSlicVpdAdrs = {			/* VPD addresses */
+ 		0,0,0,			/*	 0 -  2 */
+ 		&xItExtVpdPanel,        /*       3 Extended VPD */
+-		&paca[0],		/*       4 first Paca */
++		&alpaca[0],		/*       4 first (fake) Paca */
+ 		0,			/*       5 */
+ 		&xItIplParmsReal,	/*	 6 IPL parms */
+ 		&xMsVpd,		/*	 7 MS Vpd */
+@@ -219,10 +317,3 @@ struct ItVpdAreas itVpdAreas = {
+ 		0,0
+ 	}
+ };
+-
+-struct ItLpRegSave iseries_reg_save[] = {
+-	[0 ... (NR_CPUS-1)] = {
+-		.xDesc = 0xd397d9e2,	/* "LpRS" */
+-		.xSize = sizeof(struct ItLpRegSave),
+-	},
+-};
+diff --git a/arch/powerpc/platforms/iseries/naca.h b/arch/powerpc/platforms/iseries/naca.h
+index ab2372e..f01708e 100644
+--- a/arch/powerpc/platforms/iseries/naca.h
++++ b/arch/powerpc/platforms/iseries/naca.h
+@@ -14,7 +14,7 @@
+ 
+ struct naca_struct {
+ 	/* Kernel only data - undefined for user space */
+-	void *xItVpdAreas;              /* VPD Data                  0x00 */
++	const void *xItVpdAreas;	/* VPD Data                  0x00 */
+ 	void *xRamDisk;                 /* iSeries ramdisk           0x08 */
+ 	u64   xRamDiskSize;		/* In pages                  0x10 */
+ };
+diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
+index cc562e4..02a634f 100644
+--- a/arch/powerpc/platforms/iseries/pci.c
++++ b/arch/powerpc/platforms/iseries/pci.c
+@@ -23,6 +23,7 @@
+ 
+ #undef DEBUG
+ 
++#include <linux/jiffies.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+ #include <linux/string.h>
+@@ -586,7 +587,7 @@ static inline struct device_node *xlate_iomm_address(
+ 		static unsigned long last_jiffies;
+ 		static int num_printed;
+ 
+-		if ((jiffies - last_jiffies) > 60 * HZ) {
++		if (time_after(jiffies, last_jiffies + 60 * HZ)) {
+ 			last_jiffies = jiffies;
+ 			num_printed = 0;
+ 		}
+diff --git a/arch/powerpc/platforms/iseries/release_data.h b/arch/powerpc/platforms/iseries/release_data.h
+index 66189fd..6ad7d84 100644
+--- a/arch/powerpc/platforms/iseries/release_data.h
++++ b/arch/powerpc/platforms/iseries/release_data.h
+@@ -58,6 +58,6 @@ struct HvReleaseData {
+ 	char	xRsvd3[20];	/* Reserved			x2C-x3F */
+ };
+ 
+-extern struct HvReleaseData	hvReleaseData;
++extern const struct HvReleaseData	hvReleaseData;
+ 
+ #endif /* _ISERIES_RELEASE_DATA_H */
+diff --git a/arch/powerpc/platforms/iseries/spcomm_area.h b/arch/powerpc/platforms/iseries/spcomm_area.h
+index 6e3b685..598b7c1 100644
+--- a/arch/powerpc/platforms/iseries/spcomm_area.h
++++ b/arch/powerpc/platforms/iseries/spcomm_area.h
+@@ -31,6 +31,4 @@ struct SpCommArea {
+ 	u8	xRsvd2[80];		// Reserved				030-07F
+ };
+ 
+-extern struct SpCommArea xSpCommArea;
+-
+ #endif /* _ISERIES_SPCOMM_AREA_H */
+diff --git a/arch/powerpc/platforms/iseries/vpd_areas.h b/arch/powerpc/platforms/iseries/vpd_areas.h
+index 601e6dd..feb001f 100644
+--- a/arch/powerpc/platforms/iseries/vpd_areas.h
++++ b/arch/powerpc/platforms/iseries/vpd_areas.h
+@@ -80,9 +80,9 @@ struct ItVpdAreas {
+ 	u32	xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths	080-0A7
+ 	u32	xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens	0A8-0CF
+ 	u32	xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths	0D0-12F
+-	void	*xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers	130-1EF
++	const void *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF
+ };
+ 
+-extern struct ItVpdAreas	itVpdAreas;
++extern const struct ItVpdAreas	itVpdAreas;
+ 
+ #endif /* _ISERIES_VPD_AREAS_H */
+diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
+index 3ffa0ac..3018552 100644
+--- a/arch/powerpc/platforms/maple/pci.c
++++ b/arch/powerpc/platforms/maple/pci.c
+@@ -592,50 +592,3 @@ int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
+ 	}
+ 	return irq;
+ }
+-
+-/* XXX: To remove once all firmwares are ok */
+-static void fixup_maple_ide(struct pci_dev* dev)
+-{
+-	if (!machine_is(maple))
+-		return;
+-
+-#if 0 /* Enable this to enable IDE port 0 */
+-	{
+-		u8 v;
+-
+-		pci_read_config_byte(dev, 0x40, &v);
+-		v |= 2;
+-		pci_write_config_byte(dev, 0x40, v);
+-	}
+-#endif
+-#if 0 /* fix bus master base */
+-	pci_write_config_dword(dev, 0x20, 0xcc01);
+-	printk("old ide resource: %lx -> %lx \n",
+-	       dev->resource[4].start, dev->resource[4].end);
+-	dev->resource[4].start = 0xcc00;
+-	dev->resource[4].end = 0xcc10;
+-#endif
+-#if 0 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
+-	{
+-		struct pci_dev *apicdev;
+-		u32 v;
+-
+-		apicdev = pci_get_slot (dev->bus, PCI_DEVFN(5,0));
+-		if (apicdev == NULL)
+-			printk("IDE Fixup IRQ: Can't find IO-APIC !\n");
+-		else {
+-			pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*14);
+-			pci_read_config_dword(apicdev, 0xf4, &v);
+-			v &= ~0x00000022;
+-			pci_write_config_dword(apicdev, 0xf4, v);
+-			pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*15);
+-			pci_read_config_dword(apicdev, 0xf4, &v);
+-			v &= ~0x00000022;
+-			pci_write_config_dword(apicdev, 0xf4, v);
+-			pci_dev_put(apicdev);
+-		}
+-	}
+-#endif
+-}
+-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE,
+-			 fixup_maple_ide);
+diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
+index 3ce2d73..3647147 100644
+--- a/arch/powerpc/platforms/maple/setup.c
++++ b/arch/powerpc/platforms/maple/setup.c
+@@ -43,6 +43,7 @@
+ #include <linux/smp.h>
+ #include <linux/bitops.h>
+ #include <linux/of_device.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/sections.h>
+@@ -57,7 +58,6 @@
+ #include <asm/dma.h>
+ #include <asm/cputable.h>
+ #include <asm/time.h>
+-#include <asm/lmb.h>
+ #include <asm/mpic.h>
+ #include <asm/rtas.h>
+ #include <asm/udbg.h>
+@@ -319,7 +319,7 @@ static int __init maple_probe(void)
+ 	return 1;
+ }
+ 
+-define_machine(maple_md) {
++define_machine(maple) {
+ 	.name			= "Maple",
+ 	.probe			= maple_probe,
+ 	.setup_arch		= maple_setup_arch,
+diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c
+index c529d8d..217af32 100644
+--- a/arch/powerpc/platforms/pasemi/dma_lib.c
++++ b/arch/powerpc/platforms/pasemi/dma_lib.c
+@@ -17,6 +17,7 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+  */
+ 
++#include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
+@@ -26,6 +27,8 @@
+ 
+ #define MAX_TXCH 64
+ #define MAX_RXCH 64
++#define MAX_FLAGS 64
++#define MAX_FUN 8
+ 
+ static struct pasdma_status *dma_status;
+ 
+@@ -43,6 +46,8 @@ static struct pci_dev *dma_pdev;
+ 
+ static DECLARE_BITMAP(txch_free, MAX_TXCH);
+ static DECLARE_BITMAP(rxch_free, MAX_RXCH);
++static DECLARE_BITMAP(flags_free, MAX_FLAGS);
++static DECLARE_BITMAP(fun_free, MAX_FUN);
+ 
+ /* pasemi_read_iob_reg - read IOB register
+  * @reg: Register to read (offset into PCI CFG space)
+@@ -373,6 +378,106 @@ void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
+ }
+ EXPORT_SYMBOL(pasemi_dma_free_buf);
+ 
++/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel syncronization
++ *
++ * Allocates a flag for use with channel syncronization (event descriptors).
++ * Returns allocated flag (0-63), < 0 on error.
++ */
++int pasemi_dma_alloc_flag(void)
++{
++	int bit;
++
++retry:
++	bit = find_next_bit(flags_free, MAX_FLAGS, 0);
++	if (bit >= MAX_FLAGS)
++		return -ENOSPC;
++	if (!test_and_clear_bit(bit, flags_free))
++		goto retry;
++
++	return bit;
++}
++EXPORT_SYMBOL(pasemi_dma_alloc_flag);
++
++
++/* pasemi_dma_free_flag - Deallocates a flag (event)
++ * @flag: Flag number to deallocate
++ *
++ * Frees up a flag so it can be reused for other purposes.
++ */
++void pasemi_dma_free_flag(int flag)
++{
++	BUG_ON(test_bit(flag, flags_free));
++	BUG_ON(flag >= MAX_FLAGS);
++	set_bit(flag, flags_free);
++}
++EXPORT_SYMBOL(pasemi_dma_free_flag);
++
++
++/* pasemi_dma_set_flag - Sets a flag (event) to 1
++ * @flag: Flag number to set active
++ *
++ * Sets the flag provided to 1.
++ */
++void pasemi_dma_set_flag(int flag)
++{
++	BUG_ON(flag >= MAX_FLAGS);
++	if (flag < 32)
++		pasemi_write_dma_reg(PAS_DMA_TXF_SFLG0, 1 << flag);
++	else
++		pasemi_write_dma_reg(PAS_DMA_TXF_SFLG1, 1 << flag);
++}
++EXPORT_SYMBOL(pasemi_dma_set_flag);
++
++/* pasemi_dma_clear_flag - Sets a flag (event) to 0
++ * @flag: Flag number to set inactive
++ *
++ * Sets the flag provided to 0.
++ */
++void pasemi_dma_clear_flag(int flag)
++{
++	BUG_ON(flag >= MAX_FLAGS);
++	if (flag < 32)
++		pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 1 << flag);
++	else
++		pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 1 << flag);
++}
++EXPORT_SYMBOL(pasemi_dma_clear_flag);
++
++/* pasemi_dma_alloc_fun - Allocate a function engine
++ *
++ * Allocates a function engine to use for crypto/checksum offload
++ * Returns allocated engine (0-8), < 0 on error.
++ */
++int pasemi_dma_alloc_fun(void)
++{
++	int bit;
++
++retry:
++	bit = find_next_bit(fun_free, MAX_FLAGS, 0);
++	if (bit >= MAX_FLAGS)
++		return -ENOSPC;
++	if (!test_and_clear_bit(bit, fun_free))
++		goto retry;
++
++	return bit;
++}
++EXPORT_SYMBOL(pasemi_dma_alloc_fun);
++
++
++/* pasemi_dma_free_fun - Deallocates a function engine
++ * @flag: Engine number to deallocate
++ *
++ * Frees up a function engine so it can be used for other purposes.
++ */
++void pasemi_dma_free_fun(int fun)
++{
++	BUG_ON(test_bit(fun, fun_free));
++	BUG_ON(fun >= MAX_FLAGS);
++	set_bit(fun, fun_free);
++}
++EXPORT_SYMBOL(pasemi_dma_free_fun);
++
++
+ static void *map_onedev(struct pci_dev *p, int index)
+ {
+ 	struct device_node *dn;
+@@ -410,6 +515,7 @@ int pasemi_dma_init(void)
+ 	struct resource res;
+ 	struct device_node *dn;
+ 	int i, intf, err = 0;
++	unsigned long timeout;
+ 	u32 tmp;
+ 
+ 	if (!machine_is(pasemi))
+@@ -478,6 +584,44 @@ int pasemi_dma_init(void)
+ 	for (i = 0; i < MAX_RXCH; i++)
+ 		__set_bit(i, rxch_free);
+ 
++	timeout = jiffies + HZ;
++	pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, 0);
++	while (pasemi_read_dma_reg(PAS_DMA_COM_RXSTA) & 1) {
++		if (time_after(jiffies, timeout)) {
++			pr_warning("Warning: Could not disable RX section\n");
++			break;
++		}
++	}
++
++	timeout = jiffies + HZ;
++	pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, 0);
++	while (pasemi_read_dma_reg(PAS_DMA_COM_TXSTA) & 1) {
++		if (time_after(jiffies, timeout)) {
++			pr_warning("Warning: Could not disable TX section\n");
++			break;
++		}
++	}
++
++	/* setup resource allocations for the different DMA sections */
++	tmp = pasemi_read_dma_reg(PAS_DMA_COM_CFG);
++	pasemi_write_dma_reg(PAS_DMA_COM_CFG, tmp | 0x18000000);
++
++	/* enable tx section */
++	pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
++
++	/* enable rx section */
++	pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
++
++	for (i = 0; i < MAX_FLAGS; i++)
++		__set_bit(i, flags_free);
++
++	for (i = 0; i < MAX_FUN; i++)
++		__set_bit(i, fun_free);
++
++	/* clear all status flags */
++	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
++	pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
++
+ 	printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
+ 		"(%d tx, %d rx channels)\n", num_txch, num_rxch);
+ 
+diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
+index b465429..ab69554 100644
+--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
++++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
+@@ -241,7 +241,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
+ 	new_bus->reset = &gpio_mdio_reset;
+ 
+ 	prop = of_get_property(np, "reg", NULL);
+-	new_bus->id = *prop;
++	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", *prop);
+ 	new_bus->priv = priv;
+ 
+ 	new_bus->phy_mask = 0;
+diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
+index 5803f11..86967bd 100644
+--- a/arch/powerpc/platforms/pasemi/iommu.c
++++ b/arch/powerpc/platforms/pasemi/iommu.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2005-2007, PA Semi, Inc
++ * Copyright (C) 2005-2008, PA Semi, Inc
+  *
+  * Maintained by: Olof Johansson <olof at lixom.net>
+  *
+@@ -27,7 +27,6 @@
+ #include <asm/abs_addr.h>
+ #include <asm/firmware.h>
+ 
+-
+ #define IOBMAP_PAGE_SHIFT	12
+ #define IOBMAP_PAGE_SIZE	(1 << IOBMAP_PAGE_SHIFT)
+ #define IOBMAP_PAGE_MASK	(IOBMAP_PAGE_SIZE - 1)
+@@ -35,13 +34,13 @@
+ #define IOB_BASE		0xe0000000
+ #define IOB_SIZE		0x3000
+ /* Configuration registers */
+-#define IOBCAP_REG		0x10
+-#define IOBCOM_REG		0x40
++#define IOBCAP_REG		0x40
++#define IOBCOM_REG		0x100
+ /* Enable IOB address translation */
+ #define IOBCOM_ATEN		0x00000100
+ 
+ /* Address decode configuration register */
+-#define IOB_AD_REG		0x53
++#define IOB_AD_REG		0x14c
+ /* IOBCOM_AD_REG fields */
+ #define IOB_AD_VGPRT		0x00000e00
+ #define IOB_AD_VGAEN		0x00000100
+@@ -56,13 +55,13 @@
+ #define IOB_AD_TRNG_2G		0x00000001
+ #define IOB_AD_TRNG_128G	0x00000003
+ 
+-#define IOB_TABLEBASE_REG	0x55
++#define IOB_TABLEBASE_REG	0x154
+ 
+ /* Base of the 64 4-byte L1 registers */
+-#define IOB_XLT_L1_REGBASE	0xac0
++#define IOB_XLT_L1_REGBASE	0x2b00
+ 
+ /* Register to invalidate TLB entries */
+-#define IOB_AT_INVAL_TLB_REG	0xb40
++#define IOB_AT_INVAL_TLB_REG	0x2d00
+ 
+ /* The top two bits of the level 1 entry contains valid and type flags */
+ #define IOBMAP_L1E_V		0x40000000
+@@ -76,7 +75,7 @@
+ #define IOBMAP_L2E_V		0x80000000
+ #define IOBMAP_L2E_V_CACHED	0xc0000000
+ 
+-static u32 __iomem *iob;
++static void __iomem *iob;
+ static u32 iob_l1_emptyval;
+ static u32 iob_l2_emptyval;
+ static u32 *iob_l2_base;
+@@ -219,7 +218,7 @@ int __init iob_init(struct device_node *dn)
+ 	for (i = 0; i < 64; i++) {
+ 		/* Each L1 covers 32MB, i.e. 8K entries = 32K of ram */
+ 		regword = IOBMAP_L1E_V | (__pa(iob_l2_base + i*0x2000) >> 12);
+-		out_le32(iob+IOB_XLT_L1_REGBASE+i, regword);
++		out_le32(iob+IOB_XLT_L1_REGBASE+i*4, regword);
+ 	}
+ 
+ 	/* set 2GB translation window, based at 0 */
+diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
+index 1c58db9..bcf50d7 100644
+--- a/arch/powerpc/platforms/powermac/pci.c
++++ b/arch/powerpc/platforms/powermac/pci.c
+@@ -1144,28 +1144,6 @@ void __init pmac_pcibios_after_init(void)
+ {
+ 	struct device_node* nd;
+ 
+-#ifdef CONFIG_BLK_DEV_IDE
+-	struct pci_dev *dev = NULL;
+-
+-	/* OF fails to initialize IDE controllers on macs
+-	 * (and maybe other machines)
+-	 *
+-	 * Ideally, this should be moved to the IDE layer, but we need
+-	 * to check specifically with Andre Hedrick how to do it cleanly
+-	 * since the common IDE code seem to care about the fact that the
+-	 * BIOS may have disabled a controller.
+-	 *
+-	 * -- BenH
+-	 */
+-	for_each_pci_dev(dev) {
+-		if ((dev->class >> 16) != PCI_BASE_CLASS_STORAGE)
+-			continue;
+-		if (pci_enable_device(dev))
+-			printk(KERN_WARNING
+-			       "pci: Failed to enable %s\n", pci_name(dev));
+-	}
+-#endif /* CONFIG_BLK_DEV_IDE */
+-
+ 	for_each_node_by_name(nd, "firewire") {
+ 		if (nd->parent && (of_device_is_compatible(nd, "pci106b,18") ||
+ 				   of_device_is_compatible(nd, "pci106b,30") ||
+diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
+index 8543423..96d5ce5 100644
+--- a/arch/powerpc/platforms/powermac/pfunc_core.c
++++ b/arch/powerpc/platforms/powermac/pfunc_core.c
+@@ -12,7 +12,6 @@
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/prom.h>
+ #include <asm/pmac_pfunc.h>
+ 
+diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
+index b3abaaf..3362e78 100644
+--- a/arch/powerpc/platforms/powermac/pmac.h
++++ b/arch/powerpc/platforms/powermac/pmac.h
+@@ -2,7 +2,6 @@
+ #define __PMAC_H__
+ 
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/irq.h>
+ 
+ /*
+@@ -35,10 +34,6 @@ extern void pmac_check_ht_link(void);
+ 
+ extern void pmac_setup_smp(void);
+ 
+-extern unsigned long pmac_ide_get_base(int index);
+-extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
+-	unsigned long data_port, unsigned long ctrl_port, int *irq);
+-
+ extern int pmac_nvram_init(void);
+ extern void pmac_pic_init(void);
+ 
+diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
+index 36ff1b6..bf44c54 100644
+--- a/arch/powerpc/platforms/powermac/setup.c
++++ b/arch/powerpc/platforms/powermac/setup.c
+@@ -53,6 +53,7 @@
+ #include <linux/suspend.h>
+ #include <linux/of_device.h>
+ #include <linux/of_platform.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/reg.h>
+ #include <asm/sections.h>
+@@ -74,7 +75,6 @@
+ #include <asm/iommu.h>
+ #include <asm/smu.h>
+ #include <asm/pmc.h>
+-#include <asm/lmb.h>
+ #include <asm/udbg.h>
+ 
+ #include "pmac.h"
+@@ -574,14 +574,6 @@ static int __init pmac_probe(void)
+ 	ISA_DMA_THRESHOLD = ~0L;
+ 	DMA_MODE_READ = 1;
+ 	DMA_MODE_WRITE = 2;
+-
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+-        ppc_ide_md.ide_init_hwif	= pmac_ide_init_hwif_ports;
+-        ppc_ide_md.default_io_base	= pmac_ide_get_base;
+-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
+-
+ #endif /* CONFIG_PPC32 */
+ 
+ #ifdef CONFIG_PMAC_SMU
+diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
+index 9d251d0..3866deb 100644
+--- a/arch/powerpc/platforms/ps3/device-init.c
++++ b/arch/powerpc/platforms/ps3/device-init.c
+@@ -499,41 +499,14 @@ static int __init ps3_register_graphics_devices(void)
+ }
+ 
+ /**
+- * ps3_register_repository_device - Register a device from the repositiory info.
+- *
++ * ps3_setup_dynamic_device - Setup a dynamic device from the repository
+  */
+ 
+-static int ps3_register_repository_device(
+-	const struct ps3_repository_device *repo)
++static int ps3_setup_dynamic_device(const struct ps3_repository_device *repo)
+ {
+ 	int result;
+ 
+ 	switch (repo->dev_type) {
+-	case PS3_DEV_TYPE_SB_GELIC:
+-		result = ps3_setup_gelic_device(repo);
+-		if (result) {
+-			pr_debug("%s:%d ps3_setup_gelic_device failed\n",
+-				__func__, __LINE__);
+-		}
+-		break;
+-	case PS3_DEV_TYPE_SB_USB:
+-
+-		/* Each USB device has both an EHCI and an OHCI HC */
+-
+-		result = ps3_setup_ehci_device(repo);
+-
+-		if (result) {
+-			pr_debug("%s:%d ps3_setup_ehci_device failed\n",
+-				__func__, __LINE__);
+-		}
+-
+-		result = ps3_setup_ohci_device(repo);
+-
+-		if (result) {
+-			pr_debug("%s:%d ps3_setup_ohci_device failed\n",
+-				__func__, __LINE__);
+-		}
+-		break;
+ 	case PS3_DEV_TYPE_STOR_DISK:
+ 		result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK);
+ 
+@@ -572,6 +545,48 @@ static int ps3_register_repository_device(
+ 	return result;
+ }
+ 
++/**
++ * ps3_setup_static_device - Setup a static device from the repository
++ */
++
++static int __init ps3_setup_static_device(const struct ps3_repository_device *repo)
++{
++	int result;
++
++	switch (repo->dev_type) {
++	case PS3_DEV_TYPE_SB_GELIC:
++		result = ps3_setup_gelic_device(repo);
++		if (result) {
++			pr_debug("%s:%d ps3_setup_gelic_device failed\n",
++				__func__, __LINE__);
++		}
++		break;
++	case PS3_DEV_TYPE_SB_USB:
++
++		/* Each USB device has both an EHCI and an OHCI HC */
++
++		result = ps3_setup_ehci_device(repo);
++
++		if (result) {
++			pr_debug("%s:%d ps3_setup_ehci_device failed\n",
++				__func__, __LINE__);
++		}
++
++		result = ps3_setup_ohci_device(repo);
++
++		if (result) {
++			pr_debug("%s:%d ps3_setup_ohci_device failed\n",
++				__func__, __LINE__);
++		}
++		break;
++
++	default:
++		return ps3_setup_dynamic_device(repo);
++	}
++
++	return result;
++}
++
+ static void ps3_find_and_add_device(u64 bus_id, u64 dev_id)
+ {
+ 	struct ps3_repository_device repo;
+@@ -601,7 +616,7 @@ found:
+ 		pr_debug("%s:%u: device %lu:%lu found after %u retries\n",
+ 			 __func__, __LINE__, bus_id, dev_id, retries);
+ 
+-	ps3_register_repository_device(&repo);
++	ps3_setup_dynamic_device(&repo);
+ 	return;
+ }
+ 
+@@ -905,8 +920,7 @@ static int __init ps3_register_devices(void)
+ 
+ 	ps3_register_graphics_devices();
+ 
+-	ps3_repository_find_devices(PS3_BUS_TYPE_SB,
+-		ps3_register_repository_device);
++	ps3_repository_find_devices(PS3_BUS_TYPE_SB, ps3_setup_static_device);
+ 
+ 	ps3_register_sound_devices();
+ 
+diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
+index 7382f19..1cf901f 100644
+--- a/arch/powerpc/platforms/ps3/htab.c
++++ b/arch/powerpc/platforms/ps3/htab.c
+@@ -19,9 +19,10 @@
+  */
+ 
+ #include <linux/kernel.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/machdep.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/udbg.h>
+ #include <asm/lv1call.h>
+ #include <asm/ps3fb.h>
+diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
+index 3a6db04..a14e5cd 100644
+--- a/arch/powerpc/platforms/ps3/interrupt.c
++++ b/arch/powerpc/platforms/ps3/interrupt.c
+@@ -709,7 +709,7 @@ static unsigned int ps3_get_irq(void)
+ 	asm volatile("cntlzd %0,%1" : "=r" (plug) : "r" (x));
+ 	plug &= 0x3f;
+ 
+-	if (unlikely(plug) == NO_IRQ) {
++	if (unlikely(plug == NO_IRQ)) {
+ 		pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__,
+ 			__LINE__, pd->thread_id);
+ 		dump_bmp(&per_cpu(ps3_private, 0));
+diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
+index 6890047..5b3fb2b 100644
+--- a/arch/powerpc/platforms/ps3/mm.c
++++ b/arch/powerpc/platforms/ps3/mm.c
+@@ -21,9 +21,10 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/memory_hotplug.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/firmware.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/udbg.h>
+ #include <asm/lv1call.h>
+ 
+diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
+index b9ea09d..1d20178 100644
+--- a/arch/powerpc/platforms/ps3/os-area.c
++++ b/arch/powerpc/platforms/ps3/os-area.c
+@@ -24,8 +24,10 @@
+ #include <linux/fs.h>
+ #include <linux/syscalls.h>
+ #include <linux/ctype.h>
++#include <linux/lmb.h>
++#include <linux/of.h>
+ 
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ 
+ #include "platform.h"
+ 
+diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
+index 5c2cbb0..a413abb 100644
+--- a/arch/powerpc/platforms/ps3/setup.c
++++ b/arch/powerpc/platforms/ps3/setup.c
+@@ -95,6 +95,14 @@ static void ps3_power_off(void)
+ 	ps3_sys_manager_power_off(); /* never returns */
+ }
+ 
++static void ps3_halt(void)
++{
++	DBG("%s:%d\n", __func__, __LINE__);
++
++	smp_send_stop();
++	ps3_sys_manager_halt(); /* never returns */
++}
++
+ static void ps3_panic(char *str)
+ {
+ 	DBG("%s:%d %s\n", __func__, __LINE__, str);
+@@ -105,7 +113,8 @@ static void ps3_panic(char *str)
+ 	printk("   Please press POWER button.\n");
+ 	printk("\n");
+ 
+-	while(1);
++	while(1)
++		lv1_pause(1);
+ }
+ 
+ #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \
+@@ -117,7 +126,7 @@ static void __init prealloc(struct ps3_prealloc *p)
+ 
+ 	p->address = __alloc_bootmem(p->size, p->align, __pa(MAX_DMA_ADDRESS));
+ 	if (!p->address) {
+-		printk(KERN_ERR "%s: Cannot allocate %s\n", __FUNCTION__,
++		printk(KERN_ERR "%s: Cannot allocate %s\n", __func__,
+ 		       p->name);
+ 		return;
+ 	}
+@@ -266,6 +275,7 @@ define_machine(ps3) {
+ 	.progress			= ps3_progress,
+ 	.restart			= ps3_restart,
+ 	.power_off			= ps3_power_off,
++	.halt				= ps3_halt,
+ #if defined(CONFIG_KEXEC)
+ 	.kexec_cpu_down			= ps3_kexec_cpu_down,
+ 	.machine_kexec			= default_machine_kexec,
+diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
+index 5ad4118..d135cef 100644
+--- a/arch/powerpc/platforms/ps3/spu.c
++++ b/arch/powerpc/platforms/ps3/spu.c
+@@ -27,6 +27,7 @@
+ #include <asm/spu.h>
+ #include <asm/spu_priv1.h>
+ #include <asm/lv1call.h>
++#include <asm/ps3.h>
+ 
+ #include "../cell/spufs/spufs.h"
+ #include "platform.h"
+@@ -140,6 +141,12 @@ static void _dump_areas(unsigned int spe_id, unsigned long priv2,
+ 	pr_debug("%s:%d: shadow:  %lxh\n", func, line, shadow);
+ }
+ 
++inline u64 ps3_get_spe_id(void *arg)
++{
++	return spu_pdata(arg)->spe_id;
++}
++EXPORT_SYMBOL_GPL(ps3_get_spe_id);
++
+ static unsigned long get_vas_id(void)
+ {
+ 	unsigned long id;
+diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
+index 306a9d0..07fe5b6 100644
+--- a/arch/powerpc/platforms/pseries/Kconfig
++++ b/arch/powerpc/platforms/pseries/Kconfig
+@@ -34,3 +34,8 @@ config LPARCFG
+ 	help
+ 	Provide system capacity information via human readable
+ 	<key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
++
++config PPC_PSERIES_DEBUG
++	depends on PPC_PSERIES && PPC_EARLY_DEBUG
++	bool "Enable extra debug logging in platforms/pseries"
++	default y
+diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
+index 992ba67..bd2593e 100644
+--- a/arch/powerpc/platforms/pseries/Makefile
++++ b/arch/powerpc/platforms/pseries/Makefile
+@@ -2,6 +2,10 @@ ifeq ($(CONFIG_PPC64),y)
+ EXTRA_CFLAGS		+= -mno-minimal-toc
+ endif
+ 
++ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y)
++EXTRA_CFLAGS		+= -DDEBUG
++endif
++
+ obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
+ 			   setup.o iommu.o ras.o rtasd.o \
+ 			   firmware.o power.o
+@@ -18,3 +22,4 @@ obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
+ 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
+diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
+index 9eb539e..a3fd56b 100644
+--- a/arch/powerpc/platforms/pseries/eeh.c
++++ b/arch/powerpc/platforms/pseries/eeh.c
+@@ -39,7 +39,6 @@
+ #include <asm/ppc-pci.h>
+ #include <asm/rtas.h>
+ 
+-#undef DEBUG
+ 
+ /** Overview:
+  *  EEH, or "Extended Error Handling" is a PCI bridge technology for
+@@ -945,7 +944,6 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
+ 	unsigned int rets[3];
+ 	struct eeh_early_enable_info *info = data;
+ 	int ret;
+-	const char *status = of_get_property(dn, "status", NULL);
+ 	const u32 *class_code = of_get_property(dn, "class-code", NULL);
+ 	const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL);
+ 	const u32 *device_id = of_get_property(dn, "device-id", NULL);
+@@ -959,8 +957,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
+ 	pdn->eeh_freeze_count = 0;
+ 	pdn->eeh_false_positives = 0;
+ 
+-	if (status && strncmp(status, "ok", 2) != 0)
+-		return NULL;	/* ignore devices with bad status */
++	if (!of_device_is_available(dn))
++		return NULL;
+ 
+ 	/* Ignore bad nodes. */
+ 	if (!class_code || !vendor_id || !device_id)
+diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
+index 1e83fcd..ce37040 100644
+--- a/arch/powerpc/platforms/pseries/eeh_cache.c
++++ b/arch/powerpc/platforms/pseries/eeh_cache.c
+@@ -28,7 +28,6 @@
+ #include <asm/pci-bridge.h>
+ #include <asm/ppc-pci.h>
+ 
+-#undef DEBUG
+ 
+ /**
+  * The pci address cache subsystem.  This subsystem places
+diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
+index b765b7c..9d3a40f 100644
+--- a/arch/powerpc/platforms/pseries/firmware.c
++++ b/arch/powerpc/platforms/pseries/firmware.c
+@@ -21,17 +21,11 @@
+  * 2 of the License, or (at your option) any later version.
+  */
+ 
+-#undef DEBUG
+ 
+ #include <asm/firmware.h>
+ #include <asm/prom.h>
+ #include <asm/udbg.h>
+ 
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+ 
+ typedef struct {
+     unsigned long val;
+@@ -72,7 +66,7 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
+ 	const char *s;
+ 	int i;
+ 
+-	DBG(" -> fw_feature_init()\n");
++	pr_debug(" -> fw_feature_init()\n");
+ 
+ 	for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) {
+ 		for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) {
+@@ -88,5 +82,5 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
+ 		}
+ 	}
+ 
+-	DBG(" <- fw_feature_init()\n");
++	pr_debug(" <- fw_feature_init()\n");
+ }
+diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
+index a65c763..176f1f3 100644
+--- a/arch/powerpc/platforms/pseries/iommu.c
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -47,7 +47,6 @@
+ 
+ #include "plpar_wrappers.h"
+ 
+-#define DBG(fmt...)
+ 
+ static void tce_build_pSeries(struct iommu_table *tbl, long index,
+ 			      long npages, unsigned long uaddr,
+@@ -322,7 +321,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
+ 
+ 	dn = pci_bus_to_OF_node(bus);
+ 
+-	DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
++	pr_debug("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
+ 
+ 	if (bus->self) {
+ 		/* This is not a root bus, any setup will be done for the
+@@ -347,7 +346,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
+ 	for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
+ 		children++;
+ 
+-	DBG("Children: %d\n", children);
++	pr_debug("Children: %d\n", children);
+ 
+ 	/* Calculate amount of DMA window per slot. Each window must be
+ 	 * a power of two (due to pci_alloc_consistent requirements).
+@@ -361,8 +360,8 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
+ 
+ 		while (pci->phb->dma_window_size * children > 0x80000000ul)
+ 			pci->phb->dma_window_size >>= 1;
+-		DBG("No ISA/IDE, window size is 0x%lx\n",
+-			pci->phb->dma_window_size);
++		pr_debug("No ISA/IDE, window size is 0x%lx\n",
++			 pci->phb->dma_window_size);
+ 		pci->phb->dma_window_base_cur = 0;
+ 
+ 		return;
+@@ -387,8 +386,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
+ 	while (pci->phb->dma_window_size * children > 0x70000000ul)
+ 		pci->phb->dma_window_size >>= 1;
+ 
+-	DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
+-
++	pr_debug("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
+ }
+ 
+ 
+@@ -401,7 +399,8 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
+ 
+ 	dn = pci_bus_to_OF_node(bus);
+ 
+-	DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name);
++	pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n",
++		 dn->full_name);
+ 
+ 	/* Find nearest ibm,dma-window, walking up the device tree */
+ 	for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
+@@ -411,14 +410,14 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
+ 	}
+ 
+ 	if (dma_window == NULL) {
+-		DBG("  no ibm,dma-window property !\n");
++		pr_debug("  no ibm,dma-window property !\n");
+ 		return;
+ 	}
+ 
+ 	ppci = PCI_DN(pdn);
+ 
+-	DBG("  parent is %s, iommu_table: 0x%p\n",
+-	    pdn->full_name, ppci->iommu_table);
++	pr_debug("  parent is %s, iommu_table: 0x%p\n",
++		 pdn->full_name, ppci->iommu_table);
+ 
+ 	if (!ppci->iommu_table) {
+ 		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+@@ -426,7 +425,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
+ 		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
+ 			bus->number);
+ 		ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
+-		DBG("  created table: %p\n", ppci->iommu_table);
++		pr_debug("  created table: %p\n", ppci->iommu_table);
+ 	}
+ 
+ 	if (pdn != dn)
+@@ -439,7 +438,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
+ 	struct device_node *dn;
+ 	struct iommu_table *tbl;
+ 
+-	DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
++	pr_debug("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
+ 
+ 	dn = dev->dev.archdata.of_node;
+ 
+@@ -450,7 +449,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
+ 	if (!dev->bus->self) {
+ 		struct pci_controller *phb = PCI_DN(dn)->phb;
+ 
+-		DBG(" --> first child, no bridge. Allocating iommu table.\n");
++		pr_debug(" --> first child, no bridge. Allocating iommu table.\n");
+ 		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+ 				   phb->node);
+ 		iommu_table_setparms(phb, dn, tbl);
+@@ -480,7 +479,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
+ 	const void *dma_window = NULL;
+ 	struct pci_dn *pci;
+ 
+-	DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
++	pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
+ 
+ 	/* dev setup for LPAR is a little tricky, since the device tree might
+ 	 * contain the dma-window properties per-device and not neccesarily
+@@ -489,7 +488,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
+ 	 * already allocated.
+ 	 */
+ 	dn = pci_device_to_OF_node(dev);
+-	DBG("  node is %s\n", dn->full_name);
++	pr_debug("  node is %s\n", dn->full_name);
+ 
+ 	for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
+ 	     pdn = pdn->parent) {
+@@ -504,13 +503,13 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
+ 				 pci_name(dev), dn? dn->full_name : "<null>");
+ 		return;
+ 	}
+-	DBG("  parent is %s\n", pdn->full_name);
++	pr_debug("  parent is %s\n", pdn->full_name);
+ 
+ 	/* Check for parent == NULL so we don't try to setup the empty EADS
+ 	 * slots on POWER4 machines.
+ 	 */
+ 	if (dma_window == NULL || pdn->parent == NULL) {
+-		DBG("  no dma window for device, linking to parent\n");
++		pr_debug("  no dma window for device, linking to parent\n");
+ 		dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table;
+ 		return;
+ 	}
+@@ -522,9 +521,9 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
+ 		iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
+ 			pci->phb->bus->number);
+ 		pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
+-		DBG("  created table: %p\n", pci->iommu_table);
++		pr_debug("  created table: %p\n", pci->iommu_table);
+ 	} else {
+-		DBG("  found DMA window, table: %p\n", pci->iommu_table);
++		pr_debug("  found DMA window, table: %p\n", pci->iommu_table);
+ 	}
+ 
+ 	dev->dev.archdata.dma_data = pci->iommu_table;
+diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
+index 9a455d4..2cbaedb 100644
+--- a/arch/powerpc/platforms/pseries/lpar.c
++++ b/arch/powerpc/platforms/pseries/lpar.c
+@@ -19,7 +19,8 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+  */
+ 
+-#undef DEBUG_LOW
++/* Enables debugging of low-level hash table routines - careful! */
++#undef DEBUG
+ 
+ #include <linux/kernel.h>
+ #include <linux/dma-mapping.h>
+@@ -40,12 +41,8 @@
+ #include <asm/smp.h>
+ 
+ #include "plpar_wrappers.h"
++#include "pseries.h"
+ 
+-#ifdef DEBUG_LOW
+-#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0)
+-#else
+-#define DBG_LOW(fmt...) do { } while(0)
+-#endif
+ 
+ /* in hvCall.S */
+ EXPORT_SYMBOL(plpar_hcall);
+@@ -195,6 +192,8 @@ void __init udbg_init_debug_lpar(void)
+ 	udbg_putc = udbg_putcLP;
+ 	udbg_getc = udbg_getcLP;
+ 	udbg_getc_poll = udbg_getc_pollLP;
++
++	register_early_udbg_console();
+ }
+ 
+ /* returns 0 if couldn't find or use /chosen/stdout as console */
+@@ -203,7 +202,6 @@ void __init find_udbg_vterm(void)
+ 	struct device_node *stdout_node;
+ 	const u32 *termno;
+ 	const char *name;
+-	int add_console;
+ 
+ 	/* find the boot console from /chosen/stdout */
+ 	if (!of_chosen)
+@@ -219,8 +217,6 @@ void __init find_udbg_vterm(void)
+ 		printk(KERN_WARNING "stdout node missing 'name' property!\n");
+ 		goto out;
+ 	}
+-	/* The user has requested a console so this is already set up. */
+-	add_console = !strstr(cmd_line, "console=");
+ 
+ 	/* Check if it's a virtual terminal */
+ 	if (strncmp(name, "vty", 3) != 0)
+@@ -234,15 +230,13 @@ void __init find_udbg_vterm(void)
+ 		udbg_putc = udbg_putcLP;
+ 		udbg_getc = udbg_getcLP;
+ 		udbg_getc_poll = udbg_getc_pollLP;
+-		if (add_console)
+-			add_preferred_console("hvc", termno[0] & 0xff, NULL);
++		add_preferred_console("hvc", termno[0] & 0xff, NULL);
+ 	} else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
+ 		vtermno = termno[0];
+ 		udbg_putc = udbg_hvsi_putc;
+ 		udbg_getc = udbg_hvsi_getc;
+ 		udbg_getc_poll = udbg_hvsi_getc_poll;
+-		if (add_console)
+-			add_preferred_console("hvsi", termno[0] & 0xff, NULL);
++		add_preferred_console("hvsi", termno[0] & 0xff, NULL);
+ 	}
+ out:
+ 	of_node_put(stdout_node);
+@@ -292,15 +286,15 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+ 	unsigned long hpte_v, hpte_r;
+ 
+ 	if (!(vflags & HPTE_V_BOLTED))
+-		DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+-			"rflags=%lx, vflags=%lx, psize=%d)\n",
+-		hpte_group, va, pa, rflags, vflags, psize);
++		pr_debug("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
++			 "rflags=%lx, vflags=%lx, psize=%d)\n",
++			 hpte_group, va, pa, rflags, vflags, psize);
+ 
+ 	hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+ 	hpte_r = hpte_encode_r(pa, psize) | rflags;
+ 
+ 	if (!(vflags & HPTE_V_BOLTED))
+-		DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
++		pr_debug(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+ 
+ 	/* Now fill in the actual HPTE */
+ 	/* Set CEC cookie to 0         */
+@@ -317,7 +311,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+ 	lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
+ 	if (unlikely(lpar_rc == H_PTEG_FULL)) {
+ 		if (!(vflags & HPTE_V_BOLTED))
+-			DBG_LOW(" full\n");
++			pr_debug(" full\n");
+ 		return -1;
+ 	}
+ 
+@@ -328,11 +322,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+ 	 */
+ 	if (unlikely(lpar_rc != H_SUCCESS)) {
+ 		if (!(vflags & HPTE_V_BOLTED))
+-			DBG_LOW(" lpar err %d\n", lpar_rc);
++			pr_debug(" lpar err %lu\n", lpar_rc);
+ 		return -2;
+ 	}
+ 	if (!(vflags & HPTE_V_BOLTED))
+-		DBG_LOW(" -> slot: %d\n", slot & 7);
++		pr_debug(" -> slot: %lu\n", slot & 7);
+ 
+ 	/* Because of iSeries, we have to pass down the secondary
+ 	 * bucket bit here as well
+@@ -424,17 +418,17 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
+ 
+ 	want_v = hpte_encode_avpn(va, psize, ssize);
+ 
+-	DBG_LOW("    update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ",
+-		want_v, slot, flags, psize);
++	pr_debug("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
++		 want_v, slot, flags, psize);
+ 
+ 	lpar_rc = plpar_pte_protect(flags, slot, want_v);
+ 
+ 	if (lpar_rc == H_NOT_FOUND) {
+-		DBG_LOW("not found !\n");
++		pr_debug("not found !\n");
+ 		return -1;
+ 	}
+ 
+-	DBG_LOW("ok\n");
++	pr_debug("ok\n");
+ 
+ 	BUG_ON(lpar_rc != H_SUCCESS);
+ 
+@@ -509,8 +503,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+ 	unsigned long lpar_rc;
+ 	unsigned long dummy1, dummy2;
+ 
+-	DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d",
+-		slot, va, psize, local);
++	pr_debug("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
++		 slot, va, psize, local);
+ 
+ 	want_v = hpte_encode_avpn(va, psize, ssize);
+ 	lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
+@@ -520,6 +514,20 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+ 	BUG_ON(lpar_rc != H_SUCCESS);
+ }
+ 
++static void pSeries_lpar_hpte_removebolted(unsigned long ea,
++					   int psize, int ssize)
++{
++	unsigned long slot, vsid, va;
++
++	vsid = get_kernel_vsid(ea, ssize);
++	va = hpt_va(ea, vsid, ssize);
++
++	slot = pSeries_lpar_hpte_find(va, psize, ssize);
++	BUG_ON(slot == -1);
++
++	pSeries_lpar_hpte_invalidate(slot, va, psize, ssize, 0);
++}
++
+ /* Flag bits for H_BULK_REMOVE */
+ #define HBR_REQUEST	0x4000000000000000UL
+ #define HBR_RESPONSE	0x8000000000000000UL
+@@ -597,6 +605,7 @@ void __init hpte_init_lpar(void)
+ 	ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
+ 	ppc_md.hpte_insert	= pSeries_lpar_hpte_insert;
+ 	ppc_md.hpte_remove	= pSeries_lpar_hpte_remove;
++	ppc_md.hpte_removebolted = pSeries_lpar_hpte_removebolted;
+ 	ppc_md.flush_hash_range	= pSeries_lpar_flush_hash_range;
+ 	ppc_md.hpte_clear_all   = pSeries_lpar_hptab_clear;
+ }
+diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
+index 5a5a19e..21a6d55 100644
+--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
++++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
+@@ -88,11 +88,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus)
+ 	struct pci_dev *dev;
+ 
+ 	list_for_each_entry(dev, &bus->devices, bus_list) {
+-		/*
+-		 * Skip already-present devices (which are on the
+-		 * global device list.)
+-		 */
+-		if (list_empty(&dev->global_list)) {
++		/* Skip already-added devices */
++		if (!dev->is_added) {
+ 			int i;
+ 
+ 			/* Fill device archdata and setup iommu table */
+@@ -123,7 +120,7 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
+ 	/* Add to children of PCI bridge dev->bus */
+ 	child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
+ 	if (!child_bus) {
+-		printk (KERN_ERR "%s: could not add second bus\n", __FUNCTION__);
++		printk (KERN_ERR "%s: could not add second bus\n", __func__);
+ 		return -EIO;
+ 	}
+ 	sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
+diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c
+new file mode 100644
+index 0000000..edbc012
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/phyp_dump.c
+@@ -0,0 +1,507 @@
++/*
++ * Hypervisor-assisted dump
++ *
++ * Linas Vepstas, Manish Ahuja 2008
++ * Copyright 2008 IBM Corp.
++ *
++ *      This program is free software; you can redistribute it and/or
++ *      modify it under the terms of the GNU General Public License
++ *      as published by the Free Software Foundation; either version
++ *      2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/kobject.h>
++#include <linux/mm.h>
++#include <linux/of.h>
++#include <linux/pfn.h>
++#include <linux/swap.h>
++#include <linux/sysfs.h>
++
++#include <asm/page.h>
++#include <asm/phyp_dump.h>
++#include <asm/machdep.h>
++#include <asm/prom.h>
++#include <asm/rtas.h>
++
++/* Variables, used to communicate data between early boot and late boot */
++static struct phyp_dump phyp_dump_vars;
++struct phyp_dump *phyp_dump_info = &phyp_dump_vars;
++
++static int ibm_configure_kernel_dump;
++/* ------------------------------------------------- */
++/* RTAS interfaces to declare the dump regions */
++
++struct dump_section {
++	u32 dump_flags;
++	u16 source_type;
++	u16 error_flags;
++	u64 source_address;
++	u64 source_length;
++	u64 length_copied;
++	u64 destination_address;
++};
++
++struct phyp_dump_header {
++	u32 version;
++	u16 num_of_sections;
++	u16 status;
++
++	u32 first_offset_section;
++	u32 dump_disk_section;
++	u64 block_num_dd;
++	u64 num_of_blocks_dd;
++	u32 offset_dd;
++	u32 maxtime_to_auto;
++	/* No dump disk path string used */
++
++	struct dump_section cpu_data;
++	struct dump_section hpte_data;
++	struct dump_section kernel_data;
++};
++
++/* The dump header *must be* in low memory, so .bss it */
++static struct phyp_dump_header phdr;
++
++#define NUM_DUMP_SECTIONS	3
++#define DUMP_HEADER_VERSION	0x1
++#define DUMP_REQUEST_FLAG	0x1
++#define DUMP_SOURCE_CPU		0x0001
++#define DUMP_SOURCE_HPTE	0x0002
++#define DUMP_SOURCE_RMO		0x0011
++#define DUMP_ERROR_FLAG		0x2000
++#define DUMP_TRIGGERED		0x4000
++#define DUMP_PERFORMED		0x8000
++
++
++/**
++ * init_dump_header() - initialize the header declaring a dump
++ * Returns: length of dump save area.
++ *
++ * When the hypervisor saves crashed state, it needs to put
++ * it somewhere. The dump header tells the hypervisor where
++ * the data can be saved.
++ */
++static unsigned long init_dump_header(struct phyp_dump_header *ph)
++{
++	unsigned long addr_offset = 0;
++
++	/* Set up the dump header */
++	ph->version = DUMP_HEADER_VERSION;
++	ph->num_of_sections = NUM_DUMP_SECTIONS;
++	ph->status = 0;
++
++	ph->first_offset_section =
++		(u32)offsetof(struct phyp_dump_header, cpu_data);
++	ph->dump_disk_section = 0;
++	ph->block_num_dd = 0;
++	ph->num_of_blocks_dd = 0;
++	ph->offset_dd = 0;
++
++	ph->maxtime_to_auto = 0; /* disabled */
++
++	/* The first two sections are mandatory */
++	ph->cpu_data.dump_flags = DUMP_REQUEST_FLAG;
++	ph->cpu_data.source_type = DUMP_SOURCE_CPU;
++	ph->cpu_data.source_address = 0;
++	ph->cpu_data.source_length = phyp_dump_info->cpu_state_size;
++	ph->cpu_data.destination_address = addr_offset;
++	addr_offset += phyp_dump_info->cpu_state_size;
++
++	ph->hpte_data.dump_flags = DUMP_REQUEST_FLAG;
++	ph->hpte_data.source_type = DUMP_SOURCE_HPTE;
++	ph->hpte_data.source_address = 0;
++	ph->hpte_data.source_length = phyp_dump_info->hpte_region_size;
++	ph->hpte_data.destination_address = addr_offset;
++	addr_offset += phyp_dump_info->hpte_region_size;
++
++	/* This section describes the low kernel region */
++	ph->kernel_data.dump_flags = DUMP_REQUEST_FLAG;
++	ph->kernel_data.source_type = DUMP_SOURCE_RMO;
++	ph->kernel_data.source_address = PHYP_DUMP_RMR_START;
++	ph->kernel_data.source_length = PHYP_DUMP_RMR_END;
++	ph->kernel_data.destination_address = addr_offset;
++	addr_offset += ph->kernel_data.source_length;
++
++	return addr_offset;
++}
++
++static void print_dump_header(const struct phyp_dump_header *ph)
++{
++#ifdef DEBUG
++	printk(KERN_INFO "dump header:\n");
++	/* setup some ph->sections required */
++	printk(KERN_INFO "version = %d\n", ph->version);
++	printk(KERN_INFO "Sections = %d\n", ph->num_of_sections);
++	printk(KERN_INFO "Status = 0x%x\n", ph->status);
++
++	/* No ph->disk, so all should be set to 0 */
++	printk(KERN_INFO "Offset to first section 0x%x\n",
++		ph->first_offset_section);
++	printk(KERN_INFO "dump disk sections should be zero\n");
++	printk(KERN_INFO "dump disk section = %d\n", ph->dump_disk_section);
++	printk(KERN_INFO "block num = %ld\n", ph->block_num_dd);
++	printk(KERN_INFO "number of blocks = %ld\n", ph->num_of_blocks_dd);
++	printk(KERN_INFO "dump disk offset = %d\n", ph->offset_dd);
++	printk(KERN_INFO "Max auto time= %d\n", ph->maxtime_to_auto);
++
++	/*set cpu state and hpte states as well scratch pad area */
++	printk(KERN_INFO " CPU AREA \n");
++	printk(KERN_INFO "cpu dump_flags =%d\n", ph->cpu_data.dump_flags);
++	printk(KERN_INFO "cpu source_type =%d\n", ph->cpu_data.source_type);
++	printk(KERN_INFO "cpu error_flags =%d\n", ph->cpu_data.error_flags);
++	printk(KERN_INFO "cpu source_address =%lx\n",
++		ph->cpu_data.source_address);
++	printk(KERN_INFO "cpu source_length =%lx\n",
++		ph->cpu_data.source_length);
++	printk(KERN_INFO "cpu length_copied =%lx\n",
++		ph->cpu_data.length_copied);
++
++	printk(KERN_INFO " HPTE AREA \n");
++	printk(KERN_INFO "HPTE dump_flags =%d\n", ph->hpte_data.dump_flags);
++	printk(KERN_INFO "HPTE source_type =%d\n", ph->hpte_data.source_type);
++	printk(KERN_INFO "HPTE error_flags =%d\n", ph->hpte_data.error_flags);
++	printk(KERN_INFO "HPTE source_address =%lx\n",
++		ph->hpte_data.source_address);
++	printk(KERN_INFO "HPTE source_length =%lx\n",
++		ph->hpte_data.source_length);
++	printk(KERN_INFO "HPTE length_copied =%lx\n",
++		ph->hpte_data.length_copied);
++
++	printk(KERN_INFO " SRSD AREA \n");
++	printk(KERN_INFO "SRSD dump_flags =%d\n", ph->kernel_data.dump_flags);
++	printk(KERN_INFO "SRSD source_type =%d\n", ph->kernel_data.source_type);
++	printk(KERN_INFO "SRSD error_flags =%d\n", ph->kernel_data.error_flags);
++	printk(KERN_INFO "SRSD source_address =%lx\n",
++		ph->kernel_data.source_address);
++	printk(KERN_INFO "SRSD source_length =%lx\n",
++		ph->kernel_data.source_length);
++	printk(KERN_INFO "SRSD length_copied =%lx\n",
++		ph->kernel_data.length_copied);
++#endif
++}
++
++static ssize_t show_phyp_dump_active(struct kobject *kobj,
++			struct kobj_attribute *attr, char *buf)
++{
++
++	/* create filesystem entry so kdump is phyp-dump aware */
++	return sprintf(buf, "%lx\n", phyp_dump_info->phyp_dump_at_boot);
++}
++
++static struct kobj_attribute pdl = __ATTR(phyp_dump_active, 0600,
++					show_phyp_dump_active,
++					NULL);
++
++static void register_dump_area(struct phyp_dump_header *ph, unsigned long addr)
++{
++	int rc;
++
++	/* Add addr value if not initialized before */
++	if (ph->cpu_data.destination_address == 0) {
++		ph->cpu_data.destination_address += addr;
++		ph->hpte_data.destination_address += addr;
++		ph->kernel_data.destination_address += addr;
++	}
++
++	/* ToDo Invalidate kdump and free memory range. */
++
++	do {
++		rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
++				1, ph, sizeof(struct phyp_dump_header));
++	} while (rtas_busy_delay(rc));
++
++	if (rc) {
++		printk(KERN_ERR "phyp-dump: unexpected error (%d) on "
++						"register\n", rc);
++		print_dump_header(ph);
++		return;
++	}
++
++	rc = sysfs_create_file(kernel_kobj, &pdl.attr);
++	if (rc)
++		printk(KERN_ERR "phyp-dump: unable to create sysfs"
++				" file (%d)\n", rc);
++}
++
++static
++void invalidate_last_dump(struct phyp_dump_header *ph, unsigned long addr)
++{
++	int rc;
++
++	/* Add addr value if not initialized before */
++	if (ph->cpu_data.destination_address == 0) {
++		ph->cpu_data.destination_address += addr;
++		ph->hpte_data.destination_address += addr;
++		ph->kernel_data.destination_address += addr;
++	}
++
++	do {
++		rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
++				2, ph, sizeof(struct phyp_dump_header));
++	} while (rtas_busy_delay(rc));
++
++	if (rc) {
++		printk(KERN_ERR "phyp-dump: unexpected error (%d) "
++						"on invalidate\n", rc);
++		print_dump_header(ph);
++	}
++}
++
++/* ------------------------------------------------- */
++/**
++ * release_memory_range -- release memory previously lmb_reserved
++ * @start_pfn: starting physical frame number
++ * @nr_pages: number of pages to free.
++ *
++ * This routine will release memory that had been previously
++ * lmb_reserved in early boot. The released memory becomes
++ * available for genreal use.
++ */
++static void release_memory_range(unsigned long start_pfn,
++			unsigned long nr_pages)
++{
++	struct page *rpage;
++	unsigned long end_pfn;
++	long i;
++
++	end_pfn = start_pfn + nr_pages;
++
++	for (i = start_pfn; i <= end_pfn; i++) {
++		rpage = pfn_to_page(i);
++		if (PageReserved(rpage)) {
++			ClearPageReserved(rpage);
++			init_page_count(rpage);
++			__free_page(rpage);
++			totalram_pages++;
++		}
++	}
++}
++
++/**
++ * track_freed_range -- Counts the range being freed.
++ * Once the counter goes to zero, it re-registers dump for
++ * future use.
++ */
++static void
++track_freed_range(unsigned long addr, unsigned long length)
++{
++	static unsigned long scratch_area_size, reserved_area_size;
++
++	if (addr < phyp_dump_info->init_reserve_start)
++		return;
++
++	if ((addr >= phyp_dump_info->init_reserve_start) &&
++	    (addr <= phyp_dump_info->init_reserve_start +
++	     phyp_dump_info->init_reserve_size))
++		reserved_area_size += length;
++
++	if ((addr >= phyp_dump_info->reserved_scratch_addr) &&
++	    (addr <= phyp_dump_info->reserved_scratch_addr +
++	     phyp_dump_info->reserved_scratch_size))
++		scratch_area_size += length;
++
++	if ((reserved_area_size == phyp_dump_info->init_reserve_size) &&
++	    (scratch_area_size == phyp_dump_info->reserved_scratch_size)) {
++
++		invalidate_last_dump(&phdr,
++				phyp_dump_info->reserved_scratch_addr);
++		register_dump_area(&phdr,
++				phyp_dump_info->reserved_scratch_addr);
++	}
++}
++
++/* ------------------------------------------------- */
++/**
++ * sysfs_release_region -- sysfs interface to release memory range.
++ *
++ * Usage:
++ *   "echo <start addr> <length> > /sys/kernel/release_region"
++ *
++ * Example:
++ *   "echo 0x40000000 0x10000000 > /sys/kernel/release_region"
++ *
++ * will release 256MB starting at 1GB.
++ */
++static ssize_t store_release_region(struct kobject *kobj,
++				struct kobj_attribute *attr,
++				const char *buf, size_t count)
++{
++	unsigned long start_addr, length, end_addr;
++	unsigned long start_pfn, nr_pages;
++	ssize_t ret;
++
++	ret = sscanf(buf, "%lx %lx", &start_addr, &length);
++	if (ret != 2)
++		return -EINVAL;
++
++	track_freed_range(start_addr, length);
++
++	/* Range-check - don't free any reserved memory that
++	 * wasn't reserved for phyp-dump */
++	if (start_addr < phyp_dump_info->init_reserve_start)
++		start_addr = phyp_dump_info->init_reserve_start;
++
++	end_addr = phyp_dump_info->init_reserve_start +
++			phyp_dump_info->init_reserve_size;
++	if (start_addr+length > end_addr)
++		length = end_addr - start_addr;
++
++	/* Release the region of memory assed in by user */
++	start_pfn = PFN_DOWN(start_addr);
++	nr_pages = PFN_DOWN(length);
++	release_memory_range(start_pfn, nr_pages);
++
++	return count;
++}
++
++static ssize_t show_release_region(struct kobject *kobj,
++			struct kobj_attribute *attr, char *buf)
++{
++	u64 second_addr_range;
++
++	/* total reserved size - start of scratch area */
++	second_addr_range = phyp_dump_info->init_reserve_size -
++				phyp_dump_info->reserved_scratch_size;
++	return sprintf(buf, "CPU:0x%lx-0x%lx: HPTE:0x%lx-0x%lx:"
++			    " DUMP:0x%lx-0x%lx, 0x%lx-0x%lx:\n",
++		phdr.cpu_data.destination_address,
++		phdr.cpu_data.length_copied,
++		phdr.hpte_data.destination_address,
++		phdr.hpte_data.length_copied,
++		phdr.kernel_data.destination_address,
++		phdr.kernel_data.length_copied,
++		phyp_dump_info->init_reserve_start,
++		second_addr_range);
++}
++
++static struct kobj_attribute rr = __ATTR(release_region, 0600,
++					show_release_region,
++					store_release_region);
++
++static int __init phyp_dump_setup(void)
++{
++	struct device_node *rtas;
++	const struct phyp_dump_header *dump_header = NULL;
++	unsigned long dump_area_start;
++	unsigned long dump_area_length;
++	int header_len = 0;
++	int rc;
++
++	/* If no memory was reserved in early boot, there is nothing to do */
++	if (phyp_dump_info->init_reserve_size == 0)
++		return 0;
++
++	/* Return if phyp dump not supported */
++	if (!phyp_dump_info->phyp_dump_configured)
++		return -ENOSYS;
++
++	/* Is there dump data waiting for us? If there isn't,
++	 * then register a new dump area, and release all of
++	 * the rest of the reserved ram.
++	 *
++	 * The /rtas/ibm,kernel-dump rtas node is present only
++	 * if there is dump data waiting for us.
++	 */
++	rtas = of_find_node_by_path("/rtas");
++	if (rtas) {
++		dump_header = of_get_property(rtas, "ibm,kernel-dump",
++						&header_len);
++		of_node_put(rtas);
++	}
++
++	print_dump_header(dump_header);
++	dump_area_length = init_dump_header(&phdr);
++	/* align down */
++	dump_area_start = phyp_dump_info->init_reserve_start & PAGE_MASK;
++
++	if (dump_header == NULL) {
++		register_dump_area(&phdr, dump_area_start);
++		return 0;
++	}
++
++	/* re-register the dump area, if old dump was invalid */
++	if ((dump_header) && (dump_header->status & DUMP_ERROR_FLAG)) {
++		invalidate_last_dump(&phdr, dump_area_start);
++		register_dump_area(&phdr, dump_area_start);
++		return 0;
++	}
++
++	if (dump_header) {
++		phyp_dump_info->reserved_scratch_addr =
++				dump_header->cpu_data.destination_address;
++		phyp_dump_info->reserved_scratch_size =
++				dump_header->cpu_data.source_length +
++				dump_header->hpte_data.source_length +
++				dump_header->kernel_data.source_length;
++	}
++
++	/* Should we create a dump_subsys, analogous to s390/ipl.c ? */
++	rc = sysfs_create_file(kernel_kobj, &rr.attr);
++	if (rc)
++		printk(KERN_ERR "phyp-dump: unable to create sysfs file (%d)\n",
++									rc);
++
++	/* ToDo: re-register the dump area, for next time. */
++	return 0;
++}
++machine_subsys_initcall(pseries, phyp_dump_setup);
++
++int __init early_init_dt_scan_phyp_dump(unsigned long node,
++		const char *uname, int depth, void *data)
++{
++	const unsigned int *sizes;
++
++	phyp_dump_info->phyp_dump_configured = 0;
++	phyp_dump_info->phyp_dump_is_active = 0;
++
++	if (depth != 1 || strcmp(uname, "rtas") != 0)
++		return 0;
++
++	if (of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL))
++		phyp_dump_info->phyp_dump_configured++;
++
++	if (of_get_flat_dt_prop(node, "ibm,dump-kernel", NULL))
++		phyp_dump_info->phyp_dump_is_active++;
++
++	sizes = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes",
++				    NULL);
++	if (!sizes)
++		return 0;
++
++	if (sizes[0] == 1)
++		phyp_dump_info->cpu_state_size = *((unsigned long *)&sizes[1]);
++
++	if (sizes[3] == 2)
++		phyp_dump_info->hpte_region_size =
++						*((unsigned long *)&sizes[4]);
++	return 1;
++}
++
++/* Look for phyp_dump= cmdline option */
++static int __init early_phyp_dump_enabled(char *p)
++{
++	phyp_dump_info->phyp_dump_at_boot = 1;
++
++        if (!p)
++                return 0;
++
++        if (strncmp(p, "1", 1) == 0)
++		phyp_dump_info->phyp_dump_at_boot = 1;
++        else if (strncmp(p, "0", 1) == 0)
++		phyp_dump_info->phyp_dump_at_boot = 0;
++
++        return 0;
++}
++early_param("phyp_dump", early_phyp_dump_enabled);
++
++/* Look for phyp_dump_reserve_size= cmdline option */
++static int __init early_phyp_dump_reserve_size(char *p)
++{
++        if (p)
++		phyp_dump_info->reserve_bootvar = memparse(p, &p);
++
++        return 0;
++}
++early_param("phyp_dump_reserve_size", early_phyp_dump_reserve_size);
+diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
+index 61136d0..9e17c0d 100644
+--- a/arch/powerpc/platforms/pseries/pseries.h
++++ b/arch/powerpc/platforms/pseries/pseries.h
+@@ -38,4 +38,6 @@ extern void pSeries_final_fixup(void);
+ /* Poweron flag used for enabling auto ups restart */
+ extern unsigned long rtas_poweron_auto;
+ 
++extern void find_udbg_vterm(void);
++
+ #endif /* _PSERIES_PSERIES_H */
+diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
+index a1ab25c..2b548af 100644
+--- a/arch/powerpc/platforms/pseries/ras.c
++++ b/arch/powerpc/platforms/pseries/ras.c
+@@ -67,8 +67,6 @@ static int ras_check_exception_token;
+ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);
+ static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
+ 
+-/* #define DEBUG */
+-
+ 
+ static void request_ras_irqs(struct device_node *np,
+ 			irq_handler_t handler,
+@@ -237,7 +235,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
+ 		printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
+ 		       *((unsigned long *)&ras_log_buf), status);
+ 
+-#ifndef DEBUG
++#ifndef DEBUG_RTAS_POWER_OFF
+ 		/* Don't actually power off when debugging so we can test
+ 		 * without actually failing while injecting errors.
+ 		 * Error data will not be logged to syslog.
+diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
+index 2800fce..ac75c10 100644
+--- a/arch/powerpc/platforms/pseries/reconfig.c
++++ b/arch/powerpc/platforms/pseries/reconfig.c
+@@ -222,14 +222,14 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length
+ 	tmp = strchr(buf, ' ');
+ 	if (!tmp) {
+ 		printk(KERN_ERR "property parse failed in %s at line %d\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		return NULL;
+ 	}
+ 	*tmp = '\0';
+ 
+ 	if (++tmp >= end) {
+ 		printk(KERN_ERR "property parse failed in %s at line %d\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		return NULL;
+ 	}
+ 
+@@ -238,12 +238,12 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length
+ 	*length = simple_strtoul(tmp, &tmp, 10);
+ 	if (*length == -1) {
+ 		printk(KERN_ERR "property parse failed in %s at line %d\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		return NULL;
+ 	}
+ 	if (*tmp != ' ' || ++tmp >= end) {
+ 		printk(KERN_ERR "property parse failed in %s at line %d\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		return NULL;
+ 	}
+ 
+@@ -252,12 +252,12 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length
+ 	tmp += *length;
+ 	if (tmp > end) {
+ 		printk(KERN_ERR "property parse failed in %s at line %d\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		return NULL;
+ 	}
+ 	else if (tmp < end && *tmp != ' ' && *tmp != '\0') {
+ 		printk(KERN_ERR "property parse failed in %s at line %d\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		return NULL;
+ 	}
+ 	tmp++;
+diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
+index e3078ce..befadd4 100644
+--- a/arch/powerpc/platforms/pseries/rtasd.c
++++ b/arch/powerpc/platforms/pseries/rtasd.c
+@@ -29,11 +29,6 @@
+ #include <asm/atomic.h>
+ #include <asm/machdep.h>
+ 
+-#if 0
+-#define DEBUG(A...)	printk(KERN_ERR A)
+-#else
+-#define DEBUG(A...)
+-#endif
+ 
+ static DEFINE_SPINLOCK(rtasd_log_lock);
+ 
+@@ -198,7 +193,7 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
+ 	unsigned long s;
+ 	int len = 0;
+ 
+-	DEBUG("logging event\n");
++	pr_debug("rtasd: logging event\n");
+ 	if (buf == NULL)
+ 		return;
+ 
+@@ -409,7 +404,8 @@ static int rtasd(void *unused)
+ 	daemonize("rtasd");
+ 
+ 	printk(KERN_DEBUG "RTAS daemon started\n");
+-	DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
++	pr_debug("rtasd: will sleep for %d milliseconds\n",
++		 (30000 / rtas_event_scan_rate));
+ 
+ 	/* See if we have any error stored in NVRAM */
+ 	memset(logdata, 0, rtas_error_log_max);
+@@ -428,9 +424,9 @@ static int rtasd(void *unused)
+ 	do_event_scan_all_cpus(1000);
+ 
+ 	if (surveillance_timeout != -1) {
+-		DEBUG("enabling surveillance\n");
++		pr_debug("rtasd: enabling surveillance\n");
+ 		enable_surveillance(surveillance_timeout);
+-		DEBUG("surveillance enabled\n");
++		pr_debug("rtasd: surveillance enabled\n");
+ 	}
+ 
+ 	/* Delay should be at least one second since some
+diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
+index 8e1ef16..bec3803 100644
+--- a/arch/powerpc/platforms/pseries/scanlog.c
++++ b/arch/powerpc/platforms/pseries/scanlog.c
+@@ -38,9 +38,7 @@
+ #define SCANLOG_HWERROR -1
+ #define SCANLOG_CONTINUE 1
+ 
+-#define DEBUG(A...) do { if (scanlog_debug) printk(KERN_ERR "scanlog: " A); } while (0)
+ 
+-static int scanlog_debug;
+ static unsigned int ibm_scan_log_dump;			/* RTAS token */
+ static struct proc_dir_entry *proc_ppc64_scan_log_dump;	/* The proc file */
+ 
+@@ -86,14 +84,14 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
+ 		memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE);
+ 		spin_unlock(&rtas_data_buf_lock);
+ 
+-		DEBUG("status=%d, data[0]=%x, data[1]=%x, data[2]=%x\n",
+-		      status, data[0], data[1], data[2]);
++		pr_debug("scanlog: status=%d, data[0]=%x, data[1]=%x, " \
++			 "data[2]=%x\n", status, data[0], data[1], data[2]);
+ 		switch (status) {
+ 		    case SCANLOG_COMPLETE:
+-			DEBUG("hit eof\n");
++			pr_debug("scanlog: hit eof\n");
+ 			return 0;
+ 		    case SCANLOG_HWERROR:
+-			DEBUG("hardware error reading scan log data\n");
++			pr_debug("scanlog: hardware error reading data\n");
+ 			return -EIO;
+ 		    case SCANLOG_CONTINUE:
+ 			/* We may or may not have data yet */
+@@ -110,7 +108,8 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
+ 			/* Assume extended busy */
+ 			wait_time = rtas_busy_delay_time(status);
+ 			if (!wait_time) {
+-				printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status);
++				printk(KERN_ERR "scanlog: unknown error " \
++				       "from rtas: %d\n", status);
+ 				return -EIO;
+ 			}
+ 		}
+@@ -134,15 +133,9 @@ static ssize_t scanlog_write(struct file * file, const char __user * buf,
+ 
+ 	if (buf) {
+ 		if (strncmp(stkbuf, "reset", 5) == 0) {
+-			DEBUG("reset scanlog\n");
++			pr_debug("scanlog: reset scanlog\n");
+ 			status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, 0, 0);
+-			DEBUG("rtas returns %d\n", status);
+-		} else if (strncmp(stkbuf, "debugon", 7) == 0) {
+-			printk(KERN_ERR "scanlog: debug on\n");
+-			scanlog_debug = 1;
+-		} else if (strncmp(stkbuf, "debugoff", 8) == 0) {
+-			printk(KERN_ERR "scanlog: debug off\n");
+-			scanlog_debug = 0;
++			pr_debug("scanlog: rtas returns %d\n", status);
+ 		}
+ 	}
+ 	return count;
+@@ -195,31 +188,30 @@ const struct file_operations scanlog_fops = {
+ static int __init scanlog_init(void)
+ {
+ 	struct proc_dir_entry *ent;
++	void *data;
++	int err = -ENOMEM;
+ 
+ 	ibm_scan_log_dump = rtas_token("ibm,scan-log-dump");
+-	if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE) {
+-		printk(KERN_ERR "scan-log-dump not implemented on this system\n");
+-		return -EIO;
+-	}
++	if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE)
++		return -ENODEV;
+ 
+-        ent = create_proc_entry("ppc64/rtas/scan-log-dump",  S_IRUSR, NULL);
+-	if (ent) {
+-		ent->proc_fops = &scanlog_fops;
+-		/* Ideally we could allocate a buffer < 4G */
+-		ent->data = kmalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+-		if (!ent->data) {
+-			printk(KERN_ERR "Failed to allocate a buffer\n");
+-			remove_proc_entry("scan-log-dump", ent->parent);
+-			return -ENOMEM;
+-		}
+-		((unsigned int *)ent->data)[0] = 0;
+-	} else {
+-		printk(KERN_ERR "Failed to create ppc64/scan-log-dump proc entry\n");
+-		return -EIO;
+-	}
++	/* Ideally we could allocate a buffer < 4G */
++	data = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
++	if (!data)
++		goto err;
++
++	ent = proc_create("ppc64/rtas/scan-log-dump", S_IRUSR, NULL,
++			  &scanlog_fops);
++	if (!ent)
++		goto err;
++
++	ent->data = data;
+ 	proc_ppc64_scan_log_dump = ent;
+ 
+ 	return 0;
++err:
++	kfree(data);
++	return err;
+ }
+ 
+ static void __exit scanlog_cleanup(void)
+diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
+index fdb9b1c..f5d29f5 100644
+--- a/arch/powerpc/platforms/pseries/setup.c
++++ b/arch/powerpc/platforms/pseries/setup.c
+@@ -16,8 +16,6 @@
+  * bootup setup stuff..
+  */
+ 
+-#undef DEBUG
+-
+ #include <linux/cpu.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+@@ -70,14 +68,6 @@
+ #include "plpar_wrappers.h"
+ #include "pseries.h"
+ 
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/* move those away to a .h */
+-extern void find_udbg_vterm(void);
+ 
+ int fwnmi_active;  /* TRUE if an FWNMI handler is present */
+ 
+@@ -127,14 +117,60 @@ void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
+ 	desc->chip->eoi(irq);
+ }
+ 
+-static void __init pseries_mpic_init_IRQ(void)
++static void __init pseries_setup_i8259_cascade(void)
+ {
+-	struct device_node *np, *old, *cascade = NULL;
+-        const unsigned int *addrp;
++	struct device_node *np, *old, *found = NULL;
++	unsigned int cascade;
++	const u32 *addrp;
+ 	unsigned long intack = 0;
++	int naddr;
++
++	for_each_node_by_type(np, "interrupt-controller") {
++		if (of_device_is_compatible(np, "chrp,iic")) {
++			found = np;
++			break;
++		}
++	}
++
++	if (found == NULL) {
++		printk(KERN_DEBUG "pic: no ISA interrupt controller\n");
++		return;
++	}
++
++	cascade = irq_of_parse_and_map(found, 0);
++	if (cascade == NO_IRQ) {
++		printk(KERN_ERR "pic: failed to map cascade interrupt");
++		return;
++	}
++	pr_debug("pic: cascade mapped to irq %d\n", cascade);
++
++	for (old = of_node_get(found); old != NULL ; old = np) {
++		np = of_get_parent(old);
++		of_node_put(old);
++		if (np == NULL)
++			break;
++		if (strcmp(np->name, "pci") != 0)
++			continue;
++		addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL);
++		if (addrp == NULL)
++			continue;
++		naddr = of_n_addr_cells(np);
++		intack = addrp[naddr-1];
++		if (naddr > 1)
++			intack |= ((unsigned long)addrp[naddr-2]) << 32;
++	}
++	if (intack)
++		printk(KERN_DEBUG "pic: PCI 8259 intack at 0x%016lx\n", intack);
++	i8259_init(found, intack);
++	of_node_put(found);
++	set_irq_chained_handler(cascade, pseries_8259_cascade);
++}
++
++static void __init pseries_mpic_init_IRQ(void)
++{
++	struct device_node *np;
+ 	const unsigned int *opprop;
+ 	unsigned long openpic_addr = 0;
+-	unsigned int cascade_irq;
+ 	int naddr, n, i, opplen;
+ 	struct mpic *mpic;
+ 
+@@ -167,43 +203,13 @@ static void __init pseries_mpic_init_IRQ(void)
+ 	mpic_init(mpic);
+ 
+ 	/* Look for cascade */
+-	for_each_node_by_type(np, "interrupt-controller")
+-		if (of_device_is_compatible(np, "chrp,iic")) {
+-			cascade = np;
+-			break;
+-		}
+-	if (cascade == NULL)
+-		return;
+-
+-	cascade_irq = irq_of_parse_and_map(cascade, 0);
+-	if (cascade_irq == NO_IRQ) {
+-		printk(KERN_ERR "mpic: failed to map cascade interrupt");
+-		return;
+-	}
++	pseries_setup_i8259_cascade();
++}
+ 
+-	/* Check ACK type */
+-	for (old = of_node_get(cascade); old != NULL ; old = np) {
+-		np = of_get_parent(old);
+-		of_node_put(old);
+-		if (np == NULL)
+-			break;
+-		if (strcmp(np->name, "pci") != 0)
+-			continue;
+-		addrp = of_get_property(np, "8259-interrupt-acknowledge",
+-					    NULL);
+-		if (addrp == NULL)
+-			continue;
+-		naddr = of_n_addr_cells(np);
+-		intack = addrp[naddr-1];
+-		if (naddr > 1)
+-			intack |= ((unsigned long)addrp[naddr-2]) << 32;
+-	}
+-	if (intack)
+-		printk(KERN_DEBUG "mpic: PCI 8259 intack at 0x%016lx\n",
+-		       intack);
+-	i8259_init(cascade, intack);
+-	of_node_put(cascade);
+-	set_irq_chained_handler(cascade_irq, pseries_8259_cascade);
++static void __init pseries_xics_init_IRQ(void)
++{
++	xics_init_IRQ();
++	pseries_setup_i8259_cascade();
+ }
+ 
+ static void pseries_lpar_enable_pmcs(void)
+@@ -235,7 +241,7 @@ static void __init pseries_discover_pic(void)
+ 			smp_init_pseries_mpic();
+ 			return;
+ 		} else if (strstr(typep, "ppc-xicp")) {
+-			ppc_md.init_IRQ       = xics_init_IRQ;
++			ppc_md.init_IRQ       = pseries_xics_init_IRQ;
+ 			setup_kexec_cpu_down_xics();
+ 			smp_init_pseries_xics();
+ 			return;
+@@ -313,7 +319,7 @@ static int pseries_set_xdabr(unsigned long dabr)
+  */
+ static void __init pSeries_init_early(void)
+ {
+-	DBG(" -> pSeries_init_early()\n");
++	pr_debug(" -> pSeries_init_early()\n");
+ 
+ 	if (firmware_has_feature(FW_FEATURE_LPAR))
+ 		find_udbg_vterm();
+@@ -325,7 +331,7 @@ static void __init pSeries_init_early(void)
+ 
+ 	iommu_init_early_pSeries();
+ 
+-	DBG(" <- pSeries_init_early()\n");
++	pr_debug(" <- pSeries_init_early()\n");
+ }
+ 
+ /*
+@@ -370,7 +376,7 @@ static int __init pSeries_probe(void)
+ 	    of_flat_dt_is_compatible(root, "IBM,CBEA"))
+ 		return 0;
+ 
+-	DBG("pSeries detected, looking for LPAR capability...\n");
++	pr_debug("pSeries detected, looking for LPAR capability...\n");
+ 
+ 	/* Now try to figure out if we are running on LPAR */
+ 	of_scan_flat_dt(pSeries_probe_hypertas, NULL);
+@@ -380,8 +386,8 @@ static int __init pSeries_probe(void)
+ 	else
+ 		hpte_init_native();
+ 
+-	DBG("Machine is%s LPAR !\n",
+-	    (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
++	pr_debug("Machine is%s LPAR !\n",
++	         (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
+ 
+ 	return 1;
+ }
+@@ -393,6 +399,7 @@ static void pseries_dedicated_idle_sleep(void)
+ { 
+ 	unsigned int cpu = smp_processor_id();
+ 	unsigned long start_snooze;
++	unsigned long in_purr, out_purr;
+ 
+ 	/*
+ 	 * Indicate to the HV that we are idle. Now would be
+@@ -400,6 +407,7 @@ static void pseries_dedicated_idle_sleep(void)
+ 	 */
+ 	get_lppaca()->idle = 1;
+ 	get_lppaca()->donate_dedicated_cpu = 1;
++	in_purr = mfspr(SPRN_PURR);
+ 
+ 	/*
+ 	 * We come in with interrupts disabled, and need_resched()
+@@ -432,6 +440,8 @@ static void pseries_dedicated_idle_sleep(void)
+ 
+ out:
+ 	HMT_medium();
++	out_purr = mfspr(SPRN_PURR);
++	get_lppaca()->wait_state_cycles += out_purr - in_purr;
+ 	get_lppaca()->donate_dedicated_cpu = 0;
+ 	get_lppaca()->idle = 0;
+ }
+diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
+index ea4c659..9d8f8c8 100644
+--- a/arch/powerpc/platforms/pseries/smp.c
++++ b/arch/powerpc/platforms/pseries/smp.c
+@@ -12,7 +12,6 @@
+  *      2 of the License, or (at your option) any later version.
+  */
+ 
+-#undef DEBUG
+ 
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -51,12 +50,6 @@
+ #include "plpar_wrappers.h"
+ #include "pseries.h"
+ 
+-#ifdef DEBUG
+-#include <asm/udbg.h>
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+ 
+ /*
+  * The primary thread of each non-boot processor is recorded here before
+@@ -231,7 +224,7 @@ static void __init smp_init_pseries(void)
+ {
+ 	int i;
+ 
+-	DBG(" -> smp_init_pSeries()\n");
++	pr_debug(" -> smp_init_pSeries()\n");
+ 
+ 	/* Mark threads which are still spinning in hold loops. */
+ 	if (cpu_has_feature(CPU_FTR_SMT)) {
+@@ -255,7 +248,7 @@ static void __init smp_init_pseries(void)
+ 		smp_ops->take_timebase = pSeries_take_timebase;
+ 	}
+ 
+-	DBG(" <- smp_init_pSeries()\n");
++	pr_debug(" <- smp_init_pSeries()\n");
+ }
+ 
+ #ifdef CONFIG_MPIC
+diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
+index a977f20..ebebc28 100644
+--- a/arch/powerpc/platforms/pseries/xics.c
++++ b/arch/powerpc/platforms/pseries/xics.c
+@@ -9,7 +9,6 @@
+  *  2 of the License, or (at your option) any later version.
+  */
+ 
+-#undef DEBUG
+ 
+ #include <linux/types.h>
+ #include <linux/threads.h>
+@@ -516,6 +515,8 @@ static struct irq_chip xics_pic_lpar = {
+ 	.set_affinity = xics_set_affinity
+ };
+ 
++/* Points to the irq_chip we're actually using */
++static struct irq_chip *xics_irq_chip;
+ 
+ static int xics_host_match(struct irq_host *h, struct device_node *node)
+ {
+@@ -526,23 +527,13 @@ static int xics_host_match(struct irq_host *h, struct device_node *node)
+ 	return !of_device_is_compatible(node, "chrp,iic");
+ }
+ 
+-static int xics_host_map_direct(struct irq_host *h, unsigned int virq,
+-				irq_hw_number_t hw)
++static int xics_host_map(struct irq_host *h, unsigned int virq,
++			 irq_hw_number_t hw)
+ {
+-	pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
++	pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
+ 
+ 	get_irq_desc(virq)->status |= IRQ_LEVEL;
+-	set_irq_chip_and_handler(virq, &xics_pic_direct, handle_fasteoi_irq);
+-	return 0;
+-}
+-
+-static int xics_host_map_lpar(struct irq_host *h, unsigned int virq,
+-			      irq_hw_number_t hw)
+-{
+-	pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
+-
+-	get_irq_desc(virq)->status |= IRQ_LEVEL;
+-	set_irq_chip_and_handler(virq, &xics_pic_lpar, handle_fasteoi_irq);
++	set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
+ 	return 0;
+ }
+ 
+@@ -561,27 +552,20 @@ static int xics_host_xlate(struct irq_host *h, struct device_node *ct,
+ 	return 0;
+ }
+ 
+-static struct irq_host_ops xics_host_direct_ops = {
++static struct irq_host_ops xics_host_ops = {
+ 	.match = xics_host_match,
+-	.map = xics_host_map_direct,
+-	.xlate = xics_host_xlate,
+-};
+-
+-static struct irq_host_ops xics_host_lpar_ops = {
+-	.match = xics_host_match,
+-	.map = xics_host_map_lpar,
++	.map = xics_host_map,
+ 	.xlate = xics_host_xlate,
+ };
+ 
+ static void __init xics_init_host(void)
+ {
+-	struct irq_host_ops *ops;
+-
+ 	if (firmware_has_feature(FW_FEATURE_LPAR))
+-		ops = &xics_host_lpar_ops;
++		xics_irq_chip = &xics_pic_lpar;
+ 	else
+-		ops = &xics_host_direct_ops;
+-	xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, ops,
++		xics_irq_chip = &xics_pic_direct;
++
++	xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, &xics_host_ops,
+ 				   XICS_IRQ_SPURIOUS);
+ 	BUG_ON(xics_host == NULL);
+ 	irq_set_default_host(xics_host);
+@@ -655,52 +639,6 @@ static void __init xics_init_one_node(struct device_node *np,
+ 	}
+ }
+ 
+-
+-static void __init xics_setup_8259_cascade(void)
+-{
+-	struct device_node *np, *old, *found = NULL;
+-	int cascade, naddr;
+-	const u32 *addrp;
+-	unsigned long intack = 0;
+-
+-	for_each_node_by_type(np, "interrupt-controller")
+-		if (of_device_is_compatible(np, "chrp,iic")) {
+-			found = np;
+-			break;
+-		}
+-	if (found == NULL) {
+-		printk(KERN_DEBUG "xics: no ISA interrupt controller\n");
+-		return;
+-	}
+-	cascade = irq_of_parse_and_map(found, 0);
+-	if (cascade == NO_IRQ) {
+-		printk(KERN_ERR "xics: failed to map cascade interrupt");
+-		return;
+-	}
+-	pr_debug("xics: cascade mapped to irq %d\n", cascade);
+-
+-	for (old = of_node_get(found); old != NULL ; old = np) {
+-		np = of_get_parent(old);
+-		of_node_put(old);
+-		if (np == NULL)
+-			break;
+-		if (strcmp(np->name, "pci") != 0)
+-			continue;
+-		addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL);
+-		if (addrp == NULL)
+-			continue;
+-		naddr = of_n_addr_cells(np);
+-		intack = addrp[naddr-1];
+-		if (naddr > 1)
+-			intack |= ((unsigned long)addrp[naddr-2]) << 32;
+-	}
+-	if (intack)
+-		printk(KERN_DEBUG "xics: PCI 8259 intack at 0x%016lx\n", intack);
+-	i8259_init(found, intack);
+-	of_node_put(found);
+-	set_irq_chained_handler(cascade, pseries_8259_cascade);
+-}
+-
+ void __init xics_init_IRQ(void)
+ {
+ 	struct device_node *np;
+@@ -733,8 +671,6 @@ void __init xics_init_IRQ(void)
+ 
+ 	xics_setup_cpu();
+ 
+-	xics_setup_8259_cascade();
+-
+ 	ppc64_boot_msg(0x21, "XICS Done");
+ }
+ 
+diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
+index c26bcff..1c5321a 100644
+--- a/arch/powerpc/platforms/pseries/xics.h
++++ b/arch/powerpc/platforms/pseries/xics.h
+@@ -28,7 +28,4 @@ struct xics_ipi_struct {
+ 
+ extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+ 
+-struct irq_desc;
+-extern void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc);
+-
+ #endif /* _POWERPC_KERNEL_XICS_H */
+diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
+index 15f3e85..6d386d0 100644
+--- a/arch/powerpc/sysdev/Makefile
++++ b/arch/powerpc/sysdev/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_U3_DART)		+= dart_iommu.o
+ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
+ obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
+ obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o
++obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
+ obj-$(CONFIG_RAPIDIO)		+= fsl_rio.o
+ obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
+ obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
+@@ -27,6 +28,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
+ obj-$(CONFIG_PPC_I8259)		+= i8259.o
+ obj-$(CONFIG_IPIC)		+= ipic.o
+ obj-$(CONFIG_4xx)		+= uic.o
++obj-$(CONFIG_4xx_SOC)		+= ppc4xx_soc.o
+ obj-$(CONFIG_XILINX_VIRTEX)	+= xilinx_intc.o
+ obj-$(CONFIG_OF_RTC)		+= of_rtc.o
+ ifeq ($(CONFIG_PCI),y)
+diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
+index df8bd2b..58292a0 100644
+--- a/arch/powerpc/sysdev/cpm1.c
++++ b/arch/powerpc/sysdev/cpm1.c
+@@ -44,9 +44,6 @@
+ 
+ #define CPM_MAP_SIZE    (0x4000)
+ 
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-static void m8xx_cpm_dpinit(void);
+-#endif
+ cpm8xx_t __iomem *cpmp;  /* Pointer to comm processor space */
+ immap_t __iomem *mpc8xx_immr;
+ static cpic8xx_t __iomem *cpic_reg;
+@@ -229,12 +226,7 @@ void __init cpm_reset(void)
+ 	out_be32(&siu_conf->sc_sdcr, 1);
+ 	immr_unmap(siu_conf);
+ 
+-#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ 	cpm_muram_init();
+-#else
+-	/* Reclaim the DP memory for our use. */
+-	m8xx_cpm_dpinit();
+-#endif
+ }
+ 
+ static DEFINE_SPINLOCK(cmd_lock);
+@@ -257,7 +249,7 @@ int cpm_command(u32 command, u8 opcode)
+ 		if ((in_be16(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
+ 			goto out;
+ 
+-	printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
++	printk(KERN_ERR "%s(): Not able to issue CPM command\n", __func__);
+ 	ret = -EIO;
+ out:
+ 	spin_unlock_irqrestore(&cmd_lock, flags);
+@@ -293,110 +285,6 @@ cpm_setbrg(uint brg, uint rate)
+ 			      CPM_BRG_EN | CPM_BRG_DIV16);
+ }
+ 
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-/*
+- * dpalloc / dpfree bits.
+- */
+-static spinlock_t cpm_dpmem_lock;
+-/*
+- * 16 blocks should be enough to satisfy all requests
+- * until the memory subsystem goes up...
+- */
+-static rh_block_t cpm_boot_dpmem_rh_block[16];
+-static rh_info_t cpm_dpmem_info;
+-
+-#define CPM_DPMEM_ALIGNMENT	8
+-static u8 __iomem *dpram_vbase;
+-static phys_addr_t dpram_pbase;
+-
+-static void m8xx_cpm_dpinit(void)
+-{
+-	spin_lock_init(&cpm_dpmem_lock);
+-
+-	dpram_vbase = cpmp->cp_dpmem;
+-	dpram_pbase = get_immrbase() + offsetof(immap_t, im_cpm.cp_dpmem);
+-
+-	/* Initialize the info header */
+-	rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
+-			sizeof(cpm_boot_dpmem_rh_block) /
+-			sizeof(cpm_boot_dpmem_rh_block[0]),
+-			cpm_boot_dpmem_rh_block);
+-
+-	/*
+-	 * Attach the usable dpmem area.
+-	 * XXX: This is actually crap.  CPM_DATAONLY_BASE and
+-	 * CPM_DATAONLY_SIZE are a subset of the available dparm.  It varies
+-	 * with the processor and the microcode patches applied / activated.
+-	 * But the following should be at least safe.
+-	 */
+-	rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+-}
+-
+-/*
+- * Allocate the requested size worth of DP memory.
+- * This function returns an offset into the DPRAM area.
+- * Use cpm_dpram_addr() to get the virtual address of the area.
+- */
+-unsigned long cpm_dpalloc(uint size, uint align)
+-{
+-	unsigned long start;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+-	cpm_dpmem_info.alignment = align;
+-	start = rh_alloc(&cpm_dpmem_info, size, "commproc");
+-	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+-	return (uint)start;
+-}
+-EXPORT_SYMBOL(cpm_dpalloc);
+-
+-int cpm_dpfree(unsigned long offset)
+-{
+-	int ret;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+-	ret = rh_free(&cpm_dpmem_info, offset);
+-	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+-	return ret;
+-}
+-EXPORT_SYMBOL(cpm_dpfree);
+-
+-unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
+-{
+-	unsigned long start;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+-	cpm_dpmem_info.alignment = align;
+-	start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
+-	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+-	return start;
+-}
+-EXPORT_SYMBOL(cpm_dpalloc_fixed);
+-
+-void cpm_dpdump(void)
+-{
+-	rh_dump(&cpm_dpmem_info);
+-}
+-EXPORT_SYMBOL(cpm_dpdump);
+-
+-void *cpm_dpram_addr(unsigned long offset)
+-{
+-	return (void *)(dpram_vbase + offset);
+-}
+-EXPORT_SYMBOL(cpm_dpram_addr);
+-
+-uint cpm_dpram_phys(u8 *addr)
+-{
+-	return (dpram_pbase + (uint)(addr - dpram_vbase));
+-}
+-EXPORT_SYMBOL(cpm_dpram_phys);
+-#endif /* !CONFIG_PPC_CPM_NEW_BINDING */
+-
+ struct cpm_ioport16 {
+ 	__be16 dir, par, odr_sor, dat, intr;
+ 	__be16 res[3];
+diff --git a/arch/powerpc/sysdev/cpm2.c b/arch/powerpc/sysdev/cpm2.c
+index dd066bb..5a6c5df 100644
+--- a/arch/powerpc/sysdev/cpm2.c
++++ b/arch/powerpc/sysdev/cpm2.c
+@@ -46,10 +46,6 @@
+ 
+ #include <sysdev/fsl_soc.h>
+ 
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-static void cpm2_dpinit(void);
+-#endif
+-
+ cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor space */
+ 
+ /* We allocate this here because it is used almost exclusively for
+@@ -71,15 +67,17 @@ void __init cpm2_reset(void)
+ 
+ 	/* Reclaim the DP memory for our use.
+ 	 */
+-#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ 	cpm_muram_init();
+-#else
+-	cpm2_dpinit();
+-#endif
+ 
+ 	/* Tell everyone where the comm processor resides.
+ 	 */
+ 	cpmp = &cpm2_immr->im_cpm;
++
++#ifndef CONFIG_PPC_EARLY_DEBUG_CPM
++	/* Reset the CPM.
++	 */
++	cpm_command(CPM_CR_RST, 0);
++#endif
+ }
+ 
+ static DEFINE_SPINLOCK(cmd_lock);
+@@ -99,7 +97,7 @@ int cpm_command(u32 command, u8 opcode)
+ 		if ((in_be32(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
+ 			goto out;
+ 
+-	printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
++	printk(KERN_ERR "%s(): Not able to issue CPM command\n", __func__);
+ 	ret = -EIO;
+ out:
+ 	spin_unlock_irqrestore(&cmd_lock, flags);
+@@ -347,95 +345,6 @@ int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)
+ 	return ret;
+ }
+ 
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-/*
+- * dpalloc / dpfree bits.
+- */
+-static spinlock_t cpm_dpmem_lock;
+-/* 16 blocks should be enough to satisfy all requests
+- * until the memory subsystem goes up... */
+-static rh_block_t cpm_boot_dpmem_rh_block[16];
+-static rh_info_t cpm_dpmem_info;
+-static u8 __iomem *im_dprambase;
+-
+-static void cpm2_dpinit(void)
+-{
+-	spin_lock_init(&cpm_dpmem_lock);
+-
+-	/* initialize the info header */
+-	rh_init(&cpm_dpmem_info, 1,
+-			sizeof(cpm_boot_dpmem_rh_block) /
+-			sizeof(cpm_boot_dpmem_rh_block[0]),
+-			cpm_boot_dpmem_rh_block);
+-
+-	im_dprambase = cpm2_immr;
+-
+-	/* Attach the usable dpmem area */
+-	/* XXX: This is actually crap. CPM_DATAONLY_BASE and
+-	 * CPM_DATAONLY_SIZE is only a subset of the available dpram. It
+-	 * varies with the processor and the microcode patches activated.
+-	 * But the following should be at least safe.
+-	 */
+-	rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+-}
+-
+-/* This function returns an index into the DPRAM area.
+- */
+-unsigned long cpm_dpalloc(uint size, uint align)
+-{
+-	unsigned long start;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+-	cpm_dpmem_info.alignment = align;
+-	start = rh_alloc(&cpm_dpmem_info, size, "commproc");
+-	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+-	return (uint)start;
+-}
+-EXPORT_SYMBOL(cpm_dpalloc);
+-
+-int cpm_dpfree(unsigned long offset)
+-{
+-	int ret;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+-	ret = rh_free(&cpm_dpmem_info, offset);
+-	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+-	return ret;
+-}
+-EXPORT_SYMBOL(cpm_dpfree);
+-
+-/* not sure if this is ever needed */
+-unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
+-{
+-	unsigned long start;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+-	cpm_dpmem_info.alignment = align;
+-	start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
+-	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+-	return start;
+-}
+-EXPORT_SYMBOL(cpm_dpalloc_fixed);
+-
+-void cpm_dpdump(void)
+-{
+-	rh_dump(&cpm_dpmem_info);
+-}
+-EXPORT_SYMBOL(cpm_dpdump);
+-
+-void *cpm_dpram_addr(unsigned long offset)
+-{
+-	return (void *)(im_dprambase + offset);
+-}
+-EXPORT_SYMBOL(cpm_dpram_addr);
+-#endif /* !CONFIG_PPC_CPM_NEW_BINDING */
+-
+ struct cpm2_ioports {
+ 	u32 dir, par, sor, odr, dat;
+ 	u32 res[3];
+diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
+index 165981c..cb7df2d 100644
+--- a/arch/powerpc/sysdev/cpm_common.c
++++ b/arch/powerpc/sysdev/cpm_common.c
+@@ -58,7 +58,6 @@ void __init udbg_init_cpm(void)
+ }
+ #endif
+ 
+-#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ static spinlock_t cpm_muram_lock;
+ static rh_block_t cpm_boot_muram_rh_block[16];
+ static rh_info_t cpm_muram_info;
+@@ -199,5 +198,3 @@ dma_addr_t cpm_muram_dma(void __iomem *addr)
+ 	return muram_pbase + ((u8 __iomem *)addr - muram_vbase);
+ }
+ EXPORT_SYMBOL(cpm_muram_dma);
+-
+-#endif /* CONFIG_PPC_CPM_NEW_BINDING */
+diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
+index e0e24b0..005c2ec 100644
+--- a/arch/powerpc/sysdev/dart_iommu.c
++++ b/arch/powerpc/sysdev/dart_iommu.c
+@@ -37,6 +37,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/vmalloc.h>
+ #include <linux/suspend.h>
++#include <linux/lmb.h>
+ #include <asm/io.h>
+ #include <asm/prom.h>
+ #include <asm/iommu.h>
+@@ -44,7 +45,6 @@
+ #include <asm/machdep.h>
+ #include <asm/abs_addr.h>
+ #include <asm/cacheflush.h>
+-#include <asm/lmb.h>
+ #include <asm/ppc-pci.h>
+ 
+ #include "dart.h"
+diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
+new file mode 100644
+index 0000000..422c8fa
+--- /dev/null
++++ b/arch/powerpc/sysdev/fsl_lbc.c
+@@ -0,0 +1,129 @@
++/*
++ * Freescale LBC and UPM routines.
++ *
++ * Copyright (c) 2007-2008  MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at 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/kernel.h>
++#include <linux/of.h>
++#include <asm/fsl_lbc.h>
++
++spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
++
++struct fsl_lbc_regs __iomem *fsl_lbc_regs;
++EXPORT_SYMBOL(fsl_lbc_regs);
++
++static char __initdata *compat_lbc[] = {
++	"fsl,pq2-localbus",
++	"fsl,pq2pro-localbus",
++	"fsl,pq3-localbus",
++	"fsl,elbc",
++};
++
++static int __init fsl_lbc_init(void)
++{
++	struct device_node *lbus;
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
++		lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
++		if (lbus)
++			goto found;
++	}
++	return -ENODEV;
++
++found:
++	fsl_lbc_regs = of_iomap(lbus, 0);
++	of_node_put(lbus);
++	if (!fsl_lbc_regs)
++		return -ENOMEM;
++	return 0;
++}
++arch_initcall(fsl_lbc_init);
++
++/**
++ * fsl_lbc_find - find Localbus bank
++ * @addr_base:	base address of the memory bank
++ *
++ * This function walks LBC banks comparing "Base address" field of the BR
++ * registers with the supplied addr_base argument. When bases match this
++ * function returns bank number (starting with 0), otherwise it returns
++ * appropriate errno value.
++ */
++int fsl_lbc_find(phys_addr_t addr_base)
++{
++	int i;
++
++	if (!fsl_lbc_regs)
++		return -ENODEV;
++
++	for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
++		__be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
++		__be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
++
++		if (br & BR_V && (br & or & BR_BA) == addr_base)
++			return i;
++	}
++
++	return -ENOENT;
++}
++EXPORT_SYMBOL(fsl_lbc_find);
++
++/**
++ * fsl_upm_find - find pre-programmed UPM via base address
++ * @addr_base:	base address of the memory bank controlled by the UPM
++ * @upm:	pointer to the allocated fsl_upm structure
++ *
++ * This function fills fsl_upm structure so you can use it with the rest of
++ * UPM API. On success this function returns 0, otherwise it returns
++ * appropriate errno value.
++ */
++int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
++{
++	int bank;
++	__be32 br;
++
++	bank = fsl_lbc_find(addr_base);
++	if (bank < 0)
++		return bank;
++
++	br = in_be32(&fsl_lbc_regs->bank[bank].br);
++
++	switch (br & BR_MSEL) {
++	case BR_MS_UPMA:
++		upm->mxmr = &fsl_lbc_regs->mamr;
++		break;
++	case BR_MS_UPMB:
++		upm->mxmr = &fsl_lbc_regs->mbmr;
++		break;
++	case BR_MS_UPMC:
++		upm->mxmr = &fsl_lbc_regs->mcmr;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	switch (br & BR_PS) {
++	case BR_PS_8:
++		upm->width = 8;
++		break;
++	case BR_PS_16:
++		upm->width = 16;
++		break;
++	case BR_PS_32:
++		upm->width = 32;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL(fsl_upm_find);
+diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
+index 2c5388c..5c1b246 100644
+--- a/arch/powerpc/sysdev/fsl_soc.c
++++ b/arch/powerpc/sysdev/fsl_soc.c
+@@ -75,6 +75,33 @@ phys_addr_t get_immrbase(void)
+ 
+ EXPORT_SYMBOL(get_immrbase);
+ 
++static u32 sysfreq = -1;
++
++u32 fsl_get_sys_freq(void)
++{
++	struct device_node *soc;
++	const u32 *prop;
++	int size;
++
++	if (sysfreq != -1)
++		return sysfreq;
++
++	soc = of_find_node_by_type(NULL, "soc");
++	if (!soc)
++		return -1;
++
++	prop = of_get_property(soc, "clock-frequency", &size);
++	if (!prop || size != sizeof(*prop) || *prop == 0)
++		prop = of_get_property(soc, "bus-frequency", &size);
++
++	if (prop && size == sizeof(*prop))
++		sysfreq = *prop;
++
++	of_node_put(soc);
++	return sysfreq;
++}
++EXPORT_SYMBOL(fsl_get_sys_freq);
++
+ #if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx)
+ 
+ static u32 brgfreq = -1;
+@@ -341,7 +368,7 @@ static int __init gfar_of_init(void)
+ 				goto unreg;
+ 			}
+ 
+-			gfar_data.bus_id = 0;
++			snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "0");
+ 			gfar_data.phy_id = fixed_link[0];
+ 		} else {
+ 			phy = of_find_node_by_phandle(*ph);
+@@ -362,7 +389,8 @@ static int __init gfar_of_init(void)
+ 			}
+ 
+ 			gfar_data.phy_id = *id;
+-			gfar_data.bus_id = res.start;
++			snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "%x",
++					res.start);
+ 
+ 			of_node_put(phy);
+ 			of_node_put(mdio);
+@@ -516,9 +544,9 @@ arch_initcall(fsl_i2c_of_init);
+ static int __init mpc83xx_wdt_init(void)
+ {
+ 	struct resource r;
+-	struct device_node *soc, *np;
++	struct device_node *np;
+ 	struct platform_device *dev;
+-	const unsigned int *freq;
++	u32 freq = fsl_get_sys_freq();
+ 	int ret;
+ 
+ 	np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
+@@ -528,19 +556,6 @@ static int __init mpc83xx_wdt_init(void)
+ 		goto nodev;
+ 	}
+ 
+-	soc = of_find_node_by_type(NULL, "soc");
+-
+-	if (!soc) {
+-		ret = -ENODEV;
+-		goto nosoc;
+-	}
+-
+-	freq = of_get_property(soc, "bus-frequency", NULL);
+-	if (!freq) {
+-		ret = -ENODEV;
+-		goto err;
+-	}
+-
+ 	memset(&r, 0, sizeof(r));
+ 
+ 	ret = of_address_to_resource(np, 0, &r);
+@@ -553,20 +568,16 @@ static int __init mpc83xx_wdt_init(void)
+ 		goto err;
+ 	}
+ 
+-	ret = platform_device_add_data(dev, freq, sizeof(int));
++	ret = platform_device_add_data(dev, &freq, sizeof(freq));
+ 	if (ret)
+ 		goto unreg;
+ 
+-	of_node_put(soc);
+ 	of_node_put(np);
+-
+ 	return 0;
+ 
+ unreg:
+ 	platform_device_unregister(dev);
+ err:
+-	of_node_put(soc);
+-nosoc:
+ 	of_node_put(np);
+ nodev:
+ 	return ret;
+@@ -735,547 +746,6 @@ err:
+ 
+ arch_initcall(fsl_usb_of_init);
+ 
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-#ifdef CONFIG_CPM2
+-
+-extern void init_scc_ioports(struct fs_uart_platform_info*);
+-
+-static const char fcc_regs[] = "fcc_regs";
+-static const char fcc_regs_c[] = "fcc_regs_c";
+-static const char fcc_pram[] = "fcc_pram";
+-static char bus_id[9][BUS_ID_SIZE];
+-
+-static int __init fs_enet_of_init(void)
+-{
+-	struct device_node *np;
+-	unsigned int i;
+-	struct platform_device *fs_enet_dev;
+-	struct resource res;
+-	int ret;
+-
+-	for (np = NULL, i = 0;
+-	     (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
+-	     i++) {
+-		struct resource r[4];
+-		struct device_node *phy, *mdio;
+-		struct fs_platform_info fs_enet_data;
+-		const unsigned int *id, *phy_addr, *phy_irq;
+-		const void *mac_addr;
+-		const phandle *ph;
+-		const char *model;
+-
+-		memset(r, 0, sizeof(r));
+-		memset(&fs_enet_data, 0, sizeof(fs_enet_data));
+-
+-		ret = of_address_to_resource(np, 0, &r[0]);
+-		if (ret)
+-			goto err;
+-		r[0].name = fcc_regs;
+-
+-		ret = of_address_to_resource(np, 1, &r[1]);
+-		if (ret)
+-			goto err;
+-		r[1].name = fcc_pram;
+-
+-		ret = of_address_to_resource(np, 2, &r[2]);
+-		if (ret)
+-			goto err;
+-		r[2].name = fcc_regs_c;
+-		fs_enet_data.fcc_regs_c = r[2].start;
+-
+-		of_irq_to_resource(np, 0, &r[3]);
+-
+-		fs_enet_dev =
+-		    platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
+-
+-		if (IS_ERR(fs_enet_dev)) {
+-			ret = PTR_ERR(fs_enet_dev);
+-			goto err;
+-		}
+-
+-		model = of_get_property(np, "model", NULL);
+-		if (model == NULL) {
+-			ret = -ENODEV;
+-			goto unreg;
+-		}
+-
+-		mac_addr = of_get_mac_address(np);
+-		if (mac_addr)
+-			memcpy(fs_enet_data.macaddr, mac_addr, 6);
+-
+-		ph = of_get_property(np, "phy-handle", NULL);
+-		phy = of_find_node_by_phandle(*ph);
+-
+-		if (phy == NULL) {
+-			ret = -ENODEV;
+-			goto unreg;
+-		}
+-
+-		phy_addr = of_get_property(phy, "reg", NULL);
+-		fs_enet_data.phy_addr = *phy_addr;
+-
+-		phy_irq = of_get_property(phy, "interrupts", NULL);
+-
+-		id = of_get_property(np, "device-id", NULL);
+-		fs_enet_data.fs_no = *id;
+-		strcpy(fs_enet_data.fs_type, model);
+-
+-		mdio = of_get_parent(phy);
+-                ret = of_address_to_resource(mdio, 0, &res);
+-                if (ret) {
+-                        of_node_put(phy);
+-                        of_node_put(mdio);
+-                        goto unreg;
+-                }
+-
+-		fs_enet_data.clk_rx = *((u32 *)of_get_property(np,
+-						"rx-clock", NULL));
+-		fs_enet_data.clk_tx = *((u32 *)of_get_property(np,
+-						"tx-clock", NULL));
+-
+-		if (strstr(model, "FCC")) {
+-			int fcc_index = *id - 1;
+-			const unsigned char *mdio_bb_prop;
+-
+-			fs_enet_data.dpram_offset = (u32)cpm_dpram_addr(0);
+-			fs_enet_data.rx_ring = 32;
+-			fs_enet_data.tx_ring = 32;
+-			fs_enet_data.rx_copybreak = 240;
+-			fs_enet_data.use_napi = 0;
+-			fs_enet_data.napi_weight = 17;
+-			fs_enet_data.mem_offset = FCC_MEM_OFFSET(fcc_index);
+-			fs_enet_data.cp_page = CPM_CR_FCC_PAGE(fcc_index);
+-			fs_enet_data.cp_block = CPM_CR_FCC_SBLOCK(fcc_index);
+-
+-			snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%x:%02x",
+-							(u32)res.start, fs_enet_data.phy_addr);
+-			fs_enet_data.bus_id = (char*)&bus_id[(*id)];
+-			fs_enet_data.init_ioports = init_fcc_ioports;
+-
+-			mdio_bb_prop = of_get_property(phy, "bitbang", NULL);
+-			if (mdio_bb_prop) {
+-				struct platform_device *fs_enet_mdio_bb_dev;
+-				struct fs_mii_bb_platform_info fs_enet_mdio_bb_data;
+-
+-				fs_enet_mdio_bb_dev =
+-					platform_device_register_simple("fsl-bb-mdio",
+-							i, NULL, 0);
+-				memset(&fs_enet_mdio_bb_data, 0,
+-						sizeof(struct fs_mii_bb_platform_info));
+-				fs_enet_mdio_bb_data.mdio_dat.bit =
+-					mdio_bb_prop[0];
+-				fs_enet_mdio_bb_data.mdio_dir.bit =
+-					mdio_bb_prop[1];
+-				fs_enet_mdio_bb_data.mdc_dat.bit =
+-					mdio_bb_prop[2];
+-				fs_enet_mdio_bb_data.mdio_port =
+-					mdio_bb_prop[3];
+-				fs_enet_mdio_bb_data.mdc_port =
+-					mdio_bb_prop[4];
+-				fs_enet_mdio_bb_data.delay =
+-					mdio_bb_prop[5];
+-
+-				fs_enet_mdio_bb_data.irq[0] = phy_irq[0];
+-				fs_enet_mdio_bb_data.irq[1] = -1;
+-				fs_enet_mdio_bb_data.irq[2] = -1;
+-				fs_enet_mdio_bb_data.irq[3] = phy_irq[0];
+-				fs_enet_mdio_bb_data.irq[31] = -1;
+-
+-				fs_enet_mdio_bb_data.mdio_dat.offset =
+-					(u32)&cpm2_immr->im_ioport.iop_pdatc;
+-				fs_enet_mdio_bb_data.mdio_dir.offset =
+-					(u32)&cpm2_immr->im_ioport.iop_pdirc;
+-				fs_enet_mdio_bb_data.mdc_dat.offset =
+-					(u32)&cpm2_immr->im_ioport.iop_pdatc;
+-
+-				ret = platform_device_add_data(
+-						fs_enet_mdio_bb_dev,
+-						&fs_enet_mdio_bb_data,
+-						sizeof(struct fs_mii_bb_platform_info));
+-				if (ret)
+-					goto unreg;
+-			}
+-
+-			of_node_put(phy);
+-			of_node_put(mdio);
+-
+-			ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
+-						     sizeof(struct
+-							    fs_platform_info));
+-			if (ret)
+-				goto unreg;
+-		}
+-	}
+-	return 0;
+-
+-unreg:
+-	platform_device_unregister(fs_enet_dev);
+-err:
+-	return ret;
+-}
+-
+-arch_initcall(fs_enet_of_init);
+-
+-static const char scc_regs[] = "regs";
+-static const char scc_pram[] = "pram";
+-
+-static int __init cpm_uart_of_init(void)
+-{
+-	struct device_node *np;
+-	unsigned int i;
+-	struct platform_device *cpm_uart_dev;
+-	int ret;
+-
+-	for (np = NULL, i = 0;
+-	     (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
+-	     i++) {
+-		struct resource r[3];
+-		struct fs_uart_platform_info cpm_uart_data;
+-		const int *id;
+-		const char *model;
+-
+-		memset(r, 0, sizeof(r));
+-		memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
+-
+-		ret = of_address_to_resource(np, 0, &r[0]);
+-		if (ret)
+-			goto err;
+-
+-		r[0].name = scc_regs;
+-
+-		ret = of_address_to_resource(np, 1, &r[1]);
+-		if (ret)
+-			goto err;
+-		r[1].name = scc_pram;
+-
+-		of_irq_to_resource(np, 0, &r[2]);
+-
+-		cpm_uart_dev =
+-		    platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
+-
+-		if (IS_ERR(cpm_uart_dev)) {
+-			ret = PTR_ERR(cpm_uart_dev);
+-			goto err;
+-		}
+-
+-		id = of_get_property(np, "device-id", NULL);
+-		cpm_uart_data.fs_no = *id;
+-
+-		model = of_get_property(np, "model", NULL);
+-		strcpy(cpm_uart_data.fs_type, model);
+-
+-		cpm_uart_data.uart_clk = ppc_proc_freq;
+-
+-		cpm_uart_data.tx_num_fifo = 4;
+-		cpm_uart_data.tx_buf_size = 32;
+-		cpm_uart_data.rx_num_fifo = 4;
+-		cpm_uart_data.rx_buf_size = 32;
+-		cpm_uart_data.clk_rx = *((u32 *)of_get_property(np,
+-						"rx-clock", NULL));
+-		cpm_uart_data.clk_tx = *((u32 *)of_get_property(np,
+-						"tx-clock", NULL));
+-
+-		ret =
+-		    platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
+-					     sizeof(struct
+-						    fs_uart_platform_info));
+-		if (ret)
+-			goto unreg;
+-	}
+-
+-	return 0;
+-
+-unreg:
+-	platform_device_unregister(cpm_uart_dev);
+-err:
+-	return ret;
+-}
+-
+-arch_initcall(cpm_uart_of_init);
+-#endif /* CONFIG_CPM2 */
+-
+-#ifdef CONFIG_8xx
+-
+-extern void init_scc_ioports(struct fs_platform_info*);
+-extern int platform_device_skip(const char *model, int id);
+-
+-static int __init fs_enet_mdio_of_init(void)
+-{
+-	struct device_node *np;
+-	unsigned int i;
+-	struct platform_device *mdio_dev;
+-	struct resource res;
+-	int ret;
+-
+-	for (np = NULL, i = 0;
+-	     (np = of_find_compatible_node(np, "mdio", "fs_enet")) != NULL;
+-	     i++) {
+-		struct fs_mii_fec_platform_info mdio_data;
+-
+-		memset(&res, 0, sizeof(res));
+-		memset(&mdio_data, 0, sizeof(mdio_data));
+-
+-		ret = of_address_to_resource(np, 0, &res);
+-		if (ret)
+-			goto err;
+-
+-		mdio_dev =
+-		    platform_device_register_simple("fsl-cpm-fec-mdio",
+-						    res.start, &res, 1);
+-		if (IS_ERR(mdio_dev)) {
+-			ret = PTR_ERR(mdio_dev);
+-			goto err;
+-		}
+-
+-		mdio_data.mii_speed = ((((ppc_proc_freq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+-
+-		ret =
+-		    platform_device_add_data(mdio_dev, &mdio_data,
+-					     sizeof(struct fs_mii_fec_platform_info));
+-		if (ret)
+-			goto unreg;
+-	}
+-	return 0;
+-
+-unreg:
+-	platform_device_unregister(mdio_dev);
+-err:
+-	return ret;
+-}
+-
+-arch_initcall(fs_enet_mdio_of_init);
+-
+-static const char *enet_regs = "regs";
+-static const char *enet_pram = "pram";
+-static const char *enet_irq = "interrupt";
+-static char bus_id[9][BUS_ID_SIZE];
+-
+-static int __init fs_enet_of_init(void)
+-{
+-	struct device_node *np;
+-	unsigned int i;
+-	struct platform_device *fs_enet_dev = NULL;
+-	struct resource res;
+-	int ret;
+-
+-	for (np = NULL, i = 0;
+-	     (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
+-	     i++) {
+-		struct resource r[4];
+-		struct device_node *phy = NULL, *mdio = NULL;
+-		struct fs_platform_info fs_enet_data;
+-		const unsigned int *id;
+-		const unsigned int *phy_addr;
+-		const void *mac_addr;
+-		const phandle *ph;
+-		const char *model;
+-
+-		memset(r, 0, sizeof(r));
+-		memset(&fs_enet_data, 0, sizeof(fs_enet_data));
+-
+-		model = of_get_property(np, "model", NULL);
+-		if (model == NULL) {
+-			ret = -ENODEV;
+-			goto unreg;
+-		}
+-
+-		id = of_get_property(np, "device-id", NULL);
+-		fs_enet_data.fs_no = *id;
+-
+-		if (platform_device_skip(model, *id))
+-			continue;
+-
+-		ret = of_address_to_resource(np, 0, &r[0]);
+-		if (ret)
+-			goto err;
+-		r[0].name = enet_regs;
+-
+-		mac_addr = of_get_mac_address(np);
+-		if (mac_addr)
+-			memcpy(fs_enet_data.macaddr, mac_addr, 6);
+-
+-		ph = of_get_property(np, "phy-handle", NULL);
+-		if (ph != NULL)
+-			phy = of_find_node_by_phandle(*ph);
+-
+-		if (phy != NULL) {
+-			phy_addr = of_get_property(phy, "reg", NULL);
+-			fs_enet_data.phy_addr = *phy_addr;
+-			fs_enet_data.has_phy = 1;
+-
+-			mdio = of_get_parent(phy);
+-			ret = of_address_to_resource(mdio, 0, &res);
+-			if (ret) {
+-				of_node_put(phy);
+-				of_node_put(mdio);
+-                                goto unreg;
+-			}
+-		}
+-
+-		model = of_get_property(np, "model", NULL);
+-		strcpy(fs_enet_data.fs_type, model);
+-
+-		if (strstr(model, "FEC")) {
+-			r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
+-			r[1].flags = IORESOURCE_IRQ;
+-			r[1].name = enet_irq;
+-
+-			fs_enet_dev =
+-				    platform_device_register_simple("fsl-cpm-fec", i, &r[0], 2);
+-
+-			if (IS_ERR(fs_enet_dev)) {
+-				ret = PTR_ERR(fs_enet_dev);
+-				goto err;
+-			}
+-
+-			fs_enet_data.rx_ring = 128;
+-			fs_enet_data.tx_ring = 16;
+-			fs_enet_data.rx_copybreak = 240;
+-			fs_enet_data.use_napi = 1;
+-			fs_enet_data.napi_weight = 17;
+-
+-			snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%x:%02x",
+-							(u32)res.start, fs_enet_data.phy_addr);
+-			fs_enet_data.bus_id = (char*)&bus_id[i];
+-			fs_enet_data.init_ioports = init_fec_ioports;
+-		}
+-		if (strstr(model, "SCC")) {
+-			ret = of_address_to_resource(np, 1, &r[1]);
+-			if (ret)
+-				goto err;
+-			r[1].name = enet_pram;
+-
+-			r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
+-			r[2].flags = IORESOURCE_IRQ;
+-			r[2].name = enet_irq;
+-
+-			fs_enet_dev =
+-				    platform_device_register_simple("fsl-cpm-scc", i, &r[0], 3);
+-
+-			if (IS_ERR(fs_enet_dev)) {
+-				ret = PTR_ERR(fs_enet_dev);
+-				goto err;
+-			}
+-
+-			fs_enet_data.rx_ring = 64;
+-			fs_enet_data.tx_ring = 8;
+-			fs_enet_data.rx_copybreak = 240;
+-			fs_enet_data.use_napi = 1;
+-			fs_enet_data.napi_weight = 17;
+-
+-			snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%s", "fixed at 10:1");
+-                        fs_enet_data.bus_id = (char*)&bus_id[i];
+-			fs_enet_data.init_ioports = init_scc_ioports;
+-		}
+-
+-		of_node_put(phy);
+-		of_node_put(mdio);
+-
+-		ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
+-					     sizeof(struct
+-						    fs_platform_info));
+-		if (ret)
+-			goto unreg;
+-	}
+-	return 0;
+-
+-unreg:
+-	platform_device_unregister(fs_enet_dev);
+-err:
+-	return ret;
+-}
+-
+-arch_initcall(fs_enet_of_init);
+-
+-static int __init fsl_pcmcia_of_init(void)
+-{
+-	struct device_node *np;
+-	/*
+-	 * Register all the devices which type is "pcmcia"
+-	 */
+-	for_each_compatible_node(np, "pcmcia", "fsl,pq-pcmcia")
+-		of_platform_device_create(np, "m8xx-pcmcia", NULL);
+-	return 0;
+-}
+-
+-arch_initcall(fsl_pcmcia_of_init);
+-
+-static const char *smc_regs = "regs";
+-static const char *smc_pram = "pram";
+-
+-static int __init cpm_smc_uart_of_init(void)
+-{
+-	struct device_node *np;
+-	unsigned int i;
+-	struct platform_device *cpm_uart_dev;
+-	int ret;
+-
+-	for (np = NULL, i = 0;
+-	     (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
+-	     i++) {
+-		struct resource r[3];
+-		struct fs_uart_platform_info cpm_uart_data;
+-		const int *id;
+-		const char *model;
+-
+-		memset(r, 0, sizeof(r));
+-		memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
+-
+-		ret = of_address_to_resource(np, 0, &r[0]);
+-		if (ret)
+-			goto err;
+-
+-		r[0].name = smc_regs;
+-
+-		ret = of_address_to_resource(np, 1, &r[1]);
+-		if (ret)
+-			goto err;
+-		r[1].name = smc_pram;
+-
+-		r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
+-		r[2].flags = IORESOURCE_IRQ;
+-
+-		cpm_uart_dev =
+-		    platform_device_register_simple("fsl-cpm-smc:uart", i, &r[0], 3);
+-
+-		if (IS_ERR(cpm_uart_dev)) {
+-			ret = PTR_ERR(cpm_uart_dev);
+-			goto err;
+-		}
+-
+-		model = of_get_property(np, "model", NULL);
+-		strcpy(cpm_uart_data.fs_type, model);
+-
+-		id = of_get_property(np, "device-id", NULL);
+-		cpm_uart_data.fs_no = *id;
+-		cpm_uart_data.uart_clk = ppc_proc_freq;
+-
+-		cpm_uart_data.tx_num_fifo = 4;
+-		cpm_uart_data.tx_buf_size = 32;
+-		cpm_uart_data.rx_num_fifo = 4;
+-		cpm_uart_data.rx_buf_size = 32;
+-
+-		ret =
+-		    platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
+-					     sizeof(struct
+-						    fs_uart_platform_info));
+-		if (ret)
+-			goto unreg;
+-	}
+-
+-	return 0;
+-
+-unreg:
+-	platform_device_unregister(cpm_uart_dev);
+-err:
+-	return ret;
+-}
+-
+-arch_initcall(cpm_smc_uart_of_init);
+-
+-#endif /* CONFIG_8xx */
+-#endif /* CONFIG_PPC_CPM_NEW_BINDING */
+-
+ static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk,
+ 				   struct spi_board_info *board_infos,
+ 				   unsigned int num_board_infos,
+@@ -1371,25 +841,9 @@ int __init fsl_spi_init(struct spi_board_info *board_infos,
+ 	sysclk = get_brgfreq();
+ #endif
+ 	if (sysclk == -1) {
+-		struct device_node *np;
+-		const u32 *freq;
+-		int size;
+-
+-		np = of_find_node_by_type(NULL, "soc");
+-		if (!np)
++		sysclk = fsl_get_sys_freq();
++		if (sysclk == -1)
+ 			return -ENODEV;
+-
+-		freq = of_get_property(np, "clock-frequency", &size);
+-		if (!freq || size != sizeof(*freq) || *freq == 0) {
+-			freq = of_get_property(np, "bus-frequency", &size);
+-			if (!freq || size != sizeof(*freq) || *freq == 0) {
+-				of_node_put(np);
+-				return -ENODEV;
+-			}
+-		}
+-
+-		sysclk = *freq;
+-		of_node_put(np);
+ 	}
+ 
+ 	ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos,
+diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
+index 63e7db3..74c4a96 100644
+--- a/arch/powerpc/sysdev/fsl_soc.h
++++ b/arch/powerpc/sysdev/fsl_soc.h
+@@ -7,6 +7,7 @@
+ extern phys_addr_t get_immrbase(void);
+ extern u32 get_brgfreq(void);
+ extern u32 get_baudrate(void);
++extern u32 fsl_get_sys_freq(void);
+ 
+ struct spi_board_info;
+ 
+diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
+index 6ffdda2..8619f2a 100644
+--- a/arch/powerpc/sysdev/mpic.c
++++ b/arch/powerpc/sysdev/mpic.c
+@@ -175,13 +175,16 @@ static inline void _mpic_write(enum mpic_reg_type type,
+ 	switch(type) {
+ #ifdef CONFIG_PPC_DCR
+ 	case mpic_access_dcr:
+-		return dcr_write(rb->dhost, reg, value);
++		dcr_write(rb->dhost, reg, value);
++		break;
+ #endif
+ 	case mpic_access_mmio_be:
+-		return out_be32(rb->base + (reg >> 2), value);
++		out_be32(rb->base + (reg >> 2), value);
++		break;
+ 	case mpic_access_mmio_le:
+ 	default:
+-		return out_le32(rb->base + (reg >> 2), value);
++		out_le32(rb->base + (reg >> 2), value);
++		break;
+ 	}
+ }
+ 
+@@ -1000,7 +1003,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+ 				const char *name)
+ {
+ 	struct mpic	*mpic;
+-	u32		reg;
++	u32		greg_feature;
+ 	const char	*vers;
+ 	int		i;
+ 	int		intvec_top;
+@@ -1064,7 +1067,8 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+ 
+ 	/* Look for protected sources */
+ 	if (node) {
+-		unsigned int psize, bits, mapsize;
++		int psize;
++		unsigned int bits, mapsize;
+ 		const u32 *psrc =
+ 			of_get_property(node, "protected-sources", &psize);
+ 		if (psrc) {
+@@ -1107,8 +1111,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+ 	 * in, try to obtain one
+ 	 */
+ 	if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
+-		const u32 *reg;
+-		reg = of_get_property(node, "reg", NULL);
++		const u32 *reg = of_get_property(node, "reg", NULL);
+ 		BUG_ON(reg == NULL);
+ 		paddr = of_translate_address(node, reg);
+ 		BUG_ON(paddr == OF_BAD_ADDR);
+@@ -1137,12 +1140,13 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+ 	 * MPICs, num sources as well. On ISU MPICs, sources are counted
+ 	 * as ISUs are added
+ 	 */
+-	reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
+-	mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
++	greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
++	mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
+ 			  >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
+ 	if (isu_size == 0)
+-		mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
+-				     >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
++		mpic->num_sources =
++			((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
++			 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
+ 
+ 	/* Map the per-CPU registers */
+ 	for (i = 0; i < mpic->num_cpus; i++) {
+@@ -1161,7 +1165,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+ 	mpic->isu_mask = (1 << mpic->isu_shift) - 1;
+ 
+ 	/* Display version */
+-	switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
++	switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) {
+ 	case 1:
+ 		vers = "1.0";
+ 		break;
+@@ -1321,7 +1325,7 @@ void __init mpic_set_serial_int(struct mpic *mpic, int enable)
+ 
+ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
+ {
+-	int is_ipi;
++	unsigned int is_ipi;
+ 	struct mpic *mpic = mpic_find(irq, &is_ipi);
+ 	unsigned int src = mpic_irq_to_hw(irq);
+ 	unsigned long flags;
+@@ -1344,7 +1348,7 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
+ 
+ unsigned int mpic_irq_get_priority(unsigned int irq)
+ {
+-	int is_ipi;
++	unsigned int is_ipi;
+ 	struct mpic *mpic = mpic_find(irq, &is_ipi);
+ 	unsigned int src = mpic_irq_to_hw(irq);
+ 	unsigned long flags;
+@@ -1406,11 +1410,6 @@ void mpic_cpu_set_priority(int prio)
+ 	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio);
+ }
+ 
+-/*
+- * XXX: someone who knows mpic should check this.
+- * do we need to eoi the ipi including for kexec cpu here (see xics comments)?
+- * or can we reset the mpic in the new kernel?
+- */
+ void mpic_teardown_this_cpu(int secondary)
+ {
+ 	struct mpic *mpic = mpic_primary;
+@@ -1430,6 +1429,10 @@ void mpic_teardown_this_cpu(int secondary)
+ 
+ 	/* Set current processor priority to max */
+ 	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
++	/* We need to EOI the IPI since not all platforms reset the MPIC
++	 * on boot and new interrupts wouldn't get delivered otherwise.
++	 */
++	mpic_eoi(mpic);
+ 
+ 	spin_unlock_irqrestore(&mpic_lock, flags);
+ }
+diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
+index efda002..41af122 100644
+--- a/arch/powerpc/sysdev/mv64x60_dev.c
++++ b/arch/powerpc/sysdev/mv64x60_dev.c
+@@ -127,7 +127,7 @@ static int __init mv64x60_mpsc_device_setup(struct device_node *np, int id)
+ 	if (err)
+ 		return err;
+ 
+-	prop = of_get_property(np, "block-index", NULL);
++	prop = of_get_property(np, "cell-index", NULL);
+ 	if (!prop)
+ 		return -ENODEV;
+ 	port_number = *(int *)prop;
+@@ -136,6 +136,7 @@ static int __init mv64x60_mpsc_device_setup(struct device_node *np, int id)
+ 
+ 	pdata.cache_mgmt = 1; /* All current revs need this set */
+ 
++	pdata.max_idle = 40; /* default */
+ 	prop = of_get_property(np, "max_idle", NULL);
+ 	if (prop)
+ 		pdata.max_idle = *prop;
+@@ -205,30 +206,24 @@ error:
+ /*
+  * Create mv64x60_eth platform devices
+  */
+-static int __init eth_register_shared_pdev(struct device_node *np)
++static struct platform_device * __init mv64x60_eth_register_shared_pdev(
++						struct device_node *np, int id)
+ {
+ 	struct platform_device *pdev;
+ 	struct resource r[1];
+ 	int err;
+ 
+-	np = of_get_parent(np);
+-	if (!np)
+-		return -ENODEV;
+-
+ 	err = of_address_to_resource(np, 0, &r[0]);
+-	of_node_put(np);
+ 	if (err)
+-		return err;
++		return ERR_PTR(err);
+ 
+-	pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, 0,
++	pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
+ 					       r, 1);
+-	if (IS_ERR(pdev))
+-		return PTR_ERR(pdev);
+-
+-	return 0;
++	return pdev;
+ }
+ 
+-static int __init mv64x60_eth_device_setup(struct device_node *np, int id)
++static int __init mv64x60_eth_device_setup(struct device_node *np, int id,
++					   struct platform_device *shared_pdev)
+ {
+ 	struct resource r[1];
+ 	struct mv643xx_eth_platform_data pdata;
+@@ -239,16 +234,12 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id)
+ 	const phandle *ph;
+ 	int err;
+ 
+-	/* only register the shared platform device the first time through */
+-	if (id == 0 && (err = eth_register_shared_pdev(np)))
+-		return err;
+-
+ 	memset(r, 0, sizeof(r));
+ 	of_irq_to_resource(np, 0, &r[0]);
+ 
+ 	memset(&pdata, 0, sizeof(pdata));
+ 
+-	prop = of_get_property(np, "block-index", NULL);
++	prop = of_get_property(np, "reg", NULL);
+ 	if (!prop)
+ 		return -ENODEV;
+ 	pdata.port_number = *prop;
+@@ -301,7 +292,7 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id)
+ 
+ 	of_node_put(phy);
+ 
+-	pdev = platform_device_alloc(MV643XX_ETH_NAME, pdata.port_number);
++	pdev = platform_device_alloc(MV643XX_ETH_NAME, id);
+ 	if (!pdev)
+ 		return -ENOMEM;
+ 
+@@ -345,21 +336,17 @@ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
+ 
+ 	memset(&pdata, 0, sizeof(pdata));
+ 
++	pdata.freq_m = 8;	/* default */
+ 	prop = of_get_property(np, "freq_m", NULL);
+-	if (!prop)
+-		return -ENODEV;
+-	pdata.freq_m = *prop;
++	if (prop)
++		pdata.freq_m = *prop;
+ 
++	pdata.freq_m = 3;	/* default */
+ 	prop = of_get_property(np, "freq_n", NULL);
+-	if (!prop)
+-		return -ENODEV;
+-	pdata.freq_n = *prop;
+-
+-	prop = of_get_property(np, "timeout", NULL);
+ 	if (prop)
+-		pdata.timeout = *prop;
+-	else
+-		pdata.timeout = 1000;	/* 1 second */
++		pdata.freq_n = *prop;
++
++	pdata.timeout = 1000;				/* default: 1 second */
+ 
+ 	pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id);
+ 	if (!pdev)
+@@ -401,10 +388,7 @@ static int __init mv64x60_wdt_device_setup(struct device_node *np, int id)
+ 
+ 	memset(&pdata, 0, sizeof(pdata));
+ 
+-	prop = of_get_property(np, "timeout", NULL);
+-	if (!prop)
+-		return -ENODEV;
+-	pdata.timeout = *prop;
++	pdata.timeout = 10;			/* Default: 10 seconds */
+ 
+ 	np = of_get_parent(np);
+ 	if (!np)
+@@ -441,38 +425,64 @@ error:
+ 
+ static int __init mv64x60_device_setup(void)
+ {
+-	struct device_node *np = NULL;
+-	int id;
++	struct device_node *np, *np2;
++	struct platform_device *pdev;
++	int id, id2;
+ 	int err;
+ 
+ 	id = 0;
+-	for_each_compatible_node(np, "serial", "marvell,mpsc")
+-		if ((err = mv64x60_mpsc_device_setup(np, id++)))
+-			goto error;
++	for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
++		err = mv64x60_mpsc_device_setup(np, id++);
++		if (err)
++			printk(KERN_ERR "Failed to initialize MV64x60 "
++					"serial device %s: error %d.\n",
++					np->full_name, err);
++	}
+ 
+ 	id = 0;
+-	for_each_compatible_node(np, "network", "marvell,mv64x60-eth")
+-		if ((err = mv64x60_eth_device_setup(np, id++)))
+-			goto error;
++	id2 = 0;
++	for_each_compatible_node(np, NULL, "marvell,mv64360-eth-group") {
++		pdev = mv64x60_eth_register_shared_pdev(np, id++);
++		if (IS_ERR(pdev)) {
++			err = PTR_ERR(pdev);
++			printk(KERN_ERR "Failed to initialize MV64x60 "
++					"network block %s: error %d.\n",
++					np->full_name, err);
++			continue;
++		}
++		for_each_child_of_node(np, np2) {
++			if (!of_device_is_compatible(np2,
++					"marvell,mv64360-eth"))
++				continue;
++			err = mv64x60_eth_device_setup(np2, id2++, pdev);
++			if (err)
++				printk(KERN_ERR "Failed to initialize "
++						"MV64x60 network device %s: "
++						"error %d.\n",
++						np2->full_name, err);
++		}
++	}
+ 
+ 	id = 0;
+-	for_each_compatible_node(np, "i2c", "marvell,mv64x60-i2c")
+-		if ((err = mv64x60_i2c_device_setup(np, id++)))
+-			goto error;
++	for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") {
++		err = mv64x60_i2c_device_setup(np, id++);
++		if (err)
++			printk(KERN_ERR "Failed to initialize MV64x60 I2C "
++					"bus %s: error %d.\n",
++					np->full_name, err);
++	}
+ 
+ 	/* support up to one watchdog timer */
+-	np = of_find_compatible_node(np, NULL, "marvell,mv64x60-wdt");
++	np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt");
+ 	if (np) {
+ 		if ((err = mv64x60_wdt_device_setup(np, id)))
+-			goto error;
++			printk(KERN_ERR "Failed to initialize MV64x60 "
++					"Watchdog %s: error %d.\n",
++					np->full_name, err);
+ 		of_node_put(np);
+ 	}
+ 
+ 	return 0;
+-
+-error:
+-	of_node_put(np);
+-	return err;
+ }
+ arch_initcall(mv64x60_device_setup);
+ 
+@@ -489,10 +499,10 @@ static int __init mv64x60_add_mpsc_console(void)
+ 	if (!np)
+ 		goto not_mpsc;
+ 
+-	if (!of_device_is_compatible(np, "marvell,mpsc"))
++	if (!of_device_is_compatible(np, "marvell,mv64360-mpsc"))
+ 		goto not_mpsc;
+ 
+-	prop = of_get_property(np, "block-index", NULL);
++	prop = of_get_property(np, "cell-index", NULL);
+ 	if (!prop)
+ 		goto not_mpsc;
+ 
+diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c
+index d21ab8f..1456015 100644
+--- a/arch/powerpc/sysdev/mv64x60_pci.c
++++ b/arch/powerpc/sysdev/mv64x60_pci.c
+@@ -86,14 +86,14 @@ static int __init mv64x60_sysfs_init(void)
+ 	struct platform_device *pdev;
+ 	const unsigned int *prop;
+ 
+-	np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60");
++	np = of_find_compatible_node(NULL, NULL, "marvell,mv64360");
+ 	if (!np)
+ 		return 0;
+ 
+ 	prop = of_get_property(np, "hs_reg_valid", NULL);
+ 	of_node_put(np);
+ 
+-	pdev = platform_device_register_simple("marvell,mv64x60", 0, NULL, 0);
++	pdev = platform_device_register_simple("marvell,mv64360", 0, NULL, 0);
+ 	if (IS_ERR(pdev))
+ 		return PTR_ERR(pdev);
+ 
+@@ -166,6 +166,6 @@ void __init mv64x60_pci_init(void)
+ {
+ 	struct device_node *np;
+ 
+-	for_each_compatible_node(np, "pci", "marvell,mv64x60-pci")
++	for_each_compatible_node(np, "pci", "marvell,mv64360-pci")
+ 		mv64x60_add_bridge(np);
+ }
+diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c
+index 19e6ef2..2aa4ed0 100644
+--- a/arch/powerpc/sysdev/mv64x60_pic.c
++++ b/arch/powerpc/sysdev/mv64x60_pic.c
+@@ -238,13 +238,13 @@ void __init mv64x60_init_irq(void)
+ 	const unsigned int *reg;
+ 	unsigned long flags;
+ 
+-	np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-gpp");
++	np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-gpp");
+ 	reg = of_get_property(np, "reg", &size);
+ 	paddr = of_translate_address(np, reg);
+ 	mv64x60_gpp_reg_base = ioremap(paddr, reg[1]);
+ 	of_node_put(np);
+ 
+-	np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-pic");
++	np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-pic");
+ 	reg = of_get_property(np, "reg", &size);
+ 	paddr = of_translate_address(np, reg);
+ 	mv64x60_irq_reg_base = ioremap(paddr, reg[1]);
+diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c
+index 35c77c7..2792dc8 100644
+--- a/arch/powerpc/sysdev/mv64x60_udbg.c
++++ b/arch/powerpc/sysdev/mv64x60_udbg.c
+@@ -85,7 +85,7 @@ static void mv64x60_udbg_init(void)
+ 	if (!stdout)
+ 		return;
+ 
+-	for_each_compatible_node(np, "serial", "marvell,mpsc") {
++	for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
+ 		if (np == stdout)
+ 			break;
+ 	}
+@@ -94,7 +94,7 @@ static void mv64x60_udbg_init(void)
+ 	if (!np)
+ 		return;
+ 
+-	block_index = of_get_property(np, "block-index", NULL);
++	block_index = of_get_property(np, "cell-index", NULL);
+ 	if (!block_index)
+ 		goto error;
+ 
+diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
+index 5abfcd1..1814adb 100644
+--- a/arch/powerpc/sysdev/ppc4xx_pci.c
++++ b/arch/powerpc/sysdev/ppc4xx_pci.c
+@@ -527,6 +527,7 @@ static void __init ppc4xx_probe_pcix_bridge(struct device_node *np)
+  *
+  * ibm,plb-pciex-440spe
+  * ibm,plb-pciex-405ex
++ * ibm,plb-pciex-460ex
+  *
+  * Anything else will be rejected for now as they are all subtly
+  * different unfortunately.
+@@ -645,7 +646,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np)
+ 	int time_out = 20;
+ 
+ 	/* Set PLL clock receiver to LVPECL */
+-	mtdcri(SDR0, PESDR0_PLLLCT1, mfdcri(SDR0, PESDR0_PLLLCT1) | 1 << 28);
++	dcri_clrset(SDR0, PESDR0_PLLLCT1, 0, 1 << 28);
+ 
+ 	/* Shouldn't we do all the calibration stuff etc... here ? */
+ 	if (ppc440spe_pciex_check_reset(np))
+@@ -659,8 +660,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np)
+ 	}
+ 
+ 	/* De-assert reset of PCIe PLL, wait for lock */
+-	mtdcri(SDR0, PESDR0_PLLLCT1,
+-	       mfdcri(SDR0, PESDR0_PLLLCT1) & ~(1 << 24));
++	dcri_clrset(SDR0, PESDR0_PLLLCT1, 1 << 24, 0);
+ 	udelay(3);
+ 
+ 	while (time_out) {
+@@ -712,9 +712,8 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+ 		mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL7SET1,
+ 		       0x35000000);
+ 	}
+-	val = mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET);
+-	mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
+-	       (val & ~(1 << 24 | 1 << 16)) | 1 << 12);
++	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
++			(1 << 24) | (1 << 16), 1 << 12);
+ 
+ 	return 0;
+ }
+@@ -775,6 +774,115 @@ static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =
+ 	.setup_utl	= ppc440speB_pciex_init_utl,
+ };
+ 
++static int __init ppc460ex_pciex_core_init(struct device_node *np)
++{
++	/* Nothing to do, return 2 ports */
++	return 2;
++}
++
++static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
++{
++	u32 val;
++	u32 utlset1;
++
++	if (port->endpoint)
++		val = PTYPE_LEGACY_ENDPOINT << 20;
++	else
++		val = PTYPE_ROOT_PORT << 20;
++
++	if (port->index == 0) {
++		val |= LNKW_X1 << 12;
++		utlset1 = 0x20000000;
++	} else {
++		val |= LNKW_X4 << 12;
++		utlset1 = 0x20101101;
++	}
++
++	mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val);
++	mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, utlset1);
++	mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01210000);
++
++	switch (port->index) {
++	case 0:
++		mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230);
++		mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000136);
++		mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006);
++
++		mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST,0x10000000);
++		break;
++
++	case 1:
++		mtdcri(SDR0, PESDR1_460EX_L0CDRCTL, 0x00003230);
++		mtdcri(SDR0, PESDR1_460EX_L1CDRCTL, 0x00003230);
++		mtdcri(SDR0, PESDR1_460EX_L2CDRCTL, 0x00003230);
++		mtdcri(SDR0, PESDR1_460EX_L3CDRCTL, 0x00003230);
++		mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000136);
++		mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000136);
++		mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000136);
++		mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000136);
++		mtdcri(SDR0, PESDR1_460EX_L0CLK, 0x00000006);
++		mtdcri(SDR0, PESDR1_460EX_L1CLK, 0x00000006);
++		mtdcri(SDR0, PESDR1_460EX_L2CLK, 0x00000006);
++		mtdcri(SDR0, PESDR1_460EX_L3CLK, 0x00000006);
++
++		mtdcri(SDR0, PESDR1_460EX_PHY_CTL_RST,0x10000000);
++		break;
++	}
++
++	mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
++	       mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) |
++	       (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
++
++	/* Poll for PHY reset */
++	/* XXX FIXME add timeout */
++	switch (port->index) {
++	case 0:
++		while (!(mfdcri(SDR0, PESDR0_460EX_RSTSTA) & 0x1))
++			udelay(10);
++		break;
++	case 1:
++		while (!(mfdcri(SDR0, PESDR1_460EX_RSTSTA) & 0x1))
++			udelay(10);
++		break;
++	}
++
++	mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
++	       (mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) &
++		~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
++	       PESDRx_RCSSET_RSTPYN);
++
++	port->has_ibpre = 1;
++
++	return 0;
++}
++
++static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
++{
++	dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x0);
++
++	/*
++	 * Set buffer allocations and then assert VRB and TXE.
++	 */
++	out_be32(port->utl_base + PEUTL_PBCTL,	0x0800000c);
++	out_be32(port->utl_base + PEUTL_OUTTR,	0x08000000);
++	out_be32(port->utl_base + PEUTL_INTR,	0x02000000);
++	out_be32(port->utl_base + PEUTL_OPDBSZ,	0x04000000);
++	out_be32(port->utl_base + PEUTL_PBBSZ,	0x00000000);
++	out_be32(port->utl_base + PEUTL_IPHBSZ,	0x02000000);
++	out_be32(port->utl_base + PEUTL_IPDBSZ,	0x04000000);
++	out_be32(port->utl_base + PEUTL_RCIRQEN,0x00f00000);
++	out_be32(port->utl_base + PEUTL_PCTL,	0x80800066);
++
++	return 0;
++}
++
++static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
++{
++	.core_init	= ppc460ex_pciex_core_init,
++	.port_init_hw	= ppc460ex_pciex_init_port_hw,
++	.setup_utl	= ppc460ex_pciex_init_utl,
++};
++
+ #endif /* CONFIG_44x */
+ 
+ #ifdef CONFIG_40x
+@@ -830,17 +938,9 @@ static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+ 	 * PCIe boards don't show this problem.
+ 	 * This has to be re-tested and fixed in a later release!
+ 	 */
+-#if 0 /* XXX FIXME: Not resetting the PHY will leave all resources
+-       * configured as done previously by U-Boot. Then Linux will currently
+-       * not reassign them. So the PHY reset is now done always. This will
+-       * lead to problems with the Atheros PCIe board again.
+-       */
+ 	val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP);
+ 	if (!(val & 0x00001000))
+ 		ppc405ex_pcie_phy_reset(port);
+-#else
+-	ppc405ex_pcie_phy_reset(port);
+-#endif
+ 
+ 	dcr_write(port->dcrs, DCRO_PEGPL_CFG, 0x10000000);  /* guarded on */
+ 
+@@ -896,6 +996,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
+ 		else
+ 			ppc4xx_pciex_hwops = &ppc440speB_pcie_hwops;
+ 	}
++	if (of_device_is_compatible(np, "ibm,plb-pciex-460ex"))
++		ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops;
+ #endif /* CONFIG_44x    */
+ #ifdef CONFIG_40x
+ 	if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
+@@ -1042,8 +1144,7 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
+ 		port->link = 0;
+ 	}
+ 
+-	mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
+-	       mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) | 1 << 20);
++	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
+ 	msleep(100);
+ 
+ 	return 0;
+diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h
+index 1c07908..d04e40b 100644
+--- a/arch/powerpc/sysdev/ppc4xx_pci.h
++++ b/arch/powerpc/sysdev/ppc4xx_pci.h
+@@ -271,6 +271,59 @@
+ #define PESDR1_405EX_PHYSTA		0x044C
+ 
+ /*
++ * 460EX additional DCRs
++ */
++#define PESDR0_460EX_L0BIST		0x0308
++#define PESDR0_460EX_L0BISTSTS		0x0309
++#define PESDR0_460EX_L0CDRCTL		0x030A
++#define PESDR0_460EX_L0DRV		0x030B
++#define PESDR0_460EX_L0REC		0x030C
++#define PESDR0_460EX_L0LPB		0x030D
++#define PESDR0_460EX_L0CLK		0x030E
++#define PESDR0_460EX_PHY_CTL_RST	0x030F
++#define PESDR0_460EX_RSTSTA		0x0310
++#define PESDR0_460EX_OBS		0x0311
++#define PESDR0_460EX_L0ERRC		0x0320
++
++#define PESDR1_460EX_L0BIST		0x0348
++#define PESDR1_460EX_L1BIST		0x0349
++#define PESDR1_460EX_L2BIST		0x034A
++#define PESDR1_460EX_L3BIST		0x034B
++#define PESDR1_460EX_L0BISTSTS		0x034C
++#define PESDR1_460EX_L1BISTSTS		0x034D
++#define PESDR1_460EX_L2BISTSTS		0x034E
++#define PESDR1_460EX_L3BISTSTS		0x034F
++#define PESDR1_460EX_L0CDRCTL		0x0350
++#define PESDR1_460EX_L1CDRCTL		0x0351
++#define PESDR1_460EX_L2CDRCTL		0x0352
++#define PESDR1_460EX_L3CDRCTL		0x0353
++#define PESDR1_460EX_L0DRV		0x0354
++#define PESDR1_460EX_L1DRV		0x0355
++#define PESDR1_460EX_L2DRV		0x0356
++#define PESDR1_460EX_L3DRV		0x0357
++#define PESDR1_460EX_L0REC		0x0358
++#define PESDR1_460EX_L1REC		0x0359
++#define PESDR1_460EX_L2REC		0x035A
++#define PESDR1_460EX_L3REC		0x035B
++#define PESDR1_460EX_L0LPB		0x035C
++#define PESDR1_460EX_L1LPB		0x035D
++#define PESDR1_460EX_L2LPB		0x035E
++#define PESDR1_460EX_L3LPB		0x035F
++#define PESDR1_460EX_L0CLK		0x0360
++#define PESDR1_460EX_L1CLK		0x0361
++#define PESDR1_460EX_L2CLK		0x0362
++#define PESDR1_460EX_L3CLK		0x0363
++#define PESDR1_460EX_PHY_CTL_RST	0x0364
++#define PESDR1_460EX_RSTSTA		0x0365
++#define PESDR1_460EX_OBS		0x0366
++#define PESDR1_460EX_L0ERRC		0x0368
++#define PESDR1_460EX_L1ERRC		0x0369
++#define PESDR1_460EX_L2ERRC		0x036A
++#define PESDR1_460EX_L3ERRC		0x036B
++#define PESDR0_460EX_IHS1		0x036C
++#define PESDR0_460EX_IHS2		0x036D
++
++/*
+  * Of the above, some are common offsets from the base
+  */
+ #define PESDRn_UTLSET1			0x00
+@@ -353,6 +406,12 @@
+ #define PECFG_POM2LAL		0x390
+ #define PECFG_POM2LAH		0x394
+ 
++/* SDR Bit Mappings */
++#define PESDRx_RCSSET_HLDPLB	0x10000000
++#define PESDRx_RCSSET_RSTGU	0x01000000
++#define PESDRx_RCSSET_RDY       0x00100000
++#define PESDRx_RCSSET_RSTDL     0x00010000
++#define PESDRx_RCSSET_RSTPYN    0x00001000
+ 
+ enum
+ {
+diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c
+new file mode 100644
+index 0000000..5b32adc
+--- /dev/null
++++ b/arch/powerpc/sysdev/ppc4xx_soc.c
+@@ -0,0 +1,200 @@
++/*
++ * IBM/AMCC PPC4xx SoC setup code
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * L2 cache routines cloned from arch/ppc/syslib/ibm440gx_common.c which is:
++ *   Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
++ *   Copyright (c) 2003 - 2006 Zultys Technologies
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/stddef.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/of_platform.h>
++
++#include <asm/dcr.h>
++#include <asm/dcr-regs.h>
++#include <asm/reg.h>
++
++static u32 dcrbase_l2c;
++
++/*
++ * L2-cache
++ */
++
++/* Issue L2C diagnostic command */
++static inline u32 l2c_diag(u32 addr)
++{
++	mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, addr);
++	mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_DIAG);
++	while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC))
++		;
++
++	return mfdcr(dcrbase_l2c + DCRN_L2C0_DATA);
++}
++
++static irqreturn_t l2c_error_handler(int irq, void *dev)
++{
++	u32 sr = mfdcr(dcrbase_l2c + DCRN_L2C0_SR);
++
++	if (sr & L2C_SR_CPE) {
++		/* Read cache trapped address */
++		u32 addr = l2c_diag(0x42000000);
++		printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n",
++		       addr);
++	}
++	if (sr & L2C_SR_TPE) {
++		/* Read tag trapped address */
++		u32 addr = l2c_diag(0x82000000) >> 16;
++		printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n",
++		       addr);
++	}
++
++	/* Clear parity errors */
++	if (sr & (L2C_SR_CPE | L2C_SR_TPE)){
++		mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0);
++		mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
++	} else {
++		printk(KERN_EMERG "L2C: LRU error\n");
++	}
++
++	return IRQ_HANDLED;
++}
++
++static int __init ppc4xx_l2c_probe(void)
++{
++	struct device_node *np;
++	u32 r;
++	unsigned long flags;
++	int irq;
++	const u32 *dcrreg;
++	u32 dcrbase_isram;
++	int len;
++	const u32 *prop;
++	u32 l2_size;
++
++	np = of_find_compatible_node(NULL, NULL, "ibm,l2-cache");
++	if (!np)
++		return 0;
++
++	/* Get l2 cache size */
++	prop = of_get_property(np, "cache-size", NULL);
++	if (prop == NULL) {
++		printk(KERN_ERR "%s: Can't get cache-size!\n", np->full_name);
++		of_node_put(np);
++		return -ENODEV;
++	}
++	l2_size = prop[0];
++
++	/* Map DCRs */
++	dcrreg = of_get_property(np, "dcr-reg", &len);
++	if (!dcrreg || (len != 4 * sizeof(u32))) {
++		printk(KERN_ERR "%s: Can't get DCR register base !",
++		       np->full_name);
++		of_node_put(np);
++		return -ENODEV;
++	}
++	dcrbase_isram = dcrreg[0];
++	dcrbase_l2c = dcrreg[2];
++
++	/* Get and map irq number from device tree */
++	irq = irq_of_parse_and_map(np, 0);
++	if (irq == NO_IRQ) {
++		printk(KERN_ERR "irq_of_parse_and_map failed\n");
++		of_node_put(np);
++		return -ENODEV;
++	}
++
++	/* Install error handler */
++	if (request_irq(irq, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0) {
++		printk(KERN_ERR "Cannot install L2C error handler"
++		       ", cache is not enabled\n");
++		of_node_put(np);
++		return -ENODEV;
++	}
++
++	local_irq_save(flags);
++	asm volatile ("sync" ::: "memory");
++
++	/* Disable SRAM */
++	mtdcr(dcrbase_isram + DCRN_SRAM0_DPC,
++	      mfdcr(dcrbase_isram + DCRN_SRAM0_DPC) & ~SRAM_DPC_ENABLE);
++	mtdcr(dcrbase_isram + DCRN_SRAM0_SB0CR,
++	      mfdcr(dcrbase_isram + DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK);
++	mtdcr(dcrbase_isram + DCRN_SRAM0_SB1CR,
++	      mfdcr(dcrbase_isram + DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK);
++	mtdcr(dcrbase_isram + DCRN_SRAM0_SB2CR,
++	      mfdcr(dcrbase_isram + DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK);
++	mtdcr(dcrbase_isram + DCRN_SRAM0_SB3CR,
++	      mfdcr(dcrbase_isram + DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK);
++
++	/* Enable L2_MODE without ICU/DCU */
++	r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG) &
++		~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK);
++	r |= L2C_CFG_L2M | L2C_CFG_SS_256;
++	mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r);
++
++	mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0);
++
++	/* Hardware Clear Command */
++	mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_HCC);
++	while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC))
++		;
++
++	/* Clear Cache Parity and Tag Errors */
++	mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
++
++	/* Enable 64G snoop region starting at 0 */
++	r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP0) &
++		~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
++	r |= L2C_SNP_SSR_32G | L2C_SNP_ESR;
++	mtdcr(dcrbase_l2c + DCRN_L2C0_SNP0, r);
++
++	r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP1) &
++		~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
++	r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR;
++	mtdcr(dcrbase_l2c + DCRN_L2C0_SNP1, r);
++
++	asm volatile ("sync" ::: "memory");
++
++	/* Enable ICU/DCU ports */
++	r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG);
++	r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM
++	       | L2C_CFG_TPEI | L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM);
++	r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN
++		| L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM;
++
++	/* Check for 460EX/GT special handling */
++	if (of_device_is_compatible(np, "ibm,l2-cache-460ex"))
++		r |= L2C_CFG_RDBW;
++
++	mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r);
++
++	asm volatile ("sync; isync" ::: "memory");
++	local_irq_restore(flags);
++
++	printk(KERN_INFO "%dk L2-cache enabled\n", l2_size >> 10);
++
++	of_node_put(np);
++	return 0;
++}
++arch_initcall(ppc4xx_l2c_probe);
++
++/*
++ * At present, this routine just applies a system reset.
++ */
++void ppc4xx_reset_system(char *cmd)
++{
++	mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_RST_SYSTEM);
++	while (1)
++		;	/* Just in case the reset doesn't work */
++}
+diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
+index cc81fd1..cff550e 100644
+--- a/arch/powerpc/sysdev/qe_lib/qe.c
++++ b/arch/powerpc/sysdev/qe_lib/qe.c
+@@ -55,7 +55,7 @@ struct qe_snum {
+ /* We allocate this here because it is used almost exclusively for
+  * the communication processor devices.
+  */
+-struct qe_immap *qe_immr = NULL;
++struct qe_immap __iomem *qe_immr;
+ EXPORT_SYMBOL(qe_immr);
+ 
+ static struct qe_snum snums[QE_NUM_OF_SNUM];	/* Dynamically allocated SNUMs */
+@@ -156,7 +156,7 @@ EXPORT_SYMBOL(qe_issue_cmd);
+  */
+ static unsigned int brg_clk = 0;
+ 
+-unsigned int get_brg_clk(void)
++unsigned int qe_get_brg_clk(void)
+ {
+ 	struct device_node *qe;
+ 	unsigned int size;
+@@ -180,6 +180,7 @@ unsigned int get_brg_clk(void)
+ 
+ 	return brg_clk;
+ }
++EXPORT_SYMBOL(qe_get_brg_clk);
+ 
+ /* Program the BRG to the given sampling rate and multiplier
+  *
+@@ -197,7 +198,7 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
+ 	if ((brg < QE_BRG1) || (brg > QE_BRG16))
+ 		return -EINVAL;
+ 
+-	divisor = get_brg_clk() / (rate * multiplier);
++	divisor = qe_get_brg_clk() / (rate * multiplier);
+ 
+ 	if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
+ 		div16 = QE_BRGC_DIV16;
+@@ -415,12 +416,6 @@ void qe_muram_dump(void)
+ }
+ EXPORT_SYMBOL(qe_muram_dump);
+ 
+-void *qe_muram_addr(unsigned long offset)
+-{
+-	return (void *)&qe_immr->muram[offset];
+-}
+-EXPORT_SYMBOL(qe_muram_addr);
+-
+ /* The maximum number of RISCs we support */
+ #define MAX_QE_RISC     2
+ 
+diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
+index e53ea4d..93916a4 100644
+--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
++++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
+@@ -22,6 +22,7 @@
+ #include <linux/ioport.h>
+ 
+ #include <asm/io.h>
++#include <asm/qe.h>
+ #include <asm/prom.h>
+ #include <sysdev/fsl_soc.h>
+ 
+@@ -41,7 +42,7 @@ struct port_regs {
+ #endif
+ };
+ 
+-static struct port_regs *par_io = NULL;
++static struct port_regs __iomem *par_io;
+ static int num_par_io_ports = 0;
+ 
+ int par_io_init(struct device_node *np)
+@@ -165,7 +166,7 @@ int par_io_of_config(struct device_node *np)
+ 	}
+ 
+ 	ph = of_get_property(np, "pio-handle", NULL);
+-	if (ph == 0) {
++	if (ph == NULL) {
+ 		printk(KERN_ERR "pio-handle not available \n");
+ 		return -1;
+ 	}
+@@ -200,7 +201,7 @@ static void dump_par_io(void)
+ {
+ 	unsigned int i;
+ 
+-	printk(KERN_INFO "%s: par_io=%p\n", __FUNCTION__, par_io);
++	printk(KERN_INFO "%s: par_io=%p\n", __func__, par_io);
+ 	for (i = 0; i < num_par_io_ports; i++) {
+ 		printk(KERN_INFO "	cpodr[%u]=%08x\n", i,
+ 			in_be32(&par_io[i].cpodr));
+diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+index 3223acb..bcf88e6 100644
+--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
++++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+@@ -148,57 +148,57 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ 
+ 	/* check if the UCC port number is in range. */
+ 	if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
+-		printk(KERN_ERR "%s: illegal UCC number\n", __FUNCTION__);
++		printk(KERN_ERR "%s: illegal UCC number\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	/* Check that 'max_rx_buf_length' is properly aligned (4). */
+ 	if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
+ 		printk(KERN_ERR "%s: max_rx_buf_length not aligned\n",
+-			__FUNCTION__);
++			__func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	/* Validate Virtual Fifo register values */
+ 	if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
+-		printk(KERN_ERR "%s: urfs is too small\n", __FUNCTION__);
++		printk(KERN_ERR "%s: urfs is too small\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+-		printk(KERN_ERR "%s: urfs is not aligned\n", __FUNCTION__);
++		printk(KERN_ERR "%s: urfs is not aligned\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+-		printk(KERN_ERR "%s: urfet is not aligned.\n", __FUNCTION__);
++		printk(KERN_ERR "%s: urfet is not aligned.\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+-		printk(KERN_ERR "%s: urfset is not aligned\n", __FUNCTION__);
++		printk(KERN_ERR "%s: urfset is not aligned\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+-		printk(KERN_ERR "%s: utfs is not aligned\n", __FUNCTION__);
++		printk(KERN_ERR "%s: utfs is not aligned\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+-		printk(KERN_ERR "%s: utfet is not aligned\n", __FUNCTION__);
++		printk(KERN_ERR "%s: utfet is not aligned\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+-		printk(KERN_ERR "%s: utftt is not aligned\n", __FUNCTION__);
++		printk(KERN_ERR "%s: utftt is not aligned\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
+ 	if (!uccf) {
+ 		printk(KERN_ERR "%s: Cannot allocate private data\n",
+-			__FUNCTION__);
++			__func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -207,7 +207,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ 	/* Set the PHY base address */
+ 	uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast));
+ 	if (uccf->uf_regs == NULL) {
+-		printk(KERN_ERR "%s: Cannot map UCC registers\n", __FUNCTION__);
++		printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -230,7 +230,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ 	/* Set UCC to fast type */
+ 	ret = ucc_set_type(uf_info->ucc_num, UCC_SPEED_TYPE_FAST);
+ 	if (ret) {
+-		printk(KERN_ERR "%s: cannot set UCC type\n", __FUNCTION__);
++		printk(KERN_ERR "%s: cannot set UCC type\n", __func__);
+ 		ucc_fast_free(uccf);
+ 		return ret;
+ 	}
+@@ -270,7 +270,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ 	    qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
+ 	if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
+ 		printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n",
+-			__FUNCTION__);
++			__func__);
+ 		uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
+ 		ucc_fast_free(uccf);
+ 		return -ENOMEM;
+@@ -283,7 +283,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ 			   UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
+ 	if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
+ 		printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO\n",
+-			__FUNCTION__);
++			__func__);
+ 		uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
+ 		ucc_fast_free(uccf);
+ 		return -ENOMEM;
+@@ -314,7 +314,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ 		    ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock,
+ 					COMM_DIR_RX)) {
+ 			printk(KERN_ERR "%s: illegal value for RX clock\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			ucc_fast_free(uccf);
+ 			return -EINVAL;
+ 		}
+@@ -323,7 +323,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ 		    ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock,
+ 					COMM_DIR_TX)) {
+ 			printk(KERN_ERR "%s: illegal value for TX clock\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			ucc_fast_free(uccf);
+ 			return -EINVAL;
+ 		}
+diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+index b2870b2..a578bc7 100644
+--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
++++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+@@ -142,7 +142,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ 
+ 	/* check if the UCC port number is in range. */
+ 	if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
+-		printk(KERN_ERR "%s: illegal UCC number\n", __FUNCTION__);
++		printk(KERN_ERR "%s: illegal UCC number\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -161,7 +161,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ 	uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
+ 	if (!uccs) {
+ 		printk(KERN_ERR "%s: Cannot allocate private data\n",
+-			__FUNCTION__);
++			__func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -170,7 +170,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ 	/* Set the PHY base address */
+ 	uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow));
+ 	if (uccs->us_regs == NULL) {
+-		printk(KERN_ERR "%s: Cannot map UCC registers\n", __FUNCTION__);
++		printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -189,7 +189,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ 	uccs->us_pram_offset =
+ 		qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
+ 	if (IS_ERR_VALUE(uccs->us_pram_offset)) {
+-		printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __FUNCTION__);
++		printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __func__);
+ 		ucc_slow_free(uccs);
+ 		return -ENOMEM;
+ 	}
+@@ -202,7 +202,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ 	/* Set UCC to slow type */
+ 	ret = ucc_set_type(us_info->ucc_num, UCC_SPEED_TYPE_SLOW);
+ 	if (ret) {
+-		printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
++		printk(KERN_ERR "%s: cannot set UCC type", __func__);
+ 		ucc_slow_free(uccs);
+ 		return ret;
+ 	}
+@@ -216,7 +216,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ 		qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
+ 				QE_ALIGNMENT_OF_BD);
+ 	if (IS_ERR_VALUE(uccs->rx_base_offset)) {
+-		printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __FUNCTION__,
++		printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __func__,
+ 			us_info->rx_bd_ring_len);
+ 		uccs->rx_base_offset = 0;
+ 		ucc_slow_free(uccs);
+@@ -227,7 +227,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ 		qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
+ 			QE_ALIGNMENT_OF_BD);
+ 	if (IS_ERR_VALUE(uccs->tx_base_offset)) {
+-		printk(KERN_ERR "%s: cannot allocate TX BDs", __FUNCTION__);
++		printk(KERN_ERR "%s: cannot allocate TX BDs", __func__);
+ 		uccs->tx_base_offset = 0;
+ 		ucc_slow_free(uccs);
+ 		return -ENOMEM;
+@@ -317,7 +317,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ 		if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock,
+ 					COMM_DIR_RX)) {
+ 			printk(KERN_ERR "%s: illegal value for RX clock\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			ucc_slow_free(uccs);
+ 			return -EINVAL;
+ 		}
+@@ -325,7 +325,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ 		if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock,
+ 					COMM_DIR_TX)) {
+ 			printk(KERN_ERR "%s: illegal value for TX clock\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			ucc_slow_free(uccs);
+ 			return -EINVAL;
+ 		}
+diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c
+index 0c9ac7e..c09ddc0 100644
+--- a/arch/powerpc/sysdev/rtc_cmos_setup.c
++++ b/arch/powerpc/sysdev/rtc_cmos_setup.c
+@@ -56,3 +56,5 @@ static int  __init add_rtc(void)
+ 	return 0;
+ }
+ fs_initcall(add_rtc);
++
++MODULE_LICENSE("GPL");
+diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
+index be2808a..d4d15aa 100644
+--- a/arch/powerpc/sysdev/tsi108_dev.c
++++ b/arch/powerpc/sysdev/tsi108_dev.c
+@@ -84,7 +84,7 @@ static int __init tsi108_eth_of_init(void)
+ 
+ 		ret = of_address_to_resource(np, 0, &r[0]);
+ 		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
+-			__FUNCTION__,r[0].name, r[0].start, r[0].end);
++			__func__,r[0].name, r[0].start, r[0].end);
+ 		if (ret)
+ 			goto err;
+ 
+@@ -93,7 +93,7 @@ static int __init tsi108_eth_of_init(void)
+ 		r[1].end = irq_of_parse_and_map(np, 0);
+ 		r[1].flags = IORESOURCE_IRQ;
+ 		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
+-			__FUNCTION__,r[1].name, r[1].start, r[1].end);
++			__func__,r[1].name, r[1].start, r[1].end);
+ 
+ 		tsi_eth_dev =
+ 		    platform_device_register_simple("tsi-ethernet", i++, &r[0],
+diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
+index 31d3d33..ac1a72d 100644
+--- a/arch/powerpc/sysdev/tsi108_pci.c
++++ b/arch/powerpc/sysdev/tsi108_pci.c
+@@ -207,7 +207,7 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary)
+ 	/* PCI Config mapping */
+ 	tsi108_pci_cfg_base = (u32)ioremap(cfg_phys, TSI108_PCI_CFG_SIZE);
+ 	tsi108_pci_cfg_phys = cfg_phys;
+-	DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__,
++	DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __func__,
+ 	    tsi108_pci_cfg_base);
+ 
+ 	/* Fetch host bridge registers address */
+@@ -395,7 +395,7 @@ static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct,
+ static int pci_irq_host_map(struct irq_host *h, unsigned int virq,
+ 			  irq_hw_number_t hw)
+ {	unsigned int irq;
+-	DBG("%s(%d, 0x%lx)\n", __FUNCTION__, virq, hw);
++	DBG("%s(%d, 0x%lx)\n", __func__, virq, hw);
+ 	if ((virq >= 1) && (virq <= 4)){
+ 		irq = virq + IRQ_PCI_INTAD_BASE - 1;
+ 		get_irq_desc(irq)->status |= IRQ_LEVEL;
+diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
+index a34172d..52c7478 100644
+--- a/arch/powerpc/xmon/xmon.c
++++ b/arch/powerpc/xmon/xmon.c
+@@ -45,7 +45,6 @@
+ #ifdef CONFIG_PPC64
+ #include <asm/hvcall.h>
+ #include <asm/paca.h>
+-#include <asm/iseries/it_lp_reg_save.h>
+ #endif
+ 
+ #include "nonstdio.h"
+@@ -1244,15 +1243,12 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,
+ 
+ static int xmon_depth_to_print = 64;
+ 
+-#ifdef CONFIG_PPC64
+-#define LRSAVE_OFFSET		0x10
+-#define REG_FRAME_MARKER	0x7265677368657265ul	/* "regshere" */
+-#define MARKER_OFFSET		0x60
++#define LRSAVE_OFFSET		(STACK_FRAME_LR_SAVE * sizeof(unsigned long))
++#define MARKER_OFFSET		(STACK_FRAME_MARKER * sizeof(unsigned long))
++
++#ifdef __powerpc64__
+ #define REGS_OFFSET		0x70
+ #else
+-#define LRSAVE_OFFSET		4
+-#define REG_FRAME_MARKER	0x72656773
+-#define MARKER_OFFSET		8
+ #define REGS_OFFSET		16
+ #endif
+ 
+@@ -1318,7 +1314,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
+ 		/* Look for "regshere" marker to see if this is
+ 		   an exception frame. */
+ 		if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
+-		    && marker == REG_FRAME_MARKER) {
++		    && marker == STACK_FRAME_REGS_MARKER) {
+ 			if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
+ 			    != sizeof(regs)) {
+ 				printf("Couldn't read registers at %lx\n",
+@@ -1598,7 +1594,6 @@ void super_regs(void)
+ 		if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+ 			struct paca_struct *ptrPaca;
+ 			struct lppaca *ptrLpPaca;
+-			struct ItLpRegSave *ptrLpRegSave;
+ 
+ 			/* Dump out relevant Paca data areas. */
+ 			printf("Paca: \n");
+@@ -1611,15 +1606,6 @@ void super_regs(void)
+ 			printf("    Saved Gpr3=%.16lx  Saved Gpr4=%.16lx \n",
+ 			       ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
+ 			printf("    Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
+-
+-			printf("  Local Processor Register Save Area (LpRegSave): \n");
+-			ptrLpRegSave = ptrPaca->reg_save_ptr;
+-			printf("    Saved Sprg0=%.16lx  Saved Sprg1=%.16lx \n",
+-			       ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
+-			printf("    Saved Sprg2=%.16lx  Saved Sprg3=%.16lx \n",
+-			       ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
+-			printf("    Saved Msr  =%.16lx  Saved Nia  =%.16lx \n",
+-			       ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
+ 		}
+ #endif
+ 
+diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
+index bcc3aa9..d38b57e 100644
+--- a/arch/ppc/8260_io/fcc_enet.c
++++ b/arch/ppc/8260_io/fcc_enet.c
+@@ -165,9 +165,6 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
+ #ifdef CONFIG_SBC82xx
+ #define F1_RXCLK	9
+ #define F1_TXCLK	10
+-#elif defined(CONFIG_ADS8272)
+-#define F1_RXCLK	11
+-#define F1_TXCLK	10
+ #else
+ #define F1_RXCLK	12
+ #define F1_TXCLK	11
+@@ -175,13 +172,8 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
+ 
+ /* FCC2 Clock Source Configuration.  There are board specific.
+    Can only choose from CLK13-16 */
+-#ifdef CONFIG_ADS8272
+-#define F2_RXCLK	15
+-#define F2_TXCLK	16
+-#else
+ #define F2_RXCLK	13
+ #define F2_TXCLK	14
+-#endif
+ 
+ /* FCC3 Clock Source Configuration.  There are board specific.
+    Can only choose from CLK13-16 */
+@@ -289,10 +281,7 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
+ /* TQM8260 has MDIO and MDCK on PC30 and PC31 respectively */
+ #define PC_MDIO		((uint)0x00000002)
+ #define PC_MDCK		((uint)0x00000001)
+-#elif defined(CONFIG_ADS8272)
+-#define PC_MDIO		((uint)0x00002000)
+-#define PC_MDCK		((uint)0x00001000)
+-#elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260) || defined(CONFIG_PQ2FADS)
++#elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260)
+ #define PC_MDIO		((uint)0x00400000)
+ #define PC_MDCK		((uint)0x00200000)
+ #else
+@@ -2118,11 +2107,6 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
+ 		printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
+ 
+ #ifdef	PHY_INTERRUPT
+-#ifdef CONFIG_ADS8272
+-	if (request_irq(PHY_INTERRUPT, mii_link_interrupt, IRQF_SHARED,
+-				"mii", dev) < 0)
+-		printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
+-#else
+ 	/* Make IRQn edge triggered.  This does not work if PHY_INTERRUPT is
+ 	 * on Port C.
+ 	 */
+@@ -2132,7 +2116,6 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
+ 	if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0,
+ 							"mii", dev) < 0)
+ 		printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
+-#endif
+ #endif	/* PHY_INTERRUPT */
+ 
+ 	/* Set GFMR to enable Ethernet operating mode.
+diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
+index 9d656de..752443d 100644
+--- a/arch/ppc/8xx_io/commproc.c
++++ b/arch/ppc/8xx_io/commproc.c
+@@ -43,7 +43,7 @@
+ ({									\
+ 	u32 offset = offsetof(immap_t, member);				\
+ 	void *addr = ioremap (IMAP_ADDR + offset,			\
+-			      sizeof( ((immap_t*)0)->member));		\
++			      FIELD_SIZEOF(immap_t, member));		\
+ 	addr;								\
+ })
+ 
+diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
+index c6d047a..5899aea 100644
+--- a/arch/ppc/8xx_io/enet.c
++++ b/arch/ppc/8xx_io/enet.c
+@@ -946,29 +946,6 @@ static int __init scc_enet_init(void)
+ 	*((volatile uint *)BCSR1) &= ~BCSR1_ETHEN;
+ #endif
+ 
+-#ifdef CONFIG_MPC885ADS
+-
+-	/* Deassert PHY reset and enable the PHY.
+-	 */
+-	{
+-		volatile uint __iomem *bcsr = ioremap(BCSR_ADDR, BCSR_SIZE);
+-		uint tmp;
+-
+-		tmp = in_be32(bcsr + 1 /* BCSR1 */);
+-		tmp |= BCSR1_ETHEN;
+-		out_be32(bcsr + 1, tmp);
+-		tmp = in_be32(bcsr + 4 /* BCSR4 */);
+-		tmp |= BCSR4_ETH10_RST;
+-		out_be32(bcsr + 4, tmp);
+-		iounmap(bcsr);
+-	}
+-
+-	/* On MPC885ADS SCC ethernet PHY defaults to the full duplex mode
+-	 * upon reset. SCC is set to half duplex by default. So this
+-	 * inconsistency should be better fixed by the software.
+-	 */
+-#endif
+-
+ 	dev->base_addr = (unsigned long)ep;
+ #if 0
+ 	dev->name = "CPM_ENET";
+diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
+index 11b0aa6..2c604d4 100644
+--- a/arch/ppc/8xx_io/fec.c
++++ b/arch/ppc/8xx_io/fec.c
+@@ -199,7 +199,6 @@ static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+ #ifdef	CONFIG_USE_MDIO
+ static void fec_enet_mii(struct net_device *dev);
+ #endif	/* CONFIG_USE_MDIO */
+-static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
+ #ifdef CONFIG_FEC_PACKETHOOK
+ static void  fec_enet_tx(struct net_device *dev, __u32 regval);
+ static void  fec_enet_rx(struct net_device *dev, __u32 regval);
+@@ -472,7 +471,7 @@ fec_timeout(struct net_device *dev)
+  * This is called from the MPC core interrupt.
+  */
+ static	irqreturn_t
+-fec_enet_interrupt(int irq, void * dev_id)
++fec_enet_interrupt(int irq, void *dev_id)
+ {
+ 	struct	net_device *dev = dev_id;
+ 	volatile fec_t	*fecp;
+@@ -520,7 +519,7 @@ fec_enet_interrupt(int irq, void * dev_id)
+ #ifdef	CONFIG_USE_MDIO
+ 			fec_enet_mii(dev);
+ #else
+-printk("%s[%d] %s: unexpected FEC_ENET_MII event\n", __FILE__,__LINE__,__FUNCTION__);
++printk("%s[%d] %s: unexpected FEC_ENET_MII event\n", __FILE__, __LINE__, __func__);
+ #endif	/* CONFIG_USE_MDIO */
+ 		}
+ 
+@@ -1441,7 +1440,7 @@ irqreturn_t mii_link_interrupt(int irq, void * dev_id)
+ 		fecp->fec_ecntrl = ecntrl;	/* restore old settings */
+ 	}
+ #else
+-printk("%s[%d] %s: unexpected Link interrupt\n", __FILE__,__LINE__,__FUNCTION__);
++printk("%s[%d] %s: unexpected Link interrupt\n", __FILE__, __LINE__, __func__);
+ #endif	/* CONFIG_USE_MDIO */
+ 
+ #ifndef CONFIG_RPXCLASSIC
+diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
+index abc877f..0f1863e 100644
+--- a/arch/ppc/Kconfig
++++ b/arch/ppc/Kconfig
+@@ -372,22 +372,6 @@ config MPC8XXFADS
+ 	bool "FADS"
+ 	select FADS
+ 
+-config MPC86XADS
+-	bool "MPC86XADS"
+-	help
+-	  MPC86x Application Development System by Freescale Semiconductor.
+-	  The MPC86xADS is meant to serve as a platform for s/w and h/w
+-	  development around the MPC86X processor families.
+-	select FADS
+-
+-config MPC885ADS
+-	bool "MPC885ADS"
+-	help
+-	  Freescale Semiconductor MPC885 Application Development System (ADS).
+-	  Also known as DUET.
+-	  The MPC885ADS is meant to serve as a platform for s/w and h/w
+-	  development around the MPC885 processor family.
+-
+ config TQM823L
+ 	bool "TQM823L"
+ 	help
+@@ -479,53 +463,6 @@ config WINCEPT
+ 
+ endchoice
+ 
+-menu "Freescale Ethernet driver platform-specific options"
+-	depends on FS_ENET
+-
+-	config MPC8xx_SECOND_ETH
+-	bool "Second Ethernet channel"
+-	depends on (MPC885ADS || MPC86XADS)
+-	default y
+-	help
+-	  This enables support for second Ethernet on MPC885ADS and MPC86xADS boards.
+-	  The latter will use SCC1, for 885ADS you can select it below.
+-
+-	choice
+-		prompt "Second Ethernet channel"
+-		depends on MPC8xx_SECOND_ETH
+-		default MPC8xx_SECOND_ETH_FEC2
+-
+-		config MPC8xx_SECOND_ETH_FEC2
+-		bool "FEC2"
+-		depends on MPC885ADS
+-		help
+-		  Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2
+-		  (often 2-nd UART) will not work if this is enabled.
+-
+-		config MPC8xx_SECOND_ETH_SCC1
+-		bool "SCC1"
+-		depends on MPC86XADS
+-		select MPC8xx_SCC_ENET_FIXED
+-		help
+-		  Enable SCC1 to serve as 2-nd Ethernet channel. Note that SMC1
+-		  (often 1-nd UART) will not work if this is enabled.
+-
+-		config MPC8xx_SECOND_ETH_SCC3
+-		bool "SCC3"
+-		depends on MPC885ADS
+-		help
+-		  Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1
+-		  (often 1-nd UART) will not work if this is enabled.
+-
+-	endchoice
+-
+-	config MPC8xx_SCC_ENET_FIXED
+-	depends on MPC8xx_SECOND_ETH_SCC
+-	default n
+-	bool "Use fixed MII-less mode for SCC Ethernet"
+-
+-endmenu
+-
+ choice
+ 	prompt "Machine Type"
+ 	depends on 6xx
+@@ -666,9 +603,6 @@ config TQM8260
+ 	  End of Life: not yet :-)
+ 	  URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf>
+ 
+-config ADS8272
+-	bool "ADS8272"
+-
+ config PQ2FADS
+ 	bool "Freescale-PQ2FADS"
+ 	help
+@@ -698,11 +632,6 @@ config EV64360
+ 	  platform.
+ endchoice
+ 
+-config PQ2ADS
+-	bool
+-	depends on ADS8272
+-	default y
+-
+ config TQM8xxL
+ 	bool
+ 	depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L)
+@@ -725,15 +654,6 @@ config 8260
+ 	  this option means that you wish to build a kernel for a machine with
+ 	  an 8260 class CPU.
+ 
+-config 8272
+-	bool
+-	depends on 6xx
+-	default y if ADS8272
+-	select 8260
+-	help
+-	  The MPC8272 CPM has a different internal dpram setup than other CPM2
+-	  devices
+-
+ config CPM1
+ 	bool
+ 	depends on 8xx
+@@ -1069,7 +989,7 @@ config PCI_8260
+ 
+ config 8260_PCI9
+ 	bool "Enable workaround for MPC826x erratum PCI 9"
+-	depends on PCI_8260 && !ADS8272
++	depends on PCI_8260
+ 	default y
+ 
+ choice
+diff --git a/arch/ppc/configs/ads8272_defconfig b/arch/ppc/configs/ads8272_defconfig
+deleted file mode 100644
+index 6619f91..0000000
+--- a/arch/ppc/configs/ads8272_defconfig
++++ /dev/null
+@@ -1,930 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.21-rc5
+-# Wed Apr  4 20:55:16 2007
+-#
+-CONFIG_MMU=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_PPC=y
+-CONFIG_PPC32=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+-# CONFIG_MODULES is not set
+-
+-#
+-# Block layer
+-#
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-
+-#
+-# Processor
+-#
+-CONFIG_6xx=y
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_8xx is not set
+-# CONFIG_E200 is not set
+-# CONFIG_E500 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_KEXEC is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_WANT_EARLY_SERIAL is not set
+-CONFIG_EMBEDDEDBOOT=y
+-CONFIG_PPC_STD_MMU=y
+-
+-#
+-# Platform options
+-#
+-
+-#
+-# Freescale Ethernet driver platform-specific options
+-#
+-# CONFIG_PPC_PREP is not set
+-# CONFIG_APUS is not set
+-# CONFIG_KATANA is not set
+-# CONFIG_WILLOW is not set
+-# CONFIG_CPCI690 is not set
+-# CONFIG_POWERPMC250 is not set
+-# CONFIG_CHESTNUT is not set
+-# CONFIG_SPRUCE is not set
+-# CONFIG_HDPU is not set
+-# CONFIG_EV64260 is not set
+-# CONFIG_LOPEC is not set
+-# CONFIG_MVME5100 is not set
+-# CONFIG_PPLUS is not set
+-# CONFIG_PRPMC750 is not set
+-# CONFIG_PRPMC800 is not set
+-# CONFIG_SANDPOINT is not set
+-# CONFIG_RADSTONE_PPC7D is not set
+-# CONFIG_PAL4 is not set
+-# CONFIG_EST8260 is not set
+-# CONFIG_SBC82xx is not set
+-# CONFIG_SBS8260 is not set
+-# CONFIG_RPX8260 is not set
+-# CONFIG_TQM8260 is not set
+-CONFIG_ADS8272=y
+-# CONFIG_PQ2FADS is not set
+-# CONFIG_LITE5200 is not set
+-# CONFIG_MPC834x_SYS is not set
+-# CONFIG_EV64360 is not set
+-CONFIG_PQ2ADS=y
+-CONFIG_8260=y
+-CONFIG_8272=y
+-CONFIG_CPM2=y
+-# CONFIG_PC_KEYBOARD is not set
+-# CONFIG_SMP is not set
+-# CONFIG_HIGHMEM is not set
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-# CONFIG_PPC_I8259 is not set
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_8260=y
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0x80000000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-# CONFIG_NETDEBUG is not set
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_IP_SCTP is not set
+-
+-#
+-# TIPC Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_IEEE80211 is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+-# CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+-# CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+-# CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-# CONFIG_PNPACPI is not set
+-
+-#
+-# Block devices
+-#
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# Misc devices
+-#
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_NETLINK is not set
+-
+-#
+-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+-#
+-# CONFIG_ATA is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+-# CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_IEEE1394 is not set
+-
+-#
+-# I2O device support
+-#
+-# CONFIG_I2O is not set
+-
+-#
+-# Macintosh device drivers
+-#
+-# CONFIG_MAC_EMUMOUSEBTN is not set
+-# CONFIG_WINDFARM is not set
+-
+-#
+-# Network device support
+-#
+-CONFIG_NETDEVICES=y
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-
+-#
+-# ARCnet devices
+-#
+-# CONFIG_ARCNET is not set
+-
+-#
+-# PHY device support
+-#
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-CONFIG_DAVICOM_PHY=y
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-
+-#
+-# Tulip family network device support
+-#
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_NET_PCI is not set
+-CONFIG_FS_ENET=y
+-# CONFIG_FS_ENET_HAS_SCC is not set
+-CONFIG_FS_ENET_HAS_FCC=y
+-
+-#
+-# Ethernet (1000 Mbit)
+-#
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-
+-#
+-# Token Ring devices
+-#
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# Wan interfaces
+-#
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+-# CONFIG_ISDN is not set
+-
+-#
+-# Telephony Support
+-#
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-CONFIG_SERIAL_CPM_SCC4=y
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+-# CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-# CONFIG_WATCHDOG is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_DTLK is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+-# CONFIG_TCG_TPM is not set
+-
+-#
+-# I2C support
+-#
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+-# CONFIG_W1 is not set
+-
+-#
+-# Hardware Monitoring support
+-#
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_ABITUGURU is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-# CONFIG_FB is not set
+-# CONFIG_FB_IBM_GXT4500 is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-
+-#
+-# HID Devices
+-#
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-
+-#
+-# USB support
+-#
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-
+-#
+-# MMC/SD Card support
+-#
+-# CONFIG_MMC is not set
+-
+-#
+-# LED devices
+-#
+-# CONFIG_NEW_LEDS is not set
+-
+-#
+-# LED drivers
+-#
+-
+-#
+-# LED Triggers
+-#
+-
+-#
+-# InfiniBand support
+-#
+-# CONFIG_INFINIBAND is not set
+-
+-#
+-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+-#
+-
+-#
+-# Real Time Clock
+-#
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# DMA Engine support
+-#
+-# CONFIG_DMA_ENGINE is not set
+-
+-#
+-# DMA Clients
+-#
+-
+-#
+-# DMA Devices
+-#
+-
+-#
+-# Auxiliary Display support
+-#
+-
+-#
+-# Virtualization
+-#
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-# CONFIG_JBD_DEBUG is not set
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-CONFIG_FS_POSIX_ACL=y
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-CONFIG_DNOTIFY=y
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-CONFIG_NFS_V3_ACL=y
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_ACL_SUPPORT=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-
+-#
+-# Native Language Support
+-#
+-# CONFIG_NLS is not set
+-
+-#
+-# Distributed Lock Manager
+-#
+-# CONFIG_DLM is not set
+-# CONFIG_SCC_ENET is not set
+-# CONFIG_FEC_ENET is not set
+-
+-#
+-# CPM2 Options
+-#
+-
+-#
+-# Library routines
+-#
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC32 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-# CONFIG_PROFILING is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-
+-#
+-# Hardware crypto devices
+-#
+diff --git a/arch/ppc/configs/mpc86x_ads_defconfig b/arch/ppc/configs/mpc86x_ads_defconfig
+deleted file mode 100644
+index f63c6f5..0000000
+--- a/arch/ppc/configs/mpc86x_ads_defconfig
++++ /dev/null
+@@ -1,633 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.12-rc4
+-# Tue Jun 14 13:36:35 2005
+-#
+-CONFIG_MMU=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_HAVE_DEC_LOCK=y
+-CONFIG_PPC=y
+-CONFIG_PPC32=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+-# CONFIG_CLEAN_COMPILE is not set
+-CONFIG_BROKEN=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+-CONFIG_LOCALVERSION=""
+-# CONFIG_SWAP is not set
+-CONFIG_SYSVIPC=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-CONFIG_SYSCTL=y
+-# CONFIG_AUDIT is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_KOBJECT_UEVENT=y
+-# CONFIG_IKCONFIG is not set
+-CONFIG_EMBEDDED=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-# CONFIG_BASE_FULL is not set
+-CONFIG_FUTEX=y
+-# CONFIG_EPOLL is not set
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-# CONFIG_SHMEM is not set
+-CONFIG_CC_ALIGN_FUNCTIONS=0
+-CONFIG_CC_ALIGN_LABELS=0
+-CONFIG_CC_ALIGN_LOOPS=0
+-CONFIG_CC_ALIGN_JUMPS=0
+-CONFIG_TINY_SHMEM=y
+-CONFIG_BASE_SMALL=1
+-
+-#
+-# Loadable module support
+-#
+-CONFIG_MODULES=y
+-# CONFIG_MODULE_UNLOAD is not set
+-CONFIG_OBSOLETE_MODPARM=y
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-
+-#
+-# Processor
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_POWER3 is not set
+-# CONFIG_POWER4 is not set
+-CONFIG_8xx=y
+-# CONFIG_E500 is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_EMBEDDEDBOOT=y
+-# CONFIG_PM is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-
+-#
+-# Platform options
+-#
+-CONFIG_FADS=y
+-# CONFIG_RPXLITE is not set
+-# CONFIG_RPXCLASSIC is not set
+-# CONFIG_BSEIP is not set
+-# CONFIG_MPC8XXFADS is not set
+-CONFIG_MPC86XADS=y
+-# CONFIG_TQM823L is not set
+-# CONFIG_TQM850L is not set
+-# CONFIG_TQM855L is not set
+-# CONFIG_TQM860L is not set
+-# CONFIG_FPS850L is not set
+-# CONFIG_SPD823TS is not set
+-# CONFIG_IVMS8 is not set
+-# CONFIG_IVML24 is not set
+-# CONFIG_SM850 is not set
+-# CONFIG_HERMES_PRO is not set
+-# CONFIG_IP860 is not set
+-# CONFIG_LWMON is not set
+-# CONFIG_PCU_E is not set
+-# CONFIG_CCM is not set
+-# CONFIG_LANTEC is not set
+-# CONFIG_MBX is not set
+-# CONFIG_WINCEPT is not set
+-# CONFIG_SMP is not set
+-# CONFIG_PREEMPT is not set
+-# CONFIG_HIGHMEM is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_QSPAN is not set
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0x80000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-# CONFIG_STANDALONE is not set
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+-# CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+-# CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_RAM is not set
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_LBD is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_SCSI is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+-# CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_IEEE1394 is not set
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Macintosh device drivers
+-#
+-
+-#
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-# CONFIG_IP_PNP_BOOTP is not set
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_IP_TCPDIAG=y
+-# CONFIG_IP_TCPDIAG_IPV6 is not set
+-CONFIG_IPV6=m
+-# CONFIG_IPV6_PRIVACY is not set
+-# CONFIG_INET6_AH is not set
+-# CONFIG_INET6_ESP is not set
+-# CONFIG_INET6_IPCOMP is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_IPV6_TUNNEL is not set
+-# CONFIG_NETFILTER is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_NET_DIVERT is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_OAKNET is not set
+-
+-#
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# Wan interfaces
+-#
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+-# CONFIG_NETCONSOLE is not set
+-
+-#
+-# ISDN subsystem
+-#
+-# CONFIG_ISDN is not set
+-
+-#
+-# Telephony Support
+-#
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-CONFIG_SOUND_GAMEPORT=y
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-# CONFIG_SERIAL_CPM_SCC1 is not set
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-CONFIG_SERIAL_CPM_SMC1=y
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-CONFIG_UNIX98_PTYS=y
+-# CONFIG_LEGACY_PTYS is not set
+-
+-#
+-# IPMI
+-#
+-# CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-# CONFIG_WATCHDOG is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_DTLK is not set
+-# CONFIG_R3964 is not set
+-
+-#
+-# Ftape, the floppy tape device driver
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+-
+-#
+-# I2C support
+-#
+-# CONFIG_I2C is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+-# CONFIG_W1 is not set
+-
+-#
+-# Misc devices
+-#
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_FB is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-
+-#
+-# USB support
+-#
+-# CONFIG_USB_ARCH_HAS_HCD is not set
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-
+-#
+-# MMC/SD Card support
+-#
+-# CONFIG_MMC is not set
+-
+-#
+-# InfiniBand support
+-#
+-# CONFIG_INFINIBAND is not set
+-
+-#
+-# File systems
+-#
+-# CONFIG_EXT2_FS is not set
+-CONFIG_EXT3_FS=y
+-# CONFIG_EXT3_FS_XATTR is not set
+-CONFIG_JBD=y
+-# CONFIG_JBD_DEBUG is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-
+-#
+-# XFS support
+-#
+-# CONFIG_XFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_QUOTA is not set
+-# CONFIG_DNOTIFY is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_SYSFS=y
+-# CONFIG_DEVFS_FS is not set
+-# CONFIG_DEVPTS_FS_XATTR is not set
+-# CONFIG_TMPFS is not set
+-# CONFIG_HUGETLBFS is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+-# CONFIG_NLS is not set
+-
+-#
+-# MPC8xx CPM Options
+-#
+-CONFIG_SCC_ENET=y
+-CONFIG_SCC1_ENET=y
+-# CONFIG_SCC2_ENET is not set
+-# CONFIG_SCC3_ENET is not set
+-# CONFIG_FEC_ENET is not set
+-# CONFIG_ENET_BIG_BUFFERS is not set
+-
+-#
+-# Generic MPC8xx Options
+-#
+-# CONFIG_8xx_COPYBACK is not set
+-# CONFIG_8xx_CPU6 is not set
+-CONFIG_NO_UCODE_PATCH=y
+-# CONFIG_USB_SOF_UCODE_PATCH is not set
+-# CONFIG_I2C_SPI_UCODE_PATCH is not set
+-# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+-
+-#
+-# Library routines
+-#
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC32 is not set
+-# CONFIG_LIBCRC32C is not set
+-
+-#
+-# Profiling support
+-#
+-# CONFIG_PROFILING is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_TEST is not set
+-
+-#
+-# Hardware crypto devices
+-#
+diff --git a/arch/ppc/configs/mpc885ads_defconfig b/arch/ppc/configs/mpc885ads_defconfig
+deleted file mode 100644
+index 016f94d..0000000
+--- a/arch/ppc/configs/mpc885ads_defconfig
++++ /dev/null
+@@ -1,622 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.12-rc6
+-# Thu Jun  9 21:17:29 2005
+-#
+-CONFIG_MMU=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_HAVE_DEC_LOCK=y
+-CONFIG_PPC=y
+-CONFIG_PPC32=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+-# CONFIG_CLEAN_COMPILE is not set
+-CONFIG_BROKEN=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+-CONFIG_LOCALVERSION=""
+-# CONFIG_SWAP is not set
+-CONFIG_SYSVIPC=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-CONFIG_SYSCTL=y
+-# CONFIG_AUDIT is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_KOBJECT_UEVENT=y
+-# CONFIG_IKCONFIG is not set
+-CONFIG_EMBEDDED=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-# CONFIG_EPOLL is not set
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SHMEM=y
+-CONFIG_CC_ALIGN_FUNCTIONS=0
+-CONFIG_CC_ALIGN_LABELS=0
+-CONFIG_CC_ALIGN_LOOPS=0
+-CONFIG_CC_ALIGN_JUMPS=0
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-
+-#
+-# Loadable module support
+-#
+-# CONFIG_MODULES is not set
+-
+-#
+-# Processor
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_POWER3 is not set
+-# CONFIG_POWER4 is not set
+-CONFIG_8xx=y
+-# CONFIG_E500 is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_EMBEDDEDBOOT=y
+-# CONFIG_PM is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-
+-#
+-# Platform options
+-#
+-# CONFIG_RPXLITE is not set
+-# CONFIG_RPXCLASSIC is not set
+-# CONFIG_BSEIP is not set
+-# CONFIG_FADS is not set
+-CONFIG_MPC885ADS=y
+-# CONFIG_TQM823L is not set
+-# CONFIG_TQM850L is not set
+-# CONFIG_TQM855L is not set
+-# CONFIG_TQM860L is not set
+-# CONFIG_FPS850L is not set
+-# CONFIG_SPD823TS is not set
+-# CONFIG_IVMS8 is not set
+-# CONFIG_IVML24 is not set
+-# CONFIG_SM850 is not set
+-# CONFIG_HERMES_PRO is not set
+-# CONFIG_IP860 is not set
+-# CONFIG_LWMON is not set
+-# CONFIG_PCU_E is not set
+-# CONFIG_CCM is not set
+-# CONFIG_LANTEC is not set
+-# CONFIG_MBX is not set
+-# CONFIG_WINCEPT is not set
+-# CONFIG_SMP is not set
+-# CONFIG_PREEMPT is not set
+-# CONFIG_HIGHMEM is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_QSPAN is not set
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0x80000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+-# CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+-# CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_RAM is not set
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_LBD is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-# CONFIG_IOSCHED_AS is not set
+-# CONFIG_IOSCHED_DEADLINE is not set
+-# CONFIG_IOSCHED_CFQ is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_SCSI is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+-# CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_IEEE1394 is not set
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Macintosh device drivers
+-#
+-
+-#
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_IP_TCPDIAG=y
+-# CONFIG_IP_TCPDIAG_IPV6 is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_NETFILTER is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_NET_DIVERT is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_OAKNET is not set
+-
+-#
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# Wan interfaces
+-#
+-# CONFIG_WAN is not set
+-CONFIG_PPP=y
+-# CONFIG_PPP_MULTILINK is not set
+-# CONFIG_PPP_FILTER is not set
+-CONFIG_PPP_ASYNC=y
+-CONFIG_PPP_SYNC_TTY=y
+-CONFIG_PPP_DEFLATE=y
+-# CONFIG_PPP_BSDCOMP is not set
+-# CONFIG_PPPOE is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+-# CONFIG_NETCONSOLE is not set
+-
+-#
+-# ISDN subsystem
+-#
+-# CONFIG_ISDN is not set
+-
+-#
+-# Telephony Support
+-#
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-# CONFIG_SERIAL_CPM_SCC1 is not set
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-CONFIG_SERIAL_CPM_SMC1=y
+-CONFIG_SERIAL_CPM_SMC2=y
+-CONFIG_UNIX98_PTYS=y
+-# CONFIG_LEGACY_PTYS is not set
+-
+-#
+-# IPMI
+-#
+-# CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-# CONFIG_WATCHDOG is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_DTLK is not set
+-# CONFIG_R3964 is not set
+-
+-#
+-# Ftape, the floppy tape device driver
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+-
+-#
+-# I2C support
+-#
+-# CONFIG_I2C is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+-# CONFIG_W1 is not set
+-
+-#
+-# Misc devices
+-#
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_FB is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-
+-#
+-# USB support
+-#
+-# CONFIG_USB_ARCH_HAS_HCD is not set
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-
+-#
+-# MMC/SD Card support
+-#
+-# CONFIG_MMC is not set
+-
+-#
+-# InfiniBand support
+-#
+-# CONFIG_INFINIBAND is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-CONFIG_EXT2_FS_XATTR=y
+-# CONFIG_EXT2_FS_POSIX_ACL is not set
+-# CONFIG_EXT2_FS_SECURITY is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-CONFIG_JBD=y
+-# CONFIG_JBD_DEBUG is not set
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-
+-#
+-# XFS support
+-#
+-# CONFIG_XFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_QUOTA is not set
+-# CONFIG_DNOTIFY is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-# CONFIG_PROC_KCORE is not set
+-CONFIG_SYSFS=y
+-# CONFIG_DEVFS_FS is not set
+-# CONFIG_DEVPTS_FS_XATTR is not set
+-# CONFIG_TMPFS is not set
+-# CONFIG_HUGETLBFS is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_SUNRPC=y
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-
+-#
+-# Native Language Support
+-#
+-# CONFIG_NLS is not set
+-
+-#
+-# MPC8xx CPM Options
+-#
+-CONFIG_SCC_ENET=y
+-# CONFIG_SCC1_ENET is not set
+-# CONFIG_SCC2_ENET is not set
+-CONFIG_SCC3_ENET=y
+-# CONFIG_FEC_ENET is not set
+-# CONFIG_ENET_BIG_BUFFERS is not set
+-
+-#
+-# Generic MPC8xx Options
+-#
+-CONFIG_8xx_COPYBACK=y
+-CONFIG_8xx_CPU6=y
+-CONFIG_NO_UCODE_PATCH=y
+-# CONFIG_USB_SOF_UCODE_PATCH is not set
+-# CONFIG_I2C_SPI_UCODE_PATCH is not set
+-# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_CRC_CCITT=y
+-# CONFIG_CRC32 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-
+-#
+-# Profiling support
+-#
+-# CONFIG_PROFILING is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
+-# CONFIG_CRYPTO is not set
+-
+-#
+-# Hardware crypto devices
+-#
+diff --git a/arch/ppc/configs/sandpoint_defconfig b/arch/ppc/configs/sandpoint_defconfig
+index fb493a6..9525e34 100644
+--- a/arch/ppc/configs/sandpoint_defconfig
++++ b/arch/ppc/configs/sandpoint_defconfig
+@@ -189,7 +189,7 @@ CONFIG_IDE_TASKFILE_IO=y
+ #
+ # IDE chipset support/bugfixes
+ #
+-CONFIG_IDE_GENERIC=y
++CONFIG_BLK_DEV_SL82C105=y
+ # CONFIG_BLK_DEV_IDEPCI is not set
+ # CONFIG_BLK_DEV_IDEDMA is not set
+ # CONFIG_IDEDMA_AUTO is not set
+diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
+index 1b0ec72..e7e642b 100644
+--- a/arch/ppc/kernel/head.S
++++ b/arch/ppc/kernel/head.S
+@@ -701,23 +701,6 @@ load_up_altivec:
+ 	b	fast_exception_return
+ 
+ /*
+- * AltiVec unavailable trap from kernel - print a message, but let
+- * the task use AltiVec in the kernel until it returns to user mode.
+- */
+-KernelAltiVec:
+-	lwz	r3,_MSR(r1)
+-	oris	r3,r3,MSR_VEC at h
+-	stw	r3,_MSR(r1)	/* enable use of AltiVec after return */
+-	lis	r3,87f at h
+-	ori	r3,r3,87f at l
+-	mr	r4,r2		/* current */
+-	lwz	r5,_NIP(r1)
+-	bl	printk
+-	b	ret_from_except
+-87:	.string	"AltiVec used in kernel  (task=%p, pc=%x)  \n"
+-	.align	4,0
+-
+-/*
+  * giveup_altivec(tsk)
+  * Disable AltiVec for the task given as the argument,
+  * and save the AltiVec registers in its thread_struct.
+diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
+index c2ec13b..50ce83f 100644
+--- a/arch/ppc/kernel/pci.c
++++ b/arch/ppc/kernel/pci.c
+@@ -578,39 +578,6 @@ pcibios_assign_resources(void)
+ }
+ 
+ 
+-int
+-pcibios_enable_resources(struct pci_dev *dev, int mask)
+-{
+-	u16 cmd, old_cmd;
+-	int idx;
+-	struct resource *r;
+-
+-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+-	old_cmd = cmd;
+-	for (idx=0; idx<6; idx++) {
+-		/* Only set up the requested stuff */
+-		if (!(mask & (1<<idx)))
+-			continue;
+-	
+-		r = &dev->resource[idx];
+-		if (r->flags & IORESOURCE_UNSET) {
+-			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+-			return -EINVAL;
+-		}
+-		if (r->flags & IORESOURCE_IO)
+-			cmd |= PCI_COMMAND_IO;
+-		if (r->flags & IORESOURCE_MEM)
+-			cmd |= PCI_COMMAND_MEMORY;
+-	}
+-	if (dev->resource[PCI_ROM_RESOURCE].start)
+-		cmd |= PCI_COMMAND_MEMORY;
+-	if (cmd != old_cmd) {
+-		printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+-		pci_write_config_word(dev, PCI_COMMAND, cmd);
+-	}
+-	return 0;
+-}
+-
+ static int next_controller_index;
+ 
+ struct pci_controller * __init
+@@ -785,33 +752,11 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
+ 
+ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+-	u16 cmd, old_cmd;
+-	int idx;
+-	struct resource *r;
+-
+ 	if (ppc_md.pcibios_enable_device_hook)
+ 		if (ppc_md.pcibios_enable_device_hook(dev, 0))
+ 			return -EINVAL;
+-		
+-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+-	old_cmd = cmd;
+-	for (idx=0; idx<6; idx++) {
+-		r = &dev->resource[idx];
+-		if (r->flags & IORESOURCE_UNSET) {
+-			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+-			return -EINVAL;
+-		}
+-		if (r->flags & IORESOURCE_IO)
+-			cmd |= PCI_COMMAND_IO;
+-		if (r->flags & IORESOURCE_MEM)
+-			cmd |= PCI_COMMAND_MEMORY;
+-	}
+-	if (cmd != old_cmd) {
+-		printk("PCI: Enabling device %s (%04x -> %04x)\n",
+-		       pci_name(dev), old_cmd, cmd);
+-		pci_write_config_word(dev, PCI_COMMAND, cmd);
+-	}
+-	return 0;
++
++	return pci_enable_resources(dev, mask);
+ }
+ 
+ struct pci_controller*
+diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
+index c353502..d9036ef 100644
+--- a/arch/ppc/kernel/ppc_ksyms.c
++++ b/arch/ppc/kernel/ppc_ksyms.c
+@@ -12,7 +12,6 @@
+ #include <linux/irq.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/pm.h>
+ #include <linux/bitops.h>
+ 
+@@ -89,6 +88,7 @@ EXPORT_SYMBOL(strncpy);
+ EXPORT_SYMBOL(strcat);
+ EXPORT_SYMBOL(strlen);
+ EXPORT_SYMBOL(strcmp);
++EXPORT_SYMBOL(strncmp);
+ 
+ EXPORT_SYMBOL(csum_partial);
+ EXPORT_SYMBOL(csum_partial_copy_generic);
+@@ -124,10 +124,6 @@ EXPORT_SYMBOL(__ioremap);
+ EXPORT_SYMBOL(iounmap);
+ EXPORT_SYMBOL(ioremap_bot);	/* aka VMALLOC_END */
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-EXPORT_SYMBOL(ppc_ide_md);
+-#endif
+-
+ #ifdef CONFIG_PCI
+ EXPORT_SYMBOL(isa_io_base);
+ EXPORT_SYMBOL(isa_mem_base);
+diff --git a/arch/ppc/kernel/semaphore.c b/arch/ppc/kernel/semaphore.c
+deleted file mode 100644
+index 2fe429b..0000000
+--- a/arch/ppc/kernel/semaphore.c
++++ /dev/null
+@@ -1,131 +0,0 @@
+-/*
+- * PowerPC-specific semaphore code.
+- *
+- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * April 2001 - Reworked by Paul Mackerras <paulus at samba.org>
+- * to eliminate the SMP races in the old version between the updates
+- * of `count' and `waking'.  Now we use negative `count' values to
+- * indicate that some process(es) are waiting for the semaphore.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <asm/atomic.h>
+-#include <asm/semaphore.h>
+-#include <asm/errno.h>
+-
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- *	old_count = sem->count;
+- *	tmp = MAX(old_count, 0) + incr;
+- *	sem->count = tmp;
+- *	return old_count;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+-	int old_count, tmp;
+-
+-	__asm__ __volatile__("\n"
+-"1:	lwarx	%0,0,%3\n"
+-"	srawi	%1,%0,31\n"
+-"	andc	%1,%0,%1\n"
+-"	add	%1,%1,%4\n"
+-	PPC405_ERR77(0,%3)
+-"	stwcx.	%1,0,%3\n"
+-"	bne	1b"
+-	: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+-	: "r" (&sem->count), "r" (incr), "m" (sem->count)
+-	: "cc");
+-
+-	return old_count;
+-}
+-
+-void __up(struct semaphore *sem)
+-{
+-	/*
+-	 * Note that we incremented count in up() before we came here,
+-	 * but that was ineffective since the result was <= 0, and
+-	 * any negative value of count is equivalent to 0.
+-	 * This ends up setting count to 1, unless count is now > 0
+-	 * (i.e. because some other cpu has called up() in the meantime),
+-	 * in which case we just increment count.
+-	 */
+-	__sem_update_count(sem, 1);
+-	wake_up(&sem->wait);
+-}
+-
+-/*
+- * Note that when we come in to __down or __down_interruptible,
+- * we have already decremented count, but that decrement was
+- * ineffective since the result was < 0, and any negative value
+- * of count is equivalent to 0.
+- * Thus it is only when we decrement count from some value > 0
+- * that we have actually got the semaphore.
+- */
+-void __sched __down(struct semaphore *sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	tsk->state = TASK_UNINTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-	smp_wmb();
+-
+-	/*
+-	 * Try to get the semaphore.  If the count is > 0, then we've
+-	 * got the semaphore; we decrement count and exit the loop.
+-	 * If the count is 0 or negative, we set it to -1, indicating
+-	 * that we are asleep, and then sleep.
+-	 */
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		schedule();
+-		tsk->state = TASK_UNINTERRUPTIBLE;
+-	}
+-	remove_wait_queue(&sem->wait, &wait);
+-	tsk->state = TASK_RUNNING;
+-
+-	/*
+-	 * If there are any more sleepers, wake one of them up so
+-	 * that it can either get the semaphore, or set count to -1
+-	 * indicating that there are still processes sleeping.
+-	 */
+-	wake_up(&sem->wait);
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	tsk->state = TASK_INTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-	smp_wmb();
+-
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		if (signal_pending(current)) {
+-			/*
+-			 * A signal is pending - give up trying.
+-			 * Set sem->count to 0 if it is negative,
+-			 * since we are no longer sleeping.
+-			 */
+-			__sem_update_count(sem, 0);
+-			retval = -EINTR;
+-			break;
+-		}
+-		schedule();
+-		tsk->state = TASK_INTERRUPTIBLE;
+-	}
+-	tsk->state = TASK_RUNNING;
+-	remove_wait_queue(&sem->wait, &wait);
+-	wake_up(&sem->wait);
+-	return retval;
+-}
+diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
+index 2940559..bfddfde 100644
+--- a/arch/ppc/kernel/setup.c
++++ b/arch/ppc/kernel/setup.c
+@@ -10,7 +10,6 @@
+ #include <linux/reboot.h>
+ #include <linux/delay.h>
+ #include <linux/initrd.h>
+-#include <linux/ide.h>
+ #include <linux/screen_info.h>
+ #include <linux/bootmem.h>
+ #include <linux/seq_file.h>
+@@ -57,7 +56,6 @@ extern void ppc6xx_idle(void);
+ extern void power4_idle(void);
+ 
+ extern boot_infos_t *boot_infos;
+-struct ide_machdep_calls ppc_ide_md;
+ 
+ /* Used with the BI_MEMSIZE bootinfo parameter to store the memory
+    size value reported by the boot loader. */
+diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
+index 84ed33a..927253b 100644
+--- a/arch/ppc/lib/string.S
++++ b/arch/ppc/lib/string.S
+@@ -121,6 +121,20 @@ _GLOBAL(strcmp)
+ 	beq	1b
+ 	blr
+ 
++_GLOBAL(strncmp)
++	PPC_LCMPI r5,0
++	beqlr
++	mtctr	r5
++	addi	r5,r3,-1
++	addi	r4,r4,-1
++1:	lbzu	r3,1(r5)
++	cmpwi	1,r3,0
++	lbzu	r0,1(r4)
++	subf.	r3,r0,r3
++	beqlr	1
++	bdnzt	eq,1b
++	blr
++
+ _GLOBAL(strlen)
+ 	addi	r4,r3,-1
+ 1:	lbzu	r0,1(r4)
+diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
+index 7444df3..1a63711 100644
+--- a/arch/ppc/mm/init.c
++++ b/arch/ppc/mm/init.c
+@@ -109,7 +109,6 @@ void show_mem(void)
+ 
+ 	printk("Mem-info:\n");
+ 	show_free_areas();
+-	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ 	i = max_mapnr;
+ 	while (i-- > 0) {
+ 		total++;
+diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c
+index 017623c..01f20f4 100644
+--- a/arch/ppc/platforms/4xx/bamboo.c
++++ b/arch/ppc/platforms/4xx/bamboo.c
+@@ -22,7 +22,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
+index 453643a..8027a36 100644
+--- a/arch/ppc/platforms/4xx/ebony.c
++++ b/arch/ppc/platforms/4xx/ebony.c
+@@ -25,7 +25,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c
+index b79ebb8..f6d8c2e 100644
+--- a/arch/ppc/platforms/4xx/luan.c
++++ b/arch/ppc/platforms/4xx/luan.c
+@@ -23,7 +23,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
+index 28a712c..308386e 100644
+--- a/arch/ppc/platforms/4xx/ocotea.c
++++ b/arch/ppc/platforms/4xx/ocotea.c
+@@ -23,7 +23,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c
+index f6a0c66..1156942 100644
+--- a/arch/ppc/platforms/4xx/taishan.c
++++ b/arch/ppc/platforms/4xx/taishan.c
+@@ -23,7 +23,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c
+index 66a44ff..f6cfd44 100644
+--- a/arch/ppc/platforms/4xx/yucca.c
++++ b/arch/ppc/platforms/4xx/yucca.c
+@@ -24,7 +24,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
+index 40f53fb..6260231 100644
+--- a/arch/ppc/platforms/Makefile
++++ b/arch/ppc/platforms/Makefile
+@@ -4,7 +4,6 @@
+ 
+ obj-$(CONFIG_PPC_PREP)		+= prep_pci.o prep_setup.o
+ obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
+-obj-$(CONFIG_PQ2ADS)		+= pq2ads.o
+ obj-$(CONFIG_TQM8260)		+= tqm8260_setup.o
+ obj-$(CONFIG_CPCI690)		+= cpci690.o
+ obj-$(CONFIG_EV64260)		+= ev64260.o
+@@ -24,6 +23,3 @@ obj-$(CONFIG_SBC82xx)		+= sbc82xx.o
+ obj-$(CONFIG_SPRUCE)		+= spruce.o
+ obj-$(CONFIG_LITE5200)		+= lite5200.o
+ obj-$(CONFIG_EV64360)		+= ev64360.o
+-obj-$(CONFIG_MPC86XADS)		+= mpc866ads_setup.o
+-obj-$(CONFIG_MPC885ADS)		+= mpc885ads_setup.o
+-obj-$(CONFIG_ADS8272)		+= mpc8272ads_setup.o
+diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c
+index dcd6070..27c140f 100644
+--- a/arch/ppc/platforms/chestnut.c
++++ b/arch/ppc/platforms/chestnut.c
+@@ -22,7 +22,6 @@
+ #include <linux/initrd.h>
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial_8250.h>
+diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c
+index e78bccf..07f672d 100644
+--- a/arch/ppc/platforms/cpci690.c
++++ b/arch/ppc/platforms/cpci690.c
+@@ -10,7 +10,6 @@
+  */
+ #include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/irq.h>
+ #include <linux/fs.h>
+ #include <linux/seq_file.h>
+diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c
+index c1f77e1..f522b31 100644
+--- a/arch/ppc/platforms/ev64260.c
++++ b/arch/ppc/platforms/ev64260.c
+@@ -23,7 +23,6 @@
+ 
+ #include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/irq.h>
+ #include <linux/fs.h>
+ #include <linux/seq_file.h>
+diff --git a/arch/ppc/platforms/fads.h b/arch/ppc/platforms/fads.h
+index 2f9f0f6..5219366 100644
+--- a/arch/ppc/platforms/fads.h
++++ b/arch/ppc/platforms/fads.h
+@@ -22,29 +22,6 @@
+ 
+ #include <asm/ppcboot.h>
+ 
+-#if defined(CONFIG_MPC86XADS)
+-
+-#define BOARD_CHIP_NAME "MPC86X"
+-
+-/* U-Boot maps BCSR to 0xff080000 */
+-#define BCSR_ADDR		((uint)0xff080000)
+-
+-/* MPC86XADS has one more CPLD and an additional BCSR.
+- */
+-#define CFG_PHYDEV_ADDR		((uint)0xff0a0000)
+-#define BCSR5			((uint)(CFG_PHYDEV_ADDR + 0x300))
+-
+-#define BCSR5_T1_RST		0x10
+-#define BCSR5_ATM155_RST	0x08
+-#define BCSR5_ATM25_RST		0x04
+-#define BCSR5_MII1_EN		0x02
+-#define BCSR5_MII1_RST		0x01
+-
+-/* There is no PHY link change interrupt */
+-#define PHY_INTERRUPT	(-1)
+-
+-#else /* FADS */
+-
+ /* Memory map is configured by the PROM startup.
+  * I tried to follow the FADS manual, although the startup PROM
+  * dictates this and we simply have to move some of the physical
+@@ -55,8 +32,6 @@
+ /* PHY link change interrupt */
+ #define PHY_INTERRUPT	SIU_IRQ2
+ 
+-#endif /* CONFIG_MPC86XADS */
+-
+ #define BCSR_SIZE		((uint)(64 * 1024))
+ #define BCSR0			((uint)(BCSR_ADDR + 0x00))
+ #define BCSR1			((uint)(BCSR_ADDR + 0x04))
+diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c
+index ca5de13..904b518 100644
+--- a/arch/ppc/platforms/hdpu.c
++++ b/arch/ppc/platforms/hdpu.c
+@@ -16,7 +16,6 @@
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/irq.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/platform_device.h>
+ 
+@@ -604,41 +603,6 @@ static void parse_bootinfo(unsigned long r3,
+ 	}
+ }
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-static void
+-hdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name)
+-{
+-	request_region(from, extent, name);
+-	return;
+-}
+-
+-static void hdpu_ide_release_region(ide_ioreg_t from, unsigned int extent)
+-{
+-	release_region(from, extent);
+-	return;
+-}
+-
+-static void __init
+-hdpu_ide_pci_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port,
+-			     ide_ioreg_t ctrl_port, int *irq)
+-{
+-	struct pci_dev *dev;
+-
+-	pci_for_each_dev(dev) {
+-		if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) ||
+-		    ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)) {
+-			hw->irq = dev->irq;
+-
+-			if (irq != NULL) {
+-				*irq = dev->irq;
+-			}
+-		}
+-	}
+-
+-	return;
+-}
+-#endif
+-
+ void hdpu_heartbeat(void)
+ {
+ 	if (mv64x60_read(&bh, MV64x60_GPP_VALUE) & (1 << 5))
+diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
+index b947c77..1e3aa6e 100644
+--- a/arch/ppc/platforms/lopec.c
++++ b/arch/ppc/platforms/lopec.c
+@@ -15,7 +15,6 @@
+ #include <linux/pci_ids.h>
+ #include <linux/ioport.h>
+ #include <linux/init.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/initrd.h>
+ #include <linux/console.h>
+@@ -168,85 +167,6 @@ lopec_power_off(void)
+ 	lopec_halt();
+ }
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-int lopec_ide_ports_known = 0;
+-static unsigned long lopec_ide_regbase[MAX_HWIFS];
+-static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS];
+-static unsigned long lopec_idedma_regbase;
+-
+-static void
+-lopec_ide_probe(void)
+-{
+-	struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+-					      PCI_DEVICE_ID_WINBOND_82C105,
+-					      NULL);
+-	lopec_ide_ports_known = 1;
+-
+-	if (dev) {
+-		lopec_ide_regbase[0] = dev->resource[0].start;
+-		lopec_ide_regbase[1] = dev->resource[2].start;
+-		lopec_ide_ctl_regbase[0] = dev->resource[1].start;
+-		lopec_ide_ctl_regbase[1] = dev->resource[3].start;
+-		lopec_idedma_regbase = dev->resource[4].start;
+-		pci_dev_put(dev);
+-	}
+-}
+-
+-static int
+-lopec_ide_default_irq(unsigned long base)
+-{
+-	if (lopec_ide_ports_known == 0)
+-		lopec_ide_probe();
+-
+-	if (base == lopec_ide_regbase[0])
+-		return 14;
+-	else if (base == lopec_ide_regbase[1])
+-		return 15;
+-	else
+-		return 0;
+-}
+-
+-static unsigned long
+-lopec_ide_default_io_base(int index)
+-{
+-	if (lopec_ide_ports_known == 0)
+-		lopec_ide_probe();
+-	return lopec_ide_regbase[index];
+-}
+-
+-static void __init
+-lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data,
+-			  unsigned long ctl, int *irq)
+-{
+-	unsigned long reg = data;
+-	uint alt_status_base;
+-	int i;
+-
+-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+-		hw->io_ports[i] = reg++;
+-
+-	if (data == lopec_ide_regbase[0]) {
+-		alt_status_base = lopec_ide_ctl_regbase[0] + 2;
+-		hw->irq = 14;
+-	} else if (data == lopec_ide_regbase[1]) {
+-		alt_status_base = lopec_ide_ctl_regbase[1] + 2;
+-		hw->irq = 15;
+-	} else {
+-		alt_status_base = 0;
+-		hw->irq = 0;
+-	}
+-
+-	if (ctl)
+-		hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
+-	else
+-		hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+-
+-	if (irq != NULL)
+-		*irq = hw->irq;
+-
+-}
+-#endif /* BLK_DEV_IDE */
+-
+ static void __init
+ lopec_init_IRQ(void)
+ {
+@@ -384,11 +304,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ 	ppc_md.nvram_read_val = todc_direct_read_val;
+ 	ppc_md.nvram_write_val = todc_direct_write_val;
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-	ppc_ide_md.default_irq = lopec_ide_default_irq;
+-	ppc_ide_md.default_io_base = lopec_ide_default_io_base;
+-	ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports;
+-#endif
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ 	ppc_md.progress = gen550_progress;
+ #endif
+diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
+deleted file mode 100644
+index 47f4b38..0000000
+--- a/arch/ppc/platforms/mpc8272ads_setup.c
++++ /dev/null
+@@ -1,367 +0,0 @@
+-/*
+- * arch/ppc/platforms/mpc8272ads_setup.c
+- *
+- * MPC82xx Board-specific PlatformDevice descriptions
+- *
+- * 2005 (c) MontaVista Software, Inc.
+- * Vitaly Bordug <vbordug at ru.mvista.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/init.h>
+-#include <linux/module.h>
+-#include <linux/device.h>
+-#include <linux/ioport.h>
+-#include <linux/fs_enet_pd.h>
+-#include <linux/platform_device.h>
+-#include <linux/phy.h>
+-
+-#include <asm/io.h>
+-#include <asm/mpc8260.h>
+-#include <asm/cpm2.h>
+-#include <asm/immap_cpm2.h>
+-#include <asm/irq.h>
+-#include <asm/ppc_sys.h>
+-#include <asm/ppcboot.h>
+-#include <linux/fs_uart_pd.h>
+-
+-#include "pq2ads_pd.h"
+-
+-static void init_fcc1_ioports(struct fs_platform_info*);
+-static void init_fcc2_ioports(struct fs_platform_info*);
+-static void init_scc1_uart_ioports(struct fs_uart_platform_info*);
+-static void init_scc4_uart_ioports(struct fs_uart_platform_info*);
+-
+-static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
+-	[fsid_scc1_uart] = {
+-		.init_ioports 	= init_scc1_uart_ioports,
+-		.fs_no		= fsid_scc1_uart,
+-		.brg		= 1,
+-		.tx_num_fifo	= 4,
+-		.tx_buf_size	= 32,
+-		.rx_num_fifo	= 4,
+-		.rx_buf_size	= 32,
+-	},
+-	[fsid_scc4_uart] = {
+-		.init_ioports 	= init_scc4_uart_ioports,
+-		.fs_no		= fsid_scc4_uart,
+-		.brg		= 4,
+-		.tx_num_fifo	= 4,
+-		.tx_buf_size	= 32,
+-		.rx_num_fifo	= 4,
+-		.rx_buf_size	= 32,
+-	},
+-};
+-
+-static struct fs_mii_bb_platform_info m82xx_mii_bb_pdata = {
+-	.mdio_dat.bit	= 18,
+-	.mdio_dir.bit	= 18,
+-	.mdc_dat.bit	= 19,
+-	.delay		= 1,
+-};
+-
+-static struct fs_platform_info mpc82xx_enet_pdata[] = {
+-	[fsid_fcc1] = {
+-		.fs_no		= fsid_fcc1,
+-		.cp_page	= CPM_CR_FCC1_PAGE,
+-		.cp_block 	= CPM_CR_FCC1_SBLOCK,
+-
+-		.clk_trx 	= (PC_F1RXCLK | PC_F1TXCLK),
+-		.clk_route	= CMX1_CLK_ROUTE,
+-		.clk_mask	= CMX1_CLK_MASK,
+-		.init_ioports 	= init_fcc1_ioports,
+-
+-		.mem_offset	= FCC1_MEM_OFFSET,
+-
+-		.rx_ring	= 32,
+-		.tx_ring	= 32,
+-		.rx_copybreak	= 240,
+-		.use_napi	= 0,
+-		.napi_weight	= 17,
+-		.bus_id		= "0:00",
+-	},
+-	[fsid_fcc2] = {
+-		.fs_no		= fsid_fcc2,
+-		.cp_page	= CPM_CR_FCC2_PAGE,
+-		.cp_block 	= CPM_CR_FCC2_SBLOCK,
+-		.clk_trx 	= (PC_F2RXCLK | PC_F2TXCLK),
+-		.clk_route	= CMX2_CLK_ROUTE,
+-		.clk_mask	= CMX2_CLK_MASK,
+-		.init_ioports	= init_fcc2_ioports,
+-
+-		.mem_offset	= FCC2_MEM_OFFSET,
+-
+-		.rx_ring	= 32,
+-		.tx_ring	= 32,
+-		.rx_copybreak	= 240,
+-		.use_napi	= 0,
+-		.napi_weight	= 17,
+-		.bus_id		= "0:03",
+-	},
+-};
+-
+-static void init_fcc1_ioports(struct fs_platform_info* pdata)
+-{
+-	struct io_port *io;
+-	u32 tempval;
+-	cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+-	u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
+-
+-	io = &immap->im_ioport;
+-
+-	/* Enable the PHY */
+-	clrbits32(bcsr, BCSR1_FETHIEN);
+-	setbits32(bcsr, BCSR1_FETH_RST);
+-
+-	/* FCC1 pins are on port A/C. */
+-	/* Configure port A and C pins for FCC1 Ethernet. */
+-
+-	tempval = in_be32(&io->iop_pdira);
+-	tempval &= ~PA1_DIRA0;
+-	tempval |= PA1_DIRA1;
+-	out_be32(&io->iop_pdira, tempval);
+-
+-	tempval = in_be32(&io->iop_psora);
+-	tempval &= ~PA1_PSORA0;
+-	tempval |= PA1_PSORA1;
+-	out_be32(&io->iop_psora, tempval);
+-
+-	setbits32(&io->iop_ppara,PA1_DIRA0 | PA1_DIRA1);
+-
+-	/* Alter clocks */
+-	tempval = PC_F1TXCLK|PC_F1RXCLK;
+-
+-	clrbits32(&io->iop_psorc, tempval);
+-	clrbits32(&io->iop_pdirc, tempval);
+-	setbits32(&io->iop_pparc, tempval);
+-
+-	clrbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_MASK);
+-	setbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_ROUTE);
+-	iounmap(bcsr);
+-	iounmap(immap);
+-}
+-
+-static void init_fcc2_ioports(struct fs_platform_info* pdata)
+-{
+-	cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+-	u32 *bcsr = ioremap(BCSR_ADDR+12, sizeof(u32));
+-
+-	struct io_port *io;
+-	u32 tempval;
+-
+-	immap = cpm2_immr;
+-
+-	io = &immap->im_ioport;
+-
+-	/* Enable the PHY */
+-	clrbits32(bcsr, BCSR3_FETHIEN2);
+-	setbits32(bcsr, BCSR3_FETH2_RST);
+-
+-	/* FCC2 are port B/C. */
+-	/* Configure port A and C pins for FCC2 Ethernet. */
+-
+-	tempval = in_be32(&io->iop_pdirb);
+-	tempval &= ~PB2_DIRB0;
+-	tempval |= PB2_DIRB1;
+-	out_be32(&io->iop_pdirb, tempval);
+-
+-	tempval = in_be32(&io->iop_psorb);
+-	tempval &= ~PB2_PSORB0;
+-	tempval |= PB2_PSORB1;
+-	out_be32(&io->iop_psorb, tempval);
+-
+-	setbits32(&io->iop_pparb,PB2_DIRB0 | PB2_DIRB1);
+-
+-	tempval = PC_F2RXCLK|PC_F2TXCLK;
+-
+-	/* Alter clocks */
+-	clrbits32(&io->iop_psorc,tempval);
+-	clrbits32(&io->iop_pdirc,tempval);
+-	setbits32(&io->iop_pparc,tempval);
+-
+-	clrbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_MASK);
+-	setbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_ROUTE);
+-
+-	iounmap(bcsr);
+-	iounmap(immap);
+-}
+-
+-
+-static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
+-					      int idx)
+-{
+-	bd_t* bi = (void*)__res;
+-	int fs_no = fsid_fcc1+pdev->id-1;
+-
+-	if(fs_no >= ARRAY_SIZE(mpc82xx_enet_pdata)) {
+-		return;
+-	}
+-
+-	mpc82xx_enet_pdata[fs_no].dpram_offset=
+-			(u32)cpm2_immr->im_dprambase;
+-	mpc82xx_enet_pdata[fs_no].fcc_regs_c =
+-			(u32)cpm2_immr->im_fcc_c;
+-	memcpy(&mpc82xx_enet_pdata[fs_no].macaddr,bi->bi_enetaddr,6);
+-
+-	/* prevent dup mac */
+-	if(fs_no == fsid_fcc2)
+-		mpc82xx_enet_pdata[fs_no].macaddr[5] ^= 1;
+-
+-	pdev->dev.platform_data = &mpc82xx_enet_pdata[fs_no];
+-}
+-
+-static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
+-					      int idx)
+-{
+-	bd_t *bd = (bd_t *) __res;
+-	struct fs_uart_platform_info *pinfo;
+-	int num = ARRAY_SIZE(mpc8272_uart_pdata);
+-	int id = fs_uart_id_scc2fsid(idx);
+-
+-	/* no need to alter anything if console */
+-	if ((id < num) && (!pdev->dev.platform_data)) {
+-		pinfo = &mpc8272_uart_pdata[id];
+-		pinfo->uart_clk = bd->bi_intfreq;
+-		pdev->dev.platform_data = pinfo;
+-	}
+-}
+-
+-static void init_scc1_uart_ioports(struct fs_uart_platform_info* pdata)
+-{
+-	cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+-
+-        /* SCC1 is only on port D */
+-	setbits32(&immap->im_ioport.iop_ppard,0x00000003);
+-	clrbits32(&immap->im_ioport.iop_psord,0x00000001);
+-	setbits32(&immap->im_ioport.iop_psord,0x00000002);
+-	clrbits32(&immap->im_ioport.iop_pdird,0x00000001);
+-	setbits32(&immap->im_ioport.iop_pdird,0x00000002);
+-
+-        /* Wire BRG1 to SCC1 */
+-	clrbits32(&immap->im_cpmux.cmx_scr,0x00ffffff);
+-
+-	iounmap(immap);
+-}
+-
+-static void init_scc4_uart_ioports(struct fs_uart_platform_info* pdata)
+-{
+-	cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+-
+-	setbits32(&immap->im_ioport.iop_ppard,0x00000600);
+-	clrbits32(&immap->im_ioport.iop_psord,0x00000600);
+-	clrbits32(&immap->im_ioport.iop_pdird,0x00000200);
+-	setbits32(&immap->im_ioport.iop_pdird,0x00000400);
+-
+-        /* Wire BRG4 to SCC4 */
+-	clrbits32(&immap->im_cpmux.cmx_scr,0x000000ff);
+-	setbits32(&immap->im_cpmux.cmx_scr,0x0000001b);
+-
+-	iounmap(immap);
+-}
+-
+-static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
+-					      int idx)
+-{
+-	m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
+-	m82xx_mii_bb_pdata.irq[1] = PHY_POLL;
+-	m82xx_mii_bb_pdata.irq[2] = PHY_POLL;
+-	m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
+-	m82xx_mii_bb_pdata.irq[31] = PHY_POLL;
+-
+-
+-	m82xx_mii_bb_pdata.mdio_dat.offset =
+-				(u32)&cpm2_immr->im_ioport.iop_pdatc;
+-
+-	m82xx_mii_bb_pdata.mdio_dir.offset =
+-				(u32)&cpm2_immr->im_ioport.iop_pdirc;
+-
+-	m82xx_mii_bb_pdata.mdc_dat.offset =
+-				(u32)&cpm2_immr->im_ioport.iop_pdatc;
+-
+-
+-	pdev->dev.platform_data = &m82xx_mii_bb_pdata;
+-}
+-
+-static int mpc8272ads_platform_notify(struct device *dev)
+-{
+-	static const struct platform_notify_dev_map dev_map[] = {
+-		{
+-			.bus_id = "fsl-cpm-fcc",
+-			.rtn = mpc8272ads_fixup_enet_pdata,
+-		},
+-		{
+-			.bus_id = "fsl-cpm-scc:uart",
+-			.rtn = mpc8272ads_fixup_uart_pdata,
+-		},
+-		{
+-			.bus_id = "fsl-bb-mdio",
+-			.rtn = mpc8272ads_fixup_mdio_pdata,
+-		},
+-		{
+-			.bus_id = NULL
+-		}
+-	};
+-	platform_notify_map(dev_map,dev);
+-
+-	return 0;
+-
+-}
+-
+-int __init mpc8272ads_init(void)
+-{
+-	printk(KERN_NOTICE "mpc8272ads: Init\n");
+-
+-	platform_notify = mpc8272ads_platform_notify;
+-
+-	ppc_sys_device_initfunc();
+-
+-	ppc_sys_device_disable_all();
+-	ppc_sys_device_enable(MPC82xx_CPM_FCC1);
+-	ppc_sys_device_enable(MPC82xx_CPM_FCC2);
+-
+-	/* to be ready for console, let's attach pdata here */
+-#ifdef CONFIG_SERIAL_CPM_SCC1
+-	ppc_sys_device_setfunc(MPC82xx_CPM_SCC1, PPC_SYS_FUNC_UART);
+-	ppc_sys_device_enable(MPC82xx_CPM_SCC1);
+-
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC4
+-	ppc_sys_device_setfunc(MPC82xx_CPM_SCC4, PPC_SYS_FUNC_UART);
+-	ppc_sys_device_enable(MPC82xx_CPM_SCC4);
+-#endif
+-
+-	ppc_sys_device_enable(MPC82xx_MDIO_BB);
+-
+-	return 0;
+-}
+-
+-/*
+-   To prevent confusion, console selection is gross:
+-   by 0 assumed SCC1 and by 1 assumed SCC4
+- */
+-struct platform_device* early_uart_get_pdev(int index)
+-{
+-	bd_t *bd = (bd_t *) __res;
+-	struct fs_uart_platform_info *pinfo;
+-
+-	struct platform_device* pdev = NULL;
+-	if(index) { /*assume SCC4 here*/
+-		pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC4];
+-		pinfo = &mpc8272_uart_pdata[fsid_scc4_uart];
+-	} else { /*over SCC1*/
+-		pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1];
+-		pinfo = &mpc8272_uart_pdata[fsid_scc1_uart];
+-	}
+-
+-	pinfo->uart_clk = bd->bi_intfreq;
+-	pdev->dev.platform_data = pinfo;
+-	ppc_sys_fixup_mem_resource(pdev, CPM_MAP_ADDR);
+-	return NULL;
+-}
+-
+-arch_initcall(mpc8272ads_init);
+diff --git a/arch/ppc/platforms/mpc885ads.h b/arch/ppc/platforms/mpc885ads.h
+deleted file mode 100644
+index d3bbbb3..0000000
+--- a/arch/ppc/platforms/mpc885ads.h
++++ /dev/null
+@@ -1,93 +0,0 @@
+-/*
+- * A collection of structures, addresses, and values associated with
+- * the Freescale MPC885ADS board.
+- * Copied from the FADS stuff.
+- *
+- * Author: MontaVista Software, Inc.
+- *         source at mvista.com
+- *
+- * 2005 (c) MontaVista Software, Inc.  This file is licensed under the
+- * terms of the GNU General Public License version 2.  This program is licensed
+- * "as is" without any warranty of any kind, whether express or implied.
+- */
+-
+-#ifdef __KERNEL__
+-#ifndef __ASM_MPC885ADS_H__
+-#define __ASM_MPC885ADS_H__
+-
+-
+-#include <asm/ppcboot.h>
+-
+-/* U-Boot maps BCSR to 0xff080000 */
+-#define BCSR_ADDR		((uint)0xff080000)
+-#define BCSR_SIZE		((uint)32)
+-#define BCSR0			((uint)(BCSR_ADDR + 0x00))
+-#define BCSR1			((uint)(BCSR_ADDR + 0x04))
+-#define BCSR2			((uint)(BCSR_ADDR + 0x08))
+-#define BCSR3			((uint)(BCSR_ADDR + 0x0c))
+-#define BCSR4			((uint)(BCSR_ADDR + 0x10))
+-
+-#define CFG_PHYDEV_ADDR		((uint)0xff0a0000)
+-#define BCSR5			((uint)(CFG_PHYDEV_ADDR + 0x300))
+-
+-#define IMAP_ADDR		((uint)0xff000000)
+-#define IMAP_SIZE		((uint)(64 * 1024))
+-
+-#define PCMCIA_MEM_ADDR		((uint)0xff020000)
+-#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+-
+-/* Bits of interest in the BCSRs.
+- */
+-#define BCSR1_ETHEN		((uint)0x20000000)
+-#define BCSR1_IRDAEN		((uint)0x10000000)
+-#define BCSR1_RS232EN_1		((uint)0x01000000)
+-#define BCSR1_PCCEN		((uint)0x00800000)
+-#define BCSR1_PCCVCC0		((uint)0x00400000)
+-#define BCSR1_PCCVPP0		((uint)0x00200000)
+-#define BCSR1_PCCVPP1		((uint)0x00100000)
+-#define BCSR1_PCCVPP_MASK	(BCSR1_PCCVPP0 | BCSR1_PCCVPP1)
+-#define BCSR1_RS232EN_2		((uint)0x00040000)
+-#define BCSR1_PCCVCC1		((uint)0x00010000)
+-#define BCSR1_PCCVCC_MASK	(BCSR1_PCCVCC0 | BCSR1_PCCVCC1)
+-
+-#define BCSR4_ETH10_RST		((uint)0x80000000)	/* 10Base-T PHY reset*/
+-#define BCSR4_USB_LO_SPD	((uint)0x04000000)
+-#define BCSR4_USB_VCC		((uint)0x02000000)
+-#define BCSR4_USB_FULL_SPD	((uint)0x00040000)
+-#define BCSR4_USB_EN		((uint)0x00020000)
+-
+-#define BCSR5_MII2_EN		0x40
+-#define BCSR5_MII2_RST		0x20
+-#define BCSR5_T1_RST		0x10
+-#define BCSR5_ATM155_RST	0x08
+-#define BCSR5_ATM25_RST		0x04
+-#define BCSR5_MII1_EN		0x02
+-#define BCSR5_MII1_RST		0x01
+-
+-/* Interrupt level assignments */
+-#define PHY_INTERRUPT	SIU_IRQ7	/* PHY link change interrupt */
+-#define SIU_INT_FEC1	SIU_LEVEL1	/* FEC1 interrupt */
+-#define SIU_INT_FEC2	SIU_LEVEL3	/* FEC2 interrupt */
+-#define FEC_INTERRUPT	SIU_INT_FEC1	/* FEC interrupt */
+-
+-/* We don't use the 8259 */
+-#define NR_8259_INTS	0
+-
+-/* CPM Ethernet through SCC3 */
+-#define PA_ENET_RXD	((ushort)0x0040)
+-#define PA_ENET_TXD	((ushort)0x0080)
+-#define PE_ENET_TCLK	((uint)0x00004000)
+-#define PE_ENET_RCLK	((uint)0x00008000)
+-#define PE_ENET_TENA	((uint)0x00000010)
+-#define PC_ENET_CLSN	((ushort)0x0400)
+-#define PC_ENET_RENA	((ushort)0x0800)
+-
+-/* Control bits in the SICR to route TCLK (CLK5) and RCLK (CLK6) to
+- * SCC3.  Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero */
+-#define SICR_ENET_MASK	((uint)0x00ff0000)
+-#define SICR_ENET_CLKRT	((uint)0x002c0000)
+-
+-#define BOARD_CHIP_NAME "MPC885"
+-
+-#endif /* __ASM_MPC885ADS_H__ */
+-#endif /* __KERNEL__ */
+diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
+deleted file mode 100644
+index ba06cc0..0000000
+--- a/arch/ppc/platforms/mpc885ads_setup.c
++++ /dev/null
+@@ -1,476 +0,0 @@
+-/*arch/ppc/platforms/mpc885ads_setup.c
+- *
+- * Platform setup for the Freescale mpc885ads board
+- *
+- * Vitaly Bordug <vbordug at ru.mvista.com>
+- *
+- * Copyright 2005 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.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/param.h>
+-#include <linux/string.h>
+-#include <linux/ioport.h>
+-#include <linux/device.h>
+-
+-#include <linux/fs_enet_pd.h>
+-#include <linux/fs_uart_pd.h>
+-#include <linux/mii.h>
+-
+-#include <asm/delay.h>
+-#include <asm/io.h>
+-#include <asm/machdep.h>
+-#include <asm/page.h>
+-#include <asm/processor.h>
+-#include <asm/system.h>
+-#include <asm/time.h>
+-#include <asm/ppcboot.h>
+-#include <asm/8xx_immap.h>
+-#include <asm/cpm1.h>
+-#include <asm/ppc_sys.h>
+-
+-extern unsigned char __res[];
+-static void setup_smc1_ioports(struct fs_uart_platform_info*);
+-static void setup_smc2_ioports(struct fs_uart_platform_info*);
+-
+-static struct fs_mii_fec_platform_info	mpc8xx_mdio_fec_pdata;
+-static void setup_fec1_ioports(struct fs_platform_info*);
+-static void setup_fec2_ioports(struct fs_platform_info*);
+-static void setup_scc3_ioports(struct fs_platform_info*);
+-
+-static struct fs_uart_platform_info mpc885_uart_pdata[] = {
+-	[fsid_smc1_uart] = {
+-		.brg		= 1,
+- 		.fs_no 		= fsid_smc1_uart,
+- 		.init_ioports	= setup_smc1_ioports,
+-		.tx_num_fifo	= 4,
+-		.tx_buf_size	= 32,
+-		.rx_num_fifo	= 4,
+-		.rx_buf_size	= 32,
+- 	},
+- 	[fsid_smc2_uart] = {
+- 		.brg		= 2,
+- 		.fs_no 		= fsid_smc2_uart,
+- 		.init_ioports	= setup_smc2_ioports,
+-		.tx_num_fifo	= 4,
+-		.tx_buf_size	= 32,
+-		.rx_num_fifo	= 4,
+-		.rx_buf_size	= 32,
+- 	},
+-};
+-
+-static struct fs_platform_info mpc8xx_enet_pdata[] = {
+-	[fsid_fec1] = {
+-	 .rx_ring = 128,
+-	 .tx_ring = 16,
+-	 .rx_copybreak = 240,
+-
+-	 .use_napi = 1,
+-	 .napi_weight = 17,
+-
+-	 .init_ioports = setup_fec1_ioports,
+-
+-          .bus_id = "0:00",
+-          .has_phy = 1,
+-	 },
+-	[fsid_fec2] = {
+-	     .rx_ring = 128,
+-	     .tx_ring = 16,
+-	     .rx_copybreak = 240,
+-
+-	     .use_napi = 1,
+-	     .napi_weight = 17,
+-
+-	     .init_ioports = setup_fec2_ioports,
+-
+- 	     .bus_id = "0:01",
+- 	     .has_phy = 1,
+-	     },
+-	[fsid_scc3] = {
+-		.rx_ring = 64,
+-		.tx_ring = 8,
+-		.rx_copybreak = 240,
+-
+-		.use_napi = 1,
+-		.napi_weight = 17,
+-
+-		.init_ioports = setup_scc3_ioports,
+-#ifdef CONFIG_FIXED_MII_10_FDX
+-		.bus_id = "fixed at 100:1",
+-#else
+-		.bus_id = "0:02",
+- #endif
+-	},
+-};
+-
+-void __init board_init(void)
+-{
+-	cpm8xx_t *cp = cpmp;
+- 	unsigned int *bcsr_io;
+-
+-#ifdef CONFIG_FS_ENET
+-	immap_t *immap = (immap_t *) IMAP_ADDR;
+-#endif
+-	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+-
+-	if (bcsr_io == NULL) {
+-		printk(KERN_CRIT "Could not remap BCSR\n");
+-		return;
+-	}
+-#ifdef CONFIG_SERIAL_CPM_SMC1
+-	cp->cp_simode &= ~(0xe0000000 >> 17);	/* brg1 */
+-	clrbits32(bcsr_io, BCSR1_RS232EN_1);
+-        cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
+-        cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+-#else
+-	setbits32(bcsr_io,BCSR1_RS232EN_1);
+-	cp->cp_smc[0].smc_smcmr = 0;
+-	cp->cp_smc[0].smc_smce = 0;
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SMC2
+-	cp->cp_simode &= ~(0xe0000000 >> 1);
+-	cp->cp_simode |= (0x20000000 >> 1);	/* brg2 */
+-	clrbits32(bcsr_io,BCSR1_RS232EN_2);
+-        cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
+-        cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+-#else
+-	setbits32(bcsr_io,BCSR1_RS232EN_2);
+-	cp->cp_smc[1].smc_smcmr = 0;
+-	cp->cp_smc[1].smc_smce = 0;
+-#endif
+-	iounmap(bcsr_io);
+-
+-#ifdef CONFIG_FS_ENET
+-	/* use MDC for MII (common) */
+-	setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
+-	clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
+-	bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
+-	clrbits32(bcsr_io,BCSR5_MII1_EN);
+-	clrbits32(bcsr_io,BCSR5_MII1_RST);
+-#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
+-	clrbits32(bcsr_io,BCSR5_MII2_EN);
+-	clrbits32(bcsr_io,BCSR5_MII2_RST);
+-#endif
+-	iounmap(bcsr_io);
+-#endif
+-}
+-
+-static void setup_fec1_ioports(struct fs_platform_info* pdata)
+-{
+-	immap_t *immap = (immap_t *) IMAP_ADDR;
+-
+-	/* configure FEC1 pins  */
+-	setbits16(&immap->im_ioport.iop_papar, 0xf830);
+-	setbits16(&immap->im_ioport.iop_padir, 0x0830);
+-	clrbits16(&immap->im_ioport.iop_padir, 0xf000);
+-	setbits32(&immap->im_cpm.cp_pbpar, 0x00001001);
+-
+-	clrbits32(&immap->im_cpm.cp_pbdir, 0x00001001);
+-	setbits16(&immap->im_ioport.iop_pcpar, 0x000c);
+-	clrbits16(&immap->im_ioport.iop_pcdir, 0x000c);
+-	setbits32(&immap->im_cpm.cp_pepar, 0x00000003);
+-
+-	setbits32(&immap->im_cpm.cp_pedir, 0x00000003);
+-	clrbits32(&immap->im_cpm.cp_peso, 0x00000003);
+-	clrbits32(&immap->im_cpm.cp_cptr, 0x00000100);
+-}
+-
+-static void setup_fec2_ioports(struct fs_platform_info* pdata)
+-{
+-	immap_t *immap = (immap_t *) IMAP_ADDR;
+-
+-	/* configure FEC2 pins */
+-	setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
+-	setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
+-	clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
+-	setbits32(&immap->im_cpm.cp_peso, 0x00037800);
+-	clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
+-}
+-
+-static void setup_scc3_ioports(struct fs_platform_info* pdata)
+-{
+-	immap_t *immap = (immap_t *) IMAP_ADDR;
+-	unsigned *bcsr_io;
+-
+-	bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
+-
+-	if (bcsr_io == NULL) {
+-		printk(KERN_CRIT "Could not remap BCSR\n");
+-		return;
+-	}
+-
+-	/* Enable the PHY.
+-	 */
+-	clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
+-	udelay(1000);
+-	setbits32(bcsr_io+4, BCSR4_ETH10_RST);
+-	/* Configure port A pins for Txd and Rxd.
+-	 */
+-	setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
+-	clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
+-
+-	/* Configure port C pins to enable CLSN and RENA.
+-	 */
+-	clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
+-	clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
+-	setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
+-
+-	/* Configure port E for TCLK and RCLK.
+-	 */
+-	setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
+-	clrbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
+-	clrbits32(&immap->im_cpm.cp_pedir,
+-		  PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
+-	clrbits32(&immap->im_cpm.cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
+-	setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
+-
+-	/* Configure Serial Interface clock routing.
+-	 * First, clear all SCC bits to zero, then set the ones we want.
+-	 */
+-	clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
+-	setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);
+-
+-	/* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are used.
+-	 */
+-	immap->im_cpm.cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+-	/* On the MPC885ADS SCC ethernet PHY is initialized in the full duplex mode
+-	 * by H/W setting after reset. SCC ethernet controller support only half duplex.
+-	 * This discrepancy of modes causes a lot of carrier lost errors.
+-	 */
+-
+-	/* In the original SCC enet driver the following code is placed at
+-	   the end of the initialization */
+-	setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
+-	clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
+-	setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
+-
+-	setbits32(bcsr_io+4, BCSR1_ETHEN);
+-	iounmap(bcsr_io);
+-}
+-
+-static int mac_count = 0;
+-
+-static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
+-{
+- 	struct fs_platform_info *fpi;
+-	bd_t *bd = (bd_t *) __res;
+-	char *e;
+-	int i;
+-
+-	if(fs_no >= ARRAY_SIZE(mpc8xx_enet_pdata)) {
+-		printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
+-		return;
+-	}
+-
+-	fpi = &mpc8xx_enet_pdata[fs_no];
+-
+-	switch (fs_no) {
+-	case fsid_fec1:
+-		fpi->init_ioports = &setup_fec1_ioports;
+-		break;
+-	case fsid_fec2:
+-		fpi->init_ioports = &setup_fec2_ioports;
+-		break;
+-	case fsid_scc3:
+-		fpi->init_ioports = &setup_scc3_ioports;
+-		break;
+-	default:
+-    	        printk(KERN_WARNING "Device %s is not supported!\n", pdev->name);
+-	        return;
+-	}
+-
+-	pdev->dev.platform_data = fpi;
+-	fpi->fs_no = fs_no;
+-
+-	e = (unsigned char *)&bd->bi_enetaddr;
+-	for (i = 0; i < 6; i++)
+-		fpi->macaddr[i] = *e++;
+-
+-	fpi->macaddr[5] += mac_count++;
+-
+-}
+-
+-static void mpc885ads_fixup_fec_enet_pdata(struct platform_device *pdev,
+-					   int idx)
+-{
+-	/* This is for FEC devices only */
+-	if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
+-		return;
+-	mpc885ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
+-}
+-
+-static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
+-						  int idx)
+-{
+-	/* This is for SCC devices only */
+-	if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
+-		return;
+-
+-	mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
+-}
+-
+-static void setup_smc1_ioports(struct fs_uart_platform_info* pdata)
+-{
+-        immap_t *immap = (immap_t *) IMAP_ADDR;
+-        unsigned *bcsr_io;
+-        unsigned int iobits = 0x000000c0;
+-
+-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+-
+-        if (bcsr_io == NULL) {
+-                printk(KERN_CRIT "Could not remap BCSR1\n");
+-                return;
+-        }
+-        clrbits32(bcsr_io,BCSR1_RS232EN_1);
+-        iounmap(bcsr_io);
+-
+-        setbits32(&immap->im_cpm.cp_pbpar, iobits);
+-        clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+-        clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+-}
+-
+-static void setup_smc2_ioports(struct fs_uart_platform_info* pdata)
+-{
+-        immap_t *immap = (immap_t *) IMAP_ADDR;
+-        unsigned *bcsr_io;
+-        unsigned int iobits = 0x00000c00;
+-
+-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+-
+-        if (bcsr_io == NULL) {
+-                printk(KERN_CRIT "Could not remap BCSR1\n");
+-                return;
+-        }
+-        clrbits32(bcsr_io,BCSR1_RS232EN_2);
+-        iounmap(bcsr_io);
+-
+-#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
+-        setbits32(&immap->im_cpm.cp_pbpar, iobits);
+-        clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+-        clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+-#else
+-        setbits16(&immap->im_ioport.iop_papar, iobits);
+-        clrbits16(&immap->im_ioport.iop_padir, iobits);
+-        clrbits16(&immap->im_ioport.iop_paodr, iobits);
+-#endif
+-}
+-
+-static void __init mpc885ads_fixup_uart_pdata(struct platform_device *pdev,
+-                                              int idx)
+-{
+-	bd_t *bd = (bd_t *) __res;
+-	struct fs_uart_platform_info *pinfo;
+-	int num = ARRAY_SIZE(mpc885_uart_pdata);
+-
+-	int id = fs_uart_id_smc2fsid(idx);
+-
+-	/* no need to alter anything if console */
+-	if ((id < num) && (!pdev->dev.platform_data)) {
+-		pinfo = &mpc885_uart_pdata[id];
+-		pinfo->uart_clk = bd->bi_intfreq;
+-		pdev->dev.platform_data = pinfo;
+-	}
+-}
+-
+-
+-static int mpc885ads_platform_notify(struct device *dev)
+-{
+-
+-	static const struct platform_notify_dev_map dev_map[] = {
+-		{
+-			.bus_id = "fsl-cpm-fec",
+-			.rtn = mpc885ads_fixup_fec_enet_pdata,
+-		},
+-		{
+-			.bus_id = "fsl-cpm-scc",
+-			.rtn = mpc885ads_fixup_scc_enet_pdata,
+-		},
+-		{
+-			.bus_id = "fsl-cpm-smc:uart",
+-			.rtn = mpc885ads_fixup_uart_pdata
+-		},
+-		{
+-			.bus_id = NULL
+-		}
+-	};
+-
+-	platform_notify_map(dev_map,dev);
+-
+-	return 0;
+-}
+-
+-int __init mpc885ads_init(void)
+-{
+-	struct fs_mii_fec_platform_info* fmpi;
+-	bd_t *bd = (bd_t *) __res;
+-
+-	printk(KERN_NOTICE "mpc885ads: Init\n");
+-
+-	platform_notify = mpc885ads_platform_notify;
+-
+-	ppc_sys_device_initfunc();
+-	ppc_sys_device_disable_all();
+-
+-	ppc_sys_device_enable(MPC8xx_CPM_FEC1);
+-
+-	ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+-	fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+-		&mpc8xx_mdio_fec_pdata;
+-
+-	fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+-
+-	/* No PHY interrupt line here */
+-	fmpi->irq[0xf] = SIU_IRQ7;
+-
+-#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
+-	ppc_sys_device_enable(MPC8xx_CPM_SCC3);
+-
+-#endif
+-#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
+-	ppc_sys_device_enable(MPC8xx_CPM_FEC2);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SMC1
+-	ppc_sys_device_enable(MPC8xx_CPM_SMC1);
+-	ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SMC2
+-	ppc_sys_device_enable(MPC8xx_CPM_SMC2);
+-	ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
+-#endif
+-	return 0;
+-}
+-
+-arch_initcall(mpc885ads_init);
+-
+-/*
+-   To prevent confusion, console selection is gross:
+-   by 0 assumed SMC1 and by 1 assumed SMC2
+- */
+-struct platform_device* early_uart_get_pdev(int index)
+-{
+-	bd_t *bd = (bd_t *) __res;
+-	struct fs_uart_platform_info *pinfo;
+-
+-	struct platform_device* pdev = NULL;
+-	if(index) { /*assume SMC2 here*/
+-		pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
+-		pinfo = &mpc885_uart_pdata[1];
+-	} else { /*over SMC1*/
+-		pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
+-		pinfo = &mpc885_uart_pdata[0];
+-	}
+-
+-	pinfo->uart_clk = bd->bi_intfreq;
+-	pdev->dev.platform_data = pinfo;
+-	ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+-	return NULL;
+-}
+-
+diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c
+index bb8d4a4..053b54a 100644
+--- a/arch/ppc/platforms/mvme5100.c
++++ b/arch/ppc/platforms/mvme5100.c
+@@ -17,7 +17,6 @@
+ #include <linux/initrd.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/kdev_t.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c
+index 4d46650..162dc85 100644
+--- a/arch/ppc/platforms/powerpmc250.c
++++ b/arch/ppc/platforms/powerpmc250.c
+@@ -25,7 +25,6 @@
+ #include <linux/delay.h>
+ #include <linux/slab.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/root_dev.h>
+ 
+ #include <asm/byteorder.h>
+diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
+index 8a1788c..cbcac85 100644
+--- a/arch/ppc/platforms/pplus.c
++++ b/arch/ppc/platforms/pplus.c
+@@ -19,7 +19,6 @@
+ #include <linux/ioport.h>
+ #include <linux/console.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+ 
+@@ -668,57 +667,6 @@ static void __init pplus_init_IRQ(void)
+ 		ppc_md.progress("init_irq: exit", 0);
+ }
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-/*
+- * IDE stuff.
+- */
+-static int pplus_ide_default_irq(unsigned long base)
+-{
+-	switch (base) {
+-	case 0x1f0:
+-		return 14;
+-	case 0x170:
+-		return 15;
+-	default:
+-		return 0;
+-	}
+-}
+-
+-static unsigned long pplus_ide_default_io_base(int index)
+-{
+-	switch (index) {
+-	case 0:
+-		return 0x1f0;
+-	case 1:
+-		return 0x170;
+-	default:
+-		return 0;
+-	}
+-}
+-
+-static void __init
+-pplus_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+-			  unsigned long ctrl_port, int *irq)
+-{
+-	unsigned long reg = data_port;
+-	int i;
+-
+-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+-		hw->io_ports[i] = reg;
+-		reg += 1;
+-	}
+-
+-	if (ctrl_port)
+-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+-	else
+-		hw->io_ports[IDE_CONTROL_OFFSET] =
+-		    hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+-
+-	if (irq != NULL)
+-		*irq = pplus_ide_default_irq(data_port);
+-}
+-#endif
+-
+ #ifdef CONFIG_SMP
+ /* PowerPlus (MTX) support */
+ static int __init smp_pplus_probe(void)
+@@ -884,12 +832,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ 	ppc_md.find_end_of_memory = pplus_find_end_of_memory;
+ 	ppc_md.setup_io_mappings = pplus_map_io;
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-	ppc_ide_md.default_irq = pplus_ide_default_irq;
+-	ppc_ide_md.default_io_base = pplus_ide_default_io_base;
+-	ppc_ide_md.ide_init_hwif = pplus_ide_init_hwif_ports;
+-#endif
+-
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ 	ppc_md.progress = gen550_progress;
+ #endif				/* CONFIG_SERIAL_TEXT_DEBUG */
+diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
+deleted file mode 100644
+index 7fc2e02..0000000
+--- a/arch/ppc/platforms/pq2ads.c
++++ /dev/null
+@@ -1,53 +0,0 @@
+-/*
+- * PQ2ADS platform support
+- *
+- * Author: Kumar Gala <galak at kernel.crashing.org>
+- * Derived from: est8260_setup.c by Allen Curtis
+- *
+- * Copyright 2004 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/init.h>
+-
+-#include <asm/io.h>
+-#include <asm/mpc8260.h>
+-#include <asm/cpm2.h>
+-#include <asm/immap_cpm2.h>
+-
+-void __init
+-m82xx_board_setup(void)
+-{
+-	cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+-	u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
+-
+-	/* Enable the 2nd UART port */
+-	clrbits32(bcsr, BCSR1_RS232_EN2);
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC1
+-	clrbits32((u32*)&immap->im_scc[0].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+-	clrbits32((u32*)&immap->im_scc[0].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC2
+-	clrbits32((u32*)&immap->im_scc[1].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+-	clrbits32((u32*)&immap->im_scc[1].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC3
+-	clrbits32((u32*)&immap->im_scc[2].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+-	clrbits32((u32*)&immap->im_scc[2].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC4
+-	clrbits32((u32*)&immap->im_scc[3].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+-	clrbits32((u32*)&immap->im_scc[3].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+-#endif
+-
+-	iounmap(bcsr);
+-	iounmap(immap);
+-}
+diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
+deleted file mode 100644
+index 2b287f4..0000000
+--- a/arch/ppc/platforms/pq2ads.h
++++ /dev/null
+@@ -1,94 +0,0 @@
+-/*
+- * A collection of structures, addresses, and values associated with
+- * the Motorola MPC8260ADS/MPC8266ADS-PCI boards.
+- * Copied from the RPX-Classic and SBS8260 stuff.
+- *
+- * Copyright (c) 2001 Dan Malek (dan at mvista.com)
+- */
+-#ifdef __KERNEL__
+-#ifndef __MACH_ADS8260_DEFS
+-#define __MACH_ADS8260_DEFS
+-
+-
+-#include <asm/ppcboot.h>
+-
+-#if defined(CONFIG_ADS8272)
+-#define BOARD_CHIP_NAME "8272"
+-#endif
+-
+-/* Memory map is configured by the PROM startup.
+- * We just map a few things we need.  The CSR is actually 4 byte-wide
+- * registers that can be accessed as 8-, 16-, or 32-bit values.
+- */
+-#define CPM_MAP_ADDR		((uint)0xf0000000)
+-#define BCSR_ADDR		((uint)0xf4500000)
+-#define BCSR_SIZE		((uint)(32 * 1024))
+-
+-#define BOOTROM_RESTART_ADDR	((uint)0xff000104)
+-
+-/* For our show_cpuinfo hooks. */
+-#define CPUINFO_VENDOR		"Motorola"
+-#define CPUINFO_MACHINE		"PQ2 ADS PowerPC"
+-
+-/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
+- * only on word boundaries.
+- * Not all are used (yet), or are interesting to us (yet).
+- */
+-
+-/* Things of interest in the CSR.
+-*/
+-#define BCSR0_LED0		((uint)0x02000000)	/* 0 == on */
+-#define BCSR0_LED1		((uint)0x01000000)	/* 0 == on */
+-#define BCSR1_FETHIEN		((uint)0x08000000)	/* 0 == enable */
+-#define BCSR1_FETH_RST		((uint)0x04000000)	/* 0 == reset */
+-#define BCSR1_RS232_EN1		((uint)0x02000000)	/* 0 == enable */
+-#define BCSR1_RS232_EN2		((uint)0x01000000)	/* 0 == enable */
+-#define BCSR3_FETHIEN2		((uint)0x10000000)	/* 0 == enable */
+-#define BCSR3_FETH2_RST 	((uint)0x80000000)	/* 0 == reset */
+-
+-#define PHY_INTERRUPT	SIU_INT_IRQ7
+-
+-#ifdef CONFIG_PCI
+-/* PCI interrupt controller */
+-#define PCI_INT_STAT_REG	0xF8200000
+-#define PCI_INT_MASK_REG	0xF8200004
+-#define PIRQA			(NR_CPM_INTS + 0)
+-#define PIRQB			(NR_CPM_INTS + 1)
+-#define PIRQC			(NR_CPM_INTS + 2)
+-#define PIRQD			(NR_CPM_INTS + 3)
+-
+-/*
+- * PCI memory map definitions for MPC8266ADS-PCI.
+- *
+- * processor view
+- *	local address		PCI address		target
+- *	0x80000000-0x9FFFFFFF	0x80000000-0x9FFFFFFF	PCI mem with prefetch
+- *	0xA0000000-0xBFFFFFFF	0xA0000000-0xBFFFFFFF	PCI mem w/o prefetch
+- *	0xF4000000-0xF7FFFFFF	0x00000000-0x03FFFFFF	PCI IO
+- *
+- * PCI master view
+- *	local address		PCI address		target
+- *	0x00000000-0x1FFFFFFF	0x00000000-0x1FFFFFFF	MPC8266 local memory
+- */
+-
+-/* All the other PCI memory map definitions reside at syslib/m82xx_pci.h
+-   Here we should redefine what is unique for this board */
+-#define M82xx_PCI_SLAVE_MEM_LOCAL	0x00000000	/* Local base */
+-#define M82xx_PCI_SLAVE_MEM_BUS		0x00000000	/* PCI base */
+-#define M82xx_PCI_SLAVE_MEM_SIZE	0x10000000	/* 256 Mb */
+-
+-#define M82xx_PCI_SLAVE_SEC_WND_SIZE	~(0x40000000 - 1U)	/* 2 x 512Mb  */
+-#define M82xx_PCI_SLAVE_SEC_WND_BASE	0x80000000		/* PCI Memory base */
+-
+-#if defined(CONFIG_ADS8272)
+-#define PCI_INT_TO_SIU 	SIU_INT_IRQ2
+-#elif defined(CONFIG_PQ2FADS)
+-#define PCI_INT_TO_SIU 	SIU_INT_IRQ6
+-#else
+-#warning PCI Bridge will be without interrupts support
+-#endif
+-
+-#endif /* CONFIG_PCI */
+-
+-#endif /* __MACH_ADS8260_DEFS */
+-#endif /* __KERNEL__ */
+diff --git a/arch/ppc/platforms/pq2ads_pd.h b/arch/ppc/platforms/pq2ads_pd.h
+deleted file mode 100644
+index 672483d..0000000
+--- a/arch/ppc/platforms/pq2ads_pd.h
++++ /dev/null
+@@ -1,32 +0,0 @@
+-#ifndef __PQ2ADS_PD_H
+-#define __PQ2ADS_PD_H
+-/*
+- * arch/ppc/platforms/82xx/pq2ads_pd.h
+- *
+- * Some defines for MPC82xx board-specific PlatformDevice descriptions
+- *
+- * 2005 (c) MontaVista Software, Inc.
+- * Vitaly Bordug <vbordug at ru.mvista.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.
+- */
+-
+-/* FCC1 Clock Source Configuration.  These can be redefined in the board specific file.
+-   Can only choose from CLK9-12 */
+-
+-#define F1_RXCLK	11
+-#define F1_TXCLK	10
+-
+-/* FCC2 Clock Source Configuration.  These can be redefined in the board specific file.
+-   Can only choose from CLK13-16 */
+-#define F2_RXCLK	15
+-#define F2_TXCLK	16
+-
+-/* FCC3 Clock Source Configuration.  These can be redefined in the board specific file.
+-   Can only choose from CLK13-16 */
+-#define F3_RXCLK	13
+-#define F3_TXCLK	14
+-
+-#endif
+diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
+index 3844985..465b658 100644
+--- a/arch/ppc/platforms/prep_setup.c
++++ b/arch/ppc/platforms/prep_setup.c
+@@ -33,7 +33,6 @@
+ #include <linux/console.h>
+ #include <linux/timex.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+ 
+@@ -894,38 +893,6 @@ prep_init_IRQ(void)
+ 		i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR, 0);
+ }
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-/*
+- * IDE stuff.
+- */
+-static int
+-prep_ide_default_irq(unsigned long base)
+-{
+-	switch (base) {
+-		case 0x1f0: return 13;
+-		case 0x170: return 13;
+-		case 0x1e8: return 11;
+-		case 0x168: return 10;
+-		case 0xfff0: return 14;		/* MCP(N)750 ide0 */
+-		case 0xffe0: return 15;		/* MCP(N)750 ide1 */
+-		default: return 0;
+-	}
+-}
+-
+-static unsigned long
+-prep_ide_default_io_base(int index)
+-{
+-	switch (index) {
+-		case 0: return 0x1f0;
+-		case 1: return 0x170;
+-		case 2: return 0x1e8;
+-		case 3: return 0x168;
+-		default:
+-			return 0;
+-	}
+-}
+-#endif
+-
+ #ifdef CONFIG_SMP
+ /* PReP (MTX) support */
+ static int __init
+@@ -1070,11 +1037,6 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ 
+ 	ppc_md.setup_io_mappings = prep_map_io;
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-	ppc_ide_md.default_irq = prep_ide_default_irq;
+-	ppc_ide_md.default_io_base = prep_ide_default_io_base;
+-#endif
+-
+ #ifdef CONFIG_SMP
+ 	smp_ops			 = &prep_smp_ops;
+ #endif /* CONFIG_SMP */
+diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c
+index fcab513..93bd593 100644
+--- a/arch/ppc/platforms/prpmc750.c
++++ b/arch/ppc/platforms/prpmc750.c
+@@ -22,7 +22,6 @@
+ #include <linux/console.h>
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/root_dev.h>
+ #include <linux/slab.h>
+ #include <linux/serial_reg.h>
+diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c
+index f4ade5c..5bcda7f 100644
+--- a/arch/ppc/platforms/prpmc800.c
++++ b/arch/ppc/platforms/prpmc800.c
+@@ -20,7 +20,6 @@
+ #include <linux/console.h>
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/root_dev.h>
+ #include <linux/harrier_defs.h>
+ 
+diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
+index 44d4398..f1dee1e 100644
+--- a/arch/ppc/platforms/radstone_ppc7d.c
++++ b/arch/ppc/platforms/radstone_ppc7d.c
+@@ -29,7 +29,6 @@
+ #include <linux/initrd.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+ #include <linux/serial.h>
+@@ -512,7 +511,7 @@ static void __init ppc7d_init_irq(void)
+ {
+ 	int irq;
+ 
+-	pr_debug("%s\n", __FUNCTION__);
++	pr_debug("%s\n", __func__);
+ 	i8259_init(0, 0);
+ 	mv64360_init_irq();
+ 
+@@ -569,7 +568,7 @@ static int __init ppc7d_map_irq(struct pci_dev *dev, unsigned char idsel,
+ 	};
+ 	const long min_idsel = 10, max_idsel = 14, irqs_per_slot = 4;
+ 
+-	pr_debug("%s: %04x/%04x/%x: idsel=%hx pin=%hu\n", __FUNCTION__,
++	pr_debug("%s: %04x/%04x/%x: idsel=%hx pin=%hu\n", __func__,
+ 		 dev->vendor, dev->device, PCI_FUNC(dev->devfn), idsel, pin);
+ 
+ 	return PCI_IRQ_TABLE_LOOKUP;
+@@ -1300,7 +1299,7 @@ static void ppc7d_init2(void)
+ 	u32 data;
+ 	u8 data8;
+ 
+-	pr_debug("%s: enter\n", __FUNCTION__);
++	pr_debug("%s: enter\n", __func__);
+ 
+ 	/* Wait for debugger? */
+ 	if (ppc7d_wait_debugger) {
+@@ -1333,7 +1332,7 @@ static void ppc7d_init2(void)
+         ppc_md.set_rtc_time = ppc7d_set_rtc_time;
+         ppc_md.get_rtc_time = ppc7d_get_rtc_time;
+ 
+-	pr_debug("%s: exit\n", __FUNCTION__);
++	pr_debug("%s: exit\n", __func__);
+ }
+ 
+ /* Called from machine_init(), early, before any of the __init functions
+diff --git a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c
+index c991160..18495e7 100644
+--- a/arch/ppc/platforms/residual.c
++++ b/arch/ppc/platforms/residual.c
+@@ -38,7 +38,6 @@
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ 
+ #include <asm/sections.h>
+ #include <asm/mmu.h>
+diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
+index 3352fae..b4897bd 100644
+--- a/arch/ppc/platforms/sandpoint.c
++++ b/arch/ppc/platforms/sandpoint.c
+@@ -71,7 +71,6 @@
+ #include <linux/initrd.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+ #include <linux/serial.h>
+@@ -559,93 +558,6 @@ sandpoint_show_cpuinfo(struct seq_file *m)
+ 	return 0;
+ }
+ 
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-/*
+- * IDE support.
+- */
+-static int		sandpoint_ide_ports_known = 0;
+-static unsigned long	sandpoint_ide_regbase[MAX_HWIFS];
+-static unsigned long	sandpoint_ide_ctl_regbase[MAX_HWIFS];
+-static unsigned long	sandpoint_idedma_regbase;
+-
+-static void
+-sandpoint_ide_probe(void)
+-{
+-	struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+-			PCI_DEVICE_ID_WINBOND_82C105, NULL);
+-
+-	if (pdev) {
+-		sandpoint_ide_regbase[0]=pdev->resource[0].start;
+-		sandpoint_ide_regbase[1]=pdev->resource[2].start;
+-		sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start;
+-		sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start;
+-		sandpoint_idedma_regbase=pdev->resource[4].start;
+-		pci_dev_put(pdev);
+-	}
+-
+-	sandpoint_ide_ports_known = 1;
+-}
+-
+-static int
+-sandpoint_ide_default_irq(unsigned long base)
+-{
+-	if (sandpoint_ide_ports_known == 0)
+-		sandpoint_ide_probe();
+-
+-	if (base == sandpoint_ide_regbase[0])
+-		return SANDPOINT_IDE_INT0;
+-	else if (base == sandpoint_ide_regbase[1])
+-		return SANDPOINT_IDE_INT1;
+-	else
+-		return 0;
+-}
+-
+-static unsigned long
+-sandpoint_ide_default_io_base(int index)
+-{
+-	if (sandpoint_ide_ports_known == 0)
+-		sandpoint_ide_probe();
+-
+-	return sandpoint_ide_regbase[index];
+-}
+-
+-static void __init
+-sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+-		unsigned long ctrl_port, int *irq)
+-{
+-	unsigned long reg = data_port;
+-	uint	alt_status_base;
+-	int	i;
+-
+-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+-		hw->io_ports[i] = reg++;
+-	}
+-
+-	if (data_port == sandpoint_ide_regbase[0]) {
+-		alt_status_base = sandpoint_ide_ctl_regbase[0] + 2;
+-		hw->irq = 14;
+-	}
+-	else if (data_port == sandpoint_ide_regbase[1]) {
+-		alt_status_base = sandpoint_ide_ctl_regbase[1] + 2;
+-		hw->irq = 15;
+-	}
+-	else {
+-		alt_status_base = 0;
+-		hw->irq = 0;
+-	}
+-
+-	if (ctrl_port) {
+-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+-	} else {
+-		hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+-	}
+-
+-	if (irq != NULL) {
+-		*irq = hw->irq;
+-	}
+-}
+-#endif
+-
+ /*
+  * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+  */
+@@ -736,10 +648,4 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ 	ppc_md.progress = gen550_progress;
+ #endif
+-
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-	ppc_ide_md.default_irq = sandpoint_ide_default_irq;
+-	ppc_ide_md.default_io_base = sandpoint_ide_default_io_base;
+-	ppc_ide_md.ide_init_hwif = sandpoint_ide_init_hwif_ports;
+-#endif
+ }
+diff --git a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h
+index 3b64e64..ed83759 100644
+--- a/arch/ppc/platforms/sandpoint.h
++++ b/arch/ppc/platforms/sandpoint.h
+@@ -28,9 +28,6 @@
+  */
+ #define SANDPOINT_IDE_INT0		23	/* EPIC 7 */
+ #define SANDPOINT_IDE_INT1		24	/* EPIC 8 */
+-#else
+-#define SANDPOINT_IDE_INT0		14	/* 8259 Test */
+-#define SANDPOINT_IDE_INT1		15	/* 8259 Test */
+ #endif
+ 
+ /*
+diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c
+index cc0935c..0df6aac 100644
+--- a/arch/ppc/platforms/sbc82xx.c
++++ b/arch/ppc/platforms/sbc82xx.c
+@@ -121,8 +121,10 @@ struct hw_interrupt_type sbc82xx_i8259_ic = {
+ 	.end = sbc82xx_i8259_end_irq,
+ };
+ 
+-static irqreturn_t sbc82xx_i8259_demux(int irq, void *dev_id)
++static irqreturn_t sbc82xx_i8259_demux(int dummy, void *dev_id)
+ {
++	int irq;
++
+ 	spin_lock(&sbc82xx_i8259_lock);
+ 
+ 	sbc82xx_i8259_map[0] = 0x0c;	/* OCW3: Read IR register on RD# pulse */
+diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c
+index f4de50b..a344134 100644
+--- a/arch/ppc/platforms/spruce.c
++++ b/arch/ppc/platforms/spruce.c
+@@ -22,7 +22,6 @@
+ #include <linux/console.h>
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/root_dev.h>
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
+index 46588fa..b405837 100644
+--- a/arch/ppc/syslib/m8260_setup.c
++++ b/arch/ppc/syslib/m8260_setup.c
+@@ -175,12 +175,6 @@ m8260_init_IRQ(void)
+ 	 * in case the boot rom changed something on us.
+ 	 */
+ 	cpm2_immr->im_intctl.ic_siprr = 0x05309770;
+-
+-#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS))
+- 	/* Initialize stuff for the 82xx CPLD IC and install demux  */
+- 	pq2pci_init_irq();
+-#endif
+-
+ }
+ 
+ /*
+diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c
+index fe860d5..657a1c2 100644
+--- a/arch/ppc/syslib/m82xx_pci.c
++++ b/arch/ppc/syslib/m82xx_pci.c
+@@ -150,14 +150,6 @@ pq2pci_init_irq(void)
+ {
+ 	int irq;
+ 	volatile cpm2_map_t *immap = cpm2_immr;
+-#if defined CONFIG_ADS8272
+-	/* configure chip select for PCI interrupt controller */
+-	immap->im_memctl.memc_br3 = PCI_INT_STAT_REG | 0x00001801;
+-	immap->im_memctl.memc_or3 = 0xffff8010;
+-#elif defined CONFIG_PQ2FADS
+-	immap->im_memctl.memc_br8 = PCI_INT_STAT_REG | 0x00001801;
+-	immap->im_memctl.memc_or8 = 0xffff8010;
+-#endif
+ 	for (irq = NR_CPM_INTS; irq < NR_CPM_INTS + 4; irq++)
+ 		irq_desc[irq].chip = &pq2pci_ic;
+ 
+@@ -222,26 +214,6 @@ pq2ads_setup_pci(struct pci_controller *hose)
+ 	immap->im_memctl.memc_pcibr1  = M82xx_PCI_SEC_WND_BASE | PCIBR_ENABLE;
+ #endif
+ 
+-#if defined CONFIG_ADS8272
+-	immap->im_siu_conf.siu_82xx.sc_siumcr =
+-		(immap->im_siu_conf.siu_82xx.sc_siumcr &
+-		~(SIUMCR_BBD | SIUMCR_ESE | SIUMCR_PBSE |
+-		SIUMCR_CDIS | SIUMCR_DPPC11 | SIUMCR_L2CPC11 |
+-		SIUMCR_LBPC11 | SIUMCR_APPC11 |
+-		SIUMCR_CS10PC11 | SIUMCR_BCTLC11 | SIUMCR_MMR11)) |
+-		SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00 |
+-		SIUMCR_APPC10 | SIUMCR_CS10PC00 |
+-		SIUMCR_BCTLC00 | SIUMCR_MMR11 ;
+-
+-#elif defined CONFIG_PQ2FADS
+-	/*
+-	 * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
+-	 * and local bus for PCI (SIUMCR [LBPC]).
+-	 */
+-	immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.siu_82xx.sc_siumcr &
+-				~(SIUMCR_L2CPC11 | SIUMCR_LBPC11 | SIUMCR_CS10PC11 | SIUMCR_APPC11) |
+-				SIUMCR_BBD | SIUMCR_LBPC01 | SIUMCR_DPPC11 | SIUMCR_APPC10);
+-#endif
+ 	/* Enable PCI  */
+ 	immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
+ 
+@@ -284,12 +256,6 @@ pq2ads_setup_pci(struct pci_controller *hose)
+ 	immap->im_pci.pci_pibar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_BUS  >> PITA_ADDR_SHIFT);
+ 	immap->im_pci.pci_pitar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_LOCAL>> PITA_ADDR_SHIFT);
+ 
+-#if defined CONFIG_ADS8272
+-	/* PCI int highest prio */
+-	immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x01236745;
+-#elif defined CONFIG_PQ2FADS
+-	immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
+-#endif
+ 	/* park bus on PCI */
+ 	immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
+ 
+@@ -320,10 +286,6 @@ void __init pq2_find_bridges(void)
+ 	hose->bus_offset = 0;
+ 	hose->last_busno = 0xff;
+ 
+-#ifdef CONFIG_ADS8272
+-	hose->set_cfg_type = 1;
+-#endif
+-
+ 	setup_m8260_indirect_pci(hose,
+ 				 (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
+ 				 (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
+diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
+index 9caf850..18da720 100644
+--- a/arch/ppc/syslib/m8xx_setup.c
++++ b/arch/ppc/syslib/m8xx_setup.c
+@@ -87,8 +87,6 @@ void m8xx_calibrate_decr(void);
+ 
+ unsigned char __res[sizeof(bd_t)];
+ 
+-extern void m8xx_ide_init(void);
+-
+ extern unsigned long find_available_memory(void);
+ extern void m8xx_cpm_reset(void);
+ extern void m8xx_wdt_handler_install(bd_t *bp);
+@@ -143,16 +141,6 @@ m8xx_setup_arch(void)
+ #endif
+ #endif
+ 
+-#if defined (CONFIG_MPC86XADS) || defined (CONFIG_MPC885ADS)
+-#if defined(CONFIG_MTD_PHYSMAP)
+-       physmap_configure(binfo->bi_flashstart, binfo->bi_flashsize,
+-                                               MPC8xxADS_BANK_WIDTH, NULL);
+-#ifdef CONFIG_MTD_PARTITIONS
+-       physmap_set_partitions(mpc8xxads_partitions, mpc8xxads_part_num);
+-#endif /* CONFIG_MTD_PARTITIONS */
+-#endif /* CONFIG_MTD_PHYSMAP */
+-#endif
+-
+ 	board_init();
+ }
+ 
+@@ -474,8 +462,4 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ 
+ 	ppc_md.find_end_of_memory	= m8xx_find_end_of_memory;
+ 	ppc_md.setup_io_mappings	= m8xx_map_io;
+-
+-#if defined(CONFIG_BLK_DEV_MPC8xx_IDE)
+-	m8xx_ide_init();
+-#endif
+ }
+diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
+index 9f504fc..ab0cf4c 100644
+--- a/arch/ppc/syslib/mpc52xx_setup.c
++++ b/arch/ppc/syslib/mpc52xx_setup.c
+@@ -279,7 +279,7 @@ int mpc52xx_match_psc_function(int psc_idx, const char *func)
+ 
+ int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv)
+ {
+-	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
++	static DEFINE_SPINLOCK(lock);
+ 	struct mpc52xx_cdm __iomem *cdm;
+ 	unsigned long flags;
+ 	u16 mclken_div;
+diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
+index ac80370..a6fb7dc 100644
+--- a/arch/ppc/syslib/ocp.c
++++ b/arch/ppc/syslib/ocp.c
+@@ -49,7 +49,6 @@
+ #include <asm/io.h>
+ #include <asm/ocp.h>
+ #include <asm/errno.h>
+-#include <asm/semaphore.h>
+ 
+ //#define DBG(x)	printk x
+ #define DBG(x)
+diff --git a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c
+index debe14c..353d746 100644
+--- a/arch/ppc/syslib/ppc4xx_setup.c
++++ b/arch/ppc/syslib/ppc4xx_setup.c
+@@ -24,7 +24,6 @@
+ #include <linux/pci.h>
+ #include <linux/rtc.h>
+ #include <linux/console.h>
+-#include <linux/ide.h>
+ #include <linux/serial_reg.h>
+ #include <linux/seq_file.h>
+ 
+@@ -189,24 +188,6 @@ ppc4xx_calibrate_decr(void)
+ 	mtspr(SPRN_PIT, tb_ticks_per_jiffy);
+ }
+ 
+-/*
+- * IDE stuff.
+- * should be generic for every IDE PCI chipset
+- */
+-#if defined(CONFIG_PCI) && defined(CONFIG_IDE)
+-static void
+-ppc4xx_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+-			   unsigned long ctrl_port, int *irq)
+-{
+-	int i;
+-
+-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
+-		hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
+-
+-	hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+-}
+-#endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */
+-
+ TODC_ALLOC();
+ 
+ /*
+@@ -271,10 +252,6 @@ ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ 	ppc_md.progress = gen550_progress;
+ #endif
+-
+-#if defined(CONFIG_PCI) && defined(CONFIG_IDE)
+-	ppc_ide_md.ide_init_hwif = ppc4xx_ide_init_hwif_ports;
+-#endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */
+ }
+ 
+ /* Called from machine_check_exception */
+diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
+index 1831833..f6a68e1 100644
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -3,6 +3,10 @@
+ # see Documentation/kbuild/kconfig-language.txt.
+ #
+ 
++config SCHED_MC
++	def_bool y
++	depends on SMP
++
+ config MMU
+ 	def_bool y
+ 
+@@ -39,6 +43,9 @@ config GENERIC_HWEIGHT
+ config GENERIC_TIME
+ 	def_bool y
+ 
++config GENERIC_CLOCKEVENTS
++	def_bool y
++
+ config GENERIC_BUG
+ 	bool
+ 	depends on BUG
+@@ -69,6 +76,8 @@ menu "Base setup"
+ 
+ comment "Processor type and features"
+ 
++source "kernel/time/Kconfig"
++
+ config 64BIT
+ 	bool "64 bit kernel"
+ 	help
+@@ -301,10 +310,7 @@ config QDIO
+ 	tristate "QDIO support"
+ 	---help---
+ 	  This driver provides the Queued Direct I/O base support for
+-	  IBM mainframes.
+-
+-	  For details please refer to the documentation provided by IBM at
+-	  <http://www10.software.ibm.com/developerworks/opensource/linux390>
++	  IBM System z.
+ 
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called qdio.
+@@ -486,25 +492,6 @@ config APPLDATA_NET_SUM
+ 
+ source kernel/Kconfig.hz
+ 
+-config NO_IDLE_HZ
+-	bool "No HZ timer ticks in idle"
+-	help
+-	  Switches the regular HZ timer off when the system is going idle.
+-	  This helps z/VM to detect that the Linux system is idle. VM can
+-	  then "swap-out" this guest which reduces memory usage. It also
+-	  reduces the overhead of idle systems.
+-
+-	  The HZ timer can be switched on/off via /proc/sys/kernel/hz_timer.
+-	  hz_timer=0 means HZ timer is disabled. hz_timer=1 means HZ
+-	  timer is active.
+-
+-config NO_IDLE_HZ_INIT
+-	bool "HZ timer in idle off by default"
+-	depends on NO_IDLE_HZ
+-	help
+-	  The HZ timer is switched off in idle by default. That means the
+-	  HZ timer is already disabled at boot time.
+-
+ config S390_HYPFS_FS
+ 	bool "s390 hypervisor file system support"
+ 	select SYS_HYPERVISOR
+diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
+index 14e552c..6a1157f 100644
+--- a/arch/s390/crypto/Makefile
++++ b/arch/s390/crypto/Makefile
+@@ -2,8 +2,9 @@
+ # Cryptographic API
+ #
+ 
+-obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o
+-obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o
++obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o sha_common.o
++obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o sha_common.o
++obj-$(CONFIG_CRYPTO_SHA512_S390) += sha512_s390.o sha_common.o
+ obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o
+ obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
+ obj-$(CONFIG_S390_PRNG) += prng.o
+diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
+index a3f67f8..e33f32b 100644
+--- a/arch/s390/crypto/aes_s390.c
++++ b/arch/s390/crypto/aes_s390.c
+@@ -499,7 +499,7 @@ static struct crypto_alg cbc_aes_alg = {
+ 	}
+ };
+ 
+-static int __init aes_init(void)
++static int __init aes_s390_init(void)
+ {
+ 	int ret;
+ 
+@@ -542,15 +542,15 @@ aes_err:
+ 	goto out;
+ }
+ 
+-static void __exit aes_fini(void)
++static void __exit aes_s390_fini(void)
+ {
+ 	crypto_unregister_alg(&cbc_aes_alg);
+ 	crypto_unregister_alg(&ecb_aes_alg);
+ 	crypto_unregister_alg(&aes_alg);
+ }
+ 
+-module_init(aes_init);
+-module_exit(aes_fini);
++module_init(aes_s390_init);
++module_exit(aes_s390_fini);
+ 
+ MODULE_ALIAS("aes");
+ 
+diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
+index 95f5160..9992f95 100644
+--- a/arch/s390/crypto/crypt_s390.h
++++ b/arch/s390/crypto/crypt_s390.h
+@@ -82,6 +82,7 @@ enum crypt_s390_kimd_func {
+ 	KIMD_QUERY   = CRYPT_S390_KIMD | 0,
+ 	KIMD_SHA_1   = CRYPT_S390_KIMD | 1,
+ 	KIMD_SHA_256 = CRYPT_S390_KIMD | 2,
++	KIMD_SHA_512 = CRYPT_S390_KIMD | 3,
+ };
+ 
+ /*
+@@ -92,6 +93,7 @@ enum crypt_s390_klmd_func {
+ 	KLMD_QUERY   = CRYPT_S390_KLMD | 0,
+ 	KLMD_SHA_1   = CRYPT_S390_KLMD | 1,
+ 	KLMD_SHA_256 = CRYPT_S390_KLMD | 2,
++	KLMD_SHA_512 = CRYPT_S390_KLMD | 3,
+ };
+ 
+ /*
+diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
+index ea22707..4aba83b 100644
+--- a/arch/s390/crypto/des_s390.c
++++ b/arch/s390/crypto/des_s390.c
+@@ -550,7 +550,7 @@ static struct crypto_alg cbc_des3_192_alg = {
+ 	}
+ };
+ 
+-static int init(void)
++static int des_s390_init(void)
+ {
+ 	int ret = 0;
+ 
+@@ -612,7 +612,7 @@ des_err:
+ 	goto out;
+ }
+ 
+-static void __exit fini(void)
++static void __exit des_s390_fini(void)
+ {
+ 	crypto_unregister_alg(&cbc_des3_192_alg);
+ 	crypto_unregister_alg(&ecb_des3_192_alg);
+@@ -625,8 +625,8 @@ static void __exit fini(void)
+ 	crypto_unregister_alg(&des_alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(des_s390_init);
++module_exit(des_s390_fini);
+ 
+ MODULE_ALIAS("des");
+ MODULE_ALIAS("des3_ede");
+diff --git a/arch/s390/crypto/sha.h b/arch/s390/crypto/sha.h
+new file mode 100644
+index 0000000..1ceafa5
+--- /dev/null
++++ b/arch/s390/crypto/sha.h
+@@ -0,0 +1,35 @@
++/*
++ * Cryptographic API.
++ *
++ * s390 generic implementation of the SHA Secure Hash Algorithms.
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Jan Glauber (jang at de.ibm.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ */
++#ifndef _CRYPTO_ARCH_S390_SHA_H
++#define _CRYPTO_ARCH_S390_SHA_H
++
++#include <linux/crypto.h>
++#include <crypto/sha.h>
++
++/* must be big enough for the largest SHA variant */
++#define SHA_MAX_STATE_SIZE	16
++#define SHA_MAX_BLOCK_SIZE      SHA512_BLOCK_SIZE
++
++struct s390_sha_ctx {
++	u64 count;              /* message length in bytes */
++	u32 state[SHA_MAX_STATE_SIZE];
++	u8 buf[2 * SHA_MAX_BLOCK_SIZE];
++	int func;		/* KIMD function to use */
++};
++
++void s390_sha_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len);
++void s390_sha_final(struct crypto_tfm *tfm, u8 *out);
++
++#endif
+diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c
+index 5a834f6..b3cb5a8 100644
+--- a/arch/s390/crypto/sha1_s390.c
++++ b/arch/s390/crypto/sha1_s390.c
+@@ -29,16 +29,11 @@
+ #include <crypto/sha.h>
+ 
+ #include "crypt_s390.h"
+-
+-struct s390_sha1_ctx {
+-	u64 count;		/* message length */
+-	u32 state[5];
+-	u8 buf[2 * SHA1_BLOCK_SIZE];
+-};
++#include "sha.h"
+ 
+ static void sha1_init(struct crypto_tfm *tfm)
+ {
+-	struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
++	struct s390_sha_ctx *sctx = crypto_tfm_ctx(tfm);
+ 
+ 	sctx->state[0] = SHA1_H0;
+ 	sctx->state[1] = SHA1_H1;
+@@ -46,79 +41,7 @@ static void sha1_init(struct crypto_tfm *tfm)
+ 	sctx->state[3] = SHA1_H3;
+ 	sctx->state[4] = SHA1_H4;
+ 	sctx->count = 0;
+-}
+-
+-static void sha1_update(struct crypto_tfm *tfm, const u8 *data,
+-			unsigned int len)
+-{
+-	struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
+-	unsigned int index;
+-	int ret;
+-
+-	/* how much is already in the buffer? */
+-	index = sctx->count & 0x3f;
+-
+-	sctx->count += len;
+-
+-	if (index + len < SHA1_BLOCK_SIZE)
+-		goto store;
+-
+-	/* process one stored block */
+-	if (index) {
+-		memcpy(sctx->buf + index, data, SHA1_BLOCK_SIZE - index);
+-		ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf,
+-				      SHA1_BLOCK_SIZE);
+-		BUG_ON(ret != SHA1_BLOCK_SIZE);
+-		data += SHA1_BLOCK_SIZE - index;
+-		len -= SHA1_BLOCK_SIZE - index;
+-	}
+-
+-	/* process as many blocks as possible */
+-	if (len >= SHA1_BLOCK_SIZE) {
+-		ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, data,
+-				      len & ~(SHA1_BLOCK_SIZE - 1));
+-		BUG_ON(ret != (len & ~(SHA1_BLOCK_SIZE - 1)));
+-		data += ret;
+-		len -= ret;
+-	}
+-
+-store:
+-	/* anything left? */
+-	if (len)
+-		memcpy(sctx->buf + index , data, len);
+-}
+-
+-/* Add padding and return the message digest. */
+-static void sha1_final(struct crypto_tfm *tfm, u8 *out)
+-{
+-	struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
+-	u64 bits;
+-	unsigned int index, end;
+-	int ret;
+-
+-	/* must perform manual padding */
+-	index = sctx->count & 0x3f;
+-	end =  (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE);
+-
+-	/* start pad with 1 */
+-	sctx->buf[index] = 0x80;
+-
+-	/* pad with zeros */
+-	index++;
+-	memset(sctx->buf + index, 0x00, end - index - 8);
+-
+-	/* append message length */
+-	bits = sctx->count * 8;
+-	memcpy(sctx->buf + end - 8, &bits, sizeof(bits));
+-
+-	ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf, end);
+-	BUG_ON(ret != end);
+-
+-	/* copy digest to out */
+-	memcpy(out, sctx->state, SHA1_DIGEST_SIZE);
+-
+-	/* wipe context */
+-	memset(sctx, 0, sizeof *sctx);
++	sctx->func = KIMD_SHA_1;
+ }
+ 
+ static struct crypto_alg alg = {
+@@ -127,33 +50,31 @@ static struct crypto_alg alg = {
+ 	.cra_priority	=	CRYPT_S390_PRIORITY,
+ 	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+ 	.cra_blocksize	=	SHA1_BLOCK_SIZE,
+-	.cra_ctxsize	=	sizeof(struct s390_sha1_ctx),
++	.cra_ctxsize	=	sizeof(struct s390_sha_ctx),
+ 	.cra_module	=	THIS_MODULE,
+ 	.cra_list	=	LIST_HEAD_INIT(alg.cra_list),
+ 	.cra_u		=	{ .digest = {
+ 	.dia_digestsize	=	SHA1_DIGEST_SIZE,
+ 	.dia_init	=	sha1_init,
+-	.dia_update	=	sha1_update,
+-	.dia_final	=	sha1_final } }
++	.dia_update	=	s390_sha_update,
++	.dia_final	=	s390_sha_final } }
+ };
+ 
+-static int __init init(void)
++static int __init sha1_s390_init(void)
+ {
+ 	if (!crypt_s390_func_available(KIMD_SHA_1))
+ 		return -EOPNOTSUPP;
+-
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit sha1_s390_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(sha1_s390_init);
++module_exit(sha1_s390_fini);
+ 
+ MODULE_ALIAS("sha1");
+-
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
+diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
+index ccf8633..19c03fb 100644
+--- a/arch/s390/crypto/sha256_s390.c
++++ b/arch/s390/crypto/sha256_s390.c
+@@ -22,16 +22,11 @@
+ #include <crypto/sha.h>
+ 
+ #include "crypt_s390.h"
+-
+-struct s390_sha256_ctx {
+-	u64 count;		/* message length */
+-	u32 state[8];
+-	u8 buf[2 * SHA256_BLOCK_SIZE];
+-};
++#include "sha.h"
+ 
+ static void sha256_init(struct crypto_tfm *tfm)
+ {
+-	struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
++	struct s390_sha_ctx *sctx = crypto_tfm_ctx(tfm);
+ 
+ 	sctx->state[0] = SHA256_H0;
+ 	sctx->state[1] = SHA256_H1;
+@@ -42,79 +37,7 @@ static void sha256_init(struct crypto_tfm *tfm)
+ 	sctx->state[6] = SHA256_H6;
+ 	sctx->state[7] = SHA256_H7;
+ 	sctx->count = 0;
+-}
+-
+-static void sha256_update(struct crypto_tfm *tfm, const u8 *data,
+-			  unsigned int len)
+-{
+-	struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
+-	unsigned int index;
+-	int ret;
+-
+-	/* how much is already in the buffer? */
+-	index = sctx->count & 0x3f;
+-
+-	sctx->count += len;
+-
+-	if ((index + len) < SHA256_BLOCK_SIZE)
+-		goto store;
+-
+-	/* process one stored block */
+-	if (index) {
+-		memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index);
+-		ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf,
+-				      SHA256_BLOCK_SIZE);
+-		BUG_ON(ret != SHA256_BLOCK_SIZE);
+-		data += SHA256_BLOCK_SIZE - index;
+-		len -= SHA256_BLOCK_SIZE - index;
+-	}
+-
+-	/* process as many blocks as possible */
+-	if (len >= SHA256_BLOCK_SIZE) {
+-		ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, data,
+-				      len & ~(SHA256_BLOCK_SIZE - 1));
+-		BUG_ON(ret != (len & ~(SHA256_BLOCK_SIZE - 1)));
+-		data += ret;
+-		len -= ret;
+-	}
+-
+-store:
+-	/* anything left? */
+-	if (len)
+-		memcpy(sctx->buf + index , data, len);
+-}
+-
+-/* Add padding and return the message digest */
+-static void sha256_final(struct crypto_tfm *tfm, u8 *out)
+-{
+-	struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
+-	u64 bits;
+-	unsigned int index, end;
+-	int ret;
+-
+-	/* must perform manual padding */
+-	index = sctx->count & 0x3f;
+-	end = (index < 56) ? SHA256_BLOCK_SIZE : (2 * SHA256_BLOCK_SIZE);
+-
+-	/* start pad with 1 */
+-	sctx->buf[index] = 0x80;
+-
+-	/* pad with zeros */
+-	index++;
+-	memset(sctx->buf + index, 0x00, end - index - 8);
+-
+-	/* append message length */
+-	bits = sctx->count * 8;
+-	memcpy(sctx->buf + end - 8, &bits, sizeof(bits));
+-
+-	ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, end);
+-	BUG_ON(ret != end);
+-
+-	/* copy digest to out */
+-	memcpy(out, sctx->state, SHA256_DIGEST_SIZE);
+-
+-	/* wipe context */
+-	memset(sctx, 0, sizeof *sctx);
++	sctx->func = KIMD_SHA_256;
+ }
+ 
+ static struct crypto_alg alg = {
+@@ -123,17 +46,17 @@ static struct crypto_alg alg = {
+ 	.cra_priority	=	CRYPT_S390_PRIORITY,
+ 	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+ 	.cra_blocksize	=	SHA256_BLOCK_SIZE,
+-	.cra_ctxsize	=	sizeof(struct s390_sha256_ctx),
++	.cra_ctxsize	=	sizeof(struct s390_sha_ctx),
+ 	.cra_module	=	THIS_MODULE,
+ 	.cra_list	=	LIST_HEAD_INIT(alg.cra_list),
+ 	.cra_u		=	{ .digest = {
+ 	.dia_digestsize	=	SHA256_DIGEST_SIZE,
+ 	.dia_init	=	sha256_init,
+-	.dia_update	=	sha256_update,
+-	.dia_final	=	sha256_final } }
++	.dia_update	=	s390_sha_update,
++	.dia_final	=	s390_sha_final } }
+ };
+ 
+-static int init(void)
++static int sha256_s390_init(void)
+ {
+ 	if (!crypt_s390_func_available(KIMD_SHA_256))
+ 		return -EOPNOTSUPP;
+@@ -141,15 +64,14 @@ static int init(void)
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit sha256_s390_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(sha256_s390_init);
++module_exit(sha256_s390_fini);
+ 
+ MODULE_ALIAS("sha256");
+-
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm");
+diff --git a/arch/s390/crypto/sha512_s390.c b/arch/s390/crypto/sha512_s390.c
+new file mode 100644
+index 0000000..23c7861
+--- /dev/null
++++ b/arch/s390/crypto/sha512_s390.c
+@@ -0,0 +1,114 @@
++/*
++ * Cryptographic API.
++ *
++ * s390 implementation of the SHA512 and SHA38 Secure Hash Algorithm.
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Jan Glauber (jang at de.ibm.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ */
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/crypto.h>
++
++#include "sha.h"
++#include "crypt_s390.h"
++
++static void sha512_init(struct crypto_tfm *tfm)
++{
++	struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	*(__u64 *)&ctx->state[0] = 0x6a09e667f3bcc908ULL;
++	*(__u64 *)&ctx->state[2] = 0xbb67ae8584caa73bULL;
++	*(__u64 *)&ctx->state[4] = 0x3c6ef372fe94f82bULL;
++	*(__u64 *)&ctx->state[6] = 0xa54ff53a5f1d36f1ULL;
++	*(__u64 *)&ctx->state[8] = 0x510e527fade682d1ULL;
++	*(__u64 *)&ctx->state[10] = 0x9b05688c2b3e6c1fULL;
++	*(__u64 *)&ctx->state[12] = 0x1f83d9abfb41bd6bULL;
++	*(__u64 *)&ctx->state[14] = 0x5be0cd19137e2179ULL;
++	ctx->count = 0;
++	ctx->func = KIMD_SHA_512;
++}
++
++static struct crypto_alg sha512_alg = {
++	.cra_name	=	"sha512",
++	.cra_driver_name =	"sha512-s390",
++	.cra_priority	=	CRYPT_S390_PRIORITY,
++	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
++	.cra_blocksize	=	SHA512_BLOCK_SIZE,
++	.cra_ctxsize	=	sizeof(struct s390_sha_ctx),
++	.cra_module	=	THIS_MODULE,
++	.cra_list	=	LIST_HEAD_INIT(sha512_alg.cra_list),
++	.cra_u		=	{ .digest = {
++	.dia_digestsize	=	SHA512_DIGEST_SIZE,
++	.dia_init	=	sha512_init,
++	.dia_update	=	s390_sha_update,
++	.dia_final	=	s390_sha_final } }
++};
++
++MODULE_ALIAS("sha512");
++
++static void sha384_init(struct crypto_tfm *tfm)
++{
++	struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	*(__u64 *)&ctx->state[0] = 0xcbbb9d5dc1059ed8ULL;
++	*(__u64 *)&ctx->state[2] = 0x629a292a367cd507ULL;
++	*(__u64 *)&ctx->state[4] = 0x9159015a3070dd17ULL;
++	*(__u64 *)&ctx->state[6] = 0x152fecd8f70e5939ULL;
++	*(__u64 *)&ctx->state[8] = 0x67332667ffc00b31ULL;
++	*(__u64 *)&ctx->state[10] = 0x8eb44a8768581511ULL;
++	*(__u64 *)&ctx->state[12] = 0xdb0c2e0d64f98fa7ULL;
++	*(__u64 *)&ctx->state[14] = 0x47b5481dbefa4fa4ULL;
++	ctx->count = 0;
++	ctx->func = KIMD_SHA_512;
++}
++
++static struct crypto_alg sha384_alg = {
++	.cra_name	=	"sha384",
++	.cra_driver_name =	"sha384-s390",
++	.cra_priority	=	CRYPT_S390_PRIORITY,
++	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
++	.cra_blocksize	=	SHA384_BLOCK_SIZE,
++	.cra_ctxsize	=	sizeof(struct s390_sha_ctx),
++	.cra_module	=	THIS_MODULE,
++	.cra_list	=	LIST_HEAD_INIT(sha384_alg.cra_list),
++	.cra_u		=	{ .digest = {
++	.dia_digestsize	=	SHA384_DIGEST_SIZE,
++	.dia_init	=	sha384_init,
++	.dia_update	=	s390_sha_update,
++	.dia_final	=	s390_sha_final } }
++};
++
++MODULE_ALIAS("sha384");
++
++static int __init init(void)
++{
++	int ret;
++
++	if (!crypt_s390_func_available(KIMD_SHA_512))
++		return -EOPNOTSUPP;
++	if ((ret = crypto_register_alg(&sha512_alg)) < 0)
++		goto out;
++	if ((ret = crypto_register_alg(&sha384_alg)) < 0)
++		crypto_unregister_alg(&sha512_alg);
++out:
++	return ret;
++}
++
++static void __exit fini(void)
++{
++	crypto_unregister_alg(&sha512_alg);
++	crypto_unregister_alg(&sha384_alg);
++}
++
++module_init(init);
++module_exit(fini);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SHA512 and SHA-384 Secure Hash Algorithm");
+diff --git a/arch/s390/crypto/sha_common.c b/arch/s390/crypto/sha_common.c
+new file mode 100644
+index 0000000..9d6eb8c
+--- /dev/null
++++ b/arch/s390/crypto/sha_common.c
+@@ -0,0 +1,97 @@
++/*
++ * Cryptographic API.
++ *
++ * s390 generic implementation of the SHA Secure Hash Algorithms.
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Jan Glauber (jang at de.ibm.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ */
++
++#include <linux/crypto.h>
++#include "sha.h"
++#include "crypt_s390.h"
++
++void s390_sha_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
++{
++	struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
++	unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
++	unsigned int index;
++	int ret;
++
++	/* how much is already in the buffer? */
++	index = ctx->count & (bsize - 1);
++	ctx->count += len;
++
++	if ((index + len) < bsize)
++		goto store;
++
++	/* process one stored block */
++	if (index) {
++		memcpy(ctx->buf + index, data, bsize - index);
++		ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, bsize);
++		BUG_ON(ret != bsize);
++		data += bsize - index;
++		len -= bsize - index;
++	}
++
++	/* process as many blocks as possible */
++	if (len >= bsize) {
++		ret = crypt_s390_kimd(ctx->func, ctx->state, data,
++				      len & ~(bsize - 1));
++		BUG_ON(ret != (len & ~(bsize - 1)));
++		data += ret;
++		len -= ret;
++	}
++store:
++	if (len)
++		memcpy(ctx->buf + index , data, len);
++}
++EXPORT_SYMBOL_GPL(s390_sha_update);
++
++void s390_sha_final(struct crypto_tfm *tfm, u8 *out)
++{
++	struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
++	unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
++	u64 bits;
++	unsigned int index, end, plen;
++	int ret;
++
++	/* SHA-512 uses 128 bit padding length */
++	plen = (bsize > SHA256_BLOCK_SIZE) ? 16 : 8;
++
++	/* must perform manual padding */
++	index = ctx->count & (bsize - 1);
++	end = (index < bsize - plen) ? bsize : (2 * bsize);
++
++	/* start pad with 1 */
++	ctx->buf[index] = 0x80;
++	index++;
++
++	/* pad with zeros */
++	memset(ctx->buf + index, 0x00, end - index - 8);
++
++	/*
++	 * Append message length. Well, SHA-512 wants a 128 bit lenght value,
++	 * nevertheless we use u64, should be enough for now...
++	 */
++	bits = ctx->count * 8;
++	memcpy(ctx->buf + end - 8, &bits, sizeof(bits));
++
++	ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, end);
++	BUG_ON(ret != end);
++
++	/* copy digest to out */
++	memcpy(out, ctx->state, crypto_hash_digestsize(crypto_hash_cast(tfm)));
++	/* wipe context */
++	memset(ctx, 0, sizeof *ctx);
++}
++EXPORT_SYMBOL_GPL(s390_sha_final);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("s390 SHA cipher common functions");
+diff --git a/arch/s390/defconfig b/arch/s390/defconfig
+index 62f6b5a..a72f208 100644
+--- a/arch/s390/defconfig
++++ b/arch/s390/defconfig
+@@ -3,6 +3,7 @@
+ # Linux kernel version: 2.6.25-rc4
+ # Wed Mar  5 11:22:59 2008
+ #
++CONFIG_SCHED_MC=y
+ CONFIG_MMU=y
+ CONFIG_ZONE_DMA=y
+ CONFIG_LOCKDEP_SUPPORT=y
+@@ -537,11 +538,9 @@ CONFIG_CTC=m
+ # CONFIG_SMSGIUCV is not set
+ # CONFIG_CLAW is not set
+ CONFIG_QETH=y
+-
+-#
+-# Gigabit Ethernet default settings
+-#
+-# CONFIG_QETH_IPV6 is not set
++CONFIG_QETH_L2=y
++CONFIG_QETH_L3=y
++CONFIG_QETH_IPV6=y
+ CONFIG_CCWGROUP=y
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
+index 4d3e383..77051cd 100644
+--- a/arch/s390/kernel/Makefile
++++ b/arch/s390/kernel/Makefile
+@@ -11,7 +11,7 @@ CFLAGS_smp.o	:= -Wno-nonnull
+ 
+ obj-y	:=  bitmap.o traps.o time.o process.o base.o early.o \
+             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
+-	    semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o diag.o
++	    s390_ext.o debug.o irq.o ipl.o dis.o diag.o
+ 
+ obj-y	+= $(if $(CONFIG_64BIT),entry64.o,entry.o)
+ obj-y	+= $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
+@@ -19,7 +19,7 @@ obj-y	+= $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
+ extra-y				+= head.o init_task.o vmlinux.lds
+ 
+ obj-$(CONFIG_MODULES)		+= s390_ksyms.o module.o
+-obj-$(CONFIG_SMP)		+= smp.o
++obj-$(CONFIG_SMP)		+= smp.o topology.o
+ 
+ obj-$(CONFIG_AUDIT)		+= audit.o
+ compat-obj-$(CONFIG_AUDIT)	+= compat_audit.o
+diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
+index 50b85d0..d7f2222 100644
+--- a/arch/s390/kernel/compat_linux.c
++++ b/arch/s390/kernel/compat_linux.c
+@@ -62,7 +62,6 @@
+ 
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ 
+ #include <net/scm.h>
+ #include <net/sock.h>
+diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
+index e89f8c0..20723a0 100644
+--- a/arch/s390/kernel/compat_linux.h
++++ b/arch/s390/kernel/compat_linux.h
+@@ -162,4 +162,77 @@ struct ucontext32 {
+ 	compat_sigset_t		uc_sigmask;	/* mask last for extensibility */
+ };
+ 
++struct __sysctl_args32;
++struct stat64_emu31;
++struct mmap_arg_struct_emu31;
++struct fadvise64_64_args;
++struct old_sigaction32;
++struct old_sigaction32;
++
++long sys32_chown16(const char __user * filename, u16 user, u16 group);
++long sys32_lchown16(const char __user * filename, u16 user, u16 group);
++long sys32_fchown16(unsigned int fd, u16 user, u16 group);
++long sys32_setregid16(u16 rgid, u16 egid);
++long sys32_setgid16(u16 gid);
++long sys32_setreuid16(u16 ruid, u16 euid);
++long sys32_setuid16(u16 uid);
++long sys32_setresuid16(u16 ruid, u16 euid, u16 suid);
++long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid);
++long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid);
++long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid);
++long sys32_setfsuid16(u16 uid);
++long sys32_setfsgid16(u16 gid);
++long sys32_getgroups16(int gidsetsize, u16 __user *grouplist);
++long sys32_setgroups16(int gidsetsize, u16 __user *grouplist);
++long sys32_getuid16(void);
++long sys32_geteuid16(void);
++long sys32_getgid16(void);
++long sys32_getegid16(void);
++long sys32_ipc(u32 call, int first, int second, int third, u32 ptr);
++long sys32_truncate64(const char __user * path, unsigned long high,
++		      unsigned long low);
++long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low);
++long sys32_sched_rr_get_interval(compat_pid_t pid,
++				 struct compat_timespec __user *interval);
++long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
++			  compat_sigset_t __user *oset, size_t sigsetsize);
++long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize);
++long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo);
++long sys32_execve(void);
++long sys32_init_module(void __user *umod, unsigned long len,
++		       const char __user *uargs);
++long sys32_delete_module(const char __user *name_user, unsigned int flags);
++long sys32_gettimeofday(struct compat_timeval __user *tv,
++			struct timezone __user *tz);
++long sys32_settimeofday(struct compat_timeval __user *tv,
++			struct timezone __user *tz);
++long sys32_pause(void);
++long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
++		   u32 poshi, u32 poslo);
++long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
++		    size_t count, u32 poshi, u32 poslo);
++compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count);
++long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
++		    size_t count);
++long sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset,
++		      s32 count);
++long sys32_sysctl(struct __sysctl_args32 __user *args);
++long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf);
++long sys32_lstat64(char __user * filename,
++		   struct stat64_emu31 __user * statbuf);
++long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf);
++long sys32_fstatat64(unsigned int dfd, char __user *filename,
++		     struct stat64_emu31 __user* statbuf, int flag);
++unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg);
++long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg);
++long sys32_read(unsigned int fd, char __user * buf, size_t count);
++long sys32_write(unsigned int fd, char __user * buf, size_t count);
++long sys32_clone(void);
++long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise);
++long sys32_fadvise64_64(struct fadvise64_64_args __user *args);
++long sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
++		     struct old_sigaction32 __user *oact);
++long sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
++			struct sigaction32 __user *oact, size_t sigsetsize);
++long sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss);
+ #endif /* _ASM_S390X_S390_H */
+diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
+index a5692c4..c7f02e7 100644
+--- a/arch/s390/kernel/compat_signal.c
++++ b/arch/s390/kernel/compat_signal.c
+@@ -29,6 +29,7 @@
+ #include <asm/lowcore.h>
+ #include "compat_linux.h"
+ #include "compat_ptrace.h"
++#include "entry.h"
+ 
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+ 
+@@ -428,6 +429,10 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+ 	/* Default to using normal stack */
+ 	sp = (unsigned long) A(regs->gprs[15]);
+ 
++	/* Overflow on alternate signal stack gives SIGSEGV. */
++	if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
++		return (void __user *) -1UL;
++
+ 	/* This is the X/Open sanctioned signal stack switching.  */
+ 	if (ka->sa.sa_flags & SA_ONSTACK) {
+ 		if (! sas_ss_flags(sp))
+@@ -461,6 +466,9 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
+ 	if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
+ 		goto give_sigsegv;
+ 
++	if (frame == (void __user *) -1UL)
++		goto give_sigsegv;
++
+ 	if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
+ 		goto give_sigsegv;
+ 
+@@ -514,6 +522,9 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 	if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
+ 		goto give_sigsegv;
+ 
++	if (frame == (void __user *) -1UL)
++		goto give_sigsegv;
++
+ 	if (copy_siginfo_to_user32(&frame->info, info))
+ 		goto give_sigsegv;
+ 
+diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
+index 1b2f5ce..dff0568 100644
+--- a/arch/s390/kernel/debug.c
++++ b/arch/s390/kernel/debug.c
+@@ -17,7 +17,6 @@
+ #include <linux/ctype.h>
+ #include <linux/sysctl.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/fs.h>
+@@ -73,7 +72,7 @@ static ssize_t debug_input(struct file *file, const char __user *user_buf,
+ static int debug_open(struct inode *inode, struct file *file);
+ static int debug_close(struct inode *inode, struct file *file);
+ static debug_info_t*  debug_info_create(char *name, int pages_per_area,
+-			int nr_areas, int buf_size);
++			int nr_areas, int buf_size, mode_t mode);
+ static void debug_info_get(debug_info_t *);
+ static void debug_info_put(debug_info_t *);
+ static int debug_prolog_level_fn(debug_info_t * id,
+@@ -157,7 +156,7 @@ struct debug_view debug_sprintf_view = {
+ };
+ 
+ /* used by dump analysis tools to determine version of debug feature */
+-unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
++static unsigned int __used debug_feature_version = __DEBUG_FEATURE_VERSION;
+ 
+ /* static globals */
+ 
+@@ -327,7 +326,8 @@ debug_info_free(debug_info_t* db_info){
+  */
+ 
+ static debug_info_t*
+-debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size)
++debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size,
++		  mode_t mode)
+ {
+ 	debug_info_t* rc;
+ 
+@@ -336,6 +336,8 @@ debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size)
+         if(!rc) 
+ 		goto out;
+ 
++	rc->mode = mode & ~S_IFMT;
++
+ 	/* create root directory */
+         rc->debugfs_root_entry = debugfs_create_dir(rc->name,
+ 					debug_debugfs_root_entry);
+@@ -676,23 +678,30 @@ debug_close(struct inode *inode, struct file *file)
+ }
+ 
+ /*
+- * debug_register:
+- * - creates and initializes debug area for the caller
+- * - returns handle for debug area
++ * debug_register_mode:
++ * - Creates and initializes debug area for the caller
++ *   The mode parameter allows to specify access rights for the s390dbf files
++ * - Returns handle for debug area
+  */
+ 
+-debug_info_t*
+-debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
++debug_info_t *debug_register_mode(char *name, int pages_per_area, int nr_areas,
++				  int buf_size, mode_t mode, uid_t uid,
++				  gid_t gid)
+ {
+ 	debug_info_t *rc = NULL;
+ 
++	/* Since debugfs currently does not support uid/gid other than root, */
++	/* we do not allow gid/uid != 0 until we get support for that. */
++	if ((uid != 0) || (gid != 0))
++		printk(KERN_WARNING "debug: Warning - Currently only uid/gid "
++		       "= 0 are supported. Using root as owner now!");
+ 	if (!initialized)
+ 		BUG();
+ 	mutex_lock(&debug_mutex);
+ 
+         /* create new debug_info */
+ 
+-	rc = debug_info_create(name, pages_per_area, nr_areas, buf_size);
++	rc = debug_info_create(name, pages_per_area, nr_areas, buf_size, mode);
+ 	if(!rc) 
+ 		goto out;
+ 	debug_register_view(rc, &debug_level_view);
+@@ -705,6 +714,20 @@ out:
+ 	mutex_unlock(&debug_mutex);
+ 	return rc;
+ }
++EXPORT_SYMBOL(debug_register_mode);
++
++/*
++ * debug_register:
++ * - creates and initializes debug area for the caller
++ * - returns handle for debug area
++ */
++
++debug_info_t *debug_register(char *name, int pages_per_area, int nr_areas,
++			     int buf_size)
++{
++	return debug_register_mode(name, pages_per_area, nr_areas, buf_size,
++				   S_IRUSR | S_IWUSR, 0, 0);
++}
+ 
+ /*
+  * debug_unregister:
+@@ -1073,15 +1096,16 @@ debug_register_view(debug_info_t * id, struct debug_view *view)
+ 	int rc = 0;
+ 	int i;
+ 	unsigned long flags;
+-	mode_t mode = S_IFREG;
++	mode_t mode;
+ 	struct dentry *pde;
+ 
+ 	if (!id)
+ 		goto out;
+-	if (view->prolog_proc || view->format_proc || view->header_proc)
+-		mode |= S_IRUSR;
+-	if (view->input_proc)
+-		mode |= S_IWUSR;
++	mode = (id->mode | S_IFREG) & ~S_IXUGO;
++	if (!(view->prolog_proc || view->format_proc || view->header_proc))
++		mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
++	if (!view->input_proc)
++		mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+ 	pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
+ 				id , &debug_file_ops);
+ 	if (!pde){
+diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
+index 01832c4..540a67f 100644
+--- a/arch/s390/kernel/early.c
++++ b/arch/s390/kernel/early.c
+@@ -21,6 +21,7 @@
+ #include <asm/setup.h>
+ #include <asm/cpcmd.h>
+ #include <asm/sclp.h>
++#include "entry.h"
+ 
+ /*
+  * Create a Kernel NSS if the SAVESYS= parameter is defined
+diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
+new file mode 100644
+index 0000000..6b18963
+--- /dev/null
++++ b/arch/s390/kernel/entry.h
+@@ -0,0 +1,60 @@
++#ifndef _ENTRY_H
++#define _ENTRY_H
++
++#include <linux/types.h>
++#include <linux/signal.h>
++#include <asm/ptrace.h>
++
++typedef void pgm_check_handler_t(struct pt_regs *, long);
++extern pgm_check_handler_t *pgm_check_table[128];
++pgm_check_handler_t do_protection_exception;
++pgm_check_handler_t do_dat_exception;
++
++extern int sysctl_userprocess_debug;
++
++void do_single_step(struct pt_regs *regs);
++void syscall_trace(struct pt_regs *regs, int entryexit);
++void kernel_stack_overflow(struct pt_regs * regs);
++void do_signal(struct pt_regs *regs);
++int handle_signal32(unsigned long sig, struct k_sigaction *ka,
++		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
++
++void do_extint(struct pt_regs *regs, unsigned short code);
++int __cpuinit start_secondary(void *cpuvoid);
++void __init startup_init(void);
++void die(const char * str, struct pt_regs * regs, long err);
++
++struct new_utsname;
++struct mmap_arg_struct;
++struct fadvise64_64_args;
++struct old_sigaction;
++struct sel_arg_struct;
++
++long sys_pipe(unsigned long __user *fildes);
++long sys_mmap2(struct mmap_arg_struct __user  *arg);
++long old_mmap(struct mmap_arg_struct __user *arg);
++long sys_ipc(uint call, int first, unsigned long second,
++	     unsigned long third, void __user *ptr);
++long s390x_newuname(struct new_utsname __user *name);
++long s390x_personality(unsigned long personality);
++long s390_fadvise64(int fd, u32 offset_high, u32 offset_low,
++		    size_t len, int advice);
++long s390_fadvise64_64(struct fadvise64_64_args __user *args);
++long s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, u32 len_low);
++long sys_fork(void);
++long sys_clone(void);
++long sys_vfork(void);
++void execve_tail(void);
++long sys_execve(void);
++int sys_sigsuspend(int history0, int history1, old_sigset_t mask);
++long sys_sigaction(int sig, const struct old_sigaction __user *act,
++		   struct old_sigaction __user *oact);
++long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss);
++long sys_sigreturn(void);
++long sys_rt_sigreturn(void);
++long sys32_sigreturn(void);
++long sys32_rt_sigreturn(void);
++long old_select(struct sel_arg_struct __user *arg);
++long sys_ptrace(long request, long pid, long addr, long data);
++
++#endif /* _ENTRY_H */
+diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
+index efde6e1..cd959c0 100644
+--- a/arch/s390/kernel/entry64.S
++++ b/arch/s390/kernel/entry64.S
+@@ -475,6 +475,7 @@ pgm_check_handler:
+ pgm_no_vtime:
+ #endif
+ 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
++	mvc	SP_ARGS(8,%r15),__LC_LAST_BREAK
+ 	TRACE_IRQS_OFF
+ 	lgf	%r3,__LC_PGM_ILC	# load program interruption code
+ 	lghi	%r8,0x7f
+@@ -847,6 +848,7 @@ stack_overflow:
+ 	je	0f
+ 	la	%r1,__LC_SAVE_AREA+32
+ 0:	mvc	SP_R12(32,%r15),0(%r1)	# move %r12-%r15 to stack
++	mvc	SP_ARGS(8,%r15),__LC_LAST_BREAK
+ 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+ 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+ 	jg	kernel_stack_overflow
+diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
+index 375232c..5325424 100644
+--- a/arch/s390/kernel/ipl.c
++++ b/arch/s390/kernel/ipl.c
+@@ -655,7 +655,7 @@ static struct kobj_attribute reipl_type_attr =
+ 
+ static struct kset *reipl_kset;
+ 
+-void reipl_run(struct shutdown_trigger *trigger)
++static void reipl_run(struct shutdown_trigger *trigger)
+ {
+ 	struct ccw_dev_id devid;
+ 	static char buf[100];
+diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
+index c5549a2..ed04d13 100644
+--- a/arch/s390/kernel/kprobes.c
++++ b/arch/s390/kernel/kprobes.c
+@@ -360,7 +360,7 @@ no_kprobe:
+  *	- When the probed function returns, this probe
+  *		causes the handlers to fire
+  */
+-void kretprobe_trampoline_holder(void)
++static void __used kretprobe_trampoline_holder(void)
+ {
+ 	asm volatile(".global kretprobe_trampoline\n"
+ 		     "kretprobe_trampoline: bcr 0,0\n");
+diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
+index ce20315..c1aff19 100644
+--- a/arch/s390/kernel/process.c
++++ b/arch/s390/kernel/process.c
+@@ -36,6 +36,8 @@
+ #include <linux/module.h>
+ #include <linux/notifier.h>
+ #include <linux/utsname.h>
++#include <linux/tick.h>
++#include <linux/elfcore.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+@@ -44,6 +46,7 @@
+ #include <asm/irq.h>
+ #include <asm/timer.h>
+ #include <asm/cpu.h>
++#include "entry.h"
+ 
+ asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
+ 
+@@ -76,6 +79,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
+  * Need to know about CPUs going idle?
+  */
+ static ATOMIC_NOTIFIER_HEAD(idle_chain);
++DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
+ 
+ int register_idle_notifier(struct notifier_block *nb)
+ {
+@@ -89,9 +93,33 @@ int unregister_idle_notifier(struct notifier_block *nb)
+ }
+ EXPORT_SYMBOL(unregister_idle_notifier);
+ 
+-void do_monitor_call(struct pt_regs *regs, long interruption_code)
++static int s390_idle_enter(void)
++{
++	struct s390_idle_data *idle;
++	int nr_calls = 0;
++	void *hcpu;
++	int rc;
++
++	hcpu = (void *)(long)smp_processor_id();
++	rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1,
++					  &nr_calls);
++	if (rc == NOTIFY_BAD) {
++		nr_calls--;
++		__atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
++					     hcpu, nr_calls, NULL);
++		return rc;
++	}
++	idle = &__get_cpu_var(s390_idle);
++	spin_lock(&idle->lock);
++	idle->idle_count++;
++	idle->in_idle = 1;
++	idle->idle_enter = get_clock();
++	spin_unlock(&idle->lock);
++	return NOTIFY_OK;
++}
++
++void s390_idle_leave(void)
+ {
+-#ifdef CONFIG_SMP
+ 	struct s390_idle_data *idle;
+ 
+ 	idle = &__get_cpu_var(s390_idle);
+@@ -99,10 +127,6 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code)
+ 	idle->idle_time += get_clock() - idle->idle_enter;
+ 	idle->in_idle = 0;
+ 	spin_unlock(&idle->lock);
+-#endif
+-	/* disable monitor call class 0 */
+-	__ctl_clear_bit(8, 15);
+-
+ 	atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+ 				   (void *)(long) smp_processor_id());
+ }
+@@ -113,61 +137,30 @@ extern void s390_handle_mcck(void);
+  */
+ static void default_idle(void)
+ {
+-	int cpu, rc;
+-	int nr_calls = 0;
+-	void *hcpu;
+-#ifdef CONFIG_SMP
+-	struct s390_idle_data *idle;
+-#endif
+-
+ 	/* CPU is going idle. */
+-	cpu = smp_processor_id();
+-	hcpu = (void *)(long)cpu;
+ 	local_irq_disable();
+ 	if (need_resched()) {
+ 		local_irq_enable();
+ 		return;
+ 	}
+-
+-	rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1,
+-					  &nr_calls);
+-	if (rc == NOTIFY_BAD) {
+-		nr_calls--;
+-		__atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+-					     hcpu, nr_calls, NULL);
++	if (s390_idle_enter() == NOTIFY_BAD) {
+ 		local_irq_enable();
+ 		return;
+ 	}
+-
+-	/* enable monitor call class 0 */
+-	__ctl_set_bit(8, 15);
+-
+ #ifdef CONFIG_HOTPLUG_CPU
+-	if (cpu_is_offline(cpu)) {
++	if (cpu_is_offline(smp_processor_id())) {
+ 		preempt_enable_no_resched();
+ 		cpu_die();
+ 	}
+ #endif
+-
+ 	local_mcck_disable();
+ 	if (test_thread_flag(TIF_MCCK_PENDING)) {
+ 		local_mcck_enable();
+-		/* disable monitor call class 0 */
+-		__ctl_clear_bit(8, 15);
+-		atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+-					   hcpu);
++		s390_idle_leave();
+ 		local_irq_enable();
+ 		s390_handle_mcck();
+ 		return;
+ 	}
+-#ifdef CONFIG_SMP
+-	idle = &__get_cpu_var(s390_idle);
+-	spin_lock(&idle->lock);
+-	idle->idle_count++;
+-	idle->in_idle = 1;
+-	idle->idle_enter = get_clock();
+-	spin_unlock(&idle->lock);
+-#endif
+ 	trace_hardirqs_on();
+ 	/* Wait for external, I/O or machine check interrupt. */
+ 	__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
+@@ -177,9 +170,10 @@ static void default_idle(void)
+ void cpu_idle(void)
+ {
+ 	for (;;) {
++		tick_nohz_stop_sched_tick();
+ 		while (!need_resched())
+ 			default_idle();
+-
++		tick_nohz_restart_sched_tick();
+ 		preempt_enable_no_resched();
+ 		schedule();
+ 		preempt_disable();
+@@ -201,6 +195,7 @@ void show_regs(struct pt_regs *regs)
+ 	/* Show stack backtrace if pt_regs is from kernel mode */
+ 	if (!(regs->psw.mask & PSW_MASK_PSTATE))
+ 		show_trace(NULL, (unsigned long *) regs->gprs[15]);
++	show_last_breaking_event(regs);
+ }
+ 
+ extern void kernel_thread_starter(void);
+diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
+index 6e036ba..58a0642 100644
+--- a/arch/s390/kernel/ptrace.c
++++ b/arch/s390/kernel/ptrace.c
+@@ -41,6 +41,7 @@
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
++#include "entry.h"
+ 
+ #ifdef CONFIG_COMPAT
+ #include "compat_ptrace.h"
+diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
+index acf93db..e019b41 100644
+--- a/arch/s390/kernel/s390_ext.c
++++ b/arch/s390/kernel/s390_ext.c
+@@ -13,11 +13,12 @@
+ #include <linux/errno.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/interrupt.h>
+-
++#include <asm/cpu.h>
+ #include <asm/lowcore.h>
+ #include <asm/s390_ext.h>
+ #include <asm/irq_regs.h>
+ #include <asm/irq.h>
++#include "entry.h"
+ 
+ /*
+  * ext_int_hash[index] is the start of the list for all external interrupts
+@@ -119,13 +120,10 @@ void do_extint(struct pt_regs *regs, unsigned short code)
+ 
+ 	old_regs = set_irq_regs(regs);
+ 	irq_enter();
+-	asm volatile ("mc 0,0");
+-	if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
+-		/**
+-		 * Make sure that the i/o interrupt did not "overtake"
+-		 * the last HZ timer interrupt.
+-		 */
+-		account_ticks(S390_lowcore.int_clock);
++	s390_idle_check();
++	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
++		/* Serve timer interrupts first. */
++		clock_comparator_work();
+ 	kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
+         index = ext_hash(code);
+ 	for (p = ext_int_hash[index]; p; p = p->next) {
+diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
+index 7234c73..48238a1 100644
+--- a/arch/s390/kernel/s390_ksyms.c
++++ b/arch/s390/kernel/s390_ksyms.c
+@@ -27,13 +27,6 @@ EXPORT_SYMBOL(_zb_findmap);
+ EXPORT_SYMBOL(_sb_findmap);
+ 
+ /*
+- * semaphore ops
+- */
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-
+-/*
+  * binfmt_elf loader 
+  */
+ extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs);
+diff --git a/arch/s390/kernel/semaphore.c b/arch/s390/kernel/semaphore.c
+deleted file mode 100644
+index 191303f..0000000
+--- a/arch/s390/kernel/semaphore.c
++++ /dev/null
+@@ -1,108 +0,0 @@
+-/*
+- *  linux/arch/s390/kernel/semaphore.c
+- *
+- *  S390 version
+- *    Copyright (C) 1998-2000 IBM Corporation
+- *    Author(s): Martin Schwidefsky
+- *
+- *  Derived from "linux/arch/i386/kernel/semaphore.c
+- *    Copyright (C) 1999, Linus Torvalds
+- *
+- */
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-#include <asm/semaphore.h>
+-
+-/*
+- * Atomically update sem->count. Equivalent to:
+- *   old_val = sem->count.counter;
+- *   new_val = ((old_val >= 0) ? old_val : 0) + incr;
+- *   sem->count.counter = new_val;
+- *   return old_val;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+-	int old_val, new_val;
+-
+-	asm volatile(
+-		"	l	%0,0(%3)\n"
+-		"0:	ltr	%1,%0\n"
+-		"	jhe	1f\n"
+-		"	lhi	%1,0\n"
+-		"1:	ar	%1,%4\n"
+-		"	cs	%0,%1,0(%3)\n"
+-		"	jl	0b\n"
+-		: "=&d" (old_val), "=&d" (new_val), "=m" (sem->count)
+-		: "a" (&sem->count), "d" (incr), "m" (sem->count)
+-		: "cc");
+-	return old_val;
+-}
+-
+-/*
+- * The inline function up() incremented count but the result
+- * was <= 0. This indicates that some process is waiting on
+- * the semaphore. The semaphore is free and we'll wake the
+- * first sleeping process, so we set count to 1 unless some
+- * other cpu has called up in the meantime in which case
+- * we just increment count by 1.
+- */
+-void __up(struct semaphore *sem)
+-{
+-	__sem_update_count(sem, 1);
+-	wake_up(&sem->wait);
+-}
+-
+-/*
+- * The inline function down() decremented count and the result
+- * was < 0. The wait loop will atomically test and update the
+- * semaphore counter following the rules:
+- *   count > 0: decrement count, wake up queue and exit.
+- *   count <= 0: set count to -1, go to sleep.
+- */
+-void __sched __down(struct semaphore * sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		schedule();
+-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-	}
+-	remove_wait_queue(&sem->wait, &wait);
+-	__set_task_state(tsk, TASK_RUNNING);
+-	wake_up(&sem->wait);
+-}
+-
+-/*
+- * Same as __down() with an additional test for signals.
+- * If a signal is pending the count is updated as follows:
+- *   count > 0: wake up queue and exit.
+- *   count <= 0: set count to 0, wake up queue and exit.
+- */
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	__set_task_state(tsk, TASK_INTERRUPTIBLE);
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		if (signal_pending(current)) {
+-			__sem_update_count(sem, 0);
+-			retval = -EINTR;
+-			break;
+-		}
+-		schedule();
+-		set_task_state(tsk, TASK_INTERRUPTIBLE);
+-	}
+-	remove_wait_queue(&sem->wait, &wait);
+-	__set_task_state(tsk, TASK_RUNNING);
+-	wake_up(&sem->wait);
+-	return retval;
+-}
+-
+diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
+index 290e504..7141147 100644
+--- a/arch/s390/kernel/setup.c
++++ b/arch/s390/kernel/setup.c
+@@ -39,6 +39,7 @@
+ #include <linux/pfn.h>
+ #include <linux/ctype.h>
+ #include <linux/reboot.h>
++#include <linux/topology.h>
+ 
+ #include <asm/ipl.h>
+ #include <asm/uaccess.h>
+@@ -427,7 +428,7 @@ setup_lowcore(void)
+ 	lc->io_new_psw.mask = psw_kernel_bits;
+ 	lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
+ 	lc->ipl_device = S390_lowcore.ipl_device;
+-	lc->jiffy_timer = -1LL;
++	lc->clock_comparator = -1ULL;
+ 	lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
+ 	lc->async_stack = (unsigned long)
+ 		__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
+@@ -687,7 +688,7 @@ static __init unsigned int stfl(void)
+ 	return S390_lowcore.stfl_fac_list;
+ }
+ 
+-static __init int stfle(unsigned long long *list, int doublewords)
++static int __init __stfle(unsigned long long *list, int doublewords)
+ {
+ 	typedef struct { unsigned long long _[doublewords]; } addrtype;
+ 	register unsigned long __nr asm("0") = doublewords - 1;
+@@ -697,6 +698,13 @@ static __init int stfle(unsigned long long *list, int doublewords)
+ 	return __nr + 1;
+ }
+ 
++int __init stfle(unsigned long long *list, int doublewords)
++{
++	if (!(stfl() & (1UL << 24)))
++		return -EOPNOTSUPP;
++	return __stfle(list, doublewords);
++}
++
+ /*
+  * Setup hardware capabilities.
+  */
+@@ -741,7 +749,7 @@ static void __init setup_hwcaps(void)
+ 	 *   HWCAP_S390_DFP bit 6.
+ 	 */
+ 	if ((elf_hwcap & (1UL << 2)) &&
+-	    stfle(&facility_list_extended, 1) > 0) {
++	    __stfle(&facility_list_extended, 1) > 0) {
+ 		if (facility_list_extended & (1ULL << (64 - 43)))
+ 			elf_hwcap |= 1UL << 6;
+ 	}
+@@ -823,6 +831,7 @@ setup_arch(char **cmdline_p)
+ 
+         cpu_init();
+         __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
++	s390_init_cpu_topology();
+ 
+ 	/*
+ 	 * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
+diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
+index 4449bf3..b976820 100644
+--- a/arch/s390/kernel/signal.c
++++ b/arch/s390/kernel/signal.c
+@@ -27,6 +27,7 @@
+ #include <asm/ucontext.h>
+ #include <asm/uaccess.h>
+ #include <asm/lowcore.h>
++#include "entry.h"
+ 
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+ 
+@@ -235,6 +236,10 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+ 	/* Default to using normal stack */
+ 	sp = regs->gprs[15];
+ 
++	/* Overflow on alternate signal stack gives SIGSEGV. */
++	if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
++		return (void __user *) -1UL;
++
+ 	/* This is the X/Open sanctioned signal stack switching.  */
+ 	if (ka->sa.sa_flags & SA_ONSTACK) {
+ 		if (! sas_ss_flags(sp))
+@@ -270,6 +275,9 @@ static int setup_frame(int sig, struct k_sigaction *ka,
+ 	if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe)))
+ 		goto give_sigsegv;
+ 
++	if (frame == (void __user *) -1UL)
++		goto give_sigsegv;
++
+ 	if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
+ 		goto give_sigsegv;
+ 
+@@ -327,6 +335,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 	if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe)))
+ 		goto give_sigsegv;
+ 
++	if (frame == (void __user *) -1UL)
++		goto give_sigsegv;
++
+ 	if (copy_siginfo_to_user(&frame->info, info))
+ 		goto give_sigsegv;
+ 
+@@ -474,11 +485,6 @@ void do_signal(struct pt_regs *regs)
+ 		int ret;
+ #ifdef CONFIG_COMPAT
+ 		if (test_thread_flag(TIF_31BIT)) {
+-			extern int handle_signal32(unsigned long sig,
+-						   struct k_sigaction *ka,
+-						   siginfo_t *info,
+-						   sigset_t *oldset,
+-						   struct pt_regs *regs);
+ 			ret = handle_signal32(signr, &ka, &info, oldset, regs);
+ 	        }
+ 		else
+diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
+index 8f894d3..0dfa988 100644
+--- a/arch/s390/kernel/smp.c
++++ b/arch/s390/kernel/smp.c
+@@ -44,6 +44,7 @@
+ #include <asm/lowcore.h>
+ #include <asm/sclp.h>
+ #include <asm/cpu.h>
++#include "entry.h"
+ 
+ /*
+  * An array with a pointer the lowcore of every CPU.
+@@ -67,13 +68,12 @@ enum s390_cpu_state {
+ 	CPU_STATE_CONFIGURED,
+ };
+ 
+-#ifdef CONFIG_HOTPLUG_CPU
+-static DEFINE_MUTEX(smp_cpu_state_mutex);
+-#endif
++DEFINE_MUTEX(smp_cpu_state_mutex);
++int smp_cpu_polarization[NR_CPUS];
+ static int smp_cpu_state[NR_CPUS];
++static int cpu_management;
+ 
+ static DEFINE_PER_CPU(struct cpu, cpu_devices);
+-DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
+ 
+ static void smp_ext_bitcall(int, ec_bit_sig);
+ 
+@@ -298,7 +298,7 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
+ /*
+  * this function sends a 'purge tlb' signal to another CPU.
+  */
+-void smp_ptlb_callback(void *info)
++static void smp_ptlb_callback(void *info)
+ {
+ 	__tlb_flush_local();
+ }
+@@ -456,6 +456,7 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
+ 		if (cpu_known(cpu_id))
+ 			continue;
+ 		__cpu_logical_map[logical_cpu] = cpu_id;
++		smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN;
+ 		if (!cpu_stopped(logical_cpu))
+ 			continue;
+ 		cpu_set(logical_cpu, cpu_present_map);
+@@ -489,6 +490,7 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
+ 		if (cpu_known(cpu_id))
+ 			continue;
+ 		__cpu_logical_map[logical_cpu] = cpu_id;
++		smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN;
+ 		cpu_set(logical_cpu, cpu_present_map);
+ 		if (cpu >= info->configured)
+ 			smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY;
+@@ -846,6 +848,7 @@ void __init smp_prepare_boot_cpu(void)
+ 	S390_lowcore.percpu_offset = __per_cpu_offset[0];
+ 	current_set[0] = current;
+ 	smp_cpu_state[0] = CPU_STATE_CONFIGURED;
++	smp_cpu_polarization[0] = POLARIZATION_UNKNWN;
+ 	spin_lock_init(&(&__get_cpu_var(s390_idle))->lock);
+ }
+ 
+@@ -897,15 +900,19 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf,
+ 	case 0:
+ 		if (smp_cpu_state[cpu] == CPU_STATE_CONFIGURED) {
+ 			rc = sclp_cpu_deconfigure(__cpu_logical_map[cpu]);
+-			if (!rc)
++			if (!rc) {
+ 				smp_cpu_state[cpu] = CPU_STATE_STANDBY;
++				smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
++			}
+ 		}
+ 		break;
+ 	case 1:
+ 		if (smp_cpu_state[cpu] == CPU_STATE_STANDBY) {
+ 			rc = sclp_cpu_configure(__cpu_logical_map[cpu]);
+-			if (!rc)
++			if (!rc) {
+ 				smp_cpu_state[cpu] = CPU_STATE_CONFIGURED;
++				smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
++			}
+ 		}
+ 		break;
+ 	default:
+@@ -919,6 +926,34 @@ out:
+ static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
+ #endif /* CONFIG_HOTPLUG_CPU */
+ 
++static ssize_t cpu_polarization_show(struct sys_device *dev, char *buf)
++{
++	int cpu = dev->id;
++	ssize_t count;
++
++	mutex_lock(&smp_cpu_state_mutex);
++	switch (smp_cpu_polarization[cpu]) {
++	case POLARIZATION_HRZ:
++		count = sprintf(buf, "horizontal\n");
++		break;
++	case POLARIZATION_VL:
++		count = sprintf(buf, "vertical:low\n");
++		break;
++	case POLARIZATION_VM:
++		count = sprintf(buf, "vertical:medium\n");
++		break;
++	case POLARIZATION_VH:
++		count = sprintf(buf, "vertical:high\n");
++		break;
++	default:
++		count = sprintf(buf, "unknown\n");
++		break;
++	}
++	mutex_unlock(&smp_cpu_state_mutex);
++	return count;
++}
++static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL);
++
+ static ssize_t show_cpu_address(struct sys_device *dev, char *buf)
+ {
+ 	return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]);
+@@ -931,6 +966,7 @@ static struct attribute *cpu_common_attrs[] = {
+ 	&attr_configure.attr,
+ #endif
+ 	&attr_address.attr,
++	&attr_polarization.attr,
+ 	NULL,
+ };
+ 
+@@ -1075,11 +1111,48 @@ static ssize_t __ref rescan_store(struct sys_device *dev,
+ out:
+ 	put_online_cpus();
+ 	mutex_unlock(&smp_cpu_state_mutex);
++	if (!cpus_empty(newcpus))
++		topology_schedule_update();
+ 	return rc ? rc : count;
+ }
+ static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store);
+ #endif /* CONFIG_HOTPLUG_CPU */
+ 
++static ssize_t dispatching_show(struct sys_device *dev, char *buf)
++{
++	ssize_t count;
++
++	mutex_lock(&smp_cpu_state_mutex);
++	count = sprintf(buf, "%d\n", cpu_management);
++	mutex_unlock(&smp_cpu_state_mutex);
++	return count;
++}
++
++static ssize_t dispatching_store(struct sys_device *dev, const char *buf,
++				 size_t count)
++{
++	int val, rc;
++	char delim;
++
++	if (sscanf(buf, "%d %c", &val, &delim) != 1)
++		return -EINVAL;
++	if (val != 0 && val != 1)
++		return -EINVAL;
++	rc = 0;
++	mutex_lock(&smp_cpu_state_mutex);
++	get_online_cpus();
++	if (cpu_management == val)
++		goto out;
++	rc = topology_set_cpu_management(val);
++	if (!rc)
++		cpu_management = val;
++out:
++	put_online_cpus();
++	mutex_unlock(&smp_cpu_state_mutex);
++	return rc ? rc : count;
++}
++static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store);
++
+ static int __init topology_init(void)
+ {
+ 	int cpu;
+@@ -1093,6 +1166,10 @@ static int __init topology_init(void)
+ 	if (rc)
+ 		return rc;
+ #endif
++	rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
++			       &attr_dispatching.attr);
++	if (rc)
++		return rc;
+ 	for_each_present_cpu(cpu) {
+ 		rc = smp_add_present_cpu(cpu);
+ 		if (rc)
+diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
+index fefee99..988d0d6 100644
+--- a/arch/s390/kernel/sys_s390.c
++++ b/arch/s390/kernel/sys_s390.c
+@@ -29,8 +29,8 @@
+ #include <linux/personality.h>
+ #include <linux/unistd.h>
+ #include <linux/ipc.h>
+-
+ #include <asm/uaccess.h>
++#include "entry.h"
+ 
+ /*
+  * sys_pipe() is the normal C calling standard for creating
+diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
+index cb232c1..7aec676 100644
+--- a/arch/s390/kernel/time.c
++++ b/arch/s390/kernel/time.c
+@@ -30,7 +30,7 @@
+ #include <linux/timex.h>
+ #include <linux/notifier.h>
+ #include <linux/clocksource.h>
+-
++#include <linux/clockchips.h>
+ #include <asm/uaccess.h>
+ #include <asm/delay.h>
+ #include <asm/s390_ext.h>
+@@ -39,6 +39,7 @@
+ #include <asm/irq_regs.h>
+ #include <asm/timer.h>
+ #include <asm/etr.h>
++#include <asm/cio.h>
+ 
+ /* change this if you have some constant time drift */
+ #define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
+@@ -57,16 +58,16 @@
+ 
+ static ext_int_info_t ext_int_info_cc;
+ static ext_int_info_t ext_int_etr_cc;
+-static u64 init_timer_cc;
+ static u64 jiffies_timer_cc;
+-static u64 xtime_cc;
++
++static DEFINE_PER_CPU(struct clock_event_device, comparators);
+ 
+ /*
+  * Scheduler clock - returns current time in nanosec units.
+  */
+ unsigned long long sched_clock(void)
+ {
+-	return ((get_clock() - jiffies_timer_cc) * 125) >> 9;
++	return ((get_clock_xt() - jiffies_timer_cc) * 125) >> 9;
+ }
+ 
+ /*
+@@ -95,162 +96,40 @@ void tod_to_timeval(__u64 todval, struct timespec *xtime)
+ #define s390_do_profile()	do { ; } while(0)
+ #endif /* CONFIG_PROFILING */
+ 
+-/*
+- * Advance the per cpu tick counter up to the time given with the
+- * "time" argument. The per cpu update consists of accounting
+- * the virtual cpu time, calling update_process_times and calling
+- * the profiling hook. If xtime is before time it is advanced as well.
+- */
+-void account_ticks(u64 time)
++void clock_comparator_work(void)
+ {
+-	__u32 ticks;
+-	__u64 tmp;
+-
+-	/* Calculate how many ticks have passed. */
+-	if (time < S390_lowcore.jiffy_timer)
+-		return;
+-	tmp = time - S390_lowcore.jiffy_timer;
+-	if (tmp >= 2*CLK_TICKS_PER_JIFFY) {  /* more than two ticks ? */
+-		ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
+-		S390_lowcore.jiffy_timer +=
+-			CLK_TICKS_PER_JIFFY * (__u64) ticks;
+-	} else if (tmp >= CLK_TICKS_PER_JIFFY) {
+-		ticks = 2;
+-		S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY;
+-	} else {
+-		ticks = 1;
+-		S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
+-	}
+-
+-#ifdef CONFIG_SMP
+-	/*
+-	 * Do not rely on the boot cpu to do the calls to do_timer.
+-	 * Spread it over all cpus instead.
+-	 */
+-	write_seqlock(&xtime_lock);
+-	if (S390_lowcore.jiffy_timer > xtime_cc) {
+-		__u32 xticks;
+-		tmp = S390_lowcore.jiffy_timer - xtime_cc;
+-		if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
+-			xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
+-			xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY;
+-		} else {
+-			xticks = 1;
+-			xtime_cc += CLK_TICKS_PER_JIFFY;
+-		}
+-		do_timer(xticks);
+-	}
+-	write_sequnlock(&xtime_lock);
+-#else
+-	do_timer(ticks);
+-#endif
+-
+-	while (ticks--)
+-		update_process_times(user_mode(get_irq_regs()));
++	struct clock_event_device *cd;
+ 
++	S390_lowcore.clock_comparator = -1ULL;
++	set_clock_comparator(S390_lowcore.clock_comparator);
++	cd = &__get_cpu_var(comparators);
++	cd->event_handler(cd);
+ 	s390_do_profile();
+ }
+ 
+-#ifdef CONFIG_NO_IDLE_HZ
+-
+-#ifdef CONFIG_NO_IDLE_HZ_INIT
+-int sysctl_hz_timer = 0;
+-#else
+-int sysctl_hz_timer = 1;
+-#endif
+-
+-/*
+- * Stop the HZ tick on the current CPU.
+- * Only cpu_idle may call this function.
+- */
+-static void stop_hz_timer(void)
+-{
+-	unsigned long flags;
+-	unsigned long seq, next;
+-	__u64 timer, todval;
+-	int cpu = smp_processor_id();
+-
+-	if (sysctl_hz_timer != 0)
+-		return;
+-
+-	cpu_set(cpu, nohz_cpu_mask);
+-
+-	/*
+-	 * Leave the clock comparator set up for the next timer
+-	 * tick if either rcu or a softirq is pending.
+-	 */
+-	if (rcu_needs_cpu(cpu) || local_softirq_pending()) {
+-		cpu_clear(cpu, nohz_cpu_mask);
+-		return;
+-	}
+-
+-	/*
+-	 * This cpu is going really idle. Set up the clock comparator
+-	 * for the next event.
+-	 */
+-	next = next_timer_interrupt();
+-	do {
+-		seq = read_seqbegin_irqsave(&xtime_lock, flags);
+-		timer = ((__u64) next) - ((__u64) jiffies) + jiffies_64;
+-	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+-	todval = -1ULL;
+-	/* Be careful about overflows. */
+-	if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
+-		timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
+-		if (timer >= jiffies_timer_cc)
+-			todval = timer;
+-	}
+-	set_clock_comparator(todval);
+-}
+-
+ /*
+- * Start the HZ tick on the current CPU.
+- * Only cpu_idle may call this function.
++ * Fixup the clock comparator.
+  */
+-static void start_hz_timer(void)
++static void fixup_clock_comparator(unsigned long long delta)
+ {
+-	if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
++	/* If nobody is waiting there's nothing to fix. */
++	if (S390_lowcore.clock_comparator == -1ULL)
+ 		return;
+-	account_ticks(get_clock());
+-	set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+-	cpu_clear(smp_processor_id(), nohz_cpu_mask);
+-}
+-
+-static int nohz_idle_notify(struct notifier_block *self,
+-			    unsigned long action, void *hcpu)
+-{
+-	switch (action) {
+-	case S390_CPU_IDLE:
+-		stop_hz_timer();
+-		break;
+-	case S390_CPU_NOT_IDLE:
+-		start_hz_timer();
+-		break;
+-	}
+-	return NOTIFY_OK;
++	S390_lowcore.clock_comparator += delta;
++	set_clock_comparator(S390_lowcore.clock_comparator);
+ }
+ 
+-static struct notifier_block nohz_idle_nb = {
+-	.notifier_call = nohz_idle_notify,
+-};
+-
+-static void __init nohz_init(void)
++static int s390_next_event(unsigned long delta,
++			   struct clock_event_device *evt)
+ {
+-	if (register_idle_notifier(&nohz_idle_nb))
+-		panic("Couldn't register idle notifier");
++	S390_lowcore.clock_comparator = get_clock() + delta;
++	set_clock_comparator(S390_lowcore.clock_comparator);
++	return 0;
+ }
+ 
+-#endif
+-
+-/*
+- * Set up per cpu jiffy timer and set the clock comparator.
+- */
+-static void setup_jiffy_timer(void)
++static void s390_set_mode(enum clock_event_mode mode,
++			  struct clock_event_device *evt)
+ {
+-	/* Set up clock comparator to next jiffy. */
+-	S390_lowcore.jiffy_timer =
+-		jiffies_timer_cc + (jiffies_64 + 1) * CLK_TICKS_PER_JIFFY;
+-	set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+ }
+ 
+ /*
+@@ -259,7 +138,26 @@ static void setup_jiffy_timer(void)
+  */
+ void init_cpu_timer(void)
+ {
+-	setup_jiffy_timer();
++	struct clock_event_device *cd;
++	int cpu;
++
++	S390_lowcore.clock_comparator = -1ULL;
++	set_clock_comparator(S390_lowcore.clock_comparator);
++
++	cpu = smp_processor_id();
++	cd = &per_cpu(comparators, cpu);
++	cd->name		= "comparator";
++	cd->features		= CLOCK_EVT_FEAT_ONESHOT;
++	cd->mult		= 16777;
++	cd->shift		= 12;
++	cd->min_delta_ns	= 1;
++	cd->max_delta_ns	= LONG_MAX;
++	cd->rating		= 400;
++	cd->cpumask		= cpumask_of_cpu(cpu);
++	cd->set_next_event	= s390_next_event;
++	cd->set_mode		= s390_set_mode;
++
++	clockevents_register_device(cd);
+ 
+ 	/* Enable clock comparator timer interrupt. */
+ 	__ctl_set_bit(0,11);
+@@ -270,8 +168,6 @@ void init_cpu_timer(void)
+ 
+ static void clock_comparator_interrupt(__u16 code)
+ {
+-	/* set clock comparator for next tick */
+-	set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+ }
+ 
+ static void etr_reset(void);
+@@ -316,8 +212,9 @@ static struct clocksource clocksource_tod = {
+  */
+ void __init time_init(void)
+ {
++	u64 init_timer_cc;
++
+ 	init_timer_cc = reset_tod_clock();
+-	xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
+ 	jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY;
+ 
+ 	/* set xtime */
+@@ -342,10 +239,6 @@ void __init time_init(void)
+ 	/* Enable TOD clock interrupts on the boot cpu. */
+ 	init_cpu_timer();
+ 
+-#ifdef CONFIG_NO_IDLE_HZ
+-	nohz_init();
+-#endif
+-
+ #ifdef CONFIG_VIRT_TIMER
+ 	vtime_init();
+ #endif
+@@ -699,53 +592,49 @@ static int etr_aib_follows(struct etr_aib *a1, struct etr_aib *a2, int p)
+ }
+ 
+ /*
+- * The time is "clock". xtime is what we think the time is.
++ * The time is "clock". old is what we think the time is.
+  * Adjust the value by a multiple of jiffies and add the delta to ntp.
+  * "delay" is an approximation how long the synchronization took. If
+  * the time correction is positive, then "delay" is subtracted from
+  * the time difference and only the remaining part is passed to ntp.
+  */
+-static void etr_adjust_time(unsigned long long clock, unsigned long long delay)
++static unsigned long long etr_adjust_time(unsigned long long old,
++					  unsigned long long clock,
++					  unsigned long long delay)
+ {
+ 	unsigned long long delta, ticks;
+ 	struct timex adjust;
+ 
+-	/*
+-	 * We don't have to take the xtime lock because the cpu
+-	 * executing etr_adjust_time is running disabled in
+-	 * tasklet context and all other cpus are looping in
+-	 * etr_sync_cpu_start.
+-	 */
+-	if (clock > xtime_cc) {
++	if (clock > old) {
+ 		/* It is later than we thought. */
+-		delta = ticks = clock - xtime_cc;
++		delta = ticks = clock - old;
+ 		delta = ticks = (delta < delay) ? 0 : delta - delay;
+ 		delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+-		init_timer_cc = init_timer_cc + delta;
+-		jiffies_timer_cc = jiffies_timer_cc + delta;
+-		xtime_cc = xtime_cc + delta;
+ 		adjust.offset = ticks * (1000000 / HZ);
+ 	} else {
+ 		/* It is earlier than we thought. */
+-		delta = ticks = xtime_cc - clock;
++		delta = ticks = old - clock;
+ 		delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+-		init_timer_cc = init_timer_cc - delta;
+-		jiffies_timer_cc = jiffies_timer_cc - delta;
+-		xtime_cc = xtime_cc - delta;
++		delta = -delta;
+ 		adjust.offset = -ticks * (1000000 / HZ);
+ 	}
++	jiffies_timer_cc += delta;
+ 	if (adjust.offset != 0) {
+ 		printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
+ 		       adjust.offset);
+ 		adjust.modes = ADJ_OFFSET_SINGLESHOT;
+ 		do_adjtimex(&adjust);
+ 	}
++	return delta;
+ }
+ 
++static struct {
++	int in_sync;
++	unsigned long long fixup_cc;
++} etr_sync;
++
+ static void etr_sync_cpu_start(void *dummy)
+ {
+-	int *in_sync = dummy;
+-
+ 	etr_enable_sync_clock();
+ 	/*
+ 	 * This looks like a busy wait loop but it isn't. etr_sync_cpus
+@@ -753,7 +642,7 @@ static void etr_sync_cpu_start(void *dummy)
+ 	 * __udelay will stop the cpu on an enabled wait psw until the
+ 	 * TOD is running again.
+ 	 */
+-	while (*in_sync == 0) {
++	while (etr_sync.in_sync == 0) {
+ 		__udelay(1);
+ 		/*
+ 		 * A different cpu changes *in_sync. Therefore use
+@@ -761,14 +650,14 @@ static void etr_sync_cpu_start(void *dummy)
+ 		 */
+ 		barrier();
+ 	}
+-	if (*in_sync != 1)
++	if (etr_sync.in_sync != 1)
+ 		/* Didn't work. Clear per-cpu in sync bit again. */
+ 		etr_disable_sync_clock(NULL);
+ 	/*
+ 	 * This round of TOD syncing is done. Set the clock comparator
+ 	 * to the next tick and let the processor continue.
+ 	 */
+-	setup_jiffy_timer();
++	fixup_clock_comparator(etr_sync.fixup_cc);
+ }
+ 
+ static void etr_sync_cpu_end(void *dummy)
+@@ -783,8 +672,8 @@ static void etr_sync_cpu_end(void *dummy)
+ static int etr_sync_clock(struct etr_aib *aib, int port)
+ {
+ 	struct etr_aib *sync_port;
+-	unsigned long long clock, delay;
+-	int in_sync, follows;
++	unsigned long long clock, old_clock, delay, delta;
++	int follows;
+ 	int rc;
+ 
+ 	/* Check if the current aib is adjacent to the sync port aib. */
+@@ -799,9 +688,9 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
+ 	 * successfully synced the clock. smp_call_function will
+ 	 * return after all other cpus are in etr_sync_cpu_start.
+ 	 */
+-	in_sync = 0;
++	memset(&etr_sync, 0, sizeof(etr_sync));
+ 	preempt_disable();
+-	smp_call_function(etr_sync_cpu_start,&in_sync,0,0);
++	smp_call_function(etr_sync_cpu_start, NULL, 0, 0);
+ 	local_irq_disable();
+ 	etr_enable_sync_clock();
+ 
+@@ -809,6 +698,7 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
+ 	__ctl_set_bit(14, 21);
+ 	__ctl_set_bit(0, 29);
+ 	clock = ((unsigned long long) (aib->edf2.etv + 1)) << 32;
++	old_clock = get_clock();
+ 	if (set_clock(clock) == 0) {
+ 		__udelay(1);	/* Wait for the clock to start. */
+ 		__ctl_clear_bit(0, 29);
+@@ -817,16 +707,17 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
+ 		/* Adjust Linux timing variables. */
+ 		delay = (unsigned long long)
+ 			(aib->edf2.etv - sync_port->edf2.etv) << 32;
+-		etr_adjust_time(clock, delay);
+-		setup_jiffy_timer();
++		delta = etr_adjust_time(old_clock, clock, delay);
++		etr_sync.fixup_cc = delta;
++		fixup_clock_comparator(delta);
+ 		/* Verify that the clock is properly set. */
+ 		if (!etr_aib_follows(sync_port, aib, port)) {
+ 			/* Didn't work. */
+ 			etr_disable_sync_clock(NULL);
+-			in_sync = -EAGAIN;
++			etr_sync.in_sync = -EAGAIN;
+ 			rc = -EAGAIN;
+ 		} else {
+-			in_sync = 1;
++			etr_sync.in_sync = 1;
+ 			rc = 0;
+ 		}
+ 	} else {
+@@ -834,7 +725,7 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
+ 		__ctl_clear_bit(0, 29);
+ 		__ctl_clear_bit(14, 21);
+ 		etr_disable_sync_clock(NULL);
+-		in_sync = -EAGAIN;
++		etr_sync.in_sync = -EAGAIN;
+ 		rc = -EAGAIN;
+ 	}
+ 	local_irq_enable();
+diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
+new file mode 100644
+index 0000000..12b39b3
+--- /dev/null
++++ b/arch/s390/kernel/topology.c
+@@ -0,0 +1,314 @@
++/*
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Heiko Carstens <heiko.carstens at de.ibm.com>
++ */
++
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/bootmem.h>
++#include <linux/sched.h>
++#include <linux/workqueue.h>
++#include <linux/cpu.h>
++#include <linux/smp.h>
++#include <asm/delay.h>
++#include <asm/s390_ext.h>
++#include <asm/sysinfo.h>
++
++#define CPU_BITS 64
++#define NR_MAG 6
++
++#define PTF_HORIZONTAL	(0UL)
++#define PTF_VERTICAL	(1UL)
++#define PTF_CHECK	(2UL)
++
++struct tl_cpu {
++	unsigned char reserved0[4];
++	unsigned char :6;
++	unsigned char pp:2;
++	unsigned char reserved1;
++	unsigned short origin;
++	unsigned long mask[CPU_BITS / BITS_PER_LONG];
++};
++
++struct tl_container {
++	unsigned char reserved[8];
++};
++
++union tl_entry {
++	unsigned char nl;
++	struct tl_cpu cpu;
++	struct tl_container container;
++};
++
++struct tl_info {
++	unsigned char reserved0[2];
++	unsigned short length;
++	unsigned char mag[NR_MAG];
++	unsigned char reserved1;
++	unsigned char mnest;
++	unsigned char reserved2[4];
++	union tl_entry tle[0];
++};
++
++struct core_info {
++	struct core_info *next;
++	cpumask_t mask;
++};
++
++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 int machine_has_topology_irq;
++static struct timer_list topology_timer;
++static void set_topology_timer(void);
++static DECLARE_WORK(topology_work, topology_work_fn);
++
++cpumask_t cpu_coregroup_map(unsigned int cpu)
++{
++	struct core_info *core = &core_info;
++	cpumask_t mask;
++
++	cpus_clear(mask);
++	if (!machine_has_topology)
++		return cpu_present_map;
++	mutex_lock(&smp_cpu_state_mutex);
++	while (core) {
++		if (cpu_isset(cpu, core->mask)) {
++			mask = core->mask;
++			break;
++		}
++		core = core->next;
++	}
++	mutex_unlock(&smp_cpu_state_mutex);
++	if (cpus_empty(mask))
++		mask = cpumask_of_cpu(cpu);
++	return mask;
++}
++
++static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
++{
++	unsigned int cpu;
++
++	for (cpu = find_first_bit(&tl_cpu->mask[0], CPU_BITS);
++	     cpu < CPU_BITS;
++	     cpu = find_next_bit(&tl_cpu->mask[0], CPU_BITS, cpu + 1))
++	{
++		unsigned int rcpu, lcpu;
++
++		rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin;
++		for_each_present_cpu(lcpu) {
++			if (__cpu_logical_map[lcpu] == rcpu) {
++				cpu_set(lcpu, core->mask);
++				smp_cpu_polarization[lcpu] = tl_cpu->pp;
++			}
++		}
++	}
++}
++
++static void clear_cores(void)
++{
++	struct core_info *core = &core_info;
++
++	while (core) {
++		cpus_clear(core->mask);
++		core = core->next;
++	}
++}
++
++static union tl_entry *next_tle(union tl_entry *tle)
++{
++	if (tle->nl)
++		return (union tl_entry *)((struct tl_container *)tle + 1);
++	else
++		return (union tl_entry *)((struct tl_cpu *)tle + 1);
++}
++
++static void tl_to_cores(struct tl_info *info)
++{
++	union tl_entry *tle, *end;
++	struct core_info *core = &core_info;
++
++	mutex_lock(&smp_cpu_state_mutex);
++	clear_cores();
++	tle = info->tle;
++	end = (union tl_entry *)((unsigned long)info + info->length);
++	while (tle < end) {
++		switch (tle->nl) {
++		case 5:
++		case 4:
++		case 3:
++		case 2:
++			break;
++		case 1:
++			core = core->next;
++			break;
++		case 0:
++			add_cpus_to_core(&tle->cpu, core);
++			break;
++		default:
++			clear_cores();
++			machine_has_topology = 0;
++			return;
++		}
++		tle = next_tle(tle);
++	}
++	mutex_unlock(&smp_cpu_state_mutex);
++}
++
++static void topology_update_polarization_simple(void)
++{
++	int cpu;
++
++	mutex_lock(&smp_cpu_state_mutex);
++	for_each_present_cpu(cpu)
++		smp_cpu_polarization[cpu] = POLARIZATION_HRZ;
++	mutex_unlock(&smp_cpu_state_mutex);
++}
++
++static int ptf(unsigned long fc)
++{
++	int rc;
++
++	asm volatile(
++		"	.insn	rre,0xb9a20000,%1,%1\n"
++		"	ipm	%0\n"
++		"	srl	%0,28\n"
++		: "=d" (rc)
++		: "d" (fc)  : "cc");
++	return rc;
++}
++
++int topology_set_cpu_management(int fc)
++{
++	int cpu;
++	int rc;
++
++	if (!machine_has_topology)
++		return -EOPNOTSUPP;
++	if (fc)
++		rc = ptf(PTF_VERTICAL);
++	else
++		rc = ptf(PTF_HORIZONTAL);
++	if (rc)
++		return -EBUSY;
++	for_each_present_cpu(cpu)
++		smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
++	return rc;
++}
++
++void arch_update_cpu_topology(void)
++{
++	struct tl_info *info = tl_info;
++	struct sys_device *sysdev;
++	int cpu;
++
++	if (!machine_has_topology) {
++		topology_update_polarization_simple();
++		return;
++	}
++	stsi(info, 15, 1, 2);
++	tl_to_cores(info);
++	for_each_online_cpu(cpu) {
++		sysdev = get_cpu_sysdev(cpu);
++		kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
++	}
++}
++
++static void topology_work_fn(struct work_struct *work)
++{
++	arch_reinit_sched_domains();
++}
++
++void topology_schedule_update(void)
++{
++	schedule_work(&topology_work);
++}
++
++static void topology_timer_fn(unsigned long ignored)
++{
++	if (ptf(PTF_CHECK))
++		topology_schedule_update();
++	set_topology_timer();
++}
++
++static void set_topology_timer(void)
++{
++	topology_timer.function = topology_timer_fn;
++	topology_timer.data = 0;
++	topology_timer.expires = jiffies + 60 * HZ;
++	add_timer(&topology_timer);
++}
++
++static void topology_interrupt(__u16 code)
++{
++	schedule_work(&topology_work);
++}
++
++static int __init init_topology_update(void)
++{
++	int rc;
++
++	if (!machine_has_topology) {
++		topology_update_polarization_simple();
++		return 0;
++	}
++	init_timer_deferrable(&topology_timer);
++	if (machine_has_topology_irq) {
++		rc = register_external_interrupt(0x2005, topology_interrupt);
++		if (rc)
++			return rc;
++		ctl_set_bit(0, 8);
++	}
++	else
++		set_topology_timer();
++	return 0;
++}
++__initcall(init_topology_update);
++
++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)
++		return;
++	if (!(facility_bits & (1ULL << 52)) || !(facility_bits & (1ULL << 61)))
++		return;
++	machine_has_topology = 1;
++
++	if (facility_bits & (1ULL << 51))
++		machine_has_topology_irq = 1;
++
++	tl_info = alloc_bootmem_pages(PAGE_SIZE);
++	if (!tl_info)
++		goto error;
++	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];
++
++	printk(KERN_INFO "CPU topology:");
++	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;
++	machine_has_topology_irq = 0;
++}
+diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
+index 60f728a..57b607b 100644
+--- a/arch/s390/kernel/traps.c
++++ b/arch/s390/kernel/traps.c
+@@ -42,11 +42,8 @@
+ #include <asm/s390_ext.h>
+ #include <asm/lowcore.h>
+ #include <asm/debug.h>
++#include "entry.h"
+ 
+-/* Called from entry.S only */
+-extern void handle_per_exception(struct pt_regs *regs);
+-
+-typedef void pgm_check_handler_t(struct pt_regs *, long);
+ pgm_check_handler_t *pgm_check_table[128];
+ 
+ #ifdef CONFIG_SYSCTL
+@@ -59,7 +56,6 @@ int sysctl_userprocess_debug = 0;
+ 
+ extern pgm_check_handler_t do_protection_exception;
+ extern pgm_check_handler_t do_dat_exception;
+-extern pgm_check_handler_t do_monitor_call;
+ extern pgm_check_handler_t do_asce_exception;
+ 
+ #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
+@@ -138,7 +134,6 @@ void show_trace(struct task_struct *task, unsigned long *stack)
+ 	else
+ 		__show_trace(sp, S390_lowcore.thread_info,
+ 			     S390_lowcore.thread_info + THREAD_SIZE);
+-	printk("\n");
+ 	if (!task)
+ 		task = current;
+ 	debug_show_held_locks(task);
+@@ -166,6 +161,15 @@ void show_stack(struct task_struct *task, unsigned long *sp)
+ 	show_trace(task, sp);
+ }
+ 
++#ifdef CONFIG_64BIT
++void show_last_breaking_event(struct pt_regs *regs)
++{
++	printk("Last Breaking-Event-Address:\n");
++	printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
++	print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
++}
++#endif
++
+ /*
+  * The architecture-independent dump_stack generator
+  */
+@@ -739,6 +743,5 @@ void __init trap_init(void)
+         pgm_check_table[0x15] = &operand_exception;
+         pgm_check_table[0x1C] = &space_switch_exception;
+         pgm_check_table[0x1D] = &hfp_sqrt_exception;
+-	pgm_check_table[0x40] = &do_monitor_call;
+ 	pfault_irq_init();
+ }
+diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
+index 70f2a86..eae21a8 100644
+--- a/arch/s390/lib/delay.c
++++ b/arch/s390/lib/delay.c
+@@ -34,7 +34,7 @@ void __delay(unsigned long loops)
+  */
+ void __udelay(unsigned long usecs)
+ {
+-	u64 end, time, jiffy_timer = 0;
++	u64 end, time, old_cc = 0;
+ 	unsigned long flags, cr0, mask, dummy;
+ 	int irq_context;
+ 
+@@ -43,8 +43,8 @@ void __udelay(unsigned long usecs)
+ 		local_bh_disable();
+ 	local_irq_save(flags);
+ 	if (raw_irqs_disabled_flags(flags)) {
+-		jiffy_timer = S390_lowcore.jiffy_timer;
+-		S390_lowcore.jiffy_timer = -1ULL - (4096 << 12);
++		old_cc = S390_lowcore.clock_comparator;
++		S390_lowcore.clock_comparator = -1ULL;
+ 		__ctl_store(cr0, 0, 0);
+ 		dummy = (cr0 & 0xffff00e0) | 0x00000800;
+ 		__ctl_load(dummy , 0, 0);
+@@ -55,8 +55,8 @@ void __udelay(unsigned long usecs)
+ 
+ 	end = get_clock() + ((u64) usecs << 12);
+ 	do {
+-		time = end < S390_lowcore.jiffy_timer ?
+-			end : S390_lowcore.jiffy_timer;
++		time = end < S390_lowcore.clock_comparator ?
++			end : S390_lowcore.clock_comparator;
+ 		set_clock_comparator(time);
+ 		trace_hardirqs_on();
+ 		__load_psw_mask(mask);
+@@ -65,10 +65,10 @@ void __udelay(unsigned long usecs)
+ 
+ 	if (raw_irqs_disabled_flags(flags)) {
+ 		__ctl_load(cr0, 0, 0);
+-		S390_lowcore.jiffy_timer = jiffy_timer;
++		S390_lowcore.clock_comparator = old_cc;
+ 	}
+ 	if (!irq_context)
+ 		_local_bh_enable();
+-	set_clock_comparator(S390_lowcore.jiffy_timer);
++	set_clock_comparator(S390_lowcore.clock_comparator);
+ 	local_irq_restore(flags);
+ }
+diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
+index 5efdfe9..d66215b 100644
+--- a/arch/s390/lib/uaccess_pt.c
++++ b/arch/s390/lib/uaccess_pt.c
+@@ -302,6 +302,10 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
+ 	pte_t *pte_from, *pte_to;
+ 	int write_user;
+ 
++	if (segment_eq(get_fs(), KERNEL_DS)) {
++		memcpy((void __force *) to, (void __force *) from, n);
++		return 0;
++	}
+ 	done = 0;
+ retry:
+ 	spin_lock(&mm->page_table_lock);
+@@ -361,18 +365,10 @@ fault:
+ 		     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
+ 		       "m" (*uaddr) : "cc" );
+ 
+-int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
++static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+ {
+ 	int oldval = 0, newval, ret;
+ 
+-	spin_lock(&current->mm->page_table_lock);
+-	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+-	if (!uaddr) {
+-		spin_unlock(&current->mm->page_table_lock);
+-		return -EFAULT;
+-	}
+-	get_page(virt_to_page(uaddr));
+-	spin_unlock(&current->mm->page_table_lock);
+ 	switch (op) {
+ 	case FUTEX_OP_SET:
+ 		__futex_atomic_op("lr %2,%5\n",
+@@ -397,17 +393,17 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+ 	default:
+ 		ret = -ENOSYS;
+ 	}
+-	put_page(virt_to_page(uaddr));
+-	*old = oldval;
++	if (ret == 0)
++		*old = oldval;
+ 	return ret;
+ }
+ 
+-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
++int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+ {
+ 	int ret;
+ 
+-	if (!current->mm)
+-		return -EFAULT;
++	if (segment_eq(get_fs(), KERNEL_DS))
++		return __futex_atomic_op_pt(op, uaddr, oparg, old);
+ 	spin_lock(&current->mm->page_table_lock);
+ 	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+ 	if (!uaddr) {
+@@ -416,13 +412,40 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+ 	}
+ 	get_page(virt_to_page(uaddr));
+ 	spin_unlock(&current->mm->page_table_lock);
+-	asm volatile("   cs   %1,%4,0(%5)\n"
+-		     "0: lr   %0,%1\n"
+-		     "1:\n"
+-		     EX_TABLE(0b,1b)
++	ret = __futex_atomic_op_pt(op, uaddr, oparg, old);
++	put_page(virt_to_page(uaddr));
++	return ret;
++}
++
++static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
++{
++	int ret;
++
++	asm volatile("0: cs   %1,%4,0(%5)\n"
++		     "1: lr   %0,%1\n"
++		     "2:\n"
++		     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+ 		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
+ 		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
+ 		     : "cc", "memory" );
++	return ret;
++}
++
++int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
++{
++	int ret;
++
++	if (segment_eq(get_fs(), KERNEL_DS))
++		return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
++	spin_lock(&current->mm->page_table_lock);
++	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
++	if (!uaddr) {
++		spin_unlock(&current->mm->page_table_lock);
++		return -EFAULT;
++	}
++	get_page(virt_to_page(uaddr));
++	spin_unlock(&current->mm->page_table_lock);
++	ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+ 	put_page(virt_to_page(uaddr));
+ 	return ret;
+ }
+diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
+index 880b0eb..ed2af0a 100644
+--- a/arch/s390/mm/extmem.c
++++ b/arch/s390/mm/extmem.c
+@@ -289,22 +289,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
+ 
+ 	rc = add_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+ 
+-	switch (rc) {
+-	case 0:
+-		break;
+-	case -ENOSPC:
+-		PRINT_WARN("segment_load: not loading segment %s - overlaps "
+-			   "storage/segment\n", name);
+-		goto out_free;
+-	case -ERANGE:
+-		PRINT_WARN("segment_load: not loading segment %s - exceeds "
+-			   "kernel mapping range\n", name);
+-		goto out_free;
+-	default:
+-		PRINT_WARN("segment_load: not loading segment %s (rc: %d)\n",
+-			   name, rc);
++	if (rc)
+ 		goto out_free;
+-	}
+ 
+ 	seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+ 	if (seg->res == NULL) {
+@@ -582,8 +568,59 @@ out:
+ 	mutex_unlock(&dcss_lock);
+ }
+ 
++/*
++ * print appropriate error message for segment_load()/segment_type()
++ * return code
++ */
++void segment_warning(int rc, char *seg_name)
++{
++	switch (rc) {
++	case -ENOENT:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "does not exist\n", seg_name);
++		break;
++	case -ENOSYS:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "not running on VM\n", seg_name);
++		break;
++	case -EIO:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "hardware error\n", seg_name);
++		break;
++	case -ENOTSUPP:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "is a multi-part segment\n", seg_name);
++		break;
++	case -ENOSPC:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "overlaps with storage\n", seg_name);
++		break;
++	case -EBUSY:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "overlaps with already loaded dcss\n", seg_name);
++		break;
++	case -EPERM:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "already loaded in incompatible mode\n", seg_name);
++		break;
++	case -ENOMEM:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "out of memory\n", seg_name);
++		break;
++	case -ERANGE:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "exceeds kernel mapping range\n", seg_name);
++		break;
++	default:
++		PRINT_WARN("cannot load/query segment %s, "
++			   "return value %i\n", seg_name, rc);
++		break;
++	}
++}
++
+ EXPORT_SYMBOL(segment_load);
+ EXPORT_SYMBOL(segment_unload);
+ EXPORT_SYMBOL(segment_save);
+ EXPORT_SYMBOL(segment_type);
+ EXPORT_SYMBOL(segment_modify_shared);
++EXPORT_SYMBOL(segment_warning);
+diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
+index ed13d42..2650f46 100644
+--- a/arch/s390/mm/fault.c
++++ b/arch/s390/mm/fault.c
+@@ -28,11 +28,11 @@
+ #include <linux/hardirq.h>
+ #include <linux/kprobes.h>
+ #include <linux/uaccess.h>
+-
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+ #include <asm/s390_ext.h>
+ #include <asm/mmu_context.h>
++#include "../kernel/entry.h"
+ 
+ #ifndef CONFIG_64BIT
+ #define __FAIL_ADDR_MASK 0x7ffff000
+@@ -50,8 +50,6 @@
+ extern int sysctl_userprocess_debug;
+ #endif
+ 
+-extern void die(const char *,struct pt_regs *,long);
+-
+ #ifdef CONFIG_KPROBES
+ static inline int notify_page_fault(struct pt_regs *regs, long err)
+ {
+@@ -245,11 +243,6 @@ static void do_sigbus(struct pt_regs *regs, unsigned long error_code,
+ }
+ 
+ #ifdef CONFIG_S390_EXEC_PROTECT
+-extern long sys_sigreturn(struct pt_regs *regs);
+-extern long sys_rt_sigreturn(struct pt_regs *regs);
+-extern long sys32_sigreturn(struct pt_regs *regs);
+-extern long sys32_rt_sigreturn(struct pt_regs *regs);
+-
+ static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
+ 			 unsigned long address, unsigned long error_code)
+ {
+@@ -270,15 +263,15 @@ static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
+ #ifdef CONFIG_COMPAT
+ 	compat = test_tsk_thread_flag(current, TIF_31BIT);
+ 	if (compat && instruction == 0x0a77)
+-		sys32_sigreturn(regs);
++		sys32_sigreturn();
+ 	else if (compat && instruction == 0x0aad)
+-		sys32_rt_sigreturn(regs);
++		sys32_rt_sigreturn();
+ 	else
+ #endif
+ 	if (instruction == 0x0a77)
+-		sys_sigreturn(regs);
++		sys_sigreturn();
+ 	else if (instruction == 0x0aad)
+-		sys_rt_sigreturn(regs);
++		sys_rt_sigreturn();
+ 	else {
+ 		current->thread.prot_addr = address;
+ 		current->thread.trap_no = error_code;
+@@ -424,7 +417,7 @@ no_context:
+ }
+ 
+ void __kprobes do_protection_exception(struct pt_regs *regs,
+-				       unsigned long error_code)
++				       long error_code)
+ {
+ 	/* Protection exception is supressing, decrement psw address. */
+ 	regs->psw.addr -= (error_code >> 16);
+@@ -440,7 +433,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs,
+ 	do_exception(regs, 4, 1);
+ }
+ 
+-void __kprobes do_dat_exception(struct pt_regs *regs, unsigned long error_code)
++void __kprobes do_dat_exception(struct pt_regs *regs, long error_code)
+ {
+ 	do_exception(regs, error_code & 0xff, 0);
+ }
+diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
+index 8053245..202c952 100644
+--- a/arch/s390/mm/init.c
++++ b/arch/s390/mm/init.c
+@@ -50,7 +50,6 @@ void show_mem(void)
+ 
+ 	printk("Mem-info:\n");
+ 	show_free_areas();
+-	printk("Free swap:       %6ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10));
+ 	i = max_mapnr;
+ 	while (i-- > 0) {
+ 		if (!pfn_valid(i))
+diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
+index 8d2cd1d..6a679c3 100644
+--- a/arch/sh/Kconfig
++++ b/arch/sh/Kconfig
+@@ -167,6 +167,12 @@ config CPU_SUBTYPE_SH7263
+ 	select CPU_SH2A
+ 	select CPU_HAS_FPU
+ 
++config CPU_SUBTYPE_MXG
++	bool "Support MX-G processor"
++	select CPU_SH2A
++	help
++	  Select MX-G if running on an R8A03022BG part.
++
+ # SH-3 Processor Support
+ 
+ config CPU_SUBTYPE_SH7705
+@@ -270,6 +276,15 @@ config CPU_SUBTYPE_SH4_202
+ 
+ # SH-4A Processor Support
+ 
++config CPU_SUBTYPE_SH7723
++	bool "Support SH7723 processor"
++	select CPU_SH4A
++	select CPU_SHX2
++	select ARCH_SPARSEMEM_ENABLE
++	select SYS_SUPPORTS_NUMA
++	help
++	  Select SH7723 if you have an SH-MobileR2 CPU.
++
+ config CPU_SUBTYPE_SH7763
+ 	bool "Support SH7763 processor"
+ 	select CPU_SH4A
+@@ -366,6 +381,14 @@ config SH_7619_SOLUTION_ENGINE
+ 	  Select 7619 SolutionEngine if configuring for a Hitachi SH7619
+ 	  evaluation board.
+ 	
++config SH_7721_SOLUTION_ENGINE
++	bool "SolutionEngine7721"
++	select SOLUTION_ENGINE
++	depends on CPU_SUBTYPE_SH7721
++	help
++	  Select 7721 SolutionEngine if configuring for a Hitachi SH7721
++	  evaluation board.
++
+ config SH_7722_SOLUTION_ENGINE
+ 	bool "SolutionEngine7722"
+ 	select SOLUTION_ENGINE
+@@ -560,7 +583,7 @@ config SH_TMU
+ config SH_CMT
+ 	def_bool y
+ 	prompt "CMT timer support"
+-	depends on CPU_SH2
++	depends on CPU_SH2 && !CPU_SUBTYPE_MXG
+ 	help
+ 	  This enables the use of the CMT as the system timer.
+ 
+@@ -578,6 +601,7 @@ config SH_TIMER_IRQ
+ 	default "86" if CPU_SUBTYPE_SH7619
+ 	default "140" if CPU_SUBTYPE_SH7206
+ 	default "142" if CPU_SUBTYPE_SH7203
++	default "238" if CPU_SUBTYPE_MXG
+ 	default "16"
+ 
+ config SH_PCLK_FREQ
+@@ -585,10 +609,10 @@ config SH_PCLK_FREQ
+ 	default "27000000" if CPU_SUBTYPE_SH7343
+ 	default "31250000" if CPU_SUBTYPE_SH7619
+ 	default "32000000" if CPU_SUBTYPE_SH7722
+-	default "33333333" if CPU_SUBTYPE_SH7770 || \
++	default "33333333" if CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7723 || \
+ 			      CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
+ 			      CPU_SUBTYPE_SH7203 || CPU_SUBTYPE_SH7206 || \
+-			      CPU_SUBTYPE_SH7263
++			      CPU_SUBTYPE_SH7263 || CPU_SUBTYPE_MXG
+ 	default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
+ 	default "66000000" if CPU_SUBTYPE_SH4_202
+ 	default "50000000"
+diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
+index 5dcb74b..d9d28f9 100644
+--- a/arch/sh/Kconfig.debug
++++ b/arch/sh/Kconfig.debug
+@@ -29,16 +29,17 @@ config EARLY_SCIF_CONSOLE
+ config EARLY_SCIF_CONSOLE_PORT
+ 	hex
+ 	depends on EARLY_SCIF_CONSOLE
+-	default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763
+-	default "0xffe00000" if CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366
+-	default "0xffea0000" if CPU_SUBTYPE_SH7785
+-	default "0xfffe8000" if CPU_SUBTYPE_SH7203
+-	default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
+-	default "0xf8420000" if CPU_SUBTYPE_SH7619
+ 	default "0xa4400000" if CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7705
+ 	default "0xa4430000" if CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721
++	default "0xf8420000" if CPU_SUBTYPE_SH7619
++	default "0xff804000" if CPU_SUBTYPE_MXG
+ 	default "0xffc30000" if CPU_SUBTYPE_SHX3
++	default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
++				CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366
+ 	default "0xffe80000" if CPU_SH4
++	default "0xffea0000" if CPU_SUBTYPE_SH7785
++	default "0xfffe8000" if CPU_SUBTYPE_SH7203
++	default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
+ 	default "0x00000000"
+ 
+ config EARLY_PRINTK
+diff --git a/arch/sh/Makefile b/arch/sh/Makefile
+index cffc92b..bb06f83 100644
+--- a/arch/sh/Makefile
++++ b/arch/sh/Makefile
+@@ -107,6 +107,7 @@ machdir-$(CONFIG_SH_7722_SOLUTION_ENGINE)	+= se/7722
+ machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)	+= se/7751
+ machdir-$(CONFIG_SH_7780_SOLUTION_ENGINE)	+= se/7780
+ machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)	+= se/7343
++machdir-$(CONFIG_SH_7721_SOLUTION_ENGINE)	+= se/7721
+ machdir-$(CONFIG_SH_HP6XX)			+= hp6xx
+ machdir-$(CONFIG_SH_DREAMCAST)			+= dreamcast
+ machdir-$(CONFIG_SH_MPC1211)			+= mpc1211
+diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c
+index 21ab8c8..00d52a2 100644
+--- a/arch/sh/boards/renesas/migor/setup.c
++++ b/arch/sh/boards/renesas/migor/setup.c
+@@ -10,8 +10,14 @@
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
+ #include <linux/interrupt.h>
++#include <linux/input.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mtd/nand.h>
++#include <linux/i2c.h>
+ #include <asm/machvec.h>
+ #include <asm/io.h>
++#include <asm/sh_keysc.h>
++#include <asm/migor.h>
+ 
+ /* Address     IRQ  Size  Bus  Description
+  * 0x00000000       64MB  16   NOR Flash (SP29PL256N)
+@@ -23,9 +29,9 @@
+ 
+ static struct resource smc91x_eth_resources[] = {
+ 	[0] = {
+-		.name   = "smc91x-regs" ,
+-		.start  = P2SEGADDR(0x10000300),
+-		.end    = P2SEGADDR(0x1000030f),
++		.name   = "SMC91C111" ,
++		.start  = 0x10000300,
++		.end    = 0x1000030f,
+ 		.flags  = IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+@@ -40,19 +46,202 @@ static struct platform_device smc91x_eth_device = {
+ 	.resource       = smc91x_eth_resources,
+ };
+ 
++static struct sh_keysc_info sh_keysc_info = {
++	.mode = SH_KEYSC_MODE_2, /* KEYOUT0->4, KEYIN1->5 */
++	.scan_timing = 3,
++	.delay = 5,
++	.keycodes = {
++		0, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER,
++		0, KEY_F, KEY_C, KEY_D,	KEY_H, KEY_1,
++		0, KEY_2, KEY_3, KEY_4,	KEY_5, KEY_6,
++		0, KEY_7, KEY_8, KEY_9, KEY_S, KEY_0,
++		0, KEY_P, KEY_STOP, KEY_REWIND, KEY_PLAY, KEY_FASTFORWARD,
++	},
++};
++
++static struct resource sh_keysc_resources[] = {
++	[0] = {
++		.start  = 0x044b0000,
++		.end    = 0x044b000f,
++		.flags  = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start  = 79,
++		.flags  = IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device sh_keysc_device = {
++	.name           = "sh_keysc",
++	.num_resources  = ARRAY_SIZE(sh_keysc_resources),
++	.resource       = sh_keysc_resources,
++	.dev	= {
++		.platform_data	= &sh_keysc_info,
++	},
++};
++
++static struct mtd_partition migor_nor_flash_partitions[] =
++{
++	{
++		.name = "uboot",
++		.offset = 0,
++		.size = (1 * 1024 * 1024),
++		.mask_flags = MTD_WRITEABLE,	/* Read-only */
++	},
++	{
++		.name = "rootfs",
++		.offset = MTDPART_OFS_APPEND,
++		.size = (15 * 1024 * 1024),
++	},
++	{
++		.name = "other",
++		.offset = MTDPART_OFS_APPEND,
++		.size = MTDPART_SIZ_FULL,
++	},
++};
++
++static struct physmap_flash_data migor_nor_flash_data = {
++	.width		= 2,
++	.parts		= migor_nor_flash_partitions,
++	.nr_parts	= ARRAY_SIZE(migor_nor_flash_partitions),
++};
++
++static struct resource migor_nor_flash_resources[] = {
++	[0] = {
++		.name		= "NOR Flash",
++		.start		= 0x00000000,
++		.end		= 0x03ffffff,
++		.flags		= IORESOURCE_MEM,
++	}
++};
++
++static struct platform_device migor_nor_flash_device = {
++	.name		= "physmap-flash",
++	.resource	= migor_nor_flash_resources,
++	.num_resources	= ARRAY_SIZE(migor_nor_flash_resources),
++	.dev		= {
++		.platform_data = &migor_nor_flash_data,
++	},
++};
++
++static struct mtd_partition migor_nand_flash_partitions[] = {
++	{
++		.name		= "nanddata1",
++		.offset		= 0x0,
++		.size		= 512 * 1024 * 1024,
++	},
++	{
++		.name		= "nanddata2",
++		.offset		= MTDPART_OFS_APPEND,
++		.size		= 512 * 1024 * 1024,
++	},
++};
++
++static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd,
++				     unsigned int ctrl)
++{
++	struct nand_chip *chip = mtd->priv;
++
++	if (cmd == NAND_CMD_NONE)
++		return;
++
++	if (ctrl & NAND_CLE)
++		writeb(cmd, chip->IO_ADDR_W + 0x00400000);
++	else if (ctrl & NAND_ALE)
++		writeb(cmd, chip->IO_ADDR_W + 0x00800000);
++	else
++		writeb(cmd, chip->IO_ADDR_W);
++}
++
++static int migor_nand_flash_ready(struct mtd_info *mtd)
++{
++	return ctrl_inb(PORT_PADR) & 0x02; /* PTA1 */
++}
++
++struct platform_nand_data migor_nand_flash_data = {
++	.chip = {
++		.nr_chips = 1,
++		.partitions = migor_nand_flash_partitions,
++		.nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions),
++		.chip_delay = 20,
++		.part_probe_types = (const char *[]) { "cmdlinepart", NULL },
++	},
++	.ctrl = {
++		.dev_ready = migor_nand_flash_ready,
++		.cmd_ctrl = migor_nand_flash_cmd_ctl,
++	},
++};
++
++static struct resource migor_nand_flash_resources[] = {
++	[0] = {
++		.name		= "NAND Flash",
++		.start		= 0x18000000,
++		.end		= 0x18ffffff,
++		.flags		= IORESOURCE_MEM,
++	},
++};
++
++static struct platform_device migor_nand_flash_device = {
++	.name		= "gen_nand",
++	.resource	= migor_nand_flash_resources,
++	.num_resources	= ARRAY_SIZE(migor_nand_flash_resources),
++	.dev		= {
++		.platform_data = &migor_nand_flash_data,
++	}
++};
++
+ static struct platform_device *migor_devices[] __initdata = {
+ 	&smc91x_eth_device,
++	&sh_keysc_device,
++	&migor_nor_flash_device,
++	&migor_nand_flash_device,
++};
++
++static struct i2c_board_info __initdata migor_i2c_devices[] = {
++	{
++		I2C_BOARD_INFO("rtc-rs5c372", 0x32),
++		.type   = "rs5c372b",
++	},
++	{
++		I2C_BOARD_INFO("migor_ts", 0x51),
++		.irq = 38, /* IRQ6 */
++	},
+ };
+ 
+ static int __init migor_devices_setup(void)
+ {
++	i2c_register_board_info(0, migor_i2c_devices,
++				ARRAY_SIZE(migor_i2c_devices));
++ 
+ 	return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
+ }
+ __initcall(migor_devices_setup);
+ 
+ static void __init migor_setup(char **cmdline_p)
+ {
+-	ctrl_outw(0x1000, 0xa4050110); /* Enable IRQ0 in PJCR */
++	/* SMC91C111 - Enable IRQ0 */
++	ctrl_outw(ctrl_inw(PORT_PJCR) & ~0x0003, PORT_PJCR);
++
++	/* KEYSC */
++	ctrl_outw(ctrl_inw(PORT_PYCR) & ~0x0fff, PORT_PYCR);
++	ctrl_outw(ctrl_inw(PORT_PZCR) & ~0x0ff0, PORT_PZCR);
++	ctrl_outw(ctrl_inw(PORT_PSELA) & ~0x4100, PORT_PSELA);
++	ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
++	ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
++	ctrl_outl(ctrl_inl(MSTPCR2) & ~0x00004000, MSTPCR2);
++
++	/* NAND Flash */
++	ctrl_outw(ctrl_inw(PORT_PXCR) & 0x0fff, PORT_PXCR);
++	ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x00000600) | 0x00000200,
++		  BSC_CS6ABCR);
++
++	/* I2C */
++	ctrl_outl(ctrl_inl(MSTPCR1) & ~0x00000200, MSTPCR1);
++
++	/* Touch Panel - Enable IRQ6 */
++	ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR);
++	ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA);
++	ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC);
+ }
+ 
+ static struct sh_machine_vector mv_migor __initmv = {
+diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c b/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c
+index 1f8f073..68f0ad1 100644
+--- a/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c
++++ b/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c
+@@ -18,31 +18,44 @@ enum {
+ 	UNUSED = 0,
+ 
+ 	/* board specific interrupt sources */
+-	AX88796,          /* Ethernet controller */
+-	CF,               /* Compact Flash */
+-	PSW,              /* Push Switch */
+-	EXT1,             /* EXT1n IRQ */
+-	EXT4,             /* EXT4n IRQ */
++	CF,		/* Compact Flash */
++	TP,		/* Touch panel */
++	SCIF1,		/* FPGA SCIF1 */
++	SCIF0,		/* FPGA SCIF0 */
++	SMBUS,		/* SMBUS */
++	RTC,		/* RTC Alarm */
++	AX88796,	/* Ethernet controller */
++	PSW,		/* Push Switch */
++
++	/* external bus connector */
++	EXT1, EXT2, EXT4, EXT5, EXT6,
+ };
+ 
+ static struct intc_vect vectors[] __initdata = {
+ 	INTC_IRQ(CF, IRQ_CF),
+-	INTC_IRQ(PSW, IRQ_PSW),
++	INTC_IRQ(TP, IRQ_TP),
++	INTC_IRQ(SCIF1, IRQ_SCIF1),
++	INTC_IRQ(SCIF0, IRQ_SCIF0),
++	INTC_IRQ(SMBUS, IRQ_SMBUS),
++	INTC_IRQ(RTC, IRQ_RTC),
+ 	INTC_IRQ(AX88796, IRQ_AX88796),
+-	INTC_IRQ(EXT1, IRQ_EXT1),
+-	INTC_IRQ(EXT4, IRQ_EXT4),
++	INTC_IRQ(PSW, IRQ_PSW),
++
++	INTC_IRQ(EXT1, IRQ_EXT1), INTC_IRQ(EXT2, IRQ_EXT2),
++	INTC_IRQ(EXT4, IRQ_EXT4), INTC_IRQ(EXT5, IRQ_EXT5),
++	INTC_IRQ(EXT6, IRQ_EXT6),
+ };
+ 
+ static struct intc_mask_reg mask_registers[] __initdata = {
+ 	{ 0xa4000000, 0, 16, /* IRLMSK */
+-	  { 0, 0, 0, 0, CF, 0, 0, 0,
+-	    0, 0, 0, EXT4, 0, EXT1, PSW, AX88796 } },
++	  { SCIF0, SCIF1, RTC, 0, CF, 0, TP, SMBUS,
++	    0, EXT6, EXT5, EXT4, EXT2, EXT1, PSW, AX88796 } },
+ };
+ 
+ static unsigned char irl2irq[HL_NR_IRL] __initdata = {
+-	0, IRQ_CF, 0, 0,
+-	0, 0, 0, 0,
+-	0, IRQ_EXT4, 0, IRQ_EXT1,
++	0, IRQ_CF, IRQ_TP, IRQ_SCIF1,
++	IRQ_SCIF0, IRQ_SMBUS, IRQ_RTC, IRQ_EXT6,
++	IRQ_EXT5, IRQ_EXT4, IRQ_EXT2, IRQ_EXT1,
+ 	0, IRQ_AX88796, IRQ_PSW,
+ };
+ 
+diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
+index 2f68bea..a5c5e92 100644
+--- a/arch/sh/boards/renesas/r7780rp/setup.c
++++ b/arch/sh/boards/renesas/r7780rp/setup.c
+@@ -4,7 +4,7 @@
+  * Renesas Solutions Highlander Support.
+  *
+  * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
+- * Copyright (C) 2005 - 2007 Paul Mundt
++ * Copyright (C) 2005 - 2008 Paul Mundt
+  *
+  * This contains support for the R7780RP-1, R7780MP, and R7785RP
+  * Highlander modules.
+@@ -17,6 +17,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/ata_platform.h>
+ #include <linux/types.h>
++#include <linux/i2c.h>
+ #include <net/ax88796.h>
+ #include <asm/machvec.h>
+ #include <asm/r7780rp.h>
+@@ -176,11 +177,38 @@ static struct platform_device ax88796_device = {
+ 	.resource       = ax88796_resources,
+ };
+ 
++static struct resource smbus_resources[] = {
++	[0] = {
++		.start	= PA_SMCR,
++		.end	= PA_SMCR + 0x100 - 1,
++		.flags	= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start	= IRQ_SMBUS,
++		.end	= IRQ_SMBUS,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device smbus_device = {
++	.name		= "i2c-highlander",
++	.id		= 0,
++	.num_resources	= ARRAY_SIZE(smbus_resources),
++	.resource	= smbus_resources,
++};
++
++static struct i2c_board_info __initdata highlander_i2c_devices[] = {
++	{
++		I2C_BOARD_INFO("rtc-rs5c372", 0x32),
++		.type	= "r2025sd",
++	},
++};
+ 
+ static struct platform_device *r7780rp_devices[] __initdata = {
+ 	&r8a66597_usb_host_device,
+ 	&m66592_usb_peripheral_device,
+ 	&heartbeat_device,
++	&smbus_device,
+ #ifndef CONFIG_SH_R7780RP
+ 	&ax88796_device,
+ #endif
+@@ -199,12 +227,20 @@ static struct trapped_io cf_trapped_io = {
+ 
+ static int __init r7780rp_devices_setup(void)
+ {
++	int ret = 0;
++
+ #ifndef CONFIG_SH_R7780RP
+ 	if (register_trapped_io(&cf_trapped_io) == 0)
+-		platform_device_register(&cf_ide_device);
++		ret |= platform_device_register(&cf_ide_device);
+ #endif
+-	return platform_add_devices(r7780rp_devices,
++
++	ret |= platform_add_devices(r7780rp_devices,
+ 				    ARRAY_SIZE(r7780rp_devices));
++
++	ret |= i2c_register_board_info(0, highlander_i2c_devices,
++				       ARRAY_SIZE(highlander_i2c_devices));
++
++	return ret;
+ }
+ device_initcall(r7780rp_devices_setup);
+ 
+diff --git a/arch/sh/boards/se/7721/Makefile b/arch/sh/boards/se/7721/Makefile
+new file mode 100644
+index 0000000..7f09030
+--- /dev/null
++++ b/arch/sh/boards/se/7721/Makefile
+@@ -0,0 +1 @@
++obj-y	 := setup.o irq.o
+diff --git a/arch/sh/boards/se/7721/irq.c b/arch/sh/boards/se/7721/irq.c
+new file mode 100644
+index 0000000..c4fdd62
+--- /dev/null
++++ b/arch/sh/boards/se/7721/irq.c
+@@ -0,0 +1,45 @@
++/*
++ * linux/arch/sh/boards/se/7721/irq.c
++ *
++ * Copyright (C) 2008  Renesas Solutions Corp.
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <asm/se7721.h>
++
++enum {
++	UNUSED = 0,
++
++	/* board specific interrupt sources */
++	MRSHPC,
++};
++
++static struct intc_vect vectors[] __initdata = {
++	INTC_IRQ(MRSHPC, MRSHPC_IRQ0),
++};
++
++static struct intc_prio_reg prio_registers[] __initdata = {
++	{ FPGA_ILSR6, 0, 8, 4, /* IRLMSK */
++	  { 0, MRSHPC } },
++};
++
++static DECLARE_INTC_DESC(intc_desc, "SE7721", vectors,
++			 NULL, NULL, prio_registers, NULL);
++
++/*
++ * Initialize IRQ setting
++ */
++void __init init_se7721_IRQ(void)
++{
++	/* PPCR */
++	ctrl_outw(ctrl_inw(0xa4050118) & ~0x00ff, 0xa4050118);
++
++	register_intc_controller(&intc_desc);
++	intc_set_priority(MRSHPC_IRQ0, 0xf - MRSHPC_IRQ0);
++}
+diff --git a/arch/sh/boards/se/7721/setup.c b/arch/sh/boards/se/7721/setup.c
+new file mode 100644
+index 0000000..1be3e92
+--- /dev/null
++++ b/arch/sh/boards/se/7721/setup.c
+@@ -0,0 +1,99 @@
++/*
++ * linux/arch/sh/boards/se/7721/setup.c
++ *
++ * Copyright (C) 2008 Renesas Solutions Corp.
++ *
++ * Hitachi UL SolutionEngine 7721 Support.
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ */
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <asm/machvec.h>
++#include <asm/se7721.h>
++#include <asm/io.h>
++#include <asm/heartbeat.h>
++
++static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
++
++static struct heartbeat_data heartbeat_data = {
++	.bit_pos	= heartbeat_bit_pos,
++	.nr_bits	= ARRAY_SIZE(heartbeat_bit_pos),
++	.regsize	= 16,
++};
++
++static struct resource heartbeat_resources[] = {
++	[0] = {
++		.start	= PA_LED,
++		.end	= PA_LED,
++		.flags	= IORESOURCE_MEM,
++	},
++};
++
++static struct platform_device heartbeat_device = {
++	.name		= "heartbeat",
++	.id		= -1,
++	.dev	= {
++		.platform_data	= &heartbeat_data,
++	},
++	.num_resources	= ARRAY_SIZE(heartbeat_resources),
++	.resource	= heartbeat_resources,
++};
++
++static struct resource cf_ide_resources[] = {
++	[0] = {
++		.start	= PA_MRSHPC_IO + 0x1f0,
++		.end	= PA_MRSHPC_IO + 0x1f0 + 8 ,
++		.flags	= IORESOURCE_IO,
++	},
++	[1] = {
++		.start	= PA_MRSHPC_IO + 0x1f0 + 0x206,
++		.end	= PA_MRSHPC_IO + 0x1f0 + 8 + 0x206 + 8,
++		.flags	= IORESOURCE_IO,
++	},
++	[2] = {
++		.start  = MRSHPC_IRQ0,
++		.flags  = IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device cf_ide_device = {
++	.name		= "pata_platform",
++	.id		= -1,
++	.num_resources	= ARRAY_SIZE(cf_ide_resources),
++	.resource	= cf_ide_resources,
++};
++
++static struct platform_device *se7721_devices[] __initdata = {
++	&cf_ide_device,
++	&heartbeat_device
++};
++
++static int __init se7721_devices_setup(void)
++{
++	return platform_add_devices(se7721_devices,
++		ARRAY_SIZE(se7721_devices));
++}
++device_initcall(se7721_devices_setup);
++
++static void __init se7721_setup(char **cmdline_p)
++{
++	/* for USB */
++	ctrl_outw(0x0000, 0xA405010C);	/* PGCR */
++	ctrl_outw(0x0000, 0xA405010E);	/* PHCR */
++	ctrl_outw(0x00AA, 0xA4050118);	/* PPCR */
++	ctrl_outw(0x0000, 0xA4050124);	/* PSELA */
++}
++
++/*
++ * The Machine Vector
++ */
++struct sh_machine_vector mv_se7721 __initmv = {
++	.mv_name		= "Solution Engine 7721",
++	.mv_setup		= se7721_setup,
++	.mv_nr_irqs		= 109,
++	.mv_init_irq		= init_se7721_IRQ,
++};
+diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
+index b1a3d9d..33f6ee7 100644
+--- a/arch/sh/boards/se/7722/setup.c
++++ b/arch/sh/boards/se/7722/setup.c
+@@ -13,10 +13,12 @@
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
+ #include <linux/ata_platform.h>
++#include <linux/input.h>
+ #include <asm/machvec.h>
+ #include <asm/se7722.h>
+ #include <asm/io.h>
+ #include <asm/heartbeat.h>
++#include <asm/sh_keysc.h>
+ 
+ /* Heartbeat */
+ static struct heartbeat_data heartbeat_data = {
+@@ -92,10 +94,47 @@ static struct platform_device cf_ide_device  = {
+ 	.resource       = cf_ide_resources,
+ };
+ 
++static struct sh_keysc_info sh_keysc_info = {
++	.mode = SH_KEYSC_MODE_1, /* KEYOUT0->5, KEYIN0->4 */
++	.scan_timing = 3,
++	.delay = 5,
++	.keycodes = { /* SW1 -> SW30 */
++		KEY_A, KEY_B, KEY_C, KEY_D, KEY_E,
++		KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
++		KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
++		KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
++		KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y,
++		KEY_Z,
++		KEY_HOME, KEY_SLEEP, KEY_WAKEUP, KEY_COFFEE, /* life */
++	},
++};
++
++static struct resource sh_keysc_resources[] = {
++	[0] = {
++		.start  = 0x044b0000,
++		.end    = 0x044b000f,
++		.flags  = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start  = 79,
++		.flags  = IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device sh_keysc_device = {
++	.name           = "sh_keysc",
++	.num_resources  = ARRAY_SIZE(sh_keysc_resources),
++	.resource       = sh_keysc_resources,
++	.dev	= {
++		.platform_data	= &sh_keysc_info,
++	},
++};
++
+ static struct platform_device *se7722_devices[] __initdata = {
+ 	&heartbeat_device,
+ 	&smc91x_eth_device,
+ 	&cf_ide_device,
++	&sh_keysc_device,
+ };
+ 
+ static int __init se7722_devices_setup(void)
+@@ -136,6 +175,8 @@ static void __init se7722_setup(char **cmdline_p)
+ 	ctrl_outw(0x0A10, PORT_PSELA); /* BS,SHHID2 */
+ 	ctrl_outw(0x0000, PORT_PYCR);
+ 	ctrl_outw(0x0000, PORT_PZCR);
++	ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
++	ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
+ }
+ 
+ /*
+diff --git a/arch/sh/configs/se7721_defconfig b/arch/sh/configs/se7721_defconfig
+new file mode 100644
+index 0000000..f3d4ca0
+--- /dev/null
++++ b/arch/sh/configs/se7721_defconfig
+@@ -0,0 +1,1085 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc5
++# Fri Mar 21 12:05:31 2008
++#
++CONFIG_SUPERH=y
++CONFIG_SUPERH32=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_ARCH_NO_VIRT_TO_BUS=y
++CONFIG_ARCH_SUPPORTS_AOUT=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++# CONFIG_BUG is not set
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_BASE_FULL is not set
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++# CONFIG_SHMEM is not set
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_HAVE_KPROBES is not set
++# CONFIG_HAVE_KRETPROBES is not set
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=1
++CONFIG_MODULES=y
++# CONFIG_MODULE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_CLASSIC_RCU=y
++
++#
++# System type
++#
++CONFIG_CPU_SH3=y
++# CONFIG_CPU_SUBTYPE_SH7619 is not set
++# CONFIG_CPU_SUBTYPE_SH7203 is not set
++# CONFIG_CPU_SUBTYPE_SH7206 is not set
++# CONFIG_CPU_SUBTYPE_SH7263 is not set
++# CONFIG_CPU_SUBTYPE_MXG is not set
++# CONFIG_CPU_SUBTYPE_SH7705 is not set
++# CONFIG_CPU_SUBTYPE_SH7706 is not set
++# CONFIG_CPU_SUBTYPE_SH7707 is not set
++# CONFIG_CPU_SUBTYPE_SH7708 is not set
++# CONFIG_CPU_SUBTYPE_SH7709 is not set
++# CONFIG_CPU_SUBTYPE_SH7710 is not set
++# CONFIG_CPU_SUBTYPE_SH7712 is not set
++# CONFIG_CPU_SUBTYPE_SH7720 is not set
++CONFIG_CPU_SUBTYPE_SH7721=y
++# CONFIG_CPU_SUBTYPE_SH7750 is not set
++# CONFIG_CPU_SUBTYPE_SH7091 is not set
++# CONFIG_CPU_SUBTYPE_SH7750R is not set
++# CONFIG_CPU_SUBTYPE_SH7750S is not set
++# CONFIG_CPU_SUBTYPE_SH7751 is not set
++# CONFIG_CPU_SUBTYPE_SH7751R is not set
++# CONFIG_CPU_SUBTYPE_SH7760 is not set
++# CONFIG_CPU_SUBTYPE_SH4_202 is not set
++# CONFIG_CPU_SUBTYPE_SH7763 is not set
++# CONFIG_CPU_SUBTYPE_SH7770 is not set
++# CONFIG_CPU_SUBTYPE_SH7780 is not set
++# CONFIG_CPU_SUBTYPE_SH7785 is not set
++# CONFIG_CPU_SUBTYPE_SHX3 is not set
++# CONFIG_CPU_SUBTYPE_SH7343 is not set
++# CONFIG_CPU_SUBTYPE_SH7722 is not set
++# CONFIG_CPU_SUBTYPE_SH7366 is not set
++# CONFIG_CPU_SUBTYPE_SH5_101 is not set
++# CONFIG_CPU_SUBTYPE_SH5_103 is not set
++
++#
++# Memory management options
++#
++CONFIG_QUICKLIST=y
++CONFIG_MMU=y
++CONFIG_PAGE_OFFSET=0x80000000
++CONFIG_MEMORY_START=0x0c000000
++CONFIG_MEMORY_SIZE=0x02000000
++CONFIG_29BIT=y
++CONFIG_VSYSCALL=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_SPARSEMEM_ENABLE=y
++CONFIG_ARCH_SPARSEMEM_DEFAULT=y
++CONFIG_MAX_ACTIVE_REGIONS=1
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_ARCH_SELECT_MEMORY_MODEL=y
++CONFIG_PAGE_SIZE_4KB=y
++# CONFIG_PAGE_SIZE_8KB is not set
++# CONFIG_PAGE_SIZE_64KB is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_SPARSEMEM_STATIC=y
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_NR_QUICK=2
++
++#
++# Cache configuration
++#
++# CONFIG_SH_DIRECT_MAPPED is not set
++CONFIG_CACHE_WRITEBACK=y
++# CONFIG_CACHE_WRITETHROUGH is not set
++# CONFIG_CACHE_OFF is not set
++
++#
++# Processor features
++#
++CONFIG_CPU_LITTLE_ENDIAN=y
++# CONFIG_CPU_BIG_ENDIAN is not set
++# CONFIG_SH_FPU_EMU is not set
++# CONFIG_SH_DSP is not set
++# CONFIG_SH_ADC is not set
++CONFIG_CPU_HAS_INTEVT=y
++CONFIG_CPU_HAS_SR_RB=y
++CONFIG_CPU_HAS_DSP=y
++
++#
++# Board support
++#
++CONFIG_SOLUTION_ENGINE=y
++CONFIG_SH_7721_SOLUTION_ENGINE=y
++
++#
++# Timer and clock configuration
++#
++CONFIG_SH_TMU=y
++CONFIG_SH_TIMER_IRQ=16
++CONFIG_SH_PCLK_FREQ=33333333
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# DMA support
++#
++# CONFIG_SH_DMA is not set
++
++#
++# Companion Chips
++#
++
++#
++# Additional SuperH Device Drivers
++#
++CONFIG_HEARTBEAT=y
++# CONFIG_PUSH_SWITCH is not set
++
++#
++# Kernel features
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++# CONFIG_KEXEC is not set
++# CONFIG_CRASH_DUMP is not set
++# CONFIG_PREEMPT_NONE is not set
++CONFIG_PREEMPT_VOLUNTARY=y
++# CONFIG_PREEMPT is not set
++CONFIG_GUSA=y
++# CONFIG_GUSA_RB is not set
++
++#
++# Boot options
++#
++CONFIG_ZERO_PAGE_OFFSET=0x00001000
++CONFIG_BOOT_LINK_OFFSET=0x00800000
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda2"
++
++#
++# Bus options
++#
++CONFIG_CF_ENABLER=y
++# CONFIG_CF_AREA5 is not set
++CONFIG_CF_AREA6=y
++CONFIG_CF_BASE_ADDR=0xb8000000
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_ASK_IP_FIB_HASH=y
++# CONFIG_IP_FIB_TRIE is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++CONFIG_IP_MROUTE=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++CONFIG_INET_AH=y
++CONFIG_INET_ESP=y
++CONFIG_INET_IPCOMP=y
++CONFIG_INET_XFRM_TUNNEL=y
++CONFIG_INET_TUNNEL=y
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++CONFIG_NET_SCHED=y
++
++#
++# Queueing/Scheduling
++#
++CONFIG_NET_SCH_CBQ=y
++CONFIG_NET_SCH_HTB=y
++CONFIG_NET_SCH_HFSC=y
++CONFIG_NET_SCH_PRIO=y
++# CONFIG_NET_SCH_RR is not set
++CONFIG_NET_SCH_RED=y
++CONFIG_NET_SCH_SFQ=y
++CONFIG_NET_SCH_TEQL=y
++CONFIG_NET_SCH_TBF=y
++CONFIG_NET_SCH_GRED=y
++CONFIG_NET_SCH_DSMARK=y
++CONFIG_NET_SCH_NETEM=y
++
++#
++# Classification
++#
++CONFIG_NET_CLS=y
++# CONFIG_NET_CLS_BASIC is not set
++CONFIG_NET_CLS_TCINDEX=y
++CONFIG_NET_CLS_ROUTE4=y
++CONFIG_NET_CLS_ROUTE=y
++CONFIG_NET_CLS_FW=y
++# CONFIG_NET_CLS_U32 is not set
++# CONFIG_NET_CLS_RSVP is not set
++# CONFIG_NET_CLS_RSVP6 is not set
++# CONFIG_NET_CLS_FLOW is not set
++# CONFIG_NET_EMATCH is not set
++# CONFIG_NET_CLS_ACT is not set
++CONFIG_NET_CLS_IND=y
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_MV is not set
++CONFIG_PATA_PLATFORM=y
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_SH_KEYSC is not set
++CONFIG_INPUT_MOUSE=y
++# CONFIG_MOUSE_PS2 is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_SH_SCI=y
++CONFIG_SERIAL_SH_SCI_NR_UARTS=2
++CONFIG_SERIAL_SH_SCI_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++# CONFIG_LEDS_TRIGGER_TIMER is not set
++# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_DNOTIFY is not set
++# CONFIG_INOTIFY is not set
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_KCORE is not set
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++# CONFIG_NETWORK_FILESYSTEMS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_DETECT_SOFTLOCKUP is not set
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_SH_STANDARD_BIOS is not set
++# CONFIG_EARLY_SCIF_CONSOLE is not set
++# CONFIG_DEBUG_BOOTMEM is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_4KSTACKS is not set
++# CONFIG_IRQSTACKS is not set
++# CONFIG_SH_KGDB is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_AEAD=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++CONFIG_CRYPTO_DEFLATE=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++CONFIG_CRYPTO_AUTHENC=y
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
+index 07e2950..a83dcf7 100644
+--- a/arch/sh/drivers/pci/pci-sh4.h
++++ b/arch/sh/drivers/pci/pci-sh4.h
+@@ -15,8 +15,6 @@
+ #define PCI_PROBE_BIOS		1
+ #define PCI_PROBE_CONF1		2
+ #define PCI_PROBE_CONF2		4
+-#define PCI_NO_SORT		0x100
+-#define PCI_BIOS_SORT		0x200
+ #define PCI_NO_CHECKS		0x400
+ #define PCI_ASSIGN_ROMS		0x1000
+ #define PCI_BIOS_IRQ_SCAN	0x2000
+diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
+index 62bf373..4bbdce3 100644
+--- a/arch/sh/kernel/Makefile_32
++++ b/arch/sh/kernel/Makefile_32
+@@ -5,7 +5,7 @@
+ extra-y	:= head_32.o init_task.o vmlinux.lds
+ 
+ obj-y	:= debugtraps.o io.o io_generic.o irq.o machvec.o process_32.o \
+-	   ptrace_32.o semaphore.o setup.o signal_32.o sys_sh.o sys_sh32.o \
++	   ptrace_32.o setup.o signal_32.o sys_sh.o sys_sh32.o \
+ 	   syscalls_32.o time_32.o topology.o traps.o traps_32.o
+ 
+ obj-y				+= cpu/ timers/
+diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64
+index e01283d..6edf53b 100644
+--- a/arch/sh/kernel/Makefile_64
++++ b/arch/sh/kernel/Makefile_64
+@@ -1,7 +1,7 @@
+ extra-y	:= head_64.o init_task.o vmlinux.lds
+ 
+ obj-y	:= debugtraps.o io.o io_generic.o irq.o machvec.o process_64.o \
+-	   ptrace_64.o semaphore.o setup.o signal_64.o sys_sh.o sys_sh64.o \
++	   ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \
+ 	   syscalls_64.o time_64.o topology.o traps.o traps_64.o
+ 
+ obj-y				+= cpu/ timers/
+diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
+index 1c3b996..01ff4d0 100644
+--- a/arch/sh/kernel/cf-enabler.c
++++ b/arch/sh/kernel/cf-enabler.c
+@@ -83,6 +83,8 @@ static int __init cf_init_default(void)
+ #include <asm/se.h>
+ #elif defined(CONFIG_SH_7722_SOLUTION_ENGINE)
+ #include <asm/se7722.h>
++#elif defined(CONFIG_SH_7721_SOLUTION_ENGINE)
++#include <asm/se7721.h>
+ #endif
+ 
+ /*
+@@ -99,7 +101,9 @@ static int __init cf_init_default(void)
+  * 0xB0600000 : I/O
+  */
+ 
+-#if defined(CONFIG_SH_SOLUTION_ENGINE) || defined(CONFIG_SH_7722_SOLUTION_ENGINE) 
++#if defined(CONFIG_SH_SOLUTION_ENGINE) || \
++    defined(CONFIG_SH_7722_SOLUTION_ENGINE) || \
++    defined(CONFIG_SH_7721_SOLUTION_ENGINE)
+ static int __init cf_init_se(void)
+ {
+ 	if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0)
+@@ -112,7 +116,7 @@ static int __init cf_init_se(void)
+ 	}
+ 
+ 	/*
+-	 *  PC-Card window open 
++	 *  PC-Card window open
+ 	 *  flag == COMMON/ATTRIBUTE/IO
+ 	 */
+ 	/* common window open */
+@@ -122,7 +126,7 @@ static int __init cf_init_se(void)
+ 		ctrl_outw(0x0b00, MRSHPC_MW0CR2);
+ 	else
+ 		/* common mode & bus width 16bit SWAP = 0*/
+-		ctrl_outw(0x0300, MRSHPC_MW0CR2); 
++		ctrl_outw(0x0300, MRSHPC_MW0CR2);
+ 
+ 	/* attribute window open */
+ 	ctrl_outw(0x8a85, MRSHPC_MW1CR1);
+@@ -155,10 +159,9 @@ static int __init cf_init_se(void)
+ 
+ int __init cf_init(void)
+ {
+-	if( mach_is_se() || mach_is_7722se() ){
++	if (mach_is_se() || mach_is_7722se() || mach_is_7721se())
+ 		return cf_init_se();
+-	}
+-	
++
+ 	return cf_init_default();
+ }
+ 
+diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
+index b279cdc..7e2b90c 100644
+--- a/arch/sh/kernel/cpu/sh2a/Makefile
++++ b/arch/sh/kernel/cpu/sh2a/Makefile
+@@ -8,6 +8,7 @@ common-y	+= $(addprefix ../sh2/, ex.o entry.o)
+ 
+ obj-$(CONFIG_SH_FPU)	+= fpu.o
+ 
+-obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
+-obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o
+-obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o
++obj-$(CONFIG_CPU_SUBTYPE_SH7206)	+= setup-sh7206.o clock-sh7206.o
++obj-$(CONFIG_CPU_SUBTYPE_SH7203)	+= setup-sh7203.o clock-sh7203.o
++obj-$(CONFIG_CPU_SUBTYPE_SH7263)	+= setup-sh7203.o clock-sh7203.o
++obj-$(CONFIG_CPU_SUBTYPE_MXG)		+= setup-mxg.o clock-sh7206.o
+diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
+index 6910e26..6e79132 100644
+--- a/arch/sh/kernel/cpu/sh2a/probe.c
++++ b/arch/sh/kernel/cpu/sh2a/probe.c
+@@ -29,6 +29,9 @@ int __init detect_cpu_and_cache_system(void)
+ 	boot_cpu_data.type			= CPU_SH7206;
+ 	/* While SH7206 has a DSP.. */
+ 	boot_cpu_data.flags			|= CPU_HAS_DSP;
++#elif defined(CONFIG_CPU_SUBTYPE_MXG)
++	boot_cpu_data.type			= CPU_MXG;
++	boot_cpu_data.flags			|= CPU_HAS_DSP;
+ #endif
+ 
+ 	boot_cpu_data.dcache.ways		= 4;
+diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+new file mode 100644
+index 0000000..e611d79
+--- /dev/null
++++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+@@ -0,0 +1,168 @@
++/*
++ * Renesas MX-G (R8A03022BG) Setup
++ *
++ *  Copyright (C) 2008  Paul Mundt
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/serial.h>
++#include <linux/serial_sci.h>
++
++enum {
++	UNUSED = 0,
++
++	/* interrupt sources */
++	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
++	IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15,
++
++	PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
++
++	SINT8, SINT7, SINT6, SINT5, SINT4, SINT3, SINT2, SINT1,
++
++	SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
++	SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
++
++	MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D,
++	MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F,
++	MTU2_TGI1A, MTU2_TGI1B, MTU2_TCI1V, MTU2_TCI1U,
++	MTU2_TGI2A, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U,
++	MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D, MTU2_TCI3V,
++	MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D, MTU2_TCI4V,
++	MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W,
++
++	/* interrupt groups */
++	PINT, SCIF0, SCIF1,
++	MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5
++};
++
++static struct intc_vect vectors[] __initdata = {
++	INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65),
++	INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67),
++	INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69),
++	INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71),
++	INTC_IRQ(IRQ8, 72), INTC_IRQ(IRQ9, 73),
++	INTC_IRQ(IRQ10, 74), INTC_IRQ(IRQ11, 75),
++	INTC_IRQ(IRQ12, 76), INTC_IRQ(IRQ13, 77),
++	INTC_IRQ(IRQ14, 78), INTC_IRQ(IRQ15, 79),
++
++	INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81),
++	INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83),
++	INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
++	INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
++
++	INTC_IRQ(SINT8, 94), INTC_IRQ(SINT7, 95),
++	INTC_IRQ(SINT6, 96), INTC_IRQ(SINT5, 97),
++	INTC_IRQ(SINT4, 98), INTC_IRQ(SINT3, 99),
++	INTC_IRQ(SINT2, 100), INTC_IRQ(SINT1, 101),
++
++	INTC_IRQ(SCIF0_RXI, 220), INTC_IRQ(SCIF0_TXI, 221),
++	INTC_IRQ(SCIF0_BRI, 222), INTC_IRQ(SCIF0_ERI, 223),
++	INTC_IRQ(SCIF1_RXI, 224), INTC_IRQ(SCIF1_TXI, 225),
++	INTC_IRQ(SCIF1_BRI, 226), INTC_IRQ(SCIF1_ERI, 227),
++
++	INTC_IRQ(MTU2_TGI0A, 228), INTC_IRQ(MTU2_TGI0B, 229),
++	INTC_IRQ(MTU2_TGI0C, 230), INTC_IRQ(MTU2_TGI0D, 231),
++	INTC_IRQ(MTU2_TCI0V, 232), INTC_IRQ(MTU2_TGI0E, 233),
++
++	INTC_IRQ(MTU2_TGI0F, 234), INTC_IRQ(MTU2_TGI1A, 235),
++	INTC_IRQ(MTU2_TGI1B, 236), INTC_IRQ(MTU2_TCI1V, 237),
++	INTC_IRQ(MTU2_TCI1U, 238), INTC_IRQ(MTU2_TGI2A, 239),
++
++	INTC_IRQ(MTU2_TGI2B, 240), INTC_IRQ(MTU2_TCI2V, 241),
++	INTC_IRQ(MTU2_TCI2U, 242), INTC_IRQ(MTU2_TGI3A, 243),
++
++	INTC_IRQ(MTU2_TGI3B, 244),
++	INTC_IRQ(MTU2_TGI3C, 245),
++
++	INTC_IRQ(MTU2_TGI3D, 246), INTC_IRQ(MTU2_TCI3V, 247),
++	INTC_IRQ(MTU2_TGI4A, 248), INTC_IRQ(MTU2_TGI4B, 249),
++	INTC_IRQ(MTU2_TGI4C, 250), INTC_IRQ(MTU2_TGI4D, 251),
++
++	INTC_IRQ(MTU2_TCI4V, 252), INTC_IRQ(MTU2_TGI5U, 253),
++	INTC_IRQ(MTU2_TGI5V, 254), INTC_IRQ(MTU2_TGI5W, 255),
++};
++
++static struct intc_group groups[] __initdata = {
++	INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
++		   PINT4, PINT5, PINT6, PINT7),
++	INTC_GROUP(MTU2_GROUP1, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D,
++		   MTU2_TCI0V, MTU2_TGI0E),
++	INTC_GROUP(MTU2_GROUP2, MTU2_TGI0F, MTU2_TGI1A, MTU2_TGI1B,
++		   MTU2_TCI1V, MTU2_TCI1U, MTU2_TGI2A),
++	INTC_GROUP(MTU2_GROUP3, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U,
++		   MTU2_TGI3A),
++	INTC_GROUP(MTU2_GROUP4, MTU2_TGI3D, MTU2_TCI3V, MTU2_TGI4A,
++		   MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D),
++	INTC_GROUP(MTU2_GROUP5, MTU2_TCI4V, MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W),
++	INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
++	INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
++};
++
++static struct intc_prio_reg prio_registers[] __initdata = {
++	{ 0xfffd9418, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
++	{ 0xfffd941a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } },
++	{ 0xfffd941c, 0, 16, 4, /* IPR03 */ { IRQ8, IRQ9, IRQ10, IRQ11 } },
++	{ 0xfffd941e, 0, 16, 4, /* IPR04 */ { IRQ12, IRQ13, IRQ14, IRQ15 } },
++	{ 0xfffd9420, 0, 16, 4, /* IPR05 */ { PINT, 0, 0, 0 } },
++	{ 0xfffd9800, 0, 16, 4, /* IPR06 */ { } },
++	{ 0xfffd9802, 0, 16, 4, /* IPR07 */ { } },
++	{ 0xfffd9804, 0, 16, 4, /* IPR08 */ { } },
++	{ 0xfffd9806, 0, 16, 4, /* IPR09 */ { } },
++	{ 0xfffd9808, 0, 16, 4, /* IPR10 */ { } },
++	{ 0xfffd980a, 0, 16, 4, /* IPR11 */ { } },
++	{ 0xfffd980c, 0, 16, 4, /* IPR12 */ { } },
++	{ 0xfffd980e, 0, 16, 4, /* IPR13 */ { } },
++	{ 0xfffd9810, 0, 16, 4, /* IPR14 */ { 0, 0, 0, SCIF0 } },
++	{ 0xfffd9812, 0, 16, 4, /* IPR15 */
++		{ SCIF1, MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3 } },
++	{ 0xfffd9814, 0, 16, 4, /* IPR16 */
++		{ MTU2_TGI3B, MTU2_TGI3C, MTU2_GROUP4, MTU2_GROUP5 } },
++};
++
++static struct intc_mask_reg mask_registers[] __initdata = {
++	{ 0xfffd9408, 0, 16, /* PINTER */
++	  { 0, 0, 0, 0, 0, 0, 0, 0,
++	    PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } },
++};
++
++static DECLARE_INTC_DESC(intc_desc, "mxg", vectors, groups,
++			 mask_registers, prio_registers, NULL);
++
++static struct plat_sci_port sci_platform_data[] = {
++	{
++		.mapbase	= 0xff804000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCIF,
++		.irqs		= { 223, 220, 221, 222 },
++	}, {
++		.flags = 0,
++	}
++};
++
++static struct platform_device sci_device = {
++	.name		= "sh-sci",
++	.id		= -1,
++	.dev		= {
++		.platform_data	= sci_platform_data,
++	},
++};
++
++static struct platform_device *mxg_devices[] __initdata = {
++	&sci_device,
++};
++
++static int __init mxg_devices_setup(void)
++{
++	return platform_add_devices(mxg_devices,
++				    ARRAY_SIZE(mxg_devices));
++}
++__initcall(mxg_devices_setup);
++
++void __init plat_irq_setup(void)
++{
++	register_intc_controller(&intc_desc);
++}
+diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
+index 9e89984..ebceb0d 100644
+--- a/arch/sh/kernel/cpu/sh4/probe.c
++++ b/arch/sh/kernel/cpu/sh4/probe.c
+@@ -53,7 +53,7 @@ int __init detect_cpu_and_cache_system(void)
+ 	/*
+ 	 * Setup some generic flags we can probe on SH-4A parts
+ 	 */
+-	if (((pvr >> 16) & 0xff) == 0x10) {
++	if (((pvr >> 24) & 0xff) == 0x10) {
+ 		if ((cvr & 0x10000000) == 0)
+ 			boot_cpu_data.flags |= CPU_HAS_DSP;
+ 
+@@ -126,17 +126,22 @@ int __init detect_cpu_and_cache_system(void)
+ 					  CPU_HAS_LLSC;
+ 		break;
+ 	case 0x3008:
+-		if (prr == 0xa0 || prr == 0xa1) {
+-			boot_cpu_data.type = CPU_SH7722;
+-			boot_cpu_data.icache.ways = 4;
+-			boot_cpu_data.dcache.ways = 4;
+-			boot_cpu_data.flags |= CPU_HAS_LLSC;
+-		}
+-		else if (prr == 0x70) {
++		boot_cpu_data.icache.ways = 4;
++		boot_cpu_data.dcache.ways = 4;
++		boot_cpu_data.flags |= CPU_HAS_LLSC;
++
++		switch (prr) {
++		case 0x50:
++			boot_cpu_data.type = CPU_SH7723;
++			boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_L2_CACHE;
++			break;
++		case 0x70:
+ 			boot_cpu_data.type = CPU_SH7366;
+-			boot_cpu_data.icache.ways = 4;
+-			boot_cpu_data.dcache.ways = 4;
+-			boot_cpu_data.flags |= CPU_HAS_LLSC;
++			break;
++		case 0xa0:
++		case 0xa1:
++			boot_cpu_data.type = CPU_SH7722;
++			break;
+ 		}
+ 		break;
+ 	case 0x4000:	/* 1st cut */
+@@ -215,6 +220,12 @@ int __init detect_cpu_and_cache_system(void)
+ 	 * SH-4A's have an optional PIPT L2.
+ 	 */
+ 	if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) {
++		/* Bug if we can't decode the L2 info */
++		BUG_ON(!(cvr & 0xf));
++
++		/* Silicon and specifications have clearly never met.. */
++		cvr ^= 0xf;
++
+ 		/*
+ 		 * Size calculation is much more sensible
+ 		 * than it is for the L1.
+diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
+index 5d890ac..a880e79 100644
+--- a/arch/sh/kernel/cpu/sh4a/Makefile
++++ b/arch/sh/kernel/cpu/sh4a/Makefile
+@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780)	+= setup-sh7780.o
+ obj-$(CONFIG_CPU_SUBTYPE_SH7785)	+= setup-sh7785.o
+ obj-$(CONFIG_CPU_SUBTYPE_SH7343)	+= setup-sh7343.o
+ obj-$(CONFIG_CPU_SUBTYPE_SH7722)	+= setup-sh7722.o
++obj-$(CONFIG_CPU_SUBTYPE_SH7723)	+= setup-sh7723.o
+ obj-$(CONFIG_CPU_SUBTYPE_SH7366)	+= setup-sh7366.o
+ obj-$(CONFIG_CPU_SUBTYPE_SHX3)		+= setup-shx3.o
+ 
+@@ -22,6 +23,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780)	:= clock-sh7780.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7785)	:= clock-sh7785.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7343.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7722.o
++clock-$(CONFIG_CPU_SUBTYPE_SH7723)	:= clock-sh7722.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7366)	:= clock-sh7722.o
+ clock-$(CONFIG_CPU_SUBTYPE_SHX3)	:= clock-shx3.o
+ 
+diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+index b98b4bc..0693140 100644
+--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
++++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+@@ -16,13 +16,12 @@
+ 
+ static struct resource usbf_resources[] = {
+ 	[0] = {
+-		.name	= "m66592_udc",
+-		.start	= 0xA4480000,
+-		.end	= 0xA44800FF,
++		.name	= "USBF",
++		.start	= 0x04480000,
++		.end	= 0x044800FF,
+ 		.flags	= IORESOURCE_MEM,
+ 	},
+ 	[1] = {
+-		.name	= "m66592_udc",
+ 		.start	= 65,
+ 		.end	= 65,
+ 		.flags	= IORESOURCE_IRQ,
+@@ -40,6 +39,26 @@ static struct platform_device usbf_device = {
+ 	.resource	= usbf_resources,
+ };
+ 
++static struct resource iic_resources[] = {
++	[0] = {
++		.name	= "IIC",
++		.start  = 0x04470000,
++		.end    = 0x04470017,
++		.flags  = IORESOURCE_MEM,
++	},
++	[1] = {
++		.start  = 96,
++		.end    = 99,
++		.flags  = IORESOURCE_IRQ,
++       },
++};
++
++static struct platform_device iic_device = {
++	.name           = "i2c-sh_mobile",
++	.num_resources  = ARRAY_SIZE(iic_resources),
++	.resource       = iic_resources,
++};
++
+ static struct plat_sci_port sci_platform_data[] = {
+ 	{
+ 		.mapbase	= 0xffe00000,
+@@ -74,6 +93,7 @@ static struct platform_device sci_device = {
+ 
+ static struct platform_device *sh7722_devices[] __initdata = {
+ 	&usbf_device,
++	&iic_device,
+ 	&sci_device,
+ };
+ 
+diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+new file mode 100644
+index 0000000..16925cf
+--- /dev/null
++++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+@@ -0,0 +1,300 @@
++/*
++ * SH7723 Setup
++ *
++ *  Copyright (C) 2008  Paul Mundt
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/serial.h>
++#include <linux/mm.h>
++#include <linux/serial_sci.h>
++#include <asm/mmzone.h>
++
++static struct plat_sci_port sci_platform_data[] = {
++	{
++		.mapbase	= 0xa4e30000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCI,
++		.irqs		= { 56, 56, 56, 56 },
++	},{
++		.mapbase	= 0xa4e40000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCI,
++		.irqs		= { 88, 88, 88, 88 },
++	},{
++		.mapbase	= 0xa4e50000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCI,
++		.irqs		= { 109, 109, 109, 109 },
++	}, {
++		.flags = 0,
++	}
++};
++
++static struct platform_device sci_device = {
++	.name		= "sh-sci",
++	.id		= -1,
++	.dev		= {
++		.platform_data	= sci_platform_data,
++	},
++};
++
++static struct resource rtc_resources[] = {
++	[0] = {
++		.start	= 0xa465fec0,
++		.end	= 0xa465fec0 + 0x58 - 1,
++		.flags	= IORESOURCE_IO,
++	},
++	[1] = {
++		/* Period IRQ */
++		.start	= 69,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[2] = {
++		/* Carry IRQ */
++		.start	= 70,
++		.flags	= IORESOURCE_IRQ,
++	},
++	[3] = {
++		/* Alarm IRQ */
++		.start	= 68,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device rtc_device = {
++	.name		= "sh-rtc",
++	.id		= -1,
++	.num_resources	= ARRAY_SIZE(rtc_resources),
++	.resource	= rtc_resources,
++};
++
++static struct platform_device *sh7723_devices[] __initdata = {
++	&sci_device,
++	&rtc_device,
++};
++
++static int __init sh7723_devices_setup(void)
++{
++	return platform_add_devices(sh7723_devices,
++				    ARRAY_SIZE(sh7723_devices));
++}
++__initcall(sh7723_devices_setup);
++
++enum {
++	UNUSED=0,
++
++	/* interrupt sources */
++	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
++	HUDI,
++	DMAC1A_DEI0,DMAC1A_DEI1,DMAC1A_DEI2,DMAC1A_DEI3,
++	_2DG_TRI,_2DG_INI,_2DG_CEI,
++	DMAC0A_DEI0,DMAC0A_DEI1,DMAC0A_DEI2,DMAC0A_DEI3,
++	VIO_CEUI,VIO_BEUI,VIO_VEU2HI,VIO_VOUI,
++	SCIFA_SCIFA0,
++	VPU_VPUI,
++	TPU_TPUI,
++	ADC_ADI,
++	USB_USI0,
++	RTC_ATI,RTC_PRI,RTC_CUI,
++	DMAC1B_DEI4,DMAC1B_DEI5,DMAC1B_DADERR,
++	DMAC0B_DEI4,DMAC0B_DEI5,DMAC0B_DADERR,
++	KEYSC_KEYI,
++	SCIF_SCIF0,SCIF_SCIF1,SCIF_SCIF2,
++	MSIOF_MSIOFI0,MSIOF_MSIOFI1,
++	SCIFA_SCIFA1,
++	FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I,
++	I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI,
++	SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2,
++	CMT_CMTI,
++	TSIF_TSIFI,
++	SIU_SIUI,
++	SCIFA_SCIFA2,
++	TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2,
++	IRDA_IRDAI,
++	ATAPI_ATAPII,
++	SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2,
++	VEU2H1_VEU2HI,
++	LCDC_LCDCI,
++	TMU1_TUNI0,TMU1_TUNI1,TMU1_TUNI2,
++
++	/* interrupt groups */
++	DMAC1A, DMAC0A, VIO, DMAC0B, FLCTL, I2C, _2DG,
++	SDHI1, RTC, DMAC1B, SDHI0,
++};
++
++static struct intc_vect vectors[] __initdata = {
++	INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
++	INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
++	INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
++	INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0),
++
++	INTC_VECT(DMAC1A_DEI0,0x700),
++	INTC_VECT(DMAC1A_DEI1,0x720),
++	INTC_VECT(DMAC1A_DEI2,0x740),
++	INTC_VECT(DMAC1A_DEI3,0x760),
++
++	INTC_VECT(_2DG_TRI, 0x780),
++	INTC_VECT(_2DG_INI, 0x7A0),
++	INTC_VECT(_2DG_CEI, 0x7C0),
++
++	INTC_VECT(DMAC0A_DEI0,0x800),
++	INTC_VECT(DMAC0A_DEI1,0x820),
++	INTC_VECT(DMAC0A_DEI2,0x840),
++	INTC_VECT(DMAC0A_DEI3,0x860),
++
++	INTC_VECT(VIO_CEUI,0x880),
++	INTC_VECT(VIO_BEUI,0x8A0),
++	INTC_VECT(VIO_VEU2HI,0x8C0),
++	INTC_VECT(VIO_VOUI,0x8E0),
++
++	INTC_VECT(SCIFA_SCIFA0,0x900),
++	INTC_VECT(VPU_VPUI,0x920),
++	INTC_VECT(TPU_TPUI,0x9A0),
++	INTC_VECT(ADC_ADI,0x9E0),
++	INTC_VECT(USB_USI0,0xA20),
++
++	INTC_VECT(RTC_ATI,0xA80),
++	INTC_VECT(RTC_PRI,0xAA0),
++	INTC_VECT(RTC_CUI,0xAC0),
++
++	INTC_VECT(DMAC1B_DEI4,0xB00),
++	INTC_VECT(DMAC1B_DEI5,0xB20),
++	INTC_VECT(DMAC1B_DADERR,0xB40),
++
++	INTC_VECT(DMAC0B_DEI4,0xB80),
++	INTC_VECT(DMAC0B_DEI5,0xBA0),
++	INTC_VECT(DMAC0B_DADERR,0xBC0),
++
++	INTC_VECT(KEYSC_KEYI,0xBE0),
++	INTC_VECT(SCIF_SCIF0,0xC00),
++	INTC_VECT(SCIF_SCIF1,0xC20),
++	INTC_VECT(SCIF_SCIF2,0xC40),
++	INTC_VECT(MSIOF_MSIOFI0,0xC80),
++	INTC_VECT(MSIOF_MSIOFI1,0xCA0),
++	INTC_VECT(SCIFA_SCIFA1,0xD00),
++
++	INTC_VECT(FLCTL_FLSTEI,0xD80),
++	INTC_VECT(FLCTL_FLTENDI,0xDA0),
++	INTC_VECT(FLCTL_FLTREQ0I,0xDC0),
++	INTC_VECT(FLCTL_FLTREQ1I,0xDE0),
++
++	INTC_VECT(I2C_ALI,0xE00),
++	INTC_VECT(I2C_TACKI,0xE20),
++	INTC_VECT(I2C_WAITI,0xE40),
++	INTC_VECT(I2C_DTEI,0xE60),
++
++	INTC_VECT(SDHI0_SDHII0,0xE80),
++	INTC_VECT(SDHI0_SDHII1,0xEA0),
++	INTC_VECT(SDHI0_SDHII2,0xEC0),
++
++	INTC_VECT(CMT_CMTI,0xF00),
++	INTC_VECT(TSIF_TSIFI,0xF20),
++	INTC_VECT(SIU_SIUI,0xF80),
++	INTC_VECT(SCIFA_SCIFA2,0xFA0),
++
++	INTC_VECT(TMU0_TUNI0,0x400),
++	INTC_VECT(TMU0_TUNI1,0x420),
++	INTC_VECT(TMU0_TUNI2,0x440),
++
++	INTC_VECT(IRDA_IRDAI,0x480),
++	INTC_VECT(ATAPI_ATAPII,0x4A0),
++
++	INTC_VECT(SDHI1_SDHII0,0x4E0),
++	INTC_VECT(SDHI1_SDHII1,0x500),
++	INTC_VECT(SDHI1_SDHII2,0x520),
++
++	INTC_VECT(VEU2H1_VEU2HI,0x560),
++	INTC_VECT(LCDC_LCDCI,0x580),
++
++	INTC_VECT(TMU1_TUNI0,0x920),
++	INTC_VECT(TMU1_TUNI1,0x940),
++	INTC_VECT(TMU1_TUNI2,0x960),
++
++};
++
++static struct intc_group groups[] __initdata = {
++	INTC_GROUP(DMAC1A,DMAC1A_DEI0,DMAC1A_DEI1,DMAC1A_DEI2,DMAC1A_DEI3),
++	INTC_GROUP(DMAC0A,DMAC0A_DEI0,DMAC0A_DEI1,DMAC0A_DEI2,DMAC0A_DEI3),
++	INTC_GROUP(VIO, VIO_CEUI,VIO_BEUI,VIO_VEU2HI,VIO_VOUI),
++	INTC_GROUP(DMAC0B, DMAC0B_DEI4,DMAC0B_DEI5,DMAC0B_DADERR),
++	INTC_GROUP(FLCTL,FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I),
++	INTC_GROUP(I2C,I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI),
++	INTC_GROUP(_2DG, _2DG_TRI,_2DG_INI,_2DG_CEI),
++	INTC_GROUP(SDHI1, SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2),
++	INTC_GROUP(RTC, RTC_ATI,RTC_PRI,RTC_CUI),
++	INTC_GROUP(DMAC1B, DMAC1B_DEI4,DMAC1B_DEI5,DMAC1B_DADERR),
++	INTC_GROUP(SDHI0,SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2),
++};
++
++static struct intc_mask_reg mask_registers[] __initdata = {
++	{ 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
++	  { 0,  TMU1_TUNI2,TMU1_TUNI1,TMU1_TUNI0,0,SDHI1_SDHII2,SDHI1_SDHII1,SDHI1_SDHII0} },
++	{ 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
++	  { VIO_VOUI, VIO_VEU2HI,VIO_BEUI,VIO_CEUI,DMAC0A_DEI3,DMAC0A_DEI2,DMAC0A_DEI1,DMAC0A_DEI0 } },
++	{ 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
++	  { 0, 0, 0, VPU_VPUI,0,0,0,SCIFA_SCIFA0 } },
++	{ 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */
++	  { DMAC1A_DEI3,DMAC1A_DEI2,DMAC1A_DEI1,DMAC1A_DEI0,0,0,0,IRDA_IRDAI } },
++	{ 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */
++	  { 0,TMU0_TUNI2,TMU0_TUNI1,TMU0_TUNI0,VEU2H1_VEU2HI,0,0,LCDC_LCDCI } },
++	{ 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */
++	  { KEYSC_KEYI,DMAC0B_DADERR,DMAC0B_DEI5,DMAC0B_DEI4,0,SCIF_SCIF2,SCIF_SCIF1,SCIF_SCIF0 } },
++	{ 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */
++	  { 0,0,0,SCIFA_SCIFA1,ADC_ADI,0,MSIOF_MSIOFI1,MSIOF_MSIOFI0 } },
++	{ 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */
++	  { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
++	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
++	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
++	  { 0,SDHI0_SDHII2,SDHI0_SDHII1,SDHI0_SDHII0,0,0,SCIFA_SCIFA2,SIU_SIUI } },
++	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
++	  { 0, 0, 0, CMT_CMTI, 0, 0, USB_USI0,0 } },
++	{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
++	  { 0, DMAC1B_DADERR,DMAC1B_DEI5,DMAC1B_DEI4,0,RTC_ATI,RTC_PRI,RTC_CUI } },
++	{ 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */
++	  { 0,_2DG_CEI,_2DG_INI,_2DG_TRI,0,TPU_TPUI,0,TSIF_TSIFI } },
++	{ 0xa40800b0, 0xa40800f0, 8, /* IMR12 / IMCR12 */
++	  { 0,0,0,0,0,0,0,ATAPI_ATAPII } },
++	{ 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */
++	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
++};
++
++static struct intc_prio_reg prio_registers[] __initdata = {
++	{ 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2, IRDA_IRDAI } },
++	{ 0xa4080004, 0, 16, 4, /* IPRB */ { VEU2H1_VEU2HI, LCDC_LCDCI, DMAC1A, 0} },
++	{ 0xa4080008, 0, 16, 4, /* IPRC */ { TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2, 0} },
++	{ 0xa408000c, 0, 16, 4, /* IPRD */ { } },
++	{ 0xa4080010, 0, 16, 4, /* IPRE */ { DMAC0A, VIO, SCIFA_SCIFA0, VPU_VPUI } },
++	{ 0xa4080014, 0, 16, 4, /* IPRF */ { KEYSC_KEYI, DMAC0B, USB_USI0, CMT_CMTI } },
++	{ 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF_SCIF0, SCIF_SCIF1, SCIF_SCIF2,0 } },
++	{ 0xa408001c, 0, 16, 4, /* IPRH */ { MSIOF_MSIOFI0,MSIOF_MSIOFI1, FLCTL, I2C } },
++	{ 0xa4080020, 0, 16, 4, /* IPRI */ { SCIFA_SCIFA1,0,TSIF_TSIFI,_2DG } },
++	{ 0xa4080024, 0, 16, 4, /* IPRJ */ { ADC_ADI,0,SIU_SIUI,SDHI1 } },
++	{ 0xa4080028, 0, 16, 4, /* IPRK */ { RTC,DMAC1B,0,SDHI0 } },
++	{ 0xa408002c, 0, 16, 4, /* IPRL */ { SCIFA_SCIFA2,0,TPU_TPUI,ATAPI_ATAPII } },
++	{ 0xa4140010, 0, 32, 4, /* INTPRI00 */
++	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
++};
++
++static struct intc_sense_reg sense_registers[] __initdata = {
++	{ 0xa414001c, 16, 2, /* ICR1 */
++	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
++};
++
++static DECLARE_INTC_DESC(intc_desc, "sh7723", vectors, groups,
++			 mask_registers, prio_registers, sense_registers);
++
++void __init plat_irq_setup(void)
++{
++	register_intc_controller(&intc_desc);
++}
++
++void __init plat_mem_setup(void)
++{
++	/* Register the URAM space as Node 1 */
++	setup_bootmem_node(1, 0x055f0000, 0x05610000);
++}
+diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+index 07c988d..ae2b222 100644
+--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
++++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+@@ -231,12 +231,6 @@ static struct intc_group groups[] __initdata = {
+ 	INTC_GROUP(GPIO, GPIO_CH0, GPIO_CH1, GPIO_CH2, GPIO_CH3),
+ };
+ 
+-static struct intc_prio priorities[] __initdata = {
+-	INTC_PRIO(SCIF0, 3),
+-	INTC_PRIO(SCIF1, 3),
+-	INTC_PRIO(SCIF2, 3),
+-};
+-
+ static struct intc_mask_reg mask_registers[] __initdata = {
+ 	{ 0xffd40038, 0xffd4003c, 32, /* INT2MSKR / INT2MSKCR */
+ 	  { 0, 0, 0, 0, 0, 0, GPIO, 0,
+@@ -270,11 +264,10 @@ static struct intc_prio_reg prio_registers[] __initdata = {
+ 	{ 0xffd400b4, 0, 32, 8, /* INT2PRI13 */ { 0, 0, STIF1, STIF0 } },
+ };
+ 
+-static DECLARE_INTC_DESC(intc_desc, "sh7763", vectors, groups, priorities,
++static DECLARE_INTC_DESC(intc_desc, "sh7763", vectors, groups,
+ 			 mask_registers, prio_registers, NULL);
+ 
+ /* Support for external interrupt pins in IRQ mode */
+-
+ static struct intc_vect irq_vectors[] __initdata = {
+ 	INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
+ 	INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300),
+@@ -302,7 +295,6 @@ static DECLARE_INTC_DESC(intc_irq_desc, "sh7763-irq", irq_vectors,
+ 			 irq_sense_registers);
+ 
+ /* External interrupt pins in IRL mode */
+-
+ static struct intc_vect irl_vectors[] __initdata = {
+ 	INTC_VECT(IRL_LLLL, 0x200), INTC_VECT(IRL_LLLH, 0x220),
+ 	INTC_VECT(IRL_LLHL, 0x240), INTC_VECT(IRL_LLHH, 0x260),
+diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+index b9cec48..b73578e 100644
+--- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
++++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+@@ -1,7 +1,7 @@
+ /*
+  * SH7770 Setup
+  *
+- *  Copyright (C) 2006  Paul Mundt
++ *  Copyright (C) 2006 - 2008  Paul Mundt
+  *
+  * This file is subject to the terms and conditions of the GNU General Public
+  * License.  See the file "COPYING" in the main directory of this archive
+@@ -29,6 +29,41 @@ static struct plat_sci_port sci_platform_data[] = {
+ 		.type		= PORT_SCIF,
+ 		.irqs		= { 63, 63, 63, 63 },
+ 	}, {
++		.mapbase	= 0xff926000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCIF,
++		.irqs		= { 64, 64, 64, 64 },
++	}, {
++		.mapbase	= 0xff927000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCIF,
++		.irqs		= { 65, 65, 65, 65 },
++	}, {
++		.mapbase	= 0xff928000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCIF,
++		.irqs		= { 66, 66, 66, 66 },
++	}, {
++		.mapbase	= 0xff929000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCIF,
++		.irqs		= { 67, 67, 67, 67 },
++	}, {
++		.mapbase	= 0xff92a000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCIF,
++		.irqs		= { 68, 68, 68, 68 },
++	}, {
++		.mapbase	= 0xff92b000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCIF,
++		.irqs		= { 69, 69, 69, 69 },
++	}, {
++		.mapbase	= 0xff92c000,
++		.flags		= UPF_BOOT_AUTOCONF,
++		.type		= PORT_SCIF,
++		.irqs		= { 70, 70, 70, 70 },
++	}, {
+ 		.flags = 0,
+ 	}
+ };
+diff --git a/arch/sh/kernel/semaphore.c b/arch/sh/kernel/semaphore.c
+deleted file mode 100644
+index 184119e..0000000
+--- a/arch/sh/kernel/semaphore.c
++++ /dev/null
+@@ -1,139 +0,0 @@
+-/*
+- * Just taken from alpha implementation.
+- * This can't work well, perhaps.
+- */
+-/*
+- *  Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/wait.h>
+-#include <linux/init.h>
+-#include <asm/semaphore.h>
+-#include <asm/semaphore-helper.h>
+-
+-DEFINE_SPINLOCK(semaphore_wake_lock);
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit.  ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore.  The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+-	wake_one_more(sem);
+-	wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function.  Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible.  This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return.  If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-#define DOWN_VAR				\
+-	struct task_struct *tsk = current;	\
+-	wait_queue_t wait;			\
+-	init_waitqueue_entry(&wait, tsk);
+-
+-#define DOWN_HEAD(task_state)						\
+-									\
+-									\
+-	tsk->state = (task_state);					\
+-	add_wait_queue(&sem->wait, &wait);				\
+-									\
+-	/*								\
+-	 * Ok, we're set up.  sem->count is known to be less than zero	\
+-	 * so we must wait.						\
+-	 *								\
+-	 * We can let go the lock for purposes of waiting.		\
+-	 * We re-acquire it after awaking so as to protect		\
+-	 * all semaphore operations.					\
+-	 *								\
+-	 * If "up()" is called before we call waking_non_zero() then	\
+-	 * we will catch it right away.  If it is called later then	\
+-	 * we will have to go through a wakeup cycle to catch it.	\
+-	 *								\
+-	 * Multiple waiters contend for the semaphore lock to see	\
+-	 * who gets to gate through and who has to wait some more.	\
+-	 */								\
+-	for (;;) {
+-
+-#define DOWN_TAIL(task_state)			\
+-		tsk->state = (task_state);	\
+-	}					\
+-	tsk->state = TASK_RUNNING;		\
+-	remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	DOWN_VAR
+-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+-	if (waking_non_zero(sem))
+-		break;
+-	schedule();
+-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-	DOWN_VAR
+-	DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+-	ret = waking_non_zero_interruptible(sem, tsk);
+-	if (ret)
+-	{
+-		if (ret == 1)
+-			/* ret != 0 only if we get interrupted -arca */
+-			ret = 0;
+-		break;
+-	}
+-	schedule();
+-	DOWN_TAIL(TASK_INTERRUPTIBLE)
+-	return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+-	return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
+index ff4f54a..284f66f 100644
+--- a/arch/sh/kernel/setup.c
++++ b/arch/sh/kernel/setup.c
+@@ -23,6 +23,8 @@
+ #include <linux/kexec.h>
+ #include <linux/module.h>
+ #include <linux/smp.h>
++#include <linux/err.h>
++#include <linux/debugfs.h>
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/page.h>
+@@ -333,6 +335,7 @@ static const char *cpu_name[] = {
+ 	[CPU_SH7343]	= "SH7343",	[CPU_SH7785]	= "SH7785",
+ 	[CPU_SH7722]	= "SH7722",	[CPU_SHX3]	= "SH-X3",
+ 	[CPU_SH5_101]	= "SH5-101",	[CPU_SH5_103]	= "SH5-103",
++	[CPU_MXG]	= "MX-G",	[CPU_SH7723]	= "SH7723",
+ 	[CPU_SH7366]	= "SH7366",	[CPU_SH_NONE]	= "Unknown"
+ };
+ 
+@@ -443,3 +446,15 @@ const struct seq_operations cpuinfo_op = {
+ 	.show	= show_cpuinfo,
+ };
+ #endif /* CONFIG_PROC_FS */
++
++struct dentry *sh_debugfs_root;
++
++static int __init sh_debugfs_init(void)
++{
++	sh_debugfs_root = debugfs_create_dir("sh", NULL);
++	if (IS_ERR(sh_debugfs_root))
++		return PTR_ERR(sh_debugfs_root);
++
++	return 0;
++}
++arch_initcall(sh_debugfs_init);
+diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c
+index 45bb333..6d40546 100644
+--- a/arch/sh/kernel/sh_ksyms_32.c
++++ b/arch/sh/kernel/sh_ksyms_32.c
+@@ -9,7 +9,6 @@
+ #include <linux/pci.h>
+ #include <linux/irq.h>
+ #include <asm/sections.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+@@ -48,12 +47,6 @@ EXPORT_SYMBOL(__copy_user);
+ EXPORT_SYMBOL(get_vm_area);
+ #endif
+ 
+-/* semaphore exports */
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down_trylock);
+-
+ EXPORT_SYMBOL(__udelay);
+ EXPORT_SYMBOL(__ndelay);
+ EXPORT_SYMBOL(__const_udelay);
+diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c
+index b6410ce..a310c97 100644
+--- a/arch/sh/kernel/sh_ksyms_64.c
++++ b/arch/sh/kernel/sh_ksyms_64.c
+@@ -16,7 +16,6 @@
+ #include <linux/in6.h>
+ #include <linux/interrupt.h>
+ #include <linux/screen_info.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+@@ -37,9 +36,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
+ EXPORT_SYMBOL(screen_info);
+ #endif
+ 
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__up);
+ EXPORT_SYMBOL(__put_user_asm_l);
+ EXPORT_SYMBOL(__get_user_asm_l);
+ EXPORT_SYMBOL(copy_page);
+diff --git a/arch/sh/lib/clear_page.S b/arch/sh/lib/clear_page.S
+index 3539123..8342bfb 100644
+--- a/arch/sh/lib/clear_page.S
++++ b/arch/sh/lib/clear_page.S
+@@ -27,11 +27,11 @@ ENTRY(clear_page)
+ 	mov	#0,r0
+ 	!
+ 1:
+-#if defined(CONFIG_CPU_SH3)
+-	mov.l	r0, at r4
+-#elif defined(CONFIG_CPU_SH4)
++#if defined(CONFIG_CPU_SH4)
+ 	movca.l	r0, at r4
+ 	mov	r4,r1
++#else
++	mov.l	r0, at r4
+ #endif
+ 	add	#32,r4
+ 	mov.l	r0, at -r4
+diff --git a/arch/sh/lib/copy_page.S b/arch/sh/lib/copy_page.S
+index e002b91..5d12e65 100644
+--- a/arch/sh/lib/copy_page.S
++++ b/arch/sh/lib/copy_page.S
+@@ -41,11 +41,11 @@ ENTRY(copy_page)
+ 	mov.l	@r11+,r5
+ 	mov.l	@r11+,r6
+ 	mov.l	@r11+,r7
+-#if defined(CONFIG_CPU_SH3)
+-	mov.l	r0, at r10
+-#elif defined(CONFIG_CPU_SH4)
++#if defined(CONFIG_CPU_SH4)
+ 	movca.l	r0, at r10
+ 	mov	r10,r0
++#else
++	mov.l	r0, at r10
+ #endif
+ 	add	#32,r10
+ 	mov.l	r7, at -r10
+diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
+index db6d950..c5b56d5 100644
+--- a/arch/sh/mm/cache-debugfs.c
++++ b/arch/sh/mm/cache-debugfs.c
+@@ -127,13 +127,13 @@ static int __init cache_debugfs_init(void)
+ {
+ 	struct dentry *dcache_dentry, *icache_dentry;
+ 
+-	dcache_dentry = debugfs_create_file("dcache", S_IRUSR, NULL,
++	dcache_dentry = debugfs_create_file("dcache", S_IRUSR, sh_debugfs_root,
+ 					    (unsigned int *)CACHE_TYPE_DCACHE,
+ 					    &cache_debugfs_fops);
+ 	if (IS_ERR(dcache_dentry))
+ 		return PTR_ERR(dcache_dentry);
+ 
+-	icache_dentry = debugfs_create_file("icache", S_IRUSR, NULL,
++	icache_dentry = debugfs_create_file("icache", S_IRUSR, sh_debugfs_root,
+ 					    (unsigned int *)CACHE_TYPE_ICACHE,
+ 					    &cache_debugfs_fops);
+ 	if (IS_ERR(icache_dentry)) {
+diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
+index ab81c60..0b0ec6e 100644
+--- a/arch/sh/mm/pmb.c
++++ b/arch/sh/mm/pmb.c
+@@ -393,7 +393,7 @@ static int __init pmb_debugfs_init(void)
+ 	struct dentry *dentry;
+ 
+ 	dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
+-				     NULL, NULL, &pmb_debugfs_fops);
++				     sh_debugfs_root, NULL, &pmb_debugfs_fops);
+ 	if (IS_ERR(dentry))
+ 		return PTR_ERR(dentry);
+ 
+diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
+index d63b93d..987c668 100644
+--- a/arch/sh/tools/mach-types
++++ b/arch/sh/tools/mach-types
+@@ -21,8 +21,9 @@ HD64465			HD64465
+ 7206SE			SH_7206_SOLUTION_ENGINE
+ 7343SE			SH_7343_SOLUTION_ENGINE
+ 7619SE			SH_7619_SOLUTION_ENGINE
+-7722SE			SH_7722_SOLUTION_ENGINE		
+-7751SE			SH_7751_SOLUTION_ENGINE		
++7721SE			SH_7721_SOLUTION_ENGINE
++7722SE			SH_7722_SOLUTION_ENGINE
++7751SE			SH_7751_SOLUTION_ENGINE
+ 7780SE			SH_7780_SOLUTION_ENGINE
+ 7751SYSTEMH		SH_7751_SYSTEMH
+ HP6XX			SH_HP6XX
+diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
+index c40343c..49590f8 100644
+--- a/arch/sparc/Kconfig
++++ b/arch/sparc/Kconfig
+@@ -27,9 +27,6 @@ config ARCH_NO_VIRT_TO_BUS
+ config OF
+ 	def_bool y
+ 
+-config ARCH_SUPPORTS_AOUT
+-	def_bool y
+-
+ config HZ
+ 	int
+ 	default 100
+@@ -257,15 +254,6 @@ config SPARC_LED
+ 
+ source "fs/Kconfig.binfmt"
+ 
+-config SUNOS_EMUL
+-	bool "SunOS binary emulation"
+-	help
+-	  This allows you to run most SunOS binaries.  If you want to do this,
+-	  say Y here and place appropriate files in /usr/gnemul/sunos. See
+-	  <http://www.ultralinux.org/faq.html> for more information.  If you
+-	  want to run SunOS binaries on an Ultra you must also say Y to
+-	  "Kernel support for 32-bit a.out binaries" above.
+-
+ source "mm/Kconfig"
+ 
+ endmenu
+diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
+index f7a5091..6a2c57a 100644
+--- a/arch/sparc/defconfig
++++ b/arch/sparc/defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.23-rc1
+-# Wed Jul 25 15:30:21 2007
++# Linux kernel version: 2.6.25
++# Sun Apr 20 01:49:51 2008
+ #
+ CONFIG_MMU=y
+ CONFIG_HIGHMEM=y
+@@ -9,18 +9,15 @@ CONFIG_ZONE_DMA=y
+ CONFIG_GENERIC_ISA_DMA=y
+ CONFIG_ARCH_NO_VIRT_TO_BUS=y
+ CONFIG_OF=y
++CONFIG_HZ=100
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+ 
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+@@ -29,12 +26,23 @@ CONFIG_SYSVIPC_SYSCTL=y
+ CONFIG_POSIX_MQUEUE=y
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_USER_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
+ CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_RT_GROUP_SCHED=y
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+@@ -49,6 +57,7 @@ CONFIG_HOTPLUG=y
+ CONFIG_PRINTK=y
+ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
+ CONFIG_ANON_INODES=y
+@@ -61,6 +70,13 @@ CONFIG_VM_EVENT_COUNTERS=y
+ CONFIG_SLAB=y
+ # CONFIG_SLUB is not set
+ # CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_HAVE_KPROBES is not set
++# CONFIG_HAVE_KRETPROBES is not set
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+@@ -88,6 +104,7 @@ CONFIG_IOSCHED_CFQ=y
+ CONFIG_DEFAULT_CFQ=y
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
+ 
+ #
+ # General machine setup
+@@ -113,14 +130,13 @@ CONFIG_SUN_PM=y
+ CONFIG_PCI=y
+ CONFIG_PCI_SYSCALL=y
+ # CONFIG_ARCH_SUPPORTS_MSI is not set
++CONFIG_PCI_LEGACY=y
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_NO_DMA is not set
+ CONFIG_SUN_OPENPROMFS=m
+ # CONFIG_SPARC_LED is not set
+ CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_AOUT=y
+ CONFIG_BINFMT_MISC=m
+-CONFIG_SUNOS_EMUL=y
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+ # CONFIG_DISCONTIGMEM_MANUAL is not set
+@@ -128,6 +144,7 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4
+ # CONFIG_RESOURCES_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=1
+@@ -148,6 +165,7 @@ CONFIG_XFRM=y
+ CONFIG_XFRM_USER=m
+ # CONFIG_XFRM_SUB_POLICY is not set
+ # CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
+ CONFIG_NET_KEY=m
+ # CONFIG_NET_KEY_MIGRATE is not set
+ CONFIG_INET=y
+@@ -170,6 +188,7 @@ CONFIG_INET_TUNNEL=y
+ CONFIG_INET_XFRM_MODE_TRANSPORT=y
+ CONFIG_INET_XFRM_MODE_TUNNEL=y
+ CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+@@ -191,8 +210,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
+ CONFIG_INET6_XFRM_MODE_BEET=m
+ # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+ CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
+ CONFIG_IPV6_TUNNEL=m
+ # CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+ # CONFIG_IP_DCCP is not set
+@@ -214,10 +235,6 @@ CONFIG_SCTP_HMAC_MD5=y
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+ 
+ #
+@@ -225,6 +242,7 @@ CONFIG_SCTP_HMAC_MD5=y
+ #
+ CONFIG_NET_PKTGEN=m
+ # CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
+ CONFIG_AF_RXRPC=m
+@@ -248,6 +266,7 @@ CONFIG_AF_RXRPC=m
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+@@ -271,7 +290,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=4096
+-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_BLK_DEV_XIP is not set
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
+ CONFIG_MISC_DEVICES=y
+@@ -279,6 +298,8 @@ CONFIG_MISC_DEVICES=y
+ # CONFIG_EEPROM_93CX6 is not set
+ # CONFIG_SGI_IOC4 is not set
+ # CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
+ # CONFIG_IDE is not set
+ 
+ #
+@@ -318,6 +339,7 @@ CONFIG_SCSI_SPI_ATTRS=y
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
+ CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+@@ -338,6 +360,7 @@ CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_SCSI_IPS is not set
+ # CONFIG_SCSI_INITIO is not set
+ # CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
+ # CONFIG_SCSI_STEX is not set
+ # CONFIG_SCSI_SYM53C8XX_2 is not set
+ # CONFIG_SCSI_QLOGIC_1280 is not set
+@@ -353,14 +376,7 @@ CONFIG_SCSI_SUNESP=y
+ # CONFIG_SCSI_SRP is not set
+ # CONFIG_ATA is not set
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+ # CONFIG_FUSION is not set
+-# CONFIG_FUSION_SPI is not set
+-# CONFIG_FUSION_FC is not set
+-# CONFIG_FUSION_SAS is not set
+ 
+ #
+ # IEEE 1394 (FireWire) support
+@@ -375,6 +391,7 @@ CONFIG_DUMMY=m
+ # CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ CONFIG_TUN=m
++# CONFIG_VETH is not set
+ # CONFIG_ARCNET is not set
+ # CONFIG_PHYLIB is not set
+ CONFIG_NET_ETHERNET=y
+@@ -388,11 +405,20 @@ CONFIG_SUNQE=m
+ # CONFIG_NET_VENDOR_3COM is not set
+ # CONFIG_NET_TULIP is not set
+ # CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+ # CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
+ CONFIG_NETDEV_1000=y
+ # CONFIG_ACENIC is not set
+ # CONFIG_DL2K is not set
+ # CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
+ # CONFIG_MYRI_SBUS is not set
+ # CONFIG_NS83820 is not set
+ # CONFIG_HAMACHI is not set
+@@ -409,11 +435,15 @@ CONFIG_NETDEV_1000=y
+ CONFIG_NETDEV_10000=y
+ # CONFIG_CHELSIO_T1 is not set
+ # CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
+ # CONFIG_IXGB is not set
+ # CONFIG_S2IO is not set
+ # CONFIG_MYRI10GE is not set
+ # CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
+ # CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
+ # CONFIG_TR is not set
+ 
+ #
+@@ -421,13 +451,13 @@ CONFIG_NETDEV_10000=y
+ #
+ # CONFIG_WLAN_PRE80211 is not set
+ # CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
+ # CONFIG_WAN is not set
+ # CONFIG_FDDI is not set
+ # CONFIG_HIPPI is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+ # CONFIG_NET_FC is not set
+-# CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+@@ -449,7 +479,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ CONFIG_INPUT_JOYDEV=m
+-# CONFIG_INPUT_TSDEV is not set
+ CONFIG_INPUT_EVDEV=m
+ CONFIG_INPUT_EVBUG=m
+ 
+@@ -498,6 +527,7 @@ CONFIG_VT_CONSOLE=y
+ CONFIG_HW_CONSOLE=y
+ # CONFIG_VT_HW_CONSOLE_BINDING is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
+ 
+ #
+ # Serial drivers
+@@ -519,7 +549,6 @@ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+ # CONFIG_IPMI_HANDLER is not set
+-# CONFIG_WATCHDOG is not set
+ CONFIG_HW_RANDOM=m
+ CONFIG_JS_RTC=m
+ # CONFIG_R3964 is not set
+@@ -538,9 +567,9 @@ CONFIG_DEVPORT=y
+ # CONFIG_POWER_SUPPLY is not set
+ CONFIG_HWMON=y
+ # CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_ABITUGURU is not set
+-# CONFIG_SENSORS_ABITUGURU3 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
+ # CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
+ # CONFIG_SENSORS_IT87 is not set
+ # CONFIG_SENSORS_PC87360 is not set
+ # CONFIG_SENSORS_PC87427 is not set
+@@ -553,6 +582,14 @@ CONFIG_HWMON=y
+ # CONFIG_SENSORS_W83627HF is not set
+ # CONFIG_SENSORS_W83627EHF is not set
+ # CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+ 
+ #
+ # Multifunction device drivers
+@@ -569,15 +606,15 @@ CONFIG_HWMON=y
+ #
+ # Graphics support
+ #
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
+ # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+ 
+ #
+ # Display device support
+ #
+ # CONFIG_DISPLAY_SUPPORT is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+ 
+ #
+ # Console display driver support
+@@ -592,6 +629,7 @@ CONFIG_DUMMY_CONSOLE=y
+ CONFIG_HID_SUPPORT=y
+ CONFIG_HID=y
+ # CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
+ CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+@@ -601,34 +639,14 @@ CONFIG_USB_ARCH_HAS_EHCI=y
+ #
+ # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+ #
+-
+-#
+-# USB Gadget Support
+-#
+ # CONFIG_USB_GADGET is not set
+ # CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
+ # CONFIG_NEW_LEDS is not set
+ # CONFIG_INFINIBAND is not set
+-
+-#
+-# Real Time Clock
+-#
+ # CONFIG_RTC_CLASS is not set
+ 
+ #
+-# DMA Engine support
+-#
+-# CONFIG_DMA_ENGINE is not set
+-
+-#
+-# DMA Clients
+-#
+-
+-#
+-# DMA Devices
+-#
+-
+-#
+ # Userspace I/O
+ #
+ # CONFIG_UIO is not set
+@@ -664,18 +682,14 @@ CONFIG_FS_MBCACHE=y
+ CONFIG_FS_POSIX_ACL=y
+ CONFIG_XFS_FS=m
+ CONFIG_XFS_QUOTA=y
+-CONFIG_XFS_SECURITY=y
+ CONFIG_XFS_POSIX_ACL=y
+ CONFIG_XFS_RT=y
+-# CONFIG_GFS2_FS is not set
+ # CONFIG_OCFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-CONFIG_ROMFS_FS=m
++CONFIG_DNOTIFY=y
+ CONFIG_INOTIFY=y
+ CONFIG_INOTIFY_USER=y
+ # CONFIG_QUOTA is not set
+ CONFIG_QUOTACTL=y
+-CONFIG_DNOTIFY=y
+ CONFIG_AUTOFS_FS=m
+ CONFIG_AUTOFS4_FS=m
+ # CONFIG_FUSE_FS is not set
+@@ -704,7 +718,6 @@ CONFIG_PROC_SYSCTL=y
+ CONFIG_SYSFS=y
+ # CONFIG_TMPFS is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+ 
+ #
+@@ -721,14 +734,13 @@ CONFIG_BEFS_FS=m
+ # CONFIG_EFS_FS is not set
+ # CONFIG_CRAMFS is not set
+ # CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
+ # CONFIG_HPFS_FS is not set
+ # CONFIG_QNX4FS_FS is not set
++CONFIG_ROMFS_FS=m
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ # CONFIG_NFS_V3 is not set
+ # CONFIG_NFS_V4 is not set
+@@ -760,10 +772,6 @@ CONFIG_AFS_FS=m
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+ CONFIG_SUN_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ # CONFIG_NLS_CODEPAGE_437 is not set
+@@ -804,21 +812,14 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+-
+-#
+-# Distributed Lock Manager
+-#
+ # CONFIG_DLM is not set
+ 
+ #
+-# Instrumentation Support
+-#
+-# CONFIG_PROFILING is not set
+-
+-#
+ # Kernel hacking
+ #
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ # CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
+ CONFIG_ENABLE_MUST_CHECK=y
+ CONFIG_MAGIC_SYSRQ=y
+ # CONFIG_UNUSED_SYMBOLS is not set
+@@ -842,9 +843,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
+-CONFIG_FORCED_INLINING=y
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
+ # CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ # CONFIG_DEBUG_STACK_USAGE is not set
+ 
+ #
+@@ -853,9 +857,12 @@ CONFIG_FORCED_INLINING=y
+ CONFIG_KEYS=y
+ # CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+ # CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ CONFIG_CRYPTO=y
+ CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_AEAD=y
+ CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
+ CONFIG_CRYPTO_HASH=y
+ CONFIG_CRYPTO_MANAGER=y
+ CONFIG_CRYPTO_HMAC=y
+@@ -873,6 +880,10 @@ CONFIG_CRYPTO_ECB=m
+ CONFIG_CRYPTO_CBC=y
+ CONFIG_CRYPTO_PCBC=m
+ # CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
+ # CONFIG_CRYPTO_CRYPTD is not set
+ CONFIG_CRYPTO_DES=y
+ # CONFIG_CRYPTO_FCRYPT is not set
+@@ -887,11 +898,15 @@ CONFIG_CRYPTO_CAST6=m
+ CONFIG_CRYPTO_ARC4=m
+ # CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
+ CONFIG_CRYPTO_DEFLATE=y
+ CONFIG_CRYPTO_MICHAEL_MIC=m
+ CONFIG_CRYPTO_CRC32C=m
+ # CONFIG_CRYPTO_CAMELLIA is not set
+ # CONFIG_CRYPTO_TEST is not set
++CONFIG_CRYPTO_AUTHENC=y
++# CONFIG_CRYPTO_LZO is not set
+ # CONFIG_CRYPTO_HW is not set
+ 
+ #
+diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
+index bf1b15d..59700aa 100644
+--- a/arch/sparc/kernel/Makefile
++++ b/arch/sparc/kernel/Makefile
+@@ -9,10 +9,10 @@ EXTRA_AFLAGS	:= -ansi
+ IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o sun4d_irq.o
+ obj-y    := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \
+ 	    process.o signal.o ioport.o setup.o idprom.o \
+-	    sys_sparc.o sunos_asm.o systbls.o \
+-	    time.o windows.o cpu.o devices.o sclow.o \
+-	    tadpole.o tick14.o ptrace.o sys_solaris.o \
+-	    unaligned.o una_asm.o muldiv.o semaphore.o \
++	    sys_sparc.o systbls.o \
++	    time.o windows.o cpu.o devices.o \
++	    tadpole.o tick14.o ptrace.o \
++	    unaligned.o una_asm.o muldiv.o \
+ 	    prom.o of_device.o devres.o
+ 
+ devres-y = ../../../kernel/irq/devres.o
+@@ -25,7 +25,3 @@ obj-$(CONFIG_PCI) += ebus.o
+ obj-$(CONFIG_SUN_PM) += apc.o pmc.o
+ obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o
+ obj-$(CONFIG_SPARC_LED) += led.o
+-
+-ifdef CONFIG_SUNOS_EMUL
+-obj-y += sys_sunos.o sunos_ioctl.o
+-endif
+diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
+index c2eed8f..484c83d 100644
+--- a/arch/sparc/kernel/entry.S
++++ b/arch/sparc/kernel/entry.S
+@@ -1186,36 +1186,6 @@ srmmu_fault:
+ 
+ 	RESTORE_ALL
+ 
+-#ifdef CONFIG_SUNOS_EMUL
+-	/* SunOS uses syscall zero as the 'indirect syscall' it looks
+-	 * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
+-	 * This is complete brain damage.
+-	 */
+-	.globl	sunos_indir
+-sunos_indir:
+-	mov	%o7, %l4
+-	cmp	%o0, NR_SYSCALLS
+-	blu,a	1f
+-	 sll	%o0, 0x2, %o0
+-
+-	sethi	%hi(sunos_nosys), %l6
+-	b	2f
+-	 or	%l6, %lo(sunos_nosys), %l6
+-
+-1:
+-	set	sunos_sys_table, %l7
+-	ld	[%l7 + %o0], %l6
+-
+-2:	
+-	mov	%o1, %o0
+-	mov	%o2, %o1
+-	mov	%o3, %o2
+-	mov	%o4, %o3
+-	mov	%o5, %o4
+-	call	%l6
+-	 mov	%l4, %o7
+-#endif
+-
+ 	.align	4
+ 	.globl	sys_nis_syscall
+ sys_nis_syscall:
+@@ -1232,6 +1202,16 @@ sys_execve:
+ 	call	sparc_execve
+ 	 mov	%l5, %o7
+ 
++	.globl	sunos_execv
++sunos_execv:
++	st	%g0, [%sp + STACKFRAME_SZ + PT_I2]
++
++	call	sparc_execve
++	 add	%sp, STACKFRAME_SZ, %o0
++
++	b	ret_sys_call
++	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
++
+ 	.align	4
+ 	.globl	sys_pipe
+ sys_pipe:
+@@ -1394,7 +1374,7 @@ ret_from_fork:
+ 	b	ret_sys_call
+ 	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
+ 
+-	/* Linux native and SunOS system calls enter here... */
++	/* Linux native system calls enter here... */
+ 	.align	4
+ 	.globl	linux_sparc_syscall
+ linux_sparc_syscall:
+@@ -1429,7 +1409,6 @@ syscall_is_too_hard:
+ 
+ 	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+ 
+-	.globl	ret_sys_call
+ ret_sys_call:
+ 	ld	[%curptr + TI_FLAGS], %l6
+ 	cmp	%o0, -ERESTART_RESTARTBLOCK
+@@ -1472,170 +1451,6 @@ linux_syscall_trace2:
+ 	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
+ 
+ 
+-	/*
+-	 * Solaris system calls and indirect system calls enter here.
+-         *
+-	 * I have named the solaris indirect syscalls like that because
+-	 * it seems like Solaris has some fast path syscalls that can
+-	 * be handled as indirect system calls. - mig
+-	 */
+-
+-linux_syscall_for_solaris:
+-	sethi	%hi(sys_call_table), %l7
+-	b	linux_sparc_syscall
+-	 or	%l7, %lo(sys_call_table), %l7
+-	
+-	.align	4
+-	.globl	solaris_syscall
+-solaris_syscall:
+-	cmp	%g1,59
+-	be	linux_syscall_for_solaris
+-	 cmp	%g1,2
+-	be	linux_syscall_for_solaris
+-	 cmp    %g1,42
+-	be      linux_syscall_for_solaris
+-	 cmp	%g1,119
+-	be,a	linux_syscall_for_solaris
+-	 mov	2, %g1
+-1:	
+-	SAVE_ALL_HEAD
+-	 rd	%wim, %l3
+-
+-	wr	%l0, PSR_ET, %psr
+-	nop
+-	nop
+-	mov	%i0, %l5
+-
+-	call	do_solaris_syscall
+-	 add	%sp, STACKFRAME_SZ, %o0
+-
+-	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+-	set	PSR_C, %g2
+-	cmp	%o0, -ERESTART_RESTARTBLOCK
+-	bgeu	1f
+-	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %g3
+-
+-	/* System call success, clear Carry condition code. */		
+-	andn	%g3, %g2, %g3
+-	clr	%l6
+-	b	2f
+-	 st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]	
+-
+-1:
+-	/* System call failure, set Carry condition code.
+-	 * Also, get abs(errno) to return to the process.
+-	 */
+-	sub	%g0, %o0, %o0
+-	mov	1, %l6
+-	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+-	or	%g3, %g2, %g3
+-	st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]
+-
+-	/* Advance the pc and npc over the trap instruction.
+-	 * If the npc is unaligned (has a 1 in the lower byte), it means
+-	 * the kernel does not want us to play magic (ie, skipping over
+-	 * traps).  Mainly when the Solaris code wants to set some PC and
+-	 * nPC (setcontext).
+-	 */
+-2:
+-	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1	/* pc  = npc   */
+-	andcc	%l1, 1, %g0
+-	bne	1f
+-	 add	%l1, 0x4, %l2			/* npc = npc+4 */
+-	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
+-	b	ret_trap_entry
+-	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
+-
+-	/* kernel knows what it is doing, fixup npc and continue */
+-1:
+-	sub	%l1, 1, %l1
+- 	b	ret_trap_entry	
+-	 st	%l1, [%sp + STACKFRAME_SZ + PT_NPC]
+-
+-#ifndef CONFIG_SUNOS_EMUL
+-	.align	4
+-	.globl	sunos_syscall
+-sunos_syscall:
+-	SAVE_ALL_HEAD
+-	 rd	%wim, %l3
+-	wr	%l0, PSR_ET, %psr
+-	nop
+-	nop
+-	mov	%i0, %l5
+-	call	do_sunos_syscall
+-	 add	%sp, STACKFRAME_SZ, %o0
+-#endif
+-
+-	/* {net, open}bsd system calls enter here... */
+-	.align	4
+-	.globl	bsd_syscall
+-bsd_syscall:
+-	/* Direct access to user regs, must faster. */
+-	cmp	%g1, NR_SYSCALLS
+-	blu,a	1f
+-	 sll	%g1, 2, %l4
+-
+-	set	sys_ni_syscall, %l7
+-	b	bsd_is_too_hard
+-	 nop
+-
+-1:
+-	ld	[%l7 + %l4], %l7
+-
+-	.globl	bsd_is_too_hard
+-bsd_is_too_hard:
+-	rd	%wim, %l3
+-	SAVE_ALL
+-
+-	wr	%l0, PSR_ET, %psr
+-	WRITE_PAUSE
+-
+-2:
+-	mov	%i0, %o0
+-	mov	%i1, %o1
+-	mov	%i2, %o2
+-	mov	%i0, %l5
+-	mov	%i3, %o3
+-	mov	%i4, %o4
+-	call	%l7
+-	 mov	%i5, %o5
+-
+-	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+-	set	PSR_C, %g2
+-	cmp	%o0, -ERESTART_RESTARTBLOCK
+-	bgeu	1f
+-	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %g3
+-
+-	/* System call success, clear Carry condition code. */		
+-	andn	%g3, %g2, %g3
+-	clr	%l6
+-	b	2f
+-	 st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]	
+-
+-1:
+-	/* System call failure, set Carry condition code.
+-	 * Also, get abs(errno) to return to the process.
+-	 */
+-	sub	%g0, %o0, %o0
+-#if 0 /* XXX todo XXX */
+-	sethi	%hi(bsd_xlatb_rorl), %o3
+-	or	%o3, %lo(bsd_xlatb_rorl), %o3
+-	sll	%o0, 2, %o0
+-	ld	[%o3 + %o0], %o0
+-#endif
+-	mov	1, %l6
+-	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+-	or	%g3, %g2, %g3
+-	st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]
+-
+-	/* Advance the pc and npc over the trap instruction. */
+-2:
+-	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1	/* pc  = npc   */
+-	add	%l1, 0x4, %l2			/* npc = npc+4 */
+-	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
+-	b	ret_trap_entry
+-	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
+-
+ /* Saving and restoring the FPU state is best done from lowlevel code.
+  *
+  * void fpsave(unsigned long *fpregs, unsigned long *fsr,
+diff --git a/arch/sparc/kernel/errtbls.c b/arch/sparc/kernel/errtbls.c
+deleted file mode 100644
+index ed14df7..0000000
+--- a/arch/sparc/kernel/errtbls.c
++++ /dev/null
+@@ -1,144 +0,0 @@
+-/* errtbls.c: Error number conversion tables.
+- *
+- * Copyright (C) 1995, 2007 David S. Miller (davem at davemloft.net)
+- *
+- * Based upon preliminary work which is:
+- *
+- * Copyright (C) 1995 Adrian M. Rodriguez (adrian at remus.rutgers.edu)
+- */
+-
+-#include <asm/solerrno.h>        /* Solaris errnos */
+-
+-/* Here is the table which converts between Linux error number values
+- * to the equivalent under Solaris.  Note that since the Linux ones
+- * have been set up to match exactly those of SunOS, no translation
+- * table is needed for that OS.
+- */
+-
+-int solaris_errno[] = {
+-	0,
+-	SOL_EPERM,
+-	SOL_ENOENT,
+-	SOL_ESRCH,
+-	SOL_EINTR,
+-	SOL_EIO,
+-	SOL_ENXIO,
+-	SOL_E2BIG,
+-	SOL_ENOEXEC,
+-	SOL_EBADF,
+-	SOL_ECHILD,
+-	SOL_EAGAIN,
+-	SOL_ENOMEM,
+-	SOL_EACCES,
+-	SOL_EFAULT,
+-	SOL_NOTBLK,
+-	SOL_EBUSY,
+-	SOL_EEXIST,
+-	SOL_EXDEV,
+-	SOL_ENODEV,
+-	SOL_ENOTDIR,
+-	SOL_EISDIR,
+-	SOL_EINVAL,
+-	SOL_ENFILE,
+-	SOL_EMFILE,
+-	SOL_ENOTTY,
+-	SOL_ETXTBSY,
+-	SOL_EFBIG,
+-	SOL_ENOSPC,
+-	SOL_ESPIPE,
+-	SOL_EROFS,
+-	SOL_EMLINK,
+-	SOL_EPIPE,
+-	SOL_EDOM,
+-	SOL_ERANGE,
+-	SOL_EWOULDBLOCK,
+-	SOL_EINPROGRESS,
+-	SOL_EALREADY,
+-	SOL_ENOTSOCK,
+-	SOL_EDESTADDRREQ,
+-	SOL_EMSGSIZE,
+-	SOL_EPROTOTYPE,
+-	SOL_ENOPROTOOPT,
+-	SOL_EPROTONOSUPPORT,
+-	SOL_ESOCKTNOSUPPORT,
+-	SOL_EOPNOTSUPP,
+-	SOL_EPFNOSUPPORT,
+-	SOL_EAFNOSUPPORT,
+-	SOL_EADDRINUSE,
+-	SOL_EADDRNOTAVAIL,
+-	SOL_ENETDOWN,
+-	SOL_ENETUNREACH,
+-	SOL_ENETRESET,
+-	SOL_ECONNABORTED,
+-	SOL_ECONNRESET,
+-	SOL_ENOBUFS,
+-	SOL_EISCONN,
+-	SOL_ENOTONN,
+-	SOL_ESHUTDOWN,
+-	SOL_ETOOMANYREFS,
+-	SOL_ETIMEDOUT,
+-	SOL_ECONNREFUSED,
+-	SOL_ELOOP,
+-	SOL_ENAMETOOLONG,
+-	SOL_EHOSTDOWN,
+-	SOL_EHOSTUNREACH,
+-	SOL_ENOTEMPTY,
+-	SOL_EPROCLIM,
+-	SOL_EUSERS,
+-	SOL_EDQUOT,
+-	SOL_ESTALE,
+-	SOL_EREMOTE,
+-	SOL_ENOSTR,
+-	SOL_ETIME,
+-	SOL_ENOSR,
+-	SOL_ENOMSG,
+-	SOL_EBADMSG,
+-	SOL_IDRM,
+-	SOL_EDEADLK,
+-	SOL_ENOLCK,
+-	SOL_ENONET,
+-	SOL_ERREMOTE,
+-	SOL_ENOLINK,
+-	SOL_EADV,
+-	SOL_ESRMNT,
+-	SOL_ECOMM,
+-	SOL_EPROTO,
+-	SOL_EMULTIHOP,
+-	SOL_EINVAL,    /* EDOTDOT XXX??? */
+-	SOL_REMCHG,
+-	SOL_NOSYS,
+-	SOL_STRPIPE,
+-	SOL_EOVERFLOW,
+-	SOL_EBADFD,
+-	SOL_ECHRNG,
+-	SOL_EL2NSYNC,
+-	SOL_EL3HLT,
+-	SOL_EL3RST,
+-	SOL_NRNG,
+-	SOL_EUNATCH,
+-	SOL_ENOCSI,
+-	SOL_EL2HLT,
+-	SOL_EBADE,
+-	SOL_EBADR,
+-	SOL_EXFULL,
+-	SOL_ENOANO,
+-	SOL_EBADRQC,
+-	SOL_EBADSLT,
+-	SOL_EDEADLOCK,
+-	SOL_EBFONT,
+-	SOL_ELIBEXEC,
+-	SOL_ENODATA,
+-	SOL_ELIBBAD,
+-	SOL_ENOPKG,
+-	SOL_ELIBACC,
+-	SOL_ENOTUNIQ,
+-	SOL_ERESTART,
+-	SOL_EUCLEAN,
+-	SOL_ENOTNAM,
+-	SOL_ENAVAIL,
+-	SOL_EISNAM,
+-	SOL_EREMOTEIO,
+-	SOL_EILSEQ,
+-	SOL_ELIBMAX,
+-	SOL_ELIBSCN,
+-};
+diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
+index 9a219e8..b7f1e81 100644
+--- a/arch/sparc/kernel/head.S
++++ b/arch/sparc/kernel/head.S
+@@ -78,11 +78,6 @@ sun4e_notsup:
+         .asciz  "Sparc-Linux sun4e support does not exist\n\n"
+ 	.align 4
+ 
+-#ifndef CONFIG_SUNOS_EMUL
+-#undef SUNOS_SYSCALL_TRAP
+-#define SUNOS_SYSCALL_TRAP SUNOS_NO_SYSCALL_TRAP
+-#endif
+-
+ 	/* The Sparc trap table, bootloader gives us control at _start. */
+ 	.text
+ 	.globl	start, _stext, _start, __stext
+@@ -158,7 +153,7 @@ t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x7
+ t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+-t_sunos:SUNOS_SYSCALL_TRAP                  /* SunOS System Call             */
++t_bad80:BAD_TRAP(0x80)                      /* SunOS System Call             */
+ t_sbkpt:BREAKPOINT_TRAP                     /* Software Breakpoint/KGDB      */
+ t_divz:	TRAP_ENTRY(0x82, do_hw_divzero)     /* Divide by zero trap           */
+ t_flwin:TRAP_ENTRY(0x83, do_flush_windows)  /* Flush Windows Trap            */
+@@ -166,8 +161,8 @@ t_clwin:BAD_TRAP(0x84)                      /* Clean Windows Trap            */
+ t_rchk:	BAD_TRAP(0x85)                      /* Range Check                   */
+ t_funal:BAD_TRAP(0x86)                      /* Fix Unaligned Access Trap     */
+ t_iovf:	BAD_TRAP(0x87)                      /* Integer Overflow Trap         */
+-t_slowl:SOLARIS_SYSCALL_TRAP                /* Slowaris System Call          */
+-t_netbs:NETBSD_SYSCALL_TRAP                 /* Net-B.S. System Call          */
++t_bad88:BAD_TRAP(0x88)                      /* Slowaris System Call          */
++t_bad89:BAD_TRAP(0x89)                      /* Net-B.S. System Call          */
+ t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e)
+ t_bad8f:BAD_TRAP(0x8f)
+ t_linux:LINUX_SYSCALL_TRAP                  /* Linux System Call             */
+@@ -178,7 +173,7 @@ t_getcc:GETCC_TRAP                          /* Get Condition Codes           */
+ t_setcc:SETCC_TRAP                          /* Set Condition Codes           */
+ t_getpsr:GETPSR_TRAP                        /* Get PSR Register              */
+ t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+-t_slowi:INDIRECT_SOLARIS_SYSCALL(156)
++t_bada7:BAD_TRAP(0xa7)
+ t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+@@ -243,19 +238,19 @@ trapbase_cpu1:
+ 	BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ 	BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ 	BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+-	SUNOS_SYSCALL_TRAP 
++	BAD_TRAP(0x80)
+ 	BREAKPOINT_TRAP
+ 	TRAP_ENTRY(0x82, do_hw_divzero)
+ 	TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
+-	BAD_TRAP(0x86) BAD_TRAP(0x87) SOLARIS_SYSCALL_TRAP
+-	NETBSD_SYSCALL_TRAP BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
++	BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
++	BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
+ 	BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
+ 	LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
+ 	BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
+ 	BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
+ 	BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+ 	BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+-	INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
++	BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ 	BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ 	BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+ 	BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+@@ -311,19 +306,19 @@ trapbase_cpu2:
+ 	BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ 	BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ 	BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+-	SUNOS_SYSCALL_TRAP 
++	BAD_TRAP(0x80)
+ 	BREAKPOINT_TRAP
+ 	TRAP_ENTRY(0x82, do_hw_divzero)
+ 	TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
+-	BAD_TRAP(0x86) BAD_TRAP(0x87) SOLARIS_SYSCALL_TRAP
+-	NETBSD_SYSCALL_TRAP BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
++	BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
++	BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
+ 	BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
+ 	LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
+ 	BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
+ 	BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
+ 	BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+ 	BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+-	INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
++	BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ 	BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ 	BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+ 	BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+@@ -379,19 +374,19 @@ trapbase_cpu3:
+ 	BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ 	BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ 	BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+-	SUNOS_SYSCALL_TRAP  
++	BAD_TRAP(0x80)
+ 	BREAKPOINT_TRAP
+ 	TRAP_ENTRY(0x82, do_hw_divzero)
+ 	TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
+-	BAD_TRAP(0x86) BAD_TRAP(0x87) SOLARIS_SYSCALL_TRAP
+-	NETBSD_SYSCALL_TRAP BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
++	BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
++	BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
+ 	BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
+ 	LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
+ 	BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
+ 	BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
+ 	BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+ 	BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+-	INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
++	BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ 	BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ 	BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+ 	BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+diff --git a/arch/sparc/kernel/sclow.S b/arch/sparc/kernel/sclow.S
+deleted file mode 100644
+index 136e37c..0000000
+--- a/arch/sparc/kernel/sclow.S
++++ /dev/null
+@@ -1,86 +0,0 @@
+-/* sclow.S: Low level special syscall handling.
+- *          Basically these are cases where we can completely
+- *          handle the system call without saving any state
+- *          because we know that the process will not sleep.
+- *
+- * Copyright (C) 1996 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#include <asm/ptrace.h>
+-#include <asm/asm-offsets.h>
+-#include <asm/errno.h>
+-#include <asm/winmacro.h>
+-#include <asm/thread_info.h>
+-#include <asm/psr.h>
+-#include <asm/page.h>
+-
+-#define CC_AND_RETT  \
+-	set	PSR_C, %l4; \
+-	andn	%l0, %l4, %l4; \
+-	wr	%l4, 0x0, %psr; \
+-	nop; nop; nop; \
+-	jmp	%l2; \
+-	rett	%l2 + 4;
+-
+-#define SC_AND_RETT  \
+-	set	PSR_C, %l4; \
+-	or	%l0, %l4, %l4; \
+-	wr	%l4, 0x0, %psr; \
+-	nop; nop; nop; \
+-	jmp	%l2; \
+-	rett	%l2 + 4;
+-
+-#define LABEL(func)  func##_low
+-
+-	.globl	LABEL(sunosnop)
+-LABEL(sunosnop):
+-	CC_AND_RETT
+-
+-#if (ASIZ_task_uid == 2 && ASIZ_task_euid == 2)
+-	.globl	LABEL(sunosgetuid)
+-LABEL(sunosgetuid):
+-	LOAD_CURRENT(l4, l5)
+-	ld	[%l4 + TI_TASK], %l4
+-	lduh	[%l4 + AOFF_task_uid], %i0
+-	lduh	[%l4 + AOFF_task_euid], %i1
+-	CC_AND_RETT
+-#endif
+-
+-#if (ASIZ_task_gid == 2 && ASIZ_task_egid == 2)
+-	.globl	LABEL(sunosgetgid)
+-LABEL(sunosgetgid):
+-	LOAD_CURRENT(l4, l5)
+-	ld	[%l4 + TI_TASK], %l4
+-	lduh	[%l4 + AOFF_task_gid], %i0
+-	lduh	[%l4 + AOFF_task_egid], %i1
+-	CC_AND_RETT
+-#endif
+-
+-	.globl	LABEL(sunosmctl)
+-LABEL(sunosmctl):
+-	mov	0, %i0
+-	CC_AND_RETT
+-
+-	.globl	LABEL(sunosgdtsize)
+-LABEL(sunosgdtsize):	
+-	mov	256, %i0
+-	CC_AND_RETT
+-
+-	.globl	LABEL(getpagesize)
+-LABEL(getpagesize):
+-	set	PAGE_SIZE, %i0
+-	CC_AND_RETT
+-
+-	/* XXX sys_nice() XXX */
+-	/* XXX sys_setpriority() XXX */
+-	/* XXX sys_getpriority() XXX */
+-	/* XXX sys_setregid() XXX */
+-	/* XXX sys_setgid() XXX */
+-	/* XXX sys_setreuid() XXX */
+-	/* XXX sys_setuid() XXX */
+-	/* XXX sys_setfsuid() XXX */
+-	/* XXX sys_setfsgid() XXX */
+-	/* XXX sys_setpgid() XXX */
+-	/* XXX sys_getpgid() XXX */
+-	/* XXX sys_setsid() XXX */
+-	/* XXX sys_getsid() XXX */
+diff --git a/arch/sparc/kernel/semaphore.c b/arch/sparc/kernel/semaphore.c
+deleted file mode 100644
+index 0c37c1a..0000000
+--- a/arch/sparc/kernel/semaphore.c
++++ /dev/null
+@@ -1,155 +0,0 @@
+-/* $Id: semaphore.c,v 1.7 2001/04/18 21:06:05 davem Exp $ */
+-
+-/* sparc32 semaphore implementation, based on i386 version */
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is
+- * protected by the semaphore spinlock.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- *  - only on a boundary condition do we need to care. When we go
+- *    from a negative count to a non-negative, we wake people up.
+- *  - when we go from a non-negative count to a negative do we
+- *    (a) synchronize with the "sleeper" count and (b) make sure
+- *    that we're on the wakeup list before we synchronize so that
+- *    we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+-	wake_up(&sem->wait);
+-}
+-
+-static DEFINE_SPINLOCK(semaphore_lock);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	tsk->state = TASK_UNINTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	spin_lock_irq(&semaphore_lock);
+-	sem->sleepers++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock.
+-		 */
+-		if (!atomic24_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irq(&semaphore_lock);
+-
+-		schedule();
+-		tsk->state = TASK_UNINTERRUPTIBLE;
+-		spin_lock_irq(&semaphore_lock);
+-	}
+-	spin_unlock_irq(&semaphore_lock);
+-	remove_wait_queue(&sem->wait, &wait);
+-	tsk->state = TASK_RUNNING;
+-	wake_up(&sem->wait);
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	tsk->state = TASK_INTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	spin_lock_irq(&semaphore_lock);
+-	sem->sleepers ++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * With signals pending, this turns into
+-		 * the trylock failure case - we won't be
+-		 * sleeping, and we* can't get the lock as
+-		 * it has contention. Just correct the count
+-		 * and exit.
+-		 */
+-		if (signal_pending(current)) {
+-			retval = -EINTR;
+-			sem->sleepers = 0;
+-			atomic24_add(sleepers, &sem->count);
+-			break;
+-		}
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock. The
+-		 * "-1" is because we're still hoping to get
+-		 * the lock.
+-		 */
+-		if (!atomic24_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irq(&semaphore_lock);
+-
+-		schedule();
+-		tsk->state = TASK_INTERRUPTIBLE;
+-		spin_lock_irq(&semaphore_lock);
+-	}
+-	spin_unlock_irq(&semaphore_lock);
+-	tsk->state = TASK_RUNNING;
+-	remove_wait_queue(&sem->wait, &wait);
+-	wake_up(&sem->wait);
+-	return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- */
+-int __down_trylock(struct semaphore * sem)
+-{
+-	int sleepers;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_lock, flags);
+-	sleepers = sem->sleepers + 1;
+-	sem->sleepers = 0;
+-
+-	/*
+-	 * Add "everybody else" and us into it. They aren't
+-	 * playing, because we own the spinlock.
+-	 */
+-	if (!atomic24_add_negative(sleepers, &sem->count))
+-		wake_up(&sem->wait);
+-
+-	spin_unlock_irqrestore(&semaphore_lock, flags);
+-	return 1;
+-}
+diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
+index 9994cac..3e849e8 100644
+--- a/arch/sparc/kernel/signal.c
++++ b/arch/sparc/kernel/signal.c
+@@ -22,7 +22,6 @@
+ 
+ #include <asm/uaccess.h>
+ #include <asm/ptrace.h>
+-#include <asm/svr4.h>
+ #include <asm/pgalloc.h>
+ #include <asm/pgtable.h>
+ #include <asm/cacheflush.h>	/* flush_sig_insns */
+@@ -106,11 +105,6 @@ static int _sigpause_common(old_sigset_t set)
+ 	return -ERESTARTNOHAND;
+ }
+ 
+-asmlinkage int sys_sigpause(unsigned int set)
+-{
+-	return _sigpause_common(set);
+-}
+-
+ asmlinkage int sys_sigsuspend(old_sigset_t set)
+ {
+ 	return _sigpause_common(set);
+@@ -454,7 +448,6 @@ setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *old
+ 			break;
+ 		case SIGSYS:
+ 			if (info->si_code == (__SI_FAULT|0x100)) {
+-				/* See sys_sunos.c */
+ 				sig_code = info->si_trapno;
+ 				break;
+ 			}
+@@ -676,291 +669,17 @@ sigsegv:
+ 	force_sigsegv(signo, current);
+ }
+ 
+-/* Setup a Solaris stack frame */
+-static inline void
+-setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
+-		 struct pt_regs *regs, int signr, sigset_t *oldset)
+-{
+-	svr4_signal_frame_t __user *sfp;
+-	svr4_gregset_t  __user *gr;
+-	svr4_siginfo_t  __user *si;
+-	svr4_mcontext_t __user *mc;
+-	svr4_gwindows_t __user *gw;
+-	svr4_ucontext_t __user *uc;
+-	svr4_sigset_t	setv;
+-	struct thread_info *tp = current_thread_info();
+-	int window = 0, err;
+-
+-	synchronize_user_stack();
+-	sfp = (svr4_signal_frame_t __user *)
+-		get_sigframe(sa, regs, SVR4_SF_ALIGNED + sizeof(struct reg_window));
+-
+-	if (invalid_frame_pointer(sfp, sizeof(*sfp)))
+-		goto sigill_and_return;
+-
+-	/* Start with a clean frame pointer and fill it */
+-	err = __clear_user(sfp, sizeof(*sfp));
+-
+-	/* Setup convenience variables */
+-	si = &sfp->si;
+-	uc = &sfp->uc;
+-	gw = &sfp->gw;
+-	mc = &uc->mcontext;
+-	gr = &mc->greg;
+-	
+-	/* FIXME: where am I supposed to put this?
+-	 * sc->sigc_onstack = old_status;
+-	 * anyways, it does not look like it is used for anything at all.
+-	 */
+-	setv.sigbits[0] = oldset->sig[0];
+-	setv.sigbits[1] = oldset->sig[1];
+-	if (_NSIG_WORDS >= 4) {
+-		setv.sigbits[2] = oldset->sig[2];
+-		setv.sigbits[3] = oldset->sig[3];
+-		err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+-	} else
+-		err |= __copy_to_user(&uc->sigmask, &setv,
+-				      2 * sizeof(unsigned int));
+-
+-	/* Store registers */
+-	err |= __put_user(regs->pc, &((*gr)[SVR4_PC]));
+-	err |= __put_user(regs->npc, &((*gr)[SVR4_NPC]));
+-	err |= __put_user(regs->psr, &((*gr)[SVR4_PSR]));
+-	err |= __put_user(regs->y, &((*gr)[SVR4_Y]));
+-	
+-	/* Copy g[1..7] and o[0..7] registers */
+-	err |= __copy_to_user(&(*gr)[SVR4_G1], &regs->u_regs[UREG_G1],
+-			      sizeof(long) * 7);
+-	err |= __copy_to_user(&(*gr)[SVR4_O0], &regs->u_regs[UREG_I0],
+-			      sizeof(long) * 8);
+-
+-	/* Setup sigaltstack */
+-	err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+-	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+-	err |= __put_user(current->sas_ss_size, &uc->stack.size);
+-
+-	/* Save the currently window file: */
+-
+-	/* 1. Link sfp->uc->gwins to our windows */
+-	err |= __put_user(gw, &mc->gwin);
+-	    
+-	/* 2. Number of windows to restore at setcontext(): */
+-	err |= __put_user(tp->w_saved, &gw->count);
+-
+-	/* 3. Save each valid window
+-	 *    Currently, it makes a copy of the windows from the kernel copy.
+-	 *    David's code for SunOS, makes the copy but keeps the pointer to
+-	 *    the kernel.  My version makes the pointer point to a userland 
+-	 *    copy of those.  Mhm, I wonder if I shouldn't just ignore those
+-	 *    on setcontext and use those that are on the kernel, the signal
+-	 *    handler should not be modyfing those, mhm.
+-	 *
+-	 *    These windows are just used in case synchronize_user_stack failed
+-	 *    to flush the user windows.
+-	 */
+-	for (window = 0; window < tp->w_saved; window++) {
+-		err |= __put_user((int __user *) &(gw->win[window]), &gw->winptr[window]);
+-		err |= __copy_to_user(&gw->win[window],
+-				      &tp->reg_window[window],
+-				      sizeof(svr4_rwindow_t));
+-		err |= __put_user(0, gw->winptr[window]);
+-	}
+-
+-	/* 4. We just pay attention to the gw->count field on setcontext */
+-	tp->w_saved = 0; /* So process is allowed to execute. */
+-
+-	/* Setup the signal information.  Solaris expects a bunch of
+-	 * information to be passed to the signal handler, we don't provide
+-	 * that much currently, should use siginfo.
+-	 */
+-	err |= __put_user(signr, &si->siginfo.signo);
+-	err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
+-	if (err)
+-		goto sigsegv;
+-
+-	regs->u_regs[UREG_FP] = (unsigned long) sfp;
+-	regs->pc = (unsigned long) sa->sa_handler;
+-	regs->npc = (regs->pc + 4);
+-
+-	/* Arguments passed to signal handler */
+-	if (regs->u_regs[14]){
+-		struct reg_window __user *rw = (struct reg_window __user *)
+-			regs->u_regs[14];
+-
+-		err |= __put_user(signr, &rw->ins[0]);
+-		err |= __put_user(si, &rw->ins[1]);
+-		err |= __put_user(uc, &rw->ins[2]);
+-		err |= __put_user(sfp, &rw->ins[6]);	/* frame pointer */
+-		if (err)
+-			goto sigsegv;
+-
+-		regs->u_regs[UREG_I0] = signr;
+-		regs->u_regs[UREG_I1] = (unsigned long) si;
+-		regs->u_regs[UREG_I2] = (unsigned long) uc;
+-	}
+-	return;
+-
+-sigill_and_return:
+-	do_exit(SIGILL);
+-sigsegv:
+-	force_sigsegv(signr, current);
+-}
+-
+-asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs)
+-{
+-	svr4_gregset_t  __user *gr;
+-	svr4_mcontext_t __user *mc;
+-	svr4_sigset_t	setv;
+-	int err = 0;
+-
+-	synchronize_user_stack();
+-
+-	if (current_thread_info()->w_saved)
+-		return -EFAULT;
+-
+-	err = clear_user(uc, sizeof(*uc));
+-	if (err)
+-		return -EFAULT;
+-
+-	/* Setup convenience variables */
+-	mc = &uc->mcontext;
+-	gr = &mc->greg;
+-
+-	setv.sigbits[0] = current->blocked.sig[0];
+-	setv.sigbits[1] = current->blocked.sig[1];
+-	if (_NSIG_WORDS >= 4) {
+-		setv.sigbits[2] = current->blocked.sig[2];
+-		setv.sigbits[3] = current->blocked.sig[3];
+-		err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+-	} else
+-		err |= __copy_to_user(&uc->sigmask, &setv,
+-				      2 * sizeof(unsigned int));
+-
+-	/* Store registers */
+-	err |= __put_user(regs->pc, &uc->mcontext.greg[SVR4_PC]);
+-	err |= __put_user(regs->npc, &uc->mcontext.greg[SVR4_NPC]);
+-	err |= __put_user(regs->psr, &uc->mcontext.greg[SVR4_PSR]);
+-	err |= __put_user(regs->y, &uc->mcontext.greg[SVR4_Y]);
+-	
+-	/* Copy g[1..7] and o[0..7] registers */
+-	err |= __copy_to_user(&(*gr)[SVR4_G1], &regs->u_regs[UREG_G1],
+-			      sizeof(uint) * 7);
+-	err |= __copy_to_user(&(*gr)[SVR4_O0], &regs->u_regs[UREG_I0],
+-			      sizeof(uint) * 8);
+-
+-	/* Setup sigaltstack */
+-	err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+-	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+-	err |= __put_user(current->sas_ss_size, &uc->stack.size);
+-
+-	/* The register file is not saved
+-	 * we have already stuffed all of it with sync_user_stack
+-	 */
+-	return (err ? -EFAULT : 0);
+-}
+-
+-/* Set the context for a svr4 application, this is Solaris way to sigreturn */
+-asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs)
+-{
+-	svr4_gregset_t  __user *gr;
+-	unsigned long pc, npc, psr;
+-	mm_segment_t old_fs;
+-	sigset_t set;
+-	svr4_sigset_t setv;
+-	int err;
+-	stack_t st;
+-	
+-	/* Fixme: restore windows, or is this already taken care of in
+-	 * svr4_setup_frame when sync_user_windows is done?
+-	 */
+-	flush_user_windows();
+-
+-	if (current_thread_info()->w_saved)
+-		goto sigsegv_and_return;
+-
+-	if (((unsigned long) c) & 3)
+-		goto sigsegv_and_return;
+-
+-	if (!__access_ok((unsigned long)c, sizeof(*c)))
+-		goto sigsegv_and_return;
+-
+-	/* Check for valid PC and nPC */
+-	gr = &c->mcontext.greg;
+-	err = __get_user(pc, &((*gr)[SVR4_PC]));
+-	err |= __get_user(npc, &((*gr)[SVR4_NPC]));
+-
+-	if ((pc | npc) & 3)
+-		goto sigsegv_and_return;
+-
+-	/* Retrieve information from passed ucontext */
+-	/* note that nPC is ored a 1, this is used to inform entry.S */
+-	/* that we don't want it to mess with our PC and nPC */
+-
+-	/* This is pretty much atomic, no amount locking would prevent
+-	 * the races which exist anyways.
+-	 */
+-	err |= __copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t));
+-	
+-	err |= __get_user(st.ss_sp, &c->stack.sp);
+-	err |= __get_user(st.ss_flags, &c->stack.flags);
+-	err |= __get_user(st.ss_size, &c->stack.size);
+-	
+-	if (err)
+-		goto sigsegv_and_return;
+-		
+-	/* 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((const stack_t __user *) &st, NULL,
+-		       regs->u_regs[UREG_I6]);
+-	set_fs(old_fs);
+-	
+-	set.sig[0] = setv.sigbits[0];
+-	set.sig[1] = setv.sigbits[1];
+-	if (_NSIG_WORDS >= 4) {
+-		set.sig[2] = setv.sigbits[2];
+-		set.sig[3] = setv.sigbits[3];
+-	}
+-	sigdelsetmask(&set, ~_BLOCKABLE);
+-	spin_lock_irq(&current->sighand->siglock);
+-	current->blocked = set;
+-	recalc_sigpending();
+-	spin_unlock_irq(&current->sighand->siglock);
+-	regs->pc = pc;
+-	regs->npc = npc | 1;
+-	err |= __get_user(regs->y, &((*gr)[SVR4_Y]));
+-	err |= __get_user(psr, &((*gr)[SVR4_PSR]));
+-	regs->psr &= ~(PSR_ICC);
+-	regs->psr |= (psr & PSR_ICC);
+-
+-	/* Restore g[1..7] and o[0..7] registers */
+-	err |= __copy_from_user(&regs->u_regs[UREG_G1], &(*gr)[SVR4_G1],
+-			      sizeof(long) * 7);
+-	err |= __copy_from_user(&regs->u_regs[UREG_I0], &(*gr)[SVR4_O0],
+-			      sizeof(long) * 8);
+-	return (err ? -EFAULT : 0);
+-
+-sigsegv_and_return:
+-	force_sig(SIGSEGV, current);
+-	return -EFAULT;
+-}
+-
+ static inline void
+ handle_signal(unsigned long signr, struct k_sigaction *ka,
+-	      siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
+-	      int svr4_signal)
++	      siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+ {
+-	if (svr4_signal)
+-		setup_svr4_frame(&ka->sa, regs->pc, regs->npc, regs, signr, oldset);
+-	else {
+-		if (ka->sa.sa_flags & SA_SIGINFO)
+-			new_setup_rt_frame(ka, regs, signr, oldset, info);
+-		else if (current->thread.new_signal)
+-			new_setup_frame(ka, regs, signr, oldset);
+-		else
+-			setup_frame(&ka->sa, regs, signr, oldset, info);
+-	}
++	if (ka->sa.sa_flags & SA_SIGINFO)
++		new_setup_rt_frame(ka, regs, signr, oldset, info);
++	else if (current->thread.new_signal)
++		new_setup_frame(ka, regs, signr, oldset);
++	else
++		setup_frame(&ka->sa, regs, signr, oldset, info);
++
+ 	spin_lock_irq(&current->sighand->siglock);
+ 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ 	if (!(ka->sa.sa_flags & SA_NOMASK))
+@@ -1002,17 +721,6 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest
+ 	int signr;
+ 	sigset_t *oldset;
+ 
+-	/*
+-	 * XXX Disable svr4 signal handling until solaris emulation works.
+-	 * It is buggy - Anton
+-	 */
+-#define SVR4_SIGNAL_BROKEN 1
+-#ifdef SVR4_SIGNAL_BROKEN
+-	int svr4_signal = 0;
+-#else
+-	int svr4_signal = current->personality == PER_SVR4;
+-#endif
+-
+ 	cookie.restart_syscall = restart_syscall;
+ 	cookie.orig_i0 = orig_i0;
+ 
+@@ -1025,8 +733,8 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest
+ 	if (signr > 0) {
+ 		if (cookie.restart_syscall)
+ 			syscall_restart(cookie.orig_i0, regs, &ka.sa);
+-		handle_signal(signr, &ka, &info, oldset,
+-			      regs, svr4_signal);
++		handle_signal(signr, &ka, &info, oldset, regs);
++
+ 		/* a signal was successfully delivered; the saved
+ 		 * sigmask will have been stored in the signal frame,
+ 		 * and will be restored by sigreturn, so we can simply
+diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
+index c1025e5..0bcf98a 100644
+--- a/arch/sparc/kernel/sparc_ksyms.c
++++ b/arch/sparc/kernel/sparc_ksyms.c
+@@ -36,12 +36,10 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/idprom.h>
+-#include <asm/svr4.h>
+ #include <asm/head.h>
+ #include <asm/smp.h>
+ #include <asm/mostek.h>
+ #include <asm/ptrace.h>
+-#include <asm/user.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+ #ifdef CONFIG_SBUS
+@@ -62,8 +60,6 @@ struct poll {
+ 	short revents;
+ };
+ 
+-extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
+-extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
+ extern void (*__copy_1page)(void *, const void *);
+ extern void __memmove(void *, const void *, __kernel_size_t);
+ extern void (*bzero_1page)(void *);
+@@ -107,11 +103,6 @@ EXPORT_SYMBOL(___rw_read_try);
+ EXPORT_SYMBOL(___rw_read_exit);
+ EXPORT_SYMBOL(___rw_write_enter);
+ #endif
+-/* semaphores */
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__down_interruptible);
+ 
+ EXPORT_SYMBOL(sparc_valid_addr_bitmap);
+ EXPORT_SYMBOL(phys_base);
+@@ -209,10 +200,6 @@ EXPORT_SYMBOL(kmap_atomic);
+ EXPORT_SYMBOL(kunmap_atomic);
+ #endif
+ 
+-/* Solaris/SunOS binary compatibility */
+-EXPORT_SYMBOL(svr4_setcontext);
+-EXPORT_SYMBOL(svr4_getcontext);
+-
+ /* prom symbols */
+ EXPORT_SYMBOL(idprom);
+ EXPORT_SYMBOL(prom_root_node);
+diff --git a/arch/sparc/kernel/sunos_asm.S b/arch/sparc/kernel/sunos_asm.S
+deleted file mode 100644
+index 07fe860..0000000
+--- a/arch/sparc/kernel/sunos_asm.S
++++ /dev/null
+@@ -1,67 +0,0 @@
+-/* $Id: sunos_asm.S,v 1.15 2000/01/11 17:33:21 jj Exp $
+- * sunos_asm.S: SunOS system calls which must have a low-level
+- *              entry point to operate correctly.
+- *
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- *
+- * Based upon preliminary work which is:
+- *
+- * Copyright (C) 1995 Adrian M. Rodriguez (adrian at remus.rutgers.edu)
+- */
+-
+-#include <asm/ptrace.h>
+-
+-	.text
+-	.align 4
+-
+-	/* When calling ret_sys_call, %o0 should contain the same
+-	 * value as in [%sp + STACKFRAME_SZ + PT_I0] */
+-
+-	/* SunOS getpid() returns pid in %o0 and ppid in %o1 */
+-	.globl	sunos_getpid
+-sunos_getpid:
+-	call	sys_getppid
+-	 nop
+-
+-	call	sys_getpid
+-	 st	%o0, [%sp + STACKFRAME_SZ + PT_I1]
+-
+-	b	ret_sys_call
+-	 st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+-
+-	/* SunOS getuid() returns uid in %o0 and euid in %o1 */
+-	.globl	sunos_getuid
+-sunos_getuid:
+-	call	sys_geteuid16
+-	 nop
+-
+-	call	sys_getuid16
+-	 st	%o0, [%sp + STACKFRAME_SZ + PT_I1]
+-
+-	b	ret_sys_call
+-	 st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+-
+-	/* SunOS getgid() returns gid in %o0 and egid in %o1 */
+-	.globl	sunos_getgid
+-sunos_getgid:
+-	call	sys_getegid16
+-	 nop
+-
+-	call	sys_getgid16
+-	 st	%o0, [%sp + STACKFRAME_SZ + PT_I1]
+-
+-	b	ret_sys_call
+-	 st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+-
+-	/* SunOS's execv() call only specifies the argv argument, the
+-	 * environment settings are the same as the calling processes.
+-	 */
+-	.globl	sunos_execv
+-sunos_execv:
+-	st	%g0, [%sp + STACKFRAME_SZ + PT_I2]
+-
+-	call	sparc_execve
+-	 add	%sp, STACKFRAME_SZ, %o0
+-
+-	b	ret_sys_call
+-	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
+diff --git a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c
+deleted file mode 100644
+index e613cc6..0000000
+--- a/arch/sparc/kernel/sunos_ioctl.c
++++ /dev/null
+@@ -1,230 +0,0 @@
+-/* $Id: sunos_ioctl.c,v 1.34 2000/09/03 14:10:56 anton Exp $
+- * sunos_ioctl.c: The Linux Operating system: SunOS ioctl compatibility.
+- * 
+- * Copyright (C) 1995 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#include <asm/uaccess.h>
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/termios.h>
+-#include <linux/tty.h>
+-#include <linux/ioctl.h>
+-#include <linux/route.h>
+-#include <linux/sockios.h>
+-#include <linux/if.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/fs.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/syscalls.h>
+-#include <linux/file.h>
+-
+-#if 0
+-extern char sunkbd_type;
+-extern char sunkbd_layout;
+-#endif
+-
+-/* NR_OPEN is now larger and dynamic in recent kernels. */
+-#define SUNOS_NR_OPEN	256
+-
+-asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg)
+-{
+-	int ret = -EBADF;
+-
+-	if (fd >= SUNOS_NR_OPEN || !fcheck(fd))
+-		goto out;
+-
+-	/* First handle an easy compat. case for tty ldisc. */
+-	if (cmd == TIOCSETD) {
+-		int __user *p;
+-		int ntty = N_TTY, tmp;
+-		mm_segment_t oldfs;
+-
+-		p = (int __user *) arg;
+-		ret = -EFAULT;
+-		if (get_user(tmp, p))
+-			goto out;
+-		if (tmp == 2) {
+-			oldfs = get_fs();
+-			set_fs(KERNEL_DS);
+-			ret = sys_ioctl(fd, cmd, (unsigned long) &ntty);
+-			set_fs(oldfs);
+-			ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+-			goto out;
+-		}
+-	}
+-
+-	/* Binary compatibility is good American knowhow fuckin' up. */
+-	if (cmd == TIOCNOTTY) {
+-		ret = sys_setsid();
+-		goto out;
+-	}
+-
+-	/* SunOS networking ioctls. */
+-	switch (cmd) {
+-	case _IOW('r', 10, struct rtentry):
+-		ret = sys_ioctl(fd, SIOCADDRT, arg);
+-		goto out;
+-	case _IOW('r', 11, struct rtentry):
+-		ret = sys_ioctl(fd, SIOCDELRT, arg);
+-		goto out;
+-	case _IOW('i', 12, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCSIFADDR, arg);
+-		goto out;
+-	case _IOWR('i', 13, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCGIFADDR, arg);
+-		goto out;
+-	case _IOW('i', 14, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCSIFDSTADDR, arg);
+-		goto out;
+-	case _IOWR('i', 15, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCGIFDSTADDR, arg);
+-		goto out;
+-	case _IOW('i', 16, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCSIFFLAGS, arg);
+-		goto out;
+-	case _IOWR('i', 17, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCGIFFLAGS, arg);
+-		goto out;
+-	case _IOW('i', 18, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCSIFMEM, arg);
+-		goto out;
+-	case _IOWR('i', 19, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCGIFMEM, arg);
+-		goto out;
+-	case _IOWR('i', 20, struct ifconf):
+-		ret = sys_ioctl(fd, SIOCGIFCONF, arg);
+-		goto out;
+-	case _IOW('i', 21, struct ifreq): /* SIOCSIFMTU */
+-		ret = sys_ioctl(fd, SIOCSIFMTU, arg);
+-		goto out;
+-	case _IOWR('i', 22, struct ifreq): /* SIOCGIFMTU */
+-		ret = sys_ioctl(fd, SIOCGIFMTU, arg);
+-		goto out;
+-
+-	case _IOWR('i', 23, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCGIFBRDADDR, arg);
+-		goto out;
+-	case _IOW('i', 24, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCSIFBRDADDR, arg);
+-		goto out;
+-	case _IOWR('i', 25, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCGIFNETMASK, arg);
+-		goto out;
+-	case _IOW('i', 26, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCSIFNETMASK, arg);
+-		goto out;
+-	case _IOWR('i', 27, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCGIFMETRIC, arg);
+-		goto out;
+-	case _IOW('i', 28, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCSIFMETRIC, arg);
+-		goto out;
+-
+-	case _IOW('i', 30, struct arpreq):
+-		ret = sys_ioctl(fd, SIOCSARP, arg);
+-		goto out;
+-	case _IOWR('i', 31, struct arpreq):
+-		ret = sys_ioctl(fd, SIOCGARP, arg);
+-		goto out;
+-	case _IOW('i', 32, struct arpreq):
+-		ret = sys_ioctl(fd, SIOCDARP, arg);
+-		goto out;
+-
+-	case _IOW('i', 40, struct ifreq): /* SIOCUPPER */
+-	case _IOW('i', 41, struct ifreq): /* SIOCLOWER */
+-	case _IOW('i', 44, struct ifreq): /* SIOCSETSYNC */
+-	case _IOW('i', 45, struct ifreq): /* SIOCGETSYNC */
+-	case _IOW('i', 46, struct ifreq): /* SIOCSSDSTATS */
+-	case _IOW('i', 47, struct ifreq): /* SIOCSSESTATS */
+-	case _IOW('i', 48, struct ifreq): /* SIOCSPROMISC */
+-		ret = -EOPNOTSUPP;
+-		goto out;
+-
+-	case _IOW('i', 49, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCADDMULTI, arg);
+-		goto out;
+-	case _IOW('i', 50, struct ifreq):
+-		ret = sys_ioctl(fd, SIOCDELMULTI, arg);
+-		goto out;
+-
+-	/* FDDI interface ioctls, unsupported. */
+-		
+-	case _IOW('i', 51, struct ifreq): /* SIOCFDRESET */
+-	case _IOW('i', 52, struct ifreq): /* SIOCFDSLEEP */
+-	case _IOW('i', 53, struct ifreq): /* SIOCSTRTFMWAR */
+-	case _IOW('i', 54, struct ifreq): /* SIOCLDNSTRTFW */
+-	case _IOW('i', 55, struct ifreq): /* SIOCGETFDSTAT */
+-	case _IOW('i', 56, struct ifreq): /* SIOCFDNMIINT */
+-	case _IOW('i', 57, struct ifreq): /* SIOCFDEXUSER */
+-	case _IOW('i', 58, struct ifreq): /* SIOCFDGNETMAP */
+-	case _IOW('i', 59, struct ifreq): /* SIOCFDGIOCTL */
+-		printk("FDDI ioctl, returning EOPNOTSUPP\n");
+-		ret = -EOPNOTSUPP;
+-		goto out;
+-
+-	case _IOW('t', 125, int):
+-		/* More stupid tty sunos ioctls, just
+-		 * say it worked.
+-		 */
+-		ret = 0;
+-		goto out;
+-	/* Non posix grp */
+-	case _IOW('t', 118, int): {
+-		int oldval, newval, __user *ptr;
+-
+-		cmd = TIOCSPGRP;
+-		ptr = (int __user *) arg;
+-		ret = -EFAULT;
+-		if (get_user(oldval, ptr))
+-			goto out;
+-		ret = sys_ioctl(fd, cmd, arg);
+-		__get_user(newval, ptr);
+-		if (newval == -1) {
+-			__put_user(oldval, ptr);
+-			ret = -EIO;
+-		}
+-		if (ret == -ENOTTY)
+-			ret = -EIO;
+-		goto out;
+-	}
+-
+-	case _IOR('t', 119, int): {
+-		int oldval, newval, __user *ptr;
+-
+-		cmd = TIOCGPGRP;
+-		ptr = (int __user *) arg;
+-		ret = -EFAULT;
+-		if (get_user(oldval, ptr))
+-			goto out;
+-		ret = sys_ioctl(fd, cmd, arg);
+-		__get_user(newval, ptr);
+-		if (newval == -1) {
+-			__put_user(oldval, ptr);
+-			ret = -EIO;
+-		}
+-		if (ret == -ENOTTY)
+-			ret = -EIO;
+-		goto out;
+-	}
+-	}
+-
+-#if 0
+-	if ((cmd & 0xff00) == ('k' << 8)) {
+-		printk ("[[KBIO: %8.8x\n", (unsigned int) cmd);
+-	}
+-#endif
+-
+-	ret = sys_ioctl(fd, cmd, arg);
+-	/* so stupid... */
+-	ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+-out:
+-	return ret;
+-}
+-
+-
+diff --git a/arch/sparc/kernel/sys_solaris.c b/arch/sparc/kernel/sys_solaris.c
+deleted file mode 100644
+index 2226a59..0000000
+--- a/arch/sparc/kernel/sys_solaris.c
++++ /dev/null
+@@ -1,35 +0,0 @@
+-/*
+- * linux/arch/sparc/kernel/sys_solaris.c
+- *
+- * Copyright (C) 1996 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/personality.h>
+-#include <linux/ptrace.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/module.h>
+-
+-asmlinkage int
+-do_solaris_syscall (struct pt_regs *regs)
+-{
+-	static int cnt = 0;
+-	if (++cnt < 10) printk ("No solaris handler\n");
+-	force_sig(SIGSEGV, current);
+-	return 0;
+-}
+-
+-#ifndef CONFIG_SUNOS_EMUL
+-asmlinkage int
+-do_sunos_syscall (struct pt_regs *regs)
+-{
+-	static int cnt = 0;
+-	if (++cnt < 10) printk ("SunOS binary emulation not compiled in\n");
+-	force_sig (SIGSEGV, current);
+-	return 0;
+-}
+-#endif
+diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
+deleted file mode 100644
+index f5b608b..0000000
+--- a/arch/sparc/kernel/sys_sunos.c
++++ /dev/null
+@@ -1,1210 +0,0 @@
+-/* $Id: sys_sunos.c,v 1.137 2002/02/08 03:57:14 davem Exp $
+- * sys_sunos.c: SunOS specific syscall compatibility support.
+- *
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- * Copyright (C) 1995 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- *
+- * Based upon preliminary work which is:
+- *
+- * Copyright (C) 1995 Adrian M. Rodriguez (adrian at remus.rutgers.edu)
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/mman.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/resource.h>
+-#include <linux/ipc.h>
+-#include <linux/shm.h>
+-#include <linux/msg.h>
+-#include <linux/sem.h>
+-#include <linux/signal.h>
+-#include <linux/uio.h>
+-#include <linux/utsname.h>
+-#include <linux/major.h>
+-#include <linux/stat.h>
+-#include <linux/slab.h>
+-#include <linux/pagemap.h>
+-#include <linux/capability.h>
+-#include <linux/errno.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/syscalls.h>
+-
+-#include <net/sock.h>
+-
+-#include <asm/uaccess.h>
+-#ifndef KERNEL_DS
+-#include <linux/segment.h>
+-#endif
+-
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/pconf.h>
+-#include <asm/idprom.h> /* for gethostid() */
+-#include <asm/unistd.h>
+-#include <asm/system.h>
+-
+-/* For the nfs mount emulation */
+-#include <linux/socket.h>
+-#include <linux/in.h>
+-#include <linux/nfs.h>
+-#include <linux/nfs2.h>
+-#include <linux/nfs_mount.h>
+-
+-/* for sunos_select */
+-#include <linux/time.h>
+-#include <linux/personality.h>
+-
+-/* NR_OPEN is now larger and dynamic in recent kernels. */
+-#define SUNOS_NR_OPEN	256
+-
+-/* We use the SunOS mmap() semantics. */
+-asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
+-				    unsigned long prot, unsigned long flags,
+-				    unsigned long fd, unsigned long off)
+-{
+-	struct file * file = NULL;
+-	unsigned long retval, ret_type;
+-
+-	if (flags & MAP_NORESERVE) {
+-		static int cnt;
+-		if (cnt++ < 10)
+-			printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
+-			       current->comm);
+-		flags &= ~MAP_NORESERVE;
+-	}
+-	retval = -EBADF;
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		if (fd >= SUNOS_NR_OPEN)
+-			goto out;
+-		file = fget(fd);
+-		if (!file)
+-			goto out;
+-	}
+-
+-	retval = -EINVAL;
+-	/* If this is ld.so or a shared library doing an mmap
+-	 * of /dev/zero, transform it into an anonymous mapping.
+-	 * SunOS is so stupid some times... hmph!
+-	 */
+-	if (file) {
+-		if (imajor(file->f_path.dentry->d_inode) == MEM_MAJOR &&
+-		    iminor(file->f_path.dentry->d_inode) == 5) {
+-			flags |= MAP_ANONYMOUS;
+-			fput(file);
+-			file = NULL;
+-		}
+-	}
+-	ret_type = flags & _MAP_NEW;
+-	flags &= ~_MAP_NEW;
+-
+-	if (!(flags & MAP_FIXED))
+-		addr = 0;
+-	else {
+-		if (ARCH_SUN4C_SUN4 &&
+-		    (len > 0x20000000 ||
+-		     ((flags & MAP_FIXED) &&
+-		      addr < 0xe0000000 && addr + len > 0x20000000)))
+-			goto out_putf;
+-
+-		/* See asm-sparc/uaccess.h */
+-		if (len > TASK_SIZE - PAGE_SIZE ||
+-		    addr + len > TASK_SIZE - PAGE_SIZE)
+-			goto out_putf;
+-	}
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	down_write(&current->mm->mmap_sem);
+-	retval = do_mmap(file, addr, len, prot, flags, off);
+-	up_write(&current->mm->mmap_sem);
+-	if (!ret_type)
+-		retval = ((retval < PAGE_OFFSET) ? 0 : retval);
+-
+-out_putf:
+-	if (file)
+-		fput(file);
+-out:
+-	return retval;
+-}
+-
+-/* lmbench calls this, just say "yeah, ok" */
+-asmlinkage int sunos_mctl(unsigned long addr, unsigned long len, int function, char *arg)
+-{
+-	return 0;
+-}
+-
+-/* SunOS is completely broken... it returns 0 on success, otherwise
+- * ENOMEM.  For sys_sbrk() it wants the old brk value as a return
+- * on success and ENOMEM as before on failure.
+- */
+-asmlinkage int sunos_brk(unsigned long brk)
+-{
+-	int freepages, retval = -ENOMEM;
+-	unsigned long rlim;
+-	unsigned long newbrk, oldbrk;
+-
+-	down_write(&current->mm->mmap_sem);
+-	if (ARCH_SUN4C_SUN4) {
+-		if (brk >= 0x20000000 && brk < 0xe0000000) {
+-			goto out;
+-		}
+-	}
+-
+-	if (brk < current->mm->end_code)
+-		goto out;
+-
+-	newbrk = PAGE_ALIGN(brk);
+-	oldbrk = PAGE_ALIGN(current->mm->brk);
+-	retval = 0;
+-	if (oldbrk == newbrk) {
+-		current->mm->brk = brk;
+-		goto out;
+-	}
+-
+-	/*
+-	 * Always allow shrinking brk
+-	 */
+-	if (brk <= current->mm->brk) {
+-		current->mm->brk = brk;
+-		do_munmap(current->mm, newbrk, oldbrk-newbrk);
+-		goto out;
+-	}
+-	/*
+-	 * Check against rlimit and stack..
+-	 */
+-	retval = -ENOMEM;
+-	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+-	if (rlim >= RLIM_INFINITY)
+-		rlim = ~0;
+-	if (brk - current->mm->end_code > rlim)
+-		goto out;
+-
+-	/*
+-	 * Check against existing mmap mappings.
+-	 */
+-	if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
+-		goto out;
+-
+-	/*
+-	 * stupid algorithm to decide if we have enough memory: while
+-	 * simple, it hopefully works in most obvious cases.. Easy to
+-	 * fool it, but this should catch most mistakes.
+-	 */
+-	freepages = global_page_state(NR_FILE_PAGES);
+-	freepages >>= 1;
+-	freepages += nr_free_pages();
+-	freepages += nr_swap_pages;
+-	freepages -= num_physpages >> 4;
+-	freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
+-	if (freepages < 0)
+-		goto out;
+-	/*
+-	 * Ok, we have probably got enough memory - let it rip.
+-	 */
+-	current->mm->brk = brk;
+-	do_brk(oldbrk, newbrk-oldbrk);
+-	retval = 0;
+-out:
+-	up_write(&current->mm->mmap_sem);
+-	return retval;
+-}
+-
+-asmlinkage unsigned long sunos_sbrk(int increment)
+-{
+-	int error;
+-	unsigned long oldbrk;
+-
+-	/* This should do it hopefully... */
+-	lock_kernel();
+-	oldbrk = current->mm->brk;
+-	error = sunos_brk(((int) current->mm->brk) + increment);
+-	if (!error)
+-		error = oldbrk;
+-	unlock_kernel();
+-	return error;
+-}
+-
+-/* XXX Completely undocumented, and completely magic...
+- * XXX I believe it is to increase the size of the stack by
+- * XXX argument 'increment' and return the new end of stack
+- * XXX area.  Wheee...
+- */
+-asmlinkage unsigned long sunos_sstk(int increment)
+-{
+-	lock_kernel();
+-	printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
+-	       current->comm, increment);
+-	unlock_kernel();
+-	return -1;
+-}
+-
+-/* Give hints to the kernel as to what paging strategy to use...
+- * Completely bogus, don't remind me.
+- */
+-#define VA_NORMAL     0 /* Normal vm usage expected */
+-#define VA_ABNORMAL   1 /* Abnormal/random vm usage probable */
+-#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
+-#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
+-static char *vstrings[] = {
+-	"VA_NORMAL",
+-	"VA_ABNORMAL",
+-	"VA_SEQUENTIAL",
+-	"VA_INVALIDATE",
+-};
+-
+-asmlinkage void sunos_vadvise(unsigned long strategy)
+-{
+-	/* I wanna see who uses this... */
+-	lock_kernel();
+-	printk("%s: Advises us to use %s paging strategy\n",
+-	       current->comm,
+-	       strategy <= 3 ? vstrings[strategy] : "BOGUS");
+-	unlock_kernel();
+-}
+-
+-/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
+- * resource limit and is for backwards compatibility with older sunos
+- * revs.
+- */
+-asmlinkage long sunos_getdtablesize(void)
+-{
+-	return SUNOS_NR_OPEN;
+-}
+-
+-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+-
+-asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask)
+-{
+-	unsigned long old;
+-
+-	spin_lock_irq(&current->sighand->siglock);
+-	old = current->blocked.sig[0];
+-	current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
+-	recalc_sigpending();
+-	spin_unlock_irq(&current->sighand->siglock);
+-	return old;
+-}
+-
+-asmlinkage unsigned long sunos_sigsetmask(unsigned long newmask)
+-{
+-	unsigned long retval;
+-
+-	spin_lock_irq(&current->sighand->siglock);
+-	retval = current->blocked.sig[0];
+-	current->blocked.sig[0] = (newmask & _BLOCKABLE);
+-	recalc_sigpending();
+-	spin_unlock_irq(&current->sighand->siglock);
+-	return retval;
+-}
+-
+-/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant)    */
+-/* getdents system call, the format of the structure just has a different */
+-/* layout (d_off+d_ino instead of d_ino+d_off) */
+-struct sunos_dirent {
+-    long           d_off;
+-    unsigned long  d_ino;
+-    unsigned short d_reclen;
+-    unsigned short d_namlen;
+-    char           d_name[1];
+-};
+-
+-struct sunos_dirent_callback {
+-    struct sunos_dirent __user *curr;
+-    struct sunos_dirent __user *previous;
+-    int count;
+-    int error;
+-};
+-
+-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
+-#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
+-
+-static int sunos_filldir(void * __buf, const char * name, int namlen,
+-			 loff_t offset, u64 ino, unsigned int d_type)
+-{
+-	struct sunos_dirent __user *dirent;
+-	struct sunos_dirent_callback * buf = __buf;
+-	unsigned long d_ino;
+-	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+-
+-	buf->error = -EINVAL;	/* only used if we fail.. */
+-	if (reclen > buf->count)
+-		return -EINVAL;
+-	d_ino = ino;
+-	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
+-		return -EOVERFLOW;
+-	dirent = buf->previous;
+-	if (dirent)
+-		put_user(offset, &dirent->d_off);
+-	dirent = buf->curr;
+-	buf->previous = dirent;
+-	put_user(d_ino, &dirent->d_ino);
+-	put_user(namlen, &dirent->d_namlen);
+-	put_user(reclen, &dirent->d_reclen);
+-	copy_to_user(dirent->d_name, name, namlen);
+-	put_user(0, dirent->d_name + namlen);
+-	dirent = (void __user *) dirent + reclen;
+-	buf->curr = dirent;
+-	buf->count -= reclen;
+-	return 0;
+-}
+-
+-asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt)
+-{
+-	struct file * file;
+-	struct sunos_dirent __user *lastdirent;
+-	struct sunos_dirent_callback buf;
+-	int error = -EBADF;
+-
+-	if (fd >= SUNOS_NR_OPEN)
+-		goto out;
+-
+-	file = fget(fd);
+-	if (!file)
+-		goto out;
+-
+-	error = -EINVAL;
+-	if (cnt < (sizeof(struct sunos_dirent) + 255))
+-		goto out_putf;
+-
+-	buf.curr = (struct sunos_dirent __user *) dirent;
+-	buf.previous = NULL;
+-	buf.count = cnt;
+-	buf.error = 0;
+-
+-	error = vfs_readdir(file, sunos_filldir, &buf);
+-	if (error < 0)
+-		goto out_putf;
+-
+-	lastdirent = buf.previous;
+-	error = buf.error;
+-	if (lastdirent) {
+-		put_user(file->f_pos, &lastdirent->d_off);
+-		error = cnt - buf.count;
+-	}
+-
+-out_putf:
+-	fput(file);
+-out:
+-	return error;
+-}
+-
+-/* Old sunos getdirentries, severely broken compatibility stuff here. */
+-struct sunos_direntry {
+-    unsigned long  d_ino;
+-    unsigned short d_reclen;
+-    unsigned short d_namlen;
+-    char           d_name[1];
+-};
+-
+-struct sunos_direntry_callback {
+-    struct sunos_direntry __user *curr;
+-    struct sunos_direntry __user *previous;
+-    int count;
+-    int error;
+-};
+-
+-static int sunos_filldirentry(void * __buf, const char * name, int namlen,
+-			      loff_t offset, u64 ino, unsigned int d_type)
+-{
+-	struct sunos_direntry __user *dirent;
+-	struct sunos_direntry_callback *buf = __buf;
+-	unsigned long d_ino;
+-	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+-
+-	buf->error = -EINVAL;	/* only used if we fail.. */
+-	if (reclen > buf->count)
+-		return -EINVAL;
+-	d_ino = ino;
+-	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
+-		return -EOVERFLOW;
+-	dirent = buf->previous;
+-	dirent = buf->curr;
+-	buf->previous = dirent;
+-	put_user(d_ino, &dirent->d_ino);
+-	put_user(namlen, &dirent->d_namlen);
+-	put_user(reclen, &dirent->d_reclen);
+-	copy_to_user(dirent->d_name, name, namlen);
+-	put_user(0, dirent->d_name + namlen);
+-	dirent = (void __user *) dirent + reclen;
+-	buf->curr = dirent;
+-	buf->count -= reclen;
+-	return 0;
+-}
+-
+-asmlinkage int sunos_getdirentries(unsigned int fd, void __user *dirent,
+-				   int cnt, unsigned int __user *basep)
+-{
+-	struct file * file;
+-	struct sunos_direntry __user *lastdirent;
+-	struct sunos_direntry_callback buf;
+-	int error = -EBADF;
+-
+-	if (fd >= SUNOS_NR_OPEN)
+-		goto out;
+-
+-	file = fget(fd);
+-	if (!file)
+-		goto out;
+-
+-	error = -EINVAL;
+-	if (cnt < (sizeof(struct sunos_direntry) + 255))
+-		goto out_putf;
+-
+-	buf.curr = (struct sunos_direntry __user *) dirent;
+-	buf.previous = NULL;
+-	buf.count = cnt;
+-	buf.error = 0;
+-
+-	error = vfs_readdir(file, sunos_filldirentry, &buf);
+-	if (error < 0)
+-		goto out_putf;
+-
+-	lastdirent = buf.previous;
+-	error = buf.error;
+-	if (lastdirent) {
+-		put_user(file->f_pos, basep);
+-		error = cnt - buf.count;
+-	}
+-
+-out_putf:
+-	fput(file);
+-out:
+-	return error;
+-}
+-
+-struct sunos_utsname {
+-	char sname[9];
+-	char nname[9];
+-	char nnext[56];
+-	char rel[9];
+-	char ver[9];
+-	char mach[9];
+-};
+-
+-asmlinkage int sunos_uname(struct sunos_utsname __user *name)
+-{
+-	int ret;
+-	down_read(&uts_sem);
+-	ret = copy_to_user(&name->sname[0], &utsname()->sysname[0],
+-			   sizeof(name->sname) - 1);
+-	if (!ret) {
+-		ret |= __copy_to_user(&name->nname[0], &utsname()->nodename[0],
+-				      sizeof(name->nname) - 1);
+-		ret |= __put_user('\0', &name->nname[8]);
+-		ret |= __copy_to_user(&name->rel[0], &utsname()->release[0],
+-				      sizeof(name->rel) - 1);
+-		ret |= __copy_to_user(&name->ver[0], &utsname()->version[0],
+-				      sizeof(name->ver) - 1);
+-		ret |= __copy_to_user(&name->mach[0], &utsname()->machine[0],
+-				      sizeof(name->mach) - 1);
+-	}
+-	up_read(&uts_sem);
+-	return ret ? -EFAULT : 0;
+-}
+-
+-asmlinkage int sunos_nosys(void)
+-{
+-	struct pt_regs *regs;
+-	siginfo_t info;
+-	static int cnt;
+-
+-	lock_kernel();
+-	regs = current->thread.kregs;
+-	info.si_signo = SIGSYS;
+-	info.si_errno = 0;
+-	info.si_code = __SI_FAULT|0x100;
+-	info.si_addr = (void __user *)regs->pc;
+-	info.si_trapno = regs->u_regs[UREG_G1];
+-	send_sig_info(SIGSYS, &info, current);
+-	if (cnt++ < 4) {
+-		printk("Process makes ni_syscall number %d, register dump:\n",
+-		       (int) regs->u_regs[UREG_G1]);
+-		show_regs(regs);
+-	}
+-	unlock_kernel();
+-	return -ENOSYS;
+-}
+-
+-/* This is not a real and complete implementation yet, just to keep
+- * the easy SunOS binaries happy.
+- */
+-asmlinkage int sunos_fpathconf(int fd, int name)
+-{
+-	int ret;
+-
+-	switch(name) {
+-	case _PCONF_LINK:
+-		ret = LINK_MAX;
+-		break;
+-	case _PCONF_CANON:
+-		ret = MAX_CANON;
+-		break;
+-	case _PCONF_INPUT:
+-		ret = MAX_INPUT;
+-		break;
+-	case _PCONF_NAME:
+-		ret = NAME_MAX;
+-		break;
+-	case _PCONF_PATH:
+-		ret = PATH_MAX;
+-		break;
+-	case _PCONF_PIPE:
+-		ret = PIPE_BUF;
+-		break;
+-	case _PCONF_CHRESTRICT:		/* XXX Investigate XXX */
+-		ret = 1;
+-		break;
+-	case _PCONF_NOTRUNC:		/* XXX Investigate XXX */
+-	case _PCONF_VDISABLE:
+-		ret = 0;
+-		break;
+-	default:
+-		ret = -EINVAL;
+-		break;
+-	}
+-	return ret;
+-}
+-
+-asmlinkage int sunos_pathconf(char __user *path, int name)
+-{
+-	int ret;
+-
+-	ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
+-	return ret;
+-}
+-
+-/* SunOS mount system call emulation */
+-
+-asmlinkage int sunos_select(int width, fd_set __user *inp, fd_set __user *outp,
+-			    fd_set __user *exp, struct timeval __user *tvp)
+-{
+-	int ret;
+-
+-	/* SunOS binaries expect that select won't change the tvp contents */
+-	ret = sys_select (width, inp, outp, exp, tvp);
+-	if (ret == -EINTR && tvp) {
+-		time_t sec, usec;
+-
+-		__get_user(sec, &tvp->tv_sec);
+-		__get_user(usec, &tvp->tv_usec);
+-
+-		if (sec == 0 && usec == 0)
+-			ret = 0;
+-	}
+-	return ret;
+-}
+-
+-asmlinkage void sunos_nop(void)
+-{
+-	return;
+-}
+-
+-/* SunOS mount/umount. */
+-#define SMNT_RDONLY       1
+-#define SMNT_NOSUID       2
+-#define SMNT_NEWTYPE      4
+-#define SMNT_GRPID        8
+-#define SMNT_REMOUNT      16
+-#define SMNT_NOSUB        32
+-#define SMNT_MULTI        64
+-#define SMNT_SYS5         128
+-
+-struct sunos_fh_t {
+-	char fh_data [NFS_FHSIZE];
+-};
+-
+-struct sunos_nfs_mount_args {
+-	struct sockaddr_in  __user *addr; /* file server address */
+-	struct nfs_fh __user *fh;     /* File handle to be mounted */
+-	int        flags;      /* flags */
+-	int        wsize;      /* write size in bytes */
+-	int        rsize;      /* read size in bytes */
+-	int        timeo;      /* initial timeout in .1 secs */
+-	int        retrans;    /* times to retry send */
+-	char       __user *hostname;  /* server's hostname */
+-	int        acregmin;   /* attr cache file min secs */
+-	int        acregmax;   /* attr cache file max secs */
+-	int        acdirmin;   /* attr cache dir min secs */
+-	int        acdirmax;   /* attr cache dir max secs */
+-	char       __user *netname;   /* server's netname */
+-};
+-
+-
+-/* Bind the socket on a local reserved port and connect it to the
+- * remote server.  This on Linux/i386 is done by the mount program,
+- * not by the kernel.
+- */
+-static int
+-sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
+-{
+-	struct sockaddr_in local;
+-	struct sockaddr_in server;
+-	int    try_port;
+-	struct socket *socket;
+-	struct inode  *inode;
+-	struct file   *file;
+-	int    ret, result = 0;
+-
+-	file = fget(fd);
+-	if (!file)
+-		goto out;
+-
+-	inode = file->f_path.dentry->d_inode;
+-
+-	socket = SOCKET_I(inode);
+-	local.sin_family = AF_INET;
+-	local.sin_addr.s_addr = htonl(INADDR_ANY);
+-
+-	/* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
+-	try_port = 1024;
+-	do {
+-		local.sin_port = htons (--try_port);
+-		ret = socket->ops->bind(socket, (struct sockaddr*)&local,
+-					sizeof(local));
+-	} while (ret && try_port > (1024 / 2));
+-
+-	if (ret)
+-		goto out_putf;
+-
+-	server.sin_family = AF_INET;
+-	server.sin_addr = addr->sin_addr;
+-	server.sin_port = NFS_PORT;
+-
+-	/* Call sys_connect */
+-	ret = socket->ops->connect (socket, (struct sockaddr *) &server,
+-				    sizeof (server), file->f_flags);
+-	if (ret >= 0)
+-		result = 1;
+-
+-out_putf:
+-	fput(file);
+-out:
+-	return result;
+-}
+-
+-static int get_default (int value, int def_value)
+-{
+-    if (value)
+-	return value;
+-    else
+-	return def_value;
+-}
+-
+-static int sunos_nfs_mount(char *dir_name, int linux_flags, void __user *data)
+-{
+-	int  server_fd, err;
+-	char *the_name, *mount_page;
+-	struct nfs_mount_data linux_nfs_mount;
+-	struct sunos_nfs_mount_args sunos_mount;
+-
+-	/* Ok, here comes the fun part: Linux's nfs mount needs a
+-	 * socket connection to the server, but SunOS mount does not
+-	 * require this, so we use the information on the destination
+-	 * address to create a socket and bind it to a reserved
+-	 * port on this system
+-	 */
+-	if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)))
+-		return -EFAULT;
+-
+-	server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+-	if (server_fd < 0)
+-		return -ENXIO;
+-
+-	if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr,
+-				sizeof(*sunos_mount.addr)) ||
+-	    copy_from_user(&linux_nfs_mount.root,sunos_mount.fh,
+-				sizeof(*sunos_mount.fh))) {
+-		sys_close (server_fd);
+-		return -EFAULT;
+-	}
+-
+-	if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){
+-		sys_close (server_fd);
+-		return -ENXIO;
+-	}
+-
+-	/* Now, bind it to a locally reserved port */
+-	linux_nfs_mount.version  = NFS_MOUNT_VERSION;
+-	linux_nfs_mount.flags    = sunos_mount.flags;
+-	linux_nfs_mount.fd       = server_fd;
+-	
+-	linux_nfs_mount.rsize    = get_default (sunos_mount.rsize, 8192);
+-	linux_nfs_mount.wsize    = get_default (sunos_mount.wsize, 8192);
+-	linux_nfs_mount.timeo    = get_default (sunos_mount.timeo, 10);
+-	linux_nfs_mount.retrans  = sunos_mount.retrans;
+-	
+-	linux_nfs_mount.acregmin = sunos_mount.acregmin;
+-	linux_nfs_mount.acregmax = sunos_mount.acregmax;
+-	linux_nfs_mount.acdirmin = sunos_mount.acdirmin;
+-	linux_nfs_mount.acdirmax = sunos_mount.acdirmax;
+-
+-	the_name = getname(sunos_mount.hostname);
+-	if (IS_ERR(the_name))
+-		return PTR_ERR(the_name);
+-
+-	strlcpy(linux_nfs_mount.hostname, the_name,
+-		sizeof(linux_nfs_mount.hostname));
+-	putname (the_name);
+-	
+-	mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+-	if (!mount_page)
+-		return -ENOMEM;
+-
+-	memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+-
+-	err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+-
+-	free_page((unsigned long) mount_page);
+-	return err;
+-}
+-
+-asmlinkage int
+-sunos_mount(char __user *type, char __user *dir, int flags, void __user *data)
+-{
+-	int linux_flags = 0;
+-	int ret = -EINVAL;
+-	char *dev_fname = NULL;
+-	char *dir_page, *type_page;
+-
+-	if (!capable (CAP_SYS_ADMIN))
+-		return -EPERM;
+-		
+-	lock_kernel();
+-	/* We don't handle the integer fs type */
+-	if ((flags & SMNT_NEWTYPE) == 0)
+-		goto out;
+-
+-	/* Do not allow for those flags we don't support */
+-	if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
+-		goto out;
+-
+-	if (flags & SMNT_REMOUNT)
+-		linux_flags |= MS_REMOUNT;
+-	if (flags & SMNT_RDONLY)
+-		linux_flags |= MS_RDONLY;
+-	if (flags & SMNT_NOSUID)
+-		linux_flags |= MS_NOSUID;
+-
+-	dir_page = getname(dir);
+-	ret = PTR_ERR(dir_page);
+-	if (IS_ERR(dir_page))
+-		goto out;
+-
+-	type_page = getname(type);
+-	ret = PTR_ERR(type_page);
+-	if (IS_ERR(type_page))
+-		goto out1;
+-
+-	if (strcmp(type_page, "ext2") == 0) {
+-		dev_fname = getname(data);
+-	} else if (strcmp(type_page, "iso9660") == 0) {
+-		dev_fname = getname(data);
+-	} else if (strcmp(type_page, "minix") == 0) {
+-		dev_fname = getname(data);
+-	} else if (strcmp(type_page, "nfs") == 0) {
+-		ret = sunos_nfs_mount (dir_page, flags, data);
+-		goto out2;
+-        } else if (strcmp(type_page, "ufs") == 0) {
+-		printk("Warning: UFS filesystem mounts unsupported.\n");
+-		ret = -ENODEV;
+-		goto out2;
+-	} else if (strcmp(type_page, "proc")) {
+-		ret = -ENODEV;
+-		goto out2;
+-	}
+-	ret = PTR_ERR(dev_fname);
+-	if (IS_ERR(dev_fname))
+-		goto out2;
+-	ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL);
+-	if (dev_fname)
+-		putname(dev_fname);
+-out2:
+-	putname(type_page);
+-out1:
+-	putname(dir_page);
+-out:
+-	unlock_kernel();
+-	return ret;
+-}
+-
+-
+-asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
+-{
+-	int ret;
+-
+-	/* So stupid... */
+-	if ((!pid || pid == current->pid) &&
+-	    !pgid) {
+-		sys_setsid();
+-		ret = 0;
+-	} else {
+-		ret = sys_setpgid(pid, pgid);
+-	}
+-	return ret;
+-}
+-
+-/* So stupid... */
+-asmlinkage int sunos_wait4(pid_t pid, unsigned int __user *stat_addr,
+-			   int options, struct rusage __user*ru)
+-{
+-	int ret;
+-
+-	ret = sys_wait4((pid ? pid : -1), stat_addr, options, ru);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_killpg(int pgrp, int sig)
+-{
+-	int ret;
+-
+-	rcu_read_lock();
+-	ret = -EINVAL;
+-	if (pgrp > 0)
+-		ret = kill_pgrp(find_vpid(pgrp), sig, 0);
+-	rcu_read_unlock();
+-
+-	return ret;
+-}
+-
+-asmlinkage int sunos_audit(void)
+-{
+-	lock_kernel();
+-	printk ("sys_audit\n");
+-	unlock_kernel();
+-	return -1;
+-}
+-
+-asmlinkage unsigned long sunos_gethostid(void)
+-{
+-	unsigned long ret;
+-
+-	lock_kernel();
+-	ret = ((unsigned long)idprom->id_machtype << 24) |
+-		(unsigned long)idprom->id_sernum;
+-	unlock_kernel();
+-	return ret;
+-}
+-
+-/* sysconf options, for SunOS compatibility */
+-#define   _SC_ARG_MAX             1
+-#define   _SC_CHILD_MAX           2
+-#define   _SC_CLK_TCK             3
+-#define   _SC_NGROUPS_MAX         4
+-#define   _SC_OPEN_MAX            5
+-#define   _SC_JOB_CONTROL         6
+-#define   _SC_SAVED_IDS           7
+-#define   _SC_VERSION             8
+-
+-asmlinkage long sunos_sysconf (int name)
+-{
+-	long ret;
+-
+-	switch (name){
+-	case _SC_ARG_MAX:
+-		ret = ARG_MAX;
+-		break;
+-	case _SC_CHILD_MAX:
+-		ret = current->signal->rlim[RLIMIT_NPROC].rlim_cur;
+-		break;
+-	case _SC_CLK_TCK:
+-		ret = HZ;
+-		break;
+-	case _SC_NGROUPS_MAX:
+-		ret = NGROUPS_MAX;
+-		break;
+-	case _SC_OPEN_MAX:
+-		ret = current->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+-		break;
+-	case _SC_JOB_CONTROL:
+-		ret = 1;	/* yes, we do support job control */
+-		break;
+-	case _SC_SAVED_IDS:
+-		ret = 1;	/* yes, we do support saved uids  */
+-		break;
+-	case _SC_VERSION:
+-		/* mhm, POSIX_VERSION is in /usr/include/unistd.h
+-		 * should it go on /usr/include/linux?
+-		 */
+-		ret = 199009L; 
+-		break;
+-	default:
+-		ret = -1;
+-		break;
+-	};
+-	return ret;
+-}
+-
+-asmlinkage int sunos_semsys(int op, unsigned long arg1, unsigned long arg2,
+-			    unsigned long arg3, void *ptr)
+-{
+-	union semun arg4;
+-	int ret;
+-
+-	switch (op) {
+-	case 0:
+-		/* Most arguments match on a 1:1 basis but cmd doesn't */
+-		switch(arg3) {
+-		case 4:
+-			arg3=GETPID; break;
+-		case 5:
+-			arg3=GETVAL; break;
+-		case 6:
+-			arg3=GETALL; break;
+-		case 3:
+-			arg3=GETNCNT; break;
+-		case 7:
+-			arg3=GETZCNT; break;
+-		case 8:
+-			arg3=SETVAL; break;
+-		case 9:
+-			arg3=SETALL; break;
+-		}
+-		/* sys_semctl(): */
+-		/* value to modify semaphore to */
+-		arg4.__pad = (void __user *) ptr;
+-		ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4 );
+-		break;
+-	case 1:
+-		/* sys_semget(): */
+-		ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3);
+-		break;
+-	case 2:
+-		/* sys_semop(): */
+-		ret = sys_semop((int)arg1, (struct sembuf __user *)arg2, (unsigned)arg3);
+-		break;
+-	default:
+-		ret = -EINVAL;
+-		break;
+-	};
+-	return ret;
+-}
+-
+-asmlinkage int sunos_msgsys(int op, unsigned long arg1, unsigned long arg2,
+-			    unsigned long arg3, unsigned long arg4)
+-{
+-	struct sparc_stackf *sp;
+-	unsigned long arg5;
+-	int rval;
+-
+-	switch(op) {
+-	case 0:
+-		rval = sys_msgget((key_t)arg1, (int)arg2);
+-		break;
+-	case 1:
+-		rval = sys_msgctl((int)arg1, (int)arg2,
+-				  (struct msqid_ds __user *)arg3);
+-		break;
+-	case 2:
+-		lock_kernel();
+-		sp = (struct sparc_stackf *)current->thread.kregs->u_regs[UREG_FP];
+-		arg5 = sp->xxargs[0];
+-		unlock_kernel();
+-		rval = sys_msgrcv((int)arg1, (struct msgbuf __user *)arg2,
+-				  (size_t)arg3, (long)arg4, (int)arg5);
+-		break;
+-	case 3:
+-		rval = sys_msgsnd((int)arg1, (struct msgbuf __user *)arg2,
+-				  (size_t)arg3, (int)arg4);
+-		break;
+-	default:
+-		rval = -EINVAL;
+-		break;
+-	}
+-	return rval;
+-}
+-
+-asmlinkage int sunos_shmsys(int op, unsigned long arg1, unsigned long arg2,
+-			    unsigned long arg3)
+-{
+-	unsigned long raddr;
+-	int rval;
+-
+-	switch(op) {
+-	case 0:
+-		/* do_shmat(): attach a shared memory area */
+-		rval = do_shmat((int)arg1,(char __user *)arg2,(int)arg3,&raddr);
+-		if (!rval)
+-			rval = (int) raddr;
+-		break;
+-	case 1:
+-		/* sys_shmctl(): modify shared memory area attr. */
+-		rval = sys_shmctl((int)arg1,(int)arg2,(struct shmid_ds __user *)arg3);
+-		break;
+-	case 2:
+-		/* sys_shmdt(): detach a shared memory area */
+-		rval = sys_shmdt((char __user *)arg1);
+-		break;
+-	case 3:
+-		/* sys_shmget(): get a shared memory area */
+-		rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3);
+-		break;
+-	default:
+-		rval = -EINVAL;
+-		break;
+-	};
+-	return rval;
+-}
+-
+-#define SUNOS_EWOULDBLOCK 35
+-
+-/* see the sunos man page read(2v) for an explanation
+-   of this garbage. We use O_NDELAY to mark
+-   file descriptors that have been set non-blocking 
+-   using 4.2BSD style calls. (tridge) */
+-
+-static inline int check_nonblock(int ret, int fd)
+-{
+-	if (ret == -EAGAIN) {
+-		struct file * file = fget(fd);
+-		if (file) {
+-			if (file->f_flags & O_NDELAY)
+-				ret = -SUNOS_EWOULDBLOCK;
+-			fput(file);
+-		}
+-	}
+-	return ret;
+-}
+-
+-asmlinkage int sunos_read(unsigned int fd, char __user *buf, int count)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(sys_read(fd,buf,count),fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_readv(unsigned long fd, const struct iovec __user *vector,
+-			   long count)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(sys_readv(fd,vector,count),fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_write(unsigned int fd, char __user *buf, int count)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(sys_write(fd,buf,count),fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_writev(unsigned long fd,
+-			    const struct iovec __user *vector, long count)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(sys_writev(fd,vector,count),fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_recv(int fd, void __user *ubuf, int size, unsigned flags)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(sys_recv(fd,ubuf,size,flags),fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_send(int fd, void __user *buff, int len, unsigned flags)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(sys_send(fd,buff,len,flags),fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_accept(int fd, struct sockaddr __user *sa,
+-			    int __user *addrlen)
+-{
+-	int ret;
+-
+-	while (1) {
+-		ret = check_nonblock(sys_accept(fd,sa,addrlen),fd);	
+-		if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
+-			break;
+-	}
+-
+-	return ret;
+-}
+-
+-#define SUNOS_SV_INTERRUPT 2
+-
+-asmlinkage int
+-sunos_sigaction(int sig, const struct old_sigaction __user *act,
+-		struct old_sigaction __user *oact)
+-{
+-	struct k_sigaction new_ka, old_ka;
+-	int ret;
+-
+-	if (act) {
+-		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))
+-			return -EFAULT;
+-		__get_user(mask, &act->sa_mask);
+-		new_ka.sa.sa_restorer = NULL;
+-		new_ka.ka_restorer = NULL;
+-		siginitset(&new_ka.sa.sa_mask, mask);
+-		new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
+-	}
+-
+-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+-
+-	if (!ret && oact) {
+-		/* In the clone() case we could copy half consistent
+-		 * state to the user, however this could sleep and
+-		 * deadlock us if we held the signal lock on SMP.  So for
+-		 * now I take the easy way out and do no locking.
+-		 * But then again we don't support SunOS lwp's anyways ;-)
+-		 */
+-		old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
+-		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))
+-			 return -EFAULT;
+-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+-	}
+-
+-	return ret;
+-}
+-
+-
+-asmlinkage int sunos_setsockopt(int fd, int level, int optname,
+-				char __user *optval, int optlen)
+-{
+-	int tr_opt = optname;
+-	int ret;
+-
+-	if (level == SOL_IP) {
+-		/* Multicast socketopts (ttl, membership) */
+-		if (tr_opt >=2 && tr_opt <= 6)
+-			tr_opt += 30;
+-	}
+-	ret = sys_setsockopt(fd, level, tr_opt, optval, optlen);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_getsockopt(int fd, int level, int optname,
+-				char __user *optval, int __user *optlen)
+-{
+-	int tr_opt = optname;
+-	int ret;
+-
+-	if (level == SOL_IP) {
+-		/* Multicast socketopts (ttl, membership) */
+-		if (tr_opt >=2 && tr_opt <= 6)
+-			tr_opt += 30;
+-	}
+-	ret = sys_getsockopt(fd, level, tr_opt, optval, optlen);
+-	return ret;
+-}
+diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
+index 9064485..5a7c4c8 100644
+--- a/arch/sparc/kernel/systbls.S
++++ b/arch/sparc/kernel/systbls.S
+@@ -81,124 +81,3 @@ sys_call_table:
+ /*305*/	.long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
+ /*310*/	.long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
+ /*315*/	.long sys_timerfd_settime, sys_timerfd_gettime
+-
+-#ifdef CONFIG_SUNOS_EMUL
+-	/* Now the SunOS syscall table. */
+-
+-	.align 4
+-	.globl sunos_sys_table
+-sunos_sys_table:
+-/*0*/	.long sunos_indir, sys_exit, sys_fork
+-	.long sunos_read, sunos_write, sys_open
+-	.long sys_close, sunos_wait4, sys_creat
+-	.long sys_link, sys_unlink, sunos_execv
+-	.long sys_chdir, sunos_nosys, sys_mknod
+-	.long sys_chmod, sys_lchown16, sunos_brk
+-	.long sunos_nosys, sys_lseek, sunos_getpid
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_getuid, sunos_nosys, sys_ptrace
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sys_access, sunos_nosys, sunos_nosys
+-	.long sys_sync, sys_kill, sys_newstat
+-	.long sunos_nosys, sys_newlstat, sys_dup
+-	.long sys_pipe, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_getgid
+-	.long sunos_nosys, sunos_nosys
+-/*50*/	.long sunos_nosys, sys_acct, sunos_nosys
+-	.long sunos_mctl, sunos_ioctl, sys_reboot
+-	.long sunos_nosys, sys_symlink, sys_readlink
+-	.long sys_execve, sys_umask, sys_chroot
+-	.long sys_newfstat, sunos_nosys, sys_getpagesize
+-	.long sys_msync, sys_vfork, sunos_nosys
+-	.long sunos_nosys, sunos_sbrk, sunos_sstk
+-	.long sunos_mmap, sunos_vadvise, sys_munmap
+-	.long sys_mprotect, sys_madvise, sys_vhangup
+-	.long sunos_nosys, sys_mincore, sys_getgroups16
+-	.long sys_setgroups16, sys_getpgrp, sunos_setpgrp
+-	.long sys_setitimer, sunos_nosys, sys_swapon
+-	.long sys_getitimer, sys_gethostname, sys_sethostname
+-	.long sunos_getdtablesize, sys_dup2, sunos_nop
+-	.long sys_fcntl, sunos_select, sunos_nop
+-	.long sys_fsync, sys_setpriority, sys_socket
+-	.long sys_connect, sunos_accept
+-/*100*/	.long sys_getpriority, sunos_send, sunos_recv
+-	.long sunos_nosys, sys_bind, sunos_setsockopt
+-	.long sys_listen, sunos_nosys, sunos_sigaction
+-	.long sunos_sigblock, sunos_sigsetmask, sys_sigpause
+-	.long sys_sigstack, sys_recvmsg, sys_sendmsg
+-	.long sunos_nosys, sys_gettimeofday, sys_getrusage
+-	.long sunos_getsockopt, sunos_nosys, sunos_readv
+-	.long sunos_writev, sys_settimeofday, sys_fchown16
+-	.long sys_fchmod, sys_recvfrom, sys_setreuid16
+-	.long sys_setregid16, sys_rename, sys_truncate
+-	.long sys_ftruncate, sys_flock, sunos_nosys
+-	.long sys_sendto, sys_shutdown, sys_socketpair
+-	.long sys_mkdir, sys_rmdir, sys_utimes
+-	.long sys_sigreturn, sunos_nosys, sys_getpeername
+-	.long sunos_gethostid, sunos_nosys, sys_getrlimit
+-	.long sys_setrlimit, sunos_killpg, sunos_nosys
+-	.long sunos_nosys, sunos_nosys
+-/*150*/	.long sys_getsockname, sunos_nosys, sunos_nosys
+-	.long sys_poll, sunos_nosys, sunos_nosys
+-	.long sunos_getdirentries, sys_statfs, sys_fstatfs
+-	.long sys_oldumount, sunos_nosys, sunos_nosys
+-	.long sys_getdomainname, sys_setdomainname
+-	.long sunos_nosys, sys_quotactl, sunos_nosys
+-	.long sunos_mount, sys_ustat, sunos_semsys
+-	.long sunos_msgsys, sunos_shmsys, sunos_audit
+-	.long sunos_nosys, sunos_getdents, sys_setsid
+-	.long sys_fchdir, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sys_sigpending, sunos_nosys
+-	.long sys_setpgid, sunos_pathconf, sunos_fpathconf
+-	.long sunos_sysconf, sunos_uname, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-/*200*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys
+-/*250*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys
+-/*260*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys
+-/*270*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys
+-/*280*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys
+-/*290*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys
+-/*300*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys
+-/*310*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys, sunos_nosys, sunos_nosys
+-	.long sunos_nosys
+-
+-#endif
+diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
+index cfaf22c..53caacb 100644
+--- a/arch/sparc/kernel/time.c
++++ b/arch/sparc/kernel/time.c
+@@ -105,7 +105,7 @@ __volatile__ unsigned int *master_l10_limit;
+ 
+ #define TICK_SIZE (tick_nsec / 1000)
+ 
+-irqreturn_t timer_interrupt(int irq, void *dev_id)
++static irqreturn_t timer_interrupt(int dummy, void *dev_id)
+ {
+ 	/* last time the cmos clock got updated */
+ 	static long last_rtc_update;
+diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
+index 463d1be..8acc5cc 100644
+--- a/arch/sparc64/Kconfig
++++ b/arch/sparc64/Kconfig
+@@ -16,6 +16,7 @@ config SPARC64
+ 	bool
+ 	default y
+ 	select HAVE_IDE
++	select HAVE_LMB
+ 	help
+ 	  SPARC is a family of RISC microprocessors designed and marketed by
+ 	  Sun Microsystems, incorporated.  This port covers the newer 64-bit
+@@ -87,9 +88,6 @@ config GENERIC_HARDIRQS_NO__DO_IRQ
+ 	bool
+ 	def_bool y
+ 
+-config ARCH_SUPPORTS_AOUT
+-	def_bool y
+-
+ choice
+ 	prompt "Kernel page size"
+ 	default SPARC64_PAGE_SIZE_8KB
+@@ -147,11 +145,6 @@ config HOTPLUG_CPU
+ 
+ source "init/Kconfig"
+ 
+-config SYSVIPC_COMPAT
+-	bool
+-	depends on COMPAT && SYSVIPC
+-	default y
+-
+ config GENERIC_HARDIRQS
+ 	bool
+ 	default y
+@@ -257,6 +250,26 @@ endchoice
+ 
+ endmenu
+ 
++config NUMA
++	bool "NUMA support"
++
++config NODES_SHIFT
++	int
++	default "4"
++	depends on NEED_MULTIPLE_NODES
++
++# Some NUMA nodes have memory ranges that span
++# other nodes.  Even though a pfn is valid and
++# between a node's start and end pfns, it may not
++# reside on that node.  See memmap_init_zone()
++# for details.
++config NODES_SPAN_OTHER_NODES
++	def_bool y
++	depends on NEED_MULTIPLE_NODES
++
++config ARCH_POPULATES_NODE_MAP
++	def_bool y
++
+ config ARCH_SELECT_MEMORY_MODEL
+ 	def_bool y
+ 
+@@ -379,6 +392,10 @@ config SUN_OPENPROMFS
+ 	  To compile the /proc/openprom support as a module, choose M here: the
+ 	  module will be called openpromfs.  If unsure, choose M.
+ 
++menu "Executable file formats"
++
++source "fs/Kconfig.binfmt"
++
+ config SPARC32_COMPAT
+ 	bool "Kernel support for Linux/Sparc 32bit binary compatibility"
+ 	help
+@@ -391,37 +408,10 @@ config COMPAT
+ 	default y
+ 	select COMPAT_BINFMT_ELF
+ 
+-config BINFMT_AOUT32
+-	bool "Kernel support for 32-bit (ie. SunOS) a.out binaries"
+-	depends on SPARC32_COMPAT && ARCH_SUPPORTS_AOUT
+-	help
+-	  This allows you to run 32-bit a.out format binaries on your Ultra.
+-	  If you want to run SunOS binaries (see SunOS binary emulation below)
+-	  or other a.out binaries, say Y. If unsure, say N.
+-
+-menu "Executable file formats"
+-
+-source "fs/Kconfig.binfmt"
+-
+-config SUNOS_EMUL
+-	bool "SunOS binary emulation"
+-	depends on BINFMT_AOUT32
+-	help
+-	  This allows you to run most SunOS binaries.  If you want to do this,
+-	  say Y here and place appropriate files in /usr/gnemul/sunos. See
+-	  <http://www.ultralinux.org/faq.html> for more information.  If you
+-	  want to run SunOS binaries on an Ultra you must also say Y to
+-	  "Kernel support for 32-bit a.out binaries" above.
+-
+-config SOLARIS_EMUL
+-	tristate "Solaris binary emulation (EXPERIMENTAL)"
+-	depends on SPARC32_COMPAT && NET && EXPERIMENTAL
+-	help
+-	  This is experimental code which will enable you to run (many)
+-	  Solaris binaries on your SPARC Linux machine.
+-
+-	  To compile this code as a module, choose M here: the
+-	  module will be called solaris.
++config SYSVIPC_COMPAT
++	bool
++	depends on COMPAT && SYSVIPC
++	default y
+ 
+ endmenu
+ 
+diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile
+index f0c22f8..9cb75c8 100644
+--- a/arch/sparc64/Makefile
++++ b/arch/sparc64/Makefile
+@@ -27,7 +27,6 @@ endif
+ head-y := arch/sparc64/kernel/head.o arch/sparc64/kernel/init_task.o
+ 
+ core-y				+= arch/sparc64/kernel/ arch/sparc64/mm/
+-core-$(CONFIG_SOLARIS_EMUL)	+= arch/sparc64/solaris/
+ core-y				+= arch/sparc64/math-emu/
+ libs-y				+= arch/sparc64/prom/ arch/sparc64/lib/
+ drivers-$(CONFIG_OPROFILE)	+= arch/sparc64/oprofile/
+diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
+index 9d4bd22..92f7968 100644
+--- a/arch/sparc64/defconfig
++++ b/arch/sparc64/defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc3
+-# Wed Mar 26 04:33:35 2008
++# Linux kernel version: 2.6.25-numa
++# Wed Apr 23 04:49:08 2008
+ #
+ CONFIG_SPARC=y
+ CONFIG_SPARC64=y
+@@ -22,7 +22,6 @@ CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+ CONFIG_ARCH_NO_VIRT_TO_BUS=y
+ CONFIG_OF=y
+ CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+-CONFIG_ARCH_SUPPORTS_AOUT=y
+ CONFIG_SPARC64_PAGE_SIZE_8KB=y
+ # CONFIG_SPARC64_PAGE_SIZE_64KB is not set
+ # CONFIG_SPARC64_PAGE_SIZE_512KB is not set
+@@ -61,6 +60,7 @@ CONFIG_RT_GROUP_SCHED=y
+ CONFIG_USER_SCHED=y
+ # CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
+ CONFIG_RELAY=y
+ CONFIG_NAMESPACES=y
+ # CONFIG_UTS_NS is not set
+@@ -100,7 +100,9 @@ CONFIG_PROFILING=y
+ CONFIG_OPROFILE=m
+ CONFIG_HAVE_OPROFILE=y
+ CONFIG_KPROBES=y
++CONFIG_KRETPROBES=y
+ CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
+ CONFIG_PROC_PAGE_MONITOR=y
+ CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+@@ -131,8 +133,6 @@ CONFIG_DEFAULT_AS=y
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-CONFIG_SYSVIPC_COMPAT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ 
+ #
+@@ -152,6 +152,8 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
+ CONFIG_HUGETLB_PAGE_SIZE_4MB=y
+ # CONFIG_HUGETLB_PAGE_SIZE_512K is not set
+ # CONFIG_HUGETLB_PAGE_SIZE_64K is not set
++# CONFIG_NUMA is not set
++CONFIG_ARCH_POPULATES_NODE_MAP=y
+ CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+ CONFIG_ARCH_SPARSEMEM_ENABLE=y
+ CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+@@ -182,9 +184,6 @@ CONFIG_PCI_MSI=y
+ # CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ CONFIG_SUN_OPENPROMFS=m
+-CONFIG_SPARC32_COMPAT=y
+-CONFIG_COMPAT=y
+-# CONFIG_BINFMT_AOUT32 is not set
+ 
+ #
+ # Executable file formats
+@@ -192,13 +191,14 @@ CONFIG_COMPAT=y
+ CONFIG_BINFMT_ELF=y
+ CONFIG_COMPAT_BINFMT_ELF=y
+ CONFIG_BINFMT_MISC=m
+-CONFIG_SOLARIS_EMUL=y
++CONFIG_SPARC32_COMPAT=y
++CONFIG_COMPAT=y
++CONFIG_SYSVIPC_COMPAT=y
+ CONFIG_SCHED_SMT=y
+ CONFIG_SCHED_MC=y
+ # CONFIG_PREEMPT_NONE is not set
+ CONFIG_PREEMPT_VOLUNTARY=y
+ # CONFIG_PREEMPT is not set
+-# CONFIG_RCU_TRACE is not set
+ # CONFIG_CMDLINE_BOOL is not set
+ 
+ #
+@@ -263,8 +263,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
+ CONFIG_INET6_XFRM_MODE_BEET=m
+ # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+ CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
+ CONFIG_IPV6_TUNNEL=m
+ # CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+ CONFIG_IP_DCCP=m
+@@ -368,7 +370,7 @@ CONFIG_IDE=y
+ CONFIG_BLK_DEV_IDE=y
+ 
+ #
+-# Please see Documentation/ide.txt for help/info on IDE drives
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
+ #
+ # CONFIG_BLK_DEV_IDE_SATA is not set
+ CONFIG_BLK_DEV_IDEDISK=y
+@@ -384,7 +386,6 @@ CONFIG_IDE_PROC_FS=y
+ #
+ # IDE chipset support/bugfixes
+ #
+-CONFIG_IDE_GENERIC=y
+ # CONFIG_BLK_DEV_PLATFORM is not set
+ CONFIG_BLK_DEV_IDEDMA_SFF=y
+ 
+@@ -422,7 +423,7 @@ CONFIG_BLK_DEV_ALI15X3=y
+ # CONFIG_BLK_DEV_VIA82CXXX is not set
+ # CONFIG_BLK_DEV_TC86C001 is not set
+ CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD_ONLY is not set
+ # CONFIG_BLK_DEV_HD is not set
+ 
+ #
+@@ -588,7 +589,6 @@ CONFIG_E1000_NAPI=y
+ # CONFIG_SIS190 is not set
+ # CONFIG_SKGE is not set
+ # CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+ # CONFIG_VIA_VELOCITY is not set
+ CONFIG_TIGON3=m
+ CONFIG_BNX2=m
+@@ -613,6 +613,7 @@ CONFIG_NIU=m
+ #
+ # CONFIG_WLAN_PRE80211 is not set
+ # CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
+ 
+ #
+ # USB Network Adapters
+@@ -788,7 +789,6 @@ CONFIG_I2C_ALGOBIT=y
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_PCF8575 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
+ # CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+@@ -870,6 +870,7 @@ CONFIG_SSB_POSSIBLE=y
+ # Multifunction device drivers
+ #
+ # CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 is not set
+ 
+ #
+ # Multimedia devices
+@@ -1220,10 +1221,6 @@ CONFIG_USB_STORAGE=m
+ # CONFIG_NEW_LEDS is not set
+ # CONFIG_INFINIBAND is not set
+ # CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+ # CONFIG_UIO is not set
+ 
+ #
+@@ -1400,6 +1397,7 @@ CONFIG_SCHEDSTATS=y
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+ # CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_WRITECOUNT is not set
+ # CONFIG_DEBUG_LIST is not set
+ # CONFIG_DEBUG_SG is not set
+ # CONFIG_BOOT_PRINTK_DELAY is not set
+@@ -1426,53 +1424,82 @@ CONFIG_ASYNC_CORE=m
+ CONFIG_ASYNC_MEMCPY=m
+ CONFIG_ASYNC_XOR=m
+ CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
+ CONFIG_CRYPTO_ALGAPI=y
+ CONFIG_CRYPTO_AEAD=y
+ CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+ CONFIG_CRYPTO_HASH=y
+ CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_GF128MUL=m
++CONFIG_CRYPTO_NULL=m
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=y
++CONFIG_CRYPTO_TEST=m
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_LRW=m
++CONFIG_CRYPTO_PCBC=m
++CONFIG_CRYPTO_XTS=m
++
++#
++# Hash modes
++#
+ CONFIG_CRYPTO_HMAC=y
+ CONFIG_CRYPTO_XCBC=y
+-CONFIG_CRYPTO_NULL=m
++
++#
++# Digest
++#
++CONFIG_CRYPTO_CRC32C=m
+ CONFIG_CRYPTO_MD4=y
+ CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_MICHAEL_MIC=m
+ CONFIG_CRYPTO_SHA1=y
+ CONFIG_CRYPTO_SHA256=m
+ CONFIG_CRYPTO_SHA512=m
+-CONFIG_CRYPTO_WP512=m
+ CONFIG_CRYPTO_TGR192=m
+-CONFIG_CRYPTO_GF128MUL=m
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-CONFIG_CRYPTO_LRW=m
+-CONFIG_CRYPTO_XTS=m
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-CONFIG_CRYPTO_FCRYPT=m
+-CONFIG_CRYPTO_BLOWFISH=m
+-CONFIG_CRYPTO_TWOFISH=m
+-CONFIG_CRYPTO_TWOFISH_COMMON=m
+-CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_WP512=m
++
++#
++# Ciphers
++#
+ CONFIG_CRYPTO_AES=m
++CONFIG_CRYPTO_ANUBIS=m
++CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_BLOWFISH=m
++CONFIG_CRYPTO_CAMELLIA=m
+ CONFIG_CRYPTO_CAST5=m
+ CONFIG_CRYPTO_CAST6=m
+-CONFIG_CRYPTO_TEA=m
+-CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_FCRYPT=m
+ CONFIG_CRYPTO_KHAZAD=m
+-CONFIG_CRYPTO_ANUBIS=m
+-CONFIG_CRYPTO_SEED=m
+ # CONFIG_CRYPTO_SALSA20 is not set
++CONFIG_CRYPTO_SEED=m
++CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_TEA=m
++CONFIG_CRYPTO_TWOFISH=m
++CONFIG_CRYPTO_TWOFISH_COMMON=m
++
++#
++# Compression
++#
+ CONFIG_CRYPTO_DEFLATE=y
+-CONFIG_CRYPTO_MICHAEL_MIC=m
+-CONFIG_CRYPTO_CRC32C=m
+-CONFIG_CRYPTO_CAMELLIA=m
+-CONFIG_CRYPTO_TEST=m
+-CONFIG_CRYPTO_AUTHENC=m
+ # CONFIG_CRYPTO_LZO is not set
+ CONFIG_CRYPTO_HW=y
+ # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+@@ -1493,3 +1520,4 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
+index 1bf5b18..63c6ae0 100644
+--- a/arch/sparc64/kernel/Makefile
++++ b/arch/sparc64/kernel/Makefile
+@@ -10,7 +10,7 @@ extra-y		:= head.o init_task.o vmlinux.lds
+ obj-y		:= process.o setup.o cpu.o idprom.o \
+ 		   traps.o auxio.o una_asm.o sysfs.o iommu.o \
+ 		   irq.o ptrace.o time.o sys_sparc.o signal.o \
+-		   unaligned.o central.o pci.o starfire.o semaphore.o \
++		   unaligned.o central.o pci.o starfire.o \
+ 		   power.o sbus.o sparc64_ksyms.o chmc.o \
+ 		   visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
+ 
+@@ -21,7 +21,6 @@ obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o \
+ obj-$(CONFIG_PCI_MSI)	+= pci_msi.o
+ obj-$(CONFIG_SMP)	 += smp.o trampoline.o hvtramp.o
+ obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
+-obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
+ obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
+@@ -30,11 +29,3 @@ obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o
+ obj-$(CONFIG_AUDIT) += audit.o
+ obj-$(CONFIG_AUDIT)$(CONFIG_SPARC32_COMPAT) += compat_audit.o
+ obj-y += $(obj-yy)
+-
+-ifdef CONFIG_SUNOS_EMUL
+-  obj-y += sys_sunos32.o sunos_ioctl32.o
+-else
+-  ifdef CONFIG_SOLARIS_EMUL
+-    obj-y += sys_sunos32.o sunos_ioctl32.o
+-  endif
+-endif
+diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
+deleted file mode 100644
+index 9877f2d..0000000
+--- a/arch/sparc64/kernel/binfmt_aout32.c
++++ /dev/null
+@@ -1,419 +0,0 @@
+-/*
+- *  linux/fs/binfmt_aout.c
+- *
+- *  Copyright (C) 1991, 1992, 1996  Linus Torvalds
+- *
+- *  Hacked a bit by DaveM to make it work with 32-bit SunOS
+- *  binaries on the sparc64 port.
+- */
+-
+-#include <linux/module.h>
+-
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/mman.h>
+-#include <linux/a.out.h>
+-#include <linux/errno.h>
+-#include <linux/signal.h>
+-#include <linux/string.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/stat.h>
+-#include <linux/fcntl.h>
+-#include <linux/ptrace.h>
+-#include <linux/user.h>
+-#include <linux/slab.h>
+-#include <linux/binfmts.h>
+-#include <linux/personality.h>
+-#include <linux/init.h>
+-
+-#include <asm/system.h>
+-#include <asm/uaccess.h>
+-#include <asm/pgalloc.h>
+-#include <asm/mmu_context.h>
+-#include <asm/a.out-core.h>
+-
+-static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
+-static int load_aout32_library(struct file*);
+-static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+-
+-static struct linux_binfmt aout32_format = {
+-	.module		= THIS_MODULE,
+-	.load_binary	= load_aout32_binary,
+-	.load_shlib	= load_aout32_library,
+-	.core_dump	= aout32_core_dump,
+-	.min_coredump	= PAGE_SIZE,
+-};
+-
+-static void set_brk(unsigned long start, unsigned long end)
+-{
+-	start = PAGE_ALIGN(start);
+-	end = PAGE_ALIGN(end);
+-	if (end <= start)
+-		return;
+-	down_write(&current->mm->mmap_sem);
+-	do_brk(start, end - start);
+-	up_write(&current->mm->mmap_sem);
+-}
+-
+-/*
+- * These are the only things you should do on a core-file: use only these
+- * 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;
+-}
+-
+-#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)
+-
+-/*
+- * Routine writes a core dump image in the current directory.
+- * Currently only a stub-function.
+- *
+- * Note that setuid/setgid files won't make a core-dump if the uid/gid
+- * changed due to the set[u|g]id. It's enforced by the "current->mm->dumpable"
+- * field, which also makes sure the core-dumps won't be recursive if the
+- * dumping of the process results in another error..
+- */
+-
+-static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+-{
+-	mm_segment_t fs;
+-	int has_dumped = 0;
+-	unsigned long dump_start, dump_size;
+-	struct user dump;
+-#       define START_DATA(u)    (u.u_tsize)
+-#       define START_STACK(u)   ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
+-
+-	fs = get_fs();
+-	set_fs(KERNEL_DS);
+-	has_dumped = 1;
+-	current->flags |= PF_DUMPCORE;
+-       	strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
+-	dump.signal = signr;
+-	aout_dump_thread(regs, &dump);
+-
+-/* If the size of the dump file exceeds the rlimit, then see what would happen
+-   if we wrote the stack, but not the data area.  */
+-	if (dump.u_dsize + dump.u_ssize > limit)
+-		dump.u_dsize = 0;
+-
+-/* Make sure we have enough room to write the stack and data areas. */
+-	if (dump.u_ssize > limit)
+-		dump.u_ssize = 0;
+-
+-/* make sure we actually have a data and stack area to dump */
+-	set_fs(USER_DS);
+-	if (!access_ok(VERIFY_READ, (void __user *) START_DATA(dump), dump.u_dsize))
+-		dump.u_dsize = 0;
+-	if (!access_ok(VERIFY_READ, (void __user *) START_STACK(dump), dump.u_ssize))
+-		dump.u_ssize = 0;
+-
+-	set_fs(KERNEL_DS);
+-/* struct user */
+-	DUMP_WRITE(&dump,sizeof(dump));
+-/* now we start writing out the user space info */
+-	set_fs(USER_DS);
+-/* Dump the data area */
+-	if (dump.u_dsize != 0) {
+-		dump_start = START_DATA(dump);
+-		dump_size = dump.u_dsize;
+-		DUMP_WRITE(dump_start,dump_size);
+-	}
+-/* Now prepare to dump the stack area */
+-	if (dump.u_ssize != 0) {
+-		dump_start = START_STACK(dump);
+-		dump_size = dump.u_ssize;
+-		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;
+-}
+-
+-/*
+- * create_aout32_tables() parses the env- and arg-strings in new user
+- * memory and creates the pointer tables from them, and puts their
+- * addresses on the "stack", returning the new stack pointer value.
+- */
+-
+-static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bprm)
+-{
+-	u32 __user *argv;
+-	u32 __user *envp;
+-	u32 __user *sp;
+-	int argc = bprm->argc;
+-	int envc = bprm->envc;
+-
+-	sp = (u32 __user *)((-(unsigned long)sizeof(char *))&(unsigned long)p);
+-
+-	/* This imposes the proper stack alignment for a new process. */
+-	sp = (u32 __user *) (((unsigned long) sp) & ~7);
+-	if ((envc+argc+3)&1)
+-		--sp;
+-
+-	sp -= envc+1;
+-	envp = sp;
+-	sp -= argc+1;
+-	argv = sp;
+-	put_user(argc,--sp);
+-	current->mm->arg_start = (unsigned long) p;
+-	while (argc-->0) {
+-		char c;
+-		put_user(((u32)(unsigned long)(p)),argv++);
+-		do {
+-			get_user(c,p++);
+-		} while (c);
+-	}
+-	put_user(0,argv);
+-	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+-	while (envc-->0) {
+-		char c;
+-		put_user(((u32)(unsigned long)(p)),envp++);
+-		do {
+-			get_user(c,p++);
+-		} while (c);
+-	}
+-	put_user(0,envp);
+-	current->mm->env_end = (unsigned long) p;
+-	return sp;
+-}
+-
+-/*
+- * These are the functions used to load a.out style executables and shared
+- * libraries.  There is no binary dependent code anywhere else.
+- */
+-
+-static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+-{
+-	struct exec ex;
+-	unsigned long error;
+-	unsigned long fd_offset;
+-	unsigned long rlim;
+-	unsigned long orig_thr_flags;
+-	int retval;
+-
+-	ex = *((struct exec *) bprm->buf);		/* exec-header */
+-	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
+-	     N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
+-	    N_TRSIZE(ex) || N_DRSIZE(ex) ||
+-	    bprm->file->f_path.dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+-		return -ENOEXEC;
+-	}
+-
+-	fd_offset = N_TXTOFF(ex);
+-
+-	/* Check initial limits. This avoids letting people circumvent
+-	 * size limits imposed on them by creating programs with large
+-	 * arrays in the data or bss.
+-	 */
+-	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+-	if (rlim >= RLIM_INFINITY)
+-		rlim = ~0;
+-	if (ex.a_data + ex.a_bss > rlim)
+-		return -ENOMEM;
+-
+-	/* Flush all traces of the currently running executable */
+-	retval = flush_old_exec(bprm);
+-	if (retval)
+-		return retval;
+-
+-	/* OK, This is the point of no return */
+-	set_personality(PER_SUNOS);
+-
+-	current->mm->end_code = ex.a_text +
+-		(current->mm->start_code = N_TXTADDR(ex));
+-	current->mm->end_data = ex.a_data +
+-		(current->mm->start_data = N_DATADDR(ex));
+-	current->mm->brk = ex.a_bss +
+-		(current->mm->start_brk = N_BSSADDR(ex));
+-	current->mm->free_area_cache = current->mm->mmap_base;
+-	current->mm->cached_hole_size = 0;
+-
+-	current->mm->mmap = NULL;
+-	compute_creds(bprm);
+- 	current->flags &= ~PF_FORKNOEXEC;
+-	if (N_MAGIC(ex) == NMAGIC) {
+-		loff_t pos = fd_offset;
+-		/* Fuck me plenty... */
+-		down_write(&current->mm->mmap_sem);	
+-		error = do_brk(N_TXTADDR(ex), ex.a_text);
+-		up_write(&current->mm->mmap_sem);
+-		bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+-			  ex.a_text, &pos);
+-		down_write(&current->mm->mmap_sem);
+-		error = do_brk(N_DATADDR(ex), ex.a_data);
+-		up_write(&current->mm->mmap_sem);
+-		bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex),
+-			  ex.a_data, &pos);
+-		goto beyond_if;
+-	}
+-
+-	if (N_MAGIC(ex) == OMAGIC) {
+-		loff_t pos = fd_offset;
+-		down_write(&current->mm->mmap_sem);
+-		do_brk(N_TXTADDR(ex) & PAGE_MASK,
+-			ex.a_text+ex.a_data + PAGE_SIZE - 1);
+-		up_write(&current->mm->mmap_sem);
+-		bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+-			  ex.a_text+ex.a_data, &pos);
+-	} else {
+-		static unsigned long error_time;
+-		if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
+-		    (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time) > 5*HZ)
+-		{
+-			printk(KERN_NOTICE "executable not page aligned\n");
+-			error_time = jiffies;
+-		}
+-
+-		if (!bprm->file->f_op->mmap) {
+-			loff_t pos = fd_offset;
+-			down_write(&current->mm->mmap_sem);
+-			do_brk(0, ex.a_text+ex.a_data);
+-			up_write(&current->mm->mmap_sem);
+-			bprm->file->f_op->read(bprm->file,
+-				  (char __user *)N_TXTADDR(ex),
+-				  ex.a_text+ex.a_data, &pos);
+-			goto beyond_if;
+-		}
+-
+-	        down_write(&current->mm->mmap_sem);
+-		error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
+-			PROT_READ | PROT_EXEC,
+-			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+-			fd_offset);
+-	        up_write(&current->mm->mmap_sem);
+-
+-		if (error != N_TXTADDR(ex)) {
+-			send_sig(SIGKILL, current, 0);
+-			return error;
+-		}
+-
+-	        down_write(&current->mm->mmap_sem);
+- 		error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
+-				PROT_READ | PROT_WRITE | PROT_EXEC,
+-				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+-				fd_offset + ex.a_text);
+-	        up_write(&current->mm->mmap_sem);
+-		if (error != N_DATADDR(ex)) {
+-			send_sig(SIGKILL, current, 0);
+-			return error;
+-		}
+-	}
+-beyond_if:
+-	set_binfmt(&aout32_format);
+-
+-	set_brk(current->mm->start_brk, current->mm->brk);
+-
+-	/* Make sure STACK_TOP returns the right thing.  */
+-	orig_thr_flags = current_thread_info()->flags;
+-	current_thread_info()->flags |= _TIF_32BIT;
+-
+-	retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
+-	if (retval < 0) { 
+-		current_thread_info()->flags = orig_thr_flags;
+-
+-		/* Someone check-me: is this error path enough? */ 
+-		send_sig(SIGKILL, current, 0); 
+-		return retval;
+-	}
+-
+-	current->mm->start_stack =
+-		(unsigned long) create_aout32_tables((char __user *)bprm->p, bprm);
+-	tsb_context_switch(current->mm);
+-
+-	start_thread32(regs, ex.a_entry, current->mm->start_stack);
+-	if (current->ptrace & PT_PTRACED)
+-		send_sig(SIGTRAP, current, 0);
+-	return 0;
+-}
+-
+-/* N.B. Move to .h file and use code in fs/binfmt_aout.c? */
+-static int load_aout32_library(struct file *file)
+-{
+-	struct inode * inode;
+-	unsigned long bss, start_addr, len;
+-	unsigned long error;
+-	int retval;
+-	struct exec ex;
+-
+-	inode = file->f_path.dentry->d_inode;
+-
+-	retval = -ENOEXEC;
+-	error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
+-	if (error != sizeof(ex))
+-		goto out;
+-
+-	/* We come in here for the regular a.out style of shared libraries */
+-	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
+-	    N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
+-	    inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+-		goto out;
+-	}
+-
+-	if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
+-	    (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
+-		printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
+-		goto out;
+-	}
+-
+-	if (N_FLAGS(ex))
+-		goto out;
+-
+-	/* For  QMAGIC, the starting address is 0x20 into the page.  We mask
+-	   this off to get the starting address for the page */
+-
+-	start_addr =  ex.a_entry & 0xfffff000;
+-
+-	/* Now use mmap to map the library into memory. */
+-	down_write(&current->mm->mmap_sem);
+-	error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
+-			PROT_READ | PROT_WRITE | PROT_EXEC,
+-			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+-			N_TXTOFF(ex));
+-	up_write(&current->mm->mmap_sem);
+-	retval = error;
+-	if (error != start_addr)
+-		goto out;
+-
+-	len = PAGE_ALIGN(ex.a_text + ex.a_data);
+-	bss = ex.a_text + ex.a_data + ex.a_bss;
+-	if (bss > len) {
+-		down_write(&current->mm->mmap_sem);
+-		error = do_brk(start_addr + len, bss - len);
+-		up_write(&current->mm->mmap_sem);
+-		retval = error;
+-		if (error != start_addr + len)
+-			goto out;
+-	}
+-	retval = 0;
+-out:
+-	return retval;
+-}
+-
+-static int __init init_aout32_binfmt(void)
+-{
+-	return register_binfmt(&aout32_format);
+-}
+-
+-static void __exit exit_aout32_binfmt(void)
+-{
+-	unregister_binfmt(&aout32_format);
+-}
+-
+-module_init(init_aout32_binfmt);
+-module_exit(exit_aout32_binfmt);
+diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
+index 04ab81c..bc26322 100644
+--- a/arch/sparc64/kernel/ebus.c
++++ b/arch/sparc64/kernel/ebus.c
+@@ -396,6 +396,7 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de
+ 	sd->op = &dev->ofdev;
+ 	sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu;
+ 	sd->stc = dev->bus->ofdev.dev.parent->archdata.stc;
++	sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node;
+ 
+ 	dev->ofdev.node = dp;
+ 	dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
+diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
+index 49eca4b..fd06e93 100644
+--- a/arch/sparc64/kernel/entry.S
++++ b/arch/sparc64/kernel/entry.S
+@@ -47,7 +47,7 @@ do_fpdis:
+ 	ba,pt		%xcc, etrap
+ 109:	 or		%g7, %lo(109b), %g7
+ 	add		%g0, %g0, %g0
+-	ba,a,pt		%xcc, rtrap_clr_l6
++	ba,a,pt		%xcc, rtrap
+ 
+ 1:	TRAP_LOAD_THREAD_REG(%g6, %g1)
+ 	ldub		[%g6 + TI_FPSAVED], %g5
+@@ -226,7 +226,7 @@ fp_other_bounce:
+ 	call		do_fpother
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ 	.globl		do_fpother_check_fitos
+ 	.align		32
+@@ -489,7 +489,7 @@ utrap_trap:		/* %g3=handler,%g4=level */
+         call		bad_trap
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ invoke_utrap:
+ 	sllx		%g3, 3, %g3
+@@ -607,7 +607,7 @@ __spitfire_cee_trap_continue:
+ 	call		spitfire_access_error
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ 	/* This is the trap handler entry point for ECC correctable
+ 	 * errors.  They are corrected, but we listen for the trap
+@@ -686,7 +686,7 @@ __spitfire_data_access_exception_tl1:
+ 	call		spitfire_data_access_exception_tl1
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ __spitfire_data_access_exception:
+ 	rdpr		%pstate, %g4
+@@ -705,7 +705,7 @@ __spitfire_data_access_exception:
+ 	call		spitfire_data_access_exception
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ 	.globl		__spitfire_insn_access_exception
+ 	.globl		__spitfire_insn_access_exception_tl1
+@@ -725,7 +725,7 @@ __spitfire_insn_access_exception_tl1:
+ 	call		spitfire_insn_access_exception_tl1
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ __spitfire_insn_access_exception:
+ 	rdpr		%pstate, %g4
+@@ -743,7 +743,7 @@ __spitfire_insn_access_exception:
+ 	call		spitfire_insn_access_exception
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ 	/* These get patched into the trap table at boot time
+ 	 * once we know we have a cheetah processor.
+@@ -937,7 +937,7 @@ do_dcpe_tl1_fatal:
+ 	call		cheetah_plus_parity_error
+ 	 add		%sp, PTREGS_OFF, %o1
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ do_icpe_tl1:
+ 	rdpr		%tl, %g1		! Save original trap level
+@@ -979,7 +979,7 @@ do_icpe_tl1_fatal:
+ 	call		cheetah_plus_parity_error
+ 	 add		%sp, PTREGS_OFF, %o1
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 	
+ dcpe_icpe_tl1_common:
+ 	/* Flush D-cache, re-enable D/I caches in DCU and finally
+@@ -1281,7 +1281,7 @@ __do_privact:
+ 	call		do_privact
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ 	.globl		do_mna
+ do_mna:
+@@ -1308,7 +1308,7 @@ do_mna:
+ 	call		mem_address_unaligned
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ 	.globl		do_lddfmna
+ do_lddfmna:
+@@ -1326,7 +1326,7 @@ do_lddfmna:
+ 	call		handle_lddfmna
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ 	.globl		do_stdfmna
+ do_stdfmna:
+@@ -1344,7 +1344,7 @@ do_stdfmna:
+ 	call		handle_stdfmna
+ 	 add		%sp, PTREGS_OFF, %o0
+ 	ba,pt		%xcc, rtrap
+-	 clr		%l6
++	 nop
+ 
+ 	.globl	breakpoint_trap
+ breakpoint_trap:
+@@ -1353,63 +1353,6 @@ breakpoint_trap:
+ 	ba,pt		%xcc, rtrap
+ 	 nop
+ 
+-#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
+-    defined(CONFIG_SOLARIS_EMUL_MODULE)
+-	/* SunOS uses syscall zero as the 'indirect syscall' it looks
+-	 * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
+-	 * This is complete brain damage.
+-	 */
+-	.globl	sunos_indir
+-sunos_indir:
+-	srl		%o0, 0, %o0
+-	mov		%o7, %l4
+-	cmp		%o0, NR_SYSCALLS
+-	blu,a,pt	%icc, 1f
+-	 sll		%o0, 0x2, %o0
+-	sethi		%hi(sunos_nosys), %l6
+-	b,pt		%xcc, 2f
+-	 or		%l6, %lo(sunos_nosys), %l6
+-1:	sethi		%hi(sunos_sys_table), %l7
+-	or		%l7, %lo(sunos_sys_table), %l7
+-	lduw		[%l7 + %o0], %l6
+-2:	mov		%o1, %o0
+-	mov		%o2, %o1
+-	mov		%o3, %o2
+-	mov		%o4, %o3
+-	mov		%o5, %o4
+-	call		%l6
+-	 mov		%l4, %o7
+-
+-	.globl	sunos_getpid
+-sunos_getpid:
+-	call	sys_getppid
+-	 nop
+-	call	sys_getpid
+-	 stx	%o0, [%sp + PTREGS_OFF + PT_V9_I1]
+-	b,pt	%xcc, ret_sys_call
+-	 stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-
+-	/* SunOS getuid() returns uid in %o0 and euid in %o1 */
+-	.globl	sunos_getuid
+-sunos_getuid:
+-	call	sys32_geteuid16
+-	 nop
+-	call	sys32_getuid16
+-	 stx	%o0, [%sp + PTREGS_OFF + PT_V9_I1]
+-	b,pt	%xcc, ret_sys_call
+-	 stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-
+-	/* SunOS getgid() returns gid in %o0 and egid in %o1 */
+-	.globl	sunos_getgid
+-sunos_getgid:
+-	call	sys32_getegid16
+-	 nop
+-	call	sys32_getgid16
+-	 stx	%o0, [%sp + PTREGS_OFF + PT_V9_I1]
+-	b,pt	%xcc, ret_sys_call
+-	 stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-#endif
+-
+ 	/* SunOS's execv() call only specifies the argv argument, the
+ 	 * environment settings are the same as the calling processes.
+ 	 */
+@@ -1481,13 +1424,13 @@ sys32_rt_sigreturn:
+ 1:		ldx		[%curptr + TI_FLAGS], %l5
+ 		andcc		%l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
+ 		be,pt		%icc, rtrap
+-		 clr		%l6
++		 nop
+ 		add		%sp, PTREGS_OFF, %o0
+ 		call		syscall_trace
+ 		 mov		1, %o1
+ 
+ 		ba,pt		%xcc, rtrap
+-		 clr		%l6
++		 nop
+ 
+ 	/* This is how fork() was meant to be done, 8 instruction entry.
+ 	 *
+@@ -1591,7 +1534,7 @@ linux_syscall_trace:
+ 	 mov		%i4, %o4
+ 
+ 
+-	/* Linux 32-bit and SunOS system calls enter here... */
++	/* Linux 32-bit system calls enter here... */
+ 	.align	32
+ 	.globl	linux_sparc_syscall32
+ linux_sparc_syscall32:
+@@ -1614,9 +1557,9 @@ linux_sparc_syscall32:
+ 	 srl		%i3, 0, %o3				! IEU0
+ 	ba,a,pt		%xcc, 3f
+ 
+-	/* Linux native and SunOS system calls enter here... */
++	/* Linux native system calls enter here... */
+ 	.align	32
+-	.globl	linux_sparc_syscall, ret_sys_call
++	.globl	linux_sparc_syscall
+ linux_sparc_syscall:
+ 	/* Direct access to user regs, much faster. */
+ 	cmp		%g1, NR_SYSCALLS			! IEU1	Group
+@@ -1662,7 +1605,7 @@ ret_sys_call:
+ 	bne,pn		%icc, linux_syscall_trace2
+ 	 add		%l1, 0x4, %l2			! npc = npc+4
+ 	stx		%l1, [%sp + PTREGS_OFF + PT_V9_TPC]
+-	ba,pt		%xcc, rtrap_clr_l6
++	ba,pt		%xcc, rtrap
+ 	 stx		%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
+ 
+ 1:
+@@ -1673,7 +1616,6 @@ ret_sys_call:
+ 	sub		%g0, %o0, %o0
+ 	or		%g3, %g2, %g3
+ 	stx		%o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-	mov		1, %l6
+ 	stx		%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
+ 	bne,pn		%icc, linux_syscall_trace2
+ 	 add		%l1, 0x4, %l2			! npc = npc+4
+diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h
+index 4a91e9c..32fbab6 100644
+--- a/arch/sparc64/kernel/entry.h
++++ b/arch/sparc64/kernel/entry.h
+@@ -20,7 +20,6 @@ extern void timer_interrupt(int irq, struct pt_regs *regs);
+ 
+ extern void do_notify_resume(struct pt_regs *regs,
+ 			     unsigned long orig_i0,
+-			     int restart_syscall,
+ 			     unsigned long thread_info_flags);
+ 
+ extern asmlinkage void syscall_trace(struct pt_regs *regs,
+diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
+index 4b2bf9e..b49d3b6 100644
+--- a/arch/sparc64/kernel/etrap.S
++++ b/arch/sparc64/kernel/etrap.S
+@@ -53,7 +53,11 @@ etrap_irq:
+ 		stx	%g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
+ 		rd	%y, %g3
+ 		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
++		rdpr	%tt, %g1
+ 		st	%g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]
++		sethi	%hi(PT_REGS_MAGIC), %g3
++		or	%g3, %g1, %g1
++		st	%g1, [%g2 + STACKFRAME_SZ + PT_V9_MAGIC]
+ 
+ 		rdpr	%cansave, %g1
+ 		brnz,pt %g1, etrap_save
+diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
+index 756fa24..2a37a6c 100644
+--- a/arch/sparc64/kernel/iommu.c
++++ b/arch/sparc64/kernel/iommu.c
+@@ -173,9 +173,11 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np
+ }
+ 
+ int iommu_table_init(struct iommu *iommu, int tsbsize,
+-		     u32 dma_offset, u32 dma_addr_mask)
++		     u32 dma_offset, u32 dma_addr_mask,
++		     int numa_node)
+ {
+-	unsigned long i, tsbbase, order, sz, num_tsb_entries;
++	unsigned long i, order, sz, num_tsb_entries;
++	struct page *page;
+ 
+ 	num_tsb_entries = tsbsize / sizeof(iopte_t);
+ 
+@@ -188,11 +190,12 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
+ 	/* Allocate and initialize the free area map.  */
+ 	sz = num_tsb_entries / 8;
+ 	sz = (sz + 7UL) & ~7UL;
+-	iommu->arena.map = kzalloc(sz, GFP_KERNEL);
++	iommu->arena.map = kmalloc_node(sz, GFP_KERNEL, numa_node);
+ 	if (!iommu->arena.map) {
+ 		printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n");
+ 		return -ENOMEM;
+ 	}
++	memset(iommu->arena.map, 0, sz);
+ 	iommu->arena.limit = num_tsb_entries;
+ 
+ 	if (tlb_type != hypervisor)
+@@ -201,21 +204,23 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
+ 	/* Allocate and initialize the dummy page which we
+ 	 * set inactive IO PTEs to point to.
+ 	 */
+-	iommu->dummy_page = get_zeroed_page(GFP_KERNEL);
+-	if (!iommu->dummy_page) {
++	page = alloc_pages_node(numa_node, GFP_KERNEL, 0);
++	if (!page) {
+ 		printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n");
+ 		goto out_free_map;
+ 	}
++	iommu->dummy_page = (unsigned long) page_address(page);
++	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+ 	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+ 
+ 	/* Now allocate and setup the IOMMU page table itself.  */
+ 	order = get_order(tsbsize);
+-	tsbbase = __get_free_pages(GFP_KERNEL, order);
+-	if (!tsbbase) {
++	page = alloc_pages_node(numa_node, GFP_KERNEL, order);
++	if (!page) {
+ 		printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n");
+ 		goto out_free_dummy_page;
+ 	}
+-	iommu->page_table = (iopte_t *)tsbbase;
++	iommu->page_table = (iopte_t *)page_address(page);
+ 
+ 	for (i = 0; i < num_tsb_entries; i++)
+ 		iopte_make_dummy(iommu, &iommu->page_table[i]);
+@@ -276,20 +281,24 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
+ static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
+ 				   dma_addr_t *dma_addrp, gfp_t gfp)
+ {
++	unsigned long flags, order, first_page;
+ 	struct iommu *iommu;
++	struct page *page;
++	int npages, nid;
+ 	iopte_t *iopte;
+-	unsigned long flags, order, first_page;
+ 	void *ret;
+-	int npages;
+ 
+ 	size = IO_PAGE_ALIGN(size);
+ 	order = get_order(size);
+ 	if (order >= 10)
+ 		return NULL;
+ 
+-	first_page = __get_free_pages(gfp, order);
+-	if (first_page == 0UL)
++	nid = dev->archdata.numa_node;
++	page = alloc_pages_node(nid, gfp, order);
++	if (unlikely(!page))
+ 		return NULL;
++
++	first_page = (unsigned long) page_address(page);
+ 	memset((char *)first_page, 0, PAGE_SIZE << order);
+ 
+ 	iommu = dev->archdata.iommu;
+diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c
+index b5f7b35..a2af5ed 100644
+--- a/arch/sparc64/kernel/isa.c
++++ b/arch/sparc64/kernel/isa.c
+@@ -92,6 +92,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
+ 		sd->op = &isa_dev->ofdev;
+ 		sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu;
+ 		sd->stc = isa_br->ofdev.dev.parent->archdata.stc;
++		sd->numa_node = isa_br->ofdev.dev.parent->archdata.numa_node;
+ 
+ 		isa_dev->ofdev.node = dp;
+ 		isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
+diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
+index 9100835..dde52bc 100644
+--- a/arch/sparc64/kernel/mdesc.c
++++ b/arch/sparc64/kernel/mdesc.c
+@@ -1,10 +1,10 @@
+ /* mdesc.c: Sun4V machine description handling.
+  *
+- * Copyright (C) 2007 David S. Miller <davem at davemloft.net>
++ * Copyright (C) 2007, 2008 David S. Miller <davem at davemloft.net>
+  */
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+-#include <linux/bootmem.h>
++#include <linux/lmb.h>
+ #include <linux/log2.h>
+ #include <linux/list.h>
+ #include <linux/slab.h>
+@@ -84,24 +84,28 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
+ 	hp->handle_size = handle_size;
+ }
+ 
+-static struct mdesc_handle * __init mdesc_bootmem_alloc(unsigned int mdesc_size)
++static struct mdesc_handle * __init mdesc_lmb_alloc(unsigned int mdesc_size)
+ {
+-	struct mdesc_handle *hp;
+ 	unsigned int handle_size, alloc_size;
++	struct mdesc_handle *hp;
++	unsigned long paddr;
+ 
+ 	handle_size = (sizeof(struct mdesc_handle) -
+ 		       sizeof(struct mdesc_hdr) +
+ 		       mdesc_size);
+ 	alloc_size = PAGE_ALIGN(handle_size);
+ 
+-	hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL);
+-	if (hp)
+-		mdesc_handle_init(hp, handle_size, hp);
++	paddr = lmb_alloc(alloc_size, PAGE_SIZE);
+ 
++	hp = NULL;
++	if (paddr) {
++		hp = __va(paddr);
++		mdesc_handle_init(hp, handle_size, hp);
++	}
+ 	return hp;
+ }
+ 
+-static void mdesc_bootmem_free(struct mdesc_handle *hp)
++static void mdesc_lmb_free(struct mdesc_handle *hp)
+ {
+ 	unsigned int alloc_size, handle_size = hp->handle_size;
+ 	unsigned long start, end;
+@@ -124,9 +128,9 @@ static void mdesc_bootmem_free(struct mdesc_handle *hp)
+ 	}
+ }
+ 
+-static struct mdesc_mem_ops bootmem_mdesc_ops = {
+-	.alloc = mdesc_bootmem_alloc,
+-	.free  = mdesc_bootmem_free,
++static struct mdesc_mem_ops lmb_mdesc_ops = {
++	.alloc = mdesc_lmb_alloc,
++	.free  = mdesc_lmb_free,
+ };
+ 
+ static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
+@@ -888,7 +892,7 @@ void __init sun4v_mdesc_init(void)
+ 
+ 	printk("MDESC: Size is %lu bytes.\n", len);
+ 
+-	hp = mdesc_alloc(len, &bootmem_mdesc_ops);
++	hp = mdesc_alloc(len, &lmb_mdesc_ops);
+ 	if (hp == NULL) {
+ 		prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
+ 		prom_halt();
+diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
+index 0fd9db9..9e58e8c 100644
+--- a/arch/sparc64/kernel/of_device.c
++++ b/arch/sparc64/kernel/of_device.c
+@@ -6,6 +6,7 @@
+ #include <linux/mod_devicetable.h>
+ #include <linux/slab.h>
+ #include <linux/errno.h>
++#include <linux/irq.h>
+ #include <linux/of_device.h>
+ #include <linux/of_platform.h>
+ 
+@@ -660,6 +661,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
+ 	struct device_node *dp = op->node;
+ 	struct device_node *pp, *ip;
+ 	unsigned int orig_irq = irq;
++	int nid;
+ 
+ 	if (irq == 0xffffffff)
+ 		return irq;
+@@ -672,7 +674,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
+ 			printk("%s: direct translate %x --> %x\n",
+ 			       dp->full_name, orig_irq, irq);
+ 
+-		return irq;
++		goto out;
+ 	}
+ 
+ 	/* Something more complicated.  Walk up to the root, applying
+@@ -744,6 +746,14 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
+ 		printk("%s: Apply IRQ trans [%s] %x --> %x\n",
+ 		       op->node->full_name, ip->full_name, orig_irq, irq);
+ 
++out:
++	nid = of_node_to_nid(dp);
++	if (nid != -1) {
++		cpumask_t numa_mask = node_to_cpumask(nid);
++
++		irq_set_affinity(irq, numa_mask);
++	}
++
+ 	return irq;
+ }
+ 
+diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
+index 545356b..49f9127 100644
+--- a/arch/sparc64/kernel/pci.c
++++ b/arch/sparc64/kernel/pci.c
+@@ -369,10 +369,12 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
+ 	sd->host_controller = pbm;
+ 	sd->prom_node = node;
+ 	sd->op = of_find_device_by_node(node);
++	sd->numa_node = pbm->numa_node;
+ 
+ 	sd = &sd->op->dev.archdata;
+ 	sd->iommu = pbm->iommu;
+ 	sd->stc = &pbm->stc;
++	sd->numa_node = pbm->numa_node;
+ 
+ 	type = of_get_property(node, "device_type", NULL);
+ 	if (type == NULL)
+@@ -1159,6 +1161,16 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_NUMA
++int pcibus_to_node(struct pci_bus *pbus)
++{
++	struct pci_pbm_info *pbm = pbus->sysdata;
++
++	return pbm->numa_node;
++}
++EXPORT_SYMBOL(pcibus_to_node);
++#endif
++
+ /* Return the domain nuber for this pci bus */
+ 
+ int pci_domain_nr(struct pci_bus *pbus)
+diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c
+index 7571ed5..d23bb6f 100644
+--- a/arch/sparc64/kernel/pci_fire.c
++++ b/arch/sparc64/kernel/pci_fire.c
+@@ -71,7 +71,8 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
+ 	 */
+ 	fire_write(iommu->iommu_flushinv, ~(u64)0);
+ 
+-	err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
++	err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask,
++			       pbm->numa_node);
+ 	if (err)
+ 		return err;
+ 
+@@ -449,6 +450,8 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p,
+ 	pbm->next = pci_pbm_root;
+ 	pci_pbm_root = pbm;
+ 
++	pbm->numa_node = -1;
++
+ 	pbm->scan_bus = pci_fire_scan_bus;
+ 	pbm->pci_ops = &sun4u_pci_ops;
+ 	pbm->config_space_reg_bits = 12;
+diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
+index 4a50da1..218bac4 100644
+--- a/arch/sparc64/kernel/pci_impl.h
++++ b/arch/sparc64/kernel/pci_impl.h
+@@ -148,6 +148,8 @@ struct pci_pbm_info {
+ 	struct pci_bus			*pci_bus;
+ 	void (*scan_bus)(struct pci_pbm_info *);
+ 	struct pci_ops			*pci_ops;
++
++	int				numa_node;
+ };
+ 
+ struct pci_controller_info {
+@@ -161,8 +163,6 @@ extern struct pci_pbm_info *pci_pbm_root;
+ extern int pci_num_pbms;
+ 
+ /* PCI bus scanning and fixup support. */
+-extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize,
+-				 u32 dma_offset, u32 dma_addr_mask);
+ extern void pci_get_pbm_props(struct pci_pbm_info *pbm);
+ extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
+ extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm);
+diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c
+index d6d64b4..db5e8fd 100644
+--- a/arch/sparc64/kernel/pci_msi.c
++++ b/arch/sparc64/kernel/pci_msi.c
+@@ -279,11 +279,17 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm,
+ 				 unsigned long devino)
+ {
+ 	int irq = ops->msiq_build_irq(pbm, msiqid, devino);
+-	int err;
++	int err, nid;
+ 
+ 	if (irq < 0)
+ 		return irq;
+ 
++	nid = pbm->numa_node;
++	if (nid != -1) {
++		cpumask_t numa_mask = node_to_cpumask(nid);
++
++		irq_set_affinity(irq, numa_mask);
++	}
+ 	err = request_irq(irq, sparc64_msiq_interrupt, 0,
+ 			  "MSIQ",
+ 			  &pbm->msiq_irq_cookies[msiqid - pbm->msiq_first]);
+diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
+index 0bad96e..994dbe0 100644
+--- a/arch/sparc64/kernel/pci_psycho.c
++++ b/arch/sparc64/kernel/pci_psycho.c
+@@ -848,7 +848,8 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm)
+ 	/* Leave diag mode enabled for full-flushing done
+ 	 * in pci_iommu.c
+ 	 */
+-	err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff);
++	err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff,
++			       pbm->numa_node);
+ 	if (err)
+ 		return err;
+ 
+@@ -979,6 +980,8 @@ static void __init psycho_pbm_init(struct pci_controller_info *p,
+ 	pbm->next = pci_pbm_root;
+ 	pci_pbm_root = pbm;
+ 
++	pbm->numa_node = -1;
++
+ 	pbm->scan_bus = psycho_scan_bus;
+ 	pbm->pci_ops = &sun4u_pci_ops;
+ 	pbm->config_space_reg_bits = 8;
+diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
+index 1c5f5fa..4c34195 100644
+--- a/arch/sparc64/kernel/pci_sabre.c
++++ b/arch/sparc64/kernel/pci_sabre.c
+@@ -704,7 +704,7 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm,
+ 	 * in pci_iommu.c
+ 	 */
+ 	err = iommu_table_init(iommu, tsbsize * 1024 * 8,
+-			       dvma_offset, dma_mask);
++			       dvma_offset, dma_mask, pbm->numa_node);
+ 	if (err)
+ 		return err;
+ 
+@@ -737,6 +737,8 @@ static void __init sabre_pbm_init(struct pci_controller_info *p,
+ 	pbm->name = dp->full_name;
+ 	printk("%s: SABRE PCI Bus Module\n", pbm->name);
+ 
++	pbm->numa_node = -1;
++
+ 	pbm->scan_bus = sabre_scan_bus;
+ 	pbm->pci_ops = &sun4u_pci_ops;
+ 	pbm->config_space_reg_bits = 8;
+diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
+index e306093..615edd9 100644
+--- a/arch/sparc64/kernel/pci_schizo.c
++++ b/arch/sparc64/kernel/pci_schizo.c
+@@ -1220,7 +1220,8 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
+ 	/* Leave diag mode enabled for full-flushing done
+ 	 * in pci_iommu.c
+ 	 */
+-	err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
++	err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask,
++			       pbm->numa_node);
+ 	if (err)
+ 		return err;
+ 
+@@ -1379,6 +1380,8 @@ static int __init schizo_pbm_init(struct pci_controller_info *p,
+ 	pbm->next = pci_pbm_root;
+ 	pci_pbm_root = pbm;
+ 
++	pbm->numa_node = -1;
++
+ 	pbm->scan_bus = schizo_scan_bus;
+ 	pbm->pci_ops = &sun4u_pci_ops;
+ 	pbm->config_space_reg_bits = 8;
+diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
+index 0183970..e2bb979 100644
+--- a/arch/sparc64/kernel/pci_sun4v.c
++++ b/arch/sparc64/kernel/pci_sun4v.c
+@@ -127,10 +127,12 @@ static inline long iommu_batch_end(void)
+ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
+ 				   dma_addr_t *dma_addrp, gfp_t gfp)
+ {
+-	struct iommu *iommu;
+ 	unsigned long flags, order, first_page, npages, n;
++	struct iommu *iommu;
++	struct page *page;
+ 	void *ret;
+ 	long entry;
++	int nid;
+ 
+ 	size = IO_PAGE_ALIGN(size);
+ 	order = get_order(size);
+@@ -139,10 +141,12 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
+ 
+ 	npages = size >> IO_PAGE_SHIFT;
+ 
+-	first_page = __get_free_pages(gfp, order);
+-	if (unlikely(first_page == 0UL))
++	nid = dev->archdata.numa_node;
++	page = alloc_pages_node(nid, gfp, order);
++	if (unlikely(!page))
+ 		return NULL;
+ 
++	first_page = (unsigned long) page_address(page);
+ 	memset((char *)first_page, 0, PAGE_SIZE << order);
+ 
+ 	iommu = dev->archdata.iommu;
+@@ -899,6 +903,8 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p,
+ 	pbm->next = pci_pbm_root;
+ 	pci_pbm_root = pbm;
+ 
++	pbm->numa_node = of_node_to_nid(dp);
++
+ 	pbm->scan_bus = pci_sun4v_scan_bus;
+ 	pbm->pci_ops = &sun4v_pci_ops;
+ 	pbm->config_space_reg_bits = 12;
+@@ -913,6 +919,7 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p,
+ 	pbm->name = dp->full_name;
+ 
+ 	printk("%s: SUN4V PCI Bus Module\n", pbm->name);
++	printk("%s: On NUMA node %d\n", pbm->name, pbm->numa_node);
+ 
+ 	pci_determine_mem_io_space(pbm);
+ 
+diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
+index 68964dd..ed03a18 100644
+--- a/arch/sparc64/kernel/prom.c
++++ b/arch/sparc64/kernel/prom.c
+@@ -19,8 +19,8 @@
+ #include <linux/types.h>
+ #include <linux/string.h>
+ #include <linux/mm.h>
+-#include <linux/bootmem.h>
+ #include <linux/module.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/prom.h>
+ #include <asm/of_device.h>
+@@ -122,16 +122,20 @@ int of_find_in_proplist(const char *list, const char *match, int len)
+ }
+ EXPORT_SYMBOL(of_find_in_proplist);
+ 
+-static unsigned int prom_early_allocated;
++static unsigned int prom_early_allocated __initdata;
+ 
+ static void * __init prom_early_alloc(unsigned long size)
+ {
++	unsigned long paddr = lmb_alloc(size, SMP_CACHE_BYTES);
+ 	void *ret;
+ 
+-	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+-	if (ret != NULL)
+-		memset(ret, 0, size);
++	if (!paddr) {
++		prom_printf("prom_early_alloc(%lu) failed\n");
++		prom_halt();
++	}
+ 
++	ret = __va(paddr);
++	memset(ret, 0, size);
+ 	prom_early_allocated += size;
+ 
+ 	return ret;
+diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
+index 079d18a..ecf6753 100644
+--- a/arch/sparc64/kernel/rtrap.S
++++ b/arch/sparc64/kernel/rtrap.S
+@@ -18,12 +18,6 @@
+ #define		RTRAP_PSTATE_IRQOFF	(PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV)
+ #define		RTRAP_PSTATE_AG_IRQOFF	(PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
+ 
+-		/* Register %l6 keeps track of whether we are returning
+-		 * from a system call or not.  It is cleared if we call
+-		 * do_notify_resume, and it must not be otherwise modified
+-		 * until we fully commit to returning to userspace.
+-		 */
+-
+ 		.text
+ 		.align			32
+ __handle_softirq:
+@@ -56,14 +50,12 @@ __handle_user_windows:
+ 		be,pt			%xcc, __handle_user_windows_continue
+ 		 nop
+ 		mov			%l5, %o1
+-		mov			%l6, %o2
+ 		add			%sp, PTREGS_OFF, %o0
+-		mov			%l0, %o3
++		mov			%l0, %o2
+ 
+ 		call			do_notify_resume
+ 		 wrpr			%g0, RTRAP_PSTATE, %pstate
+ 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
+-		clr			%l6
+ 		/* Signal delivery can modify pt_regs tstate, so we must
+ 		 * reload it.
+ 		 */
+@@ -99,14 +91,12 @@ __handle_perfctrs:
+ 		be,pt			%xcc, __handle_perfctrs_continue
+ 		 sethi			%hi(TSTATE_PEF), %o0
+ 		mov			%l5, %o1
+-		mov			%l6, %o2
+ 		add			%sp, PTREGS_OFF, %o0
+-		mov			%l0, %o3
++		mov			%l0, %o2
+ 		call			do_notify_resume
+ 
+ 		 wrpr			%g0, RTRAP_PSTATE, %pstate
+ 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
+-		clr			%l6
+ 		/* Signal delivery can modify pt_regs tstate, so we must
+ 		 * reload it.
+ 		 */
+@@ -127,13 +117,11 @@ __handle_userfpu:
+ 
+ __handle_signal:
+ 		mov			%l5, %o1
+-		mov			%l6, %o2
+ 		add			%sp, PTREGS_OFF, %o0
+-		mov			%l0, %o3
++		mov			%l0, %o2
+ 		call			do_notify_resume
+ 		 wrpr			%g0, RTRAP_PSTATE, %pstate
+ 		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
+-		clr			%l6
+ 
+ 		/* Signal delivery can modify pt_regs tstate, so we must
+ 		 * reload it.
+@@ -145,9 +133,8 @@ __handle_signal:
+ 		 andn			%l1, %l4, %l1
+ 
+ 		.align			64
+-		.globl			rtrap_irq, rtrap_clr_l6, rtrap, irqsz_patchme, rtrap_xcall
++		.globl			rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall
+ rtrap_irq:
+-rtrap_clr_l6:	clr			%l6
+ rtrap:
+ #ifndef CONFIG_SMP
+ 		sethi			%hi(per_cpu____cpu_data), %l0
+diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
+index d1fb13b..fa2827c 100644
+--- a/arch/sparc64/kernel/sbus.c
++++ b/arch/sparc64/kernel/sbus.c
+@@ -544,6 +544,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
+ 
+ 	sbus->ofdev.dev.archdata.iommu = iommu;
+ 	sbus->ofdev.dev.archdata.stc = strbuf;
++	sbus->ofdev.dev.archdata.numa_node = -1;
+ 
+ 	reg_base = regs + SYSIO_IOMMUREG_BASE;
+ 	iommu->iommu_control = reg_base + IOMMU_CONTROL;
+@@ -575,7 +576,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
+ 	       sbus->portid, regs);
+ 
+ 	/* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */
+-	if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff))
++	if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1))
+ 		goto fatal_memory_error;
+ 
+ 	control = upa_readq(iommu->iommu_control);
+diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c
+deleted file mode 100644
+index 9974a68..0000000
+--- a/arch/sparc64/kernel/semaphore.c
++++ /dev/null
+@@ -1,254 +0,0 @@
+-/* semaphore.c: Sparc64 semaphore implementation.
+- *
+- * This is basically the PPC semaphore scheme ported to use
+- * the sparc64 atomic instructions, so see the PPC code for
+- * credits.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- *	old_count = sem->count;
+- *	tmp = MAX(old_count, 0) + incr;
+- *	sem->count = tmp;
+- *	return old_count;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+-	int old_count, tmp;
+-
+-	__asm__ __volatile__("\n"
+-"	! __sem_update_count old_count(%0) tmp(%1) incr(%4) &sem->count(%3)\n"
+-"1:	ldsw	[%3], %0\n"
+-"	mov	%0, %1\n"
+-"	cmp	%0, 0\n"
+-"	movl	%%icc, 0, %1\n"
+-"	add	%1, %4, %1\n"
+-"	cas	[%3], %0, %1\n"
+-"	cmp	%0, %1\n"
+-"	membar	#StoreLoad | #StoreStore\n"
+-"	bne,pn	%%icc, 1b\n"
+-"	 nop\n"
+-	: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+-	: "r" (&sem->count), "r" (incr), "m" (sem->count)
+-	: "cc");
+-
+-	return old_count;
+-}
+-
+-static void __up(struct semaphore *sem)
+-{
+-	__sem_update_count(sem, 1);
+-	wake_up(&sem->wait);
+-}
+-
+-void up(struct semaphore *sem)
+-{
+-	/* This atomically does:
+-	 * 	old_val = sem->count;
+-	 *	new_val = sem->count + 1;
+-	 *	sem->count = new_val;
+-	 *	if (old_val < 0)
+-	 *		__up(sem);
+-	 *
+-	 * The (old_val < 0) test is equivalent to
+-	 * the more straightforward (new_val <= 0),
+-	 * but it is easier to test the former because
+-	 * of how the CAS instruction works.
+-	 */
+-
+-	__asm__ __volatile__("\n"
+-"	! up sem(%0)\n"
+-"	membar	#StoreLoad | #LoadLoad\n"
+-"1:	lduw	[%0], %%g1\n"
+-"	add	%%g1, 1, %%g7\n"
+-"	cas	[%0], %%g1, %%g7\n"
+-"	cmp	%%g1, %%g7\n"
+-"	bne,pn	%%icc, 1b\n"
+-"	 addcc	%%g7, 1, %%g0\n"
+-"	membar	#StoreLoad | #StoreStore\n"
+-"	ble,pn	%%icc, 3f\n"
+-"	 nop\n"
+-"2:\n"
+-"	.subsection 2\n"
+-"3:	mov	%0, %%g1\n"
+-"	save	%%sp, -160, %%sp\n"
+-"	call	%1\n"
+-"	 mov	%%g1, %%o0\n"
+-"	ba,pt	%%xcc, 2b\n"
+-"	 restore\n"
+-"	.previous\n"
+-	: : "r" (sem), "i" (__up)
+-	: "g1", "g2", "g3", "g7", "memory", "cc");
+-}
+-
+-static void __sched __down(struct semaphore * sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	tsk->state = TASK_UNINTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		schedule();
+-		tsk->state = TASK_UNINTERRUPTIBLE;
+-	}
+-	remove_wait_queue(&sem->wait, &wait);
+-	tsk->state = TASK_RUNNING;
+-
+-	wake_up(&sem->wait);
+-}
+-
+-void __sched down(struct semaphore *sem)
+-{
+-	might_sleep();
+-	/* This atomically does:
+-	 * 	old_val = sem->count;
+-	 *	new_val = sem->count - 1;
+-	 *	sem->count = new_val;
+-	 *	if (old_val < 1)
+-	 *		__down(sem);
+-	 *
+-	 * The (old_val < 1) test is equivalent to
+-	 * the more straightforward (new_val < 0),
+-	 * but it is easier to test the former because
+-	 * of how the CAS instruction works.
+-	 */
+-
+-	__asm__ __volatile__("\n"
+-"	! down sem(%0)\n"
+-"1:	lduw	[%0], %%g1\n"
+-"	sub	%%g1, 1, %%g7\n"
+-"	cas	[%0], %%g1, %%g7\n"
+-"	cmp	%%g1, %%g7\n"
+-"	bne,pn	%%icc, 1b\n"
+-"	 cmp	%%g7, 1\n"
+-"	membar	#StoreLoad | #StoreStore\n"
+-"	bl,pn	%%icc, 3f\n"
+-"	 nop\n"
+-"2:\n"
+-"	.subsection 2\n"
+-"3:	mov	%0, %%g1\n"
+-"	save	%%sp, -160, %%sp\n"
+-"	call	%1\n"
+-"	 mov	%%g1, %%o0\n"
+-"	ba,pt	%%xcc, 2b\n"
+-"	 restore\n"
+-"	.previous\n"
+-	: : "r" (sem), "i" (__down)
+-	: "g1", "g2", "g3", "g7", "memory", "cc");
+-}
+-
+-int down_trylock(struct semaphore *sem)
+-{
+-	int ret;
+-
+-	/* This atomically does:
+-	 * 	old_val = sem->count;
+-	 *	new_val = sem->count - 1;
+-	 *	if (old_val < 1) {
+-	 *		ret = 1;
+-	 *	} else {
+-	 *		sem->count = new_val;
+-	 *		ret = 0;
+-	 *	}
+-	 *
+-	 * The (old_val < 1) test is equivalent to
+-	 * the more straightforward (new_val < 0),
+-	 * but it is easier to test the former because
+-	 * of how the CAS instruction works.
+-	 */
+-
+-	__asm__ __volatile__("\n"
+-"	! down_trylock sem(%1) ret(%0)\n"
+-"1:	lduw	[%1], %%g1\n"
+-"	sub	%%g1, 1, %%g7\n"
+-"	cmp	%%g1, 1\n"
+-"	bl,pn	%%icc, 2f\n"
+-"	 mov	1, %0\n"
+-"	cas	[%1], %%g1, %%g7\n"
+-"	cmp	%%g1, %%g7\n"
+-"	bne,pn	%%icc, 1b\n"
+-"	 mov	0, %0\n"
+-"	membar	#StoreLoad | #StoreStore\n"
+-"2:\n"
+-	: "=&r" (ret)
+-	: "r" (sem)
+-	: "g1", "g7", "memory", "cc");
+-
+-	return ret;
+-}
+-
+-static int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-
+-	tsk->state = TASK_INTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	while (__sem_update_count(sem, -1) <= 0) {
+-		if (signal_pending(current)) {
+-			__sem_update_count(sem, 0);
+-			retval = -EINTR;
+-			break;
+-		}
+-		schedule();
+-		tsk->state = TASK_INTERRUPTIBLE;
+-	}
+-	tsk->state = TASK_RUNNING;
+-	remove_wait_queue(&sem->wait, &wait);
+-	wake_up(&sem->wait);
+-	return retval;
+-}
+-
+-int __sched down_interruptible(struct semaphore *sem)
+-{
+-	int ret = 0;
+-	
+-	might_sleep();
+-	/* This atomically does:
+-	 * 	old_val = sem->count;
+-	 *	new_val = sem->count - 1;
+-	 *	sem->count = new_val;
+-	 *	if (old_val < 1)
+-	 *		ret = __down_interruptible(sem);
+-	 *
+-	 * The (old_val < 1) test is equivalent to
+-	 * the more straightforward (new_val < 0),
+-	 * but it is easier to test the former because
+-	 * of how the CAS instruction works.
+-	 */
+-
+-	__asm__ __volatile__("\n"
+-"	! down_interruptible sem(%2) ret(%0)\n"
+-"1:	lduw	[%2], %%g1\n"
+-"	sub	%%g1, 1, %%g7\n"
+-"	cas	[%2], %%g1, %%g7\n"
+-"	cmp	%%g1, %%g7\n"
+-"	bne,pn	%%icc, 1b\n"
+-"	 cmp	%%g7, 1\n"
+-"	membar	#StoreLoad | #StoreStore\n"
+-"	bl,pn	%%icc, 3f\n"
+-"	 nop\n"
+-"2:\n"
+-"	.subsection 2\n"
+-"3:	mov	%2, %%g1\n"
+-"	save	%%sp, -160, %%sp\n"
+-"	call	%3\n"
+-"	 mov	%%g1, %%o0\n"
+-"	ba,pt	%%xcc, 2b\n"
+-"	 restore\n"
+-"	.previous\n"
+-	: "=r" (ret)
+-	: "0" (ret), "r" (sem), "i" (__down_interruptible)
+-	: "g1", "g2", "g3", "g7", "memory", "cc");
+-	return ret;
+-}
+diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
+index 6acb4c5..da5e6ee 100644
+--- a/arch/sparc64/kernel/setup.c
++++ b/arch/sparc64/kernel/setup.c
+@@ -82,7 +82,7 @@ unsigned long cmdline_memory_size = 0;
+ static struct console prom_early_console = {
+ 	.name =		"earlyprom",
+ 	.write =	prom_console_write,
+-	.flags =	CON_PRINTBUFFER | CON_BOOT,
++	.flags =	CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
+ 	.index =	-1,
+ };
+ 
+@@ -281,6 +281,7 @@ void __init setup_arch(char **cmdline_p)
+ 	/* Initialize PROM console and command line. */
+ 	*cmdline_p = prom_getbootargs();
+ 	strcpy(boot_command_line, *cmdline_p);
++	parse_early_param();
+ 
+ 	boot_flags_init(*cmdline_p);
+ 	register_console(&prom_early_console);
+diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
+index 9d51956..77a3e85 100644
+--- a/arch/sparc64/kernel/signal.c
++++ b/arch/sparc64/kernel/signal.c
+@@ -25,7 +25,6 @@
+ 
+ #include <asm/uaccess.h>
+ #include <asm/ptrace.h>
+-#include <asm/svr4.h>
+ #include <asm/pgtable.h>
+ #include <asm/fpumacro.h>
+ #include <asm/uctx.h>
+@@ -511,15 +510,20 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
+  * want to handle. Thus you cannot kill init even with a SIGKILL even by
+  * mistake.
+  */
+-static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall)
++static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
+ {
+-	siginfo_t info;
+ 	struct signal_deliver_cookie cookie;
+ 	struct k_sigaction ka;
+-	int signr;
+ 	sigset_t *oldset;
++	siginfo_t info;
++	int signr, tt;
+ 	
+-	cookie.restart_syscall = restart_syscall;
++	tt = regs->magic & 0x1ff;
++	if (tt == 0x110 || tt == 0x111 || tt == 0x16d) {
++		regs->magic &= ~0x1ff;
++		cookie.restart_syscall = 1;
++	} else
++		cookie.restart_syscall = 0;
+ 	cookie.orig_i0 = orig_i0;
+ 
+ 	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+@@ -530,9 +534,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
+ #ifdef CONFIG_SPARC32_COMPAT
+ 	if (test_thread_flag(TIF_32BIT)) {
+ 		extern void do_signal32(sigset_t *, struct pt_regs *,
+-					unsigned long, int);
+-		do_signal32(oldset, regs, orig_i0,
+-			    cookie.restart_syscall);
++					struct signal_deliver_cookie *);
++		do_signal32(oldset, regs, &cookie);
+ 		return;
+ 	}
+ #endif	
+@@ -540,7 +543,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
+ 	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
+ 	if (signr > 0) {
+ 		if (cookie.restart_syscall)
+-			syscall_restart(orig_i0, regs, &ka.sa);
++			syscall_restart(cookie.orig_i0, regs, &ka.sa);
+ 		handle_signal(signr, &ka, &info, oldset, regs);
+ 
+ 		/* a signal was successfully delivered; the saved
+@@ -577,11 +580,10 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
+ 	}
+ }
+ 
+-void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall,
+-		      unsigned long thread_info_flags)
++void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
+ {
+ 	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+-		do_signal(regs, orig_i0, restart_syscall);
++		do_signal(regs, orig_i0);
+ }
+ 
+ void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
+diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
+index 8c1c121..43cdec6 100644
+--- a/arch/sparc64/kernel/signal32.c
++++ b/arch/sparc64/kernel/signal32.c
+@@ -23,7 +23,6 @@
+ 
+ #include <asm/uaccess.h>
+ #include <asm/ptrace.h>
+-#include <asm/svr4.h>
+ #include <asm/pgtable.h>
+ #include <asm/psrcompat.h>
+ #include <asm/fpumacro.h>
+@@ -798,281 +797,6 @@ sigsegv:
+ 	force_sigsegv(signo, current);
+ }
+ 
+-/* Setup a Solaris stack frame */
+-static void
+-setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
+-		   struct pt_regs *regs, int signr, sigset_t *oldset)
+-{
+-	svr4_signal_frame_t __user *sfp;
+-	svr4_gregset_t  __user *gr;
+-	svr4_siginfo_t  __user *si;
+-	svr4_mcontext_t __user *mc;
+-	svr4_gwindows_t __user *gw;
+-	svr4_ucontext_t __user *uc;
+-	svr4_sigset_t setv;
+-	unsigned int psr;
+-	int i, err;
+-
+-	synchronize_user_stack();
+-	save_and_clear_fpu();
+-	
+-	regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
+-	sfp = (svr4_signal_frame_t __user *)
+-		get_sigframe(sa, regs,
+-			     sizeof(struct reg_window32) + SVR4_SF_ALIGNED);
+-
+-	if (invalid_frame_pointer(sfp, sizeof(*sfp)))
+-		do_exit(SIGILL);
+-
+-	/* Start with a clean frame pointer and fill it */
+-	err = clear_user(sfp, sizeof(*sfp));
+-
+-	/* Setup convenience variables */
+-	si = &sfp->si;
+-	uc = &sfp->uc;
+-	gw = &sfp->gw;
+-	mc = &uc->mcontext;
+-	gr = &mc->greg;
+-	
+-	/* FIXME: where am I supposed to put this?
+-	 * sc->sigc_onstack = old_status;
+-	 * anyways, it does not look like it is used for anything at all.
+-	 */
+-	setv.sigbits[0] = oldset->sig[0];
+-	setv.sigbits[1] = (oldset->sig[0] >> 32);
+-	if (_NSIG_WORDS >= 2) {
+-		setv.sigbits[2] = oldset->sig[1];
+-		setv.sigbits[3] = (oldset->sig[1] >> 32);
+-		err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+-	} else
+-		err |= __copy_to_user(&uc->sigmask, &setv,
+-				      2 * sizeof(unsigned int));
+-	
+-	/* Store registers */
+-	if (test_thread_flag(TIF_32BIT)) {
+-		regs->tpc &= 0xffffffff;
+-		regs->tnpc &= 0xffffffff;
+-	}
+-	err |= __put_user(regs->tpc, &((*gr)[SVR4_PC]));
+-	err |= __put_user(regs->tnpc, &((*gr)[SVR4_NPC]));
+-	psr = tstate_to_psr(regs->tstate);
+-	if (current_thread_info()->fpsaved[0] & FPRS_FEF)
+-		psr |= PSR_EF;
+-	err |= __put_user(psr, &((*gr)[SVR4_PSR]));
+-	err |= __put_user(regs->y, &((*gr)[SVR4_Y]));
+-	
+-	/* Copy g[1..7] and o[0..7] registers */
+-	for (i = 0; i < 7; i++)
+-		err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+-	for (i = 0; i < 8; i++)
+-		err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+-
+-	/* Setup sigaltstack */
+-	err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+-	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+-	err |= __put_user(current->sas_ss_size, &uc->stack.size);
+-
+-	/* Save the currently window file: */
+-
+-	/* 1. Link sfp->uc->gwins to our windows */
+-	err |= __put_user(ptr_to_compat(gw), &mc->gwin);
+-	    
+-	/* 2. Number of windows to restore at setcontext (): */
+-	err |= __put_user(get_thread_wsaved(), &gw->count);
+-
+-	/* 3. We just pay attention to the gw->count field on setcontext */
+-	set_thread_wsaved(0); /* So process is allowed to execute. */
+-
+-	/* Setup the signal information.  Solaris expects a bunch of
+-	 * information to be passed to the signal handler, we don't provide
+-	 * that much currently, should use siginfo.
+-	 */
+-	err |= __put_user(signr, &si->siginfo.signo);
+-	err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
+-	if (err)
+-		goto sigsegv;
+-
+-	regs->u_regs[UREG_FP] = (unsigned long) sfp;
+-	regs->tpc = (unsigned long) sa->sa_handler;
+-	regs->tnpc = (regs->tpc + 4);
+-	if (test_thread_flag(TIF_32BIT)) {
+-		regs->tpc &= 0xffffffff;
+-		regs->tnpc &= 0xffffffff;
+-	}
+-
+-	/* Arguments passed to signal handler */
+-	if (regs->u_regs[14]){
+-		struct reg_window32 __user *rw = (struct reg_window32 __user *)
+-			(regs->u_regs[14] & 0x00000000ffffffffUL);
+-
+-		err |= __put_user(signr, &rw->ins[0]);
+-		err |= __put_user((u64)si, &rw->ins[1]);
+-		err |= __put_user((u64)uc, &rw->ins[2]);
+-		err |= __put_user((u64)sfp, &rw->ins[6]);	/* frame pointer */
+-		if (err)
+-			goto sigsegv;
+-
+-		regs->u_regs[UREG_I0] = signr;
+-		regs->u_regs[UREG_I1] = (u32)(u64) si;
+-		regs->u_regs[UREG_I2] = (u32)(u64) uc;
+-	}
+-	return;
+-
+-sigsegv:
+-	force_sigsegv(signr, current);
+-}
+-
+-asmlinkage int
+-svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs)
+-{
+-	svr4_gregset_t  __user *gr;
+-	svr4_mcontext_t __user *mc;
+-	svr4_sigset_t setv;
+-	int i, err;
+-	u32 psr;
+-
+-	synchronize_user_stack();
+-	save_and_clear_fpu();
+-	
+-	if (get_thread_wsaved())
+-		do_exit(SIGSEGV);
+-
+-	err = clear_user(uc, sizeof(*uc));
+-
+-	/* Setup convenience variables */
+-	mc = &uc->mcontext;
+-	gr = &mc->greg;
+-
+-	setv.sigbits[0] = current->blocked.sig[0];
+-	setv.sigbits[1] = (current->blocked.sig[0] >> 32);
+-	if (_NSIG_WORDS >= 2) {
+-		setv.sigbits[2] = current->blocked.sig[1];
+-		setv.sigbits[3] = (current->blocked.sig[1] >> 32);
+-		err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+-	} else
+-		err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned));
+-
+-	/* Store registers */
+-	if (test_thread_flag(TIF_32BIT)) {
+-		regs->tpc &= 0xffffffff;
+-		regs->tnpc &= 0xffffffff;
+-	}
+-	err |= __put_user(regs->tpc, &uc->mcontext.greg[SVR4_PC]);
+-	err |= __put_user(regs->tnpc, &uc->mcontext.greg[SVR4_NPC]);
+-
+-	psr = tstate_to_psr(regs->tstate) & ~PSR_EF;		   
+-	if (current_thread_info()->fpsaved[0] & FPRS_FEF)
+-		psr |= PSR_EF;
+-	err |= __put_user(psr, &uc->mcontext.greg[SVR4_PSR]);
+-
+-	err |= __put_user(regs->y, &uc->mcontext.greg[SVR4_Y]);
+-	
+-	/* Copy g[1..7] and o[0..7] registers */
+-	for (i = 0; i < 7; i++)
+-		err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+-	for (i = 0; i < 8; i++)
+-		err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+-
+-	/* Setup sigaltstack */
+-	err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+-	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+-	err |= __put_user(current->sas_ss_size, &uc->stack.size);
+-
+-	/* The register file is not saved
+-	 * we have already stuffed all of it with sync_user_stack
+-	 */
+-	return (err ? -EFAULT : 0);
+-}
+-
+-
+-/* Set the context for a svr4 application, this is Solaris way to sigreturn */
+-asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs)
+-{
+-	svr4_gregset_t  __user *gr;
+-	mm_segment_t old_fs;
+-	u32 pc, npc, psr, u_ss_sp;
+-	sigset_t set;
+-	svr4_sigset_t setv;
+-	int i, err;
+-	stack_t st;
+-	
+-	/* Fixme: restore windows, or is this already taken care of in
+-	 * svr4_setup_frame when sync_user_windows is done?
+-	 */
+-	flush_user_windows();
+-	
+-	if (get_thread_wsaved())
+-		goto sigsegv;
+-
+-	if (((unsigned long) c) & 3){
+-		printk("Unaligned structure passed\n");
+-		goto sigsegv;
+-	}
+-
+-	if (!__access_ok(c, sizeof(*c))) {
+-		/* Miguel, add nice debugging msg _here_. ;-) */
+-		goto sigsegv;
+-	}
+-
+-	/* Check for valid PC and nPC */
+-	gr = &c->mcontext.greg;
+-	err = __get_user(pc, &((*gr)[SVR4_PC]));
+-	err |= __get_user(npc, &((*gr)[SVR4_NPC]));
+-	if ((pc | npc) & 3)
+-		goto sigsegv;
+-	
+-	/* Retrieve information from passed ucontext */
+-	/* note that nPC is ored a 1, this is used to inform entry.S */
+-	/* that we don't want it to mess with our PC and nPC */
+-	
+-	err |= copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t));
+-	set.sig[0] = setv.sigbits[0] | (((long)setv.sigbits[1]) << 32);
+-	if (_NSIG_WORDS >= 2)
+-		set.sig[1] = setv.sigbits[2] | (((long)setv.sigbits[3]) << 32);
+-	
+-	err |= __get_user(u_ss_sp, &c->stack.sp);
+-	st.ss_sp = compat_ptr(u_ss_sp);
+-	err |= __get_user(st.ss_flags, &c->stack.flags);
+-	err |= __get_user(st.ss_size, &c->stack.size);
+-	if (err)
+-		goto sigsegv;
+-		
+-	/* 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->u_regs[UREG_I6]);
+-	set_fs(old_fs);
+-	
+-	sigdelsetmask(&set, ~_BLOCKABLE);
+-	spin_lock_irq(&current->sighand->siglock);
+-	current->blocked = set;
+-	recalc_sigpending();
+-	spin_unlock_irq(&current->sighand->siglock);
+-	regs->tpc = pc;
+-	regs->tnpc = npc | 1;
+-	if (test_thread_flag(TIF_32BIT)) {
+-		regs->tpc &= 0xffffffff;
+-		regs->tnpc &= 0xffffffff;
+-	}
+-	err |= __get_user(regs->y, &((*gr)[SVR4_Y]));
+-	err |= __get_user(psr, &((*gr)[SVR4_PSR]));
+-	regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
+-	regs->tstate |= psr_to_tstate_icc(psr);
+-
+-	/* Restore g[1..7] and o[0..7] registers */
+-	for (i = 0; i < 7; i++)
+-		err |= __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+-	for (i = 0; i < 8; i++)
+-		err |= __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+-	if (err)
+-		goto sigsegv;
+-
+-	return -EINTR;
+-sigsegv:
+-	return -EFAULT;
+-}
+-
+ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
+ 			     unsigned long signr, sigset_t *oldset,
+ 			     siginfo_t *info)
+@@ -1216,20 +940,14 @@ sigsegv:
+ 
+ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
+ 				   siginfo_t *info,
+-				   sigset_t *oldset, struct pt_regs *regs,
+-				   int svr4_signal)
++				   sigset_t *oldset, struct pt_regs *regs)
+ {
+-	if (svr4_signal)
+-		setup_svr4_frame32(&ka->sa, regs->tpc, regs->tnpc,
+-				   regs, signr, oldset);
+-	else {
+-		if (ka->sa.sa_flags & SA_SIGINFO)
+-			setup_rt_frame32(ka, regs, signr, oldset, info);
+-		else if (test_thread_flag(TIF_NEWSIGNALS))
+-			new_setup_frame32(ka, regs, signr, oldset);
+-		else
+-			setup_frame32(&ka->sa, regs, signr, oldset, info);
+-	}
++	if (ka->sa.sa_flags & SA_SIGINFO)
++		setup_rt_frame32(ka, regs, signr, oldset, info);
++	else if (test_thread_flag(TIF_NEWSIGNALS))
++		new_setup_frame32(ka, regs, signr, oldset);
++	else
++		setup_frame32(&ka->sa, regs, signr, oldset, info);
+ 	spin_lock_irq(&current->sighand->siglock);
+ 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ 	if (!(ka->sa.sa_flags & SA_NOMASK))
+@@ -1264,23 +982,17 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
+  * mistake.
+  */
+ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+-		 unsigned long orig_i0, int restart_syscall)
++		 struct signal_deliver_cookie *cookie)
+ {
+-	siginfo_t info;
+-	struct signal_deliver_cookie cookie;
+ 	struct k_sigaction ka;
++	siginfo_t info;
+ 	int signr;
+-	int svr4_signal = current->personality == PER_SVR4;
+ 	
+-	cookie.restart_syscall = restart_syscall;
+-	cookie.orig_i0 = orig_i0;
+-
+-	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
++	signr = get_signal_to_deliver(&info, &ka, regs, cookie);
+ 	if (signr > 0) {
+-		if (cookie.restart_syscall)
+-			syscall_restart32(orig_i0, regs, &ka.sa);
+-		handle_signal32(signr, &ka, &info, oldset,
+-				regs, svr4_signal);
++		if (cookie->restart_syscall)
++			syscall_restart32(cookie->orig_i0, regs, &ka.sa);
++		handle_signal32(signr, &ka, &info, oldset, regs);
+ 
+ 		/* a signal was successfully delivered; the saved
+ 		 * sigmask will have been stored in the signal frame,
+@@ -1291,16 +1003,16 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+ 			clear_thread_flag(TIF_RESTORE_SIGMASK);
+ 		return;
+ 	}
+-	if (cookie.restart_syscall &&
++	if (cookie->restart_syscall &&
+ 	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
+ 	     regs->u_regs[UREG_I0] == ERESTARTSYS ||
+ 	     regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
+ 		/* replay the system call when we are done */
+-		regs->u_regs[UREG_I0] = cookie.orig_i0;
++		regs->u_regs[UREG_I0] = cookie->orig_i0;
+ 		regs->tpc -= 4;
+ 		regs->tnpc -= 4;
+ 	}
+-	if (cookie.restart_syscall &&
++	if (cookie->restart_syscall &&
+ 	    regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
+ 		regs->u_regs[UREG_G1] = __NR_restart_syscall;
+ 		regs->tpc -= 4;
+diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
+index 59f020d..409dd71 100644
+--- a/arch/sparc64/kernel/smp.c
++++ b/arch/sparc64/kernel/smp.c
+@@ -20,7 +20,7 @@
+ #include <linux/cache.h>
+ #include <linux/jiffies.h>
+ #include <linux/profile.h>
+-#include <linux/bootmem.h>
++#include <linux/lmb.h>
+ 
+ #include <asm/head.h>
+ #include <asm/ptrace.h>
+@@ -866,14 +866,21 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
+ 	void *info = call_data->info;
+ 
+ 	clear_softint(1 << irq);
++
++	irq_enter();
++
++	if (!call_data->wait) {
++		/* let initiator proceed after getting data */
++		atomic_inc(&call_data->finished);
++	}
++
++	func(info);
++
++	irq_exit();
++
+ 	if (call_data->wait) {
+ 		/* let initiator proceed only after completion */
+-		func(info);
+ 		atomic_inc(&call_data->finished);
+-	} else {
+-		/* let initiator proceed after getting data */
+-		atomic_inc(&call_data->finished);
+-		func(info);
+ 	}
+ }
+ 
+@@ -1032,7 +1039,9 @@ void smp_receive_signal(int cpu)
+ 
+ void smp_receive_signal_client(int irq, struct pt_regs *regs)
+ {
++	irq_enter();
+ 	clear_softint(1 << irq);
++	irq_exit();
+ }
+ 
+ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
+@@ -1040,6 +1049,8 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
+ 	struct mm_struct *mm;
+ 	unsigned long flags;
+ 
++	irq_enter();
++
+ 	clear_softint(1 << irq);
+ 
+ 	/* See if we need to allocate a new TLB context because
+@@ -1059,6 +1070,8 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
+ 	load_secondary_context(mm);
+ 	__flush_tlb_mm(CTX_HWBITS(mm->context),
+ 		       SECONDARY_CONTEXT);
++
++	irq_exit();
+ }
+ 
+ void smp_new_mmu_context_version(void)
+@@ -1217,6 +1230,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
+ {
+ 	clear_softint(1 << irq);
+ 
++	irq_enter();
++
+ 	preempt_disable();
+ 
+ 	__asm__ __volatile__("flushw");
+@@ -1229,6 +1244,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
+ 	prom_world(0);
+ 
+ 	preempt_enable();
++
++	irq_exit();
+ }
+ 
+ /* /proc/profile writes can call this, don't __init it please. */
+@@ -1431,7 +1448,7 @@ EXPORT_SYMBOL(__per_cpu_shift);
+ 
+ void __init real_setup_per_cpu_areas(void)
+ {
+-	unsigned long goal, size, i;
++	unsigned long paddr, goal, size, i;
+ 	char *ptr;
+ 
+ 	/* Copy section for each CPU (we discard the original) */
+@@ -1441,8 +1458,13 @@ void __init real_setup_per_cpu_areas(void)
+ 	for (size = PAGE_SIZE; size < goal; size <<= 1UL)
+ 		__per_cpu_shift++;
+ 
+-	ptr = alloc_bootmem_pages(size * NR_CPUS);
++	paddr = lmb_alloc(size * NR_CPUS, PAGE_SIZE);
++	if (!paddr) {
++		prom_printf("Cannot allocate per-cpu memory.\n");
++		prom_halt();
++	}
+ 
++	ptr = __va(paddr);
+ 	__per_cpu_base = ptr - __per_cpu_start;
+ 
+ 	for (i = 0; i < NR_CPUS; i++, ptr += size)
+diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
+index 51fa773..6633659 100644
+--- a/arch/sparc64/kernel/sparc64_ksyms.c
++++ b/arch/sparc64/kernel/sparc64_ksyms.c
+@@ -33,13 +33,11 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/idprom.h>
+-#include <asm/svr4.h>
+ #include <asm/elf.h>
+ #include <asm/head.h>
+ #include <asm/smp.h>
+ #include <asm/mostek.h>
+ #include <asm/ptrace.h>
+-#include <asm/user.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+ #include <asm/fpumacro.h>
+@@ -70,16 +68,9 @@ extern void *__memscan_zero(void *, size_t);
+ extern void *__memscan_generic(void *, int, size_t);
+ extern int __memcmp(const void *, const void *, __kernel_size_t);
+ extern __kernel_size_t strlen(const char *);
+-extern void linux_sparc_syscall(void);
+-extern void rtrap(void);
+ extern void show_regs(struct pt_regs *);
+-extern void solaris_syscall(void);
+ extern void syscall_trace(struct pt_regs *, int);
+-extern u32 sunos_sys_table[], sys_call_table32[];
+-extern void tl0_solaris(void);
+ extern void sys_sigsuspend(void);
+-extern int svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
+-extern int svr4_setcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
+ extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
+ extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *);
+ extern long sparc32_open(const char __user * filename, int flags, int mode);
+@@ -90,8 +81,6 @@ extern int __ashrdi3(int, int);
+ 
+ extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs);
+ 
+-extern unsigned int sys_call_table[];
+-
+ extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
+ extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
+ 		      unsigned long *);
+@@ -130,12 +119,6 @@ EXPORT_SYMBOL(_mcount);
+ 
+ EXPORT_SYMBOL(sparc64_get_clock_tick);
+ 
+-/* semaphores */
+-EXPORT_SYMBOL(down);
+-EXPORT_SYMBOL(down_trylock);
+-EXPORT_SYMBOL(down_interruptible);
+-EXPORT_SYMBOL(up);
+-
+ /* RW semaphores */
+ EXPORT_SYMBOL(__down_read);
+ EXPORT_SYMBOL(__down_read_trylock);
+@@ -219,11 +202,6 @@ EXPORT_SYMBOL(pci_dma_supported);
+ /* I/O device mmaping on Sparc64. */
+ EXPORT_SYMBOL(io_remap_pfn_range);
+ 
+-#if defined(CONFIG_COMPAT) && defined(CONFIG_NET)
+-/* Solaris/SunOS binary compatibility */
+-EXPORT_SYMBOL(verify_compat_iovec);
+-#endif
+-
+ EXPORT_SYMBOL(dump_fpu);
+ EXPORT_SYMBOL(put_fs_struct);
+ 
+@@ -260,30 +238,6 @@ EXPORT_SYMBOL(strlen);
+ EXPORT_SYMBOL(__strlen_user);
+ EXPORT_SYMBOL(__strnlen_user);
+ 
+-#ifdef CONFIG_SOLARIS_EMUL_MODULE
+-EXPORT_SYMBOL(linux_sparc_syscall);
+-EXPORT_SYMBOL(rtrap);
+-EXPORT_SYMBOL(show_regs);
+-EXPORT_SYMBOL(solaris_syscall);
+-EXPORT_SYMBOL(syscall_trace);
+-EXPORT_SYMBOL(sunos_sys_table);
+-EXPORT_SYMBOL(sys_call_table32);
+-EXPORT_SYMBOL(tl0_solaris);
+-EXPORT_SYMBOL(sys_sigsuspend);
+-EXPORT_SYMBOL(sys_getppid);
+-EXPORT_SYMBOL(sys_getpid);
+-EXPORT_SYMBOL(sys_geteuid);
+-EXPORT_SYMBOL(sys_getuid);
+-EXPORT_SYMBOL(sys_getegid);
+-EXPORT_SYMBOL(sysctl_nr_open);
+-EXPORT_SYMBOL(sys_getgid);
+-EXPORT_SYMBOL(svr4_getcontext);
+-EXPORT_SYMBOL(svr4_setcontext);
+-EXPORT_SYMBOL(compat_sys_ioctl);
+-EXPORT_SYMBOL(sys_ioctl);
+-EXPORT_SYMBOL(sparc32_open);
+-#endif
+-
+ /* Special internal versions of library functions. */
+ EXPORT_SYMBOL(_clear_page);
+ EXPORT_SYMBOL(clear_user_page);
+@@ -340,9 +294,6 @@ EXPORT_SYMBOL(do_BUG);
+ /* for ns8703 */
+ EXPORT_SYMBOL(ns87303_lock);
+ 
+-/* for solaris compat module */
+-EXPORT_SYMBOL_GPL(sys_call_table);
+-
+ EXPORT_SYMBOL(tick_ops);
+ 
+ EXPORT_SYMBOL(xor_vis_2);
+diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c
+index 84d39e8..01b52f5 100644
+--- a/arch/sparc64/kernel/stacktrace.c
++++ b/arch/sparc64/kernel/stacktrace.c
+@@ -20,6 +20,8 @@ void save_stack_trace(struct stack_trace *trace)
+ 	thread_base = (unsigned long) tp;
+ 	do {
+ 		struct reg_window *rw;
++		struct pt_regs *regs;
++		unsigned long pc;
+ 
+ 		/* Bogus frame pointer? */
+ 		if (fp < (thread_base + sizeof(struct thread_info)) ||
+@@ -27,11 +29,19 @@ void save_stack_trace(struct stack_trace *trace)
+ 			break;
+ 
+ 		rw = (struct reg_window *) fp;
++		regs = (struct pt_regs *) (rw + 1);
++
++		if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
++			pc = regs->tpc;
++			fp = regs->u_regs[UREG_I6] + STACK_BIAS;
++		} else {
++			pc = rw->ins[7];
++			fp = rw->ins[6] + STACK_BIAS;
++		}
++
+ 		if (trace->skip > 0)
+ 			trace->skip--;
+ 		else
+-			trace->entries[trace->nr_entries++] = rw->ins[7];
+-
+-		fp = rw->ins[6] + STACK_BIAS;
++			trace->entries[trace->nr_entries++] = pc;
+ 	} while (trace->nr_entries < trace->max_entries);
+ }
+diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S
+index fd94305..e1fbf8c 100644
+--- a/arch/sparc64/kernel/sun4v_tlb_miss.S
++++ b/arch/sparc64/kernel/sun4v_tlb_miss.S
+@@ -262,7 +262,7 @@ sun4v_iacc:
+ 	mov	%l5, %o2
+ 	call	sun4v_insn_access_exception
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ 	/* Instruction Access Exception, tl1. */
+ sun4v_iacc_tl1:
+@@ -278,7 +278,7 @@ sun4v_iacc_tl1:
+ 	mov	%l5, %o2
+ 	call	sun4v_insn_access_exception_tl1
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ 	/* Data Access Exception, tl0. */
+ sun4v_dacc:
+@@ -294,7 +294,7 @@ sun4v_dacc:
+ 	mov	%l5, %o2
+ 	call	sun4v_data_access_exception
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ 	/* Data Access Exception, tl1. */
+ sun4v_dacc_tl1:
+@@ -310,7 +310,7 @@ sun4v_dacc_tl1:
+ 	mov	%l5, %o2
+ 	call	sun4v_data_access_exception_tl1
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ 	/* Memory Address Unaligned.  */
+ sun4v_mna:
+@@ -344,7 +344,7 @@ sun4v_mna:
+ 	mov	%l5, %o2
+ 	call	sun4v_do_mna
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ 	/* Privileged Action.  */
+ sun4v_privact:
+@@ -352,7 +352,7 @@ sun4v_privact:
+ 	 rd	%pc, %g7
+ 	call	do_privact
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ 	/* Unaligned ldd float, tl0. */
+ sun4v_lddfmna:
+@@ -368,7 +368,7 @@ sun4v_lddfmna:
+ 	mov	%l5, %o2
+ 	call	handle_lddfmna
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ 	/* Unaligned std float, tl0. */
+ sun4v_stdfmna:
+@@ -384,7 +384,7 @@ sun4v_stdfmna:
+ 	mov	%l5, %o2
+ 	call	handle_stdfmna
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ #define BRANCH_ALWAYS	0x10680000
+ #define NOP		0x01000000
+diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c
+deleted file mode 100644
+index 75d2bad..0000000
+--- a/arch/sparc64/kernel/sunos_ioctl32.c
++++ /dev/null
+@@ -1,275 +0,0 @@
+-/* $Id: sunos_ioctl32.c,v 1.11 2000/07/30 23:12:24 davem Exp $
+- * sunos_ioctl32.c: SunOS ioctl compatibility on sparc64.
+- *
+- * Copyright (C) 1995 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- * Copyright (C) 1995, 1996, 1997 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#include <asm/uaccess.h>
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/termios.h>
+-#include <linux/tty.h>
+-#include <linux/ioctl.h>
+-#include <linux/route.h>
+-#include <linux/sockios.h>
+-#include <linux/if.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/syscalls.h>
+-#include <linux/compat.h>
+-
+-#define SUNOS_NR_OPEN	256
+-
+-struct rtentry32 {
+-        u32   		rt_pad1;
+-        struct sockaddr rt_dst;         /* target address               */
+-        struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
+-        struct sockaddr rt_genmask;     /* target network mask (IP)     */
+-        unsigned short  rt_flags;
+-        short           rt_pad2;
+-        u32   		rt_pad3;
+-        unsigned char   rt_tos;
+-        unsigned char   rt_class;
+-        short           rt_pad4;
+-        short           rt_metric;      /* +1 for binary compatibility! */
+-        /* char * */ u32 rt_dev;        /* forcing the device at add    */
+-        u32   		rt_mtu;         /* per route MTU/Window         */
+-        u32   		rt_window;      /* Window clamping              */
+-        unsigned short  rt_irtt;        /* Initial RTT                  */
+-
+-};
+-
+-struct ifmap32 {
+-	u32 mem_start;
+-	u32 mem_end;
+-	unsigned short base_addr;
+-	unsigned char irq;
+-	unsigned char dma;
+-	unsigned char port;
+-};
+-
+-struct ifreq32 {
+-#define IFHWADDRLEN     6
+-#define IFNAMSIZ        16
+-        union {
+-                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
+-        } ifr_ifrn;
+-        union {
+-                struct  sockaddr ifru_addr;
+-                struct  sockaddr ifru_dstaddr;
+-                struct  sockaddr ifru_broadaddr;
+-                struct  sockaddr ifru_netmask;
+-                struct  sockaddr ifru_hwaddr;
+-                short   ifru_flags;
+-                int     ifru_ivalue;
+-                int     ifru_mtu;
+-                struct  ifmap32 ifru_map;
+-                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
+-                compat_caddr_t ifru_data;
+-        } ifr_ifru;
+-};
+-
+-struct ifconf32 {
+-        int     ifc_len;                        /* size of buffer       */
+-        compat_caddr_t  ifcbuf;
+-};
+-
+-extern asmlinkage int compat_sys_ioctl(unsigned int, unsigned int, u32);
+-
+-asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg)
+-{
+-	int ret = -EBADF;
+-
+-	if(fd >= SUNOS_NR_OPEN)
+-		goto out;
+-	if(!fcheck(fd))
+-		goto out;
+-
+-	if(cmd == TIOCSETD) {
+-		mm_segment_t old_fs = get_fs();
+-		int __user *p;
+-		int ntty = N_TTY;
+-		int tmp;
+-
+-		p = (int __user *) (unsigned long) arg;
+-		ret = -EFAULT;
+-		if(get_user(tmp, p))
+-			goto out;
+-		if(tmp == 2) {
+-			set_fs(KERNEL_DS);
+-			ret = sys_ioctl(fd, cmd, (unsigned long) &ntty);
+-			set_fs(old_fs);
+-			ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+-			goto out;
+-		}
+-	}
+-	if(cmd == TIOCNOTTY) {
+-		ret = sys_setsid();
+-		goto out;
+-	}
+-	switch(cmd) {
+-	case _IOW('r', 10, struct rtentry32):
+-		ret = compat_sys_ioctl(fd, SIOCADDRT, arg);
+-		goto out;
+-	case _IOW('r', 11, struct rtentry32):
+-		ret = compat_sys_ioctl(fd, SIOCDELRT, arg);
+-		goto out;
+-
+-	case _IOW('i', 12, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCSIFADDR, arg);
+-		goto out;
+-	case _IOWR('i', 13, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCGIFADDR, arg);
+-		goto out;
+-	case _IOW('i', 14, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg);
+-		goto out;
+-	case _IOWR('i', 15, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg);
+-		goto out;
+-	case _IOW('i', 16, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCSIFFLAGS, arg);
+-		goto out;
+-	case _IOWR('i', 17, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCGIFFLAGS, arg);
+-		goto out;
+-	case _IOW('i', 18, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCSIFMEM, arg);
+-		goto out;
+-	case _IOWR('i', 19, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCGIFMEM, arg);
+-		goto out;
+-
+-	case _IOWR('i', 20, struct ifconf32):
+-		ret = compat_sys_ioctl(fd, SIOCGIFCONF, arg);
+-		goto out;
+-
+-	case _IOW('i', 21, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCSIFMTU, arg);
+-		goto out;
+-
+-	case _IOWR('i', 22, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCGIFMTU, arg);
+-		goto out;
+-
+-	case _IOWR('i', 23, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg);
+-		goto out;
+-	case _IOW('i', 24, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg);
+-		goto out;
+-	case _IOWR('i', 25, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCGIFNETMASK, arg);
+-		goto out;
+-	case _IOW('i', 26, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCSIFNETMASK, arg);
+-		goto out;
+-	case _IOWR('i', 27, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCGIFMETRIC, arg);
+-		goto out;
+-	case _IOW('i', 28, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCSIFMETRIC, arg);
+-		goto out;
+-
+-	case _IOW('i', 30, struct arpreq):
+-		ret = compat_sys_ioctl(fd, SIOCSARP, arg);
+-		goto out;
+-	case _IOWR('i', 31, struct arpreq):
+-		ret = compat_sys_ioctl(fd, SIOCGARP, arg);
+-		goto out;
+-	case _IOW('i', 32, struct arpreq):
+-		ret = compat_sys_ioctl(fd, SIOCDARP, arg);
+-		goto out;
+-
+-	case _IOW('i', 40, struct ifreq32): /* SIOCUPPER */
+-	case _IOW('i', 41, struct ifreq32): /* SIOCLOWER */
+-	case _IOW('i', 44, struct ifreq32): /* SIOCSETSYNC */
+-	case _IOW('i', 45, struct ifreq32): /* SIOCGETSYNC */
+-	case _IOW('i', 46, struct ifreq32): /* SIOCSSDSTATS */
+-	case _IOW('i', 47, struct ifreq32): /* SIOCSSESTATS */
+-	case _IOW('i', 48, struct ifreq32): /* SIOCSPROMISC */
+-		ret = -EOPNOTSUPP;
+-		goto out;
+-
+-	case _IOW('i', 49, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCADDMULTI, arg);
+-		goto out;
+-	case _IOW('i', 50, struct ifreq32):
+-		ret = compat_sys_ioctl(fd, SIOCDELMULTI, arg);
+-		goto out;
+-
+-	/* FDDI interface ioctls, unsupported. */
+-		
+-	case _IOW('i', 51, struct ifreq32): /* SIOCFDRESET */
+-	case _IOW('i', 52, struct ifreq32): /* SIOCFDSLEEP */
+-	case _IOW('i', 53, struct ifreq32): /* SIOCSTRTFMWAR */
+-	case _IOW('i', 54, struct ifreq32): /* SIOCLDNSTRTFW */
+-	case _IOW('i', 55, struct ifreq32): /* SIOCGETFDSTAT */
+-	case _IOW('i', 56, struct ifreq32): /* SIOCFDNMIINT */
+-	case _IOW('i', 57, struct ifreq32): /* SIOCFDEXUSER */
+-	case _IOW('i', 58, struct ifreq32): /* SIOCFDGNETMAP */
+-	case _IOW('i', 59, struct ifreq32): /* SIOCFDGIOCTL */
+-		printk("FDDI ioctl, returning EOPNOTSUPP\n");
+-		ret = -EOPNOTSUPP;
+-		goto out;
+-
+-	case _IOW('t', 125, int):
+-		/* More stupid tty sunos ioctls, just
+-		 * say it worked.
+-		 */
+-		ret = 0;
+-		goto out;
+-
+-	/* Non posix grp */
+-	case _IOW('t', 118, int): {
+-		int oldval, newval, __user *ptr;
+-
+-		cmd = TIOCSPGRP;
+-		ptr = (int __user *) (unsigned long) arg;
+-		ret = -EFAULT;
+-		if(get_user(oldval, ptr))
+-			goto out;
+-		ret = compat_sys_ioctl(fd, cmd, arg);
+-		__get_user(newval, ptr);
+-		if(newval == -1) {
+-			__put_user(oldval, ptr);
+-			ret = -EIO;
+-		}
+-		if(ret == -ENOTTY)
+-			ret = -EIO;
+-		goto out;
+-	}
+-
+-	case _IOR('t', 119, int): {
+-		int oldval, newval, __user *ptr;
+-
+-		cmd = TIOCGPGRP;
+-		ptr = (int __user *) (unsigned long) arg;
+-		ret = -EFAULT;
+-		if(get_user(oldval, ptr))
+-			goto out;
+-		ret = compat_sys_ioctl(fd, cmd, arg);
+-		__get_user(newval, ptr);
+-		if(newval == -1) {
+-			__put_user(oldval, ptr);
+-			ret = -EIO;
+-		}
+-		if(ret == -ENOTTY)
+-			ret = -EIO;
+-		goto out;
+-	}
+-	};
+-
+-	ret = compat_sys_ioctl(fd, cmd, arg);
+-	/* so stupid... */
+-	ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+-out:
+-	return ret;
+-}
+diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
+index f952745..8d4761f 100644
+--- a/arch/sparc64/kernel/sys_sparc.c
++++ b/arch/sparc64/kernel/sys_sparc.c
+@@ -454,8 +454,8 @@ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
+ 			err = sys_semget(first, (int)second, (int)third);
+ 			goto out;
+ 		case SEMCTL: {
+-			err = sys_semctl(first, third,
+-					 (int)second | IPC_64,
++			err = sys_semctl(first, second,
++					 (int)third | IPC_64,
+ 					 (union semun) ptr);
+ 			goto out;
+ 		}
+@@ -720,44 +720,6 @@ out:
+ 	return err;
+ }
+ 
+-asmlinkage long solaris_syscall(struct pt_regs *regs)
+-{
+-	static int count;
+-
+-	regs->tpc = regs->tnpc;
+-	regs->tnpc += 4;
+-	if (test_thread_flag(TIF_32BIT)) {
+-		regs->tpc &= 0xffffffff;
+-		regs->tnpc &= 0xffffffff;
+-	}
+-	if (++count <= 5) {
+-		printk ("For Solaris binary emulation you need solaris module loaded\n");
+-		show_regs (regs);
+-	}
+-	send_sig(SIGSEGV, current, 1);
+-
+-	return -ENOSYS;
+-}
+-
+-#ifndef CONFIG_SUNOS_EMUL
+-asmlinkage long sunos_syscall(struct pt_regs *regs)
+-{
+-	static int count;
+-
+-	regs->tpc = regs->tnpc;
+-	regs->tnpc += 4;
+-	if (test_thread_flag(TIF_32BIT)) {
+-		regs->tpc &= 0xffffffff;
+-		regs->tnpc &= 0xffffffff;
+-	}
+-	if (++count <= 20)
+-		printk ("SunOS binary emulation not compiled in\n");
+-	force_sig(SIGSEGV, current);
+-
+-	return -ENOSYS;
+-}
+-#endif
+-
+ asmlinkage long sys_utrap_install(utrap_entry_t type,
+ 				  utrap_handler_t new_p,
+ 				  utrap_handler_t new_d,
+diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
+index 2455fa4..c1a61e9 100644
+--- a/arch/sparc64/kernel/sys_sparc32.c
++++ b/arch/sparc64/kernel/sys_sparc32.c
+@@ -55,7 +55,6 @@
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+ #include <asm/fpumacro.h>
+-#include <asm/semaphore.h>
+ #include <asm/mmu_context.h>
+ #include <asm/compat_signal.h>
+ 
+diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
+deleted file mode 100644
+index e91194f..0000000
+--- a/arch/sparc64/kernel/sys_sunos32.c
++++ /dev/null
+@@ -1,1359 +0,0 @@
+-/* $Id: sys_sunos32.c,v 1.64 2002/02/09 19:49:31 davem Exp $
+- * sys_sunos32.c: SunOS binary compatibility layer on sparc64.
+- *
+- * Copyright (C) 1995, 1996, 1997 David S. Miller (davem at caip.rutgers.edu)
+- * Copyright (C) 1995 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- *
+- * Based upon preliminary work which is:
+- *
+- * Copyright (C) 1995 Adrian M. Rodriguez (adrian at remus.rutgers.edu)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/capability.h>
+-#include <linux/compat.h>
+-#include <linux/mman.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/resource.h>
+-#include <linux/ipc.h>
+-#include <linux/shm.h>
+-#include <linux/msg.h>
+-#include <linux/sem.h>
+-#include <linux/signal.h>
+-#include <linux/uio.h>
+-#include <linux/utsname.h>
+-#include <linux/major.h>
+-#include <linux/stat.h>
+-#include <linux/slab.h>
+-#include <linux/pagemap.h>
+-#include <linux/errno.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/syscalls.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/pconf.h>
+-#include <asm/idprom.h> /* for gethostid() */
+-#include <asm/unistd.h>
+-#include <asm/system.h>
+-#include <asm/compat_signal.h>
+-
+-/* For the nfs mount emulation */
+-#include <linux/socket.h>
+-#include <linux/in.h>
+-#include <linux/nfs.h>
+-#include <linux/nfs2.h>
+-#include <linux/nfs_mount.h>
+-
+-/* for sunos_select */
+-#include <linux/time.h>
+-#include <linux/personality.h>
+-
+-/* For SOCKET_I */
+-#include <net/sock.h>
+-#include <net/compat.h>
+-
+-#define SUNOS_NR_OPEN	256
+-
+-asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
+-{
+-	struct file *file = NULL;
+-	unsigned long retval, ret_type;
+-
+-	if (flags & MAP_NORESERVE) {
+-		static int cnt;
+-		if (cnt++ < 10)
+-			printk("%s:  unimplemented SunOS MAP_NORESERVE mmap() flag\n",
+-			       current->comm);
+-		flags &= ~MAP_NORESERVE;
+-	}
+-	retval = -EBADF;
+-	if (!(flags & MAP_ANONYMOUS)) {
+-		struct inode * inode;
+-		if (fd >= SUNOS_NR_OPEN)
+-			goto out;
+- 		file = fget(fd);
+-		if (!file)
+-			goto out;
+-		inode = file->f_path.dentry->d_inode;
+-		if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) {
+-			flags |= MAP_ANONYMOUS;
+-			fput(file);
+-			file = NULL;
+-		}
+-	}
+-
+-	retval = -EINVAL;
+-	if (!(flags & MAP_FIXED))
+-		addr = 0;
+-	else if (len > 0xf0000000 || addr > 0xf0000000 - len)
+-		goto out_putf;
+-	ret_type = flags & _MAP_NEW;
+-	flags &= ~_MAP_NEW;
+-
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	down_write(&current->mm->mmap_sem);
+-	retval = do_mmap(file,
+-			 (unsigned long) addr, (unsigned long) len,
+-			 (unsigned long) prot, (unsigned long) flags,
+-			 (unsigned long) off);
+-	up_write(&current->mm->mmap_sem);
+-	if (!ret_type)
+-		retval = ((retval < 0xf0000000) ? 0 : retval);
+-out_putf:
+-	if (file)
+-		fput(file);
+-out:
+-	return (u32) retval;
+-}
+-
+-asmlinkage int sunos_mctl(u32 addr, u32 len, int function, u32 arg)
+-{
+-	return 0;
+-}
+-
+-asmlinkage int sunos_brk(u32 baddr)
+-{
+-	int freepages, retval = -ENOMEM;
+-	unsigned long rlim;
+-	unsigned long newbrk, oldbrk, brk = (unsigned long) baddr;
+-
+-	down_write(&current->mm->mmap_sem);
+-	if (brk < current->mm->end_code)
+-		goto out;
+-	newbrk = PAGE_ALIGN(brk);
+-	oldbrk = PAGE_ALIGN(current->mm->brk);
+-	retval = 0;
+-	if (oldbrk == newbrk) {
+-		current->mm->brk = brk;
+-		goto out;
+-	}
+-	/* Always allow shrinking brk. */
+-	if (brk <= current->mm->brk) {
+-		current->mm->brk = brk;
+-		do_munmap(current->mm, newbrk, oldbrk-newbrk);
+-		goto out;
+-	}
+-	/* Check against rlimit and stack.. */
+-	retval = -ENOMEM;
+-	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+-	if (rlim >= RLIM_INFINITY)
+-		rlim = ~0;
+-	if (brk - current->mm->end_code > rlim)
+-		goto out;
+-	/* Check against existing mmap mappings. */
+-	if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
+-		goto out;
+-	/* stupid algorithm to decide if we have enough memory: while
+-	 * simple, it hopefully works in most obvious cases.. Easy to
+-	 * fool it, but this should catch most mistakes.
+-	 */
+-	freepages = global_page_state(NR_FILE_PAGES);
+-	freepages >>= 1;
+-	freepages += nr_free_pages();
+-	freepages += nr_swap_pages;
+-	freepages -= num_physpages >> 4;
+-	freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
+-	if (freepages < 0)
+-		goto out;
+-	/* Ok, we have probably got enough memory - let it rip. */
+-	current->mm->brk = brk;
+-	do_brk(oldbrk, newbrk-oldbrk);
+-	retval = 0;
+-out:
+-	up_write(&current->mm->mmap_sem);
+-	return retval;
+-}
+-
+-asmlinkage u32 sunos_sbrk(int increment)
+-{
+-	int error, oldbrk;
+-
+-	/* This should do it hopefully... */
+-	oldbrk = (int)current->mm->brk;
+-	error = sunos_brk(((int) current->mm->brk) + increment);
+-	if (!error)
+-		error = oldbrk;
+-	return error;
+-}
+-
+-asmlinkage u32 sunos_sstk(int increment)
+-{
+-	printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
+-	       current->comm, increment);
+-
+-	return (u32)-1;
+-}
+-
+-/* Give hints to the kernel as to what paging strategy to use...
+- * Completely bogus, don't remind me.
+- */
+-#define VA_NORMAL     0 /* Normal vm usage expected */
+-#define VA_ABNORMAL   1 /* Abnormal/random vm usage probable */
+-#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
+-#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
+-static char *vstrings[] = {
+-	"VA_NORMAL",
+-	"VA_ABNORMAL",
+-	"VA_SEQUENTIAL",
+-	"VA_INVALIDATE",
+-};
+-
+-asmlinkage void sunos_vadvise(u32 strategy)
+-{
+-	static int count;
+-
+-	/* I wanna see who uses this... */
+-	if (count++ < 5)
+-		printk("%s: Advises us to use %s paging strategy\n",
+-		       current->comm,
+-		       strategy <= 3 ? vstrings[strategy] : "BOGUS");
+-}
+-
+-/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
+- * resource limit and is for backwards compatibility with older sunos
+- * revs.
+- */
+-asmlinkage int sunos_getdtablesize(void)
+-{
+-	return SUNOS_NR_OPEN;
+-}
+-
+-
+-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+-
+-asmlinkage u32 sunos_sigblock(u32 blk_mask)
+-{
+-	u32 old;
+-
+-	spin_lock_irq(&current->sighand->siglock);
+-	old = (u32) current->blocked.sig[0];
+-	current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
+-	recalc_sigpending();
+-	spin_unlock_irq(&current->sighand->siglock);
+-	return old;
+-}
+-
+-asmlinkage u32 sunos_sigsetmask(u32 newmask)
+-{
+-	u32 retval;
+-
+-	spin_lock_irq(&current->sighand->siglock);
+-	retval = (u32) current->blocked.sig[0];
+-	current->blocked.sig[0] = (newmask & _BLOCKABLE);
+-	recalc_sigpending();
+-	spin_unlock_irq(&current->sighand->siglock);
+-	return retval;
+-}
+-
+-/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant)    */
+-/* getdents system call, the format of the structure just has a different */
+-/* layout (d_off+d_ino instead of d_ino+d_off) */
+-struct sunos_dirent {
+-    s32		d_off;
+-    u32		d_ino;
+-    u16		d_reclen;
+-    u16		d_namlen;
+-    char	d_name[1];
+-};
+-
+-struct sunos_dirent_callback {
+-    struct sunos_dirent __user *curr;
+-    struct sunos_dirent __user *previous;
+-    int count;
+-    int error;
+-};
+-
+-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
+-#define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1))
+-
+-static int sunos_filldir(void * __buf, const char * name, int namlen,
+-			 loff_t offset, ino_t ino, unsigned int d_type)
+-{
+-	struct sunos_dirent __user *dirent;
+-	struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
+-	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+-	u32 d_ino;
+-
+-	buf->error = -EINVAL;	/* only used if we fail.. */
+-	if (reclen > buf->count)
+-		return -EINVAL;
+-	d_ino = ino;
+-	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
+-		return -EOVERFLOW;
+-	dirent = buf->previous;
+-	if (dirent)
+-		put_user(offset, &dirent->d_off);
+-	dirent = buf->curr;
+-	buf->previous = dirent;
+-	put_user(d_ino, &dirent->d_ino);
+-	put_user(namlen, &dirent->d_namlen);
+-	put_user(reclen, &dirent->d_reclen);
+-	if (copy_to_user(dirent->d_name, name, namlen))
+-		return -EFAULT;
+-	put_user(0, dirent->d_name + namlen);
+-	dirent = (void __user *) dirent + reclen;
+-	buf->curr = dirent;
+-	buf->count -= reclen;
+-	return 0;
+-}
+-
+-asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt)
+-{
+-	struct file * file;
+-	struct sunos_dirent __user *lastdirent;
+-	struct sunos_dirent_callback buf;
+-	int error = -EBADF;
+-
+-	if (fd >= SUNOS_NR_OPEN)
+-		goto out;
+-
+-	file = fget(fd);
+-	if (!file)
+-		goto out;
+-
+-	error = -EINVAL;
+-	if (cnt < (sizeof(struct sunos_dirent) + 255))
+-		goto out_putf;
+-
+-	buf.curr = (struct sunos_dirent __user *) dirent;
+-	buf.previous = NULL;
+-	buf.count = cnt;
+-	buf.error = 0;
+-
+-	error = vfs_readdir(file, sunos_filldir, &buf);
+-	if (error < 0)
+-		goto out_putf;
+-
+-	lastdirent = buf.previous;
+-	error = buf.error;
+-	if (lastdirent) {
+-		put_user(file->f_pos, &lastdirent->d_off);
+-		error = cnt - buf.count;
+-	}
+-
+-out_putf:
+-	fput(file);
+-out:
+-	return error;
+-}
+-
+-/* Old sunos getdirentries, severely broken compatibility stuff here. */
+-struct sunos_direntry {
+-    u32		d_ino;
+-    u16		d_reclen;
+-    u16		d_namlen;
+-    char	d_name[1];
+-};
+-
+-struct sunos_direntry_callback {
+-    struct sunos_direntry __user *curr;
+-    struct sunos_direntry __user *previous;
+-    int count;
+-    int error;
+-};
+-
+-static int sunos_filldirentry(void * __buf, const char * name, int namlen,
+-			      loff_t offset, ino_t ino, unsigned int d_type)
+-{
+-	struct sunos_direntry __user *dirent;
+-	struct sunos_direntry_callback * buf =
+-		(struct sunos_direntry_callback *) __buf;
+-	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+-	u32 d_ino;
+-
+-	buf->error = -EINVAL;	/* only used if we fail.. */
+-	if (reclen > buf->count)
+-		return -EINVAL;
+-	d_ino = ino;
+-	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
+-		return -EOVERFLOW;
+-	dirent = buf->previous;
+-	dirent = buf->curr;
+-	buf->previous = dirent;
+-	put_user(d_ino, &dirent->d_ino);
+-	put_user(namlen, &dirent->d_namlen);
+-	put_user(reclen, &dirent->d_reclen);
+-	if (copy_to_user(dirent->d_name, name, namlen))
+-		return -EFAULT;
+-	put_user(0, dirent->d_name + namlen);
+-	dirent = (void __user *) dirent + reclen;
+-	buf->curr = dirent;
+-	buf->count -= reclen;
+-	return 0;
+-}
+-
+-asmlinkage int sunos_getdirentries(unsigned int fd,
+-				   void __user *dirent,
+-				   int cnt,
+-				   unsigned int __user *basep)
+-{
+-	struct file * file;
+-	struct sunos_direntry __user *lastdirent;
+-	int error = -EBADF;
+-	struct sunos_direntry_callback buf;
+-
+-	if (fd >= SUNOS_NR_OPEN)
+-		goto out;
+-
+-	file = fget(fd);
+-	if (!file)
+-		goto out;
+-
+-	error = -EINVAL;
+-	if (cnt < (sizeof(struct sunos_direntry) + 255))
+-		goto out_putf;
+-
+-	buf.curr = (struct sunos_direntry __user *) dirent;
+-	buf.previous = NULL;
+-	buf.count = cnt;
+-	buf.error = 0;
+-
+-	error = vfs_readdir(file, sunos_filldirentry, &buf);
+-	if (error < 0)
+-		goto out_putf;
+-
+-	lastdirent = buf.previous;
+-	error = buf.error;
+-	if (lastdirent) {
+-		put_user(file->f_pos, basep);
+-		error = cnt - buf.count;
+-	}
+-
+-out_putf:
+-	fput(file);
+-out:
+-	return error;
+-}
+-
+-struct sunos_utsname {
+-	char sname[9];
+-	char nname[9];
+-	char nnext[56];
+-	char rel[9];
+-	char ver[9];
+-	char mach[9];
+-};
+-
+-asmlinkage int sunos_uname(struct sunos_utsname __user *name)
+-{
+-	int ret;
+-
+-	down_read(&uts_sem);
+-	ret = copy_to_user(&name->sname[0], &utsname()->sysname[0],
+-			   sizeof(name->sname) - 1);
+-	ret |= copy_to_user(&name->nname[0], &utsname()->nodename[0],
+-			    sizeof(name->nname) - 1);
+-	ret |= put_user('\0', &name->nname[8]);
+-	ret |= copy_to_user(&name->rel[0], &utsname()->release[0],
+-			    sizeof(name->rel) - 1);
+-	ret |= copy_to_user(&name->ver[0], &utsname()->version[0],
+-			    sizeof(name->ver) - 1);
+-	ret |= copy_to_user(&name->mach[0], &utsname()->machine[0],
+-			    sizeof(name->mach) - 1);
+-	up_read(&uts_sem);
+-	return (ret ? -EFAULT : 0);
+-}
+-
+-asmlinkage int sunos_nosys(void)
+-{
+-	struct pt_regs *regs;
+-	siginfo_t info;
+-	static int cnt;
+-
+-	regs = current_thread_info()->kregs;
+-	if (test_thread_flag(TIF_32BIT)) {
+-		regs->tpc &= 0xffffffff;
+-		regs->tnpc &= 0xffffffff;
+-	}
+-	info.si_signo = SIGSYS;
+-	info.si_errno = 0;
+-	info.si_code = __SI_FAULT|0x100;
+-	info.si_addr = (void __user *)regs->tpc;
+-	info.si_trapno = regs->u_regs[UREG_G1];
+-	send_sig_info(SIGSYS, &info, current);
+-	if (cnt++ < 4) {
+-		printk("Process makes ni_syscall number %d, register dump:\n",
+-		       (int) regs->u_regs[UREG_G1]);
+-		show_regs(regs);
+-	}
+-	return -ENOSYS;
+-}
+-
+-/* This is not a real and complete implementation yet, just to keep
+- * the easy SunOS binaries happy.
+- */
+-asmlinkage int sunos_fpathconf(int fd, int name)
+-{
+-	int ret;
+-
+-	switch(name) {
+-	case _PCONF_LINK:
+-		ret = LINK_MAX;
+-		break;
+-	case _PCONF_CANON:
+-		ret = MAX_CANON;
+-		break;
+-	case _PCONF_INPUT:
+-		ret = MAX_INPUT;
+-		break;
+-	case _PCONF_NAME:
+-		ret = NAME_MAX;
+-		break;
+-	case _PCONF_PATH:
+-		ret = PATH_MAX;
+-		break;
+-	case _PCONF_PIPE:
+-		ret = PIPE_BUF;
+-		break;
+-	case _PCONF_CHRESTRICT:		/* XXX Investigate XXX */
+-		ret = 1;
+-		break;
+-	case _PCONF_NOTRUNC:		/* XXX Investigate XXX */
+-	case _PCONF_VDISABLE:
+-		ret = 0;
+-		break;
+-	default:
+-		ret = -EINVAL;
+-		break;
+-	}
+-	return ret;
+-}
+-
+-asmlinkage int sunos_pathconf(u32 u_path, int name)
+-{
+-	int ret;
+-
+-	ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
+-	return ret;
+-}
+-
+-asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp_x)
+-{
+-	int ret;
+-
+-	/* SunOS binaries expect that select won't change the tvp contents */
+-	ret = compat_sys_select(width, compat_ptr(inp), compat_ptr(outp),
+-				compat_ptr(exp), compat_ptr(tvp_x));
+-	if (ret == -EINTR && tvp_x) {
+-		struct compat_timeval __user *tvp = compat_ptr(tvp_x);
+-		time_t sec, usec;
+-
+-		__get_user(sec, &tvp->tv_sec);
+-		__get_user(usec, &tvp->tv_usec);
+-		if (sec == 0 && usec == 0)
+-			ret = 0;
+-	}
+-	return ret;
+-}
+-
+-asmlinkage void sunos_nop(void)
+-{
+-	return;
+-}
+-
+-#if 0 /* This code doesn't translate user pointers correctly,
+-       * disable for now. -DaveM
+-       */
+-
+-/* XXXXXXXXXX SunOS mount/umount. XXXXXXXXXXX */
+-#define SMNT_RDONLY       1
+-#define SMNT_NOSUID       2
+-#define SMNT_NEWTYPE      4
+-#define SMNT_GRPID        8
+-#define SMNT_REMOUNT      16
+-#define SMNT_NOSUB        32
+-#define SMNT_MULTI        64
+-#define SMNT_SYS5         128
+-
+-struct sunos_fh_t {
+-	char fh_data [NFS_FHSIZE];
+-};
+-
+-struct sunos_nfs_mount_args {
+-	struct sockaddr_in  *addr; /* file server address */
+-	struct nfs_fh *fh;     /* File handle to be mounted */
+-	int        flags;      /* flags */
+-	int        wsize;      /* write size in bytes */
+-	int        rsize;      /* read size in bytes */
+-	int        timeo;      /* initial timeout in .1 secs */
+-	int        retrans;    /* times to retry send */
+-	char       *hostname;  /* server's hostname */
+-	int        acregmin;   /* attr cache file min secs */
+-	int        acregmax;   /* attr cache file max secs */
+-	int        acdirmin;   /* attr cache dir min secs */
+-	int        acdirmax;   /* attr cache dir max secs */
+-	char       *netname;   /* server's netname */
+-};
+-
+-
+-/* Bind the socket on a local reserved port and connect it to the
+- * remote server.  This on Linux/i386 is done by the mount program,
+- * not by the kernel. 
+- */
+-/* XXXXXXXXXXXXXXXXXXXX */
+-static int
+-sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
+-{
+-	struct sockaddr_in local;
+-	struct sockaddr_in server;
+-	int    try_port;
+-	int    ret;
+-	struct socket *socket;
+-	struct inode  *inode;
+-	struct file   *file;
+-
+-	file = fget(fd);
+-	if (!file)
+-		return 0;
+-
+-	inode = file->f_path.dentry->d_inode;
+-
+-	socket = SOCKET_I(inode);
+-	local.sin_family = AF_INET;
+-	local.sin_addr.s_addr = htonl(INADDR_ANY);
+-
+-	/* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
+-	try_port = 1024;
+-	do {
+-		local.sin_port = htons (--try_port);
+-		ret = socket->ops->bind(socket, (struct sockaddr*)&local,
+-					sizeof(local));
+-	} while (ret && try_port > (1024 / 2));
+-
+-	if (ret) {
+-		fput(file);
+-		return 0;
+-	}
+-
+-	server.sin_family = AF_INET;
+-	server.sin_addr = addr->sin_addr;
+-	server.sin_port = NFS_PORT;
+-
+-	/* Call sys_connect */
+-	ret = socket->ops->connect (socket, (struct sockaddr *) &server,
+-				    sizeof (server), file->f_flags);
+-	fput(file);
+-	if (ret < 0)
+-		return 0;
+-	return 1;
+-}
+-
+-/* XXXXXXXXXXXXXXXXXXXX */
+-static int get_default (int value, int def_value)
+-{
+-    if (value)
+-	return value;
+-    else
+-	return def_value;
+-}
+-
+-/* XXXXXXXXXXXXXXXXXXXX */
+-static int sunos_nfs_mount(char *dir_name, int linux_flags, void __user *data)
+-{
+-	int  server_fd, err;
+-	char *the_name, *mount_page;
+-	struct nfs_mount_data linux_nfs_mount;
+-	struct sunos_nfs_mount_args sunos_mount;
+-
+-	/* Ok, here comes the fun part: Linux's nfs mount needs a
+-	 * socket connection to the server, but SunOS mount does not
+-	 * require this, so we use the information on the destination
+-	 * address to create a socket and bind it to a reserved
+-	 * port on this system
+-	 */
+-	if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)))
+-		return -EFAULT;
+-
+-	server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+-	if (server_fd < 0)
+-		return -ENXIO;
+-
+-	if (copy_from_user(&linux_nfs_mount.addr, sunos_mount.addr,
+-			   sizeof(*sunos_mount.addr)) ||
+-	    copy_from_user(&linux_nfs_mount.root, sunos_mount.fh,
+-			   sizeof(*sunos_mount.fh))) {
+-		sys_close (server_fd);
+-		return -EFAULT;
+-	}
+-
+-	if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){
+-		sys_close (server_fd);
+-		return -ENXIO;
+-	}
+-
+-	/* Now, bind it to a locally reserved port */
+-	linux_nfs_mount.version  = NFS_MOUNT_VERSION;
+-	linux_nfs_mount.flags    = sunos_mount.flags;
+-	linux_nfs_mount.fd       = server_fd;
+-	
+-	linux_nfs_mount.rsize    = get_default (sunos_mount.rsize, 8192);
+-	linux_nfs_mount.wsize    = get_default (sunos_mount.wsize, 8192);
+-	linux_nfs_mount.timeo    = get_default (sunos_mount.timeo, 10);
+-	linux_nfs_mount.retrans  = sunos_mount.retrans;
+-	
+-	linux_nfs_mount.acregmin = sunos_mount.acregmin;
+-	linux_nfs_mount.acregmax = sunos_mount.acregmax;
+-	linux_nfs_mount.acdirmin = sunos_mount.acdirmin;
+-	linux_nfs_mount.acdirmax = sunos_mount.acdirmax;
+-
+-	the_name = getname(sunos_mount.hostname);
+-	if (IS_ERR(the_name))
+-		return PTR_ERR(the_name);
+-
+-	strlcpy(linux_nfs_mount.hostname, the_name,
+-		sizeof(linux_nfs_mount.hostname));
+-	putname (the_name);
+-	
+-	mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+-	if (!mount_page)
+-		return -ENOMEM;
+-
+-	memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+-
+-	err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+-
+-	free_page((unsigned long) mount_page);
+-	return err;
+-}
+-
+-/* XXXXXXXXXXXXXXXXXXXX */
+-asmlinkage int
+-sunos_mount(char *type, char *dir, int flags, void *data)
+-{
+-	int linux_flags = 0;
+-	int ret = -EINVAL;
+-	char *dev_fname = 0;
+-	char *dir_page, *type_page;
+-
+-	if (!capable (CAP_SYS_ADMIN))
+-		return -EPERM;
+-
+-	/* We don't handle the integer fs type */
+-	if ((flags & SMNT_NEWTYPE) == 0)
+-		goto out;
+-
+-	/* Do not allow for those flags we don't support */
+-	if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
+-		goto out;
+-
+-	if (flags & SMNT_REMOUNT)
+-		linux_flags |= MS_REMOUNT;
+-	if (flags & SMNT_RDONLY)
+-		linux_flags |= MS_RDONLY;
+-	if (flags & SMNT_NOSUID)
+-		linux_flags |= MS_NOSUID;
+-
+-	dir_page = getname(dir);
+-	ret = PTR_ERR(dir_page);
+-	if (IS_ERR(dir_page))
+-		goto out;
+-
+-	type_page = getname(type);
+-	ret = PTR_ERR(type_page);
+-	if (IS_ERR(type_page))
+-		goto out1;
+-
+-	if (strcmp(type_page, "ext2") == 0) {
+-		dev_fname = getname(data);
+-	} else if (strcmp(type_page, "iso9660") == 0) {
+-		dev_fname = getname(data);
+-	} else if (strcmp(type_page, "minix") == 0) {
+-		dev_fname = getname(data);
+-	} else if (strcmp(type_page, "nfs") == 0) {
+-		ret = sunos_nfs_mount (dir_page, flags, data);
+-		goto out2;
+-        } else if (strcmp(type_page, "ufs") == 0) {
+-		printk("Warning: UFS filesystem mounts unsupported.\n");
+-		ret = -ENODEV;
+-		goto out2;
+-	} else if (strcmp(type_page, "proc")) {
+-		ret = -ENODEV;
+-		goto out2;
+-	}
+-	ret = PTR_ERR(dev_fname);
+-	if (IS_ERR(dev_fname))
+-		goto out2;
+-	lock_kernel();
+-	ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL);
+-	unlock_kernel();
+-	if (dev_fname)
+-		putname(dev_fname);
+-out2:
+-	putname(type_page);
+-out1:
+-	putname(dir_page);
+-out:
+-	return ret;
+-}
+-#endif
+-
+-asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
+-{
+-	int ret;
+-
+-	/* So stupid... */
+-	if ((!pid || pid == current->pid) &&
+-	    !pgid) {
+-		sys_setsid();
+-		ret = 0;
+-	} else {
+-		ret = sys_setpgid(pid, pgid);
+-	}
+-	return ret;
+-}
+-
+-/* So stupid... */
+-extern long compat_sys_wait4(compat_pid_t, compat_uint_t __user *, int,
+-			     struct compat_rusage __user *);
+-
+-asmlinkage int sunos_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, struct compat_rusage __user *ru)
+-{
+-	int ret;
+-
+-	ret = compat_sys_wait4((pid ? pid : ((compat_pid_t)-1)),
+-			       stat_addr, options, ru);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_killpg(int pgrp, int sig)
+-{
+-	int ret;
+-
+-	rcu_read_lock();
+-	ret = -EINVAL;
+-	if (pgrp > 0)
+-		ret = kill_pgrp(find_vpid(pgrp), sig, 0);
+-	rcu_read_unlock();
+-
+-	return ret;
+-}
+-
+-asmlinkage int sunos_audit(void)
+-{
+-	printk ("sys_audit\n");
+-	return -1;
+-}
+-
+-asmlinkage u32 sunos_gethostid(void)
+-{
+-	u32 ret;
+-
+-	ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum));
+-
+-	return ret;
+-}
+-
+-/* sysconf options, for SunOS compatibility */
+-#define   _SC_ARG_MAX             1
+-#define   _SC_CHILD_MAX           2
+-#define   _SC_CLK_TCK             3
+-#define   _SC_NGROUPS_MAX         4
+-#define   _SC_OPEN_MAX            5
+-#define   _SC_JOB_CONTROL         6
+-#define   _SC_SAVED_IDS           7
+-#define   _SC_VERSION             8
+-
+-asmlinkage s32 sunos_sysconf (int name)
+-{
+-	s32 ret;
+-
+-	switch (name){
+-	case _SC_ARG_MAX:
+-		ret = ARG_MAX;
+-		break;
+-	case _SC_CHILD_MAX:
+-		ret = current->signal->rlim[RLIMIT_NPROC].rlim_cur;
+-		break;
+-	case _SC_CLK_TCK:
+-		ret = HZ;
+-		break;
+-	case _SC_NGROUPS_MAX:
+-		ret = NGROUPS_MAX;
+-		break;
+-	case _SC_OPEN_MAX:
+-		ret = current->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+-		break;
+-	case _SC_JOB_CONTROL:
+-		ret = 1;	/* yes, we do support job control */
+-		break;
+-	case _SC_SAVED_IDS:
+-		ret = 1;	/* yes, we do support saved uids  */
+-		break;
+-	case _SC_VERSION:
+-		/* mhm, POSIX_VERSION is in /usr/include/unistd.h
+-		 * should it go on /usr/include/linux?
+-		 */
+-		ret = 199009;
+-		break;
+-	default:
+-		ret = -1;
+-		break;
+-	};
+-	return ret;
+-}
+-
+-asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, void __user *ptr)
+-{
+-	union semun arg4;
+-	int ret;
+-
+-	switch (op) {
+-	case 0:
+-		/* Most arguments match on a 1:1 basis but cmd doesn't */
+-		switch(arg3) {
+-		case 4:
+-			arg3=GETPID; break;
+-		case 5:
+-			arg3=GETVAL; break;
+-		case 6:
+-			arg3=GETALL; break;
+-		case 3:
+-			arg3=GETNCNT; break;
+-		case 7:
+-			arg3=GETZCNT; break;
+-		case 8:
+-			arg3=SETVAL; break;
+-		case 9:
+-			arg3=SETALL; break;
+-		}
+-		/* sys_semctl(): */
+-		/* value to modify semaphore to */
+-		arg4.__pad = ptr;
+-		ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4);
+-		break;
+-	case 1:
+-		/* sys_semget(): */
+-		ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3);
+-		break;
+-	case 2:
+-		/* sys_semop(): */
+-		ret = sys_semop((int)arg1, (struct sembuf __user *)(unsigned long)arg2,
+-				(unsigned int) arg3);
+-		break;
+-	default:
+-		ret = -EINVAL;
+-		break;
+-	};
+-	return ret;
+-}
+-
+-struct msgbuf32 {
+-	s32 mtype;
+-	char mtext[1];
+-};
+-
+-struct ipc_perm32
+-{
+-	key_t    	  key;
+-        compat_uid_t  uid;
+-        compat_gid_t  gid;
+-        compat_uid_t  cuid;
+-        compat_gid_t  cgid;
+-        compat_mode_t mode;
+-        unsigned short  seq;
+-};
+-
+-struct msqid_ds32
+-{
+-        struct ipc_perm32 msg_perm;
+-        u32 msg_first;
+-        u32 msg_last;
+-        compat_time_t msg_stime;
+-        compat_time_t msg_rtime;
+-        compat_time_t msg_ctime;
+-        u32 wwait;
+-        u32 rwait;
+-        unsigned short msg_cbytes;
+-        unsigned short msg_qnum;  
+-        unsigned short msg_qbytes;
+-        compat_ipc_pid_t msg_lspid;
+-        compat_ipc_pid_t msg_lrpid;
+-};
+-
+-static inline int sunos_msqid_get(struct msqid_ds32 __user *user,
+-				  struct msqid_ds *kern)
+-{
+-	if (get_user(kern->msg_perm.key, &user->msg_perm.key)		||
+-	    __get_user(kern->msg_perm.uid, &user->msg_perm.uid)		||
+-	    __get_user(kern->msg_perm.gid, &user->msg_perm.gid)		||
+-	    __get_user(kern->msg_perm.cuid, &user->msg_perm.cuid)	||
+-	    __get_user(kern->msg_perm.cgid, &user->msg_perm.cgid)	||
+-	    __get_user(kern->msg_stime, &user->msg_stime)		||
+-	    __get_user(kern->msg_rtime, &user->msg_rtime)		||
+-	    __get_user(kern->msg_ctime, &user->msg_ctime)		||
+-	    __get_user(kern->msg_ctime, &user->msg_cbytes)		||
+-	    __get_user(kern->msg_ctime, &user->msg_qnum)		||
+-	    __get_user(kern->msg_ctime, &user->msg_qbytes)		||
+-	    __get_user(kern->msg_ctime, &user->msg_lspid)		||
+-	    __get_user(kern->msg_ctime, &user->msg_lrpid))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-static inline int sunos_msqid_put(struct msqid_ds32 __user *user,
+-				  struct msqid_ds *kern)
+-{
+-	if (put_user(kern->msg_perm.key, &user->msg_perm.key)		||
+-	    __put_user(kern->msg_perm.uid, &user->msg_perm.uid)		||
+-	    __put_user(kern->msg_perm.gid, &user->msg_perm.gid)		||
+-	    __put_user(kern->msg_perm.cuid, &user->msg_perm.cuid)	||
+-	    __put_user(kern->msg_perm.cgid, &user->msg_perm.cgid)	||
+-	    __put_user(kern->msg_stime, &user->msg_stime)		||
+-	    __put_user(kern->msg_rtime, &user->msg_rtime)		||
+-	    __put_user(kern->msg_ctime, &user->msg_ctime)		||
+-	    __put_user(kern->msg_ctime, &user->msg_cbytes)		||
+-	    __put_user(kern->msg_ctime, &user->msg_qnum)		||
+-	    __put_user(kern->msg_ctime, &user->msg_qbytes)		||
+-	    __put_user(kern->msg_ctime, &user->msg_lspid)		||
+-	    __put_user(kern->msg_ctime, &user->msg_lrpid))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-static inline int sunos_msgbuf_get(struct msgbuf32 __user *user, struct msgbuf *kern, int len)
+-{
+-	if (get_user(kern->mtype, &user->mtype)	||
+-	    __copy_from_user(kern->mtext, &user->mtext, len))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-static inline int sunos_msgbuf_put(struct msgbuf32 __user *user, struct msgbuf *kern, int len)
+-{
+-	if (put_user(kern->mtype, &user->mtype)	||
+-	    __copy_to_user(user->mtext, kern->mtext, len))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+-{
+-	struct sparc_stackf32 __user *sp;
+-	struct msqid_ds kds;
+-	struct msgbuf *kmbuf;
+-	mm_segment_t old_fs = get_fs();
+-	u32 arg5;
+-	int rval;
+-
+-	switch(op) {
+-	case 0:
+-		rval = sys_msgget((key_t)arg1, (int)arg2);
+-		break;
+-	case 1:
+-		if (!sunos_msqid_get((struct msqid_ds32 __user *)(unsigned long)arg3, &kds)) {
+-			set_fs(KERNEL_DS);
+-			rval = sys_msgctl((int)arg1, (int)arg2,
+-					  (struct msqid_ds __user *)(unsigned long)arg3);
+-			set_fs(old_fs);
+-			if (!rval)
+-				rval = sunos_msqid_put((struct msqid_ds32 __user *)(unsigned long)arg3,
+-						       &kds);
+-		} else
+-			rval = -EFAULT;
+-		break;
+-	case 2:
+-		rval = -EFAULT;
+-		kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
+-						 GFP_KERNEL);
+-		if (!kmbuf)
+-			break;
+-		sp = (struct sparc_stackf32 __user *)
+-			(current_thread_info()->kregs->u_regs[UREG_FP] & 0xffffffffUL);
+-		if (get_user(arg5, &sp->xxargs[0])) {
+-			rval = -EFAULT;
+-			kfree(kmbuf);
+-			break;
+-		}
+-		set_fs(KERNEL_DS);
+-		rval = sys_msgrcv((int)arg1, (struct msgbuf __user *) kmbuf,
+-				  (size_t)arg3,
+-				  (long)arg4, (int)arg5);
+-		set_fs(old_fs);
+-		if (!rval)
+-			rval = sunos_msgbuf_put((struct msgbuf32 __user *)(unsigned long)arg2,
+-						kmbuf, arg3);
+-		kfree(kmbuf);
+-		break;
+-	case 3:
+-		rval = -EFAULT;
+-		kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
+-						 GFP_KERNEL);
+-		if (!kmbuf || sunos_msgbuf_get((struct msgbuf32 __user *)(unsigned long)arg2,
+-					       kmbuf, arg3))
+-			break;
+-		set_fs(KERNEL_DS);
+-		rval = sys_msgsnd((int)arg1, (struct msgbuf __user *) kmbuf,
+-				  (size_t)arg3, (int)arg4);
+-		set_fs(old_fs);
+-		kfree(kmbuf);
+-		break;
+-	default:
+-		rval = -EINVAL;
+-		break;
+-	}
+-	return rval;
+-}
+-
+-struct shmid_ds32 {
+-        struct ipc_perm32       shm_perm;
+-        int                     shm_segsz;
+-        compat_time_t         shm_atime;
+-        compat_time_t         shm_dtime;
+-        compat_time_t         shm_ctime;
+-        compat_ipc_pid_t    shm_cpid; 
+-        compat_ipc_pid_t    shm_lpid; 
+-        unsigned short          shm_nattch;
+-};
+-                                                        
+-static inline int sunos_shmid_get(struct shmid_ds32 __user *user,
+-				  struct shmid_ds *kern)
+-{
+-	if (get_user(kern->shm_perm.key, &user->shm_perm.key)		||
+-	    __get_user(kern->shm_perm.uid, &user->shm_perm.uid)		||
+-	    __get_user(kern->shm_perm.gid, &user->shm_perm.gid)		||
+-	    __get_user(kern->shm_perm.cuid, &user->shm_perm.cuid)	||
+-	    __get_user(kern->shm_perm.cgid, &user->shm_perm.cgid)	||
+-	    __get_user(kern->shm_segsz, &user->shm_segsz)		||
+-	    __get_user(kern->shm_atime, &user->shm_atime)		||
+-	    __get_user(kern->shm_dtime, &user->shm_dtime)		||
+-	    __get_user(kern->shm_ctime, &user->shm_ctime)		||
+-	    __get_user(kern->shm_cpid, &user->shm_cpid)			||
+-	    __get_user(kern->shm_lpid, &user->shm_lpid)			||
+-	    __get_user(kern->shm_nattch, &user->shm_nattch))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-static inline int sunos_shmid_put(struct shmid_ds32 __user *user,
+-				  struct shmid_ds *kern)
+-{
+-	if (put_user(kern->shm_perm.key, &user->shm_perm.key)		||
+-	    __put_user(kern->shm_perm.uid, &user->shm_perm.uid)		||
+-	    __put_user(kern->shm_perm.gid, &user->shm_perm.gid)		||
+-	    __put_user(kern->shm_perm.cuid, &user->shm_perm.cuid)	||
+-	    __put_user(kern->shm_perm.cgid, &user->shm_perm.cgid)	||
+-	    __put_user(kern->shm_segsz, &user->shm_segsz)		||
+-	    __put_user(kern->shm_atime, &user->shm_atime)		||
+-	    __put_user(kern->shm_dtime, &user->shm_dtime)		||
+-	    __put_user(kern->shm_ctime, &user->shm_ctime)		||
+-	    __put_user(kern->shm_cpid, &user->shm_cpid)			||
+-	    __put_user(kern->shm_lpid, &user->shm_lpid)			||
+-	    __put_user(kern->shm_nattch, &user->shm_nattch))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-asmlinkage int sunos_shmsys(int op, u32 arg1, u32 arg2, u32 arg3)
+-{
+-	struct shmid_ds ksds;
+-	unsigned long raddr;
+-	mm_segment_t old_fs = get_fs();
+-	int rval;
+-
+-	switch(op) {
+-	case 0:
+-		/* do_shmat(): attach a shared memory area */
+-		rval = do_shmat((int)arg1,(char __user *)(unsigned long)arg2,(int)arg3,&raddr);
+-		if (!rval)
+-			rval = (int) raddr;
+-		break;
+-	case 1:
+-		/* sys_shmctl(): modify shared memory area attr. */
+-		if (!sunos_shmid_get((struct shmid_ds32 __user *)(unsigned long)arg3, &ksds)) {
+-			set_fs(KERNEL_DS);
+-			rval = sys_shmctl((int) arg1,(int) arg2,
+-					  (struct shmid_ds __user *) &ksds);
+-			set_fs(old_fs);
+-			if (!rval)
+-				rval = sunos_shmid_put((struct shmid_ds32 __user *)(unsigned long)arg3,
+-						       &ksds);
+-		} else
+-			rval = -EFAULT;
+-		break;
+-	case 2:
+-		/* sys_shmdt(): detach a shared memory area */
+-		rval = sys_shmdt((char __user *)(unsigned long)arg1);
+-		break;
+-	case 3:
+-		/* sys_shmget(): get a shared memory area */
+-		rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3);
+-		break;
+-	default:
+-		rval = -EINVAL;
+-		break;
+-	};
+-	return rval;
+-}
+-
+-extern asmlinkage long sparc32_open(const char __user * filename, int flags, int mode);
+-
+-asmlinkage int sunos_open(u32 fname, int flags, int mode)
+-{
+-	const char __user *filename = compat_ptr(fname);
+-
+-	return sparc32_open(filename, flags, mode);
+-}
+-
+-#define SUNOS_EWOULDBLOCK 35
+-
+-/* see the sunos man page read(2v) for an explanation
+-   of this garbage. We use O_NDELAY to mark
+-   file descriptors that have been set non-blocking 
+-   using 4.2BSD style calls. (tridge) */
+-
+-static inline int check_nonblock(int ret, int fd)
+-{
+-	if (ret == -EAGAIN) {
+-		struct file * file = fget(fd);
+-		if (file) {
+-			if (file->f_flags & O_NDELAY)
+-				ret = -SUNOS_EWOULDBLOCK;
+-			fput(file);
+-		}
+-	}
+-	return ret;
+-}
+-
+-asmlinkage int sunos_read(unsigned int fd, char __user *buf, u32 count)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(sys_read(fd, buf, count), fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_readv(u32 fd, void __user *vector, s32 count)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(compat_sys_readv(fd, vector, count), fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_write(unsigned int fd, char __user *buf, u32 count)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(sys_write(fd, buf, count), fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_writev(u32 fd, void __user *vector, s32 count)
+-{
+-	int ret;
+-
+-	ret = check_nonblock(compat_sys_writev(fd, vector, count), fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_recv(u32 __fd, void __user *ubuf, int size, unsigned flags)
+-{
+-	int ret, fd = (int) __fd;
+-
+-	ret = check_nonblock(sys_recv(fd, ubuf, size, flags), fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_send(u32 __fd, void __user *buff, int len, unsigned flags)
+-{
+-	int ret, fd = (int) __fd;
+-
+-	ret = check_nonblock(sys_send(fd, buff, len, flags), fd);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_accept(u32 __fd, struct sockaddr __user *sa, int __user *addrlen)
+-{
+-	int ret, fd = (int) __fd;
+-
+-	while (1) {
+-		ret = check_nonblock(sys_accept(fd, sa, addrlen), fd);
+-		if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
+-			break;
+-	}
+-	return ret;
+-}
+-
+-#define SUNOS_SV_INTERRUPT 2
+-
+-asmlinkage int sunos_sigaction (int sig,
+-				struct old_sigaction32 __user *act,
+-				struct old_sigaction32 __user *oact)
+-{
+-	struct k_sigaction new_ka, old_ka;
+-	int ret;
+-
+-	if (act) {
+-		compat_old_sigset_t mask;
+-		u32 u_handler;
+-
+-		if (get_user(u_handler, &act->sa_handler) ||
+-		    __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+-			return -EFAULT;
+-		new_ka.sa.sa_handler = compat_ptr(u_handler);
+-		__get_user(mask, &act->sa_mask);
+-		new_ka.sa.sa_restorer = NULL;
+-		new_ka.ka_restorer = NULL;
+-		siginitset(&new_ka.sa.sa_mask, mask);
+-		new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
+-	}
+-
+-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+-
+-	if (!ret && oact) {
+-		old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
+-		if (put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) ||
+-		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+-			return -EFAULT;
+-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+-	}
+-
+-	return ret;
+-}
+-
+-asmlinkage int sunos_setsockopt(u32 __fd, u32 __level, u32 __optname,
+-				char __user *optval, u32 __optlen)
+-{
+-	int fd = (int) __fd;
+-	int level = (int) __level;
+-	int optname = (int) __optname;
+-	int optlen = (int) __optlen;
+-	int tr_opt = optname;
+-	int ret;
+-
+-	if (level == SOL_IP) {
+-		/* Multicast socketopts (ttl, membership) */
+-		if (tr_opt >=2 && tr_opt <= 6)
+-			tr_opt += 30;
+-	}
+-	ret = sys_setsockopt(fd, level, tr_opt,
+-			     optval, optlen);
+-	return ret;
+-}
+-
+-asmlinkage int sunos_getsockopt(u32 __fd, u32 __level, u32 __optname,
+-				char __user *optval, int __user *optlen)
+-{
+-	int fd = (int) __fd;
+-	int level = (int) __level;
+-	int optname = (int) __optname;
+-	int tr_opt = optname;
+-	int ret;
+-
+-	if (level == SOL_IP) {
+-		/* Multicast socketopts (ttl, membership) */
+-		if (tr_opt >=2 && tr_opt <= 6)
+-			tr_opt += 30;
+-	}
+-	ret = compat_sys_getsockopt(fd, level, tr_opt,
+-				    optval, optlen);
+-	return ret;
+-}
+diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
+index 52816c7..e885034 100644
+--- a/arch/sparc64/kernel/sysfs.c
++++ b/arch/sparc64/kernel/sysfs.c
+@@ -273,10 +273,22 @@ static void __init check_mmu_stats(void)
+ 		mmu_stats_supported = 1;
+ }
+ 
++static void register_nodes(void)
++{
++#ifdef CONFIG_NUMA
++	int i;
++
++	for (i = 0; i < MAX_NUMNODES; i++)
++		register_one_node(i);
++#endif
++}
++
+ static int __init topology_init(void)
+ {
+ 	int cpu;
+ 
++	register_nodes();
++
+ 	check_mmu_stats();
+ 
+ 	register_cpu_notifier(&sysfs_cpu_nb);
+diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
+index 6b9b718..a4fef2b 100644
+--- a/arch/sparc64/kernel/systbls.S
++++ b/arch/sparc64/kernel/systbls.S
+@@ -155,125 +155,3 @@ sys_call_table:
+ 	.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
+ /*310*/	.word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
+ 	.word sys_timerfd_settime, sys_timerfd_gettime
+-
+-#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
+-    defined(CONFIG_SOLARIS_EMUL_MODULE)
+-	/* Now the 32-bit SunOS syscall table. */
+-
+-	.align 4
+-	.globl sunos_sys_table
+-sunos_sys_table:
+-/*0*/	.word sunos_indir, sys32_exit, sys_fork
+-	.word sunos_read, sunos_write, sunos_open
+-	.word sys_close, sunos_wait4, sys_creat
+-	.word sys_link, sys_unlink, sunos_execv
+-	.word sys_chdir, sunos_nosys, sys32_mknod
+-	.word sys_chmod, sys32_lchown16, sunos_brk
+-	.word sunos_nosys, sys32_lseek, sunos_getpid
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_getuid, sunos_nosys, sys_ptrace
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sys_access, sunos_nosys, sunos_nosys
+-	.word sys_sync, sys_kill, compat_sys_newstat
+-	.word sunos_nosys, compat_sys_newlstat, sys_dup
+-	.word sys_pipe, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_getgid
+-	.word sunos_nosys, sunos_nosys
+-/*50*/	.word sunos_nosys, sys_acct, sunos_nosys
+-	.word sunos_mctl, sunos_ioctl, sys_reboot
+-	.word sunos_nosys, sys_symlink, sys_readlink
+-	.word sys32_execve, sys_umask, sys_chroot
+-	.word compat_sys_newfstat, sunos_nosys, sys_getpagesize
+-	.word sys_msync, sys_vfork, sunos_nosys
+-	.word sunos_nosys, sunos_sbrk, sunos_sstk
+-	.word sunos_mmap, sunos_vadvise, sys_munmap
+-	.word sys_mprotect, sys_madvise, sys_vhangup
+-	.word sunos_nosys, sys_mincore, sys32_getgroups16
+-	.word sys32_setgroups16, sys_getpgrp, sunos_setpgrp
+-	.word compat_sys_setitimer, sunos_nosys, sys_swapon
+-	.word compat_sys_getitimer, sys_gethostname, sys_sethostname
+-	.word sunos_getdtablesize, sys_dup2, sunos_nop
+-	.word compat_sys_fcntl, sunos_select, sunos_nop
+-	.word sys_fsync, sys32_setpriority, sys32_socket
+-	.word sys32_connect, sunos_accept
+-/*100*/	.word sys_getpriority, sunos_send, sunos_recv
+-	.word sunos_nosys, sys32_bind, sunos_setsockopt
+-	.word sys32_listen, sunos_nosys, sunos_sigaction
+-	.word sunos_sigblock, sunos_sigsetmask, sys_sigpause
+-	.word sys32_sigstack, sys32_recvmsg, sys32_sendmsg
+-	.word sunos_nosys, sys32_gettimeofday, compat_sys_getrusage
+-	.word sunos_getsockopt, sunos_nosys, sunos_readv
+-	.word sunos_writev, sys32_settimeofday, sys32_fchown16
+-	.word sys_fchmod, sys32_recvfrom, sys32_setreuid16
+-	.word sys32_setregid16, sys_rename, sys_truncate
+-	.word sys_ftruncate, sys_flock, sunos_nosys
+-	.word sys32_sendto, sys32_shutdown, sys32_socketpair
+-	.word sys_mkdir, sys_rmdir, sys32_utimes
+-	.word sys32_sigreturn, sunos_nosys, sys32_getpeername
+-	.word sunos_gethostid, sunos_nosys, compat_sys_getrlimit
+-	.word compat_sys_setrlimit, sunos_killpg, sunos_nosys
+-	.word sunos_nosys, sunos_nosys
+-/*150*/	.word sys32_getsockname, sunos_nosys, sunos_nosys
+-	.word sys_poll, sunos_nosys, sunos_nosys
+-	.word sunos_getdirentries, compat_sys_statfs, compat_sys_fstatfs
+-	.word sys_oldumount, sunos_nosys, sunos_nosys
+-	.word sys_getdomainname, sys_setdomainname
+-	.word sunos_nosys, sys_quotactl, sunos_nosys
+-	.word sunos_nosys, sys_ustat, sunos_semsys
+-	.word sunos_nosys, sunos_shmsys, sunos_audit
+-	.word sunos_nosys, sunos_getdents, sys_setsid
+-	.word sys_fchdir, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, compat_sys_sigpending, sunos_nosys
+-	.word sys_setpgid, sunos_pathconf, sunos_fpathconf
+-	.word sunos_sysconf, sunos_uname, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-/*200*/	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys
+-/*250*/	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys
+-/*260*/	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys
+-/*270*/	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys
+-/*280*/	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys
+-/*290*/	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys
+-/*300*/	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys
+-/*310*/	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys, sunos_nosys, sunos_nosys
+-	.word sunos_nosys
+-
+-#endif
+diff --git a/arch/sparc64/kernel/systbls.h b/arch/sparc64/kernel/systbls.h
+index 8a0d20a..bc9f5da 100644
+--- a/arch/sparc64/kernel/systbls.h
++++ b/arch/sparc64/kernel/systbls.h
+@@ -27,8 +27,6 @@ extern asmlinkage unsigned long sys64_mremap(unsigned long addr,
+ 					     unsigned long new_addr);
+ extern asmlinkage unsigned long c_sys_nis_syscall(struct pt_regs *regs);
+ extern asmlinkage long sys_getdomainname(char __user *name, int len);
+-extern asmlinkage long solaris_syscall(struct pt_regs *regs);
+-extern asmlinkage long sunos_syscall(struct pt_regs *regs);
+ extern asmlinkage long sys_utrap_install(utrap_entry_t type,
+ 					 utrap_handler_t new_p,
+ 					 utrap_handler_t new_d,
+diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
+index 96da847..d9b8d46 100644
+--- a/arch/sparc64/kernel/traps.c
++++ b/arch/sparc64/kernel/traps.c
+@@ -2091,9 +2091,8 @@ static void user_instruction_dump(unsigned int __user *pc)
+ 
+ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
+ {
+-	unsigned long pc, fp, thread_base, ksp;
++	unsigned long fp, thread_base, ksp;
+ 	struct thread_info *tp;
+-	struct reg_window *rw;
+ 	int count = 0;
+ 
+ 	ksp = (unsigned long) _ksp;
+@@ -2117,15 +2116,27 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
+ 	printk("\n");
+ #endif
+ 	do {
++		struct reg_window *rw;
++		struct pt_regs *regs;
++		unsigned long pc;
++
+ 		/* Bogus frame pointer? */
+ 		if (fp < (thread_base + sizeof(struct thread_info)) ||
+ 		    fp >= (thread_base + THREAD_SIZE))
+ 			break;
+ 		rw = (struct reg_window *)fp;
+-		pc = rw->ins[7];
++		regs = (struct pt_regs *) (rw + 1);
++
++		if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
++			pc = regs->tpc;
++			fp = regs->u_regs[UREG_I6] + STACK_BIAS;
++		} else {
++			pc = rw->ins[7];
++			fp = rw->ins[6] + STACK_BIAS;
++		}
++
+ 		printk(" [%016lx] ", pc);
+ 		print_symbol("%s\n", pc);
+-		fp = rw->ins[6] + STACK_BIAS;
+ 	} while (++count < 16);
+ #ifndef CONFIG_KALLSYMS
+ 	printk("\n");
+diff --git a/arch/sparc64/kernel/tsb.S b/arch/sparc64/kernel/tsb.S
+index 10adb2f..c499214 100644
+--- a/arch/sparc64/kernel/tsb.S
++++ b/arch/sparc64/kernel/tsb.S
+@@ -275,7 +275,7 @@ sparc64_realfault_common:
+ 	stx	%l5, [%g6 + TI_FAULT_ADDR]	! Save fault address
+ 	call	do_sparc64_fault		! Call fault handler
+ 	 add	%sp, PTREGS_OFF, %o0		! Compute pt_regs arg
+-	ba,pt	%xcc, rtrap_clr_l6		! Restore cpu state
++	ba,pt	%xcc, rtrap			! Restore cpu state
+ 	 nop					! Delay slot (fill me)
+ 
+ winfix_trampoline:
+diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
+index 7575aa3..b0de4c0 100644
+--- a/arch/sparc64/kernel/ttable.S
++++ b/arch/sparc64/kernel/ttable.S
+@@ -117,16 +117,13 @@ tl0_f4o:	FILL_4_OTHER
+ tl0_f5o:	FILL_5_OTHER
+ tl0_f6o:	FILL_6_OTHER
+ tl0_f7o:	FILL_7_OTHER
+-tl0_sunos:	SUNOS_SYSCALL_TRAP
++tl0_resv100:	BTRAP(0x100)
+ tl0_bkpt:	BREAKPOINT_TRAP
+ tl0_divz:	TRAP(do_div0)
+ tl0_flushw:	FLUSH_WINDOW_TRAP
+-tl0_resv104:	BTRAP(0x104) BTRAP(0x105) BTRAP(0x106) BTRAP(0x107)
+-		.globl tl0_solaris
+-tl0_solaris:	SOLARIS_SYSCALL_TRAP
+-tl0_resv109:	BTRAP(0x109)
+-tl0_resv10a:	BTRAP(0x10a) BTRAP(0x10b) BTRAP(0x10c) BTRAP(0x10d) BTRAP(0x10e)
+-tl0_resv10f:	BTRAP(0x10f)
++tl0_resv104:	BTRAP(0x104) BTRAP(0x105) BTRAP(0x106) BTRAP(0x107) BTRAP(0x108)
++tl0_resv109:	BTRAP(0x109) BTRAP(0x10a) BTRAP(0x10b) BTRAP(0x10c) BTRAP(0x10d)
++tl0_resv10e:	BTRAP(0x10e) BTRAP(0x10f)
+ tl0_linux32:	LINUX_32BIT_SYSCALL_TRAP
+ tl0_oldlinux64:	LINUX_64BIT_SYSCALL_TRAP
+ tl0_resv112:	TRAP_UTRAP(UT_TRAP_INSTRUCTION_18,0x112) TRAP_UTRAP(UT_TRAP_INSTRUCTION_19,0x113)
+@@ -139,8 +136,7 @@ tl0_resv11e:	TRAP_UTRAP(UT_TRAP_INSTRUCTION_30,0x11e) TRAP_UTRAP(UT_TRAP_INSTRUC
+ tl0_getcc:	GETCC_TRAP
+ tl0_setcc:	SETCC_TRAP
+ tl0_getpsr:	TRAP(do_getpsr)
+-tl0_resv123:	BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126)
+-tl0_solindir:	INDIRECT_SOLARIS_SYSCALL(156)
++tl0_resv123:	BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) BTRAP(0x127)
+ tl0_resv128:	BTRAP(0x128) BTRAP(0x129) BTRAP(0x12a) BTRAP(0x12b) BTRAP(0x12c)
+ tl0_resv12d:	BTRAP(0x12d) BTRAP(0x12e) BTRAP(0x12f) BTRAP(0x130) BTRAP(0x131)
+ tl0_resv132:	BTRAP(0x132) BTRAP(0x133) BTRAP(0x134) BTRAP(0x135) BTRAP(0x136)
+diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
+index c4aa110..a6b0863 100644
+--- a/arch/sparc64/kernel/winfixup.S
++++ b/arch/sparc64/kernel/winfixup.S
+@@ -32,7 +32,7 @@ fill_fixup:
+ 	 rd	%pc, %g7
+ 	call	do_sparc64_fault
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,pt	%xcc, rtrap_clr_l6
++	ba,pt	%xcc, rtrap
+ 	 nop
+ 
+ 	/* Be very careful about usage of the trap globals here.
+@@ -100,7 +100,7 @@ spill_fixup_dax:
+ 	 rd	%pc, %g7
+ 	call	do_sparc64_fault
+ 	 add	%sp, PTREGS_OFF, %o0
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ winfix_mna:
+ 	andn	%g3, 0x7f, %g3
+@@ -122,12 +122,12 @@ fill_fixup_mna:
+ 	mov	%l4, %o2
+ 	call	sun4v_do_mna
+ 	 mov	%l5, %o1
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 1:	mov	%l4, %o1
+ 	mov	%l5, %o2
+ 	call	mem_address_unaligned
+ 	 nop
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ winfix_dax:
+ 	andn	%g3, 0x7f, %g3
+@@ -150,7 +150,7 @@ fill_fixup_dax:
+ 	 add	%sp, PTREGS_OFF, %o0
+ 	call	sun4v_data_access_exception
+ 	 nop
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 1:	call	spitfire_data_access_exception
+ 	 nop
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
+index f37078d..177d8aa 100644
+--- a/arch/sparc64/mm/init.c
++++ b/arch/sparc64/mm/init.c
+@@ -24,6 +24,8 @@
+ #include <linux/cache.h>
+ #include <linux/sort.h>
+ #include <linux/percpu.h>
++#include <linux/lmb.h>
++#include <linux/mmzone.h>
+ 
+ #include <asm/head.h>
+ #include <asm/system.h>
+@@ -72,9 +74,7 @@ extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
+ #define MAX_BANKS	32
+ 
+ static struct linux_prom64_registers pavail[MAX_BANKS] __initdata;
+-static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
+ static int pavail_ents __initdata;
+-static int pavail_rescan_ents __initdata;
+ 
+ static int cmp_p64(const void *a, const void *b)
+ {
+@@ -715,285 +715,684 @@ out:
+ 		smp_new_mmu_context_version();
+ }
+ 
+-/* Find a free area for the bootmem map, avoiding the kernel image
+- * and the initial ramdisk.
+- */
+-static unsigned long __init choose_bootmap_pfn(unsigned long start_pfn,
+-					       unsigned long end_pfn)
++static int numa_enabled = 1;
++static int numa_debug;
++
++static int __init early_numa(char *p)
+ {
+-	unsigned long avoid_start, avoid_end, bootmap_size;
+-	int i;
++	if (!p)
++		return 0;
++
++	if (strstr(p, "off"))
++		numa_enabled = 0;
++
++	if (strstr(p, "debug"))
++		numa_debug = 1;
++
++	return 0;
++}
++early_param("numa", early_numa);
+ 
+-	bootmap_size = bootmem_bootmap_pages(end_pfn - start_pfn);
+-	bootmap_size <<= PAGE_SHIFT;
++#define numadbg(f, a...) \
++do {	if (numa_debug) \
++		printk(KERN_INFO f, ## a); \
++} while (0)
+ 
+-	avoid_start = avoid_end = 0;
++static void __init find_ramdisk(unsigned long phys_base)
++{
+ #ifdef CONFIG_BLK_DEV_INITRD
+-	avoid_start = initrd_start;
+-	avoid_end = PAGE_ALIGN(initrd_end);
++	if (sparc_ramdisk_image || sparc_ramdisk_image64) {
++		unsigned long ramdisk_image;
++
++		/* Older versions of the bootloader only supported a
++		 * 32-bit physical address for the ramdisk image
++		 * location, stored at sparc_ramdisk_image.  Newer
++		 * SILO versions set sparc_ramdisk_image to zero and
++		 * provide a full 64-bit physical address at
++		 * sparc_ramdisk_image64.
++		 */
++		ramdisk_image = sparc_ramdisk_image;
++		if (!ramdisk_image)
++			ramdisk_image = sparc_ramdisk_image64;
++
++		/* Another bootloader quirk.  The bootloader normalizes
++		 * the physical address to KERNBASE, so we have to
++		 * factor that back out and add in the lowest valid
++		 * physical page address to get the true physical address.
++		 */
++		ramdisk_image -= KERNBASE;
++		ramdisk_image += phys_base;
++
++		numadbg("Found ramdisk at physical address 0x%lx, size %u\n",
++			ramdisk_image, sparc_ramdisk_size);
++
++		initrd_start = ramdisk_image;
++		initrd_end = ramdisk_image + sparc_ramdisk_size;
++
++		lmb_reserve(initrd_start, initrd_end);
++	}
+ #endif
++}
+ 
+-	for (i = 0; i < pavail_ents; i++) {
+-		unsigned long start, end;
++struct node_mem_mask {
++	unsigned long mask;
++	unsigned long val;
++	unsigned long bootmem_paddr;
++};
++static struct node_mem_mask node_masks[MAX_NUMNODES];
++static int num_node_masks;
+ 
+-		start = pavail[i].phys_addr;
+-		end = start + pavail[i].reg_size;
++int numa_cpu_lookup_table[NR_CPUS];
++cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
+ 
+-		while (start < end) {
+-			if (start >= kern_base &&
+-			    start < PAGE_ALIGN(kern_base + kern_size)) {
+-				start = PAGE_ALIGN(kern_base + kern_size);
+-				continue;
+-			}
+-			if (start >= avoid_start && start < avoid_end) {
+-				start = avoid_end;
+-				continue;
+-			}
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+ 
+-			if ((end - start) < bootmap_size)
+-				break;
++struct mdesc_mblock {
++	u64	base;
++	u64	size;
++	u64	offset; /* RA-to-PA */
++};
++static struct mdesc_mblock *mblocks;
++static int num_mblocks;
+ 
+-			if (start < kern_base &&
+-			    (start + bootmap_size) > kern_base) {
+-				start = PAGE_ALIGN(kern_base + kern_size);
+-				continue;
+-			}
++static unsigned long ra_to_pa(unsigned long addr)
++{
++	int i;
+ 
+-			if (start < avoid_start &&
+-			    (start + bootmap_size) > avoid_start) {
+-				start = avoid_end;
+-				continue;
+-			}
++	for (i = 0; i < num_mblocks; i++) {
++		struct mdesc_mblock *m = &mblocks[i];
+ 
+-			/* OK, it doesn't overlap anything, use it.  */
+-			return start >> PAGE_SHIFT;
++		if (addr >= m->base &&
++		    addr < (m->base + m->size)) {
++			addr += m->offset;
++			break;
+ 		}
+ 	}
+-
+-	prom_printf("Cannot find free area for bootmap, aborting.\n");
+-	prom_halt();
++	return addr;
+ }
+ 
+-static void __init trim_pavail(unsigned long *cur_size_p,
+-			       unsigned long *end_of_phys_p)
++static int find_node(unsigned long addr)
+ {
+-	unsigned long to_trim = *cur_size_p - cmdline_memory_size;
+-	unsigned long avoid_start, avoid_end;
+ 	int i;
+ 
+-	to_trim = PAGE_ALIGN(to_trim);
++	addr = ra_to_pa(addr);
++	for (i = 0; i < num_node_masks; i++) {
++		struct node_mem_mask *p = &node_masks[i];
+ 
+-	avoid_start = avoid_end = 0;
+-#ifdef CONFIG_BLK_DEV_INITRD
+-	avoid_start = initrd_start;
+-	avoid_end = PAGE_ALIGN(initrd_end);
++		if ((addr & p->mask) == p->val)
++			return i;
++	}
++	return -1;
++}
++
++static unsigned long nid_range(unsigned long start, unsigned long end,
++			       int *nid)
++{
++	*nid = find_node(start);
++	start += PAGE_SIZE;
++	while (start < end) {
++		int n = find_node(start);
++
++		if (n != *nid)
++			break;
++		start += PAGE_SIZE;
++	}
++
++	return start;
++}
++#else
++static unsigned long nid_range(unsigned long start, unsigned long end,
++			       int *nid)
++{
++	*nid = 0;
++	return end;
++}
+ #endif
+ 
+-	/* Trim some pavail[] entries in order to satisfy the
+-	 * requested "mem=xxx" kernel command line specification.
+-	 *
+-	 * We must not trim off the kernel image area nor the
+-	 * initial ramdisk range (if any).  Also, we must not trim
+-	 * any pavail[] entry down to zero in order to preserve
+-	 * the invariant that all pavail[] entries have a non-zero
+-	 * size which is assumed by all of the code in here.
+-	 */
+-	for (i = 0; i < pavail_ents; i++) {
+-		unsigned long start, end, kern_end;
+-		unsigned long trim_low, trim_high, n;
++/* This must be invoked after performing all of the necessary
++ * add_active_range() calls for 'nid'.  We need to be able to get
++ * correct data from get_pfn_range_for_nid().
++ */
++static void __init allocate_node_data(int nid)
++{
++	unsigned long paddr, num_pages, start_pfn, end_pfn;
++	struct pglist_data *p;
++
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++	paddr = lmb_alloc_nid(sizeof(struct pglist_data),
++			      SMP_CACHE_BYTES, nid, nid_range);
++	if (!paddr) {
++		prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid);
++		prom_halt();
++	}
++	NODE_DATA(nid) = __va(paddr);
++	memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+ 
+-		kern_end = PAGE_ALIGN(kern_base + kern_size);
++	NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
++#endif
+ 
+-		trim_low = start = pavail[i].phys_addr;
+-		trim_high = end = start + pavail[i].reg_size;
++	p = NODE_DATA(nid);
+ 
+-		if (kern_base >= start &&
+-		    kern_base < end) {
+-			trim_low = kern_base;
+-			if (kern_end >= end)
+-				continue;
+-		}
+-		if (kern_end >= start &&
+-		    kern_end < end) {
+-			trim_high = kern_end;
+-		}
+-		if (avoid_start &&
+-		    avoid_start >= start &&
+-		    avoid_start < end) {
+-			if (trim_low > avoid_start)
+-				trim_low = avoid_start;
+-			if (avoid_end >= end)
+-				continue;
+-		}
+-		if (avoid_end &&
+-		    avoid_end >= start &&
+-		    avoid_end < end) {
+-			if (trim_high < avoid_end)
+-				trim_high = avoid_end;
++	get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
++	p->node_start_pfn = start_pfn;
++	p->node_spanned_pages = end_pfn - start_pfn;
++
++	if (p->node_spanned_pages) {
++		num_pages = bootmem_bootmap_pages(p->node_spanned_pages);
++
++		paddr = lmb_alloc_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid,
++				      nid_range);
++		if (!paddr) {
++			prom_printf("Cannot allocate bootmap for nid[%d]\n",
++				  nid);
++			prom_halt();
+ 		}
++		node_masks[nid].bootmem_paddr = paddr;
++	}
++}
++
++static void init_node_masks_nonnuma(void)
++{
++	int i;
++
++	numadbg("Initializing tables for non-numa.\n");
++
++	node_masks[0].mask = node_masks[0].val = 0;
++	num_node_masks = 1;
++
++	for (i = 0; i < NR_CPUS; i++)
++		numa_cpu_lookup_table[i] = 0;
++
++	numa_cpumask_lookup_table[0] = CPU_MASK_ALL;
++}
++
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++struct pglist_data *node_data[MAX_NUMNODES];
++
++EXPORT_SYMBOL(numa_cpu_lookup_table);
++EXPORT_SYMBOL(numa_cpumask_lookup_table);
++EXPORT_SYMBOL(node_data);
++
++struct mdesc_mlgroup {
++	u64	node;
++	u64	latency;
++	u64	match;
++	u64	mask;
++};
++static struct mdesc_mlgroup *mlgroups;
++static int num_mlgroups;
++
++static int scan_pio_for_cfg_handle(struct mdesc_handle *md, u64 pio,
++				   u32 cfg_handle)
++{
++	u64 arc;
+ 
+-		if (trim_high <= trim_low)
++	mdesc_for_each_arc(arc, md, pio, MDESC_ARC_TYPE_FWD) {
++		u64 target = mdesc_arc_target(md, arc);
++		const u64 *val;
++
++		val = mdesc_get_property(md, target,
++					 "cfg-handle", NULL);
++		if (val && *val == cfg_handle)
++			return 0;
++	}
++	return -ENODEV;
++}
++
++static int scan_arcs_for_cfg_handle(struct mdesc_handle *md, u64 grp,
++				    u32 cfg_handle)
++{
++	u64 arc, candidate, best_latency = ~(u64)0;
++
++	candidate = MDESC_NODE_NULL;
++	mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_FWD) {
++		u64 target = mdesc_arc_target(md, arc);
++		const char *name = mdesc_node_name(md, target);
++		const u64 *val;
++
++		if (strcmp(name, "pio-latency-group"))
+ 			continue;
+ 
+-		if (trim_low == start && trim_high == end) {
+-			/* Whole chunk is available for trimming.
+-			 * Trim all except one page, in order to keep
+-			 * entry non-empty.
+-			 */
+-			n = (end - start) - PAGE_SIZE;
+-			if (n > to_trim)
+-				n = to_trim;
+-
+-			if (n) {
+-				pavail[i].phys_addr += n;
+-				pavail[i].reg_size -= n;
+-				to_trim -= n;
+-			}
+-		} else {
+-			n = (trim_low - start);
+-			if (n > to_trim)
+-				n = to_trim;
+-
+-			if (n) {
+-				pavail[i].phys_addr += n;
+-				pavail[i].reg_size -= n;
+-				to_trim -= n;
+-			}
+-			if (to_trim) {
+-				n = end - trim_high;
+-				if (n > to_trim)
+-					n = to_trim;
+-				if (n) {
+-					pavail[i].reg_size -= n;
+-					to_trim -= n;
+-				}
+-			}
++		val = mdesc_get_property(md, target, "latency", NULL);
++		if (!val)
++			continue;
++
++		if (*val < best_latency) {
++			candidate = target;
++			best_latency = *val;
+ 		}
++	}
++
++	if (candidate == MDESC_NODE_NULL)
++		return -ENODEV;
++
++	return scan_pio_for_cfg_handle(md, candidate, cfg_handle);
++}
++
++int of_node_to_nid(struct device_node *dp)
++{
++	const struct linux_prom64_registers *regs;
++	struct mdesc_handle *md;
++	u32 cfg_handle;
++	int count, nid;
++	u64 grp;
+ 
+-		if (!to_trim)
++	if (!mlgroups)
++		return -1;
++
++	regs = of_get_property(dp, "reg", NULL);
++	if (!regs)
++		return -1;
++
++	cfg_handle = (regs->phys_addr >> 32UL) & 0x0fffffff;
++
++	md = mdesc_grab();
++
++	count = 0;
++	nid = -1;
++	mdesc_for_each_node_by_name(md, grp, "group") {
++		if (!scan_arcs_for_cfg_handle(md, grp, cfg_handle)) {
++			nid = count;
+ 			break;
++		}
++		count++;
+ 	}
+ 
+-	/* Recalculate.  */
+-	*cur_size_p = 0UL;
+-	for (i = 0; i < pavail_ents; i++) {
+-		*end_of_phys_p = pavail[i].phys_addr +
+-			pavail[i].reg_size;
+-		*cur_size_p += pavail[i].reg_size;
+-	}
++	mdesc_release(md);
++
++	return nid;
+ }
+ 
+-/* About pages_avail, this is the value we will use to calculate
+- * the zholes_size[] argument given to free_area_init_node().  The
+- * page allocator uses this to calculate nr_kernel_pages,
+- * nr_all_pages and zone->present_pages.  On NUMA it is used
+- * to calculate zone->min_unmapped_pages and zone->min_slab_pages.
+- *
+- * So this number should really be set to what the page allocator
+- * actually ends up with.  This means:
+- * 1) It should include bootmem map pages, we'll release those.
+- * 2) It should not include the kernel image, except for the
+- *    __init sections which we will also release.
+- * 3) It should include the initrd image, since we'll release
+- *    that too.
+- */
+-static unsigned long __init bootmem_init(unsigned long *pages_avail,
+-					 unsigned long phys_base)
++static void add_node_ranges(void)
+ {
+-	unsigned long bootmap_size, end_pfn;
+-	unsigned long end_of_phys_memory = 0UL;
+-	unsigned long bootmap_pfn, bytes_avail, size;
+ 	int i;
+ 
+-	bytes_avail = 0UL;
+-	for (i = 0; i < pavail_ents; i++) {
+-		end_of_phys_memory = pavail[i].phys_addr +
+-			pavail[i].reg_size;
+-		bytes_avail += pavail[i].reg_size;
++	for (i = 0; i < lmb.memory.cnt; i++) {
++		unsigned long size = lmb_size_bytes(&lmb.memory, i);
++		unsigned long start, end;
++
++		start = lmb.memory.region[i].base;
++		end = start + size;
++		while (start < end) {
++			unsigned long this_end;
++			int nid;
++
++			this_end = nid_range(start, end, &nid);
++
++			numadbg("Adding active range nid[%d] "
++				"start[%lx] end[%lx]\n",
++				nid, start, this_end);
++
++			add_active_range(nid,
++					 start >> PAGE_SHIFT,
++					 this_end >> PAGE_SHIFT);
++
++			start = this_end;
++		}
+ 	}
++}
+ 
+-	/* Determine the location of the initial ramdisk before trying
+-	 * to honor the "mem=xxx" command line argument.  We must know
+-	 * where the kernel image and the ramdisk image are so that we
+-	 * do not trim those two areas from the physical memory map.
+-	 */
++static int __init grab_mlgroups(struct mdesc_handle *md)
++{
++	unsigned long paddr;
++	int count = 0;
++	u64 node;
++
++	mdesc_for_each_node_by_name(md, node, "memory-latency-group")
++		count++;
++	if (!count)
++		return -ENOENT;
++
++	paddr = lmb_alloc(count * sizeof(struct mdesc_mlgroup),
++			  SMP_CACHE_BYTES);
++	if (!paddr)
++		return -ENOMEM;
++
++	mlgroups = __va(paddr);
++	num_mlgroups = count;
++
++	count = 0;
++	mdesc_for_each_node_by_name(md, node, "memory-latency-group") {
++		struct mdesc_mlgroup *m = &mlgroups[count++];
++		const u64 *val;
++
++		m->node = node;
++
++		val = mdesc_get_property(md, node, "latency", NULL);
++		m->latency = *val;
++		val = mdesc_get_property(md, node, "address-match", NULL);
++		m->match = *val;
++		val = mdesc_get_property(md, node, "address-mask", NULL);
++		m->mask = *val;
++
++		numadbg("MLGROUP[%d]: node[%lx] latency[%lx] "
++			"match[%lx] mask[%lx]\n",
++			count - 1, m->node, m->latency, m->match, m->mask);
++	}
+ 
+-#ifdef CONFIG_BLK_DEV_INITRD
+-	/* Now have to check initial ramdisk, so that bootmap does not overwrite it */
+-	if (sparc_ramdisk_image || sparc_ramdisk_image64) {
+-		unsigned long ramdisk_image = sparc_ramdisk_image ?
+-			sparc_ramdisk_image : sparc_ramdisk_image64;
+-		ramdisk_image -= KERNBASE;
+-		initrd_start = ramdisk_image + phys_base;
+-		initrd_end = initrd_start + sparc_ramdisk_size;
+-		if (initrd_end > end_of_phys_memory) {
+-			printk(KERN_CRIT "initrd extends beyond end of memory "
+-		                 	 "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
+-			       initrd_end, end_of_phys_memory);
+-			initrd_start = 0;
+-			initrd_end = 0;
++	return 0;
++}
++
++static int __init grab_mblocks(struct mdesc_handle *md)
++{
++	unsigned long paddr;
++	int count = 0;
++	u64 node;
++
++	mdesc_for_each_node_by_name(md, node, "mblock")
++		count++;
++	if (!count)
++		return -ENOENT;
++
++	paddr = lmb_alloc(count * sizeof(struct mdesc_mblock),
++			  SMP_CACHE_BYTES);
++	if (!paddr)
++		return -ENOMEM;
++
++	mblocks = __va(paddr);
++	num_mblocks = count;
++
++	count = 0;
++	mdesc_for_each_node_by_name(md, node, "mblock") {
++		struct mdesc_mblock *m = &mblocks[count++];
++		const u64 *val;
++
++		val = mdesc_get_property(md, node, "base", NULL);
++		m->base = *val;
++		val = mdesc_get_property(md, node, "size", NULL);
++		m->size = *val;
++		val = mdesc_get_property(md, node,
++					 "address-congruence-offset", NULL);
++		m->offset = *val;
++
++		numadbg("MBLOCK[%d]: base[%lx] size[%lx] offset[%lx]\n",
++			count - 1, m->base, m->size, m->offset);
++	}
++
++	return 0;
++}
++
++static void __init numa_parse_mdesc_group_cpus(struct mdesc_handle *md,
++					       u64 grp, cpumask_t *mask)
++{
++	u64 arc;
++
++	cpus_clear(*mask);
++
++	mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_BACK) {
++		u64 target = mdesc_arc_target(md, arc);
++		const char *name = mdesc_node_name(md, target);
++		const u64 *id;
++
++		if (strcmp(name, "cpu"))
++			continue;
++		id = mdesc_get_property(md, target, "id", NULL);
++		if (*id < NR_CPUS)
++			cpu_set(*id, *mask);
++	}
++}
++
++static struct mdesc_mlgroup * __init find_mlgroup(u64 node)
++{
++	int i;
++
++	for (i = 0; i < num_mlgroups; i++) {
++		struct mdesc_mlgroup *m = &mlgroups[i];
++		if (m->node == node)
++			return m;
++	}
++	return NULL;
++}
++
++static int __init numa_attach_mlgroup(struct mdesc_handle *md, u64 grp,
++				      int index)
++{
++	struct mdesc_mlgroup *candidate = NULL;
++	u64 arc, best_latency = ~(u64)0;
++	struct node_mem_mask *n;
++
++	mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_FWD) {
++		u64 target = mdesc_arc_target(md, arc);
++		struct mdesc_mlgroup *m = find_mlgroup(target);
++		if (!m)
++			continue;
++		if (m->latency < best_latency) {
++			candidate = m;
++			best_latency = m->latency;
+ 		}
+ 	}
+-#endif	
++	if (!candidate)
++		return -ENOENT;
++
++	if (num_node_masks != index) {
++		printk(KERN_ERR "Inconsistent NUMA state, "
++		       "index[%d] != num_node_masks[%d]\n",
++		       index, num_node_masks);
++		return -EINVAL;
++	}
+ 
+-	if (cmdline_memory_size &&
+-	    bytes_avail > cmdline_memory_size)
+-		trim_pavail(&bytes_avail,
+-			    &end_of_phys_memory);
++	n = &node_masks[num_node_masks++];
+ 
+-	*pages_avail = bytes_avail >> PAGE_SHIFT;
++	n->mask = candidate->mask;
++	n->val = candidate->match;
+ 
+-	end_pfn = end_of_phys_memory >> PAGE_SHIFT;
++	numadbg("NUMA NODE[%d]: mask[%lx] val[%lx] (latency[%lx])\n",
++		index, n->mask, n->val, candidate->latency);
+ 
+-	/* Initialize the boot-time allocator. */
+-	max_pfn = max_low_pfn = end_pfn;
+-	min_low_pfn = (phys_base >> PAGE_SHIFT);
++	return 0;
++}
++
++static int __init numa_parse_mdesc_group(struct mdesc_handle *md, u64 grp,
++					 int index)
++{
++	cpumask_t mask;
++	int cpu;
+ 
+-	bootmap_pfn = choose_bootmap_pfn(min_low_pfn, end_pfn);
++	numa_parse_mdesc_group_cpus(md, grp, &mask);
+ 
+-	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn,
+-					 min_low_pfn, end_pfn);
++	for_each_cpu_mask(cpu, mask)
++		numa_cpu_lookup_table[cpu] = index;
++	numa_cpumask_lookup_table[index] = mask;
+ 
+-	/* Now register the available physical memory with the
+-	 * allocator.
+-	 */
+-	for (i = 0; i < pavail_ents; i++)
+-		free_bootmem(pavail[i].phys_addr, pavail[i].reg_size);
++	if (numa_debug) {
++		printk(KERN_INFO "NUMA GROUP[%d]: cpus [ ", index);
++		for_each_cpu_mask(cpu, mask)
++			printk("%d ", cpu);
++		printk("]\n");
++	}
+ 
+-#ifdef CONFIG_BLK_DEV_INITRD
+-	if (initrd_start) {
+-		size = initrd_end - initrd_start;
++	return numa_attach_mlgroup(md, grp, index);
++}
++
++static int __init numa_parse_mdesc(void)
++{
++	struct mdesc_handle *md = mdesc_grab();
++	int i, err, count;
++	u64 node;
++
++	node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
++	if (node == MDESC_NODE_NULL) {
++		mdesc_release(md);
++		return -ENOENT;
++	}
++
++	err = grab_mblocks(md);
++	if (err < 0)
++		goto out;
++
++	err = grab_mlgroups(md);
++	if (err < 0)
++		goto out;
++
++	count = 0;
++	mdesc_for_each_node_by_name(md, node, "group") {
++		err = numa_parse_mdesc_group(md, node, count);
++		if (err < 0)
++			break;
++		count++;
++	}
++
++	add_node_ranges();
++
++	for (i = 0; i < num_node_masks; i++) {
++		allocate_node_data(i);
++		node_set_online(i);
++	}
++
++	err = 0;
++out:
++	mdesc_release(md);
++	return err;
++}
++
++static int __init numa_parse_sun4u(void)
++{
++	return -1;
++}
+ 
+-		/* Reserve the initrd image area. */
+-		reserve_bootmem(initrd_start, size, BOOTMEM_DEFAULT);
++static int __init bootmem_init_numa(void)
++{
++	int err = -1;
+ 
+-		initrd_start += PAGE_OFFSET;
+-		initrd_end += PAGE_OFFSET;
++	numadbg("bootmem_init_numa()\n");
++
++	if (numa_enabled) {
++		if (tlb_type == hypervisor)
++			err = numa_parse_mdesc();
++		else
++			err = numa_parse_sun4u();
+ 	}
++	return err;
++}
++
++#else
++
++static int bootmem_init_numa(void)
++{
++	return -1;
++}
++
+ #endif
+-	/* Reserve the kernel text/data/bss. */
+-	reserve_bootmem(kern_base, kern_size, BOOTMEM_DEFAULT);
+-	*pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT;
+-
+-	/* Add back in the initmem pages. */
+-	size = ((unsigned long)(__init_end) & PAGE_MASK) -
+-		PAGE_ALIGN((unsigned long)__init_begin);
+-	*pages_avail += size >> PAGE_SHIFT;
+-
+-	/* Reserve the bootmem map.   We do not account for it
+-	 * in pages_avail because we will release that memory
+-	 * in free_all_bootmem.
+-	 */
+-	size = bootmap_size;
+-	reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size, BOOTMEM_DEFAULT);
+ 
+-	for (i = 0; i < pavail_ents; i++) {
++static void __init bootmem_init_nonnuma(void)
++{
++	unsigned long top_of_ram = lmb_end_of_DRAM();
++	unsigned long total_ram = lmb_phys_mem_size();
++	unsigned int i;
++
++	numadbg("bootmem_init_nonnuma()\n");
++
++	printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
++	       top_of_ram, total_ram);
++	printk(KERN_INFO "Memory hole size: %ldMB\n",
++	       (top_of_ram - total_ram) >> 20);
++
++	init_node_masks_nonnuma();
++
++	for (i = 0; i < lmb.memory.cnt; i++) {
++		unsigned long size = lmb_size_bytes(&lmb.memory, i);
+ 		unsigned long start_pfn, end_pfn;
+ 
+-		start_pfn = pavail[i].phys_addr >> PAGE_SHIFT;
+-		end_pfn = (start_pfn + (pavail[i].reg_size >> PAGE_SHIFT));
+-		memory_present(0, start_pfn, end_pfn);
++		if (!size)
++			continue;
++
++		start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
++		end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
++		add_active_range(0, start_pfn, end_pfn);
++	}
++
++	allocate_node_data(0);
++
++	node_set_online(0);
++}
++
++static void __init reserve_range_in_node(int nid, unsigned long start,
++					 unsigned long end)
++{
++	numadbg("    reserve_range_in_node(nid[%d],start[%lx],end[%lx]\n",
++		nid, start, end);
++	while (start < end) {
++		unsigned long this_end;
++		int n;
++
++		this_end = nid_range(start, end, &n);
++		if (n == nid) {
++			numadbg("      MATCH reserving range [%lx:%lx]\n",
++				start, this_end);
++			reserve_bootmem_node(NODE_DATA(nid), start,
++					     (this_end - start), BOOTMEM_DEFAULT);
++		} else
++			numadbg("      NO MATCH, advancing start to %lx\n",
++				this_end);
++
++		start = this_end;
++	}
++}
++
++static void __init trim_reserved_in_node(int nid)
++{
++	int i;
++
++	numadbg("  trim_reserved_in_node(%d)\n", nid);
++
++	for (i = 0; i < lmb.reserved.cnt; i++) {
++		unsigned long start = lmb.reserved.region[i].base;
++		unsigned long size = lmb_size_bytes(&lmb.reserved, i);
++		unsigned long end = start + size;
++
++		reserve_range_in_node(nid, start, end);
++	}
++}
++
++static void __init bootmem_init_one_node(int nid)
++{
++	struct pglist_data *p;
++
++	numadbg("bootmem_init_one_node(%d)\n", nid);
++
++	p = NODE_DATA(nid);
++
++	if (p->node_spanned_pages) {
++		unsigned long paddr = node_masks[nid].bootmem_paddr;
++		unsigned long end_pfn;
++
++		end_pfn = p->node_start_pfn + p->node_spanned_pages;
++
++		numadbg("  init_bootmem_node(%d, %lx, %lx, %lx)\n",
++			nid, paddr >> PAGE_SHIFT, p->node_start_pfn, end_pfn);
++
++		init_bootmem_node(p, paddr >> PAGE_SHIFT,
++				  p->node_start_pfn, end_pfn);
++
++		numadbg("  free_bootmem_with_active_regions(%d, %lx)\n",
++			nid, end_pfn);
++		free_bootmem_with_active_regions(nid, end_pfn);
++
++		trim_reserved_in_node(nid);
++
++		numadbg("  sparse_memory_present_with_active_regions(%d)\n",
++			nid);
++		sparse_memory_present_with_active_regions(nid);
+ 	}
++}
++
++static unsigned long __init bootmem_init(unsigned long phys_base)
++{
++	unsigned long end_pfn;
++	int nid;
++
++	end_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
++	max_pfn = max_low_pfn = end_pfn;
++	min_low_pfn = (phys_base >> PAGE_SHIFT);
++
++	if (bootmem_init_numa() < 0)
++		bootmem_init_nonnuma();
++
++	/* XXX cpu notifier XXX */
++
++	for_each_online_node(nid)
++		bootmem_init_one_node(nid);
+ 
+ 	sparse_init();
+ 
+@@ -1289,7 +1688,7 @@ void __init setup_per_cpu_areas(void)
+ 
+ void __init paging_init(void)
+ {
+-	unsigned long end_pfn, pages_avail, shift, phys_base;
++	unsigned long end_pfn, shift, phys_base;
+ 	unsigned long real_end, i;
+ 
+ 	/* These build time checkes make sure that the dcache_dirty_cpu()
+@@ -1330,12 +1729,26 @@ void __init paging_init(void)
+ 		sun4v_ktsb_init();
+ 	}
+ 
++	lmb_init();
++
+ 	/* Find available physical memory... */
+ 	read_obp_memory("available", &pavail[0], &pavail_ents);
+ 
+ 	phys_base = 0xffffffffffffffffUL;
+-	for (i = 0; i < pavail_ents; i++)
++	for (i = 0; i < pavail_ents; i++) {
+ 		phys_base = min(phys_base, pavail[i].phys_addr);
++		lmb_add(pavail[i].phys_addr, pavail[i].reg_size);
++	}
++
++	lmb_reserve(kern_base, kern_size);
++
++	find_ramdisk(phys_base);
++
++	if (cmdline_memory_size)
++		lmb_enforce_memory_limit(phys_base + cmdline_memory_size);
++
++	lmb_analyze();
++	lmb_dump_all();
+ 
+ 	set_bit(0, mmu_context_bmap);
+ 
+@@ -1371,14 +1784,10 @@ void __init paging_init(void)
+ 	if (tlb_type == hypervisor)
+ 		sun4v_ktsb_register();
+ 
+-	/* Setup bootmem... */
+-	pages_avail = 0;
+-	last_valid_pfn = end_pfn = bootmem_init(&pages_avail, phys_base);
+-
+-	max_mapnr = last_valid_pfn;
+-
+-	kernel_physical_mapping_init();
+-
++	/* We must setup the per-cpu areas before we pull in the
++	 * PROM and the MDESC.  The code there fills in cpu and
++	 * other information into per-cpu data structures.
++	 */
+ 	real_setup_per_cpu_areas();
+ 
+ 	prom_build_devicetree();
+@@ -1386,20 +1795,22 @@ void __init paging_init(void)
+ 	if (tlb_type == hypervisor)
+ 		sun4v_mdesc_init();
+ 
++	/* Setup bootmem... */
++	last_valid_pfn = end_pfn = bootmem_init(phys_base);
++
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++	max_mapnr = last_valid_pfn;
++#endif
++	kernel_physical_mapping_init();
++
+ 	{
+-		unsigned long zones_size[MAX_NR_ZONES];
+-		unsigned long zholes_size[MAX_NR_ZONES];
+-		int znum;
++		unsigned long max_zone_pfns[MAX_NR_ZONES];
+ 
+-		for (znum = 0; znum < MAX_NR_ZONES; znum++)
+-			zones_size[znum] = zholes_size[znum] = 0;
++		memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ 
+-		zones_size[ZONE_NORMAL] = end_pfn;
+-		zholes_size[ZONE_NORMAL] = end_pfn - pages_avail;
++		max_zone_pfns[ZONE_NORMAL] = end_pfn;
+ 
+-		free_area_init_node(0, &contig_page_data, zones_size,
+-				    __pa(PAGE_OFFSET) >> PAGE_SHIFT,
+-				    zholes_size);
++		free_area_init_nodes(max_zone_pfns);
+ 	}
+ 
+ 	printk("Booting Linux...\n");
+@@ -1408,21 +1819,52 @@ void __init paging_init(void)
+ 	cpu_probe();
+ }
+ 
+-static void __init taint_real_pages(void)
++int __init page_in_phys_avail(unsigned long paddr)
++{
++	int i;
++
++	paddr &= PAGE_MASK;
++
++	for (i = 0; i < pavail_ents; i++) {
++		unsigned long start, end;
++
++		start = pavail[i].phys_addr;
++		end = start + pavail[i].reg_size;
++
++		if (paddr >= start && paddr < end)
++			return 1;
++	}
++	if (paddr >= kern_base && paddr < (kern_base + kern_size))
++		return 1;
++#ifdef CONFIG_BLK_DEV_INITRD
++	if (paddr >= __pa(initrd_start) &&
++	    paddr < __pa(PAGE_ALIGN(initrd_end)))
++		return 1;
++#endif
++
++	return 0;
++}
++
++static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
++static int pavail_rescan_ents __initdata;
++
++/* Certain OBP calls, such as fetching "available" properties, can
++ * claim physical memory.  So, along with initializing the valid
++ * address bitmap, what we do here is refetch the physical available
++ * memory list again, and make sure it provides at least as much
++ * memory as 'pavail' does.
++ */
++static void setup_valid_addr_bitmap_from_pavail(void)
+ {
+ 	int i;
+ 
+ 	read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents);
+ 
+-	/* Find changes discovered in the physmem available rescan and
+-	 * reserve the lost portions in the bootmem maps.
+-	 */
+ 	for (i = 0; i < pavail_ents; i++) {
+ 		unsigned long old_start, old_end;
+ 
+ 		old_start = pavail[i].phys_addr;
+-		old_end = old_start +
+-			pavail[i].reg_size;
++		old_end = old_start + pavail[i].reg_size;
+ 		while (old_start < old_end) {
+ 			int n;
+ 
+@@ -1440,7 +1882,16 @@ static void __init taint_real_pages(void)
+ 					goto do_next_page;
+ 				}
+ 			}
+-			reserve_bootmem(old_start, PAGE_SIZE, BOOTMEM_DEFAULT);
++
++			prom_printf("mem_init: Lost memory in pavail\n");
++			prom_printf("mem_init: OLD start[%lx] size[%lx]\n",
++				    pavail[i].phys_addr,
++				    pavail[i].reg_size);
++			prom_printf("mem_init: NEW start[%lx] size[%lx]\n",
++				    pavail_rescan[i].phys_addr,
++				    pavail_rescan[i].reg_size);
++			prom_printf("mem_init: Cannot continue, aborting.\n");
++			prom_halt();
+ 
+ 		do_next_page:
+ 			old_start += PAGE_SIZE;
+@@ -1448,32 +1899,6 @@ static void __init taint_real_pages(void)
+ 	}
+ }
+ 
+-int __init page_in_phys_avail(unsigned long paddr)
+-{
+-	int i;
+-
+-	paddr &= PAGE_MASK;
+-
+-	for (i = 0; i < pavail_rescan_ents; i++) {
+-		unsigned long start, end;
+-
+-		start = pavail_rescan[i].phys_addr;
+-		end = start + pavail_rescan[i].reg_size;
+-
+-		if (paddr >= start && paddr < end)
+-			return 1;
+-	}
+-	if (paddr >= kern_base && paddr < (kern_base + kern_size))
+-		return 1;
+-#ifdef CONFIG_BLK_DEV_INITRD
+-	if (paddr >= __pa(initrd_start) &&
+-	    paddr < __pa(PAGE_ALIGN(initrd_end)))
+-		return 1;
+-#endif
+-
+-	return 0;
+-}
+-
+ void __init mem_init(void)
+ {
+ 	unsigned long codepages, datapages, initpages;
+@@ -1496,14 +1921,26 @@ void __init mem_init(void)
+ 		addr += PAGE_SIZE;
+ 	}
+ 
+-	taint_real_pages();
++	setup_valid_addr_bitmap_from_pavail();
+ 
+ 	high_memory = __va(last_valid_pfn << PAGE_SHIFT);
+ 
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++	for_each_online_node(i) {
++		if (NODE_DATA(i)->node_spanned_pages != 0) {
++			totalram_pages +=
++				free_all_bootmem_node(NODE_DATA(i));
++		}
++	}
++#else
++	totalram_pages = free_all_bootmem();
++#endif
++
+ 	/* We subtract one to account for the mem_map_zero page
+ 	 * allocated below.
+ 	 */
+-	totalram_pages = num_physpages = free_all_bootmem() - 1;
++	totalram_pages -= 1;
++	num_physpages = totalram_pages;
+ 
+ 	/*
+ 	 * Set up the zero page, mark it reserved, so that page count
+diff --git a/arch/sparc64/mm/tsb.c b/arch/sparc64/mm/tsb.c
+index a3e6e4b..fe70c8a 100644
+--- a/arch/sparc64/mm/tsb.c
++++ b/arch/sparc64/mm/tsb.c
+@@ -321,7 +321,8 @@ retry_tsb_alloc:
+ 	if (new_size > (PAGE_SIZE * 2))
+ 		gfp_flags = __GFP_NOWARN | __GFP_NORETRY;
+ 
+-	new_tsb = kmem_cache_alloc(tsb_caches[new_cache_index], gfp_flags);
++	new_tsb = kmem_cache_alloc_node(tsb_caches[new_cache_index],
++					gfp_flags, numa_node_id());
+ 	if (unlikely(!new_tsb)) {
+ 		/* Not being able to fork due to a high-order TSB
+ 		 * allocation failure is very bad behavior.  Just back
+diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
+index 2865c10..e686a67 100644
+--- a/arch/sparc64/mm/ultra.S
++++ b/arch/sparc64/mm/ultra.S
+@@ -476,7 +476,6 @@ xcall_sync_tick:
+ #endif
+ 	call		smp_synchronize_tick_client
+ 	 nop
+-	clr		%l6
+ 	b		rtrap_xcall
+ 	 ldx		[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
+ 
+@@ -511,7 +510,6 @@ xcall_report_regs:
+ #endif
+ 	call		__show_regs
+ 	 add		%sp, PTREGS_OFF, %o0
+-	clr		%l6
+ 	/* Has to be a non-v9 branch due to the large distance. */
+ 	b		rtrap_xcall
+ 	 ldx		[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
+@@ -576,7 +574,7 @@ __hypervisor_tlb_xcall_error:
+ 	mov	%l4, %o0
+ 	call	hypervisor_tlbop_error_xcall
+ 	 mov	%l5, %o1
+-	ba,a,pt	%xcc, rtrap_clr_l6
++	ba,a,pt	%xcc, rtrap
+ 
+ 	.globl		__hypervisor_xcall_flush_tlb_mm
+ __hypervisor_xcall_flush_tlb_mm: /* 21 insns */
+diff --git a/arch/sparc64/solaris/Makefile b/arch/sparc64/solaris/Makefile
+deleted file mode 100644
+index 8c86630..0000000
+--- a/arch/sparc64/solaris/Makefile
++++ /dev/null
+@@ -1,10 +0,0 @@
+-#
+-# Makefile for the Solaris binary emulation.
+-#
+-
+-EXTRA_AFLAGS := -ansi
+-
+-solaris-objs := entry64.o fs.o misc.o signal.o systbl.o socket.o \
+-		ioctl.o ipc.o socksys.o timod.o
+-
+-obj-$(CONFIG_SOLARIS_EMUL) += solaris.o
+diff --git a/arch/sparc64/solaris/conv.h b/arch/sparc64/solaris/conv.h
+deleted file mode 100644
+index 50e5823..0000000
+--- a/arch/sparc64/solaris/conv.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* $Id: conv.h,v 1.4 1998/08/15 20:42:51 davem Exp $
+- * conv.h: Utility macros for Solaris emulation
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+- 
+-/* #define DEBUG_SOLARIS */
+-#define DEBUG_SOLARIS_KMALLOC
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <asm/unistd.h>
+-
+-/* Use this to get at 32-bit user passed pointers. */
+-#define A(__x)				\
+-({	unsigned long __ret;		\
+-	__asm__ ("srl	%0, 0, %0"	\
+-		 : "=r" (__ret)		\
+-		 : "0" (__x));		\
+-	(void __user *)__ret;		\
+-})
+-
+-extern unsigned sys_call_table[];
+-extern unsigned sys_call_table32[];
+-extern unsigned sunos_sys_table[];
+-
+-#define SYS(name) ((long)sys_call_table[__NR_##name])
+-#define SUNOS(x) ((long)sunos_sys_table[x])
+-
+-#ifdef DEBUG_SOLARIS
+-#define SOLD(s) printk("%s,%d,%s(): %s\n",__FILE__,__LINE__,__func__,(s))
+-#define SOLDD(s) printk("solaris: "); printk s
+-#else
+-#define SOLD(s)
+-#define SOLDD(s)
+-#endif
+-
+-#endif /* __ASSEMBLY__ */
+diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S
+deleted file mode 100644
+index f170324..0000000
+--- a/arch/sparc64/solaris/entry64.S
++++ /dev/null
+@@ -1,223 +0,0 @@
+-/* $Id: entry64.S,v 1.7 2002/02/09 19:49:31 davem Exp $
+- * entry64.S:  Solaris syscall emulation entry point.
+- *
+- * Copyright (C) 1996,1997,1998 Jakub Jelinek   (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1995,1997 David S. Miller (davem at caip.rutgers.edu)
+- * Copyright (C) 1996 Miguel de Icaza      (miguel at nuclecu.unam.mx)
+- */
+-
+-#include <linux/errno.h>
+-
+-#include <asm/head.h>
+-#include <asm/asi.h>
+-#include <asm/smp.h>
+-#include <asm/ptrace.h>
+-#include <asm/page.h>
+-#include <asm/signal.h>
+-#include <asm/pgtable.h>
+-#include <asm/processor.h>
+-#include <asm/thread_info.h>
+-
+-#include "conv.h"
+-
+-#define NR_SYSCALLS	256
+-
+-	.text
+-solaris_syscall_trace:
+-	add		%sp, PTREGS_OFF, %o0
+-	call		syscall_trace
+-	 mov		0, %o1
+-	srl		%i0, 0, %o0
+-	mov		%i4, %o4
+-	srl		%i1, 0, %o1
+-	mov		%i5, %o5
+-	andcc		%l3, 1, %g0
+-	be,pt		%icc, 2f
+-	 srl		%i2, 0, %o2
+-	b,pt		%xcc, 2f
+-	 add		%sp, PTREGS_OFF, %o0
+-
+-solaris_sucks:
+-/* Solaris is a big system which needs to be able to do all the things
+- * in Inf+1 different ways */
+-	add		%i6, 0x5c, %o0
+-	mov		%i0, %g1
+-	mov		%i1, %i0
+-	mov		%i2, %i1
+-	srl		%o0, 0, %o0
+-	mov		%i3, %i2
+-	movrz		%g1, 256, %g1 /* Ensure we don't loop forever */
+-	mov		%i4, %i3
+-	mov		%i5, %i4
+-	ba,pt		%xcc, solaris_sparc_syscall
+-exen:	 lduwa		[%o0] ASI_S, %i5
+-
+-exenf:	ba,pt		%xcc, solaris_sparc_syscall
+-	 clr		%i5
+-
+-/* For shared binaries, binfmt_elf32 already sets up personality
+-   and exec_domain. This is to handle static binaries as well */
+-solaris_reg:
+-	call		solaris_register
+-	 nop
+-	ba,pt		%xcc, 1f
+-	 mov		%i4, %o4
+-
+-linux_syscall_for_solaris:
+-	sethi		%hi(sys_call_table32), %l6
+-	or		%l6, %lo(sys_call_table32), %l6
+-	sll		%l3, 2, %l4
+-	ba,pt		%xcc, 10f
+-	 lduw		[%l6 + %l4], %l3
+-
+-	/* Solaris system calls enter here... */
+-	.align	32
+-	.globl	solaris_sparc_syscall, entry64_personality_patch
+-solaris_sparc_syscall:
+-entry64_personality_patch:
+-	ldub		[%g4 + 0x0], %l0
+-	cmp		%g1, 255
+-	bg,pn		%icc, solaris_unimplemented
+-	 srl		%g1, 0, %g1
+-	sethi		%hi(solaris_sys_table), %l7
+-	or		%l7, %lo(solaris_sys_table), %l7
+-	brz,pn		%g1, solaris_sucks
+-	 mov		%i4, %o4
+-	sll		%g1, 2, %l4
+-	cmp		%l0, 1
+-	bne,pn		%icc, solaris_reg
+-1:	 srl		%i0, 0, %o0
+-	lduw		[%l7 + %l4], %l3
+-	srl		%i1, 0, %o1
+-	ldx		[%g6 + TI_FLAGS], %l5
+-	cmp		%l3, NR_SYSCALLS
+-	bleu,a,pn	%xcc, linux_syscall_for_solaris
+-	 nop
+-	andcc		%l3, 1, %g0
+-	bne,a,pn	%icc, 10f
+-	 add		%sp, PTREGS_OFF, %o0
+-10:	srl		%i2, 0, %o2
+-	mov		%i5, %o5
+-	andn		%l3, 3, %l7
+-	andcc		%l5, _TIF_SYSCALL_TRACE, %g0				
+-	bne,pn		%icc, solaris_syscall_trace		
+-	 mov		%i0, %l5
+-2:	call		%l7
+-	 srl		%i3, 0, %o3
+-ret_from_solaris:
+-	stx		%o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-	ldx		[%g6 + TI_FLAGS], %l6
+-	sra		%o0, 0, %o0
+-	mov		%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
+-	ldx		[%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
+-	cmp		%o0, -ERESTART_RESTARTBLOCK
+-	sllx		%g2, 32, %g2
+-	bgeu,pn		%xcc, 1f
+-	 andcc		%l6, _TIF_SYSCALL_TRACE, %l6	
+-
+-	/* System call success, clear Carry condition code. */
+-	andn		%g3, %g2, %g3
+-	stx		%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]	
+-	bne,pn		%icc, solaris_syscall_trace2
+-	 ldx		[%sp + PTREGS_OFF + PT_V9_TNPC], %l1
+-	andcc		%l1, 1, %g0
+-	bne,pn		%icc, 2f
+-	 clr		%l6
+-	add		%l1, 0x4, %l2				         
+-	stx		%l1, [%sp + PTREGS_OFF + PT_V9_TPC]	 ! pc = npc
+-	call		rtrap
+-	 stx		%l2, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc+4
+-
+-	/* When tnpc & 1, this comes from setcontext and we don't want to advance pc */
+-2:	andn		%l1, 3, %l1
+-	call		rtrap
+-	 stx		%l1, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc&~3
+-
+-1:
+-	/* System call failure, set Carry condition code.
+-	 * Also, get abs(errno) to return to the process.
+-	 */
+-	sub		%g0, %o0, %o0
+-	or		%g3, %g2, %g3
+-	cmp		%o0, ERANGE	/* 0-ERANGE are identity mapped */
+-	bleu,pt		%icc, 1f
+-	 cmp		%o0, EMEDIUMTYPE
+-	bgu,pn		%icc, 1f
+-	 sethi		%hi(solaris_err_table), %l6
+-	sll		%o0, 2, %o0
+-	or		%l6, %lo(solaris_err_table), %l6
+-	ldsw		[%l6 + %o0], %o0
+-1:	stx		%o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-	mov		1, %l6
+-	stx		%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
+-	bne,pn		%icc, solaris_syscall_trace2
+-	 ldx		[%sp + PTREGS_OFF + PT_V9_TNPC], %l1
+-	andcc		%l1, 1, %g0
+-	bne,pn		%icc, 2b
+-	 add		%l1, 0x4, %l2
+-	stx		%l1, [%sp + PTREGS_OFF + PT_V9_TPC]  ! pc = npc
+-	call		rtrap
+-	 stx		%l2, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc+4 
+-
+-solaris_syscall_trace2:
+-	add		%sp, PTREGS_OFF, %o0
+-	call		syscall_trace
+-	 mov		1, %o1
+-	add		%l1, 0x4, %l2			/* npc = npc+4 */
+-	andcc		%l1, 1, %g0
+-	bne,pn		%icc, 2b
+-	 nop
+-	stx		%l1, [%sp + PTREGS_OFF + PT_V9_TPC]
+-	call		rtrap
+-	 stx		%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
+-
+-	/* This one is tricky, so that's why we do it in assembly */
+-	.globl		solaris_sigsuspend
+-solaris_sigsuspend:
+-	call		do_sol_sigsuspend
+-	 nop
+-	brlz,pn		%o0, ret_from_solaris
+-	 nop
+-	call		sys_sigsuspend
+-	 stx		%o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-	b,pt		%xcc, ret_from_solaris
+-	 nop
+-
+-	.globl		solaris_getpid
+-solaris_getpid:
+-	call		sys_getppid
+-	 nop
+-	call		sys_getpid
+-	 stx		%o0, [%sp + PTREGS_OFF + PT_V9_I1]
+-	b,pt		%xcc, ret_from_solaris
+-	 nop
+-
+-	.globl	solaris_getuid
+-solaris_getuid:
+-	call		sys_geteuid
+-	 nop
+-	call		sys_getuid
+-	 stx		%o1, [%sp + PTREGS_OFF + PT_V9_I1]
+-	b,pt		%xcc, ret_from_solaris
+-	 nop
+-
+-	.globl	solaris_getgid
+-solaris_getgid:
+-	call		sys_getegid
+-	 nop
+-	call		sys_getgid
+-	 stx		%o1, [%sp + PTREGS_OFF + PT_V9_I1]
+-	b,pt		%xcc, ret_from_solaris
+-	 nop
+-
+-	.globl		solaris_unimplemented
+-solaris_unimplemented:
+-	call		do_sol_unimplemented
+-	 add		%sp, PTREGS_OFF, %o0
+-	ba,pt		%xcc, ret_from_solaris
+-	 nop
+-
+-	.section	__ex_table,"a"
+-	.align		4
+-	.word		exen, exenf
+-
+diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
+deleted file mode 100644
+index 7d035f0..0000000
+--- a/arch/sparc64/solaris/fs.c
++++ /dev/null
+@@ -1,745 +0,0 @@
+-/* $Id: fs.c,v 1.27 2002/02/08 03:57:14 davem Exp $
+- * fs.c: fs related syscall emulation for Solaris
+- *
+- * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- *
+- * 1999-08-19 Implemented solaris F_FREESP (truncate)
+- *            fcntl, by Jason Rappleye (rappleye at ccr.buffalo.edu)
+- */
+-
+-#include <linux/types.h>
+-#include <linux/sched.h>
+-#include <linux/slab.h>
+-#include <linux/capability.h>
+-#include <linux/fs.h>
+-#include <linux/namei.h>
+-#include <linux/mm.h>
+-#include <linux/file.h>
+-#include <linux/stat.h>
+-#include <linux/smp_lock.h>
+-#include <linux/limits.h>
+-#include <linux/resource.h>
+-#include <linux/quotaops.h>
+-#include <linux/mount.h>
+-#include <linux/vfs.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/string.h>
+-#include <asm/ptrace.h>
+-
+-#include "conv.h"
+-
+-#define R3_VERSION	1
+-#define R4_VERSION	2
+-
+-typedef struct {
+-	s32	tv_sec;
+-	s32	tv_nsec;
+-} timestruct_t;
+-
+-struct sol_stat {
+-	u32		st_dev;
+-	s32		st_pad1[3];     /* network id */
+-	u32		st_ino;
+-	u32		st_mode;
+-	u32		st_nlink;
+-	u32		st_uid;
+-	u32		st_gid;
+-	u32		st_rdev;
+-	s32		st_pad2[2];
+-	s32		st_size;
+-	s32		st_pad3;	/* st_size, off_t expansion */
+-	timestruct_t	st_atime;
+-	timestruct_t	st_mtime;
+-	timestruct_t	st_ctime;
+-	s32		st_blksize;
+-	s32		st_blocks;
+-	char		st_fstype[16];
+-	s32		st_pad4[8];     /* expansion area */
+-};
+-
+-struct sol_stat64 {
+-	u32		st_dev;
+-	s32		st_pad1[3];     /* network id */
+-	u64		st_ino;
+-	u32		st_mode;
+-	u32		st_nlink;
+-	u32		st_uid;
+-	u32		st_gid;
+-	u32		st_rdev;
+-	s32		st_pad2[2];
+-	s64		st_size;
+-	timestruct_t	st_atime;
+-	timestruct_t	st_mtime;
+-	timestruct_t	st_ctime;
+-	s64		st_blksize;
+-	s32		st_blocks;
+-	char		st_fstype[16];
+-	s32		st_pad4[4];     /* expansion area */
+-};
+-
+-#define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8))
+-
+-static inline int putstat(struct sol_stat __user *ubuf, struct kstat *kbuf)
+-{
+-	u32 ino;
+-
+-	if (kbuf->size > MAX_NON_LFS ||
+-	    !sysv_valid_dev(kbuf->dev) ||
+-	    !sysv_valid_dev(kbuf->rdev))
+-		return -EOVERFLOW;
+-	ino = kbuf->ino;
+-	if (sizeof(ino) < sizeof(kbuf->ino) && ino != kbuf->ino)
+-		return -EOVERFLOW;
+-	if (put_user (sysv_encode_dev(kbuf->dev), &ubuf->st_dev)	||
+-	    __put_user (ino, &ubuf->st_ino)				||
+-	    __put_user (kbuf->mode, &ubuf->st_mode)		||
+-	    __put_user (kbuf->nlink, &ubuf->st_nlink)	||
+-	    __put_user (kbuf->uid, &ubuf->st_uid)		||
+-	    __put_user (kbuf->gid, &ubuf->st_gid)		||
+-	    __put_user (sysv_encode_dev(kbuf->rdev), &ubuf->st_rdev)	||
+-	    __put_user (kbuf->size, &ubuf->st_size)		||
+-	    __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec)	||
+-	    __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec)	||
+-	    __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec)	||
+-	    __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec)	||
+-	    __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec)	||
+-	    __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec)	||
+-	    __put_user (kbuf->blksize, &ubuf->st_blksize)	||
+-	    __put_user (kbuf->blocks, &ubuf->st_blocks)	||
+-	    __put_user (UFSMAGIC, (unsigned __user *)ubuf->st_fstype))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-static inline int putstat64(struct sol_stat64 __user *ubuf, struct kstat *kbuf)
+-{
+-	if (!sysv_valid_dev(kbuf->dev) || !sysv_valid_dev(kbuf->rdev))
+-		return -EOVERFLOW;
+-	if (put_user (sysv_encode_dev(kbuf->dev), &ubuf->st_dev)	||
+-	    __put_user (kbuf->ino, &ubuf->st_ino)		||
+-	    __put_user (kbuf->mode, &ubuf->st_mode)		||
+-	    __put_user (kbuf->nlink, &ubuf->st_nlink)	||
+-	    __put_user (kbuf->uid, &ubuf->st_uid)		||
+-	    __put_user (kbuf->gid, &ubuf->st_gid)		||
+-	    __put_user (sysv_encode_dev(kbuf->rdev), &ubuf->st_rdev)	||
+-	    __put_user (kbuf->size, &ubuf->st_size)		||
+-	    __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec)	||
+-	    __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec)	||
+-	    __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec)	||
+-	    __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec)	||
+-	    __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec)	||
+-	    __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec)	||
+-	    __put_user (kbuf->blksize, &ubuf->st_blksize)	||
+-	    __put_user (kbuf->blocks, &ubuf->st_blocks)	||
+-	    __put_user (UFSMAGIC, (unsigned __user *)ubuf->st_fstype))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-asmlinkage int solaris_stat(u32 filename, u32 statbuf)
+-{
+-	struct kstat s;
+-	int ret = vfs_stat(A(filename), &s);
+-	if (!ret)
+-		return putstat(A(statbuf), &s);
+-	return ret;
+-}
+-
+-asmlinkage int solaris_xstat(int vers, u32 filename, u32 statbuf)
+-{
+-	/* Solaris doesn't bother with looking at vers, so we do neither */
+-	return solaris_stat(filename, statbuf);
+-}
+-
+-asmlinkage int solaris_stat64(u32 filename, u32 statbuf)
+-{
+-	struct kstat s;
+-	int ret = vfs_stat(A(filename), &s);
+-	if (!ret)
+-		return putstat64(A(statbuf), &s);
+-	return ret;
+-}
+-
+-asmlinkage int solaris_lstat(u32 filename, u32 statbuf)
+-{
+-	struct kstat s;
+-	int ret = vfs_lstat(A(filename), &s);
+-	if (!ret)
+-		return putstat(A(statbuf), &s);
+-	return ret;
+-}
+-
+-asmlinkage int solaris_lxstat(int vers, u32 filename, u32 statbuf)
+-{
+-	return solaris_lstat(filename, statbuf);
+-}
+-
+-asmlinkage int solaris_lstat64(u32 filename, u32 statbuf)
+-{
+-	struct kstat s;
+-	int ret = vfs_lstat(A(filename), &s);
+-	if (!ret)
+-		return putstat64(A(statbuf), &s);
+-	return ret;
+-}
+-
+-asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf)
+-{
+-	struct kstat s;
+-	int ret = vfs_fstat(fd, &s);
+-	if (!ret)
+-		return putstat(A(statbuf), &s);
+-	return ret;
+-}
+-
+-asmlinkage int solaris_fxstat(int vers, u32 fd, u32 statbuf)
+-{
+-	return solaris_fstat(fd, statbuf);
+-}
+-
+-asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf)
+-{
+-	struct kstat s;
+-	int ret = vfs_fstat(fd, &s);
+-	if (!ret)
+-		return putstat64(A(statbuf), &s);
+-	return ret;
+-}
+-
+-asmlinkage int solaris_mknod(u32 path, u32 mode, s32 dev)
+-{
+-	int (*sys_mknod)(const char __user *,int,unsigned) = 
+-		(int (*)(const char __user *,int,unsigned))SYS(mknod);
+-	int major = sysv_major(dev);
+-	int minor = sysv_minor(dev);
+-
+-	/* minor is guaranteed to be OK for MKDEV, major might be not */
+-	if (major > 0xfff)
+-		return -EINVAL;
+-	return sys_mknod(A(path), mode, new_encode_dev(MKDEV(major,minor)));
+-}
+-
+-asmlinkage int solaris_xmknod(int vers, u32 path, u32 mode, s32 dev)
+-{
+-	return solaris_mknod(path, mode, dev);
+-}
+-
+-asmlinkage int solaris_getdents64(unsigned int fd, void __user *dirent, unsigned int count)
+-{
+-	int (*sys_getdents)(unsigned int, void __user *, unsigned int) =
+-		(int (*)(unsigned int, void __user *, unsigned int))SYS(getdents);
+-		
+-	return sys_getdents(fd, dirent, count);
+-}
+-
+-/* This statfs thingie probably will go in the near future, but... */
+-
+-struct sol_statfs {
+-	short	f_type;
+-	s32	f_bsize;
+-	s32	f_frsize;
+-	s32	f_blocks;
+-	s32	f_bfree;
+-	u32	f_files;
+-	u32	f_ffree;
+-	char	f_fname[6];
+-	char	f_fpack[6];
+-};
+-
+-asmlinkage int solaris_statfs(u32 path, u32 buf, int len, int fstype)
+-{
+-	int ret;
+-	struct statfs s;
+-	mm_segment_t old_fs = get_fs();
+-	int (*sys_statfs)(const char __user *,struct statfs __user *) = 
+-		(int (*)(const char __user *,struct statfs __user *))SYS(statfs);
+-	struct sol_statfs __user *ss = A(buf);
+-	
+-	if (len != sizeof(struct sol_statfs)) return -EINVAL;
+-	if (!fstype) {
+-		/* FIXME: mixing userland and kernel pointers */
+-		set_fs (KERNEL_DS);
+-		ret = sys_statfs(A(path), &s);
+-		set_fs (old_fs);
+-		if (!ret) {
+-			if (put_user (s.f_type, &ss->f_type)		||
+-			    __put_user (s.f_bsize, &ss->f_bsize)	||
+-			    __put_user (0, &ss->f_frsize)		||
+-			    __put_user (s.f_blocks, &ss->f_blocks)	||
+-			    __put_user (s.f_bfree, &ss->f_bfree)	||
+-			    __put_user (s.f_files, &ss->f_files)	||
+-			    __put_user (s.f_ffree, &ss->f_ffree)	||
+-			    __clear_user (&ss->f_fname, 12))
+-				return -EFAULT;
+-		}
+-		return ret;
+-	}
+-/* Linux can't stat unmounted filesystems so we
+- * simply lie and claim 100MB of 1GB is free. Sorry.
+- */
+-	if (put_user (fstype, &ss->f_type)		||
+-	    __put_user (1024, &ss->f_bsize)		||
+-	    __put_user (0, &ss->f_frsize)		||
+-	    __put_user (1024*1024, &ss->f_blocks)	||
+-	    __put_user (100*1024, &ss->f_bfree)		||
+-	    __put_user (60000, &ss->f_files)		||
+-	    __put_user (50000, &ss->f_ffree)		||
+-	    __clear_user (&ss->f_fname, 12))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-asmlinkage int solaris_fstatfs(u32 fd, u32 buf, int len, int fstype)
+-{
+-	int ret;
+-	struct statfs s;
+-	mm_segment_t old_fs = get_fs();
+-	int (*sys_fstatfs)(unsigned,struct statfs __user *) = 
+-		(int (*)(unsigned,struct statfs __user *))SYS(fstatfs);
+-	struct sol_statfs __user *ss = A(buf);
+-	
+-	if (len != sizeof(struct sol_statfs)) return -EINVAL;
+-	if (!fstype) {
+-		set_fs (KERNEL_DS);
+-		ret = sys_fstatfs(fd, &s);
+-		set_fs (old_fs);
+-		if (!ret) {
+-			if (put_user (s.f_type, &ss->f_type)		||
+-			    __put_user (s.f_bsize, &ss->f_bsize)	||
+-			    __put_user (0, &ss->f_frsize)		||
+-			    __put_user (s.f_blocks, &ss->f_blocks)	||
+-			    __put_user (s.f_bfree, &ss->f_bfree)	||
+-			    __put_user (s.f_files, &ss->f_files)	||
+-			    __put_user (s.f_ffree, &ss->f_ffree)	||
+-			    __clear_user (&ss->f_fname, 12))
+-				return -EFAULT;
+-		}
+-		return ret;
+-	}
+-	/* Otherwise fstatfs is the same as statfs */
+-	return solaris_statfs(0, buf, len, fstype);
+-}
+-
+-struct sol_statvfs {
+-	u32	f_bsize;
+-	u32	f_frsize;
+-	u32	f_blocks;
+-	u32	f_bfree;
+-	u32	f_bavail;
+-	u32	f_files;
+-	u32	f_ffree;
+-	u32	f_favail;
+-	u32	f_fsid;
+-	char	f_basetype[16];
+-	u32	f_flag;
+-	u32	f_namemax;
+-	char	f_fstr[32];
+-	u32	f_filler[16];
+-};
+-
+-struct sol_statvfs64 {
+-	u32	f_bsize;
+-	u32	f_frsize;
+-	u64	f_blocks;
+-	u64	f_bfree;
+-	u64	f_bavail;
+-	u64	f_files;
+-	u64	f_ffree;
+-	u64	f_favail;
+-	u32	f_fsid;
+-	char	f_basetype[16];
+-	u32	f_flag;
+-	u32	f_namemax;
+-	char	f_fstr[32];
+-	u32	f_filler[16];
+-};
+-
+-static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf)
+-{
+-	struct kstatfs s;
+-	int error;
+-	struct sol_statvfs __user *ss = A(buf);
+-
+-	error = vfs_statfs(mnt->mnt_root, &s);
+-	if (!error) {
+-		const char *p = mnt->mnt_sb->s_type->name;
+-		int i = 0;
+-		int j = strlen (p);
+-		
+-		if (j > 15) j = 15;
+-		if (IS_RDONLY(inode)) i = 1;
+-		if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
+-		if (!sysv_valid_dev(inode->i_sb->s_dev))
+-			return -EOVERFLOW;
+-		if (put_user (s.f_bsize, &ss->f_bsize)		||
+-		    __put_user (0, &ss->f_frsize)		||
+-		    __put_user (s.f_blocks, &ss->f_blocks)	||
+-		    __put_user (s.f_bfree, &ss->f_bfree)	||
+-		    __put_user (s.f_bavail, &ss->f_bavail)	||
+-		    __put_user (s.f_files, &ss->f_files)	||
+-		    __put_user (s.f_ffree, &ss->f_ffree)	||
+-		    __put_user (s.f_ffree, &ss->f_favail)	||
+-		    __put_user (sysv_encode_dev(inode->i_sb->s_dev), &ss->f_fsid) ||
+-		    __copy_to_user (ss->f_basetype,p,j)		||
+-		    __put_user (0, (char __user *)&ss->f_basetype[j])	||
+-		    __put_user (s.f_namelen, &ss->f_namemax)	||
+-		    __put_user (i, &ss->f_flag)			||		    
+-		    __clear_user (&ss->f_fstr, 32))
+-			return -EFAULT;
+-	}
+-	return error;
+-}
+-
+-static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf)
+-{
+-	struct kstatfs s;
+-	int error;
+-	struct sol_statvfs64 __user *ss = A(buf);
+-			
+-	error = vfs_statfs(mnt->mnt_root, &s);
+-	if (!error) {
+-		const char *p = mnt->mnt_sb->s_type->name;
+-		int i = 0;
+-		int j = strlen (p);
+-		
+-		if (j > 15) j = 15;
+-		if (IS_RDONLY(inode)) i = 1;
+-		if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
+-		if (!sysv_valid_dev(inode->i_sb->s_dev))
+-			return -EOVERFLOW;
+-		if (put_user (s.f_bsize, &ss->f_bsize)		||
+-		    __put_user (0, &ss->f_frsize)		||
+-		    __put_user (s.f_blocks, &ss->f_blocks)	||
+-		    __put_user (s.f_bfree, &ss->f_bfree)	||
+-		    __put_user (s.f_bavail, &ss->f_bavail)	||
+-		    __put_user (s.f_files, &ss->f_files)	||
+-		    __put_user (s.f_ffree, &ss->f_ffree)	||
+-		    __put_user (s.f_ffree, &ss->f_favail)	||
+-		    __put_user (sysv_encode_dev(inode->i_sb->s_dev), &ss->f_fsid) ||
+-		    __copy_to_user (ss->f_basetype,p,j)		||
+-		    __put_user (0, (char __user *)&ss->f_basetype[j])	||
+-		    __put_user (s.f_namelen, &ss->f_namemax)	||
+-		    __put_user (i, &ss->f_flag)			||		    
+-		    __clear_user (&ss->f_fstr, 32))
+-			return -EFAULT;
+-	}
+-	return error;
+-}
+-
+-asmlinkage int solaris_statvfs(u32 path, u32 buf)
+-{
+-	struct nameidata nd;
+-	int error;
+-
+-	error = user_path_walk(A(path),&nd);
+-	if (!error) {
+-		struct inode *inode = nd.path.dentry->d_inode;
+-		error = report_statvfs(nd.path.mnt, inode, buf);
+-		path_put(&nd.path);
+-	}
+-	return error;
+-}
+-
+-asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf)
+-{
+-	struct file * file;
+-	int error;
+-
+-	error = -EBADF;
+-	file = fget(fd);
+-	if (file) {
+-		error = report_statvfs(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
+-		fput(file);
+-	}
+-
+-	return error;
+-}
+-
+-asmlinkage int solaris_statvfs64(u32 path, u32 buf)
+-{
+-	struct nameidata nd;
+-	int error;
+-
+-	lock_kernel();
+-	error = user_path_walk(A(path), &nd);
+-	if (!error) {
+-		struct inode *inode = nd.path.dentry->d_inode;
+-		error = report_statvfs64(nd.path.mnt, inode, buf);
+-		path_put(&nd.path);
+-	}
+-	unlock_kernel();
+-	return error;
+-}
+-
+-asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf)
+-{
+-	struct file * file;
+-	int error;
+-
+-	error = -EBADF;
+-	file = fget(fd);
+-	if (file) {
+-		lock_kernel();
+-		error = report_statvfs64(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
+-		unlock_kernel();
+-		fput(file);
+-	}
+-	return error;
+-}
+-
+-extern asmlinkage long sparc32_open(const char * filename, int flags, int mode);
+-
+-asmlinkage int solaris_open(u32 fname, int flags, u32 mode)
+-{
+-	const char *filename = (const char *)(long)fname;
+-	int fl = flags & 0xf;
+-
+-	/* Translate flags first. */
+-	if (flags & 0x2000) fl |= O_LARGEFILE;
+-	if (flags & 0x8050) fl |= O_SYNC;
+-	if (flags & 0x80) fl |= O_NONBLOCK;
+-	if (flags & 0x100) fl |= O_CREAT;
+-	if (flags & 0x200) fl |= O_TRUNC;
+-	if (flags & 0x400) fl |= O_EXCL;
+-	if (flags & 0x800) fl |= O_NOCTTY;
+-	flags = fl;
+-
+-	return sparc32_open(filename, flags, mode);
+-}
+-
+-#define SOL_F_SETLK	6
+-#define SOL_F_SETLKW	7
+-#define SOL_F_FREESP    11
+-#define SOL_F_ISSTREAM  13
+-#define SOL_F_GETLK     14
+-#define SOL_F_PRIV      15
+-#define SOL_F_NPRIV     16
+-#define SOL_F_QUOTACTL  17
+-#define SOL_F_BLOCKS    18
+-#define SOL_F_BLKSIZE   19
+-#define SOL_F_GETOWN    23
+-#define SOL_F_SETOWN    24
+-
+-struct sol_flock {
+-	short	l_type;
+-	short	l_whence;
+-	u32	l_start;
+-	u32	l_len;
+-	s32	l_sysid;
+-	s32	l_pid;
+-	s32	l_pad[4];
+-};
+-
+-asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg)
+-{
+-	int (*sys_fcntl)(unsigned,unsigned,unsigned long) = 
+-		(int (*)(unsigned,unsigned,unsigned long))SYS(fcntl);
+-	int ret, flags;
+-
+-	switch (cmd) {
+-	case F_DUPFD:
+-	case F_GETFD:
+-	case F_SETFD: return sys_fcntl(fd, cmd, (unsigned long)arg);
+-	case F_GETFL:
+-		flags = sys_fcntl(fd, cmd, 0);
+-		ret = flags & 0xf;
+-		if (flags & O_SYNC) ret |= 0x8050;
+-		if (flags & O_NONBLOCK) ret |= 0x80;
+-		return ret;
+-	case F_SETFL:
+-		flags = arg & 0xf;
+-		if (arg & 0x8050) flags |= O_SYNC;
+-		if (arg & 0x80) flags |= O_NONBLOCK;
+-		return sys_fcntl(fd, cmd, (long)flags);
+-	case SOL_F_GETLK:
+-	case SOL_F_SETLK:
+-	case SOL_F_SETLKW:
+-		{
+-			struct flock f;
+-			struct sol_flock __user *p = A(arg);
+-			mm_segment_t old_fs = get_fs();
+-
+-			switch (cmd) {
+-			case SOL_F_GETLK: cmd = F_GETLK; break;
+-			case SOL_F_SETLK: cmd = F_SETLK; break;
+-			case SOL_F_SETLKW: cmd = F_SETLKW; break;
+-			}
+-
+-			if (get_user (f.l_type, &p->l_type) ||
+-			    __get_user (f.l_whence, &p->l_whence) ||
+-			    __get_user (f.l_start, &p->l_start) ||
+-			    __get_user (f.l_len, &p->l_len) ||
+-			    __get_user (f.l_pid, &p->l_sysid))
+-				return -EFAULT;
+-
+-			set_fs(KERNEL_DS);
+-			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+-			set_fs(old_fs);
+-
+-			if (__put_user (f.l_type, &p->l_type) ||
+-			    __put_user (f.l_whence, &p->l_whence) ||
+-			    __put_user (f.l_start, &p->l_start) ||
+-			    __put_user (f.l_len, &p->l_len) ||
+-			    __put_user (f.l_pid, &p->l_pid) ||
+-			    __put_user (0, &p->l_sysid))
+-				return -EFAULT;
+-
+-			return ret;
+-		}
+-	case SOL_F_FREESP:
+-	        { 
+-		    int length;
+-		    int (*sys_newftruncate)(unsigned int, unsigned long)=
+-			    (int (*)(unsigned int, unsigned long))SYS(ftruncate);
+-
+-		    if (get_user(length, &((struct sol_flock __user *)A(arg))->l_start))
+-			    return -EFAULT;
+-
+-		    return sys_newftruncate(fd, length);
+-		}
+-	};
+-	return -EINVAL;
+-}
+-
+-asmlinkage int solaris_ulimit(int cmd, int val)
+-{
+-	switch (cmd) {
+-	case 1: /* UL_GETFSIZE - in 512B chunks */
+-		return current->signal->rlim[RLIMIT_FSIZE].rlim_cur >> 9;
+-	case 2: /* UL_SETFSIZE */
+-		if ((unsigned long)val > (LONG_MAX>>9)) return -ERANGE;
+-		val <<= 9;
+-		task_lock(current->group_leader);
+-		if (val > current->signal->rlim[RLIMIT_FSIZE].rlim_max) {
+-			if (!capable(CAP_SYS_RESOURCE)) {
+-				task_unlock(current->group_leader);
+-				return -EPERM;
+-			}
+-			current->signal->rlim[RLIMIT_FSIZE].rlim_max = val;
+-		}
+-		current->signal->rlim[RLIMIT_FSIZE].rlim_cur = val;
+-		task_unlock(current->group_leader);
+-		return 0;
+-	case 3: /* UL_GMEMLIM */
+-		return current->signal->rlim[RLIMIT_DATA].rlim_cur;
+-	case 4: /* UL_GDESLIM */
+-		return sysctl_nr_open;
+-	}
+-	return -EINVAL;
+-}
+-
+-/* At least at the time I'm writing this, Linux doesn't have ACLs, so we
+-   just fake this */
+-asmlinkage int solaris_acl(u32 filename, int cmd, int nentries, u32 aclbufp)
+-{
+-	return -ENOSYS;
+-}
+-
+-asmlinkage int solaris_facl(unsigned int fd, int cmd, int nentries, u32 aclbufp)
+-{
+-	return -ENOSYS;
+-}
+-
+-asmlinkage int solaris_pread(unsigned int fd, char __user *buf, u32 count, u32 pos)
+-{
+-	ssize_t (*sys_pread64)(unsigned int, char __user *, size_t, loff_t) =
+-		(ssize_t (*)(unsigned int, char __user *, size_t, loff_t))SYS(pread64);
+-
+-	return sys_pread64(fd, buf, count, (loff_t)pos);
+-}
+-
+-asmlinkage int solaris_pwrite(unsigned int fd, char __user *buf, u32 count, u32 pos)
+-{
+-	ssize_t (*sys_pwrite64)(unsigned int, char __user *, size_t, loff_t) =
+-		(ssize_t (*)(unsigned int, char __user *, size_t, loff_t))SYS(pwrite64);
+-
+-	return sys_pwrite64(fd, buf, count, (loff_t)pos);
+-}
+-
+-/* POSIX.1 names */
+-#define _PC_LINK_MAX    1
+-#define _PC_MAX_CANON   2
+-#define _PC_MAX_INPUT   3
+-#define _PC_NAME_MAX    4
+-#define _PC_PATH_MAX    5
+-#define _PC_PIPE_BUF    6
+-#define _PC_NO_TRUNC    7
+-#define _PC_VDISABLE    8
+-#define _PC_CHOWN_RESTRICTED    9
+-/* POSIX.4 names */
+-#define _PC_ASYNC_IO    10
+-#define _PC_PRIO_IO     11
+-#define _PC_SYNC_IO     12
+-#define _PC_LAST        12
+-
+-/* This is not a real and complete implementation yet, just to keep
+- * the easy Solaris binaries happy.
+- */
+-asmlinkage int solaris_fpathconf(int fd, int name)
+-{
+-	int ret;
+-
+-	switch(name) {
+-	case _PC_LINK_MAX:
+-		ret = LINK_MAX;
+-		break;
+-	case _PC_MAX_CANON:
+-		ret = MAX_CANON;
+-		break;
+-	case _PC_MAX_INPUT:
+-		ret = MAX_INPUT;
+-		break;
+-	case _PC_NAME_MAX:
+-		ret = NAME_MAX;
+-		break;
+-	case _PC_PATH_MAX:
+-		ret = PATH_MAX;
+-		break;
+-	case _PC_PIPE_BUF:
+-		ret = PIPE_BUF;
+-		break;
+-	case _PC_CHOWN_RESTRICTED:
+-		ret = 1;
+-		break;
+-	case _PC_NO_TRUNC:
+-	case _PC_VDISABLE:
+-		ret = 0;
+-		break;
+-	default:
+-		ret = -EINVAL;
+-		break;
+-	}
+-	return ret;
+-}
+-
+-asmlinkage int solaris_pathconf(u32 path, int name)
+-{
+-	return solaris_fpathconf(0, name);
+-}
+-
+-/* solaris_llseek returns long long - quite difficult */
+-asmlinkage long solaris_llseek(struct pt_regs *regs, u32 off_hi, u32 off_lo, int whence)
+-{
+-	int (*sys_llseek)(unsigned int, unsigned long, unsigned long, loff_t __user *, unsigned int) =
+-		(int (*)(unsigned int, unsigned long, unsigned long, loff_t __user *, unsigned int))SYS(_llseek);
+-	int ret;
+-	mm_segment_t old_fs = get_fs();
+-	loff_t retval;
+-	
+-	set_fs(KERNEL_DS);
+-	ret = sys_llseek((unsigned int)regs->u_regs[UREG_I0], off_hi, off_lo, &retval, whence);
+-	set_fs(old_fs);
+-	if (ret < 0) return ret;
+-	regs->u_regs[UREG_I1] = (u32)retval;
+-	return (retval >> 32);
+-}
+-
+-/* Have to mask out all but lower 3 bits */
+-asmlinkage int solaris_access(u32 filename, long mode)
+-{
+-	int (*sys_access)(const char __user *, int) = 
+-		(int (*)(const char __user *, int))SYS(access);
+-		
+-	return sys_access(A(filename), mode & 7);
+-}
+diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
+deleted file mode 100644
+index 8ad10a6..0000000
+--- a/arch/sparc64/solaris/ioctl.c
++++ /dev/null
+@@ -1,825 +0,0 @@
+-/* $Id: ioctl.c,v 1.17 2002/02/08 03:57:14 davem Exp $
+- * ioctl.c: Solaris ioctl emulation.
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1997,1998 Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)
+- *
+- * Streams & timod emulation based on code
+- * Copyright (C) 1995, 1996 Mike Jagdis (jaggy at purplet.demon.co.uk)
+- *
+- * 1999-08-19 Implemented solaris 'm' (mag tape) and
+- *            'O' (openprom) ioctls, by Jason Rappleye
+- *             (rappleye at ccr.buffalo.edu)
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/syscalls.h>
+-#include <linux/ioctl.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/netdevice.h>
+-#include <linux/mtio.h>
+-#include <linux/time.h>
+-#include <linux/rcupdate.h>
+-#include <linux/compat.h>
+-
+-#include <net/sock.h>
+-#include <net/net_namespace.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/termios.h>
+-#include <asm/openpromio.h>
+-
+-#include "conv.h"
+-#include "socksys.h"
+-
+-extern asmlinkage int compat_sys_ioctl(unsigned int fd, unsigned int cmd,
+-	u32 arg);
+-asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
+-
+-extern int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
+-			char __user *data_buf, int data_len, int flags);
+-extern int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, int __user *ctl_len,
+-			char __user *data_buf, int data_maxlen, int __user *data_len, int *flags);
+-
+-/* termio* stuff {{{ */
+-
+-struct solaris_termios {
+-	u32	c_iflag;
+-	u32	c_oflag;
+-	u32	c_cflag;
+-	u32	c_lflag;
+-	u8	c_cc[19];
+-};
+-
+-struct solaris_termio {
+-	u16	c_iflag;
+-	u16	c_oflag;
+-	u16	c_cflag;
+-	u16	c_lflag;
+-	s8	c_line;
+-	u8	c_cc[8];
+-};
+-
+-struct solaris_termiox {
+-	u16	x_hflag;
+-	u16	x_cflag;
+-	u16	x_rflag[5];
+-	u16	x_sflag;
+-};
+-
+-static u32 solaris_to_linux_cflag(u32 cflag)
+-{
+-	cflag &= 0x7fdff000;
+-	if (cflag & 0x200000) {
+-		int baud = cflag & 0xf;
+-		cflag &= ~0x20000f;
+-		switch (baud) {
+-		case 0: baud = B57600; break;
+-		case 1: baud = B76800; break;
+-		case 2: baud = B115200; break;
+-		case 3: baud = B153600; break;
+-		case 4: baud = B230400; break;
+-		case 5: baud = B307200; break;
+-		case 6: baud = B460800; break;
+-		}
+-		cflag |= CBAUDEX | baud;
+-	}
+-	return cflag;
+-}
+-
+-static u32 linux_to_solaris_cflag(u32 cflag)
+-{
+-	cflag &= ~(CMSPAR | CIBAUD);
+-	if (cflag & CBAUDEX) {
+-		int baud = cflag & CBAUD;
+-		cflag &= ~CBAUD;
+-		switch (baud) {
+-		case B57600: baud = 0; break;
+-		case B76800: baud = 1; break;
+-		case B115200: baud = 2; break;
+-		case B153600: baud = 3; break;
+-		case B230400: baud = 4; break;
+-		case B307200: baud = 5; break;
+-		case B460800: baud = 6; break;
+-		case B614400: baud = 7; break;
+-		case B921600: baud = 8; break;
+-#if 0		
+-		case B1843200: baud = 9; break;
+-#endif
+-		}
+-		cflag |= 0x200000 | baud;
+-	}
+-	return cflag;
+-}
+-
+-static inline int linux_to_solaris_termio(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	struct solaris_termio __user *p = A(arg);
+-	int ret;
+-	
+-	ret = sys_ioctl(fd, cmd, (unsigned long)p);
+-	if (!ret) {
+-		u32 cflag;
+-		
+-		if (__get_user (cflag, &p->c_cflag))
+-			return -EFAULT;
+-		cflag = linux_to_solaris_cflag(cflag);
+-		if (__put_user (cflag, &p->c_cflag))
+-			return -EFAULT;
+-	}
+-	return ret;
+-}
+-
+-static int solaris_to_linux_termio(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	int ret;
+-	struct solaris_termio s;
+-	mm_segment_t old_fs = get_fs();
+-	
+-	if (copy_from_user (&s, (struct solaris_termio __user *)A(arg), sizeof(struct solaris_termio)))
+-		return -EFAULT;
+-	s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
+-	set_fs(KERNEL_DS);
+-	ret = sys_ioctl(fd, cmd, (unsigned long)&s);
+-	set_fs(old_fs);
+-	return ret;
+-}
+-
+-static inline int linux_to_solaris_termios(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	int ret;
+-	struct solaris_termios s;
+-	mm_segment_t old_fs = get_fs();
+-
+-	set_fs(KERNEL_DS);	
+-	ret = sys_ioctl(fd, cmd, (unsigned long)&s);
+-	set_fs(old_fs);
+-	if (!ret) {
+-		struct solaris_termios __user *p = A(arg);
+-		if (put_user (s.c_iflag, &p->c_iflag) ||
+-		    __put_user (s.c_oflag, &p->c_oflag) ||
+-		    __put_user (linux_to_solaris_cflag(s.c_cflag), &p->c_cflag) ||
+-		    __put_user (s.c_lflag, &p->c_lflag) ||
+-		    __copy_to_user (p->c_cc, s.c_cc, 16) ||
+-		    __clear_user (p->c_cc + 16, 2))
+-			return -EFAULT;
+-	}
+-	return ret;
+-}
+-
+-static int solaris_to_linux_termios(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	int ret;
+-	struct solaris_termios s;
+-	struct solaris_termios __user *p = A(arg);
+-	mm_segment_t old_fs = get_fs();
+-
+-	set_fs(KERNEL_DS);
+-	ret = sys_ioctl(fd, TCGETS, (unsigned long)&s);
+-	set_fs(old_fs);
+-	if (ret) return ret;
+-	if (put_user (s.c_iflag, &p->c_iflag) ||
+-	    __put_user (s.c_oflag, &p->c_oflag) ||
+-	    __put_user (s.c_cflag, &p->c_cflag) ||
+-	    __put_user (s.c_lflag, &p->c_lflag) ||
+-	    __copy_from_user (s.c_cc, p->c_cc, 16))
+-		return -EFAULT;
+-	s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
+-	set_fs(KERNEL_DS);
+-	ret = sys_ioctl(fd, cmd, (unsigned long)&s);
+-	set_fs(old_fs);
+-	return ret;
+-}
+-
+-static inline int solaris_T(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	switch (cmd & 0xff) {
+-	case 1: /* TCGETA */
+-		return linux_to_solaris_termio(fd, TCGETA, arg);
+-	case 2: /* TCSETA */
+-		return solaris_to_linux_termio(fd, TCSETA, arg);
+-	case 3: /* TCSETAW */
+-		return solaris_to_linux_termio(fd, TCSETAW, arg);
+-	case 4: /* TCSETAF */
+-		return solaris_to_linux_termio(fd, TCSETAF, arg);
+-	case 5: /* TCSBRK */
+-		return sys_ioctl(fd, TCSBRK, arg);
+-	case 6: /* TCXONC */
+-		return sys_ioctl(fd, TCXONC, arg);
+-	case 7: /* TCFLSH */
+-		return sys_ioctl(fd, TCFLSH, arg);
+-	case 13: /* TCGETS */
+-		return linux_to_solaris_termios(fd, TCGETS, arg);
+-	case 14: /* TCSETS */
+-		return solaris_to_linux_termios(fd, TCSETS, arg);
+-	case 15: /* TCSETSW */
+-		return solaris_to_linux_termios(fd, TCSETSW, arg);
+-	case 16: /* TCSETSF */
+-		return solaris_to_linux_termios(fd, TCSETSF, arg);
+-	case 103: /* TIOCSWINSZ */
+-		return sys_ioctl(fd, TIOCSWINSZ, arg);
+-	case 104: /* TIOCGWINSZ */
+-		return sys_ioctl(fd, TIOCGWINSZ, arg);
+-	}
+-	return -ENOSYS;
+-}
+-
+-static inline int solaris_t(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	switch (cmd & 0xff) {
+-	case 20: /* TIOCGPGRP */
+-		return sys_ioctl(fd, TIOCGPGRP, arg);
+-	case 21: /* TIOCSPGRP */
+-		return sys_ioctl(fd, TIOCSPGRP, arg);
+-	}
+-	return -ENOSYS;
+-}
+-
+-/* }}} */
+-
+-/* A pseudo STREAMS support {{{ */
+-
+-struct strioctl {
+-	int cmd, timeout, len;
+-	u32 data;
+-};
+-
+-struct solaris_si_sockparams {
+-	int sp_family;
+-	int sp_type;
+-	int sp_protocol;
+-};
+-
+-struct solaris_o_si_udata {
+-	int tidusize;
+-	int addrsize;
+-	int optsize;
+-	int etsdusize;
+-	int servtype;
+-	int so_state;
+-	int so_options;
+-	int tsdusize;
+-};
+-
+-struct solaris_si_udata {
+-	int tidusize;
+-	int addrsize;
+-	int optsize;
+-	int etsdusize;
+-	int servtype;
+-	int so_state;
+-	int so_options;
+-	int tsdusize;
+-	struct solaris_si_sockparams sockparams;
+-};
+-
+-#define SOLARIS_MODULE_TIMOD    0
+-#define SOLARIS_MODULE_SOCKMOD  1
+-#define SOLARIS_MODULE_MAX      2
+-
+-static struct module_info {
+-        const char *name;
+-        /* can be expanded further if needed */
+-} module_table[ SOLARIS_MODULE_MAX + 1 ] = {
+-        /* the ordering here must match the module numbers above! */
+-        { "timod" },
+-        { "sockmod" },
+-        { NULL }
+-};
+-
+-static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	struct inode *ino;
+-	struct fdtable *fdt;
+-	/* I wonder which of these tests are superfluous... --patrik */
+-	rcu_read_lock();
+-	fdt = files_fdtable(current->files);
+-	if (! fdt->fd[fd] ||
+-	    ! fdt->fd[fd]->f_path.dentry ||
+-	    ! (ino = fdt->fd[fd]->f_path.dentry->d_inode) ||
+-	    ! S_ISSOCK(ino->i_mode)) {
+-		rcu_read_unlock();
+-		return TBADF;
+-	}
+-	rcu_read_unlock();
+-	
+-	switch (cmd & 0xff) {
+-	case 109: /* SI_SOCKPARAMS */
+-	{
+-		struct solaris_si_sockparams si;
+-		if (copy_from_user (&si, A(arg), sizeof(si)))
+-			return (EFAULT << 8) | TSYSERR;
+-
+-		/* Should we modify socket ino->socket_i.ops and type? */
+-		return 0;
+-	}
+-	case 110: /* SI_GETUDATA */
+-	{
+-		int etsdusize, servtype;
+-		struct solaris_si_udata __user *p = A(arg);
+-		switch (SOCKET_I(ino)->type) {
+-		case SOCK_STREAM:
+-			etsdusize = 1;
+-			servtype = 2;
+-			break;
+-		default:
+-			etsdusize = -2;
+-			servtype = 3;
+-			break;
+-		}
+-		if (put_user(16384, &p->tidusize) ||
+-		    __put_user(sizeof(struct sockaddr), &p->addrsize) ||
+-		    __put_user(-1, &p->optsize) ||
+-		    __put_user(etsdusize, &p->etsdusize) ||
+-		    __put_user(servtype, &p->servtype) ||
+-		    __put_user(0, &p->so_state) ||
+-		    __put_user(0, &p->so_options) ||
+-		    __put_user(16384, &p->tsdusize) ||
+-		    __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_family) ||
+-		    __put_user(SOCKET_I(ino)->type, &p->sockparams.sp_type) ||
+-		    __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_protocol))
+-			return (EFAULT << 8) | TSYSERR;
+-		return 0;
+-	}
+-	case 101: /* O_SI_GETUDATA */
+-	{
+-		int etsdusize, servtype;
+-		struct solaris_o_si_udata __user *p = A(arg);
+-		switch (SOCKET_I(ino)->type) {
+-		case SOCK_STREAM:
+-			etsdusize = 1;
+-			servtype = 2;
+-			break;
+-		default:
+-			etsdusize = -2;
+-			servtype = 3;
+-			break;
+-		}
+-		if (put_user(16384, &p->tidusize) ||
+-		    __put_user(sizeof(struct sockaddr), &p->addrsize) ||
+-		    __put_user(-1, &p->optsize) ||
+-		    __put_user(etsdusize, &p->etsdusize) ||
+-		    __put_user(servtype, &p->servtype) ||
+-		    __put_user(0, &p->so_state) ||
+-		    __put_user(0, &p->so_options) ||
+-		    __put_user(16384, &p->tsdusize))
+-			return (EFAULT << 8) | TSYSERR;
+-		return 0;
+-	}
+-	case 102: /* SI_SHUTDOWN */
+-	case 103: /* SI_LISTEN */
+-	case 104: /* SI_SETMYNAME */
+-	case 105: /* SI_SETPEERNAME */
+-	case 106: /* SI_GETINTRANSIT */
+-	case 107: /* SI_TCL_LINK */
+-	case 108: /* SI_TCL_UNLINK */
+-		;
+-	}
+-	return TNOTSUPPORT;
+-}
+-
+-static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
+-                                    int len, int __user *len_p)
+-{
+-	int ret;
+-		
+-	switch (cmd & 0xff) {
+-	case 141: /* TI_OPTMGMT */
+-	{
+-		int i;
+-		u32 prim;
+-		SOLD("TI_OPMGMT entry");
+-		ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0);
+-		SOLD("timod_putmsg() returned");
+-		if (ret)
+-			return (-ret << 8) | TSYSERR;
+-		i = MSG_HIPRI;
+-		SOLD("calling timod_getmsg()");
+-		ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i);
+-		SOLD("timod_getmsg() returned");
+-		if (ret)
+-			return (-ret << 8) | TSYSERR;
+-		SOLD("ret ok");
+-		if (get_user(prim, (u32 __user *)A(arg)))
+-			return (EFAULT << 8) | TSYSERR;
+-		SOLD("got prim");
+-		if (prim == T_ERROR_ACK) {
+-			u32 tmp, tmp2;
+-			SOLD("prim is T_ERROR_ACK");
+-			if (get_user(tmp, (u32 __user *)A(arg)+3) ||
+-			    get_user(tmp2, (u32 __user *)A(arg)+2))
+-				return (EFAULT << 8) | TSYSERR;
+-			return (tmp2 << 8) | tmp;
+-		}
+-		SOLD("TI_OPMGMT return 0");
+-		return 0;
+-	}
+-	case 142: /* TI_BIND */
+-	{
+-		int i;
+-		u32 prim;
+-		SOLD("TI_BIND entry");
+-		ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0);
+-		SOLD("timod_putmsg() returned");
+-		if (ret)
+-			return (-ret << 8) | TSYSERR;
+-		len = 1024; /* Solaris allows arbitrary return size */
+-		i = MSG_HIPRI;
+-		SOLD("calling timod_getmsg()");
+-		ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i);
+-		SOLD("timod_getmsg() returned");
+-		if (ret)
+-			return (-ret << 8) | TSYSERR;
+-		SOLD("ret ok");
+-		if (get_user(prim, (u32 __user *)A(arg)))
+-			return (EFAULT << 8) | TSYSERR;
+-		SOLD("got prim");
+-		if (prim == T_ERROR_ACK) {
+-			u32 tmp, tmp2;
+-			SOLD("prim is T_ERROR_ACK");
+-			if (get_user(tmp, (u32 __user *)A(arg)+3) ||
+-			    get_user(tmp2, (u32 __user *)A(arg)+2))
+-				return (EFAULT << 8) | TSYSERR;
+-			return (tmp2 << 8) | tmp;
+-		}
+-		SOLD("no ERROR_ACK requested");
+-		if (prim != T_OK_ACK)
+-			return TBADSEQ;
+-		SOLD("OK_ACK requested");
+-		i = MSG_HIPRI;
+-		SOLD("calling timod_getmsg()");
+-		ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i);
+-		SOLD("timod_getmsg() returned");
+-		if (ret)
+-			return (-ret << 8) | TSYSERR;
+-		SOLD("TI_BIND return ok");
+-		return 0;
+-	}
+-	case 140: /* TI_GETINFO */
+-	case 143: /* TI_UNBIND */
+-	case 144: /* TI_GETMYNAME */
+-	case 145: /* TI_GETPEERNAME */
+-	case 146: /* TI_SETMYNAME */
+-	case 147: /* TI_SETPEERNAME */
+-		;
+-	}
+-	return TNOTSUPPORT;
+-}
+-
+-static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	char *p;
+-	int ret;
+-	mm_segment_t old_fs;
+-	struct strioctl si;
+-	struct inode *ino;
+-        struct sol_socket_struct *sock;
+-        struct module_info *mi;
+-
+-        ino = filp->f_path.dentry->d_inode;
+-        if (!S_ISSOCK(ino->i_mode))
+-		return -EBADF;
+-        sock = filp->private_data;
+-        if (! sock) {
+-                printk("solaris_S: NULL private_data\n");
+-                return -EBADF;
+-        }
+-        if (sock->magic != SOLARIS_SOCKET_MAGIC) {
+-                printk("solaris_S: invalid magic\n");
+-                return -EBADF;
+-        }
+-        
+-
+-	switch (cmd & 0xff) {
+-	case 1: /* I_NREAD */
+-		return -ENOSYS;
+-	case 2: /* I_PUSH */
+-        {
+-		p = getname (A(arg));
+-		if (IS_ERR (p))
+-			return PTR_ERR(p);
+-                ret = -EINVAL;
+-                for (mi = module_table; mi->name; mi++) {
+-                        if (strcmp(mi->name, p) == 0) {
+-                                sol_module m;
+-                                if (sock->modcount >= MAX_NR_STREAM_MODULES) {
+-                                        ret = -ENXIO;
+-                                        break;
+-                                }
+-                                m = (sol_module) (mi - module_table);
+-                                sock->module[sock->modcount++] = m;
+-                                ret = 0;
+-                                break;
+-                        }
+-                }
+-		putname (p);
+-		return ret;
+-        }
+-	case 3: /* I_POP */
+-                if (sock->modcount <= 0) return -EINVAL;
+-                sock->modcount--;
+-		return 0;
+-        case 4: /* I_LOOK */
+-        {
+-        	const char *p;
+-                if (sock->modcount <= 0) return -EINVAL;
+-                p = module_table[(unsigned)sock->module[sock->modcount]].name;
+-                if (copy_to_user (A(arg), p, strlen(p)))
+-                	return -EFAULT;
+-                return 0;
+-        }
+-	case 5: /* I_FLUSH */
+-		return 0;
+-	case 8: /* I_STR */
+-		if (copy_from_user(&si, A(arg), sizeof(struct strioctl)))
+-			return -EFAULT;
+-                /* We ignore what module is actually at the top of stack. */
+-		switch ((si.cmd >> 8) & 0xff) {
+-		case 'I':
+-                        return solaris_sockmod(fd, si.cmd, si.data);
+-		case 'T':
+-                        return solaris_timod(fd, si.cmd, si.data, si.len,
+-				&((struct strioctl __user *)A(arg))->len);
+-		default:
+-			return solaris_ioctl(fd, si.cmd, si.data);
+-		}
+-	case 9: /* I_SETSIG */
+-		return sys_ioctl(fd, FIOSETOWN, current->pid);
+-	case 10: /* I_GETSIG */
+-		old_fs = get_fs();
+-		set_fs(KERNEL_DS);
+-		sys_ioctl(fd, FIOGETOWN, (unsigned long)&ret);
+-		set_fs(old_fs);
+-		if (ret == current->pid) return 0x3ff;
+-		else return -EINVAL;
+-	case 11: /* I_FIND */
+-        {
+-                int i;
+-		p = getname (A(arg));
+-		if (IS_ERR (p))
+-			return PTR_ERR(p);
+-                ret = 0;
+-                for (i = 0; i < sock->modcount; i++) {
+-                        unsigned m = sock->module[i];
+-                        if (strcmp(module_table[m].name, p) == 0) {
+-                                ret = 1;
+-                                break;
+-                        } 
+-                }
+-		putname (p);
+-		return ret;
+-        }
+-	case 19: /* I_SWROPT */
+-	case 32: /* I_SETCLTIME */
+-		return 0;	/* Lie */
+-	}
+-	return -ENOSYS;
+-}
+-
+-static inline int solaris_s(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	switch (cmd & 0xff) {
+-	case 0: /* SIOCSHIWAT */
+-	case 2: /* SIOCSLOWAT */
+-		return 0; /* We don't support them */
+-	case 1: /* SIOCGHIWAT */
+-	case 3: /* SIOCGLOWAT */
+-		if (put_user (0, (u32 __user *)A(arg)))
+-			return -EFAULT;
+-		return 0; /* Lie */
+-	case 7: /* SIOCATMARK */
+-		return sys_ioctl(fd, SIOCATMARK, arg);
+-	case 8: /* SIOCSPGRP */
+-		return sys_ioctl(fd, SIOCSPGRP, arg);
+-	case 9: /* SIOCGPGRP */
+-		return sys_ioctl(fd, SIOCGPGRP, arg);
+-	}
+-	return -ENOSYS;
+-}
+-
+-static inline int solaris_r(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	switch (cmd & 0xff) {
+-	case 10: /* SIOCADDRT */
+-		return compat_sys_ioctl(fd, SIOCADDRT, arg);
+-	case 11: /* SIOCDELRT */
+-		return compat_sys_ioctl(fd, SIOCDELRT, arg);
+-	}
+-	return -ENOSYS;
+-}
+-
+-static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	switch (cmd & 0xff) {
+-	case 12: /* SIOCSIFADDR */
+-		return compat_sys_ioctl(fd, SIOCSIFADDR, arg);
+-	case 13: /* SIOCGIFADDR */
+-		return compat_sys_ioctl(fd, SIOCGIFADDR, arg);
+-	case 14: /* SIOCSIFDSTADDR */
+-		return compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg);
+-	case 15: /* SIOCGIFDSTADDR */
+-		return compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg);
+-	case 16: /* SIOCSIFFLAGS */
+-		return compat_sys_ioctl(fd, SIOCSIFFLAGS, arg);
+-	case 17: /* SIOCGIFFLAGS */
+-		return compat_sys_ioctl(fd, SIOCGIFFLAGS, arg);
+-	case 18: /* SIOCSIFMEM */
+-		return compat_sys_ioctl(fd, SIOCSIFMEM, arg);
+-	case 19: /* SIOCGIFMEM */
+-		return compat_sys_ioctl(fd, SIOCGIFMEM, arg);
+-	case 20: /* SIOCGIFCONF */
+-		return compat_sys_ioctl(fd, SIOCGIFCONF, arg);
+-	case 21: /* SIOCSIFMTU */
+-		return compat_sys_ioctl(fd, SIOCSIFMTU, arg);
+-	case 22: /* SIOCGIFMTU */
+-		return compat_sys_ioctl(fd, SIOCGIFMTU, arg);
+-	case 23: /* SIOCGIFBRDADDR */
+-		return compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg);
+-	case 24: /* SIOCSIFBRDADDR */
+-		return compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg);
+-	case 25: /* SIOCGIFNETMASK */
+-		return compat_sys_ioctl(fd, SIOCGIFNETMASK, arg);
+-	case 26: /* SIOCSIFNETMASK */
+-		return compat_sys_ioctl(fd, SIOCSIFNETMASK, arg);
+-	case 27: /* SIOCGIFMETRIC */
+-		return compat_sys_ioctl(fd, SIOCGIFMETRIC, arg);
+-	case 28: /* SIOCSIFMETRIC */
+-		return compat_sys_ioctl(fd, SIOCSIFMETRIC, arg);
+-	case 30: /* SIOCSARP */
+-		return compat_sys_ioctl(fd, SIOCSARP, arg);
+-	case 31: /* SIOCGARP */
+-		return compat_sys_ioctl(fd, SIOCGARP, arg);
+-	case 32: /* SIOCDARP */
+-		return compat_sys_ioctl(fd, SIOCDARP, arg);
+-	case 52: /* SIOCGETNAME */
+-	case 53: /* SIOCGETPEER */
+-		{
+-			struct sockaddr uaddr;
+-			int uaddr_len = sizeof(struct sockaddr), ret;
+-			long args[3];
+-			mm_segment_t old_fs = get_fs();
+-			int (*sys_socketcall)(int, unsigned long *) =
+-				(int (*)(int, unsigned long *))SYS(socketcall);
+-			
+-			args[0] = fd; args[1] = (long)&uaddr; args[2] = (long)&uaddr_len;
+-			set_fs(KERNEL_DS);
+-			ret = sys_socketcall(((cmd & 0xff) == 52) ? SYS_GETSOCKNAME : SYS_GETPEERNAME,
+-					args);
+-			set_fs(old_fs);
+-			if (ret >= 0) {
+-				if (copy_to_user(A(arg), &uaddr, uaddr_len))
+-					return -EFAULT;
+-			}
+-			return ret;
+-		}
+-#if 0		
+-	case 86: /* SIOCSOCKSYS */
+-		return socksys_syscall(fd, arg);
+-#endif		
+-	case 87: /* SIOCGIFNUM */
+-		{
+-			struct net_device *d;
+-			int i = 0;
+-			
+-			read_lock_bh(&dev_base_lock);
+-			for_each_netdev(&init_net, d)
+-				i++;
+-			read_unlock_bh(&dev_base_lock);
+-
+-			if (put_user (i, (int __user *)A(arg)))
+-				return -EFAULT;
+-			return 0;
+-		}
+-	}
+-	return -ENOSYS;
+-}
+-
+-static int solaris_m(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	int ret;
+-
+-	switch (cmd & 0xff) {
+-	case 1: /* MTIOCTOP */
+-		ret = sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg);
+-		break;
+-	case 2: /* MTIOCGET */
+-		ret = sys_ioctl(fd, MTIOCGET, (unsigned long)&arg);
+-		break;
+-	case 3: /* MTIOCGETDRIVETYPE */
+-	case 4: /* MTIOCPERSISTENT */
+-	case 5: /* MTIOCPERSISTENTSTATUS */
+-	case 6: /* MTIOCLRERR */
+-	case 7: /* MTIOCGUARANTEEDORDER */
+-	case 8: /* MTIOCRESERVE */
+-	case 9: /* MTIOCRELEASE */
+-	case 10: /* MTIOCFORCERESERVE */
+-	case 13: /* MTIOCSTATE */
+-	case 14: /* MTIOCREADIGNOREILI */
+-	case 15: /* MTIOCREADIGNOREEOFS */
+-	case 16: /* MTIOCSHORTFMK */
+-	default:
+-		ret = -ENOSYS; /* linux doesn't support these */
+-		break;
+-	};
+-
+-	return ret;
+-}
+-
+-static int solaris_O(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	int ret = -EINVAL;
+-
+-	switch (cmd & 0xff) {
+-	case 1: /* OPROMGETOPT */
+-		ret = sys_ioctl(fd, OPROMGETOPT, arg);
+-		break;
+-	case 2: /* OPROMSETOPT */
+-		ret = sys_ioctl(fd, OPROMSETOPT, arg);
+-		break;
+-	case 3: /* OPROMNXTOPT */
+-		ret = sys_ioctl(fd, OPROMNXTOPT, arg);
+-		break;
+-	case 4: /* OPROMSETOPT2 */
+-		ret = sys_ioctl(fd, OPROMSETOPT2, arg);
+-		break;
+-	case 5: /* OPROMNEXT */
+-		ret = sys_ioctl(fd, OPROMNEXT, arg);
+-		break;
+-	case 6: /* OPROMCHILD */
+-		ret = sys_ioctl(fd, OPROMCHILD, arg);
+-		break;
+-	case 7: /* OPROMGETPROP */
+-		ret = sys_ioctl(fd, OPROMGETPROP, arg);
+-		break;
+-	case 8: /* OPROMNXTPROP */
+-		ret = sys_ioctl(fd, OPROMNXTPROP, arg);
+-		break;
+-	case 9: /* OPROMU2P */
+-		ret = sys_ioctl(fd, OPROMU2P, arg);
+-		break;
+-	case 10: /* OPROMGETCONS */
+-		ret = sys_ioctl(fd, OPROMGETCONS, arg);
+-		break;
+-	case 11: /* OPROMGETFBNAME */
+-		ret = sys_ioctl(fd, OPROMGETFBNAME, arg);
+-		break;
+-	case 12: /* OPROMGETBOOTARGS */
+-		ret = sys_ioctl(fd, OPROMGETBOOTARGS, arg);
+-		break;
+-	case 13: /* OPROMGETVERSION */
+-	case 14: /* OPROMPATH2DRV */
+-	case 15: /* OPROMDEV2PROMNAME */
+-	case 16: /* OPROMPROM2DEVNAME */
+-	case 17: /* OPROMGETPROPLEN */
+-	default:
+-		ret = -EINVAL;
+-		break;
+-	};
+-	return ret;
+-}
+-
+-/* }}} */
+-
+-asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+-	struct file *filp;
+-	int error = -EBADF;
+-
+-	filp = fget(fd);
+-	if (!filp)
+-		goto out;
+-
+-	lock_kernel();
+-	error = -EFAULT;
+-	switch ((cmd >> 8) & 0xff) {
+-	case 'S': error = solaris_S(filp, fd, cmd, arg); break;
+-	case 'T': error = solaris_T(fd, cmd, arg); break;
+-	case 'i': error = solaris_i(fd, cmd, arg); break;
+-	case 'r': error = solaris_r(fd, cmd, arg); break;
+-	case 's': error = solaris_s(fd, cmd, arg); break;
+-	case 't': error = solaris_t(fd, cmd, arg); break;
+-	case 'f': error = sys_ioctl(fd, cmd, arg); break;
+-	case 'm': error = solaris_m(fd, cmd, arg); break;
+-	case 'O': error = solaris_O(fd, cmd, arg); break;
+-	default:
+-		error = -ENOSYS;
+-		break;
+-	}
+-	unlock_kernel();
+-	fput(filp);
+-out:
+-	if (error == -ENOSYS) {
+-		unsigned char c = cmd>>8;
+-		
+-		if (c < ' ' || c > 126) c = '.';
+-		printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)\n",
+-		       (int)fd, (unsigned int)cmd, c, (unsigned int)arg);
+-		error = -EINVAL;
+-	}
+-	return error;
+-}
+diff --git a/arch/sparc64/solaris/ipc.c b/arch/sparc64/solaris/ipc.c
+deleted file mode 100644
+index 499135f..0000000
+--- a/arch/sparc64/solaris/ipc.c
++++ /dev/null
+@@ -1,126 +0,0 @@
+-/* $Id: ipc.c,v 1.5 1999/12/09 00:41:00 davem Exp $
+- * ipc.c: Solaris IPC emulation
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/wait.h>
+-#include <linux/mm.h>
+-#include <linux/shm.h>
+-#include <linux/sem.h>
+-#include <linux/msg.h>
+-#include <linux/ipc.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/string.h>
+-
+-#include "conv.h"
+-
+-struct solaris_ipc_perm {
+-	s32	uid;
+-	s32	gid;
+-	s32	cuid;
+-	s32	cgid;
+-	u32	mode;
+-	u32	seq;
+-	int	key;
+-	s32	pad[4];
+-};
+-
+-struct solaris_shmid_ds {
+-	struct solaris_ipc_perm	shm_perm;
+-	int			shm_segsz;
+-	u32			shm_amp;
+-	unsigned short		shm_lkcnt;
+-	char			__padxx[2];
+-	s32			shm_lpid;
+-	s32			shm_cpid;
+-	u32			shm_nattch;
+-	u32			shm_cnattch;
+-	s32			shm_atime;
+-	s32			shm_pad1;
+-	s32			shm_dtime;
+-	s32			shm_pad2;
+-	s32			shm_ctime;
+-	s32			shm_pad3;
+-	unsigned short		shm_cv;
+-	char			shm_pad4[2];
+-	u32			shm_sptas;
+-	s32			shm_pad5[2];
+-};
+-
+-asmlinkage long solaris_shmsys(int cmd, u32 arg1, u32 arg2, u32 arg3)
+-{
+-	int (*sys_ipc)(unsigned,int,int,unsigned long,void __user *,long) = 
+-		(int (*)(unsigned,int,int,unsigned long,void __user *,long))SYS(ipc);
+-	mm_segment_t old_fs;
+-	unsigned long raddr;
+-	int ret;
+-		
+-	switch (cmd) {
+-	case 0: /* shmat */
+-		old_fs = get_fs();
+-		set_fs(KERNEL_DS);
+-		ret = sys_ipc(SHMAT, arg1, arg3 & ~0x4000, (unsigned long)&raddr, A(arg2), 0);
+-		set_fs(old_fs);
+-		if (ret >= 0) return (u32)raddr;
+-		else return ret;
+-	case 1: /* shmctl */
+-		switch (arg2) {
+-		case 3: /* SHM_LOCK */
+-		case 4: /* SHM_UNLOCK */
+-			return sys_ipc(SHMCTL, arg1, (arg2 == 3) ? SHM_LOCK : SHM_UNLOCK, 0, NULL, 0);
+-		case 10: /* IPC_RMID */
+-			return sys_ipc(SHMCTL, arg1, IPC_RMID, 0, NULL, 0);
+-		case 11: /* IPC_SET */
+-			{
+-				struct shmid_ds s;
+-				struct solaris_shmid_ds __user *p = A(arg3);
+-				
+-				if (get_user (s.shm_perm.uid, &p->shm_perm.uid) ||
+-				    __get_user (s.shm_perm.gid, &p->shm_perm.gid) || 
+-				    __get_user (s.shm_perm.mode, &p->shm_perm.mode))
+-					return -EFAULT;
+-				old_fs = get_fs();
+-				set_fs(KERNEL_DS);
+-				ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0);
+-				set_fs(old_fs);
+-				return ret;
+-			}
+-		case 12: /* IPC_STAT */
+-			{
+-				struct shmid_ds s;
+-				struct solaris_shmid_ds __user *p = A(arg3);
+-				
+-				old_fs = get_fs();
+-				set_fs(KERNEL_DS);
+-				ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0);
+-				set_fs(old_fs);
+-				if (put_user (s.shm_perm.uid, &(p->shm_perm.uid)) ||
+-				    __put_user (s.shm_perm.gid, &(p->shm_perm.gid)) || 
+-				    __put_user (s.shm_perm.cuid, &(p->shm_perm.cuid)) ||
+-				    __put_user (s.shm_perm.cgid, &(p->shm_perm.cgid)) || 
+-				    __put_user (s.shm_perm.mode, &(p->shm_perm.mode)) ||
+-				    __put_user (s.shm_perm.seq, &(p->shm_perm.seq)) ||
+-				    __put_user (s.shm_perm.key, &(p->shm_perm.key)) ||
+-				    __put_user (s.shm_segsz, &(p->shm_segsz)) ||
+-				    __put_user (s.shm_lpid, &(p->shm_lpid)) ||
+-				    __put_user (s.shm_cpid, &(p->shm_cpid)) ||
+-				    __put_user (s.shm_nattch, &(p->shm_nattch)) ||
+-				    __put_user (s.shm_atime, &(p->shm_atime)) ||
+-				    __put_user (s.shm_dtime, &(p->shm_dtime)) ||
+-				    __put_user (s.shm_ctime, &(p->shm_ctime)))
+-					return -EFAULT;
+-				return ret;
+-			}
+-		default: return -EINVAL;
+-		}
+-	case 2: /* shmdt */
+-		return sys_ipc(SHMDT, 0, 0, 0, A(arg1), 0);
+-	case 3: /* shmget */
+-		return sys_ipc(SHMGET, arg1, arg2, arg3, NULL, 0);
+-	}
+-	return -EINVAL;
+-}
+diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
+deleted file mode 100644
+index d3e48e9..0000000
+--- a/arch/sparc64/solaris/misc.c
++++ /dev/null
+@@ -1,786 +0,0 @@
+-/* $Id: misc.c,v 1.36 2002/02/09 19:49:31 davem Exp $
+- * misc.c: Miscellaneous syscall emulation for Solaris
+- *
+- * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-
+-#include <linux/module.h> 
+-#include <linux/types.h>
+-#include <linux/utsname.h>
+-#include <linux/limits.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/tty.h>
+-#include <linux/mman.h>
+-#include <linux/file.h>
+-#include <linux/timex.h>
+-#include <linux/major.h>
+-#include <linux/compat.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/string.h>
+-#include <asm/oplib.h>
+-#include <asm/idprom.h>
+-#include <asm/smp.h>
+-#include <asm/prom.h>
+-
+-#include "conv.h"
+-
+-/* Conversion from Linux to Solaris errnos. 0-34 are identity mapped.
+-   Some Linux errnos (EPROCLIM, EDOTDOT, ERREMOTE, EUCLEAN, ENOTNAM, 
+-   ENAVAIL, EISNAM, EREMOTEIO, ENOMEDIUM, EMEDIUMTYPE) have no Solaris
+-   equivalents. I return EINVAL in that case, which is very wrong. If
+-   someone suggest a better value for them, you're welcomed.
+-   On the other side, Solaris ECANCELED and ENOTSUP have no Linux equivalents,
+-   but that doesn't matter here. --jj */
+-int solaris_err_table[] = {
+-/* 0 */  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+-/* 10 */  10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+-/* 20 */  20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+-/* 30 */  30, 31, 32, 33, 34, 22, 150, 149, 95, 96,
+-/* 40 */  97, 98, 99, 120, 121, 122, 123, 124, 125, 126, 
+-/* 50 */ 127, 128, 129, 130, 131, 132, 133, 134, 143, 144,
+-/* 60 */ 145, 146, 90, 78, 147, 148, 93, 22, 94, 49,
+-/* 70 */ 151, 66, 60, 62, 63, 35, 77, 36, 45, 46, 
+-/* 80 */ 64, 22, 67, 68, 69, 70, 71, 74, 22, 82, 
+-/* 90 */ 89, 92, 79, 81, 37, 38, 39, 40, 41, 42,
+-/* 100 */ 43, 44, 50, 51, 52, 53, 54, 55, 56, 57,
+-/* 110 */ 87, 61, 84, 65, 83, 80, 91, 22, 22, 22,
+-/* 120 */ 22, 22, 88, 86, 85, 22, 22,
+-};
+-
+-#define SOLARIS_NR_OPEN	256
+-
+-static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 off)
+-{
+-	struct file *file = NULL;
+-	unsigned long retval, ret_type;
+-
+-	/* Do we need it here? */
+-	set_personality(PER_SVR4);
+-	if (flags & MAP_NORESERVE) {
+-		static int cnt;
+-		
+-		if (cnt < 5) {
+-			printk("%s:  unimplemented Solaris MAP_NORESERVE mmap() flag\n",
+-			       current->comm);
+-			cnt++;
+-		}
+-		flags &= ~MAP_NORESERVE;
+-	}
+-	retval = -EBADF;
+-	if(!(flags & MAP_ANONYMOUS)) {
+-		if(fd >= SOLARIS_NR_OPEN)
+-			goto out;
+- 		file = fget(fd);
+-		if (!file)
+-			goto out;
+-		else {
+-			struct inode * inode = file->f_path.dentry->d_inode;
+-			if(imajor(inode) == MEM_MAJOR &&
+-			   iminor(inode) == 5) {
+-				flags |= MAP_ANONYMOUS;
+-				fput(file);
+-				file = NULL;
+-			}
+-		}
+-	}
+-
+-	retval = -EINVAL;
+-	len = PAGE_ALIGN(len);
+-	if(!(flags & MAP_FIXED))
+-		addr = 0;
+-	else if (len > STACK_TOP32 || addr > STACK_TOP32 - len)
+-		goto out_putf;
+-	ret_type = flags & _MAP_NEW;
+-	flags &= ~_MAP_NEW;
+-
+-	down_write(&current->mm->mmap_sem);
+-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+-	retval = do_mmap(file,
+-			 (unsigned long) addr, (unsigned long) len,
+-			 (unsigned long) prot, (unsigned long) flags, off);
+-	up_write(&current->mm->mmap_sem);
+-	if(!ret_type)
+-		retval = ((retval < STACK_TOP32) ? 0 : retval);
+-	                        
+-out_putf:
+-	if (file)
+-		fput(file);
+-out:
+-	return (u32) retval;
+-}
+-
+-asmlinkage u32 solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
+-{
+-	return do_solaris_mmap(addr, len, prot, flags, fd, (u64) off);
+-}
+-
+-asmlinkage u32 solaris_mmap64(struct pt_regs *regs, u32 len, u32 prot, u32 flags, u32 fd, u32 offhi)
+-{
+-	u32 offlo;
+-	
+-	if (regs->u_regs[UREG_G1]) {
+-		if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c)))
+-			return -EFAULT;
+-	} else {
+-		if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x60)))
+-			return -EFAULT;
+-	}
+-	return do_solaris_mmap((u32)regs->u_regs[UREG_I0], len, prot, flags, fd, (((u64)offhi)<<32)|offlo);
+-}
+-
+-asmlinkage int solaris_brk(u32 brk)
+-{
+-	int (*sunos_brk)(u32) = (int (*)(u32))SUNOS(17);
+-	
+-	return sunos_brk(brk);
+-}
+-
+-static int __set_utsfield(char __user *to, int to_size,
+-			  const char *from, int from_size,
+-			  int dotchop, int countfrom)
+-{
+-	int len = countfrom ? (to_size > from_size ?
+-			       from_size : to_size) : to_size;
+-	int off;
+-
+-	if (copy_to_user(to, from, len))
+-		return -EFAULT;
+-
+-	off = len < to_size? len: len - 1;
+-	if (dotchop) {
+-		const char *p = strnchr(from, len, '.');
+-		if (p) off = p - from;
+-	}
+-
+-	if (__put_user('\0', to + off))
+-		return -EFAULT;
+-
+-	return 0;
+-}
+-
+-#define set_utsfield(to, from, dotchop, countfrom) \
+-	__set_utsfield((to), sizeof(to), \
+-		       (from), sizeof(from), \
+-		       (dotchop), (countfrom))
+-
+-struct sol_uname {
+-	char sysname[9];
+-	char nodename[9];
+-	char release[9];
+-	char version[9];
+-	char machine[9];
+-};
+-
+-struct sol_utsname {
+-	char sysname[257];
+-	char nodename[257];
+-	char release[257];
+-	char version[257];
+-	char machine[257];
+-};
+-
+-static char *machine(void)
+-{
+-	switch (sparc_cpu_model) {
+-	case sun4: return "sun4";
+-	case sun4c: return "sun4c";
+-	case sun4e: return "sun4e";
+-	case sun4m: return "sun4m";
+-	case sun4d: return "sun4d";
+-	case sun4u: return "sun4u";
+-	default: return "sparc";
+-	}
+-}
+-
+-static char *platform(char *buffer, int sz)
+-{
+-	struct device_node *dp = of_find_node_by_path("/");
+-	int len;
+-
+-	*buffer = 0;
+-	len = strlen(dp->name);
+-	if (len > sz)
+-		len = sz;
+-	memcpy(buffer, dp->name, len);
+-	buffer[len] = 0;
+-	if (*buffer) {
+-		char *p;
+-
+-		for (p = buffer; *p; p++)
+-			if (*p == '/' || *p == ' ') *p = '_';
+-		return buffer;
+-	}
+-
+-	return "sun4u";
+-}
+-
+-static char *serial(char *buffer, int sz)
+-{
+-	struct device_node *dp = of_find_node_by_path("/options");
+-	int len;
+-
+-	*buffer = 0;
+-	if (dp) {
+-		const char *val =
+-			of_get_property(dp, "system-board-serial#", &len);
+-
+-		if (val && len > 0) {
+-			if (len > sz)
+-				len = sz;
+-			memcpy(buffer, val, len);
+-			buffer[len] = 0;
+-		}
+-	}
+-	if (!*buffer)
+-		return "4512348717234";
+-	else
+-		return buffer;
+-}
+-
+-asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
+-{
+-	struct sol_uname __user *v = A(buf);
+-	int err;
+-
+-	switch (which) {
+-	case 0:	/* old uname */
+-		/* Let's cheat */
+-		err  = set_utsfield(v->sysname, "SunOS", 1, 0);
+-		down_read(&uts_sem);
+-		err |= set_utsfield(v->nodename, utsname()->nodename,
+-				    1, 1);
+-		up_read(&uts_sem);
+-		err |= set_utsfield(v->release, "2.6", 0, 0);
+-		err |= set_utsfield(v->version, "Generic", 0, 0);
+-		err |= set_utsfield(v->machine, machine(), 0, 0);
+-		return (err ? -EFAULT : 0);
+-	case 2: /* ustat */
+-		return -ENOSYS;
+-	case 3: /* fusers */
+-		return -ENOSYS;
+-	default:
+-		return -ENOSYS;
+-	}
+-}
+-
+-asmlinkage int solaris_utsname(u32 buf)
+-{
+-	struct sol_utsname __user *v = A(buf);
+-	int err;
+-
+-	/* Why should we not lie a bit? */
+-	down_read(&uts_sem);
+-	err  = set_utsfield(v->sysname, "SunOS", 0, 0);
+-	err |= set_utsfield(v->nodename, utsname()->nodename, 1, 1);
+-	err |= set_utsfield(v->release, "5.6", 0, 0);
+-	err |= set_utsfield(v->version, "Generic", 0, 0);
+-	err |= set_utsfield(v->machine, machine(), 0, 0);
+-	up_read(&uts_sem);
+-
+-	return (err ? -EFAULT : 0);
+-}
+-
+-#define SI_SYSNAME		1       /* return name of operating system */
+-#define SI_HOSTNAME		2       /* return name of node */
+-#define SI_RELEASE		3       /* return release of operating system */
+-#define SI_VERSION		4       /* return version field of utsname */
+-#define SI_MACHINE		5       /* return kind of machine */
+-#define SI_ARCHITECTURE		6       /* return instruction set arch */
+-#define SI_HW_SERIAL		7       /* return hardware serial number */
+-#define SI_HW_PROVIDER		8       /* return hardware manufacturer */
+-#define SI_SRPC_DOMAIN		9       /* return secure RPC domain */
+-#define SI_PLATFORM		513     /* return platform identifier */
+-
+-asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count)
+-{
+-	char *p, *q, *r;
+-	char buffer[256];
+-	int len;
+-	
+-	/* Again, we cheat :)) */
+-	switch (cmd) {
+-	case SI_SYSNAME: r = "SunOS"; break;
+-	case SI_HOSTNAME:
+-		r = buffer + 256;
+-		down_read(&uts_sem);
+-		for (p = utsname()->nodename, q = buffer;
+-		     q < r && *p && *p != '.'; *q++ = *p++);
+-		up_read(&uts_sem);
+-		*q = 0;
+-		r = buffer;
+-		break;
+-	case SI_RELEASE: r = "5.6"; break;
+-	case SI_MACHINE: r = machine(); break;
+-	case SI_ARCHITECTURE: r = "sparc"; break;
+-	case SI_HW_PROVIDER: r = "Sun_Microsystems"; break;
+-	case SI_HW_SERIAL: r = serial(buffer, sizeof(buffer)); break;
+-	case SI_PLATFORM: r = platform(buffer, sizeof(buffer)); break;
+-	case SI_SRPC_DOMAIN: r = ""; break;
+-	case SI_VERSION: r = "Generic"; break;
+-	default: return -EINVAL;
+-	}
+-	len = strlen(r) + 1;
+-	if (count < len) {
+-		if (copy_to_user(A(buf), r, count - 1) ||
+-		    __put_user(0, (char __user *)A(buf) + count - 1))
+-			return -EFAULT;
+-	} else {
+-		if (copy_to_user(A(buf), r, len))
+-			return -EFAULT;
+-	}
+-	return len;
+-}
+-
+-#define	SOLARIS_CONFIG_NGROUPS			2
+-#define	SOLARIS_CONFIG_CHILD_MAX		3
+-#define	SOLARIS_CONFIG_OPEN_FILES		4
+-#define	SOLARIS_CONFIG_POSIX_VER		5
+-#define	SOLARIS_CONFIG_PAGESIZE			6
+-#define	SOLARIS_CONFIG_CLK_TCK			7
+-#define	SOLARIS_CONFIG_XOPEN_VER		8
+-#define	SOLARIS_CONFIG_PROF_TCK			10
+-#define	SOLARIS_CONFIG_NPROC_CONF		11
+-#define	SOLARIS_CONFIG_NPROC_ONLN		12
+-#define	SOLARIS_CONFIG_AIO_LISTIO_MAX		13
+-#define	SOLARIS_CONFIG_AIO_MAX			14
+-#define	SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX	15
+-#define	SOLARIS_CONFIG_DELAYTIMER_MAX		16
+-#define	SOLARIS_CONFIG_MQ_OPEN_MAX		17
+-#define	SOLARIS_CONFIG_MQ_PRIO_MAX		18
+-#define	SOLARIS_CONFIG_RTSIG_MAX		19
+-#define	SOLARIS_CONFIG_SEM_NSEMS_MAX		20
+-#define	SOLARIS_CONFIG_SEM_VALUE_MAX		21
+-#define	SOLARIS_CONFIG_SIGQUEUE_MAX		22
+-#define	SOLARIS_CONFIG_SIGRT_MIN		23
+-#define	SOLARIS_CONFIG_SIGRT_MAX		24
+-#define	SOLARIS_CONFIG_TIMER_MAX		25
+-#define	SOLARIS_CONFIG_PHYS_PAGES		26
+-#define	SOLARIS_CONFIG_AVPHYS_PAGES		27
+-
+-asmlinkage int solaris_sysconf(int id)
+-{
+-	switch (id) {
+-	case SOLARIS_CONFIG_NGROUPS:	return NGROUPS_MAX;
+-	case SOLARIS_CONFIG_CHILD_MAX:
+-		return current->signal->rlim[RLIMIT_NPROC].rlim_cur;
+-	case SOLARIS_CONFIG_OPEN_FILES:
+-		return current->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+-	case SOLARIS_CONFIG_POSIX_VER:	return 199309;
+-	case SOLARIS_CONFIG_PAGESIZE:	return PAGE_SIZE;
+-	case SOLARIS_CONFIG_XOPEN_VER:	return 3;
+-	case SOLARIS_CONFIG_CLK_TCK:
+-	case SOLARIS_CONFIG_PROF_TCK:
+-		return sparc64_get_clock_tick(smp_processor_id());
+-#ifdef CONFIG_SMP	
+-	case SOLARIS_CONFIG_NPROC_CONF:	return NR_CPUS;
+-	case SOLARIS_CONFIG_NPROC_ONLN:	return num_online_cpus();
+-#else
+-	case SOLARIS_CONFIG_NPROC_CONF:	return 1;
+-	case SOLARIS_CONFIG_NPROC_ONLN:	return 1;
+-#endif
+-	case SOLARIS_CONFIG_SIGRT_MIN:		return 37;
+-	case SOLARIS_CONFIG_SIGRT_MAX:		return 44;
+-	case SOLARIS_CONFIG_PHYS_PAGES:
+-	case SOLARIS_CONFIG_AVPHYS_PAGES:
+-		{
+-			struct sysinfo s;
+-			
+-			si_meminfo(&s);
+-			if (id == SOLARIS_CONFIG_PHYS_PAGES)
+-				return s.totalram >>= PAGE_SHIFT;
+-			else
+-				return s.freeram >>= PAGE_SHIFT;
+-		}
+-	/* XXX support these as well -jj */
+-	case SOLARIS_CONFIG_AIO_LISTIO_MAX:	return -EINVAL;
+-	case SOLARIS_CONFIG_AIO_MAX:		return -EINVAL;
+-	case SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX:	return -EINVAL;
+-	case SOLARIS_CONFIG_DELAYTIMER_MAX:	return -EINVAL;
+-	case SOLARIS_CONFIG_MQ_OPEN_MAX:	return -EINVAL;
+-	case SOLARIS_CONFIG_MQ_PRIO_MAX:	return -EINVAL;
+-	case SOLARIS_CONFIG_RTSIG_MAX:		return -EINVAL;
+-	case SOLARIS_CONFIG_SEM_NSEMS_MAX:	return -EINVAL;
+-	case SOLARIS_CONFIG_SEM_VALUE_MAX:	return -EINVAL;
+-	case SOLARIS_CONFIG_SIGQUEUE_MAX:	return -EINVAL;
+-	case SOLARIS_CONFIG_TIMER_MAX:		return -EINVAL;
+-	default: return -EINVAL;
+-	}
+-}
+-
+-asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
+-{
+-	int ret;
+-	
+-	switch (cmd) {
+-	case 0: /* getpgrp */
+-		return task_pgrp_vnr(current);
+-	case 1: /* setpgrp */
+-		{
+-			int (*sys_setpgid)(pid_t,pid_t) =
+-				(int (*)(pid_t,pid_t))SYS(setpgid);
+-				
+-			/* can anyone explain me the difference between
+-			   Solaris setpgrp and setsid? */
+-			ret = sys_setpgid(0, 0);
+-			if (ret) return ret;
+-			proc_clear_tty(current);
+-			return task_pgrp_vnr(current);
+-		}
+-	case 2: /* getsid */
+-		{
+-			int (*sys_getsid)(pid_t) = (int (*)(pid_t))SYS(getsid);
+-			return sys_getsid(pid);
+-		}
+-	case 3: /* setsid */
+-		{
+-			int (*sys_setsid)(void) = (int (*)(void))SYS(setsid);
+-			return sys_setsid();
+-		}
+-	case 4: /* getpgid */
+-		{
+-			int (*sys_getpgid)(pid_t) = (int (*)(pid_t))SYS(getpgid);
+-			return sys_getpgid(pid);
+-		}
+-	case 5: /* setpgid */
+-		{
+-			int (*sys_setpgid)(pid_t,pid_t) = 
+-				(int (*)(pid_t,pid_t))SYS(setpgid);
+-			return sys_setpgid(pid,pgid);
+-		}
+-	}
+-	return -EINVAL;
+-}
+-
+-asmlinkage int solaris_gettimeofday(u32 tim)
+-{
+-	int (*sys_gettimeofday)(struct timeval *, struct timezone *) =
+-		(int (*)(struct timeval *, struct timezone *))SYS(gettimeofday);
+-		
+-	return sys_gettimeofday((struct timeval *)(u64)tim, NULL);
+-}
+-
+-#define RLIM_SOL_INFINITY32	0x7fffffff
+-#define RLIM_SOL_SAVED_MAX32	0x7ffffffe
+-#define RLIM_SOL_SAVED_CUR32	0x7ffffffd
+-#define RLIM_SOL_INFINITY	((u64)-3)
+-#define RLIM_SOL_SAVED_MAX	((u64)-2)
+-#define RLIM_SOL_SAVED_CUR	((u64)-1)
+-#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
+-#define RLIMIT_SOL_NOFILE	5
+-#define RLIMIT_SOL_VMEM		6
+-
+-struct rlimit32 {
+-	u32	rlim_cur;
+-	u32	rlim_max;
+-};
+-
+-asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 __user *rlim)
+-{
+-	struct rlimit r;
+-	int ret;
+-	mm_segment_t old_fs = get_fs ();
+-	int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+-		(int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+-
+-	if (resource > RLIMIT_SOL_VMEM)
+-		return -EINVAL;	
+-	switch (resource) {
+-	case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+-	case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+-	default: break;
+-	}
+-	set_fs (KERNEL_DS);
+-	ret = sys_getrlimit(resource, &r);
+-	set_fs (old_fs);
+-	if (!ret) {
+-		if (r.rlim_cur == RLIM_INFINITY)
+-			r.rlim_cur = RLIM_SOL_INFINITY32;
+-		else if ((u64)r.rlim_cur > RLIM_SOL_INFINITY32)
+-			r.rlim_cur = RLIM_SOL_SAVED_CUR32;
+-		if (r.rlim_max == RLIM_INFINITY)
+-			r.rlim_max = RLIM_SOL_INFINITY32;
+-		else if ((u64)r.rlim_max > RLIM_SOL_INFINITY32)
+-			r.rlim_max = RLIM_SOL_SAVED_MAX32;
+-		ret = put_user (r.rlim_cur, &rlim->rlim_cur);
+-		ret |= __put_user (r.rlim_max, &rlim->rlim_max);
+-	}
+-	return ret;
+-}
+-
+-asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 __user *rlim)
+-{
+-	struct rlimit r, rold;
+-	int ret;
+-	mm_segment_t old_fs = get_fs ();
+-	int (*sys_getrlimit)(unsigned int, struct rlimit __user *) =
+-		(int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit);
+-	int (*sys_setrlimit)(unsigned int, struct rlimit __user *) =
+-		(int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit);
+-
+-	if (resource > RLIMIT_SOL_VMEM)
+-		return -EINVAL;	
+-	switch (resource) {
+-	case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+-	case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+-	default: break;
+-	}
+-	if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+-	    __get_user (r.rlim_max, &rlim->rlim_max))
+-		return -EFAULT;
+-	set_fs (KERNEL_DS);
+-	ret = sys_getrlimit(resource, &rold);
+-	if (!ret) {
+-		if (r.rlim_cur == RLIM_SOL_INFINITY32)
+-			r.rlim_cur = RLIM_INFINITY;
+-		else if (r.rlim_cur == RLIM_SOL_SAVED_CUR32)
+-			r.rlim_cur = rold.rlim_cur;
+-		else if (r.rlim_cur == RLIM_SOL_SAVED_MAX32)
+-			r.rlim_cur = rold.rlim_max;
+-		if (r.rlim_max == RLIM_SOL_INFINITY32)
+-			r.rlim_max = RLIM_INFINITY;
+-		else if (r.rlim_max == RLIM_SOL_SAVED_CUR32)
+-			r.rlim_max = rold.rlim_cur;
+-		else if (r.rlim_max == RLIM_SOL_SAVED_MAX32)
+-			r.rlim_max = rold.rlim_max;
+-		ret = sys_setrlimit(resource, &r);
+-	}
+-	set_fs (old_fs);
+-	return ret;
+-}
+-
+-asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit __user *rlim)
+-{
+-	struct rlimit r;
+-	int ret;
+-	mm_segment_t old_fs = get_fs ();
+-	int (*sys_getrlimit)(unsigned int, struct rlimit __user *) =
+-		(int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit);
+-
+-	if (resource > RLIMIT_SOL_VMEM)
+-		return -EINVAL;	
+-	switch (resource) {
+-	case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+-	case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+-	default: break;
+-	}
+-	set_fs (KERNEL_DS);
+-	ret = sys_getrlimit(resource, &r);
+-	set_fs (old_fs);
+-	if (!ret) {
+-		if (r.rlim_cur == RLIM_INFINITY)
+-			r.rlim_cur = RLIM_SOL_INFINITY;
+-		if (r.rlim_max == RLIM_INFINITY)
+-			r.rlim_max = RLIM_SOL_INFINITY;
+-		ret = put_user (r.rlim_cur, &rlim->rlim_cur);
+-		ret |= __put_user (r.rlim_max, &rlim->rlim_max);
+-	}
+-	return ret;
+-}
+-
+-asmlinkage int solaris_setrlimit64(unsigned int resource, struct rlimit __user *rlim)
+-{
+-	struct rlimit r, rold;
+-	int ret;
+-	mm_segment_t old_fs = get_fs ();
+-	int (*sys_getrlimit)(unsigned int, struct rlimit __user *) =
+-		(int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit);
+-	int (*sys_setrlimit)(unsigned int, struct rlimit __user *) =
+-		(int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit);
+-
+-	if (resource > RLIMIT_SOL_VMEM)
+-		return -EINVAL;	
+-	switch (resource) {
+-	case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+-	case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+-	default: break;
+-	}
+-	if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+-	    __get_user (r.rlim_max, &rlim->rlim_max))
+-		return -EFAULT;
+-	set_fs (KERNEL_DS);
+-	ret = sys_getrlimit(resource, &rold);
+-	if (!ret) {
+-		if (r.rlim_cur == RLIM_SOL_INFINITY)
+-			r.rlim_cur = RLIM_INFINITY;
+-		else if (r.rlim_cur == RLIM_SOL_SAVED_CUR)
+-			r.rlim_cur = rold.rlim_cur;
+-		else if (r.rlim_cur == RLIM_SOL_SAVED_MAX)
+-			r.rlim_cur = rold.rlim_max;
+-		if (r.rlim_max == RLIM_SOL_INFINITY)
+-			r.rlim_max = RLIM_INFINITY;
+-		else if (r.rlim_max == RLIM_SOL_SAVED_CUR)
+-			r.rlim_max = rold.rlim_cur;
+-		else if (r.rlim_max == RLIM_SOL_SAVED_MAX)
+-			r.rlim_max = rold.rlim_max;
+-		ret = sys_setrlimit(resource, &r);
+-	}
+-	set_fs (old_fs);
+-	return ret;
+-}
+-
+-struct sol_ntptimeval {
+-	struct compat_timeval time;
+-	s32 maxerror;
+-	s32 esterror;
+-};
+-
+-struct sol_timex {
+-	u32 modes;
+-	s32 offset;
+-	s32 freq;
+-	s32 maxerror;
+-	s32 esterror;
+-	s32 status;
+-	s32 constant;
+-	s32 precision;
+-	s32 tolerance;
+-	s32 ppsfreq;
+-	s32 jitter;
+-	s32 shift;
+-	s32 stabil;
+-	s32 jitcnt;
+-	s32 calcnt;
+-	s32 errcnt;
+-	s32 stbcnt;
+-};
+-
+-asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval __user *ntp)
+-{
+-	int (*sys_adjtimex)(struct timex __user *) =
+-		(int (*)(struct timex __user *))SYS(adjtimex);
+-	struct timex t;
+-	int ret;
+-	mm_segment_t old_fs = get_fs();
+-	
+-	set_fs(KERNEL_DS);
+-	t.modes = 0;
+-	ret = sys_adjtimex(&t);
+-	set_fs(old_fs);
+-	if (ret < 0)
+-		return ret;
+-	ret = put_user (t.time.tv_sec, &ntp->time.tv_sec);
+-	ret |= __put_user (t.time.tv_usec, &ntp->time.tv_usec);
+-	ret |= __put_user (t.maxerror, &ntp->maxerror);
+-	ret |= __put_user (t.esterror, &ntp->esterror);
+-	return ret;	                        
+-}
+-
+-asmlinkage int solaris_ntp_adjtime(struct sol_timex __user *txp)
+-{
+-	int (*sys_adjtimex)(struct timex __user *) =
+-		(int (*)(struct timex __user *))SYS(adjtimex);
+-	struct timex t;
+-	int ret, err;
+-	mm_segment_t old_fs = get_fs();
+-
+-	ret = get_user (t.modes, &txp->modes);
+-	ret |= __get_user (t.offset, &txp->offset);
+-	ret |= __get_user (t.freq, &txp->freq);
+-	ret |= __get_user (t.maxerror, &txp->maxerror);
+-	ret |= __get_user (t.esterror, &txp->esterror);
+-	ret |= __get_user (t.status, &txp->status);
+-	ret |= __get_user (t.constant, &txp->constant);
+-	set_fs(KERNEL_DS);
+-	ret = sys_adjtimex(&t);
+-	set_fs(old_fs);
+-	if (ret < 0)
+-		return ret;
+-	err = put_user (t.offset, &txp->offset);
+-	err |= __put_user (t.freq, &txp->freq);
+-	err |= __put_user (t.maxerror, &txp->maxerror);
+-	err |= __put_user (t.esterror, &txp->esterror);
+-	err |= __put_user (t.status, &txp->status);
+-	err |= __put_user (t.constant, &txp->constant);
+-	err |= __put_user (t.precision, &txp->precision);
+-	err |= __put_user (t.tolerance, &txp->tolerance);
+-	err |= __put_user (t.ppsfreq, &txp->ppsfreq);
+-	err |= __put_user (t.jitter, &txp->jitter);
+-	err |= __put_user (t.shift, &txp->shift);
+-	err |= __put_user (t.stabil, &txp->stabil);
+-	err |= __put_user (t.jitcnt, &txp->jitcnt);
+-	err |= __put_user (t.calcnt, &txp->calcnt);
+-	err |= __put_user (t.errcnt, &txp->errcnt);
+-	err |= __put_user (t.stbcnt, &txp->stbcnt);
+-	if (err)
+-		return -EFAULT;
+-	return ret;
+-}
+-
+-asmlinkage int do_sol_unimplemented(struct pt_regs *regs)
+-{
+-	printk ("Unimplemented Solaris syscall %d %08x %08x %08x %08x\n", 
+-			(int)regs->u_regs[UREG_G1], 
+-			(int)regs->u_regs[UREG_I0],
+-			(int)regs->u_regs[UREG_I1],
+-			(int)regs->u_regs[UREG_I2],
+-			(int)regs->u_regs[UREG_I3]);
+-	return -ENOSYS;
+-}
+-
+-asmlinkage void solaris_register(void)
+-{
+-	set_personality(PER_SVR4);
+-}
+-
+-extern long solaris_to_linux_signals[], linux_to_solaris_signals[];
+-
+-struct exec_domain solaris_exec_domain = {
+-	.name =		"Solaris",
+-	.handler =	NULL,
+-	.pers_low =	1,		/* PER_SVR4 personality */
+-	.pers_high =	1,
+-	.signal_map =	solaris_to_linux_signals,
+-	.signal_invmap =linux_to_solaris_signals,
+-	.module =	THIS_MODULE,
+-	.next =		NULL
+-};
+-
+-extern int init_socksys(void);
+-
+-MODULE_AUTHOR("Jakub Jelinek (jj at ultra.linux.cz), Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)");
+-MODULE_DESCRIPTION("Solaris binary emulation module");
+-MODULE_LICENSE("GPL");
+-
+-extern u32 tl0_solaris[8];
+-#define update_ttable(x) 										\
+-	tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000;			\
+-	wmb();		\
+-	__asm__ __volatile__ ("flush %0" : : "r" (&tl0_solaris[3]))
+-
+-extern u32 solaris_sparc_syscall[];
+-extern u32 solaris_syscall[];
+-extern void cleanup_socksys(void);
+-
+-extern u32 entry64_personality_patch;
+-
+-static int __init solaris_init(void)
+-{
+-	int ret;
+-
+-	SOLDD(("Solaris module at %p\n", solaris_sparc_syscall));
+-	register_exec_domain(&solaris_exec_domain);
+-	if ((ret = init_socksys())) {
+-		unregister_exec_domain(&solaris_exec_domain);
+-		return ret;
+-	}
+-	update_ttable(solaris_sparc_syscall);
+-	entry64_personality_patch |=
+-		(offsetof(struct task_struct, personality) +
+-		 (sizeof(unsigned long) - 1));
+-	wmb();
+-	__asm__ __volatile__("flush %0"
+-			     : : "r" (&entry64_personality_patch));
+-	return 0;
+-}
+-
+-static void __exit solaris_exit(void)
+-{
+-	update_ttable(solaris_syscall);
+-	cleanup_socksys();
+-	unregister_exec_domain(&solaris_exec_domain);
+-}
+-
+-module_init(solaris_init);
+-module_exit(solaris_exit);
+diff --git a/arch/sparc64/solaris/signal.c b/arch/sparc64/solaris/signal.c
+deleted file mode 100644
+index de10c97..0000000
+--- a/arch/sparc64/solaris/signal.c
++++ /dev/null
+@@ -1,429 +0,0 @@
+-/* $Id: signal.c,v 1.7 2000/09/05 21:44:54 davem Exp $
+- * signal.c: Signal emulation for Solaris
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-
+-#include <linux/types.h>
+-#include <linux/errno.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/svr4.h>
+-#include <asm/string.h>
+-
+-#include "conv.h"
+-#include "signal.h"
+-
+-#define _S(nr) (1L<<((nr)-1))
+-
+-#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+-
+-long linux_to_solaris_signals[] = {
+-        0,
+-	SOLARIS_SIGHUP,		SOLARIS_SIGINT,	
+-	SOLARIS_SIGQUIT,	SOLARIS_SIGILL,
+-	SOLARIS_SIGTRAP,	SOLARIS_SIGIOT,
+-	SOLARIS_SIGEMT,		SOLARIS_SIGFPE,
+-	SOLARIS_SIGKILL,	SOLARIS_SIGBUS,
+-	SOLARIS_SIGSEGV,	SOLARIS_SIGSYS,
+-	SOLARIS_SIGPIPE,	SOLARIS_SIGALRM,
+-	SOLARIS_SIGTERM,	SOLARIS_SIGURG,
+-	SOLARIS_SIGSTOP,	SOLARIS_SIGTSTP,
+-	SOLARIS_SIGCONT,	SOLARIS_SIGCLD,
+-	SOLARIS_SIGTTIN,	SOLARIS_SIGTTOU,
+-	SOLARIS_SIGPOLL,	SOLARIS_SIGXCPU,
+-	SOLARIS_SIGXFSZ,	SOLARIS_SIGVTALRM,
+-	SOLARIS_SIGPROF,	SOLARIS_SIGWINCH,
+-	SOLARIS_SIGUSR1,	SOLARIS_SIGUSR1,
+-	SOLARIS_SIGUSR2,	-1,
+-};
+-
+-long solaris_to_linux_signals[] = {
+-        0,
+-        SIGHUP,		SIGINT,		SIGQUIT,	SIGILL,
+-        SIGTRAP,	SIGIOT,		SIGEMT,		SIGFPE,
+-        SIGKILL,	SIGBUS,		SIGSEGV,	SIGSYS,
+-        SIGPIPE,	SIGALRM,	SIGTERM,	SIGUSR1,
+-        SIGUSR2,	SIGCHLD,	-1,		SIGWINCH,
+-        SIGURG,		SIGPOLL,	SIGSTOP,	SIGTSTP,
+-        SIGCONT,	SIGTTIN,	SIGTTOU,	SIGVTALRM,
+-        SIGPROF,	SIGXCPU,	SIGXFSZ,        -1,
+-	-1,		-1,		-1,		-1,
+-	-1,		-1,		-1,		-1,
+-	-1,		-1,		-1,		-1,
+-};
+-
+-static inline long mapsig(long sig)
+-{
+-	if ((unsigned long)sig > SOLARIS_NSIGNALS)
+-		return -EINVAL;
+-	return solaris_to_linux_signals[sig];
+-}
+-
+-asmlinkage int solaris_kill(int pid, int sig)
+-{
+-	int (*sys_kill)(int,int) = 
+-		(int (*)(int,int))SYS(kill);
+-	int s = mapsig(sig);
+-	
+-	if (s < 0) return s;
+-	return sys_kill(pid, s);
+-}
+-
+-static long sig_handler(int sig, u32 arg, int one_shot)
+-{
+-	struct sigaction sa, old;
+-	int ret;
+-	mm_segment_t old_fs = get_fs();
+-	int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) = 
+-		(int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction);
+-	
+-	sigemptyset(&sa.sa_mask);
+-	sa.sa_restorer = NULL;
+-	sa.sa_handler = (__sighandler_t)A(arg);
+-	sa.sa_flags = 0;
+-	if (one_shot) sa.sa_flags = SA_ONESHOT | SA_NOMASK;
+-	set_fs (KERNEL_DS);
+-	ret = sys_sigaction(sig, (void __user *)&sa, (void __user *)&old);
+-	set_fs (old_fs);
+-	if (ret < 0) return ret;
+-	return (u32)(unsigned long)old.sa_handler;
+-}
+-
+-static inline long solaris_signal(int sig, u32 arg)
+-{
+-	return sig_handler (sig, arg, 1);
+-}
+-
+-static long solaris_sigset(int sig, u32 arg)
+-{
+-	if (arg != 2) /* HOLD */ {
+-		spin_lock_irq(&current->sighand->siglock);
+-		sigdelsetmask(&current->blocked, _S(sig));
+-		recalc_sigpending();
+-		spin_unlock_irq(&current->sighand->siglock);
+-		return sig_handler (sig, arg, 0);
+-	} else {
+-		spin_lock_irq(&current->sighand->siglock);
+-		sigaddsetmask(&current->blocked, (_S(sig) & ~_BLOCKABLE));
+-		recalc_sigpending();
+-		spin_unlock_irq(&current->sighand->siglock);
+-		return 0;
+-	}
+-}
+-
+-static inline long solaris_sighold(int sig)
+-{
+-	return solaris_sigset(sig, 2);
+-}
+-
+-static inline long solaris_sigrelse(int sig)
+-{
+-	spin_lock_irq(&current->sighand->siglock);
+-	sigdelsetmask(&current->blocked, _S(sig));
+-	recalc_sigpending();
+-	spin_unlock_irq(&current->sighand->siglock);
+-	return 0;
+-}
+-
+-static inline long solaris_sigignore(int sig)
+-{
+-	return sig_handler(sig, (u32)(unsigned long)SIG_IGN, 0);
+-}
+-
+-static inline long solaris_sigpause(int sig)
+-{
+-	printk ("Need to support solaris sigpause\n");
+-	return -ENOSYS;
+-}
+-
+-asmlinkage long solaris_sigfunc(int sig, u32 arg)
+-{
+-	int func = sig & ~0xff;
+-	
+-	sig = mapsig(sig & 0xff); 
+-	if (sig < 0) return sig; 
+-	switch (func) {
+-	case 0: return solaris_signal(sig, arg); 
+-	case 0x100: return solaris_sigset(sig, arg); 
+-	case 0x200: return solaris_sighold(sig);
+-	case 0x400: return solaris_sigrelse(sig); 
+-	case 0x800: return solaris_sigignore(sig); 
+-	case 0x1000: return solaris_sigpause(sig);
+-	}
+-	return -EINVAL;
+-}
+-
+-typedef struct {
+-	u32 __sigbits[4];
+-} sol_sigset_t;
+-
+-static inline int mapin(u32 *p, sigset_t *q)
+-{
+-	int i;
+-	u32 x;
+-	int sig;
+-	
+-	sigemptyset(q);
+-	x = p[0];
+-	for (i = 1; i <= SOLARIS_NSIGNALS; i++) {
+-		if (x & 1) {
+-			sig = solaris_to_linux_signals[i];
+-			if (sig == -1)
+-				return -EINVAL;
+-			sigaddsetmask(q, (1L << (sig - 1)));
+-		}
+-		x >>= 1;
+-		if (i == 32)
+-			x = p[1];
+-	}
+-	return 0;
+-}
+-
+-static inline int mapout(sigset_t *q, u32 *p)
+-{
+-	int i;
+-	int sig;
+-	
+-	p[0] = 0;
+-	p[1] = 0;
+-	for (i = 1; i <= 32; i++) {
+-		if (sigismember(q, sigmask(i))) {
+-			sig = linux_to_solaris_signals[i];
+-			if (sig == -1)
+-				return -EINVAL;
+-			if (sig > 32)
+-				p[1] |= 1L << (sig - 33);
+-			else
+-				p[0] |= 1L << (sig - 1);
+-		}
+-	}
+-	return 0;
+-}
+-
+-asmlinkage int solaris_sigprocmask(int how, u32 in, u32 out)
+-{
+-	sigset_t in_s, *ins, out_s, *outs;
+-	mm_segment_t old_fs = get_fs();
+-	int ret;
+-	int (*sys_sigprocmask)(int,sigset_t __user *,sigset_t __user *) = 
+-		(int (*)(int,sigset_t __user *,sigset_t __user *))SYS(sigprocmask);
+-	
+-	ins = NULL; outs = NULL;
+-	if (in) {
+-		u32 tmp[2];
+-		
+-		if (copy_from_user (tmp, (void __user *)A(in), 2*sizeof(u32)))
+-			return -EFAULT;
+-		ins = &in_s;
+-		if (mapin (tmp, ins)) return -EINVAL;
+-	}
+-	if (out) outs = &out_s;
+-	set_fs (KERNEL_DS);
+-	ret = sys_sigprocmask((how == 3) ? SIG_SETMASK : how,
+-				(void __user *)ins, (void __user *)outs);
+-	set_fs (old_fs);
+-	if (ret) return ret;
+-	if (out) {
+-		u32 tmp[4];
+-		
+-		tmp[2] = 0; tmp[3] = 0;
+-		if (mapout (outs, tmp)) return -EINVAL;
+-		if (copy_to_user((void __user *)A(out), tmp, 4*sizeof(u32)))
+-			return -EFAULT;
+-	}
+-	return 0;
+-}
+-
+-asmlinkage long do_sol_sigsuspend(u32 mask)
+-{
+-	sigset_t s;
+-	u32 tmp[2];
+-		
+-	if (copy_from_user (tmp, (sol_sigset_t __user *)A(mask), 2*sizeof(u32)))
+-		return -EFAULT;
+-	if (mapin (tmp, &s)) return -EINVAL;
+-	return (long)s.sig[0];
+-}
+-
+-struct sol_sigaction {
+-	int	sa_flags;
+-	u32	sa_handler;
+-	u32	sa_mask[4];
+-	int	sa_resv[2];
+-};
+-
+-asmlinkage int solaris_sigaction(int sig, u32 act, u32 old)
+-{
+-	u32 tmp, tmp2[4];
+-	struct sigaction s, s2;
+-	int ret;
+-	mm_segment_t old_fs = get_fs();
+-	struct sol_sigaction __user *p = (void __user *)A(old);
+-	int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) = 
+-		(int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction);
+-	
+-	sig = mapsig(sig); 
+-	if (sig < 0) {
+-		/* We cheat a little bit for Solaris only signals */
+-		if (old && clear_user(p, sizeof(struct sol_sigaction)))
+-			return -EFAULT;
+-		return 0;
+-	}
+-	if (act) {
+-		if (get_user (tmp, &p->sa_flags))
+-			return -EFAULT;
+-		s.sa_flags = 0;
+-		if (tmp & SOLARIS_SA_ONSTACK) s.sa_flags |= SA_STACK;
+-		if (tmp & SOLARIS_SA_RESTART) s.sa_flags |= SA_RESTART;
+-		if (tmp & SOLARIS_SA_NODEFER) s.sa_flags |= SA_NOMASK;
+-		if (tmp & SOLARIS_SA_RESETHAND) s.sa_flags |= SA_ONESHOT;
+-		if (tmp & SOLARIS_SA_NOCLDSTOP) s.sa_flags |= SA_NOCLDSTOP;
+-		if (get_user (tmp, &p->sa_handler) ||
+-		    copy_from_user (tmp2, &p->sa_mask, 2*sizeof(u32)))
+-			return -EFAULT;
+-		s.sa_handler = (__sighandler_t)A(tmp);
+-		if (mapin (tmp2, &s.sa_mask)) return -EINVAL;
+-		s.sa_restorer = NULL;
+-	}
+-	set_fs(KERNEL_DS);
+-	ret = sys_sigaction(sig, act ? (void __user *)&s : NULL,
+-				 old ? (void __user *)&s2 : NULL);
+-	set_fs(old_fs);
+-	if (ret) return ret;
+-	if (old) {
+-		if (mapout (&s2.sa_mask, tmp2)) return -EINVAL;
+-		tmp = 0; tmp2[2] = 0; tmp2[3] = 0;
+-		if (s2.sa_flags & SA_STACK) tmp |= SOLARIS_SA_ONSTACK;
+-		if (s2.sa_flags & SA_RESTART) tmp |= SOLARIS_SA_RESTART;
+-		if (s2.sa_flags & SA_NOMASK) tmp |= SOLARIS_SA_NODEFER;
+-		if (s2.sa_flags & SA_ONESHOT) tmp |= SOLARIS_SA_RESETHAND;
+-		if (s2.sa_flags & SA_NOCLDSTOP) tmp |= SOLARIS_SA_NOCLDSTOP;
+-		if (put_user (tmp, &p->sa_flags) ||
+-		    __put_user ((u32)(unsigned long)s2.sa_handler, &p->sa_handler) ||
+-		    copy_to_user (&p->sa_mask, tmp2, 4*sizeof(u32)))
+-			return -EFAULT;
+-	}
+-	return 0;
+-}
+-
+-asmlinkage int solaris_sigpending(int which, u32 set)
+-{
+-	sigset_t s;
+-	u32 tmp[4];
+-	switch (which) {
+-	case 1: /* sigpending */
+-		spin_lock_irq(&current->sighand->siglock);
+-		sigandsets(&s, &current->blocked, &current->pending.signal);
+-		recalc_sigpending();
+-		spin_unlock_irq(&current->sighand->siglock);
+-		break;
+-	case 2: /* sigfillset - I just set signals which have linux equivalents */
+-		sigfillset(&s);
+-		break;
+-	default: return -EINVAL;
+-	}
+-	if (mapout (&s, tmp)) return -EINVAL;
+-	tmp[2] = 0; tmp[3] = 0;
+-	if (copy_to_user ((u32 __user *)A(set), tmp, sizeof(tmp)))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+-asmlinkage int solaris_wait(u32 stat_loc)
+-{
+-	unsigned __user *p = (unsigned __user *)A(stat_loc);
+-	int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) =
+-		(int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4);
+-	int ret, status;
+-	
+-	ret = sys_wait4(-1, p, WUNTRACED, NULL);
+-	if (ret >= 0 && stat_loc) {
+-		if (get_user (status, p))
+-			return -EFAULT;
+-		if (((status - 1) & 0xffff) < 0xff)
+-			status = linux_to_solaris_signals[status & 0x7f] & 0x7f;
+-		else if ((status & 0xff) == 0x7f)
+-			status = (linux_to_solaris_signals[(status >> 8) & 0xff] << 8) | 0x7f;
+-		if (__put_user (status, p))
+-			return -EFAULT;
+-	}
+-	return ret;
+-}
+-
+-asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options)
+-{
+-	int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) =
+-		(int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4);
+-	int opts, status, ret;
+-	
+-	switch (idtype) {
+-	case 0: /* P_PID */ break;
+-	case 1: /* P_PGID */ pid = -pid; break;
+-	case 7: /* P_ALL */ pid = -1; break;
+-	default: return -EINVAL;
+-	}
+-	opts = 0;
+-	if (options & SOLARIS_WUNTRACED) opts |= WUNTRACED;
+-	if (options & SOLARIS_WNOHANG) opts |= WNOHANG;
+-	current->state = TASK_RUNNING;
+-	ret = sys_wait4(pid, (unsigned int __user *)A(info), opts, NULL);
+-	if (ret < 0) return ret;
+-	if (info) {
+-		struct sol_siginfo __user *s = (void __user *)A(info);
+-	
+-		if (get_user (status, (unsigned int __user *)A(info)))
+-			return -EFAULT;
+-
+-		if (__put_user (SOLARIS_SIGCLD, &s->si_signo) ||
+-		    __put_user (ret, &s->_data._proc._pid))
+-			return -EFAULT;
+-
+-		switch (status & 0xff) {
+-		case 0: ret = SOLARIS_CLD_EXITED;
+-			status = (status >> 8) & 0xff;
+-			break;
+-		case 0x7f:
+-			status = (status >> 8) & 0xff;
+-			switch (status) {
+-			case SIGSTOP:
+-			case SIGTSTP: ret = SOLARIS_CLD_STOPPED;
+-			default: ret = SOLARIS_CLD_EXITED;
+-			}
+-			status = linux_to_solaris_signals[status];
+-			break;
+-		default:
+-			if (status & 0x80) ret = SOLARIS_CLD_DUMPED;
+-			else ret = SOLARIS_CLD_KILLED;
+-			status = linux_to_solaris_signals[status & 0x7f];
+-			break;
+-		}
+-
+-		if (__put_user (ret, &s->si_code) ||
+-		    __put_user (status, &s->_data._proc._pdata._cld._status))
+-			return -EFAULT;
+-	}
+-	return 0;
+-}
+-
+-extern int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs);
+-extern int svr4_getcontext(svr4_ucontext_t *c, struct pt_regs *regs);
+-
+-asmlinkage int solaris_context(struct pt_regs *regs)
+-{
+-	switch ((unsigned)regs->u_regs[UREG_I0]) {
+-	case 0: /* getcontext */
+-		return svr4_getcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs);
+-	case 1: /* setcontext */
+-		return svr4_setcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs);
+-	default:
+-		return -EINVAL;
+-
+-	}
+-}
+-
+-asmlinkage int solaris_sigaltstack(u32 ss, u32 oss)
+-{
+-/* XXX Implement this soon */
+-	return 0;
+-}
+diff --git a/arch/sparc64/solaris/signal.h b/arch/sparc64/solaris/signal.h
+deleted file mode 100644
+index e915708..0000000
+--- a/arch/sparc64/solaris/signal.h
++++ /dev/null
+@@ -1,108 +0,0 @@
+-/* $Id: signal.h,v 1.3 1998/04/12 06:20:33 davem Exp $
+- * signal.h: Signal emulation for Solaris
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-    
+-#define SOLARIS_SIGHUP		1
+-#define SOLARIS_SIGINT		2
+-#define SOLARIS_SIGQUIT		3
+-#define SOLARIS_SIGILL		4
+-#define SOLARIS_SIGTRAP		5
+-#define SOLARIS_SIGIOT		6
+-#define SOLARIS_SIGEMT		7
+-#define SOLARIS_SIGFPE		8
+-#define SOLARIS_SIGKILL		9
+-#define SOLARIS_SIGBUS		10
+-#define SOLARIS_SIGSEGV		11
+-#define SOLARIS_SIGSYS		12
+-#define SOLARIS_SIGPIPE		13
+-#define SOLARIS_SIGALRM		14
+-#define SOLARIS_SIGTERM		15
+-#define SOLARIS_SIGUSR1		16
+-#define SOLARIS_SIGUSR2		17
+-#define SOLARIS_SIGCLD		18
+-#define SOLARIS_SIGPWR		19
+-#define SOLARIS_SIGWINCH	20
+-#define SOLARIS_SIGURG		21
+-#define SOLARIS_SIGPOLL		22
+-#define SOLARIS_SIGSTOP		23
+-#define SOLARIS_SIGTSTP		24
+-#define SOLARIS_SIGCONT		25
+-#define SOLARIS_SIGTTIN		26
+-#define SOLARIS_SIGTTOU		27
+-#define SOLARIS_SIGVTALRM	28
+-#define SOLARIS_SIGPROF		29
+-#define SOLARIS_SIGXCPU		30
+-#define SOLARIS_SIGXFSZ		31
+-#define SOLARIS_SIGWAITING	32
+-#define SOLARIS_SIGLWP		33
+-#define SOLARIS_SIGFREEZE	34
+-#define SOLARIS_SIGTHAW		35
+-#define SOLARIS_SIGCANCEL	36
+-#define SOLARIS_SIGRTMIN	37
+-#define SOLARIS_SIGRTMAX	44
+-#define SOLARIS_NSIGNALS	44
+-
+-
+-#define SOLARIS_SA_ONSTACK	1
+-#define SOLARIS_SA_RESETHAND	2
+-#define SOLARIS_SA_RESTART	4
+-#define SOLARIS_SA_SIGINFO	8
+-#define SOLARIS_SA_NODEFER	16
+-#define SOLARIS_SA_NOCLDWAIT	0x10000
+-#define SOLARIS_SA_NOCLDSTOP	0x20000
+-
+-struct sol_siginfo {
+-	int	si_signo;
+-	int	si_code;
+-	int	si_errno;
+-	union	{
+-		char	pad[128-3*sizeof(int)];
+-		struct { 
+-			s32	_pid;
+-			union {
+-				struct {
+-					s32	_uid;
+-					s32	_value;
+-				} _kill;
+-				struct {
+-					s32	_utime;
+-					int	_status;
+-					s32	_stime;
+-				} _cld;
+-			} _pdata;
+-		} _proc;
+-		struct { /* SIGSEGV, SIGBUS, SIGILL and SIGFPE */
+-			u32	_addr;
+-			int	_trapno;
+-		} _fault;
+-		struct { /* SIGPOLL, SIGXFSZ */
+-			int	_fd;
+-			s32	_band;
+-		} _file;
+-	} _data;
+-};
+-
+-#define SOLARIS_WUNTRACED	0x04
+-#define SOLARIS_WNOHANG		0x40
+-#define SOLARIS_WEXITED         0x01
+-#define SOLARIS_WTRAPPED        0x02
+-#define SOLARIS_WSTOPPED        WUNTRACED
+-#define SOLARIS_WCONTINUED      0x08
+-#define SOLARIS_WNOWAIT         0x80
+-
+-#define SOLARIS_TRAP_BRKPT      1
+-#define SOLARIS_TRAP_TRACE      2
+-#define SOLARIS_CLD_EXITED      1
+-#define SOLARIS_CLD_KILLED      2
+-#define SOLARIS_CLD_DUMPED      3
+-#define SOLARIS_CLD_TRAPPED     4
+-#define SOLARIS_CLD_STOPPED     5
+-#define SOLARIS_CLD_CONTINUED   6
+-#define SOLARIS_POLL_IN         1
+-#define SOLARIS_POLL_OUT        2
+-#define SOLARIS_POLL_MSG        3
+-#define SOLARIS_POLL_ERR        4
+-#define SOLARIS_POLL_PRI        5
+-#define SOLARIS_POLL_HUP        6
+diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
+deleted file mode 100644
+index cc69847..0000000
+--- a/arch/sparc64/solaris/socket.c
++++ /dev/null
+@@ -1,461 +0,0 @@
+-/* $Id: socket.c,v 1.6 2002/02/08 03:57:14 davem Exp $
+- * socket.c: Socket syscall emulation for Solaris 2.6+
+- *
+- * Copyright (C) 1998 Jakub Jelinek (jj at ultra.linux.cz)
+- *
+- * 1999-08-19 Fixed socketpair code 
+- *            Jason Rappleye (rappleye at ccr.buffalo.edu)
+- */
+-
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/slab.h>
+-#include <linux/socket.h>
+-#include <linux/file.h>
+-#include <linux/net.h>
+-#include <linux/compat.h>
+-#include <net/compat.h>
+-#include <net/sock.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/string.h>
+-#include <asm/oplib.h>
+-#include <asm/idprom.h>
+-
+-#include "conv.h"
+-
+-#define SOCK_SOL_STREAM		2
+-#define SOCK_SOL_DGRAM		1
+-#define SOCK_SOL_RAW		4
+-#define SOCK_SOL_RDM		5
+-#define SOCK_SOL_SEQPACKET	6
+-
+-#define SOL_SO_SNDLOWAT		0x1003
+-#define SOL_SO_RCVLOWAT		0x1004
+-#define SOL_SO_SNDTIMEO		0x1005
+-#define SOL_SO_RCVTIMEO		0x1006
+-#define SOL_SO_STATE		0x2000
+-
+-#define SOL_SS_NDELAY		0x040
+-#define SOL_SS_NONBLOCK		0x080
+-#define SOL_SS_ASYNC		0x100
+-
+-#define SO_STATE		0x000e
+-
+-static int socket_check(int family, int type)
+-{
+-	if (family != PF_UNIX && family != PF_INET)
+-		return -ESOCKTNOSUPPORT;
+-	switch (type) {
+-	case SOCK_SOL_STREAM: type = SOCK_STREAM; break;
+-	case SOCK_SOL_DGRAM: type = SOCK_DGRAM; break;
+-	case SOCK_SOL_RAW: type = SOCK_RAW; break;
+-	case SOCK_SOL_RDM: type = SOCK_RDM; break;
+-	case SOCK_SOL_SEQPACKET: type = SOCK_SEQPACKET; break;
+-	default: return -EINVAL;
+-	}
+-	return type;
+-}
+-
+-static int solaris_to_linux_sockopt(int optname) 
+-{
+-	switch (optname) {
+-	case SOL_SO_SNDLOWAT: optname = SO_SNDLOWAT; break;
+-	case SOL_SO_RCVLOWAT: optname = SO_RCVLOWAT; break;
+-	case SOL_SO_SNDTIMEO: optname = SO_SNDTIMEO; break;
+-	case SOL_SO_RCVTIMEO: optname = SO_RCVTIMEO; break;
+-	case SOL_SO_STATE: optname = SO_STATE; break;
+-	};
+-	
+-	return optname;
+-}
+-	
+-asmlinkage int solaris_socket(int family, int type, int protocol)
+-{
+-	int (*sys_socket)(int, int, int) =
+-		(int (*)(int, int, int))SYS(socket);
+-
+-	type = socket_check (family, type);
+-	if (type < 0) return type;
+-	return sys_socket(family, type, protocol);
+-}
+-
+-asmlinkage int solaris_socketpair(int *usockvec)
+-{
+-	int (*sys_socketpair)(int, int, int, int *) =
+-		(int (*)(int, int, int, int *))SYS(socketpair);
+-
+-	/* solaris socketpair really only takes one arg at the syscall
+-	 * level, int * usockvec. The libs apparently take care of 
+-	 * making sure that family==AF_UNIX and type==SOCK_STREAM. The 
+-	 * pointer we really want ends up residing in the first (and
+-	 * supposedly only) argument.
+-	 */
+-
+-	return sys_socketpair(AF_UNIX, SOCK_STREAM, 0, (int *)usockvec);
+-}
+-
+-asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen)
+-{
+-	int (*sys_bind)(int, struct sockaddr *, int) =
+-		(int (*)(int, struct sockaddr *, int))SUNOS(104);
+-
+-	return sys_bind(fd, addr, addrlen);
+-}
+-
+-asmlinkage int solaris_setsockopt(int fd, int level, int optname, u32 optval, int optlen)
+-{
+-	int (*sunos_setsockopt)(int, int, int, u32, int) =
+-		(int (*)(int, int, int, u32, int))SUNOS(105);
+-
+-	optname = solaris_to_linux_sockopt(optname);
+-	if (optname < 0)
+-		return optname;
+-	if (optname == SO_STATE)
+-		return 0;
+-
+-	return sunos_setsockopt(fd, level, optname, optval, optlen);
+-}
+-
+-asmlinkage int solaris_getsockopt(int fd, int level, int optname, u32 optval, u32 optlen)
+-{
+-	int (*sunos_getsockopt)(int, int, int, u32, u32) =
+-		(int (*)(int, int, int, u32, u32))SUNOS(118);
+-
+-	optname = solaris_to_linux_sockopt(optname);
+-	if (optname < 0)
+-		return optname;
+-
+-	if (optname == SO_STATE)
+-		optname = SOL_SO_STATE;
+-
+-	return sunos_getsockopt(fd, level, optname, optval, optlen);
+-}
+-
+-asmlinkage int solaris_connect(int fd, struct sockaddr __user *addr, int addrlen)
+-{
+-	int (*sys_connect)(int, struct sockaddr __user *, int) =
+-		(int (*)(int, struct sockaddr __user *, int))SYS(connect);
+-
+-	return sys_connect(fd, addr, addrlen);
+-}
+-
+-asmlinkage int solaris_accept(int fd, struct sockaddr __user *addr, int __user *addrlen)
+-{
+-	int (*sys_accept)(int, struct sockaddr __user *, int __user *) =
+-		(int (*)(int, struct sockaddr __user *, int __user *))SYS(accept);
+-
+-	return sys_accept(fd, addr, addrlen);
+-}
+-
+-asmlinkage int solaris_listen(int fd, int backlog)
+-{
+-	int (*sys_listen)(int, int) =
+-		(int (*)(int, int))SUNOS(106);
+-
+-	return sys_listen(fd, backlog);
+-}
+-
+-asmlinkage int solaris_shutdown(int fd, int how)
+-{
+-	int (*sys_shutdown)(int, int) =
+-		(int (*)(int, int))SYS(shutdown);
+-
+-	return sys_shutdown(fd, how);
+-}
+-
+-#define MSG_SOL_OOB		0x1
+-#define MSG_SOL_PEEK		0x2
+-#define MSG_SOL_DONTROUTE	0x4
+-#define MSG_SOL_EOR		0x8
+-#define MSG_SOL_CTRUNC		0x10
+-#define MSG_SOL_TRUNC		0x20
+-#define MSG_SOL_WAITALL		0x40
+-#define MSG_SOL_DONTWAIT	0x80
+-
+-static int solaris_to_linux_msgflags(int flags)
+-{
+-	int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE);
+-	
+-	if (flags & MSG_SOL_EOR) fl |= MSG_EOR;
+-	if (flags & MSG_SOL_CTRUNC) fl |= MSG_CTRUNC;
+-	if (flags & MSG_SOL_TRUNC) fl |= MSG_TRUNC;
+-	if (flags & MSG_SOL_WAITALL) fl |= MSG_WAITALL;
+-	if (flags & MSG_SOL_DONTWAIT) fl |= MSG_DONTWAIT;
+-	return fl;
+-}
+-
+-static int linux_to_solaris_msgflags(int flags)
+-{
+-	int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE);
+-	
+-	if (flags & MSG_EOR) fl |= MSG_SOL_EOR;
+-	if (flags & MSG_CTRUNC) fl |= MSG_SOL_CTRUNC;
+-	if (flags & MSG_TRUNC) fl |= MSG_SOL_TRUNC;
+-	if (flags & MSG_WAITALL) fl |= MSG_SOL_WAITALL;
+-	if (flags & MSG_DONTWAIT) fl |= MSG_SOL_DONTWAIT;
+-	return fl;
+-}
+-
+-asmlinkage int solaris_recvfrom(int s, char __user *buf, int len, int flags, u32 from, u32 fromlen)
+-{
+-	int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) =
+-		(int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom);
+-	
+-	return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), A(from), A(fromlen));
+-}
+-
+-asmlinkage int solaris_recv(int s, char __user *buf, int len, int flags)
+-{
+-	int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) =
+-		(int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom);
+-	
+-	return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL);
+-}
+-
+-asmlinkage int solaris_sendto(int s, char __user *buf, int len, int flags, u32 to, u32 tolen)
+-{
+-	int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) =
+-		(int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(sendto);
+-	
+-	return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), A(to), A(tolen));
+-}
+-
+-asmlinkage int solaris_send(int s, char *buf, int len, int flags)
+-{
+-	int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+-		(int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(sendto);
+-	
+-	return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL);
+-}
+-
+-asmlinkage int solaris_getpeername(int fd, struct sockaddr *addr, int *addrlen)
+-{
+-	int (*sys_getpeername)(int, struct sockaddr *, int *) =
+-		(int (*)(int, struct sockaddr *, int *))SYS(getpeername);
+-
+-	return sys_getpeername(fd, addr, addrlen);
+-}
+-
+-asmlinkage int solaris_getsockname(int fd, struct sockaddr *addr, int *addrlen)
+-{
+-	int (*sys_getsockname)(int, struct sockaddr *, int *) =
+-		(int (*)(int, struct sockaddr *, int *))SYS(getsockname);
+-
+-	return sys_getsockname(fd, addr, addrlen);
+-}
+-
+-/* XXX This really belongs in some header file... -DaveM */
+-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
+-					   16 for IP, 16 for IPX,
+-					   24 for IPv6,
+-					   about 80 for AX.25 */
+-
+-struct sol_nmsghdr {
+-	u32		msg_name;
+-	int		msg_namelen;
+-	u32		msg_iov;
+-	u32		msg_iovlen;
+-	u32		msg_control;
+-	u32		msg_controllen;
+-	u32		msg_flags;
+-};
+-
+-struct sol_cmsghdr {
+-	u32		cmsg_len;
+-	int		cmsg_level;
+-	int		cmsg_type;
+-	unsigned char	cmsg_data[0];
+-};
+-
+-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
+-					     struct sol_nmsghdr __user *umsg)
+-{
+-	u32 tmp1, tmp2, tmp3;
+-	int err;
+-
+-	err = get_user(tmp1, &umsg->msg_name);
+-	err |= __get_user(tmp2, &umsg->msg_iov);
+-	err |= __get_user(tmp3, &umsg->msg_control);
+-	if (err)
+-		return -EFAULT;
+-
+-	kmsg->msg_name = A(tmp1);
+-	kmsg->msg_iov = A(tmp2);
+-	kmsg->msg_control = A(tmp3);
+-
+-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+-	
+-	kmsg->msg_flags = solaris_to_linux_msgflags(kmsg->msg_flags);
+-	
+-	return err;
+-}
+-
+-asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned user_flags)
+-{
+-	struct socket *sock;
+-	char address[MAX_SOCK_ADDR];
+-	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+-	unsigned char ctl[sizeof(struct cmsghdr) + 20];
+-	unsigned char *ctl_buf = ctl;
+-	struct msghdr msg_sys;
+-	int err, ctl_len, iov_size, total_len;
+-
+-	err = -EFAULT;
+-	if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
+-		goto out;
+-
+-	sock = sockfd_lookup(fd, &err);
+-	if (!sock)
+-		goto out;
+-
+-	/* do not move before msg_sys is valid */
+-	err = -EMSGSIZE;
+-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
+-		goto out_put;
+-
+-	/* Check whether to allocate the iovec area*/
+-	err = -ENOMEM;
+-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+-		if (!iov)
+-			goto out_put;
+-	}
+-
+-	err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
+-	if (err < 0)
+-		goto out_freeiov;
+-	total_len = err;
+-
+-	err = -ENOBUFS;
+-	if (msg_sys.msg_controllen > INT_MAX)
+-		goto out_freeiov;
+-
+-	ctl_len = msg_sys.msg_controllen;
+-	if (ctl_len) {
+-		struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control;
+-		unsigned long *kcmsg;
+-		compat_size_t cmlen;
+-
+-		err = -EINVAL;
+-		if (ctl_len <= sizeof(compat_size_t))
+-			goto out_freeiov;
+-
+-		if (ctl_len > sizeof(ctl)) {
+-			err = -ENOBUFS;
+-			ctl_buf = kmalloc(ctl_len, GFP_KERNEL);
+-			if (!ctl_buf)
+-				goto out_freeiov;
+-		}
+-		__get_user(cmlen, &ucmsg->cmsg_len);
+-		kcmsg = (unsigned long *) ctl_buf;
+-		*kcmsg++ = (unsigned long)cmlen;
+-		err = -EFAULT;
+-		if (copy_from_user(kcmsg, &ucmsg->cmsg_level,
+-				   ctl_len - sizeof(compat_size_t)))
+-			goto out_freectl;
+-		msg_sys.msg_control = ctl_buf;
+-	}
+-	msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags);
+-
+-	if (sock->file->f_flags & O_NONBLOCK)
+-		msg_sys.msg_flags |= MSG_DONTWAIT;
+-	err = sock_sendmsg(sock, &msg_sys, total_len);
+-
+-out_freectl:
+-	if (ctl_buf != ctl)    
+-		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
+-out_freeiov:
+-	if (iov != iovstack)
+-		sock_kfree_s(sock->sk, iov, iov_size);
+-out_put:
+-	sockfd_put(sock);
+-out:       
+-	return err;
+-}
+-
+-asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags)
+-{
+-	struct socket *sock;
+-	struct iovec iovstack[UIO_FASTIOV];
+-	struct iovec *iov = iovstack;
+-	struct msghdr msg_sys;
+-	unsigned long cmsg_ptr;
+-	int err, iov_size, total_len, len;
+-
+-	/* kernel mode address */
+-	char addr[MAX_SOCK_ADDR];
+-
+-	/* user mode address pointers */
+-	struct sockaddr __user *uaddr;
+-	int __user *uaddr_len;
+-
+-	if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
+-		return -EFAULT;
+-
+-	sock = sockfd_lookup(fd, &err);
+-	if (!sock)
+-		goto out;
+-
+-	err = -EMSGSIZE;
+-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
+-		goto out_put;
+-
+-	/* Check whether to allocate the iovec area*/
+-	err = -ENOMEM;
+-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+-		if (!iov)
+-			goto out_put;
+-	}
+-
+-	/*
+-	 *	Save the user-mode address (verify_iovec will change the
+-	 *	kernel msghdr to use the kernel address space)
+-	 */
+-	 
+-	uaddr = (void __user *) msg_sys.msg_name;
+-	uaddr_len = &user_msg->msg_namelen;
+-	err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
+-	if (err < 0)
+-		goto out_freeiov;
+-	total_len = err;
+-
+-	cmsg_ptr = (unsigned long) msg_sys.msg_control;
+-	msg_sys.msg_flags = MSG_CMSG_COMPAT;
+-
+-	if (sock->file->f_flags & O_NONBLOCK)
+-		user_flags |= MSG_DONTWAIT;
+-
+-	err = sock_recvmsg(sock, &msg_sys, total_len, user_flags);
+-	if(err < 0)
+-		goto out_freeiov;
+-
+-	len = err;
+-
+-	if (uaddr != NULL) {
+-		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
+-		if (err < 0)
+-			goto out_freeiov;
+-	}
+-	err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags);
+-	if (err)
+-		goto out_freeiov;
+-	err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
+-			 &user_msg->msg_controllen);
+-	if (err)
+-		goto out_freeiov;
+-	err = len;
+-
+-out_freeiov:
+-	if (iov != iovstack)
+-		sock_kfree_s(sock->sk, iov, iov_size);
+-out_put:
+-	sockfd_put(sock);
+-out:
+-	return err;
+-}
+diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
+deleted file mode 100644
+index 7736411..0000000
+--- a/arch/sparc64/solaris/socksys.c
++++ /dev/null
+@@ -1,203 +0,0 @@
+-/* $Id: socksys.c,v 1.21 2002/02/08 03:57:14 davem Exp $
+- * socksys.c: /dev/inet/ stuff for Solaris emulation.
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1997, 1998 Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)
+- * Copyright (C) 1995, 1996 Mike Jagdis (jaggy at purplet.demon.co.uk)
+- */
+-
+-/*
+- *  Dave, _please_ give me specifications on this fscking mess so that I
+- * could at least get it into the state when it wouldn't screw the rest of
+- * the kernel over.  socksys.c and timod.c _stink_ and we are not talking
+- * H2S here, it's isopropilmercaptan in concentrations way over LD50. -- AV
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/ioctl.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/init.h>
+-#include <linux/poll.h>
+-#include <linux/slab.h>
+-#include <linux/syscalls.h>
+-#include <linux/in.h>
+-
+-#include <net/sock.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/termios.h>
+-
+-#include "conv.h"
+-#include "socksys.h"
+-
+-static int af_inet_protocols[] = {
+-IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP,
+-IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW,
+-0, 0, 0, 0, 0, 0,
+-};
+-
+-#ifndef DEBUG_SOLARIS_KMALLOC
+-
+-#define mykmalloc kmalloc
+-#define mykfree kfree
+-
+-#else
+-
+-extern void * mykmalloc(size_t s, gfp_t gfp);
+-extern void mykfree(void *);
+-
+-#endif
+-
+-static unsigned int (*sock_poll)(struct file *, poll_table *);
+-
+-static struct file_operations socksys_file_ops = {
+-	/* Currently empty */
+-};
+-
+-static int socksys_open(struct inode * inode, struct file * filp)
+-{
+-	int family, type, protocol, fd;
+-	struct dentry *dentry;
+-	int (*sys_socket)(int,int,int) =
+-		(int (*)(int,int,int))SUNOS(97);
+-        struct sol_socket_struct * sock;
+-	
+-	family = ((iminor(inode) >> 4) & 0xf);
+-	switch (family) {
+-	case AF_UNIX:
+-		type = SOCK_STREAM;
+-		protocol = 0;
+-		break;
+-	case AF_INET:
+-		protocol = af_inet_protocols[iminor(inode) & 0xf];
+-		switch (protocol) {
+-		case IPPROTO_TCP: type = SOCK_STREAM; break;
+-		case IPPROTO_UDP: type = SOCK_DGRAM; break;
+-		default: type = SOCK_RAW; break;
+-		}
+-		break;
+-	default:
+-		type = SOCK_RAW;
+-		protocol = 0;
+-		break;
+-	}
+-
+-	fd = sys_socket(family, type, protocol);
+-	if (fd < 0)
+-		return fd;
+-	/*
+-	 * N.B. The following operations are not legal!
+-	 *
+-	 * No shit.  WTF is it supposed to do, anyway?
+-	 *
+-	 * Try instead:
+-	 * d_delete(filp->f_path.dentry), then d_instantiate with sock inode
+-	 */
+-	dentry = filp->f_path.dentry;
+-	filp->f_path.dentry = dget(fcheck(fd)->f_path.dentry);
+-	filp->f_path.dentry->d_inode->i_rdev = inode->i_rdev;
+-	filp->f_path.dentry->d_inode->i_flock = inode->i_flock;
+-	SOCKET_I(filp->f_path.dentry->d_inode)->file = filp;
+-	filp->f_op = &socksys_file_ops;
+-        sock = (struct sol_socket_struct*) 
+-        	mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL);
+-        if (!sock) return -ENOMEM;
+-	SOLDD(("sock=%016lx(%016lx)\n", sock, filp));
+-        sock->magic = SOLARIS_SOCKET_MAGIC;
+-        sock->modcount = 0;
+-        sock->state = TS_UNBND;
+-        sock->offset = 0;
+-        sock->pfirst = sock->plast = NULL;
+-        filp->private_data = sock;
+-	SOLDD(("filp->private_data %016lx\n", filp->private_data));
+-
+-	sys_close(fd);
+-	dput(dentry);
+-	return 0;
+-}
+-
+-static int socksys_release(struct inode * inode, struct file * filp)
+-{
+-        struct sol_socket_struct * sock;
+-        struct T_primsg *it;
+-
+-	/* XXX: check this */
+-	sock = (struct sol_socket_struct *)filp->private_data;
+-	SOLDD(("sock release %016lx(%016lx)\n", sock, filp));
+-	it = sock->pfirst;
+-	while (it) {
+-		struct T_primsg *next = it->next;
+-		
+-		SOLDD(("socksys_release %016lx->%016lx\n", it, next));
+-		mykfree((char*)it);
+-		it = next;
+-	}
+-	filp->private_data = NULL;
+-	SOLDD(("socksys_release %016lx\n", sock));
+-	mykfree((char*)sock);
+-	return 0;
+-}
+-
+-static unsigned int socksys_poll(struct file * filp, poll_table * wait)
+-{
+-	struct inode *ino;
+-	unsigned int mask = 0;
+-
+-	ino=filp->f_path.dentry->d_inode;
+-	if (ino && S_ISSOCK(ino->i_mode)) {
+-		struct sol_socket_struct *sock;
+-		sock = (struct sol_socket_struct*)filp->private_data;
+-		if (sock && sock->pfirst) {
+-			mask |= POLLIN | POLLRDNORM;
+-			if (sock->pfirst->pri == MSG_HIPRI)
+-				mask |= POLLPRI;
+-		}
+-	}
+-	if (sock_poll)
+-		mask |= (*sock_poll)(filp, wait);
+-	return mask;
+-}
+-	
+-static const struct file_operations socksys_fops = {
+-	.open =		socksys_open,
+-	.release =	socksys_release,
+-};
+-
+-int __init init_socksys(void)
+-{
+-	int ret;
+-	struct file * file;
+-	int (*sys_socket)(int,int,int) =
+-		(int (*)(int,int,int))SUNOS(97);
+-	int (*sys_close)(unsigned int) = 
+-		(int (*)(unsigned int))SYS(close);
+-	
+-	ret = register_chrdev (30, "socksys", &socksys_fops);
+-	if (ret < 0) {
+-		printk ("Couldn't register socksys character device\n");
+-		return ret;
+-	}
+-	ret = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+-	if (ret < 0) {
+-		printk ("Couldn't create socket\n");
+-		return ret;
+-	}
+-
+-	file = fcheck(ret);
+-	/* N.B. Is this valid? Suppose the f_ops are in a module ... */
+-	socksys_file_ops = *file->f_op;
+-	sys_close(ret);
+-	sock_poll = socksys_file_ops.poll;
+-	socksys_file_ops.poll = socksys_poll;
+-	socksys_file_ops.release = socksys_release;
+-	return 0;
+-}
+-
+-void __exit cleanup_socksys(void)
+-{
+-	unregister_chrdev(30, "socksys");
+-}
+diff --git a/arch/sparc64/solaris/socksys.h b/arch/sparc64/solaris/socksys.h
+deleted file mode 100644
+index 5d1b78e..0000000
+--- a/arch/sparc64/solaris/socksys.h
++++ /dev/null
+@@ -1,208 +0,0 @@
+-/* $Id: socksys.h,v 1.2 1998/03/26 08:46:07 jj Exp $
+- * socksys.h: Definitions for STREAMS modules emulation code.
+- *
+- * Copyright (C) 1998 Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)
+- */
+-
+-#define MSG_HIPRI	0x01
+-#define MSG_ANY		0x02
+-#define MSG_BAND	0x04
+-
+-#define MORECTL		1
+-#define MOREDATA	2
+-
+-#define	TBADADDR		1
+-#define	TBADOPT			2
+-#define	TACCES			3
+-#define TBADF			4
+-#define TNOADDR			5
+-#define TOUTSTATE	        6
+-#define TBADSEQ		        7
+-#define TSYSERR			8
+-#define TLOOK		        9
+-#define TBADDATA	       10
+-#define TBUFOVFLW	       11
+-#define TFLOW		       12
+-#define	TNODATA		       13
+-#define TNODIS		       14
+-#define TNOUDERR	       15
+-#define TBADFLAG	       16
+-#define TNOREL		       17
+-#define TNOTSUPPORT	       18
+-#define TSTATECHNG	       19
+-
+-#define T_CONN_REQ      0
+-#define T_CONN_RES      1
+-#define T_DISCON_REQ    2
+-#define T_DATA_REQ      3
+-#define T_EXDATA_REQ    4
+-#define T_INFO_REQ      5
+-#define T_BIND_REQ      6
+-#define T_UNBIND_REQ    7
+-#define T_UNITDATA_REQ  8
+-#define T_OPTMGMT_REQ   9
+-#define T_ORDREL_REQ    10
+-
+-#define T_CONN_IND      11
+-#define T_CONN_CON      12
+-#define T_DISCON_IND    13
+-#define T_DATA_IND      14
+-#define T_EXDATA_IND    15
+-#define T_INFO_ACK      16
+-#define T_BIND_ACK      17
+-#define T_ERROR_ACK     18
+-#define T_OK_ACK        19
+-#define T_UNITDATA_IND  20
+-#define T_UDERROR_IND   21
+-#define T_OPTMGMT_ACK   22
+-#define T_ORDREL_IND    23
+-
+-#define T_NEGOTIATE	0x0004
+-#define T_FAILURE	0x0040
+-
+-#define TS_UNBND	0	/* unbound */
+-#define	TS_WACK_BREQ	1	/* waiting for T_BIND_REQ ack  */
+-#define TS_WACK_UREQ	2	/* waiting for T_UNBIND_REQ ack */
+-#define TS_IDLE		3	/* idle */
+-#define TS_WACK_OPTREQ	4	/* waiting for T_OPTMGMT_REQ ack */
+-#define TS_WACK_CREQ	5	/* waiting for T_CONN_REQ ack */
+-#define TS_WCON_CREQ	6	/* waiting for T_CONN_REQ confirmation */
+-#define	TS_WRES_CIND	7	/* waiting for T_CONN_IND */
+-#define TS_WACK_CRES	8	/* waiting for T_CONN_RES ack */
+-#define TS_DATA_XFER	9	/* data transfer */
+-#define TS_WIND_ORDREL	10	/* releasing read but not write */
+-#define TS_WREQ_ORDREL	11      /* wait to release write but not read */
+-#define TS_WACK_DREQ6	12	/* waiting for T_DISCON_REQ ack */
+-#define TS_WACK_DREQ7	13	/* waiting for T_DISCON_REQ ack */
+-#define TS_WACK_DREQ9	14	/* waiting for T_DISCON_REQ ack */
+-#define TS_WACK_DREQ10	15	/* waiting for T_DISCON_REQ ack */
+-#define TS_WACK_DREQ11	16	/* waiting for T_DISCON_REQ ack */
+-#define TS_NOSTATES	17
+-
+-struct T_conn_req {
+-	s32 PRIM_type; 
+-	s32 DEST_length;
+-	s32 DEST_offset;
+-	s32 OPT_length;
+-	s32 OPT_offset;
+-};
+-
+-struct T_bind_req {
+-	s32 PRIM_type;
+-	s32 ADDR_length;
+-	s32 ADDR_offset;
+-	u32 CONIND_number;
+-};
+-
+-struct T_unitdata_req {
+-	s32 PRIM_type; 
+-	s32 DEST_length;
+-	s32 DEST_offset;
+-	s32 OPT_length;
+-	s32 OPT_offset;
+-};
+-
+-struct T_optmgmt_req {
+-	s32 PRIM_type; 
+-	s32 OPT_length;
+-	s32 OPT_offset;
+-	s32 MGMT_flags;
+-};
+-
+-struct T_bind_ack {
+-	s32 PRIM_type;
+-	s32 ADDR_length;
+-	s32 ADDR_offset;
+-	u32 CONIND_number;
+-};
+-
+-struct T_error_ack {
+-	s32 PRIM_type;
+-	s32 ERROR_prim;
+-	s32 TLI_error;
+-	s32 UNIX_error;
+-};
+-
+-struct T_ok_ack {
+-	s32 PRIM_type;
+-	s32 CORRECT_prim;
+-};
+-
+-struct T_conn_ind {
+-	s32 PRIM_type;
+-	s32 SRC_length;
+-	s32 SRC_offset;
+-	s32 OPT_length;
+-	s32 OPT_offset;
+-	s32 SEQ_number;
+-};
+-
+-struct T_conn_con {
+-	s32 PRIM_type;
+-	s32 RES_length;
+-	s32 RES_offset;
+-	s32 OPT_length;
+-	s32 OPT_offset;
+-};
+-
+-struct T_discon_ind {
+-	s32 PRIM_type;
+-	s32 DISCON_reason;
+-	s32 SEQ_number;
+-};
+-
+-struct T_unitdata_ind {
+-	s32 PRIM_type;
+-	s32 SRC_length;
+-	s32 SRC_offset;
+-	s32 OPT_length;
+-	s32 OPT_offset;
+-};
+-
+-struct T_optmgmt_ack {
+-	s32 PRIM_type; 
+-	s32 OPT_length;
+-	s32 OPT_offset;
+-	s32 MGMT_flags;
+-};
+-
+-struct opthdr {
+-	s32 level;
+-	s32 name;
+-	s32 len;
+-	char value[0];	
+-};
+-
+-struct T_primsg {
+-	struct T_primsg *next;
+-	unsigned char pri;
+-	unsigned char band;
+-	int length;
+-	s32 type;
+-};
+-
+-struct strbuf {
+-	s32 maxlen;
+-	s32 len;
+-	u32 buf;
+-} ;
+-
+-/* Constants used by STREAMS modules emulation code */
+-
+-typedef char sol_module;
+-
+-#define MAX_NR_STREAM_MODULES   16
+-
+-/* Private data structure assigned to sockets. */
+-
+-struct sol_socket_struct {
+-        int magic;
+-        int modcount;
+-        sol_module module[MAX_NR_STREAM_MODULES];
+-        long state;
+-        int offset;
+-        struct T_primsg *pfirst, *plast;
+-};
+-
+-#define SOLARIS_SOCKET_MAGIC    0xADDED
+-
+diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S
+deleted file mode 100644
+index 7043ca1..0000000
+--- a/arch/sparc64/solaris/systbl.S
++++ /dev/null
+@@ -1,285 +0,0 @@
+-/* $Id: systbl.S,v 1.11 2000/03/13 21:57:35 davem Exp $
+- * systbl.S: System call entry point table for Solaris compatibility.
+- *
+- * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1996 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- */
+-
+-#include <asm/unistd.h>
+-
+-/* Fall back to sys_call_table32 entry */
+-#define CHAIN(name)	__NR_##name
+-
+-/* Pass pt_regs pointer as first argument */
+-#define REGS(name)	name+1
+-
+-/* Hack till all be implemented */
+-#define solaris_getpmsg		solaris_unimplemented
+-#define solaris_hrtsys		solaris_unimplemented
+-#define solaris_msgsys		solaris_unimplemented
+-#define solaris_putpmsg		solaris_unimplemented
+-#define solaris_semsys		solaris_unimplemented
+-
+-        .data
+-	.globl		solaris_sys_table
+-solaris_sys_table:
+-	.word solaris_unimplemented	/* nosys		0	*/
+-	.word CHAIN(exit)		/* exit		d	1	*/
+-	.word CHAIN(fork)		/* fork			2	*/
+-	.word CHAIN(read)		/* read		dpd	3	*/
+-	.word CHAIN(write)		/* write	dpd	4	*/
+-	.word solaris_open		/* open		soo	5	*/
+-	.word CHAIN(close)		/* close	d	6	*/
+-	.word solaris_wait		/* wait		xxx	7	*/
+-	.word CHAIN(creat)		/* creat	so	8	*/
+-	.word CHAIN(link)		/* link		ss	9	*/
+-	.word CHAIN(unlink)		/* unlink	s	10	*/
+-	.word solaris_unimplemented	/* exec		sxx	11	*/
+-	.word CHAIN(chdir)		/* chdir	s	12	*/
+-	.word CHAIN(time)		/* time			13	*/
+-	.word solaris_mknod		/* mknod	sox	14	*/
+-	.word CHAIN(chmod)		/* chmod	so	15	*/ 
+-	.word CHAIN(chown)		/* chown	sdd	16	*/
+-	.word solaris_brk		/* brk/break	x	17	*/
+-	.word solaris_stat		/* stat		sp	18	*/
+-	.word CHAIN(lseek)		/* seek/lseek	ddd	19	*/
+-	.word solaris_getpid		/* getpid		20	*/
+-	.word solaris_unimplemented	/* mount		21	*/
+-	.word CHAIN(umount)		/* umount	s	22	*/
+-	.word CHAIN(setuid)		/* setuid	d	23	*/
+-	.word solaris_getuid		/* getuid		24	*/
+-	.word CHAIN(stime)		/* stime	d	25	*/
+-#if 0
+-	.word solaris_ptrace		/* ptrace	xdxx	26	*/
+-#else
+-	.word CHAIN(ptrace)		/* ptrace	xdxx	26	*/
+-#endif
+-	.word CHAIN(alarm)		/* alarm	d	27	*/
+-	.word solaris_fstat		/* fstat	dp	28	*/
+-	.word CHAIN(pause)		/* pause		29	*/
+-	.word CHAIN(utime)		/* utime	xx	30	*/
+-	.word solaris_unimplemented	/* stty			31	*/
+-	.word solaris_unimplemented	/* gtty			32	*/
+-	.word solaris_access		/* access	so	33	*/
+-	.word CHAIN(nice)		/* nice		d	34	*/
+-	.word solaris_statfs		/* statfs	spdd	35	*/
+-	.word CHAIN(sync)		/* sync			36	*/
+-	.word solaris_kill		/* kill		dd	37	*/
+-	.word solaris_fstatfs		/* fstatfs	dpdd	38	*/
+-	.word solaris_procids		/* pgrpsys	ddd	39	*/
+-	.word solaris_unimplemented	/* xenix		40	*/
+-	.word CHAIN(dup)		/* dup		d	41	*/
+-	.word CHAIN(pipe)		/* pipe			42	*/
+-	.word CHAIN(times)		/* times	p	43	*/
+-	.word 44 /*CHAIN(profil)*/	/* prof		xxxx	44	*/
+-	.word solaris_unimplemented	/* lock/plock		45	*/
+-	.word CHAIN(setgid)		/* setgid	d	46	*/
+-	.word solaris_getgid		/* getgid		47	*/
+-	.word solaris_sigfunc		/* sigfunc	xx	48	*/
+-	.word REGS(solaris_msgsys)	/* msgsys	dxddd	49	*/
+-	.word solaris_unimplemented	/* syssun/3b		50	*/
+-	.word CHAIN(acct)		/* acct/sysacct	x	51	*/
+-	.word solaris_shmsys		/* shmsys	ddxo	52	*/
+-	.word REGS(solaris_semsys)	/* semsys	dddx	53	*/
+-	.word solaris_ioctl		/* ioctl	dxx	54	*/
+-	.word solaris_unimplemented	/* uadmin	xxx	55	*/
+-	.word solaris_unimplemented	/* reserved:exch	56	*/
+-	.word solaris_utssys		/* utssys	x	57	*/
+-	.word CHAIN(fsync)		/* fsync	d	58	*/
+-	.word CHAIN(execve)		/* execv	spp	59	*/
+-	.word CHAIN(umask)		/* umask	o	60	*/
+-	.word CHAIN(chroot)		/* chroot	s	61	*/
+-	.word solaris_fcntl		/* fcntl	dxx	62	*/
+-	.word solaris_ulimit		/* ulimit	xx	63	*/
+-	.word solaris_unimplemented	/* ?			64	*/
+-	.word solaris_unimplemented	/* ?			65	*/
+-	.word solaris_unimplemented	/* ?			66	*/
+-	.word solaris_unimplemented	/* ?			67	*/
+-	.word solaris_unimplemented	/* ?			68	*/
+-	.word solaris_unimplemented	/* ?			69	*/
+-	.word solaris_unimplemented	/* advfs		70	*/
+-	.word solaris_unimplemented	/* unadvfs		71	*/
+-	.word solaris_unimplemented	/* rmount		72	*/
+-	.word solaris_unimplemented	/* rumount		73	*/
+-	.word solaris_unimplemented	/* rfstart		74	*/
+-	.word solaris_unimplemented	/* ?			75	*/
+-	.word solaris_unimplemented	/* rdebug		76	*/
+-	.word solaris_unimplemented	/* rfstop		77	*/
+-	.word solaris_unimplemented	/* rfsys		78	*/
+-	.word CHAIN(rmdir)		/* rmdir	s	79	*/
+-	.word CHAIN(mkdir)		/* mkdir	so	80	*/
+-	.word CHAIN(getdents)		/* getdents	dxd	81	*/
+-	.word solaris_unimplemented	/* libattach		82	*/
+-	.word solaris_unimplemented	/* libdetach		83	*/
+-	.word CHAIN(sysfs)		/* sysfs	dxx	84	*/
+-	.word solaris_getmsg		/* getmsg	dxxx	85	*/
+-	.word solaris_putmsg		/* putmsg	dxxd	86	*/
+-	.word CHAIN(poll)		/* poll		xdd	87	*/
+-	.word solaris_lstat		/* lstat	sp	88	*/
+-	.word CHAIN(symlink)		/* symlink	ss	89	*/
+-	.word CHAIN(readlink)		/* readlink	spd	90	*/
+-	.word CHAIN(setgroups)		/* setgroups	dp	91	*/
+-	.word CHAIN(getgroups)		/* getgroups	dp	92	*/
+-	.word CHAIN(fchmod)		/* fchmod	do	93	*/
+-	.word CHAIN(fchown)		/* fchown	ddd	94	*/
+-	.word solaris_sigprocmask	/* sigprocmask	dxx	95	*/
+-	.word solaris_sigsuspend	/* sigsuspend	x	96	*/
+-	.word solaris_sigaltstack	/* sigaltstack	xx	97	*/
+-	.word solaris_sigaction		/* sigaction	dxx	98	*/
+-	.word solaris_sigpending	/* sigpending	dd	99	*/
+-	.word REGS(solaris_context)	/* context		100	*/
+-	.word solaris_unimplemented	/* evsys		101	*/
+-	.word solaris_unimplemented	/* evtrapret		102	*/
+-	.word solaris_statvfs		/* statvfs	sp	103	*/
+-	.word solaris_fstatvfs		/* fstatvfs	dp	104	*/
+-	.word solaris_unimplemented	/* unknown		105	*/
+-	.word solaris_unimplemented	/* nfssys		106	*/
+-	.word solaris_waitid		/* waitid	ddxd	107	*/
+-	.word solaris_unimplemented	/* sigsendsys	ddd	108	*/
+-	.word REGS(solaris_hrtsys)	/* hrtsys	xxx	109	*/
+-	.word solaris_unimplemented	/* acancel	dxd	110	*/
+-	.word solaris_unimplemented	/* async		111	*/
+-	.word solaris_unimplemented	/* priocntlsys		112	*/
+-	.word solaris_pathconf		/* pathconf	sd	113	*/
+-	.word CHAIN(mincore)		/* mincore	d	114	*/
+-	.word solaris_mmap		/* mmap		xxxxdx	115	*/
+-	.word CHAIN(mprotect)		/* mprotect	xdx	116	*/
+-	.word CHAIN(munmap)		/* munmap	xd	117	*/
+-	.word solaris_fpathconf		/* fpathconf	dd	118	*/
+-	.word CHAIN(fork)		/* fork			119	*/
+-	.word solaris_unimplemented	/* fchdir	d	120	*/
+-	.word CHAIN(readv)		/* readv	dxd	121	*/
+-	.word CHAIN(writev)		/* writev	dxd	122	*/
+-	.word solaris_xstat		/* xstat	dsx	123	*/
+-	.word solaris_lxstat		/* lxstat	dsx	124	*/
+-	.word solaris_fxstat		/* fxstat	ddx	125	*/
+-	.word solaris_xmknod		/* xmknod	dsox	126	*/
+-	.word solaris_unimplemented	/* syslocal	d	127	*/
+-	.word solaris_setrlimit		/* setrlimit	dp	128	*/
+-	.word solaris_getrlimit		/* getrlimit	dp	129	*/
+-	.word CHAIN(chown)		/* lchown	sdd	130	*/
+-	.word solaris_unimplemented	/* memcntl		131	*/
+-	.word solaris_getpmsg		/* getpmsg	dxxxx	132	*/
+-	.word solaris_putpmsg		/* putpmsg	dxxdd	133	*/
+-	.word CHAIN(rename)		/* rename	ss	134	*/
+-	.word solaris_utsname		/* uname	x	135	*/
+-	.word solaris_unimplemented	/* setegid		136	*/
+-	.word solaris_sysconf		/* sysconfig	d	137	*/
+-	.word solaris_unimplemented	/* adjtime		138	*/
+-	.word solaris_sysinfo		/* systeminfo	dsd	139	*/
+-	.word solaris_unimplemented	/* ?			140	*/
+-	.word solaris_unimplemented	/* seteuid		141	*/
+-	.word solaris_unimplemented	/* ?			142	*/
+-	.word solaris_unimplemented	/* ?			143	*/
+-	.word solaris_unimplemented	/* secsys	dx	144	*/
+-	.word solaris_unimplemented	/* filepriv	sdxd	145	*/
+-	.word solaris_unimplemented	/* procpriv	dxd	146	*/
+-	.word solaris_unimplemented	/* devstat	sdx	147	*/
+-	.word solaris_unimplemented	/* aclipc	ddddx	148	*/
+-	.word solaris_unimplemented	/* fdevstat	ddx	149	*/
+-	.word solaris_unimplemented	/* flvlfile	ddx	150	*/
+-	.word solaris_unimplemented	/* lvlfile	sdx	151	*/
+-	.word solaris_unimplemented	/* ?			152	*/
+-	.word solaris_unimplemented	/* fchroot	d	153	*/
+-	.word solaris_unimplemented	/* lvlproc	dx	154	*/
+-	.word solaris_unimplemented	/* ?			155	*/
+-	.word solaris_gettimeofday	/* gettimeofday	x	156	*/
+-	.word CHAIN(getitimer)		/* getitimer	dx	157	*/
+-	.word CHAIN(setitimer)		/* setitimer	dxx	158	*/
+-	.word solaris_unimplemented	/* lwp-xxx		159	*/
+-	.word solaris_unimplemented	/* lwp-xxx		160	*/
+-	.word solaris_unimplemented	/* lwp-xxx		161	*/
+-	.word solaris_unimplemented	/* lwp-xxx		162	*/
+-	.word solaris_unimplemented	/* lwp-xxx		163	*/
+-	.word solaris_unimplemented	/* lwp-xxx		164	*/
+-	.word solaris_unimplemented	/* lwp-xxx		165	*/
+-	.word solaris_unimplemented	/* lwp-xxx		166	*/
+-	.word solaris_unimplemented	/* lwp-xxx		167	*/
+-	.word solaris_unimplemented	/* lwp-xxx		168	*/
+-	.word solaris_unimplemented	/* lwp-xxx		169	*/
+-	.word solaris_unimplemented	/* lwp-xxx		170	*/
+-	.word solaris_unimplemented	/* lwp-xxx		171	*/
+-	.word solaris_unimplemented	/* lwp-xxx		172	*/
+-	.word solaris_pread		/* pread	dpdd	173	*/
+-	.word solaris_pwrite		/* pwrite	dpdd	174	*/
+-	.word REGS(solaris_llseek)	/* llseek	dLd	175	*/
+-	.word solaris_unimplemented	/* lwpself		176	*/
+-	.word solaris_unimplemented	/* lwpinfo		177	*/
+-	.word solaris_unimplemented	/* lwpprivate		178	*/
+-	.word solaris_unimplemented	/* processorbind	179	*/
+-	.word solaris_unimplemented	/* processorexbind	180	*/
+-	.word solaris_unimplemented	/* 			181	*/
+-	.word solaris_unimplemented	/* sync_mailbox		182	*/
+-	.word solaris_unimplemented	/* prepblock		183	*/
+-	.word solaris_unimplemented	/* block		184	*/
+-	.word solaris_acl		/* acl		sddp	185	*/
+-	.word solaris_unimplemented	/* unblock		186	*/
+-	.word solaris_unimplemented	/* cancelblock		187	*/
+-	.word solaris_unimplemented	/* ?			188	*/
+-	.word solaris_unimplemented	/* xxxxx		189	*/
+-	.word solaris_unimplemented	/* xxxxxe		190	*/
+-	.word solaris_unimplemented	/*			191	*/
+-	.word solaris_unimplemented	/*			192	*/
+-	.word solaris_unimplemented	/*			193	*/
+-	.word solaris_unimplemented	/*			194	*/
+-	.word solaris_unimplemented	/* 			195	*/
+-	.word solaris_unimplemented	/* 			196	*/
+-	.word solaris_unimplemented	/* 			197	*/
+-	.word solaris_unimplemented	/* 			198	*/
+-	.word CHAIN(nanosleep)		/* nanosleep	dd	199	*/
+-	.word solaris_facl		/* facl		dddp	200	*/
+-	.word solaris_unimplemented	/* 			201	*/
+-	.word CHAIN(setreuid)		/* setreuid	dd	202	*/
+-	.word CHAIN(setregid)		/* setregid	dd	203	*/
+-	.word solaris_unimplemented	/* 			204	*/
+-	.word solaris_unimplemented	/* 			205	*/
+-	.word solaris_unimplemented	/* 			206	*/
+-	.word solaris_unimplemented	/* 			207	*/
+-	.word solaris_unimplemented	/* 			208	*/
+-	.word solaris_unimplemented	/* 			209	*/
+-	.word solaris_unimplemented	/* 			210	*/
+-	.word solaris_unimplemented	/* 			211	*/
+-	.word solaris_unimplemented	/* 			212	*/
+-	.word solaris_getdents64	/* getdents64	dpd	213	*/
+-	.word REGS(solaris_mmap64)	/* mmap64	xxxxdX	214	*/
+-	.word solaris_stat64		/* stat64	sP	215	*/
+-	.word solaris_lstat64		/* lstat64	sP	216	*/
+-	.word solaris_fstat64		/* fstat64	dP	217	*/
+-	.word solaris_statvfs64		/* statvfs64	sP	218	*/
+-	.word solaris_fstatvfs64	/* fstatvfs64	dP	219	*/
+-	.word solaris_setrlimit64	/* setrlimit64	dP	220	*/
+-	.word solaris_getrlimit64	/* getrlimit64	dP	221	*/
+-	.word CHAIN(pread64)		/* pread64	dpdD	222	*/
+-	.word CHAIN(pwrite64)		/* pwrite64	dpdD	223	*/
+-	.word CHAIN(creat)		/* creat64	so	224	*/
+-	.word solaris_open		/* open64	soo	225	*/
+-	.word solaris_unimplemented	/* 			226	*/
+-	.word solaris_unimplemented	/* 			227	*/
+-	.word solaris_unimplemented	/* 			228	*/
+-	.word solaris_unimplemented	/* 			229	*/
+-	.word solaris_socket		/* socket	ddd	230	*/
+-	.word solaris_socketpair	/* socketpair	dddp	231	*/
+-	.word solaris_bind		/* bind		dpd	232	*/
+-	.word solaris_listen		/* listen	dd	233	*/
+-	.word solaris_accept		/* accept	dpp	234	*/
+-	.word solaris_connect		/* connect	dpd	235	*/
+-	.word solaris_shutdown		/* shutdown	dd	236	*/
+-	.word solaris_recv		/* recv		dpdd	237	*/
+-	.word solaris_recvfrom		/* recvfrom	dpddpp	238	*/
+-	.word solaris_recvmsg		/* recvmsg	dpd	239	*/
+-	.word solaris_send		/* send		dpdd	240	*/
+-	.word solaris_sendmsg		/* sendmsg	dpd	241	*/
+-	.word solaris_sendto		/* sendto	dpddpd	242	*/
+-	.word solaris_getpeername	/* getpeername	dpp	243	*/
+-	.word solaris_getsockname	/* getsockname	dpp	244	*/
+-	.word solaris_getsockopt	/* getsockopt	dddpp	245	*/
+-	.word solaris_setsockopt	/* setsockopt	dddpp	246	*/
+-	.word solaris_unimplemented	/* 			247	*/
+-	.word solaris_ntp_gettime	/* ntp_gettime	p	248	*/
+-	.word solaris_ntp_adjtime	/* ntp_adjtime	p	249	*/
+-	.word solaris_unimplemented	/* 			250	*/
+-	.word solaris_unimplemented	/* 			251	*/
+-	.word solaris_unimplemented	/* 			252	*/
+-	.word solaris_unimplemented	/* 			253	*/
+-	.word solaris_unimplemented	/* 			254	*/
+-	.word solaris_unimplemented	/* 			255	*/
+diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
+deleted file mode 100644
+index 15234fc..0000000
+--- a/arch/sparc64/solaris/timod.c
++++ /dev/null
+@@ -1,976 +0,0 @@
+-/* $Id: timod.c,v 1.19 2002/02/08 03:57:14 davem Exp $
+- * timod.c: timod emulation.
+- *
+- * Copyright (C) 1998 Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)
+- *
+- * Streams & timod emulation based on code
+- * Copyright (C) 1995, 1996 Mike Jagdis (jaggy at purplet.demon.co.uk)
+- *
+- */
+- 
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/ioctl.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/netdevice.h>
+-#include <linux/poll.h>
+-
+-#include <net/sock.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/termios.h>
+-
+-#include "conv.h"
+-#include "socksys.h"
+-
+-asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
+-
+-static DEFINE_SPINLOCK(timod_pagelock);
+-static char * page = NULL ;
+-
+-#ifndef DEBUG_SOLARIS_KMALLOC
+-
+-#define mykmalloc kmalloc
+-#define mykfree kfree
+-
+-#else
+-
+-void * mykmalloc(size_t s, gfp_t gfp)
+-{
+-	static char * page;
+-	static size_t free;
+-	void * r;
+-	s = ((s + 63) & ~63);
+-	if( s > PAGE_SIZE ) {
+-		SOLD("too big size, calling real kmalloc");
+-		return kmalloc(s, gfp);
+-	}
+-	if( s > free ) {
+-		/* we are wasting memory, but we don't care */
+-		page = (char *)__get_free_page(gfp);
+-		free = PAGE_SIZE;
+-	}
+-	r = page;
+-	page += s;
+-	free -= s;
+-	return r;
+-}
+-
+-void mykfree(void *p)
+-{
+-}
+-
+-#endif
+-
+-#ifndef DEBUG_SOLARIS
+-
+-#define BUF_SIZE	PAGE_SIZE
+-#define PUT_MAGIC(a,m)
+-#define SCHECK_MAGIC(a,m)
+-#define BUF_OFFSET	0
+-#define MKCTL_TRAILER	0
+-
+-#else
+-
+-#define BUF_SIZE	(PAGE_SIZE-2*sizeof(u64))
+-#define BUFPAGE_MAGIC	0xBADC0DEDDEADBABEL
+-#define MKCTL_MAGIC	0xDEADBABEBADC0DEDL
+-#define PUT_MAGIC(a,m)	do{(*(u64*)(a))=(m);}while(0)
+-#define SCHECK_MAGIC(a,m)	do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
+-				__FILE__,__LINE__,__func__,(m),(a));}while(0)
+-#define BUF_OFFSET	sizeof(u64)
+-#define MKCTL_TRAILER	sizeof(u64)
+-
+-#endif
+-
+-static char *getpage( void )
+-{
+-	char *r;
+-	SOLD("getting page");
+-	spin_lock(&timod_pagelock);
+-	if (page) {
+-		r = page;
+-		page = NULL;
+-		spin_unlock(&timod_pagelock);
+-		SOLD("got cached");
+-		return r + BUF_OFFSET;
+-	}
+-	spin_unlock(&timod_pagelock);
+-	SOLD("getting new");
+-	r = (char *)__get_free_page(GFP_KERNEL);
+-	PUT_MAGIC(r,BUFPAGE_MAGIC);
+-	PUT_MAGIC(r+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
+-	return r + BUF_OFFSET;
+-}
+-
+-static void putpage(char *p)
+-{
+-	SOLD("putting page");
+-	p = p - BUF_OFFSET;
+-	SCHECK_MAGIC(p,BUFPAGE_MAGIC);
+-	SCHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
+-	spin_lock(&timod_pagelock);
+-	if (page) {
+-		spin_unlock(&timod_pagelock);
+-		free_page((unsigned long)p);
+-		SOLD("freed it");
+-	} else {
+-		page = p;
+-		spin_unlock(&timod_pagelock);
+-		SOLD("cached it");
+-	}
+-}
+-
+-static struct T_primsg *timod_mkctl(int size)
+-{
+-	struct T_primsg *it;
+-
+-	SOLD("creating primsg");
+-	it = (struct T_primsg *)mykmalloc(size+sizeof(*it)-sizeof(s32)+2*MKCTL_TRAILER, GFP_KERNEL);
+-	if (it) {
+-		SOLD("got it");
+-		it->pri = MSG_HIPRI;
+-		it->length = size;
+-		PUT_MAGIC((char*)((u64)(((char *)&it->type)+size+7)&~7),MKCTL_MAGIC);
+-	}
+-	return it;
+-}
+-
+-static void timod_wake_socket(unsigned int fd)
+-{
+-	struct socket *sock;
+-	struct fdtable *fdt;
+-
+-	SOLD("wakeing socket");
+-	fdt = files_fdtable(current->files);
+-	sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode);
+-	wake_up_interruptible(&sock->wait);
+-	read_lock(&sock->sk->sk_callback_lock);
+-	if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
+-		__kill_fasync(sock->fasync_list, SIGIO, POLL_IN);
+-	read_unlock(&sock->sk->sk_callback_lock);
+-	SOLD("done");
+-}
+-
+-static void timod_queue(unsigned int fd, struct T_primsg *it)
+-{
+-	struct sol_socket_struct *sock;
+-	struct fdtable *fdt;
+-
+-	SOLD("queuing primsg");
+-	fdt = files_fdtable(current->files);
+-	sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
+-	it->next = sock->pfirst;
+-	sock->pfirst = it;
+-	if (!sock->plast)
+-		sock->plast = it;
+-	timod_wake_socket(fd);
+-	SOLD("done");
+-}
+-
+-static void timod_queue_end(unsigned int fd, struct T_primsg *it)
+-{
+-	struct sol_socket_struct *sock;
+-	struct fdtable *fdt;
+-
+-	SOLD("queuing primsg at end");
+-	fdt = files_fdtable(current->files);
+-	sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
+-	it->next = NULL;
+-	if (sock->plast)
+-		sock->plast->next = it;
+-	else
+-		sock->pfirst = it;
+-	sock->plast = it;
+-	SOLD("done");
+-}
+-
+-static void timod_error(unsigned int fd, int prim, int terr, int uerr)
+-{
+-	struct T_primsg *it;
+-	
+-	SOLD("making error");
+-	it = timod_mkctl(sizeof(struct T_error_ack));
+-	if (it) {
+-		struct T_error_ack *err = (struct T_error_ack *)&it->type;
+-		
+-		SOLD("got it");
+-		err->PRIM_type = T_ERROR_ACK;
+-		err->ERROR_prim = prim;
+-		err->TLI_error = terr;
+-		err->UNIX_error = uerr; /* FIXME: convert this */
+-		timod_queue(fd, it);
+-	}
+-	SOLD("done");
+-}
+-
+-static void timod_ok(unsigned int fd, int prim)
+-{
+-	struct T_primsg *it;
+-	struct T_ok_ack *ok;
+-	
+-	SOLD("creating ok ack");
+-	it = timod_mkctl(sizeof(*ok));
+-	if (it) {
+-		SOLD("got it");
+-		ok = (struct T_ok_ack *)&it->type;
+-		ok->PRIM_type = T_OK_ACK;
+-		ok->CORRECT_prim = prim;
+-		timod_queue(fd, it);
+-	}
+-	SOLD("done");
+-}
+-
+-static int timod_optmgmt(unsigned int fd, int flag, char __user *opt_buf, int opt_len, int do_ret)
+-{
+-	int error, failed;
+-	int ret_space, ret_len;
+-	long args[5];
+-	char *ret_pos,*ret_buf;
+-	int (*sys_socketcall)(int, unsigned long *) =
+-		(int (*)(int, unsigned long *))SYS(socketcall);
+-	mm_segment_t old_fs = get_fs();
+-
+-	SOLD("entry");
+-	SOLDD(("fd %u flg %u buf %p len %u doret %u",fd,flag,opt_buf,opt_len,do_ret));
+-	if (!do_ret && (!opt_buf || opt_len <= 0))
+-		return 0;
+-	SOLD("getting page");
+-	ret_pos = ret_buf = getpage();
+-	ret_space = BUF_SIZE;
+-	ret_len = 0;
+-	
+-	error = failed = 0;
+-	SOLD("looping");
+-	while(opt_len >= sizeof(struct opthdr)) {
+-		struct opthdr *opt;
+-		int orig_opt_len; 
+-		SOLD("loop start");
+-		opt = (struct opthdr *)ret_pos; 
+-		if (ret_space < sizeof(struct opthdr)) {
+-			failed = TSYSERR;
+-			break;
+-		}
+-		SOLD("getting opthdr");
+-		if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) ||
+-			opt->len > opt_len) {
+-			failed = TBADOPT;
+-			break;
+-		}
+-		SOLD("got opthdr");
+-		if (flag == T_NEGOTIATE) {
+-			char *buf;
+-			
+-			SOLD("handling T_NEGOTIATE");
+-			buf = ret_pos + sizeof(struct opthdr);
+-			if (ret_space < opt->len + sizeof(struct opthdr) ||
+-				copy_from_user(buf, opt_buf+sizeof(struct opthdr), opt->len)) {
+-				failed = TSYSERR;
+-				break;
+-			}
+-			SOLD("got optdata");
+-			args[0] = fd;
+-			args[1] = opt->level;
+-			args[2] = opt->name;
+-			args[3] = (long)buf;
+-			args[4] = opt->len;
+-			SOLD("calling SETSOCKOPT");
+-			set_fs(KERNEL_DS);
+-			error = sys_socketcall(SYS_SETSOCKOPT, args);
+-			set_fs(old_fs);
+-			if (error) {
+-				failed = TBADOPT;
+-				break;
+-			}
+-			SOLD("SETSOCKOPT ok");
+-		}
+-		orig_opt_len = opt->len;
+-		opt->len = ret_space - sizeof(struct opthdr);
+-		if (opt->len < 0) {
+-			failed = TSYSERR;
+-			break;
+-		}
+-		args[0] = fd;
+-		args[1] = opt->level;
+-		args[2] = opt->name;
+-		args[3] = (long)(ret_pos+sizeof(struct opthdr));
+-		args[4] = (long)&opt->len;
+-		SOLD("calling GETSOCKOPT");
+-		set_fs(KERNEL_DS);
+-		error = sys_socketcall(SYS_GETSOCKOPT, args);
+-		set_fs(old_fs);
+-		if (error) {
+-			failed = TBADOPT;
+-			break;
+-		}
+-		SOLD("GETSOCKOPT ok");
+-		ret_space -= sizeof(struct opthdr) + opt->len;
+-		ret_len += sizeof(struct opthdr) + opt->len;
+-		ret_pos += sizeof(struct opthdr) + opt->len;
+-		opt_len -= sizeof(struct opthdr) + orig_opt_len;
+-		opt_buf += sizeof(struct opthdr) + orig_opt_len;
+-		SOLD("loop end");
+-	}
+-	SOLD("loop done");
+-	if (do_ret) {
+-		SOLD("generating ret msg");
+-		if (failed)
+-			timod_error(fd, T_OPTMGMT_REQ, failed, -error);
+-		else {
+-			struct T_primsg *it;
+-			it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len);
+-			if (it) {
+-				struct T_optmgmt_ack *ack =
+-					(struct T_optmgmt_ack *)&it->type;
+-				SOLD("got primsg");
+-				ack->PRIM_type = T_OPTMGMT_ACK;
+-				ack->OPT_length = ret_len;
+-				ack->OPT_offset = sizeof(struct T_optmgmt_ack);
+-				ack->MGMT_flags = (failed ? T_FAILURE : flag);
+-				memcpy(((char*)ack)+sizeof(struct T_optmgmt_ack),
+-					ret_buf, ret_len);
+-				timod_queue(fd, it);
+-			}
+-		}
+-	}
+-	SOLDD(("put_page %p\n", ret_buf));
+-	putpage(ret_buf);
+-	SOLD("done");	
+-	return 0;
+-}
+-
+-int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
+-			char __user *data_buf, int data_len, int flags)
+-{
+-	int ret, error, terror;
+-	char *buf;
+-	struct file *filp;
+-	struct inode *ino;
+-	struct fdtable *fdt;
+-	struct sol_socket_struct *sock;
+-	mm_segment_t old_fs = get_fs();
+-	long args[6];
+-	int (*sys_socketcall)(int, unsigned long __user *) =
+-		(int (*)(int, unsigned long __user *))SYS(socketcall);
+-	int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int) =
+-		(int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int))SYS(sendto);
+-
+-	fdt = files_fdtable(current->files);
+-	filp = fdt->fd[fd];
+-	ino = filp->f_path.dentry->d_inode;
+-	sock = (struct sol_socket_struct *)filp->private_data;
+-	SOLD("entry");
+-	if (get_user(ret, (int __user *)A(ctl_buf)))
+-		return -EFAULT;
+-	switch (ret) {
+-	case T_BIND_REQ:
+-	{
+-		struct T_bind_req req;
+-		
+-		SOLDD(("bind %016lx(%016lx)\n", sock, filp));
+-		SOLD("T_BIND_REQ");
+-		if (sock->state != TS_UNBND) {
+-			timod_error(fd, T_BIND_REQ, TOUTSTATE, 0);
+-			return 0;
+-		}
+-		SOLD("state ok");
+-		if (copy_from_user(&req, ctl_buf, sizeof(req))) {
+-			timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
+-			return 0;
+-		}
+-		SOLD("got ctl req");
+-		if (req.ADDR_offset && req.ADDR_length) {
+-			if (req.ADDR_length > BUF_SIZE) {
+-				timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
+-				return 0;
+-			}
+-			SOLD("req size ok");
+-			buf = getpage();
+-			if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) {
+-				timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
+-				putpage(buf);
+-				return 0;
+-			}
+-			SOLD("got ctl data");
+-			args[0] = fd;
+-			args[1] = (long)buf;
+-			args[2] = req.ADDR_length;
+-			SOLD("calling BIND");
+-			set_fs(KERNEL_DS);
+-			error = sys_socketcall(SYS_BIND, args);
+-			set_fs(old_fs);
+-			putpage(buf);
+-			SOLD("BIND returned");
+-		} else 
+-			error = 0;
+-		if (!error) {
+-			struct T_primsg *it;
+-			if (req.CONIND_number) {
+-	  			args[0] = fd;
+-  				args[1] = req.CONIND_number;
+-  				SOLD("calling LISTEN");
+-  				set_fs(KERNEL_DS);
+-	  			error = sys_socketcall(SYS_LISTEN, args);
+-  				set_fs(old_fs);
+-  				SOLD("LISTEN done");
+-  			}
+-			it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr));
+-			if (it) {
+-				struct T_bind_ack *ack;
+-
+-				ack = (struct T_bind_ack *)&it->type;
+-				ack->PRIM_type = T_BIND_ACK;
+-				ack->ADDR_offset = sizeof(*ack);
+-				ack->ADDR_length = sizeof(struct sockaddr);
+-				ack->CONIND_number = req.CONIND_number;
+-				args[0] = fd;
+-				args[1] = (long)(ack+sizeof(*ack));
+-				args[2] = (long)&ack->ADDR_length;
+-				set_fs(KERNEL_DS);
+-				sys_socketcall(SYS_GETSOCKNAME,args);
+-				set_fs(old_fs);
+-				sock->state = TS_IDLE;
+-				timod_ok(fd, T_BIND_REQ);
+-				timod_queue_end(fd, it);
+-				SOLD("BIND done");
+-				return 0;
+-			}
+-		}
+-		SOLD("some error");
+-		switch (error) {
+-			case -EINVAL:
+-				terror = TOUTSTATE;
+-				error = 0;
+-				break;
+-			case -EACCES:
+-				terror = TACCES;
+-				error = 0;
+-				break;
+-			case -EADDRNOTAVAIL:
+-			case -EADDRINUSE:
+-				terror = TNOADDR;
+-				error = 0;
+-				break;
+-			default:
+-				terror = TSYSERR;
+-				break;
+-		}
+-		timod_error(fd, T_BIND_REQ, terror, -error);
+-		SOLD("BIND done");
+-		return 0;
+-	}
+-	case T_CONN_REQ:
+-	{
+-		struct T_conn_req req;
+-		unsigned short oldflags;
+-		struct T_primsg *it;
+-		SOLD("T_CONN_REQ");
+-		if (sock->state != TS_UNBND && sock->state != TS_IDLE) {
+-			timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
+-			return 0;
+-		}
+-		SOLD("state ok");
+-		if (copy_from_user(&req, ctl_buf, sizeof(req))) {
+-			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
+-			return 0;
+-		}
+-		SOLD("got ctl req");
+-		if (ctl_len > BUF_SIZE) {
+-			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
+-			return 0;
+-		}
+-		SOLD("req size ok");
+-		buf = getpage();
+-		if (copy_from_user(buf, ctl_buf, ctl_len)) {
+-			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
+-			putpage(buf);
+-			return 0;
+-		}
+-#ifdef DEBUG_SOLARIS		
+-		{
+-			char * ptr = buf;
+-			int len = ctl_len;
+-			printk("returned data (%d bytes): ",len);
+-			while( len-- ) {
+-				if (!(len & 7))
+-					printk(" ");
+-				printk("%02x",(unsigned char)*ptr++);
+-			}
+-			printk("\n");
+-		}
+-#endif
+-		SOLD("got ctl data");
+-		args[0] = fd;
+-		args[1] = (long)buf+req.DEST_offset;
+-		args[2] = req.DEST_length;
+-		oldflags = filp->f_flags;
+-		filp->f_flags &= ~O_NONBLOCK;
+-		SOLD("calling CONNECT");
+-		set_fs(KERNEL_DS);
+-		error = sys_socketcall(SYS_CONNECT, args);
+-		set_fs(old_fs);
+-		filp->f_flags = oldflags;
+-		SOLD("CONNECT done");
+-		if (!error) {
+-			struct T_conn_con *con;
+-			SOLD("no error");
+-			it = timod_mkctl(ctl_len);
+-			if (!it) {
+-				putpage(buf);
+-				return -ENOMEM;
+-			}
+-			con = (struct T_conn_con *)&it->type;
+-#ifdef DEBUG_SOLARIS			
+-			{
+-				char * ptr = buf;
+-				int len = ctl_len;
+-				printk("returned data (%d bytes): ",len);
+-				while( len-- ) {
+-					if (!(len & 7))
+-						printk(" ");
+-					printk("%02x",(unsigned char)*ptr++);
+-				}
+-				printk("\n");
+-			}
+-#endif
+-			memcpy(con, buf, ctl_len);
+-			SOLD("copied ctl_buf");
+-			con->PRIM_type = T_CONN_CON;
+-			sock->state = TS_DATA_XFER;
+-		} else {
+-			struct T_discon_ind *dis;
+-			SOLD("some error");
+-			it = timod_mkctl(sizeof(*dis));
+-			if (!it) {
+-				putpage(buf);
+-				return -ENOMEM;
+-			}
+-			SOLD("got primsg");
+-			dis = (struct T_discon_ind *)&it->type;
+-			dis->PRIM_type = T_DISCON_IND;
+-			dis->DISCON_reason = -error;	/* FIXME: convert this as in iABI_errors() */
+-			dis->SEQ_number = 0;
+-		}
+-		putpage(buf);
+-		timod_ok(fd, T_CONN_REQ);
+-		it->pri = 0;
+-		timod_queue_end(fd, it);
+-		SOLD("CONNECT done");
+-		return 0;
+-	}
+-	case T_OPTMGMT_REQ:
+-	{
+-		struct T_optmgmt_req req;
+-		SOLD("OPTMGMT_REQ");
+-		if (copy_from_user(&req, ctl_buf, sizeof(req)))
+-			return -EFAULT;
+-		SOLD("got req");
+-		return timod_optmgmt(fd, req.MGMT_flags,
+-				req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL,
+-				req.OPT_length, 1);
+-	}
+-	case T_UNITDATA_REQ:
+-	{
+-		struct T_unitdata_req req;
+-		
+-		int err;
+-		SOLD("T_UNITDATA_REQ");
+-		if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) {
+-			timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
+-			return 0;
+-		}
+-		SOLD("state ok");
+-		if (copy_from_user(&req, ctl_buf, sizeof(req))) {
+-			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
+-			return 0;
+-		}
+-		SOLD("got ctl req");
+-#ifdef DEBUG_SOLARIS		
+-		{
+-			char * ptr = ctl_buf+req.DEST_offset;
+-			int len = req.DEST_length;
+-			printk("socket address (%d bytes): ",len);
+-			while( len-- ) {
+-				char c;
+-				if (get_user(c,ptr))
+-					printk("??");
+-				else
+-					printk("%02x",(unsigned char)c);
+-				ptr++;
+-			}
+-			printk("\n");
+-		}
+-#endif		
+-		err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr __user *)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length);
+-		if (err == data_len)
+-			return 0;
+-		if(err >= 0) {
+-			printk("timod: sendto failed to send all the data\n");
+-			return 0;
+-		}
+-		timod_error(fd, T_CONN_REQ, TSYSERR, -err);
+-		return 0;
+-	}
+-	default:
+-		printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret);
+-		break;
+-	}
+-	return -EINVAL;
+-}
+-
+-int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __user *ctl_len,
+-			char __user *data_buf, int data_maxlen, s32 __user *data_len, int *flags_p)
+-{
+-	int error;
+-	int oldflags;
+-	struct file *filp;
+-	struct inode *ino;
+-	struct fdtable *fdt;
+-	struct sol_socket_struct *sock;
+-	struct T_unitdata_ind udi;
+-	mm_segment_t old_fs = get_fs();
+-	long args[6];
+-	char __user *tmpbuf;
+-	int tmplen;
+-	int (*sys_socketcall)(int, unsigned long __user *) =
+-		(int (*)(int, unsigned long __user *))SYS(socketcall);
+-	int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *);
+-	
+-	SOLD("entry");
+-	SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));
+-	fdt = files_fdtable(current->files);
+-	filp = fdt->fd[fd];
+-	ino = filp->f_path.dentry->d_inode;
+-	sock = (struct sol_socket_struct *)filp->private_data;
+-	SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
+-	if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM
+-		&& sock->state == TS_IDLE) {
+-		SOLD("calling LISTEN");
+-		args[0] = fd;
+-		args[1] = -1;
+-		set_fs(KERNEL_DS);
+-		sys_socketcall(SYS_LISTEN, args);
+-		set_fs(old_fs);
+-		SOLD("LISTEN done");
+-	}
+-	if (!(filp->f_flags & O_NONBLOCK)) {
+-		struct poll_wqueues wait_table;
+-		poll_table *wait;
+-
+-		poll_initwait(&wait_table);
+-		wait = &wait_table.pt;
+-		for(;;) {
+-			SOLD("loop");
+-			set_current_state(TASK_INTERRUPTIBLE);
+-			/* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ 
+-			/* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ 
+-			/* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ 
+-			/* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */ 
+-			/* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */ 
+-			/* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */ 
+-			if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI))
+-				break;
+-			SOLD("cond 1 passed");
+-			if (
+-			#if 1
+-				*flags_p != MSG_HIPRI &&
+-			#endif
+-				((filp->f_op->poll(filp, wait) & POLLIN) ||
+-				(filp->f_op->poll(filp, NULL) & POLLIN) ||
+-				signal_pending(current))
+-			) {
+-				break;
+-			}
+-			if( *flags_p == MSG_HIPRI ) {
+-				SOLD("avoiding lockup");
+-				break ;
+-			}
+-			if(wait_table.error) {
+-				SOLD("wait-table error");
+-				poll_freewait(&wait_table);
+-				return wait_table.error;
+-			}
+-			SOLD("scheduling");
+-			schedule();
+-		}
+-		SOLD("loop done");
+-		current->state = TASK_RUNNING;
+-		poll_freewait(&wait_table);
+-		if (signal_pending(current)) {
+-			SOLD("signal pending");
+-			return -EINTR;
+-		}
+-	}
+-	if (ctl_maxlen >= 0 && sock->pfirst) {
+-		struct T_primsg *it = sock->pfirst;
+-		int l = min_t(int, ctl_maxlen, it->length);
+-		SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC);
+-		SOLD("purting ctl data");
+-		if(copy_to_user(ctl_buf,
+-			(char*)&it->type + sock->offset, l))
+-			return -EFAULT;
+-		SOLD("pur it");
+-		if(put_user(l, ctl_len))
+-			return -EFAULT;
+-		SOLD("set ctl_len");
+-		*flags_p = it->pri;
+-		it->length -= l;
+-		if (it->length) {
+-			SOLD("more ctl");
+-			sock->offset += l;
+-			return MORECTL;
+-		} else {
+-			SOLD("removing message");
+-			sock->pfirst = it->next;
+-			if (!sock->pfirst)
+-				sock->plast = NULL;
+-			SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst));
+-			mykfree(it);
+-			sock->offset = 0;
+-			SOLD("ctl done");
+-			return 0;
+-		}
+-	}
+-	*flags_p = 0;
+-	if (ctl_maxlen >= 0) {
+-		SOLD("ACCEPT perhaps?");
+-		if (SOCKET_I(ino)->type == SOCK_STREAM && sock->state == TS_IDLE) {
+-			struct T_conn_ind ind;
+-			char *buf = getpage();
+-			int len = BUF_SIZE;
+-
+-			SOLD("trying ACCEPT");
+-			if (put_user(ctl_maxlen - sizeof(ind), ctl_len))
+-				return -EFAULT;
+-			args[0] = fd;
+-			args[1] = (long)buf;
+-			args[2] = (long)&len;
+-			oldflags = filp->f_flags;
+-			filp->f_flags |= O_NONBLOCK;
+-			SOLD("calling ACCEPT");
+-			set_fs(KERNEL_DS);
+-			error = sys_socketcall(SYS_ACCEPT, args);
+-			set_fs(old_fs);
+-			filp->f_flags = oldflags;
+-			if (error < 0) {
+-				SOLD("some error");
+-				putpage(buf);
+-				return error;
+-			}
+-			if (error) {
+-				SOLD("connect");
+-				putpage(buf);
+-				if (sizeof(ind) > ctl_maxlen) {
+-					SOLD("generating CONN_IND");
+-					ind.PRIM_type = T_CONN_IND;
+-					ind.SRC_length = len;
+-					ind.SRC_offset = sizeof(ind);
+-					ind.OPT_length = ind.OPT_offset = 0;
+-					ind.SEQ_number = error;
+-					if(copy_to_user(ctl_buf, &ind, sizeof(ind))||
+-					   put_user(sizeof(ind)+ind.SRC_length,ctl_len))
+-						return -EFAULT;
+-					SOLD("CONN_IND created");
+-				}
+-				if (data_maxlen >= 0)
+-					put_user(0, data_len);
+-				SOLD("CONN_IND done");
+-				return 0;
+-			}
+-			if (len>ctl_maxlen) {
+-				SOLD("data don't fit");
+-				putpage(buf);
+-				return -EFAULT;		/* XXX - is this ok ? */
+-			}
+-			if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){
+-				SOLD("can't copy data");
+-				putpage(buf);
+-				return -EFAULT;
+-			}
+-			SOLD("ACCEPT done");
+-			putpage(buf);
+-		}
+-	}
+-	SOLD("checking data req");
+-	if (data_maxlen <= 0) {
+-		if (data_maxlen == 0)
+-			put_user(0, data_len);
+-		if (ctl_maxlen >= 0)
+-			put_user(0, ctl_len);
+-		return -EAGAIN;
+-	}
+-	SOLD("wants data");
+-	if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
+-		SOLD("udi fits");
+-		tmpbuf = ctl_buf + sizeof(udi);
+-		tmplen = ctl_maxlen - sizeof(udi);
+-	} else {
+-		SOLD("udi does not fit");
+-		tmpbuf = NULL;
+-		tmplen = 0;
+-	}
+-	if (put_user(tmplen, ctl_len))
+-		return -EFAULT;
+-	SOLD("set ctl_len");
+-	oldflags = filp->f_flags;
+-	filp->f_flags |= O_NONBLOCK;
+-	SOLD("calling recvfrom");
+-	sys_recvfrom = (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom);
+-	error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr __user *)tmpbuf, ctl_len);
+-	filp->f_flags = oldflags;
+-	if (error < 0)
+-		return error;
+-	SOLD("error >= 0" ) ;
+-	if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
+-		SOLD("generating udi");
+-		udi.PRIM_type = T_UNITDATA_IND;
+-		if (get_user(udi.SRC_length, ctl_len))
+-			return -EFAULT;
+-		udi.SRC_offset = sizeof(udi);
+-		udi.OPT_length = udi.OPT_offset = 0;
+-		if (copy_to_user(ctl_buf, &udi, sizeof(udi)) ||
+-		    put_user(sizeof(udi)+udi.SRC_length, ctl_len))
+-			return -EFAULT;
+-		SOLD("udi done");
+-	} else {
+-		if (put_user(0, ctl_len))
+-			return -EFAULT;
+-	}
+-	put_user(error, data_len);
+-	SOLD("done");
+-	return 0;
+-}
+-
+-asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
+-{
+-	struct file *filp;
+-	struct inode *ino;
+-	struct strbuf __user *ctlptr;
+-	struct strbuf __user *datptr;
+-	struct strbuf ctl, dat;
+-	int __user *flgptr;
+-	int flags;
+-	int error = -EBADF;
+-	struct fdtable *fdt;
+-
+-	SOLD("entry");
+-	lock_kernel();
+-	if (fd >= sysctl_nr_open)
+-		goto out;
+-
+-	fdt = files_fdtable(current->files);
+-	filp = fdt->fd[fd];
+-	if(!filp) goto out;
+-
+-	ino = filp->f_path.dentry->d_inode;
+-	if (!ino || !S_ISSOCK(ino->i_mode))
+-		goto out;
+-
+-	ctlptr = (struct strbuf __user *)A(arg1);
+-	datptr = (struct strbuf __user *)A(arg2);
+-	flgptr = (int __user *)A(arg3);
+-
+-	error = -EFAULT;
+-
+-	if (ctlptr) {
+-		if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) || 
+-		    put_user(-1,&ctlptr->len))
+-			goto out;
+-	} else
+-		ctl.maxlen = -1;
+-
+-	if (datptr) {
+-		if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) || 
+-		    put_user(-1,&datptr->len))
+-			goto out;
+-	} else
+-		dat.maxlen = -1;
+-
+-	if (get_user(flags,flgptr))
+-		goto out;
+-
+-	switch (flags) {
+-	case 0:
+-	case MSG_HIPRI:
+-	case MSG_ANY:
+-	case MSG_BAND:
+-		break;
+-	default:
+-		error = -EINVAL;
+-		goto out;
+-	}
+-
+-	error = timod_getmsg(fd,A(ctl.buf),ctl.maxlen,&ctlptr->len,
+-				A(dat.buf),dat.maxlen,&datptr->len,&flags);
+-
+-	if (!error && put_user(flags,flgptr))
+-		error = -EFAULT;
+-out:
+-	unlock_kernel();
+-	SOLD("done");
+-	return error;
+-}
+-
+-asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
+-{
+-	struct file *filp;
+-	struct inode *ino;
+-	struct strbuf __user *ctlptr;
+-	struct strbuf __user *datptr;
+-	struct strbuf ctl, dat;
+-	int flags = (int) arg3;
+-	int error = -EBADF;
+-	struct fdtable *fdt;
+-
+-	SOLD("entry");
+-	lock_kernel();
+-	if (fd >= sysctl_nr_open)
+-		goto out;
+-
+-	fdt = files_fdtable(current->files);
+-	filp = fdt->fd[fd];
+-	if(!filp) goto out;
+-
+-	ino = filp->f_path.dentry->d_inode;
+-	if (!ino) goto out;
+-
+-	if (!S_ISSOCK(ino->i_mode) &&
+-		(imajor(ino) != 30 || iminor(ino) != 1))
+-		goto out;
+-
+-	ctlptr = A(arg1);
+-	datptr = A(arg2);
+-
+-	error = -EFAULT;
+-
+-	if (ctlptr) {
+-		if (copy_from_user(&ctl,ctlptr,sizeof(ctl)))
+-			goto out;
+-		if (ctl.len < 0 && flags) {
+-			error = -EINVAL;
+-			goto out;
+-		}
+-	} else {
+-		ctl.len = 0;
+-		ctl.buf = 0;
+-	}
+-
+-	if (datptr) {
+-		if (copy_from_user(&dat,datptr,sizeof(dat)))
+-			goto out;
+-	} else {
+-		dat.len = 0;
+-		dat.buf = 0;
+-	}
+-
+-	error = timod_putmsg(fd,A(ctl.buf),ctl.len,
+-				A(dat.buf),dat.len,flags);
+-out:
+-	unlock_kernel();
+-	SOLD("done");
+-	return error;
+-}
+diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
+index 3cd8a04..e09edfa 100644
+--- a/arch/um/Kconfig.i386
++++ b/arch/um/Kconfig.i386
+@@ -19,10 +19,6 @@ config 64BIT
+ 	bool
+ 	default n
+ 
+-config SEMAPHORE_SLEEPERS
+-	bool
+-	default y
+-
+ config 3_LEVEL_PGTABLES
+ 	bool "Three-level pagetables (EXPERIMENTAL)"
+ 	default n
+diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64
+index 6533b34..3fbe69e 100644
+--- a/arch/um/Kconfig.x86_64
++++ b/arch/um/Kconfig.x86_64
+@@ -11,10 +11,6 @@ config RWSEM_GENERIC_SPINLOCK
+ 	bool
+ 	default y
+ 
+-config SEMAPHORE_SLEEPERS
+-	bool
+-	default y
+-
+ config 3_LEVEL_PGTABLES
+        bool
+        default y
+diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
+index 2a1eac1..bfbefd3 100644
+--- a/arch/um/sys-i386/ksyms.c
++++ b/arch/um/sys-i386/ksyms.c
+@@ -1,17 +1,5 @@
+ #include "linux/module.h"
+-#include "linux/in6.h"
+-#include "linux/rwsem.h"
+-#include "asm/byteorder.h"
+-#include "asm/delay.h"
+-#include "asm/semaphore.h"
+-#include "asm/uaccess.h"
+ #include "asm/checksum.h"
+-#include "asm/errno.h"
+-
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+ 
+ /* Networking helper routines. */
+ EXPORT_SYMBOL(csum_partial);
+diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
+index 0890152..b8bc844 100644
+--- a/arch/um/sys-ppc/Makefile
++++ b/arch/um/sys-ppc/Makefile
+@@ -3,7 +3,7 @@ OBJ = built-in.o
+ .S.o:
+ 	$(CC) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+ 
+-OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
++OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \
+ 	ptrace_user.o sysrq.o
+ 
+ EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
+@@ -20,10 +20,6 @@ ptrace_user.o: ptrace_user.c
+ sigcontext.o: sigcontext.c
+ 	$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+ 
+-semaphore.c:
+-	rm -f $@
+-	ln -s $(srctree)/arch/ppc/kernel/$@ $@
+-
+ checksum.S:
+ 	rm -f $@
+ 	ln -s $(srctree)/arch/ppc/lib/$@ $@
+@@ -66,4 +62,4 @@ misc.o: misc.S ppc_defs.h
+ 	$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+ 	rm -f asm
+ 
+-clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c
++clean-files := $(OBJS) ppc_defs.h checksum.S mk_defs.c
+diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c
+index 12c5936..4d7d1a8 100644
+--- a/arch/um/sys-x86_64/ksyms.c
++++ b/arch/um/sys-x86_64/ksyms.c
+@@ -1,16 +1,5 @@
+ #include "linux/module.h"
+-#include "linux/in6.h"
+-#include "linux/rwsem.h"
+-#include "asm/byteorder.h"
+-#include "asm/semaphore.h"
+-#include "asm/uaccess.h"
+-#include "asm/checksum.h"
+-#include "asm/errno.h"
+-
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
++#include "asm/string.h"
+ 
+ /*XXX: we need them because they would be exported by x86_64 */
+ EXPORT_SYMBOL(__memcpy);
+diff --git a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
+index 3930482..da5889c 100644
+--- a/arch/v850/kernel/Makefile
++++ b/arch/v850/kernel/Makefile
+@@ -11,7 +11,7 @@
+ 
+ extra-y := head.o init_task.o vmlinux.lds
+ 
+-obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \
++obj-y += intv.o entry.o process.o syscalls.o time.o setup.o \
+ 	 signal.o irq.o mach.o ptrace.o bug.o
+ obj-$(CONFIG_MODULES)		+= module.o v850_ksyms.o
+ # chip-specific code
+diff --git a/arch/v850/kernel/semaphore.c b/arch/v850/kernel/semaphore.c
+deleted file mode 100644
+index fc89fd6..0000000
+--- a/arch/v850/kernel/semaphore.c
++++ /dev/null
+@@ -1,166 +0,0 @@
+-/*
+- * arch/v850/kernel/semaphore.c -- Semaphore support
+- *
+- *  Copyright (C) 1998-2000  IBM Corporation
+- *  Copyright (C) 1999  Linus Torvalds
+- *
+- * This file is subject to the terms and conditions of the GNU General
+- * Public License.  See the file COPYING in the main directory of this
+- * archive for more details.
+- *
+- * This file is a copy of the s390 version, arch/s390/kernel/semaphore.c
+- *    Author(s): Martin Schwidefsky
+- * which was derived from the i386 version, linux/arch/i386/kernel/semaphore.c
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is
+- * protected by the semaphore spinlock.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- *  - only on a boundary condition do we need to care. When we go
+- *    from a negative count to a non-negative, we wake people up.
+- *  - when we go from a non-negative count to a negative do we
+- *    (a) synchronize with the "sleeper" count and (b) make sure
+- *    that we're on the wakeup list before we synchronize so that
+- *    we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+-	wake_up(&sem->wait);
+-}
+-
+-static DEFINE_SPINLOCK(semaphore_lock);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	tsk->state = TASK_UNINTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	spin_lock_irq(&semaphore_lock);
+-	sem->sleepers++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irq(&semaphore_lock);
+-
+-		schedule();
+-		tsk->state = TASK_UNINTERRUPTIBLE;
+-		spin_lock_irq(&semaphore_lock);
+-	}
+-	spin_unlock_irq(&semaphore_lock);
+-	remove_wait_queue(&sem->wait, &wait);
+-	tsk->state = TASK_RUNNING;
+-	wake_up(&sem->wait);
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	tsk->state = TASK_INTERRUPTIBLE;
+-	add_wait_queue_exclusive(&sem->wait, &wait);
+-
+-	spin_lock_irq(&semaphore_lock);
+-	sem->sleepers ++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * With signals pending, this turns into
+-		 * the trylock failure case - we won't be
+-		 * sleeping, and we* can't get the lock as
+-		 * it has contention. Just correct the count
+-		 * and exit.
+-		 */
+-		if (signal_pending(current)) {
+-			retval = -EINTR;
+-			sem->sleepers = 0;
+-			atomic_add(sleepers, &sem->count);
+-			break;
+-		}
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock. The
+-		 * "-1" is because we're still hoping to get
+-		 * the lock.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irq(&semaphore_lock);
+-
+-		schedule();
+-		tsk->state = TASK_INTERRUPTIBLE;
+-		spin_lock_irq(&semaphore_lock);
+-	}
+-	spin_unlock_irq(&semaphore_lock);
+-	tsk->state = TASK_RUNNING;
+-	remove_wait_queue(&sem->wait, &wait);
+-	wake_up(&sem->wait);
+-	return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- */
+-int __down_trylock(struct semaphore * sem)
+-{
+-        unsigned long flags;
+-	int sleepers;
+-
+-	spin_lock_irqsave(&semaphore_lock, flags);
+-	sleepers = sem->sleepers + 1;
+-	sem->sleepers = 0;
+-
+-	/*
+-	 * Add "everybody else" and us into it. They aren't
+-	 * playing, because we own the spinlock.
+-	 */
+-	if (!atomic_add_negative(sleepers, &sem->count))
+-		wake_up(&sem->wait);
+-
+-	spin_unlock_irqrestore(&semaphore_lock, flags);
+-	return 1;
+-}
+diff --git a/arch/v850/kernel/syscalls.c b/arch/v850/kernel/syscalls.c
+index 0a4df4d..003db9c 100644
+--- a/arch/v850/kernel/syscalls.c
++++ b/arch/v850/kernel/syscalls.c
+@@ -30,7 +30,6 @@
+ #include <linux/file.h>
+ 
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/unistd.h>
+ 
+ /*
+diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
+index 93575fd..8d386a5 100644
+--- a/arch/v850/kernel/v850_ksyms.c
++++ b/arch/v850/kernel/v850_ksyms.c
+@@ -11,7 +11,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/current.h>
+ 
+@@ -34,12 +33,6 @@ EXPORT_SYMBOL (memset);
+ EXPORT_SYMBOL (memcpy);
+ EXPORT_SYMBOL (memmove);
+ 
+-/* semaphores */
+-EXPORT_SYMBOL (__down);
+-EXPORT_SYMBOL (__down_interruptible);
+-EXPORT_SYMBOL (__down_trylock);
+-EXPORT_SYMBOL (__up);
+-
+ /*
+  * libgcc functions - functions that are used internally by the
+  * compiler...  (prototypes are not correct though, but that
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 6c70fed..2fadf79 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -23,6 +23,7 @@ config X86
+ 	select HAVE_KPROBES
+ 	select HAVE_KRETPROBES
+ 	select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
++	select HAVE_ARCH_KGDB if !X86_VOYAGER
+ 
+ 
+ config GENERIC_LOCKBREAK
+@@ -53,9 +54,6 @@ config STACKTRACE_SUPPORT
+ config HAVE_LATENCYTOP_SUPPORT
+ 	def_bool y
+ 
+-config SEMAPHORE_SLEEPERS
+-	def_bool y
+-
+ config FAST_CMPXCHG_LOCAL
+ 	bool
+ 	default y
+@@ -117,7 +115,10 @@ config ARCH_HAS_CPU_RELAX
+ 	def_bool y
+ 
+ config HAVE_SETUP_PER_CPU_AREA
+-	def_bool X86_64
++	def_bool X86_64 || (X86_SMP && !X86_VOYAGER)
++
++config HAVE_CPUMASK_OF_CPU_MAP
++	def_bool X86_64_SMP
+ 
+ config ARCH_HIBERNATION_POSSIBLE
+ 	def_bool y
+@@ -141,6 +142,9 @@ config AUDIT_ARCH
+ config ARCH_SUPPORTS_AOUT
+ 	def_bool y
+ 
++config ARCH_SUPPORTS_OPTIMIZED_INLINING
++	def_bool y
++
+ # Use the generic interrupt handling code in kernel/irq/:
+ config GENERIC_HARDIRQS
+ 	bool
+@@ -171,7 +175,7 @@ config X86_64_SMP
+ config X86_HT
+ 	bool
+ 	depends on SMP
+-	depends on (X86_32 && !(X86_VISWS || X86_VOYAGER)) || (X86_64 && !MK8)
++	depends on (X86_32 && !(X86_VISWS || X86_VOYAGER)) || X86_64
+ 	default y
+ 
+ config X86_BIOS_REBOOT
+@@ -181,7 +185,7 @@ config X86_BIOS_REBOOT
+ 
+ config X86_TRAMPOLINE
+ 	bool
+-	depends on X86_SMP || (X86_VOYAGER && SMP)
++	depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP)
+ 	default y
+ 
+ config KTIME_SCALAR
+@@ -241,8 +245,7 @@ config X86_ELAN
+ 
+ config X86_VOYAGER
+ 	bool "Voyager (NCR)"
+-	depends on X86_32
+-	select SMP if !BROKEN
++	depends on X86_32 && (SMP || BROKEN)
+ 	help
+ 	  Voyager is an MCA-based 32-way capable SMP architecture proprietary
+ 	  to NCR Corp.  Machine classes 345x/35xx/4100/51xx are Voyager-based.
+@@ -254,9 +257,8 @@ config X86_VOYAGER
+ 
+ config X86_NUMAQ
+ 	bool "NUMAQ (IBM/Sequent)"
+-	select SMP
++	depends on SMP && X86_32
+ 	select NUMA
+-	depends on X86_32
+ 	help
+ 	  This option is used for getting Linux to run on a (IBM/Sequent) NUMA
+ 	  multiquad box. This changes the way that processors are bootstrapped,
+@@ -327,8 +329,9 @@ config X86_RDC321X
+ 
+ config X86_VSMP
+ 	bool "Support for ScaleMP vSMP"
+-	depends on X86_64 && PCI
+-	 help
++	select PARAVIRT
++	depends on X86_64
++	help
+ 	  Support for ScaleMP vSMP systems.  Say 'Y' here if this kernel is
+ 	  supposed to run on these EM64T-based machines.  Only choose this option
+ 	  if you have one of these machines.
+@@ -383,6 +386,35 @@ config PARAVIRT
+ 
+ endif
+ 
++config MEMTEST_BOOTPARAM
++	bool "Memtest boot parameter"
++	depends on X86_64
++	default y
++	help
++	  This option adds a kernel parameter 'memtest', which allows memtest
++	  to be disabled at boot.  If this option is selected, memtest
++	  functionality can be disabled with memtest=0 on the kernel
++	  command line.  The purpose of this option is to allow a single
++	  kernel image to be distributed with memtest built in, but not
++	  necessarily enabled.
++
++	  If you are unsure how to answer this question, answer Y.
++
++config MEMTEST_BOOTPARAM_VALUE
++	int "Memtest boot parameter default value (0-4)"
++	depends on MEMTEST_BOOTPARAM
++	range 0 4
++	default 0
++	help
++	  This option sets the default value for the kernel parameter
++	  'memtest', which allows memtest to be disabled at boot.  If this
++	  option is set to 0 (zero), the memtest kernel parameter will
++	  default to 0, disabling memtest at bootup.  If this option is
++	  set to 4, the memtest kernel parameter will default to 4,
++	  enabling memtest at bootup, and use that as pattern number.
++
++	  If you are unsure how to answer this question, answer 0.
++
+ config ACPI_SRAT
+ 	def_bool y
+ 	depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
+@@ -507,7 +539,7 @@ config NR_CPUS
+ 
+ config SCHED_SMT
+ 	bool "SMT (Hyperthreading) scheduler support"
+-	depends on (X86_64 && SMP) || (X86_32 && X86_HT)
++	depends on X86_HT
+ 	help
+ 	  SMT scheduler support improves the CPU scheduler's decision making
+ 	  when dealing with Intel Pentium 4 chips with HyperThreading at a
+@@ -517,7 +549,7 @@ config SCHED_SMT
+ config SCHED_MC
+ 	def_bool y
+ 	prompt "Multi-core scheduler support"
+-	depends on (X86_64 && SMP) || (X86_32 && X86_HT)
++	depends on X86_HT
+ 	help
+ 	  Multi-core scheduler support improves the CPU scheduler's decision
+ 	  making when dealing with multi-core CPU chips at a cost of slightly
+@@ -877,6 +909,15 @@ config X86_64_ACPI_NUMA
+ 	help
+ 	  Enable ACPI SRAT based node topology detection.
+ 
++# Some NUMA nodes have memory ranges that span
++# other nodes.  Even though a pfn is valid and
++# between a node's start and end pfns, it may not
++# reside on that node.  See memmap_init_zone()
++# for details.
++config NODES_SPAN_OTHER_NODES
++	def_bool y
++	depends on X86_64_ACPI_NUMA
++
+ config NUMA_EMU
+ 	bool "NUMA emulation"
+ 	depends on X86_64 && NUMA
+@@ -886,7 +927,7 @@ config NUMA_EMU
+ 	  number of nodes. This is only useful for debugging.
+ 
+ config NODES_SHIFT
+-	int
++	int "Max num nodes shift(1-15)"
+ 	range 1 15  if X86_64
+ 	default "6" if X86_64
+ 	default "4" if X86_NUMAQ
+@@ -1010,6 +1051,21 @@ config MTRR
+ 
+ 	  See <file:Documentation/mtrr.txt> for more information.
+ 
++config X86_PAT
++	bool
++	prompt "x86 PAT support"
++	depends on MTRR
++	help
++	  Use PAT attributes to setup page level cache control.
++
++	  PATs are the modern equivalents of MTRRs and are much more
++	  flexible than MTRRs.
++
++	  Say N here if you see bootup problems (boot crash, boot hang,
++	  spontaneous reboots) or a non-working video driver.
++
++	  If unsure, say Y.
++
+ config EFI
+ 	def_bool n
+ 	prompt "EFI runtime service support"
+@@ -1078,6 +1134,7 @@ source kernel/Kconfig.hz
+ 
+ config KEXEC
+ 	bool "kexec system call"
++	depends on X86_64 || X86_BIOS_REBOOT
+ 	help
+ 	  kexec is a system call that implements the ability to shutdown your
+ 	  current kernel, and to start another kernel.  It is like a reboot
+@@ -1379,7 +1436,7 @@ endmenu
+ menu "Bus options (PCI etc.)"
+ 
+ config PCI
+-	bool "PCI support" if !X86_VISWS
++	bool "PCI support" if !X86_VISWS && !X86_VSMP
+ 	depends on !X86_VOYAGER
+ 	default y
+ 	select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
+diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
+index 9304bfb..4da3cdb 100644
+--- a/arch/x86/Kconfig.cpu
++++ b/arch/x86/Kconfig.cpu
+@@ -21,8 +21,8 @@ config M386
+ 
+ 	  Here are the settings recommended for greatest speed:
+ 	  - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI
+-	  486DLC/DLC2, UMC 486SX-S and NexGen Nx586.  Only "386" kernels
+-	  will run on a 386 class machine.
++	  486DLC/DLC2, and UMC 486SX-S.  Only "386" kernels will run on a 386
++	  class machine.
+ 	  - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
+ 	  SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
+ 	  - "586" for generic Pentium CPUs lacking the TSC
+@@ -388,7 +388,7 @@ config X86_OOSTORE
+ #
+ config X86_P6_NOP
+ 	def_bool y
+-	depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4)
++	depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4 || MPSC)
+ 
+ config X86_TSC
+ 	def_bool y
+diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
+index 702eb39..5b1979a 100644
+--- a/arch/x86/Kconfig.debug
++++ b/arch/x86/Kconfig.debug
+@@ -5,6 +5,17 @@ config TRACE_IRQFLAGS_SUPPORT
+ 
+ source "lib/Kconfig.debug"
+ 
++config NONPROMISC_DEVMEM
++	bool "Disable promiscuous /dev/mem"
++	help
++	  The /dev/mem file by default only allows userspace access to PCI
++	  space and the BIOS code and data regions. This is sufficient for
++	  dosemu and X and all common users of /dev/mem. With this config
++	  option, you allow userspace access to all of memory, including
++	  kernel and userspace memory. Accidental access to this is
++	  obviously disasterous, but specific access can be used by people
++	  debugging the kernel.
++
+ config EARLY_PRINTK
+ 	bool "Early printk" if EMBEDDED
+ 	default y
+@@ -54,6 +65,18 @@ config DEBUG_PER_CPU_MAPS
+ 
+ 	  Say N if unsure.
+ 
++config X86_PTDUMP
++	bool "Export kernel pagetable layout to userspace via debugfs"
++	depends on DEBUG_KERNEL
++	select DEBUG_FS
++	help
++	  Say Y here if you want to show the kernel pagetable layout in a
++	  debugfs file. This information is only useful for kernel developers
++	  who are working in architecture specific areas of the kernel.
++	  It is probably not a good idea to enable this feature in a production
++	  kernel.
++	  If in doubt, say "N"
++
+ config DEBUG_RODATA
+ 	bool "Write protect kernel read-only data structures"
+ 	default y
+@@ -64,6 +87,18 @@ config DEBUG_RODATA
+ 	  data. This is recommended so that we can catch kernel bugs sooner.
+ 	  If in doubt, say "Y".
+ 
++config DIRECT_GBPAGES
++	bool "Enable gbpages-mapped kernel pagetables"
++	depends on DEBUG_KERNEL && EXPERIMENTAL && X86_64
++	help
++	  Enable gigabyte pages support (if the CPU supports it). This can
++	  improve the kernel's performance a tiny bit by reducing TLB
++	  pressure.
++
++	  This is experimental code.
++
++	  If in doubt, say "N".
++
+ config DEBUG_RODATA_TEST
+ 	bool "Testcase for the DEBUG_RODATA feature"
+ 	depends on DEBUG_RODATA
+@@ -82,8 +117,8 @@ config DEBUG_NX_TEST
+ 
+ config 4KSTACKS
+ 	bool "Use 4Kb for kernel stacks instead of 8Kb"
+-	depends on DEBUG_KERNEL
+ 	depends on X86_32
++	default y
+ 	help
+ 	  If you say Y here the kernel will use a 4Kb stacksize for the
+ 	  kernel stack attached to each process/thread. This facilitates
+@@ -222,3 +257,16 @@ config CPA_DEBUG
+ 	  Do change_page_attr() self-tests every 30 seconds.
+ 
+ endmenu
++
++config OPTIMIZE_INLINING
++	bool "Allow gcc to uninline functions marked 'inline'"
++	default y
++	help
++	  This option determines if the kernel forces gcc to inline the functions
++	  developers have marked 'inline'. Doing so takes away freedom from gcc to
++	  do what it thinks is best, which is desirable for the gcc 3.x series of
++	  compilers. The gcc 4.x series have a rewritten inlining algorithm and
++	  disabling this option will generate a smaller kernel there. Hopefully
++	  this algorithm is so good that allowing gcc4 to make the decision can
++	  become the default in the future, until then this option is there to
++	  test gcc for this.
+diff --git a/arch/x86/Makefile b/arch/x86/Makefile
+index f1e739a..3cff3c8 100644
+--- a/arch/x86/Makefile
++++ b/arch/x86/Makefile
+@@ -151,7 +151,6 @@ mflags-y += -Iinclude/asm-x86/mach-default
+ # 64 bit does not support subarch support - clear sub arch variables
+ fcore-$(CONFIG_X86_64)  :=
+ mcore-$(CONFIG_X86_64)  :=
+-mflags-$(CONFIG_X86_64) :=
+ 
+ KBUILD_CFLAGS += $(mflags-y)
+ KBUILD_AFLAGS += $(mflags-y)
+@@ -159,9 +158,9 @@ KBUILD_AFLAGS += $(mflags-y)
+ ###
+ # Kernel objects
+ 
+-head-y                := arch/x86/kernel/head_$(BITS).o
+-head-$(CONFIG_X86_64) += arch/x86/kernel/head64.o
+-head-y                += arch/x86/kernel/init_task.o
++head-y := arch/x86/kernel/head_$(BITS).o
++head-y += arch/x86/kernel/head$(BITS).o
++head-y += arch/x86/kernel/init_task.o
+ 
+ libs-y  += arch/x86/lib/
+ 
+diff --git a/arch/x86/boot/.gitignore b/arch/x86/boot/.gitignore
+index b1bdc4c..172cf8a 100644
+--- a/arch/x86/boot/.gitignore
++++ b/arch/x86/boot/.gitignore
+@@ -1,7 +1,8 @@
+ bootsect
+ bzImage
++cpustr.h
++mkcpustr
++offsets.h
+ setup
+ setup.bin
+ setup.elf
+-cpustr.h
+-mkcpustr
+diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
+index f88458e..7ee102f 100644
+--- a/arch/x86/boot/Makefile
++++ b/arch/x86/boot/Makefile
+@@ -30,7 +30,7 @@ subdir-		:= compressed
+ 
+ setup-y		+= a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+ setup-y		+= header.o main.o mca.o memory.o pm.o pmjump.o
+-setup-y		+= printf.o string.o tty.o video.o version.o
++setup-y		+= printf.o string.o tty.o video.o video-mode.o version.o
+ setup-$(CONFIG_X86_APM_BOOT) += apm.o
+ setup-$(CONFIG_X86_VOYAGER) += voyager.o
+ 
+@@ -94,6 +94,20 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
+ 
+ SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
+ 
++sed-offsets := -e 's/^00*/0/' \
++        -e 's/^\([0-9a-fA-F]*\) . \(input_data\|input_data_end\)$$/\#define \2 0x\1/p'
++
++quiet_cmd_offsets = OFFSETS $@
++      cmd_offsets = $(NM) $< | sed -n $(sed-offsets) > $@
++
++$(obj)/offsets.h: $(obj)/compressed/vmlinux FORCE
++	$(call if_changed,offsets)
++
++targets += offsets.h
++
++AFLAGS_header.o += -I$(obj)
++$(obj)/header.o: $(obj)/offsets.h
++
+ LDFLAGS_setup.elf	:= -T
+ $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
+ 	$(call if_changed,ld)
+diff --git a/arch/x86/boot/a20.c b/arch/x86/boot/a20.c
+index 31348d0..90943f8 100644
+--- a/arch/x86/boot/a20.c
++++ b/arch/x86/boot/a20.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/a20.c
+- *
+  * Enable A20 gate (return -1 on failure)
+  */
+ 
+diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c
+index c117c7f..7aa6033 100644
+--- a/arch/x86/boot/apm.c
++++ b/arch/x86/boot/apm.c
+@@ -12,8 +12,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/apm.c
+- *
+  * Get APM BIOS information
+  */
+ 
+diff --git a/arch/x86/boot/bitops.h b/arch/x86/boot/bitops.h
+index 8dcc8dc..878e4b9 100644
+--- a/arch/x86/boot/bitops.h
++++ b/arch/x86/boot/bitops.h
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/bitops.h
+- *
+  * Very simple bitops for the boot code.
+  */
+ 
+diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
+index 7822a49..a34b998 100644
+--- a/arch/x86/boot/boot.h
++++ b/arch/x86/boot/boot.h
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/boot.h
+- *
+  * Header file for the real-mode kernel code
+  */
+ 
+@@ -286,6 +284,11 @@ int getchar_timeout(void);
+ /* video.c */
+ void set_video(void);
+ 
++/* video-mode.c */
++int set_mode(u16 mode);
++int mode_defined(u16 mode);
++void probe_cards(int unsafe);
++
+ /* video-vesa.c */
+ void vesa_store_edid(void);
+ 
+diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
+index 680408a..a1d3563 100644
+--- a/arch/x86/boot/cmdline.c
++++ b/arch/x86/boot/cmdline.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/cmdline.c
+- *
+  * Simple command-line parser for early boot.
+  */
+ 
+diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
+index d2b9f3b..92fdd35 100644
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -22,7 +22,7 @@ $(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $
+ 	$(call if_changed,ld)
+ 	@:
+ 
+-OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note -R .comment -S
++OBJCOPYFLAGS_vmlinux.bin :=  -R .comment -S
+ $(obj)/vmlinux.bin: vmlinux FORCE
+ 	$(call if_changed,objcopy)
+ 
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index 036e635..ba7736c 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -130,7 +130,7 @@ relocated:
+ /*
+  * Setup the stack for the decompressor
+  */
+-	leal stack_end(%ebx), %esp
++	leal boot_stack_end(%ebx), %esp
+ 
+ /*
+  * Do the decompression, and jump to the new kernel..
+@@ -142,8 +142,8 @@ relocated:
+ 	pushl %eax	# input_len
+ 	leal input_data(%ebx), %eax
+ 	pushl %eax	# input_data
+-	leal _end(%ebx), %eax
+-	pushl %eax	# end of the image as third argument
++	leal boot_heap(%ebx), %eax
++	pushl %eax	# heap area as third argument
+ 	pushl %esi	# real mode pointer as second arg
+ 	call decompress_kernel
+ 	addl $20, %esp
+@@ -181,7 +181,10 @@ relocated:
+ 	jmp *%ebp
+ 
+ .bss
++/* Stack and heap for uncompression */
+ .balign 4
+-stack:
+-	.fill 4096, 1, 0
+-stack_end:
++boot_heap:
++	.fill BOOT_HEAP_SIZE, 1, 0
++boot_stack:
++	.fill BOOT_STACK_SIZE, 1, 0
++boot_stack_end:
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index e8657b9..d8819ef 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -28,6 +28,7 @@
+ #include <asm/segment.h>
+ #include <asm/pgtable.h>
+ #include <asm/page.h>
++#include <asm/boot.h>
+ #include <asm/msr.h>
+ #include <asm/asm-offsets.h>
+ 
+@@ -62,7 +63,7 @@ startup_32:
+ 	subl	$1b, %ebp
+ 
+ /* setup a stack and make sure cpu supports long mode. */
+-	movl	$user_stack_end, %eax
++	movl	$boot_stack_end, %eax
+ 	addl	%ebp, %eax
+ 	movl	%eax, %esp
+ 
+@@ -243,9 +244,9 @@ ENTRY(startup_64)
+ /* Copy the compressed kernel to the end of our buffer
+  * where decompression in place becomes safe.
+  */
+-	leaq	_end(%rip), %r8
+-	leaq	_end(%rbx), %r9
+-	movq	$_end /* - $startup_32 */, %rcx
++	leaq	_end_before_pgt(%rip), %r8
++	leaq	_end_before_pgt(%rbx), %r9
++	movq	$_end_before_pgt /* - $startup_32 */, %rcx
+ 1:	subq	$8, %r8
+ 	subq	$8, %r9
+ 	movq	0(%r8), %rax
+@@ -267,14 +268,14 @@ relocated:
+  */
+ 	xorq	%rax, %rax
+ 	leaq    _edata(%rbx), %rdi
+-	leaq    _end(%rbx), %rcx
++	leaq    _end_before_pgt(%rbx), %rcx
+ 	subq	%rdi, %rcx
+ 	cld
+ 	rep
+ 	stosb
+ 
+ 	/* Setup the stack */
+-	leaq	user_stack_end(%rip), %rsp
++	leaq	boot_stack_end(%rip), %rsp
+ 
+ 	/* zero EFLAGS after setting rsp */
+ 	pushq	$0
+@@ -285,7 +286,7 @@ relocated:
+  */
+ 	pushq	%rsi			# Save the real mode argument
+ 	movq	%rsi, %rdi		# real mode address
+-	leaq	_heap(%rip), %rsi	# _heap
++	leaq	boot_heap(%rip), %rsi	# malloc area for uncompression
+ 	leaq	input_data(%rip), %rdx  # input_data
+ 	movl	input_len(%rip), %eax
+ 	movq	%rax, %rcx		# input_len
+@@ -310,9 +311,12 @@ gdt:
+ 	.quad	0x0080890000000000	/* TS descriptor */
+ 	.quad   0x0000000000000000	/* TS continued */
+ gdt_end:
+-	.bss
+-/* Stack for uncompression */
+-	.balign 4
+-user_stack:
+-	.fill 4096,4,0
+-user_stack_end:
++
++.bss
++/* Stack and heap for uncompression */
++.balign 4
++boot_heap:
++	.fill BOOT_HEAP_SIZE, 1, 0
++boot_stack:
++	.fill BOOT_STACK_SIZE, 1, 0
++boot_stack_end:
+diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
+index 8182e32..90456ce 100644
+--- a/arch/x86/boot/compressed/misc.c
++++ b/arch/x86/boot/compressed/misc.c
+@@ -15,6 +15,10 @@
+  * we just keep it from happening
+  */
+ #undef CONFIG_PARAVIRT
++#ifdef CONFIG_X86_32
++#define _ASM_DESC_H_ 1
++#endif
++
+ #ifdef CONFIG_X86_64
+ #define _LINUX_STRING_H_ 1
+ #define __LINUX_BITMAP_H 1
+@@ -22,6 +26,7 @@
+ 
+ #include <linux/linkage.h>
+ #include <linux/screen_info.h>
++#include <linux/elf.h>
+ #include <asm/io.h>
+ #include <asm/page.h>
+ #include <asm/boot.h>
+@@ -53,8 +58,8 @@
+  * 1 bit (last block flag)
+  * 2 bits (block type)
+  *
+- * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
+- * The smallest block type encoding is always used.
++ * 1 block occurs every 32K -1 bytes or when there 50% compression
++ * has been achieved. The smallest block type encoding is always used.
+  *
+  * stored:
+  *    32 bits length in bytes.
+@@ -90,9 +95,9 @@
+  *
+  * All of which is enough to compute an amount of extra data that is required
+  * to be safe.  To avoid problems at the block level allocating 5 extra bytes
+- * per 32767 bytes of data is sufficient.  To avoind problems internal to a block
+- * adding an extra 32767 bytes (the worst case uncompressed block size) is
+- * sufficient, to ensure that in the worst case the decompressed data for
++ * per 32767 bytes of data is sufficient.  To avoind problems internal to a
++ * block adding an extra 32767 bytes (the worst case uncompressed block size)
++ * is sufficient, to ensure that in the worst case the decompressed data for
+  * block will stop the byte before the compressed data for a block begins.
+  * To avoid problems with the compressed data's meta information an extra 18
+  * bytes are needed.  Leading to the formula:
+@@ -111,58 +116,66 @@
+  * gzip declarations
+  */
+ 
+-#define OF(args)  args
+-#define STATIC static
++#define OF(args)	args
++#define STATIC		static
+ 
+ #undef memset
+ #undef memcpy
+-#define memzero(s, n)     memset ((s), 0, (n))
++#define memzero(s, n)	memset((s), 0, (n))
+ 
+-typedef unsigned char  uch;
+-typedef unsigned short ush;
+-typedef unsigned long  ulg;
++typedef unsigned char	uch;
++typedef unsigned short	ush;
++typedef unsigned long	ulg;
+ 
+-#define WSIZE 0x80000000	/* Window size must be at least 32k,
+-				 * and a power of two
+-				 * We don't actually have a window just
+-				 * a huge output buffer so I report
+-				 * a 2G windows size, as that should
+-				 * always be larger than our output buffer.
+-				 */
++/*
++ * Window size must be at least 32k, and a power of two.
++ * We don't actually have a window just a huge output buffer,
++ * so we report a 2G window size, as that should always be
++ * larger than our output buffer:
++ */
++#define WSIZE		0x80000000
+ 
+-static uch *inbuf;	/* input buffer */
+-static uch *window;	/* Sliding window buffer, (and final output buffer) */
++/* Input buffer: */
++static unsigned char	*inbuf;
+ 
+-static unsigned insize;  /* valid bytes in inbuf */
+-static unsigned inptr;   /* index of next byte to be processed in inbuf */
+-static unsigned outcnt;  /* bytes in output buffer */
++/* Sliding window buffer (and final output buffer): */
++static unsigned char	*window;
++
++/* Valid bytes in inbuf: */
++static unsigned		insize;
++
++/* Index of next byte to be processed in inbuf: */
++static unsigned		inptr;
++
++/* Bytes in output buffer: */
++static unsigned		outcnt;
+ 
+ /* gzip flag byte */
+-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
+-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+-#define COMMENT      0x10 /* bit 4 set: file comment present */
+-#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+-#define RESERVED     0xC0 /* bit 6,7:   reserved */
+-
+-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+-		
++#define ASCII_FLAG	0x01 /* bit 0 set: file probably ASCII text */
++#define CONTINUATION	0x02 /* bit 1 set: continuation of multi-part gz file */
++#define EXTRA_FIELD	0x04 /* bit 2 set: extra field present */
++#define ORIG_NAM	0x08 /* bit 3 set: original file name present */
++#define COMMENT		0x10 /* bit 4 set: file comment present */
++#define ENCRYPTED	0x20 /* bit 5 set: file is encrypted */
++#define RESERVED	0xC0 /* bit 6, 7:  reserved */
++
++#define get_byte()	(inptr < insize ? inbuf[inptr++] : fill_inbuf())
++
+ /* Diagnostic functions */
+ #ifdef DEBUG
+-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+-#  define Trace(x) fprintf x
+-#  define Tracev(x) {if (verbose) fprintf x ;}
+-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
++#  define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0)
++#  define Trace(x)	do { fprintf x; } while (0)
++#  define Tracev(x)	do { if (verbose) fprintf x ; } while (0)
++#  define Tracevv(x)	do { if (verbose > 1) fprintf x ; } while (0)
++#  define Tracec(c, x)	do { if (verbose && (c)) fprintf x ; } while (0)
++#  define Tracecv(c, x)	do { if (verbose > 1 && (c)) fprintf x ; } while (0)
+ #else
+-#  define Assert(cond,msg)
++#  define Assert(cond, msg)
+ #  define Trace(x)
+ #  define Tracev(x)
+ #  define Tracevv(x)
+-#  define Tracec(c,x)
+-#  define Tracecv(c,x)
++#  define Tracec(c, x)
++#  define Tracecv(c, x)
+ #endif
+ 
+ static int  fill_inbuf(void);
+@@ -170,7 +183,7 @@ static void flush_window(void);
+ static void error(char *m);
+ static void gzip_mark(void **);
+ static void gzip_release(void **);
+-  
++
+ /*
+  * This is set up by the setup-routine at boot-time
+  */
+@@ -185,7 +198,7 @@ static unsigned char *real_mode; /* Pointer to real-mode data */
+ extern unsigned char input_data[];
+ extern int input_len;
+ 
+-static long bytes_out = 0;
++static long bytes_out;
+ 
+ static void *malloc(int size);
+ static void free(void *where);
+@@ -204,13 +217,7 @@ static void putstr(const char *);
+ static memptr free_mem_ptr;
+ static memptr free_mem_end_ptr;
+ 
+-#ifdef CONFIG_X86_64
+-#define HEAP_SIZE             0x7000
+-#else
+-#define HEAP_SIZE             0x4000
+-#endif
+-
+-static char *vidmem = (char *)0xb8000;
++static char *vidmem;
+ static int vidport;
+ static int lines, cols;
+ 
+@@ -224,8 +231,10 @@ static void *malloc(int size)
+ {
+ 	void *p;
+ 
+-	if (size <0) error("Malloc error");
+-	if (free_mem_ptr <= 0) error("Memory error");
++	if (size < 0)
++		error("Malloc error");
++	if (free_mem_ptr <= 0)
++		error("Memory error");
+ 
+ 	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
+ 
+@@ -251,19 +260,19 @@ static void gzip_release(void **ptr)
+ {
+ 	free_mem_ptr = (memptr) *ptr;
+ }
+- 
++
+ static void scroll(void)
+ {
+ 	int i;
+ 
+-	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+-	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
++	memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
++	for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
+ 		vidmem[i] = ' ';
+ }
+ 
+ static void putstr(const char *s)
+ {
+-	int x,y,pos;
++	int x, y, pos;
+ 	char c;
+ 
+ #ifdef CONFIG_X86_32
+@@ -274,18 +283,18 @@ static void putstr(const char *s)
+ 	x = RM_SCREEN_INFO.orig_x;
+ 	y = RM_SCREEN_INFO.orig_y;
+ 
+-	while ( ( c = *s++ ) != '\0' ) {
+-		if ( c == '\n' ) {
++	while ((c = *s++) != '\0') {
++		if (c == '\n') {
+ 			x = 0;
+-			if ( ++y >= lines ) {
++			if (++y >= lines) {
+ 				scroll();
+ 				y--;
+ 			}
+ 		} else {
+ 			vidmem [(x + cols * y) * 2] = c;
+-			if ( ++x >= cols ) {
++			if (++x >= cols) {
+ 				x = 0;
+-				if ( ++y >= lines ) {
++				if (++y >= lines) {
+ 					scroll();
+ 					y--;
+ 				}
+@@ -303,22 +312,22 @@ static void putstr(const char *s)
+ 	outb(0xff & (pos >> 1), vidport+1);
+ }
+ 
+-static void* memset(void* s, int c, unsigned n)
++static void *memset(void *s, int c, unsigned n)
+ {
+ 	int i;
+ 	char *ss = s;
+ 
+-	for (i=0;i<n;i++) ss[i] = c;
++	for (i = 0; i < n; i++) ss[i] = c;
+ 	return s;
+ }
+ 
+-static void* memcpy(void* dest, const void* src, unsigned n)
++static void *memcpy(void *dest, const void *src, unsigned n)
+ {
+ 	int i;
+ 	const char *s = src;
+ 	char *d = dest;
+ 
+-	for (i=0;i<n;i++) d[i] = s[i];
++	for (i = 0; i < n; i++) d[i] = s[i];
+ 	return dest;
+ }
+ 
+@@ -341,9 +350,9 @@ static void flush_window(void)
+ 	/* With my window equal to my output buffer
+ 	 * I only need to compute the crc here.
+ 	 */
+-	ulg c = crc;         /* temporary variable */
++	unsigned long c = crc;         /* temporary variable */
+ 	unsigned n;
+-	uch *in, ch;
++	unsigned char *in, ch;
+ 
+ 	in = window;
+ 	for (n = 0; n < outcnt; n++) {
+@@ -351,7 +360,7 @@ static void flush_window(void)
+ 		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+ 	}
+ 	crc = c;
+-	bytes_out += (ulg)outcnt;
++	bytes_out += (unsigned long)outcnt;
+ 	outcnt = 0;
+ }
+ 
+@@ -365,9 +374,59 @@ static void error(char *x)
+ 		asm("hlt");
+ }
+ 
++static void parse_elf(void *output)
++{
++#ifdef CONFIG_X86_64
++	Elf64_Ehdr ehdr;
++	Elf64_Phdr *phdrs, *phdr;
++#else
++	Elf32_Ehdr ehdr;
++	Elf32_Phdr *phdrs, *phdr;
++#endif
++	void *dest;
++	int i;
++
++	memcpy(&ehdr, output, sizeof(ehdr));
++	if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
++	   ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
++	   ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
++	   ehdr.e_ident[EI_MAG3] != ELFMAG3) {
++		error("Kernel is not a valid ELF file");
++		return;
++	}
++
++	putstr("Parsing ELF... ");
++
++	phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
++	if (!phdrs)
++		error("Failed to allocate space for phdrs");
++
++	memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum);
++
++	for (i = 0; i < ehdr.e_phnum; i++) {
++		phdr = &phdrs[i];
++
++		switch (phdr->p_type) {
++		case PT_LOAD:
++#ifdef CONFIG_RELOCATABLE
++			dest = output;
++			dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR);
++#else
++			dest = (void *)(phdr->p_paddr);
++#endif
++			memcpy(dest,
++			       output + phdr->p_offset,
++			       phdr->p_filesz);
++			break;
++		default: /* Ignore other PT_* */ break;
++		}
++	}
++}
++
+ asmlinkage void decompress_kernel(void *rmode, memptr heap,
+-				  uch *input_data, unsigned long input_len,
+-				  uch *output)
++				  unsigned char *input_data,
++				  unsigned long input_len,
++				  unsigned char *output)
+ {
+ 	real_mode = rmode;
+ 
+@@ -384,18 +443,18 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
+ 
+ 	window = output;		/* Output buffer (Normally at 1M) */
+ 	free_mem_ptr     = heap;	/* Heap */
+-	free_mem_end_ptr = heap + HEAP_SIZE;
++	free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
+ 	inbuf  = input_data;		/* Input buffer */
+ 	insize = input_len;
+ 	inptr  = 0;
+ 
+ #ifdef CONFIG_X86_64
+-	if ((ulg)output & (__KERNEL_ALIGN - 1))
++	if ((unsigned long)output & (__KERNEL_ALIGN - 1))
+ 		error("Destination address not 2M aligned");
+-	if ((ulg)output >= 0xffffffffffUL)
++	if ((unsigned long)output >= 0xffffffffffUL)
+ 		error("Destination address too large");
+ #else
+-	if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
++	if ((u32)output & (CONFIG_PHYSICAL_ALIGN - 1))
+ 		error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
+ 	if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
+ 		error("Destination address too large");
+@@ -408,6 +467,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
+ 	makecrc();
+ 	putstr("\nDecompressing Linux... ");
+ 	gunzip();
++	parse_elf(output);
+ 	putstr("done.\nBooting the kernel.\n");
+ 	return;
+ }
+diff --git a/arch/x86/boot/compressed/vmlinux_64.lds b/arch/x86/boot/compressed/vmlinux_64.lds
+index 7e5c720..bef1ac8 100644
+--- a/arch/x86/boot/compressed/vmlinux_64.lds
++++ b/arch/x86/boot/compressed/vmlinux_64.lds
+@@ -39,10 +39,10 @@ SECTIONS
+ 		*(.bss.*)
+ 		*(COMMON)
+ 		. = ALIGN(8);
+-		_end = . ;
++		_end_before_pgt = . ;
+ 		. = ALIGN(4096);
+ 		pgtable = . ;
+ 		. = . + 4096 * 6;
+-		_heap = .;
++		_ebss = .;
+ 	}
+ }
+diff --git a/arch/x86/boot/copy.S b/arch/x86/boot/copy.S
+index ef127e5..ef50c84 100644
+--- a/arch/x86/boot/copy.S
++++ b/arch/x86/boot/copy.S
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/copy.S
+- *
+  * Memory copy routines
+  */
+ 
+diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
+index 769065b..7804389 100644
+--- a/arch/x86/boot/cpucheck.c
++++ b/arch/x86/boot/cpucheck.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/cpucheck.c
+- *
+  * Check for obligatory CPU features and abort if the features are not
+  * present.  This code should be compilable as 16-, 32- or 64-bit
+  * code, so be very careful with types and inline assembly.
+@@ -56,27 +54,27 @@ static const u32 req_flags[NCAPINTS] =
+ 	REQUIRED_MASK7,
+ };
+ 
+-#define A32(a,b,c,d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
++#define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
+ 
+ static int is_amd(void)
+ {
+-	return cpu_vendor[0] == A32('A','u','t','h') &&
+-	       cpu_vendor[1] == A32('e','n','t','i') &&
+-	       cpu_vendor[2] == A32('c','A','M','D');
++	return cpu_vendor[0] == A32('A', 'u', 't', 'h') &&
++	       cpu_vendor[1] == A32('e', 'n', 't', 'i') &&
++	       cpu_vendor[2] == A32('c', 'A', 'M', 'D');
+ }
+ 
+ static int is_centaur(void)
+ {
+-	return cpu_vendor[0] == A32('C','e','n','t') &&
+-	       cpu_vendor[1] == A32('a','u','r','H') &&
+-	       cpu_vendor[2] == A32('a','u','l','s');
++	return cpu_vendor[0] == A32('C', 'e', 'n', 't') &&
++	       cpu_vendor[1] == A32('a', 'u', 'r', 'H') &&
++	       cpu_vendor[2] == A32('a', 'u', 'l', 's');
+ }
+ 
+ static int is_transmeta(void)
+ {
+-	return cpu_vendor[0] == A32('G','e','n','u') &&
+-	       cpu_vendor[1] == A32('i','n','e','T') &&
+-	       cpu_vendor[2] == A32('M','x','8','6');
++	return cpu_vendor[0] == A32('G', 'e', 'n', 'u') &&
++	       cpu_vendor[1] == A32('i', 'n', 'e', 'T') &&
++	       cpu_vendor[2] == A32('M', 'x', '8', '6');
+ }
+ 
+ static int has_fpu(void)
+diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c
+index 8721dc4..d84a48e 100644
+--- a/arch/x86/boot/edd.c
++++ b/arch/x86/boot/edd.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/edd.c
+- *
+  * Get EDD BIOS disk information
+  */
+ 
+diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
+index 64ad901..6d2df8d 100644
+--- a/arch/x86/boot/header.S
++++ b/arch/x86/boot/header.S
+@@ -22,6 +22,7 @@
+ #include <asm/page.h>
+ #include <asm/setup.h>
+ #include "boot.h"
++#include "offsets.h"
+ 
+ SETUPSECTS	= 4			/* default nr of setup-sectors */
+ BOOTSEG		= 0x07C0		/* original address of boot-sector */
+@@ -119,7 +120,7 @@ _start:
+ 	# Part 2 of the header, from the old setup.S
+ 
+ 		.ascii	"HdrS"		# header signature
+-		.word	0x0207		# header version number (>= 0x0105)
++		.word	0x0208		# header version number (>= 0x0105)
+ 					# or else old loadlin-1.5 will fail)
+ 		.globl realmode_swtch
+ realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
+@@ -223,6 +224,9 @@ hardware_subarch:	.long 0			# subarchitecture, added with 2.07
+ 
+ hardware_subarch_data:	.quad 0
+ 
++payload_offset:		.long input_data
++payload_length:		.long input_data_end-input_data
++
+ # End of setup header #####################################################
+ 
+ 	.section ".inittext", "ax"
+diff --git a/arch/x86/boot/install.sh b/arch/x86/boot/install.sh
+index 88d7776..8d60ee1 100644
+--- a/arch/x86/boot/install.sh
++++ b/arch/x86/boot/install.sh
+@@ -1,7 +1,5 @@
+ #!/bin/sh
+ #
+-# arch/i386/boot/install.sh
+-#
+ # 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.
+diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
+index 7828da5..77569a4 100644
+--- a/arch/x86/boot/main.c
++++ b/arch/x86/boot/main.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/main.c
+- *
+  * Main module for the real-mode kernel code
+  */
+ 
+diff --git a/arch/x86/boot/mca.c b/arch/x86/boot/mca.c
+index 68222f2..911eaae 100644
+--- a/arch/x86/boot/mca.c
++++ b/arch/x86/boot/mca.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/mca.c
+- *
+  * Get the MCA system description table
+  */
+ 
+diff --git a/arch/x86/boot/memory.c b/arch/x86/boot/memory.c
+index e77d89f..acad32e 100644
+--- a/arch/x86/boot/memory.c
++++ b/arch/x86/boot/memory.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/memory.c
+- *
+  * Memory detection code
+  */
+ 
+diff --git a/arch/x86/boot/pm.c b/arch/x86/boot/pm.c
+index 1a0f936..328956f 100644
+--- a/arch/x86/boot/pm.c
++++ b/arch/x86/boot/pm.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/pm.c
+- *
+  * Prepare the machine for transition to protected mode.
+  */
+ 
+@@ -100,7 +98,7 @@ static void reset_coprocessor(void)
+ /*
+  * Set up the GDT
+  */
+-#define GDT_ENTRY(flags,base,limit)		\
++#define GDT_ENTRY(flags, base, limit)		\
+ 	(((u64)(base & 0xff000000) << 32) |	\
+ 	 ((u64)flags << 40) |			\
+ 	 ((u64)(limit & 0x00ff0000) << 32) |	\
+diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
+index f5402d5..ab049d4 100644
+--- a/arch/x86/boot/pmjump.S
++++ b/arch/x86/boot/pmjump.S
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/pmjump.S
+- *
+  * The actual transition into protected mode
+  */
+ 
+diff --git a/arch/x86/boot/printf.c b/arch/x86/boot/printf.c
+index 7e7e890..c1d00c0 100644
+--- a/arch/x86/boot/printf.c
++++ b/arch/x86/boot/printf.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/printf.c
+- *
+  * Oh, it's a waste of space, but oh-so-yummy for debugging.  This
+  * version of printf() does not include 64-bit support.  "Live with
+  * it."
+diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c
+index 481a220..f94b7a0 100644
+--- a/arch/x86/boot/string.c
++++ b/arch/x86/boot/string.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/string.c
+- *
+  * Very basic string functions
+  */
+ 
+diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
+index b424874..44dc192 100644
+--- a/arch/x86/boot/tools/build.c
++++ b/arch/x86/boot/tools/build.c
+@@ -50,6 +50,75 @@ typedef unsigned long  u32;
+ u8 buf[SETUP_SECT_MAX*512];
+ int is_big_kernel;
+ 
++/*----------------------------------------------------------------------*/
++
++static const u32 crctab32[] = {
++	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
++	0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
++	0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
++	0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
++	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
++	0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
++	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
++	0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
++	0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
++	0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
++	0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
++	0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
++	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
++	0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
++	0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
++	0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
++	0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
++	0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
++	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
++	0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
++	0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
++	0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
++	0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
++	0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
++	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
++	0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
++	0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
++	0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
++	0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
++	0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
++	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
++	0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
++	0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
++	0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
++	0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
++	0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
++	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
++	0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
++	0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
++	0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
++	0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
++	0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
++	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
++	0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
++	0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
++	0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
++	0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
++	0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
++	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
++	0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
++	0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
++	0x2d02ef8d
++};
++
++static u32 partial_crc32_one(u8 c, u32 crc)
++{
++	return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
++}
++
++static u32 partial_crc32(const u8 *s, int len, u32 crc)
++{
++	while (len--)
++		crc = partial_crc32_one(*s++, crc);
++	return crc;
++}
++
+ static void die(const char * str, ...)
+ {
+ 	va_list args;
+@@ -74,6 +143,7 @@ int main(int argc, char ** argv)
+ 	FILE *file;
+ 	int fd;
+ 	void *kernel;
++	u32 crc = 0xffffffffUL;
+ 
+ 	if (argc > 2 && !strcmp(argv[1], "-b"))
+ 	  {
+@@ -144,7 +214,8 @@ int main(int argc, char ** argv)
+ 	kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
+ 	if (kernel == MAP_FAILED)
+ 		die("Unable to mmap '%s': %m", argv[2]);
+-	sys_size = (sz + 15) / 16;
++	/* Number of 16-byte paragraphs, including space for a 4-byte CRC */
++	sys_size = (sz + 15 + 4) / 16;
+ 	if (!is_big_kernel && sys_size > DEF_SYSSIZE)
+ 		die("System is too big. Try using bzImage or modules.");
+ 
+@@ -155,12 +226,27 @@ int main(int argc, char ** argv)
+ 	buf[0x1f6] = sys_size >> 16;
+ 	buf[0x1f7] = sys_size >> 24;
+ 
++	crc = partial_crc32(buf, i, crc);
+ 	if (fwrite(buf, 1, i, stdout) != i)
+ 		die("Writing setup failed");
+ 
+ 	/* Copy the kernel code */
++	crc = partial_crc32(kernel, sz, crc);
+ 	if (fwrite(kernel, 1, sz, stdout) != sz)
+ 		die("Writing kernel failed");
++
++	/* Add padding leaving 4 bytes for the checksum */
++	while (sz++ < (sys_size*16) - 4) {
++		crc = partial_crc32_one('\0', crc);
++		if (fwrite("\0", 1, 1, stdout) != 1)
++			die("Writing padding failed");
++	}
++
++	/* Write the CRC */
++	fprintf(stderr, "CRC %lx\n", crc);
++	if (fwrite(&crc, 1, 4, stdout) != 4)
++		die("Writing CRC failed");
++
+ 	close(fd);
+ 
+ 	/* Everything is OK */
+diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c
+index f3f14bd..0be77b3 100644
+--- a/arch/x86/boot/tty.c
++++ b/arch/x86/boot/tty.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/tty.c
+- *
+  * Very simple screen I/O
+  * XXX: Probably should add very simple serial I/O?
+  */
+diff --git a/arch/x86/boot/version.c b/arch/x86/boot/version.c
+index c61462f..2723d9b 100644
+--- a/arch/x86/boot/version.c
++++ b/arch/x86/boot/version.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/version.c
+- *
+  * Kernel version string
+  */
+ 
+diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c
+index ff664a1..49f26aa 100644
+--- a/arch/x86/boot/video-bios.c
++++ b/arch/x86/boot/video-bios.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/video-bios.c
+- *
+  * Standard video BIOS modes
+  *
+  * We have two options for this; silent and scanned.
+@@ -50,6 +48,7 @@ static int set_bios_mode(u8 mode)
+ 	if (new_mode == mode)
+ 		return 0;	/* Mode change OK */
+ 
++#ifndef _WAKEUP
+ 	if (new_mode != boot_params.screen_info.orig_video_mode) {
+ 		/* Mode setting failed, but we didn't end up where we
+ 		   started.  That's bad.  Try to revert to the original
+@@ -59,13 +58,18 @@ static int set_bios_mode(u8 mode)
+ 			     : "+a" (ax)
+ 			     : : "ebx", "ecx", "edx", "esi", "edi");
+ 	}
++#endif
+ 	return -1;
+ }
+ 
+ static int bios_probe(void)
+ {
+ 	u8 mode;
++#ifdef _WAKEUP
++	u8 saved_mode = 0x03;
++#else
+ 	u8 saved_mode = boot_params.screen_info.orig_video_mode;
++#endif
+ 	u16 crtc;
+ 	struct mode_info *mi;
+ 	int nmodes = 0;
+diff --git a/arch/x86/boot/video-mode.c b/arch/x86/boot/video-mode.c
+new file mode 100644
+index 0000000..748e8d0
+--- /dev/null
++++ b/arch/x86/boot/video-mode.c
+@@ -0,0 +1,173 @@
++/* -*- linux-c -*- ------------------------------------------------------- *
++ *
++ *   Copyright (C) 1991, 1992 Linus Torvalds
++ *   Copyright 2007-2008 rPath, Inc. - All Rights Reserved
++ *
++ *   This file is part of the Linux kernel, and is made available under
++ *   the terms of the GNU General Public License version 2.
++ *
++ * ----------------------------------------------------------------------- */
++
++/*
++ * arch/i386/boot/video-mode.c
++ *
++ * Set the video mode.  This is separated out into a different
++ * file in order to be shared with the ACPI wakeup code.
++ */
++
++#include "boot.h"
++#include "video.h"
++#include "vesa.h"
++
++/*
++ * Common variables
++ */
++int adapter;			/* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
++u16 video_segment;
++int force_x, force_y;	/* Don't query the BIOS for cols/rows */
++
++int do_restore;		/* Screen contents changed during mode flip */
++int graphic_mode;	/* Graphic mode with linear frame buffer */
++
++/* Probe the video drivers and have them generate their mode lists. */
++void probe_cards(int unsafe)
++{
++	struct card_info *card;
++	static u8 probed[2];
++
++	if (probed[unsafe])
++		return;
++
++	probed[unsafe] = 1;
++
++	for (card = video_cards; card < video_cards_end; card++) {
++		if (card->unsafe == unsafe) {
++			if (card->probe)
++				card->nmodes = card->probe();
++			else
++				card->nmodes = 0;
++		}
++	}
++}
++
++/* Test if a mode is defined */
++int mode_defined(u16 mode)
++{
++	struct card_info *card;
++	struct mode_info *mi;
++	int i;
++
++	for (card = video_cards; card < video_cards_end; card++) {
++		mi = card->modes;
++		for (i = 0; i < card->nmodes; i++, mi++) {
++			if (mi->mode == mode)
++				return 1;
++		}
++	}
++
++	return 0;
++}
++
++/* Set mode (without recalc) */
++static int raw_set_mode(u16 mode, u16 *real_mode)
++{
++	int nmode, i;
++	struct card_info *card;
++	struct mode_info *mi;
++
++	/* Drop the recalc bit if set */
++	mode &= ~VIDEO_RECALC;
++
++	/* Scan for mode based on fixed ID, position, or resolution */
++	nmode = 0;
++	for (card = video_cards; card < video_cards_end; card++) {
++		mi = card->modes;
++		for (i = 0; i < card->nmodes; i++, mi++) {
++			int visible = mi->x || mi->y;
++
++			if ((mode == nmode && visible) ||
++			    mode == mi->mode ||
++			    mode == (mi->y << 8)+mi->x) {
++				*real_mode = mi->mode;
++				return card->set_mode(mi);
++			}
++
++			if (visible)
++				nmode++;
++		}
++	}
++
++	/* Nothing found?  Is it an "exceptional" (unprobed) mode? */
++	for (card = video_cards; card < video_cards_end; card++) {
++		if (mode >= card->xmode_first &&
++		    mode < card->xmode_first+card->xmode_n) {
++			struct mode_info mix;
++			*real_mode = mix.mode = mode;
++			mix.x = mix.y = 0;
++			return card->set_mode(&mix);
++		}
++	}
++
++	/* Otherwise, failure... */
++	return -1;
++}
++
++/*
++ * Recalculate the vertical video cutoff (hack!)
++ */
++static void vga_recalc_vertical(void)
++{
++	unsigned int font_size, rows;
++	u16 crtc;
++	u8 pt, ov;
++
++	set_fs(0);
++	font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
++	rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
++
++	rows *= font_size;	/* Visible scan lines */
++	rows--;			/* ... minus one */
++
++	crtc = vga_crtc();
++
++	pt = in_idx(crtc, 0x11);
++	pt &= ~0x80;		/* Unlock CR0-7 */
++	out_idx(pt, crtc, 0x11);
++
++	out_idx((u8)rows, crtc, 0x12); /* Lower height register */
++
++	ov = in_idx(crtc, 0x07); /* Overflow register */
++	ov &= 0xbd;
++	ov |= (rows >> (8-1)) & 0x02;
++	ov |= (rows >> (9-6)) & 0x40;
++	out_idx(ov, crtc, 0x07);
++}
++
++/* Set mode (with recalc if specified) */
++int set_mode(u16 mode)
++{
++	int rv;
++	u16 real_mode;
++
++	/* Very special mode numbers... */
++	if (mode == VIDEO_CURRENT_MODE)
++		return 0;	/* Nothing to do... */
++	else if (mode == NORMAL_VGA)
++		mode = VIDEO_80x25;
++	else if (mode == EXTENDED_VGA)
++		mode = VIDEO_8POINT;
++
++	rv = raw_set_mode(mode, &real_mode);
++	if (rv)
++		return rv;
++
++	if (mode & VIDEO_RECALC)
++		vga_recalc_vertical();
++
++	/* Save the canonical mode number for the kernel, not
++	   an alias, size specification or menu position */
++#ifndef _WAKEUP
++	boot_params.hdr.vid_mode = real_mode;
++#endif
++	return 0;
++}
+diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
+index 419b5c2..401ad99 100644
+--- a/arch/x86/boot/video-vesa.c
++++ b/arch/x86/boot/video-vesa.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/video-vesa.c
+- *
+  * VESA text modes
+  */
+ 
+@@ -24,7 +22,11 @@ static struct vesa_mode_info vminfo;
+ 
+ __videocard video_vesa;
+ 
++#ifndef _WAKEUP
+ static void vesa_store_mode_params_graphics(void);
++#else /* _WAKEUP */
++static inline void vesa_store_mode_params_graphics(void) {}
++#endif /* _WAKEUP */
+ 
+ static int vesa_probe(void)
+ {
+@@ -165,6 +167,8 @@ static int vesa_set_mode(struct mode_info *mode)
+ }
+ 
+ 
++#ifndef _WAKEUP
++
+ /* Switch DAC to 8-bit mode */
+ static void vesa_dac_set_8bits(void)
+ {
+@@ -288,6 +292,8 @@ void vesa_store_edid(void)
+ #endif /* CONFIG_FIRMWARE_EDID */
+ }
+ 
++#endif /* not _WAKEUP */
++
+ __videocard video_vesa =
+ {
+ 	.card_name	= "VESA",
+diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
+index 7259387..40ecb8d 100644
+--- a/arch/x86/boot/video-vga.c
++++ b/arch/x86/boot/video-vga.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/video-vga.c
+- *
+  * Common all-VGA modes
+  */
+ 
+@@ -210,6 +208,8 @@ static int vga_set_mode(struct mode_info *mode)
+  */
+ static int vga_probe(void)
+ {
++	u16 ega_bx;
++
+ 	static const char *card_name[] = {
+ 		"CGA/MDA/HGC", "EGA", "VGA"
+ 	};
+@@ -226,12 +226,16 @@ static int vga_probe(void)
+ 	u8 vga_flag;
+ 
+ 	asm(INT10
+-	    : "=b" (boot_params.screen_info.orig_video_ega_bx)
++	    : "=b" (ega_bx)
+ 	    : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
+ 	    : "ecx", "edx", "esi", "edi");
+ 
++#ifndef _WAKEUP
++	boot_params.screen_info.orig_video_ega_bx = ega_bx;
++#endif
++
+ 	/* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
+-	if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) {
++	if ((u8)ega_bx != 0x10) {
+ 		/* EGA/VGA */
+ 		asm(INT10
+ 		    : "=a" (vga_flag)
+@@ -240,7 +244,9 @@ static int vga_probe(void)
+ 
+ 		if (vga_flag == 0x1a) {
+ 			adapter = ADAPTER_VGA;
++#ifndef _WAKEUP
+ 			boot_params.screen_info.orig_video_isVGA = 1;
++#endif
+ 		} else {
+ 			adapter = ADAPTER_EGA;
+ 		}
+diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c
+index 696d08f..83598b2 100644
+--- a/arch/x86/boot/video.c
++++ b/arch/x86/boot/video.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/video.c
+- *
+  * Select video mode
+  */
+ 
+@@ -18,21 +16,6 @@
+ #include "video.h"
+ #include "vesa.h"
+ 
+-/*
+- * Mode list variables
+- */
+-static struct card_info cards[];    /* List of cards to probe for */
+-
+-/*
+- * Common variables
+- */
+-int adapter;			/* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
+-u16 video_segment;
+-int force_x, force_y;	/* Don't query the BIOS for cols/rows */
+-
+-int do_restore = 0;	/* Screen contents changed during mode flip */
+-int graphic_mode;	/* Graphic mode with linear frame buffer */
+-
+ static void store_cursor_position(void)
+ {
+ 	u16 curpos;
+@@ -107,147 +90,6 @@ static void store_mode_params(void)
+ 	boot_params.screen_info.orig_video_lines = y;
+ }
+ 
+-/* Probe the video drivers and have them generate their mode lists. */
+-static void probe_cards(int unsafe)
+-{
+-	struct card_info *card;
+-	static u8 probed[2];
+-
+-	if (probed[unsafe])
+-		return;
+-
+-	probed[unsafe] = 1;
+-
+-	for (card = video_cards; card < video_cards_end; card++) {
+-		if (card->unsafe == unsafe) {
+-			if (card->probe)
+-				card->nmodes = card->probe();
+-			else
+-				card->nmodes = 0;
+-		}
+-	}
+-}
+-
+-/* Test if a mode is defined */
+-int mode_defined(u16 mode)
+-{
+-	struct card_info *card;
+-	struct mode_info *mi;
+-	int i;
+-
+-	for (card = video_cards; card < video_cards_end; card++) {
+-		mi = card->modes;
+-		for (i = 0; i < card->nmodes; i++, mi++) {
+-			if (mi->mode == mode)
+-				return 1;
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-/* Set mode (without recalc) */
+-static int raw_set_mode(u16 mode, u16 *real_mode)
+-{
+-	int nmode, i;
+-	struct card_info *card;
+-	struct mode_info *mi;
+-
+-	/* Drop the recalc bit if set */
+-	mode &= ~VIDEO_RECALC;
+-
+-	/* Scan for mode based on fixed ID, position, or resolution */
+-	nmode = 0;
+-	for (card = video_cards; card < video_cards_end; card++) {
+-		mi = card->modes;
+-		for (i = 0; i < card->nmodes; i++, mi++) {
+-			int visible = mi->x || mi->y;
+-
+-			if ((mode == nmode && visible) ||
+-			    mode == mi->mode ||
+-			    mode == (mi->y << 8)+mi->x) {
+-				*real_mode = mi->mode;
+-				return card->set_mode(mi);
+-			}
+-
+-			if (visible)
+-				nmode++;
+-		}
+-	}
+-
+-	/* Nothing found?  Is it an "exceptional" (unprobed) mode? */
+-	for (card = video_cards; card < video_cards_end; card++) {
+-		if (mode >= card->xmode_first &&
+-		    mode < card->xmode_first+card->xmode_n) {
+-			struct mode_info mix;
+-			*real_mode = mix.mode = mode;
+-			mix.x = mix.y = 0;
+-			return card->set_mode(&mix);
+-		}
+-	}
+-
+-	/* Otherwise, failure... */
+-	return -1;
+-}
+-
+-/*
+- * Recalculate the vertical video cutoff (hack!)
+- */
+-static void vga_recalc_vertical(void)
+-{
+-	unsigned int font_size, rows;
+-	u16 crtc;
+-	u8 pt, ov;
+-
+-	set_fs(0);
+-	font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
+-	rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
+-
+-	rows *= font_size;	/* Visible scan lines */
+-	rows--;			/* ... minus one */
+-
+-	crtc = vga_crtc();
+-
+-	pt = in_idx(crtc, 0x11);
+-	pt &= ~0x80;		/* Unlock CR0-7 */
+-	out_idx(pt, crtc, 0x11);
+-
+-	out_idx((u8)rows, crtc, 0x12); /* Lower height register */
+-
+-	ov = in_idx(crtc, 0x07); /* Overflow register */
+-	ov &= 0xbd;
+-	ov |= (rows >> (8-1)) & 0x02;
+-	ov |= (rows >> (9-6)) & 0x40;
+-	out_idx(ov, crtc, 0x07);
+-}
+-
+-/* Set mode (with recalc if specified) */
+-static int set_mode(u16 mode)
+-{
+-	int rv;
+-	u16 real_mode;
+-
+-	/* Very special mode numbers... */
+-	if (mode == VIDEO_CURRENT_MODE)
+-		return 0;	/* Nothing to do... */
+-	else if (mode == NORMAL_VGA)
+-		mode = VIDEO_80x25;
+-	else if (mode == EXTENDED_VGA)
+-		mode = VIDEO_8POINT;
+-
+-	rv = raw_set_mode(mode, &real_mode);
+-	if (rv)
+-		return rv;
+-
+-	if (mode & VIDEO_RECALC)
+-		vga_recalc_vertical();
+-
+-	/* Save the canonical mode number for the kernel, not
+-	   an alias, size specification or menu position */
+-	boot_params.hdr.vid_mode = real_mode;
+-	return 0;
+-}
+-
+ static unsigned int get_entry(void)
+ {
+ 	char entry_buf[4];
+@@ -486,6 +328,7 @@ void set_video(void)
+ 		printf("Undefined video mode number: %x\n", mode);
+ 		mode = ASK_VGA;
+ 	}
++	boot_params.hdr.vid_mode = mode;
+ 	vesa_store_edid();
+ 	store_mode_params();
+ 
+diff --git a/arch/x86/boot/video.h b/arch/x86/boot/video.h
+index d69347f..ee63f5d 100644
+--- a/arch/x86/boot/video.h
++++ b/arch/x86/boot/video.h
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/video.h
+- *
+  * Header file for the real-mode video probing code
+  */
+ 
+diff --git a/arch/x86/boot/voyager.c b/arch/x86/boot/voyager.c
+index 6499e32..433909d 100644
+--- a/arch/x86/boot/voyager.c
++++ b/arch/x86/boot/voyager.c
+@@ -9,8 +9,6 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/voyager.c
+- *
+  * Get the Voyager config information
+  */
+ 
+diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
+index 3df340b..ad7ddaa 100644
+--- a/arch/x86/configs/i386_defconfig
++++ b/arch/x86/configs/i386_defconfig
+@@ -1421,6 +1421,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
+ # CONFIG_FRAME_POINTER is not set
++CONFIG_OPTIMIZE_INLINING=y
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_LKDTM is not set
+ # CONFIG_FAULT_INJECTION is not set
+diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
+index eef98cb..2d6f5b2 100644
+--- a/arch/x86/configs/x86_64_defconfig
++++ b/arch/x86/configs/x86_64_defconfig
+@@ -1346,6 +1346,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
+ # CONFIG_FRAME_POINTER is not set
++CONFIG_OPTIMIZE_INLINING=y
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_LKDTM is not set
+ # CONFIG_FAULT_INJECTION is not set
+diff --git a/arch/x86/crypto/aes-i586-asm_32.S b/arch/x86/crypto/aes-i586-asm_32.S
+index 1093bed..e41b147 100644
+--- a/arch/x86/crypto/aes-i586-asm_32.S
++++ b/arch/x86/crypto/aes-i586-asm_32.S
+@@ -289,7 +289,6 @@ aes_enc_blk:
+ 	pop     %ebx
+ 	mov     %r0,(%ebp)
+ 	pop     %ebp
+-	mov     $1,%eax
+ 	ret
+ 
+ // AES (Rijndael) Decryption Subroutine
+@@ -365,6 +364,4 @@ aes_dec_blk:
+ 	pop     %ebx
+ 	mov     %r0,(%ebp)
+ 	pop     %ebp
+-	mov     $1,%eax
+ 	ret
+-
+diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
+index 5e7771a..bbed3a2 100644
+--- a/arch/x86/ia32/ia32_signal.c
++++ b/arch/x86/ia32/ia32_signal.c
+@@ -468,7 +468,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
+ 		restorer = ka->sa.sa_restorer;
+ 	} else {
+ 		/* Return stub is in 32bit vsyscall page */
+-		if (current->binfmt->hasvdso)
++		if (current->mm->context.vdso)
+ 			restorer = VDSO32_SYMBOL(current->mm->context.vdso,
+ 						 sigreturn);
+ 		else
+@@ -499,11 +499,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
+ 	regs->cs = __USER32_CS;
+ 	regs->ss = __USER32_DS;
+ 
+-	set_fs(USER_DS);
+-	regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
+-	if (test_thread_flag(TIF_SINGLESTEP))
+-		ptrace_notify(SIGTRAP);
+-
+ #if DEBUG_SIG
+ 	printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
+ 	       current->comm, current->pid, frame, regs->ip, frame->pretcode);
+@@ -599,11 +594,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 	regs->cs = __USER32_CS;
+ 	regs->ss = __USER32_DS;
+ 
+-	set_fs(USER_DS);
+-	regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
+-	if (test_thread_flag(TIF_SINGLESTEP))
+-		ptrace_notify(SIGTRAP);
+-
+ #if DEBUG_SIG
+ 	printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
+ 	       current->comm, current->pid, frame, regs->ip, frame->pretcode);
+diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
+index 8022d3c..b5e329d 100644
+--- a/arch/x86/ia32/ia32entry.S
++++ b/arch/x86/ia32/ia32entry.S
+@@ -162,12 +162,14 @@ sysenter_tracesys:
+ 	SAVE_REST
+ 	CLEAR_RREGS
+ 	movq	%r9,R9(%rsp)
+-	movq	$-ENOSYS,RAX(%rsp)	/* really needed? */
++	movq	$-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
+ 	movq	%rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call	syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+ 	xchgl	%ebp,%r9d
++	cmpl	$(IA32_NR_syscalls-1),%eax
++	ja	int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
+ 	jmp	sysenter_do_call
+ 	CFI_ENDPROC
+ ENDPROC(ia32_sysenter_target)
+@@ -261,13 +263,15 @@ cstar_tracesys:
+ 	SAVE_REST
+ 	CLEAR_RREGS
+ 	movq %r9,R9(%rsp)
+-	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
++	movq $-ENOSYS,RAX(%rsp)	/* ptrace can change this for a bad syscall */
+ 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+ 	xchgl %ebp,%r9d
+ 	movl RSP-ARGOFFSET(%rsp), %r8d
++	cmpl $(IA32_NR_syscalls-1),%eax
++	ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
+ 	jmp cstar_do_call
+ END(ia32_cstar_target)
+ 				
+@@ -325,7 +329,7 @@ ENTRY(ia32_syscall)
+ 	jnz ia32_tracesys
+ ia32_do_syscall:	
+ 	cmpl $(IA32_NR_syscalls-1),%eax
+-	ja  ia32_badsys
++	ja  int_ret_from_sys_call	/* ia32_tracesys has set RAX(%rsp) */
+ 	IA32_ARG_FIXUP
+ 	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
+ ia32_sysret:
+@@ -335,7 +339,7 @@ ia32_sysret:
+ ia32_tracesys:			 
+ 	SAVE_REST
+ 	CLEAR_RREGS
+-	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
++	movq $-ENOSYS,RAX(%rsp)	/* ptrace can change this for a bad syscall */
+ 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+@@ -426,7 +430,7 @@ ia32_sys_call_table:
+ 	.quad sys_setuid16
+ 	.quad sys_getuid16
+ 	.quad compat_sys_stime	/* stime */		/* 25 */
+-	.quad sys32_ptrace	/* ptrace */
++	.quad compat_sys_ptrace	/* ptrace */
+ 	.quad sys_alarm
+ 	.quad sys_fstat	/* (old)fstat */
+ 	.quad sys_pause
+diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
+index abf71d2..f00afdf 100644
+--- a/arch/x86/ia32/sys_ia32.c
++++ b/arch/x86/ia32/sys_ia32.c
+@@ -26,51 +26,26 @@
+ #include <linux/file.h>
+ #include <linux/signal.h>
+ #include <linux/syscalls.h>
+-#include <linux/resource.h>
+ #include <linux/times.h>
+ #include <linux/utsname.h>
+-#include <linux/smp.h>
+ #include <linux/smp_lock.h>
+-#include <linux/sem.h>
+-#include <linux/msg.h>
+ #include <linux/mm.h>
+-#include <linux/shm.h>
+-#include <linux/slab.h>
+ #include <linux/uio.h>
+-#include <linux/nfs_fs.h>
+-#include <linux/quota.h>
+-#include <linux/module.h>
+-#include <linux/sunrpc/svc.h>
+-#include <linux/nfsd/nfsd.h>
+-#include <linux/nfsd/cache.h>
+-#include <linux/nfsd/xdr.h>
+-#include <linux/nfsd/syscall.h>
+ #include <linux/poll.h>
+ #include <linux/personality.h>
+ #include <linux/stat.h>
+-#include <linux/ipc.h>
+ #include <linux/rwsem.h>
+-#include <linux/binfmts.h>
+-#include <linux/init.h>
+-#include <linux/aio_abi.h>
+-#include <linux/aio.h>
+ #include <linux/compat.h>
+ #include <linux/vfs.h>
+ #include <linux/ptrace.h>
+ #include <linux/highuid.h>
+-#include <linux/vmalloc.h>
+-#include <linux/fsnotify.h>
+ #include <linux/sysctl.h>
+ #include <asm/mman.h>
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/atomic.h>
+-#include <asm/ldt.h>
+-
+-#include <net/scm.h>
+-#include <net/sock.h>
+ #include <asm/ia32.h>
++#include <asm/vgtod.h>
+ 
+ #define AA(__x)		((unsigned long)(__x))
+ 
+@@ -804,11 +779,6 @@ asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
+ 	if (IS_ERR(filename))
+ 		return error;
+ 	error = compat_do_execve(filename, argv, envp, regs);
+-	if (error == 0) {
+-		task_lock(current);
+-		current->ptrace &= ~PT_DTRACE;
+-		task_unlock(current);
+-	}
+ 	putname(filename);
+ 	return error;
+ }
+diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
+index 4eb5ce8..90e092d 100644
+--- a/arch/x86/kernel/Makefile
++++ b/arch/x86/kernel/Makefile
+@@ -2,8 +2,7 @@
+ # Makefile for the linux kernel.
+ #
+ 
+-extra-y                := head_$(BITS).o init_task.o vmlinux.lds
+-extra-$(CONFIG_X86_64) += head64.o
++extra-y                := head_$(BITS).o head$(BITS).o init_task.o vmlinux.lds
+ 
+ CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
+ 
+@@ -19,16 +18,18 @@ CFLAGS_tsc_64.o		:= $(nostackp)
+ obj-y			:= process_$(BITS).o signal_$(BITS).o entry_$(BITS).o
+ obj-y			+= traps_$(BITS).o irq_$(BITS).o
+ obj-y			+= time_$(BITS).o ioport.o ldt.o
+-obj-y			+= setup_$(BITS).o i8259_$(BITS).o
++obj-y			+= setup_$(BITS).o i8259_$(BITS).o setup.o
+ obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
+ obj-$(CONFIG_X86_64)	+= sys_x86_64.o x8664_ksyms_64.o
+ obj-$(CONFIG_X86_64)	+= syscall_64.o vsyscall_64.o setup64.o
+-obj-y			+= pci-dma_$(BITS).o  bootflag.o e820_$(BITS).o
+-obj-y			+= quirks.o i8237.o topology.o kdebugfs.o
+-obj-y			+= alternative.o i8253.o
+-obj-$(CONFIG_X86_64)	+= pci-nommu_64.o bugs_64.o
++obj-y			+= bootflag.o e820_$(BITS).o
++obj-y			+= pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
++obj-y			+= alternative.o i8253.o pci-nommu.o
++obj-$(CONFIG_X86_64)	+= bugs_64.o
+ obj-y			+= tsc_$(BITS).o io_delay.o rtc.o
+ 
++obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
++obj-y				+= process.o
+ obj-y				+= i387.o
+ obj-y				+= ptrace.o
+ obj-y				+= ds.o
+@@ -47,11 +48,12 @@ obj-$(CONFIG_MICROCODE)		+= microcode.o
+ obj-$(CONFIG_PCI)		+= early-quirks.o
+ apm-y				:= apm_32.o
+ obj-$(CONFIG_APM)		+= apm.o
+-obj-$(CONFIG_X86_SMP)		+= smp_$(BITS).o smpboot_$(BITS).o tsc_sync.o
+-obj-$(CONFIG_X86_32_SMP)	+= smpcommon_32.o
+-obj-$(CONFIG_X86_64_SMP)	+= smp_64.o smpboot_64.o tsc_sync.o
++obj-$(CONFIG_X86_SMP)		+= smp.o
++obj-$(CONFIG_X86_SMP)		+= smpboot.o tsc_sync.o ipi.o tlb_$(BITS).o
++obj-$(CONFIG_X86_32_SMP)	+= smpcommon.o
++obj-$(CONFIG_X86_64_SMP)	+= tsc_sync.o smpcommon.o
+ obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline_$(BITS).o
+-obj-$(CONFIG_X86_MPPARSE)	+= mpparse_$(BITS).o
++obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
+ obj-$(CONFIG_X86_LOCAL_APIC)	+= apic_$(BITS).o nmi_$(BITS).o
+ obj-$(CONFIG_X86_IO_APIC)	+= io_apic_$(BITS).o
+ obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups_32.o
+@@ -60,12 +62,13 @@ obj-$(CONFIG_KEXEC)		+= relocate_kernel_$(BITS).o crash.o
+ obj-$(CONFIG_CRASH_DUMP)	+= crash_dump_$(BITS).o
+ obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
+ obj-$(CONFIG_X86_SUMMIT_NUMA)	+= summit_32.o
+-obj-$(CONFIG_X86_VSMP)		+= vsmp_64.o
++obj-y				+= vsmp_64.o
+ obj-$(CONFIG_KPROBES)		+= kprobes.o
+ obj-$(CONFIG_MODULES)		+= module_$(BITS).o
+ obj-$(CONFIG_ACPI_SRAT) 	+= srat_32.o
+ obj-$(CONFIG_EFI) 		+= efi.o efi_$(BITS).o efi_stub_$(BITS).o
+ obj-$(CONFIG_DOUBLEFAULT) 	+= doublefault_32.o
++obj-$(CONFIG_KGDB)		+= kgdb.o
+ obj-$(CONFIG_VM86)		+= vm86_32.o
+ obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+ 
+@@ -89,7 +92,7 @@ scx200-y			+= scx200_32.o
+ ###
+ # 64 bit specific files
+ ifeq ($(CONFIG_X86_64),y)
+-        obj-y				+= genapic_64.o genapic_flat_64.o
++        obj-y				+= genapic_64.o genapic_flat_64.o genx2apic_uv_x.o
+         obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer_64.o
+         obj-$(CONFIG_AUDIT)		+= audit_64.o
+ 
+diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile
+index 19d3d6e..7335959 100644
+--- a/arch/x86/kernel/acpi/Makefile
++++ b/arch/x86/kernel/acpi/Makefile
+@@ -1,7 +1,14 @@
++subdir-				:= realmode
++
+ obj-$(CONFIG_ACPI)		+= boot.o
+-obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup_$(BITS).o
++obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup_rm.o wakeup_$(BITS).o
+ 
+ ifneq ($(CONFIG_ACPI_PROCESSOR),)
+ obj-y				+= cstate.o processor.o
+ endif
+ 
++$(obj)/wakeup_rm.o:    $(obj)/realmode/wakeup.bin
++
++$(obj)/realmode/wakeup.bin: FORCE
++	$(Q)$(MAKE) $(build)=$(obj)/realmode $@
++
+diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
+index 2cdc9de..977ed5c 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -39,6 +39,11 @@
+ #include <asm/apic.h>
+ #include <asm/io.h>
+ #include <asm/mpspec.h>
++#include <asm/smp.h>
++
++#ifdef CONFIG_X86_LOCAL_APIC
++# include <mach_apic.h>
++#endif
+ 
+ static int __initdata acpi_force = 0;
+ 
+@@ -52,9 +57,7 @@ EXPORT_SYMBOL(acpi_disabled);
+ #ifdef	CONFIG_X86_64
+ 
+ #include <asm/proto.h>
+-
+-static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; }
+-
++#include <asm/genapic.h>
+ 
+ #else				/* X86 */
+ 
+@@ -111,7 +114,7 @@ char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
+ 	if (!phys_addr || !size)
+ 		return NULL;
+ 
+-	if (phys_addr+size <= (end_pfn_map << PAGE_SHIFT) + PAGE_SIZE)
++	if (phys_addr+size <= (max_pfn_mapped << PAGE_SHIFT) + PAGE_SIZE)
+ 		return __va(phys_addr);
+ 
+ 	return NULL;
+@@ -237,6 +240,16 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
+ 	return 0;
+ }
+ 
++static void __cpuinit acpi_register_lapic(int id, u8 enabled)
++{
++	if (!enabled) {
++		++disabled_cpus;
++		return;
++	}
++
++	generic_processor_info(id, 0);
++}
++
+ static int __init
+ acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
+ {
+@@ -256,8 +269,26 @@ acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
+ 	 * to not preallocating memory for all NR_CPUS
+ 	 * when we use CPU hotplug.
+ 	 */
+-	mp_register_lapic(processor->id,	/* APIC ID */
+-			  processor->lapic_flags & ACPI_MADT_ENABLED);	/* Enabled? */
++	acpi_register_lapic(processor->id,	/* APIC ID */
++			    processor->lapic_flags & ACPI_MADT_ENABLED);
++
++	return 0;
++}
++
++static int __init
++acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end)
++{
++	struct acpi_madt_local_sapic *processor = NULL;
++
++	processor = (struct acpi_madt_local_sapic *)header;
++
++	if (BAD_MADT_ENTRY(processor, end))
++		return -EINVAL;
++
++	acpi_table_print_madt_entry(header);
++
++	acpi_register_lapic((processor->id << 8) | processor->eid,/* APIC ID */
++			    processor->lapic_flags & ACPI_MADT_ENABLED);
+ 
+ 	return 0;
+ }
+@@ -300,6 +331,8 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
+ 
+ #ifdef CONFIG_X86_IO_APIC
+ 
++struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS];
++
+ static int __init
+ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
+ {
+@@ -532,7 +565,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
+ 	buffer.pointer = NULL;
+ 
+ 	tmp_map = cpu_present_map;
+-	mp_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
++	acpi_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
+ 
+ 	/*
+ 	 * If mp_register_lapic successfully generates a new logical cpu
+@@ -664,10 +697,6 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
+ #define HPET_RESOURCE_NAME_SIZE 9
+ 	hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
+ 
+-	if (!hpet_res)
+-		return 0;
+-
+-	memset(hpet_res, 0, sizeof(*hpet_res));
+ 	hpet_res->name = (void *)&hpet_res[1];
+ 	hpet_res->flags = IORESOURCE_MEM;
+ 	snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, "HPET %u",
+@@ -732,6 +761,16 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
+  * Parse LAPIC entries in MADT
+  * returns 0 on success, < 0 on error
+  */
++
++static void __init acpi_register_lapic_address(unsigned long address)
++{
++	mp_lapic_addr = address;
++
++	set_fixmap_nocache(FIX_APIC_BASE, address);
++	if (boot_cpu_physical_apicid == -1U)
++		boot_cpu_physical_apicid  = GET_APIC_ID(read_apic_id());
++}
++
+ static int __init acpi_parse_madt_lapic_entries(void)
+ {
+ 	int count;
+@@ -753,10 +792,14 @@ static int __init acpi_parse_madt_lapic_entries(void)
+ 		return count;
+ 	}
+ 
+-	mp_register_lapic_address(acpi_lapic_addr);
++	acpi_register_lapic_address(acpi_lapic_addr);
++
++	count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
++				      acpi_parse_sapic, MAX_APICS);
+ 
+-	count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, acpi_parse_lapic,
+-				      MAX_APICS);
++	if (!count)
++		count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
++					      acpi_parse_lapic, MAX_APICS);
+ 	if (!count) {
+ 		printk(KERN_ERR PREFIX "No LAPIC entries present\n");
+ 		/* TBD: Cleanup to allow fallback to MPS */
+diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
+index 8ca3557..c2502eb 100644
+--- a/arch/x86/kernel/acpi/cstate.c
++++ b/arch/x86/kernel/acpi/cstate.c
+@@ -1,6 +1,4 @@
+ /*
+- * arch/i386/kernel/acpi/cstate.c
+- *
+  * Copyright (C) 2005 Intel Corporation
+  * 	Venkatesh Pallipadi <venkatesh.pallipadi at intel.com>
+  * 	- Added _PDC for SMP C-states on Intel CPUs
+@@ -93,7 +91,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
+ 
+ 	/* Make sure we are running on right CPU */
+ 	saved_mask = current->cpus_allowed;
+-	retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
++	retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 	if (retval)
+ 		return -1;
+ 
+@@ -130,7 +128,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
+ 		 cx->address);
+ 
+ out:
+-	set_cpus_allowed(current, saved_mask);
++	set_cpus_allowed_ptr(current, &saved_mask);
+ 	return retval;
+ }
+ EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
+diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c
+index 324eb0c..de2d2e4 100644
+--- a/arch/x86/kernel/acpi/processor.c
++++ b/arch/x86/kernel/acpi/processor.c
+@@ -1,6 +1,4 @@
+ /*
+- * arch/i386/kernel/acpi/processor.c
+- *
+  * Copyright (C) 2005 Intel Corporation
+  * 	Venkatesh Pallipadi <venkatesh.pallipadi at intel.com>
+  * 	- Added _PDC for platforms with Intel CPUs
+diff --git a/arch/x86/kernel/acpi/realmode/.gitignore b/arch/x86/kernel/acpi/realmode/.gitignore
+new file mode 100644
+index 0000000..58f1f48
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/.gitignore
+@@ -0,0 +1,3 @@
++wakeup.bin
++wakeup.elf
++wakeup.lds
+diff --git a/arch/x86/kernel/acpi/realmode/Makefile b/arch/x86/kernel/acpi/realmode/Makefile
+new file mode 100644
+index 0000000..0929008
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/Makefile
+@@ -0,0 +1,57 @@
++#
++# arch/x86/kernel/acpi/realmode/Makefile
++#
++# 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.
++#
++
++targets		:= wakeup.bin wakeup.elf
++
++wakeup-y	+= wakeup.o wakemain.o video-mode.o copy.o
++
++# The link order of the video-*.o modules can matter.  In particular,
++# video-vga.o *must* be listed first, followed by video-vesa.o.
++# Hardware-specific drivers should follow in the order they should be
++# probed, and video-bios.o should typically be last.
++wakeup-y	+= video-vga.o
++wakeup-y	+= video-vesa.o
++wakeup-y	+= video-bios.o
++
++targets		+= $(wakeup-y)
++
++bootsrc		:= $(src)/../../../boot
++
++# ---------------------------------------------------------------------------
++
++# How to compile the 16-bit code.  Note we always compile for -march=i386,
++# that way we can complain to the user if the CPU is insufficient.
++# Compile with _SETUP since this is similar to the boot-time setup code.
++KBUILD_CFLAGS	:= $(LINUXINCLUDE) -g -Os -D_SETUP -D_WAKEUP -D__KERNEL__ \
++		   -I$(srctree)/$(bootsrc) \
++		   $(cflags-y) \
++		   -Wall -Wstrict-prototypes \
++		   -march=i386 -mregparm=3 \
++		   -include $(srctree)/$(bootsrc)/code16gcc.h \
++		   -fno-strict-aliasing -fomit-frame-pointer \
++		   $(call cc-option, -ffreestanding) \
++		   $(call cc-option, -fno-toplevel-reorder,\
++			$(call cc-option, -fno-unit-at-a-time)) \
++		   $(call cc-option, -fno-stack-protector) \
++		   $(call cc-option, -mpreferred-stack-boundary=2)
++KBUILD_CFLAGS	+= $(call cc-option, -m32)
++KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
++
++WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y))
++
++LDFLAGS_wakeup.elf	:= -T
++
++CPPFLAGS_wakeup.lds += -P -C
++
++$(obj)/wakeup.elf: $(src)/wakeup.lds $(WAKEUP_OBJS) FORCE
++	$(call if_changed,ld)
++
++OBJCOPYFLAGS_wakeup.bin	:= -O binary
++
++$(obj)/wakeup.bin: $(obj)/wakeup.elf FORCE
++	$(call if_changed,objcopy)
+diff --git a/arch/x86/kernel/acpi/realmode/copy.S b/arch/x86/kernel/acpi/realmode/copy.S
+new file mode 100644
+index 0000000..dc59ebe
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/copy.S
+@@ -0,0 +1 @@
++#include "../../../boot/copy.S"
+diff --git a/arch/x86/kernel/acpi/realmode/video-bios.c b/arch/x86/kernel/acpi/realmode/video-bios.c
+new file mode 100644
+index 0000000..7deabc1
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/video-bios.c
+@@ -0,0 +1 @@
++#include "../../../boot/video-bios.c"
+diff --git a/arch/x86/kernel/acpi/realmode/video-mode.c b/arch/x86/kernel/acpi/realmode/video-mode.c
+new file mode 100644
+index 0000000..328ad20
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/video-mode.c
+@@ -0,0 +1 @@
++#include "../../../boot/video-mode.c"
+diff --git a/arch/x86/kernel/acpi/realmode/video-vesa.c b/arch/x86/kernel/acpi/realmode/video-vesa.c
+new file mode 100644
+index 0000000..9dbb967
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/video-vesa.c
+@@ -0,0 +1 @@
++#include "../../../boot/video-vesa.c"
+diff --git a/arch/x86/kernel/acpi/realmode/video-vga.c b/arch/x86/kernel/acpi/realmode/video-vga.c
+new file mode 100644
+index 0000000..bcc8125
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/video-vga.c
+@@ -0,0 +1 @@
++#include "../../../boot/video-vga.c"
+diff --git a/arch/x86/kernel/acpi/realmode/wakemain.c b/arch/x86/kernel/acpi/realmode/wakemain.c
+new file mode 100644
+index 0000000..883962d
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/wakemain.c
+@@ -0,0 +1,81 @@
++#include "wakeup.h"
++#include "boot.h"
++
++static void udelay(int loops)
++{
++	while (loops--)
++		io_delay();	/* Approximately 1 us */
++}
++
++static void beep(unsigned int hz)
++{
++	u8 enable;
++
++	if (!hz) {
++		enable = 0x00;		/* Turn off speaker */
++	} else {
++		u16 div = 1193181/hz;
++
++		outb(0xb6, 0x43);	/* Ctr 2, squarewave, load, binary */
++		io_delay();
++		outb(div, 0x42);	/* LSB of counter */
++		io_delay();
++		outb(div >> 8, 0x42);	/* MSB of counter */
++		io_delay();
++
++		enable = 0x03;		/* Turn on speaker */
++	}
++	inb(0x61);		/* Dummy read of System Control Port B */
++	io_delay();
++	outb(enable, 0x61);	/* Enable timer 2 output to speaker */
++	io_delay();
++}
++
++#define DOT_HZ		880
++#define DASH_HZ		587
++#define US_PER_DOT	125000
++
++/* Okay, this is totally silly, but it's kind of fun. */
++static void send_morse(const char *pattern)
++{
++	char s;
++
++	while ((s = *pattern++)) {
++		switch (s) {
++		case '.':
++			beep(DOT_HZ);
++			udelay(US_PER_DOT);
++			beep(0);
++			udelay(US_PER_DOT);
++			break;
++		case '-':
++			beep(DASH_HZ);
++			udelay(US_PER_DOT * 3);
++			beep(0);
++			udelay(US_PER_DOT);
++			break;
++		default:	/* Assume it's a space */
++			udelay(US_PER_DOT * 3);
++			break;
++		}
++	}
++}
++
++void main(void)
++{
++	/* Kill machine if structures are wrong */
++	if (wakeup_header.real_magic != 0x12345678)
++		while (1);
++
++	if (wakeup_header.realmode_flags & 4)
++		send_morse("...-");
++
++	if (wakeup_header.realmode_flags & 1)
++		asm volatile("lcallw   $0xc000,$3");
++
++	if (wakeup_header.realmode_flags & 2) {
++		/* Need to call BIOS */
++		probe_cards(0);
++		set_mode(wakeup_header.video_mode);
++	}
++}
+diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S
+new file mode 100644
+index 0000000..f9b77fb
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/wakeup.S
+@@ -0,0 +1,113 @@
++/*
++ * ACPI wakeup real mode startup stub
++ */
++#include <asm/segment.h>
++#include <asm/msr-index.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++
++	.code16
++	.section ".header", "a"
++
++/* This should match the structure in wakeup.h */
++		.globl	wakeup_header
++wakeup_header:
++video_mode:	.short	0	/* Video mode number */
++pmode_return:	.byte	0x66, 0xea	/* ljmpl */
++		.long	0	/* offset goes here */
++		.short	__KERNEL_CS
++pmode_cr0:	.long	0	/* Saved %cr0 */
++pmode_cr3:	.long	0	/* Saved %cr3 */
++pmode_cr4:	.long	0	/* Saved %cr4 */
++pmode_efer:	.quad	0	/* Saved EFER */
++pmode_gdt:	.quad	0
++realmode_flags:	.long	0
++real_magic:	.long	0
++trampoline_segment:	.word 0
++signature:	.long	0x51ee1111
++
++	.text
++	.globl	_start
++	.code16
++wakeup_code:
++_start:
++	cli
++	cld
++
++	/* Set up segments */
++	movw	%cs, %ax
++	movw	%ax, %ds
++	movw	%ax, %es
++	movw	%ax, %ss
++
++	movl	$wakeup_stack_end, %esp
++
++	/* Clear the EFLAGS */
++	pushl	$0
++	popfl
++
++	/* Check header signature... */
++	movl	signature, %eax
++	cmpl	$0x51ee1111, %eax
++	jne	bogus_real_magic
++
++	/* Check we really have everything... */
++	movl	end_signature, %eax
++	cmpl	$0x65a22c82, %eax
++	jne	bogus_real_magic
++
++	/* Call the C code */
++	calll	main
++
++	/* Do any other stuff... */
++
++#ifndef CONFIG_64BIT
++	/* This could also be done in C code... */
++	movl	pmode_cr3, %eax
++	movl	%eax, %cr3
++
++	movl	pmode_cr4, %ecx
++	jecxz	1f
++	movl	%ecx, %cr4
++1:
++	movl	pmode_efer, %eax
++	movl	pmode_efer + 4, %edx
++	movl	%eax, %ecx
++	orl	%edx, %ecx
++	jz	1f
++	movl	$0xc0000080, %ecx
++	wrmsr
++1:
++
++	lgdtl	pmode_gdt
++
++	/* This really couldn't... */
++	movl	pmode_cr0, %eax
++	movl	%eax, %cr0
++	jmp	pmode_return
++#else
++	pushw	$0
++	pushw	trampoline_segment
++	pushw	$0
++	lret
++#endif
++
++bogus_real_magic:
++1:
++	hlt
++	jmp	1b
++
++	.data
++	.balign	4
++	.globl	HEAP, heap_end
++HEAP:
++	.long	wakeup_heap
++heap_end:
++	.long	wakeup_stack
++
++	.bss
++wakeup_heap:
++	.space	2048
++wakeup_stack:
++	.space	2048
++wakeup_stack_end:
+diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h
+new file mode 100644
+index 0000000..ef8166f
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/wakeup.h
+@@ -0,0 +1,36 @@
++/*
++ * Definitions for the wakeup data structure at the head of the
++ * wakeup code.
++ */
++
++#ifndef ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H
++#define ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H
++
++#ifndef __ASSEMBLY__
++#include <linux/types.h>
++
++/* This must match data at wakeup.S */
++struct wakeup_header {
++	u16 video_mode;		/* Video mode number */
++	u16 _jmp1;		/* ljmpl opcode, 32-bit only */
++	u32 pmode_entry;	/* Protected mode resume point, 32-bit only */
++	u16 _jmp2;		/* CS value, 32-bit only */
++	u32 pmode_cr0;		/* Protected mode cr0 */
++	u32 pmode_cr3;		/* Protected mode cr3 */
++	u32 pmode_cr4;		/* Protected mode cr4 */
++	u32 pmode_efer_low;	/* Protected mode EFER */
++	u32 pmode_efer_high;
++	u64 pmode_gdt;
++	u32 realmode_flags;
++	u32 real_magic;
++	u16 trampoline_segment;	/* segment with trampoline code, 64-bit only */
++	u32 signature;		/* To check we have correct structure */
++} __attribute__((__packed__));
++
++extern struct wakeup_header wakeup_header;
++#endif
++
++#define HEADER_OFFSET 0x3f00
++#define WAKEUP_SIZE   0x4000
++
++#endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
+diff --git a/arch/x86/kernel/acpi/realmode/wakeup.lds.S b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
+new file mode 100644
+index 0000000..22fab6c
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
+@@ -0,0 +1,61 @@
++/*
++ * wakeup.ld
++ *
++ * Linker script for the real-mode wakeup code
++ */
++#undef i386
++#include "wakeup.h"
++
++OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
++OUTPUT_ARCH(i386)
++ENTRY(_start)
++
++SECTIONS
++{
++	. = HEADER_OFFSET;
++	.header : {
++		 *(.header)
++	}
++
++	. = 0;
++	.text : {
++		 *(.text*)
++	}
++
++	. = ALIGN(16);
++	.rodata : {
++		*(.rodata*)
++	}
++
++	.videocards : {
++		video_cards = .;
++		*(.videocards)
++		video_cards_end = .;
++	}
++
++	. = ALIGN(16);
++	.data : {
++		 *(.data*)
++	}
++
++	.signature : {
++		end_signature = .;
++		LONG(0x65a22c82)
++	}
++
++	. = ALIGN(16);
++	.bss :	{
++		__bss_start = .;
++		*(.bss)
++		__bss_end = .;
++	}
++
++	. = ALIGN(16);
++	_end = .;
++
++	/DISCARD/ : {
++		*(.note*)
++	}
++
++	. = ASSERT(_end <= WAKEUP_SIZE, "Wakeup too big!");
++}
+diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
+index 6bc815c..afc25ee 100644
+--- a/arch/x86/kernel/acpi/sleep.c
++++ b/arch/x86/kernel/acpi/sleep.c
+@@ -10,30 +10,72 @@
+ #include <linux/dmi.h>
+ #include <linux/cpumask.h>
+ 
+-#include <asm/smp.h>
++#include "realmode/wakeup.h"
++#include "sleep.h"
+ 
+-/* address in low memory of the wakeup routine. */
+-unsigned long acpi_wakeup_address = 0;
++unsigned long acpi_wakeup_address;
+ unsigned long acpi_realmode_flags;
+-extern char wakeup_start, wakeup_end;
+ 
+-extern unsigned long acpi_copy_wakeup_routine(unsigned long);
++/* address in low memory of the wakeup routine. */
++static unsigned long acpi_realmode;
++
++#ifdef CONFIG_64BIT
++static char temp_stack[10240];
++#endif
+ 
+ /**
+  * acpi_save_state_mem - save kernel state
+  *
+  * Create an identity mapped page table and copy the wakeup routine to
+  * low memory.
++ *
++ * Note that this is too late to change acpi_wakeup_address.
+  */
+ int acpi_save_state_mem(void)
+ {
+-	if (!acpi_wakeup_address) {
+-		printk(KERN_ERR "Could not allocate memory during boot, S3 disabled\n");
++	struct wakeup_header *header;
++
++	if (!acpi_realmode) {
++		printk(KERN_ERR "Could not allocate memory during boot, "
++		       "S3 disabled\n");
+ 		return -ENOMEM;
+ 	}
+-	memcpy((void *)acpi_wakeup_address, &wakeup_start,
+-	       &wakeup_end - &wakeup_start);
+-	acpi_copy_wakeup_routine(acpi_wakeup_address);
++	memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE);
++
++	header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET);
++	if (header->signature != 0x51ee1111) {
++		printk(KERN_ERR "wakeup header does not match\n");
++		return -EINVAL;
++	}
++
++	header->video_mode = saved_video_mode;
++
++#ifndef CONFIG_64BIT
++	store_gdt((struct desc_ptr *)&header->pmode_gdt);
++
++	header->pmode_efer_low = nx_enabled;
++	if (header->pmode_efer_low & 1) {
++		/* This is strange, why not save efer, always? */
++		rdmsr(MSR_EFER, header->pmode_efer_low,
++			header->pmode_efer_high);
++	}
++#endif /* !CONFIG_64BIT */
++
++	header->pmode_cr0 = read_cr0();
++	header->pmode_cr4 = read_cr4();
++	header->realmode_flags = acpi_realmode_flags;
++	header->real_magic = 0x12345678;
++
++#ifndef CONFIG_64BIT
++	header->pmode_entry = (u32)&wakeup_pmode_return;
++	header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET);
++	saved_magic = 0x12345678;
++#else /* CONFIG_64BIT */
++	header->trampoline_segment = setup_trampoline() >> 4;
++	init_rsp = (unsigned long)temp_stack + 4096;
++	initial_code = (unsigned long)wakeup_long64;
++	saved_magic = 0x123456789abcdef0;
++#endif /* CONFIG_64BIT */
+ 
+ 	return 0;
+ }
+@@ -56,15 +98,20 @@ void acpi_restore_state_mem(void)
+  */
+ void __init acpi_reserve_bootmem(void)
+ {
+-	if ((&wakeup_end - &wakeup_start) > PAGE_SIZE*2) {
++	if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
+ 		printk(KERN_ERR
+ 		       "ACPI: Wakeup code way too big, S3 disabled.\n");
+ 		return;
+ 	}
+ 
+-	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2);
+-	if (!acpi_wakeup_address)
++	acpi_realmode = (unsigned long)alloc_bootmem_low(WAKEUP_SIZE);
++
++	if (!acpi_realmode) {
+ 		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
++		return;
++	}
++
++	acpi_wakeup_address = acpi_realmode;
+ }
+ 
+ 
+diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h
+new file mode 100644
+index 0000000..adbcbaa
+--- /dev/null
++++ b/arch/x86/kernel/acpi/sleep.h
+@@ -0,0 +1,16 @@
++/*
++ *	Variables and functions used by the code in sleep.c
++ */
++
++#include <asm/trampoline.h>
++
++extern char wakeup_code_start, wakeup_code_end;
++
++extern unsigned long saved_video_mode;
++extern long saved_magic;
++
++extern int wakeup_pmode_return;
++extern char swsusp_pg_dir[PAGE_SIZE];
++
++extern unsigned long acpi_copy_wakeup_routine(unsigned long);
++extern void wakeup_long64(void);
+diff --git a/arch/x86/kernel/acpi/sleep_32.c b/arch/x86/kernel/acpi/sleep_32.c
+deleted file mode 100644
+index 63fe552..0000000
+--- a/arch/x86/kernel/acpi/sleep_32.c
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/*
+- * sleep.c - x86-specific ACPI sleep support.
+- *
+- *  Copyright (C) 2001-2003 Patrick Mochel
+- *  Copyright (C) 2001-2003 Pavel Machek <pavel at suse.cz>
+- */
+-
+-#include <linux/acpi.h>
+-#include <linux/bootmem.h>
+-#include <linux/dmi.h>
+-#include <linux/cpumask.h>
+-
+-#include <asm/smp.h>
+-
+-/* Ouch, we want to delete this. We already have better version in userspace, in
+-   s2ram from suspend.sf.net project */
+-static __init int reset_videomode_after_s3(const struct dmi_system_id *d)
+-{
+-	acpi_realmode_flags |= 2;
+-	return 0;
+-}
+-
+-static __initdata struct dmi_system_id acpisleep_dmi_table[] = {
+-	{			/* Reset video mode after returning from ACPI S3 sleep */
+-	 .callback = reset_videomode_after_s3,
+-	 .ident = "Toshiba Satellite 4030cdt",
+-	 .matches = {
+-		     DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
+-		     },
+-	 },
+-	{}
+-};
+-
+-static int __init acpisleep_dmi_init(void)
+-{
+-	dmi_check_system(acpisleep_dmi_table);
+-	return 0;
+-}
+-
+-core_initcall(acpisleep_dmi_init);
+diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S
+index f53e327..a12e6a9 100644
+--- a/arch/x86/kernel/acpi/wakeup_32.S
++++ b/arch/x86/kernel/acpi/wakeup_32.S
+@@ -3,178 +3,12 @@
+ #include <asm/segment.h>
+ #include <asm/page.h>
+ 
+-#
+-# wakeup_code runs in real mode, and at unknown address (determined at run-time).
+-# Therefore it must only use relative jumps/calls. 
+-#
+-# Do we need to deal with A20? It is okay: ACPI specs says A20 must be enabled
+-#
+-# If physical address of wakeup_code is 0x12345, BIOS should call us with
+-# cs = 0x1234, eip = 0x05
+-#
+-
+-#define BEEP \
+-	inb	$97, %al; 	\
+-	outb	%al, $0x80; 	\
+-	movb	$3, %al; 	\
+-	outb	%al, $97; 	\
+-	outb	%al, $0x80; 	\
+-	movb	$-74, %al; 	\
+-	outb	%al, $67; 	\
+-	outb	%al, $0x80; 	\
+-	movb	$-119, %al; 	\
+-	outb	%al, $66; 	\
+-	outb	%al, $0x80; 	\
+-	movb	$15, %al; 	\
+-	outb	%al, $66;
+-
+-ALIGN
+-	.align	4096
+-ENTRY(wakeup_start)
+-wakeup_code:
+-	wakeup_code_start = .
+-	.code16
+-
+-	cli
+-	cld
+-
+-	# setup data segment
+-	movw	%cs, %ax
+-	movw	%ax, %ds					# Make ds:0 point to wakeup_start
+-	movw	%ax, %ss
+-
+-	testl   $4, realmode_flags - wakeup_code
+-	jz      1f
+-	BEEP
+-1:
+-	mov	$(wakeup_stack - wakeup_code), %sp		# Private stack is needed for ASUS board
+-
+-	pushl	$0						# Kill any dangerous flags
+-	popfl
+-
+-	movl	real_magic - wakeup_code, %eax
+-	cmpl	$0x12345678, %eax
+-	jne	bogus_real_magic
+-
+-	testl	$1, realmode_flags - wakeup_code
+-	jz	1f
+-	lcall   $0xc000,$3
+-	movw	%cs, %ax
+-	movw	%ax, %ds					# Bios might have played with that
+-	movw	%ax, %ss
+-1:
+-
+-	testl	$2, realmode_flags - wakeup_code
+-	jz	1f
+-	mov	video_mode - wakeup_code, %ax
+-	call	mode_set
+-1:
+-
+-	# set up page table
+-	movl	$swsusp_pg_dir-__PAGE_OFFSET, %eax
+-	movl	%eax, %cr3
+-
+-	testl	$1, real_efer_save_restore - wakeup_code
+-	jz	4f
+-	# restore efer setting
+-	movl	real_save_efer_edx - wakeup_code, %edx
+-	movl	real_save_efer_eax - wakeup_code, %eax
+-	mov     $0xc0000080, %ecx
+-	wrmsr
+-4:
+-	# make sure %cr4 is set correctly (features, etc)
+-	movl	real_save_cr4 - wakeup_code, %eax
+-	movl	%eax, %cr4
+-	
+-	# need a gdt -- use lgdtl to force 32-bit operands, in case
+-	# the GDT is located past 16 megabytes.
+-	lgdtl	real_save_gdt - wakeup_code
+-
+-	movl	real_save_cr0 - wakeup_code, %eax
+-	movl	%eax, %cr0
+-	jmp 1f
+-1:
+-	movl	real_magic - wakeup_code, %eax
+-	cmpl	$0x12345678, %eax
+-	jne	bogus_real_magic
+-
+-	testl   $8, realmode_flags - wakeup_code
+-	jz      1f
+-	BEEP
+-1:
+-	ljmpl	$__KERNEL_CS, $wakeup_pmode_return
+-
+-real_save_gdt:	.word 0
+-		.long 0
+-real_save_cr0:	.long 0
+-real_save_cr3:	.long 0
+-real_save_cr4:	.long 0
+-real_magic:	.long 0
+-video_mode:	.long 0
+-realmode_flags:	.long 0
+-real_efer_save_restore:	.long 0
+-real_save_efer_edx: 	.long 0
+-real_save_efer_eax: 	.long 0
+-
+-bogus_real_magic:
+-	jmp bogus_real_magic
+-
+-/* This code uses an extended set of video mode numbers. These include:
+- * Aliases for standard modes
+- *	NORMAL_VGA (-1)
+- *	EXTENDED_VGA (-2)
+- *	ASK_VGA (-3)
+- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+- * of compatibility when extending the table. These are between 0x00 and 0xff.
+- */
+-#define VIDEO_FIRST_MENU 0x0000
+-
+-/* Standard BIOS video modes (BIOS number + 0x0100) */
+-#define VIDEO_FIRST_BIOS 0x0100
+-
+-/* VESA BIOS video modes (VESA number + 0x0200) */
+-#define VIDEO_FIRST_VESA 0x0200
+-
+-/* Video7 special modes (BIOS number + 0x0900) */
+-#define VIDEO_FIRST_V7 0x0900
+-
+-# Setting of user mode (AX=mode ID) => CF=success
+-
+-# For now, we only handle VESA modes (0x0200..0x03ff).  To handle other
+-# modes, we should probably compile in the video code from the boot
+-# directory.
+-mode_set:
+-	movw	%ax, %bx
+-	subb	$VIDEO_FIRST_VESA>>8, %bh
+-	cmpb	$2, %bh
+-	jb	check_vesa
+-
+-setbad:
+-	clc
+-	ret
+-
+-check_vesa:
+-	orw	$0x4000, %bx			# Use linear frame buffer
+-	movw	$0x4f02, %ax			# VESA BIOS mode set call
+-	int	$0x10
+-	cmpw	$0x004f, %ax			# AL=4f if implemented
+-	jnz	setbad				# AH=0 if OK
+-
+-	stc
+-	ret
++# Copyright 2003, 2008 Pavel Machek <pavel at suse.cz>, distribute under GPLv2
+ 
+ 	.code32
+ 	ALIGN
+ 
+-.org	0x800
+-wakeup_stack_begin:	# Stack grows down
+-
+-.org	0xff0		# Just below end of page
+-wakeup_stack:
+-ENTRY(wakeup_end)
+-	
+-.org	0x1000
+-
++ENTRY(wakeup_pmode_return)
+ wakeup_pmode_return:
+ 	movw	$__KERNEL_DS, %ax
+ 	movw	%ax, %ss
+@@ -187,7 +21,7 @@ wakeup_pmode_return:
+ 	lgdt	saved_gdt
+ 	lidt	saved_idt
+ 	lldt	saved_ldt
+-	ljmp	$(__KERNEL_CS),$1f
++	ljmp	$(__KERNEL_CS), $1f
+ 1:
+ 	movl	%cr3, %eax
+ 	movl	%eax, %cr3
+@@ -201,82 +35,41 @@ wakeup_pmode_return:
+ 	jne	bogus_magic
+ 
+ 	# jump to place where we left off
+-	movl	saved_eip,%eax
++	movl	saved_eip, %eax
+ 	jmp	*%eax
+ 
+ bogus_magic:
+ 	jmp	bogus_magic
+ 
+ 
+-##
+-# acpi_copy_wakeup_routine
+-#
+-# Copy the above routine to low memory.
+-#
+-# Parameters:
+-# %eax:	place to copy wakeup routine to
+-#
+-# Returned address is location of code in low memory (past data and stack)
+-#
+-ENTRY(acpi_copy_wakeup_routine)
+ 
+-	pushl	%ebx
++save_registers:
+ 	sgdt	saved_gdt
+ 	sidt	saved_idt
+ 	sldt	saved_ldt
+ 	str	saved_tss
+ 
+-	movl	nx_enabled, %edx
+-	movl	%edx, real_efer_save_restore - wakeup_start (%eax)
+-	testl	$1, real_efer_save_restore - wakeup_start (%eax)
+-	jz	2f
+-	# save efer setting
+-	pushl	%eax
+-	movl	%eax, %ebx
+-	mov     $0xc0000080, %ecx
+-	rdmsr
+-	movl	%edx, real_save_efer_edx - wakeup_start (%ebx)
+-	movl	%eax, real_save_efer_eax - wakeup_start (%ebx)
+-	popl	%eax
+-2:
+-
+-	movl    %cr3, %edx
+-	movl    %edx, real_save_cr3 - wakeup_start (%eax)
+-	movl    %cr4, %edx
+-	movl    %edx, real_save_cr4 - wakeup_start (%eax)
+-	movl	%cr0, %edx
+-	movl	%edx, real_save_cr0 - wakeup_start (%eax)
+-	sgdt    real_save_gdt - wakeup_start (%eax)
+-
+-	movl	saved_videomode, %edx
+-	movl	%edx, video_mode - wakeup_start (%eax)
+-	movl	acpi_realmode_flags, %edx
+-	movl	%edx, realmode_flags - wakeup_start (%eax)
+-	movl	$0x12345678, real_magic - wakeup_start (%eax)
+-	movl	$0x12345678, saved_magic
+-	popl	%ebx
+-	ret
+-
+-save_registers:
+ 	leal	4(%esp), %eax
+ 	movl	%eax, saved_context_esp
+-	movl %ebx, saved_context_ebx
+-	movl %ebp, saved_context_ebp
+-	movl %esi, saved_context_esi
+-	movl %edi, saved_context_edi
+-	pushfl ; popl saved_context_eflags
+-
+-	movl $ret_point, saved_eip
++	movl	%ebx, saved_context_ebx
++	movl	%ebp, saved_context_ebp
++	movl	%esi, saved_context_esi
++	movl	%edi, saved_context_edi
++	pushfl
++	popl	saved_context_eflags
++
++	movl	$ret_point, saved_eip
+ 	ret
+ 
+ 
+ restore_registers:
+-	movl saved_context_ebp, %ebp
+-	movl saved_context_ebx, %ebx
+-	movl saved_context_esi, %esi
+-	movl saved_context_edi, %edi
+-	pushl saved_context_eflags ; popfl
+-	ret	
++	movl	saved_context_ebp, %ebp
++	movl	saved_context_ebx, %ebx
++	movl	saved_context_esi, %esi
++	movl	saved_context_edi, %edi
++	pushl	saved_context_eflags
++	popfl
++	ret
+ 
+ ENTRY(do_suspend_lowlevel)
+ 	call	save_processor_state
+diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
+index 2e1b9e0..bcc2934 100644
+--- a/arch/x86/kernel/acpi/wakeup_64.S
++++ b/arch/x86/kernel/acpi/wakeup_64.S
+@@ -7,191 +7,18 @@
+ #include <asm/asm-offsets.h>
+ 
+ # Copyright 2003 Pavel Machek <pavel at suse.cz>, distribute under GPLv2
+-#
+-# wakeup_code runs in real mode, and at unknown address (determined at run-time).
+-# Therefore it must only use relative jumps/calls. 
+-#
+-# Do we need to deal with A20? It is okay: ACPI specs says A20 must be enabled
+-#
+-# If physical address of wakeup_code is 0x12345, BIOS should call us with
+-# cs = 0x1234, eip = 0x05
+-#
+-
+-#define BEEP \
+-	inb	$97, %al; 	\
+-	outb	%al, $0x80; 	\
+-	movb	$3, %al; 	\
+-	outb	%al, $97; 	\
+-	outb	%al, $0x80; 	\
+-	movb	$-74, %al; 	\
+-	outb	%al, $67; 	\
+-	outb	%al, $0x80; 	\
+-	movb	$-119, %al; 	\
+-	outb	%al, $66; 	\
+-	outb	%al, $0x80; 	\
+-	movb	$15, %al; 	\
+-	outb	%al, $66;
+-
+-
+-ALIGN
+-	.align	16
+-ENTRY(wakeup_start)
+-wakeup_code:
+-	wakeup_code_start = .
+-	.code16
+-
+-# Running in *copy* of this code, somewhere in low 1MB.
+-
+-	cli
+-	cld
+-	# setup data segment
+-	movw	%cs, %ax
+-	movw	%ax, %ds		# Make ds:0 point to wakeup_start
+-	movw	%ax, %ss
+-
+-	# Data segment must be set up before we can see whether to beep.
+-	testl   $4, realmode_flags - wakeup_code
+-	jz      1f
+-	BEEP
+-1:
+-
+-					# Private stack is needed for ASUS board
+-	mov	$(wakeup_stack - wakeup_code), %sp
+-
+-	pushl	$0			# Kill any dangerous flags
+-	popfl
+-
+-	movl	real_magic - wakeup_code, %eax
+-	cmpl	$0x12345678, %eax
+-	jne	bogus_real_magic
+-
+-	testl	$1, realmode_flags - wakeup_code
+-	jz	1f
+-	lcall   $0xc000,$3
+-	movw	%cs, %ax
+-	movw	%ax, %ds		# Bios might have played with that
+-	movw	%ax, %ss
+-1:
+-
+-	testl	$2, realmode_flags - wakeup_code
+-	jz	1f
+-	mov	video_mode - wakeup_code, %ax
+-	call	mode_set
+-1:
+-
+-	mov	%ds, %ax			# Find 32bit wakeup_code addr
+-	movzx   %ax, %esi			# (Convert %ds:gdt to a liner ptr)
+-	shll    $4, %esi
+-						# Fix up the vectors
+-	addl    %esi, wakeup_32_vector - wakeup_code
+-	addl    %esi, wakeup_long64_vector - wakeup_code
+-	addl    %esi, gdt_48a + 2 - wakeup_code # Fixup the gdt pointer
+-
+-	lidtl	%ds:idt_48a - wakeup_code
+-	lgdtl	%ds:gdt_48a - wakeup_code	# load gdt with whatever is
+-						# appropriate
+-
+-	movl	$1, %eax			# protected mode (PE) bit
+-	lmsw	%ax				# This is it!
+-	jmp	1f
+-1:
+-
+-	ljmpl   *(wakeup_32_vector - wakeup_code)
+-
+-	.balign 4
+-wakeup_32_vector:
+-	.long   wakeup_32 - wakeup_code
+-	.word   __KERNEL32_CS, 0
+-
+-	.code32
+-wakeup_32:
+-# Running in this code, but at low address; paging is not yet turned on.
+-
+-	movl	$__KERNEL_DS, %eax
+-	movl	%eax, %ds
+-
+-	/*
+-	 * Prepare for entering 64bits mode
+-	 */
+-
+-	/* Enable PAE */
+-	xorl	%eax, %eax
+-	btsl	$5, %eax
+-	movl	%eax, %cr4
+-
+-	/* Setup early boot stage 4 level pagetables */
+-	leal    (wakeup_level4_pgt - wakeup_code)(%esi), %eax
+-	movl	%eax, %cr3
+-
+-        /* Check if nx is implemented */
+-        movl    $0x80000001, %eax
+-        cpuid
+-        movl    %edx,%edi
+-
+-	/* Enable Long Mode */
+-	xorl    %eax, %eax
+-	btsl	$_EFER_LME, %eax
+-
+-	/* No Execute supported? */
+-	btl	$20,%edi
+-	jnc     1f
+-	btsl	$_EFER_NX, %eax
+-				
+-	/* Make changes effective */
+-1:	movl    $MSR_EFER, %ecx
+-	xorl    %edx, %edx
+-	wrmsr
+-
+-	xorl	%eax, %eax
+-	btsl	$31, %eax			/* Enable paging and in turn activate Long Mode */
+-	btsl	$0, %eax			/* Enable protected mode */
+-
+-	/* Make changes effective */
+-	movl	%eax, %cr0
+-
+-	/* At this point:
+-		CR4.PAE must be 1
+-		CS.L must be 0
+-		CR3 must point to PML4
+-		Next instruction must be a branch
+-		This must be on identity-mapped page
+-	*/
+-	/*
+-	 * At this point we're in long mode but in 32bit compatibility mode
+-	 * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
+-	 * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we load
+-	 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
+-	 */
+-
+-	/* Finally jump in 64bit mode */
+-        ljmp    *(wakeup_long64_vector - wakeup_code)(%esi)
+-
+-	.balign 4
+-wakeup_long64_vector:
+-	.long   wakeup_long64 - wakeup_code
+-	.word   __KERNEL_CS, 0
+ 
+ .code64
+-
+-	/* Hooray, we are in Long 64-bit mode (but still running in
+-	 * low memory)
+-	 */
+-wakeup_long64:
+ 	/*
+-	 * We must switch to a new descriptor in kernel space for the GDT
+-	 * because soon the kernel won't have access anymore to the userspace
+-	 * addresses where we're currently running on. We have to do that here
+-	 * because in 32bit we couldn't load a 64bit linear address.
++	 * Hooray, we are in Long 64-bit mode (but still running in low memory)
+ 	 */
+-	lgdt	cpu_gdt_descr
+-
+-	movq    saved_magic, %rax
+-	movq    $0x123456789abcdef0, %rdx
+-	cmpq    %rdx, %rax
+-	jne     bogus_64_magic
++ENTRY(wakeup_long64)
++wakeup_long64:
++	movq	saved_magic, %rax
++	movq	$0x123456789abcdef0, %rdx
++	cmpq	%rdx, %rax
++	jne	bogus_64_magic
+ 
+-	nop
+-	nop
+ 	movw	$__KERNEL_DS, %ax
+ 	movw	%ax, %ss	
+ 	movw	%ax, %ds
+@@ -208,130 +35,8 @@ wakeup_long64:
+ 	movq	saved_rip, %rax
+ 	jmp	*%rax
+ 
+-.code32
+-
+-	.align	64	
+-gdta:
+-	/* Its good to keep gdt in sync with one in trampoline.S */
+-	.word	0, 0, 0, 0			# dummy
+-	/* ??? Why I need the accessed bit set in order for this to work? */
+-	.quad   0x00cf9b000000ffff              # __KERNEL32_CS
+-	.quad   0x00af9b000000ffff              # __KERNEL_CS
+-	.quad   0x00cf93000000ffff              # __KERNEL_DS
+-
+-idt_48a:
+-	.word	0				# idt limit = 0
+-	.word	0, 0				# idt base = 0L
+-
+-gdt_48a:
+-	.word	0x800				# gdt limit=2048,
+-						#  256 GDT entries
+-	.long   gdta - wakeup_code              # gdt base (relocated in later)
+-	
+-real_magic:	.quad 0
+-video_mode:	.quad 0
+-realmode_flags:	.quad 0
+-
+-.code16
+-bogus_real_magic:
+-	jmp bogus_real_magic
+-
+-.code64
+ bogus_64_magic:
+-	jmp bogus_64_magic
+-
+-/* This code uses an extended set of video mode numbers. These include:
+- * Aliases for standard modes
+- *	NORMAL_VGA (-1)
+- *	EXTENDED_VGA (-2)
+- *	ASK_VGA (-3)
+- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+- * of compatibility when extending the table. These are between 0x00 and 0xff.
+- */
+-#define VIDEO_FIRST_MENU 0x0000
+-
+-/* Standard BIOS video modes (BIOS number + 0x0100) */
+-#define VIDEO_FIRST_BIOS 0x0100
+-
+-/* VESA BIOS video modes (VESA number + 0x0200) */
+-#define VIDEO_FIRST_VESA 0x0200
+-
+-/* Video7 special modes (BIOS number + 0x0900) */
+-#define VIDEO_FIRST_V7 0x0900
+-
+-# Setting of user mode (AX=mode ID) => CF=success
+-
+-# For now, we only handle VESA modes (0x0200..0x03ff).  To handle other
+-# modes, we should probably compile in the video code from the boot
+-# directory.
+-.code16
+-mode_set:
+-	movw	%ax, %bx
+-	subb	$VIDEO_FIRST_VESA>>8, %bh
+-	cmpb	$2, %bh
+-	jb	check_vesa
+-
+-setbad:
+-	clc
+-	ret
+-
+-check_vesa:
+-	orw	$0x4000, %bx			# Use linear frame buffer
+-	movw	$0x4f02, %ax			# VESA BIOS mode set call
+-	int	$0x10
+-	cmpw	$0x004f, %ax			# AL=4f if implemented
+-	jnz	setbad				# AH=0 if OK
+-
+-	stc
+-	ret
+-
+-wakeup_stack_begin:	# Stack grows down
+-
+-.org	0xff0
+-wakeup_stack:		# Just below end of page
+-
+-.org   0x1000
+-ENTRY(wakeup_level4_pgt)
+-	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+-	.fill   510,8,0
+-	/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
+-	.quad   level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
+-
+-ENTRY(wakeup_end)
+-	
+-##
+-# acpi_copy_wakeup_routine
+-#
+-# Copy the above routine to low memory.
+-#
+-# Parameters:
+-# %rdi:	place to copy wakeup routine to
+-#
+-# Returned address is location of code in low memory (past data and stack)
+-#
+-	.code64
+-ENTRY(acpi_copy_wakeup_routine)
+-	pushq	%rax
+-	pushq	%rdx
+-
+-	movl	saved_video_mode, %edx
+-	movl	%edx, video_mode - wakeup_start (,%rdi)
+-	movl	acpi_realmode_flags, %edx
+-	movl	%edx, realmode_flags - wakeup_start (,%rdi)
+-	movq	$0x12345678, real_magic - wakeup_start (,%rdi)
+-	movq	$0x123456789abcdef0, %rdx
+-	movq	%rdx, saved_magic
+-
+-	movq    saved_magic, %rax
+-	movq    $0x123456789abcdef0, %rdx
+-	cmpq    %rdx, %rax
+-	jne     bogus_64_magic
+-
+-	# restore the regs we used
+-	popq	%rdx
+-	popq	%rax
+-ENTRY(do_suspend_lowlevel_s4bios)
+-	ret
++	jmp	bogus_64_magic
+ 
+ 	.align 2
+ 	.p2align 4,,15
+@@ -414,7 +119,7 @@ do_suspend_lowlevel:
+ 	jmp	restore_processor_state
+ .LFE5:
+ .Lfe5:
+-	.size	do_suspend_lowlevel,.Lfe5-do_suspend_lowlevel
++	.size	do_suspend_lowlevel, .Lfe5-do_suspend_lowlevel
+ 	
+ .data
+ ALIGN
+diff --git a/arch/x86/kernel/acpi/wakeup_rm.S b/arch/x86/kernel/acpi/wakeup_rm.S
+new file mode 100644
+index 0000000..6ff3b57
+--- /dev/null
++++ b/arch/x86/kernel/acpi/wakeup_rm.S
+@@ -0,0 +1,10 @@
++/*
++ * Wrapper script for the realmode binary as a transport object
++ * before copying to low memory.
++ */
++	.section ".rodata","a"
++	.globl	wakeup_code_start, wakeup_code_end
++wakeup_code_start:
++	.incbin	"arch/x86/kernel/acpi/realmode/wakeup.bin"
++wakeup_code_end:
++	.size	wakeup_code_start, .-wakeup_code_start
+diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
+index 5fed98c..65c7857 100644
+--- a/arch/x86/kernel/alternative.c
++++ b/arch/x86/kernel/alternative.c
+@@ -11,6 +11,8 @@
+ #include <asm/mce.h>
+ #include <asm/nmi.h>
+ #include <asm/vsyscall.h>
++#include <asm/cacheflush.h>
++#include <asm/io.h>
+ 
+ #define MAX_PATCH_LEN (255-1)
+ 
+@@ -177,7 +179,7 @@ static const unsigned char*const * find_nop_table(void)
+ #endif /* CONFIG_X86_64 */
+ 
+ /* Use this to add nops to a buffer, then text_poke the whole buffer. */
+-static void add_nops(void *insns, unsigned int len)
++void add_nops(void *insns, unsigned int len)
+ {
+ 	const unsigned char *const *noptable = find_nop_table();
+ 
+@@ -190,6 +192,7 @@ static void add_nops(void *insns, unsigned int len)
+ 		len -= noplen;
+ 	}
+ }
++EXPORT_SYMBOL_GPL(add_nops);
+ 
+ extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+ extern u8 *__smp_locks[], *__smp_locks_end[];
+@@ -205,7 +208,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+ 	struct alt_instr *a;
+ 	char insnbuf[MAX_PATCH_LEN];
+ 
+-	DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
++	DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
+ 	for (a = start; a < end; a++) {
+ 		u8 *instr = a->instr;
+ 		BUG_ON(a->replacementlen > a->instrlen);
+@@ -217,13 +220,13 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+ 		if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
+ 			instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
+ 			DPRINTK("%s: vsyscall fixup: %p => %p\n",
+-				__FUNCTION__, a->instr, instr);
++				__func__, a->instr, instr);
+ 		}
+ #endif
+ 		memcpy(insnbuf, a->replacement, a->replacementlen);
+ 		add_nops(insnbuf + a->replacementlen,
+ 			 a->instrlen - a->replacementlen);
+-		text_poke(instr, insnbuf, a->instrlen);
++		text_poke_early(instr, insnbuf, a->instrlen);
+ 	}
+ }
+ 
+@@ -284,7 +287,6 @@ void alternatives_smp_module_add(struct module *mod, char *name,
+ 				 void *text,  void *text_end)
+ {
+ 	struct smp_alt_module *smp;
+-	unsigned long flags;
+ 
+ 	if (noreplace_smp)
+ 		return;
+@@ -307,42 +309,40 @@ void alternatives_smp_module_add(struct module *mod, char *name,
+ 	smp->text	= text;
+ 	smp->text_end	= text_end;
+ 	DPRINTK("%s: locks %p -> %p, text %p -> %p, name %s\n",
+-		__FUNCTION__, smp->locks, smp->locks_end,
++		__func__, smp->locks, smp->locks_end,
+ 		smp->text, smp->text_end, smp->name);
+ 
+-	spin_lock_irqsave(&smp_alt, flags);
++	spin_lock(&smp_alt);
+ 	list_add_tail(&smp->next, &smp_alt_modules);
+ 	if (boot_cpu_has(X86_FEATURE_UP))
+ 		alternatives_smp_unlock(smp->locks, smp->locks_end,
+ 					smp->text, smp->text_end);
+-	spin_unlock_irqrestore(&smp_alt, flags);
++	spin_unlock(&smp_alt);
+ }
+ 
+ void alternatives_smp_module_del(struct module *mod)
+ {
+ 	struct smp_alt_module *item;
+-	unsigned long flags;
+ 
+ 	if (smp_alt_once || noreplace_smp)
+ 		return;
+ 
+-	spin_lock_irqsave(&smp_alt, flags);
++	spin_lock(&smp_alt);
+ 	list_for_each_entry(item, &smp_alt_modules, next) {
+ 		if (mod != item->mod)
+ 			continue;
+ 		list_del(&item->next);
+-		spin_unlock_irqrestore(&smp_alt, flags);
+-		DPRINTK("%s: %s\n", __FUNCTION__, item->name);
++		spin_unlock(&smp_alt);
++		DPRINTK("%s: %s\n", __func__, item->name);
+ 		kfree(item);
+ 		return;
+ 	}
+-	spin_unlock_irqrestore(&smp_alt, flags);
++	spin_unlock(&smp_alt);
+ }
+ 
+ void alternatives_smp_switch(int smp)
+ {
+ 	struct smp_alt_module *mod;
+-	unsigned long flags;
+ 
+ #ifdef CONFIG_LOCKDEP
+ 	/*
+@@ -359,7 +359,7 @@ void alternatives_smp_switch(int smp)
+ 		return;
+ 	BUG_ON(!smp && (num_online_cpus() > 1));
+ 
+-	spin_lock_irqsave(&smp_alt, flags);
++	spin_lock(&smp_alt);
+ 
+ 	/*
+ 	 * Avoid unnecessary switches because it forces JIT based VMs to
+@@ -383,7 +383,7 @@ void alternatives_smp_switch(int smp)
+ 						mod->text, mod->text_end);
+ 	}
+ 	smp_mode = smp;
+-	spin_unlock_irqrestore(&smp_alt, flags);
++	spin_unlock(&smp_alt);
+ }
+ 
+ #endif
+@@ -411,7 +411,7 @@ void apply_paravirt(struct paravirt_patch_site *start,
+ 
+ 		/* Pad the rest with nops */
+ 		add_nops(insnbuf + used, p->len - used);
+-		text_poke(p->instr, insnbuf, p->len);
++		text_poke_early(p->instr, insnbuf, p->len);
+ 	}
+ }
+ extern struct paravirt_patch_site __start_parainstructions[],
+@@ -420,8 +420,6 @@ extern struct paravirt_patch_site __start_parainstructions[],
+ 
+ void __init alternative_instructions(void)
+ {
+-	unsigned long flags;
+-
+ 	/* The patching is not fully atomic, so try to avoid local interruptions
+ 	   that might execute the to be patched code.
+ 	   Other CPUs are not running. */
+@@ -430,7 +428,6 @@ void __init alternative_instructions(void)
+ 	stop_mce();
+ #endif
+ 
+-	local_irq_save(flags);
+ 	apply_alternatives(__alt_instructions, __alt_instructions_end);
+ 
+ 	/* switch to patch-once-at-boottime-only mode and free the
+@@ -462,7 +459,6 @@ void __init alternative_instructions(void)
+ 	}
+ #endif
+  	apply_paravirt(__parainstructions, __parainstructions_end);
+-	local_irq_restore(flags);
+ 
+ 	if (smp_alt_once)
+ 		free_init_pages("SMP alternatives",
+@@ -475,18 +471,70 @@ void __init alternative_instructions(void)
+ #endif
+ }
+ 
+-/*
+- * Warning:
++/**
++ * text_poke_early - Update instructions on a live kernel at boot time
++ * @addr: address to modify
++ * @opcode: source of the copy
++ * @len: length to copy
++ *
+  * When you use this code to patch more than one byte of an instruction
+  * you need to make sure that other CPUs cannot execute this code in parallel.
+- * Also no thread must be currently preempted in the middle of these instructions.
+- * And on the local CPU you need to be protected again NMI or MCE handlers
+- * seeing an inconsistent instruction while you patch.
++ * Also no thread must be currently preempted in the middle of these
++ * instructions. And on the local CPU you need to be protected again NMI or MCE
++ * handlers seeing an inconsistent instruction while you patch.
+  */
+-void __kprobes text_poke(void *addr, unsigned char *opcode, int len)
++void *text_poke_early(void *addr, const void *opcode, size_t len)
+ {
++	unsigned long flags;
++	local_irq_save(flags);
+ 	memcpy(addr, opcode, len);
++	local_irq_restore(flags);
++	sync_core();
++	/* Could also do a CLFLUSH here to speed up CPU recovery; but
++	   that causes hangs on some VIA CPUs. */
++	return addr;
++}
++
++/**
++ * text_poke - Update instructions on a live kernel
++ * @addr: address to modify
++ * @opcode: source of the copy
++ * @len: length to copy
++ *
++ * Only atomic text poke/set should be allowed when not doing early patching.
++ * It means the size must be writable atomically and the address must be aligned
++ * in a way that permits an atomic write. It also makes sure we fit on a single
++ * page.
++ */
++void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
++{
++	unsigned long flags;
++	char *vaddr;
++	int nr_pages = 2;
++	struct page *pages[2];
++	int i;
++
++	if (!core_kernel_text((unsigned long)addr)) {
++		pages[0] = vmalloc_to_page(addr);
++		pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
++	} else {
++		pages[0] = virt_to_page(addr);
++		WARN_ON(!PageReserved(pages[0]));
++		pages[1] = virt_to_page(addr + PAGE_SIZE);
++	}
++	BUG_ON(!pages[0]);
++	if (!pages[1])
++		nr_pages = 1;
++	vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
++	BUG_ON(!vaddr);
++	local_irq_save(flags);
++	memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
++	local_irq_restore(flags);
++	vunmap(vaddr);
+ 	sync_core();
+ 	/* Could also do a CLFLUSH here to speed up CPU recovery; but
+ 	   that causes hangs on some VIA CPUs. */
++	for (i = 0; i < len; i++)
++		BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
++	return addr;
+ }
+diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
+index 00df126..479926d 100644
+--- a/arch/x86/kernel/aperture_64.c
++++ b/arch/x86/kernel/aperture_64.c
+@@ -27,11 +27,11 @@
+ #include <asm/k8.h>
+ 
+ int gart_iommu_aperture;
+-int gart_iommu_aperture_disabled __initdata = 0;
+-int gart_iommu_aperture_allowed __initdata = 0;
++int gart_iommu_aperture_disabled __initdata;
++int gart_iommu_aperture_allowed __initdata;
+ 
+ int fallback_aper_order __initdata = 1; /* 64MB */
+-int fallback_aper_force __initdata = 0;
++int fallback_aper_force __initdata;
+ 
+ int fix_aperture __initdata = 1;
+ 
+diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
+index 35a568e..4b99b1b 100644
+--- a/arch/x86/kernel/apic_32.c
++++ b/arch/x86/kernel/apic_32.c
+@@ -50,6 +50,11 @@
+ # error SPURIOUS_APIC_VECTOR definition error
+ #endif
+ 
++unsigned long mp_lapic_addr;
++
++DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
++
+ /*
+  * Knob to control our willingness to enable the local APIC.
+  *
+@@ -446,7 +451,8 @@ void __init setup_boot_APIC_clock(void)
+ 	}
+ 
+ 	/* Calculate the scaled math multiplication factor */
+-	lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, 32);
++	lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS,
++				       lapic_clockevent.shift);
+ 	lapic_clockevent.max_delta_ns =
+ 		clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+ 	lapic_clockevent.min_delta_ns =
+@@ -621,6 +627,35 @@ int setup_profiling_timer(unsigned int multiplier)
+ }
+ 
+ /*
++ * Setup extended LVT, AMD specific (K8, family 10h)
++ *
++ * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
++ * MCE interrupts are supported. Thus MCE offset must be set to 0.
++ */
++
++#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)
++{
++	unsigned long reg = (lvt_off << 4) + APIC_EILVT0;
++	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
++	apic_write(reg, v);
++}
++
++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;
++}
++
++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;
++}
++
++/*
+  * Local APIC start and shutdown
+  */
+ 
+@@ -868,12 +903,50 @@ void __init init_bsp_APIC(void)
+ 	apic_write_around(APIC_LVT1, value);
+ }
+ 
++static void __cpuinit lapic_setup_esr(void)
++{
++	unsigned long oldvalue, value, maxlvt;
++	if (lapic_is_integrated() && !esr_disable) {
++		/* !82489DX */
++		maxlvt = lapic_get_maxlvt();
++		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
++			apic_write(APIC_ESR, 0);
++		oldvalue = apic_read(APIC_ESR);
++
++		/* enables sending errors */
++		value = ERROR_APIC_VECTOR;
++		apic_write_around(APIC_LVTERR, value);
++		/*
++		 * spec says clear errors after enabling vector.
++		 */
++		if (maxlvt > 3)
++			apic_write(APIC_ESR, 0);
++		value = apic_read(APIC_ESR);
++		if (value != oldvalue)
++			apic_printk(APIC_VERBOSE, "ESR value before enabling "
++				"vector: 0x%08lx  after: 0x%08lx\n",
++				oldvalue, value);
++	} else {
++		if (esr_disable)
++			/*
++			 * Something untraceable is creating bad interrupts on
++			 * secondary quads ... for the moment, just leave the
++			 * ESR disabled - we can't do anything useful with the
++			 * errors anyway - mbligh
++			 */
++			printk(KERN_INFO "Leaving ESR disabled.\n");
++		else
++			printk(KERN_INFO "No ESR for 82489DX.\n");
++	}
++}
++
++
+ /**
+  * setup_local_APIC - setup the local APIC
+  */
+ void __cpuinit setup_local_APIC(void)
+ {
+-	unsigned long oldvalue, value, maxlvt, integrated;
++	unsigned long value, integrated;
+ 	int i, j;
+ 
+ 	/* Pound the ESR really hard over the head with a big hammer - mbligh */
+@@ -997,40 +1070,13 @@ void __cpuinit setup_local_APIC(void)
+ 	if (!integrated)		/* 82489DX */
+ 		value |= APIC_LVT_LEVEL_TRIGGER;
+ 	apic_write_around(APIC_LVT1, value);
++}
+ 
+-	if (integrated && !esr_disable) {
+-		/* !82489DX */
+-		maxlvt = lapic_get_maxlvt();
+-		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
+-			apic_write(APIC_ESR, 0);
+-		oldvalue = apic_read(APIC_ESR);
+-
+-		/* enables sending errors */
+-		value = ERROR_APIC_VECTOR;
+-		apic_write_around(APIC_LVTERR, value);
+-		/*
+-		 * spec says clear errors after enabling vector.
+-		 */
+-		if (maxlvt > 3)
+-			apic_write(APIC_ESR, 0);
+-		value = apic_read(APIC_ESR);
+-		if (value != oldvalue)
+-			apic_printk(APIC_VERBOSE, "ESR value before enabling "
+-				"vector: 0x%08lx  after: 0x%08lx\n",
+-				oldvalue, value);
+-	} else {
+-		if (esr_disable)
+-			/*
+-			 * Something untraceable is creating bad interrupts on
+-			 * secondary quads ... for the moment, just leave the
+-			 * ESR disabled - we can't do anything useful with the
+-			 * errors anyway - mbligh
+-			 */
+-			printk(KERN_INFO "Leaving ESR disabled.\n");
+-		else
+-			printk(KERN_INFO "No ESR for 82489DX.\n");
+-	}
++void __cpuinit end_local_APIC_setup(void)
++{
++	unsigned long value;
+ 
++	lapic_setup_esr();
+ 	/* Disable the local apic timer */
+ 	value = apic_read(APIC_LVTT);
+ 	value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+@@ -1147,7 +1193,7 @@ void __init init_apic_mappings(void)
+ 	 * default configuration (or the MP table is broken).
+ 	 */
+ 	if (boot_cpu_physical_apicid == -1U)
+-		boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
++		boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+ 
+ #ifdef CONFIG_X86_IO_APIC
+ 	{
+@@ -1185,6 +1231,9 @@ fake_ioapic_page:
+  * This initializes the IO-APIC and APIC hardware if this is
+  * a UP kernel.
+  */
++
++int apic_version[MAX_APICS];
++
+ int __init APIC_init_uniprocessor(void)
+ {
+ 	if (enable_local_apic < 0)
+@@ -1214,12 +1263,13 @@ int __init APIC_init_uniprocessor(void)
+ 	 * might be zero if read from MP tables. Get it from LAPIC.
+ 	 */
+ #ifdef CONFIG_CRASH_DUMP
+-	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
++	boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+ #endif
+ 	phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
+ 
+ 	setup_local_APIC();
+ 
++	end_local_APIC_setup();
+ #ifdef CONFIG_X86_IO_APIC
+ 	if (smp_found_config)
+ 		if (!skip_ioapic_setup && nr_ioapics)
+@@ -1288,6 +1338,29 @@ void smp_error_interrupt(struct pt_regs *regs)
+ 	irq_exit();
+ }
+ 
++#ifdef CONFIG_SMP
++void __init smp_intr_init(void)
++{
++	/*
++	 * IRQ0 must be given a fixed assignment and initialized,
++	 * because it's used before the IO-APIC is set up.
++	 */
++	set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
++
++	/*
++	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
++	 * IPI, driven by wakeup.
++	 */
++	set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
++
++	/* IPI for invalidation */
++	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
++
++	/* IPI for generic function call */
++	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
++}
++#endif
++
+ /*
+  * Initialize APIC interrupts
+  */
+@@ -1394,6 +1467,88 @@ void disconnect_bsp_APIC(int virt_wire_setup)
+ 	}
+ }
+ 
++unsigned int __cpuinitdata maxcpus = NR_CPUS;
++
++void __cpuinit generic_processor_info(int apicid, int version)
++{
++	int cpu;
++	cpumask_t tmp_map;
++	physid_mask_t phys_cpu;
++
++	/*
++	 * Validate version
++	 */
++	if (version == 0x0) {
++		printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! "
++				"fixing up to 0x10. (tell your hw vendor)\n",
++				version);
++		version = 0x10;
++	}
++	apic_version[apicid] = version;
++
++	phys_cpu = apicid_to_cpu_present(apicid);
++	physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
++
++	if (num_processors >= NR_CPUS) {
++		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
++			"  Processor ignored.\n", NR_CPUS);
++		return;
++	}
++
++	if (num_processors >= maxcpus) {
++		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
++			" Processor ignored.\n", maxcpus);
++		return;
++	}
++
++	num_processors++;
++	cpus_complement(tmp_map, cpu_present_map);
++	cpu = first_cpu(tmp_map);
++
++	if (apicid == boot_cpu_physical_apicid)
++		/*
++		 * x86_bios_cpu_apicid is required to have processors listed
++		 * in same order as logical cpu numbers. Hence the first
++		 * entry is BSP, and so on.
++		 */
++		cpu = 0;
++
++	/*
++	 * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
++	 * but we need to work other dependencies like SMP_SUSPEND etc
++	 * before this can be done without some confusion.
++	 * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
++	 *       - Ashok Raj <ashok.raj at intel.com>
++	 */
++	if (num_processors > 8) {
++		switch (boot_cpu_data.x86_vendor) {
++		case X86_VENDOR_INTEL:
++			if (!APIC_XAPIC(version)) {
++				def_to_bigsmp = 0;
++				break;
++			}
++			/* If P4 and above fall through */
++		case X86_VENDOR_AMD:
++			def_to_bigsmp = 1;
++		}
++	}
++#ifdef CONFIG_SMP
++	/* are we being called early in kernel startup? */
++	if (x86_cpu_to_apicid_early_ptr) {
++		u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
++		u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
++
++		cpu_to_apicid[cpu] = apicid;
++		bios_cpu_apicid[cpu] = apicid;
++	} else {
++		per_cpu(x86_cpu_to_apicid, cpu) = apicid;
++		per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
++	}
++#endif
++	cpu_set(cpu, cpu_possible_map);
++	cpu_set(cpu, cpu_present_map);
++}
++
+ /*
+  * Power management
+  */
+diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
+index d8d03e0..5910020 100644
+--- a/arch/x86/kernel/apic_64.c
++++ b/arch/x86/kernel/apic_64.c
+@@ -34,13 +34,15 @@
+ #include <asm/mpspec.h>
+ #include <asm/hpet.h>
+ #include <asm/pgalloc.h>
+-#include <asm/mach_apic.h>
+ #include <asm/nmi.h>
+ #include <asm/idle.h>
+ #include <asm/proto.h>
+ #include <asm/timex.h>
+ #include <asm/apic.h>
+ 
++#include <mach_ipi.h>
++#include <mach_apic.h>
++
+ int disable_apic_timer __cpuinitdata;
+ static int apic_calibrate_pmtmr __initdata;
+ int disable_apic;
+@@ -83,6 +85,12 @@ static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
+ 
+ static unsigned long apic_phys;
+ 
++unsigned long mp_lapic_addr;
++
++DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
++
++unsigned int __cpuinitdata maxcpus = NR_CPUS;
+ /*
+  * Get the LAPIC version
+  */
+@@ -352,7 +360,8 @@ static void __init calibrate_APIC_clock(void)
+ 		result / 1000 / 1000, result / 1000 % 1000);
+ 
+ 	/* Calculate the scaled math multiplication factor */
+-	lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32);
++	lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC,
++				       lapic_clockevent.shift);
+ 	lapic_clockevent.max_delta_ns =
+ 		clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+ 	lapic_clockevent.min_delta_ns =
+@@ -421,7 +430,7 @@ void __init setup_boot_APIC_clock(void)
+  * set the DUMMY flag again and force the broadcast mode in the
+  * clockevents layer.
+  */
+-void __cpuinit check_boot_apic_timer_broadcast(void)
++static void __cpuinit check_boot_apic_timer_broadcast(void)
+ {
+ 	if (!disable_apic_timer ||
+ 	    (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY))
+@@ -431,7 +440,8 @@ void __cpuinit check_boot_apic_timer_broadcast(void)
+ 	lapic_clockevent.features |= CLOCK_EVT_FEAT_DUMMY;
+ 
+ 	local_irq_enable();
+-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, &boot_cpu_id);
++	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
++			   &boot_cpu_physical_apicid);
+ 	local_irq_disable();
+ }
+ 
+@@ -640,10 +650,10 @@ int __init verify_local_APIC(void)
+ 	/*
+ 	 * The ID register is read/write in a real APIC.
+ 	 */
+-	reg0 = apic_read(APIC_ID);
++	reg0 = read_apic_id();
+ 	apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
+ 	apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
+-	reg1 = apic_read(APIC_ID);
++	reg1 = read_apic_id();
+ 	apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
+ 	apic_write(APIC_ID, reg0);
+ 	if (reg1 != (reg0 ^ APIC_ID_MASK))
+@@ -728,6 +738,7 @@ void __cpuinit setup_local_APIC(void)
+ 	unsigned int value;
+ 	int i, j;
+ 
++	preempt_disable();
+ 	value = apic_read(APIC_LVR);
+ 
+ 	BUILD_BUG_ON((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f);
+@@ -821,9 +832,10 @@ void __cpuinit setup_local_APIC(void)
+ 	else
+ 		value = APIC_DM_NMI | APIC_LVT_MASKED;
+ 	apic_write(APIC_LVT1, value);
++	preempt_enable();
+ }
+ 
+-void __cpuinit lapic_setup_esr(void)
++static void __cpuinit lapic_setup_esr(void)
+ {
+ 	unsigned maxlvt = lapic_get_maxlvt();
+ 
+@@ -857,10 +869,34 @@ static int __init detect_init_APIC(void)
+ 	}
+ 
+ 	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+-	boot_cpu_id = 0;
++	boot_cpu_physical_apicid = 0;
+ 	return 0;
+ }
+ 
++void __init early_init_lapic_mapping(void)
++{
++	unsigned long apic_phys;
++
++	/*
++	 * If no local APIC can be found then go out
++	 * : it means there is no mpatable and MADT
++	 */
++	if (!smp_found_config)
++		return;
++
++	apic_phys = mp_lapic_addr;
++
++	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
++	apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
++				 APIC_BASE, apic_phys);
++
++	/*
++	 * Fetch the APIC ID of the BSP in case we have a
++	 * default configuration (or the MP table is broken).
++	 */
++	boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
++}
++
+ /**
+  * init_apic_mappings - initialize APIC mappings
+  */
+@@ -881,16 +917,11 @@ void __init init_apic_mappings(void)
+ 	apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
+ 				APIC_BASE, apic_phys);
+ 
+-	/* Put local APIC into the resource map. */
+-	lapic_resource.start = apic_phys;
+-	lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1;
+-	insert_resource(&iomem_resource, &lapic_resource);
+-
+ 	/*
+ 	 * Fetch the APIC ID of the BSP in case we have a
+ 	 * default configuration (or the MP table is broken).
+ 	 */
+-	boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
++	boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+ }
+ 
+ /*
+@@ -911,8 +942,8 @@ int __init APIC_init_uniprocessor(void)
+ 
+ 	verify_local_APIC();
+ 
+-	phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
+-	apic_write(APIC_ID, SET_APIC_ID(boot_cpu_id));
++	phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
++	apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid));
+ 
+ 	setup_local_APIC();
+ 
+@@ -1029,6 +1060,52 @@ void disconnect_bsp_APIC(int virt_wire_setup)
+ 	apic_write(APIC_LVT1, value);
+ }
+ 
++void __cpuinit generic_processor_info(int apicid, int version)
++{
++	int cpu;
++	cpumask_t tmp_map;
++
++	if (num_processors >= NR_CPUS) {
++		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
++		       " Processor ignored.\n", NR_CPUS);
++		return;
++	}
++
++	if (num_processors >= maxcpus) {
++		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
++		       " Processor ignored.\n", maxcpus);
++		return;
++	}
++
++	num_processors++;
++	cpus_complement(tmp_map, cpu_present_map);
++	cpu = first_cpu(tmp_map);
++
++	physid_set(apicid, phys_cpu_present_map);
++	if (apicid == boot_cpu_physical_apicid) {
++		/*
++		 * x86_bios_cpu_apicid is required to have processors listed
++		 * in same order as logical cpu numbers. Hence the first
++		 * entry is BSP, and so on.
++		 */
++		cpu = 0;
++	}
++	/* are we being called early in kernel startup? */
++	if (x86_cpu_to_apicid_early_ptr) {
++		u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
++		u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
++
++		cpu_to_apicid[cpu] = apicid;
++		bios_cpu_apicid[cpu] = apicid;
++	} else {
++		per_cpu(x86_cpu_to_apicid, cpu) = apicid;
++		per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
++	}
++
++	cpu_set(cpu, cpu_possible_map);
++	cpu_set(cpu, cpu_present_map);
++}
++
+ /*
+  * Power management
+  */
+@@ -1065,7 +1142,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
+ 
+ 	maxlvt = lapic_get_maxlvt();
+ 
+-	apic_pm_state.apic_id = apic_read(APIC_ID);
++	apic_pm_state.apic_id = read_apic_id();
+ 	apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
+ 	apic_pm_state.apic_ldr = apic_read(APIC_LDR);
+ 	apic_pm_state.apic_dfr = apic_read(APIC_DFR);
+@@ -1180,9 +1257,19 @@ __cpuinit int apic_is_clustered_box(void)
+ {
+ 	int i, clusters, zeros;
+ 	unsigned id;
+-	u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
++	u16 *bios_cpu_apicid;
+ 	DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
+ 
++	/*
++	 * there is not this kind of box with AMD CPU yet.
++	 * Some AMD box with quadcore cpu and 8 sockets apicid
++	 * will be [4, 0x23] or [8, 0x27] could be thought to
++	 * vsmp box still need checking...
++	 */
++	if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box())
++		return 0;
++
++	bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
+ 	bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
+ 
+ 	for (i = 0; i < NR_CPUS; i++) {
+@@ -1219,6 +1306,12 @@ __cpuinit int apic_is_clustered_box(void)
+ 			++zeros;
+ 	}
+ 
++	/* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
++	 * not guaranteed to be synced between boards
++	 */
++	if (is_vsmp_box() && clusters > 1)
++		return 1;
++
+ 	/*
+ 	 * If clusters > 2, then should be multi-chassis.
+ 	 * May have to revisit this when multi-core + hyperthreaded CPUs come
+@@ -1290,3 +1383,21 @@ static __init int setup_apicpmtimer(char *s)
+ }
+ __setup("apicpmtimer", setup_apicpmtimer);
+ 
++static int __init lapic_insert_resource(void)
++{
++	if (!apic_phys)
++		return -1;
++
++	/* Put local APIC into the resource map. */
++	lapic_resource.start = apic_phys;
++	lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1;
++	insert_resource(&iomem_resource, &lapic_resource);
++
++	return 0;
++}
++
++/*
++ * need call insert after e820_reserve_resources()
++ * that is using request_resource
++ */
++late_initcall(lapic_insert_resource);
+diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
+index d4438ef..f0030a0 100644
+--- a/arch/x86/kernel/apm_32.c
++++ b/arch/x86/kernel/apm_32.c
+@@ -2217,7 +2217,6 @@ static struct dmi_system_id __initdata apm_dmi_table[] = {
+  */
+ static int __init apm_init(void)
+ {
+-	struct proc_dir_entry *apm_proc;
+ 	struct desc_struct *gdt;
+ 	int err;
+ 
+@@ -2322,9 +2321,7 @@ static int __init apm_init(void)
+ 	set_base(gdt[APM_DS >> 3],
+ 		 __va((unsigned long)apm_info.bios.dseg << 4));
+ 
+-	apm_proc = create_proc_entry("apm", 0, NULL);
+-	if (apm_proc)
+-		apm_proc->proc_fops = &apm_file_ops;
++	proc_create("apm", 0, NULL, &apm_file_ops);
+ 
+ 	kapmd_task = kthread_create(apm, NULL, "kapmd");
+ 	if (IS_ERR(kapmd_task)) {
+diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
+index 8ea0401..670c3c3 100644
+--- a/arch/x86/kernel/asm-offsets_32.c
++++ b/arch/x86/kernel/asm-offsets_32.c
+@@ -10,7 +10,7 @@
+ #include <linux/personality.h>
+ #include <linux/suspend.h>
+ #include <asm/ucontext.h>
+-#include "sigframe_32.h"
++#include "sigframe.h"
+ #include <asm/pgtable.h>
+ #include <asm/fixmap.h>
+ #include <asm/processor.h>
+diff --git a/arch/x86/kernel/bugs_64.c b/arch/x86/kernel/bugs_64.c
+index 8f520f9..9a3ed06 100644
+--- a/arch/x86/kernel/bugs_64.c
++++ b/arch/x86/kernel/bugs_64.c
+@@ -9,13 +9,25 @@
+ #include <asm/bugs.h>
+ #include <asm/processor.h>
+ #include <asm/mtrr.h>
++#include <asm/cacheflush.h>
+ 
+ void __init check_bugs(void)
+ {
+-	identify_cpu(&boot_cpu_data);
++	identify_boot_cpu();
+ #if !defined(CONFIG_SMP)
+ 	printk("CPU: ");
+ 	print_cpu_info(&boot_cpu_data);
+ #endif
+ 	alternative_instructions();
++
++	/*
++	 * Make sure the first 2MB area is not mapped by huge pages
++	 * There are typically fixed size MTRRs in there and overlapping
++	 * MTRRs into large pages causes slow downs.
++	 *
++	 * Right now we don't do that with gbpages because there seems
++	 * very little benefit for that case.
++	 */
++	if (!direct_gbpages)
++		set_memory_4k((unsigned long)__va(0), 1);
+ }
+diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
+index a0c4d7c..a0c6f81 100644
+--- a/arch/x86/kernel/cpu/Makefile
++++ b/arch/x86/kernel/cpu/Makefile
+@@ -3,15 +3,14 @@
+ #
+ 
+ obj-y			:= intel_cacheinfo.o addon_cpuid_features.o
+-obj-y			+= feature_names.o
++obj-y			+= proc.o feature_names.o
+ 
+-obj-$(CONFIG_X86_32)	+= common.o proc.o bugs.o
++obj-$(CONFIG_X86_32)	+= common.o bugs.o
+ obj-$(CONFIG_X86_32)	+= amd.o
+ obj-$(CONFIG_X86_32)	+= cyrix.o
+ obj-$(CONFIG_X86_32)	+= centaur.o
+ obj-$(CONFIG_X86_32)	+= transmeta.o
+ obj-$(CONFIG_X86_32)	+= intel.o
+-obj-$(CONFIG_X86_32)	+= nexgen.o
+ obj-$(CONFIG_X86_32)	+= umc.o
+ 
+ obj-$(CONFIG_X86_MCE)	+= mcheck/
+diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
+index 693e353..2458668 100644
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -4,8 +4,8 @@
+ #include <asm/io.h>
+ #include <asm/processor.h>
+ #include <asm/apic.h>
+-#include <asm/mach_apic.h>
+ 
++#include <mach_apic.h>
+ #include "cpu.h"
+ 
+ /*
+@@ -20,7 +20,7 @@
+  *	the chip setting when fixing the bug but they also tweaked some
+  *	performance at the same time..
+  */
+- 
++
+ extern void vide(void);
+ __asm__(".align 4\nvide: ret");
+ 
+@@ -63,12 +63,12 @@ static __cpuinit int amd_apic_timer_broken(void)
+ 
+ int force_mwait __cpuinitdata;
+ 
+-void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
++static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
+ {
+ 	if (cpuid_eax(0x80000000) >= 0x80000007) {
+ 		c->x86_power = cpuid_edx(0x80000007);
+ 		if (c->x86_power & (1<<8))
+-			set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
++			set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ 	}
+ }
+ 
+@@ -81,7 +81,8 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ #ifdef CONFIG_SMP
+ 	unsigned long long value;
+ 
+-	/* Disable TLB flush filter by setting HWCR.FFDIS on K8
++	/*
++	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
+ 	 * bit 6 of msr C001_0015
+ 	 *
+ 	 * Errata 63 for SH-B3 steppings
+@@ -102,15 +103,16 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ 	 *	no bus pipeline)
+ 	 */
+ 
+-	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+-	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+-	clear_bit(0*32+31, c->x86_capability);
+-	
++	/*
++	 * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
++	 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
++	 */
++	clear_cpu_cap(c, 0*32+31);
++
+ 	r = get_model_name(c);
+ 
+-	switch(c->x86)
+-	{
+-		case 4:
++	switch (c->x86) {
++	case 4:
+ 		/*
+ 		 * General Systems BIOSen alias the cpu frequency registers
+ 		 * of the Elan at 0x000df000. Unfortuantly, one of the Linux
+@@ -120,61 +122,60 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ #define CBAR		(0xfffc) /* Configuration Base Address  (32-bit) */
+ #define CBAR_ENB	(0x80000000)
+ #define CBAR_KEY	(0X000000CB)
+-			if (c->x86_model==9 || c->x86_model == 10) {
++			if (c->x86_model == 9 || c->x86_model == 10) {
+ 				if (inl (CBAR) & CBAR_ENB)
+ 					outl (0 | CBAR_KEY, CBAR);
+ 			}
+ 			break;
+-		case 5:
+-			if( c->x86_model < 6 )
+-			{
++	case 5:
++			if (c->x86_model < 6) {
+ 				/* Based on AMD doc 20734R - June 2000 */
+-				if ( c->x86_model == 0 ) {
+-					clear_bit(X86_FEATURE_APIC, c->x86_capability);
+-					set_bit(X86_FEATURE_PGE, c->x86_capability);
++				if (c->x86_model == 0) {
++					clear_cpu_cap(c, X86_FEATURE_APIC);
++					set_cpu_cap(c, X86_FEATURE_PGE);
+ 				}
+ 				break;
+ 			}
+-			
+-			if ( c->x86_model == 6 && c->x86_mask == 1 ) {
++
++			if (c->x86_model == 6 && c->x86_mask == 1) {
+ 				const int K6_BUG_LOOP = 1000000;
+ 				int n;
+ 				void (*f_vide)(void);
+ 				unsigned long d, d2;
+-				
++
+ 				printk(KERN_INFO "AMD K6 stepping B detected - ");
+-				
++
+ 				/*
+-				 * It looks like AMD fixed the 2.6.2 bug and improved indirect 
++				 * It looks like AMD fixed the 2.6.2 bug and improved indirect
+ 				 * calls at the same time.
+ 				 */
+ 
+ 				n = K6_BUG_LOOP;
+ 				f_vide = vide;
+ 				rdtscl(d);
+-				while (n--) 
++				while (n--)
+ 					f_vide();
+ 				rdtscl(d2);
+ 				d = d2-d;
+ 
+-				if (d > 20*K6_BUG_LOOP) 
++				if (d > 20*K6_BUG_LOOP)
+ 					printk("system stability may be impaired when more than 32 MB are used.\n");
+-				else 
++				else
+ 					printk("probably OK (after B9730xxxx).\n");
+ 				printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n");
+ 			}
+ 
+ 			/* K6 with old style WHCR */
+ 			if (c->x86_model < 8 ||
+-			   (c->x86_model== 8 && c->x86_mask < 8)) {
++			   (c->x86_model == 8 && c->x86_mask < 8)) {
+ 				/* We can only write allocate on the low 508Mb */
+-				if(mbytes>508)
+-					mbytes=508;
++				if (mbytes > 508)
++					mbytes = 508;
+ 
+ 				rdmsr(MSR_K6_WHCR, l, h);
+-				if ((l&0x0000FFFF)==0) {
++				if ((l&0x0000FFFF) == 0) {
+ 					unsigned long flags;
+-					l=(1<<0)|((mbytes/4)<<1);
++					l = (1<<0)|((mbytes/4)<<1);
+ 					local_irq_save(flags);
+ 					wbinvd();
+ 					wrmsr(MSR_K6_WHCR, l, h);
+@@ -185,17 +186,17 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ 				break;
+ 			}
+ 
+-			if ((c->x86_model == 8 && c->x86_mask >7) ||
++			if ((c->x86_model == 8 && c->x86_mask > 7) ||
+ 			     c->x86_model == 9 || c->x86_model == 13) {
+ 				/* The more serious chips .. */
+ 
+-				if(mbytes>4092)
+-					mbytes=4092;
++				if (mbytes > 4092)
++					mbytes = 4092;
+ 
+ 				rdmsr(MSR_K6_WHCR, l, h);
+-				if ((l&0xFFFF0000)==0) {
++				if ((l&0xFFFF0000) == 0) {
+ 					unsigned long flags;
+-					l=((mbytes>>2)<<22)|(1<<16);
++					l = ((mbytes>>2)<<22)|(1<<16);
+ 					local_irq_save(flags);
+ 					wbinvd();
+ 					wrmsr(MSR_K6_WHCR, l, h);
+@@ -207,7 +208,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ 				/*  Set MTRR capability flag if appropriate */
+ 				if (c->x86_model == 13 || c->x86_model == 9 ||
+ 				   (c->x86_model == 8 && c->x86_mask >= 8))
+-					set_bit(X86_FEATURE_K6_MTRR, c->x86_capability);
++					set_cpu_cap(c, X86_FEATURE_K6_MTRR);
+ 				break;
+ 			}
+ 
+@@ -217,10 +218,11 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ 				break;
+ 			}
+ 			break;
+-		case 6: /* An Athlon/Duron */
+- 
+-			/* Bit 15 of Athlon specific MSR 15, needs to be 0
+- 			 * to enable SSE on Palomino/Morgan/Barton CPU's.
++	case 6: /* An Athlon/Duron */
++
++			/*
++			 * Bit 15 of Athlon specific MSR 15, needs to be 0
++			 * to enable SSE on Palomino/Morgan/Barton CPU's.
+ 			 * If the BIOS didn't enable it already, enable it here.
+ 			 */
+ 			if (c->x86_model >= 6 && c->x86_model <= 10) {
+@@ -229,15 +231,16 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ 					rdmsr(MSR_K7_HWCR, l, h);
+ 					l &= ~0x00008000;
+ 					wrmsr(MSR_K7_HWCR, l, h);
+-					set_bit(X86_FEATURE_XMM, c->x86_capability);
++					set_cpu_cap(c, X86_FEATURE_XMM);
+ 				}
+ 			}
+ 
+-			/* It's been determined by AMD that Athlons since model 8 stepping 1
++			/*
++			 * It's been determined by AMD that Athlons since model 8 stepping 1
+ 			 * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
+ 			 * As per AMD technical note 27212 0.2
+ 			 */
+-			if ((c->x86_model == 8 && c->x86_mask>=1) || (c->x86_model > 8)) {
++			if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
+ 				rdmsr(MSR_K7_CLK_CTL, l, h);
+ 				if ((l & 0xfff00000) != 0x20000000) {
+ 					printk ("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", l,
+@@ -253,20 +256,19 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ 	/* Use K8 tuning for Fam10h and Fam11h */
+ 	case 0x10:
+ 	case 0x11:
+-		set_bit(X86_FEATURE_K8, c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_K8);
+ 		break;
+ 	case 6:
+-		set_bit(X86_FEATURE_K7, c->x86_capability); 
++		set_cpu_cap(c, X86_FEATURE_K7);
+ 		break;
+ 	}
+ 	if (c->x86 >= 6)
+-		set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
+ 
+ 	display_cacheinfo(c);
+ 
+-	if (cpuid_eax(0x80000000) >= 0x80000008) {
++	if (cpuid_eax(0x80000000) >= 0x80000008)
+ 		c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+-	}
+ 
+ #ifdef CONFIG_X86_HT
+ 	/*
+@@ -302,20 +304,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ 
+ 	/* K6s reports MCEs but don't actually have all the MSRs */
+ 	if (c->x86 < 6)
+-		clear_bit(X86_FEATURE_MCE, c->x86_capability);
++		clear_cpu_cap(c, X86_FEATURE_MCE);
+ 
+ 	if (cpu_has_xmm2)
+-		set_bit(X86_FEATURE_MFENCE_RDTSC, c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
+ }
+ 
+-static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
++static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size)
+ {
+ 	/* AMD errata T13 (order #21922) */
+ 	if ((c->x86 == 6)) {
+ 		if (c->x86_model == 3 && c->x86_mask == 0)	/* Duron Rev A0 */
+ 			size = 64;
+ 		if (c->x86_model == 4 &&
+-		    (c->x86_mask==0 || c->x86_mask==1))	/* Tbird rev A1/A2 */
++		    (c->x86_mask == 0 || c->x86_mask == 1))	/* Tbird rev A1/A2 */
+ 			size = 256;
+ 	}
+ 	return size;
+@@ -323,25 +325,22 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned in
+ 
+ static struct cpu_dev amd_cpu_dev __cpuinitdata = {
+ 	.c_vendor	= "AMD",
+-	.c_ident 	= { "AuthenticAMD" },
++	.c_ident	= { "AuthenticAMD" },
+ 	.c_models = {
+ 		{ .vendor = X86_VENDOR_AMD, .family = 4, .model_names =
+ 		  {
+ 			  [3] = "486 DX/2",
+ 			  [7] = "486 DX/2-WB",
+-			  [8] = "486 DX/4", 
+-			  [9] = "486 DX/4-WB", 
++			  [8] = "486 DX/4",
++			  [9] = "486 DX/4-WB",
+ 			  [14] = "Am5x86-WT",
+-			  [15] = "Am5x86-WB" 
++			  [15] = "Am5x86-WB"
+ 		  }
+ 		},
+ 	},
++	.c_early_init   = early_init_amd,
+ 	.c_init		= init_amd,
+ 	.c_size_cache	= amd_size_cache,
+ };
+ 
+-int __init amd_init_cpu(void)
+-{
+-	cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev;
+-	return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_AMD, &amd_cpu_dev);
+diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
+index 9681fa1..e0f45ed 100644
+--- a/arch/x86/kernel/cpu/centaur.c
++++ b/arch/x86/kernel/cpu/centaur.c
+@@ -1,31 +1,34 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/bitops.h>
++
+ #include <asm/processor.h>
+ #include <asm/msr.h>
+ #include <asm/e820.h>
+ #include <asm/mtrr.h>
++
+ #include "cpu.h"
+ 
+ #ifdef CONFIG_X86_OOSTORE
+ 
+ static u32 __cpuinit power2(u32 x)
+ {
+-	u32 s=1;
+-	while(s<=x)
+-		s<<=1;
+-	return s>>=1;
++	u32 s = 1;
++
++	while (s <= x)
++		s <<= 1;
++
++	return s >>= 1;
+ }
+ 
+ 
+ /*
+- *	Set up an actual MCR
++ * Set up an actual MCR
+  */
+- 
+ static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key)
+ {
+ 	u32 lo, hi;
+-	
++
+ 	hi = base & ~0xFFF;
+ 	lo = ~(size-1);		/* Size is a power of 2 so this makes a mask */
+ 	lo &= ~0xFFF;		/* Remove the ctrl value bits */
+@@ -35,30 +38,28 @@ static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key)
+ }
+ 
+ /*
+- *	Figure what we can cover with MCR's
++ * Figure what we can cover with MCR's
+  *
+- *	Shortcut: We know you can't put 4Gig of RAM on a winchip
++ * Shortcut: We know you can't put 4Gig of RAM on a winchip
+  */
+-
+-static u32 __cpuinit ramtop(void)		/* 16388 */
++static u32 __cpuinit ramtop(void)
+ {
+-	int i;
+-	u32 top = 0;
+ 	u32 clip = 0xFFFFFFFFUL;
+-	
++	u32 top = 0;
++	int i;
++
+ 	for (i = 0; i < e820.nr_map; i++) {
+ 		unsigned long start, end;
+ 
+ 		if (e820.map[i].addr > 0xFFFFFFFFUL)
+ 			continue;
+ 		/*
+-		 *	Don't MCR over reserved space. Ignore the ISA hole
+-		 *	we frob around that catastrophe already
++		 * Don't MCR over reserved space. Ignore the ISA hole
++		 * we frob around that catastrophe already
+ 		 */
+-		 			
+-		if (e820.map[i].type == E820_RESERVED)
+-		{
+-			if(e820.map[i].addr >= 0x100000UL && e820.map[i].addr < clip)
++		if (e820.map[i].type == E820_RESERVED) {
++			if (e820.map[i].addr >= 0x100000UL &&
++			    e820.map[i].addr < clip)
+ 				clip = e820.map[i].addr;
+ 			continue;
+ 		}
+@@ -69,28 +70,27 @@ static u32 __cpuinit ramtop(void)		/* 16388 */
+ 		if (end > top)
+ 			top = end;
+ 	}
+-	/* Everything below 'top' should be RAM except for the ISA hole.
+-	   Because of the limited MCR's we want to map NV/ACPI into our
+-	   MCR range for gunk in RAM 
+-	   
+-	   Clip might cause us to MCR insufficient RAM but that is an
+-	   acceptable failure mode and should only bite obscure boxes with
+-	   a VESA hole at 15Mb
+-	   
+-	   The second case Clip sometimes kicks in is when the EBDA is marked
+-	   as reserved. Again we fail safe with reasonable results
+-	*/
+-	
+-	if(top>clip)
+-		top=clip;
+-		
++	/*
++	 * Everything below 'top' should be RAM except for the ISA hole.
++	 * Because of the limited MCR's we want to map NV/ACPI into our
++	 * MCR range for gunk in RAM
++	 *
++	 * Clip might cause us to MCR insufficient RAM but that is an
++	 * acceptable failure mode and should only bite obscure boxes with
++	 * a VESA hole at 15Mb
++	 *
++	 * The second case Clip sometimes kicks in is when the EBDA is marked
++	 * as reserved. Again we fail safe with reasonable results
++	 */
++	if (top > clip)
++		top = clip;
++
+ 	return top;
+ }
+ 
+ /*
+- *	Compute a set of MCR's to give maximum coverage
++ * Compute a set of MCR's to give maximum coverage
+  */
+-
+ static int __cpuinit centaur_mcr_compute(int nr, int key)
+ {
+ 	u32 mem = ramtop();
+@@ -99,141 +99,131 @@ static int __cpuinit centaur_mcr_compute(int nr, int key)
+ 	u32 top = root;
+ 	u32 floor = 0;
+ 	int ct = 0;
+-	
+-	while(ct<nr)
+-	{
++
++	while (ct < nr) {
+ 		u32 fspace = 0;
++		u32 high;
++		u32 low;
+ 
+ 		/*
+-		 *	Find the largest block we will fill going upwards
++		 * Find the largest block we will fill going upwards
+ 		 */
+-
+-		u32 high = power2(mem-top);	
++		high = power2(mem-top);
+ 
+ 		/*
+-		 *	Find the largest block we will fill going downwards
++		 * Find the largest block we will fill going downwards
+ 		 */
+-
+-		u32 low = base/2;
++		low = base/2;
+ 
+ 		/*
+-		 *	Don't fill below 1Mb going downwards as there
+-		 *	is an ISA hole in the way.
+-		 */		
+-		 
+-		if(base <= 1024*1024)
++		 * Don't fill below 1Mb going downwards as there
++		 * is an ISA hole in the way.
++		 */
++		if (base <= 1024*1024)
+ 			low = 0;
+-			
++
+ 		/*
+-		 *	See how much space we could cover by filling below
+-		 *	the ISA hole
++		 * See how much space we could cover by filling below
++		 * the ISA hole
+ 		 */
+-		 
+-		if(floor == 0)
++
++		if (floor == 0)
+ 			fspace = 512*1024;
+-		else if(floor ==512*1024)
++		else if (floor == 512*1024)
+ 			fspace = 128*1024;
+ 
+ 		/* And forget ROM space */
+-		
++
+ 		/*
+-		 *	Now install the largest coverage we get
++		 * Now install the largest coverage we get
+ 		 */
+-		 
+-		if(fspace > high && fspace > low)
+-		{
++		if (fspace > high && fspace > low) {
+ 			centaur_mcr_insert(ct, floor, fspace, key);
+ 			floor += fspace;
+-		}
+-		else if(high > low)
+-		{
++		} else if (high > low) {
+ 			centaur_mcr_insert(ct, top, high, key);
+ 			top += high;
+-		}
+-		else if(low > 0)
+-		{
++		} else if (low > 0) {
+ 			base -= low;
+ 			centaur_mcr_insert(ct, base, low, key);
+-		}
+-		else break;
++		} else
++			break;
+ 		ct++;
+ 	}
+ 	/*
+-	 *	We loaded ct values. We now need to set the mask. The caller
+-	 *	must do this bit.
++	 * We loaded ct values. We now need to set the mask. The caller
++	 * must do this bit.
+ 	 */
+-	 
+ 	return ct;
+ }
+ 
+ static void __cpuinit centaur_create_optimal_mcr(void)
+ {
++	int used;
+ 	int i;
++
+ 	/*
+-	 *	Allocate up to 6 mcrs to mark as much of ram as possible
+-	 *	as write combining and weak write ordered.
++	 * Allocate up to 6 mcrs to mark as much of ram as possible
++	 * as write combining and weak write ordered.
+ 	 *
+-	 *	To experiment with: Linux never uses stack operations for 
+-	 *	mmio spaces so we could globally enable stack operation wc
++	 * To experiment with: Linux never uses stack operations for
++	 * mmio spaces so we could globally enable stack operation wc
+ 	 *
+-	 *	Load the registers with type 31 - full write combining, all
+-	 *	writes weakly ordered.
++	 * Load the registers with type 31 - full write combining, all
++	 * writes weakly ordered.
+ 	 */
+-	int used = centaur_mcr_compute(6, 31);
++	used = centaur_mcr_compute(6, 31);
+ 
+ 	/*
+-	 *	Wipe unused MCRs
++	 * Wipe unused MCRs
+ 	 */
+-	 
+-	for(i=used;i<8;i++)
++	for (i = used; i < 8; i++)
+ 		wrmsr(MSR_IDT_MCR0+i, 0, 0);
+ }
+ 
+ static void __cpuinit winchip2_create_optimal_mcr(void)
+ {
+ 	u32 lo, hi;
++	int used;
+ 	int i;
+ 
+ 	/*
+-	 *	Allocate up to 6 mcrs to mark as much of ram as possible
+-	 *	as write combining, weak store ordered.
++	 * Allocate up to 6 mcrs to mark as much of ram as possible
++	 * as write combining, weak store ordered.
+ 	 *
+-	 *	Load the registers with type 25
+-	 *		8	-	weak write ordering
+-	 *		16	-	weak read ordering
+-	 *		1	-	write combining
++	 * Load the registers with type 25
++	 *	8	-	weak write ordering
++	 *	16	-	weak read ordering
++	 *	1	-	write combining
+ 	 */
++	used = centaur_mcr_compute(6, 25);
+ 
+-	int used = centaur_mcr_compute(6, 25);
+-	
+ 	/*
+-	 *	Mark the registers we are using.
++	 * Mark the registers we are using.
+ 	 */
+-	 
+ 	rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+-	for(i=0;i<used;i++)
+-		lo|=1<<(9+i);
++	for (i = 0; i < used; i++)
++		lo |= 1<<(9+i);
+ 	wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+-	
++
+ 	/*
+-	 *	Wipe unused MCRs
++	 * Wipe unused MCRs
+ 	 */
+-	 
+-	for(i=used;i<8;i++)
++
++	for (i = used; i < 8; i++)
+ 		wrmsr(MSR_IDT_MCR0+i, 0, 0);
+ }
+ 
+ /*
+- *	Handle the MCR key on the Winchip 2.
++ * Handle the MCR key on the Winchip 2.
+  */
+-
+ static void __cpuinit winchip2_unprotect_mcr(void)
+ {
+ 	u32 lo, hi;
+ 	u32 key;
+-	
++
+ 	rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+-	lo&=~0x1C0;	/* blank bits 8-6 */
++	lo &= ~0x1C0;	/* blank bits 8-6 */
+ 	key = (lo>>17) & 7;
+ 	lo |= key<<6;	/* replace with unlock key */
+ 	wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+@@ -242,9 +232,9 @@ static void __cpuinit winchip2_unprotect_mcr(void)
+ static void __cpuinit winchip2_protect_mcr(void)
+ {
+ 	u32 lo, hi;
+-	
++
+ 	rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+-	lo&=~0x1C0;	/* blank bits 8-6 */
++	lo &= ~0x1C0;	/* blank bits 8-6 */
+ 	wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+ }
+ #endif /* CONFIG_X86_OOSTORE */
+@@ -267,17 +257,17 @@ static void __cpuinit init_c3(struct cpuinfo_x86 *c)
+ 
+ 		/* enable ACE unit, if present and disabled */
+ 		if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) {
+-			rdmsr (MSR_VIA_FCR, lo, hi);
++			rdmsr(MSR_VIA_FCR, lo, hi);
+ 			lo |= ACE_FCR;		/* enable ACE unit */
+-			wrmsr (MSR_VIA_FCR, lo, hi);
++			wrmsr(MSR_VIA_FCR, lo, hi);
+ 			printk(KERN_INFO "CPU: Enabled ACE h/w crypto\n");
+ 		}
+ 
+ 		/* enable RNG unit, if present and disabled */
+ 		if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) {
+-			rdmsr (MSR_VIA_RNG, lo, hi);
++			rdmsr(MSR_VIA_RNG, lo, hi);
+ 			lo |= RNG_ENABLE;	/* enable RNG unit */
+-			wrmsr (MSR_VIA_RNG, lo, hi);
++			wrmsr(MSR_VIA_RNG, lo, hi);
+ 			printk(KERN_INFO "CPU: Enabled h/w RNG\n");
+ 		}
+ 
+@@ -288,171 +278,183 @@ static void __cpuinit init_c3(struct cpuinfo_x86 *c)
+ 	}
+ 
+ 	/* Cyrix III family needs CX8 & PGE explicitly enabled. */
+-	if (c->x86_model >=6 && c->x86_model <= 9) {
+-		rdmsr (MSR_VIA_FCR, lo, hi);
++	if (c->x86_model >= 6 && c->x86_model <= 9) {
++		rdmsr(MSR_VIA_FCR, lo, hi);
+ 		lo |= (1<<1 | 1<<7);
+-		wrmsr (MSR_VIA_FCR, lo, hi);
+-		set_bit(X86_FEATURE_CX8, c->x86_capability);
++		wrmsr(MSR_VIA_FCR, lo, hi);
++		set_cpu_cap(c, X86_FEATURE_CX8);
+ 	}
+ 
+ 	/* Before Nehemiah, the C3's had 3dNOW! */
+-	if (c->x86_model >=6 && c->x86_model <9)
+-		set_bit(X86_FEATURE_3DNOW, c->x86_capability);
++	if (c->x86_model >= 6 && c->x86_model < 9)
++		set_cpu_cap(c, X86_FEATURE_3DNOW);
+ 
+ 	get_model_name(c);
+ 	display_cacheinfo(c);
+ }
+ 
++enum {
++		ECX8		= 1<<1,
++		EIERRINT	= 1<<2,
++		DPM		= 1<<3,
++		DMCE		= 1<<4,
++		DSTPCLK		= 1<<5,
++		ELINEAR		= 1<<6,
++		DSMC		= 1<<7,
++		DTLOCK		= 1<<8,
++		EDCTLB		= 1<<8,
++		EMMX		= 1<<9,
++		DPDC		= 1<<11,
++		EBRPRED		= 1<<12,
++		DIC		= 1<<13,
++		DDC		= 1<<14,
++		DNA		= 1<<15,
++		ERETSTK		= 1<<16,
++		E2MMX		= 1<<19,
++		EAMD3D		= 1<<20,
++};
++
+ static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
+ {
+-	enum {
+-		ECX8=1<<1,
+-		EIERRINT=1<<2,
+-		DPM=1<<3,
+-		DMCE=1<<4,
+-		DSTPCLK=1<<5,
+-		ELINEAR=1<<6,
+-		DSMC=1<<7,
+-		DTLOCK=1<<8,
+-		EDCTLB=1<<8,
+-		EMMX=1<<9,
+-		DPDC=1<<11,
+-		EBRPRED=1<<12,
+-		DIC=1<<13,
+-		DDC=1<<14,
+-		DNA=1<<15,
+-		ERETSTK=1<<16,
+-		E2MMX=1<<19,
+-		EAMD3D=1<<20,
+-	};
+ 
+ 	char *name;
+-	u32  fcr_set=0;
+-	u32  fcr_clr=0;
+-	u32  lo,hi,newlo;
+-	u32  aa,bb,cc,dd;
++	u32  fcr_set = 0;
++	u32  fcr_clr = 0;
++	u32  lo, hi, newlo;
++	u32  aa, bb, cc, dd;
+ 
+-	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+-	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+-	clear_bit(0*32+31, c->x86_capability);
++	/*
++	 * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
++	 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
++	 */
++	clear_cpu_cap(c, 0*32+31);
+ 
+ 	switch (c->x86) {
+-
+-		case 5:
+-			switch(c->x86_model) {
+-			case 4:
+-				name="C6";
+-				fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
+-				fcr_clr=DPDC;
+-				printk(KERN_NOTICE "Disabling bugged TSC.\n");
+-				clear_bit(X86_FEATURE_TSC, c->x86_capability);
++	case 5:
++		switch (c->x86_model) {
++		case 4:
++			name = "C6";
++			fcr_set = ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
++			fcr_clr = DPDC;
++			printk(KERN_NOTICE "Disabling bugged TSC.\n");
++			clear_cpu_cap(c, X86_FEATURE_TSC);
+ #ifdef CONFIG_X86_OOSTORE
+-				centaur_create_optimal_mcr();
+-				/* Enable
+-					write combining on non-stack, non-string
+-					write combining on string, all types
+-					weak write ordering 
+-					
+-				   The C6 original lacks weak read order 
+-				   
+-				   Note 0x120 is write only on Winchip 1 */
+-				   
+-				wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);
+-#endif				
++			centaur_create_optimal_mcr();
++			/*
++			 * Enable:
++			 *	write combining on non-stack, non-string
++			 *	write combining on string, all types
++			 *	weak write ordering
++			 *
++			 * The C6 original lacks weak read order
++			 *
++			 * Note 0x120 is write only on Winchip 1
++			 */
++			wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);
++#endif
++			break;
++		case 8:
++			switch (c->x86_mask) {
++			default:
++			name = "2";
++				break;
++			case 7 ... 9:
++				name = "2A";
+ 				break;
+-			case 8:
+-				switch(c->x86_mask) {
+-				default:
+-					name="2";
+-					break;
+-				case 7 ... 9:
+-					name="2A";
+-					break;
+-				case 10 ... 15:
+-					name="2B";
+-					break;
+-				}
+-				fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
+-				fcr_clr=DPDC;
++			case 10 ... 15:
++				name = "2B";
++				break;
++			}
++			fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
++				  E2MMX|EAMD3D;
++			fcr_clr = DPDC;
+ #ifdef CONFIG_X86_OOSTORE
+-				winchip2_unprotect_mcr();
+-				winchip2_create_optimal_mcr();
+-				rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+-				/* Enable
+-					write combining on non-stack, non-string
+-					write combining on string, all types
+-					weak write ordering 
+-				*/
+-				lo|=31;				
+-				wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+-				winchip2_protect_mcr();
++			winchip2_unprotect_mcr();
++			winchip2_create_optimal_mcr();
++			rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
++			/*
++			 * Enable:
++			 *	write combining on non-stack, non-string
++			 *	write combining on string, all types
++			 *	weak write ordering
++			 */
++			lo |= 31;
++			wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
++			winchip2_protect_mcr();
+ #endif
+-				break;
+-			case 9:
+-				name="3";
+-				fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
+-				fcr_clr=DPDC;
++			break;
++		case 9:
++			name = "3";
++			fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
++				  E2MMX|EAMD3D;
++			fcr_clr = DPDC;
+ #ifdef CONFIG_X86_OOSTORE
+-				winchip2_unprotect_mcr();
+-				winchip2_create_optimal_mcr();
+-				rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+-				/* Enable
+-					write combining on non-stack, non-string
+-					write combining on string, all types
+-					weak write ordering 
+-				*/
+-				lo|=31;				
+-				wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+-				winchip2_protect_mcr();
++			winchip2_unprotect_mcr();
++			winchip2_create_optimal_mcr();
++			rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
++			/*
++			 * Enable:
++			 *	write combining on non-stack, non-string
++			 *	write combining on string, all types
++			 *	weak write ordering
++			 */
++			lo |= 31;
++			wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
++			winchip2_protect_mcr();
+ #endif
+-				break;
+-			default:
+-				name="??";
+-			}
++			break;
++		default:
++			name = "??";
++		}
+ 
+-			rdmsr(MSR_IDT_FCR1, lo, hi);
+-			newlo=(lo|fcr_set) & (~fcr_clr);
++		rdmsr(MSR_IDT_FCR1, lo, hi);
++		newlo = (lo|fcr_set) & (~fcr_clr);
+ 
+-			if (newlo!=lo) {
+-				printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", lo, newlo );
+-				wrmsr(MSR_IDT_FCR1, newlo, hi );
+-			} else {
+-				printk(KERN_INFO "Centaur FCR is 0x%X\n",lo);
+-			}
+-			/* Emulate MTRRs using Centaur's MCR. */
+-			set_bit(X86_FEATURE_CENTAUR_MCR, c->x86_capability);
+-			/* Report CX8 */
+-			set_bit(X86_FEATURE_CX8, c->x86_capability);
+-			/* Set 3DNow! on Winchip 2 and above. */
+-			if (c->x86_model >=8)
+-				set_bit(X86_FEATURE_3DNOW, c->x86_capability);
+-			/* See if we can find out some more. */
+-			if ( cpuid_eax(0x80000000) >= 0x80000005 ) {
+-				/* Yes, we can. */
+-				cpuid(0x80000005,&aa,&bb,&cc,&dd);
+-				/* Add L1 data and code cache sizes. */
+-				c->x86_cache_size = (cc>>24)+(dd>>24);
+-			}
+-			sprintf( c->x86_model_id, "WinChip %s", name );
+-			break;
++		if (newlo != lo) {
++			printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n",
++				lo, newlo);
++			wrmsr(MSR_IDT_FCR1, newlo, hi);
++		} else {
++			printk(KERN_INFO "Centaur FCR is 0x%X\n", lo);
++		}
++		/* Emulate MTRRs using Centaur's MCR. */
++		set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
++		/* Report CX8 */
++		set_cpu_cap(c, X86_FEATURE_CX8);
++		/* Set 3DNow! on Winchip 2 and above. */
++		if (c->x86_model >= 8)
++			set_cpu_cap(c, X86_FEATURE_3DNOW);
++		/* See if we can find out some more. */
++		if (cpuid_eax(0x80000000) >= 0x80000005) {
++			/* Yes, we can. */
++			cpuid(0x80000005, &aa, &bb, &cc, &dd);
++			/* Add L1 data and code cache sizes. */
++			c->x86_cache_size = (cc>>24)+(dd>>24);
++		}
++		sprintf(c->x86_model_id, "WinChip %s", name);
++		break;
+ 
+-		case 6:
+-			init_c3(c);
+-			break;
++	case 6:
++		init_c3(c);
++		break;
+ 	}
+ }
+ 
+-static unsigned int __cpuinit centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size)
++static unsigned int __cpuinit
++centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
+ {
+ 	/* VIA C3 CPUs (670-68F) need further shifting. */
+ 	if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
+ 		size >>= 8;
+ 
+-	/* VIA also screwed up Nehemiah stepping 1, and made
+-	   it return '65KB' instead of '64KB'
+-	   - Note, it seems this may only be in engineering samples. */
+-	if ((c->x86==6) && (c->x86_model==9) && (c->x86_mask==1) && (size==65))
+-		size -=1;
++	/*
++	 * There's also an erratum in Nehemiah stepping 1, which
++	 * returns '65KB' instead of '64KB'
++	 *  - Note, it seems this may only be in engineering samples.
++	 */
++	if ((c->x86 == 6) && (c->x86_model == 9) &&
++				(c->x86_mask == 1) && (size == 65))
++		size -= 1;
+ 
+ 	return size;
+ }
+@@ -464,8 +466,4 @@ static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
+ 	.c_size_cache	= centaur_size_cache,
+ };
+ 
+-int __init centaur_init_cpu(void)
+-{
+-	cpu_devs[X86_VENDOR_CENTAUR] = &centaur_cpu_dev;
+-	return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_CENTAUR, &centaur_cpu_dev);
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index a38aafa..35b4f6a 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -5,7 +5,6 @@
+ #include <linux/module.h>
+ #include <linux/percpu.h>
+ #include <linux/bootmem.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/msr.h>
+@@ -62,9 +61,9 @@ __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+ static int cachesize_override __cpuinitdata = -1;
+ static int disable_x86_serial_nr __cpuinitdata = 1;
+ 
+-struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
++struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
+ 
+-static void __cpuinit default_init(struct cpuinfo_x86 * c)
++static void __cpuinit default_init(struct cpuinfo_x86 *c)
+ {
+ 	/* Not much we can do here... */
+ 	/* Check if at least it has cpuid */
+@@ -81,11 +80,11 @@ static struct cpu_dev __cpuinitdata default_cpu = {
+ 	.c_init	= default_init,
+ 	.c_vendor = "Unknown",
+ };
+-static struct cpu_dev * this_cpu __cpuinitdata = &default_cpu;
++static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+ 
+ static int __init cachesize_setup(char *str)
+ {
+-	get_option (&str, &cachesize_override);
++	get_option(&str, &cachesize_override);
+ 	return 1;
+ }
+ __setup("cachesize=", cachesize_setup);
+@@ -107,12 +106,12 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c)
+ 	/* Intel chips right-justify this string for some dumb reason;
+ 	   undo that brain damage */
+ 	p = q = &c->x86_model_id[0];
+-	while ( *p == ' ' )
++	while (*p == ' ')
+ 	     p++;
+-	if ( p != q ) {
+-	     while ( *p )
++	if (p != q) {
++	     while (*p)
+ 		  *q++ = *p++;
+-	     while ( q <= &c->x86_model_id[48] )
++	     while (q <= &c->x86_model_id[48])
+ 		  *q++ = '\0';	/* Zero-pad the rest */
+ 	}
+ 
+@@ -130,7 +129,7 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+ 		cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+ 		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
+ 			edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+-		c->x86_cache_size=(ecx>>24)+(edx>>24);	
++		c->x86_cache_size = (ecx>>24)+(edx>>24);
+ 	}
+ 
+ 	if (n < 0x80000006)	/* Some chips just has a large L1. */
+@@ -138,16 +137,16 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+ 
+ 	ecx = cpuid_ecx(0x80000006);
+ 	l2size = ecx >> 16;
+-	
++
+ 	/* do processor-specific cache resizing */
+ 	if (this_cpu->c_size_cache)
+-		l2size = this_cpu->c_size_cache(c,l2size);
++		l2size = this_cpu->c_size_cache(c, l2size);
+ 
+ 	/* Allow user to override all this if necessary. */
+ 	if (cachesize_override != -1)
+ 		l2size = cachesize_override;
+ 
+-	if ( l2size == 0 )
++	if (l2size == 0)
+ 		return;		/* Again, no L2 cache is possible */
+ 
+ 	c->x86_cache_size = l2size;
+@@ -156,16 +155,19 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+ 	       l2size, ecx & 0xFF);
+ }
+ 
+-/* Naming convention should be: <Name> [(<Codename>)] */
+-/* This table only is used unless init_<vendor>() below doesn't set it; */
+-/* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */
++/*
++ * Naming convention should be: <Name> [(<Codename>)]
++ * This table only is used unless init_<vendor>() below doesn't set it;
++ * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used
++ *
++ */
+ 
+ /* Look up CPU names by table lookup. */
+ static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c)
+ {
+ 	struct cpu_model_info *info;
+ 
+-	if ( c->x86_model >= 16 )
++	if (c->x86_model >= 16)
+ 		return NULL;	/* Range check */
+ 
+ 	if (!this_cpu)
+@@ -190,9 +192,9 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
+ 
+ 	for (i = 0; i < X86_VENDOR_NUM; i++) {
+ 		if (cpu_devs[i]) {
+-			if (!strcmp(v,cpu_devs[i]->c_ident[0]) ||
+-			    (cpu_devs[i]->c_ident[1] && 
+-			     !strcmp(v,cpu_devs[i]->c_ident[1]))) {
++			if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
++			    (cpu_devs[i]->c_ident[1] &&
++			     !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+ 				c->x86_vendor = i;
+ 				if (!early)
+ 					this_cpu = cpu_devs[i];
+@@ -210,7 +212,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
+ }
+ 
+ 
+-static int __init x86_fxsr_setup(char * s)
++static int __init x86_fxsr_setup(char *s)
+ {
+ 	setup_clear_cpu_cap(X86_FEATURE_FXSR);
+ 	setup_clear_cpu_cap(X86_FEATURE_XMM);
+@@ -219,7 +221,7 @@ static int __init x86_fxsr_setup(char * s)
+ __setup("nofxsr", x86_fxsr_setup);
+ 
+ 
+-static int __init x86_sep_setup(char * s)
++static int __init x86_sep_setup(char *s)
+ {
+ 	setup_clear_cpu_cap(X86_FEATURE_SEP);
+ 	return 1;
+@@ -306,14 +308,30 @@ static void __cpuinit early_get_cap(struct cpuinfo_x86 *c)
+ 
+ 	}
+ 
+-}
++	clear_cpu_cap(c, X86_FEATURE_PAT);
++
++	switch (c->x86_vendor) {
++	case X86_VENDOR_AMD:
++		if (c->x86 >= 0xf && c->x86 <= 0x11)
++			set_cpu_cap(c, X86_FEATURE_PAT);
++		break;
++	case X86_VENDOR_INTEL:
++		if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15))
++			set_cpu_cap(c, X86_FEATURE_PAT);
++		break;
++	}
+ 
+-/* Do minimum CPU detection early.
+-   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
+-   The others are not touched to avoid unwanted side effects.
++}
+ 
+-   WARNING: this function is only called on the BP.  Don't add code here
+-   that is supposed to run on all CPUs. */
++/*
++ * Do minimum CPU detection early.
++ * Fields really needed: vendor, cpuid_level, family, model, mask,
++ * cache alignment.
++ * The others are not touched to avoid unwanted side effects.
++ *
++ * WARNING: this function is only called on the BP.  Don't add code here
++ * that is supposed to run on all CPUs.
++ */
+ static void __init early_cpu_detect(void)
+ {
+ 	struct cpuinfo_x86 *c = &boot_cpu_data;
+@@ -328,19 +346,14 @@ static void __init early_cpu_detect(void)
+ 
+ 	get_cpu_vendor(c, 1);
+ 
+-	switch (c->x86_vendor) {
+-	case X86_VENDOR_AMD:
+-		early_init_amd(c);
+-		break;
+-	case X86_VENDOR_INTEL:
+-		early_init_intel(c);
+-		break;
+-	}
++	if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
++	    cpu_devs[c->x86_vendor]->c_early_init)
++		cpu_devs[c->x86_vendor]->c_early_init(c);
+ 
+ 	early_get_cap(c);
+ }
+ 
+-static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
++static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
+ {
+ 	u32 tfms, xlvl;
+ 	unsigned int ebx;
+@@ -351,13 +364,12 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+ 		      (unsigned int *)&c->x86_vendor_id[0],
+ 		      (unsigned int *)&c->x86_vendor_id[8],
+ 		      (unsigned int *)&c->x86_vendor_id[4]);
+-		
++
+ 		get_cpu_vendor(c, 0);
+ 		/* Initialize the standard set of capabilities */
+ 		/* Note that the vendor-specific code below might override */
+-	
+ 		/* Intel-defined flags: level 0x00000001 */
+-		if ( c->cpuid_level >= 0x00000001 ) {
++		if (c->cpuid_level >= 0x00000001) {
+ 			u32 capability, excap;
+ 			cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
+ 			c->x86_capability[0] = capability;
+@@ -369,12 +381,14 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+ 			if (c->x86 >= 0x6)
+ 				c->x86_model += ((tfms >> 16) & 0xF) << 4;
+ 			c->x86_mask = tfms & 15;
++			c->initial_apicid = (ebx >> 24) & 0xFF;
+ #ifdef CONFIG_X86_HT
+-			c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
++			c->apicid = phys_pkg_id(c->initial_apicid, 0);
++			c->phys_proc_id = c->initial_apicid;
+ #else
+-			c->apicid = (ebx >> 24) & 0xFF;
++			c->apicid = c->initial_apicid;
+ #endif
+-			if (c->x86_capability[0] & (1<<19))
++			if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
+ 				c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
+ 		} else {
+ 			/* Have CPUID level 0 only - unheard of */
+@@ -383,33 +397,42 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+ 
+ 		/* AMD-defined flags: level 0x80000001 */
+ 		xlvl = cpuid_eax(0x80000000);
+-		if ( (xlvl & 0xffff0000) == 0x80000000 ) {
+-			if ( xlvl >= 0x80000001 ) {
++		if ((xlvl & 0xffff0000) == 0x80000000) {
++			if (xlvl >= 0x80000001) {
+ 				c->x86_capability[1] = cpuid_edx(0x80000001);
+ 				c->x86_capability[6] = cpuid_ecx(0x80000001);
+ 			}
+-			if ( xlvl >= 0x80000004 )
++			if (xlvl >= 0x80000004)
+ 				get_model_name(c); /* Default name */
+ 		}
+ 
+ 		init_scattered_cpuid_features(c);
+ 	}
+ 
+-#ifdef CONFIG_X86_HT
+-	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
+-#endif
++	clear_cpu_cap(c, X86_FEATURE_PAT);
++
++	switch (c->x86_vendor) {
++	case X86_VENDOR_AMD:
++		if (c->x86 >= 0xf && c->x86 <= 0x11)
++			set_cpu_cap(c, X86_FEATURE_PAT);
++		break;
++	case X86_VENDOR_INTEL:
++		if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15))
++			set_cpu_cap(c, X86_FEATURE_PAT);
++		break;
++	}
+ }
+ 
+ static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+ {
+-	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) {
++	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) {
+ 		/* Disable processor serial number */
+-		unsigned long lo,hi;
+-		rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
++		unsigned long lo, hi;
++		rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+ 		lo |= 0x200000;
+-		wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
++		wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+ 		printk(KERN_NOTICE "CPU serial number disabled.\n");
+-		clear_bit(X86_FEATURE_PN, c->x86_capability);
++		clear_cpu_cap(c, X86_FEATURE_PN);
+ 
+ 		/* Disabling the serial number may affect the cpuid level */
+ 		c->cpuid_level = cpuid_eax(0);
+@@ -444,9 +467,11 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+ 
+ 	if (!have_cpuid_p()) {
+-		/* First of all, decide if this is a 486 or higher */
+-		/* It's a 486 if we can modify the AC flag */
+-		if ( flag_is_changeable_p(X86_EFLAGS_AC) )
++		/*
++		 * First of all, decide if this is a 486 or higher
++		 * It's a 486 if we can modify the AC flag
++		 */
++		if (flag_is_changeable_p(X86_EFLAGS_AC))
+ 			c->x86 = 4;
+ 		else
+ 			c->x86 = 3;
+@@ -479,10 +504,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ 	 */
+ 
+ 	/* If the model name is still unset, do table lookup. */
+-	if ( !c->x86_model_id[0] ) {
++	if (!c->x86_model_id[0]) {
+ 		char *p;
+ 		p = table_lookup_model(c);
+-		if ( p )
++		if (p)
+ 			strcpy(c->x86_model_id, p);
+ 		else
+ 			/* Last resort... */
+@@ -496,9 +521,9 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ 	 * common between the CPUs.  The first time this routine gets
+ 	 * executed, c == &boot_cpu_data.
+ 	 */
+-	if ( c != &boot_cpu_data ) {
++	if (c != &boot_cpu_data) {
+ 		/* AND the already accumulated flags with these */
+-		for ( i = 0 ; i < NCAPINTS ; i++ )
++		for (i = 0 ; i < NCAPINTS ; i++)
+ 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+ 	}
+ 
+@@ -542,7 +567,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+ 
+ 	if (smp_num_siblings == 1) {
+ 		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+-	} else if (smp_num_siblings > 1 ) {
++	} else if (smp_num_siblings > 1) {
+ 
+ 		if (smp_num_siblings > NR_CPUS) {
+ 			printk(KERN_WARNING "CPU: Unsupported number of the "
+@@ -552,7 +577,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+ 		}
+ 
+ 		index_msb = get_count_order(smp_num_siblings);
+-		c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
++		c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb);
+ 
+ 		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+ 		       c->phys_proc_id);
+@@ -563,7 +588,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+ 
+ 		core_bits = get_count_order(c->x86_max_cores);
+ 
+-		c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
++		c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
+ 					       ((1 << core_bits) - 1);
+ 
+ 		if (c->x86_max_cores > 1)
+@@ -597,7 +622,7 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
+ 	else
+ 		printk("%s", c->x86_model_id);
+ 
+-	if (c->x86_mask || c->cpuid_level >= 0) 
++	if (c->x86_mask || c->cpuid_level >= 0)
+ 		printk(" stepping %02x\n", c->x86_mask);
+ 	else
+ 		printk("\n");
+@@ -616,23 +641,15 @@ __setup("clearcpuid=", setup_disablecpuid);
+ 
+ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+ 
+-/* This is hacky. :)
+- * We're emulating future behavior.
+- * In the future, the cpu-specific init functions will be called implicitly
+- * via the magic of initcalls.
+- * They will insert themselves into the cpu_devs structure.
+- * Then, when cpu_init() is called, we can just iterate over that array.
+- */
+ void __init early_cpu_init(void)
+ {
+-	intel_cpu_init();
+-	cyrix_init_cpu();
+-	nsc_init_cpu();
+-	amd_init_cpu();
+-	centaur_init_cpu();
+-	transmeta_init_cpu();
+-	nexgen_init_cpu();
+-	umc_init_cpu();
++	struct cpu_vendor_dev *cvdev;
++
++	for (cvdev = __x86cpuvendor_start ;
++	     cvdev < __x86cpuvendor_end   ;
++	     cvdev++)
++		cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
++
+ 	early_cpu_detect();
+ }
+ 
+@@ -666,7 +683,7 @@ void __cpuinit cpu_init(void)
+ {
+ 	int cpu = smp_processor_id();
+ 	struct task_struct *curr = current;
+-	struct tss_struct * t = &per_cpu(init_tss, cpu);
++	struct tss_struct *t = &per_cpu(init_tss, cpu);
+ 	struct thread_struct *thread = &curr->thread;
+ 
+ 	if (cpu_test_and_set(cpu, cpu_initialized)) {
+@@ -692,7 +709,7 @@ void __cpuinit cpu_init(void)
+ 	enter_lazy_tlb(&init_mm, curr);
+ 
+ 	load_sp0(t, thread);
+-	set_tss_desc(cpu,t);
++	set_tss_desc(cpu, t);
+ 	load_TR_desc();
+ 	load_LDT(&init_mm.context);
+ 
+diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
+index e0b38c3..783691b 100644
+--- a/arch/x86/kernel/cpu/cpu.h
++++ b/arch/x86/kernel/cpu/cpu.h
+@@ -14,6 +14,7 @@ struct cpu_dev {
+ 
+ 	struct		cpu_model_info c_models[4];
+ 
++	void            (*c_early_init)(struct cpuinfo_x86 *c);
+ 	void		(*c_init)(struct cpuinfo_x86 * c);
+ 	void		(*c_identify)(struct cpuinfo_x86 * c);
+ 	unsigned int	(*c_size_cache)(struct cpuinfo_x86 * c, unsigned int size);
+@@ -21,18 +22,17 @@ struct cpu_dev {
+ 
+ extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM];
+ 
++struct cpu_vendor_dev {
++	int vendor;
++	struct cpu_dev *cpu_dev;
++};
++
++#define cpu_vendor_dev_register(cpu_vendor_id, cpu_dev) \
++	static struct cpu_vendor_dev __cpu_vendor_dev_##cpu_vendor_id __used \
++	__attribute__((__section__(".x86cpuvendor.init"))) = \
++	{ cpu_vendor_id, cpu_dev }
++
++extern struct cpu_vendor_dev __x86cpuvendor_start[], __x86cpuvendor_end[];
++
+ extern int get_model_name(struct cpuinfo_x86 *c);
+ extern void display_cacheinfo(struct cpuinfo_x86 *c);
+-
+-extern void early_init_intel(struct cpuinfo_x86 *c);
+-extern void early_init_amd(struct cpuinfo_x86 *c);
+-
+-/* Specific CPU type init functions */
+-int intel_cpu_init(void);
+-int amd_init_cpu(void);
+-int cyrix_init_cpu(void);
+-int nsc_init_cpu(void);
+-int centaur_init_cpu(void);
+-int transmeta_init_cpu(void);
+-int nexgen_init_cpu(void);
+-int umc_init_cpu(void);
+diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+index a962dcb..e2d870d 100644
+--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
++++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+@@ -192,9 +192,9 @@ static void drv_read(struct drv_cmd *cmd)
+ 	cpumask_t saved_mask = current->cpus_allowed;
+ 	cmd->val = 0;
+ 
+-	set_cpus_allowed(current, cmd->mask);
++	set_cpus_allowed_ptr(current, &cmd->mask);
+ 	do_drv_read(cmd);
+-	set_cpus_allowed(current, saved_mask);
++	set_cpus_allowed_ptr(current, &saved_mask);
+ }
+ 
+ static void drv_write(struct drv_cmd *cmd)
+@@ -203,30 +203,30 @@ static void drv_write(struct drv_cmd *cmd)
+ 	unsigned int i;
+ 
+ 	for_each_cpu_mask(i, cmd->mask) {
+-		set_cpus_allowed(current, cpumask_of_cpu(i));
++		set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
+ 		do_drv_write(cmd);
+ 	}
+ 
+-	set_cpus_allowed(current, saved_mask);
++	set_cpus_allowed_ptr(current, &saved_mask);
+ 	return;
+ }
+ 
+-static u32 get_cur_val(cpumask_t mask)
++static u32 get_cur_val(const cpumask_t *mask)
+ {
+ 	struct acpi_processor_performance *perf;
+ 	struct drv_cmd cmd;
+ 
+-	if (unlikely(cpus_empty(mask)))
++	if (unlikely(cpus_empty(*mask)))
+ 		return 0;
+ 
+-	switch (per_cpu(drv_data, first_cpu(mask))->cpu_feature) {
++	switch (per_cpu(drv_data, first_cpu(*mask))->cpu_feature) {
+ 	case SYSTEM_INTEL_MSR_CAPABLE:
+ 		cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
+ 		cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
+ 		break;
+ 	case SYSTEM_IO_CAPABLE:
+ 		cmd.type = SYSTEM_IO_CAPABLE;
+-		perf = per_cpu(drv_data, first_cpu(mask))->acpi_data;
++		perf = per_cpu(drv_data, first_cpu(*mask))->acpi_data;
+ 		cmd.addr.io.port = perf->control_register.address;
+ 		cmd.addr.io.bit_width = perf->control_register.bit_width;
+ 		break;
+@@ -234,7 +234,7 @@ static u32 get_cur_val(cpumask_t mask)
+ 		return 0;
+ 	}
+ 
+-	cmd.mask = mask;
++	cmd.mask = *mask;
+ 
+ 	drv_read(&cmd);
+ 
+@@ -271,7 +271,7 @@ static unsigned int get_measured_perf(unsigned int cpu)
+ 	unsigned int retval;
+ 
+ 	saved_mask = current->cpus_allowed;
+-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 	if (get_cpu() != cpu) {
+ 		/* We were not able to run on requested processor */
+ 		put_cpu();
+@@ -329,7 +329,7 @@ static unsigned int get_measured_perf(unsigned int cpu)
+ 	retval = per_cpu(drv_data, cpu)->max_freq * perf_percent / 100;
+ 
+ 	put_cpu();
+-	set_cpus_allowed(current, saved_mask);
++	set_cpus_allowed_ptr(current, &saved_mask);
+ 
+ 	dprintk("cpu %d: performance percent %d\n", cpu, perf_percent);
+ 	return retval;
+@@ -347,13 +347,13 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
+ 		return 0;
+ 	}
+ 
+-	freq = extract_freq(get_cur_val(cpumask_of_cpu(cpu)), data);
++	freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
+ 	dprintk("cur freq = %u\n", freq);
+ 
+ 	return freq;
+ }
+ 
+-static unsigned int check_freqs(cpumask_t mask, unsigned int freq,
++static unsigned int check_freqs(const cpumask_t *mask, unsigned int freq,
+ 				struct acpi_cpufreq_data *data)
+ {
+ 	unsigned int cur_freq;
+@@ -449,7 +449,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
+ 	drv_write(&cmd);
+ 
+ 	if (acpi_pstate_strict) {
+-		if (!check_freqs(cmd.mask, freqs.new, data)) {
++		if (!check_freqs(&cmd.mask, freqs.new, data)) {
+ 			dprintk("acpi_cpufreq_target failed (%d)\n",
+ 				policy->cpu);
+ 			return -EAGAIN;
+diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+index 14791ec..199e4e0 100644
+--- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
++++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+@@ -289,8 +289,8 @@ static int __init cpufreq_p4_init(void)
+ 	if (c->x86_vendor != X86_VENDOR_INTEL)
+ 		return -ENODEV;
+ 
+-	if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) ||
+-		!test_bit(X86_FEATURE_ACC, c->x86_capability))
++	if (!test_cpu_cap(c, X86_FEATURE_ACPI) ||
++				!test_cpu_cap(c, X86_FEATURE_ACC))
+ 		return -ENODEV;
+ 
+ 	ret = cpufreq_register_driver(&p4clockmod_driver);
+diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+index c99d59d..46d4034 100644
+--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
++++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+@@ -478,12 +478,12 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
+ 
+ static int check_supported_cpu(unsigned int cpu)
+ {
+-	cpumask_t oldmask = CPU_MASK_ALL;
++	cpumask_t oldmask;
+ 	u32 eax, ebx, ecx, edx;
+ 	unsigned int rc = 0;
+ 
+ 	oldmask = current->cpus_allowed;
+-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 
+ 	if (smp_processor_id() != cpu) {
+ 		printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
+@@ -528,7 +528,7 @@ static int check_supported_cpu(unsigned int cpu)
+ 	rc = 1;
+ 
+ out:
+-	set_cpus_allowed(current, oldmask);
++	set_cpus_allowed_ptr(current, &oldmask);
+ 	return rc;
+ }
+ 
+@@ -1015,7 +1015,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
+ /* Driver entry point to switch to the target frequency */
+ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
+ {
+-	cpumask_t oldmask = CPU_MASK_ALL;
++	cpumask_t oldmask;
+ 	struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
+ 	u32 checkfid;
+ 	u32 checkvid;
+@@ -1030,7 +1030,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
+ 
+ 	/* only run on specific CPU from here on */
+ 	oldmask = current->cpus_allowed;
+-	set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
+ 
+ 	if (smp_processor_id() != pol->cpu) {
+ 		printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
+@@ -1085,7 +1085,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
+ 	ret = 0;
+ 
+ err_out:
+-	set_cpus_allowed(current, oldmask);
++	set_cpus_allowed_ptr(current, &oldmask);
+ 	return ret;
+ }
+ 
+@@ -1104,7 +1104,7 @@ static int powernowk8_verify(struct cpufreq_policy *pol)
+ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+ {
+ 	struct powernow_k8_data *data;
+-	cpumask_t oldmask = CPU_MASK_ALL;
++	cpumask_t oldmask;
+ 	int rc;
+ 
+ 	if (!cpu_online(pol->cpu))
+@@ -1145,7 +1145,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+ 
+ 	/* only run on specific CPU from here on */
+ 	oldmask = current->cpus_allowed;
+-	set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
+ 
+ 	if (smp_processor_id() != pol->cpu) {
+ 		printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
+@@ -1164,7 +1164,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+ 		fidvid_msr_init();
+ 
+ 	/* run on any CPU again */
+-	set_cpus_allowed(current, oldmask);
++	set_cpus_allowed_ptr(current, &oldmask);
+ 
+ 	if (cpu_family == CPU_HW_PSTATE)
+ 		pol->cpus = cpumask_of_cpu(pol->cpu);
+@@ -1205,7 +1205,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+ 	return 0;
+ 
+ err_out:
+-	set_cpus_allowed(current, oldmask);
++	set_cpus_allowed_ptr(current, &oldmask);
+ 	powernow_k8_cpu_exit_acpi(data);
+ 
+ 	kfree(data);
+@@ -1242,10 +1242,11 @@ static unsigned int powernowk8_get (unsigned int cpu)
+ 	if (!data)
+ 		return -EINVAL;
+ 
+-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 	if (smp_processor_id() != cpu) {
+-		printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu);
+-		set_cpus_allowed(current, oldmask);
++		printk(KERN_ERR PFX
++			"limiting to CPU %d failed in powernowk8_get\n", cpu);
++		set_cpus_allowed_ptr(current, &oldmask);
+ 		return 0;
+ 	}
+ 
+@@ -1253,13 +1254,14 @@ static unsigned int powernowk8_get (unsigned int cpu)
+ 		goto out;
+ 
+ 	if (cpu_family == CPU_HW_PSTATE)
+-		khz = find_khz_freq_from_pstate(data->powernow_table, data->currpstate);
++		khz = find_khz_freq_from_pstate(data->powernow_table,
++						data->currpstate);
+ 	else
+ 		khz = find_khz_freq_from_fid(data->currfid);
+ 
+ 
+ out:
+-	set_cpus_allowed(current, oldmask);
++	set_cpus_allowed_ptr(current, &oldmask);
+ 	return khz;
+ }
+ 
+diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+index 3031f11..908dd34 100644
+--- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
++++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+@@ -315,7 +315,7 @@ static unsigned int get_cur_freq(unsigned int cpu)
+ 	cpumask_t saved_mask;
+ 
+ 	saved_mask = current->cpus_allowed;
+-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 	if (smp_processor_id() != cpu)
+ 		return 0;
+ 
+@@ -333,7 +333,7 @@ static unsigned int get_cur_freq(unsigned int cpu)
+ 		clock_freq = extract_clock(l, cpu, 1);
+ 	}
+ 
+-	set_cpus_allowed(current, saved_mask);
++	set_cpus_allowed_ptr(current, &saved_mask);
+ 	return clock_freq;
+ }
+ 
+@@ -487,7 +487,7 @@ static int centrino_target (struct cpufreq_policy *policy,
+ 		else
+ 			cpu_set(j, set_mask);
+ 
+-		set_cpus_allowed(current, set_mask);
++		set_cpus_allowed_ptr(current, &set_mask);
+ 		preempt_disable();
+ 		if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
+ 			dprintk("couldn't limit to CPUs in this domain\n");
+@@ -555,7 +555,8 @@ static int centrino_target (struct cpufreq_policy *policy,
+ 
+ 		if (!cpus_empty(covered_cpus)) {
+ 			for_each_cpu_mask(j, covered_cpus) {
+-				set_cpus_allowed(current, cpumask_of_cpu(j));
++				set_cpus_allowed_ptr(current,
++						     &cpumask_of_cpu(j));
+ 				wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+ 			}
+ 		}
+@@ -569,12 +570,12 @@ static int centrino_target (struct cpufreq_policy *policy,
+ 			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ 		}
+ 	}
+-	set_cpus_allowed(current, saved_mask);
++	set_cpus_allowed_ptr(current, &saved_mask);
+ 	return 0;
+ 
+ migrate_end:
+ 	preempt_enable();
+-	set_cpus_allowed(current, saved_mask);
++	set_cpus_allowed_ptr(current, &saved_mask);
+ 	return 0;
+ }
+ 
+diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
+index 14d68aa..1b50244 100644
+--- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
++++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
+@@ -229,22 +229,22 @@ static unsigned int speedstep_detect_chipset (void)
+ 	return 0;
+ }
+ 
+-static unsigned int _speedstep_get(cpumask_t cpus)
++static unsigned int _speedstep_get(const cpumask_t *cpus)
+ {
+ 	unsigned int speed;
+ 	cpumask_t cpus_allowed;
+ 
+ 	cpus_allowed = current->cpus_allowed;
+-	set_cpus_allowed(current, cpus);
++	set_cpus_allowed_ptr(current, cpus);
+ 	speed = speedstep_get_processor_frequency(speedstep_processor);
+-	set_cpus_allowed(current, cpus_allowed);
++	set_cpus_allowed_ptr(current, &cpus_allowed);
+ 	dprintk("detected %u kHz as current frequency\n", speed);
+ 	return speed;
+ }
+ 
+ static unsigned int speedstep_get(unsigned int cpu)
+ {
+-	return _speedstep_get(cpumask_of_cpu(cpu));
++	return _speedstep_get(&cpumask_of_cpu(cpu));
+ }
+ 
+ /**
+@@ -267,7 +267,7 @@ static int speedstep_target (struct cpufreq_policy *policy,
+ 	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
+ 		return -EINVAL;
+ 
+-	freqs.old = _speedstep_get(policy->cpus);
++	freqs.old = _speedstep_get(&policy->cpus);
+ 	freqs.new = speedstep_freqs[newstate].frequency;
+ 	freqs.cpu = policy->cpu;
+ 
+@@ -285,12 +285,12 @@ static int speedstep_target (struct cpufreq_policy *policy,
+ 	}
+ 
+ 	/* switch to physical CPU where state is to be changed */
+-	set_cpus_allowed(current, policy->cpus);
++	set_cpus_allowed_ptr(current, &policy->cpus);
+ 
+ 	speedstep_set_state(newstate);
+ 
+ 	/* allow to be run on all CPUs */
+-	set_cpus_allowed(current, cpus_allowed);
++	set_cpus_allowed_ptr(current, &cpus_allowed);
+ 
+ 	for_each_cpu_mask(i, policy->cpus) {
+ 		freqs.cpu = i;
+@@ -326,7 +326,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
+ #endif
+ 
+ 	cpus_allowed = current->cpus_allowed;
+-	set_cpus_allowed(current, policy->cpus);
++	set_cpus_allowed_ptr(current, &policy->cpus);
+ 
+ 	/* detect low and high frequency and transition latency */
+ 	result = speedstep_get_freqs(speedstep_processor,
+@@ -334,12 +334,12 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
+ 				     &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+ 				     &policy->cpuinfo.transition_latency,
+ 				     &speedstep_set_state);
+-	set_cpus_allowed(current, cpus_allowed);
++	set_cpus_allowed_ptr(current, &cpus_allowed);
+ 	if (result)
+ 		return result;
+ 
+ 	/* get current speed setting */
+-	speed = _speedstep_get(policy->cpus);
++	speed = _speedstep_get(&policy->cpus);
+ 	if (!speed)
+ 		return -EIO;
+ 
+diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
+index 7139b02..3fd7a67 100644
+--- a/arch/x86/kernel/cpu/cyrix.c
++++ b/arch/x86/kernel/cpu/cyrix.c
+@@ -19,7 +19,7 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+ {
+ 	unsigned char ccr2, ccr3;
+ 	unsigned long flags;
+-	
++
+ 	/* we test for DEVID by checking whether CCR3 is writable */
+ 	local_irq_save(flags);
+ 	ccr3 = getCx86(CX86_CCR3);
+@@ -37,8 +37,7 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+ 			setCx86(CX86_CCR2, ccr2);
+ 			*dir0 = 0xfe;
+ 		}
+-	}
+-	else {
++	} else {
+ 		setCx86(CX86_CCR3, ccr3);  /* restore CCR3 */
+ 
+ 		/* read DIR0 and DIR1 CPU registers */
+@@ -86,7 +85,7 @@ static char cyrix_model_mult2[] __cpuinitdata = "12233445";
+ static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c)
+ {
+ 	unsigned long flags;
+-	
++
+ 	if (Cx86_dir0_msb == 3) {
+ 		unsigned char ccr3, ccr5;
+ 
+@@ -132,7 +131,7 @@ static void __cpuinit set_cx86_memwb(void)
+ 	/* set 'Not Write-through' */
+ 	write_cr0(read_cr0() | X86_CR0_NW);
+ 	/* CCR2 bit 2: lock NW bit and set WT1 */
+-	setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
++	setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14);
+ }
+ 
+ static void __cpuinit set_cx86_inc(void)
+@@ -148,7 +147,7 @@ static void __cpuinit set_cx86_inc(void)
+ 	setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02);
+ 	/* PCR0 -- Performance Control */
+ 	/* Incrementor Margin 10 */
+-	setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04); 
++	setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04);
+ 	setCx86(CX86_CCR3, ccr3);	/* disable MAPEN */
+ }
+ 
+@@ -167,16 +166,16 @@ static void __cpuinit geode_configure(void)
+ 
+ 	ccr3 = getCx86(CX86_CCR3);
+ 	setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);	/* enable MAPEN */
+-	
++
+ 
+ 	/* FPU fast, DTE cache, Mem bypass */
+ 	setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x38);
+ 	setCx86(CX86_CCR3, ccr3);			/* disable MAPEN */
+-	
++
+ 	set_cx86_memwb();
+-	set_cx86_reorder();	
++	set_cx86_reorder();
+ 	set_cx86_inc();
+-	
++
+ 	local_irq_restore(flags);
+ }
+ 
+@@ -187,14 +186,16 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ 	char *buf = c->x86_model_id;
+ 	const char *p = NULL;
+ 
+-	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+-	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+-	clear_bit(0*32+31, c->x86_capability);
++	/*
++	 * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
++	 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
++	 */
++	clear_cpu_cap(c, 0*32+31);
+ 
+ 	/* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */
+-	if ( test_bit(1*32+24, c->x86_capability) ) {
+-		clear_bit(1*32+24, c->x86_capability);
+-		set_bit(X86_FEATURE_CXMMX, c->x86_capability);
++	if (test_cpu_cap(c, 1*32+24)) {
++		clear_cpu_cap(c, 1*32+24);
++		set_cpu_cap(c, X86_FEATURE_CXMMX);
+ 	}
+ 
+ 	do_cyrix_devid(&dir0, &dir1);
+@@ -213,7 +214,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ 	 * the model, multiplier and stepping.  Black magic included,
+ 	 * to make the silicon step/rev numbers match the printed ones.
+ 	 */
+-	 
++
+ 	switch (dir0_msn) {
+ 		unsigned char tmp;
+ 
+@@ -241,7 +242,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ 		} else             /* 686 */
+ 			p = Cx86_cb+1;
+ 		/* Emulate MTRRs using Cyrix's ARRs. */
+-		set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
+ 		/* 6x86's contain this bug */
+ 		c->coma_bug = 1;
+ 		break;
+@@ -250,17 +251,18 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ #ifdef CONFIG_PCI
+ 	{
+ 		u32 vendor, device;
+-		/* It isn't really a PCI quirk directly, but the cure is the
+-		   same. The MediaGX has deep magic SMM stuff that handles the
+-		   SB emulation. It throws away the fifo on disable_dma() which
+-		   is wrong and ruins the audio. 
+-
+-		   Bug2: VSA1 has a wrap bug so that using maximum sized DMA 
+-		   causes bad things. According to NatSemi VSA2 has another
+-		   bug to do with 'hlt'. I've not seen any boards using VSA2
+-		   and X doesn't seem to support it either so who cares 8).
+-		   VSA1 we work around however.
+-		*/
++		/*
++		 * It isn't really a PCI quirk directly, but the cure is the
++		 * same. The MediaGX has deep magic SMM stuff that handles the
++		 * SB emulation. It throws away the fifo on disable_dma() which
++		 * is wrong and ruins the audio.
++		 *
++		 *  Bug2: VSA1 has a wrap bug so that using maximum sized DMA
++		 *  causes bad things. According to NatSemi VSA2 has another
++		 *  bug to do with 'hlt'. I've not seen any boards using VSA2
++		 *  and X doesn't seem to support it either so who cares 8).
++		 *  VSA1 we work around however.
++		 */
+ 
+ 		printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
+ 		isa_dma_bridge_buggy = 2;
+@@ -273,55 +275,51 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ 
+ 		/*
+ 		 *  The 5510/5520 companion chips have a funky PIT.
+-		 */  
++		 */
+ 		if (vendor == PCI_VENDOR_ID_CYRIX &&
+ 	 (device == PCI_DEVICE_ID_CYRIX_5510 || device == PCI_DEVICE_ID_CYRIX_5520))
+ 			mark_tsc_unstable("cyrix 5510/5520 detected");
+ 	}
+ #endif
+-		c->x86_cache_size=16;	/* Yep 16K integrated cache thats it */
++		c->x86_cache_size = 16;	/* Yep 16K integrated cache thats it */
+ 
+ 		/* GXm supports extended cpuid levels 'ala' AMD */
+ 		if (c->cpuid_level == 2) {
+ 			/* Enable cxMMX extensions (GX1 Datasheet 54) */
+ 			setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
+-			
++
+ 			/*
+ 			 * GXm : 0x30 ... 0x5f GXm  datasheet 51
+ 			 * GXlv: 0x6x          GXlv datasheet 54
+ 			 *  ?  : 0x7x
+ 			 * GX1 : 0x8x          GX1  datasheet 56
+ 			 */
+-			if((0x30 <= dir1 && dir1 <= 0x6f) || (0x80 <=dir1 && dir1 <= 0x8f))
++			if ((0x30 <= dir1 && dir1 <= 0x6f) || (0x80 <= dir1 && dir1 <= 0x8f))
+ 				geode_configure();
+ 			get_model_name(c);  /* get CPU marketing name */
+ 			return;
+-		}
+-		else {  /* MediaGX */
++		} else { /* MediaGX */
+ 			Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
+ 			p = Cx86_cb+2;
+ 			c->x86_model = (dir1 & 0x20) ? 1 : 2;
+ 		}
+ 		break;
+ 
+-        case 5: /* 6x86MX/M II */
+-		if (dir1 > 7)
+-		{
++	case 5: /* 6x86MX/M II */
++		if (dir1 > 7) {
+ 			dir0_msn++;  /* M II */
+ 			/* Enable MMX extensions (App note 108) */
+ 			setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
+-		}
+-		else
+-		{
++		} else {
+ 			c->coma_bug = 1;      /* 6x86MX, it has the bug. */
+ 		}
+ 		tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
+ 		Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
+ 		p = Cx86_cb+tmp;
+-        	if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
++		if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
+ 			(c->x86_model)++;
+ 		/* Emulate MTRRs using Cyrix's ARRs. */
+-		set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
+ 		break;
+ 
+ 	case 0xf:  /* Cyrix 486 without DEVID registers */
+@@ -343,7 +341,8 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ 		break;
+ 	}
+ 	strcpy(buf, Cx86_model[dir0_msn & 7]);
+-	if (p) strcat(buf, p);
++	if (p)
++		strcat(buf, p);
+ 	return;
+ }
+ 
+@@ -352,7 +351,8 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+  */
+ static void __cpuinit init_nsc(struct cpuinfo_x86 *c)
+ {
+-	/* There may be GX1 processors in the wild that are branded
++	/*
++	 * There may be GX1 processors in the wild that are branded
+ 	 * NSC and not Cyrix.
+ 	 *
+ 	 * This function only handles the GX processor, and kicks every
+@@ -377,7 +377,7 @@ static void __cpuinit init_nsc(struct cpuinfo_x86 *c)
+  * by the fact that they preserve the flags across the division of 5/2.
+  * PII and PPro exhibit this behavior too, but they have cpuid available.
+  */
+- 
++
+ /*
+  * Perform the Cyrix 5/2 test. A Cyrix won't change
+  * the flags, while other 486 chips will.
+@@ -398,27 +398,26 @@ static inline int test_cyrix_52div(void)
+ 	return (unsigned char) (test >> 8) == 0x02;
+ }
+ 
+-static void __cpuinit cyrix_identify(struct cpuinfo_x86 * c)
++static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c)
+ {
+ 	/* Detect Cyrix with disabled CPUID */
+-	if ( c->x86 == 4 && test_cyrix_52div() ) {
++	if (c->x86 == 4 && test_cyrix_52div()) {
+ 		unsigned char dir0, dir1;
+-		
++
+ 		strcpy(c->x86_vendor_id, "CyrixInstead");
+-	        c->x86_vendor = X86_VENDOR_CYRIX;
+-	        
+-	        /* Actually enable cpuid on the older cyrix */
+-	    
+-	    	/* Retrieve CPU revisions */
+-	    	
++		c->x86_vendor = X86_VENDOR_CYRIX;
++
++		/* Actually enable cpuid on the older cyrix */
++
++		/* Retrieve CPU revisions */
++
+ 		do_cyrix_devid(&dir0, &dir1);
+ 
+-		dir0>>=4;		
+-		
++		dir0 >>= 4;
++
+ 		/* Check it is an affected model */
+-		
+-   	        if (dir0 == 5 || dir0 == 3)
+-   	        {
++
++		if (dir0 == 5 || dir0 == 3) {
+ 			unsigned char ccr3;
+ 			unsigned long flags;
+ 			printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
+@@ -434,26 +433,17 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 * c)
+ 
+ static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
+ 	.c_vendor	= "Cyrix",
+-	.c_ident 	= { "CyrixInstead" },
++	.c_ident	= { "CyrixInstead" },
+ 	.c_init		= init_cyrix,
+ 	.c_identify	= cyrix_identify,
+ };
+ 
+-int __init cyrix_init_cpu(void)
+-{
+-	cpu_devs[X86_VENDOR_CYRIX] = &cyrix_cpu_dev;
+-	return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_CYRIX, &cyrix_cpu_dev);
+ 
+ static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
+ 	.c_vendor	= "NSC",
+-	.c_ident 	= { "Geode by NSC" },
++	.c_ident	= { "Geode by NSC" },
+ 	.c_init		= init_nsc,
+ };
+ 
+-int __init nsc_init_cpu(void)
+-{
+-	cpu_devs[X86_VENDOR_NSC] = &nsc_cpu_dev;
+-	return 0;
+-}
+-
++cpu_vendor_dev_register(X86_VENDOR_NSC, &nsc_cpu_dev);
+diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c
+index ee975ac..e43ad4a 100644
+--- a/arch/x86/kernel/cpu/feature_names.c
++++ b/arch/x86/kernel/cpu/feature_names.c
+@@ -4,7 +4,7 @@
+  * This file must not contain any executable code.
+  */
+ 
+-#include "asm/cpufeature.h"
++#include <asm/cpufeature.h>
+ 
+ /*
+  * These flag bits must match the definitions in <asm/cpufeature.h>.
+diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
+index fae31ce..fe9224c 100644
+--- a/arch/x86/kernel/cpu/intel.c
++++ b/arch/x86/kernel/cpu/intel.c
+@@ -30,7 +30,7 @@
+ struct movsl_mask movsl_mask __read_mostly;
+ #endif
+ 
+-void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
++static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
+ {
+ 	/* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */
+ 	if (c->x86 == 15 && c->x86_cache_alignment == 64)
+@@ -45,7 +45,7 @@ void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
+  *
+  *	This is called before we do cpu ident work
+  */
+- 
++
+ int __cpuinit ppro_with_ram_bug(void)
+ {
+ 	/* Uses data from early_cpu_detect now */
+@@ -58,7 +58,7 @@ int __cpuinit ppro_with_ram_bug(void)
+ 	}
+ 	return 0;
+ }
+-	
++
+ 
+ /*
+  * P4 Xeon errata 037 workaround.
+@@ -69,7 +69,7 @@ static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c)
+ 	unsigned long lo, hi;
+ 
+ 	if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) {
+-		rdmsr (MSR_IA32_MISC_ENABLE, lo, hi);
++		rdmsr(MSR_IA32_MISC_ENABLE, lo, hi);
+ 		if ((lo & (1<<9)) == 0) {
+ 			printk (KERN_INFO "CPU: C0 stepping P4 Xeon detected.\n");
+ 			printk (KERN_INFO "CPU: Disabling hardware prefetching (Errata 037)\n");
+@@ -127,10 +127,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ 	 */
+ 	c->f00f_bug = 0;
+ 	if (!paravirt_enabled() && c->x86 == 5) {
+-		static int f00f_workaround_enabled = 0;
++		static int f00f_workaround_enabled;
+ 
+ 		c->f00f_bug = 1;
+-		if ( !f00f_workaround_enabled ) {
++		if (!f00f_workaround_enabled) {
+ 			trap_init_f00f_bug();
+ 			printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n");
+ 			f00f_workaround_enabled = 1;
+@@ -139,20 +139,22 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ #endif
+ 
+ 	l2 = init_intel_cacheinfo(c);
+-	if (c->cpuid_level > 9 ) {
++	if (c->cpuid_level > 9) {
+ 		unsigned eax = cpuid_eax(10);
+ 		/* Check for version and the number of counters */
+ 		if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
+-			set_bit(X86_FEATURE_ARCH_PERFMON, c->x86_capability);
++			set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
+ 	}
+ 
+ 	/* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
+ 	if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
+-		clear_bit(X86_FEATURE_SEP, c->x86_capability);
++		clear_cpu_cap(c, X86_FEATURE_SEP);
+ 
+-	/* Names for the Pentium II/Celeron processors 
+-	   detectable only by also checking the cache size.
+-	   Dixon is NOT a Celeron. */
++	/*
++	 * Names for the Pentium II/Celeron processors
++	 * detectable only by also checking the cache size.
++	 * Dixon is NOT a Celeron.
++	 */
+ 	if (c->x86 == 6) {
+ 		switch (c->x86_model) {
+ 		case 5:
+@@ -163,14 +165,14 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ 					p = "Mobile Pentium II (Dixon)";
+ 			}
+ 			break;
+-			
++
+ 		case 6:
+ 			if (l2 == 128)
+ 				p = "Celeron (Mendocino)";
+ 			else if (c->x86_mask == 0 || c->x86_mask == 5)
+ 				p = "Celeron-A";
+ 			break;
+-			
++
+ 		case 8:
+ 			if (l2 == 128)
+ 				p = "Celeron (Coppermine)";
+@@ -178,9 +180,9 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ 		}
+ 	}
+ 
+-	if ( p )
++	if (p)
+ 		strcpy(c->x86_model_id, p);
+-	
++
+ 	c->x86_max_cores = num_cpu_cores(c);
+ 
+ 	detect_ht(c);
+@@ -207,28 +209,29 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ #endif
+ 
+ 	if (cpu_has_xmm2)
+-		set_bit(X86_FEATURE_LFENCE_RDTSC, c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
+ 	if (c->x86 == 15) {
+-		set_bit(X86_FEATURE_P4, c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_P4);
+ 	}
+-	if (c->x86 == 6) 
+-		set_bit(X86_FEATURE_P3, c->x86_capability);
++	if (c->x86 == 6)
++		set_cpu_cap(c, X86_FEATURE_P3);
+ 	if (cpu_has_ds) {
+ 		unsigned int l1;
+ 		rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
+ 		if (!(l1 & (1<<11)))
+-			set_bit(X86_FEATURE_BTS, c->x86_capability);
++			set_cpu_cap(c, X86_FEATURE_BTS);
+ 		if (!(l1 & (1<<12)))
+-			set_bit(X86_FEATURE_PEBS, c->x86_capability);
++			set_cpu_cap(c, X86_FEATURE_PEBS);
+ 	}
+ 
+ 	if (cpu_has_bts)
+ 		ds_init_intel(c);
+ }
+ 
+-static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
++static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned int size)
+ {
+-	/* Intel PIII Tualatin. This comes in two flavours.
++	/*
++	 * Intel PIII Tualatin. This comes in two flavours.
+ 	 * One has 256kb of cache, the other 512. We have no way
+ 	 * to determine which, so we use a boottime override
+ 	 * for the 512kb model, and assume 256 otherwise.
+@@ -240,42 +243,42 @@ static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned
+ 
+ static struct cpu_dev intel_cpu_dev __cpuinitdata = {
+ 	.c_vendor	= "Intel",
+-	.c_ident 	= { "GenuineIntel" },
++	.c_ident	= { "GenuineIntel" },
+ 	.c_models = {
+-		{ .vendor = X86_VENDOR_INTEL, .family = 4, .model_names = 
+-		  { 
+-			  [0] = "486 DX-25/33", 
+-			  [1] = "486 DX-50", 
+-			  [2] = "486 SX", 
+-			  [3] = "486 DX/2", 
+-			  [4] = "486 SL", 
+-			  [5] = "486 SX/2", 
+-			  [7] = "486 DX/2-WB", 
+-			  [8] = "486 DX/4", 
++		{ .vendor = X86_VENDOR_INTEL, .family = 4, .model_names =
++		  {
++			  [0] = "486 DX-25/33",
++			  [1] = "486 DX-50",
++			  [2] = "486 SX",
++			  [3] = "486 DX/2",
++			  [4] = "486 SL",
++			  [5] = "486 SX/2",
++			  [7] = "486 DX/2-WB",
++			  [8] = "486 DX/4",
+ 			  [9] = "486 DX/4-WB"
+ 		  }
+ 		},
+ 		{ .vendor = X86_VENDOR_INTEL, .family = 5, .model_names =
+-		  { 
+-			  [0] = "Pentium 60/66 A-step", 
+-			  [1] = "Pentium 60/66", 
++		  {
++			  [0] = "Pentium 60/66 A-step",
++			  [1] = "Pentium 60/66",
+ 			  [2] = "Pentium 75 - 200",
+-			  [3] = "OverDrive PODP5V83", 
++			  [3] = "OverDrive PODP5V83",
+ 			  [4] = "Pentium MMX",
+-			  [7] = "Mobile Pentium 75 - 200", 
++			  [7] = "Mobile Pentium 75 - 200",
+ 			  [8] = "Mobile Pentium MMX"
+ 		  }
+ 		},
+ 		{ .vendor = X86_VENDOR_INTEL, .family = 6, .model_names =
+-		  { 
++		  {
+ 			  [0] = "Pentium Pro A-step",
+-			  [1] = "Pentium Pro", 
+-			  [3] = "Pentium II (Klamath)", 
+-			  [4] = "Pentium II (Deschutes)", 
+-			  [5] = "Pentium II (Deschutes)", 
++			  [1] = "Pentium Pro",
++			  [3] = "Pentium II (Klamath)",
++			  [4] = "Pentium II (Deschutes)",
++			  [5] = "Pentium II (Deschutes)",
+ 			  [6] = "Mobile Pentium II",
+-			  [7] = "Pentium III (Katmai)", 
+-			  [8] = "Pentium III (Coppermine)", 
++			  [7] = "Pentium III (Katmai)",
++			  [8] = "Pentium III (Coppermine)",
+ 			  [10] = "Pentium III (Cascades)",
+ 			  [11] = "Pentium III (Tualatin)",
+ 		  }
+@@ -290,15 +293,12 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = {
+ 		  }
+ 		},
+ 	},
++	.c_early_init   = early_init_intel,
+ 	.c_init		= init_intel,
+ 	.c_size_cache	= intel_size_cache,
+ };
+ 
+-__init int intel_cpu_init(void)
+-{
+-	cpu_devs[X86_VENDOR_INTEL] = &intel_cpu_dev;
+-	return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev);
+ 
+ #ifndef CONFIG_X86_CMPXCHG
+ unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new)
+@@ -364,5 +364,5 @@ unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new)
+ EXPORT_SYMBOL(cmpxchg_486_u64);
+ #endif
+ 
+-// arch_initcall(intel_cpu_init);
++/* arch_initcall(intel_cpu_init); */
+ 
+diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
+index 1b88986..26d615d 100644
+--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
++++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
+@@ -129,7 +129,7 @@ struct _cpuid4_info {
+ 	union _cpuid4_leaf_ebx ebx;
+ 	union _cpuid4_leaf_ecx ecx;
+ 	unsigned long size;
+-	cpumask_t shared_cpu_map;
++	cpumask_t shared_cpu_map;	/* future?: only cpus/node is needed */
+ };
+ 
+ unsigned short			num_cache_leaves;
+@@ -451,8 +451,8 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
+ }
+ 
+ /* pointer to _cpuid4_info array (for each cache leaf) */
+-static struct _cpuid4_info *cpuid4_info[NR_CPUS];
+-#define CPUID4_INFO_IDX(x,y)    (&((cpuid4_info[x])[y]))
++static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info);
++#define CPUID4_INFO_IDX(x, y)    (&((per_cpu(cpuid4_info, x))[y]))
+ 
+ #ifdef CONFIG_SMP
+ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+@@ -474,7 +474,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+ 			if (cpu_data(i).apicid >> index_msb ==
+ 			    c->apicid >> index_msb) {
+ 				cpu_set(i, this_leaf->shared_cpu_map);
+-				if (i != cpu && cpuid4_info[i])  {
++				if (i != cpu && per_cpu(cpuid4_info, i))  {
+ 					sibling_leaf = CPUID4_INFO_IDX(i, index);
+ 					cpu_set(cpu, sibling_leaf->shared_cpu_map);
+ 				}
+@@ -505,8 +505,8 @@ static void __cpuinit free_cache_attributes(unsigned int cpu)
+ 	for (i = 0; i < num_cache_leaves; i++)
+ 		cache_remove_shared_cpu_map(cpu, i);
+ 
+-	kfree(cpuid4_info[cpu]);
+-	cpuid4_info[cpu] = NULL;
++	kfree(per_cpu(cpuid4_info, cpu));
++	per_cpu(cpuid4_info, cpu) = NULL;
+ }
+ 
+ static int __cpuinit detect_cache_attributes(unsigned int cpu)
+@@ -519,13 +519,13 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
+ 	if (num_cache_leaves == 0)
+ 		return -ENOENT;
+ 
+-	cpuid4_info[cpu] = kzalloc(
++	per_cpu(cpuid4_info, cpu) = kzalloc(
+ 	    sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
+-	if (cpuid4_info[cpu] == NULL)
++	if (per_cpu(cpuid4_info, cpu) == NULL)
+ 		return -ENOMEM;
+ 
+ 	oldmask = current->cpus_allowed;
+-	retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
++	retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 	if (retval)
+ 		goto out;
+ 
+@@ -542,12 +542,12 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
+ 		}
+ 		cache_shared_cpu_map_setup(cpu, j);
+ 	}
+-	set_cpus_allowed(current, oldmask);
++	set_cpus_allowed_ptr(current, &oldmask);
+ 
+ out:
+ 	if (retval) {
+-		kfree(cpuid4_info[cpu]);
+-		cpuid4_info[cpu] = NULL;
++		kfree(per_cpu(cpuid4_info, cpu));
++		per_cpu(cpuid4_info, cpu) = NULL;
+ 	}
+ 
+ 	return retval;
+@@ -561,7 +561,7 @@ out:
+ extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
+ 
+ /* pointer to kobject for cpuX/cache */
+-static struct kobject * cache_kobject[NR_CPUS];
++static DEFINE_PER_CPU(struct kobject *, cache_kobject);
+ 
+ struct _index_kobject {
+ 	struct kobject kobj;
+@@ -570,8 +570,8 @@ struct _index_kobject {
+ };
+ 
+ /* pointer to array of kobjects for cpuX/cache/indexY */
+-static struct _index_kobject *index_kobject[NR_CPUS];
+-#define INDEX_KOBJECT_PTR(x,y)    (&((index_kobject[x])[y]))
++static DEFINE_PER_CPU(struct _index_kobject *, index_kobject);
++#define INDEX_KOBJECT_PTR(x, y)    (&((per_cpu(index_kobject, x))[y]))
+ 
+ #define show_one_plus(file_name, object, val)				\
+ static ssize_t show_##file_name						\
+@@ -591,11 +591,32 @@ static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
+ 	return sprintf (buf, "%luK\n", this_leaf->size / 1024);
+ }
+ 
+-static ssize_t show_shared_cpu_map(struct _cpuid4_info *this_leaf, char *buf)
++static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
++					int type, char *buf)
+ {
+-	char mask_str[NR_CPUS];
+-	cpumask_scnprintf(mask_str, NR_CPUS, this_leaf->shared_cpu_map);
+-	return sprintf(buf, "%s\n", mask_str);
++	ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
++	int n = 0;
++
++	if (len > 1) {
++		cpumask_t *mask = &this_leaf->shared_cpu_map;
++
++		n = type?
++			cpulist_scnprintf(buf, len-2, *mask):
++			cpumask_scnprintf(buf, len-2, *mask);
++		buf[n++] = '\n';
++		buf[n] = '\0';
++	}
++	return n;
++}
++
++static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf)
++{
++	return show_shared_cpu_map_func(leaf, 0, buf);
++}
++
++static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf)
++{
++	return show_shared_cpu_map_func(leaf, 1, buf);
+ }
+ 
+ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) {
+@@ -633,6 +654,7 @@ define_one_ro(ways_of_associativity);
+ define_one_ro(number_of_sets);
+ define_one_ro(size);
+ define_one_ro(shared_cpu_map);
++define_one_ro(shared_cpu_list);
+ 
+ static struct attribute * default_attrs[] = {
+ 	&type.attr,
+@@ -643,6 +665,7 @@ static struct attribute * default_attrs[] = {
+ 	&number_of_sets.attr,
+ 	&size.attr,
+ 	&shared_cpu_map.attr,
++	&shared_cpu_list.attr,
+ 	NULL
+ };
+ 
+@@ -684,10 +707,10 @@ static struct kobj_type ktype_percpu_entry = {
+ 
+ static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu)
+ {
+-	kfree(cache_kobject[cpu]);
+-	kfree(index_kobject[cpu]);
+-	cache_kobject[cpu] = NULL;
+-	index_kobject[cpu] = NULL;
++	kfree(per_cpu(cache_kobject, cpu));
++	kfree(per_cpu(index_kobject, cpu));
++	per_cpu(cache_kobject, cpu) = NULL;
++	per_cpu(index_kobject, cpu) = NULL;
+ 	free_cache_attributes(cpu);
+ }
+ 
+@@ -703,13 +726,14 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
+ 		return err;
+ 
+ 	/* Allocate all required memory */
+-	cache_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL);
+-	if (unlikely(cache_kobject[cpu] == NULL))
++	per_cpu(cache_kobject, cpu) =
++		kzalloc(sizeof(struct kobject), GFP_KERNEL);
++	if (unlikely(per_cpu(cache_kobject, cpu) == NULL))
+ 		goto err_out;
+ 
+-	index_kobject[cpu] = kzalloc(
++	per_cpu(index_kobject, cpu) = kzalloc(
+ 	    sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
+-	if (unlikely(index_kobject[cpu] == NULL))
++	if (unlikely(per_cpu(index_kobject, cpu) == NULL))
+ 		goto err_out;
+ 
+ 	return 0;
+@@ -733,7 +757,8 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
+ 	if (unlikely(retval < 0))
+ 		return retval;
+ 
+-	retval = kobject_init_and_add(cache_kobject[cpu], &ktype_percpu_entry,
++	retval = kobject_init_and_add(per_cpu(cache_kobject, cpu),
++				      &ktype_percpu_entry,
+ 				      &sys_dev->kobj, "%s", "cache");
+ 	if (retval < 0) {
+ 		cpuid4_cache_sysfs_exit(cpu);
+@@ -745,13 +770,14 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
+ 		this_object->cpu = cpu;
+ 		this_object->index = i;
+ 		retval = kobject_init_and_add(&(this_object->kobj),
+-					      &ktype_cache, cache_kobject[cpu],
++					      &ktype_cache,
++					      per_cpu(cache_kobject, cpu),
+ 					      "index%1lu", i);
+ 		if (unlikely(retval)) {
+ 			for (j = 0; j < i; j++) {
+ 				kobject_put(&(INDEX_KOBJECT_PTR(cpu,j)->kobj));
+ 			}
+-			kobject_put(cache_kobject[cpu]);
++			kobject_put(per_cpu(cache_kobject, cpu));
+ 			cpuid4_cache_sysfs_exit(cpu);
+ 			break;
+ 		}
+@@ -760,7 +786,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
+ 	if (!retval)
+ 		cpu_set(cpu, cache_dev_map);
+ 
+-	kobject_uevent(cache_kobject[cpu], KOBJ_ADD);
++	kobject_uevent(per_cpu(cache_kobject, cpu), KOBJ_ADD);
+ 	return retval;
+ }
+ 
+@@ -769,7 +795,7 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
+ 	unsigned int cpu = sys_dev->id;
+ 	unsigned long i;
+ 
+-	if (cpuid4_info[cpu] == NULL)
++	if (per_cpu(cpuid4_info, cpu) == NULL)
+ 		return;
+ 	if (!cpu_isset(cpu, cache_dev_map))
+ 		return;
+@@ -777,7 +803,7 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
+ 
+ 	for (i = 0; i < num_cache_leaves; i++)
+ 		kobject_put(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
+-	kobject_put(cache_kobject[cpu]);
++	kobject_put(per_cpu(cache_kobject, cpu));
+ 	cpuid4_cache_sysfs_exit(cpu);
+ }
+ 
+diff --git a/arch/x86/kernel/cpu/mcheck/mce_32.c b/arch/x86/kernel/cpu/mcheck/mce_32.c
+index a5182dc..774d87c 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce_32.c
++++ b/arch/x86/kernel/cpu/mcheck/mce_32.c
+@@ -10,20 +10,20 @@
+ #include <linux/smp.h>
+ #include <linux/thread_info.h>
+ 
+-#include <asm/processor.h> 
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/mce.h>
+ 
+ #include "mce.h"
+ 
+-int mce_disabled = 0;
++int mce_disabled;
+ int nr_mce_banks;
+ 
+ EXPORT_SYMBOL_GPL(nr_mce_banks);	/* non-fatal.o */
+ 
+ /* Handle unconfigured int18 (should never happen) */
+-static void unexpected_machine_check(struct pt_regs * regs, long error_code)
+-{	
++static void unexpected_machine_check(struct pt_regs *regs, long error_code)
++{
+ 	printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
+ }
+ 
+@@ -33,30 +33,30 @@ void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_mac
+ /* This has to be run for each processor */
+ void mcheck_init(struct cpuinfo_x86 *c)
+ {
+-	if (mce_disabled==1)
++	if (mce_disabled == 1)
+ 		return;
+ 
+ 	switch (c->x86_vendor) {
+-		case X86_VENDOR_AMD:
+-			amd_mcheck_init(c);
+-			break;
+-
+-		case X86_VENDOR_INTEL:
+-			if (c->x86==5)
+-				intel_p5_mcheck_init(c);
+-			if (c->x86==6)
+-				intel_p6_mcheck_init(c);
+-			if (c->x86==15)
+-				intel_p4_mcheck_init(c);
+-			break;
+-
+-		case X86_VENDOR_CENTAUR:
+-			if (c->x86==5)
+-				winchip_mcheck_init(c);
+-			break;
+-
+-		default:
+-			break;
++	case X86_VENDOR_AMD:
++		amd_mcheck_init(c);
++		break;
++
++	case X86_VENDOR_INTEL:
++		if (c->x86 == 5)
++			intel_p5_mcheck_init(c);
++		if (c->x86 == 6)
++			intel_p6_mcheck_init(c);
++		if (c->x86 == 15)
++			intel_p4_mcheck_init(c);
++		break;
++
++	case X86_VENDOR_CENTAUR:
++		if (c->x86 == 5)
++			winchip_mcheck_init(c);
++		break;
++
++	default:
++		break;
+ 	}
+ }
+ 
+diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
+index 9a699ed..e07e8c0 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
++++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
+@@ -49,7 +49,7 @@ static int banks;
+ static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL };
+ static unsigned long notify_user;
+ static int rip_msr;
+-static int mce_bootlog = 1;
++static int mce_bootlog = -1;
+ static atomic_t mce_events;
+ 
+ static char trigger[128];
+@@ -471,13 +471,15 @@ static void mce_init(void *dummy)
+ static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
+ {
+ 	/* This should be disabled by the BIOS, but isn't always */
+-	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 15) {
+-		/* disable GART TBL walk error reporting, which trips off
+-		   incorrectly with the IOMMU & 3ware & Cerberus. */
+-		clear_bit(10, &bank[4]);
+-		/* Lots of broken BIOS around that don't clear them
+-		   by default and leave crap in there. Don't log. */
+-		mce_bootlog = 0;
++	if (c->x86_vendor == X86_VENDOR_AMD) {
++		if(c->x86 == 15)
++			/* disable GART TBL walk error reporting, which trips off
++			   incorrectly with the IOMMU & 3ware & Cerberus. */
++			clear_bit(10, &bank[4]);
++		if(c->x86 <= 17 && mce_bootlog < 0)
++			/* Lots of broken BIOS around that don't clear them
++			   by default and leave crap in there. Don't log. */
++			mce_bootlog = 0;
+ 	}
+ 
+ }
+diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+index 32671da..7c9a813 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
++++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+@@ -251,18 +251,18 @@ struct threshold_attr {
+ 	ssize_t(*store) (struct threshold_block *, const char *, size_t count);
+ };
+ 
+-static cpumask_t affinity_set(unsigned int cpu)
++static void affinity_set(unsigned int cpu, cpumask_t *oldmask,
++					   cpumask_t *newmask)
+ {
+-	cpumask_t oldmask = current->cpus_allowed;
+-	cpumask_t newmask = CPU_MASK_NONE;
+-	cpu_set(cpu, newmask);
+-	set_cpus_allowed(current, newmask);
+-	return oldmask;
++	*oldmask = current->cpus_allowed;
++	cpus_clear(*newmask);
++	cpu_set(cpu, *newmask);
++	set_cpus_allowed_ptr(current, newmask);
+ }
+ 
+-static void affinity_restore(cpumask_t oldmask)
++static void affinity_restore(const cpumask_t *oldmask)
+ {
+-	set_cpus_allowed(current, oldmask);
++	set_cpus_allowed_ptr(current, oldmask);
+ }
+ 
+ #define SHOW_FIELDS(name)                                           \
+@@ -277,15 +277,15 @@ static ssize_t store_interrupt_enable(struct threshold_block *b,
+ 				      const char *buf, size_t count)
+ {
+ 	char *end;
+-	cpumask_t oldmask;
++	cpumask_t oldmask, newmask;
+ 	unsigned long new = simple_strtoul(buf, &end, 0);
+ 	if (end == buf)
+ 		return -EINVAL;
+ 	b->interrupt_enable = !!new;
+ 
+-	oldmask = affinity_set(b->cpu);
++	affinity_set(b->cpu, &oldmask, &newmask);
+ 	threshold_restart_bank(b, 0, 0);
+-	affinity_restore(oldmask);
++	affinity_restore(&oldmask);
+ 
+ 	return end - buf;
+ }
+@@ -294,7 +294,7 @@ static ssize_t store_threshold_limit(struct threshold_block *b,
+ 				     const char *buf, size_t count)
+ {
+ 	char *end;
+-	cpumask_t oldmask;
++	cpumask_t oldmask, newmask;
+ 	u16 old;
+ 	unsigned long new = simple_strtoul(buf, &end, 0);
+ 	if (end == buf)
+@@ -306,9 +306,9 @@ static ssize_t store_threshold_limit(struct threshold_block *b,
+ 	old = b->threshold_limit;
+ 	b->threshold_limit = new;
+ 
+-	oldmask = affinity_set(b->cpu);
++	affinity_set(b->cpu, &oldmask, &newmask);
+ 	threshold_restart_bank(b, 0, old);
+-	affinity_restore(oldmask);
++	affinity_restore(&oldmask);
+ 
+ 	return end - buf;
+ }
+@@ -316,10 +316,10 @@ static ssize_t store_threshold_limit(struct threshold_block *b,
+ static ssize_t show_error_count(struct threshold_block *b, char *buf)
+ {
+ 	u32 high, low;
+-	cpumask_t oldmask;
+-	oldmask = affinity_set(b->cpu);
++	cpumask_t oldmask, newmask;
++	affinity_set(b->cpu, &oldmask, &newmask);
+ 	rdmsr(b->address, low, high);
+-	affinity_restore(oldmask);
++	affinity_restore(&oldmask);
+ 	return sprintf(buf, "%x\n",
+ 		       (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit));
+ }
+@@ -327,10 +327,10 @@ static ssize_t show_error_count(struct threshold_block *b, char *buf)
+ static ssize_t store_error_count(struct threshold_block *b,
+ 				 const char *buf, size_t count)
+ {
+-	cpumask_t oldmask;
+-	oldmask = affinity_set(b->cpu);
++	cpumask_t oldmask, newmask;
++	affinity_set(b->cpu, &oldmask, &newmask);
+ 	threshold_restart_bank(b, 1, 0);
+-	affinity_restore(oldmask);
++	affinity_restore(&oldmask);
+ 	return 1;
+ }
+ 
+@@ -468,7 +468,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
+ {
+ 	int i, err = 0;
+ 	struct threshold_bank *b = NULL;
+-	cpumask_t oldmask = CPU_MASK_NONE;
++	cpumask_t oldmask, newmask;
+ 	char name[32];
+ 
+ 	sprintf(name, "threshold_bank%i", bank);
+@@ -519,10 +519,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
+ 
+ 	per_cpu(threshold_banks, cpu)[bank] = b;
+ 
+-	oldmask = affinity_set(cpu);
++	affinity_set(cpu, &oldmask, &newmask);
+ 	err = allocate_threshold_blocks(cpu, bank, 0,
+ 					MSR_IA32_MC0_MISC + bank * 4);
+-	affinity_restore(oldmask);
++	affinity_restore(&oldmask);
+ 
+ 	if (err)
+ 		goto out_free;
+diff --git a/arch/x86/kernel/cpu/mcheck/non-fatal.c b/arch/x86/kernel/cpu/mcheck/non-fatal.c
+index bf39409..00ccb6c 100644
+--- a/arch/x86/kernel/cpu/mcheck/non-fatal.c
++++ b/arch/x86/kernel/cpu/mcheck/non-fatal.c
+@@ -16,7 +16,7 @@
+ #include <linux/smp.h>
+ #include <linux/module.h>
+ 
+-#include <asm/processor.h> 
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/msr.h>
+ 
+@@ -26,23 +26,26 @@ static int firstbank;
+ 
+ #define MCE_RATE	15*HZ	/* timer rate is 15s */
+ 
+-static void mce_checkregs (void *info)
++static void mce_checkregs(void *info)
+ {
+ 	u32 low, high;
+ 	int i;
+ 
+-	for (i=firstbank; i<nr_mce_banks; i++) {
+-		rdmsr (MSR_IA32_MC0_STATUS+i*4, low, high);
++	for (i = firstbank; i < nr_mce_banks; i++) {
++		rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high);
+ 
+ 		if (high & (1<<31)) {
+ 			printk(KERN_INFO "MCE: The hardware reports a non "
+ 				"fatal, correctable incident occurred on "
+ 				"CPU %d.\n",
+ 				smp_processor_id());
+-			printk (KERN_INFO "Bank %d: %08x%08x\n", i, high, low);
++			printk(KERN_INFO "Bank %d: %08x%08x\n", i, high, low);
+ 
+-			/* Scrub the error so we don't pick it up in MCE_RATE seconds time. */
+-			wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
++			/*
++			 * Scrub the error so we don't pick it up in MCE_RATE
++			 * seconds time.
++			 */
++			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
+ 
+ 			/* Serialize */
+ 			wmb();
+@@ -55,10 +58,10 @@ static void mce_work_fn(struct work_struct *work);
+ static DECLARE_DELAYED_WORK(mce_work, mce_work_fn);
+ 
+ static void mce_work_fn(struct work_struct *work)
+-{ 
++{
+ 	on_each_cpu(mce_checkregs, NULL, 1, 1);
+ 	schedule_delayed_work(&mce_work, round_jiffies_relative(MCE_RATE));
+-} 
++}
+ 
+ static int __init init_nonfatal_mce_checker(void)
+ {
+diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c
+index a18310a..bfa5817 100644
+--- a/arch/x86/kernel/cpu/mcheck/p5.c
++++ b/arch/x86/kernel/cpu/mcheck/p5.c
+@@ -9,20 +9,20 @@
+ #include <linux/interrupt.h>
+ #include <linux/smp.h>
+ 
+-#include <asm/processor.h> 
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/msr.h>
+ 
+ #include "mce.h"
+ 
+ /* Machine check handler for Pentium class Intel */
+-static void pentium_machine_check(struct pt_regs * regs, long error_code)
++static void pentium_machine_check(struct pt_regs *regs, long error_code)
+ {
+ 	u32 loaddr, hi, lotype;
+ 	rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
+ 	rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
+ 	printk(KERN_EMERG "CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
+-	if(lotype&(1<<5))
++	if (lotype&(1<<5))
+ 		printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
+ 	add_taint(TAINT_MACHINE_CHECK);
+ }
+@@ -31,13 +31,13 @@ static void pentium_machine_check(struct pt_regs * regs, long error_code)
+ void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
+ {
+ 	u32 l, h;
+-	
++
+ 	/*Check for MCE support */
+-	if( !cpu_has(c, X86_FEATURE_MCE) )
+-		return;	
++	if (!cpu_has(c, X86_FEATURE_MCE))
++		return;
+ 
+ 	/* Default P5 to off as its often misconnected */
+-	if(mce_disabled != -1)
++	if (mce_disabled != -1)
+ 		return;
+ 	machine_check_vector = pentium_machine_check;
+ 	wmb();
+@@ -47,7 +47,7 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
+ 	rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
+ 	printk(KERN_INFO "Intel old style machine check architecture supported.\n");
+ 
+- 	/* Enable MCE */
++	/* Enable MCE */
+ 	set_in_cr4(X86_CR4_MCE);
+ 	printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+ }
+diff --git a/arch/x86/kernel/cpu/mcheck/p6.c b/arch/x86/kernel/cpu/mcheck/p6.c
+index 7434260..62efc9c 100644
+--- a/arch/x86/kernel/cpu/mcheck/p6.c
++++ b/arch/x86/kernel/cpu/mcheck/p6.c
+@@ -9,23 +9,23 @@
+ #include <linux/interrupt.h>
+ #include <linux/smp.h>
+ 
+-#include <asm/processor.h> 
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/msr.h>
+ 
+ #include "mce.h"
+ 
+ /* Machine Check Handler For PII/PIII */
+-static void intel_machine_check(struct pt_regs * regs, long error_code)
++static void intel_machine_check(struct pt_regs *regs, long error_code)
+ {
+-	int recover=1;
++	int recover = 1;
+ 	u32 alow, ahigh, high, low;
+ 	u32 mcgstl, mcgsth;
+ 	int i;
+ 
+-	rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
++	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
+ 	if (mcgstl & (1<<0))	/* Recoverable ? */
+-		recover=0;
++		recover = 0;
+ 
+ 	printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
+ 		smp_processor_id(), mcgsth, mcgstl);
+@@ -55,30 +55,30 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
+ 	}
+ 
+ 	if (recover & 2)
+-		panic ("CPU context corrupt");
++		panic("CPU context corrupt");
+ 	if (recover & 1)
+-		panic ("Unable to continue");
++		panic("Unable to continue");
+ 
+-	printk (KERN_EMERG "Attempting to continue.\n");
+-	/* 
+-	 * Do not clear the MSR_IA32_MCi_STATUS if the error is not 
++	printk(KERN_EMERG "Attempting to continue.\n");
++	/*
++	 * Do not clear the MSR_IA32_MCi_STATUS if the error is not
+ 	 * recoverable/continuable.This will allow BIOS to look at the MSRs
+ 	 * for errors if the OS could not log the error.
+ 	 */
+-	for (i=0; i<nr_mce_banks; i++) {
++	for (i = 0; i < nr_mce_banks; i++) {
+ 		unsigned int msr;
+ 		msr = MSR_IA32_MC0_STATUS+i*4;
+-		rdmsr (msr,low, high);
++		rdmsr(msr, low, high);
+ 		if (high & (1<<31)) {
+ 			/* Clear it */
+-			wrmsr (msr, 0UL, 0UL);
++			wrmsr(msr, 0UL, 0UL);
+ 			/* Serialize */
+ 			wmb();
+ 			add_taint(TAINT_MACHINE_CHECK);
+ 		}
+ 	}
+ 	mcgstl &= ~(1<<2);
+-	wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
++	wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
+ }
+ 
+ /* Set up machine check reporting for processors with Intel style MCE */
+@@ -86,21 +86,21 @@ void intel_p6_mcheck_init(struct cpuinfo_x86 *c)
+ {
+ 	u32 l, h;
+ 	int i;
+-	
++
+ 	/* Check for MCE support */
+ 	if (!cpu_has(c, X86_FEATURE_MCE))
+ 		return;
+ 
+ 	/* Check for PPro style MCA */
+- 	if (!cpu_has(c, X86_FEATURE_MCA))
++	if (!cpu_has(c, X86_FEATURE_MCA))
+ 		return;
+ 
+ 	/* Ok machine check is available */
+ 	machine_check_vector = intel_machine_check;
+ 	wmb();
+ 
+-	printk (KERN_INFO "Intel machine check architecture supported.\n");
+-	rdmsr (MSR_IA32_MCG_CAP, l, h);
++	printk(KERN_INFO "Intel machine check architecture supported.\n");
++	rdmsr(MSR_IA32_MCG_CAP, l, h);
+ 	if (l & (1<<8))	/* Control register present ? */
+ 		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
+ 	nr_mce_banks = l & 0xff;
+@@ -110,13 +110,13 @@ void intel_p6_mcheck_init(struct cpuinfo_x86 *c)
+ 	 * - MC0_CTL should not be written
+ 	 * - Status registers on all banks should be cleared on reset
+ 	 */
+-	for (i=1; i<nr_mce_banks; i++)
+-		wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
++	for (i = 1; i < nr_mce_banks; i++)
++		wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
+ 
+-	for (i=0; i<nr_mce_banks; i++)
+-		wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
++	for (i = 0; i < nr_mce_banks; i++)
++		wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
+ 
+-	set_in_cr4 (X86_CR4_MCE);
+-	printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
++	set_in_cr4(X86_CR4_MCE);
++	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
+ 		smp_processor_id());
+ }
+diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
+index 9b7e01d..1f4cc48 100644
+--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
++++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
+@@ -1,5 +1,4 @@
+ /*
+- * linux/arch/i386/kernel/cpu/mcheck/therm_throt.c
+  *
+  * Thermal throttle event support code (such as syslog messaging and rate
+  * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
+diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c
+index 3d428d5..f2be3e1 100644
+--- a/arch/x86/kernel/cpu/mcheck/winchip.c
++++ b/arch/x86/kernel/cpu/mcheck/winchip.c
+@@ -8,14 +8,14 @@
+ #include <linux/kernel.h>
+ #include <linux/interrupt.h>
+ 
+-#include <asm/processor.h> 
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/msr.h>
+ 
+ #include "mce.h"
+ 
+ /* Machine check handler for WinChip C6 */
+-static void winchip_machine_check(struct pt_regs * regs, long error_code)
++static void winchip_machine_check(struct pt_regs *regs, long error_code)
+ {
+ 	printk(KERN_EMERG "CPU0: Machine Check Exception.\n");
+ 	add_taint(TAINT_MACHINE_CHECK);
+@@ -28,8 +28,8 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c)
+ 	machine_check_vector = winchip_machine_check;
+ 	wmb();
+ 	rdmsr(MSR_IDT_FCR1, lo, hi);
+-	lo|= (1<<2);	/* Enable EIERRINT (int 18 MCE) */
+-	lo&= ~(1<<4);	/* Enable MCE */
++	lo |= (1<<2);	/* Enable EIERRINT (int 18 MCE) */
++	lo &= ~(1<<4);	/* Enable MCE */
+ 	wrmsr(MSR_IDT_FCR1, lo, hi);
+ 	set_in_cr4(X86_CR4_MCE);
+ 	printk(KERN_INFO "Winchip machine check reporting enabled on CPU#0.\n");
+diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
+index 3e18db4..353efe4 100644
+--- a/arch/x86/kernel/cpu/mtrr/generic.c
++++ b/arch/x86/kernel/cpu/mtrr/generic.c
+@@ -11,6 +11,7 @@
+ #include <asm/cpufeature.h>
+ #include <asm/processor-flags.h>
+ #include <asm/tlbflush.h>
++#include <asm/pat.h>
+ #include "mtrr.h"
+ 
+ struct mtrr_state {
+@@ -35,6 +36,8 @@ static struct fixed_range_block fixed_range_blocks[] = {
+ 
+ static unsigned long smp_changes_mask;
+ static struct mtrr_state mtrr_state = {};
++static int mtrr_state_set;
++static u64 tom2;
+ 
+ #undef MODULE_PARAM_PREFIX
+ #define MODULE_PARAM_PREFIX "mtrr."
+@@ -42,6 +45,111 @@ static struct mtrr_state mtrr_state = {};
+ static int mtrr_show;
+ module_param_named(show, mtrr_show, bool, 0);
+ 
++/*
++ * 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
++ */
++u8 mtrr_type_lookup(u64 start, u64 end)
++{
++	int i;
++	u64 base, mask;
++	u8 prev_match, curr_match;
++
++	if (!mtrr_state_set)
++		return 0xFF;
++
++	if (!mtrr_state.enabled)
++		return 0xFF;
++
++	/* Make end inclusive end, instead of exclusive */
++	end--;
++
++	/* Look in fixed ranges. Just return the type as per start */
++	if (mtrr_state.have_fixed && (start < 0x100000)) {
++		int idx;
++
++		if (start < 0x80000) {
++			idx = 0;
++			idx += (start >> 16);
++			return mtrr_state.fixed_ranges[idx];
++		} else if (start < 0xC0000) {
++			idx = 1 * 8;
++			idx += ((start - 0x80000) >> 14);
++			return mtrr_state.fixed_ranges[idx];
++		} else if (start < 0x1000000) {
++			idx = 3 * 8;
++			idx += ((start - 0xC0000) >> 12);
++			return mtrr_state.fixed_ranges[idx];
++		}
++	}
++
++	/*
++	 * Look in variable ranges
++	 * Look of multiple ranges matching this address and pick type
++	 * as per MTRR precedence
++	 */
++	if (!mtrr_state.enabled & 2) {
++		return mtrr_state.def_type;
++	}
++
++	prev_match = 0xFF;
++	for (i = 0; i < num_var_ranges; ++i) {
++		unsigned short start_state, end_state;
++
++		if (!(mtrr_state.var_ranges[i].mask_lo & (1 << 11)))
++			continue;
++
++		base = (((u64)mtrr_state.var_ranges[i].base_hi) << 32) +
++		       (mtrr_state.var_ranges[i].base_lo & PAGE_MASK);
++		mask = (((u64)mtrr_state.var_ranges[i].mask_hi) << 32) +
++		       (mtrr_state.var_ranges[i].mask_lo & PAGE_MASK);
++
++		start_state = ((start & mask) == (base & mask));
++		end_state = ((end & mask) == (base & mask));
++		if (start_state != end_state)
++			return 0xFE;
++
++		if ((start & mask) != (base & mask)) {
++			continue;
++		}
++
++		curr_match = mtrr_state.var_ranges[i].base_lo & 0xff;
++		if (prev_match == 0xFF) {
++			prev_match = curr_match;
++			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 (tom2) {
++		if (start >= (1ULL<<32) && (end < tom2))
++			return MTRR_TYPE_WRBACK;
++	}
++
++	if (prev_match != 0xFF)
++		return prev_match;
++
++	return mtrr_state.def_type;
++}
++
+ /*  Get the MSR pair relating to a var range  */
+ static void
+ get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
+@@ -79,12 +187,16 @@ static void print_fixed(unsigned base, unsigned step, const mtrr_type*types)
+ 			base, base + step - 1, mtrr_attrib_to_str(*types));
+ }
+ 
++static void prepare_set(void);
++static void post_set(void);
++
+ /*  Grab all of the MTRR state for this CPU into *state  */
+ void __init get_mtrr_state(void)
+ {
+ 	unsigned int i;
+ 	struct mtrr_var_range *vrs;
+ 	unsigned lo, dummy;
++	unsigned long flags;
+ 
+ 	vrs = mtrr_state.var_ranges;
+ 
+@@ -100,6 +212,15 @@ void __init get_mtrr_state(void)
+ 	mtrr_state.def_type = (lo & 0xff);
+ 	mtrr_state.enabled = (lo & 0xc00) >> 10;
+ 
++	if (amd_special_default_mtrr()) {
++		unsigned lo, hi;
++		/* TOP_MEM2 */
++		rdmsr(MSR_K8_TOP_MEM2, lo, hi);
++		tom2 = hi;
++		tom2 <<= 32;
++		tom2 |= lo;
++		tom2 &= 0xffffff8000000ULL;
++	}
+ 	if (mtrr_show) {
+ 		int high_width;
+ 
+@@ -130,7 +251,22 @@ void __init get_mtrr_state(void)
+ 			else
+ 				printk(KERN_INFO "MTRR %u disabled\n", i);
+ 		}
++		if (tom2) {
++			printk(KERN_INFO "TOM2: %016llx aka %lldM\n",
++					  tom2, tom2>>20);
++		}
+ 	}
++	mtrr_state_set = 1;
++
++	/* PAT setup for BP. We need to go through sync steps here */
++	local_irq_save(flags);
++	prepare_set();
++
++	pat_init();
++
++	post_set();
++	local_irq_restore(flags);
++
+ }
+ 
+ /*  Some BIOS's are fucked and don't set all MTRRs the same!  */
+@@ -397,6 +533,9 @@ static void generic_set_all(void)
+ 	/* Actually set the state */
+ 	mask = set_mtrr_state();
+ 
++	/* also set PAT */
++	pat_init();
++
+ 	post_set();
+ 	local_irq_restore(flags);
+ 
+diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c
+index 91e150a..1960f19 100644
+--- a/arch/x86/kernel/cpu/mtrr/if.c
++++ b/arch/x86/kernel/cpu/mtrr/if.c
+@@ -424,11 +424,10 @@ static int __init mtrr_if_init(void)
+ 		return -ENODEV;
+ 
+ 	proc_root_mtrr =
+-	    create_proc_entry("mtrr", S_IWUSR | S_IRUGO, &proc_root);
+-	if (proc_root_mtrr) {
++		proc_create("mtrr", S_IWUSR | S_IRUGO, &proc_root, &mtrr_fops);
++
++	if (proc_root_mtrr)
+ 		proc_root_mtrr->owner = THIS_MODULE;
+-		proc_root_mtrr->proc_fops = &mtrr_fops;
+-	}
+ 	return 0;
+ }
+ 
+diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
+index a6450b3..6a1e278 100644
+--- a/arch/x86/kernel/cpu/mtrr/main.c
++++ b/arch/x86/kernel/cpu/mtrr/main.c
+@@ -627,7 +627,7 @@ early_param("disable_mtrr_trim", disable_mtrr_trim_setup);
+ #define Tom2Enabled (1U << 21)
+ #define Tom2ForceMemTypeWB (1U << 22)
+ 
+-static __init int amd_special_default_mtrr(void)
++int __init amd_special_default_mtrr(void)
+ {
+ 	u32 l, h;
+ 
+diff --git a/arch/x86/kernel/cpu/mtrr/state.c b/arch/x86/kernel/cpu/mtrr/state.c
+index 9f8ba92..7f7e275 100644
+--- a/arch/x86/kernel/cpu/mtrr/state.c
++++ b/arch/x86/kernel/cpu/mtrr/state.c
+@@ -19,13 +19,15 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt)
+ 	if (use_intel() || is_cpu(CYRIX)) {
+ 
+ 		/*  Save value of CR4 and clear Page Global Enable (bit 7)  */
+-		if ( cpu_has_pge ) {
++		if (cpu_has_pge) {
+ 			ctxt->cr4val = read_cr4();
+ 			write_cr4(ctxt->cr4val & ~X86_CR4_PGE);
+ 		}
+ 
+-		/*  Disable and flush caches. Note that wbinvd flushes the TLBs as
+-		    a side-effect  */
++		/*
++		 * Disable and flush caches. Note that wbinvd flushes the TLBs
++		 * as a side-effect
++		 */
+ 		cr0 = read_cr0() | X86_CR0_CD;
+ 		wbinvd();
+ 		write_cr0(cr0);
+@@ -42,7 +44,7 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt)
+ 
+ void set_mtrr_cache_disable(struct set_mtrr_context *ctxt)
+ {
+-	if (use_intel()) 
++	if (use_intel())
+ 		/*  Disable MTRRs, and set the default type to uncached  */
+ 		mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL,
+ 		      ctxt->deftype_hi);
+@@ -66,12 +68,12 @@ void set_mtrr_done(struct set_mtrr_context *ctxt)
+ 		else
+ 			/* Cyrix ARRs - everything else was excluded at the top */
+ 			setCx86(CX86_CCR3, ctxt->ccr3);
+-		
++
+ 		/*  Enable caches  */
+ 		write_cr0(read_cr0() & 0xbfffffff);
+ 
+ 		/*  Restore value of CR4  */
+-		if ( cpu_has_pge )
++		if (cpu_has_pge)
+ 			write_cr4(ctxt->cr4val);
+ 	}
+ 	/*  Re-enable interrupts locally (if enabled previously)  */
+diff --git a/arch/x86/kernel/cpu/nexgen.c b/arch/x86/kernel/cpu/nexgen.c
+deleted file mode 100644
+index 961fbe1..0000000
+--- a/arch/x86/kernel/cpu/nexgen.c
++++ /dev/null
+@@ -1,60 +0,0 @@
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/string.h>
+-#include <asm/processor.h>
+-
+-#include "cpu.h"
+-
+-/*
+- *	Detect a NexGen CPU running without BIOS hypercode new enough
+- *	to have CPUID. (Thanks to Herbert Oppmann)
+- */
+- 
+-static int __cpuinit deep_magic_nexgen_probe(void)
+-{
+-	int ret;
+-	
+-	__asm__ __volatile__ (
+-		"	movw	$0x5555, %%ax\n"
+-		"	xorw	%%dx,%%dx\n"
+-		"	movw	$2, %%cx\n"
+-		"	divw	%%cx\n"
+-		"	movl	$0, %%eax\n"
+-		"	jnz	1f\n"
+-		"	movl	$1, %%eax\n"
+-		"1:\n" 
+-		: "=a" (ret) : : "cx", "dx" );
+-	return  ret;
+-}
+-
+-static void __cpuinit init_nexgen(struct cpuinfo_x86 * c)
+-{
+-	c->x86_cache_size = 256; /* A few had 1 MB... */
+-}
+-
+-static void __cpuinit nexgen_identify(struct cpuinfo_x86 * c)
+-{
+-	/* Detect NexGen with old hypercode */
+-	if ( deep_magic_nexgen_probe() ) {
+-		strcpy(c->x86_vendor_id, "NexGenDriven");
+-	}
+-}
+-
+-static struct cpu_dev nexgen_cpu_dev __cpuinitdata = {
+-	.c_vendor	= "Nexgen",
+-	.c_ident	= { "NexGenDriven" },
+-	.c_models = {
+-			{ .vendor = X86_VENDOR_NEXGEN,
+-			  .family = 5,
+-			  .model_names = { [1] = "Nx586" }
+-			},
+-	},
+-	.c_init		= init_nexgen,
+-	.c_identify	= nexgen_identify,
+-};
+-
+-int __init nexgen_init_cpu(void)
+-{
+-	cpu_devs[X86_VENDOR_NEXGEN] = &nexgen_cpu_dev;
+-	return 0;
+-}
+diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
+index b943e10..f9ae93a 100644
+--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
++++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
+@@ -614,16 +614,6 @@ static struct wd_ops intel_arch_wd_ops __read_mostly = {
+ 	.evntsel = MSR_ARCH_PERFMON_EVENTSEL1,
+ };
+ 
+-static struct wd_ops coreduo_wd_ops = {
+-	.reserve = single_msr_reserve,
+-	.unreserve = single_msr_unreserve,
+-	.setup = setup_intel_arch_watchdog,
+-	.rearm = p6_rearm,
+-	.stop = single_msr_stop_watchdog,
+-	.perfctr = MSR_ARCH_PERFMON_PERFCTR0,
+-	.evntsel = MSR_ARCH_PERFMON_EVENTSEL0,
+-};
+-
+ static void probe_nmi_watchdog(void)
+ {
+ 	switch (boot_cpu_data.x86_vendor) {
+@@ -637,8 +627,8 @@ static void probe_nmi_watchdog(void)
+ 		/* Work around Core Duo (Yonah) errata AE49 where perfctr1
+ 		   doesn't have a working enable bit. */
+ 		if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) {
+-			wd_ops = &coreduo_wd_ops;
+-			break;
++			intel_arch_wd_ops.perfctr = MSR_ARCH_PERFMON_PERFCTR0;
++			intel_arch_wd_ops.evntsel = MSR_ARCH_PERFMON_EVENTSEL0;
+ 		}
+ 		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+ 			wd_ops = &intel_arch_wd_ops;
+diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
+index af11d31..0d0d905 100644
+--- a/arch/x86/kernel/cpu/proc.c
++++ b/arch/x86/kernel/cpu/proc.c
+@@ -1,85 +1,145 @@
+ #include <linux/smp.h>
+ #include <linux/timex.h>
+ #include <linux/string.h>
+-#include <asm/semaphore.h>
+ #include <linux/seq_file.h>
+ #include <linux/cpufreq.h>
+ 
+ /*
+  *	Get CPU information for use by the procfs.
+  */
++#ifdef CONFIG_X86_32
++static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
++			      unsigned int cpu)
++{
++#ifdef CONFIG_X86_HT
++	if (c->x86_max_cores * smp_num_siblings > 1) {
++		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
++		seq_printf(m, "siblings\t: %d\n",
++			   cpus_weight(per_cpu(cpu_core_map, cpu)));
++		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
++		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
++		seq_printf(m, "apicid\t\t: %d\n", c->apicid);
++		seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid);
++	}
++#endif
++}
++
++static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
++{
++	/*
++	 * We use exception 16 if we have hardware math and we've either seen
++	 * it or the CPU claims it is internal
++	 */
++	int fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu);
++	seq_printf(m,
++		   "fdiv_bug\t: %s\n"
++		   "hlt_bug\t\t: %s\n"
++		   "f00f_bug\t: %s\n"
++		   "coma_bug\t: %s\n"
++		   "fpu\t\t: %s\n"
++		   "fpu_exception\t: %s\n"
++		   "cpuid level\t: %d\n"
++		   "wp\t\t: %s\n",
++		   c->fdiv_bug ? "yes" : "no",
++		   c->hlt_works_ok ? "no" : "yes",
++		   c->f00f_bug ? "yes" : "no",
++		   c->coma_bug ? "yes" : "no",
++		   c->hard_math ? "yes" : "no",
++		   fpu_exception ? "yes" : "no",
++		   c->cpuid_level,
++		   c->wp_works_ok ? "yes" : "no");
++}
++#else
++static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
++			      unsigned int cpu)
++{
++#ifdef CONFIG_SMP
++	if (c->x86_max_cores * smp_num_siblings > 1) {
++		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
++		seq_printf(m, "siblings\t: %d\n",
++			   cpus_weight(per_cpu(cpu_core_map, cpu)));
++		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
++		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
++		seq_printf(m, "apicid\t\t: %d\n", c->apicid);
++		seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid);
++	}
++#endif
++}
++
++static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
++{
++	seq_printf(m,
++		   "fpu\t\t: yes\n"
++		   "fpu_exception\t: yes\n"
++		   "cpuid level\t: %d\n"
++		   "wp\t\t: yes\n",
++		   c->cpuid_level);
++}
++#endif
++
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+ 	struct cpuinfo_x86 *c = v;
+-	int i, n = 0;
+-	int fpu_exception;
++	unsigned int cpu = 0;
++	int i;
+ 
+ #ifdef CONFIG_SMP
+-	n = c->cpu_index;
++	cpu = c->cpu_index;
+ #endif
+-	seq_printf(m, "processor\t: %d\n"
+-		"vendor_id\t: %s\n"
+-		"cpu family\t: %d\n"
+-		"model\t\t: %d\n"
+-		"model name\t: %s\n",
+-		n,
+-		c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+-		c->x86,
+-		c->x86_model,
+-		c->x86_model_id[0] ? c->x86_model_id : "unknown");
++	seq_printf(m, "processor\t: %u\n"
++		   "vendor_id\t: %s\n"
++		   "cpu family\t: %d\n"
++		   "model\t\t: %u\n"
++		   "model name\t: %s\n",
++		   cpu,
++		   c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
++		   c->x86,
++		   c->x86_model,
++		   c->x86_model_id[0] ? c->x86_model_id : "unknown");
+ 
+ 	if (c->x86_mask || c->cpuid_level >= 0)
+ 		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+ 	else
+ 		seq_printf(m, "stepping\t: unknown\n");
+ 
+-	if ( cpu_has(c, X86_FEATURE_TSC) ) {
+-		unsigned int freq = cpufreq_quick_get(n);
++	if (cpu_has(c, X86_FEATURE_TSC)) {
++		unsigned int freq = cpufreq_quick_get(cpu);
++
+ 		if (!freq)
+ 			freq = cpu_khz;
+ 		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
+-			freq / 1000, (freq % 1000));
++			   freq / 1000, (freq % 1000));
+ 	}
+ 
+ 	/* Cache size */
+ 	if (c->x86_cache_size >= 0)
+ 		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
+-#ifdef CONFIG_X86_HT
+-	if (c->x86_max_cores * smp_num_siblings > 1) {
+-		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+-		seq_printf(m, "siblings\t: %d\n",
+-				cpus_weight(per_cpu(cpu_core_map, n)));
+-		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+-		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
+-	}
+-#endif
+-	
+-	/* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
+-	fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu);
+-	seq_printf(m, "fdiv_bug\t: %s\n"
+-			"hlt_bug\t\t: %s\n"
+-			"f00f_bug\t: %s\n"
+-			"coma_bug\t: %s\n"
+-			"fpu\t\t: %s\n"
+-			"fpu_exception\t: %s\n"
+-			"cpuid level\t: %d\n"
+-			"wp\t\t: %s\n"
+-			"flags\t\t:",
+-		     c->fdiv_bug ? "yes" : "no",
+-		     c->hlt_works_ok ? "no" : "yes",
+-		     c->f00f_bug ? "yes" : "no",
+-		     c->coma_bug ? "yes" : "no",
+-		     c->hard_math ? "yes" : "no",
+-		     fpu_exception ? "yes" : "no",
+-		     c->cpuid_level,
+-		     c->wp_works_ok ? "yes" : "no");
+-
+-	for ( i = 0 ; i < 32*NCAPINTS ; i++ )
+-		if ( test_bit(i, c->x86_capability) &&
+-		     x86_cap_flags[i] != NULL )
++
++	show_cpuinfo_core(m, c, cpu);
++	show_cpuinfo_misc(m, c);
++
++	seq_printf(m, "flags\t\t:");
++	for (i = 0; i < 32*NCAPINTS; i++)
++		if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
+ 			seq_printf(m, " %s", x86_cap_flags[i]);
+ 
+-	for (i = 0; i < 32; i++)
++	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
++		   c->loops_per_jiffy/(500000/HZ),
++		   (c->loops_per_jiffy/(5000/HZ)) % 100);
++
++#ifdef CONFIG_X86_64
++	if (c->x86_tlbsize > 0)
++		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
++#endif
++	seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size);
++#ifdef CONFIG_X86_64
++	seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
++	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
++		   c->x86_phys_bits, c->x86_virt_bits);
++#endif
++
++	seq_printf(m, "power management:");
++	for (i = 0; i < 32; i++) {
+ 		if (c->x86_power & (1 << i)) {
+ 			if (i < ARRAY_SIZE(x86_power_flags) &&
+ 			    x86_power_flags[i])
+@@ -89,11 +149,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ 			else
+ 				seq_printf(m, " [%d]", i);
+ 		}
++	}
+ 
+-	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
+-		     c->loops_per_jiffy/(500000/HZ),
+-		     (c->loops_per_jiffy/(5000/HZ)) % 100);
+-	seq_printf(m, "clflush size\t: %u\n\n", c->x86_clflush_size);
++	seq_printf(m, "\n\n");
+ 
+ 	return 0;
+ }
+@@ -106,14 +164,17 @@ static void *c_start(struct seq_file *m, loff_t *pos)
+ 		return &cpu_data(*pos);
+ 	return NULL;
+ }
++
+ static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+ {
+ 	*pos = next_cpu(*pos, cpu_online_map);
+ 	return c_start(m, pos);
+ }
++
+ static void c_stop(struct seq_file *m, void *v)
+ {
+ }
++
+ const struct seq_operations cpuinfo_op = {
+ 	.start	= c_start,
+ 	.next	= c_next,
+diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c
+index e8b422c..b911a2c 100644
+--- a/arch/x86/kernel/cpu/transmeta.c
++++ b/arch/x86/kernel/cpu/transmeta.c
+@@ -18,8 +18,8 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
+ 	/* Print CMS and CPU revision */
+ 	max = cpuid_eax(0x80860000);
+ 	cpu_rev = 0;
+-	if ( max >= 0x80860001 ) {
+-		cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags); 
++	if (max >= 0x80860001) {
++		cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags);
+ 		if (cpu_rev != 0x02000000) {
+ 			printk(KERN_INFO "CPU: Processor revision %u.%u.%u.%u, %u MHz\n",
+ 				(cpu_rev >> 24) & 0xff,
+@@ -29,7 +29,7 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
+ 				cpu_freq);
+ 		}
+ 	}
+-	if ( max >= 0x80860002 ) {
++	if (max >= 0x80860002) {
+ 		cpuid(0x80860002, &new_cpu_rev, &cms_rev1, &cms_rev2, &dummy);
+ 		if (cpu_rev == 0x02000000) {
+ 			printk(KERN_INFO "CPU: Processor revision %08X, %u MHz\n",
+@@ -42,7 +42,7 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
+ 		       cms_rev1 & 0xff,
+ 		       cms_rev2);
+ 	}
+-	if ( max >= 0x80860006 ) {
++	if (max >= 0x80860006) {
+ 		cpuid(0x80860003,
+ 		      (void *)&cpu_info[0],
+ 		      (void *)&cpu_info[4],
+@@ -74,23 +74,25 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
+ 	wrmsr(0x80860004, cap_mask, uk);
+ 
+ 	/* All Transmeta CPUs have a constant TSC */
+-	set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
+-	
++	set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
++
+ #ifdef CONFIG_SYSCTL
+-	/* randomize_va_space slows us down enormously;
+-	   it probably triggers retranslation of x86->native bytecode */
++	/*
++	 * randomize_va_space slows us down enormously;
++	 * it probably triggers retranslation of x86->native bytecode
++	 */
+ 	randomize_va_space = 0;
+ #endif
+ }
+ 
+-static void __cpuinit transmeta_identify(struct cpuinfo_x86 * c)
++static void __cpuinit transmeta_identify(struct cpuinfo_x86 *c)
+ {
+ 	u32 xlvl;
+ 
+ 	/* Transmeta-defined flags: level 0x80860001 */
+ 	xlvl = cpuid_eax(0x80860000);
+-	if ( (xlvl & 0xffff0000) == 0x80860000 ) {
+-		if (  xlvl >= 0x80860001 )
++	if ((xlvl & 0xffff0000) == 0x80860000) {
++		if (xlvl >= 0x80860001)
+ 			c->x86_capability[2] = cpuid_edx(0x80860001);
+ 	}
+ }
+@@ -102,8 +104,4 @@ static struct cpu_dev transmeta_cpu_dev __cpuinitdata = {
+ 	.c_identify	= transmeta_identify,
+ };
+ 
+-int __init transmeta_init_cpu(void)
+-{
+-	cpu_devs[X86_VENDOR_TRANSMETA] = &transmeta_cpu_dev;
+-	return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_TRANSMETA, &transmeta_cpu_dev);
+diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c
+index a7a4e75..b1fc909 100644
+--- a/arch/x86/kernel/cpu/umc.c
++++ b/arch/x86/kernel/cpu/umc.c
+@@ -3,24 +3,23 @@
+ #include <asm/processor.h>
+ #include "cpu.h"
+ 
+-/* UMC chips appear to be only either 386 or 486, so no special init takes place.
++/*
++ * UMC chips appear to be only either 386 or 486,
++ * so no special init takes place.
+  */
+ 
+ static struct cpu_dev umc_cpu_dev __cpuinitdata = {
+ 	.c_vendor	= "UMC",
+-	.c_ident 	= { "UMC UMC UMC" },
++	.c_ident	= { "UMC UMC UMC" },
+ 	.c_models = {
+ 		{ .vendor = X86_VENDOR_UMC, .family = 4, .model_names =
+-		  { 
+-			  [1] = "U5D", 
+-			  [2] = "U5S", 
++		  {
++			  [1] = "U5D",
++			  [2] = "U5S",
+ 		  }
+ 		},
+ 	},
+ };
+ 
+-int __init umc_init_cpu(void)
+-{
+-	cpu_devs[X86_VENDOR_UMC] = &umc_cpu_dev;
+-	return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_UMC, &umc_cpu_dev);
++
+diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
+index 288e7a6..daff52a 100644
+--- a/arch/x86/kernel/cpuid.c
++++ b/arch/x86/kernel/cpuid.c
+@@ -154,12 +154,10 @@ static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb,
+ 		err = cpuid_device_create(cpu);
+ 		break;
+ 	case CPU_UP_CANCELED:
++	case CPU_UP_CANCELED_FROZEN:
+ 	case CPU_DEAD:
+ 		cpuid_device_destroy(cpu);
+ 		break;
+-	case CPU_UP_CANCELED_FROZEN:
+-		destroy_suspended_device(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+-		break;
+ 	}
+ 	return err ? NOTIFY_BAD : NOTIFY_OK;
+ }
+diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
+index 9a5fa0a..2251d0a 100644
+--- a/arch/x86/kernel/crash.c
++++ b/arch/x86/kernel/crash.c
+@@ -26,11 +26,7 @@
+ #include <linux/kdebug.h>
+ #include <asm/smp.h>
+ 
+-#ifdef CONFIG_X86_32
+ #include <mach_ipi.h>
+-#else
+-#include <asm/mach_apic.h>
+-#endif
+ 
+ /* This keeps a track of which one is crashing cpu. */
+ static int crashing_cpu;
+diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
+index dcd918c..11c11b8 100644
+--- a/arch/x86/kernel/ds.c
++++ b/arch/x86/kernel/ds.c
+@@ -220,11 +220,11 @@ int ds_allocate(void **dsp, size_t bts_size_in_bytes)
+ 
+ int ds_free(void **dsp)
+ {
+-	if (*dsp)
++	if (*dsp) {
+ 		kfree((void *)get_bts_buffer_base(*dsp));
+-	kfree(*dsp);
+-	*dsp = NULL;
+-
++		kfree(*dsp);
++		*dsp = NULL;
++	}
+ 	return 0;
+ }
+ 
+diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c
+index 80444c5..ed733e7 100644
+--- a/arch/x86/kernel/e820_32.c
++++ b/arch/x86/kernel/e820_32.c
+@@ -450,45 +450,32 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
+  * thinkpad 560x, for example, does not cooperate with the memory
+  * detection code.)
+  */
+-int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
++int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
+ {
+ 	/* Only one memory region (or negative)? Ignore it */
+ 	if (nr_map < 2)
+ 		return -1;
+ 
+ 	do {
+-		unsigned long long start = biosmap->addr;
+-		unsigned long long size = biosmap->size;
+-		unsigned long long end = start + size;
+-		unsigned long type = biosmap->type;
++		u64 start = biosmap->addr;
++		u64 size = biosmap->size;
++		u64 end = start + size;
++		u32 type = biosmap->type;
+ 
+ 		/* Overflow in 64 bits? Ignore the memory map. */
+ 		if (start > end)
+ 			return -1;
+ 
+-		/*
+-		 * Some BIOSes claim RAM in the 640k - 1M region.
+-		 * Not right. Fix it up.
+-		 */
+-		if (type == E820_RAM) {
+-			if (start < 0x100000ULL && end > 0xA0000ULL) {
+-				if (start < 0xA0000ULL)
+-					add_memory_region(start, 0xA0000ULL-start, type);
+-				if (end <= 0x100000ULL)
+-					continue;
+-				start = 0x100000ULL;
+-				size = end - start;
+-			}
+-		}
+ 		add_memory_region(start, size, type);
+-	} while (biosmap++,--nr_map);
++	} while (biosmap++, --nr_map);
++
+ 	return 0;
+ }
+ 
+ /*
+  * Find the highest page frame number we have available
+  */
+-void __init find_max_pfn(void)
++void __init propagate_e820_map(void)
+ {
+ 	int i;
+ 
+@@ -717,7 +704,7 @@ static int __init parse_memmap(char *arg)
+ 		 * size before original memory map is
+ 		 * reset.
+ 		 */
+-		find_max_pfn();
++		propagate_e820_map();
+ 		saved_max_pfn = max_pfn;
+ #endif
+ 		e820.nr_map = 0;
+diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c
+index 9be6971..cbd42e5 100644
+--- a/arch/x86/kernel/e820_64.c
++++ b/arch/x86/kernel/e820_64.c
+@@ -27,6 +27,7 @@
+ #include <asm/setup.h>
+ #include <asm/sections.h>
+ #include <asm/kdebug.h>
++#include <asm/trampoline.h>
+ 
+ struct e820map e820;
+ 
+@@ -36,11 +37,11 @@ struct e820map e820;
+ unsigned long end_pfn;
+ 
+ /*
+- * end_pfn only includes RAM, while end_pfn_map includes all e820 entries.
+- * The direct mapping extends to end_pfn_map, so that we can directly access
++ * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
++ * The direct mapping extends to max_pfn_mapped, so that we can directly access
+  * apertures, ACPI and other tables without having to play with fixmaps.
+  */
+-unsigned long end_pfn_map;
++unsigned long max_pfn_mapped;
+ 
+ /*
+  * Last pfn which the user wants to use.
+@@ -58,8 +59,8 @@ struct early_res {
+ };
+ static struct early_res early_res[MAX_EARLY_RES] __initdata = {
+ 	{ 0, PAGE_SIZE, "BIOS data page" },			/* BIOS data page */
+-#ifdef CONFIG_SMP
+-	{ SMP_TRAMPOLINE_BASE, SMP_TRAMPOLINE_BASE + 2*PAGE_SIZE, "SMP_TRAMPOLINE" },
++#ifdef CONFIG_X86_TRAMPOLINE
++	{ TRAMPOLINE_BASE, TRAMPOLINE_BASE + 2 * PAGE_SIZE, "TRAMPOLINE" },
+ #endif
+ 	{}
+ };
+@@ -95,7 +96,8 @@ void __init early_res_to_bootmem(void)
+ }
+ 
+ /* Check for already reserved areas */
+-static inline int bad_addr(unsigned long *addrp, unsigned long size)
++static inline int __init
++bad_addr(unsigned long *addrp, unsigned long size, unsigned long align)
+ {
+ 	int i;
+ 	unsigned long addr = *addrp, last;
+@@ -105,7 +107,7 @@ again:
+ 	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->end) {
+-			*addrp = addr = r->end;
++			*addrp = addr = round_up(r->end, align);
+ 			changed = 1;
+ 			goto again;
+ 		}
+@@ -113,6 +115,40 @@ again:
+ 	return changed;
+ }
+ 
++/* Check for already reserved areas */
++static inline int __init
++bad_addr_size(unsigned long *addrp, unsigned long *sizep, unsigned long align)
++{
++	int i;
++	unsigned long addr = *addrp, last;
++	unsigned long 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;
++}
+ /*
+  * This function checks if any part of the range <start,end> is mapped
+  * with type.
+@@ -174,26 +210,27 @@ int __init e820_all_mapped(unsigned long start, unsigned long end,
+  * Find a free area with specified alignment in a specific range.
+  */
+ unsigned long __init find_e820_area(unsigned long start, unsigned long end,
+-				    unsigned size, unsigned long align)
++				    unsigned long size, unsigned long align)
+ {
+ 	int i;
+-	unsigned long mask = ~(align - 1);
+ 
+ 	for (i = 0; i < e820.nr_map; i++) {
+ 		struct e820entry *ei = &e820.map[i];
+-		unsigned long addr = ei->addr, last;
++		unsigned long addr, last;
++		unsigned long ei_last;
+ 
+ 		if (ei->type != E820_RAM)
+ 			continue;
++		addr = round_up(ei->addr, align);
++		ei_last = ei->addr + ei->size;
+ 		if (addr < start)
+-			addr = start;
+-		if (addr > ei->addr + ei->size)
++			addr = round_up(start, align);
++		if (addr >= ei_last)
+ 			continue;
+-		while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
++		while (bad_addr(&addr, size, align) && addr+size <= ei_last)
+ 			;
+-		addr = (addr + align - 1) & mask;
+ 		last = addr + size;
+-		if (last > ei->addr + ei->size)
++		if (last > ei_last)
+ 			continue;
+ 		if (last > end)
+ 			continue;
+@@ -203,6 +240,40 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end,
+ }
+ 
+ /*
++ * Find next free range after *start
++ */
++unsigned long __init find_e820_area_size(unsigned long start,
++					 unsigned long *sizep,
++					 unsigned long align)
++{
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		unsigned long addr, last;
++		unsigned long ei_last;
++
++		if (ei->type != E820_RAM)
++			continue;
++		addr = round_up(ei->addr, align);
++		ei_last = ei->addr + ei->size;
++		if (addr < start)
++			addr = round_up(start, align);
++		if (addr >= ei_last)
++			continue;
++		*sizep = ei_last - addr;
++		while (bad_addr_size(&addr, sizep, align) &&
++			addr + *sizep <= ei_last)
++			;
++		last = addr + *sizep;
++		if (last > ei_last)
++			continue;
++		return addr;
++	}
++	return -1UL;
++
++}
++/*
+  * Find the highest page frame number we have available
+  */
+ unsigned long __init e820_end_of_ram(void)
+@@ -211,29 +282,29 @@ unsigned long __init e820_end_of_ram(void)
+ 
+ 	end_pfn = find_max_pfn_with_active_regions();
+ 
+-	if (end_pfn > end_pfn_map)
+-		end_pfn_map = end_pfn;
+-	if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
+-		end_pfn_map = MAXMEM>>PAGE_SHIFT;
++	if (end_pfn > max_pfn_mapped)
++		max_pfn_mapped = end_pfn;
++	if (max_pfn_mapped > MAXMEM>>PAGE_SHIFT)
++		max_pfn_mapped = MAXMEM>>PAGE_SHIFT;
+ 	if (end_pfn > end_user_pfn)
+ 		end_pfn = end_user_pfn;
+-	if (end_pfn > end_pfn_map)
+-		end_pfn = end_pfn_map;
++	if (end_pfn > max_pfn_mapped)
++		end_pfn = max_pfn_mapped;
+ 
+-	printk(KERN_INFO "end_pfn_map = %lu\n", end_pfn_map);
++	printk(KERN_INFO "max_pfn_mapped = %lu\n", max_pfn_mapped);
+ 	return end_pfn;
+ }
+ 
+ /*
+  * Mark e820 reserved areas as busy for the resource manager.
+  */
+-void __init e820_reserve_resources(struct resource *code_resource,
+-		struct resource *data_resource, struct resource *bss_resource)
++void __init e820_reserve_resources(void)
+ {
+ 	int i;
++	struct resource *res;
++
++	res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map);
+ 	for (i = 0; i < e820.nr_map; i++) {
+-		struct resource *res;
+-		res = alloc_bootmem_low(sizeof(struct resource));
+ 		switch (e820.map[i].type) {
+ 		case E820_RAM:	res->name = "System RAM"; break;
+ 		case E820_ACPI:	res->name = "ACPI Tables"; break;
+@@ -243,21 +314,8 @@ void __init e820_reserve_resources(struct resource *code_resource,
+ 		res->start = e820.map[i].addr;
+ 		res->end = res->start + e820.map[i].size - 1;
+ 		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+-		request_resource(&iomem_resource, res);
+-		if (e820.map[i].type == E820_RAM) {
+-			/*
+-			 * We don't know which RAM region contains kernel data,
+-			 * so we try it repeatedly and let the resource manager
+-			 * test it.
+-			 */
+-			request_resource(res, code_resource);
+-			request_resource(res, data_resource);
+-			request_resource(res, bss_resource);
+-#ifdef CONFIG_KEXEC
+-			if (crashk_res.start != crashk_res.end)
+-				request_resource(res, &crashk_res);
+-#endif
+-		}
++		insert_resource(&iomem_resource, res);
++		res++;
+ 	}
+ }
+ 
+@@ -309,9 +367,9 @@ static int __init e820_find_active_region(const struct e820entry *ei,
+ 	if (*ei_startpfn >= *ei_endpfn)
+ 		return 0;
+ 
+-	/* Check if end_pfn_map should be updated */
+-	if (ei->type != E820_RAM && *ei_endpfn > end_pfn_map)
+-		end_pfn_map = *ei_endpfn;
++	/* Check if max_pfn_mapped should be updated */
++	if (ei->type != E820_RAM && *ei_endpfn > max_pfn_mapped)
++		max_pfn_mapped = *ei_endpfn;
+ 
+ 	/* Skip if map is outside the node */
+ 	if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
+@@ -634,10 +692,10 @@ static int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
+ 		return -1;
+ 
+ 	do {
+-		unsigned long start = biosmap->addr;
+-		unsigned long size = biosmap->size;
+-		unsigned long end = start + size;
+-		unsigned long type = biosmap->type;
++		u64 start = biosmap->addr;
++		u64 size = biosmap->size;
++		u64 end = start + size;
++		u32 type = biosmap->type;
+ 
+ 		/* Overflow in 64 bits? Ignore the memory map. */
+ 		if (start > end)
+@@ -702,7 +760,7 @@ static int __init parse_memmap_opt(char *p)
+ 		saved_max_pfn = e820_end_of_ram();
+ 		remove_all_active_ranges();
+ #endif
+-		end_pfn_map = 0;
++		max_pfn_mapped = 0;
+ 		e820.nr_map = 0;
+ 		userdef = 1;
+ 		return 0;
+diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
+index cff84cd..643fd86 100644
+--- a/arch/x86/kernel/early_printk.c
++++ b/arch/x86/kernel/early_printk.c
+@@ -13,7 +13,7 @@
+ #define VGABASE		(__ISA_IO_base + 0xb8000)
+ 
+ static int max_ypos = 25, max_xpos = 80;
+-static int current_ypos = 25, current_xpos = 0;
++static int current_ypos = 25, current_xpos;
+ 
+ static void early_vga_write(struct console *con, const char *str, unsigned n)
+ {
+@@ -108,12 +108,12 @@ static __init void early_serial_init(char *s)
+ 
+ 	if (*s) {
+ 		unsigned port;
+-		if (!strncmp(s,"0x",2)) {
++		if (!strncmp(s, "0x", 2)) {
+ 			early_serial_base = simple_strtoul(s, &e, 16);
+ 		} else {
+ 			static int bases[] = { 0x3f8, 0x2f8 };
+ 
+-			if (!strncmp(s,"ttyS",4))
++			if (!strncmp(s, "ttyS", 4))
+ 				s += 4;
+ 			port = simple_strtoul(s, &e, 10);
+ 			if (port > 1 || s == e)
+@@ -194,7 +194,7 @@ static struct console simnow_console = {
+ 
+ /* Direct interface for emergencies */
+ static struct console *early_console = &early_vga_console;
+-static int early_console_initialized = 0;
++static int early_console_initialized;
+ 
+ void early_printk(const char *fmt, ...)
+ {
+@@ -202,9 +202,9 @@ void early_printk(const char *fmt, ...)
+ 	int n;
+ 	va_list ap;
+ 
+-	va_start(ap,fmt);
+-	n = vscnprintf(buf,512,fmt,ap);
+-	early_console->write(early_console,buf,n);
++	va_start(ap, fmt);
++	n = vscnprintf(buf, 512, fmt, ap);
++	early_console->write(early_console, buf, n);
+ 	va_end(ap);
+ }
+ 
+@@ -229,15 +229,15 @@ static int __init setup_early_printk(char *buf)
+ 		early_serial_init(buf);
+ 		early_console = &early_serial_console;
+ 	} else if (!strncmp(buf, "vga", 3)
+-	           && boot_params.screen_info.orig_video_isVGA == 1) {
++		&& boot_params.screen_info.orig_video_isVGA == 1) {
+ 		max_xpos = boot_params.screen_info.orig_video_cols;
+ 		max_ypos = boot_params.screen_info.orig_video_lines;
+ 		current_ypos = boot_params.screen_info.orig_y;
+ 		early_console = &early_vga_console;
+- 	} else if (!strncmp(buf, "simnow", 6)) {
+- 		simnow_init(buf + 6);
+- 		early_console = &simnow_console;
+- 		keep_early = 1;
++	} else if (!strncmp(buf, "simnow", 6)) {
++		simnow_init(buf + 6);
++		early_console = &simnow_console;
++		keep_early = 1;
+ #ifdef CONFIG_HVC_XEN
+ 	} else if (!strncmp(buf, "xen", 3)) {
+ 		early_console = &xenboot_console;
+diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c
+index 759e02b..77d424c 100644
+--- a/arch/x86/kernel/efi.c
++++ b/arch/x86/kernel/efi.c
+@@ -383,6 +383,7 @@ static void __init runtime_code_page_mkexec(void)
+ {
+ 	efi_memory_desc_t *md;
+ 	void *p;
++	u64 addr, npages;
+ 
+ 	/* Make EFI runtime service code area executable */
+ 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+@@ -391,7 +392,10 @@ static void __init runtime_code_page_mkexec(void)
+ 		if (md->type != EFI_RUNTIME_SERVICES_CODE)
+ 			continue;
+ 
+-		set_memory_x(md->virt_addr, md->num_pages);
++		addr = md->virt_addr;
++		npages = md->num_pages;
++		memrange_efi_to_native(&addr, &npages);
++		set_memory_x(addr, npages);
+ 	}
+ }
+ 
+@@ -408,7 +412,7 @@ void __init efi_enter_virtual_mode(void)
+ 	efi_memory_desc_t *md;
+ 	efi_status_t status;
+ 	unsigned long size;
+-	u64 end, systab;
++	u64 end, systab, addr, npages;
+ 	void *p, *va;
+ 
+ 	efi.systab = NULL;
+@@ -420,7 +424,7 @@ void __init efi_enter_virtual_mode(void)
+ 		size = md->num_pages << EFI_PAGE_SHIFT;
+ 		end = md->phys_addr + size;
+ 
+-		if ((end >> PAGE_SHIFT) <= max_pfn_mapped)
++		if (PFN_UP(end) <= max_pfn_mapped)
+ 			va = __va(md->phys_addr);
+ 		else
+ 			va = efi_ioremap(md->phys_addr, size);
+@@ -433,8 +437,12 @@ void __init efi_enter_virtual_mode(void)
+ 			continue;
+ 		}
+ 
+-		if (!(md->attribute & EFI_MEMORY_WB))
+-			set_memory_uc(md->virt_addr, md->num_pages);
++		if (!(md->attribute & EFI_MEMORY_WB)) {
++			addr = md->virt_addr;
++			npages = md->num_pages;
++			memrange_efi_to_native(&addr, &npages);
++			set_memory_uc(addr, npages);
++		}
+ 
+ 		systab = (u64) (unsigned long) efi_phys.systab;
+ 		if (md->phys_addr <= systab && systab < end) {
+diff --git a/arch/x86/kernel/efi_64.c b/arch/x86/kernel/efi_64.c
+index d143a1e..d0060fd 100644
+--- a/arch/x86/kernel/efi_64.c
++++ b/arch/x86/kernel/efi_64.c
+@@ -105,14 +105,14 @@ void __init efi_reserve_bootmem(void)
+ 
+ void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size)
+ {
+-	static unsigned pages_mapped;
++	static unsigned pages_mapped __initdata;
+ 	unsigned i, pages;
++	unsigned long offset;
+ 
+-	/* phys_addr and size must be page aligned */
+-	if ((phys_addr & ~PAGE_MASK) || (size & ~PAGE_MASK))
+-		return NULL;
++	pages = PFN_UP(phys_addr + size) - PFN_DOWN(phys_addr);
++	offset = phys_addr & ~PAGE_MASK;
++	phys_addr &= PAGE_MASK;
+ 
+-	pages = size >> PAGE_SHIFT;
+ 	if (pages_mapped + pages > MAX_EFI_IO_PAGES)
+ 		return NULL;
+ 
+@@ -124,5 +124,5 @@ void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size)
+ 	}
+ 
+ 	return (void __iomem *)__fix_to_virt(FIX_EFI_IO_MAP_FIRST_PAGE - \
+-					     (pages_mapped - pages));
++					     (pages_mapped - pages)) + offset;
+ }
+diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
+index 4b87c32..2a609dc 100644
+--- a/arch/x86/kernel/entry_32.S
++++ b/arch/x86/kernel/entry_32.S
+@@ -1,5 +1,4 @@
+ /*
+- *  linux/arch/i386/entry.S
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  */
+@@ -51,6 +50,7 @@
+ #include <asm/desc.h>
+ #include <asm/percpu.h>
+ #include <asm/dwarf2.h>
++#include <asm/processor-flags.h>
+ #include "irq_vectors.h"
+ 
+ /*
+@@ -68,13 +68,6 @@
+ 
+ #define nr_syscalls ((syscall_table_size)/4)
+ 
+-CF_MASK		= 0x00000001
+-TF_MASK		= 0x00000100
+-IF_MASK		= 0x00000200
+-DF_MASK		= 0x00000400 
+-NT_MASK		= 0x00004000
+-VM_MASK		= 0x00020000
+-
+ #ifdef CONFIG_PREEMPT
+ #define preempt_stop(clobbers)	DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
+ #else
+@@ -84,7 +77,7 @@ VM_MASK		= 0x00020000
+ 
+ .macro TRACE_IRQS_IRET
+ #ifdef CONFIG_TRACE_IRQFLAGS
+-	testl $IF_MASK,PT_EFLAGS(%esp)     # interrupts off?
++	testl $X86_EFLAGS_IF,PT_EFLAGS(%esp)     # interrupts off?
+ 	jz 1f
+ 	TRACE_IRQS_ON
+ 1:
+@@ -246,7 +239,7 @@ ret_from_intr:
+ check_userspace:
+ 	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
+ 	movb PT_CS(%esp), %al
+-	andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
++	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+ 	cmpl $USER_RPL, %eax
+ 	jb resume_kernel		# not returning to v8086 or userspace
+ 
+@@ -271,7 +264,7 @@ need_resched:
+ 	movl TI_flags(%ebp), %ecx	# need_resched set ?
+ 	testb $_TIF_NEED_RESCHED, %cl
+ 	jz restore_all
+-	testl $IF_MASK,PT_EFLAGS(%esp)	# interrupts off (exception path) ?
++	testl $X86_EFLAGS_IF,PT_EFLAGS(%esp)	# interrupts off (exception path) ?
+ 	jz restore_all
+ 	call preempt_schedule_irq
+ 	jmp need_resched
+@@ -291,10 +284,10 @@ ENTRY(ia32_sysenter_target)
+ 	movl TSS_sysenter_sp0(%esp),%esp
+ sysenter_past_esp:
+ 	/*
+-	 * No need to follow this irqs on/off section: the syscall
+-	 * disabled irqs and here we enable it straight after entry:
++	 * Interrupts are disabled here, but we can't trace it until
++	 * enough kernel state to call TRACE_IRQS_OFF can be called - but
++	 * we immediately enable interrupts at that point anyway.
+ 	 */
+-	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	pushl $(__USER_DS)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET ss, 0*/
+@@ -302,6 +295,7 @@ sysenter_past_esp:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET esp, 0
+ 	pushfl
++	orl $X86_EFLAGS_IF, (%esp)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	pushl $(__USER_CS)
+ 	CFI_ADJUST_CFA_OFFSET 4
+@@ -315,6 +309,11 @@ sysenter_past_esp:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET eip, 0
+ 
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	ENABLE_INTERRUPTS(CLBR_NONE)
++
+ /*
+  * Load the potential sixth argument from user stack.
+  * Careful about security.
+@@ -322,14 +321,12 @@ sysenter_past_esp:
+ 	cmpl $__PAGE_OFFSET-3,%ebp
+ 	jae syscall_fault
+ 1:	movl (%ebp),%ebp
++	movl %ebp,PT_EBP(%esp)
+ .section __ex_table,"a"
+ 	.align 4
+ 	.long 1b,syscall_fault
+ .previous
+ 
+-	pushl %eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+ 
+ 	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+@@ -384,7 +381,7 @@ syscall_exit:
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+ 	TRACE_IRQS_OFF
+-	testl $TF_MASK,PT_EFLAGS(%esp)	# If tracing set singlestep flag on exit
++	testl $X86_EFLAGS_TF,PT_EFLAGS(%esp)	# If tracing set singlestep flag on exit
+ 	jz no_singlestep
+ 	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+ no_singlestep:
+@@ -399,7 +396,7 @@ restore_all:
+ 	# See comments in process.c:copy_thread() for details.
+ 	movb PT_OLDSS(%esp), %ah
+ 	movb PT_CS(%esp), %al
+-	andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
++	andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
+ 	cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
+ 	CFI_REMEMBER_STATE
+ 	je ldt_ss			# returning to user-space with LDT SS
+@@ -412,7 +409,7 @@ restore_nocheck_notrace:
+ irq_return:
+ 	INTERRUPT_RETURN
+ .section .fixup,"ax"
+-iret_exc:
++ENTRY(iret_exc)
+ 	pushl $0			# no error code
+ 	pushl $do_iret_error
+ 	jmp error_code
+@@ -486,7 +483,7 @@ work_resched:
+ work_notifysig:				# deal with pending signals and
+ 					# notify-resume requests
+ #ifdef CONFIG_VM86
+-	testl $VM_MASK, PT_EFLAGS(%esp)
++	testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
+ 	movl %esp, %eax
+ 	jne work_notifysig_v86		# returning to kernel-space or
+ 					# vm86-space
+@@ -543,9 +540,6 @@ END(syscall_exit_work)
+ 
+ 	RING0_INT_FRAME			# can't unwind into user space anyway
+ syscall_fault:
+-	pushl %eax			# save orig_eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+ 	movl $-EFAULT,PT_EAX(%esp)
+ 	jmp resume_userspace
+@@ -1023,6 +1017,13 @@ ENTRY(kernel_thread_helper)
+ ENDPROC(kernel_thread_helper)
+ 
+ #ifdef CONFIG_XEN
++/* Xen doesn't set %esp to be precisely what the normal sysenter
++   entrypoint expects, so fix it up before using the normal path. */
++ENTRY(xen_sysenter_target)
++	RING0_INT_FRAME
++	addl $5*4, %esp		/* remove xen-provided frame */
++	jmp sysenter_past_esp
++
+ ENTRY(xen_hypervisor_callback)
+ 	CFI_STARTPROC
+ 	pushl $0
+@@ -1041,8 +1042,9 @@ ENTRY(xen_hypervisor_callback)
+ 	cmpl $xen_iret_end_crit,%eax
+ 	jae  1f
+ 
+-	call xen_iret_crit_fixup
++	jmp  xen_iret_crit_fixup
+ 
++ENTRY(xen_do_upcall)
+ 1:	mov %esp, %eax
+ 	call xen_evtchn_do_upcall
+ 	jmp  ret_from_intr
+diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
+index c20c9e7..556a8df 100644
+--- a/arch/x86/kernel/entry_64.S
++++ b/arch/x86/kernel/entry_64.S
+@@ -319,19 +319,17 @@ badsys:
+ 	/* Do syscall tracing */
+ tracesys:			 
+ 	SAVE_REST
+-	movq $-ENOSYS,RAX(%rsp)
++	movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
+ 	FIXUP_TOP_OF_STACK %rdi
+ 	movq %rsp,%rdi
+ 	call syscall_trace_enter
+ 	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+ 	cmpq $__NR_syscall_max,%rax
+-	movq $-ENOSYS,%rcx
+-	cmova %rcx,%rax
+-	ja  1f
++	ja   int_ret_from_sys_call	/* RAX(%rsp) set to -ENOSYS above */
+ 	movq %r10,%rcx	/* fixup for C */
+ 	call *sys_call_table(,%rax,8)
+-1:	movq %rax,RAX-ARGOFFSET(%rsp)
++	movq %rax,RAX-ARGOFFSET(%rsp)
+ 	/* Use IRET because user could have changed frame */
+ 		
+ /* 
+diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c
+index 4ae7b64..021624c 100644
+--- a/arch/x86/kernel/genapic_64.c
++++ b/arch/x86/kernel/genapic_64.c
+@@ -15,6 +15,7 @@
+ #include <linux/kernel.h>
+ #include <linux/ctype.h>
+ #include <linux/init.h>
++#include <linux/hardirq.h>
+ 
+ #include <asm/smp.h>
+ #include <asm/ipi.h>
+@@ -24,20 +25,20 @@
+ #include <acpi/acpi_bus.h>
+ #endif
+ 
+-/* which logical CPU number maps to which CPU (physical APIC ID) */
+-u16 x86_cpu_to_apicid_init[NR_CPUS] __initdata
+-					= { [0 ... NR_CPUS-1] = BAD_APICID };
+-void *x86_cpu_to_apicid_early_ptr;
+-DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
+-EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
++DEFINE_PER_CPU(int, x2apic_extra_bits);
+ 
+ struct genapic __read_mostly *genapic = &apic_flat;
+ 
++static enum uv_system_type uv_system_type;
++
+ /*
+  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
+  */
+ void __init setup_apic_routing(void)
+ {
++	if (uv_system_type == UV_NON_UNIQUE_APIC)
++		genapic = &apic_x2apic_uv_x;
++	else
+ #ifdef CONFIG_ACPI
+ 	/*
+ 	 * Quirk: some x86_64 machines can only use physical APIC mode
+@@ -50,7 +51,7 @@ void __init setup_apic_routing(void)
+ 	else
+ #endif
+ 
+-	if (cpus_weight(cpu_possible_map) <= 8)
++	if (num_possible_cpus() <= 8)
+ 		genapic = &apic_flat;
+ 	else
+ 		genapic = &apic_physflat;
+@@ -64,3 +65,37 @@ void send_IPI_self(int vector)
+ {
+ 	__send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
+ }
++
++int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
++{
++	if (!strcmp(oem_id, "SGI")) {
++		if (!strcmp(oem_table_id, "UVL"))
++			uv_system_type = UV_LEGACY_APIC;
++		else if (!strcmp(oem_table_id, "UVX"))
++			uv_system_type = UV_X2APIC;
++		else if (!strcmp(oem_table_id, "UVH"))
++			uv_system_type = UV_NON_UNIQUE_APIC;
++	}
++	return 0;
++}
++
++unsigned int read_apic_id(void)
++{
++	unsigned int id;
++
++	WARN_ON(preemptible());
++	id = apic_read(APIC_ID);
++	if (uv_system_type >= UV_X2APIC)
++		id  |= __get_cpu_var(x2apic_extra_bits);
++	return id;
++}
++
++enum uv_system_type get_uv_system_type(void)
++{
++	return uv_system_type;
++}
++
++int is_uv_system(void)
++{
++	return uv_system_type != UV_NONE;
++}
+diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c
+index 07352b7..1a9c688 100644
+--- a/arch/x86/kernel/genapic_flat_64.c
++++ b/arch/x86/kernel/genapic_flat_64.c
+@@ -97,7 +97,7 @@ static void flat_send_IPI_all(int vector)
+ 
+ static int flat_apic_id_registered(void)
+ {
+-	return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
++	return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map);
+ }
+ 
+ static unsigned int flat_cpu_mask_to_apicid(cpumask_t cpumask)
+@@ -138,12 +138,9 @@ static cpumask_t physflat_target_cpus(void)
+ 
+ static cpumask_t physflat_vector_allocation_domain(int cpu)
+ {
+-	cpumask_t domain = CPU_MASK_NONE;
+-	cpu_set(cpu, domain);
+-	return domain;
++	return cpumask_of_cpu(cpu);
+ }
+ 
+-
+ static void physflat_send_IPI_mask(cpumask_t cpumask, int vector)
+ {
+ 	send_IPI_mask_sequence(cpumask, vector);
+diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c
+new file mode 100644
+index 0000000..ebf1390
+--- /dev/null
++++ b/arch/x86/kernel/genx2apic_uv_x.c
+@@ -0,0 +1,250 @@
++/*
++ * 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.
++ *
++ * SGI UV APIC functions (note: not an Intel compatible APIC)
++ *
++ * Copyright (C) 2007 Silicon Graphics, Inc. All rights reserved.
++ */
++
++#include <linux/threads.h>
++#include <linux/cpumask.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/bootmem.h>
++#include <linux/module.h>
++#include <asm/smp.h>
++#include <asm/ipi.h>
++#include <asm/genapic.h>
++#include <asm/uv/uv_mmrs.h>
++#include <asm/uv/uv_hub.h>
++
++DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
++EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);
++
++struct uv_blade_info *uv_blade_info;
++EXPORT_SYMBOL_GPL(uv_blade_info);
++
++short *uv_node_to_blade;
++EXPORT_SYMBOL_GPL(uv_node_to_blade);
++
++short *uv_cpu_to_blade;
++EXPORT_SYMBOL_GPL(uv_cpu_to_blade);
++
++short uv_possible_blades;
++EXPORT_SYMBOL_GPL(uv_possible_blades);
++
++/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
++
++static cpumask_t uv_target_cpus(void)
++{
++	return cpumask_of_cpu(0);
++}
++
++static cpumask_t uv_vector_allocation_domain(int cpu)
++{
++	cpumask_t domain = CPU_MASK_NONE;
++	cpu_set(cpu, domain);
++	return domain;
++}
++
++int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip)
++{
++	unsigned long val;
++	int nasid;
++
++	nasid = uv_apicid_to_nasid(phys_apicid);
++	val = (1UL << UVH_IPI_INT_SEND_SHFT) |
++	    (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
++	    (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
++	    APIC_DM_INIT;
++	uv_write_global_mmr64(nasid, UVH_IPI_INT, val);
++	mdelay(10);
++
++	val = (1UL << UVH_IPI_INT_SEND_SHFT) |
++	    (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
++	    (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
++	    APIC_DM_STARTUP;
++	uv_write_global_mmr64(nasid, UVH_IPI_INT, val);
++	return 0;
++}
++
++static void uv_send_IPI_one(int cpu, int vector)
++{
++	unsigned long val, apicid, lapicid;
++	int nasid;
++
++	apicid = per_cpu(x86_cpu_to_apicid, cpu); /* ZZZ - cache node-local ? */
++	lapicid = apicid & 0x3f;		/* ZZZ macro needed */
++	nasid = uv_apicid_to_nasid(apicid);
++	val =
++	    (1UL << UVH_IPI_INT_SEND_SHFT) | (lapicid <<
++					      UVH_IPI_INT_APIC_ID_SHFT) |
++	    (vector << UVH_IPI_INT_VECTOR_SHFT);
++	uv_write_global_mmr64(nasid, UVH_IPI_INT, val);
++}
++
++static void uv_send_IPI_mask(cpumask_t mask, int vector)
++{
++	unsigned int cpu;
++
++	for (cpu = 0; cpu < NR_CPUS; ++cpu)
++		if (cpu_isset(cpu, mask))
++			uv_send_IPI_one(cpu, vector);
++}
++
++static void uv_send_IPI_allbutself(int vector)
++{
++	cpumask_t mask = cpu_online_map;
++
++	cpu_clear(smp_processor_id(), mask);
++
++	if (!cpus_empty(mask))
++		uv_send_IPI_mask(mask, vector);
++}
++
++static void uv_send_IPI_all(int vector)
++{
++	uv_send_IPI_mask(cpu_online_map, vector);
++}
++
++static int uv_apic_id_registered(void)
++{
++	return 1;
++}
++
++static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
++{
++	int cpu;
++
++	/*
++	 * We're using fixed IRQ delivery, can only return one phys APIC ID.
++	 * May as well be the first.
++	 */
++	cpu = first_cpu(cpumask);
++	if ((unsigned)cpu < NR_CPUS)
++		return per_cpu(x86_cpu_to_apicid, cpu);
++	else
++		return BAD_APICID;
++}
++
++static unsigned int phys_pkg_id(int index_msb)
++{
++	return GET_APIC_ID(read_apic_id()) >> index_msb;
++}
++
++#ifdef ZZZ		/* Needs x2apic patch */
++static void uv_send_IPI_self(int vector)
++{
++	apic_write(APIC_SELF_IPI, vector);
++}
++#endif
++
++struct genapic apic_x2apic_uv_x = {
++	.name = "UV large system",
++	.int_delivery_mode = dest_Fixed,
++	.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
++	.target_cpus = uv_target_cpus,
++	.vector_allocation_domain = uv_vector_allocation_domain,/* Fixme ZZZ */
++	.apic_id_registered = uv_apic_id_registered,
++	.send_IPI_all = uv_send_IPI_all,
++	.send_IPI_allbutself = uv_send_IPI_allbutself,
++	.send_IPI_mask = uv_send_IPI_mask,
++	/* ZZZ.send_IPI_self = uv_send_IPI_self, */
++	.cpu_mask_to_apicid = uv_cpu_mask_to_apicid,
++	.phys_pkg_id = phys_pkg_id,	/* Fixme ZZZ */
++};
++
++static __cpuinit void set_x2apic_extra_bits(int nasid)
++{
++	__get_cpu_var(x2apic_extra_bits) = ((nasid >> 1) << 6);
++}
++
++/*
++ * Called on boot cpu.
++ */
++static __init void uv_system_init(void)
++{
++	union uvh_si_addr_map_config_u m_n_config;
++	int bytes, nid, cpu, lcpu, nasid, last_nasid, blade;
++	unsigned long mmr_base;
++
++	m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG);
++	mmr_base =
++	    uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
++	    ~UV_MMR_ENABLE;
++	printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base);
++
++	last_nasid = -1;
++	for_each_possible_cpu(cpu) {
++		nid = cpu_to_node(cpu);
++		nasid = uv_apicid_to_nasid(per_cpu(x86_cpu_to_apicid, cpu));
++		if (nasid != last_nasid)
++			uv_possible_blades++;
++		last_nasid = nasid;
++	}
++	printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades());
++
++	bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
++	uv_blade_info = alloc_bootmem_pages(bytes);
++
++	bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
++	uv_node_to_blade = alloc_bootmem_pages(bytes);
++	memset(uv_node_to_blade, 255, bytes);
++
++	bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
++	uv_cpu_to_blade = alloc_bootmem_pages(bytes);
++	memset(uv_cpu_to_blade, 255, bytes);
++
++	last_nasid = -1;
++	blade = -1;
++	lcpu = -1;
++	for_each_possible_cpu(cpu) {
++		nid = cpu_to_node(cpu);
++		nasid = uv_apicid_to_nasid(per_cpu(x86_cpu_to_apicid, cpu));
++		if (nasid != last_nasid) {
++			blade++;
++			lcpu = -1;
++			uv_blade_info[blade].nr_posible_cpus = 0;
++			uv_blade_info[blade].nr_online_cpus = 0;
++		}
++		last_nasid = nasid;
++		lcpu++;
++
++		uv_cpu_hub_info(cpu)->m_val = m_n_config.s.m_skt;
++		uv_cpu_hub_info(cpu)->n_val = m_n_config.s.n_skt;
++		uv_cpu_hub_info(cpu)->numa_blade_id = blade;
++		uv_cpu_hub_info(cpu)->blade_processor_id = lcpu;
++		uv_cpu_hub_info(cpu)->local_nasid = nasid;
++		uv_cpu_hub_info(cpu)->gnode_upper =
++		    nasid & ~((1 << uv_hub_info->n_val) - 1);
++		uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
++		uv_cpu_hub_info(cpu)->coherency_domain_number = 0;/* ZZZ */
++		uv_blade_info[blade].nasid = nasid;
++		uv_blade_info[blade].nr_posible_cpus++;
++		uv_node_to_blade[nid] = blade;
++		uv_cpu_to_blade[cpu] = blade;
++
++		printk(KERN_DEBUG "UV cpu %d, apicid 0x%x, nasid %d, nid %d\n",
++		       cpu, per_cpu(x86_cpu_to_apicid, cpu), nasid, nid);
++		printk(KERN_DEBUG "UV   lcpu %d, blade %d\n", lcpu, blade);
++	}
++}
++
++/*
++ * Called on each cpu to initialize the per_cpu UV data area.
++ */
++void __cpuinit uv_cpu_init(void)
++{
++	if (!uv_node_to_blade)
++		uv_system_init();
++
++	uv_blade_info[uv_numa_blade_id()].nr_online_cpus++;
++
++	if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
++		set_x2apic_extra_bits(uv_hub_info->local_nasid);
++}
+diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
+new file mode 100644
+index 0000000..3db0590
+--- /dev/null
++++ b/arch/x86/kernel/head32.c
+@@ -0,0 +1,14 @@
++/*
++ *  linux/arch/i386/kernel/head32.c -- prepare to run common code
++ *
++ *  Copyright (C) 2000 Andrea Arcangeli <andrea at suse.de> SuSE
++ *  Copyright (C) 2007 Eric Biederman <ebiederm at xmission.com>
++ */
++
++#include <linux/init.h>
++#include <linux/start_kernel.h>
++
++void __init i386_start_kernel(void)
++{
++	start_kernel();
++}
+diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
+index ad24408..d31d6b7 100644
+--- a/arch/x86/kernel/head64.c
++++ b/arch/x86/kernel/head64.c
+@@ -22,6 +22,7 @@
+ #include <asm/sections.h>
+ #include <asm/kdebug.h>
+ #include <asm/e820.h>
++#include <asm/bios_ebda.h>
+ 
+ static void __init zap_identity_mappings(void)
+ {
+@@ -49,39 +50,73 @@ static void __init copy_bootdata(char *real_mode_data)
+ 	}
+ }
+ 
+-#define EBDA_ADDR_POINTER 0x40E
++#define BIOS_LOWMEM_KILOBYTES 0x413
+ 
+-static __init void reserve_ebda(void)
++/*
++ * The BIOS places the EBDA/XBDA at the top of conventional
++ * memory, and usually decreases the reported amount of
++ * conventional memory (int 0x12) too. This also contains a
++ * workaround for Dell systems that neglect to reserve EBDA.
++ * The same workaround also avoids a problem with the AMD768MPX
++ * chipset: reserve a page before VGA to prevent PCI prefetch
++ * into it (errata #56). Usually the page is reserved anyways,
++ * unless you have no PS/2 mouse plugged in.
++ */
++static void __init reserve_ebda_region(void)
+ {
+-	unsigned ebda_addr, ebda_size;
++	unsigned int lowmem, ebda_addr;
++
++	/* To determine the position of the EBDA and the */
++	/* end of conventional memory, we need to look at */
++	/* the BIOS data area. In a paravirtual environment */
++	/* that area is absent. We'll just have to assume */
++	/* that the paravirt case can handle memory setup */
++	/* correctly, without our help. */
++	if (paravirt_enabled())
++		return;
+ 
+-	/*
+-	 * there is a real-mode segmented pointer pointing to the
+-	 * 4K EBDA area at 0x40E
+-	 */
+-	ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
+-	ebda_addr <<= 4;
++	/* end of low (conventional) memory */
++	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
++	lowmem <<= 10;
+ 
+-	if (!ebda_addr)
+-		return;
++	/* start of EBDA area */
++	ebda_addr = get_bios_ebda();
+ 
+-	ebda_size = *(unsigned short *)__va(ebda_addr);
++	/* Fixup: bios puts an EBDA in the top 64K segment */
++	/* of conventional memory, but does not adjust lowmem. */
++	if ((lowmem - ebda_addr) <= 0x10000)
++		lowmem = ebda_addr;
+ 
+-	/* Round EBDA up to pages */
+-	if (ebda_size == 0)
+-		ebda_size = 1;
+-	ebda_size <<= 10;
+-	ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
+-	if (ebda_size > 64*1024)
+-		ebda_size = 64*1024;
++	/* Fixup: bios does not report an EBDA at all. */
++	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
++	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
++		lowmem = 0x9f000;
+ 
+-	reserve_early(ebda_addr, ebda_addr + ebda_size, "EBDA");
++	/* Paranoia: should never happen, but... */
++	if ((lowmem == 0) || (lowmem >= 0x100000))
++		lowmem = 0x9f000;
++
++	/* reserve all memory between lowmem and the 1MB mark */
++	reserve_early(lowmem, 0x100000, "BIOS reserved");
+ }
+ 
+ void __init x86_64_start_kernel(char * real_mode_data)
+ {
+ 	int i;
+ 
++	/*
++	 * Build-time sanity checks on the kernel image and module
++	 * area mappings. (these are purely build-time and produce no code)
++	 */
++	BUILD_BUG_ON(MODULES_VADDR < KERNEL_IMAGE_START);
++	BUILD_BUG_ON(MODULES_VADDR-KERNEL_IMAGE_START < KERNEL_IMAGE_SIZE);
++	BUILD_BUG_ON(MODULES_LEN + KERNEL_IMAGE_SIZE > 2*PUD_SIZE);
++	BUILD_BUG_ON((KERNEL_IMAGE_START & ~PMD_MASK) != 0);
++	BUILD_BUG_ON((MODULES_VADDR & ~PMD_MASK) != 0);
++	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
++	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
++				(__START_KERNEL & PGDIR_MASK)));
++
+ 	/* clear bss before set_intr_gate with early_idt_handler */
+ 	clear_bss();
+ 
+@@ -91,7 +126,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
+ 	/* Cleanup the over mapped high alias */
+ 	cleanup_highmap();
+ 
+-	for (i = 0; i < IDT_ENTRIES; i++) {
++	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
+ #ifdef CONFIG_EARLY_PRINTK
+ 		set_intr_gate(i, &early_idt_handlers[i]);
+ #else
+@@ -110,6 +145,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
+ 
+ 	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
+ 
++#ifdef CONFIG_BLK_DEV_INITRD
+ 	/* Reserve INITRD */
+ 	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+ 		unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
+@@ -117,8 +153,9 @@ void __init x86_64_start_kernel(char * real_mode_data)
+ 		unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
+ 		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+ 	}
++#endif
+ 
+-	reserve_ebda();
++	reserve_ebda_region();
+ 
+ 	/*
+ 	 * At this point everything still needed from the boot loader
+diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
+index 74d87ea..90f038a 100644
+--- a/arch/x86/kernel/head_32.S
++++ b/arch/x86/kernel/head_32.S
+@@ -1,5 +1,4 @@
+ /*
+- *  linux/arch/i386/kernel/head.S -- the 32-bit startup code.
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  *
+@@ -450,7 +449,7 @@ is386:	movl $2,%ecx		# set MP
+ 	jmp initialize_secondary # all other CPUs call initialize_secondary
+ 1:
+ #endif /* CONFIG_SMP */
+-	jmp start_kernel
++	jmp i386_start_kernel
+ 
+ /*
+  * We depend on ET to be correct. This checks for 287/387.
+diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
+index a007454..10a1955 100644
+--- a/arch/x86/kernel/head_64.S
++++ b/arch/x86/kernel/head_64.S
+@@ -132,10 +132,6 @@ ident_complete:
+ 	addq	%rbp, trampoline_level4_pgt + 0(%rip)
+ 	addq	%rbp, trampoline_level4_pgt + (511*8)(%rip)
+ #endif
+-#ifdef CONFIG_ACPI_SLEEP
+-	addq	%rbp, wakeup_level4_pgt + 0(%rip)
+-	addq	%rbp, wakeup_level4_pgt + (511*8)(%rip)
+-#endif
+ 
+ 	/* Due to ENTRY(), sometimes the empty space gets filled with
+ 	 * zeros. Better take a jmp than relying on empty space being
+@@ -267,21 +263,16 @@ ENTRY(secondary_startup_64)
+ bad_address:
+ 	jmp bad_address
+ 
++	.section ".init.text","ax"
+ #ifdef CONFIG_EARLY_PRINTK
+-.macro early_idt_tramp first, last
+-	.ifgt \last-\first
+-	early_idt_tramp \first, \last-1
+-	.endif
+-	movl $\last,%esi
+-	jmp early_idt_handler
+-.endm
+-
+ 	.globl early_idt_handlers
+ early_idt_handlers:
+-	early_idt_tramp 0, 63
+-	early_idt_tramp 64, 127
+-	early_idt_tramp 128, 191
+-	early_idt_tramp 192, 255
++	i = 0
++	.rept NUM_EXCEPTION_VECTORS
++	movl $i, %esi
++	jmp early_idt_handler
++	i = i + 1
++	.endr
+ #endif
+ 
+ ENTRY(early_idt_handler)
+@@ -327,6 +318,7 @@ early_idt_msg:
+ early_idt_ripmsg:
+ 	.asciz "RIP %s\n"
+ #endif /* CONFIG_EARLY_PRINTK */
++	.previous
+ 
+ .balign PAGE_SIZE
+ 
+@@ -383,12 +375,12 @@ NEXT_PAGE(level2_ident_pgt)
+ 
+ NEXT_PAGE(level2_kernel_pgt)
+ 	/*
+-	 * 128 MB kernel mapping. We spend a full page on this pagetable
++	 * 512 MB kernel mapping. We spend a full page on this pagetable
+ 	 * anyway.
+ 	 *
+ 	 * The kernel code+data+bss must not be bigger than that.
+ 	 *
+-	 * (NOTE: at +128MB starts the module area, see MODULES_VADDR.
++	 * (NOTE: at +512MB starts the module area, see MODULES_VADDR.
+ 	 *  If you want to increase this then increase MODULES_VADDR
+ 	 *  too.)
+ 	 */
+diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
+index 36652ea..9007f9e 100644
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -218,7 +218,7 @@ static void hpet_legacy_clockevent_register(void)
+ 	hpet_freq = 1000000000000000ULL;
+ 	do_div(hpet_freq, hpet_period);
+ 	hpet_clockevent.mult = div_sc((unsigned long) hpet_freq,
+-				      NSEC_PER_SEC, 32);
++				      NSEC_PER_SEC, hpet_clockevent.shift);
+ 	/* Calculate the min / max delta */
+ 	hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
+ 							   &hpet_clockevent);
+diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c
+index 0616278..deb4378 100644
+--- a/arch/x86/kernel/i386_ksyms_32.c
++++ b/arch/x86/kernel/i386_ksyms_32.c
+@@ -1,13 +1,8 @@
+ #include <linux/module.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/desc.h>
+ #include <asm/pgtable.h>
+ 
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+ /* Networking helper routines. */
+ EXPORT_SYMBOL(csum_partial_copy_generic);
+ 
+diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
+index d2e39e6..db6839b 100644
+--- a/arch/x86/kernel/i387.c
++++ b/arch/x86/kernel/i387.c
+@@ -5,51 +5,48 @@
+  *  General FPU state handling cleanups
+  *	Gareth Hughes <gareth at valinux.com>, May 2000
+  */
+-
+-#include <linux/sched.h>
+ #include <linux/module.h>
+ #include <linux/regset.h>
++#include <linux/sched.h>
++
++#include <asm/sigcontext.h>
+ #include <asm/processor.h>
+-#include <asm/i387.h>
+ #include <asm/math_emu.h>
+-#include <asm/sigcontext.h>
+-#include <asm/user.h>
+-#include <asm/ptrace.h>
+ #include <asm/uaccess.h>
++#include <asm/ptrace.h>
++#include <asm/i387.h>
++#include <asm/user.h>
+ 
+ #ifdef CONFIG_X86_64
+-
+-#include <asm/sigcontext32.h>
+-#include <asm/user32.h>
+-
++# include <asm/sigcontext32.h>
++# include <asm/user32.h>
+ #else
+-
+-#define	save_i387_ia32		save_i387
+-#define	restore_i387_ia32	restore_i387
+-
+-#define _fpstate_ia32 		_fpstate
+-#define user_i387_ia32_struct	user_i387_struct
+-#define user32_fxsr_struct	user_fxsr_struct
+-
++# define save_i387_ia32		save_i387
++# define restore_i387_ia32	restore_i387
++# define _fpstate_ia32		_fpstate
++# define user_i387_ia32_struct	user_i387_struct
++# define user32_fxsr_struct	user_fxsr_struct
+ #endif
+ 
+ #ifdef CONFIG_MATH_EMULATION
+-#define HAVE_HWFP (boot_cpu_data.hard_math)
++# define HAVE_HWFP		(boot_cpu_data.hard_math)
+ #else
+-#define HAVE_HWFP 1
++# define HAVE_HWFP		1
+ #endif
+ 
+-static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu;
++static unsigned int		mxcsr_feature_mask __read_mostly = 0xffffffffu;
++unsigned int xstate_size;
++static struct i387_fxsave_struct fx_scratch __cpuinitdata;
+ 
+-void mxcsr_feature_mask_init(void)
++void __cpuinit mxcsr_feature_mask_init(void)
+ {
+ 	unsigned long mask = 0;
++
+ 	clts();
+ 	if (cpu_has_fxsr) {
+-		memset(&current->thread.i387.fxsave, 0,
+-		       sizeof(struct i387_fxsave_struct));
+-		asm volatile("fxsave %0" : : "m" (current->thread.i387.fxsave));
+-		mask = current->thread.i387.fxsave.mxcsr_mask;
++		memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct));
++		asm volatile("fxsave %0" : : "m" (fx_scratch));
++		mask = fx_scratch.mxcsr_mask;
+ 		if (mask == 0)
+ 			mask = 0x0000ffbf;
+ 	}
+@@ -57,6 +54,16 @@ void mxcsr_feature_mask_init(void)
+ 	stts();
+ }
+ 
++void __init init_thread_xstate(void)
++{
++	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
+@@ -65,14 +72,11 @@ void mxcsr_feature_mask_init(void)
+ void __cpuinit fpu_init(void)
+ {
+ 	unsigned long oldcr0 = read_cr0();
+-	extern void __bad_fxsave_alignment(void);
+ 
+-	if (offsetof(struct task_struct, thread.i387.fxsave) & 15)
+-		__bad_fxsave_alignment();
+ 	set_in_cr4(X86_CR4_OSFXSR);
+ 	set_in_cr4(X86_CR4_OSXMMEXCPT);
+ 
+-	write_cr0(oldcr0 & ~((1UL<<3)|(1UL<<2))); /* clear TS and EM */
++	write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */
+ 
+ 	mxcsr_feature_mask_init();
+ 	/* clean state in init */
+@@ -87,32 +91,44 @@ void __cpuinit fpu_init(void)
+  * value at reset if we support XMM instructions and then
+  * remeber the current task has used the FPU.
+  */
+-void init_fpu(struct task_struct *tsk)
++int init_fpu(struct task_struct *tsk)
+ {
+ 	if (tsk_used_math(tsk)) {
+ 		if (tsk == current)
+ 			unlazy_fpu(tsk);
+-		return;
++		return 0;
++	}
++
++	/*
++	 * Memory allocation at the first usage of the FPU and other state.
++	 */
++	if (!tsk->thread.xstate) {
++		tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
++						      GFP_KERNEL);
++		if (!tsk->thread.xstate)
++			return -ENOMEM;
+ 	}
+ 
+ 	if (cpu_has_fxsr) {
+-		memset(&tsk->thread.i387.fxsave, 0,
+-		       sizeof(struct i387_fxsave_struct));
+-		tsk->thread.i387.fxsave.cwd = 0x37f;
++		struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave;
++
++		memset(fx, 0, xstate_size);
++		fx->cwd = 0x37f;
+ 		if (cpu_has_xmm)
+-			tsk->thread.i387.fxsave.mxcsr = MXCSR_DEFAULT;
++			fx->mxcsr = MXCSR_DEFAULT;
+ 	} else {
+-		memset(&tsk->thread.i387.fsave, 0,
+-		       sizeof(struct i387_fsave_struct));
+-		tsk->thread.i387.fsave.cwd = 0xffff037fu;
+-		tsk->thread.i387.fsave.swd = 0xffff0000u;
+-		tsk->thread.i387.fsave.twd = 0xffffffffu;
+-		tsk->thread.i387.fsave.fos = 0xffff0000u;
++		struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave;
++		memset(fp, 0, xstate_size);
++		fp->cwd = 0xffff037fu;
++		fp->swd = 0xffff0000u;
++		fp->twd = 0xffffffffu;
++		fp->fos = 0xffff0000u;
+ 	}
+ 	/*
+ 	 * Only the device not available exception or ptrace can call init_fpu.
+ 	 */
+ 	set_stopped_child_used_math(tsk);
++	return 0;
+ }
+ 
+ int fpregs_active(struct task_struct *target, const struct user_regset *regset)
+@@ -129,13 +145,17 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
+ 		unsigned int pos, unsigned int count,
+ 		void *kbuf, void __user *ubuf)
+ {
++	int ret;
++
+ 	if (!cpu_has_fxsr)
+ 		return -ENODEV;
+ 
+-	init_fpu(target);
++	ret = init_fpu(target);
++	if (ret)
++		return ret;
+ 
+ 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+-				   &target->thread.i387.fxsave, 0, -1);
++				   &target->thread.xstate->fxsave, 0, -1);
+ }
+ 
+ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
+@@ -147,16 +167,19 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
+ 	if (!cpu_has_fxsr)
+ 		return -ENODEV;
+ 
+-	init_fpu(target);
++	ret = init_fpu(target);
++	if (ret)
++		return ret;
++
+ 	set_stopped_child_used_math(target);
+ 
+ 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+-				 &target->thread.i387.fxsave, 0, -1);
++				 &target->thread.xstate->fxsave, 0, -1);
+ 
+ 	/*
+ 	 * mxcsr reserved bits must be masked to zero for security reasons.
+ 	 */
+-	target->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
++	target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
+ 
+ 	return ret;
+ }
+@@ -178,6 +201,7 @@ static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
+ 	tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+ 	tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+ 	tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
++
+ 	return tmp;
+ }
+ 
+@@ -232,10 +256,10 @@ static inline u32 twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave)
+  * FXSR floating point environment conversions.
+  */
+ 
+-static void convert_from_fxsr(struct user_i387_ia32_struct *env,
+-			      struct task_struct *tsk)
++static void
++convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
+ {
+-	struct i387_fxsave_struct *fxsave = &tsk->thread.i387.fxsave;
++	struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave;
+ 	struct _fpreg *to = (struct _fpreg *) &env->st_space[0];
+ 	struct _fpxreg *from = (struct _fpxreg *) &fxsave->st_space[0];
+ 	int i;
+@@ -252,10 +276,11 @@ static void convert_from_fxsr(struct user_i387_ia32_struct *env,
+ 		 * should be actually ds/cs at fpu exception time, but
+ 		 * that information is not available in 64bit mode.
+ 		 */
+-		asm("mov %%ds,%0" : "=r" (env->fos));
+-		asm("mov %%cs,%0" : "=r" (env->fcs));
++		asm("mov %%ds, %[fos]" : [fos] "=r" (env->fos));
++		asm("mov %%cs, %[fcs]" : [fcs] "=r" (env->fcs));
+ 	} else {
+ 		struct pt_regs *regs = task_pt_regs(tsk);
++
+ 		env->fos = 0xffff0000 | tsk->thread.ds;
+ 		env->fcs = regs->cs;
+ 	}
+@@ -274,7 +299,7 @@ static void convert_to_fxsr(struct task_struct *tsk,
+ 			    const struct user_i387_ia32_struct *env)
+ 
+ {
+-	struct i387_fxsave_struct *fxsave = &tsk->thread.i387.fxsave;
++	struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave;
+ 	struct _fpreg *from = (struct _fpreg *) &env->st_space[0];
+ 	struct _fpxreg *to = (struct _fpxreg *) &fxsave->st_space[0];
+ 	int i;
+@@ -303,15 +328,20 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
+ 	       void *kbuf, void __user *ubuf)
+ {
+ 	struct user_i387_ia32_struct env;
++	int ret;
+ 
+ 	if (!HAVE_HWFP)
+ 		return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf);
+ 
+-	init_fpu(target);
++	ret = init_fpu(target);
++	if (ret)
++		return ret;
+ 
+-	if (!cpu_has_fxsr)
++	if (!cpu_has_fxsr) {
+ 		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+-					   &target->thread.i387.fsave, 0, -1);
++					   &target->thread.xstate->fsave, 0,
++					   -1);
++	}
+ 
+ 	if (kbuf && pos == 0 && count == sizeof(env)) {
+ 		convert_from_fxsr(kbuf, target);
+@@ -319,6 +349,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
+ 	}
+ 
+ 	convert_from_fxsr(&env, target);
++
+ 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &env, 0, -1);
+ }
+ 
+@@ -332,12 +363,16 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
+ 	if (!HAVE_HWFP)
+ 		return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);
+ 
+-	init_fpu(target);
++	ret = init_fpu(target);
++	if (ret)
++		return ret;
++
+ 	set_stopped_child_used_math(target);
+ 
+-	if (!cpu_has_fxsr)
++	if (!cpu_has_fxsr) {
+ 		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+-					  &target->thread.i387.fsave, 0, -1);
++					  &target->thread.xstate->fsave, 0, -1);
++	}
+ 
+ 	if (pos > 0 || count < sizeof(env))
+ 		convert_from_fxsr(&env, target);
+@@ -356,11 +391,11 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
+ static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf)
+ {
+ 	struct task_struct *tsk = current;
++	struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave;
+ 
+ 	unlazy_fpu(tsk);
+-	tsk->thread.i387.fsave.status = tsk->thread.i387.fsave.swd;
+-	if (__copy_to_user(buf, &tsk->thread.i387.fsave,
+-			   sizeof(struct i387_fsave_struct)))
++	fp->status = fp->swd;
++	if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct)))
+ 		return -1;
+ 	return 1;
+ }
+@@ -368,6 +403,7 @@ static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf)
+ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf)
+ {
+ 	struct task_struct *tsk = current;
++	struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave;
+ 	struct user_i387_ia32_struct env;
+ 	int err = 0;
+ 
+@@ -377,12 +413,12 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf)
+ 	if (__copy_to_user(buf, &env, sizeof(env)))
+ 		return -1;
+ 
+-	err |= __put_user(tsk->thread.i387.fxsave.swd, &buf->status);
++	err |= __put_user(fx->swd, &buf->status);
+ 	err |= __put_user(X86_FXSR_MAGIC, &buf->magic);
+ 	if (err)
+ 		return -1;
+ 
+-	if (__copy_to_user(&buf->_fxsr_env[0], &tsk->thread.i387.fxsave,
++	if (__copy_to_user(&buf->_fxsr_env[0], fx,
+ 			   sizeof(struct i387_fxsave_struct)))
+ 		return -1;
+ 	return 1;
+@@ -392,46 +428,48 @@ int save_i387_ia32(struct _fpstate_ia32 __user *buf)
+ {
+ 	if (!used_math())
+ 		return 0;
+-
+-	/* This will cause a "finit" to be triggered by the next
++	/*
++	 * This will cause a "finit" to be triggered by the next
+ 	 * attempted FPU operation by the 'current' process.
+ 	 */
+ 	clear_used_math();
+ 
+-	if (HAVE_HWFP) {
+-		if (cpu_has_fxsr) {
+-			return save_i387_fxsave(buf);
+-		} else {
+-			return save_i387_fsave(buf);
+-		}
+-	} else {
++	if (!HAVE_HWFP) {
+ 		return fpregs_soft_get(current, NULL,
+ 				       0, sizeof(struct user_i387_ia32_struct),
+ 				       NULL, buf) ? -1 : 1;
+ 	}
++
++	if (cpu_has_fxsr)
++		return save_i387_fxsave(buf);
++	else
++		return save_i387_fsave(buf);
+ }
+ 
+ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf)
+ {
+ 	struct task_struct *tsk = current;
++
+ 	clear_fpu(tsk);
+-	return __copy_from_user(&tsk->thread.i387.fsave, buf,
++	return __copy_from_user(&tsk->thread.xstate->fsave, buf,
+ 				sizeof(struct i387_fsave_struct));
+ }
+ 
+ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf)
+ {
+-	int err;
+ 	struct task_struct *tsk = current;
+ 	struct user_i387_ia32_struct env;
++	int err;
++
+ 	clear_fpu(tsk);
+-	err = __copy_from_user(&tsk->thread.i387.fxsave, &buf->_fxsr_env[0],
++	err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0],
+ 			       sizeof(struct i387_fxsave_struct));
+ 	/* mxcsr reserved bits must be masked to zero for security reasons */
+-	tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
++	tsk->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
+ 	if (err || __copy_from_user(&env, buf, sizeof(env)))
+ 		return 1;
+ 	convert_to_fxsr(tsk, &env);
++
+ 	return 0;
+ }
+ 
+@@ -440,17 +478,17 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf)
+ 	int err;
+ 
+ 	if (HAVE_HWFP) {
+-		if (cpu_has_fxsr) {
++		if (cpu_has_fxsr)
+ 			err = restore_i387_fxsave(buf);
+-		} else {
++		else
+ 			err = restore_i387_fsave(buf);
+-		}
+ 	} else {
+ 		err = fpregs_soft_set(current, NULL,
+ 				      0, sizeof(struct user_i387_ia32_struct),
+ 				      NULL, buf) != 0;
+ 	}
+ 	set_used_math();
++
+ 	return err;
+ }
+ 
+@@ -463,8 +501,8 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf)
+  */
+ int dump_fpu(struct pt_regs *regs, struct user_i387_struct *fpu)
+ {
+-	int fpvalid;
+ 	struct task_struct *tsk = current;
++	int fpvalid;
+ 
+ 	fpvalid = !!used_math();
+ 	if (fpvalid)
+diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
+index 8540abe..c1b5e3e 100644
+--- a/arch/x86/kernel/i8253.c
++++ b/arch/x86/kernel/i8253.c
+@@ -115,7 +115,8 @@ void __init setup_pit_timer(void)
+ 	 * IO_APIC has been initialized.
+ 	 */
+ 	pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
+-	pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
++	pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
++				     pit_clockevent.shift);
+ 	pit_clockevent.max_delta_ns =
+ 		clockevent_delta2ns(0x7FFF, &pit_clockevent);
+ 	pit_clockevent.min_delta_ns =
+@@ -224,7 +225,8 @@ static int __init init_pit_clocksource(void)
+ 	    pit_clockevent.mode != CLOCK_EVT_MODE_PERIODIC)
+ 		return 0;
+ 
+-	clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
++	clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
++						   clocksource_pit.shift);
+ 	return clocksource_register(&clocksource_pit);
+ }
+ arch_initcall(init_pit_clocksource);
+diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
+index 4ca5486..696b8e4 100644
+--- a/arch/x86/kernel/io_apic_32.c
++++ b/arch/x86/kernel/io_apic_32.c
+@@ -71,6 +71,16 @@ int sis_apic_bug = -1;
+  */
+ int nr_ioapic_registers[MAX_IO_APICS];
+ 
++/* I/O APIC entries */
++struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++int nr_ioapics;
++
++/* MP IRQ source entries */
++struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++
++/* # of MP IRQ source entries */
++int mp_irq_entries;
++
+ static int disable_timer_pin_1 __initdata;
+ 
+ /*
+@@ -810,10 +820,7 @@ static int __init find_isa_irq_pin(int irq, int type)
+ 	for (i = 0; i < mp_irq_entries; i++) {
+ 		int lbus = mp_irqs[i].mpc_srcbus;
+ 
+-		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_MCA
+-		    ) &&
++		if (test_bit(lbus, mp_bus_not_pci) &&
+ 		    (mp_irqs[i].mpc_irqtype == type) &&
+ 		    (mp_irqs[i].mpc_srcbusirq == irq))
+ 
+@@ -829,10 +836,7 @@ static int __init find_isa_irq_apic(int irq, int type)
+ 	for (i = 0; i < mp_irq_entries; i++) {
+ 		int lbus = mp_irqs[i].mpc_srcbus;
+ 
+-		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_MCA
+-		    ) &&
++		if (test_bit(lbus, mp_bus_not_pci) &&
+ 		    (mp_irqs[i].mpc_irqtype == type) &&
+ 		    (mp_irqs[i].mpc_srcbusirq == irq))
+ 			break;
+@@ -872,7 +876,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
+ 			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
+ 				break;
+ 
+-		if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
++		if (!test_bit(lbus, mp_bus_not_pci) &&
+ 		    !mp_irqs[i].mpc_irqtype &&
+ 		    (bus == lbus) &&
+ 		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
+@@ -921,6 +925,7 @@ void __init setup_ioapic_dest(void)
+ }
+ #endif
+ 
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ /*
+  * EISA Edge/Level control register, ELCR
+  */
+@@ -934,6 +939,13 @@ static int EISA_ELCR(unsigned int irq)
+ 			"Broken MPtable reports ISA irq %d\n", irq);
+ 	return 0;
+ }
++#endif
++
++/* ISA interrupts are always polarity zero edge triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_ISA_trigger(idx)	(0)
++#define default_ISA_polarity(idx)	(0)
+ 
+ /* EISA interrupts are always polarity zero and can be edge or level
+  * trigger depending on the ELCR value.  If an interrupt is listed as
+@@ -941,13 +953,7 @@ static int EISA_ELCR(unsigned int irq)
+  * be read in from the ELCR */
+ 
+ #define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
+-#define default_EISA_polarity(idx)	(0)
+-
+-/* ISA interrupts are always polarity zero edge triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_ISA_trigger(idx)	(0)
+-#define default_ISA_polarity(idx)	(0)
++#define default_EISA_polarity(idx)	default_ISA_polarity(idx)
+ 
+ /* PCI interrupts are always polarity one level triggered,
+  * when listed as conforming in the MP table. */
+@@ -959,7 +965,7 @@ static int EISA_ELCR(unsigned int irq)
+  * when listed as conforming in the MP table. */
+ 
+ #define default_MCA_trigger(idx)	(1)
+-#define default_MCA_polarity(idx)	(0)
++#define default_MCA_polarity(idx)	default_ISA_polarity(idx)
+ 
+ static int MPBIOS_polarity(int idx)
+ {
+@@ -973,35 +979,9 @@ static int MPBIOS_polarity(int idx)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent polarity */
+ 		{
+-			switch (mp_bus_id_to_type[bus])
+-			{
+-				case MP_BUS_ISA: /* ISA pin */
+-				{
+-					polarity = default_ISA_polarity(idx);
+-					break;
+-				}
+-				case MP_BUS_EISA: /* EISA pin */
+-				{
+-					polarity = default_EISA_polarity(idx);
+-					break;
+-				}
+-				case MP_BUS_PCI: /* PCI pin */
+-				{
+-					polarity = default_PCI_polarity(idx);
+-					break;
+-				}
+-				case MP_BUS_MCA: /* MCA pin */
+-				{
+-					polarity = default_MCA_polarity(idx);
+-					break;
+-				}
+-				default:
+-				{
+-					printk(KERN_WARNING "broken BIOS!!\n");
+-					polarity = 1;
+-					break;
+-				}
+-			}
++			polarity = test_bit(bus, mp_bus_not_pci)?
++				default_ISA_polarity(idx):
++				default_PCI_polarity(idx);
+ 			break;
+ 		}
+ 		case 1: /* high active */
+@@ -1042,11 +1022,15 @@ static int MPBIOS_trigger(int idx)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent */
+ 		{
++			trigger = test_bit(bus, mp_bus_not_pci)?
++					default_ISA_trigger(idx):
++					default_PCI_trigger(idx);
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ 			switch (mp_bus_id_to_type[bus])
+ 			{
+ 				case MP_BUS_ISA: /* ISA pin */
+ 				{
+-					trigger = default_ISA_trigger(idx);
++					/* set before the switch */
+ 					break;
+ 				}
+ 				case MP_BUS_EISA: /* EISA pin */
+@@ -1056,7 +1040,7 @@ static int MPBIOS_trigger(int idx)
+ 				}
+ 				case MP_BUS_PCI: /* PCI pin */
+ 				{
+-					trigger = default_PCI_trigger(idx);
++					/* set before the switch */
+ 					break;
+ 				}
+ 				case MP_BUS_MCA: /* MCA pin */
+@@ -1071,6 +1055,7 @@ static int MPBIOS_trigger(int idx)
+ 					break;
+ 				}
+ 			}
++#endif
+ 			break;
+ 		}
+ 		case 1: /* edge */
+@@ -1120,39 +1105,22 @@ static int pin_2_irq(int idx, int apic, int pin)
+ 	if (mp_irqs[idx].mpc_dstirq != pin)
+ 		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+ 
+-	switch (mp_bus_id_to_type[bus])
+-	{
+-		case MP_BUS_ISA: /* ISA pin */
+-		case MP_BUS_EISA:
+-		case MP_BUS_MCA:
+-		{
+-			irq = mp_irqs[idx].mpc_srcbusirq;
+-			break;
+-		}
+-		case MP_BUS_PCI: /* PCI pin */
+-		{
+-			/*
+-			 * PCI IRQs are mapped in order
+-			 */
+-			i = irq = 0;
+-			while (i < apic)
+-				irq += nr_ioapic_registers[i++];
+-			irq += pin;
+-
+-			/*
+-			 * For MPS mode, so far only needed by ES7000 platform
+-			 */
+-			if (ioapic_renumber_irq)
+-				irq = ioapic_renumber_irq(apic, irq);
++	if (test_bit(bus, mp_bus_not_pci))
++		irq = mp_irqs[idx].mpc_srcbusirq;
++	else {
++		/*
++		 * PCI IRQs are mapped in order
++		 */
++		i = irq = 0;
++		while (i < apic)
++			irq += nr_ioapic_registers[i++];
++		irq += pin;
+ 
+-			break;
+-		}
+-		default:
+-		{
+-			printk(KERN_ERR "unknown bus type %d.\n",bus); 
+-			irq = 0;
+-			break;
+-		}
++		/*
++		 * For MPS mode, so far only needed by ES7000 platform
++		 */
++		if (ioapic_renumber_irq)
++			irq = ioapic_renumber_irq(apic, irq);
+ 	}
+ 
+ 	/*
+@@ -1260,7 +1228,6 @@ static void __init setup_IO_APIC_irqs(void)
+ {
+ 	struct IO_APIC_route_entry entry;
+ 	int apic, pin, idx, irq, first_notcon = 1, vector;
+-	unsigned long flags;
+ 
+ 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+ 
+@@ -1326,9 +1293,7 @@ static void __init setup_IO_APIC_irqs(void)
+ 			if (!apic && (irq < 16))
+ 				disable_8259A_irq(irq);
+ 		}
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		__ioapic_write_entry(apic, pin, entry);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
++		ioapic_write_entry(apic, pin, entry);
+ 	}
+ 	}
+ 
+@@ -1524,8 +1489,8 @@ void /*__init*/ print_local_APIC(void * dummy)
+ 
+ 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ 		smp_processor_id(), hard_smp_processor_id());
+-	v = apic_read(APIC_ID);
+-	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(v));
++	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v,
++			GET_APIC_ID(read_apic_id()));
+ 	v = apic_read(APIC_LVR);
+ 	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+ 	ver = GET_APIC_VERSION(v);
+@@ -1734,7 +1699,7 @@ void disable_IO_APIC(void)
+ 		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
+ 		entry.vector          = 0;
+ 		entry.dest.physical.physical_dest =
+-					GET_APIC_ID(apic_read(APIC_ID));
++					GET_APIC_ID(read_apic_id());
+ 
+ 		/*
+ 		 * Add it to the IO-APIC irq-routing table:
+@@ -2031,8 +1996,7 @@ static inline void init_IO_APIC_traps(void)
+ 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+ 	 */
+ 	for (irq = 0; irq < NR_IRQS ; irq++) {
+-		int tmp = irq;
+-		if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
++		if (IO_APIC_IRQ(irq) && !irq_vector[irq]) {
+ 			/*
+ 			 * Hmm.. We don't have an entry for this,
+ 			 * so default to an old-fashioned 8259
+@@ -2104,7 +2068,7 @@ static void __init setup_nmi(void)
+  * cycles as some i82489DX-based boards have glue logic that keeps the
+  * 8259A interrupt line asserted until INTA.  --macro
+  */
+-static inline void unlock_ExtINT_logic(void)
++static inline void __init unlock_ExtINT_logic(void)
+ {
+ 	int apic, pin, i;
+ 	struct IO_APIC_route_entry entry0, entry1;
+@@ -2156,8 +2120,6 @@ static inline void unlock_ExtINT_logic(void)
+ 	ioapic_write_entry(apic, pin, entry0);
+ }
+ 
+-int timer_uses_ioapic_pin_0;
+-
+ /*
+  * This code may look a bit paranoid, but it's supposed to cooperate with
+  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
+@@ -2168,10 +2130,14 @@ static inline void __init check_timer(void)
+ {
+ 	int apic1, pin1, apic2, pin2;
+ 	int vector;
++	unsigned int ver;
+ 	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+ 
++	ver = apic_read(APIC_LVR);
++	ver = GET_APIC_VERSION(ver);
++
+ 	/*
+ 	 * get/set the timer IRQ vector:
+ 	 */
+@@ -2184,11 +2150,15 @@ static inline void __init check_timer(void)
+ 	 * mode for the 8259A whenever interrupts are routed
+ 	 * through I/O APICs.  Also IRQ0 has to be enabled in
+ 	 * the 8259A which implies the virtual wire has to be
+-	 * disabled in the local APIC.
++	 * disabled in the local APIC.  Finally timer interrupts
++	 * need to be acknowledged manually in the 8259A for
++	 * timer_interrupt() and for the i82489DX when using
++	 * the NMI watchdog.
+ 	 */
+ 	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+ 	init_8259A(1);
+-	timer_ack = 1;
++	timer_ack = !cpu_has_tsc;
++	timer_ack |= (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
+ 	if (timer_over_8254 > 0)
+ 		enable_8259A_irq(0);
+ 
+@@ -2197,9 +2167,6 @@ static inline void __init check_timer(void)
+ 	pin2  = ioapic_i8259.pin;
+ 	apic2 = ioapic_i8259.apic;
+ 
+-	if (pin1 == 0)
+-		timer_uses_ioapic_pin_0 = 1;
+-
+ 	printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+ 		vector, apic1, pin1, apic2, pin2);
+ 
+@@ -2789,7 +2756,6 @@ int __init io_apic_get_redir_entries (int ioapic)
+ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
+ {
+ 	struct IO_APIC_route_entry entry;
+-	unsigned long flags;
+ 
+ 	if (!IO_APIC_IRQ(irq)) {
+ 		printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+@@ -2830,9 +2796,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
+ 	if (!ioapic && (irq < 16))
+ 		disable_8259A_irq(irq);
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__ioapic_write_entry(ioapic, pin, entry);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(ioapic, pin, entry);
+ 
+ 	return 0;
+ }
+diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
+index 1627c0d..ef1a8df 100644
+--- a/arch/x86/kernel/io_apic_64.c
++++ b/arch/x86/kernel/io_apic_64.c
+@@ -43,13 +43,15 @@
+ #include <asm/smp.h>
+ #include <asm/desc.h>
+ #include <asm/proto.h>
+-#include <asm/mach_apic.h>
+ #include <asm/acpi.h>
+ #include <asm/dma.h>
+ #include <asm/nmi.h>
+ #include <asm/msidef.h>
+ #include <asm/hypertransport.h>
+ 
++#include <mach_ipi.h>
++#include <mach_apic.h>
++
+ struct irq_cfg {
+ 	cpumask_t domain;
+ 	cpumask_t old_domain;
+@@ -101,6 +103,16 @@ DEFINE_SPINLOCK(vector_lock);
+  */
+ int nr_ioapic_registers[MAX_IO_APICS];
+ 
++/* I/O APIC entries */
++struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++int nr_ioapics;
++
++/* MP IRQ source entries */
++struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++
++/* # of MP IRQ source entries */
++int mp_irq_entries;
++
+ /*
+  * Rough estimation of how many shared IRQs there are, can
+  * be changed anytime.
+@@ -155,11 +167,10 @@ static inline void io_apic_modify(unsigned int apic, unsigned int value)
+ 	writel(value, &io_apic->data);
+ }
+ 
+-static int io_apic_level_ack_pending(unsigned int irq)
++static bool io_apic_level_ack_pending(unsigned int irq)
+ {
+ 	struct irq_pin_list *entry;
+ 	unsigned long flags;
+-	int pending = 0;
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+ 	entry = irq_2_pin + irq;
+@@ -172,13 +183,17 @@ static int io_apic_level_ack_pending(unsigned int irq)
+ 			break;
+ 		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+ 		/* Is the remote IRR bit set? */
+-		pending |= (reg >> 14) & 1;
++		if ((reg >> 14) & 1) {
++			spin_unlock_irqrestore(&ioapic_lock, flags);
++			return true;
++		}
+ 		if (!entry->next)
+ 			break;
+ 		entry = irq_2_pin + entry->next;
+ 	}
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+-	return pending;
++
++	return false;
+ }
+ 
+ /*
+@@ -770,7 +785,7 @@ static void __clear_irq_vector(int irq)
+ 		per_cpu(vector_irq, cpu)[vector] = -1;
+ 
+ 	cfg->vector = 0;
+-	cfg->domain = CPU_MASK_NONE;
++	cpus_clear(cfg->domain);
+ }
+ 
+ void __setup_vector_irq(int cpu)
+@@ -902,9 +917,8 @@ static void __init setup_IO_APIC_irqs(void)
+ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
+ {
+ 	struct IO_APIC_route_entry entry;
+-	unsigned long flags;
+ 
+-	memset(&entry,0,sizeof(entry));
++	memset(&entry, 0, sizeof(entry));
+ 
+ 	disable_8259A_irq(0);
+ 
+@@ -932,10 +946,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
+ 	/*
+ 	 * Add it to the IO-APIC irq-routing table:
+ 	 */
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+-	io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(apic, pin, entry);
+ 
+ 	enable_8259A_irq(0);
+ }
+@@ -1066,8 +1077,7 @@ void __apicdebuginit print_local_APIC(void * dummy)
+ 
+ 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ 		smp_processor_id(), hard_smp_processor_id());
+-	v = apic_read(APIC_ID);
+-	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(v));
++	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(read_apic_id()));
+ 	v = apic_read(APIC_LVR);
+ 	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+ 	ver = GET_APIC_VERSION(v);
+@@ -1261,7 +1271,7 @@ void disable_IO_APIC(void)
+ 		entry.dest_mode       = 0; /* Physical */
+ 		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
+ 		entry.vector          = 0;
+-		entry.dest          = GET_APIC_ID(apic_read(APIC_ID));
++		entry.dest          = GET_APIC_ID(read_apic_id());
+ 
+ 		/*
+ 		 * Add it to the IO-APIC irq-routing table:
+@@ -1352,9 +1362,7 @@ static int ioapic_retrigger_irq(unsigned int irq)
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	cpus_clear(mask);
+-	cpu_set(first_cpu(cfg->domain), mask);
+-
++	mask = cpumask_of_cpu(first_cpu(cfg->domain));
+ 	send_IPI_mask(mask, cfg->vector);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+@@ -1517,8 +1525,7 @@ static inline void init_IO_APIC_traps(void)
+ 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+ 	 */
+ 	for (irq = 0; irq < NR_IRQS ; irq++) {
+-		int tmp = irq;
+-		if (IO_APIC_IRQ(tmp) && !irq_cfg[tmp].vector) {
++		if (IO_APIC_IRQ(irq) && !irq_cfg[irq].vector) {
+ 			/*
+ 			 * Hmm.. We don't have an entry for this,
+ 			 * so default to an old-fashioned 8259
+@@ -1592,22 +1599,19 @@ static void __init setup_nmi(void)
+  * cycles as some i82489DX-based boards have glue logic that keeps the
+  * 8259A interrupt line asserted until INTA.  --macro
+  */
+-static inline void unlock_ExtINT_logic(void)
++static inline void __init unlock_ExtINT_logic(void)
+ {
+ 	int apic, pin, i;
+ 	struct IO_APIC_route_entry entry0, entry1;
+ 	unsigned char save_control, save_freq_select;
+-	unsigned long flags;
+ 
+ 	pin  = find_isa_irq_pin(8, mp_INT);
+ 	apic = find_isa_irq_apic(8, mp_INT);
+ 	if (pin == -1)
+ 		return;
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	*(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+-	*(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	entry0 = ioapic_read_entry(apic, pin);
++
+ 	clear_IO_APIC_pin(apic, pin);
+ 
+ 	memset(&entry1, 0, sizeof(entry1));
+@@ -1620,10 +1624,7 @@ static inline void unlock_ExtINT_logic(void)
+ 	entry1.trigger = 0;
+ 	entry1.vector = 0;
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
+-	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(apic, pin, entry1);
+ 
+ 	save_control = CMOS_READ(RTC_CONTROL);
+ 	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+@@ -1642,10 +1643,7 @@ static inline void unlock_ExtINT_logic(void)
+ 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ 	clear_IO_APIC_pin(apic, pin);
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
+-	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(apic, pin, entry0);
+ }
+ 
+ /*
+@@ -2314,7 +2312,6 @@ static struct resource * __init ioapic_setup_resources(void)
+ 	res = (void *)mem;
+ 
+ 	if (mem != NULL) {
+-		memset(mem, 0, n);
+ 		mem += sizeof(struct resource) * nr_ioapics;
+ 
+ 		for (i = 0; i < nr_ioapics; i++) {
+diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c
+new file mode 100644
+index 0000000..c0df7b8
+--- /dev/null
++++ b/arch/x86/kernel/ipi.c
+@@ -0,0 +1,178 @@
++#include <linux/cpumask.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/cpu.h>
++#include <linux/module.h>
++
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/apic.h>
++#include <asm/proto.h>
++
++#ifdef CONFIG_X86_32
++#include <mach_apic.h>
++/*
++ * the following functions deal with sending IPIs between CPUs.
++ *
++ * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
++ */
++
++static inline int __prepare_ICR(unsigned int shortcut, int vector)
++{
++	unsigned int icr = shortcut | APIC_DEST_LOGICAL;
++
++	switch (vector) {
++	default:
++		icr |= APIC_DM_FIXED | vector;
++		break;
++	case NMI_VECTOR:
++		icr |= APIC_DM_NMI;
++		break;
++	}
++	return icr;
++}
++
++static inline int __prepare_ICR2(unsigned int mask)
++{
++	return SET_APIC_DEST_FIELD(mask);
++}
++
++void __send_IPI_shortcut(unsigned int shortcut, int vector)
++{
++	/*
++	 * Subtle. In the case of the 'never do double writes' workaround
++	 * we have to lock out interrupts to be safe.  As we don't care
++	 * of the value read we use an atomic rmw access to avoid costly
++	 * cli/sti.  Otherwise we use an even cheaper single atomic write
++	 * to the APIC.
++	 */
++	unsigned int cfg;
++
++	/*
++	 * Wait for idle.
++	 */
++	apic_wait_icr_idle();
++
++	/*
++	 * No need to touch the target chip field
++	 */
++	cfg = __prepare_ICR(shortcut, vector);
++
++	/*
++	 * Send the IPI. The write to APIC_ICR fires this off.
++	 */
++	apic_write_around(APIC_ICR, cfg);
++}
++
++void send_IPI_self(int vector)
++{
++	__send_IPI_shortcut(APIC_DEST_SELF, vector);
++}
++
++/*
++ * This is used to send an IPI with no shorthand notation (the destination is
++ * specified in bits 56 to 63 of the ICR).
++ */
++static inline void __send_IPI_dest_field(unsigned long mask, int vector)
++{
++	unsigned long cfg;
++
++	/*
++	 * Wait for idle.
++	 */
++	if (unlikely(vector == NMI_VECTOR))
++		safe_apic_wait_icr_idle();
++	else
++		apic_wait_icr_idle();
++
++	/*
++	 * prepare target chip field
++	 */
++	cfg = __prepare_ICR2(mask);
++	apic_write_around(APIC_ICR2, cfg);
++
++	/*
++	 * program the ICR
++	 */
++	cfg = __prepare_ICR(0, vector);
++
++	/*
++	 * Send the IPI. The write to APIC_ICR fires this off.
++	 */
++	apic_write_around(APIC_ICR, cfg);
++}
++
++/*
++ * This is only used on smaller machines.
++ */
++void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
++{
++	unsigned long mask = cpus_addr(cpumask)[0];
++	unsigned long flags;
++
++	local_irq_save(flags);
++	WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
++	__send_IPI_dest_field(mask, vector);
++	local_irq_restore(flags);
++}
++
++void send_IPI_mask_sequence(cpumask_t mask, int vector)
++{
++	unsigned long flags;
++	unsigned int query_cpu;
++
++	/*
++	 * Hack. The clustered APIC addressing mode doesn't allow us to send
++	 * to an arbitrary mask, so I do a unicasts to each CPU instead. This
++	 * should be modified to do 1 message per cluster ID - mbligh
++	 */
++
++	local_irq_save(flags);
++	for_each_possible_cpu(query_cpu) {
++		if (cpu_isset(query_cpu, mask)) {
++			__send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
++					      vector);
++		}
++	}
++	local_irq_restore(flags);
++}
++
++/* must come after the send_IPI functions above for inlining */
++#include <mach_ipi.h>
++static int convert_apicid_to_cpu(int apic_id)
++{
++	int i;
++
++	for_each_possible_cpu(i) {
++		if (per_cpu(x86_cpu_to_apicid, i) == apic_id)
++			return i;
++	}
++	return -1;
++}
++
++int safe_smp_processor_id(void)
++{
++	int apicid, cpuid;
++
++	if (!boot_cpu_has(X86_FEATURE_APIC))
++		return 0;
++
++	apicid = hard_smp_processor_id();
++	if (apicid == BAD_APICID)
++		return 0;
++
++	cpuid = convert_apicid_to_cpu(apicid);
++
++	return cpuid >= 0 ? cpuid : 0;
++}
++#endif
+diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
+index cef054b..00bda7b 100644
+--- a/arch/x86/kernel/irq_32.c
++++ b/arch/x86/kernel/irq_32.c
+@@ -79,7 +79,7 @@ unsigned int do_IRQ(struct pt_regs *regs)
+ 
+ 	if (unlikely((unsigned)irq >= NR_IRQS)) {
+ 		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+-					__FUNCTION__, irq);
++					__func__, irq);
+ 		BUG();
+ 	}
+ 
+@@ -134,7 +134,7 @@ unsigned int do_IRQ(struct pt_regs *regs)
+ 			: "=a" (arg1), "=d" (arg2), "=b" (bx)
+ 			:  "0" (irq),   "1" (desc),  "2" (isp),
+ 			   "D" (desc->handle_irq)
+-			: "memory", "cc"
++			: "memory", "cc", "ecx"
+ 		);
+ 	} else
+ #endif
+diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
+new file mode 100644
+index 0000000..f47f0eb
+--- /dev/null
++++ b/arch/x86/kernel/kgdb.c
+@@ -0,0 +1,567 @@
++/*
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ */
++
++/*
++ * Copyright (C) 2004 Amit S. Kale <amitkale at linsyssoft.com>
++ * Copyright (C) 2000-2001 VERITAS Software Corporation.
++ * Copyright (C) 2002 Andi Kleen, SuSE Labs
++ * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd.
++ * Copyright (C) 2007 MontaVista Software, Inc.
++ * Copyright (C) 2007-2008 Jason Wessel, Wind River Systems, Inc.
++ */
++/****************************************************************************
++ *  Contributor:     Lake Stevens Instrument Division$
++ *  Written by:      Glenn Engel $
++ *  Updated by:	     Amit Kale<akale at veritas.com>
++ *  Updated by:	     Tom Rini <trini at kernel.crashing.org>
++ *  Updated by:	     Jason Wessel <jason.wessel at windriver.com>
++ *  Modified for 386 by Jim Kingdon, Cygnus Support.
++ *  Origianl kgdb, compatibility with 2.1.xx kernel by
++ *  David Grothe <dave at gcom.com>
++ *  Integrated into 2.2.5 kernel by Tigran Aivazian <tigran at sco.com>
++ *  X86_64 changes from Andi Kleen's patch merged by Jim Houston
++ */
++#include <linux/spinlock.h>
++#include <linux/kdebug.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/ptrace.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/kgdb.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/nmi.h>
++
++#include <asm/apicdef.h>
++#include <asm/system.h>
++
++#include <mach_ipi.h>
++
++/*
++ * Put the error code here just in case the user cares:
++ */
++static int gdb_x86errcode;
++
++/*
++ * Likewise, the vector number here (since GDB only gets the signal
++ * number through the usual means, and that's not very specific):
++ */
++static int gdb_x86vector = -1;
++
++/**
++ *	pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs
++ *	@gdb_regs: A pointer to hold the registers in the order GDB wants.
++ *	@regs: The &struct pt_regs of the current process.
++ *
++ *	Convert the pt_regs in @regs into the format for registers that
++ *	GDB expects, stored in @gdb_regs.
++ */
++void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++	gdb_regs[GDB_AX]	= regs->ax;
++	gdb_regs[GDB_BX]	= regs->bx;
++	gdb_regs[GDB_CX]	= regs->cx;
++	gdb_regs[GDB_DX]	= regs->dx;
++	gdb_regs[GDB_SI]	= regs->si;
++	gdb_regs[GDB_DI]	= regs->di;
++	gdb_regs[GDB_BP]	= regs->bp;
++	gdb_regs[GDB_PS]	= regs->flags;
++	gdb_regs[GDB_PC]	= regs->ip;
++#ifdef CONFIG_X86_32
++	gdb_regs[GDB_DS]	= regs->ds;
++	gdb_regs[GDB_ES]	= regs->es;
++	gdb_regs[GDB_CS]	= regs->cs;
++	gdb_regs[GDB_SS]	= __KERNEL_DS;
++	gdb_regs[GDB_FS]	= 0xFFFF;
++	gdb_regs[GDB_GS]	= 0xFFFF;
++#else
++	gdb_regs[GDB_R8]	= regs->r8;
++	gdb_regs[GDB_R9]	= regs->r9;
++	gdb_regs[GDB_R10]	= regs->r10;
++	gdb_regs[GDB_R11]	= regs->r11;
++	gdb_regs[GDB_R12]	= regs->r12;
++	gdb_regs[GDB_R13]	= regs->r13;
++	gdb_regs[GDB_R14]	= regs->r14;
++	gdb_regs[GDB_R15]	= regs->r15;
++#endif
++	gdb_regs[GDB_SP]	= regs->sp;
++}
++
++/**
++ *	sleeping_thread_to_gdb_regs - Convert ptrace regs to GDB regs
++ *	@gdb_regs: A pointer to hold the registers in the order GDB wants.
++ *	@p: The &struct task_struct of the desired process.
++ *
++ *	Convert the register values of the sleeping process in @p to
++ *	the format that GDB expects.
++ *	This function is called when kgdb does not have access to the
++ *	&struct pt_regs and therefore it should fill the gdb registers
++ *	@gdb_regs with what has	been saved in &struct thread_struct
++ *	thread field during switch_to.
++ */
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++	gdb_regs[GDB_AX]	= 0;
++	gdb_regs[GDB_BX]	= 0;
++	gdb_regs[GDB_CX]	= 0;
++	gdb_regs[GDB_DX]	= 0;
++	gdb_regs[GDB_SI]	= 0;
++	gdb_regs[GDB_DI]	= 0;
++	gdb_regs[GDB_BP]	= *(unsigned long *)p->thread.sp;
++#ifdef CONFIG_X86_32
++	gdb_regs[GDB_DS]	= __KERNEL_DS;
++	gdb_regs[GDB_ES]	= __KERNEL_DS;
++	gdb_regs[GDB_PS]	= 0;
++	gdb_regs[GDB_CS]	= __KERNEL_CS;
++	gdb_regs[GDB_PC]	= p->thread.ip;
++	gdb_regs[GDB_SS]	= __KERNEL_DS;
++	gdb_regs[GDB_FS]	= 0xFFFF;
++	gdb_regs[GDB_GS]	= 0xFFFF;
++#else
++	gdb_regs[GDB_PS]	= *(unsigned long *)(p->thread.sp + 8);
++	gdb_regs[GDB_PC]	= 0;
++	gdb_regs[GDB_R8]	= 0;
++	gdb_regs[GDB_R9]	= 0;
++	gdb_regs[GDB_R10]	= 0;
++	gdb_regs[GDB_R11]	= 0;
++	gdb_regs[GDB_R12]	= 0;
++	gdb_regs[GDB_R13]	= 0;
++	gdb_regs[GDB_R14]	= 0;
++	gdb_regs[GDB_R15]	= 0;
++#endif
++	gdb_regs[GDB_SP]	= p->thread.sp;
++}
++
++/**
++ *	gdb_regs_to_pt_regs - Convert GDB regs to ptrace regs.
++ *	@gdb_regs: A pointer to hold the registers we've received from GDB.
++ *	@regs: A pointer to a &struct pt_regs to hold these values in.
++ *
++ *	Convert the GDB regs in @gdb_regs into the pt_regs, and store them
++ *	in @regs.
++ */
++void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++	regs->ax		= gdb_regs[GDB_AX];
++	regs->bx		= gdb_regs[GDB_BX];
++	regs->cx		= gdb_regs[GDB_CX];
++	regs->dx		= gdb_regs[GDB_DX];
++	regs->si		= gdb_regs[GDB_SI];
++	regs->di		= gdb_regs[GDB_DI];
++	regs->bp		= gdb_regs[GDB_BP];
++	regs->flags		= gdb_regs[GDB_PS];
++	regs->ip		= gdb_regs[GDB_PC];
++#ifdef CONFIG_X86_32
++	regs->ds		= gdb_regs[GDB_DS];
++	regs->es		= gdb_regs[GDB_ES];
++	regs->cs		= gdb_regs[GDB_CS];
++#else
++	regs->r8		= gdb_regs[GDB_R8];
++	regs->r9		= gdb_regs[GDB_R9];
++	regs->r10		= gdb_regs[GDB_R10];
++	regs->r11		= gdb_regs[GDB_R11];
++	regs->r12		= gdb_regs[GDB_R12];
++	regs->r13		= gdb_regs[GDB_R13];
++	regs->r14		= gdb_regs[GDB_R14];
++	regs->r15		= gdb_regs[GDB_R15];
++#endif
++}
++
++static struct hw_breakpoint {
++	unsigned		enabled;
++	unsigned		type;
++	unsigned		len;
++	unsigned long		addr;
++} breakinfo[4];
++
++static void kgdb_correct_hw_break(void)
++{
++	unsigned long dr7;
++	int correctit = 0;
++	int breakbit;
++	int breakno;
++
++	get_debugreg(dr7, 7);
++	for (breakno = 0; breakno < 4; breakno++) {
++		breakbit = 2 << (breakno << 1);
++		if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
++			correctit = 1;
++			dr7 |= breakbit;
++			dr7 &= ~(0xf0000 << (breakno << 2));
++			dr7 |= ((breakinfo[breakno].len << 2) |
++				 breakinfo[breakno].type) <<
++			       ((breakno << 2) + 16);
++			if (breakno >= 0 && breakno <= 3)
++				set_debugreg(breakinfo[breakno].addr, breakno);
++
++		} else {
++			if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
++				correctit = 1;
++				dr7 &= ~breakbit;
++				dr7 &= ~(0xf0000 << (breakno << 2));
++			}
++		}
++	}
++	if (correctit)
++		set_debugreg(dr7, 7);
++}
++
++static int
++kgdb_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
++{
++	int i;
++
++	for (i = 0; i < 4; i++)
++		if (breakinfo[i].addr == addr && breakinfo[i].enabled)
++			break;
++	if (i == 4)
++		return -1;
++
++	breakinfo[i].enabled = 0;
++
++	return 0;
++}
++
++static void kgdb_remove_all_hw_break(void)
++{
++	int i;
++
++	for (i = 0; i < 4; i++)
++		memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
++}
++
++static int
++kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
++{
++	unsigned type;
++	int i;
++
++	for (i = 0; i < 4; i++)
++		if (!breakinfo[i].enabled)
++			break;
++	if (i == 4)
++		return -1;
++
++	switch (bptype) {
++	case BP_HARDWARE_BREAKPOINT:
++		type = 0;
++		len  = 1;
++		break;
++	case BP_WRITE_WATCHPOINT:
++		type = 1;
++		break;
++	case BP_ACCESS_WATCHPOINT:
++		type = 3;
++		break;
++	default:
++		return -1;
++	}
++
++	if (len == 1 || len == 2 || len == 4)
++		breakinfo[i].len  = len - 1;
++	else
++		return -1;
++
++	breakinfo[i].enabled = 1;
++	breakinfo[i].addr = addr;
++	breakinfo[i].type = type;
++
++	return 0;
++}
++
++/**
++ *	kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb.
++ *	@regs: Current &struct pt_regs.
++ *
++ *	This function will be called if the particular architecture must
++ *	disable hardware debugging while it is processing gdb packets or
++ *	handling exception.
++ */
++void kgdb_disable_hw_debug(struct pt_regs *regs)
++{
++	/* Disable hardware debugging while we are in kgdb: */
++	set_debugreg(0UL, 7);
++}
++
++/**
++ *	kgdb_post_primary_code - Save error vector/code numbers.
++ *	@regs: Original pt_regs.
++ *	@e_vector: Original error vector.
++ *	@err_code: Original error code.
++ *
++ *	This is needed on architectures which support SMP and KGDB.
++ *	This function is called after all the slave cpus have been put
++ *	to a know spin state and the primary CPU has control over KGDB.
++ */
++void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code)
++{
++	/* primary processor is completely in the debugger */
++	gdb_x86vector = e_vector;
++	gdb_x86errcode = err_code;
++}
++
++#ifdef CONFIG_SMP
++/**
++ *	kgdb_roundup_cpus - Get other CPUs into a holding pattern
++ *	@flags: Current IRQ state
++ *
++ *	On SMP systems, we need to get the attention of the other CPUs
++ *	and get them be in a known state.  This should do what is needed
++ *	to get the other CPUs to call kgdb_wait(). Note that on some arches,
++ *	the NMI approach is not used for rounding up all the CPUs. For example,
++ *	in case of MIPS, smp_call_function() is used to roundup CPUs. In
++ *	this case, we have to make sure that interrupts are enabled before
++ *	calling smp_call_function(). The argument to this function is
++ *	the flags that will be used when restoring the interrupts. There is
++ *	local_irq_save() call before kgdb_roundup_cpus().
++ *
++ *	On non-SMP systems, this is not called.
++ */
++void kgdb_roundup_cpus(unsigned long flags)
++{
++	send_IPI_allbutself(APIC_DM_NMI);
++}
++#endif
++
++/**
++ *	kgdb_arch_handle_exception - Handle architecture specific GDB packets.
++ *	@vector: The error vector of the exception that happened.
++ *	@signo: The signal number of the exception that happened.
++ *	@err_code: The error code of the exception that happened.
++ *	@remcom_in_buffer: The buffer of the packet we have read.
++ *	@remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
++ *	@regs: The &struct pt_regs of the current process.
++ *
++ *	This function MUST handle the 'c' and 's' command packets,
++ *	as well packets to set / remove a hardware breakpoint, if used.
++ *	If there are additional packets which the hardware needs to handle,
++ *	they are handled here.  The code should return -1 if it wants to
++ *	process more packets, and a %0 or %1 if it wants to exit from the
++ *	kgdb callback.
++ */
++int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
++			       char *remcomInBuffer, char *remcomOutBuffer,
++			       struct pt_regs *linux_regs)
++{
++	unsigned long addr;
++	unsigned long dr6;
++	char *ptr;
++	int newPC;
++
++	switch (remcomInBuffer[0]) {
++	case 'c':
++	case 's':
++		/* try to read optional parameter, pc unchanged if no parm */
++		ptr = &remcomInBuffer[1];
++		if (kgdb_hex2long(&ptr, &addr))
++			linux_regs->ip = addr;
++	case 'D':
++	case 'k':
++		newPC = linux_regs->ip;
++
++		/* clear the trace bit */
++		linux_regs->flags &= ~X86_EFLAGS_TF;
++		atomic_set(&kgdb_cpu_doing_single_step, -1);
++
++		/* set the trace bit if we're stepping */
++		if (remcomInBuffer[0] == 's') {
++			linux_regs->flags |= X86_EFLAGS_TF;
++			kgdb_single_step = 1;
++			if (kgdb_contthread) {
++				atomic_set(&kgdb_cpu_doing_single_step,
++					   raw_smp_processor_id());
++			}
++		}
++
++		get_debugreg(dr6, 6);
++		if (!(dr6 & 0x4000)) {
++			int breakno;
++
++			for (breakno = 0; breakno < 4; breakno++) {
++				if (dr6 & (1 << breakno) &&
++				    breakinfo[breakno].type == 0) {
++					/* Set restore flag: */
++					linux_regs->flags |= X86_EFLAGS_RF;
++					break;
++				}
++			}
++		}
++		set_debugreg(0UL, 6);
++		kgdb_correct_hw_break();
++
++		return 0;
++	}
++
++	/* this means that we do not want to exit from the handler: */
++	return -1;
++}
++
++static inline int
++single_step_cont(struct pt_regs *regs, struct die_args *args)
++{
++	/*
++	 * Single step exception from kernel space to user space so
++	 * eat the exception and continue the process:
++	 */
++	printk(KERN_ERR "KGDB: trap/step from kernel to user space, "
++			"resuming...\n");
++	kgdb_arch_handle_exception(args->trapnr, args->signr,
++				   args->err, "c", "", regs);
++
++	return NOTIFY_STOP;
++}
++
++static int was_in_debug_nmi[NR_CPUS];
++
++static int __kgdb_notify(struct die_args *args, unsigned long cmd)
++{
++	struct pt_regs *regs = args->regs;
++
++	switch (cmd) {
++	case DIE_NMI:
++		if (atomic_read(&kgdb_active) != -1) {
++			/* KGDB CPU roundup */
++			kgdb_nmicallback(raw_smp_processor_id(), regs);
++			was_in_debug_nmi[raw_smp_processor_id()] = 1;
++			touch_nmi_watchdog();
++			return NOTIFY_STOP;
++		}
++		return NOTIFY_DONE;
++
++	case DIE_NMI_IPI:
++		if (atomic_read(&kgdb_active) != -1) {
++			/* KGDB CPU roundup */
++			kgdb_nmicallback(raw_smp_processor_id(), regs);
++			was_in_debug_nmi[raw_smp_processor_id()] = 1;
++			touch_nmi_watchdog();
++		}
++		return NOTIFY_DONE;
++
++	case DIE_NMIUNKNOWN:
++		if (was_in_debug_nmi[raw_smp_processor_id()]) {
++			was_in_debug_nmi[raw_smp_processor_id()] = 0;
++			return NOTIFY_STOP;
++		}
++		return NOTIFY_DONE;
++
++	case DIE_NMIWATCHDOG:
++		if (atomic_read(&kgdb_active) != -1) {
++			/* KGDB CPU roundup: */
++			kgdb_nmicallback(raw_smp_processor_id(), regs);
++			return NOTIFY_STOP;
++		}
++		/* Enter debugger: */
++		break;
++
++	case DIE_DEBUG:
++		if (atomic_read(&kgdb_cpu_doing_single_step) ==
++			raw_smp_processor_id() &&
++			user_mode(regs))
++			return single_step_cont(regs, args);
++		/* fall through */
++	default:
++		if (user_mode(regs))
++			return NOTIFY_DONE;
++	}
++
++	if (kgdb_handle_exception(args->trapnr, args->signr, args->err, regs))
++		return NOTIFY_DONE;
++
++	/* Must touch watchdog before return to normal operation */
++	touch_nmi_watchdog();
++	return NOTIFY_STOP;
++}
++
++static int
++kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
++{
++	unsigned long flags;
++	int ret;
++
++	local_irq_save(flags);
++	ret = __kgdb_notify(ptr, cmd);
++	local_irq_restore(flags);
++
++	return ret;
++}
++
++static struct notifier_block kgdb_notifier = {
++	.notifier_call	= kgdb_notify,
++
++	/*
++	 * Lowest-prio notifier priority, we want to be notified last:
++	 */
++	.priority	= -INT_MAX,
++};
++
++/**
++ *	kgdb_arch_init - Perform any architecture specific initalization.
++ *
++ *	This function will handle the initalization of any architecture
++ *	specific callbacks.
++ */
++int kgdb_arch_init(void)
++{
++	return register_die_notifier(&kgdb_notifier);
++}
++
++/**
++ *	kgdb_arch_exit - Perform any architecture specific uninitalization.
++ *
++ *	This function will handle the uninitalization of any architecture
++ *	specific callbacks, for dynamic registration and unregistration.
++ */
++void kgdb_arch_exit(void)
++{
++	unregister_die_notifier(&kgdb_notifier);
++}
++
++/**
++ *
++ *	kgdb_skipexception - Bail out of KGDB when we've been triggered.
++ *	@exception: Exception vector number
++ *	@regs: Current &struct pt_regs.
++ *
++ *	On some architectures we need to skip a breakpoint exception when
++ *	it occurs after a breakpoint has been removed.
++ *
++ * Skip an int3 exception when it occurs after a breakpoint has been
++ * removed. Backtrack eip by 1 since the int3 would have caused it to
++ * increment by 1.
++ */
++int kgdb_skipexception(int exception, struct pt_regs *regs)
++{
++	if (exception == 3 && kgdb_isremovedbreak(regs->ip - 1)) {
++		regs->ip -= 1;
++		return 1;
++	}
++	return 0;
++}
++
++unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
++{
++	if (exception == 3)
++		return instruction_pointer(regs) - 1;
++	return instruction_pointer(regs);
++}
++
++struct kgdb_arch arch_kgdb_ops = {
++	/* Breakpoint instruction: */
++	.gdb_bpt_instr		= { 0xcc },
++	.flags			= KGDB_HW_BREAKPOINT,
++	.set_hw_breakpoint	= kgdb_set_hw_break,
++	.remove_hw_breakpoint	= kgdb_remove_hw_break,
++	.remove_all_hw_break	= kgdb_remove_all_hw_break,
++	.correct_hw_break	= kgdb_correct_hw_break,
++};
+diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
+index 34a5912..b8c6743 100644
+--- a/arch/x86/kernel/kprobes.c
++++ b/arch/x86/kernel/kprobes.c
+@@ -410,13 +410,13 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+ static void __kprobes clear_btf(void)
+ {
+ 	if (test_thread_flag(TIF_DEBUGCTLMSR))
+-		wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++		update_debugctlmsr(0);
+ }
+ 
+ static void __kprobes restore_btf(void)
+ {
+ 	if (test_thread_flag(TIF_DEBUGCTLMSR))
+-		wrmsrl(MSR_IA32_DEBUGCTLMSR, current->thread.debugctlmsr);
++		update_debugctlmsr(current->thread.debugctlmsr);
+ }
+ 
+ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+@@ -489,7 +489,7 @@ static int __kprobes reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
+ 		break;
+ 	case KPROBE_HIT_SS:
+ 		if (p == kprobe_running()) {
+-			regs->flags &= ~TF_MASK;
++			regs->flags &= ~X86_EFLAGS_TF;
+ 			regs->flags |= kcb->kprobe_saved_flags;
+ 			return 0;
+ 		} else {
+@@ -858,15 +858,15 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
+ 	if (!cur)
+ 		return 0;
+ 
++	resume_execution(cur, regs, kcb);
++	regs->flags |= kcb->kprobe_saved_flags;
++	trace_hardirqs_fixup_flags(regs->flags);
++
+ 	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+ 		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ 		cur->post_handler(cur, regs, 0);
+ 	}
+ 
+-	resume_execution(cur, regs, kcb);
+-	regs->flags |= kcb->kprobe_saved_flags;
+-	trace_hardirqs_fixup_flags(regs->flags);
+-
+ 	/* Restore back the original saved kprobes variables and continue. */
+ 	if (kcb->kprobe_status == KPROBE_REENTER) {
+ 		restore_previous_kprobe(kcb);
+diff --git a/arch/x86/kernel/mca_32.c b/arch/x86/kernel/mca_32.c
+index 9482033..2dc1837 100644
+--- a/arch/x86/kernel/mca_32.c
++++ b/arch/x86/kernel/mca_32.c
+@@ -53,9 +53,9 @@
+ #include <linux/init.h>
+ #include <asm/arch_hooks.h>
+ 
+-static unsigned char which_scsi = 0;
++static unsigned char which_scsi;
+ 
+-int MCA_bus = 0;
++int MCA_bus;
+ EXPORT_SYMBOL(MCA_bus);
+ 
+ /*
+@@ -68,15 +68,17 @@ static DEFINE_SPINLOCK(mca_lock);
+ 
+ /* Build the status info for the adapter */
+ 
+-static void mca_configure_adapter_status(struct mca_device *mca_dev) {
++static void mca_configure_adapter_status(struct mca_device *mca_dev)
++{
+ 	mca_dev->status = MCA_ADAPTER_NONE;
+ 
+ 	mca_dev->pos_id = mca_dev->pos[0]
+ 		+ (mca_dev->pos[1] << 8);
+ 
+-	if(!mca_dev->pos_id && mca_dev->slot < MCA_MAX_SLOT_NR) {
++	if (!mca_dev->pos_id && mca_dev->slot < MCA_MAX_SLOT_NR) {
+ 
+-		/* id = 0x0000 usually indicates hardware failure,
++		/*
++		 * id = 0x0000 usually indicates hardware failure,
+ 		 * however, ZP Gu (zpg at castle.net> reports that his 9556
+ 		 * has 0x0000 as id and everything still works. There
+ 		 * also seem to be an adapter with id = 0x0000; the
+@@ -87,9 +89,10 @@ static void mca_configure_adapter_status(struct mca_device *mca_dev) {
+ 		mca_dev->status = MCA_ADAPTER_ERROR;
+ 
+ 		return;
+-	} else if(mca_dev->pos_id != 0xffff) {
++	} else if (mca_dev->pos_id != 0xffff) {
+ 
+-		/* 0xffff usually indicates that there's no adapter,
++		/*
++		 * 0xffff usually indicates that there's no adapter,
+ 		 * however, some integrated adapters may have 0xffff as
+ 		 * their id and still be valid. Examples are on-board
+ 		 * VGA of the 55sx, the integrated SCSI of the 56 & 57,
+@@ -99,19 +102,19 @@ static void mca_configure_adapter_status(struct mca_device *mca_dev) {
+ 		mca_dev->status = MCA_ADAPTER_NORMAL;
+ 	}
+ 
+-	if((mca_dev->pos_id == 0xffff ||
++	if ((mca_dev->pos_id == 0xffff ||
+ 	    mca_dev->pos_id == 0x0000) && mca_dev->slot >= MCA_MAX_SLOT_NR) {
+ 		int j;
+ 
+-		for(j = 2; j < 8; j++) {
+-			if(mca_dev->pos[j] != 0xff) {
++		for (j = 2; j < 8; j++) {
++			if (mca_dev->pos[j] != 0xff) {
+ 				mca_dev->status = MCA_ADAPTER_NORMAL;
+ 				break;
+ 			}
+ 		}
+ 	}
+ 
+-	if(!(mca_dev->pos[2] & MCA_ENABLED)) {
++	if (!(mca_dev->pos[2] & MCA_ENABLED)) {
+ 
+ 		/* enabled bit is in POS 2 */
+ 
+@@ -133,7 +136,7 @@ static struct resource mca_standard_resources[] = {
+ 
+ #define MCA_STANDARD_RESOURCES	ARRAY_SIZE(mca_standard_resources)
+ 
+-/**
++/*
+  *	mca_read_and_store_pos - read the POS registers into a memory buffer
+  *      @pos: a char pointer to 8 bytes, contains the POS register value on
+  *            successful return
+@@ -141,12 +144,14 @@ static struct resource mca_standard_resources[] = {
+  *	Returns 1 if a card actually exists (i.e. the pos isn't
+  *	all 0xff) or 0 otherwise
+  */
+-static int mca_read_and_store_pos(unsigned char *pos) {
++static int mca_read_and_store_pos(unsigned char *pos)
++{
+ 	int j;
+ 	int found = 0;
+ 
+-	for(j=0; j<8; j++) {
+-		if((pos[j] = inb_p(MCA_POS_REG(j))) != 0xff) {
++	for (j = 0; j < 8; j++) {
++		pos[j] = inb_p(MCA_POS_REG(j));
++		if (pos[j] != 0xff) {
+ 			/* 0xff all across means no device. 0x00 means
+ 			 * something's broken, but a device is
+ 			 * probably there.  However, if you get 0x00
+@@ -167,11 +172,11 @@ static unsigned char mca_pc_read_pos(struct mca_device *mca_dev, int reg)
+ 	unsigned char byte;
+ 	unsigned long flags;
+ 
+-	if(reg < 0 || reg >= 8)
++	if (reg < 0 || reg >= 8)
+ 		return 0;
+ 
+ 	spin_lock_irqsave(&mca_lock, flags);
+-	if(mca_dev->pos_register) {
++	if (mca_dev->pos_register) {
+ 		/* Disable adapter setup, enable motherboard setup */
+ 
+ 		outb_p(0, MCA_ADAPTER_SETUP_REG);
+@@ -203,7 +208,7 @@ static void mca_pc_write_pos(struct mca_device *mca_dev, int reg,
+ {
+ 	unsigned long flags;
+ 
+-	if(reg < 0 || reg >= 8)
++	if (reg < 0 || reg >= 8)
+ 		return;
+ 
+ 	spin_lock_irqsave(&mca_lock, flags);
+@@ -227,17 +232,17 @@ static void mca_pc_write_pos(struct mca_device *mca_dev, int reg,
+ }
+ 
+ /* for the primary MCA bus, we have identity transforms */
+-static int mca_dummy_transform_irq(struct mca_device * mca_dev, int irq)
++static int mca_dummy_transform_irq(struct mca_device *mca_dev, int irq)
+ {
+ 	return irq;
+ }
+ 
+-static int mca_dummy_transform_ioport(struct mca_device * mca_dev, int port)
++static int mca_dummy_transform_ioport(struct mca_device *mca_dev, int port)
+ {
+ 	return port;
+ }
+ 
+-static void *mca_dummy_transform_memory(struct mca_device * mca_dev, void *mem)
++static void *mca_dummy_transform_memory(struct mca_device *mca_dev, void *mem)
+ {
+ 	return mem;
+ }
+@@ -251,7 +256,8 @@ static int __init mca_init(void)
+ 	short mca_builtin_scsi_ports[] = {0xf7, 0xfd, 0x00};
+ 	struct mca_bus *bus;
+ 
+-	/* WARNING: Be careful when making changes here. Putting an adapter
++	/*
++	 * WARNING: Be careful when making changes here. Putting an adapter
+ 	 * and the motherboard simultaneously into setup mode may result in
+ 	 * damage to chips (according to The Indispensible PC Hardware Book
+ 	 * by Hans-Peter Messmer). Also, we disable system interrupts (so
+@@ -283,7 +289,7 @@ static int __init mca_init(void)
+ 
+ 	/* get the motherboard device */
+ 	mca_dev = kzalloc(sizeof(struct mca_device), GFP_KERNEL);
+-	if(unlikely(!mca_dev))
++	if (unlikely(!mca_dev))
+ 		goto out_nomem;
+ 
+ 	/*
+@@ -309,7 +315,7 @@ static int __init mca_init(void)
+ 	mca_register_device(MCA_PRIMARY_BUS, mca_dev);
+ 
+ 	mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
+-	if(unlikely(!mca_dev))
++	if (unlikely(!mca_dev))
+ 		goto out_unlock_nomem;
+ 
+ 	/* Put motherboard into video setup mode, read integrated video
+@@ -326,7 +332,8 @@ static int __init mca_init(void)
+ 	mca_dev->slot = MCA_INTEGVIDEO;
+ 	mca_register_device(MCA_PRIMARY_BUS, mca_dev);
+ 
+-	/* Put motherboard into scsi setup mode, read integrated scsi
++	/*
++	 * Put motherboard into scsi setup mode, read integrated scsi
+ 	 * POS registers, and turn motherboard setup off.
+ 	 *
+ 	 * It seems there are two possible SCSI registers. Martin says that
+@@ -338,18 +345,18 @@ static int __init mca_init(void)
+ 	 * machine.
+ 	 */
+ 
+-	for(i = 0; (which_scsi = mca_builtin_scsi_ports[i]) != 0; i++) {
++	for (i = 0; (which_scsi = mca_builtin_scsi_ports[i]) != 0; i++) {
+ 		outb_p(which_scsi, MCA_MOTHERBOARD_SETUP_REG);
+-		if(mca_read_and_store_pos(pos))
++		if (mca_read_and_store_pos(pos))
+ 			break;
+ 	}
+-	if(which_scsi) {
++	if (which_scsi) {
+ 		/* found a scsi card */
+ 		mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
+-		if(unlikely(!mca_dev))
++		if (unlikely(!mca_dev))
+ 			goto out_unlock_nomem;
+ 
+-		for(j = 0; j < 8; j++)
++		for (j = 0; j < 8; j++)
+ 			mca_dev->pos[j] = pos[j];
+ 
+ 		mca_configure_adapter_status(mca_dev);
+@@ -364,21 +371,22 @@ static int __init mca_init(void)
+ 
+ 	outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
+ 
+-	/* Now loop over MCA slots: put each adapter into setup mode, and
++	/*
++	 * Now loop over MCA slots: put each adapter into setup mode, and
+ 	 * read its POS registers. Then put adapter setup off.
+ 	 */
+ 
+-	for(i=0; i<MCA_MAX_SLOT_NR; i++) {
++	for (i = 0; i < MCA_MAX_SLOT_NR; i++) {
+ 		outb_p(0x8|(i&0xf), MCA_ADAPTER_SETUP_REG);
+-		if(!mca_read_and_store_pos(pos))
++		if (!mca_read_and_store_pos(pos))
+ 			continue;
+ 
+ 		mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
+-		if(unlikely(!mca_dev))
++		if (unlikely(!mca_dev))
+ 			goto out_unlock_nomem;
+ 
+-		for(j=0; j<8; j++)
+-			mca_dev->pos[j]=pos[j];
++		for (j = 0; j < 8; j++)
++			mca_dev->pos[j] = pos[j];
+ 
+ 		mca_dev->driver_loaded = 0;
+ 		mca_dev->slot = i;
+@@ -414,20 +422,20 @@ mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
+ {
+ 	int slot = mca_dev->slot;
+ 
+-	if(slot == MCA_INTEGSCSI) {
++	if (slot == MCA_INTEGSCSI) {
+ 		printk(KERN_CRIT "NMI: caused by MCA integrated SCSI adapter (%s)\n",
+ 			mca_dev->name);
+-	} else if(slot == MCA_INTEGVIDEO) {
++	} else if (slot == MCA_INTEGVIDEO) {
+ 		printk(KERN_CRIT "NMI: caused by MCA integrated video adapter (%s)\n",
+ 			mca_dev->name);
+-	} else if(slot == MCA_MOTHERBOARD) {
++	} else if (slot == MCA_MOTHERBOARD) {
+ 		printk(KERN_CRIT "NMI: caused by motherboard (%s)\n",
+ 			mca_dev->name);
+ 	}
+ 
+ 	/* More info available in POS 6 and 7? */
+ 
+-	if(check_flag) {
++	if (check_flag) {
+ 		unsigned char pos6, pos7;
+ 
+ 		pos6 = mca_device_read_pos(mca_dev, 6);
+@@ -447,8 +455,9 @@ static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data)
+ 
+ 	pos5 = mca_device_read_pos(mca_dev, 5);
+ 
+-	if(!(pos5 & 0x80)) {
+-		/* Bit 7 of POS 5 is reset when this adapter has a hardware
++	if (!(pos5 & 0x80)) {
++		/*
++		 *  Bit 7 of POS 5 is reset when this adapter has a hardware
+ 		 * error. Bit 7 it reset if there's error information
+ 		 * available in POS 6 and 7.
+ 		 */
+@@ -460,7 +469,8 @@ static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data)
+ 
+ void __kprobes mca_handle_nmi(void)
+ {
+-	/* First try - scan the various adapters and see if a specific
++	/*
++	 *  First try - scan the various adapters and see if a specific
+ 	 * adapter was responsible for the error.
+ 	 */
+ 	bus_for_each_dev(&mca_bus_type, NULL, NULL, mca_handle_nmi_callback);
+diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c
+index b402c0f..cfc2648 100644
+--- a/arch/x86/kernel/mfgpt_32.c
++++ b/arch/x86/kernel/mfgpt_32.c
+@@ -364,7 +364,8 @@ int __init mfgpt_timer_setup(void)
+ 	geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val);
+ 
+ 	/* Set up the clock event */
+-	mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, 32);
++	mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC,
++				       mfgpt_clockevent.shift);
+ 	mfgpt_clockevent.min_delta_ns = clockevent_delta2ns(0xF,
+ 			&mfgpt_clockevent);
+ 	mfgpt_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE,
+diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
+index f2702d0..69729e3 100644
+--- a/arch/x86/kernel/microcode.c
++++ b/arch/x86/kernel/microcode.c
+@@ -290,7 +290,7 @@ static int get_maching_microcode(void *mc, int cpu)
+ 	}
+ 	return 0;
+ find:
+-	pr_debug("microcode: CPU %d found a matching microcode update with"
++	pr_debug("microcode: CPU%d found a matching microcode update with"
+ 		" version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
+ 	new_mc = vmalloc(total_size);
+ 	if (!new_mc) {
+@@ -336,11 +336,11 @@ static void apply_microcode(int cpu)
+ 
+ 	spin_unlock_irqrestore(&microcode_update_lock, flags);
+ 	if (val[1] != uci->mc->hdr.rev) {
+-		printk(KERN_ERR "microcode: CPU%d updated from revision "
++		printk(KERN_ERR "microcode: CPU%d update from revision "
+ 			"0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
+ 		return;
+ 	}
+-	pr_debug("microcode: CPU%d updated from revision "
++	printk(KERN_INFO "microcode: CPU%d updated from revision "
+ 	       "0x%x to 0x%x, date = %08x \n", 
+ 	       cpu_num, uci->rev, val[1], uci->mc->hdr.date);
+ 	uci->rev = val[1];
+@@ -402,7 +402,7 @@ static int do_microcode_update (void)
+ 
+ 			if (!uci->valid)
+ 				continue;
+-			set_cpus_allowed(current, cpumask_of_cpu(cpu));
++			set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 			error = get_maching_microcode(new_mc, cpu);
+ 			if (error < 0)
+ 				goto out;
+@@ -416,7 +416,7 @@ out:
+ 		vfree(new_mc);
+ 	if (cursor < 0)
+ 		error = cursor;
+-	set_cpus_allowed(current, old);
++	set_cpus_allowed_ptr(current, &old);
+ 	return error;
+ }
+ 
+@@ -534,7 +534,7 @@ static int cpu_request_microcode(int cpu)
+ 		c->x86, c->x86_model, c->x86_mask);
+ 	error = request_firmware(&firmware, name, &microcode_pdev->dev);
+ 	if (error) {
+-		pr_debug("ucode data file %s load failed\n", name);
++		pr_debug("microcode: ucode data file %s load failed\n", name);
+ 		return error;
+ 	}
+ 	buf = firmware->data;
+@@ -579,7 +579,7 @@ static int apply_microcode_check_cpu(int cpu)
+ 		return 0;
+ 
+ 	old = current->cpus_allowed;
+-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 
+ 	/* Check if the microcode we have in memory matches the CPU */
+ 	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
+@@ -610,7 +610,7 @@ static int apply_microcode_check_cpu(int cpu)
+ 			" sig=0x%x, pf=0x%x, rev=0x%x\n",
+ 			cpu, uci->sig, uci->pf, uci->rev);
+ 
+-	set_cpus_allowed(current, old);
++	set_cpus_allowed_ptr(current, &old);
+ 	return err;
+ }
+ 
+@@ -621,13 +621,13 @@ static void microcode_init_cpu(int cpu, int resume)
+ 
+ 	old = current->cpus_allowed;
+ 
+-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 	mutex_lock(&microcode_mutex);
+ 	collect_cpu_info(cpu);
+ 	if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
+ 		cpu_request_microcode(cpu);
+ 	mutex_unlock(&microcode_mutex);
+-	set_cpus_allowed(current, old);
++	set_cpus_allowed_ptr(current, &old);
+ }
+ 
+ static void microcode_fini_cpu(int cpu)
+@@ -657,14 +657,14 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
+ 		old = current->cpus_allowed;
+ 
+ 		get_online_cpus();
+-		set_cpus_allowed(current, cpumask_of_cpu(cpu));
++		set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 
+ 		mutex_lock(&microcode_mutex);
+ 		if (uci->valid)
+ 			err = cpu_request_microcode(cpu);
+ 		mutex_unlock(&microcode_mutex);
+ 		put_online_cpus();
+-		set_cpus_allowed(current, old);
++		set_cpus_allowed_ptr(current, &old);
+ 	}
+ 	if (err)
+ 		return err;
+@@ -709,7 +709,7 @@ static int __mc_sysdev_add(struct sys_device *sys_dev, int resume)
+ 	if (!cpu_online(cpu))
+ 		return 0;
+ 
+-	pr_debug("Microcode:CPU %d added\n", cpu);
++	pr_debug("microcode: CPU%d added\n", cpu);
+ 	memset(uci, 0, sizeof(*uci));
+ 
+ 	err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
+@@ -733,7 +733,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev)
+ 	if (!cpu_online(cpu))
+ 		return 0;
+ 
+-	pr_debug("Microcode:CPU %d removed\n", cpu);
++	pr_debug("microcode: CPU%d removed\n", cpu);
+ 	microcode_fini_cpu(cpu);
+ 	sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
+ 	return 0;
+@@ -745,7 +745,7 @@ static int mc_sysdev_resume(struct sys_device *dev)
+ 
+ 	if (!cpu_online(cpu))
+ 		return 0;
+-	pr_debug("Microcode:CPU %d resumed\n", cpu);
++	pr_debug("microcode: CPU%d resumed\n", cpu);
+ 	/* only CPU 0 will apply ucode here */
+ 	apply_microcode(0);
+ 	return 0;
+@@ -783,7 +783,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
+ 		}
+ 	case CPU_DOWN_FAILED_FROZEN:
+ 		if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
+-			printk(KERN_ERR "Microcode: Failed to create the sysfs "
++			printk(KERN_ERR "microcode: Failed to create the sysfs "
+ 				"group for CPU%d\n", cpu);
+ 		break;
+ 	case CPU_DOWN_PREPARE:
+diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
+new file mode 100644
+index 0000000..3e2c54d
+--- /dev/null
++++ b/arch/x86/kernel/mpparse.c
+@@ -0,0 +1,1084 @@
++/*
++ *	Intel Multiprocessor Specification 1.1 and 1.4
++ *	compliant MP-table parsing routines.
++ *
++ *	(c) 1995 Alan Cox, Building #3 <alan at redhat.com>
++ *	(c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
++ *      (c) 2008 Alexey Starikovskiy <astarikovskiy at suse.de>
++ */
++
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/bitops.h>
++#include <linux/acpi.h>
++#include <linux/module.h>
++
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/mpspec.h>
++#include <asm/pgalloc.h>
++#include <asm/io_apic.h>
++#include <asm/proto.h>
++#include <asm/acpi.h>
++#include <asm/bios_ebda.h>
++
++#include <mach_apic.h>
++#ifdef CONFIG_X86_32
++#include <mach_apicdef.h>
++#include <mach_mpparse.h>
++#endif
++
++/* Have we found an MP table */
++int smp_found_config;
++
++/*
++ * Various Linux-internal data structures created from the
++ * MP-table.
++ */
++#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
++int mp_bus_id_to_type[MAX_MP_BUSSES];
++#endif
++
++DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++int mp_bus_id_to_pci_bus[MAX_MP_BUSSES] = {[0 ... MAX_MP_BUSSES - 1] = -1 };
++
++static int mp_current_pci_id;
++
++int pic_mode;
++
++/*
++ * Intel MP BIOS table parsing routines:
++ */
++
++/*
++ * Checksum an MP configuration block.
++ */
++
++static int __init mpf_checksum(unsigned char *mp, int len)
++{
++	int sum = 0;
++
++	while (len--)
++		sum += *mp++;
++
++	return sum & 0xFF;
++}
++
++#ifdef CONFIG_X86_NUMAQ
++/*
++ * Have to match translation table entries to main table entries by counter
++ * hence the mpc_record variable .... can't see a less disgusting way of
++ * doing this ....
++ */
++
++static int mpc_record;
++static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
++    __cpuinitdata;
++#endif
++
++static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
++{
++	int apicid;
++	char *bootup_cpu = "";
++
++	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
++		disabled_cpus++;
++		return;
++	}
++#ifdef CONFIG_X86_NUMAQ
++	apicid = mpc_apic_id(m, translation_table[mpc_record]);
++#else
++	apicid = m->mpc_apicid;
++#endif
++	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
++		bootup_cpu = " (Bootup-CPU)";
++		boot_cpu_physical_apicid = m->mpc_apicid;
++	}
++
++	printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
++	generic_processor_info(apicid, m->mpc_apicver);
++}
++
++static void __init MP_bus_info(struct mpc_config_bus *m)
++{
++	char str[7];
++
++	memcpy(str, m->mpc_bustype, 6);
++	str[6] = 0;
++
++#ifdef CONFIG_X86_NUMAQ
++	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
++#else
++	Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
++#endif
++
++#if MAX_MP_BUSSES < 256
++	if (m->mpc_busid >= MAX_MP_BUSSES) {
++		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
++		       " is too large, max. supported is %d\n",
++		       m->mpc_busid, str, MAX_MP_BUSSES - 1);
++		return;
++	}
++#endif
++
++	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
++		 set_bit(m->mpc_busid, mp_bus_not_pci);
++#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
++#endif
++	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
++#ifdef CONFIG_X86_NUMAQ
++		mpc_oem_pci_bus(m, translation_table[mpc_record]);
++#endif
++		clear_bit(m->mpc_busid, mp_bus_not_pci);
++		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
++		mp_current_pci_id++;
++#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
++	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
++	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA) - 1) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
++#endif
++	} else
++		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
++}
++
++#ifdef CONFIG_X86_IO_APIC
++
++static int bad_ioapic(unsigned long address)
++{
++	if (nr_ioapics >= MAX_IO_APICS) {
++		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
++		       "(found %d)\n", MAX_IO_APICS, nr_ioapics);
++		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
++	}
++	if (!address) {
++		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
++		       " found in table, skipping!\n");
++		return 1;
++	}
++	return 0;
++}
++
++static void __init MP_ioapic_info(struct mpc_config_ioapic *m)
++{
++	if (!(m->mpc_flags & MPC_APIC_USABLE))
++		return;
++
++	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
++	       m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
++
++	if (bad_ioapic(m->mpc_apicaddr))
++		return;
++
++	mp_ioapics[nr_ioapics] = *m;
++	nr_ioapics++;
++}
++
++static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
++{
++	mp_irqs[mp_irq_entries] = *m;
++	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
++		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
++		m->mpc_irqtype, m->mpc_irqflag & 3,
++		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
++		m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
++	if (++mp_irq_entries == MAX_IRQ_SOURCES)
++		panic("Max # of irq sources exceeded!!\n");
++}
++
++#endif
++
++static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m)
++{
++	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
++		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
++		m->mpc_irqtype, m->mpc_irqflag & 3,
++		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid,
++		m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
++}
++
++#ifdef CONFIG_X86_NUMAQ
++static void __init MP_translation_info(struct mpc_config_translation *m)
++{
++	printk(KERN_INFO
++	       "Translation: record %d, type %d, quad %d, global %d, local %d\n",
++	       mpc_record, m->trans_type, m->trans_quad, m->trans_global,
++	       m->trans_local);
++
++	if (mpc_record >= MAX_MPC_ENTRY)
++		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
++	else
++		translation_table[mpc_record] = m;	/* stash this for later */
++	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
++		node_set_online(m->trans_quad);
++}
++
++/*
++ * Read/parse the MPC oem tables
++ */
++
++static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
++				    unsigned short oemsize)
++{
++	int count = sizeof(*oemtable);	/* the header size */
++	unsigned char *oemptr = ((unsigned char *)oemtable) + count;
++
++	mpc_record = 0;
++	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
++	       oemtable);
++	if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
++		printk(KERN_WARNING
++		       "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
++		       oemtable->oem_signature[0], oemtable->oem_signature[1],
++		       oemtable->oem_signature[2], oemtable->oem_signature[3]);
++		return;
++	}
++	if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
++		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
++		return;
++	}
++	while (count < oemtable->oem_length) {
++		switch (*oemptr) {
++		case MP_TRANSLATION:
++			{
++				struct mpc_config_translation *m =
++				    (struct mpc_config_translation *)oemptr;
++				MP_translation_info(m);
++				oemptr += sizeof(*m);
++				count += sizeof(*m);
++				++mpc_record;
++				break;
++			}
++		default:
++			{
++				printk(KERN_WARNING
++				       "Unrecognised OEM table entry type! - %d\n",
++				       (int)*oemptr);
++				return;
++			}
++		}
++	}
++}
++
++static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
++				 char *productid)
++{
++	if (strncmp(oem, "IBM NUMA", 8))
++		printk("Warning!  May not be a NUMA-Q system!\n");
++	if (mpc->mpc_oemptr)
++		smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr,
++				 mpc->mpc_oemsize);
++}
++#endif /* CONFIG_X86_NUMAQ */
++
++/*
++ * Read/parse the MPC
++ */
++
++static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
++{
++	char str[16];
++	char oem[10];
++	int count = sizeof(*mpc);
++	unsigned char *mpt = ((unsigned char *)mpc) + count;
++
++	if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
++		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
++		       mpc->mpc_signature[0], mpc->mpc_signature[1],
++		       mpc->mpc_signature[2], mpc->mpc_signature[3]);
++		return 0;
++	}
++	if (mpf_checksum((unsigned char *)mpc, mpc->mpc_length)) {
++		printk(KERN_ERR "MPTABLE: checksum error!\n");
++		return 0;
++	}
++	if (mpc->mpc_spec != 0x01 && mpc->mpc_spec != 0x04) {
++		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
++		       mpc->mpc_spec);
++		return 0;
++	}
++	if (!mpc->mpc_lapic) {
++		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
++		return 0;
++	}
++	memcpy(oem, mpc->mpc_oem, 8);
++	oem[8] = 0;
++	printk(KERN_INFO "MPTABLE: OEM ID: %s ", oem);
++
++	memcpy(str, mpc->mpc_productid, 12);
++	str[12] = 0;
++	printk("Product ID: %s ", str);
++
++#ifdef CONFIG_X86_32
++	mps_oem_check(mpc, oem, str);
++#endif
++	printk(KERN_INFO "MPTABLE: Product ID: %s ", str);
++
++	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
++
++	/* save the local APIC address, it might be non-default */
++	if (!acpi_lapic)
++		mp_lapic_addr = mpc->mpc_lapic;
++
++	if (early)
++		return 1;
++
++	/*
++	 *      Now process the configuration blocks.
++	 */
++#ifdef CONFIG_X86_NUMAQ
++	mpc_record = 0;
++#endif
++	while (count < mpc->mpc_length) {
++		switch (*mpt) {
++		case MP_PROCESSOR:
++			{
++				struct mpc_config_processor *m =
++				    (struct mpc_config_processor *)mpt;
++				/* ACPI may have already provided this data */
++				if (!acpi_lapic)
++					MP_processor_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++		case MP_BUS:
++			{
++				struct mpc_config_bus *m =
++				    (struct mpc_config_bus *)mpt;
++				MP_bus_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++		case MP_IOAPIC:
++			{
++#ifdef CONFIG_X86_IO_APIC
++				struct mpc_config_ioapic *m =
++				    (struct mpc_config_ioapic *)mpt;
++				MP_ioapic_info(m);
++#endif
++				mpt += sizeof(struct mpc_config_ioapic);
++				count += sizeof(struct mpc_config_ioapic);
++				break;
++			}
++		case MP_INTSRC:
++			{
++#ifdef CONFIG_X86_IO_APIC
++				struct mpc_config_intsrc *m =
++				    (struct mpc_config_intsrc *)mpt;
++
++				MP_intsrc_info(m);
++#endif
++				mpt += sizeof(struct mpc_config_intsrc);
++				count += sizeof(struct mpc_config_intsrc);
++				break;
++			}
++		case MP_LINTSRC:
++			{
++				struct mpc_config_lintsrc *m =
++				    (struct mpc_config_lintsrc *)mpt;
++				MP_lintsrc_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++		default:
++			/* wrong mptable */
++			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
++			printk(KERN_ERR "type %x\n", *mpt);
++			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
++					1, mpc, mpc->mpc_length, 1);
++			count = mpc->mpc_length;
++			break;
++		}
++#ifdef CONFIG_X86_NUMAQ
++		++mpc_record;
++#endif
++	}
++	setup_apic_routing();
++	if (!num_processors)
++		printk(KERN_ERR "MPTABLE: no processors registered!\n");
++	return num_processors;
++}
++
++#ifdef CONFIG_X86_IO_APIC
++
++static int __init ELCR_trigger(unsigned int irq)
++{
++	unsigned int port;
++
++	port = 0x4d0 + (irq >> 3);
++	return (inb(port) >> (irq & 7)) & 1;
++}
++
++static void __init construct_default_ioirq_mptable(int mpc_default_type)
++{
++	struct mpc_config_intsrc intsrc;
++	int i;
++	int ELCR_fallback = 0;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqflag = 0;	/* conforming */
++	intsrc.mpc_srcbus = 0;
++	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
++
++	intsrc.mpc_irqtype = mp_INT;
++
++	/*
++	 *  If true, we have an ISA/PCI system with no IRQ entries
++	 *  in the MP table. To prevent the PCI interrupts from being set up
++	 *  incorrectly, we try to use the ELCR. The sanity check to see if
++	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
++	 *  never be level sensitive, so we simply see if the ELCR agrees.
++	 *  If it does, we assume it's valid.
++	 */
++	if (mpc_default_type == 5) {
++		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
++		       "falling back to ELCR\n");
++
++		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
++		    ELCR_trigger(13))
++			printk(KERN_ERR "ELCR contains invalid data... "
++			       "not using ELCR\n");
++		else {
++			printk(KERN_INFO
++			       "Using ELCR to identify PCI interrupts\n");
++			ELCR_fallback = 1;
++		}
++	}
++
++	for (i = 0; i < 16; i++) {
++		switch (mpc_default_type) {
++		case 2:
++			if (i == 0 || i == 13)
++				continue;	/* IRQ0 & IRQ13 not connected */
++			/* fall through */
++		default:
++			if (i == 2)
++				continue;	/* IRQ2 is never connected */
++		}
++
++		if (ELCR_fallback) {
++			/*
++			 *  If the ELCR indicates a level-sensitive interrupt, we
++			 *  copy that information over to the MP table in the
++			 *  irqflag field (level sensitive, active high polarity).
++			 */
++			if (ELCR_trigger(i))
++				intsrc.mpc_irqflag = 13;
++			else
++				intsrc.mpc_irqflag = 0;
++		}
++
++		intsrc.mpc_srcbusirq = i;
++		intsrc.mpc_dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
++		MP_intsrc_info(&intsrc);
++	}
++
++	intsrc.mpc_irqtype = mp_ExtINT;
++	intsrc.mpc_srcbusirq = 0;
++	intsrc.mpc_dstirq = 0;	/* 8259A to INTIN0 */
++	MP_intsrc_info(&intsrc);
++}
++
++#endif
++
++static inline void __init construct_default_ISA_mptable(int mpc_default_type)
++{
++	struct mpc_config_processor processor;
++	struct mpc_config_bus bus;
++#ifdef CONFIG_X86_IO_APIC
++	struct mpc_config_ioapic ioapic;
++#endif
++	struct mpc_config_lintsrc lintsrc;
++	int linttypes[2] = { mp_ExtINT, mp_NMI };
++	int i;
++
++	/*
++	 * local APIC has default address
++	 */
++	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++
++	/*
++	 * 2 CPUs, numbered 0 & 1.
++	 */
++	processor.mpc_type = MP_PROCESSOR;
++	/* Either an integrated APIC or a discrete 82489DX. */
++	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	processor.mpc_cpuflag = CPU_ENABLED;
++	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
++	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
++	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++	processor.mpc_reserved[0] = 0;
++	processor.mpc_reserved[1] = 0;
++	for (i = 0; i < 2; i++) {
++		processor.mpc_apicid = i;
++		MP_processor_info(&processor);
++	}
++
++	bus.mpc_type = MP_BUS;
++	bus.mpc_busid = 0;
++	switch (mpc_default_type) {
++	default:
++		printk(KERN_ERR "???\nUnknown standard configuration %d\n",
++		       mpc_default_type);
++		/* fall through */
++	case 1:
++	case 5:
++		memcpy(bus.mpc_bustype, "ISA   ", 6);
++		break;
++	case 2:
++	case 6:
++	case 3:
++		memcpy(bus.mpc_bustype, "EISA  ", 6);
++		break;
++	case 4:
++	case 7:
++		memcpy(bus.mpc_bustype, "MCA   ", 6);
++	}
++	MP_bus_info(&bus);
++	if (mpc_default_type > 4) {
++		bus.mpc_busid = 1;
++		memcpy(bus.mpc_bustype, "PCI   ", 6);
++		MP_bus_info(&bus);
++	}
++
++#ifdef CONFIG_X86_IO_APIC
++	ioapic.mpc_type = MP_IOAPIC;
++	ioapic.mpc_apicid = 2;
++	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	ioapic.mpc_flags = MPC_APIC_USABLE;
++	ioapic.mpc_apicaddr = 0xFEC00000;
++	MP_ioapic_info(&ioapic);
++
++	/*
++	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
++	 */
++	construct_default_ioirq_mptable(mpc_default_type);
++#endif
++	lintsrc.mpc_type = MP_LINTSRC;
++	lintsrc.mpc_irqflag = 0;	/* conforming */
++	lintsrc.mpc_srcbusid = 0;
++	lintsrc.mpc_srcbusirq = 0;
++	lintsrc.mpc_destapic = MP_APIC_ALL;
++	for (i = 0; i < 2; i++) {
++		lintsrc.mpc_irqtype = linttypes[i];
++		lintsrc.mpc_destapiclint = i;
++		MP_lintsrc_info(&lintsrc);
++	}
++}
++
++static struct intel_mp_floating *mpf_found;
++
++/*
++ * Scan the memory blocks for an SMP configuration block.
++ */
++static void __init __get_smp_config(unsigned early)
++{
++	struct intel_mp_floating *mpf = mpf_found;
++
++	if (acpi_lapic && early)
++		return;
++	/*
++	 * ACPI supports both logical (e.g. Hyper-Threading) and physical
++	 * processors, where MPS only supports physical.
++	 */
++	if (acpi_lapic && acpi_ioapic) {
++		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
++		       "information\n");
++		return;
++	} else if (acpi_lapic)
++		printk(KERN_INFO "Using ACPI for processor (LAPIC) "
++		       "configuration information\n");
++
++	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
++	       mpf->mpf_specification);
++#ifdef CONFIG_X86_32
++	if (mpf->mpf_feature2 & (1 << 7)) {
++		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
++		pic_mode = 1;
++	} else {
++		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
++		pic_mode = 0;
++	}
++#endif
++	/*
++	 * Now see if we need to read further.
++	 */
++	if (mpf->mpf_feature1 != 0) {
++		if (early) {
++			/*
++			 * local APIC has default address
++			 */
++			mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++			return;
++		}
++
++		printk(KERN_INFO "Default MP configuration #%d\n",
++		       mpf->mpf_feature1);
++		construct_default_ISA_mptable(mpf->mpf_feature1);
++
++	} else if (mpf->mpf_physptr) {
++
++		/*
++		 * Read the physical hardware table.  Anything here will
++		 * override the defaults.
++		 */
++		if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr), early)) {
++			smp_found_config = 0;
++			printk(KERN_ERR
++			       "BIOS bug, MP table errors detected!...\n");
++			printk(KERN_ERR "... disabling SMP support. "
++			       "(tell your hw vendor)\n");
++			return;
++		}
++
++		if (early)
++			return;
++#ifdef CONFIG_X86_IO_APIC
++		/*
++		 * If there are no explicit MP IRQ entries, then we are
++		 * broken.  We set up most of the low 16 IO-APIC pins to
++		 * ISA defaults and hope it will work.
++		 */
++		if (!mp_irq_entries) {
++			struct mpc_config_bus bus;
++
++			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
++			       "using default mptable. "
++			       "(tell your hw vendor)\n");
++
++			bus.mpc_type = MP_BUS;
++			bus.mpc_busid = 0;
++			memcpy(bus.mpc_bustype, "ISA   ", 6);
++			MP_bus_info(&bus);
++
++			construct_default_ioirq_mptable(0);
++		}
++#endif
++	} else
++		BUG();
++
++	if (!early)
++		printk(KERN_INFO "Processors: %d\n", num_processors);
++	/*
++	 * Only use the first configuration found.
++	 */
++}
++
++void __init early_get_smp_config(void)
++{
++	__get_smp_config(1);
++}
++
++void __init get_smp_config(void)
++{
++	__get_smp_config(0);
++}
++
++static int __init smp_scan_config(unsigned long base, unsigned long length,
++				  unsigned reserve)
++{
++	unsigned int *bp = phys_to_virt(base);
++	struct intel_mp_floating *mpf;
++
++	Dprintk("Scan SMP from %p for %ld bytes.\n", bp, length);
++	BUILD_BUG_ON(sizeof(*mpf) != 16);
++
++	while (length > 0) {
++		mpf = (struct intel_mp_floating *)bp;
++		if ((*bp == SMP_MAGIC_IDENT) &&
++		    (mpf->mpf_length == 1) &&
++		    !mpf_checksum((unsigned char *)bp, 16) &&
++		    ((mpf->mpf_specification == 1)
++		     || (mpf->mpf_specification == 4))) {
++
++			smp_found_config = 1;
++			mpf_found = mpf;
++#ifdef CONFIG_X86_32
++			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
++			       mpf, virt_to_phys(mpf));
++			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
++					BOOTMEM_DEFAULT);
++			if (mpf->mpf_physptr) {
++				/*
++				 * We cannot access to MPC table to compute
++				 * table size yet, as only few megabytes from
++				 * the bottom is mapped now.
++				 * PC-9800's MPC table places on the very last
++				 * of physical memory; so that simply reserving
++				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
++				 * in reserve_bootmem.
++				 */
++				unsigned long size = PAGE_SIZE;
++				unsigned long end = max_low_pfn * PAGE_SIZE;
++				if (mpf->mpf_physptr + size > end)
++					size = end - mpf->mpf_physptr;
++				reserve_bootmem(mpf->mpf_physptr, size,
++						BOOTMEM_DEFAULT);
++			}
++
++#else
++			if (!reserve)
++				return 1;
++
++			reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE);
++			if (mpf->mpf_physptr)
++				reserve_bootmem_generic(mpf->mpf_physptr,
++							PAGE_SIZE);
++#endif
++		return 1;
++		}
++		bp += 4;
++		length -= 16;
++	}
++	return 0;
++}
++
++static void __init __find_smp_config(unsigned reserve)
++{
++	unsigned int address;
++
++	/*
++	 * FIXME: Linux assumes you have 640K of base ram..
++	 * this continues the error...
++	 *
++	 * 1) Scan the bottom 1K for a signature
++	 * 2) Scan the top 1K of base RAM
++	 * 3) Scan the 64K of bios
++	 */
++	if (smp_scan_config(0x0, 0x400, reserve) ||
++	    smp_scan_config(639 * 0x400, 0x400, reserve) ||
++	    smp_scan_config(0xF0000, 0x10000, reserve))
++		return;
++	/*
++	 * If it is an SMP machine we should know now, unless the
++	 * configuration is in an EISA/MCA bus machine with an
++	 * extended bios data area.
++	 *
++	 * there is a real-mode segmented pointer pointing to the
++	 * 4K EBDA area at 0x40E, calculate and scan it here.
++	 *
++	 * NOTE! There are Linux loaders that will corrupt the EBDA
++	 * area, and as such this kind of SMP config may be less
++	 * trustworthy, simply because the SMP table may have been
++	 * stomped on during early boot. These loaders are buggy and
++	 * should be fixed.
++	 *
++	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
++	 */
++
++	address = get_bios_ebda();
++	if (address)
++		smp_scan_config(address, 0x400, reserve);
++}
++
++void __init early_find_smp_config(void)
++{
++	__find_smp_config(0);
++}
++
++void __init find_smp_config(void)
++{
++	__find_smp_config(1);
++}
++
++/* --------------------------------------------------------------------------
++                            ACPI-based MP Configuration
++   -------------------------------------------------------------------------- */
++
++#ifdef CONFIG_ACPI
++
++#ifdef	CONFIG_X86_IO_APIC
++
++#define MP_ISA_BUS		0
++
++extern struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS];
++
++static int mp_find_ioapic(int gsi)
++{
++	int i = 0;
++
++	/* Find the IOAPIC that manages this GSI. */
++	for (i = 0; i < nr_ioapics; i++) {
++		if ((gsi >= mp_ioapic_routing[i].gsi_base)
++		    && (gsi <= mp_ioapic_routing[i].gsi_end))
++			return i;
++	}
++
++	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
++	return -1;
++}
++
++static u8 __init uniq_ioapic_id(u8 id)
++{
++#ifdef CONFIG_X86_32
++	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
++	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
++		return io_apic_get_unique_id(nr_ioapics, id);
++	else
++		return id;
++#else
++	int i;
++	DECLARE_BITMAP(used, 256);
++	bitmap_zero(used, 256);
++	for (i = 0; i < nr_ioapics; i++) {
++		struct mpc_config_ioapic *ia = &mp_ioapics[i];
++		__set_bit(ia->mpc_apicid, used);
++	}
++	if (!test_bit(id, used))
++		return id;
++	return find_first_zero_bit(used, 256);
++#endif
++}
++
++void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
++{
++	int idx = 0;
++
++	if (bad_ioapic(address))
++		return;
++
++	idx = nr_ioapics;
++
++	mp_ioapics[idx].mpc_type = MP_IOAPIC;
++	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
++	mp_ioapics[idx].mpc_apicaddr = address;
++
++	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
++	mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
++#ifdef CONFIG_X86_32
++	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
++#else
++	mp_ioapics[idx].mpc_apicver = 0;
++#endif
++	/*
++	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
++	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
++	 */
++	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
++	mp_ioapic_routing[idx].gsi_base = gsi_base;
++	mp_ioapic_routing[idx].gsi_end = gsi_base +
++	    io_apic_get_redir_entries(idx);
++
++	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
++	       "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
++	       mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
++	       mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end);
++
++	nr_ioapics++;
++}
++
++void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
++{
++	struct mpc_config_intsrc intsrc;
++	int ioapic = -1;
++	int pin = -1;
++
++	/*
++	 * Convert 'gsi' to 'ioapic.pin'.
++	 */
++	ioapic = mp_find_ioapic(gsi);
++	if (ioapic < 0)
++		return;
++	pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++
++	/*
++	 * TBD: This check is for faulty timer entries, where the override
++	 *      erroneously sets the trigger to level, resulting in a HUGE
++	 *      increase of timer interrupts!
++	 */
++	if ((bus_irq == 0) && (trigger == 3))
++		trigger = 1;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqtype = mp_INT;
++	intsrc.mpc_irqflag = (trigger << 2) | polarity;
++	intsrc.mpc_srcbus = MP_ISA_BUS;
++	intsrc.mpc_srcbusirq = bus_irq;	/* IRQ */
++	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	/* APIC ID */
++	intsrc.mpc_dstirq = pin;	/* INTIN# */
++
++	MP_intsrc_info(&intsrc);
++}
++
++int es7000_plat;
++
++void __init mp_config_acpi_legacy_irqs(void)
++{
++	struct mpc_config_intsrc intsrc;
++	int i = 0;
++	int ioapic = -1;
++
++#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
++	/*
++	 * Fabricate the legacy ISA bus (bus #31).
++	 */
++	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
++#endif
++	set_bit(MP_ISA_BUS, mp_bus_not_pci);
++	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
++
++	/*
++	 * Older generations of ES7000 have no legacy identity mappings
++	 */
++	if (es7000_plat == 1)
++		return;
++
++	/*
++	 * Locate the IOAPIC that manages the ISA IRQs (0-15).
++	 */
++	ioapic = mp_find_ioapic(0);
++	if (ioapic < 0)
++		return;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqflag = 0;	/* Conforming */
++	intsrc.mpc_srcbus = MP_ISA_BUS;
++#ifdef CONFIG_X86_IO_APIC
++	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
++#endif
++	/*
++	 * Use the default configuration for the IRQs 0-15.  Unless
++	 * overridden by (MADT) interrupt source override entries.
++	 */
++	for (i = 0; i < 16; i++) {
++		int idx;
++
++		for (idx = 0; idx < mp_irq_entries; idx++) {
++			struct mpc_config_intsrc *irq = mp_irqs + idx;
++
++			/* Do we already have a mapping for this ISA IRQ? */
++			if (irq->mpc_srcbus == MP_ISA_BUS
++			    && irq->mpc_srcbusirq == i)
++				break;
++
++			/* Do we already have a mapping for this IOAPIC pin */
++			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
++			    (irq->mpc_dstirq == i))
++				break;
++		}
++
++		if (idx != mp_irq_entries) {
++			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
++			continue;	/* IRQ already used */
++		}
++
++		intsrc.mpc_irqtype = mp_INT;
++		intsrc.mpc_srcbusirq = i;	/* Identity mapped */
++		intsrc.mpc_dstirq = i;
++
++		MP_intsrc_info(&intsrc);
++	}
++}
++
++int mp_register_gsi(u32 gsi, int triggering, int polarity)
++{
++	int ioapic;
++	int ioapic_pin;
++#ifdef CONFIG_X86_32
++#define MAX_GSI_NUM	4096
++#define IRQ_COMPRESSION_START	64
++
++	static int pci_irq = IRQ_COMPRESSION_START;
++	/*
++	 * Mapping between Global System Interrupts, which
++	 * represent all possible interrupts, and IRQs
++	 * assigned to actual devices.
++	 */
++	static int gsi_to_irq[MAX_GSI_NUM];
++#else
++
++	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
++		return gsi;
++#endif
++
++	/* Don't set up the ACPI SCI because it's already set up */
++	if (acpi_gbl_FADT.sci_interrupt == gsi)
++		return gsi;
++
++	ioapic = mp_find_ioapic(gsi);
++	if (ioapic < 0) {
++		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
++		return gsi;
++	}
++
++	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++
++#ifdef CONFIG_X86_32
++	if (ioapic_renumber_irq)
++		gsi = ioapic_renumber_irq(ioapic, gsi);
++#endif
++
++	/*
++	 * Avoid pin reprogramming.  PRTs typically include entries
++	 * with redundant pin->gsi mappings (but unique PCI devices);
++	 * we only program the IOAPIC on the first.
++	 */
++	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
++		printk(KERN_ERR "Invalid reference to IOAPIC pin "
++		       "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
++		       ioapic_pin);
++		return gsi;
++	}
++	if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
++		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
++			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
++#ifdef CONFIG_X86_32
++		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
++#else
++		return gsi;
++#endif
++	}
++
++	set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
++#ifdef CONFIG_X86_32
++	/*
++	 * For GSI >= 64, use IRQ compression
++	 */
++	if ((gsi >= IRQ_COMPRESSION_START)
++	    && (triggering == ACPI_LEVEL_SENSITIVE)) {
++		/*
++		 * For PCI devices assign IRQs in order, avoiding gaps
++		 * due to unused I/O APIC pins.
++		 */
++		int irq = gsi;
++		if (gsi < MAX_GSI_NUM) {
++			/*
++			 * Retain the VIA chipset work-around (gsi > 15), but
++			 * avoid a problem where the 8254 timer (IRQ0) is setup
++			 * via an override (so it's not on pin 0 of the ioapic),
++			 * and at the same time, the pin 0 interrupt is a PCI
++			 * type.  The gsi > 15 test could cause these two pins
++			 * to be shared as IRQ0, and they are not shareable.
++			 * So test for this condition, and if necessary, avoid
++			 * the pin collision.
++			 */
++			gsi = pci_irq++;
++			/*
++			 * Don't assign IRQ used by ACPI SCI
++			 */
++			if (gsi == acpi_gbl_FADT.sci_interrupt)
++				gsi = pci_irq++;
++			gsi_to_irq[irq] = gsi;
++		} else {
++			printk(KERN_ERR "GSI %u is too high\n", gsi);
++			return gsi;
++		}
++	}
++#endif
++	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
++				triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
++				polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
++	return gsi;
++}
++
++#endif /* CONFIG_X86_IO_APIC */
++#endif /* CONFIG_ACPI */
+diff --git a/arch/x86/kernel/mpparse_32.c b/arch/x86/kernel/mpparse_32.c
+deleted file mode 100644
+index f349e68..0000000
+--- a/arch/x86/kernel/mpparse_32.c
++++ /dev/null
+@@ -1,1139 +0,0 @@
+-/*
+- *	Intel Multiprocessor Specification 1.1 and 1.4
+- *	compliant MP-table parsing routines.
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- *	(c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
+- *
+- *	Fixes
+- *		Erich Boleyn	:	MP v1.4 and additional changes.
+- *		Alan Cox	:	Added EBDA scanning
+- *		Ingo Molnar	:	various cleanups and rewrites
+- *		Maciej W. Rozycki:	Bits for default MP configurations
+- *		Paul Diefenbaugh:	Added full ACPI support
+- */
+-
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/acpi.h>
+-#include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/bitops.h>
+-
+-#include <asm/smp.h>
+-#include <asm/acpi.h>
+-#include <asm/mtrr.h>
+-#include <asm/mpspec.h>
+-#include <asm/io_apic.h>
+-
+-#include <mach_apic.h>
+-#include <mach_apicdef.h>
+-#include <mach_mpparse.h>
+-#include <bios_ebda.h>
+-
+-/* Have we found an MP table */
+-int smp_found_config;
+-unsigned int __cpuinitdata maxcpus = NR_CPUS;
+-
+-/*
+- * Various Linux-internal data structures created from the
+- * MP-table.
+- */
+-int apic_version [MAX_APICS];
+-int mp_bus_id_to_type [MAX_MP_BUSSES];
+-int mp_bus_id_to_node [MAX_MP_BUSSES];
+-int mp_bus_id_to_local [MAX_MP_BUSSES];
+-int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+-static int mp_current_pci_id;
+-
+-/* I/O APIC entries */
+-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+-
+-/* # of MP IRQ source entries */
+-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+-
+-/* MP IRQ source entries */
+-int mp_irq_entries;
+-
+-int nr_ioapics;
+-
+-int pic_mode;
+-unsigned long mp_lapic_addr;
+-
+-unsigned int def_to_bigsmp = 0;
+-
+-/* Processor that is doing the boot up */
+-unsigned int boot_cpu_physical_apicid = -1U;
+-/* Internal processor count */
+-unsigned int num_processors;
+-
+-/* Bitmask of physically existing CPUs */
+-physid_mask_t phys_cpu_present_map;
+-
+-u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+-
+-/*
+- * Intel MP BIOS table parsing routines:
+- */
+-
+-
+-/*
+- * Checksum an MP configuration block.
+- */
+-
+-static int __init mpf_checksum(unsigned char *mp, int len)
+-{
+-	int sum = 0;
+-
+-	while (len--)
+-		sum += *mp++;
+-
+-	return sum & 0xFF;
+-}
+-
+-/*
+- * Have to match translation table entries to main table entries by counter
+- * hence the mpc_record variable .... can't see a less disgusting way of
+- * doing this ....
+- */
+-
+-static int mpc_record; 
+-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __cpuinitdata;
+-
+-static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
+-{
+- 	int ver, apicid;
+-	physid_mask_t phys_cpu;
+- 	
+-	if (!(m->mpc_cpuflag & CPU_ENABLED))
+-		return;
+-
+-	apicid = mpc_apic_id(m, translation_table[mpc_record]);
+-
+-	if (m->mpc_featureflag&(1<<0))
+-		Dprintk("    Floating point unit present.\n");
+-	if (m->mpc_featureflag&(1<<7))
+-		Dprintk("    Machine Exception supported.\n");
+-	if (m->mpc_featureflag&(1<<8))
+-		Dprintk("    64 bit compare & exchange supported.\n");
+-	if (m->mpc_featureflag&(1<<9))
+-		Dprintk("    Internal APIC present.\n");
+-	if (m->mpc_featureflag&(1<<11))
+-		Dprintk("    SEP present.\n");
+-	if (m->mpc_featureflag&(1<<12))
+-		Dprintk("    MTRR  present.\n");
+-	if (m->mpc_featureflag&(1<<13))
+-		Dprintk("    PGE  present.\n");
+-	if (m->mpc_featureflag&(1<<14))
+-		Dprintk("    MCA  present.\n");
+-	if (m->mpc_featureflag&(1<<15))
+-		Dprintk("    CMOV  present.\n");
+-	if (m->mpc_featureflag&(1<<16))
+-		Dprintk("    PAT  present.\n");
+-	if (m->mpc_featureflag&(1<<17))
+-		Dprintk("    PSE  present.\n");
+-	if (m->mpc_featureflag&(1<<18))
+-		Dprintk("    PSN  present.\n");
+-	if (m->mpc_featureflag&(1<<19))
+-		Dprintk("    Cache Line Flush Instruction present.\n");
+-	/* 20 Reserved */
+-	if (m->mpc_featureflag&(1<<21))
+-		Dprintk("    Debug Trace and EMON Store present.\n");
+-	if (m->mpc_featureflag&(1<<22))
+-		Dprintk("    ACPI Thermal Throttle Registers  present.\n");
+-	if (m->mpc_featureflag&(1<<23))
+-		Dprintk("    MMX  present.\n");
+-	if (m->mpc_featureflag&(1<<24))
+-		Dprintk("    FXSR  present.\n");
+-	if (m->mpc_featureflag&(1<<25))
+-		Dprintk("    XMM  present.\n");
+-	if (m->mpc_featureflag&(1<<26))
+-		Dprintk("    Willamette New Instructions  present.\n");
+-	if (m->mpc_featureflag&(1<<27))
+-		Dprintk("    Self Snoop  present.\n");
+-	if (m->mpc_featureflag&(1<<28))
+-		Dprintk("    HT  present.\n");
+-	if (m->mpc_featureflag&(1<<29))
+-		Dprintk("    Thermal Monitor present.\n");
+-	/* 30, 31 Reserved */
+-
+-
+-	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+-		Dprintk("    Bootup CPU\n");
+-		boot_cpu_physical_apicid = m->mpc_apicid;
+-	}
+-
+-	ver = m->mpc_apicver;
+-
+-	/*
+-	 * Validate version
+-	 */
+-	if (ver == 0x0) {
+-		printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! "
+-				"fixing up to 0x10. (tell your hw vendor)\n",
+-				m->mpc_apicid);
+-		ver = 0x10;
+-	}
+-	apic_version[m->mpc_apicid] = ver;
+-
+-	phys_cpu = apicid_to_cpu_present(apicid);
+-	physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
+-
+-	if (num_processors >= NR_CPUS) {
+-		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+-			"  Processor ignored.\n", NR_CPUS);
+-		return;
+-	}
+-
+-	if (num_processors >= maxcpus) {
+-		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
+-			" Processor ignored.\n", maxcpus);
+-		return;
+-	}
+-
+-	cpu_set(num_processors, cpu_possible_map);
+-	num_processors++;
+-
+-	/*
+-	 * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
+-	 * but we need to work other dependencies like SMP_SUSPEND etc
+-	 * before this can be done without some confusion.
+-	 * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
+-	 *       - Ashok Raj <ashok.raj at intel.com>
+-	 */
+-	if (num_processors > 8) {
+-		switch (boot_cpu_data.x86_vendor) {
+-		case X86_VENDOR_INTEL:
+-			if (!APIC_XAPIC(ver)) {
+-				def_to_bigsmp = 0;
+-				break;
+-			}
+-			/* If P4 and above fall through */
+-		case X86_VENDOR_AMD:
+-			def_to_bigsmp = 1;
+-		}
+-	}
+-	bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
+-}
+-
+-static void __init MP_bus_info (struct mpc_config_bus *m)
+-{
+-	char str[7];
+-
+-	memcpy(str, m->mpc_bustype, 6);
+-	str[6] = 0;
+-
+-	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+-
+-#if MAX_MP_BUSSES < 256
+-	if (m->mpc_busid >= MAX_MP_BUSSES) {
+-		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+-			" is too large, max. supported is %d\n",
+-			m->mpc_busid, str, MAX_MP_BUSSES - 1);
+-		return;
+-	}
+-#endif
+-
+-	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
+-	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
+-	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
+-		mpc_oem_pci_bus(m, translation_table[mpc_record]);
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+-		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
+-		mp_current_pci_id++;
+-	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
+-	} else {
+-		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+-	}
+-}
+-
+-static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
+-{
+-	if (!(m->mpc_flags & MPC_APIC_USABLE))
+-		return;
+-
+-	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
+-		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
+-	if (nr_ioapics >= MAX_IO_APICS) {
+-		printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
+-			MAX_IO_APICS, nr_ioapics);
+-		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
+-	}
+-	if (!m->mpc_apicaddr) {
+-		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
+-			" found in MP table, skipping!\n");
+-		return;
+-	}
+-	mp_ioapics[nr_ioapics] = *m;
+-	nr_ioapics++;
+-}
+-
+-static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
+-{
+-	mp_irqs [mp_irq_entries] = *m;
+-	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
+-		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+-			m->mpc_irqtype, m->mpc_irqflag & 3,
+-			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
+-			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
+-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-		panic("Max # of irq sources exceeded!!\n");
+-}
+-
+-static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
+-{
+-	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
+-		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+-			m->mpc_irqtype, m->mpc_irqflag & 3,
+-			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
+-			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+-}
+-
+-#ifdef CONFIG_X86_NUMAQ
+-static void __init MP_translation_info (struct mpc_config_translation *m)
+-{
+-	printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
+-
+-	if (mpc_record >= MAX_MPC_ENTRY) 
+-		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
+-	else
+-		translation_table[mpc_record] = m; /* stash this for later */
+-	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
+-		node_set_online(m->trans_quad);
+-}
+-
+-/*
+- * Read/parse the MPC oem tables
+- */
+-
+-static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
+-	unsigned short oemsize)
+-{
+-	int count = sizeof (*oemtable); /* the header size */
+-	unsigned char *oemptr = ((unsigned char *)oemtable)+count;
+-	
+-	mpc_record = 0;
+-	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
+-	if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
+-	{
+-		printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
+-			oemtable->oem_signature[0],
+-			oemtable->oem_signature[1],
+-			oemtable->oem_signature[2],
+-			oemtable->oem_signature[3]);
+-		return;
+-	}
+-	if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
+-	{
+-		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
+-		return;
+-	}
+-	while (count < oemtable->oem_length) {
+-		switch (*oemptr) {
+-			case MP_TRANSLATION:
+-			{
+-				struct mpc_config_translation *m=
+-					(struct mpc_config_translation *)oemptr;
+-				MP_translation_info(m);
+-				oemptr += sizeof(*m);
+-				count += sizeof(*m);
+-				++mpc_record;
+-				break;
+-			}
+-			default:
+-			{
+-				printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
+-				return;
+-			}
+-		}
+-       }
+-}
+-
+-static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
+-		char *productid)
+-{
+-	if (strncmp(oem, "IBM NUMA", 8))
+-		printk("Warning!  May not be a NUMA-Q system!\n");
+-	if (mpc->mpc_oemptr)
+-		smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr,
+-				mpc->mpc_oemsize);
+-}
+-#endif	/* CONFIG_X86_NUMAQ */
+-
+-/*
+- * Read/parse the MPC
+- */
+-
+-static int __init smp_read_mpc(struct mp_config_table *mpc)
+-{
+-	char str[16];
+-	char oem[10];
+-	int count=sizeof(*mpc);
+-	unsigned char *mpt=((unsigned char *)mpc)+count;
+-
+-	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
+-		printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n",
+-			*(u32 *)mpc->mpc_signature);
+-		return 0;
+-	}
+-	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
+-		printk(KERN_ERR "SMP mptable: checksum error!\n");
+-		return 0;
+-	}
+-	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
+-		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
+-			mpc->mpc_spec);
+-		return 0;
+-	}
+-	if (!mpc->mpc_lapic) {
+-		printk(KERN_ERR "SMP mptable: null local APIC address!\n");
+-		return 0;
+-	}
+-	memcpy(oem,mpc->mpc_oem,8);
+-	oem[8]=0;
+-	printk(KERN_INFO "OEM ID: %s ",oem);
+-
+-	memcpy(str,mpc->mpc_productid,12);
+-	str[12]=0;
+-	printk("Product ID: %s ",str);
+-
+-	mps_oem_check(mpc, oem, str);
+-
+-	printk("APIC at: 0x%X\n", mpc->mpc_lapic);
+-
+-	/*
+-	 * Save the local APIC address (it might be non-default) -- but only
+-	 * if we're not using ACPI.
+-	 */
+-	if (!acpi_lapic)
+-		mp_lapic_addr = mpc->mpc_lapic;
+-
+-	/*
+-	 *	Now process the configuration blocks.
+-	 */
+-	mpc_record = 0;
+-	while (count < mpc->mpc_length) {
+-		switch(*mpt) {
+-			case MP_PROCESSOR:
+-			{
+-				struct mpc_config_processor *m=
+-					(struct mpc_config_processor *)mpt;
+-				/* ACPI may have already provided this data */
+-				if (!acpi_lapic)
+-					MP_processor_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_BUS:
+-			{
+-				struct mpc_config_bus *m=
+-					(struct mpc_config_bus *)mpt;
+-				MP_bus_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_IOAPIC:
+-			{
+-				struct mpc_config_ioapic *m=
+-					(struct mpc_config_ioapic *)mpt;
+-				MP_ioapic_info(m);
+-				mpt+=sizeof(*m);
+-				count+=sizeof(*m);
+-				break;
+-			}
+-			case MP_INTSRC:
+-			{
+-				struct mpc_config_intsrc *m=
+-					(struct mpc_config_intsrc *)mpt;
+-
+-				MP_intsrc_info(m);
+-				mpt+=sizeof(*m);
+-				count+=sizeof(*m);
+-				break;
+-			}
+-			case MP_LINTSRC:
+-			{
+-				struct mpc_config_lintsrc *m=
+-					(struct mpc_config_lintsrc *)mpt;
+-				MP_lintsrc_info(m);
+-				mpt+=sizeof(*m);
+-				count+=sizeof(*m);
+-				break;
+-			}
+-			default:
+-			{
+-				count = mpc->mpc_length;
+-				break;
+-			}
+-		}
+-		++mpc_record;
+-	}
+-	setup_apic_routing();
+-	if (!num_processors)
+-		printk(KERN_ERR "SMP mptable: no processors registered!\n");
+-	return num_processors;
+-}
+-
+-static int __init ELCR_trigger(unsigned int irq)
+-{
+-	unsigned int port;
+-
+-	port = 0x4d0 + (irq >> 3);
+-	return (inb(port) >> (irq & 7)) & 1;
+-}
+-
+-static void __init construct_default_ioirq_mptable(int mpc_default_type)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int i;
+-	int ELCR_fallback = 0;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;			/* conforming */
+-	intsrc.mpc_srcbus = 0;
+-	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
+-
+-	intsrc.mpc_irqtype = mp_INT;
+-
+-	/*
+-	 *  If true, we have an ISA/PCI system with no IRQ entries
+-	 *  in the MP table. To prevent the PCI interrupts from being set up
+-	 *  incorrectly, we try to use the ELCR. The sanity check to see if
+-	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
+-	 *  never be level sensitive, so we simply see if the ELCR agrees.
+-	 *  If it does, we assume it's valid.
+-	 */
+-	if (mpc_default_type == 5) {
+-		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
+-
+-		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
+-			printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n");
+-		else {
+-			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
+-			ELCR_fallback = 1;
+-		}
+-	}
+-
+-	for (i = 0; i < 16; i++) {
+-		switch (mpc_default_type) {
+-		case 2:
+-			if (i == 0 || i == 13)
+-				continue;	/* IRQ0 & IRQ13 not connected */
+-			/* fall through */
+-		default:
+-			if (i == 2)
+-				continue;	/* IRQ2 is never connected */
+-		}
+-
+-		if (ELCR_fallback) {
+-			/*
+-			 *  If the ELCR indicates a level-sensitive interrupt, we
+-			 *  copy that information over to the MP table in the
+-			 *  irqflag field (level sensitive, active high polarity).
+-			 */
+-			if (ELCR_trigger(i))
+-				intsrc.mpc_irqflag = 13;
+-			else
+-				intsrc.mpc_irqflag = 0;
+-		}
+-
+-		intsrc.mpc_srcbusirq = i;
+-		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
+-		MP_intsrc_info(&intsrc);
+-	}
+-
+-	intsrc.mpc_irqtype = mp_ExtINT;
+-	intsrc.mpc_srcbusirq = 0;
+-	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
+-	MP_intsrc_info(&intsrc);
+-}
+-
+-static inline void __init construct_default_ISA_mptable(int mpc_default_type)
+-{
+-	struct mpc_config_processor processor;
+-	struct mpc_config_bus bus;
+-	struct mpc_config_ioapic ioapic;
+-	struct mpc_config_lintsrc lintsrc;
+-	int linttypes[2] = { mp_ExtINT, mp_NMI };
+-	int i;
+-
+-	/*
+-	 * local APIC has default address
+-	 */
+-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+-
+-	/*
+-	 * 2 CPUs, numbered 0 & 1.
+-	 */
+-	processor.mpc_type = MP_PROCESSOR;
+-	/* Either an integrated APIC or a discrete 82489DX. */
+-	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+-	processor.mpc_cpuflag = CPU_ENABLED;
+-	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
+-				   (boot_cpu_data.x86_model << 4) |
+-				   boot_cpu_data.x86_mask;
+-	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
+-	for (i = 0; i < 2; i++) {
+-		processor.mpc_apicid = i;
+-		MP_processor_info(&processor);
+-	}
+-
+-	bus.mpc_type = MP_BUS;
+-	bus.mpc_busid = 0;
+-	switch (mpc_default_type) {
+-		default:
+-			printk("???\n");
+-			printk(KERN_ERR "Unknown standard configuration %d\n",
+-				mpc_default_type);
+-			/* fall through */
+-		case 1:
+-		case 5:
+-			memcpy(bus.mpc_bustype, "ISA   ", 6);
+-			break;
+-		case 2:
+-		case 6:
+-		case 3:
+-			memcpy(bus.mpc_bustype, "EISA  ", 6);
+-			break;
+-		case 4:
+-		case 7:
+-			memcpy(bus.mpc_bustype, "MCA   ", 6);
+-	}
+-	MP_bus_info(&bus);
+-	if (mpc_default_type > 4) {
+-		bus.mpc_busid = 1;
+-		memcpy(bus.mpc_bustype, "PCI   ", 6);
+-		MP_bus_info(&bus);
+-	}
+-
+-	ioapic.mpc_type = MP_IOAPIC;
+-	ioapic.mpc_apicid = 2;
+-	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+-	ioapic.mpc_flags = MPC_APIC_USABLE;
+-	ioapic.mpc_apicaddr = 0xFEC00000;
+-	MP_ioapic_info(&ioapic);
+-
+-	/*
+-	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
+-	 */
+-	construct_default_ioirq_mptable(mpc_default_type);
+-
+-	lintsrc.mpc_type = MP_LINTSRC;
+-	lintsrc.mpc_irqflag = 0;		/* conforming */
+-	lintsrc.mpc_srcbusid = 0;
+-	lintsrc.mpc_srcbusirq = 0;
+-	lintsrc.mpc_destapic = MP_APIC_ALL;
+-	for (i = 0; i < 2; i++) {
+-		lintsrc.mpc_irqtype = linttypes[i];
+-		lintsrc.mpc_destapiclint = i;
+-		MP_lintsrc_info(&lintsrc);
+-	}
+-}
+-
+-static struct intel_mp_floating *mpf_found;
+-
+-/*
+- * Scan the memory blocks for an SMP configuration block.
+- */
+-void __init get_smp_config (void)
+-{
+-	struct intel_mp_floating *mpf = mpf_found;
+-
+-	/*
+-	 * ACPI supports both logical (e.g. Hyper-Threading) and physical 
+-	 * processors, where MPS only supports physical.
+-	 */
+-	if (acpi_lapic && acpi_ioapic) {
+-		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
+-		return;
+-	}
+-	else if (acpi_lapic)
+-		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
+-
+-	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+-	if (mpf->mpf_feature2 & (1<<7)) {
+-		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
+-		pic_mode = 1;
+-	} else {
+-		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
+-		pic_mode = 0;
+-	}
+-
+-	/*
+-	 * Now see if we need to read further.
+-	 */
+-	if (mpf->mpf_feature1 != 0) {
+-
+-		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
+-		construct_default_ISA_mptable(mpf->mpf_feature1);
+-
+-	} else if (mpf->mpf_physptr) {
+-
+-		/*
+-		 * Read the physical hardware table.  Anything here will
+-		 * override the defaults.
+-		 */
+-		if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) {
+-			smp_found_config = 0;
+-			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
+-			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
+-			return;
+-		}
+-		/*
+-		 * If there are no explicit MP IRQ entries, then we are
+-		 * broken.  We set up most of the low 16 IO-APIC pins to
+-		 * ISA defaults and hope it will work.
+-		 */
+-		if (!mp_irq_entries) {
+-			struct mpc_config_bus bus;
+-
+-			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
+-
+-			bus.mpc_type = MP_BUS;
+-			bus.mpc_busid = 0;
+-			memcpy(bus.mpc_bustype, "ISA   ", 6);
+-			MP_bus_info(&bus);
+-
+-			construct_default_ioirq_mptable(0);
+-		}
+-
+-	} else
+-		BUG();
+-
+-	printk(KERN_INFO "Processors: %d\n", num_processors);
+-	/*
+-	 * Only use the first configuration found.
+-	 */
+-}
+-
+-static int __init smp_scan_config (unsigned long base, unsigned long length)
+-{
+-	unsigned long *bp = phys_to_virt(base);
+-	struct intel_mp_floating *mpf;
+-
+-	printk(KERN_INFO "Scan SMP from %p for %ld bytes.\n", bp,length);
+-	if (sizeof(*mpf) != 16)
+-		printk("Error: MPF size\n");
+-
+-	while (length > 0) {
+-		mpf = (struct intel_mp_floating *)bp;
+-		if ((*bp == SMP_MAGIC_IDENT) &&
+-			(mpf->mpf_length == 1) &&
+-			!mpf_checksum((unsigned char *)bp, 16) &&
+-			((mpf->mpf_specification == 1)
+-				|| (mpf->mpf_specification == 4)) ) {
+-
+-			smp_found_config = 1;
+-			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+-				mpf, virt_to_phys(mpf));
+-			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
+-					BOOTMEM_DEFAULT);
+-			if (mpf->mpf_physptr) {
+-				/*
+-				 * We cannot access to MPC table to compute
+-				 * table size yet, as only few megabytes from
+-				 * the bottom is mapped now.
+-				 * PC-9800's MPC table places on the very last
+-				 * of physical memory; so that simply reserving
+-				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
+-				 * in reserve_bootmem.
+-				 */
+-				unsigned long size = PAGE_SIZE;
+-				unsigned long end = max_low_pfn * PAGE_SIZE;
+-				if (mpf->mpf_physptr + size > end)
+-					size = end - mpf->mpf_physptr;
+-				reserve_bootmem(mpf->mpf_physptr, size,
+-						BOOTMEM_DEFAULT);
+-			}
+-
+-			mpf_found = mpf;
+-			return 1;
+-		}
+-		bp += 4;
+-		length -= 16;
+-	}
+-	return 0;
+-}
+-
+-void __init find_smp_config (void)
+-{
+-	unsigned int address;
+-
+-	/*
+-	 * FIXME: Linux assumes you have 640K of base ram..
+-	 * this continues the error...
+-	 *
+-	 * 1) Scan the bottom 1K for a signature
+-	 * 2) Scan the top 1K of base RAM
+-	 * 3) Scan the 64K of bios
+-	 */
+-	if (smp_scan_config(0x0,0x400) ||
+-		smp_scan_config(639*0x400,0x400) ||
+-			smp_scan_config(0xF0000,0x10000))
+-		return;
+-	/*
+-	 * If it is an SMP machine we should know now, unless the
+-	 * configuration is in an EISA/MCA bus machine with an
+-	 * extended bios data area.
+-	 *
+-	 * there is a real-mode segmented pointer pointing to the
+-	 * 4K EBDA area at 0x40E, calculate and scan it here.
+-	 *
+-	 * NOTE! There are Linux loaders that will corrupt the EBDA
+-	 * area, and as such this kind of SMP config may be less
+-	 * trustworthy, simply because the SMP table may have been
+-	 * stomped on during early boot. These loaders are buggy and
+-	 * should be fixed.
+-	 *
+-	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
+-	 */
+-
+-	address = get_bios_ebda();
+-	if (address)
+-		smp_scan_config(address, 0x400);
+-}
+-
+-int es7000_plat;
+-
+-/* --------------------------------------------------------------------------
+-                            ACPI-based MP Configuration
+-   -------------------------------------------------------------------------- */
+-
+-#ifdef CONFIG_ACPI
+-
+-void __init mp_register_lapic_address(u64 address)
+-{
+-	mp_lapic_addr = (unsigned long) address;
+-
+-	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+-
+-	if (boot_cpu_physical_apicid == -1U)
+-		boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+-
+-	Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
+-}
+-
+-void __cpuinit mp_register_lapic (u8 id, u8 enabled)
+-{
+-	struct mpc_config_processor processor;
+-	int boot_cpu = 0;
+-	
+-	if (MAX_APICS - id <= 0) {
+-		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
+-			id, MAX_APICS);
+-		return;
+-	}
+-
+-	if (id == boot_cpu_physical_apicid)
+-		boot_cpu = 1;
+-
+-	processor.mpc_type = MP_PROCESSOR;
+-	processor.mpc_apicid = id;
+-	processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
+-	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
+-	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
+-	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
+-		(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+-	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
+-
+-	MP_processor_info(&processor);
+-}
+-
+-#ifdef	CONFIG_X86_IO_APIC
+-
+-#define MP_ISA_BUS		0
+-#define MP_MAX_IOAPIC_PIN	127
+-
+-static struct mp_ioapic_routing {
+-	int			apic_id;
+-	int			gsi_base;
+-	int			gsi_end;
+-	u32			pin_programmed[4];
+-} mp_ioapic_routing[MAX_IO_APICS];
+-
+-static int mp_find_ioapic (int gsi)
+-{
+-	int i = 0;
+-
+-	/* Find the IOAPIC that manages this GSI. */
+-	for (i = 0; i < nr_ioapics; i++) {
+-		if ((gsi >= mp_ioapic_routing[i].gsi_base)
+-			&& (gsi <= mp_ioapic_routing[i].gsi_end))
+-			return i;
+-	}
+-
+-	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
+-
+-	return -1;
+-}
+-
+-void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
+-{
+-	int idx = 0;
+-	int tmpid;
+-
+-	if (nr_ioapics >= MAX_IO_APICS) {
+-		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+-			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
+-		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+-	}
+-	if (!address) {
+-		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+-			" found in MADT table, skipping!\n");
+-		return;
+-	}
+-
+-	idx = nr_ioapics++;
+-
+-	mp_ioapics[idx].mpc_type = MP_IOAPIC;
+-	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
+-	mp_ioapics[idx].mpc_apicaddr = address;
+-
+-	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+-	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+-		&& !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+-		tmpid = io_apic_get_unique_id(idx, id);
+-	else
+-		tmpid = id;
+-	if (tmpid == -1) {
+-		nr_ioapics--;
+-		return;
+-	}
+-	mp_ioapics[idx].mpc_apicid = tmpid;
+-	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
+-	
+-	/* 
+-	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
+-	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
+-	 */
+-	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
+-	mp_ioapic_routing[idx].gsi_base = gsi_base;
+-	mp_ioapic_routing[idx].gsi_end = gsi_base +
+-		io_apic_get_redir_entries(idx);
+-
+-	printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+-	       "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
+-	       mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
+-	       mp_ioapic_routing[idx].gsi_base,
+-	       mp_ioapic_routing[idx].gsi_end);
+-}
+-
+-void __init
+-mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int			ioapic = -1;
+-	int			pin = -1;
+-
+-	/* 
+-	 * Convert 'gsi' to 'ioapic.pin'.
+-	 */
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0)
+-		return;
+-	pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
+-
+-	/*
+-	 * TBD: This check is for faulty timer entries, where the override
+-	 *      erroneously sets the trigger to level, resulting in a HUGE 
+-	 *      increase of timer interrupts!
+-	 */
+-	if ((bus_irq == 0) && (trigger == 3))
+-		trigger = 1;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqtype = mp_INT;
+-	intsrc.mpc_irqflag = (trigger << 2) | polarity;
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-	intsrc.mpc_srcbusirq = bus_irq;				       /* IRQ */
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	   /* APIC ID */
+-	intsrc.mpc_dstirq = pin;				    /* INTIN# */
+-
+-	Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n",
+-		intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
+-		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
+-		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
+-
+-	mp_irqs[mp_irq_entries] = intsrc;
+-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-		panic("Max # of irq sources exceeded!\n");
+-}
+-
+-void __init mp_config_acpi_legacy_irqs (void)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int i = 0;
+-	int ioapic = -1;
+-
+-	/* 
+-	 * Fabricate the legacy ISA bus (bus #31).
+-	 */
+-	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
+-	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+-
+-	/*
+-	 * Older generations of ES7000 have no legacy identity mappings
+-	 */
+-	if (es7000_plat == 1)
+-		return;
+-
+-	/* 
+-	 * Locate the IOAPIC that manages the ISA IRQs (0-15). 
+-	 */
+-	ioapic = mp_find_ioapic(0);
+-	if (ioapic < 0)
+-		return;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;					/* Conforming */
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
+-
+-	/* 
+-	 * Use the default configuration for the IRQs 0-15.  Unless
+-	 * overridden by (MADT) interrupt source override entries.
+-	 */
+-	for (i = 0; i < 16; i++) {
+-		int idx;
+-
+-		for (idx = 0; idx < mp_irq_entries; idx++) {
+-			struct mpc_config_intsrc *irq = mp_irqs + idx;
+-
+-			/* Do we already have a mapping for this ISA IRQ? */
+-			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+-				break;
+-
+-			/* Do we already have a mapping for this IOAPIC pin */
+-			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+-				(irq->mpc_dstirq == i))
+-				break;
+-		}
+-
+-		if (idx != mp_irq_entries) {
+-			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+-			continue;			/* IRQ already used */
+-		}
+-
+-		intsrc.mpc_irqtype = mp_INT;
+-		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
+-		intsrc.mpc_dstirq = i;
+-
+-		Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
+-			"%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
+-			(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
+-			intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, 
+-			intsrc.mpc_dstirq);
+-
+-		mp_irqs[mp_irq_entries] = intsrc;
+-		if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-			panic("Max # of irq sources exceeded!\n");
+-	}
+-}
+-
+-#define MAX_GSI_NUM	4096
+-#define IRQ_COMPRESSION_START	64
+-
+-int mp_register_gsi(u32 gsi, int triggering, int polarity)
+-{
+-	int ioapic = -1;
+-	int ioapic_pin = 0;
+-	int idx, bit = 0;
+-	static int pci_irq = IRQ_COMPRESSION_START;
+-	/*
+-	 * Mapping between Global System Interrupts, which
+-	 * represent all possible interrupts, and IRQs
+-	 * assigned to actual devices.
+-	 */
+-	static int		gsi_to_irq[MAX_GSI_NUM];
+-
+-	/* Don't set up the ACPI SCI because it's already set up */
+-	if (acpi_gbl_FADT.sci_interrupt == gsi)
+-		return gsi;
+-
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0) {
+-		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+-		return gsi;
+-	}
+-
+-	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
+-
+-	if (ioapic_renumber_irq)
+-		gsi = ioapic_renumber_irq(ioapic, gsi);
+-
+-	/* 
+-	 * Avoid pin reprogramming.  PRTs typically include entries  
+-	 * with redundant pin->gsi mappings (but unique PCI devices);
+-	 * we only program the IOAPIC on the first.
+-	 */
+-	bit = ioapic_pin % 32;
+-	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+-	if (idx > 3) {
+-		printk(KERN_ERR "Invalid reference to IOAPIC pin "
+-			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
+-			ioapic_pin);
+-		return gsi;
+-	}
+-	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+-		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+-		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
+-	}
+-
+-	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+-
+-	/*
+-	 * For GSI >= 64, use IRQ compression
+-	 */
+-	if ((gsi >= IRQ_COMPRESSION_START)
+-		&& (triggering == ACPI_LEVEL_SENSITIVE)) {
+-		/*
+-		 * For PCI devices assign IRQs in order, avoiding gaps
+-		 * due to unused I/O APIC pins.
+-		 */
+-		int irq = gsi;
+-		if (gsi < MAX_GSI_NUM) {
+-			/*
+-			 * Retain the VIA chipset work-around (gsi > 15), but
+-			 * avoid a problem where the 8254 timer (IRQ0) is setup
+-			 * via an override (so it's not on pin 0 of the ioapic),
+-			 * and at the same time, the pin 0 interrupt is a PCI
+-			 * type.  The gsi > 15 test could cause these two pins
+-			 * to be shared as IRQ0, and they are not shareable.
+-			 * So test for this condition, and if necessary, avoid
+-			 * the pin collision.
+-			 */
+-			if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
+-				gsi = pci_irq++;
+-			/*
+-			 * Don't assign IRQ used by ACPI SCI
+-			 */
+-			if (gsi == acpi_gbl_FADT.sci_interrupt)
+-				gsi = pci_irq++;
+-			gsi_to_irq[irq] = gsi;
+-		} else {
+-			printk(KERN_ERR "GSI %u is too high\n", gsi);
+-			return gsi;
+-		}
+-	}
+-
+-	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+-		    triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+-		    polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+-	return gsi;
+-}
+-
+-#endif /* CONFIG_X86_IO_APIC */
+-#endif /* CONFIG_ACPI */
+diff --git a/arch/x86/kernel/mpparse_64.c b/arch/x86/kernel/mpparse_64.c
+deleted file mode 100644
+index 72ab140..0000000
+--- a/arch/x86/kernel/mpparse_64.c
++++ /dev/null
+@@ -1,867 +0,0 @@
+-/*
+- *	Intel Multiprocessor Specification 1.1 and 1.4
+- *	compliant MP-table parsing routines.
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- *	(c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
+- *
+- *	Fixes
+- *		Erich Boleyn	:	MP v1.4 and additional changes.
+- *		Alan Cox	:	Added EBDA scanning
+- *		Ingo Molnar	:	various cleanups and rewrites
+- *		Maciej W. Rozycki:	Bits for default MP configurations
+- *		Paul Diefenbaugh:	Added full ACPI support
+- */
+-
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/acpi.h>
+-#include <linux/module.h>
+-
+-#include <asm/smp.h>
+-#include <asm/mtrr.h>
+-#include <asm/mpspec.h>
+-#include <asm/pgalloc.h>
+-#include <asm/io_apic.h>
+-#include <asm/proto.h>
+-#include <asm/acpi.h>
+-
+-/* Have we found an MP table */
+-int smp_found_config;
+-
+-/*
+- * Various Linux-internal data structures created from the
+- * MP-table.
+- */
+-DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+-
+-static int mp_current_pci_id = 0;
+-/* I/O APIC entries */
+-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+-
+-/* # of MP IRQ source entries */
+-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+-
+-/* MP IRQ source entries */
+-int mp_irq_entries;
+-
+-int nr_ioapics;
+-unsigned long mp_lapic_addr = 0;
+-
+-
+-
+-/* Processor that is doing the boot up */
+-unsigned int boot_cpu_id = -1U;
+-EXPORT_SYMBOL(boot_cpu_id);
+-
+-/* Internal processor count */
+-unsigned int num_processors;
+-
+-unsigned disabled_cpus __cpuinitdata;
+-
+-/* Bitmask of physically existing CPUs */
+-physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
+-
+-u16 x86_bios_cpu_apicid_init[NR_CPUS] __initdata
+-				= { [0 ... NR_CPUS-1] = BAD_APICID };
+-void *x86_bios_cpu_apicid_early_ptr;
+-DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
+-EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
+-
+-
+-/*
+- * Intel MP BIOS table parsing routines:
+- */
+-
+-/*
+- * Checksum an MP configuration block.
+- */
+-
+-static int __init mpf_checksum(unsigned char *mp, int len)
+-{
+-	int sum = 0;
+-
+-	while (len--)
+-		sum += *mp++;
+-
+-	return sum & 0xFF;
+-}
+-
+-static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
+-{
+-	int cpu;
+-	cpumask_t tmp_map;
+-	char *bootup_cpu = "";
+-
+-	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
+-		disabled_cpus++;
+-		return;
+-	}
+-	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+-		bootup_cpu = " (Bootup-CPU)";
+-		boot_cpu_id = m->mpc_apicid;
+-	}
+-
+-	printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
+-
+-	if (num_processors >= NR_CPUS) {
+-		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+-			" Processor ignored.\n", NR_CPUS);
+-		return;
+-	}
+-
+-	num_processors++;
+-	cpus_complement(tmp_map, cpu_present_map);
+-	cpu = first_cpu(tmp_map);
+-
+-	physid_set(m->mpc_apicid, phys_cpu_present_map);
+- 	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+- 		/*
+-		 * x86_bios_cpu_apicid is required to have processors listed
+- 		 * in same order as logical cpu numbers. Hence the first
+- 		 * entry is BSP, and so on.
+- 		 */
+-		cpu = 0;
+- 	}
+-	/* are we being called early in kernel startup? */
+-	if (x86_cpu_to_apicid_early_ptr) {
+-		u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
+-		u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
+-
+-		cpu_to_apicid[cpu] = m->mpc_apicid;
+-		bios_cpu_apicid[cpu] = m->mpc_apicid;
+-	} else {
+-		per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid;
+-		per_cpu(x86_bios_cpu_apicid, cpu) = m->mpc_apicid;
+-	}
+-
+-	cpu_set(cpu, cpu_possible_map);
+-	cpu_set(cpu, cpu_present_map);
+-}
+-
+-static void __init MP_bus_info (struct mpc_config_bus *m)
+-{
+-	char str[7];
+-
+-	memcpy(str, m->mpc_bustype, 6);
+-	str[6] = 0;
+-	Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
+-
+-	if (strncmp(str, "ISA", 3) == 0) {
+-		set_bit(m->mpc_busid, mp_bus_not_pci);
+-	} else if (strncmp(str, "PCI", 3) == 0) {
+-		clear_bit(m->mpc_busid, mp_bus_not_pci);
+-		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
+-		mp_current_pci_id++;
+-	} else {
+-		printk(KERN_ERR "Unknown bustype %s\n", str);
+-	}
+-}
+-
+-static int bad_ioapic(unsigned long address)
+-{
+-	if (nr_ioapics >= MAX_IO_APICS) {
+-		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+-			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
+-		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+-	}
+-	if (!address) {
+-		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+-			" found in table, skipping!\n");
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
+-{
+-	if (!(m->mpc_flags & MPC_APIC_USABLE))
+-		return;
+-
+-	printk("I/O APIC #%d at 0x%X.\n",
+-		m->mpc_apicid, m->mpc_apicaddr);
+-
+-	if (bad_ioapic(m->mpc_apicaddr))
+-		return;
+-
+-	mp_ioapics[nr_ioapics] = *m;
+-	nr_ioapics++;
+-}
+-
+-static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
+-{
+-	mp_irqs [mp_irq_entries] = *m;
+-	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
+-		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+-			m->mpc_irqtype, m->mpc_irqflag & 3,
+-			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
+-			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
+-	if (++mp_irq_entries >= MAX_IRQ_SOURCES)
+-		panic("Max # of irq sources exceeded!!\n");
+-}
+-
+-static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
+-{
+-	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
+-		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+-			m->mpc_irqtype, m->mpc_irqflag & 3,
+-			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
+-			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+-}
+-
+-/*
+- * Read/parse the MPC
+- */
+-
+-static int __init smp_read_mpc(struct mp_config_table *mpc)
+-{
+-	char str[16];
+-	int count=sizeof(*mpc);
+-	unsigned char *mpt=((unsigned char *)mpc)+count;
+-
+-	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
+-		printk("MPTABLE: bad signature [%c%c%c%c]!\n",
+-			mpc->mpc_signature[0],
+-			mpc->mpc_signature[1],
+-			mpc->mpc_signature[2],
+-			mpc->mpc_signature[3]);
+-		return 0;
+-	}
+-	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
+-		printk("MPTABLE: checksum error!\n");
+-		return 0;
+-	}
+-	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
+-		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
+-			mpc->mpc_spec);
+-		return 0;
+-	}
+-	if (!mpc->mpc_lapic) {
+-		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+-		return 0;
+-	}
+-	memcpy(str,mpc->mpc_oem,8);
+-	str[8] = 0;
+-	printk(KERN_INFO "MPTABLE: OEM ID: %s ",str);
+-
+-	memcpy(str,mpc->mpc_productid,12);
+-	str[12] = 0;
+-	printk("MPTABLE: Product ID: %s ",str);
+-
+-	printk("MPTABLE: APIC at: 0x%X\n",mpc->mpc_lapic);
+-
+-	/* save the local APIC address, it might be non-default */
+-	if (!acpi_lapic)
+-		mp_lapic_addr = mpc->mpc_lapic;
+-
+-	/*
+-	 *	Now process the configuration blocks.
+-	 */
+-	while (count < mpc->mpc_length) {
+-		switch(*mpt) {
+-			case MP_PROCESSOR:
+-			{
+-				struct mpc_config_processor *m=
+-					(struct mpc_config_processor *)mpt;
+-				if (!acpi_lapic)
+-					MP_processor_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_BUS:
+-			{
+-				struct mpc_config_bus *m=
+-					(struct mpc_config_bus *)mpt;
+-				MP_bus_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_IOAPIC:
+-			{
+-				struct mpc_config_ioapic *m=
+-					(struct mpc_config_ioapic *)mpt;
+-				MP_ioapic_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_INTSRC:
+-			{
+-				struct mpc_config_intsrc *m=
+-					(struct mpc_config_intsrc *)mpt;
+-
+-				MP_intsrc_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_LINTSRC:
+-			{
+-				struct mpc_config_lintsrc *m=
+-					(struct mpc_config_lintsrc *)mpt;
+-				MP_lintsrc_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-		}
+-	}
+-	setup_apic_routing();
+-	if (!num_processors)
+-		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+-	return num_processors;
+-}
+-
+-static int __init ELCR_trigger(unsigned int irq)
+-{
+-	unsigned int port;
+-
+-	port = 0x4d0 + (irq >> 3);
+-	return (inb(port) >> (irq & 7)) & 1;
+-}
+-
+-static void __init construct_default_ioirq_mptable(int mpc_default_type)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int i;
+-	int ELCR_fallback = 0;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;			/* conforming */
+-	intsrc.mpc_srcbus = 0;
+-	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
+-
+-	intsrc.mpc_irqtype = mp_INT;
+-
+-	/*
+-	 *  If true, we have an ISA/PCI system with no IRQ entries
+-	 *  in the MP table. To prevent the PCI interrupts from being set up
+-	 *  incorrectly, we try to use the ELCR. The sanity check to see if
+-	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
+-	 *  never be level sensitive, so we simply see if the ELCR agrees.
+-	 *  If it does, we assume it's valid.
+-	 */
+-	if (mpc_default_type == 5) {
+-		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
+-
+-		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
+-			printk(KERN_ERR "ELCR contains invalid data... not using ELCR\n");
+-		else {
+-			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
+-			ELCR_fallback = 1;
+-		}
+-	}
+-
+-	for (i = 0; i < 16; i++) {
+-		switch (mpc_default_type) {
+-		case 2:
+-			if (i == 0 || i == 13)
+-				continue;	/* IRQ0 & IRQ13 not connected */
+-			/* fall through */
+-		default:
+-			if (i == 2)
+-				continue;	/* IRQ2 is never connected */
+-		}
+-
+-		if (ELCR_fallback) {
+-			/*
+-			 *  If the ELCR indicates a level-sensitive interrupt, we
+-			 *  copy that information over to the MP table in the
+-			 *  irqflag field (level sensitive, active high polarity).
+-			 */
+-			if (ELCR_trigger(i))
+-				intsrc.mpc_irqflag = 13;
+-			else
+-				intsrc.mpc_irqflag = 0;
+-		}
+-
+-		intsrc.mpc_srcbusirq = i;
+-		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
+-		MP_intsrc_info(&intsrc);
+-	}
+-
+-	intsrc.mpc_irqtype = mp_ExtINT;
+-	intsrc.mpc_srcbusirq = 0;
+-	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
+-	MP_intsrc_info(&intsrc);
+-}
+-
+-static inline void __init construct_default_ISA_mptable(int mpc_default_type)
+-{
+-	struct mpc_config_processor processor;
+-	struct mpc_config_bus bus;
+-	struct mpc_config_ioapic ioapic;
+-	struct mpc_config_lintsrc lintsrc;
+-	int linttypes[2] = { mp_ExtINT, mp_NMI };
+-	int i;
+-
+-	/*
+-	 * local APIC has default address
+-	 */
+-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+-
+-	/*
+-	 * 2 CPUs, numbered 0 & 1.
+-	 */
+-	processor.mpc_type = MP_PROCESSOR;
+-	processor.mpc_apicver = 0;
+-	processor.mpc_cpuflag = CPU_ENABLED;
+-	processor.mpc_cpufeature = 0;
+-	processor.mpc_featureflag = 0;
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
+-	for (i = 0; i < 2; i++) {
+-		processor.mpc_apicid = i;
+-		MP_processor_info(&processor);
+-	}
+-
+-	bus.mpc_type = MP_BUS;
+-	bus.mpc_busid = 0;
+-	switch (mpc_default_type) {
+-		default:
+-			printk(KERN_ERR "???\nUnknown standard configuration %d\n",
+-				mpc_default_type);
+-			/* fall through */
+-		case 1:
+-		case 5:
+-			memcpy(bus.mpc_bustype, "ISA   ", 6);
+-			break;
+-	}
+-	MP_bus_info(&bus);
+-	if (mpc_default_type > 4) {
+-		bus.mpc_busid = 1;
+-		memcpy(bus.mpc_bustype, "PCI   ", 6);
+-		MP_bus_info(&bus);
+-	}
+-
+-	ioapic.mpc_type = MP_IOAPIC;
+-	ioapic.mpc_apicid = 2;
+-	ioapic.mpc_apicver = 0;
+-	ioapic.mpc_flags = MPC_APIC_USABLE;
+-	ioapic.mpc_apicaddr = 0xFEC00000;
+-	MP_ioapic_info(&ioapic);
+-
+-	/*
+-	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
+-	 */
+-	construct_default_ioirq_mptable(mpc_default_type);
+-
+-	lintsrc.mpc_type = MP_LINTSRC;
+-	lintsrc.mpc_irqflag = 0;		/* conforming */
+-	lintsrc.mpc_srcbusid = 0;
+-	lintsrc.mpc_srcbusirq = 0;
+-	lintsrc.mpc_destapic = MP_APIC_ALL;
+-	for (i = 0; i < 2; i++) {
+-		lintsrc.mpc_irqtype = linttypes[i];
+-		lintsrc.mpc_destapiclint = i;
+-		MP_lintsrc_info(&lintsrc);
+-	}
+-}
+-
+-static struct intel_mp_floating *mpf_found;
+-
+-/*
+- * Scan the memory blocks for an SMP configuration block.
+- */
+-void __init get_smp_config (void)
+-{
+-	struct intel_mp_floating *mpf = mpf_found;
+-
+-	/*
+- 	 * ACPI supports both logical (e.g. Hyper-Threading) and physical 
+- 	 * processors, where MPS only supports physical.
+- 	 */
+- 	if (acpi_lapic && acpi_ioapic) {
+- 		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
+- 		return;
+-	}
+- 	else if (acpi_lapic)
+- 		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
+-
+-	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+-
+-	/*
+-	 * Now see if we need to read further.
+-	 */
+-	if (mpf->mpf_feature1 != 0) {
+-
+-		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
+-		construct_default_ISA_mptable(mpf->mpf_feature1);
+-
+-	} else if (mpf->mpf_physptr) {
+-
+-		/*
+-		 * Read the physical hardware table.  Anything here will
+-		 * override the defaults.
+-		 */
+-		if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) {
+-			smp_found_config = 0;
+-			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
+-			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
+-			return;
+-		}
+-		/*
+-		 * If there are no explicit MP IRQ entries, then we are
+-		 * broken.  We set up most of the low 16 IO-APIC pins to
+-		 * ISA defaults and hope it will work.
+-		 */
+-		if (!mp_irq_entries) {
+-			struct mpc_config_bus bus;
+-
+-			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
+-
+-			bus.mpc_type = MP_BUS;
+-			bus.mpc_busid = 0;
+-			memcpy(bus.mpc_bustype, "ISA   ", 6);
+-			MP_bus_info(&bus);
+-
+-			construct_default_ioirq_mptable(0);
+-		}
+-
+-	} else
+-		BUG();
+-
+-	printk(KERN_INFO "Processors: %d\n", num_processors);
+-	/*
+-	 * Only use the first configuration found.
+-	 */
+-}
+-
+-static int __init smp_scan_config (unsigned long base, unsigned long length)
+-{
+-	extern void __bad_mpf_size(void); 
+-	unsigned int *bp = phys_to_virt(base);
+-	struct intel_mp_floating *mpf;
+-
+-	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
+-	if (sizeof(*mpf) != 16)
+-		__bad_mpf_size();
+-
+-	while (length > 0) {
+-		mpf = (struct intel_mp_floating *)bp;
+-		if ((*bp == SMP_MAGIC_IDENT) &&
+-			(mpf->mpf_length == 1) &&
+-			!mpf_checksum((unsigned char *)bp, 16) &&
+-			((mpf->mpf_specification == 1)
+-				|| (mpf->mpf_specification == 4)) ) {
+-
+-			smp_found_config = 1;
+-			reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE);
+-			if (mpf->mpf_physptr)
+-				reserve_bootmem_generic(mpf->mpf_physptr, PAGE_SIZE);
+-			mpf_found = mpf;
+-			return 1;
+-		}
+-		bp += 4;
+-		length -= 16;
+-	}
+-	return 0;
+-}
+-
+-void __init find_smp_config(void)
+-{
+-	unsigned int address;
+-
+-	/*
+-	 * FIXME: Linux assumes you have 640K of base ram..
+-	 * this continues the error...
+-	 *
+-	 * 1) Scan the bottom 1K for a signature
+-	 * 2) Scan the top 1K of base RAM
+-	 * 3) Scan the 64K of bios
+-	 */
+-	if (smp_scan_config(0x0,0x400) ||
+-		smp_scan_config(639*0x400,0x400) ||
+-			smp_scan_config(0xF0000,0x10000))
+-		return;
+-	/*
+-	 * If it is an SMP machine we should know now.
+-	 *
+-	 * there is a real-mode segmented pointer pointing to the
+-	 * 4K EBDA area at 0x40E, calculate and scan it here.
+-	 *
+-	 * NOTE! There are Linux loaders that will corrupt the EBDA
+-	 * area, and as such this kind of SMP config may be less
+-	 * trustworthy, simply because the SMP table may have been
+-	 * stomped on during early boot. These loaders are buggy and
+-	 * should be fixed.
+-	 */
+-
+-	address = *(unsigned short *)phys_to_virt(0x40E);
+-	address <<= 4;
+-	if (smp_scan_config(address, 0x1000))
+-		return;
+-
+-	/* If we have come this far, we did not find an MP table  */
+-	 printk(KERN_INFO "No mptable found.\n");
+-}
+-
+-/* --------------------------------------------------------------------------
+-                            ACPI-based MP Configuration
+-   -------------------------------------------------------------------------- */
+-
+-#ifdef CONFIG_ACPI
+-
+-void __init mp_register_lapic_address(u64 address)
+-{
+-	mp_lapic_addr = (unsigned long) address;
+-	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+-	if (boot_cpu_id == -1U)
+-		boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+-}
+-
+-void __cpuinit mp_register_lapic (u8 id, u8 enabled)
+-{
+-	struct mpc_config_processor processor;
+-	int			boot_cpu = 0;
+-	
+-	if (id == boot_cpu_id)
+-		boot_cpu = 1;
+-
+-	processor.mpc_type = MP_PROCESSOR;
+-	processor.mpc_apicid = id;
+-	processor.mpc_apicver = 0;
+-	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
+-	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
+-	processor.mpc_cpufeature = 0;
+-	processor.mpc_featureflag = 0;
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
+-
+-	MP_processor_info(&processor);
+-}
+-
+-#define MP_ISA_BUS		0
+-#define MP_MAX_IOAPIC_PIN	127
+-
+-static struct mp_ioapic_routing {
+-	int			apic_id;
+-	int			gsi_start;
+-	int			gsi_end;
+-	u32			pin_programmed[4];
+-} mp_ioapic_routing[MAX_IO_APICS];
+-
+-static int mp_find_ioapic(int gsi)
+-{
+-	int i = 0;
+-
+-	/* Find the IOAPIC that manages this GSI. */
+-	for (i = 0; i < nr_ioapics; i++) {
+-		if ((gsi >= mp_ioapic_routing[i].gsi_start)
+-			&& (gsi <= mp_ioapic_routing[i].gsi_end))
+-			return i;
+-	}
+-
+-	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
+-	return -1;
+-}
+-
+-static u8 uniq_ioapic_id(u8 id)
+-{
+-	int i;
+-	DECLARE_BITMAP(used, 256);
+-	bitmap_zero(used, 256);
+-	for (i = 0; i < nr_ioapics; i++) {
+-		struct mpc_config_ioapic *ia = &mp_ioapics[i];
+-		__set_bit(ia->mpc_apicid, used);
+-	}
+-	if (!test_bit(id, used))
+-		return id;
+-	return find_first_zero_bit(used, 256);
+-}
+-
+-void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
+-{
+-	int idx = 0;
+-
+-	if (bad_ioapic(address))
+-		return;
+-
+-	idx = nr_ioapics;
+-
+-	mp_ioapics[idx].mpc_type = MP_IOAPIC;
+-	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
+-	mp_ioapics[idx].mpc_apicaddr = address;
+-
+-	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+-	mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
+-	mp_ioapics[idx].mpc_apicver = 0;
+-	
+-	/* 
+-	 * Build basic IRQ lookup table to facilitate gsi->io_apic lookups
+-	 * and to prevent reprogramming of IOAPIC pins (PCI IRQs).
+-	 */
+-	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
+-	mp_ioapic_routing[idx].gsi_start = gsi_base;
+-	mp_ioapic_routing[idx].gsi_end = gsi_base + 
+-		io_apic_get_redir_entries(idx);
+-
+-	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, address 0x%x, "
+-		"GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
+-		mp_ioapics[idx].mpc_apicaddr,
+-		mp_ioapic_routing[idx].gsi_start,
+-		mp_ioapic_routing[idx].gsi_end);
+-
+-	nr_ioapics++;
+-}
+-
+-void __init
+-mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32	gsi)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int			ioapic = -1;
+-	int			pin = -1;
+-
+-	/* 
+-	 * Convert 'gsi' to 'ioapic.pin'.
+-	 */
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0)
+-		return;
+-	pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
+-
+-	/*
+-	 * TBD: This check is for faulty timer entries, where the override
+-	 *      erroneously sets the trigger to level, resulting in a HUGE 
+-	 *      increase of timer interrupts!
+-	 */
+-	if ((bus_irq == 0) && (trigger == 3))
+-		trigger = 1;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqtype = mp_INT;
+-	intsrc.mpc_irqflag = (trigger << 2) | polarity;
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-	intsrc.mpc_srcbusirq = bus_irq;				       /* IRQ */
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	   /* APIC ID */
+-	intsrc.mpc_dstirq = pin;				    /* INTIN# */
+-
+-	Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n", 
+-		intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
+-		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
+-		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
+-
+-	mp_irqs[mp_irq_entries] = intsrc;
+-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-		panic("Max # of irq sources exceeded!\n");
+-}
+-
+-void __init mp_config_acpi_legacy_irqs(void)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int i = 0;
+-	int ioapic = -1;
+-
+-	/* 
+-	 * Fabricate the legacy ISA bus (bus #31).
+-	 */
+-	set_bit(MP_ISA_BUS, mp_bus_not_pci);
+-
+-	/* 
+-	 * Locate the IOAPIC that manages the ISA IRQs (0-15). 
+-	 */
+-	ioapic = mp_find_ioapic(0);
+-	if (ioapic < 0)
+-		return;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;					/* Conforming */
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
+-
+-	/* 
+-	 * Use the default configuration for the IRQs 0-15.  Unless
+-	 * overridden by (MADT) interrupt source override entries.
+-	 */
+-	for (i = 0; i < 16; i++) {
+-		int idx;
+-
+-		for (idx = 0; idx < mp_irq_entries; idx++) {
+-			struct mpc_config_intsrc *irq = mp_irqs + idx;
+-
+-			/* Do we already have a mapping for this ISA IRQ? */
+-			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+-				break;
+-
+-			/* Do we already have a mapping for this IOAPIC pin */
+-			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+-				(irq->mpc_dstirq == i))
+-				break;
+-		}
+-
+-		if (idx != mp_irq_entries) {
+-			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+-			continue;			/* IRQ already used */
+-		}
+-
+-		intsrc.mpc_irqtype = mp_INT;
+-		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
+-		intsrc.mpc_dstirq = i;
+-
+-		Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
+-			"%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
+-			(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
+-			intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, 
+-			intsrc.mpc_dstirq);
+-
+-		mp_irqs[mp_irq_entries] = intsrc;
+-		if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-			panic("Max # of irq sources exceeded!\n");
+-	}
+-}
+-
+-int mp_register_gsi(u32 gsi, int triggering, int polarity)
+-{
+-	int ioapic = -1;
+-	int ioapic_pin = 0;
+-	int idx, bit = 0;
+-
+-	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+-		return gsi;
+-
+-	/* Don't set up the ACPI SCI because it's already set up */
+-	if (acpi_gbl_FADT.sci_interrupt == gsi)
+-		return gsi;
+-
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0) {
+-		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+-		return gsi;
+-	}
+-
+-	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
+-
+-	/* 
+-	 * Avoid pin reprogramming.  PRTs typically include entries  
+-	 * with redundant pin->gsi mappings (but unique PCI devices);
+-	 * we only program the IOAPIC on the first.
+-	 */
+-	bit = ioapic_pin % 32;
+-	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+-	if (idx > 3) {
+-		printk(KERN_ERR "Invalid reference to IOAPIC pin "
+-			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
+-			ioapic_pin);
+-		return gsi;
+-	}
+-	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+-		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+-		return gsi;
+-	}
+-
+-	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+-
+-	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+-		triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+-		polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+-	return gsi;
+-}
+-#endif /*CONFIG_ACPI*/
+diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
+index af51ea8..1f3abe0 100644
+--- a/arch/x86/kernel/msr.c
++++ b/arch/x86/kernel/msr.c
+@@ -65,8 +65,8 @@ static loff_t msr_seek(struct file *file, loff_t offset, int orig)
+ 	return ret;
+ }
+ 
+-static ssize_t msr_read(struct file *file, char __user * buf,
+-			size_t count, loff_t * ppos)
++static ssize_t msr_read(struct file *file, char __user *buf,
++			size_t count, loff_t *ppos)
+ {
+ 	u32 __user *tmp = (u32 __user *) buf;
+ 	u32 data[2];
+@@ -162,12 +162,10 @@ static int __cpuinit msr_class_cpu_callback(struct notifier_block *nfb,
+ 		err = msr_device_create(cpu);
+ 		break;
+ 	case CPU_UP_CANCELED:
++	case CPU_UP_CANCELED_FROZEN:
+ 	case CPU_DEAD:
+ 		msr_device_destroy(cpu);
+ 		break;
+-	case CPU_UP_CANCELED_FROZEN:
+-		destroy_suspended_device(msr_class, MKDEV(MSR_MAJOR, cpu));
+-		break;
+ 	}
+ 	return err ? NOTIFY_BAD : NOTIFY_OK;
+ }
+diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c
+index 6a0aa70..11b14bb 100644
+--- a/arch/x86/kernel/nmi_32.c
++++ b/arch/x86/kernel/nmi_32.c
+@@ -22,9 +22,11 @@
+ #include <linux/cpumask.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/kdebug.h>
++#include <linux/slab.h>
+ 
+ #include <asm/smp.h>
+ #include <asm/nmi.h>
++#include <asm/timer.h>
+ 
+ #include "mach_traps.h"
+ 
+@@ -67,7 +69,7 @@ static __init void nmi_cpu_busy(void *data)
+ }
+ #endif
+ 
+-static int __init check_nmi_watchdog(void)
++int __init check_nmi_watchdog(void)
+ {
+ 	unsigned int *prev_nmi_count;
+ 	int cpu;
+@@ -80,7 +82,7 @@ static int __init check_nmi_watchdog(void)
+ 
+ 	prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
+ 	if (!prev_nmi_count)
+-		return -1;
++		goto error;
+ 
+ 	printk(KERN_INFO "Testing NMI watchdog ... ");
+ 
+@@ -117,7 +119,7 @@ static int __init check_nmi_watchdog(void)
+ 	if (!atomic_read(&nmi_active)) {
+ 		kfree(prev_nmi_count);
+ 		atomic_set(&nmi_active, -1);
+-		return -1;
++		goto error;
+ 	}
+ 	printk("OK.\n");
+ 
+@@ -128,9 +130,11 @@ static int __init check_nmi_watchdog(void)
+ 
+ 	kfree(prev_nmi_count);
+ 	return 0;
++error:
++	timer_ack = !cpu_has_tsc;
++
++	return -1;
+ }
+-/* This needs to happen later in boot so counters are working */
+-late_initcall(check_nmi_watchdog);
+ 
+ static int __init setup_nmi_watchdog(char *str)
+ {
+@@ -317,7 +321,8 @@ EXPORT_SYMBOL(touch_nmi_watchdog);
+ 
+ extern void die_nmi(struct pt_regs *, const char *msg);
+ 
+-__kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
++notrace __kprobes int
++nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
+ {
+ 
+ 	/*
+diff --git a/arch/x86/kernel/nmi_64.c b/arch/x86/kernel/nmi_64.c
+index 9a4fde7..5a29ded 100644
+--- a/arch/x86/kernel/nmi_64.c
++++ b/arch/x86/kernel/nmi_64.c
+@@ -26,6 +26,8 @@
+ #include <asm/proto.h>
+ #include <asm/mce.h>
+ 
++#include <mach_traps.h>
++
+ int unknown_nmi_panic;
+ int nmi_watchdog_enabled;
+ int panic_on_unrecovered_nmi;
+@@ -311,7 +313,8 @@ void touch_nmi_watchdog(void)
+ }
+ EXPORT_SYMBOL(touch_nmi_watchdog);
+ 
+-int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
++notrace __kprobes int
++nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
+ {
+ 	int sum;
+ 	int touched = 0;
+@@ -382,7 +385,8 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
+ 
+ static unsigned ignore_nmis;
+ 
+-asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code)
++asmlinkage notrace __kprobes void
++do_nmi(struct pt_regs *regs, long error_code)
+ {
+ 	nmi_enter();
+ 	add_pda(__nmi_count,1);
+diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
+index 075962c..74f0c5e 100644
+--- a/arch/x86/kernel/paravirt.c
++++ b/arch/x86/kernel/paravirt.c
+@@ -206,13 +206,6 @@ static struct resource reserve_ioports = {
+ 	.flags = IORESOURCE_IO | IORESOURCE_BUSY,
+ };
+ 
+-static struct resource reserve_iomem = {
+-	.start = 0,
+-	.end = -1,
+-	.name = "paravirt-iomem",
+-	.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
+-};
+-
+ /*
+  * Reserve the whole legacy IO space to prevent any legacy drivers
+  * from wasting time probing for their hardware.  This is a fairly
+@@ -222,16 +215,7 @@ static struct resource reserve_iomem = {
+  */
+ int paravirt_disable_iospace(void)
+ {
+-	int ret;
+-
+-	ret = request_resource(&ioport_resource, &reserve_ioports);
+-	if (ret == 0) {
+-		ret = request_resource(&iomem_resource, &reserve_iomem);
+-		if (ret)
+-			release_resource(&reserve_ioports);
+-	}
+-
+-	return ret;
++	return request_resource(&ioport_resource, &reserve_ioports);
+ }
+ 
+ static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
+@@ -382,11 +366,13 @@ struct pv_mmu_ops pv_mmu_ops = {
+ 	.flush_tlb_single = native_flush_tlb_single,
+ 	.flush_tlb_others = native_flush_tlb_others,
+ 
+-	.alloc_pt = paravirt_nop,
+-	.alloc_pd = paravirt_nop,
+-	.alloc_pd_clone = paravirt_nop,
+-	.release_pt = paravirt_nop,
+-	.release_pd = paravirt_nop,
++	.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,
++	.release_pud = paravirt_nop,
+ 
+ 	.set_pte = native_set_pte,
+ 	.set_pte_at = native_set_pte_at,
+diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
+index 1b5464c..e28ec49 100644
+--- a/arch/x86/kernel/pci-calgary_64.c
++++ b/arch/x86/kernel/pci-calgary_64.c
+@@ -43,6 +43,7 @@
+ #include <asm/system.h>
+ #include <asm/dma.h>
+ #include <asm/rio.h>
++#include <asm/bios_ebda.h>
+ 
+ #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
+ int use_calgary __read_mostly = 1;
+@@ -470,10 +471,11 @@ error:
+ 	return 0;
+ }
+ 
+-static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
++static dma_addr_t calgary_map_single(struct device *dev, phys_addr_t paddr,
+ 	size_t size, int direction)
+ {
+ 	dma_addr_t dma_handle = bad_dma_address;
++	void *vaddr = phys_to_virt(paddr);
+ 	unsigned long uaddr;
+ 	unsigned int npages;
+ 	struct iommu_table *tbl = find_iommu_table(dev);
+@@ -1232,8 +1234,7 @@ static int __init calgary_init(void)
+ 
+ error:
+ 	do {
+-		dev = pci_get_device_reverse(PCI_VENDOR_ID_IBM,
+-					     PCI_ANY_ID, dev);
++		dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_ANY_ID, dev);
+ 		if (!dev)
+ 			break;
+ 		if (!is_cal_pci_dev(dev->device))
+diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
+new file mode 100644
+index 0000000..388b113
+--- /dev/null
++++ b/arch/x86/kernel/pci-dma.c
+@@ -0,0 +1,524 @@
++#include <linux/dma-mapping.h>
++#include <linux/dmar.h>
++#include <linux/bootmem.h>
++#include <linux/pci.h>
++
++#include <asm/proto.h>
++#include <asm/dma.h>
++#include <asm/gart.h>
++#include <asm/calgary.h>
++
++int forbid_dac __read_mostly;
++EXPORT_SYMBOL(forbid_dac);
++
++const struct dma_mapping_ops *dma_ops;
++EXPORT_SYMBOL(dma_ops);
++
++int iommu_sac_force __read_mostly = 0;
++
++#ifdef CONFIG_IOMMU_DEBUG
++int panic_on_overflow __read_mostly = 1;
++int force_iommu __read_mostly = 1;
++#else
++int panic_on_overflow __read_mostly = 0;
++int force_iommu __read_mostly = 0;
++#endif
++
++int iommu_merge __read_mostly = 0;
++
++int no_iommu __read_mostly;
++/* Set this to 1 if there is a HW IOMMU in the system */
++int iommu_detected __read_mostly = 0;
++
++/* This tells the BIO block layer to assume merging. Default to off
++   because we cannot guarantee merging later. */
++int iommu_bio_merge __read_mostly = 0;
++EXPORT_SYMBOL(iommu_bio_merge);
++
++dma_addr_t bad_dma_address __read_mostly = 0;
++EXPORT_SYMBOL(bad_dma_address);
++
++/* Dummy device used for NULL arguments (normally ISA). Better would
++   be probably a smaller DMA mask, but this is bug-to-bug compatible
++   to older i386. */
++struct device fallback_dev = {
++	.bus_id = "fallback device",
++	.coherent_dma_mask = DMA_32BIT_MASK,
++	.dma_mask = &fallback_dev.coherent_dma_mask,
++};
++
++int dma_set_mask(struct device *dev, u64 mask)
++{
++	if (!dev->dma_mask || !dma_supported(dev, mask))
++		return -EIO;
++
++	*dev->dma_mask = mask;
++
++	return 0;
++}
++EXPORT_SYMBOL(dma_set_mask);
++
++#ifdef CONFIG_X86_64
++static __initdata void *dma32_bootmem_ptr;
++static unsigned long dma32_bootmem_size __initdata = (128ULL<<20);
++
++static int __init parse_dma32_size_opt(char *p)
++{
++	if (!p)
++		return -EINVAL;
++	dma32_bootmem_size = memparse(p, &p);
++	return 0;
++}
++early_param("dma32_size", parse_dma32_size_opt);
++
++void __init dma32_reserve_bootmem(void)
++{
++	unsigned long size, align;
++	if (end_pfn <= MAX_DMA32_PFN)
++		return;
++
++	align = 64ULL<<20;
++	size = round_up(dma32_bootmem_size, align);
++	dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align,
++				 __pa(MAX_DMA_ADDRESS));
++	if (dma32_bootmem_ptr)
++		dma32_bootmem_size = size;
++	else
++		dma32_bootmem_size = 0;
++}
++static void __init dma32_free_bootmem(void)
++{
++	int node;
++
++	if (end_pfn <= MAX_DMA32_PFN)
++		return;
++
++	if (!dma32_bootmem_ptr)
++		return;
++
++	for_each_online_node(node)
++		free_bootmem_node(NODE_DATA(node), __pa(dma32_bootmem_ptr),
++				  dma32_bootmem_size);
++
++	dma32_bootmem_ptr = NULL;
++	dma32_bootmem_size = 0;
++}
++
++void __init pci_iommu_alloc(void)
++{
++	/* free the range so iommu could get some range less than 4G */
++	dma32_free_bootmem();
++	/*
++	 * The order of these functions is important for
++	 * fall-back/fail-over reasons
++	 */
++#ifdef CONFIG_GART_IOMMU
++	gart_iommu_hole_init();
++#endif
++
++#ifdef CONFIG_CALGARY_IOMMU
++	detect_calgary();
++#endif
++
++	detect_intel_iommu();
++
++#ifdef CONFIG_SWIOTLB
++	pci_swiotlb_init();
++#endif
++}
++#endif
++
++/*
++ * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
++ * documentation.
++ */
++static __init int iommu_setup(char *p)
++{
++	iommu_merge = 1;
++
++	if (!p)
++		return -EINVAL;
++
++	while (*p) {
++		if (!strncmp(p, "off", 3))
++			no_iommu = 1;
++		/* gart_parse_options has more force support */
++		if (!strncmp(p, "force", 5))
++			force_iommu = 1;
++		if (!strncmp(p, "noforce", 7)) {
++			iommu_merge = 0;
++			force_iommu = 0;
++		}
++
++		if (!strncmp(p, "biomerge", 8)) {
++			iommu_bio_merge = 4096;
++			iommu_merge = 1;
++			force_iommu = 1;
++		}
++		if (!strncmp(p, "panic", 5))
++			panic_on_overflow = 1;
++		if (!strncmp(p, "nopanic", 7))
++			panic_on_overflow = 0;
++		if (!strncmp(p, "merge", 5)) {
++			iommu_merge = 1;
++			force_iommu = 1;
++		}
++		if (!strncmp(p, "nomerge", 7))
++			iommu_merge = 0;
++		if (!strncmp(p, "forcesac", 8))
++			iommu_sac_force = 1;
++		if (!strncmp(p, "allowdac", 8))
++			forbid_dac = 0;
++		if (!strncmp(p, "nodac", 5))
++			forbid_dac = -1;
++		if (!strncmp(p, "usedac", 6)) {
++			forbid_dac = -1;
++			return 1;
++		}
++#ifdef CONFIG_SWIOTLB
++		if (!strncmp(p, "soft", 4))
++			swiotlb = 1;
++#endif
++
++#ifdef CONFIG_GART_IOMMU
++		gart_parse_options(p);
++#endif
++
++#ifdef CONFIG_CALGARY_IOMMU
++		if (!strncmp(p, "calgary", 7))
++			use_calgary = 1;
++#endif /* CONFIG_CALGARY_IOMMU */
++
++		p += strcspn(p, ",");
++		if (*p == ',')
++			++p;
++	}
++	return 0;
++}
++early_param("iommu", iommu_setup);
++
++#ifdef CONFIG_X86_32
++int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
++				dma_addr_t device_addr, size_t size, int flags)
++{
++	void __iomem *mem_base = NULL;
++	int pages = size >> PAGE_SHIFT;
++	int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
++
++	if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
++		goto out;
++	if (!size)
++		goto out;
++	if (dev->dma_mem)
++		goto out;
++
++	/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
++
++	mem_base = ioremap(bus_addr, size);
++	if (!mem_base)
++		goto out;
++
++	dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
++	if (!dev->dma_mem)
++		goto out;
++	dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
++	if (!dev->dma_mem->bitmap)
++		goto free1_out;
++
++	dev->dma_mem->virt_base = mem_base;
++	dev->dma_mem->device_base = device_addr;
++	dev->dma_mem->size = pages;
++	dev->dma_mem->flags = flags;
++
++	if (flags & DMA_MEMORY_MAP)
++		return DMA_MEMORY_MAP;
++
++	return DMA_MEMORY_IO;
++
++ free1_out:
++	kfree(dev->dma_mem);
++ out:
++	if (mem_base)
++		iounmap(mem_base);
++	return 0;
++}
++EXPORT_SYMBOL(dma_declare_coherent_memory);
++
++void dma_release_declared_memory(struct device *dev)
++{
++	struct dma_coherent_mem *mem = dev->dma_mem;
++
++	if (!mem)
++		return;
++	dev->dma_mem = NULL;
++	iounmap(mem->virt_base);
++	kfree(mem->bitmap);
++	kfree(mem);
++}
++EXPORT_SYMBOL(dma_release_declared_memory);
++
++void *dma_mark_declared_memory_occupied(struct device *dev,
++					dma_addr_t device_addr, size_t size)
++{
++	struct dma_coherent_mem *mem = dev->dma_mem;
++	int pos, err;
++	int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
++
++	pages >>= PAGE_SHIFT;
++
++	if (!mem)
++		return ERR_PTR(-EINVAL);
++
++	pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
++	err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
++	if (err != 0)
++		return ERR_PTR(err);
++	return mem->virt_base + (pos << PAGE_SHIFT);
++}
++EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
++
++static int dma_alloc_from_coherent_mem(struct device *dev, ssize_t size,
++				       dma_addr_t *dma_handle, void **ret)
++{
++	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
++	int order = get_order(size);
++
++	if (mem) {
++		int page = bitmap_find_free_region(mem->bitmap, mem->size,
++						     order);
++		if (page >= 0) {
++			*dma_handle = mem->device_base + (page << PAGE_SHIFT);
++			*ret = mem->virt_base + (page << PAGE_SHIFT);
++			memset(*ret, 0, size);
++		}
++		if (mem->flags & DMA_MEMORY_EXCLUSIVE)
++			*ret = NULL;
++	}
++	return (mem != NULL);
++}
++
++static int dma_release_coherent(struct device *dev, int order, void *vaddr)
++{
++	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
++
++	if (mem && vaddr >= mem->virt_base && vaddr <
++		   (mem->virt_base + (mem->size << PAGE_SHIFT))) {
++		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
++
++		bitmap_release_region(mem->bitmap, page, order);
++		return 1;
++	}
++	return 0;
++}
++#else
++#define dma_alloc_from_coherent_mem(dev, size, handle, ret) (0)
++#define dma_release_coherent(dev, order, vaddr) (0)
++#endif /* CONFIG_X86_32 */
++
++int dma_supported(struct device *dev, u64 mask)
++{
++#ifdef CONFIG_PCI
++	if (mask > 0xffffffff && forbid_dac > 0) {
++		printk(KERN_INFO "PCI: Disallowing DAC for device %s\n",
++				 dev->bus_id);
++		return 0;
++	}
++#endif
++
++	if (dma_ops->dma_supported)
++		return dma_ops->dma_supported(dev, mask);
++
++	/* Copied from i386. Doesn't make much sense, because it will
++	   only work for pci_alloc_coherent.
++	   The caller just has to use GFP_DMA in this case. */
++	if (mask < DMA_24BIT_MASK)
++		return 0;
++
++	/* Tell the device to use SAC when IOMMU force is on.  This
++	   allows the driver to use cheaper accesses in some cases.
++
++	   Problem with this is that if we overflow the IOMMU area and
++	   return DAC as fallback address the device may not handle it
++	   correctly.
++
++	   As a special case some controllers have a 39bit address
++	   mode that is as efficient as 32bit (aic79xx). Don't force
++	   SAC for these.  Assume all masks <= 40 bits are of this
++	   type. Normally this doesn't make any difference, but gives
++	   more gentle handling of IOMMU overflow. */
++	if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
++		printk(KERN_INFO "%s: Force SAC with mask %Lx\n",
++				 dev->bus_id, mask);
++		return 0;
++	}
++
++	return 1;
++}
++EXPORT_SYMBOL(dma_supported);
++
++/* Allocate DMA memory on node near device */
++noinline struct page *
++dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
++{
++	int node;
++
++	node = dev_to_node(dev);
++
++	return alloc_pages_node(node, gfp, order);
++}
++
++/*
++ * Allocate memory for a coherent mapping.
++ */
++void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++		   gfp_t gfp)
++{
++	void *memory = NULL;
++	struct page *page;
++	unsigned long dma_mask = 0;
++	dma_addr_t bus;
++
++	/* ignore region specifiers */
++	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
++
++	if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory))
++		return memory;
++
++	if (!dev)
++		dev = &fallback_dev;
++	dma_mask = dev->coherent_dma_mask;
++	if (dma_mask == 0)
++		dma_mask = DMA_32BIT_MASK;
++
++	/* Device not DMA able */
++	if (dev->dma_mask == NULL)
++		return NULL;
++
++	/* Don't invoke OOM killer */
++	gfp |= __GFP_NORETRY;
++
++#ifdef CONFIG_X86_64
++	/* Why <=? Even when the mask is smaller than 4GB it is often
++	   larger than 16MB and in this case we have a chance of
++	   finding fitting memory in the next higher zone first. If
++	   not retry with true GFP_DMA. -AK */
++	if (dma_mask <= DMA_32BIT_MASK)
++		gfp |= GFP_DMA32;
++#endif
++
++ again:
++	page = dma_alloc_pages(dev, gfp, get_order(size));
++	if (page == NULL)
++		return NULL;
++
++	{
++		int high, mmu;
++		bus = page_to_phys(page);
++		memory = page_address(page);
++		high = (bus + size) >= dma_mask;
++		mmu = high;
++		if (force_iommu && !(gfp & GFP_DMA))
++			mmu = 1;
++		else if (high) {
++			free_pages((unsigned long)memory,
++				   get_order(size));
++
++			/* Don't use the 16MB ZONE_DMA unless absolutely
++			   needed. It's better to use remapping first. */
++			if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
++				gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
++				goto again;
++			}
++
++			/* Let low level make its own zone decisions */
++			gfp &= ~(GFP_DMA32|GFP_DMA);
++
++			if (dma_ops->alloc_coherent)
++				return dma_ops->alloc_coherent(dev, size,
++							   dma_handle, gfp);
++			return NULL;
++		}
++
++		memset(memory, 0, size);
++		if (!mmu) {
++			*dma_handle = bus;
++			return memory;
++		}
++	}
++
++	if (dma_ops->alloc_coherent) {
++		free_pages((unsigned long)memory, get_order(size));
++		gfp &= ~(GFP_DMA|GFP_DMA32);
++		return dma_ops->alloc_coherent(dev, size, dma_handle, gfp);
++	}
++
++	if (dma_ops->map_simple) {
++		*dma_handle = dma_ops->map_simple(dev, virt_to_phys(memory),
++					      size,
++					      PCI_DMA_BIDIRECTIONAL);
++		if (*dma_handle != bad_dma_address)
++			return memory;
++	}
++
++	if (panic_on_overflow)
++		panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n",
++		      (unsigned long)size);
++	free_pages((unsigned long)memory, get_order(size));
++	return NULL;
++}
++EXPORT_SYMBOL(dma_alloc_coherent);
++
++/*
++ * Unmap coherent memory.
++ * The caller must ensure that the device has finished accessing the mapping.
++ */
++void dma_free_coherent(struct device *dev, size_t size,
++			 void *vaddr, dma_addr_t bus)
++{
++	int order = get_order(size);
++	WARN_ON(irqs_disabled());	/* for portability */
++	if (dma_release_coherent(dev, order, vaddr))
++		return;
++	if (dma_ops->unmap_single)
++		dma_ops->unmap_single(dev, bus, size, 0);
++	free_pages((unsigned long)vaddr, order);
++}
++EXPORT_SYMBOL(dma_free_coherent);
++
++static int __init pci_iommu_init(void)
++{
++#ifdef CONFIG_CALGARY_IOMMU
++	calgary_iommu_init();
++#endif
++
++	intel_iommu_init();
++
++#ifdef CONFIG_GART_IOMMU
++	gart_iommu_init();
++#endif
++
++	no_iommu_init();
++	return 0;
++}
++
++void pci_iommu_shutdown(void)
++{
++	gart_iommu_shutdown();
++}
++/* Must execute after PCI subsystem */
++fs_initcall(pci_iommu_init);
++
++#ifdef CONFIG_PCI
++/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
++
++static __devinit void via_no_dac(struct pci_dev *dev)
++{
++	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
++		printk(KERN_INFO "PCI: VIA PCI bridge detected."
++				 "Disabling DAC.\n");
++		forbid_dac = 1;
++	}
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
++#endif
+diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c
+deleted file mode 100644
+index 5133032..0000000
+--- a/arch/x86/kernel/pci-dma_32.c
++++ /dev/null
+@@ -1,177 +0,0 @@
+-/*
+- * Dynamic DMA mapping support.
+- *
+- * On i386 there is no hardware dynamic DMA address translation,
+- * so consistent alloc/free are merely page allocation/freeing.
+- * The rest of the dynamic DMA mapping interface is implemented
+- * in asm/pci.h.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/string.h>
+-#include <linux/pci.h>
+-#include <linux/module.h>
+-#include <asm/io.h>
+-
+-struct dma_coherent_mem {
+-	void		*virt_base;
+-	u32		device_base;
+-	int		size;
+-	int		flags;
+-	unsigned long	*bitmap;
+-};
+-
+-void *dma_alloc_coherent(struct device *dev, size_t size,
+-			   dma_addr_t *dma_handle, gfp_t gfp)
+-{
+-	void *ret;
+-	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+-	int order = get_order(size);
+-	/* ignore region specifiers */
+-	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+-
+-	if (mem) {
+-		int page = bitmap_find_free_region(mem->bitmap, mem->size,
+-						     order);
+-		if (page >= 0) {
+-			*dma_handle = mem->device_base + (page << PAGE_SHIFT);
+-			ret = mem->virt_base + (page << PAGE_SHIFT);
+-			memset(ret, 0, size);
+-			return ret;
+-		}
+-		if (mem->flags & DMA_MEMORY_EXCLUSIVE)
+-			return NULL;
+-	}
+-
+-	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+-		gfp |= GFP_DMA;
+-
+-	ret = (void *)__get_free_pages(gfp, order);
+-
+-	if (ret != NULL) {
+-		memset(ret, 0, size);
+-		*dma_handle = virt_to_phys(ret);
+-	}
+-	return ret;
+-}
+-EXPORT_SYMBOL(dma_alloc_coherent);
+-
+-void dma_free_coherent(struct device *dev, size_t size,
+-			 void *vaddr, dma_addr_t dma_handle)
+-{
+-	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+-	int order = get_order(size);
+-
+-	WARN_ON(irqs_disabled());	/* for portability */
+-	if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+-		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+-
+-		bitmap_release_region(mem->bitmap, page, order);
+-	} else
+-		free_pages((unsigned long)vaddr, order);
+-}
+-EXPORT_SYMBOL(dma_free_coherent);
+-
+-int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+-				dma_addr_t device_addr, size_t size, int flags)
+-{
+-	void __iomem *mem_base = NULL;
+-	int pages = size >> PAGE_SHIFT;
+-	int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+-
+-	if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
+-		goto out;
+-	if (!size)
+-		goto out;
+-	if (dev->dma_mem)
+-		goto out;
+-
+-	/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
+-
+-	mem_base = ioremap(bus_addr, size);
+-	if (!mem_base)
+-		goto out;
+-
+-	dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
+-	if (!dev->dma_mem)
+-		goto out;
+-	dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+-	if (!dev->dma_mem->bitmap)
+-		goto free1_out;
+-
+-	dev->dma_mem->virt_base = mem_base;
+-	dev->dma_mem->device_base = device_addr;
+-	dev->dma_mem->size = pages;
+-	dev->dma_mem->flags = flags;
+-
+-	if (flags & DMA_MEMORY_MAP)
+-		return DMA_MEMORY_MAP;
+-
+-	return DMA_MEMORY_IO;
+-
+- free1_out:
+-	kfree(dev->dma_mem);
+- out:
+-	if (mem_base)
+-		iounmap(mem_base);
+-	return 0;
+-}
+-EXPORT_SYMBOL(dma_declare_coherent_memory);
+-
+-void dma_release_declared_memory(struct device *dev)
+-{
+-	struct dma_coherent_mem *mem = dev->dma_mem;
+-	
+-	if(!mem)
+-		return;
+-	dev->dma_mem = NULL;
+-	iounmap(mem->virt_base);
+-	kfree(mem->bitmap);
+-	kfree(mem);
+-}
+-EXPORT_SYMBOL(dma_release_declared_memory);
+-
+-void *dma_mark_declared_memory_occupied(struct device *dev,
+-					dma_addr_t device_addr, size_t size)
+-{
+-	struct dma_coherent_mem *mem = dev->dma_mem;
+-	int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+-	int pos, err;
+-
+-	if (!mem)
+-		return ERR_PTR(-EINVAL);
+-
+-	pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
+-	err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
+-	if (err != 0)
+-		return ERR_PTR(err);
+-	return mem->virt_base + (pos << PAGE_SHIFT);
+-}
+-EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
+-
+-#ifdef CONFIG_PCI
+-/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+-
+-int forbid_dac;
+-EXPORT_SYMBOL(forbid_dac);
+-
+-static __devinit void via_no_dac(struct pci_dev *dev)
+-{
+-	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+-		printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
+-		forbid_dac = 1;
+-	}
+-}
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+-
+-static int check_iommu(char *s)
+-{
+-	if (!strcmp(s, "usedac")) {
+-		forbid_dac = -1;
+-		return 1;
+-	}
+-	return 0;
+-}
+-__setup("iommu=", check_iommu);
+-#endif
+diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c
+deleted file mode 100644
+index 375cb2b..0000000
+--- a/arch/x86/kernel/pci-dma_64.c
++++ /dev/null
+@@ -1,344 +0,0 @@
+-/*
+- * Dynamic DMA mapping support.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/string.h>
+-#include <linux/pci.h>
+-#include <linux/module.h>
+-#include <linux/dmar.h>
+-#include <asm/io.h>
+-#include <asm/gart.h>
+-#include <asm/calgary.h>
+-
+-int iommu_merge __read_mostly = 0;
+-
+-dma_addr_t bad_dma_address __read_mostly;
+-EXPORT_SYMBOL(bad_dma_address);
+-
+-/* This tells the BIO block layer to assume merging. Default to off
+-   because we cannot guarantee merging later. */
+-int iommu_bio_merge __read_mostly = 0;
+-EXPORT_SYMBOL(iommu_bio_merge);
+-
+-static int iommu_sac_force __read_mostly = 0;
+-
+-int no_iommu __read_mostly;
+-#ifdef CONFIG_IOMMU_DEBUG
+-int panic_on_overflow __read_mostly = 1;
+-int force_iommu __read_mostly = 1;
+-#else
+-int panic_on_overflow __read_mostly = 0;
+-int force_iommu __read_mostly= 0;
+-#endif
+-
+-/* Set this to 1 if there is a HW IOMMU in the system */
+-int iommu_detected __read_mostly = 0;
+-
+-/* Dummy device used for NULL arguments (normally ISA). Better would
+-   be probably a smaller DMA mask, but this is bug-to-bug compatible
+-   to i386. */
+-struct device fallback_dev = {
+-	.bus_id = "fallback device",
+-	.coherent_dma_mask = DMA_32BIT_MASK,
+-	.dma_mask = &fallback_dev.coherent_dma_mask,
+-};
+-
+-/* Allocate DMA memory on node near device */
+-noinline static void *
+-dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
+-{
+-	struct page *page;
+-	int node;
+-
+-	node = dev_to_node(dev);
+-
+-	page = alloc_pages_node(node, gfp, order);
+-	return page ? page_address(page) : NULL;
+-}
+-
+-/*
+- * Allocate memory for a coherent mapping.
+- */
+-void *
+-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+-		   gfp_t gfp)
+-{
+-	void *memory;
+-	unsigned long dma_mask = 0;
+-	u64 bus;
+-
+-	if (!dev)
+-		dev = &fallback_dev;
+-	dma_mask = dev->coherent_dma_mask;
+-	if (dma_mask == 0)
+-		dma_mask = DMA_32BIT_MASK;
+-
+-	/* Device not DMA able */
+-	if (dev->dma_mask == NULL)
+-		return NULL;
+-
+-	/* Don't invoke OOM killer */
+-	gfp |= __GFP_NORETRY;
+-
+-	/* Kludge to make it bug-to-bug compatible with i386. i386
+-	   uses the normal dma_mask for alloc_coherent. */
+-	dma_mask &= *dev->dma_mask;
+-
+-	/* Why <=? Even when the mask is smaller than 4GB it is often
+-	   larger than 16MB and in this case we have a chance of
+-	   finding fitting memory in the next higher zone first. If
+-	   not retry with true GFP_DMA. -AK */
+-	if (dma_mask <= DMA_32BIT_MASK)
+-		gfp |= GFP_DMA32;
+-
+- again:
+-	memory = dma_alloc_pages(dev, gfp, get_order(size));
+-	if (memory == NULL)
+-		return NULL;
+-
+-	{
+-		int high, mmu;
+-		bus = virt_to_bus(memory);
+-	        high = (bus + size) >= dma_mask;
+-		mmu = high;
+-		if (force_iommu && !(gfp & GFP_DMA))
+-			mmu = 1;
+-		else if (high) {
+-			free_pages((unsigned long)memory,
+-				   get_order(size));
+-
+-			/* Don't use the 16MB ZONE_DMA unless absolutely
+-			   needed. It's better to use remapping first. */
+-			if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
+-				gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
+-				goto again;
+-			}
+-
+-			/* Let low level make its own zone decisions */
+-			gfp &= ~(GFP_DMA32|GFP_DMA);
+-
+-			if (dma_ops->alloc_coherent)
+-				return dma_ops->alloc_coherent(dev, size,
+-							   dma_handle, gfp);
+-			return NULL;
+-		}
+-
+-		memset(memory, 0, size);
+-		if (!mmu) {
+-			*dma_handle = virt_to_bus(memory);
+-			return memory;
+-		}
+-	}
+-
+-	if (dma_ops->alloc_coherent) {
+-		free_pages((unsigned long)memory, get_order(size));
+-		gfp &= ~(GFP_DMA|GFP_DMA32);
+-		return dma_ops->alloc_coherent(dev, size, dma_handle, gfp);
+-	}
+-
+-	if (dma_ops->map_simple) {
+-		*dma_handle = dma_ops->map_simple(dev, memory,
+-					      size,
+-					      PCI_DMA_BIDIRECTIONAL);
+-		if (*dma_handle != bad_dma_address)
+-			return memory;
+-	}
+-
+-	if (panic_on_overflow)
+-		panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n",size);
+-	free_pages((unsigned long)memory, get_order(size));
+-	return NULL;
+-}
+-EXPORT_SYMBOL(dma_alloc_coherent);
+-
+-/*
+- * Unmap coherent memory.
+- * The caller must ensure that the device has finished accessing the mapping.
+- */
+-void dma_free_coherent(struct device *dev, size_t size,
+-			 void *vaddr, dma_addr_t bus)
+-{
+-	WARN_ON(irqs_disabled());	/* for portability */
+-	if (dma_ops->unmap_single)
+-		dma_ops->unmap_single(dev, bus, size, 0);
+-	free_pages((unsigned long)vaddr, get_order(size));
+-}
+-EXPORT_SYMBOL(dma_free_coherent);
+-
+-static int forbid_dac __read_mostly;
+-
+-int dma_supported(struct device *dev, u64 mask)
+-{
+-#ifdef CONFIG_PCI
+-	if (mask > 0xffffffff && forbid_dac > 0) {
+-
+-
+-
+-		printk(KERN_INFO "PCI: Disallowing DAC for device %s\n", dev->bus_id);
+-		return 0;
+-	}
+-#endif
+-
+-	if (dma_ops->dma_supported)
+-		return dma_ops->dma_supported(dev, mask);
+-
+-	/* Copied from i386. Doesn't make much sense, because it will
+-	   only work for pci_alloc_coherent.
+-	   The caller just has to use GFP_DMA in this case. */
+-        if (mask < DMA_24BIT_MASK)
+-                return 0;
+-
+-	/* Tell the device to use SAC when IOMMU force is on.  This
+-	   allows the driver to use cheaper accesses in some cases.
+-
+-	   Problem with this is that if we overflow the IOMMU area and
+-	   return DAC as fallback address the device may not handle it
+-	   correctly.
+-
+-	   As a special case some controllers have a 39bit address
+-	   mode that is as efficient as 32bit (aic79xx). Don't force
+-	   SAC for these.  Assume all masks <= 40 bits are of this
+-	   type. Normally this doesn't make any difference, but gives
+-	   more gentle handling of IOMMU overflow. */
+-	if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
+-		printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask);
+-		return 0;
+-	}
+-
+-	return 1;
+-}
+-EXPORT_SYMBOL(dma_supported);
+-
+-int dma_set_mask(struct device *dev, u64 mask)
+-{
+-	if (!dev->dma_mask || !dma_supported(dev, mask))
+-		return -EIO;
+-	*dev->dma_mask = mask;
+-	return 0;
+-}
+-EXPORT_SYMBOL(dma_set_mask);
+-
+-/*
+- * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
+- * documentation.
+- */
+-static __init int iommu_setup(char *p)
+-{
+-	iommu_merge = 1;
+-
+-	if (!p)
+-		return -EINVAL;
+-
+-	while (*p) {
+-		if (!strncmp(p,"off",3))
+-			no_iommu = 1;
+-		/* gart_parse_options has more force support */
+-		if (!strncmp(p,"force",5))
+-			force_iommu = 1;
+-		if (!strncmp(p,"noforce",7)) {
+-			iommu_merge = 0;
+-			force_iommu = 0;
+-		}
+-
+-		if (!strncmp(p, "biomerge",8)) {
+-			iommu_bio_merge = 4096;
+-			iommu_merge = 1;
+-			force_iommu = 1;
+-		}
+-		if (!strncmp(p, "panic",5))
+-			panic_on_overflow = 1;
+-		if (!strncmp(p, "nopanic",7))
+-			panic_on_overflow = 0;
+-		if (!strncmp(p, "merge",5)) {
+-			iommu_merge = 1;
+-			force_iommu = 1;
+-		}
+-		if (!strncmp(p, "nomerge",7))
+-			iommu_merge = 0;
+-		if (!strncmp(p, "forcesac",8))
+-			iommu_sac_force = 1;
+-		if (!strncmp(p, "allowdac", 8))
+-			forbid_dac = 0;
+-		if (!strncmp(p, "nodac", 5))
+-			forbid_dac = -1;
+-
+-#ifdef CONFIG_SWIOTLB
+-		if (!strncmp(p, "soft",4))
+-			swiotlb = 1;
+-#endif
+-
+-#ifdef CONFIG_GART_IOMMU
+-		gart_parse_options(p);
+-#endif
+-
+-#ifdef CONFIG_CALGARY_IOMMU
+-		if (!strncmp(p, "calgary", 7))
+-			use_calgary = 1;
+-#endif /* CONFIG_CALGARY_IOMMU */
+-
+-		p += strcspn(p, ",");
+-		if (*p == ',')
+-			++p;
+-	}
+-	return 0;
+-}
+-early_param("iommu", iommu_setup);
+-
+-void __init pci_iommu_alloc(void)
+-{
+-	/*
+-	 * The order of these functions is important for
+-	 * fall-back/fail-over reasons
+-	 */
+-#ifdef CONFIG_GART_IOMMU
+-	gart_iommu_hole_init();
+-#endif
+-
+-#ifdef CONFIG_CALGARY_IOMMU
+-	detect_calgary();
+-#endif
+-
+-	detect_intel_iommu();
+-
+-#ifdef CONFIG_SWIOTLB
+-	pci_swiotlb_init();
+-#endif
+-}
+-
+-static int __init pci_iommu_init(void)
+-{
+-#ifdef CONFIG_CALGARY_IOMMU
+-	calgary_iommu_init();
+-#endif
+-
+-	intel_iommu_init();
+-
+-#ifdef CONFIG_GART_IOMMU
+-	gart_iommu_init();
+-#endif
+-
+-	no_iommu_init();
+-	return 0;
+-}
+-
+-void pci_iommu_shutdown(void)
+-{
+-	gart_iommu_shutdown();
+-}
+-
+-#ifdef CONFIG_PCI
+-/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+-
+-static __devinit void via_no_dac(struct pci_dev *dev)
+-{
+-	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+-		printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
+-		forbid_dac = 1;
+-	}
+-}
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+-#endif
+-/* Must execute after PCI subsystem */
+-fs_initcall(pci_iommu_init);
+diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
+index 700e464..c07455d 100644
+--- a/arch/x86/kernel/pci-gart_64.c
++++ b/arch/x86/kernel/pci-gart_64.c
+@@ -264,9 +264,9 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
+ }
+ 
+ static dma_addr_t
+-gart_map_simple(struct device *dev, char *buf, size_t size, int dir)
++gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir)
+ {
+-	dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir);
++	dma_addr_t map = dma_map_area(dev, paddr, size, dir);
+ 
+ 	flush_gart();
+ 
+@@ -275,18 +275,17 @@ gart_map_simple(struct device *dev, char *buf, size_t size, int dir)
+ 
+ /* Map a single area into the IOMMU */
+ static dma_addr_t
+-gart_map_single(struct device *dev, void *addr, size_t size, int dir)
++gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir)
+ {
+-	unsigned long phys_mem, bus;
++	unsigned long bus;
+ 
+ 	if (!dev)
+ 		dev = &fallback_dev;
+ 
+-	phys_mem = virt_to_phys(addr);
+-	if (!need_iommu(dev, phys_mem, size))
+-		return phys_mem;
++	if (!need_iommu(dev, paddr, size))
++		return paddr;
+ 
+-	bus = gart_map_simple(dev, addr, size, dir);
++	bus = gart_map_simple(dev, paddr, size, dir);
+ 
+ 	return bus;
+ }
+diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
+new file mode 100644
+index 0000000..aec43d5
+--- /dev/null
++++ b/arch/x86/kernel/pci-nommu.c
+@@ -0,0 +1,100 @@
++/* Fallback functions when the main IOMMU code is not compiled in. This
++   code is roughly equivalent to i386. */
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/string.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++
++#include <asm/gart.h>
++#include <asm/processor.h>
++#include <asm/dma.h>
++
++static int
++check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
++{
++	if (hwdev && bus + size > *hwdev->dma_mask) {
++		if (*hwdev->dma_mask >= DMA_32BIT_MASK)
++			printk(KERN_ERR
++			    "nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
++				name, (long long)bus, size,
++				(long long)*hwdev->dma_mask);
++		return 0;
++	}
++	return 1;
++}
++
++static dma_addr_t
++nommu_map_single(struct device *hwdev, phys_addr_t paddr, size_t size,
++	       int direction)
++{
++	dma_addr_t bus = paddr;
++	WARN_ON(size == 0);
++	if (!check_addr("map_single", hwdev, bus, size))
++				return bad_dma_address;
++	flush_write_buffers();
++	return bus;
++}
++
++
++/* Map a set of buffers described by scatterlist in streaming
++ * mode for DMA.  This is the scatter-gather version of the
++ * above pci_map_single interface.  Here the scatter gather list
++ * elements are each tagged with the appropriate dma address
++ * and length.  They are obtained via sg_dma_{address,length}(SG).
++ *
++ * NOTE: An implementation may be able to use a smaller number of
++ *       DMA address/length pairs than there are SG table elements.
++ *       (for example via virtual mapping capabilities)
++ *       The routine returns the number of addr/length pairs actually
++ *       used, at most nents.
++ *
++ * Device ownership issues as mentioned above for pci_map_single are
++ * the same here.
++ */
++static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
++	       int nents, int direction)
++{
++	struct scatterlist *s;
++	int i;
++
++	WARN_ON(nents == 0 || sg[0].length == 0);
++
++	for_each_sg(sg, s, nents, i) {
++		BUG_ON(!sg_page(s));
++		s->dma_address = sg_phys(s);
++		if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
++			return 0;
++		s->dma_length = s->length;
++	}
++	flush_write_buffers();
++	return nents;
++}
++
++/* Make sure we keep the same behaviour */
++static int nommu_mapping_error(dma_addr_t dma_addr)
++{
++#ifdef CONFIG_X86_32
++	return 0;
++#else
++	return (dma_addr == bad_dma_address);
++#endif
++}
++
++
++const struct dma_mapping_ops nommu_dma_ops = {
++	.map_single = nommu_map_single,
++	.map_sg = nommu_map_sg,
++	.mapping_error = nommu_mapping_error,
++	.is_phys = 1,
++};
++
++void __init no_iommu_init(void)
++{
++	if (dma_ops)
++		return;
++
++	force_iommu = 0; /* no HW IOMMU */
++	dma_ops = &nommu_dma_ops;
++}
+diff --git a/arch/x86/kernel/pci-nommu_64.c b/arch/x86/kernel/pci-nommu_64.c
+deleted file mode 100644
+index ab08e18..0000000
+--- a/arch/x86/kernel/pci-nommu_64.c
++++ /dev/null
+@@ -1,98 +0,0 @@
+-/* Fallback functions when the main IOMMU code is not compiled in. This
+-   code is roughly equivalent to i386. */
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/pci.h>
+-#include <linux/string.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/scatterlist.h>
+-
+-#include <asm/gart.h>
+-#include <asm/processor.h>
+-#include <asm/dma.h>
+-
+-static int
+-check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
+-{
+-        if (hwdev && bus + size > *hwdev->dma_mask) {
+-		if (*hwdev->dma_mask >= DMA_32BIT_MASK)
+-			printk(KERN_ERR
+-			    "nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
+-				name, (long long)bus, size,
+-				(long long)*hwdev->dma_mask);
+-		return 0;
+-	}
+-	return 1;
+-}
+-
+-static dma_addr_t
+-nommu_map_single(struct device *hwdev, void *ptr, size_t size,
+-	       int direction)
+-{
+-	dma_addr_t bus = virt_to_bus(ptr);
+-	if (!check_addr("map_single", hwdev, bus, size))
+-				return bad_dma_address;
+-	return bus;
+-}
+-
+-static void nommu_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
+-			int direction)
+-{
+-}
+-
+-/* Map a set of buffers described by scatterlist in streaming
+- * mode for DMA.  This is the scatter-gather version of the
+- * above pci_map_single interface.  Here the scatter gather list
+- * elements are each tagged with the appropriate dma address
+- * and length.  They are obtained via sg_dma_{address,length}(SG).
+- *
+- * NOTE: An implementation may be able to use a smaller number of
+- *       DMA address/length pairs than there are SG table elements.
+- *       (for example via virtual mapping capabilities)
+- *       The routine returns the number of addr/length pairs actually
+- *       used, at most nents.
+- *
+- * Device ownership issues as mentioned above for pci_map_single are
+- * the same here.
+- */
+-static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
+-	       int nents, int direction)
+-{
+-	struct scatterlist *s;
+-	int i;
+-
+-	for_each_sg(sg, s, nents, i) {
+-		BUG_ON(!sg_page(s));
+-		s->dma_address = virt_to_bus(sg_virt(s));
+-		if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
+-			return 0;
+-		s->dma_length = s->length;
+-	}
+-	return nents;
+-}
+-
+-/* Unmap a set of streaming mode DMA translations.
+- * Again, cpu read rules concerning calls here are the same as for
+- * pci_unmap_single() above.
+- */
+-static void nommu_unmap_sg(struct device *dev, struct scatterlist *sg,
+-		  int nents, int dir)
+-{
+-}
+-
+-const struct dma_mapping_ops nommu_dma_ops = {
+-	.map_single = nommu_map_single,
+-	.unmap_single = nommu_unmap_single,
+-	.map_sg = nommu_map_sg,
+-	.unmap_sg = nommu_unmap_sg,
+-	.is_phys = 1,
+-};
+-
+-void __init no_iommu_init(void)
+-{
+-	if (dma_ops)
+-		return;
+-
+-	force_iommu = 0; /* no HW IOMMU */
+-	dma_ops = &nommu_dma_ops;
+-}
+diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c
+index 82a0a67..490da7f 100644
+--- a/arch/x86/kernel/pci-swiotlb_64.c
++++ b/arch/x86/kernel/pci-swiotlb_64.c
+@@ -11,11 +11,18 @@
+ 
+ int swiotlb __read_mostly;
+ 
++static dma_addr_t
++swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size,
++			int direction)
++{
++	return swiotlb_map_single(hwdev, phys_to_virt(paddr), size, direction);
++}
++
+ const struct dma_mapping_ops swiotlb_dma_ops = {
+ 	.mapping_error = swiotlb_dma_mapping_error,
+ 	.alloc_coherent = swiotlb_alloc_coherent,
+ 	.free_coherent = swiotlb_free_coherent,
+-	.map_single = swiotlb_map_single,
++	.map_single = swiotlb_map_single_phys,
+ 	.unmap_single = swiotlb_unmap_single,
+ 	.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+ 	.sync_single_for_device = swiotlb_sync_single_for_device,
+diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
+new file mode 100644
+index 0000000..3004d71
+--- /dev/null
++++ b/arch/x86/kernel/process.c
+@@ -0,0 +1,44 @@
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++
++struct kmem_cache *task_xstate_cachep;
++
++int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
++{
++	*dst = *src;
++	if (src->thread.xstate) {
++		dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
++						      GFP_KERNEL);
++		if (!dst->thread.xstate)
++			return -ENOMEM;
++		WARN_ON((unsigned long)dst->thread.xstate & 15);
++		memcpy(dst->thread.xstate, src->thread.xstate, xstate_size);
++	}
++	return 0;
++}
++
++void free_thread_xstate(struct task_struct *tsk)
++{
++	if (tsk->thread.xstate) {
++		kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
++		tsk->thread.xstate = NULL;
++	}
++}
++
++void free_thread_info(struct thread_info *ti)
++{
++	free_thread_xstate(ti->task);
++	free_pages((unsigned long)ti, get_order(THREAD_SIZE));
++}
++
++void arch_task_cache_init(void)
++{
++        task_xstate_cachep =
++        	kmem_cache_create("task_xstate", xstate_size,
++				  __alignof__(union thread_xstate),
++				  SLAB_PANIC, NULL);
++}
+diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
+index 43930e7..77de848 100644
+--- a/arch/x86/kernel/process_32.c
++++ b/arch/x86/kernel/process_32.c
+@@ -36,6 +36,7 @@
+ #include <linux/personality.h>
+ #include <linux/tick.h>
+ #include <linux/percpu.h>
++#include <linux/prctl.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -45,7 +46,6 @@
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/desc.h>
+-#include <asm/vm86.h>
+ #ifdef CONFIG_MATH_EMULATION
+ #include <asm/math_emu.h>
+ #endif
+@@ -113,20 +113,13 @@ void default_idle(void)
+ 
+ 		local_irq_disable();
+ 		if (!need_resched()) {
+-			ktime_t t0, t1;
+-			u64 t0n, t1n;
+-
+-			t0 = ktime_get();
+-			t0n = ktime_to_ns(t0);
+ 			safe_halt();	/* enables interrupts racelessly */
+ 			local_irq_disable();
+-			t1 = ktime_get();
+-			t1n = ktime_to_ns(t1);
+-			sched_clock_idle_wakeup_event(t1n - t0n);
+ 		}
+ 		local_irq_enable();
+ 		current_thread_info()->status |= TS_POLLING;
+ 	} else {
++		local_irq_enable();
+ 		/* loop is done by the caller */
+ 		cpu_relax();
+ 	}
+@@ -142,6 +135,7 @@ EXPORT_SYMBOL(default_idle);
+  */
+ static void poll_idle(void)
+ {
++	local_irq_enable();
+ 	cpu_relax();
+ }
+ 
+@@ -248,8 +242,11 @@ void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
+ 		__monitor((void *)&current_thread_info()->flags, 0, 0);
+ 		smp_mb();
+ 		if (!need_resched())
+-			__mwait(ax, cx);
+-	}
++			__sti_mwait(ax, cx);
++		else
++			local_irq_enable();
++	} else
++		local_irq_enable();
+ }
+ 
+ /* Default MONITOR/MWAIT with no hints, used for default C1 state */
+@@ -332,7 +329,7 @@ void __show_registers(struct pt_regs *regs, int all)
+ 			init_utsname()->version);
+ 
+ 	printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
+-			0xffff & regs->cs, regs->ip, regs->flags,
++			(u16)regs->cs, regs->ip, regs->flags,
+ 			smp_processor_id());
+ 	print_symbol("EIP is at %s\n", regs->ip);
+ 
+@@ -341,8 +338,7 @@ void __show_registers(struct pt_regs *regs, int all)
+ 	printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
+ 		regs->si, regs->di, regs->bp, sp);
+ 	printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
+-	       regs->ds & 0xffff, regs->es & 0xffff,
+-	       regs->fs & 0xffff, gs, ss);
++	       (u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss);
+ 
+ 	if (!all)
+ 		return;
+@@ -513,11 +509,30 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ 	return err;
+ }
+ 
+-#ifdef CONFIG_SECCOMP
++void
++start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
++{
++	__asm__("movl %0, %%gs" :: "r"(0));
++	regs->fs		= 0;
++	set_fs(USER_DS);
++	regs->ds		= __USER_DS;
++	regs->es		= __USER_DS;
++	regs->ss		= __USER_DS;
++	regs->cs		= __USER_CS;
++	regs->ip		= new_ip;
++	regs->sp		= new_sp;
++	/*
++	 * Free the old FP and other extended state
++	 */
++	free_thread_xstate(current);
++}
++EXPORT_SYMBOL_GPL(start_thread);
++
+ static void hard_disable_TSC(void)
+ {
+ 	write_cr4(read_cr4() | X86_CR4_TSD);
+ }
++
+ void disable_TSC(void)
+ {
+ 	preempt_disable();
+@@ -529,11 +544,47 @@ void disable_TSC(void)
+ 		hard_disable_TSC();
+ 	preempt_enable();
+ }
++
+ static void hard_enable_TSC(void)
+ {
+ 	write_cr4(read_cr4() & ~X86_CR4_TSD);
+ }
+-#endif /* CONFIG_SECCOMP */
++
++static void enable_TSC(void)
++{
++	preempt_disable();
++	if (test_and_clear_thread_flag(TIF_NOTSC))
++		/*
++		 * Must flip the CPU state synchronously with
++		 * TIF_NOTSC in the current running context.
++		 */
++		hard_enable_TSC();
++	preempt_enable();
++}
++
++int get_tsc_mode(unsigned long adr)
++{
++	unsigned int val;
++
++	if (test_thread_flag(TIF_NOTSC))
++		val = PR_TSC_SIGSEGV;
++	else
++		val = PR_TSC_ENABLE;
++
++	return put_user(val, (unsigned int __user *)adr);
++}
++
++int set_tsc_mode(unsigned int val)
++{
++	if (val == PR_TSC_SIGSEGV)
++		disable_TSC();
++	else if (val == PR_TSC_ENABLE)
++		enable_TSC();
++	else
++		return -EINVAL;
++
++	return 0;
++}
+ 
+ static noinline void
+ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+@@ -550,12 +601,12 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+ 		/* we clear debugctl to make sure DS
+ 		 * is not in use when we change it */
+ 		debugctl = 0;
+-		wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++		update_debugctlmsr(0);
+ 		wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0);
+ 	}
+ 
+ 	if (next->debugctlmsr != debugctl)
+-		wrmsr(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr, 0);
++		update_debugctlmsr(next->debugctlmsr);
+ 
+ 	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+ 		set_debugreg(next->debugreg0, 0);
+@@ -567,7 +618,6 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+ 		set_debugreg(next->debugreg7, 7);
+ 	}
+ 
+-#ifdef CONFIG_SECCOMP
+ 	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
+ 	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
+ 		/* prev and next are different */
+@@ -576,7 +626,6 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+ 		else
+ 			hard_enable_TSC();
+ 	}
+-#endif
+ 
+ #ifdef X86_BTS
+ 	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
+@@ -658,7 +707,7 @@ struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct
+ 
+ 	/* we're going to use this soon, after a few expensive things */
+ 	if (next_p->fpu_counter > 5)
+-		prefetch(&next->i387.fxsave);
++		prefetch(next->xstate);
+ 
+ 	/*
+ 	 * Reload esp0.
+diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
+index 46c4c54..131c2ee 100644
+--- a/arch/x86/kernel/process_64.c
++++ b/arch/x86/kernel/process_64.c
+@@ -36,6 +36,7 @@
+ #include <linux/kprobes.h>
+ #include <linux/kdebug.h>
+ #include <linux/tick.h>
++#include <linux/prctl.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -107,16 +108,8 @@ void default_idle(void)
+ 	smp_mb();
+ 	local_irq_disable();
+ 	if (!need_resched()) {
+-		ktime_t t0, t1;
+-		u64 t0n, t1n;
+-
+-		t0 = ktime_get();
+-		t0n = ktime_to_ns(t0);
+ 		safe_halt();	/* enables interrupts racelessly */
+ 		local_irq_disable();
+-		t1 = ktime_get();
+-		t1n = ktime_to_ns(t1);
+-		sched_clock_idle_wakeup_event(t1n - t0n);
+ 	}
+ 	local_irq_enable();
+ 	current_thread_info()->status |= TS_POLLING;
+@@ -528,6 +521,83 @@ out:
+ 	return err;
+ }
+ 
++void
++start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
++{
++	asm volatile("movl %0, %%fs; movl %0, %%es; movl %0, %%ds" :: "r"(0));
++	load_gs_index(0);
++	regs->ip		= new_ip;
++	regs->sp		= new_sp;
++	write_pda(oldrsp, new_sp);
++	regs->cs		= __USER_CS;
++	regs->ss		= __USER_DS;
++	regs->flags		= 0x200;
++	set_fs(USER_DS);
++	/*
++	 * Free the old FP and other extended state
++	 */
++	free_thread_xstate(current);
++}
++EXPORT_SYMBOL_GPL(start_thread);
++
++static void hard_disable_TSC(void)
++{
++	write_cr4(read_cr4() | X86_CR4_TSD);
++}
++
++void disable_TSC(void)
++{
++	preempt_disable();
++	if (!test_and_set_thread_flag(TIF_NOTSC))
++		/*
++		 * Must flip the CPU state synchronously with
++		 * TIF_NOTSC in the current running context.
++		 */
++		hard_disable_TSC();
++	preempt_enable();
++}
++
++static void hard_enable_TSC(void)
++{
++	write_cr4(read_cr4() & ~X86_CR4_TSD);
++}
++
++static void enable_TSC(void)
++{
++	preempt_disable();
++	if (test_and_clear_thread_flag(TIF_NOTSC))
++		/*
++		 * Must flip the CPU state synchronously with
++		 * TIF_NOTSC in the current running context.
++		 */
++		hard_enable_TSC();
++	preempt_enable();
++}
++
++int get_tsc_mode(unsigned long adr)
++{
++	unsigned int val;
++
++	if (test_thread_flag(TIF_NOTSC))
++		val = PR_TSC_SIGSEGV;
++	else
++		val = PR_TSC_ENABLE;
++
++	return put_user(val, (unsigned int __user *)adr);
++}
++
++int set_tsc_mode(unsigned int val)
++{
++	if (val == PR_TSC_SIGSEGV)
++		disable_TSC();
++	else if (val == PR_TSC_ENABLE)
++		enable_TSC();
++	else
++		return -EINVAL;
++
++	return 0;
++}
++
+ /*
+  * This special macro can be used to load a debugging register
+  */
+@@ -548,12 +618,12 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
+ 		/* we clear debugctl to make sure DS
+ 		 * is not in use when we change it */
+ 		debugctl = 0;
+-		wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++		update_debugctlmsr(0);
+ 		wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr);
+ 	}
+ 
+ 	if (next->debugctlmsr != debugctl)
+-		wrmsrl(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr);
++		update_debugctlmsr(next->debugctlmsr);
+ 
+ 	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+ 		loaddebug(next, 0);
+@@ -565,6 +635,15 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
+ 		loaddebug(next, 7);
+ 	}
+ 
++	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
++	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
++		/* prev and next are different */
++		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
++			hard_disable_TSC();
++		else
++			hard_enable_TSC();
++	}
++
+ 	if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
+ 		/*
+ 		 * Copy the relevant range of the IO bitmap.
+@@ -607,7 +686,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+ 
+ 	/* we're going to use this soon, after a few expensive things */
+ 	if (next_p->fpu_counter>5)
+-		prefetch(&next->i387.fxsave);
++		prefetch(next->xstate);
+ 
+ 	/*
+ 	 * Reload esp0, LDT and the page table pointer:
+diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
+index eb92ccb..fb03ef3 100644
+--- a/arch/x86/kernel/ptrace.c
++++ b/arch/x86/kernel/ptrace.c
+@@ -1207,97 +1207,16 @@ static int genregs32_set(struct task_struct *target,
+ 	return ret;
+ }
+ 
+-static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data)
++long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
++			compat_ulong_t caddr, compat_ulong_t cdata)
+ {
+-	siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t));
+-	compat_siginfo_t __user *si32 = compat_ptr(data);
+-	siginfo_t ssi;
+-	int ret;
+-
+-	if (request == PTRACE_SETSIGINFO) {
+-		memset(&ssi, 0, sizeof(siginfo_t));
+-		ret = copy_siginfo_from_user32(&ssi, si32);
+-		if (ret)
+-			return ret;
+-		if (copy_to_user(si, &ssi, sizeof(siginfo_t)))
+-			return -EFAULT;
+-	}
+-	ret = sys_ptrace(request, pid, addr, (unsigned long)si);
+-	if (ret)
+-		return ret;
+-	if (request == PTRACE_GETSIGINFO) {
+-		if (copy_from_user(&ssi, si, sizeof(siginfo_t)))
+-			return -EFAULT;
+-		ret = copy_siginfo_to_user32(si32, &ssi);
+-	}
+-	return ret;
+-}
+-
+-asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
+-{
+-	struct task_struct *child;
+-	struct pt_regs *childregs;
++	unsigned long addr = caddr;
++	unsigned long data = cdata;
+ 	void __user *datap = compat_ptr(data);
+ 	int ret;
+ 	__u32 val;
+ 
+ 	switch (request) {
+-	case PTRACE_TRACEME:
+-	case PTRACE_ATTACH:
+-	case PTRACE_KILL:
+-	case PTRACE_CONT:
+-	case PTRACE_SINGLESTEP:
+-	case PTRACE_SINGLEBLOCK:
+-	case PTRACE_DETACH:
+-	case PTRACE_SYSCALL:
+-	case PTRACE_OLDSETOPTIONS:
+-	case PTRACE_SETOPTIONS:
+-	case PTRACE_SET_THREAD_AREA:
+-	case PTRACE_GET_THREAD_AREA:
+-#ifdef X86_BTS
+-	case PTRACE_BTS_CONFIG:
+-	case PTRACE_BTS_STATUS:
+-	case PTRACE_BTS_SIZE:
+-	case PTRACE_BTS_GET:
+-	case PTRACE_BTS_CLEAR:
+-	case PTRACE_BTS_DRAIN:
+-#endif
+-		return sys_ptrace(request, pid, addr, data);
+-
+-	default:
+-		return -EINVAL;
+-
+-	case PTRACE_PEEKTEXT:
+-	case PTRACE_PEEKDATA:
+-	case PTRACE_POKEDATA:
+-	case PTRACE_POKETEXT:
+-	case PTRACE_POKEUSR:
+-	case PTRACE_PEEKUSR:
+-	case PTRACE_GETREGS:
+-	case PTRACE_SETREGS:
+-	case PTRACE_SETFPREGS:
+-	case PTRACE_GETFPREGS:
+-	case PTRACE_SETFPXREGS:
+-	case PTRACE_GETFPXREGS:
+-	case PTRACE_GETEVENTMSG:
+-		break;
+-
+-	case PTRACE_SETSIGINFO:
+-	case PTRACE_GETSIGINFO:
+-		return ptrace32_siginfo(request, pid, addr, data);
+-	}
+-
+-	child = ptrace_get_task_struct(pid);
+-	if (IS_ERR(child))
+-		return PTR_ERR(child);
+-
+-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+-	if (ret < 0)
+-		goto out;
+-
+-	childregs = task_pt_regs(child);
+-
+-	switch (request) {
+ 	case PTRACE_PEEKUSR:
+ 		ret = getreg32(child, addr, &val);
+ 		if (ret == 0)
+@@ -1343,12 +1262,14 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
+ 					     sizeof(struct user32_fxsr_struct),
+ 					     datap);
+ 
++	case PTRACE_GET_THREAD_AREA:
++	case PTRACE_SET_THREAD_AREA:
++		return arch_ptrace(child, request, addr, data);
++
+ 	default:
+ 		return compat_ptrace_request(child, request, addr, data);
+ 	}
+ 
+- out:
+-	put_task_struct(child);
+ 	return ret;
+ }
+ 
+@@ -1456,7 +1377,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
+ /* notification of system call entry/exit
+  * - triggered by current->work.syscall_trace
+  */
+-__attribute__((regparm(3)))
+ int do_syscall_trace(struct pt_regs *regs, int entryexit)
+ {
+ 	int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU);
+diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
+index 484c4a8..1791a75 100644
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -1,5 +1,4 @@
+ #include <linux/module.h>
+-#include <linux/init.h>
+ #include <linux/reboot.h>
+ #include <linux/init.h>
+ #include <linux/pm.h>
+@@ -9,6 +8,7 @@
+ #include <asm/apic.h>
+ #include <asm/desc.h>
+ #include <asm/hpet.h>
++#include <asm/pgtable.h>
+ #include <asm/reboot_fixups.h>
+ #include <asm/reboot.h>
+ 
+@@ -16,7 +16,6 @@
+ # include <linux/dmi.h>
+ # include <linux/ctype.h>
+ # include <linux/mc146818rtc.h>
+-# include <asm/pgtable.h>
+ #else
+ # include <asm/iommu.h>
+ #endif
+@@ -276,7 +275,7 @@ void machine_real_restart(unsigned char *code, int length)
+ 	/* 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 + USER_PGD_PTRS,
++	memcpy(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+ 		sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
+ 
+ 	/*
+@@ -412,16 +411,16 @@ static void native_machine_shutdown(void)
+ #ifdef CONFIG_X86_32
+ 	/* See if there has been given a command line override */
+ 	if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
+-		cpu_isset(reboot_cpu, cpu_online_map))
++		cpu_online(reboot_cpu))
+ 		reboot_cpu_id = reboot_cpu;
+ #endif
+ 
+ 	/* Make certain the cpu I'm about to reboot on is online */
+-	if (!cpu_isset(reboot_cpu_id, cpu_online_map))
++	if (!cpu_online(reboot_cpu_id))
+ 		reboot_cpu_id = smp_processor_id();
+ 
+ 	/* Make certain I only run on the appropriate processor */
+-	set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id));
+ 
+ 	/* O.K Now that I'm on the appropriate processor,
+ 	 * stop all of the others.
+diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S
+index f151d6f..c30fe25 100644
+--- a/arch/x86/kernel/relocate_kernel_32.S
++++ b/arch/x86/kernel/relocate_kernel_32.S
+@@ -9,18 +9,19 @@
+ #include <linux/linkage.h>
+ #include <asm/page.h>
+ #include <asm/kexec.h>
++#include <asm/processor-flags.h>
++#include <asm/pgtable.h>
+ 
+ /*
+  * Must be relocatable PIC code callable as a C function
+  */
+ 
+ #define PTR(x) (x << 2)
+-#define PAGE_ALIGNED (1 << PAGE_SHIFT)
+-#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
+-#define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */
++#define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
++#define PAE_PGD_ATTR (_PAGE_PRESENT)
+ 
+ 	.text
+-	.align PAGE_ALIGNED
++	.align PAGE_SIZE
+ 	.globl relocate_kernel
+ relocate_kernel:
+ 	movl	8(%esp), %ebp /* list of pages */
+@@ -155,7 +156,7 @@ relocate_new_kernel:
+ 	movl	%eax, %cr3
+ 
+ 	/* setup a new stack at the end of the physical control page */
+-	lea	4096(%edi), %esp
++	lea	PAGE_SIZE(%edi), %esp
+ 
+ 	/* jump to identity mapped page */
+ 	movl    %edi, %eax
+@@ -168,16 +169,16 @@ identity_mapped:
+ 	pushl   %edx
+ 
+ 	/* Set cr0 to a known state:
+-	 * 31 0 == Paging disabled
+-	 * 18 0 == Alignment check disabled
+-	 * 16 0 == Write protect disabled
+-	 * 3  0 == No task switch
+-	 * 2  0 == Don't do FP software emulation.
+-	 * 0  1 == Proctected mode enabled
++	 *  - Paging disabled
++	 *  - Alignment check disabled
++	 *  - Write protect disabled
++	 *  - No task switch
++	 *  - Don't do FP software emulation.
++	 *  - Proctected mode enabled
+ 	 */
+ 	movl	%cr0, %eax
+-	andl	$~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax
+-	orl	$(1<<0), %eax
++	andl	$~(X86_CR0_PG | X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %eax
++	orl	$(X86_CR0_PE), %eax
+ 	movl	%eax, %cr0
+ 
+ 	/* clear cr4 if applicable */
+@@ -186,8 +187,7 @@ identity_mapped:
+ 	/* Set cr4 to a known state:
+ 	 * Setting everything to zero seems safe.
+ 	 */
+-	movl	%cr4, %eax
+-	andl	$0, %eax
++	xorl	%eax, %eax
+ 	movl	%eax, %cr4
+ 
+ 	jmp 1f
+diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
+index 14e9587..f5afe66 100644
+--- a/arch/x86/kernel/relocate_kernel_64.S
++++ b/arch/x86/kernel/relocate_kernel_64.S
+@@ -9,17 +9,18 @@
+ #include <linux/linkage.h>
+ #include <asm/page.h>
+ #include <asm/kexec.h>
++#include <asm/processor-flags.h>
++#include <asm/pgtable.h>
+ 
+ /*
+  * Must be relocatable PIC code callable as a C function
+  */
+ 
+ #define PTR(x) (x << 3)
+-#define PAGE_ALIGNED (1 << PAGE_SHIFT)
+-#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
++#define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+ 
+ 	.text
+-	.align PAGE_ALIGNED
++	.align PAGE_SIZE
+ 	.code64
+ 	.globl relocate_kernel
+ relocate_kernel:
+@@ -160,7 +161,7 @@ relocate_new_kernel:
+ 	movq	%r9, %cr3
+ 
+ 	/* setup a new stack at the end of the physical control page */
+-	lea	4096(%r8), %rsp
++	lea	PAGE_SIZE(%r8), %rsp
+ 
+ 	/* jump to identity mapped page */
+ 	addq	$(identity_mapped - relocate_kernel), %r8
+@@ -172,33 +173,22 @@ identity_mapped:
+ 	pushq   %rdx
+ 
+ 	/* Set cr0 to a known state:
+-	 * 31 1 == Paging enabled
+-	 * 18 0 == Alignment check disabled
+-	 * 16 0 == Write protect disabled
+-	 * 3  0 == No task switch
+-	 * 2  0 == Don't do FP software emulation.
+-	 * 0  1 == Proctected mode enabled
++	 *  - Paging enabled
++	 *  - Alignment check disabled
++	 *  - Write protect disabled
++	 *  - No task switch
++	 *  - Don't do FP software emulation.
++	 *  - Proctected mode enabled
+ 	 */
+ 	movq	%cr0, %rax
+-	andq	$~((1<<18)|(1<<16)|(1<<3)|(1<<2)), %rax
+-	orl	$((1<<31)|(1<<0)), %eax
++	andq	$~(X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %rax
++	orl	$(X86_CR0_PG | X86_CR0_PE), %eax
+ 	movq	%rax, %cr0
+ 
+ 	/* Set cr4 to a known state:
+-	 * 10 0 == xmm exceptions disabled
+-	 * 9  0 == xmm registers instructions disabled
+-	 * 8  0 == performance monitoring counter disabled
+-	 * 7  0 == page global disabled
+-	 * 6  0 == machine check exceptions disabled
+-	 * 5  1 == physical address extension enabled
+-	 * 4  0 == page size extensions	disabled
+-	 * 3  0 == Debug extensions disabled
+-	 * 2  0 == Time stamp disable (disabled)
+-	 * 1  0 == Protected mode virtual interrupts disabled
+-	 * 0  0 == VME disabled
++	 *  - physical address extension enabled
+ 	 */
+-
+-	movq	$((1<<5)), %rax
++	movq	$X86_CR4_PAE, %rax
+ 	movq	%rax, %cr4
+ 
+ 	jmp 1f
+diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
+index eb9b1a1..9615eee 100644
+--- a/arch/x86/kernel/rtc.c
++++ b/arch/x86/kernel/rtc.c
+@@ -9,7 +9,6 @@
+ #include <asm/vsyscall.h>
+ 
+ #ifdef CONFIG_X86_32
+-# define CMOS_YEARS_OFFS 1900
+ /*
+  * This is a special lock that is owned by the CPU and holds the index
+  * register we are working with.  It is required for NMI access to the
+@@ -17,14 +16,11 @@
+  */
+ volatile unsigned long cmos_lock = 0;
+ EXPORT_SYMBOL(cmos_lock);
+-#else
+-/*
+- * x86-64 systems only exists since 2002.
+- * This will work up to Dec 31, 2100
+- */
+-# define CMOS_YEARS_OFFS 2000
+ #endif
+ 
++/* For two digit years assume time is always after that */
++#define CMOS_YEARS_OFFS 2000
++
+ DEFINE_SPINLOCK(rtc_lock);
+ EXPORT_SYMBOL(rtc_lock);
+ 
+@@ -98,7 +94,7 @@ int mach_set_rtc_mmss(unsigned long nowtime)
+ 
+ unsigned long mach_get_cmos_time(void)
+ {
+-	unsigned int year, mon, day, hour, min, sec, century = 0;
++	unsigned int status, year, mon, day, hour, min, sec, century = 0;
+ 
+ 	/*
+ 	 * If UIP is clear, then we have >= 244 microseconds before
+@@ -116,14 +112,16 @@ unsigned long mach_get_cmos_time(void)
+ 	mon = CMOS_READ(RTC_MONTH);
+ 	year = CMOS_READ(RTC_YEAR);
+ 
+-#if defined(CONFIG_ACPI) && defined(CONFIG_X86_64)
+-	/* CHECKME: Is this really 64bit only ??? */
++#ifdef CONFIG_ACPI
+ 	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
+ 	    acpi_gbl_FADT.century)
+ 		century = CMOS_READ(acpi_gbl_FADT.century);
+ #endif
+ 
+-	if (RTC_ALWAYS_BCD || !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)) {
++	status = CMOS_READ(RTC_CONTROL);
++	WARN_ON_ONCE(RTC_ALWAYS_BCD && (status & RTC_DM_BINARY));
++
++	if (RTC_ALWAYS_BCD || !(status & RTC_DM_BINARY)) {
+ 		BCD_TO_BIN(sec);
+ 		BCD_TO_BIN(min);
+ 		BCD_TO_BIN(hour);
+@@ -136,11 +134,8 @@ unsigned long mach_get_cmos_time(void)
+ 		BCD_TO_BIN(century);
+ 		year += century * 100;
+ 		printk(KERN_INFO "Extended CMOS year: %d\n", century * 100);
+-	} else {
++	} else
+ 		year += CMOS_YEARS_OFFS;
+-		if (year < 1970)
+-			year += 100;
+-	}
+ 
+ 	return mktime(year, mon, day, hour, min, sec);
+ }
+@@ -151,8 +146,8 @@ unsigned char rtc_cmos_read(unsigned char addr)
+ 	unsigned char val;
+ 
+ 	lock_cmos_prefix(addr);
+-	outb_p(addr, RTC_PORT(0));
+-	val = inb_p(RTC_PORT(1));
++	outb(addr, RTC_PORT(0));
++	val = inb(RTC_PORT(1));
+ 	lock_cmos_suffix(addr);
+ 	return val;
+ }
+@@ -161,8 +156,8 @@ EXPORT_SYMBOL(rtc_cmos_read);
+ void rtc_cmos_write(unsigned char val, unsigned char addr)
+ {
+ 	lock_cmos_prefix(addr);
+-	outb_p(addr, RTC_PORT(0));
+-	outb_p(val, RTC_PORT(1));
++	outb(addr, RTC_PORT(0));
++	outb(val, RTC_PORT(1));
+ 	lock_cmos_suffix(addr);
+ }
+ EXPORT_SYMBOL(rtc_cmos_write);
+diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
+new file mode 100644
+index 0000000..c0c68c1
+--- /dev/null
++++ b/arch/x86/kernel/setup.c
+@@ -0,0 +1,137 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/percpu.h>
++#include <asm/smp.h>
++#include <asm/percpu.h>
++#include <asm/sections.h>
++#include <asm/processor.h>
++#include <asm/setup.h>
++#include <asm/topology.h>
++#include <asm/mpspec.h>
++#include <asm/apicdef.h>
++
++unsigned int num_processors;
++unsigned disabled_cpus __cpuinitdata;
++/* Processor that is doing the boot up */
++unsigned int boot_cpu_physical_apicid = -1U;
++EXPORT_SYMBOL(boot_cpu_physical_apicid);
++
++DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
++
++/* Bitmask of physically existing CPUs */
++physid_mask_t phys_cpu_present_map;
++
++#if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_SMP)
++/*
++ * Copy data used in early init routines from the initial arrays to the
++ * per cpu data areas.  These arrays then become expendable and the
++ * *_early_ptr's are zeroed indicating that the static arrays are gone.
++ */
++static void __init setup_per_cpu_maps(void)
++{
++	int cpu;
++
++	for_each_possible_cpu(cpu) {
++		per_cpu(x86_cpu_to_apicid, cpu) = x86_cpu_to_apicid_init[cpu];
++		per_cpu(x86_bios_cpu_apicid, cpu) =
++						x86_bios_cpu_apicid_init[cpu];
++#ifdef CONFIG_NUMA
++		per_cpu(x86_cpu_to_node_map, cpu) =
++						x86_cpu_to_node_map_init[cpu];
++#endif
++	}
++
++	/* indicate the early static arrays will soon be gone */
++	x86_cpu_to_apicid_early_ptr = NULL;
++	x86_bios_cpu_apicid_early_ptr = NULL;
++#ifdef CONFIG_NUMA
++	x86_cpu_to_node_map_early_ptr = NULL;
++#endif
++}
++
++#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
++cpumask_t *cpumask_of_cpu_map __read_mostly;
++EXPORT_SYMBOL(cpumask_of_cpu_map);
++
++/* requires nr_cpu_ids to be initialized */
++static void __init setup_cpumask_of_cpu(void)
++{
++	int i;
++
++	/* alloc_bootmem zeroes memory */
++	cpumask_of_cpu_map = alloc_bootmem_low(sizeof(cpumask_t) * nr_cpu_ids);
++	for (i = 0; i < nr_cpu_ids; i++)
++		cpu_set(i, cpumask_of_cpu_map[i]);
++}
++#else
++static inline void setup_cpumask_of_cpu(void) { }
++#endif
++
++#ifdef CONFIG_X86_32
++/*
++ * Great future not-so-futuristic plan: make i386 and x86_64 do it
++ * the same way
++ */
++unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
++EXPORT_SYMBOL(__per_cpu_offset);
++#endif
++
++/*
++ * Great future plan:
++ * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
++ * Always point %gs to its beginning
++ */
++void __init setup_per_cpu_areas(void)
++{
++	int i, highest_cpu = 0;
++	unsigned long size;
++
++#ifdef CONFIG_HOTPLUG_CPU
++	prefill_possible_map();
++#endif
++
++	/* Copy section for each CPU (we discard the original) */
++	size = PERCPU_ENOUGH_ROOM;
++	printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n",
++			  size);
++
++	for_each_possible_cpu(i) {
++		char *ptr;
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++		ptr = alloc_bootmem_pages(size);
++#else
++		int node = early_cpu_to_node(i);
++		if (!node_online(node) || !NODE_DATA(node)) {
++			ptr = alloc_bootmem_pages(size);
++			printk(KERN_INFO
++			       "cpu %d has no node or node-local memory\n", i);
++		}
++		else
++			ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
++#endif
++		if (!ptr)
++			panic("Cannot allocate cpu data for CPU %d\n", i);
++#ifdef CONFIG_X86_64
++		cpu_pda(i)->data_offset = ptr - __per_cpu_start;
++#else
++		__per_cpu_offset[i] = ptr - __per_cpu_start;
++#endif
++		memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
++
++		highest_cpu = i;
++	}
++
++	nr_cpu_ids = highest_cpu + 1;
++	printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d\n", NR_CPUS, nr_cpu_ids);
++
++	/* Setup percpu data maps */
++	setup_per_cpu_maps();
++
++	/* Setup cpumask_of_cpu map */
++	setup_cpumask_of_cpu();
++}
++
++#endif
+diff --git a/arch/x86/kernel/setup64.c b/arch/x86/kernel/setup64.c
+index e24c456..aee0e82 100644
+--- a/arch/x86/kernel/setup64.c
++++ b/arch/x86/kernel/setup64.c
+@@ -11,6 +11,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/bitops.h>
+ #include <linux/module.h>
++#include <linux/kgdb.h>
+ #include <asm/pda.h>
+ #include <asm/pgtable.h>
+ #include <asm/processor.h>
+@@ -23,6 +24,7 @@
+ #include <asm/proto.h>
+ #include <asm/sections.h>
+ #include <asm/setup.h>
++#include <asm/genapic.h>
+ 
+ #ifndef CONFIG_DEBUG_BOOT_PARAMS
+ struct boot_params __initdata boot_params;
+@@ -72,8 +74,8 @@ int force_personality32 = 0;
+ Control non executable heap for 32bit processes.
+ To control the stack too use noexec=off
+ 
+-on	PROT_READ does not imply PROT_EXEC for 32bit processes
+-off	PROT_READ implies PROT_EXEC (default)
++on	PROT_READ does not imply PROT_EXEC for 32bit processes (default)
++off	PROT_READ implies PROT_EXEC
+ */
+ static int __init nonx32_setup(char *str)
+ {
+@@ -85,83 +87,6 @@ static int __init nonx32_setup(char *str)
+ }
+ __setup("noexec32=", nonx32_setup);
+ 
+-/*
+- * Copy data used in early init routines from the initial arrays to the
+- * per cpu data areas.  These arrays then become expendable and the
+- * *_early_ptr's are zeroed indicating that the static arrays are gone.
+- */
+-static void __init setup_per_cpu_maps(void)
+-{
+-	int cpu;
+-
+-	for_each_possible_cpu(cpu) {
+-#ifdef CONFIG_SMP
+-		if (per_cpu_offset(cpu)) {
+-#endif
+-			per_cpu(x86_cpu_to_apicid, cpu) =
+-						x86_cpu_to_apicid_init[cpu];
+-			per_cpu(x86_bios_cpu_apicid, cpu) =
+-						x86_bios_cpu_apicid_init[cpu];
+-#ifdef CONFIG_NUMA
+-			per_cpu(x86_cpu_to_node_map, cpu) =
+-						x86_cpu_to_node_map_init[cpu];
+-#endif
+-#ifdef CONFIG_SMP
+-		}
+-		else
+-			printk(KERN_NOTICE "per_cpu_offset zero for cpu %d\n",
+-									cpu);
+-#endif
+-	}
+-
+-	/* indicate the early static arrays will soon be gone */
+-	x86_cpu_to_apicid_early_ptr = NULL;
+-	x86_bios_cpu_apicid_early_ptr = NULL;
+-#ifdef CONFIG_NUMA
+-	x86_cpu_to_node_map_early_ptr = NULL;
+-#endif
+-}
+-
+-/*
+- * Great future plan:
+- * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
+- * Always point %gs to its beginning
+- */
+-void __init setup_per_cpu_areas(void)
+-{ 
+-	int i;
+-	unsigned long size;
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-	prefill_possible_map();
+-#endif
+-
+-	/* Copy section for each CPU (we discard the original) */
+-	size = PERCPU_ENOUGH_ROOM;
+-
+-	printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n", size);
+-	for_each_cpu_mask (i, cpu_possible_map) {
+-		char *ptr;
+-#ifndef CONFIG_NEED_MULTIPLE_NODES
+-		ptr = alloc_bootmem_pages(size);
+-#else
+-		int node = early_cpu_to_node(i);
+-
+-		if (!node_online(node) || !NODE_DATA(node))
+-			ptr = alloc_bootmem_pages(size);
+-		else
+-			ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
+-#endif
+-		if (!ptr)
+-			panic("Cannot allocate cpu data for CPU %d\n", i);
+-		cpu_pda(i)->data_offset = ptr - __per_cpu_start;
+-		memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+-	}
+-
+-	/* setup percpu data maps early */
+-	setup_per_cpu_maps();
+-} 
+-
+ void pda_init(int cpu)
+ { 
+ 	struct x8664_pda *pda = cpu_pda(cpu);
+@@ -327,6 +252,17 @@ void __cpuinit cpu_init (void)
+ 	load_TR_desc();
+ 	load_LDT(&init_mm.context);
+ 
++#ifdef CONFIG_KGDB
++	/*
++	 * If the kgdb is connected no debug regs should be altered.  This
++	 * is only applicable when KGDB and a KGDB I/O module are built
++	 * into the kernel and you are using early debugging with
++	 * kgdbwait. KGDB will control the kernel HW breakpoint registers.
++	 */
++	if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
++		arch_kgdb_ops.correct_hw_break();
++	else {
++#endif
+ 	/*
+ 	 * Clear all 6 debug registers:
+ 	 */
+@@ -337,8 +273,15 @@ void __cpuinit cpu_init (void)
+ 	set_debugreg(0UL, 3);
+ 	set_debugreg(0UL, 6);
+ 	set_debugreg(0UL, 7);
++#ifdef CONFIG_KGDB
++	/* If the kgdb is connected no debug regs should be altered. */
++	}
++#endif
+ 
+ 	fpu_init(); 
+ 
+ 	raw_local_save_flags(kernel_eflags);
++
++	if (is_uv_system())
++		uv_cpu_init();
+ }
+diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
+index 2b3e5d4..44cc9b9 100644
+--- a/arch/x86/kernel/setup_32.c
++++ b/arch/x86/kernel/setup_32.c
+@@ -39,6 +39,7 @@
+ #include <linux/efi.h>
+ #include <linux/init.h>
+ #include <linux/edd.h>
++#include <linux/iscsi_ibft.h>
+ #include <linux/nodemask.h>
+ #include <linux/kexec.h>
+ #include <linux/crash_dump.h>
+@@ -62,8 +63,9 @@
+ #include <asm/io.h>
+ #include <asm/vmi.h>
+ #include <setup_arch.h>
+-#include <bios_ebda.h>
++#include <asm/bios_ebda.h>
+ #include <asm/cacheflush.h>
++#include <asm/processor.h>
+ 
+ /* This value is set up by the early boot code to point to the value
+    immediately after the boot time page tables.  It contains a *physical*
+@@ -154,6 +156,8 @@ struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+ struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+ EXPORT_SYMBOL(boot_cpu_data);
+ 
++unsigned int def_to_bigsmp;
++
+ #ifndef CONFIG_X86_PAE
+ unsigned long mmu_cr4_features;
+ #else
+@@ -189,7 +193,7 @@ EXPORT_SYMBOL(ist_info);
+ extern void early_cpu_init(void);
+ extern int root_mountflags;
+ 
+-unsigned long saved_videomode;
++unsigned long saved_video_mode;
+ 
+ #define RAMDISK_IMAGE_START_MASK	0x07FF
+ #define RAMDISK_PROMPT_FLAG		0x8000
+@@ -227,7 +231,7 @@ static inline void copy_edd(void)
+ }
+ #endif
+ 
+-int __initdata user_defined_memmap = 0;
++int __initdata user_defined_memmap;
+ 
+ /*
+  * "mem=nopentium" disables the 4MB page tables.
+@@ -385,19 +389,58 @@ unsigned long __init find_max_low_pfn(void)
+ 	return max_low_pfn;
+ }
+ 
++#define BIOS_LOWMEM_KILOBYTES 0x413
++
+ /*
+- * workaround for Dell systems that neglect to reserve EBDA
++ * The BIOS places the EBDA/XBDA at the top of conventional
++ * memory, and usually decreases the reported amount of
++ * conventional memory (int 0x12) too. This also contains a
++ * workaround for Dell systems that neglect to reserve EBDA.
++ * The same workaround also avoids a problem with the AMD768MPX
++ * chipset: reserve a page before VGA to prevent PCI prefetch
++ * into it (errata #56). Usually the page is reserved anyways,
++ * unless you have no PS/2 mouse plugged in.
+  */
+ static void __init reserve_ebda_region(void)
+ {
+-	unsigned int addr;
+-	addr = get_bios_ebda();
+-	if (addr)
+-		reserve_bootmem(addr, PAGE_SIZE, BOOTMEM_DEFAULT);
++	unsigned int lowmem, ebda_addr;
++
++	/* To determine the position of the EBDA and the */
++	/* end of conventional memory, we need to look at */
++	/* the BIOS data area. In a paravirtual environment */
++	/* that area is absent. We'll just have to assume */
++	/* that the paravirt case can handle memory setup */
++	/* correctly, without our help. */
++	if (paravirt_enabled())
++		return;
++
++	/* end of low (conventional) memory */
++	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
++	lowmem <<= 10;
++
++	/* start of EBDA area */
++	ebda_addr = get_bios_ebda();
++
++	/* Fixup: bios puts an EBDA in the top 64K segment */
++	/* of conventional memory, but does not adjust lowmem. */
++	if ((lowmem - ebda_addr) <= 0x10000)
++		lowmem = ebda_addr;
++
++	/* Fixup: bios does not report an EBDA at all. */
++	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
++	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
++		lowmem = 0x9f000;
++
++	/* Paranoia: should never happen, but... */
++	if ((lowmem == 0) || (lowmem >= 0x100000))
++		lowmem = 0x9f000;
++
++	/* reserve all memory between lowmem and the 1MB mark */
++	reserve_bootmem(lowmem, 0x100000 - lowmem, BOOTMEM_DEFAULT);
+ }
+ 
+ #ifndef CONFIG_NEED_MULTIPLE_NODES
+-void __init setup_bootmem_allocator(void);
++static void __init setup_bootmem_allocator(void);
+ static unsigned long __init setup_memory(void)
+ {
+ 	/*
+@@ -432,7 +475,7 @@ static unsigned long __init setup_memory(void)
+ 	return max_low_pfn;
+ }
+ 
+-void __init zone_sizes_init(void)
++static void __init zone_sizes_init(void)
+ {
+ 	unsigned long max_zone_pfns[MAX_NR_ZONES];
+ 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+@@ -617,16 +660,9 @@ void __init setup_bootmem_allocator(void)
+ 	 */
+ 	reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
+ 
+-	/* reserve EBDA region, it's a 4K region */
++	/* reserve EBDA region */
+ 	reserve_ebda_region();
+ 
+-    /* could be an AMD 768MPX chipset. Reserve a page  before VGA to prevent
+-       PCI prefetch into it (errata #56). Usually the page is reserved anyways,
+-       unless you have no PS/2 mouse plugged in. */
+-	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+-	    boot_cpu_data.x86 == 6)
+-	     reserve_bootmem(0xa0000 - 4096, 4096, BOOTMEM_DEFAULT);
+-
+ #ifdef CONFIG_SMP
+ 	/*
+ 	 * But first pinch a few for the stack/trampoline stuff
+@@ -652,6 +688,8 @@ void __init setup_bootmem_allocator(void)
+ #endif
+ 	numa_kva_reserve();
+ 	reserve_crashkernel();
++
++	reserve_ibft_region();
+ }
+ 
+ /*
+@@ -687,6 +725,18 @@ char * __init __attribute__((weak)) memory_setup(void)
+ 	return machine_specific_memory_setup();
+ }
+ 
++#ifdef CONFIG_NUMA
++/*
++ * In the golden day, when everything among i386 and x86_64 will be
++ * integrated, this will not live here
++ */
++void *x86_cpu_to_node_map_early_ptr;
++int x86_cpu_to_node_map_init[NR_CPUS] = {
++	[0 ... NR_CPUS-1] = NUMA_NO_NODE
++};
++DEFINE_PER_CPU(int, x86_cpu_to_node_map) = NUMA_NO_NODE;
++#endif
++
+ /*
+  * 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
+@@ -714,7 +764,7 @@ void __init setup_arch(char **cmdline_p)
+ 	edid_info = boot_params.edid_info;
+ 	apm_info.bios = boot_params.apm_bios_info;
+ 	ist_info = boot_params.ist_info;
+-	saved_videomode = boot_params.hdr.vid_mode;
++	saved_video_mode = boot_params.hdr.vid_mode;
+ 	if( boot_params.sys_desc_table.length != 0 ) {
+ 		set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
+ 		machine_id = boot_params.sys_desc_table.table[0];
+@@ -763,10 +813,10 @@ void __init setup_arch(char **cmdline_p)
+ 		efi_init();
+ 
+ 	/* update e820 for memory not covered by WB MTRRs */
+-	find_max_pfn();
++	propagate_e820_map();
+ 	mtrr_bp_init();
+ 	if (mtrr_trim_uncached_memory(max_pfn))
+-		find_max_pfn();
++		propagate_e820_map();
+ 
+ 	max_low_pfn = setup_memory();
+ 
+@@ -820,6 +870,18 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	io_delay_init();
+ 
++#ifdef CONFIG_X86_SMP
++	/*
++	 * setup to use the early static init tables during kernel startup
++	 * X86_SMP will exclude sub-arches that don't deal well with it.
++	 */
++	x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
++	x86_bios_cpu_apicid_early_ptr = (void *)x86_bios_cpu_apicid_init;
++#ifdef CONFIG_NUMA
++	x86_cpu_to_node_map_early_ptr = (void *)x86_cpu_to_node_map_init;
++#endif
++#endif
++
+ #ifdef CONFIG_X86_GENERICARCH
+ 	generic_apic_probe();
+ #endif
+diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
+index f4f7ecf..17bdf23 100644
+--- a/arch/x86/kernel/setup_64.c
++++ b/arch/x86/kernel/setup_64.c
+@@ -33,6 +33,7 @@
+ #include <linux/acpi.h>
+ #include <linux/kallsyms.h>
+ #include <linux/edd.h>
++#include <linux/iscsi_ibft.h>
+ #include <linux/mmzone.h>
+ #include <linux/kexec.h>
+ #include <linux/cpufreq.h>
+@@ -58,7 +59,6 @@
+ #include <asm/mmu_context.h>
+ #include <asm/proto.h>
+ #include <asm/setup.h>
+-#include <asm/mach_apic.h>
+ #include <asm/numa.h>
+ #include <asm/sections.h>
+ #include <asm/dmi.h>
+@@ -66,7 +66,9 @@
+ #include <asm/mce.h>
+ #include <asm/ds.h>
+ #include <asm/topology.h>
++#include <asm/trampoline.h>
+ 
++#include <mach_apic.h>
+ #ifdef CONFIG_PARAVIRT
+ #include <asm/paravirt.h>
+ #else
+@@ -114,7 +116,7 @@ extern int root_mountflags;
+ 
+ char __initdata command_line[COMMAND_LINE_SIZE];
+ 
+-struct resource standard_io_resources[] = {
++static struct resource standard_io_resources[] = {
+ 	{ .name = "dma1", .start = 0x00, .end = 0x1f,
+ 		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+ 	{ .name = "pic1", .start = 0x20, .end = 0x21,
+@@ -248,6 +250,7 @@ static void __init reserve_crashkernel(void)
+ 				(unsigned long)(total_mem >> 20));
+ 		crashk_res.start = crash_base;
+ 		crashk_res.end   = crash_base + crash_size - 1;
++		insert_resource(&iomem_resource, &crashk_res);
+ 	}
+ }
+ #else
+@@ -322,6 +325,11 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	finish_e820_parsing();
+ 
++	/* after parse_early_param, so could debug it */
++	insert_resource(&iomem_resource, &code_resource);
++	insert_resource(&iomem_resource, &data_resource);
++	insert_resource(&iomem_resource, &bss_resource);
++
+ 	early_gart_iommu_check();
+ 
+ 	e820_register_active_regions(0, 0, -1UL);
+@@ -341,10 +349,12 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	check_efer();
+ 
+-	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
++	max_pfn_mapped = init_memory_mapping(0, (max_pfn_mapped << PAGE_SHIFT));
+ 	if (efi_enabled)
+ 		efi_init();
+ 
++	vsmp_init();
++
+ 	dmi_scan_machine();
+ 
+ 	io_delay_init();
+@@ -389,6 +399,8 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	early_res_to_bootmem();
+ 
++	dma32_reserve_bootmem();
++
+ #ifdef CONFIG_ACPI_SLEEP
+ 	/*
+ 	 * Reserve low memory region for sleep support.
+@@ -411,11 +423,14 @@ void __init setup_arch(char **cmdline_p)
+ 		unsigned long end_of_mem    = end_pfn << PAGE_SHIFT;
+ 
+ 		if (ramdisk_end <= end_of_mem) {
+-			reserve_bootmem_generic(ramdisk_image, ramdisk_size);
++			/*
++			 * don't need to reserve again, already reserved early
++			 * in x86_64_start_kernel, and early_res_to_bootmem
++			 * convert that to reserved in bootmem
++			 */
+ 			initrd_start = ramdisk_image + PAGE_OFFSET;
+ 			initrd_end = initrd_start+ramdisk_size;
+ 		} else {
+-			/* Assumes everything on node 0 */
+ 			free_bootmem(ramdisk_image, ramdisk_size);
+ 			printk(KERN_ERR "initrd extends beyond end of memory "
+ 			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+@@ -425,6 +440,9 @@ void __init setup_arch(char **cmdline_p)
+ 	}
+ #endif
+ 	reserve_crashkernel();
++
++	reserve_ibft_region();
++
+ 	paging_init();
+ 	map_vsyscall();
+ 
+@@ -450,7 +468,7 @@ void __init setup_arch(char **cmdline_p)
+ 	/*
+ 	 * We trust e820 completely. No explicit ROM probing in memory.
+ 	 */
+-	e820_reserve_resources(&code_resource, &data_resource, &bss_resource);
++	e820_reserve_resources();
+ 	e820_mark_nosave_regions();
+ 
+ 	/* request I/O space for devices used on all i[345]86 PCs */
+@@ -552,9 +570,9 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
+ 	bits = c->x86_coreid_bits;
+ 
+ 	/* Low order bits define the core id (index of core in socket) */
+-	c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
+-	/* Convert the APIC ID into the socket ID */
+-	c->phys_proc_id = phys_pkg_id(bits);
++	c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
++	/* Convert the initial APIC ID into the socket ID */
++	c->phys_proc_id = c->initial_apicid >> bits;
+ 
+ #ifdef CONFIG_NUMA
+ 	node = c->phys_proc_id;
+@@ -571,7 +589,7 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
+ 		   If that doesn't result in a usable node fall back to the
+ 		   path for the previous case.  */
+ 
+-		int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
++		int ht_nodeid = c->initial_apicid;
+ 
+ 		if (ht_nodeid >= 0 &&
+ 		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+@@ -677,7 +695,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ 
+ 	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+ 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+-	clear_bit(0*32+31, (unsigned long *)&c->x86_capability);
++	clear_cpu_cap(c, 0*32+31);
+ 
+ 	/* On C+ stepping K8 rep microcode works well for copy/memset */
+ 	level = cpuid_eax(1);
+@@ -721,6 +739,19 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ 
+ 	if (amd_apic_timer_broken())
+ 		disable_apic_timer = 1;
++
++	if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
++		unsigned long long tseg;
++
++		/*
++		 * Split up direct mapping around the TSEG SMM area.
++		 * Don't do it for gbpages because there seems very little
++		 * benefit in doing so.
++		 */
++		if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg) &&
++		(tseg >> PMD_SHIFT) < (max_pfn_mapped >> (PMD_SHIFT-PAGE_SHIFT)))
++			set_memory_4k((unsigned long)__va(tseg), 1);
++	}
+ }
+ 
+ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+@@ -813,7 +844,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
+ {
+ 	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+ 	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
+-		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ }
+ 
+ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+@@ -856,9 +887,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ 
+ 	if (c->x86 == 15)
+ 		c->x86_cache_alignment = c->x86_clflush_size * 2;
+-	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+-	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
+-		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ 	if (c->x86 == 6)
+ 		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+ 	set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
+@@ -867,6 +895,32 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ 	srat_detect_node();
+ }
+ 
++static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
++{
++	if (c->x86 == 0x6 && c->x86_model >= 0xf)
++		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++}
++
++static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
++{
++	/* Cache sizes */
++	unsigned n;
++
++	n = c->extended_cpuid_level;
++	if (n >= 0x80000008) {
++		unsigned eax = cpuid_eax(0x80000008);
++		c->x86_virt_bits = (eax >> 8) & 0xff;
++		c->x86_phys_bits = eax & 0xff;
++	}
++
++	if (c->x86 == 0x6 && c->x86_model >= 0xf) {
++		c->x86_cache_alignment = c->x86_clflush_size * 2;
++		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
++		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
++	}
++	set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
++}
++
+ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+ {
+ 	char *v = c->x86_vendor_id;
+@@ -875,6 +929,8 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+ 		c->x86_vendor = X86_VENDOR_AMD;
+ 	else if (!strcmp(v, "GenuineIntel"))
+ 		c->x86_vendor = X86_VENDOR_INTEL;
++	else if (!strcmp(v, "CentaurHauls"))
++		c->x86_vendor = X86_VENDOR_CENTAUR;
+ 	else
+ 		c->x86_vendor = X86_VENDOR_UNKNOWN;
+ }
+@@ -922,15 +978,16 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
+ 			c->x86 += (tfms >> 20) & 0xff;
+ 		if (c->x86 >= 0x6)
+ 			c->x86_model += ((tfms >> 16) & 0xF) << 4;
+-		if (c->x86_capability[0] & (1<<19))
++		if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
+ 			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+ 	} else {
+ 		/* Have CPUID level 0 only - unheard of */
+ 		c->x86 = 4;
+ 	}
+ 
++	c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff;
+ #ifdef CONFIG_SMP
+-	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
++	c->phys_proc_id = c->initial_apicid;
+ #endif
+ 	/* AMD-defined flags: level 0x80000001 */
+ 	xlvl = cpuid_eax(0x80000000);
+@@ -956,12 +1013,22 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
+ 	if (c->extended_cpuid_level >= 0x80000007)
+ 		c->x86_power = cpuid_edx(0x80000007);
+ 
++
++	clear_cpu_cap(c, X86_FEATURE_PAT);
++
+ 	switch (c->x86_vendor) {
+ 	case X86_VENDOR_AMD:
+ 		early_init_amd(c);
++		if (c->x86 >= 0xf && c->x86 <= 0x11)
++			set_cpu_cap(c, X86_FEATURE_PAT);
+ 		break;
+ 	case X86_VENDOR_INTEL:
+ 		early_init_intel(c);
++		if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15))
++			set_cpu_cap(c, X86_FEATURE_PAT);
++		break;
++	case X86_VENDOR_CENTAUR:
++		early_init_centaur(c);
+ 		break;
+ 	}
+ 
+@@ -999,6 +1066,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ 		init_intel(c);
+ 		break;
+ 
++	case X86_VENDOR_CENTAUR:
++		init_centaur(c);
++		break;
++
+ 	case X86_VENDOR_UNKNOWN:
+ 	default:
+ 		display_cacheinfo(c);
+@@ -1028,14 +1099,24 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ #endif
+ 	select_idle_routine(c);
+ 
+-	if (c != &boot_cpu_data)
+-		mtrr_ap_init();
+ #ifdef CONFIG_NUMA
+ 	numa_add_cpu(smp_processor_id());
+ #endif
+ 
+ }
+ 
++void __cpuinit identify_boot_cpu(void)
++{
++	identify_cpu(&boot_cpu_data);
++}
++
++void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
++{
++	BUG_ON(c == &boot_cpu_data);
++	identify_cpu(c);
++	mtrr_ap_init();
++}
++
+ static __init int setup_noclflush(char *arg)
+ {
+ 	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
+@@ -1064,123 +1145,3 @@ static __init int setup_disablecpuid(char *arg)
+ 	return 1;
+ }
+ __setup("clearcpuid=", setup_disablecpuid);
+-
+-/*
+- *	Get CPU information for use by the procfs.
+- */
+-
+-static int show_cpuinfo(struct seq_file *m, void *v)
+-{
+-	struct cpuinfo_x86 *c = v;
+-	int cpu = 0, i;
+-
+-#ifdef CONFIG_SMP
+-	cpu = c->cpu_index;
+-#endif
+-
+-	seq_printf(m, "processor\t: %u\n"
+-		   "vendor_id\t: %s\n"
+-		   "cpu family\t: %d\n"
+-		   "model\t\t: %d\n"
+-		   "model name\t: %s\n",
+-		   (unsigned)cpu,
+-		   c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+-		   c->x86,
+-		   (int)c->x86_model,
+-		   c->x86_model_id[0] ? c->x86_model_id : "unknown");
+-
+-	if (c->x86_mask || c->cpuid_level >= 0)
+-		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+-	else
+-		seq_printf(m, "stepping\t: unknown\n");
+-
+-	if (cpu_has(c, X86_FEATURE_TSC)) {
+-		unsigned int freq = cpufreq_quick_get((unsigned)cpu);
+-
+-		if (!freq)
+-			freq = cpu_khz;
+-		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
+-			   freq / 1000, (freq % 1000));
+-	}
+-
+-	/* Cache size */
+-	if (c->x86_cache_size >= 0)
+-		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
+-
+-#ifdef CONFIG_SMP
+-	if (smp_num_siblings * c->x86_max_cores > 1) {
+-		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+-		seq_printf(m, "siblings\t: %d\n",
+-			       cpus_weight(per_cpu(cpu_core_map, cpu)));
+-		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+-		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
+-	}
+-#endif
+-
+-	seq_printf(m,
+-		   "fpu\t\t: yes\n"
+-		   "fpu_exception\t: yes\n"
+-		   "cpuid level\t: %d\n"
+-		   "wp\t\t: yes\n"
+-		   "flags\t\t:",
+-		   c->cpuid_level);
+-
+-	for (i = 0; i < 32*NCAPINTS; i++)
+-		if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
+-			seq_printf(m, " %s", x86_cap_flags[i]);
+-
+-	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
+-		   c->loops_per_jiffy/(500000/HZ),
+-		   (c->loops_per_jiffy/(5000/HZ)) % 100);
+-
+-	if (c->x86_tlbsize > 0)
+-		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
+-	seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size);
+-	seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
+-
+-	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
+-		   c->x86_phys_bits, c->x86_virt_bits);
+-
+-	seq_printf(m, "power management:");
+-	for (i = 0; i < 32; i++) {
+-		if (c->x86_power & (1 << i)) {
+-			if (i < ARRAY_SIZE(x86_power_flags) &&
+-			    x86_power_flags[i])
+-				seq_printf(m, "%s%s",
+-					   x86_power_flags[i][0]?" ":"",
+-					   x86_power_flags[i]);
+-			else
+-				seq_printf(m, " [%d]", i);
+-		}
+-	}
+-
+-	seq_printf(m, "\n\n");
+-
+-	return 0;
+-}
+-
+-static void *c_start(struct seq_file *m, loff_t *pos)
+-{
+-	if (*pos == 0)	/* just in case, cpu 0 is not the first */
+-		*pos = first_cpu(cpu_online_map);
+-	if ((*pos) < NR_CPUS && cpu_online(*pos))
+-		return &cpu_data(*pos);
+-	return NULL;
+-}
+-
+-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+-{
+-	*pos = next_cpu(*pos, cpu_online_map);
+-	return c_start(m, pos);
+-}
+-
+-static void c_stop(struct seq_file *m, void *v)
+-{
+-}
+-
+-const struct seq_operations cpuinfo_op = {
+-	.start = c_start,
+-	.next =	c_next,
+-	.stop =	c_stop,
+-	.show =	show_cpuinfo,
+-};
+diff --git a/arch/x86/kernel/sigframe.h b/arch/x86/kernel/sigframe.h
+new file mode 100644
+index 0000000..72bbb51
+--- /dev/null
++++ b/arch/x86/kernel/sigframe.h
+@@ -0,0 +1,27 @@
++#ifdef CONFIG_X86_32
++struct sigframe {
++	char __user *pretcode;
++	int sig;
++	struct sigcontext sc;
++	struct _fpstate fpstate;
++	unsigned long extramask[_NSIG_WORDS-1];
++	char retcode[8];
++};
++
++struct rt_sigframe {
++	char __user *pretcode;
++	int sig;
++	struct siginfo __user *pinfo;
++	void __user *puc;
++	struct siginfo info;
++	struct ucontext uc;
++	struct _fpstate fpstate;
++	char retcode[8];
++};
++#else
++struct rt_sigframe {
++	char __user *pretcode;
++	struct ucontext uc;
++	struct siginfo info;
++};
++#endif
+diff --git a/arch/x86/kernel/sigframe_32.h b/arch/x86/kernel/sigframe_32.h
+deleted file mode 100644
+index 0b22217..0000000
+--- a/arch/x86/kernel/sigframe_32.h
++++ /dev/null
+@@ -1,21 +0,0 @@
+-struct sigframe
+-{
+-	char __user *pretcode;
+-	int sig;
+-	struct sigcontext sc;
+-	struct _fpstate fpstate;
+-	unsigned long extramask[_NSIG_WORDS-1];
+-	char retcode[8];
+-};
+-
+-struct rt_sigframe
+-{
+-	char __user *pretcode;
+-	int sig;
+-	struct siginfo __user *pinfo;
+-	void __user *puc;
+-	struct siginfo info;
+-	struct ucontext uc;
+-	struct _fpstate fpstate;
+-	char retcode[8];
+-};
+diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
+index 0157a6f..8e05e7f 100644
+--- a/arch/x86/kernel/signal_32.c
++++ b/arch/x86/kernel/signal_32.c
+@@ -4,32 +4,44 @@
+  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
+  */
++#include <linux/list.h>
+ 
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
++#include <linux/personality.h>
++#include <linux/binfmts.h>
++#include <linux/suspend.h>
+ #include <linux/kernel.h>
++#include <linux/ptrace.h>
+ #include <linux/signal.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
+ #include <linux/errno.h>
++#include <linux/sched.h>
+ #include <linux/wait.h>
+-#include <linux/unistd.h>
+-#include <linux/stddef.h>
+-#include <linux/personality.h>
+-#include <linux/suspend.h>
+-#include <linux/ptrace.h>
+ #include <linux/elf.h>
+-#include <linux/binfmts.h>
++#include <linux/smp.h>
++#include <linux/mm.h>
++
+ #include <asm/processor.h>
+ #include <asm/ucontext.h>
+ #include <asm/uaccess.h>
+ #include <asm/i387.h>
+ #include <asm/vdso.h>
+-#include "sigframe_32.h"
+ 
+-#define DEBUG_SIG 0
++#include "sigframe.h"
+ 
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+ 
++#define __FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_OF | \
++			 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
++			 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
++			 X86_EFLAGS_CF)
++
++#ifdef CONFIG_X86_32
++# define FIX_EFLAGS	(__FIX_EFLAGS | X86_EFLAGS_RF)
++#else
++# define FIX_EFLAGS	__FIX_EFLAGS
++#endif
++
+ /*
+  * Atomically swap in the new signal mask, and wait for a signal.
+  */
+@@ -46,10 +58,11 @@ sys_sigsuspend(int history0, int history1, old_sigset_t mask)
+ 	current->state = TASK_INTERRUPTIBLE;
+ 	schedule();
+ 	set_thread_flag(TIF_RESTORE_SIGMASK);
++
+ 	return -ERESTARTNOHAND;
+ }
+ 
+-asmlinkage int 
++asmlinkage int
+ sys_sigaction(int sig, const struct old_sigaction __user *act,
+ 	      struct old_sigaction __user *oact)
+ {
+@@ -58,10 +71,12 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
+ 
+ 	if (act) {
+ 		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_restorer, &act->sa_restorer))
+ 			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);
+@@ -74,6 +89,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
+ 		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ 		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+ 			return -EFAULT;
++
+ 		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ 		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ 	}
+@@ -81,10 +97,12 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
+ 	return ret;
+ }
+ 
+-asmlinkage int
+-sys_sigaltstack(unsigned long bx)
++asmlinkage int sys_sigaltstack(unsigned long bx)
+ {
+-	/* This is needed to make gcc realize it doesn't own the "struct pt_regs" */
++	/*
++	 * This is needed to make gcc realize it doesn't own the
++	 * "struct pt_regs"
++	 */
+ 	struct pt_regs *regs = (struct pt_regs *)&bx;
+ 	const stack_t __user *uss = (const stack_t __user *)bx;
+ 	stack_t __user *uoss = (stack_t __user *)regs->cx;
+@@ -96,9 +114,9 @@ sys_sigaltstack(unsigned long bx)
+ /*
+  * Do a signal return; undo the signal stack.
+  */
+-
+ static int
+-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax)
++restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
++		   unsigned long *pax)
+ {
+ 	unsigned int err = 0;
+ 
+@@ -120,37 +138,29 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
+ #define GET_SEG(seg)							\
+ 	{ unsigned short tmp;						\
+ 	  err |= __get_user(tmp, &sc->seg);				\
+-	  loadsegment(seg,tmp); }
+-
+-#define	FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_RF |		 \
+-			 X86_EFLAGS_OF | X86_EFLAGS_DF |		 \
+-			 X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \
+-			 X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF)
++	  loadsegment(seg, tmp); }
+ 
+ 	GET_SEG(gs);
+ 	COPY_SEG(fs);
+ 	COPY_SEG(es);
+ 	COPY_SEG(ds);
+-	COPY(di);
+-	COPY(si);
+-	COPY(bp);
+-	COPY(sp);
+-	COPY(bx);
+-	COPY(dx);
+-	COPY(cx);
+-	COPY(ip);
++	COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
++	COPY(dx); COPY(cx); COPY(ip);
+ 	COPY_SEG_STRICT(cs);
+ 	COPY_SEG_STRICT(ss);
+-	
++
+ 	{
+ 		unsigned int tmpflags;
++
+ 		err |= __get_user(tmpflags, &sc->flags);
+-		regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
++		regs->flags = (regs->flags & ~FIX_EFLAGS) |
++						(tmpflags & FIX_EFLAGS);
+ 		regs->orig_ax = -1;		/* disable syscall checks */
+ 	}
+ 
+ 	{
+-		struct _fpstate __user * buf;
++		struct _fpstate __user *buf;
++
+ 		err |= __get_user(buf, &sc->fpstate);
+ 		if (buf) {
+ 			if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
+@@ -158,6 +168,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
+ 			err |= restore_i387(buf);
+ 		} else {
+ 			struct task_struct *me = current;
++
+ 			if (used_math()) {
+ 				clear_fpu(me);
+ 				clear_used_math();
+@@ -165,24 +176,26 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
+ 		}
+ 	}
+ 
+-	err |= __get_user(*peax, &sc->ax);
++	err |= __get_user(*pax, &sc->ax);
+ 	return err;
+ 
+ badframe:
+ 	return 1;
+ }
+ 
+-asmlinkage int sys_sigreturn(unsigned long __unused)
++asmlinkage unsigned long sys_sigreturn(unsigned long __unused)
+ {
+-	struct pt_regs *regs = (struct pt_regs *) &__unused;
+-	struct sigframe __user *frame = (struct sigframe __user *)(regs->sp - 8);
++	struct sigframe __user *frame;
++	struct pt_regs *regs;
++	unsigned long ax;
+ 	sigset_t set;
+-	int ax;
++
++	regs = (struct pt_regs *) &__unused;
++	frame = (struct sigframe __user *)(regs->sp - 8);
+ 
+ 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ 		goto badframe;
+-	if (__get_user(set.sig[0], &frame->sc.oldmask)
+-	    || (_NSIG_WORDS > 1
++	if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1
+ 		&& __copy_from_user(&set.sig[1], &frame->extramask,
+ 				    sizeof(frame->extramask))))
+ 		goto badframe;
+@@ -192,33 +205,35 @@ asmlinkage int sys_sigreturn(unsigned long __unused)
+ 	current->blocked = set;
+ 	recalc_sigpending();
+ 	spin_unlock_irq(&current->sighand->siglock);
+-	
++
+ 	if (restore_sigcontext(regs, &frame->sc, &ax))
+ 		goto badframe;
+ 	return ax;
+ 
+ badframe:
+ 	if (show_unhandled_signals && printk_ratelimit()) {
+-		printk("%s%s[%d] bad frame in sigreturn frame:%p ip:%lx"
+-		       " sp:%lx oeax:%lx",
++		printk(KERN_INFO "%s%s[%d] bad frame in sigreturn frame:"
++			"%p ip:%lx sp:%lx oeax:%lx",
+ 		    task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
+ 		    current->comm, task_pid_nr(current), frame, regs->ip,
+ 		    regs->sp, regs->orig_ax);
+ 		print_vma_addr(" in ", regs->ip);
+-		printk("\n");
++		printk(KERN_CONT "\n");
+ 	}
+ 
+ 	force_sig(SIGSEGV, current);
++
+ 	return 0;
+-}	
++}
+ 
+ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
+ {
+-	struct pt_regs *regs = (struct pt_regs *) &__unused;
+-	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->sp - 4);
++	struct pt_regs *regs = (struct pt_regs *)&__unused;
++	struct rt_sigframe __user *frame;
++	unsigned long ax;
+ 	sigset_t set;
+-	int ax;
+ 
++	frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
+ 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ 		goto badframe;
+ 	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+@@ -229,7 +244,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
+ 	current->blocked = set;
+ 	recalc_sigpending();
+ 	spin_unlock_irq(&current->sighand->siglock);
+-	
++
+ 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
+ 		goto badframe;
+ 
+@@ -241,12 +256,11 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
+ badframe:
+ 	force_sig(SIGSEGV, current);
+ 	return 0;
+-}	
++}
+ 
+ /*
+  * Set up a signal frame.
+  */
+-
+ static int
+ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
+ 		 struct pt_regs *regs, unsigned long mask)
+@@ -277,9 +291,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
+ 
+ 	tmp = save_i387(fpstate);
+ 	if (tmp < 0)
+-	  err = 1;
++		err = 1;
+ 	else
+-	  err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
++		err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
+ 
+ 	/* non-iBCS2 extensions.. */
+ 	err |= __put_user(mask, &sc->oldmask);
+@@ -292,7 +306,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
+  * Determine which stack to use..
+  */
+ static inline void __user *
+-get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
++get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+ {
+ 	unsigned long sp;
+ 
+@@ -310,32 +324,30 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+ 	if (ka->sa.sa_flags & SA_ONSTACK) {
+ 		if (sas_ss_flags(sp) == 0)
+ 			sp = current->sas_ss_sp + current->sas_ss_size;
+-	}
+-
+-	/* This is the legacy signal stack switching. */
+-	else if ((regs->ss & 0xffff) != __USER_DS &&
+-		 !(ka->sa.sa_flags & SA_RESTORER) &&
+-		 ka->sa.sa_restorer) {
+-		sp = (unsigned long) ka->sa.sa_restorer;
++	} else {
++		/* This is the legacy signal stack switching. */
++		if ((regs->ss & 0xffff) != __USER_DS &&
++			!(ka->sa.sa_flags & SA_RESTORER) &&
++				ka->sa.sa_restorer)
++			sp = (unsigned long) ka->sa.sa_restorer;
+ 	}
+ 
+ 	sp -= frame_size;
+-	/* Align the stack pointer according to the i386 ABI,
+-	 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
++	/*
++	 * Align the stack pointer according to the i386 ABI,
++	 * i.e. so that on function entry ((sp + 4) & 15) == 0.
++	 */
+ 	sp = ((sp + 4) & -16ul) - 4;
++
+ 	return (void __user *) sp;
+ }
+ 
+-/* These symbols are defined with the addresses in the vsyscall page.
+-   See vsyscall-sigreturn.S.  */
+-extern void __user __kernel_sigreturn;
+-extern void __user __kernel_rt_sigreturn;
+-
+-static int setup_frame(int sig, struct k_sigaction *ka,
+-		       sigset_t *set, struct pt_regs * regs)
++static int
++setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
++	    struct pt_regs *regs)
+ {
+-	void __user *restorer;
+ 	struct sigframe __user *frame;
++	void __user *restorer;
+ 	int err = 0;
+ 	int usig;
+ 
+@@ -365,7 +377,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
+ 			goto give_sigsegv;
+ 	}
+ 
+-	if (current->binfmt->hasvdso)
++	if (current->mm->context.vdso)
+ 		restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn);
+ 	else
+ 		restorer = &frame->retcode;
+@@ -374,9 +386,9 @@ static int setup_frame(int sig, struct k_sigaction *ka,
+ 
+ 	/* Set up to return from userspace.  */
+ 	err |= __put_user(restorer, &frame->pretcode);
+-	 
++
+ 	/*
+-	 * This is popl %eax ; movl $,%eax ; int $0x80
++	 * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80
+ 	 *
+ 	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
+ 	 * reasons and because gdb uses it as a signature to notice
+@@ -390,32 +402,17 @@ static int setup_frame(int sig, struct k_sigaction *ka,
+ 		goto give_sigsegv;
+ 
+ 	/* Set up registers for signal handler */
+-	regs->sp = (unsigned long) frame;
+-	regs->ip = (unsigned long) ka->sa.sa_handler;
+-	regs->ax = (unsigned long) sig;
+-	regs->dx = (unsigned long) 0;
+-	regs->cx = (unsigned long) 0;
++	regs->sp = (unsigned long)frame;
++	regs->ip = (unsigned long)ka->sa.sa_handler;
++	regs->ax = (unsigned long)sig;
++	regs->dx = 0;
++	regs->cx = 0;
+ 
+ 	regs->ds = __USER_DS;
+ 	regs->es = __USER_DS;
+ 	regs->ss = __USER_DS;
+ 	regs->cs = __USER_CS;
+ 
+-	/*
+-	 * Clear TF when entering the signal handler, but
+-	 * notify any tracer that was single-stepping it.
+-	 * The tracer may want to single-step inside the
+-	 * handler too.
+-	 */
+-	regs->flags &= ~(TF_MASK | X86_EFLAGS_DF);
+-	if (test_thread_flag(TIF_SINGLESTEP))
+-		ptrace_notify(SIGTRAP);
+-
+-#if DEBUG_SIG
+-	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+-		current->comm, current->pid, frame, regs->ip, frame->pretcode);
+-#endif
+-
+ 	return 0;
+ 
+ give_sigsegv:
+@@ -424,10 +421,10 @@ give_sigsegv:
+ }
+ 
+ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+-			   sigset_t *set, struct pt_regs * regs)
++			  sigset_t *set, struct pt_regs *regs)
+ {
+-	void __user *restorer;
+ 	struct rt_sigframe __user *frame;
++	void __user *restorer;
+ 	int err = 0;
+ 	int usig;
+ 
+@@ -457,7 +454,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 			  &frame->uc.uc_stack.ss_flags);
+ 	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ 	err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
+-			        regs, set->sig[0]);
++				regs, set->sig[0]);
+ 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ 	if (err)
+ 		goto give_sigsegv;
+@@ -467,9 +464,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 	if (ka->sa.sa_flags & SA_RESTORER)
+ 		restorer = ka->sa.sa_restorer;
+ 	err |= __put_user(restorer, &frame->pretcode);
+-	 
++
+ 	/*
+-	 * This is movl $,%ax ; int $0x80
++	 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
+ 	 *
+ 	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
+ 	 * reasons and because gdb uses it as a signature to notice
+@@ -483,32 +480,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 		goto give_sigsegv;
+ 
+ 	/* Set up registers for signal handler */
+-	regs->sp = (unsigned long) frame;
+-	regs->ip = (unsigned long) ka->sa.sa_handler;
+-	regs->ax = (unsigned long) usig;
+-	regs->dx = (unsigned long) &frame->info;
+-	regs->cx = (unsigned long) &frame->uc;
++	regs->sp = (unsigned long)frame;
++	regs->ip = (unsigned long)ka->sa.sa_handler;
++	regs->ax = (unsigned long)usig;
++	regs->dx = (unsigned long)&frame->info;
++	regs->cx = (unsigned long)&frame->uc;
+ 
+ 	regs->ds = __USER_DS;
+ 	regs->es = __USER_DS;
+ 	regs->ss = __USER_DS;
+ 	regs->cs = __USER_CS;
+ 
+-	/*
+-	 * Clear TF when entering the signal handler, but
+-	 * notify any tracer that was single-stepping it.
+-	 * The tracer may want to single-step inside the
+-	 * handler too.
+-	 */
+-	regs->flags &= ~(TF_MASK | X86_EFLAGS_DF);
+-	if (test_thread_flag(TIF_SINGLESTEP))
+-		ptrace_notify(SIGTRAP);
+-
+-#if DEBUG_SIG
+-	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+-		current->comm, current->pid, frame, regs->ip, frame->pretcode);
+-#endif
+-
+ 	return 0;
+ 
+ give_sigsegv:
+@@ -517,33 +499,33 @@ give_sigsegv:
+ }
+ 
+ /*
+- * OK, we're invoking a handler
+- */	
+-
++ * OK, we're invoking a handler:
++ */
+ static int
+ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+-	      sigset_t *oldset,	struct pt_regs * regs)
++	      sigset_t *oldset, struct pt_regs *regs)
+ {
+ 	int ret;
+ 
+ 	/* Are we from a system call? */
+-	if (regs->orig_ax >= 0) {
++	if ((long)regs->orig_ax >= 0) {
+ 		/* If so, check system call restarting.. */
+ 		switch (regs->ax) {
+-		        case -ERESTART_RESTARTBLOCK:
+-			case -ERESTARTNOHAND:
++		case -ERESTART_RESTARTBLOCK:
++		case -ERESTARTNOHAND:
++			regs->ax = -EINTR;
++			break;
++
++		case -ERESTARTSYS:
++			if (!(ka->sa.sa_flags & SA_RESTART)) {
+ 				regs->ax = -EINTR;
+ 				break;
+-
+-			case -ERESTARTSYS:
+-				if (!(ka->sa.sa_flags & SA_RESTART)) {
+-					regs->ax = -EINTR;
+-					break;
+-				}
+-			/* fallthrough */
+-			case -ERESTARTNOINTR:
+-				regs->ax = regs->orig_ax;
+-				regs->ip -= 2;
++			}
++		/* fallthrough */
++		case -ERESTARTNOINTR:
++			regs->ax = regs->orig_ax;
++			regs->ip -= 2;
++			break;
+ 		}
+ 	}
+ 
+@@ -561,16 +543,32 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+ 	else
+ 		ret = setup_frame(sig, ka, oldset, regs);
+ 
+-	if (ret == 0) {
+-		spin_lock_irq(&current->sighand->siglock);
+-		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+-		if (!(ka->sa.sa_flags & SA_NODEFER))
+-			sigaddset(&current->blocked,sig);
+-		recalc_sigpending();
+-		spin_unlock_irq(&current->sighand->siglock);
+-	}
++	if (ret)
++		return ret;
+ 
+-	return ret;
++	/*
++	 * Clear the direction flag as per the ABI for function entry.
++	 */
++	regs->flags &= ~X86_EFLAGS_DF;
++
++	/*
++	 * Clear TF when entering the signal handler, but
++	 * notify any tracer that was single-stepping it.
++	 * The tracer may want to single-step inside the
++	 * handler too.
++	 */
++	regs->flags &= ~X86_EFLAGS_TF;
++	if (test_thread_flag(TIF_SINGLESTEP))
++		ptrace_notify(SIGTRAP);
++
++	spin_lock_irq(&current->sighand->siglock);
++	sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
++	if (!(ka->sa.sa_flags & SA_NODEFER))
++		sigaddset(&current->blocked, sig);
++	recalc_sigpending();
++	spin_unlock_irq(&current->sighand->siglock);
++
++	return 0;
+ }
+ 
+ /*
+@@ -580,18 +578,17 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+  */
+ static void do_signal(struct pt_regs *regs)
+ {
++	struct k_sigaction ka;
+ 	siginfo_t info;
+ 	int signr;
+-	struct k_sigaction ka;
+ 	sigset_t *oldset;
+ 
+ 	/*
+-	 * We want the common case to go fast, which
+-	 * is why we may in certain cases get here from
+-	 * kernel mode. Just return without doing anything
+- 	 * if so.  vm86 regs switched out by assembly code
+- 	 * before reaching here, so testing against kernel
+- 	 * CS suffices.
++	 * We want the common case to go fast, which is why we may in certain
++	 * cases get here from kernel mode. Just return without doing anything
++	 * if so.
++	 * X86_32: vm86 regs switched out by assembly code before reaching
++	 * here, so testing against kernel CS suffices.
+ 	 */
+ 	if (!user_mode(regs))
+ 		return;
+@@ -603,29 +600,31 @@ static void do_signal(struct pt_regs *regs)
+ 
+ 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ 	if (signr > 0) {
+-		/* Re-enable any watchpoints before delivering the
++		/*
++		 * Re-enable any watchpoints before delivering the
+ 		 * signal to user space. The processor register will
+ 		 * have been cleared if the watchpoint triggered
+ 		 * inside the kernel.
+ 		 */
+-		if (unlikely(current->thread.debugreg7))
++		if (current->thread.debugreg7)
+ 			set_debugreg(current->thread.debugreg7, 7);
+ 
+-		/* Whee!  Actually deliver the signal.  */
++		/* Whee! Actually deliver the signal.  */
+ 		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+-			/* a signal was successfully delivered; the saved
++			/*
++			 * a signal was successfully delivered; the saved
+ 			 * sigmask will have been stored in the signal frame,
+ 			 * and will be restored by sigreturn, so we can simply
+-			 * clear the TIF_RESTORE_SIGMASK flag */
++			 * clear the TIF_RESTORE_SIGMASK flag
++			 */
+ 			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ 				clear_thread_flag(TIF_RESTORE_SIGMASK);
+ 		}
+-
+ 		return;
+ 	}
+ 
+ 	/* Did we come from a system call? */
+-	if (regs->orig_ax >= 0) {
++	if ((long)regs->orig_ax >= 0) {
+ 		/* Restart the system call - no handlers present */
+ 		switch (regs->ax) {
+ 		case -ERESTARTNOHAND:
+@@ -642,8 +641,10 @@ static void do_signal(struct pt_regs *regs)
+ 		}
+ 	}
+ 
+-	/* if there's no signal to deliver, we just put the saved sigmask
+-	 * back */
++	/*
++	 * If there's no signal to deliver, we just put the saved sigmask
++	 * back.
++	 */
+ 	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ 		clear_thread_flag(TIF_RESTORE_SIGMASK);
+ 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+@@ -654,13 +655,12 @@ static void do_signal(struct pt_regs *regs)
+  * notification of userspace execution resumption
+  * - triggered by the TIF_WORK_MASK flags
+  */
+-__attribute__((regparm(3)))
+-void do_notify_resume(struct pt_regs *regs, void *_unused,
+-		      __u32 thread_info_flags)
++void
++do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
+ {
+ 	/* Pending single-step? */
+ 	if (thread_info_flags & _TIF_SINGLESTEP) {
+-		regs->flags |= TF_MASK;
++		regs->flags |= X86_EFLAGS_TF;
+ 		clear_thread_flag(TIF_SINGLESTEP);
+ 	}
+ 
+@@ -670,6 +670,6 @@ void do_notify_resume(struct pt_regs *regs, void *_unused,
+ 
+ 	if (thread_info_flags & _TIF_HRTICK_RESCHED)
+ 		hrtick_resched();
+-	
++
+ 	clear_thread_flag(TIF_IRET);
+ }
+diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
+index 1c83e51..ccb2a45 100644
+--- a/arch/x86/kernel/signal_64.c
++++ b/arch/x86/kernel/signal_64.c
+@@ -19,17 +19,28 @@
+ #include <linux/stddef.h>
+ #include <linux/personality.h>
+ #include <linux/compiler.h>
++#include <asm/processor.h>
+ #include <asm/ucontext.h>
+ #include <asm/uaccess.h>
+ #include <asm/i387.h>
+ #include <asm/proto.h>
+ #include <asm/ia32_unistd.h>
+ #include <asm/mce.h>
+-
+-/* #define DEBUG_SIG 1 */
++#include "sigframe.h"
+ 
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+ 
++#define __FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_OF | \
++			 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
++			 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
++			 X86_EFLAGS_CF)
++
++#ifdef CONFIG_X86_32
++# define FIX_EFLAGS	(__FIX_EFLAGS | X86_EFLAGS_RF)
++#else
++# define FIX_EFLAGS	__FIX_EFLAGS
++#endif
++
+ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+                sigset_t *set, struct pt_regs * regs); 
+ int ia32_setup_frame(int sig, struct k_sigaction *ka,
+@@ -46,16 +57,9 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+ /*
+  * Do a signal return; undo the signal stack.
+  */
+-
+-struct rt_sigframe
+-{
+-	char __user *pretcode;
+-	struct ucontext uc;
+-	struct siginfo info;
+-};
+-
+ static int
+-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long *prax)
++restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
++		   unsigned long *pax)
+ {
+ 	unsigned int err = 0;
+ 
+@@ -87,7 +91,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
+ 	{
+ 		unsigned int tmpflags;
+ 		err |= __get_user(tmpflags, &sc->flags);
+-		regs->flags = (regs->flags & ~0x40DD5) | (tmpflags & 0x40DD5);
++		regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
+ 		regs->orig_ax = -1;		/* disable syscall checks */
+ 	}
+ 
+@@ -108,7 +112,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
+ 		}
+ 	}
+ 
+-	err |= __get_user(*prax, &sc->ax);
++	err |= __get_user(*pax, &sc->ax);
+ 	return err;
+ 
+ badframe:
+@@ -121,13 +125,11 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
+ 	sigset_t set;
+ 	unsigned long ax;
+ 
+-	frame = (struct rt_sigframe __user *)(regs->sp - 8);
+-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) {
++	frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
++	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ 		goto badframe;
+-	} 
+-	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) { 
++	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ 		goto badframe;
+-	} 
+ 
+ 	sigdelsetmask(&set, ~_BLOCKABLE);
+ 	spin_lock_irq(&current->sighand->siglock);
+@@ -138,10 +140,6 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
+ 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
+ 		goto badframe;
+ 
+-#ifdef DEBUG_SIG
+-	printk("%d sigreturn ip:%lx sp:%lx frame:%p ax:%lx\n",current->pid,regs->ip,regs->sp,frame,ax);
+-#endif
+-
+ 	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
+ 		goto badframe;
+ 
+@@ -270,10 +268,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 	if (err)
+ 		goto give_sigsegv;
+ 
+-#ifdef DEBUG_SIG
+-	printk("%d old ip %lx old sp %lx old ax %lx\n", current->pid,regs->ip,regs->sp,regs->ax);
+-#endif
+-
+ 	/* Set up registers for signal handler */
+ 	regs->di = sig;
+ 	/* In case the signal handler was declared without prototypes */ 
+@@ -291,18 +285,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 	   even if the handler happens to be interrupting 32-bit code. */
+ 	regs->cs = __USER_CS;
+ 
+-	/* This, by contrast, has nothing to do with segment registers -
+-	   see include/asm-x86_64/uaccess.h for details. */
+-	set_fs(USER_DS);
+-
+-	regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
+-	if (test_thread_flag(TIF_SINGLESTEP))
+-		ptrace_notify(SIGTRAP);
+-#ifdef DEBUG_SIG
+-	printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%p\n",
+-		current->comm, current->pid, frame, regs->ip, frame->pretcode);
+-#endif
+-
+ 	return 0;
+ 
+ give_sigsegv:
+@@ -345,35 +327,29 @@ static long current_syscall_ret(struct pt_regs *regs)
+ 
+ static int
+ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+-		sigset_t *oldset, struct pt_regs *regs)
++	      sigset_t *oldset, struct pt_regs *regs)
+ {
+ 	int ret;
+ 
+-#ifdef DEBUG_SIG
+-	printk("handle_signal pid:%d sig:%lu ip:%lx sp:%lx regs=%p\n",
+-		current->pid, sig,
+-		regs->ip, regs->sp, regs);
+-#endif
+-
+ 	/* Are we from a system call? */
+ 	if (current_syscall(regs) >= 0) {
+ 		/* If so, check system call restarting.. */
+ 		switch (current_syscall_ret(regs)) {
+-		        case -ERESTART_RESTARTBLOCK:
+-			case -ERESTARTNOHAND:
+-				regs->ax = -EINTR;
+-				break;
++		case -ERESTART_RESTARTBLOCK:
++		case -ERESTARTNOHAND:
++			regs->ax = -EINTR;
++			break;
+ 
+-			case -ERESTARTSYS:
+-				if (!(ka->sa.sa_flags & SA_RESTART)) {
+-					regs->ax = -EINTR;
+-					break;
+-				}
+-				/* fallthrough */
+-			case -ERESTARTNOINTR:
+-				regs->ax = regs->orig_ax;
+-				regs->ip -= 2;
++		case -ERESTARTSYS:
++			if (!(ka->sa.sa_flags & SA_RESTART)) {
++				regs->ax = -EINTR;
+ 				break;
++			}
++		/* fallthrough */
++		case -ERESTARTNOINTR:
++			regs->ax = regs->orig_ax;
++			regs->ip -= 2;
++			break;
+ 		}
+ 	}
+ 
+@@ -396,6 +372,28 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+ 	ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ 
+ 	if (ret == 0) {
++		/*
++		 * This has nothing to do with segment registers,
++		 * despite the name.  This magic affects uaccess.h
++		 * macros' behavior.  Reset it to the normal setting.
++		 */
++		set_fs(USER_DS);
++
++		/*
++		 * Clear the direction flag as per the ABI for function entry.
++		 */
++		regs->flags &= ~X86_EFLAGS_DF;
++
++		/*
++		 * Clear TF when entering the signal handler, but
++		 * notify any tracer that was single-stepping it.
++		 * The tracer may want to single-step inside the
++		 * handler too.
++		 */
++		regs->flags &= ~X86_EFLAGS_TF;
++		if (test_thread_flag(TIF_SINGLESTEP))
++			ptrace_notify(SIGTRAP);
++
+ 		spin_lock_irq(&current->sighand->siglock);
+ 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ 		if (!(ka->sa.sa_flags & SA_NODEFER))
+@@ -420,10 +418,11 @@ static void do_signal(struct pt_regs *regs)
+ 	sigset_t *oldset;
+ 
+ 	/*
+-	 * We want the common case to go fast, which
+-	 * is why we may in certain cases get here from
+-	 * kernel mode. Just return without doing anything
++	 * We want the common case to go fast, which is why we may in certain
++	 * cases get here from kernel mode. Just return without doing anything
+ 	 * if so.
++	 * X86_32: vm86 regs switched out by assembly code before reaching
++	 * here, so testing against kernel CS suffices.
+ 	 */
+ 	if (!user_mode(regs))
+ 		return;
+@@ -473,22 +472,19 @@ static void do_signal(struct pt_regs *regs)
+ 		}
+ 	}
+ 
+-	/* if there's no signal to deliver, we just put the saved sigmask
+-	   back. */
++	/*
++	 * If there's no signal to deliver, we just put the saved sigmask
++	 * back.
++	 */
+ 	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ 		clear_thread_flag(TIF_RESTORE_SIGMASK);
+ 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ 	}
+ }
+ 
+-void
+-do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
++void do_notify_resume(struct pt_regs *regs, void *unused,
++		      __u32 thread_info_flags)
+ {
+-#ifdef DEBUG_SIG
+-	printk("do_notify_resume flags:%x ip:%lx sp:%lx caller:%p pending:%x\n",
+-	       thread_info_flags, regs->ip, regs->sp, __builtin_return_address(0),signal_pending(current));
+-#endif
+-	       
+ 	/* Pending single-step? */
+ 	if (thread_info_flags & _TIF_SINGLESTEP) {
+ 		regs->flags |= X86_EFLAGS_TF;
+@@ -502,7 +498,7 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
+ #endif /* CONFIG_X86_MCE */
+ 
+ 	/* deal with pending signal delivery */
+-	if (thread_info_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK))
++	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ 		do_signal(regs);
+ 
+ 	if (thread_info_flags & _TIF_HRTICK_RESCHED)
+diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
+new file mode 100644
+index 0000000..8f75893
+--- /dev/null
++++ b/arch/x86/kernel/smp.c
+@@ -0,0 +1,343 @@
++/*
++ *	Intel SMP support routines.
++ *
++ *	(c) 1995 Alan Cox, Building #3 <alan at redhat.com>
++ *	(c) 1998-99, 2000 Ingo Molnar <mingo at redhat.com>
++ *      (c) 2002,2003 Andi Kleen, SuSE Labs.
++ *
++ *	i386 and x86_64 integration by Glauber Costa <gcosta at redhat.com>
++ *
++ *	This code is released under the GNU General Public License version 2 or
++ *	later.
++ */
++
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/cpu.h>
++
++#include <asm/mtrr.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/proto.h>
++#include <mach_ipi.h>
++#include <mach_apic.h>
++/*
++ *	Some notes on x86 processor bugs affecting SMP operation:
++ *
++ *	Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
++ *	The Linux implications for SMP are handled as follows:
++ *
++ *	Pentium III / [Xeon]
++ *		None of the E1AP-E3AP errata are visible to the user.
++ *
++ *	E1AP.	see PII A1AP
++ *	E2AP.	see PII A2AP
++ *	E3AP.	see PII A3AP
++ *
++ *	Pentium II / [Xeon]
++ *		None of the A1AP-A3AP errata are visible to the user.
++ *
++ *	A1AP.	see PPro 1AP
++ *	A2AP.	see PPro 2AP
++ *	A3AP.	see PPro 7AP
++ *
++ *	Pentium Pro
++ *		None of 1AP-9AP errata are visible to the normal user,
++ *	except occasional delivery of 'spurious interrupt' as trap #15.
++ *	This is very rare and a non-problem.
++ *
++ *	1AP.	Linux maps APIC as non-cacheable
++ *	2AP.	worked around in hardware
++ *	3AP.	fixed in C0 and above steppings microcode update.
++ *		Linux does not use excessive STARTUP_IPIs.
++ *	4AP.	worked around in hardware
++ *	5AP.	symmetric IO mode (normal Linux operation) not affected.
++ *		'noapic' mode has vector 0xf filled out properly.
++ *	6AP.	'noapic' mode might be affected - fixed in later steppings
++ *	7AP.	We do not assume writes to the LVT deassering IRQs
++ *	8AP.	We do not enable low power mode (deep sleep) during MP bootup
++ *	9AP.	We do not use mixed mode
++ *
++ *	Pentium
++ *		There is a marginal case where REP MOVS on 100MHz SMP
++ *	machines with B stepping processors can fail. XXX should provide
++ *	an L1cache=Writethrough or L1cache=off option.
++ *
++ *		B stepping CPUs may hang. There are hardware work arounds
++ *	for this. We warn about it in case your board doesn't have the work
++ *	arounds. Basically that's so I can tell anyone with a B stepping
++ *	CPU and SMP problems "tough".
++ *
++ *	Specific items [From Pentium Processor Specification Update]
++ *
++ *	1AP.	Linux doesn't use remote read
++ *	2AP.	Linux doesn't trust APIC errors
++ *	3AP.	We work around this
++ *	4AP.	Linux never generated 3 interrupts of the same priority
++ *		to cause a lost local interrupt.
++ *	5AP.	Remote read is never used
++ *	6AP.	not affected - worked around in hardware
++ *	7AP.	not affected - worked around in hardware
++ *	8AP.	worked around in hardware - we get explicit CS errors if not
++ *	9AP.	only 'noapic' mode affected. Might generate spurious
++ *		interrupts, we log only the first one and count the
++ *		rest silently.
++ *	10AP.	not affected - worked around in hardware
++ *	11AP.	Linux reads the APIC between writes to avoid this, as per
++ *		the documentation. Make sure you preserve this as it affects
++ *		the C stepping chips too.
++ *	12AP.	not affected - worked around in hardware
++ *	13AP.	not affected - worked around in hardware
++ *	14AP.	we always deassert INIT during bootup
++ *	15AP.	not affected - worked around in hardware
++ *	16AP.	not affected - worked around in hardware
++ *	17AP.	not affected - worked around in hardware
++ *	18AP.	not affected - worked around in hardware
++ *	19AP.	not affected - worked around in BIOS
++ *
++ *	If this sounds worrying believe me these bugs are either ___RARE___,
++ *	or are signal timing bugs worked around in hardware and there's
++ *	about nothing of note with C stepping upwards.
++ */
++
++/*
++ * this function sends a 'reschedule' IPI to another CPU.
++ * it goes straight through and wastes no time serializing
++ * anything. Worst case is that we lose a reschedule ...
++ */
++static void native_smp_send_reschedule(int cpu)
++{
++	if (unlikely(cpu_is_offline(cpu))) {
++		WARN_ON(1);
++		return;
++	}
++	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
++}
++
++/*
++ * Structure and data for smp_call_function(). This is designed to minimise
++ * static memory requirements. It also looks cleaner.
++ */
++static DEFINE_SPINLOCK(call_lock);
++
++struct call_data_struct {
++	void (*func) (void *info);
++	void *info;
++	atomic_t started;
++	atomic_t finished;
++	int wait;
++};
++
++void lock_ipi_call_lock(void)
++{
++	spin_lock_irq(&call_lock);
++}
++
++void unlock_ipi_call_lock(void)
++{
++	spin_unlock_irq(&call_lock);
++}
++
++static struct call_data_struct *call_data;
++
++static void __smp_call_function(void (*func) (void *info), void *info,
++				int nonatomic, int wait)
++{
++	struct call_data_struct data;
++	int cpus = num_online_cpus() - 1;
++
++	if (!cpus)
++		return;
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	mb();
++
++	/* Send a message to all other CPUs and wait for them to respond */
++	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (wait)
++		while (atomic_read(&data.finished) != cpus)
++			cpu_relax();
++}
++
++
++/**
++ * smp_call_function_mask(): Run a function on a set of other CPUs.
++ * @mask: The set of cpus to run on.  Must not include the current cpu.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @wait: If true, wait (atomically) until function has completed on other CPUs.
++ *
++  * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++static int
++native_smp_call_function_mask(cpumask_t mask,
++			      void (*func)(void *), void *info,
++			      int wait)
++{
++	struct call_data_struct data;
++	cpumask_t allbutself;
++	int cpus;
++
++	/* Can deadlock when called with interrupts disabled */
++	WARN_ON(irqs_disabled());
++
++	/* Holding any lock stops cpus from going down. */
++	spin_lock(&call_lock);
++
++	allbutself = cpu_online_map;
++	cpu_clear(smp_processor_id(), allbutself);
++
++	cpus_and(mask, mask, allbutself);
++	cpus = cpus_weight(mask);
++
++	if (!cpus) {
++		spin_unlock(&call_lock);
++		return 0;
++	}
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	wmb();
++
++	/* Send a message to other CPUs */
++	if (cpus_equal(mask, allbutself))
++		send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++	else
++		send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (wait)
++		while (atomic_read(&data.finished) != cpus)
++			cpu_relax();
++	spin_unlock(&call_lock);
++
++	return 0;
++}
++
++static void stop_this_cpu(void *dummy)
++{
++	local_irq_disable();
++	/*
++	 * Remove this CPU:
++	 */
++	cpu_clear(smp_processor_id(), cpu_online_map);
++	disable_local_APIC();
++	if (hlt_works(smp_processor_id()))
++		for (;;) halt();
++	for (;;);
++}
++
++/*
++ * this function calls the 'stop' function on all other CPUs in the system.
++ */
++
++static void native_smp_send_stop(void)
++{
++	int nolock;
++	unsigned long flags;
++
++	if (reboot_force)
++		return;
++
++	/* Don't deadlock on the call lock in panic */
++	nolock = !spin_trylock(&call_lock);
++	local_irq_save(flags);
++	__smp_call_function(stop_this_cpu, NULL, 0, 0);
++	if (!nolock)
++		spin_unlock(&call_lock);
++	disable_local_APIC();
++	local_irq_restore(flags);
++}
++
++/*
++ * Reschedule call back. Nothing to do,
++ * all the work is done automatically when
++ * we return from the interrupt.
++ */
++void smp_reschedule_interrupt(struct pt_regs *regs)
++{
++	ack_APIC_irq();
++#ifdef CONFIG_X86_32
++	__get_cpu_var(irq_stat).irq_resched_count++;
++#else
++	add_pda(irq_resched_count, 1);
++#endif
++}
++
++void smp_call_function_interrupt(struct pt_regs *regs)
++{
++	void (*func) (void *info) = call_data->func;
++	void *info = call_data->info;
++	int wait = call_data->wait;
++
++	ack_APIC_irq();
++	/*
++	 * Notify initiating CPU that I've grabbed the data and am
++	 * about to execute the function
++	 */
++	mb();
++	atomic_inc(&call_data->started);
++	/*
++	 * At this point the info structure may be out of scope unless wait==1
++	 */
++	irq_enter();
++	(*func)(info);
++#ifdef CONFIG_X86_32
++	__get_cpu_var(irq_stat).irq_call_count++;
++#else
++	add_pda(irq_call_count, 1);
++#endif
++	irq_exit();
++
++	if (wait) {
++		mb();
++		atomic_inc(&call_data->finished);
++	}
++}
++
++struct smp_ops smp_ops = {
++	.smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
++	.smp_prepare_cpus = native_smp_prepare_cpus,
++	.cpu_up = native_cpu_up,
++	.smp_cpus_done = native_smp_cpus_done,
++
++	.smp_send_stop = native_smp_send_stop,
++	.smp_send_reschedule = native_smp_send_reschedule,
++	.smp_call_function_mask = native_smp_call_function_mask,
++};
++EXPORT_SYMBOL_GPL(smp_ops);
++
+diff --git a/arch/x86/kernel/smp_32.c b/arch/x86/kernel/smp_32.c
+deleted file mode 100644
+index dc0cde9..0000000
+--- a/arch/x86/kernel/smp_32.c
++++ /dev/null
+@@ -1,712 +0,0 @@
+-/*
+- *	Intel SMP support routines.
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- *	(c) 1998-99, 2000 Ingo Molnar <mingo at redhat.com>
+- *
+- *	This code is released under the GNU General Public License version 2 or
+- *	later.
+- */
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/cache.h>
+-#include <linux/interrupt.h>
+-#include <linux/cpu.h>
+-#include <linux/module.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/tlbflush.h>
+-#include <asm/mmu_context.h>
+-#include <mach_apic.h>
+-
+-/*
+- *	Some notes on x86 processor bugs affecting SMP operation:
+- *
+- *	Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
+- *	The Linux implications for SMP are handled as follows:
+- *
+- *	Pentium III / [Xeon]
+- *		None of the E1AP-E3AP errata are visible to the user.
+- *
+- *	E1AP.	see PII A1AP
+- *	E2AP.	see PII A2AP
+- *	E3AP.	see PII A3AP
+- *
+- *	Pentium II / [Xeon]
+- *		None of the A1AP-A3AP errata are visible to the user.
+- *
+- *	A1AP.	see PPro 1AP
+- *	A2AP.	see PPro 2AP
+- *	A3AP.	see PPro 7AP
+- *
+- *	Pentium Pro
+- *		None of 1AP-9AP errata are visible to the normal user,
+- *	except occasional delivery of 'spurious interrupt' as trap #15.
+- *	This is very rare and a non-problem.
+- *
+- *	1AP.	Linux maps APIC as non-cacheable
+- *	2AP.	worked around in hardware
+- *	3AP.	fixed in C0 and above steppings microcode update.
+- *		Linux does not use excessive STARTUP_IPIs.
+- *	4AP.	worked around in hardware
+- *	5AP.	symmetric IO mode (normal Linux operation) not affected.
+- *		'noapic' mode has vector 0xf filled out properly.
+- *	6AP.	'noapic' mode might be affected - fixed in later steppings
+- *	7AP.	We do not assume writes to the LVT deassering IRQs
+- *	8AP.	We do not enable low power mode (deep sleep) during MP bootup
+- *	9AP.	We do not use mixed mode
+- *
+- *	Pentium
+- *		There is a marginal case where REP MOVS on 100MHz SMP
+- *	machines with B stepping processors can fail. XXX should provide
+- *	an L1cache=Writethrough or L1cache=off option.
+- *
+- *		B stepping CPUs may hang. There are hardware work arounds
+- *	for this. We warn about it in case your board doesn't have the work
+- *	arounds. Basically that's so I can tell anyone with a B stepping
+- *	CPU and SMP problems "tough".
+- *
+- *	Specific items [From Pentium Processor Specification Update]
+- *
+- *	1AP.	Linux doesn't use remote read
+- *	2AP.	Linux doesn't trust APIC errors
+- *	3AP.	We work around this
+- *	4AP.	Linux never generated 3 interrupts of the same priority
+- *		to cause a lost local interrupt.
+- *	5AP.	Remote read is never used
+- *	6AP.	not affected - worked around in hardware
+- *	7AP.	not affected - worked around in hardware
+- *	8AP.	worked around in hardware - we get explicit CS errors if not
+- *	9AP.	only 'noapic' mode affected. Might generate spurious
+- *		interrupts, we log only the first one and count the
+- *		rest silently.
+- *	10AP.	not affected - worked around in hardware
+- *	11AP.	Linux reads the APIC between writes to avoid this, as per
+- *		the documentation. Make sure you preserve this as it affects
+- *		the C stepping chips too.
+- *	12AP.	not affected - worked around in hardware
+- *	13AP.	not affected - worked around in hardware
+- *	14AP.	we always deassert INIT during bootup
+- *	15AP.	not affected - worked around in hardware
+- *	16AP.	not affected - worked around in hardware
+- *	17AP.	not affected - worked around in hardware
+- *	18AP.	not affected - worked around in hardware
+- *	19AP.	not affected - worked around in BIOS
+- *
+- *	If this sounds worrying believe me these bugs are either ___RARE___,
+- *	or are signal timing bugs worked around in hardware and there's
+- *	about nothing of note with C stepping upwards.
+- */
+-
+-DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, };
+-
+-/*
+- * the following functions deal with sending IPIs between CPUs.
+- *
+- * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
+- */
+-
+-static inline int __prepare_ICR (unsigned int shortcut, int vector)
+-{
+-	unsigned int icr = shortcut | APIC_DEST_LOGICAL;
+-
+-	switch (vector) {
+-	default:
+-		icr |= APIC_DM_FIXED | vector;
+-		break;
+-	case NMI_VECTOR:
+-		icr |= APIC_DM_NMI;
+-		break;
+-	}
+-	return icr;
+-}
+-
+-static inline int __prepare_ICR2 (unsigned int mask)
+-{
+-	return SET_APIC_DEST_FIELD(mask);
+-}
+-
+-void __send_IPI_shortcut(unsigned int shortcut, int vector)
+-{
+-	/*
+-	 * Subtle. In the case of the 'never do double writes' workaround
+-	 * we have to lock out interrupts to be safe.  As we don't care
+-	 * of the value read we use an atomic rmw access to avoid costly
+-	 * cli/sti.  Otherwise we use an even cheaper single atomic write
+-	 * to the APIC.
+-	 */
+-	unsigned int cfg;
+-
+-	/*
+-	 * Wait for idle.
+-	 */
+-	apic_wait_icr_idle();
+-
+-	/*
+-	 * No need to touch the target chip field
+-	 */
+-	cfg = __prepare_ICR(shortcut, vector);
+-
+-	/*
+-	 * Send the IPI. The write to APIC_ICR fires this off.
+-	 */
+-	apic_write_around(APIC_ICR, cfg);
+-}
+-
+-void send_IPI_self(int vector)
+-{
+-	__send_IPI_shortcut(APIC_DEST_SELF, vector);
+-}
+-
+-/*
+- * This is used to send an IPI with no shorthand notation (the destination is
+- * specified in bits 56 to 63 of the ICR).
+- */
+-static inline void __send_IPI_dest_field(unsigned long mask, int vector)
+-{
+-	unsigned long cfg;
+-
+-	/*
+-	 * Wait for idle.
+-	 */
+-	if (unlikely(vector == NMI_VECTOR))
+-		safe_apic_wait_icr_idle();
+-	else
+-		apic_wait_icr_idle();
+-		
+-	/*
+-	 * prepare target chip field
+-	 */
+-	cfg = __prepare_ICR2(mask);
+-	apic_write_around(APIC_ICR2, cfg);
+-		
+-	/*
+-	 * program the ICR 
+-	 */
+-	cfg = __prepare_ICR(0, vector);
+-			
+-	/*
+-	 * Send the IPI. The write to APIC_ICR fires this off.
+-	 */
+-	apic_write_around(APIC_ICR, cfg);
+-}
+-
+-/*
+- * This is only used on smaller machines.
+- */
+-void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
+-{
+-	unsigned long mask = cpus_addr(cpumask)[0];
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
+-	__send_IPI_dest_field(mask, vector);
+-	local_irq_restore(flags);
+-}
+-
+-void send_IPI_mask_sequence(cpumask_t mask, int vector)
+-{
+-	unsigned long flags;
+-	unsigned int query_cpu;
+-
+-	/*
+-	 * Hack. The clustered APIC addressing mode doesn't allow us to send 
+-	 * to an arbitrary mask, so I do a unicasts to each CPU instead. This 
+-	 * should be modified to do 1 message per cluster ID - mbligh
+-	 */ 
+-
+-	local_irq_save(flags);
+-	for_each_possible_cpu(query_cpu) {
+-		if (cpu_isset(query_cpu, mask)) {
+-			__send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
+-					      vector);
+-		}
+-	}
+-	local_irq_restore(flags);
+-}
+-
+-#include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */
+-
+-/*
+- *	Smarter SMP flushing macros. 
+- *		c/o Linus Torvalds.
+- *
+- *	These mean you can really definitely utterly forget about
+- *	writing to user space from interrupts. (Its not allowed anyway).
+- *
+- *	Optimizations Manfred Spraul <manfred at colorfullife.com>
+- */
+-
+-static cpumask_t flush_cpumask;
+-static struct mm_struct * flush_mm;
+-static unsigned long flush_va;
+-static DEFINE_SPINLOCK(tlbstate_lock);
+-
+-/*
+- * We cannot call mmdrop() because we are in interrupt context,
+- * instead update mm->cpu_vm_mask.
+- *
+- * We need to reload %cr3 since the page tables may be going
+- * away from under us..
+- */
+-void leave_mm(int cpu)
+-{
+-	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
+-		BUG();
+-	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
+-	load_cr3(swapper_pg_dir);
+-}
+-EXPORT_SYMBOL_GPL(leave_mm);
+-
+-/*
+- *
+- * The flush IPI assumes that a thread switch happens in this order:
+- * [cpu0: the cpu that switches]
+- * 1) switch_mm() either 1a) or 1b)
+- * 1a) thread switch to a different mm
+- * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
+- * 	Stop ipi delivery for the old mm. This is not synchronized with
+- * 	the other cpus, but smp_invalidate_interrupt ignore flush ipis
+- * 	for the wrong mm, and in the worst case we perform a superfluous
+- * 	tlb flush.
+- * 1a2) set cpu_tlbstate to TLBSTATE_OK
+- * 	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
+- *	was in lazy tlb mode.
+- * 1a3) update cpu_tlbstate[].active_mm
+- * 	Now cpu0 accepts tlb flushes for the new mm.
+- * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
+- * 	Now the other cpus will send tlb flush ipis.
+- * 1a4) change cr3.
+- * 1b) thread switch without mm change
+- *	cpu_tlbstate[].active_mm is correct, cpu0 already handles
+- *	flush ipis.
+- * 1b1) set cpu_tlbstate to TLBSTATE_OK
+- * 1b2) test_and_set the cpu bit in cpu_vm_mask.
+- * 	Atomically set the bit [other cpus will start sending flush ipis],
+- * 	and test the bit.
+- * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
+- * 2) switch %%esp, ie current
+- *
+- * The interrupt must handle 2 special cases:
+- * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
+- * - the cpu performs speculative tlb reads, i.e. even if the cpu only
+- *   runs in kernel space, the cpu could load tlb entries for user space
+- *   pages.
+- *
+- * The good news is that cpu_tlbstate is local to each cpu, no
+- * write/read ordering problems.
+- */
+-
+-/*
+- * TLB flush IPI:
+- *
+- * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
+- * 2) Leave the mm if we are in the lazy tlb mode.
+- */
+-
+-void smp_invalidate_interrupt(struct pt_regs *regs)
+-{
+-	unsigned long cpu;
+-
+-	cpu = get_cpu();
+-
+-	if (!cpu_isset(cpu, flush_cpumask))
+-		goto out;
+-		/* 
+-		 * This was a BUG() but until someone can quote me the
+-		 * line from the intel manual that guarantees an IPI to
+-		 * multiple CPUs is retried _only_ on the erroring CPUs
+-		 * its staying as a return
+-		 *
+-		 * BUG();
+-		 */
+-		 
+-	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
+-		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
+-			if (flush_va == TLB_FLUSH_ALL)
+-				local_flush_tlb();
+-			else
+-				__flush_tlb_one(flush_va);
+-		} else
+-			leave_mm(cpu);
+-	}
+-	ack_APIC_irq();
+-	smp_mb__before_clear_bit();
+-	cpu_clear(cpu, flush_cpumask);
+-	smp_mb__after_clear_bit();
+-out:
+-	put_cpu_no_resched();
+-	__get_cpu_var(irq_stat).irq_tlb_count++;
+-}
+-
+-void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
+-			     unsigned long va)
+-{
+-	cpumask_t cpumask = *cpumaskp;
+-
+-	/*
+-	 * A couple of (to be removed) sanity checks:
+-	 *
+-	 * - current CPU must not be in mask
+-	 * - mask must exist :)
+-	 */
+-	BUG_ON(cpus_empty(cpumask));
+-	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
+-	BUG_ON(!mm);
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-	/* If a CPU which we ran on has gone down, OK. */
+-	cpus_and(cpumask, cpumask, cpu_online_map);
+-	if (unlikely(cpus_empty(cpumask)))
+-		return;
+-#endif
+-
+-	/*
+-	 * i'm not happy about this global shared spinlock in the
+-	 * MM hot path, but we'll see how contended it is.
+-	 * AK: x86-64 has a faster method that could be ported.
+-	 */
+-	spin_lock(&tlbstate_lock);
+-	
+-	flush_mm = mm;
+-	flush_va = va;
+-	cpus_or(flush_cpumask, cpumask, flush_cpumask);
+-	/*
+-	 * We have to send the IPI only to
+-	 * CPUs affected.
+-	 */
+-	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
+-
+-	while (!cpus_empty(flush_cpumask))
+-		/* nothing. lockup detection does not belong here */
+-		cpu_relax();
+-
+-	flush_mm = NULL;
+-	flush_va = 0;
+-	spin_unlock(&tlbstate_lock);
+-}
+-	
+-void flush_tlb_current_task(void)
+-{
+-	struct mm_struct *mm = current->mm;
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	local_flush_tlb();
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-	preempt_enable();
+-}
+-
+-void flush_tlb_mm (struct mm_struct * mm)
+-{
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	if (current->active_mm == mm) {
+-		if (current->mm)
+-			local_flush_tlb();
+-		else
+-			leave_mm(smp_processor_id());
+-	}
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-
+-	preempt_enable();
+-}
+-
+-void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+-{
+-	struct mm_struct *mm = vma->vm_mm;
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	if (current->active_mm == mm) {
+-		if(current->mm)
+-			__flush_tlb_one(va);
+-		 else
+-		 	leave_mm(smp_processor_id());
+-	}
+-
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, va);
+-
+-	preempt_enable();
+-}
+-EXPORT_SYMBOL(flush_tlb_page);
+-
+-static void do_flush_tlb_all(void* info)
+-{
+-	unsigned long cpu = smp_processor_id();
+-
+-	__flush_tlb_all();
+-	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
+-		leave_mm(cpu);
+-}
+-
+-void flush_tlb_all(void)
+-{
+-	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
+-}
+-
+-/*
+- * this function sends a 'reschedule' IPI to another CPU.
+- * it goes straight through and wastes no time serializing
+- * anything. Worst case is that we lose a reschedule ...
+- */
+-static void native_smp_send_reschedule(int cpu)
+-{
+-	WARN_ON(cpu_is_offline(cpu));
+-	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
+-}
+-
+-/*
+- * Structure and data for smp_call_function(). This is designed to minimise
+- * static memory requirements. It also looks cleaner.
+- */
+-static DEFINE_SPINLOCK(call_lock);
+-
+-struct call_data_struct {
+-	void (*func) (void *info);
+-	void *info;
+-	atomic_t started;
+-	atomic_t finished;
+-	int wait;
+-};
+-
+-void lock_ipi_call_lock(void)
+-{
+-	spin_lock_irq(&call_lock);
+-}
+-
+-void unlock_ipi_call_lock(void)
+-{
+-	spin_unlock_irq(&call_lock);
+-}
+-
+-static struct call_data_struct *call_data;
+-
+-static void __smp_call_function(void (*func) (void *info), void *info,
+-				int nonatomic, int wait)
+-{
+-	struct call_data_struct data;
+-	int cpus = num_online_cpus() - 1;
+-
+-	if (!cpus)
+-		return;
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	mb();
+-	
+-	/* Send a message to all other CPUs and wait for them to respond */
+-	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (wait)
+-		while (atomic_read(&data.finished) != cpus)
+-			cpu_relax();
+-}
+-
+-
+-/**
+- * smp_call_function_mask(): Run a function on a set of other CPUs.
+- * @mask: The set of cpus to run on.  Must not include the current cpu.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+-  * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-static int
+-native_smp_call_function_mask(cpumask_t mask,
+-			      void (*func)(void *), void *info,
+-			      int wait)
+-{
+-	struct call_data_struct data;
+-	cpumask_t allbutself;
+-	int cpus;
+-
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+-	/* Holding any lock stops cpus from going down. */
+-	spin_lock(&call_lock);
+-
+-	allbutself = cpu_online_map;
+-	cpu_clear(smp_processor_id(), allbutself);
+-
+-	cpus_and(mask, mask, allbutself);
+-	cpus = cpus_weight(mask);
+-
+-	if (!cpus) {
+-		spin_unlock(&call_lock);
+-		return 0;
+-	}
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	mb();
+-
+-	/* Send a message to other CPUs */
+-	if (cpus_equal(mask, allbutself))
+-		send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-	else
+-		send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (wait)
+-		while (atomic_read(&data.finished) != cpus)
+-			cpu_relax();
+-	spin_unlock(&call_lock);
+-
+-	return 0;
+-}
+-
+-static void stop_this_cpu (void * dummy)
+-{
+-	local_irq_disable();
+-	/*
+-	 * Remove this CPU:
+-	 */
+-	cpu_clear(smp_processor_id(), cpu_online_map);
+-	disable_local_APIC();
+-	if (cpu_data(smp_processor_id()).hlt_works_ok)
+-		for(;;) halt();
+-	for (;;);
+-}
+-
+-/*
+- * this function calls the 'stop' function on all other CPUs in the system.
+- */
+-
+-static void native_smp_send_stop(void)
+-{
+-	/* Don't deadlock on the call lock in panic */
+-	int nolock = !spin_trylock(&call_lock);
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	__smp_call_function(stop_this_cpu, NULL, 0, 0);
+-	if (!nolock)
+-		spin_unlock(&call_lock);
+-	disable_local_APIC();
+-	local_irq_restore(flags);
+-}
+-
+-/*
+- * Reschedule call back. Nothing to do,
+- * all the work is done automatically when
+- * we return from the interrupt.
+- */
+-void smp_reschedule_interrupt(struct pt_regs *regs)
+-{
+-	ack_APIC_irq();
+-	__get_cpu_var(irq_stat).irq_resched_count++;
+-}
+-
+-void smp_call_function_interrupt(struct pt_regs *regs)
+-{
+-	void (*func) (void *info) = call_data->func;
+-	void *info = call_data->info;
+-	int wait = call_data->wait;
+-
+-	ack_APIC_irq();
+-	/*
+-	 * Notify initiating CPU that I've grabbed the data and am
+-	 * about to execute the function
+-	 */
+-	mb();
+-	atomic_inc(&call_data->started);
+-	/*
+-	 * At this point the info structure may be out of scope unless wait==1
+-	 */
+-	irq_enter();
+-	(*func)(info);
+-	__get_cpu_var(irq_stat).irq_call_count++;
+-	irq_exit();
+-
+-	if (wait) {
+-		mb();
+-		atomic_inc(&call_data->finished);
+-	}
+-}
+-
+-static int convert_apicid_to_cpu(int apic_id)
+-{
+-	int i;
+-
+-	for_each_possible_cpu(i) {
+-		if (per_cpu(x86_cpu_to_apicid, i) == apic_id)
+-			return i;
+-	}
+-	return -1;
+-}
+-
+-int safe_smp_processor_id(void)
+-{
+-	int apicid, cpuid;
+-
+-	if (!boot_cpu_has(X86_FEATURE_APIC))
+-		return 0;
+-
+-	apicid = hard_smp_processor_id();
+-	if (apicid == BAD_APICID)
+-		return 0;
+-
+-	cpuid = convert_apicid_to_cpu(apicid);
+-
+-	return cpuid >= 0 ? cpuid : 0;
+-}
+-
+-struct smp_ops smp_ops = {
+-	.smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
+-	.smp_prepare_cpus = native_smp_prepare_cpus,
+-	.cpu_up = native_cpu_up,
+-	.smp_cpus_done = native_smp_cpus_done,
+-
+-	.smp_send_stop = native_smp_send_stop,
+-	.smp_send_reschedule = native_smp_send_reschedule,
+-	.smp_call_function_mask = native_smp_call_function_mask,
+-};
+-EXPORT_SYMBOL_GPL(smp_ops);
+diff --git a/arch/x86/kernel/smp_64.c b/arch/x86/kernel/smp_64.c
+deleted file mode 100644
+index 2fd74b0..0000000
+--- a/arch/x86/kernel/smp_64.c
++++ /dev/null
+@@ -1,530 +0,0 @@
+-/*
+- *	Intel SMP support routines.
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- *	(c) 1998-99, 2000 Ingo Molnar <mingo at redhat.com>
+- *      (c) 2002,2003 Andi Kleen, SuSE Labs.
+- *
+- *	This code is released under the GNU General Public License version 2 or
+- *	later.
+- */
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/smp.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/interrupt.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/pgalloc.h>
+-#include <asm/tlbflush.h>
+-#include <asm/mach_apic.h>
+-#include <asm/mmu_context.h>
+-#include <asm/proto.h>
+-#include <asm/apicdef.h>
+-#include <asm/idle.h>
+-
+-/*
+- *	Smarter SMP flushing macros.
+- *		c/o Linus Torvalds.
+- *
+- *	These mean you can really definitely utterly forget about
+- *	writing to user space from interrupts. (Its not allowed anyway).
+- *
+- *	Optimizations Manfred Spraul <manfred at colorfullife.com>
+- *
+- *	More scalable flush, from Andi Kleen
+- *
+- *	To avoid global state use 8 different call vectors.
+- *	Each CPU uses a specific vector to trigger flushes on other
+- *	CPUs. Depending on the received vector the target CPUs look into
+- *	the right per cpu variable for the flush data.
+- *
+- *	With more than 8 CPUs they are hashed to the 8 available
+- *	vectors. The limited global vector space forces us to this right now.
+- *	In future when interrupts are split into per CPU domains this could be
+- *	fixed, at the cost of triggering multiple IPIs in some cases.
+- */
+-
+-union smp_flush_state {
+-	struct {
+-		cpumask_t flush_cpumask;
+-		struct mm_struct *flush_mm;
+-		unsigned long flush_va;
+-		spinlock_t tlbstate_lock;
+-	};
+-	char pad[SMP_CACHE_BYTES];
+-} ____cacheline_aligned;
+-
+-/* State is put into the per CPU data section, but padded
+-   to a full cache line because other CPUs can access it and we don't
+-   want false sharing in the per cpu data segment. */
+-static DEFINE_PER_CPU(union smp_flush_state, flush_state);
+-
+-/*
+- * We cannot call mmdrop() because we are in interrupt context,
+- * instead update mm->cpu_vm_mask.
+- */
+-void leave_mm(int cpu)
+-{
+-	if (read_pda(mmu_state) == TLBSTATE_OK)
+-		BUG();
+-	cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
+-	load_cr3(swapper_pg_dir);
+-}
+-EXPORT_SYMBOL_GPL(leave_mm);
+-
+-/*
+- *
+- * The flush IPI assumes that a thread switch happens in this order:
+- * [cpu0: the cpu that switches]
+- * 1) switch_mm() either 1a) or 1b)
+- * 1a) thread switch to a different mm
+- * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
+- *	Stop ipi delivery for the old mm. This is not synchronized with
+- *	the other cpus, but smp_invalidate_interrupt ignore flush ipis
+- *	for the wrong mm, and in the worst case we perform a superfluous
+- *	tlb flush.
+- * 1a2) set cpu mmu_state to TLBSTATE_OK
+- *	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
+- *	was in lazy tlb mode.
+- * 1a3) update cpu active_mm
+- *	Now cpu0 accepts tlb flushes for the new mm.
+- * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
+- *	Now the other cpus will send tlb flush ipis.
+- * 1a4) change cr3.
+- * 1b) thread switch without mm change
+- *	cpu active_mm is correct, cpu0 already handles
+- *	flush ipis.
+- * 1b1) set cpu mmu_state to TLBSTATE_OK
+- * 1b2) test_and_set the cpu bit in cpu_vm_mask.
+- *	Atomically set the bit [other cpus will start sending flush ipis],
+- *	and test the bit.
+- * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
+- * 2) switch %%esp, ie current
+- *
+- * The interrupt must handle 2 special cases:
+- * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
+- * - the cpu performs speculative tlb reads, i.e. even if the cpu only
+- *   runs in kernel space, the cpu could load tlb entries for user space
+- *   pages.
+- *
+- * The good news is that cpu mmu_state is local to each cpu, no
+- * write/read ordering problems.
+- */
+-
+-/*
+- * TLB flush IPI:
+- *
+- * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
+- * 2) Leave the mm if we are in the lazy tlb mode.
+- *
+- * Interrupts are disabled.
+- */
+-
+-asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
+-{
+-	int cpu;
+-	int sender;
+-	union smp_flush_state *f;
+-
+-	cpu = smp_processor_id();
+-	/*
+-	 * orig_rax contains the negated interrupt vector.
+-	 * Use that to determine where the sender put the data.
+-	 */
+-	sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
+-	f = &per_cpu(flush_state, sender);
+-
+-	if (!cpu_isset(cpu, f->flush_cpumask))
+-		goto out;
+-		/*
+-		 * This was a BUG() but until someone can quote me the
+-		 * line from the intel manual that guarantees an IPI to
+-		 * multiple CPUs is retried _only_ on the erroring CPUs
+-		 * its staying as a return
+-		 *
+-		 * BUG();
+-		 */
+-
+-	if (f->flush_mm == read_pda(active_mm)) {
+-		if (read_pda(mmu_state) == TLBSTATE_OK) {
+-			if (f->flush_va == TLB_FLUSH_ALL)
+-				local_flush_tlb();
+-			else
+-				__flush_tlb_one(f->flush_va);
+-		} else
+-			leave_mm(cpu);
+-	}
+-out:
+-	ack_APIC_irq();
+-	cpu_clear(cpu, f->flush_cpumask);
+-	add_pda(irq_tlb_count, 1);
+-}
+-
+-void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
+-			     unsigned long va)
+-{
+-	int sender;
+-	union smp_flush_state *f;
+-	cpumask_t cpumask = *cpumaskp;
+-
+-	/* Caller has disabled preemption */
+-	sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+-	f = &per_cpu(flush_state, sender);
+-
+-	/*
+-	 * Could avoid this lock when
+-	 * num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
+-	 * probably not worth checking this for a cache-hot lock.
+-	 */
+-	spin_lock(&f->tlbstate_lock);
+-
+-	f->flush_mm = mm;
+-	f->flush_va = va;
+-	cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
+-
+-	/*
+-	 * We have to send the IPI only to
+-	 * CPUs affected.
+-	 */
+-	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
+-
+-	while (!cpus_empty(f->flush_cpumask))
+-		cpu_relax();
+-
+-	f->flush_mm = NULL;
+-	f->flush_va = 0;
+-	spin_unlock(&f->tlbstate_lock);
+-}
+-
+-int __cpuinit init_smp_flush(void)
+-{
+-	int i;
+-
+-	for_each_cpu_mask(i, cpu_possible_map) {
+-		spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
+-	}
+-	return 0;
+-}
+-core_initcall(init_smp_flush);
+-
+-void flush_tlb_current_task(void)
+-{
+-	struct mm_struct *mm = current->mm;
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	local_flush_tlb();
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-	preempt_enable();
+-}
+-
+-void flush_tlb_mm (struct mm_struct * mm)
+-{
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	if (current->active_mm == mm) {
+-		if (current->mm)
+-			local_flush_tlb();
+-		else
+-			leave_mm(smp_processor_id());
+-	}
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-
+-	preempt_enable();
+-}
+-
+-void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+-{
+-	struct mm_struct *mm = vma->vm_mm;
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	if (current->active_mm == mm) {
+-		if(current->mm)
+-			__flush_tlb_one(va);
+-		else
+-			leave_mm(smp_processor_id());
+-	}
+-
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, va);
+-
+-	preempt_enable();
+-}
+-
+-static void do_flush_tlb_all(void* info)
+-{
+-	unsigned long cpu = smp_processor_id();
+-
+-	__flush_tlb_all();
+-	if (read_pda(mmu_state) == TLBSTATE_LAZY)
+-		leave_mm(cpu);
+-}
+-
+-void flush_tlb_all(void)
+-{
+-	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
+-}
+-
+-/*
+- * this function sends a 'reschedule' IPI to another CPU.
+- * it goes straight through and wastes no time serializing
+- * anything. Worst case is that we lose a reschedule ...
+- */
+-
+-void smp_send_reschedule(int cpu)
+-{
+-	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
+-}
+-
+-/*
+- * Structure and data for smp_call_function(). This is designed to minimise
+- * static memory requirements. It also looks cleaner.
+- */
+-static DEFINE_SPINLOCK(call_lock);
+-
+-struct call_data_struct {
+-	void (*func) (void *info);
+-	void *info;
+-	atomic_t started;
+-	atomic_t finished;
+-	int wait;
+-};
+-
+-static struct call_data_struct * call_data;
+-
+-void lock_ipi_call_lock(void)
+-{
+-	spin_lock_irq(&call_lock);
+-}
+-
+-void unlock_ipi_call_lock(void)
+-{
+-	spin_unlock_irq(&call_lock);
+-}
+-
+-/*
+- * this function sends a 'generic call function' IPI to all other CPU
+- * of the system defined in the mask.
+- */
+-static int __smp_call_function_mask(cpumask_t mask,
+-				    void (*func)(void *), void *info,
+-				    int wait)
+-{
+-	struct call_data_struct data;
+-	cpumask_t allbutself;
+-	int cpus;
+-
+-	allbutself = cpu_online_map;
+-	cpu_clear(smp_processor_id(), allbutself);
+-
+-	cpus_and(mask, mask, allbutself);
+-	cpus = cpus_weight(mask);
+-
+-	if (!cpus)
+-		return 0;
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	wmb();
+-
+-	/* Send a message to other CPUs */
+-	if (cpus_equal(mask, allbutself))
+-		send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-	else
+-		send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (!wait)
+-		return 0;
+-
+-	while (atomic_read(&data.finished) != cpus)
+-		cpu_relax();
+-
+-	return 0;
+-}
+-/**
+- * smp_call_function_mask(): Run a function on a set of other CPUs.
+- * @mask: The set of cpus to run on.  Must not include the current cpu.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-int smp_call_function_mask(cpumask_t mask,
+-			   void (*func)(void *), void *info,
+-			   int wait)
+-{
+-	int ret;
+-
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+-	spin_lock(&call_lock);
+-	ret = __smp_call_function_mask(mask, func, info, wait);
+-	spin_unlock(&call_lock);
+-	return ret;
+-}
+-EXPORT_SYMBOL(smp_call_function_mask);
+-
+-/*
+- * smp_call_function_single - Run a function on a specific CPU
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Currently unused.
+- * @wait: If true, wait until function has completed on other CPUs.
+- *
+- * Retrurns 0 on success, else a negative status code.
+- *
+- * Does not return until the remote CPU is nearly ready to execute <func>
+- * or is or has executed.
+- */
+-
+-int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
+-			      int nonatomic, int wait)
+-{
+-	/* prevent preemption and reschedule on another processor */
+-	int ret, me = get_cpu();
+-
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+-	if (cpu == me) {
+-		local_irq_disable();
+-		func(info);
+-		local_irq_enable();
+-		put_cpu();
+-		return 0;
+-	}
+-
+-	ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+-
+-	put_cpu();
+-	return ret;
+-}
+-EXPORT_SYMBOL(smp_call_function_single);
+-
+-/*
+- * smp_call_function - run a function on all other CPUs.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: currently unused.
+- * @wait: If true, wait (atomically) until function has completed on other
+- *        CPUs.
+- *
+- * Returns 0 on success, else a negative status code. Does not return until
+- * remote CPUs are nearly ready to execute func or are or have executed.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- * Actually there are a few legal cases, like panic.
+- */
+-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+-			int wait)
+-{
+-	return smp_call_function_mask(cpu_online_map, func, info, wait);
+-}
+-EXPORT_SYMBOL(smp_call_function);
+-
+-static void stop_this_cpu(void *dummy)
+-{
+-	local_irq_disable();
+-	/*
+-	 * Remove this CPU:
+-	 */
+-	cpu_clear(smp_processor_id(), cpu_online_map);
+-	disable_local_APIC();
+-	for (;;)
+-		halt();
+-}
+-
+-void smp_send_stop(void)
+-{
+-	int nolock;
+-	unsigned long flags;
+-
+-	if (reboot_force)
+-		return;
+-
+-	/* Don't deadlock on the call lock in panic */
+-	nolock = !spin_trylock(&call_lock);
+-	local_irq_save(flags);
+-	__smp_call_function_mask(cpu_online_map, stop_this_cpu, NULL, 0);
+-	if (!nolock)
+-		spin_unlock(&call_lock);
+-	disable_local_APIC();
+-	local_irq_restore(flags);
+-}
+-
+-/*
+- * Reschedule call back. Nothing to do,
+- * all the work is done automatically when
+- * we return from the interrupt.
+- */
+-asmlinkage void smp_reschedule_interrupt(void)
+-{
+-	ack_APIC_irq();
+-	add_pda(irq_resched_count, 1);
+-}
+-
+-asmlinkage void smp_call_function_interrupt(void)
+-{
+-	void (*func) (void *info) = call_data->func;
+-	void *info = call_data->info;
+-	int wait = call_data->wait;
+-
+-	ack_APIC_irq();
+-	/*
+-	 * Notify initiating CPU that I've grabbed the data and am
+-	 * about to execute the function
+-	 */
+-	mb();
+-	atomic_inc(&call_data->started);
+-	/*
+-	 * At this point the info structure may be out of scope unless wait==1
+-	 */
+-	exit_idle();
+-	irq_enter();
+-	(*func)(info);
+-	add_pda(irq_call_count, 1);
+-	irq_exit();
+-	if (wait) {
+-		mb();
+-		atomic_inc(&call_data->finished);
+-	}
+-}
+-
+diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
+new file mode 100644
+index 0000000..04c662b
+--- /dev/null
++++ b/arch/x86/kernel/smpboot.c
+@@ -0,0 +1,1450 @@
++/*
++ *	x86 SMP booting functions
++ *
++ *	(c) 1995 Alan Cox, Building #3 <alan at redhat.com>
++ *	(c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
++ *	Copyright 2001 Andi Kleen, SuSE Labs.
++ *
++ *	Much of the core SMP work is based on previous work by Thomas Radke, to
++ *	whom a great many thanks are extended.
++ *
++ *	Thanks to Intel for making available several different Pentium,
++ *	Pentium Pro and Pentium-II/Xeon MP machines.
++ *	Original development of Linux SMP code supported by Caldera.
++ *
++ *	This code is released under the GNU General Public License version 2 or
++ *	later.
++ *
++ *	Fixes
++ *		Felix Koop	:	NR_CPUS used properly
++ *		Jose Renau	:	Handle single CPU case.
++ *		Alan Cox	:	By repeated request 8) - Total BogoMIPS report.
++ *		Greg Wright	:	Fix for kernel stacks panic.
++ *		Erich Boleyn	:	MP v1.4 and additional changes.
++ *	Matthias Sattler	:	Changes for 2.1 kernel map.
++ *	Michel Lespinasse	:	Changes for 2.1 kernel map.
++ *	Michael Chastain	:	Change trampoline.S to gnu as.
++ *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
++ *		Ingo Molnar	:	Added APIC timers, based on code
++ *					from Jose Renau
++ *		Ingo Molnar	:	various cleanups and rewrites
++ *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
++ *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs
++ *	Andi Kleen		:	Changed for SMP boot into long mode.
++ *		Martin J. Bligh	: 	Added support for multi-quad systems
++ *		Dave Jones	:	Report invalid combinations of Athlon CPUs.
++ *		Rusty Russell	:	Hacked into shape for new "hotplug" boot process.
++ *      Andi Kleen              :       Converted to new state machine.
++ *	Ashok Raj		: 	CPU hotplug support
++ *	Glauber Costa		:	i386 and x86_64 integration
++ */
++
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/percpu.h>
++#include <linux/bootmem.h>
++#include <linux/err.h>
++#include <linux/nmi.h>
++
++#include <asm/acpi.h>
++#include <asm/desc.h>
++#include <asm/nmi.h>
++#include <asm/irq.h>
++#include <asm/smp.h>
++#include <asm/trampoline.h>
++#include <asm/cpu.h>
++#include <asm/numa.h>
++#include <asm/pgtable.h>
++#include <asm/tlbflush.h>
++#include <asm/mtrr.h>
++#include <asm/nmi.h>
++#include <asm/vmi.h>
++#include <asm/genapic.h>
++#include <linux/mc146818rtc.h>
++
++#include <mach_apic.h>
++#include <mach_wakecpu.h>
++#include <smpboot_hooks.h>
++
++/*
++ * FIXME: For x86_64, those are defined in other files. But moving them here,
++ * would make the setup areas dependent on smp, which is a loss. When we
++ * integrate apic between arches, we can probably do a better job, but
++ * right now, they'll stay here -- glommer
++ */
++
++/* which logical CPU number maps to which CPU (physical APIC ID) */
++u16 x86_cpu_to_apicid_init[NR_CPUS] __initdata =
++			{ [0 ... NR_CPUS-1] = BAD_APICID };
++void *x86_cpu_to_apicid_early_ptr;
++
++u16 x86_bios_cpu_apicid_init[NR_CPUS] __initdata
++				= { [0 ... NR_CPUS-1] = BAD_APICID };
++void *x86_bios_cpu_apicid_early_ptr;
++
++#ifdef CONFIG_X86_32
++u8 apicid_2_node[MAX_APICID];
++#endif
++
++/* State of each CPU */
++DEFINE_PER_CPU(int, cpu_state) = { 0 };
++
++/* Store all idle threads, this can be reused instead of creating
++* a new thread. Also avoids complicated thread destroy functionality
++* for idle threads.
++*/
++#ifdef CONFIG_HOTPLUG_CPU
++/*
++ * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is
++ * removed after init for !CONFIG_HOTPLUG_CPU.
++ */
++static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
++#define get_idle_for_cpu(x)      (per_cpu(idle_thread_array, x))
++#define set_idle_for_cpu(x, p)   (per_cpu(idle_thread_array, x) = (p))
++#else
++struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
++#define get_idle_for_cpu(x)      (idle_thread_array[(x)])
++#define set_idle_for_cpu(x, p)   (idle_thread_array[(x)] = (p))
++#endif
++
++/* Number of siblings per CPU package */
++int smp_num_siblings = 1;
++EXPORT_SYMBOL(smp_num_siblings);
++
++/* Last level cache ID of each logical CPU */
++DEFINE_PER_CPU(u16, cpu_llc_id) = BAD_APICID;
++
++/* bitmap of online cpus */
++cpumask_t cpu_online_map __read_mostly;
++EXPORT_SYMBOL(cpu_online_map);
++
++cpumask_t cpu_callin_map;
++cpumask_t cpu_callout_map;
++cpumask_t cpu_possible_map;
++EXPORT_SYMBOL(cpu_possible_map);
++
++/* representing HT siblings of each logical CPU */
++DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
++EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
++
++/* representing HT and core siblings of each logical CPU */
++DEFINE_PER_CPU(cpumask_t, cpu_core_map);
++EXPORT_PER_CPU_SYMBOL(cpu_core_map);
++
++/* Per CPU bogomips and other parameters */
++DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
++EXPORT_PER_CPU_SYMBOL(cpu_info);
++
++static atomic_t init_deasserted;
++
++static int boot_cpu_logical_apicid;
++
++/* representing cpus for which sibling maps can be computed */
++static cpumask_t cpu_sibling_setup_map;
++
++/* Set if we find a B stepping CPU */
++int __cpuinitdata smp_b_stepping;
++
++#if defined(CONFIG_NUMA) && defined(CONFIG_X86_32)
++
++/* which logical CPUs are on which nodes */
++cpumask_t node_to_cpumask_map[MAX_NUMNODES] __read_mostly =
++				{ [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
++EXPORT_SYMBOL(node_to_cpumask_map);
++/* which node each logical CPU is on */
++int cpu_to_node_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 };
++EXPORT_SYMBOL(cpu_to_node_map);
++
++/* set up a mapping between cpu and node. */
++static void map_cpu_to_node(int cpu, int node)
++{
++	printk(KERN_INFO "Mapping cpu %d to node %d\n", cpu, node);
++	cpu_set(cpu, node_to_cpumask_map[node]);
++	cpu_to_node_map[cpu] = node;
++}
++
++/* undo a mapping between cpu and node. */
++static void unmap_cpu_to_node(int cpu)
++{
++	int node;
++
++	printk(KERN_INFO "Unmapping cpu %d from all nodes\n", cpu);
++	for (node = 0; node < MAX_NUMNODES; node++)
++		cpu_clear(cpu, node_to_cpumask_map[node]);
++	cpu_to_node_map[cpu] = 0;
++}
++#else /* !(CONFIG_NUMA && CONFIG_X86_32) */
++#define map_cpu_to_node(cpu, node)	({})
++#define unmap_cpu_to_node(cpu)	({})
++#endif
++
++#ifdef CONFIG_X86_32
++u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
++					{ [0 ... NR_CPUS-1] = BAD_APICID };
++
++static void map_cpu_to_logical_apicid(void)
++{
++	int cpu = smp_processor_id();
++	int apicid = logical_smp_processor_id();
++	int node = apicid_to_node(apicid);
++
++	if (!node_online(node))
++		node = first_online_node;
++
++	cpu_2_logical_apicid[cpu] = apicid;
++	map_cpu_to_node(cpu, node);
++}
++
++static void unmap_cpu_to_logical_apicid(int cpu)
++{
++	cpu_2_logical_apicid[cpu] = BAD_APICID;
++	unmap_cpu_to_node(cpu);
++}
++#else
++#define unmap_cpu_to_logical_apicid(cpu) do {} while (0)
++#define map_cpu_to_logical_apicid()  do {} while (0)
++#endif
++
++/*
++ * Report back to the Boot Processor.
++ * Running on AP.
++ */
++static void __cpuinit smp_callin(void)
++{
++	int cpuid, phys_id;
++	unsigned long timeout;
++
++	/*
++	 * If waken up by an INIT in an 82489DX configuration
++	 * we may get here before an INIT-deassert IPI reaches
++	 * our local APIC.  We have to wait for the IPI or we'll
++	 * lock up on an APIC access.
++	 */
++	wait_for_init_deassert(&init_deasserted);
++
++	/*
++	 * (This works even if the APIC is not enabled.)
++	 */
++	phys_id = GET_APIC_ID(read_apic_id());
++	cpuid = smp_processor_id();
++	if (cpu_isset(cpuid, cpu_callin_map)) {
++		panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__,
++					phys_id, cpuid);
++	}
++	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
++
++	/*
++	 * STARTUP IPIs are fragile beasts as they might sometimes
++	 * trigger some glue motherboard logic. Complete APIC bus
++	 * silence for 1 second, this overestimates the time the
++	 * boot CPU is spending to send the up to 2 STARTUP IPIs
++	 * by a factor of two. This should be enough.
++	 */
++
++	/*
++	 * Waiting 2s total for startup (udelay is not yet working)
++	 */
++	timeout = jiffies + 2*HZ;
++	while (time_before(jiffies, timeout)) {
++		/*
++		 * Has the boot CPU finished it's STARTUP sequence?
++		 */
++		if (cpu_isset(cpuid, cpu_callout_map))
++			break;
++		cpu_relax();
++	}
++
++	if (!time_before(jiffies, timeout)) {
++		panic("%s: CPU%d started up but did not get a callout!\n",
++		      __func__, cpuid);
++	}
++
++	/*
++	 * the boot CPU has finished the init stage and is spinning
++	 * on callin_map until we finish. We are free to set up this
++	 * CPU, first the APIC. (this is probably redundant on most
++	 * boards)
++	 */
++
++	Dprintk("CALLIN, before setup_local_APIC().\n");
++	smp_callin_clear_local_apic();
++	setup_local_APIC();
++	end_local_APIC_setup();
++	map_cpu_to_logical_apicid();
++
++	/*
++	 * Get our bogomips.
++	 *
++	 * Need to enable IRQs because it can take longer and then
++	 * the NMI watchdog might kill us.
++	 */
++	local_irq_enable();
++	calibrate_delay();
++	local_irq_disable();
++	Dprintk("Stack at about %p\n", &cpuid);
++
++	/*
++	 * Save our processor parameters
++	 */
++	smp_store_cpu_info(cpuid);
++
++	/*
++	 * Allow the master to continue.
++	 */
++	cpu_set(cpuid, cpu_callin_map);
++}
++
++/*
++ * Activate a secondary processor.
++ */
++void __cpuinit start_secondary(void *unused)
++{
++	/*
++	 * Don't put *anything* before cpu_init(), SMP booting is too
++	 * fragile that we want to limit the things done here to the
++	 * most necessary things.
++	 */
++#ifdef CONFIG_VMI
++	vmi_bringup();
++#endif
++	cpu_init();
++	preempt_disable();
++	smp_callin();
++
++	/* otherwise gcc will move up smp_processor_id before the cpu_init */
++	barrier();
++	/*
++	 * Check TSC synchronization with the BP:
++	 */
++	check_tsc_sync_target();
++
++	if (nmi_watchdog == NMI_IO_APIC) {
++		disable_8259A_irq(0);
++		enable_NMI_through_LVT0();
++		enable_8259A_irq(0);
++	}
++
++	/* This must be done before setting cpu_online_map */
++	set_cpu_sibling_map(raw_smp_processor_id());
++	wmb();
++
++	/*
++	 * We need to hold call_lock, so there is no inconsistency
++	 * between the time smp_call_function() determines number of
++	 * IPI recipients, and the time when the determination is made
++	 * for which cpus receive the IPI. Holding this
++	 * lock helps us to not include this cpu in a currently in progress
++	 * smp_call_function().
++	 */
++	lock_ipi_call_lock();
++#ifdef CONFIG_X86_64
++	spin_lock(&vector_lock);
++
++	/* Setup the per cpu irq handling data structures */
++	__setup_vector_irq(smp_processor_id());
++	/*
++	 * Allow the master to continue.
++	 */
++	spin_unlock(&vector_lock);
++#endif
++	cpu_set(smp_processor_id(), cpu_online_map);
++	unlock_ipi_call_lock();
++	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
++
++	setup_secondary_clock();
++
++	wmb();
++	cpu_idle();
++}
++
++#ifdef CONFIG_X86_32
++/*
++ * Everything has been set up for the secondary
++ * CPUs - they just need to reload everything
++ * from the task structure
++ * This function must not return.
++ */
++void __devinit initialize_secondary(void)
++{
++	/*
++	 * We don't actually need to load the full TSS,
++	 * basically just the stack pointer and the ip.
++	 */
++
++	asm volatile(
++		"movl %0,%%esp\n\t"
++		"jmp *%1"
++		:
++		:"m" (current->thread.sp), "m" (current->thread.ip));
++}
++#endif
++
++static void __cpuinit smp_apply_quirks(struct cpuinfo_x86 *c)
++{
++#ifdef CONFIG_X86_32
++	/*
++	 * Mask B, Pentium, but not Pentium MMX
++	 */
++	if (c->x86_vendor == X86_VENDOR_INTEL &&
++	    c->x86 == 5 &&
++	    c->x86_mask >= 1 && c->x86_mask <= 4 &&
++	    c->x86_model <= 3)
++		/*
++		 * Remember we have B step Pentia with bugs
++		 */
++		smp_b_stepping = 1;
++
++	/*
++	 * Certain Athlons might work (for various values of 'work') in SMP
++	 * but they are not certified as MP capable.
++	 */
++	if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
++
++		if (num_possible_cpus() == 1)
++			goto valid_k7;
++
++		/* Athlon 660/661 is valid. */
++		if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
++		    (c->x86_mask == 1)))
++			goto valid_k7;
++
++		/* Duron 670 is valid */
++		if ((c->x86_model == 7) && (c->x86_mask == 0))
++			goto valid_k7;
++
++		/*
++		 * Athlon 662, Duron 671, and Athlon >model 7 have capability
++		 * bit. It's worth noting that the A5 stepping (662) of some
++		 * Athlon XP's have the MP bit set.
++		 * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for
++		 * more.
++		 */
++		if (((c->x86_model == 6) && (c->x86_mask >= 2)) ||
++		    ((c->x86_model == 7) && (c->x86_mask >= 1)) ||
++		     (c->x86_model > 7))
++			if (cpu_has_mp)
++				goto valid_k7;
++
++		/* If we get here, not a certified SMP capable AMD system. */
++		add_taint(TAINT_UNSAFE_SMP);
++	}
++
++valid_k7:
++	;
++#endif
++}
++
++static void __cpuinit smp_checks(void)
++{
++	if (smp_b_stepping)
++		printk(KERN_WARNING "WARNING: SMP operation may be unreliable"
++				    "with B stepping processors.\n");
++
++	/*
++	 * Don't taint if we are running SMP kernel on a single non-MP
++	 * approved Athlon
++	 */
++	if (tainted & TAINT_UNSAFE_SMP) {
++		if (num_online_cpus())
++			printk(KERN_INFO "WARNING: This combination of AMD"
++				"processors is not suitable for SMP.\n");
++		else
++			tainted &= ~TAINT_UNSAFE_SMP;
++	}
++}
++
++/*
++ * The bootstrap kernel entry code has set these up. Save them for
++ * a given CPU
++ */
++
++void __cpuinit smp_store_cpu_info(int id)
++{
++	struct cpuinfo_x86 *c = &cpu_data(id);
++
++	*c = boot_cpu_data;
++	c->cpu_index = id;
++	if (id != 0)
++		identify_secondary_cpu(c);
++	smp_apply_quirks(c);
++}
++
++
++void __cpuinit set_cpu_sibling_map(int cpu)
++{
++	int i;
++	struct cpuinfo_x86 *c = &cpu_data(cpu);
++
++	cpu_set(cpu, cpu_sibling_setup_map);
++
++	if (smp_num_siblings > 1) {
++		for_each_cpu_mask(i, cpu_sibling_setup_map) {
++			if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
++			    c->cpu_core_id == cpu_data(i).cpu_core_id) {
++				cpu_set(i, per_cpu(cpu_sibling_map, cpu));
++				cpu_set(cpu, per_cpu(cpu_sibling_map, i));
++				cpu_set(i, per_cpu(cpu_core_map, cpu));
++				cpu_set(cpu, per_cpu(cpu_core_map, i));
++				cpu_set(i, c->llc_shared_map);
++				cpu_set(cpu, cpu_data(i).llc_shared_map);
++			}
++		}
++	} else {
++		cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
++	}
++
++	cpu_set(cpu, c->llc_shared_map);
++
++	if (current_cpu_data.x86_max_cores == 1) {
++		per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
++		c->booted_cores = 1;
++		return;
++	}
++
++	for_each_cpu_mask(i, cpu_sibling_setup_map) {
++		if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
++		    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
++			cpu_set(i, c->llc_shared_map);
++			cpu_set(cpu, cpu_data(i).llc_shared_map);
++		}
++		if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
++			cpu_set(i, per_cpu(cpu_core_map, cpu));
++			cpu_set(cpu, per_cpu(cpu_core_map, i));
++			/*
++			 *  Does this new cpu bringup a new core?
++			 */
++			if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
++				/*
++				 * for each core in package, increment
++				 * the booted_cores for this new cpu
++				 */
++				if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
++					c->booted_cores++;
++				/*
++				 * increment the core count for all
++				 * the other cpus in this package
++				 */
++				if (i != cpu)
++					cpu_data(i).booted_cores++;
++			} else if (i != cpu && !c->booted_cores)
++				c->booted_cores = cpu_data(i).booted_cores;
++		}
++	}
++}
++
++/* maps the cpu to the sched domain representing multi-core */
++cpumask_t cpu_coregroup_map(int cpu)
++{
++	struct cpuinfo_x86 *c = &cpu_data(cpu);
++	/*
++	 * For perf, we return last level cache shared map.
++	 * And for power savings, we return cpu_core_map
++	 */
++	if (sched_mc_power_savings || sched_smt_power_savings)
++		return per_cpu(cpu_core_map, cpu);
++	else
++		return c->llc_shared_map;
++}
++
++#ifdef CONFIG_X86_32
++/*
++ * We are called very early to get the low memory for the
++ * SMP bootup trampoline page.
++ */
++void __init smp_alloc_memory(void)
++{
++	trampoline_base = alloc_bootmem_low_pages(PAGE_SIZE);
++	/*
++	 * Has to be in very low memory so we can execute
++	 * real-mode AP code.
++	 */
++	if (__pa(trampoline_base) >= 0x9F000)
++		BUG();
++}
++#endif
++
++static void impress_friends(void)
++{
++	int cpu;
++	unsigned long bogosum = 0;
++	/*
++	 * Allow the user to impress friends.
++	 */
++	Dprintk("Before bogomips.\n");
++	for_each_possible_cpu(cpu)
++		if (cpu_isset(cpu, cpu_callout_map))
++			bogosum += cpu_data(cpu).loops_per_jiffy;
++	printk(KERN_INFO
++		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
++		num_online_cpus(),
++		bogosum/(500000/HZ),
++		(bogosum/(5000/HZ))%100);
++
++	Dprintk("Before bogocount - setting activated=1.\n");
++}
++
++static inline void __inquire_remote_apic(int apicid)
++{
++	unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
++	char *names[] = { "ID", "VERSION", "SPIV" };
++	int timeout;
++	u32 status;
++
++	printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid);
++
++	for (i = 0; i < ARRAY_SIZE(regs); i++) {
++		printk(KERN_INFO "... APIC #%d %s: ", apicid, names[i]);
++
++		/*
++		 * Wait for idle.
++		 */
++		status = safe_apic_wait_icr_idle();
++		if (status)
++			printk(KERN_CONT
++			       "a previous APIC delivery may have failed\n");
++
++		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
++		apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
++
++		timeout = 0;
++		do {
++			udelay(100);
++			status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
++		} while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
++
++		switch (status) {
++		case APIC_ICR_RR_VALID:
++			status = apic_read(APIC_RRR);
++			printk(KERN_CONT "%08x\n", status);
++			break;
++		default:
++			printk(KERN_CONT "failed\n");
++		}
++	}
++}
++
++#ifdef WAKE_SECONDARY_VIA_NMI
++/*
++ * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
++ * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
++ * won't ... remember to clear down the APIC, etc later.
++ */
++static int __devinit
++wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
++{
++	unsigned long send_status, accept_status = 0;
++	int maxlvt;
++
++	/* Target chip */
++	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
++
++	/* Boot on the stack */
++	/* Kick the second */
++	apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
++
++	Dprintk("Waiting for send to finish...\n");
++	send_status = safe_apic_wait_icr_idle();
++
++	/*
++	 * Give the other CPU some time to accept the IPI.
++	 */
++	udelay(200);
++	/*
++	 * Due to the Pentium erratum 3AP.
++	 */
++	maxlvt = lapic_get_maxlvt();
++	if (maxlvt > 3) {
++		apic_read_around(APIC_SPIV);
++		apic_write(APIC_ESR, 0);
++	}
++	accept_status = (apic_read(APIC_ESR) & 0xEF);
++	Dprintk("NMI sent.\n");
++
++	if (send_status)
++		printk(KERN_ERR "APIC never delivered???\n");
++	if (accept_status)
++		printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
++
++	return (send_status | accept_status);
++}
++#endif	/* WAKE_SECONDARY_VIA_NMI */
++
++#ifdef WAKE_SECONDARY_VIA_INIT
++static int __devinit
++wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
++{
++	unsigned long send_status, accept_status = 0;
++	int maxlvt, num_starts, j;
++
++	if (get_uv_system_type() == UV_NON_UNIQUE_APIC) {
++		send_status = uv_wakeup_secondary(phys_apicid, start_eip);
++		atomic_set(&init_deasserted, 1);
++		return send_status;
++	}
++
++	/*
++	 * Be paranoid about clearing APIC errors.
++	 */
++	if (APIC_INTEGRATED(apic_version[phys_apicid])) {
++		apic_read_around(APIC_SPIV);
++		apic_write(APIC_ESR, 0);
++		apic_read(APIC_ESR);
++	}
++
++	Dprintk("Asserting INIT.\n");
++
++	/*
++	 * Turn INIT on target chip
++	 */
++	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
++
++	/*
++	 * Send IPI
++	 */
++	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
++				| APIC_DM_INIT);
++
++	Dprintk("Waiting for send to finish...\n");
++	send_status = safe_apic_wait_icr_idle();
++
++	mdelay(10);
++
++	Dprintk("Deasserting INIT.\n");
++
++	/* Target chip */
++	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
++
++	/* Send IPI */
++	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
++
++	Dprintk("Waiting for send to finish...\n");
++	send_status = safe_apic_wait_icr_idle();
++
++	mb();
++	atomic_set(&init_deasserted, 1);
++
++	/*
++	 * Should we send STARTUP IPIs ?
++	 *
++	 * Determine this based on the APIC version.
++	 * If we don't have an integrated APIC, don't send the STARTUP IPIs.
++	 */
++	if (APIC_INTEGRATED(apic_version[phys_apicid]))
++		num_starts = 2;
++	else
++		num_starts = 0;
++
++	/*
++	 * Paravirt / VMI wants a startup IPI hook here to set up the
++	 * target processor state.
++	 */
++	startup_ipi_hook(phys_apicid, (unsigned long) start_secondary,
++#ifdef CONFIG_X86_64
++			 (unsigned long)init_rsp);
++#else
++			 (unsigned long)stack_start.sp);
++#endif
++
++	/*
++	 * Run STARTUP IPI loop.
++	 */
++	Dprintk("#startup loops: %d.\n", num_starts);
++
++	maxlvt = lapic_get_maxlvt();
++
++	for (j = 1; j <= num_starts; j++) {
++		Dprintk("Sending STARTUP #%d.\n", j);
++		apic_read_around(APIC_SPIV);
++		apic_write(APIC_ESR, 0);
++		apic_read(APIC_ESR);
++		Dprintk("After apic_write.\n");
++
++		/*
++		 * STARTUP IPI
++		 */
++
++		/* Target chip */
++		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
++
++		/* Boot on the stack */
++		/* Kick the second */
++		apic_write_around(APIC_ICR, APIC_DM_STARTUP
++					| (start_eip >> 12));
++
++		/*
++		 * Give the other CPU some time to accept the IPI.
++		 */
++		udelay(300);
++
++		Dprintk("Startup point 1.\n");
++
++		Dprintk("Waiting for send to finish...\n");
++		send_status = safe_apic_wait_icr_idle();
++
++		/*
++		 * Give the other CPU some time to accept the IPI.
++		 */
++		udelay(200);
++		/*
++		 * Due to the Pentium erratum 3AP.
++		 */
++		if (maxlvt > 3) {
++			apic_read_around(APIC_SPIV);
++			apic_write(APIC_ESR, 0);
++		}
++		accept_status = (apic_read(APIC_ESR) & 0xEF);
++		if (send_status || accept_status)
++			break;
++	}
++	Dprintk("After Startup.\n");
++
++	if (send_status)
++		printk(KERN_ERR "APIC never delivered???\n");
++	if (accept_status)
++		printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
++
++	return (send_status | accept_status);
++}
++#endif	/* WAKE_SECONDARY_VIA_INIT */
++
++struct create_idle {
++	struct work_struct work;
++	struct task_struct *idle;
++	struct completion done;
++	int cpu;
++};
++
++static void __cpuinit do_fork_idle(struct work_struct *work)
++{
++	struct create_idle *c_idle =
++		container_of(work, struct create_idle, work);
++
++	c_idle->idle = fork_idle(c_idle->cpu);
++	complete(&c_idle->done);
++}
++
++static int __cpuinit do_boot_cpu(int apicid, int cpu)
++/*
++ * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
++ * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
++ * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu.
++ */
++{
++	unsigned long boot_error = 0;
++	int timeout;
++	unsigned long start_ip;
++	unsigned short nmi_high = 0, nmi_low = 0;
++	struct create_idle c_idle = {
++		.cpu = cpu,
++		.done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
++	};
++	INIT_WORK(&c_idle.work, do_fork_idle);
++#ifdef CONFIG_X86_64
++	/* allocate memory for gdts of secondary cpus. Hotplug is considered */
++	if (!cpu_gdt_descr[cpu].address &&
++		!(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
++		printk(KERN_ERR "Failed to allocate GDT for CPU %d\n", cpu);
++		return -1;
++	}
++
++	/* Allocate node local memory for AP pdas */
++	if (cpu_pda(cpu) == &boot_cpu_pda[cpu]) {
++		struct x8664_pda *newpda, *pda;
++		int node = cpu_to_node(cpu);
++		pda = cpu_pda(cpu);
++		newpda = kmalloc_node(sizeof(struct x8664_pda), GFP_ATOMIC,
++				      node);
++		if (newpda) {
++			memcpy(newpda, pda, sizeof(struct x8664_pda));
++			cpu_pda(cpu) = newpda;
++		} else
++			printk(KERN_ERR
++		"Could not allocate node local PDA for CPU %d on node %d\n",
++				cpu, node);
++	}
++#endif
++
++	alternatives_smp_switch(1);
++
++	c_idle.idle = get_idle_for_cpu(cpu);
++
++	/*
++	 * We can't use kernel_thread since we must avoid to
++	 * reschedule the child.
++	 */
++	if (c_idle.idle) {
++		c_idle.idle->thread.sp = (unsigned long) (((struct pt_regs *)
++			(THREAD_SIZE +  task_stack_page(c_idle.idle))) - 1);
++		init_idle(c_idle.idle, cpu);
++		goto do_rest;
++	}
++
++	if (!keventd_up() || current_is_keventd())
++		c_idle.work.func(&c_idle.work);
++	else {
++		schedule_work(&c_idle.work);
++		wait_for_completion(&c_idle.done);
++	}
++
++	if (IS_ERR(c_idle.idle)) {
++		printk("failed fork for CPU %d\n", cpu);
++		return PTR_ERR(c_idle.idle);
++	}
++
++	set_idle_for_cpu(cpu, c_idle.idle);
++do_rest:
++#ifdef CONFIG_X86_32
++	per_cpu(current_task, cpu) = c_idle.idle;
++	init_gdt(cpu);
++	early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
++	c_idle.idle->thread.ip = (unsigned long) start_secondary;
++	/* Stack for startup_32 can be just as for start_secondary onwards */
++	stack_start.sp = (void *) c_idle.idle->thread.sp;
++	irq_ctx_init(cpu);
++#else
++	cpu_pda(cpu)->pcurrent = c_idle.idle;
++	init_rsp = c_idle.idle->thread.sp;
++	load_sp0(&per_cpu(init_tss, cpu), &c_idle.idle->thread);
++	initial_code = (unsigned long)start_secondary;
++	clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
++#endif
++
++	/* start_ip had better be page-aligned! */
++	start_ip = setup_trampoline();
++
++	/* So we see what's up   */
++	printk(KERN_INFO "Booting processor %d/%d ip %lx\n",
++			  cpu, apicid, start_ip);
++
++	/*
++	 * This grunge runs the startup process for
++	 * the targeted processor.
++	 */
++
++	atomic_set(&init_deasserted, 0);
++
++	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
++
++		Dprintk("Setting warm reset code and vector.\n");
++
++		store_NMI_vector(&nmi_high, &nmi_low);
++
++		smpboot_setup_warm_reset_vector(start_ip);
++		/*
++		 * Be paranoid about clearing APIC errors.
++	 	*/
++		apic_write(APIC_ESR, 0);
++		apic_read(APIC_ESR);
++	}
++
++	/*
++	 * Starting actual IPI sequence...
++	 */
++	boot_error = wakeup_secondary_cpu(apicid, start_ip);
++
++	if (!boot_error) {
++		/*
++		 * allow APs to start initializing.
++		 */
++		Dprintk("Before Callout %d.\n", cpu);
++		cpu_set(cpu, cpu_callout_map);
++		Dprintk("After Callout %d.\n", cpu);
++
++		/*
++		 * Wait 5s total for a response
++		 */
++		for (timeout = 0; timeout < 50000; timeout++) {
++			if (cpu_isset(cpu, cpu_callin_map))
++				break;	/* It has booted */
++			udelay(100);
++		}
++
++		if (cpu_isset(cpu, cpu_callin_map)) {
++			/* number CPUs logically, starting from 1 (BSP is 0) */
++			Dprintk("OK.\n");
++			printk(KERN_INFO "CPU%d: ", cpu);
++			print_cpu_info(&cpu_data(cpu));
++			Dprintk("CPU has booted.\n");
++		} else {
++			boot_error = 1;
++			if (*((volatile unsigned char *)trampoline_base)
++					== 0xA5)
++				/* trampoline started but...? */
++				printk(KERN_ERR "Stuck ??\n");
++			else
++				/* trampoline code not run */
++				printk(KERN_ERR "Not responding.\n");
++			if (get_uv_system_type() != UV_NON_UNIQUE_APIC)
++				inquire_remote_apic(apicid);
++		}
++	}
++
++	if (boot_error) {
++		/* Try to put things back the way they were before ... */
++		unmap_cpu_to_logical_apicid(cpu);
++#ifdef CONFIG_X86_64
++		clear_node_cpumask(cpu); /* was set by numa_add_cpu */
++#endif
++		cpu_clear(cpu, cpu_callout_map); /* was set by do_boot_cpu() */
++		cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
++		cpu_clear(cpu, cpu_possible_map);
++		cpu_clear(cpu, cpu_present_map);
++		per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
++	}
++
++	/* mark "stuck" area as not stuck */
++	*((volatile unsigned long *)trampoline_base) = 0;
++
++	/*
++	 * Cleanup possible dangling ends...
++	 */
++	smpboot_restore_warm_reset_vector();
++
++	return boot_error;
++}
++
++int __cpuinit native_cpu_up(unsigned int cpu)
++{
++	int apicid = cpu_present_to_apicid(cpu);
++	unsigned long flags;
++	int err;
++
++	WARN_ON(irqs_disabled());
++
++	Dprintk("++++++++++++++++++++=_---CPU UP  %u\n", cpu);
++
++	if (apicid == BAD_APICID || apicid == boot_cpu_physical_apicid ||
++	    !physid_isset(apicid, phys_cpu_present_map)) {
++		printk(KERN_ERR "%s: bad cpu %d\n", __func__, cpu);
++		return -EINVAL;
++	}
++
++	/*
++	 * Already booted CPU?
++	 */
++	if (cpu_isset(cpu, cpu_callin_map)) {
++		Dprintk("do_boot_cpu %d Already started\n", cpu);
++		return -ENOSYS;
++	}
++
++	/*
++	 * Save current MTRR state in case it was changed since early boot
++	 * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
++	 */
++	mtrr_save_state();
++
++	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
++
++#ifdef CONFIG_X86_32
++	/* init low mem mapping */
++	clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++			min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
++	flush_tlb_all();
++#endif
++
++	err = do_boot_cpu(apicid, cpu);
++	if (err < 0) {
++		Dprintk("do_boot_cpu failed %d\n", err);
++		return err;
++	}
++
++	/*
++	 * Check TSC synchronization with the AP (keep irqs disabled
++	 * while doing so):
++	 */
++	local_irq_save(flags);
++	check_tsc_sync_source(cpu);
++	local_irq_restore(flags);
++
++	while (!cpu_online(cpu)) {
++		cpu_relax();
++		touch_nmi_watchdog();
++	}
++
++	return 0;
++}
++
++/*
++ * Fall back to non SMP mode after errors.
++ *
++ * RED-PEN audit/test this more. I bet there is more state messed up here.
++ */
++static __init void disable_smp(void)
++{
++	cpu_present_map = cpumask_of_cpu(0);
++	cpu_possible_map = cpumask_of_cpu(0);
++#ifdef CONFIG_X86_32
++	smpboot_clear_io_apic_irqs();
++#endif
++	if (smp_found_config)
++		phys_cpu_present_map =
++				physid_mask_of_physid(boot_cpu_physical_apicid);
++	else
++		phys_cpu_present_map = physid_mask_of_physid(0);
++	map_cpu_to_logical_apicid();
++	cpu_set(0, per_cpu(cpu_sibling_map, 0));
++	cpu_set(0, per_cpu(cpu_core_map, 0));
++}
++
++/*
++ * Various sanity checks.
++ */
++static int __init smp_sanity_check(unsigned max_cpus)
++{
++	preempt_disable();
++	if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
++		printk(KERN_WARNING "weird, boot CPU (#%d) not listed"
++				    "by the BIOS.\n", hard_smp_processor_id());
++		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
++	}
++
++	/*
++	 * If we couldn't find an SMP configuration at boot time,
++	 * get out of here now!
++	 */
++	if (!smp_found_config && !acpi_lapic) {
++		preempt_enable();
++		printk(KERN_NOTICE "SMP motherboard not detected.\n");
++		disable_smp();
++		if (APIC_init_uniprocessor())
++			printk(KERN_NOTICE "Local APIC not detected."
++					   " Using dummy APIC emulation.\n");
++		return -1;
++	}
++
++	/*
++	 * Should not be necessary because the MP table should list the boot
++	 * CPU too, but we do it for the sake of robustness anyway.
++	 */
++	if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
++		printk(KERN_NOTICE
++			"weird, boot CPU (#%d) not listed by the BIOS.\n",
++			boot_cpu_physical_apicid);
++		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
++	}
++	preempt_enable();
++
++	/*
++	 * If we couldn't find a local APIC, then get out of here now!
++	 */
++	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) &&
++	    !cpu_has_apic) {
++		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
++			boot_cpu_physical_apicid);
++		printk(KERN_ERR "... forcing use of dummy APIC emulation."
++				"(tell your hw vendor)\n");
++		smpboot_clear_io_apic();
++		return -1;
++	}
++
++	verify_local_APIC();
++
++	/*
++	 * If SMP should be disabled, then really disable it!
++	 */
++	if (!max_cpus) {
++		printk(KERN_INFO "SMP mode deactivated,"
++				 "forcing use of dummy APIC emulation.\n");
++		smpboot_clear_io_apic();
++#ifdef CONFIG_X86_32
++		if (nmi_watchdog == NMI_LOCAL_APIC) {
++			printk(KERN_INFO "activating minimal APIC for"
++					 "NMI watchdog use.\n");
++			connect_bsp_APIC();
++			setup_local_APIC();
++			end_local_APIC_setup();
++		}
++#endif
++		return -1;
++	}
++
++	return 0;
++}
++
++static void __init smp_cpu_index_default(void)
++{
++	int i;
++	struct cpuinfo_x86 *c;
++
++	for_each_possible_cpu(i) {
++		c = &cpu_data(i);
++		/* mark all to hotplug */
++		c->cpu_index = NR_CPUS;
++	}
++}
++
++/*
++ * Prepare for SMP bootup.  The MP table or ACPI has been read
++ * earlier.  Just do some sanity checking here and enable APIC mode.
++ */
++void __init native_smp_prepare_cpus(unsigned int max_cpus)
++{
++	nmi_watchdog_default();
++	smp_cpu_index_default();
++	current_cpu_data = boot_cpu_data;
++	cpu_callin_map = cpumask_of_cpu(0);
++	mb();
++	/*
++	 * Setup boot CPU information
++	 */
++	smp_store_cpu_info(0); /* Final full version of the data */
++	boot_cpu_logical_apicid = logical_smp_processor_id();
++	current_thread_info()->cpu = 0;  /* needed? */
++	set_cpu_sibling_map(0);
++
++	if (smp_sanity_check(max_cpus) < 0) {
++		printk(KERN_INFO "SMP disabled\n");
++		disable_smp();
++		return;
++	}
++
++	preempt_disable();
++	if (GET_APIC_ID(read_apic_id()) != boot_cpu_physical_apicid) {
++		panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
++		     GET_APIC_ID(read_apic_id()), boot_cpu_physical_apicid);
++		/* Or can we switch back to PIC here? */
++	}
++	preempt_enable();
++
++#ifdef CONFIG_X86_32
++	connect_bsp_APIC();
++#endif
++	/*
++	 * Switch from PIC to APIC mode.
++	 */
++	setup_local_APIC();
++
++#ifdef CONFIG_X86_64
++	/*
++	 * Enable IO APIC before setting up error vector
++	 */
++	if (!skip_ioapic_setup && nr_ioapics)
++		enable_IO_APIC();
++#endif
++	end_local_APIC_setup();
++
++	map_cpu_to_logical_apicid();
++
++	setup_portio_remap();
++
++	smpboot_setup_io_apic();
++	/*
++	 * Set up local APIC timer on boot CPU.
++	 */
++
++	printk(KERN_INFO "CPU%d: ", 0);
++	print_cpu_info(&cpu_data(0));
++	setup_boot_clock();
++}
++/*
++ * Early setup to make printk work.
++ */
++void __init native_smp_prepare_boot_cpu(void)
++{
++	int me = smp_processor_id();
++#ifdef CONFIG_X86_32
++	init_gdt(me);
++	switch_to_new_gdt();
++#endif
++	/* already set me in cpu_online_map in boot_cpu_init() */
++	cpu_set(me, cpu_callout_map);
++	per_cpu(cpu_state, me) = CPU_ONLINE;
++}
++
++void __init native_smp_cpus_done(unsigned int max_cpus)
++{
++	Dprintk("Boot done.\n");
++
++	impress_friends();
++	smp_checks();
++#ifdef CONFIG_X86_IO_APIC
++	setup_ioapic_dest();
++#endif
++	check_nmi_watchdog();
++#ifdef CONFIG_X86_32
++	zap_low_mappings();
++#endif
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++
++#  ifdef CONFIG_X86_32
++void cpu_exit_clear(void)
++{
++	int cpu = raw_smp_processor_id();
++
++	idle_task_exit();
++
++	cpu_uninit();
++	irq_ctx_exit(cpu);
++
++	cpu_clear(cpu, cpu_callout_map);
++	cpu_clear(cpu, cpu_callin_map);
++
++	unmap_cpu_to_logical_apicid(cpu);
++}
++#  endif /* CONFIG_X86_32 */
++
++static void remove_siblinginfo(int cpu)
++{
++	int sibling;
++	struct cpuinfo_x86 *c = &cpu_data(cpu);
++
++	for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
++		cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
++		/*/
++		 * last thread sibling in this cpu core going down
++		 */
++		if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
++			cpu_data(sibling).booted_cores--;
++	}
++
++	for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
++		cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
++	cpus_clear(per_cpu(cpu_sibling_map, cpu));
++	cpus_clear(per_cpu(cpu_core_map, cpu));
++	c->phys_proc_id = 0;
++	c->cpu_core_id = 0;
++	cpu_clear(cpu, cpu_sibling_setup_map);
++}
++
++int additional_cpus __initdata = -1;
++
++static __init int setup_additional_cpus(char *s)
++{
++	return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL;
++}
++early_param("additional_cpus", setup_additional_cpus);
++
++/*
++ * cpu_possible_map should be static, it cannot change as cpu's
++ * are onlined, or offlined. The reason is per-cpu data-structures
++ * are allocated by some modules at init time, and dont expect to
++ * do this dynamically on cpu arrival/departure.
++ * cpu_present_map on the other hand can change dynamically.
++ * In case when cpu_hotplug is not compiled, then we resort to current
++ * behaviour, which is cpu_possible == cpu_present.
++ * - Ashok Raj
++ *
++ * Three ways to find out the number of additional hotplug CPUs:
++ * - If the BIOS specified disabled CPUs in ACPI/mptables use that.
++ * - The user can overwrite it with additional_cpus=NUM
++ * - Otherwise don't reserve additional CPUs.
++ * We do this because additional CPUs waste a lot of memory.
++ * -AK
++ */
++__init void prefill_possible_map(void)
++{
++	int i;
++	int possible;
++
++	if (additional_cpus == -1) {
++		if (disabled_cpus > 0)
++			additional_cpus = disabled_cpus;
++		else
++			additional_cpus = 0;
++	}
++	possible = num_processors + additional_cpus;
++	if (possible > NR_CPUS)
++		possible = NR_CPUS;
++
++	printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
++		possible, max_t(int, possible - num_processors, 0));
++
++	for (i = 0; i < possible; i++)
++		cpu_set(i, cpu_possible_map);
++}
++
++static void __ref remove_cpu_from_maps(int cpu)
++{
++	cpu_clear(cpu, cpu_online_map);
++#ifdef CONFIG_X86_64
++	cpu_clear(cpu, cpu_callout_map);
++	cpu_clear(cpu, cpu_callin_map);
++	/* was set by cpu_init() */
++	clear_bit(cpu, (unsigned long *)&cpu_initialized);
++	clear_node_cpumask(cpu);
++#endif
++}
++
++int __cpu_disable(void)
++{
++	int cpu = smp_processor_id();
++
++	/*
++	 * Perhaps use cpufreq to drop frequency, but that could go
++	 * into generic code.
++	 *
++	 * We won't take down the boot processor on i386 due to some
++	 * interrupts only being able to be serviced by the BSP.
++	 * Especially so if we're not using an IOAPIC	-zwane
++	 */
++	if (cpu == 0)
++		return -EBUSY;
++
++	if (nmi_watchdog == NMI_LOCAL_APIC)
++		stop_apic_nmi_watchdog(NULL);
++	clear_local_APIC();
++
++	/*
++	 * HACK:
++	 * Allow any queued timer interrupts to get serviced
++	 * This is only a temporary solution until we cleanup
++	 * fixup_irqs as we do for IA64.
++	 */
++	local_irq_enable();
++	mdelay(1);
++
++	local_irq_disable();
++	remove_siblinginfo(cpu);
++
++	/* It's now safe to remove this processor from the online map */
++	remove_cpu_from_maps(cpu);
++	fixup_irqs(cpu_online_map);
++	return 0;
++}
++
++void __cpu_die(unsigned int cpu)
++{
++	/* We don't do anything here: idle task is faking death itself. */
++	unsigned int i;
++
++	for (i = 0; i < 10; i++) {
++		/* They ack this in play_dead by setting CPU_DEAD */
++		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
++			printk(KERN_INFO "CPU %d is now offline\n", cpu);
++			if (1 == num_online_cpus())
++				alternatives_smp_switch(0);
++			return;
++		}
++		msleep(100);
++	}
++	printk(KERN_ERR "CPU %u didn't die...\n", cpu);
++}
++#else /* ... !CONFIG_HOTPLUG_CPU */
++int __cpu_disable(void)
++{
++	return -ENOSYS;
++}
++
++void __cpu_die(unsigned int cpu)
++{
++	/* We said "no" in __cpu_disable */
++	BUG();
++}
++#endif
++
++/*
++ * If the BIOS enumerates physical processors before logical,
++ * maxcpus=N at enumeration-time can be used to disable HT.
++ */
++static int __init parse_maxcpus(char *arg)
++{
++	extern unsigned int maxcpus;
++
++	maxcpus = simple_strtoul(arg, NULL, 0);
++	return 0;
++}
++early_param("maxcpus", parse_maxcpus);
+diff --git a/arch/x86/kernel/smpboot_32.c b/arch/x86/kernel/smpboot_32.c
+deleted file mode 100644
+index 579b9b7..0000000
+--- a/arch/x86/kernel/smpboot_32.c
++++ /dev/null
+@@ -1,1320 +0,0 @@
+-/*
+- *	x86 SMP booting functions
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- *	(c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
+- *
+- *	Much of the core SMP work is based on previous work by Thomas Radke, to
+- *	whom a great many thanks are extended.
+- *
+- *	Thanks to Intel for making available several different Pentium,
+- *	Pentium Pro and Pentium-II/Xeon MP machines.
+- *	Original development of Linux SMP code supported by Caldera.
+- *
+- *	This code is released under the GNU General Public License version 2 or
+- *	later.
+- *
+- *	Fixes
+- *		Felix Koop	:	NR_CPUS used properly
+- *		Jose Renau	:	Handle single CPU case.
+- *		Alan Cox	:	By repeated request 8) - Total BogoMIPS report.
+- *		Greg Wright	:	Fix for kernel stacks panic.
+- *		Erich Boleyn	:	MP v1.4 and additional changes.
+- *	Matthias Sattler	:	Changes for 2.1 kernel map.
+- *	Michel Lespinasse	:	Changes for 2.1 kernel map.
+- *	Michael Chastain	:	Change trampoline.S to gnu as.
+- *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
+- *		Ingo Molnar	:	Added APIC timers, based on code
+- *					from Jose Renau
+- *		Ingo Molnar	:	various cleanups and rewrites
+- *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
+- *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs
+- *		Martin J. Bligh	: 	Added support for multi-quad systems
+- *		Dave Jones	:	Report invalid combinations of Athlon CPUs.
+-*		Rusty Russell	:	Hacked into shape for new "hotplug" boot process. */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/bootmem.h>
+-#include <linux/notifier.h>
+-#include <linux/cpu.h>
+-#include <linux/percpu.h>
+-#include <linux/nmi.h>
+-
+-#include <linux/delay.h>
+-#include <linux/mc146818rtc.h>
+-#include <asm/tlbflush.h>
+-#include <asm/desc.h>
+-#include <asm/arch_hooks.h>
+-#include <asm/nmi.h>
+-
+-#include <mach_apic.h>
+-#include <mach_wakecpu.h>
+-#include <smpboot_hooks.h>
+-#include <asm/vmi.h>
+-#include <asm/mtrr.h>
+-
+-/* Set if we find a B stepping CPU */
+-static int __cpuinitdata smp_b_stepping;
+-
+-/* Number of siblings per CPU package */
+-int smp_num_siblings = 1;
+-EXPORT_SYMBOL(smp_num_siblings);
+-
+-/* Last level cache ID of each logical CPU */
+-DEFINE_PER_CPU(u8, cpu_llc_id) = BAD_APICID;
+-
+-/* representing HT siblings of each logical CPU */
+-DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
+-EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
+-
+-/* representing HT and core siblings of each logical CPU */
+-DEFINE_PER_CPU(cpumask_t, cpu_core_map);
+-EXPORT_PER_CPU_SYMBOL(cpu_core_map);
+-
+-/* bitmap of online cpus */
+-cpumask_t cpu_online_map __read_mostly;
+-EXPORT_SYMBOL(cpu_online_map);
+-
+-cpumask_t cpu_callin_map;
+-cpumask_t cpu_callout_map;
+-cpumask_t cpu_possible_map;
+-EXPORT_SYMBOL(cpu_possible_map);
+-static cpumask_t smp_commenced_mask;
+-
+-/* Per CPU bogomips and other parameters */
+-DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+-EXPORT_PER_CPU_SYMBOL(cpu_info);
+-
+-/* which logical CPU number maps to which CPU (physical APIC ID) */
+-u8 x86_cpu_to_apicid_init[NR_CPUS] __initdata =
+-			{ [0 ... NR_CPUS-1] = BAD_APICID };
+-void *x86_cpu_to_apicid_early_ptr;
+-DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID;
+-EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
+-
+-u8 apicid_2_node[MAX_APICID];
+-
+-/*
+- * Trampoline 80x86 program as an array.
+- */
+-
+-extern const unsigned char trampoline_data [];
+-extern const unsigned char trampoline_end  [];
+-static unsigned char *trampoline_base;
+-
+-static void map_cpu_to_logical_apicid(void);
+-
+-/* State of each CPU. */
+-DEFINE_PER_CPU(int, cpu_state) = { 0 };
+-
+-/*
+- * Currently trivial. Write the real->protected mode
+- * bootstrap into the page concerned. The caller
+- * has made sure it's suitably aligned.
+- */
+-
+-static unsigned long __cpuinit setup_trampoline(void)
+-{
+-	memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data);
+-	return virt_to_phys(trampoline_base);
+-}
+-
+-/*
+- * We are called very early to get the low memory for the
+- * SMP bootup trampoline page.
+- */
+-void __init smp_alloc_memory(void)
+-{
+-	trampoline_base = alloc_bootmem_low_pages(PAGE_SIZE);
+-	/*
+-	 * Has to be in very low memory so we can execute
+-	 * real-mode AP code.
+-	 */
+-	if (__pa(trampoline_base) >= 0x9F000)
+-		BUG();
+-}
+-
+-/*
+- * The bootstrap kernel entry code has set these up. Save them for
+- * a given CPU
+- */
+-
+-void __cpuinit smp_store_cpu_info(int id)
+-{
+-	struct cpuinfo_x86 *c = &cpu_data(id);
+-
+-	*c = boot_cpu_data;
+-	c->cpu_index = id;
+-	if (id!=0)
+-		identify_secondary_cpu(c);
+-	/*
+-	 * Mask B, Pentium, but not Pentium MMX
+-	 */
+-	if (c->x86_vendor == X86_VENDOR_INTEL &&
+-	    c->x86 == 5 &&
+-	    c->x86_mask >= 1 && c->x86_mask <= 4 &&
+-	    c->x86_model <= 3)
+-		/*
+-		 * Remember we have B step Pentia with bugs
+-		 */
+-		smp_b_stepping = 1;
+-
+-	/*
+-	 * Certain Athlons might work (for various values of 'work') in SMP
+-	 * but they are not certified as MP capable.
+-	 */
+-	if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
+-
+-		if (num_possible_cpus() == 1)
+-			goto valid_k7;
+-
+-		/* Athlon 660/661 is valid. */	
+-		if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1)))
+-			goto valid_k7;
+-
+-		/* Duron 670 is valid */
+-		if ((c->x86_model==7) && (c->x86_mask==0))
+-			goto valid_k7;
+-
+-		/*
+-		 * Athlon 662, Duron 671, and Athlon >model 7 have capability bit.
+-		 * It's worth noting that the A5 stepping (662) of some Athlon XP's
+-		 * have the MP bit set.
+-		 * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for more.
+-		 */
+-		if (((c->x86_model==6) && (c->x86_mask>=2)) ||
+-		    ((c->x86_model==7) && (c->x86_mask>=1)) ||
+-		     (c->x86_model> 7))
+-			if (cpu_has_mp)
+-				goto valid_k7;
+-
+-		/* If we get here, it's not a certified SMP capable AMD system. */
+-		add_taint(TAINT_UNSAFE_SMP);
+-	}
+-
+-valid_k7:
+-	;
+-}
+-
+-static atomic_t init_deasserted;
+-
+-static void __cpuinit smp_callin(void)
+-{
+-	int cpuid, phys_id;
+-	unsigned long timeout;
+-
+-	/*
+-	 * If waken up by an INIT in an 82489DX configuration
+-	 * we may get here before an INIT-deassert IPI reaches
+-	 * our local APIC.  We have to wait for the IPI or we'll
+-	 * lock up on an APIC access.
+-	 */
+-	wait_for_init_deassert(&init_deasserted);
+-
+-	/*
+-	 * (This works even if the APIC is not enabled.)
+-	 */
+-	phys_id = GET_APIC_ID(apic_read(APIC_ID));
+-	cpuid = smp_processor_id();
+-	if (cpu_isset(cpuid, cpu_callin_map)) {
+-		printk("huh, phys CPU#%d, CPU#%d already present??\n",
+-					phys_id, cpuid);
+-		BUG();
+-	}
+-	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
+-
+-	/*
+-	 * STARTUP IPIs are fragile beasts as they might sometimes
+-	 * trigger some glue motherboard logic. Complete APIC bus
+-	 * silence for 1 second, this overestimates the time the
+-	 * boot CPU is spending to send the up to 2 STARTUP IPIs
+-	 * by a factor of two. This should be enough.
+-	 */
+-
+-	/*
+-	 * Waiting 2s total for startup (udelay is not yet working)
+-	 */
+-	timeout = jiffies + 2*HZ;
+-	while (time_before(jiffies, timeout)) {
+-		/*
+-		 * Has the boot CPU finished it's STARTUP sequence?
+-		 */
+-		if (cpu_isset(cpuid, cpu_callout_map))
+-			break;
+-		rep_nop();
+-	}
+-
+-	if (!time_before(jiffies, timeout)) {
+-		printk("BUG: CPU%d started up but did not get a callout!\n",
+-			cpuid);
+-		BUG();
+-	}
+-
+-	/*
+-	 * the boot CPU has finished the init stage and is spinning
+-	 * on callin_map until we finish. We are free to set up this
+-	 * CPU, first the APIC. (this is probably redundant on most
+-	 * boards)
+-	 */
+-
+-	Dprintk("CALLIN, before setup_local_APIC().\n");
+-	smp_callin_clear_local_apic();
+-	setup_local_APIC();
+-	map_cpu_to_logical_apicid();
+-
+-	/*
+-	 * Get our bogomips.
+-	 */
+-	calibrate_delay();
+-	Dprintk("Stack at about %p\n",&cpuid);
+-
+-	/*
+-	 * Save our processor parameters
+-	 */
+-	smp_store_cpu_info(cpuid);
+-
+-	/*
+-	 * Allow the master to continue.
+-	 */
+-	cpu_set(cpuid, cpu_callin_map);
+-}
+-
+-static int cpucount;
+-
+-/* maps the cpu to the sched domain representing multi-core */
+-cpumask_t cpu_coregroup_map(int cpu)
+-{
+-	struct cpuinfo_x86 *c = &cpu_data(cpu);
+-	/*
+-	 * For perf, we return last level cache shared map.
+-	 * And for power savings, we return cpu_core_map
+-	 */
+-	if (sched_mc_power_savings || sched_smt_power_savings)
+-		return per_cpu(cpu_core_map, cpu);
+-	else
+-		return c->llc_shared_map;
+-}
+-
+-/* representing cpus for which sibling maps can be computed */
+-static cpumask_t cpu_sibling_setup_map;
+-
+-void __cpuinit set_cpu_sibling_map(int cpu)
+-{
+-	int i;
+-	struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+-	cpu_set(cpu, cpu_sibling_setup_map);
+-
+-	if (smp_num_siblings > 1) {
+-		for_each_cpu_mask(i, cpu_sibling_setup_map) {
+-			if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
+-			    c->cpu_core_id == cpu_data(i).cpu_core_id) {
+-				cpu_set(i, per_cpu(cpu_sibling_map, cpu));
+-				cpu_set(cpu, per_cpu(cpu_sibling_map, i));
+-				cpu_set(i, per_cpu(cpu_core_map, cpu));
+-				cpu_set(cpu, per_cpu(cpu_core_map, i));
+-				cpu_set(i, c->llc_shared_map);
+-				cpu_set(cpu, cpu_data(i).llc_shared_map);
+-			}
+-		}
+-	} else {
+-		cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
+-	}
+-
+-	cpu_set(cpu, c->llc_shared_map);
+-
+-	if (current_cpu_data.x86_max_cores == 1) {
+-		per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
+-		c->booted_cores = 1;
+-		return;
+-	}
+-
+-	for_each_cpu_mask(i, cpu_sibling_setup_map) {
+-		if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
+-		    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
+-			cpu_set(i, c->llc_shared_map);
+-			cpu_set(cpu, cpu_data(i).llc_shared_map);
+-		}
+-		if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
+-			cpu_set(i, per_cpu(cpu_core_map, cpu));
+-			cpu_set(cpu, per_cpu(cpu_core_map, i));
+-			/*
+-			 *  Does this new cpu bringup a new core?
+-			 */
+-			if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
+-				/*
+-				 * for each core in package, increment
+-				 * the booted_cores for this new cpu
+-				 */
+-				if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
+-					c->booted_cores++;
+-				/*
+-				 * increment the core count for all
+-				 * the other cpus in this package
+-				 */
+-				if (i != cpu)
+-					cpu_data(i).booted_cores++;
+-			} else if (i != cpu && !c->booted_cores)
+-				c->booted_cores = cpu_data(i).booted_cores;
+-		}
+-	}
+-}
+-
+-/*
+- * Activate a secondary processor.
+- */
+-static void __cpuinit start_secondary(void *unused)
+-{
+-	/*
+-	 * Don't put *anything* before cpu_init(), SMP booting is too
+-	 * fragile that we want to limit the things done here to the
+-	 * most necessary things.
+-	 */
+-#ifdef CONFIG_VMI
+-	vmi_bringup();
+-#endif
+-	cpu_init();
+-	preempt_disable();
+-	smp_callin();
+-	while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
+-		rep_nop();
+-	/*
+-	 * Check TSC synchronization with the BP:
+-	 */
+-	check_tsc_sync_target();
+-
+-	setup_secondary_clock();
+-	if (nmi_watchdog == NMI_IO_APIC) {
+-		disable_8259A_irq(0);
+-		enable_NMI_through_LVT0();
+-		enable_8259A_irq(0);
+-	}
+-	/*
+-	 * low-memory mappings have been cleared, flush them from
+-	 * the local TLBs too.
+-	 */
+-	local_flush_tlb();
+-
+-	/* This must be done before setting cpu_online_map */
+-	set_cpu_sibling_map(raw_smp_processor_id());
+-	wmb();
+-
+-	/*
+-	 * We need to hold call_lock, so there is no inconsistency
+-	 * between the time smp_call_function() determines number of
+-	 * IPI recipients, and the time when the determination is made
+-	 * for which cpus receive the IPI. Holding this
+-	 * lock helps us to not include this cpu in a currently in progress
+-	 * smp_call_function().
+-	 */
+-	lock_ipi_call_lock();
+-	cpu_set(smp_processor_id(), cpu_online_map);
+-	unlock_ipi_call_lock();
+-	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+-
+-	/* We can take interrupts now: we're officially "up". */
+-	local_irq_enable();
+-
+-	wmb();
+-	cpu_idle();
+-}
+-
+-/*
+- * Everything has been set up for the secondary
+- * CPUs - they just need to reload everything
+- * from the task structure
+- * This function must not return.
+- */
+-void __devinit initialize_secondary(void)
+-{
+-	/*
+-	 * We don't actually need to load the full TSS,
+-	 * basically just the stack pointer and the ip.
+-	 */
+-
+-	asm volatile(
+-		"movl %0,%%esp\n\t"
+-		"jmp *%1"
+-		:
+-		:"m" (current->thread.sp),"m" (current->thread.ip));
+-}
+-
+-/* Static state in head.S used to set up a CPU */
+-extern struct {
+-	void * sp;
+-	unsigned short ss;
+-} stack_start;
+-
+-#ifdef CONFIG_NUMA
+-
+-/* which logical CPUs are on which nodes */
+-cpumask_t node_to_cpumask_map[MAX_NUMNODES] __read_mostly =
+-				{ [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
+-EXPORT_SYMBOL(node_to_cpumask_map);
+-/* which node each logical CPU is on */
+-int cpu_to_node_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 };
+-EXPORT_SYMBOL(cpu_to_node_map);
+-
+-/* set up a mapping between cpu and node. */
+-static inline void map_cpu_to_node(int cpu, int node)
+-{
+-	printk("Mapping cpu %d to node %d\n", cpu, node);
+-	cpu_set(cpu, node_to_cpumask_map[node]);
+-	cpu_to_node_map[cpu] = node;
+-}
+-
+-/* undo a mapping between cpu and node. */
+-static inline void unmap_cpu_to_node(int cpu)
+-{
+-	int node;
+-
+-	printk("Unmapping cpu %d from all nodes\n", cpu);
+-	for (node = 0; node < MAX_NUMNODES; node ++)
+-		cpu_clear(cpu, node_to_cpumask_map[node]);
+-	cpu_to_node_map[cpu] = 0;
+-}
+-#else /* !CONFIG_NUMA */
+-
+-#define map_cpu_to_node(cpu, node)	({})
+-#define unmap_cpu_to_node(cpu)	({})
+-
+-#endif /* CONFIG_NUMA */
+-
+-u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
+-
+-static void map_cpu_to_logical_apicid(void)
+-{
+-	int cpu = smp_processor_id();
+-	int apicid = logical_smp_processor_id();
+-	int node = apicid_to_node(apicid);
+-
+-	if (!node_online(node))
+-		node = first_online_node;
+-
+-	cpu_2_logical_apicid[cpu] = apicid;
+-	map_cpu_to_node(cpu, node);
+-}
+-
+-static void unmap_cpu_to_logical_apicid(int cpu)
+-{
+-	cpu_2_logical_apicid[cpu] = BAD_APICID;
+-	unmap_cpu_to_node(cpu);
+-}
+-
+-static inline void __inquire_remote_apic(int apicid)
+-{
+-	int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
+-	char *names[] = { "ID", "VERSION", "SPIV" };
+-	int timeout;
+-	unsigned long status;
+-
+-	printk("Inquiring remote APIC #%d...\n", apicid);
+-
+-	for (i = 0; i < ARRAY_SIZE(regs); i++) {
+-		printk("... APIC #%d %s: ", apicid, names[i]);
+-
+-		/*
+-		 * Wait for idle.
+-		 */
+-		status = safe_apic_wait_icr_idle();
+-		if (status)
+-			printk("a previous APIC delivery may have failed\n");
+-
+-		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+-		apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
+-
+-		timeout = 0;
+-		do {
+-			udelay(100);
+-			status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
+-		} while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
+-
+-		switch (status) {
+-		case APIC_ICR_RR_VALID:
+-			status = apic_read(APIC_RRR);
+-			printk("%lx\n", status);
+-			break;
+-		default:
+-			printk("failed\n");
+-		}
+-	}
+-}
+-
+-#ifdef WAKE_SECONDARY_VIA_NMI
+-/* 
+- * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
+- * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
+- * won't ... remember to clear down the APIC, etc later.
+- */
+-static int __devinit
+-wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
+-{
+-	unsigned long send_status, accept_status = 0;
+-	int maxlvt;
+-
+-	/* Target chip */
+-	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
+-
+-	/* Boot on the stack */
+-	/* Kick the second */
+-	apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
+-
+-	Dprintk("Waiting for send to finish...\n");
+-	send_status = safe_apic_wait_icr_idle();
+-
+-	/*
+-	 * Give the other CPU some time to accept the IPI.
+-	 */
+-	udelay(200);
+-	/*
+-	 * Due to the Pentium erratum 3AP.
+-	 */
+-	maxlvt = lapic_get_maxlvt();
+-	if (maxlvt > 3) {
+-		apic_read_around(APIC_SPIV);
+-		apic_write(APIC_ESR, 0);
+-	}
+-	accept_status = (apic_read(APIC_ESR) & 0xEF);
+-	Dprintk("NMI sent.\n");
+-
+-	if (send_status)
+-		printk("APIC never delivered???\n");
+-	if (accept_status)
+-		printk("APIC delivery error (%lx).\n", accept_status);
+-
+-	return (send_status | accept_status);
+-}
+-#endif	/* WAKE_SECONDARY_VIA_NMI */
+-
+-#ifdef WAKE_SECONDARY_VIA_INIT
+-static int __devinit
+-wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
+-{
+-	unsigned long send_status, accept_status = 0;
+-	int maxlvt, num_starts, j;
+-
+-	/*
+-	 * Be paranoid about clearing APIC errors.
+-	 */
+-	if (APIC_INTEGRATED(apic_version[phys_apicid])) {
+-		apic_read_around(APIC_SPIV);
+-		apic_write(APIC_ESR, 0);
+-		apic_read(APIC_ESR);
+-	}
+-
+-	Dprintk("Asserting INIT.\n");
+-
+-	/*
+-	 * Turn INIT on target chip
+-	 */
+-	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+-	/*
+-	 * Send IPI
+-	 */
+-	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+-				| APIC_DM_INIT);
+-
+-	Dprintk("Waiting for send to finish...\n");
+-	send_status = safe_apic_wait_icr_idle();
+-
+-	mdelay(10);
+-
+-	Dprintk("Deasserting INIT.\n");
+-
+-	/* Target chip */
+-	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+-	/* Send IPI */
+-	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+-
+-	Dprintk("Waiting for send to finish...\n");
+-	send_status = safe_apic_wait_icr_idle();
+-
+-	atomic_set(&init_deasserted, 1);
+-
+-	/*
+-	 * Should we send STARTUP IPIs ?
+-	 *
+-	 * Determine this based on the APIC version.
+-	 * If we don't have an integrated APIC, don't send the STARTUP IPIs.
+-	 */
+-	if (APIC_INTEGRATED(apic_version[phys_apicid]))
+-		num_starts = 2;
+-	else
+-		num_starts = 0;
+-
+-	/*
+-	 * Paravirt / VMI wants a startup IPI hook here to set up the
+-	 * target processor state.
+-	 */
+-	startup_ipi_hook(phys_apicid, (unsigned long) start_secondary,
+-		         (unsigned long) stack_start.sp);
+-
+-	/*
+-	 * Run STARTUP IPI loop.
+-	 */
+-	Dprintk("#startup loops: %d.\n", num_starts);
+-
+-	maxlvt = lapic_get_maxlvt();
+-
+-	for (j = 1; j <= num_starts; j++) {
+-		Dprintk("Sending STARTUP #%d.\n",j);
+-		apic_read_around(APIC_SPIV);
+-		apic_write(APIC_ESR, 0);
+-		apic_read(APIC_ESR);
+-		Dprintk("After apic_write.\n");
+-
+-		/*
+-		 * STARTUP IPI
+-		 */
+-
+-		/* Target chip */
+-		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+-		/* Boot on the stack */
+-		/* Kick the second */
+-		apic_write_around(APIC_ICR, APIC_DM_STARTUP
+-					| (start_eip >> 12));
+-
+-		/*
+-		 * Give the other CPU some time to accept the IPI.
+-		 */
+-		udelay(300);
+-
+-		Dprintk("Startup point 1.\n");
+-
+-		Dprintk("Waiting for send to finish...\n");
+-		send_status = safe_apic_wait_icr_idle();
+-
+-		/*
+-		 * Give the other CPU some time to accept the IPI.
+-		 */
+-		udelay(200);
+-		/*
+-		 * Due to the Pentium erratum 3AP.
+-		 */
+-		if (maxlvt > 3) {
+-			apic_read_around(APIC_SPIV);
+-			apic_write(APIC_ESR, 0);
+-		}
+-		accept_status = (apic_read(APIC_ESR) & 0xEF);
+-		if (send_status || accept_status)
+-			break;
+-	}
+-	Dprintk("After Startup.\n");
+-
+-	if (send_status)
+-		printk("APIC never delivered???\n");
+-	if (accept_status)
+-		printk("APIC delivery error (%lx).\n", accept_status);
+-
+-	return (send_status | accept_status);
+-}
+-#endif	/* WAKE_SECONDARY_VIA_INIT */
+-
+-extern cpumask_t cpu_initialized;
+-static inline int alloc_cpu_id(void)
+-{
+-	cpumask_t	tmp_map;
+-	int cpu;
+-	cpus_complement(tmp_map, cpu_present_map);
+-	cpu = first_cpu(tmp_map);
+-	if (cpu >= NR_CPUS)
+-		return -ENODEV;
+-	return cpu;
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-static struct task_struct * __cpuinitdata cpu_idle_tasks[NR_CPUS];
+-static inline struct task_struct * __cpuinit alloc_idle_task(int cpu)
+-{
+-	struct task_struct *idle;
+-
+-	if ((idle = cpu_idle_tasks[cpu]) != NULL) {
+-		/* initialize thread_struct.  we really want to avoid destroy
+-		 * idle tread
+-		 */
+-		idle->thread.sp = (unsigned long)task_pt_regs(idle);
+-		init_idle(idle, cpu);
+-		return idle;
+-	}
+-	idle = fork_idle(cpu);
+-
+-	if (!IS_ERR(idle))
+-		cpu_idle_tasks[cpu] = idle;
+-	return idle;
+-}
+-#else
+-#define alloc_idle_task(cpu) fork_idle(cpu)
+-#endif
+-
+-static int __cpuinit do_boot_cpu(int apicid, int cpu)
+-/*
+- * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
+- * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
+- * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu.
+- */
+-{
+-	struct task_struct *idle;
+-	unsigned long boot_error;
+-	int timeout;
+-	unsigned long start_eip;
+-	unsigned short nmi_high = 0, nmi_low = 0;
+-
+-	/*
+-	 * Save current MTRR state in case it was changed since early boot
+-	 * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
+-	 */
+-	mtrr_save_state();
+-
+-	/*
+-	 * We can't use kernel_thread since we must avoid to
+-	 * reschedule the child.
+-	 */
+-	idle = alloc_idle_task(cpu);
+-	if (IS_ERR(idle))
+-		panic("failed fork for CPU %d", cpu);
+-
+-	init_gdt(cpu);
+- 	per_cpu(current_task, cpu) = idle;
+-	early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
+-
+-	idle->thread.ip = (unsigned long) start_secondary;
+-	/* start_eip had better be page-aligned! */
+-	start_eip = setup_trampoline();
+-
+-	++cpucount;
+-	alternatives_smp_switch(1);
+-
+-	/* So we see what's up   */
+-	printk("Booting processor %d/%d ip %lx\n", cpu, apicid, start_eip);
+-	/* Stack for startup_32 can be just as for start_secondary onwards */
+-	stack_start.sp = (void *) idle->thread.sp;
+-
+-	irq_ctx_init(cpu);
+-
+-	per_cpu(x86_cpu_to_apicid, cpu) = apicid;
+-	/*
+-	 * This grunge runs the startup process for
+-	 * the targeted processor.
+-	 */
+-
+-	atomic_set(&init_deasserted, 0);
+-
+-	Dprintk("Setting warm reset code and vector.\n");
+-
+-	store_NMI_vector(&nmi_high, &nmi_low);
+-
+-	smpboot_setup_warm_reset_vector(start_eip);
+-
+-	/*
+-	 * Starting actual IPI sequence...
+-	 */
+-	boot_error = wakeup_secondary_cpu(apicid, start_eip);
+-
+-	if (!boot_error) {
+-		/*
+-		 * allow APs to start initializing.
+-		 */
+-		Dprintk("Before Callout %d.\n", cpu);
+-		cpu_set(cpu, cpu_callout_map);
+-		Dprintk("After Callout %d.\n", cpu);
+-
+-		/*
+-		 * Wait 5s total for a response
+-		 */
+-		for (timeout = 0; timeout < 50000; timeout++) {
+-			if (cpu_isset(cpu, cpu_callin_map))
+-				break;	/* It has booted */
+-			udelay(100);
+-		}
+-
+-		if (cpu_isset(cpu, cpu_callin_map)) {
+-			/* number CPUs logically, starting from 1 (BSP is 0) */
+-			Dprintk("OK.\n");
+-			printk("CPU%d: ", cpu);
+-			print_cpu_info(&cpu_data(cpu));
+-			Dprintk("CPU has booted.\n");
+-		} else {
+-			boot_error= 1;
+-			if (*((volatile unsigned char *)trampoline_base)
+-					== 0xA5)
+-				/* trampoline started but...? */
+-				printk("Stuck ??\n");
+-			else
+-				/* trampoline code not run */
+-				printk("Not responding.\n");
+-			inquire_remote_apic(apicid);
+-		}
+-	}
+-
+-	if (boot_error) {
+-		/* Try to put things back the way they were before ... */
+-		unmap_cpu_to_logical_apicid(cpu);
+-		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
+-		cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
+-		cpucount--;
+-	} else {
+-		per_cpu(x86_cpu_to_apicid, cpu) = apicid;
+-		cpu_set(cpu, cpu_present_map);
+-	}
+-
+-	/* mark "stuck" area as not stuck */
+-	*((volatile unsigned long *)trampoline_base) = 0;
+-
+-	return boot_error;
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-void cpu_exit_clear(void)
+-{
+-	int cpu = raw_smp_processor_id();
+-
+-	idle_task_exit();
+-
+-	cpucount --;
+-	cpu_uninit();
+-	irq_ctx_exit(cpu);
+-
+-	cpu_clear(cpu, cpu_callout_map);
+-	cpu_clear(cpu, cpu_callin_map);
+-
+-	cpu_clear(cpu, smp_commenced_mask);
+-	unmap_cpu_to_logical_apicid(cpu);
+-}
+-
+-struct warm_boot_cpu_info {
+-	struct completion *complete;
+-	struct work_struct task;
+-	int apicid;
+-	int cpu;
+-};
+-
+-static void __cpuinit do_warm_boot_cpu(struct work_struct *work)
+-{
+-	struct warm_boot_cpu_info *info =
+-		container_of(work, struct warm_boot_cpu_info, task);
+-	do_boot_cpu(info->apicid, info->cpu);
+-	complete(info->complete);
+-}
+-
+-static int __cpuinit __smp_prepare_cpu(int cpu)
+-{
+-	DECLARE_COMPLETION_ONSTACK(done);
+-	struct warm_boot_cpu_info info;
+-	int	apicid, ret;
+-
+-	apicid = per_cpu(x86_cpu_to_apicid, cpu);
+-	if (apicid == BAD_APICID) {
+-		ret = -ENODEV;
+-		goto exit;
+-	}
+-
+-	info.complete = &done;
+-	info.apicid = apicid;
+-	info.cpu = cpu;
+-	INIT_WORK(&info.task, do_warm_boot_cpu);
+-
+-	/* init low mem mapping */
+-	clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+-			min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
+-	flush_tlb_all();
+-	schedule_work(&info.task);
+-	wait_for_completion(&done);
+-
+-	zap_low_mappings();
+-	ret = 0;
+-exit:
+-	return ret;
+-}
+-#endif
+-
+-/*
+- * Cycle through the processors sending APIC IPIs to boot each.
+- */
+-
+-static int boot_cpu_logical_apicid;
+-/* Where the IO area was mapped on multiquad, always 0 otherwise */
+-void *xquad_portio;
+-#ifdef CONFIG_X86_NUMAQ
+-EXPORT_SYMBOL(xquad_portio);
+-#endif
+-
+-static void __init smp_boot_cpus(unsigned int max_cpus)
+-{
+-	int apicid, cpu, bit, kicked;
+-	unsigned long bogosum = 0;
+-
+-	/*
+-	 * Setup boot CPU information
+-	 */
+-	smp_store_cpu_info(0); /* Final full version of the data */
+-	printk("CPU%d: ", 0);
+-	print_cpu_info(&cpu_data(0));
+-
+-	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+-	boot_cpu_logical_apicid = logical_smp_processor_id();
+-	per_cpu(x86_cpu_to_apicid, 0) = boot_cpu_physical_apicid;
+-
+-	current_thread_info()->cpu = 0;
+-
+-	set_cpu_sibling_map(0);
+-
+-	/*
+-	 * If we couldn't find an SMP configuration at boot time,
+-	 * get out of here now!
+-	 */
+-	if (!smp_found_config && !acpi_lapic) {
+-		printk(KERN_NOTICE "SMP motherboard not detected.\n");
+-		smpboot_clear_io_apic_irqs();
+-		phys_cpu_present_map = physid_mask_of_physid(0);
+-		if (APIC_init_uniprocessor())
+-			printk(KERN_NOTICE "Local APIC not detected."
+-					   " Using dummy APIC emulation.\n");
+-		map_cpu_to_logical_apicid();
+-		cpu_set(0, per_cpu(cpu_sibling_map, 0));
+-		cpu_set(0, per_cpu(cpu_core_map, 0));
+-		return;
+-	}
+-
+-	/*
+-	 * Should not be necessary because the MP table should list the boot
+-	 * CPU too, but we do it for the sake of robustness anyway.
+-	 * Makes no sense to do this check in clustered apic mode, so skip it
+-	 */
+-	if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
+-		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
+-				boot_cpu_physical_apicid);
+-		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
+-	}
+-
+-	/*
+-	 * If we couldn't find a local APIC, then get out of here now!
+-	 */
+-	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) {
+-		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+-			boot_cpu_physical_apicid);
+-		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
+-		smpboot_clear_io_apic_irqs();
+-		phys_cpu_present_map = physid_mask_of_physid(0);
+-		map_cpu_to_logical_apicid();
+-		cpu_set(0, per_cpu(cpu_sibling_map, 0));
+-		cpu_set(0, per_cpu(cpu_core_map, 0));
+-		return;
+-	}
+-
+-	verify_local_APIC();
+-
+-	/*
+-	 * If SMP should be disabled, then really disable it!
+-	 */
+-	if (!max_cpus) {
+-		smp_found_config = 0;
+-		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
+-
+-		if (nmi_watchdog == NMI_LOCAL_APIC) {
+-			printk(KERN_INFO "activating minimal APIC for NMI watchdog use.\n");
+-			connect_bsp_APIC();
+-			setup_local_APIC();
+-		}
+-		smpboot_clear_io_apic_irqs();
+-		phys_cpu_present_map = physid_mask_of_physid(0);
+-		map_cpu_to_logical_apicid();
+-		cpu_set(0, per_cpu(cpu_sibling_map, 0));
+-		cpu_set(0, per_cpu(cpu_core_map, 0));
+-		return;
+-	}
+-
+-	connect_bsp_APIC();
+-	setup_local_APIC();
+-	map_cpu_to_logical_apicid();
+-
+-
+-	setup_portio_remap();
+-
+-	/*
+-	 * Scan the CPU present map and fire up the other CPUs via do_boot_cpu
+-	 *
+-	 * In clustered apic mode, phys_cpu_present_map is a constructed thus:
+-	 * bits 0-3 are quad0, 4-7 are quad1, etc. A perverse twist on the 
+-	 * clustered apic ID.
+-	 */
+-	Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map));
+-
+-	kicked = 1;
+-	for (bit = 0; kicked < NR_CPUS && bit < MAX_APICS; bit++) {
+-		apicid = cpu_present_to_apicid(bit);
+-		/*
+-		 * Don't even attempt to start the boot CPU!
+-		 */
+-		if ((apicid == boot_cpu_apicid) || (apicid == BAD_APICID))
+-			continue;
+-
+-		if (!check_apicid_present(bit))
+-			continue;
+-		if (max_cpus <= cpucount+1)
+-			continue;
+-
+-		if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
+-			printk("CPU #%d not responding - cannot use it.\n",
+-								apicid);
+-		else
+-			++kicked;
+-	}
+-
+-	/*
+-	 * Cleanup possible dangling ends...
+-	 */
+-	smpboot_restore_warm_reset_vector();
+-
+-	/*
+-	 * Allow the user to impress friends.
+-	 */
+-	Dprintk("Before bogomips.\n");
+-	for_each_possible_cpu(cpu)
+-		if (cpu_isset(cpu, cpu_callout_map))
+-			bogosum += cpu_data(cpu).loops_per_jiffy;
+-	printk(KERN_INFO
+-		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
+-		cpucount+1,
+-		bogosum/(500000/HZ),
+-		(bogosum/(5000/HZ))%100);
+-	
+-	Dprintk("Before bogocount - setting activated=1.\n");
+-
+-	if (smp_b_stepping)
+-		printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
+-
+-	/*
+-	 * Don't taint if we are running SMP kernel on a single non-MP
+-	 * approved Athlon
+-	 */
+-	if (tainted & TAINT_UNSAFE_SMP) {
+-		if (cpucount)
+-			printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n");
+-		else
+-			tainted &= ~TAINT_UNSAFE_SMP;
+-	}
+-
+-	Dprintk("Boot done.\n");
+-
+-	/*
+-	 * construct cpu_sibling_map, so that we can tell sibling CPUs
+-	 * efficiently.
+-	 */
+-	for_each_possible_cpu(cpu) {
+-		cpus_clear(per_cpu(cpu_sibling_map, cpu));
+-		cpus_clear(per_cpu(cpu_core_map, cpu));
+-	}
+-
+-	cpu_set(0, per_cpu(cpu_sibling_map, 0));
+-	cpu_set(0, per_cpu(cpu_core_map, 0));
+-
+-	smpboot_setup_io_apic();
+-
+-	setup_boot_clock();
+-}
+-
+-/* These are wrappers to interface to the new boot process.  Someone
+-   who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
+-void __init native_smp_prepare_cpus(unsigned int max_cpus)
+-{
+-	smp_commenced_mask = cpumask_of_cpu(0);
+-	cpu_callin_map = cpumask_of_cpu(0);
+-	mb();
+-	smp_boot_cpus(max_cpus);
+-}
+-
+-void __init native_smp_prepare_boot_cpu(void)
+-{
+-	unsigned int cpu = smp_processor_id();
+-
+-	init_gdt(cpu);
+-	switch_to_new_gdt();
+-
+-	cpu_set(cpu, cpu_online_map);
+-	cpu_set(cpu, cpu_callout_map);
+-	cpu_set(cpu, cpu_present_map);
+-	cpu_set(cpu, cpu_possible_map);
+-	__get_cpu_var(cpu_state) = CPU_ONLINE;
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-void remove_siblinginfo(int cpu)
+-{
+-	int sibling;
+-	struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+-	for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
+-		cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
+-		/*/
+-		 * last thread sibling in this cpu core going down
+-		 */
+-		if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
+-			cpu_data(sibling).booted_cores--;
+-	}
+-			
+-	for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
+-		cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
+-	cpus_clear(per_cpu(cpu_sibling_map, cpu));
+-	cpus_clear(per_cpu(cpu_core_map, cpu));
+-	c->phys_proc_id = 0;
+-	c->cpu_core_id = 0;
+-	cpu_clear(cpu, cpu_sibling_setup_map);
+-}
+-
+-int __cpu_disable(void)
+-{
+-	cpumask_t map = cpu_online_map;
+-	int cpu = smp_processor_id();
+-
+-	/*
+-	 * Perhaps use cpufreq to drop frequency, but that could go
+-	 * into generic code.
+- 	 *
+-	 * We won't take down the boot processor on i386 due to some
+-	 * interrupts only being able to be serviced by the BSP.
+-	 * Especially so if we're not using an IOAPIC	-zwane
+-	 */
+-	if (cpu == 0)
+-		return -EBUSY;
+-	if (nmi_watchdog == NMI_LOCAL_APIC)
+-		stop_apic_nmi_watchdog(NULL);
+-	clear_local_APIC();
+-	/* Allow any queued timer interrupts to get serviced */
+-	local_irq_enable();
+-	mdelay(1);
+-	local_irq_disable();
+-
+-	remove_siblinginfo(cpu);
+-
+-	cpu_clear(cpu, map);
+-	fixup_irqs(map);
+-	/* It's now safe to remove this processor from the online map */
+-	cpu_clear(cpu, cpu_online_map);
+-	return 0;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+-	/* We don't do anything here: idle task is faking death itself. */
+-	unsigned int i;
+-
+-	for (i = 0; i < 10; i++) {
+-		/* They ack this in play_dead by setting CPU_DEAD */
+-		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+-			printk ("CPU %d is now offline\n", cpu);
+-			if (1 == num_online_cpus())
+-				alternatives_smp_switch(0);
+-			return;
+-		}
+-		msleep(100);
+-	}
+- 	printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+-}
+-#else /* ... !CONFIG_HOTPLUG_CPU */
+-int __cpu_disable(void)
+-{
+-	return -ENOSYS;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+-	/* We said "no" in __cpu_disable */
+-	BUG();
+-}
+-#endif /* CONFIG_HOTPLUG_CPU */
+-
+-int __cpuinit native_cpu_up(unsigned int cpu)
+-{
+-	unsigned long flags;
+-#ifdef CONFIG_HOTPLUG_CPU
+-	int ret = 0;
+-
+-	/*
+-	 * We do warm boot only on cpus that had booted earlier
+-	 * Otherwise cold boot is all handled from smp_boot_cpus().
+-	 * cpu_callin_map is set during AP kickstart process. Its reset
+-	 * when a cpu is taken offline from cpu_exit_clear().
+-	 */
+-	if (!cpu_isset(cpu, cpu_callin_map))
+-		ret = __smp_prepare_cpu(cpu);
+-
+-	if (ret)
+-		return -EIO;
+-#endif
+-
+-	/* In case one didn't come up */
+-	if (!cpu_isset(cpu, cpu_callin_map)) {
+-		printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
+-		return -EIO;
+-	}
+-
+-	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+-	/* Unleash the CPU! */
+-	cpu_set(cpu, smp_commenced_mask);
+-
+-	/*
+-	 * Check TSC synchronization with the AP (keep irqs disabled
+-	 * while doing so):
+-	 */
+-	local_irq_save(flags);
+-	check_tsc_sync_source(cpu);
+-	local_irq_restore(flags);
+-
+-	while (!cpu_isset(cpu, cpu_online_map)) {
+-		cpu_relax();
+-		touch_nmi_watchdog();
+-	}
+-
+-	return 0;
+-}
+-
+-void __init native_smp_cpus_done(unsigned int max_cpus)
+-{
+-#ifdef CONFIG_X86_IO_APIC
+-	setup_ioapic_dest();
+-#endif
+-	zap_low_mappings();
+-}
+-
+-void __init smp_intr_init(void)
+-{
+-	/*
+-	 * IRQ0 must be given a fixed assignment and initialized,
+-	 * because it's used before the IO-APIC is set up.
+-	 */
+-	set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
+-
+-	/*
+-	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
+-	 * IPI, driven by wakeup.
+-	 */
+-	set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
+-
+-	/* IPI for invalidation */
+-	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+-
+-	/* IPI for generic function call */
+-	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+-}
+-
+-/*
+- * If the BIOS enumerates physical processors before logical,
+- * maxcpus=N at enumeration-time can be used to disable HT.
+- */
+-static int __init parse_maxcpus(char *arg)
+-{
+-	extern unsigned int maxcpus;
+-
+-	maxcpus = simple_strtoul(arg, NULL, 0);
+-	return 0;
+-}
+-early_param("maxcpus", parse_maxcpus);
+diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c
+deleted file mode 100644
+index 0880f2c..0000000
+--- a/arch/x86/kernel/smpboot_64.c
++++ /dev/null
+@@ -1,1108 +0,0 @@
+-/*
+- *	x86 SMP booting functions
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- *	(c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
+- *	Copyright 2001 Andi Kleen, SuSE Labs.
+- *
+- *	Much of the core SMP work is based on previous work by Thomas Radke, to
+- *	whom a great many thanks are extended.
+- *
+- *	Thanks to Intel for making available several different Pentium,
+- *	Pentium Pro and Pentium-II/Xeon MP machines.
+- *	Original development of Linux SMP code supported by Caldera.
+- *
+- *	This code is released under the GNU General Public License version 2
+- *
+- *	Fixes
+- *		Felix Koop	:	NR_CPUS used properly
+- *		Jose Renau	:	Handle single CPU case.
+- *		Alan Cox	:	By repeated request 8) - Total BogoMIP report.
+- *		Greg Wright	:	Fix for kernel stacks panic.
+- *		Erich Boleyn	:	MP v1.4 and additional changes.
+- *	Matthias Sattler	:	Changes for 2.1 kernel map.
+- *	Michel Lespinasse	:	Changes for 2.1 kernel map.
+- *	Michael Chastain	:	Change trampoline.S to gnu as.
+- *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
+- *		Ingo Molnar	:	Added APIC timers, based on code
+- *					from Jose Renau
+- *		Ingo Molnar	:	various cleanups and rewrites
+- *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
+- *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs
+- *	Andi Kleen		:	Changed for SMP boot into long mode.
+- *		Rusty Russell	:	Hacked into shape for new "hotplug" boot process.
+- *      Andi Kleen              :       Converted to new state machine.
+- *					Various cleanups.
+- *					Probably mostly hotplug CPU ready now.
+- *	Ashok Raj			: CPU hotplug support
+- */
+-
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/bootmem.h>
+-#include <linux/thread_info.h>
+-#include <linux/module.h>
+-#include <linux/delay.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/smp.h>
+-#include <linux/kdebug.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/pgalloc.h>
+-#include <asm/desc.h>
+-#include <asm/tlbflush.h>
+-#include <asm/proto.h>
+-#include <asm/nmi.h>
+-#include <asm/irq.h>
+-#include <asm/hw_irq.h>
+-#include <asm/numa.h>
+-
+-/* Number of siblings per CPU package */
+-int smp_num_siblings = 1;
+-EXPORT_SYMBOL(smp_num_siblings);
+-
+-/* Last level cache ID of each logical CPU */
+-DEFINE_PER_CPU(u16, cpu_llc_id) = BAD_APICID;
+-
+-/* Bitmask of currently online CPUs */
+-cpumask_t cpu_online_map __read_mostly;
+-
+-EXPORT_SYMBOL(cpu_online_map);
+-
+-/*
+- * Private maps to synchronize booting between AP and BP.
+- * Probably not needed anymore, but it makes for easier debugging. -AK
+- */
+-cpumask_t cpu_callin_map;
+-cpumask_t cpu_callout_map;
+-cpumask_t cpu_possible_map;
+-EXPORT_SYMBOL(cpu_possible_map);
+-
+-/* Per CPU bogomips and other parameters */
+-DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+-EXPORT_PER_CPU_SYMBOL(cpu_info);
+-
+-/* Set when the idlers are all forked */
+-int smp_threads_ready;
+-
+-/* representing HT siblings of each logical CPU */
+-DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
+-EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
+-
+-/* representing HT and core siblings of each logical CPU */
+-DEFINE_PER_CPU(cpumask_t, cpu_core_map);
+-EXPORT_PER_CPU_SYMBOL(cpu_core_map);
+-
+-/*
+- * Trampoline 80x86 program as an array.
+- */
+-
+-extern const unsigned char trampoline_data[];
+-extern const unsigned char trampoline_end[];
+-
+-/* State of each CPU */
+-DEFINE_PER_CPU(int, cpu_state) = { 0 };
+-
+-/*
+- * Store all idle threads, this can be reused instead of creating
+- * a new thread. Also avoids complicated thread destroy functionality
+- * for idle threads.
+- */
+-#ifdef CONFIG_HOTPLUG_CPU
+-/*
+- * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is
+- * removed after init for !CONFIG_HOTPLUG_CPU.
+- */
+-static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
+-#define get_idle_for_cpu(x)     (per_cpu(idle_thread_array, x))
+-#define set_idle_for_cpu(x,p)   (per_cpu(idle_thread_array, x) = (p))
+-#else
+-struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
+-#define get_idle_for_cpu(x)     (idle_thread_array[(x)])
+-#define set_idle_for_cpu(x,p)   (idle_thread_array[(x)] = (p))
+-#endif
+-
+-
+-/*
+- * Currently trivial. Write the real->protected mode
+- * bootstrap into the page concerned. The caller
+- * has made sure it's suitably aligned.
+- */
+-
+-static unsigned long __cpuinit setup_trampoline(void)
+-{
+-	void *tramp = __va(SMP_TRAMPOLINE_BASE); 
+-	memcpy(tramp, trampoline_data, trampoline_end - trampoline_data);
+-	return virt_to_phys(tramp);
+-}
+-
+-/*
+- * The bootstrap kernel entry code has set these up. Save them for
+- * a given CPU
+- */
+-
+-static void __cpuinit smp_store_cpu_info(int id)
+-{
+-	struct cpuinfo_x86 *c = &cpu_data(id);
+-
+-	*c = boot_cpu_data;
+-	c->cpu_index = id;
+-	identify_cpu(c);
+-	print_cpu_info(c);
+-}
+-
+-static atomic_t init_deasserted __cpuinitdata;
+-
+-/*
+- * Report back to the Boot Processor.
+- * Running on AP.
+- */
+-void __cpuinit smp_callin(void)
+-{
+-	int cpuid, phys_id;
+-	unsigned long timeout;
+-
+-	/*
+-	 * If waken up by an INIT in an 82489DX configuration
+-	 * we may get here before an INIT-deassert IPI reaches
+-	 * our local APIC.  We have to wait for the IPI or we'll
+-	 * lock up on an APIC access.
+-	 */
+-	while (!atomic_read(&init_deasserted))
+-		cpu_relax();
+-
+-	/*
+-	 * (This works even if the APIC is not enabled.)
+-	 */
+-	phys_id = GET_APIC_ID(apic_read(APIC_ID));
+-	cpuid = smp_processor_id();
+-	if (cpu_isset(cpuid, cpu_callin_map)) {
+-		panic("smp_callin: phys CPU#%d, CPU#%d already present??\n",
+-					phys_id, cpuid);
+-	}
+-	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
+-
+-	/*
+-	 * STARTUP IPIs are fragile beasts as they might sometimes
+-	 * trigger some glue motherboard logic. Complete APIC bus
+-	 * silence for 1 second, this overestimates the time the
+-	 * boot CPU is spending to send the up to 2 STARTUP IPIs
+-	 * by a factor of two. This should be enough.
+-	 */
+-
+-	/*
+-	 * Waiting 2s total for startup (udelay is not yet working)
+-	 */
+-	timeout = jiffies + 2*HZ;
+-	while (time_before(jiffies, timeout)) {
+-		/*
+-		 * Has the boot CPU finished it's STARTUP sequence?
+-		 */
+-		if (cpu_isset(cpuid, cpu_callout_map))
+-			break;
+-		cpu_relax();
+-	}
+-
+-	if (!time_before(jiffies, timeout)) {
+-		panic("smp_callin: CPU%d started up but did not get a callout!\n",
+-			cpuid);
+-	}
+-
+-	/*
+-	 * the boot CPU has finished the init stage and is spinning
+-	 * on callin_map until we finish. We are free to set up this
+-	 * CPU, first the APIC. (this is probably redundant on most
+-	 * boards)
+-	 */
+-
+-	Dprintk("CALLIN, before setup_local_APIC().\n");
+-	setup_local_APIC();
+-	end_local_APIC_setup();
+-
+-	/*
+-	 * Get our bogomips.
+- 	 *
+- 	 * Need to enable IRQs because it can take longer and then
+-	 * the NMI watchdog might kill us.
+-	 */
+-	local_irq_enable();
+-	calibrate_delay();
+-	local_irq_disable();
+-	Dprintk("Stack at about %p\n",&cpuid);
+-
+-	/*
+-	 * Save our processor parameters
+-	 */
+- 	smp_store_cpu_info(cpuid);
+-
+-	/*
+-	 * Allow the master to continue.
+-	 */
+-	cpu_set(cpuid, cpu_callin_map);
+-}
+-
+-/* maps the cpu to the sched domain representing multi-core */
+-cpumask_t cpu_coregroup_map(int cpu)
+-{
+-	struct cpuinfo_x86 *c = &cpu_data(cpu);
+-	/*
+-	 * For perf, we return last level cache shared map.
+-	 * And for power savings, we return cpu_core_map
+-	 */
+-	if (sched_mc_power_savings || sched_smt_power_savings)
+-		return per_cpu(cpu_core_map, cpu);
+-	else
+-		return c->llc_shared_map;
+-}
+-
+-/* representing cpus for which sibling maps can be computed */
+-static cpumask_t cpu_sibling_setup_map;
+-
+-static inline void set_cpu_sibling_map(int cpu)
+-{
+-	int i;
+-	struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+-	cpu_set(cpu, cpu_sibling_setup_map);
+-
+-	if (smp_num_siblings > 1) {
+-		for_each_cpu_mask(i, cpu_sibling_setup_map) {
+-			if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
+-			    c->cpu_core_id == cpu_data(i).cpu_core_id) {
+-				cpu_set(i, per_cpu(cpu_sibling_map, cpu));
+-				cpu_set(cpu, per_cpu(cpu_sibling_map, i));
+-				cpu_set(i, per_cpu(cpu_core_map, cpu));
+-				cpu_set(cpu, per_cpu(cpu_core_map, i));
+-				cpu_set(i, c->llc_shared_map);
+-				cpu_set(cpu, cpu_data(i).llc_shared_map);
+-			}
+-		}
+-	} else {
+-		cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
+-	}
+-
+-	cpu_set(cpu, c->llc_shared_map);
+-
+-	if (current_cpu_data.x86_max_cores == 1) {
+-		per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
+-		c->booted_cores = 1;
+-		return;
+-	}
+-
+-	for_each_cpu_mask(i, cpu_sibling_setup_map) {
+-		if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
+-		    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
+-			cpu_set(i, c->llc_shared_map);
+-			cpu_set(cpu, cpu_data(i).llc_shared_map);
+-		}
+-		if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
+-			cpu_set(i, per_cpu(cpu_core_map, cpu));
+-			cpu_set(cpu, per_cpu(cpu_core_map, i));
+-			/*
+-			 *  Does this new cpu bringup a new core?
+-			 */
+-			if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
+-				/*
+-				 * for each core in package, increment
+-				 * the booted_cores for this new cpu
+-				 */
+-				if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
+-					c->booted_cores++;
+-				/*
+-				 * increment the core count for all
+-				 * the other cpus in this package
+-				 */
+-				if (i != cpu)
+-					cpu_data(i).booted_cores++;
+-			} else if (i != cpu && !c->booted_cores)
+-				c->booted_cores = cpu_data(i).booted_cores;
+-		}
+-	}
+-}
+-
+-/*
+- * Setup code on secondary processor (after comming out of the trampoline)
+- */
+-void __cpuinit start_secondary(void)
+-{
+-	/*
+-	 * Dont put anything before smp_callin(), SMP
+-	 * booting is too fragile that we want to limit the
+-	 * things done here to the most necessary things.
+-	 */
+-	cpu_init();
+-	preempt_disable();
+-	smp_callin();
+-
+-	/* otherwise gcc will move up the smp_processor_id before the cpu_init */
+-	barrier();
+-
+-	/*
+-  	 * Check TSC sync first:
+- 	 */
+-	check_tsc_sync_target();
+-
+-	if (nmi_watchdog == NMI_IO_APIC) {
+-		disable_8259A_irq(0);
+-		enable_NMI_through_LVT0();
+-		enable_8259A_irq(0);
+-	}
+-
+-	/*
+-	 * The sibling maps must be set before turing the online map on for
+-	 * this cpu
+-	 */
+-	set_cpu_sibling_map(smp_processor_id());
+-
+-	/*
+-	 * We need to hold call_lock, so there is no inconsistency
+-	 * between the time smp_call_function() determines number of
+-	 * IPI recipients, and the time when the determination is made
+-	 * for which cpus receive the IPI in genapic_flat.c. Holding this
+-	 * lock helps us to not include this cpu in a currently in progress
+-	 * smp_call_function().
+-	 */
+-	lock_ipi_call_lock();
+-	spin_lock(&vector_lock);
+-
+-	/* Setup the per cpu irq handling data structures */
+-	__setup_vector_irq(smp_processor_id());
+-	/*
+-	 * Allow the master to continue.
+-	 */
+-	cpu_set(smp_processor_id(), cpu_online_map);
+-	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+-	spin_unlock(&vector_lock);
+-
+-	unlock_ipi_call_lock();
+-
+-	setup_secondary_clock();
+-
+-	cpu_idle();
+-}
+-
+-extern volatile unsigned long init_rsp;
+-extern void (*initial_code)(void);
+-
+-#ifdef APIC_DEBUG
+-static void inquire_remote_apic(int apicid)
+-{
+-	unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
+-	char *names[] = { "ID", "VERSION", "SPIV" };
+-	int timeout;
+-	u32 status;
+-
+-	printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid);
+-
+-	for (i = 0; i < ARRAY_SIZE(regs); i++) {
+-		printk(KERN_INFO "... APIC #%d %s: ", apicid, names[i]);
+-
+-		/*
+-		 * Wait for idle.
+-		 */
+-		status = safe_apic_wait_icr_idle();
+-		if (status)
+-			printk(KERN_CONT
+-			       "a previous APIC delivery may have failed\n");
+-
+-		apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+-		apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
+-
+-		timeout = 0;
+-		do {
+-			udelay(100);
+-			status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
+-		} while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
+-
+-		switch (status) {
+-		case APIC_ICR_RR_VALID:
+-			status = apic_read(APIC_RRR);
+-			printk(KERN_CONT "%08x\n", status);
+-			break;
+-		default:
+-			printk(KERN_CONT "failed\n");
+-		}
+-	}
+-}
+-#endif
+-
+-/*
+- * Kick the secondary to wake up.
+- */
+-static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int start_rip)
+-{
+-	unsigned long send_status, accept_status = 0;
+-	int maxlvt, num_starts, j;
+-
+-	Dprintk("Asserting INIT.\n");
+-
+-	/*
+-	 * Turn INIT on target chip
+-	 */
+-	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+-	/*
+-	 * Send IPI
+-	 */
+-	apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+-				| APIC_DM_INIT);
+-
+-	Dprintk("Waiting for send to finish...\n");
+-	send_status = safe_apic_wait_icr_idle();
+-
+-	mdelay(10);
+-
+-	Dprintk("Deasserting INIT.\n");
+-
+-	/* Target chip */
+-	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+-	/* Send IPI */
+-	apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+-
+-	Dprintk("Waiting for send to finish...\n");
+-	send_status = safe_apic_wait_icr_idle();
+-
+-	mb();
+-	atomic_set(&init_deasserted, 1);
+-
+-	num_starts = 2;
+-
+-	/*
+-	 * Run STARTUP IPI loop.
+-	 */
+-	Dprintk("#startup loops: %d.\n", num_starts);
+-
+-	maxlvt = lapic_get_maxlvt();
+-
+-	for (j = 1; j <= num_starts; j++) {
+-		Dprintk("Sending STARTUP #%d.\n",j);
+-		apic_write(APIC_ESR, 0);
+-		apic_read(APIC_ESR);
+-		Dprintk("After apic_write.\n");
+-
+-		/*
+-		 * STARTUP IPI
+-		 */
+-
+-		/* Target chip */
+-		apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+-		/* Boot on the stack */
+-		/* Kick the second */
+-		apic_write(APIC_ICR, APIC_DM_STARTUP | (start_rip >> 12));
+-
+-		/*
+-		 * Give the other CPU some time to accept the IPI.
+-		 */
+-		udelay(300);
+-
+-		Dprintk("Startup point 1.\n");
+-
+-		Dprintk("Waiting for send to finish...\n");
+-		send_status = safe_apic_wait_icr_idle();
+-
+-		/*
+-		 * Give the other CPU some time to accept the IPI.
+-		 */
+-		udelay(200);
+-		/*
+-		 * Due to the Pentium erratum 3AP.
+-		 */
+-		if (maxlvt > 3) {
+-			apic_write(APIC_ESR, 0);
+-		}
+-		accept_status = (apic_read(APIC_ESR) & 0xEF);
+-		if (send_status || accept_status)
+-			break;
+-	}
+-	Dprintk("After Startup.\n");
+-
+-	if (send_status)
+-		printk(KERN_ERR "APIC never delivered???\n");
+-	if (accept_status)
+-		printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
+-
+-	return (send_status | accept_status);
+-}
+-
+-struct create_idle {
+-	struct work_struct work;
+-	struct task_struct *idle;
+-	struct completion done;
+-	int cpu;
+-};
+-
+-static void __cpuinit do_fork_idle(struct work_struct *work)
+-{
+-	struct create_idle *c_idle =
+-		container_of(work, struct create_idle, work);
+-
+-	c_idle->idle = fork_idle(c_idle->cpu);
+-	complete(&c_idle->done);
+-}
+-
+-/*
+- * Boot one CPU.
+- */
+-static int __cpuinit do_boot_cpu(int cpu, int apicid)
+-{
+-	unsigned long boot_error;
+-	int timeout;
+-	unsigned long start_rip;
+-	struct create_idle c_idle = {
+-		.cpu = cpu,
+-		.done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
+-	};
+-	INIT_WORK(&c_idle.work, do_fork_idle);
+-
+-	/* allocate memory for gdts of secondary cpus. Hotplug is considered */
+-	if (!cpu_gdt_descr[cpu].address &&
+-		!(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
+-		printk(KERN_ERR "Failed to allocate GDT for CPU %d\n", cpu);
+-		return -1;
+-	}
+-
+-	/* Allocate node local memory for AP pdas */
+-	if (cpu_pda(cpu) == &boot_cpu_pda[cpu]) {
+-		struct x8664_pda *newpda, *pda;
+-		int node = cpu_to_node(cpu);
+-		pda = cpu_pda(cpu);
+-		newpda = kmalloc_node(sizeof (struct x8664_pda), GFP_ATOMIC,
+-				      node);
+-		if (newpda) {
+-			memcpy(newpda, pda, sizeof (struct x8664_pda));
+-			cpu_pda(cpu) = newpda;
+-		} else
+-			printk(KERN_ERR
+-		"Could not allocate node local PDA for CPU %d on node %d\n",
+-				cpu, node);
+-	}
+-
+-	alternatives_smp_switch(1);
+-
+-	c_idle.idle = get_idle_for_cpu(cpu);
+-
+-	if (c_idle.idle) {
+-		c_idle.idle->thread.sp = (unsigned long) (((struct pt_regs *)
+-			(THREAD_SIZE +  task_stack_page(c_idle.idle))) - 1);
+-		init_idle(c_idle.idle, cpu);
+-		goto do_rest;
+-	}
+-
+-	/*
+-	 * During cold boot process, keventd thread is not spun up yet.
+-	 * When we do cpu hot-add, we create idle threads on the fly, we should
+-	 * not acquire any attributes from the calling context. Hence the clean
+-	 * way to create kernel_threads() is to do that from keventd().
+-	 * We do the current_is_keventd() due to the fact that ACPI notifier
+-	 * was also queuing to keventd() and when the caller is already running
+-	 * in context of keventd(), we would end up with locking up the keventd
+-	 * thread.
+-	 */
+-	if (!keventd_up() || current_is_keventd())
+-		c_idle.work.func(&c_idle.work);
+-	else {
+-		schedule_work(&c_idle.work);
+-		wait_for_completion(&c_idle.done);
+-	}
+-
+-	if (IS_ERR(c_idle.idle)) {
+-		printk("failed fork for CPU %d\n", cpu);
+-		return PTR_ERR(c_idle.idle);
+-	}
+-
+-	set_idle_for_cpu(cpu, c_idle.idle);
+-
+-do_rest:
+-
+-	cpu_pda(cpu)->pcurrent = c_idle.idle;
+-
+-	start_rip = setup_trampoline();
+-
+-	init_rsp = c_idle.idle->thread.sp;
+-	load_sp0(&per_cpu(init_tss, cpu), &c_idle.idle->thread);
+-	initial_code = start_secondary;
+-	clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
+-
+-	printk(KERN_INFO "Booting processor %d/%d APIC 0x%x\n", cpu,
+-		cpus_weight(cpu_present_map),
+-		apicid);
+-
+-	/*
+-	 * This grunge runs the startup process for
+-	 * the targeted processor.
+-	 */
+-
+-	atomic_set(&init_deasserted, 0);
+-
+-	Dprintk("Setting warm reset code and vector.\n");
+-
+-	CMOS_WRITE(0xa, 0xf);
+-	local_flush_tlb();
+-	Dprintk("1.\n");
+-	*((volatile unsigned short *) phys_to_virt(0x469)) = start_rip >> 4;
+-	Dprintk("2.\n");
+-	*((volatile unsigned short *) phys_to_virt(0x467)) = start_rip & 0xf;
+-	Dprintk("3.\n");
+-
+-	/*
+-	 * Be paranoid about clearing APIC errors.
+-	 */
+-	apic_write(APIC_ESR, 0);
+-	apic_read(APIC_ESR);
+-
+-	/*
+-	 * Status is now clean
+-	 */
+-	boot_error = 0;
+-
+-	/*
+-	 * Starting actual IPI sequence...
+-	 */
+-	boot_error = wakeup_secondary_via_INIT(apicid, start_rip);
+-
+-	if (!boot_error) {
+-		/*
+-		 * allow APs to start initializing.
+-		 */
+-		Dprintk("Before Callout %d.\n", cpu);
+-		cpu_set(cpu, cpu_callout_map);
+-		Dprintk("After Callout %d.\n", cpu);
+-
+-		/*
+-		 * Wait 5s total for a response
+-		 */
+-		for (timeout = 0; timeout < 50000; timeout++) {
+-			if (cpu_isset(cpu, cpu_callin_map))
+-				break;	/* It has booted */
+-			udelay(100);
+-		}
+-
+-		if (cpu_isset(cpu, cpu_callin_map)) {
+-			/* number CPUs logically, starting from 1 (BSP is 0) */
+-			Dprintk("CPU has booted.\n");
+-		} else {
+-			boot_error = 1;
+-			if (*((volatile unsigned char *)phys_to_virt(SMP_TRAMPOLINE_BASE))
+-					== 0xA5)
+-				/* trampoline started but...? */
+-				printk("Stuck ??\n");
+-			else
+-				/* trampoline code not run */
+-				printk("Not responding.\n");
+-#ifdef APIC_DEBUG
+-			inquire_remote_apic(apicid);
+-#endif
+-		}
+-	}
+-	if (boot_error) {
+-		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
+-		clear_bit(cpu, (unsigned long *)&cpu_initialized); /* was set by cpu_init() */
+-		clear_node_cpumask(cpu); /* was set by numa_add_cpu */
+-		cpu_clear(cpu, cpu_present_map);
+-		cpu_clear(cpu, cpu_possible_map);
+-		per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
+-		return -EIO;
+-	}
+-
+-	return 0;
+-}
+-
+-cycles_t cacheflush_time;
+-unsigned long cache_decay_ticks;
+-
+-/*
+- * Cleanup possible dangling ends...
+- */
+-static __cpuinit void smp_cleanup_boot(void)
+-{
+-	/*
+-	 * Paranoid:  Set warm reset code and vector here back
+-	 * to default values.
+-	 */
+-	CMOS_WRITE(0, 0xf);
+-
+-	/*
+-	 * Reset trampoline flag
+-	 */
+-	*((volatile int *) phys_to_virt(0x467)) = 0;
+-}
+-
+-/*
+- * Fall back to non SMP mode after errors.
+- *
+- * RED-PEN audit/test this more. I bet there is more state messed up here.
+- */
+-static __init void disable_smp(void)
+-{
+-	cpu_present_map = cpumask_of_cpu(0);
+-	cpu_possible_map = cpumask_of_cpu(0);
+-	if (smp_found_config)
+-		phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
+-	else
+-		phys_cpu_present_map = physid_mask_of_physid(0);
+-	cpu_set(0, per_cpu(cpu_sibling_map, 0));
+-	cpu_set(0, per_cpu(cpu_core_map, 0));
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-
+-int additional_cpus __initdata = -1;
+-
+-/*
+- * cpu_possible_map should be static, it cannot change as cpu's
+- * are onlined, or offlined. The reason is per-cpu data-structures
+- * are allocated by some modules at init time, and dont expect to
+- * do this dynamically on cpu arrival/departure.
+- * cpu_present_map on the other hand can change dynamically.
+- * In case when cpu_hotplug is not compiled, then we resort to current
+- * behaviour, which is cpu_possible == cpu_present.
+- * - Ashok Raj
+- *
+- * Three ways to find out the number of additional hotplug CPUs:
+- * - If the BIOS specified disabled CPUs in ACPI/mptables use that.
+- * - The user can overwrite it with additional_cpus=NUM
+- * - Otherwise don't reserve additional CPUs.
+- * We do this because additional CPUs waste a lot of memory.
+- * -AK
+- */
+-__init void prefill_possible_map(void)
+-{
+-	int i;
+-	int possible;
+-
+- 	if (additional_cpus == -1) {
+- 		if (disabled_cpus > 0)
+- 			additional_cpus = disabled_cpus;
+- 		else
+-			additional_cpus = 0;
+- 	}
+-	possible = num_processors + additional_cpus;
+-	if (possible > NR_CPUS) 
+-		possible = NR_CPUS;
+-
+-	printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
+-		possible,
+-	        max_t(int, possible - num_processors, 0));
+-
+-	for (i = 0; i < possible; i++)
+-		cpu_set(i, cpu_possible_map);
+-}
+-#endif
+-
+-/*
+- * Various sanity checks.
+- */
+-static int __init smp_sanity_check(unsigned max_cpus)
+-{
+-	if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
+-		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
+-		       hard_smp_processor_id());
+-		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
+-	}
+-
+-	/*
+-	 * If we couldn't find an SMP configuration at boot time,
+-	 * get out of here now!
+-	 */
+-	if (!smp_found_config) {
+-		printk(KERN_NOTICE "SMP motherboard not detected.\n");
+-		disable_smp();
+-		if (APIC_init_uniprocessor())
+-			printk(KERN_NOTICE "Local APIC not detected."
+-					   " Using dummy APIC emulation.\n");
+-		return -1;
+-	}
+-
+-	/*
+-	 * Should not be necessary because the MP table should list the boot
+-	 * CPU too, but we do it for the sake of robustness anyway.
+-	 */
+-	if (!physid_isset(boot_cpu_id, phys_cpu_present_map)) {
+-		printk(KERN_NOTICE "weird, boot CPU (#%d) not listed by the BIOS.\n",
+-								 boot_cpu_id);
+-		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
+-	}
+-
+-	/*
+-	 * If we couldn't find a local APIC, then get out of here now!
+-	 */
+-	if (!cpu_has_apic) {
+-		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+-			boot_cpu_id);
+-		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
+-		nr_ioapics = 0;
+-		return -1;
+-	}
+-
+-	/*
+-	 * If SMP should be disabled, then really disable it!
+-	 */
+-	if (!max_cpus) {
+-		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
+-		nr_ioapics = 0;
+-		return -1;
+-	}
+-
+-	return 0;
+-}
+-
+-static void __init smp_cpu_index_default(void)
+-{
+-	int i;
+-	struct cpuinfo_x86 *c;
+-
+-	for_each_cpu_mask(i, cpu_possible_map) {
+-		c = &cpu_data(i);
+-		/* mark all to hotplug */
+-		c->cpu_index = NR_CPUS;
+-	}
+-}
+-
+-/*
+- * Prepare for SMP bootup.  The MP table or ACPI has been read
+- * earlier.  Just do some sanity checking here and enable APIC mode.
+- */
+-void __init smp_prepare_cpus(unsigned int max_cpus)
+-{
+-	nmi_watchdog_default();
+-	smp_cpu_index_default();
+-	current_cpu_data = boot_cpu_data;
+-	current_thread_info()->cpu = 0;  /* needed? */
+-	set_cpu_sibling_map(0);
+-
+-	if (smp_sanity_check(max_cpus) < 0) {
+-		printk(KERN_INFO "SMP disabled\n");
+-		disable_smp();
+-		return;
+-	}
+-
+-
+-	/*
+-	 * Switch from PIC to APIC mode.
+-	 */
+-	setup_local_APIC();
+-
+-	/*
+-	 * Enable IO APIC before setting up error vector
+-	 */
+-	if (!skip_ioapic_setup && nr_ioapics)
+-		enable_IO_APIC();
+-	end_local_APIC_setup();
+-
+-	if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id) {
+-		panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
+-		      GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
+-		/* Or can we switch back to PIC here? */
+-	}
+-
+-	/*
+-	 * Now start the IO-APICs
+-	 */
+-	if (!skip_ioapic_setup && nr_ioapics)
+-		setup_IO_APIC();
+-	else
+-		nr_ioapics = 0;
+-
+-	/*
+-	 * Set up local APIC timer on boot CPU.
+-	 */
+-
+-	setup_boot_clock();
+-}
+-
+-/*
+- * Early setup to make printk work.
+- */
+-void __init smp_prepare_boot_cpu(void)
+-{
+-	int me = smp_processor_id();
+-	/* already set me in cpu_online_map in boot_cpu_init() */
+-	cpu_set(me, cpu_callout_map);
+-	per_cpu(cpu_state, me) = CPU_ONLINE;
+-}
+-
+-/*
+- * Entry point to boot a CPU.
+- */
+-int __cpuinit __cpu_up(unsigned int cpu)
+-{
+-	int apicid = cpu_present_to_apicid(cpu);
+-	unsigned long flags;
+-	int err;
+-
+-	WARN_ON(irqs_disabled());
+-
+-	Dprintk("++++++++++++++++++++=_---CPU UP  %u\n", cpu);
+-
+-	if (apicid == BAD_APICID || apicid == boot_cpu_id ||
+-	    !physid_isset(apicid, phys_cpu_present_map)) {
+-		printk("__cpu_up: bad cpu %d\n", cpu);
+-		return -EINVAL;
+-	}
+-
+-	/*
+-	 * Already booted CPU?
+-	 */
+- 	if (cpu_isset(cpu, cpu_callin_map)) {
+-		Dprintk("do_boot_cpu %d Already started\n", cpu);
+- 		return -ENOSYS;
+-	}
+-
+-	/*
+-	 * Save current MTRR state in case it was changed since early boot
+-	 * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
+-	 */
+-	mtrr_save_state();
+-
+-	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+-	/* Boot it! */
+-	err = do_boot_cpu(cpu, apicid);
+-	if (err < 0) {
+-		Dprintk("do_boot_cpu failed %d\n", err);
+-		return err;
+-	}
+-
+-	/* Unleash the CPU! */
+-	Dprintk("waiting for cpu %d\n", cpu);
+-
+-	/*
+-  	 * Make sure and check TSC sync:
+- 	 */
+-	local_irq_save(flags);
+-	check_tsc_sync_source(cpu);
+-	local_irq_restore(flags);
+-
+-	while (!cpu_isset(cpu, cpu_online_map))
+-		cpu_relax();
+-	err = 0;
+-
+-	return err;
+-}
+-
+-/*
+- * Finish the SMP boot.
+- */
+-void __init smp_cpus_done(unsigned int max_cpus)
+-{
+-	smp_cleanup_boot();
+-	setup_ioapic_dest();
+-	check_nmi_watchdog();
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-
+-static void remove_siblinginfo(int cpu)
+-{
+-	int sibling;
+-	struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+-	for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
+-		cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
+-		/*
+-		 * last thread sibling in this cpu core going down
+-		 */
+-		if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
+-			cpu_data(sibling).booted_cores--;
+-	}
+-			
+-	for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
+-		cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
+-	cpus_clear(per_cpu(cpu_sibling_map, cpu));
+-	cpus_clear(per_cpu(cpu_core_map, cpu));
+-	c->phys_proc_id = 0;
+-	c->cpu_core_id = 0;
+-	cpu_clear(cpu, cpu_sibling_setup_map);
+-}
+-
+-static void __ref remove_cpu_from_maps(void)
+-{
+-	int cpu = smp_processor_id();
+-
+-	cpu_clear(cpu, cpu_callout_map);
+-	cpu_clear(cpu, cpu_callin_map);
+-	clear_bit(cpu, (unsigned long *)&cpu_initialized); /* was set by cpu_init() */
+-	clear_node_cpumask(cpu);
+-}
+-
+-int __cpu_disable(void)
+-{
+-	int cpu = smp_processor_id();
+-
+-	/*
+-	 * Perhaps use cpufreq to drop frequency, but that could go
+-	 * into generic code.
+- 	 *
+-	 * We won't take down the boot processor on i386 due to some
+-	 * interrupts only being able to be serviced by the BSP.
+-	 * Especially so if we're not using an IOAPIC	-zwane
+-	 */
+-	if (cpu == 0)
+-		return -EBUSY;
+-
+-	if (nmi_watchdog == NMI_LOCAL_APIC)
+-		stop_apic_nmi_watchdog(NULL);
+-	clear_local_APIC();
+-
+-	/*
+-	 * HACK:
+-	 * Allow any queued timer interrupts to get serviced
+-	 * This is only a temporary solution until we cleanup
+-	 * fixup_irqs as we do for IA64.
+-	 */
+-	local_irq_enable();
+-	mdelay(1);
+-
+-	local_irq_disable();
+-	remove_siblinginfo(cpu);
+-
+-	spin_lock(&vector_lock);
+-	/* It's now safe to remove this processor from the online map */
+-	cpu_clear(cpu, cpu_online_map);
+-	spin_unlock(&vector_lock);
+-	remove_cpu_from_maps();
+-	fixup_irqs(cpu_online_map);
+-	return 0;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+-	/* We don't do anything here: idle task is faking death itself. */
+-	unsigned int i;
+-
+-	for (i = 0; i < 10; i++) {
+-		/* They ack this in play_dead by setting CPU_DEAD */
+-		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+-			printk ("CPU %d is now offline\n", cpu);
+-			if (1 == num_online_cpus())
+-				alternatives_smp_switch(0);
+-			return;
+-		}
+-		msleep(100);
+-	}
+- 	printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+-}
+-
+-static __init int setup_additional_cpus(char *s)
+-{
+-	return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL;
+-}
+-early_param("additional_cpus", setup_additional_cpus);
+-
+-#else /* ... !CONFIG_HOTPLUG_CPU */
+-
+-int __cpu_disable(void)
+-{
+-	return -ENOSYS;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+-	/* We said "no" in __cpu_disable */
+-	BUG();
+-}
+-#endif /* CONFIG_HOTPLUG_CPU */
+diff --git a/arch/x86/kernel/smpcommon.c b/arch/x86/kernel/smpcommon.c
+new file mode 100644
+index 0000000..3449064
+--- /dev/null
++++ b/arch/x86/kernel/smpcommon.c
+@@ -0,0 +1,83 @@
++/*
++ * SMP stuff which is common to all sub-architectures.
++ */
++#include <linux/module.h>
++#include <asm/smp.h>
++
++#ifdef CONFIG_X86_32
++DEFINE_PER_CPU(unsigned long, this_cpu_off);
++EXPORT_PER_CPU_SYMBOL(this_cpu_off);
++
++/* Initialize the CPU's GDT.  This is either the boot CPU doing itself
++   (still using the master per-cpu area), or a CPU doing it for a
++   secondary which will soon come up. */
++__cpuinit void init_gdt(int cpu)
++{
++	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
++
++	pack_descriptor(&gdt[GDT_ENTRY_PERCPU],
++			__per_cpu_offset[cpu], 0xFFFFF,
++			0x2 | DESCTYPE_S, 0x8);
++
++	gdt[GDT_ENTRY_PERCPU].s = 1;
++
++	per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
++	per_cpu(cpu_number, cpu) = cpu;
++}
++#endif
++
++/**
++ * smp_call_function(): Run a function on all other CPUs.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: Unused.
++ * @wait: If true, wait (atomically) until function has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
++		      int wait)
++{
++	return smp_call_function_mask(cpu_online_map, func, info, wait);
++}
++EXPORT_SYMBOL(smp_call_function);
++
++/**
++ * smp_call_function_single - Run a function on a specific CPU
++ * @cpu: The target CPU.  Cannot be the calling CPU.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: Unused.
++ * @wait: If true, wait until function has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ */
++int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
++			     int nonatomic, int wait)
++{
++	/* prevent preemption and reschedule on another processor */
++	int ret;
++	int me = get_cpu();
++	if (cpu == me) {
++		local_irq_disable();
++		func(info);
++		local_irq_enable();
++		put_cpu();
++		return 0;
++	}
++
++	ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
++
++	put_cpu();
++	return ret;
++}
++EXPORT_SYMBOL(smp_call_function_single);
+diff --git a/arch/x86/kernel/smpcommon_32.c b/arch/x86/kernel/smpcommon_32.c
+index 8bc38af..8b13789 100644
+--- a/arch/x86/kernel/smpcommon_32.c
++++ b/arch/x86/kernel/smpcommon_32.c
+@@ -1,82 +1 @@
+-/*
+- * SMP stuff which is common to all sub-architectures.
+- */
+-#include <linux/module.h>
+-#include <asm/smp.h>
+ 
+-DEFINE_PER_CPU(unsigned long, this_cpu_off);
+-EXPORT_PER_CPU_SYMBOL(this_cpu_off);
+-
+-/* Initialize the CPU's GDT.  This is either the boot CPU doing itself
+-   (still using the master per-cpu area), or a CPU doing it for a
+-   secondary which will soon come up. */
+-__cpuinit void init_gdt(int cpu)
+-{
+-	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+-
+-	pack_descriptor(&gdt[GDT_ENTRY_PERCPU],
+-			__per_cpu_offset[cpu], 0xFFFFF,
+-			0x2 | DESCTYPE_S, 0x8);
+-
+-	gdt[GDT_ENTRY_PERCPU].s = 1;
+-
+-	per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
+-	per_cpu(cpu_number, cpu) = cpu;
+-}
+-
+-
+-/**
+- * smp_call_function(): Run a function on all other CPUs.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Unused.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+-		      int wait)
+-{
+-	return smp_call_function_mask(cpu_online_map, func, info, wait);
+-}
+-EXPORT_SYMBOL(smp_call_function);
+-
+-/**
+- * smp_call_function_single - Run a function on a specific CPU
+- * @cpu: The target CPU.  Cannot be the calling CPU.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Unused.
+- * @wait: If true, wait until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- */
+-int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+-			     int nonatomic, int wait)
+-{
+-	/* prevent preemption and reschedule on another processor */
+-	int ret;
+-	int me = get_cpu();
+-	if (cpu == me) {
+-		local_irq_disable();
+-		func(info);
+-		local_irq_enable();
+-		put_cpu();
+-		return 0;
+-	}
+-
+-	ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+-
+-	put_cpu();
+-	return ret;
+-}
+-EXPORT_SYMBOL(smp_call_function_single);
+diff --git a/arch/x86/kernel/srat_32.c b/arch/x86/kernel/srat_32.c
+index b72e613..70e4a37 100644
+--- a/arch/x86/kernel/srat_32.c
++++ b/arch/x86/kernel/srat_32.c
+@@ -277,14 +277,14 @@ int __init get_memcfg_from_srat(void)
+ 	rsdp_address = acpi_os_get_root_pointer();
+ 	if (!rsdp_address) {
+ 		printk("%s: System description tables not found\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		goto out_err;
+ 	}
+ 
+-	printk("%s: assigning address to rsdp\n", __FUNCTION__);
++	printk("%s: assigning address to rsdp\n", __func__);
+ 	rsdp = (struct acpi_table_rsdp *)(u32)rsdp_address;
+ 	if (!rsdp) {
+-		printk("%s: Didn't find ACPI root!\n", __FUNCTION__);
++		printk("%s: Didn't find ACPI root!\n", __func__);
+ 		goto out_err;
+ 	}
+ 
+@@ -292,7 +292,7 @@ int __init get_memcfg_from_srat(void)
+ 		rsdp->oem_id);
+ 
+ 	if (strncmp(rsdp->signature, ACPI_SIG_RSDP,strlen(ACPI_SIG_RSDP))) {
+-		printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __FUNCTION__);
++		printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __func__);
+ 		goto out_err;
+ 	}
+ 
+@@ -302,7 +302,7 @@ int __init get_memcfg_from_srat(void)
+ 	if (!rsdt) {
+ 		printk(KERN_WARNING
+ 		       "%s: ACPI: Invalid root system description tables (RSDT)\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		goto out_err;
+ 	}
+ 
+diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
+index 071ff47..92c20fe 100644
+--- a/arch/x86/kernel/step.c
++++ b/arch/x86/kernel/step.c
+@@ -148,7 +148,7 @@ static void write_debugctlmsr(struct task_struct *child, unsigned long val)
+ 	if (child != current)
+ 		return;
+ 
+-	wrmsrl(MSR_IA32_DEBUGCTLMSR, val);
++	update_debugctlmsr(val);
+ }
+ 
+ /*
+diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c
+index 72f4634..ae75109 100644
+--- a/arch/x86/kernel/summit_32.c
++++ b/arch/x86/kernel/summit_32.c
+@@ -29,49 +29,54 @@
+ #include <linux/mm.h>
+ #include <linux/init.h>
+ #include <asm/io.h>
++#include <asm/bios_ebda.h>
+ #include <asm/mach-summit/mach_mpparse.h>
+ 
+ static struct rio_table_hdr *rio_table_hdr __initdata;
+ static struct scal_detail   *scal_devs[MAX_NUMNODES] __initdata;
+ static struct rio_detail    *rio_devs[MAX_NUMNODES*4] __initdata;
+ 
++static int mp_bus_id_to_node[MAX_MP_BUSSES] __initdata;
++
+ static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
+ {
+ 	int twister = 0, node = 0;
+ 	int i, bus, num_buses;
+ 
+-	for(i = 0; i < rio_table_hdr->num_rio_dev; i++){
+-		if (rio_devs[i]->node_id == rio_devs[wpeg_num]->owner_id){
++	for (i = 0; i < rio_table_hdr->num_rio_dev; i++) {
++		if (rio_devs[i]->node_id == rio_devs[wpeg_num]->owner_id) {
+ 			twister = rio_devs[i]->owner_id;
+ 			break;
+ 		}
+ 	}
+-	if (i == rio_table_hdr->num_rio_dev){
+-		printk(KERN_ERR "%s: Couldn't find owner Cyclone for Winnipeg!\n", __FUNCTION__);
++	if (i == rio_table_hdr->num_rio_dev) {
++		printk(KERN_ERR "%s: Couldn't find owner Cyclone for Winnipeg!\n", __func__);
+ 		return last_bus;
+ 	}
+ 
+-	for(i = 0; i < rio_table_hdr->num_scal_dev; i++){
+-		if (scal_devs[i]->node_id == twister){
++	for (i = 0; i < rio_table_hdr->num_scal_dev; i++) {
++		if (scal_devs[i]->node_id == twister) {
+ 			node = scal_devs[i]->node_id;
+ 			break;
+ 		}
+ 	}
+-	if (i == rio_table_hdr->num_scal_dev){
+-		printk(KERN_ERR "%s: Couldn't find owner Twister for Cyclone!\n", __FUNCTION__);
++	if (i == rio_table_hdr->num_scal_dev) {
++		printk(KERN_ERR "%s: Couldn't find owner Twister for Cyclone!\n", __func__);
+ 		return last_bus;
+ 	}
+ 
+-	switch (rio_devs[wpeg_num]->type){
++	switch (rio_devs[wpeg_num]->type) {
+ 	case CompatWPEG:
+-		/* The Compatibility Winnipeg controls the 2 legacy buses,
++		/*
++		 * The Compatibility Winnipeg controls the 2 legacy buses,
+ 		 * the 66MHz PCI bus [2 slots] and the 2 "extra" buses in case
+ 		 * a PCI-PCI bridge card is used in either slot: total 5 buses.
+ 		 */
+ 		num_buses = 5;
+ 		break;
+ 	case AltWPEG:
+-		/* The Alternate Winnipeg controls the 2 133MHz buses [1 slot
++		/*
++		 * The Alternate Winnipeg controls the 2 133MHz buses [1 slot
+ 		 * each], their 2 "extra" buses, the 100MHz bus [2 slots] and
+ 		 * the "extra" buses for each of those slots: total 7 buses.
+ 		 */
+@@ -79,17 +84,18 @@ static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
+ 		break;
+ 	case LookOutAWPEG:
+ 	case LookOutBWPEG:
+-		/* A Lookout Winnipeg controls 3 100MHz buses [2 slots each]
++		/*
++		 * A Lookout Winnipeg controls 3 100MHz buses [2 slots each]
+ 		 * & the "extra" buses for each of those slots: total 9 buses.
+ 		 */
+ 		num_buses = 9;
+ 		break;
+ 	default:
+-		printk(KERN_INFO "%s: Unsupported Winnipeg type!\n", __FUNCTION__);
++		printk(KERN_INFO "%s: Unsupported Winnipeg type!\n", __func__);
+ 		return last_bus;
+ 	}
+ 
+-	for(bus = last_bus; bus < last_bus + num_buses; bus++)
++	for (bus = last_bus; bus < last_bus + num_buses; bus++)
+ 		mp_bus_id_to_node[bus] = node;
+ 	return bus;
+ }
+@@ -99,14 +105,14 @@ static int __init build_detail_arrays(void)
+ 	unsigned long ptr;
+ 	int i, scal_detail_size, rio_detail_size;
+ 
+-	if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){
+-		printk(KERN_WARNING "%s: MAX_NUMNODES too low!  Defined as %d, but system has %d nodes.\n", __FUNCTION__, MAX_NUMNODES, rio_table_hdr->num_scal_dev);
++	if (rio_table_hdr->num_scal_dev > MAX_NUMNODES) {
++		printk(KERN_WARNING "%s: MAX_NUMNODES too low!  Defined as %d, but system has %d nodes.\n", __func__, MAX_NUMNODES, rio_table_hdr->num_scal_dev);
+ 		return 0;
+ 	}
+ 
+-	switch (rio_table_hdr->version){
++	switch (rio_table_hdr->version) {
+ 	default:
+-		printk(KERN_WARNING "%s: Invalid Rio Grande Table Version: %d\n", __FUNCTION__, rio_table_hdr->version);
++		printk(KERN_WARNING "%s: Invalid Rio Grande Table Version: %d\n", __func__, rio_table_hdr->version);
+ 		return 0;
+ 	case 2:
+ 		scal_detail_size = 11;
+@@ -119,10 +125,10 @@ static int __init build_detail_arrays(void)
+ 	}
+ 
+ 	ptr = (unsigned long)rio_table_hdr + 3;
+-	for(i = 0; i < rio_table_hdr->num_scal_dev; i++, ptr += scal_detail_size)
++	for (i = 0; i < rio_table_hdr->num_scal_dev; i++, ptr += scal_detail_size)
+ 		scal_devs[i] = (struct scal_detail *)ptr;
+ 
+-	for(i = 0; i < rio_table_hdr->num_rio_dev; i++, ptr += rio_detail_size)
++	for (i = 0; i < rio_table_hdr->num_rio_dev; i++, ptr += rio_detail_size)
+ 		rio_devs[i] = (struct rio_detail *)ptr;
+ 
+ 	return 1;
+@@ -135,14 +141,14 @@ void __init setup_summit(void)
+ 	int			i, next_wpeg, next_bus = 0;
+ 
+ 	/* The pointer to the EBDA is stored in the word @ phys 0x40E(40:0E) */
+-	ptr = *(unsigned short *)phys_to_virt(0x40Eul);
+-	ptr = (unsigned long)phys_to_virt(ptr << 4);
++	ptr = get_bios_ebda();
++	ptr = (unsigned long)phys_to_virt(ptr);
+ 
+ 	rio_table_hdr = NULL;
+ 	offset = 0x180;
+-	while (offset){
++	while (offset) {
+ 		/* The block id is stored in the 2nd word */
+-		if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){
++		if (*((unsigned short *)(ptr + offset + 2)) == 0x4752) {
+ 			/* set the pointer past the offset & block id */
+ 			rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4);
+ 			break;
+@@ -150,8 +156,8 @@ void __init setup_summit(void)
+ 		/* The next offset is stored in the 1st word.  0 means no more */
+ 		offset = *((unsigned short *)(ptr + offset));
+ 	}
+-	if (!rio_table_hdr){
+-		printk(KERN_ERR "%s: Unable to locate Rio Grande Table in EBDA - bailing!\n", __FUNCTION__);
++	if (!rio_table_hdr) {
++		printk(KERN_ERR "%s: Unable to locate Rio Grande Table in EBDA - bailing!\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -161,8 +167,8 @@ void __init setup_summit(void)
+ 	/* The first Winnipeg we're looking for has an index of 0 */
+ 	next_wpeg = 0;
+ 	do {
+-		for(i = 0; i < rio_table_hdr->num_rio_dev; i++){
+-			if (is_WPEG(rio_devs[i]) && rio_devs[i]->WP_index == next_wpeg){
++		for (i = 0; i < rio_table_hdr->num_rio_dev; i++) {
++			if (is_WPEG(rio_devs[i]) && rio_devs[i]->WP_index == next_wpeg) {
+ 				/* It's the Winnipeg we're looking for! */
+ 				next_bus = setup_pci_node_map_for_wpeg(i, next_bus);
+ 				next_wpeg++;
+diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c
+index 9d498c2..170d43c 100644
+--- a/arch/x86/kernel/syscall_64.c
++++ b/arch/x86/kernel/syscall_64.c
+@@ -1,4 +1,4 @@
+-/* System call table for x86-64. */ 
++/* System call table for x86-64. */
+ 
+ #include <linux/linkage.h>
+ #include <linux/sys.h>
+@@ -7,20 +7,23 @@
+ 
+ #define __NO_STUBS
+ 
+-#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; 
++#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
+ #undef _ASM_X86_64_UNISTD_H_
+ #include <asm/unistd_64.h>
+ 
+ #undef __SYSCALL
+-#define __SYSCALL(nr, sym) [ nr ] = sym, 
++#define __SYSCALL(nr, sym) [nr] = sym,
+ #undef _ASM_X86_64_UNISTD_H_
+ 
+-typedef void (*sys_call_ptr_t)(void); 
++typedef void (*sys_call_ptr_t)(void);
+ 
+ extern void sys_ni_syscall(void);
+ 
+ const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
+-	/* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */ 
++	/*
++	*Smells like a like a compiler bug -- it doesn't work
++	*when the & below is removed.
++	*/
+ 	[0 ... __NR_syscall_max] = &sys_ni_syscall,
+ #include <asm/unistd_64.h>
+ };
+diff --git a/arch/x86/kernel/test_nx.c b/arch/x86/kernel/test_nx.c
+index 10b8a6f..787a5e4 100644
+--- a/arch/x86/kernel/test_nx.c
++++ b/arch/x86/kernel/test_nx.c
+@@ -11,6 +11,8 @@
+  */
+ #include <linux/module.h>
+ #include <linux/sort.h>
++#include <linux/slab.h>
++
+ #include <asm/uaccess.h>
+ #include <asm/asm.h>
+ 
+diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c
+new file mode 100644
+index 0000000..9bb2363
+--- /dev/null
++++ b/arch/x86/kernel/tlb_32.c
+@@ -0,0 +1,243 @@
++#include <linux/spinlock.h>
++#include <linux/cpu.h>
++#include <linux/interrupt.h>
++
++#include <asm/tlbflush.h>
++
++DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate)
++			____cacheline_aligned = { &init_mm, 0, };
++
++/* must come after the send_IPI functions above for inlining */
++#include <mach_ipi.h>
++
++/*
++ *	Smarter SMP flushing macros.
++ *		c/o Linus Torvalds.
++ *
++ *	These mean you can really definitely utterly forget about
++ *	writing to user space from interrupts. (Its not allowed anyway).
++ *
++ *	Optimizations Manfred Spraul <manfred at colorfullife.com>
++ */
++
++static cpumask_t flush_cpumask;
++static struct mm_struct *flush_mm;
++static unsigned long flush_va;
++static DEFINE_SPINLOCK(tlbstate_lock);
++
++/*
++ * We cannot call mmdrop() because we are in interrupt context,
++ * instead update mm->cpu_vm_mask.
++ *
++ * We need to reload %cr3 since the page tables may be going
++ * away from under us..
++ */
++void leave_mm(int cpu)
++{
++	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
++		BUG();
++	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
++	load_cr3(swapper_pg_dir);
++}
++EXPORT_SYMBOL_GPL(leave_mm);
++
++/*
++ *
++ * The flush IPI assumes that a thread switch happens in this order:
++ * [cpu0: the cpu that switches]
++ * 1) switch_mm() either 1a) or 1b)
++ * 1a) thread switch to a different mm
++ * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
++ * 	Stop ipi delivery for the old mm. This is not synchronized with
++ * 	the other cpus, but smp_invalidate_interrupt ignore flush ipis
++ * 	for the wrong mm, and in the worst case we perform a superfluous
++ * 	tlb flush.
++ * 1a2) set cpu_tlbstate to TLBSTATE_OK
++ * 	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
++ *	was in lazy tlb mode.
++ * 1a3) update cpu_tlbstate[].active_mm
++ * 	Now cpu0 accepts tlb flushes for the new mm.
++ * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
++ * 	Now the other cpus will send tlb flush ipis.
++ * 1a4) change cr3.
++ * 1b) thread switch without mm change
++ *	cpu_tlbstate[].active_mm is correct, cpu0 already handles
++ *	flush ipis.
++ * 1b1) set cpu_tlbstate to TLBSTATE_OK
++ * 1b2) test_and_set the cpu bit in cpu_vm_mask.
++ * 	Atomically set the bit [other cpus will start sending flush ipis],
++ * 	and test the bit.
++ * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
++ * 2) switch %%esp, ie current
++ *
++ * The interrupt must handle 2 special cases:
++ * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
++ * - the cpu performs speculative tlb reads, i.e. even if the cpu only
++ *   runs in kernel space, the cpu could load tlb entries for user space
++ *   pages.
++ *
++ * The good news is that cpu_tlbstate is local to each cpu, no
++ * write/read ordering problems.
++ */
++
++/*
++ * TLB flush IPI:
++ *
++ * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
++ * 2) Leave the mm if we are in the lazy tlb mode.
++ */
++
++void smp_invalidate_interrupt(struct pt_regs *regs)
++{
++	unsigned long cpu;
++
++	cpu = get_cpu();
++
++	if (!cpu_isset(cpu, flush_cpumask))
++		goto out;
++		/*
++		 * This was a BUG() but until someone can quote me the
++		 * line from the intel manual that guarantees an IPI to
++		 * multiple CPUs is retried _only_ on the erroring CPUs
++		 * its staying as a return
++		 *
++		 * BUG();
++		 */
++
++	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
++		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
++			if (flush_va == TLB_FLUSH_ALL)
++				local_flush_tlb();
++			else
++				__flush_tlb_one(flush_va);
++		} else
++			leave_mm(cpu);
++	}
++	ack_APIC_irq();
++	smp_mb__before_clear_bit();
++	cpu_clear(cpu, flush_cpumask);
++	smp_mb__after_clear_bit();
++out:
++	put_cpu_no_resched();
++	__get_cpu_var(irq_stat).irq_tlb_count++;
++}
++
++void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
++			     unsigned long va)
++{
++	cpumask_t cpumask = *cpumaskp;
++
++	/*
++	 * A couple of (to be removed) sanity checks:
++	 *
++	 * - current CPU must not be in mask
++	 * - mask must exist :)
++	 */
++	BUG_ON(cpus_empty(cpumask));
++	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
++	BUG_ON(!mm);
++
++#ifdef CONFIG_HOTPLUG_CPU
++	/* If a CPU which we ran on has gone down, OK. */
++	cpus_and(cpumask, cpumask, cpu_online_map);
++	if (unlikely(cpus_empty(cpumask)))
++		return;
++#endif
++
++	/*
++	 * i'm not happy about this global shared spinlock in the
++	 * MM hot path, but we'll see how contended it is.
++	 * AK: x86-64 has a faster method that could be ported.
++	 */
++	spin_lock(&tlbstate_lock);
++
++	flush_mm = mm;
++	flush_va = va;
++	cpus_or(flush_cpumask, cpumask, flush_cpumask);
++	/*
++	 * We have to send the IPI only to
++	 * CPUs affected.
++	 */
++	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
++
++	while (!cpus_empty(flush_cpumask))
++		/* nothing. lockup detection does not belong here */
++		cpu_relax();
++
++	flush_mm = NULL;
++	flush_va = 0;
++	spin_unlock(&tlbstate_lock);
++}
++
++void flush_tlb_current_task(void)
++{
++	struct mm_struct *mm = current->mm;
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	local_flush_tlb();
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++	preempt_enable();
++}
++
++void flush_tlb_mm(struct mm_struct *mm)
++{
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	if (current->active_mm == mm) {
++		if (current->mm)
++			local_flush_tlb();
++		else
++			leave_mm(smp_processor_id());
++	}
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++
++	preempt_enable();
++}
++
++void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
++{
++	struct mm_struct *mm = vma->vm_mm;
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	if (current->active_mm == mm) {
++		if (current->mm)
++			__flush_tlb_one(va);
++		 else
++			leave_mm(smp_processor_id());
++	}
++
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, va);
++
++	preempt_enable();
++}
++EXPORT_SYMBOL(flush_tlb_page);
++
++static void do_flush_tlb_all(void *info)
++{
++	unsigned long cpu = smp_processor_id();
++
++	__flush_tlb_all();
++	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
++		leave_mm(cpu);
++}
++
++void flush_tlb_all(void)
++{
++	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
++}
++
+diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c
+new file mode 100644
+index 0000000..a1f07d7
+--- /dev/null
++++ b/arch/x86/kernel/tlb_64.c
+@@ -0,0 +1,274 @@
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/smp.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/interrupt.h>
++
++#include <asm/mtrr.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/proto.h>
++#include <asm/apicdef.h>
++#include <asm/idle.h>
++
++#include <mach_ipi.h>
++/*
++ *	Smarter SMP flushing macros.
++ *		c/o Linus Torvalds.
++ *
++ *	These mean you can really definitely utterly forget about
++ *	writing to user space from interrupts. (Its not allowed anyway).
++ *
++ *	Optimizations Manfred Spraul <manfred at colorfullife.com>
++ *
++ *	More scalable flush, from Andi Kleen
++ *
++ *	To avoid global state use 8 different call vectors.
++ *	Each CPU uses a specific vector to trigger flushes on other
++ *	CPUs. Depending on the received vector the target CPUs look into
++ *	the right per cpu variable for the flush data.
++ *
++ *	With more than 8 CPUs they are hashed to the 8 available
++ *	vectors. The limited global vector space forces us to this right now.
++ *	In future when interrupts are split into per CPU domains this could be
++ *	fixed, at the cost of triggering multiple IPIs in some cases.
++ */
++
++union smp_flush_state {
++	struct {
++		cpumask_t flush_cpumask;
++		struct mm_struct *flush_mm;
++		unsigned long flush_va;
++		spinlock_t tlbstate_lock;
++	};
++	char pad[SMP_CACHE_BYTES];
++} ____cacheline_aligned;
++
++/* State is put into the per CPU data section, but padded
++   to a full cache line because other CPUs can access it and we don't
++   want false sharing in the per cpu data segment. */
++static DEFINE_PER_CPU(union smp_flush_state, flush_state);
++
++/*
++ * We cannot call mmdrop() because we are in interrupt context,
++ * instead update mm->cpu_vm_mask.
++ */
++void leave_mm(int cpu)
++{
++	if (read_pda(mmu_state) == TLBSTATE_OK)
++		BUG();
++	cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
++	load_cr3(swapper_pg_dir);
++}
++EXPORT_SYMBOL_GPL(leave_mm);
++
++/*
++ *
++ * The flush IPI assumes that a thread switch happens in this order:
++ * [cpu0: the cpu that switches]
++ * 1) switch_mm() either 1a) or 1b)
++ * 1a) thread switch to a different mm
++ * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
++ *	Stop ipi delivery for the old mm. This is not synchronized with
++ *	the other cpus, but smp_invalidate_interrupt ignore flush ipis
++ *	for the wrong mm, and in the worst case we perform a superfluous
++ *	tlb flush.
++ * 1a2) set cpu mmu_state to TLBSTATE_OK
++ *	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
++ *	was in lazy tlb mode.
++ * 1a3) update cpu active_mm
++ *	Now cpu0 accepts tlb flushes for the new mm.
++ * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
++ *	Now the other cpus will send tlb flush ipis.
++ * 1a4) change cr3.
++ * 1b) thread switch without mm change
++ *	cpu active_mm is correct, cpu0 already handles
++ *	flush ipis.
++ * 1b1) set cpu mmu_state to TLBSTATE_OK
++ * 1b2) test_and_set the cpu bit in cpu_vm_mask.
++ *	Atomically set the bit [other cpus will start sending flush ipis],
++ *	and test the bit.
++ * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
++ * 2) switch %%esp, ie current
++ *
++ * The interrupt must handle 2 special cases:
++ * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
++ * - the cpu performs speculative tlb reads, i.e. even if the cpu only
++ *   runs in kernel space, the cpu could load tlb entries for user space
++ *   pages.
++ *
++ * The good news is that cpu mmu_state is local to each cpu, no
++ * write/read ordering problems.
++ */
++
++/*
++ * TLB flush IPI:
++ *
++ * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
++ * 2) Leave the mm if we are in the lazy tlb mode.
++ *
++ * Interrupts are disabled.
++ */
++
++asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
++{
++	int cpu;
++	int sender;
++	union smp_flush_state *f;
++
++	cpu = smp_processor_id();
++	/*
++	 * orig_rax contains the negated interrupt vector.
++	 * Use that to determine where the sender put the data.
++	 */
++	sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
++	f = &per_cpu(flush_state, sender);
++
++	if (!cpu_isset(cpu, f->flush_cpumask))
++		goto out;
++		/*
++		 * This was a BUG() but until someone can quote me the
++		 * line from the intel manual that guarantees an IPI to
++		 * multiple CPUs is retried _only_ on the erroring CPUs
++		 * its staying as a return
++		 *
++		 * BUG();
++		 */
++
++	if (f->flush_mm == read_pda(active_mm)) {
++		if (read_pda(mmu_state) == TLBSTATE_OK) {
++			if (f->flush_va == TLB_FLUSH_ALL)
++				local_flush_tlb();
++			else
++				__flush_tlb_one(f->flush_va);
++		} else
++			leave_mm(cpu);
++	}
++out:
++	ack_APIC_irq();
++	cpu_clear(cpu, f->flush_cpumask);
++	add_pda(irq_tlb_count, 1);
++}
++
++void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
++			     unsigned long va)
++{
++	int sender;
++	union smp_flush_state *f;
++	cpumask_t cpumask = *cpumaskp;
++
++	/* Caller has disabled preemption */
++	sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
++	f = &per_cpu(flush_state, sender);
++
++	/*
++	 * Could avoid this lock when
++	 * num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
++	 * probably not worth checking this for a cache-hot lock.
++	 */
++	spin_lock(&f->tlbstate_lock);
++
++	f->flush_mm = mm;
++	f->flush_va = va;
++	cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
++
++	/*
++	 * We have to send the IPI only to
++	 * CPUs affected.
++	 */
++	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
++
++	while (!cpus_empty(f->flush_cpumask))
++		cpu_relax();
++
++	f->flush_mm = NULL;
++	f->flush_va = 0;
++	spin_unlock(&f->tlbstate_lock);
++}
++
++static int __cpuinit init_smp_flush(void)
++{
++	int i;
++
++	for_each_possible_cpu(i)
++		spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
++
++	return 0;
++}
++core_initcall(init_smp_flush);
++
++void flush_tlb_current_task(void)
++{
++	struct mm_struct *mm = current->mm;
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	local_flush_tlb();
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++	preempt_enable();
++}
++
++void flush_tlb_mm(struct mm_struct *mm)
++{
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	if (current->active_mm == mm) {
++		if (current->mm)
++			local_flush_tlb();
++		else
++			leave_mm(smp_processor_id());
++	}
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++
++	preempt_enable();
++}
++
++void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
++{
++	struct mm_struct *mm = vma->vm_mm;
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	if (current->active_mm == mm) {
++		if (current->mm)
++			__flush_tlb_one(va);
++		else
++			leave_mm(smp_processor_id());
++	}
++
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, va);
++
++	preempt_enable();
++}
++
++static void do_flush_tlb_all(void *info)
++{
++	unsigned long cpu = smp_processor_id();
++
++	__flush_tlb_all();
++	if (read_pda(mmu_state) == TLBSTATE_LAZY)
++		leave_mm(cpu);
++}
++
++void flush_tlb_all(void)
++{
++	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
++}
+diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
+new file mode 100644
+index 0000000..abbf199
+--- /dev/null
++++ b/arch/x86/kernel/trampoline.c
+@@ -0,0 +1,18 @@
++#include <linux/io.h>
++
++#include <asm/trampoline.h>
++
++/* ready for x86_64, no harm for x86, since it will overwrite after alloc */
++unsigned char *trampoline_base = __va(TRAMPOLINE_BASE);
++
++/*
++ * Currently trivial. Write the real->protected mode
++ * bootstrap into the page concerned. The caller
++ * has made sure it's suitably aligned.
++ */
++unsigned long setup_trampoline(void)
++{
++	memcpy(trampoline_base, trampoline_data,
++	       trampoline_end - trampoline_data);
++	return virt_to_phys(trampoline_base);
++}
+diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S
+index 6458067..d8ccc3c 100644
+--- a/arch/x86/kernel/trampoline_32.S
++++ b/arch/x86/kernel/trampoline_32.S
+@@ -33,7 +33,7 @@
+ 
+ /* We can free up trampoline after bootup if cpu hotplug is not supported. */
+ #ifndef CONFIG_HOTPLUG_CPU
+-.section ".init.data","aw", at progbits
++.section ".cpuinit.data","aw", at progbits
+ #else
+ .section .rodata,"a", at progbits
+ #endif
+diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
+index 4aedd0b..894293c 100644
+--- a/arch/x86/kernel/trampoline_64.S
++++ b/arch/x86/kernel/trampoline_64.S
+@@ -30,12 +30,7 @@
+ #include <asm/msr.h>
+ #include <asm/segment.h>
+ 
+-/* We can free up trampoline after bootup if cpu hotplug is not supported. */
+-#ifndef CONFIG_HOTPLUG_CPU
+-.section .init.data, "aw", @progbits
+-#else
+ .section .rodata, "a", @progbits
+-#endif
+ 
+ .code16
+ 
+diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
+index b22c01e..bde6f63 100644
+--- a/arch/x86/kernel/traps_32.c
++++ b/arch/x86/kernel/traps_32.c
+@@ -9,26 +9,28 @@
+  * 'Traps.c' handles hardware traps and faults after we have saved some
+  * state in 'asm.s'.
+  */
+-#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/kallsyms.h>
++#include <linux/spinlock.h>
++#include <linux/highmem.h>
++#include <linux/kprobes.h>
++#include <linux/uaccess.h>
++#include <linux/utsname.h>
++#include <linux/kdebug.h>
+ #include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ptrace.h>
+ #include <linux/string.h>
++#include <linux/unwind.h>
++#include <linux/delay.h>
+ #include <linux/errno.h>
++#include <linux/kexec.h>
++#include <linux/sched.h>
+ #include <linux/timer.h>
+-#include <linux/mm.h>
+ #include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-#include <linux/highmem.h>
+-#include <linux/kallsyms.h>
+-#include <linux/ptrace.h>
+-#include <linux/utsname.h>
+-#include <linux/kprobes.h>
+-#include <linux/kexec.h>
+-#include <linux/unwind.h>
+-#include <linux/uaccess.h>
+-#include <linux/nmi.h>
+ #include <linux/bug.h>
++#include <linux/nmi.h>
++#include <linux/mm.h>
+ 
+ #ifdef CONFIG_EISA
+ #include <linux/ioport.h>
+@@ -43,21 +45,18 @@
+ #include <linux/edac.h>
+ #endif
+ 
++#include <asm/arch_hooks.h>
++#include <asm/stacktrace.h>
+ #include <asm/processor.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/atomic.h>
+ #include <asm/debugreg.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++#include <asm/unwind.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+ #include <asm/nmi.h>
+-#include <asm/unwind.h>
+ #include <asm/smp.h>
+-#include <asm/arch_hooks.h>
+-#include <linux/kdebug.h>
+-#include <asm/stacktrace.h>
+-
+-#include <linux/module.h>
++#include <asm/io.h>
+ 
+ #include "mach_traps.h"
+ 
+@@ -69,7 +68,7 @@ EXPORT_SYMBOL_GPL(used_vectors);
+ asmlinkage int system_call(void);
+ 
+ /* Do we ignore FPU interrupts ? */
+-char ignore_fpu_irq = 0;
++char ignore_fpu_irq;
+ 
+ /*
+  * The IDT has to be page-aligned to simplify the Pentium
+@@ -105,12 +104,13 @@ static unsigned int code_bytes = 64;
+ void printk_address(unsigned long address, int reliable)
+ {
+ #ifdef CONFIG_KALLSYMS
+-	unsigned long offset = 0, symsize;
++	char namebuf[KSYM_NAME_LEN];
++	unsigned long offset = 0;
++	unsigned long symsize;
+ 	const char *symname;
+-	char *modname;
+-	char *delim = ":";
+-	char namebuf[128];
+ 	char reliab[4] = "";
++	char *delim = ":";
++	char *modname;
+ 
+ 	symname = kallsyms_lookup(address, &symsize, &offset,
+ 					&modname, namebuf);
+@@ -138,13 +138,14 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned s
+ 
+ /* The form of the top of the frame on the stack */
+ struct stack_frame {
+-	struct stack_frame *next_frame;
+-	unsigned long return_address;
++	struct stack_frame	*next_frame;
++	unsigned long		return_address;
+ };
+ 
+-static inline unsigned long print_context_stack(struct thread_info *tinfo,
+-				unsigned long *stack, unsigned long bp,
+-				const struct stacktrace_ops *ops, void *data)
++static inline unsigned long
++print_context_stack(struct thread_info *tinfo,
++		    unsigned long *stack, unsigned long bp,
++		    const struct stacktrace_ops *ops, void *data)
+ {
+ 	struct stack_frame *frame = (struct stack_frame *)bp;
+ 
+@@ -166,7 +167,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
+ 	return bp;
+ }
+ 
+-#define MSG(msg) ops->warning(data, msg)
++#define MSG(msg)		ops->warning(data, msg)
+ 
+ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ 		unsigned long *stack, unsigned long bp,
+@@ -177,6 +178,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ 
+ 	if (!stack) {
+ 		unsigned long dummy;
++
+ 		stack = &dummy;
+ 		if (task != current)
+ 			stack = (unsigned long *)task->thread.sp;
+@@ -186,7 +188,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ 	if (!bp) {
+ 		if (task == current) {
+ 			/* Grab bp right from our regs */
+-			asm ("movl %%ebp, %0" : "=r" (bp) : );
++			asm("movl %%ebp, %0" : "=r" (bp) :);
+ 		} else {
+ 			/* bp is the last reg pushed by switch_to */
+ 			bp = *(unsigned long *) task->thread.sp;
+@@ -196,15 +198,18 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ 
+ 	while (1) {
+ 		struct thread_info *context;
++
+ 		context = (struct thread_info *)
+ 			((unsigned long)stack & (~(THREAD_SIZE - 1)));
+ 		bp = print_context_stack(context, stack, bp, ops, data);
+-		/* Should be after the line below, but somewhere
+-		   in early boot context comes out corrupted and we
+-		   can't reference it -AK */
++		/*
++		 * Should be after the line below, but somewhere
++		 * in early boot context comes out corrupted and we
++		 * can't reference it:
++		 */
+ 		if (ops->stack(data, "IRQ") < 0)
+ 			break;
+-		stack = (unsigned long*)context->previous_esp;
++		stack = (unsigned long *)context->previous_esp;
+ 		if (!stack)
+ 			break;
+ 		touch_nmi_watchdog();
+@@ -243,15 +248,15 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
+ }
+ 
+ static const struct stacktrace_ops print_trace_ops = {
+-	.warning = print_trace_warning,
+-	.warning_symbol = print_trace_warning_symbol,
+-	.stack = print_trace_stack,
+-	.address = print_trace_address,
++	.warning		= print_trace_warning,
++	.warning_symbol		= print_trace_warning_symbol,
++	.stack			= print_trace_stack,
++	.address		= print_trace_address,
+ };
+ 
+ static void
+ show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long *stack, unsigned long bp, char *log_lvl)
++		   unsigned long *stack, unsigned long bp, char *log_lvl)
+ {
+ 	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+ 	printk("%s =======================\n", log_lvl);
+@@ -263,21 +268,22 @@ void show_trace(struct task_struct *task, struct pt_regs *regs,
+ 	show_trace_log_lvl(task, regs, stack, bp, "");
+ }
+ 
+-static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		       unsigned long *sp, unsigned long bp, char *log_lvl)
++static void
++show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
++		   unsigned long *sp, unsigned long bp, char *log_lvl)
+ {
+ 	unsigned long *stack;
+ 	int i;
+ 
+ 	if (sp == NULL) {
+ 		if (task)
+-			sp = (unsigned long*)task->thread.sp;
++			sp = (unsigned long *)task->thread.sp;
+ 		else
+ 			sp = (unsigned long *)&sp;
+ 	}
+ 
+ 	stack = sp;
+-	for(i = 0; i < kstack_depth_to_print; i++) {
++	for (i = 0; i < kstack_depth_to_print; i++) {
+ 		if (kstack_end(stack))
+ 			break;
+ 		if (i && ((i % 8) == 0))
+@@ -285,6 +291,7 @@ static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+ 		printk("%08lx ", *stack++);
+ 	}
+ 	printk("\n%sCall Trace:\n", log_lvl);
++
+ 	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+ }
+ 
+@@ -299,8 +306,8 @@ void show_stack(struct task_struct *task, unsigned long *sp)
+  */
+ void dump_stack(void)
+ {
+-	unsigned long stack;
+ 	unsigned long bp = 0;
++	unsigned long stack;
+ 
+ #ifdef CONFIG_FRAME_POINTER
+ 	if (!bp)
+@@ -312,6 +319,7 @@ void dump_stack(void)
+ 		init_utsname()->release,
+ 		(int)strcspn(init_utsname()->version, " "),
+ 		init_utsname()->version);
++
+ 	show_trace(current, NULL, &stack, bp);
+ }
+ 
+@@ -323,6 +331,7 @@ void show_registers(struct pt_regs *regs)
+ 
+ 	print_modules();
+ 	__show_registers(regs, 0);
++
+ 	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+ 		TASK_COMM_LEN, current->comm, task_pid_nr(current),
+ 		current_thread_info(), current, task_thread_info(current));
+@@ -331,10 +340,10 @@ void show_registers(struct pt_regs *regs)
+ 	 * time of the fault..
+ 	 */
+ 	if (!user_mode_vm(regs)) {
+-		u8 *ip;
+ 		unsigned int code_prologue = code_bytes * 43 / 64;
+ 		unsigned int code_len = code_bytes;
+ 		unsigned char c;
++		u8 *ip;
+ 
+ 		printk("\n" KERN_EMERG "Stack: ");
+ 		show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
+@@ -361,7 +370,7 @@ void show_registers(struct pt_regs *regs)
+ 		}
+ 	}
+ 	printk("\n");
+-}	
++}
+ 
+ int is_valid_bugaddr(unsigned long ip)
+ {
+@@ -377,10 +386,10 @@ int is_valid_bugaddr(unsigned long ip)
+ 
+ static int die_counter;
+ 
+-int __kprobes __die(const char * str, struct pt_regs * regs, long err)
++int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+ {
+-	unsigned long sp;
+ 	unsigned short ss;
++	unsigned long sp;
+ 
+ 	printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+ #ifdef CONFIG_PREEMPT
+@@ -395,8 +404,8 @@ int __kprobes __die(const char * str, struct pt_regs * regs, long err)
+ 	printk("\n");
+ 
+ 	if (notify_die(DIE_OOPS, str, regs, err,
+-				current->thread.trap_no, SIGSEGV) !=
+-			NOTIFY_STOP) {
++			current->thread.trap_no, SIGSEGV) != NOTIFY_STOP) {
++
+ 		show_registers(regs);
+ 		/* Executive summary in case the oops scrolled away */
+ 		sp = (unsigned long) (&regs->sp);
+@@ -408,17 +417,18 @@ int __kprobes __die(const char * str, struct pt_regs * regs, long err)
+ 		printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
+ 		print_symbol("%s", regs->ip);
+ 		printk(" SS:ESP %04x:%08lx\n", ss, sp);
++
+ 		return 0;
+-	} else {
+-		return 1;
+ 	}
++
++	return 1;
+ }
+ 
+ /*
+- * This is gone through when something in the kernel has done something bad and
+- * is about to be terminated.
++ * This is gone through when something in the kernel has done something bad
++ * and is about to be terminated:
+  */
+-void die(const char * str, struct pt_regs * regs, long err)
++void die(const char *str, struct pt_regs *regs, long err)
+ {
+ 	static struct {
+ 		raw_spinlock_t lock;
+@@ -440,8 +450,9 @@ void die(const char * str, struct pt_regs * regs, long err)
+ 		die.lock_owner = smp_processor_id();
+ 		die.lock_owner_depth = 0;
+ 		bust_spinlocks(1);
+-	} else
++	} else {
+ 		raw_local_irq_save(flags);
++	}
+ 
+ 	if (++die.lock_owner_depth < 3) {
+ 		report_bug(regs->ip, regs);
+@@ -474,19 +485,20 @@ void die(const char * str, struct pt_regs * regs, long err)
+ 	do_exit(SIGSEGV);
+ }
+ 
+-static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
++static inline void
++die_if_kernel(const char *str, struct pt_regs *regs, long err)
+ {
+ 	if (!user_mode_vm(regs))
+ 		die(str, regs, err);
+ }
+ 
+-static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
+-			      struct pt_regs * regs, long error_code,
+-			      siginfo_t *info)
++static void __kprobes
++do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs *regs,
++	long error_code, siginfo_t *info)
+ {
+ 	struct task_struct *tsk = current;
+ 
+-	if (regs->flags & VM_MASK) {
++	if (regs->flags & X86_VM_MASK) {
+ 		if (vm86)
+ 			goto vm86_trap;
+ 		goto trap_signal;
+@@ -495,111 +507,112 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
+ 	if (!user_mode(regs))
+ 		goto kernel_trap;
+ 
+-	trap_signal: {
+-		/*
+-		 * We want error_code and trap_no set for userspace faults and
+-		 * kernelspace faults which result in die(), but not
+-		 * kernelspace faults which are fixed up.  die() gives the
+-		 * process no chance to handle the signal and notice the
+-		 * kernel fault information, so that won't result in polluting
+-		 * the information about previously queued, but not yet
+-		 * delivered, faults.  See also do_general_protection below.
+-		 */
+-		tsk->thread.error_code = error_code;
+-		tsk->thread.trap_no = trapnr;
++trap_signal:
++	/*
++	 * We want error_code and trap_no set for userspace faults and
++	 * kernelspace faults which result in die(), but not
++	 * kernelspace faults which are fixed up.  die() gives the
++	 * process no chance to handle the signal and notice the
++	 * kernel fault information, so that won't result in polluting
++	 * the information about previously queued, but not yet
++	 * delivered, faults.  See also do_general_protection below.
++	 */
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = trapnr;
+ 
+-		if (info)
+-			force_sig_info(signr, info, tsk);
+-		else
+-			force_sig(signr, tsk);
+-		return;
+-	}
++	if (info)
++		force_sig_info(signr, info, tsk);
++	else
++		force_sig(signr, tsk);
++	return;
+ 
+-	kernel_trap: {
+-		if (!fixup_exception(regs)) {
+-			tsk->thread.error_code = error_code;
+-			tsk->thread.trap_no = trapnr;
+-			die(str, regs, error_code);
+-		}
+-		return;
++kernel_trap:
++	if (!fixup_exception(regs)) {
++		tsk->thread.error_code = error_code;
++		tsk->thread.trap_no = trapnr;
++		die(str, regs, error_code);
+ 	}
++	return;
+ 
+-	vm86_trap: {
+-		int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
+-		if (ret) goto trap_signal;
+-		return;
+-	}
++vm86_trap:
++	if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
++						error_code, trapnr))
++		goto trap_signal;
++	return;
+ }
+ 
+-#define DO_ERROR(trapnr, signr, str, name) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-						== NOTIFY_STOP) \
+-		return; \
+-	do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
++#define DO_ERROR(trapnr, signr, str, name)				\
++void do_##name(struct pt_regs *regs, long error_code)			\
++{									\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++						== NOTIFY_STOP)		\
++		return;							\
++	do_trap(trapnr, signr, str, 0, regs, error_code, NULL);		\
+ }
+ 
+-#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	siginfo_t info; \
+-	if (irq) \
+-		local_irq_enable(); \
+-	info.si_signo = signr; \
+-	info.si_errno = 0; \
+-	info.si_code = sicode; \
+-	info.si_addr = (void __user *)siaddr; \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-						== NOTIFY_STOP) \
+-		return; \
+-	do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
++#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq)	\
++void do_##name(struct pt_regs *regs, long error_code)			\
++{									\
++	siginfo_t info;							\
++	if (irq)							\
++		local_irq_enable();					\
++	info.si_signo = signr;						\
++	info.si_errno = 0;						\
++	info.si_code = sicode;						\
++	info.si_addr = (void __user *)siaddr;				\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++						== NOTIFY_STOP)		\
++		return;							\
++	do_trap(trapnr, signr, str, 0, regs, error_code, &info);	\
+ }
+ 
+-#define DO_VM86_ERROR(trapnr, signr, str, name) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-						== NOTIFY_STOP) \
+-		return; \
+-	do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
++#define DO_VM86_ERROR(trapnr, signr, str, name)				\
++void do_##name(struct pt_regs *regs, long error_code)			\
++{									\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++						== NOTIFY_STOP)		\
++		return;							\
++	do_trap(trapnr, signr, str, 1, regs, error_code, NULL);		\
+ }
+ 
+-#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	siginfo_t info; \
+-	info.si_signo = signr; \
+-	info.si_errno = 0; \
+-	info.si_code = sicode; \
+-	info.si_addr = (void __user *)siaddr; \
+-	trace_hardirqs_fixup(); \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-						== NOTIFY_STOP) \
+-		return; \
+-	do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
++#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)	\
++void do_##name(struct pt_regs *regs, long error_code)			\
++{									\
++	siginfo_t info;							\
++	info.si_signo = signr;						\
++	info.si_errno = 0;						\
++	info.si_code = sicode;						\
++	info.si_addr = (void __user *)siaddr;				\
++	trace_hardirqs_fixup();						\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++						== NOTIFY_STOP)		\
++		return;							\
++	do_trap(trapnr, signr, str, 1, regs, error_code, &info);	\
+ }
+ 
+-DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->ip)
++DO_VM86_ERROR_INFO(0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->ip)
+ #ifndef CONFIG_KPROBES
+-DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
++DO_VM86_ERROR(3, SIGTRAP, "int3", int3)
+ #endif
+-DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
+-DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
+-DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
++DO_VM86_ERROR(4, SIGSEGV, "overflow", overflow)
++DO_VM86_ERROR(5, SIGSEGV, "bounds", bounds)
++DO_ERROR_INFO(6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
++DO_ERROR(9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+ DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
+ DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
+ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
+-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
++DO_ERROR_INFO(32, SIGILL, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+ 
+-void __kprobes do_general_protection(struct pt_regs * regs,
+-					      long error_code)
++void __kprobes do_general_protection(struct pt_regs *regs, long error_code)
+ {
+-	int cpu = get_cpu();
+-	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+-	struct thread_struct *thread = &current->thread;
++	struct thread_struct *thread;
++	struct tss_struct *tss;
++	int cpu;
++
++	cpu = get_cpu();
++	tss = &per_cpu(init_tss, cpu);
++	thread = &current->thread;
+ 
+ 	/*
+ 	 * Perform the lazy TSS's I/O bitmap copy. If the TSS has an
+@@ -616,19 +629,21 @@ void __kprobes do_general_protection(struct pt_regs * regs,
+ 		 * If the previously set map was extending to higher ports
+ 		 * than the current one, pad extra space with 0xff (no access).
+ 		 */
+-		if (thread->io_bitmap_max < tss->io_bitmap_max)
++		if (thread->io_bitmap_max < tss->io_bitmap_max) {
+ 			memset((char *) tss->io_bitmap +
+ 				thread->io_bitmap_max, 0xff,
+ 				tss->io_bitmap_max - thread->io_bitmap_max);
++		}
+ 		tss->io_bitmap_max = thread->io_bitmap_max;
+ 		tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
+ 		tss->io_bitmap_owner = thread;
+ 		put_cpu();
++
+ 		return;
+ 	}
+ 	put_cpu();
+ 
+-	if (regs->flags & VM_MASK)
++	if (regs->flags & X86_VM_MASK)
+ 		goto gp_in_vm86;
+ 
+ 	if (!user_mode(regs))
+@@ -636,6 +651,7 @@ void __kprobes do_general_protection(struct pt_regs * regs,
+ 
+ 	current->thread.error_code = error_code;
+ 	current->thread.trap_no = 13;
++
+ 	if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
+ 	    printk_ratelimit()) {
+ 		printk(KERN_INFO
+@@ -665,22 +681,25 @@ gp_in_kernel:
+ 	}
+ }
+ 
+-static __kprobes void
+-mem_parity_error(unsigned char reason, struct pt_regs * regs)
++static notrace __kprobes void
++mem_parity_error(unsigned char reason, struct pt_regs *regs)
+ {
+-	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+-		"CPU %d.\n", reason, smp_processor_id());
+-	printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
++	printk(KERN_EMERG
++		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
++			reason, smp_processor_id());
++
++	printk(KERN_EMERG
++		"You have some hardware problem, likely on the PCI bus.\n");
+ 
+ #if defined(CONFIG_EDAC)
+-	if(edac_handler_set()) {
++	if (edac_handler_set()) {
+ 		edac_atomic_assert_error();
+ 		return;
+ 	}
+ #endif
+ 
+ 	if (panic_on_unrecovered_nmi)
+-                panic("NMI: Not continuing");
++		panic("NMI: Not continuing");
+ 
+ 	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ 
+@@ -688,8 +707,8 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ 	clear_mem_error(reason);
+ }
+ 
+-static __kprobes void
+-io_check_error(unsigned char reason, struct pt_regs * regs)
++static notrace __kprobes void
++io_check_error(unsigned char reason, struct pt_regs *regs)
+ {
+ 	unsigned long i;
+ 
+@@ -699,44 +718,52 @@ io_check_error(unsigned char reason, struct pt_regs * regs)
+ 	/* Re-enable the IOCK line, wait for a few seconds */
+ 	reason = (reason & 0xf) | 8;
+ 	outb(reason, 0x61);
++
+ 	i = 2000;
+-	while (--i) udelay(1000);
++	while (--i)
++		udelay(1000);
++
+ 	reason &= ~8;
+ 	outb(reason, 0x61);
+ }
+ 
+-static __kprobes void
+-unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
++static notrace __kprobes void
++unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
+ {
++	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
++		return;
+ #ifdef CONFIG_MCA
+-	/* Might actually be able to figure out what the guilty party
+-	* is. */
+-	if( MCA_bus ) {
++	/*
++	 * Might actually be able to figure out what the guilty party
++	 * is:
++	 */
++	if (MCA_bus) {
+ 		mca_handle_nmi();
+ 		return;
+ 	}
+ #endif
+-	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+-		"CPU %d.\n", reason, smp_processor_id());
++	printk(KERN_EMERG
++		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
++			reason, smp_processor_id());
++
+ 	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+ 	if (panic_on_unrecovered_nmi)
+-                panic("NMI: Not continuing");
++		panic("NMI: Not continuing");
+ 
+ 	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ }
+ 
+ static DEFINE_SPINLOCK(nmi_print_lock);
+ 
+-void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
++void notrace __kprobes die_nmi(struct pt_regs *regs, const char *msg)
+ {
+-	if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) ==
+-	    NOTIFY_STOP)
++	if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) == NOTIFY_STOP)
+ 		return;
+ 
+ 	spin_lock(&nmi_print_lock);
+ 	/*
+ 	* We are in trouble anyway, lets at least try
+-	* to get a message out.
++	* to get a message out:
+ 	*/
+ 	bust_spinlocks(1);
+ 	printk(KERN_EMERG "%s", msg);
+@@ -747,9 +774,10 @@ void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
+ 	spin_unlock(&nmi_print_lock);
+ 	bust_spinlocks(0);
+ 
+-	/* If we are in kernel we are probably nested up pretty bad
+-	 * and might aswell get out now while we still can.
+-	*/
++	/*
++	 * If we are in kernel we are probably nested up pretty bad
++	 * and might aswell get out now while we still can:
++	 */
+ 	if (!user_mode_vm(regs)) {
+ 		current->thread.trap_no = 2;
+ 		crash_kexec(regs);
+@@ -758,14 +786,14 @@ void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
+ 	do_exit(SIGSEGV);
+ }
+ 
+-static __kprobes void default_do_nmi(struct pt_regs * regs)
++static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+ {
+ 	unsigned char reason = 0;
+ 
+-	/* Only the BSP gets external NMIs from the system.  */
++	/* Only the BSP gets external NMIs from the system: */
+ 	if (!smp_processor_id())
+ 		reason = get_nmi_reason();
+- 
++
+ 	if (!(reason & 0xc0)) {
+ 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
+ 							== NOTIFY_STOP)
+@@ -778,8 +806,10 @@ static __kprobes void default_do_nmi(struct pt_regs * regs)
+ 		if (nmi_watchdog_tick(regs, reason))
+ 			return;
+ 		if (!do_nmi_callback(regs, smp_processor_id()))
+-#endif
+ 			unknown_nmi_error(reason, regs);
++#else
++		unknown_nmi_error(reason, regs);
++#endif
+ 
+ 		return;
+ 	}
+@@ -791,14 +821,14 @@ static __kprobes void default_do_nmi(struct pt_regs * regs)
+ 		io_check_error(reason, regs);
+ 	/*
+ 	 * Reassert NMI in case it became active meanwhile
+-	 * as it's edge-triggered.
++	 * as it's edge-triggered:
+ 	 */
+ 	reassert_nmi();
+ }
+ 
+ static int ignore_nmis;
+ 
+-__kprobes void do_nmi(struct pt_regs * regs, long error_code)
++notrace __kprobes void do_nmi(struct pt_regs *regs, long error_code)
+ {
+ 	int cpu;
+ 
+@@ -834,9 +864,12 @@ void __kprobes do_int3(struct pt_regs *regs, long error_code)
+ 	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+ 			== NOTIFY_STOP)
+ 		return;
+-	/* This is an interrupt gate, because kprobes wants interrupts
+-	disabled.  Normal trap handlers don't. */
++	/*
++	 * This is an interrupt gate, because kprobes wants interrupts
++	 * disabled. Normal trap handlers don't.
++	 */
+ 	restore_interrupts(regs);
++
+ 	do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
+ }
+ #endif
+@@ -851,7 +884,7 @@ void __kprobes do_int3(struct pt_regs *regs, long error_code)
+  * from user space. Such code must not hold kernel locks (since it
+  * can equally take a page fault), therefore it is safe to call
+  * force_sig_info even though that claims and releases locks.
+- * 
++ *
+  * Code in ./signal.c ensures that the debug control register
+  * is restored before we deliver any signal, and therefore that
+  * user code runs with the correct debug control register even though
+@@ -863,10 +896,10 @@ void __kprobes do_int3(struct pt_regs *regs, long error_code)
+  * find every occurrence of the TF bit that could be saved away even
+  * by user code)
+  */
+-void __kprobes do_debug(struct pt_regs * regs, long error_code)
++void __kprobes do_debug(struct pt_regs *regs, long error_code)
+ {
+-	unsigned int condition;
+ 	struct task_struct *tsk = current;
++	unsigned int condition;
+ 
+ 	trace_hardirqs_fixup();
+ 
+@@ -891,7 +924,7 @@ void __kprobes do_debug(struct pt_regs * regs, long error_code)
+ 			goto clear_dr7;
+ 	}
+ 
+-	if (regs->flags & VM_MASK)
++	if (regs->flags & X86_VM_MASK)
+ 		goto debug_vm86;
+ 
+ 	/* Save debug status register where ptrace can see it */
+@@ -914,7 +947,8 @@ void __kprobes do_debug(struct pt_regs * regs, long error_code)
+ 	/* Ok, finally something we can handle */
+ 	send_sigtrap(tsk, regs, error_code);
+ 
+-	/* Disable additional traps. They'll be re-enabled when
++	/*
++	 * Disable additional traps. They'll be re-enabled when
+ 	 * the signal is delivered.
+ 	 */
+ clear_dr7:
+@@ -927,7 +961,7 @@ debug_vm86:
+ 
+ clear_TF_reenable:
+ 	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+-	regs->flags &= ~TF_MASK;
++	regs->flags &= ~X86_EFLAGS_TF;
+ 	return;
+ }
+ 
+@@ -938,9 +972,10 @@ clear_TF_reenable:
+  */
+ void math_error(void __user *ip)
+ {
+-	struct task_struct * task;
++	struct task_struct *task;
++	unsigned short cwd;
++	unsigned short swd;
+ 	siginfo_t info;
+-	unsigned short cwd, swd;
+ 
+ 	/*
+ 	 * Save the info for the exception handler and clear the error.
+@@ -966,36 +1001,36 @@ void math_error(void __user *ip)
+ 	cwd = get_fpu_cwd(task);
+ 	swd = get_fpu_swd(task);
+ 	switch (swd & ~cwd & 0x3f) {
+-		case 0x000: /* No unmasked exception */
+-			return;
+-		default:    /* Multiple exceptions */
+-			break;
+-		case 0x001: /* Invalid Op */
+-			/*
+-			 * swd & 0x240 == 0x040: Stack Underflow
+-			 * swd & 0x240 == 0x240: Stack Overflow
+-			 * User must clear the SF bit (0x40) if set
+-			 */
+-			info.si_code = FPE_FLTINV;
+-			break;
+-		case 0x002: /* Denormalize */
+-		case 0x010: /* Underflow */
+-			info.si_code = FPE_FLTUND;
+-			break;
+-		case 0x004: /* Zero Divide */
+-			info.si_code = FPE_FLTDIV;
+-			break;
+-		case 0x008: /* Overflow */
+-			info.si_code = FPE_FLTOVF;
+-			break;
+-		case 0x020: /* Precision */
+-			info.si_code = FPE_FLTRES;
+-			break;
++	case 0x000: /* No unmasked exception */
++		return;
++	default:    /* Multiple exceptions */
++		break;
++	case 0x001: /* Invalid Op */
++		/*
++		 * swd & 0x240 == 0x040: Stack Underflow
++		 * swd & 0x240 == 0x240: Stack Overflow
++		 * User must clear the SF bit (0x40) if set
++		 */
++		info.si_code = FPE_FLTINV;
++		break;
++	case 0x002: /* Denormalize */
++	case 0x010: /* Underflow */
++		info.si_code = FPE_FLTUND;
++		break;
++	case 0x004: /* Zero Divide */
++		info.si_code = FPE_FLTDIV;
++		break;
++	case 0x008: /* Overflow */
++		info.si_code = FPE_FLTOVF;
++		break;
++	case 0x020: /* Precision */
++		info.si_code = FPE_FLTRES;
++		break;
+ 	}
+ 	force_sig_info(SIGFPE, &info, task);
+ }
+ 
+-void do_coprocessor_error(struct pt_regs * regs, long error_code)
++void do_coprocessor_error(struct pt_regs *regs, long error_code)
+ {
+ 	ignore_fpu_irq = 1;
+ 	math_error((void __user *)regs->ip);
+@@ -1003,9 +1038,9 @@ void do_coprocessor_error(struct pt_regs * regs, long error_code)
+ 
+ static void simd_math_error(void __user *ip)
+ {
+-	struct task_struct * task;
+-	siginfo_t info;
++	struct task_struct *task;
+ 	unsigned short mxcsr;
++	siginfo_t info;
+ 
+ 	/*
+ 	 * Save the info for the exception handler and clear the error.
+@@ -1026,82 +1061,80 @@ static void simd_math_error(void __user *ip)
+ 	 */
+ 	mxcsr = get_fpu_mxcsr(task);
+ 	switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+-		case 0x000:
+-		default:
+-			break;
+-		case 0x001: /* Invalid Op */
+-			info.si_code = FPE_FLTINV;
+-			break;
+-		case 0x002: /* Denormalize */
+-		case 0x010: /* Underflow */
+-			info.si_code = FPE_FLTUND;
+-			break;
+-		case 0x004: /* Zero Divide */
+-			info.si_code = FPE_FLTDIV;
+-			break;
+-		case 0x008: /* Overflow */
+-			info.si_code = FPE_FLTOVF;
+-			break;
+-		case 0x020: /* Precision */
+-			info.si_code = FPE_FLTRES;
+-			break;
++	case 0x000:
++	default:
++		break;
++	case 0x001: /* Invalid Op */
++		info.si_code = FPE_FLTINV;
++		break;
++	case 0x002: /* Denormalize */
++	case 0x010: /* Underflow */
++		info.si_code = FPE_FLTUND;
++		break;
++	case 0x004: /* Zero Divide */
++		info.si_code = FPE_FLTDIV;
++		break;
++	case 0x008: /* Overflow */
++		info.si_code = FPE_FLTOVF;
++		break;
++	case 0x020: /* Precision */
++		info.si_code = FPE_FLTRES;
++		break;
+ 	}
+ 	force_sig_info(SIGFPE, &info, task);
+ }
+ 
+-void do_simd_coprocessor_error(struct pt_regs * regs,
+-					  long error_code)
++void do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
+ {
+ 	if (cpu_has_xmm) {
+ 		/* Handle SIMD FPU exceptions on PIII+ processors. */
+ 		ignore_fpu_irq = 1;
+ 		simd_math_error((void __user *)regs->ip);
+-	} else {
+-		/*
+-		 * Handle strange cache flush from user space exception
+-		 * in all other cases.  This is undocumented behaviour.
+-		 */
+-		if (regs->flags & VM_MASK) {
+-			handle_vm86_fault((struct kernel_vm86_regs *)regs,
+-					  error_code);
+-			return;
+-		}
+-		current->thread.trap_no = 19;
+-		current->thread.error_code = error_code;
+-		die_if_kernel("cache flush denied", regs, error_code);
+-		force_sig(SIGSEGV, current);
++		return;
+ 	}
++	/*
++	 * Handle strange cache flush from user space exception
++	 * in all other cases.  This is undocumented behaviour.
++	 */
++	if (regs->flags & X86_VM_MASK) {
++		handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
++		return;
++	}
++	current->thread.trap_no = 19;
++	current->thread.error_code = error_code;
++	die_if_kernel("cache flush denied", regs, error_code);
++	force_sig(SIGSEGV, current);
+ }
+ 
+-void do_spurious_interrupt_bug(struct pt_regs * regs,
+-					  long error_code)
++void do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
+ {
+ #if 0
+ 	/* No need to warn about this any longer. */
+-	printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
++	printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+ #endif
+ }
+ 
+-unsigned long patch_espfix_desc(unsigned long uesp,
+-					  unsigned long kesp)
++unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
+ {
+ 	struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt;
+ 	unsigned long base = (kesp - uesp) & -THREAD_SIZE;
+ 	unsigned long new_kesp = kesp - base;
+ 	unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
+ 	__u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
++
+ 	/* Set up base for espfix segment */
+- 	desc &= 0x00f0ff0000000000ULL;
+- 	desc |=	((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
++	desc &= 0x00f0ff0000000000ULL;
++	desc |=	((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
+ 		((((__u64)base) << 32) & 0xff00000000000000ULL) |
+ 		((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
+ 		(lim_pages & 0xffff);
+ 	*(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
++
+ 	return new_kesp;
+ }
+ 
+ /*
+- *  'math_state_restore()' saves the current math information in the
++ * 'math_state_restore()' saves the current math information in the
+  * old math state array, and gets the new ones from the current task
+  *
+  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+@@ -1115,9 +1148,22 @@ asmlinkage void math_state_restore(void)
+ 	struct thread_info *thread = current_thread_info();
+ 	struct task_struct *tsk = thread->task;
+ 
+-	clts();		/* Allow maths ops (or we recurse) */
+-	if (!tsk_used_math(tsk))
+-		init_fpu(tsk);
++	if (!tsk_used_math(tsk)) {
++		local_irq_enable();
++		/*
++		 * does a slab alloc which can sleep
++		 */
++		if (init_fpu(tsk)) {
++			/*
++			 * ran out of memory!
++			 */
++			do_group_exit(SIGKILL);
++			return;
++		}
++		local_irq_disable();
++	}
++
++	clts();				/* Allow maths ops (or we recurse) */
+ 	restore_fpu(tsk);
+ 	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
+ 	tsk->fpu_counter++;
+@@ -1128,80 +1174,76 @@ EXPORT_SYMBOL_GPL(math_state_restore);
+ 
+ asmlinkage void math_emulate(long arg)
+ {
+-	printk(KERN_EMERG "math-emulation not enabled and no coprocessor found.\n");
+-	printk(KERN_EMERG "killing %s.\n",current->comm);
+-	force_sig(SIGFPE,current);
++	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 */
+ 
+-
+ void __init trap_init(void)
+ {
+ 	int i;
+ 
+ #ifdef CONFIG_EISA
+ 	void __iomem *p = early_ioremap(0x0FFFD9, 4);
+-	if (readl(p) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) {
++
++	if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
+ 		EISA_bus = 1;
+-	}
+ 	early_iounmap(p, 4);
+ #endif
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	init_apic_mappings();
+ #endif
+-
+-	set_trap_gate(0,&divide_error);
+-	set_intr_gate(1,&debug);
+-	set_intr_gate(2,&nmi);
++	set_trap_gate(0,  &divide_error);
++	set_intr_gate(1,  &debug);
++	set_intr_gate(2,  &nmi);
+ 	set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
+-	set_system_gate(4,&overflow);
+-	set_trap_gate(5,&bounds);
+-	set_trap_gate(6,&invalid_op);
+-	set_trap_gate(7,&device_not_available);
+-	set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
+-	set_trap_gate(9,&coprocessor_segment_overrun);
+-	set_trap_gate(10,&invalid_TSS);
+-	set_trap_gate(11,&segment_not_present);
+-	set_trap_gate(12,&stack_segment);
+-	set_trap_gate(13,&general_protection);
+-	set_intr_gate(14,&page_fault);
+-	set_trap_gate(15,&spurious_interrupt_bug);
+-	set_trap_gate(16,&coprocessor_error);
+-	set_trap_gate(17,&alignment_check);
++	set_system_gate(4, &overflow);
++	set_trap_gate(5,  &bounds);
++	set_trap_gate(6,  &invalid_op);
++	set_trap_gate(7,  &device_not_available);
++	set_task_gate(8,  GDT_ENTRY_DOUBLEFAULT_TSS);
++	set_trap_gate(9,  &coprocessor_segment_overrun);
++	set_trap_gate(10, &invalid_TSS);
++	set_trap_gate(11, &segment_not_present);
++	set_trap_gate(12, &stack_segment);
++	set_trap_gate(13, &general_protection);
++	set_intr_gate(14, &page_fault);
++	set_trap_gate(15, &spurious_interrupt_bug);
++	set_trap_gate(16, &coprocessor_error);
++	set_trap_gate(17, &alignment_check);
+ #ifdef CONFIG_X86_MCE
+-	set_trap_gate(18,&machine_check);
++	set_trap_gate(18, &machine_check);
+ #endif
+-	set_trap_gate(19,&simd_coprocessor_error);
++	set_trap_gate(19, &simd_coprocessor_error);
+ 
+-	/*
+-	 * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
+-	 * Generate a build-time error if the alignment is wrong.
+-	 */
+-	BUILD_BUG_ON(offsetof(struct task_struct, thread.i387.fxsave) & 15);
+ 	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... ");
++		printk(KERN_INFO
++			"Enabling unmasked SIMD FPU exception support... ");
+ 		set_in_cr4(X86_CR4_OSXMMEXCPT);
+ 		printk("done.\n");
+ 	}
+ 
+-	set_system_gate(SYSCALL_VECTOR,&system_call);
++	set_system_gate(SYSCALL_VECTOR, &system_call);
+ 
+-	/* Reserve all the builtin and the syscall vector. */
++	/* Reserve all the builtin and the syscall vector: */
+ 	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
+ 		set_bit(i, used_vectors);
++
+ 	set_bit(SYSCALL_VECTOR, used_vectors);
+ 
++	init_thread_xstate();
+ 	/*
+-	 * Should be a barrier for any external CPU state.
++	 * Should be a barrier for any external CPU state:
+ 	 */
+ 	cpu_init();
+ 
+@@ -1211,6 +1253,7 @@ void __init trap_init(void)
+ static int __init kstack_setup(char *s)
+ {
+ 	kstack_depth_to_print = simple_strtoul(s, NULL, 0);
++
+ 	return 1;
+ }
+ __setup("kstack=", kstack_setup);
+diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
+index 0454666..adff76e 100644
+--- a/arch/x86/kernel/traps_64.c
++++ b/arch/x86/kernel/traps_64.c
+@@ -33,6 +33,8 @@
+ #include <linux/kdebug.h>
+ #include <linux/utsname.h>
+ 
++#include <mach_traps.h>
++
+ #if defined(CONFIG_EDAC)
+ #include <linux/edac.h>
+ #endif
+@@ -598,10 +600,16 @@ void die(const char * str, struct pt_regs * regs, long err)
+ 	oops_end(flags, regs, SIGSEGV);
+ }
+ 
+-void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
++notrace __kprobes void
++die_nmi(char *str, struct pt_regs *regs, int do_panic)
+ {
+-	unsigned long flags = oops_begin();
++	unsigned long flags;
++
++	if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) ==
++	    NOTIFY_STOP)
++		return;
+ 
++	flags = oops_begin();
+ 	/*
+ 	 * We are in trouble anyway, lets at least try
+ 	 * to get a message out.
+@@ -765,7 +773,7 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
+ 	die("general protection fault", regs, error_code);
+ }
+ 
+-static __kprobes void
++static notrace __kprobes void
+ mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ {
+ 	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+@@ -789,7 +797,7 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ 	outb(reason, 0x61);
+ }
+ 
+-static __kprobes void
++static notrace __kprobes void
+ io_check_error(unsigned char reason, struct pt_regs * regs)
+ {
+ 	printk("NMI: IOCK error (debug interrupt?)\n");
+@@ -803,9 +811,11 @@ io_check_error(unsigned char reason, struct pt_regs * regs)
+ 	outb(reason, 0x61);
+ }
+ 
+-static __kprobes void
++static notrace __kprobes void
+ unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+ {
++	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
++		return;
+ 	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+ 		reason);
+ 	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+@@ -818,7 +828,7 @@ unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+ 
+ /* Runs on IST stack. This code must keep interrupts off all the time.
+    Nested NMIs are prevented by the CPU. */
+-asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
++asmlinkage notrace  __kprobes void default_do_nmi(struct pt_regs *regs)
+ {
+ 	unsigned char reason = 0;
+ 	int cpu;
+@@ -1114,11 +1124,24 @@ asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
+ asmlinkage void math_state_restore(void)
+ {
+ 	struct task_struct *me = current;
+-	clts();			/* Allow maths ops (or we recurse) */
+ 
+-	if (!used_math())
+-		init_fpu(me);
+-	restore_fpu_checking(&me->thread.i387.fxsave);
++	if (!used_math()) {
++		local_irq_enable();
++		/*
++		 * does a slab alloc which can sleep
++		 */
++		if (init_fpu(me)) {
++			/*
++			 * ran out of memory!
++			 */
++			do_group_exit(SIGKILL);
++			return;
++		}
++		local_irq_disable();
++	}
++
++	clts();			/* Allow maths ops (or we recurse) */
++	restore_fpu_checking(&me->thread.xstate->fxsave);
+ 	task_thread_info(me)->status |= TS_USEDFPU;
+ 	me->fpu_counter++;
+ }
+@@ -1154,6 +1177,10 @@ void __init trap_init(void)
+ #endif
+        
+ 	/*
++	 * initialize the per thread extended state:
++	 */
++        init_thread_xstate();
++	/*
+ 	 * Should be a barrier for any external CPU state.
+ 	 */
+ 	cpu_init();
+diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c
+index c2241e0..e479072 100644
+--- a/arch/x86/kernel/tsc_32.c
++++ b/arch/x86/kernel/tsc_32.c
+@@ -84,8 +84,8 @@ DEFINE_PER_CPU(unsigned long, cyc2ns);
+ 
+ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+ {
+-	unsigned long flags, prev_scale, *scale;
+ 	unsigned long long tsc_now, ns_now;
++	unsigned long flags, *scale;
+ 
+ 	local_irq_save(flags);
+ 	sched_clock_idle_sleep_event();
+@@ -95,7 +95,6 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+ 	rdtscll(tsc_now);
+ 	ns_now = __cycles_2_ns(tsc_now);
+ 
+-	prev_scale = *scale;
+ 	if (cpu_khz)
+ 		*scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
+ 
+@@ -222,9 +221,9 @@ EXPORT_SYMBOL(recalibrate_cpu_khz);
+  * if the CPU frequency is scaled, TSC-based delays will need a different
+  * loops_per_jiffy value to function properly.
+  */
+-static unsigned int ref_freq = 0;
+-static unsigned long loops_per_jiffy_ref = 0;
+-static unsigned long cpu_khz_ref = 0;
++static unsigned int ref_freq;
++static unsigned long loops_per_jiffy_ref;
++static unsigned long cpu_khz_ref;
+ 
+ static int
+ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
+@@ -284,15 +283,28 @@ core_initcall(cpufreq_tsc);
+ 
+ /* clock source code */
+ 
+-static unsigned long current_tsc_khz = 0;
++static unsigned long current_tsc_khz;
++static struct clocksource clocksource_tsc;
+ 
++/*
++ * We compare the TSC to the cycle_last value in the clocksource
++ * structure to avoid a nasty time-warp issue. This can be observed in
++ * a very small window right after one CPU updated cycle_last under
++ * xtime lock and the other CPU reads a TSC value which is smaller
++ * than the cycle_last reference value due to a TSC which is slighty
++ * behind. This delta is nowhere else observable, but in that case it
++ * results in a forward time jump in the range of hours due to the
++ * unsigned delta calculation of the time keeping core code, which is
++ * necessary to support wrapping clocksources like pm timer.
++ */
+ static cycle_t read_tsc(void)
+ {
+ 	cycle_t ret;
+ 
+ 	rdtscll(ret);
+ 
+-	return ret;
++	return ret >= clocksource_tsc.cycle_last ?
++		ret : clocksource_tsc.cycle_last;
+ }
+ 
+ static struct clocksource clocksource_tsc = {
+@@ -392,13 +404,15 @@ void __init tsc_init(void)
+ 	int cpu;
+ 
+ 	if (!cpu_has_tsc)
+-		goto out_no_tsc;
++		return;
+ 
+ 	cpu_khz = calculate_cpu_khz();
+ 	tsc_khz = cpu_khz;
+ 
+-	if (!cpu_khz)
+-		goto out_no_tsc;
++	if (!cpu_khz) {
++		mark_tsc_unstable("could not calculate TSC khz");
++		return;
++	}
+ 
+ 	printk("Detected %lu.%03lu MHz processor.\n",
+ 				(unsigned long)cpu_khz / 1000,
+@@ -431,9 +445,4 @@ void __init tsc_init(void)
+ 		tsc_enabled = 1;
+ 
+ 	clocksource_register(&clocksource_tsc);
+-
+-	return;
+-
+-out_no_tsc:
+-	setup_clear_cpu_cap(X86_FEATURE_TSC);
+ }
+diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c
+index d3bebaa..fcc16e5 100644
+--- a/arch/x86/kernel/tsc_64.c
++++ b/arch/x86/kernel/tsc_64.c
+@@ -11,6 +11,7 @@
+ #include <asm/hpet.h>
+ #include <asm/timex.h>
+ #include <asm/timer.h>
++#include <asm/vgtod.h>
+ 
+ static int notsc __initdata = 0;
+ 
+@@ -44,8 +45,8 @@ DEFINE_PER_CPU(unsigned long, cyc2ns);
+ 
+ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+ {
+-	unsigned long flags, prev_scale, *scale;
+ 	unsigned long long tsc_now, ns_now;
++	unsigned long flags, *scale;
+ 
+ 	local_irq_save(flags);
+ 	sched_clock_idle_sleep_event();
+@@ -55,7 +56,6 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+ 	rdtscll(tsc_now);
+ 	ns_now = __cycles_2_ns(tsc_now);
+ 
+-	prev_scale = *scale;
+ 	if (cpu_khz)
+ 		*scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
+ 
+@@ -288,18 +288,34 @@ int __init notsc_setup(char *s)
+ 
+ __setup("notsc", notsc_setup);
+ 
++static struct clocksource clocksource_tsc;
+ 
+-/* clock source code: */
++/*
++ * We compare the TSC to the cycle_last value in the clocksource
++ * structure to avoid a nasty time-warp. This can be observed in a
++ * very small window right after one CPU updated cycle_last under
++ * xtime/vsyscall_gtod lock and the other CPU reads a TSC value which
++ * is smaller than the cycle_last reference value due to a TSC which
++ * is slighty behind. This delta is nowhere else observable, but in
++ * that case it results in a forward time jump in the range of hours
++ * due to the unsigned delta calculation of the time keeping core
++ * code, which is necessary to support wrapping clocksources like pm
++ * timer.
++ */
+ static cycle_t read_tsc(void)
+ {
+ 	cycle_t ret = (cycle_t)get_cycles();
+-	return ret;
++
++	return ret >= clocksource_tsc.cycle_last ?
++		ret : clocksource_tsc.cycle_last;
+ }
+ 
+ static cycle_t __vsyscall_fn vread_tsc(void)
+ {
+ 	cycle_t ret = (cycle_t)vget_cycles();
+-	return ret;
++
++	return ret >= __vsyscall_gtod_data.clock.cycle_last ?
++		ret : __vsyscall_gtod_data.clock.cycle_last;
+ }
+ 
+ static struct clocksource clocksource_tsc = {
+diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
+index 738c210..38f566f 100644
+--- a/arch/x86/kernel/vm86_32.c
++++ b/arch/x86/kernel/vm86_32.c
+@@ -64,7 +64,7 @@
+ 
+ 
+ #define KVM86	((struct kernel_vm86_struct *)regs)
+-#define VMPI 	KVM86->vm86plus
++#define VMPI	KVM86->vm86plus
+ 
+ 
+ /*
+@@ -81,7 +81,7 @@
+ #define VFLAGS	(*(unsigned short *)&(current->thread.v86flags))
+ #define VEFLAGS	(current->thread.v86flags)
+ 
+-#define set_flags(X,new,mask) \
++#define set_flags(X, new, mask) \
+ ((X) = ((X) & ~(mask)) | ((new) & (mask)))
+ 
+ #define SAFE_MASK	(0xDD5)
+@@ -93,8 +93,10 @@ static int copy_vm86_regs_to_user(struct vm86_regs __user *user,
+ {
+ 	int ret = 0;
+ 
+-	/* kernel_vm86_regs is missing gs, so copy everything up to
+-	   (but not including) orig_eax, and then rest including orig_eax. */
++	/*
++	 * kernel_vm86_regs is missing gs, so copy everything up to
++	 * (but not including) orig_eax, and then rest including orig_eax.
++	 */
+ 	ret += copy_to_user(user, regs, offsetof(struct kernel_vm86_regs, pt.orig_ax));
+ 	ret += copy_to_user(&user->orig_eax, &regs->pt.orig_ax,
+ 			    sizeof(struct kernel_vm86_regs) -
+@@ -120,7 +122,7 @@ static int copy_vm86_regs_from_user(struct kernel_vm86_regs *regs,
+ 	return ret;
+ }
+ 
+-struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
++struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
+ {
+ 	struct tss_struct *tss;
+ 	struct pt_regs *ret;
+@@ -137,9 +139,9 @@ struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
+ 		printk("no vm86_info: BAD\n");
+ 		do_exit(SIGSEGV);
+ 	}
+-	set_flags(regs->pt.flags, VEFLAGS, VIF_MASK | current->thread.v86mask);
+-	tmp = copy_vm86_regs_to_user(&current->thread.vm86_info->regs,regs);
+-	tmp += put_user(current->thread.screen_bitmap,&current->thread.vm86_info->screen_bitmap);
++	set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | current->thread.v86mask);
++	tmp = copy_vm86_regs_to_user(&current->thread.vm86_info->regs, regs);
++	tmp += put_user(current->thread.screen_bitmap, &current->thread.vm86_info->screen_bitmap);
+ 	if (tmp) {
+ 		printk("vm86: could not access userspace vm86_info\n");
+ 		do_exit(SIGSEGV);
+@@ -237,20 +239,21 @@ asmlinkage int sys_vm86(struct pt_regs regs)
+ 
+ 	tsk = current;
+ 	switch (regs.bx) {
+-		case VM86_REQUEST_IRQ:
+-		case VM86_FREE_IRQ:
+-		case VM86_GET_IRQ_BITS:
+-		case VM86_GET_AND_RESET_IRQ:
+-			ret = do_vm86_irq_handling(regs.bx, (int)regs.cx);
+-			goto out;
+-		case VM86_PLUS_INSTALL_CHECK:
+-			/* NOTE: on old vm86 stuff this will return the error
+-			   from access_ok(), because the subfunction is
+-			   interpreted as (invalid) address to vm86_struct.
+-			   So the installation check works.
+-			 */
+-			ret = 0;
+-			goto out;
++	case VM86_REQUEST_IRQ:
++	case VM86_FREE_IRQ:
++	case VM86_GET_IRQ_BITS:
++	case VM86_GET_AND_RESET_IRQ:
++		ret = do_vm86_irq_handling(regs.bx, (int)regs.cx);
++		goto out;
++	case VM86_PLUS_INSTALL_CHECK:
++		/*
++		 * NOTE: on old vm86 stuff this will return the error
++		 *  from access_ok(), because the subfunction is
++		 *  interpreted as (invalid) address to vm86_struct.
++		 *  So the installation check works.
++		 */
++		ret = 0;
++		goto out;
+ 	}
+ 
+ 	/* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */
+@@ -296,21 +299,21 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
+ 	VEFLAGS = info->regs.pt.flags;
+ 	info->regs.pt.flags &= SAFE_MASK;
+ 	info->regs.pt.flags |= info->regs32->flags & ~SAFE_MASK;
+-	info->regs.pt.flags |= VM_MASK;
++	info->regs.pt.flags |= X86_VM_MASK;
+ 
+ 	switch (info->cpu_type) {
+-		case CPU_286:
+-			tsk->thread.v86mask = 0;
+-			break;
+-		case CPU_386:
+-			tsk->thread.v86mask = NT_MASK | IOPL_MASK;
+-			break;
+-		case CPU_486:
+-			tsk->thread.v86mask = AC_MASK | NT_MASK | IOPL_MASK;
+-			break;
+-		default:
+-			tsk->thread.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
+-			break;
++	case CPU_286:
++		tsk->thread.v86mask = 0;
++		break;
++	case CPU_386:
++		tsk->thread.v86mask = X86_EFLAGS_NT | X86_EFLAGS_IOPL;
++		break;
++	case CPU_486:
++		tsk->thread.v86mask = X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
++		break;
++	default:
++		tsk->thread.v86mask = X86_EFLAGS_ID | X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
++		break;
+ 	}
+ 
+ /*
+@@ -346,9 +349,9 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
+ 	/* we never return here */
+ }
+ 
+-static inline void return_to_32bit(struct kernel_vm86_regs * regs16, int retval)
++static inline void return_to_32bit(struct kernel_vm86_regs *regs16, int retval)
+ {
+-	struct pt_regs * regs32;
++	struct pt_regs *regs32;
+ 
+ 	regs32 = save_v86_state(regs16);
+ 	regs32->ax = retval;
+@@ -358,29 +361,30 @@ static inline void return_to_32bit(struct kernel_vm86_regs * regs16, int retval)
+ 		: : "r" (regs32), "r" (current_thread_info()));
+ }
+ 
+-static inline void set_IF(struct kernel_vm86_regs * regs)
++static inline void set_IF(struct kernel_vm86_regs *regs)
+ {
+-	VEFLAGS |= VIF_MASK;
+-	if (VEFLAGS & VIP_MASK)
++	VEFLAGS |= X86_EFLAGS_VIF;
++	if (VEFLAGS & X86_EFLAGS_VIP)
+ 		return_to_32bit(regs, VM86_STI);
+ }
+ 
+-static inline void clear_IF(struct kernel_vm86_regs * regs)
++static inline void clear_IF(struct kernel_vm86_regs *regs)
+ {
+-	VEFLAGS &= ~VIF_MASK;
++	VEFLAGS &= ~X86_EFLAGS_VIF;
+ }
+ 
+-static inline void clear_TF(struct kernel_vm86_regs * regs)
++static inline void clear_TF(struct kernel_vm86_regs *regs)
+ {
+-	regs->pt.flags &= ~TF_MASK;
++	regs->pt.flags &= ~X86_EFLAGS_TF;
+ }
+ 
+-static inline void clear_AC(struct kernel_vm86_regs * regs)
++static inline void clear_AC(struct kernel_vm86_regs *regs)
+ {
+-	regs->pt.flags &= ~AC_MASK;
++	regs->pt.flags &= ~X86_EFLAGS_AC;
+ }
+ 
+-/* It is correct to call set_IF(regs) from the set_vflags_*
++/*
++ * It is correct to call set_IF(regs) from the set_vflags_*
+  * functions. However someone forgot to call clear_IF(regs)
+  * in the opposite case.
+  * After the command sequence CLI PUSHF STI POPF you should
+@@ -391,41 +395,41 @@ static inline void clear_AC(struct kernel_vm86_regs * regs)
+  * [KD]
+  */
+ 
+-static inline void set_vflags_long(unsigned long flags, struct kernel_vm86_regs * regs)
++static inline void set_vflags_long(unsigned long flags, struct kernel_vm86_regs *regs)
+ {
+ 	set_flags(VEFLAGS, flags, current->thread.v86mask);
+ 	set_flags(regs->pt.flags, flags, SAFE_MASK);
+-	if (flags & IF_MASK)
++	if (flags & X86_EFLAGS_IF)
+ 		set_IF(regs);
+ 	else
+ 		clear_IF(regs);
+ }
+ 
+-static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs * regs)
++static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs *regs)
+ {
+ 	set_flags(VFLAGS, flags, current->thread.v86mask);
+ 	set_flags(regs->pt.flags, flags, SAFE_MASK);
+-	if (flags & IF_MASK)
++	if (flags & X86_EFLAGS_IF)
+ 		set_IF(regs);
+ 	else
+ 		clear_IF(regs);
+ }
+ 
+-static inline unsigned long get_vflags(struct kernel_vm86_regs * regs)
++static inline unsigned long get_vflags(struct kernel_vm86_regs *regs)
+ {
+ 	unsigned long flags = regs->pt.flags & RETURN_MASK;
+ 
+-	if (VEFLAGS & VIF_MASK)
+-		flags |= IF_MASK;
+-	flags |= IOPL_MASK;
++	if (VEFLAGS & X86_EFLAGS_VIF)
++		flags |= X86_EFLAGS_IF;
++	flags |= X86_EFLAGS_IOPL;
+ 	return flags | (VEFLAGS & current->thread.v86mask);
+ }
+ 
+-static inline int is_revectored(int nr, struct revectored_struct * bitmap)
++static inline int is_revectored(int nr, struct revectored_struct *bitmap)
+ {
+ 	__asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
+ 		:"=r" (nr)
+-		:"m" (*bitmap),"r" (nr));
++		:"m" (*bitmap), "r" (nr));
+ 	return nr;
+ }
+ 
+@@ -437,7 +441,7 @@ static inline int is_revectored(int nr, struct revectored_struct * bitmap)
+ 		ptr--; \
+ 		if (put_user(__val, base + ptr) < 0) \
+ 			goto err_label; \
+-	} while(0)
++	} while (0)
+ 
+ #define pushw(base, ptr, val, err_label) \
+ 	do { \
+@@ -448,7 +452,7 @@ static inline int is_revectored(int nr, struct revectored_struct * bitmap)
+ 		ptr--; \
+ 		if (put_user(val_byte(__val, 0), base + ptr) < 0) \
+ 			goto err_label; \
+-	} while(0)
++	} while (0)
+ 
+ #define pushl(base, ptr, val, err_label) \
+ 	do { \
+@@ -465,7 +469,7 @@ static inline int is_revectored(int nr, struct revectored_struct * bitmap)
+ 		ptr--; \
+ 		if (put_user(val_byte(__val, 0), base + ptr) < 0) \
+ 			goto err_label; \
+-	} while(0)
++	} while (0)
+ 
+ #define popb(base, ptr, err_label) \
+ 	({ \
+@@ -512,7 +516,7 @@ static inline int is_revectored(int nr, struct revectored_struct * bitmap)
+  * in userspace is always better than an Oops anyway.) [KD]
+  */
+ static void do_int(struct kernel_vm86_regs *regs, int i,
+-    unsigned char __user * ssp, unsigned short sp)
++    unsigned char __user *ssp, unsigned short sp)
+ {
+ 	unsigned long __user *intr_ptr;
+ 	unsigned long segoffs;
+@@ -521,7 +525,7 @@ static void do_int(struct kernel_vm86_regs *regs, int i,
+ 		goto cannot_handle;
+ 	if (is_revectored(i, &KVM86->int_revectored))
+ 		goto cannot_handle;
+-	if (i==0x21 && is_revectored(AH(regs),&KVM86->int21_revectored))
++	if (i == 0x21 && is_revectored(AH(regs), &KVM86->int21_revectored))
+ 		goto cannot_handle;
+ 	intr_ptr = (unsigned long __user *) (i << 2);
+ 	if (get_user(segoffs, intr_ptr))
+@@ -543,30 +547,23 @@ cannot_handle:
+ 	return_to_32bit(regs, VM86_INTx + (i << 8));
+ }
+ 
+-int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno)
++int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno)
+ {
+ 	if (VMPI.is_vm86pus) {
+-		if ( (trapno==3) || (trapno==1) )
++		if ((trapno == 3) || (trapno == 1))
+ 			return_to_32bit(regs, VM86_TRAP + (trapno << 8));
+ 		do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs));
+ 		return 0;
+ 	}
+-	if (trapno !=1)
++	if (trapno != 1)
+ 		return 1; /* we let this handle by the calling routine */
+-	if (current->ptrace & PT_PTRACED) {
+-		unsigned long flags;
+-		spin_lock_irqsave(&current->sighand->siglock, flags);
+-		sigdelset(&current->blocked, SIGTRAP);
+-		recalc_sigpending();
+-		spin_unlock_irqrestore(&current->sighand->siglock, flags);
+-	}
+-	send_sig(SIGTRAP, current, 1);
+ 	current->thread.trap_no = trapno;
+ 	current->thread.error_code = error_code;
++	force_sig(SIGTRAP, current);
+ 	return 0;
+ }
+ 
+-void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
++void handle_vm86_fault(struct kernel_vm86_regs *regs, long error_code)
+ {
+ 	unsigned char opcode;
+ 	unsigned char __user *csp;
+@@ -576,11 +573,11 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+ 
+ #define CHECK_IF_IN_TRAP \
+ 	if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \
+-		newflags |= TF_MASK
++		newflags |= X86_EFLAGS_TF
+ #define VM86_FAULT_RETURN do { \
+-	if (VMPI.force_return_for_pic  && (VEFLAGS & (IF_MASK | VIF_MASK))) \
++	if (VMPI.force_return_for_pic  && (VEFLAGS & (X86_EFLAGS_IF | X86_EFLAGS_VIF))) \
+ 		return_to_32bit(regs, VM86_PICRETURN); \
+-	if (orig_flags & TF_MASK) \
++	if (orig_flags & X86_EFLAGS_TF) \
+ 		handle_vm86_trap(regs, 0, 1); \
+ 	return; } while (0)
+ 
+@@ -595,17 +592,17 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+ 	pref_done = 0;
+ 	do {
+ 		switch (opcode = popb(csp, ip, simulate_sigsegv)) {
+-			case 0x66:      /* 32-bit data */     data32=1; break;
+-			case 0x67:      /* 32-bit address */  break;
+-			case 0x2e:      /* CS */              break;
+-			case 0x3e:      /* DS */              break;
+-			case 0x26:      /* ES */              break;
+-			case 0x36:      /* SS */              break;
+-			case 0x65:      /* GS */              break;
+-			case 0x64:      /* FS */              break;
+-			case 0xf2:      /* repnz */       break;
+-			case 0xf3:      /* rep */             break;
+-			default: pref_done = 1;
++		case 0x66:      /* 32-bit data */     data32 = 1; break;
++		case 0x67:      /* 32-bit address */  break;
++		case 0x2e:      /* CS */              break;
++		case 0x3e:      /* DS */              break;
++		case 0x26:      /* ES */              break;
++		case 0x36:      /* SS */              break;
++		case 0x65:      /* GS */              break;
++		case 0x64:      /* FS */              break;
++		case 0xf2:      /* repnz */       break;
++		case 0xf3:      /* rep */             break;
++		default: pref_done = 1;
+ 		}
+ 	} while (!pref_done);
+ 
+@@ -628,7 +625,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+ 		{
+ 		unsigned long newflags;
+ 		if (data32) {
+-			newflags=popl(ssp, sp, simulate_sigsegv);
++			newflags = popl(ssp, sp, simulate_sigsegv);
+ 			SP(regs) += 4;
+ 		} else {
+ 			newflags = popw(ssp, sp, simulate_sigsegv);
+@@ -636,20 +633,20 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+ 		}
+ 		IP(regs) = ip;
+ 		CHECK_IF_IN_TRAP;
+-		if (data32) {
++		if (data32)
+ 			set_vflags_long(newflags, regs);
+-		} else {
++		else
+ 			set_vflags_short(newflags, regs);
+-		}
++
+ 		VM86_FAULT_RETURN;
+ 		}
+ 
+ 	/* int xx */
+ 	case 0xcd: {
+-		int intno=popb(csp, ip, simulate_sigsegv);
++		int intno = popb(csp, ip, simulate_sigsegv);
+ 		IP(regs) = ip;
+ 		if (VMPI.vm86dbg_active) {
+-			if ( (1 << (intno &7)) & VMPI.vm86dbg_intxxtab[intno >> 3] )
++			if ((1 << (intno & 7)) & VMPI.vm86dbg_intxxtab[intno >> 3])
+ 				return_to_32bit(regs, VM86_INTx + (intno << 8));
+ 		}
+ 		do_int(regs, intno, ssp, sp);
+@@ -663,9 +660,9 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+ 		unsigned long newcs;
+ 		unsigned long newflags;
+ 		if (data32) {
+-			newip=popl(ssp, sp, simulate_sigsegv);
+-			newcs=popl(ssp, sp, simulate_sigsegv);
+-			newflags=popl(ssp, sp, simulate_sigsegv);
++			newip = popl(ssp, sp, simulate_sigsegv);
++			newcs = popl(ssp, sp, simulate_sigsegv);
++			newflags = popl(ssp, sp, simulate_sigsegv);
+ 			SP(regs) += 12;
+ 		} else {
+ 			newip = popw(ssp, sp, simulate_sigsegv);
+@@ -734,18 +731,18 @@ static struct vm86_irqs {
+ static DEFINE_SPINLOCK(irqbits_lock);
+ static int irqbits;
+ 
+-#define ALLOWED_SIGS ( 1 /* 0 = don't send a signal */ \
++#define ALLOWED_SIGS (1 /* 0 = don't send a signal */ \
+ 	| (1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGIO)  | (1 << SIGURG) \
+-	| (1 << SIGUNUSED) )
+-	
++	| (1 << SIGUNUSED))
++
+ static irqreturn_t irq_handler(int intno, void *dev_id)
+ {
+ 	int irq_bit;
+ 	unsigned long flags;
+ 
+-	spin_lock_irqsave(&irqbits_lock, flags);	
++	spin_lock_irqsave(&irqbits_lock, flags);
+ 	irq_bit = 1 << intno;
+-	if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk)
++	if ((irqbits & irq_bit) || !vm86_irqs[intno].tsk)
+ 		goto out;
+ 	irqbits |= irq_bit;
+ 	if (vm86_irqs[intno].sig)
+@@ -759,7 +756,7 @@ static irqreturn_t irq_handler(int intno, void *dev_id)
+ 	return IRQ_HANDLED;
+ 
+ out:
+-	spin_unlock_irqrestore(&irqbits_lock, flags);	
++	spin_unlock_irqrestore(&irqbits_lock, flags);
+ 	return IRQ_NONE;
+ }
+ 
+@@ -770,9 +767,9 @@ static inline void free_vm86_irq(int irqnumber)
+ 	free_irq(irqnumber, NULL);
+ 	vm86_irqs[irqnumber].tsk = NULL;
+ 
+-	spin_lock_irqsave(&irqbits_lock, flags);	
++	spin_lock_irqsave(&irqbits_lock, flags);
+ 	irqbits &= ~(1 << irqnumber);
+-	spin_unlock_irqrestore(&irqbits_lock, flags);	
++	spin_unlock_irqrestore(&irqbits_lock, flags);
+ }
+ 
+ void release_vm86_irqs(struct task_struct *task)
+@@ -788,10 +785,10 @@ static inline int get_and_reset_irq(int irqnumber)
+ 	int bit;
+ 	unsigned long flags;
+ 	int ret = 0;
+-	
++
+ 	if (invalid_vm86_irq(irqnumber)) return 0;
+ 	if (vm86_irqs[irqnumber].tsk != current) return 0;
+-	spin_lock_irqsave(&irqbits_lock, flags);	
++	spin_lock_irqsave(&irqbits_lock, flags);
+ 	bit = irqbits & (1 << irqnumber);
+ 	irqbits &= ~bit;
+ 	if (bit) {
+@@ -799,7 +796,7 @@ static inline int get_and_reset_irq(int irqnumber)
+ 		ret = 1;
+ 	}
+ 
+-	spin_unlock_irqrestore(&irqbits_lock, flags);	
++	spin_unlock_irqrestore(&irqbits_lock, flags);
+ 	return ret;
+ }
+ 
+diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
+index 12affe1..956f389 100644
+--- a/arch/x86/kernel/vmi_32.c
++++ b/arch/x86/kernel/vmi_32.c
+@@ -320,7 +320,7 @@ static void check_zeroed_page(u32 pfn, int type, struct page *page)
+ 	 * pdes need to be zeroed.
+ 	 */
+ 	if (type & VMI_PAGE_CLONE)
+-		limit = USER_PTRS_PER_PGD;
++		limit = KERNEL_PGD_BOUNDARY;
+ 	for (i = 0; i < limit; i++)
+ 		BUG_ON(ptr[i]);
+ }
+@@ -392,13 +392,13 @@ static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type)
+ }
+ #endif
+ 
+-static void vmi_allocate_pt(struct mm_struct *mm, u32 pfn)
++static void vmi_allocate_pte(struct mm_struct *mm, u32 pfn)
+ {
+ 	vmi_set_page_type(pfn, VMI_PAGE_L1);
+ 	vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
+ }
+ 
+-static void vmi_allocate_pd(struct mm_struct *mm, u32 pfn)
++static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn)
+ {
+  	/*
+ 	 * This call comes in very early, before mem_map is setup.
+@@ -409,20 +409,20 @@ static void vmi_allocate_pd(struct mm_struct *mm, u32 pfn)
+ 	vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0);
+ }
+ 
+-static void vmi_allocate_pd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count)
++static void vmi_allocate_pmd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count)
+ {
+  	vmi_set_page_type(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE);
+ 	vmi_check_page_type(clonepfn, VMI_PAGE_L2);
+ 	vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count);
+ }
+ 
+-static void vmi_release_pt(u32 pfn)
++static void vmi_release_pte(u32 pfn)
+ {
+ 	vmi_ops.release_page(pfn, VMI_PAGE_L1);
+ 	vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
+ }
+ 
+-static void vmi_release_pd(u32 pfn)
++static void vmi_release_pmd(u32 pfn)
+ {
+ 	vmi_ops.release_page(pfn, VMI_PAGE_L2);
+ 	vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
+@@ -871,15 +871,15 @@ static inline int __init activate_vmi(void)
+ 
+ 	vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
+ 	if (vmi_ops.allocate_page) {
+-		pv_mmu_ops.alloc_pt = vmi_allocate_pt;
+-		pv_mmu_ops.alloc_pd = vmi_allocate_pd;
+-		pv_mmu_ops.alloc_pd_clone = vmi_allocate_pd_clone;
++		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_pt = vmi_release_pt;
+-		pv_mmu_ops.release_pd = vmi_release_pd;
++		pv_mmu_ops.release_pte = vmi_release_pte;
++		pv_mmu_ops.release_pmd = vmi_release_pmd;
+ 	}
+ 
+ 	/* Set linear is needed in all cases */
+diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S
+index 2ffa965..ce5ed08 100644
+--- a/arch/x86/kernel/vmlinux_32.lds.S
++++ b/arch/x86/kernel/vmlinux_32.lds.S
+@@ -149,6 +149,11 @@ SECTIONS
+ 	*(.con_initcall.init)
+   	__con_initcall_end = .;
+   }
++  .x86cpuvendor.init : AT(ADDR(.x86cpuvendor.init) - LOAD_OFFSET) {
++	__x86cpuvendor_start = .;
++	*(.x86cpuvendor.init)
++	__x86cpuvendor_end = .;
++  }
+   SECURITY_INIT
+   . = ALIGN(4);
+   .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
+index fab1322..b7ab3c3 100644
+--- a/arch/x86/kernel/vmlinux_64.lds.S
++++ b/arch/x86/kernel/vmlinux_64.lds.S
+@@ -177,6 +177,11 @@ SECTIONS
+ 	*(.con_initcall.init)
+   }
+   __con_initcall_end = .;
++  __x86cpuvendor_start = .;
++  .x86cpuvendor.init : AT(ADDR(.x86cpuvendor.init) - LOAD_OFFSET) {
++	*(.x86cpuvendor.init)
++  }
++  __x86cpuvendor_end = .;
+   SECURITY_INIT
+ 
+   . = ALIGN(8);
+@@ -247,3 +252,9 @@ SECTIONS
+ 
+   DWARF_DEBUG
+ }
++
++/*
++ * Build-time check on the image size:
++ */
++ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
++	"kernel image bigger than KERNEL_IMAGE_SIZE")
+diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c
+index d971210..caf2a26 100644
+--- a/arch/x86/kernel/vsmp_64.c
++++ b/arch/x86/kernel/vsmp_64.c
+@@ -8,6 +8,8 @@
+  *
+  * Ravikiran Thirumalai <kiran at scalemp.com>,
+  * Shai Fultheim <shai at scalemp.com>
++ * Paravirt ops integration: Glauber de Oliveira Costa <gcosta at redhat.com>,
++ *			     Ravikiran Thirumalai <kiran at scalemp.com>
+  */
+ 
+ #include <linux/init.h>
+@@ -15,38 +17,137 @@
+ #include <linux/pci_regs.h>
+ #include <asm/pci-direct.h>
+ #include <asm/io.h>
++#include <asm/paravirt.h>
+ 
+-static int __init vsmp_init(void)
++#if defined CONFIG_PCI && defined CONFIG_PARAVIRT
++/*
++ * Interrupt control on vSMPowered systems:
++ * ~AC is a shadow of IF.  If IF is 'on' AC should be 'off'
++ * and vice versa.
++ */
++
++static unsigned long vsmp_save_fl(void)
+ {
+-	void *address;
+-	unsigned int cap, ctl;
++	unsigned long flags = native_save_fl();
+ 
+-	if (!early_pci_allowed())
+-		return 0;
++	if (!(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC))
++		flags &= ~X86_EFLAGS_IF;
++	return flags;
++}
+ 
+-	/* Check if we are running on a ScaleMP vSMP box */
+-	if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) !=
+-	     PCI_VENDOR_ID_SCALEMP) ||
+-	    (read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) !=
+-	     PCI_DEVICE_ID_SCALEMP_VSMP_CTL))
+-		return 0;
++static void vsmp_restore_fl(unsigned long flags)
++{
++	if (flags & X86_EFLAGS_IF)
++		flags &= ~X86_EFLAGS_AC;
++	else
++		flags |= X86_EFLAGS_AC;
++	native_restore_fl(flags);
++}
++
++static void vsmp_irq_disable(void)
++{
++	unsigned long flags = native_save_fl();
++
++	native_restore_fl((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
++}
++
++static void vsmp_irq_enable(void)
++{
++	unsigned long flags = native_save_fl();
++
++	native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
++}
++
++static unsigned __init vsmp_patch(u8 type, u16 clobbers, void *ibuf,
++				  unsigned long addr, unsigned len)
++{
++	switch (type) {
++	case PARAVIRT_PATCH(pv_irq_ops.irq_enable):
++	case PARAVIRT_PATCH(pv_irq_ops.irq_disable):
++	case PARAVIRT_PATCH(pv_irq_ops.save_fl):
++	case PARAVIRT_PATCH(pv_irq_ops.restore_fl):
++		return paravirt_patch_default(type, clobbers, ibuf, addr, len);
++	default:
++		return native_patch(type, clobbers, ibuf, addr, len);
++	}
++
++}
++
++static void __init set_vsmp_pv_ops(void)
++{
++	void *address;
++	unsigned int cap, ctl, cfg;
+ 
+ 	/* set vSMP magic bits to indicate vSMP capable kernel */
+-	address = ioremap(read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0), 8);
++	cfg = read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0);
++	address = early_ioremap(cfg, 8);
+ 	cap = readl(address);
+ 	ctl = readl(address + 4);
+ 	printk(KERN_INFO "vSMP CTL: capabilities:0x%08x  control:0x%08x\n",
+ 	       cap, ctl);
+ 	if (cap & ctl & (1 << 4)) {
+-		/* Turn on vSMP IRQ fastpath handling (see system.h) */
++		/* Setup irq ops and turn on vSMP  IRQ fastpath handling */
++		pv_irq_ops.irq_disable = vsmp_irq_disable;
++		pv_irq_ops.irq_enable  = vsmp_irq_enable;
++		pv_irq_ops.save_fl  = vsmp_save_fl;
++		pv_irq_ops.restore_fl  = vsmp_restore_fl;
++		pv_init_ops.patch = vsmp_patch;
++
+ 		ctl &= ~(1 << 4);
+ 		writel(ctl, address + 4);
+ 		ctl = readl(address + 4);
+ 		printk(KERN_INFO "vSMP CTL: control set to:0x%08x\n", ctl);
+ 	}
+ 
+-	iounmap(address);
++	early_iounmap(address, 8);
++}
++#else
++static void __init set_vsmp_pv_ops(void)
++{
++}
++#endif
++
++#ifdef CONFIG_PCI
++static int is_vsmp = -1;
++
++static void __init detect_vsmp_box(void)
++{
++	is_vsmp = 0;
++
++	if (!early_pci_allowed())
++		return;
++
++	/* Check if we are running on a ScaleMP vSMPowered box */
++	if (read_pci_config(0, 0x1f, 0, PCI_VENDOR_ID) ==
++	     (PCI_VENDOR_ID_SCALEMP | (PCI_DEVICE_ID_SCALEMP_VSMP_CTL << 16)))
++		is_vsmp = 1;
++}
++
++int is_vsmp_box(void)
++{
++	if (is_vsmp != -1)
++		return is_vsmp;
++	else {
++		WARN_ON_ONCE(1);
++		return 0;
++	}
++}
++#else
++static int __init detect_vsmp_box(void)
++{
++}
++int is_vsmp_box(void)
++{
+ 	return 0;
+ }
++#endif
+ 
+-core_initcall(vsmp_init);
++void __init vsmp_init(void)
++{
++	detect_vsmp_box();
++	if (!is_vsmp_box())
++		return;
++
++	set_vsmp_pv_ops();
++	return;
++}
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index edff4c9..61efa2f 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -216,7 +216,7 @@ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+ 	return 0;
+ }
+ 
+-long __vsyscall(3) venosys_1(void)
++static long __vsyscall(3) venosys_1(void)
+ {
+ 	return -ENOSYS;
+ }
+diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
+index a66e9c1..58882f9 100644
+--- a/arch/x86/kernel/x8664_ksyms_64.c
++++ b/arch/x86/kernel/x8664_ksyms_64.c
+@@ -4,7 +4,6 @@
+ #include <linux/module.h>
+ #include <linux/smp.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -12,11 +11,6 @@
+ 
+ EXPORT_SYMBOL(kernel_thread);
+ 
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+-
+ EXPORT_SYMBOL(__get_user_1);
+ EXPORT_SYMBOL(__get_user_2);
+ EXPORT_SYMBOL(__get_user_4);
+@@ -35,15 +29,17 @@ EXPORT_SYMBOL(__copy_from_user_inatomic);
+ EXPORT_SYMBOL(copy_page);
+ EXPORT_SYMBOL(clear_page);
+ 
+-/* Export string functions. We normally rely on gcc builtin for most of these,
+-   but gcc sometimes decides not to inline them. */    
++/*
++ * Export string functions. We normally rely on gcc builtin for most of these,
++ * but gcc sometimes decides not to inline them.
++ */
+ #undef memcpy
+ #undef memset
+ #undef memmove
+ 
+-extern void * memset(void *,int,__kernel_size_t);
+-extern void * memcpy(void *,const void *,__kernel_size_t);
+-extern void * __memcpy(void *,const void *,__kernel_size_t);
++extern void *memset(void *, int, __kernel_size_t);
++extern void *memcpy(void *, const void *, __kernel_size_t);
++extern void *__memcpy(void *, const void *, __kernel_size_t);
+ 
+ EXPORT_SYMBOL(memset);
+ EXPORT_SYMBOL(memcpy);
+diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
+index 3335b45..af65b2d 100644
+--- a/arch/x86/lguest/boot.c
++++ b/arch/x86/lguest/boot.c
+@@ -661,7 +661,7 @@ static int lguest_clockevent_set_next_event(unsigned long delta,
+ 	if (delta < LG_CLOCK_MIN_DELTA) {
+ 		if (printk_ratelimit())
+ 			printk(KERN_DEBUG "%s: small delta %lu ns\n",
+-			       __FUNCTION__, delta);
++			       __func__, delta);
+ 		return -ETIME;
+ 	}
+ 
+diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
+index 37756b6..5415a9d 100644
+--- a/arch/x86/lib/memcpy_32.c
++++ b/arch/x86/lib/memcpy_32.c
+@@ -25,7 +25,7 @@ void *memmove(void *dest, const void *src, size_t n)
+ 	int d0, d1, d2;
+ 
+ 	if (dest < src) {
+-		memcpy(dest,src,n);
++		memcpy(dest, src, n);
+ 	} else {
+ 		__asm__ __volatile__(
+ 			"std\n\t"
+diff --git a/arch/x86/lib/memmove_64.c b/arch/x86/lib/memmove_64.c
+index 80175e4..0a33909 100644
+--- a/arch/x86/lib/memmove_64.c
++++ b/arch/x86/lib/memmove_64.c
+@@ -6,10 +6,10 @@
+ #include <linux/module.h>
+ 
+ #undef memmove
+-void *memmove(void * dest,const void *src,size_t count)
++void *memmove(void *dest, const void *src, size_t count)
+ {
+-	if (dest < src) { 
+-		return memcpy(dest,src,count);
++	if (dest < src) {
++		return memcpy(dest, src, count);
+ 	} else {
+ 		char *p = dest + count;
+ 		const char *s = src + count;
+@@ -17,5 +17,5 @@ void *memmove(void * dest,const void *src,size_t count)
+ 			*--p = *--s;
+ 	}
+ 	return dest;
+-} 
++}
+ EXPORT_SYMBOL(memmove);
+diff --git a/arch/x86/lib/mmx_32.c b/arch/x86/lib/mmx_32.c
+index cc9b4a4..c9f2d9b 100644
+--- a/arch/x86/lib/mmx_32.c
++++ b/arch/x86/lib/mmx_32.c
+@@ -1,32 +1,30 @@
+-#include <linux/types.h>
+-#include <linux/string.h>
+-#include <linux/sched.h>
+-#include <linux/hardirq.h>
+-#include <linux/module.h>
+-
+-#include <asm/asm.h>
+-#include <asm/i387.h>
+-
+-
+ /*
+  *	MMX 3DNow! library helper functions
+  *
+  *	To do:
+- *	We can use MMX just for prefetch in IRQ's. This may be a win. 
++ *	We can use MMX just for prefetch in IRQ's. This may be a win.
+  *		(reported so on K6-III)
+  *	We should use a better code neutral filler for the short jump
+  *		leal ebx. [ebx] is apparently best for K6-2, but Cyrix ??
+  *	We also want to clobber the filler register so we don't get any
+- *		register forwarding stalls on the filler. 
++ *		register forwarding stalls on the filler.
+  *
+  *	Add *user handling. Checksums are not a win with MMX on any CPU
+  *	tested so far for any MMX solution figured.
+  *
+- *	22/09/2000 - Arjan van de Ven 
+- *		Improved for non-egineering-sample Athlons 
++ *	22/09/2000 - Arjan van de Ven
++ *		Improved for non-egineering-sample Athlons
+  *
+  */
+- 
++#include <linux/hardirq.h>
++#include <linux/string.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++
++#include <asm/i387.h>
++#include <asm/asm.h>
++
+ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ {
+ 	void *p;
+@@ -51,12 +49,10 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ 		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		_ASM_EXTABLE(1b,3b)
+-		: : "r" (from) );
+-		
+-	
+-	for(; i>5; i--)
+-	{
++			_ASM_EXTABLE(1b, 3b)
++			: : "r" (from));
++
++	for ( ; i > 5; i--) {
+ 		__asm__ __volatile__ (
+ 		"1:  prefetch 320(%0)\n"
+ 		"2:  movq (%0), %%mm0\n"
+@@ -79,14 +75,14 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ 		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		_ASM_EXTABLE(1b,3b)
+-		: : "r" (from), "r" (to) : "memory");
+-		from+=64;
+-		to+=64;
++			_ASM_EXTABLE(1b, 3b)
++			: : "r" (from), "r" (to) : "memory");
++
++		from += 64;
++		to += 64;
+ 	}
+ 
+-	for(; i>0; i--)
+-	{
++	for ( ; i > 0; i--) {
+ 		__asm__ __volatile__ (
+ 		"  movq (%0), %%mm0\n"
+ 		"  movq 8(%0), %%mm1\n"
+@@ -104,17 +100,20 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ 		"  movq %%mm1, 40(%1)\n"
+ 		"  movq %%mm2, 48(%1)\n"
+ 		"  movq %%mm3, 56(%1)\n"
+-		: : "r" (from), "r" (to) : "memory");
+-		from+=64;
+-		to+=64;
++			: : "r" (from), "r" (to) : "memory");
++
++		from += 64;
++		to += 64;
+ 	}
+ 	/*
+-	 *	Now do the tail of the block
++	 * Now do the tail of the block:
+ 	 */
+-	__memcpy(to, from, len&63);
++	__memcpy(to, from, len & 63);
+ 	kernel_fpu_end();
++
+ 	return p;
+ }
++EXPORT_SYMBOL(_mmx_memcpy);
+ 
+ #ifdef CONFIG_MK7
+ 
+@@ -128,13 +127,12 @@ static void fast_clear_page(void *page)
+ 	int i;
+ 
+ 	kernel_fpu_begin();
+-	
++
+ 	__asm__ __volatile__ (
+ 		"  pxor %%mm0, %%mm0\n" : :
+ 	);
+ 
+-	for(i=0;i<4096/64;i++)
+-	{
++	for (i = 0; i < 4096/64; i++) {
+ 		__asm__ __volatile__ (
+ 		"  movntq %%mm0, (%0)\n"
+ 		"  movntq %%mm0, 8(%0)\n"
+@@ -145,14 +143,15 @@ static void fast_clear_page(void *page)
+ 		"  movntq %%mm0, 48(%0)\n"
+ 		"  movntq %%mm0, 56(%0)\n"
+ 		: : "r" (page) : "memory");
+-		page+=64;
++		page += 64;
+ 	}
+-	/* since movntq is weakly-ordered, a "sfence" is needed to become
+-	 * ordered again.
++
++	/*
++	 * Since movntq is weakly-ordered, a "sfence" is needed to become
++	 * ordered again:
+ 	 */
+-	__asm__ __volatile__ (
+-		"  sfence \n" : :
+-	);
++	__asm__ __volatile__("sfence\n"::);
++
+ 	kernel_fpu_end();
+ }
+ 
+@@ -162,10 +161,11 @@ static void fast_copy_page(void *to, void *from)
+ 
+ 	kernel_fpu_begin();
+ 
+-	/* maybe the prefetch stuff can go before the expensive fnsave...
++	/*
++	 * maybe the prefetch stuff can go before the expensive fnsave...
+ 	 * but that is for later. -AV
+ 	 */
+-	__asm__ __volatile__ (
++	__asm__ __volatile__(
+ 		"1: prefetch (%0)\n"
+ 		"   prefetch 64(%0)\n"
+ 		"   prefetch 128(%0)\n"
+@@ -176,11 +176,9 @@ static void fast_copy_page(void *to, void *from)
+ 		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		_ASM_EXTABLE(1b,3b)
+-		: : "r" (from) );
++			_ASM_EXTABLE(1b, 3b) : : "r" (from));
+ 
+-	for(i=0; i<(4096-320)/64; i++)
+-	{
++	for (i = 0; i < (4096-320)/64; i++) {
+ 		__asm__ __volatile__ (
+ 		"1: prefetch 320(%0)\n"
+ 		"2: movq (%0), %%mm0\n"
+@@ -203,13 +201,13 @@ static void fast_copy_page(void *to, void *from)
+ 		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		_ASM_EXTABLE(1b,3b)
+-		: : "r" (from), "r" (to) : "memory");
+-		from+=64;
+-		to+=64;
++		_ASM_EXTABLE(1b, 3b) : : "r" (from), "r" (to) : "memory");
++
++		from += 64;
++		to += 64;
+ 	}
+-	for(i=(4096-320)/64; i<4096/64; i++)
+-	{
++
++	for (i = (4096-320)/64; i < 4096/64; i++) {
+ 		__asm__ __volatile__ (
+ 		"2: movq (%0), %%mm0\n"
+ 		"   movntq %%mm0, (%1)\n"
+@@ -227,37 +225,34 @@ static void fast_copy_page(void *to, void *from)
+ 		"   movntq %%mm6, 48(%1)\n"
+ 		"   movq 56(%0), %%mm7\n"
+ 		"   movntq %%mm7, 56(%1)\n"
+-		: : "r" (from), "r" (to) : "memory");
+-		from+=64;
+-		to+=64;
++			: : "r" (from), "r" (to) : "memory");
++		from += 64;
++		to += 64;
+ 	}
+-	/* since movntq is weakly-ordered, a "sfence" is needed to become
+-	 * ordered again.
++	/*
++	 * Since movntq is weakly-ordered, a "sfence" is needed to become
++	 * ordered again:
+ 	 */
+-	__asm__ __volatile__ (
+-		"  sfence \n" : :
+-	);
++	__asm__ __volatile__("sfence \n"::);
+ 	kernel_fpu_end();
+ }
+ 
+-#else
++#else /* CONFIG_MK7 */
+ 
+ /*
+  *	Generic MMX implementation without K7 specific streaming
+  */
+- 
+ static void fast_clear_page(void *page)
+ {
+ 	int i;
+-	
++
+ 	kernel_fpu_begin();
+-	
++
+ 	__asm__ __volatile__ (
+ 		"  pxor %%mm0, %%mm0\n" : :
+ 	);
+ 
+-	for(i=0;i<4096/128;i++)
+-	{
++	for (i = 0; i < 4096/128; i++) {
+ 		__asm__ __volatile__ (
+ 		"  movq %%mm0, (%0)\n"
+ 		"  movq %%mm0, 8(%0)\n"
+@@ -275,8 +270,8 @@ static void fast_clear_page(void *page)
+ 		"  movq %%mm0, 104(%0)\n"
+ 		"  movq %%mm0, 112(%0)\n"
+ 		"  movq %%mm0, 120(%0)\n"
+-		: : "r" (page) : "memory");
+-		page+=128;
++			: : "r" (page) : "memory");
++		page += 128;
+ 	}
+ 
+ 	kernel_fpu_end();
+@@ -285,8 +280,7 @@ static void fast_clear_page(void *page)
+ static void fast_copy_page(void *to, void *from)
+ {
+ 	int i;
+-	
+-	
++
+ 	kernel_fpu_begin();
+ 
+ 	__asm__ __volatile__ (
+@@ -300,11 +294,9 @@ static void fast_copy_page(void *to, void *from)
+ 		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		_ASM_EXTABLE(1b,3b)
+-		: : "r" (from) );
++			_ASM_EXTABLE(1b, 3b) : : "r" (from));
+ 
+-	for(i=0; i<4096/64; i++)
+-	{
++	for (i = 0; i < 4096/64; i++) {
+ 		__asm__ __volatile__ (
+ 		"1: prefetch 320(%0)\n"
+ 		"2: movq (%0), %%mm0\n"
+@@ -327,60 +319,59 @@ static void fast_copy_page(void *to, void *from)
+ 		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		_ASM_EXTABLE(1b,3b)
+-		: : "r" (from), "r" (to) : "memory");
+-		from+=64;
+-		to+=64;
++			_ASM_EXTABLE(1b, 3b)
++			: : "r" (from), "r" (to) : "memory");
++
++		from += 64;
++		to += 64;
+ 	}
+ 	kernel_fpu_end();
+ }
+ 
+-
+-#endif
++#endif /* !CONFIG_MK7 */
+ 
+ /*
+- *	Favour MMX for page clear and copy. 
++ * Favour MMX for page clear and copy:
+  */
+-
+-static void slow_zero_page(void * page)
++static void slow_zero_page(void *page)
+ {
+ 	int d0, d1;
+-	__asm__ __volatile__( \
+-		"cld\n\t" \
+-		"rep ; stosl" \
+-		: "=&c" (d0), "=&D" (d1)
+-		:"a" (0),"1" (page),"0" (1024)
+-		:"memory");
++
++	__asm__ __volatile__(
++		"cld\n\t"
++		"rep ; stosl"
++
++			: "=&c" (d0), "=&D" (d1)
++			:"a" (0), "1" (page), "0" (1024)
++			:"memory");
+ }
+- 
+-void mmx_clear_page(void * page)
++
++void mmx_clear_page(void *page)
+ {
+-	if(unlikely(in_interrupt()))
++	if (unlikely(in_interrupt()))
+ 		slow_zero_page(page);
+ 	else
+ 		fast_clear_page(page);
+ }
++EXPORT_SYMBOL(mmx_clear_page);
+ 
+ static void slow_copy_page(void *to, void *from)
+ {
+ 	int d0, d1, d2;
+-	__asm__ __volatile__( \
+-		"cld\n\t" \
+-		"rep ; movsl" \
+-		: "=&c" (d0), "=&D" (d1), "=&S" (d2) \
+-		: "0" (1024),"1" ((long) to),"2" ((long) from) \
++
++	__asm__ __volatile__(
++		"cld\n\t"
++		"rep ; movsl"
++		: "=&c" (d0), "=&D" (d1), "=&S" (d2)
++		: "0" (1024), "1" ((long) to), "2" ((long) from)
+ 		: "memory");
+ }
+-  
+ 
+ void mmx_copy_page(void *to, void *from)
+ {
+-	if(unlikely(in_interrupt()))
++	if (unlikely(in_interrupt()))
+ 		slow_copy_page(to, from);
+ 	else
+ 		fast_copy_page(to, from);
+ }
+-
+-EXPORT_SYMBOL(_mmx_memcpy);
+-EXPORT_SYMBOL(mmx_clear_page);
+ EXPORT_SYMBOL(mmx_copy_page);
+diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S
+index 3899bd3..648fe47 100644
+--- a/arch/x86/lib/semaphore_32.S
++++ b/arch/x86/lib/semaphore_32.S
+@@ -30,89 +30,6 @@
+  * value or just clobbered..
+  */
+ 	.section .sched.text, "ax"
+-ENTRY(__down_failed)
+-	CFI_STARTPROC
+-	FRAME
+-	pushl %edx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET edx,0
+-	pushl %ecx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET ecx,0
+-	call __down
+-	popl %ecx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	CFI_RESTORE ecx
+-	popl %edx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	CFI_RESTORE edx
+-	ENDFRAME
+-	ret
+-	CFI_ENDPROC
+-	ENDPROC(__down_failed)
+-
+-ENTRY(__down_failed_interruptible)
+-	CFI_STARTPROC
+-	FRAME
+-	pushl %edx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET edx,0
+-	pushl %ecx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET ecx,0
+-	call __down_interruptible
+-	popl %ecx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	CFI_RESTORE ecx
+-	popl %edx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	CFI_RESTORE edx
+-	ENDFRAME
+-	ret
+-	CFI_ENDPROC
+-	ENDPROC(__down_failed_interruptible)
+-
+-ENTRY(__down_failed_trylock)
+-	CFI_STARTPROC
+-	FRAME
+-	pushl %edx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET edx,0
+-	pushl %ecx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET ecx,0
+-	call __down_trylock
+-	popl %ecx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	CFI_RESTORE ecx
+-	popl %edx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	CFI_RESTORE edx
+-	ENDFRAME
+-	ret
+-	CFI_ENDPROC
+-	ENDPROC(__down_failed_trylock)
+-
+-ENTRY(__up_wakeup)
+-	CFI_STARTPROC
+-	FRAME
+-	pushl %edx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET edx,0
+-	pushl %ecx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET ecx,0
+-	call __up
+-	popl %ecx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	CFI_RESTORE ecx
+-	popl %edx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	CFI_RESTORE edx
+-	ENDFRAME
+-	ret
+-	CFI_ENDPROC
+-	ENDPROC(__up_wakeup)
+ 
+ /*
+  * rw spinlock fallbacks
+diff --git a/arch/x86/lib/string_32.c b/arch/x86/lib/string_32.c
+index c2c0504..94972e7 100644
+--- a/arch/x86/lib/string_32.c
++++ b/arch/x86/lib/string_32.c
+@@ -14,25 +14,25 @@
+ #include <linux/module.h>
+ 
+ #ifdef __HAVE_ARCH_STRCPY
+-char *strcpy(char * dest,const char *src)
++char *strcpy(char *dest, const char *src)
+ {
+ 	int d0, d1, d2;
+-	asm volatile( "1:\tlodsb\n\t"
++	asm volatile("1:\tlodsb\n\t"
+ 		"stosb\n\t"
+ 		"testb %%al,%%al\n\t"
+ 		"jne 1b"
+ 		: "=&S" (d0), "=&D" (d1), "=&a" (d2)
+-		:"0" (src),"1" (dest) : "memory");
++		:"0" (src), "1" (dest) : "memory");
+ 	return dest;
+ }
+ EXPORT_SYMBOL(strcpy);
+ #endif
+ 
+ #ifdef __HAVE_ARCH_STRNCPY
+-char *strncpy(char * dest,const char *src,size_t count)
++char *strncpy(char *dest, const char *src, size_t count)
+ {
+ 	int d0, d1, d2, d3;
+-	asm volatile( "1:\tdecl %2\n\t"
++	asm volatile("1:\tdecl %2\n\t"
+ 		"js 2f\n\t"
+ 		"lodsb\n\t"
+ 		"stosb\n\t"
+@@ -42,17 +42,17 @@ char *strncpy(char * dest,const char *src,size_t count)
+ 		"stosb\n"
+ 		"2:"
+ 		: "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
+-		:"0" (src),"1" (dest),"2" (count) : "memory");
++		:"0" (src), "1" (dest), "2" (count) : "memory");
+ 	return dest;
+ }
+ EXPORT_SYMBOL(strncpy);
+ #endif
+ 
+ #ifdef __HAVE_ARCH_STRCAT
+-char *strcat(char * dest,const char * src)
++char *strcat(char *dest, const char *src)
+ {
+ 	int d0, d1, d2, d3;
+-	asm volatile( "repne\n\t"
++	asm volatile("repne\n\t"
+ 		"scasb\n\t"
+ 		"decl %1\n"
+ 		"1:\tlodsb\n\t"
+@@ -67,10 +67,10 @@ EXPORT_SYMBOL(strcat);
+ #endif
+ 
+ #ifdef __HAVE_ARCH_STRNCAT
+-char *strncat(char * dest,const char * src,size_t count)
++char *strncat(char *dest, const char *src, size_t count)
+ {
+ 	int d0, d1, d2, d3;
+-	asm volatile( "repne\n\t"
++	asm volatile("repne\n\t"
+ 		"scasb\n\t"
+ 		"decl %1\n\t"
+ 		"movl %8,%3\n"
+@@ -83,7 +83,7 @@ char *strncat(char * dest,const char * src,size_t count)
+ 		"2:\txorl %2,%2\n\t"
+ 		"stosb"
+ 		: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
+-		: "0" (src),"1" (dest),"2" (0),"3" (0xffffffffu), "g" (count)
++		: "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu), "g" (count)
+ 		: "memory");
+ 	return dest;
+ }
+@@ -91,11 +91,11 @@ EXPORT_SYMBOL(strncat);
+ #endif
+ 
+ #ifdef __HAVE_ARCH_STRCMP
+-int strcmp(const char * cs,const char * ct)
++int strcmp(const char *cs, const char *ct)
+ {
+ 	int d0, d1;
+ 	int res;
+-	asm volatile( "1:\tlodsb\n\t"
++	asm volatile("1:\tlodsb\n\t"
+ 		"scasb\n\t"
+ 		"jne 2f\n\t"
+ 		"testb %%al,%%al\n\t"
+@@ -106,7 +106,7 @@ int strcmp(const char * cs,const char * ct)
+ 		"orb $1,%%al\n"
+ 		"3:"
+ 		:"=a" (res), "=&S" (d0), "=&D" (d1)
+-		:"1" (cs),"2" (ct)
++		:"1" (cs), "2" (ct)
+ 		:"memory");
+ 	return res;
+ }
+@@ -114,11 +114,11 @@ EXPORT_SYMBOL(strcmp);
+ #endif
+ 
+ #ifdef __HAVE_ARCH_STRNCMP
+-int strncmp(const char * cs,const char * ct,size_t count)
++int strncmp(const char *cs, const char *ct, size_t count)
+ {
+ 	int res;
+ 	int d0, d1, d2;
+-	asm volatile( "1:\tdecl %3\n\t"
++	asm volatile("1:\tdecl %3\n\t"
+ 		"js 2f\n\t"
+ 		"lodsb\n\t"
+ 		"scasb\n\t"
+@@ -131,7 +131,7 @@ int strncmp(const char * cs,const char * ct,size_t count)
+ 		"orb $1,%%al\n"
+ 		"4:"
+ 		:"=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
+-		:"1" (cs),"2" (ct),"3" (count)
++		:"1" (cs), "2" (ct), "3" (count)
+ 		:"memory");
+ 	return res;
+ }
+@@ -139,11 +139,11 @@ EXPORT_SYMBOL(strncmp);
+ #endif
+ 
+ #ifdef __HAVE_ARCH_STRCHR
+-char *strchr(const char * s, int c)
++char *strchr(const char *s, int c)
+ {
+ 	int d0;
+-	char * res;
+-	asm volatile( "movb %%al,%%ah\n"
++	char *res;
++	asm volatile("movb %%al,%%ah\n"
+ 		"1:\tlodsb\n\t"
+ 		"cmpb %%ah,%%al\n\t"
+ 		"je 2f\n\t"
+@@ -153,7 +153,7 @@ char *strchr(const char * s, int c)
+ 		"2:\tmovl %1,%0\n\t"
+ 		"decl %0"
+ 		:"=a" (res), "=&S" (d0)
+-		:"1" (s),"0" (c)
++		:"1" (s), "0" (c)
+ 		:"memory");
+ 	return res;
+ }
+@@ -161,16 +161,16 @@ EXPORT_SYMBOL(strchr);
+ #endif
+ 
+ #ifdef __HAVE_ARCH_STRLEN
+-size_t strlen(const char * s)
++size_t strlen(const char *s)
+ {
+ 	int d0;
+ 	int res;
+-	asm volatile( "repne\n\t"
++	asm volatile("repne\n\t"
+ 		"scasb\n\t"
+ 		"notl %0\n\t"
+ 		"decl %0"
+ 		:"=c" (res), "=&D" (d0)
+-		:"1" (s),"a" (0), "0" (0xffffffffu)
++		:"1" (s), "a" (0), "0" (0xffffffffu)
+ 		:"memory");
+ 	return res;
+ }
+@@ -178,19 +178,19 @@ EXPORT_SYMBOL(strlen);
+ #endif
+ 
+ #ifdef __HAVE_ARCH_MEMCHR
+-void *memchr(const void *cs,int c,size_t count)
++void *memchr(const void *cs, int c, size_t count)
+ {
+ 	int d0;
+ 	void *res;
+ 	if (!count)
+ 		return NULL;
+-	asm volatile( "repne\n\t"
++	asm volatile("repne\n\t"
+ 		"scasb\n\t"
+ 		"je 1f\n\t"
+ 		"movl $1,%0\n"
+ 		"1:\tdecl %0"
+ 		:"=D" (res), "=&c" (d0)
+-		:"a" (c),"0" (cs),"1" (count)
++		:"a" (c), "0" (cs), "1" (count)
+ 		:"memory");
+ 	return res;
+ }
+@@ -198,7 +198,7 @@ EXPORT_SYMBOL(memchr);
+ #endif
+ 
+ #ifdef __HAVE_ARCH_MEMSCAN
+-void *memscan(void * addr, int c, size_t size)
++void *memscan(void *addr, int c, size_t size)
+ {
+ 	if (!size)
+ 		return addr;
+@@ -219,7 +219,7 @@ size_t strnlen(const char *s, size_t count)
+ {
+ 	int d0;
+ 	int res;
+-	asm volatile( "movl %2,%0\n\t"
++	asm volatile("movl %2,%0\n\t"
+ 		"jmp 2f\n"
+ 		"1:\tcmpb $0,(%0)\n\t"
+ 		"je 3f\n\t"
+@@ -229,7 +229,7 @@ size_t strnlen(const char *s, size_t count)
+ 		"jne 1b\n"
+ 		"3:\tsubl %2,%0"
+ 		:"=a" (res), "=&d" (d0)
+-		:"c" (s),"1" (count)
++		:"c" (s), "1" (count)
+ 		:"memory");
+ 	return res;
+ }
+diff --git a/arch/x86/lib/strstr_32.c b/arch/x86/lib/strstr_32.c
+index a3dafbf..42e8a50 100644
+--- a/arch/x86/lib/strstr_32.c
++++ b/arch/x86/lib/strstr_32.c
+@@ -1,9 +1,9 @@
+ #include <linux/string.h>
+ 
+-char * strstr(const char * cs,const char * ct)
++char *strstr(const char *cs, const char *ct)
+ {
+ int	d0, d1;
+-register char * __res;
++register char *__res;
+ __asm__ __volatile__(
+ 	"movl %6,%%edi\n\t"
+ 	"repne\n\t"
+diff --git a/arch/x86/lib/thunk_64.S b/arch/x86/lib/thunk_64.S
+index 8b92d42..e009251 100644
+--- a/arch/x86/lib/thunk_64.S
++++ b/arch/x86/lib/thunk_64.S
+@@ -41,11 +41,6 @@
+ 	thunk rwsem_downgrade_thunk,rwsem_downgrade_wake
+ #endif	
+ 	
+-	thunk __down_failed,__down
+-	thunk_retrax __down_failed_interruptible,__down_interruptible
+-	thunk_retrax __down_failed_trylock,__down_trylock
+-	thunk __up_wakeup,__up
+-
+ #ifdef CONFIG_TRACE_IRQFLAGS
+ 	thunk trace_hardirqs_on_thunk,trace_hardirqs_on
+ 	thunk trace_hardirqs_off_thunk,trace_hardirqs_off
+diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
+index e849b99..24e6094 100644
+--- a/arch/x86/lib/usercopy_32.c
++++ b/arch/x86/lib/usercopy_32.c
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * User address space access functions.
+  * The non inlined parts of asm-i386/uaccess.h are here.
+  *
+@@ -22,14 +22,14 @@ static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned lon
+ #endif
+ 	return 1;
+ }
+-#define movsl_is_ok(a1,a2,n) \
+-	__movsl_is_ok((unsigned long)(a1),(unsigned long)(a2),(n))
++#define movsl_is_ok(a1, a2, n) \
++	__movsl_is_ok((unsigned long)(a1), (unsigned long)(a2), (n))
+ 
+ /*
+  * Copy a null terminated string from userspace.
+  */
+ 
+-#define __do_strncpy_from_user(dst,src,count,res)			   \
++#define __do_strncpy_from_user(dst, src, count, res)			   \
+ do {									   \
+ 	int __d0, __d1, __d2;						   \
+ 	might_sleep();							   \
+@@ -61,7 +61,7 @@ do {									   \
+  *         least @count bytes long.
+  * @src:   Source address, in user space.
+  * @count: Maximum number of bytes to copy, including the trailing NUL.
+- * 
++ *
+  * Copies a NUL-terminated string from userspace to kernel space.
+  * Caller must check the specified block with access_ok() before calling
+  * this function.
+@@ -90,7 +90,7 @@ EXPORT_SYMBOL(__strncpy_from_user);
+  *         least @count bytes long.
+  * @src:   Source address, in user space.
+  * @count: Maximum number of bytes to copy, including the trailing NUL.
+- * 
++ *
+  * Copies a NUL-terminated string from userspace to kernel space.
+  *
+  * On success, returns the length of the string (not including the trailing
+@@ -120,7 +120,7 @@ EXPORT_SYMBOL(strncpy_from_user);
+ do {									\
+ 	int __d0;							\
+ 	might_sleep();							\
+-  	__asm__ __volatile__(						\
++	__asm__ __volatile__(						\
+ 		"0:	rep; stosl\n"					\
+ 		"	movl %2,%0\n"					\
+ 		"1:	rep; stosb\n"					\
+@@ -333,17 +333,17 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
+ 	__asm__ __volatile__(
+ 		       "        .align 2,0x90\n"
+ 		       "0:      movl 32(%4), %%eax\n"
+-		       "        cmpl $67, %0\n"      
+-		       "        jbe 2f\n"            
++		       "        cmpl $67, %0\n"
++		       "        jbe 2f\n"
+ 		       "1:      movl 64(%4), %%eax\n"
+-		       "        .align 2,0x90\n"     
+-		       "2:      movl 0(%4), %%eax\n" 
+-		       "21:     movl 4(%4), %%edx\n" 
+-		       "        movl %%eax, 0(%3)\n" 
+-		       "        movl %%edx, 4(%3)\n" 
+-		       "3:      movl 8(%4), %%eax\n" 
+-		       "31:     movl 12(%4),%%edx\n" 
+-		       "        movl %%eax, 8(%3)\n" 
++		       "        .align 2,0x90\n"
++		       "2:      movl 0(%4), %%eax\n"
++		       "21:     movl 4(%4), %%edx\n"
++		       "        movl %%eax, 0(%3)\n"
++		       "        movl %%edx, 4(%3)\n"
++		       "3:      movl 8(%4), %%eax\n"
++		       "31:     movl 12(%4),%%edx\n"
++		       "        movl %%eax, 8(%3)\n"
+ 		       "        movl %%edx, 12(%3)\n"
+ 		       "4:      movl 16(%4), %%eax\n"
+ 		       "41:     movl 20(%4), %%edx\n"
+@@ -369,38 +369,38 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
+ 		       "91:     movl 60(%4), %%edx\n"
+ 		       "        movl %%eax, 56(%3)\n"
+ 		       "        movl %%edx, 60(%3)\n"
+-		       "        addl $-64, %0\n"     
+-		       "        addl $64, %4\n"      
+-		       "        addl $64, %3\n"      
+-		       "        cmpl $63, %0\n"      
+-		       "        ja  0b\n"            
+-		       "5:      movl  %0, %%eax\n"   
+-		       "        shrl  $2, %0\n"      
+-		       "        andl $3, %%eax\n"    
+-		       "        cld\n"               
+-		       "6:      rep; movsl\n"   
++		       "        addl $-64, %0\n"
++		       "        addl $64, %4\n"
++		       "        addl $64, %3\n"
++		       "        cmpl $63, %0\n"
++		       "        ja  0b\n"
++		       "5:      movl  %0, %%eax\n"
++		       "        shrl  $2, %0\n"
++		       "        andl $3, %%eax\n"
++		       "        cld\n"
++		       "6:      rep; movsl\n"
+ 		       "        movl %%eax,%0\n"
+-		       "7:      rep; movsb\n"	
+-		       "8:\n"			
++		       "7:      rep; movsb\n"
++		       "8:\n"
+ 		       ".section .fixup,\"ax\"\n"
+-		       "9:      lea 0(%%eax,%0,4),%0\n"	
+-		       "16:     pushl %0\n"	
+-		       "        pushl %%eax\n"	
++		       "9:      lea 0(%%eax,%0,4),%0\n"
++		       "16:     pushl %0\n"
++		       "        pushl %%eax\n"
+ 		       "        xorl %%eax,%%eax\n"
+-		       "        rep; stosb\n"	
+-		       "        popl %%eax\n"	
+-		       "        popl %0\n"	
+-		       "        jmp 8b\n"	
+-		       ".previous\n"		
++		       "        rep; stosb\n"
++		       "        popl %%eax\n"
++		       "        popl %0\n"
++		       "        jmp 8b\n"
++		       ".previous\n"
+ 		       ".section __ex_table,\"a\"\n"
+-		       "	.align 4\n"	   
+-		       "	.long 0b,16b\n"	 
++		       "	.align 4\n"
++		       "	.long 0b,16b\n"
+ 		       "	.long 1b,16b\n"
+ 		       "	.long 2b,16b\n"
+ 		       "	.long 21b,16b\n"
+-		       "	.long 3b,16b\n"	
++		       "	.long 3b,16b\n"
+ 		       "	.long 31b,16b\n"
+-		       "	.long 4b,16b\n"	
++		       "	.long 4b,16b\n"
+ 		       "	.long 41b,16b\n"
+ 		       "	.long 10b,16b\n"
+ 		       "	.long 51b,16b\n"
+@@ -412,9 +412,9 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
+ 		       "	.long 81b,16b\n"
+ 		       "	.long 14b,16b\n"
+ 		       "	.long 91b,16b\n"
+-		       "	.long 6b,9b\n"	
+-		       "        .long 7b,16b\n" 
+-		       ".previous"		
++		       "	.long 6b,9b\n"
++		       "        .long 7b,16b\n"
++		       ".previous"
+ 		       : "=&c"(size), "=&D" (d0), "=&S" (d1)
+ 		       :  "1"(to), "2"(from), "0"(size)
+ 		       : "eax", "edx", "memory");
+@@ -429,7 +429,7 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
+ static unsigned long __copy_user_zeroing_intel_nocache(void *to,
+ 				const void __user *from, unsigned long size)
+ {
+-        int d0, d1;
++	int d0, d1;
+ 
+ 	__asm__ __volatile__(
+ 	       "        .align 2,0x90\n"
+@@ -526,7 +526,7 @@ static unsigned long __copy_user_zeroing_intel_nocache(void *to,
+ static unsigned long __copy_user_intel_nocache(void *to,
+ 				const void __user *from, unsigned long size)
+ {
+-        int d0, d1;
++	int d0, d1;
+ 
+ 	__asm__ __volatile__(
+ 	       "        .align 2,0x90\n"
+@@ -629,7 +629,7 @@ unsigned long __copy_user_zeroing_intel_nocache(void *to,
+ #endif /* CONFIG_X86_INTEL_USERCOPY */
+ 
+ /* Generic arbitrary sized copy.  */
+-#define __copy_user(to,from,size)					\
++#define __copy_user(to, from, size)					\
+ do {									\
+ 	int __d0, __d1, __d2;						\
+ 	__asm__ __volatile__(						\
+@@ -665,7 +665,7 @@ do {									\
+ 		: "memory");						\
+ } while (0)
+ 
+-#define __copy_user_zeroing(to,from,size)				\
++#define __copy_user_zeroing(to, from, size)				\
+ do {									\
+ 	int __d0, __d1, __d2;						\
+ 	__asm__ __volatile__(						\
+@@ -712,7 +712,7 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from,
+ {
+ #ifndef CONFIG_X86_WP_WORKS_OK
+ 	if (unlikely(boot_cpu_data.wp_works_ok == 0) &&
+-			((unsigned long )to) < TASK_SIZE) {
++			((unsigned long)to) < TASK_SIZE) {
+ 		/*
+ 		 * When we are in an atomic section (see
+ 		 * mm/filemap.c:file_read_actor), return the full
+@@ -721,26 +721,26 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from,
+ 		if (in_atomic())
+ 			return n;
+ 
+-		/* 
++		/*
+ 		 * CPU does not honor the WP bit when writing
+ 		 * from supervisory mode, and due to preemption or SMP,
+ 		 * the page tables can change at any time.
+ 		 * Do it manually.	Manfred <manfred at colorfullife.com>
+ 		 */
+ 		while (n) {
+-		      	unsigned long offset = ((unsigned long)to)%PAGE_SIZE;
++			unsigned long offset = ((unsigned long)to)%PAGE_SIZE;
+ 			unsigned long len = PAGE_SIZE - offset;
+ 			int retval;
+ 			struct page *pg;
+ 			void *maddr;
+-			
++
+ 			if (len > n)
+ 				len = n;
+ 
+ survive:
+ 			down_read(&current->mm->mmap_sem);
+ 			retval = get_user_pages(current, current->mm,
+-					(unsigned long )to, 1, 1, 0, &pg, NULL);
++					(unsigned long)to, 1, 1, 0, &pg, NULL);
+ 
+ 			if (retval == -ENOMEM && is_global_init(current)) {
+ 				up_read(&current->mm->mmap_sem);
+@@ -750,8 +750,8 @@ survive:
+ 
+ 			if (retval != 1) {
+ 				up_read(&current->mm->mmap_sem);
+-		       		break;
+-		       	}
++				break;
++			}
+ 
+ 			maddr = kmap_atomic(pg, KM_USER0);
+ 			memcpy(maddr + offset, from, len);
+@@ -802,12 +802,12 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
+ 					unsigned long n)
+ {
+ #ifdef CONFIG_X86_INTEL_USERCOPY
+-	if ( n > 64 && cpu_has_xmm2)
+-                n = __copy_user_zeroing_intel_nocache(to, from, n);
++	if (n > 64 && cpu_has_xmm2)
++		n = __copy_user_zeroing_intel_nocache(to, from, n);
+ 	else
+ 		__copy_user_zeroing(to, from, n);
+ #else
+-        __copy_user_zeroing(to, from, n);
++	__copy_user_zeroing(to, from, n);
+ #endif
+ 	return n;
+ }
+@@ -817,12 +817,12 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
+ 					unsigned long n)
+ {
+ #ifdef CONFIG_X86_INTEL_USERCOPY
+-	if ( n > 64 && cpu_has_xmm2)
+-                n = __copy_user_intel_nocache(to, from, n);
++	if (n > 64 && cpu_has_xmm2)
++		n = __copy_user_intel_nocache(to, from, n);
+ 	else
+ 		__copy_user(to, from, n);
+ #else
+-        __copy_user(to, from, n);
++	__copy_user(to, from, n);
+ #endif
+ 	return n;
+ }
+diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c
+index 292a225..95fc463 100644
+--- a/arch/x86/mach-generic/bigsmp.c
++++ b/arch/x86/mach-generic/bigsmp.c
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs.
+  * Drives the local APIC in "clustered mode".
+  */
+@@ -32,26 +32,26 @@ static int hp_ht_bigsmp(const struct dmi_system_id *d)
+ 
+ 
+ static const struct dmi_system_id bigsmp_dmi_table[] = {
+-	{ hp_ht_bigsmp, "HP ProLiant DL760 G2", {
+-		DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+-		DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
+-	}},
+-
+-	{ hp_ht_bigsmp, "HP ProLiant DL740", {
+-		DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+-		DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
+-	 }},
++	{ hp_ht_bigsmp, "HP ProLiant DL760 G2",
++	{ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
++	DMI_MATCH(DMI_BIOS_VERSION, "P44-"),}
++	},
++
++	{ hp_ht_bigsmp, "HP ProLiant DL740",
++	{ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
++	DMI_MATCH(DMI_BIOS_VERSION, "P47-"),}
++	},
+ 	 { }
+ };
+ 
+ 
+ static int probe_bigsmp(void)
+-{ 
++{
+ 	if (def_to_bigsmp)
+-        	dmi_bigsmp = 1;
++	dmi_bigsmp = 1;
+ 	else
+ 		dmi_check_system(bigsmp_dmi_table);
+-	return dmi_bigsmp; 
+-} 
++	return dmi_bigsmp;
++}
+ 
+-struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp); 
++struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp);
+diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c
+index 1af0cc7..9e835a1 100644
+--- a/arch/x86/mach-generic/default.c
++++ b/arch/x86/mach-generic/default.c
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * Default generic APIC driver. This handles up to 8 CPUs.
+  */
+ #define APIC_DEFINITION 1
+@@ -19,8 +19,8 @@
+ 
+ /* should be called last. */
+ static int probe_default(void)
+-{ 
++{
+ 	return 1;
+-} 
++}
+ 
+-struct genapic apic_default = APIC_INIT("default", probe_default); 
++struct genapic apic_default = APIC_INIT("default", probe_default);
+diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c
+index f410d3c..c5ae751 100644
+--- a/arch/x86/mach-generic/probe.c
++++ b/arch/x86/mach-generic/probe.c
+@@ -1,8 +1,9 @@
+-/* Copyright 2003 Andi Kleen, SuSE Labs. 
+- * Subject to the GNU Public License, v.2 
+- * 
++/*
++ * Copyright 2003 Andi Kleen, SuSE Labs.
++ * Subject to the GNU Public License, v.2
++ *
+  * Generic x86 APIC driver probe layer.
+- */  
++ */
+ #include <linux/threads.h>
+ #include <linux/cpumask.h>
+ #include <linux/string.h>
+@@ -24,7 +25,7 @@ struct genapic *genapic = &apic_default;
+ 
+ static struct genapic *apic_probe[] __initdata = {
+ 	&apic_summit,
+-	&apic_bigsmp, 
++	&apic_bigsmp,
+ 	&apic_es7000,
+ 	&apic_default,	/* must be last */
+ 	NULL,
+@@ -69,7 +70,7 @@ void __init generic_bigsmp_probe(void)
+ }
+ 
+ void __init generic_apic_probe(void)
+-{ 
++{
+ 	if (!cmdline_apic) {
+ 		int i;
+ 		for (i = 0; apic_probe[i]; i++) {
+@@ -83,40 +84,40 @@ void __init generic_apic_probe(void)
+ 			panic("Didn't find an APIC driver");
+ 	}
+ 	printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
+-} 
++}
+ 
+ /* These functions can switch the APIC even after the initial ->probe() */
+ 
+ int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid)
+-{ 
++{
+ 	int i;
+-	for (i = 0; apic_probe[i]; ++i) { 
+-		if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) { 
++	for (i = 0; apic_probe[i]; ++i) {
++		if (apic_probe[i]->mps_oem_check(mpc, oem, productid)) {
+ 			if (!cmdline_apic) {
+ 				genapic = apic_probe[i];
+ 				printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+ 				       genapic->name);
+ 			}
+ 			return 1;
+-		} 
+-	} 
++		}
++	}
+ 	return 0;
+-} 
++}
+ 
+ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+ {
+ 	int i;
+-	for (i = 0; apic_probe[i]; ++i) { 
+-		if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { 
++	for (i = 0; apic_probe[i]; ++i) {
++		if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
+ 			if (!cmdline_apic) {
+ 				genapic = apic_probe[i];
+ 				printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+ 				       genapic->name);
+ 			}
+ 			return 1;
+-		} 
+-	} 
+-	return 0;	
++		}
++	}
++	return 0;
+ }
+ 
+ int hard_smp_processor_id(void)
+diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c
+index 74883cc..a97ea0f 100644
+--- a/arch/x86/mach-generic/summit.c
++++ b/arch/x86/mach-generic/summit.c
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * APIC driver for the IBM "Summit" chipset.
+  */
+ #define APIC_DEFINITION 1
+@@ -19,9 +19,9 @@
+ #include <asm/mach-summit/mach_mpparse.h>
+ 
+ static int probe_summit(void)
+-{ 
++{
+ 	/* probed later in mptable/ACPI hooks */
+ 	return 0;
+-} 
++}
+ 
+-struct genapic apic_summit = APIC_INIT("summit", probe_summit); 
++struct genapic apic_summit = APIC_INIT("summit", probe_summit);
+diff --git a/arch/x86/mach-rdc321x/Makefile b/arch/x86/mach-rdc321x/Makefile
+index 1faac81..8325b4c 100644
+--- a/arch/x86/mach-rdc321x/Makefile
++++ b/arch/x86/mach-rdc321x/Makefile
+@@ -1,5 +1,5 @@
+ #
+ # Makefile for the RDC321x specific parts of the kernel
+ #
+-obj-$(CONFIG_X86_RDC321X)        := gpio.o platform.o wdt.o
++obj-$(CONFIG_X86_RDC321X)        := gpio.o platform.o
+ 
+diff --git a/arch/x86/mach-rdc321x/wdt.c b/arch/x86/mach-rdc321x/wdt.c
+deleted file mode 100644
+index ec5625a..0000000
+--- a/arch/x86/mach-rdc321x/wdt.c
++++ /dev/null
+@@ -1,275 +0,0 @@
+-/*
+- * RDC321x watchdog driver
+- *
+- * Copyright (C) 2007 Florian Fainelli <florian at openwrt.org>
+- *
+- * This driver is highly inspired from the cpu5_wdt driver
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/types.h>
+-#include <linux/errno.h>
+-#include <linux/miscdevice.h>
+-#include <linux/fs.h>
+-#include <linux/init.h>
+-#include <linux/ioport.h>
+-#include <linux/timer.h>
+-#include <linux/completion.h>
+-#include <linux/jiffies.h>
+-#include <linux/platform_device.h>
+-#include <linux/watchdog.h>
+-#include <linux/io.h>
+-#include <linux/uaccess.h>
+-
+-#include <asm/mach-rdc321x/rdc321x_defs.h>
+-
+-#define RDC_WDT_MASK	0x80000000 /* Mask */
+-#define RDC_WDT_EN	0x00800000 /* Enable bit */
+-#define RDC_WDT_WTI	0x00200000 /* Generate CPU reset/NMI/WDT on timeout */
+-#define RDC_WDT_RST	0x00100000 /* Reset bit */
+-#define RDC_WDT_WIF	0x00040000 /* WDT IRQ Flag */
+-#define RDC_WDT_IRT	0x00000100 /* IRQ Routing table */
+-#define RDC_WDT_CNT	0x00000001 /* WDT count */
+-
+-#define RDC_CLS_TMR	0x80003844 /* Clear timer */
+-
+-#define RDC_WDT_INTERVAL	(HZ/10+1)
+-
+-int nowayout = WATCHDOG_NOWAYOUT;
+-module_param(nowayout, int, 0);
+-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+-
+-static int ticks = 1000;
+-
+-/* some device data */
+-
+-static struct {
+-	struct completion stop;
+-	volatile int running;
+-	struct timer_list timer;
+-	volatile int queue;
+-	int default_ticks;
+-	unsigned long inuse;
+-} rdc321x_wdt_device;
+-
+-/* generic helper functions */
+-
+-static void rdc321x_wdt_trigger(unsigned long unused)
+-{
+-	if (rdc321x_wdt_device.running)
+-		ticks--;
+-
+-	/* keep watchdog alive */
+-	outl(RDC_WDT_EN|inl(RDC3210_CFGREG_DATA), RDC3210_CFGREG_DATA);
+-
+-	/* requeue?? */
+-	if (rdc321x_wdt_device.queue && ticks)
+-		mod_timer(&rdc321x_wdt_device.timer,
+-				jiffies + RDC_WDT_INTERVAL);
+-	else {
+-		/* ticks doesn't matter anyway */
+-		complete(&rdc321x_wdt_device.stop);
+-	}
+-
+-}
+-
+-static void rdc321x_wdt_reset(void)
+-{
+-	ticks = rdc321x_wdt_device.default_ticks;
+-}
+-
+-static void rdc321x_wdt_start(void)
+-{
+-	if (!rdc321x_wdt_device.queue) {
+-		rdc321x_wdt_device.queue = 1;
+-
+-		/* Clear the timer */
+-		outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR);
+-
+-		/* Enable watchdog and set the timeout to 81.92 us */
+-		outl(RDC_WDT_EN|RDC_WDT_CNT, RDC3210_CFGREG_DATA);
+-
+-		mod_timer(&rdc321x_wdt_device.timer,
+-				jiffies + RDC_WDT_INTERVAL);
+-	}
+-
+-	/* if process dies, counter is not decremented */
+-	rdc321x_wdt_device.running++;
+-}
+-
+-static int rdc321x_wdt_stop(void)
+-{
+-	if (rdc321x_wdt_device.running)
+-		rdc321x_wdt_device.running = 0;
+-
+-	ticks = rdc321x_wdt_device.default_ticks;
+-
+-	return -EIO;
+-}
+-
+-/* filesystem operations */
+-
+-static int rdc321x_wdt_open(struct inode *inode, struct file *file)
+-{
+-	if (test_and_set_bit(0, &rdc321x_wdt_device.inuse))
+-		return -EBUSY;
+-
+-	return nonseekable_open(inode, file);
+-}
+-
+-static int rdc321x_wdt_release(struct inode *inode, struct file *file)
+-{
+-	clear_bit(0, &rdc321x_wdt_device.inuse);
+-	return 0;
+-}
+-
+-static int rdc321x_wdt_ioctl(struct inode *inode, struct file *file,
+-				unsigned int cmd, unsigned long arg)
+-{
+-	void __user *argp = (void __user *)arg;
+-	unsigned int value;
+-	static struct watchdog_info ident = {
+-		.options = WDIOF_CARDRESET,
+-		.identity = "RDC321x WDT",
+-	};
+-
+-	switch (cmd) {
+-	case WDIOC_KEEPALIVE:
+-		rdc321x_wdt_reset();
+-		break;
+-	case WDIOC_GETSTATUS:
+-		/* Read the value from the DATA register */
+-		value = inl(RDC3210_CFGREG_DATA);
+-		if (copy_to_user(argp, &value, sizeof(int)))
+-			return -EFAULT;
+-		break;
+-	case WDIOC_GETSUPPORT:
+-		if (copy_to_user(argp, &ident, sizeof(ident)))
+-			return -EFAULT;
+-		break;
+-	case WDIOC_SETOPTIONS:
+-		if (copy_from_user(&value, argp, sizeof(int)))
+-			return -EFAULT;
+-		switch (value) {
+-		case WDIOS_ENABLECARD:
+-			rdc321x_wdt_start();
+-			break;
+-		case WDIOS_DISABLECARD:
+-			return rdc321x_wdt_stop();
+-		default:
+-			return -EINVAL;
+-		}
+-		break;
+-	default:
+-		return -ENOTTY;
+-	}
+-	return 0;
+-}
+-
+-static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf,
+-				size_t count, loff_t *ppos)
+-{
+-	if (!count)
+-		return -EIO;
+-
+-	rdc321x_wdt_reset();
+-
+-	return count;
+-}
+-
+-static const struct file_operations rdc321x_wdt_fops = {
+-	.owner		= THIS_MODULE,
+-	.llseek		= no_llseek,
+-	.ioctl		= rdc321x_wdt_ioctl,
+-	.open		= rdc321x_wdt_open,
+-	.write		= rdc321x_wdt_write,
+-	.release	= rdc321x_wdt_release,
+-};
+-
+-static struct miscdevice rdc321x_wdt_misc = {
+-	.minor	= WATCHDOG_MINOR,
+-	.name	= "watchdog",
+-	.fops	= &rdc321x_wdt_fops,
+-};
+-
+-static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
+-{
+-	int err;
+-
+-	err = misc_register(&rdc321x_wdt_misc);
+-	if (err < 0) {
+-		printk(KERN_ERR PFX "watchdog misc_register failed\n");
+-		return err;
+-	}
+-
+-	/* Reset the watchdog */
+-	outl(RDC_WDT_RST, RDC3210_CFGREG_DATA);
+-
+-	init_completion(&rdc321x_wdt_device.stop);
+-	rdc321x_wdt_device.queue = 0;
+-
+-	clear_bit(0, &rdc321x_wdt_device.inuse);
+-
+-	setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0);
+-
+-	rdc321x_wdt_device.default_ticks = ticks;
+-
+-	printk(KERN_INFO PFX "watchdog init success\n");
+-
+-	return 0;
+-}
+-
+-static int rdc321x_wdt_remove(struct platform_device *pdev)
+-{
+-	if (rdc321x_wdt_device.queue) {
+-		rdc321x_wdt_device.queue = 0;
+-		wait_for_completion(&rdc321x_wdt_device.stop);
+-	}
+-
+-	misc_deregister(&rdc321x_wdt_misc);
+-
+-	return 0;
+-}
+-
+-static struct platform_driver rdc321x_wdt_driver = {
+-	.probe = rdc321x_wdt_probe,
+-	.remove = rdc321x_wdt_remove,
+-	.driver = {
+-		.owner = THIS_MODULE,
+-		.name = "rdc321x-wdt",
+-	},
+-};
+-
+-static int __init rdc321x_wdt_init(void)
+-{
+-	return platform_driver_register(&rdc321x_wdt_driver);
+-}
+-
+-static void __exit rdc321x_wdt_exit(void)
+-{
+-	platform_driver_unregister(&rdc321x_wdt_driver);
+-}
+-
+-module_init(rdc321x_wdt_init);
+-module_exit(rdc321x_wdt_exit);
+-
+-MODULE_AUTHOR("Florian Fainelli <florian at openwrt.org>");
+-MODULE_DESCRIPTION("RDC321x watchdog driver");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+diff --git a/arch/x86/mach-visws/mpparse.c b/arch/x86/mach-visws/mpparse.c
+index 2a8456a..57484e9 100644
+--- a/arch/x86/mach-visws/mpparse.c
++++ b/arch/x86/mach-visws/mpparse.c
+@@ -11,22 +11,9 @@
+ /* Have we found an MP table */
+ int smp_found_config;
+ 
+-/*
+- * Various Linux-internal data structures created from the
+- * MP-table.
+- */
+-int apic_version [MAX_APICS];
+-
+ int pic_mode;
+-unsigned long mp_lapic_addr;
+-
+-/* Processor that is doing the boot up */
+-unsigned int boot_cpu_physical_apicid = -1U;
+-
+-/* Bitmask of physically existing CPUs */
+-physid_mask_t phys_cpu_present_map;
+ 
+-unsigned int __initdata maxcpus = NR_CPUS;
++extern unsigned int __cpuinitdata maxcpus;
+ 
+ /*
+  * The Visual Workstation is Intel MP compliant in the hardware
+diff --git a/arch/x86/mach-visws/visws_apic.c b/arch/x86/mach-visws/visws_apic.c
+index 710faf7..cef9cb1 100644
+--- a/arch/x86/mach-visws/visws_apic.c
++++ b/arch/x86/mach-visws/visws_apic.c
+@@ -1,6 +1,4 @@
+ /*
+- *	linux/arch/i386/mach-visws/visws_apic.c
+- *
+  *	Copyright (C) 1999 Bent Hagemark, Ingo Molnar
+  *
+  *  SGI Visual Workstation interrupt controller
+diff --git a/arch/x86/mach-voyager/voyager_basic.c b/arch/x86/mach-voyager/voyager_basic.c
+index 6a949e4..46d6f80 100644
+--- a/arch/x86/mach-voyager/voyager_basic.c
++++ b/arch/x86/mach-voyager/voyager_basic.c
+@@ -2,8 +2,6 @@
+  *
+  * Author: J.E.J.Bottomley at HansenPartnership.com
+  *
+- * linux/arch/i386/kernel/voyager.c
+- *
+  * This file contains all the voyager specific routines for getting
+  * initialisation of the architecture to function.  For additional
+  * features see:
+diff --git a/arch/x86/mach-voyager/voyager_cat.c b/arch/x86/mach-voyager/voyager_cat.c
+index 17a7904..ecab9ff 100644
+--- a/arch/x86/mach-voyager/voyager_cat.c
++++ b/arch/x86/mach-voyager/voyager_cat.c
+@@ -4,8 +4,6 @@
+  *
+  * Author: J.E.J.Bottomley at HansenPartnership.com
+  *
+- * linux/arch/i386/kernel/voyager_cat.c
+- *
+  * This file contains all the logic for manipulating the CAT bus
+  * in a level 5 machine.
+  *
+diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c
+index 3cc8eb2..8acbf0c 100644
+--- a/arch/x86/mach-voyager/voyager_smp.c
++++ b/arch/x86/mach-voyager/voyager_smp.c
+@@ -4,8 +4,6 @@
+  *
+  * Author: J.E.J.Bottomley at HansenPartnership.com
+  *
+- * linux/arch/i386/kernel/voyager_smp.c
+- *
+  * This file provides all the same external entries as smp.c but uses
+  * the voyager hal to provide the functionality
+  */
+@@ -27,6 +25,7 @@
+ #include <asm/pgalloc.h>
+ #include <asm/tlbflush.h>
+ #include <asm/arch_hooks.h>
++#include <asm/trampoline.h>
+ 
+ /* TLB state -- visible externally, indexed physically */
+ DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = { &init_mm, 0 };
+@@ -114,7 +113,7 @@ static inline void send_QIC_CPI(__u32 cpuset, __u8 cpi)
+ 	for_each_online_cpu(cpu) {
+ 		if (cpuset & (1 << cpu)) {
+ #ifdef VOYAGER_DEBUG
+-			if (!cpu_isset(cpu, cpu_online_map))
++			if (!cpu_online(cpu))
+ 				VDEBUG(("CPU%d sending cpi %d to CPU%d not in "
+ 					"cpu_online_map\n",
+ 					hard_smp_processor_id(), cpi, cpu));
+@@ -207,11 +206,6 @@ static struct irq_chip vic_chip = {
+ /* used to count up as CPUs are brought on line (starts at 0) */
+ static int cpucount = 0;
+ 
+-/* steal a page from the bottom of memory for the trampoline and
+- * squirrel its address away here.  This will be in kernel virtual
+- * space */
+-static __u32 trampoline_base;
+-
+ /* The per cpu profile stuff - used in smp_local_timer_interrupt */
+ static DEFINE_PER_CPU(int, prof_multiplier) = 1;
+ static DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
+@@ -428,18 +422,6 @@ void __init smp_store_cpu_info(int id)
+ 	identify_secondary_cpu(c);
+ }
+ 
+-/* set up the trampoline and return the physical address of the code */
+-static __u32 __init setup_trampoline(void)
+-{
+-	/* these two are global symbols in trampoline.S */
+-	extern const __u8 trampoline_end[];
+-	extern const __u8 trampoline_data[];
+-
+-	memcpy((__u8 *) trampoline_base, trampoline_data,
+-	       trampoline_end - trampoline_data);
+-	return virt_to_phys((__u8 *) trampoline_base);
+-}
+-
+ /* Routine initially called when a non-boot CPU is brought online */
+ static void __init start_secondary(void *unused)
+ {
+@@ -520,13 +502,6 @@ static void __init do_boot_cpu(__u8 cpu)
+ 	    & ~(voyager_extended_vic_processors
+ 		& voyager_allowed_boot_processors);
+ 
+-	/* This is an area in head.S which was used to set up the
+-	 * initial kernel stack.  We need to alter this to give the
+-	 * booting CPU a new stack (taken from its idle process) */
+-	extern struct {
+-		__u8 *sp;
+-		unsigned short ss;
+-	} stack_start;
+ 	/* This is the format of the CPI IDT gate (in real mode) which
+ 	 * we're hijacking to boot the CPU */
+ 	union IDTFormat {
+@@ -568,8 +543,8 @@ static void __init do_boot_cpu(__u8 cpu)
+ 		hijack_source.idt.Offset, stack_start.sp));
+ 
+ 	/* init lowmem identity mapping */
+-	clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+-			min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
++	clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++			min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
+ 	flush_tlb_all();
+ 
+ 	if (quad_boot) {
+@@ -708,9 +683,9 @@ void __init smp_boot_cpus(void)
+ 	 * Code added from smpboot.c */
+ 	{
+ 		unsigned long bogosum = 0;
+-		for (i = 0; i < NR_CPUS; i++)
+-			if (cpu_isset(i, cpu_online_map))
+-				bogosum += cpu_data(i).loops_per_jiffy;
++
++		for_each_online_cpu(i)
++			bogosum += cpu_data(i).loops_per_jiffy;
+ 		printk(KERN_INFO "Total of %d processors activated "
+ 		       "(%lu.%02lu BogoMIPS).\n",
+ 		       cpucount + 1, bogosum / (500000 / HZ),
+@@ -1166,7 +1141,7 @@ void flush_tlb_all(void)
+  * is sorted out */
+ void __init smp_alloc_memory(void)
+ {
+-	trampoline_base = (__u32) alloc_bootmem_low_pages(PAGE_SIZE);
++	trampoline_base = alloc_bootmem_low_pages(PAGE_SIZE);
+ 	if (__pa(trampoline_base) >= 0x93000)
+ 		BUG();
+ }
+@@ -1863,7 +1838,7 @@ static int __cpuinit voyager_cpu_up(unsigned int cpu)
+ 		return -EIO;
+ 	/* Unleash the CPU! */
+ 	cpu_set(cpu, smp_commenced_mask);
+-	while (!cpu_isset(cpu, cpu_online_map))
++	while (!cpu_online(cpu))
+ 		mb();
+ 	return 0;
+ }
+diff --git a/arch/x86/mach-voyager/voyager_thread.c b/arch/x86/mach-voyager/voyager_thread.c
+index c69c931..15464a2 100644
+--- a/arch/x86/mach-voyager/voyager_thread.c
++++ b/arch/x86/mach-voyager/voyager_thread.c
+@@ -4,8 +4,6 @@
+  *
+  * Author: J.E.J.Bottomley at HansenPartnership.com
+  *
+- * linux/arch/i386/kernel/voyager_thread.c
+- *
+  * This module provides the machine status monitor thread for the
+  * voyager architecture.  This allows us to monitor the machine
+  * environment (temp, voltage, fan function) and the front panel and
+diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c
+index 760baee..6e38d87 100644
+--- a/arch/x86/math-emu/fpu_entry.c
++++ b/arch/x86/math-emu/fpu_entry.c
+@@ -276,6 +276,7 @@ asmlinkage void math_emulate(long arg)
+ 	entry_sel_off.offset = FPU_ORIG_EIP;
+ 	entry_sel_off.selector = FPU_CS;
+ 	entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
++	entry_sel_off.empty = 0;
+ 
+ 	FPU_rm = FPU_modrm & 7;
+ 
+@@ -677,7 +678,7 @@ int fpregs_soft_set(struct task_struct *target,
+ 		    unsigned int pos, unsigned int count,
+ 		    const void *kbuf, const void __user *ubuf)
+ {
+-	struct i387_soft_struct *s387 = &target->thread.i387.soft;
++	struct i387_soft_struct *s387 = &target->thread.xstate->soft;
+ 	void *space = s387->st_space;
+ 	int ret;
+ 	int offset, other, i, tags, regnr, tag, newtop;
+@@ -729,7 +730,7 @@ int fpregs_soft_get(struct task_struct *target,
+ 		    unsigned int pos, unsigned int count,
+ 		    void *kbuf, void __user *ubuf)
+ {
+-	struct i387_soft_struct *s387 = &target->thread.i387.soft;
++	struct i387_soft_struct *s387 = &target->thread.xstate->soft;
+ 	const void *space = s387->st_space;
+ 	int ret;
+ 	int offset = (S387->ftop & 7) * 10, other = 80 - offset;
+diff --git a/arch/x86/math-emu/fpu_system.h b/arch/x86/math-emu/fpu_system.h
+index a3ae28c..13488fa 100644
+--- a/arch/x86/math-emu/fpu_system.h
++++ b/arch/x86/math-emu/fpu_system.h
+@@ -35,8 +35,8 @@
+ #define SEG_EXPAND_DOWN(s)	(((s).b & ((1 << 11) | (1 << 10))) \
+ 				 == (1 << 10))
+ 
+-#define I387			(current->thread.i387)
+-#define FPU_info		(I387.soft.info)
++#define I387			(current->thread.xstate)
++#define FPU_info		(I387->soft.info)
+ 
+ #define FPU_CS			(*(unsigned short *) &(FPU_info->___cs))
+ #define FPU_SS			(*(unsigned short *) &(FPU_info->___ss))
+@@ -46,25 +46,25 @@
+ #define FPU_EIP			(FPU_info->___eip)
+ #define FPU_ORIG_EIP		(FPU_info->___orig_eip)
+ 
+-#define FPU_lookahead           (I387.soft.lookahead)
++#define FPU_lookahead           (I387->soft.lookahead)
+ 
+ /* nz if ip_offset and cs_selector are not to be set for the current
+    instruction. */
+-#define no_ip_update		(*(u_char *)&(I387.soft.no_update))
+-#define FPU_rm			(*(u_char *)&(I387.soft.rm))
++#define no_ip_update		(*(u_char *)&(I387->soft.no_update))
++#define FPU_rm			(*(u_char *)&(I387->soft.rm))
+ 
+ /* Number of bytes of data which can be legally accessed by the current
+    instruction. This only needs to hold a number <= 108, so a byte will do. */
+-#define access_limit		(*(u_char *)&(I387.soft.alimit))
++#define access_limit		(*(u_char *)&(I387->soft.alimit))
+ 
+-#define partial_status		(I387.soft.swd)
+-#define control_word		(I387.soft.cwd)
+-#define fpu_tag_word		(I387.soft.twd)
+-#define registers		(I387.soft.st_space)
+-#define top			(I387.soft.ftop)
++#define partial_status		(I387->soft.swd)
++#define control_word		(I387->soft.cwd)
++#define fpu_tag_word		(I387->soft.twd)
++#define registers		(I387->soft.st_space)
++#define top			(I387->soft.ftop)
+ 
+-#define instruction_address	(*(struct address *)&I387.soft.fip)
+-#define operand_address		(*(struct address *)&I387.soft.foo)
++#define instruction_address	(*(struct address *)&I387->soft.fip)
++#define operand_address		(*(struct address *)&I387->soft.foo)
+ 
+ #define FPU_access_ok(x,y,z)	if ( !access_ok(x,y,z) ) \
+ 				math_abort(FPU_info,SIGSEGV)
+diff --git a/arch/x86/math-emu/reg_ld_str.c b/arch/x86/math-emu/reg_ld_str.c
+index 799d4af..d597fe7 100644
+--- a/arch/x86/math-emu/reg_ld_str.c
++++ b/arch/x86/math-emu/reg_ld_str.c
+@@ -383,15 +383,15 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+ 	int exp;
+ 	FPU_REG tmp;
+ 
++	l[0] = 0;
++	l[1] = 0;
+ 	if (st0_tag == TAG_Valid) {
+ 		reg_copy(st0_ptr, &tmp);
+ 		exp = exponent(&tmp);
+ 
+ 		if (exp < DOUBLE_Emin) {	/* It may be a denormal */
+ 			addexponent(&tmp, -DOUBLE_Emin + 52);	/* largest exp to be 51 */
+-
+-		      denormal_arg:
+-
++denormal_arg:
+ 			if ((precision_loss = FPU_round_to_int(&tmp, st0_tag))) {
+ #ifdef PECULIAR_486
+ 				/* Did it round to a non-denormal ? */
+@@ -477,8 +477,7 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+ 
+ 				/* This is a special case: see sec 16.2.5.1 of the 80486 book */
+ 				/* Overflow to infinity */
+-				l[0] = 0x00000000;	/* Set to */
+-				l[1] = 0x7ff00000;	/* + INF */
++				l[1] = 0x7ff00000;	/* Set to + INF */
+ 			} else {
+ 				if (precision_loss) {
+ 					if (increment)
+@@ -492,8 +491,6 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+ 		}
+ 	} else if (st0_tag == TAG_Zero) {
+ 		/* Number is zero */
+-		l[0] = 0;
+-		l[1] = 0;
+ 	} else if (st0_tag == TAG_Special) {
+ 		st0_tag = FPU_Special(st0_ptr);
+ 		if (st0_tag == TW_Denormal) {
+@@ -508,7 +505,6 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+ 			reg_copy(st0_ptr, &tmp);
+ 			goto denormal_arg;
+ 		} else if (st0_tag == TW_Infinity) {
+-			l[0] = 0;
+ 			l[1] = 0x7ff00000;
+ 		} else if (st0_tag == TW_NaN) {
+ 			/* Is it really a NaN ? */
+@@ -532,7 +528,6 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+ 				EXCEPTION(EX_Invalid);
+ 				if (!(control_word & CW_Invalid))
+ 					return 0;
+-				l[0] = 0;
+ 				l[1] = 0xfff80000;
+ 			}
+ 		}
+@@ -1185,8 +1180,8 @@ u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
+ 		control_word |= 0xffff0040;
+ 		partial_status = status_word() | 0xffff0000;
+ 		fpu_tag_word |= 0xffff0000;
+-		I387.soft.fcs &= ~0xf8000000;
+-		I387.soft.fos |= 0xffff0000;
++		I387->soft.fcs &= ~0xf8000000;
++		I387->soft.fos |= 0xffff0000;
+ #endif /* PECULIAR_486 */
+ 		if (__copy_to_user(d, &control_word, 7 * 4))
+ 			FPU_abort;
+diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
+index 9832910..b7b3e4c 100644
+--- a/arch/x86/mm/Makefile
++++ b/arch/x86/mm/Makefile
+@@ -1,5 +1,17 @@
++obj-y	:=  init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \
++	    pat.o pgtable.o
++
++obj-$(CONFIG_X86_32)		+= pgtable_32.o
++
++obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
++obj-$(CONFIG_X86_PTDUMP)	+= dump_pagetables.o
++
++obj-$(CONFIG_HIGHMEM)		+= highmem_32.o
++
+ ifeq ($(CONFIG_X86_32),y)
+-include ${srctree}/arch/x86/mm/Makefile_32
++obj-$(CONFIG_NUMA)		+= discontig_32.o
+ else
+-include ${srctree}/arch/x86/mm/Makefile_64
++obj-$(CONFIG_NUMA)		+= numa_64.o
++obj-$(CONFIG_K8_NUMA)		+= k8topology_64.o
++obj-$(CONFIG_ACPI_NUMA)		+= srat_64.o
+ endif
+diff --git a/arch/x86/mm/Makefile_32 b/arch/x86/mm/Makefile_32
+deleted file mode 100644
+index c36ae88..0000000
+--- a/arch/x86/mm/Makefile_32
++++ /dev/null
+@@ -1,9 +0,0 @@
+-#
+-# Makefile for the linux i386-specific parts of the memory manager.
+-#
+-
+-obj-y	:= init_32.o pgtable_32.o fault.o ioremap.o extable.o pageattr.o mmap.o
+-
+-obj-$(CONFIG_NUMA) += discontig_32.o
+-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+-obj-$(CONFIG_HIGHMEM) += highmem_32.o
+diff --git a/arch/x86/mm/Makefile_64 b/arch/x86/mm/Makefile_64
+deleted file mode 100644
+index 688c8c2..0000000
+--- a/arch/x86/mm/Makefile_64
++++ /dev/null
+@@ -1,9 +0,0 @@
+-#
+-# Makefile for the linux x86_64-specific parts of the memory manager.
+-#
+-
+-obj-y	 := init_64.o fault.o ioremap.o extable.o pageattr.o mmap.o
+-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+-obj-$(CONFIG_NUMA) += numa_64.o
+-obj-$(CONFIG_K8_NUMA) += k8topology_64.o
+-obj-$(CONFIG_ACPI_NUMA) += srat_64.o
+diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c
+index 8e25e06..1837885 100644
+--- a/arch/x86/mm/discontig_32.c
++++ b/arch/x86/mm/discontig_32.c
+@@ -37,7 +37,7 @@
+ #include <asm/e820.h>
+ #include <asm/setup.h>
+ #include <asm/mmzone.h>
+-#include <bios_ebda.h>
++#include <asm/bios_ebda.h>
+ 
+ struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
+ EXPORT_SYMBOL(node_data);
+@@ -120,7 +120,7 @@ int __init get_memcfg_numa_flat(void)
+ 	printk("NUMA - single node, flat memory mode\n");
+ 
+ 	/* Run the memory configuration and find the top of memory. */
+-	find_max_pfn();
++	propagate_e820_map();
+ 	node_start_pfn[0] = 0;
+ 	node_end_pfn[0] = max_pfn;
+ 	memory_present(0, 0, max_pfn);
+@@ -134,7 +134,7 @@ int __init get_memcfg_numa_flat(void)
+ /*
+  * Find the highest page frame number we have available for the node
+  */
+-static void __init find_max_pfn_node(int nid)
++static void __init propagate_e820_map_node(int nid)
+ {
+ 	if (node_end_pfn[nid] > max_pfn)
+ 		node_end_pfn[nid] = max_pfn;
+@@ -379,7 +379,7 @@ unsigned long __init setup_memory(void)
+ 	printk("High memory starts at vaddr %08lx\n",
+ 			(ulong) pfn_to_kaddr(highstart_pfn));
+ 	for_each_online_node(nid)
+-		find_max_pfn_node(nid);
++		propagate_e820_map_node(nid);
+ 
+ 	memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
+ 	NODE_DATA(0)->bdata = &node0_bdata;
+diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
+new file mode 100644
+index 0000000..2c24bea
+--- /dev/null
++++ b/arch/x86/mm/dump_pagetables.c
+@@ -0,0 +1,354 @@
++/*
++ * Debug helper to dump the current kernel pagetables of the system
++ * so that we can see what the various memory ranges are set to.
++ *
++ * (C) Copyright 2008 Intel Corporation
++ *
++ * Author: Arjan van de Ven <arjan at linux.intel.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; version 2
++ * of the License.
++ */
++
++#include <linux/debugfs.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++
++#include <asm/pgtable.h>
++
++/*
++ * The dumper groups pagetable entries of the same type into one, and for
++ * that it needs to keep some state when walking, and flush this state
++ * when a "break" in the continuity is found.
++ */
++struct pg_state {
++	int level;
++	pgprot_t current_prot;
++	unsigned long start_address;
++	unsigned long current_address;
++	const struct addr_marker *marker;
++};
++
++struct addr_marker {
++	unsigned long start_address;
++	const char *name;
++};
++
++/* Address space markers hints */
++static struct addr_marker address_markers[] = {
++	{ 0, "User Space" },
++#ifdef CONFIG_X86_64
++	{ 0x8000000000000000UL, "Kernel Space" },
++	{ 0xffff810000000000UL, "Low Kernel Mapping" },
++	{ VMALLOC_START,        "vmalloc() Area" },
++	{ VMEMMAP_START,        "Vmemmap" },
++	{ __START_KERNEL_map,   "High Kernel Mapping" },
++	{ MODULES_VADDR,        "Modules" },
++	{ MODULES_END,          "End Modules" },
++#else
++	{ PAGE_OFFSET,          "Kernel Mapping" },
++	{ 0/* VMALLOC_START */, "vmalloc() Area" },
++	{ 0/*VMALLOC_END*/,     "vmalloc() End" },
++# ifdef CONFIG_HIGHMEM
++	{ 0/*PKMAP_BASE*/,      "Persisent kmap() Area" },
++# endif
++	{ 0/*FIXADDR_START*/,   "Fixmap Area" },
++#endif
++	{ -1, NULL }		/* End of list */
++};
++
++/* Multipliers for offsets within the PTEs */
++#define PTE_LEVEL_MULT (PAGE_SIZE)
++#define PMD_LEVEL_MULT (PTRS_PER_PTE * PTE_LEVEL_MULT)
++#define PUD_LEVEL_MULT (PTRS_PER_PMD * PMD_LEVEL_MULT)
++#define PGD_LEVEL_MULT (PTRS_PER_PUD * PUD_LEVEL_MULT)
++
++/*
++ * Print a readable form of a pgprot_t to the seq_file
++ */
++static void printk_prot(struct seq_file *m, pgprot_t prot, int level)
++{
++	pgprotval_t pr = pgprot_val(prot);
++	static const char * const level_name[] =
++		{ "cr3", "pgd", "pud", "pmd", "pte" };
++
++	if (!pgprot_val(prot)) {
++		/* Not present */
++		seq_printf(m, "                          ");
++	} else {
++		if (pr & _PAGE_USER)
++			seq_printf(m, "USR ");
++		else
++			seq_printf(m, "    ");
++		if (pr & _PAGE_RW)
++			seq_printf(m, "RW ");
++		else
++			seq_printf(m, "ro ");
++		if (pr & _PAGE_PWT)
++			seq_printf(m, "PWT ");
++		else
++			seq_printf(m, "    ");
++		if (pr & _PAGE_PCD)
++			seq_printf(m, "PCD ");
++		else
++			seq_printf(m, "    ");
++
++		/* Bit 9 has a different meaning on level 3 vs 4 */
++		if (level <= 3) {
++			if (pr & _PAGE_PSE)
++				seq_printf(m, "PSE ");
++			else
++				seq_printf(m, "    ");
++		} else {
++			if (pr & _PAGE_PAT)
++				seq_printf(m, "pat ");
++			else
++				seq_printf(m, "    ");
++		}
++		if (pr & _PAGE_GLOBAL)
++			seq_printf(m, "GLB ");
++		else
++			seq_printf(m, "    ");
++		if (pr & _PAGE_NX)
++			seq_printf(m, "NX ");
++		else
++			seq_printf(m, "x  ");
++	}
++	seq_printf(m, "%s\n", level_name[level]);
++}
++
++/*
++ * On 64 bits, sign-extend the 48 bit address to 64 bit
++ */
++static unsigned long normalize_addr(unsigned long u)
++{
++#ifdef CONFIG_X86_64
++	return (signed long)(u << 16) >> 16;
++#else
++	return u;
++#endif
++}
++
++/*
++ * This function gets called on a break in a continuous series
++ * of PTE entries; the next one is different so we need to
++ * print what we collected so far.
++ */
++static void note_page(struct seq_file *m, struct pg_state *st,
++		      pgprot_t new_prot, int level)
++{
++	pgprotval_t prot, cur;
++	static const char units[] = "KMGTPE";
++
++	/*
++	 * If we have a "break" in the series, we need to flush the state that
++	 * we have now. "break" is either changing perms, levels or
++	 * address space marker.
++	 */
++	prot = pgprot_val(new_prot) & ~(PTE_MASK);
++	cur = pgprot_val(st->current_prot) & ~(PTE_MASK);
++
++	if (!st->level) {
++		/* First entry */
++		st->current_prot = new_prot;
++		st->level = level;
++		st->marker = address_markers;
++		seq_printf(m, "---[ %s ]---\n", st->marker->name);
++	} else if (prot != cur || level != st->level ||
++		   st->current_address >= st->marker[1].start_address) {
++		const char *unit = units;
++		unsigned long delta;
++
++		/*
++		 * Now print the actual finished series
++		 */
++		seq_printf(m, "0x%p-0x%p   ",
++			   (void *)st->start_address,
++			   (void *)st->current_address);
++
++		delta = (st->current_address - st->start_address) >> 10;
++		while (!(delta & 1023) && unit[1]) {
++			delta >>= 10;
++			unit++;
++		}
++		seq_printf(m, "%9lu%c ", delta, *unit);
++		printk_prot(m, st->current_prot, st->level);
++
++		/*
++		 * We print markers for special areas of address space,
++		 * such as the start of vmalloc space etc.
++		 * This helps in the interpretation.
++		 */
++		if (st->current_address >= st->marker[1].start_address) {
++			st->marker++;
++			seq_printf(m, "---[ %s ]---\n", st->marker->name);
++		}
++
++		st->start_address = st->current_address;
++		st->current_prot = new_prot;
++		st->level = level;
++	}
++}
++
++static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
++							unsigned long P)
++{
++	int i;
++	pte_t *start;
++
++	start = (pte_t *) pmd_page_vaddr(addr);
++	for (i = 0; i < PTRS_PER_PTE; i++) {
++		pgprot_t prot = pte_pgprot(*start);
++
++		st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT);
++		note_page(m, st, prot, 4);
++		start++;
++	}
++}
++
++#if PTRS_PER_PMD > 1
++
++static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr,
++							unsigned long P)
++{
++	int i;
++	pmd_t *start;
++
++	start = (pmd_t *) pud_page_vaddr(addr);
++	for (i = 0; i < PTRS_PER_PMD; i++) {
++		st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT);
++		if (!pmd_none(*start)) {
++			pgprotval_t prot = pmd_val(*start) & ~PTE_MASK;
++
++			if (pmd_large(*start) || !pmd_present(*start))
++				note_page(m, st, __pgprot(prot), 3);
++			else
++				walk_pte_level(m, st, *start,
++					       P + i * PMD_LEVEL_MULT);
++		} else
++			note_page(m, st, __pgprot(0), 3);
++		start++;
++	}
++}
++
++#else
++#define walk_pmd_level(m,s,a,p) walk_pte_level(m,s,__pmd(pud_val(a)),p)
++#define pud_large(a) pmd_large(__pmd(pud_val(a)))
++#define pud_none(a)  pmd_none(__pmd(pud_val(a)))
++#endif
++
++#if PTRS_PER_PUD > 1
++
++static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
++							unsigned long P)
++{
++	int i;
++	pud_t *start;
++
++	start = (pud_t *) pgd_page_vaddr(addr);
++
++	for (i = 0; i < PTRS_PER_PUD; i++) {
++		st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT);
++		if (!pud_none(*start)) {
++			pgprotval_t prot = pud_val(*start) & ~PTE_MASK;
++
++			if (pud_large(*start) || !pud_present(*start))
++				note_page(m, st, __pgprot(prot), 2);
++			else
++				walk_pmd_level(m, st, *start,
++					       P + i * PUD_LEVEL_MULT);
++		} else
++			note_page(m, st, __pgprot(0), 2);
++
++		start++;
++	}
++}
++
++#else
++#define walk_pud_level(m,s,a,p) walk_pmd_level(m,s,__pud(pgd_val(a)),p)
++#define pgd_large(a) pud_large(__pud(pgd_val(a)))
++#define pgd_none(a)  pud_none(__pud(pgd_val(a)))
++#endif
++
++static void walk_pgd_level(struct seq_file *m)
++{
++#ifdef CONFIG_X86_64
++	pgd_t *start = (pgd_t *) &init_level4_pgt;
++#else
++	pgd_t *start = swapper_pg_dir;
++#endif
++	int i;
++	struct pg_state st;
++
++	memset(&st, 0, sizeof(st));
++
++	for (i = 0; i < PTRS_PER_PGD; i++) {
++		st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
++		if (!pgd_none(*start)) {
++			pgprotval_t prot = pgd_val(*start) & ~PTE_MASK;
++
++			if (pgd_large(*start) || !pgd_present(*start))
++				note_page(m, &st, __pgprot(prot), 1);
++			else
++				walk_pud_level(m, &st, *start,
++					       i * PGD_LEVEL_MULT);
++		} else
++			note_page(m, &st, __pgprot(0), 1);
++
++		start++;
++	}
++
++	/* Flush out the last page */
++	st.current_address = normalize_addr(PTRS_PER_PGD*PGD_LEVEL_MULT);
++	note_page(m, &st, __pgprot(0), 0);
++}
++
++static int ptdump_show(struct seq_file *m, void *v)
++{
++	walk_pgd_level(m);
++	return 0;
++}
++
++static int ptdump_open(struct inode *inode, struct file *filp)
++{
++	return single_open(filp, ptdump_show, NULL);
++}
++
++static const struct file_operations ptdump_fops = {
++	.open		= ptdump_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
++
++static int pt_dump_init(void)
++{
++	struct dentry *pe;
++
++#ifdef CONFIG_X86_32
++	/* Not a compile-time constant on x86-32 */
++	address_markers[2].start_address = VMALLOC_START;
++	address_markers[3].start_address = VMALLOC_END;
++# ifdef CONFIG_HIGHMEM
++	address_markers[4].start_address = PKMAP_BASE;
++	address_markers[5].start_address = FIXADDR_START;
++# else
++	address_markers[4].start_address = FIXADDR_START;
++# endif
++#endif
++
++	pe = debugfs_create_file("kernel_page_tables", 0600, NULL, NULL,
++				 &ptdump_fops);
++	if (!pe)
++		return -ENOMEM;
++
++	return 0;
++}
++
++__initcall(pt_dump_init);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Arjan van de Ven <arjan at linux.intel.com>");
++MODULE_DESCRIPTION("Kernel debugging helper that dumps pagetables");
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index ec08d83..fd7e179 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -639,7 +639,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
+ #ifdef CONFIG_X86_32
+ 	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
+ 	   fault has been handled. */
+-	if (regs->flags & (X86_EFLAGS_IF|VM_MASK))
++	if (regs->flags & (X86_EFLAGS_IF | X86_VM_MASK))
+ 		local_irq_enable();
+ 
+ 	/*
+@@ -976,9 +976,5 @@ void vmalloc_sync_all(void)
+ 		if (address == start)
+ 			start = address + PGDIR_SIZE;
+ 	}
+-	/* Check that there is no need to do the same for the modules area. */
+-	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
+-	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
+-				(__START_KERNEL & PGDIR_MASK)));
+ #endif
+ }
+diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
+index ee1091a..4a47618 100644
+--- a/arch/x86/mm/init_32.c
++++ b/arch/x86/mm/init_32.c
+@@ -1,5 +1,4 @@
+ /*
+- *  linux/arch/i386/mm/init.c
+  *
+  *  Copyright (C) 1995  Linus Torvalds
+  *
+@@ -51,6 +50,8 @@
+ 
+ unsigned int __VMALLOC_RESERVE = 128 << 20;
+ 
++unsigned long max_pfn_mapped;
++
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ unsigned long highstart_pfn, highend_pfn;
+ 
+@@ -70,7 +71,7 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
+ 	if (!(pgd_val(*pgd) & _PAGE_PRESENT)) {
+ 		pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ 
+-		paravirt_alloc_pd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
++		paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+ 		set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+ 		pud = pud_offset(pgd, 0);
+ 		BUG_ON(pmd_table != pmd_offset(pud, 0));
+@@ -99,7 +100,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
+ 				(pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+ 		}
+ 
+-		paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
++		paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+ 		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+ 		BUG_ON(page_table != pte_offset_kernel(pmd, 0));
+ 	}
+@@ -179,8 +180,13 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+ 			/*
+ 			 * Map with big pages if possible, otherwise
+ 			 * create normal page tables:
++			 *
++			 * Don't use a large page for the first 2/4MB of memory
++			 * because there are often fixed size MTRRs in there
++			 * and overlapping MTRRs into large pages can cause
++			 * slowdowns.
+ 			 */
+-			if (cpu_has_pse) {
++			if (cpu_has_pse && !(pgd_idx == 0 && pmd_idx == 0)) {
+ 				unsigned int addr2;
+ 				pgprot_t prot = PAGE_KERNEL_LARGE;
+ 
+@@ -194,6 +200,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+ 				set_pmd(pmd, pfn_pmd(pfn, prot));
+ 
+ 				pfn += PTRS_PER_PTE;
++				max_pfn_mapped = pfn;
+ 				continue;
+ 			}
+ 			pte = one_page_table_init(pmd);
+@@ -208,6 +215,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+ 
+ 				set_pte(pte, pfn_pte(pfn, prot));
+ 			}
++			max_pfn_mapped = pfn;
+ 		}
+ 	}
+ }
+@@ -219,6 +227,25 @@ static inline int page_kills_ppro(unsigned long pagenr)
+ 	return 0;
+ }
+ 
++/*
++ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
++ * is valid. The argument is a physical page number.
++ *
++ *
++ * On x86, access has to be given to the first megabyte of ram because that area
++ * contains bios code and data regions used by X and dosemu and similar apps.
++ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
++ * mmio resources as well as potential bios/acpi data regions.
++ */
++int devmem_is_allowed(unsigned long pagenr)
++{
++	if (pagenr <= 256)
++		return 1;
++	if (!page_is_ram(pagenr))
++		return 1;
++	return 0;
++}
++
+ #ifdef CONFIG_HIGHMEM
+ pte_t *kmap_pte;
+ pgprot_t kmap_prot;
+@@ -357,7 +384,7 @@ void __init native_pagetable_setup_start(pgd_t *base)
+ 
+ 		pte_clear(NULL, va, pte);
+ 	}
+-	paravirt_alloc_pd(&init_mm, __pa(base) >> PAGE_SHIFT);
++	paravirt_alloc_pmd(&init_mm, __pa(base) >> PAGE_SHIFT);
+ }
+ 
+ void __init native_pagetable_setup_done(pgd_t *base)
+@@ -449,7 +476,7 @@ void zap_low_mappings(void)
+ 	 * Note that "pgd_clear()" doesn't do it for
+ 	 * us, because pgd_clear() is a no-op on i386.
+ 	 */
+-	for (i = 0; i < USER_PTRS_PER_PGD; i++) {
++	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
+@@ -539,9 +566,9 @@ void __init paging_init(void)
+ 
+ /*
+  * Test if the WP bit works in supervisor mode. It isn't supported on 386's
+- * and also on some strange 486's (NexGen etc.). All 586+'s are OK. This
+- * used to involve black magic jumps to work around some nasty CPU bugs,
+- * but fortunately the switch to using exceptions got rid of all that.
++ * and also on some strange 486's. All 586+'s are OK. This used to involve
++ * black magic jumps to work around some nasty CPU bugs, but fortunately the
++ * switch to using exceptions got rid of all that.
+  */
+ static void __init test_wp_bit(void)
+ {
+@@ -723,25 +750,17 @@ void mark_rodata_ro(void)
+ 	unsigned long start = PFN_ALIGN(_text);
+ 	unsigned long size = PFN_ALIGN(_etext) - start;
+ 
+-#ifndef CONFIG_KPROBES
+-#ifdef CONFIG_HOTPLUG_CPU
+-	/* It must still be possible to apply SMP alternatives. */
+-	if (num_possible_cpus() <= 1)
+-#endif
+-	{
+-		set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+-		printk(KERN_INFO "Write protecting the kernel text: %luk\n",
+-			size >> 10);
++	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
++	printk(KERN_INFO "Write protecting the kernel text: %luk\n",
++		size >> 10);
+ 
+ #ifdef CONFIG_CPA_DEBUG
+-		printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
+-			start, start+size);
+-		set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT);
++	printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
++		start, start+size);
++	set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT);
+ 
+-		printk(KERN_INFO "Testing CPA: write protecting again\n");
+-		set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
+-#endif
+-	}
++	printk(KERN_INFO "Testing CPA: write protecting again\n");
++	set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
+ #endif
+ 	start += size;
+ 	size = (unsigned long)__end_rodata - start;
+diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
+index a02a14f..0cca626 100644
+--- a/arch/x86/mm/init_64.c
++++ b/arch/x86/mm/init_64.c
+@@ -47,13 +47,30 @@
+ #include <asm/numa.h>
+ #include <asm/cacheflush.h>
+ 
+-const struct dma_mapping_ops *dma_ops;
+-EXPORT_SYMBOL(dma_ops);
+-
+ static unsigned long dma_reserve __initdata;
+ 
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ 
++int direct_gbpages __meminitdata
++#ifdef CONFIG_DIRECT_GBPAGES
++				= 1
++#endif
++;
++
++static int __init parse_direct_gbpages_off(char *arg)
++{
++	direct_gbpages = 0;
++	return 0;
++}
++early_param("nogbpages", parse_direct_gbpages_off);
++
++static int __init parse_direct_gbpages_on(char *arg)
++{
++	direct_gbpages = 1;
++	return 0;
++}
++early_param("gbpages", parse_direct_gbpages_on);
++
+ /*
+  * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
+  * physical space so we can cache the place of the first one and move
+@@ -69,9 +86,6 @@ void show_mem(void)
+ 
+ 	printk(KERN_INFO "Mem-info:\n");
+ 	show_free_areas();
+-	printk(KERN_INFO "Free swap:       %6ldkB\n",
+-		nr_swap_pages << (PAGE_SHIFT-10));
+-
+ 	for_each_online_pgdat(pgdat) {
+ 		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+ 			/*
+@@ -121,7 +135,7 @@ static __init void *spp_getpage(void)
+ 	return ptr;
+ }
+ 
+-static __init void
++static void
+ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
+ {
+ 	pgd_t *pgd;
+@@ -159,7 +173,7 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
+ 	new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
+ 
+ 	pte = pte_offset_kernel(pmd, vaddr);
+-	if (!pte_none(*pte) &&
++	if (!pte_none(*pte) && pte_val(new_pte) &&
+ 	    pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask))
+ 		pte_ERROR(*pte);
+ 	set_pte(pte, new_pte);
+@@ -200,8 +214,7 @@ void __init cleanup_highmap(void)
+ }
+ 
+ /* NOTE: this is meant to be run only at boot */
+-void __init
+-__set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
++void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
+ {
+ 	unsigned long address = __fix_to_virt(idx);
+ 
+@@ -296,7 +309,7 @@ __meminit void early_iounmap(void *addr, unsigned long size)
+ 	__flush_tlb_all();
+ }
+ 
+-static void __meminit
++static unsigned long __meminit
+ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
+ {
+ 	int i = pmd_index(address);
+@@ -318,21 +331,26 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
+ 		set_pte((pte_t *)pmd,
+ 			pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
+ 	}
++	return address;
+ }
+ 
+-static void __meminit
++static unsigned long __meminit
+ phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
+ {
+ 	pmd_t *pmd = pmd_offset(pud, 0);
++	unsigned long last_map_addr;
++
+ 	spin_lock(&init_mm.page_table_lock);
+-	phys_pmd_init(pmd, address, end);
++	last_map_addr = phys_pmd_init(pmd, address, end);
+ 	spin_unlock(&init_mm.page_table_lock);
+ 	__flush_tlb_all();
++	return last_map_addr;
+ }
+ 
+-static void __meminit
++static unsigned long __meminit
+ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
+ {
++	unsigned long last_map_addr = end;
+ 	int i = pud_index(addr);
+ 
+ 	for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) {
+@@ -350,7 +368,15 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
+ 		}
+ 
+ 		if (pud_val(*pud)) {
+-			phys_pmd_update(pud, addr, end);
++			if (!pud_large(*pud))
++				last_map_addr = phys_pmd_update(pud, addr, end);
++			continue;
++		}
++
++		if (direct_gbpages) {
++			set_pte((pte_t *)pud,
++				pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
++			last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
+ 			continue;
+ 		}
+ 
+@@ -358,12 +384,14 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
+ 
+ 		spin_lock(&init_mm.page_table_lock);
+ 		set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
+-		phys_pmd_init(pmd, addr, end);
++		last_map_addr = phys_pmd_init(pmd, addr, end);
+ 		spin_unlock(&init_mm.page_table_lock);
+ 
+ 		unmap_low_page(pmd);
+ 	}
+ 	__flush_tlb_all();
++
++	return last_map_addr >> PAGE_SHIFT;
+ }
+ 
+ static void __init find_early_table_space(unsigned long end)
+@@ -371,9 +399,11 @@ static void __init find_early_table_space(unsigned long end)
+ 	unsigned long puds, pmds, tables, start;
+ 
+ 	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
+-	pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+-	tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) +
+-		 round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
++	tables = round_up(puds * sizeof(pud_t), PAGE_SIZE);
++	if (!direct_gbpages) {
++		pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
++		tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
++	}
+ 
+ 	/*
+ 	 * RED-PEN putting page tables only on node 0 could
+@@ -393,16 +423,135 @@ static void __init find_early_table_space(unsigned long end)
+ 		(table_start << PAGE_SHIFT) + tables);
+ }
+ 
++static void __init init_gbpages(void)
++{
++	if (direct_gbpages && cpu_has_gbpages)
++		printk(KERN_INFO "Using GB pages for direct mapping\n");
++	else
++		direct_gbpages = 0;
++}
++
++#ifdef CONFIG_MEMTEST_BOOTPARAM
++
++static void __init memtest(unsigned long start_phys, unsigned long size,
++				 unsigned pattern)
++{
++	unsigned long i;
++	unsigned long *start;
++	unsigned long start_bad;
++	unsigned long last_bad;
++	unsigned long val;
++	unsigned long start_phys_aligned;
++	unsigned long count;
++	unsigned long incr;
++
++	switch (pattern) {
++	case 0:
++		val = 0UL;
++		break;
++	case 1:
++		val = -1UL;
++		break;
++	case 2:
++		val = 0x5555555555555555UL;
++		break;
++	case 3:
++		val = 0xaaaaaaaaaaaaaaaaUL;
++		break;
++	default:
++		return;
++	}
++
++	incr = sizeof(unsigned long);
++	start_phys_aligned = ALIGN(start_phys, incr);
++	count = (size - (start_phys_aligned - start_phys))/incr;
++	start = __va(start_phys_aligned);
++	start_bad = 0;
++	last_bad = 0;
++
++	for (i = 0; i < count; i++)
++		start[i] = val;
++	for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
++		if (*start != val) {
++			if (start_phys_aligned == last_bad + incr) {
++				last_bad += incr;
++			} else {
++				if (start_bad) {
++					printk(KERN_CONT "\n  %016lx bad mem addr %016lx - %016lx reserved",
++						val, start_bad, last_bad + incr);
++					reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
++				}
++				start_bad = last_bad = start_phys_aligned;
++			}
++		}
++	}
++	if (start_bad) {
++		printk(KERN_CONT "\n  %016lx bad mem addr %016lx - %016lx reserved",
++			val, start_bad, last_bad + incr);
++		reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
++	}
++
++}
++
++static int memtest_pattern __initdata = CONFIG_MEMTEST_BOOTPARAM_VALUE;
++
++static int __init parse_memtest(char *arg)
++{
++	if (arg)
++		memtest_pattern = simple_strtoul(arg, NULL, 0);
++	return 0;
++}
++
++early_param("memtest", parse_memtest);
++
++static void __init early_memtest(unsigned long start, unsigned long end)
++{
++	unsigned long t_start, t_size;
++	unsigned pattern;
++
++	if (!memtest_pattern)
++		return;
++
++	printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern);
++	for (pattern = 0; pattern < memtest_pattern; pattern++) {
++		t_start = start;
++		t_size = 0;
++		while (t_start < end) {
++			t_start = find_e820_area_size(t_start, &t_size, 1);
++
++			/* done ? */
++			if (t_start >= end)
++				break;
++			if (t_start + t_size > end)
++				t_size = end - t_start;
++
++			printk(KERN_CONT "\n  %016lx - %016lx pattern %d",
++				t_start, t_start + t_size, pattern);
++
++			memtest(t_start, t_size, pattern);
++
++			t_start += t_size;
++		}
++	}
++	printk(KERN_CONT "\n");
++}
++#else
++static void __init early_memtest(unsigned long start, unsigned long end)
++{
++}
++#endif
++
+ /*
+  * Setup the direct mapping of the physical memory at PAGE_OFFSET.
+  * This runs before bootmem is initialized and gets pages directly from
+  * the physical memory. To access them they are temporarily mapped.
+  */
+-void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
++unsigned long __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ {
+-	unsigned long next;
++	unsigned long next, last_map_addr = end;
++	unsigned long start_phys = start, end_phys = end;
+ 
+-	pr_debug("init_memory_mapping\n");
++	printk(KERN_INFO "init_memory_mapping\n");
+ 
+ 	/*
+ 	 * Find space for the kernel direct mapping tables.
+@@ -411,8 +560,10 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ 	 * memory mapped. Unfortunately this is done currently before the
+ 	 * nodes are discovered.
+ 	 */
+-	if (!after_bootmem)
++	if (!after_bootmem) {
++		init_gbpages();
+ 		find_early_table_space(end);
++	}
+ 
+ 	start = (unsigned long)__va(start);
+ 	end = (unsigned long)__va(end);
+@@ -430,7 +581,7 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ 		next = start + PGDIR_SIZE;
+ 		if (next > end)
+ 			next = end;
+-		phys_pud_init(pud, __pa(start), __pa(next));
++		last_map_addr = phys_pud_init(pud, __pa(start), __pa(next));
+ 		if (!after_bootmem)
+ 			set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
+ 		unmap_low_page(pud);
+@@ -443,6 +594,11 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ 	if (!after_bootmem)
+ 		reserve_early(table_start << PAGE_SHIFT,
+ 				 table_end << PAGE_SHIFT, "PGTABLE");
++
++	if (!after_bootmem)
++		early_memtest(start_phys, end_phys);
++
++	return last_map_addr;
+ }
+ 
+ #ifndef CONFIG_NUMA
+@@ -482,11 +638,13 @@ int arch_add_memory(int nid, u64 start, u64 size)
+ {
+ 	struct pglist_data *pgdat = NODE_DATA(nid);
+ 	struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
+-	unsigned long start_pfn = start >> PAGE_SHIFT;
++	unsigned long last_mapped_pfn, start_pfn = start >> PAGE_SHIFT;
+ 	unsigned long nr_pages = size >> PAGE_SHIFT;
+ 	int ret;
+ 
+-	init_memory_mapping(start, start + size-1);
++	last_mapped_pfn = init_memory_mapping(start, start + size-1);
++	if (last_mapped_pfn > max_pfn_mapped)
++		max_pfn_mapped = last_mapped_pfn;
+ 
+ 	ret = __add_pages(zone, start_pfn, nr_pages);
+ 	WARN_ON(1);
+@@ -505,6 +663,26 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+ 
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+ 
++/*
++ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
++ * is valid. The argument is a physical page number.
++ *
++ *
++ * On x86, access has to be given to the first megabyte of ram because that area
++ * contains bios code and data regions used by X and dosemu and similar apps.
++ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
++ * mmio resources as well as potential bios/acpi data regions.
++ */
++int devmem_is_allowed(unsigned long pagenr)
++{
++	if (pagenr <= 256)
++		return 1;
++	if (!page_is_ram(pagenr))
++		return 1;
++	return 0;
++}
++
++
+ static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
+ 			 kcore_modules, kcore_vsyscall;
+ 
+@@ -596,24 +774,7 @@ EXPORT_SYMBOL_GPL(rodata_test_data);
+ 
+ void mark_rodata_ro(void)
+ {
+-	unsigned long start = (unsigned long)_stext, end;
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-	/* It must still be possible to apply SMP alternatives. */
+-	if (num_possible_cpus() > 1)
+-		start = (unsigned long)_etext;
+-#endif
+-
+-#ifdef CONFIG_KPROBES
+-	start = (unsigned long)__start_rodata;
+-#endif
+-
+-	end = (unsigned long)__end_rodata;
+-	start = (start + PAGE_SIZE - 1) & PAGE_MASK;
+-	end &= PAGE_MASK;
+-	if (end <= start)
+-		return;
+-
++	unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata);
+ 
+ 	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+ 	       (end - start) >> 10);
+@@ -636,6 +797,7 @@ void mark_rodata_ro(void)
+ 	set_memory_ro(start, (end-start) >> PAGE_SHIFT);
+ #endif
+ }
++
+ #endif
+ 
+ #ifdef CONFIG_BLK_DEV_INITRD
+@@ -657,7 +819,7 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
+ 		 * This can happen with kdump kernels when accessing
+ 		 * firmware tables:
+ 		 */
+-		if (pfn < end_pfn_map)
++		if (pfn < max_pfn_mapped)
+ 			return;
+ 
+ 		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
+diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
+index 794895c..d176b23 100644
+--- a/arch/x86/mm/ioremap.c
++++ b/arch/x86/mm/ioremap.c
+@@ -19,11 +19,7 @@
+ #include <asm/pgtable.h>
+ #include <asm/tlbflush.h>
+ #include <asm/pgalloc.h>
+-
+-enum ioremap_mode {
+-	IOR_MODE_UNCACHED,
+-	IOR_MODE_CACHED,
+-};
++#include <asm/pat.h>
+ 
+ #ifdef CONFIG_X86_64
+ 
+@@ -35,11 +31,23 @@ unsigned long __phys_addr(unsigned long x)
+ }
+ EXPORT_SYMBOL(__phys_addr);
+ 
++static inline int phys_addr_valid(unsigned long addr)
++{
++	return addr < (1UL << boot_cpu_data.x86_phys_bits);
++}
++
++#else
++
++static inline int phys_addr_valid(unsigned long addr)
++{
++	return 1;
++}
++
+ #endif
+ 
+ int page_is_ram(unsigned long pagenr)
+ {
+-	unsigned long addr, end;
++	resource_size_t addr, end;
+ 	int i;
+ 
+ 	/*
+@@ -78,19 +86,22 @@ int page_is_ram(unsigned long pagenr)
+  * Fix up the linear direct mapping of the kernel to avoid cache attribute
+  * conflicts.
+  */
+-static int ioremap_change_attr(unsigned long vaddr, unsigned long size,
+-			       enum ioremap_mode mode)
++int ioremap_change_attr(unsigned long vaddr, unsigned long size,
++			       unsigned long prot_val)
+ {
+ 	unsigned long nrpages = size >> PAGE_SHIFT;
+ 	int err;
+ 
+-	switch (mode) {
+-	case IOR_MODE_UNCACHED:
++	switch (prot_val) {
++	case _PAGE_CACHE_UC:
+ 	default:
+-		err = set_memory_uc(vaddr, nrpages);
++		err = _set_memory_uc(vaddr, nrpages);
++		break;
++	case _PAGE_CACHE_WC:
++		err = _set_memory_wc(vaddr, nrpages);
+ 		break;
+-	case IOR_MODE_CACHED:
+-		err = set_memory_wb(vaddr, nrpages);
++	case _PAGE_CACHE_WB:
++		err = _set_memory_wb(vaddr, nrpages);
+ 		break;
+ 	}
+ 
+@@ -107,17 +118,27 @@ static int ioremap_change_attr(unsigned long vaddr, unsigned long size,
+  * caller shouldn't need to know that small detail.
+  */
+ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+-			       enum ioremap_mode mode)
++			       unsigned long prot_val)
+ {
+-	unsigned long pfn, offset, last_addr, vaddr;
++	unsigned long pfn, offset, vaddr;
++	resource_size_t last_addr;
+ 	struct vm_struct *area;
++	unsigned long new_prot_val;
+ 	pgprot_t prot;
++	int retval;
+ 
+ 	/* Don't allow wraparound or zero size */
+ 	last_addr = phys_addr + size - 1;
+ 	if (!size || last_addr < phys_addr)
+ 		return NULL;
+ 
++	if (!phys_addr_valid(phys_addr)) {
++		printk(KERN_WARNING "ioremap: invalid physical address %llx\n",
++		       (unsigned long long)phys_addr);
++		WARN_ON_ONCE(1);
++		return NULL;
++	}
++
+ 	/*
+ 	 * Don't remap the low PCI/ISA area, it's always mapped..
+ 	 */
+@@ -127,25 +148,14 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+ 	/*
+ 	 * Don't allow anybody to remap normal RAM that we're using..
+ 	 */
+-	for (pfn = phys_addr >> PAGE_SHIFT; pfn < max_pfn_mapped &&
+-	     (pfn << PAGE_SHIFT) < last_addr; pfn++) {
+-		if (page_is_ram(pfn) && pfn_valid(pfn) &&
+-		    !PageReserved(pfn_to_page(pfn)))
+-			return NULL;
+-	}
++	for (pfn = phys_addr >> PAGE_SHIFT;
++				(pfn << PAGE_SHIFT) < last_addr; pfn++) {
+ 
+-	switch (mode) {
+-	case IOR_MODE_UNCACHED:
+-	default:
+-		/*
+-		 * FIXME: we will use UC MINUS for now, as video fb drivers
+-		 * depend on it. Upcoming ioremap_wc() will fix this behavior.
+-		 */
+-		prot = PAGE_KERNEL_UC_MINUS;
+-		break;
+-	case IOR_MODE_CACHED:
+-		prot = PAGE_KERNEL;
+-		break;
++		int is_ram = page_is_ram(pfn);
++
++		if (is_ram && pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn)))
++			return NULL;
++		WARN_ON_ONCE(is_ram);
+ 	}
+ 
+ 	/*
+@@ -155,6 +165,50 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+ 	phys_addr &= PAGE_MASK;
+ 	size = PAGE_ALIGN(last_addr+1) - phys_addr;
+ 
++	retval = reserve_memtype(phys_addr, phys_addr + size,
++						prot_val, &new_prot_val);
++	if (retval) {
++		pr_debug("Warning: reserve_memtype returned %d\n", retval);
++		return NULL;
++	}
++
++	if (prot_val != new_prot_val) {
++		/*
++		 * Do not fallback to certain memory types with certain
++		 * requested type:
++		 * - request is uncached, return cannot be write-back
++		 * - request is uncached, return cannot be write-combine
++		 * - request is write-combine, return cannot be write-back
++		 */
++		if ((prot_val == _PAGE_CACHE_UC &&
++		     (new_prot_val == _PAGE_CACHE_WB ||
++		      new_prot_val == _PAGE_CACHE_WC)) ||
++		    (prot_val == _PAGE_CACHE_WC &&
++		     new_prot_val == _PAGE_CACHE_WB)) {
++			pr_debug(
++		"ioremap error for 0x%llx-0x%llx, requested 0x%lx, got 0x%lx\n",
++				(unsigned long long)phys_addr,
++				(unsigned long long)(phys_addr + size),
++				prot_val, new_prot_val);
++			free_memtype(phys_addr, phys_addr + size);
++			return NULL;
++		}
++		prot_val = new_prot_val;
++	}
++
++	switch (prot_val) {
++	case _PAGE_CACHE_UC:
++	default:
++		prot = PAGE_KERNEL_NOCACHE;
++		break;
++	case _PAGE_CACHE_WC:
++		prot = PAGE_KERNEL_WC;
++		break;
++	case _PAGE_CACHE_WB:
++		prot = PAGE_KERNEL;
++		break;
++	}
++
+ 	/*
+ 	 * Ok, go for it..
+ 	 */
+@@ -164,11 +218,13 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+ 	area->phys_addr = phys_addr;
+ 	vaddr = (unsigned long) area->addr;
+ 	if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
++		free_memtype(phys_addr, phys_addr + size);
+ 		free_vm_area(area);
+ 		return NULL;
+ 	}
+ 
+-	if (ioremap_change_attr(vaddr, size, mode) < 0) {
++	if (ioremap_change_attr(vaddr, size, prot_val) < 0) {
++		free_memtype(phys_addr, phys_addr + size);
+ 		vunmap(area->addr);
+ 		return NULL;
+ 	}
+@@ -199,13 +255,32 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+  */
+ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
+ {
+-	return __ioremap(phys_addr, size, IOR_MODE_UNCACHED);
++	return __ioremap(phys_addr, size, _PAGE_CACHE_UC);
+ }
+ EXPORT_SYMBOL(ioremap_nocache);
+ 
++/**
++ * ioremap_wc	-	map memory into CPU space write combined
++ * @offset:	bus address of the memory
++ * @size:	size of the resource to map
++ *
++ * This version of ioremap ensures that the memory is marked write combining.
++ * Write combining allows faster writes to some hardware devices.
++ *
++ * Must be freed with iounmap.
++ */
++void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
++{
++	if (pat_wc_enabled)
++		return __ioremap(phys_addr, size, _PAGE_CACHE_WC);
++	else
++		return ioremap_nocache(phys_addr, size);
++}
++EXPORT_SYMBOL(ioremap_wc);
++
+ void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
+ {
+-	return __ioremap(phys_addr, size, IOR_MODE_CACHED);
++	return __ioremap(phys_addr, size, _PAGE_CACHE_WB);
+ }
+ EXPORT_SYMBOL(ioremap_cache);
+ 
+@@ -252,6 +327,8 @@ void iounmap(volatile void __iomem *addr)
+ 		return;
+ 	}
+ 
++	free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));
++
+ 	/* Finally remove it */
+ 	o = remove_vm_area((void *)addr);
+ 	BUG_ON(p != o || o == NULL);
+@@ -259,6 +336,35 @@ void iounmap(volatile void __iomem *addr)
+ }
+ EXPORT_SYMBOL(iounmap);
+ 
++/*
++ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
++ * access
++ */
++void *xlate_dev_mem_ptr(unsigned long phys)
++{
++	void *addr;
++	unsigned long start = phys & PAGE_MASK;
++
++	/* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
++	if (page_is_ram(start >> PAGE_SHIFT))
++		return __va(phys);
++
++	addr = (void *)ioremap(start, PAGE_SIZE);
++	if (addr)
++		addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
++
++	return addr;
++}
++
++void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
++{
++	if (page_is_ram(phys >> PAGE_SHIFT))
++		return;
++
++	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
++	return;
++}
++
+ #ifdef CONFIG_X86_32
+ 
+ int __initdata early_ioremap_debug;
+@@ -272,8 +378,8 @@ static int __init early_ioremap_debug_setup(char *str)
+ early_param("early_ioremap_debug", early_ioremap_debug_setup);
+ 
+ static __initdata int after_paging_init;
+-static __initdata pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
+-				__attribute__((aligned(PAGE_SIZE)));
++static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
++		__section(.bss.page_aligned);
+ 
+ static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+ {
+@@ -330,7 +436,7 @@ void __init early_ioremap_clear(void)
+ 
+ 	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+ 	pmd_clear(pmd);
+-	paravirt_release_pt(__pa(bm_pte) >> PAGE_SHIFT);
++	paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT);
+ 	__flush_tlb_all();
+ }
+ 
+diff --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/k8topology_64.c
+index 7a2ebce..86808e6 100644
+--- a/arch/x86/mm/k8topology_64.c
++++ b/arch/x86/mm/k8topology_64.c
+@@ -164,7 +164,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
+ 	if (!found)
+ 		return -1;
+ 
+-	memnode_shift = compute_hash_shift(nodes, 8);
++	memnode_shift = compute_hash_shift(nodes, 8, NULL);
+ 	if (memnode_shift < 0) {
+ 		printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n");
+ 		return -1;
+diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
+index 16b82ad..9a68922 100644
+--- a/arch/x86/mm/numa_64.c
++++ b/arch/x86/mm/numa_64.c
+@@ -31,13 +31,15 @@ bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+ 
+ struct memnode memnode;
+ 
++#ifdef CONFIG_SMP
+ int x86_cpu_to_node_map_init[NR_CPUS] = {
+ 	[0 ... NR_CPUS-1] = NUMA_NO_NODE
+ };
+ void *x86_cpu_to_node_map_early_ptr;
++EXPORT_SYMBOL(x86_cpu_to_node_map_early_ptr);
++#endif
+ DEFINE_PER_CPU(int, x86_cpu_to_node_map) = NUMA_NO_NODE;
+ EXPORT_PER_CPU_SYMBOL(x86_cpu_to_node_map);
+-EXPORT_SYMBOL(x86_cpu_to_node_map_early_ptr);
+ 
+ s16 apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
+ 	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+@@ -58,7 +60,7 @@ unsigned long __initdata nodemap_size;
+  * -1 if node overlap or lost ram (shift too big)
+  */
+ static int __init populate_memnodemap(const struct bootnode *nodes,
+-				      int numnodes, int shift)
++				      int numnodes, int shift, int *nodeids)
+ {
+ 	unsigned long addr, end;
+ 	int i, res = -1;
+@@ -74,7 +76,12 @@ static int __init populate_memnodemap(const struct bootnode *nodes,
+ 		do {
+ 			if (memnodemap[addr >> shift] != NUMA_NO_NODE)
+ 				return -1;
+-			memnodemap[addr >> shift] = i;
++
++			if (!nodeids)
++				memnodemap[addr >> shift] = i;
++			else
++				memnodemap[addr >> shift] = nodeids[i];
++
+ 			addr += (1UL << shift);
+ 		} while (addr < end);
+ 		res = 1;
+@@ -137,7 +144,8 @@ static int __init extract_lsb_from_nodes(const struct bootnode *nodes,
+ 	return i;
+ }
+ 
+-int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
++int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
++			      int *nodeids)
+ {
+ 	int shift;
+ 
+@@ -147,7 +155,7 @@ int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
+ 	printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
+ 		shift);
+ 
+-	if (populate_memnodemap(nodes, numnodes, shift) != 1) {
++	if (populate_memnodemap(nodes, numnodes, shift, nodeids) != 1) {
+ 		printk(KERN_INFO "Your memory is not aligned you need to "
+ 		       "rebuild your kernel with a bigger NODEMAPSIZE "
+ 		       "shift=%d\n", shift);
+@@ -378,9 +386,10 @@ static int __init split_nodes_by_size(struct bootnode *nodes, u64 *addr,
+  * Sets up the system RAM area from start_pfn to end_pfn according to the
+  * numa=fake command-line option.
+  */
++static struct bootnode nodes[MAX_NUMNODES] __initdata;
++
+ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
+ {
+-	struct bootnode nodes[MAX_NUMNODES];
+ 	u64 size, addr = start_pfn << PAGE_SHIFT;
+ 	u64 max_addr = end_pfn << PAGE_SHIFT;
+ 	int num_nodes = 0, num = 0, coeff_flag, coeff = -1, i;
+@@ -460,7 +469,7 @@ done:
+ 		}
+ 	}
+ out:
+-	memnode_shift = compute_hash_shift(nodes, num_nodes);
++	memnode_shift = compute_hash_shift(nodes, num_nodes, NULL);
+ 	if (memnode_shift < 0) {
+ 		memnode_shift = 0;
+ 		printk(KERN_ERR "No NUMA hash function found.  NUMA emulation "
+@@ -548,8 +557,6 @@ void __cpuinit numa_set_node(int cpu, int node)
+ {
+ 	int *cpu_to_node_map = x86_cpu_to_node_map_early_ptr;
+ 
+-	cpu_pda(cpu)->nodenumber = node;
+-
+ 	if(cpu_to_node_map)
+ 		cpu_to_node_map[cpu] = node;
+ 	else if(per_cpu_offset(cpu))
+diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
+index 7b79f6b..bd5e05c 100644
+--- a/arch/x86/mm/pageattr.c
++++ b/arch/x86/mm/pageattr.c
+@@ -9,6 +9,8 @@
+ #include <linux/slab.h>
+ #include <linux/mm.h>
+ #include <linux/interrupt.h>
++#include <linux/seq_file.h>
++#include <linux/debugfs.h>
+ 
+ #include <asm/e820.h>
+ #include <asm/processor.h>
+@@ -17,6 +19,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+ #include <asm/proto.h>
++#include <asm/pat.h>
+ 
+ /*
+  * The current flushing context - we pass it instead of 5 arguments:
+@@ -28,6 +31,7 @@ struct cpa_data {
+ 	int		numpages;
+ 	int		flushtlb;
+ 	unsigned long	pfn;
++	unsigned	force_split : 1;
+ };
+ 
+ #ifdef CONFIG_X86_64
+@@ -259,6 +263,9 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
+ 	int i, do_split = 1;
+ 	unsigned int level;
+ 
++	if (cpa->force_split)
++		return 1;
++
+ 	spin_lock_irqsave(&pgd_lock, flags);
+ 	/*
+ 	 * Check for races, another CPU might have split this page
+@@ -476,9 +483,7 @@ static int split_large_page(pte_t *kpte, unsigned long address)
+ 		goto out_unlock;
+ 
+ 	pbase = (pte_t *)page_address(base);
+-#ifdef CONFIG_X86_32
+-	paravirt_alloc_pt(&init_mm, page_to_pfn(base));
+-#endif
++	paravirt_alloc_pte(&init_mm, page_to_pfn(base));
+ 	ref_prot = pte_pgprot(pte_clrhuge(*kpte));
+ 
+ #ifdef CONFIG_X86_64
+@@ -535,7 +540,7 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
+ repeat:
+ 	kpte = lookup_address(address, &level);
+ 	if (!kpte)
+-		return primary ? -EINVAL : 0;
++		return 0;
+ 
+ 	old_pte = *kpte;
+ 	if (!pte_val(old_pte)) {
+@@ -693,7 +698,8 @@ static inline int cache_attr(pgprot_t attr)
+ }
+ 
+ static int change_page_attr_set_clr(unsigned long addr, int numpages,
+-				    pgprot_t mask_set, pgprot_t mask_clr)
++				    pgprot_t mask_set, pgprot_t mask_clr,
++				    int force_split)
+ {
+ 	struct cpa_data cpa;
+ 	int ret, cache, checkalias;
+@@ -704,7 +710,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
+ 	 */
+ 	mask_set = canon_pgprot(mask_set);
+ 	mask_clr = canon_pgprot(mask_clr);
+-	if (!pgprot_val(mask_set) && !pgprot_val(mask_clr))
++	if (!pgprot_val(mask_set) && !pgprot_val(mask_clr) && !force_split)
+ 		return 0;
+ 
+ 	/* Ensure we are PAGE_SIZE aligned */
+@@ -721,6 +727,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
+ 	cpa.mask_set = mask_set;
+ 	cpa.mask_clr = mask_clr;
+ 	cpa.flushtlb = 0;
++	cpa.force_split = force_split;
+ 
+ 	/* No alias checking for _NX bit modifications */
+ 	checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
+@@ -759,26 +766,61 @@ out:
+ static inline int change_page_attr_set(unsigned long addr, int numpages,
+ 				       pgprot_t mask)
+ {
+-	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0));
++	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0);
+ }
+ 
+ static inline int change_page_attr_clear(unsigned long addr, int numpages,
+ 					 pgprot_t mask)
+ {
+-	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask);
++	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0);
+ }
+ 
+-int set_memory_uc(unsigned long addr, int numpages)
++int _set_memory_uc(unsigned long addr, int numpages)
+ {
+ 	return change_page_attr_set(addr, numpages,
+-				    __pgprot(_PAGE_PCD));
++				    __pgprot(_PAGE_CACHE_UC));
++}
++
++int set_memory_uc(unsigned long addr, int numpages)
++{
++	if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
++	                    _PAGE_CACHE_UC, NULL))
++		return -EINVAL;
++
++	return _set_memory_uc(addr, numpages);
+ }
+ EXPORT_SYMBOL(set_memory_uc);
+ 
+-int set_memory_wb(unsigned long addr, int numpages)
++int _set_memory_wc(unsigned long addr, int numpages)
++{
++	return change_page_attr_set(addr, numpages,
++				    __pgprot(_PAGE_CACHE_WC));
++}
++
++int set_memory_wc(unsigned long addr, int numpages)
++{
++	if (!pat_wc_enabled)
++		return set_memory_uc(addr, numpages);
++
++	if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
++		_PAGE_CACHE_WC, NULL))
++		return -EINVAL;
++
++	return _set_memory_wc(addr, numpages);
++}
++EXPORT_SYMBOL(set_memory_wc);
++
++int _set_memory_wb(unsigned long addr, int numpages)
+ {
+ 	return change_page_attr_clear(addr, numpages,
+-				      __pgprot(_PAGE_PCD | _PAGE_PWT));
++				      __pgprot(_PAGE_CACHE_MASK));
++}
++
++int set_memory_wb(unsigned long addr, int numpages)
++{
++	free_memtype(addr, addr + numpages * PAGE_SIZE);
++
++	return _set_memory_wb(addr, numpages);
+ }
+ EXPORT_SYMBOL(set_memory_wb);
+ 
+@@ -809,6 +851,12 @@ int set_memory_np(unsigned long addr, int numpages)
+ 	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT));
+ }
+ 
++int set_memory_4k(unsigned long addr, int numpages)
++{
++	return change_page_attr_set_clr(addr, numpages, __pgprot(0),
++					__pgprot(0), 1);
++}
++
+ int set_pages_uc(struct page *page, int numpages)
+ {
+ 	unsigned long addr = (unsigned long)page_address(page);
+@@ -918,6 +966,45 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
+ 	cpa_fill_pool(NULL);
+ }
+ 
++#ifdef CONFIG_DEBUG_FS
++static int dpa_show(struct seq_file *m, void *v)
++{
++	seq_puts(m, "DEBUG_PAGEALLOC\n");
++	seq_printf(m, "pool_size     : %lu\n", pool_size);
++	seq_printf(m, "pool_pages    : %lu\n", pool_pages);
++	seq_printf(m, "pool_low      : %lu\n", pool_low);
++	seq_printf(m, "pool_used     : %lu\n", pool_used);
++	seq_printf(m, "pool_failed   : %lu\n", pool_failed);
++
++	return 0;
++}
++
++static int dpa_open(struct inode *inode, struct file *filp)
++{
++	return single_open(filp, dpa_show, NULL);
++}
++
++static const struct file_operations dpa_fops = {
++	.open		= dpa_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
++
++static int __init debug_pagealloc_proc_init(void)
++{
++	struct dentry *de;
++
++	de = debugfs_create_file("debug_pagealloc", 0600, NULL, NULL,
++				 &dpa_fops);
++	if (!de)
++		return -ENOMEM;
++
++	return 0;
++}
++__initcall(debug_pagealloc_proc_init);
++#endif
++
+ #ifdef CONFIG_HIBERNATION
+ 
+ bool kernel_page_present(struct page *page)
+diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
+new file mode 100644
+index 0000000..9851265
+--- /dev/null
++++ b/arch/x86/mm/pat.c
+@@ -0,0 +1,568 @@
++/*
++ * Handle caching attributes in page tables (PAT)
++ *
++ * Authors: Venkatesh Pallipadi <venkatesh.pallipadi at intel.com>
++ *          Suresh B Siddha <suresh.b.siddha at intel.com>
++ *
++ * Loosely based on earlier PAT patchset from Eric Biederman and Andi Kleen.
++ */
++
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/gfp.h>
++#include <linux/fs.h>
++#include <linux/bootmem.h>
++
++#include <asm/msr.h>
++#include <asm/tlbflush.h>
++#include <asm/processor.h>
++#include <asm/pgtable.h>
++#include <asm/pat.h>
++#include <asm/e820.h>
++#include <asm/cacheflush.h>
++#include <asm/fcntl.h>
++#include <asm/mtrr.h>
++#include <asm/io.h>
++
++int pat_wc_enabled = 1;
++
++static u64 __read_mostly boot_pat_state;
++
++static int nopat(char *str)
++{
++	pat_wc_enabled = 0;
++	printk(KERN_INFO "x86: PAT support disabled.\n");
++
++	return 0;
++}
++early_param("nopat", nopat);
++
++static int pat_known_cpu(void)
++{
++	if (!pat_wc_enabled)
++		return 0;
++
++	if (cpu_has_pat)
++		return 1;
++
++	pat_wc_enabled = 0;
++	printk(KERN_INFO "CPU and/or kernel does not support PAT.\n");
++	return 0;
++}
++
++enum {
++	PAT_UC = 0,		/* uncached */
++	PAT_WC = 1,		/* Write combining */
++	PAT_WT = 4,		/* Write Through */
++	PAT_WP = 5,		/* Write Protected */
++	PAT_WB = 6,		/* Write Back (default) */
++	PAT_UC_MINUS = 7,	/* UC, but can be overriden by MTRR */
++};
++
++#define PAT(x,y)	((u64)PAT_ ## y << ((x)*8))
++
++void pat_init(void)
++{
++	u64 pat;
++
++#ifndef CONFIG_X86_PAT
++	nopat(NULL);
++#endif
++
++	/* Boot CPU enables PAT based on CPU feature */
++	if (!smp_processor_id() && !pat_known_cpu())
++		return;
++
++	/* APs enable PAT iff boot CPU has enabled it before */
++	if (smp_processor_id() && !pat_wc_enabled)
++		return;
++
++	/* Set PWT to Write-Combining. All other bits stay the same */
++	/*
++	 * PTE encoding used in Linux:
++	 *      PAT
++	 *      |PCD
++	 *      ||PWT
++	 *      |||
++	 *      000 WB		_PAGE_CACHE_WB
++	 *      001 WC		_PAGE_CACHE_WC
++	 *      010 UC-		_PAGE_CACHE_UC_MINUS
++	 *      011 UC		_PAGE_CACHE_UC
++	 * PAT bit unused
++	 */
++	pat = PAT(0,WB) | PAT(1,WC) | PAT(2,UC_MINUS) | PAT(3,UC) |
++	      PAT(4,WB) | PAT(5,WC) | PAT(6,UC_MINUS) | PAT(7,UC);
++
++	/* Boot CPU check */
++	if (!smp_processor_id()) {
++		rdmsrl(MSR_IA32_CR_PAT, boot_pat_state);
++	}
++
++	wrmsrl(MSR_IA32_CR_PAT, pat);
++	printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n",
++	       smp_processor_id(), boot_pat_state, pat);
++}
++
++#undef PAT
++
++static char *cattr_name(unsigned long flags)
++{
++	switch (flags & _PAGE_CACHE_MASK) {
++		case _PAGE_CACHE_UC:		return "uncached";
++		case _PAGE_CACHE_UC_MINUS:	return "uncached-minus";
++		case _PAGE_CACHE_WB:		return "write-back";
++		case _PAGE_CACHE_WC:		return "write-combining";
++		default:			return "broken";
++	}
++}
++
++/*
++ * The global memtype list keeps track of memory type for specific
++ * physical memory areas. Conflicting memory types in different
++ * mappings can cause CPU cache corruption. To avoid this we keep track.
++ *
++ * The list is sorted based on starting address and can contain multiple
++ * entries for each address (this allows reference counting for overlapping
++ * areas). All the aliases have the same cache attributes of course.
++ * Zero attributes are represented as holes.
++ *
++ * Currently the data structure is a list because the number of mappings
++ * are expected to be relatively small. If this should be a problem
++ * it could be changed to a rbtree or similar.
++ *
++ * memtype_lock protects the whole list.
++ */
++
++struct memtype {
++	u64 start;
++	u64 end;
++	unsigned long type;
++	struct list_head nd;
++};
++
++static LIST_HEAD(memtype_list);
++static DEFINE_SPINLOCK(memtype_lock); 	/* protects memtype list */
++
++/*
++ * Does intersection of PAT memory type and MTRR memory type and returns
++ * the resulting memory type as PAT understands it.
++ * (Type in pat and mtrr will not have same value)
++ * The intersection is based on "Effective Memory Type" tables in IA-32
++ * SDM vol 3a
++ */
++static int pat_x_mtrr_type(u64 start, u64 end, unsigned long prot,
++				unsigned long *ret_prot)
++{
++	unsigned long pat_type;
++	u8 mtrr_type;
++
++	mtrr_type = mtrr_type_lookup(start, end);
++	if (mtrr_type == 0xFF) {		/* MTRR not enabled */
++		*ret_prot = prot;
++		return 0;
++	}
++	if (mtrr_type == 0xFE) {		/* MTRR match error */
++		*ret_prot = _PAGE_CACHE_UC;
++		return -1;
++	}
++	if (mtrr_type != MTRR_TYPE_UNCACHABLE &&
++	    mtrr_type != MTRR_TYPE_WRBACK &&
++	    mtrr_type != MTRR_TYPE_WRCOMB) {	/* MTRR type unhandled */
++		*ret_prot = _PAGE_CACHE_UC;
++		return -1;
++	}
++
++	pat_type = prot & _PAGE_CACHE_MASK;
++	prot &= (~_PAGE_CACHE_MASK);
++
++	/* Currently doing intersection by hand. Optimize it later. */
++	if (pat_type == _PAGE_CACHE_WC) {
++		*ret_prot = prot | _PAGE_CACHE_WC;
++	} else if (pat_type == _PAGE_CACHE_UC_MINUS) {
++		*ret_prot = prot | _PAGE_CACHE_UC_MINUS;
++	} else if (pat_type == _PAGE_CACHE_UC ||
++	           mtrr_type == MTRR_TYPE_UNCACHABLE) {
++		*ret_prot = prot | _PAGE_CACHE_UC;
++	} else if (mtrr_type == MTRR_TYPE_WRCOMB) {
++		*ret_prot = prot | _PAGE_CACHE_WC;
++	} else {
++		*ret_prot = prot | _PAGE_CACHE_WB;
++	}
++
++	return 0;
++}
++
++/*
++ * req_type typically has one of the:
++ * - _PAGE_CACHE_WB
++ * - _PAGE_CACHE_WC
++ * - _PAGE_CACHE_UC_MINUS
++ * - _PAGE_CACHE_UC
++ *
++ * req_type will have a special case value '-1', when requester want to inherit
++ * the memory type from mtrr (if WB), existing PAT, defaulting to UC_MINUS.
++ *
++ * If ret_type is NULL, function will return an error if it cannot reserve the
++ * region with req_type. If ret_type is non-null, function will return
++ * available type in ret_type in case of no error. In case of any error
++ * it will return a negative return value.
++ */
++int reserve_memtype(u64 start, u64 end, unsigned long req_type,
++			unsigned long *ret_type)
++{
++	struct memtype *new_entry = NULL;
++	struct memtype *parse;
++	unsigned long actual_type;
++	int err = 0;
++
++	/* Only track when pat_wc_enabled */
++	if (!pat_wc_enabled) {
++		/* This is identical to page table setting without PAT */
++		if (ret_type) {
++			if (req_type == -1) {
++				*ret_type = _PAGE_CACHE_WB;
++			} else {
++				*ret_type = req_type;
++			}
++		}
++		return 0;
++	}
++
++	/* Low ISA region is always mapped WB in page table. No need to track */
++	if (start >= ISA_START_ADDRESS && (end - 1) <= ISA_END_ADDRESS) {
++		if (ret_type)
++			*ret_type = _PAGE_CACHE_WB;
++
++		return 0;
++	}
++
++	if (req_type == -1) {
++		/*
++		 * Special case where caller wants to inherit from mtrr or
++		 * existing pat mapping, defaulting to UC_MINUS in case of
++		 * no match.
++		 */
++		u8 mtrr_type = mtrr_type_lookup(start, end);
++		if (mtrr_type == 0xFE) { /* MTRR match error */
++			err = -1;
++		}
++
++		if (mtrr_type == MTRR_TYPE_WRBACK) {
++			req_type = _PAGE_CACHE_WB;
++			actual_type = _PAGE_CACHE_WB;
++		} else {
++			req_type = _PAGE_CACHE_UC_MINUS;
++			actual_type = _PAGE_CACHE_UC_MINUS;
++		}
++	} else {
++		req_type &= _PAGE_CACHE_MASK;
++		err = pat_x_mtrr_type(start, end, req_type, &actual_type);
++	}
++
++	if (err) {
++		if (ret_type)
++			*ret_type = actual_type;
++
++		return -EINVAL;
++	}
++
++	new_entry  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
++	if (!new_entry)
++		return -ENOMEM;
++
++	new_entry->start = start;
++	new_entry->end = end;
++	new_entry->type = actual_type;
++
++	if (ret_type)
++		*ret_type = actual_type;
++
++	spin_lock(&memtype_lock);
++
++	/* Search for existing mapping that overlaps the current range */
++	list_for_each_entry(parse, &memtype_list, nd) {
++		struct memtype *saved_ptr;
++
++		if (parse->start >= end) {
++			pr_debug("New Entry\n");
++			list_add(&new_entry->nd, parse->nd.prev);
++			new_entry = NULL;
++			break;
++		}
++
++		if (start <= parse->start && end >= parse->start) {
++			if (actual_type != parse->type && ret_type) {
++				actual_type = parse->type;
++				*ret_type = actual_type;
++				new_entry->type = actual_type;
++			}
++
++			if (actual_type != parse->type) {
++				printk(
++		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++					current->comm, current->pid,
++					start, end,
++					cattr_name(actual_type),
++					cattr_name(parse->type));
++				err = -EBUSY;
++				break;
++			}
++
++			saved_ptr = parse;
++			/*
++			 * Check to see whether the request overlaps more
++			 * than one entry in the list
++			 */
++			list_for_each_entry_continue(parse, &memtype_list, nd) {
++				if (end <= parse->start) {
++					break;
++				}
++
++				if (actual_type != parse->type) {
++					printk(
++		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++						current->comm, current->pid,
++						start, end,
++						cattr_name(actual_type),
++						cattr_name(parse->type));
++					err = -EBUSY;
++					break;
++				}
++			}
++
++			if (err) {
++				break;
++			}
++
++			pr_debug("Overlap at 0x%Lx-0x%Lx\n",
++			       saved_ptr->start, saved_ptr->end);
++			/* No conflict. Go ahead and add this new entry */
++			list_add(&new_entry->nd, saved_ptr->nd.prev);
++			new_entry = NULL;
++			break;
++		}
++
++		if (start < parse->end) {
++			if (actual_type != parse->type && ret_type) {
++				actual_type = parse->type;
++				*ret_type = actual_type;
++				new_entry->type = actual_type;
++			}
++
++			if (actual_type != parse->type) {
++				printk(
++		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++					current->comm, current->pid,
++					start, end,
++					cattr_name(actual_type),
++					cattr_name(parse->type));
++				err = -EBUSY;
++				break;
++			}
++
++			saved_ptr = parse;
++			/*
++			 * Check to see whether the request overlaps more
++			 * than one entry in the list
++			 */
++			list_for_each_entry_continue(parse, &memtype_list, nd) {
++				if (end <= parse->start) {
++					break;
++				}
++
++				if (actual_type != parse->type) {
++					printk(
++		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++						current->comm, current->pid,
++						start, end,
++						cattr_name(actual_type),
++						cattr_name(parse->type));
++					err = -EBUSY;
++					break;
++				}
++			}
++
++			if (err) {
++				break;
++			}
++
++			printk(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n",
++			       saved_ptr->start, saved_ptr->end);
++			/* No conflict. Go ahead and add this new entry */
++			list_add(&new_entry->nd, &saved_ptr->nd);
++			new_entry = NULL;
++			break;
++		}
++	}
++
++	if (err) {
++		printk(KERN_INFO
++	"reserve_memtype failed 0x%Lx-0x%Lx, track %s, req %s\n",
++			start, end, cattr_name(new_entry->type),
++			cattr_name(req_type));
++		kfree(new_entry);
++		spin_unlock(&memtype_lock);
++		return err;
++	}
++
++	if (new_entry) {
++		/* No conflict. Not yet added to the list. Add to the tail */
++		list_add_tail(&new_entry->nd, &memtype_list);
++		pr_debug("New Entry\n");
++	}
++
++	if (ret_type) {
++		pr_debug(
++	"reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
++			start, end, cattr_name(actual_type),
++			cattr_name(req_type), cattr_name(*ret_type));
++	} else {
++		pr_debug(
++	"reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n",
++			start, end, cattr_name(actual_type),
++			cattr_name(req_type));
++	}
++
++	spin_unlock(&memtype_lock);
++	return err;
++}
++
++int free_memtype(u64 start, u64 end)
++{
++	struct memtype *ml;
++	int err = -EINVAL;
++
++	/* Only track when pat_wc_enabled */
++	if (!pat_wc_enabled) {
++		return 0;
++	}
++
++	/* Low ISA region is always mapped WB. No need to track */
++	if (start >= ISA_START_ADDRESS && end <= ISA_END_ADDRESS) {
++		return 0;
++	}
++
++	spin_lock(&memtype_lock);
++	list_for_each_entry(ml, &memtype_list, nd) {
++		if (ml->start == start && ml->end == end) {
++			list_del(&ml->nd);
++			kfree(ml);
++			err = 0;
++			break;
++		}
++	}
++	spin_unlock(&memtype_lock);
++
++	if (err) {
++		printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
++			current->comm, current->pid, start, end);
++	}
++
++	pr_debug("free_memtype request 0x%Lx-0x%Lx\n", start, end);
++	return err;
++}
++
++
++/*
++ * /dev/mem mmap interface. The memtype used for mapping varies:
++ * - Use UC for mappings with O_SYNC flag
++ * - Without O_SYNC flag, if there is any conflict in reserve_memtype,
++ *   inherit the memtype from existing mapping.
++ * - Else use UC_MINUS memtype (for backward compatibility with existing
++ *   X drivers.
++ */
++pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
++				unsigned long size, pgprot_t vma_prot)
++{
++	return vma_prot;
++}
++
++int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
++				unsigned long size, pgprot_t *vma_prot)
++{
++	u64 offset = ((u64) pfn) << PAGE_SHIFT;
++	unsigned long flags = _PAGE_CACHE_UC_MINUS;
++	unsigned long ret_flags;
++	int retval;
++
++	if (file->f_flags & O_SYNC) {
++		flags = _PAGE_CACHE_UC;
++	}
++
++#ifdef CONFIG_X86_32
++	/*
++	 * On the PPro and successors, the MTRRs are used to set
++	 * memory types for physical addresses outside main memory,
++	 * so blindly setting UC or PWT on those pages is wrong.
++	 * For Pentiums and earlier, the surround logic should disable
++	 * caching for the high addresses through the KEN pin, but
++	 * we maintain the tradition of paranoia in this code.
++	 */
++	if (!pat_wc_enabled &&
++	    ! ( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
++		test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
++		test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
++		test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability)) &&
++	   (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
++		flags = _PAGE_CACHE_UC;
++	}
++#endif
++
++	/*
++	 * With O_SYNC, we can only take UC mapping. Fail if we cannot.
++	 * Without O_SYNC, we want to get
++	 * - WB for WB-able memory and no other conflicting mappings
++	 * - UC_MINUS for non-WB-able memory with no other conflicting mappings
++	 * - Inherit from confliting mappings otherwise
++	 */
++	if (flags != _PAGE_CACHE_UC_MINUS) {
++		retval = reserve_memtype(offset, offset + size, flags, NULL);
++	} else {
++		retval = reserve_memtype(offset, offset + size, -1, &ret_flags);
++	}
++
++	if (retval < 0)
++		return 0;
++
++	flags = ret_flags;
++
++	if (pfn <= max_pfn_mapped &&
++            ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
++		free_memtype(offset, offset + size);
++		printk(KERN_INFO
++		"%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
++			current->comm, current->pid,
++			cattr_name(flags),
++			offset, offset + size);
++		return 0;
++	}
++
++	*vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
++			     flags);
++	return 1;
++}
++
++void map_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
++{
++	u64 addr = (u64)pfn << PAGE_SHIFT;
++	unsigned long flags;
++	unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
++
++	reserve_memtype(addr, addr + size, want_flags, &flags);
++	if (flags != want_flags) {
++		printk(KERN_INFO
++		"%s:%d /dev/mem expected mapping type %s for %Lx-%Lx, got %s\n",
++			current->comm, current->pid,
++			cattr_name(want_flags),
++			addr, addr + size,
++			cattr_name(flags));
++	}
++}
++
++void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
++{
++	u64 addr = (u64)pfn << PAGE_SHIFT;
++
++	free_memtype(addr, addr + size);
++}
++
+diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
+new file mode 100644
+index 0000000..5015976
+--- /dev/null
++++ b/arch/x86/mm/pgtable.c
+@@ -0,0 +1,276 @@
++#include <linux/mm.h>
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/tlb.h>
++
++pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
++{
++	return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
++}
++
++pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++	struct page *pte;
++
++#ifdef CONFIG_HIGHPTE
++	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
++#else
++	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++#endif
++	if (pte)
++		pgtable_page_ctor(pte);
++	return pte;
++}
++
++void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
++{
++	pgtable_page_dtor(pte);
++	paravirt_release_pte(page_to_pfn(pte));
++	tlb_remove_page(tlb, pte);
++}
++
++#if PAGETABLE_LEVELS > 2
++void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
++{
++	paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
++	tlb_remove_page(tlb, virt_to_page(pmd));
++}
++
++#if PAGETABLE_LEVELS > 3
++void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
++{
++	paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
++	tlb_remove_page(tlb, virt_to_page(pud));
++}
++#endif	/* PAGETABLE_LEVELS > 3 */
++#endif	/* PAGETABLE_LEVELS > 2 */
++
++static inline void pgd_list_add(pgd_t *pgd)
++{
++	struct page *page = virt_to_page(pgd);
++
++	list_add(&page->lru, &pgd_list);
++}
++
++static inline void pgd_list_del(pgd_t *pgd)
++{
++	struct page *page = virt_to_page(pgd);
++
++	list_del(&page->lru);
++}
++
++#define UNSHARED_PTRS_PER_PGD				\
++	(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
++
++static void pgd_ctor(void *p)
++{
++	pgd_t *pgd = p;
++	unsigned long flags;
++
++	/* Clear usermode parts of PGD */
++	memset(pgd, 0, KERNEL_PGD_BOUNDARY*sizeof(pgd_t));
++
++	spin_lock_irqsave(&pgd_lock, flags);
++
++	/* If the pgd points to a shared pagetable level (either the
++	   ptes in non-PAE, or shared PMD in PAE), then just copy the
++	   references from swapper_pg_dir. */
++	if (PAGETABLE_LEVELS == 2 ||
++	    (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD) ||
++	    PAGETABLE_LEVELS == 4) {
++		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)
++		pgd_list_add(pgd);
++
++	spin_unlock_irqrestore(&pgd_lock, flags);
++}
++
++static void pgd_dtor(void *pgd)
++{
++	unsigned long flags; /* can be called from interrupt context */
++
++	if (SHARED_KERNEL_PMD)
++		return;
++
++	spin_lock_irqsave(&pgd_lock, flags);
++	pgd_list_del(pgd);
++	spin_unlock_irqrestore(&pgd_lock, flags);
++}
++
++/*
++ * List of all pgd's needed for non-PAE so it can invalidate entries
++ * in both cached and uncached pgd's; not needed for PAE since the
++ * kernel pmd is shared. If PAE were not to share the pmd a similar
++ * tactic would be needed. This is essentially codepath-based locking
++ * against pageattr.c; it is the unique case in which a valid change
++ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
++ * vmalloc faults work because attached pagetables are never freed.
++ * -- wli
++ */
++
++#ifdef CONFIG_X86_PAE
++/*
++ * Mop up any pmd pages which may still be attached to the pgd.
++ * Normally they will be freed by munmap/exit_mmap, but any pmd we
++ * preallocate which never got a corresponding vma will need to be
++ * freed manually.
++ */
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
++{
++	int i;
++
++	for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
++		pgd_t pgd = pgdp[i];
++
++		if (pgd_val(pgd) != 0) {
++			pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
++
++			pgdp[i] = native_make_pgd(0);
++
++			paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
++			pmd_free(mm, pmd);
++		}
++	}
++}
++
++/*
++ * In PAE mode, we need to do a cr3 reload (=tlb flush) when
++ * updating the top-level pagetable entries to guarantee the
++ * processor notices the update.  Since this is expensive, and
++ * all 4 top-level entries are used almost immediately in a
++ * new process's life, we just pre-populate them here.
++ *
++ * Also, if we're in a paravirt environment where the kernel pmd is
++ * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
++ * and initialize the kernel pmds here.
++ */
++static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
++{
++	pud_t *pud;
++	unsigned long addr;
++	int i;
++
++	pud = pud_offset(pgd, 0);
++ 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
++	     i++, pud++, addr += PUD_SIZE) {
++		pmd_t *pmd = pmd_alloc_one(mm, addr);
++
++		if (!pmd) {
++			pgd_mop_up_pmds(mm, pgd);
++			return 0;
++		}
++
++		if (i >= KERNEL_PGD_BOUNDARY)
++			memcpy(pmd, (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
++			       sizeof(pmd_t) * PTRS_PER_PMD);
++
++		pud_populate(mm, pud, pmd);
++	}
++
++	return 1;
++}
++
++void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
++{
++	paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
++
++	/* Note: almost everything apart from _PAGE_PRESENT is
++	   reserved at the pmd (PDPT) level. */
++	set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
++
++	/*
++	 * According to Intel App note "TLBs, Paging-Structure Caches,
++	 * and Their Invalidation", April 2007, document 317080-001,
++	 * section 8.1: in PAE mode we explicitly have to flush the
++	 * TLB via cr3 if the top-level pgd is changed...
++	 */
++	if (mm == current->active_mm)
++		write_cr3(read_cr3());
++}
++#else  /* !CONFIG_X86_PAE */
++/* No need to prepopulate any pagetable entries in non-PAE modes. */
++static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
++{
++	return 1;
++}
++
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgd)
++{
++}
++#endif	/* CONFIG_X86_PAE */
++
++pgd_t *pgd_alloc(struct mm_struct *mm)
++{
++	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
++
++	/* so that alloc_pmd can use it */
++	mm->pgd = pgd;
++	if (pgd)
++		pgd_ctor(pgd);
++
++	if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
++		pgd_dtor(pgd);
++		free_page((unsigned long)pgd);
++		pgd = NULL;
++	}
++
++	return pgd;
++}
++
++void pgd_free(struct mm_struct *mm, pgd_t *pgd)
++{
++	pgd_mop_up_pmds(mm, pgd);
++	pgd_dtor(pgd);
++	free_page((unsigned long)pgd);
++}
++
++int ptep_set_access_flags(struct vm_area_struct *vma,
++			  unsigned long address, pte_t *ptep,
++			  pte_t entry, int dirty)
++{
++	int changed = !pte_same(*ptep, entry);
++
++	if (changed && dirty) {
++		*ptep = entry;
++		pte_update_defer(vma->vm_mm, address, ptep);
++		flush_tlb_page(vma, address);
++	}
++
++	return changed;
++}
++
++int ptep_test_and_clear_young(struct vm_area_struct *vma,
++			      unsigned long addr, pte_t *ptep)
++{
++	int ret = 0;
++
++	if (pte_young(*ptep))
++		ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,
++					 &ptep->pte);
++
++	if (ret)
++		pte_update(vma->vm_mm, addr, ptep);
++
++	return ret;
++}
++
++int ptep_clear_flush_young(struct vm_area_struct *vma,
++			   unsigned long address, pte_t *ptep)
++{
++	int young;
++
++	young = ptep_test_and_clear_young(vma, address, ptep);
++	if (young)
++		flush_tlb_page(vma, address);
++
++	return young;
++}
+diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
+index 2f9e9af..9ee007b 100644
+--- a/arch/x86/mm/pgtable_32.c
++++ b/arch/x86/mm/pgtable_32.c
+@@ -1,7 +1,3 @@
+-/*
+- *  linux/arch/i386/mm/pgtable.c
+- */
+-
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+@@ -36,7 +32,6 @@ void show_mem(void)
+ 
+ 	printk(KERN_INFO "Mem-info:\n");
+ 	show_free_areas();
+-	printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ 	for_each_online_pgdat(pgdat) {
+ 		pgdat_resize_lock(pgdat, &flags);
+ 		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+@@ -178,206 +173,9 @@ void reserve_top_address(unsigned long reserve)
+ 	__VMALLOC_RESERVE += reserve;
+ }
+ 
+-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+-{
+-	return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+-}
+-
+-pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
++int pmd_bad(pmd_t pmd)
+ {
+-	struct page *pte;
++	WARN_ON_ONCE(pmd_bad_v1(pmd) != pmd_bad_v2(pmd));
+ 
+-#ifdef CONFIG_HIGHPTE
+-	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
+-#else
+-	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+-#endif
+-	if (pte)
+-		pgtable_page_ctor(pte);
+-	return pte;
++	return pmd_bad_v1(pmd);
+ }
+-
+-/*
+- * List of all pgd's needed for non-PAE so it can invalidate entries
+- * in both cached and uncached pgd's; not needed for PAE since the
+- * kernel pmd is shared. If PAE were not to share the pmd a similar
+- * tactic would be needed. This is essentially codepath-based locking
+- * against pageattr.c; it is the unique case in which a valid change
+- * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+- * vmalloc faults work because attached pagetables are never freed.
+- * -- wli
+- */
+-static inline void pgd_list_add(pgd_t *pgd)
+-{
+-	struct page *page = virt_to_page(pgd);
+-
+-	list_add(&page->lru, &pgd_list);
+-}
+-
+-static inline void pgd_list_del(pgd_t *pgd)
+-{
+-	struct page *page = virt_to_page(pgd);
+-
+-	list_del(&page->lru);
+-}
+-
+-#define UNSHARED_PTRS_PER_PGD				\
+-	(SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
+-
+-static void pgd_ctor(void *p)
+-{
+-	pgd_t *pgd = p;
+-	unsigned long flags;
+-
+-	/* Clear usermode parts of PGD */
+-	memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-
+-	/* If the pgd points to a shared pagetable level (either the
+-	   ptes in non-PAE, or shared PMD in PAE), then just copy the
+-	   references from swapper_pg_dir. */
+-	if (PAGETABLE_LEVELS == 2 ||
+-	    (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD)) {
+-		clone_pgd_range(pgd + USER_PTRS_PER_PGD,
+-				swapper_pg_dir + USER_PTRS_PER_PGD,
+-				KERNEL_PGD_PTRS);
+-		paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+-					__pa(swapper_pg_dir) >> PAGE_SHIFT,
+-					USER_PTRS_PER_PGD,
+-					KERNEL_PGD_PTRS);
+-	}
+-
+-	/* list required to sync kernel mapping updates */
+-	if (!SHARED_KERNEL_PMD)
+-		pgd_list_add(pgd);
+-
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-static void pgd_dtor(void *pgd)
+-{
+-	unsigned long flags; /* can be called from interrupt context */
+-
+-	if (SHARED_KERNEL_PMD)
+-		return;
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	pgd_list_del(pgd);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-#ifdef CONFIG_X86_PAE
+-/*
+- * Mop up any pmd pages which may still be attached to the pgd.
+- * Normally they will be freed by munmap/exit_mmap, but any pmd we
+- * preallocate which never got a corresponding vma will need to be
+- * freed manually.
+- */
+-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+-{
+-	int i;
+-
+-	for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
+-		pgd_t pgd = pgdp[i];
+-
+-		if (pgd_val(pgd) != 0) {
+-			pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
+-
+-			pgdp[i] = native_make_pgd(0);
+-
+-			paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
+-			pmd_free(mm, pmd);
+-		}
+-	}
+-}
+-
+-/*
+- * In PAE mode, we need to do a cr3 reload (=tlb flush) when
+- * updating the top-level pagetable entries to guarantee the
+- * processor notices the update.  Since this is expensive, and
+- * all 4 top-level entries are used almost immediately in a
+- * new process's life, we just pre-populate them here.
+- *
+- * Also, if we're in a paravirt environment where the kernel pmd is
+- * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
+- * and initialize the kernel pmds here.
+- */
+-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+-{
+-	pud_t *pud;
+-	unsigned long addr;
+-	int i;
+-
+-	pud = pud_offset(pgd, 0);
+- 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
+-	     i++, pud++, addr += PUD_SIZE) {
+-		pmd_t *pmd = pmd_alloc_one(mm, addr);
+-
+-		if (!pmd) {
+-			pgd_mop_up_pmds(mm, pgd);
+-			return 0;
+-		}
+-
+-		if (i >= USER_PTRS_PER_PGD)
+-			memcpy(pmd, (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
+-			       sizeof(pmd_t) * PTRS_PER_PMD);
+-
+-		pud_populate(mm, pud, pmd);
+-	}
+-
+-	return 1;
+-}
+-#else  /* !CONFIG_X86_PAE */
+-/* No need to prepopulate any pagetable entries in non-PAE modes. */
+-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+-{
+-	return 1;
+-}
+-
+-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+-{
+-}
+-#endif	/* CONFIG_X86_PAE */
+-
+-pgd_t *pgd_alloc(struct mm_struct *mm)
+-{
+-	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+-
+-	/* so that alloc_pd can use it */
+-	mm->pgd = pgd;
+-	if (pgd)
+-		pgd_ctor(pgd);
+-
+-	if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
+-		pgd_dtor(pgd);
+-		free_page((unsigned long)pgd);
+-		pgd = NULL;
+-	}
+-
+-	return pgd;
+-}
+-
+-void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+-{
+-	pgd_mop_up_pmds(mm, pgd);
+-	pgd_dtor(pgd);
+-	free_page((unsigned long)pgd);
+-}
+-
+-void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
+-{
+-	pgtable_page_dtor(pte);
+-	paravirt_release_pt(page_to_pfn(pte));
+-	tlb_remove_page(tlb, pte);
+-}
+-
+-#ifdef CONFIG_X86_PAE
+-
+-void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+-{
+-	paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+-	tlb_remove_page(tlb, virt_to_page(pmd));
+-}
+-
+-#endif
+diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
+index 845001c..3890234 100644
+--- a/arch/x86/mm/srat_64.c
++++ b/arch/x86/mm/srat_64.c
+@@ -20,6 +20,7 @@
+ #include <asm/proto.h>
+ #include <asm/numa.h>
+ #include <asm/e820.h>
++#include <asm/genapic.h>
+ 
+ int acpi_numa __initdata;
+ 
+@@ -31,6 +32,10 @@ static struct bootnode nodes_add[MAX_NUMNODES];
+ static int found_add_area __initdata;
+ int hotadd_percent __initdata = 0;
+ 
++static int num_node_memblks __initdata;
++static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata;
++static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata;
++
+ /* Too small nodes confuse the VM badly. Usually they result
+    from BIOS bugs. */
+ #define NODE_MIN_SIZE (4*1024*1024)
+@@ -40,17 +45,17 @@ static __init int setup_node(int pxm)
+ 	return acpi_map_pxm_to_node(pxm);
+ }
+ 
+-static __init int conflicting_nodes(unsigned long start, unsigned long end)
++static __init int conflicting_memblks(unsigned long start, unsigned long end)
+ {
+ 	int i;
+-	for_each_node_mask(i, nodes_parsed) {
+-		struct bootnode *nd = &nodes[i];
++	for (i = 0; i < num_node_memblks; i++) {
++		struct bootnode *nd = &node_memblk_range[i];
+ 		if (nd->start == nd->end)
+ 			continue;
+ 		if (nd->end > start && nd->start < end)
+-			return i;
++			return memblk_nodeid[i];
+ 		if (nd->end == end && nd->start == start)
+-			return i;
++			return memblk_nodeid[i];
+ 	}
+ 	return -1;
+ }
+@@ -132,7 +137,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
+ 	int pxm, node;
+ 	int apic_id;
+ 
+-	apic_id = pa->apic_id;
+ 	if (srat_disabled())
+ 		return;
+ 	if (pa->header.length != sizeof(struct acpi_srat_cpu_affinity)) {
+@@ -148,13 +152,18 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
+ 		bad_srat();
+ 		return;
+ 	}
++
++	if (is_uv_system())
++		apic_id = (pa->apic_id << 8) | pa->local_sapic_eid;
++	else
++		apic_id = pa->apic_id;
+ 	apicid_to_node[apic_id] = node;
+ 	acpi_numa = 1;
+ 	printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
+ 	       pxm, apic_id, node);
+ }
+ 
+-int update_end_of_memory(unsigned long end) {return -1;}
++static int update_end_of_memory(unsigned long end) {return -1;}
+ static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
+ #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
+ static inline int save_add_info(void) {return 1;}
+@@ -253,7 +262,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
+ 		bad_srat();
+ 		return;
+ 	}
+-	i = conflicting_nodes(start, end);
++	i = conflicting_memblks(start, end);
+ 	if (i == node) {
+ 		printk(KERN_WARNING
+ 		"SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
+@@ -278,10 +287,10 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
+ 			nd->end = end;
+ 	}
+ 
+-	printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
+-	       nd->start, nd->end);
+-	e820_register_active_regions(node, nd->start >> PAGE_SHIFT,
+-						nd->end >> PAGE_SHIFT);
++	printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
++	       start, end);
++	e820_register_active_regions(node, start >> PAGE_SHIFT,
++				     end >> PAGE_SHIFT);
+ 	push_node_boundaries(node, nd->start >> PAGE_SHIFT,
+ 						nd->end >> PAGE_SHIFT);
+ 
+@@ -293,6 +302,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
+ 		if ((nd->start | nd->end) == 0)
+ 			node_clear(node, nodes_parsed);
+ 	}
++
++	node_memblk_range[num_node_memblks].start = start;
++	node_memblk_range[num_node_memblks].end = end;
++	memblk_nodeid[num_node_memblks] = node;
++	num_node_memblks++;
+ }
+ 
+ /* Sanity check to catch more bad SRATs (they are amazingly common).
+@@ -363,7 +377,8 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
+ 		return -1;
+ 	}
+ 
+-	memnode_shift = compute_hash_shift(nodes, MAX_NUMNODES);
++	memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
++					   memblk_nodeid);
+ 	if (memnode_shift < 0) {
+ 		printk(KERN_ERR
+ 		     "SRAT: No NUMA node hash function found. Contact maintainer\n");
+diff --git a/arch/x86/oprofile/init.c b/arch/x86/oprofile/init.c
+index 5341d48..cdfe4c5 100644
+--- a/arch/x86/oprofile/init.c
++++ b/arch/x86/oprofile/init.c
+@@ -10,18 +10,19 @@
+ #include <linux/oprofile.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
+- 
+-/* We support CPUs that have performance counters like the Pentium Pro
++
++/*
++ * We support CPUs that have performance counters like the Pentium Pro
+  * with the NMI mode driver.
+  */
+- 
+-extern int op_nmi_init(struct oprofile_operations * ops);
+-extern int op_nmi_timer_init(struct oprofile_operations * ops);
++
++extern int op_nmi_init(struct oprofile_operations *ops);
++extern int op_nmi_timer_init(struct oprofile_operations *ops);
+ extern void op_nmi_exit(void);
+ extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
+ 
+ 
+-int __init oprofile_arch_init(struct oprofile_operations * ops)
++int __init oprofile_arch_init(struct oprofile_operations *ops)
+ {
+ 	int ret;
+ 
+diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
+index 1f11cf0..cc48d3f 100644
+--- a/arch/x86/oprofile/nmi_int.c
++++ b/arch/x86/oprofile/nmi_int.c
+@@ -23,8 +23,8 @@
+ #include "op_x86_model.h"
+ 
+ static struct op_x86_model_spec const *model;
+-static struct op_msrs cpu_msrs[NR_CPUS];
+-static unsigned long saved_lvtpc[NR_CPUS];
++static DEFINE_PER_CPU(struct op_msrs, cpu_msrs);
++static DEFINE_PER_CPU(unsigned long, saved_lvtpc);
+ 
+ static int nmi_start(void);
+ static void nmi_stop(void);
+@@ -89,7 +89,7 @@ static int profile_exceptions_notify(struct notifier_block *self,
+ 
+ 	switch (val) {
+ 	case DIE_NMI:
+-		if (model->check_ctrs(args->regs, &cpu_msrs[cpu]))
++		if (model->check_ctrs(args->regs, &per_cpu(cpu_msrs, cpu)))
+ 			ret = NOTIFY_STOP;
+ 		break;
+ 	default:
+@@ -126,7 +126,7 @@ static void nmi_cpu_save_registers(struct op_msrs *msrs)
+ static void nmi_save_registers(void *dummy)
+ {
+ 	int cpu = smp_processor_id();
+-	struct op_msrs *msrs = &cpu_msrs[cpu];
++	struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
+ 	nmi_cpu_save_registers(msrs);
+ }
+ 
+@@ -134,10 +134,10 @@ static void free_msrs(void)
+ {
+ 	int i;
+ 	for_each_possible_cpu(i) {
+-		kfree(cpu_msrs[i].counters);
+-		cpu_msrs[i].counters = NULL;
+-		kfree(cpu_msrs[i].controls);
+-		cpu_msrs[i].controls = NULL;
++		kfree(per_cpu(cpu_msrs, i).counters);
++		per_cpu(cpu_msrs, i).counters = NULL;
++		kfree(per_cpu(cpu_msrs, i).controls);
++		per_cpu(cpu_msrs, i).controls = NULL;
+ 	}
+ }
+ 
+@@ -149,13 +149,15 @@ static int allocate_msrs(void)
+ 
+ 	int i;
+ 	for_each_possible_cpu(i) {
+-		cpu_msrs[i].counters = kmalloc(counters_size, GFP_KERNEL);
+-		if (!cpu_msrs[i].counters) {
++		per_cpu(cpu_msrs, i).counters = kmalloc(counters_size,
++								GFP_KERNEL);
++		if (!per_cpu(cpu_msrs, i).counters) {
+ 			success = 0;
+ 			break;
+ 		}
+-		cpu_msrs[i].controls = kmalloc(controls_size, GFP_KERNEL);
+-		if (!cpu_msrs[i].controls) {
++		per_cpu(cpu_msrs, i).controls = kmalloc(controls_size,
++								GFP_KERNEL);
++		if (!per_cpu(cpu_msrs, i).controls) {
+ 			success = 0;
+ 			break;
+ 		}
+@@ -170,11 +172,11 @@ static int allocate_msrs(void)
+ static void nmi_cpu_setup(void *dummy)
+ {
+ 	int cpu = smp_processor_id();
+-	struct op_msrs *msrs = &cpu_msrs[cpu];
++	struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
+ 	spin_lock(&oprofilefs_lock);
+ 	model->setup_ctrs(msrs);
+ 	spin_unlock(&oprofilefs_lock);
+-	saved_lvtpc[cpu] = apic_read(APIC_LVTPC);
++	per_cpu(saved_lvtpc, cpu) = apic_read(APIC_LVTPC);
+ 	apic_write(APIC_LVTPC, APIC_DM_NMI);
+ }
+ 
+@@ -203,13 +205,15 @@ static int nmi_setup(void)
+ 	 */
+ 
+ 	/* Assume saved/restored counters are the same on all CPUs */
+-	model->fill_in_addresses(&cpu_msrs[0]);
++	model->fill_in_addresses(&per_cpu(cpu_msrs, 0));
+ 	for_each_possible_cpu(cpu) {
+ 		if (cpu != 0) {
+-			memcpy(cpu_msrs[cpu].counters, cpu_msrs[0].counters,
++			memcpy(per_cpu(cpu_msrs, cpu).counters,
++				per_cpu(cpu_msrs, 0).counters,
+ 				sizeof(struct op_msr) * model->num_counters);
+ 
+-			memcpy(cpu_msrs[cpu].controls, cpu_msrs[0].controls,
++			memcpy(per_cpu(cpu_msrs, cpu).controls,
++				per_cpu(cpu_msrs, 0).controls,
+ 				sizeof(struct op_msr) * model->num_controls);
+ 		}
+ 
+@@ -249,7 +253,7 @@ static void nmi_cpu_shutdown(void *dummy)
+ {
+ 	unsigned int v;
+ 	int cpu = smp_processor_id();
+-	struct op_msrs *msrs = &cpu_msrs[cpu];
++	struct op_msrs *msrs = &__get_cpu_var(cpu_msrs);
+ 
+ 	/* restoring APIC_LVTPC can trigger an apic error because the delivery
+ 	 * mode and vector nr combination can be illegal. That's by design: on
+@@ -258,23 +262,24 @@ static void nmi_cpu_shutdown(void *dummy)
+ 	 */
+ 	v = apic_read(APIC_LVTERR);
+ 	apic_write(APIC_LVTERR, v | APIC_LVT_MASKED);
+-	apic_write(APIC_LVTPC, saved_lvtpc[cpu]);
++	apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu));
+ 	apic_write(APIC_LVTERR, v);
+ 	nmi_restore_registers(msrs);
+ }
+ 
+ static void nmi_shutdown(void)
+ {
++	struct op_msrs *msrs = &__get_cpu_var(cpu_msrs);
+ 	nmi_enabled = 0;
+ 	on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1);
+ 	unregister_die_notifier(&profile_exceptions_nb);
+-	model->shutdown(cpu_msrs);
++	model->shutdown(msrs);
+ 	free_msrs();
+ }
+ 
+ static void nmi_cpu_start(void *dummy)
+ {
+-	struct op_msrs const *msrs = &cpu_msrs[smp_processor_id()];
++	struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
+ 	model->start(msrs);
+ }
+ 
+@@ -286,7 +291,7 @@ static int nmi_start(void)
+ 
+ static void nmi_cpu_stop(void *dummy)
+ {
+-	struct op_msrs const *msrs = &cpu_msrs[smp_processor_id()];
++	struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
+ 	model->stop(msrs);
+ }
+ 
+diff --git a/arch/x86/oprofile/nmi_timer_int.c b/arch/x86/oprofile/nmi_timer_int.c
+index 1418e36..e3ecb71 100644
+--- a/arch/x86/oprofile/nmi_timer_int.c
++++ b/arch/x86/oprofile/nmi_timer_int.c
+@@ -17,14 +17,14 @@
+ #include <asm/nmi.h>
+ #include <asm/apic.h>
+ #include <asm/ptrace.h>
+- 
++
+ static int profile_timer_exceptions_notify(struct notifier_block *self,
+ 					   unsigned long val, void *data)
+ {
+ 	struct die_args *args = (struct die_args *)data;
+ 	int ret = NOTIFY_DONE;
+ 
+-	switch(val) {
++	switch (val) {
+ 	case DIE_NMI:
+ 		oprofile_add_sample(args->regs, 0);
+ 		ret = NOTIFY_STOP;
+@@ -56,7 +56,7 @@ static void timer_stop(void)
+ }
+ 
+ 
+-int __init op_nmi_timer_init(struct oprofile_operations * ops)
++int __init op_nmi_timer_init(struct oprofile_operations *ops)
+ {
+ 	if ((nmi_watchdog != NMI_IO_APIC) || (atomic_read(&nmi_active) <= 0))
+ 		return -ENODEV;
+diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c
+index c3ee433..3d53487 100644
+--- a/arch/x86/oprofile/op_model_athlon.c
++++ b/arch/x86/oprofile/op_model_athlon.c
+@@ -1,4 +1,4 @@
+-/**
++/*
+  * @file op_model_athlon.h
+  * athlon / K7 / K8 / Family 10h model-specific MSR operations
+  *
+@@ -14,28 +14,28 @@
+ #include <asm/ptrace.h>
+ #include <asm/msr.h>
+ #include <asm/nmi.h>
+- 
++
+ #include "op_x86_model.h"
+ #include "op_counter.h"
+ 
+ #define NUM_COUNTERS 4
+ #define NUM_CONTROLS 4
+ 
+-#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
+-#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
+-#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1);} while (0)
++#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0)
++#define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0)
++#define CTR_WRITE(l, msrs, c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1); } while (0)
+ #define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
+ 
+-#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
+-#define CTRL_READ(l,h,msrs,c) do {rdmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
+-#define CTRL_WRITE(l,h,msrs,c) do {wrmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
++#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0)
++#define CTRL_READ(l, h, msrs, c) do {rdmsr(msrs->controls[(c)].addr, (l), (h)); } while (0)
++#define CTRL_WRITE(l, h, msrs, c) do {wrmsr(msrs->controls[(c)].addr, (l), (h)); } while (0)
+ #define CTRL_SET_ACTIVE(n) (n |= (1<<22))
+ #define CTRL_SET_INACTIVE(n) (n &= ~(1<<22))
+ #define CTRL_CLEAR_LO(x) (x &= (1<<21))
+ #define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0)
+ #define CTRL_SET_ENABLE(val) (val |= 1<<20)
+-#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16))
+-#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17))
++#define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16))
++#define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17))
+ #define CTRL_SET_UM(val, m) (val |= (m << 8))
+ #define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff))
+ #define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf))
+@@ -43,19 +43,19 @@
+ #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8))
+ 
+ static unsigned long reset_value[NUM_COUNTERS];
+- 
++
+ static void athlon_fill_in_addresses(struct op_msrs * const msrs)
+ {
+ 	int i;
+ 
+-	for (i=0; i < NUM_COUNTERS; i++) {
++	for (i = 0; i < NUM_COUNTERS; i++) {
+ 		if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
+ 			msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
+ 		else
+ 			msrs->counters[i].addr = 0;
+ 	}
+ 
+-	for (i=0; i < NUM_CONTROLS; i++) {
++	for (i = 0; i < NUM_CONTROLS; i++) {
+ 		if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
+ 			msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
+ 		else
+@@ -63,15 +63,15 @@ static void athlon_fill_in_addresses(struct op_msrs * const msrs)
+ 	}
+ }
+ 
+- 
++
+ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
+ {
+ 	unsigned int low, high;
+ 	int i;
+- 
++
+ 	/* clear all counters */
+ 	for (i = 0 ; i < NUM_CONTROLS; ++i) {
+-		if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
++		if (unlikely(!CTRL_IS_RESERVED(msrs, i)))
+ 			continue;
+ 		CTRL_READ(low, high, msrs, i);
+ 		CTRL_CLEAR_LO(low);
+@@ -81,14 +81,14 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
+ 
+ 	/* avoid a false detection of ctr overflows in NMI handler */
+ 	for (i = 0; i < NUM_COUNTERS; ++i) {
+-		if (unlikely(!CTR_IS_RESERVED(msrs,i)))
++		if (unlikely(!CTR_IS_RESERVED(msrs, i)))
+ 			continue;
+ 		CTR_WRITE(1, msrs, i);
+ 	}
+ 
+ 	/* enable active counters */
+ 	for (i = 0; i < NUM_COUNTERS; ++i) {
+-		if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs,i))) {
++		if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) {
+ 			reset_value[i] = counter_config[i].count;
+ 
+ 			CTR_WRITE(counter_config[i].count, msrs, i);
+@@ -112,7 +112,7 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
+ 	}
+ }
+ 
+- 
++
+ static int athlon_check_ctrs(struct pt_regs * const regs,
+ 			     struct op_msrs const * const msrs)
+ {
+@@ -133,7 +133,7 @@ static int athlon_check_ctrs(struct pt_regs * const regs,
+ 	return 1;
+ }
+ 
+- 
++
+ static void athlon_start(struct op_msrs const * const msrs)
+ {
+ 	unsigned int low, high;
+@@ -150,7 +150,7 @@ static void athlon_start(struct op_msrs const * const msrs)
+ 
+ static void athlon_stop(struct op_msrs const * const msrs)
+ {
+-	unsigned int low,high;
++	unsigned int low, high;
+ 	int i;
+ 
+ 	/* Subtle: stop on all counters to avoid race with
+@@ -169,11 +169,11 @@ static void athlon_shutdown(struct op_msrs const * const msrs)
+ 	int i;
+ 
+ 	for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+-		if (CTR_IS_RESERVED(msrs,i))
++		if (CTR_IS_RESERVED(msrs, i))
+ 			release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+ 	}
+ 	for (i = 0 ; i < NUM_CONTROLS ; ++i) {
+-		if (CTRL_IS_RESERVED(msrs,i))
++		if (CTRL_IS_RESERVED(msrs, i))
+ 			release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+ 	}
+ }
+diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c
+index c554f52..eff431f 100644
+--- a/arch/x86/oprofile/op_model_ppro.c
++++ b/arch/x86/oprofile/op_model_ppro.c
+@@ -1,4 +1,4 @@
+-/**
++/*
+  * @file op_model_ppro.h
+  * pentium pro / P6 model-specific MSR operations
+  *
+@@ -15,45 +15,45 @@
+ #include <asm/msr.h>
+ #include <asm/apic.h>
+ #include <asm/nmi.h>
+- 
++
+ #include "op_x86_model.h"
+ #include "op_counter.h"
+ 
+ #define NUM_COUNTERS 2
+ #define NUM_CONTROLS 2
+ 
+-#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
+-#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
+-#define CTR_32BIT_WRITE(l,msrs,c)	\
+-	do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), 0);} while (0)
++#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0)
++#define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0)
++#define CTR_32BIT_WRITE(l, msrs, c)	\
++	do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), 0); } while (0)
+ #define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
+ 
+-#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
+-#define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
+-#define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
++#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0)
++#define CTRL_READ(l, h, msrs, c) do {rdmsr((msrs->controls[(c)].addr), (l), (h)); } while (0)
++#define CTRL_WRITE(l, h, msrs, c) do {wrmsr((msrs->controls[(c)].addr), (l), (h)); } while (0)
+ #define CTRL_SET_ACTIVE(n) (n |= (1<<22))
+ #define CTRL_SET_INACTIVE(n) (n &= ~(1<<22))
+ #define CTRL_CLEAR(x) (x &= (1<<21))
+ #define CTRL_SET_ENABLE(val) (val |= 1<<20)
+-#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16))
+-#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17))
++#define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16))
++#define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17))
+ #define CTRL_SET_UM(val, m) (val |= (m << 8))
+ #define CTRL_SET_EVENT(val, e) (val |= e)
+ 
+ static unsigned long reset_value[NUM_COUNTERS];
+- 
++
+ static void ppro_fill_in_addresses(struct op_msrs * const msrs)
+ {
+ 	int i;
+ 
+-	for (i=0; i < NUM_COUNTERS; i++) {
++	for (i = 0; i < NUM_COUNTERS; i++) {
+ 		if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
+ 			msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+ 		else
+ 			msrs->counters[i].addr = 0;
+ 	}
+-	
+-	for (i=0; i < NUM_CONTROLS; i++) {
++
++	for (i = 0; i < NUM_CONTROLS; i++) {
+ 		if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i))
+ 			msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+ 		else
+@@ -69,23 +69,23 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
+ 
+ 	/* clear all counters */
+ 	for (i = 0 ; i < NUM_CONTROLS; ++i) {
+-		if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
++		if (unlikely(!CTRL_IS_RESERVED(msrs, i)))
+ 			continue;
+ 		CTRL_READ(low, high, msrs, i);
+ 		CTRL_CLEAR(low);
+ 		CTRL_WRITE(low, high, msrs, i);
+ 	}
+-	
++
+ 	/* avoid a false detection of ctr overflows in NMI handler */
+ 	for (i = 0; i < NUM_COUNTERS; ++i) {
+-		if (unlikely(!CTR_IS_RESERVED(msrs,i)))
++		if (unlikely(!CTR_IS_RESERVED(msrs, i)))
+ 			continue;
+ 		CTR_32BIT_WRITE(1, msrs, i);
+ 	}
+ 
+ 	/* enable active counters */
+ 	for (i = 0; i < NUM_COUNTERS; ++i) {
+-		if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs,i))) {
++		if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) {
+ 			reset_value[i] = counter_config[i].count;
+ 
+ 			CTR_32BIT_WRITE(counter_config[i].count, msrs, i);
+@@ -104,13 +104,13 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
+ 	}
+ }
+ 
+- 
++
+ static int ppro_check_ctrs(struct pt_regs * const regs,
+ 			   struct op_msrs const * const msrs)
+ {
+ 	unsigned int low, high;
+ 	int i;
+- 
++
+ 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
+ 		if (!reset_value[i])
+ 			continue;
+@@ -135,10 +135,10 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
+ 	return 1;
+ }
+ 
+- 
++
+ static void ppro_start(struct op_msrs const * const msrs)
+ {
+-	unsigned int low,high;
++	unsigned int low, high;
+ 	int i;
+ 
+ 	for (i = 0; i < NUM_COUNTERS; ++i) {
+@@ -153,7 +153,7 @@ static void ppro_start(struct op_msrs const * const msrs)
+ 
+ static void ppro_stop(struct op_msrs const * const msrs)
+ {
+-	unsigned int low,high;
++	unsigned int low, high;
+ 	int i;
+ 
+ 	for (i = 0; i < NUM_COUNTERS; ++i) {
+@@ -170,11 +170,11 @@ static void ppro_shutdown(struct op_msrs const * const msrs)
+ 	int i;
+ 
+ 	for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+-		if (CTR_IS_RESERVED(msrs,i))
++		if (CTR_IS_RESERVED(msrs, i))
+ 			release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
+ 	}
+ 	for (i = 0 ; i < NUM_CONTROLS ; ++i) {
+-		if (CTRL_IS_RESERVED(msrs,i))
++		if (CTRL_IS_RESERVED(msrs, i))
+ 			release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
+ 	}
+ }
+diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
+index 378136f..2664cb3 100644
+--- a/arch/x86/pci/acpi.c
++++ b/arch/x86/pci/acpi.c
+@@ -151,7 +151,7 @@ adjust_transparent_bridge_resources(struct pci_bus *bus)
+ 
+ static void
+ get_current_resources(struct acpi_device *device, int busnum,
+-			struct pci_bus *bus)
++			int domain, struct pci_bus *bus)
+ {
+ 	struct pci_root_info info;
+ 	size_t size;
+@@ -168,10 +168,10 @@ get_current_resources(struct acpi_device *device, int busnum,
+ 	if (!info.res)
+ 		goto res_alloc_fail;
+ 
+-	info.name = kmalloc(12, GFP_KERNEL);
++	info.name = kmalloc(16, GFP_KERNEL);
+ 	if (!info.name)
+ 		goto name_alloc_fail;
+-	sprintf(info.name, "PCI Bus #%02x", busnum);
++	sprintf(info.name, "PCI Bus %04x:%02x", domain, busnum);
+ 
+ 	info.res_num = 0;
+ 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
+@@ -247,7 +247,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
+ #endif
+ 
+ 	if (bus && (pci_probe & PCI_USE__CRS))
+-		get_current_resources(device, busnum, bus);
++		get_current_resources(device, busnum, domain, bus);
+ 	
+ 	return bus;
+ }
+@@ -278,8 +278,7 @@ static int __init pci_acpi_init(void)
+ 		printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
+ 		for_each_pci_dev(dev)
+ 			acpi_pci_irq_enable(dev);
+-	} else
+-		printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\".  If it helps, post a report\n");
++	}
+ 
+ #ifdef CONFIG_X86_IO_APIC
+ 	if (acpi_ioapic)
+diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
+index 7b6e3bb..75fcc29 100644
+--- a/arch/x86/pci/common.c
++++ b/arch/x86/pci/common.c
+@@ -77,59 +77,6 @@ int pcibios_scanned;
+  */
+ DEFINE_SPINLOCK(pci_config_lock);
+ 
+-/*
+- * Several buggy motherboards address only 16 devices and mirror
+- * them to next 16 IDs. We try to detect this `feature' on all
+- * primary buses (those containing host bridges as they are
+- * expected to be unique) and remove the ghost devices.
+- */
+-
+-static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
+-{
+-	struct list_head *ln, *mn;
+-	struct pci_dev *d, *e;
+-	int mirror = PCI_DEVFN(16,0);
+-	int seen_host_bridge = 0;
+-	int i;
+-
+-	DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
+-	list_for_each(ln, &b->devices) {
+-		d = pci_dev_b(ln);
+-		if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+-			seen_host_bridge++;
+-		for (mn=ln->next; mn != &b->devices; mn=mn->next) {
+-			e = pci_dev_b(mn);
+-			if (e->devfn != d->devfn + mirror ||
+-			    e->vendor != d->vendor ||
+-			    e->device != d->device ||
+-			    e->class != d->class)
+-				continue;
+-			for(i=0; i<PCI_NUM_RESOURCES; i++)
+-				if (e->resource[i].start != d->resource[i].start ||
+-				    e->resource[i].end != d->resource[i].end ||
+-				    e->resource[i].flags != d->resource[i].flags)
+-					continue;
+-			break;
+-		}
+-		if (mn == &b->devices)
+-			return;
+-	}
+-	if (!seen_host_bridge)
+-		return;
+-	printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number);
+-
+-	ln = &b->devices;
+-	while (ln->next != &b->devices) {
+-		d = pci_dev_b(ln->next);
+-		if (d->devfn >= mirror) {
+-			list_del(&d->global_list);
+-			list_del(&d->bus_list);
+-			kfree(d);
+-		} else
+-			ln = ln->next;
+-	}
+-}
+-
+ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+ {
+ 	struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
+@@ -152,7 +99,6 @@ void __devinit  pcibios_fixup_bus(struct pci_bus *b)
+ {
+ 	struct pci_dev *dev;
+ 
+-	pcibios_fixup_ghosts(b);
+ 	pci_read_bridge_bases(b);
+ 	list_for_each_entry(dev, &b->devices, bus_list)
+ 		pcibios_fixup_device_resources(dev);
+@@ -427,10 +373,6 @@ static int __init pcibios_init(void)
+ 
+ 	if (pci_bf_sort >= pci_force_bf)
+ 		pci_sort_breadthfirst();
+-#ifdef CONFIG_PCI_BIOS
+-	if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
+-		pcibios_sort();
+-#endif
+ 	return 0;
+ }
+ 
+@@ -455,9 +397,6 @@ char * __devinit  pcibios_setup(char *str)
+ 	} else if (!strcmp(str, "nobios")) {
+ 		pci_probe &= ~PCI_PROBE_BIOS;
+ 		return NULL;
+-	} else if (!strcmp(str, "nosort")) {
+-		pci_probe |= PCI_NO_SORT;
+-		return NULL;
+ 	} else if (!strcmp(str, "biosirq")) {
+ 		pci_probe |= PCI_BIOS_IRQ_SCAN;
+ 		return NULL;
+@@ -527,7 +466,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+ 	int err;
+ 
+-	if ((err = pcibios_enable_resources(dev, mask)) < 0)
++	if ((err = pci_enable_resources(dev, mask)) < 0)
+ 		return err;
+ 
+ 	if (!dev->msi_enabled)
+diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
+index 103b9df..94f6c73 100644
+--- a/arch/x86/pci/i386.c
++++ b/arch/x86/pci/i386.c
+@@ -30,6 +30,9 @@
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/errno.h>
++#include <linux/bootmem.h>
++
++#include <asm/pat.h>
+ 
+ #include "pci.h"
+ 
+@@ -238,44 +241,6 @@ void __init pcibios_resource_survey(void)
+  */
+ fs_initcall(pcibios_assign_resources);
+ 
+-int pcibios_enable_resources(struct pci_dev *dev, int mask)
+-{
+-	u16 cmd, old_cmd;
+-	int idx;
+-	struct resource *r;
+-
+-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+-	old_cmd = cmd;
+-	for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+-		/* Only set up the requested stuff */
+-		if (!(mask & (1 << idx)))
+-			continue;
+-
+-		r = &dev->resource[idx];
+-		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+-			continue;
+-		if ((idx == PCI_ROM_RESOURCE) &&
+-				(!(r->flags & IORESOURCE_ROM_ENABLE)))
+-			continue;
+-		if (!r->start && r->end) {
+-			printk(KERN_ERR "PCI: Device %s not available "
+-				"because of resource %d collisions\n",
+-				pci_name(dev), idx);
+-			return -EINVAL;
+-		}
+-		if (r->flags & IORESOURCE_IO)
+-			cmd |= PCI_COMMAND_IO;
+-		if (r->flags & IORESOURCE_MEM)
+-			cmd |= PCI_COMMAND_MEMORY;
+-	}
+-	if (cmd != old_cmd) {
+-		printk("PCI: Enabling device %s (%04x -> %04x)\n",
+-			pci_name(dev), old_cmd, cmd);
+-		pci_write_config_word(dev, PCI_COMMAND, cmd);
+-	}
+-	return 0;
+-}
+-
+ /*
+  *  If we set up a device for bus mastering, we need to check the latency
+  *  timer as certain crappy BIOSes forget to set it properly.
+@@ -297,10 +262,35 @@ void pcibios_set_master(struct pci_dev *dev)
+ 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+ }
+ 
++static void pci_unmap_page_range(struct vm_area_struct *vma)
++{
++	u64 addr = (u64)vma->vm_pgoff << PAGE_SHIFT;
++	free_memtype(addr, addr + vma->vm_end - vma->vm_start);
++}
++
++static void pci_track_mmap_page_range(struct vm_area_struct *vma)
++{
++	u64 addr = (u64)vma->vm_pgoff << PAGE_SHIFT;
++	unsigned long flags = pgprot_val(vma->vm_page_prot)
++						& _PAGE_CACHE_MASK;
++
++	reserve_memtype(addr, addr + vma->vm_end - vma->vm_start, flags, NULL);
++}
++
++static struct vm_operations_struct pci_mmap_ops = {
++	.open  = pci_track_mmap_page_range,
++	.close = pci_unmap_page_range,
++};
++
+ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ 			enum pci_mmap_state mmap_state, int write_combine)
+ {
+ 	unsigned long prot;
++	u64 addr = vma->vm_pgoff << PAGE_SHIFT;
++	unsigned long len = vma->vm_end - vma->vm_start;
++	unsigned long flags;
++	unsigned long new_flags;
++	int retval;
+ 
+ 	/* I/O space cannot be accessed via normal processor loads and
+ 	 * stores on this platform.
+@@ -308,21 +298,50 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ 	if (mmap_state == pci_mmap_io)
+ 		return -EINVAL;
+ 
+-	/* Leave vm_pgoff as-is, the PCI space address is the physical
+-	 * address on this platform.
+-	 */
+ 	prot = pgprot_val(vma->vm_page_prot);
+-	if (boot_cpu_data.x86 > 3)
+-		prot |= _PAGE_PCD | _PAGE_PWT;
++	if (pat_wc_enabled && write_combine)
++		prot |= _PAGE_CACHE_WC;
++	else if (boot_cpu_data.x86 > 3)
++		prot |= _PAGE_CACHE_UC;
++
+ 	vma->vm_page_prot = __pgprot(prot);
+ 
+-	/* Write-combine setting is ignored, it is changed via the mtrr
+-	 * interfaces on this platform.
+-	 */
++	flags = pgprot_val(vma->vm_page_prot) & _PAGE_CACHE_MASK;
++	retval = reserve_memtype(addr, addr + len, flags, &new_flags);
++	if (retval)
++		return retval;
++
++	if (flags != new_flags) {
++		/*
++		 * Do not fallback to certain memory types with certain
++		 * requested type:
++		 * - request is uncached, return cannot be write-back
++		 * - request is uncached, return cannot be write-combine
++		 * - request is write-combine, return cannot be write-back
++		 */
++		if ((flags == _PAGE_CACHE_UC &&
++		     (new_flags == _PAGE_CACHE_WB ||
++		      new_flags == _PAGE_CACHE_WC)) ||
++		    (flags == _PAGE_CACHE_WC &&
++		     new_flags == _PAGE_CACHE_WB)) {
++			free_memtype(addr, addr+len);
++			return -EINVAL;
++		}
++		flags = new_flags;
++	}
++
++	if (vma->vm_pgoff <= max_pfn_mapped &&
++	    ioremap_change_attr((unsigned long)__va(addr), len, flags)) {
++		free_memtype(addr, addr + len);
++		return -EINVAL;
++	}
++
+ 	if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ 			       vma->vm_end - vma->vm_start,
+ 			       vma->vm_page_prot))
+ 		return -EAGAIN;
+ 
++	vma->vm_ops = &pci_mmap_ops;
++
+ 	return 0;
+ }
+diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
+index a871586..579745c 100644
+--- a/arch/x86/pci/irq.c
++++ b/arch/x86/pci/irq.c
+@@ -200,7 +200,7 @@ static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+ {
+ 	static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+ 
+-	WARN_ON_ONCE(pirq >= 16);
++	WARN_ON_ONCE(pirq > 16);
+ 	return irqmap[read_config_nybble(router, 0x48, pirq-1)];
+ }
+ 
+@@ -209,7 +209,7 @@ static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
+ 	static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+ 	unsigned int val = irqmap[irq];
+ 
+-	WARN_ON_ONCE(pirq >= 16);
++	WARN_ON_ONCE(pirq > 16);
+ 	if (val) {
+ 		write_config_nybble(router, 0x48, pirq-1, val);
+ 		return 1;
+@@ -260,7 +260,7 @@ static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq
+ {
+ 	static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+ 
+-	WARN_ON_ONCE(pirq >= 5);
++	WARN_ON_ONCE(pirq > 5);
+ 	return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
+ }
+ 
+@@ -268,7 +268,7 @@ static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq
+ {
+ 	static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+ 
+-	WARN_ON_ONCE(pirq >= 5);
++	WARN_ON_ONCE(pirq > 5);
+ 	write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+ 	return 1;
+ }
+@@ -282,7 +282,7 @@ static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+ {
+ 	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+ 
+-	WARN_ON_ONCE(pirq >= 4);
++	WARN_ON_ONCE(pirq > 4);
+ 	return read_config_nybble(router,0x43, pirqmap[pirq-1]);
+ }
+ 
+@@ -290,7 +290,7 @@ static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
+ {
+ 	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+ 
+-	WARN_ON_ONCE(pirq >= 4);
++	WARN_ON_ONCE(pirq > 4);
+ 	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
+ 	return 1;
+ }
+diff --git a/arch/x86/pci/numa.c b/arch/x86/pci/numa.c
+index 55270c2..d9afbae 100644
+--- a/arch/x86/pci/numa.c
++++ b/arch/x86/pci/numa.c
+@@ -11,11 +11,41 @@
+ #define XQUAD_PORTIO_BASE 0xfe400000
+ #define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */
+ 
++int mp_bus_id_to_node[MAX_MP_BUSSES];
+ #define BUS2QUAD(global) (mp_bus_id_to_node[global])
++
++int mp_bus_id_to_local[MAX_MP_BUSSES];
+ #define BUS2LOCAL(global) (mp_bus_id_to_local[global])
++
++void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
++	struct mpc_config_translation *translation)
++{
++	int quad = translation->trans_quad;
++	int local = translation->trans_local;
++
++	mp_bus_id_to_node[m->mpc_busid] = quad;
++	mp_bus_id_to_local[m->mpc_busid] = local;
++	printk(KERN_INFO "Bus #%d is %s (node %d)\n",
++	       m->mpc_busid, name, quad);
++}
++
++int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+ #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
++void mpc_oem_pci_bus(struct mpc_config_bus *m,
++	struct mpc_config_translation *translation)
++{
++	int quad = translation->trans_quad;
++	int local = translation->trans_local;
++
++	quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
++}
++
++/* Where the IO area was mapped on multiquad, always 0 otherwise */
++void *xquad_portio;
++#ifdef CONFIG_X86_NUMAQ
++EXPORT_SYMBOL(xquad_portio);
++#endif
+ 
+-extern void *xquad_portio;    /* Where the IO area was mapped */
+ #define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
+ 
+ #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
+diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c
+index 2f7109a..37472fc 100644
+--- a/arch/x86/pci/pcbios.c
++++ b/arch/x86/pci/pcbios.c
+@@ -152,28 +152,6 @@ static int __devinit check_pcibios(void)
+ 	return 0;
+ }
+ 
+-static int __devinit pci_bios_find_device (unsigned short vendor, unsigned short device_id,
+-					unsigned short index, unsigned char *bus, unsigned char *device_fn)
+-{
+-	unsigned short bx;
+-	unsigned short ret;
+-
+-	__asm__("lcall *(%%edi); cld\n\t"
+-		"jc 1f\n\t"
+-		"xor %%ah, %%ah\n"
+-		"1:"
+-		: "=b" (bx),
+-		  "=a" (ret)
+-		: "1" (PCIBIOS_FIND_PCI_DEVICE),
+-		  "c" (device_id),
+-		  "d" (vendor),
+-		  "S" ((int) index),
+-		  "D" (&pci_indirect));
+-	*bus = (bx >> 8) & 0xff;
+-	*device_fn = bx & 0xff;
+-	return (int) (ret & 0xff00) >> 8;
+-}
+-
+ static int pci_bios_read(unsigned int seg, unsigned int bus,
+ 			 unsigned int devfn, int reg, int len, u32 *value)
+ {
+@@ -364,55 +342,6 @@ static struct pci_raw_ops * __devinit pci_find_bios(void)
+ }
+ 
+ /*
+- * Sort the device list according to PCI BIOS. Nasty hack, but since some
+- * fool forgot to define the `correct' device order in the PCI BIOS specs
+- * and we want to be (possibly bug-to-bug ;-]) compatible with older kernels
+- * which used BIOS ordering, we are bound to do this...
+- */
+-
+-void __devinit pcibios_sort(void)
+-{
+-	LIST_HEAD(sorted_devices);
+-	struct list_head *ln;
+-	struct pci_dev *dev, *d;
+-	int idx, found;
+-	unsigned char bus, devfn;
+-
+-	DBG("PCI: Sorting device list...\n");
+-	while (!list_empty(&pci_devices)) {
+-		ln = pci_devices.next;
+-		dev = pci_dev_g(ln);
+-		idx = found = 0;
+-		while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
+-			idx++;
+-			list_for_each(ln, &pci_devices) {
+-				d = pci_dev_g(ln);
+-				if (d->bus->number == bus && d->devfn == devfn) {
+-					list_move_tail(&d->global_list, &sorted_devices);
+-					if (d == dev)
+-						found = 1;
+-					break;
+-				}
+-			}
+-			if (ln == &pci_devices) {
+-				printk(KERN_WARNING "PCI: BIOS reporting unknown device %02x:%02x\n", bus, devfn);
+-				/*
+-				 * We must not continue scanning as several buggy BIOSes
+-				 * return garbage after the last device. Grr.
+-				 */
+-				break;
+-			}
+-		}
+-		if (!found) {
+-			printk(KERN_WARNING "PCI: Device %s not found by BIOS\n",
+-				pci_name(dev));
+-			list_move_tail(&dev->global_list, &sorted_devices);
+-		}
+-	}
+-	list_splice(&sorted_devices, &pci_devices);
+-}
+-
+-/*
+  *  BIOS Functions for IRQ Routing
+  */
+ 
+@@ -495,7 +424,6 @@ void __init pci_pcbios_init(void)
+ {
+ 	if ((pci_probe & PCI_PROBE_BIOS) 
+ 		&& ((raw_pci_ops = pci_find_bios()))) {
+-		pci_probe |= PCI_BIOS_SORT;
+ 		pci_bios_present = 1;
+ 	}
+ }
+diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
+index 3431518..c4bddae 100644
+--- a/arch/x86/pci/pci.h
++++ b/arch/x86/pci/pci.h
+@@ -19,8 +19,6 @@
+ #define PCI_PROBE_MASK		0x000f
+ #define PCI_PROBE_NOEARLY	0x0010
+ 
+-#define PCI_NO_SORT		0x0100
+-#define PCI_BIOS_SORT		0x0200
+ #define PCI_NO_CHECKS		0x0400
+ #define PCI_USE_PIRQ_MASK	0x0800
+ #define PCI_ASSIGN_ROMS		0x1000
+@@ -44,7 +42,6 @@ enum pci_bf_sort_state {
+ extern unsigned int pcibios_max_latency;
+ 
+ void pcibios_resource_survey(void);
+-int pcibios_enable_resources(struct pci_dev *, int);
+ 
+ /* pci-pc.c */
+ 
+@@ -101,7 +98,6 @@ extern int pci_direct_probe(void);
+ extern void pci_direct_init(int type);
+ extern void pci_pcbios_init(void);
+ extern void pci_mmcfg_init(int type);
+-extern void pcibios_sort(void);
+ 
+ /* pci-mmconfig.c */
+ 
+diff --git a/arch/x86/power/cpu_32.c b/arch/x86/power/cpu_32.c
+index 7f9c6da..7dc5d5c 100644
+--- a/arch/x86/power/cpu_32.c
++++ b/arch/x86/power/cpu_32.c
+@@ -27,17 +27,17 @@ static void __save_processor_state(struct saved_context *ctxt)
+ 	/*
+ 	 * descriptor tables
+ 	 */
+- 	store_gdt(&ctxt->gdt);
+- 	store_idt(&ctxt->idt);
+- 	store_tr(ctxt->tr);
++	store_gdt(&ctxt->gdt);
++	store_idt(&ctxt->idt);
++	store_tr(ctxt->tr);
+ 
+ 	/*
+ 	 * segment registers
+ 	 */
+- 	savesegment(es, ctxt->es);
+- 	savesegment(fs, ctxt->fs);
+- 	savesegment(gs, ctxt->gs);
+- 	savesegment(ss, ctxt->ss);
++	savesegment(es, ctxt->es);
++	savesegment(fs, ctxt->fs);
++	savesegment(gs, ctxt->gs);
++	savesegment(ss, ctxt->ss);
+ 
+ 	/*
+ 	 * control registers
+@@ -48,10 +48,12 @@ static void __save_processor_state(struct saved_context *ctxt)
+ 	ctxt->cr4 = read_cr4();
+ }
+ 
++/* Needed by apm.c */
+ void save_processor_state(void)
+ {
+ 	__save_processor_state(&saved_context);
+ }
++EXPORT_SYMBOL(save_processor_state);
+ 
+ static void do_fpu_end(void)
+ {
+@@ -64,9 +66,14 @@ static void do_fpu_end(void)
+ static void fix_processor_context(void)
+ {
+ 	int cpu = smp_processor_id();
+-	struct tss_struct * t = &per_cpu(init_tss, cpu);
++	struct tss_struct *t = &per_cpu(init_tss, cpu);
+ 
+-	set_tss_desc(cpu,t);	/* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
++	set_tss_desc(cpu, t);	/*
++				 * This just modifies memory; should not be
++				 * necessary. But... This is necessary, because
++				 * 386 hardware has concept of busy TSS or some
++				 * similar stupidity.
++				 */
+ 
+ 	load_TR_desc();				/* This does ltr */
+ 	load_LDT(&current->active_mm->context);	/* This does lldt */
+@@ -100,16 +107,16 @@ static void __restore_processor_state(struct saved_context *ctxt)
+ 	 * now restore the descriptor tables to their proper values
+ 	 * ltr is done i fix_processor_context().
+ 	 */
+- 	load_gdt(&ctxt->gdt);
+- 	load_idt(&ctxt->idt);
++	load_gdt(&ctxt->gdt);
++	load_idt(&ctxt->idt);
+ 
+ 	/*
+ 	 * segment registers
+ 	 */
+- 	loadsegment(es, ctxt->es);
+- 	loadsegment(fs, ctxt->fs);
+- 	loadsegment(gs, ctxt->gs);
+- 	loadsegment(ss, ctxt->ss);
++	loadsegment(es, ctxt->es);
++	loadsegment(fs, ctxt->fs);
++	loadsegment(gs, ctxt->gs);
++	loadsegment(ss, ctxt->ss);
+ 
+ 	/*
+ 	 * sysenter MSRs
+@@ -123,11 +130,9 @@ static void __restore_processor_state(struct saved_context *ctxt)
+ 	mcheck_init(&boot_cpu_data);
+ }
+ 
++/* Needed by apm.c */
+ void restore_processor_state(void)
+ {
+ 	__restore_processor_state(&saved_context);
+ }
+-
+-/* Needed by apm.c */
+-EXPORT_SYMBOL(save_processor_state);
+ EXPORT_SYMBOL(restore_processor_state);
+diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
+index 0a8f474..b7ad9f8 100644
+--- a/arch/x86/vdso/Makefile
++++ b/arch/x86/vdso/Makefile
+@@ -37,9 +37,10 @@ $(obj)/%.so: OBJCOPYFLAGS := -S
+ $(obj)/%.so: $(obj)/%.so.dbg FORCE
+ 	$(call if_changed,objcopy)
+ 
+-CFL := $(PROFILING) -mcmodel=small -fPIC -g0 -O2 -fasynchronous-unwind-tables -m64
++CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
++       $(filter -g%,$(KBUILD_CFLAGS))
+ 
+-$(vobjs): KBUILD_CFLAGS = $(CFL)
++$(vobjs): KBUILD_CFLAGS += $(CFL)
+ 
+ targets += vdso-syms.lds
+ obj-$(VDSO64-y)			+= vdso-syms.lds
+diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
+index 348f134..e2af8ee 100644
+--- a/arch/x86/vdso/vdso32-setup.c
++++ b/arch/x86/vdso/vdso32-setup.c
+@@ -210,8 +210,12 @@ static int use_sysenter __read_mostly = -1;
+ /* May not be __init: called during resume */
+ void syscall32_cpu_init(void)
+ {
+-	if (use_sysenter < 0)
+-		use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL);
++	if (use_sysenter < 0) {
++		if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
++			use_sysenter = 1;
++		if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR)
++			use_sysenter = 1;
++	}
+ 
+ 	/* Load these always in case some future AMD CPU supports
+ 	   SYSENTER from compat mode too. */
+@@ -325,6 +329,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
+ 	int ret = 0;
+ 	bool compat;
+ 
++	if (vdso_enabled == VDSO_DISABLED)
++		return 0;
++
+ 	down_write(&mm->mmap_sem);
+ 
+ 	/* Test compat mode once here, in case someone
+diff --git a/arch/x86/video/fbdev.c b/arch/x86/video/fbdev.c
+index 48fb38d..4db42bf 100644
+--- a/arch/x86/video/fbdev.c
++++ b/arch/x86/video/fbdev.c
+@@ -1,5 +1,4 @@
+ /*
+- * arch/i386/video/fbdev.c - i386 Framebuffer
+  *
+  * Copyright (C) 2007 Antonino Daplas <adaplas at gmail.com>
+  *
+diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
+index 4d5f264..2e641be 100644
+--- a/arch/x86/xen/Kconfig
++++ b/arch/x86/xen/Kconfig
+@@ -6,7 +6,7 @@ config XEN
+ 	bool "Xen guest support"
+ 	select PARAVIRT
+ 	depends on X86_32
+-	depends on X86_CMPXCHG && X86_TSC && !NEED_MULTIPLE_NODES && !(X86_VISWS || X86_VOYAGER)
++	depends on X86_CMPXCHG && X86_TSC && !(X86_VISWS || X86_VOYAGER)
+ 	help
+ 	  This is the Linux Xen port.  Enabling this will allow the
+ 	  kernel to boot in a paravirtualized environment under the
+diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
+index 343df24..3d8df98 100644
+--- a/arch/x86/xen/Makefile
++++ b/arch/x86/xen/Makefile
+@@ -1,4 +1,4 @@
+-obj-y		:= enlighten.o setup.o features.o multicalls.o mmu.o \
+-			events.o time.o manage.o xen-asm.o
++obj-y		:= enlighten.o setup.o multicalls.o mmu.o \
++			time.o manage.o xen-asm.o grant-table.o
+ 
+ obj-$(CONFIG_SMP)	+= smp.o
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index 27ee26a..c8a56e4 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -25,6 +25,7 @@
+ #include <linux/mm.h>
+ #include <linux/page-flags.h>
+ #include <linux/highmem.h>
++#include <linux/console.h>
+ 
+ #include <xen/interface/xen.h>
+ #include <xen/interface/physdev.h>
+@@ -154,7 +155,8 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
+ 	if (*ax == 1)
+ 		maskedx = ~((1 << X86_FEATURE_APIC) |  /* disable APIC */
+ 			    (1 << X86_FEATURE_ACPI) |  /* disable ACPI */
+-			    (1 << X86_FEATURE_SEP)  |  /* disable SEP */
++			    (1 << X86_FEATURE_MCE)  |  /* disable MCE */
++			    (1 << X86_FEATURE_MCA)  |  /* disable MCA */
+ 			    (1 << X86_FEATURE_ACC));   /* thermal monitoring */
+ 
+ 	asm(XEN_EMULATE_PREFIX "cpuid"
+@@ -530,26 +532,37 @@ static void xen_apic_write(unsigned long reg, u32 val)
+ static void xen_flush_tlb(void)
+ {
+ 	struct mmuext_op *op;
+-	struct multicall_space mcs = xen_mc_entry(sizeof(*op));
++	struct multicall_space mcs;
++
++	preempt_disable();
++
++	mcs = xen_mc_entry(sizeof(*op));
+ 
+ 	op = mcs.args;
+ 	op->cmd = MMUEXT_TLB_FLUSH_LOCAL;
+ 	MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+ 
+ 	xen_mc_issue(PARAVIRT_LAZY_MMU);
++
++	preempt_enable();
+ }
+ 
+ static void xen_flush_tlb_single(unsigned long addr)
+ {
+ 	struct mmuext_op *op;
+-	struct multicall_space mcs = xen_mc_entry(sizeof(*op));
++	struct multicall_space mcs;
++
++	preempt_disable();
+ 
++	mcs = xen_mc_entry(sizeof(*op));
+ 	op = mcs.args;
+ 	op->cmd = MMUEXT_INVLPG_LOCAL;
+ 	op->arg1.linear_addr = addr & PAGE_MASK;
+ 	MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+ 
+ 	xen_mc_issue(PARAVIRT_LAZY_MMU);
++
++	preempt_enable();
+ }
+ 
+ static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm,
+@@ -654,15 +667,17 @@ static void xen_write_cr3(unsigned long cr3)
+ 
+ /* Early in boot, while setting up the initial pagetable, assume
+    everything is pinned. */
+-static __init void xen_alloc_pt_init(struct mm_struct *mm, u32 pfn)
++static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn)
+ {
++#ifdef CONFIG_FLATMEM
+ 	BUG_ON(mem_map);	/* should only be used early */
++#endif
+ 	make_lowmem_page_readonly(__va(PFN_PHYS(pfn)));
+ }
+ 
+-/* Early release_pt assumes that all pts are pinned, since there's
++/* Early release_pte assumes that all pts are pinned, since there's
+    only init_mm and anything attached to that is pinned. */
+-static void xen_release_pt_init(u32 pfn)
++static void xen_release_pte_init(u32 pfn)
+ {
+ 	make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
+ }
+@@ -696,12 +711,12 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level)
+ 	}
+ }
+ 
+-static void xen_alloc_pt(struct mm_struct *mm, u32 pfn)
++static void xen_alloc_pte(struct mm_struct *mm, u32 pfn)
+ {
+ 	xen_alloc_ptpage(mm, pfn, PT_PTE);
+ }
+ 
+-static void xen_alloc_pd(struct mm_struct *mm, u32 pfn)
++static void xen_alloc_pmd(struct mm_struct *mm, u32 pfn)
+ {
+ 	xen_alloc_ptpage(mm, pfn, PT_PMD);
+ }
+@@ -721,12 +736,12 @@ static void xen_release_ptpage(u32 pfn, unsigned level)
+ 	}
+ }
+ 
+-static void xen_release_pt(u32 pfn)
++static void xen_release_pte(u32 pfn)
+ {
+ 	xen_release_ptpage(pfn, PT_PTE);
+ }
+ 
+-static void xen_release_pd(u32 pfn)
++static void xen_release_pmd(u32 pfn)
+ {
+ 	xen_release_ptpage(pfn, PT_PMD);
+ }
+@@ -848,10 +863,10 @@ static __init void xen_pagetable_setup_done(pgd_t *base)
+ {
+ 	/* This will work as long as patching hasn't happened yet
+ 	   (which it hasn't) */
+-	pv_mmu_ops.alloc_pt = xen_alloc_pt;
+-	pv_mmu_ops.alloc_pd = xen_alloc_pd;
+-	pv_mmu_ops.release_pt = xen_release_pt;
+-	pv_mmu_ops.release_pd = xen_release_pd;
++	pv_mmu_ops.alloc_pte = xen_alloc_pte;
++	pv_mmu_ops.alloc_pmd = xen_alloc_pmd;
++	pv_mmu_ops.release_pte = xen_release_pte;
++	pv_mmu_ops.release_pmd = xen_release_pmd;
+ 	pv_mmu_ops.set_pte = xen_set_pte;
+ 
+ 	setup_shared_info();
+@@ -889,7 +904,6 @@ void __init xen_setup_vcpu_info_placement(void)
+ 		pv_irq_ops.irq_disable = xen_irq_disable_direct;
+ 		pv_irq_ops.irq_enable = xen_irq_enable_direct;
+ 		pv_mmu_ops.read_cr2 = xen_read_cr2_direct;
+-		pv_cpu_ops.iret = xen_iret_direct;
+ 	}
+ }
+ 
+@@ -993,8 +1007,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
+ 	.read_tsc = native_read_tsc,
+ 	.read_pmc = native_read_pmc,
+ 
+-	.iret = (void *)&hypercall_page[__HYPERVISOR_iret],
+-	.irq_enable_syscall_ret = NULL,  /* never called */
++	.iret = xen_iret,
++	.irq_enable_syscall_ret = xen_sysexit,
+ 
+ 	.load_tr_desc = paravirt_nop,
+ 	.set_ldt = xen_set_ldt,
+@@ -1059,11 +1073,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
+ 	.pte_update = paravirt_nop,
+ 	.pte_update_defer = paravirt_nop,
+ 
+-	.alloc_pt = xen_alloc_pt_init,
+-	.release_pt = xen_release_pt_init,
+-	.alloc_pd = xen_alloc_pt_init,
+-	.alloc_pd_clone = paravirt_nop,
+-	.release_pd = xen_release_pt_init,
++	.alloc_pte = xen_alloc_pte_init,
++	.release_pte = xen_release_pte_init,
++	.alloc_pmd = xen_alloc_pte_init,
++	.alloc_pmd_clone = paravirt_nop,
++	.release_pmd = xen_release_pte_init,
+ 
+ #ifdef CONFIG_HIGHPTE
+ 	.kmap_atomic_pte = xen_kmap_atomic_pte,
+@@ -1228,6 +1242,9 @@ asmlinkage void __init xen_start_kernel(void)
+ 		? __pa(xen_start_info->mod_start) : 0;
+ 	boot_params.hdr.ramdisk_size = xen_start_info->mod_len;
+ 
++	if (!is_initial_xendomain())
++		add_preferred_console("hvc", 0, NULL);
++
+ 	/* Start the world */
+ 	start_kernel();
+ }
+diff --git a/arch/x86/xen/events.c b/arch/x86/xen/events.c
+deleted file mode 100644
+index dcf613e..0000000
+--- a/arch/x86/xen/events.c
++++ /dev/null
+@@ -1,591 +0,0 @@
+-/*
+- * Xen event channels
+- *
+- * Xen models interrupts with abstract event channels.  Because each
+- * domain gets 1024 event channels, but NR_IRQ is not that large, we
+- * must dynamically map irqs<->event channels.  The event channels
+- * interface with the rest of the kernel by defining a xen interrupt
+- * chip.  When an event is recieved, it is mapped to an irq and sent
+- * through the normal interrupt processing path.
+- *
+- * There are four kinds of events which can be mapped to an event
+- * channel:
+- *
+- * 1. Inter-domain notifications.  This includes all the virtual
+- *    device events, since they're driven by front-ends in another domain
+- *    (typically dom0).
+- * 2. VIRQs, typically used for timers.  These are per-cpu events.
+- * 3. IPIs.
+- * 4. Hardware interrupts. Not supported at present.
+- *
+- * Jeremy Fitzhardinge <jeremy at xensource.com>, XenSource Inc, 2007
+- */
+-
+-#include <linux/linkage.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/module.h>
+-#include <linux/string.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/irq.h>
+-#include <asm/sync_bitops.h>
+-#include <asm/xen/hypercall.h>
+-#include <asm/xen/hypervisor.h>
+-
+-#include <xen/events.h>
+-#include <xen/interface/xen.h>
+-#include <xen/interface/event_channel.h>
+-
+-#include "xen-ops.h"
+-
+-/*
+- * This lock protects updates to the following mapping and reference-count
+- * arrays. The lock does not need to be acquired to read the mapping tables.
+- */
+-static DEFINE_SPINLOCK(irq_mapping_update_lock);
+-
+-/* IRQ <-> VIRQ mapping. */
+-static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
+-
+-/* IRQ <-> IPI mapping */
+-static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1};
+-
+-/* Packed IRQ information: binding type, sub-type index, and event channel. */
+-struct packed_irq
+-{
+-	unsigned short evtchn;
+-	unsigned char index;
+-	unsigned char type;
+-};
+-
+-static struct packed_irq irq_info[NR_IRQS];
+-
+-/* Binding types. */
+-enum {
+-	IRQT_UNBOUND,
+-	IRQT_PIRQ,
+-	IRQT_VIRQ,
+-	IRQT_IPI,
+-	IRQT_EVTCHN
+-};
+-
+-/* Convenient shorthand for packed representation of an unbound IRQ. */
+-#define IRQ_UNBOUND	mk_irq_info(IRQT_UNBOUND, 0, 0)
+-
+-static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
+-	[0 ... NR_EVENT_CHANNELS-1] = -1
+-};
+-static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
+-static u8 cpu_evtchn[NR_EVENT_CHANNELS];
+-
+-/* Reference counts for bindings to IRQs. */
+-static int irq_bindcount[NR_IRQS];
+-
+-/* Xen will never allocate port zero for any purpose. */
+-#define VALID_EVTCHN(chn)	((chn) != 0)
+-
+-/*
+- * Force a proper event-channel callback from Xen after clearing the
+- * callback mask. We do this in a very simple manner, by making a call
+- * down into Xen. The pending flag will be checked by Xen on return.
+- */
+-void force_evtchn_callback(void)
+-{
+-	(void)HYPERVISOR_xen_version(0, NULL);
+-}
+-EXPORT_SYMBOL_GPL(force_evtchn_callback);
+-
+-static struct irq_chip xen_dynamic_chip;
+-
+-/* Constructor for packed IRQ information. */
+-static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn)
+-{
+-	return (struct packed_irq) { evtchn, index, type };
+-}
+-
+-/*
+- * Accessors for packed IRQ information.
+- */
+-static inline unsigned int evtchn_from_irq(int irq)
+-{
+-	return irq_info[irq].evtchn;
+-}
+-
+-static inline unsigned int index_from_irq(int irq)
+-{
+-	return irq_info[irq].index;
+-}
+-
+-static inline unsigned int type_from_irq(int irq)
+-{
+-	return irq_info[irq].type;
+-}
+-
+-static inline unsigned long active_evtchns(unsigned int cpu,
+-					   struct shared_info *sh,
+-					   unsigned int idx)
+-{
+-	return (sh->evtchn_pending[idx] &
+-		cpu_evtchn_mask[cpu][idx] &
+-		~sh->evtchn_mask[idx]);
+-}
+-
+-static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
+-{
+-	int irq = evtchn_to_irq[chn];
+-
+-	BUG_ON(irq == -1);
+-#ifdef CONFIG_SMP
+-	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+-#endif
+-
+-	__clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
+-	__set_bit(chn, cpu_evtchn_mask[cpu]);
+-
+-	cpu_evtchn[chn] = cpu;
+-}
+-
+-static void init_evtchn_cpu_bindings(void)
+-{
+-#ifdef CONFIG_SMP
+-	int i;
+-	/* By default all event channels notify CPU#0. */
+-	for (i = 0; i < NR_IRQS; i++)
+-		irq_desc[i].affinity = cpumask_of_cpu(0);
+-#endif
+-
+-	memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
+-	memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
+-}
+-
+-static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
+-{
+-	return cpu_evtchn[evtchn];
+-}
+-
+-static inline void clear_evtchn(int port)
+-{
+-	struct shared_info *s = HYPERVISOR_shared_info;
+-	sync_clear_bit(port, &s->evtchn_pending[0]);
+-}
+-
+-static inline void set_evtchn(int port)
+-{
+-	struct shared_info *s = HYPERVISOR_shared_info;
+-	sync_set_bit(port, &s->evtchn_pending[0]);
+-}
+-
+-
+-/**
+- * notify_remote_via_irq - send event to remote end of event channel via irq
+- * @irq: irq of event channel to send event to
+- *
+- * Unlike notify_remote_via_evtchn(), this is safe to use across
+- * save/restore. Notifications on a broken connection are silently
+- * dropped.
+- */
+-void notify_remote_via_irq(int irq)
+-{
+-	int evtchn = evtchn_from_irq(irq);
+-
+-	if (VALID_EVTCHN(evtchn))
+-		notify_remote_via_evtchn(evtchn);
+-}
+-EXPORT_SYMBOL_GPL(notify_remote_via_irq);
+-
+-static void mask_evtchn(int port)
+-{
+-	struct shared_info *s = HYPERVISOR_shared_info;
+-	sync_set_bit(port, &s->evtchn_mask[0]);
+-}
+-
+-static void unmask_evtchn(int port)
+-{
+-	struct shared_info *s = HYPERVISOR_shared_info;
+-	unsigned int cpu = get_cpu();
+-
+-	BUG_ON(!irqs_disabled());
+-
+-	/* Slow path (hypercall) if this is a non-local port. */
+-	if (unlikely(cpu != cpu_from_evtchn(port))) {
+-		struct evtchn_unmask unmask = { .port = port };
+-		(void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
+-	} else {
+-		struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
+-
+-		sync_clear_bit(port, &s->evtchn_mask[0]);
+-
+-		/*
+-		 * The following is basically the equivalent of
+-		 * 'hw_resend_irq'. Just like a real IO-APIC we 'lose
+-		 * the interrupt edge' if the channel is masked.
+-		 */
+-		if (sync_test_bit(port, &s->evtchn_pending[0]) &&
+-		    !sync_test_and_set_bit(port / BITS_PER_LONG,
+-					   &vcpu_info->evtchn_pending_sel))
+-			vcpu_info->evtchn_upcall_pending = 1;
+-	}
+-
+-	put_cpu();
+-}
+-
+-static int find_unbound_irq(void)
+-{
+-	int irq;
+-
+-	/* Only allocate from dynirq range */
+-	for (irq = 0; irq < NR_IRQS; irq++)
+-		if (irq_bindcount[irq] == 0)
+-			break;
+-
+-	if (irq == NR_IRQS)
+-		panic("No available IRQ to bind to: increase NR_IRQS!\n");
+-
+-	return irq;
+-}
+-
+-int bind_evtchn_to_irq(unsigned int evtchn)
+-{
+-	int irq;
+-
+-	spin_lock(&irq_mapping_update_lock);
+-
+-	irq = evtchn_to_irq[evtchn];
+-
+-	if (irq == -1) {
+-		irq = find_unbound_irq();
+-
+-		dynamic_irq_init(irq);
+-		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
+-					      handle_level_irq, "event");
+-
+-		evtchn_to_irq[evtchn] = irq;
+-		irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
+-	}
+-
+-	irq_bindcount[irq]++;
+-
+-	spin_unlock(&irq_mapping_update_lock);
+-
+-	return irq;
+-}
+-EXPORT_SYMBOL_GPL(bind_evtchn_to_irq);
+-
+-static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
+-{
+-	struct evtchn_bind_ipi bind_ipi;
+-	int evtchn, irq;
+-
+-	spin_lock(&irq_mapping_update_lock);
+-
+-	irq = per_cpu(ipi_to_irq, cpu)[ipi];
+-	if (irq == -1) {
+-		irq = find_unbound_irq();
+-		if (irq < 0)
+-			goto out;
+-
+-		dynamic_irq_init(irq);
+-		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
+-					      handle_level_irq, "ipi");
+-
+-		bind_ipi.vcpu = cpu;
+-		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
+-						&bind_ipi) != 0)
+-			BUG();
+-		evtchn = bind_ipi.port;
+-
+-		evtchn_to_irq[evtchn] = irq;
+-		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
+-
+-		per_cpu(ipi_to_irq, cpu)[ipi] = irq;
+-
+-		bind_evtchn_to_cpu(evtchn, cpu);
+-	}
+-
+-	irq_bindcount[irq]++;
+-
+- out:
+-	spin_unlock(&irq_mapping_update_lock);
+-	return irq;
+-}
+-
+-
+-static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
+-{
+-	struct evtchn_bind_virq bind_virq;
+-	int evtchn, irq;
+-
+-	spin_lock(&irq_mapping_update_lock);
+-
+-	irq = per_cpu(virq_to_irq, cpu)[virq];
+-
+-	if (irq == -1) {
+-		bind_virq.virq = virq;
+-		bind_virq.vcpu = cpu;
+-		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
+-						&bind_virq) != 0)
+-			BUG();
+-		evtchn = bind_virq.port;
+-
+-		irq = find_unbound_irq();
+-
+-		dynamic_irq_init(irq);
+-		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
+-					      handle_level_irq, "virq");
+-
+-		evtchn_to_irq[evtchn] = irq;
+-		irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
+-
+-		per_cpu(virq_to_irq, cpu)[virq] = irq;
+-
+-		bind_evtchn_to_cpu(evtchn, cpu);
+-	}
+-
+-	irq_bindcount[irq]++;
+-
+-	spin_unlock(&irq_mapping_update_lock);
+-
+-	return irq;
+-}
+-
+-static void unbind_from_irq(unsigned int irq)
+-{
+-	struct evtchn_close close;
+-	int evtchn = evtchn_from_irq(irq);
+-
+-	spin_lock(&irq_mapping_update_lock);
+-
+-	if (VALID_EVTCHN(evtchn) && (--irq_bindcount[irq] == 0)) {
+-		close.port = evtchn;
+-		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+-			BUG();
+-
+-		switch (type_from_irq(irq)) {
+-		case IRQT_VIRQ:
+-			per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
+-				[index_from_irq(irq)] = -1;
+-			break;
+-		default:
+-			break;
+-		}
+-
+-		/* Closed ports are implicitly re-bound to VCPU0. */
+-		bind_evtchn_to_cpu(evtchn, 0);
+-
+-		evtchn_to_irq[evtchn] = -1;
+-		irq_info[irq] = IRQ_UNBOUND;
+-
+-		dynamic_irq_init(irq);
+-	}
+-
+-	spin_unlock(&irq_mapping_update_lock);
+-}
+-
+-int bind_evtchn_to_irqhandler(unsigned int evtchn,
+-			      irq_handler_t handler,
+-			      unsigned long irqflags,
+-			      const char *devname, void *dev_id)
+-{
+-	unsigned int irq;
+-	int retval;
+-
+-	irq = bind_evtchn_to_irq(evtchn);
+-	retval = request_irq(irq, handler, irqflags, devname, dev_id);
+-	if (retval != 0) {
+-		unbind_from_irq(irq);
+-		return retval;
+-	}
+-
+-	return irq;
+-}
+-EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
+-
+-int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
+-			    irq_handler_t handler,
+-			    unsigned long irqflags, const char *devname, void *dev_id)
+-{
+-	unsigned int irq;
+-	int retval;
+-
+-	irq = bind_virq_to_irq(virq, cpu);
+-	retval = request_irq(irq, handler, irqflags, devname, dev_id);
+-	if (retval != 0) {
+-		unbind_from_irq(irq);
+-		return retval;
+-	}
+-
+-	return irq;
+-}
+-EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
+-
+-int bind_ipi_to_irqhandler(enum ipi_vector ipi,
+-			   unsigned int cpu,
+-			   irq_handler_t handler,
+-			   unsigned long irqflags,
+-			   const char *devname,
+-			   void *dev_id)
+-{
+-	int irq, retval;
+-
+-	irq = bind_ipi_to_irq(ipi, cpu);
+-	if (irq < 0)
+-		return irq;
+-
+-	retval = request_irq(irq, handler, irqflags, devname, dev_id);
+-	if (retval != 0) {
+-		unbind_from_irq(irq);
+-		return retval;
+-	}
+-
+-	return irq;
+-}
+-
+-void unbind_from_irqhandler(unsigned int irq, void *dev_id)
+-{
+-	free_irq(irq, dev_id);
+-	unbind_from_irq(irq);
+-}
+-EXPORT_SYMBOL_GPL(unbind_from_irqhandler);
+-
+-void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector)
+-{
+-	int irq = per_cpu(ipi_to_irq, cpu)[vector];
+-	BUG_ON(irq < 0);
+-	notify_remote_via_irq(irq);
+-}
+-
+-
+-/*
+- * Search the CPUs pending events bitmasks.  For each one found, map
+- * the event number to an irq, and feed it into do_IRQ() for
+- * handling.
+- *
+- * Xen uses a two-level bitmap to speed searching.  The first level is
+- * a bitset of words which contain pending event bits.  The second
+- * level is a bitset of pending events themselves.
+- */
+-void xen_evtchn_do_upcall(struct pt_regs *regs)
+-{
+-	int cpu = get_cpu();
+-	struct shared_info *s = HYPERVISOR_shared_info;
+-	struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
+-	unsigned long pending_words;
+-
+-	vcpu_info->evtchn_upcall_pending = 0;
+-
+-	/* NB. No need for a barrier here -- XCHG is a barrier on x86. */
+-	pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
+-	while (pending_words != 0) {
+-		unsigned long pending_bits;
+-		int word_idx = __ffs(pending_words);
+-		pending_words &= ~(1UL << word_idx);
+-
+-		while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
+-			int bit_idx = __ffs(pending_bits);
+-			int port = (word_idx * BITS_PER_LONG) + bit_idx;
+-			int irq = evtchn_to_irq[port];
+-
+-			if (irq != -1) {
+-				regs->orig_ax = ~irq;
+-				do_IRQ(regs);
+-			}
+-		}
+-	}
+-
+-	put_cpu();
+-}
+-
+-/* Rebind an evtchn so that it gets delivered to a specific cpu */
+-static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
+-{
+-	struct evtchn_bind_vcpu bind_vcpu;
+-	int evtchn = evtchn_from_irq(irq);
+-
+-	if (!VALID_EVTCHN(evtchn))
+-		return;
+-
+-	/* Send future instances of this interrupt to other vcpu. */
+-	bind_vcpu.port = evtchn;
+-	bind_vcpu.vcpu = tcpu;
+-
+-	/*
+-	 * If this fails, it usually just indicates that we're dealing with a
+-	 * virq or IPI channel, which don't actually need to be rebound. Ignore
+-	 * it, but don't do the xenlinux-level rebind in that case.
+-	 */
+-	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
+-		bind_evtchn_to_cpu(evtchn, tcpu);
+-}
+-
+-
+-static void set_affinity_irq(unsigned irq, cpumask_t dest)
+-{
+-	unsigned tcpu = first_cpu(dest);
+-	rebind_irq_to_cpu(irq, tcpu);
+-}
+-
+-static void enable_dynirq(unsigned int irq)
+-{
+-	int evtchn = evtchn_from_irq(irq);
+-
+-	if (VALID_EVTCHN(evtchn))
+-		unmask_evtchn(evtchn);
+-}
+-
+-static void disable_dynirq(unsigned int irq)
+-{
+-	int evtchn = evtchn_from_irq(irq);
+-
+-	if (VALID_EVTCHN(evtchn))
+-		mask_evtchn(evtchn);
+-}
+-
+-static void ack_dynirq(unsigned int irq)
+-{
+-	int evtchn = evtchn_from_irq(irq);
+-
+-	move_native_irq(irq);
+-
+-	if (VALID_EVTCHN(evtchn))
+-		clear_evtchn(evtchn);
+-}
+-
+-static int retrigger_dynirq(unsigned int irq)
+-{
+-	int evtchn = evtchn_from_irq(irq);
+-	int ret = 0;
+-
+-	if (VALID_EVTCHN(evtchn)) {
+-		set_evtchn(evtchn);
+-		ret = 1;
+-	}
+-
+-	return ret;
+-}
+-
+-static struct irq_chip xen_dynamic_chip __read_mostly = {
+-	.name		= "xen-dyn",
+-	.mask		= disable_dynirq,
+-	.unmask		= enable_dynirq,
+-	.ack		= ack_dynirq,
+-	.set_affinity	= set_affinity_irq,
+-	.retrigger	= retrigger_dynirq,
+-};
+-
+-void __init xen_init_IRQ(void)
+-{
+-	int i;
+-
+-	init_evtchn_cpu_bindings();
+-
+-	/* No event channels are 'live' right now. */
+-	for (i = 0; i < NR_EVENT_CHANNELS; i++)
+-		mask_evtchn(i);
+-
+-	/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
+-	for (i = 0; i < NR_IRQS; i++)
+-		irq_bindcount[i] = 0;
+-
+-	irq_ctx_init(smp_processor_id());
+-}
+diff --git a/arch/x86/xen/features.c b/arch/x86/xen/features.c
+deleted file mode 100644
+index 0707714..0000000
+--- a/arch/x86/xen/features.c
++++ /dev/null
+@@ -1,29 +0,0 @@
+-/******************************************************************************
+- * features.c
+- *
+- * Xen feature flags.
+- *
+- * Copyright (c) 2006, Ian Campbell, XenSource Inc.
+- */
+-#include <linux/types.h>
+-#include <linux/cache.h>
+-#include <linux/module.h>
+-#include <asm/xen/hypervisor.h>
+-#include <xen/features.h>
+-
+-u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
+-EXPORT_SYMBOL_GPL(xen_features);
+-
+-void xen_setup_features(void)
+-{
+-	struct xen_feature_info fi;
+-	int i, j;
+-
+-	for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
+-		fi.submap_idx = i;
+-		if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
+-			break;
+-		for (j = 0; j < 32; j++)
+-			xen_features[i * 32 + j] = !!(fi.submap & 1<<j);
+-	}
+-}
+diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c
+new file mode 100644
+index 0000000..49ba9b5
+--- /dev/null
++++ b/arch/x86/xen/grant-table.c
+@@ -0,0 +1,91 @@
++/******************************************************************************
++ * grant_table.c
++ * x86 specific part
++ *
++ * Granting foreign access to our memory reservation.
++ *
++ * Copyright (c) 2005-2006, Christopher Clark
++ * Copyright (c) 2004-2005, K A Fraser
++ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
++ *                    VA Linux Systems Japan. Split out x86 specific part.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/vmalloc.h>
++
++#include <xen/interface/xen.h>
++#include <xen/page.h>
++#include <xen/grant_table.h>
++
++#include <asm/pgtable.h>
++
++static int map_pte_fn(pte_t *pte, struct page *pmd_page,
++		      unsigned long addr, void *data)
++{
++	unsigned long **frames = (unsigned long **)data;
++
++	set_pte_at(&init_mm, addr, pte, mfn_pte((*frames)[0], PAGE_KERNEL));
++	(*frames)++;
++	return 0;
++}
++
++static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
++			unsigned long addr, void *data)
++{
++
++	set_pte_at(&init_mm, addr, pte, __pte(0));
++	return 0;
++}
++
++int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
++			   unsigned long max_nr_gframes,
++			   struct grant_entry **__shared)
++{
++	int rc;
++	struct grant_entry *shared = *__shared;
++
++	if (shared == NULL) {
++		struct vm_struct *area =
++			xen_alloc_vm_area(PAGE_SIZE * max_nr_gframes);
++		BUG_ON(area == NULL);
++		shared = area->addr;
++		*__shared = shared;
++	}
++
++	rc = apply_to_page_range(&init_mm, (unsigned long)shared,
++				 PAGE_SIZE * nr_gframes,
++				 map_pte_fn, &frames);
++	return rc;
++}
++
++void arch_gnttab_unmap_shared(struct grant_entry *shared,
++			      unsigned long nr_gframes)
++{
++	apply_to_page_range(&init_mm, (unsigned long)shared,
++			    PAGE_SIZE * nr_gframes, unmap_pte_fn, NULL);
++}
+diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
+index 2a054ef..6cbcf65 100644
+--- a/arch/x86/xen/mmu.c
++++ b/arch/x86/xen/mmu.c
+@@ -156,6 +156,10 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags)
+ void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
+ 		    pte_t *ptep, pte_t pteval)
+ {
++	/* updates to init_mm may be done without lock */
++	if (mm == &init_mm)
++		preempt_disable();
++
+ 	if (mm == current->mm || mm == &init_mm) {
+ 		if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
+ 			struct multicall_space mcs;
+@@ -163,14 +167,61 @@ void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
+ 
+ 			MULTI_update_va_mapping(mcs.mc, addr, pteval, 0);
+ 			xen_mc_issue(PARAVIRT_LAZY_MMU);
+-			return;
++			goto out;
+ 		} else
+ 			if (HYPERVISOR_update_va_mapping(addr, pteval, 0) == 0)
+-				return;
++				goto out;
+ 	}
+ 	xen_set_pte(ptep, pteval);
++
++out:
++	if (mm == &init_mm)
++		preempt_enable();
++}
++
++pteval_t xen_pte_val(pte_t pte)
++{
++	pteval_t ret = pte.pte;
++
++	if (ret & _PAGE_PRESENT)
++		ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
++
++	return ret;
++}
++
++pgdval_t xen_pgd_val(pgd_t pgd)
++{
++	pgdval_t ret = pgd.pgd;
++	if (ret & _PAGE_PRESENT)
++		ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
++	return ret;
++}
++
++pte_t xen_make_pte(pteval_t pte)
++{
++	if (pte & _PAGE_PRESENT) {
++		pte = phys_to_machine(XPADDR(pte)).maddr;
++		pte &= ~(_PAGE_PCD | _PAGE_PWT);
++	}
++
++	return (pte_t){ .pte = pte };
+ }
+ 
++pgd_t xen_make_pgd(pgdval_t pgd)
++{
++	if (pgd & _PAGE_PRESENT)
++		pgd = phys_to_machine(XPADDR(pgd)).maddr;
++
++	return (pgd_t){ pgd };
++}
++
++pmdval_t xen_pmd_val(pmd_t pmd)
++{
++	pmdval_t ret = native_pmd_val(pmd);
++	if (ret & _PAGE_PRESENT)
++		ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
++	return ret;
++}
+ #ifdef CONFIG_X86_PAE
+ void xen_set_pud(pud_t *ptr, pud_t val)
+ {
+@@ -214,100 +265,18 @@ void xen_pmd_clear(pmd_t *pmdp)
+ 	xen_set_pmd(pmdp, __pmd(0));
+ }
+ 
+-unsigned long long xen_pte_val(pte_t pte)
++pmd_t xen_make_pmd(pmdval_t pmd)
+ {
+-	unsigned long long ret = 0;
+-
+-	if (pte.pte_low) {
+-		ret = ((unsigned long long)pte.pte_high << 32) | pte.pte_low;
+-		ret = machine_to_phys(XMADDR(ret)).paddr | 1;
+-	}
+-
+-	return ret;
+-}
+-
+-unsigned long long xen_pmd_val(pmd_t pmd)
+-{
+-	unsigned long long ret = pmd.pmd;
+-	if (ret)
+-		ret = machine_to_phys(XMADDR(ret)).paddr | 1;
+-	return ret;
+-}
+-
+-unsigned long long xen_pgd_val(pgd_t pgd)
+-{
+-	unsigned long long ret = pgd.pgd;
+-	if (ret)
+-		ret = machine_to_phys(XMADDR(ret)).paddr | 1;
+-	return ret;
+-}
+-
+-pte_t xen_make_pte(unsigned long long pte)
+-{
+-	if (pte & _PAGE_PRESENT) {
+-		pte = phys_to_machine(XPADDR(pte)).maddr;
+-		pte &= ~(_PAGE_PCD | _PAGE_PWT);
+-	}
+-
+-	return (pte_t){ .pte = pte };
+-}
+-
+-pmd_t xen_make_pmd(unsigned long long pmd)
+-{
+-	if (pmd & 1)
++	if (pmd & _PAGE_PRESENT)
+ 		pmd = phys_to_machine(XPADDR(pmd)).maddr;
+ 
+-	return (pmd_t){ pmd };
+-}
+-
+-pgd_t xen_make_pgd(unsigned long long pgd)
+-{
+-	if (pgd & _PAGE_PRESENT)
+-		pgd = phys_to_machine(XPADDR(pgd)).maddr;
+-
+-	return (pgd_t){ pgd };
++	return native_make_pmd(pmd);
+ }
+ #else  /* !PAE */
+ void xen_set_pte(pte_t *ptep, pte_t pte)
+ {
+ 	*ptep = pte;
+ }
+-
+-unsigned long xen_pte_val(pte_t pte)
+-{
+-	unsigned long ret = pte.pte_low;
+-
+-	if (ret & _PAGE_PRESENT)
+-		ret = machine_to_phys(XMADDR(ret)).paddr;
+-
+-	return ret;
+-}
+-
+-unsigned long xen_pgd_val(pgd_t pgd)
+-{
+-	unsigned long ret = pgd.pgd;
+-	if (ret)
+-		ret = machine_to_phys(XMADDR(ret)).paddr | 1;
+-	return ret;
+-}
+-
+-pte_t xen_make_pte(unsigned long pte)
+-{
+-	if (pte & _PAGE_PRESENT) {
+-		pte = phys_to_machine(XPADDR(pte)).maddr;
+-		pte &= ~(_PAGE_PCD | _PAGE_PWT);
+-	}
+-
+-	return (pte_t){ pte };
+-}
+-
+-pgd_t xen_make_pgd(unsigned long pgd)
+-{
+-	if (pgd & _PAGE_PRESENT)
+-		pgd = phys_to_machine(XPADDR(pgd)).maddr;
+-
+-	return (pgd_t){ pgd };
+-}
+ #endif	/* CONFIG_X86_PAE */
+ 
+ /*
+diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c
+index 5e6f36f..5791eb2 100644
+--- a/arch/x86/xen/multicalls.c
++++ b/arch/x86/xen/multicalls.c
+@@ -76,7 +76,7 @@ void xen_mc_flush(void)
+ 		if (ret) {
+ 			printk(KERN_ERR "%d multicall(s) failed: cpu %d\n",
+ 			       ret, smp_processor_id());
+-			for(i = 0; i < b->mcidx; i++) {
++			for (i = 0; i < b->mcidx; i++) {
+ 				printk("  call %2d/%d: op=%lu arg=[%lx] result=%ld\n",
+ 				       i+1, b->mcidx,
+ 				       b->debug[i].op,
+@@ -93,7 +93,7 @@ void xen_mc_flush(void)
+ 
+ 	local_irq_restore(flags);
+ 
+-	for(i = 0; i < b->cbidx; i++) {
++	for (i = 0; i < b->cbidx; i++) {
+ 		struct callback *cb = &b->callbacks[i];
+ 
+ 		(*cb->fn)(cb->data);
+diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
+index 2341492..82517e4 100644
+--- a/arch/x86/xen/setup.c
++++ b/arch/x86/xen/setup.c
+@@ -16,6 +16,7 @@
+ #include <asm/xen/hypervisor.h>
+ #include <asm/xen/hypercall.h>
+ 
++#include <xen/interface/callback.h>
+ #include <xen/interface/physdev.h>
+ #include <xen/features.h>
+ 
+@@ -68,6 +69,24 @@ static void __init fiddle_vdso(void)
+ 	*mask |= 1 << VDSO_NOTE_NONEGSEG_BIT;
+ }
+ 
++void xen_enable_sysenter(void)
++{
++	int cpu = smp_processor_id();
++	extern void xen_sysenter_target(void);
++	/* Mask events on entry, even though they get enabled immediately */
++	static struct callback_register sysenter = {
++		.type = CALLBACKTYPE_sysenter,
++		.address = { __KERNEL_CS, (unsigned long)xen_sysenter_target },
++		.flags = CALLBACKF_mask_events,
++	};
++
++	if (!boot_cpu_has(X86_FEATURE_SEP) ||
++	    HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) != 0) {
++		clear_cpu_cap(&cpu_data(cpu), X86_FEATURE_SEP);
++		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_SEP);
++	}
++}
++
+ void __init xen_arch_setup(void)
+ {
+ 	struct physdev_set_iopl set_iopl;
+@@ -82,6 +101,8 @@ void __init xen_arch_setup(void)
+ 	HYPERVISOR_set_callbacks(__KERNEL_CS, (unsigned long)xen_hypervisor_callback,
+ 				 __KERNEL_CS, (unsigned long)xen_failsafe_callback);
+ 
++	xen_enable_sysenter();
++
+ 	set_iopl.iopl = 1;
+ 	rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
+ 	if (rc != 0)
+diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
+index aafc544..94e6900 100644
+--- a/arch/x86/xen/smp.c
++++ b/arch/x86/xen/smp.c
+@@ -35,9 +35,10 @@
+ #include "xen-ops.h"
+ #include "mmu.h"
+ 
+-static cpumask_t cpu_initialized_map;
+-static DEFINE_PER_CPU(int, resched_irq);
+-static DEFINE_PER_CPU(int, callfunc_irq);
++static cpumask_t xen_cpu_initialized_map;
++static DEFINE_PER_CPU(int, resched_irq) = -1;
++static DEFINE_PER_CPU(int, callfunc_irq) = -1;
++static DEFINE_PER_CPU(int, debug_irq) = -1;
+ 
+ /*
+  * Structure and data for smp_call_function(). This is designed to minimise
+@@ -72,6 +73,7 @@ static __cpuinit void cpu_bringup_and_idle(void)
+ 	int cpu = smp_processor_id();
+ 
+ 	cpu_init();
++	xen_enable_sysenter();
+ 
+ 	preempt_disable();
+ 	per_cpu(cpu_state, cpu) = CPU_ONLINE;
+@@ -88,9 +90,7 @@ static __cpuinit void cpu_bringup_and_idle(void)
+ static int xen_smp_intr_init(unsigned int cpu)
+ {
+ 	int rc;
+-	const char *resched_name, *callfunc_name;
+-
+-	per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;
++	const char *resched_name, *callfunc_name, *debug_name;
+ 
+ 	resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
+ 	rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
+@@ -114,6 +114,14 @@ static int xen_smp_intr_init(unsigned int cpu)
+ 		goto fail;
+ 	per_cpu(callfunc_irq, cpu) = rc;
+ 
++	debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
++	rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt,
++				     IRQF_DISABLED | IRQF_PERCPU | IRQF_NOBALANCING,
++				     debug_name, NULL);
++	if (rc < 0)
++		goto fail;
++	per_cpu(debug_irq, cpu) = rc;
++
+ 	return 0;
+ 
+  fail:
+@@ -121,6 +129,8 @@ static int xen_smp_intr_init(unsigned int cpu)
+ 		unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+ 	if (per_cpu(callfunc_irq, cpu) >= 0)
+ 		unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
++	if (per_cpu(debug_irq, cpu) >= 0)
++		unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL);
+ 	return rc;
+ }
+ 
+@@ -179,11 +189,11 @@ void __init xen_smp_prepare_cpus(unsigned int max_cpus)
+ 	if (xen_smp_intr_init(0))
+ 		BUG();
+ 
+-	cpu_initialized_map = cpumask_of_cpu(0);
++	xen_cpu_initialized_map = cpumask_of_cpu(0);
+ 
+ 	/* Restrict the possible_map according to max_cpus. */
+ 	while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
+-		for (cpu = NR_CPUS-1; !cpu_isset(cpu, cpu_possible_map); cpu--)
++		for (cpu = NR_CPUS - 1; !cpu_possible(cpu); cpu--)
+ 			continue;
+ 		cpu_clear(cpu, cpu_possible_map);
+ 	}
+@@ -210,7 +220,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
+ 	struct vcpu_guest_context *ctxt;
+ 	struct gdt_page *gdt = &per_cpu(gdt_page, cpu);
+ 
+-	if (cpu_test_and_set(cpu, cpu_initialized_map))
++	if (cpu_test_and_set(cpu, xen_cpu_initialized_map))
+ 		return 0;
+ 
+ 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
+diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
+index 6b71904..2497a30 100644
+--- a/arch/x86/xen/xen-asm.S
++++ b/arch/x86/xen/xen-asm.S
+@@ -108,6 +108,20 @@ ENDPATCH(xen_restore_fl_direct)
+ 	RELOC(xen_restore_fl_direct, 2b+1)
+ 
+ /*
++	We can't use sysexit directly, because we're not running in ring0.
++	But we can easily fake it up using iret.  Assuming xen_sysexit
++	is jumped to with a standard stack frame, we can just strip it
++	back to a standard iret frame and use iret.
++ */
++ENTRY(xen_sysexit)
++	movl PT_EAX(%esp), %eax			/* Shouldn't be necessary? */
++	orl $X86_EFLAGS_IF, PT_EFLAGS(%esp)
++	lea PT_EIP(%esp), %esp
++
++	jmp xen_iret
++ENDPROC(xen_sysexit)
++
++/*
+ 	This is run where a normal iret would be run, with the same stack setup:
+ 	      8: eflags
+ 	      4: cs
+@@ -135,13 +149,8 @@ ENDPATCH(xen_restore_fl_direct)
+ 	current stack state in whatever form its in, we keep things
+ 	simple by only using a single register which is pushed/popped
+ 	on the stack.
+-
+-	Non-direct iret could be done in the same way, but it would
+-	require an annoying amount of code duplication.  We'll assume
+-	that direct mode will be the common case once the hypervisor
+-	support becomes commonplace.
+  */
+-ENTRY(xen_iret_direct)
++ENTRY(xen_iret)
+ 	/* test eflags for special cases */
+ 	testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp)
+ 	jnz hyper_iret
+@@ -155,9 +164,9 @@ ENTRY(xen_iret_direct)
+ 	GET_THREAD_INFO(%eax)
+ 	movl TI_cpu(%eax),%eax
+ 	movl __per_cpu_offset(,%eax,4),%eax
+-	lea per_cpu__xen_vcpu_info(%eax),%eax
++	mov per_cpu__xen_vcpu(%eax),%eax
+ #else
+-	movl $per_cpu__xen_vcpu_info, %eax
++	movl per_cpu__xen_vcpu, %eax
+ #endif
+ 
+ 	/* check IF state we're restoring */
+@@ -189,8 +198,12 @@ iret_restore_end:
+ 	   region is OK. */
+ 	je xen_hypervisor_callback
+ 
+-	iret
++1:	iret
+ xen_iret_end_crit:
++.section __ex_table,"a"
++	.align 4
++	.long 1b,iret_exc
++.previous
+ 
+ hyper_iret:
+ 	/* put this out of line since its very rarely used */
+@@ -224,9 +237,7 @@ hyper_iret:
+ 	 ds		}  SAVE_ALL state
+ 	 eax		}
+ 	  :		:
+-	 ebx		}
+-	----------------
+-	 return addr	 <- esp
++	 ebx		}<- esp
+ 	----------------
+ 
+    In order to deliver the nested exception properly, we need to shift
+@@ -241,10 +252,8 @@ hyper_iret:
+    it's usermode state which we eventually need to restore.
+  */
+ ENTRY(xen_iret_crit_fixup)
+-	/* offsets +4 for return address */
+-
+ 	/*
+-	   Paranoia: Make sure we're really coming from userspace.
++	   Paranoia: Make sure we're really coming from kernel space.
+ 	   One could imagine a case where userspace jumps into the
+ 	   critical range address, but just before the CPU delivers a GP,
+ 	   it decides to deliver an interrupt instead.  Unlikely?
+@@ -253,32 +262,32 @@ ENTRY(xen_iret_crit_fixup)
+ 	   jump instruction itself, not the destination, but some virtual
+ 	   environments get this wrong.
+ 	 */
+-	movl PT_CS+4(%esp), %ecx
++	movl PT_CS(%esp), %ecx
+ 	andl $SEGMENT_RPL_MASK, %ecx
+ 	cmpl $USER_RPL, %ecx
+ 	je 2f
+ 
+-	lea PT_ORIG_EAX+4(%esp), %esi
+-	lea PT_EFLAGS+4(%esp), %edi
++	lea PT_ORIG_EAX(%esp), %esi
++	lea PT_EFLAGS(%esp), %edi
+ 
+ 	/* If eip is before iret_restore_end then stack
+ 	   hasn't been restored yet. */
+ 	cmp $iret_restore_end, %eax
+ 	jae 1f
+ 
+-	movl 0+4(%edi),%eax		/* copy EAX */
+-	movl %eax, PT_EAX+4(%esp)
++	movl 0+4(%edi),%eax		/* copy EAX (just above top of frame) */
++	movl %eax, PT_EAX(%esp)
+ 
+ 	lea ESP_OFFSET(%edi),%edi	/* move dest up over saved regs */
+ 
+ 	/* set up the copy */
+ 1:	std
+-	mov $(PT_EIP+4) / 4, %ecx	/* copy ret+saved regs up to orig_eax */
++	mov $PT_EIP / 4, %ecx		/* saved regs up to orig_eax */
+ 	rep movsl
+ 	cld
+ 
+ 	lea 4(%edi),%esp		/* point esp to new frame */
+-2:	ret
++2:	jmp xen_do_upcall
+ 
+ 
+ /*
+diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
+index b02a909..f1063ae 100644
+--- a/arch/x86/xen/xen-ops.h
++++ b/arch/x86/xen/xen-ops.h
+@@ -2,6 +2,8 @@
+ #define XEN_OPS_H
+ 
+ #include <linux/init.h>
++#include <linux/irqreturn.h>
++#include <xen/xen-ops.h>
+ 
+ /* These are code, but not functions.  Defined in entry.S */
+ extern const char xen_hypervisor_callback[];
+@@ -9,7 +11,6 @@ extern const char xen_failsafe_callback[];
+ 
+ void xen_copy_trap_info(struct trap_info *traps);
+ 
+-DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
+ DECLARE_PER_CPU(unsigned long, xen_cr3);
+ DECLARE_PER_CPU(unsigned long, xen_current_cr3);
+ 
+@@ -19,6 +20,7 @@ extern struct shared_info *HYPERVISOR_shared_info;
+ char * __init xen_memory_setup(void);
+ void __init xen_arch_setup(void);
+ void __init xen_init_IRQ(void);
++void xen_enable_sysenter(void);
+ 
+ void xen_setup_timer(int cpu);
+ void xen_setup_cpu_clockevents(void);
+@@ -28,6 +30,8 @@ unsigned long xen_get_wallclock(void);
+ int xen_set_wallclock(unsigned long time);
+ unsigned long long xen_sched_clock(void);
+ 
++irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
++
+ bool xen_vcpu_stolen(int vcpu);
+ 
+ void xen_mark_init_mm_pinned(void);
+@@ -63,5 +67,7 @@ DECL_ASM(void, xen_irq_disable_direct, void);
+ DECL_ASM(unsigned long, xen_save_fl_direct, void);
+ DECL_ASM(void, xen_restore_fl_direct, unsigned long);
+ 
+-void xen_iret_direct(void);
++void xen_iret(void);
++void xen_sysexit(void);
++
+ #endif /* XEN_OPS_H */
+diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
+index f582d6a..7419dbc 100644
+--- a/arch/xtensa/kernel/Makefile
++++ b/arch/xtensa/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y := head.o vmlinux.lds
+ 
+ 
+-obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o  \
++obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o \
+ 	 setup.o signal.o syscall.o time.o traps.o vectors.o platform.o  \
+ 	 pci-dma.o init_task.o io.o
+ 
+diff --git a/arch/xtensa/kernel/semaphore.c b/arch/xtensa/kernel/semaphore.c
+deleted file mode 100644
+index 995c641..0000000
+--- a/arch/xtensa/kernel/semaphore.c
++++ /dev/null
+@@ -1,226 +0,0 @@
+-/*
+- * arch/xtensa/kernel/semaphore.c
+- *
+- * Generic semaphore code. Buyer beware. Do your own specific changes
+- * in <asm/semaphore-helper.h>
+- *
+- * 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.
+- *
+- * Joe Taylor	<joe at tensilica.com, joetylr at yahoo.com>
+- * Chris Zankel	<chris at zankel.net>
+- * Marc Gauthier<marc at tensilica.com, marc at alumni.uwaterloo.ca>
+- * Kevin Chea
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/wait.h>
+-#include <linux/init.h>
+-#include <asm/semaphore.h>
+-#include <asm/errno.h>
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-
+-static __inline__ void wake_one_more(struct semaphore * sem)
+-{
+-	atomic_inc((atomic_t *)&sem->sleepers);
+-}
+-
+-static __inline__ int waking_non_zero(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->sleepers > 0) {
+-		sem->sleepers--;
+-		ret = 1;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- *	1	got the lock
+- *	0	go to sleep
+- *	-EINTR	interrupted
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-
+-static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+-						struct task_struct *tsk)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->sleepers > 0) {
+-		sem->sleepers--;
+-		ret = 1;
+-	} else if (signal_pending(tsk)) {
+-		atomic_inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- *	1	failed to lock
+- *	0	got the lock
+- *
+- * We must undo the sem->count down_trylock() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-
+-static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 1;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->sleepers <= 0)
+-		atomic_inc(&sem->count);
+-	else {
+-		sem->sleepers--;
+-		ret = 0;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-DEFINE_SPINLOCK(semaphore_wake_lock);
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit.  ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore.  The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+-	wake_one_more(sem);
+-	wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function.  Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible.  This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return.  If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-#define DOWN_VAR				\
+-	struct task_struct *tsk = current;	\
+-	wait_queue_t wait;			\
+-	init_waitqueue_entry(&wait, tsk);
+-
+-#define DOWN_HEAD(task_state)						\
+-									\
+-									\
+-	tsk->state = (task_state);					\
+-	add_wait_queue(&sem->wait, &wait);				\
+-									\
+-	/*								\
+-	 * Ok, we're set up.  sem->count is known to be less than zero	\
+-	 * so we must wait.						\
+-	 *								\
+-	 * We can let go the lock for purposes of waiting.		\
+-	 * We re-acquire it after awaking so as to protect		\
+-	 * all semaphore operations.					\
+-	 *								\
+-	 * If "up()" is called before we call waking_non_zero() then	\
+-	 * we will catch it right away.  If it is called later then	\
+-	 * we will have to go through a wakeup cycle to catch it.	\
+-	 *								\
+-	 * Multiple waiters contend for the semaphore lock to see	\
+-	 * who gets to gate through and who has to wait some more.	\
+-	 */								\
+-	for (;;) {
+-
+-#define DOWN_TAIL(task_state)			\
+-		tsk->state = (task_state);	\
+-	}					\
+-	tsk->state = TASK_RUNNING;		\
+-	remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+-	DOWN_VAR
+-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+-	if (waking_non_zero(sem))
+-		break;
+-	schedule();
+-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-	DOWN_VAR
+-	DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+-	ret = waking_non_zero_interruptible(sem, tsk);
+-	if (ret)
+-	{
+-		if (ret == 1)
+-			/* ret != 0 only if we get interrupted -arca */
+-			ret = 0;
+-		break;
+-	}
+-	schedule();
+-	DOWN_TAIL(TASK_INTERRUPTIBLE)
+-	return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+-	return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
+index 60dbdb4..6e52cdd 100644
+--- a/arch/xtensa/kernel/xtensa_ksyms.c
++++ b/arch/xtensa/kernel/xtensa_ksyms.c
+@@ -26,7 +26,6 @@
+ #include <asm/io.h>
+ #include <asm/page.h>
+ #include <asm/pgalloc.h>
+-#include <asm/semaphore.h>
+ #ifdef CONFIG_BLK_DEV_FD
+ #include <asm/floppy.h>
+ #endif
+@@ -71,14 +70,6 @@ EXPORT_SYMBOL(__umodsi3);
+ EXPORT_SYMBOL(__udivdi3);
+ EXPORT_SYMBOL(__umoddi3);
+ 
+-/*
+- * Semaphore operations
+- */
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__up);
+-
+ #ifdef CONFIG_NET
+ /*
+  * Networking support
+diff --git a/block/Kconfig b/block/Kconfig
+index 7db9a41..3e97f2b 100644
+--- a/block/Kconfig
++++ b/block/Kconfig
+@@ -5,14 +5,18 @@ menuconfig BLOCK
+        bool "Enable the block layer" if EMBEDDED
+        default y
+        help
+-	 This permits the block layer to be removed from the kernel if it's not
+-	 needed (on some embedded devices for example).  If this option is
+-	 disabled, then blockdev files will become unusable and some
+-	 filesystems (such as ext3) will become unavailable.
++	 Provide block layer support for the kernel.
+ 
+-	 This option will also disable SCSI character devices and USB storage
+-	 since they make use of various block layer definitions and
+-	 facilities.
++	 Disable this option to remove the block layer support from the
++	 kernel. This may be useful for embedded devices.
++
++	 If this option is disabled:
++
++	   - block device files will become unusable
++	   - some filesystems (such as ext3) will become unavailable.
++
++	 Also, SCSI character devices and USB storage will be disabled since
++	 they make use of various block layer definitions and facilities.
+ 
+ 	 Say Y here unless you know you really don't want to mount disks and
+ 	 suchlike.
+@@ -23,9 +27,20 @@ config LBD
+ 	bool "Support for Large Block Devices"
+ 	depends on !64BIT
+ 	help
+-	  Say Y here if you want to attach large (bigger than 2TB) discs to
+-	  your machine, or if you want to have a raid or loopback device
+-	  bigger than 2TB.  Otherwise say N.
++	  Enable block devices of size 2TB and larger.
++
++	  This option is required to support the full capacity of large
++	  (2TB+) block devices, including RAID, disk, Network Block Device,
++	  Logical Volume Manager (LVM) and loopback.
++
++	  For example, RAID devices are frequently bigger than the capacity
++	  of the largest individual hard drive.
++
++	  This option is not required if you have individual disk drives
++	  which total 2TB+ and you are not aggregating the capacity into
++	  a large block device (e.g. using RAID or LVM).
++
++	  If unsure, say N.
+ 
+ config BLK_DEV_IO_TRACE
+ 	bool "Support for tracing block io actions"
+@@ -33,19 +48,21 @@ config BLK_DEV_IO_TRACE
+ 	select RELAY
+ 	select DEBUG_FS
+ 	help
+-	  Say Y here, if you want to be able to trace the block layer actions
++	  Say Y here if you want to be able to trace the block layer actions
+ 	  on a given queue. Tracing allows you to see any traffic happening
+-	  on a block device queue. For more information (and the user space
+-	  support tools needed), fetch the blktrace app from:
++	  on a block device queue. For more information (and the userspace
++	  support tools needed), fetch the blktrace tools from:
+ 
+ 	  git://git.kernel.dk/blktrace.git
+ 
++	  If unsure, say N.
++
+ config LSF
+ 	bool "Support for Large Single Files"
+ 	depends on !64BIT
+ 	help
+-	  Say Y here if you want to be able to handle very large files (bigger
+-	  than 2TB), otherwise say N.
++	  Say Y here if you want to be able to handle very large files (2TB
++	  and larger), otherwise say N.
+ 
+ 	  If unsure, say Y.
+ 
+@@ -53,14 +70,16 @@ config BLK_DEV_BSG
+ 	bool "Block layer SG support v4 (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL
+ 	---help---
+-	Saying Y here will enable generic SG (SCSI generic) v4 support
+-	for any block device.
+-
+-	Unlike SG v3 (aka block/scsi_ioctl.c drivers/scsi/sg.c), SG v4
+-	can handle complicated SCSI commands: tagged variable length cdbs
+-	with bidirectional data transfers and generic request/response
+-	protocols (e.g. Task Management Functions and SMP in Serial
+-	Attached SCSI).
++	  Saying Y here will enable generic SG (SCSI generic) v4 support
++	  for any block device.
++
++	  Unlike SG v3 (aka block/scsi_ioctl.c drivers/scsi/sg.c), SG v4
++	  can handle complicated SCSI commands: tagged variable length cdbs
++	  with bidirectional data transfers and generic request/response
++	  protocols (e.g. Task Management Functions and SMP in Serial
++	  Attached SCSI).
++
++	  If unsure, say N.
+ 
+ endif # BLOCK
+ 
+diff --git a/block/blk-map.c b/block/blk-map.c
+index c07d9c8..3c942bd 100644
+--- a/block/blk-map.c
++++ b/block/blk-map.c
+@@ -5,6 +5,7 @@
+ #include <linux/module.h>
+ #include <linux/bio.h>
+ #include <linux/blkdev.h>
++#include <scsi/sg.h>		/* for struct sg_iovec */
+ 
+ #include "blk.h"
+ 
+@@ -140,25 +141,8 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
+ 		ubuf += ret;
+ 	}
+ 
+-	/*
+-	 * __blk_rq_map_user() copies the buffers if starting address
+-	 * or length isn't aligned to dma_pad_mask.  As the copied
+-	 * buffer is always page aligned, we know that there's enough
+-	 * room for padding.  Extend the last bio and update
+-	 * rq->data_len accordingly.
+-	 *
+-	 * On unmap, bio_uncopy_user() will use unmodified
+-	 * bio_map_data pointed to by bio->bi_private.
+-	 */
+-	if (len & q->dma_pad_mask) {
+-		unsigned int pad_len = (q->dma_pad_mask & ~len) + 1;
+-		struct bio *tail = rq->biotail;
+-
+-		tail->bi_io_vec[tail->bi_vcnt - 1].bv_len += pad_len;
+-		tail->bi_size += pad_len;
+-
+-		rq->extra_len += pad_len;
+-	}
++	if (!bio_flagged(bio, BIO_USER_MAPPED))
++		rq->cmd_flags |= REQ_COPY_USER;
+ 
+ 	rq->buffer = rq->data = NULL;
+ 	return 0;
+@@ -194,15 +178,26 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
+ 			struct sg_iovec *iov, int iov_count, unsigned int len)
+ {
+ 	struct bio *bio;
++	int i, read = rq_data_dir(rq) == READ;
++	int unaligned = 0;
+ 
+ 	if (!iov || iov_count <= 0)
+ 		return -EINVAL;
+ 
+-	/* we don't allow misaligned data like bio_map_user() does.  If the
+-	 * user is using sg, they're expected to know the alignment constraints
+-	 * and respect them accordingly */
+-	bio = bio_map_user_iov(q, NULL, iov, iov_count,
+-				rq_data_dir(rq) == READ);
++	for (i = 0; i < iov_count; i++) {
++		unsigned long uaddr = (unsigned long)iov[i].iov_base;
++
++		if (uaddr & queue_dma_alignment(q)) {
++			unaligned = 1;
++			break;
++		}
++	}
++
++	if (unaligned || (q->dma_pad_mask & len))
++		bio = bio_copy_user_iov(q, iov, iov_count, read);
++	else
++		bio = bio_map_user_iov(q, NULL, iov, iov_count, read);
++
+ 	if (IS_ERR(bio))
+ 		return PTR_ERR(bio);
+ 
+@@ -212,6 +207,9 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
+ 		return -EINVAL;
+ 	}
+ 
++	if (!bio_flagged(bio, BIO_USER_MAPPED))
++		rq->cmd_flags |= REQ_COPY_USER;
++
+ 	bio_get(bio);
+ 	blk_rq_bio_prep(q, rq, bio);
+ 	rq->buffer = rq->data = NULL;
+diff --git a/block/blk-merge.c b/block/blk-merge.c
+index 0f58616..b5c5c4a 100644
+--- a/block/blk-merge.c
++++ b/block/blk-merge.c
+@@ -220,6 +220,15 @@ new_segment:
+ 		bvprv = bvec;
+ 	} /* segments in rq */
+ 
++
++	if (unlikely(rq->cmd_flags & REQ_COPY_USER) &&
++	    (rq->data_len & q->dma_pad_mask)) {
++		unsigned int pad_len = (q->dma_pad_mask & ~rq->data_len) + 1;
++
++		sg->length += pad_len;
++		rq->extra_len += pad_len;
++	}
++
+ 	if (q->dma_drain_size && q->dma_drain_needed(rq)) {
+ 		if (rq->cmd_flags & REQ_RW)
+ 			memset(q->dma_drain_buffer, 0, q->dma_drain_size);
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index 54d0db1..fc41d83 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -276,9 +276,12 @@ int blk_register_queue(struct gendisk *disk)
+ 
+ 	struct request_queue *q = disk->queue;
+ 
+-	if (!q || !q->request_fn)
++	if (WARN_ON(!q))
+ 		return -ENXIO;
+ 
++	if (!q->request_fn)
++		return 0;
++
+ 	ret = kobject_add(&q->kobj, kobject_get(&disk->dev.kobj),
+ 			  "%s", "queue");
+ 	if (ret < 0)
+@@ -300,7 +303,10 @@ void blk_unregister_queue(struct gendisk *disk)
+ {
+ 	struct request_queue *q = disk->queue;
+ 
+-	if (q && q->request_fn) {
++	if (WARN_ON(!q))
++		return;
++
++	if (q->request_fn) {
+ 		elv_unregister_queue(q);
+ 
+ 		kobject_uevent(&q->kobj, KOBJ_REMOVE);
+diff --git a/block/bsg.c b/block/bsg.c
+index 8917c51..f51172e 100644
+--- a/block/bsg.c
++++ b/block/bsg.c
+@@ -37,7 +37,6 @@ struct bsg_device {
+ 	struct list_head done_list;
+ 	struct hlist_node dev_list;
+ 	atomic_t ref_count;
+-	int minor;
+ 	int queued_cmds;
+ 	int done_cmds;
+ 	wait_queue_head_t wq_done;
+@@ -368,7 +367,7 @@ static struct bsg_command *bsg_next_done_cmd(struct bsg_device *bd)
+ 
+ 	spin_lock_irq(&bd->lock);
+ 	if (bd->done_cmds) {
+-		bc = list_entry(bd->done_list.next, struct bsg_command, list);
++		bc = list_first_entry(&bd->done_list, struct bsg_command, list);
+ 		list_del(&bc->list);
+ 		bd->done_cmds--;
+ 	}
+@@ -468,8 +467,6 @@ static int bsg_complete_all_commands(struct bsg_device *bd)
+ 
+ 	dprintk("%s: entered\n", bd->name);
+ 
+-	set_bit(BSG_F_BLOCK, &bd->flags);
+-
+ 	/*
+ 	 * wait for all commands to complete
+ 	 */
+@@ -705,6 +702,7 @@ static struct bsg_device *bsg_alloc_device(void)
+ static int bsg_put_device(struct bsg_device *bd)
+ {
+ 	int ret = 0;
++	struct device *dev = bd->queue->bsg_dev.dev;
+ 
+ 	mutex_lock(&bsg_mutex);
+ 
+@@ -730,6 +728,7 @@ static int bsg_put_device(struct bsg_device *bd)
+ 	kfree(bd);
+ out:
+ 	mutex_unlock(&bsg_mutex);
++	put_device(dev);
+ 	return ret;
+ }
+ 
+@@ -738,24 +737,28 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
+ 					 struct file *file)
+ {
+ 	struct bsg_device *bd;
++	int ret;
+ #ifdef BSG_DEBUG
+ 	unsigned char buf[32];
+ #endif
++	ret = blk_get_queue(rq);
++	if (ret)
++		return ERR_PTR(-ENXIO);
+ 
+ 	bd = bsg_alloc_device();
+-	if (!bd)
++	if (!bd) {
++		blk_put_queue(rq);
+ 		return ERR_PTR(-ENOMEM);
++	}
+ 
+ 	bd->queue = rq;
+-	kobject_get(&rq->kobj);
+ 	bsg_set_block(bd, file);
+ 
+ 	atomic_set(&bd->ref_count, 1);
+-	bd->minor = iminor(inode);
+ 	mutex_lock(&bsg_mutex);
+-	hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(bd->minor));
++	hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode)));
+ 
+-	strncpy(bd->name, rq->bsg_dev.class_dev->class_id, sizeof(bd->name) - 1);
++	strncpy(bd->name, rq->bsg_dev.class_dev->bus_id, sizeof(bd->name) - 1);
+ 	dprintk("bound to <%s>, max queue %d\n",
+ 		format_dev_t(buf, inode->i_rdev), bd->max_queue);
+ 
+@@ -763,23 +766,21 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
+ 	return bd;
+ }
+ 
+-static struct bsg_device *__bsg_get_device(int minor)
++static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)
+ {
+-	struct bsg_device *bd = NULL;
++	struct bsg_device *bd;
+ 	struct hlist_node *entry;
+ 
+ 	mutex_lock(&bsg_mutex);
+ 
+-	hlist_for_each(entry, bsg_dev_idx_hash(minor)) {
+-		bd = hlist_entry(entry, struct bsg_device, dev_list);
+-		if (bd->minor == minor) {
++	hlist_for_each_entry(bd, entry, bsg_dev_idx_hash(minor), dev_list) {
++		if (bd->queue == q) {
+ 			atomic_inc(&bd->ref_count);
+-			break;
++			goto found;
+ 		}
+-
+-		bd = NULL;
+ 	}
+-
++	bd = NULL;
++found:
+ 	mutex_unlock(&bsg_mutex);
+ 	return bd;
+ }
+@@ -789,21 +790,27 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
+ 	struct bsg_device *bd;
+ 	struct bsg_class_device *bcd;
+ 
+-	bd = __bsg_get_device(iminor(inode));
+-	if (bd)
+-		return bd;
+-
+ 	/*
+ 	 * find the class device
+ 	 */
+ 	mutex_lock(&bsg_mutex);
+ 	bcd = idr_find(&bsg_minor_idr, iminor(inode));
++	if (bcd)
++		get_device(bcd->dev);
+ 	mutex_unlock(&bsg_mutex);
+ 
+ 	if (!bcd)
+ 		return ERR_PTR(-ENODEV);
+ 
+-	return bsg_add_device(inode, bcd->queue, file);
++	bd = __bsg_get_device(iminor(inode), bcd->queue);
++	if (bd)
++		return bd;
++
++	bd = bsg_add_device(inode, bcd->queue, file);
++	if (IS_ERR(bd))
++		put_device(bcd->dev);
++
++	return bd;
+ }
+ 
+ static int bsg_open(struct inode *inode, struct file *file)
+@@ -939,10 +946,9 @@ void bsg_unregister_queue(struct request_queue *q)
+ 	mutex_lock(&bsg_mutex);
+ 	idr_remove(&bsg_minor_idr, bcd->minor);
+ 	sysfs_remove_link(&q->kobj, "bsg");
+-	class_device_unregister(bcd->class_dev);
++	device_unregister(bcd->class_dev);
+ 	put_device(bcd->dev);
+ 	bcd->class_dev = NULL;
+-	bcd->dev = NULL;
+ 	mutex_unlock(&bsg_mutex);
+ }
+ EXPORT_SYMBOL_GPL(bsg_unregister_queue);
+@@ -953,7 +959,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
+ 	struct bsg_class_device *bcd;
+ 	dev_t dev;
+ 	int ret, minor;
+-	struct class_device *class_dev = NULL;
++	struct device *class_dev = NULL;
+ 	const char *devname;
+ 
+ 	if (name)
+@@ -992,8 +998,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
+ 	bcd->queue = q;
+ 	bcd->dev = get_device(gdev);
+ 	dev = MKDEV(bsg_major, bcd->minor);
+-	class_dev = class_device_create(bsg_class, NULL, dev, gdev, "%s",
+-					devname);
++	class_dev = device_create(bsg_class, gdev, dev, "%s", devname);
+ 	if (IS_ERR(class_dev)) {
+ 		ret = PTR_ERR(class_dev);
+ 		goto put_dev;
+@@ -1010,7 +1015,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
+ 	return 0;
+ 
+ unregister_class_dev:
+-	class_device_unregister(class_dev);
++	device_unregister(class_dev);
+ put_dev:
+ 	put_device(gdev);
+ remove_idr:
+diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
+index b733732..c70d0b6 100644
+--- a/block/compat_ioctl.c
++++ b/block/compat_ioctl.c
+@@ -624,7 +624,6 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
+ 	case HDIO_GET_IDENTITY:
+ 	case HDIO_DRIVE_TASK:
+ 	case HDIO_DRIVE_CMD:
+-	case HDIO_SCAN_HWIF:
+ 	/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
+ 	case 0x330:
+ 	/* 0x02 -- Floppy ioctls */
+diff --git a/crypto/Kconfig b/crypto/Kconfig
+index 69f1be6..864456c 100644
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -13,12 +13,14 @@ source "crypto/async_tx/Kconfig"
+ # Cryptographic API Configuration
+ #
+ menuconfig CRYPTO
+-	bool "Cryptographic API"
++	tristate "Cryptographic API"
+ 	help
+ 	  This option provides the core Cryptographic API.
+ 
+ if CRYPTO
+ 
++comment "Crypto core or helper"
++
+ config CRYPTO_ALGAPI
+ 	tristate
+ 	help
+@@ -32,15 +34,6 @@ config CRYPTO_BLKCIPHER
+ 	tristate
+ 	select CRYPTO_ALGAPI
+ 
+-config CRYPTO_SEQIV
+-	tristate "Sequence Number IV Generator"
+-	select CRYPTO_AEAD
+-	select CRYPTO_BLKCIPHER
+-	help
+-	  This IV generator generates an IV based on a sequence number by
+-	  xoring it with a salt.  This algorithm is mainly useful for CTR
+-	  and similar modes.
+-
+ config CRYPTO_HASH
+ 	tristate
+ 	select CRYPTO_ALGAPI
+@@ -52,24 +45,15 @@ config CRYPTO_MANAGER
+ 	  Create default cryptographic template instantiations such as
+ 	  cbc(aes).
+ 
+-config CRYPTO_HMAC
+-	tristate "HMAC support"
+-	select CRYPTO_HASH
+-	select CRYPTO_MANAGER
+-	help
+-	  HMAC: Keyed-Hashing for Message Authentication (RFC2104).
+-	  This is required for IPSec.
+-
+-config CRYPTO_XCBC
+-	tristate "XCBC support"
++config CRYPTO_GF128MUL
++	tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL
+-	select CRYPTO_HASH
+-	select CRYPTO_MANAGER
+ 	help
+-	  XCBC: Keyed-Hashing with encryption algorithm
+-		http://www.ietf.org/rfc/rfc3566.txt
+-		http://csrc.nist.gov/encryption/modes/proposedmodes/
+-		 xcbc-mac/xcbc-mac-spec.pdf
++	  Efficient table driven implementation of multiplications in the
++	  field GF(2^128).  This is needed by some cypher modes. This
++	  option will be selected automatically if you select such a
++	  cipher mode.  Only select this option by hand if you expect to load
++	  an external module that requires these functions.
+ 
+ config CRYPTO_NULL
+ 	tristate "Null algorithms"
+@@ -78,107 +62,98 @@ config CRYPTO_NULL
+ 	help
+ 	  These are 'Null' algorithms, used by IPsec, which do nothing.
+ 
+-config CRYPTO_MD4
+-	tristate "MD4 digest algorithm"
+-	select CRYPTO_ALGAPI
+-	help
+-	  MD4 message digest algorithm (RFC1320).
+-
+-config CRYPTO_MD5
+-	tristate "MD5 digest algorithm"
+-	select CRYPTO_ALGAPI
++config CRYPTO_CRYPTD
++	tristate "Software async crypto daemon"
++	select CRYPTO_BLKCIPHER
++	select CRYPTO_MANAGER
+ 	help
+-	  MD5 message digest algorithm (RFC1321).
++	  This is a generic software asynchronous crypto daemon that
++	  converts an arbitrary synchronous software crypto algorithm
++	  into an asynchronous algorithm that executes in a kernel thread.
+ 
+-config CRYPTO_SHA1
+-	tristate "SHA1 digest algorithm"
+-	select CRYPTO_ALGAPI
++config CRYPTO_AUTHENC
++	tristate "Authenc support"
++	select CRYPTO_AEAD
++	select CRYPTO_BLKCIPHER
++	select CRYPTO_MANAGER
++	select CRYPTO_HASH
+ 	help
+-	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
++	  Authenc: Combined mode wrapper for IPsec.
++	  This is required for IPSec.
+ 
+-config CRYPTO_SHA256
+-	tristate "SHA224 and SHA256 digest algorithm"
++config CRYPTO_TEST
++	tristate "Testing module"
++	depends on m
+ 	select CRYPTO_ALGAPI
++	select CRYPTO_AEAD
++	select CRYPTO_BLKCIPHER
+ 	help
+-	  SHA256 secure hash standard (DFIPS 180-2).
+-	  
+-	  This version of SHA implements a 256 bit hash with 128 bits of
+-	  security against collision attacks.
++	  Quick & dirty crypto test module.
+ 
+-          This code also includes SHA-224, a 224 bit hash with 112 bits
+-          of security against collision attacks.
++comment "Authenticated Encryption with Associated Data"
+ 
+-config CRYPTO_SHA512
+-	tristate "SHA384 and SHA512 digest algorithms"
+-	select CRYPTO_ALGAPI
++config CRYPTO_CCM
++	tristate "CCM support"
++	select CRYPTO_CTR
++	select CRYPTO_AEAD
+ 	help
+-	  SHA512 secure hash standard (DFIPS 180-2).
+-	  
+-	  This version of SHA implements a 512 bit hash with 256 bits of
+-	  security against collision attacks.
+-
+-	  This code also includes SHA-384, a 384 bit hash with 192 bits
+-	  of security against collision attacks.
++	  Support for Counter with CBC MAC. Required for IPsec.
+ 
+-config CRYPTO_WP512
+-	tristate "Whirlpool digest algorithms"
+-	select CRYPTO_ALGAPI
++config CRYPTO_GCM
++	tristate "GCM/GMAC support"
++	select CRYPTO_CTR
++	select CRYPTO_AEAD
++	select CRYPTO_GF128MUL
+ 	help
+-	  Whirlpool hash algorithm 512, 384 and 256-bit hashes
+-
+-	  Whirlpool-512 is part of the NESSIE cryptographic primitives.
+-	  Whirlpool will be part of the ISO/IEC 10118-3:2003(E) standard
+-
+-	  See also:
+-	  <http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html>
++	  Support for Galois/Counter Mode (GCM) and Galois Message
++	  Authentication Code (GMAC). Required for IPSec.
+ 
+-config CRYPTO_TGR192
+-	tristate "Tiger digest algorithms"
+-	select CRYPTO_ALGAPI
++config CRYPTO_SEQIV
++	tristate "Sequence Number IV Generator"
++	select CRYPTO_AEAD
++	select CRYPTO_BLKCIPHER
+ 	help
+-	  Tiger hash algorithm 192, 160 and 128-bit hashes
+-
+-	  Tiger is a hash function optimized for 64-bit processors while
+-	  still having decent performance on 32-bit processors.
+-	  Tiger was developed by Ross Anderson and Eli Biham.
+-
+-	  See also:
+-	  <http://www.cs.technion.ac.il/~biham/Reports/Tiger/>.
++	  This IV generator generates an IV based on a sequence number by
++	  xoring it with a salt.  This algorithm is mainly useful for CTR
+ 
+-config CRYPTO_GF128MUL
+-	tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
+-	depends on EXPERIMENTAL
+-	help
+-	  Efficient table driven implementation of multiplications in the
+-	  field GF(2^128).  This is needed by some cypher modes. This
+-	  option will be selected automatically if you select such a
+-	  cipher mode.  Only select this option by hand if you expect to load
+-	  an external module that requires these functions.
++comment "Block modes"
+ 
+-config CRYPTO_ECB
+-	tristate "ECB support"
++config CRYPTO_CBC
++	tristate "CBC support"
+ 	select CRYPTO_BLKCIPHER
+ 	select CRYPTO_MANAGER
+ 	help
+-	  ECB: Electronic CodeBook mode
+-	  This is the simplest block cipher algorithm.  It simply encrypts
+-	  the input block by block.
++	  CBC: Cipher Block Chaining mode
++	  This block cipher algorithm is required for IPSec.
+ 
+-config CRYPTO_CBC
+-	tristate "CBC support"
++config CRYPTO_CTR
++	tristate "CTR support"
+ 	select CRYPTO_BLKCIPHER
++	select CRYPTO_SEQIV
+ 	select CRYPTO_MANAGER
+ 	help
+-	  CBC: Cipher Block Chaining mode
++	  CTR: Counter mode
+ 	  This block cipher algorithm is required for IPSec.
+ 
+-config CRYPTO_PCBC
+-	tristate "PCBC support"
++config CRYPTO_CTS
++	tristate "CTS support"
++	select CRYPTO_BLKCIPHER
++	help
++	  CTS: Cipher Text Stealing
++	  This is the Cipher Text Stealing mode as described by
++	  Section 8 of rfc2040 and referenced by rfc3962.
++	  (rfc3962 includes errata information in its Appendix A)
++	  This mode is required for Kerberos gss mechanism support
++	  for AES encryption.
++
++config CRYPTO_ECB
++	tristate "ECB support"
+ 	select CRYPTO_BLKCIPHER
+ 	select CRYPTO_MANAGER
+ 	help
+-	  PCBC: Propagating Cipher Block Chaining mode
+-	  This block cipher algorithm is required for RxRPC.
++	  ECB: Electronic CodeBook mode
++	  This is the simplest block cipher algorithm.  It simply encrypts
++	  the input block by block.
+ 
+ config CRYPTO_LRW
+ 	tristate "LRW support (EXPERIMENTAL)"
+@@ -193,6 +168,14 @@ config CRYPTO_LRW
+ 	  The first 128, 192 or 256 bits in the key are used for AES and the
+ 	  rest is used to tie each cipher block to its logical position.
+ 
++config CRYPTO_PCBC
++	tristate "PCBC support"
++	select CRYPTO_BLKCIPHER
++	select CRYPTO_MANAGER
++	help
++	  PCBC: Propagating Cipher Block Chaining mode
++	  This block cipher algorithm is required for RxRPC.
++
+ config CRYPTO_XTS
+ 	tristate "XTS support (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL
+@@ -204,149 +187,134 @@ config CRYPTO_XTS
+ 	  key size 256, 384 or 512 bits. This implementation currently
+ 	  can't handle a sectorsize which is not a multiple of 16 bytes.
+ 
+-config CRYPTO_CTR
+-	tristate "CTR support"
+-	select CRYPTO_BLKCIPHER
+-	select CRYPTO_SEQIV
++comment "Hash modes"
++
++config CRYPTO_HMAC
++	tristate "HMAC support"
++	select CRYPTO_HASH
+ 	select CRYPTO_MANAGER
+ 	help
+-	  CTR: Counter mode
+-	  This block cipher algorithm is required for IPSec.
++	  HMAC: Keyed-Hashing for Message Authentication (RFC2104).
++	  This is required for IPSec.
+ 
+-config CRYPTO_GCM
+-	tristate "GCM/GMAC support"
+-	select CRYPTO_CTR
+-	select CRYPTO_AEAD
+-	select CRYPTO_GF128MUL
++config CRYPTO_XCBC
++	tristate "XCBC support"
++	depends on EXPERIMENTAL
++	select CRYPTO_HASH
++	select CRYPTO_MANAGER
+ 	help
+-	  Support for Galois/Counter Mode (GCM) and Galois Message
+-	  Authentication Code (GMAC). Required for IPSec.
++	  XCBC: Keyed-Hashing with encryption algorithm
++		http://www.ietf.org/rfc/rfc3566.txt
++		http://csrc.nist.gov/encryption/modes/proposedmodes/
++		 xcbc-mac/xcbc-mac-spec.pdf
+ 
+-config CRYPTO_CCM
+-	tristate "CCM support"
+-	select CRYPTO_CTR
+-	select CRYPTO_AEAD
+-	help
+-	  Support for Counter with CBC MAC. Required for IPsec.
++comment "Digest"
+ 
+-config CRYPTO_CRYPTD
+-	tristate "Software async crypto daemon"
+-	select CRYPTO_BLKCIPHER
+-	select CRYPTO_MANAGER
++config CRYPTO_CRC32C
++	tristate "CRC32c CRC algorithm"
++	select CRYPTO_ALGAPI
++	select LIBCRC32C
+ 	help
+-	  This is a generic software asynchronous crypto daemon that
+-	  converts an arbitrary synchronous software crypto algorithm
+-	  into an asynchronous algorithm that executes in a kernel thread.
++	  Castagnoli, et al Cyclic Redundancy-Check Algorithm.  Used
++	  by iSCSI for header and data digests and by others.
++	  See Castagnoli93.  This implementation uses lib/libcrc32c.
++          Module will be crc32c.
+ 
+-config CRYPTO_DES
+-	tristate "DES and Triple DES EDE cipher algorithms"
++config CRYPTO_MD4
++	tristate "MD4 digest algorithm"
+ 	select CRYPTO_ALGAPI
+ 	help
+-	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
++	  MD4 message digest algorithm (RFC1320).
+ 
+-config CRYPTO_FCRYPT
+-	tristate "FCrypt cipher algorithm"
++config CRYPTO_MD5
++	tristate "MD5 digest algorithm"
+ 	select CRYPTO_ALGAPI
+-	select CRYPTO_BLKCIPHER
+ 	help
+-	  FCrypt algorithm used by RxRPC.
++	  MD5 message digest algorithm (RFC1321).
+ 
+-config CRYPTO_BLOWFISH
+-	tristate "Blowfish cipher algorithm"
++config CRYPTO_MICHAEL_MIC
++	tristate "Michael MIC keyed digest algorithm"
+ 	select CRYPTO_ALGAPI
+ 	help
+-	  Blowfish cipher algorithm, by Bruce Schneier.
+-	  
+-	  This is a variable key length cipher which can use keys from 32
+-	  bits to 448 bits in length.  It's fast, simple and specifically
+-	  designed for use on "large microprocessors".
+-	  
+-	  See also:
+-	  <http://www.schneier.com/blowfish.html>
++	  Michael MIC is used for message integrity protection in TKIP
++	  (IEEE 802.11i). This algorithm is required for TKIP, but it
++	  should not be used for other purposes because of the weakness
++	  of the algorithm.
+ 
+-config CRYPTO_TWOFISH
+-	tristate "Twofish cipher algorithm"
++config CRYPTO_SHA1
++	tristate "SHA1 digest algorithm"
+ 	select CRYPTO_ALGAPI
+-	select CRYPTO_TWOFISH_COMMON
+ 	help
+-	  Twofish cipher algorithm.
+-	  
+-	  Twofish was submitted as an AES (Advanced Encryption Standard)
+-	  candidate cipher by researchers at CounterPane Systems.  It is a
+-	  16 round block cipher supporting key sizes of 128, 192, and 256
+-	  bits.
+-	  
+-	  See also:
+-	  <http://www.schneier.com/twofish.html>
++	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+ 
+-config CRYPTO_TWOFISH_COMMON
+-	tristate
++config CRYPTO_SHA256
++	tristate "SHA224 and SHA256 digest algorithm"
++	select CRYPTO_ALGAPI
+ 	help
+-	  Common parts of the Twofish cipher algorithm shared by the
+-	  generic c and the assembler implementations.
++	  SHA256 secure hash standard (DFIPS 180-2).
+ 
+-config CRYPTO_TWOFISH_586
+-	tristate "Twofish cipher algorithms (i586)"
+-	depends on (X86 || UML_X86) && !64BIT
++	  This version of SHA implements a 256 bit hash with 128 bits of
++	  security against collision attacks.
++
++          This code also includes SHA-224, a 224 bit hash with 112 bits
++          of security against collision attacks.
++
++config CRYPTO_SHA512
++	tristate "SHA384 and SHA512 digest algorithms"
+ 	select CRYPTO_ALGAPI
+-	select CRYPTO_TWOFISH_COMMON
+ 	help
+-	  Twofish cipher algorithm.
++	  SHA512 secure hash standard (DFIPS 180-2).
+ 
+-	  Twofish was submitted as an AES (Advanced Encryption Standard)
+-	  candidate cipher by researchers at CounterPane Systems.  It is a
+-	  16 round block cipher supporting key sizes of 128, 192, and 256
+-	  bits.
++	  This version of SHA implements a 512 bit hash with 256 bits of
++	  security against collision attacks.
+ 
+-	  See also:
+-	  <http://www.schneier.com/twofish.html>
++	  This code also includes SHA-384, a 384 bit hash with 192 bits
++	  of security against collision attacks.
+ 
+-config CRYPTO_TWOFISH_X86_64
+-	tristate "Twofish cipher algorithm (x86_64)"
+-	depends on (X86 || UML_X86) && 64BIT
++config CRYPTO_TGR192
++	tristate "Tiger digest algorithms"
+ 	select CRYPTO_ALGAPI
+-	select CRYPTO_TWOFISH_COMMON
+ 	help
+-	  Twofish cipher algorithm (x86_64).
++	  Tiger hash algorithm 192, 160 and 128-bit hashes
+ 
+-	  Twofish was submitted as an AES (Advanced Encryption Standard)
+-	  candidate cipher by researchers at CounterPane Systems.  It is a
+-	  16 round block cipher supporting key sizes of 128, 192, and 256
+-	  bits.
++	  Tiger is a hash function optimized for 64-bit processors while
++	  still having decent performance on 32-bit processors.
++	  Tiger was developed by Ross Anderson and Eli Biham.
+ 
+ 	  See also:
+-	  <http://www.schneier.com/twofish.html>
++	  <http://www.cs.technion.ac.il/~biham/Reports/Tiger/>.
+ 
+-config CRYPTO_SERPENT
+-	tristate "Serpent cipher algorithm"
++config CRYPTO_WP512
++	tristate "Whirlpool digest algorithms"
+ 	select CRYPTO_ALGAPI
+ 	help
+-	  Serpent cipher algorithm, by Anderson, Biham & Knudsen.
++	  Whirlpool hash algorithm 512, 384 and 256-bit hashes
+ 
+-	  Keys are allowed to be from 0 to 256 bits in length, in steps
+-	  of 8 bits.  Also includes the 'Tnepres' algorithm, a reversed
+-	  variant of Serpent for compatibility with old kerneli.org code.
++	  Whirlpool-512 is part of the NESSIE cryptographic primitives.
++	  Whirlpool will be part of the ISO/IEC 10118-3:2003(E) standard
+ 
+ 	  See also:
+-	  <http://www.cl.cam.ac.uk/~rja14/serpent.html>
++	  <http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html>
++
++comment "Ciphers"
+ 
+ config CRYPTO_AES
+ 	tristate "AES cipher algorithms"
+ 	select CRYPTO_ALGAPI
+ 	help
+-	  AES cipher algorithms (FIPS-197). AES uses the Rijndael 
++	  AES cipher algorithms (FIPS-197). AES uses the Rijndael
+ 	  algorithm.
+ 
+ 	  Rijndael appears to be consistently a very good performer in
+-	  both hardware and software across a wide range of computing 
+-	  environments regardless of its use in feedback or non-feedback 
+-	  modes. Its key setup time is excellent, and its key agility is 
+-	  good. Rijndael's very low memory requirements make it very well 
+-	  suited for restricted-space environments, in which it also 
+-	  demonstrates excellent performance. Rijndael's operations are 
+-	  among the easiest to defend against power and timing attacks.	
++	  both hardware and software across a wide range of computing
++	  environments regardless of its use in feedback or non-feedback
++	  modes. Its key setup time is excellent, and its key agility is
++	  good. Rijndael's very low memory requirements make it very well
++	  suited for restricted-space environments, in which it also
++	  demonstrates excellent performance. Rijndael's operations are
++	  among the easiest to defend against power and timing attacks.
+ 
+-	  The AES specifies three key sizes: 128, 192 and 256 bits	  
++	  The AES specifies three key sizes: 128, 192 and 256 bits
+ 
+ 	  See <http://csrc.nist.gov/CryptoToolkit/aes/> for more information.
+ 
+@@ -356,19 +324,19 @@ config CRYPTO_AES_586
+ 	select CRYPTO_ALGAPI
+ 	select CRYPTO_AES
+ 	help
+-	  AES cipher algorithms (FIPS-197). AES uses the Rijndael 
++	  AES cipher algorithms (FIPS-197). AES uses the Rijndael
+ 	  algorithm.
+ 
+ 	  Rijndael appears to be consistently a very good performer in
+-	  both hardware and software across a wide range of computing 
+-	  environments regardless of its use in feedback or non-feedback 
+-	  modes. Its key setup time is excellent, and its key agility is 
+-	  good. Rijndael's very low memory requirements make it very well 
+-	  suited for restricted-space environments, in which it also 
+-	  demonstrates excellent performance. Rijndael's operations are 
+-	  among the easiest to defend against power and timing attacks.	
++	  both hardware and software across a wide range of computing
++	  environments regardless of its use in feedback or non-feedback
++	  modes. Its key setup time is excellent, and its key agility is
++	  good. Rijndael's very low memory requirements make it very well
++	  suited for restricted-space environments, in which it also
++	  demonstrates excellent performance. Rijndael's operations are
++	  among the easiest to defend against power and timing attacks.
+ 
+-	  The AES specifies three key sizes: 128, 192 and 256 bits	  
++	  The AES specifies three key sizes: 128, 192 and 256 bits
+ 
+ 	  See <http://csrc.nist.gov/encryption/aes/> for more information.
+ 
+@@ -378,22 +346,75 @@ config CRYPTO_AES_X86_64
+ 	select CRYPTO_ALGAPI
+ 	select CRYPTO_AES
+ 	help
+-	  AES cipher algorithms (FIPS-197). AES uses the Rijndael 
++	  AES cipher algorithms (FIPS-197). AES uses the Rijndael
+ 	  algorithm.
+ 
+ 	  Rijndael appears to be consistently a very good performer in
+-	  both hardware and software across a wide range of computing 
+-	  environments regardless of its use in feedback or non-feedback 
+-	  modes. Its key setup time is excellent, and its key agility is 
+-	  good. Rijndael's very low memory requirements make it very well 
+-	  suited for restricted-space environments, in which it also 
+-	  demonstrates excellent performance. Rijndael's operations are 
+-	  among the easiest to defend against power and timing attacks.	
++	  both hardware and software across a wide range of computing
++	  environments regardless of its use in feedback or non-feedback
++	  modes. Its key setup time is excellent, and its key agility is
++	  good. Rijndael's very low memory requirements make it very well
++	  suited for restricted-space environments, in which it also
++	  demonstrates excellent performance. Rijndael's operations are
++	  among the easiest to defend against power and timing attacks.
+ 
+-	  The AES specifies three key sizes: 128, 192 and 256 bits	  
++	  The AES specifies three key sizes: 128, 192 and 256 bits
+ 
+ 	  See <http://csrc.nist.gov/encryption/aes/> for more information.
+ 
++config CRYPTO_ANUBIS
++	tristate "Anubis cipher algorithm"
++	select CRYPTO_ALGAPI
++	help
++	  Anubis cipher algorithm.
++
++	  Anubis is a variable key length cipher which can use keys from
++	  128 bits to 320 bits in length.  It was evaluated as a entrant
++	  in the NESSIE competition.
++
++	  See also:
++	  <https://www.cosic.esat.kuleuven.ac.be/nessie/reports/>
++	  <http://planeta.terra.com.br/informatica/paulobarreto/AnubisPage.html>
++
++config CRYPTO_ARC4
++	tristate "ARC4 cipher algorithm"
++	select CRYPTO_ALGAPI
++	help
++	  ARC4 cipher algorithm.
++
++	  ARC4 is a stream cipher using keys ranging from 8 bits to 2048
++	  bits in length.  This algorithm is required for driver-based
++	  WEP, but it should not be for other purposes because of the
++	  weakness of the algorithm.
++
++config CRYPTO_BLOWFISH
++	tristate "Blowfish cipher algorithm"
++	select CRYPTO_ALGAPI
++	help
++	  Blowfish cipher algorithm, by Bruce Schneier.
++
++	  This is a variable key length cipher which can use keys from 32
++	  bits to 448 bits in length.  It's fast, simple and specifically
++	  designed for use on "large microprocessors".
++
++	  See also:
++	  <http://www.schneier.com/blowfish.html>
++
++config CRYPTO_CAMELLIA
++	tristate "Camellia cipher algorithms"
++	depends on CRYPTO
++	select CRYPTO_ALGAPI
++	help
++	  Camellia cipher algorithms module.
++
++	  Camellia is a symmetric key block cipher developed jointly
++	  at NTT and Mitsubishi Electric Corporation.
++
++	  The Camellia specifies three key sizes: 128, 192 and 256 bits.
++
++	  See also:
++	  <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
++
+ config CRYPTO_CAST5
+ 	tristate "CAST5 (CAST-128) cipher algorithm"
+ 	select CRYPTO_ALGAPI
+@@ -408,33 +429,18 @@ config CRYPTO_CAST6
+ 	  The CAST6 encryption algorithm (synonymous with CAST-256) is
+ 	  described in RFC2612.
+ 
+-config CRYPTO_TEA
+-	tristate "TEA, XTEA and XETA cipher algorithms"
++config CRYPTO_DES
++	tristate "DES and Triple DES EDE cipher algorithms"
+ 	select CRYPTO_ALGAPI
+ 	help
+-	  TEA cipher algorithm.
+-
+-	  Tiny Encryption Algorithm is a simple cipher that uses
+-	  many rounds for security.  It is very fast and uses
+-	  little memory.
+-
+-	  Xtendend Tiny Encryption Algorithm is a modification to
+-	  the TEA algorithm to address a potential key weakness
+-	  in the TEA algorithm.
+-
+-	  Xtendend Encryption Tiny Algorithm is a mis-implementation 
+-	  of the XTEA algorithm for compatibility purposes.
++	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
+ 
+-config CRYPTO_ARC4
+-	tristate "ARC4 cipher algorithm"
++config CRYPTO_FCRYPT
++	tristate "FCrypt cipher algorithm"
+ 	select CRYPTO_ALGAPI
++	select CRYPTO_BLKCIPHER
+ 	help
+-	  ARC4 cipher algorithm.
+-
+-	  ARC4 is a stream cipher using keys ranging from 8 bits to 2048
+-	  bits in length.  This algorithm is required for driver-based 
+-	  WEP, but it should not be for other purposes because of the
+-	  weakness of the algorithm.
++	  FCrypt algorithm used by RxRPC.
+ 
+ config CRYPTO_KHAZAD
+ 	tristate "Khazad cipher algorithm"
+@@ -449,34 +455,6 @@ config CRYPTO_KHAZAD
+ 	  See also:
+ 	  <http://planeta.terra.com.br/informatica/paulobarreto/KhazadPage.html>
+ 
+-config CRYPTO_ANUBIS
+-	tristate "Anubis cipher algorithm"
+-	select CRYPTO_ALGAPI
+-	help
+-	  Anubis cipher algorithm.
+-
+-	  Anubis is a variable key length cipher which can use keys from 
+-	  128 bits to 320 bits in length.  It was evaluated as a entrant
+-	  in the NESSIE competition.
+-	  
+-	  See also:
+-	  <https://www.cosic.esat.kuleuven.ac.be/nessie/reports/>
+-	  <http://planeta.terra.com.br/informatica/paulobarreto/AnubisPage.html>
+-
+-config CRYPTO_SEED
+-	tristate "SEED cipher algorithm"
+-	select CRYPTO_ALGAPI
+-	help
+-	  SEED cipher algorithm (RFC4269).
+-
+-	  SEED is a 128-bit symmetric key block cipher that has been
+-	  developed by KISA (Korea Information Security Agency) as a
+-	  national standard encryption algorithm of the Republic of Korea.
+-	  It is a 16 round block cipher with the key size of 128 bit.
+-
+-	  See also:
+-	  <http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp>
+-
+ config CRYPTO_SALSA20
+ 	tristate "Salsa20 stream cipher algorithm (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL
+@@ -518,69 +496,115 @@ config CRYPTO_SALSA20_X86_64
+ 	  The Salsa20 stream cipher algorithm is designed by Daniel J.
+ 	  Bernstein <djb at cr.yp.to>. See <http://cr.yp.to/snuffle.html>
+ 
+-config CRYPTO_DEFLATE
+-	tristate "Deflate compression algorithm"
++config CRYPTO_SEED
++	tristate "SEED cipher algorithm"
+ 	select CRYPTO_ALGAPI
+-	select ZLIB_INFLATE
+-	select ZLIB_DEFLATE
+ 	help
+-	  This is the Deflate algorithm (RFC1951), specified for use in
+-	  IPSec with the IPCOMP protocol (RFC3173, RFC2394).
+-	  
+-	  You will most probably want this if using IPSec.
++	  SEED cipher algorithm (RFC4269).
+ 
+-config CRYPTO_MICHAEL_MIC
+-	tristate "Michael MIC keyed digest algorithm"
++	  SEED is a 128-bit symmetric key block cipher that has been
++	  developed by KISA (Korea Information Security Agency) as a
++	  national standard encryption algorithm of the Republic of Korea.
++	  It is a 16 round block cipher with the key size of 128 bit.
++
++	  See also:
++	  <http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp>
++
++config CRYPTO_SERPENT
++	tristate "Serpent cipher algorithm"
+ 	select CRYPTO_ALGAPI
+ 	help
+-	  Michael MIC is used for message integrity protection in TKIP
+-	  (IEEE 802.11i). This algorithm is required for TKIP, but it
+-	  should not be used for other purposes because of the weakness
+-	  of the algorithm.
++	  Serpent cipher algorithm, by Anderson, Biham & Knudsen.
+ 
+-config CRYPTO_CRC32C
+-	tristate "CRC32c CRC algorithm"
++	  Keys are allowed to be from 0 to 256 bits in length, in steps
++	  of 8 bits.  Also includes the 'Tnepres' algorithm, a reversed
++	  variant of Serpent for compatibility with old kerneli.org code.
++
++	  See also:
++	  <http://www.cl.cam.ac.uk/~rja14/serpent.html>
++
++config CRYPTO_TEA
++	tristate "TEA, XTEA and XETA cipher algorithms"
+ 	select CRYPTO_ALGAPI
+-	select LIBCRC32C
+ 	help
+-	  Castagnoli, et al Cyclic Redundancy-Check Algorithm.  Used
+-	  by iSCSI for header and data digests and by others.
+-	  See Castagnoli93.  This implementation uses lib/libcrc32c.
+-          Module will be crc32c.
++	  TEA cipher algorithm.
+ 
+-config CRYPTO_CAMELLIA
+-	tristate "Camellia cipher algorithms"
+-	depends on CRYPTO
++	  Tiny Encryption Algorithm is a simple cipher that uses
++	  many rounds for security.  It is very fast and uses
++	  little memory.
++
++	  Xtendend Tiny Encryption Algorithm is a modification to
++	  the TEA algorithm to address a potential key weakness
++	  in the TEA algorithm.
++
++	  Xtendend Encryption Tiny Algorithm is a mis-implementation
++	  of the XTEA algorithm for compatibility purposes.
++
++config CRYPTO_TWOFISH
++	tristate "Twofish cipher algorithm"
+ 	select CRYPTO_ALGAPI
++	select CRYPTO_TWOFISH_COMMON
+ 	help
+-	  Camellia cipher algorithms module.
++	  Twofish cipher algorithm.
+ 
+-	  Camellia is a symmetric key block cipher developed jointly
+-	  at NTT and Mitsubishi Electric Corporation.
++	  Twofish was submitted as an AES (Advanced Encryption Standard)
++	  candidate cipher by researchers at CounterPane Systems.  It is a
++	  16 round block cipher supporting key sizes of 128, 192, and 256
++	  bits.
+ 
+-	  The Camellia specifies three key sizes: 128, 192 and 256 bits.
++	  See also:
++	  <http://www.schneier.com/twofish.html>
++
++config CRYPTO_TWOFISH_COMMON
++	tristate
++	help
++	  Common parts of the Twofish cipher algorithm shared by the
++	  generic c and the assembler implementations.
++
++config CRYPTO_TWOFISH_586
++	tristate "Twofish cipher algorithms (i586)"
++	depends on (X86 || UML_X86) && !64BIT
++	select CRYPTO_ALGAPI
++	select CRYPTO_TWOFISH_COMMON
++	help
++	  Twofish cipher algorithm.
++
++	  Twofish was submitted as an AES (Advanced Encryption Standard)
++	  candidate cipher by researchers at CounterPane Systems.  It is a
++	  16 round block cipher supporting key sizes of 128, 192, and 256
++	  bits.
+ 
+ 	  See also:
+-	  <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
++	  <http://www.schneier.com/twofish.html>
+ 
+-config CRYPTO_TEST
+-	tristate "Testing module"
+-	depends on m
++config CRYPTO_TWOFISH_X86_64
++	tristate "Twofish cipher algorithm (x86_64)"
++	depends on (X86 || UML_X86) && 64BIT
+ 	select CRYPTO_ALGAPI
+-	select CRYPTO_AEAD
+-	select CRYPTO_BLKCIPHER
++	select CRYPTO_TWOFISH_COMMON
+ 	help
+-	  Quick & dirty crypto test module.
++	  Twofish cipher algorithm (x86_64).
+ 
+-config CRYPTO_AUTHENC
+-	tristate "Authenc support"
+-	select CRYPTO_AEAD
+-	select CRYPTO_BLKCIPHER
+-	select CRYPTO_MANAGER
+-	select CRYPTO_HASH
++	  Twofish was submitted as an AES (Advanced Encryption Standard)
++	  candidate cipher by researchers at CounterPane Systems.  It is a
++	  16 round block cipher supporting key sizes of 128, 192, and 256
++	  bits.
++
++	  See also:
++	  <http://www.schneier.com/twofish.html>
++
++comment "Compression"
++
++config CRYPTO_DEFLATE
++	tristate "Deflate compression algorithm"
++	select CRYPTO_ALGAPI
++	select ZLIB_INFLATE
++	select ZLIB_DEFLATE
+ 	help
+-	  Authenc: Combined mode wrapper for IPsec.
+-	  This is required for IPSec.
++	  This is the Deflate algorithm (RFC1951), specified for use in
++	  IPSec with the IPCOMP protocol (RFC3173, RFC2394).
++
++	  You will most probably want this if using IPSec.
+ 
+ config CRYPTO_LZO
+ 	tristate "LZO compression algorithm"
+diff --git a/crypto/Makefile b/crypto/Makefile
+index 7cf3625..ca02441 100644
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -2,7 +2,8 @@
+ # Cryptographic API
+ #
+ 
+-obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o
++obj-$(CONFIG_CRYPTO) += crypto.o
++crypto-objs := api.o cipher.o digest.o compress.o
+ 
+ crypto_algapi-$(CONFIG_PROC_FS) += proc.o
+ crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
+@@ -28,13 +29,14 @@ obj-$(CONFIG_CRYPTO_MD4) += md4.o
+ obj-$(CONFIG_CRYPTO_MD5) += md5.o
+ obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o
+ obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o
+-obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
++obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o
+ obj-$(CONFIG_CRYPTO_WP512) += wp512.o
+ obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
+ obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
+ obj-$(CONFIG_CRYPTO_ECB) += ecb.o
+ obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+ obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
++obj-$(CONFIG_CRYPTO_CTS) += cts.o
+ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
+ obj-$(CONFIG_CRYPTO_XTS) += xts.o
+ obj-$(CONFIG_CRYPTO_CTR) += ctr.o
+diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c
+index cf30af7..136dc98 100644
+--- a/crypto/aes_generic.c
++++ b/crypto/aes_generic.c
+@@ -229,18 +229,29 @@ static void __init gen_tabs(void)
+ 	ctx->key_enc[8 * i + 15] = t;			\
+ } while (0)
+ 
+-int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
++/**
++ * crypto_aes_expand_key - Expands the AES key as described in FIPS-197
++ * @ctx:	The location where the computed key will be stored.
++ * @in_key:	The supplied key.
++ * @key_len:	The length of the supplied key.
++ *
++ * Returns 0 on success. The function fails only if an invalid key size (or
++ * pointer) is supplied.
++ * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes
++ * key schedule plus a 16 bytes key which is used before the first round).
++ * The decryption key is prepared for the "Equivalent Inverse Cipher" as
++ * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is
++ * for the initial combination, the second slot for the first round and so on.
++ */
++int crypto_aes_expand_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
+ 		unsigned int key_len)
+ {
+-	struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ 	const __le32 *key = (const __le32 *)in_key;
+-	u32 *flags = &tfm->crt_flags;
+ 	u32 i, t, u, v, w, j;
+ 
+-	if (key_len % 8) {
+-		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++	if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 &&
++			key_len != AES_KEYSIZE_256)
+ 		return -EINVAL;
+-	}
+ 
+ 	ctx->key_length = key_len;
+ 
+@@ -250,20 +261,20 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 	ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]);
+ 
+ 	switch (key_len) {
+-	case 16:
++	case AES_KEYSIZE_128:
+ 		t = ctx->key_enc[3];
+ 		for (i = 0; i < 10; ++i)
+ 			loop4(i);
+ 		break;
+ 
+-	case 24:
++	case AES_KEYSIZE_192:
+ 		ctx->key_enc[4] = le32_to_cpu(key[4]);
+ 		t = ctx->key_enc[5] = le32_to_cpu(key[5]);
+ 		for (i = 0; i < 8; ++i)
+ 			loop6(i);
+ 		break;
+ 
+-	case 32:
++	case AES_KEYSIZE_256:
+ 		ctx->key_enc[4] = le32_to_cpu(key[4]);
+ 		ctx->key_enc[5] = le32_to_cpu(key[5]);
+ 		ctx->key_enc[6] = le32_to_cpu(key[6]);
+@@ -284,6 +295,33 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 	}
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(crypto_aes_expand_key);
++
++/**
++ * crypto_aes_set_key - Set the AES key.
++ * @tfm:	The %crypto_tfm that is used in the context.
++ * @in_key:	The input key.
++ * @key_len:	The size of the key.
++ *
++ * Returns 0 on success, on failure the %CRYPTO_TFM_RES_BAD_KEY_LEN flag in tfm
++ * is set. The function uses crypto_aes_expand_key() to expand the key.
++ * &crypto_aes_ctx _must_ be the private data embedded in @tfm which is
++ * retrieved with crypto_tfm_ctx().
++ */
++int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
++		unsigned int key_len)
++{
++	struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
++	u32 *flags = &tfm->crt_flags;
++	int ret;
++
++	ret = crypto_aes_expand_key(ctx, in_key, key_len);
++	if (!ret)
++		return 0;
++
++	*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++	return -EINVAL;
++}
+ EXPORT_SYMBOL_GPL(crypto_aes_set_key);
+ 
+ /* encrypt a block of text */
+diff --git a/crypto/anubis.c b/crypto/anubis.c
+index 4ff0e1e..e42c3a8 100644
+--- a/crypto/anubis.c
++++ b/crypto/anubis.c
+@@ -687,7 +687,7 @@ static struct crypto_alg anubis_alg = {
+ 	.cia_decrypt		=	anubis_decrypt } }
+ };
+ 
+-static int __init init(void)
++static int __init anubis_mod_init(void)
+ {
+ 	int ret = 0;
+ 	
+@@ -695,13 +695,13 @@ static int __init init(void)
+ 	return ret;
+ }
+ 
+-static void __exit fini(void)
++static void __exit anubis_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&anubis_alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(anubis_mod_init);
++module_exit(anubis_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Anubis Cryptographic Algorithm");
+diff --git a/crypto/api.c b/crypto/api.c
+index a2496d1..0a0f41e 100644
+--- a/crypto/api.c
++++ b/crypto/api.c
+@@ -445,3 +445,6 @@ int crypto_has_alg(const char *name, u32 type, u32 mask)
+ 	return ret;
+ }
+ EXPORT_SYMBOL_GPL(crypto_has_alg);
++
++MODULE_DESCRIPTION("Cryptographic core API");
++MODULE_LICENSE("GPL");
+diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
+index 84caa4e..a5eda80 100644
+--- a/crypto/async_tx/async_memcpy.c
++++ b/crypto/async_tx/async_memcpy.c
+@@ -77,7 +77,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+ 			/* if ack is already set then we cannot be sure
+ 			 * we are referring to the correct operation
+ 			 */
+-			BUG_ON(depend_tx->ack);
++			BUG_ON(async_tx_test_ack(depend_tx));
+ 			if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ 				panic("%s: DMA_ERROR waiting for depend_tx\n",
+ 					__func__);
+diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
+index 2be3bae..c6e772f 100644
+--- a/crypto/async_tx/async_tx.c
++++ b/crypto/async_tx/async_tx.c
+@@ -89,13 +89,19 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+ 		iter = tx;
+ 
+ 		/* find the root of the unsubmitted dependency chain */
+-		while (iter->cookie == -EBUSY) {
++		do {
+ 			parent = iter->parent;
+-			if (parent && parent->cookie == -EBUSY)
+-				iter = iter->parent;
+-			else
++			if (!parent)
+ 				break;
+-		}
++			else
++				iter = parent;
++		} while (parent);
++
++		/* there is a small window for ->parent == NULL and
++		 * ->cookie == -EBUSY
++		 */
++		while (iter->cookie == -EBUSY)
++			cpu_relax();
+ 
+ 		status = dma_sync_wait(iter->chan, iter->cookie);
+ 	} while (status == DMA_IN_PROGRESS || (iter != tx));
+@@ -111,24 +117,33 @@ EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
+ void
+ async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
+ {
+-	struct dma_async_tx_descriptor *dep_tx, *_dep_tx;
+-	struct dma_device *dev;
++	struct dma_async_tx_descriptor *next = tx->next;
+ 	struct dma_chan *chan;
+ 
+-	list_for_each_entry_safe(dep_tx, _dep_tx, &tx->depend_list,
+-		depend_node) {
+-		chan = dep_tx->chan;
+-		dev = chan->device;
+-		/* we can't depend on ourselves */
+-		BUG_ON(chan == tx->chan);
+-		list_del(&dep_tx->depend_node);
+-		tx->tx_submit(dep_tx);
+-
+-		/* we need to poke the engine as client code does not
+-		 * know about dependency submission events
+-		 */
+-		dev->device_issue_pending(chan);
++	if (!next)
++		return;
++
++	tx->next = NULL;
++	chan = next->chan;
++
++	/* keep submitting up until a channel switch is detected
++	 * in that case we will be called again as a result of
++	 * processing the interrupt from async_tx_channel_switch
++	 */
++	while (next && next->chan == chan) {
++		struct dma_async_tx_descriptor *_next;
++
++		spin_lock_bh(&next->lock);
++		next->parent = NULL;
++		_next = next->next;
++		next->next = NULL;
++		spin_unlock_bh(&next->lock);
++
++		next->tx_submit(next);
++		next = _next;
+ 	}
++
++	chan->device->device_issue_pending(chan);
+ }
+ EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
+ 
+@@ -397,6 +412,92 @@ static void __exit async_tx_exit(void)
+ }
+ #endif
+ 
++
++/**
++ * async_tx_channel_switch - queue an interrupt descriptor with a dependency
++ * 	pre-attached.
++ * @depend_tx: the operation that must finish before the new operation runs
++ * @tx: the new operation
++ */
++static void
++async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx,
++			struct dma_async_tx_descriptor *tx)
++{
++	struct dma_chan *chan;
++	struct dma_device *device;
++	struct dma_async_tx_descriptor *intr_tx = (void *) ~0;
++
++	/* first check to see if we can still append to depend_tx */
++	spin_lock_bh(&depend_tx->lock);
++	if (depend_tx->parent && depend_tx->chan == tx->chan) {
++		tx->parent = depend_tx;
++		depend_tx->next = tx;
++		intr_tx = NULL;
++	}
++	spin_unlock_bh(&depend_tx->lock);
++
++	if (!intr_tx)
++		return;
++
++	chan = depend_tx->chan;
++	device = chan->device;
++
++	/* see if we can schedule an interrupt
++	 * otherwise poll for completion
++	 */
++	if (dma_has_cap(DMA_INTERRUPT, device->cap_mask))
++		intr_tx = device->device_prep_dma_interrupt(chan, 0);
++	else
++		intr_tx = NULL;
++
++	if (intr_tx) {
++		intr_tx->callback = NULL;
++		intr_tx->callback_param = NULL;
++		tx->parent = intr_tx;
++		/* safe to set ->next outside the lock since we know we are
++		 * not submitted yet
++		 */
++		intr_tx->next = tx;
++
++		/* check if we need to append */
++		spin_lock_bh(&depend_tx->lock);
++		if (depend_tx->parent) {
++			intr_tx->parent = depend_tx;
++			depend_tx->next = intr_tx;
++			async_tx_ack(intr_tx);
++			intr_tx = NULL;
++		}
++		spin_unlock_bh(&depend_tx->lock);
++
++		if (intr_tx) {
++			intr_tx->parent = NULL;
++			intr_tx->tx_submit(intr_tx);
++			async_tx_ack(intr_tx);
++		}
++	} else {
++		if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
++			panic("%s: DMA_ERROR waiting for depend_tx\n",
++			      __func__);
++		tx->tx_submit(tx);
++	}
++}
++
++
++/**
++ * submit_disposition - while holding depend_tx->lock we must avoid submitting
++ * 	new operations to prevent a circular locking dependency with
++ * 	drivers that already hold a channel lock when calling
++ * 	async_tx_run_dependencies.
++ * @ASYNC_TX_SUBMITTED: we were able to append the new operation under the lock
++ * @ASYNC_TX_CHANNEL_SWITCH: when the lock is dropped schedule a channel switch
++ * @ASYNC_TX_DIRECT_SUBMIT: when the lock is dropped submit directly
++ */
++enum submit_disposition {
++	ASYNC_TX_SUBMITTED,
++	ASYNC_TX_CHANNEL_SWITCH,
++	ASYNC_TX_DIRECT_SUBMIT,
++};
++
+ void
+ async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+ 	enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+@@ -405,28 +506,55 @@ async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+ 	tx->callback = cb_fn;
+ 	tx->callback_param = cb_param;
+ 
+-	/* set this new tx to run after depend_tx if:
+-	 * 1/ a dependency exists (depend_tx is !NULL)
+-	 * 2/ the tx can not be submitted to the current channel
+-	 */
+-	if (depend_tx && depend_tx->chan != chan) {
+-		/* if ack is already set then we cannot be sure
++	if (depend_tx) {
++		enum submit_disposition s;
++
++		/* sanity check the dependency chain:
++		 * 1/ if ack is already set then we cannot be sure
+ 		 * we are referring to the correct operation
++		 * 2/ dependencies are 1:1 i.e. two transactions can
++		 * not depend on the same parent
+ 		 */
+-		BUG_ON(depend_tx->ack);
++		BUG_ON(async_tx_test_ack(depend_tx) || depend_tx->next ||
++		       tx->parent);
+ 
+-		tx->parent = depend_tx;
++		/* the lock prevents async_tx_run_dependencies from missing
++		 * the setting of ->next when ->parent != NULL
++		 */
+ 		spin_lock_bh(&depend_tx->lock);
+-		list_add_tail(&tx->depend_node, &depend_tx->depend_list);
+-		if (depend_tx->cookie == 0) {
+-			struct dma_chan *dep_chan = depend_tx->chan;
+-			struct dma_device *dep_dev = dep_chan->device;
+-			dep_dev->device_dependency_added(dep_chan);
++		if (depend_tx->parent) {
++			/* we have a parent so we can not submit directly
++			 * if we are staying on the same channel: append
++			 * else: channel switch
++			 */
++			if (depend_tx->chan == chan) {
++				tx->parent = depend_tx;
++				depend_tx->next = tx;
++				s = ASYNC_TX_SUBMITTED;
++			} else
++				s = ASYNC_TX_CHANNEL_SWITCH;
++		} else {
++			/* we do not have a parent so we may be able to submit
++			 * directly if we are staying on the same channel
++			 */
++			if (depend_tx->chan == chan)
++				s = ASYNC_TX_DIRECT_SUBMIT;
++			else
++				s = ASYNC_TX_CHANNEL_SWITCH;
+ 		}
+ 		spin_unlock_bh(&depend_tx->lock);
+ 
+-		/* schedule an interrupt to trigger the channel switch */
+-		async_trigger_callback(ASYNC_TX_ACK, depend_tx, NULL, NULL);
++		switch (s) {
++		case ASYNC_TX_SUBMITTED:
++			break;
++		case ASYNC_TX_CHANNEL_SWITCH:
++			async_tx_channel_switch(depend_tx, tx);
++			break;
++		case ASYNC_TX_DIRECT_SUBMIT:
++			tx->parent = NULL;
++			tx->tx_submit(tx);
++			break;
++		}
+ 	} else {
+ 		tx->parent = NULL;
+ 		tx->tx_submit(tx);
+@@ -467,7 +595,7 @@ async_trigger_callback(enum async_tx_flags flags,
+ 		if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask))
+ 			device = NULL;
+ 
+-		tx = device ? device->device_prep_dma_interrupt(chan) : NULL;
++		tx = device ? device->device_prep_dma_interrupt(chan, 0) : NULL;
+ 	} else
+ 		tx = NULL;
+ 
+@@ -483,7 +611,7 @@ async_trigger_callback(enum async_tx_flags flags,
+ 			/* if ack is already set then we cannot be sure
+ 			 * we are referring to the correct operation
+ 			 */
+-			BUG_ON(depend_tx->ack);
++			BUG_ON(async_tx_test_ack(depend_tx));
+ 			if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ 				panic("%s: DMA_ERROR waiting for depend_tx\n",
+ 					__func__);
+diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
+index 1c445c7..3a0dddc 100644
+--- a/crypto/async_tx/async_xor.c
++++ b/crypto/async_tx/async_xor.c
+@@ -191,7 +191,7 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+ 				/* if ack is already set then we cannot be sure
+ 				 * we are referring to the correct operation
+ 				 */
+-				BUG_ON(depend_tx->ack);
++				BUG_ON(async_tx_test_ack(depend_tx));
+ 				if (dma_wait_for_async_tx(depend_tx) ==
+ 					DMA_ERROR)
+ 					panic("%s: DMA_ERROR waiting for "
+diff --git a/crypto/blowfish.c b/crypto/blowfish.c
+index 80c3fd8..6f5b487 100644
+--- a/crypto/blowfish.c
++++ b/crypto/blowfish.c
+@@ -465,18 +465,18 @@ static struct crypto_alg alg = {
+ 	.cia_decrypt  		=	bf_decrypt } }
+ };
+ 
+-static int __init init(void)
++static int __init blowfish_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit blowfish_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(blowfish_mod_init);
++module_exit(blowfish_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
+diff --git a/crypto/cast5.c b/crypto/cast5.c
+index 13ea60a..8cbe28f 100644
+--- a/crypto/cast5.c
++++ b/crypto/cast5.c
+@@ -817,18 +817,18 @@ static struct crypto_alg alg = {
+ 	}
+ };
+ 
+-static int __init init(void)
++static int __init cast5_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit cast5_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(cast5_mod_init);
++module_exit(cast5_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Cast5 Cipher Algorithm");
+diff --git a/crypto/cast6.c b/crypto/cast6.c
+index 5fd9420..007d02b 100644
+--- a/crypto/cast6.c
++++ b/crypto/cast6.c
+@@ -528,18 +528,18 @@ static struct crypto_alg alg = {
+ 		  }
+ };
+ 
+-static int __init init(void)
++static int __init cast6_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit cast6_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(cast6_mod_init);
++module_exit(cast6_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Cast6 Cipher Algorithm");
+diff --git a/crypto/crc32c.c b/crypto/crc32c.c
+index 0fa7443..0dcf64a 100644
+--- a/crypto/crc32c.c
++++ b/crypto/crc32c.c
+@@ -98,18 +98,18 @@ static struct crypto_alg alg = {
+ 	}
+ };
+ 
+-static int __init init(void)
++static int __init crc32c_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit crc32c_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(crc32c_mod_init);
++module_exit(crc32c_mod_fini);
+ 
+ MODULE_AUTHOR("Clay Haapala <chaapala at cisco.com>");
+ MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
+diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
+index ff7b3de..1f7d530 100644
+--- a/crypto/crypto_null.c
++++ b/crypto/crypto_null.c
+@@ -142,7 +142,7 @@ MODULE_ALIAS("compress_null");
+ MODULE_ALIAS("digest_null");
+ MODULE_ALIAS("cipher_null");
+ 
+-static int __init init(void)
++static int __init crypto_null_mod_init(void)
+ {
+ 	int ret = 0;
+ 	
+@@ -174,7 +174,7 @@ out_unregister_cipher:
+ 	goto out;
+ }
+ 
+-static void __exit fini(void)
++static void __exit crypto_null_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&compress_null);
+ 	crypto_unregister_alg(&digest_null);
+@@ -182,8 +182,8 @@ static void __exit fini(void)
+ 	crypto_unregister_alg(&cipher_null);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(crypto_null_mod_init);
++module_exit(crypto_null_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Null Cryptographic Algorithms");
+diff --git a/crypto/cts.c b/crypto/cts.c
+new file mode 100644
+index 0000000..c4e70bf
+--- /dev/null
++++ b/crypto/cts.c
+@@ -0,0 +1,347 @@
++/*
++ * CTS: Cipher Text Stealing mode
++ *
++ * COPYRIGHT (c) 2008
++ * The Regents of the University of Michigan
++ * ALL RIGHTS RESERVED
++ *
++ * Permission is granted to use, copy, create derivative works
++ * and redistribute this software and such derivative works
++ * for any purpose, so long as the name of The University of
++ * Michigan is not used in any advertising or publicity
++ * pertaining to the use of distribution of this software
++ * without specific, written prior authorization.  If the
++ * above copyright notice or any other identification of the
++ * University of Michigan is included in any copy of any
++ * portion of this software, then the disclaimer below must
++ * also be included.
++ *
++ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
++ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
++ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
++ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
++ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
++ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
++ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
++ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
++ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
++ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGES.
++ */
++
++/* Derived from various:
++ *	Copyright (c) 2006 Herbert Xu <herbert at gondor.apana.org.au>
++ */
++
++/*
++ * This is the Cipher Text Stealing mode as described by
++ * Section 8 of rfc2040 and referenced by rfc3962.
++ * rfc3962 includes errata information in its Appendix A.
++ */
++
++#include <crypto/algapi.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/log2.h>
++#include <linux/module.h>
++#include <linux/scatterlist.h>
++#include <crypto/scatterwalk.h>
++#include <linux/slab.h>
++
++struct crypto_cts_ctx {
++	struct crypto_blkcipher *child;
++};
++
++static int crypto_cts_setkey(struct crypto_tfm *parent, const u8 *key,
++			     unsigned int keylen)
++{
++	struct crypto_cts_ctx *ctx = crypto_tfm_ctx(parent);
++	struct crypto_blkcipher *child = ctx->child;
++	int err;
++
++	crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
++	crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
++				       CRYPTO_TFM_REQ_MASK);
++	err = crypto_blkcipher_setkey(child, key, keylen);
++	crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
++				     CRYPTO_TFM_RES_MASK);
++	return err;
++}
++
++static int cts_cbc_encrypt(struct crypto_cts_ctx *ctx,
++			   struct blkcipher_desc *desc,
++			   struct scatterlist *dst,
++			   struct scatterlist *src,
++			   unsigned int offset,
++			   unsigned int nbytes)
++{
++	int bsize = crypto_blkcipher_blocksize(desc->tfm);
++	u8 tmp[bsize], tmp2[bsize];
++	struct blkcipher_desc lcldesc;
++	struct scatterlist sgsrc[1], sgdst[1];
++	int lastn = nbytes - bsize;
++	u8 iv[bsize];
++	u8 s[bsize * 2], d[bsize * 2];
++	int err;
++
++	if (lastn < 0)
++		return -EINVAL;
++
++	memset(s, 0, sizeof(s));
++	scatterwalk_map_and_copy(s, src, offset, nbytes, 0);
++
++	memcpy(iv, desc->info, bsize);
++
++	lcldesc.tfm = ctx->child;
++	lcldesc.info = iv;
++	lcldesc.flags = desc->flags;
++
++	sg_set_buf(&sgsrc[0], s, bsize);
++	sg_set_buf(&sgdst[0], tmp, bsize);
++	err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++
++	memcpy(d + bsize, tmp, lastn);
++
++	lcldesc.info = tmp;
++
++	sg_set_buf(&sgsrc[0], s + bsize, bsize);
++	sg_set_buf(&sgdst[0], tmp2, bsize);
++	err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++
++	memcpy(d, tmp2, bsize);
++
++	scatterwalk_map_and_copy(d, dst, offset, nbytes, 1);
++
++	memcpy(desc->info, tmp2, bsize);
++
++	return err;
++}
++
++static int crypto_cts_encrypt(struct blkcipher_desc *desc,
++			      struct scatterlist *dst, struct scatterlist *src,
++			      unsigned int nbytes)
++{
++	struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
++	int bsize = crypto_blkcipher_blocksize(desc->tfm);
++	int tot_blocks = (nbytes + bsize - 1) / bsize;
++	int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0;
++	struct blkcipher_desc lcldesc;
++	int err;
++
++	lcldesc.tfm = ctx->child;
++	lcldesc.info = desc->info;
++	lcldesc.flags = desc->flags;
++
++	if (tot_blocks == 1) {
++		err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src, bsize);
++	} else if (nbytes <= bsize * 2) {
++		err = cts_cbc_encrypt(ctx, desc, dst, src, 0, nbytes);
++	} else {
++		/* do normal function for tot_blocks - 2 */
++		err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src,
++							cbc_blocks * bsize);
++		if (err == 0) {
++			/* do cts for final two blocks */
++			err = cts_cbc_encrypt(ctx, desc, dst, src,
++						cbc_blocks * bsize,
++						nbytes - (cbc_blocks * bsize));
++		}
++	}
++
++	return err;
++}
++
++static int cts_cbc_decrypt(struct crypto_cts_ctx *ctx,
++			   struct blkcipher_desc *desc,
++			   struct scatterlist *dst,
++			   struct scatterlist *src,
++			   unsigned int offset,
++			   unsigned int nbytes)
++{
++	int bsize = crypto_blkcipher_blocksize(desc->tfm);
++	u8 tmp[bsize];
++	struct blkcipher_desc lcldesc;
++	struct scatterlist sgsrc[1], sgdst[1];
++	int lastn = nbytes - bsize;
++	u8 iv[bsize];
++	u8 s[bsize * 2], d[bsize * 2];
++	int err;
++
++	if (lastn < 0)
++		return -EINVAL;
++
++	scatterwalk_map_and_copy(s, src, offset, nbytes, 0);
++
++	lcldesc.tfm = ctx->child;
++	lcldesc.info = iv;
++	lcldesc.flags = desc->flags;
++
++	/* 1. Decrypt Cn-1 (s) to create Dn (tmp)*/
++	memset(iv, 0, sizeof(iv));
++	sg_set_buf(&sgsrc[0], s, bsize);
++	sg_set_buf(&sgdst[0], tmp, bsize);
++	err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++	if (err)
++		return err;
++	/* 2. Pad Cn with zeros at the end to create C of length BB */
++	memset(iv, 0, sizeof(iv));
++	memcpy(iv, s + bsize, lastn);
++	/* 3. Exclusive-or Dn (tmp) with C (iv) to create Xn (tmp) */
++	crypto_xor(tmp, iv, bsize);
++	/* 4. Select the first Ln bytes of Xn (tmp) to create Pn */
++	memcpy(d + bsize, tmp, lastn);
++
++	/* 5. Append the tail (BB - Ln) bytes of Xn (tmp) to Cn to create En */
++	memcpy(s + bsize + lastn, tmp + lastn, bsize - lastn);
++	/* 6. Decrypt En to create Pn-1 */
++	memset(iv, 0, sizeof(iv));
++	sg_set_buf(&sgsrc[0], s + bsize, bsize);
++	sg_set_buf(&sgdst[0], d, bsize);
++	err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++
++	/* XOR with previous block */
++	crypto_xor(d, desc->info, bsize);
++
++	scatterwalk_map_and_copy(d, dst, offset, nbytes, 1);
++
++	memcpy(desc->info, s, bsize);
++	return err;
++}
++
++static int crypto_cts_decrypt(struct blkcipher_desc *desc,
++			      struct scatterlist *dst, struct scatterlist *src,
++			      unsigned int nbytes)
++{
++	struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
++	int bsize = crypto_blkcipher_blocksize(desc->tfm);
++	int tot_blocks = (nbytes + bsize - 1) / bsize;
++	int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0;
++	struct blkcipher_desc lcldesc;
++	int err;
++
++	lcldesc.tfm = ctx->child;
++	lcldesc.info = desc->info;
++	lcldesc.flags = desc->flags;
++
++	if (tot_blocks == 1) {
++		err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src, bsize);
++	} else if (nbytes <= bsize * 2) {
++		err = cts_cbc_decrypt(ctx, desc, dst, src, 0, nbytes);
++	} else {
++		/* do normal function for tot_blocks - 2 */
++		err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src,
++							cbc_blocks * bsize);
++		if (err == 0) {
++			/* do cts for final two blocks */
++			err = cts_cbc_decrypt(ctx, desc, dst, src,
++						cbc_blocks * bsize,
++						nbytes - (cbc_blocks * bsize));
++		}
++	}
++	return err;
++}
++
++static int crypto_cts_init_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
++	struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_blkcipher *cipher;
++
++	cipher = crypto_spawn_blkcipher(spawn);
++	if (IS_ERR(cipher))
++		return PTR_ERR(cipher);
++
++	ctx->child = cipher;
++	return 0;
++}
++
++static void crypto_cts_exit_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm);
++	crypto_free_blkcipher(ctx->child);
++}
++
++static struct crypto_instance *crypto_cts_alloc(struct rtattr **tb)
++{
++	struct crypto_instance *inst;
++	struct crypto_alg *alg;
++	int err;
++
++	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
++	if (err)
++		return ERR_PTR(err);
++
++	alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
++				  CRYPTO_ALG_TYPE_MASK);
++	err = PTR_ERR(alg);
++	if (IS_ERR(alg))
++		return ERR_PTR(err);
++
++	inst = ERR_PTR(-EINVAL);
++	if (!is_power_of_2(alg->cra_blocksize))
++		goto out_put_alg;
++
++	inst = crypto_alloc_instance("cts", alg);
++	if (IS_ERR(inst))
++		goto out_put_alg;
++
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
++	inst->alg.cra_priority = alg->cra_priority;
++	inst->alg.cra_blocksize = alg->cra_blocksize;
++	inst->alg.cra_alignmask = alg->cra_alignmask;
++	inst->alg.cra_type = &crypto_blkcipher_type;
++
++	/* We access the data as u32s when xoring. */
++	inst->alg.cra_alignmask |= __alignof__(u32) - 1;
++
++	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
++	inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
++	inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
++
++	inst->alg.cra_blkcipher.geniv = "seqiv";
++
++	inst->alg.cra_ctxsize = sizeof(struct crypto_cts_ctx);
++
++	inst->alg.cra_init = crypto_cts_init_tfm;
++	inst->alg.cra_exit = crypto_cts_exit_tfm;
++
++	inst->alg.cra_blkcipher.setkey = crypto_cts_setkey;
++	inst->alg.cra_blkcipher.encrypt = crypto_cts_encrypt;
++	inst->alg.cra_blkcipher.decrypt = crypto_cts_decrypt;
++
++out_put_alg:
++	crypto_mod_put(alg);
++	return inst;
++}
++
++static void crypto_cts_free(struct crypto_instance *inst)
++{
++	crypto_drop_spawn(crypto_instance_ctx(inst));
++	kfree(inst);
++}
++
++static struct crypto_template crypto_cts_tmpl = {
++	.name = "cts",
++	.alloc = crypto_cts_alloc,
++	.free = crypto_cts_free,
++	.module = THIS_MODULE,
++};
++
++static int __init crypto_cts_module_init(void)
++{
++	return crypto_register_template(&crypto_cts_tmpl);
++}
++
++static void __exit crypto_cts_module_exit(void)
++{
++	crypto_unregister_template(&crypto_cts_tmpl);
++}
++
++module_init(crypto_cts_module_init);
++module_exit(crypto_cts_module_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_DESCRIPTION("CTS-CBC CipherText Stealing for CBC");
+diff --git a/crypto/deflate.c b/crypto/deflate.c
+index 6588bbf..9128da4 100644
+--- a/crypto/deflate.c
++++ b/crypto/deflate.c
+@@ -208,18 +208,18 @@ static struct crypto_alg alg = {
+ 	.coa_decompress  	= deflate_decompress } }
+ };
+ 
+-static int __init init(void)
++static int __init deflate_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit deflate_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(deflate_mod_init);
++module_exit(deflate_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
+diff --git a/crypto/des_generic.c b/crypto/des_generic.c
+index 355ecb7..5d0e458 100644
+--- a/crypto/des_generic.c
++++ b/crypto/des_generic.c
+@@ -977,7 +977,7 @@ static struct crypto_alg des3_ede_alg = {
+ 
+ MODULE_ALIAS("des3_ede");
+ 
+-static int __init init(void)
++static int __init des_generic_mod_init(void)
+ {
+ 	int ret = 0;
+ 
+@@ -992,14 +992,14 @@ out:
+ 	return ret;
+ }
+ 
+-static void __exit fini(void)
++static void __exit des_generic_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&des3_ede_alg);
+ 	crypto_unregister_alg(&des_alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(des_generic_mod_init);
++module_exit(des_generic_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
+diff --git a/crypto/fcrypt.c b/crypto/fcrypt.c
+index a32cb68..1302f4c 100644
+--- a/crypto/fcrypt.c
++++ b/crypto/fcrypt.c
+@@ -405,18 +405,18 @@ static struct crypto_alg fcrypt_alg = {
+ 	.cia_decrypt		=	fcrypt_decrypt } }
+ };
+ 
+-static int __init init(void)
++static int __init fcrypt_mod_init(void)
+ {
+ 	return crypto_register_alg(&fcrypt_alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit fcrypt_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&fcrypt_alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(fcrypt_mod_init);
++module_exit(fcrypt_mod_fini);
+ 
+ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_DESCRIPTION("FCrypt Cipher Algorithm");
+diff --git a/crypto/khazad.c b/crypto/khazad.c
+index 704ebfe..527e4e3 100644
+--- a/crypto/khazad.c
++++ b/crypto/khazad.c
+@@ -862,7 +862,7 @@ static struct crypto_alg khazad_alg = {
+ 	.cia_decrypt		=	khazad_decrypt } }
+ };
+ 
+-static int __init init(void)
++static int __init khazad_mod_init(void)
+ {
+ 	int ret = 0;
+ 	
+@@ -870,14 +870,14 @@ static int __init init(void)
+ 	return ret;
+ }
+ 
+-static void __exit fini(void)
++static void __exit khazad_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&khazad_alg);
+ }
+ 
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(khazad_mod_init);
++module_exit(khazad_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Khazad Cryptographic Algorithm");
+diff --git a/crypto/lrw.c b/crypto/lrw.c
+index 9d52e58..8ef664e 100644
+--- a/crypto/lrw.c
++++ b/crypto/lrw.c
+@@ -91,8 +91,9 @@ struct sinfo {
+ 
+ static inline void inc(be128 *iv)
+ {
+-	if (!(iv->b = cpu_to_be64(be64_to_cpu(iv->b) + 1)))
+-		iv->a = cpu_to_be64(be64_to_cpu(iv->a) + 1);
++	be64_add_cpu(&iv->b, 1);
++	if (!iv->b)
++		be64_add_cpu(&iv->a, 1);
+ }
+ 
+ static inline void lrw_round(struct sinfo *s, void *dst, const void *src)
+diff --git a/crypto/lzo.c b/crypto/lzo.c
+index 48c3288..b5e7707 100644
+--- a/crypto/lzo.c
++++ b/crypto/lzo.c
+@@ -89,18 +89,18 @@ static struct crypto_alg alg = {
+ 	.coa_decompress  	= lzo_decompress } }
+ };
+ 
+-static int __init init(void)
++static int __init lzo_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit lzo_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(lzo_mod_init);
++module_exit(lzo_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("LZO Compression Algorithm");
+diff --git a/crypto/md4.c b/crypto/md4.c
+index c1bc71b..3c19aa0 100644
+--- a/crypto/md4.c
++++ b/crypto/md4.c
+@@ -233,18 +233,18 @@ static struct crypto_alg alg = {
+ 	.dia_final  	=	md4_final } }
+ };
+ 
+-static int __init init(void)
++static int __init md4_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit md4_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(md4_mod_init);
++module_exit(md4_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("MD4 Message Digest Algorithm");
+diff --git a/crypto/md5.c b/crypto/md5.c
+index 93d18e8..39268f3 100644
+--- a/crypto/md5.c
++++ b/crypto/md5.c
+@@ -228,18 +228,18 @@ static struct crypto_alg alg = {
+ 	.dia_final  	=	md5_final } }
+ };
+ 
+-static int __init init(void)
++static int __init md5_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit md5_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(md5_mod_init);
++module_exit(md5_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("MD5 Message Digest Algorithm");
+diff --git a/crypto/proc.c b/crypto/proc.c
+index 3d73323..02ff567 100644
+--- a/crypto/proc.c
++++ b/crypto/proc.c
+@@ -78,7 +78,7 @@ static int c_show(struct seq_file *m, void *p)
+ 	return 0;
+ }
+ 
+-static struct seq_operations crypto_seq_ops = {
++static const struct seq_operations crypto_seq_ops = {
+ 	.start		= c_start,
+ 	.next		= c_next,
+ 	.stop		= c_stop,
+@@ -99,11 +99,7 @@ static const struct file_operations proc_crypto_ops = {
+ 
+ void __init crypto_init_proc(void)
+ {
+-	struct proc_dir_entry *proc;
+-	
+-	proc = create_proc_entry("crypto", 0, NULL);
+-	if (proc)
+-		proc->proc_fops = &proc_crypto_ops;
++	proc_create("crypto", 0, NULL, &proc_crypto_ops);
+ }
+ 
+ void __exit crypto_exit_proc(void)
+diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c
+index 1fa4e4d..b07d559 100644
+--- a/crypto/salsa20_generic.c
++++ b/crypto/salsa20_generic.c
+@@ -237,18 +237,18 @@ static struct crypto_alg alg = {
+ 	}
+ };
+ 
+-static int __init init(void)
++static int __init salsa20_generic_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit salsa20_generic_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(salsa20_generic_mod_init);
++module_exit(salsa20_generic_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm");
+diff --git a/crypto/serpent.c b/crypto/serpent.c
+index 2b0a19a..b651a55 100644
+--- a/crypto/serpent.c
++++ b/crypto/serpent.c
+@@ -557,7 +557,7 @@ static struct crypto_alg tnepres_alg = {
+ 	.cia_decrypt  		=	tnepres_decrypt } }
+ };
+ 
+-static int __init init(void)
++static int __init serpent_mod_init(void)
+ {
+ 	int ret = crypto_register_alg(&serpent_alg);
+ 
+@@ -572,14 +572,14 @@ static int __init init(void)
+ 	return ret;
+ }
+ 
+-static void __exit fini(void)
++static void __exit serpent_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&tnepres_alg);
+ 	crypto_unregister_alg(&serpent_alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(serpent_mod_init);
++module_exit(serpent_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Serpent and tnepres (kerneli compatible serpent reversed) Cipher Algorithm");
+diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
+index 68c62f5..c7c6899 100644
+--- a/crypto/sha1_generic.c
++++ b/crypto/sha1_generic.c
+@@ -120,18 +120,18 @@ static struct crypto_alg alg = {
+ 	.dia_final  	=	sha1_final } }
+ };
+ 
+-static int __init init(void)
++static int __init sha1_generic_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit sha1_generic_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(sha1_generic_mod_init);
++module_exit(sha1_generic_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
+diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
+index 3cc93fd..5a8dd47 100644
+--- a/crypto/sha256_generic.c
++++ b/crypto/sha256_generic.c
+@@ -353,7 +353,7 @@ static struct crypto_alg sha224 = {
+ 	.dia_final	= sha224_final } }
+ };
+ 
+-static int __init init(void)
++static int __init sha256_generic_mod_init(void)
+ {
+ 	int ret = 0;
+ 
+@@ -370,14 +370,14 @@ static int __init init(void)
+ 	return ret;
+ }
+ 
+-static void __exit fini(void)
++static void __exit sha256_generic_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&sha224);
+ 	crypto_unregister_alg(&sha256);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(sha256_generic_mod_init);
++module_exit(sha256_generic_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm");
+diff --git a/crypto/sha512.c b/crypto/sha512.c
+deleted file mode 100644
+index c39c803..0000000
+--- a/crypto/sha512.c
++++ /dev/null
+@@ -1,305 +0,0 @@
+-/* SHA-512 code by Jean-Luc Cooke <jlcooke at certainkey.com>
+- *
+- * Copyright (c) Jean-Luc Cooke <jlcooke at certainkey.com>
+- * Copyright (c) Andrew McDonald <andrew at mcdonald.org.uk>
+- * Copyright (c) 2003 Kyle McMartin <kyle at debian.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, or (at your option) any
+- * later version.
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/crypto.h>
+-#include <linux/types.h>
+-#include <crypto/sha.h>
+-
+-#include <asm/byteorder.h>
+-
+-struct sha512_ctx {
+-	u64 state[8];
+-	u32 count[4];
+-	u8 buf[128];
+-	u64 W[80];
+-};
+-
+-static inline u64 Ch(u64 x, u64 y, u64 z)
+-{
+-        return z ^ (x & (y ^ z));
+-}
+-
+-static inline u64 Maj(u64 x, u64 y, u64 z)
+-{
+-        return (x & y) | (z & (x | y));
+-}
+-
+-static inline u64 RORu64(u64 x, u64 y)
+-{
+-        return (x >> y) | (x << (64 - y));
+-}
+-
+-static const u64 sha512_K[80] = {
+-        0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+-        0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+-        0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+-        0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+-        0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+-        0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+-        0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+-        0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+-        0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+-        0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+-        0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+-        0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+-        0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+-        0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+-        0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+-        0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+-        0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+-        0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+-        0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+-        0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+-        0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+-        0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+-        0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+-        0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+-        0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+-        0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+-        0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
+-};
+-
+-#define e0(x)       (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
+-#define e1(x)       (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
+-#define s0(x)       (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
+-#define s1(x)       (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
+-
+-static inline void LOAD_OP(int I, u64 *W, const u8 *input)
+-{
+-	W[I] = __be64_to_cpu( ((__be64*)(input))[I] );
+-}
+-
+-static inline void BLEND_OP(int I, u64 *W)
+-{
+-	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+-}
+-
+-static void
+-sha512_transform(u64 *state, u64 *W, const u8 *input)
+-{
+-	u64 a, b, c, d, e, f, g, h, t1, t2;
+-
+-	int i;
+-
+-	/* load the input */
+-        for (i = 0; i < 16; i++)
+-                LOAD_OP(i, W, input);
+-
+-        for (i = 16; i < 80; i++) {
+-                BLEND_OP(i, W);
+-        }
+-
+-	/* load the state into our registers */
+-	a=state[0];   b=state[1];   c=state[2];   d=state[3];  
+-	e=state[4];   f=state[5];   g=state[6];   h=state[7];  
+-  
+-	/* now iterate */
+-	for (i=0; i<80; i+=8) {
+-		t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[i  ];
+-		t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+-		t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
+-		t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+-		t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
+-		t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+-		t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
+-		t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+-		t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
+-		t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+-		t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
+-		t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+-		t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
+-		t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+-		t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
+-		t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+-	}
+-  
+-	state[0] += a; state[1] += b; state[2] += c; state[3] += d;  
+-	state[4] += e; state[5] += f; state[6] += g; state[7] += h;  
+-
+-	/* erase our data */
+-	a = b = c = d = e = f = g = h = t1 = t2 = 0;
+-}
+-
+-static void
+-sha512_init(struct crypto_tfm *tfm)
+-{
+-	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+-	sctx->state[0] = SHA512_H0;
+-	sctx->state[1] = SHA512_H1;
+-	sctx->state[2] = SHA512_H2;
+-	sctx->state[3] = SHA512_H3;
+-	sctx->state[4] = SHA512_H4;
+-	sctx->state[5] = SHA512_H5;
+-	sctx->state[6] = SHA512_H6;
+-	sctx->state[7] = SHA512_H7;
+-	sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
+-}
+-
+-static void
+-sha384_init(struct crypto_tfm *tfm)
+-{
+-	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+-	sctx->state[0] = SHA384_H0;
+-	sctx->state[1] = SHA384_H1;
+-	sctx->state[2] = SHA384_H2;
+-	sctx->state[3] = SHA384_H3;
+-	sctx->state[4] = SHA384_H4;
+-	sctx->state[5] = SHA384_H5;
+-	sctx->state[6] = SHA384_H6;
+-	sctx->state[7] = SHA384_H7;
+-        sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
+-}
+-
+-static void
+-sha512_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
+-{
+-	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+-
+-	unsigned int i, index, part_len;
+-
+-	/* Compute number of bytes mod 128 */
+-	index = (unsigned int)((sctx->count[0] >> 3) & 0x7F);
+-	
+-	/* Update number of bits */
+-	if ((sctx->count[0] += (len << 3)) < (len << 3)) {
+-		if ((sctx->count[1] += 1) < 1)
+-			if ((sctx->count[2] += 1) < 1)
+-				sctx->count[3]++;
+-		sctx->count[1] += (len >> 29);
+-	}
+-	
+-        part_len = 128 - index;
+-	
+-	/* Transform as many times as possible. */
+-	if (len >= part_len) {
+-		memcpy(&sctx->buf[index], data, part_len);
+-		sha512_transform(sctx->state, sctx->W, sctx->buf);
+-
+-		for (i = part_len; i + 127 < len; i+=128)
+-			sha512_transform(sctx->state, sctx->W, &data[i]);
+-
+-		index = 0;
+-	} else {
+-		i = 0;
+-	}
+-
+-	/* Buffer remaining input */
+-	memcpy(&sctx->buf[index], &data[i], len - i);
+-
+-	/* erase our data */
+-	memset(sctx->W, 0, sizeof(sctx->W));
+-}
+-
+-static void
+-sha512_final(struct crypto_tfm *tfm, u8 *hash)
+-{
+-	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+-        static u8 padding[128] = { 0x80, };
+-	__be64 *dst = (__be64 *)hash;
+-	__be32 bits[4];
+-	unsigned int index, pad_len;
+-	int i;
+-
+-	/* Save number of bits */
+-	bits[3] = cpu_to_be32(sctx->count[0]);
+-	bits[2] = cpu_to_be32(sctx->count[1]);
+-	bits[1] = cpu_to_be32(sctx->count[2]);
+-	bits[0] = cpu_to_be32(sctx->count[3]);
+-
+-	/* Pad out to 112 mod 128. */
+-	index = (sctx->count[0] >> 3) & 0x7f;
+-	pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
+-	sha512_update(tfm, padding, pad_len);
+-
+-	/* Append length (before padding) */
+-	sha512_update(tfm, (const u8 *)bits, sizeof(bits));
+-
+-	/* Store state in digest */
+-	for (i = 0; i < 8; i++)
+-		dst[i] = cpu_to_be64(sctx->state[i]);
+-
+-	/* Zeroize sensitive information. */
+-	memset(sctx, 0, sizeof(struct sha512_ctx));
+-}
+-
+-static void sha384_final(struct crypto_tfm *tfm, u8 *hash)
+-{
+-        u8 D[64];
+-
+-	sha512_final(tfm, D);
+-
+-        memcpy(hash, D, 48);
+-        memset(D, 0, 64);
+-}
+-
+-static struct crypto_alg sha512 = {
+-        .cra_name       = "sha512",
+-        .cra_flags      = CRYPTO_ALG_TYPE_DIGEST,
+-	.cra_blocksize  = SHA512_BLOCK_SIZE,
+-        .cra_ctxsize    = sizeof(struct sha512_ctx),
+-        .cra_module     = THIS_MODULE,
+-	.cra_alignmask	= 3,
+-        .cra_list       = LIST_HEAD_INIT(sha512.cra_list),
+-        .cra_u          = { .digest = {
+-                                .dia_digestsize = SHA512_DIGEST_SIZE,
+-                                .dia_init       = sha512_init,
+-                                .dia_update     = sha512_update,
+-                                .dia_final      = sha512_final }
+-        }
+-};
+-
+-static struct crypto_alg sha384 = {
+-        .cra_name       = "sha384",
+-        .cra_flags      = CRYPTO_ALG_TYPE_DIGEST,
+-	.cra_blocksize  = SHA384_BLOCK_SIZE,
+-        .cra_ctxsize    = sizeof(struct sha512_ctx),
+-	.cra_alignmask	= 3,
+-        .cra_module     = THIS_MODULE,
+-        .cra_list       = LIST_HEAD_INIT(sha384.cra_list),
+-        .cra_u          = { .digest = {
+-                                .dia_digestsize = SHA384_DIGEST_SIZE,
+-                                .dia_init       = sha384_init,
+-                                .dia_update     = sha512_update,
+-                                .dia_final      = sha384_final }
+-        }
+-};
+-
+-MODULE_ALIAS("sha384");
+-
+-static int __init init(void)
+-{
+-        int ret = 0;
+-
+-        if ((ret = crypto_register_alg(&sha384)) < 0)
+-                goto out;
+-        if ((ret = crypto_register_alg(&sha512)) < 0)
+-                crypto_unregister_alg(&sha384);
+-out:
+-        return ret;
+-}
+-
+-static void __exit fini(void)
+-{
+-        crypto_unregister_alg(&sha384);
+-        crypto_unregister_alg(&sha512);
+-}
+-
+-module_init(init);
+-module_exit(fini);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms");
+diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
+new file mode 100644
+index 0000000..bc36861
+--- /dev/null
++++ b/crypto/sha512_generic.c
+@@ -0,0 +1,306 @@
++/* SHA-512 code by Jean-Luc Cooke <jlcooke at certainkey.com>
++ *
++ * Copyright (c) Jean-Luc Cooke <jlcooke at certainkey.com>
++ * Copyright (c) Andrew McDonald <andrew at mcdonald.org.uk>
++ * Copyright (c) 2003 Kyle McMartin <kyle at debian.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, or (at your option) any
++ * later version.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/crypto.h>
++#include <linux/types.h>
++#include <crypto/sha.h>
++
++#include <asm/byteorder.h>
++
++struct sha512_ctx {
++	u64 state[8];
++	u32 count[4];
++	u8 buf[128];
++	u64 W[80];
++};
++
++static inline u64 Ch(u64 x, u64 y, u64 z)
++{
++        return z ^ (x & (y ^ z));
++}
++
++static inline u64 Maj(u64 x, u64 y, u64 z)
++{
++        return (x & y) | (z & (x | y));
++}
++
++static inline u64 RORu64(u64 x, u64 y)
++{
++        return (x >> y) | (x << (64 - y));
++}
++
++static const u64 sha512_K[80] = {
++        0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
++        0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
++        0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
++        0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
++        0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
++        0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
++        0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
++        0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
++        0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
++        0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
++        0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
++        0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
++        0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
++        0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
++        0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
++        0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
++        0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
++        0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
++        0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
++        0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
++        0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
++        0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
++        0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
++        0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
++        0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
++        0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
++        0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
++};
++
++#define e0(x)       (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
++#define e1(x)       (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
++#define s0(x)       (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
++#define s1(x)       (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
++
++static inline void LOAD_OP(int I, u64 *W, const u8 *input)
++{
++	W[I] = __be64_to_cpu( ((__be64*)(input))[I] );
++}
++
++static inline void BLEND_OP(int I, u64 *W)
++{
++	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
++}
++
++static void
++sha512_transform(u64 *state, u64 *W, const u8 *input)
++{
++	u64 a, b, c, d, e, f, g, h, t1, t2;
++
++	int i;
++
++	/* load the input */
++        for (i = 0; i < 16; i++)
++                LOAD_OP(i, W, input);
++
++        for (i = 16; i < 80; i++) {
++                BLEND_OP(i, W);
++        }
++
++	/* load the state into our registers */
++	a=state[0];   b=state[1];   c=state[2];   d=state[3];
++	e=state[4];   f=state[5];   g=state[6];   h=state[7];
++
++	/* now iterate */
++	for (i=0; i<80; i+=8) {
++		t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[i  ];
++		t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
++		t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
++		t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
++		t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
++		t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
++		t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
++		t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
++		t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
++		t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
++		t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
++		t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
++		t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
++		t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
++		t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
++		t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
++	}
++
++	state[0] += a; state[1] += b; state[2] += c; state[3] += d;
++	state[4] += e; state[5] += f; state[6] += g; state[7] += h;
++
++	/* erase our data */
++	a = b = c = d = e = f = g = h = t1 = t2 = 0;
++}
++
++static void
++sha512_init(struct crypto_tfm *tfm)
++{
++	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
++	sctx->state[0] = SHA512_H0;
++	sctx->state[1] = SHA512_H1;
++	sctx->state[2] = SHA512_H2;
++	sctx->state[3] = SHA512_H3;
++	sctx->state[4] = SHA512_H4;
++	sctx->state[5] = SHA512_H5;
++	sctx->state[6] = SHA512_H6;
++	sctx->state[7] = SHA512_H7;
++	sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
++}
++
++static void
++sha384_init(struct crypto_tfm *tfm)
++{
++	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
++	sctx->state[0] = SHA384_H0;
++	sctx->state[1] = SHA384_H1;
++	sctx->state[2] = SHA384_H2;
++	sctx->state[3] = SHA384_H3;
++	sctx->state[4] = SHA384_H4;
++	sctx->state[5] = SHA384_H5;
++	sctx->state[6] = SHA384_H6;
++	sctx->state[7] = SHA384_H7;
++        sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
++}
++
++static void
++sha512_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
++{
++	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
++
++	unsigned int i, index, part_len;
++
++	/* Compute number of bytes mod 128 */
++	index = (unsigned int)((sctx->count[0] >> 3) & 0x7F);
++
++	/* Update number of bits */
++	if ((sctx->count[0] += (len << 3)) < (len << 3)) {
++		if ((sctx->count[1] += 1) < 1)
++			if ((sctx->count[2] += 1) < 1)
++				sctx->count[3]++;
++		sctx->count[1] += (len >> 29);
++	}
++
++        part_len = 128 - index;
++
++	/* Transform as many times as possible. */
++	if (len >= part_len) {
++		memcpy(&sctx->buf[index], data, part_len);
++		sha512_transform(sctx->state, sctx->W, sctx->buf);
++
++		for (i = part_len; i + 127 < len; i+=128)
++			sha512_transform(sctx->state, sctx->W, &data[i]);
++
++		index = 0;
++	} else {
++		i = 0;
++	}
++
++	/* Buffer remaining input */
++	memcpy(&sctx->buf[index], &data[i], len - i);
++
++	/* erase our data */
++	memset(sctx->W, 0, sizeof(sctx->W));
++}
++
++static void
++sha512_final(struct crypto_tfm *tfm, u8 *hash)
++{
++	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
++        static u8 padding[128] = { 0x80, };
++	__be64 *dst = (__be64 *)hash;
++	__be32 bits[4];
++	unsigned int index, pad_len;
++	int i;
++
++	/* Save number of bits */
++	bits[3] = cpu_to_be32(sctx->count[0]);
++	bits[2] = cpu_to_be32(sctx->count[1]);
++	bits[1] = cpu_to_be32(sctx->count[2]);
++	bits[0] = cpu_to_be32(sctx->count[3]);
++
++	/* Pad out to 112 mod 128. */
++	index = (sctx->count[0] >> 3) & 0x7f;
++	pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
++	sha512_update(tfm, padding, pad_len);
++
++	/* Append length (before padding) */
++	sha512_update(tfm, (const u8 *)bits, sizeof(bits));
++
++	/* Store state in digest */
++	for (i = 0; i < 8; i++)
++		dst[i] = cpu_to_be64(sctx->state[i]);
++
++	/* Zeroize sensitive information. */
++	memset(sctx, 0, sizeof(struct sha512_ctx));
++}
++
++static void sha384_final(struct crypto_tfm *tfm, u8 *hash)
++{
++        u8 D[64];
++
++	sha512_final(tfm, D);
++
++        memcpy(hash, D, 48);
++        memset(D, 0, 64);
++}
++
++static struct crypto_alg sha512 = {
++        .cra_name       = "sha512",
++        .cra_flags      = CRYPTO_ALG_TYPE_DIGEST,
++	.cra_blocksize  = SHA512_BLOCK_SIZE,
++        .cra_ctxsize    = sizeof(struct sha512_ctx),
++        .cra_module     = THIS_MODULE,
++	.cra_alignmask	= 3,
++        .cra_list       = LIST_HEAD_INIT(sha512.cra_list),
++        .cra_u          = { .digest = {
++                                .dia_digestsize = SHA512_DIGEST_SIZE,
++                                .dia_init       = sha512_init,
++                                .dia_update     = sha512_update,
++                                .dia_final      = sha512_final }
++        }
++};
++
++static struct crypto_alg sha384 = {
++        .cra_name       = "sha384",
++        .cra_flags      = CRYPTO_ALG_TYPE_DIGEST,
++	.cra_blocksize  = SHA384_BLOCK_SIZE,
++        .cra_ctxsize    = sizeof(struct sha512_ctx),
++	.cra_alignmask	= 3,
++        .cra_module     = THIS_MODULE,
++        .cra_list       = LIST_HEAD_INIT(sha384.cra_list),
++        .cra_u          = { .digest = {
++                                .dia_digestsize = SHA384_DIGEST_SIZE,
++                                .dia_init       = sha384_init,
++                                .dia_update     = sha512_update,
++                                .dia_final      = sha384_final }
++        }
++};
++
++static int __init sha512_generic_mod_init(void)
++{
++        int ret = 0;
++
++        if ((ret = crypto_register_alg(&sha384)) < 0)
++                goto out;
++        if ((ret = crypto_register_alg(&sha512)) < 0)
++                crypto_unregister_alg(&sha384);
++out:
++        return ret;
++}
++
++static void __exit sha512_generic_mod_fini(void)
++{
++        crypto_unregister_alg(&sha384);
++        crypto_unregister_alg(&sha512);
++}
++
++module_init(sha512_generic_mod_init);
++module_exit(sha512_generic_mod_fini);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms");
++
++MODULE_ALIAS("sha384");
++MODULE_ALIAS("sha512");
+diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
+index 1ab8c01..6beabc5 100644
+--- a/crypto/tcrypt.c
++++ b/crypto/tcrypt.c
+@@ -82,9 +82,8 @@ static char *check[] = {
+ 	"des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256",
+ 	"blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes",
+ 	"cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
+-	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
+ 	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
+-	"camellia", "seed", "salsa20", "lzo", NULL
++	"camellia", "seed", "salsa20", "lzo", "cts", NULL
+ };
+ 
+ static void hexdump(unsigned char *buf, unsigned int len)
+@@ -113,23 +112,11 @@ static void test_hash(char *algo, struct hash_testvec *template,
+ 	char result[64];
+ 	struct crypto_hash *tfm;
+ 	struct hash_desc desc;
+-	struct hash_testvec *hash_tv;
+-	unsigned int tsize;
+ 	int ret;
++	void *hash_buff;
+ 
+ 	printk("\ntesting %s\n", algo);
+ 
+-	tsize = sizeof(struct hash_testvec);
+-	tsize *= tcount;
+-
+-	if (tsize > TVMEMSIZE) {
+-		printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE);
+-		return;
+-	}
+-
+-	memcpy(tvmem, template, tsize);
+-	hash_tv = (void *)tvmem;
+-
+ 	tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC);
+ 	if (IS_ERR(tfm)) {
+ 		printk("failed to load transform for %s: %ld\n", algo,
+@@ -144,28 +131,36 @@ static void test_hash(char *algo, struct hash_testvec *template,
+ 		printk("test %u:\n", i + 1);
+ 		memset(result, 0, 64);
+ 
+-		sg_init_one(&sg[0], hash_tv[i].plaintext, hash_tv[i].psize);
++		hash_buff = kzalloc(template[i].psize, GFP_KERNEL);
++		if (!hash_buff)
++			continue;
++
++		memcpy(hash_buff, template[i].plaintext, template[i].psize);
++		sg_init_one(&sg[0], hash_buff, template[i].psize);
+ 
+-		if (hash_tv[i].ksize) {
+-			ret = crypto_hash_setkey(tfm, hash_tv[i].key,
+-						 hash_tv[i].ksize);
++		if (template[i].ksize) {
++			ret = crypto_hash_setkey(tfm, template[i].key,
++						 template[i].ksize);
+ 			if (ret) {
+ 				printk("setkey() failed ret=%d\n", ret);
++				kfree(hash_buff);
+ 				goto out;
+ 			}
+ 		}
+ 
+-		ret = crypto_hash_digest(&desc, sg, hash_tv[i].psize, result);
++		ret = crypto_hash_digest(&desc, sg, template[i].psize, result);
+ 		if (ret) {
+ 			printk("digest () failed ret=%d\n", ret);
++			kfree(hash_buff);
+ 			goto out;
+ 		}
+ 
+ 		hexdump(result, crypto_hash_digestsize(tfm));
+ 		printk("%s\n",
+-		       memcmp(result, hash_tv[i].digest,
++		       memcmp(result, template[i].digest,
+ 			      crypto_hash_digestsize(tfm)) ?
+ 		       "fail" : "pass");
++		kfree(hash_buff);
+ 	}
+ 
+ 	printk("testing %s across pages\n", algo);
+@@ -175,25 +170,25 @@ static void test_hash(char *algo, struct hash_testvec *template,
+ 
+ 	j = 0;
+ 	for (i = 0; i < tcount; i++) {
+-		if (hash_tv[i].np) {
++		if (template[i].np) {
+ 			j++;
+ 			printk("test %u:\n", j);
+ 			memset(result, 0, 64);
+ 
+ 			temp = 0;
+-			sg_init_table(sg, hash_tv[i].np);
+-			for (k = 0; k < hash_tv[i].np; k++) {
++			sg_init_table(sg, template[i].np);
++			for (k = 0; k < template[i].np; k++) {
+ 				memcpy(&xbuf[IDX[k]],
+-				       hash_tv[i].plaintext + temp,
+-				       hash_tv[i].tap[k]);
+-				temp += hash_tv[i].tap[k];
++				       template[i].plaintext + temp,
++				       template[i].tap[k]);
++				temp += template[i].tap[k];
+ 				sg_set_buf(&sg[k], &xbuf[IDX[k]],
+-					    hash_tv[i].tap[k]);
++					    template[i].tap[k]);
+ 			}
+ 
+-			if (hash_tv[i].ksize) {
+-				ret = crypto_hash_setkey(tfm, hash_tv[i].key,
+-							 hash_tv[i].ksize);
++			if (template[i].ksize) {
++				ret = crypto_hash_setkey(tfm, template[i].key,
++							 template[i].ksize);
+ 
+ 				if (ret) {
+ 					printk("setkey() failed ret=%d\n", ret);
+@@ -201,7 +196,7 @@ static void test_hash(char *algo, struct hash_testvec *template,
+ 				}
+ 			}
+ 
+-			ret = crypto_hash_digest(&desc, sg, hash_tv[i].psize,
++			ret = crypto_hash_digest(&desc, sg, template[i].psize,
+ 						 result);
+ 			if (ret) {
+ 				printk("digest () failed ret=%d\n", ret);
+@@ -210,7 +205,7 @@ static void test_hash(char *algo, struct hash_testvec *template,
+ 
+ 			hexdump(result, crypto_hash_digestsize(tfm));
+ 			printk("%s\n",
+-			       memcmp(result, hash_tv[i].digest,
++			       memcmp(result, template[i].digest,
+ 				      crypto_hash_digestsize(tfm)) ?
+ 			       "fail" : "pass");
+ 		}
+@@ -224,17 +219,18 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ 		      unsigned int tcount)
+ {
+ 	unsigned int ret, i, j, k, temp;
+-	unsigned int tsize;
+ 	char *q;
+ 	struct crypto_aead *tfm;
+ 	char *key;
+-	struct aead_testvec *aead_tv;
+ 	struct aead_request *req;
+ 	struct scatterlist sg[8];
+ 	struct scatterlist asg[8];
+ 	const char *e;
+ 	struct tcrypt_result result;
+ 	unsigned int authsize;
++	void *input;
++	void *assoc;
++	char iv[MAX_IVLEN];
+ 
+ 	if (enc == ENCRYPT)
+ 		e = "encryption";
+@@ -243,18 +239,6 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ 
+ 	printk(KERN_INFO "\ntesting %s %s\n", algo, e);
+ 
+-	tsize = sizeof(struct aead_testvec);
+-	tsize *= tcount;
+-
+-	if (tsize > TVMEMSIZE) {
+-		printk(KERN_INFO "template (%u) too big for tvmem (%u)\n",
+-		       tsize, TVMEMSIZE);
+-		return;
+-	}
+-
+-	memcpy(tvmem, template, tsize);
+-	aead_tv = (void *)tvmem;
+-
+ 	init_completion(&result.completion);
+ 
+ 	tfm = crypto_alloc_aead(algo, 0, 0);
+@@ -275,46 +259,68 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ 				  tcrypt_complete, &result);
+ 
+ 	for (i = 0, j = 0; i < tcount; i++) {
+-		if (!aead_tv[i].np) {
++		if (!template[i].np) {
+ 			printk(KERN_INFO "test %u (%d bit key):\n",
+-			       ++j, aead_tv[i].klen * 8);
++			       ++j, template[i].klen * 8);
++
++			/* some tepmplates have no input data but they will
++			 * touch input
++			 */
++			input = kzalloc(template[i].ilen + template[i].rlen, GFP_KERNEL);
++			if (!input)
++				continue;
++
++			assoc = kzalloc(template[i].alen, GFP_KERNEL);
++			if (!assoc) {
++				kfree(input);
++				continue;
++			}
++
++			memcpy(input, template[i].input, template[i].ilen);
++			memcpy(assoc, template[i].assoc, template[i].alen);
++			if (template[i].iv)
++				memcpy(iv, template[i].iv, MAX_IVLEN);
++			else
++				memset(iv, 0, MAX_IVLEN);
+ 
+ 			crypto_aead_clear_flags(tfm, ~0);
+-			if (aead_tv[i].wk)
++			if (template[i].wk)
+ 				crypto_aead_set_flags(
+ 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+-			key = aead_tv[i].key;
++
++			if (template[i].key)
++				key = template[i].key;
++			else
++				key = kzalloc(template[i].klen, GFP_KERNEL);
+ 
+ 			ret = crypto_aead_setkey(tfm, key,
+-						 aead_tv[i].klen);
++						 template[i].klen);
+ 			if (ret) {
+ 				printk(KERN_INFO "setkey() failed flags=%x\n",
+ 				       crypto_aead_get_flags(tfm));
+ 
+-				if (!aead_tv[i].fail)
+-					goto out;
++				if (!template[i].fail)
++					goto next_one;
+ 			}
+ 
+-			authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
++			authsize = abs(template[i].rlen - template[i].ilen);
+ 			ret = crypto_aead_setauthsize(tfm, authsize);
+ 			if (ret) {
+ 				printk(KERN_INFO
+ 				       "failed to set authsize = %u\n",
+ 				       authsize);
+-				goto out;
++				goto next_one;
+ 			}
+ 
+-			sg_init_one(&sg[0], aead_tv[i].input,
+-				    aead_tv[i].ilen + (enc ? authsize : 0));
++			sg_init_one(&sg[0], input,
++				    template[i].ilen + (enc ? authsize : 0));
+ 
+-			sg_init_one(&asg[0], aead_tv[i].assoc,
+-				    aead_tv[i].alen);
++			sg_init_one(&asg[0], assoc, template[i].alen);
+ 
+ 			aead_request_set_crypt(req, sg, sg,
+-					       aead_tv[i].ilen,
+-					       aead_tv[i].iv);
++					       template[i].ilen, iv);
+ 
+-			aead_request_set_assoc(req, asg, aead_tv[i].alen);
++			aead_request_set_assoc(req, asg, template[i].alen);
+ 
+ 			ret = enc ?
+ 				crypto_aead_encrypt(req) :
+@@ -335,15 +341,21 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ 			default:
+ 				printk(KERN_INFO "%s () failed err=%d\n",
+ 				       e, -ret);
+-				goto out;
++				goto next_one;
+ 			}
+ 
+ 			q = kmap(sg_page(&sg[0])) + sg[0].offset;
+-			hexdump(q, aead_tv[i].rlen);
++			hexdump(q, template[i].rlen);
+ 
+ 			printk(KERN_INFO "enc/dec: %s\n",
+-			       memcmp(q, aead_tv[i].result,
+-				      aead_tv[i].rlen) ? "fail" : "pass");
++			       memcmp(q, template[i].result,
++				      template[i].rlen) ? "fail" : "pass");
++			kunmap(sg_page(&sg[0]));
++next_one:
++			if (!template[i].key)
++				kfree(key);
++			kfree(assoc);
++			kfree(input);
+ 		}
+ 	}
+ 
+@@ -352,36 +364,41 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ 	memset(axbuf, 0, XBUFSIZE);
+ 
+ 	for (i = 0, j = 0; i < tcount; i++) {
+-		if (aead_tv[i].np) {
++		if (template[i].np) {
+ 			printk(KERN_INFO "test %u (%d bit key):\n",
+-			       ++j, aead_tv[i].klen * 8);
++			       ++j, template[i].klen * 8);
++
++			if (template[i].iv)
++				memcpy(iv, template[i].iv, MAX_IVLEN);
++			else
++				memset(iv, 0, MAX_IVLEN);
+ 
+ 			crypto_aead_clear_flags(tfm, ~0);
+-			if (aead_tv[i].wk)
++			if (template[i].wk)
+ 				crypto_aead_set_flags(
+ 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+-			key = aead_tv[i].key;
++			key = template[i].key;
+ 
+-			ret = crypto_aead_setkey(tfm, key, aead_tv[i].klen);
++			ret = crypto_aead_setkey(tfm, key, template[i].klen);
+ 			if (ret) {
+ 				printk(KERN_INFO "setkey() failed flags=%x\n",
+ 				       crypto_aead_get_flags(tfm));
+ 
+-				if (!aead_tv[i].fail)
++				if (!template[i].fail)
+ 					goto out;
+ 			}
+ 
+-			sg_init_table(sg, aead_tv[i].np);
+-			for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
++			sg_init_table(sg, template[i].np);
++			for (k = 0, temp = 0; k < template[i].np; k++) {
+ 				memcpy(&xbuf[IDX[k]],
+-				       aead_tv[i].input + temp,
+-				       aead_tv[i].tap[k]);
+-				temp += aead_tv[i].tap[k];
++				       template[i].input + temp,
++				       template[i].tap[k]);
++				temp += template[i].tap[k];
+ 				sg_set_buf(&sg[k], &xbuf[IDX[k]],
+-					   aead_tv[i].tap[k]);
++					   template[i].tap[k]);
+ 			}
+ 
+-			authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
++			authsize = abs(template[i].rlen - template[i].ilen);
+ 			ret = crypto_aead_setauthsize(tfm, authsize);
+ 			if (ret) {
+ 				printk(KERN_INFO
+@@ -393,21 +410,21 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ 			if (enc)
+ 				sg[k - 1].length += authsize;
+ 
+-			sg_init_table(asg, aead_tv[i].anp);
+-			for (k = 0, temp = 0; k < aead_tv[i].anp; k++) {
++			sg_init_table(asg, template[i].anp);
++			for (k = 0, temp = 0; k < template[i].anp; k++) {
+ 				memcpy(&axbuf[IDX[k]],
+-				       aead_tv[i].assoc + temp,
+-				       aead_tv[i].atap[k]);
+-				temp += aead_tv[i].atap[k];
++				       template[i].assoc + temp,
++				       template[i].atap[k]);
++				temp += template[i].atap[k];
+ 				sg_set_buf(&asg[k], &axbuf[IDX[k]],
+-					   aead_tv[i].atap[k]);
++					   template[i].atap[k]);
+ 			}
+ 
+ 			aead_request_set_crypt(req, sg, sg,
+-					       aead_tv[i].ilen,
+-					       aead_tv[i].iv);
++					       template[i].ilen,
++					       iv);
+ 
+-			aead_request_set_assoc(req, asg, aead_tv[i].alen);
++			aead_request_set_assoc(req, asg, template[i].alen);
+ 
+ 			ret = enc ?
+ 				crypto_aead_encrypt(req) :
+@@ -431,18 +448,19 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ 				goto out;
+ 			}
+ 
+-			for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
++			for (k = 0, temp = 0; k < template[i].np; k++) {
+ 				printk(KERN_INFO "page %u\n", k);
+ 				q = kmap(sg_page(&sg[k])) + sg[k].offset;
+-				hexdump(q, aead_tv[i].tap[k]);
++				hexdump(q, template[i].tap[k]);
+ 				printk(KERN_INFO "%s\n",
+-				       memcmp(q, aead_tv[i].result + temp,
+-					      aead_tv[i].tap[k] -
+-					      (k < aead_tv[i].np - 1 || enc ?
++				       memcmp(q, template[i].result + temp,
++					      template[i].tap[k] -
++					      (k < template[i].np - 1 || enc ?
+ 					       0 : authsize)) ?
+ 				       "fail" : "pass");
+ 
+-				temp += aead_tv[i].tap[k];
++				temp += template[i].tap[k];
++				kunmap(sg_page(&sg[k]));
+ 			}
+ 		}
+ 	}
+@@ -456,15 +474,14 @@ static void test_cipher(char *algo, int enc,
+ 			struct cipher_testvec *template, unsigned int tcount)
+ {
+ 	unsigned int ret, i, j, k, temp;
+-	unsigned int tsize;
+ 	char *q;
+ 	struct crypto_ablkcipher *tfm;
+-	char *key;
+-	struct cipher_testvec *cipher_tv;
+ 	struct ablkcipher_request *req;
+ 	struct scatterlist sg[8];
+ 	const char *e;
+ 	struct tcrypt_result result;
++	void *data;
++	char iv[MAX_IVLEN];
+ 
+ 	if (enc == ENCRYPT)
+ 	        e = "encryption";
+@@ -473,16 +490,7 @@ static void test_cipher(char *algo, int enc,
+ 
+ 	printk("\ntesting %s %s\n", algo, e);
+ 
+-	tsize = sizeof (struct cipher_testvec);
+-	if (tsize > TVMEMSIZE) {
+-		printk("template (%u) too big for tvmem (%u)\n", tsize,
+-		       TVMEMSIZE);
+-		return;
+-	}
+-	cipher_tv = (void *)tvmem;
+-
+ 	init_completion(&result.completion);
+-
+ 	tfm = crypto_alloc_ablkcipher(algo, 0, 0);
+ 
+ 	if (IS_ERR(tfm)) {
+@@ -502,35 +510,43 @@ static void test_cipher(char *algo, int enc,
+ 
+ 	j = 0;
+ 	for (i = 0; i < tcount; i++) {
+-		memcpy(cipher_tv, &template[i], tsize);
+-		if (!(cipher_tv->np)) {
++
++		data = kzalloc(template[i].ilen, GFP_KERNEL);
++		if (!data)
++			continue;
++
++		memcpy(data, template[i].input, template[i].ilen);
++		if (template[i].iv)
++			memcpy(iv, template[i].iv, MAX_IVLEN);
++		else
++			memset(iv, 0, MAX_IVLEN);
++
++		if (!(template[i].np)) {
+ 			j++;
+ 			printk("test %u (%d bit key):\n",
+-			j, cipher_tv->klen * 8);
++			j, template[i].klen * 8);
+ 
+ 			crypto_ablkcipher_clear_flags(tfm, ~0);
+-			if (cipher_tv->wk)
++			if (template[i].wk)
+ 				crypto_ablkcipher_set_flags(
+ 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+-			key = cipher_tv->key;
+ 
+-			ret = crypto_ablkcipher_setkey(tfm, key,
+-						       cipher_tv->klen);
++			ret = crypto_ablkcipher_setkey(tfm, template[i].key,
++						       template[i].klen);
+ 			if (ret) {
+ 				printk("setkey() failed flags=%x\n",
+ 				       crypto_ablkcipher_get_flags(tfm));
+ 
+-				if (!cipher_tv->fail)
++				if (!template[i].fail) {
++					kfree(data);
+ 					goto out;
++				}
+ 			}
+ 
+-			sg_init_one(&sg[0], cipher_tv->input,
+-				    cipher_tv->ilen);
++			sg_init_one(&sg[0], data, template[i].ilen);
+ 
+ 			ablkcipher_request_set_crypt(req, sg, sg,
+-						     cipher_tv->ilen,
+-						     cipher_tv->iv);
+-
++						     template[i].ilen, iv);
+ 			ret = enc ?
+ 				crypto_ablkcipher_encrypt(req) :
+ 				crypto_ablkcipher_decrypt(req);
+@@ -549,16 +565,19 @@ static void test_cipher(char *algo, int enc,
+ 				/* fall through */
+ 			default:
+ 				printk("%s () failed err=%d\n", e, -ret);
++				kfree(data);
+ 				goto out;
+ 			}
+ 
+ 			q = kmap(sg_page(&sg[0])) + sg[0].offset;
+-			hexdump(q, cipher_tv->rlen);
++			hexdump(q, template[i].rlen);
+ 
+ 			printk("%s\n",
+-			       memcmp(q, cipher_tv->result,
+-				      cipher_tv->rlen) ? "fail" : "pass");
++			       memcmp(q, template[i].result,
++				      template[i].rlen) ? "fail" : "pass");
++			kunmap(sg_page(&sg[0]));
+ 		}
++		kfree(data);
+ 	}
+ 
+ 	printk("\ntesting %s %s across pages (chunking)\n", algo, e);
+@@ -566,42 +585,53 @@ static void test_cipher(char *algo, int enc,
+ 
+ 	j = 0;
+ 	for (i = 0; i < tcount; i++) {
+-		memcpy(cipher_tv, &template[i], tsize);
+-		if (cipher_tv->np) {
++
++		data = kzalloc(template[i].ilen, GFP_KERNEL);
++		if (!data)
++			continue;
++
++		memcpy(data, template[i].input, template[i].ilen);
++
++		if (template[i].iv)
++			memcpy(iv, template[i].iv, MAX_IVLEN);
++		else
++			memset(iv, 0, MAX_IVLEN);
++
++		if (template[i].np) {
+ 			j++;
+ 			printk("test %u (%d bit key):\n",
+-			j, cipher_tv->klen * 8);
++			j, template[i].klen * 8);
+ 
+ 			crypto_ablkcipher_clear_flags(tfm, ~0);
+-			if (cipher_tv->wk)
++			if (template[i].wk)
+ 				crypto_ablkcipher_set_flags(
+ 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+-			key = cipher_tv->key;
+ 
+-			ret = crypto_ablkcipher_setkey(tfm, key,
+-						       cipher_tv->klen);
++			ret = crypto_ablkcipher_setkey(tfm, template[i].key,
++						       template[i].klen);
+ 			if (ret) {
+ 				printk("setkey() failed flags=%x\n",
+-				       crypto_ablkcipher_get_flags(tfm));
++						crypto_ablkcipher_get_flags(tfm));
+ 
+-				if (!cipher_tv->fail)
++				if (!template[i].fail) {
++					kfree(data);
+ 					goto out;
++				}
+ 			}
+ 
+ 			temp = 0;
+-			sg_init_table(sg, cipher_tv->np);
+-			for (k = 0; k < cipher_tv->np; k++) {
++			sg_init_table(sg, template[i].np);
++			for (k = 0; k < template[i].np; k++) {
+ 				memcpy(&xbuf[IDX[k]],
+-				       cipher_tv->input + temp,
+-				       cipher_tv->tap[k]);
+-				temp += cipher_tv->tap[k];
++						template[i].input + temp,
++						template[i].tap[k]);
++				temp += template[i].tap[k];
+ 				sg_set_buf(&sg[k], &xbuf[IDX[k]],
+-					   cipher_tv->tap[k]);
++						template[i].tap[k]);
+ 			}
+ 
+ 			ablkcipher_request_set_crypt(req, sg, sg,
+-						     cipher_tv->ilen,
+-						     cipher_tv->iv);
++					template[i].ilen, iv);
+ 
+ 			ret = enc ?
+ 				crypto_ablkcipher_encrypt(req) :
+@@ -625,19 +655,19 @@ static void test_cipher(char *algo, int enc,
+ 			}
+ 
+ 			temp = 0;
+-			for (k = 0; k < cipher_tv->np; k++) {
++			for (k = 0; k < template[i].np; k++) {
+ 				printk("page %u\n", k);
+ 				q = kmap(sg_page(&sg[k])) + sg[k].offset;
+-				hexdump(q, cipher_tv->tap[k]);
++				hexdump(q, template[i].tap[k]);
+ 				printk("%s\n",
+-					memcmp(q, cipher_tv->result + temp,
+-						cipher_tv->tap[k]) ? "fail" :
++					memcmp(q, template[i].result + temp,
++						template[i].tap[k]) ? "fail" :
+ 					"pass");
+-				temp += cipher_tv->tap[k];
++				temp += template[i].tap[k];
++				kunmap(sg_page(&sg[k]));
+ 			}
+ 		}
+ 	}
+-
+ out:
+ 	crypto_free_ablkcipher(tfm);
+ 	ablkcipher_request_free(req);
+@@ -721,15 +751,18 @@ out:
+ 	return ret;
+ }
+ 
++static u32 block_sizes[] = { 16, 64, 256, 1024, 8192, 0 };
++
+ static void test_cipher_speed(char *algo, int enc, unsigned int sec,
+ 			      struct cipher_testvec *template,
+-			      unsigned int tcount, struct cipher_speed *speed)
++			      unsigned int tcount, u8 *keysize)
+ {
+ 	unsigned int ret, i, j, iv_len;
+ 	unsigned char *key, *p, iv[128];
+ 	struct crypto_blkcipher *tfm;
+ 	struct blkcipher_desc desc;
+ 	const char *e;
++	u32 *b_size;
+ 
+ 	if (enc == ENCRYPT)
+ 	        e = "encryption";
+@@ -748,52 +781,60 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec,
+ 	desc.tfm = tfm;
+ 	desc.flags = 0;
+ 
+-	for (i = 0; speed[i].klen != 0; i++) {
+-		if ((speed[i].blen + speed[i].klen) > TVMEMSIZE) {
+-			printk("template (%u) too big for tvmem (%u)\n",
+-			       speed[i].blen + speed[i].klen, TVMEMSIZE);
+-			goto out;
+-		}
++	i = 0;
++	do {
++
++		b_size = block_sizes;
++		do {
++
++			if ((*keysize + *b_size) > TVMEMSIZE) {
++				printk("template (%u) too big for tvmem (%u)\n",
++						*keysize + *b_size, TVMEMSIZE);
++				goto out;
++			}
+ 
+-		printk("test %u (%d bit key, %d byte blocks): ", i,
+-		       speed[i].klen * 8, speed[i].blen);
++			printk("test %u (%d bit key, %d byte blocks): ", i,
++					*keysize * 8, *b_size);
+ 
+-		memset(tvmem, 0xff, speed[i].klen + speed[i].blen);
++			memset(tvmem, 0xff, *keysize + *b_size);
+ 
+-		/* set key, plain text and IV */
+-		key = (unsigned char *)tvmem;
+-		for (j = 0; j < tcount; j++) {
+-			if (template[j].klen == speed[i].klen) {
+-				key = template[j].key;
+-				break;
++			/* set key, plain text and IV */
++			key = (unsigned char *)tvmem;
++			for (j = 0; j < tcount; j++) {
++				if (template[j].klen == *keysize) {
++					key = template[j].key;
++					break;
++				}
+ 			}
+-		}
+-		p = (unsigned char *)tvmem + speed[i].klen;
++			p = (unsigned char *)tvmem + *keysize;
+ 
+-		ret = crypto_blkcipher_setkey(tfm, key, speed[i].klen);
+-		if (ret) {
+-			printk("setkey() failed flags=%x\n",
+-			       crypto_blkcipher_get_flags(tfm));
+-			goto out;
+-		}
++			ret = crypto_blkcipher_setkey(tfm, key, *keysize);
++			if (ret) {
++				printk("setkey() failed flags=%x\n",
++						crypto_blkcipher_get_flags(tfm));
++				goto out;
++			}
+ 
+-		iv_len = crypto_blkcipher_ivsize(tfm);
+-		if (iv_len) {
+-			memset(&iv, 0xff, iv_len);
+-			crypto_blkcipher_set_iv(tfm, iv, iv_len);
+-		}
++			iv_len = crypto_blkcipher_ivsize(tfm);
++			if (iv_len) {
++				memset(&iv, 0xff, iv_len);
++				crypto_blkcipher_set_iv(tfm, iv, iv_len);
++			}
+ 
+-		if (sec)
+-			ret = test_cipher_jiffies(&desc, enc, p, speed[i].blen,
+-						  sec);
+-		else
+-			ret = test_cipher_cycles(&desc, enc, p, speed[i].blen);
++			if (sec)
++				ret = test_cipher_jiffies(&desc, enc, p, *b_size, sec);
++			else
++				ret = test_cipher_cycles(&desc, enc, p, *b_size);
+ 
+-		if (ret) {
+-			printk("%s() failed flags=%x\n", e, desc.flags);
+-			break;
+-		}
+-	}
++			if (ret) {
++				printk("%s() failed flags=%x\n", e, desc.flags);
++				break;
++			}
++			b_size++;
++			i++;
++		} while (*b_size);
++		keysize++;
++	} while (*keysize);
+ 
+ out:
+ 	crypto_free_blkcipher(tfm);
+@@ -1041,22 +1082,10 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ 	unsigned int i;
+ 	char result[COMP_BUF_SIZE];
+ 	struct crypto_comp *tfm;
+-	struct comp_testvec *tv;
+ 	unsigned int tsize;
+ 
+ 	printk("\ntesting %s compression\n", algo);
+ 
+-	tsize = sizeof(struct comp_testvec);
+-	tsize *= ctcount;
+-	if (tsize > TVMEMSIZE) {
+-		printk("template (%u) too big for tvmem (%u)\n", tsize,
+-		       TVMEMSIZE);
+-		return;
+-	}
+-
+-	memcpy(tvmem, ctemplate, tsize);
+-	tv = (void *)tvmem;
+-
+ 	tfm = crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC);
+ 	if (IS_ERR(tfm)) {
+ 		printk("failed to load transform for %s\n", algo);
+@@ -1069,8 +1098,8 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ 		printk("test %u:\n", i + 1);
+ 		memset(result, 0, sizeof (result));
+ 
+-		ilen = tv[i].inlen;
+-		ret = crypto_comp_compress(tfm, tv[i].input,
++		ilen = ctemplate[i].inlen;
++		ret = crypto_comp_compress(tfm, ctemplate[i].input,
+ 		                           ilen, result, &dlen);
+ 		if (ret) {
+ 			printk("fail: ret=%d\n", ret);
+@@ -1078,7 +1107,7 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ 		}
+ 		hexdump(result, dlen);
+ 		printk("%s (ratio %d:%d)\n",
+-		       memcmp(result, tv[i].output, dlen) ? "fail" : "pass",
++		       memcmp(result, ctemplate[i].output, dlen) ? "fail" : "pass",
+ 		       ilen, dlen);
+ 	}
+ 
+@@ -1092,17 +1121,14 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ 		goto out;
+ 	}
+ 
+-	memcpy(tvmem, dtemplate, tsize);
+-	tv = (void *)tvmem;
+-
+ 	for (i = 0; i < dtcount; i++) {
+ 		int ilen, ret, dlen = COMP_BUF_SIZE;
+ 
+ 		printk("test %u:\n", i + 1);
+ 		memset(result, 0, sizeof (result));
+ 
+-		ilen = tv[i].inlen;
+-		ret = crypto_comp_decompress(tfm, tv[i].input,
++		ilen = dtemplate[i].inlen;
++		ret = crypto_comp_decompress(tfm, dtemplate[i].input,
+ 		                             ilen, result, &dlen);
+ 		if (ret) {
+ 			printk("fail: ret=%d\n", ret);
+@@ -1110,7 +1136,7 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ 		}
+ 		hexdump(result, dlen);
+ 		printk("%s (ratio %d:%d)\n",
+-		       memcmp(result, tv[i].output, dlen) ? "fail" : "pass",
++		       memcmp(result, dtemplate[i].output, dlen) ? "fail" : "pass",
+ 		       ilen, dlen);
+ 	}
+ out:
+@@ -1301,6 +1327,12 @@ static void do_test(void)
+ 		test_cipher("ecb(seed)", DECRYPT, seed_dec_tv_template,
+ 			    SEED_DEC_TEST_VECTORS);
+ 
++		//CTS
++		test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
++			    CTS_MODE_ENC_TEST_VECTORS);
++		test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
++			    CTS_MODE_DEC_TEST_VECTORS);
++
+ 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
+ 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
+ 		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
+@@ -1584,6 +1616,13 @@ static void do_test(void)
+ 			  AES_CCM_DEC_TEST_VECTORS);
+ 		break;
+ 
++	case 38:
++		test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
++			    CTS_MODE_ENC_TEST_VECTORS);
++		test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
++			    CTS_MODE_DEC_TEST_VECTORS);
++		break;
++
+ 	case 100:
+ 		test_hash("hmac(md5)", hmac_md5_tv_template,
+ 			  HMAC_MD5_TEST_VECTORS);
+@@ -1621,89 +1660,85 @@ static void do_test(void)
+ 
+ 	case 200:
+ 		test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
+-				  aes_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("ecb(aes)", DECRYPT, sec, NULL, 0,
+-				  aes_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("cbc(aes)", ENCRYPT, sec, NULL, 0,
+-				  aes_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0,
+-				  aes_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("lrw(aes)", ENCRYPT, sec, NULL, 0,
+-				  aes_lrw_speed_template);
++				speed_template_32_40_48);
+ 		test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0,
+-				  aes_lrw_speed_template);
++				speed_template_32_40_48);
+ 		test_cipher_speed("xts(aes)", ENCRYPT, sec, NULL, 0,
+-				  aes_xts_speed_template);
++				speed_template_32_48_64);
+ 		test_cipher_speed("xts(aes)", DECRYPT, sec, NULL, 0,
+-				  aes_xts_speed_template);
++				speed_template_32_48_64);
+ 		break;
+ 
+ 	case 201:
+ 		test_cipher_speed("ecb(des3_ede)", ENCRYPT, sec,
+-				  des3_ede_enc_tv_template,
+-				  DES3_EDE_ENC_TEST_VECTORS,
+-				  des3_ede_speed_template);
++				des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
++				speed_template_24);
+ 		test_cipher_speed("ecb(des3_ede)", DECRYPT, sec,
+-				  des3_ede_dec_tv_template,
+-				  DES3_EDE_DEC_TEST_VECTORS,
+-				  des3_ede_speed_template);
++				des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
++				speed_template_24);
+ 		test_cipher_speed("cbc(des3_ede)", ENCRYPT, sec,
+-				  des3_ede_enc_tv_template,
+-				  DES3_EDE_ENC_TEST_VECTORS,
+-				  des3_ede_speed_template);
++				des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
++				speed_template_24);
+ 		test_cipher_speed("cbc(des3_ede)", DECRYPT, sec,
+-				  des3_ede_dec_tv_template,
+-				  DES3_EDE_DEC_TEST_VECTORS,
+-				  des3_ede_speed_template);
++				des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
++				speed_template_24);
+ 		break;
+ 
+ 	case 202:
+ 		test_cipher_speed("ecb(twofish)", ENCRYPT, sec, NULL, 0,
+-				  twofish_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("ecb(twofish)", DECRYPT, sec, NULL, 0,
+-				  twofish_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("cbc(twofish)", ENCRYPT, sec, NULL, 0,
+-				  twofish_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0,
+-				  twofish_speed_template);
++				speed_template_16_24_32);
+ 		break;
+ 
+ 	case 203:
+ 		test_cipher_speed("ecb(blowfish)", ENCRYPT, sec, NULL, 0,
+-				  blowfish_speed_template);
++				  speed_template_8_32);
+ 		test_cipher_speed("ecb(blowfish)", DECRYPT, sec, NULL, 0,
+-				  blowfish_speed_template);
++				  speed_template_8_32);
+ 		test_cipher_speed("cbc(blowfish)", ENCRYPT, sec, NULL, 0,
+-				  blowfish_speed_template);
++				  speed_template_8_32);
+ 		test_cipher_speed("cbc(blowfish)", DECRYPT, sec, NULL, 0,
+-				  blowfish_speed_template);
++				  speed_template_8_32);
+ 		break;
+ 
+ 	case 204:
+ 		test_cipher_speed("ecb(des)", ENCRYPT, sec, NULL, 0,
+-				  des_speed_template);
++				  speed_template_8);
+ 		test_cipher_speed("ecb(des)", DECRYPT, sec, NULL, 0,
+-				  des_speed_template);
++				  speed_template_8);
+ 		test_cipher_speed("cbc(des)", ENCRYPT, sec, NULL, 0,
+-				  des_speed_template);
++				  speed_template_8);
+ 		test_cipher_speed("cbc(des)", DECRYPT, sec, NULL, 0,
+-				  des_speed_template);
++				  speed_template_8);
+ 		break;
+ 
+ 	case 205:
+ 		test_cipher_speed("ecb(camellia)", ENCRYPT, sec, NULL, 0,
+-				camellia_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("ecb(camellia)", DECRYPT, sec, NULL, 0,
+-				camellia_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("cbc(camellia)", ENCRYPT, sec, NULL, 0,
+-				camellia_speed_template);
++				speed_template_16_24_32);
+ 		test_cipher_speed("cbc(camellia)", DECRYPT, sec, NULL, 0,
+-				camellia_speed_template);
++				speed_template_16_24_32);
+ 		break;
+ 
+ 	case 206:
+ 		test_cipher_speed("salsa20", ENCRYPT, sec, NULL, 0,
+-				  salsa20_speed_template);
++				  speed_template_16_32);
+ 		break;
+ 
+ 	case 300:
+@@ -1775,7 +1810,7 @@ static void do_test(void)
+ 	}
+ }
+ 
+-static int __init init(void)
++static int __init tcrypt_mod_init(void)
+ {
+ 	int err = -ENOMEM;
+ 
+@@ -1814,10 +1849,10 @@ static int __init init(void)
+  * If an init function is provided, an exit function must also be provided
+  * to allow module unload.
+  */
+-static void __exit fini(void) { }
++static void __exit tcrypt_mod_fini(void) { }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(tcrypt_mod_init);
++module_exit(tcrypt_mod_fini);
+ 
+ module_param(mode, int, 0);
+ module_param(sec, uint, 0);
+diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
+index f785e56..47bc0ec 100644
+--- a/crypto/tcrypt.h
++++ b/crypto/tcrypt.h
+@@ -31,9 +31,9 @@
+ 
+ struct hash_testvec {
+ 	/* only used with keyed hash algorithms */
+-	char key[132] __attribute__ ((__aligned__(4)));
+-	char plaintext[240];
+-	char digest[MAX_DIGEST_SIZE];
++	char *key;
++	char *plaintext;
++	char *digest;
+ 	unsigned char tap[MAX_TAP];
+ 	unsigned char psize;
+ 	unsigned char np;
+@@ -41,10 +41,10 @@ struct hash_testvec {
+ };
+ 
+ struct cipher_testvec {
+-	char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
+-	char iv[MAX_IVLEN];
+-	char input[4100];
+-	char result[4100];
++	char *key;
++	char *iv;
++	char *input;
++	char *result;
+ 	unsigned char tap[MAX_TAP];
+ 	int np;
+ 	unsigned char fail;
+@@ -55,11 +55,11 @@ struct cipher_testvec {
+ };
+ 
+ struct aead_testvec {
+-	char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
+-	char iv[MAX_IVLEN];
+-	char input[512];
+-	char assoc[512];
+-	char result[512];
++	char *key;
++	char *iv;
++	char *input;
++	char *assoc;
++	char *result;
+ 	unsigned char tap[MAX_TAP];
+ 	unsigned char atap[MAX_TAP];
+ 	int np;
+@@ -72,16 +72,13 @@ struct aead_testvec {
+ 	unsigned short rlen;
+ };
+ 
+-struct cipher_speed {
+-	unsigned char klen;
+-	unsigned int blen;
+-};
+-
+ struct hash_speed {
+ 	unsigned int blen;	/* buffer length */
+ 	unsigned int plen;	/* per-update length */
+ };
+ 
++static char zeroed_string[48];
++
+ /*
+  * MD4 test vectors from RFC1320
+  */
+@@ -90,41 +87,41 @@ struct hash_speed {
+ static struct hash_testvec md4_tv_template [] = {
+ 	{
+ 		.plaintext = "",
+-		.digest	= { 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
+-			    0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 },
++		.digest	= "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31"
++			  "\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0",
+ 	}, {
+ 		.plaintext = "a",
+ 		.psize	= 1,
+-		.digest	= { 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
+-			    0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 },
++		.digest	= "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46"
++			  "\x24\x5e\x05\xfb\xdb\xd6\xfb\x24",
+ 	}, {
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest	= { 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
+-			    0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d },
++		.digest	= "\xa4\x48\x01\x7a\xaf\x21\xd8\x52"
++			  "\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d",
+ 	}, {
+ 		.plaintext = "message digest",
+ 		.psize	= 14,
+-		.digest	= { 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
+-			    0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b },
++		.digest	= "\xd9\x13\x0a\x81\x64\x54\x9f\xe8"
++			"\x18\x87\x48\x06\xe1\xc7\x01\x4b",
+ 	}, {
+ 		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+ 		.psize	= 26,
+-		.digest	= { 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
+-			    0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 },
++		.digest	= "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd"
++			  "\xee\xa8\xed\x63\xdf\x41\x2d\xa9",
+ 		.np	= 2,
+ 		.tap	= { 13, 13 },
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ 		.psize	= 62,
+-		.digest	= { 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
+-			    0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 },
++		.digest	= "\x04\x3f\x85\x82\xf2\x41\xdb\x35"
++			  "\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4",
+ 	}, {
+ 		.plaintext = "123456789012345678901234567890123456789012345678901234567890123"
+-			     "45678901234567890",
++			   "45678901234567890",
+ 		.psize	= 80,
+-		.digest	= { 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
+-			    0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 },
++		.digest	= "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19"
++			  "\x9c\x3e\x7b\x16\x4f\xcc\x05\x36",
+ 	},
+ };
+ 
+@@ -135,41 +132,41 @@ static struct hash_testvec md4_tv_template [] = {
+ 
+ static struct hash_testvec md5_tv_template[] = {
+ 	{
+-		.digest	= { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+-			    0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e },
++		.digest	= "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04"
++			  "\xe9\x80\x09\x98\xec\xf8\x42\x7e",
+ 	}, {
+ 		.plaintext = "a",
+ 		.psize	= 1,
+-		.digest	= { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
+-			    0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 },
++		.digest	= "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8"
++			  "\x31\xc3\x99\xe2\x69\x77\x26\x61",
+ 	}, {
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest	= { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
+-			    0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 },
++		.digest	= "\x90\x01\x50\x98\x3c\xd2\x4f\xb0"
++			  "\xd6\x96\x3f\x7d\x28\xe1\x7f\x72",
+ 	}, {
+ 		.plaintext = "message digest",
+ 		.psize	= 14,
+-		.digest	= { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
+-			    0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 },
++		.digest	= "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d"
++			  "\x52\x5a\x2f\x31\xaa\xf1\x61\xd0",
+ 	}, {
+ 		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+ 		.psize	= 26,
+-		.digest	= { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
+-			    0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b },
++		.digest	= "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00"
++			  "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b",
+ 		.np	= 2,
+ 		.tap	= {13, 13}
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ 		.psize	= 62,
+-		.digest	= { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
+-			    0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f },
++		.digest	= "\xd1\x74\xab\x98\xd2\x77\xd9\xf5"
++			  "\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f",
+ 	}, {
+ 		.plaintext = "12345678901234567890123456789012345678901234567890123456789012"
+-			     "345678901234567890",
++			   "345678901234567890",
+ 		.psize	= 80,
+-		.digest	= { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
+-			    0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a },
++		.digest	= "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55"
++			  "\xac\x49\xda\x2e\x21\x07\xb6\x7a",
+ 	}
+ };
+ 
+@@ -182,13 +179,13 @@ static struct hash_testvec sha1_tv_template[] = {
+ 	{
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest	= { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
+-			    0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d },
++		.digest	= "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e"
++			  "\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d",
+ 	}, {
+ 		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ 		.psize	= 56,
+-		.digest	= { 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae,
+-			    0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1 },
++		.digest	= "\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae"
++			  "\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1",
+ 		.np	= 2,
+ 		.tap	= { 28, 28 }
+ 	}
+@@ -204,18 +201,18 @@ static struct hash_testvec sha224_tv_template[] = {
+ 	{
+ 		.plaintext = "abc",
+ 		.psize  = 3,
+-		.digest = { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
+-			0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+-			0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
+-			0xE3, 0x6C, 0x9D, 0xA7},
++		.digest = "\x23\x09\x7D\x22\x34\x05\xD8\x22"
++			  "\x86\x42\xA4\x77\xBD\xA2\x55\xB3"
++			  "\x2A\xAD\xBC\xE4\xBD\xA0\xB3\xF7"
++			  "\xE3\x6C\x9D\xA7",
+ 	}, {
+ 		.plaintext =
+ 		"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ 		.psize  = 56,
+-		.digest = { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
+-			0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+-			0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
+-			0x52, 0x52, 0x25, 0x25 },
++		.digest = "\x75\x38\x8B\x16\x51\x27\x76\xCC"
++			  "\x5D\xBA\x5D\xA1\xFD\x89\x01\x50"
++			  "\xB0\xC6\x45\x5C\xB4\xF5\x8B\x19"
++			  "\x52\x52\x25\x25",
+ 		.np     = 2,
+ 		.tap    = { 28, 28 }
+ 	}
+@@ -230,17 +227,17 @@ static struct hash_testvec sha256_tv_template[] = {
+ 	{
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest	= { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
+-			    0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+-			    0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+-			    0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad },
++		.digest	= "\xba\x78\x16\xbf\x8f\x01\xcf\xea"
++			  "\x41\x41\x40\xde\x5d\xae\x22\x23"
++			  "\xb0\x03\x61\xa3\x96\x17\x7a\x9c"
++			  "\xb4\x10\xff\x61\xf2\x00\x15\xad",
+ 	}, {
+ 		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ 		.psize	= 56,
+-		.digest	= { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
+-			    0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+-			    0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
+-			    0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 },
++		.digest	= "\x24\x8d\x6a\x61\xd2\x06\x38\xb8"
++			  "\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
++			  "\xa3\x3c\xe4\x59\x64\xff\x21\x67"
++			  "\xf6\xec\xed\xd4\x19\xdb\x06\xc1",
+ 		.np	= 2,
+ 		.tap	= { 28, 28 }
+ 	},
+@@ -255,41 +252,41 @@ static struct hash_testvec sha384_tv_template[] = {
+ 	{
+ 		.plaintext= "abc",
+ 		.psize	= 3,
+-		.digest	= { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
+-			    0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
+-			    0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
+-			    0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
+-			    0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
+-			    0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 },
++		.digest	= "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b"
++			  "\xb5\xa0\x3d\x69\x9a\xc6\x50\x07"
++			  "\x27\x2c\x32\xab\x0e\xde\xd1\x63"
++			  "\x1a\x8b\x60\x5a\x43\xff\x5b\xed"
++			  "\x80\x86\x07\x2b\xa1\xe7\xcc\x23"
++			  "\x58\xba\xec\xa1\x34\xc8\x25\xa7",
+ 	}, {
+ 		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ 		.psize	= 56,
+-		.digest	= { 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39,
+-			    0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39,
+-			    0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab,
+-			    0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6,
+-			    0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f,
+-			    0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b},
++		.digest	= "\x33\x91\xfd\xdd\xfc\x8d\xc7\x39"
++			  "\x37\x07\xa6\x5b\x1b\x47\x09\x39"
++			  "\x7c\xf8\xb1\xd1\x62\xaf\x05\xab"
++			  "\xfe\x8f\x45\x0d\xe5\xf3\x6b\xc6"
++			  "\xb0\x45\x5a\x85\x20\xbc\x4e\x6f"
++			  "\x5f\xe9\x5b\x1f\xe3\xc8\x45\x2b",
+ 	}, {
+ 		.plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+-			     "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
++			   "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ 		.psize	= 112,
+-		.digest	= { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
+-			    0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
+-			    0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
+-			    0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
+-			    0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
+-			    0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39  },
++		.digest	= "\x09\x33\x0c\x33\xf7\x11\x47\xe8"
++			  "\x3d\x19\x2f\xc7\x82\xcd\x1b\x47"
++			  "\x53\x11\x1b\x17\x3b\x3b\x05\xd2"
++			  "\x2f\xa0\x80\x86\xe3\xb0\xf7\x12"
++			  "\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9"
++			  "\x66\xc3\xe9\xfa\x91\x74\x60\x39",
+ 	}, {
+ 		.plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"
+-			     "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
++			   "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+ 		.psize	= 104,
+-		.digest	= { 0x3d, 0x20, 0x89, 0x73, 0xab, 0x35, 0x08, 0xdb,
+-			    0xbd, 0x7e, 0x2c, 0x28, 0x62, 0xba, 0x29, 0x0a,
+-			    0xd3, 0x01, 0x0e, 0x49, 0x78, 0xc1, 0x98, 0xdc,
+-			    0x4d, 0x8f, 0xd0, 0x14, 0xe5, 0x82, 0x82, 0x3a,
+-			    0x89, 0xe1, 0x6f, 0x9b, 0x2a, 0x7b, 0xbc, 0x1a,
+-			    0xc9, 0x38, 0xe2, 0xd1, 0x99, 0xe8, 0xbe, 0xa4 },
++		.digest	= "\x3d\x20\x89\x73\xab\x35\x08\xdb"
++			  "\xbd\x7e\x2c\x28\x62\xba\x29\x0a"
++			  "\xd3\x01\x0e\x49\x78\xc1\x98\xdc"
++			  "\x4d\x8f\xd0\x14\xe5\x82\x82\x3a"
++			  "\x89\xe1\x6f\x9b\x2a\x7b\xbc\x1a"
++			  "\xc9\x38\xe2\xd1\x99\xe8\xbe\xa4",
+ 		.np	= 4,
+ 		.tap	= { 26, 26, 26, 26 }
+ 	},
+@@ -304,49 +301,49 @@ static struct hash_testvec sha512_tv_template[] = {
+ 	{
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest	= { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
+-			    0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+-			    0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
+-			    0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+-			    0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
+-			    0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+-			    0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
+-			    0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f },
++		.digest	= "\xdd\xaf\x35\xa1\x93\x61\x7a\xba"
++			  "\xcc\x41\x73\x49\xae\x20\x41\x31"
++			  "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2"
++			  "\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
++			  "\x21\x92\x99\x2a\x27\x4f\xc1\xa8"
++			  "\x36\xba\x3c\x23\xa3\xfe\xeb\xbd"
++			  "\x45\x4d\x44\x23\x64\x3c\xe8\x0e"
++			  "\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f",
+ 	}, {
+ 		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ 		.psize	= 56,
+-		.digest	= { 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a,
+-			    0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16,
+-			    0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8,
+-			    0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35,
+-			    0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9,
+-			    0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0,
+-			    0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03,
+-			    0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45 },
++		.digest	= "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a"
++			  "\x0c\xed\x7b\xeb\x8e\x08\xa4\x16"
++			  "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8"
++			  "\x27\x9b\xe3\x31\xa7\x03\xc3\x35"
++			  "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9"
++			  "\xaa\x1d\x3b\xea\x57\x78\x9c\xa0"
++			  "\x31\xad\x85\xc7\xa7\x1d\xd7\x03"
++			  "\x54\xec\x63\x12\x38\xca\x34\x45",
+ 	}, {
+ 		.plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+-			     "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
++			   "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ 		.psize	= 112,
+-		.digest	= { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
+-			    0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
+-			    0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
+-			    0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
+-			    0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
+-			    0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
+-			    0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
+-			    0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 },
++		.digest	= "\x8e\x95\x9b\x75\xda\xe3\x13\xda"
++			  "\x8c\xf4\xf7\x28\x14\xfc\x14\x3f"
++			  "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1"
++			  "\x72\x99\xae\xad\xb6\x88\x90\x18"
++			  "\x50\x1d\x28\x9e\x49\x00\xf7\xe4"
++			  "\x33\x1b\x99\xde\xc4\xb5\x43\x3a"
++			  "\xc7\xd3\x29\xee\xb6\xdd\x26\x54"
++			  "\x5e\x96\xe5\x5b\x87\x4b\xe9\x09",
+ 	}, {
+ 		.plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"
+-			     "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
++			   "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+ 		.psize	= 104,
+-		.digest	= { 0x93, 0x0d, 0x0c, 0xef, 0xcb, 0x30, 0xff, 0x11,
+-			    0x33, 0xb6, 0x89, 0x81, 0x21, 0xf1, 0xcf, 0x3d,
+-			    0x27, 0x57, 0x8a, 0xfc, 0xaf, 0xe8, 0x67, 0x7c,
+-			    0x52, 0x57, 0xcf, 0x06, 0x99, 0x11, 0xf7, 0x5d,
+-			    0x8f, 0x58, 0x31, 0xb5, 0x6e, 0xbf, 0xda, 0x67,
+-			    0xb2, 0x78, 0xe6, 0x6d, 0xff, 0x8b, 0x84, 0xfe,
+-			    0x2b, 0x28, 0x70, 0xf7, 0x42, 0xa5, 0x80, 0xd8,
+-			    0xed, 0xb4, 0x19, 0x87, 0x23, 0x28, 0x50, 0xc9 },
++		.digest	= "\x93\x0d\x0c\xef\xcb\x30\xff\x11"
++			  "\x33\xb6\x89\x81\x21\xf1\xcf\x3d"
++			  "\x27\x57\x8a\xfc\xaf\xe8\x67\x7c"
++			  "\x52\x57\xcf\x06\x99\x11\xf7\x5d"
++			  "\x8f\x58\x31\xb5\x6e\xbf\xda\x67"
++			  "\xb2\x78\xe6\x6d\xff\x8b\x84\xfe"
++			  "\x2b\x28\x70\xf7\x42\xa5\x80\xd8"
++			  "\xed\xb4\x19\x87\x23\x28\x50\xc9",
+ 		.np	= 4,
+ 		.tap	= { 26, 26, 26, 26 }
+ 	},
+@@ -364,95 +361,95 @@ static struct hash_testvec wp512_tv_template[] = {
+ 	{
+ 		.plaintext = "",
+ 		.psize	= 0,
+-		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+-			    0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+-			    0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+-			    0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+-			    0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB,
+-			    0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57,
+-			    0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37,
+-			    0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 },
++		.digest	= "\x19\xFA\x61\xD7\x55\x22\xA4\x66"
++			  "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26"
++			  "\xC5\x30\x23\x21\x30\xD4\x07\xF8"
++			  "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7"
++			  "\x3E\x83\xBE\x69\x8B\x28\x8F\xEB"
++			  "\xCF\x88\xE3\xE0\x3C\x4F\x07\x57"
++			  "\xEA\x89\x64\xE5\x9B\x63\xD9\x37"
++			  "\x08\xB1\x38\xCC\x42\xA6\x6E\xB3",
+ 
+ 
+ 	}, {
+ 		.plaintext = "a",
+ 		.psize	= 1,
+-		.digest	= { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+-			    0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+-			    0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+-			    0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42,
+-			    0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6,
+-			    0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59,
+-			    0x1A, 0x92, 0x20, 0x0D, 0x56, 0x01, 0x95, 0xE5,
+-			    0x3B, 0x47, 0x85, 0x84, 0xFD, 0xAE, 0x23, 0x1A },
++		.digest	= "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F"
++			  "\x11\xA6\x72\x06\x53\x1F\xB7\xD7"
++			  "\xF0\xDF\xF5\x94\x13\x14\x5E\x69"
++			  "\x73\xC4\x50\x01\xD0\x08\x7B\x42"
++			  "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6"
++			  "\x3A\x42\x39\x1A\x39\x14\x5A\x59"
++			  "\x1A\x92\x20\x0D\x56\x01\x95\xE5"
++			  "\x3B\x47\x85\x84\xFD\xAE\x23\x1A",
+ 	}, {
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest	= { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+-			    0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+-			    0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+-			    0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C,
+-			    0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27,
+-			    0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6,
+-			    0xC7, 0x97, 0xFC, 0x9D, 0x95, 0xD8, 0xB5, 0x82,
+-			    0xD2, 0x25, 0x29, 0x20, 0x76, 0xD4, 0xEE, 0xF5 },
++		.digest	= "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB"
++			  "\x16\xB6\x56\x2C\x73\xB4\x02\x0B"
++			  "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72"
++			  "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C"
++			  "\x71\x81\xEE\xBD\xB6\xC5\x7E\x27"
++			  "\x7D\x0E\x34\x95\x71\x14\xCB\xD6"
++			  "\xC7\x97\xFC\x9D\x95\xD8\xB5\x82"
++			  "\xD2\x25\x29\x20\x76\xD4\xEE\xF5",
+ 	}, {
+ 		.plaintext = "message digest",
+ 		.psize	= 14,
+-		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+-			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+-			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+-			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
+-			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
+-			    0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6,
+-			    0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33,
+-			    0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E },
++		.digest	= "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6"
++			  "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC"
++			  "\x83\x8D\x00\x03\x22\x30\xF5\x3C"
++			  "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B"
++			  "\x84\x21\x55\x76\x59\xEF\x55\xC1"
++			  "\x06\xB4\xB5\x2A\xC5\xA4\xAA\xA6"
++			  "\x92\xED\x92\x00\x52\x83\x8F\x33"
++			  "\x62\xE8\x6D\xBD\x37\xA8\x90\x3E",
+ 	}, {
+ 		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+ 		.psize	= 26,
+-		.digest	= { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+-			    0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+-			    0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+-			    0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B,
+-			    0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A,
+-			    0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6,
+-			    0xF6, 0x8F, 0x67, 0x3E, 0x72, 0x07, 0x86, 0x5D,
+-			    0x5D, 0x98, 0x19, 0xA3, 0xDB, 0xA4, 0xEB, 0x3B },
++		.digest	= "\xF1\xD7\x54\x66\x26\x36\xFF\xE9"
++			  "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A"
++			  "\x8D\x38\x63\x1E\xAD\x42\x38\xF5"
++			  "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B"
++			  "\x08\xBF\x2A\x92\x51\xC3\x0B\x6A"
++			  "\x0B\x8A\xAE\x86\x17\x7A\xB4\xA6"
++			  "\xF6\x8F\x67\x3E\x72\x07\x86\x5D"
++			  "\x5D\x98\x19\xA3\xDB\xA4\xEB\x3B",
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+-			     "abcdefghijklmnopqrstuvwxyz0123456789",
++			   "abcdefghijklmnopqrstuvwxyz0123456789",
+ 		.psize	= 62,
+-		.digest	= { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+-			    0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+-			    0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+-			    0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E,
+-			    0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F,
+-			    0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6,
+-			    0x55, 0x17, 0xCC, 0x87, 0x9D, 0x7B, 0x96, 0x21,
+-			    0x42, 0xC6, 0x5F, 0x5A, 0x7A, 0xF0, 0x14, 0x67 },
++		.digest	= "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B"
++			  "\xF1\x1F\x00\xED\x9A\xBA\x26\x90"
++			  "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC"
++			  "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E"
++			  "\x08\xEB\xA2\x66\x29\x12\x9D\x8F"
++			  "\xB7\xCB\x57\x21\x1B\x92\x81\xA6"
++			  "\x55\x17\xCC\x87\x9D\x7B\x96\x21"
++			  "\x42\xC6\x5F\x5A\x7A\xF0\x14\x67",
+ 	}, {
+ 		.plaintext = "1234567890123456789012345678901234567890"
+-			     "1234567890123456789012345678901234567890",
++			   "1234567890123456789012345678901234567890",
+ 		.psize	= 80,
+-		.digest	= { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+-			    0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+-			    0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+-			    0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29,
+-			    0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5,
+-			    0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A,
+-			    0x2C, 0x60, 0x48, 0x1E, 0x88, 0xC5, 0xA2, 0x0B,
+-			    0x2C, 0x2A, 0x80, 0xCF, 0x3A, 0x9A, 0x08, 0x3B },
++		.digest	= "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D"
++			  "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0"
++			  "\x87\x84\x37\x2B\xCC\xB2\x04\xD6"
++			  "\x54\x9C\x4A\xFA\xDB\x60\x14\x29"
++			  "\x4D\x5B\xD8\xDF\x2A\x6C\x44\xE5"
++			  "\x38\xCD\x04\x7B\x26\x81\xA5\x1A"
++			  "\x2C\x60\x48\x1E\x88\xC5\xA2\x0B"
++			  "\x2C\x2A\x80\xCF\x3A\x9A\x08\x3B",
+ 	}, {
+ 		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+ 		.psize	= 32,
+-		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
+-			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+-			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+-			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
+-			    0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B,
+-			    0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56,
+-			    0x93, 0x9B, 0xAA, 0xA0, 0xAD, 0xFF, 0x9A, 0xE6,
+-			    0x74, 0x5B, 0x7B, 0x18, 0x1C, 0x3B, 0xE3, 0xFD },
++		.digest	= "\x2A\x98\x7E\xA4\x0F\x91\x70\x61"
++			  "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48"
++			  "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62"
++			  "\x07\xC5\x62\xF9\x88\xE9\x5C\x69"
++			  "\x16\xBD\xC8\x03\x1B\xC5\xBE\x1B"
++			  "\x7B\x94\x76\x39\xFE\x05\x0B\x56"
++			  "\x93\x9B\xAA\xA0\xAD\xFF\x9A\xE6"
++			  "\x74\x5B\x7B\x18\x1C\x3B\xE3\xFD",
+ 	},
+ };
+ 
+@@ -462,79 +459,79 @@ static struct hash_testvec wp384_tv_template[] = {
+ 	{
+ 		.plaintext = "",
+ 		.psize	= 0,
+-		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+-			    0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+-			    0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+-			    0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+-			    0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB,
+-			    0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57 },
++		.digest	= "\x19\xFA\x61\xD7\x55\x22\xA4\x66"
++			  "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26"
++			  "\xC5\x30\x23\x21\x30\xD4\x07\xF8"
++			  "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7"
++			  "\x3E\x83\xBE\x69\x8B\x28\x8F\xEB"
++			  "\xCF\x88\xE3\xE0\x3C\x4F\x07\x57",
+ 
+ 
+ 	}, {
+ 		.plaintext = "a",
+ 		.psize	= 1,
+-		.digest	= { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+-			    0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+-			    0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+-			    0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42,
+-			    0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6,
+-			    0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59 },
++		.digest	= "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F"
++			  "\x11\xA6\x72\x06\x53\x1F\xB7\xD7"
++			  "\xF0\xDF\xF5\x94\x13\x14\x5E\x69"
++			  "\x73\xC4\x50\x01\xD0\x08\x7B\x42"
++			  "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6"
++			  "\x3A\x42\x39\x1A\x39\x14\x5A\x59",
+ 	}, {
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest	= { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+-			    0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+-			    0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+-			    0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C,
+-			    0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27,
+-			    0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6 },
++		.digest	= "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB"
++			  "\x16\xB6\x56\x2C\x73\xB4\x02\x0B"
++			  "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72"
++			  "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C"
++			  "\x71\x81\xEE\xBD\xB6\xC5\x7E\x27"
++			  "\x7D\x0E\x34\x95\x71\x14\xCB\xD6",
+ 	}, {
+ 		.plaintext = "message digest",
+ 		.psize	= 14,
+-		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+-			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+-			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+-			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
+-			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
+-			    0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6 },
++		.digest	= "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6"
++			  "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC"
++			  "\x83\x8D\x00\x03\x22\x30\xF5\x3C"
++			  "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B"
++			  "\x84\x21\x55\x76\x59\xEF\x55\xC1"
++			  "\x06\xB4\xB5\x2A\xC5\xA4\xAA\xA6",
+ 	}, {
+ 		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+ 		.psize	= 26,
+-		.digest	= { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+-			    0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+-			    0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+-			    0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B,
+-			    0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A,
+-			    0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6 },
++		.digest	= "\xF1\xD7\x54\x66\x26\x36\xFF\xE9"
++			  "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A"
++			  "\x8D\x38\x63\x1E\xAD\x42\x38\xF5"
++			  "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B"
++			  "\x08\xBF\x2A\x92\x51\xC3\x0B\x6A"
++			  "\x0B\x8A\xAE\x86\x17\x7A\xB4\xA6",
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+-			     "abcdefghijklmnopqrstuvwxyz0123456789",
++			   "abcdefghijklmnopqrstuvwxyz0123456789",
+ 		.psize	= 62,
+-		.digest	= { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+-			    0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+-			    0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+-			    0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E,
+-			    0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F,
+-			    0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6 },
++		.digest	= "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B"
++			  "\xF1\x1F\x00\xED\x9A\xBA\x26\x90"
++			  "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC"
++			  "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E"
++			  "\x08\xEB\xA2\x66\x29\x12\x9D\x8F"
++			  "\xB7\xCB\x57\x21\x1B\x92\x81\xA6",
+ 	}, {
+ 		.plaintext = "1234567890123456789012345678901234567890"
+-			     "1234567890123456789012345678901234567890",
++			   "1234567890123456789012345678901234567890",
+ 		.psize	= 80,
+-		.digest	= { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+-			    0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+-			    0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+-			    0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29,
+-			    0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5,
+-			    0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A },
++		.digest	= "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D"
++			  "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0"
++			  "\x87\x84\x37\x2B\xCC\xB2\x04\xD6"
++			  "\x54\x9C\x4A\xFA\xDB\x60\x14\x29"
++			  "\x4D\x5B\xD8\xDF\x2A\x6C\x44\xE5"
++			  "\x38\xCD\x04\x7B\x26\x81\xA5\x1A",
+ 	}, {
+ 		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+ 		.psize	= 32,
+-		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
+-			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+-			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+-			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
+-			    0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B,
+-			    0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56 },
++		.digest	= "\x2A\x98\x7E\xA4\x0F\x91\x70\x61"
++			  "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48"
++			  "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62"
++			  "\x07\xC5\x62\xF9\x88\xE9\x5C\x69"
++			  "\x16\xBD\xC8\x03\x1B\xC5\xBE\x1B"
++			  "\x7B\x94\x76\x39\xFE\x05\x0B\x56",
+ 	},
+ };
+ 
+@@ -544,63 +541,63 @@ static struct hash_testvec wp256_tv_template[] = {
+ 	{
+ 		.plaintext = "",
+ 		.psize	= 0,
+-		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+-			    0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+-			    0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+-			    0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7 },
++		.digest	= "\x19\xFA\x61\xD7\x55\x22\xA4\x66"
++			  "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26"
++			  "\xC5\x30\x23\x21\x30\xD4\x07\xF8"
++			  "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7",
+ 
+ 
+ 	}, {
+ 		.plaintext = "a",
+ 		.psize	= 1,
+-		.digest	= { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+-			    0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+-			    0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+-			    0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42 },
++		.digest	= "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F"
++			  "\x11\xA6\x72\x06\x53\x1F\xB7\xD7"
++			  "\xF0\xDF\xF5\x94\x13\x14\x5E\x69"
++			  "\x73\xC4\x50\x01\xD0\x08\x7B\x42",
+ 	}, {
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest	= { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+-			    0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+-			    0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+-			    0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C },
++		.digest	= "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB"
++			  "\x16\xB6\x56\x2C\x73\xB4\x02\x0B"
++			  "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72"
++			  "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C",
+ 	}, {
+ 		.plaintext = "message digest",
+ 		.psize	= 14,
+-		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+-			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+-			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+-			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B },
++		.digest	= "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6"
++			  "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC"
++			  "\x83\x8D\x00\x03\x22\x30\xF5\x3C"
++			  "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B",
+ 	}, {
+ 		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+ 		.psize	= 26,
+-		.digest	= { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+-			    0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+-			    0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+-			    0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B },
++		.digest	= "\xF1\xD7\x54\x66\x26\x36\xFF\xE9"
++			  "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A"
++			  "\x8D\x38\x63\x1E\xAD\x42\x38\xF5"
++			  "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B",
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+-			     "abcdefghijklmnopqrstuvwxyz0123456789",
++			   "abcdefghijklmnopqrstuvwxyz0123456789",
+ 		.psize	= 62,
+-		.digest	= { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+-			    0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+-			    0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+-			    0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E },
++		.digest	= "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B"
++			  "\xF1\x1F\x00\xED\x9A\xBA\x26\x90"
++			  "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC"
++			  "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E",
+ 	}, {
+ 		.plaintext = "1234567890123456789012345678901234567890"
+-			     "1234567890123456789012345678901234567890",
++			   "1234567890123456789012345678901234567890",
+ 		.psize	= 80,
+-		.digest	= { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+-			    0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+-			    0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+-			    0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29 },
++		.digest	= "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D"
++			  "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0"
++			  "\x87\x84\x37\x2B\xCC\xB2\x04\xD6"
++			  "\x54\x9C\x4A\xFA\xDB\x60\x14\x29",
+ 	}, {
+ 		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+ 		.psize	= 32,
+-		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
+-			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+-			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+-			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69 },
++		.digest	= "\x2A\x98\x7E\xA4\x0F\x91\x70\x61"
++			  "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48"
++			  "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62"
++			  "\x07\xC5\x62\xF9\x88\xE9\x5C\x69",
+ 	},
+ };
+ 
+@@ -613,42 +610,42 @@ static struct hash_testvec tgr192_tv_template[] = {
+ 	{
+ 		.plaintext = "",
+ 		.psize	= 0,
+-		.digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+-			    0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f,
+-			    0xf3, 0x73, 0xde, 0x2d, 0x49, 0x58, 0x4e, 0x7a },
++		.digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32"
++			  "\x16\x16\x6e\x76\xb1\xbb\x92\x5f"
++			  "\xf3\x73\xde\x2d\x49\x58\x4e\x7a",
+ 	}, {
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+-			    0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf,
+-			    0x93, 0x5f, 0x7b, 0x95, 0x1c, 0x13, 0x29, 0x51 },
++		.digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a"
++			  "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf"
++			  "\x93\x5f\x7b\x95\x1c\x13\x29\x51",
+ 	}, {
+ 		.plaintext = "Tiger",
+ 		.psize	= 5,
+-		.digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+-			    0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec,
+-			    0x37, 0x79, 0x0c, 0x11, 0x6f, 0x9d, 0x2b, 0xdf },
++		.digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd"
++			  "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec"
++			  "\x37\x79\x0c\x11\x6f\x9d\x2b\xdf",
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ 		.psize	= 64,
+-		.digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+-			    0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e,
+-			    0xb5, 0x86, 0x44, 0x50, 0x34, 0xa5, 0xa3, 0x86 },
++		.digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7"
++			  "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e"
++			  "\xb5\x86\x44\x50\x34\xa5\xa3\x86",
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ 		.psize	= 64,
+-		.digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+-			    0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9,
+-			    0x57, 0x89, 0x65, 0x65, 0x97, 0x5f, 0x91, 0x97 },
++		.digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48"
++			  "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9"
++			  "\x57\x89\x65\x65\x97\x5f\x91\x97",
+ 	}, {
+ 		.plaintext = "Tiger - A Fast New Hash Function, "
+-			     "by Ross Anderson and Eli Biham, "
+-			     "proceedings of Fast Software Encryption 3, "
+-			     "Cambridge, 1996.",
++			   "by Ross Anderson and Eli Biham, "
++			   "proceedings of Fast Software Encryption 3, "
++			   "Cambridge, 1996.",
+ 		.psize  = 125,
+-		.digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+-			    0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24,
+-			    0xdd, 0x68, 0x15, 0x1d, 0x50, 0x39, 0x74, 0xfc },
++		.digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63"
++			  "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24"
++			  "\xdd\x68\x15\x1d\x50\x39\x74\xfc",
+ 	},
+ };
+ 
+@@ -658,42 +655,42 @@ static struct hash_testvec tgr160_tv_template[] = {
+ 	{
+ 		.plaintext = "",
+ 		.psize	= 0,
+-		.digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+-			    0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f,
+-			    0xf3, 0x73, 0xde, 0x2d },
++		.digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32"
++			  "\x16\x16\x6e\x76\xb1\xbb\x92\x5f"
++			  "\xf3\x73\xde\x2d",
+ 	}, {
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+-			    0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf,
+-			    0x93, 0x5f, 0x7b, 0x95 },
++		.digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a"
++			  "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf"
++			  "\x93\x5f\x7b\x95",
+ 	}, {
+ 		.plaintext = "Tiger",
+ 		.psize	= 5,
+-		.digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+-			    0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec,
+-			    0x37, 0x79, 0x0c, 0x11 },
++		.digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd"
++			  "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec"
++			  "\x37\x79\x0c\x11",
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ 		.psize	= 64,
+-		.digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+-			    0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e,
+-			    0xb5, 0x86, 0x44, 0x50 },
++		.digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7"
++			  "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e"
++			  "\xb5\x86\x44\x50",
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ 		.psize	= 64,
+-		.digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+-			    0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9,
+-			    0x57, 0x89, 0x65, 0x65 },
++		.digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48"
++			  "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9"
++			  "\x57\x89\x65\x65",
+ 	}, {
+ 		.plaintext = "Tiger - A Fast New Hash Function, "
+-			     "by Ross Anderson and Eli Biham, "
+-			     "proceedings of Fast Software Encryption 3, "
+-			     "Cambridge, 1996.",
++			   "by Ross Anderson and Eli Biham, "
++			   "proceedings of Fast Software Encryption 3, "
++			   "Cambridge, 1996.",
+ 		.psize  = 125,
+-		.digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+-			    0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24,
+-			    0xdd, 0x68, 0x15, 0x1d },
++		.digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63"
++			  "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24"
++			  "\xdd\x68\x15\x1d",
+ 	},
+ };
+ 
+@@ -703,36 +700,36 @@ static struct hash_testvec tgr128_tv_template[] = {
+ 	{
+ 		.plaintext = "",
+ 		.psize	= 0,
+-		.digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+-			    0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f },
++		.digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32"
++			  "\x16\x16\x6e\x76\xb1\xbb\x92\x5f",
+ 	}, {
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+-			    0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf },
++		.digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a"
++			  "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf",
+ 	}, {
+ 		.plaintext = "Tiger",
+ 		.psize	= 5,
+-		.digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+-			    0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec },
++		.digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd"
++			  "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec",
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ 		.psize	= 64,
+-		.digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+-			    0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e },
++		.digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7"
++			  "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e",
+ 	}, {
+ 		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ 		.psize	= 64,
+-		.digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+-			    0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9 },
++		.digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48"
++			  "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9",
+ 	}, {
+ 		.plaintext = "Tiger - A Fast New Hash Function, "
+-			     "by Ross Anderson and Eli Biham, "
+-			     "proceedings of Fast Software Encryption 3, "
+-			     "Cambridge, 1996.",
++			   "by Ross Anderson and Eli Biham, "
++			   "proceedings of Fast Software Encryption 3, "
++			   "Cambridge, 1996.",
+ 		.psize  = 125,
+-		.digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+-			    0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24 },
++		.digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63"
++			  "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24",
+ 	},
+ };
+ 
+@@ -745,59 +742,77 @@ static struct hash_testvec tgr128_tv_template[] = {
+ static struct hash_testvec hmac_md5_tv_template[] =
+ {
+ 	{
+-		.key	= { [0 ... 15] =  0x0b },
++		.key	= "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ 		.ksize	= 16,
+ 		.plaintext = "Hi There",
+ 		.psize	= 8,
+-		.digest	= { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
+-			    0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d },
++		.digest	= "\x92\x94\x72\x7a\x36\x38\xbb\x1c"
++			  "\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d",
+ 	}, {
+-		.key	= { 'J', 'e', 'f', 'e' },
++		.key	= "Jefe",
+ 		.ksize	= 4,
+ 		.plaintext = "what do ya want for nothing?",
+ 		.psize	= 28,
+-		.digest	= { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
+-			    0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 },
++		.digest	= "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03"
++			  "\xea\xa8\x6e\x31\x0a\x5d\xb7\x38",
+ 		.np	= 2,
+ 		.tap	= {14, 14}
+ 	}, {
+-		.key	= { [0 ... 15] = 0xaa },
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ 		.ksize	= 16,
+-		.plaintext = { [0 ... 49] =  0xdd },
++		.plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+ 		.psize	= 50,
+-		.digest	= { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
+-			    0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 },
++		.digest	= "\x56\xbe\x34\x52\x1d\x14\x4c\x88"
++			  "\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6",
+ 	}, {
+-		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+-			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+-			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, },
++		.key	= "\x01\x02\x03\x04\x05\x06\x07\x08"
++			  "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++			  "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+ 		.ksize	= 25,
+-		.plaintext = { [0 ... 49] =  0xcd },
++		.plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+ 		.psize	= 50,
+-		.digest	= { 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea,
+-			    0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 },
++		.digest	= "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea"
++			  "\x3a\x75\x16\x47\x46\xff\xaa\x79",
+ 	}, {
+-		.key	= { [0 ... 15] = 0x0c },
++		.key	= "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
+ 		.ksize	= 16,
+ 		.plaintext = "Test With Truncation",
+ 		.psize	= 20,
+-		.digest	= { 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00,
+-			    0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c },
+-	}, {
+-		.key	= { [0 ... 79] =  0xaa },
++		.digest	= "\x56\x46\x1e\xf2\x34\x2e\xdc\x00"
++			  "\xf9\xba\xb9\x95\x69\x0e\xfd\x4c",
++	}, {
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa",
+ 		.ksize	= 80,
+ 		.plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
+ 		.psize	= 54,
+-		.digest	= { 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f,
+-			    0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd },
+-	}, {
+-		.key	= { [0 ... 79] =  0xaa },
++		.digest	= "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f"
++			  "\x0b\x62\xe6\xce\x61\xb9\xd0\xcd",
++	}, {
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa",
+ 		.ksize	= 80,
+ 		.plaintext = "Test Using Larger Than Block-Size Key and Larger Than One "
+-			     "Block-Size Data",
++			   "Block-Size Data",
+ 		.psize	= 73,
+-		.digest	= { 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
+-			    0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e },
++		.digest	= "\x6f\x63\x0f\xad\x67\xcd\xa0\xee"
++			  "\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e",
+ 	},
+ };
+ 
+@@ -808,60 +823,78 @@ static struct hash_testvec hmac_md5_tv_template[] =
+ 
+ static struct hash_testvec hmac_sha1_tv_template[] = {
+ 	{
+-		.key	= { [0 ... 19] = 0x0b },
++		.key	= "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ 		.ksize	= 20,
+ 		.plaintext = "Hi There",
+ 		.psize	= 8,
+-		.digest	= { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
+-			    0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1,
+-			    0x46, 0xbe },
++		.digest	= "\xb6\x17\x31\x86\x55\x05\x72\x64"
++			  "\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1"
++			  "\x46\xbe",
+ 	}, {
+-		.key	= { 'J', 'e', 'f', 'e' },
++		.key	= "Jefe",
+ 		.ksize	= 4,
+ 		.plaintext = "what do ya want for nothing?",
+ 		.psize	= 28,
+-		.digest	= { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74,
+-			    0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 },
++		.digest	= "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74"
++			  "\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79",
+ 		.np	= 2,
+ 		.tap	= { 14, 14 }
+ 	}, {
+-		.key	= { [0 ... 19] = 0xaa },
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ 		.ksize	= 20,
+-		.plaintext = { [0 ... 49] = 0xdd },
++		.plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+ 		.psize	= 50,
+-		.digest	= { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3,
+-			    0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 },
++		.digest	= "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3"
++			  "\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3",
+ 	}, {
+-		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+-			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+-			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 },
++		.key	= "\x01\x02\x03\x04\x05\x06\x07\x08"
++			  "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++			  "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+ 		.ksize	= 25,
+-		.plaintext = { [0 ... 49] = 0xcd },
++		.plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+ 		.psize	= 50,
+-		.digest	= { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84,
+-			    0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda },
++		.digest	= "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84"
++			  "\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda",
+ 	}, {
+-		.key	= { [0 ... 19] = 0x0c },
++		.key	= "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
+ 		.ksize	= 20,
+ 		.plaintext = "Test With Truncation",
+ 		.psize	= 20,
+-		.digest	= { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
+-			    0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 },
+-	}, {
+-		.key	= { [0 ... 79] = 0xaa },
++		.digest	= "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2"
++			  "\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04",
++	}, {
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa",
+ 		.ksize	= 80,
+ 		.plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
+ 		.psize	= 54,
+-		.digest	= { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70,
+-			    0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 },
+-	}, {
+-		.key	= { [0 ... 79] = 0xaa },
++		.digest	= "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70"
++			  "\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12",
++	}, {
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa",
+ 		.ksize	= 80,
+ 		.plaintext = "Test Using Larger Than Block-Size Key and Larger Than One "
+-			     "Block-Size Data",
++			   "Block-Size Data",
+ 		.psize	= 73,
+-		.digest	= { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b,
+-			    0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 },
++		.digest	= "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b"
++			  "\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91",
+ 	},
+ };
+ 
+@@ -873,110 +906,110 @@ static struct hash_testvec hmac_sha1_tv_template[] = {
+ 
+ static struct hash_testvec hmac_sha224_tv_template[] = {
+ 	{
+-		.key    = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+-			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+-			0x0b, 0x0b, 0x0b, 0x0b },
++		.key    = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++			"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++			"\x0b\x0b\x0b\x0b",
+ 		.ksize  = 20,
+ 		/*  ("Hi There") */
+-		.plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 },
++		.plaintext = "\x48\x69\x20\x54\x68\x65\x72\x65",
+ 		.psize  = 8,
+-		.digest = { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19,
+-			0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f,
+-			0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f,
+-			0x53, 0x68, 0x4b, 0x22},
++		.digest = "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19"
++			"\x68\x32\x10\x7c\xd4\x9d\xf3\x3f"
++			"\x47\xb4\xb1\x16\x99\x12\xba\x4f"
++			"\x53\x68\x4b\x22",
+ 	}, {
+-		.key    = { 0x4a, 0x65, 0x66, 0x65 }, /* ("Jefe") */
++		.key    = "Jefe",
+ 		.ksize  = 4,
+ 		/* ("what do ya want for nothing?") */
+-		.plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+-			0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
+-			0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+-			0x69, 0x6e, 0x67, 0x3f },
++		.plaintext = "\x77\x68\x61\x74\x20\x64\x6f\x20"
++			"\x79\x61\x20\x77\x61\x6e\x74\x20"
++			"\x66\x6f\x72\x20\x6e\x6f\x74\x68"
++			"\x69\x6e\x67\x3f",
+ 		.psize  = 28,
+-		.digest = { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf,
+-			0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
+-			0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00,
+-			0x8f, 0xd0, 0x5e, 0x44 },
++		.digest = "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf"
++			"\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f"
++			"\x8b\xbe\xa2\xa3\x9e\x61\x48\x00"
++			"\x8f\xd0\x5e\x44",
+ 		.np = 4,
+ 		.tap    = { 7, 7, 7, 7 }
+ 	}, {
+-		.key    = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa },
++		.key    = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa",
+ 		.ksize  = 131,
+ 		/* ("Test Using Larger Than Block-Size Key - Hash Key First") */
+-		.plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+-			0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
+-			0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+-			0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
+-			0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+-			0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
+-			0x20, 0x46, 0x69, 0x72, 0x73, 0x74 },
++		.plaintext = "\x54\x65\x73\x74\x20\x55\x73\x69"
++			"\x6e\x67\x20\x4c\x61\x72\x67\x65"
++			"\x72\x20\x54\x68\x61\x6e\x20\x42"
++			"\x6c\x6f\x63\x6b\x2d\x53\x69\x7a"
++			"\x65\x20\x4b\x65\x79\x20\x2d\x20"
++			"\x48\x61\x73\x68\x20\x4b\x65\x79"
++			"\x20\x46\x69\x72\x73\x74",
+ 		.psize  = 54,
+-		.digest = { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad,
+-			0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
+-			0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27,
+-			0x3f, 0xa6, 0x87, 0x0e },
+-	}, {
+-		.key    = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			0xaa, 0xaa, 0xaa },
++		.digest = "\x95\xe9\xa0\xdb\x96\x20\x95\xad"
++			"\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2"
++			"\xd4\x99\xf1\x12\xf2\xd2\xb7\x27"
++			"\x3f\xa6\x87\x0e",
++	}, {
++		.key    = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa",
+ 		.ksize  = 131,
+ 		/* ("This is a test using a larger than block-size key and a")
+ 		(" larger than block-size data. The key needs to be")
+ 			(" hashed before being used by the HMAC algorithm.") */
+-		.plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+-			0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75,
+-			0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+-			0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68,
+-			0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+-			0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
+-			0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+-			0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74,
+-			0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+-			0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64,
+-			0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+-			0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
+-			0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+-			0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20,
+-			0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+-			0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65,
+-			0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+-			0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
+-			0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e },
++		.plaintext = "\x54\x68\x69\x73\x20\x69\x73\x20"
++			"\x61\x20\x74\x65\x73\x74\x20\x75"
++			"\x73\x69\x6e\x67\x20\x61\x20\x6c"
++			"\x61\x72\x67\x65\x72\x20\x74\x68"
++			"\x61\x6e\x20\x62\x6c\x6f\x63\x6b"
++			"\x2d\x73\x69\x7a\x65\x20\x6b\x65"
++			"\x79\x20\x61\x6e\x64\x20\x61\x20"
++			"\x6c\x61\x72\x67\x65\x72\x20\x74"
++			"\x68\x61\x6e\x20\x62\x6c\x6f\x63"
++			"\x6b\x2d\x73\x69\x7a\x65\x20\x64"
++			"\x61\x74\x61\x2e\x20\x54\x68\x65"
++			"\x20\x6b\x65\x79\x20\x6e\x65\x65"
++			"\x64\x73\x20\x74\x6f\x20\x62\x65"
++			"\x20\x68\x61\x73\x68\x65\x64\x20"
++			"\x62\x65\x66\x6f\x72\x65\x20\x62"
++			"\x65\x69\x6e\x67\x20\x75\x73\x65"
++			"\x64\x20\x62\x79\x20\x74\x68\x65"
++			"\x20\x48\x4d\x41\x43\x20\x61\x6c"
++			"\x67\x6f\x72\x69\x74\x68\x6d\x2e",
+ 		.psize  = 152,
+-		.digest = { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02,
+-			0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd,
+-			0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9,
+-			0xf6, 0xf5, 0x65, 0xd1 },
++		.digest = "\x3a\x85\x41\x66\xac\x5d\x9f\x02"
++			"\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd"
++			"\x94\x67\x70\xdb\x9c\x2b\x95\xc9"
++			"\xf6\xf5\x65\xd1",
+ 	},
+ };
+ 
+@@ -988,112 +1021,136 @@ static struct hash_testvec hmac_sha224_tv_template[] = {
+ 
+ static struct hash_testvec hmac_sha256_tv_template[] = {
+ 	{
+-		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+-			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+-			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+-			    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20},
++		.key	= "\x01\x02\x03\x04\x05\x06\x07\x08"
++			  "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++			  "\x11\x12\x13\x14\x15\x16\x17\x18"
++			  "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20",
+ 		.ksize	= 32,
+ 		.plaintext = "abc",
+ 		.psize	= 3,
+-		.digest	= { 0xa2, 0x1b, 0x1f, 0x5d, 0x4c, 0xf4, 0xf7, 0x3a,
+-			    0x4d, 0xd9, 0x39, 0x75, 0x0f, 0x7a, 0x06, 0x6a,
+-			    0x7f, 0x98, 0xcc, 0x13, 0x1c, 0xb1, 0x6a, 0x66,
+-			    0x92, 0x75, 0x90, 0x21, 0xcf, 0xab, 0x81, 0x81 },
+-	}, {
+-		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+-			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+-			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+-			    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 },
++		.digest	= "\xa2\x1b\x1f\x5d\x4c\xf4\xf7\x3a"
++			  "\x4d\xd9\x39\x75\x0f\x7a\x06\x6a"
++			  "\x7f\x98\xcc\x13\x1c\xb1\x6a\x66"
++			  "\x92\x75\x90\x21\xcf\xab\x81\x81",
++	}, {
++		.key	= "\x01\x02\x03\x04\x05\x06\x07\x08"
++			  "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++			  "\x11\x12\x13\x14\x15\x16\x17\x18"
++			  "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20",
+ 		.ksize	= 32,
+ 		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ 		.psize	= 56,
+-		.digest	= { 0x10, 0x4f, 0xdc, 0x12, 0x57, 0x32, 0x8f, 0x08,
+-			    0x18, 0x4b, 0xa7, 0x31, 0x31, 0xc5, 0x3c, 0xae,
+-			    0xe6, 0x98, 0xe3, 0x61, 0x19, 0x42, 0x11, 0x49,
+-			    0xea, 0x8c, 0x71, 0x24, 0x56, 0x69, 0x7d, 0x30 },
+-	}, {
+-		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+-			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+-			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+-			    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 },
++		.digest	= "\x10\x4f\xdc\x12\x57\x32\x8f\x08"
++			  "\x18\x4b\xa7\x31\x31\xc5\x3c\xae"
++			  "\xe6\x98\xe3\x61\x19\x42\x11\x49"
++			  "\xea\x8c\x71\x24\x56\x69\x7d\x30",
++	}, {
++		.key	= "\x01\x02\x03\x04\x05\x06\x07\x08"
++			  "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++			  "\x11\x12\x13\x14\x15\x16\x17\x18"
++			  "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20",
+ 		.ksize	= 32,
+ 		.plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+-			     "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
++			   "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ 		.psize	= 112,
+-		.digest	= { 0x47, 0x03, 0x05, 0xfc, 0x7e, 0x40, 0xfe, 0x34,
+-			    0xd3, 0xee, 0xb3, 0xe7, 0x73, 0xd9, 0x5a, 0xab,
+-			    0x73, 0xac, 0xf0, 0xfd, 0x06, 0x04, 0x47, 0xa5,
+-			    0xeb, 0x45, 0x95, 0xbf, 0x33, 0xa9, 0xd1, 0xa3 },
+-	}, {
+-		.key	= { [0 ... 31] = 0x0b },
++		.digest	= "\x47\x03\x05\xfc\x7e\x40\xfe\x34"
++			  "\xd3\xee\xb3\xe7\x73\xd9\x5a\xab"
++			  "\x73\xac\xf0\xfd\x06\x04\x47\xa5"
++			  "\xeb\x45\x95\xbf\x33\xa9\xd1\xa3",
++	}, {
++		.key	= "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++			"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++			"\x0b\x0b\x0b\x0b\x0b\x0b",
+ 		.ksize	= 32,
+ 		.plaintext = "Hi There",
+ 		.psize	= 8,
+-		.digest	= { 0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6,
+-			    0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5,
+-			    0xba, 0x0a, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c,
+-			    0x7a, 0x3b, 0x16, 0x96, 0xa0, 0xb6, 0x8c, 0xf7 },
++		.digest	= "\x19\x8a\x60\x7e\xb4\x4b\xfb\xc6"
++			  "\x99\x03\xa0\xf1\xcf\x2b\xbd\xc5"
++			  "\xba\x0a\xa3\xf3\xd9\xae\x3c\x1c"
++			  "\x7a\x3b\x16\x96\xa0\xb6\x8c\xf7",
+ 	}, {
+ 		.key	= "Jefe",
+ 		.ksize	= 4,
+ 		.plaintext = "what do ya want for nothing?",
+ 		.psize	= 28,
+-		.digest	= { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
+-			    0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
+-			    0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
+-			    0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 },
++		.digest	= "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e"
++			  "\x6a\x04\x24\x26\x08\x95\x75\xc7"
++			  "\x5a\x00\x3f\x08\x9d\x27\x39\x83"
++			  "\x9d\xec\x58\xb9\x64\xec\x38\x43",
+ 		.np	= 2,
+ 		.tap	= { 14, 14 }
+ 	}, {
+-		.key	= { [0 ... 31] = 0xaa },
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ 		.ksize	= 32,
+-		.plaintext = { [0 ... 49] = 0xdd },
++		.plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++			"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+ 		.psize	= 50,
+-		.digest	= { 0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea,
+-			    0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62,
+-			    0xe5, 0x49, 0xfe, 0x6c, 0xe9, 0xed, 0x7f, 0xdc,
+-			    0x43, 0x19, 0x1f, 0xbd, 0xe4, 0x5c, 0x30, 0xb0 },
+-	}, {
+-		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+-			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+-			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+-			    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+-			    0x21, 0x22, 0x23, 0x24, 0x25 },
++		.digest	= "\xcd\xcb\x12\x20\xd1\xec\xcc\xea"
++			  "\x91\xe5\x3a\xba\x30\x92\xf9\x62"
++			  "\xe5\x49\xfe\x6c\xe9\xed\x7f\xdc"
++			  "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0",
++	}, {
++		.key	= "\x01\x02\x03\x04\x05\x06\x07\x08"
++			  "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++			  "\x11\x12\x13\x14\x15\x16\x17\x18"
++			  "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
++			  "\x21\x22\x23\x24\x25",
+ 		.ksize	= 37,
+-		.plaintext = { [0 ... 49] = 0xcd },
++		.plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++			"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+ 		.psize	= 50,
+-		.digest	= { 0xd4, 0x63, 0x3c, 0x17, 0xf6, 0xfb, 0x8d, 0x74,
+-			    0x4c, 0x66, 0xde, 0xe0, 0xf8, 0xf0, 0x74, 0x55,
+-			    0x6e, 0xc4, 0xaf, 0x55, 0xef, 0x07, 0x99, 0x85,
+-			    0x41, 0x46, 0x8e, 0xb4, 0x9b, 0xd2, 0xe9, 0x17 },
+-	}, {
+-		.key	= { [0 ... 31] = 0x0c },
++		.digest	= "\xd4\x63\x3c\x17\xf6\xfb\x8d\x74"
++			  "\x4c\x66\xde\xe0\xf8\xf0\x74\x55"
++			  "\x6e\xc4\xaf\x55\xef\x07\x99\x85"
++			  "\x41\x46\x8e\xb4\x9b\xd2\xe9\x17",
++	}, {
++		.key	= "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
++			"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
++			"\x0c\x0c\x0c\x0c\x0c\x0c",
+ 		.ksize	= 32,
+ 		.plaintext = "Test With Truncation",
+ 		.psize	= 20,
+-		.digest	= { 0x75, 0x46, 0xaf, 0x01, 0x84, 0x1f, 0xc0, 0x9b,
+-			    0x1a, 0xb9, 0xc3, 0x74, 0x9a, 0x5f, 0x1c, 0x17,
+-			    0xd4, 0xf5, 0x89, 0x66, 0x8a, 0x58, 0x7b, 0x27,
+-			    0x00, 0xa9, 0xc9, 0x7c, 0x11, 0x93, 0xcf, 0x42 },
+-	}, {
+-		.key	= { [0 ... 79] = 0xaa },
++		.digest	= "\x75\x46\xaf\x01\x84\x1f\xc0\x9b"
++			  "\x1a\xb9\xc3\x74\x9a\x5f\x1c\x17"
++			  "\xd4\xf5\x89\x66\x8a\x58\x7b\x27"
++			  "\x00\xa9\xc9\x7c\x11\x93\xcf\x42",
++	}, {
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa",
+ 		.ksize	= 80,
+ 		.plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
+ 		.psize	= 54,
+-		.digest	= { 0x69, 0x53, 0x02, 0x5e, 0xd9, 0x6f, 0x0c, 0x09,
+-			    0xf8, 0x0a, 0x96, 0xf7, 0x8e, 0x65, 0x38, 0xdb,
+-			    0xe2, 0xe7, 0xb8, 0x20, 0xe3, 0xdd, 0x97, 0x0e,
+-			    0x7d, 0xdd, 0x39, 0x09, 0x1b, 0x32, 0x35, 0x2f },
+-	}, {
+-		.key	= { [0 ... 79] = 0xaa },
++		.digest	= "\x69\x53\x02\x5e\xd9\x6f\x0c\x09"
++			  "\xf8\x0a\x96\xf7\x8e\x65\x38\xdb"
++			  "\xe2\xe7\xb8\x20\xe3\xdd\x97\x0e"
++			  "\x7d\xdd\x39\x09\x1b\x32\x35\x2f",
++	}, {
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa",
+ 		.ksize	= 80,
+ 		.plaintext = "Test Using Larger Than Block-Size Key and Larger Than "
+-			     "One Block-Size Data",
++			   "One Block-Size Data",
+ 		.psize	= 73,
+-		.digest	= { 0x63, 0x55, 0xac, 0x22, 0xe8, 0x90, 0xd0, 0xa3,
+-			    0xc8, 0x48, 0x1a, 0x5c, 0xa4, 0x82, 0x5b, 0xc8,
+-			    0x84, 0xd3, 0xe7, 0xa1, 0xff, 0x98, 0xa2, 0xfc,
+-			    0x2a, 0xc7, 0xd8, 0xe0, 0x64, 0xc3, 0xb2, 0xe6 },
++		.digest	= "\x63\x55\xac\x22\xe8\x90\xd0\xa3"
++			  "\xc8\x48\x1a\x5c\xa4\x82\x5b\xc8"
++			  "\x84\xd3\xe7\xa1\xff\x98\xa2\xfc"
++			  "\x2a\xc7\xd8\xe0\x64\xc3\xb2\xe6",
+ 	},
+ };
+ 
+@@ -1101,63 +1158,63 @@ static struct hash_testvec hmac_sha256_tv_template[] = {
+ 
+ static struct hash_testvec aes_xcbc128_tv_template[] = {
+ 	{
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.plaintext = { [0 ... 15] = 0 },
+-		.digest = { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c,
+-			    0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.plaintext = zeroed_string,
++		.digest = "\x75\xf0\x25\x1d\x52\x8a\xc0\x1c"
++			  "\x45\x73\xdf\xd5\x84\xd7\x9f\x29",
+ 		.psize	= 0,
+ 		.ksize	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.plaintext = { 0x00, 0x01, 0x02 },
+-		.digest	= { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf,
+-			    0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.plaintext = "\x00\x01\x02",
++		.digest	= "\x5b\x37\x65\x80\xae\x2f\x19\xaf"
++			  "\xe7\x21\x9c\xee\xf1\x72\x75\x6f",
+ 		.psize	= 3,
+ 		.ksize	= 16,
+ 	} , {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.digest = { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7,
+-			    0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			     "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.digest = "\xd2\xa2\x46\xfa\x34\x9b\x68\xa7"
++			  "\x99\x98\xa4\x39\x4f\xf7\xa2\x63",
+ 		.psize	= 16,
+ 		.ksize	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			       0x10, 0x11, 0x12, 0x13 },
+-		.digest = { 0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15,
+-			    0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08 },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			     "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			     "\x10\x11\x12\x13",
++		.digest = "\x47\xf5\x1b\x45\x64\x96\x62\x15"
++			  "\xb8\x98\x5c\x63\x05\x5e\xd3\x08",
+ 		.tap	= { 10, 10 },
+ 		.psize	= 20,
+ 		.np	= 2,
+ 		.ksize	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+-		.digest = { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3,
+-			    0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			     "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			     "\x10\x11\x12\x13\x14\x15\x16\x17"
++			     "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
++		.digest = "\xf5\x4f\x0e\xc8\xd2\xb9\xf3\xd3"
++			  "\x68\x07\x73\x4b\xd5\x28\x3f\xd4",
+ 		.psize	= 32,
+ 		.ksize	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			       0x20, 0x21 },
+-		.digest = { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3,
+-			    0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			     "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			     "\x10\x11\x12\x13\x14\x15\x16\x17"
++			     "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			     "\x20\x21",
++		.digest = "\xbe\xcb\xb3\xbc\xcd\xb5\x18\xa3"
++			  "\x06\x77\xd5\x48\x1f\xb6\xb4\xd8",
+ 		.tap	= { 17, 17 },
+ 		.psize	= 34,
+ 		.np	= 2,
+@@ -1173,112 +1230,95 @@ static struct hash_testvec aes_xcbc128_tv_template[] = {
+ 
+ static struct hash_testvec hmac_sha384_tv_template[] = {
+ 	{
+-		.key	= { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+-			    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+-			    0x0b, 0x0b, 0x0b, 0x0b }, // (20 bytes)
++		.key	= "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++			  "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++			  "\x0b\x0b\x0b\x0b",
+ 		.ksize	= 20,
+-		.plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 }, // ("Hi There")
++		.plaintext = "Hi There",
+ 		.psize	= 8,
+-		.digest	= { 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62,
+-			    0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f,
+-			    0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
+-			    0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
+-			    0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f,
+-			    0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6 },
+-	}, {
+-		.key	= { 0x4a, 0x65, 0x66, 0x65 }, // ("Jefe")
++		.digest	= "\xaf\xd0\x39\x44\xd8\x48\x95\x62"
++			  "\x6b\x08\x25\xf4\xab\x46\x90\x7f"
++			  "\x15\xf9\xda\xdb\xe4\x10\x1e\xc6"
++			  "\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c"
++			  "\xfa\xea\x9e\xa9\x07\x6e\xde\x7f"
++			  "\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6",
++	}, {
++		.key	= "Jefe",
+ 		.ksize	= 4,
+-		.plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+-			       0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, // ("what do ya want ")
+-			       0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+-			       0x69, 0x6e, 0x67, 0x3f }, // ("for nothing?")
++		.plaintext = "what do ya want for nothing?",
+ 		.psize	= 28,
+-		.digest	= { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31,
+-			    0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
+-			    0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
+-			    0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
+-			    0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7,
+-			    0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49 },
++		.digest	= "\xaf\x45\xd2\xe3\x76\x48\x40\x31"
++			  "\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b"
++			  "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47"
++			  "\xe4\x2e\xc3\x73\x63\x22\x44\x5e"
++			  "\x8e\x22\x40\xca\x5e\x69\xe2\xc7"
++			  "\x8b\x32\x39\xec\xfa\xb2\x16\x49",
+ 		.np	= 4,
+ 		.tap	= { 7, 7, 7, 7 }
+ 	}, {
+-		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa }, // (131 bytes)
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa",
+ 		.ksize	= 131,
+-		.plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+-			       0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, // ("Test Using Large")
+-			       0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+-			       0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, // ("r Than Block-Siz")
+-			       0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+-			       0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, // ("e Key - Hash Key")
+-			       0x20, 0x46, 0x69, 0x72, 0x73, 0x74 }, // (" First")
++		.plaintext = "Test Using Larger Than Block-Siz"
++			   "e Key - Hash Key First",
+ 		.psize	= 54,
+-		.digest	= { 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90,
+-			    0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
+-			    0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
+-			    0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
+-			    0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82,
+-			    0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52 },
+-	}, {
+-		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa }, // (131 bytes)
++		.digest	= "\x4e\xce\x08\x44\x85\x81\x3e\x90"
++			  "\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4"
++			  "\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f"
++			  "\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6"
++			  "\x0c\x2e\xf6\xab\x40\x30\xfe\x82"
++			  "\x96\x24\x8d\xf1\x63\xf4\x49\x52",
++	}, {
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa",
+ 		.ksize	= 131,
+-		.plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+-			       0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, // ("This is a test u")
+-			       0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+-			       0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, // ("sing a larger th")
+-			       0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+-			       0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65, // ("an block-size ke")
+-			       0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+-			       0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, // ("y and a larger t")
+-			       0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+-			       0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, // ("han block-size d")
+-			       0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+-			       0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65, // ("ata. The key nee")
+-			       0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+-			       0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, // ("ds to be hashed ")
+-			       0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+-			       0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, // ("before being use")
+-			       0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+-			       0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c, // ("d by the HMAC al")
+-			       0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e }, // ("gorithm.")
++		.plaintext = "This is a test u"
++			   "sing a larger th"
++			   "an block-size ke"
++			   "y and a larger t"
++			   "han block-size d"
++			   "ata. The key nee"
++			   "ds to be hashed "
++			   "before being use"
++			   "d by the HMAC al"
++			   "gorithm.",
+ 		.psize	= 152,
+-		.digest	= { 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d,
+-			    0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c,
+-			    0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
+-			    0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5,
+-			    0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d,
+-			    0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e },
++		.digest	= "\x66\x17\x17\x8e\x94\x1f\x02\x0d"
++			  "\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c"
++			  "\x60\x24\x20\xfe\xb0\xb8\xfb\x9a"
++			  "\xdc\xce\xbb\x82\x46\x1e\x99\xc5"
++			  "\xa6\x78\xcc\x31\xe7\x99\x17\x6d"
++			  "\x38\x60\xe6\x11\x0c\x46\x52\x3e",
+ 	},
+ };
+ 
+@@ -1290,120 +1330,106 @@ static struct hash_testvec hmac_sha384_tv_template[] = {
+ 
+ static struct hash_testvec hmac_sha512_tv_template[] = {
+ 	{
+-		.key	= { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+-			    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+-			    0x0b, 0x0b, 0x0b, 0x0b }, // (20 bytes)
++		.key	= "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++			  "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++			  "\x0b\x0b\x0b\x0b",
+ 		.ksize	= 20,
+-		.plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 }, // ("Hi There")
++		.plaintext = "Hi There",
+ 		.psize	= 8,
+-		.digest	= { 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
+-			    0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
+-			    0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
+-			    0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
+-			    0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02,
+-			    0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
+-			    0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70,
+-			    0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54 },
+-	}, {
+-		.key	= { 0x4a, 0x65, 0x66, 0x65 }, // ("Jefe")
++		.digest	= "\x87\xaa\x7c\xde\xa5\xef\x61\x9d"
++			  "\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0"
++			  "\x23\x79\xf4\xe2\xce\x4e\xc2\x78"
++			  "\x7a\xd0\xb3\x05\x45\xe1\x7c\xde"
++			  "\xda\xa8\x33\xb7\xd6\xb8\xa7\x02"
++			  "\x03\x8b\x27\x4e\xae\xa3\xf4\xe4"
++			  "\xbe\x9d\x91\x4e\xeb\x61\xf1\x70"
++			  "\x2e\x69\x6c\x20\x3a\x12\x68\x54",
++	}, {
++		.key	= "Jefe",
+ 		.ksize	= 4,
+-		.plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+-			       0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, // ("what do ya want ")
+-			       0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+-			       0x69, 0x6e, 0x67, 0x3f }, // ("for nothing?")
++		.plaintext = "what do ya want for nothing?",
+ 		.psize	= 28,
+-		.digest	= { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
+-			    0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
+-			    0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
+-			    0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
+-			    0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a,
+-			    0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
+-			    0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b,
+-			    0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37 },
++		.digest	= "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2"
++			  "\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3"
++			  "\x87\xbd\x64\x22\x2e\x83\x1f\xd6"
++			  "\x10\x27\x0c\xd7\xea\x25\x05\x54"
++			  "\x97\x58\xbf\x75\xc0\x5a\x99\x4a"
++			  "\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd"
++			  "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b"
++			  "\x63\x6e\x07\x0a\x38\xbc\xe7\x37",
+ 		.np	= 4,
+ 		.tap	= { 7, 7, 7, 7 }
+ 	}, {
+-		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa }, // (131 bytes)
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			  "\xaa\xaa\xaa",
+ 		.ksize	= 131,
+-		.plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+-			       0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, // ("Test Using Large")
+-			       0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+-			       0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, // ("r Than Block-Siz")
+-			       0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+-			       0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, // ("e Key - Hash Key")
+-			       0x20, 0x46, 0x69, 0x72, 0x73, 0x74 }, // (" First")
++		.plaintext = "Test Using Large"
++			   "r Than Block-Siz"
++			   "e Key - Hash Key"
++			   " First",
+ 		.psize	= 54,
+-		.digest	= { 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb,
+-			    0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
+-			    0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1,
+-			    0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
+-			    0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98,
+-			    0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
+-			    0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec,
+-			    0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98 },
+-	}, {
+-		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+-			    0xaa, 0xaa, 0xaa }, // (131 bytes)
++		.digest	= "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb"
++			"\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4"
++			"\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1"
++			"\x12\x1b\x01\x37\x83\xf8\xf3\x52"
++			"\x6b\x56\xd0\x37\xe0\x5f\x25\x98"
++			"\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52"
++			"\x95\xe6\x4f\x73\xf6\x3f\x0a\xec"
++			"\x8b\x91\x5a\x98\x5d\x78\x65\x98",
++	}, {
++		.key	= "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++			"\xaa\xaa\xaa",
+ 		.ksize	= 131,
+-		.plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+-			       0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, // ("This is a test u")
+-			       0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+-			       0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, // ("sing a larger th")
+-			       0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+-			       0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65, // ("an block-size ke")
+-			       0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+-			       0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, // ("y and a larger t")
+-			       0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+-			       0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, // ("han block-size d")
+-			       0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+-			       0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65, // ("ata. The key nee")
+-			       0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+-			       0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, // ("ds to be hashed ")
+-			       0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+-			       0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, // ("before being use")
+-			       0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+-			       0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c, // ("d by the HMAC al")
+-			       0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e }, // ("gorithm.")
++		.plaintext =
++			  "This is a test u"
++			  "sing a larger th"
++			  "an block-size ke"
++			  "y and a larger t"
++			  "han block-size d"
++			  "ata. The key nee"
++			  "ds to be hashed "
++			  "before being use"
++			  "d by the HMAC al"
++			  "gorithm.",
+ 		.psize	= 152,
+-		.digest	= { 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba,
+-			    0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd,
+-			    0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86,
+-			    0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44,
+-			    0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1,
+-			    0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
+-			    0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60,
+-			    0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58 },
++		.digest	= "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba"
++			"\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd"
++			"\xde\xbd\x71\xf8\x86\x72\x89\x86"
++			"\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44"
++			"\xb6\x02\x2c\xac\x3c\x49\x82\xb1"
++			"\x0d\x5e\xeb\x55\xc3\xe4\xde\x15"
++			"\x13\x46\x76\xfb\x6d\xe0\x44\x60"
++			"\x65\xc9\x74\x40\xfa\x8c\x6a\x58",
+ 	},
+ };
+ 
+@@ -1419,102 +1445,102 @@ static struct hash_testvec hmac_sha512_tv_template[] = {
+ 
+ static struct cipher_testvec des_enc_tv_template[] = {
+ 	{ /* From Applied Cryptography */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xe7",
+ 		.ilen	= 8,
+-		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
++		.result	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d",
+ 		.rlen	= 8,
+ 	}, { /* Same key, different plaintext block */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
++		.input	= "\x22\x33\x44\x55\x66\x77\x88\x99",
+ 		.ilen	= 8,
+-		.result	= { 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
++		.result	= "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b",
+ 		.rlen	= 8,
+ 	}, { /* Sbox test from NBS */
+-		.key	= { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },
++		.key	= "\x7c\xa1\x10\x45\x4a\x1a\x6e\x57",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 },
++		.input	= "\x01\xa1\xd6\xd0\x39\x77\x67\x42",
+ 		.ilen	= 8,
+-		.result	= { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
++		.result	= "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b",
+ 		.rlen	= 8,
+ 	}, { /* Three blocks */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+-			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+-			    0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++			  "\x22\x33\x44\x55\x66\x77\x88\x99"
++			  "\xca\xfe\xba\xbe\xfe\xed\xbe\xef",
+ 		.ilen	= 24,
+-		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+-			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+-			    0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },
++		.result	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++			  "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b"
++			  "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90",
+ 		.rlen	= 24,
+ 	}, { /* Weak key */
+ 		.fail	= 1,
+ 		.wk	= 1,
+-		.key	= { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
++		.key	= "\x01\x01\x01\x01\x01\x01\x01\x01",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xe7",
+ 		.ilen	= 8,
+-		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
++		.result	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d",
+ 		.rlen	= 8,
+ 	}, { /* Two blocks -- for testing encryption across pages */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+-			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++			  "\x22\x33\x44\x55\x66\x77\x88\x99",
+ 		.ilen	= 16,
+-		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+-			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
++		.result	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++			  "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b",
+ 		.rlen	= 16,
+ 		.np	= 2,
+ 		.tap	= { 8, 8 }
+ 	}, { /* Four blocks -- for testing encryption with chunking */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+-			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+-			    0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef,
+-			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++			  "\x22\x33\x44\x55\x66\x77\x88\x99"
++			  "\xca\xfe\xba\xbe\xfe\xed\xbe\xef"
++			  "\x22\x33\x44\x55\x66\x77\x88\x99",
+ 		.ilen	= 32,
+-		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+-			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+-			    0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90,
+-			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
++		.result	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++			  "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b"
++			  "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90"
++			  "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b",
+ 		.rlen	= 32,
+ 		.np	= 3,
+ 		.tap	= { 14, 10, 8 }
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+-			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+-			    0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++			  "\x22\x33\x44\x55\x66\x77\x88\x99"
++			  "\xca\xfe\xba\xbe\xfe\xed\xbe\xef",
+ 		.ilen	= 24,
+-		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+-			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+-			    0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },
++		.result	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++			  "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b"
++			  "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90",
+ 		.rlen	= 24,
+ 		.np	= 4,
+ 		.tap	= { 2, 1, 3, 18 }
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+-			    0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++			  "\x22\x33\x44\x55\x66\x77\x88\x99",
+ 		.ilen	= 16,
+-		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+-			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
++		.result	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++			  "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b",
+ 		.rlen	= 16,
+ 		.np	= 5,
+ 		.tap	= { 2, 2, 2, 2, 8 }
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xe7",
+ 		.ilen	= 8,
+-		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
++		.result	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d",
+ 		.rlen	= 8,
+ 		.np	= 8,
+ 		.tap	= { 1, 1, 1, 1, 1, 1, 1, 1 }
+@@ -1523,38 +1549,38 @@ static struct cipher_testvec des_enc_tv_template[] = {
+ 
+ static struct cipher_testvec des_dec_tv_template[] = {
+ 	{ /* From Applied Cryptography */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
++		.input	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d",
+ 		.ilen	= 8,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xe7",
+ 		.rlen	= 8,
+ 	}, { /* Sbox test from NBS */
+-		.key	= { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },
++		.key	= "\x7c\xa1\x10\x45\x4a\x1a\x6e\x57",
+ 		.klen	= 8,
+-		.input	= { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
++		.input	= "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b",
+ 		.ilen	= 8,
+-		.result	= { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 },
++		.result	= "\x01\xa1\xd6\xd0\x39\x77\x67\x42",
+ 		.rlen	= 8,
+ 	}, { /* Two blocks, for chunking test */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+-			    0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
++		.input	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++			  "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b",
+ 		.ilen	= 16,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+-			    0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++			  "\xa3\x99\x7b\xca\xaf\x69\xa0\xf5",
+ 		.rlen	= 16,
+ 		.np	= 2,
+ 		.tap	= { 8, 8 }
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+-			    0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
++		.input	= "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++			  "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b",
+ 		.ilen	= 16,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+-			    0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++			  "\xa3\x99\x7b\xca\xaf\x69\xa0\xf5",
+ 		.rlen	= 16,
+ 		.np	= 3,
+ 		.tap	= { 3, 12, 1 }
+@@ -1563,53 +1589,53 @@ static struct cipher_testvec des_dec_tv_template[] = {
+ 
+ static struct cipher_testvec des_cbc_enc_tv_template[] = {
+ 	{ /* From OpenSSL */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+-		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+-			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+-			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
++		.iv	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++		.input	= "\x37\x36\x35\x34\x33\x32\x31\x20"
++			  "\x4e\x6f\x77\x20\x69\x73\x20\x74"
++			  "\x68\x65\x20\x74\x69\x6d\x65\x20",
+ 		.ilen	= 24,
+-		.result	= { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+-			    0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+-			    0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
++		.result	= "\xcc\xd1\x73\xff\xab\x20\x39\xf4"
++			  "\xac\xd8\xae\xfd\xdf\xd8\xa1\xeb"
++			  "\x46\x8e\x91\x15\x78\x88\xba\x68",
+ 		.rlen	= 24,
+ 	}, { /* FIPS Pub 81 */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.iv	= { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
+-		.input	= { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
++		.iv	= "\x12\x34\x56\x78\x90\xab\xcd\xef",
++		.input	= "\x4e\x6f\x77\x20\x69\x73\x20\x74",
+ 		.ilen	= 8,
+-		.result	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
++		.result	= "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.iv	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+-		.input	= { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
++		.iv	= "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c",
++		.input	= "\x68\x65\x20\x74\x69\x6d\x65\x20",
+ 		.ilen	= 8,
+-		.result	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
++		.result	= "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.iv	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+-		.input	= { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
++		.iv	= "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
++		.input	= "\x66\x6f\x72\x20\x61\x6c\x6c\x20",
+ 		.ilen	= 8,
+-		.result	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
++		.result	= "\x68\x37\x88\x49\x9a\x7c\x05\xf6",
+ 		.rlen	= 8,
+ 	}, { /* Copy of openssl vector for chunk testing */
+ 	     /* From OpenSSL */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+-		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+-			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+-			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
++		.iv	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++		.input	= "\x37\x36\x35\x34\x33\x32\x31\x20"
++			  "\x4e\x6f\x77\x20\x69\x73\x20\x74"
++			  "\x68\x65\x20\x74\x69\x6d\x65\x20",
+ 		.ilen	= 24,
+-		.result	= { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+-			    0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+-			    0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
++		.result	= "\xcc\xd1\x73\xff\xab\x20\x39\xf4"
++			  "\xac\xd8\xae\xfd\xdf\xd8\xa1\xeb"
++			  "\x46\x8e\x91\x15\x78\x88\xba\x68",
+ 		.rlen	= 24,
+ 		.np	= 2,
+ 		.tap	= { 13, 11 }
+@@ -1618,36 +1644,36 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
+ 
+ static struct cipher_testvec des_cbc_dec_tv_template[] = {
+ 	{ /* FIPS Pub 81 */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.iv	= { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
+-		.input	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
++		.iv	= "\x12\x34\x56\x78\x90\xab\xcd\xef",
++		.input	= "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c",
+ 		.ilen	= 8,
+-		.result	= { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
++		.result	= "\x4e\x6f\x77\x20\x69\x73\x20\x74",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.iv	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+-		.input	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
++		.iv	= "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c",
++		.input	= "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
+ 		.ilen	= 8,
+-		.result	= { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
++		.result	= "\x68\x65\x20\x74\x69\x6d\x65\x20",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.iv	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+-		.input	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
++		.iv	= "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
++		.input	= "\x68\x37\x88\x49\x9a\x7c\x05\xf6",
+ 		.ilen	= 8,
+-		.result	= { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
++		.result	= "\x66\x6f\x72\x20\x61\x6c\x6c\x20",
+ 		.rlen	= 8,
+ 	}, { /* Copy of above, for chunk testing */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.iv	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+-		.input	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
++		.iv	= "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
++		.input	= "\x68\x37\x88\x49\x9a\x7c\x05\xf6",
+ 		.ilen	= 8,
+-		.result	= { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
++		.result	= "\x66\x6f\x72\x20\x61\x6c\x6c\x20",
+ 		.rlen	= 8,
+ 		.np	= 2,
+ 		.tap	= { 4, 4 }
+@@ -1659,62 +1685,62 @@ static struct cipher_testvec des_cbc_dec_tv_template[] = {
+  */
+ static struct cipher_testvec des3_ede_enc_tv_template[] = {
+ 	{ /* These are from openssl */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\x55\x55\x55\x55\x55\x55\x55\x55"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.klen	= 24,
+-		.input	= { 0x73, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x74, 0x61 },
++		.input	= "\x73\x6f\x6d\x65\x64\x61\x74\x61",
+ 		.ilen	= 8,
+-		.result	= { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 },
++		.result	= "\x18\xd7\x48\xe5\x63\x62\x05\x72",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x03, 0x52, 0x02, 0x07, 0x67, 0x20, 0x82, 0x17,
+-			    0x86, 0x02, 0x87, 0x66, 0x59, 0x08, 0x21, 0x98,
+-			    0x64, 0x05, 0x6a, 0xbd, 0xfe, 0xa9, 0x34, 0x57 },
++		.key	= "\x03\x52\x02\x07\x67\x20\x82\x17"
++			  "\x86\x02\x87\x66\x59\x08\x21\x98"
++			  "\x64\x05\x6a\xbd\xfe\xa9\x34\x57",
+ 		.klen	= 24,
+-		.input	= { 0x73, 0x71, 0x75, 0x69, 0x67, 0x67, 0x6c, 0x65 },
++		.input	= "\x73\x71\x75\x69\x67\x67\x6c\x65",
+ 		.ilen	= 8,
+-		.result	= { 0xc0, 0x7d, 0x2a, 0x0f, 0xa5, 0x66, 0xfa, 0x30 },
++		.result	= "\xc0\x7d\x2a\x0f\xa5\x66\xfa\x30",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+-			    0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+-			    0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01 },
++		.key	= "\x10\x46\x10\x34\x89\x98\x80\x20"
++			  "\x91\x07\xd0\x15\x89\x19\x01\x01"
++			  "\x19\x07\x92\x10\x98\x1a\x01\x01",
+ 		.klen	= 24,
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 8,
+-		.result	= { 0xe1, 0xef, 0x62, 0xc3, 0x32, 0xfe, 0x82, 0x5b },
++		.result	= "\xe1\xef\x62\xc3\x32\xfe\x82\x5b",
+ 		.rlen	= 8,
+ 	},
+ };
+ 
+ static struct cipher_testvec des3_ede_dec_tv_template[] = {
+ 	{ /* These are from openssl */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\x55\x55\x55\x55\x55\x55\x55\x55"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.klen	= 24,
+-		.input	= { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 },
++		.input	= "\x18\xd7\x48\xe5\x63\x62\x05\x72",
+ 		.ilen	= 8,
+-		.result	= { 0x73, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x74, 0x61 },
++		.result	= "\x73\x6f\x6d\x65\x64\x61\x74\x61",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x03, 0x52, 0x02, 0x07, 0x67, 0x20, 0x82, 0x17,
+-			    0x86, 0x02, 0x87, 0x66, 0x59, 0x08, 0x21, 0x98,
+-			    0x64, 0x05, 0x6a, 0xbd, 0xfe, 0xa9, 0x34, 0x57 },
++		.key	= "\x03\x52\x02\x07\x67\x20\x82\x17"
++			  "\x86\x02\x87\x66\x59\x08\x21\x98"
++			  "\x64\x05\x6a\xbd\xfe\xa9\x34\x57",
+ 		.klen	= 24,
+-		.input	= { 0xc0, 0x7d, 0x2a, 0x0f, 0xa5, 0x66, 0xfa, 0x30 },
++		.input	= "\xc0\x7d\x2a\x0f\xa5\x66\xfa\x30",
+ 		.ilen	= 8,
+-		.result	= { 0x73, 0x71, 0x75, 0x69, 0x67, 0x67, 0x6c, 0x65 },
++		.result	= "\x73\x71\x75\x69\x67\x67\x6c\x65",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+-			    0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+-			    0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01 },
++		.key	= "\x10\x46\x10\x34\x89\x98\x80\x20"
++			  "\x91\x07\xd0\x15\x89\x19\x01\x01"
++			  "\x19\x07\x92\x10\x98\x1a\x01\x01",
+ 		.klen	= 24,
+-		.input	= { 0xe1, 0xef, 0x62, 0xc3, 0x32, 0xfe, 0x82, 0x5b },
++		.input	= "\xe1\xef\x62\xc3\x32\xfe\x82\x5b",
+ 		.ilen	= 8,
+-		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.rlen	= 8,
+ 	},
+ };
+@@ -1729,148 +1755,148 @@ static struct cipher_testvec des3_ede_dec_tv_template[] = {
+ 
+ static struct cipher_testvec bf_enc_tv_template[] = {
+ 	{ /* DES test vectors from OpenSSL */
+-		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 8,
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 8,
+-		.result	= { 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78 },
++		.result	= "\x4e\xf9\x97\x45\x61\x98\xdd\x78",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
++		.key	= "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.ilen	= 8,
+-		.result	= { 0xa7, 0x90, 0x79, 0x51, 0x08, 0xea, 0x3c, 0xae },
++		.result	= "\xa7\x90\x79\x51\x08\xea\x3c\xae",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ 		.klen	= 8,
+-		.input	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.input	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.ilen	= 8,
+-		.result	= { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 },
++		.result	= "\xe8\x7a\x24\x4e\x2c\xc8\x5e\x82",
+ 		.rlen	= 8,
+ 	}, { /* Vary the keylength... */
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+-			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++			  "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f",
+ 		.klen	= 16,
+-		.input	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.input	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.ilen	= 8,
+-		.result	= { 0x93, 0x14, 0x28, 0x87, 0xee, 0x3b, 0xe1, 0x5c },
++		.result	= "\x93\x14\x28\x87\xee\x3b\xe1\x5c",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+-			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+-			    0x00, 0x11, 0x22, 0x33, 0x44 },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++			  "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
++			  "\x00\x11\x22\x33\x44",
+ 		.klen	= 21,
+-		.input	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.input	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.ilen	= 8,
+-		.result	= { 0xe6, 0xf5, 0x1e, 0xd7, 0x9b, 0x9d, 0xb2, 0x1f },
++		.result	= "\xe6\xf5\x1e\xd7\x9b\x9d\xb2\x1f",
+ 		.rlen	= 8,
+ 	}, { /* Generated with bf488 */
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+-			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+-			    0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+-			    0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
+-			    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++			  "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x04\x68\x91\x04\xc2\xfd\x3b\x2f"
++			  "\x58\x40\x23\x64\x1a\xba\x61\x76"
++			  "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e"
++			  "\xff\xff\xff\xff\xff\xff\xff\xff",
+ 		.klen	= 56,
+-		.input	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.input	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.ilen	= 8,
+-		.result	= { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 },
++		.result	= "\xc0\x45\x04\x01\x2e\x4e\x1f\x53",
+ 		.rlen	= 8,
+ 	},
+ };
+ 
+ static struct cipher_testvec bf_dec_tv_template[] = {
+ 	{ /* DES test vectors from OpenSSL */
+-		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 8,
+-		.input	= { 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78 },
++		.input	= "\x4e\xf9\x97\x45\x61\x98\xdd\x78",
+ 		.ilen	= 8,
+-		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
++		.key	= "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e",
+ 		.klen	= 8,
+-		.input	= { 0xa7, 0x90, 0x79, 0x51, 0x08, 0xea, 0x3c, 0xae },
++		.input	= "\xa7\x90\x79\x51\x08\xea\x3c\xae",
+ 		.ilen	= 8,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ 		.klen	= 8,
+-		.input	= { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 },
++		.input	= "\xe8\x7a\x24\x4e\x2c\xc8\x5e\x82",
+ 		.ilen	= 8,
+-		.result	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.result	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.rlen	= 8,
+ 	}, { /* Vary the keylength... */
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+-			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++			  "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f",
+ 		.klen	= 16,
+-		.input	= { 0x93, 0x14, 0x28, 0x87, 0xee, 0x3b, 0xe1, 0x5c },
++		.input	= "\x93\x14\x28\x87\xee\x3b\xe1\x5c",
+ 		.ilen	= 8,
+-		.result	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.result	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+-			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+-			    0x00, 0x11, 0x22, 0x33, 0x44 },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++			  "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
++			  "\x00\x11\x22\x33\x44",
+ 		.klen	= 21,
+-		.input	= { 0xe6, 0xf5, 0x1e, 0xd7, 0x9b, 0x9d, 0xb2, 0x1f },
++		.input	= "\xe6\xf5\x1e\xd7\x9b\x9d\xb2\x1f",
+ 		.ilen	= 8,
+-		.result	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.result	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.rlen	= 8,
+ 	}, { /* Generated with bf488, using OpenSSL, Libgcrypt and Nettle */
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+-			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+-			    0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+-			    0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
+-			    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++			  "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x04\x68\x91\x04\xc2\xfd\x3b\x2f"
++			  "\x58\x40\x23\x64\x1a\xba\x61\x76"
++			  "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e"
++			  "\xff\xff\xff\xff\xff\xff\xff\xff",
+ 		.klen	= 56,
+-		.input	= { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 },
++		.input	= "\xc0\x45\x04\x01\x2e\x4e\x1f\x53",
+ 		.ilen	= 8,
+-		.result	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.result	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.rlen	= 8,
+ 	},
+ };
+ 
+ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
+ 	{ /* From OpenSSL */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ 		.klen	= 16,
+-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+-		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+-			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+-			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
+-			    0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 },
++		.iv	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++		.input	= "\x37\x36\x35\x34\x33\x32\x31\x20"
++			  "\x4e\x6f\x77\x20\x69\x73\x20\x74"
++			  "\x68\x65\x20\x74\x69\x6d\x65\x20"
++			  "\x66\x6f\x72\x20\x00\x00\x00\x00",
+ 		.ilen	= 32,
+-		.result	= { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6,
+-			    0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93,
+-			    0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9,
+-			    0x59, 0xf1, 0x65, 0x2b, 0xd5, 0xff, 0x92, 0xcc },
++		.result	= "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
++			  "\x05\xb1\x56\xe2\x74\x03\x97\x93"
++			  "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
++			  "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
+ 		.rlen	= 32,
+ 	},
+ };
+ 
+ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
+ 	{ /* From OpenSSL */
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ 		.klen	= 16,
+-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+-		.input	= { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6,
+-			    0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93,
+-			    0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9,
+-			    0x59, 0xf1, 0x65, 0x2b, 0xd5, 0xff, 0x92, 0xcc },
++		.iv	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++		.input	= "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
++			  "\x05\xb1\x56\xe2\x74\x03\x97\x93"
++			  "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
++			  "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
+ 		.ilen	= 32,
+-		.result	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+-			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+-			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
+-			    0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 },
++		.result	= "\x37\x36\x35\x34\x33\x32\x31\x20"
++			  "\x4e\x6f\x77\x20\x69\x73\x20\x74"
++			  "\x68\x65\x20\x74\x69\x6d\x65\x20"
++			  "\x66\x6f\x72\x20\x00\x00\x00\x00",
+ 		.rlen	= 32,
+ 	},
+ };
+@@ -1885,158 +1911,158 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
+ 
+ static struct cipher_testvec tf_enc_tv_template[] = {
+ 	{
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.input	= { [0 ... 15] = 0x00 },
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
++		.result	= "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++			  "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77",
+ 		.klen	= 24,
+-		.input	= { [0 ... 15] = 0x00 },
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf,
+-			    0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48 },
++		.result	= "\xcf\xd1\xd2\xe5\xa9\xbe\x9c\xdf"
++			  "\x50\x1f\x13\xb8\x92\xbd\x22\x48",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.klen	= 32,
+-		.input	= { [0 ... 15] = 0x00 },
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8,
+-			    0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20 },
++		.result	= "\x37\x52\x7b\xe0\x05\x23\x34\xb8"
++			  "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec tf_dec_tv_template[] = {
+ 	{
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.input	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
++		.input	= "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++			  "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77",
+ 		.klen	= 24,
+-		.input	= { 0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf,
+-			    0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48 },
++		.input	= "\xcf\xd1\xd2\xe5\xa9\xbe\x9c\xdf"
++			  "\x50\x1f\x13\xb8\x92\xbd\x22\x48",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.klen	= 32,
+-		.input	= { 0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8,
+-			    0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20 },
++		.input	= "\x37\x52\x7b\xe0\x05\x23\x34\xb8"
++			  "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec tf_cbc_enc_tv_template[] = {
+ 	{ /* Generated with Nettle */
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.iv	= { [0 ... 15] = 0x00 },
+-		.input	= { [0 ... 15] = 0x00 },
++		.iv	= zeroed_string,
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
++		.result	= "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++			  "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.iv	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+-		.input	= { [0 ... 15] = 0x00 },
++		.iv	= "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++			  "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+-			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
++		.result	= "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++			  "\x86\xcb\x08\x6b\x78\x9f\x54\x19",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.iv	= { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+-			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
+-		.input	= { [0 ... 15] = 0x00 },
++		.iv	= "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++			  "\x86\xcb\x08\x6b\x78\x9f\x54\x19",
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+-			    0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
++		.result	= "\x05\xef\x8c\x61\xa8\x11\x58\x26"
++			  "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.iv	= { [0 ... 15] = 0x00 },
+-		.input	= { [0 ... 47] = 0x00 },
++		.iv	= zeroed_string,
++		.input	= zeroed_string,
+ 		.ilen	= 48,
+-		.result	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
+-			    0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+-			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
+-			    0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+-			    0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
++		.result	= "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++			  "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a"
++			  "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++			  "\x86\xcb\x08\x6b\x78\x9f\x54\x19"
++			  "\x05\xef\x8c\x61\xa8\x11\x58\x26"
++			  "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
+ 		.rlen	= 48,
+ 	},
+ };
+ 
+ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
+ 	{ /* Reverse of the first four above */
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.iv	= { [0 ... 15] = 0x00 },
+-		.input	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
++		.iv	= zeroed_string,
++		.input	= "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++			  "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.iv	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+-		.input	= { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+-			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
++		.iv	= "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++			  "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
++		.input	= "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++			  "\x86\xcb\x08\x6b\x78\x9f\x54\x19",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.iv	= { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+-			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
+-		.input	= { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+-			    0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
++		.iv	= "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++			  "\x86\xcb\x08\x6b\x78\x9f\x54\x19",
++		.input	= "\x05\xef\x8c\x61\xa8\x11\x58\x26"
++			  "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { [0 ... 15] = 0x00 },
++		.key	= zeroed_string,
+ 		.klen	= 16,
+-		.iv	= { [0 ... 15] = 0x00 },
+-		.input	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
+-			    0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+-			    0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
+-			    0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+-			    0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
++		.iv	= zeroed_string,
++		.input	= "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++			  "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a"
++			  "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++			  "\x86\xcb\x08\x6b\x78\x9f\x54\x19"
++			  "\x05\xef\x8c\x61\xa8\x11\x58\x26"
++			  "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
+ 		.ilen	= 48,
+-		.result	= { [0 ... 47] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 48,
+ 	},
+ };
+@@ -2053,90 +2079,90 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
+ 
+ static struct cipher_testvec serpent_enc_tv_template[] = {
+ 	{
+-		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.input	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.ilen	= 16,
+-		.result	= { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
+-			    0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 },
++		.result	= "\x12\x07\xfc\xce\x9b\xd0\xd6\x47"
++			  "\x6a\xe9\x8f\xbe\xd1\x43\xa0\xe2",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.klen	= 16,
+-		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.input	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.ilen	= 16,
+-		.result	= { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c,
+-			    0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d },
++		.result	= "\x4c\x7d\x8a\x32\x80\x72\xa2\x2c"
++			  "\x82\x3e\x4a\x1f\x3a\xcd\xa1\x6d",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.klen	= 32,
+-		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.input	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.ilen	= 16,
+-		.result	= { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8,
+-			    0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c },
++		.result	= "\xde\x26\x9f\xf8\x33\xe4\x32\xb8"
++			  "\x5b\x2e\x88\xd2\x70\x1c\xe7\x5c",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { [15] = 0x80 },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80",
+ 		.klen	= 16,
+-		.input	= { [0 ... 15] = 0x00 },
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
+-			    0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49},
++		.result	= "\xdd\xd2\x6b\x98\xa5\xff\xd8\x2c"
++			  "\x05\x34\x5a\x9d\xad\xbf\xaf\x49",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec tnepres_enc_tv_template[] = {
+ 	{ /* KeySize=128, PT=0, I=1 */
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.key    = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.key    = "\x80\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen   = 16,
+ 		.ilen	= 16,
+-		.result	= { 0x49, 0xaf, 0xbf, 0xad, 0x9d, 0x5a, 0x34, 0x05,
+-			    0x2c, 0xd8, 0xff, 0xa5, 0x98, 0x6b, 0xd2, 0xdd },
++		.result	= "\x49\xaf\xbf\xad\x9d\x5a\x34\x05"
++			  "\x2c\xd8\xff\xa5\x98\x6b\xd2\xdd",
+ 		.rlen	= 16,
+ 	}, { /* KeySize=192, PT=0, I=1 */
+-		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x80\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 24,
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 16,
+-		.result	= { 0xe7, 0x8e, 0x54, 0x02, 0xc7, 0x19, 0x55, 0x68,
+-			    0xac, 0x36, 0x78, 0xf7, 0xa3, 0xf6, 0x0c, 0x66 },
++		.result	= "\xe7\x8e\x54\x02\xc7\x19\x55\x68"
++			  "\xac\x36\x78\xf7\xa3\xf6\x0c\x66",
+ 		.rlen	= 16,
+ 	}, { /* KeySize=256, PT=0, I=1 */
+-		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x80\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 32,
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 16,
+-		.result	= { 0xab, 0xed, 0x96, 0xe7, 0x66, 0xbf, 0x28, 0xcb,
+-			    0xc0, 0xeb, 0xd2, 0x1a, 0x82, 0xef, 0x08, 0x19 },
++		.result	= "\xab\xed\x96\xe7\x66\xbf\x28\xcb"
++			  "\xc0\xeb\xd2\x1a\x82\xef\x08\x19",
+ 		.rlen	= 16,
+ 	}, { /* KeySize=256, I=257 */
+-	        .key	= { 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
+-			    0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
+-			    0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+-			    0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 },
++		.key	= "\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18"
++			  "\x17\x16\x15\x14\x13\x12\x11\x10"
++			  "\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08"
++			  "\x07\x06\x05\x04\x03\x02\x01\x00",
+ 		.klen	= 32,
+-		.input	= { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+-			    0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 },
++		.input	= "\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08"
++			  "\x07\x06\x05\x04\x03\x02\x01\x00",
+ 		.ilen	= 16,
+-		.result	= { 0x5c, 0xe7, 0x1c, 0x70, 0xd2, 0x88, 0x2e, 0x5b,
+-			    0xb8, 0x32, 0xe4, 0x33, 0xf8, 0x9f, 0x26, 0xde },
++		.result	= "\x5c\xe7\x1c\x70\xd2\x88\x2e\x5b"
++			  "\xb8\x32\xe4\x33\xf8\x9f\x26\xde",
+ 		.rlen	= 16,
+ 	},
+ };
+@@ -2144,82 +2170,82 @@ static struct cipher_testvec tnepres_enc_tv_template[] = {
+ 
+ static struct cipher_testvec serpent_dec_tv_template[] = {
+ 	{
+-		.input	= { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
+-			    0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 },
++		.input	= "\x12\x07\xfc\xce\x9b\xd0\xd6\x47"
++			  "\x6a\xe9\x8f\xbe\xd1\x43\xa0\xe2",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.klen	= 16,
+-		.input	= { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c,
+-			    0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d },
++		.input	= "\x4c\x7d\x8a\x32\x80\x72\xa2\x2c"
++			  "\x82\x3e\x4a\x1f\x3a\xcd\xa1\x6d",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.klen	= 32,
+-		.input	= { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8,
+-			    0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c },
++		.input	= "\xde\x26\x9f\xf8\x33\xe4\x32\xb8"
++			  "\x5b\x2e\x88\xd2\x70\x1c\xe7\x5c",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { [15] = 0x80 },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80",
+ 		.klen	= 16,
+-		.input	= { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
+-			    0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49},
++		.input	= "\xdd\xd2\x6b\x98\xa5\xff\xd8\x2c"
++			  "\x05\x34\x5a\x9d\xad\xbf\xaf\x49",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec tnepres_dec_tv_template[] = {
+ 	{
+-		.input	= { 0x41, 0xcc, 0x6b, 0x31, 0x59, 0x31, 0x45, 0x97,
+-			    0x6d, 0x6f, 0xbb, 0x38, 0x4b, 0x37, 0x21, 0x28 },
++		.input	= "\x41\xcc\x6b\x31\x59\x31\x45\x97"
++			  "\x6d\x6f\xbb\x38\x4b\x37\x21\x28",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.klen	= 16,
+-		.input	= { 0xea, 0xf4, 0xd7, 0xfc, 0xd8, 0x01, 0x34, 0x47,
+-			    0x81, 0x45, 0x0b, 0xfa, 0x0c, 0xd6, 0xad, 0x6e },
++		.input	= "\xea\xf4\xd7\xfc\xd8\x01\x34\x47"
++			  "\x81\x45\x0b\xfa\x0c\xd6\xad\x6e",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.klen	= 32,
+-		.input	= { 0x64, 0xa9, 0x1a, 0x37, 0xed, 0x9f, 0xe7, 0x49,
+-			    0xa8, 0x4e, 0x76, 0xd6, 0xf5, 0x0d, 0x78, 0xee },
++		.input	= "\x64\xa9\x1a\x37\xed\x9f\xe7\x49"
++			  "\xa8\x4e\x76\xd6\xf5\x0d\x78\xee",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.rlen	= 16,
+ 	}, { /* KeySize=128, I=121 */
+-		.key	= { [15] = 0x80 },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80",
+ 		.klen	= 16,
+-		.input	= { 0x3d, 0xda, 0xbf, 0xc0, 0x06, 0xda, 0xab, 0x06,
+-			    0x46, 0x2a, 0xf4, 0xef, 0x81, 0x54, 0x4e, 0x26 },
++		.input	= "\x3d\xda\xbf\xc0\x06\xda\xab\x06"
++			  "\x46\x2a\xf4\xef\x81\x54\x4e\x26",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	},
+ };
+@@ -2231,68 +2257,68 @@ static struct cipher_testvec tnepres_dec_tv_template[] = {
+ 
+ static struct cipher_testvec cast6_enc_tv_template[] = {
+ 	{
+-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+-			    0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
++		.key	= "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++			  "\x0a\xf7\x56\x47\xf2\x9f\x61\x5d",
+ 		.klen	= 16,
+-		.input	= { [0 ... 15] = 0x00 },
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
+-			    0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
++		.result	= "\xc8\x42\xa0\x89\x72\xb4\x3d\x20"
++			  "\x83\x6c\x91\xd1\xb7\x53\x0f\x6b",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+-			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+-			    0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
++		.key	= "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++			  "\xbe\xd0\xac\x83\x94\x0a\xc2\x98"
++			  "\xba\xc7\x7a\x77\x17\x94\x28\x63",
+ 		.klen	= 24,
+-		.input	= { [0 ... 15] = 0x00 },
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
+-			    0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
++		.result	= "\x1b\x38\x6c\x02\x10\xdc\xad\xcb"
++			  "\xdd\x0e\x41\xaa\x08\xa7\xa7\xe8",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+-			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+-			    0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
+-			    0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
++		.key	= "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++			  "\xbe\xd0\xac\x83\x94\x0a\xc2\x98"
++			  "\x8d\x7c\x47\xce\x26\x49\x08\x46"
++			  "\x1c\xc1\xb5\x13\x7a\xe6\xb6\x04",
+ 		.klen	= 32,
+-		.input	= { [0 ... 15] = 0x00 },
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
+-			    0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
++		.result	= "\x4f\x6a\x20\x38\x28\x68\x97\xb9"
++			  "\xc9\x87\x01\x36\x55\x33\x17\xfa",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec cast6_dec_tv_template[] = {
+ 	{
+-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+-			    0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
++		.key	= "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++			  "\x0a\xf7\x56\x47\xf2\x9f\x61\x5d",
+ 		.klen	= 16,
+-		.input	= { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
+-			    0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
++		.input	= "\xc8\x42\xa0\x89\x72\xb4\x3d\x20"
++			  "\x83\x6c\x91\xd1\xb7\x53\x0f\x6b",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+-			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+-			    0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
++		.key	= "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++			  "\xbe\xd0\xac\x83\x94\x0a\xc2\x98"
++			  "\xba\xc7\x7a\x77\x17\x94\x28\x63",
+ 		.klen	= 24,
+-		.input	= { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
+-			    0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
++		.input	= "\x1b\x38\x6c\x02\x10\xdc\xad\xcb"
++			  "\xdd\x0e\x41\xaa\x08\xa7\xa7\xe8",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+-			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+-			    0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
+-			    0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
++		.key	= "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++			  "\xbe\xd0\xac\x83\x94\x0a\xc2\x98"
++			  "\x8d\x7c\x47\xce\x26\x49\x08\x46"
++			  "\x1c\xc1\xb5\x13\x7a\xe6\xb6\x04",
+ 		.klen	= 32,
+-		.input	= { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
+-			    0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
++		.input	= "\x4f\x6a\x20\x38\x28\x68\x97\xb9"
++			  "\xc9\x87\x01\x36\x55\x33\x17\xfa",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	},
+ };
+@@ -2318,238 +2344,238 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
+ 
+ static struct cipher_testvec aes_enc_tv_template[] = {
+ 	{ /* From FIPS-197 */
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.klen	= 16,
+-		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.input	= "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.ilen	= 16,
+-		.result	= { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+-			    0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
++		.result	= "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
++			  "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17",
+ 		.klen	= 24,
+-		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.input	= "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.ilen	= 16,
+-		.result	= { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+-			    0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
++		.result	= "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
++			  "\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.klen	= 32,
+-		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.input	= "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.ilen	= 16,
+-		.result	= { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+-			    0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
++		.result	= "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
++			  "\xea\xfc\x49\x90\x4b\x49\x60\x89",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec aes_dec_tv_template[] = {
+ 	{ /* From FIPS-197 */
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.klen	= 16,
+-		.input	= { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+-			    0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
++		.input	= "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
++			  "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17",
+ 		.klen	= 24,
+-		.input	= { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+-			    0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
++		.input	= "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
++			  "\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.klen	= 32,
+-		.input	= { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+-			    0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
++		.input	= "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
++			  "\xea\xfc\x49\x90\x4b\x49\x60\x89",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
+ 	{ /* From RFC 3602 */
+-		.key    = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+-			    0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
++		.key    = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
++			  "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ 		.klen   = 16,
+-		.iv	= { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+-			    0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+-		.input	= { "Single block msg" },
++		.iv	= "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
++			  "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
++		.input	= "Single block msg",
+ 		.ilen   = 16,
+-		.result = { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
+-			    0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
++		.result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
++			  "\x27\x08\x94\x2d\xbe\x77\x18\x1a",
+ 		.rlen   = 16,
+ 	}, {
+-		.key    = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+-			    0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
++		.key    = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
++			  "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
+ 		.klen   = 16,
+-		.iv     = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+-			    0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+-		.input  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.iv     = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
++			  "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
++		.input  = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.ilen   = 32,
+-		.result = { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
+-			    0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
+-			    0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
+-			    0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
++		.result = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a"
++			  "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a"
++			  "\x75\x86\x60\x2d\x25\x3c\xff\xf9"
++			  "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1",
+ 		.rlen   = 32,
+ 	}, { /* From NIST SP800-38A */
+-		.key	= { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+-			    0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+-			    0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
++		.key	= "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
++			  "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
++			  "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+ 		.klen	= 24,
+-		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.input	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+-			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+-			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+-			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+-			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+-			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+-			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+-			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++		.iv	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.input	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
++			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
++			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
++			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
++			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
++			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
++			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
++			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ 		.ilen	= 64,
+-		.result	= { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
+-			    0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
+-			    0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
+-			    0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
+-			    0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
+-			    0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
+-			    0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
+-			    0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
++		.result	= "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d"
++			  "\x71\x78\x18\x3a\x9f\xa0\x71\xe8"
++			  "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4"
++			  "\xe5\xe7\x38\x76\x3f\x69\x14\x5a"
++			  "\x57\x1b\x24\x20\x12\xfb\x7a\xe0"
++			  "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0"
++			  "\x08\xb0\xe2\x79\x88\x59\x88\x81"
++			  "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd",
+ 		.rlen	= 64,
+ 	}, {
+-		.key	= { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+-			    0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+-			    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+-			    0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
++		.key	= "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
++			  "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
++			  "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
++			  "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+ 		.klen	= 32,
+-		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.input	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+-			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+-			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+-			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+-			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+-			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+-			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+-			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++		.iv	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.input	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
++			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
++			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
++			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
++			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
++			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
++			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
++			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ 		.ilen	= 64,
+-		.result	= { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+-			    0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+-			    0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+-			    0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+-			    0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+-			    0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+-			    0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+-			    0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
++		.result	= "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba"
++			  "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6"
++			  "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d"
++			  "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d"
++			  "\x39\xf2\x33\x69\xa9\xd9\xba\xcf"
++			  "\xa5\x30\xe2\x63\x04\x23\x14\x61"
++			  "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
++			  "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
+ 		.rlen	= 64,
+ 	},
+ };
+ 
+ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
+ 	{ /* From RFC 3602 */
+-		.key    = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+-			    0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
++		.key    = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
++			  "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ 		.klen   = 16,
+-		.iv     = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+-			    0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+-		.input  = { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
+-			    0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
++		.iv     = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
++			  "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
++		.input  = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
++			  "\x27\x08\x94\x2d\xbe\x77\x18\x1a",
+ 		.ilen   = 16,
+-		.result = { "Single block msg" },
++		.result = "Single block msg",
+ 		.rlen   = 16,
+ 	}, {
+-		.key    = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+-			    0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
++		.key    = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
++			  "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
+ 		.klen   = 16,
+-		.iv     = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+-			    0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+-		.input  = { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
+-			    0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
+-			    0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
+-			    0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
++		.iv     = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
++			  "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
++		.input  = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a"
++			  "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a"
++			  "\x75\x86\x60\x2d\x25\x3c\xff\xf9"
++			  "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1",
+ 		.ilen   = 32,
+-		.result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.rlen   = 32,
+ 	}, { /* From NIST SP800-38A */
+-		.key	= { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+-			    0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+-			    0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
++		.key	= "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
++			  "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
++			  "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+ 		.klen	= 24,
+-		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.input	= { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
+-			    0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
+-			    0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
+-			    0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
+-			    0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
+-			    0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
+-			    0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
+-			    0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
++		.iv	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.input	= "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d"
++			  "\x71\x78\x18\x3a\x9f\xa0\x71\xe8"
++			  "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4"
++			  "\xe5\xe7\x38\x76\x3f\x69\x14\x5a"
++			  "\x57\x1b\x24\x20\x12\xfb\x7a\xe0"
++			  "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0"
++			  "\x08\xb0\xe2\x79\x88\x59\x88\x81"
++			  "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd",
+ 		.ilen	= 64,
+-		.result	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+-			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+-			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+-			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+-			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+-			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+-			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+-			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++		.result	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
++			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
++			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
++			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
++			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
++			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
++			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
++			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ 		.rlen	= 64,
+ 	}, {
+-		.key	= { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+-			    0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+-			    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+-			    0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
++		.key	= "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
++			  "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
++			  "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
++			  "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+ 		.klen	= 32,
+-		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+-		.input	= { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+-			    0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+-			    0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+-			    0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+-			    0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+-			    0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+-			    0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+-			    0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
++		.iv	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++		.input	= "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba"
++			  "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6"
++			  "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d"
++			  "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d"
++			  "\x39\xf2\x33\x69\xa9\xd9\xba\xcf"
++			  "\xa5\x30\xe2\x63\x04\x23\x14\x61"
++			  "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
++			  "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
+ 		.ilen	= 64,
+-		.result	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+-			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+-			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+-			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+-			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+-			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+-			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+-			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++		.result	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
++			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
++			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
++			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
++			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
++			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
++			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
++			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ 		.rlen	= 64,
+ 	},
+ };
+@@ -2557,250 +2583,249 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
+ static struct cipher_testvec aes_lrw_enc_tv_template[] = {
+ 	/* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */
+ 	{ /* LRW-32-AES 1 */
+-		.key    = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d,
+-			    0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85,
+-			    0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03,
+-			    0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
++		.key    = "\x45\x62\xac\x25\xf8\x28\x17\x6d"
++			  "\x4c\x26\x84\x14\xb5\x68\x01\x85"
++			  "\x25\x8e\x2a\x05\xe7\x3e\x9d\x03"
++			  "\xee\x5a\x83\x0c\xcc\x09\x4c\x87",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+-		.input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x01",
++		.input  = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.ilen   = 16,
+-		.result = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f,
+-			    0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 },
++		.result = "\xf1\xb2\x73\xcd\x65\xa3\xdf\x5f"
++			  "\xe9\x5d\x48\x92\x54\x63\x4e\xb8",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 2 */
+-		.key    = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c,
+-		  	    0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44,
+-			    0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea,
+-			    0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf
+-		},
++		.key    = "\x59\x70\x47\x14\xf5\x57\x47\x8c"
++			  "\xd7\x79\xe8\x0f\x54\x88\x79\x44"
++			  "\x0d\x48\xf0\xb7\xb1\x5a\x53\xea"
++			  "\x1c\xaa\x6b\x29\xc2\xca\xfb\xaf",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+-		.input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x02",
++		.input  = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.ilen   = 16,
+-		.result = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5,
+-			    0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
++		.result = "\x00\xc8\x2b\xae\x95\xbb\xcd\xe5"
++			  "\x27\x4f\x07\x69\xb2\x60\xe1\x36",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 3 */
+-		.key    = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50,
+-		  	    0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47,
+-			    0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6,
+-			    0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f },
++		.key    = "\xd8\x2a\x91\x34\xb2\x6a\x56\x50"
++			  "\x30\xfe\x69\xe2\x37\x7f\x98\x47"
++			  "\xcd\xf9\x0b\x16\x0c\x64\x8f\xb6"
++			  "\xb0\x0d\x0d\x1b\xae\x85\x87\x1f",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x02\x00\x00\x00\x00",
++		.input  = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.ilen   = 16,
+-		.result = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82,
+-			    0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },
++		.result = "\x76\x32\x21\x83\xed\x8f\xf1\x82"
++			  "\xf9\x59\x62\x03\x69\x0e\x5e\x01",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 4 */
+-		.key    = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15,
+-		  	    0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74,
+-			    0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54,
+-			    0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc,
+-			    0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 },
++		.key    = "\x0f\x6a\xef\xf8\xd3\xd2\xbb\x15"
++			  "\x25\x83\xf7\x3c\x1f\x01\x28\x74"
++			  "\xca\xc6\xbc\x35\x4d\x4a\x65\x54"
++			  "\x90\xae\x61\xcf\x7b\xae\xbd\xcc"
++			  "\xad\xe4\x94\xc5\x4a\x29\xae\x70",
+ 		.klen   = 40,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+-		.input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x01",
++		.input  = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.ilen   = 16,
+-		.result = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0,
+-			    0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 },
++		.result = "\x9c\x0f\x15\x2f\x55\xa2\xd8\xf0"
++			  "\xd6\x7b\x8f\x9e\x28\x22\xbc\x41",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 5 */
+-		.key    = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff,
+-		  	    0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6,
+-			    0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd,
+-			    0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8,
+-			    0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f },
++		.key    = "\x8a\xd4\xee\x10\x2f\xbd\x81\xff"
++			  "\xf8\x86\xce\xac\x93\xc5\xad\xc6"
++			  "\xa0\x19\x07\xc0\x9d\xf7\xbb\xdd"
++			  "\x52\x13\xb2\xb7\xf0\xff\x11\xd8"
++			  "\xd6\x08\xd0\xcd\x2e\xb1\x17\x6f",
+ 		.klen   = 40,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x02\x00\x00\x00\x00",
++		.input  = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.ilen   = 16,
+-		.result = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65,
+-			    0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 },
++		.result = "\xd4\x27\x6a\x7f\x14\x91\x3d\x65"
++			  "\xc8\x60\x48\x02\x87\xe3\x34\x06",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 6 */
+-		.key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+-		  	    0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+-			    0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+-			    0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+-			    0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+-			    0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
++		.key    = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
++			  "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
++			  "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
++			  "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
++			  "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
++			  "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+ 		.klen   = 48,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+-		.input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x01",
++		.input  = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.ilen   = 16,
+-		.result = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e,
+-			    0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b },
++		.result = "\xbd\x06\xb8\xe1\xdb\x98\x89\x9e"
++			  "\xc4\x98\xe4\x91\xcf\x1c\x70\x2b",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 7 */
+-		.key    = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d,
+-		  	    0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8,
+-			    0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d,
+-			    0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7,
+-			    0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4,
+-			    0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c },
++		.key    = "\xfb\x76\x15\xb2\x3d\x80\x89\x1d"
++			  "\xd4\x70\x98\x0b\xc7\x95\x84\xc8"
++			  "\xb2\xfb\x64\xce\x60\x97\x87\x8d"
++			  "\x17\xfc\xe4\x5a\x49\xe8\x30\xb7"
++			  "\x6e\x78\x17\xe7\x2d\x5e\x12\xd4"
++			  "\x60\x64\x04\x7a\xf1\x2f\x9e\x0c",
+ 		.klen   = 48,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x02\x00\x00\x00\x00",
++		.input  = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.ilen   = 16,
+-		.result = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f,
+-			    0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 },
++		.result = "\x5b\x90\x8e\xc1\xab\xdd\x67\x5f"
++			  "\x3d\x69\x8a\x95\x53\xc8\x9c\xe5",
+ 		.rlen   = 16,
+ 	}, {
+ /* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */
+-		.key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+-			    0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+-			    0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+-			    0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+-			    0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+-			    0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
++		.key    = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
++			  "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
++			  "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
++			  "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
++			  "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
++			  "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+ 		.klen   = 48,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+-		.input  = { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac,
+-			    0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c,
+-			    0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8,
+-			    0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6,
+-			    0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90,
+-			    0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6,
+-			    0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04,
+-			    0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab,
+-			    0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c,
+-			    0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04,
+-			    0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6,
+-			    0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03,
+-			    0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65,
+-			    0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01,
+-			    0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1,
+-			    0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50,
+-			    0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd,
+-			    0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3,
+-			    0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5,
+-			    0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74,
+-			    0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53,
+-			    0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40,
+-			    0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5,
+-			    0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72,
+-			    0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda,
+-			    0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd,
+-			    0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60,
+-			    0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09,
+-			    0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9,
+-			    0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8,
+-			    0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8,
+-			    0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10,
+-			    0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1,
+-			    0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c,
+-			    0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e,
+-			    0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f,
+-			    0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e,
+-			    0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22,
+-			    0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78,
+-			    0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5,
+-			    0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41,
+-			    0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75,
+-			    0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43,
+-			    0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe,
+-			    0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65,
+-			    0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9,
+-			    0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4,
+-			    0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a,
+-			    0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d,
+-			    0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf,
+-			    0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b,
+-			    0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7,
+-			    0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85,
+-			    0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb,
+-			    0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8,
+-			    0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24,
+-			    0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01,
+-			    0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce,
+-			    0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6,
+-			    0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32,
+-			    0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45,
+-			    0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6,
+-			    0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4,
+-			    0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x01",
++		.input  = "\x05\x11\xb7\x18\xab\xc6\x2d\xac"
++			  "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c"
++			  "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8"
++			  "\x50\x38\x1f\x71\x49\xb6\x57\xd6"
++			  "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90"
++			  "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6"
++			  "\xad\x1e\x9e\x20\x5f\x38\xbe\x04"
++			  "\xda\x10\x8e\xed\xa2\xa4\x87\xab"
++			  "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c"
++			  "\xc9\xac\x42\x31\x95\x7c\xc9\x04"
++			  "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6"
++			  "\x15\xd7\x3f\x4f\x2f\x66\x69\x03"
++			  "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65"
++			  "\x4c\x96\x12\xed\x7c\x92\x03\x01"
++			  "\x6f\xbc\x35\x93\xac\xf1\x27\xf1"
++			  "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50"
++			  "\x89\xa4\x8e\x66\x44\x85\xcc\xfd"
++			  "\x33\x14\x70\xe3\x96\xb2\xc3\xd3"
++			  "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5"
++			  "\x2d\x64\x75\xdd\xb4\x54\xe6\x74"
++			  "\x8c\xd3\x9d\x9e\x86\xab\x51\x53"
++			  "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40"
++			  "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5"
++			  "\x76\x12\x73\x44\x1a\x56\xd7\x72"
++			  "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda"
++			  "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd"
++			  "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60"
++			  "\x1a\xe2\x70\x85\x58\xc2\x1b\x09"
++			  "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9"
++			  "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8"
++			  "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8"
++			  "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10"
++			  "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1"
++			  "\x90\x3e\x76\x4a\x74\xa4\x21\x2c"
++			  "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e"
++			  "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f"
++			  "\x8d\x23\x31\x74\x84\xeb\x88\x6e"
++			  "\xcc\xb9\xbc\x22\x83\x19\x07\x22"
++			  "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78"
++			  "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5"
++			  "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41"
++			  "\x3c\xce\x8f\x42\x60\x71\xa7\x75"
++			  "\x08\x40\x65\x8a\x82\xbf\xf5\x43"
++			  "\x71\x96\xa9\x4d\x44\x8a\x20\xbe"
++			  "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65"
++			  "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9"
++			  "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4"
++			  "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a"
++			  "\x62\x73\x65\xfd\x46\x63\x25\x3d"
++			  "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf"
++			  "\x24\xf3\xb4\xac\x64\xba\xdf\x4b"
++			  "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7"
++			  "\xc5\x68\x77\x84\x32\x2b\xcc\x85"
++			  "\x74\x96\xf0\x12\x77\x61\xb9\xeb"
++			  "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8"
++			  "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24"
++			  "\xda\x39\x87\x45\xc0\x2b\xbb\x01"
++			  "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce"
++			  "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6"
++			  "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32"
++			  "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45"
++			  "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6"
++			  "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4"
++			  "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
+ 		.ilen   = 512,
+-		.result = { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b,
+-			    0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a,
+-			    0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23,
+-			    0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e,
+-			    0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c,
+-			    0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d,
+-			    0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3,
+-			    0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde,
+-			    0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3,
+-			    0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59,
+-			    0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d,
+-			    0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae,
+-			    0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82,
+-			    0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68,
+-			    0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce,
+-			    0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98,
+-			    0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2,
+-			    0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f,
+-			    0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf,
+-			    0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc,
+-			    0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf,
+-			    0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63,
+-			    0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3,
+-			    0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8,
+-			    0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99,
+-			    0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c,
+-			    0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50,
+-			    0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d,
+-			    0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c,
+-			    0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48,
+-			    0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1,
+-			    0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46,
+-			    0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b,
+-			    0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28,
+-			    0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62,
+-			    0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43,
+-			    0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16,
+-			    0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c,
+-			    0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13,
+-			    0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6,
+-			    0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4,
+-			    0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f,
+-			    0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17,
+-			    0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30,
+-			    0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd,
+-			    0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85,
+-			    0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee,
+-			    0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11,
+-			    0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62,
+-			    0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1,
+-			    0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a,
+-			    0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33,
+-			    0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1,
+-			    0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0,
+-			    0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7,
+-			    0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a,
+-			    0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32,
+-			    0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6,
+-			    0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d,
+-			    0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4,
+-			    0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3,
+-			    0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29,
+-			    0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7,
+-			    0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e },
++		.result = "\x1a\x1d\xa9\x30\xad\xf9\x2f\x9b"
++			  "\xb6\x1d\xae\xef\xf0\x2f\xf8\x5a"
++			  "\x39\x3c\xbf\x2a\xb2\x45\xb2\x23"
++			  "\x1b\x63\x3c\xcf\xaa\xbe\xcf\x4e"
++			  "\xfa\xe8\x29\xc2\x20\x68\x2b\x3c"
++			  "\x2e\x8b\xf7\x6e\x25\xbd\xe3\x3d"
++			  "\x66\x27\xd6\xaf\xd6\x64\x3e\xe3"
++			  "\xe8\x58\x46\x97\x39\x51\x07\xde"
++			  "\xcb\x37\xbc\xa9\xc0\x5f\x75\xc3"
++			  "\x0e\x84\x23\x1d\x16\xd4\x1c\x59"
++			  "\x9c\x1a\x02\x55\xab\x3a\x97\x1d"
++			  "\xdf\xdd\xc7\x06\x51\xd7\x70\xae"
++			  "\x23\xc6\x8c\xf5\x1e\xa0\xe5\x82"
++			  "\xb8\xb2\xbf\x04\xa0\x32\x8e\x68"
++			  "\xeb\xaf\x6e\x2d\x94\x22\x2f\xce"
++			  "\x4c\xb5\x59\xe2\xa2\x2f\xa0\x98"
++			  "\x1a\x97\xc6\xd4\xb5\x00\x59\xf2"
++			  "\x84\x14\x72\xb1\x9a\x6e\xa3\x7f"
++			  "\xea\x20\xe7\xcb\x65\x77\x3a\xdf"
++			  "\xc8\x97\x67\x15\xc2\x2a\x27\xcc"
++			  "\x18\x55\xa1\x24\x0b\x24\x24\xaf"
++			  "\x5b\xec\x68\xb8\xc8\xf5\xba\x63"
++			  "\xff\xed\x89\xce\xd5\x3d\x88\xf3"
++			  "\x25\xef\x05\x7c\x3a\xef\xeb\xd8"
++			  "\x7a\x32\x0d\xd1\x1e\x58\x59\x99"
++			  "\x90\x25\xb5\x26\xb0\xe3\x2b\x6c"
++			  "\x4c\xa9\x8b\x84\x4f\x5e\x01\x50"
++			  "\x41\x30\x58\xc5\x62\x74\x52\x1d"
++			  "\x45\x24\x6a\x42\x64\x4f\x97\x1c"
++			  "\xa8\x66\xb5\x6d\x79\xd4\x0d\x48"
++			  "\xc5\x5f\xf3\x90\x32\xdd\xdd\xe1"
++			  "\xe4\xa9\x9f\xfc\xc3\x52\x5a\x46"
++			  "\xe4\x81\x84\x95\x36\x59\x7a\x6b"
++			  "\xaa\xb3\x60\xad\xce\x9f\x9f\x28"
++			  "\xe0\x01\x75\x22\xc4\x4e\xa9\x62"
++			  "\x5c\x62\x0d\x00\xcb\x13\xe8\x43"
++			  "\x72\xd4\x2d\x53\x46\xb5\xd1\x16"
++			  "\x22\x18\xdf\x34\x33\xf5\xd6\x1c"
++			  "\xb8\x79\x78\x97\x94\xff\x72\x13"
++			  "\x4c\x27\xfc\xcb\xbf\x01\x53\xa6"
++			  "\xb4\x50\x6e\xde\xdf\xb5\x43\xa4"
++			  "\x59\xdf\x52\xf9\x7c\xe0\x11\x6f"
++			  "\x2d\x14\x8e\x24\x61\x2c\xe1\x17"
++			  "\xcc\xce\x51\x0c\x19\x8a\x82\x30"
++			  "\x94\xd5\x3d\x6a\x53\x06\x5e\xbd"
++			  "\xb7\xeb\xfa\xfd\x27\x51\xde\x85"
++			  "\x1e\x86\x53\x11\x53\x94\x00\xee"
++			  "\x2b\x8c\x08\x2a\xbf\xdd\xae\x11"
++			  "\xcb\x1e\xa2\x07\x9a\x80\xcf\x62"
++			  "\x9b\x09\xdc\x95\x3c\x96\x8e\xb1"
++			  "\x09\xbd\xe4\xeb\xdb\xca\x70\x7a"
++			  "\x9e\xfa\x31\x18\x45\x3c\x21\x33"
++			  "\xb0\xb3\x2b\xea\xf3\x71\x2d\xe1"
++			  "\x03\xad\x1b\x48\xd4\x67\x27\xf0"
++			  "\x62\xe4\x3d\xfb\x9b\x08\x76\xe7"
++			  "\xdd\x2b\x01\x39\x04\x5a\x58\x7a"
++			  "\xf7\x11\x90\xec\xbd\x51\x5c\x32"
++			  "\x6b\xd7\x35\x39\x02\x6b\xf2\xa6"
++			  "\xd0\x0d\x07\xe1\x06\xc4\x5b\x7d"
++			  "\xe4\x6a\xd7\xee\x15\x1f\x83\xb4"
++			  "\xa3\xa7\x5e\xc3\x90\xb7\xef\xd3"
++			  "\xb7\x4f\xf8\x92\x4c\xb7\x3c\x29"
++			  "\xcd\x7e\x2b\x5d\x43\xea\x42\xe7"
++			  "\x74\x3f\x7d\x58\x88\x75\xde\x3e",
+ 		.rlen   = 512,
+ 	}
+ };
+@@ -2809,250 +2834,249 @@ static struct cipher_testvec aes_lrw_dec_tv_template[] = {
+ 	/* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */
+ 	/* same as enc vectors with input and result reversed */
+ 	{ /* LRW-32-AES 1 */
+-		.key    = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d,
+-			    0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85,
+-			    0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03,
+-			    0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
++		.key    = "\x45\x62\xac\x25\xf8\x28\x17\x6d"
++			  "\x4c\x26\x84\x14\xb5\x68\x01\x85"
++			  "\x25\x8e\x2a\x05\xe7\x3e\x9d\x03"
++			  "\xee\x5a\x83\x0c\xcc\x09\x4c\x87",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+-		.input  = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f,
+-			    0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x01",
++		.input  = "\xf1\xb2\x73\xcd\x65\xa3\xdf\x5f"
++			  "\xe9\x5d\x48\x92\x54\x63\x4e\xb8",
+ 		.ilen   = 16,
+-		.result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 2 */
+-		.key    = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c,
+-		  	    0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44,
+-			    0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea,
+-			    0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf
+-		},
++		.key    = "\x59\x70\x47\x14\xf5\x57\x47\x8c"
++			  "\xd7\x79\xe8\x0f\x54\x88\x79\x44"
++			  "\x0d\x48\xf0\xb7\xb1\x5a\x53\xea"
++			  "\x1c\xaa\x6b\x29\xc2\xca\xfb\xaf",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+-		.input  = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5,
+-			    0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x02",
++		.input  = "\x00\xc8\x2b\xae\x95\xbb\xcd\xe5"
++			  "\x27\x4f\x07\x69\xb2\x60\xe1\x36",
+ 		.ilen   = 16,
+-		.result  = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			     0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.result  = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			   "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 3 */
+-		.key    = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50,
+-		  	    0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47,
+-			    0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6,
+-			    0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f },
++		.key    = "\xd8\x2a\x91\x34\xb2\x6a\x56\x50"
++			  "\x30\xfe\x69\xe2\x37\x7f\x98\x47"
++			  "\xcd\xf9\x0b\x16\x0c\x64\x8f\xb6"
++			  "\xb0\x0d\x0d\x1b\xae\x85\x87\x1f",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82,
+-			    0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x02\x00\x00\x00\x00",
++		.input  = "\x76\x32\x21\x83\xed\x8f\xf1\x82"
++			  "\xf9\x59\x62\x03\x69\x0e\x5e\x01",
+ 		.ilen   = 16,
+-		.result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 4 */
+-		.key    = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15,
+-		  	    0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74,
+-			    0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54,
+-			    0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc,
+-			    0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 },
++		.key    = "\x0f\x6a\xef\xf8\xd3\xd2\xbb\x15"
++			  "\x25\x83\xf7\x3c\x1f\x01\x28\x74"
++			  "\xca\xc6\xbc\x35\x4d\x4a\x65\x54"
++			  "\x90\xae\x61\xcf\x7b\xae\xbd\xcc"
++			  "\xad\xe4\x94\xc5\x4a\x29\xae\x70",
+ 		.klen   = 40,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+-		.input  = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0,
+-			    0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x01",
++		.input  = "\x9c\x0f\x15\x2f\x55\xa2\xd8\xf0"
++			  "\xd6\x7b\x8f\x9e\x28\x22\xbc\x41",
+ 		.ilen   = 16,
+-		.result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 5 */
+-		.key    = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff,
+-		  	    0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6,
+-			    0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd,
+-			    0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8,
+-			    0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f },
++		.key    = "\x8a\xd4\xee\x10\x2f\xbd\x81\xff"
++			  "\xf8\x86\xce\xac\x93\xc5\xad\xc6"
++			  "\xa0\x19\x07\xc0\x9d\xf7\xbb\xdd"
++			  "\x52\x13\xb2\xb7\xf0\xff\x11\xd8"
++			  "\xd6\x08\xd0\xcd\x2e\xb1\x17\x6f",
+ 		.klen   = 40,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65,
+-			    0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x02\x00\x00\x00\x00",
++		.input  = "\xd4\x27\x6a\x7f\x14\x91\x3d\x65"
++			  "\xc8\x60\x48\x02\x87\xe3\x34\x06",
+ 		.ilen   = 16,
+-		.result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 6 */
+-		.key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+-		  	    0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+-			    0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+-			    0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+-			    0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+-			    0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
++		.key    = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
++			  "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
++			  "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
++			  "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
++			  "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
++			  "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+ 		.klen   = 48,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+-		.input  = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e,
+-			    0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x01",
++		.input  = "\xbd\x06\xb8\xe1\xdb\x98\x89\x9e"
++			  "\xc4\x98\xe4\x91\xcf\x1c\x70\x2b",
+ 		.ilen   = 16,
+-		.result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.rlen   = 16,
+ 	}, { /* LRW-32-AES 7 */
+-		.key    = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d,
+-		  	    0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8,
+-			    0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d,
+-			    0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7,
+-			    0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4,
+-			    0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c },
++		.key    = "\xfb\x76\x15\xb2\x3d\x80\x89\x1d"
++			  "\xd4\x70\x98\x0b\xc7\x95\x84\xc8"
++			  "\xb2\xfb\x64\xce\x60\x97\x87\x8d"
++			  "\x17\xfc\xe4\x5a\x49\xe8\x30\xb7"
++			  "\x6e\x78\x17\xe7\x2d\x5e\x12\xd4"
++			  "\x60\x64\x04\x7a\xf1\x2f\x9e\x0c",
+ 		.klen   = 48,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f,
+-			    0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x02\x00\x00\x00\x00",
++		.input  = "\x5b\x90\x8e\xc1\xab\xdd\x67\x5f"
++			  "\x3d\x69\x8a\x95\x53\xc8\x9c\xe5",
+ 		.ilen   = 16,
+-		.result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++		.result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x41\x42\x43\x44\x45\x46",
+ 		.rlen   = 16,
+ 	}, {
+ /* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */
+-		.key    = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+-			    0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+-			    0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+-			    0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+-			    0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+-			    0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
++		.key    = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
++			  "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
++			  "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
++			  "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
++			  "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
++			  "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+ 		.klen   = 48,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+-		.input	= { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b,
+-			    0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a,
+-			    0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23,
+-			    0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e,
+-			    0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c,
+-			    0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d,
+-			    0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3,
+-			    0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde,
+-			    0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3,
+-			    0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59,
+-			    0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d,
+-			    0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae,
+-			    0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82,
+-			    0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68,
+-			    0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce,
+-			    0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98,
+-			    0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2,
+-			    0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f,
+-			    0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf,
+-			    0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc,
+-			    0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf,
+-			    0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63,
+-			    0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3,
+-			    0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8,
+-			    0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99,
+-			    0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c,
+-			    0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50,
+-			    0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d,
+-			    0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c,
+-			    0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48,
+-			    0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1,
+-			    0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46,
+-			    0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b,
+-			    0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28,
+-			    0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62,
+-			    0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43,
+-			    0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16,
+-			    0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c,
+-			    0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13,
+-			    0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6,
+-			    0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4,
+-			    0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f,
+-			    0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17,
+-			    0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30,
+-			    0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd,
+-			    0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85,
+-			    0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee,
+-			    0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11,
+-			    0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62,
+-			    0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1,
+-			    0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a,
+-			    0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33,
+-			    0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1,
+-			    0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0,
+-			    0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7,
+-			    0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a,
+-			    0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32,
+-			    0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6,
+-			    0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d,
+-			    0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4,
+-			    0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3,
+-			    0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29,
+-			    0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7,
+-			    0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x01",
++		.input	= "\x1a\x1d\xa9\x30\xad\xf9\x2f\x9b"
++			  "\xb6\x1d\xae\xef\xf0\x2f\xf8\x5a"
++			  "\x39\x3c\xbf\x2a\xb2\x45\xb2\x23"
++			  "\x1b\x63\x3c\xcf\xaa\xbe\xcf\x4e"
++			  "\xfa\xe8\x29\xc2\x20\x68\x2b\x3c"
++			  "\x2e\x8b\xf7\x6e\x25\xbd\xe3\x3d"
++			  "\x66\x27\xd6\xaf\xd6\x64\x3e\xe3"
++			  "\xe8\x58\x46\x97\x39\x51\x07\xde"
++			  "\xcb\x37\xbc\xa9\xc0\x5f\x75\xc3"
++			  "\x0e\x84\x23\x1d\x16\xd4\x1c\x59"
++			  "\x9c\x1a\x02\x55\xab\x3a\x97\x1d"
++			  "\xdf\xdd\xc7\x06\x51\xd7\x70\xae"
++			  "\x23\xc6\x8c\xf5\x1e\xa0\xe5\x82"
++			  "\xb8\xb2\xbf\x04\xa0\x32\x8e\x68"
++			  "\xeb\xaf\x6e\x2d\x94\x22\x2f\xce"
++			  "\x4c\xb5\x59\xe2\xa2\x2f\xa0\x98"
++			  "\x1a\x97\xc6\xd4\xb5\x00\x59\xf2"
++			  "\x84\x14\x72\xb1\x9a\x6e\xa3\x7f"
++			  "\xea\x20\xe7\xcb\x65\x77\x3a\xdf"
++			  "\xc8\x97\x67\x15\xc2\x2a\x27\xcc"
++			  "\x18\x55\xa1\x24\x0b\x24\x24\xaf"
++			  "\x5b\xec\x68\xb8\xc8\xf5\xba\x63"
++			  "\xff\xed\x89\xce\xd5\x3d\x88\xf3"
++			  "\x25\xef\x05\x7c\x3a\xef\xeb\xd8"
++			  "\x7a\x32\x0d\xd1\x1e\x58\x59\x99"
++			  "\x90\x25\xb5\x26\xb0\xe3\x2b\x6c"
++			  "\x4c\xa9\x8b\x84\x4f\x5e\x01\x50"
++			  "\x41\x30\x58\xc5\x62\x74\x52\x1d"
++			  "\x45\x24\x6a\x42\x64\x4f\x97\x1c"
++			  "\xa8\x66\xb5\x6d\x79\xd4\x0d\x48"
++			  "\xc5\x5f\xf3\x90\x32\xdd\xdd\xe1"
++			  "\xe4\xa9\x9f\xfc\xc3\x52\x5a\x46"
++			  "\xe4\x81\x84\x95\x36\x59\x7a\x6b"
++			  "\xaa\xb3\x60\xad\xce\x9f\x9f\x28"
++			  "\xe0\x01\x75\x22\xc4\x4e\xa9\x62"
++			  "\x5c\x62\x0d\x00\xcb\x13\xe8\x43"
++			  "\x72\xd4\x2d\x53\x46\xb5\xd1\x16"
++			  "\x22\x18\xdf\x34\x33\xf5\xd6\x1c"
++			  "\xb8\x79\x78\x97\x94\xff\x72\x13"
++			  "\x4c\x27\xfc\xcb\xbf\x01\x53\xa6"
++			  "\xb4\x50\x6e\xde\xdf\xb5\x43\xa4"
++			  "\x59\xdf\x52\xf9\x7c\xe0\x11\x6f"
++			  "\x2d\x14\x8e\x24\x61\x2c\xe1\x17"
++			  "\xcc\xce\x51\x0c\x19\x8a\x82\x30"
++			  "\x94\xd5\x3d\x6a\x53\x06\x5e\xbd"
++			  "\xb7\xeb\xfa\xfd\x27\x51\xde\x85"
++			  "\x1e\x86\x53\x11\x53\x94\x00\xee"
++			  "\x2b\x8c\x08\x2a\xbf\xdd\xae\x11"
++			  "\xcb\x1e\xa2\x07\x9a\x80\xcf\x62"
++			  "\x9b\x09\xdc\x95\x3c\x96\x8e\xb1"
++			  "\x09\xbd\xe4\xeb\xdb\xca\x70\x7a"
++			  "\x9e\xfa\x31\x18\x45\x3c\x21\x33"
++			  "\xb0\xb3\x2b\xea\xf3\x71\x2d\xe1"
++			  "\x03\xad\x1b\x48\xd4\x67\x27\xf0"
++			  "\x62\xe4\x3d\xfb\x9b\x08\x76\xe7"
++			  "\xdd\x2b\x01\x39\x04\x5a\x58\x7a"
++			  "\xf7\x11\x90\xec\xbd\x51\x5c\x32"
++			  "\x6b\xd7\x35\x39\x02\x6b\xf2\xa6"
++			  "\xd0\x0d\x07\xe1\x06\xc4\x5b\x7d"
++			  "\xe4\x6a\xd7\xee\x15\x1f\x83\xb4"
++			  "\xa3\xa7\x5e\xc3\x90\xb7\xef\xd3"
++			  "\xb7\x4f\xf8\x92\x4c\xb7\x3c\x29"
++			  "\xcd\x7e\x2b\x5d\x43\xea\x42\xe7"
++			  "\x74\x3f\x7d\x58\x88\x75\xde\x3e",
+ 		.ilen   = 512,
+-		.result	= { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac,
+-			    0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c,
+-			    0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8,
+-			    0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6,
+-			    0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90,
+-			    0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6,
+-			    0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04,
+-			    0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab,
+-			    0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c,
+-			    0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04,
+-			    0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6,
+-			    0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03,
+-			    0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65,
+-			    0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01,
+-			    0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1,
+-			    0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50,
+-			    0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd,
+-			    0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3,
+-			    0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5,
+-			    0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74,
+-			    0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53,
+-			    0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40,
+-			    0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5,
+-			    0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72,
+-			    0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda,
+-			    0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd,
+-			    0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60,
+-			    0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09,
+-			    0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9,
+-			    0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8,
+-			    0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8,
+-			    0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10,
+-			    0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1,
+-			    0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c,
+-			    0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e,
+-			    0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f,
+-			    0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e,
+-			    0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22,
+-			    0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78,
+-			    0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5,
+-			    0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41,
+-			    0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75,
+-			    0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43,
+-			    0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe,
+-			    0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65,
+-			    0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9,
+-			    0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4,
+-			    0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a,
+-			    0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d,
+-			    0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf,
+-			    0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b,
+-			    0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7,
+-			    0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85,
+-			    0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb,
+-			    0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8,
+-			    0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24,
+-			    0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01,
+-			    0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce,
+-			    0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6,
+-			    0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32,
+-			    0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45,
+-			    0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6,
+-			    0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4,
+-			    0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a },
++		.result	= "\x05\x11\xb7\x18\xab\xc6\x2d\xac"
++			  "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c"
++			  "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8"
++			  "\x50\x38\x1f\x71\x49\xb6\x57\xd6"
++			  "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90"
++			  "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6"
++			  "\xad\x1e\x9e\x20\x5f\x38\xbe\x04"
++			  "\xda\x10\x8e\xed\xa2\xa4\x87\xab"
++			  "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c"
++			  "\xc9\xac\x42\x31\x95\x7c\xc9\x04"
++			  "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6"
++			  "\x15\xd7\x3f\x4f\x2f\x66\x69\x03"
++			  "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65"
++			  "\x4c\x96\x12\xed\x7c\x92\x03\x01"
++			  "\x6f\xbc\x35\x93\xac\xf1\x27\xf1"
++			  "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50"
++			  "\x89\xa4\x8e\x66\x44\x85\xcc\xfd"
++			  "\x33\x14\x70\xe3\x96\xb2\xc3\xd3"
++			  "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5"
++			  "\x2d\x64\x75\xdd\xb4\x54\xe6\x74"
++			  "\x8c\xd3\x9d\x9e\x86\xab\x51\x53"
++			  "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40"
++			  "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5"
++			  "\x76\x12\x73\x44\x1a\x56\xd7\x72"
++			  "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda"
++			  "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd"
++			  "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60"
++			  "\x1a\xe2\x70\x85\x58\xc2\x1b\x09"
++			  "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9"
++			  "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8"
++			  "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8"
++			  "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10"
++			  "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1"
++			  "\x90\x3e\x76\x4a\x74\xa4\x21\x2c"
++			  "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e"
++			  "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f"
++			  "\x8d\x23\x31\x74\x84\xeb\x88\x6e"
++			  "\xcc\xb9\xbc\x22\x83\x19\x07\x22"
++			  "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78"
++			  "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5"
++			  "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41"
++			  "\x3c\xce\x8f\x42\x60\x71\xa7\x75"
++			  "\x08\x40\x65\x8a\x82\xbf\xf5\x43"
++			  "\x71\x96\xa9\x4d\x44\x8a\x20\xbe"
++			  "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65"
++			  "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9"
++			  "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4"
++			  "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a"
++			  "\x62\x73\x65\xfd\x46\x63\x25\x3d"
++			  "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf"
++			  "\x24\xf3\xb4\xac\x64\xba\xdf\x4b"
++			  "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7"
++			  "\xc5\x68\x77\x84\x32\x2b\xcc\x85"
++			  "\x74\x96\xf0\x12\x77\x61\xb9\xeb"
++			  "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8"
++			  "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24"
++			  "\xda\x39\x87\x45\xc0\x2b\xbb\x01"
++			  "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce"
++			  "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6"
++			  "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32"
++			  "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45"
++			  "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6"
++			  "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4"
++			  "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
+ 		.rlen   = 512,
+ 	}
+ };
+@@ -3060,196 +3084,196 @@ static struct cipher_testvec aes_lrw_dec_tv_template[] = {
+ static struct cipher_testvec aes_xts_enc_tv_template[] = {
+ 	/* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */
+ 	{ /* XTS-AES 1 */
+-		.key    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key    = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input  = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen   = 32,
+-		.result = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+-			    0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+-			    0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+-			    0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
++		.result = "\x91\x7c\xf6\x9e\xbd\x68\xb2\xec"
++			  "\x9b\x9f\xe9\xa3\xea\xdd\xa6\x92"
++			  "\xcd\x43\xd2\xf5\x95\x98\xed\x85"
++			  "\x8c\x02\xc2\x65\x2f\xbf\x92\x2e",
+ 		.rlen   = 32,
+ 	}, { /* XTS-AES 2 */
+-		.key    = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+-			    0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+-			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+-			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
++		.key    = "\x11\x11\x11\x11\x11\x11\x11\x11"
++			  "\x11\x11\x11\x11\x11\x11\x11\x11"
++			  "\x22\x22\x22\x22\x22\x22\x22\x22"
++			  "\x22\x22\x22\x22\x22\x22\x22\x22",
+ 		.klen   = 32,
+-		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
++		.iv     = "\x33\x33\x33\x33\x33\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input  = "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44",
+ 		.ilen   = 32,
+-		.result = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+-			    0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+-			    0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+-			    0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
++		.result = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e"
++			  "\x39\x33\x40\x38\xac\xef\x83\x8b"
++			  "\xfb\x18\x6f\xff\x74\x80\xad\xc4"
++			  "\x28\x93\x82\xec\xd6\xd3\x94\xf0",
+ 		.rlen   = 32,
+ 	}, { /* XTS-AES 3 */
+-		.key    = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+-			    0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+-			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+-			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
++		.key    = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8"
++			  "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
++			  "\x22\x22\x22\x22\x22\x22\x22\x22"
++			  "\x22\x22\x22\x22\x22\x22\x22\x22",
+ 		.klen   = 32,
+-		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
++		.iv     = "\x33\x33\x33\x33\x33\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input  = "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44",
+ 		.ilen   = 32,
+-		.result = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+-			    0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+-			    0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+-			    0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
++		.result = "\xaf\x85\x33\x6b\x59\x7a\xfc\x1a"
++			  "\x90\x0b\x2e\xb2\x1e\xc9\x49\xd2"
++			  "\x92\xdf\x4c\x04\x7e\x0b\x21\x53"
++			  "\x21\x86\xa5\x97\x1a\x22\x7a\x89",
+ 		.rlen   = 32,
+ 	}, { /* XTS-AES 4 */
+-		.key    = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
+-			    0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
+-			    0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
+-			    0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 },
++		.key    = "\x27\x18\x28\x18\x28\x45\x90\x45"
++			  "\x23\x53\x60\x28\x74\x71\x35\x26"
++			  "\x31\x41\x59\x26\x53\x58\x97\x93"
++			  "\x23\x84\x62\x64\x33\x83\x27\x95",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+-			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+-			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+-			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+-			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+-			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+-			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+-			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+-			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+-			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+-			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+-			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+-			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+-			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+-			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+-			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+-			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+-			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+-			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+-			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+-			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+-			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+-			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+-			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+-			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+-			    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+-			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+-			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+-			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+-			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+-			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+-			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+-			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+-			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+-			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+-			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+-			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+-			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+-			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+-			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+-			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+-			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+-			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+-			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+-			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+-			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+-			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+-			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+-			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+-			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input  = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			  "\x20\x21\x22\x23\x24\x25\x26\x27"
++			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++			  "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++			  "\x40\x41\x42\x43\x44\x45\x46\x47"
++			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++			  "\x50\x51\x52\x53\x54\x55\x56\x57"
++			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++			  "\x60\x61\x62\x63\x64\x65\x66\x67"
++			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++			  "\x70\x71\x72\x73\x74\x75\x76\x77"
++			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++			  "\x80\x81\x82\x83\x84\x85\x86\x87"
++			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++			  "\x90\x91\x92\x93\x94\x95\x96\x97"
++			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
++			  "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			  "\x20\x21\x22\x23\x24\x25\x26\x27"
++			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++			  "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++			  "\x40\x41\x42\x43\x44\x45\x46\x47"
++			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++			  "\x50\x51\x52\x53\x54\x55\x56\x57"
++			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++			  "\x60\x61\x62\x63\x64\x65\x66\x67"
++			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++			  "\x70\x71\x72\x73\x74\x75\x76\x77"
++			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++			  "\x80\x81\x82\x83\x84\x85\x86\x87"
++			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++			  "\x90\x91\x92\x93\x94\x95\x96\x97"
++			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ 		.ilen   = 512,
+-		.result = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
+-			    0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
+-			    0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
+-			    0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
+-			    0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
+-			    0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
+-			    0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
+-			    0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
+-			    0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5,
+-			    0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5,
+-			    0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc,
+-			    0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce,
+-			    0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4,
+-			    0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84,
+-			    0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a,
+-			    0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65,
+-			    0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89,
+-			    0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51,
+-			    0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15,
+-			    0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8,
+-			    0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed,
+-			    0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91,
+-			    0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e,
+-			    0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34,
+-			    0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b,
+-			    0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5,
+-			    0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4,
+-			    0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c,
+-			    0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd,
+-			    0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3,
+-			    0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f,
+-			    0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e,
+-			    0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91,
+-			    0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19,
+-			    0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1,
+-			    0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc,
+-			    0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed,
+-			    0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde,
+-			    0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98,
+-			    0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3,
+-			    0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca,
+-			    0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6,
+-			    0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc,
+-			    0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44,
+-			    0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0,
+-			    0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95,
+-			    0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4,
+-			    0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd,
+-			    0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13,
+-			    0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7,
+-			    0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a,
+-			    0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52,
+-			    0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a,
+-			    0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38,
+-			    0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e,
+-			    0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e,
+-			    0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad,
+-			    0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8,
+-			    0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c,
+-			    0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d,
+-			    0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f,
+-			    0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2,
+-			    0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea,
+-			    0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 },
++		.result = "\x27\xa7\x47\x9b\xef\xa1\xd4\x76"
++			  "\x48\x9f\x30\x8c\xd4\xcf\xa6\xe2"
++			  "\xa9\x6e\x4b\xbe\x32\x08\xff\x25"
++			  "\x28\x7d\xd3\x81\x96\x16\xe8\x9c"
++			  "\xc7\x8c\xf7\xf5\xe5\x43\x44\x5f"
++			  "\x83\x33\xd8\xfa\x7f\x56\x00\x00"
++			  "\x05\x27\x9f\xa5\xd8\xb5\xe4\xad"
++			  "\x40\xe7\x36\xdd\xb4\xd3\x54\x12"
++			  "\x32\x80\x63\xfd\x2a\xab\x53\xe5"
++			  "\xea\x1e\x0a\x9f\x33\x25\x00\xa5"
++			  "\xdf\x94\x87\xd0\x7a\x5c\x92\xcc"
++			  "\x51\x2c\x88\x66\xc7\xe8\x60\xce"
++			  "\x93\xfd\xf1\x66\xa2\x49\x12\xb4"
++			  "\x22\x97\x61\x46\xae\x20\xce\x84"
++			  "\x6b\xb7\xdc\x9b\xa9\x4a\x76\x7a"
++			  "\xae\xf2\x0c\x0d\x61\xad\x02\x65"
++			  "\x5e\xa9\x2d\xc4\xc4\xe4\x1a\x89"
++			  "\x52\xc6\x51\xd3\x31\x74\xbe\x51"
++			  "\xa1\x0c\x42\x11\x10\xe6\xd8\x15"
++			  "\x88\xed\xe8\x21\x03\xa2\x52\xd8"
++			  "\xa7\x50\xe8\x76\x8d\xef\xff\xed"
++			  "\x91\x22\x81\x0a\xae\xb9\x9f\x91"
++			  "\x72\xaf\x82\xb6\x04\xdc\x4b\x8e"
++			  "\x51\xbc\xb0\x82\x35\xa6\xf4\x34"
++			  "\x13\x32\xe4\xca\x60\x48\x2a\x4b"
++			  "\xa1\xa0\x3b\x3e\x65\x00\x8f\xc5"
++			  "\xda\x76\xb7\x0b\xf1\x69\x0d\xb4"
++			  "\xea\xe2\x9c\x5f\x1b\xad\xd0\x3c"
++			  "\x5c\xcf\x2a\x55\xd7\x05\xdd\xcd"
++			  "\x86\xd4\x49\x51\x1c\xeb\x7e\xc3"
++			  "\x0b\xf1\x2b\x1f\xa3\x5b\x91\x3f"
++			  "\x9f\x74\x7a\x8a\xfd\x1b\x13\x0e"
++			  "\x94\xbf\xf9\x4e\xff\xd0\x1a\x91"
++			  "\x73\x5c\xa1\x72\x6a\xcd\x0b\x19"
++			  "\x7c\x4e\x5b\x03\x39\x36\x97\xe1"
++			  "\x26\x82\x6f\xb6\xbb\xde\x8e\xcc"
++			  "\x1e\x08\x29\x85\x16\xe2\xc9\xed"
++			  "\x03\xff\x3c\x1b\x78\x60\xf6\xde"
++			  "\x76\xd4\xce\xcd\x94\xc8\x11\x98"
++			  "\x55\xef\x52\x97\xca\x67\xe9\xf3"
++			  "\xe7\xff\x72\xb1\xe9\x97\x85\xca"
++			  "\x0a\x7e\x77\x20\xc5\xb3\x6d\xc6"
++			  "\xd7\x2c\xac\x95\x74\xc8\xcb\xbc"
++			  "\x2f\x80\x1e\x23\xe5\x6f\xd3\x44"
++			  "\xb0\x7f\x22\x15\x4b\xeb\xa0\xf0"
++			  "\x8c\xe8\x89\x1e\x64\x3e\xd9\x95"
++			  "\xc9\x4d\x9a\x69\xc9\xf1\xb5\xf4"
++			  "\x99\x02\x7a\x78\x57\x2a\xee\xbd"
++			  "\x74\xd2\x0c\xc3\x98\x81\xc2\x13"
++			  "\xee\x77\x0b\x10\x10\xe4\xbe\xa7"
++			  "\x18\x84\x69\x77\xae\x11\x9f\x7a"
++			  "\x02\x3a\xb5\x8c\xca\x0a\xd7\x52"
++			  "\xaf\xe6\x56\xbb\x3c\x17\x25\x6a"
++			  "\x9f\x6e\x9b\xf1\x9f\xdd\x5a\x38"
++			  "\xfc\x82\xbb\xe8\x72\xc5\x53\x9e"
++			  "\xdb\x60\x9e\xf4\xf7\x9c\x20\x3e"
++			  "\xbb\x14\x0f\x2e\x58\x3c\xb2\xad"
++			  "\x15\xb4\xaa\x5b\x65\x50\x16\xa8"
++			  "\x44\x92\x77\xdb\xd4\x77\xef\x2c"
++			  "\x8d\x6c\x01\x7d\xb7\x38\xb1\x8d"
++			  "\xeb\x4a\x42\x7d\x19\x23\xce\x3f"
++			  "\xf2\x62\x73\x57\x79\xa4\x18\xf2"
++			  "\x0a\x28\x2d\xf9\x20\x14\x7b\xea"
++			  "\xbe\x42\x1e\xe5\x31\x9d\x05\x68",
+ 		.rlen   = 512,
+ 	}
+ };
+@@ -3257,196 +3281,196 @@ static struct cipher_testvec aes_xts_enc_tv_template[] = {
+ static struct cipher_testvec aes_xts_dec_tv_template[] = {
+ 	/* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */
+ 	{ /* XTS-AES 1 */
+-		.key    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key    = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+-			   0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+-			   0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+-			   0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input = "\x91\x7c\xf6\x9e\xbd\x68\xb2\xec"
++			 "\x9b\x9f\xe9\xa3\xea\xdd\xa6\x92"
++			 "\xcd\x43\xd2\xf5\x95\x98\xed\x85"
++			 "\x8c\x02\xc2\x65\x2f\xbf\x92\x2e",
+ 		.ilen   = 32,
+-		.result  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.result  = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			   "\x00\x00\x00\x00\x00\x00\x00\x00"
++			   "\x00\x00\x00\x00\x00\x00\x00\x00"
++			   "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.rlen   = 32,
+ 	}, { /* XTS-AES 2 */
+-		.key    = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+-			    0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+-			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+-			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
++		.key    = "\x11\x11\x11\x11\x11\x11\x11\x11"
++			  "\x11\x11\x11\x11\x11\x11\x11\x11"
++			  "\x22\x22\x22\x22\x22\x22\x22\x22"
++			  "\x22\x22\x22\x22\x22\x22\x22\x22",
+ 		.klen   = 32,
+-		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+-			    0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+-			    0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+-			    0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
++		.iv     = "\x33\x33\x33\x33\x33\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input  = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e"
++			  "\x39\x33\x40\x38\xac\xef\x83\x8b"
++			  "\xfb\x18\x6f\xff\x74\x80\xad\xc4"
++			  "\x28\x93\x82\xec\xd6\xd3\x94\xf0",
+ 		.ilen   = 32,
+-		.result = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
++		.result = "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44",
+ 		.rlen   = 32,
+ 	}, { /* XTS-AES 3 */
+-		.key    = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+-			    0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+-			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+-			    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
++		.key    = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8"
++			  "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
++			  "\x22\x22\x22\x22\x22\x22\x22\x22"
++			  "\x22\x22\x22\x22\x22\x22\x22\x22",
+ 		.klen   = 32,
+-		.iv     = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+-			    0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+-			    0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+-			    0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
++		.iv     = "\x33\x33\x33\x33\x33\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input = "\xaf\x85\x33\x6b\x59\x7a\xfc\x1a"
++			  "\x90\x0b\x2e\xb2\x1e\xc9\x49\xd2"
++			  "\x92\xdf\x4c\x04\x7e\x0b\x21\x53"
++			  "\x21\x86\xa5\x97\x1a\x22\x7a\x89",
+ 		.ilen   = 32,
+-		.result  = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+-			    0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
++		.result  = "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44"
++			  "\x44\x44\x44\x44\x44\x44\x44\x44",
+ 		.rlen   = 32,
+ 	}, { /* XTS-AES 4 */
+-		.key    = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
+-			    0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
+-			    0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
+-			    0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 },
++		.key    = "\x27\x18\x28\x18\x28\x45\x90\x45"
++			  "\x23\x53\x60\x28\x74\x71\x35\x26"
++			  "\x31\x41\x59\x26\x53\x58\x97\x93"
++			  "\x23\x84\x62\x64\x33\x83\x27\x95",
+ 		.klen   = 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input  = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
+-			    0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
+-			    0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
+-			    0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
+-			    0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
+-			    0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
+-			    0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
+-			    0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
+-			    0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5,
+-			    0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5,
+-			    0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc,
+-			    0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce,
+-			    0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4,
+-			    0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84,
+-			    0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a,
+-			    0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65,
+-			    0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89,
+-			    0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51,
+-			    0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15,
+-			    0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8,
+-			    0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed,
+-			    0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91,
+-			    0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e,
+-			    0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34,
+-			    0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b,
+-			    0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5,
+-			    0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4,
+-			    0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c,
+-			    0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd,
+-			    0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3,
+-			    0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f,
+-			    0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e,
+-			    0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91,
+-			    0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19,
+-			    0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1,
+-			    0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc,
+-			    0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed,
+-			    0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde,
+-			    0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98,
+-			    0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3,
+-			    0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca,
+-			    0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6,
+-			    0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc,
+-			    0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44,
+-			    0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0,
+-			    0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95,
+-			    0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4,
+-			    0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd,
+-			    0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13,
+-			    0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7,
+-			    0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a,
+-			    0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52,
+-			    0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a,
+-			    0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38,
+-			    0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e,
+-			    0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e,
+-			    0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad,
+-			    0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8,
+-			    0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c,
+-			    0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d,
+-			    0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f,
+-			    0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2,
+-			    0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea,
+-			    0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input  = "\x27\xa7\x47\x9b\xef\xa1\xd4\x76"
++			  "\x48\x9f\x30\x8c\xd4\xcf\xa6\xe2"
++			  "\xa9\x6e\x4b\xbe\x32\x08\xff\x25"
++			  "\x28\x7d\xd3\x81\x96\x16\xe8\x9c"
++			  "\xc7\x8c\xf7\xf5\xe5\x43\x44\x5f"
++			  "\x83\x33\xd8\xfa\x7f\x56\x00\x00"
++			  "\x05\x27\x9f\xa5\xd8\xb5\xe4\xad"
++			  "\x40\xe7\x36\xdd\xb4\xd3\x54\x12"
++			  "\x32\x80\x63\xfd\x2a\xab\x53\xe5"
++			  "\xea\x1e\x0a\x9f\x33\x25\x00\xa5"
++			  "\xdf\x94\x87\xd0\x7a\x5c\x92\xcc"
++			  "\x51\x2c\x88\x66\xc7\xe8\x60\xce"
++			  "\x93\xfd\xf1\x66\xa2\x49\x12\xb4"
++			  "\x22\x97\x61\x46\xae\x20\xce\x84"
++			  "\x6b\xb7\xdc\x9b\xa9\x4a\x76\x7a"
++			  "\xae\xf2\x0c\x0d\x61\xad\x02\x65"
++			  "\x5e\xa9\x2d\xc4\xc4\xe4\x1a\x89"
++			  "\x52\xc6\x51\xd3\x31\x74\xbe\x51"
++			  "\xa1\x0c\x42\x11\x10\xe6\xd8\x15"
++			  "\x88\xed\xe8\x21\x03\xa2\x52\xd8"
++			  "\xa7\x50\xe8\x76\x8d\xef\xff\xed"
++			  "\x91\x22\x81\x0a\xae\xb9\x9f\x91"
++			  "\x72\xaf\x82\xb6\x04\xdc\x4b\x8e"
++			  "\x51\xbc\xb0\x82\x35\xa6\xf4\x34"
++			  "\x13\x32\xe4\xca\x60\x48\x2a\x4b"
++			  "\xa1\xa0\x3b\x3e\x65\x00\x8f\xc5"
++			  "\xda\x76\xb7\x0b\xf1\x69\x0d\xb4"
++			  "\xea\xe2\x9c\x5f\x1b\xad\xd0\x3c"
++			  "\x5c\xcf\x2a\x55\xd7\x05\xdd\xcd"
++			  "\x86\xd4\x49\x51\x1c\xeb\x7e\xc3"
++			  "\x0b\xf1\x2b\x1f\xa3\x5b\x91\x3f"
++			  "\x9f\x74\x7a\x8a\xfd\x1b\x13\x0e"
++			  "\x94\xbf\xf9\x4e\xff\xd0\x1a\x91"
++			  "\x73\x5c\xa1\x72\x6a\xcd\x0b\x19"
++			  "\x7c\x4e\x5b\x03\x39\x36\x97\xe1"
++			  "\x26\x82\x6f\xb6\xbb\xde\x8e\xcc"
++			  "\x1e\x08\x29\x85\x16\xe2\xc9\xed"
++			  "\x03\xff\x3c\x1b\x78\x60\xf6\xde"
++			  "\x76\xd4\xce\xcd\x94\xc8\x11\x98"
++			  "\x55\xef\x52\x97\xca\x67\xe9\xf3"
++			  "\xe7\xff\x72\xb1\xe9\x97\x85\xca"
++			  "\x0a\x7e\x77\x20\xc5\xb3\x6d\xc6"
++			  "\xd7\x2c\xac\x95\x74\xc8\xcb\xbc"
++			  "\x2f\x80\x1e\x23\xe5\x6f\xd3\x44"
++			  "\xb0\x7f\x22\x15\x4b\xeb\xa0\xf0"
++			  "\x8c\xe8\x89\x1e\x64\x3e\xd9\x95"
++			  "\xc9\x4d\x9a\x69\xc9\xf1\xb5\xf4"
++			  "\x99\x02\x7a\x78\x57\x2a\xee\xbd"
++			  "\x74\xd2\x0c\xc3\x98\x81\xc2\x13"
++			  "\xee\x77\x0b\x10\x10\xe4\xbe\xa7"
++			  "\x18\x84\x69\x77\xae\x11\x9f\x7a"
++			  "\x02\x3a\xb5\x8c\xca\x0a\xd7\x52"
++			  "\xaf\xe6\x56\xbb\x3c\x17\x25\x6a"
++			  "\x9f\x6e\x9b\xf1\x9f\xdd\x5a\x38"
++			  "\xfc\x82\xbb\xe8\x72\xc5\x53\x9e"
++			  "\xdb\x60\x9e\xf4\xf7\x9c\x20\x3e"
++			  "\xbb\x14\x0f\x2e\x58\x3c\xb2\xad"
++			  "\x15\xb4\xaa\x5b\x65\x50\x16\xa8"
++			  "\x44\x92\x77\xdb\xd4\x77\xef\x2c"
++			  "\x8d\x6c\x01\x7d\xb7\x38\xb1\x8d"
++			  "\xeb\x4a\x42\x7d\x19\x23\xce\x3f"
++			  "\xf2\x62\x73\x57\x79\xa4\x18\xf2"
++			  "\x0a\x28\x2d\xf9\x20\x14\x7b\xea"
++			  "\xbe\x42\x1e\xe5\x31\x9d\x05\x68",
+ 		.ilen   = 512,
+-		.result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+-			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+-			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+-			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+-			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+-			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+-			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+-			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+-			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+-			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+-			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+-			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+-			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+-			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+-			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+-			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+-			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+-			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+-			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+-			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+-			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+-			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+-			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+-			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+-			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+-			    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+-			    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+-			    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+-			    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+-			    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+-			    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+-			    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+-			    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+-			    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+-			    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+-			    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+-			    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+-			    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+-			    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+-			    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+-			    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+-			    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+-			    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+-			    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+-			    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+-			    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+-			    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+-			    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+-			    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+-			    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
++		.result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			  "\x20\x21\x22\x23\x24\x25\x26\x27"
++			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++			  "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++			  "\x40\x41\x42\x43\x44\x45\x46\x47"
++			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++			  "\x50\x51\x52\x53\x54\x55\x56\x57"
++			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++			  "\x60\x61\x62\x63\x64\x65\x66\x67"
++			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++			  "\x70\x71\x72\x73\x74\x75\x76\x77"
++			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++			  "\x80\x81\x82\x83\x84\x85\x86\x87"
++			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++			  "\x90\x91\x92\x93\x94\x95\x96\x97"
++			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
++			  "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			  "\x20\x21\x22\x23\x24\x25\x26\x27"
++			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++			  "\x30\x31\x32\x33\x34\x35\x36\x37"
++			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++			  "\x40\x41\x42\x43\x44\x45\x46\x47"
++			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++			  "\x50\x51\x52\x53\x54\x55\x56\x57"
++			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++			  "\x60\x61\x62\x63\x64\x65\x66\x67"
++			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++			  "\x70\x71\x72\x73\x74\x75\x76\x77"
++			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++			  "\x80\x81\x82\x83\x84\x85\x86\x87"
++			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++			  "\x90\x91\x92\x93\x94\x95\x96\x97"
++			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ 		.rlen   = 512,
+ 	}
+ };
+@@ -3454,1836 +3478,1841 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
+ 
+ static struct cipher_testvec aes_ctr_enc_tv_template[] = {
+ 	{ /* From RFC 3686 */
+-		.key	= { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
+-			    0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
+-			    0x00, 0x00, 0x00, 0x30 },
++		.key	= "\xae\x68\x52\xf8\x12\x10\x67\xcc"
++			  "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e"
++			  "\x00\x00\x00\x30",
+ 		.klen	= 20,
+-		.iv 	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input 	= { "Single block msg" },
++		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input	= "Single block msg",
+ 		.ilen	= 16,
+-		.result = { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
+-			    0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
++		.result = "\xe4\x09\x5d\x4f\xb7\xa7\xb3\x79"
++			  "\x2d\x61\x75\xa3\x26\x13\x11\xb8",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
+-			    0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
+-			    0x00, 0x6c, 0xb6, 0xdb },
++		.key	= "\x7e\x24\x06\x78\x17\xfa\xe0\xd7"
++			  "\x43\xd6\xce\x1f\x32\x53\x91\x63"
++			  "\x00\x6c\xb6\xdb",
+ 		.klen	= 20,
+-		.iv 	= { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
+-		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+-		.ilen 	= 32,
+-		.result = { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
+-			    0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
+-			    0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
+-			    0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
++		.iv	= "\xc0\x54\x3b\x59\xda\x48\xd9\x0b",
++		.input	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
++		.ilen	= 32,
++		.result = "\x51\x04\xa1\x06\x16\x8a\x72\xd9"
++			  "\x79\x0d\x41\xee\x8e\xda\xd3\x88"
++			  "\xeb\x2e\x1e\xfc\x46\xda\x57\xc8"
++			  "\xfc\xe6\x30\xdf\x91\x41\xbe\x28",
+ 		.rlen	= 32,
+ 	}, {
+-		.key 	= { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
+-			    0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
+-			    0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
+-			    0x00, 0x00, 0x00, 0x48 },
+-		.klen 	= 28,
+-		.iv	= { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
+-		.input	= { "Single block msg" },
+-		.ilen 	= 16,
+-		.result	= { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
+-			    0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
++		.key	= "\x16\xaf\x5b\x14\x5f\xc9\xf5\x79"
++			  "\xc1\x75\xf9\x3e\x3b\xfb\x0e\xed"
++			  "\x86\x3d\x06\xcc\xfd\xb7\x85\x15"
++			  "\x00\x00\x00\x48",
++		.klen	= 28,
++		.iv	= "\x36\x73\x3c\x14\x7d\x6d\x93\xcb",
++		.input	= "Single block msg",
++		.ilen	= 16,
++		.result	= "\x4b\x55\x38\x4f\xe2\x59\xc9\xc8"
++			  "\x4e\x79\x35\xa0\x03\xcb\xe9\x28",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
+-			    0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
+-			    0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
+-			    0x00, 0x96, 0xb0, 0x3b },
++		.key	= "\x7c\x5c\xb2\x40\x1b\x3d\xc3\x3c"
++			  "\x19\xe7\x34\x08\x19\xe0\xf6\x9c"
++			  "\x67\x8c\x3d\xb8\xe6\xf6\xa9\x1a"
++			  "\x00\x96\xb0\x3b",
+ 		.klen	= 28,
+-		.iv 	= { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
+-		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.iv	= "\x02\x0c\x6e\xad\xc2\xcb\x50\x0d",
++		.input	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.ilen	= 32,
+-		.result	= { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
+-			    0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
+-			    0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
+-			    0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
+-		.rlen 	= 32,
+-	}, {
+-		.key 	= { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
+-			    0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
+-			    0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
+-			    0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
+-			    0x00, 0x00, 0x00, 0x60 },
++		.result	= "\x45\x32\x43\xfc\x60\x9b\x23\x32"
++			  "\x7e\xdf\xaa\xfa\x71\x31\xcd\x9f"
++			  "\x84\x90\x70\x1c\x5a\xd4\xa7\x9c"
++			  "\xfc\x1f\xe0\xff\x42\xf4\xfb\x00",
++		.rlen	= 32,
++	}, {
++		.key	= "\x77\x6b\xef\xf2\x85\x1d\xb0\x6f"
++			  "\x4c\x8a\x05\x42\xc8\x69\x6f\x6c"
++			  "\x6a\x81\xaf\x1e\xec\x96\xb4\xd3"
++			  "\x7f\xc1\xd6\x89\xe6\xc1\xc1\x04"
++			  "\x00\x00\x00\x60",
+ 		.klen	= 36,
+-		.iv 	= { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
+-		.input	= { "Single block msg" },
++		.iv	= "\xdb\x56\x72\xc9\x7a\xa8\xf0\xb2",
++		.input	= "Single block msg",
+ 		.ilen	= 16,
+-		.result = { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
+-			    0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
+-		.rlen 	= 16,
+-	}, {
+-		.key	= { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
+-			    0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
+-			    0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
+-			    0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
+-			    0x00, 0xfa, 0xac, 0x24 },
+-		.klen 	= 36,
+-		.iv	= { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
+-		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.result = "\x14\x5a\xd0\x1d\xbf\x82\x4e\xc7"
++			  "\x56\x08\x63\xdc\x71\xe3\xe0\xc0",
++		.rlen	= 16,
++	}, {
++		.key	= "\xf6\xd6\x6d\x6b\xd5\x2d\x59\xbb"
++			  "\x07\x96\x36\x58\x79\xef\xf8\x86"
++			  "\xc6\x6d\xd5\x1a\x5b\x6a\x99\x74"
++			  "\x4b\x50\x59\x0c\x87\xa2\x38\x84"
++			  "\x00\xfa\xac\x24",
++		.klen	= 36,
++		.iv	= "\xc1\x58\x5e\xf1\x5a\x43\xd8\x75",
++		.input	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.ilen	= 32,
+-		.result = { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
+-			    0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
+-			    0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
+-			    0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
++		.result = "\xf0\x5e\x23\x1b\x38\x94\x61\x2c"
++			  "\x49\xee\x00\x0b\x80\x4e\xb2\xa9"
++			  "\xb8\x30\x6b\x50\x8f\x83\x9d\x6a"
++			  "\x55\x30\x83\x1d\x93\x44\xaf\x1c",
+ 		.rlen	= 32,
+ 	}, {
+ 	// generated using Crypto++
+-		.key = {
+-			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			0x00, 0x00, 0x00, 0x00,
+-		},
++		.key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			"\x10\x11\x12\x13\x14\x15\x16\x17"
++			"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			"\x00\x00\x00\x00",
+ 		.klen = 32 + 4,
+-		.iv = {
+-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-		},
+-		.input = {
+-			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+-			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+-			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+-			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+-			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+-			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+-			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+-			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+-			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+-			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+-			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+-			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+-			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+-			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+-			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+-			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+-			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+-			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+-			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+-			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+-			0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+-			0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+-			0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+-			0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+-			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+-			0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+-			0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
+-			0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
+-			0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
+-			0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
+-			0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
+-			0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
+-			0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
+-			0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
+-			0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
+-			0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
+-			0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
+-			0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
+-			0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
+-			0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
+-			0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
+-			0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
+-			0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
+-			0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
+-			0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
+-			0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
+-			0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
+-			0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
+-			0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
+-			0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
+-			0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
+-			0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
+-			0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
+-			0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
+-			0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
+-			0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
+-			0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
+-			0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
+-			0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
+-			0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
+-			0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
+-			0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
+-			0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
+-			0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
+-			0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
+-			0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
+-			0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
+-			0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
+-			0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
+-			0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
+-			0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
+-			0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
+-			0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
+-			0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
+-			0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
+-			0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
+-			0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
+-			0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
+-			0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
+-			0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
+-			0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
+-			0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
+-			0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
+-			0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
+-			0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
+-			0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
+-			0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
+-			0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
+-			0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
+-			0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
+-			0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
+-			0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
+-			0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
+-			0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
+-			0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
+-			0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
+-			0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
+-			0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
+-			0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
+-			0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
+-			0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
+-			0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
+-			0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
+-			0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
+-			0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
+-			0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
+-			0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
+-			0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
+-			0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
+-			0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
+-			0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
+-			0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
+-			0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
+-			0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
+-			0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
+-			0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
+-			0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
+-			0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
+-			0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
+-			0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
+-			0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
+-			0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
+-			0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+-			0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
+-			0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
+-			0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
+-			0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
+-			0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
+-			0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
+-			0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
+-			0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
+-			0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
+-			0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
+-			0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
+-			0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
+-			0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
+-			0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
+-			0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
+-			0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
+-			0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
+-			0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
+-			0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
+-			0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
+-			0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
+-			0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
+-			0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
+-			0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
+-			0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
+-			0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
+-			0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
+-			0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
+-			0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
+-			0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
+-			0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
+-			0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
+-			0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
+-			0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
+-			0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
+-			0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
+-			0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
+-			0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
+-			0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
+-			0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
+-			0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
+-			0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
+-			0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
+-			0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
+-			0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
+-			0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
+-			0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
+-			0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
+-			0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
+-			0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
+-			0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
+-			0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
+-			0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
+-			0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
+-			0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
+-			0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
+-			0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
+-			0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
+-			0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
+-			0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
+-			0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
+-			0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
+-			0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
+-			0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
+-			0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
+-			0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
+-			0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
+-			0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
+-			0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
+-			0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
+-			0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
+-			0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
+-			0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
+-			0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
+-			0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
+-			0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
+-			0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
+-			0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
+-			0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
+-			0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
+-			0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
+-			0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
+-			0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
+-			0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
+-			0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
+-			0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
+-			0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
+-			0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
+-			0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
+-			0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
+-			0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
+-			0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
+-			0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
+-			0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
+-			0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
+-			0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
+-			0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
+-			0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
+-			0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
+-			0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
+-			0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
+-			0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
+-			0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
+-			0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
+-			0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
+-			0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
+-			0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
+-			0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
+-			0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
+-			0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
+-			0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
+-			0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
+-			0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
+-			0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
+-			0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
+-			0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
+-			0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
+-			0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
+-			0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
+-			0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
+-			0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
+-			0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
+-			0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
+-			0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
+-			0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
+-			0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
+-			0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
+-			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+-			0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
+-			0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
+-			0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
+-			0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
+-			0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
+-			0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
+-			0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
+-			0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
+-			0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
+-			0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
+-			0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
+-			0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
+-			0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
+-			0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
+-			0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
+-			0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
+-			0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
+-			0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
+-			0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
+-			0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
+-			0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
+-			0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
+-			0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
+-			0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
+-			0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
+-			0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
+-			0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
+-			0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
+-			0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
+-			0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
+-			0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
+-			0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
+-			0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
+-			0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
+-			0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
+-			0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
+-			0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
+-			0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
+-			0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
+-			0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
+-			0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
+-			0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
+-			0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
+-			0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
+-			0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
+-			0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
+-			0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
+-			0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
+-			0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
+-			0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
+-			0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
+-			0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
+-			0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
+-			0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
+-			0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
+-			0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
+-			0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
+-			0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
+-			0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
+-			0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
+-			0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
+-			0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
+-			0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
+-			0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
+-			0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
+-			0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
+-			0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
+-			0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
+-			0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
+-			0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
+-			0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
+-			0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
+-			0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
+-			0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
+-			0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
+-			0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
+-			0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
+-			0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
+-			0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
+-			0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
+-			0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
+-			0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
+-			0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
+-			0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
+-			0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
+-			0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
+-			0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
+-			0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
+-			0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
+-			0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
+-			0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
+-			0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
+-			0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
+-			0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
+-			0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
+-			0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
+-			0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
+-			0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
+-			0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
+-			0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
+-			0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
+-			0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
+-			0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
+-			0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
+-			0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
+-			0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
+-			0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
+-			0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
+-			0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
+-			0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
+-			0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
+-			0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
+-			0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
+-			0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
+-			0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
+-			0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
+-			0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
+-			0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
+-			0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
+-			0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
+-			0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
+-			0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
+-			0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
+-			0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
+-			0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
+-			0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
+-			0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
+-			0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
+-			0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
+-			0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
+-			0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
+-			0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
+-			0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
+-			0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
+-			0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
+-			0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
+-			0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
+-			0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
+-			0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
+-			0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
+-			0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
+-			0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
+-			0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
+-			0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
+-			0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
+-			0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
+-			0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
+-			0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
+-			0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
+-			0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
+-			0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
+-			0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
+-			0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
+-			0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
+-			0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
+-			0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
+-			0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
+-			0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
+-			0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
+-			0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
+-			0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
+-			0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
+-			0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
+-			0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
+-			0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
+-			0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
+-			0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
+-			0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
+-			0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
+-			0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
+-			0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
+-			0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
+-			0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
+-			0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
+-			0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
+-			0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
+-			0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
+-			0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
+-			0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
+-			0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
+-			0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
+-			0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
+-			0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
+-			0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
+-			0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
+-			0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
+-			0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
+-			0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
+-			0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
+-			0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
+-			0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
+-			0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
+-			0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
+-			0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
+-			0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
+-			0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
+-			0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
+-			0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
+-			0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
+-			0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
+-			0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
+-			0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
+-			0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
+-			0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
+-			0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
+-			0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
+-			0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
+-			0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
+-			0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
+-			0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
+-			0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
+-			0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
+-			0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
+-			0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
+-			0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
+-			0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
+-			0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
+-			0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
+-			0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
+-			0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
+-			0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
+-			0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
+-			0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
+-			0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
+-			0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
+-			0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
+-			0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
+-			0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
+-			0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
+-			0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
+-			0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
+-			0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
+-			0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
+-			0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
+-			0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
+-			0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
+-			0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
+-			0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
+-			0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
+-			0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
+-			0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
+-			0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
+-			0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
+-			0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
+-			0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
+-			0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
+-			0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
+-			0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
+-			0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
+-			0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
+-			0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
+-			0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
+-			0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
+-			0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
+-			0x00, 0x21, 0x42, 0x63,
+-		},
++		.iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input =
++			"\x00\x01\x02\x03\x04\x05\x06\x07"
++			"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			"\x10\x11\x12\x13\x14\x15\x16\x17"
++			"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			"\x20\x21\x22\x23\x24\x25\x26\x27"
++			"\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++			"\x30\x31\x32\x33\x34\x35\x36\x37"
++			"\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++			"\x40\x41\x42\x43\x44\x45\x46\x47"
++			"\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++			"\x50\x51\x52\x53\x54\x55\x56\x57"
++			"\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++			"\x60\x61\x62\x63\x64\x65\x66\x67"
++			"\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++			"\x70\x71\x72\x73\x74\x75\x76\x77"
++			"\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++			"\x80\x81\x82\x83\x84\x85\x86\x87"
++			"\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++			"\x90\x91\x92\x93\x94\x95\x96\x97"
++			"\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++			"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++			"\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++			"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++			"\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++			"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			"\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++			"\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++			"\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++			"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++			"\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++			"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++			"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
++			"\x00\x03\x06\x09\x0c\x0f\x12\x15"
++			"\x18\x1b\x1e\x21\x24\x27\x2a\x2d"
++			"\x30\x33\x36\x39\x3c\x3f\x42\x45"
++			"\x48\x4b\x4e\x51\x54\x57\x5a\x5d"
++			"\x60\x63\x66\x69\x6c\x6f\x72\x75"
++			"\x78\x7b\x7e\x81\x84\x87\x8a\x8d"
++			"\x90\x93\x96\x99\x9c\x9f\xa2\xa5"
++			"\xa8\xab\xae\xb1\xb4\xb7\xba\xbd"
++			"\xc0\xc3\xc6\xc9\xcc\xcf\xd2\xd5"
++			"\xd8\xdb\xde\xe1\xe4\xe7\xea\xed"
++			"\xf0\xf3\xf6\xf9\xfc\xff\x02\x05"
++			"\x08\x0b\x0e\x11\x14\x17\x1a\x1d"
++			"\x20\x23\x26\x29\x2c\x2f\x32\x35"
++			"\x38\x3b\x3e\x41\x44\x47\x4a\x4d"
++			"\x50\x53\x56\x59\x5c\x5f\x62\x65"
++			"\x68\x6b\x6e\x71\x74\x77\x7a\x7d"
++			"\x80\x83\x86\x89\x8c\x8f\x92\x95"
++			"\x98\x9b\x9e\xa1\xa4\xa7\xaa\xad"
++			"\xb0\xb3\xb6\xb9\xbc\xbf\xc2\xc5"
++			"\xc8\xcb\xce\xd1\xd4\xd7\xda\xdd"
++			"\xe0\xe3\xe6\xe9\xec\xef\xf2\xf5"
++			"\xf8\xfb\xfe\x01\x04\x07\x0a\x0d"
++			"\x10\x13\x16\x19\x1c\x1f\x22\x25"
++			"\x28\x2b\x2e\x31\x34\x37\x3a\x3d"
++			"\x40\x43\x46\x49\x4c\x4f\x52\x55"
++			"\x58\x5b\x5e\x61\x64\x67\x6a\x6d"
++			"\x70\x73\x76\x79\x7c\x7f\x82\x85"
++			"\x88\x8b\x8e\x91\x94\x97\x9a\x9d"
++			"\xa0\xa3\xa6\xa9\xac\xaf\xb2\xb5"
++			"\xb8\xbb\xbe\xc1\xc4\xc7\xca\xcd"
++			"\xd0\xd3\xd6\xd9\xdc\xdf\xe2\xe5"
++			"\xe8\xeb\xee\xf1\xf4\xf7\xfa\xfd"
++			"\x00\x05\x0a\x0f\x14\x19\x1e\x23"
++			"\x28\x2d\x32\x37\x3c\x41\x46\x4b"
++			"\x50\x55\x5a\x5f\x64\x69\x6e\x73"
++			"\x78\x7d\x82\x87\x8c\x91\x96\x9b"
++			"\xa0\xa5\xaa\xaf\xb4\xb9\xbe\xc3"
++			"\xc8\xcd\xd2\xd7\xdc\xe1\xe6\xeb"
++			"\xf0\xf5\xfa\xff\x04\x09\x0e\x13"
++			"\x18\x1d\x22\x27\x2c\x31\x36\x3b"
++			"\x40\x45\x4a\x4f\x54\x59\x5e\x63"
++			"\x68\x6d\x72\x77\x7c\x81\x86\x8b"
++			"\x90\x95\x9a\x9f\xa4\xa9\xae\xb3"
++			"\xb8\xbd\xc2\xc7\xcc\xd1\xd6\xdb"
++			"\xe0\xe5\xea\xef\xf4\xf9\xfe\x03"
++			"\x08\x0d\x12\x17\x1c\x21\x26\x2b"
++			"\x30\x35\x3a\x3f\x44\x49\x4e\x53"
++			"\x58\x5d\x62\x67\x6c\x71\x76\x7b"
++			"\x80\x85\x8a\x8f\x94\x99\x9e\xa3"
++			"\xa8\xad\xb2\xb7\xbc\xc1\xc6\xcb"
++			"\xd0\xd5\xda\xdf\xe4\xe9\xee\xf3"
++			"\xf8\xfd\x02\x07\x0c\x11\x16\x1b"
++			"\x20\x25\x2a\x2f\x34\x39\x3e\x43"
++			"\x48\x4d\x52\x57\x5c\x61\x66\x6b"
++			"\x70\x75\x7a\x7f\x84\x89\x8e\x93"
++			"\x98\x9d\xa2\xa7\xac\xb1\xb6\xbb"
++			"\xc0\xc5\xca\xcf\xd4\xd9\xde\xe3"
++			"\xe8\xed\xf2\xf7\xfc\x01\x06\x0b"
++			"\x10\x15\x1a\x1f\x24\x29\x2e\x33"
++			"\x38\x3d\x42\x47\x4c\x51\x56\x5b"
++			"\x60\x65\x6a\x6f\x74\x79\x7e\x83"
++			"\x88\x8d\x92\x97\x9c\xa1\xa6\xab"
++			"\xb0\xb5\xba\xbf\xc4\xc9\xce\xd3"
++			"\xd8\xdd\xe2\xe7\xec\xf1\xf6\xfb"
++			"\x00\x07\x0e\x15\x1c\x23\x2a\x31"
++			"\x38\x3f\x46\x4d\x54\x5b\x62\x69"
++			"\x70\x77\x7e\x85\x8c\x93\x9a\xa1"
++			"\xa8\xaf\xb6\xbd\xc4\xcb\xd2\xd9"
++			"\xe0\xe7\xee\xf5\xfc\x03\x0a\x11"
++			"\x18\x1f\x26\x2d\x34\x3b\x42\x49"
++			"\x50\x57\x5e\x65\x6c\x73\x7a\x81"
++			"\x88\x8f\x96\x9d\xa4\xab\xb2\xb9"
++			"\xc0\xc7\xce\xd5\xdc\xe3\xea\xf1"
++			"\xf8\xff\x06\x0d\x14\x1b\x22\x29"
++			"\x30\x37\x3e\x45\x4c\x53\x5a\x61"
++			"\x68\x6f\x76\x7d\x84\x8b\x92\x99"
++			"\xa0\xa7\xae\xb5\xbc\xc3\xca\xd1"
++			"\xd8\xdf\xe6\xed\xf4\xfb\x02\x09"
++			"\x10\x17\x1e\x25\x2c\x33\x3a\x41"
++			"\x48\x4f\x56\x5d\x64\x6b\x72\x79"
++			"\x80\x87\x8e\x95\x9c\xa3\xaa\xb1"
++			"\xb8\xbf\xc6\xcd\xd4\xdb\xe2\xe9"
++			"\xf0\xf7\xfe\x05\x0c\x13\x1a\x21"
++			"\x28\x2f\x36\x3d\x44\x4b\x52\x59"
++			"\x60\x67\x6e\x75\x7c\x83\x8a\x91"
++			"\x98\x9f\xa6\xad\xb4\xbb\xc2\xc9"
++			"\xd0\xd7\xde\xe5\xec\xf3\xfa\x01"
++			"\x08\x0f\x16\x1d\x24\x2b\x32\x39"
++			"\x40\x47\x4e\x55\x5c\x63\x6a\x71"
++			"\x78\x7f\x86\x8d\x94\x9b\xa2\xa9"
++			"\xb0\xb7\xbe\xc5\xcc\xd3\xda\xe1"
++			"\xe8\xef\xf6\xfd\x04\x0b\x12\x19"
++			"\x20\x27\x2e\x35\x3c\x43\x4a\x51"
++			"\x58\x5f\x66\x6d\x74\x7b\x82\x89"
++			"\x90\x97\x9e\xa5\xac\xb3\xba\xc1"
++			"\xc8\xcf\xd6\xdd\xe4\xeb\xf2\xf9"
++			"\x00\x09\x12\x1b\x24\x2d\x36\x3f"
++			"\x48\x51\x5a\x63\x6c\x75\x7e\x87"
++			"\x90\x99\xa2\xab\xb4\xbd\xc6\xcf"
++			"\xd8\xe1\xea\xf3\xfc\x05\x0e\x17"
++			"\x20\x29\x32\x3b\x44\x4d\x56\x5f"
++			"\x68\x71\x7a\x83\x8c\x95\x9e\xa7"
++			"\xb0\xb9\xc2\xcb\xd4\xdd\xe6\xef"
++			"\xf8\x01\x0a\x13\x1c\x25\x2e\x37"
++			"\x40\x49\x52\x5b\x64\x6d\x76\x7f"
++			"\x88\x91\x9a\xa3\xac\xb5\xbe\xc7"
++			"\xd0\xd9\xe2\xeb\xf4\xfd\x06\x0f"
++			"\x18\x21\x2a\x33\x3c\x45\x4e\x57"
++			"\x60\x69\x72\x7b\x84\x8d\x96\x9f"
++			"\xa8\xb1\xba\xc3\xcc\xd5\xde\xe7"
++			"\xf0\xf9\x02\x0b\x14\x1d\x26\x2f"
++			"\x38\x41\x4a\x53\x5c\x65\x6e\x77"
++			"\x80\x89\x92\x9b\xa4\xad\xb6\xbf"
++			"\xc8\xd1\xda\xe3\xec\xf5\xfe\x07"
++			"\x10\x19\x22\x2b\x34\x3d\x46\x4f"
++			"\x58\x61\x6a\x73\x7c\x85\x8e\x97"
++			"\xa0\xa9\xb2\xbb\xc4\xcd\xd6\xdf"
++			"\xe8\xf1\xfa\x03\x0c\x15\x1e\x27"
++			"\x30\x39\x42\x4b\x54\x5d\x66\x6f"
++			"\x78\x81\x8a\x93\x9c\xa5\xae\xb7"
++			"\xc0\xc9\xd2\xdb\xe4\xed\xf6\xff"
++			"\x08\x11\x1a\x23\x2c\x35\x3e\x47"
++			"\x50\x59\x62\x6b\x74\x7d\x86\x8f"
++			"\x98\xa1\xaa\xb3\xbc\xc5\xce\xd7"
++			"\xe0\xe9\xf2\xfb\x04\x0d\x16\x1f"
++			"\x28\x31\x3a\x43\x4c\x55\x5e\x67"
++			"\x70\x79\x82\x8b\x94\x9d\xa6\xaf"
++			"\xb8\xc1\xca\xd3\xdc\xe5\xee\xf7"
++			"\x00\x0b\x16\x21\x2c\x37\x42\x4d"
++			"\x58\x63\x6e\x79\x84\x8f\x9a\xa5"
++			"\xb0\xbb\xc6\xd1\xdc\xe7\xf2\xfd"
++			"\x08\x13\x1e\x29\x34\x3f\x4a\x55"
++			"\x60\x6b\x76\x81\x8c\x97\xa2\xad"
++			"\xb8\xc3\xce\xd9\xe4\xef\xfa\x05"
++			"\x10\x1b\x26\x31\x3c\x47\x52\x5d"
++			"\x68\x73\x7e\x89\x94\x9f\xaa\xb5"
++			"\xc0\xcb\xd6\xe1\xec\xf7\x02\x0d"
++			"\x18\x23\x2e\x39\x44\x4f\x5a\x65"
++			"\x70\x7b\x86\x91\x9c\xa7\xb2\xbd"
++			"\xc8\xd3\xde\xe9\xf4\xff\x0a\x15"
++			"\x20\x2b\x36\x41\x4c\x57\x62\x6d"
++			"\x78\x83\x8e\x99\xa4\xaf\xba\xc5"
++			"\xd0\xdb\xe6\xf1\xfc\x07\x12\x1d"
++			"\x28\x33\x3e\x49\x54\x5f\x6a\x75"
++			"\x80\x8b\x96\xa1\xac\xb7\xc2\xcd"
++			"\xd8\xe3\xee\xf9\x04\x0f\x1a\x25"
++			"\x30\x3b\x46\x51\x5c\x67\x72\x7d"
++			"\x88\x93\x9e\xa9\xb4\xbf\xca\xd5"
++			"\xe0\xeb\xf6\x01\x0c\x17\x22\x2d"
++			"\x38\x43\x4e\x59\x64\x6f\x7a\x85"
++			"\x90\x9b\xa6\xb1\xbc\xc7\xd2\xdd"
++			"\xe8\xf3\xfe\x09\x14\x1f\x2a\x35"
++			"\x40\x4b\x56\x61\x6c\x77\x82\x8d"
++			"\x98\xa3\xae\xb9\xc4\xcf\xda\xe5"
++			"\xf0\xfb\x06\x11\x1c\x27\x32\x3d"
++			"\x48\x53\x5e\x69\x74\x7f\x8a\x95"
++			"\xa0\xab\xb6\xc1\xcc\xd7\xe2\xed"
++			"\xf8\x03\x0e\x19\x24\x2f\x3a\x45"
++			"\x50\x5b\x66\x71\x7c\x87\x92\x9d"
++			"\xa8\xb3\xbe\xc9\xd4\xdf\xea\xf5"
++			"\x00\x0d\x1a\x27\x34\x41\x4e\x5b"
++			"\x68\x75\x82\x8f\x9c\xa9\xb6\xc3"
++			"\xd0\xdd\xea\xf7\x04\x11\x1e\x2b"
++			"\x38\x45\x52\x5f\x6c\x79\x86\x93"
++			"\xa0\xad\xba\xc7\xd4\xe1\xee\xfb"
++			"\x08\x15\x22\x2f\x3c\x49\x56\x63"
++			"\x70\x7d\x8a\x97\xa4\xb1\xbe\xcb"
++			"\xd8\xe5\xf2\xff\x0c\x19\x26\x33"
++			"\x40\x4d\x5a\x67\x74\x81\x8e\x9b"
++			"\xa8\xb5\xc2\xcf\xdc\xe9\xf6\x03"
++			"\x10\x1d\x2a\x37\x44\x51\x5e\x6b"
++			"\x78\x85\x92\x9f\xac\xb9\xc6\xd3"
++			"\xe0\xed\xfa\x07\x14\x21\x2e\x3b"
++			"\x48\x55\x62\x6f\x7c\x89\x96\xa3"
++			"\xb0\xbd\xca\xd7\xe4\xf1\xfe\x0b"
++			"\x18\x25\x32\x3f\x4c\x59\x66\x73"
++			"\x80\x8d\x9a\xa7\xb4\xc1\xce\xdb"
++			"\xe8\xf5\x02\x0f\x1c\x29\x36\x43"
++			"\x50\x5d\x6a\x77\x84\x91\x9e\xab"
++			"\xb8\xc5\xd2\xdf\xec\xf9\x06\x13"
++			"\x20\x2d\x3a\x47\x54\x61\x6e\x7b"
++			"\x88\x95\xa2\xaf\xbc\xc9\xd6\xe3"
++			"\xf0\xfd\x0a\x17\x24\x31\x3e\x4b"
++			"\x58\x65\x72\x7f\x8c\x99\xa6\xb3"
++			"\xc0\xcd\xda\xe7\xf4\x01\x0e\x1b"
++			"\x28\x35\x42\x4f\x5c\x69\x76\x83"
++			"\x90\x9d\xaa\xb7\xc4\xd1\xde\xeb"
++			"\xf8\x05\x12\x1f\x2c\x39\x46\x53"
++			"\x60\x6d\x7a\x87\x94\xa1\xae\xbb"
++			"\xc8\xd5\xe2\xef\xfc\x09\x16\x23"
++			"\x30\x3d\x4a\x57\x64\x71\x7e\x8b"
++			"\x98\xa5\xb2\xbf\xcc\xd9\xe6\xf3"
++			"\x00\x0f\x1e\x2d\x3c\x4b\x5a\x69"
++			"\x78\x87\x96\xa5\xb4\xc3\xd2\xe1"
++			"\xf0\xff\x0e\x1d\x2c\x3b\x4a\x59"
++			"\x68\x77\x86\x95\xa4\xb3\xc2\xd1"
++			"\xe0\xef\xfe\x0d\x1c\x2b\x3a\x49"
++			"\x58\x67\x76\x85\x94\xa3\xb2\xc1"
++			"\xd0\xdf\xee\xfd\x0c\x1b\x2a\x39"
++			"\x48\x57\x66\x75\x84\x93\xa2\xb1"
++			"\xc0\xcf\xde\xed\xfc\x0b\x1a\x29"
++			"\x38\x47\x56\x65\x74\x83\x92\xa1"
++			"\xb0\xbf\xce\xdd\xec\xfb\x0a\x19"
++			"\x28\x37\x46\x55\x64\x73\x82\x91"
++			"\xa0\xaf\xbe\xcd\xdc\xeb\xfa\x09"
++			"\x18\x27\x36\x45\x54\x63\x72\x81"
++			"\x90\x9f\xae\xbd\xcc\xdb\xea\xf9"
++			"\x08\x17\x26\x35\x44\x53\x62\x71"
++			"\x80\x8f\x9e\xad\xbc\xcb\xda\xe9"
++			"\xf8\x07\x16\x25\x34\x43\x52\x61"
++			"\x70\x7f\x8e\x9d\xac\xbb\xca\xd9"
++			"\xe8\xf7\x06\x15\x24\x33\x42\x51"
++			"\x60\x6f\x7e\x8d\x9c\xab\xba\xc9"
++			"\xd8\xe7\xf6\x05\x14\x23\x32\x41"
++			"\x50\x5f\x6e\x7d\x8c\x9b\xaa\xb9"
++			"\xc8\xd7\xe6\xf5\x04\x13\x22\x31"
++			"\x40\x4f\x5e\x6d\x7c\x8b\x9a\xa9"
++			"\xb8\xc7\xd6\xe5\xf4\x03\x12\x21"
++			"\x30\x3f\x4e\x5d\x6c\x7b\x8a\x99"
++			"\xa8\xb7\xc6\xd5\xe4\xf3\x02\x11"
++			"\x20\x2f\x3e\x4d\x5c\x6b\x7a\x89"
++			"\x98\xa7\xb6\xc5\xd4\xe3\xf2\x01"
++			"\x10\x1f\x2e\x3d\x4c\x5b\x6a\x79"
++			"\x88\x97\xa6\xb5\xc4\xd3\xe2\xf1"
++			"\x00\x11\x22\x33\x44\x55\x66\x77"
++			"\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
++			"\x10\x21\x32\x43\x54\x65\x76\x87"
++			"\x98\xa9\xba\xcb\xdc\xed\xfe\x0f"
++			"\x20\x31\x42\x53\x64\x75\x86\x97"
++			"\xa8\xb9\xca\xdb\xec\xfd\x0e\x1f"
++			"\x30\x41\x52\x63\x74\x85\x96\xa7"
++			"\xb8\xc9\xda\xeb\xfc\x0d\x1e\x2f"
++			"\x40\x51\x62\x73\x84\x95\xa6\xb7"
++			"\xc8\xd9\xea\xfb\x0c\x1d\x2e\x3f"
++			"\x50\x61\x72\x83\x94\xa5\xb6\xc7"
++			"\xd8\xe9\xfa\x0b\x1c\x2d\x3e\x4f"
++			"\x60\x71\x82\x93\xa4\xb5\xc6\xd7"
++			"\xe8\xf9\x0a\x1b\x2c\x3d\x4e\x5f"
++			"\x70\x81\x92\xa3\xb4\xc5\xd6\xe7"
++			"\xf8\x09\x1a\x2b\x3c\x4d\x5e\x6f"
++			"\x80\x91\xa2\xb3\xc4\xd5\xe6\xf7"
++			"\x08\x19\x2a\x3b\x4c\x5d\x6e\x7f"
++			"\x90\xa1\xb2\xc3\xd4\xe5\xf6\x07"
++			"\x18\x29\x3a\x4b\x5c\x6d\x7e\x8f"
++			"\xa0\xb1\xc2\xd3\xe4\xf5\x06\x17"
++			"\x28\x39\x4a\x5b\x6c\x7d\x8e\x9f"
++			"\xb0\xc1\xd2\xe3\xf4\x05\x16\x27"
++			"\x38\x49\x5a\x6b\x7c\x8d\x9e\xaf"
++			"\xc0\xd1\xe2\xf3\x04\x15\x26\x37"
++			"\x48\x59\x6a\x7b\x8c\x9d\xae\xbf"
++			"\xd0\xe1\xf2\x03\x14\x25\x36\x47"
++			"\x58\x69\x7a\x8b\x9c\xad\xbe\xcf"
++			"\xe0\xf1\x02\x13\x24\x35\x46\x57"
++			"\x68\x79\x8a\x9b\xac\xbd\xce\xdf"
++			"\xf0\x01\x12\x23\x34\x45\x56\x67"
++			"\x78\x89\x9a\xab\xbc\xcd\xde\xef"
++			"\x00\x13\x26\x39\x4c\x5f\x72\x85"
++			"\x98\xab\xbe\xd1\xe4\xf7\x0a\x1d"
++			"\x30\x43\x56\x69\x7c\x8f\xa2\xb5"
++			"\xc8\xdb\xee\x01\x14\x27\x3a\x4d"
++			"\x60\x73\x86\x99\xac\xbf\xd2\xe5"
++			"\xf8\x0b\x1e\x31\x44\x57\x6a\x7d"
++			"\x90\xa3\xb6\xc9\xdc\xef\x02\x15"
++			"\x28\x3b\x4e\x61\x74\x87\x9a\xad"
++			"\xc0\xd3\xe6\xf9\x0c\x1f\x32\x45"
++			"\x58\x6b\x7e\x91\xa4\xb7\xca\xdd"
++			"\xf0\x03\x16\x29\x3c\x4f\x62\x75"
++			"\x88\x9b\xae\xc1\xd4\xe7\xfa\x0d"
++			"\x20\x33\x46\x59\x6c\x7f\x92\xa5"
++			"\xb8\xcb\xde\xf1\x04\x17\x2a\x3d"
++			"\x50\x63\x76\x89\x9c\xaf\xc2\xd5"
++			"\xe8\xfb\x0e\x21\x34\x47\x5a\x6d"
++			"\x80\x93\xa6\xb9\xcc\xdf\xf2\x05"
++			"\x18\x2b\x3e\x51\x64\x77\x8a\x9d"
++			"\xb0\xc3\xd6\xe9\xfc\x0f\x22\x35"
++			"\x48\x5b\x6e\x81\x94\xa7\xba\xcd"
++			"\xe0\xf3\x06\x19\x2c\x3f\x52\x65"
++			"\x78\x8b\x9e\xb1\xc4\xd7\xea\xfd"
++			"\x10\x23\x36\x49\x5c\x6f\x82\x95"
++			"\xa8\xbb\xce\xe1\xf4\x07\x1a\x2d"
++			"\x40\x53\x66\x79\x8c\x9f\xb2\xc5"
++			"\xd8\xeb\xfe\x11\x24\x37\x4a\x5d"
++			"\x70\x83\x96\xa9\xbc\xcf\xe2\xf5"
++			"\x08\x1b\x2e\x41\x54\x67\x7a\x8d"
++			"\xa0\xb3\xc6\xd9\xec\xff\x12\x25"
++			"\x38\x4b\x5e\x71\x84\x97\xaa\xbd"
++			"\xd0\xe3\xf6\x09\x1c\x2f\x42\x55"
++			"\x68\x7b\x8e\xa1\xb4\xc7\xda\xed"
++			"\x00\x15\x2a\x3f\x54\x69\x7e\x93"
++			"\xa8\xbd\xd2\xe7\xfc\x11\x26\x3b"
++			"\x50\x65\x7a\x8f\xa4\xb9\xce\xe3"
++			"\xf8\x0d\x22\x37\x4c\x61\x76\x8b"
++			"\xa0\xb5\xca\xdf\xf4\x09\x1e\x33"
++			"\x48\x5d\x72\x87\x9c\xb1\xc6\xdb"
++			"\xf0\x05\x1a\x2f\x44\x59\x6e\x83"
++			"\x98\xad\xc2\xd7\xec\x01\x16\x2b"
++			"\x40\x55\x6a\x7f\x94\xa9\xbe\xd3"
++			"\xe8\xfd\x12\x27\x3c\x51\x66\x7b"
++			"\x90\xa5\xba\xcf\xe4\xf9\x0e\x23"
++			"\x38\x4d\x62\x77\x8c\xa1\xb6\xcb"
++			"\xe0\xf5\x0a\x1f\x34\x49\x5e\x73"
++			"\x88\x9d\xb2\xc7\xdc\xf1\x06\x1b"
++			"\x30\x45\x5a\x6f\x84\x99\xae\xc3"
++			"\xd8\xed\x02\x17\x2c\x41\x56\x6b"
++			"\x80\x95\xaa\xbf\xd4\xe9\xfe\x13"
++			"\x28\x3d\x52\x67\x7c\x91\xa6\xbb"
++			"\xd0\xe5\xfa\x0f\x24\x39\x4e\x63"
++			"\x78\x8d\xa2\xb7\xcc\xe1\xf6\x0b"
++			"\x20\x35\x4a\x5f\x74\x89\x9e\xb3"
++			"\xc8\xdd\xf2\x07\x1c\x31\x46\x5b"
++			"\x70\x85\x9a\xaf\xc4\xd9\xee\x03"
++			"\x18\x2d\x42\x57\x6c\x81\x96\xab"
++			"\xc0\xd5\xea\xff\x14\x29\x3e\x53"
++			"\x68\x7d\x92\xa7\xbc\xd1\xe6\xfb"
++			"\x10\x25\x3a\x4f\x64\x79\x8e\xa3"
++			"\xb8\xcd\xe2\xf7\x0c\x21\x36\x4b"
++			"\x60\x75\x8a\x9f\xb4\xc9\xde\xf3"
++			"\x08\x1d\x32\x47\x5c\x71\x86\x9b"
++			"\xb0\xc5\xda\xef\x04\x19\x2e\x43"
++			"\x58\x6d\x82\x97\xac\xc1\xd6\xeb"
++			"\x00\x17\x2e\x45\x5c\x73\x8a\xa1"
++			"\xb8\xcf\xe6\xfd\x14\x2b\x42\x59"
++			"\x70\x87\x9e\xb5\xcc\xe3\xfa\x11"
++			"\x28\x3f\x56\x6d\x84\x9b\xb2\xc9"
++			"\xe0\xf7\x0e\x25\x3c\x53\x6a\x81"
++			"\x98\xaf\xc6\xdd\xf4\x0b\x22\x39"
++			"\x50\x67\x7e\x95\xac\xc3\xda\xf1"
++			"\x08\x1f\x36\x4d\x64\x7b\x92\xa9"
++			"\xc0\xd7\xee\x05\x1c\x33\x4a\x61"
++			"\x78\x8f\xa6\xbd\xd4\xeb\x02\x19"
++			"\x30\x47\x5e\x75\x8c\xa3\xba\xd1"
++			"\xe8\xff\x16\x2d\x44\x5b\x72\x89"
++			"\xa0\xb7\xce\xe5\xfc\x13\x2a\x41"
++			"\x58\x6f\x86\x9d\xb4\xcb\xe2\xf9"
++			"\x10\x27\x3e\x55\x6c\x83\x9a\xb1"
++			"\xc8\xdf\xf6\x0d\x24\x3b\x52\x69"
++			"\x80\x97\xae\xc5\xdc\xf3\x0a\x21"
++			"\x38\x4f\x66\x7d\x94\xab\xc2\xd9"
++			"\xf0\x07\x1e\x35\x4c\x63\x7a\x91"
++			"\xa8\xbf\xd6\xed\x04\x1b\x32\x49"
++			"\x60\x77\x8e\xa5\xbc\xd3\xea\x01"
++			"\x18\x2f\x46\x5d\x74\x8b\xa2\xb9"
++			"\xd0\xe7\xfe\x15\x2c\x43\x5a\x71"
++			"\x88\x9f\xb6\xcd\xe4\xfb\x12\x29"
++			"\x40\x57\x6e\x85\x9c\xb3\xca\xe1"
++			"\xf8\x0f\x26\x3d\x54\x6b\x82\x99"
++			"\xb0\xc7\xde\xf5\x0c\x23\x3a\x51"
++			"\x68\x7f\x96\xad\xc4\xdb\xf2\x09"
++			"\x20\x37\x4e\x65\x7c\x93\xaa\xc1"
++			"\xd8\xef\x06\x1d\x34\x4b\x62\x79"
++			"\x90\xa7\xbe\xd5\xec\x03\x1a\x31"
++			"\x48\x5f\x76\x8d\xa4\xbb\xd2\xe9"
++			"\x00\x19\x32\x4b\x64\x7d\x96\xaf"
++			"\xc8\xe1\xfa\x13\x2c\x45\x5e\x77"
++			"\x90\xa9\xc2\xdb\xf4\x0d\x26\x3f"
++			"\x58\x71\x8a\xa3\xbc\xd5\xee\x07"
++			"\x20\x39\x52\x6b\x84\x9d\xb6\xcf"
++			"\xe8\x01\x1a\x33\x4c\x65\x7e\x97"
++			"\xb0\xc9\xe2\xfb\x14\x2d\x46\x5f"
++			"\x78\x91\xaa\xc3\xdc\xf5\x0e\x27"
++			"\x40\x59\x72\x8b\xa4\xbd\xd6\xef"
++			"\x08\x21\x3a\x53\x6c\x85\x9e\xb7"
++			"\xd0\xe9\x02\x1b\x34\x4d\x66\x7f"
++			"\x98\xb1\xca\xe3\xfc\x15\x2e\x47"
++			"\x60\x79\x92\xab\xc4\xdd\xf6\x0f"
++			"\x28\x41\x5a\x73\x8c\xa5\xbe\xd7"
++			"\xf0\x09\x22\x3b\x54\x6d\x86\x9f"
++			"\xb8\xd1\xea\x03\x1c\x35\x4e\x67"
++			"\x80\x99\xb2\xcb\xe4\xfd\x16\x2f"
++			"\x48\x61\x7a\x93\xac\xc5\xde\xf7"
++			"\x10\x29\x42\x5b\x74\x8d\xa6\xbf"
++			"\xd8\xf1\x0a\x23\x3c\x55\x6e\x87"
++			"\xa0\xb9\xd2\xeb\x04\x1d\x36\x4f"
++			"\x68\x81\x9a\xb3\xcc\xe5\xfe\x17"
++			"\x30\x49\x62\x7b\x94\xad\xc6\xdf"
++			"\xf8\x11\x2a\x43\x5c\x75\x8e\xa7"
++			"\xc0\xd9\xf2\x0b\x24\x3d\x56\x6f"
++			"\x88\xa1\xba\xd3\xec\x05\x1e\x37"
++			"\x50\x69\x82\x9b\xb4\xcd\xe6\xff"
++			"\x18\x31\x4a\x63\x7c\x95\xae\xc7"
++			"\xe0\xf9\x12\x2b\x44\x5d\x76\x8f"
++			"\xa8\xc1\xda\xf3\x0c\x25\x3e\x57"
++			"\x70\x89\xa2\xbb\xd4\xed\x06\x1f"
++			"\x38\x51\x6a\x83\x9c\xb5\xce\xe7"
++			"\x00\x1b\x36\x51\x6c\x87\xa2\xbd"
++			"\xd8\xf3\x0e\x29\x44\x5f\x7a\x95"
++			"\xb0\xcb\xe6\x01\x1c\x37\x52\x6d"
++			"\x88\xa3\xbe\xd9\xf4\x0f\x2a\x45"
++			"\x60\x7b\x96\xb1\xcc\xe7\x02\x1d"
++			"\x38\x53\x6e\x89\xa4\xbf\xda\xf5"
++			"\x10\x2b\x46\x61\x7c\x97\xb2\xcd"
++			"\xe8\x03\x1e\x39\x54\x6f\x8a\xa5"
++			"\xc0\xdb\xf6\x11\x2c\x47\x62\x7d"
++			"\x98\xb3\xce\xe9\x04\x1f\x3a\x55"
++			"\x70\x8b\xa6\xc1\xdc\xf7\x12\x2d"
++			"\x48\x63\x7e\x99\xb4\xcf\xea\x05"
++			"\x20\x3b\x56\x71\x8c\xa7\xc2\xdd"
++			"\xf8\x13\x2e\x49\x64\x7f\x9a\xb5"
++			"\xd0\xeb\x06\x21\x3c\x57\x72\x8d"
++			"\xa8\xc3\xde\xf9\x14\x2f\x4a\x65"
++			"\x80\x9b\xb6\xd1\xec\x07\x22\x3d"
++			"\x58\x73\x8e\xa9\xc4\xdf\xfa\x15"
++			"\x30\x4b\x66\x81\x9c\xb7\xd2\xed"
++			"\x08\x23\x3e\x59\x74\x8f\xaa\xc5"
++			"\xe0\xfb\x16\x31\x4c\x67\x82\x9d"
++			"\xb8\xd3\xee\x09\x24\x3f\x5a\x75"
++			"\x90\xab\xc6\xe1\xfc\x17\x32\x4d"
++			"\x68\x83\x9e\xb9\xd4\xef\x0a\x25"
++			"\x40\x5b\x76\x91\xac\xc7\xe2\xfd"
++			"\x18\x33\x4e\x69\x84\x9f\xba\xd5"
++			"\xf0\x0b\x26\x41\x5c\x77\x92\xad"
++			"\xc8\xe3\xfe\x19\x34\x4f\x6a\x85"
++			"\xa0\xbb\xd6\xf1\x0c\x27\x42\x5d"
++			"\x78\x93\xae\xc9\xe4\xff\x1a\x35"
++			"\x50\x6b\x86\xa1\xbc\xd7\xf2\x0d"
++			"\x28\x43\x5e\x79\x94\xaf\xca\xe5"
++			"\x00\x1d\x3a\x57\x74\x91\xae\xcb"
++			"\xe8\x05\x22\x3f\x5c\x79\x96\xb3"
++			"\xd0\xed\x0a\x27\x44\x61\x7e\x9b"
++			"\xb8\xd5\xf2\x0f\x2c\x49\x66\x83"
++			"\xa0\xbd\xda\xf7\x14\x31\x4e\x6b"
++			"\x88\xa5\xc2\xdf\xfc\x19\x36\x53"
++			"\x70\x8d\xaa\xc7\xe4\x01\x1e\x3b"
++			"\x58\x75\x92\xaf\xcc\xe9\x06\x23"
++			"\x40\x5d\x7a\x97\xb4\xd1\xee\x0b"
++			"\x28\x45\x62\x7f\x9c\xb9\xd6\xf3"
++			"\x10\x2d\x4a\x67\x84\xa1\xbe\xdb"
++			"\xf8\x15\x32\x4f\x6c\x89\xa6\xc3"
++			"\xe0\xfd\x1a\x37\x54\x71\x8e\xab"
++			"\xc8\xe5\x02\x1f\x3c\x59\x76\x93"
++			"\xb0\xcd\xea\x07\x24\x41\x5e\x7b"
++			"\x98\xb5\xd2\xef\x0c\x29\x46\x63"
++			"\x80\x9d\xba\xd7\xf4\x11\x2e\x4b"
++			"\x68\x85\xa2\xbf\xdc\xf9\x16\x33"
++			"\x50\x6d\x8a\xa7\xc4\xe1\xfe\x1b"
++			"\x38\x55\x72\x8f\xac\xc9\xe6\x03"
++			"\x20\x3d\x5a\x77\x94\xb1\xce\xeb"
++			"\x08\x25\x42\x5f\x7c\x99\xb6\xd3"
++			"\xf0\x0d\x2a\x47\x64\x81\x9e\xbb"
++			"\xd8\xf5\x12\x2f\x4c\x69\x86\xa3"
++			"\xc0\xdd\xfa\x17\x34\x51\x6e\x8b"
++			"\xa8\xc5\xe2\xff\x1c\x39\x56\x73"
++			"\x90\xad\xca\xe7\x04\x21\x3e\x5b"
++			"\x78\x95\xb2\xcf\xec\x09\x26\x43"
++			"\x60\x7d\x9a\xb7\xd4\xf1\x0e\x2b"
++			"\x48\x65\x82\x9f\xbc\xd9\xf6\x13"
++			"\x30\x4d\x6a\x87\xa4\xc1\xde\xfb"
++			"\x18\x35\x52\x6f\x8c\xa9\xc6\xe3"
++			"\x00\x1f\x3e\x5d\x7c\x9b\xba\xd9"
++			"\xf8\x17\x36\x55\x74\x93\xb2\xd1"
++			"\xf0\x0f\x2e\x4d\x6c\x8b\xaa\xc9"
++			"\xe8\x07\x26\x45\x64\x83\xa2\xc1"
++			"\xe0\xff\x1e\x3d\x5c\x7b\x9a\xb9"
++			"\xd8\xf7\x16\x35\x54\x73\x92\xb1"
++			"\xd0\xef\x0e\x2d\x4c\x6b\x8a\xa9"
++			"\xc8\xe7\x06\x25\x44\x63\x82\xa1"
++			"\xc0\xdf\xfe\x1d\x3c\x5b\x7a\x99"
++			"\xb8\xd7\xf6\x15\x34\x53\x72\x91"
++			"\xb0\xcf\xee\x0d\x2c\x4b\x6a\x89"
++			"\xa8\xc7\xe6\x05\x24\x43\x62\x81"
++			"\xa0\xbf\xde\xfd\x1c\x3b\x5a\x79"
++			"\x98\xb7\xd6\xf5\x14\x33\x52\x71"
++			"\x90\xaf\xce\xed\x0c\x2b\x4a\x69"
++			"\x88\xa7\xc6\xe5\x04\x23\x42\x61"
++			"\x80\x9f\xbe\xdd\xfc\x1b\x3a\x59"
++			"\x78\x97\xb6\xd5\xf4\x13\x32\x51"
++			"\x70\x8f\xae\xcd\xec\x0b\x2a\x49"
++			"\x68\x87\xa6\xc5\xe4\x03\x22\x41"
++			"\x60\x7f\x9e\xbd\xdc\xfb\x1a\x39"
++			"\x58\x77\x96\xb5\xd4\xf3\x12\x31"
++			"\x50\x6f\x8e\xad\xcc\xeb\x0a\x29"
++			"\x48\x67\x86\xa5\xc4\xe3\x02\x21"
++			"\x40\x5f\x7e\x9d\xbc\xdb\xfa\x19"
++			"\x38\x57\x76\x95\xb4\xd3\xf2\x11"
++			"\x30\x4f\x6e\x8d\xac\xcb\xea\x09"
++			"\x28\x47\x66\x85\xa4\xc3\xe2\x01"
++			"\x20\x3f\x5e\x7d\x9c\xbb\xda\xf9"
++			"\x18\x37\x56\x75\x94\xb3\xd2\xf1"
++			"\x10\x2f\x4e\x6d\x8c\xab\xca\xe9"
++			"\x08\x27\x46\x65\x84\xa3\xc2\xe1"
++			"\x00\x21\x42\x63",
+ 		.ilen = 4100,
+-		.result = {
+-			0xf0, 0x5c, 0x74, 0xad, 0x4e, 0xbc, 0x99, 0xe2,
+-			0xae, 0xff, 0x91, 0x3a, 0x44, 0xcf, 0x38, 0x32,
+-			0x1e, 0xad, 0xa7, 0xcd, 0xa1, 0x39, 0x95, 0xaa,
+-			0x10, 0xb1, 0xb3, 0x2e, 0x04, 0x31, 0x8f, 0x86,
+-			0xf2, 0x62, 0x74, 0x70, 0x0c, 0xa4, 0x46, 0x08,
+-			0xa8, 0xb7, 0x99, 0xa8, 0xe9, 0xd2, 0x73, 0x79,
+-			0x7e, 0x6e, 0xd4, 0x8f, 0x1e, 0xc7, 0x8e, 0x31,
+-			0x0b, 0xfa, 0x4b, 0xce, 0xfd, 0xf3, 0x57, 0x71,
+-			0xe9, 0x46, 0x03, 0xa5, 0x3d, 0x34, 0x00, 0xe2,
+-			0x18, 0xff, 0x75, 0x6d, 0x06, 0x2d, 0x00, 0xab,
+-			0xb9, 0x3e, 0x6c, 0x59, 0xc5, 0x84, 0x06, 0xb5,
+-			0x8b, 0xd0, 0x89, 0x9c, 0x4a, 0x79, 0x16, 0xc6,
+-			0x3d, 0x74, 0x54, 0xfa, 0x44, 0xcd, 0x23, 0x26,
+-			0x5c, 0xcf, 0x7e, 0x28, 0x92, 0x32, 0xbf, 0xdf,
+-			0xa7, 0x20, 0x3c, 0x74, 0x58, 0x2a, 0x9a, 0xde,
+-			0x61, 0x00, 0x1c, 0x4f, 0xff, 0x59, 0xc4, 0x22,
+-			0xac, 0x3c, 0xd0, 0xe8, 0x6c, 0xf9, 0x97, 0x1b,
+-			0x58, 0x9b, 0xad, 0x71, 0xe8, 0xa9, 0xb5, 0x0d,
+-			0xee, 0x2f, 0x04, 0x1f, 0x7f, 0xbc, 0x99, 0xee,
+-			0x84, 0xff, 0x42, 0x60, 0xdc, 0x3a, 0x18, 0xa5,
+-			0x81, 0xf9, 0xef, 0xdc, 0x7a, 0x0f, 0x65, 0x41,
+-			0x2f, 0xa3, 0xd3, 0xf9, 0xc2, 0xcb, 0xc0, 0x4d,
+-			0x8f, 0xd3, 0x76, 0x96, 0xad, 0x49, 0x6d, 0x38,
+-			0x3d, 0x39, 0x0b, 0x6c, 0x80, 0xb7, 0x54, 0x69,
+-			0xf0, 0x2c, 0x90, 0x02, 0x29, 0x0d, 0x1c, 0x12,
+-			0xad, 0x55, 0xc3, 0x8b, 0x68, 0xd9, 0xcc, 0xb3,
+-			0xb2, 0x64, 0x33, 0x90, 0x5e, 0xca, 0x4b, 0xe2,
+-			0xfb, 0x75, 0xdc, 0x63, 0xf7, 0x9f, 0x82, 0x74,
+-			0xf0, 0xc9, 0xaa, 0x7f, 0xe9, 0x2a, 0x9b, 0x33,
+-			0xbc, 0x88, 0x00, 0x7f, 0xca, 0xb2, 0x1f, 0x14,
+-			0xdb, 0xc5, 0x8e, 0x7b, 0x11, 0x3c, 0x3e, 0x08,
+-			0xf3, 0x83, 0xe8, 0xe0, 0x94, 0x86, 0x2e, 0x92,
+-			0x78, 0x6b, 0x01, 0xc9, 0xc7, 0x83, 0xba, 0x21,
+-			0x6a, 0x25, 0x15, 0x33, 0x4e, 0x45, 0x08, 0xec,
+-			0x35, 0xdb, 0xe0, 0x6e, 0x31, 0x51, 0x79, 0xa9,
+-			0x42, 0x44, 0x65, 0xc1, 0xa0, 0xf1, 0xf9, 0x2a,
+-			0x70, 0xd5, 0xb6, 0xc6, 0xc1, 0x8c, 0x39, 0xfc,
+-			0x25, 0xa6, 0x55, 0xd9, 0xdd, 0x2d, 0x4c, 0xec,
+-			0x49, 0xc6, 0xeb, 0x0e, 0xa8, 0x25, 0x2a, 0x16,
+-			0x1b, 0x66, 0x84, 0xda, 0xe2, 0x92, 0xe5, 0xc0,
+-			0xc8, 0x53, 0x07, 0xaf, 0x80, 0x84, 0xec, 0xfd,
+-			0xcd, 0xd1, 0x6e, 0xcd, 0x6f, 0x6a, 0xf5, 0x36,
+-			0xc5, 0x15, 0xe5, 0x25, 0x7d, 0x77, 0xd1, 0x1a,
+-			0x93, 0x36, 0xa9, 0xcf, 0x7c, 0xa4, 0x54, 0x4a,
+-			0x06, 0x51, 0x48, 0x4e, 0xf6, 0x59, 0x87, 0xd2,
+-			0x04, 0x02, 0xef, 0xd3, 0x44, 0xde, 0x76, 0x31,
+-			0xb3, 0x34, 0x17, 0x1b, 0x9d, 0x66, 0x11, 0x9f,
+-			0x1e, 0xcc, 0x17, 0xe9, 0xc7, 0x3c, 0x1b, 0xe7,
+-			0xcb, 0x50, 0x08, 0xfc, 0xdc, 0x2b, 0x24, 0xdb,
+-			0x65, 0x83, 0xd0, 0x3b, 0xe3, 0x30, 0xea, 0x94,
+-			0x6c, 0xe7, 0xe8, 0x35, 0x32, 0xc7, 0xdb, 0x64,
+-			0xb4, 0x01, 0xab, 0x36, 0x2c, 0x77, 0x13, 0xaf,
+-			0xf8, 0x2b, 0x88, 0x3f, 0x54, 0x39, 0xc4, 0x44,
+-			0xfe, 0xef, 0x6f, 0x68, 0x34, 0xbe, 0x0f, 0x05,
+-			0x16, 0x6d, 0xf6, 0x0a, 0x30, 0xe7, 0xe3, 0xed,
+-			0xc4, 0xde, 0x3c, 0x1b, 0x13, 0xd8, 0xdb, 0xfe,
+-			0x41, 0x62, 0xe5, 0x28, 0xd4, 0x8d, 0xa3, 0xc7,
+-			0x93, 0x97, 0xc6, 0x48, 0x45, 0x1d, 0x9f, 0x83,
+-			0xdf, 0x4b, 0x40, 0x3e, 0x42, 0x25, 0x87, 0x80,
+-			0x4c, 0x7d, 0xa8, 0xd4, 0x98, 0x23, 0x95, 0x75,
+-			0x41, 0x8c, 0xda, 0x41, 0x9b, 0xd4, 0xa7, 0x06,
+-			0xb5, 0xf1, 0x71, 0x09, 0x53, 0xbe, 0xca, 0xbf,
+-			0x32, 0x03, 0xed, 0xf0, 0x50, 0x1c, 0x56, 0x39,
+-			0x5b, 0xa4, 0x75, 0x18, 0xf7, 0x9b, 0x58, 0xef,
+-			0x53, 0xfc, 0x2a, 0x38, 0x23, 0x15, 0x75, 0xcd,
+-			0x45, 0xe5, 0x5a, 0x82, 0x55, 0xba, 0x21, 0xfa,
+-			0xd4, 0xbd, 0xc6, 0x94, 0x7c, 0xc5, 0x80, 0x12,
+-			0xf7, 0x4b, 0x32, 0xc4, 0x9a, 0x82, 0xd8, 0x28,
+-			0x8f, 0xd9, 0xc2, 0x0f, 0x60, 0x03, 0xbe, 0x5e,
+-			0x21, 0xd6, 0x5f, 0x58, 0xbf, 0x5c, 0xb1, 0x32,
+-			0x82, 0x8d, 0xa9, 0xe5, 0xf2, 0x66, 0x1a, 0xc0,
+-			0xa0, 0xbc, 0x58, 0x2f, 0x71, 0xf5, 0x2f, 0xed,
+-			0xd1, 0x26, 0xb9, 0xd8, 0x49, 0x5a, 0x07, 0x19,
+-			0x01, 0x7c, 0x59, 0xb0, 0xf8, 0xa4, 0xb7, 0xd3,
+-			0x7b, 0x1a, 0x8c, 0x38, 0xf4, 0x50, 0xa4, 0x59,
+-			0xb0, 0xcc, 0x41, 0x0b, 0x88, 0x7f, 0xe5, 0x31,
+-			0xb3, 0x42, 0xba, 0xa2, 0x7e, 0xd4, 0x32, 0x71,
+-			0x45, 0x87, 0x48, 0xa9, 0xc2, 0xf2, 0x89, 0xb3,
+-			0xe4, 0xa7, 0x7e, 0x52, 0x15, 0x61, 0xfa, 0xfe,
+-			0xc9, 0xdd, 0x81, 0xeb, 0x13, 0xab, 0xab, 0xc3,
+-			0x98, 0x59, 0xd8, 0x16, 0x3d, 0x14, 0x7a, 0x1c,
+-			0x3c, 0x41, 0x9a, 0x16, 0x16, 0x9b, 0xd2, 0xd2,
+-			0x69, 0x3a, 0x29, 0x23, 0xac, 0x86, 0x32, 0xa5,
+-			0x48, 0x9c, 0x9e, 0xf3, 0x47, 0x77, 0x81, 0x70,
+-			0x24, 0xe8, 0x85, 0xd2, 0xf5, 0xb5, 0xfa, 0xff,
+-			0x59, 0x6a, 0xd3, 0x50, 0x59, 0x43, 0x59, 0xde,
+-			0xd9, 0xf1, 0x55, 0xa5, 0x0c, 0xc3, 0x1a, 0x1a,
+-			0x18, 0x34, 0x0d, 0x1a, 0x63, 0x33, 0xed, 0x10,
+-			0xe0, 0x1d, 0x2a, 0x18, 0xd2, 0xc0, 0x54, 0xa8,
+-			0xca, 0xb5, 0x9a, 0xd3, 0xdd, 0xca, 0x45, 0x84,
+-			0x50, 0xe7, 0x0f, 0xfe, 0xa4, 0x99, 0x5a, 0xbe,
+-			0x43, 0x2d, 0x9a, 0xcb, 0x92, 0x3f, 0x5a, 0x1d,
+-			0x85, 0xd8, 0xc9, 0xdf, 0x68, 0xc9, 0x12, 0x80,
+-			0x56, 0x0c, 0xdc, 0x00, 0xdc, 0x3a, 0x7d, 0x9d,
+-			0xa3, 0xa2, 0xe8, 0x4d, 0xbf, 0xf9, 0x70, 0xa0,
+-			0xa4, 0x13, 0x4f, 0x6b, 0xaf, 0x0a, 0x89, 0x7f,
+-			0xda, 0xf0, 0xbf, 0x9b, 0xc8, 0x1d, 0xe5, 0xf8,
+-			0x2e, 0x8b, 0x07, 0xb5, 0x73, 0x1b, 0xcc, 0xa2,
+-			0xa6, 0xad, 0x30, 0xbc, 0x78, 0x3c, 0x5b, 0x10,
+-			0xfa, 0x5e, 0x62, 0x2d, 0x9e, 0x64, 0xb3, 0x33,
+-			0xce, 0xf9, 0x1f, 0x86, 0xe7, 0x8b, 0xa2, 0xb8,
+-			0xe8, 0x99, 0x57, 0x8c, 0x11, 0xed, 0x66, 0xd9,
+-			0x3c, 0x72, 0xb9, 0xc3, 0xe6, 0x4e, 0x17, 0x3a,
+-			0x6a, 0xcb, 0x42, 0x24, 0x06, 0xed, 0x3e, 0x4e,
+-			0xa3, 0xe8, 0x6a, 0x94, 0xda, 0x0d, 0x4e, 0xd5,
+-			0x14, 0x19, 0xcf, 0xb6, 0x26, 0xd8, 0x2e, 0xcc,
+-			0x64, 0x76, 0x38, 0x49, 0x4d, 0xfe, 0x30, 0x6d,
+-			0xe4, 0xc8, 0x8c, 0x7b, 0xc4, 0xe0, 0x35, 0xba,
+-			0x22, 0x6e, 0x76, 0xe1, 0x1a, 0xf2, 0x53, 0xc3,
+-			0x28, 0xa2, 0x82, 0x1f, 0x61, 0x69, 0xad, 0xc1,
+-			0x7b, 0x28, 0x4b, 0x1e, 0x6c, 0x85, 0x95, 0x9b,
+-			0x51, 0xb5, 0x17, 0x7f, 0x12, 0x69, 0x8c, 0x24,
+-			0xd5, 0xc7, 0x5a, 0x5a, 0x11, 0x54, 0xff, 0x5a,
+-			0xf7, 0x16, 0xc3, 0x91, 0xa6, 0xf0, 0xdc, 0x0a,
+-			0xb6, 0xa7, 0x4a, 0x0d, 0x7a, 0x58, 0xfe, 0xa5,
+-			0xf5, 0xcb, 0x8f, 0x7b, 0x0e, 0xea, 0x57, 0xe7,
+-			0xbd, 0x79, 0xd6, 0x1c, 0x88, 0x23, 0x6c, 0xf2,
+-			0x4d, 0x29, 0x77, 0x53, 0x35, 0x6a, 0x00, 0x8d,
+-			0xcd, 0xa3, 0x58, 0xbe, 0x77, 0x99, 0x18, 0xf8,
+-			0xe6, 0xe1, 0x8f, 0xe9, 0x37, 0x8f, 0xe3, 0xe2,
+-			0x5a, 0x8a, 0x93, 0x25, 0xaf, 0xf3, 0x78, 0x80,
+-			0xbe, 0xa6, 0x1b, 0xc6, 0xac, 0x8b, 0x1c, 0x91,
+-			0x58, 0xe1, 0x9f, 0x89, 0x35, 0x9d, 0x1d, 0x21,
+-			0x29, 0x9f, 0xf4, 0x99, 0x02, 0x27, 0x0f, 0xa8,
+-			0x4f, 0x79, 0x94, 0x2b, 0x33, 0x2c, 0xda, 0xa2,
+-			0x26, 0x39, 0x83, 0x94, 0xef, 0x27, 0xd8, 0x53,
+-			0x8f, 0x66, 0x0d, 0xe4, 0x41, 0x7d, 0x34, 0xcd,
+-			0x43, 0x7c, 0x95, 0x0a, 0x53, 0xef, 0x66, 0xda,
+-			0x7e, 0x9b, 0xf3, 0x93, 0xaf, 0xd0, 0x73, 0x71,
+-			0xba, 0x40, 0x9b, 0x74, 0xf8, 0xd7, 0xd7, 0x41,
+-			0x6d, 0xaf, 0x72, 0x9c, 0x8d, 0x21, 0x87, 0x3c,
+-			0xfd, 0x0a, 0x90, 0xa9, 0x47, 0x96, 0x9e, 0xd3,
+-			0x88, 0xee, 0x73, 0xcf, 0x66, 0x2f, 0x52, 0x56,
+-			0x6d, 0xa9, 0x80, 0x4c, 0xe2, 0x6f, 0x62, 0x88,
+-			0x3f, 0x0e, 0x54, 0x17, 0x48, 0x80, 0x5d, 0xd3,
+-			0xc3, 0xda, 0x25, 0x3d, 0xa1, 0xc8, 0xcb, 0x9f,
+-			0x9b, 0x70, 0xb3, 0xa1, 0xeb, 0x04, 0x52, 0xa1,
+-			0xf2, 0x22, 0x0f, 0xfc, 0xc8, 0x18, 0xfa, 0xf9,
+-			0x85, 0x9c, 0xf1, 0xac, 0xeb, 0x0c, 0x02, 0x46,
+-			0x75, 0xd2, 0xf5, 0x2c, 0xe3, 0xd2, 0x59, 0x94,
+-			0x12, 0xf3, 0x3c, 0xfc, 0xd7, 0x92, 0xfa, 0x36,
+-			0xba, 0x61, 0x34, 0x38, 0x7c, 0xda, 0x48, 0x3e,
+-			0x08, 0xc9, 0x39, 0x23, 0x5e, 0x02, 0x2c, 0x1a,
+-			0x18, 0x7e, 0xb4, 0xd9, 0xfd, 0x9e, 0x40, 0x02,
+-			0xb1, 0x33, 0x37, 0x32, 0xe7, 0xde, 0xd6, 0xd0,
+-			0x7c, 0x58, 0x65, 0x4b, 0xf8, 0x34, 0x27, 0x9c,
+-			0x44, 0xb4, 0xbd, 0xe9, 0xe9, 0x4c, 0x78, 0x7d,
+-			0x4b, 0x9f, 0xce, 0xb1, 0xcd, 0x47, 0xa5, 0x37,
+-			0xe5, 0x6d, 0xbd, 0xb9, 0x43, 0x94, 0x0a, 0xd4,
+-			0xd6, 0xf9, 0x04, 0x5f, 0xb5, 0x66, 0x6c, 0x1a,
+-			0x35, 0x12, 0xe3, 0x36, 0x28, 0x27, 0x36, 0x58,
+-			0x01, 0x2b, 0x79, 0xe4, 0xba, 0x6d, 0x10, 0x7d,
+-			0x65, 0xdf, 0x84, 0x95, 0xf4, 0xd5, 0xb6, 0x8f,
+-			0x2b, 0x9f, 0x96, 0x00, 0x86, 0x60, 0xf0, 0x21,
+-			0x76, 0xa8, 0x6a, 0x8c, 0x28, 0x1c, 0xb3, 0x6b,
+-			0x97, 0xd7, 0xb6, 0x53, 0x2a, 0xcc, 0xab, 0x40,
+-			0x9d, 0x62, 0x79, 0x58, 0x52, 0xe6, 0x65, 0xb7,
+-			0xab, 0x55, 0x67, 0x9c, 0x89, 0x7c, 0x03, 0xb0,
+-			0x73, 0x59, 0xc5, 0x81, 0xf5, 0x18, 0x17, 0x5c,
+-			0x89, 0xf3, 0x78, 0x35, 0x44, 0x62, 0x78, 0x72,
+-			0xd0, 0x96, 0xeb, 0x31, 0xe7, 0x87, 0x77, 0x14,
+-			0x99, 0x51, 0xf2, 0x59, 0x26, 0x9e, 0xb5, 0xa6,
+-			0x45, 0xfe, 0x6e, 0xbd, 0x07, 0x4c, 0x94, 0x5a,
+-			0xa5, 0x7d, 0xfc, 0xf1, 0x2b, 0x77, 0xe2, 0xfe,
+-			0x17, 0xd4, 0x84, 0xa0, 0xac, 0xb5, 0xc7, 0xda,
+-			0xa9, 0x1a, 0xb6, 0xf3, 0x74, 0x11, 0xb4, 0x9d,
+-			0xfb, 0x79, 0x2e, 0x04, 0x2d, 0x50, 0x28, 0x83,
+-			0xbf, 0xc6, 0x52, 0xd3, 0x34, 0xd6, 0xe8, 0x7a,
+-			0xb6, 0xea, 0xe7, 0xa8, 0x6c, 0x15, 0x1e, 0x2c,
+-			0x57, 0xbc, 0x48, 0x4e, 0x5f, 0x5c, 0xb6, 0x92,
+-			0xd2, 0x49, 0x77, 0x81, 0x6d, 0x90, 0x70, 0xae,
+-			0x98, 0xa1, 0x03, 0x0d, 0x6b, 0xb9, 0x77, 0x14,
+-			0xf1, 0x4e, 0x23, 0xd3, 0xf8, 0x68, 0xbd, 0xc2,
+-			0xfe, 0x04, 0xb7, 0x5c, 0xc5, 0x17, 0x60, 0x8f,
+-			0x65, 0x54, 0xa4, 0x7a, 0x42, 0xdc, 0x18, 0x0d,
+-			0xb5, 0xcf, 0x0f, 0xd3, 0xc7, 0x91, 0x66, 0x1b,
+-			0x45, 0x42, 0x27, 0x75, 0x50, 0xe5, 0xee, 0xb8,
+-			0x7f, 0x33, 0x2c, 0xba, 0x4a, 0x92, 0x4d, 0x2c,
+-			0x3c, 0xe3, 0x0d, 0x80, 0x01, 0xba, 0x0d, 0x29,
+-			0xd8, 0x3c, 0xe9, 0x13, 0x16, 0x57, 0xe6, 0xea,
+-			0x94, 0x52, 0xe7, 0x00, 0x4d, 0x30, 0xb0, 0x0f,
+-			0x35, 0xb8, 0xb8, 0xa7, 0xb1, 0xb5, 0x3b, 0x44,
+-			0xe1, 0x2f, 0xfd, 0x88, 0xed, 0x43, 0xe7, 0x52,
+-			0x10, 0x93, 0xb3, 0x8a, 0x30, 0x6b, 0x0a, 0xf7,
+-			0x23, 0xc6, 0x50, 0x9d, 0x4a, 0xb0, 0xde, 0xc3,
+-			0xdc, 0x9b, 0x2f, 0x01, 0x56, 0x36, 0x09, 0xc5,
+-			0x2f, 0x6b, 0xfe, 0xf1, 0xd8, 0x27, 0x45, 0x03,
+-			0x30, 0x5e, 0x5c, 0x5b, 0xb4, 0x62, 0x0e, 0x1a,
+-			0xa9, 0x21, 0x2b, 0x92, 0x94, 0x87, 0x62, 0x57,
+-			0x4c, 0x10, 0x74, 0x1a, 0xf1, 0x0a, 0xc5, 0x84,
+-			0x3b, 0x9e, 0x72, 0x02, 0xd7, 0xcc, 0x09, 0x56,
+-			0xbd, 0x54, 0xc1, 0xf0, 0xc3, 0xe3, 0xb3, 0xf8,
+-			0xd2, 0x0d, 0x61, 0xcb, 0xef, 0xce, 0x0d, 0x05,
+-			0xb0, 0x98, 0xd9, 0x8e, 0x4f, 0xf9, 0xbc, 0x93,
+-			0xa6, 0xea, 0xc8, 0xcf, 0x10, 0x53, 0x4b, 0xf1,
+-			0xec, 0xfc, 0x89, 0xf9, 0x64, 0xb0, 0x22, 0xbf,
+-			0x9e, 0x55, 0x46, 0x9f, 0x7c, 0x50, 0x8e, 0x84,
+-			0x54, 0x20, 0x98, 0xd7, 0x6c, 0x40, 0x1e, 0xdb,
+-			0x69, 0x34, 0x78, 0x61, 0x24, 0x21, 0x9c, 0x8a,
+-			0xb3, 0x62, 0x31, 0x8b, 0x6e, 0xf5, 0x2a, 0x35,
+-			0x86, 0x13, 0xb1, 0x6c, 0x64, 0x2e, 0x41, 0xa5,
+-			0x05, 0xf2, 0x42, 0xba, 0xd2, 0x3a, 0x0d, 0x8e,
+-			0x8a, 0x59, 0x94, 0x3c, 0xcf, 0x36, 0x27, 0x82,
+-			0xc2, 0x45, 0xee, 0x58, 0xcd, 0x88, 0xb4, 0xec,
+-			0xde, 0xb2, 0x96, 0x0a, 0xaf, 0x38, 0x6f, 0x88,
+-			0xd7, 0xd8, 0xe1, 0xdf, 0xb9, 0x96, 0xa9, 0x0a,
+-			0xb1, 0x95, 0x28, 0x86, 0x20, 0xe9, 0x17, 0x49,
+-			0xa2, 0x29, 0x38, 0xaa, 0xa5, 0xe9, 0x6e, 0xf1,
+-			0x19, 0x27, 0xc0, 0xd5, 0x2a, 0x22, 0xc3, 0x0b,
+-			0xdb, 0x7c, 0x73, 0x10, 0xb9, 0xba, 0x89, 0x76,
+-			0x54, 0xae, 0x7d, 0x71, 0xb3, 0x93, 0xf6, 0x32,
+-			0xe6, 0x47, 0x43, 0x55, 0xac, 0xa0, 0x0d, 0xc2,
+-			0x93, 0x27, 0x4a, 0x8e, 0x0e, 0x74, 0x15, 0xc7,
+-			0x0b, 0x85, 0xd9, 0x0c, 0xa9, 0x30, 0x7a, 0x3e,
+-			0xea, 0x8f, 0x85, 0x6d, 0x3a, 0x12, 0x4f, 0x72,
+-			0x69, 0x58, 0x7a, 0x80, 0xbb, 0xb5, 0x97, 0xf3,
+-			0xcf, 0x70, 0xd2, 0x5d, 0xdd, 0x4d, 0x21, 0x79,
+-			0x54, 0x4d, 0xe4, 0x05, 0xe8, 0xbd, 0xc2, 0x62,
+-			0xb1, 0x3b, 0x77, 0x1c, 0xd6, 0x5c, 0xf3, 0xa0,
+-			0x79, 0x00, 0xa8, 0x6c, 0x29, 0xd9, 0x18, 0x24,
+-			0x36, 0xa2, 0x46, 0xc0, 0x96, 0x65, 0x7f, 0xbd,
+-			0x2a, 0xed, 0x36, 0x16, 0x0c, 0xaa, 0x9f, 0xf4,
+-			0xc5, 0xb4, 0xe2, 0x12, 0xed, 0x69, 0xed, 0x4f,
+-			0x26, 0x2c, 0x39, 0x52, 0x89, 0x98, 0xe7, 0x2c,
+-			0x99, 0xa4, 0x9e, 0xa3, 0x9b, 0x99, 0x46, 0x7a,
+-			0x3a, 0xdc, 0xa8, 0x59, 0xa3, 0xdb, 0xc3, 0x3b,
+-			0x95, 0x0d, 0x3b, 0x09, 0x6e, 0xee, 0x83, 0x5d,
+-			0x32, 0x4d, 0xed, 0xab, 0xfa, 0x98, 0x14, 0x4e,
+-			0xc3, 0x15, 0x45, 0x53, 0x61, 0xc4, 0x93, 0xbd,
+-			0x90, 0xf4, 0x99, 0x95, 0x4c, 0xe6, 0x76, 0x92,
+-			0x29, 0x90, 0x46, 0x30, 0x92, 0x69, 0x7d, 0x13,
+-			0xf2, 0xa5, 0xcd, 0x69, 0x49, 0x44, 0xb2, 0x0f,
+-			0x63, 0x40, 0x36, 0x5f, 0x09, 0xe2, 0x78, 0xf8,
+-			0x91, 0xe3, 0xe2, 0xfa, 0x10, 0xf7, 0xc8, 0x24,
+-			0xa8, 0x89, 0x32, 0x5c, 0x37, 0x25, 0x1d, 0xb2,
+-			0xea, 0x17, 0x8a, 0x0a, 0xa9, 0x64, 0xc3, 0x7c,
+-			0x3c, 0x7c, 0xbd, 0xc6, 0x79, 0x34, 0xe7, 0xe2,
+-			0x85, 0x8e, 0xbf, 0xf8, 0xde, 0x92, 0xa0, 0xae,
+-			0x20, 0xc4, 0xf6, 0xbb, 0x1f, 0x38, 0x19, 0x0e,
+-			0xe8, 0x79, 0x9c, 0xa1, 0x23, 0xe9, 0x54, 0x7e,
+-			0x37, 0x2f, 0xe2, 0x94, 0x32, 0xaf, 0xa0, 0x23,
+-			0x49, 0xe4, 0xc0, 0xb3, 0xac, 0x00, 0x8f, 0x36,
+-			0x05, 0xc4, 0xa6, 0x96, 0xec, 0x05, 0x98, 0x4f,
+-			0x96, 0x67, 0x57, 0x1f, 0x20, 0x86, 0x1b, 0x2d,
+-			0x69, 0xe4, 0x29, 0x93, 0x66, 0x5f, 0xaf, 0x6b,
+-			0x88, 0x26, 0x2c, 0x67, 0x02, 0x4b, 0x52, 0xd0,
+-			0x83, 0x7a, 0x43, 0x1f, 0xc0, 0x71, 0x15, 0x25,
+-			0x77, 0x65, 0x08, 0x60, 0x11, 0x76, 0x4c, 0x8d,
+-			0xed, 0xa9, 0x27, 0xc6, 0xb1, 0x2a, 0x2c, 0x6a,
+-			0x4a, 0x97, 0xf5, 0xc6, 0xb7, 0x70, 0x42, 0xd3,
+-			0x03, 0xd1, 0x24, 0x95, 0xec, 0x6d, 0xab, 0x38,
+-			0x72, 0xce, 0xe2, 0x8b, 0x33, 0xd7, 0x51, 0x09,
+-			0xdc, 0x45, 0xe0, 0x09, 0x96, 0x32, 0xf3, 0xc4,
+-			0x84, 0xdc, 0x73, 0x73, 0x2d, 0x1b, 0x11, 0x98,
+-			0xc5, 0x0e, 0x69, 0x28, 0x94, 0xc7, 0xb5, 0x4d,
+-			0xc8, 0x8a, 0xd0, 0xaa, 0x13, 0x2e, 0x18, 0x74,
+-			0xdd, 0xd1, 0x1e, 0xf3, 0x90, 0xe8, 0xfc, 0x9a,
+-			0x72, 0x4a, 0x0e, 0xd1, 0xe4, 0xfb, 0x0d, 0x96,
+-			0xd1, 0x0c, 0x79, 0x85, 0x1b, 0x1c, 0xfe, 0xe1,
+-			0x62, 0x8f, 0x7a, 0x73, 0x32, 0xab, 0xc8, 0x18,
+-			0x69, 0xe3, 0x34, 0x30, 0xdf, 0x13, 0xa6, 0xe5,
+-			0xe8, 0x0e, 0x67, 0x7f, 0x81, 0x11, 0xb4, 0x60,
+-			0xc7, 0xbd, 0x79, 0x65, 0x50, 0xdc, 0xc4, 0x5b,
+-			0xde, 0x39, 0xa4, 0x01, 0x72, 0x63, 0xf3, 0xd1,
+-			0x64, 0x4e, 0xdf, 0xfc, 0x27, 0x92, 0x37, 0x0d,
+-			0x57, 0xcd, 0x11, 0x4f, 0x11, 0x04, 0x8e, 0x1d,
+-			0x16, 0xf7, 0xcd, 0x92, 0x9a, 0x99, 0x30, 0x14,
+-			0xf1, 0x7c, 0x67, 0x1b, 0x1f, 0x41, 0x0b, 0xe8,
+-			0x32, 0xe8, 0xb8, 0xc1, 0x4f, 0x54, 0x86, 0x4f,
+-			0xe5, 0x79, 0x81, 0x73, 0xcd, 0x43, 0x59, 0x68,
+-			0x73, 0x02, 0x3b, 0x78, 0x21, 0x72, 0x43, 0x00,
+-			0x49, 0x17, 0xf7, 0x00, 0xaf, 0x68, 0x24, 0x53,
+-			0x05, 0x0a, 0xc3, 0x33, 0xe0, 0x33, 0x3f, 0x69,
+-			0xd2, 0x84, 0x2f, 0x0b, 0xed, 0xde, 0x04, 0xf4,
+-			0x11, 0x94, 0x13, 0x69, 0x51, 0x09, 0x28, 0xde,
+-			0x57, 0x5c, 0xef, 0xdc, 0x9a, 0x49, 0x1c, 0x17,
+-			0x97, 0xf3, 0x96, 0xc1, 0x7f, 0x5d, 0x2e, 0x7d,
+-			0x55, 0xb8, 0xb3, 0x02, 0x09, 0xb3, 0x1f, 0xe7,
+-			0xc9, 0x8d, 0xa3, 0x36, 0x34, 0x8a, 0x77, 0x13,
+-			0x30, 0x63, 0x4c, 0xa5, 0xcd, 0xc3, 0xe0, 0x7e,
+-			0x05, 0xa1, 0x7b, 0x0c, 0xcb, 0x74, 0x47, 0x31,
+-			0x62, 0x03, 0x43, 0xf1, 0x87, 0xb4, 0xb0, 0x85,
+-			0x87, 0x8e, 0x4b, 0x25, 0xc7, 0xcf, 0xae, 0x4b,
+-			0x36, 0x46, 0x3e, 0x62, 0xbc, 0x6f, 0xeb, 0x5f,
+-			0x73, 0xac, 0xe6, 0x07, 0xee, 0xc1, 0xa1, 0xd6,
+-			0xc4, 0xab, 0xc9, 0xd6, 0x89, 0x45, 0xe1, 0xf1,
+-			0x04, 0x4e, 0x1a, 0x6f, 0xbb, 0x4f, 0x3a, 0xa3,
+-			0xa0, 0xcb, 0xa3, 0x0a, 0xd8, 0x71, 0x35, 0x55,
+-			0xe4, 0xbc, 0x2e, 0x04, 0x06, 0xe6, 0xff, 0x5b,
+-			0x1c, 0xc0, 0x11, 0x7c, 0xc5, 0x17, 0xf3, 0x38,
+-			0xcf, 0xe9, 0xba, 0x0f, 0x0e, 0xef, 0x02, 0xc2,
+-			0x8d, 0xc6, 0xbc, 0x4b, 0x67, 0x20, 0x95, 0xd7,
+-			0x2c, 0x45, 0x5b, 0x86, 0x44, 0x8c, 0x6f, 0x2e,
+-			0x7e, 0x9f, 0x1c, 0x77, 0xba, 0x6b, 0x0e, 0xa3,
+-			0x69, 0xdc, 0xab, 0x24, 0x57, 0x60, 0x47, 0xc1,
+-			0xd1, 0xa5, 0x9d, 0x23, 0xe6, 0xb1, 0x37, 0xfe,
+-			0x93, 0xd2, 0x4c, 0x46, 0xf9, 0x0c, 0xc6, 0xfb,
+-			0xd6, 0x9d, 0x99, 0x69, 0xab, 0x7a, 0x07, 0x0c,
+-			0x65, 0xe7, 0xc4, 0x08, 0x96, 0xe2, 0xa5, 0x01,
+-			0x3f, 0x46, 0x07, 0x05, 0x7e, 0xe8, 0x9a, 0x90,
+-			0x50, 0xdc, 0xe9, 0x7a, 0xea, 0xa1, 0x39, 0x6e,
+-			0x66, 0xe4, 0x6f, 0xa5, 0x5f, 0xb2, 0xd9, 0x5b,
+-			0xf5, 0xdb, 0x2a, 0x32, 0xf0, 0x11, 0x6f, 0x7c,
+-			0x26, 0x10, 0x8f, 0x3d, 0x80, 0xe9, 0x58, 0xf7,
+-			0xe0, 0xa8, 0x57, 0xf8, 0xdb, 0x0e, 0xce, 0x99,
+-			0x63, 0x19, 0x3d, 0xd5, 0xec, 0x1b, 0x77, 0x69,
+-			0x98, 0xf6, 0xe4, 0x5f, 0x67, 0x17, 0x4b, 0x09,
+-			0x85, 0x62, 0x82, 0x70, 0x18, 0xe2, 0x9a, 0x78,
+-			0xe2, 0x62, 0xbd, 0xb4, 0xf1, 0x42, 0xc6, 0xfb,
+-			0x08, 0xd0, 0xbd, 0xeb, 0x4e, 0x09, 0xf2, 0xc8,
+-			0x1e, 0xdc, 0x3d, 0x32, 0x21, 0x56, 0x9c, 0x4f,
+-			0x35, 0xf3, 0x61, 0x06, 0x72, 0x84, 0xc4, 0x32,
+-			0xf2, 0xf1, 0xfa, 0x0b, 0x2f, 0xc3, 0xdb, 0x02,
+-			0x04, 0xc2, 0xde, 0x57, 0x64, 0x60, 0x8d, 0xcf,
+-			0xcb, 0x86, 0x5d, 0x97, 0x3e, 0xb1, 0x9c, 0x01,
+-			0xd6, 0x28, 0x8f, 0x99, 0xbc, 0x46, 0xeb, 0x05,
+-			0xaf, 0x7e, 0xb8, 0x21, 0x2a, 0x56, 0x85, 0x1c,
+-			0xb3, 0x71, 0xa0, 0xde, 0xca, 0x96, 0xf1, 0x78,
+-			0x49, 0xa2, 0x99, 0x81, 0x80, 0x5c, 0x01, 0xf5,
+-			0xa0, 0xa2, 0x56, 0x63, 0xe2, 0x70, 0x07, 0xa5,
+-			0x95, 0xd6, 0x85, 0xeb, 0x36, 0x9e, 0xa9, 0x51,
+-			0x66, 0x56, 0x5f, 0x1d, 0x02, 0x19, 0xe2, 0xf6,
+-			0x4f, 0x73, 0x38, 0x09, 0x75, 0x64, 0x48, 0xe0,
+-			0xf1, 0x7e, 0x0e, 0xe8, 0x9d, 0xf9, 0xed, 0x94,
+-			0xfe, 0x16, 0x26, 0x62, 0x49, 0x74, 0xf4, 0xb0,
+-			0xd4, 0xa9, 0x6c, 0xb0, 0xfd, 0x53, 0xe9, 0x81,
+-			0xe0, 0x7a, 0xbf, 0xcf, 0xb5, 0xc4, 0x01, 0x81,
+-			0x79, 0x99, 0x77, 0x01, 0x3b, 0xe9, 0xa2, 0xb6,
+-			0xe6, 0x6a, 0x8a, 0x9e, 0x56, 0x1c, 0x8d, 0x1e,
+-			0x8f, 0x06, 0x55, 0x2c, 0x6c, 0xdc, 0x92, 0x87,
+-			0x64, 0x3b, 0x4b, 0x19, 0xa1, 0x13, 0x64, 0x1d,
+-			0x4a, 0xe9, 0xc0, 0x00, 0xb8, 0x95, 0xef, 0x6b,
+-			0x1a, 0x86, 0x6d, 0x37, 0x52, 0x02, 0xc2, 0xe0,
+-			0xc8, 0xbb, 0x42, 0x0c, 0x02, 0x21, 0x4a, 0xc9,
+-			0xef, 0xa0, 0x54, 0xe4, 0x5e, 0x16, 0x53, 0x81,
+-			0x70, 0x62, 0x10, 0xaf, 0xde, 0xb8, 0xb5, 0xd3,
+-			0xe8, 0x5e, 0x6c, 0xc3, 0x8a, 0x3e, 0x18, 0x07,
+-			0xf2, 0x2f, 0x7d, 0xa7, 0xe1, 0x3d, 0x4e, 0xb4,
+-			0x26, 0xa7, 0xa3, 0x93, 0x86, 0xb2, 0x04, 0x1e,
+-			0x53, 0x5d, 0x86, 0xd6, 0xde, 0x65, 0xca, 0xe3,
+-			0x4e, 0xc1, 0xcf, 0xef, 0xc8, 0x70, 0x1b, 0x83,
+-			0x13, 0xdd, 0x18, 0x8b, 0x0d, 0x76, 0xd2, 0xf6,
+-			0x37, 0x7a, 0x93, 0x7a, 0x50, 0x11, 0x9f, 0x96,
+-			0x86, 0x25, 0xfd, 0xac, 0xdc, 0xbe, 0x18, 0x93,
+-			0x19, 0x6b, 0xec, 0x58, 0x4f, 0xb9, 0x75, 0xa7,
+-			0xdd, 0x3f, 0x2f, 0xec, 0xc8, 0x5a, 0x84, 0xab,
+-			0xd5, 0xe4, 0x8a, 0x07, 0xf6, 0x4d, 0x23, 0xd6,
+-			0x03, 0xfb, 0x03, 0x6a, 0xea, 0x66, 0xbf, 0xd4,
+-			0xb1, 0x34, 0xfb, 0x78, 0xe9, 0x55, 0xdc, 0x7c,
+-			0x3d, 0x9c, 0xe5, 0x9a, 0xac, 0xc3, 0x7a, 0x80,
+-			0x24, 0x6d, 0xa0, 0xef, 0x25, 0x7c, 0xb7, 0xea,
+-			0xce, 0x4d, 0x5f, 0x18, 0x60, 0xce, 0x87, 0x22,
+-			0x66, 0x2f, 0xd5, 0xdd, 0xdd, 0x02, 0x21, 0x75,
+-			0x82, 0xa0, 0x1f, 0x58, 0xc6, 0xd3, 0x62, 0xf7,
+-			0x32, 0xd8, 0xaf, 0x1e, 0x07, 0x77, 0x51, 0x96,
+-			0xd5, 0x6b, 0x1e, 0x7e, 0x80, 0x02, 0xe8, 0x67,
+-			0xea, 0x17, 0x0b, 0x10, 0xd2, 0x3f, 0x28, 0x25,
+-			0x4f, 0x05, 0x77, 0x02, 0x14, 0x69, 0xf0, 0x2c,
+-			0xbe, 0x0c, 0xf1, 0x74, 0x30, 0xd1, 0xb9, 0x9b,
+-			0xfc, 0x8c, 0xbb, 0x04, 0x16, 0xd9, 0xba, 0xc3,
+-			0xbc, 0x91, 0x8a, 0xc4, 0x30, 0xa4, 0xb0, 0x12,
+-			0x4c, 0x21, 0x87, 0xcb, 0xc9, 0x1d, 0x16, 0x96,
+-			0x07, 0x6f, 0x23, 0x54, 0xb9, 0x6f, 0x79, 0xe5,
+-			0x64, 0xc0, 0x64, 0xda, 0xb1, 0xae, 0xdd, 0x60,
+-			0x6c, 0x1a, 0x9d, 0xd3, 0x04, 0x8e, 0x45, 0xb0,
+-			0x92, 0x61, 0xd0, 0x48, 0x81, 0xed, 0x5e, 0x1d,
+-			0xa0, 0xc9, 0xa4, 0x33, 0xc7, 0x13, 0x51, 0x5d,
+-			0x7f, 0x83, 0x73, 0xb6, 0x70, 0x18, 0x65, 0x3e,
+-			0x2f, 0x0e, 0x7a, 0x12, 0x39, 0x98, 0xab, 0xd8,
+-			0x7e, 0x6f, 0xa3, 0xd1, 0xba, 0x56, 0xad, 0xbd,
+-			0xf0, 0x03, 0x01, 0x1c, 0x85, 0x35, 0x9f, 0xeb,
+-			0x19, 0x63, 0xa1, 0xaf, 0xfe, 0x2d, 0x35, 0x50,
+-			0x39, 0xa0, 0x65, 0x7c, 0x95, 0x7e, 0x6b, 0xfe,
+-			0xc1, 0xac, 0x07, 0x7c, 0x98, 0x4f, 0xbe, 0x57,
+-			0xa7, 0x22, 0xec, 0xe2, 0x7e, 0x29, 0x09, 0x53,
+-			0xe8, 0xbf, 0xb4, 0x7e, 0x3f, 0x8f, 0xfc, 0x14,
+-			0xce, 0x54, 0xf9, 0x18, 0x58, 0xb5, 0xff, 0x44,
+-			0x05, 0x9d, 0xce, 0x1b, 0xb6, 0x82, 0x23, 0xc8,
+-			0x2e, 0xbc, 0x69, 0xbb, 0x4a, 0x29, 0x0f, 0x65,
+-			0x94, 0xf0, 0x63, 0x06, 0x0e, 0xef, 0x8c, 0xbd,
+-			0xff, 0xfd, 0xb0, 0x21, 0x6e, 0x57, 0x05, 0x75,
+-			0xda, 0xd5, 0xc4, 0xeb, 0x8d, 0x32, 0xf7, 0x50,
+-			0xd3, 0x6f, 0x22, 0xed, 0x5f, 0x8e, 0xa2, 0x5b,
+-			0x80, 0x8c, 0xc8, 0x78, 0x40, 0x24, 0x4b, 0x89,
+-			0x30, 0xce, 0x7a, 0x97, 0x0e, 0xc4, 0xaf, 0xef,
+-			0x9b, 0xb4, 0xcd, 0x66, 0x74, 0x14, 0x04, 0x2b,
+-			0xf7, 0xce, 0x0b, 0x1c, 0x6e, 0xc2, 0x78, 0x8c,
+-			0xca, 0xc5, 0xd0, 0x1c, 0x95, 0x4a, 0x91, 0x2d,
+-			0xa7, 0x20, 0xeb, 0x86, 0x52, 0xb7, 0x67, 0xd8,
+-			0x0c, 0xd6, 0x04, 0x14, 0xde, 0x51, 0x74, 0x75,
+-			0xe7, 0x11, 0xb4, 0x87, 0xa3, 0x3d, 0x2d, 0xad,
+-			0x4f, 0xef, 0xa0, 0x0f, 0x70, 0x00, 0x6d, 0x13,
+-			0x19, 0x1d, 0x41, 0x50, 0xe9, 0xd8, 0xf0, 0x32,
+-			0x71, 0xbc, 0xd3, 0x11, 0xf2, 0xac, 0xbe, 0xaf,
+-			0x75, 0x46, 0x65, 0x4e, 0x07, 0x34, 0x37, 0xa3,
+-			0x89, 0xfe, 0x75, 0xd4, 0x70, 0x4c, 0xc6, 0x3f,
+-			0x69, 0x24, 0x0e, 0x38, 0x67, 0x43, 0x8c, 0xde,
+-			0x06, 0xb5, 0xb8, 0xe7, 0xc4, 0xf0, 0x41, 0x8f,
+-			0xf0, 0xbd, 0x2f, 0x0b, 0xb9, 0x18, 0xf8, 0xde,
+-			0x64, 0xb1, 0xdb, 0xee, 0x00, 0x50, 0x77, 0xe1,
+-			0xc7, 0xff, 0xa6, 0xfa, 0xdd, 0x70, 0xf4, 0xe3,
+-			0x93, 0xe9, 0x77, 0x35, 0x3d, 0x4b, 0x2f, 0x2b,
+-			0x6d, 0x55, 0xf0, 0xfc, 0x88, 0x54, 0x4e, 0x89,
+-			0xc1, 0x8a, 0x23, 0x31, 0x2d, 0x14, 0x2a, 0xb8,
+-			0x1b, 0x15, 0xdd, 0x9e, 0x6e, 0x7b, 0xda, 0x05,
+-			0x91, 0x7d, 0x62, 0x64, 0x96, 0x72, 0xde, 0xfc,
+-			0xc1, 0xec, 0xf0, 0x23, 0x51, 0x6f, 0xdb, 0x5b,
+-			0x1d, 0x08, 0x57, 0xce, 0x09, 0xb8, 0xf6, 0xcd,
+-			0x8d, 0x95, 0xf2, 0x20, 0xbf, 0x0f, 0x20, 0x57,
+-			0x98, 0x81, 0x84, 0x4f, 0x15, 0x5c, 0x76, 0xe7,
+-			0x3e, 0x0a, 0x3a, 0x6c, 0xc4, 0x8a, 0xbe, 0x78,
+-			0x74, 0x77, 0xc3, 0x09, 0x4b, 0x5d, 0x48, 0xe4,
+-			0xc8, 0xcb, 0x0b, 0xea, 0x17, 0x28, 0xcf, 0xcf,
+-			0x31, 0x32, 0x44, 0xa4, 0xe5, 0x0e, 0x1a, 0x98,
+-			0x94, 0xc4, 0xf0, 0xff, 0xae, 0x3e, 0x44, 0xe8,
+-			0xa5, 0xb3, 0xb5, 0x37, 0x2f, 0xe8, 0xaf, 0x6f,
+-			0x28, 0xc1, 0x37, 0x5f, 0x31, 0xd2, 0xb9, 0x33,
+-			0xb1, 0xb2, 0x52, 0x94, 0x75, 0x2c, 0x29, 0x59,
+-			0x06, 0xc2, 0x25, 0xe8, 0x71, 0x65, 0x4e, 0xed,
+-			0xc0, 0x9c, 0xb1, 0xbb, 0x25, 0xdc, 0x6c, 0xe7,
+-			0x4b, 0xa5, 0x7a, 0x54, 0x7a, 0x60, 0xff, 0x7a,
+-			0xe0, 0x50, 0x40, 0x96, 0x35, 0x63, 0xe4, 0x0b,
+-			0x76, 0xbd, 0xa4, 0x65, 0x00, 0x1b, 0x57, 0x88,
+-			0xae, 0xed, 0x39, 0x88, 0x42, 0x11, 0x3c, 0xed,
+-			0x85, 0x67, 0x7d, 0xb9, 0x68, 0x82, 0xe9, 0x43,
+-			0x3c, 0x47, 0x53, 0xfa, 0xe8, 0xf8, 0x9f, 0x1f,
+-			0x9f, 0xef, 0x0f, 0xf7, 0x30, 0xd9, 0x30, 0x0e,
+-			0xb9, 0x9f, 0x69, 0x18, 0x2f, 0x7e, 0xf8, 0xf8,
+-			0xf8, 0x8c, 0x0f, 0xd4, 0x02, 0x4d, 0xea, 0xcd,
+-			0x0a, 0x9c, 0x6f, 0x71, 0x6d, 0x5a, 0x4c, 0x60,
+-			0xce, 0x20, 0x56, 0x32, 0xc6, 0xc5, 0x99, 0x1f,
+-			0x09, 0xe6, 0x4e, 0x18, 0x1a, 0x15, 0x13, 0xa8,
+-			0x7d, 0xb1, 0x6b, 0xc0, 0xb2, 0x6d, 0xf8, 0x26,
+-			0x66, 0xf8, 0x3d, 0x18, 0x74, 0x70, 0x66, 0x7a,
+-			0x34, 0x17, 0xde, 0xba, 0x47, 0xf1, 0x06, 0x18,
+-			0xcb, 0xaf, 0xeb, 0x4a, 0x1e, 0x8f, 0xa7, 0x77,
+-			0xe0, 0x3b, 0x78, 0x62, 0x66, 0xc9, 0x10, 0xea,
+-			0x1f, 0xb7, 0x29, 0x0a, 0x45, 0xa1, 0x1d, 0x1e,
+-			0x1d, 0xe2, 0x65, 0x61, 0x50, 0x9c, 0xd7, 0x05,
+-			0xf2, 0x0b, 0x5b, 0x12, 0x61, 0x02, 0xc8, 0xe5,
+-			0x63, 0x4f, 0x20, 0x0c, 0x07, 0x17, 0x33, 0x5e,
+-			0x03, 0x9a, 0x53, 0x0f, 0x2e, 0x55, 0xfe, 0x50,
+-			0x43, 0x7d, 0xd0, 0xb6, 0x7e, 0x5a, 0xda, 0xae,
+-			0x58, 0xef, 0x15, 0xa9, 0x83, 0xd9, 0x46, 0xb1,
+-			0x42, 0xaa, 0xf5, 0x02, 0x6c, 0xce, 0x92, 0x06,
+-			0x1b, 0xdb, 0x66, 0x45, 0x91, 0x79, 0xc2, 0x2d,
+-			0xe6, 0x53, 0xd3, 0x14, 0xfd, 0xbb, 0x44, 0x63,
+-			0xc6, 0xd7, 0x3d, 0x7a, 0x0c, 0x75, 0x78, 0x9d,
+-			0x5c, 0xa6, 0x39, 0xb3, 0xe5, 0x63, 0xca, 0x8b,
+-			0xfe, 0xd3, 0xef, 0x60, 0x83, 0xf6, 0x8e, 0x70,
+-			0xb6, 0x67, 0xc7, 0x77, 0xed, 0x23, 0xef, 0x4c,
+-			0xf0, 0xed, 0x2d, 0x07, 0x59, 0x6f, 0xc1, 0x01,
+-			0x34, 0x37, 0x08, 0xab, 0xd9, 0x1f, 0x09, 0xb1,
+-			0xce, 0x5b, 0x17, 0xff, 0x74, 0xf8, 0x9c, 0xd5,
+-			0x2c, 0x56, 0x39, 0x79, 0x0f, 0x69, 0x44, 0x75,
+-			0x58, 0x27, 0x01, 0xc4, 0xbf, 0xa7, 0xa1, 0x1d,
+-			0x90, 0x17, 0x77, 0x86, 0x5a, 0x3f, 0xd9, 0xd1,
+-			0x0e, 0xa0, 0x10, 0xf8, 0xec, 0x1e, 0xa5, 0x7f,
+-			0x5e, 0x36, 0xd1, 0xe3, 0x04, 0x2c, 0x70, 0xf7,
+-			0x8e, 0xc0, 0x98, 0x2f, 0x6c, 0x94, 0x2b, 0x41,
+-			0xb7, 0x60, 0x00, 0xb7, 0x2e, 0xb8, 0x02, 0x8d,
+-			0xb8, 0xb0, 0xd3, 0x86, 0xba, 0x1d, 0xd7, 0x90,
+-			0xd6, 0xb6, 0xe1, 0xfc, 0xd7, 0xd8, 0x28, 0x06,
+-			0x63, 0x9b, 0xce, 0x61, 0x24, 0x79, 0xc0, 0x70,
+-			0x52, 0xd0, 0xb6, 0xd4, 0x28, 0x95, 0x24, 0x87,
+-			0x03, 0x1f, 0xb7, 0x9a, 0xda, 0xa3, 0xfb, 0x52,
+-			0x5b, 0x68, 0xe7, 0x4c, 0x8c, 0x24, 0xe1, 0x42,
+-			0xf7, 0xd5, 0xfd, 0xad, 0x06, 0x32, 0x9f, 0xba,
+-			0xc1, 0xfc, 0xdd, 0xc6, 0xfc, 0xfc, 0xb3, 0x38,
+-			0x74, 0x56, 0x58, 0x40, 0x02, 0x37, 0x52, 0x2c,
+-			0x55, 0xcc, 0xb3, 0x9e, 0x7a, 0xe9, 0xd4, 0x38,
+-			0x41, 0x5e, 0x0c, 0x35, 0xe2, 0x11, 0xd1, 0x13,
+-			0xf8, 0xb7, 0x8d, 0x72, 0x6b, 0x22, 0x2a, 0xb0,
+-			0xdb, 0x08, 0xba, 0x35, 0xb9, 0x3f, 0xc8, 0xd3,
+-			0x24, 0x90, 0xec, 0x58, 0xd2, 0x09, 0xc7, 0x2d,
+-			0xed, 0x38, 0x80, 0x36, 0x72, 0x43, 0x27, 0x49,
+-			0x4a, 0x80, 0x8a, 0xa2, 0xe8, 0xd3, 0xda, 0x30,
+-			0x7d, 0xb6, 0x82, 0x37, 0x86, 0x92, 0x86, 0x3e,
+-			0x08, 0xb2, 0x28, 0x5a, 0x55, 0x44, 0x24, 0x7d,
+-			0x40, 0x48, 0x8a, 0xb6, 0x89, 0x58, 0x08, 0xa0,
+-			0xd6, 0x6d, 0x3a, 0x17, 0xbf, 0xf6, 0x54, 0xa2,
+-			0xf5, 0xd3, 0x8c, 0x0f, 0x78, 0x12, 0x57, 0x8b,
+-			0xd5, 0xc2, 0xfd, 0x58, 0x5b, 0x7f, 0x38, 0xe3,
+-			0xcc, 0xb7, 0x7c, 0x48, 0xb3, 0x20, 0xe8, 0x81,
+-			0x14, 0x32, 0x45, 0x05, 0xe0, 0xdb, 0x9f, 0x75,
+-			0x85, 0xb4, 0x6a, 0xfc, 0x95, 0xe3, 0x54, 0x22,
+-			0x12, 0xee, 0x30, 0xfe, 0xd8, 0x30, 0xef, 0x34,
+-			0x50, 0xab, 0x46, 0x30, 0x98, 0x2f, 0xb7, 0xc0,
+-			0x15, 0xa2, 0x83, 0xb6, 0xf2, 0x06, 0x21, 0xa2,
+-			0xc3, 0x26, 0x37, 0x14, 0xd1, 0x4d, 0xb5, 0x10,
+-			0x52, 0x76, 0x4d, 0x6a, 0xee, 0xb5, 0x2b, 0x15,
+-			0xb7, 0xf9, 0x51, 0xe8, 0x2a, 0xaf, 0xc7, 0xfa,
+-			0x77, 0xaf, 0xb0, 0x05, 0x4d, 0xd1, 0x68, 0x8e,
+-			0x74, 0x05, 0x9f, 0x9d, 0x93, 0xa5, 0x3e, 0x7f,
+-			0x4e, 0x5f, 0x9d, 0xcb, 0x09, 0xc7, 0x83, 0xe3,
+-			0x02, 0x9d, 0x27, 0x1f, 0xef, 0x85, 0x05, 0x8d,
+-			0xec, 0x55, 0x88, 0x0f, 0x0d, 0x7c, 0x4c, 0xe8,
+-			0xa1, 0x75, 0xa0, 0xd8, 0x06, 0x47, 0x14, 0xef,
+-			0xaa, 0x61, 0xcf, 0x26, 0x15, 0xad, 0xd8, 0xa3,
+-			0xaa, 0x75, 0xf2, 0x78, 0x4a, 0x5a, 0x61, 0xdf,
+-			0x8b, 0xc7, 0x04, 0xbc, 0xb2, 0x32, 0xd2, 0x7e,
+-			0x42, 0xee, 0xb4, 0x2f, 0x51, 0xff, 0x7b, 0x2e,
+-			0xd3, 0x02, 0xe8, 0xdc, 0x5d, 0x0d, 0x50, 0xdc,
+-			0xae, 0xb7, 0x46, 0xf9, 0xa8, 0xe6, 0xd0, 0x16,
+-			0xcc, 0xe6, 0x2c, 0x81, 0xc7, 0xad, 0xe9, 0xf0,
+-			0x05, 0x72, 0x6d, 0x3d, 0x0a, 0x7a, 0xa9, 0x02,
+-			0xac, 0x82, 0x93, 0x6e, 0xb6, 0x1c, 0x28, 0xfc,
+-			0x44, 0x12, 0xfb, 0x73, 0x77, 0xd4, 0x13, 0x39,
+-			0x29, 0x88, 0x8a, 0xf3, 0x5c, 0xa6, 0x36, 0xa0,
+-			0x2a, 0xed, 0x7e, 0xb1, 0x1d, 0xd6, 0x4c, 0x6b,
+-			0x41, 0x01, 0x18, 0x5d, 0x5d, 0x07, 0x97, 0xa6,
+-			0x4b, 0xef, 0x31, 0x18, 0xea, 0xac, 0xb1, 0x84,
+-			0x21, 0xed, 0xda, 0x86,
+-		},
++		.result =
++			"\xf0\x5c\x74\xad\x4e\xbc\x99\xe2"
++			"\xae\xff\x91\x3a\x44\xcf\x38\x32"
++			"\x1e\xad\xa7\xcd\xa1\x39\x95\xaa"
++			"\x10\xb1\xb3\x2e\x04\x31\x8f\x86"
++			"\xf2\x62\x74\x70\x0c\xa4\x46\x08"
++			"\xa8\xb7\x99\xa8\xe9\xd2\x73\x79"
++			"\x7e\x6e\xd4\x8f\x1e\xc7\x8e\x31"
++			"\x0b\xfa\x4b\xce\xfd\xf3\x57\x71"
++			"\xe9\x46\x03\xa5\x3d\x34\x00\xe2"
++			"\x18\xff\x75\x6d\x06\x2d\x00\xab"
++			"\xb9\x3e\x6c\x59\xc5\x84\x06\xb5"
++			"\x8b\xd0\x89\x9c\x4a\x79\x16\xc6"
++			"\x3d\x74\x54\xfa\x44\xcd\x23\x26"
++			"\x5c\xcf\x7e\x28\x92\x32\xbf\xdf"
++			"\xa7\x20\x3c\x74\x58\x2a\x9a\xde"
++			"\x61\x00\x1c\x4f\xff\x59\xc4\x22"
++			"\xac\x3c\xd0\xe8\x6c\xf9\x97\x1b"
++			"\x58\x9b\xad\x71\xe8\xa9\xb5\x0d"
++			"\xee\x2f\x04\x1f\x7f\xbc\x99\xee"
++			"\x84\xff\x42\x60\xdc\x3a\x18\xa5"
++			"\x81\xf9\xef\xdc\x7a\x0f\x65\x41"
++			"\x2f\xa3\xd3\xf9\xc2\xcb\xc0\x4d"
++			"\x8f\xd3\x76\x96\xad\x49\x6d\x38"
++			"\x3d\x39\x0b\x6c\x80\xb7\x54\x69"
++			"\xf0\x2c\x90\x02\x29\x0d\x1c\x12"
++			"\xad\x55\xc3\x8b\x68\xd9\xcc\xb3"
++			"\xb2\x64\x33\x90\x5e\xca\x4b\xe2"
++			"\xfb\x75\xdc\x63\xf7\x9f\x82\x74"
++			"\xf0\xc9\xaa\x7f\xe9\x2a\x9b\x33"
++			"\xbc\x88\x00\x7f\xca\xb2\x1f\x14"
++			"\xdb\xc5\x8e\x7b\x11\x3c\x3e\x08"
++			"\xf3\x83\xe8\xe0\x94\x86\x2e\x92"
++			"\x78\x6b\x01\xc9\xc7\x83\xba\x21"
++			"\x6a\x25\x15\x33\x4e\x45\x08\xec"
++			"\x35\xdb\xe0\x6e\x31\x51\x79\xa9"
++			"\x42\x44\x65\xc1\xa0\xf1\xf9\x2a"
++			"\x70\xd5\xb6\xc6\xc1\x8c\x39\xfc"
++			"\x25\xa6\x55\xd9\xdd\x2d\x4c\xec"
++			"\x49\xc6\xeb\x0e\xa8\x25\x2a\x16"
++			"\x1b\x66\x84\xda\xe2\x92\xe5\xc0"
++			"\xc8\x53\x07\xaf\x80\x84\xec\xfd"
++			"\xcd\xd1\x6e\xcd\x6f\x6a\xf5\x36"
++			"\xc5\x15\xe5\x25\x7d\x77\xd1\x1a"
++			"\x93\x36\xa9\xcf\x7c\xa4\x54\x4a"
++			"\x06\x51\x48\x4e\xf6\x59\x87\xd2"
++			"\x04\x02\xef\xd3\x44\xde\x76\x31"
++			"\xb3\x34\x17\x1b\x9d\x66\x11\x9f"
++			"\x1e\xcc\x17\xe9\xc7\x3c\x1b\xe7"
++			"\xcb\x50\x08\xfc\xdc\x2b\x24\xdb"
++			"\x65\x83\xd0\x3b\xe3\x30\xea\x94"
++			"\x6c\xe7\xe8\x35\x32\xc7\xdb\x64"
++			"\xb4\x01\xab\x36\x2c\x77\x13\xaf"
++			"\xf8\x2b\x88\x3f\x54\x39\xc4\x44"
++			"\xfe\xef\x6f\x68\x34\xbe\x0f\x05"
++			"\x16\x6d\xf6\x0a\x30\xe7\xe3\xed"
++			"\xc4\xde\x3c\x1b\x13\xd8\xdb\xfe"
++			"\x41\x62\xe5\x28\xd4\x8d\xa3\xc7"
++			"\x93\x97\xc6\x48\x45\x1d\x9f\x83"
++			"\xdf\x4b\x40\x3e\x42\x25\x87\x80"
++			"\x4c\x7d\xa8\xd4\x98\x23\x95\x75"
++			"\x41\x8c\xda\x41\x9b\xd4\xa7\x06"
++			"\xb5\xf1\x71\x09\x53\xbe\xca\xbf"
++			"\x32\x03\xed\xf0\x50\x1c\x56\x39"
++			"\x5b\xa4\x75\x18\xf7\x9b\x58\xef"
++			"\x53\xfc\x2a\x38\x23\x15\x75\xcd"
++			"\x45\xe5\x5a\x82\x55\xba\x21\xfa"
++			"\xd4\xbd\xc6\x94\x7c\xc5\x80\x12"
++			"\xf7\x4b\x32\xc4\x9a\x82\xd8\x28"
++			"\x8f\xd9\xc2\x0f\x60\x03\xbe\x5e"
++			"\x21\xd6\x5f\x58\xbf\x5c\xb1\x32"
++			"\x82\x8d\xa9\xe5\xf2\x66\x1a\xc0"
++			"\xa0\xbc\x58\x2f\x71\xf5\x2f\xed"
++			"\xd1\x26\xb9\xd8\x49\x5a\x07\x19"
++			"\x01\x7c\x59\xb0\xf8\xa4\xb7\xd3"
++			"\x7b\x1a\x8c\x38\xf4\x50\xa4\x59"
++			"\xb0\xcc\x41\x0b\x88\x7f\xe5\x31"
++			"\xb3\x42\xba\xa2\x7e\xd4\x32\x71"
++			"\x45\x87\x48\xa9\xc2\xf2\x89\xb3"
++			"\xe4\xa7\x7e\x52\x15\x61\xfa\xfe"
++			"\xc9\xdd\x81\xeb\x13\xab\xab\xc3"
++			"\x98\x59\xd8\x16\x3d\x14\x7a\x1c"
++			"\x3c\x41\x9a\x16\x16\x9b\xd2\xd2"
++			"\x69\x3a\x29\x23\xac\x86\x32\xa5"
++			"\x48\x9c\x9e\xf3\x47\x77\x81\x70"
++			"\x24\xe8\x85\xd2\xf5\xb5\xfa\xff"
++			"\x59\x6a\xd3\x50\x59\x43\x59\xde"
++			"\xd9\xf1\x55\xa5\x0c\xc3\x1a\x1a"
++			"\x18\x34\x0d\x1a\x63\x33\xed\x10"
++			"\xe0\x1d\x2a\x18\xd2\xc0\x54\xa8"
++			"\xca\xb5\x9a\xd3\xdd\xca\x45\x84"
++			"\x50\xe7\x0f\xfe\xa4\x99\x5a\xbe"
++			"\x43\x2d\x9a\xcb\x92\x3f\x5a\x1d"
++			"\x85\xd8\xc9\xdf\x68\xc9\x12\x80"
++			"\x56\x0c\xdc\x00\xdc\x3a\x7d\x9d"
++			"\xa3\xa2\xe8\x4d\xbf\xf9\x70\xa0"
++			"\xa4\x13\x4f\x6b\xaf\x0a\x89\x7f"
++			"\xda\xf0\xbf\x9b\xc8\x1d\xe5\xf8"
++			"\x2e\x8b\x07\xb5\x73\x1b\xcc\xa2"
++			"\xa6\xad\x30\xbc\x78\x3c\x5b\x10"
++			"\xfa\x5e\x62\x2d\x9e\x64\xb3\x33"
++			"\xce\xf9\x1f\x86\xe7\x8b\xa2\xb8"
++			"\xe8\x99\x57\x8c\x11\xed\x66\xd9"
++			"\x3c\x72\xb9\xc3\xe6\x4e\x17\x3a"
++			"\x6a\xcb\x42\x24\x06\xed\x3e\x4e"
++			"\xa3\xe8\x6a\x94\xda\x0d\x4e\xd5"
++			"\x14\x19\xcf\xb6\x26\xd8\x2e\xcc"
++			"\x64\x76\x38\x49\x4d\xfe\x30\x6d"
++			"\xe4\xc8\x8c\x7b\xc4\xe0\x35\xba"
++			"\x22\x6e\x76\xe1\x1a\xf2\x53\xc3"
++			"\x28\xa2\x82\x1f\x61\x69\xad\xc1"
++			"\x7b\x28\x4b\x1e\x6c\x85\x95\x9b"
++			"\x51\xb5\x17\x7f\x12\x69\x8c\x24"
++			"\xd5\xc7\x5a\x5a\x11\x54\xff\x5a"
++			"\xf7\x16\xc3\x91\xa6\xf0\xdc\x0a"
++			"\xb6\xa7\x4a\x0d\x7a\x58\xfe\xa5"
++			"\xf5\xcb\x8f\x7b\x0e\xea\x57\xe7"
++			"\xbd\x79\xd6\x1c\x88\x23\x6c\xf2"
++			"\x4d\x29\x77\x53\x35\x6a\x00\x8d"
++			"\xcd\xa3\x58\xbe\x77\x99\x18\xf8"
++			"\xe6\xe1\x8f\xe9\x37\x8f\xe3\xe2"
++			"\x5a\x8a\x93\x25\xaf\xf3\x78\x80"
++			"\xbe\xa6\x1b\xc6\xac\x8b\x1c\x91"
++			"\x58\xe1\x9f\x89\x35\x9d\x1d\x21"
++			"\x29\x9f\xf4\x99\x02\x27\x0f\xa8"
++			"\x4f\x79\x94\x2b\x33\x2c\xda\xa2"
++			"\x26\x39\x83\x94\xef\x27\xd8\x53"
++			"\x8f\x66\x0d\xe4\x41\x7d\x34\xcd"
++			"\x43\x7c\x95\x0a\x53\xef\x66\xda"
++			"\x7e\x9b\xf3\x93\xaf\xd0\x73\x71"
++			"\xba\x40\x9b\x74\xf8\xd7\xd7\x41"
++			"\x6d\xaf\x72\x9c\x8d\x21\x87\x3c"
++			"\xfd\x0a\x90\xa9\x47\x96\x9e\xd3"
++			"\x88\xee\x73\xcf\x66\x2f\x52\x56"
++			"\x6d\xa9\x80\x4c\xe2\x6f\x62\x88"
++			"\x3f\x0e\x54\x17\x48\x80\x5d\xd3"
++			"\xc3\xda\x25\x3d\xa1\xc8\xcb\x9f"
++			"\x9b\x70\xb3\xa1\xeb\x04\x52\xa1"
++			"\xf2\x22\x0f\xfc\xc8\x18\xfa\xf9"
++			"\x85\x9c\xf1\xac\xeb\x0c\x02\x46"
++			"\x75\xd2\xf5\x2c\xe3\xd2\x59\x94"
++			"\x12\xf3\x3c\xfc\xd7\x92\xfa\x36"
++			"\xba\x61\x34\x38\x7c\xda\x48\x3e"
++			"\x08\xc9\x39\x23\x5e\x02\x2c\x1a"
++			"\x18\x7e\xb4\xd9\xfd\x9e\x40\x02"
++			"\xb1\x33\x37\x32\xe7\xde\xd6\xd0"
++			"\x7c\x58\x65\x4b\xf8\x34\x27\x9c"
++			"\x44\xb4\xbd\xe9\xe9\x4c\x78\x7d"
++			"\x4b\x9f\xce\xb1\xcd\x47\xa5\x37"
++			"\xe5\x6d\xbd\xb9\x43\x94\x0a\xd4"
++			"\xd6\xf9\x04\x5f\xb5\x66\x6c\x1a"
++			"\x35\x12\xe3\x36\x28\x27\x36\x58"
++			"\x01\x2b\x79\xe4\xba\x6d\x10\x7d"
++			"\x65\xdf\x84\x95\xf4\xd5\xb6\x8f"
++			"\x2b\x9f\x96\x00\x86\x60\xf0\x21"
++			"\x76\xa8\x6a\x8c\x28\x1c\xb3\x6b"
++			"\x97\xd7\xb6\x53\x2a\xcc\xab\x40"
++			"\x9d\x62\x79\x58\x52\xe6\x65\xb7"
++			"\xab\x55\x67\x9c\x89\x7c\x03\xb0"
++			"\x73\x59\xc5\x81\xf5\x18\x17\x5c"
++			"\x89\xf3\x78\x35\x44\x62\x78\x72"
++			"\xd0\x96\xeb\x31\xe7\x87\x77\x14"
++			"\x99\x51\xf2\x59\x26\x9e\xb5\xa6"
++			"\x45\xfe\x6e\xbd\x07\x4c\x94\x5a"
++			"\xa5\x7d\xfc\xf1\x2b\x77\xe2\xfe"
++			"\x17\xd4\x84\xa0\xac\xb5\xc7\xda"
++			"\xa9\x1a\xb6\xf3\x74\x11\xb4\x9d"
++			"\xfb\x79\x2e\x04\x2d\x50\x28\x83"
++			"\xbf\xc6\x52\xd3\x34\xd6\xe8\x7a"
++			"\xb6\xea\xe7\xa8\x6c\x15\x1e\x2c"
++			"\x57\xbc\x48\x4e\x5f\x5c\xb6\x92"
++			"\xd2\x49\x77\x81\x6d\x90\x70\xae"
++			"\x98\xa1\x03\x0d\x6b\xb9\x77\x14"
++			"\xf1\x4e\x23\xd3\xf8\x68\xbd\xc2"
++			"\xfe\x04\xb7\x5c\xc5\x17\x60\x8f"
++			"\x65\x54\xa4\x7a\x42\xdc\x18\x0d"
++			"\xb5\xcf\x0f\xd3\xc7\x91\x66\x1b"
++			"\x45\x42\x27\x75\x50\xe5\xee\xb8"
++			"\x7f\x33\x2c\xba\x4a\x92\x4d\x2c"
++			"\x3c\xe3\x0d\x80\x01\xba\x0d\x29"
++			"\xd8\x3c\xe9\x13\x16\x57\xe6\xea"
++			"\x94\x52\xe7\x00\x4d\x30\xb0\x0f"
++			"\x35\xb8\xb8\xa7\xb1\xb5\x3b\x44"
++			"\xe1\x2f\xfd\x88\xed\x43\xe7\x52"
++			"\x10\x93\xb3\x8a\x30\x6b\x0a\xf7"
++			"\x23\xc6\x50\x9d\x4a\xb0\xde\xc3"
++			"\xdc\x9b\x2f\x01\x56\x36\x09\xc5"
++			"\x2f\x6b\xfe\xf1\xd8\x27\x45\x03"
++			"\x30\x5e\x5c\x5b\xb4\x62\x0e\x1a"
++			"\xa9\x21\x2b\x92\x94\x87\x62\x57"
++			"\x4c\x10\x74\x1a\xf1\x0a\xc5\x84"
++			"\x3b\x9e\x72\x02\xd7\xcc\x09\x56"
++			"\xbd\x54\xc1\xf0\xc3\xe3\xb3\xf8"
++			"\xd2\x0d\x61\xcb\xef\xce\x0d\x05"
++			"\xb0\x98\xd9\x8e\x4f\xf9\xbc\x93"
++			"\xa6\xea\xc8\xcf\x10\x53\x4b\xf1"
++			"\xec\xfc\x89\xf9\x64\xb0\x22\xbf"
++			"\x9e\x55\x46\x9f\x7c\x50\x8e\x84"
++			"\x54\x20\x98\xd7\x6c\x40\x1e\xdb"
++			"\x69\x34\x78\x61\x24\x21\x9c\x8a"
++			"\xb3\x62\x31\x8b\x6e\xf5\x2a\x35"
++			"\x86\x13\xb1\x6c\x64\x2e\x41\xa5"
++			"\x05\xf2\x42\xba\xd2\x3a\x0d\x8e"
++			"\x8a\x59\x94\x3c\xcf\x36\x27\x82"
++			"\xc2\x45\xee\x58\xcd\x88\xb4\xec"
++			"\xde\xb2\x96\x0a\xaf\x38\x6f\x88"
++			"\xd7\xd8\xe1\xdf\xb9\x96\xa9\x0a"
++			"\xb1\x95\x28\x86\x20\xe9\x17\x49"
++			"\xa2\x29\x38\xaa\xa5\xe9\x6e\xf1"
++			"\x19\x27\xc0\xd5\x2a\x22\xc3\x0b"
++			"\xdb\x7c\x73\x10\xb9\xba\x89\x76"
++			"\x54\xae\x7d\x71\xb3\x93\xf6\x32"
++			"\xe6\x47\x43\x55\xac\xa0\x0d\xc2"
++			"\x93\x27\x4a\x8e\x0e\x74\x15\xc7"
++			"\x0b\x85\xd9\x0c\xa9\x30\x7a\x3e"
++			"\xea\x8f\x85\x6d\x3a\x12\x4f\x72"
++			"\x69\x58\x7a\x80\xbb\xb5\x97\xf3"
++			"\xcf\x70\xd2\x5d\xdd\x4d\x21\x79"
++			"\x54\x4d\xe4\x05\xe8\xbd\xc2\x62"
++			"\xb1\x3b\x77\x1c\xd6\x5c\xf3\xa0"
++			"\x79\x00\xa8\x6c\x29\xd9\x18\x24"
++			"\x36\xa2\x46\xc0\x96\x65\x7f\xbd"
++			"\x2a\xed\x36\x16\x0c\xaa\x9f\xf4"
++			"\xc5\xb4\xe2\x12\xed\x69\xed\x4f"
++			"\x26\x2c\x39\x52\x89\x98\xe7\x2c"
++			"\x99\xa4\x9e\xa3\x9b\x99\x46\x7a"
++			"\x3a\xdc\xa8\x59\xa3\xdb\xc3\x3b"
++			"\x95\x0d\x3b\x09\x6e\xee\x83\x5d"
++			"\x32\x4d\xed\xab\xfa\x98\x14\x4e"
++			"\xc3\x15\x45\x53\x61\xc4\x93\xbd"
++			"\x90\xf4\x99\x95\x4c\xe6\x76\x92"
++			"\x29\x90\x46\x30\x92\x69\x7d\x13"
++			"\xf2\xa5\xcd\x69\x49\x44\xb2\x0f"
++			"\x63\x40\x36\x5f\x09\xe2\x78\xf8"
++			"\x91\xe3\xe2\xfa\x10\xf7\xc8\x24"
++			"\xa8\x89\x32\x5c\x37\x25\x1d\xb2"
++			"\xea\x17\x8a\x0a\xa9\x64\xc3\x7c"
++			"\x3c\x7c\xbd\xc6\x79\x34\xe7\xe2"
++			"\x85\x8e\xbf\xf8\xde\x92\xa0\xae"
++			"\x20\xc4\xf6\xbb\x1f\x38\x19\x0e"
++			"\xe8\x79\x9c\xa1\x23\xe9\x54\x7e"
++			"\x37\x2f\xe2\x94\x32\xaf\xa0\x23"
++			"\x49\xe4\xc0\xb3\xac\x00\x8f\x36"
++			"\x05\xc4\xa6\x96\xec\x05\x98\x4f"
++			"\x96\x67\x57\x1f\x20\x86\x1b\x2d"
++			"\x69\xe4\x29\x93\x66\x5f\xaf\x6b"
++			"\x88\x26\x2c\x67\x02\x4b\x52\xd0"
++			"\x83\x7a\x43\x1f\xc0\x71\x15\x25"
++			"\x77\x65\x08\x60\x11\x76\x4c\x8d"
++			"\xed\xa9\x27\xc6\xb1\x2a\x2c\x6a"
++			"\x4a\x97\xf5\xc6\xb7\x70\x42\xd3"
++			"\x03\xd1\x24\x95\xec\x6d\xab\x38"
++			"\x72\xce\xe2\x8b\x33\xd7\x51\x09"
++			"\xdc\x45\xe0\x09\x96\x32\xf3\xc4"
++			"\x84\xdc\x73\x73\x2d\x1b\x11\x98"
++			"\xc5\x0e\x69\x28\x94\xc7\xb5\x4d"
++			"\xc8\x8a\xd0\xaa\x13\x2e\x18\x74"
++			"\xdd\xd1\x1e\xf3\x90\xe8\xfc\x9a"
++			"\x72\x4a\x0e\xd1\xe4\xfb\x0d\x96"
++			"\xd1\x0c\x79\x85\x1b\x1c\xfe\xe1"
++			"\x62\x8f\x7a\x73\x32\xab\xc8\x18"
++			"\x69\xe3\x34\x30\xdf\x13\xa6\xe5"
++			"\xe8\x0e\x67\x7f\x81\x11\xb4\x60"
++			"\xc7\xbd\x79\x65\x50\xdc\xc4\x5b"
++			"\xde\x39\xa4\x01\x72\x63\xf3\xd1"
++			"\x64\x4e\xdf\xfc\x27\x92\x37\x0d"
++			"\x57\xcd\x11\x4f\x11\x04\x8e\x1d"
++			"\x16\xf7\xcd\x92\x9a\x99\x30\x14"
++			"\xf1\x7c\x67\x1b\x1f\x41\x0b\xe8"
++			"\x32\xe8\xb8\xc1\x4f\x54\x86\x4f"
++			"\xe5\x79\x81\x73\xcd\x43\x59\x68"
++			"\x73\x02\x3b\x78\x21\x72\x43\x00"
++			"\x49\x17\xf7\x00\xaf\x68\x24\x53"
++			"\x05\x0a\xc3\x33\xe0\x33\x3f\x69"
++			"\xd2\x84\x2f\x0b\xed\xde\x04\xf4"
++			"\x11\x94\x13\x69\x51\x09\x28\xde"
++			"\x57\x5c\xef\xdc\x9a\x49\x1c\x17"
++			"\x97\xf3\x96\xc1\x7f\x5d\x2e\x7d"
++			"\x55\xb8\xb3\x02\x09\xb3\x1f\xe7"
++			"\xc9\x8d\xa3\x36\x34\x8a\x77\x13"
++			"\x30\x63\x4c\xa5\xcd\xc3\xe0\x7e"
++			"\x05\xa1\x7b\x0c\xcb\x74\x47\x31"
++			"\x62\x03\x43\xf1\x87\xb4\xb0\x85"
++			"\x87\x8e\x4b\x25\xc7\xcf\xae\x4b"
++			"\x36\x46\x3e\x62\xbc\x6f\xeb\x5f"
++			"\x73\xac\xe6\x07\xee\xc1\xa1\xd6"
++			"\xc4\xab\xc9\xd6\x89\x45\xe1\xf1"
++			"\x04\x4e\x1a\x6f\xbb\x4f\x3a\xa3"
++			"\xa0\xcb\xa3\x0a\xd8\x71\x35\x55"
++			"\xe4\xbc\x2e\x04\x06\xe6\xff\x5b"
++			"\x1c\xc0\x11\x7c\xc5\x17\xf3\x38"
++			"\xcf\xe9\xba\x0f\x0e\xef\x02\xc2"
++			"\x8d\xc6\xbc\x4b\x67\x20\x95\xd7"
++			"\x2c\x45\x5b\x86\x44\x8c\x6f\x2e"
++			"\x7e\x9f\x1c\x77\xba\x6b\x0e\xa3"
++			"\x69\xdc\xab\x24\x57\x60\x47\xc1"
++			"\xd1\xa5\x9d\x23\xe6\xb1\x37\xfe"
++			"\x93\xd2\x4c\x46\xf9\x0c\xc6\xfb"
++			"\xd6\x9d\x99\x69\xab\x7a\x07\x0c"
++			"\x65\xe7\xc4\x08\x96\xe2\xa5\x01"
++			"\x3f\x46\x07\x05\x7e\xe8\x9a\x90"
++			"\x50\xdc\xe9\x7a\xea\xa1\x39\x6e"
++			"\x66\xe4\x6f\xa5\x5f\xb2\xd9\x5b"
++			"\xf5\xdb\x2a\x32\xf0\x11\x6f\x7c"
++			"\x26\x10\x8f\x3d\x80\xe9\x58\xf7"
++			"\xe0\xa8\x57\xf8\xdb\x0e\xce\x99"
++			"\x63\x19\x3d\xd5\xec\x1b\x77\x69"
++			"\x98\xf6\xe4\x5f\x67\x17\x4b\x09"
++			"\x85\x62\x82\x70\x18\xe2\x9a\x78"
++			"\xe2\x62\xbd\xb4\xf1\x42\xc6\xfb"
++			"\x08\xd0\xbd\xeb\x4e\x09\xf2\xc8"
++			"\x1e\xdc\x3d\x32\x21\x56\x9c\x4f"
++			"\x35\xf3\x61\x06\x72\x84\xc4\x32"
++			"\xf2\xf1\xfa\x0b\x2f\xc3\xdb\x02"
++			"\x04\xc2\xde\x57\x64\x60\x8d\xcf"
++			"\xcb\x86\x5d\x97\x3e\xb1\x9c\x01"
++			"\xd6\x28\x8f\x99\xbc\x46\xeb\x05"
++			"\xaf\x7e\xb8\x21\x2a\x56\x85\x1c"
++			"\xb3\x71\xa0\xde\xca\x96\xf1\x78"
++			"\x49\xa2\x99\x81\x80\x5c\x01\xf5"
++			"\xa0\xa2\x56\x63\xe2\x70\x07\xa5"
++			"\x95\xd6\x85\xeb\x36\x9e\xa9\x51"
++			"\x66\x56\x5f\x1d\x02\x19\xe2\xf6"
++			"\x4f\x73\x38\x09\x75\x64\x48\xe0"
++			"\xf1\x7e\x0e\xe8\x9d\xf9\xed\x94"
++			"\xfe\x16\x26\x62\x49\x74\xf4\xb0"
++			"\xd4\xa9\x6c\xb0\xfd\x53\xe9\x81"
++			"\xe0\x7a\xbf\xcf\xb5\xc4\x01\x81"
++			"\x79\x99\x77\x01\x3b\xe9\xa2\xb6"
++			"\xe6\x6a\x8a\x9e\x56\x1c\x8d\x1e"
++			"\x8f\x06\x55\x2c\x6c\xdc\x92\x87"
++			"\x64\x3b\x4b\x19\xa1\x13\x64\x1d"
++			"\x4a\xe9\xc0\x00\xb8\x95\xef\x6b"
++			"\x1a\x86\x6d\x37\x52\x02\xc2\xe0"
++			"\xc8\xbb\x42\x0c\x02\x21\x4a\xc9"
++			"\xef\xa0\x54\xe4\x5e\x16\x53\x81"
++			"\x70\x62\x10\xaf\xde\xb8\xb5\xd3"
++			"\xe8\x5e\x6c\xc3\x8a\x3e\x18\x07"
++			"\xf2\x2f\x7d\xa7\xe1\x3d\x4e\xb4"
++			"\x26\xa7\xa3\x93\x86\xb2\x04\x1e"
++			"\x53\x5d\x86\xd6\xde\x65\xca\xe3"
++			"\x4e\xc1\xcf\xef\xc8\x70\x1b\x83"
++			"\x13\xdd\x18\x8b\x0d\x76\xd2\xf6"
++			"\x37\x7a\x93\x7a\x50\x11\x9f\x96"
++			"\x86\x25\xfd\xac\xdc\xbe\x18\x93"
++			"\x19\x6b\xec\x58\x4f\xb9\x75\xa7"
++			"\xdd\x3f\x2f\xec\xc8\x5a\x84\xab"
++			"\xd5\xe4\x8a\x07\xf6\x4d\x23\xd6"
++			"\x03\xfb\x03\x6a\xea\x66\xbf\xd4"
++			"\xb1\x34\xfb\x78\xe9\x55\xdc\x7c"
++			"\x3d\x9c\xe5\x9a\xac\xc3\x7a\x80"
++			"\x24\x6d\xa0\xef\x25\x7c\xb7\xea"
++			"\xce\x4d\x5f\x18\x60\xce\x87\x22"
++			"\x66\x2f\xd5\xdd\xdd\x02\x21\x75"
++			"\x82\xa0\x1f\x58\xc6\xd3\x62\xf7"
++			"\x32\xd8\xaf\x1e\x07\x77\x51\x96"
++			"\xd5\x6b\x1e\x7e\x80\x02\xe8\x67"
++			"\xea\x17\x0b\x10\xd2\x3f\x28\x25"
++			"\x4f\x05\x77\x02\x14\x69\xf0\x2c"
++			"\xbe\x0c\xf1\x74\x30\xd1\xb9\x9b"
++			"\xfc\x8c\xbb\x04\x16\xd9\xba\xc3"
++			"\xbc\x91\x8a\xc4\x30\xa4\xb0\x12"
++			"\x4c\x21\x87\xcb\xc9\x1d\x16\x96"
++			"\x07\x6f\x23\x54\xb9\x6f\x79\xe5"
++			"\x64\xc0\x64\xda\xb1\xae\xdd\x60"
++			"\x6c\x1a\x9d\xd3\x04\x8e\x45\xb0"
++			"\x92\x61\xd0\x48\x81\xed\x5e\x1d"
++			"\xa0\xc9\xa4\x33\xc7\x13\x51\x5d"
++			"\x7f\x83\x73\xb6\x70\x18\x65\x3e"
++			"\x2f\x0e\x7a\x12\x39\x98\xab\xd8"
++			"\x7e\x6f\xa3\xd1\xba\x56\xad\xbd"
++			"\xf0\x03\x01\x1c\x85\x35\x9f\xeb"
++			"\x19\x63\xa1\xaf\xfe\x2d\x35\x50"
++			"\x39\xa0\x65\x7c\x95\x7e\x6b\xfe"
++			"\xc1\xac\x07\x7c\x98\x4f\xbe\x57"
++			"\xa7\x22\xec\xe2\x7e\x29\x09\x53"
++			"\xe8\xbf\xb4\x7e\x3f\x8f\xfc\x14"
++			"\xce\x54\xf9\x18\x58\xb5\xff\x44"
++			"\x05\x9d\xce\x1b\xb6\x82\x23\xc8"
++			"\x2e\xbc\x69\xbb\x4a\x29\x0f\x65"
++			"\x94\xf0\x63\x06\x0e\xef\x8c\xbd"
++			"\xff\xfd\xb0\x21\x6e\x57\x05\x75"
++			"\xda\xd5\xc4\xeb\x8d\x32\xf7\x50"
++			"\xd3\x6f\x22\xed\x5f\x8e\xa2\x5b"
++			"\x80\x8c\xc8\x78\x40\x24\x4b\x89"
++			"\x30\xce\x7a\x97\x0e\xc4\xaf\xef"
++			"\x9b\xb4\xcd\x66\x74\x14\x04\x2b"
++			"\xf7\xce\x0b\x1c\x6e\xc2\x78\x8c"
++			"\xca\xc5\xd0\x1c\x95\x4a\x91\x2d"
++			"\xa7\x20\xeb\x86\x52\xb7\x67\xd8"
++			"\x0c\xd6\x04\x14\xde\x51\x74\x75"
++			"\xe7\x11\xb4\x87\xa3\x3d\x2d\xad"
++			"\x4f\xef\xa0\x0f\x70\x00\x6d\x13"
++			"\x19\x1d\x41\x50\xe9\xd8\xf0\x32"
++			"\x71\xbc\xd3\x11\xf2\xac\xbe\xaf"
++			"\x75\x46\x65\x4e\x07\x34\x37\xa3"
++			"\x89\xfe\x75\xd4\x70\x4c\xc6\x3f"
++			"\x69\x24\x0e\x38\x67\x43\x8c\xde"
++			"\x06\xb5\xb8\xe7\xc4\xf0\x41\x8f"
++			"\xf0\xbd\x2f\x0b\xb9\x18\xf8\xde"
++			"\x64\xb1\xdb\xee\x00\x50\x77\xe1"
++			"\xc7\xff\xa6\xfa\xdd\x70\xf4\xe3"
++			"\x93\xe9\x77\x35\x3d\x4b\x2f\x2b"
++			"\x6d\x55\xf0\xfc\x88\x54\x4e\x89"
++			"\xc1\x8a\x23\x31\x2d\x14\x2a\xb8"
++			"\x1b\x15\xdd\x9e\x6e\x7b\xda\x05"
++			"\x91\x7d\x62\x64\x96\x72\xde\xfc"
++			"\xc1\xec\xf0\x23\x51\x6f\xdb\x5b"
++			"\x1d\x08\x57\xce\x09\xb8\xf6\xcd"
++			"\x8d\x95\xf2\x20\xbf\x0f\x20\x57"
++			"\x98\x81\x84\x4f\x15\x5c\x76\xe7"
++			"\x3e\x0a\x3a\x6c\xc4\x8a\xbe\x78"
++			"\x74\x77\xc3\x09\x4b\x5d\x48\xe4"
++			"\xc8\xcb\x0b\xea\x17\x28\xcf\xcf"
++			"\x31\x32\x44\xa4\xe5\x0e\x1a\x98"
++			"\x94\xc4\xf0\xff\xae\x3e\x44\xe8"
++			"\xa5\xb3\xb5\x37\x2f\xe8\xaf\x6f"
++			"\x28\xc1\x37\x5f\x31\xd2\xb9\x33"
++			"\xb1\xb2\x52\x94\x75\x2c\x29\x59"
++			"\x06\xc2\x25\xe8\x71\x65\x4e\xed"
++			"\xc0\x9c\xb1\xbb\x25\xdc\x6c\xe7"
++			"\x4b\xa5\x7a\x54\x7a\x60\xff\x7a"
++			"\xe0\x50\x40\x96\x35\x63\xe4\x0b"
++			"\x76\xbd\xa4\x65\x00\x1b\x57\x88"
++			"\xae\xed\x39\x88\x42\x11\x3c\xed"
++			"\x85\x67\x7d\xb9\x68\x82\xe9\x43"
++			"\x3c\x47\x53\xfa\xe8\xf8\x9f\x1f"
++			"\x9f\xef\x0f\xf7\x30\xd9\x30\x0e"
++			"\xb9\x9f\x69\x18\x2f\x7e\xf8\xf8"
++			"\xf8\x8c\x0f\xd4\x02\x4d\xea\xcd"
++			"\x0a\x9c\x6f\x71\x6d\x5a\x4c\x60"
++			"\xce\x20\x56\x32\xc6\xc5\x99\x1f"
++			"\x09\xe6\x4e\x18\x1a\x15\x13\xa8"
++			"\x7d\xb1\x6b\xc0\xb2\x6d\xf8\x26"
++			"\x66\xf8\x3d\x18\x74\x70\x66\x7a"
++			"\x34\x17\xde\xba\x47\xf1\x06\x18"
++			"\xcb\xaf\xeb\x4a\x1e\x8f\xa7\x77"
++			"\xe0\x3b\x78\x62\x66\xc9\x10\xea"
++			"\x1f\xb7\x29\x0a\x45\xa1\x1d\x1e"
++			"\x1d\xe2\x65\x61\x50\x9c\xd7\x05"
++			"\xf2\x0b\x5b\x12\x61\x02\xc8\xe5"
++			"\x63\x4f\x20\x0c\x07\x17\x33\x5e"
++			"\x03\x9a\x53\x0f\x2e\x55\xfe\x50"
++			"\x43\x7d\xd0\xb6\x7e\x5a\xda\xae"
++			"\x58\xef\x15\xa9\x83\xd9\x46\xb1"
++			"\x42\xaa\xf5\x02\x6c\xce\x92\x06"
++			"\x1b\xdb\x66\x45\x91\x79\xc2\x2d"
++			"\xe6\x53\xd3\x14\xfd\xbb\x44\x63"
++			"\xc6\xd7\x3d\x7a\x0c\x75\x78\x9d"
++			"\x5c\xa6\x39\xb3\xe5\x63\xca\x8b"
++			"\xfe\xd3\xef\x60\x83\xf6\x8e\x70"
++			"\xb6\x67\xc7\x77\xed\x23\xef\x4c"
++			"\xf0\xed\x2d\x07\x59\x6f\xc1\x01"
++			"\x34\x37\x08\xab\xd9\x1f\x09\xb1"
++			"\xce\x5b\x17\xff\x74\xf8\x9c\xd5"
++			"\x2c\x56\x39\x79\x0f\x69\x44\x75"
++			"\x58\x27\x01\xc4\xbf\xa7\xa1\x1d"
++			"\x90\x17\x77\x86\x5a\x3f\xd9\xd1"
++			"\x0e\xa0\x10\xf8\xec\x1e\xa5\x7f"
++			"\x5e\x36\xd1\xe3\x04\x2c\x70\xf7"
++			"\x8e\xc0\x98\x2f\x6c\x94\x2b\x41"
++			"\xb7\x60\x00\xb7\x2e\xb8\x02\x8d"
++			"\xb8\xb0\xd3\x86\xba\x1d\xd7\x90"
++			"\xd6\xb6\xe1\xfc\xd7\xd8\x28\x06"
++			"\x63\x9b\xce\x61\x24\x79\xc0\x70"
++			"\x52\xd0\xb6\xd4\x28\x95\x24\x87"
++			"\x03\x1f\xb7\x9a\xda\xa3\xfb\x52"
++			"\x5b\x68\xe7\x4c\x8c\x24\xe1\x42"
++			"\xf7\xd5\xfd\xad\x06\x32\x9f\xba"
++			"\xc1\xfc\xdd\xc6\xfc\xfc\xb3\x38"
++			"\x74\x56\x58\x40\x02\x37\x52\x2c"
++			"\x55\xcc\xb3\x9e\x7a\xe9\xd4\x38"
++			"\x41\x5e\x0c\x35\xe2\x11\xd1\x13"
++			"\xf8\xb7\x8d\x72\x6b\x22\x2a\xb0"
++			"\xdb\x08\xba\x35\xb9\x3f\xc8\xd3"
++			"\x24\x90\xec\x58\xd2\x09\xc7\x2d"
++			"\xed\x38\x80\x36\x72\x43\x27\x49"
++			"\x4a\x80\x8a\xa2\xe8\xd3\xda\x30"
++			"\x7d\xb6\x82\x37\x86\x92\x86\x3e"
++			"\x08\xb2\x28\x5a\x55\x44\x24\x7d"
++			"\x40\x48\x8a\xb6\x89\x58\x08\xa0"
++			"\xd6\x6d\x3a\x17\xbf\xf6\x54\xa2"
++			"\xf5\xd3\x8c\x0f\x78\x12\x57\x8b"
++			"\xd5\xc2\xfd\x58\x5b\x7f\x38\xe3"
++			"\xcc\xb7\x7c\x48\xb3\x20\xe8\x81"
++			"\x14\x32\x45\x05\xe0\xdb\x9f\x75"
++			"\x85\xb4\x6a\xfc\x95\xe3\x54\x22"
++			"\x12\xee\x30\xfe\xd8\x30\xef\x34"
++			"\x50\xab\x46\x30\x98\x2f\xb7\xc0"
++			"\x15\xa2\x83\xb6\xf2\x06\x21\xa2"
++			"\xc3\x26\x37\x14\xd1\x4d\xb5\x10"
++			"\x52\x76\x4d\x6a\xee\xb5\x2b\x15"
++			"\xb7\xf9\x51\xe8\x2a\xaf\xc7\xfa"
++			"\x77\xaf\xb0\x05\x4d\xd1\x68\x8e"
++			"\x74\x05\x9f\x9d\x93\xa5\x3e\x7f"
++			"\x4e\x5f\x9d\xcb\x09\xc7\x83\xe3"
++			"\x02\x9d\x27\x1f\xef\x85\x05\x8d"
++			"\xec\x55\x88\x0f\x0d\x7c\x4c\xe8"
++			"\xa1\x75\xa0\xd8\x06\x47\x14\xef"
++			"\xaa\x61\xcf\x26\x15\xad\xd8\xa3"
++			"\xaa\x75\xf2\x78\x4a\x5a\x61\xdf"
++			"\x8b\xc7\x04\xbc\xb2\x32\xd2\x7e"
++			"\x42\xee\xb4\x2f\x51\xff\x7b\x2e"
++			"\xd3\x02\xe8\xdc\x5d\x0d\x50\xdc"
++			"\xae\xb7\x46\xf9\xa8\xe6\xd0\x16"
++			"\xcc\xe6\x2c\x81\xc7\xad\xe9\xf0"
++			"\x05\x72\x6d\x3d\x0a\x7a\xa9\x02"
++			"\xac\x82\x93\x6e\xb6\x1c\x28\xfc"
++			"\x44\x12\xfb\x73\x77\xd4\x13\x39"
++			"\x29\x88\x8a\xf3\x5c\xa6\x36\xa0"
++			"\x2a\xed\x7e\xb1\x1d\xd6\x4c\x6b"
++			"\x41\x01\x18\x5d\x5d\x07\x97\xa6"
++			"\x4b\xef\x31\x18\xea\xac\xb1\x84"
++			"\x21\xed\xda\x86",
+ 		.rlen = 4100,
+ 	},
+ };
+ 
+ static struct cipher_testvec aes_ctr_dec_tv_template[] = {
+ 	{ /* From RFC 3686 */
+-		.key	= { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
+-			    0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
+-			    0x00, 0x00, 0x00, 0x30 },
++		.key	= "\xae\x68\x52\xf8\x12\x10\x67\xcc"
++			  "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e"
++			  "\x00\x00\x00\x30",
+ 		.klen	= 20,
+-		.iv 	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input	= { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
+-			    0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
++		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input	= "\xe4\x09\x5d\x4f\xb7\xa7\xb3\x79"
++			  "\x2d\x61\x75\xa3\x26\x13\x11\xb8",
+ 		.ilen	= 16,
+-		.result	= { "Single block msg" },
++		.result	= "Single block msg",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
+-			    0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
+-			    0x00, 0x6c, 0xb6, 0xdb },
++		.key	= "\x7e\x24\x06\x78\x17\xfa\xe0\xd7"
++			  "\x43\xd6\xce\x1f\x32\x53\x91\x63"
++			  "\x00\x6c\xb6\xdb",
+ 		.klen	= 20,
+-		.iv 	= { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
+-		.input	= { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
+-			    0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
+-			    0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
+-			    0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
+-		.ilen 	= 32,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.iv	= "\xc0\x54\x3b\x59\xda\x48\xd9\x0b",
++		.input	= "\x51\x04\xa1\x06\x16\x8a\x72\xd9"
++			  "\x79\x0d\x41\xee\x8e\xda\xd3\x88"
++			  "\xeb\x2e\x1e\xfc\x46\xda\x57\xc8"
++			  "\xfc\xe6\x30\xdf\x91\x41\xbe\x28",
++		.ilen	= 32,
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.rlen	= 32,
+ 	}, {
+-		.key 	= { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
+-			    0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
+-			    0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
+-			    0x00, 0x00, 0x00, 0x48 },
+-		.klen 	= 28,
+-		.iv	= { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
+-		.input	= { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
+-			    0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
+-		.ilen 	= 16,
+-		.result	= { "Single block msg" },
++		.key	= "\x16\xaf\x5b\x14\x5f\xc9\xf5\x79"
++			  "\xc1\x75\xf9\x3e\x3b\xfb\x0e\xed"
++			  "\x86\x3d\x06\xcc\xfd\xb7\x85\x15"
++			  "\x00\x00\x00\x48",
++		.klen	= 28,
++		.iv	= "\x36\x73\x3c\x14\x7d\x6d\x93\xcb",
++		.input	= "\x4b\x55\x38\x4f\xe2\x59\xc9\xc8"
++			  "\x4e\x79\x35\xa0\x03\xcb\xe9\x28",
++		.ilen	= 16,
++		.result	= "Single block msg",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
+-			    0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
+-			    0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
+-			    0x00, 0x96, 0xb0, 0x3b },
++		.key	= "\x7c\x5c\xb2\x40\x1b\x3d\xc3\x3c"
++			  "\x19\xe7\x34\x08\x19\xe0\xf6\x9c"
++			  "\x67\x8c\x3d\xb8\xe6\xf6\xa9\x1a"
++			  "\x00\x96\xb0\x3b",
+ 		.klen	= 28,
+-		.iv 	= { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
+-		.input	= { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
+-			    0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
+-			    0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
+-			    0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
++		.iv	= "\x02\x0c\x6e\xad\xc2\xcb\x50\x0d",
++		.input	= "\x45\x32\x43\xfc\x60\x9b\x23\x32"
++			  "\x7e\xdf\xaa\xfa\x71\x31\xcd\x9f"
++			  "\x84\x90\x70\x1c\x5a\xd4\xa7\x9c"
++			  "\xfc\x1f\xe0\xff\x42\xf4\xfb\x00",
+ 		.ilen	= 32,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+-		.rlen 	= 32,
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
++		.rlen	= 32,
+ 	}, { 
+-		.key 	= { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
+-			    0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
+-			    0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
+-			    0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
+-			    0x00, 0x00, 0x00, 0x60 },
++		.key	= "\x77\x6b\xef\xf2\x85\x1d\xb0\x6f"
++			  "\x4c\x8a\x05\x42\xc8\x69\x6f\x6c"
++			  "\x6a\x81\xaf\x1e\xec\x96\xb4\xd3"
++			  "\x7f\xc1\xd6\x89\xe6\xc1\xc1\x04"
++			  "\x00\x00\x00\x60",
+ 		.klen	= 36,
+-		.iv 	= { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
+-		.input	= { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
+-			    0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
++		.iv	= "\xdb\x56\x72\xc9\x7a\xa8\xf0\xb2",
++		.input	= "\x14\x5a\xd0\x1d\xbf\x82\x4e\xc7"
++			  "\x56\x08\x63\xdc\x71\xe3\xe0\xc0",
+ 		.ilen	= 16,
+-		.result	= { "Single block msg" },
+-		.rlen 	= 16,
+-	}, {
+-		.key	= { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
+-			    0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
+-			    0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
+-			    0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
+-			    0x00, 0xfa, 0xac, 0x24 },
+-		.klen 	= 36,
+-		.iv	= { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
+-		.input	= { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
+-			    0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
+-			    0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
+-			    0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
++		.result	= "Single block msg",
++		.rlen	= 16,
++	}, {
++		.key	= "\xf6\xd6\x6d\x6b\xd5\x2d\x59\xbb"
++			  "\x07\x96\x36\x58\x79\xef\xf8\x86"
++			  "\xc6\x6d\xd5\x1a\x5b\x6a\x99\x74"
++			  "\x4b\x50\x59\x0c\x87\xa2\x38\x84"
++			  "\x00\xfa\xac\x24",
++		.klen	= 36,
++		.iv	= "\xc1\x58\x5e\xf1\x5a\x43\xd8\x75",
++		.input	= "\xf0\x5e\x23\x1b\x38\x94\x61\x2c"
++			  "\x49\xee\x00\x0b\x80\x4e\xb2\xa9"
++			  "\xb8\x30\x6b\x50\x8f\x83\x9d\x6a"
++			  "\x55\x30\x83\x1d\x93\x44\xaf\x1c",
+ 		.ilen	= 32,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.rlen	= 32,
+ 	},
+ };
+ 
+ static struct aead_testvec aes_gcm_enc_tv_template[] = {
+ 	{ /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
++		.key    = zeroed_string,
+ 		.klen	= 16,
+-		.result	= { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+-			    0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
++		.result	= "\x58\xe2\xfc\xce\xfa\x7e\x30\x61"
++			  "\x36\x7f\x1d\x57\xa4\xe7\x45\x5a",
+ 		.rlen	= 16,
+ 	}, {
++		.key    = zeroed_string,
+ 		.klen	= 16,
++		.input  = zeroed_string,
+ 		.ilen	= 16,
+-		.result = { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+-			    0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78,
+-			    0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+-			    0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
++		.result = "\x03\x88\xda\xce\x60\xb6\xa3\x92"
++			  "\xf3\x28\xc2\xb9\x71\xb2\xfe\x78"
++			  "\xab\x6e\x47\xd4\x2c\xec\x13\xbd"
++			  "\xf5\x3a\x67\xb2\x12\x57\xbd\xdf",
+ 		.rlen	= 32,
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ 		.klen	= 16,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ 		.ilen	= 64,
+-		.result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+-			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+-			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+-			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+-			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+-			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+-			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+-			    0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
+-			    0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+-			    0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
++		.result = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
++			  "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
++			  "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
++			  "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
++			  "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
++			  "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
++			  "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
++			  "\x3d\x58\xe0\x91\x47\x3f\x59\x85"
++			  "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6"
++			  "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4",
+ 		.rlen	= 80,
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ 		.klen	= 16,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39 },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39",
+ 		.ilen	= 60,
+-		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xab, 0xad, 0xda, 0xd2 },
++		.assoc	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xab\xad\xda\xd2",
+ 		.alen	= 20,
+-		.result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+-			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+-			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+-			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+-			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+-			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+-			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+-			    0x3d, 0x58, 0xe0, 0x91,
+-			    0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+-			    0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
++		.result = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
++			  "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
++			  "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
++			  "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
++			  "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
++			  "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
++			  "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
++			  "\x3d\x58\xe0\x91"
++			  "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb"
++			  "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47",
+ 		.rlen	= 76,
+ 	}, {
++		.key    = zeroed_string,
+ 		.klen	= 24,
+-		.result	= { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
+-			    0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
++		.result	= "\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b"
++			  "\xa0\x0e\xd1\xf3\x12\x57\x24\x35",
+ 		.rlen	= 16,
+ 	}, {
++		.key    = zeroed_string,
+ 		.klen	= 24,
++		.input  = zeroed_string,
+ 		.ilen	= 16,
+-		.result = { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+-			    0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
+-			    0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+-			    0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
++		.result = "\x98\xe7\x24\x7c\x07\xf0\xfe\x41"
++			  "\x1c\x26\x7e\x43\x84\xb0\xf6\x00"
++			  "\x2f\xf5\x8d\x80\x03\x39\x27\xab"
++			  "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb",
+ 		.rlen	= 32,
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+-			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
+ 		.klen	= 24,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ 		.ilen	= 64,
+-		.result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+-			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+-			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+-			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+-			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+-			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+-			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+-			    0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
+-			    0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+-			    0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
++		.result = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
++			  "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
++			  "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
++			  "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
++			  "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
++			  "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
++			  "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
++			  "\xcc\xda\x27\x10\xac\xad\xe2\x56"
++			  "\x99\x24\xa7\xc8\x58\x73\x36\xbf"
++			  "\xb1\x18\x02\x4d\xb8\x67\x4a\x14",
+ 		.rlen	= 80,
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+-			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
+ 		.klen	= 24,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39 },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39",
+ 		.ilen	= 60,
+-		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xab, 0xad, 0xda, 0xd2 },
++		.assoc	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xab\xad\xda\xd2",
+ 		.alen	= 20,
+-		.result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+-			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+-			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+-			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+-			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+-			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+-			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+-			    0xcc, 0xda, 0x27, 0x10,
+-			    0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+-			    0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
++		.result = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
++			  "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
++			  "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
++			  "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
++			  "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
++			  "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
++			  "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
++			  "\xcc\xda\x27\x10"
++			  "\x25\x19\x49\x8e\x80\xf1\x47\x8f"
++			  "\x37\xba\x55\xbd\x6d\x27\x61\x8c",
+ 		.rlen	= 76,
+ 		.np	= 2,
+ 		.tap	= { 32, 28 },
+ 		.anp	= 2,
+ 		.atap	= { 8, 12 }
+ 	}, {
++		.key    = zeroed_string,
+ 		.klen	= 32,
+-		.result	= { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
+-			    0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
++		.result	= "\x53\x0f\x8a\xfb\xc7\x45\x36\xb9"
++			  "\xa9\x63\xb4\xf1\xc4\xcb\x73\x8b",
+ 		.rlen	= 16,
+ 	}
+ };
+ 
+ static struct aead_testvec aes_gcm_dec_tv_template[] = {
+ 	{ /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
++		.key    = zeroed_string,
+ 		.klen	= 32,
+-		.input	= { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
+-			    0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18,
+-			    0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
+-			    0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
++		.input	= "\xce\xa7\x40\x3d\x4d\x60\x6b\x6e"
++			  "\x07\x4e\xc5\xd3\xba\xf3\x9d\x18"
++			  "\xd0\xd1\xc8\xa7\x99\x99\x6b\xf0"
++			  "\x26\x5b\x98\xb5\xd4\x8a\xb9\x19",
+ 		.ilen	= 32,
++		.result  = zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+-			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ 		.klen	= 32,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+-			    0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+-			    0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+-			    0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+-			    0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+-			    0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+-			    0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+-			    0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad,
+-			    0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
+-			    0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
++			  "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
++			  "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
++			  "\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
++			  "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
++			  "\xa7\xb0\x8b\x10\x56\x82\x88\x38"
++			  "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
++			  "\xbc\xc9\xf6\x62\x89\x80\x15\xad"
++			  "\xb0\x94\xda\xc5\xd9\x34\x71\xbd"
++			  "\xec\x1a\x50\x22\x70\xe3\xcc\x6c",
+ 		.ilen	= 80,
+-		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ 		.rlen	= 64,
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+-			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ 		.klen	= 32,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+-			    0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+-			    0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+-			    0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+-			    0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+-			    0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+-			    0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+-			    0xbc, 0xc9, 0xf6, 0x62,
+-			    0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
+-			    0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
++			  "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
++			  "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
++			  "\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
++			  "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
++			  "\xa7\xb0\x8b\x10\x56\x82\x88\x38"
++			  "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
++			  "\xbc\xc9\xf6\x62"
++			  "\x76\xfc\x6e\xce\x0f\x4e\x17\x68"
++			  "\xcd\xdf\x88\x53\xbb\x2d\x55\x1b",
+ 		.ilen	= 76,
+-		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xab, 0xad, 0xda, 0xd2 },
++		.assoc	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xab\xad\xda\xd2",
+ 		.alen	= 20,
+-		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39 },
++		.result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39",
+ 		.rlen	= 60,
+ 		.np     = 2,
+ 		.tap    = { 48, 28 },
+ 		.anp	= 3,
+ 		.atap	= { 8, 8, 4 }
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ 		.klen	= 16,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+-			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+-			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+-			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+-			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+-			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+-			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+-			    0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
+-			    0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+-			    0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\x42\x83\x1e\xc2\x21\x77\x74\x24"
++			  "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
++			  "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
++			  "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
++			  "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
++			  "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
++			  "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
++			  "\x3d\x58\xe0\x91\x47\x3f\x59\x85"
++			  "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6"
++			  "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4",
+ 		.ilen	= 80,
+-		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ 		.rlen	= 64,
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ 		.klen	= 16,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+-			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+-			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+-			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+-			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+-			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+-			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+-			    0x3d, 0x58, 0xe0, 0x91,
+-			    0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+-			    0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\x42\x83\x1e\xc2\x21\x77\x74\x24"
++			  "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
++			  "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
++			  "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
++			  "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
++			  "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
++			  "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
++			  "\x3d\x58\xe0\x91"
++			  "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb"
++			  "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47",
+ 		.ilen	= 76,
+-		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xab, 0xad, 0xda, 0xd2 },
++		.assoc	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xab\xad\xda\xd2",
+ 		.alen	= 20,
+-		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39 },
++		.result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39",
+ 		.rlen	= 60,
+ 	}, {
++		.key    = zeroed_string,
+ 		.klen	= 24,
+-		.input	= { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+-			    0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
+-			    0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+-			    0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
++		.input	= "\x98\xe7\x24\x7c\x07\xf0\xfe\x41"
++			  "\x1c\x26\x7e\x43\x84\xb0\xf6\x00"
++			  "\x2f\xf5\x8d\x80\x03\x39\x27\xab"
++			  "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb",
+ 		.ilen	= 32,
++		.result  = zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+-			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
+ 		.klen	= 24,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+-			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+-			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+-			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+-			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+-			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+-			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+-			    0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
+-			    0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+-			    0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
++			  "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
++			  "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
++			  "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
++			  "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
++			  "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
++			  "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
++			  "\xcc\xda\x27\x10\xac\xad\xe2\x56"
++			  "\x99\x24\xa7\xc8\x58\x73\x36\xbf"
++			  "\xb1\x18\x02\x4d\xb8\x67\x4a\x14",
+ 		.ilen	= 80,
+-		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ 		.rlen	= 64,
+ 	}, {
+-		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+-			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+-			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++		.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++			  "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
+ 		.klen	= 24,
+-		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+-			    0xde, 0xca, 0xf8, 0x88 },
+-		.input	= { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+-			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+-			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+-			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+-			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+-			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+-			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+-			    0xcc, 0xda, 0x27, 0x10,
+-			    0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+-			    0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
++		.iv	= "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++			  "\xde\xca\xf8\x88",
++		.input	= "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
++			  "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
++			  "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
++			  "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
++			  "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
++			  "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
++			  "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
++			  "\xcc\xda\x27\x10"
++			  "\x25\x19\x49\x8e\x80\xf1\x47\x8f"
++			  "\x37\xba\x55\xbd\x6d\x27\x61\x8c",
+ 		.ilen	= 76,
+-		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+-			    0xab, 0xad, 0xda, 0xd2 },
++		.assoc	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++			  "\xab\xad\xda\xd2",
+ 		.alen	= 20,
+-		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+-			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+-			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+-			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+-			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+-			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+-			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+-			    0xba, 0x63, 0x7b, 0x39 },
++		.result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++			  "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++			  "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++			  "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++			  "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++			  "\xba\x63\x7b\x39",
+ 		.rlen	= 60,
+ 	}
+ };
+ 
+ static struct aead_testvec aes_ccm_enc_tv_template[] = {
+ 	{ /* From RFC 3610 */
+-		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.key	= "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+-		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++		.iv	= "\x01\x00\x00\x00\x03\x02\x01\x00"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++		.assoc	= "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 		.alen	= 8,
+-		.input	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
++		.input	= "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e",
+ 		.ilen	= 23,
+-		.result	= { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
+-			    0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
+-			    0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
+-			    0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
++		.result	= "\x58\x8c\x97\x9a\x61\xc6\x63\xd2"
++			  "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80"
++			  "\x6d\x5f\x6b\x61\xda\xc3\x84\x17"
++			  "\xe8\xd1\x2c\xfd\xf9\x26\xe0",
+ 		.rlen	= 31,
+ 	}, {
+-		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.key	= "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+-		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b },
++		.iv	= "\x01\x00\x00\x00\x07\x06\x05\x04"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++		.assoc	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b",
+ 		.alen	= 12,
+-		.input	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+-			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+-			    0x1c, 0x1d, 0x1e, 0x1f },
++		.input	= "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
++			  "\x14\x15\x16\x17\x18\x19\x1a\x1b"
++			  "\x1c\x1d\x1e\x1f",
+ 		.ilen	= 20,
+-		.result	= { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
+-			    0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
+-			    0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
+-			    0x7d, 0x9c, 0x2d, 0x93 },
++		.result	= "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb"
++			  "\x9d\x4e\x13\x12\x53\x65\x8a\xd8"
++			  "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07"
++			  "\x7d\x9c\x2d\x93",
+ 		.rlen	= 28,
+ 	}, {
+-		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.key	= "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+-		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++		.iv	= "\x01\x00\x00\x00\x0b\x0a\x09\x08"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++		.assoc	= "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 		.alen	= 8,
+-		.input	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			    0x20 },
++		.input	= "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			  "\x20",
+ 		.ilen	= 25,
+-		.result	= { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
+-			    0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
+-			    0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
+-			    0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
+-			    0x7e, 0x5f, 0x4e },
++		.result	= "\x82\x53\x1a\x60\xcc\x24\x94\x5a"
++			  "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d"
++			  "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1"
++			  "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1"
++			  "\x7e\x5f\x4e",
+ 		.rlen	= 35,
+ 	}, {
+-		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.key	= "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+-		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b },
++		.iv	= "\x01\x00\x00\x00\x0c\x0b\x0a\x09"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++		.assoc	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b",
+ 		.alen	= 12,
+-		.input	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+-			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+-			    0x1c, 0x1d, 0x1e },
++		.input	= "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
++			  "\x14\x15\x16\x17\x18\x19\x1a\x1b"
++			  "\x1c\x1d\x1e",
+ 		.ilen	= 19,
+-		.result	= { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
+-			    0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
+-			    0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
+-			    0x4d, 0x99, 0x99, 0x88, 0xdd },
++		.result	= "\x07\x34\x25\x94\x15\x77\x85\x15"
++			  "\x2b\x07\x40\x98\x33\x0a\xbb\x14"
++			  "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b"
++			  "\x4d\x99\x99\x88\xdd",
+ 		.rlen	= 29,
+ 	}, {
+-		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+-			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.key	= "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++			  "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
+-			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+-		.assoc	= { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
++		.iv	= "\x01\x00\x33\x56\x8e\xf7\xb2\x63"
++			  "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++		.assoc	= "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb",
+ 		.alen	= 8,
+-		.input	= { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
+-			    0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
+-			    0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
++		.input	= "\x90\x20\xea\x6f\x91\xbd\xd8\x5a"
++			  "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf"
++			  "\xb7\x9c\x70\x28\x94\x9c\xd0\xec",
+ 		.ilen	= 24,
+-		.result	= { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
+-			    0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
+-			    0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
+-			    0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
++		.result	= "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa"
++			  "\xa0\x72\x6c\x55\xd3\x78\x06\x12"
++			  "\x98\xc8\x5c\x92\x81\x4a\xbc\x33"
++			  "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a",
+ 		.rlen	= 32,
+ 	}, {
+-		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+-			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.key	= "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++			  "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
+-			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+-		.assoc	= { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
+-			    0x20, 0xea, 0x60, 0xc0 },
++		.iv	= "\x01\x00\xd5\x60\x91\x2d\x3f\x70"
++			  "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++		.assoc	= "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81"
++			  "\x20\xea\x60\xc0",
+ 		.alen	= 12,
+-		.input	= { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
+-			    0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
+-			    0x3a, 0x80, 0x3b, 0xa8, 0x7f },
++		.input	= "\x64\x35\xac\xba\xfb\x11\xa8\x2e"
++			  "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9"
++			  "\x3a\x80\x3b\xa8\x7f",
+ 		.ilen	= 21,
+-		.result	= { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
+-			    0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
+-			    0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
+-			    0x5a, 0xe0, 0x70, 0x45, 0x51 },
++		.result	= "\x00\x97\x69\xec\xab\xdf\x48\x62"
++			  "\x55\x94\xc5\x92\x51\xe6\x03\x57"
++			  "\x22\x67\x5e\x04\xc8\x47\x09\x9e"
++			  "\x5a\xe0\x70\x45\x51",
+ 		.rlen	= 29,
+ 	}, {
+-		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+-			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.key	= "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++			  "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
+-			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+-		.assoc	= { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
++		.iv	= "\x01\x00\x42\xff\xf8\xf1\x95\x1c"
++			  "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++		.assoc	= "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8",
+ 		.alen	= 8,
+-		.input	= { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
+-			    0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
+-			    0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
++		.input	= "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01"
++			  "\x8e\x5e\x67\x01\xc9\x17\x87\x65"
++			  "\x98\x09\xd6\x7d\xbe\xdd\x18",
+ 		.ilen	= 23,
+-		.result	= { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
+-			    0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
+-			    0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
+-			    0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
+-			    0xba },
++		.result	= "\xbc\x21\x8d\xaa\x94\x74\x27\xb6"
++			  "\xdb\x38\x6a\x99\xac\x1a\xef\x23"
++			  "\xad\xe0\xb5\x29\x39\xcb\x6a\x63"
++			  "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6"
++			  "\xba",
+ 		.rlen	= 33,
+ 	},
+ };
+ 
+ static struct aead_testvec aes_ccm_dec_tv_template[] = {
+ 	{ /* From RFC 3610 */
+-		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.key	= "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+-		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++		.iv	= "\x01\x00\x00\x00\x03\x02\x01\x00"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++		.assoc	= "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 		.alen	= 8,
+-		.input	= { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
+-			    0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
+-			    0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
+-			    0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
++		.input	= "\x58\x8c\x97\x9a\x61\xc6\x63\xd2"
++			  "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80"
++			  "\x6d\x5f\x6b\x61\xda\xc3\x84\x17"
++			  "\xe8\xd1\x2c\xfd\xf9\x26\xe0",
+ 		.ilen	= 31,
+-		.result	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
++		.result	= "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e",
+ 		.rlen	= 23,
+ 	}, {
+-		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.key	= "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+-		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b },
++		.iv	= "\x01\x00\x00\x00\x07\x06\x05\x04"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++		.assoc	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b",
+ 		.alen	= 12,
+-		.input	= { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
+-			    0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
+-			    0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
+-			    0x7d, 0x9c, 0x2d, 0x93 },
++		.input	= "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb"
++			  "\x9d\x4e\x13\x12\x53\x65\x8a\xd8"
++			  "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07"
++			  "\x7d\x9c\x2d\x93",
+ 		.ilen	= 28,
+-		.result	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+-			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+-			    0x1c, 0x1d, 0x1e, 0x1f },
++		.result	= "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
++			  "\x14\x15\x16\x17\x18\x19\x1a\x1b"
++			  "\x1c\x1d\x1e\x1f",
+ 		.rlen	= 20,
+ 	}, {
+-		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.key	= "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+-		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++		.iv	= "\x01\x00\x00\x00\x0b\x0a\x09\x08"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++		.assoc	= "\x00\x01\x02\x03\x04\x05\x06\x07",
+ 		.alen	= 8,
+-		.input	= { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
+-			    0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
+-			    0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
+-			    0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
+-			    0x7e, 0x5f, 0x4e },
++		.input	= "\x82\x53\x1a\x60\xcc\x24\x94\x5a"
++			  "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d"
++			  "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1"
++			  "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1"
++			  "\x7e\x5f\x4e",
+ 		.ilen	= 35,
+-		.result	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			    0x20 },
++		.result	= "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			  "\x20",
+ 		.rlen	= 25,
+ 	}, {
+-		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.key	= "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
+-			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+-		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b },
++		.iv	= "\x01\x00\x00\x00\x0c\x0b\x0a\x09"
++			  "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++		.assoc	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b",
+ 		.alen	= 12,
+-		.input	= { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
+-			    0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
+-			    0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
+-			    0x4d, 0x99, 0x99, 0x88, 0xdd },
++		.input	= "\x07\x34\x25\x94\x15\x77\x85\x15"
++			  "\x2b\x07\x40\x98\x33\x0a\xbb\x14"
++			  "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b"
++			  "\x4d\x99\x99\x88\xdd",
+ 		.ilen	= 29,
+-		.result	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+-			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+-			    0x1c, 0x1d, 0x1e },
++		.result	= "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
++			  "\x14\x15\x16\x17\x18\x19\x1a\x1b"
++			  "\x1c\x1d\x1e",
+ 		.rlen	= 19,
+ 	}, {
+-		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+-			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.key	= "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++			  "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
+-			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+-		.assoc	= { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
++		.iv	= "\x01\x00\x33\x56\x8e\xf7\xb2\x63"
++			  "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++		.assoc	= "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb",
+ 		.alen	= 8,
+-		.input	= { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
+-			    0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
+-			    0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
+-			    0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
++		.input	= "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa"
++			  "\xa0\x72\x6c\x55\xd3\x78\x06\x12"
++			  "\x98\xc8\x5c\x92\x81\x4a\xbc\x33"
++			  "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a",
+ 		.ilen	= 32,
+-		.result	= { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
+-			    0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
+-			    0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
++		.result	= "\x90\x20\xea\x6f\x91\xbd\xd8\x5a"
++			  "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf"
++			  "\xb7\x9c\x70\x28\x94\x9c\xd0\xec",
+ 		.rlen	= 24,
+ 	}, {
+-		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+-			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.key	= "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++			  "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
+-			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+-		.assoc	= { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
+-			    0x20, 0xea, 0x60, 0xc0 },
++		.iv	= "\x01\x00\xd5\x60\x91\x2d\x3f\x70"
++			  "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++		.assoc	= "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81"
++			  "\x20\xea\x60\xc0",
+ 		.alen	= 12,
+-		.input	= { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
+-			    0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
+-			    0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
+-			    0x5a, 0xe0, 0x70, 0x45, 0x51 },
++		.input	= "\x00\x97\x69\xec\xab\xdf\x48\x62"
++			  "\x55\x94\xc5\x92\x51\xe6\x03\x57"
++			  "\x22\x67\x5e\x04\xc8\x47\x09\x9e"
++			  "\x5a\xe0\x70\x45\x51",
+ 		.ilen	= 29,
+-		.result	= { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
+-			    0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
+-			    0x3a, 0x80, 0x3b, 0xa8, 0x7f },
++		.result	= "\x64\x35\xac\xba\xfb\x11\xa8\x2e"
++			  "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9"
++			  "\x3a\x80\x3b\xa8\x7f",
+ 		.rlen	= 21,
+ 	}, {
+-		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+-			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.key	= "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++			  "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ 		.klen	= 16,
+-		.iv	= { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
+-			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+-		.assoc	= { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
++		.iv	= "\x01\x00\x42\xff\xf8\xf1\x95\x1c"
++			  "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++		.assoc	= "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8",
+ 		.alen	= 8,
+-		.input	= { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
+-			    0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
+-			    0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
+-			    0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
+-			    0xba },
++		.input	= "\xbc\x21\x8d\xaa\x94\x74\x27\xb6"
++			  "\xdb\x38\x6a\x99\xac\x1a\xef\x23"
++			  "\xad\xe0\xb5\x29\x39\xcb\x6a\x63"
++			  "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6"
++			  "\xba",
+ 		.ilen	= 33,
+-		.result	= { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
+-			    0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
+-			    0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
++		.result	= "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01"
++			  "\x8e\x5e\x67\x01\xc9\x17\x87\x65"
++			  "\x98\x09\xd6\x7d\xbe\xdd\x18",
+ 		.rlen	= 23,
+ 	},
+ };
+@@ -5294,54 +5323,54 @@ static struct aead_testvec aes_ccm_dec_tv_template[] = {
+ 
+ static struct cipher_testvec cast5_enc_tv_template[] = {
+ 	{
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+-			    0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
++		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
++			  "\x23\x45\x67\x89\x34\x56\x78\x9a",
+ 		.klen	= 16,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.ilen	= 8,
+-		.result	= { 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 },
++		.result	= "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+-			    0x23, 0x45 },
++		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
++			  "\x23\x45",
+ 		.klen	= 10,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.ilen	= 8,
+-		.result	= { 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b },
++		.result	= "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12 },
++		.key	= "\x01\x23\x45\x67\x12",
+ 		.klen	= 5,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.ilen	= 8,
+-		.result	= { 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e },
++		.result	= "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e",
+ 		.rlen	= 8,
+ 	},
+ };
+ 
+ static struct cipher_testvec cast5_dec_tv_template[] = {
+ 	{
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+-			    0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
++		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
++			  "\x23\x45\x67\x89\x34\x56\x78\x9a",
+ 		.klen	= 16,
+-		.input	= { 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 },
++		.input	= "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2",
+ 		.ilen	= 8,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+-			    0x23, 0x45 },
++		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
++			  "\x23\x45",
+ 		.klen	= 10,
+-		.input	= { 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b },
++		.input	= "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b",
+ 		.ilen	= 8,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12 },
++		.key	= "\x01\x23\x45\x67\x12",
+ 		.klen	= 5,
+-		.input	= { 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e },
++		.input	= "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e",
+ 		.ilen	= 8,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.rlen	= 8,
+ 	},
+ };
+@@ -5354,132 +5383,132 @@ static struct cipher_testvec cast5_dec_tv_template[] = {
+ 
+ static struct cipher_testvec arc4_enc_tv_template[] = {
+ 	{
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.ilen	= 8,
+-		.result	= { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
++		.result	= "\x75\xb7\x87\x80\x99\xe0\xc5\x96",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 8,
+-		.result	= { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
++		.result	= "\x74\x94\xc2\xe7\x10\x4b\x08\x79",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 8,
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 8,
+-		.result	= { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
++		.result	= "\xde\x18\x89\x41\xa3\x37\x5d\x3a",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0xef, 0x01, 0x23, 0x45},
++		.key	= "\xef\x01\x23\x45",
+ 		.klen	= 4,
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00",
+ 		.ilen	= 20,
+-		.result	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+-			    0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+-			    0x36, 0xb6, 0x78, 0x58 },
++		.result	= "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf"
++			  "\xbd\x61\x5a\x11\x62\xe1\xc7\xba"
++			  "\x36\xb6\x78\x58",
+ 		.rlen	= 20,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+-			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+-			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+-			    0x12, 0x34, 0x56, 0x78 },
++		.input	= "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++			  "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++			  "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++			  "\x12\x34\x56\x78",
+ 		.ilen	= 28,
+-		.result	= { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+-			    0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+-			    0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+-			    0x40, 0x01, 0x1e, 0xcf },
++		.result	= "\x66\xa0\x94\x9f\x8a\xf7\xd6\x89"
++			  "\x1f\x7f\x83\x2b\xa8\x33\xc0\x0c"
++			  "\x89\x2e\xbe\x30\x14\x3c\xe2\x87"
++			  "\x40\x01\x1e\xcf",
+ 		.rlen	= 28,
+ 	}, {
+-		.key	= { 0xef, 0x01, 0x23, 0x45 },
++		.key	= "\xef\x01\x23\x45",
+ 		.klen	= 4,
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00",
+ 		.ilen	= 10,
+-		.result	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+-			    0xbd, 0x61 },
++		.result	= "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf"
++			  "\xbd\x61",
+ 		.rlen	= 10,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+-		            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x01\x23\x45\x67\x89\xAB\xCD\xEF"
++			"\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 16,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
++		.input	= "\x01\x23\x45\x67\x89\xAB\xCD\xEF",
+ 		.ilen	= 8,
+-		.result	= { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
++		.result	= "\x69\x72\x36\x59\x1B\x52\x42\xB1",
+ 		.rlen	= 8,
+ 	},
+ };
+ 
+ static struct cipher_testvec arc4_dec_tv_template[] = {
+ 	{
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
++		.input	= "\x75\xb7\x87\x80\x99\xe0\xc5\x96",
+ 		.ilen	= 8,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
++		.input	= "\x74\x94\xc2\xe7\x10\x4b\x08\x79",
+ 		.ilen	= 8,
+-		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 8,
+-		.input	= { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
++		.input	= "\xde\x18\x89\x41\xa3\x37\x5d\x3a",
+ 		.ilen	= 8,
+-		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0xef, 0x01, 0x23, 0x45},
++		.key	= "\xef\x01\x23\x45",
+ 		.klen	= 4,
+-		.input	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+-			    0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+-			    0x36, 0xb6, 0x78, 0x58 },
++		.input	= "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf"
++			  "\xbd\x61\x5a\x11\x62\xe1\xc7\xba"
++			  "\x36\xb6\x78\x58",
+ 		.ilen	= 20,
+-		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00 },
++		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00",
+ 		.rlen	= 20,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ 		.klen	= 8,
+-		.input	= { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+-			    0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+-			    0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+-			    0x40, 0x01, 0x1e, 0xcf },
++		.input	= "\x66\xa0\x94\x9f\x8a\xf7\xd6\x89"
++			  "\x1f\x7f\x83\x2b\xa8\x33\xc0\x0c"
++			  "\x89\x2e\xbe\x30\x14\x3c\xe2\x87"
++			  "\x40\x01\x1e\xcf",
+ 		.ilen	= 28,
+-		.result	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+-			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+-			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+-			    0x12, 0x34, 0x56, 0x78 },
++		.result	= "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++			  "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++			  "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++			  "\x12\x34\x56\x78",
+ 		.rlen	= 28,
+ 	}, {
+-		.key	= { 0xef, 0x01, 0x23, 0x45 },
++		.key	= "\xef\x01\x23\x45",
+ 		.klen	= 4,
+-		.input	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+-			    0xbd, 0x61 },
++		.input	= "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf"
++			  "\xbd\x61",
+ 		.ilen	= 10,
+-		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00 },
++		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00",
+ 		.rlen	= 10,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+-		            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x01\x23\x45\x67\x89\xAB\xCD\xEF"
++			"\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 16,
+-		.input	= { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
++		.input	= "\x69\x72\x36\x59\x1B\x52\x42\xB1",
+ 		.ilen	= 8,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
++		.result	= "\x01\x23\x45\x67\x89\xAB\xCD\xEF",
+ 		.rlen	= 8,
+ 	},
+ };
+@@ -5492,86 +5521,86 @@ static struct cipher_testvec arc4_dec_tv_template[] = {
+ 
+ static struct cipher_testvec tea_enc_tv_template[] = {
+ 	{
+-		.key    = { [0 ... 15] = 0x00 },
++		.key    = zeroed_string,
+ 		.klen	= 16,
+-		.input  = { [0 ... 8] = 0x00 },
++		.input  = zeroed_string,
+ 		.ilen	= 8,
+-		.result	= { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
++		.result	= "\x0a\x3a\xea\x41\x40\xa9\xba\x94",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+-			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++		.key	= "\x2b\x02\x05\x68\x06\x14\x49\x76"
++			  "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ 		.klen	= 16,
+-		.input	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++		.input	= "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ 		.ilen	= 8,
+-		.result	= { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
++		.result	= "\x77\x5d\x2a\x6a\xf6\xce\x92\x09",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+-			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++		.key	= "\x09\x65\x43\x11\x66\x44\x39\x25"
++			  "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ 		.klen	= 16,
+-		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+-			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++		.input	= "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++			  "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ 		.ilen	= 16,
+-		.result	= { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
+-			    0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
++		.result	= "\xbe\x7a\xbb\x81\x95\x2d\x1f\x1e"
++			  "\xdd\x89\xa1\x25\x04\x21\xdf\x95",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+-			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++		.key	= "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++			  "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ 		.klen	= 16,
+-		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+-			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++		.input	= "\x54\x65\x61\x20\x69\x73\x20\x67"
++			  "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++			  "\x79\x6f\x75\x21\x21\x21\x20\x72"
++			  "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ 		.ilen	= 32,
+-		.result	= { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+-			    0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+-			    0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+-			    0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
++		.result	= "\xe0\x4d\x5d\x3c\xb7\x8c\x36\x47"
++			  "\x94\x18\x95\x91\xa9\xfc\x49\xf8"
++			  "\x44\xd1\x2d\xc2\x99\xb8\x08\x2a"
++			  "\x07\x89\x73\xc2\x45\x92\xc6\x90",
+ 		.rlen	= 32,
+ 	}
+ };
+ 
+ static struct cipher_testvec tea_dec_tv_template[] = {
+ 	{
+-		.key    = { [0 ... 15] = 0x00 },
++		.key    = zeroed_string,
+ 		.klen	= 16,
+-		.input	= { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
++		.input	= "\x0a\x3a\xea\x41\x40\xa9\xba\x94",
+ 		.ilen	= 8,
+-		.result = { [0 ... 8] = 0x00 },
++		.result = zeroed_string,
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+-			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++		.key	= "\x2b\x02\x05\x68\x06\x14\x49\x76"
++			  "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ 		.klen	= 16,
+-		.input	= { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
++		.input	= "\x77\x5d\x2a\x6a\xf6\xce\x92\x09",
+ 		.ilen	= 8,
+-		.result	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++		.result	= "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+-			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++		.key	= "\x09\x65\x43\x11\x66\x44\x39\x25"
++			  "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ 		.klen	= 16,
+-		.input	= { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
+-			    0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
++		.input	= "\xbe\x7a\xbb\x81\x95\x2d\x1f\x1e"
++			  "\xdd\x89\xa1\x25\x04\x21\xdf\x95",
+ 		.ilen   = 16,
+-		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+-			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++		.result	= "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++			  "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+-			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++		.key	= "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++			  "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ 		.klen	= 16,
+-		.input	= { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+-			    0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+-			    0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+-			    0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
++		.input	= "\xe0\x4d\x5d\x3c\xb7\x8c\x36\x47"
++			  "\x94\x18\x95\x91\xa9\xfc\x49\xf8"
++			  "\x44\xd1\x2d\xc2\x99\xb8\x08\x2a"
++			  "\x07\x89\x73\xc2\x45\x92\xc6\x90",
+ 		.ilen	= 32,
+-		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+-			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++		.result	= "\x54\x65\x61\x20\x69\x73\x20\x67"
++			  "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++			  "\x79\x6f\x75\x21\x21\x21\x20\x72"
++			  "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ 		.rlen	= 32,
+ 	}
+ };
+@@ -5584,86 +5613,86 @@ static struct cipher_testvec tea_dec_tv_template[] = {
+ 
+ static struct cipher_testvec xtea_enc_tv_template[] = {
+ 	{
+-		.key    = { [0 ... 15] = 0x00 },
++		.key    = zeroed_string,
+ 		.klen	= 16,
+-		.input  = { [0 ... 8] = 0x00 },
++		.input  = zeroed_string,
+ 		.ilen	= 8,
+-		.result	= { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 },
++		.result	= "\xd8\xd4\xe9\xde\xd9\x1e\x13\xf7",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+-			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++		.key	= "\x2b\x02\x05\x68\x06\x14\x49\x76"
++			  "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ 		.klen	= 16,
+-		.input	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++		.input	= "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ 		.ilen	= 8,
+-		.result	= { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 },
++		.result	= "\x94\xeb\xc8\x96\x84\x6a\x49\xa8",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+-			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++		.key	= "\x09\x65\x43\x11\x66\x44\x39\x25"
++			  "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ 		.klen	= 16,
+-		.input	= { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d,
+-			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++		.input	= "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++			  "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ 		.ilen	= 16,
+-		.result	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+-			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
++		.result	= "\x3e\xce\xae\x22\x60\x56\xa8\x9d"
++			  "\x77\x4d\xd4\xb4\x87\x24\xe3\x9a",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+-			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++		.key	= "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++			  "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ 		.klen	= 16,
+-		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+-			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++		.input	= "\x54\x65\x61\x20\x69\x73\x20\x67"
++			  "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++			  "\x79\x6f\x75\x21\x21\x21\x20\x72"
++			  "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ 		.ilen	= 32,
+-		.result	= { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a,
+-			    0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07,
+-			    0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4,
+-			    0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 },
++		.result	= "\x99\x81\x9f\x5d\x6f\x4b\x31\x3a"
++			  "\x86\xff\x6f\xd0\xe3\x87\x70\x07"
++			  "\x4d\xb8\xcf\xf3\x99\x50\xb3\xd4"
++			  "\x73\xa2\xfa\xc9\x16\x59\x5d\x81",
+ 		.rlen	= 32,
+ 	}
+ };
+ 
+ static struct cipher_testvec xtea_dec_tv_template[] = {
+ 	{
+-		.key    = { [0 ... 15] = 0x00 },
++		.key    = zeroed_string,
+ 		.klen	= 16,
+-		.input	= { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 },
++		.input	= "\xd8\xd4\xe9\xde\xd9\x1e\x13\xf7",
+ 		.ilen	= 8,
+-		.result = { [0 ... 8] = 0x00 },
++		.result = zeroed_string,
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+-			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++		.key	= "\x2b\x02\x05\x68\x06\x14\x49\x76"
++			  "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ 		.klen	= 16,
+-		.input	= { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 },
++		.input	= "\x94\xeb\xc8\x96\x84\x6a\x49\xa8",
+ 		.ilen	= 8,
+-		.result	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++		.result	= "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+-			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++		.key	= "\x09\x65\x43\x11\x66\x44\x39\x25"
++			  "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ 		.klen	= 16,
+-		.input	= { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d,
+-			    0x77, 0x4d, 0xd4, 0xb4, 0x87, 0x24, 0xe3, 0x9a },
++		.input	= "\x3e\xce\xae\x22\x60\x56\xa8\x9d"
++			  "\x77\x4d\xd4\xb4\x87\x24\xe3\x9a",
+ 		.ilen	= 16,
+-		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+-			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++		.result	= "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++			  "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+-			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++		.key	= "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++			  "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ 		.klen	= 16,
+-		.input	= { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a,
+-			    0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07,
+-			    0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4,
+-			    0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 },
++		.input	= "\x99\x81\x9f\x5d\x6f\x4b\x31\x3a"
++			  "\x86\xff\x6f\xd0\xe3\x87\x70\x07"
++			  "\x4d\xb8\xcf\xf3\x99\x50\xb3\xd4"
++			  "\x73\xa2\xfa\xc9\x16\x59\x5d\x81",
+ 		.ilen	= 32,
+-		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+-			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++		.result	= "\x54\x65\x61\x20\x69\x73\x20\x67"
++			  "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++			  "\x79\x6f\x75\x21\x21\x21\x20\x72"
++			  "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ 		.rlen	= 32,
+ 	}
+ };
+@@ -5676,92 +5705,92 @@ static struct cipher_testvec xtea_dec_tv_template[] = {
+ 
+ static struct cipher_testvec khazad_enc_tv_template[] = {
+ 	{
+-		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x80\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 16,
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 8,
+-		.result	= { 0x49, 0xa4, 0xce, 0x32, 0xac, 0x19, 0x0e, 0x3f },
++		.result	= "\x49\xa4\xce\x32\xac\x19\x0e\x3f",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+-			    0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
++		.key	= "\x38\x38\x38\x38\x38\x38\x38\x38"
++			  "\x38\x38\x38\x38\x38\x38\x38\x38",
+ 		.klen	= 16,
+-		.input	= { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
++		.input	= "\x38\x38\x38\x38\x38\x38\x38\x38",
+ 		.ilen	= 8,
+-		.result	= { 0x7e, 0x82, 0x12, 0xa1, 0Xd9, 0X5b, 0Xe4, 0Xf9 },
++		.result	= "\x7e\x82\x12\xa1\xd9\x5b\xe4\xf9",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2,
+-			    0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
++		.key	= "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2"
++			"\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2",
+ 		.klen	= 16,
+-		.input	= { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
++		.input	= "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2",
+ 		.ilen	= 8,
+-		.result	= { 0Xaa, 0Xbe, 0Xc1, 0X95, 0Xc5, 0X94, 0X1a, 0X9c },
++		.result	= "\xaa\xbe\xc1\x95\xc5\x94\x1a\x9c",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+-			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++		.key	= "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++			"\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ 		.klen	= 16,
+-		.input	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++		.input	= "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ 		.ilen	= 8,
+-		.result = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
++		.result = "\x04\x74\xf5\x70\x50\x16\xd3\xb8",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+-			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++		.key	= "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++			"\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ 		.klen	= 16,
+-		.input	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f ,
+-			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++		.input	= "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++			"\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ 		.ilen	= 16,
+-		.result = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 ,
+-			    0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
++		.result = "\x04\x74\xf5\x70\x50\x16\xd3\xb8"
++			"\x04\x74\xf5\x70\x50\x16\xd3\xb8",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec khazad_dec_tv_template[] = {
+ 	{
+-		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x80\x00\x00\x00\x00\x00\x00\x00"
++			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 16,
+-		.input	= { 0X49, 0Xa4, 0Xce, 0X32, 0Xac, 0X19, 0X0e, 0X3f },
++		.input	= "\x49\xa4\xce\x32\xac\x19\x0e\x3f",
+ 		.ilen	= 8,
+-		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+-			    0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
++		.key	= "\x38\x38\x38\x38\x38\x38\x38\x38"
++			  "\x38\x38\x38\x38\x38\x38\x38\x38",
+ 		.klen	= 16,
+-		.input	= { 0X7e, 0X82, 0X12, 0Xa1, 0Xd9, 0X5b, 0Xe4, 0Xf9 },
++		.input	= "\x7e\x82\x12\xa1\xd9\x5b\xe4\xf9",
+ 		.ilen	= 8,
+-		.result	= { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
++		.result	= "\x38\x38\x38\x38\x38\x38\x38\x38",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2,
+-			    0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
++		.key	= "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2"
++			"\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2",
+ 		.klen	= 16,
+-		.input	= { 0Xaa, 0Xbe, 0Xc1, 0X95, 0Xc5, 0X94, 0X1a, 0X9c },
++		.input	= "\xaa\xbe\xc1\x95\xc5\x94\x1a\x9c",
+ 		.ilen	= 8,
+-		.result	= { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
++		.result	= "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+-			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++		.key	= "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++			"\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ 		.klen	= 16,
+-		.input = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
++		.input  = "\x04\x74\xf5\x70\x50\x16\xd3\xb8",
+ 		.ilen	= 8,
+-		.result	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++		.result	= "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+-			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++		.key	= "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++			"\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ 		.klen	= 16,
+-		.input = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 ,
+-			    0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
++		.input  = "\x04\x74\xf5\x70\x50\x16\xd3\xb8"
++			"\x04\x74\xf5\x70\x50\x16\xd3\xb8",
+ 		.ilen	= 16,
+-		.result	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f ,
+-			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++		.result	= "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++			"\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ 		.rlen	= 16,
+ 	},
+ };
+@@ -5777,196 +5806,196 @@ static struct cipher_testvec khazad_dec_tv_template[] = {
+ 
+ static struct cipher_testvec anubis_enc_tv_template[] = {
+ 	{
+-		.key	= { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++		.key	= "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ 		.klen	= 16,
+-		.input	= { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++		.input	= "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ 		.ilen	= 16,
+-		.result	= { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f,
+-			    0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90 },
++		.result	= "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f"
++			  "\x08\xb7\x52\x8e\x6e\x6e\x86\x90",
+ 		.rlen	= 16,
+ 	}, {
+ 
+-		.key	= { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+-			    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+-			    0x03, 0x03, 0x03, 0x03 },
++		.key	= "\x03\x03\x03\x03\x03\x03\x03\x03"
++			  "\x03\x03\x03\x03\x03\x03\x03\x03"
++			  "\x03\x03\x03\x03",
+ 		.klen	= 20,
+-		.input	= { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+-			    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 },
++		.input	= "\x03\x03\x03\x03\x03\x03\x03\x03"
++			  "\x03\x03\x03\x03\x03\x03\x03\x03",
+ 		.ilen	= 16,
+-		.result	= { 0xdb, 0xf1, 0x42, 0xf4, 0xd1, 0x8a, 0xc7, 0x49,
+-			    0x87, 0x41, 0x6f, 0x82, 0x0a, 0x98, 0x64, 0xae },
++		.result	= "\xdb\xf1\x42\xf4\xd1\x8a\xc7\x49"
++			  "\x87\x41\x6f\x82\x0a\x98\x64\xae",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+-			    0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+-			    0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+-			    0x24, 0x24, 0x24, 0x24 },
++		.key	= "\x24\x24\x24\x24\x24\x24\x24\x24"
++			  "\x24\x24\x24\x24\x24\x24\x24\x24"
++			  "\x24\x24\x24\x24\x24\x24\x24\x24"
++			  "\x24\x24\x24\x24",
+ 		.klen	= 28,
+-		.input	= { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+-			    0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24 },
++		.input	= "\x24\x24\x24\x24\x24\x24\x24\x24"
++			  "\x24\x24\x24\x24\x24\x24\x24\x24",
+ 		.ilen	= 16,
+-		.result	= { 0xfd, 0x1b, 0x4a, 0xe3, 0xbf, 0xf0, 0xad, 0x3d,
+-			    0x06, 0xd3, 0x61, 0x27, 0xfd, 0x13, 0x9e, 0xde },
++		.result	= "\xfd\x1b\x4a\xe3\xbf\xf0\xad\x3d"
++			  "\x06\xd3\x61\x27\xfd\x13\x9e\xde",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+-			    0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+-			    0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+-			    0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 },
++		.key	= "\x25\x25\x25\x25\x25\x25\x25\x25"
++			  "\x25\x25\x25\x25\x25\x25\x25\x25"
++			  "\x25\x25\x25\x25\x25\x25\x25\x25"
++			  "\x25\x25\x25\x25\x25\x25\x25\x25",
+ 		.klen	= 32,
+-		.input	= { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+-			    0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 },
++		.input	= "\x25\x25\x25\x25\x25\x25\x25\x25"
++			  "\x25\x25\x25\x25\x25\x25\x25\x25",
+ 		.ilen	= 16,
+-		.result	= { 0x1a, 0x91, 0xfb, 0x2b, 0xb7, 0x78, 0x6b, 0xc4,
+-		            0x17, 0xd9, 0xff, 0x40, 0x3b, 0x0e, 0xe5, 0xfe },
++		.result	= "\x1a\x91\xfb\x2b\xb7\x78\x6b\xc4"
++			"\x17\xd9\xff\x40\x3b\x0e\xe5\xfe",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++		.key	= "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35",
+ 		.klen	= 40,
+-		.input	= { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++		.input	= "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35",
+ 		.ilen	= 16,
+-		.result = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97,
+-			    0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee },
++		.result = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97"
++			  "\x9e\xc6\x84\x0f\x17\x21\x07\xee",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec anubis_dec_tv_template[] = {
+ 	{
+-		.key	= { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++		.key	= "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ 		.klen	= 16,
+-		.input	= { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f,
+-			    0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90 },
++		.input	= "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f"
++			  "\x08\xb7\x52\x8e\x6e\x6e\x86\x90",
+ 		.ilen	= 16,
+-		.result	= { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++		.result	= "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ 		.rlen	= 16,
+ 	}, {
+ 
+-		.key	= { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+-			    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+-			    0x03, 0x03, 0x03, 0x03 },
++		.key	= "\x03\x03\x03\x03\x03\x03\x03\x03"
++			  "\x03\x03\x03\x03\x03\x03\x03\x03"
++			  "\x03\x03\x03\x03",
+ 		.klen	= 20,
+-		.input	= { 0xdb, 0xf1, 0x42, 0xf4, 0xd1, 0x8a, 0xc7, 0x49,
+-			    0x87, 0x41, 0x6f, 0x82, 0x0a, 0x98, 0x64, 0xae },
++		.input	= "\xdb\xf1\x42\xf4\xd1\x8a\xc7\x49"
++			  "\x87\x41\x6f\x82\x0a\x98\x64\xae",
+ 		.ilen	= 16,
+-		.result	= { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+-			    0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 },
++		.result	= "\x03\x03\x03\x03\x03\x03\x03\x03"
++			  "\x03\x03\x03\x03\x03\x03\x03\x03",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+-			    0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+-			    0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+-			    0x24, 0x24, 0x24, 0x24 },
++		.key	= "\x24\x24\x24\x24\x24\x24\x24\x24"
++			  "\x24\x24\x24\x24\x24\x24\x24\x24"
++			  "\x24\x24\x24\x24\x24\x24\x24\x24"
++			  "\x24\x24\x24\x24",
+ 		.klen	= 28,
+-		.input	= { 0xfd, 0x1b, 0x4a, 0xe3, 0xbf, 0xf0, 0xad, 0x3d,
+-			    0x06, 0xd3, 0x61, 0x27, 0xfd, 0x13, 0x9e, 0xde },
++		.input	= "\xfd\x1b\x4a\xe3\xbf\xf0\xad\x3d"
++			  "\x06\xd3\x61\x27\xfd\x13\x9e\xde",
+ 		.ilen	= 16,
+-		.result	= { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+-			    0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24 },
++		.result	= "\x24\x24\x24\x24\x24\x24\x24\x24"
++			  "\x24\x24\x24\x24\x24\x24\x24\x24",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+-			    0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+-			    0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+-			    0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 },
++		.key	= "\x25\x25\x25\x25\x25\x25\x25\x25"
++			  "\x25\x25\x25\x25\x25\x25\x25\x25"
++			  "\x25\x25\x25\x25\x25\x25\x25\x25"
++			  "\x25\x25\x25\x25\x25\x25\x25\x25",
+ 		.klen	= 32,
+-		.input	= { 0x1a, 0x91, 0xfb, 0x2b, 0xb7, 0x78, 0x6b, 0xc4,
+-		            0x17, 0xd9, 0xff, 0x40, 0x3b, 0x0e, 0xe5, 0xfe },
++		.input	= "\x1a\x91\xfb\x2b\xb7\x78\x6b\xc4"
++			"\x17\xd9\xff\x40\x3b\x0e\xe5\xfe",
+ 		.ilen	= 16,
+-		.result	= { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+-			    0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 },
++		.result	= "\x25\x25\x25\x25\x25\x25\x25\x25"
++			  "\x25\x25\x25\x25\x25\x25\x25\x25",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
+-		.input = {  0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97,
+-			    0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee },
++		.key	= "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35",
++		.input = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97"
++			 "\x9e\xc6\x84\x0f\x17\x21\x07\xee",
+ 		.klen	= 40,
+ 		.ilen	= 16,
+-		.result	= { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++		.result	= "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec anubis_cbc_enc_tv_template[] = {
+ 	{
+-		.key	= { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++		.key	= "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ 		.klen	= 16,
+-		.input	= { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++		.input	= "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ 		.ilen	= 32,
+-		.result	= { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f,
+-			    0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90,
+-			    0x86, 0xd8, 0xb5, 0x6f, 0x98, 0x5e, 0x8a, 0x66,
+-			    0x4f, 0x1f, 0x78, 0xa1, 0xbb, 0x37, 0xf1, 0xbe },
++		.result	= "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f"
++			  "\x08\xb7\x52\x8e\x6e\x6e\x86\x90"
++			  "\x86\xd8\xb5\x6f\x98\x5e\x8a\x66"
++			  "\x4f\x1f\x78\xa1\xbb\x37\xf1\xbe",
+ 		.rlen	= 32,
+ 	}, {
+-		.key	= { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++		.key	= "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35",
+ 		.klen	= 40,
+-		.input	= { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++		.input	= "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35",
+ 		.ilen	= 32,
+-		.result = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97,
+-			    0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee,
+-			    0xa2, 0xbc, 0x06, 0x98, 0xc6, 0x4b, 0xda, 0x75,
+-			    0x2e, 0xaa, 0xbe, 0x58, 0xce, 0x01, 0x5b, 0xc7 },
++		.result = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97"
++			  "\x9e\xc6\x84\x0f\x17\x21\x07\xee"
++			  "\xa2\xbc\x06\x98\xc6\x4b\xda\x75"
++			  "\x2e\xaa\xbe\x58\xce\x01\x5b\xc7",
+ 		.rlen	= 32,
+ 	},
+ };
+ 
+ static struct cipher_testvec anubis_cbc_dec_tv_template[] = {
+ 	{
+-		.key	= { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++		.key	= "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ 		.klen	= 16,
+-		.input	= { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f,
+-			    0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90,
+-			    0x86, 0xd8, 0xb5, 0x6f, 0x98, 0x5e, 0x8a, 0x66,
+-			    0x4f, 0x1f, 0x78, 0xa1, 0xbb, 0x37, 0xf1, 0xbe },
++		.input	= "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f"
++			  "\x08\xb7\x52\x8e\x6e\x6e\x86\x90"
++			  "\x86\xd8\xb5\x6f\x98\x5e\x8a\x66"
++			  "\x4f\x1f\x78\xa1\xbb\x37\xf1\xbe",
+ 		.ilen	= 32,
+-		.result	= { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+-			    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++		.result	= "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++			  "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ 		.rlen	= 32,
+ 	}, {
+-		.key	= { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++		.key	= "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35",
+ 		.klen	= 40,
+-		.input = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97,
+-			    0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee,
+-			    0xa2, 0xbc, 0x06, 0x98, 0xc6, 0x4b, 0xda, 0x75,
+-			    0x2e, 0xaa, 0xbe, 0x58, 0xce, 0x01, 0x5b, 0xc7 },
++		.input = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97"
++			  "\x9e\xc6\x84\x0f\x17\x21\x07\xee"
++			  "\xa2\xbc\x06\x98\xc6\x4b\xda\x75"
++			  "\x2e\xaa\xbe\x58\xce\x01\x5b\xc7",
+ 		.ilen	= 32,
+-		.result	= { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+-			    0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++		.result	= "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35"
++			  "\x35\x35\x35\x35\x35\x35\x35\x35",
+ 		.rlen	= 32,
+ 	},
+ };
+@@ -5979,86 +6008,86 @@ static struct cipher_testvec anubis_cbc_dec_tv_template[] = {
+ 
+ static struct cipher_testvec xeta_enc_tv_template[] = {
+ 	{
+-		.key    = { [0 ... 15] = 0x00 },
++		.key    = zeroed_string,
+ 		.klen	= 16,
+-		.input  = { [0 ... 8] = 0x00 },
++		.input  = zeroed_string,
+ 		.ilen	= 8,
+-		.result	= { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
++		.result	= "\xaa\x22\x96\xe5\x6c\x61\xf3\x45",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+-			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++		.key	= "\x2b\x02\x05\x68\x06\x14\x49\x76"
++			  "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ 		.klen	= 16,
+-		.input	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++		.input	= "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ 		.ilen	= 8,
+-		.result	= { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
++		.result	= "\x82\x3e\xeb\x35\xdc\xdd\xd9\xc3",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+-			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++		.key	= "\x09\x65\x43\x11\x66\x44\x39\x25"
++			  "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ 		.klen	= 16,
+-		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+-			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++		.input	= "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++			  "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ 		.ilen	= 16,
+-		.result	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+-			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
++		.result	= "\xe2\x04\xdb\xf2\x89\x85\x9e\xea"
++			  "\x61\x35\xaa\xed\xb5\xcb\x71\x2c",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+-			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++		.key	= "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++			  "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ 		.klen	= 16,
+-		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+-			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++		.input	= "\x54\x65\x61\x20\x69\x73\x20\x67"
++			  "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++			  "\x79\x6f\x75\x21\x21\x21\x20\x72"
++			  "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ 		.ilen	= 32,
+-		.result	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
+-			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
+-			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+-			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
++		.result	= "\x0b\x03\xcd\x8a\xbe\x95\xfd\xb1"
++			  "\xc1\x44\x91\x0b\xa5\xc9\x1b\xb4"
++			  "\xa9\xda\x1e\x9e\xb1\x3e\x2a\x8f"
++			  "\xea\xa5\x6a\x85\xd1\xf4\xa8\xa5",
+ 		.rlen	= 32,
+ 	}
+ };
+ 
+ static struct cipher_testvec xeta_dec_tv_template[] = {
+ 	{
+-		.key    = { [0 ... 15] = 0x00 },
++		.key    = zeroed_string,
+ 		.klen	= 16,
+-		.input	= { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
++		.input	= "\xaa\x22\x96\xe5\x6c\x61\xf3\x45",
+ 		.ilen	= 8,
+-		.result = { [0 ... 8] = 0x00 },
++		.result = zeroed_string,
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+-			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++		.key	= "\x2b\x02\x05\x68\x06\x14\x49\x76"
++			  "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ 		.klen	= 16,
+-		.input	= { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
++		.input	= "\x82\x3e\xeb\x35\xdc\xdd\xd9\xc3",
+ 		.ilen	= 8,
+-		.result	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++		.result	= "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+-			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++		.key	= "\x09\x65\x43\x11\x66\x44\x39\x25"
++			  "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ 		.klen	= 16,
+-		.input	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+-			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
++		.input	= "\xe2\x04\xdb\xf2\x89\x85\x9e\xea"
++			  "\x61\x35\xaa\xed\xb5\xcb\x71\x2c",
+ 		.ilen	= 16,
+-		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+-			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++		.result	= "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++			  "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+-			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++		.key	= "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++			  "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ 		.klen	= 16,
+-		.input	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
+-			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
+-			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+-			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
++		.input	= "\x0b\x03\xcd\x8a\xbe\x95\xfd\xb1"
++			  "\xc1\x44\x91\x0b\xa5\xc9\x1b\xb4"
++			  "\xa9\xda\x1e\x9e\xb1\x3e\x2a\x8f"
++			  "\xea\xa5\x6a\x85\xd1\xf4\xa8\xa5",
+ 		.ilen	= 32,
+-		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+-			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++		.result	= "\x54\x65\x61\x20\x69\x73\x20\x67"
++			  "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++			  "\x79\x6f\x75\x21\x21\x21\x20\x72"
++			  "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ 		.rlen	= 32,
+ 	}
+ };
+@@ -6071,59 +6100,59 @@ static struct cipher_testvec xeta_dec_tv_template[] = {
+ 
+ static struct cipher_testvec fcrypt_pcbc_enc_tv_template[] = {
+ 	{ /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */
+-		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 8,
+-		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 8,
+-		.result	= { 0x0E, 0x09, 0x00, 0xC7, 0x3E, 0xF7, 0xED, 0x41 },
++		.result	= "\x0E\x09\x00\xC7\x3E\xF7\xED\x41",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x11, 0x44, 0x77, 0xAA, 0xDD, 0x00, 0x33, 0x66 },
++		.key	= "\x11\x44\x77\xAA\xDD\x00\x33\x66",
+ 		.klen	= 8,
+-		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 },
++		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input	= "\x12\x34\x56\x78\x9A\xBC\xDE\xF0",
+ 		.ilen	= 8,
+-		.result	= { 0xD8, 0xED, 0x78, 0x74, 0x77, 0xEC, 0x06, 0x80 },
++		.result	= "\xD8\xED\x78\x74\x77\xEC\x06\x80",
+ 		.rlen	= 8,
+ 	}, { /* From Arla */
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ 		.klen	= 8,
+-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.iv	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.input	= "The quick brown fox jumps over the lazy dogs.\0\0",
+ 		.ilen	= 48,
+-		.result	= { 0x00, 0xf0, 0xe,  0x11, 0x75, 0xe6, 0x23, 0x82,
+-			    0xee, 0xac, 0x98, 0x62, 0x44, 0x51, 0xe4, 0x84,
+-			    0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
+-			    0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03,
+-			    0x23, 0xb5, 0x62, 0xd7, 0x0c, 0xf5, 0x27, 0xd1,
+-			    0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef },
++		.result	= "\x00\xf0\x0e\x11\x75\xe6\x23\x82"
++			  "\xee\xac\x98\x62\x44\x51\xe4\x84"
++			  "\xc3\x59\xd8\xaa\x64\x60\xae\xf7"
++			  "\xd2\xd9\x13\x79\x72\xa3\x45\x03"
++			  "\x23\xb5\x62\xd7\x0c\xf5\x27\xd1"
++			  "\xf8\x91\x3c\xac\x44\x22\x92\xef",
+ 		.rlen	= 48,
+ 	}, {
+-		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.key	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.klen	= 8,
+-		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++		.iv	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ 		.input	= "The quick brown fox jumps over the lazy dogs.\0\0",
+ 		.ilen	= 48,
+-		.result	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+-			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+-			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+-			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+-			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+-			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
++		.result	= "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c"
++			  "\x01\x88\x7f\x3e\x31\x6e\x62\x9d"
++			  "\xd8\xe0\x57\xa3\x06\x3a\x42\x58"
++			  "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0"
++			  "\x19\x89\x09\x1c\x2a\x8e\x8c\x94"
++			  "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f",
+ 		.rlen	= 48,
+ 	}, { /* split-page version */
+-		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.key	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.klen	= 8,
+-		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++		.iv	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ 		.input	= "The quick brown fox jumps over the lazy dogs.\0\0",
+ 		.ilen	= 48,
+-		.result	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+-			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+-			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+-			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+-			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+-			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
++		.result	= "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c"
++			  "\x01\x88\x7f\x3e\x31\x6e\x62\x9d"
++			  "\xd8\xe0\x57\xa3\x06\x3a\x42\x58"
++			  "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0"
++			  "\x19\x89\x09\x1c\x2a\x8e\x8c\x94"
++			  "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f",
+ 		.rlen	= 48,
+ 		.np	= 2,
+ 		.tap	= { 20, 28 },
+@@ -6132,57 +6161,57 @@ static struct cipher_testvec fcrypt_pcbc_enc_tv_template[] = {
+ 
+ static struct cipher_testvec fcrypt_pcbc_dec_tv_template[] = {
+ 	{ /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */
+-		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 8,
+-		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input	= { 0x0E, 0x09, 0x00, 0xC7, 0x3E, 0xF7, 0xED, 0x41 },
++		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input	= "\x0E\x09\x00\xC7\x3E\xF7\xED\x41",
+ 		.ilen	= 8,
+-		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.rlen	= 8,
+ 	}, {
+-		.key	= { 0x11, 0x44, 0x77, 0xAA, 0xDD, 0x00, 0x33, 0x66 },
++		.key	= "\x11\x44\x77\xAA\xDD\x00\x33\x66",
+ 		.klen	= 8,
+-		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input	= { 0xD8, 0xED, 0x78, 0x74, 0x77, 0xEC, 0x06, 0x80 },
++		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input	= "\xD8\xED\x78\x74\x77\xEC\x06\x80",
+ 		.ilen	= 8,
+-		.result	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 },
++		.result	= "\x12\x34\x56\x78\x9A\xBC\xDE\xF0",
+ 		.rlen	= 8,
+ 	}, { /* From Arla */
+-		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++		.key	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ 		.klen	= 8,
+-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+-		.input	= { 0x00, 0xf0, 0xe,  0x11, 0x75, 0xe6, 0x23, 0x82,
+-			    0xee, 0xac, 0x98, 0x62, 0x44, 0x51, 0xe4, 0x84,
+-			    0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
+-			    0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03,
+-			    0x23, 0xb5, 0x62, 0xd7, 0x0c, 0xf5, 0x27, 0xd1,
+-			    0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef },
++		.iv	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++		.input	= "\x00\xf0\x0e\x11\x75\xe6\x23\x82"
++			  "\xee\xac\x98\x62\x44\x51\xe4\x84"
++			  "\xc3\x59\xd8\xaa\x64\x60\xae\xf7"
++			  "\xd2\xd9\x13\x79\x72\xa3\x45\x03"
++			  "\x23\xb5\x62\xd7\x0c\xf5\x27\xd1"
++			  "\xf8\x91\x3c\xac\x44\x22\x92\xef",
+ 		.ilen	= 48,
+ 		.result	= "The quick brown fox jumps over the lazy dogs.\0\0",
+ 		.rlen	= 48,
+ 	}, {
+-		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.key	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.klen	= 8,
+-		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+-		.input	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+-			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+-			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+-			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+-			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+-			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
++		.iv	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
++		.input	= "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c"
++			  "\x01\x88\x7f\x3e\x31\x6e\x62\x9d"
++			  "\xd8\xe0\x57\xa3\x06\x3a\x42\x58"
++			  "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0"
++			  "\x19\x89\x09\x1c\x2a\x8e\x8c\x94"
++			  "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f",
+ 		.ilen	= 48,
+ 		.result	= "The quick brown fox jumps over the lazy dogs.\0\0",
+ 		.rlen	= 48,
+ 	}, { /* split-page version */
+-		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.key	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.klen	= 8,
+-		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+-		.input	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+-			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+-			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+-			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+-			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+-			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
++		.iv	= "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
++		.input	= "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c"
++			  "\x01\x88\x7f\x3e\x31\x6e\x62\x9d"
++			  "\xd8\xe0\x57\xa3\x06\x3a\x42\x58"
++			  "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0"
++			  "\x19\x89\x09\x1c\x2a\x8e\x8c\x94"
++			  "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f",
+ 		.ilen	= 48,
+ 		.result	= "The quick brown fox jumps over the lazy dogs.\0\0",
+ 		.rlen	= 48,
+@@ -6201,136 +6230,136 @@ static struct cipher_testvec fcrypt_pcbc_dec_tv_template[] = {
+ 
+ static struct cipher_testvec camellia_enc_tv_template[] = {
+ 	{
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.klen	= 16,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.ilen	= 16,
+-		.result	= { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+-			    0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
++		.result	= "\x67\x67\x31\x38\x54\x96\x69\x73"
++			  "\x08\x57\x06\x56\x48\xea\xbe\x43",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77",
+ 		.klen	= 24,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.ilen	= 16,
+-		.result	= { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+-			    0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
++		.result	= "\xb4\x99\x34\x01\xb3\xe9\x96\xf8"
++			  "\x4e\xe5\xce\xe7\xd7\x9b\x09\xb9",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.klen	= 32,
+-		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.ilen	= 16,
+-		.result	= { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+-			    0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
++		.result	= "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c"
++			  "\x20\xef\x7c\x91\x9e\x3a\x75\x09",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec camellia_dec_tv_template[] = {
+ 	{
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.klen	= 16,
+-		.input	= { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+-			    0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
++		.input	= "\x67\x67\x31\x38\x54\x96\x69\x73"
++			  "\x08\x57\x06\x56\x48\xea\xbe\x43",
+ 		.ilen	= 16,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77",
+ 		.klen	= 24,
+-		.input	= { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+-			    0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
++		.input	= "\xb4\x99\x34\x01\xb3\xe9\x96\xf8"
++			  "\x4e\xe5\xce\xe7\xd7\x9b\x09\xb9",
+ 		.ilen	= 16,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+-			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++			  "\x00\x11\x22\x33\x44\x55\x66\x77"
++			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ 		.klen	= 32,
+-		.input	= { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+-			    0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
++		.input	= "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c"
++			  "\x20\xef\x7c\x91\x9e\x3a\x75\x09",
+ 		.ilen	= 16,
+-		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+-			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
++			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ 		.rlen	= 16,
+ 	},
+ };
+ 
+ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
+ 	{
+-		.key    = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+-			    0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
++		.key    = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
++			  "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ 		.klen   = 16,
+-		.iv	= { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+-			    0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+-		.input	= { "Single block msg" },
++		.iv	= "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
++			  "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
++		.input	= "Single block msg",
+ 		.ilen   = 16,
+-		.result = { 0xea, 0x32, 0x12, 0x76, 0x3b, 0x50, 0x10, 0xe7,
+-			    0x18, 0xf6, 0xfd, 0x5d, 0xf6, 0x8f, 0x13, 0x51 },
++		.result = "\xea\x32\x12\x76\x3b\x50\x10\xe7"
++			  "\x18\xf6\xfd\x5d\xf6\x8f\x13\x51",
+ 		.rlen   = 16,
+ 	}, {
+-		.key    = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+-			    0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
++		.key    = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
++			  "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
+ 		.klen   = 16,
+-		.iv     = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+-			    0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+-		.input  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.iv     = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
++			  "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
++		.input  = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.ilen   = 32,
+-		.result = { 0xa5, 0xdf, 0x6e, 0x50, 0xda, 0x70, 0x6c, 0x01,
+-			    0x4a, 0xab, 0xf3, 0xf2, 0xd6, 0xfc, 0x6c, 0xfd,
+-			    0x19, 0xb4, 0x3e, 0x57, 0x1c, 0x02, 0x5e, 0xa0,
+-			    0x15, 0x78, 0xe0, 0x5e, 0xf2, 0xcb, 0x87, 0x16 },
++		.result = "\xa5\xdf\x6e\x50\xda\x70\x6c\x01"
++			  "\x4a\xab\xf3\xf2\xd6\xfc\x6c\xfd"
++			  "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0"
++			  "\x15\x78\xe0\x5e\xf2\xcb\x87\x16",
+ 		.rlen   = 32,
+ 	},
+ };
+ 
+ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
+ 	{
+-		.key    = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+-			    0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
++		.key    = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
++			  "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ 		.klen   = 16,
+-		.iv	= { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+-			    0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+-		.input	= { 0xea, 0x32, 0x12, 0x76, 0x3b, 0x50, 0x10, 0xe7,
+-			    0x18, 0xf6, 0xfd, 0x5d, 0xf6, 0x8f, 0x13, 0x51 },
++		.iv	= "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
++			  "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
++		.input	= "\xea\x32\x12\x76\x3b\x50\x10\xe7"
++			  "\x18\xf6\xfd\x5d\xf6\x8f\x13\x51",
+ 		.ilen   = 16,
+-		.result = { "Single block msg" },
++		.result = "Single block msg",
+ 		.rlen   = 16,
+ 	}, {
+-		.key    = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+-			    0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
++		.key    = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
++			  "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
+ 		.klen   = 16,
+-		.iv     = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+-			    0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+-		.input = { 0xa5, 0xdf, 0x6e, 0x50, 0xda, 0x70, 0x6c, 0x01,
+-			    0x4a, 0xab, 0xf3, 0xf2, 0xd6, 0xfc, 0x6c, 0xfd,
+-			    0x19, 0xb4, 0x3e, 0x57, 0x1c, 0x02, 0x5e, 0xa0,
+-			    0x15, 0x78, 0xe0, 0x5e, 0xf2, 0xcb, 0x87, 0x16 },
++		.iv     = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
++			  "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
++		.input = "\xa5\xdf\x6e\x50\xda\x70\x6c\x01"
++			  "\x4a\xab\xf3\xf2\xd6\xfc\x6c\xfd"
++			  "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0"
++			  "\x15\x78\xe0\x5e\xf2\xcb\x87\x16",
+ 		.ilen   = 32,
+-		.result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			  "\x10\x11\x12\x13\x14\x15\x16\x17"
++			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.rlen   = 32,
+ 	},
+ };
+@@ -6343,84 +6372,84 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
+ 
+ static struct cipher_testvec seed_enc_tv_template[] = {
+ 	{
+-		.key    = { [0 ... 15] = 0x00 },
++		.key    = zeroed_string,
+ 		.klen	= 16,
+-		.input  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.input  = "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.ilen	= 16,
+-		.result	= { 0x5e, 0xba, 0xc6, 0xe0, 0x05, 0x4e, 0x16, 0x68,
+-			    0x19, 0xaf, 0xf1, 0xcc, 0x6d, 0x34, 0x6c, 0xdb },
++		.result	= "\x5e\xba\xc6\xe0\x05\x4e\x16\x68"
++			  "\x19\xaf\xf1\xcc\x6d\x34\x6c\xdb",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.klen	= 16,
+-		.input	= { [0 ... 15] = 0x00 },
++		.input	= zeroed_string,
+ 		.ilen	= 16,
+-		.result	= { 0xc1, 0x1f, 0x22, 0xf2, 0x01, 0x40, 0x50, 0x50,
+-			    0x84, 0x48, 0x35, 0x97, 0xe4, 0x37, 0x0f, 0x43 },
++		.result	= "\xc1\x1f\x22\xf2\x01\x40\x50\x50"
++			  "\x84\x48\x35\x97\xe4\x37\x0f\x43",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x47, 0x06, 0x48, 0x08, 0x51, 0xe6, 0x1b, 0xe8,
+-			    0x5d, 0x74, 0xbf, 0xb3, 0xfd, 0x95, 0x61, 0x85 },
++		.key	= "\x47\x06\x48\x08\x51\xe6\x1b\xe8"
++			  "\x5d\x74\xbf\xb3\xfd\x95\x61\x85",
+ 		.klen	= 16,
+-		.input	= { 0x83, 0xa2, 0xf8, 0xa2, 0x88, 0x64, 0x1f, 0xb9,
+-			    0xa4, 0xe9, 0xa5, 0xcc, 0x2f, 0x13, 0x1c, 0x7d },
++		.input	= "\x83\xa2\xf8\xa2\x88\x64\x1f\xb9"
++			  "\xa4\xe9\xa5\xcc\x2f\x13\x1c\x7d",
+ 		.ilen	= 16,
+-		.result	= { 0xee, 0x54, 0xd1, 0x3e, 0xbc, 0xae, 0x70, 0x6d,
+-			    0x22, 0x6b, 0xc3, 0x14, 0x2c, 0xd4, 0x0d, 0x4a },
++		.result	= "\xee\x54\xd1\x3e\xbc\xae\x70\x6d"
++			  "\x22\x6b\xc3\x14\x2c\xd4\x0d\x4a",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x28, 0xdb, 0xc3, 0xbc, 0x49, 0xff, 0xd8, 0x7d,
+-			    0xcf, 0xa5, 0x09, 0xb1, 0x1d, 0x42, 0x2b, 0xe7 },
++		.key	= "\x28\xdb\xc3\xbc\x49\xff\xd8\x7d"
++			  "\xcf\xa5\x09\xb1\x1d\x42\x2b\xe7",
+ 		.klen	= 16,
+-		.input	= { 0xb4, 0x1e, 0x6b, 0xe2, 0xeb, 0xa8, 0x4a, 0x14,
+-			    0x8e, 0x2e, 0xed, 0x84, 0x59, 0x3c, 0x5e, 0xc7 },
++		.input	= "\xb4\x1e\x6b\xe2\xeb\xa8\x4a\x14"
++			  "\x8e\x2e\xed\x84\x59\x3c\x5e\xc7",
+ 		.ilen	= 16,
+-		.result	= { 0x9b, 0x9b, 0x7b, 0xfc, 0xd1, 0x81, 0x3c, 0xb9,
+-			    0x5d, 0x0b, 0x36, 0x18, 0xf4, 0x0f, 0x51, 0x22 },
++		.result	= "\x9b\x9b\x7b\xfc\xd1\x81\x3c\xb9"
++			  "\x5d\x0b\x36\x18\xf4\x0f\x51\x22",
+ 		.rlen	= 16,
+ 	}
+ };
+ 
+ static struct cipher_testvec seed_dec_tv_template[] = {
+ 	{
+-		.key    = { [0 ... 15] = 0x00 },
++		.key    = zeroed_string,
+ 		.klen	= 16,
+-		.input	= { 0x5e, 0xba, 0xc6, 0xe0, 0x05, 0x4e, 0x16, 0x68,
+-			    0x19, 0xaf, 0xf1, 0xcc, 0x6d, 0x34, 0x6c, 0xdb },
++		.input	= "\x5e\xba\xc6\xe0\x05\x4e\x16\x68"
++			  "\x19\xaf\xf1\xcc\x6d\x34\x6c\xdb",
+ 		.ilen	= 16,
+-		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ 		.klen	= 16,
+-		.input	= { 0xc1, 0x1f, 0x22, 0xf2, 0x01, 0x40, 0x50, 0x50,
+-			    0x84, 0x48, 0x35, 0x97, 0xe4, 0x37, 0x0f, 0x43 },
++		.input	= "\xc1\x1f\x22\xf2\x01\x40\x50\x50"
++			  "\x84\x48\x35\x97\xe4\x37\x0f\x43",
+ 		.ilen	= 16,
+-		.result	= { [0 ... 15] = 0x00 },
++		.result	= zeroed_string,
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x47, 0x06, 0x48, 0x08, 0x51, 0xe6, 0x1b, 0xe8,
+-			    0x5d, 0x74, 0xbf, 0xb3, 0xfd, 0x95, 0x61, 0x85 },
++		.key	= "\x47\x06\x48\x08\x51\xe6\x1b\xe8"
++			  "\x5d\x74\xbf\xb3\xfd\x95\x61\x85",
+ 		.klen	= 16,
+-		.input	= { 0xee, 0x54, 0xd1, 0x3e, 0xbc, 0xae, 0x70, 0x6d,
+-			    0x22, 0x6b, 0xc3, 0x14, 0x2c, 0xd4, 0x0d, 0x4a },
++		.input	= "\xee\x54\xd1\x3e\xbc\xae\x70\x6d"
++			  "\x22\x6b\xc3\x14\x2c\xd4\x0d\x4a",
+ 		.ilen	= 16,
+-		.result	= { 0x83, 0xa2, 0xf8, 0xa2, 0x88, 0x64, 0x1f, 0xb9,
+-			    0xa4, 0xe9, 0xa5, 0xcc, 0x2f, 0x13, 0x1c, 0x7d },
++		.result	= "\x83\xa2\xf8\xa2\x88\x64\x1f\xb9"
++			  "\xa4\xe9\xa5\xcc\x2f\x13\x1c\x7d",
+ 		.rlen	= 16,
+ 	}, {
+-		.key	= { 0x28, 0xdb, 0xc3, 0xbc, 0x49, 0xff, 0xd8, 0x7d,
+-			    0xcf, 0xa5, 0x09, 0xb1, 0x1d, 0x42, 0x2b, 0xe7 },
++		.key	= "\x28\xdb\xc3\xbc\x49\xff\xd8\x7d"
++			  "\xcf\xa5\x09\xb1\x1d\x42\x2b\xe7",
+ 		.klen	= 16,
+-		.input	= { 0x9b, 0x9b, 0x7b, 0xfc, 0xd1, 0x81, 0x3c, 0xb9,
+-			    0x5d, 0x0b, 0x36, 0x18, 0xf4, 0x0f, 0x51, 0x22 },
++		.input	= "\x9b\x9b\x7b\xfc\xd1\x81\x3c\xb9"
++			  "\x5d\x0b\x36\x18\xf4\x0f\x51\x22",
+ 		.ilen	= 16,
+-		.result	= { 0xb4, 0x1e, 0x6b, 0xe2, 0xeb, 0xa8, 0x4a, 0x14,
+-			    0x8e, 0x2e, 0xed, 0x84, 0x59, 0x3c, 0x5e, 0xc7 },
++		.result	= "\xb4\x1e\x6b\xe2\xeb\xa8\x4a\x14"
++			  "\x8e\x2e\xed\x84\x59\x3c\x5e\xc7",
+ 		.rlen	= 16,
+ 	}
+ };
+@@ -6433,1204 +6462,1376 @@ static struct cipher_testvec salsa20_stream_enc_tv_template[] = {
+ 	* of input length.
+ 	*/
+ 	{ /* Set 3, vector 0 */
+-		.key	= {
+-			    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+-			  },
++		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
++			"\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+ 		.klen	= 16,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input	= {
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			  },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 39,
+-		.result	= {
+-			    0x2D, 0xD5, 0xC3, 0xF7, 0xBA, 0x2B, 0x20, 0xF7,
+-                            0x68, 0x02, 0x41, 0x0C, 0x68, 0x86, 0x88, 0x89,
+-                            0x5A, 0xD8, 0xC1, 0xBD, 0x4E, 0xA6, 0xC9, 0xB1,
+-                            0x40, 0xFB, 0x9B, 0x90, 0xE2, 0x10, 0x49, 0xBF,
+-                            0x58, 0x3F, 0x52, 0x79, 0x70, 0xEB, 0xC1,
+-			},
++		.result	= "\x2D\xD5\xC3\xF7\xBA\x2B\x20\xF7"
++			 "\x68\x02\x41\x0C\x68\x86\x88\x89"
++			 "\x5A\xD8\xC1\xBD\x4E\xA6\xC9\xB1"
++			 "\x40\xFB\x9B\x90\xE2\x10\x49\xBF"
++			 "\x58\x3F\x52\x79\x70\xEB\xC1",
+ 		.rlen	= 39,
+ 	}, { /* Set 5, vector 0 */
+-		.key	= {
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+-			  },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 16,
+-		.iv     = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input	= {
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			  },
++		.iv     = "\x80\x00\x00\x00\x00\x00\x00\x00",
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 64,
+-		.result	= {
+-			    0xB6, 0x6C, 0x1E, 0x44, 0x46, 0xDD, 0x95, 0x57,
+-                            0xE5, 0x78, 0xE2, 0x23, 0xB0, 0xB7, 0x68, 0x01,
+-                            0x7B, 0x23, 0xB2, 0x67, 0xBB, 0x02, 0x34, 0xAE,
+-                            0x46, 0x26, 0xBF, 0x44, 0x3F, 0x21, 0x97, 0x76,
+-                            0x43, 0x6F, 0xB1, 0x9F, 0xD0, 0xE8, 0x86, 0x6F,
+-                            0xCD, 0x0D, 0xE9, 0xA9, 0x53, 0x8F, 0x4A, 0x09,
+-                            0xCA, 0x9A, 0xC0, 0x73, 0x2E, 0x30, 0xBC, 0xF9,
+-                            0x8E, 0x4F, 0x13, 0xE4, 0xB9, 0xE2, 0x01, 0xD9,
+-			  },
++		.result	= "\xB6\x6C\x1E\x44\x46\xDD\x95\x57"
++			 "\xE5\x78\xE2\x23\xB0\xB7\x68\x01"
++			 "\x7B\x23\xB2\x67\xBB\x02\x34\xAE"
++			 "\x46\x26\xBF\x44\x3F\x21\x97\x76"
++			 "\x43\x6F\xB1\x9F\xD0\xE8\x86\x6F"
++			 "\xCD\x0D\xE9\xA9\x53\x8F\x4A\x09"
++			 "\xCA\x9A\xC0\x73\x2E\x30\xBC\xF9"
++			 "\x8E\x4F\x13\xE4\xB9\xE2\x01\xD9",
+ 		.rlen	= 64,
+ 	}, { /* Set 3, vector 27 */
+-		.key	= {
+-			    0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,
+-			    0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
+-                            0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
+-			    0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+-			  },
++		.key	= "\x1B\x1C\x1D\x1E\x1F\x20\x21\x22"
++			"\x23\x24\x25\x26\x27\x28\x29\x2A"
++			"\x2B\x2C\x2D\x2E\x2F\x30\x31\x32"
++			"\x33\x34\x35\x36\x37\x38\x39\x3A",
+ 		.klen	= 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+-		.input	= {
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			  },
++		.iv     = "\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00",
+ 		.ilen	= 111,
+-		.result	= {
+-			    0xAE, 0x39, 0x50, 0x8E, 0xAC, 0x9A, 0xEC, 0xE7,
+-                            0xBF, 0x97, 0xBB, 0x20, 0xB9, 0xDE, 0xE4, 0x1F,
+-                            0x87, 0xD9, 0x47, 0xF8, 0x28, 0x91, 0x35, 0x98,
+-                            0xDB, 0x72, 0xCC, 0x23, 0x29, 0x48, 0x56, 0x5E,
+-                            0x83, 0x7E, 0x0B, 0xF3, 0x7D, 0x5D, 0x38, 0x7B,
+-                            0x2D, 0x71, 0x02, 0xB4, 0x3B, 0xB5, 0xD8, 0x23,
+-                            0xB0, 0x4A, 0xDF, 0x3C, 0xEC, 0xB6, 0xD9, 0x3B,
+-                            0x9B, 0xA7, 0x52, 0xBE, 0xC5, 0xD4, 0x50, 0x59,
+-
+-                            0x15, 0x14, 0xB4, 0x0E, 0x40, 0xE6, 0x53, 0xD1,
+-                            0x83, 0x9C, 0x5B, 0xA0, 0x92, 0x29, 0x6B, 0x5E,
+-                            0x96, 0x5B, 0x1E, 0x2F, 0xD3, 0xAC, 0xC1, 0x92,
+-                            0xB1, 0x41, 0x3F, 0x19, 0x2F, 0xC4, 0x3B, 0xC6,
+-                            0x95, 0x46, 0x45, 0x54, 0xE9, 0x75, 0x03, 0x08,
+-                            0x44, 0xAF, 0xE5, 0x8A, 0x81, 0x12, 0x09,
+-			  },
++		.result	= "\xAE\x39\x50\x8E\xAC\x9A\xEC\xE7"
++			 "\xBF\x97\xBB\x20\xB9\xDE\xE4\x1F"
++			 "\x87\xD9\x47\xF8\x28\x91\x35\x98"
++			 "\xDB\x72\xCC\x23\x29\x48\x56\x5E"
++			 "\x83\x7E\x0B\xF3\x7D\x5D\x38\x7B"
++			 "\x2D\x71\x02\xB4\x3B\xB5\xD8\x23"
++			 "\xB0\x4A\xDF\x3C\xEC\xB6\xD9\x3B"
++			 "\x9B\xA7\x52\xBE\xC5\xD4\x50\x59"
++			 "\x15\x14\xB4\x0E\x40\xE6\x53\xD1"
++			 "\x83\x9C\x5B\xA0\x92\x29\x6B\x5E"
++			 "\x96\x5B\x1E\x2F\xD3\xAC\xC1\x92"
++			 "\xB1\x41\x3F\x19\x2F\xC4\x3B\xC6"
++			 "\x95\x46\x45\x54\xE9\x75\x03\x08"
++			 "\x44\xAF\xE5\x8A\x81\x12\x09",
+ 		.rlen	= 111,
+-
+ 	}, { /* Set 5, vector 27 */
+-		.key	= {
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+-			  },
++		.key	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.klen	= 32,
+-		.iv     = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 },
+-		.input	= {
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-
+-			    0x00,
+-			  },
++		.iv     = "\x00\x00\x00\x10\x00\x00\x00\x00",
++		.input	= "\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00",
+ 		.ilen	= 129,
+-		.result	= {
+-			    0xD2, 0xDB, 0x1A, 0x5C, 0xF1, 0xC1, 0xAC, 0xDB,
+-                            0xE8, 0x1A, 0x7A, 0x43, 0x40, 0xEF, 0x53, 0x43,
+-                            0x5E, 0x7F, 0x4B, 0x1A, 0x50, 0x52, 0x3F, 0x8D,
+-                            0x28, 0x3D, 0xCF, 0x85, 0x1D, 0x69, 0x6E, 0x60,
+-                            0xF2, 0xDE, 0x74, 0x56, 0x18, 0x1B, 0x84, 0x10,
+-                            0xD4, 0x62, 0xBA, 0x60, 0x50, 0xF0, 0x61, 0xF2,
+-                            0x1C, 0x78, 0x7F, 0xC1, 0x24, 0x34, 0xAF, 0x58,
+-                            0xBF, 0x2C, 0x59, 0xCA, 0x90, 0x77, 0xF3, 0xB0,
+-
+-                            0x5B, 0x4A, 0xDF, 0x89, 0xCE, 0x2C, 0x2F, 0xFC,
+-                            0x67, 0xF0, 0xE3, 0x45, 0xE8, 0xB3, 0xB3, 0x75,
+-                            0xA0, 0x95, 0x71, 0xA1, 0x29, 0x39, 0x94, 0xCA,
+-                            0x45, 0x2F, 0xBD, 0xCB, 0x10, 0xB6, 0xBE, 0x9F,
+-                            0x8E, 0xF9, 0xB2, 0x01, 0x0A, 0x5A, 0x0A, 0xB7,
+-                            0x6B, 0x9D, 0x70, 0x8E, 0x4B, 0xD6, 0x2F, 0xCD,
+-                            0x2E, 0x40, 0x48, 0x75, 0xE9, 0xE2, 0x21, 0x45,
+-                            0x0B, 0xC9, 0xB6, 0xB5, 0x66, 0xBC, 0x9A, 0x59,
+-
+-                            0x5A,
+-			  },
++		.result	= "\xD2\xDB\x1A\x5C\xF1\xC1\xAC\xDB"
++			 "\xE8\x1A\x7A\x43\x40\xEF\x53\x43"
++			 "\x5E\x7F\x4B\x1A\x50\x52\x3F\x8D"
++			 "\x28\x3D\xCF\x85\x1D\x69\x6E\x60"
++			 "\xF2\xDE\x74\x56\x18\x1B\x84\x10"
++			 "\xD4\x62\xBA\x60\x50\xF0\x61\xF2"
++			 "\x1C\x78\x7F\xC1\x24\x34\xAF\x58"
++			 "\xBF\x2C\x59\xCA\x90\x77\xF3\xB0"
++			 "\x5B\x4A\xDF\x89\xCE\x2C\x2F\xFC"
++			 "\x67\xF0\xE3\x45\xE8\xB3\xB3\x75"
++			 "\xA0\x95\x71\xA1\x29\x39\x94\xCA"
++			 "\x45\x2F\xBD\xCB\x10\xB6\xBE\x9F"
++			 "\x8E\xF9\xB2\x01\x0A\x5A\x0A\xB7"
++			 "\x6B\x9D\x70\x8E\x4B\xD6\x2F\xCD"
++			 "\x2E\x40\x48\x75\xE9\xE2\x21\x45"
++			 "\x0B\xC9\xB6\xB5\x66\xBC\x9A\x59"
++			 "\x5A",
+ 		.rlen	= 129,
+ 	}, { /* large test vector generated using Crypto++ */
+-		.key = {
+-			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-		},
++		.key =  "\x00\x01\x02\x03\x04\x05\x06\x07"
++			"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			"\x10\x11\x12\x13\x14\x15\x16\x17"
++			"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ 		.klen = 32,
+-		.iv = {
+-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-		},
+-		.input = {
+-			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+-			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+-			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+-			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+-			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+-			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+-			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+-			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+-			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+-			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+-			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+-			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+-			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+-			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+-			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+-			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+-			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+-			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+-			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+-			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+-			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+-			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+-			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+-			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+-			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+-			0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+-			0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+-			0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+-			0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+-			0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+-			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+-			0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+-			0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
+-			0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
+-			0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
+-			0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
+-			0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
+-			0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
+-			0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
+-			0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
+-			0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
+-			0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
+-			0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
+-			0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
+-			0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
+-			0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
+-			0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
+-			0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
+-			0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
+-			0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
+-			0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
+-			0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
+-			0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
+-			0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
+-			0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
+-			0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
+-			0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
+-			0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
+-			0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
+-			0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
+-			0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
+-			0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
+-			0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
+-			0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
+-			0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
+-			0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
+-			0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
+-			0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
+-			0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
+-			0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
+-			0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
+-			0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
+-			0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
+-			0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
+-			0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
+-			0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
+-			0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
+-			0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
+-			0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
+-			0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
+-			0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
+-			0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
+-			0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
+-			0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
+-			0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
+-			0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
+-			0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
+-			0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
+-			0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
+-			0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
+-			0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
+-			0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
+-			0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
+-			0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
+-			0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
+-			0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
+-			0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
+-			0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
+-			0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
+-			0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
+-			0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
+-			0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
+-			0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
+-			0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
+-			0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
+-			0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
+-			0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
+-			0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
+-			0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
+-			0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
+-			0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
+-			0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
+-			0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
+-			0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
+-			0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
+-			0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
+-			0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
+-			0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
+-			0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
+-			0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
+-			0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
+-			0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
+-			0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
+-			0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
+-			0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
+-			0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
+-			0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
+-			0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
+-			0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+-			0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
+-			0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
+-			0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
+-			0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
+-			0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
+-			0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
+-			0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
+-			0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
+-			0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
+-			0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
+-			0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
+-			0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
+-			0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
+-			0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
+-			0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
+-			0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
+-			0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
+-			0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
+-			0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
+-			0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
+-			0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
+-			0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
+-			0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
+-			0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
+-			0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
+-			0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
+-			0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
+-			0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
+-			0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
+-			0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
+-			0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
+-			0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
+-			0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
+-			0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
+-			0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
+-			0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
+-			0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
+-			0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
+-			0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
+-			0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
+-			0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
+-			0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
+-			0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
+-			0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
+-			0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
+-			0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
+-			0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
+-			0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
+-			0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
+-			0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
+-			0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
+-			0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
+-			0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
+-			0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
+-			0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
+-			0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
+-			0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
+-			0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
+-			0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
+-			0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
+-			0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
+-			0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
+-			0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
+-			0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
+-			0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
+-			0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
+-			0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
+-			0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
+-			0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
+-			0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
+-			0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
+-			0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
+-			0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
+-			0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
+-			0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
+-			0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
+-			0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
+-			0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
+-			0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
+-			0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
+-			0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
+-			0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
+-			0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
+-			0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
+-			0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
+-			0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
+-			0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
+-			0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
+-			0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
+-			0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
+-			0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
+-			0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
+-			0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
+-			0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
+-			0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
+-			0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
+-			0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
+-			0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
+-			0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
+-			0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
+-			0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
+-			0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
+-			0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
+-			0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
+-			0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
+-			0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
+-			0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
+-			0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
+-			0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
+-			0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
+-			0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
+-			0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
+-			0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
+-			0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
+-			0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
+-			0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
+-			0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
+-			0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
+-			0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
+-			0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
+-			0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
+-			0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
+-			0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
+-			0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
+-			0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
+-			0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
+-			0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
+-			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+-			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+-			0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
+-			0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
+-			0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
+-			0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
+-			0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
+-			0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
+-			0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
+-			0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
+-			0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
+-			0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
+-			0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
+-			0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
+-			0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
+-			0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
+-			0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
+-			0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
+-			0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
+-			0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
+-			0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
+-			0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
+-			0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
+-			0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
+-			0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
+-			0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
+-			0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
+-			0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
+-			0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
+-			0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
+-			0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
+-			0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
+-			0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
+-			0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
+-			0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
+-			0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
+-			0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
+-			0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
+-			0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
+-			0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
+-			0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
+-			0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
+-			0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
+-			0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
+-			0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
+-			0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
+-			0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
+-			0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
+-			0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
+-			0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
+-			0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
+-			0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
+-			0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
+-			0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
+-			0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
+-			0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
+-			0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
+-			0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
+-			0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
+-			0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
+-			0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
+-			0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
+-			0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
+-			0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
+-			0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
+-			0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
+-			0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
+-			0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
+-			0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
+-			0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
+-			0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
+-			0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
+-			0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
+-			0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
+-			0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
+-			0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
+-			0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
+-			0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
+-			0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
+-			0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
+-			0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
+-			0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
+-			0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
+-			0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
+-			0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
+-			0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
+-			0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
+-			0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
+-			0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
+-			0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
+-			0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
+-			0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
+-			0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
+-			0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
+-			0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
+-			0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
+-			0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
+-			0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
+-			0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
+-			0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
+-			0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
+-			0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
+-			0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
+-			0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
+-			0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
+-			0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
+-			0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
+-			0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
+-			0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
+-			0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
+-			0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
+-			0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
+-			0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
+-			0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
+-			0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
+-			0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
+-			0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
+-			0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
+-			0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
+-			0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
+-			0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
+-			0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
+-			0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
+-			0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
+-			0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
+-			0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
+-			0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
+-			0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
+-			0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
+-			0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
+-			0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
+-			0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
+-			0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
+-			0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
+-			0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
+-			0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
+-			0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
+-			0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
+-			0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
+-			0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
+-			0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
+-			0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
+-			0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
+-			0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
+-			0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
+-			0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
+-			0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
+-			0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
+-			0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
+-			0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
+-			0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
+-			0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
+-			0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
+-			0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
+-			0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
+-			0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
+-			0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
+-			0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
+-			0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
+-			0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
+-			0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
+-			0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
+-			0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
+-			0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
+-			0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
+-			0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
+-			0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
+-			0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
+-			0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
+-			0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
+-			0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
+-			0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
+-			0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
+-			0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
+-			0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
+-			0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
+-			0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
+-			0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
+-			0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
+-			0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
+-			0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
+-			0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
+-			0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
+-			0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
+-			0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
+-			0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
+-			0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
+-			0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
+-			0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
+-			0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
+-			0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
+-			0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
+-			0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
+-			0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
+-			0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
+-			0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
+-			0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
+-			0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
+-			0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
+-			0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
+-			0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
+-			0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
+-			0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
+-			0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
+-			0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
+-			0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
+-			0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
+-			0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
+-			0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
+-			0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
+-			0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
+-			0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
+-			0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
+-			0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
+-			0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
+-			0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
+-			0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
+-			0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
+-			0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
+-			0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
+-			0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
+-			0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
+-			0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
+-			0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
+-			0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
+-			0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
+-			0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
+-			0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
+-			0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
+-			0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
+-			0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
+-			0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
+-			0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
+-			0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
+-			0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
+-			0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
+-			0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
+-			0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
+-			0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
+-			0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
+-			0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
+-			0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
+-			0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
+-			0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
+-			0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
+-			0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
+-			0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
+-			0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
+-			0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
+-			0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
+-			0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
+-			0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
+-			0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
+-			0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
+-			0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
+-			0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
+-			0x00, 0x21, 0x42, 0x63,
+-		},
++		.iv =	"\x00\x00\x00\x00\x00\x00\x00\x00"
++			"\x00\x00\x00\x00\x00\x00\x00\x00",
++		.input =
++			"\x00\x01\x02\x03\x04\x05\x06\x07"
++			"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++			"\x10\x11\x12\x13\x14\x15\x16\x17"
++			"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++			"\x20\x21\x22\x23\x24\x25\x26\x27"
++			"\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++			"\x30\x31\x32\x33\x34\x35\x36\x37"
++			"\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++			"\x40\x41\x42\x43\x44\x45\x46\x47"
++			"\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++			"\x50\x51\x52\x53\x54\x55\x56\x57"
++			"\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++			"\x60\x61\x62\x63\x64\x65\x66\x67"
++			"\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++			"\x70\x71\x72\x73\x74\x75\x76\x77"
++			"\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++			"\x80\x81\x82\x83\x84\x85\x86\x87"
++			"\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++			"\x90\x91\x92\x93\x94\x95\x96\x97"
++			"\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++			"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++			"\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++			"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++			"\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++			"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++			"\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++			"\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++			"\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++			"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++			"\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++			"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++			"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
++			"\x00\x03\x06\x09\x0c\x0f\x12\x15"
++			"\x18\x1b\x1e\x21\x24\x27\x2a\x2d"
++			"\x30\x33\x36\x39\x3c\x3f\x42\x45"
++			"\x48\x4b\x4e\x51\x54\x57\x5a\x5d"
++			"\x60\x63\x66\x69\x6c\x6f\x72\x75"
++			"\x78\x7b\x7e\x81\x84\x87\x8a\x8d"
++			"\x90\x93\x96\x99\x9c\x9f\xa2\xa5"
++			"\xa8\xab\xae\xb1\xb4\xb7\xba\xbd"
++			"\xc0\xc3\xc6\xc9\xcc\xcf\xd2\xd5"
++			"\xd8\xdb\xde\xe1\xe4\xe7\xea\xed"
++			"\xf0\xf3\xf6\xf9\xfc\xff\x02\x05"
++			"\x08\x0b\x0e\x11\x14\x17\x1a\x1d"
++			"\x20\x23\x26\x29\x2c\x2f\x32\x35"
++			"\x38\x3b\x3e\x41\x44\x47\x4a\x4d"
++			"\x50\x53\x56\x59\x5c\x5f\x62\x65"
++			"\x68\x6b\x6e\x71\x74\x77\x7a\x7d"
++			"\x80\x83\x86\x89\x8c\x8f\x92\x95"
++			"\x98\x9b\x9e\xa1\xa4\xa7\xaa\xad"
++			"\xb0\xb3\xb6\xb9\xbc\xbf\xc2\xc5"
++			"\xc8\xcb\xce\xd1\xd4\xd7\xda\xdd"
++			"\xe0\xe3\xe6\xe9\xec\xef\xf2\xf5"
++			"\xf8\xfb\xfe\x01\x04\x07\x0a\x0d"
++			"\x10\x13\x16\x19\x1c\x1f\x22\x25"
++			"\x28\x2b\x2e\x31\x34\x37\x3a\x3d"
++			"\x40\x43\x46\x49\x4c\x4f\x52\x55"
++			"\x58\x5b\x5e\x61\x64\x67\x6a\x6d"
++			"\x70\x73\x76\x79\x7c\x7f\x82\x85"
++			"\x88\x8b\x8e\x91\x94\x97\x9a\x9d"
++			"\xa0\xa3\xa6\xa9\xac\xaf\xb2\xb5"
++			"\xb8\xbb\xbe\xc1\xc4\xc7\xca\xcd"
++			"\xd0\xd3\xd6\xd9\xdc\xdf\xe2\xe5"
++			"\xe8\xeb\xee\xf1\xf4\xf7\xfa\xfd"
++			"\x00\x05\x0a\x0f\x14\x19\x1e\x23"
++			"\x28\x2d\x32\x37\x3c\x41\x46\x4b"
++			"\x50\x55\x5a\x5f\x64\x69\x6e\x73"
++			"\x78\x7d\x82\x87\x8c\x91\x96\x9b"
++			"\xa0\xa5\xaa\xaf\xb4\xb9\xbe\xc3"
++			"\xc8\xcd\xd2\xd7\xdc\xe1\xe6\xeb"
++			"\xf0\xf5\xfa\xff\x04\x09\x0e\x13"
++			"\x18\x1d\x22\x27\x2c\x31\x36\x3b"
++			"\x40\x45\x4a\x4f\x54\x59\x5e\x63"
++			"\x68\x6d\x72\x77\x7c\x81\x86\x8b"
++			"\x90\x95\x9a\x9f\xa4\xa9\xae\xb3"
++			"\xb8\xbd\xc2\xc7\xcc\xd1\xd6\xdb"
++			"\xe0\xe5\xea\xef\xf4\xf9\xfe\x03"
++			"\x08\x0d\x12\x17\x1c\x21\x26\x2b"
++			"\x30\x35\x3a\x3f\x44\x49\x4e\x53"
++			"\x58\x5d\x62\x67\x6c\x71\x76\x7b"
++			"\x80\x85\x8a\x8f\x94\x99\x9e\xa3"
++			"\xa8\xad\xb2\xb7\xbc\xc1\xc6\xcb"
++			"\xd0\xd5\xda\xdf\xe4\xe9\xee\xf3"
++			"\xf8\xfd\x02\x07\x0c\x11\x16\x1b"
++			"\x20\x25\x2a\x2f\x34\x39\x3e\x43"
++			"\x48\x4d\x52\x57\x5c\x61\x66\x6b"
++			"\x70\x75\x7a\x7f\x84\x89\x8e\x93"
++			"\x98\x9d\xa2\xa7\xac\xb1\xb6\xbb"
++			"\xc0\xc5\xca\xcf\xd4\xd9\xde\xe3"
++			"\xe8\xed\xf2\xf7\xfc\x01\x06\x0b"
++			"\x10\x15\x1a\x1f\x24\x29\x2e\x33"
++			"\x38\x3d\x42\x47\x4c\x51\x56\x5b"
++			"\x60\x65\x6a\x6f\x74\x79\x7e\x83"
++			"\x88\x8d\x92\x97\x9c\xa1\xa6\xab"
++			"\xb0\xb5\xba\xbf\xc4\xc9\xce\xd3"
++			"\xd8\xdd\xe2\xe7\xec\xf1\xf6\xfb"
++			"\x00\x07\x0e\x15\x1c\x23\x2a\x31"
++			"\x38\x3f\x46\x4d\x54\x5b\x62\x69"
++			"\x70\x77\x7e\x85\x8c\x93\x9a\xa1"
++			"\xa8\xaf\xb6\xbd\xc4\xcb\xd2\xd9"
++			"\xe0\xe7\xee\xf5\xfc\x03\x0a\x11"
++			"\x18\x1f\x26\x2d\x34\x3b\x42\x49"
++			"\x50\x57\x5e\x65\x6c\x73\x7a\x81"
++			"\x88\x8f\x96\x9d\xa4\xab\xb2\xb9"
++			"\xc0\xc7\xce\xd5\xdc\xe3\xea\xf1"
++			"\xf8\xff\x06\x0d\x14\x1b\x22\x29"
++			"\x30\x37\x3e\x45\x4c\x53\x5a\x61"
++			"\x68\x6f\x76\x7d\x84\x8b\x92\x99"
++			"\xa0\xa7\xae\xb5\xbc\xc3\xca\xd1"
++			"\xd8\xdf\xe6\xed\xf4\xfb\x02\x09"
++			"\x10\x17\x1e\x25\x2c\x33\x3a\x41"
++			"\x48\x4f\x56\x5d\x64\x6b\x72\x79"
++			"\x80\x87\x8e\x95\x9c\xa3\xaa\xb1"
++			"\xb8\xbf\xc6\xcd\xd4\xdb\xe2\xe9"
++			"\xf0\xf7\xfe\x05\x0c\x13\x1a\x21"
++			"\x28\x2f\x36\x3d\x44\x4b\x52\x59"
++			"\x60\x67\x6e\x75\x7c\x83\x8a\x91"
++			"\x98\x9f\xa6\xad\xb4\xbb\xc2\xc9"
++			"\xd0\xd7\xde\xe5\xec\xf3\xfa\x01"
++			"\x08\x0f\x16\x1d\x24\x2b\x32\x39"
++			"\x40\x47\x4e\x55\x5c\x63\x6a\x71"
++			"\x78\x7f\x86\x8d\x94\x9b\xa2\xa9"
++			"\xb0\xb7\xbe\xc5\xcc\xd3\xda\xe1"
++			"\xe8\xef\xf6\xfd\x04\x0b\x12\x19"
++			"\x20\x27\x2e\x35\x3c\x43\x4a\x51"
++			"\x58\x5f\x66\x6d\x74\x7b\x82\x89"
++			"\x90\x97\x9e\xa5\xac\xb3\xba\xc1"
++			"\xc8\xcf\xd6\xdd\xe4\xeb\xf2\xf9"
++			"\x00\x09\x12\x1b\x24\x2d\x36\x3f"
++			"\x48\x51\x5a\x63\x6c\x75\x7e\x87"
++			"\x90\x99\xa2\xab\xb4\xbd\xc6\xcf"
++			"\xd8\xe1\xea\xf3\xfc\x05\x0e\x17"
++			"\x20\x29\x32\x3b\x44\x4d\x56\x5f"
++			"\x68\x71\x7a\x83\x8c\x95\x9e\xa7"
++			"\xb0\xb9\xc2\xcb\xd4\xdd\xe6\xef"
++			"\xf8\x01\x0a\x13\x1c\x25\x2e\x37"
++			"\x40\x49\x52\x5b\x64\x6d\x76\x7f"
++			"\x88\x91\x9a\xa3\xac\xb5\xbe\xc7"
++			"\xd0\xd9\xe2\xeb\xf4\xfd\x06\x0f"
++			"\x18\x21\x2a\x33\x3c\x45\x4e\x57"
++			"\x60\x69\x72\x7b\x84\x8d\x96\x9f"
++			"\xa8\xb1\xba\xc3\xcc\xd5\xde\xe7"
++			"\xf0\xf9\x02\x0b\x14\x1d\x26\x2f"
++			"\x38\x41\x4a\x53\x5c\x65\x6e\x77"
++			"\x80\x89\x92\x9b\xa4\xad\xb6\xbf"
++			"\xc8\xd1\xda\xe3\xec\xf5\xfe\x07"
++			"\x10\x19\x22\x2b\x34\x3d\x46\x4f"
++			"\x58\x61\x6a\x73\x7c\x85\x8e\x97"
++			"\xa0\xa9\xb2\xbb\xc4\xcd\xd6\xdf"
++			"\xe8\xf1\xfa\x03\x0c\x15\x1e\x27"
++			"\x30\x39\x42\x4b\x54\x5d\x66\x6f"
++			"\x78\x81\x8a\x93\x9c\xa5\xae\xb7"
++			"\xc0\xc9\xd2\xdb\xe4\xed\xf6\xff"
++			"\x08\x11\x1a\x23\x2c\x35\x3e\x47"
++			"\x50\x59\x62\x6b\x74\x7d\x86\x8f"
++			"\x98\xa1\xaa\xb3\xbc\xc5\xce\xd7"
++			"\xe0\xe9\xf2\xfb\x04\x0d\x16\x1f"
++			"\x28\x31\x3a\x43\x4c\x55\x5e\x67"
++			"\x70\x79\x82\x8b\x94\x9d\xa6\xaf"
++			"\xb8\xc1\xca\xd3\xdc\xe5\xee\xf7"
++			"\x00\x0b\x16\x21\x2c\x37\x42\x4d"
++			"\x58\x63\x6e\x79\x84\x8f\x9a\xa5"
++			"\xb0\xbb\xc6\xd1\xdc\xe7\xf2\xfd"
++			"\x08\x13\x1e\x29\x34\x3f\x4a\x55"
++			"\x60\x6b\x76\x81\x8c\x97\xa2\xad"
++			"\xb8\xc3\xce\xd9\xe4\xef\xfa\x05"
++			"\x10\x1b\x26\x31\x3c\x47\x52\x5d"
++			"\x68\x73\x7e\x89\x94\x9f\xaa\xb5"
++			"\xc0\xcb\xd6\xe1\xec\xf7\x02\x0d"
++			"\x18\x23\x2e\x39\x44\x4f\x5a\x65"
++			"\x70\x7b\x86\x91\x9c\xa7\xb2\xbd"
++			"\xc8\xd3\xde\xe9\xf4\xff\x0a\x15"
++			"\x20\x2b\x36\x41\x4c\x57\x62\x6d"
++			"\x78\x83\x8e\x99\xa4\xaf\xba\xc5"
++			"\xd0\xdb\xe6\xf1\xfc\x07\x12\x1d"
++			"\x28\x33\x3e\x49\x54\x5f\x6a\x75"
++			"\x80\x8b\x96\xa1\xac\xb7\xc2\xcd"
++			"\xd8\xe3\xee\xf9\x04\x0f\x1a\x25"
++			"\x30\x3b\x46\x51\x5c\x67\x72\x7d"
++			"\x88\x93\x9e\xa9\xb4\xbf\xca\xd5"
++			"\xe0\xeb\xf6\x01\x0c\x17\x22\x2d"
++			"\x38\x43\x4e\x59\x64\x6f\x7a\x85"
++			"\x90\x9b\xa6\xb1\xbc\xc7\xd2\xdd"
++			"\xe8\xf3\xfe\x09\x14\x1f\x2a\x35"
++			"\x40\x4b\x56\x61\x6c\x77\x82\x8d"
++			"\x98\xa3\xae\xb9\xc4\xcf\xda\xe5"
++			"\xf0\xfb\x06\x11\x1c\x27\x32\x3d"
++			"\x48\x53\x5e\x69\x74\x7f\x8a\x95"
++			"\xa0\xab\xb6\xc1\xcc\xd7\xe2\xed"
++			"\xf8\x03\x0e\x19\x24\x2f\x3a\x45"
++			"\x50\x5b\x66\x71\x7c\x87\x92\x9d"
++			"\xa8\xb3\xbe\xc9\xd4\xdf\xea\xf5"
++			"\x00\x0d\x1a\x27\x34\x41\x4e\x5b"
++			"\x68\x75\x82\x8f\x9c\xa9\xb6\xc3"
++			"\xd0\xdd\xea\xf7\x04\x11\x1e\x2b"
++			"\x38\x45\x52\x5f\x6c\x79\x86\x93"
++			"\xa0\xad\xba\xc7\xd4\xe1\xee\xfb"
++			"\x08\x15\x22\x2f\x3c\x49\x56\x63"
++			"\x70\x7d\x8a\x97\xa4\xb1\xbe\xcb"
++			"\xd8\xe5\xf2\xff\x0c\x19\x26\x33"
++			"\x40\x4d\x5a\x67\x74\x81\x8e\x9b"
++			"\xa8\xb5\xc2\xcf\xdc\xe9\xf6\x03"
++			"\x10\x1d\x2a\x37\x44\x51\x5e\x6b"
++			"\x78\x85\x92\x9f\xac\xb9\xc6\xd3"
++			"\xe0\xed\xfa\x07\x14\x21\x2e\x3b"
++			"\x48\x55\x62\x6f\x7c\x89\x96\xa3"
++			"\xb0\xbd\xca\xd7\xe4\xf1\xfe\x0b"
++			"\x18\x25\x32\x3f\x4c\x59\x66\x73"
++			"\x80\x8d\x9a\xa7\xb4\xc1\xce\xdb"
++			"\xe8\xf5\x02\x0f\x1c\x29\x36\x43"
++			"\x50\x5d\x6a\x77\x84\x91\x9e\xab"
++			"\xb8\xc5\xd2\xdf\xec\xf9\x06\x13"
++			"\x20\x2d\x3a\x47\x54\x61\x6e\x7b"
++			"\x88\x95\xa2\xaf\xbc\xc9\xd6\xe3"
++			"\xf0\xfd\x0a\x17\x24\x31\x3e\x4b"
++			"\x58\x65\x72\x7f\x8c\x99\xa6\xb3"
++			"\xc0\xcd\xda\xe7\xf4\x01\x0e\x1b"
++			"\x28\x35\x42\x4f\x5c\x69\x76\x83"
++			"\x90\x9d\xaa\xb7\xc4\xd1\xde\xeb"
++			"\xf8\x05\x12\x1f\x2c\x39\x46\x53"
++			"\x60\x6d\x7a\x87\x94\xa1\xae\xbb"
++			"\xc8\xd5\xe2\xef\xfc\x09\x16\x23"
++			"\x30\x3d\x4a\x57\x64\x71\x7e\x8b"
++			"\x98\xa5\xb2\xbf\xcc\xd9\xe6\xf3"
++			"\x00\x0f\x1e\x2d\x3c\x4b\x5a\x69"
++			"\x78\x87\x96\xa5\xb4\xc3\xd2\xe1"
++			"\xf0\xff\x0e\x1d\x2c\x3b\x4a\x59"
++			"\x68\x77\x86\x95\xa4\xb3\xc2\xd1"
++			"\xe0\xef\xfe\x0d\x1c\x2b\x3a\x49"
++			"\x58\x67\x76\x85\x94\xa3\xb2\xc1"
++			"\xd0\xdf\xee\xfd\x0c\x1b\x2a\x39"
++			"\x48\x57\x66\x75\x84\x93\xa2\xb1"
++			"\xc0\xcf\xde\xed\xfc\x0b\x1a\x29"
++			"\x38\x47\x56\x65\x74\x83\x92\xa1"
++			"\xb0\xbf\xce\xdd\xec\xfb\x0a\x19"
++			"\x28\x37\x46\x55\x64\x73\x82\x91"
++			"\xa0\xaf\xbe\xcd\xdc\xeb\xfa\x09"
++			"\x18\x27\x36\x45\x54\x63\x72\x81"
++			"\x90\x9f\xae\xbd\xcc\xdb\xea\xf9"
++			"\x08\x17\x26\x35\x44\x53\x62\x71"
++			"\x80\x8f\x9e\xad\xbc\xcb\xda\xe9"
++			"\xf8\x07\x16\x25\x34\x43\x52\x61"
++			"\x70\x7f\x8e\x9d\xac\xbb\xca\xd9"
++			"\xe8\xf7\x06\x15\x24\x33\x42\x51"
++			"\x60\x6f\x7e\x8d\x9c\xab\xba\xc9"
++			"\xd8\xe7\xf6\x05\x14\x23\x32\x41"
++			"\x50\x5f\x6e\x7d\x8c\x9b\xaa\xb9"
++			"\xc8\xd7\xe6\xf5\x04\x13\x22\x31"
++			"\x40\x4f\x5e\x6d\x7c\x8b\x9a\xa9"
++			"\xb8\xc7\xd6\xe5\xf4\x03\x12\x21"
++			"\x30\x3f\x4e\x5d\x6c\x7b\x8a\x99"
++			"\xa8\xb7\xc6\xd5\xe4\xf3\x02\x11"
++			"\x20\x2f\x3e\x4d\x5c\x6b\x7a\x89"
++			"\x98\xa7\xb6\xc5\xd4\xe3\xf2\x01"
++			"\x10\x1f\x2e\x3d\x4c\x5b\x6a\x79"
++			"\x88\x97\xa6\xb5\xc4\xd3\xe2\xf1"
++			"\x00\x11\x22\x33\x44\x55\x66\x77"
++			"\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
++			"\x10\x21\x32\x43\x54\x65\x76\x87"
++			"\x98\xa9\xba\xcb\xdc\xed\xfe\x0f"
++			"\x20\x31\x42\x53\x64\x75\x86\x97"
++			"\xa8\xb9\xca\xdb\xec\xfd\x0e\x1f"
++			"\x30\x41\x52\x63\x74\x85\x96\xa7"
++			"\xb8\xc9\xda\xeb\xfc\x0d\x1e\x2f"
++			"\x40\x51\x62\x73\x84\x95\xa6\xb7"
++			"\xc8\xd9\xea\xfb\x0c\x1d\x2e\x3f"
++			"\x50\x61\x72\x83\x94\xa5\xb6\xc7"
++			"\xd8\xe9\xfa\x0b\x1c\x2d\x3e\x4f"
++			"\x60\x71\x82\x93\xa4\xb5\xc6\xd7"
++			"\xe8\xf9\x0a\x1b\x2c\x3d\x4e\x5f"
++			"\x70\x81\x92\xa3\xb4\xc5\xd6\xe7"
++			"\xf8\x09\x1a\x2b\x3c\x4d\x5e\x6f"
++			"\x80\x91\xa2\xb3\xc4\xd5\xe6\xf7"
++			"\x08\x19\x2a\x3b\x4c\x5d\x6e\x7f"
++			"\x90\xa1\xb2\xc3\xd4\xe5\xf6\x07"
++			"\x18\x29\x3a\x4b\x5c\x6d\x7e\x8f"
++			"\xa0\xb1\xc2\xd3\xe4\xf5\x06\x17"
++			"\x28\x39\x4a\x5b\x6c\x7d\x8e\x9f"
++			"\xb0\xc1\xd2\xe3\xf4\x05\x16\x27"
++			"\x38\x49\x5a\x6b\x7c\x8d\x9e\xaf"
++			"\xc0\xd1\xe2\xf3\x04\x15\x26\x37"
++			"\x48\x59\x6a\x7b\x8c\x9d\xae\xbf"
++			"\xd0\xe1\xf2\x03\x14\x25\x36\x47"
++			"\x58\x69\x7a\x8b\x9c\xad\xbe\xcf"
++			"\xe0\xf1\x02\x13\x24\x35\x46\x57"
++			"\x68\x79\x8a\x9b\xac\xbd\xce\xdf"
++			"\xf0\x01\x12\x23\x34\x45\x56\x67"
++			"\x78\x89\x9a\xab\xbc\xcd\xde\xef"
++			"\x00\x13\x26\x39\x4c\x5f\x72\x85"
++			"\x98\xab\xbe\xd1\xe4\xf7\x0a\x1d"
++			"\x30\x43\x56\x69\x7c\x8f\xa2\xb5"
++			"\xc8\xdb\xee\x01\x14\x27\x3a\x4d"
++			"\x60\x73\x86\x99\xac\xbf\xd2\xe5"
++			"\xf8\x0b\x1e\x31\x44\x57\x6a\x7d"
++			"\x90\xa3\xb6\xc9\xdc\xef\x02\x15"
++			"\x28\x3b\x4e\x61\x74\x87\x9a\xad"
++			"\xc0\xd3\xe6\xf9\x0c\x1f\x32\x45"
++			"\x58\x6b\x7e\x91\xa4\xb7\xca\xdd"
++			"\xf0\x03\x16\x29\x3c\x4f\x62\x75"
++			"\x88\x9b\xae\xc1\xd4\xe7\xfa\x0d"
++			"\x20\x33\x46\x59\x6c\x7f\x92\xa5"
++			"\xb8\xcb\xde\xf1\x04\x17\x2a\x3d"
++			"\x50\x63\x76\x89\x9c\xaf\xc2\xd5"
++			"\xe8\xfb\x0e\x21\x34\x47\x5a\x6d"
++			"\x80\x93\xa6\xb9\xcc\xdf\xf2\x05"
++			"\x18\x2b\x3e\x51\x64\x77\x8a\x9d"
++			"\xb0\xc3\xd6\xe9\xfc\x0f\x22\x35"
++			"\x48\x5b\x6e\x81\x94\xa7\xba\xcd"
++			"\xe0\xf3\x06\x19\x2c\x3f\x52\x65"
++			"\x78\x8b\x9e\xb1\xc4\xd7\xea\xfd"
++			"\x10\x23\x36\x49\x5c\x6f\x82\x95"
++			"\xa8\xbb\xce\xe1\xf4\x07\x1a\x2d"
++			"\x40\x53\x66\x79\x8c\x9f\xb2\xc5"
++			"\xd8\xeb\xfe\x11\x24\x37\x4a\x5d"
++			"\x70\x83\x96\xa9\xbc\xcf\xe2\xf5"
++			"\x08\x1b\x2e\x41\x54\x67\x7a\x8d"
++			"\xa0\xb3\xc6\xd9\xec\xff\x12\x25"
++			"\x38\x4b\x5e\x71\x84\x97\xaa\xbd"
++			"\xd0\xe3\xf6\x09\x1c\x2f\x42\x55"
++			"\x68\x7b\x8e\xa1\xb4\xc7\xda\xed"
++			"\x00\x15\x2a\x3f\x54\x69\x7e\x93"
++			"\xa8\xbd\xd2\xe7\xfc\x11\x26\x3b"
++			"\x50\x65\x7a\x8f\xa4\xb9\xce\xe3"
++			"\xf8\x0d\x22\x37\x4c\x61\x76\x8b"
++			"\xa0\xb5\xca\xdf\xf4\x09\x1e\x33"
++			"\x48\x5d\x72\x87\x9c\xb1\xc6\xdb"
++			"\xf0\x05\x1a\x2f\x44\x59\x6e\x83"
++			"\x98\xad\xc2\xd7\xec\x01\x16\x2b"
++			"\x40\x55\x6a\x7f\x94\xa9\xbe\xd3"
++			"\xe8\xfd\x12\x27\x3c\x51\x66\x7b"
++			"\x90\xa5\xba\xcf\xe4\xf9\x0e\x23"
++			"\x38\x4d\x62\x77\x8c\xa1\xb6\xcb"
++			"\xe0\xf5\x0a\x1f\x34\x49\x5e\x73"
++			"\x88\x9d\xb2\xc7\xdc\xf1\x06\x1b"
++			"\x30\x45\x5a\x6f\x84\x99\xae\xc3"
++			"\xd8\xed\x02\x17\x2c\x41\x56\x6b"
++			"\x80\x95\xaa\xbf\xd4\xe9\xfe\x13"
++			"\x28\x3d\x52\x67\x7c\x91\xa6\xbb"
++			"\xd0\xe5\xfa\x0f\x24\x39\x4e\x63"
++			"\x78\x8d\xa2\xb7\xcc\xe1\xf6\x0b"
++			"\x20\x35\x4a\x5f\x74\x89\x9e\xb3"
++			"\xc8\xdd\xf2\x07\x1c\x31\x46\x5b"
++			"\x70\x85\x9a\xaf\xc4\xd9\xee\x03"
++			"\x18\x2d\x42\x57\x6c\x81\x96\xab"
++			"\xc0\xd5\xea\xff\x14\x29\x3e\x53"
++			"\x68\x7d\x92\xa7\xbc\xd1\xe6\xfb"
++			"\x10\x25\x3a\x4f\x64\x79\x8e\xa3"
++			"\xb8\xcd\xe2\xf7\x0c\x21\x36\x4b"
++			"\x60\x75\x8a\x9f\xb4\xc9\xde\xf3"
++			"\x08\x1d\x32\x47\x5c\x71\x86\x9b"
++			"\xb0\xc5\xda\xef\x04\x19\x2e\x43"
++			"\x58\x6d\x82\x97\xac\xc1\xd6\xeb"
++			"\x00\x17\x2e\x45\x5c\x73\x8a\xa1"
++			"\xb8\xcf\xe6\xfd\x14\x2b\x42\x59"
++			"\x70\x87\x9e\xb5\xcc\xe3\xfa\x11"
++			"\x28\x3f\x56\x6d\x84\x9b\xb2\xc9"
++			"\xe0\xf7\x0e\x25\x3c\x53\x6a\x81"
++			"\x98\xaf\xc6\xdd\xf4\x0b\x22\x39"
++			"\x50\x67\x7e\x95\xac\xc3\xda\xf1"
++			"\x08\x1f\x36\x4d\x64\x7b\x92\xa9"
++			"\xc0\xd7\xee\x05\x1c\x33\x4a\x61"
++			"\x78\x8f\xa6\xbd\xd4\xeb\x02\x19"
++			"\x30\x47\x5e\x75\x8c\xa3\xba\xd1"
++			"\xe8\xff\x16\x2d\x44\x5b\x72\x89"
++			"\xa0\xb7\xce\xe5\xfc\x13\x2a\x41"
++			"\x58\x6f\x86\x9d\xb4\xcb\xe2\xf9"
++			"\x10\x27\x3e\x55\x6c\x83\x9a\xb1"
++			"\xc8\xdf\xf6\x0d\x24\x3b\x52\x69"
++			"\x80\x97\xae\xc5\xdc\xf3\x0a\x21"
++			"\x38\x4f\x66\x7d\x94\xab\xc2\xd9"
++			"\xf0\x07\x1e\x35\x4c\x63\x7a\x91"
++			"\xa8\xbf\xd6\xed\x04\x1b\x32\x49"
++			"\x60\x77\x8e\xa5\xbc\xd3\xea\x01"
++			"\x18\x2f\x46\x5d\x74\x8b\xa2\xb9"
++			"\xd0\xe7\xfe\x15\x2c\x43\x5a\x71"
++			"\x88\x9f\xb6\xcd\xe4\xfb\x12\x29"
++			"\x40\x57\x6e\x85\x9c\xb3\xca\xe1"
++			"\xf8\x0f\x26\x3d\x54\x6b\x82\x99"
++			"\xb0\xc7\xde\xf5\x0c\x23\x3a\x51"
++			"\x68\x7f\x96\xad\xc4\xdb\xf2\x09"
++			"\x20\x37\x4e\x65\x7c\x93\xaa\xc1"
++			"\xd8\xef\x06\x1d\x34\x4b\x62\x79"
++			"\x90\xa7\xbe\xd5\xec\x03\x1a\x31"
++			"\x48\x5f\x76\x8d\xa4\xbb\xd2\xe9"
++			"\x00\x19\x32\x4b\x64\x7d\x96\xaf"
++			"\xc8\xe1\xfa\x13\x2c\x45\x5e\x77"
++			"\x90\xa9\xc2\xdb\xf4\x0d\x26\x3f"
++			"\x58\x71\x8a\xa3\xbc\xd5\xee\x07"
++			"\x20\x39\x52\x6b\x84\x9d\xb6\xcf"
++			"\xe8\x01\x1a\x33\x4c\x65\x7e\x97"
++			"\xb0\xc9\xe2\xfb\x14\x2d\x46\x5f"
++			"\x78\x91\xaa\xc3\xdc\xf5\x0e\x27"
++			"\x40\x59\x72\x8b\xa4\xbd\xd6\xef"
++			"\x08\x21\x3a\x53\x6c\x85\x9e\xb7"
++			"\xd0\xe9\x02\x1b\x34\x4d\x66\x7f"
++			"\x98\xb1\xca\xe3\xfc\x15\x2e\x47"
++			"\x60\x79\x92\xab\xc4\xdd\xf6\x0f"
++			"\x28\x41\x5a\x73\x8c\xa5\xbe\xd7"
++			"\xf0\x09\x22\x3b\x54\x6d\x86\x9f"
++			"\xb8\xd1\xea\x03\x1c\x35\x4e\x67"
++			"\x80\x99\xb2\xcb\xe4\xfd\x16\x2f"
++			"\x48\x61\x7a\x93\xac\xc5\xde\xf7"
++			"\x10\x29\x42\x5b\x74\x8d\xa6\xbf"
++			"\xd8\xf1\x0a\x23\x3c\x55\x6e\x87"
++			"\xa0\xb9\xd2\xeb\x04\x1d\x36\x4f"
++			"\x68\x81\x9a\xb3\xcc\xe5\xfe\x17"
++			"\x30\x49\x62\x7b\x94\xad\xc6\xdf"
++			"\xf8\x11\x2a\x43\x5c\x75\x8e\xa7"
++			"\xc0\xd9\xf2\x0b\x24\x3d\x56\x6f"
++			"\x88\xa1\xba\xd3\xec\x05\x1e\x37"
++			"\x50\x69\x82\x9b\xb4\xcd\xe6\xff"
++			"\x18\x31\x4a\x63\x7c\x95\xae\xc7"
++			"\xe0\xf9\x12\x2b\x44\x5d\x76\x8f"
++			"\xa8\xc1\xda\xf3\x0c\x25\x3e\x57"
++			"\x70\x89\xa2\xbb\xd4\xed\x06\x1f"
++			"\x38\x51\x6a\x83\x9c\xb5\xce\xe7"
++			"\x00\x1b\x36\x51\x6c\x87\xa2\xbd"
++			"\xd8\xf3\x0e\x29\x44\x5f\x7a\x95"
++			"\xb0\xcb\xe6\x01\x1c\x37\x52\x6d"
++			"\x88\xa3\xbe\xd9\xf4\x0f\x2a\x45"
++			"\x60\x7b\x96\xb1\xcc\xe7\x02\x1d"
++			"\x38\x53\x6e\x89\xa4\xbf\xda\xf5"
++			"\x10\x2b\x46\x61\x7c\x97\xb2\xcd"
++			"\xe8\x03\x1e\x39\x54\x6f\x8a\xa5"
++			"\xc0\xdb\xf6\x11\x2c\x47\x62\x7d"
++			"\x98\xb3\xce\xe9\x04\x1f\x3a\x55"
++			"\x70\x8b\xa6\xc1\xdc\xf7\x12\x2d"
++			"\x48\x63\x7e\x99\xb4\xcf\xea\x05"
++			"\x20\x3b\x56\x71\x8c\xa7\xc2\xdd"
++			"\xf8\x13\x2e\x49\x64\x7f\x9a\xb5"
++			"\xd0\xeb\x06\x21\x3c\x57\x72\x8d"
++			"\xa8\xc3\xde\xf9\x14\x2f\x4a\x65"
++			"\x80\x9b\xb6\xd1\xec\x07\x22\x3d"
++			"\x58\x73\x8e\xa9\xc4\xdf\xfa\x15"
++			"\x30\x4b\x66\x81\x9c\xb7\xd2\xed"
++			"\x08\x23\x3e\x59\x74\x8f\xaa\xc5"
++			"\xe0\xfb\x16\x31\x4c\x67\x82\x9d"
++			"\xb8\xd3\xee\x09\x24\x3f\x5a\x75"
++			"\x90\xab\xc6\xe1\xfc\x17\x32\x4d"
++			"\x68\x83\x9e\xb9\xd4\xef\x0a\x25"
++			"\x40\x5b\x76\x91\xac\xc7\xe2\xfd"
++			"\x18\x33\x4e\x69\x84\x9f\xba\xd5"
++			"\xf0\x0b\x26\x41\x5c\x77\x92\xad"
++			"\xc8\xe3\xfe\x19\x34\x4f\x6a\x85"
++			"\xa0\xbb\xd6\xf1\x0c\x27\x42\x5d"
++			"\x78\x93\xae\xc9\xe4\xff\x1a\x35"
++			"\x50\x6b\x86\xa1\xbc\xd7\xf2\x0d"
++			"\x28\x43\x5e\x79\x94\xaf\xca\xe5"
++			"\x00\x1d\x3a\x57\x74\x91\xae\xcb"
++			"\xe8\x05\x22\x3f\x5c\x79\x96\xb3"
++			"\xd0\xed\x0a\x27\x44\x61\x7e\x9b"
++			"\xb8\xd5\xf2\x0f\x2c\x49\x66\x83"
++			"\xa0\xbd\xda\xf7\x14\x31\x4e\x6b"
++			"\x88\xa5\xc2\xdf\xfc\x19\x36\x53"
++			"\x70\x8d\xaa\xc7\xe4\x01\x1e\x3b"
++			"\x58\x75\x92\xaf\xcc\xe9\x06\x23"
++			"\x40\x5d\x7a\x97\xb4\xd1\xee\x0b"
++			"\x28\x45\x62\x7f\x9c\xb9\xd6\xf3"
++			"\x10\x2d\x4a\x67\x84\xa1\xbe\xdb"
++			"\xf8\x15\x32\x4f\x6c\x89\xa6\xc3"
++			"\xe0\xfd\x1a\x37\x54\x71\x8e\xab"
++			"\xc8\xe5\x02\x1f\x3c\x59\x76\x93"
++			"\xb0\xcd\xea\x07\x24\x41\x5e\x7b"
++			"\x98\xb5\xd2\xef\x0c\x29\x46\x63"
++			"\x80\x9d\xba\xd7\xf4\x11\x2e\x4b"
++			"\x68\x85\xa2\xbf\xdc\xf9\x16\x33"
++			"\x50\x6d\x8a\xa7\xc4\xe1\xfe\x1b"
++			"\x38\x55\x72\x8f\xac\xc9\xe6\x03"
++			"\x20\x3d\x5a\x77\x94\xb1\xce\xeb"
++			"\x08\x25\x42\x5f\x7c\x99\xb6\xd3"
++			"\xf0\x0d\x2a\x47\x64\x81\x9e\xbb"
++			"\xd8\xf5\x12\x2f\x4c\x69\x86\xa3"
++			"\xc0\xdd\xfa\x17\x34\x51\x6e\x8b"
++			"\xa8\xc5\xe2\xff\x1c\x39\x56\x73"
++			"\x90\xad\xca\xe7\x04\x21\x3e\x5b"
++			"\x78\x95\xb2\xcf\xec\x09\x26\x43"
++			"\x60\x7d\x9a\xb7\xd4\xf1\x0e\x2b"
++			"\x48\x65\x82\x9f\xbc\xd9\xf6\x13"
++			"\x30\x4d\x6a\x87\xa4\xc1\xde\xfb"
++			"\x18\x35\x52\x6f\x8c\xa9\xc6\xe3"
++			"\x00\x1f\x3e\x5d\x7c\x9b\xba\xd9"
++			"\xf8\x17\x36\x55\x74\x93\xb2\xd1"
++			"\xf0\x0f\x2e\x4d\x6c\x8b\xaa\xc9"
++			"\xe8\x07\x26\x45\x64\x83\xa2\xc1"
++			"\xe0\xff\x1e\x3d\x5c\x7b\x9a\xb9"
++			"\xd8\xf7\x16\x35\x54\x73\x92\xb1"
++			"\xd0\xef\x0e\x2d\x4c\x6b\x8a\xa9"
++			"\xc8\xe7\x06\x25\x44\x63\x82\xa1"
++			"\xc0\xdf\xfe\x1d\x3c\x5b\x7a\x99"
++			"\xb8\xd7\xf6\x15\x34\x53\x72\x91"
++			"\xb0\xcf\xee\x0d\x2c\x4b\x6a\x89"
++			"\xa8\xc7\xe6\x05\x24\x43\x62\x81"
++			"\xa0\xbf\xde\xfd\x1c\x3b\x5a\x79"
++			"\x98\xb7\xd6\xf5\x14\x33\x52\x71"
++			"\x90\xaf\xce\xed\x0c\x2b\x4a\x69"
++			"\x88\xa7\xc6\xe5\x04\x23\x42\x61"
++			"\x80\x9f\xbe\xdd\xfc\x1b\x3a\x59"
++			"\x78\x97\xb6\xd5\xf4\x13\x32\x51"
++			"\x70\x8f\xae\xcd\xec\x0b\x2a\x49"
++			"\x68\x87\xa6\xc5\xe4\x03\x22\x41"
++			"\x60\x7f\x9e\xbd\xdc\xfb\x1a\x39"
++			"\x58\x77\x96\xb5\xd4\xf3\x12\x31"
++			"\x50\x6f\x8e\xad\xcc\xeb\x0a\x29"
++			"\x48\x67\x86\xa5\xc4\xe3\x02\x21"
++			"\x40\x5f\x7e\x9d\xbc\xdb\xfa\x19"
++			"\x38\x57\x76\x95\xb4\xd3\xf2\x11"
++			"\x30\x4f\x6e\x8d\xac\xcb\xea\x09"
++			"\x28\x47\x66\x85\xa4\xc3\xe2\x01"
++			"\x20\x3f\x5e\x7d\x9c\xbb\xda\xf9"
++			"\x18\x37\x56\x75\x94\xb3\xd2\xf1"
++			"\x10\x2f\x4e\x6d\x8c\xab\xca\xe9"
++			"\x08\x27\x46\x65\x84\xa3\xc2\xe1"
++			"\x00\x21\x42\x63",
+ 		.ilen = 4100,
+-		.result = {
+-			0xb5, 0x81, 0xf5, 0x64, 0x18, 0x73, 0xe3, 0xf0,
+-			0x4c, 0x13, 0xf2, 0x77, 0x18, 0x60, 0x65, 0x5e,
+-			0x29, 0x01, 0xce, 0x98, 0x55, 0x53, 0xf9, 0x0c,
+-			0x2a, 0x08, 0xd5, 0x09, 0xb3, 0x57, 0x55, 0x56,
+-			0xc5, 0xe9, 0x56, 0x90, 0xcb, 0x6a, 0xa3, 0xc0,
+-			0xff, 0xc4, 0x79, 0xb4, 0xd2, 0x97, 0x5d, 0xc4,
+-			0x43, 0xd1, 0xfe, 0x94, 0x7b, 0x88, 0x06, 0x5a,
+-			0xb2, 0x9e, 0x2c, 0xfc, 0x44, 0x03, 0xb7, 0x90,
+-			0xa0, 0xc1, 0xba, 0x6a, 0x33, 0xb8, 0xc7, 0xb2,
+-			0x9d, 0xe1, 0x12, 0x4f, 0xc0, 0x64, 0xd4, 0x01,
+-			0xfe, 0x8c, 0x7a, 0x66, 0xf7, 0xe6, 0x5a, 0x91,
+-			0xbb, 0xde, 0x56, 0x86, 0xab, 0x65, 0x21, 0x30,
+-			0x00, 0x84, 0x65, 0x24, 0xa5, 0x7d, 0x85, 0xb4,
+-			0xe3, 0x17, 0xed, 0x3a, 0xb7, 0x6f, 0xb4, 0x0b,
+-			0x0b, 0xaf, 0x15, 0xae, 0x5a, 0x8f, 0xf2, 0x0c,
+-			0x2f, 0x27, 0xf4, 0x09, 0xd8, 0xd2, 0x96, 0xb7,
+-			0x71, 0xf2, 0xc5, 0x99, 0x4d, 0x7e, 0x7f, 0x75,
+-			0x77, 0x89, 0x30, 0x8b, 0x59, 0xdb, 0xa2, 0xb2,
+-			0xa0, 0xf3, 0x19, 0x39, 0x2b, 0xc5, 0x7e, 0x3f,
+-			0x4f, 0xd9, 0xd3, 0x56, 0x28, 0x97, 0x44, 0xdc,
+-			0xc0, 0x8b, 0x77, 0x24, 0xd9, 0x52, 0xe7, 0xc5,
+-			0xaf, 0xf6, 0x7d, 0x59, 0xb2, 0x44, 0x05, 0x1d,
+-			0xb1, 0xb0, 0x11, 0xa5, 0x0f, 0xec, 0x33, 0xe1,
+-			0x6d, 0x1b, 0x4e, 0x1f, 0xff, 0x57, 0x91, 0xb4,
+-			0x5b, 0x9a, 0x96, 0xc5, 0x53, 0xbc, 0xae, 0x20,
+-			0x3c, 0xbb, 0x14, 0xe2, 0xe8, 0x22, 0x33, 0xc1,
+-			0x5e, 0x76, 0x9e, 0x46, 0x99, 0xf6, 0x2a, 0x15,
+-			0xc6, 0x97, 0x02, 0xa0, 0x66, 0x43, 0xd1, 0xa6,
+-			0x31, 0xa6, 0x9f, 0xfb, 0xf4, 0xd3, 0x69, 0xe5,
+-			0xcd, 0x76, 0x95, 0xb8, 0x7a, 0x82, 0x7f, 0x21,
+-			0x45, 0xff, 0x3f, 0xce, 0x55, 0xf6, 0x95, 0x10,
+-			0x08, 0x77, 0x10, 0x43, 0xc6, 0xf3, 0x09, 0xe5,
+-			0x68, 0xe7, 0x3c, 0xad, 0x00, 0x52, 0x45, 0x0d,
+-			0xfe, 0x2d, 0xc6, 0xc2, 0x94, 0x8c, 0x12, 0x1d,
+-			0xe6, 0x25, 0xae, 0x98, 0x12, 0x8e, 0x19, 0x9c,
+-			0x81, 0x68, 0xb1, 0x11, 0xf6, 0x69, 0xda, 0xe3,
+-			0x62, 0x08, 0x18, 0x7a, 0x25, 0x49, 0x28, 0xac,
+-			0xba, 0x71, 0x12, 0x0b, 0xe4, 0xa2, 0xe5, 0xc7,
+-			0x5d, 0x8e, 0xec, 0x49, 0x40, 0x21, 0xbf, 0x5a,
+-			0x98, 0xf3, 0x02, 0x68, 0x55, 0x03, 0x7f, 0x8a,
+-			0xe5, 0x94, 0x0c, 0x32, 0x5c, 0x07, 0x82, 0x63,
+-			0xaf, 0x6f, 0x91, 0x40, 0x84, 0x8e, 0x52, 0x25,
+-			0xd0, 0xb0, 0x29, 0x53, 0x05, 0xe2, 0x50, 0x7a,
+-			0x34, 0xeb, 0xc9, 0x46, 0x20, 0xa8, 0x3d, 0xde,
+-			0x7f, 0x16, 0x5f, 0x36, 0xc5, 0x2e, 0xdc, 0xd1,
+-			0x15, 0x47, 0xc7, 0x50, 0x40, 0x6d, 0x91, 0xc5,
+-			0xe7, 0x93, 0x95, 0x1a, 0xd3, 0x57, 0xbc, 0x52,
+-			0x33, 0xee, 0x14, 0x19, 0x22, 0x52, 0x89, 0xa7,
+-			0x4a, 0x25, 0x56, 0x77, 0x4b, 0xca, 0xcf, 0x0a,
+-			0xe1, 0xf5, 0x35, 0x85, 0x30, 0x7e, 0x59, 0x4a,
+-			0xbd, 0x14, 0x5b, 0xdf, 0xe3, 0x46, 0xcb, 0xac,
+-			0x1f, 0x6c, 0x96, 0x0e, 0xf4, 0x81, 0xd1, 0x99,
+-			0xca, 0x88, 0x63, 0x3d, 0x02, 0x58, 0x6b, 0xa9,
+-			0xe5, 0x9f, 0xb3, 0x00, 0xb2, 0x54, 0xc6, 0x74,
+-			0x1c, 0xbf, 0x46, 0xab, 0x97, 0xcc, 0xf8, 0x54,
+-			0x04, 0x07, 0x08, 0x52, 0xe6, 0xc0, 0xda, 0x93,
+-			0x74, 0x7d, 0x93, 0x99, 0x5d, 0x78, 0x68, 0xa6,
+-			0x2e, 0x6b, 0xd3, 0x6a, 0x69, 0xcc, 0x12, 0x6b,
+-			0xd4, 0xc7, 0xa5, 0xc6, 0xe7, 0xf6, 0x03, 0x04,
+-			0x5d, 0xcd, 0x61, 0x5e, 0x17, 0x40, 0xdc, 0xd1,
+-			0x5c, 0xf5, 0x08, 0xdf, 0x5c, 0x90, 0x85, 0xa4,
+-			0xaf, 0xf6, 0x78, 0xbb, 0x0d, 0xf1, 0xf4, 0xa4,
+-			0x54, 0x26, 0x72, 0x9e, 0x61, 0xfa, 0x86, 0xcf,
+-			0xe8, 0x9e, 0xa1, 0xe0, 0xc7, 0x48, 0x23, 0xae,
+-			0x5a, 0x90, 0xae, 0x75, 0x0a, 0x74, 0x18, 0x89,
+-			0x05, 0xb1, 0x92, 0xb2, 0x7f, 0xd0, 0x1b, 0xa6,
+-			0x62, 0x07, 0x25, 0x01, 0xc7, 0xc2, 0x4f, 0xf9,
+-			0xe8, 0xfe, 0x63, 0x95, 0x80, 0x07, 0xb4, 0x26,
+-			0xcc, 0xd1, 0x26, 0xb6, 0xc4, 0x3f, 0x9e, 0xcb,
+-			0x8e, 0x3b, 0x2e, 0x44, 0x16, 0xd3, 0x10, 0x9a,
+-			0x95, 0x08, 0xeb, 0xc8, 0xcb, 0xeb, 0xbf, 0x6f,
+-			0x0b, 0xcd, 0x1f, 0xc8, 0xca, 0x86, 0xaa, 0xec,
+-			0x33, 0xe6, 0x69, 0xf4, 0x45, 0x25, 0x86, 0x3a,
+-			0x22, 0x94, 0x4f, 0x00, 0x23, 0x6a, 0x44, 0xc2,
+-			0x49, 0x97, 0x33, 0xab, 0x36, 0x14, 0x0a, 0x70,
+-			0x24, 0xc3, 0xbe, 0x04, 0x3b, 0x79, 0xa0, 0xf9,
+-			0xb8, 0xe7, 0x76, 0x29, 0x22, 0x83, 0xd7, 0xf2,
+-			0x94, 0xf4, 0x41, 0x49, 0xba, 0x5f, 0x7b, 0x07,
+-			0xb5, 0xfb, 0xdb, 0x03, 0x1a, 0x9f, 0xb6, 0x4c,
+-			0xc2, 0x2e, 0x37, 0x40, 0x49, 0xc3, 0x38, 0x16,
+-			0xe2, 0x4f, 0x77, 0x82, 0xb0, 0x68, 0x4c, 0x71,
+-			0x1d, 0x57, 0x61, 0x9c, 0xd9, 0x4e, 0x54, 0x99,
+-			0x47, 0x13, 0x28, 0x73, 0x3c, 0xbb, 0x00, 0x90,
+-			0xf3, 0x4d, 0xc9, 0x0e, 0xfd, 0xe7, 0xb1, 0x71,
+-			0xd3, 0x15, 0x79, 0xbf, 0xcc, 0x26, 0x2f, 0xbd,
+-			0xad, 0x6c, 0x50, 0x69, 0x6c, 0x3e, 0x6d, 0x80,
+-			0x9a, 0xea, 0x78, 0xaf, 0x19, 0xb2, 0x0d, 0x4d,
+-			0xad, 0x04, 0x07, 0xae, 0x22, 0x90, 0x4a, 0x93,
+-			0x32, 0x0e, 0x36, 0x9b, 0x1b, 0x46, 0xba, 0x3b,
+-			0xb4, 0xac, 0xc6, 0xd1, 0xa2, 0x31, 0x53, 0x3b,
+-			0x2a, 0x3d, 0x45, 0xfe, 0x03, 0x61, 0x10, 0x85,
+-			0x17, 0x69, 0xa6, 0x78, 0xcc, 0x6c, 0x87, 0x49,
+-			0x53, 0xf9, 0x80, 0x10, 0xde, 0x80, 0xa2, 0x41,
+-			0x6a, 0xc3, 0x32, 0x02, 0xad, 0x6d, 0x3c, 0x56,
+-			0x00, 0x71, 0x51, 0x06, 0xa7, 0xbd, 0xfb, 0xef,
+-			0x3c, 0xb5, 0x9f, 0xfc, 0x48, 0x7d, 0x53, 0x7c,
+-			0x66, 0xb0, 0x49, 0x23, 0xc4, 0x47, 0x10, 0x0e,
+-			0xe5, 0x6c, 0x74, 0x13, 0xe6, 0xc5, 0x3f, 0xaa,
+-			0xde, 0xff, 0x07, 0x44, 0xdd, 0x56, 0x1b, 0xad,
+-			0x09, 0x77, 0xfb, 0x5b, 0x12, 0xb8, 0x0d, 0x38,
+-			0x17, 0x37, 0x35, 0x7b, 0x9b, 0xbc, 0xfe, 0xd4,
+-			0x7e, 0x8b, 0xda, 0x7e, 0x5b, 0x04, 0xa7, 0x22,
+-			0xa7, 0x31, 0xa1, 0x20, 0x86, 0xc7, 0x1b, 0x99,
+-			0xdb, 0xd1, 0x89, 0xf4, 0x94, 0xa3, 0x53, 0x69,
+-			0x8d, 0xe7, 0xe8, 0x74, 0x11, 0x8d, 0x74, 0xd6,
+-			0x07, 0x37, 0x91, 0x9f, 0xfd, 0x67, 0x50, 0x3a,
+-			0xc9, 0xe1, 0xf4, 0x36, 0xd5, 0xa0, 0x47, 0xd1,
+-			0xf9, 0xe5, 0x39, 0xa3, 0x31, 0xac, 0x07, 0x36,
+-			0x23, 0xf8, 0x66, 0x18, 0x14, 0x28, 0x34, 0x0f,
+-			0xb8, 0xd0, 0xe7, 0x29, 0xb3, 0x04, 0x4b, 0x55,
+-			0x01, 0x41, 0xb2, 0x75, 0x8d, 0xcb, 0x96, 0x85,
+-			0x3a, 0xfb, 0xab, 0x2b, 0x9e, 0xfa, 0x58, 0x20,
+-			0x44, 0x1f, 0xc0, 0x14, 0x22, 0x75, 0x61, 0xe8,
+-			0xaa, 0x19, 0xcf, 0xf1, 0x82, 0x56, 0xf4, 0xd7,
+-			0x78, 0x7b, 0x3d, 0x5f, 0xb3, 0x9e, 0x0b, 0x8a,
+-			0x57, 0x50, 0xdb, 0x17, 0x41, 0x65, 0x4d, 0xa3,
+-			0x02, 0xc9, 0x9c, 0x9c, 0x53, 0xfb, 0x39, 0x39,
+-			0x9b, 0x1d, 0x72, 0x24, 0xda, 0xb7, 0x39, 0xbe,
+-			0x13, 0x3b, 0xfa, 0x29, 0xda, 0x9e, 0x54, 0x64,
+-			0x6e, 0xba, 0xd8, 0xa1, 0xcb, 0xb3, 0x36, 0xfa,
+-			0xcb, 0x47, 0x85, 0xe9, 0x61, 0x38, 0xbc, 0xbe,
+-			0xc5, 0x00, 0x38, 0x2a, 0x54, 0xf7, 0xc4, 0xb9,
+-			0xb3, 0xd3, 0x7b, 0xa0, 0xa0, 0xf8, 0x72, 0x7f,
+-			0x8c, 0x8e, 0x82, 0x0e, 0xc6, 0x1c, 0x75, 0x9d,
+-			0xca, 0x8e, 0x61, 0x87, 0xde, 0xad, 0x80, 0xd2,
+-			0xf5, 0xf9, 0x80, 0xef, 0x15, 0x75, 0xaf, 0xf5,
+-			0x80, 0xfb, 0xff, 0x6d, 0x1e, 0x25, 0xb7, 0x40,
+-			0x61, 0x6a, 0x39, 0x5a, 0x6a, 0xb5, 0x31, 0xab,
+-			0x97, 0x8a, 0x19, 0x89, 0x44, 0x40, 0xc0, 0xa6,
+-			0xb4, 0x4e, 0x30, 0x32, 0x7b, 0x13, 0xe7, 0x67,
+-			0xa9, 0x8b, 0x57, 0x04, 0xc2, 0x01, 0xa6, 0xf4,
+-			0x28, 0x99, 0xad, 0x2c, 0x76, 0xa3, 0x78, 0xc2,
+-			0x4a, 0xe6, 0xca, 0x5c, 0x50, 0x6a, 0xc1, 0xb0,
+-			0x62, 0x4b, 0x10, 0x8e, 0x7c, 0x17, 0x43, 0xb3,
+-			0x17, 0x66, 0x1c, 0x3e, 0x8d, 0x69, 0xf0, 0x5a,
+-			0x71, 0xf5, 0x97, 0xdc, 0xd1, 0x45, 0xdd, 0x28,
+-			0xf3, 0x5d, 0xdf, 0x53, 0x7b, 0x11, 0xe5, 0xbc,
+-			0x4c, 0xdb, 0x1b, 0x51, 0x6b, 0xe9, 0xfb, 0x3d,
+-			0xc1, 0xc3, 0x2c, 0xb9, 0x71, 0xf5, 0xb6, 0xb2,
+-			0x13, 0x36, 0x79, 0x80, 0x53, 0xe8, 0xd3, 0xa6,
+-			0x0a, 0xaf, 0xfd, 0x56, 0x97, 0xf7, 0x40, 0x8e,
+-			0x45, 0xce, 0xf8, 0xb0, 0x9e, 0x5c, 0x33, 0x82,
+-			0xb0, 0x44, 0x56, 0xfc, 0x05, 0x09, 0xe9, 0x2a,
+-			0xac, 0x26, 0x80, 0x14, 0x1d, 0xc8, 0x3a, 0x35,
+-			0x4c, 0x82, 0x97, 0xfd, 0x76, 0xb7, 0xa9, 0x0a,
+-			0x35, 0x58, 0x79, 0x8e, 0x0f, 0x66, 0xea, 0xaf,
+-			0x51, 0x6c, 0x09, 0xa9, 0x6e, 0x9b, 0xcb, 0x9a,
+-			0x31, 0x47, 0xa0, 0x2f, 0x7c, 0x71, 0xb4, 0x4a,
+-			0x11, 0xaa, 0x8c, 0x66, 0xc5, 0x64, 0xe6, 0x3a,
+-			0x54, 0xda, 0x24, 0x6a, 0xc4, 0x41, 0x65, 0x46,
+-			0x82, 0xa0, 0x0a, 0x0f, 0x5f, 0xfb, 0x25, 0xd0,
+-			0x2c, 0x91, 0xa7, 0xee, 0xc4, 0x81, 0x07, 0x86,
+-			0x75, 0x5e, 0x33, 0x69, 0x97, 0xe4, 0x2c, 0xa8,
+-			0x9d, 0x9f, 0x0b, 0x6a, 0xbe, 0xad, 0x98, 0xda,
+-			0x6d, 0x94, 0x41, 0xda, 0x2c, 0x1e, 0x89, 0xc4,
+-			0xc2, 0xaf, 0x1e, 0x00, 0x05, 0x0b, 0x83, 0x60,
+-			0xbd, 0x43, 0xea, 0x15, 0x23, 0x7f, 0xb9, 0xac,
+-			0xee, 0x4f, 0x2c, 0xaf, 0x2a, 0xf3, 0xdf, 0xd0,
+-			0xf3, 0x19, 0x31, 0xbb, 0x4a, 0x74, 0x84, 0x17,
+-			0x52, 0x32, 0x2c, 0x7d, 0x61, 0xe4, 0xcb, 0xeb,
+-			0x80, 0x38, 0x15, 0x52, 0xcb, 0x6f, 0xea, 0xe5,
+-			0x73, 0x9c, 0xd9, 0x24, 0x69, 0xc6, 0x95, 0x32,
+-			0x21, 0xc8, 0x11, 0xe4, 0xdc, 0x36, 0xd7, 0x93,
+-			0x38, 0x66, 0xfb, 0xb2, 0x7f, 0x3a, 0xb9, 0xaf,
+-			0x31, 0xdd, 0x93, 0x75, 0x78, 0x8a, 0x2c, 0x94,
+-			0x87, 0x1a, 0x58, 0xec, 0x9e, 0x7d, 0x4d, 0xba,
+-			0xe1, 0xe5, 0x4d, 0xfc, 0xbc, 0xa4, 0x2a, 0x14,
+-			0xef, 0xcc, 0xa7, 0xec, 0xab, 0x43, 0x09, 0x18,
+-			0xd3, 0xab, 0x68, 0xd1, 0x07, 0x99, 0x44, 0x47,
+-			0xd6, 0x83, 0x85, 0x3b, 0x30, 0xea, 0xa9, 0x6b,
+-			0x63, 0xea, 0xc4, 0x07, 0xfb, 0x43, 0x2f, 0xa4,
+-			0xaa, 0xb0, 0xab, 0x03, 0x89, 0xce, 0x3f, 0x8c,
+-			0x02, 0x7c, 0x86, 0x54, 0xbc, 0x88, 0xaf, 0x75,
+-			0xd2, 0xdc, 0x63, 0x17, 0xd3, 0x26, 0xf6, 0x96,
+-			0xa9, 0x3c, 0xf1, 0x61, 0x8c, 0x11, 0x18, 0xcc,
+-			0xd6, 0xea, 0x5b, 0xe2, 0xcd, 0xf0, 0xf1, 0xb2,
+-			0xe5, 0x35, 0x90, 0x1f, 0x85, 0x4c, 0x76, 0x5b,
+-			0x66, 0xce, 0x44, 0xa4, 0x32, 0x9f, 0xe6, 0x7b,
+-			0x71, 0x6e, 0x9f, 0x58, 0x15, 0x67, 0x72, 0x87,
+-			0x64, 0x8e, 0x3a, 0x44, 0x45, 0xd4, 0x76, 0xfa,
+-			0xc2, 0xf6, 0xef, 0x85, 0x05, 0x18, 0x7a, 0x9b,
+-			0xba, 0x41, 0x54, 0xac, 0xf0, 0xfc, 0x59, 0x12,
+-			0x3f, 0xdf, 0xa0, 0xe5, 0x8a, 0x65, 0xfd, 0x3a,
+-			0x62, 0x8d, 0x83, 0x2c, 0x03, 0xbe, 0x05, 0x76,
+-			0x2e, 0x53, 0x49, 0x97, 0x94, 0x33, 0xae, 0x40,
+-			0x81, 0x15, 0xdb, 0x6e, 0xad, 0xaa, 0xf5, 0x4b,
+-			0xe3, 0x98, 0x70, 0xdf, 0xe0, 0x7c, 0xcd, 0xdb,
+-			0x02, 0xd4, 0x7d, 0x2f, 0xc1, 0xe6, 0xb4, 0xf3,
+-			0xd7, 0x0d, 0x7a, 0xd9, 0x23, 0x9e, 0x87, 0x2d,
+-			0xce, 0x87, 0xad, 0xcc, 0x72, 0x05, 0x00, 0x29,
+-			0xdc, 0x73, 0x7f, 0x64, 0xc1, 0x15, 0x0e, 0xc2,
+-			0xdf, 0xa7, 0x5f, 0xeb, 0x41, 0xa1, 0xcd, 0xef,
+-			0x5c, 0x50, 0x79, 0x2a, 0x56, 0x56, 0x71, 0x8c,
+-			0xac, 0xc0, 0x79, 0x50, 0x69, 0xca, 0x59, 0x32,
+-			0x65, 0xf2, 0x54, 0xe4, 0x52, 0x38, 0x76, 0xd1,
+-			0x5e, 0xde, 0x26, 0x9e, 0xfb, 0x75, 0x2e, 0x11,
+-			0xb5, 0x10, 0xf4, 0x17, 0x73, 0xf5, 0x89, 0xc7,
+-			0x4f, 0x43, 0x5c, 0x8e, 0x7c, 0xb9, 0x05, 0x52,
+-			0x24, 0x40, 0x99, 0xfe, 0x9b, 0x85, 0x0b, 0x6c,
+-			0x22, 0x3e, 0x8b, 0xae, 0x86, 0xa1, 0xd2, 0x79,
+-			0x05, 0x68, 0x6b, 0xab, 0xe3, 0x41, 0x49, 0xed,
+-			0x15, 0xa1, 0x8d, 0x40, 0x2d, 0x61, 0xdf, 0x1a,
+-			0x59, 0xc9, 0x26, 0x8b, 0xef, 0x30, 0x4c, 0x88,
+-			0x4b, 0x10, 0xf8, 0x8d, 0xa6, 0x92, 0x9f, 0x4b,
+-			0xf3, 0xc4, 0x53, 0x0b, 0x89, 0x5d, 0x28, 0x92,
+-			0xcf, 0x78, 0xb2, 0xc0, 0x5d, 0xed, 0x7e, 0xfc,
+-			0xc0, 0x12, 0x23, 0x5f, 0x5a, 0x78, 0x86, 0x43,
+-			0x6e, 0x27, 0xf7, 0x5a, 0xa7, 0x6a, 0xed, 0x19,
+-			0x04, 0xf0, 0xb3, 0x12, 0xd1, 0xbd, 0x0e, 0x89,
+-			0x6e, 0xbc, 0x96, 0xa8, 0xd8, 0x49, 0x39, 0x9f,
+-			0x7e, 0x67, 0xf0, 0x2e, 0x3e, 0x01, 0xa9, 0xba,
+-			0xec, 0x8b, 0x62, 0x8e, 0xcb, 0x4a, 0x70, 0x43,
+-			0xc7, 0xc2, 0xc4, 0xca, 0x82, 0x03, 0x73, 0xe9,
+-			0x11, 0xdf, 0xcf, 0x54, 0xea, 0xc9, 0xb0, 0x95,
+-			0x51, 0xc0, 0x13, 0x3d, 0x92, 0x05, 0xfa, 0xf4,
+-			0xa9, 0x34, 0xc8, 0xce, 0x6c, 0x3d, 0x54, 0xcc,
+-			0xc4, 0xaf, 0xf1, 0xdc, 0x11, 0x44, 0x26, 0xa2,
+-			0xaf, 0xf1, 0x85, 0x75, 0x7d, 0x03, 0x61, 0x68,
+-			0x4e, 0x78, 0xc6, 0x92, 0x7d, 0x86, 0x7d, 0x77,
+-			0xdc, 0x71, 0x72, 0xdb, 0xc6, 0xae, 0xa1, 0xcb,
+-			0x70, 0x9a, 0x0b, 0x19, 0xbe, 0x4a, 0x6c, 0x2a,
+-			0xe2, 0xba, 0x6c, 0x64, 0x9a, 0x13, 0x28, 0xdf,
+-			0x85, 0x75, 0xe6, 0x43, 0xf6, 0x87, 0x08, 0x68,
+-			0x6e, 0xba, 0x6e, 0x79, 0x9f, 0x04, 0xbc, 0x23,
+-			0x50, 0xf6, 0x33, 0x5c, 0x1f, 0x24, 0x25, 0xbe,
+-			0x33, 0x47, 0x80, 0x45, 0x56, 0xa3, 0xa7, 0xd7,
+-			0x7a, 0xb1, 0x34, 0x0b, 0x90, 0x3c, 0x9c, 0xad,
+-			0x44, 0x5f, 0x9e, 0x0e, 0x9d, 0xd4, 0xbd, 0x93,
+-			0x5e, 0xfa, 0x3c, 0xe0, 0xb0, 0xd9, 0xed, 0xf3,
+-			0xd6, 0x2e, 0xff, 0x24, 0xd8, 0x71, 0x6c, 0xed,
+-			0xaf, 0x55, 0xeb, 0x22, 0xac, 0x93, 0x68, 0x32,
+-			0x05, 0x5b, 0x47, 0xdd, 0xc6, 0x4a, 0xcb, 0xc7,
+-			0x10, 0xe1, 0x3c, 0x92, 0x1a, 0xf3, 0x23, 0x78,
+-			0x2b, 0xa1, 0xd2, 0x80, 0xf4, 0x12, 0xb1, 0x20,
+-			0x8f, 0xff, 0x26, 0x35, 0xdd, 0xfb, 0xc7, 0x4e,
+-			0x78, 0xf1, 0x2d, 0x50, 0x12, 0x77, 0xa8, 0x60,
+-			0x7c, 0x0f, 0xf5, 0x16, 0x2f, 0x63, 0x70, 0x2a,
+-			0xc0, 0x96, 0x80, 0x4e, 0x0a, 0xb4, 0x93, 0x35,
+-			0x5d, 0x1d, 0x3f, 0x56, 0xf7, 0x2f, 0xbb, 0x90,
+-			0x11, 0x16, 0x8f, 0xa2, 0xec, 0x47, 0xbe, 0xac,
+-			0x56, 0x01, 0x26, 0x56, 0xb1, 0x8c, 0xb2, 0x10,
+-			0xf9, 0x1a, 0xca, 0xf5, 0xd1, 0xb7, 0x39, 0x20,
+-			0x63, 0xf1, 0x69, 0x20, 0x4f, 0x13, 0x12, 0x1f,
+-			0x5b, 0x65, 0xfc, 0x98, 0xf7, 0xc4, 0x7a, 0xbe,
+-			0xf7, 0x26, 0x4d, 0x2b, 0x84, 0x7b, 0x42, 0xad,
+-			0xd8, 0x7a, 0x0a, 0xb4, 0xd8, 0x74, 0xbf, 0xc1,
+-			0xf0, 0x6e, 0xb4, 0x29, 0xa3, 0xbb, 0xca, 0x46,
+-			0x67, 0x70, 0x6a, 0x2d, 0xce, 0x0e, 0xa2, 0x8a,
+-			0xa9, 0x87, 0xbf, 0x05, 0xc4, 0xc1, 0x04, 0xa3,
+-			0xab, 0xd4, 0x45, 0x43, 0x8c, 0xb6, 0x02, 0xb0,
+-			0x41, 0xc8, 0xfc, 0x44, 0x3d, 0x59, 0xaa, 0x2e,
+-			0x44, 0x21, 0x2a, 0x8d, 0x88, 0x9d, 0x57, 0xf4,
+-			0xa0, 0x02, 0x77, 0xb8, 0xa6, 0xa0, 0xe6, 0x75,
+-			0x5c, 0x82, 0x65, 0x3e, 0x03, 0x5c, 0x29, 0x8f,
+-			0x38, 0x55, 0xab, 0x33, 0x26, 0xef, 0x9f, 0x43,
+-			0x52, 0xfd, 0x68, 0xaf, 0x36, 0xb4, 0xbb, 0x9a,
+-			0x58, 0x09, 0x09, 0x1b, 0xc3, 0x65, 0x46, 0x46,
+-			0x1d, 0xa7, 0x94, 0x18, 0x23, 0x50, 0x2c, 0xca,
+-			0x2c, 0x55, 0x19, 0x97, 0x01, 0x9d, 0x93, 0x3b,
+-			0x63, 0x86, 0xf2, 0x03, 0x67, 0x45, 0xd2, 0x72,
+-			0x28, 0x52, 0x6c, 0xf4, 0xe3, 0x1c, 0xb5, 0x11,
+-			0x13, 0xf1, 0xeb, 0x21, 0xc7, 0xd9, 0x56, 0x82,
+-			0x2b, 0x82, 0x39, 0xbd, 0x69, 0x54, 0xed, 0x62,
+-			0xc3, 0xe2, 0xde, 0x73, 0xd4, 0x6a, 0x12, 0xae,
+-			0x13, 0x21, 0x7f, 0x4b, 0x5b, 0xfc, 0xbf, 0xe8,
+-			0x2b, 0xbe, 0x56, 0xba, 0x68, 0x8b, 0x9a, 0xb1,
+-			0x6e, 0xfa, 0xbf, 0x7e, 0x5a, 0x4b, 0xf1, 0xac,
+-			0x98, 0x65, 0x85, 0xd1, 0x93, 0x53, 0xd3, 0x7b,
+-			0x09, 0xdd, 0x4b, 0x10, 0x6d, 0x84, 0xb0, 0x13,
+-			0x65, 0xbd, 0xcf, 0x52, 0x09, 0xc4, 0x85, 0xe2,
+-			0x84, 0x74, 0x15, 0x65, 0xb7, 0xf7, 0x51, 0xaf,
+-			0x55, 0xad, 0xa4, 0xd1, 0x22, 0x54, 0x70, 0x94,
+-			0xa0, 0x1c, 0x90, 0x41, 0xfd, 0x99, 0xd7, 0x5a,
+-			0x31, 0xef, 0xaa, 0x25, 0xd0, 0x7f, 0x4f, 0xea,
+-			0x1d, 0x55, 0x42, 0xe5, 0x49, 0xb0, 0xd0, 0x46,
+-			0x62, 0x36, 0x43, 0xb2, 0x82, 0x15, 0x75, 0x50,
+-			0xa4, 0x72, 0xeb, 0x54, 0x27, 0x1f, 0x8a, 0xe4,
+-			0x7d, 0xe9, 0x66, 0xc5, 0xf1, 0x53, 0xa4, 0xd1,
+-			0x0c, 0xeb, 0xb8, 0xf8, 0xbc, 0xd4, 0xe2, 0xe7,
+-			0xe1, 0xf8, 0x4b, 0xcb, 0xa9, 0xa1, 0xaf, 0x15,
+-			0x83, 0xcb, 0x72, 0xd0, 0x33, 0x79, 0x00, 0x2d,
+-			0x9f, 0xd7, 0xf1, 0x2e, 0x1e, 0x10, 0xe4, 0x45,
+-			0xc0, 0x75, 0x3a, 0x39, 0xea, 0x68, 0xf7, 0x5d,
+-			0x1b, 0x73, 0x8f, 0xe9, 0x8e, 0x0f, 0x72, 0x47,
+-			0xae, 0x35, 0x0a, 0x31, 0x7a, 0x14, 0x4d, 0x4a,
+-			0x6f, 0x47, 0xf7, 0x7e, 0x91, 0x6e, 0x74, 0x8b,
+-			0x26, 0x47, 0xf9, 0xc3, 0xf9, 0xde, 0x70, 0xf5,
+-			0x61, 0xab, 0xa9, 0x27, 0x9f, 0x82, 0xe4, 0x9c,
+-			0x89, 0x91, 0x3f, 0x2e, 0x6a, 0xfd, 0xb5, 0x49,
+-			0xe9, 0xfd, 0x59, 0x14, 0x36, 0x49, 0x40, 0x6d,
+-			0x32, 0xd8, 0x85, 0x42, 0xf3, 0xa5, 0xdf, 0x0c,
+-			0xa8, 0x27, 0xd7, 0x54, 0xe2, 0x63, 0x2f, 0xf2,
+-			0x7e, 0x8b, 0x8b, 0xe7, 0xf1, 0x9a, 0x95, 0x35,
+-			0x43, 0xdc, 0x3a, 0xe4, 0xb6, 0xf4, 0xd0, 0xdf,
+-			0x9c, 0xcb, 0x94, 0xf3, 0x21, 0xa0, 0x77, 0x50,
+-			0xe2, 0xc6, 0xc4, 0xc6, 0x5f, 0x09, 0x64, 0x5b,
+-			0x92, 0x90, 0xd8, 0xe1, 0xd1, 0xed, 0x4b, 0x42,
+-			0xd7, 0x37, 0xaf, 0x65, 0x3d, 0x11, 0x39, 0xb6,
+-			0x24, 0x8a, 0x60, 0xae, 0xd6, 0x1e, 0xbf, 0x0e,
+-			0x0d, 0xd7, 0xdc, 0x96, 0x0e, 0x65, 0x75, 0x4e,
+-			0x29, 0x06, 0x9d, 0xa4, 0x51, 0x3a, 0x10, 0x63,
+-			0x8f, 0x17, 0x07, 0xd5, 0x8e, 0x3c, 0xf4, 0x28,
+-			0x00, 0x5a, 0x5b, 0x05, 0x19, 0xd8, 0xc0, 0x6c,
+-			0xe5, 0x15, 0xe4, 0x9c, 0x9d, 0x71, 0x9d, 0x5e,
+-			0x94, 0x29, 0x1a, 0xa7, 0x80, 0xfa, 0x0e, 0x33,
+-			0x03, 0xdd, 0xb7, 0x3e, 0x9a, 0xa9, 0x26, 0x18,
+-			0x37, 0xa9, 0x64, 0x08, 0x4d, 0x94, 0x5a, 0x88,
+-			0xca, 0x35, 0xce, 0x81, 0x02, 0xe3, 0x1f, 0x1b,
+-			0x89, 0x1a, 0x77, 0x85, 0xe3, 0x41, 0x6d, 0x32,
+-			0x42, 0x19, 0x23, 0x7d, 0xc8, 0x73, 0xee, 0x25,
+-			0x85, 0x0d, 0xf8, 0x31, 0x25, 0x79, 0x1b, 0x6f,
+-			0x79, 0x25, 0xd2, 0xd8, 0xd4, 0x23, 0xfd, 0xf7,
+-			0x82, 0x36, 0x6a, 0x0c, 0x46, 0x22, 0x15, 0xe9,
+-			0xff, 0x72, 0x41, 0x91, 0x91, 0x7d, 0x3a, 0xb7,
+-			0xdd, 0x65, 0x99, 0x70, 0xf6, 0x8d, 0x84, 0xf8,
+-			0x67, 0x15, 0x20, 0x11, 0xd6, 0xb2, 0x55, 0x7b,
+-			0xdb, 0x87, 0xee, 0xef, 0x55, 0x89, 0x2a, 0x59,
+-			0x2b, 0x07, 0x8f, 0x43, 0x8a, 0x59, 0x3c, 0x01,
+-			0x8b, 0x65, 0x54, 0xa1, 0x66, 0xd5, 0x38, 0xbd,
+-			0xc6, 0x30, 0xa9, 0xcc, 0x49, 0xb6, 0xa8, 0x1b,
+-			0xb8, 0xc0, 0x0e, 0xe3, 0x45, 0x28, 0xe2, 0xff,
+-			0x41, 0x9f, 0x7e, 0x7c, 0xd1, 0xae, 0x9e, 0x25,
+-			0x3f, 0x4c, 0x7c, 0x7c, 0xf4, 0xa8, 0x26, 0x4d,
+-			0x5c, 0xfd, 0x4b, 0x27, 0x18, 0xf9, 0x61, 0x76,
+-			0x48, 0xba, 0x0c, 0x6b, 0xa9, 0x4d, 0xfc, 0xf5,
+-			0x3b, 0x35, 0x7e, 0x2f, 0x4a, 0xa9, 0xc2, 0x9a,
+-			0xae, 0xab, 0x86, 0x09, 0x89, 0xc9, 0xc2, 0x40,
+-			0x39, 0x2c, 0x81, 0xb3, 0xb8, 0x17, 0x67, 0xc2,
+-			0x0d, 0x32, 0x4a, 0x3a, 0x67, 0x81, 0xd7, 0x1a,
+-			0x34, 0x52, 0xc5, 0xdb, 0x0a, 0xf5, 0x63, 0x39,
+-			0xea, 0x1f, 0xe1, 0x7c, 0xa1, 0x9e, 0xc1, 0x35,
+-			0xe3, 0xb1, 0x18, 0x45, 0x67, 0xf9, 0x22, 0x38,
+-			0x95, 0xd9, 0x34, 0x34, 0x86, 0xc6, 0x41, 0x94,
+-			0x15, 0xf9, 0x5b, 0x41, 0xa6, 0x87, 0x8b, 0xf8,
+-			0xd5, 0xe1, 0x1b, 0xe2, 0x5b, 0xf3, 0x86, 0x10,
+-			0xff, 0xe6, 0xae, 0x69, 0x76, 0xbc, 0x0d, 0xb4,
+-			0x09, 0x90, 0x0c, 0xa2, 0x65, 0x0c, 0xad, 0x74,
+-			0xf5, 0xd7, 0xff, 0xda, 0xc1, 0xce, 0x85, 0xbe,
+-			0x00, 0xa7, 0xff, 0x4d, 0x2f, 0x65, 0xd3, 0x8c,
+-			0x86, 0x2d, 0x05, 0xe8, 0xed, 0x3e, 0x6b, 0x8b,
+-			0x0f, 0x3d, 0x83, 0x8c, 0xf1, 0x1d, 0x5b, 0x96,
+-			0x2e, 0xb1, 0x9c, 0xc2, 0x98, 0xe1, 0x70, 0xb9,
+-			0xba, 0x5c, 0x8a, 0x43, 0xd6, 0x34, 0xa7, 0x2d,
+-			0xc9, 0x92, 0xae, 0xf2, 0xa5, 0x7b, 0x05, 0x49,
+-			0xa7, 0x33, 0x34, 0x86, 0xca, 0xe4, 0x96, 0x23,
+-			0x76, 0x5b, 0xf2, 0xc6, 0xf1, 0x51, 0x28, 0x42,
+-			0x7b, 0xcc, 0x76, 0x8f, 0xfa, 0xa2, 0xad, 0x31,
+-			0xd4, 0xd6, 0x7a, 0x6d, 0x25, 0x25, 0x54, 0xe4,
+-			0x3f, 0x50, 0x59, 0xe1, 0x5c, 0x05, 0xb7, 0x27,
+-			0x48, 0xbf, 0x07, 0xec, 0x1b, 0x13, 0xbe, 0x2b,
+-			0xa1, 0x57, 0x2b, 0xd5, 0xab, 0xd7, 0xd0, 0x4c,
+-			0x1e, 0xcb, 0x71, 0x9b, 0xc5, 0x90, 0x85, 0xd3,
+-			0xde, 0x59, 0xec, 0x71, 0xeb, 0x89, 0xbb, 0xd0,
+-			0x09, 0x50, 0xe1, 0x16, 0x3f, 0xfd, 0x1c, 0x34,
+-			0xc3, 0x1c, 0xa1, 0x10, 0x77, 0x53, 0x98, 0xef,
+-			0xf2, 0xfd, 0xa5, 0x01, 0x59, 0xc2, 0x9b, 0x26,
+-			0xc7, 0x42, 0xd9, 0x49, 0xda, 0x58, 0x2b, 0x6e,
+-			0x9f, 0x53, 0x19, 0x76, 0x7e, 0xd9, 0xc9, 0x0e,
+-			0x68, 0xc8, 0x7f, 0x51, 0x22, 0x42, 0xef, 0x49,
+-			0xa4, 0x55, 0xb6, 0x36, 0xac, 0x09, 0xc7, 0x31,
+-			0x88, 0x15, 0x4b, 0x2e, 0x8f, 0x3a, 0x08, 0xf7,
+-			0xd8, 0xf7, 0xa8, 0xc5, 0xa9, 0x33, 0xa6, 0x45,
+-			0xe4, 0xc4, 0x94, 0x76, 0xf3, 0x0d, 0x8f, 0x7e,
+-			0xc8, 0xf6, 0xbc, 0x23, 0x0a, 0xb6, 0x4c, 0xd3,
+-			0x6a, 0xcd, 0x36, 0xc2, 0x90, 0x5c, 0x5c, 0x3c,
+-			0x65, 0x7b, 0xc2, 0xd6, 0xcc, 0xe6, 0x0d, 0x87,
+-			0x73, 0x2e, 0x71, 0x79, 0x16, 0x06, 0x63, 0x28,
+-			0x09, 0x15, 0xd8, 0x89, 0x38, 0x38, 0x3d, 0xb5,
+-			0x42, 0x1c, 0x08, 0x24, 0xf7, 0x2a, 0xd2, 0x9d,
+-			0xc8, 0xca, 0xef, 0xf9, 0x27, 0xd8, 0x07, 0x86,
+-			0xf7, 0x43, 0x0b, 0x55, 0x15, 0x3f, 0x9f, 0x83,
+-			0xef, 0xdc, 0x49, 0x9d, 0x2a, 0xc1, 0x54, 0x62,
+-			0xbd, 0x9b, 0x66, 0x55, 0x9f, 0xb7, 0x12, 0xf3,
+-			0x1b, 0x4d, 0x9d, 0x2a, 0x5c, 0xed, 0x87, 0x75,
+-			0x87, 0x26, 0xec, 0x61, 0x2c, 0xb4, 0x0f, 0x89,
+-			0xb0, 0xfb, 0x2e, 0x68, 0x5d, 0x15, 0xc7, 0x8d,
+-			0x2e, 0xc0, 0xd9, 0xec, 0xaf, 0x4f, 0xd2, 0x25,
+-			0x29, 0xe8, 0xd2, 0x26, 0x2b, 0x67, 0xe9, 0xfc,
+-			0x2b, 0xa8, 0x67, 0x96, 0x12, 0x1f, 0x5b, 0x96,
+-			0xc6, 0x14, 0x53, 0xaf, 0x44, 0xea, 0xd6, 0xe2,
+-			0x94, 0x98, 0xe4, 0x12, 0x93, 0x4c, 0x92, 0xe0,
+-			0x18, 0xa5, 0x8d, 0x2d, 0xe4, 0x71, 0x3c, 0x47,
+-			0x4c, 0xf7, 0xe6, 0x47, 0x9e, 0xc0, 0x68, 0xdf,
+-			0xd4, 0xf5, 0x5a, 0x74, 0xb1, 0x2b, 0x29, 0x03,
+-			0x19, 0x07, 0xaf, 0x90, 0x62, 0x5c, 0x68, 0x98,
+-			0x48, 0x16, 0x11, 0x02, 0x9d, 0xee, 0xb4, 0x9b,
+-			0xe5, 0x42, 0x7f, 0x08, 0xfd, 0x16, 0x32, 0x0b,
+-			0xd0, 0xb3, 0xfa, 0x2b, 0xb7, 0x99, 0xf9, 0x29,
+-			0xcd, 0x20, 0x45, 0x9f, 0xb3, 0x1a, 0x5d, 0xa2,
+-			0xaf, 0x4d, 0xe0, 0xbd, 0x42, 0x0d, 0xbc, 0x74,
+-			0x99, 0x9c, 0x8e, 0x53, 0x1a, 0xb4, 0x3e, 0xbd,
+-			0xa2, 0x9a, 0x2d, 0xf7, 0xf8, 0x39, 0x0f, 0x67,
+-			0x63, 0xfc, 0x6b, 0xc0, 0xaf, 0xb3, 0x4b, 0x4f,
+-			0x55, 0xc4, 0xcf, 0xa7, 0xc8, 0x04, 0x11, 0x3e,
+-			0x14, 0x32, 0xbb, 0x1b, 0x38, 0x77, 0xd6, 0x7f,
+-			0x54, 0x4c, 0xdf, 0x75, 0xf3, 0x07, 0x2d, 0x33,
+-			0x9b, 0xa8, 0x20, 0xe1, 0x7b, 0x12, 0xb5, 0xf3,
+-			0xef, 0x2f, 0xce, 0x72, 0xe5, 0x24, 0x60, 0xc1,
+-			0x30, 0xe2, 0xab, 0xa1, 0x8e, 0x11, 0x09, 0xa8,
+-			0x21, 0x33, 0x44, 0xfe, 0x7f, 0x35, 0x32, 0x93,
+-			0x39, 0xa7, 0xad, 0x8b, 0x79, 0x06, 0xb2, 0xcb,
+-			0x4e, 0xa9, 0x5f, 0xc7, 0xba, 0x74, 0x29, 0xec,
+-			0x93, 0xa0, 0x4e, 0x54, 0x93, 0xc0, 0xbc, 0x55,
+-			0x64, 0xf0, 0x48, 0xe5, 0x57, 0x99, 0xee, 0x75,
+-			0xd6, 0x79, 0x0f, 0x66, 0xb7, 0xc6, 0x57, 0x76,
+-			0xf7, 0xb7, 0xf3, 0x9c, 0xc5, 0x60, 0xe8, 0x7f,
+-			0x83, 0x76, 0xd6, 0x0e, 0xaa, 0xe6, 0x90, 0x39,
+-			0x1d, 0xa6, 0x32, 0x6a, 0x34, 0xe3, 0x55, 0xf8,
+-			0x58, 0xa0, 0x58, 0x7d, 0x33, 0xe0, 0x22, 0x39,
+-			0x44, 0x64, 0x87, 0x86, 0x5a, 0x2f, 0xa7, 0x7e,
+-			0x0f, 0x38, 0xea, 0xb0, 0x30, 0xcc, 0x61, 0xa5,
+-			0x6a, 0x32, 0xae, 0x1e, 0xf7, 0xe9, 0xd0, 0xa9,
+-			0x0c, 0x32, 0x4b, 0xb5, 0x49, 0x28, 0xab, 0x85,
+-			0x2f, 0x8e, 0x01, 0x36, 0x38, 0x52, 0xd0, 0xba,
+-			0xd6, 0x02, 0x78, 0xf8, 0x0e, 0x3e, 0x9c, 0x8b,
+-			0x6b, 0x45, 0x99, 0x3f, 0x5c, 0xfe, 0x58, 0xf1,
+-			0x5c, 0x94, 0x04, 0xe1, 0xf5, 0x18, 0x6d, 0x51,
+-			0xb2, 0x5d, 0x18, 0x20, 0xb6, 0xc2, 0x9a, 0x42,
+-			0x1d, 0xb3, 0xab, 0x3c, 0xb6, 0x3a, 0x13, 0x03,
+-			0xb2, 0x46, 0x82, 0x4f, 0xfc, 0x64, 0xbc, 0x4f,
+-			0xca, 0xfa, 0x9c, 0xc0, 0xd5, 0xa7, 0xbd, 0x11,
+-			0xb7, 0xe4, 0x5a, 0xf6, 0x6f, 0x4d, 0x4d, 0x54,
+-			0xea, 0xa4, 0x98, 0x66, 0xd4, 0x22, 0x3b, 0xd3,
+-			0x8f, 0x34, 0x47, 0xd9, 0x7c, 0xf4, 0x72, 0x3b,
+-			0x4d, 0x02, 0x77, 0xf6, 0xd6, 0xdd, 0x08, 0x0a,
+-			0x81, 0xe1, 0x86, 0x89, 0x3e, 0x56, 0x10, 0x3c,
+-			0xba, 0xd7, 0x81, 0x8c, 0x08, 0xbc, 0x8b, 0xe2,
+-			0x53, 0xec, 0xa7, 0x89, 0xee, 0xc8, 0x56, 0xb5,
+-			0x36, 0x2c, 0xb2, 0x03, 0xba, 0x99, 0xdd, 0x7c,
+-			0x48, 0xa0, 0xb0, 0xbc, 0x91, 0x33, 0xe9, 0xa8,
+-			0xcb, 0xcd, 0xcf, 0x59, 0x5f, 0x1f, 0x15, 0xe2,
+-			0x56, 0xf5, 0x4e, 0x01, 0x35, 0x27, 0x45, 0x77,
+-			0x47, 0xc8, 0xbc, 0xcb, 0x7e, 0x39, 0xc1, 0x97,
+-			0x28, 0xd3, 0x84, 0xfc, 0x2c, 0x3e, 0xc8, 0xad,
+-			0x9c, 0xf8, 0x8a, 0x61, 0x9c, 0x28, 0xaa, 0xc5,
+-			0x99, 0x20, 0x43, 0x85, 0x9d, 0xa5, 0xe2, 0x8b,
+-			0xb8, 0xae, 0xeb, 0xd0, 0x32, 0x0d, 0x52, 0x78,
+-			0x09, 0x56, 0x3f, 0xc7, 0xd8, 0x7e, 0x26, 0xfc,
+-			0x37, 0xfb, 0x6f, 0x04, 0xfc, 0xfa, 0x92, 0x10,
+-			0xac, 0xf8, 0x3e, 0x21, 0xdc, 0x8c, 0x21, 0x16,
+-			0x7d, 0x67, 0x6e, 0xf6, 0xcd, 0xda, 0xb6, 0x98,
+-			0x23, 0xab, 0x23, 0x3c, 0xb2, 0x10, 0xa0, 0x53,
+-			0x5a, 0x56, 0x9f, 0xc5, 0xd0, 0xff, 0xbb, 0xe4,
+-			0x98, 0x3c, 0x69, 0x1e, 0xdb, 0x38, 0x8f, 0x7e,
+-			0x0f, 0xd2, 0x98, 0x88, 0x81, 0x8b, 0x45, 0x67,
+-			0xea, 0x33, 0xf1, 0xeb, 0xe9, 0x97, 0x55, 0x2e,
+-			0xd9, 0xaa, 0xeb, 0x5a, 0xec, 0xda, 0xe1, 0x68,
+-			0xa8, 0x9d, 0x3c, 0x84, 0x7c, 0x05, 0x3d, 0x62,
+-			0x87, 0x8f, 0x03, 0x21, 0x28, 0x95, 0x0c, 0x89,
+-			0x25, 0x22, 0x4a, 0xb0, 0x93, 0xa9, 0x50, 0xa2,
+-			0x2f, 0x57, 0x6e, 0x18, 0x42, 0x19, 0x54, 0x0c,
+-			0x55, 0x67, 0xc6, 0x11, 0x49, 0xf4, 0x5c, 0xd2,
+-			0xe9, 0x3d, 0xdd, 0x8b, 0x48, 0x71, 0x21, 0x00,
+-			0xc3, 0x9a, 0x6c, 0x85, 0x74, 0x28, 0x83, 0x4a,
+-			0x1b, 0x31, 0x05, 0xe1, 0x06, 0x92, 0xe7, 0xda,
+-			0x85, 0x73, 0x78, 0x45, 0x20, 0x7f, 0xae, 0x13,
+-			0x7c, 0x33, 0x06, 0x22, 0xf4, 0x83, 0xf9, 0x35,
+-			0x3f, 0x6c, 0x71, 0xa8, 0x4e, 0x48, 0xbe, 0x9b,
+-			0xce, 0x8a, 0xba, 0xda, 0xbe, 0x28, 0x08, 0xf7,
+-			0xe2, 0x14, 0x8c, 0x71, 0xea, 0x72, 0xf9, 0x33,
+-			0xf2, 0x88, 0x3f, 0xd7, 0xbb, 0x69, 0x6c, 0x29,
+-			0x19, 0xdc, 0x84, 0xce, 0x1f, 0x12, 0x4f, 0xc8,
+-			0xaf, 0xa5, 0x04, 0xba, 0x5a, 0xab, 0xb0, 0xd9,
+-			0x14, 0x1f, 0x6c, 0x68, 0x98, 0x39, 0x89, 0x7a,
+-			0xd9, 0xd8, 0x2f, 0xdf, 0xa8, 0x47, 0x4a, 0x25,
+-			0xe2, 0xfb, 0x33, 0xf4, 0x59, 0x78, 0xe1, 0x68,
+-			0x85, 0xcf, 0xfe, 0x59, 0x20, 0xd4, 0x05, 0x1d,
+-			0x80, 0x99, 0xae, 0xbc, 0xca, 0xae, 0x0f, 0x2f,
+-			0x65, 0x43, 0x34, 0x8e, 0x7e, 0xac, 0xd3, 0x93,
+-			0x2f, 0xac, 0x6d, 0x14, 0x3d, 0x02, 0x07, 0x70,
+-			0x9d, 0xa4, 0xf3, 0x1b, 0x5c, 0x36, 0xfc, 0x01,
+-			0x73, 0x34, 0x85, 0x0c, 0x6c, 0xd6, 0xf1, 0xbd,
+-			0x3f, 0xdf, 0xee, 0xf5, 0xd9, 0xba, 0x56, 0xef,
+-			0xf4, 0x9b, 0x6b, 0xee, 0x9f, 0x5a, 0x78, 0x6d,
+-			0x32, 0x19, 0xf4, 0xf7, 0xf8, 0x4c, 0x69, 0x0b,
+-			0x4b, 0xbc, 0xbb, 0xb7, 0xf2, 0x85, 0xaf, 0x70,
+-			0x75, 0x24, 0x6c, 0x54, 0xa7, 0x0e, 0x4d, 0x1d,
+-			0x01, 0xbf, 0x08, 0xac, 0xcf, 0x7f, 0x2c, 0xe3,
+-			0x14, 0x89, 0x5e, 0x70, 0x5a, 0x99, 0x92, 0xcd,
+-			0x01, 0x84, 0xc8, 0xd2, 0xab, 0xe5, 0x4f, 0x58,
+-			0xe7, 0x0f, 0x2f, 0x0e, 0xff, 0x68, 0xea, 0xfd,
+-			0x15, 0xb3, 0x17, 0xe6, 0xb0, 0xe7, 0x85, 0xd8,
+-			0x23, 0x2e, 0x05, 0xc7, 0xc9, 0xc4, 0x46, 0x1f,
+-			0xe1, 0x9e, 0x49, 0x20, 0x23, 0x24, 0x4d, 0x7e,
+-			0x29, 0x65, 0xff, 0xf4, 0xb6, 0xfd, 0x1a, 0x85,
+-			0xc4, 0x16, 0xec, 0xfc, 0xea, 0x7b, 0xd6, 0x2c,
+-			0x43, 0xf8, 0xb7, 0xbf, 0x79, 0xc0, 0x85, 0xcd,
+-			0xef, 0xe1, 0x98, 0xd3, 0xa5, 0xf7, 0x90, 0x8c,
+-			0xe9, 0x7f, 0x80, 0x6b, 0xd2, 0xac, 0x4c, 0x30,
+-			0xa7, 0xc6, 0x61, 0x6c, 0xd2, 0xf9, 0x2c, 0xff,
+-			0x30, 0xbc, 0x22, 0x81, 0x7d, 0x93, 0x12, 0xe4,
+-			0x0a, 0xcd, 0xaf, 0xdd, 0xe8, 0xab, 0x0a, 0x1e,
+-			0x13, 0xa4, 0x27, 0xc3, 0x5f, 0xf7, 0x4b, 0xbb,
+-			0x37, 0x09, 0x4b, 0x91, 0x6f, 0x92, 0x4f, 0xaf,
+-			0x52, 0xee, 0xdf, 0xef, 0x09, 0x6f, 0xf7, 0x5c,
+-			0x6e, 0x12, 0x17, 0x72, 0x63, 0x57, 0xc7, 0xba,
+-			0x3b, 0x6b, 0x38, 0x32, 0x73, 0x1b, 0x9c, 0x80,
+-			0xc1, 0x7a, 0xc6, 0xcf, 0xcd, 0x35, 0xc0, 0x6b,
+-			0x31, 0x1a, 0x6b, 0xe9, 0xd8, 0x2c, 0x29, 0x3f,
+-			0x96, 0xfb, 0xb6, 0xcd, 0x13, 0x91, 0x3b, 0xc2,
+-			0xd2, 0xa3, 0x31, 0x8d, 0xa4, 0xcd, 0x57, 0xcd,
+-			0x13, 0x3d, 0x64, 0xfd, 0x06, 0xce, 0xe6, 0xdc,
+-			0x0c, 0x24, 0x43, 0x31, 0x40, 0x57, 0xf1, 0x72,
+-			0x17, 0xe3, 0x3a, 0x63, 0x6d, 0x35, 0xcf, 0x5d,
+-			0x97, 0x40, 0x59, 0xdd, 0xf7, 0x3c, 0x02, 0xf7,
+-			0x1c, 0x7e, 0x05, 0xbb, 0xa9, 0x0d, 0x01, 0xb1,
+-			0x8e, 0xc0, 0x30, 0xa9, 0x53, 0x24, 0xc9, 0x89,
+-			0x84, 0x6d, 0xaa, 0xd0, 0xcd, 0x91, 0xc2, 0x4d,
+-			0x91, 0xb0, 0x89, 0xe2, 0xbf, 0x83, 0x44, 0xaa,
+-			0x28, 0x72, 0x23, 0xa0, 0xc2, 0xad, 0xad, 0x1c,
+-			0xfc, 0x3f, 0x09, 0x7a, 0x0b, 0xdc, 0xc5, 0x1b,
+-			0x87, 0x13, 0xc6, 0x5b, 0x59, 0x8d, 0xf2, 0xc8,
+-			0xaf, 0xdf, 0x11, 0x95,
+-		},
++		.result =
++			"\xb5\x81\xf5\x64\x18\x73\xe3\xf0"
++			"\x4c\x13\xf2\x77\x18\x60\x65\x5e"
++			"\x29\x01\xce\x98\x55\x53\xf9\x0c"
++			"\x2a\x08\xd5\x09\xb3\x57\x55\x56"
++			"\xc5\xe9\x56\x90\xcb\x6a\xa3\xc0"
++			"\xff\xc4\x79\xb4\xd2\x97\x5d\xc4"
++			"\x43\xd1\xfe\x94\x7b\x88\x06\x5a"
++			"\xb2\x9e\x2c\xfc\x44\x03\xb7\x90"
++			"\xa0\xc1\xba\x6a\x33\xb8\xc7\xb2"
++			"\x9d\xe1\x12\x4f\xc0\x64\xd4\x01"
++			"\xfe\x8c\x7a\x66\xf7\xe6\x5a\x91"
++			"\xbb\xde\x56\x86\xab\x65\x21\x30"
++			"\x00\x84\x65\x24\xa5\x7d\x85\xb4"
++			"\xe3\x17\xed\x3a\xb7\x6f\xb4\x0b"
++			"\x0b\xaf\x15\xae\x5a\x8f\xf2\x0c"
++			"\x2f\x27\xf4\x09\xd8\xd2\x96\xb7"
++			"\x71\xf2\xc5\x99\x4d\x7e\x7f\x75"
++			"\x77\x89\x30\x8b\x59\xdb\xa2\xb2"
++			"\xa0\xf3\x19\x39\x2b\xc5\x7e\x3f"
++			"\x4f\xd9\xd3\x56\x28\x97\x44\xdc"
++			"\xc0\x8b\x77\x24\xd9\x52\xe7\xc5"
++			"\xaf\xf6\x7d\x59\xb2\x44\x05\x1d"
++			"\xb1\xb0\x11\xa5\x0f\xec\x33\xe1"
++			"\x6d\x1b\x4e\x1f\xff\x57\x91\xb4"
++			"\x5b\x9a\x96\xc5\x53\xbc\xae\x20"
++			"\x3c\xbb\x14\xe2\xe8\x22\x33\xc1"
++			"\x5e\x76\x9e\x46\x99\xf6\x2a\x15"
++			"\xc6\x97\x02\xa0\x66\x43\xd1\xa6"
++			"\x31\xa6\x9f\xfb\xf4\xd3\x69\xe5"
++			"\xcd\x76\x95\xb8\x7a\x82\x7f\x21"
++			"\x45\xff\x3f\xce\x55\xf6\x95\x10"
++			"\x08\x77\x10\x43\xc6\xf3\x09\xe5"
++			"\x68\xe7\x3c\xad\x00\x52\x45\x0d"
++			"\xfe\x2d\xc6\xc2\x94\x8c\x12\x1d"
++			"\xe6\x25\xae\x98\x12\x8e\x19\x9c"
++			"\x81\x68\xb1\x11\xf6\x69\xda\xe3"
++			"\x62\x08\x18\x7a\x25\x49\x28\xac"
++			"\xba\x71\x12\x0b\xe4\xa2\xe5\xc7"
++			"\x5d\x8e\xec\x49\x40\x21\xbf\x5a"
++			"\x98\xf3\x02\x68\x55\x03\x7f\x8a"
++			"\xe5\x94\x0c\x32\x5c\x07\x82\x63"
++			"\xaf\x6f\x91\x40\x84\x8e\x52\x25"
++			"\xd0\xb0\x29\x53\x05\xe2\x50\x7a"
++			"\x34\xeb\xc9\x46\x20\xa8\x3d\xde"
++			"\x7f\x16\x5f\x36\xc5\x2e\xdc\xd1"
++			"\x15\x47\xc7\x50\x40\x6d\x91\xc5"
++			"\xe7\x93\x95\x1a\xd3\x57\xbc\x52"
++			"\x33\xee\x14\x19\x22\x52\x89\xa7"
++			"\x4a\x25\x56\x77\x4b\xca\xcf\x0a"
++			"\xe1\xf5\x35\x85\x30\x7e\x59\x4a"
++			"\xbd\x14\x5b\xdf\xe3\x46\xcb\xac"
++			"\x1f\x6c\x96\x0e\xf4\x81\xd1\x99"
++			"\xca\x88\x63\x3d\x02\x58\x6b\xa9"
++			"\xe5\x9f\xb3\x00\xb2\x54\xc6\x74"
++			"\x1c\xbf\x46\xab\x97\xcc\xf8\x54"
++			"\x04\x07\x08\x52\xe6\xc0\xda\x93"
++			"\x74\x7d\x93\x99\x5d\x78\x68\xa6"
++			"\x2e\x6b\xd3\x6a\x69\xcc\x12\x6b"
++			"\xd4\xc7\xa5\xc6\xe7\xf6\x03\x04"
++			"\x5d\xcd\x61\x5e\x17\x40\xdc\xd1"
++			"\x5c\xf5\x08\xdf\x5c\x90\x85\xa4"
++			"\xaf\xf6\x78\xbb\x0d\xf1\xf4\xa4"
++			"\x54\x26\x72\x9e\x61\xfa\x86\xcf"
++			"\xe8\x9e\xa1\xe0\xc7\x48\x23\xae"
++			"\x5a\x90\xae\x75\x0a\x74\x18\x89"
++			"\x05\xb1\x92\xb2\x7f\xd0\x1b\xa6"
++			"\x62\x07\x25\x01\xc7\xc2\x4f\xf9"
++			"\xe8\xfe\x63\x95\x80\x07\xb4\x26"
++			"\xcc\xd1\x26\xb6\xc4\x3f\x9e\xcb"
++			"\x8e\x3b\x2e\x44\x16\xd3\x10\x9a"
++			"\x95\x08\xeb\xc8\xcb\xeb\xbf\x6f"
++			"\x0b\xcd\x1f\xc8\xca\x86\xaa\xec"
++			"\x33\xe6\x69\xf4\x45\x25\x86\x3a"
++			"\x22\x94\x4f\x00\x23\x6a\x44\xc2"
++			"\x49\x97\x33\xab\x36\x14\x0a\x70"
++			"\x24\xc3\xbe\x04\x3b\x79\xa0\xf9"
++			"\xb8\xe7\x76\x29\x22\x83\xd7\xf2"
++			"\x94\xf4\x41\x49\xba\x5f\x7b\x07"
++			"\xb5\xfb\xdb\x03\x1a\x9f\xb6\x4c"
++			"\xc2\x2e\x37\x40\x49\xc3\x38\x16"
++			"\xe2\x4f\x77\x82\xb0\x68\x4c\x71"
++			"\x1d\x57\x61\x9c\xd9\x4e\x54\x99"
++			"\x47\x13\x28\x73\x3c\xbb\x00\x90"
++			"\xf3\x4d\xc9\x0e\xfd\xe7\xb1\x71"
++			"\xd3\x15\x79\xbf\xcc\x26\x2f\xbd"
++			"\xad\x6c\x50\x69\x6c\x3e\x6d\x80"
++			"\x9a\xea\x78\xaf\x19\xb2\x0d\x4d"
++			"\xad\x04\x07\xae\x22\x90\x4a\x93"
++			"\x32\x0e\x36\x9b\x1b\x46\xba\x3b"
++			"\xb4\xac\xc6\xd1\xa2\x31\x53\x3b"
++			"\x2a\x3d\x45\xfe\x03\x61\x10\x85"
++			"\x17\x69\xa6\x78\xcc\x6c\x87\x49"
++			"\x53\xf9\x80\x10\xde\x80\xa2\x41"
++			"\x6a\xc3\x32\x02\xad\x6d\x3c\x56"
++			"\x00\x71\x51\x06\xa7\xbd\xfb\xef"
++			"\x3c\xb5\x9f\xfc\x48\x7d\x53\x7c"
++			"\x66\xb0\x49\x23\xc4\x47\x10\x0e"
++			"\xe5\x6c\x74\x13\xe6\xc5\x3f\xaa"
++			"\xde\xff\x07\x44\xdd\x56\x1b\xad"
++			"\x09\x77\xfb\x5b\x12\xb8\x0d\x38"
++			"\x17\x37\x35\x7b\x9b\xbc\xfe\xd4"
++			"\x7e\x8b\xda\x7e\x5b\x04\xa7\x22"
++			"\xa7\x31\xa1\x20\x86\xc7\x1b\x99"
++			"\xdb\xd1\x89\xf4\x94\xa3\x53\x69"
++			"\x8d\xe7\xe8\x74\x11\x8d\x74\xd6"
++			"\x07\x37\x91\x9f\xfd\x67\x50\x3a"
++			"\xc9\xe1\xf4\x36\xd5\xa0\x47\xd1"
++			"\xf9\xe5\x39\xa3\x31\xac\x07\x36"
++			"\x23\xf8\x66\x18\x14\x28\x34\x0f"
++			"\xb8\xd0\xe7\x29\xb3\x04\x4b\x55"
++			"\x01\x41\xb2\x75\x8d\xcb\x96\x85"
++			"\x3a\xfb\xab\x2b\x9e\xfa\x58\x20"
++			"\x44\x1f\xc0\x14\x22\x75\x61\xe8"
++			"\xaa\x19\xcf\xf1\x82\x56\xf4\xd7"
++			"\x78\x7b\x3d\x5f\xb3\x9e\x0b\x8a"
++			"\x57\x50\xdb\x17\x41\x65\x4d\xa3"
++			"\x02\xc9\x9c\x9c\x53\xfb\x39\x39"
++			"\x9b\x1d\x72\x24\xda\xb7\x39\xbe"
++			"\x13\x3b\xfa\x29\xda\x9e\x54\x64"
++			"\x6e\xba\xd8\xa1\xcb\xb3\x36\xfa"
++			"\xcb\x47\x85\xe9\x61\x38\xbc\xbe"
++			"\xc5\x00\x38\x2a\x54\xf7\xc4\xb9"
++			"\xb3\xd3\x7b\xa0\xa0\xf8\x72\x7f"
++			"\x8c\x8e\x82\x0e\xc6\x1c\x75\x9d"
++			"\xca\x8e\x61\x87\xde\xad\x80\xd2"
++			"\xf5\xf9\x80\xef\x15\x75\xaf\xf5"
++			"\x80\xfb\xff\x6d\x1e\x25\xb7\x40"
++			"\x61\x6a\x39\x5a\x6a\xb5\x31\xab"
++			"\x97\x8a\x19\x89\x44\x40\xc0\xa6"
++			"\xb4\x4e\x30\x32\x7b\x13\xe7\x67"
++			"\xa9\x8b\x57\x04\xc2\x01\xa6\xf4"
++			"\x28\x99\xad\x2c\x76\xa3\x78\xc2"
++			"\x4a\xe6\xca\x5c\x50\x6a\xc1\xb0"
++			"\x62\x4b\x10\x8e\x7c\x17\x43\xb3"
++			"\x17\x66\x1c\x3e\x8d\x69\xf0\x5a"
++			"\x71\xf5\x97\xdc\xd1\x45\xdd\x28"
++			"\xf3\x5d\xdf\x53\x7b\x11\xe5\xbc"
++			"\x4c\xdb\x1b\x51\x6b\xe9\xfb\x3d"
++			"\xc1\xc3\x2c\xb9\x71\xf5\xb6\xb2"
++			"\x13\x36\x79\x80\x53\xe8\xd3\xa6"
++			"\x0a\xaf\xfd\x56\x97\xf7\x40\x8e"
++			"\x45\xce\xf8\xb0\x9e\x5c\x33\x82"
++			"\xb0\x44\x56\xfc\x05\x09\xe9\x2a"
++			"\xac\x26\x80\x14\x1d\xc8\x3a\x35"
++			"\x4c\x82\x97\xfd\x76\xb7\xa9\x0a"
++			"\x35\x58\x79\x8e\x0f\x66\xea\xaf"
++			"\x51\x6c\x09\xa9\x6e\x9b\xcb\x9a"
++			"\x31\x47\xa0\x2f\x7c\x71\xb4\x4a"
++			"\x11\xaa\x8c\x66\xc5\x64\xe6\x3a"
++			"\x54\xda\x24\x6a\xc4\x41\x65\x46"
++			"\x82\xa0\x0a\x0f\x5f\xfb\x25\xd0"
++			"\x2c\x91\xa7\xee\xc4\x81\x07\x86"
++			"\x75\x5e\x33\x69\x97\xe4\x2c\xa8"
++			"\x9d\x9f\x0b\x6a\xbe\xad\x98\xda"
++			"\x6d\x94\x41\xda\x2c\x1e\x89\xc4"
++			"\xc2\xaf\x1e\x00\x05\x0b\x83\x60"
++			"\xbd\x43\xea\x15\x23\x7f\xb9\xac"
++			"\xee\x4f\x2c\xaf\x2a\xf3\xdf\xd0"
++			"\xf3\x19\x31\xbb\x4a\x74\x84\x17"
++			"\x52\x32\x2c\x7d\x61\xe4\xcb\xeb"
++			"\x80\x38\x15\x52\xcb\x6f\xea\xe5"
++			"\x73\x9c\xd9\x24\x69\xc6\x95\x32"
++			"\x21\xc8\x11\xe4\xdc\x36\xd7\x93"
++			"\x38\x66\xfb\xb2\x7f\x3a\xb9\xaf"
++			"\x31\xdd\x93\x75\x78\x8a\x2c\x94"
++			"\x87\x1a\x58\xec\x9e\x7d\x4d\xba"
++			"\xe1\xe5\x4d\xfc\xbc\xa4\x2a\x14"
++			"\xef\xcc\xa7\xec\xab\x43\x09\x18"
++			"\xd3\xab\x68\xd1\x07\x99\x44\x47"
++			"\xd6\x83\x85\x3b\x30\xea\xa9\x6b"
++			"\x63\xea\xc4\x07\xfb\x43\x2f\xa4"
++			"\xaa\xb0\xab\x03\x89\xce\x3f\x8c"
++			"\x02\x7c\x86\x54\xbc\x88\xaf\x75"
++			"\xd2\xdc\x63\x17\xd3\x26\xf6\x96"
++			"\xa9\x3c\xf1\x61\x8c\x11\x18\xcc"
++			"\xd6\xea\x5b\xe2\xcd\xf0\xf1\xb2"
++			"\xe5\x35\x90\x1f\x85\x4c\x76\x5b"
++			"\x66\xce\x44\xa4\x32\x9f\xe6\x7b"
++			"\x71\x6e\x9f\x58\x15\x67\x72\x87"
++			"\x64\x8e\x3a\x44\x45\xd4\x76\xfa"
++			"\xc2\xf6\xef\x85\x05\x18\x7a\x9b"
++			"\xba\x41\x54\xac\xf0\xfc\x59\x12"
++			"\x3f\xdf\xa0\xe5\x8a\x65\xfd\x3a"
++			"\x62\x8d\x83\x2c\x03\xbe\x05\x76"
++			"\x2e\x53\x49\x97\x94\x33\xae\x40"
++			"\x81\x15\xdb\x6e\xad\xaa\xf5\x4b"
++			"\xe3\x98\x70\xdf\xe0\x7c\xcd\xdb"
++			"\x02\xd4\x7d\x2f\xc1\xe6\xb4\xf3"
++			"\xd7\x0d\x7a\xd9\x23\x9e\x87\x2d"
++			"\xce\x87\xad\xcc\x72\x05\x00\x29"
++			"\xdc\x73\x7f\x64\xc1\x15\x0e\xc2"
++			"\xdf\xa7\x5f\xeb\x41\xa1\xcd\xef"
++			"\x5c\x50\x79\x2a\x56\x56\x71\x8c"
++			"\xac\xc0\x79\x50\x69\xca\x59\x32"
++			"\x65\xf2\x54\xe4\x52\x38\x76\xd1"
++			"\x5e\xde\x26\x9e\xfb\x75\x2e\x11"
++			"\xb5\x10\xf4\x17\x73\xf5\x89\xc7"
++			"\x4f\x43\x5c\x8e\x7c\xb9\x05\x52"
++			"\x24\x40\x99\xfe\x9b\x85\x0b\x6c"
++			"\x22\x3e\x8b\xae\x86\xa1\xd2\x79"
++			"\x05\x68\x6b\xab\xe3\x41\x49\xed"
++			"\x15\xa1\x8d\x40\x2d\x61\xdf\x1a"
++			"\x59\xc9\x26\x8b\xef\x30\x4c\x88"
++			"\x4b\x10\xf8\x8d\xa6\x92\x9f\x4b"
++			"\xf3\xc4\x53\x0b\x89\x5d\x28\x92"
++			"\xcf\x78\xb2\xc0\x5d\xed\x7e\xfc"
++			"\xc0\x12\x23\x5f\x5a\x78\x86\x43"
++			"\x6e\x27\xf7\x5a\xa7\x6a\xed\x19"
++			"\x04\xf0\xb3\x12\xd1\xbd\x0e\x89"
++			"\x6e\xbc\x96\xa8\xd8\x49\x39\x9f"
++			"\x7e\x67\xf0\x2e\x3e\x01\xa9\xba"
++			"\xec\x8b\x62\x8e\xcb\x4a\x70\x43"
++			"\xc7\xc2\xc4\xca\x82\x03\x73\xe9"
++			"\x11\xdf\xcf\x54\xea\xc9\xb0\x95"
++			"\x51\xc0\x13\x3d\x92\x05\xfa\xf4"
++			"\xa9\x34\xc8\xce\x6c\x3d\x54\xcc"
++			"\xc4\xaf\xf1\xdc\x11\x44\x26\xa2"
++			"\xaf\xf1\x85\x75\x7d\x03\x61\x68"
++			"\x4e\x78\xc6\x92\x7d\x86\x7d\x77"
++			"\xdc\x71\x72\xdb\xc6\xae\xa1\xcb"
++			"\x70\x9a\x0b\x19\xbe\x4a\x6c\x2a"
++			"\xe2\xba\x6c\x64\x9a\x13\x28\xdf"
++			"\x85\x75\xe6\x43\xf6\x87\x08\x68"
++			"\x6e\xba\x6e\x79\x9f\x04\xbc\x23"
++			"\x50\xf6\x33\x5c\x1f\x24\x25\xbe"
++			"\x33\x47\x80\x45\x56\xa3\xa7\xd7"
++			"\x7a\xb1\x34\x0b\x90\x3c\x9c\xad"
++			"\x44\x5f\x9e\x0e\x9d\xd4\xbd\x93"
++			"\x5e\xfa\x3c\xe0\xb0\xd9\xed\xf3"
++			"\xd6\x2e\xff\x24\xd8\x71\x6c\xed"
++			"\xaf\x55\xeb\x22\xac\x93\x68\x32"
++			"\x05\x5b\x47\xdd\xc6\x4a\xcb\xc7"
++			"\x10\xe1\x3c\x92\x1a\xf3\x23\x78"
++			"\x2b\xa1\xd2\x80\xf4\x12\xb1\x20"
++			"\x8f\xff\x26\x35\xdd\xfb\xc7\x4e"
++			"\x78\xf1\x2d\x50\x12\x77\xa8\x60"
++			"\x7c\x0f\xf5\x16\x2f\x63\x70\x2a"
++			"\xc0\x96\x80\x4e\x0a\xb4\x93\x35"
++			"\x5d\x1d\x3f\x56\xf7\x2f\xbb\x90"
++			"\x11\x16\x8f\xa2\xec\x47\xbe\xac"
++			"\x56\x01\x26\x56\xb1\x8c\xb2\x10"
++			"\xf9\x1a\xca\xf5\xd1\xb7\x39\x20"
++			"\x63\xf1\x69\x20\x4f\x13\x12\x1f"
++			"\x5b\x65\xfc\x98\xf7\xc4\x7a\xbe"
++			"\xf7\x26\x4d\x2b\x84\x7b\x42\xad"
++			"\xd8\x7a\x0a\xb4\xd8\x74\xbf\xc1"
++			"\xf0\x6e\xb4\x29\xa3\xbb\xca\x46"
++			"\x67\x70\x6a\x2d\xce\x0e\xa2\x8a"
++			"\xa9\x87\xbf\x05\xc4\xc1\x04\xa3"
++			"\xab\xd4\x45\x43\x8c\xb6\x02\xb0"
++			"\x41\xc8\xfc\x44\x3d\x59\xaa\x2e"
++			"\x44\x21\x2a\x8d\x88\x9d\x57\xf4"
++			"\xa0\x02\x77\xb8\xa6\xa0\xe6\x75"
++			"\x5c\x82\x65\x3e\x03\x5c\x29\x8f"
++			"\x38\x55\xab\x33\x26\xef\x9f\x43"
++			"\x52\xfd\x68\xaf\x36\xb4\xbb\x9a"
++			"\x58\x09\x09\x1b\xc3\x65\x46\x46"
++			"\x1d\xa7\x94\x18\x23\x50\x2c\xca"
++			"\x2c\x55\x19\x97\x01\x9d\x93\x3b"
++			"\x63\x86\xf2\x03\x67\x45\xd2\x72"
++			"\x28\x52\x6c\xf4\xe3\x1c\xb5\x11"
++			"\x13\xf1\xeb\x21\xc7\xd9\x56\x82"
++			"\x2b\x82\x39\xbd\x69\x54\xed\x62"
++			"\xc3\xe2\xde\x73\xd4\x6a\x12\xae"
++			"\x13\x21\x7f\x4b\x5b\xfc\xbf\xe8"
++			"\x2b\xbe\x56\xba\x68\x8b\x9a\xb1"
++			"\x6e\xfa\xbf\x7e\x5a\x4b\xf1\xac"
++			"\x98\x65\x85\xd1\x93\x53\xd3\x7b"
++			"\x09\xdd\x4b\x10\x6d\x84\xb0\x13"
++			"\x65\xbd\xcf\x52\x09\xc4\x85\xe2"
++			"\x84\x74\x15\x65\xb7\xf7\x51\xaf"
++			"\x55\xad\xa4\xd1\x22\x54\x70\x94"
++			"\xa0\x1c\x90\x41\xfd\x99\xd7\x5a"
++			"\x31\xef\xaa\x25\xd0\x7f\x4f\xea"
++			"\x1d\x55\x42\xe5\x49\xb0\xd0\x46"
++			"\x62\x36\x43\xb2\x82\x15\x75\x50"
++			"\xa4\x72\xeb\x54\x27\x1f\x8a\xe4"
++			"\x7d\xe9\x66\xc5\xf1\x53\xa4\xd1"
++			"\x0c\xeb\xb8\xf8\xbc\xd4\xe2\xe7"
++			"\xe1\xf8\x4b\xcb\xa9\xa1\xaf\x15"
++			"\x83\xcb\x72\xd0\x33\x79\x00\x2d"
++			"\x9f\xd7\xf1\x2e\x1e\x10\xe4\x45"
++			"\xc0\x75\x3a\x39\xea\x68\xf7\x5d"
++			"\x1b\x73\x8f\xe9\x8e\x0f\x72\x47"
++			"\xae\x35\x0a\x31\x7a\x14\x4d\x4a"
++			"\x6f\x47\xf7\x7e\x91\x6e\x74\x8b"
++			"\x26\x47\xf9\xc3\xf9\xde\x70\xf5"
++			"\x61\xab\xa9\x27\x9f\x82\xe4\x9c"
++			"\x89\x91\x3f\x2e\x6a\xfd\xb5\x49"
++			"\xe9\xfd\x59\x14\x36\x49\x40\x6d"
++			"\x32\xd8\x85\x42\xf3\xa5\xdf\x0c"
++			"\xa8\x27\xd7\x54\xe2\x63\x2f\xf2"
++			"\x7e\x8b\x8b\xe7\xf1\x9a\x95\x35"
++			"\x43\xdc\x3a\xe4\xb6\xf4\xd0\xdf"
++			"\x9c\xcb\x94\xf3\x21\xa0\x77\x50"
++			"\xe2\xc6\xc4\xc6\x5f\x09\x64\x5b"
++			"\x92\x90\xd8\xe1\xd1\xed\x4b\x42"
++			"\xd7\x37\xaf\x65\x3d\x11\x39\xb6"
++			"\x24\x8a\x60\xae\xd6\x1e\xbf\x0e"
++			"\x0d\xd7\xdc\x96\x0e\x65\x75\x4e"
++			"\x29\x06\x9d\xa4\x51\x3a\x10\x63"
++			"\x8f\x17\x07\xd5\x8e\x3c\xf4\x28"
++			"\x00\x5a\x5b\x05\x19\xd8\xc0\x6c"
++			"\xe5\x15\xe4\x9c\x9d\x71\x9d\x5e"
++			"\x94\x29\x1a\xa7\x80\xfa\x0e\x33"
++			"\x03\xdd\xb7\x3e\x9a\xa9\x26\x18"
++			"\x37\xa9\x64\x08\x4d\x94\x5a\x88"
++			"\xca\x35\xce\x81\x02\xe3\x1f\x1b"
++			"\x89\x1a\x77\x85\xe3\x41\x6d\x32"
++			"\x42\x19\x23\x7d\xc8\x73\xee\x25"
++			"\x85\x0d\xf8\x31\x25\x79\x1b\x6f"
++			"\x79\x25\xd2\xd8\xd4\x23\xfd\xf7"
++			"\x82\x36\x6a\x0c\x46\x22\x15\xe9"
++			"\xff\x72\x41\x91\x91\x7d\x3a\xb7"
++			"\xdd\x65\x99\x70\xf6\x8d\x84\xf8"
++			"\x67\x15\x20\x11\xd6\xb2\x55\x7b"
++			"\xdb\x87\xee\xef\x55\x89\x2a\x59"
++			"\x2b\x07\x8f\x43\x8a\x59\x3c\x01"
++			"\x8b\x65\x54\xa1\x66\xd5\x38\xbd"
++			"\xc6\x30\xa9\xcc\x49\xb6\xa8\x1b"
++			"\xb8\xc0\x0e\xe3\x45\x28\xe2\xff"
++			"\x41\x9f\x7e\x7c\xd1\xae\x9e\x25"
++			"\x3f\x4c\x7c\x7c\xf4\xa8\x26\x4d"
++			"\x5c\xfd\x4b\x27\x18\xf9\x61\x76"
++			"\x48\xba\x0c\x6b\xa9\x4d\xfc\xf5"
++			"\x3b\x35\x7e\x2f\x4a\xa9\xc2\x9a"
++			"\xae\xab\x86\x09\x89\xc9\xc2\x40"
++			"\x39\x2c\x81\xb3\xb8\x17\x67\xc2"
++			"\x0d\x32\x4a\x3a\x67\x81\xd7\x1a"
++			"\x34\x52\xc5\xdb\x0a\xf5\x63\x39"
++			"\xea\x1f\xe1\x7c\xa1\x9e\xc1\x35"
++			"\xe3\xb1\x18\x45\x67\xf9\x22\x38"
++			"\x95\xd9\x34\x34\x86\xc6\x41\x94"
++			"\x15\xf9\x5b\x41\xa6\x87\x8b\xf8"
++			"\xd5\xe1\x1b\xe2\x5b\xf3\x86\x10"
++			"\xff\xe6\xae\x69\x76\xbc\x0d\xb4"
++			"\x09\x90\x0c\xa2\x65\x0c\xad\x74"
++			"\xf5\xd7\xff\xda\xc1\xce\x85\xbe"
++			"\x00\xa7\xff\x4d\x2f\x65\xd3\x8c"
++			"\x86\x2d\x05\xe8\xed\x3e\x6b\x8b"
++			"\x0f\x3d\x83\x8c\xf1\x1d\x5b\x96"
++			"\x2e\xb1\x9c\xc2\x98\xe1\x70\xb9"
++			"\xba\x5c\x8a\x43\xd6\x34\xa7\x2d"
++			"\xc9\x92\xae\xf2\xa5\x7b\x05\x49"
++			"\xa7\x33\x34\x86\xca\xe4\x96\x23"
++			"\x76\x5b\xf2\xc6\xf1\x51\x28\x42"
++			"\x7b\xcc\x76\x8f\xfa\xa2\xad\x31"
++			"\xd4\xd6\x7a\x6d\x25\x25\x54\xe4"
++			"\x3f\x50\x59\xe1\x5c\x05\xb7\x27"
++			"\x48\xbf\x07\xec\x1b\x13\xbe\x2b"
++			"\xa1\x57\x2b\xd5\xab\xd7\xd0\x4c"
++			"\x1e\xcb\x71\x9b\xc5\x90\x85\xd3"
++			"\xde\x59\xec\x71\xeb\x89\xbb\xd0"
++			"\x09\x50\xe1\x16\x3f\xfd\x1c\x34"
++			"\xc3\x1c\xa1\x10\x77\x53\x98\xef"
++			"\xf2\xfd\xa5\x01\x59\xc2\x9b\x26"
++			"\xc7\x42\xd9\x49\xda\x58\x2b\x6e"
++			"\x9f\x53\x19\x76\x7e\xd9\xc9\x0e"
++			"\x68\xc8\x7f\x51\x22\x42\xef\x49"
++			"\xa4\x55\xb6\x36\xac\x09\xc7\x31"
++			"\x88\x15\x4b\x2e\x8f\x3a\x08\xf7"
++			"\xd8\xf7\xa8\xc5\xa9\x33\xa6\x45"
++			"\xe4\xc4\x94\x76\xf3\x0d\x8f\x7e"
++			"\xc8\xf6\xbc\x23\x0a\xb6\x4c\xd3"
++			"\x6a\xcd\x36\xc2\x90\x5c\x5c\x3c"
++			"\x65\x7b\xc2\xd6\xcc\xe6\x0d\x87"
++			"\x73\x2e\x71\x79\x16\x06\x63\x28"
++			"\x09\x15\xd8\x89\x38\x38\x3d\xb5"
++			"\x42\x1c\x08\x24\xf7\x2a\xd2\x9d"
++			"\xc8\xca\xef\xf9\x27\xd8\x07\x86"
++			"\xf7\x43\x0b\x55\x15\x3f\x9f\x83"
++			"\xef\xdc\x49\x9d\x2a\xc1\x54\x62"
++			"\xbd\x9b\x66\x55\x9f\xb7\x12\xf3"
++			"\x1b\x4d\x9d\x2a\x5c\xed\x87\x75"
++			"\x87\x26\xec\x61\x2c\xb4\x0f\x89"
++			"\xb0\xfb\x2e\x68\x5d\x15\xc7\x8d"
++			"\x2e\xc0\xd9\xec\xaf\x4f\xd2\x25"
++			"\x29\xe8\xd2\x26\x2b\x67\xe9\xfc"
++			"\x2b\xa8\x67\x96\x12\x1f\x5b\x96"
++			"\xc6\x14\x53\xaf\x44\xea\xd6\xe2"
++			"\x94\x98\xe4\x12\x93\x4c\x92\xe0"
++			"\x18\xa5\x8d\x2d\xe4\x71\x3c\x47"
++			"\x4c\xf7\xe6\x47\x9e\xc0\x68\xdf"
++			"\xd4\xf5\x5a\x74\xb1\x2b\x29\x03"
++			"\x19\x07\xaf\x90\x62\x5c\x68\x98"
++			"\x48\x16\x11\x02\x9d\xee\xb4\x9b"
++			"\xe5\x42\x7f\x08\xfd\x16\x32\x0b"
++			"\xd0\xb3\xfa\x2b\xb7\x99\xf9\x29"
++			"\xcd\x20\x45\x9f\xb3\x1a\x5d\xa2"
++			"\xaf\x4d\xe0\xbd\x42\x0d\xbc\x74"
++			"\x99\x9c\x8e\x53\x1a\xb4\x3e\xbd"
++			"\xa2\x9a\x2d\xf7\xf8\x39\x0f\x67"
++			"\x63\xfc\x6b\xc0\xaf\xb3\x4b\x4f"
++			"\x55\xc4\xcf\xa7\xc8\x04\x11\x3e"
++			"\x14\x32\xbb\x1b\x38\x77\xd6\x7f"
++			"\x54\x4c\xdf\x75\xf3\x07\x2d\x33"
++			"\x9b\xa8\x20\xe1\x7b\x12\xb5\xf3"
++			"\xef\x2f\xce\x72\xe5\x24\x60\xc1"
++			"\x30\xe2\xab\xa1\x8e\x11\x09\xa8"
++			"\x21\x33\x44\xfe\x7f\x35\x32\x93"
++			"\x39\xa7\xad\x8b\x79\x06\xb2\xcb"
++			"\x4e\xa9\x5f\xc7\xba\x74\x29\xec"
++			"\x93\xa0\x4e\x54\x93\xc0\xbc\x55"
++			"\x64\xf0\x48\xe5\x57\x99\xee\x75"
++			"\xd6\x79\x0f\x66\xb7\xc6\x57\x76"
++			"\xf7\xb7\xf3\x9c\xc5\x60\xe8\x7f"
++			"\x83\x76\xd6\x0e\xaa\xe6\x90\x39"
++			"\x1d\xa6\x32\x6a\x34\xe3\x55\xf8"
++			"\x58\xa0\x58\x7d\x33\xe0\x22\x39"
++			"\x44\x64\x87\x86\x5a\x2f\xa7\x7e"
++			"\x0f\x38\xea\xb0\x30\xcc\x61\xa5"
++			"\x6a\x32\xae\x1e\xf7\xe9\xd0\xa9"
++			"\x0c\x32\x4b\xb5\x49\x28\xab\x85"
++			"\x2f\x8e\x01\x36\x38\x52\xd0\xba"
++			"\xd6\x02\x78\xf8\x0e\x3e\x9c\x8b"
++			"\x6b\x45\x99\x3f\x5c\xfe\x58\xf1"
++			"\x5c\x94\x04\xe1\xf5\x18\x6d\x51"
++			"\xb2\x5d\x18\x20\xb6\xc2\x9a\x42"
++			"\x1d\xb3\xab\x3c\xb6\x3a\x13\x03"
++			"\xb2\x46\x82\x4f\xfc\x64\xbc\x4f"
++			"\xca\xfa\x9c\xc0\xd5\xa7\xbd\x11"
++			"\xb7\xe4\x5a\xf6\x6f\x4d\x4d\x54"
++			"\xea\xa4\x98\x66\xd4\x22\x3b\xd3"
++			"\x8f\x34\x47\xd9\x7c\xf4\x72\x3b"
++			"\x4d\x02\x77\xf6\xd6\xdd\x08\x0a"
++			"\x81\xe1\x86\x89\x3e\x56\x10\x3c"
++			"\xba\xd7\x81\x8c\x08\xbc\x8b\xe2"
++			"\x53\xec\xa7\x89\xee\xc8\x56\xb5"
++			"\x36\x2c\xb2\x03\xba\x99\xdd\x7c"
++			"\x48\xa0\xb0\xbc\x91\x33\xe9\xa8"
++			"\xcb\xcd\xcf\x59\x5f\x1f\x15\xe2"
++			"\x56\xf5\x4e\x01\x35\x27\x45\x77"
++			"\x47\xc8\xbc\xcb\x7e\x39\xc1\x97"
++			"\x28\xd3\x84\xfc\x2c\x3e\xc8\xad"
++			"\x9c\xf8\x8a\x61\x9c\x28\xaa\xc5"
++			"\x99\x20\x43\x85\x9d\xa5\xe2\x8b"
++			"\xb8\xae\xeb\xd0\x32\x0d\x52\x78"
++			"\x09\x56\x3f\xc7\xd8\x7e\x26\xfc"
++			"\x37\xfb\x6f\x04\xfc\xfa\x92\x10"
++			"\xac\xf8\x3e\x21\xdc\x8c\x21\x16"
++			"\x7d\x67\x6e\xf6\xcd\xda\xb6\x98"
++			"\x23\xab\x23\x3c\xb2\x10\xa0\x53"
++			"\x5a\x56\x9f\xc5\xd0\xff\xbb\xe4"
++			"\x98\x3c\x69\x1e\xdb\x38\x8f\x7e"
++			"\x0f\xd2\x98\x88\x81\x8b\x45\x67"
++			"\xea\x33\xf1\xeb\xe9\x97\x55\x2e"
++			"\xd9\xaa\xeb\x5a\xec\xda\xe1\x68"
++			"\xa8\x9d\x3c\x84\x7c\x05\x3d\x62"
++			"\x87\x8f\x03\x21\x28\x95\x0c\x89"
++			"\x25\x22\x4a\xb0\x93\xa9\x50\xa2"
++			"\x2f\x57\x6e\x18\x42\x19\x54\x0c"
++			"\x55\x67\xc6\x11\x49\xf4\x5c\xd2"
++			"\xe9\x3d\xdd\x8b\x48\x71\x21\x00"
++			"\xc3\x9a\x6c\x85\x74\x28\x83\x4a"
++			"\x1b\x31\x05\xe1\x06\x92\xe7\xda"
++			"\x85\x73\x78\x45\x20\x7f\xae\x13"
++			"\x7c\x33\x06\x22\xf4\x83\xf9\x35"
++			"\x3f\x6c\x71\xa8\x4e\x48\xbe\x9b"
++			"\xce\x8a\xba\xda\xbe\x28\x08\xf7"
++			"\xe2\x14\x8c\x71\xea\x72\xf9\x33"
++			"\xf2\x88\x3f\xd7\xbb\x69\x6c\x29"
++			"\x19\xdc\x84\xce\x1f\x12\x4f\xc8"
++			"\xaf\xa5\x04\xba\x5a\xab\xb0\xd9"
++			"\x14\x1f\x6c\x68\x98\x39\x89\x7a"
++			"\xd9\xd8\x2f\xdf\xa8\x47\x4a\x25"
++			"\xe2\xfb\x33\xf4\x59\x78\xe1\x68"
++			"\x85\xcf\xfe\x59\x20\xd4\x05\x1d"
++			"\x80\x99\xae\xbc\xca\xae\x0f\x2f"
++			"\x65\x43\x34\x8e\x7e\xac\xd3\x93"
++			"\x2f\xac\x6d\x14\x3d\x02\x07\x70"
++			"\x9d\xa4\xf3\x1b\x5c\x36\xfc\x01"
++			"\x73\x34\x85\x0c\x6c\xd6\xf1\xbd"
++			"\x3f\xdf\xee\xf5\xd9\xba\x56\xef"
++			"\xf4\x9b\x6b\xee\x9f\x5a\x78\x6d"
++			"\x32\x19\xf4\xf7\xf8\x4c\x69\x0b"
++			"\x4b\xbc\xbb\xb7\xf2\x85\xaf\x70"
++			"\x75\x24\x6c\x54\xa7\x0e\x4d\x1d"
++			"\x01\xbf\x08\xac\xcf\x7f\x2c\xe3"
++			"\x14\x89\x5e\x70\x5a\x99\x92\xcd"
++			"\x01\x84\xc8\xd2\xab\xe5\x4f\x58"
++			"\xe7\x0f\x2f\x0e\xff\x68\xea\xfd"
++			"\x15\xb3\x17\xe6\xb0\xe7\x85\xd8"
++			"\x23\x2e\x05\xc7\xc9\xc4\x46\x1f"
++			"\xe1\x9e\x49\x20\x23\x24\x4d\x7e"
++			"\x29\x65\xff\xf4\xb6\xfd\x1a\x85"
++			"\xc4\x16\xec\xfc\xea\x7b\xd6\x2c"
++			"\x43\xf8\xb7\xbf\x79\xc0\x85\xcd"
++			"\xef\xe1\x98\xd3\xa5\xf7\x90\x8c"
++			"\xe9\x7f\x80\x6b\xd2\xac\x4c\x30"
++			"\xa7\xc6\x61\x6c\xd2\xf9\x2c\xff"
++			"\x30\xbc\x22\x81\x7d\x93\x12\xe4"
++			"\x0a\xcd\xaf\xdd\xe8\xab\x0a\x1e"
++			"\x13\xa4\x27\xc3\x5f\xf7\x4b\xbb"
++			"\x37\x09\x4b\x91\x6f\x92\x4f\xaf"
++			"\x52\xee\xdf\xef\x09\x6f\xf7\x5c"
++			"\x6e\x12\x17\x72\x63\x57\xc7\xba"
++			"\x3b\x6b\x38\x32\x73\x1b\x9c\x80"
++			"\xc1\x7a\xc6\xcf\xcd\x35\xc0\x6b"
++			"\x31\x1a\x6b\xe9\xd8\x2c\x29\x3f"
++			"\x96\xfb\xb6\xcd\x13\x91\x3b\xc2"
++			"\xd2\xa3\x31\x8d\xa4\xcd\x57\xcd"
++			"\x13\x3d\x64\xfd\x06\xce\xe6\xdc"
++			"\x0c\x24\x43\x31\x40\x57\xf1\x72"
++			"\x17\xe3\x3a\x63\x6d\x35\xcf\x5d"
++			"\x97\x40\x59\xdd\xf7\x3c\x02\xf7"
++			"\x1c\x7e\x05\xbb\xa9\x0d\x01\xb1"
++			"\x8e\xc0\x30\xa9\x53\x24\xc9\x89"
++			"\x84\x6d\xaa\xd0\xcd\x91\xc2\x4d"
++			"\x91\xb0\x89\xe2\xbf\x83\x44\xaa"
++			"\x28\x72\x23\xa0\xc2\xad\xad\x1c"
++			"\xfc\x3f\x09\x7a\x0b\xdc\xc5\x1b"
++			"\x87\x13\xc6\x5b\x59\x8d\xf2\xc8"
++			"\xaf\xdf\x11\x95",
+ 		.rlen = 4100,
+ 	},
+ };
+ 
+ /*
++ * CTS (Cipher Text Stealing) mode tests
++ */
++#define CTS_MODE_ENC_TEST_VECTORS 6
++#define CTS_MODE_DEC_TEST_VECTORS 6
++static struct cipher_testvec cts_mode_enc_tv_template[] = {
++	{ /* from rfc3962 */
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen	= 17,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20",
++		.rlen	= 17,
++		.result	= "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4"
++			  "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
++			  "\x97",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 31,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20",
++		.rlen   = 31,
++		.result = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1"
++			  "\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
++			  "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 32,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43",
++		.rlen   = 32,
++		.result = "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++			  "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 47,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c",
++		.rlen   = 47,
++		.result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c"
++			  "\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 48,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c\x20",
++		.rlen   = 48,
++		.result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++			  "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.ilen   = 64,
++		.input  = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c\x20"
++			  "\x61\x6e\x64\x20\x77\x6f\x6e\x74"
++			  "\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
++		.rlen   = 64,
++		.result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++			  "\x48\x07\xef\xe8\x36\xee\x89\xa5"
++			  "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
++			  "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++			  "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
++	}
++};
++
++static struct cipher_testvec cts_mode_dec_tv_template[] = {
++	{ /* from rfc3962 */
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen	= 17,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20",
++		.ilen	= 17,
++		.input	= "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4"
++			  "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
++			  "\x97",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 31,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20",
++		.ilen   = 31,
++		.input  = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1"
++			  "\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
++			  "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 32,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43",
++		.ilen   = 32,
++		.input  = "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++			  "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 47,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c",
++		.ilen   = 47,
++		.input  = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c"
++			  "\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 48,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c\x20",
++		.ilen   = 48,
++		.input  = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++			  "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
++	}, {
++		.klen	= 16,
++		.key    = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++			  "\x74\x65\x72\x69\x79\x61\x6b\x69",
++		.rlen   = 64,
++		.result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++			  "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++			  "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++			  "\x20\x47\x61\x75\x27\x73\x20\x43"
++			  "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++			  "\x70\x6c\x65\x61\x73\x65\x2c\x20"
++			  "\x61\x6e\x64\x20\x77\x6f\x6e\x74"
++			  "\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
++		.ilen   = 64,
++		.input  = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++			  "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++			  "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++			  "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++			  "\x48\x07\xef\xe8\x36\xee\x89\xa5"
++			  "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
++			  "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++			  "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
++	}
++};
++
++/*
+  * Compression stuff.
+  */
+ #define COMP_BUF_SIZE           512
+@@ -7652,35 +7853,35 @@ static struct comp_testvec deflate_comp_tv_template[] = {
+ 	{
+ 		.inlen	= 70,
+ 		.outlen	= 38,
+-	  	.input	= "Join us now and share the software "
+-			  "Join us now and share the software ",
+-		.output	= { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
+-			    0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
+-			    0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
+-			    0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
+-			    0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 },
++		.input	= "Join us now and share the software "
++			"Join us now and share the software ",
++		.output	= "\xf3\xca\xcf\xcc\x53\x28\x2d\x56"
++			  "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51"
++			  "\x28\xce\x48\x2c\x4a\x55\x28\xc9"
++			  "\x48\x55\x28\xce\x4f\x2b\x29\x07"
++			  "\x71\xbc\x08\x2b\x01\x00",
+ 	}, {
+ 		.inlen	= 191,
+ 		.outlen	= 122,
+ 		.input	= "This document describes a compression method based on the DEFLATE"
+-			  "compression algorithm.  This document defines the application of "
+-			  "the DEFLATE algorithm to the IP Payload Compression Protocol.",
+-		.output	= { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
+-			    0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
+-			    0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
+-			    0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
+-			    0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
+-			    0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
+-			    0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
+-			    0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
+-			    0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
+-			    0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
+-			    0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
+-			    0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
+-			    0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
+-			    0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
+-			    0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
+-			    0xfa, 0x02 },
++			"compression algorithm.  This document defines the application of "
++			"the DEFLATE algorithm to the IP Payload Compression Protocol.",
++		.output	= "\x5d\x8d\x31\x0e\xc2\x30\x10\x04"
++			  "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09"
++			  "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8"
++			  "\x24\xdb\x67\xd9\x47\xc1\xef\x49"
++			  "\x68\x12\x51\xae\x76\x67\xd6\x27"
++			  "\x19\x88\x1a\xde\x85\xab\x21\xf2"
++			  "\x08\x5d\x16\x1e\x20\x04\x2d\xad"
++			  "\xf3\x18\xa2\x15\x85\x2d\x69\xc4"
++			  "\x42\x83\x23\xb6\x6c\x89\x71\x9b"
++			  "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f"
++			  "\xed\x62\xa9\x4c\x80\xff\x13\xaf"
++			  "\x52\x37\xed\x0e\x52\x6b\x59\x02"
++			  "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98"
++			  "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a"
++			  "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79"
++			  "\xfa\x02",
+ 	},
+ };
+ 
+@@ -7688,35 +7889,35 @@ static struct comp_testvec deflate_decomp_tv_template[] = {
+ 	{
+ 		.inlen	= 122,
+ 		.outlen	= 191,
+-		.input	= { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
+-			    0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
+-			    0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
+-			    0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
+-			    0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
+-			    0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
+-			    0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
+-			    0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
+-			    0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
+-			    0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
+-			    0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
+-			    0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
+-			    0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
+-			    0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
+-			    0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
+-			    0xfa, 0x02 },
++		.input	= "\x5d\x8d\x31\x0e\xc2\x30\x10\x04"
++			  "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09"
++			  "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8"
++			  "\x24\xdb\x67\xd9\x47\xc1\xef\x49"
++			  "\x68\x12\x51\xae\x76\x67\xd6\x27"
++			  "\x19\x88\x1a\xde\x85\xab\x21\xf2"
++			  "\x08\x5d\x16\x1e\x20\x04\x2d\xad"
++			  "\xf3\x18\xa2\x15\x85\x2d\x69\xc4"
++			  "\x42\x83\x23\xb6\x6c\x89\x71\x9b"
++			  "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f"
++			  "\xed\x62\xa9\x4c\x80\xff\x13\xaf"
++			  "\x52\x37\xed\x0e\x52\x6b\x59\x02"
++			  "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98"
++			  "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a"
++			  "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79"
++			  "\xfa\x02",
+ 		.output	= "This document describes a compression method based on the DEFLATE"
+-			  "compression algorithm.  This document defines the application of "
+-			  "the DEFLATE algorithm to the IP Payload Compression Protocol.",
++			"compression algorithm.  This document defines the application of "
++			"the DEFLATE algorithm to the IP Payload Compression Protocol.",
+ 	}, {
+ 		.inlen	= 38,
+ 		.outlen	= 70,
+-		.input	= { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
+-			    0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
+-			    0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
+-			    0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
+-			    0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 },
++		.input	= "\xf3\xca\xcf\xcc\x53\x28\x2d\x56"
++			  "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51"
++			  "\x28\xce\x48\x2c\x4a\x55\x28\xc9"
++			  "\x48\x55\x28\xce\x4f\x2b\x29\x07"
++			  "\x71\xbc\x08\x2b\x01\x00",
+ 		.output	= "Join us now and share the software "
+-			  "Join us now and share the software ",
++			"Join us now and share the software ",
+ 	},
+ };
+ 
+@@ -7731,36 +7932,36 @@ static struct comp_testvec lzo_comp_tv_template[] = {
+ 		.inlen	= 70,
+ 		.outlen	= 46,
+ 		.input	= "Join us now and share the software "
+-			  "Join us now and share the software ",
+-		.output	= {  0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
+-			     0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
+-			     0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
+-			     0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
+-			     0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
+-			     0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
++			"Join us now and share the software ",
++		.output	= "\x00\x0d\x4a\x6f\x69\x6e\x20\x75"
++			"\x73\x20\x6e\x6f\x77\x20\x61\x6e"
++			"\x64\x20\x73\x68\x61\x72\x65\x20"
++			"\x74\x68\x65\x20\x73\x6f\x66\x74"
++			"\x77\x70\x01\x01\x4a\x6f\x69\x6e"
++			"\x3d\x88\x00\x11\x00\x00",
+ 	}, {
+ 		.inlen	= 159,
+ 		.outlen	= 133,
+ 		.input	= "This document describes a compression method based on the LZO "
+-			  "compression algorithm.  This document defines the application of "
+-			  "the LZO algorithm used in UBIFS.",
+-		.output	= { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
+-			    0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
+-			    0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
+-			    0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
+-			    0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
+-			    0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
+-			    0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
+-			    0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
+-			    0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
+-			    0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
+-			    0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
+-			    0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
+-			    0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
+-			    0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
+-			    0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
+-			    0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
+-			    0x53, 0x2e, 0x11, 0x00, 0x00 },
++			"compression algorithm.  This document defines the application of "
++			"the LZO algorithm used in UBIFS.",
++		.output	= "\x00\x2b\x54\x68\x69\x73\x20\x64"
++			  "\x6f\x63\x75\x6d\x65\x6e\x74\x20"
++			  "\x64\x65\x73\x63\x72\x69\x62\x65"
++			  "\x73\x20\x61\x20\x63\x6f\x6d\x70"
++			  "\x72\x65\x73\x73\x69\x6f\x6e\x20"
++			  "\x6d\x65\x74\x68\x6f\x64\x20\x62"
++			  "\x61\x73\x65\x64\x20\x6f\x6e\x20"
++			  "\x74\x68\x65\x20\x4c\x5a\x4f\x2b"
++			  "\x8c\x00\x0d\x61\x6c\x67\x6f\x72"
++			  "\x69\x74\x68\x6d\x2e\x20\x20\x54"
++			  "\x68\x69\x73\x2a\x54\x01\x02\x66"
++			  "\x69\x6e\x65\x73\x94\x06\x05\x61"
++			  "\x70\x70\x6c\x69\x63\x61\x74\x76"
++			  "\x0a\x6f\x66\x88\x02\x60\x09\x27"
++			  "\xf0\x00\x0c\x20\x75\x73\x65\x64"
++			  "\x20\x69\x6e\x20\x55\x42\x49\x46"
++			  "\x53\x2e\x11\x00\x00",
+ 	},
+ };
+ 
+@@ -7768,37 +7969,37 @@ static struct comp_testvec lzo_decomp_tv_template[] = {
+ 	{
+ 		.inlen	= 133,
+ 		.outlen	= 159,
+-		.input	= { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
+-			    0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
+-			    0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
+-			    0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
+-			    0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
+-			    0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
+-			    0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
+-			    0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
+-			    0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
+-			    0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
+-			    0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
+-			    0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
+-			    0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
+-			    0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
+-			    0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
+-			    0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
+-			    0x53, 0x2e, 0x11, 0x00, 0x00 },
++		.input	= "\x00\x2b\x54\x68\x69\x73\x20\x64"
++			  "\x6f\x63\x75\x6d\x65\x6e\x74\x20"
++			  "\x64\x65\x73\x63\x72\x69\x62\x65"
++			  "\x73\x20\x61\x20\x63\x6f\x6d\x70"
++			  "\x72\x65\x73\x73\x69\x6f\x6e\x20"
++			  "\x6d\x65\x74\x68\x6f\x64\x20\x62"
++			  "\x61\x73\x65\x64\x20\x6f\x6e\x20"
++			  "\x74\x68\x65\x20\x4c\x5a\x4f\x2b"
++			  "\x8c\x00\x0d\x61\x6c\x67\x6f\x72"
++			  "\x69\x74\x68\x6d\x2e\x20\x20\x54"
++			  "\x68\x69\x73\x2a\x54\x01\x02\x66"
++			  "\x69\x6e\x65\x73\x94\x06\x05\x61"
++			  "\x70\x70\x6c\x69\x63\x61\x74\x76"
++			  "\x0a\x6f\x66\x88\x02\x60\x09\x27"
++			  "\xf0\x00\x0c\x20\x75\x73\x65\x64"
++			  "\x20\x69\x6e\x20\x55\x42\x49\x46"
++			  "\x53\x2e\x11\x00\x00",
+ 		.output	= "This document describes a compression method based on the LZO "
+-			  "compression algorithm.  This document defines the application of "
+-			  "the LZO algorithm used in UBIFS.",
++			"compression algorithm.  This document defines the application of "
++			"the LZO algorithm used in UBIFS.",
+ 	}, {
+ 		.inlen	= 46,
+ 		.outlen	= 70,
+-		.input	= { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
+-			    0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
+-			    0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
+-			    0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
+-			    0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
+-			    0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
++		.input	= "\x00\x0d\x4a\x6f\x69\x6e\x20\x75"
++			  "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
++			  "\x64\x20\x73\x68\x61\x72\x65\x20"
++			  "\x74\x68\x65\x20\x73\x6f\x66\x74"
++			  "\x77\x70\x01\x01\x4a\x6f\x69\x6e"
++			  "\x3d\x88\x00\x11\x00\x00",
+ 		.output	= "Join us now and share the software "
+-			  "Join us now and share the software ",
++			"Join us now and share the software ",
+ 	},
+ };
+ 
+@@ -7809,46 +8010,46 @@ static struct comp_testvec lzo_decomp_tv_template[] = {
+ 
+ static struct hash_testvec michael_mic_tv_template[] = {
+ 	{
+-		.key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.key = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 		.ksize = 8,
+-		.plaintext = { },
++		.plaintext = zeroed_string,
+ 		.psize = 0,
+-		.digest = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 }
++		.digest = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8",
+ 	},
+ 	{
+-		.key = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 },
++		.key = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8",
+ 		.ksize = 8,
+-		.plaintext = { 'M' },
++		.plaintext = "M",
+ 		.psize = 1,
+-		.digest = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f }
++		.digest = "\x43\x47\x21\xca\x40\x63\x9b\x3f",
+ 	},
+ 	{
+-		.key = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f },
++		.key = "\x43\x47\x21\xca\x40\x63\x9b\x3f",
+ 		.ksize = 8,
+-		.plaintext = { 'M', 'i' },
++		.plaintext = "Mi",
+ 		.psize = 2,
+-		.digest = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 }
++		.digest = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29",
+ 	},
+ 	{
+-		.key = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 },
++		.key = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29",
+ 		.ksize = 8,
+-		.plaintext = { 'M', 'i', 'c' },
++		.plaintext = "Mic",
+ 		.psize = 3,
+-		.digest = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb }
++		.digest = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb",
+ 	},
+ 	{
+-		.key = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb },
++		.key = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb",
+ 		.ksize = 8,
+-		.plaintext = { 'M', 'i', 'c', 'h' },
++		.plaintext = "Mich",
+ 		.psize = 4,
+-		.digest = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 }
++		.digest = "\xd5\x5e\x10\x05\x10\x12\x89\x86",
+ 	},
+ 	{
+-		.key = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 },
++		.key = "\xd5\x5e\x10\x05\x10\x12\x89\x86",
+ 		.ksize = 8,
+-		.plaintext = { 'M', 'i', 'c', 'h', 'a', 'e', 'l' },
++		.plaintext = "Michael",
+ 		.psize = 7,
+-		.digest = { 0x0a, 0x94, 0x2b, 0x12, 0x4e, 0xca, 0xa5, 0x46 },
++		.digest = "\x0a\x94\x2b\x12\x4e\xca\xa5\x46",
+ 	}
+ };
+ 
+@@ -7860,170 +8061,170 @@ static struct hash_testvec michael_mic_tv_template[] = {
+ static struct hash_testvec crc32c_tv_template[] = {
+ 	{
+ 		.psize = 0,
+-		.digest = { 0x00, 0x00, 0x00, 0x00 }
++		.digest = "\x00\x00\x00\x00",
+ 	},
+ 	{
+-		.key = { 0x87, 0xa9, 0xcb, 0xed },
++		.key = "\x87\xa9\xcb\xed",
+ 		.ksize = 4,
+ 		.psize = 0,
+-		.digest = { 0x78, 0x56, 0x34, 0x12 },
++		.digest = "\x78\x56\x34\x12",
+ 	},
+ 	{
+-		.key = { 0xff, 0xff, 0xff, 0xff },
++		.key = "\xff\xff\xff\xff",
+ 		.ksize = 4,
+-		.plaintext = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+-			       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+-			       0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+-			       0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+-			       0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28 },
++		.plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08"
++			     "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++			     "\x11\x12\x13\x14\x15\x16\x17\x18"
++			     "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
++			     "\x21\x22\x23\x24\x25\x26\x27\x28",
+ 		.psize = 40,
+-		.digest = { 0x7f, 0x15, 0x2c, 0x0e }
++		.digest = "\x7f\x15\x2c\x0e",
+ 	},
+ 	{
+-		.key = { 0xff, 0xff, 0xff, 0xff },
++		.key = "\xff\xff\xff\xff",
+ 		.ksize = 4,
+-		.plaintext = { 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+-			       0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+-			       0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
+-			       0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+-			       0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50 },
++		.plaintext = "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
++			     "\x31\x32\x33\x34\x35\x36\x37\x38"
++			     "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
++			     "\x41\x42\x43\x44\x45\x46\x47\x48"
++			     "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50",
+ 		.psize = 40,
+-		.digest = { 0xf6, 0xeb, 0x80, 0xe9 }
++		.digest = "\xf6\xeb\x80\xe9",
+ 	},
+ 	{
+-		.key = { 0xff, 0xff, 0xff, 0xff },
++		.key = "\xff\xff\xff\xff",
+ 		.ksize = 4,
+-		.plaintext = { 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+-			       0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
+-			       0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+-			       0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+-			       0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78 },
++		.plaintext = "\x51\x52\x53\x54\x55\x56\x57\x58"
++			     "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
++			     "\x61\x62\x63\x64\x65\x66\x67\x68"
++			     "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
++			     "\x71\x72\x73\x74\x75\x76\x77\x78",
+ 		.psize = 40,
+-		.digest = { 0xed, 0xbd, 0x74, 0xde }
++		.digest = "\xed\xbd\x74\xde",
+ 	},
+ 	{
+-		.key = { 0xff, 0xff, 0xff, 0xff },
++		.key = "\xff\xff\xff\xff",
+ 		.ksize = 4,
+-		.plaintext = { 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
+-			       0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+-			       0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+-			       0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+-			       0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 },
++		.plaintext = "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
++			     "\x81\x82\x83\x84\x85\x86\x87\x88"
++			     "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
++			     "\x91\x92\x93\x94\x95\x96\x97\x98"
++			     "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0",
+ 		.psize = 40,
+-		.digest = { 0x62, 0xc8, 0x79, 0xd5 }
++		.digest = "\x62\xc8\x79\xd5",
+ 	},
+ 	{
+-		.key = { 0xff, 0xff, 0xff, 0xff },
++		.key = "\xff\xff\xff\xff",
+ 		.ksize = 4,
+-		.plaintext = { 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+-			       0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
+-			       0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
+-			       0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
+-			       0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8 },
++		.plaintext = "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
++			     "\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
++			     "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8"
++			     "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
++			     "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8",
+ 		.psize = 40,
+-		.digest = { 0xd0, 0x9a, 0x97, 0xba }
++		.digest = "\xd0\x9a\x97\xba",
+ 	},
+ 	{
+-		.key = { 0xff, 0xff, 0xff, 0xff },
++		.key = "\xff\xff\xff\xff",
+ 		.ksize = 4,
+-		.plaintext = { 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+-			       0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+-			       0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
+-			       0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+-			       0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0 },
++		.plaintext = "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
++			     "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8"
++			     "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
++			     "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
++			     "\xe9\xea\xeb\xec\xed\xee\xef\xf0",
+ 		.psize = 40,
+-		.digest = { 0x13, 0xd9, 0x29, 0x2b }
++		.digest = "\x13\xd9\x29\x2b",
+ 	},
+ 	{
+-		.key = { 0x80, 0xea, 0xd3, 0xf1 },
++		.key = "\x80\xea\xd3\xf1",
+ 		.ksize = 4,
+-		.plaintext = { 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+-			       0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+-			       0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
+-			       0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+-			       0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50 },
++		.plaintext = "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
++			     "\x31\x32\x33\x34\x35\x36\x37\x38"
++			     "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
++			     "\x41\x42\x43\x44\x45\x46\x47\x48"
++			     "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50",
+ 		.psize = 40,
+-		.digest = { 0x0c, 0xb5, 0xe2, 0xa2 }
++		.digest = "\x0c\xb5\xe2\xa2",
+ 	},
+ 	{
+-		.key = { 0xf3, 0x4a, 0x1d, 0x5d },
++		.key = "\xf3\x4a\x1d\x5d",
+ 		.ksize = 4,
+-		.plaintext = { 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+-			       0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
+-			       0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+-			       0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+-			       0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78 },
++		.plaintext = "\x51\x52\x53\x54\x55\x56\x57\x58"
++			     "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
++			     "\x61\x62\x63\x64\x65\x66\x67\x68"
++			     "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
++			     "\x71\x72\x73\x74\x75\x76\x77\x78",
+ 		.psize = 40,
+-		.digest = { 0xd1, 0x7f, 0xfb, 0xa6 }
++		.digest = "\xd1\x7f\xfb\xa6",
+ 	},
+ 	{
+-		.key = { 0x2e, 0x80, 0x04, 0x59 },
++		.key = "\x2e\x80\x04\x59",
+ 		.ksize = 4,
+-		.plaintext = { 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
+-			       0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+-			       0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+-			       0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+-			       0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 },
++		.plaintext = "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
++			     "\x81\x82\x83\x84\x85\x86\x87\x88"
++			     "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
++			     "\x91\x92\x93\x94\x95\x96\x97\x98"
++			     "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0",
+ 		.psize = 40,
+-		.digest = { 0x59, 0x33, 0xe6, 0x7a }
++		.digest = "\x59\x33\xe6\x7a",
+ 	},
+ 	{
+-		.key = { 0xa6, 0xcc, 0x19, 0x85 },
++		.key = "\xa6\xcc\x19\x85",
+ 		.ksize = 4,
+-		.plaintext = { 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+-			       0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
+-			       0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
+-			       0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
+-			       0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8 },
++		.plaintext = "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
++			     "\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
++			     "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8"
++			     "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
++			     "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8",
+ 		.psize = 40,
+-		.digest = { 0xbe, 0x03, 0x01, 0xd2 }
++		.digest = "\xbe\x03\x01\xd2",
+ 	},
+ 	{
+-		.key = { 0x41, 0xfc, 0xfe, 0x2d },
++		.key = "\x41\xfc\xfe\x2d",
+ 		.ksize = 4,
+-		.plaintext = { 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+-			       0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+-			       0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
+-			       0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+-			       0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0 },
++		.plaintext = "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
++			     "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8"
++			     "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
++			     "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
++			     "\xe9\xea\xeb\xec\xed\xee\xef\xf0",
+ 		.psize = 40,
+-		.digest = { 0x75, 0xd3, 0xc5, 0x24 }
++		.digest = "\x75\xd3\xc5\x24",
+ 	},
+ 	{
+-		.key = { 0xff, 0xff, 0xff, 0xff },
++		.key = "\xff\xff\xff\xff",
+ 		.ksize = 4,
+-		.plaintext = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+-			       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+-			       0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+-			       0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+-			       0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+-			       0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+-			       0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+-			       0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
+-			       0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+-			       0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+-			       0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+-			       0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
+-			       0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+-			       0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+-			       0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+-			       0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
+-			       0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+-			       0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+-			       0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+-			       0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
+-			       0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+-			       0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
+-			       0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
+-			       0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
+-			       0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+-			       0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+-			       0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+-			       0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
+-			       0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+-			       0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0 },
++		.plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08"
++			     "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++			     "\x11\x12\x13\x14\x15\x16\x17\x18"
++			     "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
++			     "\x21\x22\x23\x24\x25\x26\x27\x28"
++			     "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
++			     "\x31\x32\x33\x34\x35\x36\x37\x38"
++			     "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
++			     "\x41\x42\x43\x44\x45\x46\x47\x48"
++			     "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
++			     "\x51\x52\x53\x54\x55\x56\x57\x58"
++			     "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
++			     "\x61\x62\x63\x64\x65\x66\x67\x68"
++			     "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
++			     "\x71\x72\x73\x74\x75\x76\x77\x78"
++			     "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
++			     "\x81\x82\x83\x84\x85\x86\x87\x88"
++			     "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
++			     "\x91\x92\x93\x94\x95\x96\x97\x98"
++			     "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
++			     "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
++			     "\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
++			     "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8"
++			     "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
++			     "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8"
++			     "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
++			     "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8"
++			     "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
++			     "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
++			     "\xe9\xea\xeb\xec\xed\xee\xef\xf0",
+ 		.psize = 240,
+-		.digest = { 0x75, 0xd3, 0xc5, 0x24 },
++		.digest = "\x75\xd3\xc5\x24",
+ 		.np = 2,
+ 		.tap = { 31, 209 }
+ 	},
+@@ -8032,134 +8233,19 @@ static struct hash_testvec crc32c_tv_template[] = {
+ /*
+  * Cipher speed tests
+  */
+-static struct cipher_speed aes_speed_template[] = {
+-	{ .klen = 16, .blen = 16, },
+-	{ .klen = 16, .blen = 64, },
+-	{ .klen = 16, .blen = 256, },
+-	{ .klen = 16, .blen = 1024, },
+-	{ .klen = 16, .blen = 8192, },
+-	{ .klen = 24, .blen = 16, },
+-	{ .klen = 24, .blen = 64, },
+-	{ .klen = 24, .blen = 256, },
+-	{ .klen = 24, .blen = 1024, },
+-	{ .klen = 24, .blen = 8192, },
+-	{ .klen = 32, .blen = 16, },
+-	{ .klen = 32, .blen = 64, },
+-	{ .klen = 32, .blen = 256, },
+-	{ .klen = 32, .blen = 1024, },
+-	{ .klen = 32, .blen = 8192, },
+-
+-	/* End marker */
+-	{  .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed aes_lrw_speed_template[] = {
+-	{ .klen = 32, .blen = 16, },
+-	{ .klen = 32, .blen = 64, },
+-	{ .klen = 32, .blen = 256, },
+-	{ .klen = 32, .blen = 1024, },
+-	{ .klen = 32, .blen = 8192, },
+-	{ .klen = 40, .blen = 16, },
+-	{ .klen = 40, .blen = 64, },
+-	{ .klen = 40, .blen = 256, },
+-	{ .klen = 40, .blen = 1024, },
+-	{ .klen = 40, .blen = 8192, },
+-	{ .klen = 48, .blen = 16, },
+-	{ .klen = 48, .blen = 64, },
+-	{ .klen = 48, .blen = 256, },
+-	{ .klen = 48, .blen = 1024, },
+-	{ .klen = 48, .blen = 8192, },
+-
+-	/* End marker */
+-	{  .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed aes_xts_speed_template[] = {
+-	{ .klen = 32, .blen = 16, },
+-	{ .klen = 32, .blen = 64, },
+-	{ .klen = 32, .blen = 256, },
+-	{ .klen = 32, .blen = 1024, },
+-	{ .klen = 32, .blen = 8192, },
+-	{ .klen = 48, .blen = 16, },
+-	{ .klen = 48, .blen = 64, },
+-	{ .klen = 48, .blen = 256, },
+-	{ .klen = 48, .blen = 1024, },
+-	{ .klen = 48, .blen = 8192, },
+-	{ .klen = 64, .blen = 16, },
+-	{ .klen = 64, .blen = 64, },
+-	{ .klen = 64, .blen = 256, },
+-	{ .klen = 64, .blen = 1024, },
+-	{ .klen = 64, .blen = 8192, },
+-
+-	/* End marker */
+-	{  .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed des3_ede_speed_template[] = {
+-	{ .klen = 24, .blen = 16, },
+-	{ .klen = 24, .blen = 64, },
+-	{ .klen = 24, .blen = 256, },
+-	{ .klen = 24, .blen = 1024, },
+-	{ .klen = 24, .blen = 8192, },
+-
+-	/* End marker */
+-	{  .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed twofish_speed_template[] = {
+-	{ .klen = 16, .blen = 16, },
+-	{ .klen = 16, .blen = 64, },
+-	{ .klen = 16, .blen = 256, },
+-	{ .klen = 16, .blen = 1024, },
+-	{ .klen = 16, .blen = 8192, },
+-	{ .klen = 24, .blen = 16, },
+-	{ .klen = 24, .blen = 64, },
+-	{ .klen = 24, .blen = 256, },
+-	{ .klen = 24, .blen = 1024, },
+-	{ .klen = 24, .blen = 8192, },
+-	{ .klen = 32, .blen = 16, },
+-	{ .klen = 32, .blen = 64, },
+-	{ .klen = 32, .blen = 256, },
+-	{ .klen = 32, .blen = 1024, },
+-	{ .klen = 32, .blen = 8192, },
+-
+-	/* End marker */
+-	{  .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed blowfish_speed_template[] = {
+-	/* Don't support blowfish keys > 256 bit in this test */
+-	{ .klen = 8, .blen = 16, },
+-	{ .klen = 8, .blen = 64, },
+-	{ .klen = 8, .blen = 256, },
+-	{ .klen = 8, .blen = 1024, },
+-	{ .klen = 8, .blen = 8192, },
+-	{ .klen = 32, .blen = 16, },
+-	{ .klen = 32, .blen = 64, },
+-	{ .klen = 32, .blen = 256, },
+-	{ .klen = 32, .blen = 1024, },
+-	{ .klen = 32, .blen = 8192, },
+-
+-	/* End marker */
+-	{  .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed des_speed_template[] = {
+-	{ .klen = 8, .blen = 16, },
+-	{ .klen = 8, .blen = 64, },
+-	{ .klen = 8, .blen = 256, },
+-	{ .klen = 8, .blen = 1024, },
+-	{ .klen = 8, .blen = 8192, },
+-
+-	/* End marker */
+-	{  .klen = 0, .blen = 0, }
+-};
++static u8 speed_template_8[] = {8, 0};
++static u8 speed_template_24[] = {24, 0};
++static u8 speed_template_8_32[] = {8, 32, 0};
++static u8 speed_template_16_32[] = {16, 32, 0};
++static u8 speed_template_16_24_32[] = {16, 24, 32, 0};
++static u8 speed_template_32_40_48[] = {32, 40, 48, 0};
++static u8 speed_template_32_48_64[] = {32, 48, 64, 0};
+ 
+ /*
+  * Digest speed tests
+  */
+ static struct hash_speed generic_hash_speed_template[] = {
+-	{ .blen = 16, 	.plen = 16, },
++	{ .blen = 16,	.plen = 16, },
+ 	{ .blen = 64,	.plen = 16, },
+ 	{ .blen = 64,	.plen = 64, },
+ 	{ .blen = 256,	.plen = 16, },
+@@ -8186,41 +8272,4 @@ static struct hash_speed generic_hash_speed_template[] = {
+ 	{  .blen = 0,	.plen = 0, }
+ };
+ 
+-static struct cipher_speed camellia_speed_template[] = {
+-      { .klen = 16, .blen = 16, },
+-      { .klen = 16, .blen = 64, },
+-      { .klen = 16, .blen = 256, },
+-      { .klen = 16, .blen = 1024, },
+-      { .klen = 16, .blen = 8192, },
+-      { .klen = 24, .blen = 16, },
+-      { .klen = 24, .blen = 64, },
+-      { .klen = 24, .blen = 256, },
+-      { .klen = 24, .blen = 1024, },
+-      { .klen = 24, .blen = 8192, },
+-      { .klen = 32, .blen = 16, },
+-      { .klen = 32, .blen = 64, },
+-      { .klen = 32, .blen = 256, },
+-      { .klen = 32, .blen = 1024, },
+-      { .klen = 32, .blen = 8192, },
+-
+-      /* End marker */
+-      {  .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed salsa20_speed_template[] = {
+-      { .klen = 16, .blen = 16, },
+-      { .klen = 16, .blen = 64, },
+-      { .klen = 16, .blen = 256, },
+-      { .klen = 16, .blen = 1024, },
+-      { .klen = 16, .blen = 8192, },
+-      { .klen = 32, .blen = 16, },
+-      { .klen = 32, .blen = 64, },
+-      { .klen = 32, .blen = 256, },
+-      { .klen = 32, .blen = 1024, },
+-      { .klen = 32, .blen = 8192, },
+-
+-      /* End marker */
+-      {  .klen = 0, .blen = 0, }
+-};
+-
+ #endif	/* _CRYPTO_TCRYPT_H */
+diff --git a/crypto/tea.c b/crypto/tea.c
+index 6893b3f..412bc74 100644
+--- a/crypto/tea.c
++++ b/crypto/tea.c
+@@ -267,7 +267,7 @@ static struct crypto_alg xeta_alg = {
+ 	.cia_decrypt		=	xeta_decrypt } }
+ };
+ 
+-static int __init init(void)
++static int __init tea_mod_init(void)
+ {
+ 	int ret = 0;
+ 	
+@@ -292,7 +292,7 @@ out:
+ 	return ret;
+ }
+ 
+-static void __exit fini(void)
++static void __exit tea_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&tea_alg);
+ 	crypto_unregister_alg(&xtea_alg);
+@@ -302,8 +302,8 @@ static void __exit fini(void)
+ MODULE_ALIAS("xtea");
+ MODULE_ALIAS("xeta");
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(tea_mod_init);
++module_exit(tea_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("TEA, XTEA & XETA Cryptographic Algorithms");
+diff --git a/crypto/tgr192.c b/crypto/tgr192.c
+index 2e7ea16..a92414f 100644
+--- a/crypto/tgr192.c
++++ b/crypto/tgr192.c
+@@ -663,7 +663,7 @@ static struct crypto_alg tgr128 = {
+ 			     .dia_final = tgr128_final}}
+ };
+ 
+-static int __init init(void)
++static int __init tgr192_mod_init(void)
+ {
+ 	int ret = 0;
+ 
+@@ -688,7 +688,7 @@ static int __init init(void)
+ 	return ret;
+ }
+ 
+-static void __exit fini(void)
++static void __exit tgr192_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&tgr192);
+ 	crypto_unregister_alg(&tgr160);
+@@ -698,8 +698,8 @@ static void __exit fini(void)
+ MODULE_ALIAS("tgr160");
+ MODULE_ALIAS("tgr128");
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(tgr192_mod_init);
++module_exit(tgr192_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Tiger Message Digest Algorithm");
+diff --git a/crypto/twofish.c b/crypto/twofish.c
+index 4979a2b..dfcda23 100644
+--- a/crypto/twofish.c
++++ b/crypto/twofish.c
+@@ -197,18 +197,18 @@ static struct crypto_alg alg = {
+ 	.cia_decrypt        =   twofish_decrypt } }
+ };
+ 
+-static int __init init(void)
++static int __init twofish_mod_init(void)
+ {
+ 	return crypto_register_alg(&alg);
+ }
+ 
+-static void __exit fini(void)
++static void __exit twofish_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&alg);
+ }
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(twofish_mod_init);
++module_exit(twofish_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION ("Twofish Cipher Algorithm");
+diff --git a/crypto/wp512.c b/crypto/wp512.c
+index f746952..bff2856 100644
+--- a/crypto/wp512.c
++++ b/crypto/wp512.c
+@@ -1146,7 +1146,7 @@ static struct crypto_alg wp256 = {
+ 	.dia_final  	=	wp256_final } }
+ };
+ 
+-static int __init init(void)
++static int __init wp512_mod_init(void)
+ {
+ 	int ret = 0;
+ 
+@@ -1172,7 +1172,7 @@ out:
+ 	return ret;
+ }
+ 
+-static void __exit fini(void)
++static void __exit wp512_mod_fini(void)
+ {
+ 	crypto_unregister_alg(&wp512);
+ 	crypto_unregister_alg(&wp384);
+@@ -1182,8 +1182,8 @@ static void __exit fini(void)
+ MODULE_ALIAS("wp384");
+ MODULE_ALIAS("wp256");
+ 
+-module_init(init);
+-module_exit(fini);
++module_init(wp512_mod_init);
++module_exit(wp512_mod_fini);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Whirlpool Message Digest Algorithm");
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index 3a0e354..80f0ec9 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -97,4 +97,6 @@ source "drivers/dca/Kconfig"
+ source "drivers/auxdisplay/Kconfig"
+ 
+ source "drivers/uio/Kconfig"
++
++source "drivers/xen/Kconfig"
+ endmenu
+diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
+index 76b9bea..43a95e5 100644
+--- a/drivers/acpi/ac.c
++++ b/drivers/acpi/ac.c
+@@ -63,7 +63,7 @@ static int acpi_ac_add(struct acpi_device *device);
+ static int acpi_ac_remove(struct acpi_device *device, int type);
+ static int acpi_ac_resume(struct acpi_device *device);
+ 
+-const static struct acpi_device_id ac_device_ids[] = {
++static const struct acpi_device_id ac_device_ids[] = {
+ 	{"ACPI0003", 0},
+ 	{"", 0},
+ };
+diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
+index a697fb6..a498a6c 100644
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -4,6 +4,8 @@
+  *  Copyright (C) 2000       Andrew Henroid
+  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover at intel.com>
+  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh at intel.com>
++ *  Copyright (c) 2008 Intel Corporation
++ *   Author: Matthew Wilcox <willy at linux.intel.com>
+  *
+  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  *
+@@ -37,15 +39,18 @@
+ #include <linux/workqueue.h>
+ #include <linux/nmi.h>
+ #include <linux/acpi.h>
+-#include <acpi/acpi.h>
+-#include <asm/io.h>
+-#include <acpi/acpi_bus.h>
+-#include <acpi/processor.h>
+-#include <asm/uaccess.h>
+-
+ #include <linux/efi.h>
+ #include <linux/ioport.h>
+ #include <linux/list.h>
++#include <linux/jiffies.h>
++#include <linux/semaphore.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <acpi/acpi.h>
++#include <acpi/acpi_bus.h>
++#include <acpi/processor.h>
+ 
+ #define _COMPONENT		ACPI_OS_SERVICES
+ ACPI_MODULE_NAME("osl");
+@@ -764,7 +769,6 @@ acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
+ {
+ 	struct semaphore *sem = NULL;
+ 
+-
+ 	sem = acpi_os_allocate(sizeof(struct semaphore));
+ 	if (!sem)
+ 		return AE_NO_MEMORY;
+@@ -791,12 +795,12 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
+ {
+ 	struct semaphore *sem = (struct semaphore *)handle;
+ 
+-
+ 	if (!sem)
+ 		return AE_BAD_PARAMETER;
+ 
+ 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
+ 
++	BUG_ON(!list_empty(&sem->wait_list));
+ 	kfree(sem);
+ 	sem = NULL;
+ 
+@@ -804,21 +808,15 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
+ }
+ 
+ /*
+- * TODO: The kernel doesn't have a 'down_timeout' function -- had to
+- * improvise.  The process is to sleep for one scheduler quantum
+- * until the semaphore becomes available.  Downside is that this
+- * may result in starvation for timeout-based waits when there's
+- * lots of semaphore activity.
+- *
+  * TODO: Support for units > 1?
+  */
+ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
+ {
+ 	acpi_status status = AE_OK;
+ 	struct semaphore *sem = (struct semaphore *)handle;
++	long jiffies;
+ 	int ret = 0;
+ 
+-
+ 	if (!sem || (units < 1))
+ 		return AE_BAD_PARAMETER;
+ 
+@@ -828,58 +826,14 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
+ 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
+ 			  handle, units, timeout));
+ 
+-	/*
+-	 * This can be called during resume with interrupts off.
+-	 * Like boot-time, we should be single threaded and will
+-	 * always get the lock if we try -- timeout or not.
+-	 * If this doesn't succeed, then we will oops courtesy of
+-	 * might_sleep() in down().
+-	 */
+-	if (!down_trylock(sem))
+-		return AE_OK;
+-
+-	switch (timeout) {
+-		/*
+-		 * No Wait:
+-		 * --------
+-		 * A zero timeout value indicates that we shouldn't wait - just
+-		 * acquire the semaphore if available otherwise return AE_TIME
+-		 * (a.k.a. 'would block').
+-		 */
+-	case 0:
+-		if (down_trylock(sem))
+-			status = AE_TIME;
+-		break;
+-
+-		/*
+-		 * Wait Indefinitely:
+-		 * ------------------
+-		 */
+-	case ACPI_WAIT_FOREVER:
+-		down(sem);
+-		break;
+-
+-		/*
+-		 * Wait w/ Timeout:
+-		 * ----------------
+-		 */
+-	default:
+-		// TODO: A better timeout algorithm?
+-		{
+-			int i = 0;
+-			static const int quantum_ms = 1000 / HZ;
+-
+-			ret = down_trylock(sem);
+-			for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
+-				schedule_timeout_interruptible(1);
+-				ret = down_trylock(sem);
+-			}
+-
+-			if (ret != 0)
+-				status = AE_TIME;
+-		}
+-		break;
+-	}
++	if (timeout == ACPI_WAIT_FOREVER)
++		jiffies = MAX_SCHEDULE_TIMEOUT;
++	else
++		jiffies = msecs_to_jiffies(timeout);
++	
++	ret = down_timeout(sem, jiffies);
++	if (ret)
++		status = AE_TIME;
+ 
+ 	if (ACPI_FAILURE(status)) {
+ 		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+@@ -902,7 +856,6 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
+ {
+ 	struct semaphore *sem = (struct semaphore *)handle;
+ 
+-
+ 	if (!sem || (units < 1))
+ 		return AE_BAD_PARAMETER;
+ 
+diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
+index 1b8e592..0bba3a9 100644
+--- a/drivers/acpi/processor_throttling.c
++++ b/drivers/acpi/processor_throttling.c
+@@ -838,10 +838,10 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
+ 	 * Migrate task to the cpu pointed by pr.
+ 	 */
+ 	saved_mask = current->cpus_allowed;
+-	set_cpus_allowed(current, cpumask_of_cpu(pr->id));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ 	ret = pr->throttling.acpi_processor_get_throttling(pr);
+ 	/* restore the previous state */
+-	set_cpus_allowed(current, saved_mask);
++	set_cpus_allowed_ptr(current, &saved_mask);
+ 
+ 	return ret;
+ }
+@@ -1025,7 +1025,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+ 	 * it can be called only for the cpu pointed by pr.
+ 	 */
+ 	if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
+-		set_cpus_allowed(current, cpumask_of_cpu(pr->id));
++		set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ 		ret = p_throttling->acpi_processor_set_throttling(pr,
+ 						t_state.target_state);
+ 	} else {
+@@ -1056,7 +1056,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+ 				continue;
+ 			}
+ 			t_state.cpu = i;
+-			set_cpus_allowed(current, cpumask_of_cpu(i));
++			set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
+ 			ret = match_pr->throttling.
+ 				acpi_processor_set_throttling(
+ 				match_pr, t_state.target_state);
+@@ -1074,7 +1074,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+ 							&t_state);
+ 	}
+ 	/* restore the previous state */
+-	set_cpus_allowed(current, saved_mask);
++	set_cpus_allowed_ptr(current, &saved_mask);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index 25aba69..292aa9a 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -28,7 +28,7 @@ config ATA_NONSTANDARD
+        default n
+ 
+ config ATA_ACPI
+-	bool
++	bool "ATA ACPI Support"
+ 	depends on ACPI && PCI
+ 	select ACPI_DOCK
+ 	default y
+@@ -41,6 +41,13 @@ config ATA_ACPI
+ 	  You can disable this at kernel boot time by using the
+ 	  option libata.noacpi=1
+ 
++config SATA_PMP
++	bool "SATA Port Multiplier support"
++	default y
++	help
++	  This option adds support for SATA Port Multipliers
++	  (the SATA version of an ethernet hub, or SAS expander).
++
+ config SATA_AHCI
+ 	tristate "AHCI SATA support"
+ 	depends on PCI
+@@ -49,6 +56,43 @@ config SATA_AHCI
+ 
+ 	  If unsure, say N.
+ 
++config SATA_SIL24
++	tristate "Silicon Image 3124/3132 SATA support"
++	depends on PCI
++	help
++	  This option enables support for Silicon Image 3124/3132 Serial ATA.
++
++	  If unsure, say N.
++
++config SATA_FSL
++	tristate "Freescale 3.0Gbps SATA support"
++	depends on FSL_SOC
++	help
++	  This option enables support for Freescale 3.0Gbps SATA controller.
++	  It can be found on MPC837x and MPC8315.
++
++	  If unsure, say N.
++
++config ATA_SFF
++	bool "ATA SFF support"
++	default y
++	help
++	  This option adds support for ATA controllers with SFF
++	  compliant or similar programming interface.
++
++	  SFF is the legacy IDE interface that has been around since
++	  the dawn of time.  Almost all PATA controllers have an
++	  SFF interface.  Many SATA controllers have an SFF interface
++	  when configured into a legacy compatibility mode.
++
++	  For users with exclusively modern controllers like AHCI,
++	  Silicon Image 3124, or Marvell 6440, you may choose to
++	  disable this uneeded SFF support.
++
++	  If unsure, say Y.
++
++if ATA_SFF
++
+ config SATA_SVW
+ 	tristate "ServerWorks Frodo / Apple K2 SATA support"
+ 	depends on PCI
+@@ -125,14 +169,6 @@ config SATA_SIL
+ 
+ 	  If unsure, say N.
+ 
+-config SATA_SIL24
+-	tristate "Silicon Image 3124/3132 SATA support"
+-	depends on PCI
+-	help
+-	  This option enables support for Silicon Image 3124/3132 Serial ATA.
+-
+-	  If unsure, say N.
+-
+ config SATA_SIS
+ 	tristate "SiS 964/965/966/180 SATA support"
+ 	depends on PCI
+@@ -183,15 +219,6 @@ config PATA_ACPI
+ 	  firmware in the BIOS. This driver can sometimes handle
+ 	  otherwise unsupported hardware.
+ 
+-config SATA_FSL
+-	tristate "Freescale 3.0Gbps SATA support"
+-	depends on FSL_SOC
+-	help
+-	  This option enables support for Freescale 3.0Gbps SATA controller.
+-	  It can be found on MPC837x and MPC8315.
+-
+-	  If unsure, say N.
+-
+ config PATA_ALI
+ 	tristate "ALi PATA support (Experimental)"
+ 	depends on PCI && EXPERIMENTAL
+@@ -679,4 +706,5 @@ config PATA_BF54X
+ 
+ 	  If unsure, say N.
+ 
++endif # ATA_SFF
+ endif # ATA
+diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
+index 0511e6f..1fbc2aa 100644
+--- a/drivers/ata/Makefile
++++ b/drivers/ata/Makefile
+@@ -78,6 +78,7 @@ obj-$(CONFIG_ATA_GENERIC)	+= ata_generic.o
+ # Should be last libata driver
+ obj-$(CONFIG_PATA_LEGACY)	+= pata_legacy.o
+ 
+-libata-objs	:= libata-core.o libata-scsi.o libata-sff.o libata-eh.o \
+-		   libata-pmp.o
++libata-objs	:= libata-core.o libata-scsi.o libata-eh.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 b1eb4e2..7c4f886 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -62,7 +62,6 @@ enum {
+ 	AHCI_MAX_PORTS		= 32,
+ 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
+ 	AHCI_DMA_BOUNDARY	= 0xffffffff,
+-	AHCI_USE_CLUSTERING	= 1,
+ 	AHCI_MAX_CMDS		= 32,
+ 	AHCI_CMD_SZ		= 32,
+ 	AHCI_CMD_SLOT_SZ	= AHCI_MAX_CMDS * AHCI_CMD_SZ,
+@@ -198,7 +197,6 @@ enum {
+ 					  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ 					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
+ 					  ATA_FLAG_IPM,
+-	AHCI_LFLAG_COMMON		= ATA_LFLAG_SKIP_D2H_BSY,
+ 
+ 	ICH_MAP				= 0x90, /* ICH MAP register */
+ };
+@@ -245,19 +243,24 @@ static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
+ static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
+-static void ahci_irq_clear(struct ata_port *ap);
++static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
+ static int ahci_port_start(struct ata_port *ap);
+ static void ahci_port_stop(struct ata_port *ap);
+-static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+ static void ahci_qc_prep(struct ata_queued_cmd *qc);
+-static u8 ahci_check_status(struct ata_port *ap);
+ static void ahci_freeze(struct ata_port *ap);
+ static void ahci_thaw(struct ata_port *ap);
+ static void ahci_pmp_attach(struct ata_port *ap);
+ static void ahci_pmp_detach(struct ata_port *ap);
++static int ahci_softreset(struct ata_link *link, unsigned int *class,
++			  unsigned long deadline);
++static int ahci_hardreset(struct ata_link *link, unsigned int *class,
++			  unsigned long deadline);
++static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
++				 unsigned long deadline);
++static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
++				unsigned long deadline);
++static void ahci_postreset(struct ata_link *link, unsigned int *class);
+ static void ahci_error_handler(struct ata_port *ap);
+-static void ahci_vt8251_error_handler(struct ata_port *ap);
+-static void ahci_p5wdh_error_handler(struct ata_port *ap);
+ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+ static int ahci_port_resume(struct ata_port *ap);
+ static void ahci_dev_config(struct ata_device *dev);
+@@ -270,135 +273,60 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+ static int ahci_pci_device_resume(struct pci_dev *pdev);
+ #endif
+ 
+-static struct class_device_attribute *ahci_shost_attrs[] = {
+-	&class_device_attr_link_power_management_policy,
++static struct device_attribute *ahci_shost_attrs[] = {
++	&dev_attr_link_power_management_policy,
+ 	NULL
+ };
+ 
+ static struct scsi_host_template ahci_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.change_queue_depth	= ata_scsi_change_queue_depth,
++	ATA_NCQ_SHT(DRV_NAME),
+ 	.can_queue		= AHCI_MAX_CMDS - 1,
+-	.this_id		= ATA_SHT_THIS_ID,
+ 	.sg_tablesize		= AHCI_MAX_SG,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= AHCI_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= AHCI_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ 	.shost_attrs		= ahci_shost_attrs,
+ };
+ 
+-static const struct ata_port_operations ahci_ops = {
+-	.check_status		= ahci_check_status,
+-	.check_altstatus	= ahci_check_status,
+-	.dev_select		= ata_noop_dev_select,
+-
+-	.dev_config		= ahci_dev_config,
+-
+-	.tf_read		= ahci_tf_read,
++static struct ata_port_operations ahci_ops = {
++	.inherits		= &sata_pmp_port_ops,
+ 
+ 	.qc_defer		= sata_pmp_qc_defer_cmd_switch,
+ 	.qc_prep		= ahci_qc_prep,
+ 	.qc_issue		= ahci_qc_issue,
+-
+-	.irq_clear		= ahci_irq_clear,
+-
+-	.scr_read		= ahci_scr_read,
+-	.scr_write		= ahci_scr_write,
++	.qc_fill_rtf		= ahci_qc_fill_rtf,
+ 
+ 	.freeze			= ahci_freeze,
+ 	.thaw			= ahci_thaw,
+-
++	.softreset		= ahci_softreset,
++	.hardreset		= ahci_hardreset,
++	.postreset		= ahci_postreset,
++	.pmp_softreset		= ahci_softreset,
+ 	.error_handler		= ahci_error_handler,
+ 	.post_internal_cmd	= ahci_post_internal_cmd,
+-
+-	.pmp_attach		= ahci_pmp_attach,
+-	.pmp_detach		= ahci_pmp_detach,
+-
+-#ifdef CONFIG_PM
+-	.port_suspend		= ahci_port_suspend,
+-	.port_resume		= ahci_port_resume,
+-#endif
+-	.enable_pm		= ahci_enable_alpm,
+-	.disable_pm		= ahci_disable_alpm,
+-
+-	.port_start		= ahci_port_start,
+-	.port_stop		= ahci_port_stop,
+-};
+-
+-static const struct ata_port_operations ahci_vt8251_ops = {
+-	.check_status		= ahci_check_status,
+-	.check_altstatus	= ahci_check_status,
+-	.dev_select		= ata_noop_dev_select,
+-
+-	.tf_read		= ahci_tf_read,
+-
+-	.qc_defer		= sata_pmp_qc_defer_cmd_switch,
+-	.qc_prep		= ahci_qc_prep,
+-	.qc_issue		= ahci_qc_issue,
+-
+-	.irq_clear		= ahci_irq_clear,
++	.dev_config		= ahci_dev_config,
+ 
+ 	.scr_read		= ahci_scr_read,
+ 	.scr_write		= ahci_scr_write,
+-
+-	.freeze			= ahci_freeze,
+-	.thaw			= ahci_thaw,
+-
+-	.error_handler		= ahci_vt8251_error_handler,
+-	.post_internal_cmd	= ahci_post_internal_cmd,
+-
+ 	.pmp_attach		= ahci_pmp_attach,
+ 	.pmp_detach		= ahci_pmp_detach,
+ 
++	.enable_pm		= ahci_enable_alpm,
++	.disable_pm		= ahci_disable_alpm,
+ #ifdef CONFIG_PM
+ 	.port_suspend		= ahci_port_suspend,
+ 	.port_resume		= ahci_port_resume,
+ #endif
+-
+ 	.port_start		= ahci_port_start,
+ 	.port_stop		= ahci_port_stop,
+ };
+ 
+-static const struct ata_port_operations ahci_p5wdh_ops = {
+-	.check_status		= ahci_check_status,
+-	.check_altstatus	= ahci_check_status,
+-	.dev_select		= ata_noop_dev_select,
+-
+-	.tf_read		= ahci_tf_read,
+-
+-	.qc_defer		= sata_pmp_qc_defer_cmd_switch,
+-	.qc_prep		= ahci_qc_prep,
+-	.qc_issue		= ahci_qc_issue,
+-
+-	.irq_clear		= ahci_irq_clear,
+-
+-	.scr_read		= ahci_scr_read,
+-	.scr_write		= ahci_scr_write,
+-
+-	.freeze			= ahci_freeze,
+-	.thaw			= ahci_thaw,
+-
+-	.error_handler		= ahci_p5wdh_error_handler,
+-	.post_internal_cmd	= ahci_post_internal_cmd,
+-
+-	.pmp_attach		= ahci_pmp_attach,
+-	.pmp_detach		= ahci_pmp_detach,
+-
+-#ifdef CONFIG_PM
+-	.port_suspend		= ahci_port_suspend,
+-	.port_resume		= ahci_port_resume,
+-#endif
++static struct ata_port_operations ahci_vt8251_ops = {
++	.inherits		= &ahci_ops,
++	.hardreset		= ahci_vt8251_hardreset,
++};
+ 
+-	.port_start		= ahci_port_start,
+-	.port_stop		= ahci_port_stop,
++static struct ata_port_operations ahci_p5wdh_ops = {
++	.inherits		= &ahci_ops,
++	.hardreset		= ahci_p5wdh_hardreset,
+ };
+ 
+ #define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)
+@@ -407,7 +335,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ 	/* board_ahci */
+ 	{
+ 		.flags		= AHCI_FLAG_COMMON,
+-		.link_flags	= AHCI_LFLAG_COMMON,
+ 		.pio_mask	= 0x1f, /* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &ahci_ops,
+@@ -416,7 +343,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ 	{
+ 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
+ 		.flags		= AHCI_FLAG_COMMON,
+-		.link_flags	= AHCI_LFLAG_COMMON | ATA_LFLAG_HRST_TO_RESUME,
+ 		.pio_mask	= 0x1f, /* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &ahci_vt8251_ops,
+@@ -425,7 +351,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ 	{
+ 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
+ 		.flags		= AHCI_FLAG_COMMON,
+-		.link_flags	= AHCI_LFLAG_COMMON,
+ 		.pio_mask	= 0x1f, /* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &ahci_ops,
+@@ -436,7 +361,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ 				 AHCI_HFLAG_32BIT_ONLY |
+ 				 AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP),
+ 		.flags		= AHCI_FLAG_COMMON,
+-		.link_flags	= AHCI_LFLAG_COMMON,
+ 		.pio_mask	= 0x1f, /* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &ahci_ops,
+@@ -447,7 +371,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ 				 AHCI_HFLAG_MV_PATA),
+ 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ 				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
+-		.link_flags	= AHCI_LFLAG_COMMON,
+ 		.pio_mask	= 0x1f, /* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &ahci_ops,
+@@ -457,7 +380,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
+ 				 AHCI_HFLAG_NO_PMP),
+ 		.flags		= AHCI_FLAG_COMMON,
+-		.link_flags	= AHCI_LFLAG_COMMON,
+ 		.pio_mask	= 0x1f, /* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &ahci_ops,
+@@ -634,16 +556,27 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
+ 
+ static void ahci_enable_ahci(void __iomem *mmio)
+ {
++	int i;
+ 	u32 tmp;
+ 
+ 	/* turn on AHCI_EN */
+ 	tmp = readl(mmio + HOST_CTL);
+-	if (!(tmp & HOST_AHCI_EN)) {
++	if (tmp & HOST_AHCI_EN)
++		return;
++
++	/* Some controllers need AHCI_EN to be written multiple times.
++	 * Try a few times before giving up.
++	 */
++	for (i = 0; i < 5; i++) {
+ 		tmp |= HOST_AHCI_EN;
+ 		writel(tmp, mmio + HOST_CTL);
+ 		tmp = readl(mmio + HOST_CTL);	/* flush && sanity check */
+-		WARN_ON(!(tmp & HOST_AHCI_EN));
++		if (tmp & HOST_AHCI_EN)
++			return;
++		msleep(10);
+ 	}
++
++	WARN_ON(1);
+ }
+ 
+ /**
+@@ -1255,13 +1188,14 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+ 
+ static int ahci_kick_engine(struct ata_port *ap, int force_restart)
+ {
+-	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
++	void __iomem *port_mmio = ahci_port_base(ap);
+ 	struct ahci_host_priv *hpriv = ap->host->private_data;
++	u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
+ 	u32 tmp;
+ 	int busy, rc;
+ 
+ 	/* do we need to kick the port? */
+-	busy = ahci_check_status(ap) & (ATA_BUSY | ATA_DRQ);
++	busy = status & (ATA_BUSY | ATA_DRQ);
+ 	if (!busy && !force_restart)
+ 		return 0;
+ 
+@@ -1328,10 +1262,21 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
+ 	return 0;
+ }
+ 
+-static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
+-			     int pmp, unsigned long deadline)
++static int ahci_check_ready(struct ata_link *link)
++{
++	void __iomem *port_mmio = ahci_port_base(link->ap);
++	u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
++
++	if (!(status & ATA_BUSY))
++		return 1;
++	return 0;
++}
++
++static int ahci_softreset(struct ata_link *link, unsigned int *class,
++			  unsigned long deadline)
+ {
+ 	struct ata_port *ap = link->ap;
++	int pmp = sata_srst_pmp(link);
+ 	const char *reason = NULL;
+ 	unsigned long now, msecs;
+ 	struct ata_taskfile tf;
+@@ -1339,12 +1284,6 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
+ 
+ 	DPRINTK("ENTER\n");
+ 
+-	if (ata_link_offline(link)) {
+-		DPRINTK("PHY reports no device\n");
+-		*class = ATA_DEV_NONE;
+-		return 0;
+-	}
+-
+ 	/* prepare for SRST (AHCI-1.1 10.4.1) */
+ 	rc = ahci_kick_engine(ap, 1);
+ 	if (rc && rc != -EOPNOTSUPP)
+@@ -1374,10 +1313,8 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
+ 	tf.ctl &= ~ATA_SRST;
+ 	ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
+ 
+-	/* wait a while before checking status */
+-	ata_wait_after_reset(ap, deadline);
+-
+-	rc = ata_wait_ready(ap, deadline);
++	/* wait for link to become ready */
++	rc = ata_wait_after_reset(link, deadline, ahci_check_ready);
+ 	/* link occupied, -ENODEV too is an error */
+ 	if (rc) {
+ 		reason = "device not ready";
+@@ -1393,24 +1330,15 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
+ 	return rc;
+ }
+ 
+-static int ahci_softreset(struct ata_link *link, unsigned int *class,
+-			  unsigned long deadline)
+-{
+-	int pmp = 0;
+-
+-	if (link->ap->flags & ATA_FLAG_PMP)
+-		pmp = SATA_PMP_CTRL_PORT;
+-
+-	return ahci_do_softreset(link, class, pmp, deadline);
+-}
+-
+ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
+ 			  unsigned long deadline)
+ {
++	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+ 	struct ata_port *ap = link->ap;
+ 	struct ahci_port_priv *pp = ap->private_data;
+ 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ 	struct ata_taskfile tf;
++	bool online;
+ 	int rc;
+ 
+ 	DPRINTK("ENTER\n");
+@@ -1422,14 +1350,13 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
+ 	tf.command = 0x80;
+ 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+ 
+-	rc = sata_std_hardreset(link, class, deadline);
++	rc = sata_link_hardreset(link, timing, deadline, &online,
++				 ahci_check_ready);
+ 
+ 	ahci_start_engine(ap);
+ 
+-	if (rc == 0 && ata_link_online(link))
++	if (online)
+ 		*class = ahci_dev_classify(ap);
+-	if (rc != -EAGAIN && *class == ATA_DEV_UNKNOWN)
+-		*class = ATA_DEV_NONE;
+ 
+ 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
+ 	return rc;
+@@ -1439,7 +1366,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
+ 				 unsigned long deadline)
+ {
+ 	struct ata_port *ap = link->ap;
+-	u32 serror;
++	bool online;
+ 	int rc;
+ 
+ 	DPRINTK("ENTER\n");
+@@ -1447,11 +1374,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
+ 	ahci_stop_engine(ap);
+ 
+ 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
+-				 deadline);
+-
+-	/* vt8251 needs SError cleared for the port to operate */
+-	ahci_scr_read(ap, SCR_ERROR, &serror);
+-	ahci_scr_write(ap, SCR_ERROR, serror);
++				 deadline, &online, NULL);
+ 
+ 	ahci_start_engine(ap);
+ 
+@@ -1460,7 +1383,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
+ 	/* vt8251 doesn't clear BSY on signature FIS reception,
+ 	 * request follow-up softreset.
+ 	 */
+-	return rc ?: -EAGAIN;
++	return online ? -EAGAIN : rc;
+ }
+ 
+ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+@@ -1470,6 +1393,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+ 	struct ahci_port_priv *pp = ap->private_data;
+ 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ 	struct ata_taskfile tf;
++	bool online;
+ 	int rc;
+ 
+ 	ahci_stop_engine(ap);
+@@ -1480,16 +1404,10 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+ 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+ 
+ 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
+-				 deadline);
++				 deadline, &online, NULL);
+ 
+ 	ahci_start_engine(ap);
+ 
+-	if (rc || ata_link_offline(link))
+-		return rc;
+-
+-	/* spec mandates ">= 2ms" before checking status */
+-	msleep(150);
+-
+ 	/* The pseudo configuration device on SIMG4726 attached to
+ 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
+ 	 * hardreset if no device is attached to the first downstream
+@@ -1503,11 +1421,13 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+ 	 * have to be reset again.  For most cases, this should
+ 	 * suffice while making probing snappish enough.
+ 	 */
+-	rc = ata_wait_ready(ap, jiffies + 2 * HZ);
+-	if (rc)
+-		ahci_kick_engine(ap, 0);
+-
+-	return 0;
++	if (online) {
++		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
++					  ahci_check_ready);
++		if (rc)
++			ahci_kick_engine(ap, 0);
++	}
++	return rc;
+ }
+ 
+ static void ahci_postreset(struct ata_link *link, unsigned int *class)
+@@ -1530,27 +1450,6 @@ static void ahci_postreset(struct ata_link *link, unsigned int *class)
+ 	}
+ }
+ 
+-static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
+-			      unsigned long deadline)
+-{
+-	return ahci_do_softreset(link, class, link->pmp, deadline);
+-}
+-
+-static u8 ahci_check_status(struct ata_port *ap)
+-{
+-	void __iomem *mmio = ap->ioaddr.cmd_addr;
+-
+-	return readl(mmio + PORT_TFDATA) & 0xFF;
+-}
+-
+-static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+-	struct ahci_port_priv *pp = ap->private_data;
+-	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+-
+-	ata_tf_from_fis(d2h_fis, tf);
+-}
+-
+ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
+ {
+ 	struct scatterlist *sg;
+@@ -1663,27 +1562,27 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
+ 		u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
+ 
+ 		active_ehi->err_mask |= AC_ERR_HSM;
+-		active_ehi->action |= ATA_EH_SOFTRESET;
++		active_ehi->action |= ATA_EH_RESET;
+ 		ata_ehi_push_desc(active_ehi,
+ 				  "unknown FIS %08x %08x %08x %08x" ,
+ 				  unk[0], unk[1], unk[2], unk[3]);
+ 	}
+ 
+-	if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) {
++	if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
+ 		active_ehi->err_mask |= AC_ERR_HSM;
+-		active_ehi->action |= ATA_EH_SOFTRESET;
++		active_ehi->action |= ATA_EH_RESET;
+ 		ata_ehi_push_desc(active_ehi, "incorrect PMP");
+ 	}
+ 
+ 	if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
+ 		host_ehi->err_mask |= AC_ERR_HOST_BUS;
+-		host_ehi->action |= ATA_EH_SOFTRESET;
++		host_ehi->action |= ATA_EH_RESET;
+ 		ata_ehi_push_desc(host_ehi, "host bus error");
+ 	}
+ 
+ 	if (irq_stat & PORT_IRQ_IF_ERR) {
+ 		host_ehi->err_mask |= AC_ERR_ATA_BUS;
+-		host_ehi->action |= ATA_EH_SOFTRESET;
++		host_ehi->action |= ATA_EH_RESET;
+ 		ata_ehi_push_desc(host_ehi, "interface fatal error");
+ 	}
+ 
+@@ -1704,7 +1603,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
+ 
+ static void ahci_port_intr(struct ata_port *ap)
+ {
+-	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
++	void __iomem *port_mmio = ahci_port_base(ap);
+ 	struct ata_eh_info *ehi = &ap->link.eh_info;
+ 	struct ahci_port_priv *pp = ap->private_data;
+ 	struct ahci_host_priv *hpriv = ap->host->private_data;
+@@ -1766,21 +1665,16 @@ static void ahci_port_intr(struct ata_port *ap)
+ 	else
+ 		qc_active = readl(port_mmio + PORT_CMD_ISSUE);
+ 
+-	rc = ata_qc_complete_multiple(ap, qc_active, NULL);
++	rc = ata_qc_complete_multiple(ap, qc_active);
+ 
+ 	/* while resetting, invalid completions are expected */
+ 	if (unlikely(rc < 0 && !resetting)) {
+ 		ehi->err_mask |= AC_ERR_HSM;
+-		ehi->action |= ATA_EH_SOFTRESET;
++		ehi->action |= ATA_EH_RESET;
+ 		ata_port_freeze(ap);
+ 	}
+ }
+ 
+-static void ahci_irq_clear(struct ata_port *ap)
+-{
+-	/* TODO */
+-}
+-
+ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
+ {
+ 	struct ata_host *host = dev_instance;
+@@ -1854,6 +1748,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
+ 	return 0;
+ }
+ 
++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;
++
++	ata_tf_from_fis(d2h_fis, &qc->result_tf);
++	return true;
++}
++
+ static void ahci_freeze(struct ata_port *ap)
+ {
+ 	void __iomem *port_mmio = ahci_port_base(ap);
+@@ -1886,37 +1789,7 @@ static void ahci_error_handler(struct ata_port *ap)
+ 		ahci_start_engine(ap);
+ 	}
+ 
+-	/* perform recovery */
+-	sata_pmp_do_eh(ap, ata_std_prereset, ahci_softreset,
+-		       ahci_hardreset, ahci_postreset,
+-		       sata_pmp_std_prereset, ahci_pmp_softreset,
+-		       sata_pmp_std_hardreset, sata_pmp_std_postreset);
+-}
+-
+-static void ahci_vt8251_error_handler(struct ata_port *ap)
+-{
+-	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+-		/* restart engine */
+-		ahci_stop_engine(ap);
+-		ahci_start_engine(ap);
+-	}
+-
+-	/* perform recovery */
+-	ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_vt8251_hardreset,
+-		  ahci_postreset);
+-}
+-
+-static void ahci_p5wdh_error_handler(struct ata_port *ap)
+-{
+-	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+-		/* restart engine */
+-		ahci_stop_engine(ap);
+-		ahci_start_engine(ap);
+-	}
+-
+-	/* perform recovery */
+-	ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_p5wdh_hardreset,
+-		  ahci_postreset);
++	sata_pmp_error_handler(ap);
+ }
+ 
+ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
+@@ -1961,7 +1834,7 @@ static int ahci_port_resume(struct ata_port *ap)
+ 	ahci_power_up(ap);
+ 	ahci_start_port(ap);
+ 
+-	if (ap->nr_pmp_links)
++	if (sata_pmp_attached(ap))
+ 		ahci_pmp_attach(ap);
+ 	else
+ 		ahci_pmp_detach(ap);
+@@ -2324,7 +2197,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	for (i = 0; i < host->n_ports; i++) {
+ 		struct ata_port *ap = host->ports[i];
+-		void __iomem *port_mmio = ahci_port_base(ap);
+ 
+ 		ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
+ 		ata_port_pbar_desc(ap, AHCI_PCI_BAR,
+@@ -2333,12 +2205,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		/* set initial link pm policy */
+ 		ap->pm_policy = NOT_AVAILABLE;
+ 
+-		/* standard SATA port setup */
+-		if (hpriv->port_map & (1 << i))
+-			ap->ioaddr.cmd_addr = port_mmio;
+-
+ 		/* disabled/not-implemented port */
+-		else
++		if (!(hpriv->port_map & (1 << i)))
+ 			ap->ops = &ata_dummy_port_ops;
+ 	}
+ 
+diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
+index 2053420..47aeccd 100644
+--- a/drivers/ata/ata_generic.c
++++ b/drivers/ata/ata_generic.c
+@@ -95,53 +95,13 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
+ }
+ 
+ static struct scsi_host_template generic_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations generic_port_ops = {
+-	.set_mode	= generic_set_mode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_bmdma_port_ops,
+ 	.cable_detect	= ata_cable_unknown,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_mode	= generic_set_mode,
+ };
+ 
+ static int all_generic_ide;		/* Set to claim all devices */
+@@ -160,7 +120,6 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
+ {
+ 	u16 command;
+ 	static const struct ata_port_info info = {
+-		.sht = &generic_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -191,9 +150,9 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
+ 		return -ENODEV;
+ 
+ 	if (dev->vendor == PCI_VENDOR_ID_AL)
+-	    	ata_pci_clear_simplex(dev);
++		ata_pci_bmdma_clear_simplex(dev);
+ 
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL);
+ }
+ 
+ static struct pci_device_id ata_generic[] = {
+diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
+index fae8404..ea2c764 100644
+--- a/drivers/ata/ata_piix.c
++++ b/drivers/ata/ata_piix.c
+@@ -100,13 +100,11 @@ enum {
+ 	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */
+ 	ICH5_PMR		= 0x90, /* port mapping register */
+ 	ICH5_PCS		= 0x92,	/* port control and status */
+-	PIIX_SCC		= 0x0A, /* sub-class code register */
+ 	PIIX_SIDPR_BAR		= 5,
+ 	PIIX_SIDPR_LEN		= 16,
+ 	PIIX_SIDPR_IDX		= 0,
+ 	PIIX_SIDPR_DATA		= 4,
+ 
+-	PIIX_FLAG_AHCI		= (1 << 27), /* AHCI possible */
+ 	PIIX_FLAG_CHECKINTR	= (1 << 28), /* make sure PCI INTx enabled */
+ 	PIIX_FLAG_SIDPR		= (1 << 29), /* SATA idx/data pair regs */
+ 
+@@ -140,12 +138,11 @@ enum piix_controller_ids {
+ 	ich_pata_100,		/* ICH up to UDMA 100 */
+ 	ich5_sata,
+ 	ich6_sata,
+-	ich6_sata_ahci,
+-	ich6m_sata_ahci,
+-	ich8_sata_ahci,
++	ich6m_sata,
++	ich8_sata,
+ 	ich8_2port_sata,
+-	ich8m_apple_sata_ahci,	/* locks up on second port enable */
+-	tolapai_sata_ahci,
++	ich8m_apple_sata,	/* locks up on second port enable */
++	tolapai_sata,
+ 	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
+ };
+ 
+@@ -162,7 +159,7 @@ struct piix_host_priv {
+ 
+ static int piix_init_one(struct pci_dev *pdev,
+ 			 const struct pci_device_id *ent);
+-static void piix_pata_error_handler(struct ata_port *ap);
++static int piix_pata_prereset(struct ata_link *link, unsigned long deadline);
+ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);
+ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+@@ -170,7 +167,6 @@ static int ich_pata_cable_detect(struct ata_port *ap);
+ static u8 piix_vmw_bmdma_status(struct ata_port *ap);
+ static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
+ static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
+-static void piix_sidpr_error_handler(struct ata_port *ap);
+ #ifdef CONFIG_PM
+ static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+ static int piix_pci_device_resume(struct pci_dev *pdev);
+@@ -236,25 +232,27 @@ static const struct pci_device_id piix_pci_tbl[] = {
+ 	/* 82801FB/FW (ICH6/ICH6W) */
+ 	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+ 	/* 82801FR/FRW (ICH6R/ICH6RW) */
+-	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+-	/* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */
+-	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
++	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
++	/* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented).
++	 * Attach iff the controller is in IDE mode. */
++	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID,
++	  PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich6m_sata },
+ 	/* 82801GB/GR/GH (ICH7, identical to ICH6) */
+-	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
++	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+ 	/* 2801GBM/GHM (ICH7M, identical to ICH6M) */
+-	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
++	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata },
+ 	/* Enterprise Southbridge 2 (631xESB/632xESB) */
+-	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
++	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+ 	/* SATA Controller 1 IDE (ICH8) */
+-	{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++	{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ 	/* SATA Controller 2 IDE (ICH8) */
+ 	{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ 	/* Mobile SATA Controller IDE (ICH8M) */
+-	{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++	{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ 	/* Mobile SATA Controller IDE (ICH8M), Apple */
+-	{ 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata_ahci },
++	{ 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata },
+ 	/* SATA Controller IDE (ICH9) */
+-	{ 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++	{ 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ 	/* SATA Controller IDE (ICH9) */
+ 	{ 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ 	/* SATA Controller IDE (ICH9) */
+@@ -264,15 +262,15 @@ static const struct pci_device_id piix_pci_tbl[] = {
+ 	/* SATA Controller IDE (ICH9M) */
+ 	{ 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ 	/* SATA Controller IDE (ICH9M) */
+-	{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++	{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ 	/* SATA Controller IDE (Tolapai) */
+-	{ 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata_ahci },
++	{ 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata },
+ 	/* SATA Controller IDE (ICH10) */
+-	{ 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++	{ 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ 	/* SATA Controller IDE (ICH10) */
+ 	{ 0x8086, 0x3a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ 	/* SATA Controller IDE (ICH10) */
+-	{ 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++	{ 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ 	/* SATA Controller IDE (ICH10) */
+ 	{ 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ 
+@@ -291,170 +289,37 @@ static struct pci_driver piix_pci_driver = {
+ };
+ 
+ static struct scsi_host_template piix_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations piix_pata_ops = {
++static struct ata_port_operations piix_pata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.cable_detect		= ata_cable_40wire,
+ 	.set_piomode		= piix_set_piomode,
+ 	.set_dmamode		= piix_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= piix_pata_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= ata_cable_40wire,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
++	.prereset		= piix_pata_prereset,
++};
+ 
+-	.port_start		= ata_port_start,
++static struct ata_port_operations piix_vmw_ops = {
++	.inherits		= &piix_pata_ops,
++	.bmdma_status		= piix_vmw_bmdma_status,
+ };
+ 
+-static const struct ata_port_operations ich_pata_ops = {
+-	.set_piomode		= piix_set_piomode,
+-	.set_dmamode		= ich_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= piix_pata_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
++static struct ata_port_operations ich_pata_ops = {
++	.inherits		= &piix_pata_ops,
+ 	.cable_detect		= ich_pata_cable_detect,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_port_start,
++	.set_dmamode		= ich_set_dmamode,
+ };
+ 
+-static const struct ata_port_operations piix_sata_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_port_start,
++static struct ata_port_operations piix_sata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
+ };
+ 
+-static const struct ata_port_operations piix_vmw_ops = {
+-	.set_piomode		= piix_set_piomode,
+-	.set_dmamode		= piix_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= piix_vmw_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= piix_pata_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= ata_cable_40wire,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_port_start,
+-};
+-
+-static const struct ata_port_operations piix_sidpr_sata_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
++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,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= piix_sidpr_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_port_start,
+ };
+ 
+ static const struct piix_map_db ich5_map_db = {
+@@ -553,12 +418,11 @@ static const struct piix_map_db tolapai_map_db = {
+ static const struct piix_map_db *piix_map_db_table[] = {
+ 	[ich5_sata]		= &ich5_map_db,
+ 	[ich6_sata]		= &ich6_map_db,
+-	[ich6_sata_ahci]	= &ich6_map_db,
+-	[ich6m_sata_ahci]	= &ich6m_map_db,
+-	[ich8_sata_ahci]	= &ich8_map_db,
++	[ich6m_sata]		= &ich6m_map_db,
++	[ich8_sata]		= &ich8_map_db,
+ 	[ich8_2port_sata]	= &ich8_2port_map_db,
+-	[ich8m_apple_sata_ahci]	= &ich8m_apple_map_db,
+-	[tolapai_sata_ahci]	= &tolapai_map_db,
++	[ich8m_apple_sata]	= &ich8m_apple_map_db,
++	[tolapai_sata]		= &tolapai_map_db,
+ };
+ 
+ static struct ata_port_info piix_port_info[] = {
+@@ -624,28 +488,18 @@ static struct ata_port_info piix_port_info[] = {
+ 		.port_ops	= &piix_sata_ops,
+ 	},
+ 
+-	[ich6_sata_ahci] =
+-	{
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
+-		.pio_mask	= 0x1f,	/* pio0-4 */
+-		.mwdma_mask	= 0x07, /* mwdma0-2 */
+-		.udma_mask	= ATA_UDMA6,
+-		.port_ops	= &piix_sata_ops,
+-	},
+-
+-	[ich6m_sata_ahci] =
++	[ich6m_sata] =
+ 	{
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
++		.flags		= PIIX_SATA_FLAGS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &piix_sata_ops,
+ 	},
+ 
+-	[ich8_sata_ahci] =
++	[ich8_sata] =
+ 	{
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
+-				  PIIX_FLAG_SIDPR,
++		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -654,27 +508,25 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[ich8_2port_sata] =
+ 	{
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
+-				  PIIX_FLAG_SIDPR,
++		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &piix_sata_ops,
+ 	},
+ 
+-	[tolapai_sata_ahci] =
++	[tolapai_sata] =
+ 	{
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
++		.flags		= PIIX_SATA_FLAGS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &piix_sata_ops,
+ 	},
+ 
+-	[ich8m_apple_sata_ahci] =
++	[ich8m_apple_sata] =
+ 	{
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
+-				  PIIX_FLAG_SIDPR,
++		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -683,7 +535,6 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[piix_pata_vmw] =
+ 	{
+-		.sht		= &piix_sht,
+ 		.flags		= PIIX_PATA_FLAGS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+@@ -722,6 +573,7 @@ static const struct ich_laptop ich_laptop[] = {
+ 	{ 0x27DF, 0x1043, 0x1267 },	/* ICH7 on Asus W5F */
+ 	{ 0x27DF, 0x103C, 0x30A1 },	/* ICH7 on HP Compaq nc2400 */
+ 	{ 0x24CA, 0x1025, 0x0061 },	/* ICH4 on ACER Aspire 2023WLMi */
++	{ 0x2653, 0x1043, 0x82D8 },	/* ICH6M on Asus Eee 701 */
+ 	/* end marker */
+ 	{ 0, }
+ };
+@@ -776,13 +628,7 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
+ 
+ 	if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-static void piix_pata_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL,
+-			   ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -1168,35 +1014,6 @@ static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
+ 	return 0;
+ }
+ 
+-static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
+-				unsigned long deadline)
+-{
+-	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+-	int rc;
+-
+-	/* do hardreset */
+-	rc = sata_link_hardreset(link, timing, deadline);
+-	if (rc) {
+-		ata_link_printk(link, KERN_ERR,
+-				"COMRESET failed (errno=%d)\n", rc);
+-		return rc;
+-	}
+-
+-	/* TODO: phy layer with polling, timeouts, etc. */
+-	if (ata_link_offline(link)) {
+-		*class = ATA_DEV_NONE;
+-		return 0;
+-	}
+-
+-	return -EAGAIN;
+-}
+-
+-static void piix_sidpr_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+-			   piix_sidpr_hardreset, ata_std_postreset);
+-}
+-
+ #ifdef CONFIG_PM
+ static int piix_broken_suspend(void)
+ {
+@@ -1633,6 +1450,16 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
+ 	if (rc)
+ 		return rc;
+ 
++	/* ICH6R may be driven by either ata_piix or ahci driver
++	 * regardless of BIOS configuration.  Make sure AHCI mode is
++	 * off.
++	 */
++	if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2652) {
++		int rc = piix_disable_ahci(pdev);
++		if (rc)
++			return rc;
++	}
++
+ 	/* SATA map init can change port_info, do it before prepping host */
+ 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+ 	if (!hpriv)
+@@ -1642,22 +1469,12 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
+ 		hpriv->map = piix_init_sata_map(pdev, port_info,
+ 					piix_map_db_table[ent->driver_data]);
+ 
+-	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ 	if (rc)
+ 		return rc;
+ 	host->private_data = hpriv;
+ 
+ 	/* initialize controller */
+-	if (port_flags & PIIX_FLAG_AHCI) {
+-		u8 tmp;
+-		pci_read_config_byte(pdev, PIIX_SCC, &tmp);
+-		if (tmp == PIIX_AHCI_DEVICE) {
+-			rc = piix_disable_ahci(pdev);
+-			if (rc)
+-				return rc;
+-		}
+-	}
+-
+ 	if (port_flags & ATA_FLAG_SATA) {
+ 		piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
+ 		piix_init_sidpr(host);
+@@ -1686,7 +1503,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
+ 	}
+ 
+ 	pci_set_master(pdev);
+-	return ata_pci_activate_sff_host(host, ata_interrupt, &piix_sht);
++	return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
+ }
+ 
+ static int __init piix_init(void)
+diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
+index bf98a56..70b77e0 100644
+--- a/drivers/ata/libata-acpi.c
++++ b/drivers/ata/libata-acpi.c
+@@ -77,7 +77,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap)
+ {
+ 	WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA));
+ 
+-	if (!ap->nr_pmp_links) {
++	if (!sata_pmp_attached(ap)) {
+ 		acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
+ 
+ 		ap->link.device->acpi_handle =
+@@ -227,11 +227,9 @@ void ata_acpi_associate(struct ata_host *host)
+ 			acpi_install_notify_handler(ap->acpi_handle,
+ 						    ACPI_SYSTEM_NOTIFY,
+ 						    ata_acpi_ap_notify, ap);
+-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
+ 			/* we might be on a docking station */
+ 			register_hotplug_dock_device(ap->acpi_handle,
+ 						     ata_acpi_ap_notify, ap);
+-#endif
+ 		}
+ 
+ 		for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
+@@ -241,11 +239,9 @@ void ata_acpi_associate(struct ata_host *host)
+ 				acpi_install_notify_handler(dev->acpi_handle,
+ 						ACPI_SYSTEM_NOTIFY,
+ 						ata_acpi_dev_notify, dev);
+-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
+ 				/* we might be on a docking station */
+ 				register_hotplug_dock_device(dev->acpi_handle,
+ 						ata_acpi_dev_notify, dev);
+-#endif
+ 			}
+ 		}
+ 	}
+@@ -839,7 +835,8 @@ void ata_acpi_on_resume(struct ata_port *ap)
+ 		 */
+ 		ata_link_for_each_dev(dev, &ap->link) {
+ 			ata_acpi_clear_gtf(dev);
+-			if (ata_dev_get_GTF(dev, NULL) >= 0)
++			if (ata_dev_enabled(dev) &&
++			    ata_dev_get_GTF(dev, NULL) >= 0)
+ 				dev->flags |= ATA_DFLAG_ACPI_PENDING;
+ 		}
+ 	} else {
+@@ -849,7 +846,8 @@ void ata_acpi_on_resume(struct ata_port *ap)
+ 		 */
+ 		ata_link_for_each_dev(dev, &ap->link) {
+ 			ata_acpi_clear_gtf(dev);
+-			dev->flags |= ATA_DFLAG_ACPI_PENDING;
++			if (ata_dev_enabled(dev))
++				dev->flags |= ATA_DFLAG_ACPI_PENDING;
+ 		}
+ 	}
+ }
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index be95fdb..51b7d2f 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -46,7 +46,6 @@
+ #include <linux/init.h>
+ #include <linux/list.h>
+ #include <linux/mm.h>
+-#include <linux/highmem.h>
+ #include <linux/spinlock.h>
+ #include <linux/blkdev.h>
+ #include <linux/delay.h>
+@@ -62,7 +61,6 @@
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_host.h>
+ #include <linux/libata.h>
+-#include <asm/semaphore.h>
+ #include <asm/byteorder.h>
+ #include <linux/cdrom.h>
+ 
+@@ -74,6 +72,19 @@ const unsigned long sata_deb_timing_normal[]		= {   5,  100, 2000 };
+ const unsigned long sata_deb_timing_hotplug[]		= {  25,  500, 2000 };
+ const unsigned long sata_deb_timing_long[]		= { 100, 2000, 5000 };
+ 
++const struct ata_port_operations ata_base_port_ops = {
++	.prereset		= ata_std_prereset,
++	.postreset		= ata_std_postreset,
++	.error_handler		= ata_std_error_handler,
++};
++
++const struct ata_port_operations sata_port_ops = {
++	.inherits		= &ata_base_port_ops,
++
++	.qc_defer		= ata_std_qc_defer,
++	.hardreset		= sata_std_hardreset,
++};
++
+ 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);
+@@ -1043,50 +1054,6 @@ static void ata_lpm_disable(struct ata_host *host)
+ }
+ #endif	/* CONFIG_PM */
+ 
+-
+-/**
+- *	ata_devchk - PATA device presence detection
+- *	@ap: ATA channel to examine
+- *	@device: Device to examine (starting at zero)
+- *
+- *	This technique was originally described in
+- *	Hale Landis's ATADRVR (www.ata-atapi.com), and
+- *	later found its way into the ATA/ATAPI spec.
+- *
+- *	Write a pattern to the ATA shadow registers,
+- *	and if a device is present, it will respond by
+- *	correctly storing and echoing back the
+- *	ATA shadow register contents.
+- *
+- *	LOCKING:
+- *	caller.
+- */
+-
+-static unsigned int ata_devchk(struct ata_port *ap, unsigned int device)
+-{
+-	struct ata_ioports *ioaddr = &ap->ioaddr;
+-	u8 nsect, lbal;
+-
+-	ap->ops->dev_select(ap, device);
+-
+-	iowrite8(0x55, ioaddr->nsect_addr);
+-	iowrite8(0xaa, ioaddr->lbal_addr);
+-
+-	iowrite8(0xaa, ioaddr->nsect_addr);
+-	iowrite8(0x55, ioaddr->lbal_addr);
+-
+-	iowrite8(0x55, ioaddr->nsect_addr);
+-	iowrite8(0xaa, ioaddr->lbal_addr);
+-
+-	nsect = ioread8(ioaddr->nsect_addr);
+-	lbal = ioread8(ioaddr->lbal_addr);
+-
+-	if ((nsect == 0x55) && (lbal == 0xaa))
+-		return 1;	/* we found a device */
+-
+-	return 0;		/* nothing found */
+-}
+-
+ /**
+  *	ata_dev_classify - determine device type based on ATA-spec signature
+  *	@tf: ATA taskfile register set for device to be identified
+@@ -1147,75 +1114,6 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
+ }
+ 
+ /**
+- *	ata_dev_try_classify - Parse returned ATA device signature
+- *	@dev: ATA device to classify (starting at zero)
+- *	@present: device seems present
+- *	@r_err: Value of error register on completion
+- *
+- *	After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
+- *	an ATA/ATAPI-defined set of values is placed in the ATA
+- *	shadow registers, indicating the results of device detection
+- *	and diagnostics.
+- *
+- *	Select the ATA device, and read the values from the ATA shadow
+- *	registers.  Then parse according to the Error register value,
+- *	and the spec-defined values examined by ata_dev_classify().
+- *
+- *	LOCKING:
+- *	caller.
+- *
+- *	RETURNS:
+- *	Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
+- */
+-unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
+-				  u8 *r_err)
+-{
+-	struct ata_port *ap = dev->link->ap;
+-	struct ata_taskfile tf;
+-	unsigned int class;
+-	u8 err;
+-
+-	ap->ops->dev_select(ap, dev->devno);
+-
+-	memset(&tf, 0, sizeof(tf));
+-
+-	ap->ops->tf_read(ap, &tf);
+-	err = tf.feature;
+-	if (r_err)
+-		*r_err = err;
+-
+-	/* see if device passed diags: continue and warn later */
+-	if (err == 0)
+-		/* diagnostic fail : do nothing _YET_ */
+-		dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
+-	else if (err == 1)
+-		/* do nothing */ ;
+-	else if ((dev->devno == 0) && (err == 0x81))
+-		/* do nothing */ ;
+-	else
+-		return ATA_DEV_NONE;
+-
+-	/* determine if device is ATA or ATAPI */
+-	class = ata_dev_classify(&tf);
+-
+-	if (class == ATA_DEV_UNKNOWN) {
+-		/* If the device failed diagnostic, it's likely to
+-		 * have reported incorrect device signature too.
+-		 * Assume ATA device if the device seems present but
+-		 * device signature is invalid with diagnostic
+-		 * failure.
+-		 */
+-		if (present && (dev->horkage & ATA_HORKAGE_DIAGNOSTIC))
+-			class = ATA_DEV_ATA;
+-		else
+-			class = ATA_DEV_NONE;
+-	} else if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0))
+-		class = ATA_DEV_NONE;
+-
+-	return class;
+-}
+-
+-/**
+  *	ata_id_string - Convert IDENTIFY DEVICE page into string
+  *	@id: IDENTIFY DEVICE results we will examine
+  *	@s: string into which data is output
+@@ -1293,7 +1191,7 @@ static u64 ata_id_n_sectors(const u16 *id)
+ 	}
+ }
+ 
+-static u64 ata_tf_to_lba48(struct ata_taskfile *tf)
++u64 ata_tf_to_lba48(const struct ata_taskfile *tf)
+ {
+ 	u64 sectors = 0;
+ 
+@@ -1304,10 +1202,10 @@ static u64 ata_tf_to_lba48(struct ata_taskfile *tf)
+ 	sectors |= (tf->lbam & 0xff) << 8;
+ 	sectors |= (tf->lbal & 0xff);
+ 
+-	return ++sectors;
++	return sectors;
+ }
+ 
+-static u64 ata_tf_to_lba(struct ata_taskfile *tf)
++u64 ata_tf_to_lba(const struct ata_taskfile *tf)
+ {
+ 	u64 sectors = 0;
+ 
+@@ -1316,7 +1214,7 @@ static u64 ata_tf_to_lba(struct ata_taskfile *tf)
+ 	sectors |= (tf->lbam & 0xff) << 8;
+ 	sectors |= (tf->lbal & 0xff);
+ 
+-	return ++sectors;
++	return sectors;
+ }
+ 
+ /**
+@@ -1361,9 +1259,9 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
+ 	}
+ 
+ 	if (lba48)
+-		*max_sectors = ata_tf_to_lba48(&tf);
++		*max_sectors = ata_tf_to_lba48(&tf) + 1;
+ 	else
+-		*max_sectors = ata_tf_to_lba(&tf);
++		*max_sectors = ata_tf_to_lba(&tf) + 1;
+ 	if (dev->horkage & ATA_HORKAGE_HPA_SIZE)
+ 		(*max_sectors)--;
+ 	return 0;
+@@ -1523,89 +1421,6 @@ static int ata_hpa_resize(struct ata_device *dev)
+ }
+ 
+ /**
+- *	ata_noop_dev_select - Select device 0/1 on ATA bus
+- *	@ap: ATA channel to manipulate
+- *	@device: ATA device (numbered from zero) to select
+- *
+- *	This function performs no actual function.
+- *
+- *	May be used as the dev_select() entry in ata_port_operations.
+- *
+- *	LOCKING:
+- *	caller.
+- */
+-void ata_noop_dev_select(struct ata_port *ap, unsigned int device)
+-{
+-}
+-
+-
+-/**
+- *	ata_std_dev_select - Select device 0/1 on ATA bus
+- *	@ap: ATA channel to manipulate
+- *	@device: ATA device (numbered from zero) to select
+- *
+- *	Use the method defined in the ATA specification to
+- *	make either device 0, or device 1, active on the
+- *	ATA channel.  Works with both PIO and MMIO.
+- *
+- *	May be used as the dev_select() entry in ata_port_operations.
+- *
+- *	LOCKING:
+- *	caller.
+- */
+-
+-void ata_std_dev_select(struct ata_port *ap, unsigned int device)
+-{
+-	u8 tmp;
+-
+-	if (device == 0)
+-		tmp = ATA_DEVICE_OBS;
+-	else
+-		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+-
+-	iowrite8(tmp, ap->ioaddr.device_addr);
+-	ata_pause(ap);		/* needed; also flushes, for mmio */
+-}
+-
+-/**
+- *	ata_dev_select - Select device 0/1 on ATA bus
+- *	@ap: ATA channel to manipulate
+- *	@device: ATA device (numbered from zero) to select
+- *	@wait: non-zero to wait for Status register BSY bit to clear
+- *	@can_sleep: non-zero if context allows sleeping
+- *
+- *	Use the method defined in the ATA specification to
+- *	make either device 0, or device 1, active on the
+- *	ATA channel.
+- *
+- *	This is a high-level version of ata_std_dev_select(),
+- *	which additionally provides the services of inserting
+- *	the proper pauses and status polling, where needed.
+- *
+- *	LOCKING:
+- *	caller.
+- */
+-
+-void ata_dev_select(struct ata_port *ap, unsigned int device,
+-			   unsigned int wait, unsigned int can_sleep)
+-{
+-	if (ata_msg_probe(ap))
+-		ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
+-				"device %u, wait %u\n", device, wait);
+-
+-	if (wait)
+-		ata_wait_idle(ap);
+-
+-	ap->ops->dev_select(ap, device);
+-
+-	if (wait) {
+-		if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
+-			msleep(150);
+-		ata_wait_idle(ap);
+-	}
+-}
+-
+-/**
+  *	ata_dump_id - IDENTIFY DEVICE info debugging output
+  *	@id: IDENTIFY DEVICE page to dump
+  *
+@@ -1732,8 +1547,7 @@ unsigned long ata_id_xfermask(const u16 *id)
+  *	LOCKING:
+  *	Inherited from caller.
+  */
+-static void ata_pio_queue_task(struct ata_port *ap, void *data,
+-			       unsigned long delay)
++void ata_pio_queue_task(struct ata_port *ap, void *data, unsigned long delay)
+ {
+ 	ap->port_task_data = data;
+ 
+@@ -2097,7 +1911,6 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+ 	if (ata_msg_ctl(ap))
+ 		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
+ 
+-	ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
+  retry:
+ 	ata_tf_init(dev, &tf);
+ 
+@@ -2464,7 +2277,7 @@ int ata_dev_configure(struct ata_device *dev)
+ 		 * changed notifications and ATAPI ANs.
+ 		 */
+ 		if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
+-		    (!ap->nr_pmp_links ||
++		    (!sata_pmp_attached(ap) ||
+ 		     sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
+ 			unsigned int err_mask;
+ 
+@@ -2558,9 +2371,6 @@ int ata_dev_configure(struct ata_device *dev)
+ 		}
+ 	}
+ 
+-	if (ata_msg_probe(ap))
+-		ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
+-			__func__, ata_chk_status(ap));
+ 	return 0;
+ 
+ err_out_nosup:
+@@ -2806,7 +2616,7 @@ void ata_port_probe(struct ata_port *ap)
+  *	LOCKING:
+  *	None.
+  */
+-void sata_print_link_status(struct ata_link *link)
++static void sata_print_link_status(struct ata_link *link)
+ {
+ 	u32 sstatus, scontrol, tmp;
+ 
+@@ -2962,7 +2772,7 @@ static int __sata_set_spd_needed(struct ata_link *link, u32 *scontrol)
+  *	RETURNS:
+  *	1 if SATA spd configuration is needed, 0 otherwise.
+  */
+-int sata_set_spd_needed(struct ata_link *link)
++static int sata_set_spd_needed(struct ata_link *link)
+ {
+ 	u32 scontrol;
+ 
+@@ -3321,16 +3131,21 @@ static int ata_dev_set_mode(struct ata_device *dev)
+ 	if (rc)
+ 		return rc;
+ 
+-	/* Old CFA may refuse this command, which is just fine */
+-	if (dev->xfer_shift == ATA_SHIFT_PIO && ata_id_is_cfa(dev->id))
+-		ign_dev_err = 1;
+-
+-	/* Some very old devices and some bad newer ones fail any kind of
+-	   SET_XFERMODE request but support PIO0-2 timings and no IORDY */
+-	if (dev->xfer_shift == ATA_SHIFT_PIO && !ata_id_has_iordy(dev->id) &&
+-			dev->pio_mode <= XFER_PIO_2)
+-		ign_dev_err = 1;
+-
++	if (dev->xfer_shift == ATA_SHIFT_PIO) {
++		/* Old CFA may refuse this command, which is just fine */
++		if (ata_id_is_cfa(dev->id))
++			ign_dev_err = 1;
++		/* Catch several broken garbage emulations plus some pre
++		   ATA devices */
++		if (ata_id_major_version(dev->id) == 0 &&
++					dev->pio_mode <= XFER_PIO_2)
++			ign_dev_err = 1;
++		/* Some very old devices and some bad newer ones fail
++		   any kind of SET_XFERMODE request but support PIO0-2
++		   timings and no IORDY */
++		if (!ata_id_has_iordy(dev->id) && dev->pio_mode <= XFER_PIO_2)
++			ign_dev_err = 1;
++	}
+ 	/* Early MWDMA devices do DMA but don't allow DMA mode setting.
+ 	   Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */
+ 	if (dev->xfer_shift == ATA_SHIFT_MWDMA &&
+@@ -3474,170 +3289,73 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ }
+ 
+ /**
+- *	ata_tf_to_host - issue ATA taskfile to host controller
+- *	@ap: port to which command is being issued
+- *	@tf: ATA taskfile register set
+- *
+- *	Issues ATA taskfile register set to ATA host controller,
+- *	with proper synchronization with interrupt handler and
+- *	other threads.
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- */
+-
+-static inline void ata_tf_to_host(struct ata_port *ap,
+-				  const struct ata_taskfile *tf)
+-{
+-	ap->ops->tf_load(ap, tf);
+-	ap->ops->exec_command(ap, tf);
+-}
+-
+-/**
+- *	ata_busy_sleep - sleep until BSY clears, or timeout
+- *	@ap: port containing status register to be polled
+- *	@tmout_pat: impatience timeout
+- *	@tmout: overall timeout
+- *
+- *	Sleep until ATA Status register bit BSY clears,
+- *	or a timeout occurs.
+- *
+- *	LOCKING:
+- *	Kernel thread context (may sleep).
+- *
+- *	RETURNS:
+- *	0 on success, -errno otherwise.
+- */
+-int ata_busy_sleep(struct ata_port *ap,
+-		   unsigned long tmout_pat, unsigned long tmout)
+-{
+-	unsigned long timer_start, timeout;
+-	u8 status;
+-
+-	status = ata_busy_wait(ap, ATA_BUSY, 300);
+-	timer_start = jiffies;
+-	timeout = timer_start + tmout_pat;
+-	while (status != 0xff && (status & ATA_BUSY) &&
+-	       time_before(jiffies, timeout)) {
+-		msleep(50);
+-		status = ata_busy_wait(ap, ATA_BUSY, 3);
+-	}
+-
+-	if (status != 0xff && (status & ATA_BUSY))
+-		ata_port_printk(ap, KERN_WARNING,
+-				"port is slow to respond, please be patient "
+-				"(Status 0x%x)\n", status);
+-
+-	timeout = timer_start + tmout;
+-	while (status != 0xff && (status & ATA_BUSY) &&
+-	       time_before(jiffies, timeout)) {
+-		msleep(50);
+-		status = ata_chk_status(ap);
+-	}
+-
+-	if (status == 0xff)
+-		return -ENODEV;
+-
+-	if (status & ATA_BUSY) {
+-		ata_port_printk(ap, KERN_ERR, "port failed to respond "
+-				"(%lu secs, Status 0x%x)\n",
+-				tmout / HZ, status);
+-		return -EBUSY;
+-	}
+-
+-	return 0;
+-}
+-
+-/**
+- *	ata_wait_after_reset - wait before checking status after reset
+- *	@ap: port containing status register to be polled
++ *	ata_wait_ready - wait for link to become ready
++ *	@link: link to be waited on
+  *	@deadline: deadline jiffies for the operation
++ *	@check_ready: callback to check link readiness
+  *
+- *	After reset, we need to pause a while before reading status.
+- *	Also, certain combination of controller and device report 0xff
+- *	for some duration (e.g. until SATA PHY is up and running)
+- *	which is interpreted as empty port in ATA world.  This
+- *	function also waits for such devices to get out of 0xff
+- *	status.
++ *	Wait for @link to become ready.  @check_ready should return
++ *	positive number if @link is ready, 0 if it isn't, -ENODEV if
++ *	link doesn't seem to be occupied, other errno for other error
++ *	conditions.
+  *
+- *	LOCKING:
+- *	Kernel thread context (may sleep).
+- */
+-void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline)
+-{
+-	unsigned long until = jiffies + ATA_TMOUT_FF_WAIT;
+-
+-	if (time_before(until, deadline))
+-		deadline = until;
+-
+-	/* Spec mandates ">= 2ms" before checking status.  We wait
+-	 * 150ms, because that was the magic delay used for ATAPI
+-	 * devices in Hale Landis's ATADRVR, for the period of time
+-	 * between when the ATA command register is written, and then
+-	 * status is checked.  Because waiting for "a while" before
+-	 * checking status is fine, post SRST, we perform this magic
+-	 * delay here as well.
+-	 *
+-	 * Old drivers/ide uses the 2mS rule and then waits for ready.
+-	 */
+-	msleep(150);
+-
+-	/* Wait for 0xff to clear.  Some SATA devices take a long time
+-	 * to clear 0xff after reset.  For example, HHD424020F7SV00
+-	 * iVDR needs >= 800ms while.  Quantum GoVault needs even more
+-	 * than that.
+-	 *
+-	 * Note that some PATA controllers (pata_ali) explode if
+-	 * status register is read more than once when there's no
+-	 * device attached.
+-	 */
+-	if (ap->flags & ATA_FLAG_SATA) {
+-		while (1) {
+-			u8 status = ata_chk_status(ap);
+-
+-			if (status != 0xff || time_after(jiffies, deadline))
+-				return;
+-
+-			msleep(50);
+-		}
+-	}
+-}
+-
+-/**
+- *	ata_wait_ready - sleep until BSY clears, or timeout
+- *	@ap: port containing status register to be polled
+- *	@deadline: deadline jiffies for the operation
+- *
+- *	Sleep until ATA Status register bit BSY clears, or timeout
+- *	occurs.
++ *	Transient -ENODEV conditions are allowed for
++ *	ATA_TMOUT_FF_WAIT.
+  *
+  *	LOCKING:
+- *	Kernel thread context (may sleep).
++ *	EH context.
+  *
+  *	RETURNS:
+- *	0 on success, -errno otherwise.
++ *	0 if @linke is ready before @deadline; otherwise, -errno.
+  */
+-int ata_wait_ready(struct ata_port *ap, unsigned long deadline)
++int ata_wait_ready(struct ata_link *link, unsigned long deadline,
++		   int (*check_ready)(struct ata_link *link))
+ {
+ 	unsigned long start = jiffies;
++	unsigned long nodev_deadline = start + ATA_TMOUT_FF_WAIT;
+ 	int warned = 0;
+ 
++	if (time_after(nodev_deadline, deadline))
++		nodev_deadline = deadline;
++
+ 	while (1) {
+-		u8 status = ata_chk_status(ap);
+ 		unsigned long now = jiffies;
++		int ready, tmp;
+ 
+-		if (!(status & ATA_BUSY))
++		ready = tmp = check_ready(link);
++		if (ready > 0)
+ 			return 0;
+-		if (!ata_link_online(&ap->link) && status == 0xff)
+-			return -ENODEV;
++
++		/* -ENODEV could be transient.  Ignore -ENODEV if link
++		 * is online.  Also, some SATA devices take a long
++		 * time to clear 0xff after reset.  For example,
++		 * HHD424020F7SV00 iVDR needs >= 800ms while Quantum
++		 * GoVault needs even more than that.  Wait for
++		 * ATA_TMOUT_FF_WAIT on -ENODEV if link isn't offline.
++		 *
++		 * Note that some PATA controllers (pata_ali) explode
++		 * if status register is read more than once when
++		 * there's no device attached.
++		 */
++		if (ready == -ENODEV) {
++			if (ata_link_online(link))
++				ready = 0;
++			else if ((link->ap->flags & ATA_FLAG_SATA) &&
++				 !ata_link_offline(link) &&
++				 time_before(now, nodev_deadline))
++				ready = 0;
++		}
++
++		if (ready)
++			return ready;
+ 		if (time_after(now, deadline))
+ 			return -EBUSY;
+ 
+ 		if (!warned && time_after(now, start + 5 * HZ) &&
+ 		    (deadline - now > 3 * HZ)) {
+-			ata_port_printk(ap, KERN_WARNING,
+-				"port is slow to respond, please be patient "
+-				"(Status 0x%x)\n", status);
++			ata_link_printk(link, KERN_WARNING,
++				"link is slow to respond, please be patient "
++				"(ready=%d)\n", tmp);
+ 			warned = 1;
+ 		}
+ 
+@@ -3645,179 +3363,26 @@ int ata_wait_ready(struct ata_port *ap, unsigned long deadline)
+ 	}
+ }
+ 
+-static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
+-			      unsigned long deadline)
+-{
+-	struct ata_ioports *ioaddr = &ap->ioaddr;
+-	unsigned int dev0 = devmask & (1 << 0);
+-	unsigned int dev1 = devmask & (1 << 1);
+-	int rc, ret = 0;
+-
+-	/* if device 0 was found in ata_devchk, wait for its
+-	 * BSY bit to clear
+-	 */
+-	if (dev0) {
+-		rc = ata_wait_ready(ap, deadline);
+-		if (rc) {
+-			if (rc != -ENODEV)
+-				return rc;
+-			ret = rc;
+-		}
+-	}
+-
+-	/* if device 1 was found in ata_devchk, wait for register
+-	 * access briefly, then wait for BSY to clear.
+-	 */
+-	if (dev1) {
+-		int i;
+-
+-		ap->ops->dev_select(ap, 1);
+-
+-		/* Wait for register access.  Some ATAPI devices fail
+-		 * to set nsect/lbal after reset, so don't waste too
+-		 * much time on it.  We're gonna wait for !BSY anyway.
+-		 */
+-		for (i = 0; i < 2; i++) {
+-			u8 nsect, lbal;
+-
+-			nsect = ioread8(ioaddr->nsect_addr);
+-			lbal = ioread8(ioaddr->lbal_addr);
+-			if ((nsect == 1) && (lbal == 1))
+-				break;
+-			msleep(50);	/* give drive a breather */
+-		}
+-
+-		rc = ata_wait_ready(ap, deadline);
+-		if (rc) {
+-			if (rc != -ENODEV)
+-				return rc;
+-			ret = rc;
+-		}
+-	}
+-
+-	/* is all this really necessary? */
+-	ap->ops->dev_select(ap, 0);
+-	if (dev1)
+-		ap->ops->dev_select(ap, 1);
+-	if (dev0)
+-		ap->ops->dev_select(ap, 0);
+-
+-	return ret;
+-}
+-
+-static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
+-			     unsigned long deadline)
+-{
+-	struct ata_ioports *ioaddr = &ap->ioaddr;
+-
+-	DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
+-
+-	/* software reset.  causes dev0 to be selected */
+-	iowrite8(ap->ctl, ioaddr->ctl_addr);
+-	udelay(20);	/* FIXME: flush */
+-	iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+-	udelay(20);	/* FIXME: flush */
+-	iowrite8(ap->ctl, ioaddr->ctl_addr);
+-
+-	/* wait a while before checking status */
+-	ata_wait_after_reset(ap, deadline);
+-
+-	/* Before we perform post reset processing we want to see if
+-	 * the bus shows 0xFF because the odd clown forgets the D7
+-	 * pulldown resistor.
+-	 */
+-	if (ata_chk_status(ap) == 0xFF)
+-		return -ENODEV;
+-
+-	return ata_bus_post_reset(ap, devmask, deadline);
+-}
+-
+ /**
+- *	ata_bus_reset - reset host port and associated ATA channel
+- *	@ap: port to reset
++ *	ata_wait_after_reset - wait for link to become ready after reset
++ *	@link: link to be waited on
++ *	@deadline: deadline jiffies for the operation
++ *	@check_ready: callback to check link readiness
+  *
+- *	This is typically the first time we actually start issuing
+- *	commands to the ATA channel.  We wait for BSY to clear, then
+- *	issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
+- *	result.  Determine what devices, if any, are on the channel
+- *	by looking at the device 0/1 error register.  Look at the signature
+- *	stored in each device's taskfile registers, to determine if
+- *	the device is ATA or ATAPI.
++ *	Wait for @link to become ready after reset.
+  *
+  *	LOCKING:
+- *	PCI/etc. bus probe sem.
+- *	Obtains host lock.
++ *	EH context.
+  *
+- *	SIDE EFFECTS:
+- *	Sets ATA_FLAG_DISABLED if bus reset fails.
++ *	RETURNS:
++ *	0 if @linke is ready before @deadline; otherwise, -errno.
+  */
+-
+-void ata_bus_reset(struct ata_port *ap)
++int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
++				int (*check_ready)(struct ata_link *link))
+ {
+-	struct ata_device *device = ap->link.device;
+-	struct ata_ioports *ioaddr = &ap->ioaddr;
+-	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+-	u8 err;
+-	unsigned int dev0, dev1 = 0, devmask = 0;
+-	int rc;
+-
+-	DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
+-
+-	/* determine if device 0/1 are present */
+-	if (ap->flags & ATA_FLAG_SATA_RESET)
+-		dev0 = 1;
+-	else {
+-		dev0 = ata_devchk(ap, 0);
+-		if (slave_possible)
+-			dev1 = ata_devchk(ap, 1);
+-	}
+-
+-	if (dev0)
+-		devmask |= (1 << 0);
+-	if (dev1)
+-		devmask |= (1 << 1);
++	msleep(ATA_WAIT_AFTER_RESET_MSECS);
+ 
+-	/* select device 0 again */
+-	ap->ops->dev_select(ap, 0);
+-
+-	/* issue bus reset */
+-	if (ap->flags & ATA_FLAG_SRST) {
+-		rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
+-		if (rc && rc != -ENODEV)
+-			goto err_out;
+-	}
+-
+-	/*
+-	 * determine by signature whether we have ATA or ATAPI devices
+-	 */
+-	device[0].class = ata_dev_try_classify(&device[0], dev0, &err);
+-	if ((slave_possible) && (err != 0x81))
+-		device[1].class = ata_dev_try_classify(&device[1], dev1, &err);
+-
+-	/* is double-select really necessary? */
+-	if (device[1].class != ATA_DEV_NONE)
+-		ap->ops->dev_select(ap, 1);
+-	if (device[0].class != ATA_DEV_NONE)
+-		ap->ops->dev_select(ap, 0);
+-
+-	/* if no devices were detected, disable this port */
+-	if ((device[0].class == ATA_DEV_NONE) &&
+-	    (device[1].class == ATA_DEV_NONE))
+-		goto err_out;
+-
+-	if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
+-		/* set up device control for ATA_FLAG_SATA_RESET */
+-		iowrite8(ap->ctl, ioaddr->ctl_addr);
+-	}
+-
+-	DPRINTK("EXIT\n");
+-	return;
+-
+-err_out:
+-	ata_port_printk(ap, KERN_ERR, "disabling port\n");
+-	ata_port_disable(ap);
+-
+-	DPRINTK("EXIT\n");
++	return ata_wait_ready(link, deadline, check_ready);
+ }
+ 
+ /**
+@@ -3906,7 +3471,7 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params,
+ int sata_link_resume(struct ata_link *link, const unsigned long *params,
+ 		     unsigned long deadline)
+ {
+-	u32 scontrol;
++	u32 scontrol, serror;
+ 	int rc;
+ 
+ 	if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
+@@ -3922,7 +3487,25 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
+ 	 */
+ 	msleep(200);
+ 
+-	return sata_link_debounce(link, params, deadline);
++	if ((rc = sata_link_debounce(link, params, deadline)))
++		return rc;
++
++	/* Clear SError.  PMP and some host PHYs require this to
++	 * operate and clearing should be done before checking PHY
++	 * online status to avoid race condition (hotplugging between
++	 * link resume and status check).
++	 */
++	if (!(rc = sata_scr_read(link, SCR_ERROR, &serror)))
++		rc = sata_scr_write(link, SCR_ERROR, serror);
++	if (rc == 0 || rc == -EINVAL) {
++		unsigned long flags;
++
++		spin_lock_irqsave(link->ap->lock, flags);
++		link->eh_info.serror = 0;
++		spin_unlock_irqrestore(link->ap->lock, flags);
++		rc = 0;
++	}
++	return rc;
+ }
+ 
+ /**
+@@ -3949,17 +3532,6 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
+ 	const unsigned long *timing = sata_ehc_deb_timing(ehc);
+ 	int rc;
+ 
+-	/* handle link resume */
+-	if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
+-	    (link->flags & ATA_LFLAG_HRST_TO_RESUME))
+-		ehc->i.action |= ATA_EH_HARDRESET;
+-
+-	/* Some PMPs don't work with only SRST, force hardreset if PMP
+-	 * is supported.
+-	 */
+-	if (ap->flags & ATA_FLAG_PMP)
+-		ehc->i.action |= ATA_EH_HARDRESET;
+-
+ 	/* if we're about to do hardreset, nothing more to do */
+ 	if (ehc->i.action & ATA_EH_HARDRESET)
+ 		return 0;
+@@ -3973,88 +3545,30 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
+ 					"link for reset (errno=%d)\n", rc);
+ 	}
+ 
+-	/* Wait for !BSY if the controller can wait for the first D2H
+-	 * Reg FIS and we don't know that no device is attached.
+-	 */
+-	if (!(link->flags & ATA_LFLAG_SKIP_D2H_BSY) && !ata_link_offline(link)) {
+-		rc = ata_wait_ready(ap, deadline);
+-		if (rc && rc != -ENODEV) {
+-			ata_link_printk(link, KERN_WARNING, "device not ready "
+-					"(errno=%d), forcing hardreset\n", rc);
+-			ehc->i.action |= ATA_EH_HARDRESET;
+-		}
+-	}
++	/* no point in trying softreset on offline link */
++	if (ata_link_offline(link))
++		ehc->i.action &= ~ATA_EH_SOFTRESET;
+ 
+ 	return 0;
+ }
+ 
+ /**
+- *	ata_std_softreset - reset host port via ATA SRST
+- *	@link: ATA link to reset
+- *	@classes: resulting classes of attached devices
+- *	@deadline: deadline jiffies for the operation
+- *
+- *	Reset host port using ATA SRST.
+- *
+- *	LOCKING:
+- *	Kernel thread context (may sleep)
+- *
+- *	RETURNS:
+- *	0 on success, -errno otherwise.
+- */
+-int ata_std_softreset(struct ata_link *link, unsigned int *classes,
+-		      unsigned long deadline)
+-{
+-	struct ata_port *ap = link->ap;
+-	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+-	unsigned int devmask = 0;
+-	int rc;
+-	u8 err;
+-
+-	DPRINTK("ENTER\n");
+-
+-	if (ata_link_offline(link)) {
+-		classes[0] = ATA_DEV_NONE;
+-		goto out;
+-	}
+-
+-	/* determine if device 0/1 are present */
+-	if (ata_devchk(ap, 0))
+-		devmask |= (1 << 0);
+-	if (slave_possible && ata_devchk(ap, 1))
+-		devmask |= (1 << 1);
+-
+-	/* select device 0 again */
+-	ap->ops->dev_select(ap, 0);
+-
+-	/* issue bus reset */
+-	DPRINTK("about to softreset, devmask=%x\n", devmask);
+-	rc = ata_bus_softreset(ap, devmask, deadline);
+-	/* if link is occupied, -ENODEV too is an error */
+-	if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
+-		ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+-		return rc;
+-	}
+-
+-	/* determine by signature whether we have ATA or ATAPI devices */
+-	classes[0] = ata_dev_try_classify(&link->device[0],
+-					  devmask & (1 << 0), &err);
+-	if (slave_possible && err != 0x81)
+-		classes[1] = ata_dev_try_classify(&link->device[1],
+-						  devmask & (1 << 1), &err);
+-
+- out:
+-	DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+-	return 0;
+-}
+-
+-/**
+  *	sata_link_hardreset - reset link via SATA phy reset
+  *	@link: link to reset
+  *	@timing: timing parameters { interval, duratinon, timeout } in msec
+  *	@deadline: deadline jiffies for the operation
++ *	@online: optional out parameter indicating link onlineness
++ *	@check_ready: optional callback to check link readiness
+  *
+  *	SATA phy-reset @link using DET bits of SControl register.
++ *	After hardreset, link readiness is waited upon using
++ *	ata_wait_ready() if @check_ready is specified.  LLDs are
++ *	allowed to not specify @check_ready and wait itself after this
++ *	function returns.  Device classification is LLD's
++ *	responsibility.
++ *
++ *	*@online is set to one iff reset succeeded and @link is online
++ *	after reset.
+  *
+  *	LOCKING:
+  *	Kernel thread context (may sleep)
+@@ -4063,13 +3577,17 @@ int ata_std_softreset(struct ata_link *link, unsigned int *classes,
+  *	0 on success, -errno otherwise.
+  */
+ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
+-			unsigned long deadline)
++			unsigned long deadline,
++			bool *online, int (*check_ready)(struct ata_link *))
+ {
+ 	u32 scontrol;
+ 	int rc;
+ 
+ 	DPRINTK("ENTER\n");
+ 
++	if (online)
++		*online = false;
++
+ 	if (sata_set_spd_needed(link)) {
+ 		/* SATA spec says nothing about how to reconfigure
+ 		 * spd.  To be on the safe side, turn off phy during
+@@ -4103,77 +3621,69 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
+ 
+ 	/* bring link back */
+ 	rc = sata_link_resume(link, timing, deadline);
++	if (rc)
++		goto out;
++	/* if link is offline nothing more to do */
++	if (ata_link_offline(link))
++		goto out;
++
++	/* Link is online.  From this point, -ENODEV too is an error. */
++	if (online)
++		*online = true;
++
++	if (sata_pmp_supported(link->ap) && ata_is_host_link(link)) {
++		/* If PMP is supported, we have to do follow-up SRST.
++		 * Some PMPs don't send D2H Reg FIS after hardreset if
++		 * the first port is empty.  Wait only for
++		 * ATA_TMOUT_PMP_SRST_WAIT.
++		 */
++		if (check_ready) {
++			unsigned long pmp_deadline;
++
++			pmp_deadline = jiffies + ATA_TMOUT_PMP_SRST_WAIT;
++			if (time_after(pmp_deadline, deadline))
++				pmp_deadline = deadline;
++			ata_wait_ready(link, pmp_deadline, check_ready);
++		}
++		rc = -EAGAIN;
++		goto out;
++	}
++
++	rc = 0;
++	if (check_ready)
++		rc = ata_wait_ready(link, deadline, check_ready);
+  out:
++	if (rc && rc != -EAGAIN)
++		ata_link_printk(link, KERN_ERR,
++				"COMRESET failed (errno=%d)\n", rc);
+ 	DPRINTK("EXIT, rc=%d\n", rc);
+ 	return rc;
+ }
+ 
+ /**
+- *	sata_std_hardreset - reset host port via SATA phy reset
++ *	sata_std_hardreset - COMRESET w/o waiting or classification
+  *	@link: link to reset
+  *	@class: resulting class of attached device
+  *	@deadline: deadline jiffies for the operation
+  *
+- *	SATA phy-reset host port using DET bits of SControl register,
+- *	wait for !BSY and classify the attached device.
++ *	Standard SATA COMRESET w/o waiting or classification.
+  *
+  *	LOCKING:
+  *	Kernel thread context (may sleep)
+  *
+  *	RETURNS:
+- *	0 on success, -errno otherwise.
++ *	0 if link offline, -EAGAIN if link online, -errno on errors.
+  */
+ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ 		       unsigned long deadline)
+ {
+-	struct ata_port *ap = link->ap;
+ 	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
++	bool online;
+ 	int rc;
+ 
+-	DPRINTK("ENTER\n");
+-
+ 	/* do hardreset */
+-	rc = sata_link_hardreset(link, timing, deadline);
+-	if (rc) {
+-		ata_link_printk(link, KERN_ERR,
+-				"COMRESET failed (errno=%d)\n", rc);
+-		return rc;
+-	}
+-
+-	/* TODO: phy layer with polling, timeouts, etc. */
+-	if (ata_link_offline(link)) {
+-		*class = ATA_DEV_NONE;
+-		DPRINTK("EXIT, link offline\n");
+-		return 0;
+-	}
+-
+-	/* wait a while before checking status */
+-	ata_wait_after_reset(ap, deadline);
+-
+-	/* If PMP is supported, we have to do follow-up SRST.  Note
+-	 * that some PMPs don't send D2H Reg FIS after hardreset at
+-	 * all if the first port is empty.  Wait for it just for a
+-	 * second and request follow-up SRST.
+-	 */
+-	if (ap->flags & ATA_FLAG_PMP) {
+-		ata_wait_ready(ap, jiffies + HZ);
+-		return -EAGAIN;
+-	}
+-
+-	rc = ata_wait_ready(ap, deadline);
+-	/* link occupied, -ENODEV too is an error */
+-	if (rc) {
+-		ata_link_printk(link, KERN_ERR,
+-				"COMRESET failed (errno=%d)\n", rc);
+-		return rc;
+-	}
+-
+-	ap->ops->dev_select(ap, 0);	/* probably unnecessary */
+-
+-	*class = ata_dev_try_classify(link->device, 1, NULL);
+-
+-	DPRINTK("EXIT, class=%u\n", *class);
+-	return 0;
++	rc = sata_link_hardreset(link, timing, deadline, &online, NULL);
++	return online ? -EAGAIN : rc;
+ }
+ 
+ /**
+@@ -4190,35 +3700,11 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+  */
+ void ata_std_postreset(struct ata_link *link, unsigned int *classes)
+ {
+-	struct ata_port *ap = link->ap;
+-	u32 serror;
+-
+ 	DPRINTK("ENTER\n");
+ 
+ 	/* print link status */
+ 	sata_print_link_status(link);
+ 
+-	/* clear SError */
+-	if (sata_scr_read(link, SCR_ERROR, &serror) == 0)
+-		sata_scr_write(link, SCR_ERROR, serror);
+-	link->eh_info.serror = 0;
+-
+-	/* is double-select really necessary? */
+-	if (classes[0] != ATA_DEV_NONE)
+-		ap->ops->dev_select(ap, 1);
+-	if (classes[1] != ATA_DEV_NONE)
+-		ap->ops->dev_select(ap, 0);
+-
+-	/* bail out if no device is present */
+-	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+-		DPRINTK("EXIT, no device\n");
+-		return;
+-	}
+-
+-	/* set up device control */
+-	if (ap->ioaddr.ctl_addr)
+-		iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+-
+ 	DPRINTK("EXIT\n");
+ }
+ 
+@@ -4528,6 +4014,53 @@ static int ata_is_40wire(struct ata_device *dev)
+ }
+ 
+ /**
++ *	cable_is_40wire		-	40/80/SATA decider
++ *	@ap: port to consider
++ *
++ *	This function encapsulates the policy for speed management
++ *	in one place. At the moment we don't cache the result but
++ *	there is a good case for setting ap->cbl to the result when
++ *	we are called with unknown cables (and figuring out if it
++ *	impacts hotplug at all).
++ *
++ *	Return 1 if the cable appears to be 40 wire.
++ */
++
++static int cable_is_40wire(struct ata_port *ap)
++{
++	struct ata_link *link;
++	struct ata_device *dev;
++
++	/* If the controller thinks we are 40 wire, we are */
++	if (ap->cbl == ATA_CBL_PATA40)
++		return 1;
++	/* If the controller thinks we are 80 wire, we are */
++	if (ap->cbl == ATA_CBL_PATA80 || ap->cbl == ATA_CBL_SATA)
++		return 0;
++	/* If the system is known to be 40 wire short cable (eg laptop),
++	   then we allow 80 wire modes even if the drive isn't sure */
++	if (ap->cbl == ATA_CBL_PATA40_SHORT)
++		return 0;
++	/* If the controller doesn't know we scan
++
++	   - Note: We look for all 40 wire detects at this point.
++	     Any 80 wire detect is taken to be 80 wire cable
++	     because
++	     - In many setups only the one drive (slave if present)
++               will give a valid detect
++             - If you have a non detect capable drive you don't
++               want it to colour the choice
++        */
++	ata_port_for_each_link(link, ap) {
++		ata_link_for_each_dev(dev, link) {
++			if (!ata_is_40wire(dev))
++				return 0;
++		}
++	}
++	return 1;
++}
++
++/**
+  *	ata_dev_xfermask - Compute supported xfermask of the given device
+  *	@dev: Device to compute xfermask for
+  *
+@@ -4595,10 +4128,7 @@ static void ata_dev_xfermask(struct ata_device *dev)
+ 	 */
+ 	if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
+ 		/* UDMA/44 or higher would be available */
+-		if ((ap->cbl == ATA_CBL_PATA40) ||
+-		    (ata_is_40wire(dev) &&
+-		    (ap->cbl == ATA_CBL_PATA_UNK ||
+-		     ap->cbl == ATA_CBL_PATA80))) {
++		if (cable_is_40wire(ap)) {
+ 			ata_dev_printk(dev, KERN_WARNING,
+ 				 "limited to UDMA/33 due to 40-wire cable\n");
+ 			xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
+@@ -4759,112 +4289,6 @@ void ata_sg_clean(struct ata_queued_cmd *qc)
+ }
+ 
+ /**
+- *	ata_fill_sg - Fill PCI IDE PRD table
+- *	@qc: Metadata associated with taskfile to be transferred
+- *
+- *	Fill PCI IDE PRD (scatter-gather) table with segments
+- *	associated with the current disk command.
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- *
+- */
+-static void ata_fill_sg(struct ata_queued_cmd *qc)
+-{
+-	struct ata_port *ap = qc->ap;
+-	struct scatterlist *sg;
+-	unsigned int si, pi;
+-
+-	pi = 0;
+-	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+-		u32 addr, offset;
+-		u32 sg_len, len;
+-
+-		/* determine if physical DMA addr spans 64K boundary.
+-		 * Note h/w doesn't support 64-bit, so we unconditionally
+-		 * truncate dma_addr_t to u32.
+-		 */
+-		addr = (u32) sg_dma_address(sg);
+-		sg_len = sg_dma_len(sg);
+-
+-		while (sg_len) {
+-			offset = addr & 0xffff;
+-			len = sg_len;
+-			if ((offset + sg_len) > 0x10000)
+-				len = 0x10000 - offset;
+-
+-			ap->prd[pi].addr = cpu_to_le32(addr);
+-			ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
+-			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+-
+-			pi++;
+-			sg_len -= len;
+-			addr += len;
+-		}
+-	}
+-
+-	ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+-}
+-
+-/**
+- *	ata_fill_sg_dumb - Fill PCI IDE PRD table
+- *	@qc: Metadata associated with taskfile to be transferred
+- *
+- *	Fill PCI IDE PRD (scatter-gather) table with segments
+- *	associated with the current disk command. Perform the fill
+- *	so that we avoid writing any length 64K records for
+- *	controllers that don't follow the spec.
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- *
+- */
+-static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
+-{
+-	struct ata_port *ap = qc->ap;
+-	struct scatterlist *sg;
+-	unsigned int si, pi;
+-
+-	pi = 0;
+-	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+-		u32 addr, offset;
+-		u32 sg_len, len, blen;
+-
+-		/* determine if physical DMA addr spans 64K boundary.
+-		 * Note h/w doesn't support 64-bit, so we unconditionally
+-		 * truncate dma_addr_t to u32.
+-		 */
+-		addr = (u32) sg_dma_address(sg);
+-		sg_len = sg_dma_len(sg);
+-
+-		while (sg_len) {
+-			offset = addr & 0xffff;
+-			len = sg_len;
+-			if ((offset + sg_len) > 0x10000)
+-				len = 0x10000 - offset;
+-
+-			blen = len & 0xffff;
+-			ap->prd[pi].addr = cpu_to_le32(addr);
+-			if (blen == 0) {
+-			   /* Some PATA chipsets like the CS5530 can't
+-			      cope with 0x0000 meaning 64K as the spec says */
+-				ap->prd[pi].flags_len = cpu_to_le32(0x8000);
+-				blen = 0x8000;
+-				ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
+-			}
+-			ap->prd[pi].flags_len = cpu_to_le32(blen);
+-			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+-
+-			pi++;
+-			sg_len -= len;
+-			addr += len;
+-		}
+-	}
+-
+-	ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+-}
+-
+-/**
+  *	ata_check_atapi_dma - Check whether ATAPI DMA can be supported
+  *	@qc: Metadata associated with taskfile to check
+  *
+@@ -4924,40 +4348,6 @@ int ata_std_qc_defer(struct ata_queued_cmd *qc)
+ 	return ATA_DEFER_LINK;
+ }
+ 
+-/**
+- *	ata_qc_prep - Prepare taskfile for submission
+- *	@qc: Metadata associated with taskfile to be prepared
+- *
+- *	Prepare ATA taskfile for submission.
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- */
+-void ata_qc_prep(struct ata_queued_cmd *qc)
+-{
+-	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+-		return;
+-
+-	ata_fill_sg(qc);
+-}
+-
+-/**
+- *	ata_dumb_qc_prep - Prepare taskfile for submission
+- *	@qc: Metadata associated with taskfile to be prepared
+- *
+- *	Prepare ATA taskfile for submission.
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- */
+-void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
+-{
+-	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+-		return;
+-
+-	ata_fill_sg_dumb(qc);
+-}
+-
+ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
+ 
+ /**
+@@ -5036,698 +4426,6 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
+ }
+ 
+ /**
+- *	ata_data_xfer - Transfer data by PIO
+- *	@dev: device to target
+- *	@buf: data buffer
+- *	@buflen: buffer length
+- *	@rw: read/write
+- *
+- *	Transfer data from/to the device data register by PIO.
+- *
+- *	LOCKING:
+- *	Inherited from caller.
+- *
+- *	RETURNS:
+- *	Bytes consumed.
+- */
+-unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf,
+-			   unsigned int buflen, int rw)
+-{
+-	struct ata_port *ap = dev->link->ap;
+-	void __iomem *data_addr = ap->ioaddr.data_addr;
+-	unsigned int words = buflen >> 1;
+-
+-	/* Transfer multiple of 2 bytes */
+-	if (rw == READ)
+-		ioread16_rep(data_addr, buf, words);
+-	else
+-		iowrite16_rep(data_addr, buf, words);
+-
+-	/* Transfer trailing 1 byte, if any. */
+-	if (unlikely(buflen & 0x01)) {
+-		__le16 align_buf[1] = { 0 };
+-		unsigned char *trailing_buf = buf + buflen - 1;
+-
+-		if (rw == READ) {
+-			align_buf[0] = cpu_to_le16(ioread16(data_addr));
+-			memcpy(trailing_buf, align_buf, 1);
+-		} else {
+-			memcpy(align_buf, trailing_buf, 1);
+-			iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+-		}
+-		words++;
+-	}
+-
+-	return words << 1;
+-}
+-
+-/**
+- *	ata_data_xfer_noirq - Transfer data by PIO
+- *	@dev: device to target
+- *	@buf: data buffer
+- *	@buflen: buffer length
+- *	@rw: read/write
+- *
+- *	Transfer data from/to the device data register by PIO. Do the
+- *	transfer with interrupts disabled.
+- *
+- *	LOCKING:
+- *	Inherited from caller.
+- *
+- *	RETURNS:
+- *	Bytes consumed.
+- */
+-unsigned int ata_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
+-				 unsigned int buflen, int rw)
+-{
+-	unsigned long flags;
+-	unsigned int consumed;
+-
+-	local_irq_save(flags);
+-	consumed = ata_data_xfer(dev, buf, buflen, rw);
+-	local_irq_restore(flags);
+-
+-	return consumed;
+-}
+-
+-
+-/**
+- *	ata_pio_sector - Transfer a sector of data.
+- *	@qc: Command on going
+- *
+- *	Transfer qc->sect_size bytes of data from/to the ATA device.
+- *
+- *	LOCKING:
+- *	Inherited from caller.
+- */
+-
+-static void ata_pio_sector(struct ata_queued_cmd *qc)
+-{
+-	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+-	struct ata_port *ap = qc->ap;
+-	struct page *page;
+-	unsigned int offset;
+-	unsigned char *buf;
+-
+-	if (qc->curbytes == qc->nbytes - qc->sect_size)
+-		ap->hsm_task_state = HSM_ST_LAST;
+-
+-	page = sg_page(qc->cursg);
+-	offset = qc->cursg->offset + qc->cursg_ofs;
+-
+-	/* get the current page and offset */
+-	page = nth_page(page, (offset >> PAGE_SHIFT));
+-	offset %= PAGE_SIZE;
+-
+-	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+-
+-	if (PageHighMem(page)) {
+-		unsigned long flags;
+-
+-		/* FIXME: use a bounce buffer */
+-		local_irq_save(flags);
+-		buf = kmap_atomic(page, KM_IRQ0);
+-
+-		/* do the actual data transfer */
+-		ap->ops->data_xfer(qc->dev, buf + offset, qc->sect_size, do_write);
+-
+-		kunmap_atomic(buf, KM_IRQ0);
+-		local_irq_restore(flags);
+-	} else {
+-		buf = page_address(page);
+-		ap->ops->data_xfer(qc->dev, buf + offset, qc->sect_size, do_write);
+-	}
+-
+-	qc->curbytes += qc->sect_size;
+-	qc->cursg_ofs += qc->sect_size;
+-
+-	if (qc->cursg_ofs == qc->cursg->length) {
+-		qc->cursg = sg_next(qc->cursg);
+-		qc->cursg_ofs = 0;
+-	}
+-}
+-
+-/**
+- *	ata_pio_sectors - Transfer one or many sectors.
+- *	@qc: Command on going
+- *
+- *	Transfer one or many sectors of data from/to the
+- *	ATA device for the DRQ request.
+- *
+- *	LOCKING:
+- *	Inherited from caller.
+- */
+-
+-static void ata_pio_sectors(struct ata_queued_cmd *qc)
+-{
+-	if (is_multi_taskfile(&qc->tf)) {
+-		/* READ/WRITE MULTIPLE */
+-		unsigned int nsect;
+-
+-		WARN_ON(qc->dev->multi_count == 0);
+-
+-		nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
+-			    qc->dev->multi_count);
+-		while (nsect--)
+-			ata_pio_sector(qc);
+-	} else
+-		ata_pio_sector(qc);
+-
+-	ata_altstatus(qc->ap); /* flush */
+-}
+-
+-/**
+- *	atapi_send_cdb - Write CDB bytes to hardware
+- *	@ap: Port to which ATAPI device is attached.
+- *	@qc: Taskfile currently active
+- *
+- *	When device has indicated its readiness to accept
+- *	a CDB, this function is called.  Send the CDB.
+- *
+- *	LOCKING:
+- *	caller.
+- */
+-
+-static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
+-{
+-	/* send SCSI cdb */
+-	DPRINTK("send cdb\n");
+-	WARN_ON(qc->dev->cdb_len < 12);
+-
+-	ap->ops->data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
+-	ata_altstatus(ap); /* flush */
+-
+-	switch (qc->tf.protocol) {
+-	case ATAPI_PROT_PIO:
+-		ap->hsm_task_state = HSM_ST;
+-		break;
+-	case ATAPI_PROT_NODATA:
+-		ap->hsm_task_state = HSM_ST_LAST;
+-		break;
+-	case ATAPI_PROT_DMA:
+-		ap->hsm_task_state = HSM_ST_LAST;
+-		/* initiate bmdma */
+-		ap->ops->bmdma_start(qc);
+-		break;
+-	}
+-}
+-
+-/**
+- *	__atapi_pio_bytes - Transfer data from/to the ATAPI device.
+- *	@qc: Command on going
+- *	@bytes: number of bytes
+- *
+- *	Transfer Transfer data from/to the ATAPI device.
+- *
+- *	LOCKING:
+- *	Inherited from caller.
+- *
+- */
+-static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
+-{
+-	int rw = (qc->tf.flags & ATA_TFLAG_WRITE) ? WRITE : READ;
+-	struct ata_port *ap = qc->ap;
+-	struct ata_device *dev = qc->dev;
+-	struct ata_eh_info *ehi = &dev->link->eh_info;
+-	struct scatterlist *sg;
+-	struct page *page;
+-	unsigned char *buf;
+-	unsigned int offset, count, consumed;
+-
+-next_sg:
+-	sg = qc->cursg;
+-	if (unlikely(!sg)) {
+-		ata_ehi_push_desc(ehi, "unexpected or too much trailing data "
+-				  "buf=%u cur=%u bytes=%u",
+-				  qc->nbytes, qc->curbytes, bytes);
+-		return -1;
+-	}
+-
+-	page = sg_page(sg);
+-	offset = sg->offset + qc->cursg_ofs;
+-
+-	/* get the current page and offset */
+-	page = nth_page(page, (offset >> PAGE_SHIFT));
+-	offset %= PAGE_SIZE;
+-
+-	/* don't overrun current sg */
+-	count = min(sg->length - qc->cursg_ofs, bytes);
+-
+-	/* don't cross page boundaries */
+-	count = min(count, (unsigned int)PAGE_SIZE - offset);
+-
+-	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+-
+-	if (PageHighMem(page)) {
+-		unsigned long flags;
+-
+-		/* FIXME: use bounce buffer */
+-		local_irq_save(flags);
+-		buf = kmap_atomic(page, KM_IRQ0);
+-
+-		/* do the actual data transfer */
+-		consumed = ap->ops->data_xfer(dev,  buf + offset, count, rw);
+-
+-		kunmap_atomic(buf, KM_IRQ0);
+-		local_irq_restore(flags);
+-	} else {
+-		buf = page_address(page);
+-		consumed = ap->ops->data_xfer(dev,  buf + offset, count, rw);
+-	}
+-
+-	bytes -= min(bytes, consumed);
+-	qc->curbytes += count;
+-	qc->cursg_ofs += count;
+-
+-	if (qc->cursg_ofs == sg->length) {
+-		qc->cursg = sg_next(qc->cursg);
+-		qc->cursg_ofs = 0;
+-	}
+-
+-	/* consumed can be larger than count only for the last transfer */
+-	WARN_ON(qc->cursg && count != consumed);
+-
+-	if (bytes)
+-		goto next_sg;
+-	return 0;
+-}
+-
+-/**
+- *	atapi_pio_bytes - Transfer data from/to the ATAPI device.
+- *	@qc: Command on going
+- *
+- *	Transfer Transfer data from/to the ATAPI device.
+- *
+- *	LOCKING:
+- *	Inherited from caller.
+- */
+-
+-static void atapi_pio_bytes(struct ata_queued_cmd *qc)
+-{
+-	struct ata_port *ap = qc->ap;
+-	struct ata_device *dev = qc->dev;
+-	struct ata_eh_info *ehi = &dev->link->eh_info;
+-	unsigned int ireason, bc_lo, bc_hi, bytes;
+-	int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
+-
+-	/* Abuse qc->result_tf for temp storage of intermediate TF
+-	 * here to save some kernel stack usage.
+-	 * For normal completion, qc->result_tf is not relevant. For
+-	 * error, qc->result_tf is later overwritten by ata_qc_complete().
+-	 * So, the correctness of qc->result_tf is not affected.
+-	 */
+-	ap->ops->tf_read(ap, &qc->result_tf);
+-	ireason = qc->result_tf.nsect;
+-	bc_lo = qc->result_tf.lbam;
+-	bc_hi = qc->result_tf.lbah;
+-	bytes = (bc_hi << 8) | bc_lo;
+-
+-	/* shall be cleared to zero, indicating xfer of data */
+-	if (unlikely(ireason & (1 << 0)))
+-		goto atapi_check;
+-
+-	/* make sure transfer direction matches expected */
+-	i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
+-	if (unlikely(do_write != i_write))
+-		goto atapi_check;
+-
+-	if (unlikely(!bytes))
+-		goto atapi_check;
+-
+-	VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
+-
+-	if (unlikely(__atapi_pio_bytes(qc, bytes)))
+-		goto err_out;
+-	ata_altstatus(ap); /* flush */
+-
+-	return;
+-
+- atapi_check:
+-	ata_ehi_push_desc(ehi, "ATAPI check failed (ireason=0x%x bytes=%u)",
+-			  ireason, bytes);
+- err_out:
+-	qc->err_mask |= AC_ERR_HSM;
+-	ap->hsm_task_state = HSM_ST_ERR;
+-}
+-
+-/**
+- *	ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue.
+- *	@ap: the target ata_port
+- *	@qc: qc on going
+- *
+- *	RETURNS:
+- *	1 if ok in workqueue, 0 otherwise.
+- */
+-
+-static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
+-{
+-	if (qc->tf.flags & ATA_TFLAG_POLLING)
+-		return 1;
+-
+-	if (ap->hsm_task_state == HSM_ST_FIRST) {
+-		if (qc->tf.protocol == ATA_PROT_PIO &&
+-		    (qc->tf.flags & ATA_TFLAG_WRITE))
+-		    return 1;
+-
+-		if (ata_is_atapi(qc->tf.protocol) &&
+-		    !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+-			return 1;
+-	}
+-
+-	return 0;
+-}
+-
+-/**
+- *	ata_hsm_qc_complete - finish a qc running on standard HSM
+- *	@qc: Command to complete
+- *	@in_wq: 1 if called from workqueue, 0 otherwise
+- *
+- *	Finish @qc which is running on standard HSM.
+- *
+- *	LOCKING:
+- *	If @in_wq is zero, spin_lock_irqsave(host lock).
+- *	Otherwise, none on entry and grabs host lock.
+- */
+-static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+-{
+-	struct ata_port *ap = qc->ap;
+-	unsigned long flags;
+-
+-	if (ap->ops->error_handler) {
+-		if (in_wq) {
+-			spin_lock_irqsave(ap->lock, flags);
+-
+-			/* EH might have kicked in while host lock is
+-			 * released.
+-			 */
+-			qc = ata_qc_from_tag(ap, qc->tag);
+-			if (qc) {
+-				if (likely(!(qc->err_mask & AC_ERR_HSM))) {
+-					ap->ops->irq_on(ap);
+-					ata_qc_complete(qc);
+-				} else
+-					ata_port_freeze(ap);
+-			}
+-
+-			spin_unlock_irqrestore(ap->lock, flags);
+-		} else {
+-			if (likely(!(qc->err_mask & AC_ERR_HSM)))
+-				ata_qc_complete(qc);
+-			else
+-				ata_port_freeze(ap);
+-		}
+-	} else {
+-		if (in_wq) {
+-			spin_lock_irqsave(ap->lock, flags);
+-			ap->ops->irq_on(ap);
+-			ata_qc_complete(qc);
+-			spin_unlock_irqrestore(ap->lock, flags);
+-		} else
+-			ata_qc_complete(qc);
+-	}
+-}
+-
+-/**
+- *	ata_hsm_move - move the HSM to the next state.
+- *	@ap: the target ata_port
+- *	@qc: qc on going
+- *	@status: current device status
+- *	@in_wq: 1 if called from workqueue, 0 otherwise
+- *
+- *	RETURNS:
+- *	1 when poll next status needed, 0 otherwise.
+- */
+-int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+-		 u8 status, int in_wq)
+-{
+-	unsigned long flags = 0;
+-	int poll_next;
+-
+-	WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+-
+-	/* Make sure ata_qc_issue_prot() does not throw things
+-	 * like DMA polling into the workqueue. Notice that
+-	 * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
+-	 */
+-	WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
+-
+-fsm_start:
+-	DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
+-		ap->print_id, qc->tf.protocol, ap->hsm_task_state, status);
+-
+-	switch (ap->hsm_task_state) {
+-	case HSM_ST_FIRST:
+-		/* Send first data block or PACKET CDB */
+-
+-		/* If polling, we will stay in the work queue after
+-		 * sending the data. Otherwise, interrupt handler
+-		 * takes over after sending the data.
+-		 */
+-		poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+-
+-		/* check device status */
+-		if (unlikely((status & ATA_DRQ) == 0)) {
+-			/* handle BSY=0, DRQ=0 as error */
+-			if (likely(status & (ATA_ERR | ATA_DF)))
+-				/* device stops HSM for abort/error */
+-				qc->err_mask |= AC_ERR_DEV;
+-			else
+-				/* HSM violation. Let EH handle this */
+-				qc->err_mask |= AC_ERR_HSM;
+-
+-			ap->hsm_task_state = HSM_ST_ERR;
+-			goto fsm_start;
+-		}
+-
+-		/* Device should not ask for data transfer (DRQ=1)
+-		 * when it finds something wrong.
+-		 * We ignore DRQ here and stop the HSM by
+-		 * changing hsm_task_state to HSM_ST_ERR and
+-		 * let the EH abort the command or reset the device.
+-		 */
+-		if (unlikely(status & (ATA_ERR | ATA_DF))) {
+-			/* Some ATAPI tape drives forget to clear the ERR bit
+-			 * when doing the next command (mostly request sense).
+-			 * We ignore ERR here to workaround and proceed sending
+-			 * the CDB.
+-			 */
+-			if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
+-				ata_port_printk(ap, KERN_WARNING,
+-						"DRQ=1 with device error, "
+-						"dev_stat 0x%X\n", status);
+-				qc->err_mask |= AC_ERR_HSM;
+-				ap->hsm_task_state = HSM_ST_ERR;
+-				goto fsm_start;
+-			}
+-		}
+-
+-		/* Send the CDB (atapi) or the first data block (ata pio out).
+-		 * During the state transition, interrupt handler shouldn't
+-		 * be invoked before the data transfer is complete and
+-		 * hsm_task_state is changed. Hence, the following locking.
+-		 */
+-		if (in_wq)
+-			spin_lock_irqsave(ap->lock, flags);
+-
+-		if (qc->tf.protocol == ATA_PROT_PIO) {
+-			/* PIO data out protocol.
+-			 * send first data block.
+-			 */
+-
+-			/* ata_pio_sectors() might change the state
+-			 * to HSM_ST_LAST. so, the state is changed here
+-			 * before ata_pio_sectors().
+-			 */
+-			ap->hsm_task_state = HSM_ST;
+-			ata_pio_sectors(qc);
+-		} else
+-			/* send CDB */
+-			atapi_send_cdb(ap, qc);
+-
+-		if (in_wq)
+-			spin_unlock_irqrestore(ap->lock, flags);
+-
+-		/* if polling, ata_pio_task() handles the rest.
+-		 * otherwise, interrupt handler takes over from here.
+-		 */
+-		break;
+-
+-	case HSM_ST:
+-		/* complete command or read/write the data register */
+-		if (qc->tf.protocol == ATAPI_PROT_PIO) {
+-			/* ATAPI PIO protocol */
+-			if ((status & ATA_DRQ) == 0) {
+-				/* No more data to transfer or device error.
+-				 * Device error will be tagged in HSM_ST_LAST.
+-				 */
+-				ap->hsm_task_state = HSM_ST_LAST;
+-				goto fsm_start;
+-			}
+-
+-			/* Device should not ask for data transfer (DRQ=1)
+-			 * when it finds something wrong.
+-			 * We ignore DRQ here and stop the HSM by
+-			 * changing hsm_task_state to HSM_ST_ERR and
+-			 * let the EH abort the command or reset the device.
+-			 */
+-			if (unlikely(status & (ATA_ERR | ATA_DF))) {
+-				ata_port_printk(ap, KERN_WARNING, "DRQ=1 with "
+-						"device error, dev_stat 0x%X\n",
+-						status);
+-				qc->err_mask |= AC_ERR_HSM;
+-				ap->hsm_task_state = HSM_ST_ERR;
+-				goto fsm_start;
+-			}
+-
+-			atapi_pio_bytes(qc);
+-
+-			if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
+-				/* bad ireason reported by device */
+-				goto fsm_start;
+-
+-		} else {
+-			/* ATA PIO protocol */
+-			if (unlikely((status & ATA_DRQ) == 0)) {
+-				/* handle BSY=0, DRQ=0 as error */
+-				if (likely(status & (ATA_ERR | ATA_DF)))
+-					/* device stops HSM for abort/error */
+-					qc->err_mask |= AC_ERR_DEV;
+-				else
+-					/* HSM violation. Let EH handle this.
+-					 * Phantom devices also trigger this
+-					 * condition.  Mark hint.
+-					 */
+-					qc->err_mask |= AC_ERR_HSM |
+-							AC_ERR_NODEV_HINT;
+-
+-				ap->hsm_task_state = HSM_ST_ERR;
+-				goto fsm_start;
+-			}
+-
+-			/* For PIO reads, some devices may ask for
+-			 * data transfer (DRQ=1) alone with ERR=1.
+-			 * We respect DRQ here and transfer one
+-			 * block of junk data before changing the
+-			 * hsm_task_state to HSM_ST_ERR.
+-			 *
+-			 * For PIO writes, ERR=1 DRQ=1 doesn't make
+-			 * sense since the data block has been
+-			 * transferred to the device.
+-			 */
+-			if (unlikely(status & (ATA_ERR | ATA_DF))) {
+-				/* data might be corrputed */
+-				qc->err_mask |= AC_ERR_DEV;
+-
+-				if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+-					ata_pio_sectors(qc);
+-					status = ata_wait_idle(ap);
+-				}
+-
+-				if (status & (ATA_BUSY | ATA_DRQ))
+-					qc->err_mask |= AC_ERR_HSM;
+-
+-				/* ata_pio_sectors() might change the
+-				 * state to HSM_ST_LAST. so, the state
+-				 * is changed after ata_pio_sectors().
+-				 */
+-				ap->hsm_task_state = HSM_ST_ERR;
+-				goto fsm_start;
+-			}
+-
+-			ata_pio_sectors(qc);
+-
+-			if (ap->hsm_task_state == HSM_ST_LAST &&
+-			    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+-				/* all data read */
+-				status = ata_wait_idle(ap);
+-				goto fsm_start;
+-			}
+-		}
+-
+-		poll_next = 1;
+-		break;
+-
+-	case HSM_ST_LAST:
+-		if (unlikely(!ata_ok(status))) {
+-			qc->err_mask |= __ac_err_mask(status);
+-			ap->hsm_task_state = HSM_ST_ERR;
+-			goto fsm_start;
+-		}
+-
+-		/* no more data to transfer */
+-		DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
+-			ap->print_id, qc->dev->devno, status);
+-
+-		WARN_ON(qc->err_mask);
+-
+-		ap->hsm_task_state = HSM_ST_IDLE;
+-
+-		/* complete taskfile transaction */
+-		ata_hsm_qc_complete(qc, in_wq);
+-
+-		poll_next = 0;
+-		break;
+-
+-	case HSM_ST_ERR:
+-		/* make sure qc->err_mask is available to
+-		 * know what's wrong and recover
+-		 */
+-		WARN_ON(qc->err_mask == 0);
+-
+-		ap->hsm_task_state = HSM_ST_IDLE;
+-
+-		/* complete taskfile transaction */
+-		ata_hsm_qc_complete(qc, in_wq);
+-
+-		poll_next = 0;
+-		break;
+-	default:
+-		poll_next = 0;
+-		BUG();
+-	}
+-
+-	return poll_next;
+-}
+-
+-static void ata_pio_task(struct work_struct *work)
+-{
+-	struct ata_port *ap =
+-		container_of(work, struct ata_port, port_task.work);
+-	struct ata_queued_cmd *qc = ap->port_task_data;
+-	u8 status;
+-	int poll_next;
+-
+-fsm_start:
+-	WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
+-
+-	/*
+-	 * This is purely heuristic.  This is a fast path.
+-	 * Sometimes when we enter, BSY will be cleared in
+-	 * a chk-status or two.  If not, the drive is probably seeking
+-	 * or something.  Snooze for a couple msecs, then
+-	 * chk-status again.  If still busy, queue delayed work.
+-	 */
+-	status = ata_busy_wait(ap, ATA_BUSY, 5);
+-	if (status & ATA_BUSY) {
+-		msleep(2);
+-		status = ata_busy_wait(ap, ATA_BUSY, 10);
+-		if (status & ATA_BUSY) {
+-			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+-			return;
+-		}
+-	}
+-
+-	/* move the HSM */
+-	poll_next = ata_hsm_move(ap, qc, status, 1);
+-
+-	/* another command or interrupt handler
+-	 * may be running at this point.
+-	 */
+-	if (poll_next)
+-		goto fsm_start;
+-}
+-
+-/**
+  *	ata_qc_new - Request an available ATA command, for queueing
+  *	@ap: Port associated with device @dev
+  *	@dev: Device from whom we request an available command structure
+@@ -5850,7 +4548,7 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
+ 	struct ata_port *ap = qc->ap;
+ 
+ 	qc->result_tf.flags = qc->tf.flags;
+-	ap->ops->tf_read(ap, &qc->result_tf);
++	ap->ops->qc_fill_rtf(qc);
+ }
+ 
+ static void ata_verify_xfer(struct ata_queued_cmd *qc)
+@@ -5960,7 +4658,6 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
+  *	ata_qc_complete_multiple - Complete multiple qcs successfully
+  *	@ap: port in question
+  *	@qc_active: new qc_active mask
+- *	@finish_qc: LLDD callback invoked before completing a qc
+  *
+  *	Complete in-flight commands.  This functions is meant to be
+  *	called from low-level driver's interrupt routine to complete
+@@ -5973,8 +4670,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
+  *	RETURNS:
+  *	Number of completed commands on success, -errno otherwise.
+  */
+-int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+-			     void (*finish_qc)(struct ata_queued_cmd *))
++int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active)
+ {
+ 	int nr_done = 0;
+ 	u32 done_mask;
+@@ -5995,8 +4691,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+ 			continue;
+ 
+ 		if ((qc = ata_qc_from_tag(ap, i))) {
+-			if (finish_qc)
+-				finish_qc(qc);
+ 			ata_qc_complete(qc);
+ 			nr_done++;
+ 		}
+@@ -6055,9 +4749,9 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
+ 		if (ata_sg_setup(qc))
+ 			goto sg_err;
+ 
+-	/* if device is sleeping, schedule softreset and abort the link */
++	/* if device is sleeping, schedule reset and abort the link */
+ 	if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
+-		link->eh_info.action |= ATA_EH_SOFTRESET;
++		link->eh_info.action |= ATA_EH_RESET;
+ 		ata_ehi_push_desc(&link->eh_info, "waking up from sleep");
+ 		ata_link_abort(link);
+ 		return;
+@@ -6077,285 +4771,6 @@ err:
+ }
+ 
+ /**
+- *	ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
+- *	@qc: command to issue to device
+- *
+- *	Using various libata functions and hooks, this function
+- *	starts an ATA command.  ATA commands are grouped into
+- *	classes called "protocols", and issuing each type of protocol
+- *	is slightly different.
+- *
+- *	May be used as the qc_issue() entry in ata_port_operations.
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- *
+- *	RETURNS:
+- *	Zero on success, AC_ERR_* mask on failure
+- */
+-
+-unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+-{
+-	struct ata_port *ap = qc->ap;
+-
+-	/* Use polling pio if the LLD doesn't handle
+-	 * interrupt driven pio and atapi CDB interrupt.
+-	 */
+-	if (ap->flags & ATA_FLAG_PIO_POLLING) {
+-		switch (qc->tf.protocol) {
+-		case ATA_PROT_PIO:
+-		case ATA_PROT_NODATA:
+-		case ATAPI_PROT_PIO:
+-		case ATAPI_PROT_NODATA:
+-			qc->tf.flags |= ATA_TFLAG_POLLING;
+-			break;
+-		case ATAPI_PROT_DMA:
+-			if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
+-				/* see ata_dma_blacklisted() */
+-				BUG();
+-			break;
+-		default:
+-			break;
+-		}
+-	}
+-
+-	/* select the device */
+-	ata_dev_select(ap, qc->dev->devno, 1, 0);
+-
+-	/* start the command */
+-	switch (qc->tf.protocol) {
+-	case ATA_PROT_NODATA:
+-		if (qc->tf.flags & ATA_TFLAG_POLLING)
+-			ata_qc_set_polling(qc);
+-
+-		ata_tf_to_host(ap, &qc->tf);
+-		ap->hsm_task_state = HSM_ST_LAST;
+-
+-		if (qc->tf.flags & ATA_TFLAG_POLLING)
+-			ata_pio_queue_task(ap, qc, 0);
+-
+-		break;
+-
+-	case ATA_PROT_DMA:
+-		WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+-
+-		ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
+-		ap->ops->bmdma_setup(qc);	    /* set up bmdma */
+-		ap->ops->bmdma_start(qc);	    /* initiate bmdma */
+-		ap->hsm_task_state = HSM_ST_LAST;
+-		break;
+-
+-	case ATA_PROT_PIO:
+-		if (qc->tf.flags & ATA_TFLAG_POLLING)
+-			ata_qc_set_polling(qc);
+-
+-		ata_tf_to_host(ap, &qc->tf);
+-
+-		if (qc->tf.flags & ATA_TFLAG_WRITE) {
+-			/* PIO data out protocol */
+-			ap->hsm_task_state = HSM_ST_FIRST;
+-			ata_pio_queue_task(ap, qc, 0);
+-
+-			/* always send first data block using
+-			 * the ata_pio_task() codepath.
+-			 */
+-		} else {
+-			/* PIO data in protocol */
+-			ap->hsm_task_state = HSM_ST;
+-
+-			if (qc->tf.flags & ATA_TFLAG_POLLING)
+-				ata_pio_queue_task(ap, qc, 0);
+-
+-			/* if polling, ata_pio_task() handles the rest.
+-			 * otherwise, interrupt handler takes over from here.
+-			 */
+-		}
+-
+-		break;
+-
+-	case ATAPI_PROT_PIO:
+-	case ATAPI_PROT_NODATA:
+-		if (qc->tf.flags & ATA_TFLAG_POLLING)
+-			ata_qc_set_polling(qc);
+-
+-		ata_tf_to_host(ap, &qc->tf);
+-
+-		ap->hsm_task_state = HSM_ST_FIRST;
+-
+-		/* send cdb by polling if no cdb interrupt */
+-		if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
+-		    (qc->tf.flags & ATA_TFLAG_POLLING))
+-			ata_pio_queue_task(ap, qc, 0);
+-		break;
+-
+-	case ATAPI_PROT_DMA:
+-		WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+-
+-		ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
+-		ap->ops->bmdma_setup(qc);	    /* set up bmdma */
+-		ap->hsm_task_state = HSM_ST_FIRST;
+-
+-		/* send cdb by polling if no cdb interrupt */
+-		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+-			ata_pio_queue_task(ap, qc, 0);
+-		break;
+-
+-	default:
+-		WARN_ON(1);
+-		return AC_ERR_SYSTEM;
+-	}
+-
+-	return 0;
+-}
+-
+-/**
+- *	ata_host_intr - Handle host interrupt for given (port, task)
+- *	@ap: Port on which interrupt arrived (possibly...)
+- *	@qc: Taskfile currently active in engine
+- *
+- *	Handle host interrupt for given queued command.  Currently,
+- *	only DMA interrupts are handled.  All other commands are
+- *	handled via polling with interrupts disabled (nIEN bit).
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- *
+- *	RETURNS:
+- *	One if interrupt was handled, zero if not (shared irq).
+- */
+-
+-inline unsigned int ata_host_intr(struct ata_port *ap,
+-				  struct ata_queued_cmd *qc)
+-{
+-	struct ata_eh_info *ehi = &ap->link.eh_info;
+-	u8 status, host_stat = 0;
+-
+-	VPRINTK("ata%u: protocol %d task_state %d\n",
+-		ap->print_id, qc->tf.protocol, ap->hsm_task_state);
+-
+-	/* Check whether we are expecting interrupt in this state */
+-	switch (ap->hsm_task_state) {
+-	case HSM_ST_FIRST:
+-		/* Some pre-ATAPI-4 devices assert INTRQ
+-		 * at this state when ready to receive CDB.
+-		 */
+-
+-		/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+-		 * The flag was turned on only for atapi devices.  No
+-		 * need to check ata_is_atapi(qc->tf.protocol) again.
+-		 */
+-		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+-			goto idle_irq;
+-		break;
+-	case HSM_ST_LAST:
+-		if (qc->tf.protocol == ATA_PROT_DMA ||
+-		    qc->tf.protocol == ATAPI_PROT_DMA) {
+-			/* check status of DMA engine */
+-			host_stat = ap->ops->bmdma_status(ap);
+-			VPRINTK("ata%u: host_stat 0x%X\n",
+-				ap->print_id, host_stat);
+-
+-			/* if it's not our irq... */
+-			if (!(host_stat & ATA_DMA_INTR))
+-				goto idle_irq;
+-
+-			/* before we do anything else, clear DMA-Start bit */
+-			ap->ops->bmdma_stop(qc);
+-
+-			if (unlikely(host_stat & ATA_DMA_ERR)) {
+-				/* error when transfering data to/from memory */
+-				qc->err_mask |= AC_ERR_HOST_BUS;
+-				ap->hsm_task_state = HSM_ST_ERR;
+-			}
+-		}
+-		break;
+-	case HSM_ST:
+-		break;
+-	default:
+-		goto idle_irq;
+-	}
+-
+-	/* check altstatus */
+-	status = ata_altstatus(ap);
+-	if (status & ATA_BUSY)
+-		goto idle_irq;
+-
+-	/* check main status, clearing INTRQ */
+-	status = ata_chk_status(ap);
+-	if (unlikely(status & ATA_BUSY))
+-		goto idle_irq;
+-
+-	/* ack bmdma irq events */
+-	ap->ops->irq_clear(ap);
+-
+-	ata_hsm_move(ap, qc, status, 0);
+-
+-	if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
+-				       qc->tf.protocol == ATAPI_PROT_DMA))
+-		ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+-
+-	return 1;	/* irq handled */
+-
+-idle_irq:
+-	ap->stats.idle_irq++;
+-
+-#ifdef ATA_IRQ_TRAP
+-	if ((ap->stats.idle_irq % 1000) == 0) {
+-		ata_chk_status(ap);
+-		ap->ops->irq_clear(ap);
+-		ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+-		return 1;
+-	}
+-#endif
+-	return 0;	/* irq not handled */
+-}
+-
+-/**
+- *	ata_interrupt - Default ATA host interrupt handler
+- *	@irq: irq line (unused)
+- *	@dev_instance: pointer to our ata_host information structure
+- *
+- *	Default interrupt handler for PCI IDE devices.  Calls
+- *	ata_host_intr() for each port that is not disabled.
+- *
+- *	LOCKING:
+- *	Obtains host lock during operation.
+- *
+- *	RETURNS:
+- *	IRQ_NONE or IRQ_HANDLED.
+- */
+-
+-irqreturn_t ata_interrupt(int irq, void *dev_instance)
+-{
+-	struct ata_host *host = dev_instance;
+-	unsigned int i;
+-	unsigned int handled = 0;
+-	unsigned long flags;
+-
+-	/* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
+-	spin_lock_irqsave(&host->lock, flags);
+-
+-	for (i = 0; i < host->n_ports; i++) {
+-		struct ata_port *ap;
+-
+-		ap = host->ports[i];
+-		if (ap &&
+-		    !(ap->flags & ATA_FLAG_DISABLED)) {
+-			struct ata_queued_cmd *qc;
+-
+-			qc = ata_qc_from_tag(ap, ap->link.active_tag);
+-			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
+-			    (qc->flags & ATA_QCFLAG_ACTIVE))
+-				handled |= ata_host_intr(ap, qc);
+-		}
+-	}
+-
+-	spin_unlock_irqrestore(&host->lock, flags);
+-
+-	return IRQ_RETVAL(handled);
+-}
+-
+-/**
+  *	sata_scr_valid - test whether SCRs are accessible
+  *	@link: ATA link to test SCR accessibility for
+  *
+@@ -6513,32 +4928,6 @@ int ata_link_offline(struct ata_link *link)
+ 	return 0;
+ }
+ 
+-int ata_flush_cache(struct ata_device *dev)
+-{
+-	unsigned int err_mask;
+-	u8 cmd;
+-
+-	if (!ata_try_flush_cache(dev))
+-		return 0;
+-
+-	if (dev->flags & ATA_DFLAG_FLUSH_EXT)
+-		cmd = ATA_CMD_FLUSH_EXT;
+-	else
+-		cmd = ATA_CMD_FLUSH;
+-
+-	/* This is wrong. On a failed flush we get back the LBA of the lost
+-	   sector and we should (assuming it wasn't aborted as unknown) issue
+-	   a further flush command to continue the writeback until it
+-	   does not error */
+-	err_mask = ata_do_simple_cmd(dev, cmd);
+-	if (err_mask) {
+-		ata_dev_printk(dev, KERN_ERR, "failed to flush cache\n");
+-		return -EIO;
+-	}
+-
+-	return 0;
+-}
+-
+ #ifdef CONFIG_PM
+ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
+ 			       unsigned int action, unsigned int ehi_flags,
+@@ -6634,7 +5023,7 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
+  */
+ void ata_host_resume(struct ata_host *host)
+ {
+-	ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
++	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;
+ 
+@@ -6809,7 +5198,9 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
+ 	ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
+ #endif
+ 
++#ifdef CONFIG_ATA_SFF
+ 	INIT_DELAYED_WORK(&ap->port_task, ata_pio_task);
++#endif
+ 	INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
+ 	INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
+ 	INIT_LIST_HEAD(&ap->eh_done_q);
+@@ -6959,8 +5350,6 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
+ 
+ 		if (!host->ops && (pi->port_ops != &ata_dummy_port_ops))
+ 			host->ops = pi->port_ops;
+-		if (!host->private_data && pi->private_data)
+-			host->private_data = pi->private_data;
+ 	}
+ 
+ 	return host;
+@@ -6985,6 +5374,56 @@ static void ata_host_stop(struct device *gendev, void *res)
+ }
+ 
+ /**
++ *	ata_finalize_port_ops - finalize ata_port_operations
++ *	@ops: ata_port_operations to finalize
++ *
++ *	An ata_port_operations can inherit from another ops and that
++ *	ops can again inherit from another.  This can go on as many
++ *	times as necessary as long as there is no loop in the
++ *	inheritance chain.
++ *
++ *	Ops tables are finalized when the host is started.  NULL or
++ *	unspecified entries are inherited from the closet ancestor
++ *	which has the method and the entry is populated with it.
++ *	After finalization, the ops table directly points to all the
++ *	methods and ->inherits is no longer necessary and cleared.
++ *
++ *	Using ATA_OP_NULL, inheriting ops can force a method to NULL.
++ *
++ *	LOCKING:
++ *	None.
++ */
++static void ata_finalize_port_ops(struct ata_port_operations *ops)
++{
++	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
++	const struct ata_port_operations *cur;
++	void **begin = (void **)ops;
++	void **end = (void **)&ops->inherits;
++	void **pp;
++
++	if (!ops || !ops->inherits)
++		return;
++
++	spin_lock(&lock);
++
++	for (cur = ops->inherits; cur; cur = cur->inherits) {
++		void **inherit = (void **)cur;
++
++		for (pp = begin; pp < end; pp++, inherit++)
++			if (!*pp)
++				*pp = *inherit;
++	}
++
++	for (pp = begin; pp < end; pp++)
++		if (IS_ERR(*pp))
++			*pp = NULL;
++
++	ops->inherits = NULL;
++
++	spin_unlock(&lock);
++}
++
++/**
+  *	ata_host_start - start and freeze ports of an ATA host
+  *	@host: ATA host to start ports for
+  *
+@@ -7009,9 +5448,13 @@ int ata_host_start(struct ata_host *host)
+ 	if (host->flags & ATA_HOST_STARTED)
+ 		return 0;
+ 
++	ata_finalize_port_ops(host->ops);
++
+ 	for (i = 0; i < host->n_ports; i++) {
+ 		struct ata_port *ap = host->ports[i];
+ 
++		ata_finalize_port_ops(ap->ops);
++
+ 		if (!host->ops && !ata_port_is_dummy(ap))
+ 			host->ops = ap->ops;
+ 
+@@ -7073,7 +5516,7 @@ int ata_host_start(struct ata_host *host)
+  */
+ /* KILLME - the only user left is ipr */
+ void ata_host_init(struct ata_host *host, struct device *dev,
+-		   unsigned long flags, const struct ata_port_operations *ops)
++		   unsigned long flags, struct ata_port_operations *ops)
+ {
+ 	spin_lock_init(&host->lock);
+ 	host->dev = dev;
+@@ -7169,9 +5612,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
+ 			/* kick EH for boot probing */
+ 			spin_lock_irqsave(ap->lock, flags);
+ 
+-			ehi->probe_mask =
+-				(1 << ata_link_max_devices(&ap->link)) - 1;
+-			ehi->action |= ATA_EH_SOFTRESET;
++			ehi->probe_mask |= ATA_ALL_DEVICES;
++			ehi->action |= ATA_EH_RESET;
+ 			ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
+ 
+ 			ap->pflags &= ~ATA_PFLAG_INITIALIZING;
+@@ -7336,33 +5778,6 @@ void ata_host_detach(struct ata_host *host)
+ 	ata_acpi_dissociate(host);
+ }
+ 
+-/**
+- *	ata_std_ports - initialize ioaddr with standard port offsets.
+- *	@ioaddr: IO address structure to be initialized
+- *
+- *	Utility function which initializes data_addr, error_addr,
+- *	feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
+- *	device_addr, status_addr, and command_addr to standard offsets
+- *	relative to cmd_addr.
+- *
+- *	Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
+- */
+-
+-void ata_std_ports(struct ata_ioports *ioaddr)
+-{
+-	ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
+-	ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR;
+-	ioaddr->feature_addr = ioaddr->cmd_addr + ATA_REG_FEATURE;
+-	ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT;
+-	ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL;
+-	ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM;
+-	ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH;
+-	ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE;
+-	ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS;
+-	ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
+-}
+-
+-
+ #ifdef CONFIG_PCI
+ 
+ /**
+@@ -7749,33 +6164,20 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+ /*
+  * Dummy port_ops
+  */
+-static void ata_dummy_noret(struct ata_port *ap)	{ }
+-static int ata_dummy_ret0(struct ata_port *ap)		{ return 0; }
+-static void ata_dummy_qc_noret(struct ata_queued_cmd *qc) { }
+-
+-static u8 ata_dummy_check_status(struct ata_port *ap)
++static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
+ {
+-	return ATA_DRDY;
++	return AC_ERR_SYSTEM;
+ }
+ 
+-static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
++static void ata_dummy_error_handler(struct ata_port *ap)
+ {
+-	return AC_ERR_SYSTEM;
++	/* truly dummy */
+ }
+ 
+-const struct ata_port_operations ata_dummy_port_ops = {
+-	.check_status		= ata_dummy_check_status,
+-	.check_altstatus	= ata_dummy_check_status,
+-	.dev_select		= ata_noop_dev_select,
++struct ata_port_operations ata_dummy_port_ops = {
+ 	.qc_prep		= ata_noop_qc_prep,
+ 	.qc_issue		= ata_dummy_qc_issue,
+-	.freeze			= ata_dummy_noret,
+-	.thaw			= ata_dummy_noret,
+-	.error_handler		= ata_dummy_noret,
+-	.post_internal_cmd	= ata_dummy_qc_noret,
+-	.irq_clear		= ata_dummy_noret,
+-	.port_start		= ata_dummy_ret0,
+-	.port_stop		= ata_dummy_noret,
++	.error_handler		= ata_dummy_error_handler,
+ };
+ 
+ const struct ata_port_info ata_dummy_port_info = {
+@@ -7791,10 +6193,11 @@ const struct ata_port_info ata_dummy_port_info = {
+ EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
+ EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
+ EXPORT_SYMBOL_GPL(sata_deb_timing_long);
++EXPORT_SYMBOL_GPL(ata_base_port_ops);
++EXPORT_SYMBOL_GPL(sata_port_ops);
+ EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
+ EXPORT_SYMBOL_GPL(ata_dummy_port_info);
+ EXPORT_SYMBOL_GPL(ata_std_bios_param);
+-EXPORT_SYMBOL_GPL(ata_std_ports);
+ EXPORT_SYMBOL_GPL(ata_host_init);
+ EXPORT_SYMBOL_GPL(ata_host_alloc);
+ EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
+@@ -7803,15 +6206,8 @@ EXPORT_SYMBOL_GPL(ata_host_register);
+ EXPORT_SYMBOL_GPL(ata_host_activate);
+ EXPORT_SYMBOL_GPL(ata_host_detach);
+ EXPORT_SYMBOL_GPL(ata_sg_init);
+-EXPORT_SYMBOL_GPL(ata_hsm_move);
+ EXPORT_SYMBOL_GPL(ata_qc_complete);
+ EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
+-EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
+-EXPORT_SYMBOL_GPL(ata_tf_load);
+-EXPORT_SYMBOL_GPL(ata_tf_read);
+-EXPORT_SYMBOL_GPL(ata_noop_dev_select);
+-EXPORT_SYMBOL_GPL(ata_std_dev_select);
+-EXPORT_SYMBOL_GPL(sata_print_link_status);
+ EXPORT_SYMBOL_GPL(atapi_cmd_type);
+ EXPORT_SYMBOL_GPL(ata_tf_to_fis);
+ EXPORT_SYMBOL_GPL(ata_tf_from_fis);
+@@ -7822,37 +6218,17 @@ EXPORT_SYMBOL_GPL(ata_xfer_mode2mask);
+ EXPORT_SYMBOL_GPL(ata_xfer_mode2shift);
+ EXPORT_SYMBOL_GPL(ata_mode_string);
+ EXPORT_SYMBOL_GPL(ata_id_xfermask);
+-EXPORT_SYMBOL_GPL(ata_check_status);
+-EXPORT_SYMBOL_GPL(ata_altstatus);
+-EXPORT_SYMBOL_GPL(ata_exec_command);
+ EXPORT_SYMBOL_GPL(ata_port_start);
+-EXPORT_SYMBOL_GPL(ata_sff_port_start);
+-EXPORT_SYMBOL_GPL(ata_interrupt);
+ EXPORT_SYMBOL_GPL(ata_do_set_mode);
+-EXPORT_SYMBOL_GPL(ata_data_xfer);
+-EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
+ EXPORT_SYMBOL_GPL(ata_std_qc_defer);
+-EXPORT_SYMBOL_GPL(ata_qc_prep);
+-EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
+ EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
+-EXPORT_SYMBOL_GPL(ata_bmdma_setup);
+-EXPORT_SYMBOL_GPL(ata_bmdma_start);
+-EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
+-EXPORT_SYMBOL_GPL(ata_bmdma_status);
+-EXPORT_SYMBOL_GPL(ata_bmdma_stop);
+-EXPORT_SYMBOL_GPL(ata_bmdma_freeze);
+-EXPORT_SYMBOL_GPL(ata_bmdma_thaw);
+-EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh);
+-EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
+-EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
+ EXPORT_SYMBOL_GPL(ata_port_probe);
+ EXPORT_SYMBOL_GPL(ata_dev_disable);
+ EXPORT_SYMBOL_GPL(sata_set_spd);
++EXPORT_SYMBOL_GPL(ata_wait_after_reset);
+ EXPORT_SYMBOL_GPL(sata_link_debounce);
+ EXPORT_SYMBOL_GPL(sata_link_resume);
+-EXPORT_SYMBOL_GPL(ata_bus_reset);
+ EXPORT_SYMBOL_GPL(ata_std_prereset);
+-EXPORT_SYMBOL_GPL(ata_std_softreset);
+ EXPORT_SYMBOL_GPL(sata_link_hardreset);
+ EXPORT_SYMBOL_GPL(sata_std_hardreset);
+ EXPORT_SYMBOL_GPL(ata_std_postreset);
+@@ -7861,15 +6237,11 @@ EXPORT_SYMBOL_GPL(ata_dev_pair);
+ EXPORT_SYMBOL_GPL(ata_port_disable);
+ EXPORT_SYMBOL_GPL(ata_ratelimit);
+ EXPORT_SYMBOL_GPL(ata_wait_register);
+-EXPORT_SYMBOL_GPL(ata_busy_sleep);
+-EXPORT_SYMBOL_GPL(ata_wait_after_reset);
+-EXPORT_SYMBOL_GPL(ata_wait_ready);
+ EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
+ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
+ EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
+ EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
+ EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
+-EXPORT_SYMBOL_GPL(ata_host_intr);
+ EXPORT_SYMBOL_GPL(sata_scr_valid);
+ EXPORT_SYMBOL_GPL(sata_scr_read);
+ EXPORT_SYMBOL_GPL(sata_scr_write);
+@@ -7892,11 +6264,6 @@ EXPORT_SYMBOL_GPL(ata_timing_cycle2mode);
+ 
+ #ifdef CONFIG_PCI
+ EXPORT_SYMBOL_GPL(pci_test_config_bits);
+-EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
+-EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
+-EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
+-EXPORT_SYMBOL_GPL(ata_pci_activate_sff_host);
+-EXPORT_SYMBOL_GPL(ata_pci_init_one);
+ EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+ #ifdef CONFIG_PM
+ EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend);
+@@ -7904,16 +6271,8 @@ EXPORT_SYMBOL_GPL(ata_pci_device_do_resume);
+ EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
+ EXPORT_SYMBOL_GPL(ata_pci_device_resume);
+ #endif /* CONFIG_PM */
+-EXPORT_SYMBOL_GPL(ata_pci_default_filter);
+-EXPORT_SYMBOL_GPL(ata_pci_clear_simplex);
+ #endif /* CONFIG_PCI */
+ 
+-EXPORT_SYMBOL_GPL(sata_pmp_qc_defer_cmd_switch);
+-EXPORT_SYMBOL_GPL(sata_pmp_std_prereset);
+-EXPORT_SYMBOL_GPL(sata_pmp_std_hardreset);
+-EXPORT_SYMBOL_GPL(sata_pmp_std_postreset);
+-EXPORT_SYMBOL_GPL(sata_pmp_do_eh);
+-
+ EXPORT_SYMBOL_GPL(__ata_ehi_push_desc);
+ EXPORT_SYMBOL_GPL(ata_ehi_push_desc);
+ EXPORT_SYMBOL_GPL(ata_ehi_clear_desc);
+@@ -7931,8 +6290,7 @@ EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
+ EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
+ EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
+ EXPORT_SYMBOL_GPL(ata_do_eh);
+-EXPORT_SYMBOL_GPL(ata_irq_on);
+-EXPORT_SYMBOL_GPL(ata_dev_try_classify);
++EXPORT_SYMBOL_GPL(ata_std_error_handler);
+ 
+ EXPORT_SYMBOL_GPL(ata_cable_40wire);
+ EXPORT_SYMBOL_GPL(ata_cable_80wire);
+diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
+index a583032..61dcd00 100644
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -873,9 +873,9 @@ int sata_async_notification(struct ata_port *ap)
+ 	if (rc == 0)
+ 		sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);
+ 
+-	if (!ap->nr_pmp_links || rc) {
++	if (!sata_pmp_attached(ap) || rc) {
+ 		/* PMP is not attached or SNTF is not available */
+-		if (!ap->nr_pmp_links) {
++		if (!sata_pmp_attached(ap)) {
+ 			/* PMP is not attached.  Check whether ATAPI
+ 			 * AN is configured.  If so, notify media
+ 			 * change.
+@@ -1079,19 +1079,6 @@ void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
+ 
+ 	spin_lock_irqsave(ap->lock, flags);
+ 
+-	/* Reset is represented by combination of actions and EHI
+-	 * flags.  Suck in all related bits before clearing eh_info to
+-	 * avoid losing requested action.
+-	 */
+-	if (action & ATA_EH_RESET_MASK) {
+-		ehc->i.action |= ehi->action & ATA_EH_RESET_MASK;
+-		ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
+-
+-		/* make sure all reset actions are cleared & clear EHI flags */
+-		action |= ATA_EH_RESET_MASK;
+-		ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+-	}
+-
+ 	ata_eh_clear_action(link, dev, ehi, action);
+ 
+ 	if (!(ehc->i.flags & ATA_EHI_QUIET))
+@@ -1117,12 +1104,6 @@ void ata_eh_done(struct ata_link *link, struct ata_device *dev,
+ {
+ 	struct ata_eh_context *ehc = &link->eh_context;
+ 
+-	/* if reset is complete, clear all reset actions & reset modifier */
+-	if (action & ATA_EH_RESET_MASK) {
+-		action |= ATA_EH_RESET_MASK;
+-		ehc->i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+-	}
+-
+ 	ata_eh_clear_action(link, dev, &ehc->i, action);
+ }
+ 
+@@ -1329,20 +1310,20 @@ static void ata_eh_analyze_serror(struct ata_link *link)
+ 
+ 	if (serror & SERR_PERSISTENT) {
+ 		err_mask |= AC_ERR_ATA_BUS;
+-		action |= ATA_EH_HARDRESET;
++		action |= ATA_EH_RESET;
+ 	}
+ 	if (serror &
+ 	    (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
+ 		err_mask |= AC_ERR_ATA_BUS;
+-		action |= ATA_EH_SOFTRESET;
++		action |= ATA_EH_RESET;
+ 	}
+ 	if (serror & SERR_PROTOCOL) {
+ 		err_mask |= AC_ERR_HSM;
+-		action |= ATA_EH_SOFTRESET;
++		action |= ATA_EH_RESET;
+ 	}
+ 	if (serror & SERR_INTERNAL) {
+ 		err_mask |= AC_ERR_SYSTEM;
+-		action |= ATA_EH_HARDRESET;
++		action |= ATA_EH_RESET;
+ 	}
+ 
+ 	/* Determine whether a hotplug event has occurred.  Both
+@@ -1421,6 +1402,7 @@ static void ata_eh_analyze_ncq_error(struct ata_link *link)
+ 	/* we've got the perpetrator, condemn it */
+ 	qc = __ata_qc_from_tag(ap, tag);
+ 	memcpy(&qc->result_tf, &tf, sizeof(tf));
++	qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+ 	qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ;
+ 	ehc->i.err_mask &= ~AC_ERR_DEV;
+ }
+@@ -1448,7 +1430,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+ 
+ 	if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
+ 		qc->err_mask |= AC_ERR_HSM;
+-		return ATA_EH_SOFTRESET;
++		return ATA_EH_RESET;
+ 	}
+ 
+ 	if (stat & (ATA_ERR | ATA_DF))
+@@ -1484,7 +1466,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+ 	}
+ 
+ 	if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
+-		action |= ATA_EH_SOFTRESET;
++		action |= ATA_EH_RESET;
+ 
+ 	return action;
+ }
+@@ -1685,7 +1667,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
+ 	if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
+ 		/* speed down SATA link speed if possible */
+ 		if (sata_down_spd_limit(link) == 0) {
+-			action |= ATA_EH_HARDRESET;
++			action |= ATA_EH_RESET;
+ 			goto done;
+ 		}
+ 
+@@ -1705,7 +1687,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
+ 			dev->spdn_cnt++;
+ 
+ 			if (ata_down_xfermask_limit(dev, sel) == 0) {
+-				action |= ATA_EH_SOFTRESET;
++				action |= ATA_EH_RESET;
+ 				goto done;
+ 			}
+ 		}
+@@ -1719,7 +1701,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
+ 	    (dev->xfer_shift != ATA_SHIFT_PIO)) {
+ 		if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
+ 			dev->spdn_cnt = 0;
+-			action |= ATA_EH_SOFTRESET;
++			action |= ATA_EH_RESET;
+ 			goto done;
+ 		}
+ 	}
+@@ -1764,9 +1746,9 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ 		ehc->i.serror |= serror;
+ 		ata_eh_analyze_serror(link);
+ 	} else if (rc != -EOPNOTSUPP) {
+-		/* SError read failed, force hardreset and probing */
+-		ata_ehi_schedule_probe(&ehc->i);
+-		ehc->i.action |= ATA_EH_HARDRESET;
++		/* SError read failed, force reset and probing */
++		ehc->i.probe_mask |= ATA_ALL_DEVICES;
++		ehc->i.action |= ATA_EH_RESET;
+ 		ehc->i.err_mask |= AC_ERR_OTHER;
+ 	}
+ 
+@@ -1804,6 +1786,11 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ 		if (qc->flags & ATA_QCFLAG_SENSE_VALID)
+ 			qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
+ 
++		/* determine whether the command is worth retrying */
++		if (!(qc->err_mask & AC_ERR_INVALID) &&
++		    ((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV))
++			qc->flags |= ATA_QCFLAG_RETRY;
++
+ 		/* accumulate error info */
+ 		ehc->i.dev = qc->dev;
+ 		all_err_mask |= qc->err_mask;
+@@ -1814,7 +1801,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ 	/* enforce default EH actions */
+ 	if (ap->pflags & ATA_PFLAG_FROZEN ||
+ 	    all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
+-		ehc->i.action |= ATA_EH_SOFTRESET;
++		ehc->i.action |= ATA_EH_RESET;
+ 	else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) ||
+ 		 (!(eflags & ATA_EFLAG_IS_IO) && (all_err_mask & ~AC_ERR_DEV)))
+ 		ehc->i.action |= ATA_EH_REVALIDATE;
+@@ -1867,7 +1854,7 @@ void ata_eh_autopsy(struct ata_port *ap)
+ 	/* Autopsy of fanout ports can affect host link autopsy.
+ 	 * Perform host link autopsy last.
+ 	 */
+-	if (ap->nr_pmp_links)
++	if (sata_pmp_attached(ap))
+ 		ata_eh_link_autopsy(&ap->link);
+ }
+ 
+@@ -2066,41 +2053,29 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
+ 		classes[dev->devno] = ATA_DEV_UNKNOWN;
+ 
+ 	rc = reset(link, classes, deadline);
+-	if (rc)
+-		return rc;
+ 
+-	/* If any class isn't ATA_DEV_UNKNOWN, consider classification
+-	 * is complete and convert all ATA_DEV_UNKNOWN to
+-	 * ATA_DEV_NONE.
+-	 */
++	/* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
+ 	ata_link_for_each_dev(dev, link)
+-		if (classes[dev->devno] != ATA_DEV_UNKNOWN)
+-			break;
+-
+-	if (dev) {
+-		ata_link_for_each_dev(dev, link) {
+-			if (classes[dev->devno] == ATA_DEV_UNKNOWN)
+-				classes[dev->devno] = ATA_DEV_NONE;
+-		}
+-	}
++		if (classes[dev->devno] == ATA_DEV_UNKNOWN)
++			classes[dev->devno] = ATA_DEV_NONE;
+ 
+-	return 0;
++	return rc;
+ }
+ 
+ static int ata_eh_followup_srst_needed(struct ata_link *link,
+ 				       int rc, int classify,
+ 				       const unsigned int *classes)
+ {
+-	if (link->flags & ATA_LFLAG_NO_SRST)
++	if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link))
+ 		return 0;
+-	if (rc == -EAGAIN)
+-		return 1;
++	if (rc == -EAGAIN) {
++		if (classify)
++			return 1;
++		rc = 0;
++	}
+ 	if (rc != 0)
+ 		return 0;
+-	if ((link->ap->flags & ATA_FLAG_PMP) && ata_is_host_link(link))
+-		return 1;
+-	if (classify && !(link->flags & ATA_LFLAG_ASSUME_CLASS) &&
+-	    classes[0] == ATA_DEV_UNKNOWN)
++	if (sata_pmp_supported(link->ap) && ata_is_host_link(link))
+ 		return 1;
+ 	return 0;
+ }
+@@ -2118,7 +2093,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 	int try = 0;
+ 	struct ata_device *dev;
+ 	unsigned long deadline, now;
+-	unsigned int tmp_action;
+ 	ata_reset_fn_t reset;
+ 	unsigned long flags;
+ 	u32 sstatus;
+@@ -2129,7 +2103,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 	ap->pflags |= ATA_PFLAG_RESETTING;
+ 	spin_unlock_irqrestore(ap->lock, flags);
+ 
+-	ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
++	ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
+ 
+ 	ata_link_for_each_dev(dev, link) {
+ 		/* If we issue an SRST then an ATA drive (not ATAPI)
+@@ -2159,17 +2133,20 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 		goto done;
+ 	}
+ 
+-	/* Determine which reset to use and record in ehc->i.action.
+-	 * prereset() may examine and modify it.
+-	 */
+-	if (softreset && (!hardreset || (!(lflags & ATA_LFLAG_NO_SRST) &&
+-					 !sata_set_spd_needed(link) &&
+-					 !(ehc->i.action & ATA_EH_HARDRESET))))
+-		tmp_action = ATA_EH_SOFTRESET;
+-	else
+-		tmp_action = ATA_EH_HARDRESET;
+-
+-	ehc->i.action = (ehc->i.action & ~ATA_EH_RESET_MASK) | tmp_action;
++	/* prefer hardreset */
++	ehc->i.action &= ~ATA_EH_RESET;
++	if (hardreset) {
++		reset = hardreset;
++		ehc->i.action = ATA_EH_HARDRESET;
++	} else if (softreset) {
++		reset = softreset;
++		ehc->i.action = ATA_EH_SOFTRESET;
++	} else {
++		ata_link_printk(link, KERN_ERR, "BUG: no reset method, "
++				"please report to linux-ide at vger.kernel.org\n");
++		dump_stack();
++		return -EINVAL;
++	}
+ 
+ 	if (prereset) {
+ 		rc = prereset(link, jiffies + ATA_EH_PRERESET_TIMEOUT);
+@@ -2177,7 +2154,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 			if (rc == -ENOENT) {
+ 				ata_link_printk(link, KERN_DEBUG,
+ 						"port disabled. ignoring.\n");
+-				ehc->i.action &= ~ATA_EH_RESET_MASK;
++				ehc->i.action &= ~ATA_EH_RESET;
+ 
+ 				ata_link_for_each_dev(dev, link)
+ 					classes[dev->devno] = ATA_DEV_NONE;
+@@ -2190,12 +2167,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 		}
+ 	}
+ 
+-	/* prereset() might have modified ehc->i.action */
+-	if (ehc->i.action & ATA_EH_HARDRESET)
+-		reset = hardreset;
+-	else if (ehc->i.action & ATA_EH_SOFTRESET)
+-		reset = softreset;
+-	else {
++	/* prereset() might have cleared ATA_EH_RESET */
++	if (!(ehc->i.action & ATA_EH_RESET)) {
+ 		/* prereset told us not to reset, bang classes and return */
+ 		ata_link_for_each_dev(dev, link)
+ 			classes[dev->devno] = ATA_DEV_NONE;
+@@ -2203,14 +2176,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 		goto out;
+ 	}
+ 
+-	/* did prereset() screw up?  if so, fix up to avoid oopsing */
+-	if (!reset) {
+-		if (softreset)
+-			reset = softreset;
+-		else
+-			reset = hardreset;
+-	}
+-
+  retry:
+ 	deadline = jiffies + ata_eh_reset_timeouts[try++];
+ 
+@@ -2240,7 +2205,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 			goto fail;
+ 		}
+ 
+-		ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
++		ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
+ 		rc = ata_do_reset(link, reset, classes, deadline);
+ 	}
+ 
+@@ -2248,21 +2213,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 	if (rc && rc != -EAGAIN)
+ 		goto fail;
+ 
+-	/* was classification successful? */
+-	if (classify && classes[0] == ATA_DEV_UNKNOWN &&
+-	    !(lflags & ATA_LFLAG_ASSUME_CLASS)) {
+-		if (try < max_tries) {
+-			ata_link_printk(link, KERN_WARNING,
+-					"classification failed\n");
+-			rc = -EINVAL;
+-			goto fail;
+-		}
+-
+-		ata_link_printk(link, KERN_WARNING,
+-				"classfication failed, assuming ATA\n");
+-		lflags |= ATA_LFLAG_ASSUME_ATA;
+-	}
+-
+  done:
+ 	ata_link_for_each_dev(dev, link) {
+ 		/* After the reset, the device state is PIO 0 and the
+@@ -2290,7 +2240,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 		postreset(link, classes);
+ 
+ 	/* reset successful, schedule revalidation */
+-	ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
++	ata_eh_done(link, NULL, ATA_EH_RESET);
+ 	ehc->i.action |= ATA_EH_REVALIDATE;
+ 
+ 	rc = 0;
+@@ -2305,6 +2255,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ 	return rc;
+ 
+  fail:
++	/* if SCR isn't accessible on a fan-out port, PMP needs to be reset */
++	if (!ata_is_host_link(link) &&
++	    sata_scr_read(link, SCR_STATUS, &sstatus))
++		rc = -ERESTART;
++
+ 	if (rc == -ERESTART || try >= max_tries)
+ 		goto out;
+ 
+@@ -2515,6 +2470,7 @@ static int ata_link_nr_vacant(struct ata_link *link)
+ 
+ static int ata_eh_skip_recovery(struct ata_link *link)
+ {
++	struct ata_port *ap = link->ap;
+ 	struct ata_eh_context *ehc = &link->eh_context;
+ 	struct ata_device *dev;
+ 
+@@ -2522,9 +2478,13 @@ static int ata_eh_skip_recovery(struct ata_link *link)
+ 	if (link->flags & ATA_LFLAG_DISABLED)
+ 		return 1;
+ 
+-	/* thaw frozen port, resume link and recover failed devices */
+-	if ((link->ap->pflags & ATA_PFLAG_FROZEN) ||
+-	    (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_link_nr_enabled(link))
++	/* thaw frozen port and recover failed devices */
++	if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link))
++		return 0;
++
++	/* reset at least once if reset is requested */
++	if ((ehc->i.action & ATA_EH_RESET) &&
++	    !(ehc->i.flags & ATA_EHI_DID_RESET))
+ 		return 0;
+ 
+ 	/* skip if class codes for all vacant slots are ATA_DEV_NONE */
+@@ -2548,7 +2508,7 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
+ 	ata_eh_detach_dev(dev);
+ 	ata_dev_init(dev);
+ 	ehc->did_probe_mask |= (1 << dev->devno);
+-	ehc->i.action |= ATA_EH_SOFTRESET;
++	ehc->i.action |= ATA_EH_RESET;
+ 	ehc->saved_xfer_mode[dev->devno] = 0;
+ 	ehc->saved_ncq_enabled &= ~(1 << dev->devno);
+ 
+@@ -2592,12 +2552,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+ 
+ 		return 1;
+ 	} else {
+-		/* soft didn't work?  be haaaaard */
+-		if (ehc->i.flags & ATA_EHI_DID_RESET)
+-			ehc->i.action |= ATA_EH_HARDRESET;
+-		else
+-			ehc->i.action |= ATA_EH_SOFTRESET;
+-
++		ehc->i.action |= ATA_EH_RESET;
+ 		return 0;
+ 	}
+ }
+@@ -2690,7 +2645,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 			ehc->i.action = 0;
+ 
+ 		/* do we need to reset? */
+-		if (ehc->i.action & ATA_EH_RESET_MASK)
++		if (ehc->i.action & ATA_EH_RESET)
+ 			reset = 1;
+ 
+ 		ata_link_for_each_dev(dev, link)
+@@ -2702,13 +2657,13 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 		/* if PMP is attached, this function only deals with
+ 		 * downstream links, port should stay thawed.
+ 		 */
+-		if (!ap->nr_pmp_links)
++		if (!sata_pmp_attached(ap))
+ 			ata_eh_freeze_port(ap);
+ 
+ 		ata_port_for_each_link(link, ap) {
+ 			struct ata_eh_context *ehc = &link->eh_context;
+ 
+-			if (!(ehc->i.action & ATA_EH_RESET_MASK))
++			if (!(ehc->i.action & ATA_EH_RESET))
+ 				continue;
+ 
+ 			rc = ata_eh_reset(link, ata_link_nr_vacant(link),
+@@ -2721,7 +2676,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 			}
+ 		}
+ 
+-		if (!ap->nr_pmp_links)
++		if (!sata_pmp_attached(ap))
+ 			ata_eh_thaw_port(ap);
+ 	}
+ 
+@@ -2765,7 +2720,7 @@ dev_fail:
+ 			/* PMP reset requires working host port.
+ 			 * Can't retry if it's frozen.
+ 			 */
+-			if (ap->nr_pmp_links)
++			if (sata_pmp_attached(ap))
+ 				goto out;
+ 			break;
+ 		}
+@@ -2817,18 +2772,11 @@ void ata_eh_finish(struct ata_port *ap)
+ 			/* FIXME: Once EH migration is complete,
+ 			 * generate sense data in this function,
+ 			 * considering both err_mask and tf.
+-			 *
+-			 * There's no point in retrying invalid
+-			 * (detected by libata) and non-IO device
+-			 * errors (rejected by device).  Finish them
+-			 * immediately.
+ 			 */
+-			if ((qc->err_mask & AC_ERR_INVALID) ||
+-			    (!(qc->flags & ATA_QCFLAG_IO) &&
+-			     qc->err_mask == AC_ERR_DEV))
+-				ata_eh_qc_complete(qc);
+-			else
++			if (qc->flags & ATA_QCFLAG_RETRY)
+ 				ata_eh_qc_retry(qc);
++			else
++				ata_eh_qc_complete(qc);
+ 		} else {
+ 			if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+ 				ata_eh_qc_complete(qc);
+@@ -2848,6 +2796,7 @@ void ata_eh_finish(struct ata_port *ap)
+ /**
+  *	ata_do_eh - do standard error handling
+  *	@ap: host port to handle error for
++ *
+  *	@prereset: prereset method (can be NULL)
+  *	@softreset: softreset method (can be NULL)
+  *	@hardreset: hardreset method (can be NULL)
+@@ -2878,6 +2827,27 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 	ata_eh_finish(ap);
+ }
+ 
++/**
++ *	ata_std_error_handler - standard error handler
++ *	@ap: host port to handle error for
++ *
++ *	Standard error handler
++ *
++ *	LOCKING:
++ *	Kernel thread context (may sleep).
++ */
++void ata_std_error_handler(struct ata_port *ap)
++{
++	struct ata_port_operations *ops = ap->ops;
++	ata_reset_fn_t hardreset = ops->hardreset;
++
++	/* ignore built-in hardreset if SCR access is not available */
++	if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
++		hardreset = NULL;
++
++	ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
++}
++
+ #ifdef CONFIG_PM
+ /**
+  *	ata_eh_handle_port_suspend - perform port suspend operation
+diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
+index d91f509..ff1822a 100644
+--- a/drivers/ata/libata-pmp.c
++++ b/drivers/ata/libata-pmp.c
+@@ -11,6 +11,14 @@
+ #include <linux/libata.h>
+ #include "libata.h"
+ 
++const struct ata_port_operations sata_pmp_port_ops = {
++	.inherits		= &sata_port_ops,
++	.pmp_prereset		= ata_std_prereset,
++	.pmp_hardreset		= sata_std_hardreset,
++	.pmp_postreset		= ata_std_postreset,
++	.error_handler		= sata_pmp_error_handler,
++};
++
+ /**
+  *	sata_pmp_read - read PMP register
+  *	@link: link to read PMP register for
+@@ -176,140 +184,6 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
+ }
+ 
+ /**
+- *	sata_pmp_std_prereset - prepare PMP link for reset
+- *	@link: link to be reset
+- *	@deadline: deadline jiffies for the operation
+- *
+- *	@link is about to be reset.  Initialize it.
+- *
+- *	LOCKING:
+- *	Kernel thread context (may sleep)
+- *
+- *	RETURNS:
+- *	0 on success, -errno otherwise.
+- */
+-int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline)
+-{
+-	struct ata_eh_context *ehc = &link->eh_context;
+-	const unsigned long *timing = sata_ehc_deb_timing(ehc);
+-	int rc;
+-
+-	/* force HRST? */
+-	if (link->flags & ATA_LFLAG_NO_SRST)
+-		ehc->i.action |= ATA_EH_HARDRESET;
+-
+-	/* handle link resume */
+-	if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
+-	    (link->flags & ATA_LFLAG_HRST_TO_RESUME))
+-		ehc->i.action |= ATA_EH_HARDRESET;
+-
+-	/* if we're about to do hardreset, nothing more to do */
+-	if (ehc->i.action & ATA_EH_HARDRESET)
+-		return 0;
+-
+-	/* resume link */
+-	rc = sata_link_resume(link, timing, deadline);
+-	if (rc) {
+-		/* phy resume failed */
+-		ata_link_printk(link, KERN_WARNING, "failed to resume link "
+-				"for reset (errno=%d)\n", rc);
+-		return rc;
+-	}
+-
+-	/* clear SError bits including .X which blocks the port when set */
+-	rc = sata_scr_write(link, SCR_ERROR, 0xffffffff);
+-	if (rc) {
+-		ata_link_printk(link, KERN_ERR,
+-				"failed to clear SError (errno=%d)\n", rc);
+-		return rc;
+-	}
+-
+-	return 0;
+-}
+-
+-/**
+- *	sata_pmp_std_hardreset - standard hardreset method for PMP link
+- *	@link: link to be reset
+- *	@class: resulting class of attached device
+- *	@deadline: deadline jiffies for the operation
+- *
+- *	Hardreset PMP port @link.  Note that this function doesn't
+- *	wait for BSY clearance.  There simply isn't a generic way to
+- *	wait the event.  Instead, this function return -EAGAIN thus
+- *	telling libata-EH to followup with softreset.
+- *
+- *	LOCKING:
+- *	Kernel thread context (may sleep)
+- *
+- *	RETURNS:
+- *	0 on success, -errno otherwise.
+- */
+-int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class,
+-			   unsigned long deadline)
+-{
+-	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+-	u32 tmp;
+-	int rc;
+-
+-	DPRINTK("ENTER\n");
+-
+-	/* do hardreset */
+-	rc = sata_link_hardreset(link, timing, deadline);
+-	if (rc) {
+-		ata_link_printk(link, KERN_ERR,
+-				"COMRESET failed (errno=%d)\n", rc);
+-		goto out;
+-	}
+-
+-	/* clear SError bits including .X which blocks the port when set */
+-	rc = sata_scr_write(link, SCR_ERROR, 0xffffffff);
+-	if (rc) {
+-		ata_link_printk(link, KERN_ERR, "failed to clear SError "
+-				"during hardreset (errno=%d)\n", rc);
+-		goto out;
+-	}
+-
+-	/* if device is present, follow up with srst to wait for !BSY */
+-	if (ata_link_online(link))
+-		rc = -EAGAIN;
+- out:
+-	/* if SCR isn't accessible, we need to reset the PMP */
+-	if (rc && rc != -EAGAIN && sata_scr_read(link, SCR_STATUS, &tmp))
+-		rc = -ERESTART;
+-
+-	DPRINTK("EXIT, rc=%d\n", rc);
+-	return rc;
+-}
+-
+-/**
+- *	ata_std_postreset - standard postreset method for PMP link
+- *	@link: the target ata_link
+- *	@classes: classes of attached devices
+- *
+- *	This function is invoked after a successful reset.  Note that
+- *	the device might have been reset more than once using
+- *	different reset methods before postreset is invoked.
+- *
+- *	LOCKING:
+- *	Kernel thread context (may sleep)
+- */
+-void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class)
+-{
+-	u32 serror;
+-
+-	DPRINTK("ENTER\n");
+-
+-	/* clear SError */
+-	if (sata_scr_read(link, SCR_ERROR, &serror) == 0)
+-		sata_scr_write(link, SCR_ERROR, serror);
+-
+-	/* print link status */
+-	sata_print_link_status(link);
+-
+-	DPRINTK("EXIT\n");
+-}
+-
+-/**
+  *	sata_pmp_read_gscr - read GSCR block of SATA PMP
+  *	@dev: PMP device
+  *	@gscr: buffer to read GSCR block into
+@@ -444,9 +318,8 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
+ 		struct ata_eh_context *ehc = &link->eh_context;
+ 
+ 		link->flags = 0;
+-		ehc->i.probe_mask |= 1;
+-		ehc->i.action |= ATA_EH_SOFTRESET;
+-		ehc->i.flags |= ATA_EHI_RESUME_LINK;
++		ehc->i.probe_mask |= ATA_ALL_DEVICES;
++		ehc->i.action |= ATA_EH_RESET;
+ 	}
+ 
+ 	return 0;
+@@ -462,9 +335,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ 	if (vendor == 0x1095 && devid == 0x3726) {
+ 		/* sil3726 quirks */
+ 		ata_port_for_each_link(link, ap) {
+-			/* SError.N need a kick in the ass to get working */
+-			link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+-
+ 			/* class code report is unreliable */
+ 			if (link->pmp < 5)
+ 				link->flags |= ATA_LFLAG_ASSUME_ATA;
+@@ -477,9 +347,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ 	} else if (vendor == 0x1095 && devid == 0x4723) {
+ 		/* sil4723 quirks */
+ 		ata_port_for_each_link(link, ap) {
+-			/* SError.N need a kick in the ass to get working */
+-			link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+-
+ 			/* class code report is unreliable */
+ 			if (link->pmp < 2)
+ 				link->flags |= ATA_LFLAG_ASSUME_ATA;
+@@ -492,9 +359,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ 	} else if (vendor == 0x1095 && devid == 0x4726) {
+ 		/* sil4726 quirks */
+ 		ata_port_for_each_link(link, ap) {
+-			/* SError.N need a kick in the ass to get working */
+-			link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+-
+ 			/* Class code report is unreliable and SRST
+ 			 * times out under certain configurations.
+ 			 * Config device can be at port 0 or 5 and
+@@ -522,13 +386,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ 		 * otherwise.  Don't try hard to recover it.
+ 		 */
+ 		ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
+-	} else if (vendor == 0x11ab && devid == 0x4140) {
+-		/* Marvell 88SM4140 quirks.  Fan-out ports require PHY
+-		 * reset to work; other than that, it behaves very
+-		 * nicely.
+-		 */
+-		ata_port_for_each_link(link, ap)
+-			link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+ 	}
+ }
+ 
+@@ -554,7 +411,7 @@ int sata_pmp_attach(struct ata_device *dev)
+ 	int rc;
+ 
+ 	/* is it hanging off the right place? */
+-	if (!(ap->flags & ATA_FLAG_PMP)) {
++	if (!sata_pmp_supported(ap)) {
+ 		ata_dev_printk(dev, KERN_ERR,
+ 			       "host does not support Port Multiplier\n");
+ 		return -EINVAL;
+@@ -840,13 +697,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+  retry:
+ 	ehc->classes[0] = ATA_DEV_UNKNOWN;
+ 
+-	if (ehc->i.action & ATA_EH_RESET_MASK) {
++	if (ehc->i.action & ATA_EH_RESET) {
+ 		struct ata_link *tlink;
+ 
+ 		ata_eh_freeze_port(ap);
+ 
+ 		/* reset */
+-		ehc->i.action = ATA_EH_HARDRESET;
+ 		rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
+ 				  postreset);
+ 		if (rc) {
+@@ -858,8 +714,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ 		ata_eh_thaw_port(ap);
+ 
+ 		/* PMP is reset, SErrors cannot be trusted, scan all */
+-		ata_port_for_each_link(tlink, ap)
+-			ata_ehi_schedule_probe(&tlink->eh_context.i);
++		ata_port_for_each_link(tlink, ap) {
++			struct ata_eh_context *ehc = &tlink->eh_context;
++
++			ehc->i.probe_mask |= ATA_ALL_DEVICES;
++			ehc->i.action |= ATA_EH_RESET;
++		}
+ 	}
+ 
+ 	/* If revalidation is requested, revalidate and reconfigure;
+@@ -874,7 +734,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ 		tries--;
+ 
+ 		if (rc == -ENODEV) {
+-			ehc->i.probe_mask |= 1;
++			ehc->i.probe_mask |= ATA_ALL_DEVICES;
+ 			detach = 1;
+ 			/* give it just two more chances */
+ 			tries = min(tries, 2);
+@@ -890,11 +750,11 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ 				reval_failed = 1;
+ 
+ 			ata_dev_printk(dev, KERN_WARNING,
+-				       "retrying hardreset%s\n",
++				       "retrying reset%s\n",
+ 				       sleep ? " in 5 secs" : "");
+ 			if (sleep)
+ 				ssleep(5);
+-			ehc->i.action |= ATA_EH_HARDRESET;
++			ehc->i.action |= ATA_EH_RESET;
+ 			goto retry;
+ 		} else {
+ 			ata_dev_printk(dev, KERN_ERR, "failed to recover PMP "
+@@ -938,10 +798,8 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)
+ 		/* Some PMPs require hardreset sequence to get
+ 		 * SError.N working.
+ 		 */
+-		if ((link->flags & ATA_LFLAG_HRST_TO_RESUME) &&
+-		    (link->eh_context.i.flags & ATA_EHI_RESUME_LINK))
+-			sata_link_hardreset(link, sata_deb_timing_normal,
+-					    jiffies + ATA_TMOUT_INTERNAL_QUICK);
++		sata_link_hardreset(link, sata_deb_timing_normal,
++				jiffies + ATA_TMOUT_INTERNAL_QUICK, NULL, NULL);
+ 
+ 		/* unconditionally clear SError.N */
+ 		rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
+@@ -987,14 +845,6 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
+ /**
+  *	sata_pmp_eh_recover - recover PMP-enabled port
+  *	@ap: ATA port to recover
+- *	@prereset: prereset method (can be NULL)
+- *	@softreset: softreset method
+- *	@hardreset: hardreset method
+- *	@postreset: postreset method (can be NULL)
+- *	@pmp_prereset: PMP prereset method (can be NULL)
+- *	@pmp_softreset: PMP softreset method (can be NULL)
+- *	@pmp_hardreset: PMP hardreset method (can be NULL)
+- *	@pmp_postreset: PMP postreset method (can be NULL)
+  *
+  *	Drive EH recovery operation for PMP enabled port @ap.  This
+  *	function recovers host and PMP ports with proper retrials and
+@@ -1007,12 +857,9 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
+  *	RETURNS:
+  *	0 on success, -errno on failure.
+  */
+-static int sata_pmp_eh_recover(struct ata_port *ap,
+-		ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+-		ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
+-		ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
+-		ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset)
++static int sata_pmp_eh_recover(struct ata_port *ap)
+ {
++	struct ata_port_operations *ops = ap->ops;
+ 	int pmp_tries, link_tries[SATA_PMP_MAX_PORTS];
+ 	struct ata_link *pmp_link = &ap->link;
+ 	struct ata_device *pmp_dev = pmp_link->device;
+@@ -1029,9 +876,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ 
+  retry:
+ 	/* PMP attached? */
+-	if (!ap->nr_pmp_links) {
+-		rc = ata_eh_recover(ap, prereset, softreset, hardreset,
+-				    postreset, NULL);
++	if (!sata_pmp_attached(ap)) {
++		rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
++				    ops->hardreset, ops->postreset, NULL);
+ 		if (rc) {
+ 			ata_link_for_each_dev(dev, &ap->link)
+ 				ata_dev_disable(dev);
+@@ -1049,8 +896,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ 	}
+ 
+ 	/* recover pmp */
+-	rc = sata_pmp_eh_recover_pmp(ap, prereset, softreset, hardreset,
+-				     postreset);
++	rc = sata_pmp_eh_recover_pmp(ap, ops->prereset, ops->softreset,
++				     ops->hardreset, ops->postreset);
+ 	if (rc)
+ 		goto pmp_fail;
+ 
+@@ -1060,8 +907,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ 		goto pmp_fail;
+ 
+ 	/* recover links */
+-	rc = ata_eh_recover(ap, pmp_prereset, pmp_softreset, pmp_hardreset,
+-			    pmp_postreset, &link);
++	rc = ata_eh_recover(ap, ops->pmp_prereset, ops->pmp_softreset,
++			    ops->pmp_hardreset, ops->pmp_postreset, &link);
+ 	if (rc)
+ 		goto link_fail;
+ 
+@@ -1124,7 +971,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ 
+  link_fail:
+ 	if (sata_pmp_handle_link_fail(link, link_tries)) {
+-		pmp_ehc->i.action |= ATA_EH_HARDRESET;
++		pmp_ehc->i.action |= ATA_EH_RESET;
+ 		goto retry;
+ 	}
+ 
+@@ -1136,13 +983,13 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ 	if (ap->pflags & ATA_PFLAG_UNLOADING)
+ 		return rc;
+ 
+-	if (!ap->nr_pmp_links)
++	if (!sata_pmp_attached(ap))
+ 		goto retry;
+ 
+ 	if (--pmp_tries) {
+ 		ata_port_printk(ap, KERN_WARNING,
+ 				"failed to recover PMP, retrying in 5 secs\n");
+-		pmp_ehc->i.action |= ATA_EH_HARDRESET;
++		pmp_ehc->i.action |= ATA_EH_RESET;
+ 		ssleep(5);
+ 		goto retry;
+ 	}
+@@ -1157,16 +1004,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ }
+ 
+ /**
+- *	sata_pmp_do_eh - do standard error handling for PMP-enabled host
++ *	sata_pmp_error_handler - do standard error handling for PMP-enabled host
+  *	@ap: host port to handle error for
+- *	@prereset: prereset method (can be NULL)
+- *	@softreset: softreset method
+- *	@hardreset: hardreset method
+- *	@postreset: postreset method (can be NULL)
+- *	@pmp_prereset: PMP prereset method (can be NULL)
+- *	@pmp_softreset: PMP softreset method (can be NULL)
+- *	@pmp_hardreset: PMP hardreset method (can be NULL)
+- *	@pmp_postreset: PMP postreset method (can be NULL)
+  *
+  *	Perform standard error handling sequence for PMP-enabled host
+  *	@ap.
+@@ -1174,16 +1013,14 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+  *	LOCKING:
+  *	Kernel thread context (may sleep).
+  */
+-void sata_pmp_do_eh(struct ata_port *ap,
+-		ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+-		ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
+-		ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
+-		ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset)
++void sata_pmp_error_handler(struct ata_port *ap)
+ {
+ 	ata_eh_autopsy(ap);
+ 	ata_eh_report(ap);
+-	sata_pmp_eh_recover(ap, prereset, softreset, hardreset, postreset,
+-			    pmp_prereset, pmp_softreset, pmp_hardreset,
+-			    pmp_postreset);
++	sata_pmp_eh_recover(ap);
+ 	ata_eh_finish(ap);
+ }
++
++EXPORT_SYMBOL_GPL(sata_pmp_port_ops);
++EXPORT_SYMBOL_GPL(sata_pmp_qc_defer_cmd_switch);
++EXPORT_SYMBOL_GPL(sata_pmp_error_handler);
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 1579539..a34f324 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -131,10 +131,11 @@ static const char *ata_scsi_lpm_get(enum link_pm policy)
+ 	return NULL;
+ }
+ 
+-static ssize_t ata_scsi_lpm_put(struct class_device *class_dev,
+-	const char *buf, size_t count)
++static ssize_t ata_scsi_lpm_put(struct device *dev,
++				struct device_attribute *attr,
++				const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ata_port *ap = ata_shost_to_port(shost);
+ 	enum link_pm policy = 0;
+ 	int i;
+@@ -162,9 +163,9 @@ static ssize_t ata_scsi_lpm_put(struct class_device *class_dev,
+ }
+ 
+ static ssize_t
+-ata_scsi_lpm_show(struct class_device *class_dev, char *buf)
++ata_scsi_lpm_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	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);
+@@ -174,9 +175,9 @@ ata_scsi_lpm_show(struct class_device *class_dev, char *buf)
+ 
+ 	return snprintf(buf, 23, "%s\n", policy);
+ }
+-CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
++DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
+ 		ata_scsi_lpm_show, ata_scsi_lpm_put);
+-EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy);
++EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
+ 
+ static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
+ 				   void (*done)(struct scsi_cmnd *))
+@@ -2332,11 +2333,7 @@ void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+ {
+ 	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+ 
+-	cmd->sense_buffer[0] = 0x70;	/* fixed format, current */
+-	cmd->sense_buffer[2] = sk;
+-	cmd->sense_buffer[7] = 18 - 8;	/* additional sense length */
+-	cmd->sense_buffer[12] = asc;
+-	cmd->sense_buffer[13] = ascq;
++	scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
+ }
+ 
+ /**
+@@ -2393,7 +2390,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
+ 	/* FIXME: is this needed? */
+ 	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+ 
+-	ap->ops->tf_read(ap, &qc->tf);
++#ifdef CONFIG_ATA_SFF
++	if (ap->ops->sff_tf_read)
++		ap->ops->sff_tf_read(ap, &qc->tf);
++#endif
+ 
+ 	/* fill these in, for the case where they are -not- overwritten */
+ 	cmd->sense_buffer[0] = 0x70;
+@@ -2615,7 +2615,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
+ 
+ static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
+ {
+-	if (ap->nr_pmp_links == 0) {
++	if (!sata_pmp_attached(ap)) {
+ 		if (likely(devno < ata_link_max_devices(&ap->link)))
+ 			return &ap->link.device[devno];
+ 	} else {
+@@ -2632,7 +2632,7 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
+ 	int devno;
+ 
+ 	/* skip commands not addressed to targets we simulate */
+-	if (ap->nr_pmp_links == 0) {
++	if (!sata_pmp_attached(ap)) {
+ 		if (unlikely(scsidev->channel || scsidev->lun))
+ 			return NULL;
+ 		devno = scsidev->id;
+@@ -3490,7 +3490,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ 	if (lun != SCAN_WILD_CARD && lun)
+ 		return -EINVAL;
+ 
+-	if (ap->nr_pmp_links == 0) {
++	if (!sata_pmp_attached(ap)) {
+ 		if (channel != SCAN_WILD_CARD && channel)
+ 			return -EINVAL;
+ 		devno = id;
+@@ -3507,8 +3507,8 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ 
+ 		ata_port_for_each_link(link, ap) {
+ 			struct ata_eh_info *ehi = &link->eh_info;
+-			ehi->probe_mask |= (1 << ata_link_max_devices(link)) - 1;
+-			ehi->action |= ATA_EH_SOFTRESET;
++			ehi->probe_mask |= ATA_ALL_DEVICES;
++			ehi->action |= ATA_EH_RESET;
+ 		}
+ 	} else {
+ 		struct ata_device *dev = ata_find_dev(ap, devno);
+@@ -3516,8 +3516,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ 		if (dev) {
+ 			struct ata_eh_info *ehi = &dev->link->eh_info;
+ 			ehi->probe_mask |= 1 << dev->devno;
+-			ehi->action |= ATA_EH_SOFTRESET;
+-			ehi->flags |= ATA_EHI_RESUME_LINK;
++			ehi->action |= ATA_EH_RESET;
+ 		} else
+ 			rc = -EINVAL;
+ 	}
+diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
+index 20dc572..2ec65a8 100644
+--- a/drivers/ata/libata-sff.c
++++ b/drivers/ata/libata-sff.c
+@@ -35,11 +35,377 @@
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+ #include <linux/libata.h>
++#include <linux/highmem.h>
+ 
+ #include "libata.h"
+ 
++const struct ata_port_operations ata_sff_port_ops = {
++	.inherits		= &ata_base_port_ops,
++
++	.qc_prep		= ata_sff_qc_prep,
++	.qc_issue		= ata_sff_qc_issue,
++	.qc_fill_rtf		= ata_sff_qc_fill_rtf,
++
++	.freeze			= ata_sff_freeze,
++	.thaw			= ata_sff_thaw,
++	.prereset		= ata_sff_prereset,
++	.softreset		= ata_sff_softreset,
++	.hardreset		= sata_sff_hardreset,
++	.postreset		= ata_sff_postreset,
++	.error_handler		= ata_sff_error_handler,
++	.post_internal_cmd	= ata_sff_post_internal_cmd,
++
++	.sff_dev_select		= ata_sff_dev_select,
++	.sff_check_status	= ata_sff_check_status,
++	.sff_tf_load		= ata_sff_tf_load,
++	.sff_tf_read		= ata_sff_tf_read,
++	.sff_exec_command	= ata_sff_exec_command,
++	.sff_data_xfer		= ata_sff_data_xfer,
++	.sff_irq_on		= ata_sff_irq_on,
++	.sff_irq_clear		= ata_sff_irq_clear,
++
++	.port_start		= ata_sff_port_start,
++};
++
++const struct ata_port_operations ata_bmdma_port_ops = {
++	.inherits		= &ata_sff_port_ops,
++
++	.mode_filter		= ata_bmdma_mode_filter,
++
++	.bmdma_setup		= ata_bmdma_setup,
++	.bmdma_start		= ata_bmdma_start,
++	.bmdma_stop		= ata_bmdma_stop,
++	.bmdma_status		= ata_bmdma_status,
++};
++
++/**
++ *	ata_fill_sg - Fill PCI IDE PRD table
++ *	@qc: Metadata associated with taskfile to be transferred
++ *
++ *	Fill PCI IDE PRD (scatter-gather) table with segments
++ *	associated with the current disk command.
++ *
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ *
++ */
++static void ata_fill_sg(struct ata_queued_cmd *qc)
++{
++	struct ata_port *ap = qc->ap;
++	struct scatterlist *sg;
++	unsigned int si, pi;
++
++	pi = 0;
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
++		u32 addr, offset;
++		u32 sg_len, len;
++
++		/* determine if physical DMA addr spans 64K boundary.
++		 * Note h/w doesn't support 64-bit, so we unconditionally
++		 * truncate dma_addr_t to u32.
++		 */
++		addr = (u32) sg_dma_address(sg);
++		sg_len = sg_dma_len(sg);
++
++		while (sg_len) {
++			offset = addr & 0xffff;
++			len = sg_len;
++			if ((offset + sg_len) > 0x10000)
++				len = 0x10000 - offset;
++
++			ap->prd[pi].addr = cpu_to_le32(addr);
++			ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
++			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
++
++			pi++;
++			sg_len -= len;
++			addr += len;
++		}
++	}
++
++	ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++}
++
++/**
++ *	ata_fill_sg_dumb - Fill PCI IDE PRD table
++ *	@qc: Metadata associated with taskfile to be transferred
++ *
++ *	Fill PCI IDE PRD (scatter-gather) table with segments
++ *	associated with the current disk command. Perform the fill
++ *	so that we avoid writing any length 64K records for
++ *	controllers that don't follow the spec.
++ *
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ *
++ */
++static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
++{
++	struct ata_port *ap = qc->ap;
++	struct scatterlist *sg;
++	unsigned int si, pi;
++
++	pi = 0;
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
++		u32 addr, offset;
++		u32 sg_len, len, blen;
++
++		/* determine if physical DMA addr spans 64K boundary.
++		 * Note h/w doesn't support 64-bit, so we unconditionally
++		 * truncate dma_addr_t to u32.
++		 */
++		addr = (u32) sg_dma_address(sg);
++		sg_len = sg_dma_len(sg);
++
++		while (sg_len) {
++			offset = addr & 0xffff;
++			len = sg_len;
++			if ((offset + sg_len) > 0x10000)
++				len = 0x10000 - offset;
++
++			blen = len & 0xffff;
++			ap->prd[pi].addr = cpu_to_le32(addr);
++			if (blen == 0) {
++			   /* Some PATA chipsets like the CS5530 can't
++			      cope with 0x0000 meaning 64K as the spec says */
++				ap->prd[pi].flags_len = cpu_to_le32(0x8000);
++				blen = 0x8000;
++				ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
++			}
++			ap->prd[pi].flags_len = cpu_to_le32(blen);
++			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
++
++			pi++;
++			sg_len -= len;
++			addr += len;
++		}
++	}
++
++	ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++}
++
++/**
++ *	ata_sff_qc_prep - Prepare taskfile for submission
++ *	@qc: Metadata associated with taskfile to be prepared
++ *
++ *	Prepare ATA taskfile for submission.
++ *
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ */
++void ata_sff_qc_prep(struct ata_queued_cmd *qc)
++{
++	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
++		return;
++
++	ata_fill_sg(qc);
++}
++
++/**
++ *	ata_sff_dumb_qc_prep - Prepare taskfile for submission
++ *	@qc: Metadata associated with taskfile to be prepared
++ *
++ *	Prepare ATA taskfile for submission.
++ *
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ */
++void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc)
++{
++	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
++		return;
++
++	ata_fill_sg_dumb(qc);
++}
++
++/**
++ *	ata_sff_check_status - Read device status reg & clear interrupt
++ *	@ap: port where the device is
++ *
++ *	Reads ATA taskfile status register for currently-selected device
++ *	and return its value. This also clears pending interrupts
++ *      from this device
++ *
++ *	LOCKING:
++ *	Inherited from caller.
++ */
++u8 ata_sff_check_status(struct ata_port *ap)
++{
++	return ioread8(ap->ioaddr.status_addr);
++}
++
++/**
++ *	ata_sff_altstatus - Read device alternate status reg
++ *	@ap: port where the device is
++ *
++ *	Reads ATA taskfile alternate status register for
++ *	currently-selected device and return its value.
++ *
++ *	Note: may NOT be used as the check_altstatus() entry in
++ *	ata_port_operations.
++ *
++ *	LOCKING:
++ *	Inherited from caller.
++ */
++u8 ata_sff_altstatus(struct ata_port *ap)
++{
++	if (ap->ops->sff_check_altstatus)
++		return ap->ops->sff_check_altstatus(ap);
++
++	return ioread8(ap->ioaddr.altstatus_addr);
++}
++
++/**
++ *	ata_sff_busy_sleep - sleep until BSY clears, or timeout
++ *	@ap: port containing status register to be polled
++ *	@tmout_pat: impatience timeout
++ *	@tmout: overall timeout
++ *
++ *	Sleep until ATA Status register bit BSY clears,
++ *	or a timeout occurs.
++ *
++ *	LOCKING:
++ *	Kernel thread context (may sleep).
++ *
++ *	RETURNS:
++ *	0 on success, -errno otherwise.
++ */
++int ata_sff_busy_sleep(struct ata_port *ap,
++		       unsigned long tmout_pat, unsigned long tmout)
++{
++	unsigned long timer_start, timeout;
++	u8 status;
++
++	status = ata_sff_busy_wait(ap, ATA_BUSY, 300);
++	timer_start = jiffies;
++	timeout = timer_start + tmout_pat;
++	while (status != 0xff && (status & ATA_BUSY) &&
++	       time_before(jiffies, timeout)) {
++		msleep(50);
++		status = ata_sff_busy_wait(ap, ATA_BUSY, 3);
++	}
++
++	if (status != 0xff && (status & ATA_BUSY))
++		ata_port_printk(ap, KERN_WARNING,
++				"port is slow to respond, please be patient "
++				"(Status 0x%x)\n", status);
++
++	timeout = timer_start + tmout;
++	while (status != 0xff && (status & ATA_BUSY) &&
++	       time_before(jiffies, timeout)) {
++		msleep(50);
++		status = ap->ops->sff_check_status(ap);
++	}
++
++	if (status == 0xff)
++		return -ENODEV;
++
++	if (status & ATA_BUSY) {
++		ata_port_printk(ap, KERN_ERR, "port failed to respond "
++				"(%lu secs, Status 0x%x)\n",
++				tmout / HZ, status);
++		return -EBUSY;
++	}
++
++	return 0;
++}
++
++static int ata_sff_check_ready(struct ata_link *link)
++{
++	u8 status = link->ap->ops->sff_check_status(link->ap);
++
++	if (!(status & ATA_BUSY))
++		return 1;
++	if (status == 0xff)
++		return -ENODEV;
++	return 0;
++}
++
++/**
++ *	ata_sff_wait_ready - sleep until BSY clears, or timeout
++ *	@link: SFF link to wait ready status for
++ *	@deadline: deadline jiffies for the operation
++ *
++ *	Sleep until ATA Status register bit BSY clears, or timeout
++ *	occurs.
++ *
++ *	LOCKING:
++ *	Kernel thread context (may sleep).
++ *
++ *	RETURNS:
++ *	0 on success, -errno otherwise.
++ */
++int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline)
++{
++	return ata_wait_ready(link, deadline, ata_sff_check_ready);
++}
++
++/**
++ *	ata_sff_dev_select - Select device 0/1 on ATA bus
++ *	@ap: ATA channel to manipulate
++ *	@device: ATA device (numbered from zero) to select
++ *
++ *	Use the method defined in the ATA specification to
++ *	make either device 0, or device 1, active on the
++ *	ATA channel.  Works with both PIO and MMIO.
++ *
++ *	May be used as the dev_select() entry in ata_port_operations.
++ *
++ *	LOCKING:
++ *	caller.
++ */
++void ata_sff_dev_select(struct ata_port *ap, unsigned int device)
++{
++	u8 tmp;
++
++	if (device == 0)
++		tmp = ATA_DEVICE_OBS;
++	else
++		tmp = ATA_DEVICE_OBS | ATA_DEV1;
++
++	iowrite8(tmp, ap->ioaddr.device_addr);
++	ata_sff_pause(ap);	/* needed; also flushes, for mmio */
++}
++
++/**
++ *	ata_dev_select - Select device 0/1 on ATA bus
++ *	@ap: ATA channel to manipulate
++ *	@device: ATA device (numbered from zero) to select
++ *	@wait: non-zero to wait for Status register BSY bit to clear
++ *	@can_sleep: non-zero if context allows sleeping
++ *
++ *	Use the method defined in the ATA specification to
++ *	make either device 0, or device 1, active on the
++ *	ATA channel.
++ *
++ *	This is a high-level version of ata_sff_dev_select(), which
++ *	additionally provides the services of inserting the proper
++ *	pauses and status polling, where needed.
++ *
++ *	LOCKING:
++ *	caller.
++ */
++void ata_dev_select(struct ata_port *ap, unsigned int device,
++			   unsigned int wait, unsigned int can_sleep)
++{
++	if (ata_msg_probe(ap))
++		ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
++				"device %u, wait %u\n", device, wait);
++
++	if (wait)
++		ata_wait_idle(ap);
++
++	ap->ops->sff_dev_select(ap, device);
++
++	if (wait) {
++		if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
++			msleep(150);
++		ata_wait_idle(ap);
++	}
++}
++
+ /**
+- *	ata_irq_on - Enable interrupts on a port.
++ *	ata_sff_irq_on - Enable interrupts on a port.
+  *	@ap: Port on which interrupts are enabled.
+  *
+  *	Enable interrupts on a legacy IDE device using MMIO or PIO,
+@@ -48,7 +414,7 @@
+  *	LOCKING:
+  *	Inherited from caller.
+  */
+-u8 ata_irq_on(struct ata_port *ap)
++u8 ata_sff_irq_on(struct ata_port *ap)
+ {
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 	u8 tmp;
+@@ -60,13 +426,34 @@ u8 ata_irq_on(struct ata_port *ap)
+ 		iowrite8(ap->ctl, ioaddr->ctl_addr);
+ 	tmp = ata_wait_idle(ap);
+ 
+-	ap->ops->irq_clear(ap);
++	ap->ops->sff_irq_clear(ap);
+ 
+ 	return tmp;
+ }
+ 
+ /**
+- *	ata_tf_load - send taskfile registers to host controller
++ *	ata_sff_irq_clear - Clear PCI IDE BMDMA interrupt.
++ *	@ap: Port associated with this ATA transaction.
++ *
++ *	Clear interrupt and error flags in DMA status register.
++ *
++ *	May be used as the irq_clear() entry in ata_port_operations.
++ *
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ */
++void ata_sff_irq_clear(struct ata_port *ap)
++{
++	void __iomem *mmio = ap->ioaddr.bmdma_addr;
++
++	if (!mmio)
++		return;
++
++	iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
++}
++
++/**
++ *	ata_sff_tf_load - send taskfile registers to host controller
+  *	@ap: Port to which output is sent
+  *	@tf: ATA taskfile register set
+  *
+@@ -75,8 +462,7 @@ u8 ata_irq_on(struct ata_port *ap)
+  *	LOCKING:
+  *	Inherited from caller.
+  */
+-
+-void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
++void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+@@ -126,26 +512,7 @@ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ }
+ 
+ /**
+- *	ata_exec_command - issue ATA command to host controller
+- *	@ap: port to which command is being issued
+- *	@tf: ATA taskfile register set
+- *
+- *	Issues ATA command, with proper synchronization with interrupt
+- *	handler / other threads.
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- */
+-void ata_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);
+-	ata_pause(ap);
+-}
+-
+-/**
+- *	ata_tf_read - input device's ATA taskfile shadow registers
++ *	ata_sff_tf_read - input device's ATA taskfile shadow registers
+  *	@ap: Port from which input is read
+  *	@tf: ATA taskfile register set for storing input
+  *
+@@ -157,11 +524,11 @@ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+  *	LOCKING:
+  *	Inherited from caller.
+  */
+-void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
++void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ {
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 
+-	tf->command = ata_check_status(ap);
++	tf->command = ata_sff_check_status(ap);
+ 	tf->feature = ioread8(ioaddr->error_addr);
+ 	tf->nsect = ioread8(ioaddr->nsect_addr);
+ 	tf->lbal = ioread8(ioaddr->lbal_addr);
+@@ -185,165 +552,1028 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ }
+ 
+ /**
+- *	ata_check_status - Read device status reg & clear interrupt
+- *	@ap: port where the device is
++ *	ata_sff_exec_command - issue ATA command to host controller
++ *	@ap: port to which command is being issued
++ *	@tf: ATA taskfile register set
+  *
+- *	Reads ATA taskfile status register for currently-selected device
+- *	and return its value. This also clears pending interrupts
+- *      from this device
++ *	Issues ATA command, with proper synchronization with interrupt
++ *	handler / other threads.
+  *
+  *	LOCKING:
+- *	Inherited from caller.
++ *	spin_lock_irqsave(host lock)
+  */
+-u8 ata_check_status(struct ata_port *ap)
++void ata_sff_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+-	return ioread8(ap->ioaddr.status_addr);
++	DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
++
++	iowrite8(tf->command, ap->ioaddr.command_addr);
++	ata_sff_pause(ap);
+ }
+ 
+ /**
+- *	ata_altstatus - Read device alternate status reg
+- *	@ap: port where the device is
++ *	ata_tf_to_host - issue ATA taskfile to host controller
++ *	@ap: port to which command is being issued
++ *	@tf: ATA taskfile register set
+  *
+- *	Reads ATA taskfile alternate status register for
+- *	currently-selected device and return its value.
++ *	Issues ATA taskfile register set to ATA host controller,
++ *	with proper synchronization with interrupt handler and
++ *	other threads.
+  *
+- *	Note: may NOT be used as the check_altstatus() entry in
+- *	ata_port_operations.
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ */
++static inline void ata_tf_to_host(struct ata_port *ap,
++				  const struct ata_taskfile *tf)
++{
++	ap->ops->sff_tf_load(ap, tf);
++	ap->ops->sff_exec_command(ap, tf);
++}
++
++/**
++ *	ata_sff_data_xfer - Transfer data by PIO
++ *	@dev: device to target
++ *	@buf: data buffer
++ *	@buflen: buffer length
++ *	@rw: read/write
++ *
++ *	Transfer data from/to the device data register by PIO.
+  *
+  *	LOCKING:
+  *	Inherited from caller.
++ *
++ *	RETURNS:
++ *	Bytes consumed.
+  */
+-u8 ata_altstatus(struct ata_port *ap)
++unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
++			       unsigned int buflen, int rw)
+ {
+-	if (ap->ops->check_altstatus)
+-		return ap->ops->check_altstatus(ap);
++	struct ata_port *ap = dev->link->ap;
++	void __iomem *data_addr = ap->ioaddr.data_addr;
++	unsigned int words = buflen >> 1;
+ 
+-	return ioread8(ap->ioaddr.altstatus_addr);
++	/* Transfer multiple of 2 bytes */
++	if (rw == READ)
++		ioread16_rep(data_addr, buf, words);
++	else
++		iowrite16_rep(data_addr, buf, words);
++
++	/* Transfer trailing 1 byte, if any. */
++	if (unlikely(buflen & 0x01)) {
++		__le16 align_buf[1] = { 0 };
++		unsigned char *trailing_buf = buf + buflen - 1;
++
++		if (rw == READ) {
++			align_buf[0] = cpu_to_le16(ioread16(data_addr));
++			memcpy(trailing_buf, align_buf, 1);
++		} else {
++			memcpy(align_buf, trailing_buf, 1);
++			iowrite16(le16_to_cpu(align_buf[0]), data_addr);
++		}
++		words++;
++	}
++
++	return words << 1;
+ }
+ 
+ /**
+- *	ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+- *	@qc: Info associated with this ATA transaction.
++ *	ata_sff_data_xfer_noirq - Transfer data by PIO
++ *	@dev: device to target
++ *	@buf: data buffer
++ *	@buflen: buffer length
++ *	@rw: read/write
++ *
++ *	Transfer data from/to the device data register by PIO. Do the
++ *	transfer with interrupts disabled.
+  *
+  *	LOCKING:
+- *	spin_lock_irqsave(host lock)
++ *	Inherited from caller.
++ *
++ *	RETURNS:
++ *	Bytes consumed.
+  */
+-void ata_bmdma_setup(struct ata_queued_cmd *qc)
++unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
++				     unsigned int buflen, int rw)
++{
++	unsigned long flags;
++	unsigned int consumed;
++
++	local_irq_save(flags);
++	consumed = ata_sff_data_xfer(dev, buf, buflen, rw);
++	local_irq_restore(flags);
++
++	return consumed;
++}
++
++/**
++ *	ata_pio_sector - Transfer a sector of data.
++ *	@qc: Command on going
++ *
++ *	Transfer qc->sect_size bytes of data from/to the ATA device.
++ *
++ *	LOCKING:
++ *	Inherited from caller.
++ */
++static void ata_pio_sector(struct ata_queued_cmd *qc)
+ {
++	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+ 	struct ata_port *ap = qc->ap;
+-	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+-	u8 dmactl;
++	struct page *page;
++	unsigned int offset;
++	unsigned char *buf;
+ 
+-	/* load PRD table addr. */
+-	mb();	/* make sure PRD table writes are visible to controller */
+-	iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
++	if (qc->curbytes == qc->nbytes - qc->sect_size)
++		ap->hsm_task_state = HSM_ST_LAST;
+ 
+-	/* specify data direction, triple-check start bit is clear */
+-	dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+-	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+-	if (!rw)
+-		dmactl |= ATA_DMA_WR;
+-	iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++	page = sg_page(qc->cursg);
++	offset = qc->cursg->offset + qc->cursg_ofs;
+ 
+-	/* issue r/w command */
+-	ap->ops->exec_command(ap, &qc->tf);
++	/* get the current page and offset */
++	page = nth_page(page, (offset >> PAGE_SHIFT));
++	offset %= PAGE_SIZE;
++
++	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
++
++	if (PageHighMem(page)) {
++		unsigned long flags;
++
++		/* FIXME: use a bounce buffer */
++		local_irq_save(flags);
++		buf = kmap_atomic(page, KM_IRQ0);
++
++		/* do the actual data transfer */
++		ap->ops->sff_data_xfer(qc->dev, buf + offset, qc->sect_size,
++				       do_write);
++
++		kunmap_atomic(buf, KM_IRQ0);
++		local_irq_restore(flags);
++	} else {
++		buf = page_address(page);
++		ap->ops->sff_data_xfer(qc->dev, buf + offset, qc->sect_size,
++				       do_write);
++	}
++
++	qc->curbytes += qc->sect_size;
++	qc->cursg_ofs += qc->sect_size;
++
++	if (qc->cursg_ofs == qc->cursg->length) {
++		qc->cursg = sg_next(qc->cursg);
++		qc->cursg_ofs = 0;
++	}
+ }
+ 
+ /**
+- *	ata_bmdma_start - Start a PCI IDE BMDMA transaction
+- *	@qc: Info associated with this ATA transaction.
++ *	ata_pio_sectors - Transfer one or many sectors.
++ *	@qc: Command on going
++ *
++ *	Transfer one or many sectors of data from/to the
++ *	ATA device for the DRQ request.
+  *
+  *	LOCKING:
+- *	spin_lock_irqsave(host lock)
++ *	Inherited from caller.
+  */
+-void ata_bmdma_start(struct ata_queued_cmd *qc)
++static void ata_pio_sectors(struct ata_queued_cmd *qc)
++{
++	if (is_multi_taskfile(&qc->tf)) {
++		/* READ/WRITE MULTIPLE */
++		unsigned int nsect;
++
++		WARN_ON(qc->dev->multi_count == 0);
++
++		nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
++			    qc->dev->multi_count);
++		while (nsect--)
++			ata_pio_sector(qc);
++	} else
++		ata_pio_sector(qc);
++
++	ata_sff_altstatus(qc->ap); /* flush */
++}
++
++/**
++ *	atapi_send_cdb - Write CDB bytes to hardware
++ *	@ap: Port to which ATAPI device is attached.
++ *	@qc: Taskfile currently active
++ *
++ *	When device has indicated its readiness to accept
++ *	a CDB, this function is called.  Send the CDB.
++ *
++ *	LOCKING:
++ *	caller.
++ */
++static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
++{
++	/* send SCSI cdb */
++	DPRINTK("send cdb\n");
++	WARN_ON(qc->dev->cdb_len < 12);
++
++	ap->ops->sff_data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
++	ata_sff_altstatus(ap); /* flush */
++
++	switch (qc->tf.protocol) {
++	case ATAPI_PROT_PIO:
++		ap->hsm_task_state = HSM_ST;
++		break;
++	case ATAPI_PROT_NODATA:
++		ap->hsm_task_state = HSM_ST_LAST;
++		break;
++	case ATAPI_PROT_DMA:
++		ap->hsm_task_state = HSM_ST_LAST;
++		/* initiate bmdma */
++		ap->ops->bmdma_start(qc);
++		break;
++	}
++}
++
++/**
++ *	__atapi_pio_bytes - Transfer data from/to the ATAPI device.
++ *	@qc: Command on going
++ *	@bytes: number of bytes
++ *
++ *	Transfer Transfer data from/to the ATAPI device.
++ *
++ *	LOCKING:
++ *	Inherited from caller.
++ *
++ */
++static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
+ {
++	int rw = (qc->tf.flags & ATA_TFLAG_WRITE) ? WRITE : READ;
+ 	struct ata_port *ap = qc->ap;
+-	u8 dmactl;
++	struct ata_device *dev = qc->dev;
++	struct ata_eh_info *ehi = &dev->link->eh_info;
++	struct scatterlist *sg;
++	struct page *page;
++	unsigned char *buf;
++	unsigned int offset, count, consumed;
++
++next_sg:
++	sg = qc->cursg;
++	if (unlikely(!sg)) {
++		ata_ehi_push_desc(ehi, "unexpected or too much trailing data "
++				  "buf=%u cur=%u bytes=%u",
++				  qc->nbytes, qc->curbytes, bytes);
++		return -1;
++	}
+ 
+-	/* start host DMA transaction */
+-	dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+-	iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++	page = sg_page(sg);
++	offset = sg->offset + qc->cursg_ofs;
+ 
+-	/* Strictly, one may wish to issue an ioread8() here, to
+-	 * flush the mmio write.  However, control also passes
+-	 * to the hardware at this point, and it will interrupt
+-	 * us when we are to resume control.  So, in effect,
+-	 * we don't care when the mmio write flushes.
+-	 * Further, a read of the DMA status register _immediately_
+-	 * following the write may not be what certain flaky hardware
+-	 * is expected, so I think it is best to not add a readb()
+-	 * without first all the MMIO ATA cards/mobos.
+-	 * Or maybe I'm just being paranoid.
+-	 *
+-	 * FIXME: The posting of this write means I/O starts are
+-	 * unneccessarily delayed for MMIO
++	/* get the current page and offset */
++	page = nth_page(page, (offset >> PAGE_SHIFT));
++	offset %= PAGE_SIZE;
++
++	/* don't overrun current sg */
++	count = min(sg->length - qc->cursg_ofs, bytes);
++
++	/* don't cross page boundaries */
++	count = min(count, (unsigned int)PAGE_SIZE - offset);
++
++	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
++
++	if (PageHighMem(page)) {
++		unsigned long flags;
++
++		/* FIXME: use bounce buffer */
++		local_irq_save(flags);
++		buf = kmap_atomic(page, KM_IRQ0);
++
++		/* do the actual data transfer */
++		consumed = ap->ops->sff_data_xfer(dev,  buf + offset, count, rw);
++
++		kunmap_atomic(buf, KM_IRQ0);
++		local_irq_restore(flags);
++	} else {
++		buf = page_address(page);
++		consumed = ap->ops->sff_data_xfer(dev,  buf + offset, count, rw);
++	}
++
++	bytes -= min(bytes, consumed);
++	qc->curbytes += count;
++	qc->cursg_ofs += count;
++
++	if (qc->cursg_ofs == sg->length) {
++		qc->cursg = sg_next(qc->cursg);
++		qc->cursg_ofs = 0;
++	}
++
++	/* consumed can be larger than count only for the last transfer */
++	WARN_ON(qc->cursg && count != consumed);
++
++	if (bytes)
++		goto next_sg;
++	return 0;
++}
++
++/**
++ *	atapi_pio_bytes - Transfer data from/to the ATAPI device.
++ *	@qc: Command on going
++ *
++ *	Transfer Transfer data from/to the ATAPI device.
++ *
++ *	LOCKING:
++ *	Inherited from caller.
++ */
++static void atapi_pio_bytes(struct ata_queued_cmd *qc)
++{
++	struct ata_port *ap = qc->ap;
++	struct ata_device *dev = qc->dev;
++	struct ata_eh_info *ehi = &dev->link->eh_info;
++	unsigned int ireason, bc_lo, bc_hi, bytes;
++	int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
++
++	/* Abuse qc->result_tf for temp storage of intermediate TF
++	 * here to save some kernel stack usage.
++	 * For normal completion, qc->result_tf is not relevant. For
++	 * error, qc->result_tf is later overwritten by ata_qc_complete().
++	 * So, the correctness of qc->result_tf is not affected.
+ 	 */
++	ap->ops->sff_tf_read(ap, &qc->result_tf);
++	ireason = qc->result_tf.nsect;
++	bc_lo = qc->result_tf.lbam;
++	bc_hi = qc->result_tf.lbah;
++	bytes = (bc_hi << 8) | bc_lo;
++
++	/* shall be cleared to zero, indicating xfer of data */
++	if (unlikely(ireason & (1 << 0)))
++		goto atapi_check;
++
++	/* make sure transfer direction matches expected */
++	i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
++	if (unlikely(do_write != i_write))
++		goto atapi_check;
++
++	if (unlikely(!bytes))
++		goto atapi_check;
++
++	VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
++
++	if (unlikely(__atapi_pio_bytes(qc, bytes)))
++		goto err_out;
++	ata_sff_altstatus(ap); /* flush */
++
++	return;
++
++ atapi_check:
++	ata_ehi_push_desc(ehi, "ATAPI check failed (ireason=0x%x bytes=%u)",
++			  ireason, bytes);
++ err_out:
++	qc->err_mask |= AC_ERR_HSM;
++	ap->hsm_task_state = HSM_ST_ERR;
+ }
+ 
+ /**
+- *	ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+- *	@ap: Port associated with this ATA transaction.
++ *	ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue.
++ *	@ap: the target ata_port
++ *	@qc: qc on going
+  *
+- *	Clear interrupt and error flags in DMA status register.
++ *	RETURNS:
++ *	1 if ok in workqueue, 0 otherwise.
++ */
++static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
++{
++	if (qc->tf.flags & ATA_TFLAG_POLLING)
++		return 1;
++
++	if (ap->hsm_task_state == HSM_ST_FIRST) {
++		if (qc->tf.protocol == ATA_PROT_PIO &&
++		    (qc->tf.flags & ATA_TFLAG_WRITE))
++		    return 1;
++
++		if (ata_is_atapi(qc->tf.protocol) &&
++		    !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
++			return 1;
++	}
++
++	return 0;
++}
++
++/**
++ *	ata_hsm_qc_complete - finish a qc running on standard HSM
++ *	@qc: Command to complete
++ *	@in_wq: 1 if called from workqueue, 0 otherwise
+  *
+- *	May be used as the irq_clear() entry in ata_port_operations.
++ *	Finish @qc which is running on standard HSM.
+  *
+  *	LOCKING:
+- *	spin_lock_irqsave(host lock)
++ *	If @in_wq is zero, spin_lock_irqsave(host lock).
++ *	Otherwise, none on entry and grabs host lock.
+  */
+-void ata_bmdma_irq_clear(struct ata_port *ap)
++static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ {
+-	void __iomem *mmio = ap->ioaddr.bmdma_addr;
++	struct ata_port *ap = qc->ap;
++	unsigned long flags;
+ 
+-	if (!mmio)
+-		return;
++	if (ap->ops->error_handler) {
++		if (in_wq) {
++			spin_lock_irqsave(ap->lock, flags);
++
++			/* EH might have kicked in while host lock is
++			 * released.
++			 */
++			qc = ata_qc_from_tag(ap, qc->tag);
++			if (qc) {
++				if (likely(!(qc->err_mask & AC_ERR_HSM))) {
++					ap->ops->sff_irq_on(ap);
++					ata_qc_complete(qc);
++				} else
++					ata_port_freeze(ap);
++			}
++
++			spin_unlock_irqrestore(ap->lock, flags);
++		} else {
++			if (likely(!(qc->err_mask & AC_ERR_HSM)))
++				ata_qc_complete(qc);
++			else
++				ata_port_freeze(ap);
++		}
++	} else {
++		if (in_wq) {
++			spin_lock_irqsave(ap->lock, flags);
++			ap->ops->sff_irq_on(ap);
++			ata_qc_complete(qc);
++			spin_unlock_irqrestore(ap->lock, flags);
++		} else
++			ata_qc_complete(qc);
++	}
++}
+ 
+-	iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
++/**
++ *	ata_sff_hsm_move - move the HSM to the next state.
++ *	@ap: the target ata_port
++ *	@qc: qc on going
++ *	@status: current device status
++ *	@in_wq: 1 if called from workqueue, 0 otherwise
++ *
++ *	RETURNS:
++ *	1 when poll next status needed, 0 otherwise.
++ */
++int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
++		     u8 status, int in_wq)
++{
++	unsigned long flags = 0;
++	int poll_next;
++
++	WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
++
++	/* Make sure ata_sff_qc_issue() does not throw things
++	 * like DMA polling into the workqueue. Notice that
++	 * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
++	 */
++	WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
++
++fsm_start:
++	DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
++		ap->print_id, qc->tf.protocol, ap->hsm_task_state, status);
++
++	switch (ap->hsm_task_state) {
++	case HSM_ST_FIRST:
++		/* Send first data block or PACKET CDB */
++
++		/* If polling, we will stay in the work queue after
++		 * sending the data. Otherwise, interrupt handler
++		 * takes over after sending the data.
++		 */
++		poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
++
++		/* check device status */
++		if (unlikely((status & ATA_DRQ) == 0)) {
++			/* handle BSY=0, DRQ=0 as error */
++			if (likely(status & (ATA_ERR | ATA_DF)))
++				/* device stops HSM for abort/error */
++				qc->err_mask |= AC_ERR_DEV;
++			else
++				/* HSM violation. Let EH handle this */
++				qc->err_mask |= AC_ERR_HSM;
++
++			ap->hsm_task_state = HSM_ST_ERR;
++			goto fsm_start;
++		}
++
++		/* Device should not ask for data transfer (DRQ=1)
++		 * when it finds something wrong.
++		 * We ignore DRQ here and stop the HSM by
++		 * changing hsm_task_state to HSM_ST_ERR and
++		 * let the EH abort the command or reset the device.
++		 */
++		if (unlikely(status & (ATA_ERR | ATA_DF))) {
++			/* Some ATAPI tape drives forget to clear the ERR bit
++			 * when doing the next command (mostly request sense).
++			 * We ignore ERR here to workaround and proceed sending
++			 * the CDB.
++			 */
++			if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
++				ata_port_printk(ap, KERN_WARNING,
++						"DRQ=1 with device error, "
++						"dev_stat 0x%X\n", status);
++				qc->err_mask |= AC_ERR_HSM;
++				ap->hsm_task_state = HSM_ST_ERR;
++				goto fsm_start;
++			}
++		}
++
++		/* Send the CDB (atapi) or the first data block (ata pio out).
++		 * During the state transition, interrupt handler shouldn't
++		 * be invoked before the data transfer is complete and
++		 * hsm_task_state is changed. Hence, the following locking.
++		 */
++		if (in_wq)
++			spin_lock_irqsave(ap->lock, flags);
++
++		if (qc->tf.protocol == ATA_PROT_PIO) {
++			/* PIO data out protocol.
++			 * send first data block.
++			 */
++
++			/* ata_pio_sectors() might change the state
++			 * to HSM_ST_LAST. so, the state is changed here
++			 * before ata_pio_sectors().
++			 */
++			ap->hsm_task_state = HSM_ST;
++			ata_pio_sectors(qc);
++		} else
++			/* send CDB */
++			atapi_send_cdb(ap, qc);
++
++		if (in_wq)
++			spin_unlock_irqrestore(ap->lock, flags);
++
++		/* if polling, ata_pio_task() handles the rest.
++		 * otherwise, interrupt handler takes over from here.
++		 */
++		break;
++
++	case HSM_ST:
++		/* complete command or read/write the data register */
++		if (qc->tf.protocol == ATAPI_PROT_PIO) {
++			/* ATAPI PIO protocol */
++			if ((status & ATA_DRQ) == 0) {
++				/* No more data to transfer or device error.
++				 * Device error will be tagged in HSM_ST_LAST.
++				 */
++				ap->hsm_task_state = HSM_ST_LAST;
++				goto fsm_start;
++			}
++
++			/* Device should not ask for data transfer (DRQ=1)
++			 * when it finds something wrong.
++			 * We ignore DRQ here and stop the HSM by
++			 * changing hsm_task_state to HSM_ST_ERR and
++			 * let the EH abort the command or reset the device.
++			 */
++			if (unlikely(status & (ATA_ERR | ATA_DF))) {
++				ata_port_printk(ap, KERN_WARNING, "DRQ=1 with "
++						"device error, dev_stat 0x%X\n",
++						status);
++				qc->err_mask |= AC_ERR_HSM;
++				ap->hsm_task_state = HSM_ST_ERR;
++				goto fsm_start;
++			}
++
++			atapi_pio_bytes(qc);
++
++			if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
++				/* bad ireason reported by device */
++				goto fsm_start;
++
++		} else {
++			/* ATA PIO protocol */
++			if (unlikely((status & ATA_DRQ) == 0)) {
++				/* handle BSY=0, DRQ=0 as error */
++				if (likely(status & (ATA_ERR | ATA_DF)))
++					/* device stops HSM for abort/error */
++					qc->err_mask |= AC_ERR_DEV;
++				else
++					/* HSM violation. Let EH handle this.
++					 * Phantom devices also trigger this
++					 * condition.  Mark hint.
++					 */
++					qc->err_mask |= AC_ERR_HSM |
++							AC_ERR_NODEV_HINT;
++
++				ap->hsm_task_state = HSM_ST_ERR;
++				goto fsm_start;
++			}
++
++			/* For PIO reads, some devices may ask for
++			 * data transfer (DRQ=1) alone with ERR=1.
++			 * We respect DRQ here and transfer one
++			 * block of junk data before changing the
++			 * hsm_task_state to HSM_ST_ERR.
++			 *
++			 * For PIO writes, ERR=1 DRQ=1 doesn't make
++			 * sense since the data block has been
++			 * transferred to the device.
++			 */
++			if (unlikely(status & (ATA_ERR | ATA_DF))) {
++				/* data might be corrputed */
++				qc->err_mask |= AC_ERR_DEV;
++
++				if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
++					ata_pio_sectors(qc);
++					status = ata_wait_idle(ap);
++				}
++
++				if (status & (ATA_BUSY | ATA_DRQ))
++					qc->err_mask |= AC_ERR_HSM;
++
++				/* ata_pio_sectors() might change the
++				 * state to HSM_ST_LAST. so, the state
++				 * is changed after ata_pio_sectors().
++				 */
++				ap->hsm_task_state = HSM_ST_ERR;
++				goto fsm_start;
++			}
++
++			ata_pio_sectors(qc);
++
++			if (ap->hsm_task_state == HSM_ST_LAST &&
++			    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
++				/* all data read */
++				status = ata_wait_idle(ap);
++				goto fsm_start;
++			}
++		}
++
++		poll_next = 1;
++		break;
++
++	case HSM_ST_LAST:
++		if (unlikely(!ata_ok(status))) {
++			qc->err_mask |= __ac_err_mask(status);
++			ap->hsm_task_state = HSM_ST_ERR;
++			goto fsm_start;
++		}
++
++		/* no more data to transfer */
++		DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
++			ap->print_id, qc->dev->devno, status);
++
++		WARN_ON(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM));
++
++		ap->hsm_task_state = HSM_ST_IDLE;
++
++		/* complete taskfile transaction */
++		ata_hsm_qc_complete(qc, in_wq);
++
++		poll_next = 0;
++		break;
++
++	case HSM_ST_ERR:
++		/* make sure qc->err_mask is available to
++		 * know what's wrong and recover
++		 */
++		WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
++
++		ap->hsm_task_state = HSM_ST_IDLE;
++
++		/* complete taskfile transaction */
++		ata_hsm_qc_complete(qc, in_wq);
++
++		poll_next = 0;
++		break;
++	default:
++		poll_next = 0;
++		BUG();
++	}
++
++	return poll_next;
++}
++
++void ata_pio_task(struct work_struct *work)
++{
++	struct ata_port *ap =
++		container_of(work, struct ata_port, port_task.work);
++	struct ata_queued_cmd *qc = ap->port_task_data;
++	u8 status;
++	int poll_next;
++
++fsm_start:
++	WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
++
++	/*
++	 * This is purely heuristic.  This is a fast path.
++	 * Sometimes when we enter, BSY will be cleared in
++	 * a chk-status or two.  If not, the drive is probably seeking
++	 * or something.  Snooze for a couple msecs, then
++	 * chk-status again.  If still busy, queue delayed work.
++	 */
++	status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
++	if (status & ATA_BUSY) {
++		msleep(2);
++		status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
++		if (status & ATA_BUSY) {
++			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
++			return;
++		}
++	}
++
++	/* move the HSM */
++	poll_next = ata_sff_hsm_move(ap, qc, status, 1);
++
++	/* another command or interrupt handler
++	 * may be running at this point.
++	 */
++	if (poll_next)
++		goto fsm_start;
+ }
+ 
+ /**
+- *	ata_bmdma_status - Read PCI IDE BMDMA status
+- *	@ap: Port associated with this ATA transaction.
++ *	ata_sff_qc_issue - issue taskfile to device in proto-dependent manner
++ *	@qc: command to issue to device
+  *
+- *	Read and return BMDMA status register.
++ *	Using various libata functions and hooks, this function
++ *	starts an ATA command.  ATA commands are grouped into
++ *	classes called "protocols", and issuing each type of protocol
++ *	is slightly different.
+  *
+- *	May be used as the bmdma_status() entry in ata_port_operations.
++ *	May be used as the qc_issue() entry in ata_port_operations.
+  *
+  *	LOCKING:
+  *	spin_lock_irqsave(host lock)
++ *
++ *	RETURNS:
++ *	Zero on success, AC_ERR_* mask on failure
+  */
+-u8 ata_bmdma_status(struct ata_port *ap)
++unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
+ {
+-	return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
++	struct ata_port *ap = qc->ap;
++
++	/* Use polling pio if the LLD doesn't handle
++	 * interrupt driven pio and atapi CDB interrupt.
++	 */
++	if (ap->flags & ATA_FLAG_PIO_POLLING) {
++		switch (qc->tf.protocol) {
++		case ATA_PROT_PIO:
++		case ATA_PROT_NODATA:
++		case ATAPI_PROT_PIO:
++		case ATAPI_PROT_NODATA:
++			qc->tf.flags |= ATA_TFLAG_POLLING;
++			break;
++		case ATAPI_PROT_DMA:
++			if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
++				/* see ata_dma_blacklisted() */
++				BUG();
++			break;
++		default:
++			break;
++		}
++	}
++
++	/* select the device */
++	ata_dev_select(ap, qc->dev->devno, 1, 0);
++
++	/* start the command */
++	switch (qc->tf.protocol) {
++	case ATA_PROT_NODATA:
++		if (qc->tf.flags & ATA_TFLAG_POLLING)
++			ata_qc_set_polling(qc);
++
++		ata_tf_to_host(ap, &qc->tf);
++		ap->hsm_task_state = HSM_ST_LAST;
++
++		if (qc->tf.flags & ATA_TFLAG_POLLING)
++			ata_pio_queue_task(ap, qc, 0);
++
++		break;
++
++	case ATA_PROT_DMA:
++		WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
++
++		ap->ops->sff_tf_load(ap, &qc->tf);  /* load tf registers */
++		ap->ops->bmdma_setup(qc);	    /* set up bmdma */
++		ap->ops->bmdma_start(qc);	    /* initiate bmdma */
++		ap->hsm_task_state = HSM_ST_LAST;
++		break;
++
++	case ATA_PROT_PIO:
++		if (qc->tf.flags & ATA_TFLAG_POLLING)
++			ata_qc_set_polling(qc);
++
++		ata_tf_to_host(ap, &qc->tf);
++
++		if (qc->tf.flags & ATA_TFLAG_WRITE) {
++			/* PIO data out protocol */
++			ap->hsm_task_state = HSM_ST_FIRST;
++			ata_pio_queue_task(ap, qc, 0);
++
++			/* always send first data block using
++			 * the ata_pio_task() codepath.
++			 */
++		} else {
++			/* PIO data in protocol */
++			ap->hsm_task_state = HSM_ST;
++
++			if (qc->tf.flags & ATA_TFLAG_POLLING)
++				ata_pio_queue_task(ap, qc, 0);
++
++			/* if polling, ata_pio_task() handles the rest.
++			 * otherwise, interrupt handler takes over from here.
++			 */
++		}
++
++		break;
++
++	case ATAPI_PROT_PIO:
++	case ATAPI_PROT_NODATA:
++		if (qc->tf.flags & ATA_TFLAG_POLLING)
++			ata_qc_set_polling(qc);
++
++		ata_tf_to_host(ap, &qc->tf);
++
++		ap->hsm_task_state = HSM_ST_FIRST;
++
++		/* send cdb by polling if no cdb interrupt */
++		if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
++		    (qc->tf.flags & ATA_TFLAG_POLLING))
++			ata_pio_queue_task(ap, qc, 0);
++		break;
++
++	case ATAPI_PROT_DMA:
++		WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
++
++		ap->ops->sff_tf_load(ap, &qc->tf);  /* load tf registers */
++		ap->ops->bmdma_setup(qc);	    /* set up bmdma */
++		ap->hsm_task_state = HSM_ST_FIRST;
++
++		/* send cdb by polling if no cdb interrupt */
++		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
++			ata_pio_queue_task(ap, qc, 0);
++		break;
++
++	default:
++		WARN_ON(1);
++		return AC_ERR_SYSTEM;
++	}
++
++	return 0;
+ }
+ 
+ /**
+- *	ata_bmdma_stop - Stop PCI IDE BMDMA transfer
+- *	@qc: Command we are ending DMA for
++ *	ata_sff_qc_fill_rtf - fill result TF using ->sff_tf_read
++ *	@qc: qc to fill result TF for
+  *
+- *	Clears the ATA_DMA_START flag in the dma control register
++ *	@qc is finished and result TF needs to be filled.  Fill it
++ *	using ->sff_tf_read.
+  *
+- *	May be used as the bmdma_stop() entry in ata_port_operations.
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ *
++ *	RETURNS:
++ *	true indicating that result TF is successfully filled.
++ */
++bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc)
++{
++	qc->ap->ops->sff_tf_read(qc->ap, &qc->result_tf);
++	return true;
++}
++
++/**
++ *	ata_sff_host_intr - Handle host interrupt for given (port, task)
++ *	@ap: Port on which interrupt arrived (possibly...)
++ *	@qc: Taskfile currently active in engine
++ *
++ *	Handle host interrupt for given queued command.  Currently,
++ *	only DMA interrupts are handled.  All other commands are
++ *	handled via polling with interrupts disabled (nIEN bit).
+  *
+  *	LOCKING:
+  *	spin_lock_irqsave(host lock)
++ *
++ *	RETURNS:
++ *	One if interrupt was handled, zero if not (shared irq).
+  */
+-void ata_bmdma_stop(struct ata_queued_cmd *qc)
++inline unsigned int ata_sff_host_intr(struct ata_port *ap,
++				      struct ata_queued_cmd *qc)
+ {
+-	struct ata_port *ap = qc->ap;
+-	void __iomem *mmio = ap->ioaddr.bmdma_addr;
++	struct ata_eh_info *ehi = &ap->link.eh_info;
++	u8 status, host_stat = 0;
+ 
+-	/* clear start/stop bit */
+-	iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
+-		 mmio + ATA_DMA_CMD);
++	VPRINTK("ata%u: protocol %d task_state %d\n",
++		ap->print_id, qc->tf.protocol, ap->hsm_task_state);
+ 
+-	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+-	ata_altstatus(ap);        /* dummy read */
++	/* Check whether we are expecting interrupt in this state */
++	switch (ap->hsm_task_state) {
++	case HSM_ST_FIRST:
++		/* Some pre-ATAPI-4 devices assert INTRQ
++		 * at this state when ready to receive CDB.
++		 */
++
++		/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
++		 * The flag was turned on only for atapi devices.  No
++		 * need to check ata_is_atapi(qc->tf.protocol) again.
++		 */
++		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
++			goto idle_irq;
++		break;
++	case HSM_ST_LAST:
++		if (qc->tf.protocol == ATA_PROT_DMA ||
++		    qc->tf.protocol == ATAPI_PROT_DMA) {
++			/* check status of DMA engine */
++			host_stat = ap->ops->bmdma_status(ap);
++			VPRINTK("ata%u: host_stat 0x%X\n",
++				ap->print_id, host_stat);
++
++			/* if it's not our irq... */
++			if (!(host_stat & ATA_DMA_INTR))
++				goto idle_irq;
++
++			/* before we do anything else, clear DMA-Start bit */
++			ap->ops->bmdma_stop(qc);
++
++			if (unlikely(host_stat & ATA_DMA_ERR)) {
++				/* error when transfering data to/from memory */
++				qc->err_mask |= AC_ERR_HOST_BUS;
++				ap->hsm_task_state = HSM_ST_ERR;
++			}
++		}
++		break;
++	case HSM_ST:
++		break;
++	default:
++		goto idle_irq;
++	}
++
++	/* check altstatus */
++	status = ata_sff_altstatus(ap);
++	if (status & ATA_BUSY)
++		goto idle_irq;
++
++	/* check main status, clearing INTRQ */
++	status = ap->ops->sff_check_status(ap);
++	if (unlikely(status & ATA_BUSY))
++		goto idle_irq;
++
++	/* ack bmdma irq events */
++	ap->ops->sff_irq_clear(ap);
++
++	ata_sff_hsm_move(ap, qc, status, 0);
++
++	if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
++				       qc->tf.protocol == ATAPI_PROT_DMA))
++		ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
++
++	return 1;	/* irq handled */
++
++idle_irq:
++	ap->stats.idle_irq++;
++
++#ifdef ATA_IRQ_TRAP
++	if ((ap->stats.idle_irq % 1000) == 0) {
++		ap->ops->sff_check_status(ap);
++		ap->ops->sff_irq_clear(ap);
++		ata_port_printk(ap, KERN_WARNING, "irq trap\n");
++		return 1;
++	}
++#endif
++	return 0;	/* irq not handled */
++}
++
++/**
++ *	ata_sff_interrupt - Default ATA host interrupt handler
++ *	@irq: irq line (unused)
++ *	@dev_instance: pointer to our ata_host information structure
++ *
++ *	Default interrupt handler for PCI IDE devices.  Calls
++ *	ata_sff_host_intr() for each port that is not disabled.
++ *
++ *	LOCKING:
++ *	Obtains host lock during operation.
++ *
++ *	RETURNS:
++ *	IRQ_NONE or IRQ_HANDLED.
++ */
++irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
++{
++	struct ata_host *host = dev_instance;
++	unsigned int i;
++	unsigned int handled = 0;
++	unsigned long flags;
++
++	/* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
++	spin_lock_irqsave(&host->lock, flags);
++
++	for (i = 0; i < host->n_ports; i++) {
++		struct ata_port *ap;
++
++		ap = host->ports[i];
++		if (ap &&
++		    !(ap->flags & ATA_FLAG_DISABLED)) {
++			struct ata_queued_cmd *qc;
++
++			qc = ata_qc_from_tag(ap, ap->link.active_tag);
++			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
++			    (qc->flags & ATA_QCFLAG_ACTIVE))
++				handled |= ata_sff_host_intr(ap, qc);
++		}
++	}
++
++	spin_unlock_irqrestore(&host->lock, flags);
++
++	return IRQ_RETVAL(handled);
+ }
+ 
+ /**
+- *	ata_bmdma_freeze - Freeze BMDMA controller port
++ *	ata_sff_freeze - Freeze SFF controller port
+  *	@ap: port to freeze
+  *
+  *	Freeze BMDMA controller port.
+@@ -351,7 +1581,7 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc)
+  *	LOCKING:
+  *	Inherited from caller.
+  */
+-void ata_bmdma_freeze(struct ata_port *ap)
++void ata_sff_freeze(struct ata_port *ap)
+ {
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 
+@@ -365,51 +1595,412 @@ void ata_bmdma_freeze(struct ata_port *ap)
+ 	 * ATA_NIEN manipulation.  Also, many controllers fail to mask
+ 	 * previously pending IRQ on ATA_NIEN assertion.  Clear it.
+ 	 */
+-	ata_chk_status(ap);
++	ap->ops->sff_check_status(ap);
+ 
+-	ap->ops->irq_clear(ap);
++	ap->ops->sff_irq_clear(ap);
+ }
+ 
+ /**
+- *	ata_bmdma_thaw - Thaw BMDMA controller port
++ *	ata_sff_thaw - Thaw SFF controller port
+  *	@ap: port to thaw
+  *
+- *	Thaw BMDMA controller port.
++ *	Thaw SFF controller port.
+  *
+  *	LOCKING:
+  *	Inherited from caller.
+  */
+-void ata_bmdma_thaw(struct ata_port *ap)
++void ata_sff_thaw(struct ata_port *ap)
+ {
+ 	/* clear & re-enable interrupts */
+-	ata_chk_status(ap);
+-	ap->ops->irq_clear(ap);
+-	ap->ops->irq_on(ap);
++	ap->ops->sff_check_status(ap);
++	ap->ops->sff_irq_clear(ap);
++	ap->ops->sff_irq_on(ap);
++}
++
++/**
++ *	ata_sff_prereset - prepare SFF link for reset
++ *	@link: SFF link to be reset
++ *	@deadline: deadline jiffies for the operation
++ *
++ *	SFF link @link is about to be reset.  Initialize it.  It first
++ *	calls ata_std_prereset() and wait for !BSY if the port is
++ *	being softreset.
++ *
++ *	LOCKING:
++ *	Kernel thread context (may sleep)
++ *
++ *	RETURNS:
++ *	0 on success, -errno otherwise.
++ */
++int ata_sff_prereset(struct ata_link *link, unsigned long deadline)
++{
++	struct ata_eh_context *ehc = &link->eh_context;
++	int rc;
++
++	rc = ata_std_prereset(link, deadline);
++	if (rc)
++		return rc;
++
++	/* if we're about to do hardreset, nothing more to do */
++	if (ehc->i.action & ATA_EH_HARDRESET)
++		return 0;
++
++	/* wait for !BSY if we don't know that no device is attached */
++	if (!ata_link_offline(link)) {
++		rc = ata_sff_wait_ready(link, deadline);
++		if (rc && rc != -ENODEV) {
++			ata_link_printk(link, KERN_WARNING, "device not ready "
++					"(errno=%d), forcing hardreset\n", rc);
++			ehc->i.action |= ATA_EH_HARDRESET;
++		}
++	}
++
++	return 0;
++}
++
++/**
++ *	ata_devchk - PATA device presence detection
++ *	@ap: ATA channel to examine
++ *	@device: Device to examine (starting at zero)
++ *
++ *	This technique was originally described in
++ *	Hale Landis's ATADRVR (www.ata-atapi.com), and
++ *	later found its way into the ATA/ATAPI spec.
++ *
++ *	Write a pattern to the ATA shadow registers,
++ *	and if a device is present, it will respond by
++ *	correctly storing and echoing back the
++ *	ATA shadow register contents.
++ *
++ *	LOCKING:
++ *	caller.
++ */
++static unsigned int ata_devchk(struct ata_port *ap, unsigned int device)
++{
++	struct ata_ioports *ioaddr = &ap->ioaddr;
++	u8 nsect, lbal;
++
++	ap->ops->sff_dev_select(ap, device);
++
++	iowrite8(0x55, ioaddr->nsect_addr);
++	iowrite8(0xaa, ioaddr->lbal_addr);
++
++	iowrite8(0xaa, ioaddr->nsect_addr);
++	iowrite8(0x55, ioaddr->lbal_addr);
++
++	iowrite8(0x55, ioaddr->nsect_addr);
++	iowrite8(0xaa, ioaddr->lbal_addr);
++
++	nsect = ioread8(ioaddr->nsect_addr);
++	lbal = ioread8(ioaddr->lbal_addr);
++
++	if ((nsect == 0x55) && (lbal == 0xaa))
++		return 1;	/* we found a device */
++
++	return 0;		/* nothing found */
++}
++
++/**
++ *	ata_sff_dev_classify - Parse returned ATA device signature
++ *	@dev: ATA device to classify (starting at zero)
++ *	@present: device seems present
++ *	@r_err: Value of error register on completion
++ *
++ *	After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
++ *	an ATA/ATAPI-defined set of values is placed in the ATA
++ *	shadow registers, indicating the results of device detection
++ *	and diagnostics.
++ *
++ *	Select the ATA device, and read the values from the ATA shadow
++ *	registers.  Then parse according to the Error register value,
++ *	and the spec-defined values examined by ata_dev_classify().
++ *
++ *	LOCKING:
++ *	caller.
++ *
++ *	RETURNS:
++ *	Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
++ */
++unsigned int ata_sff_dev_classify(struct ata_device *dev, int present,
++				  u8 *r_err)
++{
++	struct ata_port *ap = dev->link->ap;
++	struct ata_taskfile tf;
++	unsigned int class;
++	u8 err;
++
++	ap->ops->sff_dev_select(ap, dev->devno);
++
++	memset(&tf, 0, sizeof(tf));
++
++	ap->ops->sff_tf_read(ap, &tf);
++	err = tf.feature;
++	if (r_err)
++		*r_err = err;
++
++	/* see if device passed diags: continue and warn later */
++	if (err == 0)
++		/* diagnostic fail : do nothing _YET_ */
++		dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
++	else if (err == 1)
++		/* do nothing */ ;
++	else if ((dev->devno == 0) && (err == 0x81))
++		/* do nothing */ ;
++	else
++		return ATA_DEV_NONE;
++
++	/* determine if device is ATA or ATAPI */
++	class = ata_dev_classify(&tf);
++
++	if (class == ATA_DEV_UNKNOWN) {
++		/* If the device failed diagnostic, it's likely to
++		 * have reported incorrect device signature too.
++		 * Assume ATA device if the device seems present but
++		 * device signature is invalid with diagnostic
++		 * failure.
++		 */
++		if (present && (dev->horkage & ATA_HORKAGE_DIAGNOSTIC))
++			class = ATA_DEV_ATA;
++		else
++			class = ATA_DEV_NONE;
++	} else if ((class == ATA_DEV_ATA) &&
++		   (ap->ops->sff_check_status(ap) == 0))
++		class = ATA_DEV_NONE;
++
++	return class;
++}
++
++/**
++ *	ata_sff_wait_after_reset - wait for devices to become ready after reset
++ *	@link: SFF link which is just reset
++ *	@devmask: mask of present devices
++ *	@deadline: deadline jiffies for the operation
++ *
++ *	Wait devices attached to SFF @link to become ready after
++ *	reset.  It contains preceding 150ms wait to avoid accessing TF
++ *	status register too early.
++ *
++ *	LOCKING:
++ *	Kernel thread context (may sleep).
++ *
++ *	RETURNS:
++ *	0 on success, -ENODEV if some or all of devices in @devmask
++ *	don't seem to exist.  -errno on other errors.
++ */
++int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
++			     unsigned long deadline)
++{
++	struct ata_port *ap = link->ap;
++	struct ata_ioports *ioaddr = &ap->ioaddr;
++	unsigned int dev0 = devmask & (1 << 0);
++	unsigned int dev1 = devmask & (1 << 1);
++	int rc, ret = 0;
++
++	msleep(ATA_WAIT_AFTER_RESET_MSECS);
++
++	/* always check readiness of the master device */
++	rc = ata_sff_wait_ready(link, deadline);
++	/* -ENODEV means the odd clown forgot the D7 pulldown resistor
++	 * and TF status is 0xff, bail out on it too.
++	 */
++	if (rc)
++		return rc;
++
++	/* if device 1 was found in ata_devchk, wait for register
++	 * access briefly, then wait for BSY to clear.
++	 */
++	if (dev1) {
++		int i;
++
++		ap->ops->sff_dev_select(ap, 1);
++
++		/* Wait for register access.  Some ATAPI devices fail
++		 * to set nsect/lbal after reset, so don't waste too
++		 * much time on it.  We're gonna wait for !BSY anyway.
++		 */
++		for (i = 0; i < 2; i++) {
++			u8 nsect, lbal;
++
++			nsect = ioread8(ioaddr->nsect_addr);
++			lbal = ioread8(ioaddr->lbal_addr);
++			if ((nsect == 1) && (lbal == 1))
++				break;
++			msleep(50);	/* give drive a breather */
++		}
++
++		rc = ata_sff_wait_ready(link, deadline);
++		if (rc) {
++			if (rc != -ENODEV)
++				return rc;
++			ret = rc;
++		}
++	}
++
++	/* is all this really necessary? */
++	ap->ops->sff_dev_select(ap, 0);
++	if (dev1)
++		ap->ops->sff_dev_select(ap, 1);
++	if (dev0)
++		ap->ops->sff_dev_select(ap, 0);
++
++	return ret;
++}
++
++static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
++			     unsigned long deadline)
++{
++	struct ata_ioports *ioaddr = &ap->ioaddr;
++
++	DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
++
++	/* software reset.  causes dev0 to be selected */
++	iowrite8(ap->ctl, ioaddr->ctl_addr);
++	udelay(20);	/* FIXME: flush */
++	iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
++	udelay(20);	/* FIXME: flush */
++	iowrite8(ap->ctl, ioaddr->ctl_addr);
++
++	/* wait the port to become ready */
++	return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
++}
++
++/**
++ *	ata_sff_softreset - reset host port via ATA SRST
++ *	@link: ATA link to reset
++ *	@classes: resulting classes of attached devices
++ *	@deadline: deadline jiffies for the operation
++ *
++ *	Reset host port using ATA SRST.
++ *
++ *	LOCKING:
++ *	Kernel thread context (may sleep)
++ *
++ *	RETURNS:
++ *	0 on success, -errno otherwise.
++ */
++int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
++		      unsigned long deadline)
++{
++	struct ata_port *ap = link->ap;
++	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
++	unsigned int devmask = 0;
++	int rc;
++	u8 err;
++
++	DPRINTK("ENTER\n");
++
++	/* determine if device 0/1 are present */
++	if (ata_devchk(ap, 0))
++		devmask |= (1 << 0);
++	if (slave_possible && ata_devchk(ap, 1))
++		devmask |= (1 << 1);
++
++	/* select device 0 again */
++	ap->ops->sff_dev_select(ap, 0);
++
++	/* issue bus reset */
++	DPRINTK("about to softreset, devmask=%x\n", devmask);
++	rc = ata_bus_softreset(ap, devmask, deadline);
++	/* if link is occupied, -ENODEV too is an error */
++	if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
++		ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
++		return rc;
++	}
++
++	/* determine by signature whether we have ATA or ATAPI devices */
++	classes[0] = ata_sff_dev_classify(&link->device[0],
++					  devmask & (1 << 0), &err);
++	if (slave_possible && err != 0x81)
++		classes[1] = ata_sff_dev_classify(&link->device[1],
++						  devmask & (1 << 1), &err);
++
++	DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
++	return 0;
++}
++
++/**
++ *	sata_sff_hardreset - reset host port via SATA phy reset
++ *	@link: link to reset
++ *	@class: resulting class of attached device
++ *	@deadline: deadline jiffies for the operation
++ *
++ *	SATA phy-reset host port using DET bits of SControl register,
++ *	wait for !BSY and classify the attached device.
++ *
++ *	LOCKING:
++ *	Kernel thread context (may sleep)
++ *
++ *	RETURNS:
++ *	0 on success, -errno otherwise.
++ */
++int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
++		       unsigned long deadline)
++{
++	struct ata_eh_context *ehc = &link->eh_context;
++	const unsigned long *timing = sata_ehc_deb_timing(ehc);
++	bool online;
++	int rc;
++
++	rc = sata_link_hardreset(link, timing, deadline, &online,
++				 ata_sff_check_ready);
++	if (online)
++		*class = ata_sff_dev_classify(link->device, 1, NULL);
++
++	DPRINTK("EXIT, class=%u\n", *class);
++	return rc;
+ }
+ 
+ /**
+- *	ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
++ *	ata_sff_postreset - SFF postreset callback
++ *	@link: the target SFF ata_link
++ *	@classes: classes of attached devices
++ *
++ *	This function is invoked after a successful reset.  It first
++ *	calls ata_std_postreset() and performs SFF specific postreset
++ *	processing.
++ *
++ *	LOCKING:
++ *	Kernel thread context (may sleep)
++ */
++void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
++{
++	struct ata_port *ap = link->ap;
++
++	ata_std_postreset(link, classes);
++
++	/* is double-select really necessary? */
++	if (classes[0] != ATA_DEV_NONE)
++		ap->ops->sff_dev_select(ap, 1);
++	if (classes[1] != ATA_DEV_NONE)
++		ap->ops->sff_dev_select(ap, 0);
++
++	/* bail out if no device is present */
++	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
++		DPRINTK("EXIT, no device\n");
++		return;
++	}
++
++	/* set up device control */
++	if (ap->ioaddr.ctl_addr)
++		iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
++}
++
++/**
++ *	ata_sff_error_handler - Stock error handler for BMDMA controller
+  *	@ap: port to handle error for
+- *	@prereset: prereset method (can be NULL)
+- *	@softreset: softreset method (can be NULL)
+- *	@hardreset: hardreset method (can be NULL)
+- *	@postreset: postreset method (can be NULL)
+  *
+- *	Handle error for ATA BMDMA controller.  It can handle both
++ *	Stock error handler for SFF controller.  It can handle both
+  *	PATA and SATA controllers.  Many controllers should be able to
+  *	use this EH as-is or with some added handling before and
+  *	after.
+  *
+- *	This function is intended to be used for constructing
+- *	->error_handler callback by low level drivers.
+- *
+  *	LOCKING:
+  *	Kernel thread context (may sleep)
+  */
+-void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+-			ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+-			ata_postreset_fn_t postreset)
++void ata_sff_error_handler(struct ata_port *ap)
+ {
++	ata_reset_fn_t softreset = ap->ops->softreset;
++	ata_reset_fn_t hardreset = ap->ops->hardreset;
+ 	struct ata_queued_cmd *qc;
+ 	unsigned long flags;
+ 	int thaw = 0;
+@@ -423,7 +2014,8 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 
+ 	ap->hsm_task_state = HSM_ST_IDLE;
+ 
+-	if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
++	if (ap->ioaddr.bmdma_addr &&
++	    qc && (qc->tf.protocol == ATA_PROT_DMA ||
+ 		   qc->tf.protocol == ATAPI_PROT_DMA)) {
+ 		u8 host_stat;
+ 
+@@ -442,9 +2034,9 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 		ap->ops->bmdma_stop(qc);
+ 	}
+ 
+-	ata_altstatus(ap);
+-	ata_chk_status(ap);
+-	ap->ops->irq_clear(ap);
++	ata_sff_altstatus(ap);
++	ap->ops->sff_check_status(ap);
++	ap->ops->sff_irq_clear(ap);
+ 
+ 	spin_unlock_irqrestore(ap->lock, flags);
+ 
+@@ -452,40 +2044,27 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 		ata_eh_thaw_port(ap);
+ 
+ 	/* PIO and DMA engines have been stopped, perform recovery */
+-	ata_do_eh(ap, prereset, softreset, hardreset, postreset);
+-}
+-
+-/**
+- *	ata_bmdma_error_handler - Stock error handler for BMDMA controller
+- *	@ap: port to handle error for
+- *
+- *	Stock error handler for BMDMA controller.
+- *
+- *	LOCKING:
+- *	Kernel thread context (may sleep)
+- */
+-void ata_bmdma_error_handler(struct ata_port *ap)
+-{
+-	ata_reset_fn_t softreset = NULL, hardreset = NULL;
+ 
+-	if (ap->ioaddr.ctl_addr)
+-		softreset = ata_std_softreset;
+-	if (sata_scr_valid(&ap->link))
+-		hardreset = sata_std_hardreset;
++	/* Ignore ata_sff_softreset if ctl isn't accessible and
++	 * built-in hardresets if SCR access isn't available.
++	 */
++	if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr)
++		softreset = NULL;
++	if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
++		hardreset = NULL;
+ 
+-	ata_bmdma_drive_eh(ap, ata_std_prereset, softreset, hardreset,
+-			   ata_std_postreset);
++	ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
++		  ap->ops->postreset);
+ }
+ 
+ /**
+- *	ata_bmdma_post_internal_cmd - Stock post_internal_cmd for
+- *				      BMDMA controller
++ *	ata_sff_post_internal_cmd - Stock post_internal_cmd for SFF controller
+  *	@qc: internal command to clean up
+  *
+  *	LOCKING:
+  *	Kernel thread context (may sleep)
+  */
+-void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
++void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
+ {
+ 	if (qc->ap->ioaddr.bmdma_addr)
+ 		ata_bmdma_stop(qc);
+@@ -504,7 +2083,6 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
+  *	LOCKING:
+  *	Inherited from caller.
+  */
+-
+ int ata_sff_port_start(struct ata_port *ap)
+ {
+ 	if (ap->ioaddr.bmdma_addr)
+@@ -512,24 +2090,262 @@ int ata_sff_port_start(struct ata_port *ap)
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_PCI
++/**
++ *	ata_sff_std_ports - initialize ioaddr with standard port offsets.
++ *	@ioaddr: IO address structure to be initialized
++ *
++ *	Utility function which initializes data_addr, error_addr,
++ *	feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
++ *	device_addr, status_addr, and command_addr to standard offsets
++ *	relative to cmd_addr.
++ *
++ *	Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
++ */
++void ata_sff_std_ports(struct ata_ioports *ioaddr)
++{
++	ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
++	ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR;
++	ioaddr->feature_addr = ioaddr->cmd_addr + ATA_REG_FEATURE;
++	ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT;
++	ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL;
++	ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM;
++	ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH;
++	ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE;
++	ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS;
++	ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
++}
+ 
+-static int ata_resources_present(struct pci_dev *pdev, int port)
++unsigned long ata_bmdma_mode_filter(struct ata_device *adev,
++				    unsigned long xfer_mask)
+ {
+-	int i;
++	/* Filter out DMA modes if the device has been configured by
++	   the BIOS as PIO only */
+ 
+-	/* Check the PCI resources for this channel are enabled */
+-	port = port * 2;
+-	for (i = 0; i < 2; i ++) {
+-		if (pci_resource_start(pdev, port + i) == 0 ||
+-		    pci_resource_len(pdev, port + i) == 0)
+-			return 0;
++	if (adev->link->ap->ioaddr.bmdma_addr == NULL)
++		xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
++	return xfer_mask;
++}
++
++/**
++ *	ata_bmdma_setup - Set up PCI IDE BMDMA transaction
++ *	@qc: Info associated with this ATA transaction.
++ *
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ */
++void ata_bmdma_setup(struct ata_queued_cmd *qc)
++{
++	struct ata_port *ap = qc->ap;
++	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
++	u8 dmactl;
++
++	/* load PRD table addr. */
++	mb();	/* make sure PRD table writes are visible to controller */
++	iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
++
++	/* specify data direction, triple-check start bit is clear */
++	dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
++	if (!rw)
++		dmactl |= ATA_DMA_WR;
++	iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++
++	/* issue r/w command */
++	ap->ops->sff_exec_command(ap, &qc->tf);
++}
++
++/**
++ *	ata_bmdma_start - Start a PCI IDE BMDMA transaction
++ *	@qc: Info associated with this ATA transaction.
++ *
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ */
++void ata_bmdma_start(struct ata_queued_cmd *qc)
++{
++	struct ata_port *ap = qc->ap;
++	u8 dmactl;
++
++	/* start host DMA transaction */
++	dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++	iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++
++	/* Strictly, one may wish to issue an ioread8() here, to
++	 * flush the mmio write.  However, control also passes
++	 * to the hardware at this point, and it will interrupt
++	 * us when we are to resume control.  So, in effect,
++	 * we don't care when the mmio write flushes.
++	 * Further, a read of the DMA status register _immediately_
++	 * following the write may not be what certain flaky hardware
++	 * is expected, so I think it is best to not add a readb()
++	 * without first all the MMIO ATA cards/mobos.
++	 * Or maybe I'm just being paranoid.
++	 *
++	 * FIXME: The posting of this write means I/O starts are
++	 * unneccessarily delayed for MMIO
++	 */
++}
++
++/**
++ *	ata_bmdma_stop - Stop PCI IDE BMDMA transfer
++ *	@qc: Command we are ending DMA for
++ *
++ *	Clears the ATA_DMA_START flag in the dma control register
++ *
++ *	May be used as the bmdma_stop() entry in ata_port_operations.
++ *
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ */
++void ata_bmdma_stop(struct ata_queued_cmd *qc)
++{
++	struct ata_port *ap = qc->ap;
++	void __iomem *mmio = ap->ioaddr.bmdma_addr;
++
++	/* clear start/stop bit */
++	iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
++		 mmio + ATA_DMA_CMD);
++
++	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
++	ata_sff_altstatus(ap);        /* dummy read */
++}
++
++/**
++ *	ata_bmdma_status - Read PCI IDE BMDMA status
++ *	@ap: Port associated with this ATA transaction.
++ *
++ *	Read and return BMDMA status register.
++ *
++ *	May be used as the bmdma_status() entry in ata_port_operations.
++ *
++ *	LOCKING:
++ *	spin_lock_irqsave(host lock)
++ */
++u8 ata_bmdma_status(struct ata_port *ap)
++{
++	return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
++}
++
++/**
++ *	ata_bus_reset - reset host port and associated ATA channel
++ *	@ap: port to reset
++ *
++ *	This is typically the first time we actually start issuing
++ *	commands to the ATA channel.  We wait for BSY to clear, then
++ *	issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
++ *	result.  Determine what devices, if any, are on the channel
++ *	by looking at the device 0/1 error register.  Look at the signature
++ *	stored in each device's taskfile registers, to determine if
++ *	the device is ATA or ATAPI.
++ *
++ *	LOCKING:
++ *	PCI/etc. bus probe sem.
++ *	Obtains host lock.
++ *
++ *	SIDE EFFECTS:
++ *	Sets ATA_FLAG_DISABLED if bus reset fails.
++ *
++ *	DEPRECATED:
++ *	This function is only for drivers which still use old EH and
++ *	will be removed soon.
++ */
++void ata_bus_reset(struct ata_port *ap)
++{
++	struct ata_device *device = ap->link.device;
++	struct ata_ioports *ioaddr = &ap->ioaddr;
++	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
++	u8 err;
++	unsigned int dev0, dev1 = 0, devmask = 0;
++	int rc;
++
++	DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
++
++	/* determine if device 0/1 are present */
++	if (ap->flags & ATA_FLAG_SATA_RESET)
++		dev0 = 1;
++	else {
++		dev0 = ata_devchk(ap, 0);
++		if (slave_possible)
++			dev1 = ata_devchk(ap, 1);
+ 	}
+-	return 1;
++
++	if (dev0)
++		devmask |= (1 << 0);
++	if (dev1)
++		devmask |= (1 << 1);
++
++	/* select device 0 again */
++	ap->ops->sff_dev_select(ap, 0);
++
++	/* issue bus reset */
++	if (ap->flags & ATA_FLAG_SRST) {
++		rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
++		if (rc && rc != -ENODEV)
++			goto err_out;
++	}
++
++	/*
++	 * determine by signature whether we have ATA or ATAPI devices
++	 */
++	device[0].class = ata_sff_dev_classify(&device[0], dev0, &err);
++	if ((slave_possible) && (err != 0x81))
++		device[1].class = ata_sff_dev_classify(&device[1], dev1, &err);
++
++	/* is double-select really necessary? */
++	if (device[1].class != ATA_DEV_NONE)
++		ap->ops->sff_dev_select(ap, 1);
++	if (device[0].class != ATA_DEV_NONE)
++		ap->ops->sff_dev_select(ap, 0);
++
++	/* if no devices were detected, disable this port */
++	if ((device[0].class == ATA_DEV_NONE) &&
++	    (device[1].class == ATA_DEV_NONE))
++		goto err_out;
++
++	if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
++		/* set up device control for ATA_FLAG_SATA_RESET */
++		iowrite8(ap->ctl, ioaddr->ctl_addr);
++	}
++
++	DPRINTK("EXIT\n");
++	return;
++
++err_out:
++	ata_port_printk(ap, KERN_ERR, "disabling port\n");
++	ata_port_disable(ap);
++
++	DPRINTK("EXIT\n");
+ }
+ 
++#ifdef CONFIG_PCI
++
+ /**
+- *	ata_pci_init_bmdma - acquire PCI BMDMA resources and init ATA host
++ *	ata_pci_bmdma_clear_simplex -	attempt to kick device out of simplex
++ *	@pdev: PCI device
++ *
++ *	Some PCI ATA devices report simplex mode but in fact can be told to
++ *	enter non simplex mode. This implements the necessary logic to
++ *	perform the task on such devices. Calling it on other devices will
++ *	have -undefined- behaviour.
++ */
++int ata_pci_bmdma_clear_simplex(struct pci_dev *pdev)
++{
++	unsigned long bmdma = pci_resource_start(pdev, 4);
++	u8 simplex;
++
++	if (bmdma == 0)
++		return -ENOENT;
++
++	simplex = inb(bmdma + 0x02);
++	outb(simplex & 0x60, bmdma + 0x02);
++	simplex = inb(bmdma + 0x02);
++	if (simplex & 0x80)
++		return -EOPNOTSUPP;
++	return 0;
++}
++
++/**
++ *	ata_pci_bmdma_init - acquire PCI BMDMA resources and init ATA host
+  *	@host: target ATA host
+  *
+  *	Acquire PCI BMDMA resources and initialize @host accordingly.
+@@ -540,7 +2356,7 @@ static int ata_resources_present(struct pci_dev *pdev, int port)
+  *	RETURNS:
+  *	0 on success, -errno otherwise.
+  */
+-int ata_pci_init_bmdma(struct ata_host *host)
++int ata_pci_bmdma_init(struct ata_host *host)
+ {
+ 	struct device *gdev = host->dev;
+ 	struct pci_dev *pdev = to_pci_dev(gdev);
+@@ -585,8 +2401,22 @@ int ata_pci_init_bmdma(struct ata_host *host)
+ 	return 0;
+ }
+ 
++static int ata_resources_present(struct pci_dev *pdev, int port)
++{
++	int i;
++
++	/* Check the PCI resources for this channel are enabled */
++	port = port * 2;
++	for (i = 0; i < 2; i ++) {
++		if (pci_resource_start(pdev, port + i) == 0 ||
++		    pci_resource_len(pdev, port + i) == 0)
++			return 0;
++	}
++	return 1;
++}
++
+ /**
+- *	ata_pci_init_sff_host - acquire native PCI ATA resources and init host
++ *	ata_pci_sff_init_host - acquire native PCI ATA resources and init host
+  *	@host: target ATA host
+  *
+  *	Acquire native PCI ATA resources for @host and initialize the
+@@ -604,7 +2434,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
+  *	0 if at least one port is initialized, -ENODEV if no port is
+  *	available.
+  */
+-int ata_pci_init_sff_host(struct ata_host *host)
++int ata_pci_sff_init_host(struct ata_host *host)
+ {
+ 	struct device *gdev = host->dev;
+ 	struct pci_dev *pdev = to_pci_dev(gdev);
+@@ -646,7 +2476,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
+ 		ap->ioaddr.altstatus_addr =
+ 		ap->ioaddr.ctl_addr = (void __iomem *)
+ 			((unsigned long)iomap[base + 1] | ATA_PCI_CTL_OFS);
+-		ata_std_ports(&ap->ioaddr);
++		ata_sff_std_ports(&ap->ioaddr);
+ 
+ 		ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
+ 			(unsigned long long)pci_resource_start(pdev, base),
+@@ -664,7 +2494,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
+ }
+ 
+ /**
+- *	ata_pci_prepare_sff_host - helper to prepare native PCI ATA host
++ *	ata_pci_sff_prepare_host - helper to prepare native PCI ATA host
+  *	@pdev: target PCI device
+  *	@ppi: array of port_info, must be enough for two ports
+  *	@r_host: out argument for the initialized ATA host
+@@ -678,7 +2508,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
+  *	RETURNS:
+  *	0 on success, -errno otherwise.
+  */
+-int ata_pci_prepare_sff_host(struct pci_dev *pdev,
++int ata_pci_sff_prepare_host(struct pci_dev *pdev,
+ 			     const struct ata_port_info * const * ppi,
+ 			     struct ata_host **r_host)
+ {
+@@ -696,12 +2526,12 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ 		goto err_out;
+ 	}
+ 
+-	rc = ata_pci_init_sff_host(host);
++	rc = ata_pci_sff_init_host(host);
+ 	if (rc)
+ 		goto err_out;
+ 
+ 	/* init DMA related stuff */
+-	rc = ata_pci_init_bmdma(host);
++	rc = ata_pci_bmdma_init(host);
+ 	if (rc)
+ 		goto err_bmdma;
+ 
+@@ -722,7 +2552,7 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ }
+ 
+ /**
+- *	ata_pci_activate_sff_host - start SFF host, request IRQ and register it
++ *	ata_pci_sff_activate_host - start SFF host, request IRQ and register it
+  *	@host: target SFF ATA host
+  *	@irq_handler: irq_handler used when requesting IRQ(s)
+  *	@sht: scsi_host_template to use when registering the host
+@@ -737,7 +2567,7 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+  *	RETURNS:
+  *	0 on success, -errno otherwise.
+  */
+-int ata_pci_activate_sff_host(struct ata_host *host,
++int ata_pci_sff_activate_host(struct ata_host *host,
+ 			      irq_handler_t irq_handler,
+ 			      struct scsi_host_template *sht)
+ {
+@@ -815,9 +2645,11 @@ int ata_pci_activate_sff_host(struct ata_host *host,
+ }
+ 
+ /**
+- *	ata_pci_init_one - Initialize/register PCI IDE host controller
++ *	ata_pci_sff_init_one - Initialize/register PCI IDE host controller
+  *	@pdev: Controller to be initialized
+  *	@ppi: array of port_info, must be enough for two ports
++ *	@sht: scsi_host_template to use when registering the host
++ *	@host_priv: host private_data
+  *
+  *	This is a helper function which can be called from a driver's
+  *	xxx_init_one() probe function if the hardware uses traditional
+@@ -837,8 +2669,9 @@ int ata_pci_activate_sff_host(struct ata_host *host,
+  *	RETURNS:
+  *	Zero on success, negative on errno-based value on error.
+  */
+-int ata_pci_init_one(struct pci_dev *pdev,
+-		     const struct ata_port_info * const * ppi)
++int ata_pci_sff_init_one(struct pci_dev *pdev,
++			 const struct ata_port_info * const * ppi,
++			 struct scsi_host_template *sht, void *host_priv)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	const struct ata_port_info *pi = NULL;
+@@ -869,13 +2702,13 @@ int ata_pci_init_one(struct pci_dev *pdev,
+ 		goto out;
+ 
+ 	/* prepare and activate SFF host */
+-	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ 	if (rc)
+ 		goto out;
++	host->private_data = host_priv;
+ 
+ 	pci_set_master(pdev);
+-	rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler,
+-				       pi->sht);
++	rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
+  out:
+ 	if (rc == 0)
+ 		devres_remove_group(&pdev->dev, NULL);
+@@ -885,41 +2718,52 @@ int ata_pci_init_one(struct pci_dev *pdev,
+ 	return rc;
+ }
+ 
+-/**
+- *	ata_pci_clear_simplex	-	attempt to kick device out of simplex
+- *	@pdev: PCI device
+- *
+- *	Some PCI ATA devices report simplex mode but in fact can be told to
+- *	enter non simplex mode. This implements the necessary logic to
+- *	perform the task on such devices. Calling it on other devices will
+- *	have -undefined- behaviour.
+- */
+-
+-int ata_pci_clear_simplex(struct pci_dev *pdev)
+-{
+-	unsigned long bmdma = pci_resource_start(pdev, 4);
+-	u8 simplex;
+-
+-	if (bmdma == 0)
+-		return -ENOENT;
+-
+-	simplex = inb(bmdma + 0x02);
+-	outb(simplex & 0x60, bmdma + 0x02);
+-	simplex = inb(bmdma + 0x02);
+-	if (simplex & 0x80)
+-		return -EOPNOTSUPP;
+-	return 0;
+-}
+-
+-unsigned long ata_pci_default_filter(struct ata_device *adev, unsigned long xfer_mask)
+-{
+-	/* Filter out DMA modes if the device has been configured by
+-	   the BIOS as PIO only */
+-
+-	if (adev->link->ap->ioaddr.bmdma_addr == NULL)
+-		xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+-	return xfer_mask;
+-}
+-
+ #endif /* CONFIG_PCI */
+ 
++EXPORT_SYMBOL_GPL(ata_sff_port_ops);
++EXPORT_SYMBOL_GPL(ata_bmdma_port_ops);
++EXPORT_SYMBOL_GPL(ata_sff_qc_prep);
++EXPORT_SYMBOL_GPL(ata_sff_dumb_qc_prep);
++EXPORT_SYMBOL_GPL(ata_sff_dev_select);
++EXPORT_SYMBOL_GPL(ata_sff_check_status);
++EXPORT_SYMBOL_GPL(ata_sff_altstatus);
++EXPORT_SYMBOL_GPL(ata_sff_busy_sleep);
++EXPORT_SYMBOL_GPL(ata_sff_wait_ready);
++EXPORT_SYMBOL_GPL(ata_sff_tf_load);
++EXPORT_SYMBOL_GPL(ata_sff_tf_read);
++EXPORT_SYMBOL_GPL(ata_sff_exec_command);
++EXPORT_SYMBOL_GPL(ata_sff_data_xfer);
++EXPORT_SYMBOL_GPL(ata_sff_data_xfer_noirq);
++EXPORT_SYMBOL_GPL(ata_sff_irq_on);
++EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
++EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
++EXPORT_SYMBOL_GPL(ata_sff_qc_issue);
++EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
++EXPORT_SYMBOL_GPL(ata_sff_host_intr);
++EXPORT_SYMBOL_GPL(ata_sff_interrupt);
++EXPORT_SYMBOL_GPL(ata_sff_freeze);
++EXPORT_SYMBOL_GPL(ata_sff_thaw);
++EXPORT_SYMBOL_GPL(ata_sff_prereset);
++EXPORT_SYMBOL_GPL(ata_sff_dev_classify);
++EXPORT_SYMBOL_GPL(ata_sff_wait_after_reset);
++EXPORT_SYMBOL_GPL(ata_sff_softreset);
++EXPORT_SYMBOL_GPL(sata_sff_hardreset);
++EXPORT_SYMBOL_GPL(ata_sff_postreset);
++EXPORT_SYMBOL_GPL(ata_sff_error_handler);
++EXPORT_SYMBOL_GPL(ata_sff_post_internal_cmd);
++EXPORT_SYMBOL_GPL(ata_sff_port_start);
++EXPORT_SYMBOL_GPL(ata_sff_std_ports);
++EXPORT_SYMBOL_GPL(ata_bmdma_mode_filter);
++EXPORT_SYMBOL_GPL(ata_bmdma_setup);
++EXPORT_SYMBOL_GPL(ata_bmdma_start);
++EXPORT_SYMBOL_GPL(ata_bmdma_stop);
++EXPORT_SYMBOL_GPL(ata_bmdma_status);
++EXPORT_SYMBOL_GPL(ata_bus_reset);
++#ifdef CONFIG_PCI
++EXPORT_SYMBOL_GPL(ata_pci_bmdma_clear_simplex);
++EXPORT_SYMBOL_GPL(ata_pci_bmdma_init);
++EXPORT_SYMBOL_GPL(ata_pci_sff_init_host);
++EXPORT_SYMBOL_GPL(ata_pci_sff_prepare_host);
++EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
++EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
++#endif /* CONFIG_PCI */
+diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
+index aa884f7..ae2cfd9 100644
+--- a/drivers/ata/libata.h
++++ b/drivers/ata/libata.h
+@@ -38,6 +38,17 @@ struct ata_scsi_args {
+ 	void			(*done)(struct scsi_cmnd *);
+ };
+ 
++static inline int ata_is_builtin_hardreset(ata_reset_fn_t reset)
++{
++	if (reset == sata_std_hardreset)
++		return 1;
++#ifdef CONFIG_ATA_SFF
++	if (reset == sata_sff_hardreset)
++		return 1;
++#endif
++	return 0;
++}
++
+ /* libata-core.c */
+ enum {
+ 	/* flags for ata_dev_read_id() */
+@@ -61,12 +72,16 @@ extern int libata_fua;
+ extern int libata_noacpi;
+ extern int libata_allow_tpm;
+ extern void ata_force_cbl(struct ata_port *ap);
++extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
++extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
+ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
+ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
+ 			   u64 block, u32 n_block, unsigned int tf_flags,
+ 			   unsigned int tag);
+ extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
+ extern void ata_dev_disable(struct ata_device *dev);
++extern void ata_pio_queue_task(struct ata_port *ap, void *data,
++			       unsigned long delay);
+ extern void ata_port_flush_task(struct ata_port *ap);
+ extern unsigned ata_exec_internal(struct ata_device *dev,
+ 				  struct ata_taskfile *tf, const u8 *cdb,
+@@ -77,6 +92,8 @@ extern unsigned ata_exec_internal_sg(struct ata_device *dev,
+ 				     int dma_dir, struct scatterlist *sg,
+ 				     unsigned int n_elem, unsigned long timeout);
+ extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
++extern int ata_wait_ready(struct ata_link *link, unsigned long deadline,
++			  int (*check_ready)(struct ata_link *link));
+ extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+ 			   unsigned int flags, u16 *id);
+ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
+@@ -84,17 +101,13 @@ extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
+ 			      unsigned int readid_flags);
+ extern int ata_dev_configure(struct ata_device *dev);
+ extern int sata_down_spd_limit(struct ata_link *link);
+-extern int sata_set_spd_needed(struct ata_link *link);
+ extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
+ 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);
+ extern void __ata_qc_complete(struct ata_queued_cmd *qc);
+ extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
+-extern void ata_dev_select(struct ata_port *ap, unsigned int device,
+-                           unsigned int wait, unsigned int can_sleep);
+ extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
+-extern int ata_flush_cache(struct ata_device *dev);
+ extern void ata_dev_init(struct ata_device *dev);
+ extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp);
+ extern int sata_link_init_spd(struct ata_link *link);
+@@ -165,11 +178,6 @@ 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);
+ 
+-/* libata-pmp.c */
+-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_attach(struct ata_device *dev);
+-
+ /* libata-eh.c */
+ extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
+ extern void ata_scsi_error(struct Scsi_Host *host);
+@@ -193,8 +201,34 @@ extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 			  struct ata_link **r_failed_disk);
+ extern void ata_eh_finish(struct ata_port *ap);
+ 
++/* 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_attach(struct ata_device *dev);
++#else /* CONFIG_SATA_PMP */
++static inline int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val)
++{
++	return -EINVAL;
++}
++
++static inline int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
++{
++	return -EINVAL;
++}
++
++static inline int sata_pmp_attach(struct ata_device *dev)
++{
++	return -EINVAL;
++}
++#endif /* CONFIG_SATA_PMP */
++
+ /* libata-sff.c */
++#ifdef CONFIG_ATA_SFF
++extern void ata_dev_select(struct ata_port *ap, unsigned int device,
++                           unsigned int wait, unsigned int can_sleep);
+ extern u8 ata_irq_on(struct ata_port *ap);
+-
++extern void ata_pio_task(struct work_struct *work);
++#endif /* CONFIG_ATA_SFF */
+ 
+ #endif /* __LIBATA_H__ */
+diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
+index bdc3b9d..c5f91e6 100644
+--- a/drivers/ata/pata_acpi.c
++++ b/drivers/ata/pata_acpi.c
+@@ -47,7 +47,7 @@ static int pacpi_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (ap->acpi_handle == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0)
+ 		return -ENODEV;
+ 
+-	return ata_std_prereset(link, deadline);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -68,20 +68,6 @@ static int pacpi_cable_detect(struct ata_port *ap)
+ }
+ 
+ /**
+- *	pacpi_error_handler - Setup and error handler
+- *	@ap: Port to handle
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void pacpi_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, pacpi_pre_reset, ata_std_softreset, NULL,
+-			   ata_std_postreset);
+-}
+-
+-/**
+  *	pacpi_discover_modes	-	filter non ACPI modes
+  *	@adev: ATA device
+  *	@mask: proposed modes
+@@ -120,7 +106,7 @@ static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device
+ static unsigned long pacpi_mode_filter(struct ata_device *adev, unsigned long mask)
+ {
+ 	struct pata_acpi *acpi = adev->link->ap->private_data;
+-	return ata_pci_default_filter(adev, mask & acpi->mask[adev->devno]);
++	return ata_bmdma_mode_filter(adev, mask & acpi->mask[adev->devno]);
+ }
+ 
+ /**
+@@ -176,7 +162,7 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	pacpi_qc_issue_prot	-	command issue
++ *	pacpi_qc_issue	-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+@@ -184,14 +170,14 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+  *	neccessary.
+  */
+ 
+-static unsigned int pacpi_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+ 	struct pata_acpi *acpi = ap->private_data;
+ 
+ 	if (acpi->gtm.flags & 0x10)
+-		return ata_qc_issue_prot(qc);
++		return ata_sff_qc_issue(qc);
+ 
+ 	if (adev != acpi->last) {
+ 		pacpi_set_piomode(ap, adev);
+@@ -199,7 +185,7 @@ static unsigned int pacpi_qc_issue_prot(struct ata_queued_cmd *qc)
+ 			pacpi_set_dmamode(ap, adev);
+ 		acpi->last = adev;
+ 	}
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ /**
+@@ -232,57 +218,17 @@ static int pacpi_port_start(struct ata_port *ap)
+ }
+ 
+ static struct scsi_host_template pacpi_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	/* Use standard CHS mapping rules */
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations pacpi_ops = {
++static struct ata_port_operations pacpi_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.qc_issue		= pacpi_qc_issue,
++	.cable_detect		= pacpi_cable_detect,
++	.mode_filter		= pacpi_mode_filter,
+ 	.set_piomode		= pacpi_set_piomode,
+ 	.set_dmamode		= pacpi_set_dmamode,
+-	.mode_filter		= pacpi_mode_filter,
+-
+-	/* Task file is PCI ATA format, use helpers */
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= pacpi_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= pacpi_cable_detect,
+-
+-	/* BMDMA handling is PCI ATA format, use helpers */
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= pacpi_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	/* Timeout handling */
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	/* Generic PATA PCI ATA helpers */
++	.prereset		= pacpi_pre_reset,
+ 	.port_start		= pacpi_port_start,
+ };
+ 
+@@ -304,7 +250,6 @@ static const struct ata_port_operations pacpi_ops = {
+ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht		= &pacpi_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ 
+ 		.pio_mask	= 0x1f,
+@@ -314,7 +259,7 @@ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ 		.port_ops	= &pacpi_ops,
+ 	};
+ 	const struct ata_port_info *ppi[] = { &info, NULL };
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &pacpi_sht, NULL);
+ }
+ 
+ static const struct pci_device_id pacpi_pci_tbl[] = {
+diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
+index 511a830..fcabe46 100644
+--- a/drivers/ata/pata_ali.c
++++ b/drivers/ata/pata_ali.c
+@@ -121,7 +121,7 @@ static unsigned long ali_20_filter(struct ata_device *adev, unsigned long mask)
+ 	ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
+ 	if (strstr(model_num, "WDC"))
+ 		return mask &= ~ATA_MASK_UDMA;
+-	return ata_pci_default_filter(adev, mask);
++	return ata_bmdma_mode_filter(adev, mask);
+ }
+ 
+ /**
+@@ -339,21 +339,7 @@ static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
+ }
+ 
+ static struct scsi_host_template ali_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ /*
+@@ -361,29 +347,15 @@ static struct scsi_host_template ali_sht = {
+  */
+ 
+ static struct ata_port_operations ali_early_port_ops = {
+-	.set_piomode	= ali_set_piomode,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
+ 	.cable_detect	= ata_cable_40wire,
++	.set_piomode	= ali_set_piomode,
++};
+ 
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++static const struct ata_port_operations ali_dma_base_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.set_piomode	= ali_set_piomode,
++	.set_dmamode	= ali_set_dmamode,
+ };
+ 
+ /*
+@@ -391,115 +363,31 @@ static struct ata_port_operations ali_early_port_ops = {
+  *	detect
+  */
+ static struct ata_port_operations ali_20_port_ops = {
+-	.set_piomode	= ali_set_piomode,
+-	.set_dmamode	= ali_set_dmamode,
++	.inherits	= &ali_dma_base_ops,
++	.cable_detect	= ata_cable_40wire,
+ 	.mode_filter	= ali_20_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+ 	.check_atapi_dma = ali_check_atapi_dma,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+ 	.dev_config	= ali_lock_sectors,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+  *	Port operations for DMA capable ALi with cable detect
+  */
+ static struct ata_port_operations ali_c2_port_ops = {
+-	.set_piomode	= ali_set_piomode,
+-	.set_dmamode	= ali_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
++	.inherits	= &ali_dma_base_ops,
+ 	.check_atapi_dma = ali_check_atapi_dma,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-	.dev_config	= ali_lock_sectors,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ 	.cable_detect	= ali_c2_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.dev_config	= ali_lock_sectors,
+ };
+ 
+ /*
+  *	Port operations for DMA capable ALi with cable detect and LBA48
+  */
+ static struct ata_port_operations ali_c5_port_ops = {
+-	.set_piomode	= ali_set_piomode,
+-	.set_dmamode	= ali_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
++	.inherits	= &ali_dma_base_ops,
+ 	.check_atapi_dma = ali_check_atapi_dma,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+ 	.dev_config	= ali_warn_atapi_dma,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ 	.cable_detect	= ali_c2_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ 
+@@ -561,7 +449,7 @@ static void ali_init_chipset(struct pci_dev *pdev)
+ 	}
+ 	pci_dev_put(isa_bridge);
+ 	pci_dev_put(north);
+-	ata_pci_clear_simplex(pdev);
++	ata_pci_bmdma_clear_simplex(pdev);
+ }
+ /**
+  *	ali_init_one		-	discovery callback
+@@ -575,14 +463,12 @@ static void ali_init_chipset(struct pci_dev *pdev)
+ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info_early = {
+-		.sht = &ali_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.port_ops = &ali_early_port_ops
+ 	};
+ 	/* Revision 0x20 added DMA */
+ 	static const struct ata_port_info info_20 = {
+-		.sht = &ali_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -590,7 +476,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* Revision 0x20 with support logic added UDMA */
+ 	static const struct ata_port_info info_20_udma = {
+-		.sht = &ali_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -599,7 +484,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* Revision 0xC2 adds UDMA66 */
+ 	static const struct ata_port_info info_c2 = {
+-		.sht = &ali_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -608,7 +492,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* Revision 0xC3 is UDMA66 for now */
+ 	static const struct ata_port_info info_c3 = {
+-		.sht = &ali_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -617,7 +500,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* Revision 0xC4 is UDMA100 */
+ 	static const struct ata_port_info info_c4 = {
+-		.sht = &ali_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -626,7 +508,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* Revision 0xC5 is UDMA133 with LBA48 DMA */
+ 	static const struct ata_port_info info_c5 = {
+-		.sht = &ali_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -637,6 +518,11 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	const struct ata_port_info *ppi[] = { NULL, NULL };
+ 	u8 tmp;
+ 	struct pci_dev *isa_bridge;
++	int rc;
++
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
+ 
+ 	/*
+ 	 * The chipset revision selects the driver operations and
+@@ -666,14 +552,21 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	        	ppi[0] = &info_20_udma;
+ 		pci_dev_put(isa_bridge);
+ 	}
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL);
+ }
+ 
+ #ifdef CONFIG_PM
+ static int ali_reinit_one(struct pci_dev *pdev)
+ {
++	struct ata_host *host = dev_get_drvdata(&pdev->dev);
++	int rc;
++
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
+ 	ali_init_chipset(pdev);
+-	return ata_pci_device_resume(pdev);
++	ata_host_resume(host);
++	return 0;
+ }
+ #endif
+ 
+diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
+index 4b8d9b5..26665c3 100644
+--- a/drivers/ata/pata_amd.c
++++ b/drivers/ata/pata_amd.c
+@@ -56,7 +56,9 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
+ 	u8 t;
+ 
+ 	T = 1000000000 / amd_clock;
+-	UT = T / min_t(int, max_t(int, clock, 1), 2);
++	UT = T;
++	if (clock >= 2)
++		UT = T / 2;
+ 
+ 	if (ata_timing_compute(adev, speed, &at, T, UT) < 0) {
+ 		dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", speed);
+@@ -141,13 +143,7 @@ static int amd_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-static void amd_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, amd_pre_reset, ata_std_softreset, NULL,
+-			   ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ static int amd_cable_detect(struct ata_port *ap)
+@@ -297,14 +293,7 @@ static int nv_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-static void nv_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, nv_pre_reset,
+-			       ata_std_softreset, NULL,
+-			       ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -353,228 +342,66 @@ static void nv_host_stop(struct ata_host *host)
+ }
+ 
+ static struct scsi_host_template amd_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
++};
++
++static const struct ata_port_operations amd_base_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.prereset	= amd_pre_reset,
+ };
+ 
+ static struct ata_port_operations amd33_port_ops = {
++	.inherits	= &amd_base_port_ops,
++	.cable_detect	= ata_cable_40wire,
+ 	.set_piomode	= amd33_set_piomode,
+ 	.set_dmamode	= amd33_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= amd_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ static struct ata_port_operations amd66_port_ops = {
++	.inherits	= &amd_base_port_ops,
++	.cable_detect	= ata_cable_unknown,
+ 	.set_piomode	= amd66_set_piomode,
+ 	.set_dmamode	= amd66_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= amd_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_unknown,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ static struct ata_port_operations amd100_port_ops = {
++	.inherits	= &amd_base_port_ops,
++	.cable_detect	= ata_cable_unknown,
+ 	.set_piomode	= amd100_set_piomode,
+ 	.set_dmamode	= amd100_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= amd_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_unknown,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ static struct ata_port_operations amd133_port_ops = {
++	.inherits	= &amd_base_port_ops,
++	.cable_detect	= amd_cable_detect,
+ 	.set_piomode	= amd133_set_piomode,
+ 	.set_dmamode	= amd133_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= amd_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= amd_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
++};
+ 
+-	.port_start	= ata_sff_port_start,
++static const struct ata_port_operations nv_base_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.cable_detect	= ata_cable_ignore,
++	.mode_filter	= nv_mode_filter,
++	.prereset	= nv_pre_reset,
++	.host_stop	= nv_host_stop,
+ };
+ 
+ static struct ata_port_operations nv100_port_ops = {
++	.inherits	= &nv_base_port_ops,
+ 	.set_piomode	= nv100_set_piomode,
+ 	.set_dmamode	= nv100_set_dmamode,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= nv_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_ignore,
+-	.mode_filter	= nv_mode_filter,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+-	.host_stop	= nv_host_stop,
+ };
+ 
+ static struct ata_port_operations nv133_port_ops = {
++	.inherits	= &nv_base_port_ops,
+ 	.set_piomode	= nv133_set_piomode,
+ 	.set_dmamode	= nv133_set_dmamode,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= nv_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_ignore,
+-	.mode_filter	= nv_mode_filter,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+-	.host_stop	= nv_host_stop,
+ };
+ 
+ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info[10] = {
+ 		{	/* 0: AMD 7401 */
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,	/* No SWDMA */
+@@ -582,7 +409,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &amd33_port_ops
+ 		},
+ 		{	/* 1: Early AMD7409 - no swdma */
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -590,7 +416,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &amd66_port_ops
+ 		},
+ 		{	/* 2: AMD 7409, no swdma errata */
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -598,7 +423,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &amd66_port_ops
+ 		},
+ 		{	/* 3: AMD 7411 */
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -606,7 +430,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &amd100_port_ops
+ 		},
+ 		{	/* 4: AMD 7441 */
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -614,7 +437,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &amd100_port_ops
+ 		},
+ 		{	/* 5: AMD 8111*/
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -622,7 +444,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &amd133_port_ops
+ 		},
+ 		{	/* 6: AMD 8111 UDMA 100 (Serenade) */
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -630,7 +451,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &amd133_port_ops
+ 		},
+ 		{	/* 7: Nvidia Nforce */
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -638,7 +458,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &nv100_port_ops
+ 		},
+ 		{	/* 8: Nvidia Nforce2 and later */
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -646,7 +465,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &nv133_port_ops
+ 		},
+ 		{	/* 9: AMD CS5536 (Geode companion) */
+-			.sht = &amd_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -654,15 +472,20 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &amd100_port_ops
+ 		}
+ 	};
+-	struct ata_port_info pi;
+-	const struct ata_port_info *ppi[] = { &pi, NULL };
++	const struct ata_port_info *ppi[] = { NULL, NULL };
+ 	static int printed_version;
+ 	int type = id->driver_data;
++	void *hpriv = NULL;
+ 	u8 fifo;
++	int rc;
+ 
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ 
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
++
+ 	pci_read_config_byte(pdev, 0x41, &fifo);
+ 
+ 	/* Check for AMD7409 without swdma errata and if found adjust type */
+@@ -677,10 +500,10 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	/*
+ 	 * Okay, type is determined now.  Apply type-specific workarounds.
+ 	 */
+-	pi = info[type];
++	ppi[0] = &info[type];
+ 
+ 	if (type < 3)
+-		ata_pci_clear_simplex(pdev);
++		ata_pci_bmdma_clear_simplex(pdev);
+ 
+ 	/* Check for AMD7411 */
+ 	if (type == 3)
+@@ -696,16 +519,23 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		u32 udma;
+ 
+ 		pci_read_config_dword(pdev, 0x60, &udma);
+-		pi.private_data = (void *)(unsigned long)udma;
++		hpriv = (void *)(unsigned long)udma;
+ 	}
+ 
+ 	/* And fire it up */
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &amd_sht, hpriv);
+ }
+ 
+ #ifdef CONFIG_PM
+ static int amd_reinit_one(struct pci_dev *pdev)
+ {
++	struct ata_host *host = dev_get_drvdata(&pdev->dev);
++	int rc;
++
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
++
+ 	if (pdev->vendor == PCI_VENDOR_ID_AMD) {
+ 		u8 fifo;
+ 		pci_read_config_byte(pdev, 0x41, &fifo);
+@@ -716,9 +546,11 @@ static int amd_reinit_one(struct pci_dev *pdev)
+ 			pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
+ 		if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
+ 		    pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
+-		    	ata_pci_clear_simplex(pdev);
++			ata_pci_bmdma_clear_simplex(pdev);
+ 	}
+-	return ata_pci_device_resume(pdev);
++
++	ata_host_resume(host);
++	return 0;
+ }
+ #endif
+ 
+diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
+index d421831..0f513bc 100644
+--- a/drivers/ata/pata_artop.c
++++ b/drivers/ata/pata_artop.c
+@@ -52,22 +52,7 @@ static int artop6210_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	artop6210_error_handler - Probe specified port on PATA host controller
+- *	@ap: Port to probe
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void artop6210_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, artop6210_pre_reset,
+-				    ata_std_softreset, NULL,
+-				    ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -93,7 +78,7 @@ static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -114,21 +99,6 @@ static int artop6260_cable_detect(struct ata_port *ap)
+ }
+ 
+ /**
+- *	artop6260_error_handler - Probe specified port on PATA host controller
+- *	@ap: Port to probe
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void artop6260_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, artop6260_pre_reset,
+-				    ata_std_softreset, NULL,
+-				    ata_std_postreset);
+-}
+-
+-/**
+  *	artop6210_load_piomode - Load a set of PATA PIO timings
+  *	@ap: Port whose timings we are configuring
+  *	@adev: Device
+@@ -314,85 +284,23 @@ static void artop6260_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template artop_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations artop6210_ops = {
++static struct ata_port_operations artop6210_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.cable_detect		= ata_cable_40wire,
+ 	.set_piomode		= artop6210_set_piomode,
+ 	.set_dmamode		= artop6210_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= artop6210_error_handler,
+-	.post_internal_cmd 	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= ata_cable_40wire,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
++	.prereset		= artop6210_pre_reset,
+ };
+ 
+-static const struct ata_port_operations artop6260_ops = {
++static struct ata_port_operations artop6260_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.cable_detect		= artop6260_cable_detect,
+ 	.set_piomode		= artop6260_set_piomode,
+ 	.set_dmamode		= artop6260_set_dmamode,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= artop6260_error_handler,
+-	.post_internal_cmd 	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= artop6260_cable_detect,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
++	.prereset		= artop6260_pre_reset,
+ };
+ 
+ 
+@@ -414,7 +322,6 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static int printed_version;
+ 	static const struct ata_port_info info_6210 = {
+-		.sht		= &artop_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+@@ -422,7 +329,6 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ 		.port_ops	= &artop6210_ops,
+ 	};
+ 	static const struct ata_port_info info_626x = {
+-		.sht		= &artop_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+@@ -430,7 +336,6 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ 		.port_ops	= &artop6260_ops,
+ 	};
+ 	static const struct ata_port_info info_628x = {
+-		.sht		= &artop_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+@@ -438,7 +343,6 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ 		.port_ops	= &artop6260_ops,
+ 	};
+ 	static const struct ata_port_info info_628x_fast = {
+-		.sht		= &artop_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+@@ -446,11 +350,16 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ 		.port_ops	= &artop6260_ops,
+ 	};
+ 	const struct ata_port_info *ppi[] = { NULL, NULL };
++	int rc;
+ 
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+ 			   "version " DRV_VERSION "\n");
+ 
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
++
+ 	if (id->driver_data == 0) {	/* 6210 variant */
+ 		ppi[0] = &info_6210;
+ 		ppi[1] = &ata_dummy_port_info;
+@@ -491,7 +400,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ 
+ 	BUG_ON(ppi[0] == NULL);
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &artop_sht, NULL);
+ }
+ 
+ static const struct pci_device_id artop_pci_tbl[] = {
+diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c
+index db057b1..5e10438 100644
+--- a/drivers/ata/pata_at32.c
++++ b/drivers/ata/pata_at32.c
+@@ -166,52 +166,14 @@ static void pata_at32_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ 	}
+ }
+ 
+-static void pata_at32_irq_clear(struct ata_port *ap)
+-{
+-	/* No DMA controller yet */
+-}
+-
+ static struct scsi_host_template at32_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations at32_port_ops = {
+-	.set_piomode		= pata_at32_set_piomode,
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.exec_command		= ata_exec_command,
+-	.check_status		= ata_check_status,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
++	.inherits		= &ata_sff_port_ops,
+ 	.cable_detect		= ata_cable_40wire,
+-
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_clear		= pata_at32_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
++	.set_piomode		= pata_at32_set_piomode,
+ };
+ 
+ static int __init pata_at32_init_one(struct device *dev,
+@@ -261,7 +223,7 @@ static int __init pata_at32_init_one(struct device *dev,
+ 	host->private_data = info;
+ 
+ 	/* Register ATA device and return */
+-	return ata_host_activate(host, info->irq, ata_interrupt,
++	return ata_host_activate(host, info->irq, ata_sff_interrupt,
+ 				 IRQF_SHARED | IRQF_TRIGGER_RISING,
+ 				 &at32_sht);
+ }
+@@ -419,6 +381,9 @@ static int __exit pata_at32_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:at32_ide");
++
+ static struct platform_driver pata_at32_driver = {
+ 	.remove	       = __exit_p(pata_at32_remove),
+ 	.driver	       = {
+diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
+index 408bdc1..78738fb 100644
+--- a/drivers/ata/pata_atiixp.c
++++ b/drivers/ata/pata_atiixp.c
+@@ -45,12 +45,7 @@ static int atiixp_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-static void atiixp_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, atiixp_pre_reset, ata_std_softreset, NULL,   ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ static int atiixp_cable_detect(struct ata_port *ap)
+@@ -221,60 +216,26 @@ static void atiixp_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+ 
+ static struct scsi_host_template atiixp_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
++	ATA_BMDMA_SHT(DRV_NAME),
+ 	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+ static struct ata_port_operations atiixp_port_ops = {
+-	.set_piomode	= atiixp_set_piomode,
+-	.set_dmamode	= atiixp_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= atiixp_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= atiixp_cable_detect,
++	.inherits	= &ata_bmdma_port_ops,
+ 
+-	.bmdma_setup 	= ata_bmdma_setup,
++	.qc_prep 	= ata_sff_dumb_qc_prep,
+ 	.bmdma_start 	= atiixp_bmdma_start,
+ 	.bmdma_stop	= atiixp_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+ 
+-	.qc_prep 	= ata_dumb_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.cable_detect	= atiixp_cable_detect,
++	.set_piomode	= atiixp_set_piomode,
++	.set_dmamode	= atiixp_set_dmamode,
++	.prereset	= atiixp_pre_reset,
+ };
+ 
+ static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &atiixp_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x06,	/* No MWDMA0 support */
+@@ -282,7 +243,7 @@ static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 		.port_ops = &atiixp_port_ops
+ 	};
+ 	const struct ata_port_info *ppi[] = { &info, NULL };
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &atiixp_sht, NULL);
+ }
+ 
+ static const struct pci_device_id atiixp[] = {
+diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
+index 7f87f10..a75de06 100644
+--- a/drivers/ata/pata_bf54x.c
++++ b/drivers/ata/pata_bf54x.c
+@@ -674,7 +674,7 @@ static void read_atapi_data(void __iomem *base,
+  *	@ap: Port to which output is sent
+  *	@tf: ATA taskfile register set
+  *
+- *	Note: Original code is ata_tf_load().
++ *	Note: Original code is ata_sff_tf_load().
+  */
+ 
+ static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+@@ -745,7 +745,7 @@ static u8 bfin_check_status(struct ata_port *ap)
+  *	@ap: Port from which input is read
+  *	@tf: ATA taskfile register set for storing input
+  *
+- *	Note: Original code is ata_tf_read().
++ *	Note: Original code is ata_sff_tf_read().
+  */
+ 
+ static void bfin_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+@@ -775,7 +775,7 @@ static void bfin_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+  *	@ap: port to which command is being issued
+  *	@tf: ATA taskfile register set
+  *
+- *	Note: Original code is ata_exec_command().
++ *	Note: Original code is ata_sff_exec_command().
+  */
+ 
+ static void bfin_exec_command(struct ata_port *ap,
+@@ -785,7 +785,7 @@ static void bfin_exec_command(struct ata_port *ap,
+ 	dev_dbg(ap->dev, "ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+ 
+ 	write_atapi_register(base, ATA_REG_CMD, tf->command);
+-	ata_pause(ap);
++	ata_sff_pause(ap);
+ }
+ 
+ /**
+@@ -800,14 +800,14 @@ static u8 bfin_check_altstatus(struct ata_port *ap)
+ }
+ 
+ /**
+- *	bfin_std_dev_select - Select device 0/1 on ATA bus
++ *	bfin_dev_select - Select device 0/1 on ATA bus
+  *	@ap: ATA channel to manipulate
+  *	@device: ATA device (numbered from zero) to select
+  *
+- *	Note: Original code is ata_std_dev_select().
++ *	Note: Original code is ata_sff_dev_select().
+  */
+ 
+-static void bfin_std_dev_select(struct ata_port *ap, unsigned int device)
++static void bfin_dev_select(struct ata_port *ap, unsigned int device)
+ {
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ 	u8 tmp;
+@@ -818,7 +818,7 @@ static void bfin_std_dev_select(struct ata_port *ap, unsigned int device)
+ 		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+ 
+ 	write_atapi_register(base, ATA_REG_DEVICE, tmp);
+-	ata_pause(ap);
++	ata_sff_pause(ap);
+ }
+ 
+ /**
+@@ -977,7 +977,7 @@ static unsigned int bfin_devchk(struct ata_port *ap,
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ 	u8 nsect, lbal;
+ 
+-	bfin_std_dev_select(ap, device);
++	bfin_dev_select(ap, device);
+ 
+ 	write_atapi_register(base, ATA_REG_NSECT, 0x55);
+ 	write_atapi_register(base, ATA_REG_LBAL, 0xaa);
+@@ -1014,7 +1014,7 @@ static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+ 	 * BSY bit to clear
+ 	 */
+ 	if (dev0)
+-		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
++		ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+ 
+ 	/* if device 1 was found in ata_devchk, wait for
+ 	 * register access, then wait for BSY to clear
+@@ -1023,7 +1023,7 @@ static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+ 	while (dev1) {
+ 		u8 nsect, lbal;
+ 
+-		bfin_std_dev_select(ap, 1);
++		bfin_dev_select(ap, 1);
+ 		nsect = read_atapi_register(base, ATA_REG_NSECT);
+ 		lbal = read_atapi_register(base, ATA_REG_LBAL);
+ 		if ((nsect == 1) && (lbal == 1))
+@@ -1035,14 +1035,14 @@ static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+ 		msleep(50);	/* give drive a breather */
+ 	}
+ 	if (dev1)
+-		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
++		ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+ 
+ 	/* is all this really necessary? */
+-	bfin_std_dev_select(ap, 0);
++	bfin_dev_select(ap, 0);
+ 	if (dev1)
+-		bfin_std_dev_select(ap, 1);
++		bfin_dev_select(ap, 1);
+ 	if (dev0)
+-		bfin_std_dev_select(ap, 0);
++		bfin_dev_select(ap, 0);
+ }
+ 
+ /**
+@@ -1088,26 +1088,21 @@ static unsigned int bfin_bus_softreset(struct ata_port *ap,
+ }
+ 
+ /**
+- *	bfin_std_softreset - reset host port via ATA SRST
++ *	bfin_softreset - reset host port via ATA SRST
+  *	@ap: port to reset
+  *	@classes: resulting classes of attached devices
+  *
+- *	Note: Original code is ata_std_softreset().
++ *	Note: Original code is ata_sff_softreset().
+  */
+ 
+-static int bfin_std_softreset(struct ata_link *link, unsigned int *classes,
+-		unsigned long deadline)
++static int bfin_softreset(struct ata_link *link, unsigned int *classes,
++			  unsigned long deadline)
+ {
+ 	struct ata_port *ap = link->ap;
+ 	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+ 	unsigned int devmask = 0, err_mask;
+ 	u8 err;
+ 
+-	if (ata_link_offline(link)) {
+-		classes[0] = ATA_DEV_NONE;
+-		goto out;
+-	}
+-
+ 	/* determine if device 0/1 are present */
+ 	if (bfin_devchk(ap, 0))
+ 		devmask |= (1 << 0);
+@@ -1115,7 +1110,7 @@ static int bfin_std_softreset(struct ata_link *link, unsigned int *classes,
+ 		devmask |= (1 << 1);
+ 
+ 	/* select device 0 again */
+-	bfin_std_dev_select(ap, 0);
++	bfin_dev_select(ap, 0);
+ 
+ 	/* issue bus reset */
+ 	err_mask = bfin_bus_softreset(ap, devmask);
+@@ -1126,13 +1121,12 @@ static int bfin_std_softreset(struct ata_link *link, unsigned int *classes,
+ 	}
+ 
+ 	/* determine by signature whether we have ATA or ATAPI devices */
+-	classes[0] = ata_dev_try_classify(&ap->link.device[0],
++	classes[0] = ata_sff_dev_classify(&ap->link.device[0],
+ 				devmask & (1 << 0), &err);
+ 	if (slave_possible && err != 0x81)
+-		classes[1] = ata_dev_try_classify(&ap->link.device[1],
++		classes[1] = ata_sff_dev_classify(&ap->link.device[1],
+ 					devmask & (1 << 1), &err);
+ 
+- out:
+ 	return 0;
+ }
+ 
+@@ -1167,7 +1161,7 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
+  *	@buflen: buffer length
+  *	@write_data: read/write
+  *
+- *	Note: Original code is ata_data_xfer().
++ *	Note: Original code is ata_sff_data_xfer().
+  */
+ 
+ static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
+@@ -1206,7 +1200,7 @@ static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
+  *	bfin_irq_clear - Clear ATAPI interrupt.
+  *	@ap: Port associated with this ATA transaction.
+  *
+- *	Note: Original code is ata_bmdma_irq_clear().
++ *	Note: Original code is ata_sff_irq_clear().
+  */
+ 
+ static void bfin_irq_clear(struct ata_port *ap)
+@@ -1223,7 +1217,7 @@ static void bfin_irq_clear(struct ata_port *ap)
+  *	bfin_irq_on - Enable interrupts on a port.
+  *	@ap: Port on which interrupts are enabled.
+  *
+- *	Note: Original code is ata_irq_on().
++ *	Note: Original code is ata_sff_irq_on().
+  */
+ 
+ static unsigned char bfin_irq_on(struct ata_port *ap)
+@@ -1244,13 +1238,13 @@ static unsigned char bfin_irq_on(struct ata_port *ap)
+ }
+ 
+ /**
+- *	bfin_bmdma_freeze - Freeze DMA controller port
++ *	bfin_freeze - Freeze DMA controller port
+  *	@ap: port to freeze
+  *
+- *	Note: Original code is ata_bmdma_freeze().
++ *	Note: Original code is ata_sff_freeze().
+  */
+ 
+-static void bfin_bmdma_freeze(struct ata_port *ap)
++static void bfin_freeze(struct ata_port *ap)
+ {
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ 
+@@ -1264,19 +1258,19 @@ static void bfin_bmdma_freeze(struct ata_port *ap)
+ 	 * ATA_NIEN manipulation.  Also, many controllers fail to mask
+ 	 * previously pending IRQ on ATA_NIEN assertion.  Clear it.
+ 	 */
+-	ata_chk_status(ap);
++	ap->ops->sff_check_status(ap);
+ 
+ 	bfin_irq_clear(ap);
+ }
+ 
+ /**
+- *	bfin_bmdma_thaw - Thaw DMA controller port
++ *	bfin_thaw - Thaw DMA controller port
+  *	@ap: port to thaw
+  *
+- *	Note: Original code is ata_bmdma_thaw().
++ *	Note: Original code is ata_sff_thaw().
+  */
+ 
+-void bfin_bmdma_thaw(struct ata_port *ap)
++void bfin_thaw(struct ata_port *ap)
+ {
+ 	bfin_check_status(ap);
+ 	bfin_irq_clear(ap);
+@@ -1284,14 +1278,14 @@ void bfin_bmdma_thaw(struct ata_port *ap)
+ }
+ 
+ /**
+- *	bfin_std_postreset - standard postreset callback
++ *	bfin_postreset - standard postreset callback
+  *	@ap: the target ata_port
+  *	@classes: classes of attached devices
+  *
+- *	Note: Original code is ata_std_postreset().
++ *	Note: Original code is ata_sff_postreset().
+  */
+ 
+-static void bfin_std_postreset(struct ata_link *link, unsigned int *classes)
++static void bfin_postreset(struct ata_link *link, unsigned int *classes)
+ {
+ 	struct ata_port *ap = link->ap;
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+@@ -1301,9 +1295,9 @@ static void bfin_std_postreset(struct ata_link *link, unsigned int *classes)
+ 
+ 	/* is double-select really necessary? */
+ 	if (classes[0] != ATA_DEV_NONE)
+-		bfin_std_dev_select(ap, 1);
++		bfin_dev_select(ap, 1);
+ 	if (classes[1] != ATA_DEV_NONE)
+-		bfin_std_dev_select(ap, 0);
++		bfin_dev_select(ap, 0);
+ 
+ 	/* bail out if no device is present */
+ 	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+@@ -1314,17 +1308,6 @@ static void bfin_std_postreset(struct ata_link *link, unsigned int *classes)
+ 	write_atapi_register(base, ATA_REG_CTRL, ap->ctl);
+ }
+ 
+-/**
+- *	bfin_error_handler - Stock error handler for DMA controller
+- *	@ap: port to handle error for
+- */
+-
+-static void bfin_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, ata_std_prereset, bfin_std_softreset, NULL,
+-			   bfin_std_postreset);
+-}
+-
+ static void bfin_port_stop(struct ata_port *ap)
+ {
+ 	dev_dbg(ap->dev, "in atapi port stop\n");
+@@ -1357,51 +1340,40 @@ static int bfin_port_start(struct ata_port *ap)
+ }
+ 
+ static struct scsi_host_template bfin_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
++	ATA_BASE_SHT(DRV_NAME),
+ 	.sg_tablesize		= SG_NONE,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+ static const struct ata_port_operations bfin_pata_ops = {
++	.inherits		= &ata_sff_port_ops,
++
+ 	.set_piomode		= bfin_set_piomode,
+ 	.set_dmamode		= bfin_set_dmamode,
+ 
+-	.tf_load		= bfin_tf_load,
+-	.tf_read		= bfin_tf_read,
+-	.exec_command		= bfin_exec_command,
+-	.check_status		= bfin_check_status,
+-	.check_altstatus	= bfin_check_altstatus,
+-	.dev_select		= bfin_std_dev_select,
++	.sff_tf_load		= bfin_tf_load,
++	.sff_tf_read		= bfin_tf_read,
++	.sff_exec_command	= bfin_exec_command,
++	.sff_check_status	= bfin_check_status,
++	.sff_check_altstatus	= bfin_check_altstatus,
++	.sff_dev_select		= bfin_dev_select,
+ 
+ 	.bmdma_setup		= bfin_bmdma_setup,
+ 	.bmdma_start		= bfin_bmdma_start,
+ 	.bmdma_stop		= bfin_bmdma_stop,
+ 	.bmdma_status		= bfin_bmdma_status,
+-	.data_xfer		= bfin_data_xfer,
++	.sff_data_xfer		= bfin_data_xfer,
+ 
+ 	.qc_prep		= ata_noop_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+ 
+-	.freeze			= bfin_bmdma_freeze,
+-	.thaw			= bfin_bmdma_thaw,
+-	.error_handler		= bfin_error_handler,
++	.freeze			= bfin_freeze,
++	.thaw			= bfin_thaw,
++	.softreset		= bfin_softreset,
++	.postreset		= bfin_postreset,
+ 	.post_internal_cmd	= bfin_bmdma_stop,
+ 
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= bfin_irq_clear,
+-	.irq_on			= bfin_irq_on,
++	.sff_irq_clear		= bfin_irq_clear,
++	.sff_irq_on		= bfin_irq_on,
+ 
+ 	.port_start		= bfin_port_start,
+ 	.port_stop		= bfin_port_stop,
+@@ -1409,7 +1381,6 @@ static const struct ata_port_operations bfin_pata_ops = {
+ 
+ static struct ata_port_info bfin_port_info[] = {
+ 	{
+-		.sht		= &bfin_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS
+ 				| ATA_FLAG_MMIO
+ 				| ATA_FLAG_NO_LEGACY,
+@@ -1446,7 +1417,7 @@ static int bfin_reset_controller(struct ata_host *host)
+ 	count = 10000000;
+ 	do {
+ 		status = read_atapi_register(base, ATA_REG_STATUS);
+-	} while (count-- && (status & ATA_BUSY));
++	} while (--count && (status & ATA_BUSY));
+ 
+ 	/* Enable only ATAPI Device interrupt */
+ 	ATAPI_SET_INT_MASK(base, 1);
+@@ -1536,7 +1507,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	if (ata_host_activate(host, platform_get_irq(pdev, 0),
+-		ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
++		ata_sff_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
+ 		peripheral_free_list(atapi_io_port);
+ 		dev_err(&pdev->dev, "Fail to attach ATAPI device\n");
+ 		return -ENODEV;
+@@ -1630,3 +1601,4 @@ MODULE_AUTHOR("Sonic Zhang <sonic.zhang at analog.com>");
+ MODULE_DESCRIPTION("PATA driver for blackfin 54x ATAPI controller");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
+index 43d198f..2de30b9 100644
+--- a/drivers/ata/pata_cmd640.c
++++ b/drivers/ata/pata_cmd640.c
+@@ -107,8 +107,8 @@ static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ 		pci_write_config_byte(pdev, arttim + 1, (t.active << 4) | t.recover);
+ 	} else {
+ 		/* Save the shared timings for channel, they will be loaded
+-		   by qc_issue_prot. Reloading the setup time is expensive
+-		   so we keep a merged one loaded */
++		   by qc_issue. Reloading the setup time is expensive so we
++		   keep a merged one loaded */
+ 		pci_read_config_byte(pdev, ARTIM23, &reg);
+ 		reg &= 0x3F;
+ 		reg |= t.setup;
+@@ -119,14 +119,14 @@ static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ 
+ 
+ /**
+- *	cmd640_qc_issue_prot	-	command preparation hook
++ *	cmd640_qc_issue	-	command preparation hook
+  *	@qc: Command to be issued
+  *
+  *	Channel 1 has shared timings. We must reprogram the
+  *	clock each drive 2/3 switch we do.
+  */
+ 
+-static unsigned int cmd640_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int cmd640_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -137,7 +137,7 @@ static unsigned int cmd640_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		pci_write_config_byte(pdev, DRWTIM23, timing->reg58[adev->devno]);
+ 		timing->last = adev->devno;
+ 	}
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ /**
+@@ -166,53 +166,16 @@ static int cmd640_port_start(struct ata_port *ap)
+ }
+ 
+ static struct scsi_host_template cmd640_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations cmd640_port_ops = {
+-	.set_piomode	= cmd640_set_piomode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_bmdma_port_ops,
++	/* In theory xfer_noirq is not needed once we kill the prefetcher */
++	.sff_data_xfer	= ata_sff_data_xfer_noirq,
++	.qc_issue	= cmd640_qc_issue,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= cmd640_qc_issue_prot,
+-
+-	/* In theory this is not needed once we kill the prefetcher */
+-	.data_xfer	= ata_data_xfer_noirq,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
++	.set_piomode	= cmd640_set_piomode,
+ 	.port_start	= cmd640_port_start,
+ };
+ 
+@@ -248,26 +211,36 @@ static void cmd640_hardware_init(struct pci_dev *pdev)
+ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &cmd640_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.port_ops = &cmd640_port_ops
+ 	};
+ 	const struct ata_port_info *ppi[] = { &info, NULL };
++	int rc;
++
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
+ 
+ 	cmd640_hardware_init(pdev);
+-	return ata_pci_init_one(pdev, ppi);
++
++	return ata_pci_sff_init_one(pdev, ppi, &cmd640_sht, NULL);
+ }
+ 
++#ifdef CONFIG_PM
+ static int cmd640_reinit_one(struct pci_dev *pdev)
+ {
++	struct ata_host *host = dev_get_drvdata(&pdev->dev);
++	int rc;
++
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
+ 	cmd640_hardware_init(pdev);
+-#ifdef CONFIG_PM
+-	return ata_pci_device_resume(pdev);
+-#else
++	ata_host_resume(host);
+ 	return 0;
+-#endif
+ }
++#endif
+ 
+ static const struct pci_device_id cmd640[] = {
+ 	{ PCI_VDEVICE(CMD, 0x640), 0 },
+@@ -281,8 +254,8 @@ static struct pci_driver cmd640_pci_driver = {
+ 	.remove		= ata_pci_remove_one,
+ #ifdef CONFIG_PM
+ 	.suspend	= ata_pci_device_suspend,
+-#endif
+ 	.resume		= cmd640_reinit_one,
++#endif
+ };
+ 
+ static int __init cmd640_init(void)
+diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
+index 7acbbd9..ddd09b7 100644
+--- a/drivers/ata/pata_cmd64x.c
++++ b/drivers/ata/pata_cmd64x.c
+@@ -266,120 +266,30 @@ static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+ 
+ static struct scsi_host_template cmd64x_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static struct ata_port_operations cmd64x_port_ops = {
++static const struct ata_port_operations cmd64x_base_ops = {
++	.inherits	= &ata_bmdma_port_ops,
+ 	.set_piomode	= cmd64x_set_piomode,
+ 	.set_dmamode	= cmd64x_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_port_start,
+ };
+ 
+-static struct ata_port_operations cmd646r1_port_ops = {
+-	.set_piomode	= cmd64x_set_piomode,
+-	.set_dmamode	= cmd64x_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++static struct ata_port_operations cmd64x_port_ops = {
++	.inherits	= &cmd64x_base_ops,
+ 	.cable_detect	= ata_cable_40wire,
++};
+ 
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
++static struct ata_port_operations cmd646r1_port_ops = {
++	.inherits	= &cmd64x_base_ops,
+ 	.bmdma_stop	= cmd646r1_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_port_start,
++	.cable_detect	= ata_cable_40wire,
+ };
+ 
+ static struct ata_port_operations cmd648_port_ops = {
+-	.set_piomode	= cmd64x_set_piomode,
+-	.set_dmamode	= cmd64x_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= cmd648_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
++	.inherits	= &cmd64x_base_ops,
+ 	.bmdma_stop	= cmd648_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_port_start,
++	.cable_detect	= cmd648_cable_detect,
+ };
+ 
+ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+@@ -388,21 +298,18 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 
+ 	static const struct ata_port_info cmd_info[6] = {
+ 		{	/* CMD 643 - no UDMA */
+-			.sht = &cmd64x_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+ 			.port_ops = &cmd64x_port_ops
+ 		},
+ 		{	/* CMD 646 with broken UDMA */
+-			.sht = &cmd64x_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+ 			.port_ops = &cmd64x_port_ops
+ 		},
+ 		{	/* CMD 646 with working UDMA */
+-			.sht = &cmd64x_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -410,14 +317,12 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &cmd64x_port_ops
+ 		},
+ 		{	/* CMD 646 rev 1  */
+-			.sht = &cmd64x_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+ 			.port_ops = &cmd646r1_port_ops
+ 		},
+ 		{	/* CMD 648 */
+-			.sht = &cmd64x_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -425,7 +330,6 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &cmd648_port_ops
+ 		},
+ 		{	/* CMD 649 */
+-			.sht = &cmd64x_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -435,12 +339,17 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
+ 	u8 mrdmode;
++	int rc;
++
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
+ 
+ 	pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
+ 	class_rev &= 0xFF;
+ 
+ 	if (id->driver_data == 0)	/* 643 */
+-		ata_pci_clear_simplex(pdev);
++		ata_pci_bmdma_clear_simplex(pdev);
+ 
+ 	if (pdev->device == PCI_DEVICE_ID_CMD_646) {
+ 		/* Does UDMA work ? */
+@@ -464,13 +373,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+ #endif
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL);
+ }
+ 
+ #ifdef CONFIG_PM
+ static int cmd64x_reinit_one(struct pci_dev *pdev)
+ {
++	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ 	u8 mrdmode;
++	int rc;
++
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
++
+ 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+ 	pci_read_config_byte(pdev, MRDMODE, &mrdmode);
+ 	mrdmode &= ~ 0x30;	/* IRQ set up */
+@@ -479,7 +395,8 @@ static int cmd64x_reinit_one(struct pci_dev *pdev)
+ #ifdef CONFIG_PPC
+ 	pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+ #endif
+-	return ata_pci_device_resume(pdev);
++	ata_host_resume(host);
++	return 0;
+ }
+ #endif
+ 
+diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
+index 7ed279b..1186bcd 100644
+--- a/drivers/ata/pata_cs5520.c
++++ b/drivers/ata/pata_cs5520.c
+@@ -140,51 +140,16 @@ static void cs5520_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template cs5520_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
++	ATA_BMDMA_SHT(DRV_NAME),
+ 	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+ static struct ata_port_operations cs5520_port_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.qc_prep		= ata_sff_dumb_qc_prep,
++	.cable_detect		= ata_cable_40wire,
+ 	.set_piomode		= cs5520_set_piomode,
+ 	.set_dmamode		= cs5520_set_dmamode,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= ata_cable_40wire,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_dumb_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
+ };
+ 
+ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+@@ -203,6 +168,10 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ 	struct ata_ioports *ioaddr;
+ 	int i, rc;
+ 
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
++
+ 	/* IDE port enable bits */
+ 	pci_read_config_byte(pdev, 0x60, &pcicfg);
+ 
+@@ -258,7 +227,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ 	ioaddr->ctl_addr = iomap[1];
+ 	ioaddr->altstatus_addr = iomap[1];
+ 	ioaddr->bmdma_addr = iomap[4];
+-	ata_std_ports(ioaddr);
++	ata_sff_std_ports(ioaddr);
+ 
+ 	ata_port_desc(host->ports[0],
+ 		      "cmd 0x%x ctl 0x%x", cmd_port[0], ctl_port[0]);
+@@ -269,7 +238,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ 	ioaddr->ctl_addr = iomap[3];
+ 	ioaddr->altstatus_addr = iomap[3];
+ 	ioaddr->bmdma_addr = iomap[4] + 8;
+-	ata_std_ports(ioaddr);
++	ata_sff_std_ports(ioaddr);
+ 
+ 	ata_port_desc(host->ports[1],
+ 		      "cmd 0x%x ctl 0x%x", cmd_port[1], ctl_port[1]);
+@@ -289,7 +258,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ 			continue;
+ 
+ 		rc = devm_request_irq(&pdev->dev, irq[ap->port_no],
+-				      ata_interrupt, 0, DRV_NAME, host);
++				      ata_sff_interrupt, 0, DRV_NAME, host);
+ 		if (rc)
+ 			return rc;
+ 
+@@ -310,11 +279,20 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ 
+ static int cs5520_reinit_one(struct pci_dev *pdev)
+ {
++	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ 	u8 pcicfg;
++	int rc;
++
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
++
+ 	pci_read_config_byte(pdev, 0x60, &pcicfg);
+ 	if ((pcicfg & 0x40) == 0)
+ 		pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
+-	return ata_pci_device_resume(pdev);
++
++	ata_host_resume(host);
++	return 0;
+ }
+ 
+ /**
+diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
+index e1818fd..744beeb 100644
+--- a/drivers/ata/pata_cs5530.c
++++ b/drivers/ata/pata_cs5530.c
+@@ -133,7 +133,7 @@ static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	cs5530_qc_issue_prot	-	command issue
++ *	cs5530_qc_issue		-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+@@ -142,7 +142,7 @@ static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+  *	one MWDMA/UDMA bit.
+  */
+ 
+-static unsigned int cs5530_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int cs5530_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -157,59 +157,23 @@ static unsigned int cs5530_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		    	cs5530_set_dmamode(ap, adev);
+ 	}
+ 
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static struct scsi_host_template cs5530_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
++	.sg_tablesize	= LIBATA_DUMB_MAX_PRD,
+ };
+ 
+ static struct ata_port_operations cs5530_port_ops = {
+-	.set_piomode	= cs5530_set_piomode,
+-	.set_dmamode	= cs5530_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_dumb_qc_prep,
+-	.qc_issue	= cs5530_qc_issue_prot,
++	.inherits	= &ata_bmdma_port_ops,
+ 
+-	.data_xfer	= ata_data_xfer,
++	.qc_prep 	= ata_sff_dumb_qc_prep,
++	.qc_issue	= cs5530_qc_issue,
+ 
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.cable_detect	= ata_cable_40wire,
++	.set_piomode	= cs5530_set_piomode,
++	.set_dmamode	= cs5530_set_dmamode,
+ };
+ 
+ static const struct dmi_system_id palmax_dmi_table[] = {
+@@ -334,7 +298,6 @@ fail_put:
+ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &cs5530_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -343,12 +306,16 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* The docking connector doesn't do UDMA, and it seems not MWDMA */
+ 	static const struct ata_port_info info_palmax_secondary = {
+-		.sht = &cs5530_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.port_ops = &cs5530_port_ops
+ 	};
+ 	const struct ata_port_info *ppi[] = { &info, NULL };
++	int rc;
++
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
+ 
+ 	/* Chip initialisation */
+ 	if (cs5530_init_chip())
+@@ -358,16 +325,25 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		ppi[1] = &info_palmax_secondary;
+ 
+ 	/* Now kick off ATA set up */
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL);
+ }
+ 
+ #ifdef CONFIG_PM
+ static int cs5530_reinit_one(struct pci_dev *pdev)
+ {
++	struct ata_host *host = dev_get_drvdata(&pdev->dev);
++	int rc;
++
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
++
+ 	/* If we fail on resume we are doomed */
+ 	if (cs5530_init_chip())
+-		BUG();
+-	return ata_pci_device_resume(pdev);
++		return -EIO;
++
++	ata_host_resume(host);
++	return 0;
+ }
+ #endif /* CONFIG_PM */
+ 
+diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
+index 0132453..f1b6556 100644
+--- a/drivers/ata/pata_cs5535.c
++++ b/drivers/ata/pata_cs5535.c
+@@ -158,55 +158,14 @@ static void cs5535_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template cs5535_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations cs5535_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.cable_detect	= cs5535_cable_detect,
+ 	.set_piomode	= cs5535_set_piomode,
+ 	.set_dmamode	= cs5535_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= cs5535_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /**
+@@ -222,7 +181,6 @@ static struct ata_port_operations cs5535_port_ops = {
+ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &cs5535_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -241,7 +199,7 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	rdmsr(ATAC_CH0D1_PIO, timings, dummy);
+ 	if (CS5535_BAD_PIO(timings))
+ 		wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &cs5535_sht, NULL);
+ }
+ 
+ static const struct pci_device_id cs5535[] = {
+diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
+index 1c4ff9b..73f8332 100644
+--- a/drivers/ata/pata_cs5536.c
++++ b/drivers/ata/pata_cs5536.c
+@@ -221,55 +221,14 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template cs5536_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations cs5536_port_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.cable_detect		= cs5536_cable_detect,
+ 	.set_piomode		= cs5536_set_piomode,
+ 	.set_dmamode		= cs5536_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= cs5536_cable_detect,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_port_start,
+ };
+ 
+ /**
+@@ -282,7 +241,6 @@ static struct ata_port_operations cs5536_port_ops = {
+ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &cs5536_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -303,7 +261,7 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 		return -ENODEV;
+ 	}
+ 
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &cs5536_sht, NULL);
+ }
+ 
+ static const struct pci_device_id cs5536[] = {
+diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
+index fc5f9c4..a9c3218 100644
+--- a/drivers/ata/pata_cypress.c
++++ b/drivers/ata/pata_cypress.c
+@@ -110,61 +110,19 @@ static void cy82c693_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template cy82c693_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations cy82c693_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.cable_detect	= ata_cable_40wire,
+ 	.set_piomode	= cy82c693_set_piomode,
+ 	.set_dmamode	= cy82c693_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &cy82c693_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -178,7 +136,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i
+ 	if (PCI_FUNC(pdev->devfn) != 1)
+ 		return -ENODEV;
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &cy82c693_sht, NULL);
+ }
+ 
+ static const struct pci_device_id cy82c693[] = {
+diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
+index dc33220..9fba829 100644
+--- a/drivers/ata/pata_efar.c
++++ b/drivers/ata/pata_efar.c
+@@ -45,20 +45,7 @@ static int efar_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	efar_probe_reset - Probe specified port on PATA host controller
+- *	@ap: Port to probe
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void efar_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, efar_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -233,53 +220,15 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template efar_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations efar_ops = {
++static struct ata_port_operations efar_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.cable_detect		= efar_cable_detect,
+ 	.set_piomode		= efar_set_piomode,
+ 	.set_dmamode		= efar_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= efar_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= efar_cable_detect,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
++	.prereset		= efar_pre_reset,
+ };
+ 
+ 
+@@ -301,7 +250,6 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	static int printed_version;
+ 	static const struct ata_port_info info = {
+-		.sht		= &efar_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma1-2 */
+@@ -314,7 +262,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+ 			   "version " DRV_VERSION "\n");
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL);
+ }
+ 
+ static const struct pci_device_id efar_pci_tbl[] = {
+diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
+index a742efa..f2b83ea 100644
+--- a/drivers/ata/pata_hpt366.c
++++ b/drivers/ata/pata_hpt366.c
+@@ -184,7 +184,7 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
+ 		if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
+ 			mask &= ~(0xF0 << ATA_SHIFT_UDMA);
+ 	}
+-	return ata_pci_default_filter(adev, mask);
++	return ata_bmdma_mode_filter(adev, mask);
+ }
+ 
+ /**
+@@ -290,21 +290,7 @@ static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template hpt36x_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ /*
+@@ -312,37 +298,11 @@ static struct scsi_host_template hpt36x_sht = {
+  */
+ 
+ static struct ata_port_operations hpt366_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.cable_detect	= hpt36x_cable_detect,
++	.mode_filter	= hpt366_filter,
+ 	.set_piomode	= hpt366_set_piomode,
+ 	.set_dmamode	= hpt366_set_dmamode,
+-	.mode_filter	= hpt366_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= hpt36x_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /**
+@@ -390,18 +350,22 @@ static void hpt36x_init_chipset(struct pci_dev *dev)
+ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info_hpt366 = {
+-		.sht = &hpt36x_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+ 		.udma_mask = ATA_UDMA4,
+ 		.port_ops = &hpt366_port_ops
+ 	};
+-	struct ata_port_info info = info_hpt366;
+-	const struct ata_port_info *ppi[] = { &info, NULL };
++	const struct ata_port_info *ppi[] = { &info_hpt366, NULL };
+ 
++	void *hpriv = NULL;
+ 	u32 class_rev;
+ 	u32 reg1;
++	int rc;
++
++	rc = pcim_enable_device(dev);
++	if (rc)
++		return rc;
+ 
+ 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ 	class_rev &= 0xFF;
+@@ -419,24 +383,31 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	/* info_hpt366 is safe against re-entry so we can scribble on it */
+ 	switch((reg1 & 0x700) >> 8) {
+ 		case 5:
+-			info.private_data = &hpt366_40;
++			hpriv = &hpt366_40;
+ 			break;
+ 		case 9:
+-			info.private_data = &hpt366_25;
++			hpriv = &hpt366_25;
+ 			break;
+ 		default:
+-			info.private_data = &hpt366_33;
++			hpriv = &hpt366_33;
+ 			break;
+ 	}
+ 	/* Now kick off ATA set up */
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &hpt36x_sht, hpriv);
+ }
+ 
+ #ifdef CONFIG_PM
+ static int hpt36x_reinit_one(struct pci_dev *dev)
+ {
++	struct ata_host *host = dev_get_drvdata(&dev->dev);
++	int rc;
++
++	rc = ata_pci_device_do_resume(dev);
++	if (rc)
++		return rc;
+ 	hpt36x_init_chipset(dev);
+-	return ata_pci_device_resume(dev);
++	ata_host_resume(host);
++	return 0;
+ }
+ #endif
+ 
+diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
+index 9a10878..4216399 100644
+--- a/drivers/ata/pata_hpt37x.c
++++ b/drivers/ata/pata_hpt37x.c
+@@ -283,7 +283,7 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask)
+ 		if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
+ 			mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ 	}
+-	return ata_pci_default_filter(adev, mask);
++	return ata_bmdma_mode_filter(adev, mask);
+ }
+ 
+ /**
+@@ -299,7 +299,7 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
+ 		if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
+ 			mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ 	}
+-	return ata_pci_default_filter(adev, mask);
++	return ata_bmdma_mode_filter(adev, mask);
+ }
+ 
+ /**
+@@ -338,22 +338,10 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ 	udelay(100);
+ 
+-	return ata_std_prereset(link, deadline);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+-/**
+- *	hpt37x_error_handler	-	reset the hpt374
+- *	@ap: ATA port to reset
+- *
+- *	Perform probe for HPT37x, except for HPT374 channel 2
+- */
+-
+-static void hpt37x_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+-}
+-
+-static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
++static int hpt374_fn1_pre_reset(struct ata_link *link, unsigned long deadline)
+ {
+ 	static const struct pci_bits hpt37x_enable_bits[] = {
+ 		{ 0x50, 1, 0x04, 0x04 },
+@@ -386,26 +374,7 @@ static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ 	udelay(100);
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	hpt374_error_handler	-	reset the hpt374
+- *	@classes:
+- *
+- *	The 374 cable detect is a little different due to the extra
+- *	channels. The function 0 channels work like usual but function 1
+- *	is special
+- */
+-
+-static void hpt374_error_handler(struct ata_port *ap)
+-{
+-	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+-
+-	if (!(PCI_FUNC(pdev->devfn) & 1))
+-		hpt37x_error_handler(ap);
+-	else
+-		ata_bmdma_drive_eh(ap, hpt374_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -619,21 +588,7 @@ static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc)
+ 
+ 
+ static struct scsi_host_template hpt37x_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ /*
+@@ -641,36 +596,15 @@ static struct scsi_host_template hpt37x_sht = {
+  */
+ 
+ static struct ata_port_operations hpt370_port_ops = {
+-	.set_piomode	= hpt370_set_piomode,
+-	.set_dmamode	= hpt370_set_dmamode,
+-	.mode_filter	= hpt370_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
++	.inherits	= &ata_bmdma_port_ops,
+ 
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= hpt37x_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+ 	.bmdma_start 	= hpt370_bmdma_start,
+ 	.bmdma_stop	= hpt370_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+ 
+-	.port_start	= ata_sff_port_start,
++	.mode_filter	= hpt370_filter,
++	.set_piomode	= hpt370_set_piomode,
++	.set_dmamode	= hpt370_set_dmamode,
++	.prereset	= hpt37x_pre_reset,
+ };
+ 
+ /*
+@@ -678,36 +612,8 @@ static struct ata_port_operations hpt370_port_ops = {
+  */
+ 
+ static struct ata_port_operations hpt370a_port_ops = {
+-	.set_piomode	= hpt370_set_piomode,
+-	.set_dmamode	= hpt370_set_dmamode,
++	.inherits	= &hpt370_port_ops,
+ 	.mode_filter	= hpt370a_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= hpt37x_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= hpt370_bmdma_start,
+-	.bmdma_stop	= hpt370_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+@@ -716,74 +622,23 @@ static struct ata_port_operations hpt370a_port_ops = {
+  */
+ 
+ static struct ata_port_operations hpt372_port_ops = {
+-	.set_piomode	= hpt372_set_piomode,
+-	.set_dmamode	= hpt372_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
++	.inherits	= &ata_bmdma_port_ops,
+ 
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= hpt37x_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+ 	.bmdma_stop	= hpt37x_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+ 
+-	.port_start	= ata_sff_port_start,
++	.set_piomode	= hpt372_set_piomode,
++	.set_dmamode	= hpt372_set_dmamode,
++	.prereset	= hpt37x_pre_reset,
+ };
+ 
+ /*
+  *	Configuration for HPT374. Mode setting works like 372 and friends
+- *	but we have a different cable detection procedure.
++ *	but we have a different cable detection procedure for function 1.
+  */
+ 
+-static struct ata_port_operations hpt374_port_ops = {
+-	.set_piomode	= hpt372_set_piomode,
+-	.set_dmamode	= hpt372_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= hpt374_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= hpt37x_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++static struct ata_port_operations hpt374_fn1_port_ops = {
++	.inherits	= &hpt372_port_ops,
++	.prereset	= hpt374_fn1_pre_reset,
+ };
+ 
+ /**
+@@ -897,7 +752,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	/* HPT370 - UDMA100 */
+ 	static const struct ata_port_info info_hpt370 = {
+-		.sht = &hpt37x_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -906,7 +760,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	};
+ 	/* HPT370A - UDMA100 */
+ 	static const struct ata_port_info info_hpt370a = {
+-		.sht = &hpt37x_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -915,7 +768,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	};
+ 	/* HPT370 - UDMA100 */
+ 	static const struct ata_port_info info_hpt370_33 = {
+-		.sht = &hpt37x_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -924,7 +776,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	};
+ 	/* HPT370A - UDMA100 */
+ 	static const struct ata_port_info info_hpt370a_33 = {
+-		.sht = &hpt37x_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -933,28 +784,31 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	};
+ 	/* HPT371, 372 and friends - UDMA133 */
+ 	static const struct ata_port_info info_hpt372 = {
+-		.sht = &hpt37x_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+ 		.udma_mask = ATA_UDMA6,
+ 		.port_ops = &hpt372_port_ops
+ 	};
+-	/* HPT374 - UDMA100 */
+-	static const struct ata_port_info info_hpt374 = {
+-		.sht = &hpt37x_sht,
++	/* HPT374 - UDMA100, function 1 uses different prereset method */
++	static const struct ata_port_info info_hpt374_fn0 = {
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+ 		.udma_mask = ATA_UDMA5,
+-		.port_ops = &hpt374_port_ops
++		.port_ops = &hpt372_port_ops
++	};
++	static const struct ata_port_info info_hpt374_fn1 = {
++		.flags = ATA_FLAG_SLAVE_POSS,
++		.pio_mask = 0x1f,
++		.mwdma_mask = 0x07,
++		.udma_mask = ATA_UDMA5,
++		.port_ops = &hpt374_fn1_port_ops
+ 	};
+ 
+ 	static const int MHz[4] = { 33, 40, 50, 66 };
+-	const struct ata_port_info *port;
+ 	void *private_data = NULL;
+-	struct ata_port_info port_info;
+-	const struct ata_port_info *ppi[] = { &port_info, NULL };
++	const struct ata_port_info *ppi[] = { NULL, NULL };
+ 
+ 	u8 irqmask;
+ 	u32 class_rev;
+@@ -966,6 +820,11 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 
+ 	const struct hpt_chip *chip_table;
+ 	int clock_slot;
++	int rc;
++
++	rc = pcim_enable_device(dev);
++	if (rc)
++		return rc;
+ 
+ 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ 	class_rev &= 0xFF;
+@@ -981,17 +840,17 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 
+ 		switch(class_rev) {
+ 			case 3:
+-				port = &info_hpt370;
++				ppi[0] = &info_hpt370;
+ 				chip_table = &hpt370;
+ 				prefer_dpll = 0;
+ 				break;
+ 			case 4:
+-				port = &info_hpt370a;
++				ppi[0] = &info_hpt370a;
+ 				chip_table = &hpt370a;
+ 				prefer_dpll = 0;
+ 				break;
+ 			case 5:
+-				port = &info_hpt372;
++				ppi[0] = &info_hpt372;
+ 				chip_table = &hpt372;
+ 				break;
+ 			default:
+@@ -1004,21 +863,21 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 				/* 372N if rev >= 2*/
+ 				if (class_rev >= 2)
+ 					return -ENODEV;
+-				port = &info_hpt372;
++				ppi[0] = &info_hpt372;
+ 				chip_table = &hpt372a;
+ 				break;
+ 			case PCI_DEVICE_ID_TTI_HPT302:
+ 				/* 302N if rev > 1 */
+ 				if (class_rev > 1)
+ 					return -ENODEV;
+-				port = &info_hpt372;
++				ppi[0] = &info_hpt372;
+ 				/* Check this */
+ 				chip_table = &hpt302;
+ 				break;
+ 			case PCI_DEVICE_ID_TTI_HPT371:
+ 				if (class_rev > 1)
+ 					return -ENODEV;
+-				port = &info_hpt372;
++				ppi[0] = &info_hpt372;
+ 				chip_table = &hpt371;
+ 				/* Single channel device, master is not present
+ 				   but the BIOS (or us for non x86) must mark it
+@@ -1029,7 +888,10 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 				break;
+ 			case PCI_DEVICE_ID_TTI_HPT374:
+ 				chip_table = &hpt374;
+-				port = &info_hpt374;
++				if (!(PCI_FUNC(dev->devfn) & 1))
++					*ppi = &info_hpt374_fn0;
++				else
++					*ppi = &info_hpt374_fn1;
+ 				break;
+ 			default:
+ 				printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device);
+@@ -1108,7 +970,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 		int dpll, adjust;
+ 
+ 		/* Compute DPLL */
+-		dpll = (port->udma_mask & 0xC0) ? 3 : 2;
++		dpll = (ppi[0]->udma_mask & 0xC0) ? 3 : 2;
+ 
+ 		f_low = (MHz[clock_slot] * 48) / MHz[dpll];
+ 		f_high = f_low + 2;
+@@ -1148,19 +1010,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 		 *	about lack of UDMA133 support on lower clocks
+  		 */
+ 
+-		if (clock_slot < 2 && port == &info_hpt370)
+-			port = &info_hpt370_33;
+-		if (clock_slot < 2 && port == &info_hpt370a)
+-			port = &info_hpt370a_33;
++		if (clock_slot < 2 && ppi[0] == &info_hpt370)
++			ppi[0] = &info_hpt370_33;
++		if (clock_slot < 2 && ppi[0] == &info_hpt370a)
++			ppi[0] = &info_hpt370a_33;
+ 		printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n",
+ 		       chip_table->name, MHz[clock_slot]);
+ 	}
+ 
+ 	/* Now kick off ATA set up */
+-	port_info = *port;
+-	port_info.private_data = private_data;
+-
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &hpt37x_sht, private_data);
+ }
+ 
+ static const struct pci_device_id hpt37x[] = {
+diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
+index 9f1c084..d5c9fd7 100644
+--- a/drivers/ata/pata_hpt3x2n.c
++++ b/drivers/ata/pata_hpt3x2n.c
+@@ -148,7 +148,7 @@ static int hpt3x2n_cable_detect(struct ata_port *ap)
+  *	Reset the hardware and state machine,
+  */
+ 
+-static int hpt3xn_pre_reset(struct ata_link *link, unsigned long deadline)
++static int hpt3x2n_pre_reset(struct ata_link *link, unsigned long deadline)
+ {
+ 	struct ata_port *ap = link->ap;
+ 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+@@ -156,19 +156,7 @@ static int hpt3xn_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ 	udelay(100);
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	hpt3x2n_error_handler	-	probe the hpt3x2n bus
+- *	@ap: ATA port to reset
+- *
+- *	Perform the probe reset handling for the 3x2N
+- */
+-
+-static void hpt3x2n_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, hpt3xn_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -320,7 +308,7 @@ static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
+ 	return 0;
+ }
+ 
+-static unsigned int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_taskfile *tf = &qc->tf;
+ 	struct ata_port *ap = qc->ap;
+@@ -335,25 +323,11 @@ static unsigned int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc)
+ 				hpt3x2n_set_clock(ap, 0x23);
+ 		}
+ 	}
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static struct scsi_host_template hpt3x2n_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ /*
+@@ -361,37 +335,15 @@ static struct scsi_host_template hpt3x2n_sht = {
+  */
+ 
+ static struct ata_port_operations hpt3x2n_port_ops = {
+-	.set_piomode	= hpt3x2n_set_piomode,
+-	.set_dmamode	= hpt3x2n_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= hpt3x2n_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= hpt3x2n_cable_detect,
++	.inherits	= &ata_bmdma_port_ops,
+ 
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+ 	.bmdma_stop	= hpt3x2n_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= hpt3x2n_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
++	.qc_issue	= hpt3x2n_qc_issue,
+ 
+-	.port_start	= ata_sff_port_start,
++	.cable_detect	= hpt3x2n_cable_detect,
++	.set_piomode	= hpt3x2n_set_piomode,
++	.set_dmamode	= hpt3x2n_set_dmamode,
++	.prereset	= hpt3x2n_pre_reset,
+ };
+ 
+ /**
+@@ -488,15 +440,13 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	/* HPT372N and friends - UDMA133 */
+ 	static const struct ata_port_info info = {
+-		.sht = &hpt3x2n_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+ 		.udma_mask = ATA_UDMA6,
+ 		.port_ops = &hpt3x2n_port_ops
+ 	};
+-	struct ata_port_info port = info;
+-	const struct ata_port_info *ppi[] = { &port, NULL };
++	const struct ata_port_info *ppi[] = { &info, NULL };
+ 
+ 	u8 irqmask;
+ 	u32 class_rev;
+@@ -505,6 +455,12 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	unsigned int f_low, f_high;
+ 	int adjust;
+ 	unsigned long iobase = pci_resource_start(dev, 4);
++	void *hpriv = NULL;
++	int rc;
++
++	rc = pcim_enable_device(dev);
++	if (rc)
++		return rc;
+ 
+ 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ 	class_rev &= 0xFF;
+@@ -586,9 +542,8 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	       pci_mhz);
+ 	/* Set our private data up. We only need a few flags so we use
+ 	   it directly */
+-	port.private_data = NULL;
+ 	if (pci_mhz > 60) {
+-		port.private_data = (void *)PCI66;
++		hpriv = (void *)PCI66;
+ 		/*
+ 		 * On  HPT371N, if ATA clock is 66 MHz we must set bit 2 in
+ 		 * the MISC. register to stretch the UltraDMA Tss timing.
+@@ -599,7 +554,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	}
+ 
+ 	/* Now kick off ATA set up */
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &hpt3x2n_sht, hpriv);
+ }
+ 
+ static const struct pci_device_id hpt3x2n[] = {
+diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
+index cb8bdb6..f11a320 100644
+--- a/drivers/ata/pata_hpt3x3.c
++++ b/drivers/ata/pata_hpt3x3.c
+@@ -102,58 +102,17 @@ static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc)
+ }
+ 
+ static struct scsi_host_template hpt3x3_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations hpt3x3_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.check_atapi_dma= hpt3x3_atapi_dma,
++	.cable_detect	= ata_cable_40wire,
+ 	.set_piomode	= hpt3x3_set_piomode,
+ #if defined(CONFIG_PATA_HPT3X3_DMA)
+ 	.set_dmamode	= hpt3x3_set_dmamode,
+ #endif
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-	.check_atapi_dma= hpt3x3_atapi_dma,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /**
+@@ -189,7 +148,6 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static int printed_version;
+ 	static const struct ata_port_info info = {
+-		.sht = &hpt3x3_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ #if defined(CONFIG_PATA_HPT3X3_DMA)
+@@ -244,15 +202,15 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		ioaddr->altstatus_addr =
+ 		ioaddr->ctl_addr = base + offset_ctl[i];
+ 		ioaddr->scr_addr = NULL;
+-		ata_std_ports(ioaddr);
++		ata_sff_std_ports(ioaddr);
+ 		ioaddr->bmdma_addr = base + 8 * i;
+ 
+ 		ata_port_pbar_desc(ap, 4, -1, "ioport");
+ 		ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd");
+ 	}
+ 	pci_set_master(pdev);
+-	return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+-				 &hpt3x3_sht);
++	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++				 IRQF_SHARED, &hpt3x3_sht);
+ }
+ 
+ #ifdef CONFIG_PM
+diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
+index f97068b..1713843 100644
+--- a/drivers/ata/pata_icside.c
++++ b/drivers/ata/pata_icside.c
+@@ -250,7 +250,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
+ 	set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ);
+ 
+ 	/* issue r/w command */
+-	ap->ops->exec_command(ap, &qc->tf);
++	ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+ 
+ static void pata_icside_bmdma_start(struct ata_queued_cmd *qc)
+@@ -270,7 +270,7 @@ static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
+ 	disable_dma(state->dma);
+ 
+ 	/* see ata_bmdma_stop */
+-	ata_altstatus(ap);
++	ata_sff_altstatus(ap);
+ }
+ 
+ static u8 pata_icside_bmdma_status(struct ata_port *ap)
+@@ -305,35 +305,18 @@ static int icside_dma_init(struct pata_icside_info *info)
+ 
+ 
+ static struct scsi_host_template pata_icside_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
++	ATA_BASE_SHT(DRV_NAME),
+ 	.sg_tablesize		= PATA_ICSIDE_MAX_SG,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= ~0, /* no dma boundaries */
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+-/* wish this was exported from libata-core */
+-static void ata_dummy_noret(struct ata_port *port)
+-{
+-}
+-
+ static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
+ {
+ 	struct ata_port *ap = link->ap;
+ 	struct pata_icside_state *state = ap->host->private_data;
+ 
+ 	if (classes[0] != ATA_DEV_NONE || classes[1] != ATA_DEV_NONE)
+-		return ata_std_postreset(link, classes);
++		return ata_sff_postreset(link, classes);
+ 
+ 	state->port[ap->port_no].disabled = 1;
+ 
+@@ -349,42 +332,20 @@ static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
+ 	}
+ }
+ 
+-static void pata_icside_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+-			   pata_icside_postreset);
+-}
+-
+ static struct ata_port_operations pata_icside_port_ops = {
+-	.set_dmamode		= pata_icside_set_dmamode,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.exec_command		= ata_exec_command,
+-	.check_status		= ata_check_status,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.cable_detect		= ata_cable_40wire,
+-
+-	.bmdma_setup		= pata_icside_bmdma_setup,
+-	.bmdma_start		= pata_icside_bmdma_start,
+-
+-	.data_xfer		= ata_data_xfer_noirq,
+-
++	.inherits		= &ata_sff_port_ops,
+ 	/* no need to build any PRD tables for DMA */
+ 	.qc_prep		= ata_noop_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= pata_icside_error_handler,
+-	.post_internal_cmd	= pata_icside_bmdma_stop,
+-
+-	.irq_clear		= ata_dummy_noret,
+-	.irq_on			= ata_irq_on,
+-
++	.sff_data_xfer		= ata_sff_data_xfer_noirq,
++	.bmdma_setup		= pata_icside_bmdma_setup,
++	.bmdma_start		= pata_icside_bmdma_start,
+ 	.bmdma_stop		= pata_icside_bmdma_stop,
+ 	.bmdma_status		= pata_icside_bmdma_status,
++
++	.cable_detect		= ata_cable_40wire,
++	.set_dmamode		= pata_icside_set_dmamode,
++	.postreset		= pata_icside_postreset,
++	.post_internal_cmd	= pata_icside_bmdma_stop,
+ };
+ 
+ static void __devinit
+@@ -520,7 +481,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
+ 		pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]);
+ 	}
+ 
+-	return ata_host_activate(host, ec->irq, ata_interrupt, 0,
++	return ata_host_activate(host, ec->irq, ata_sff_interrupt, 0,
+ 				 &pata_icside_sht);
+ }
+ 
+diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
+index 4320e79..6a111ba 100644
+--- a/drivers/ata/pata_isapnp.c
++++ b/drivers/ata/pata_isapnp.c
+@@ -20,45 +20,12 @@
+ #define DRV_VERSION "0.2.2"
+ 
+ static struct scsi_host_template isapnp_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations isapnp_port_ops = {
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /**
+@@ -83,7 +50,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
+ 
+ 	if (pnp_irq_valid(idev, 0)) {
+ 		irq = pnp_irq(idev, 0);
+-		handler = ata_interrupt;
++		handler = ata_sff_interrupt;
+ 	}
+ 
+ 	/* allocate host */
+@@ -111,7 +78,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
+ 		ap->ioaddr.ctl_addr = ctl_addr;
+ 	}
+ 
+-	ata_std_ports(&ap->ioaddr);
++	ata_sff_std_ports(&ap->ioaddr);
+ 
+ 	ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
+ 		      (unsigned long long)pnp_port_start(idev, 0),
+diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
+index e0c2cc2..c113d7c 100644
+--- a/drivers/ata/pata_it8213.c
++++ b/drivers/ata/pata_it8213.c
+@@ -40,20 +40,7 @@ static int it8213_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &it8213_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	it8213_error_handler - Probe specified port on PATA host controller
+- *	@ap: Port to probe
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void it8213_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, it8213_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -243,53 +230,16 @@ static void it8213_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template it8213_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.max_sectors		= ATA_MAX_SECTORS,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations it8213_ops = {
++
++static struct ata_port_operations it8213_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.cable_detect		= it8213_cable_detect,
+ 	.set_piomode		= it8213_set_piomode,
+ 	.set_dmamode		= it8213_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= it8213_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= it8213_cable_detect,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
++	.prereset		= it8213_pre_reset,
+ };
+ 
+ 
+@@ -311,7 +261,6 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ {
+ 	static int printed_version;
+ 	static const struct ata_port_info info = {
+-		.sht		= &it8213_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+@@ -325,7 +274,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+ 			   "version " DRV_VERSION "\n");
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &it8213_sht, NULL);
+ }
+ 
+ static const struct pci_device_id it8213_pci_tbl[] = {
+diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
+index 257951d..e108169 100644
+--- a/drivers/ata/pata_it821x.c
++++ b/drivers/ata/pata_it821x.c
+@@ -395,11 +395,11 @@ static void it821x_passthru_dev_select(struct ata_port *ap,
+ 		it821x_program(ap, adev, itdev->pio[adev->devno]);
+ 		itdev->last_device = device;
+ 	}
+-	ata_std_dev_select(ap, device);
++	ata_sff_dev_select(ap, device);
+ }
+ 
+ /**
+- *	it821x_smart_qc_issue_prot	-	wrap qc issue prot
++ *	it821x_smart_qc_issue		-	wrap qc issue prot
+  *	@qc: command
+  *
+  *	Wrap the command issue sequence for the IT821x. We need to
+@@ -407,7 +407,7 @@ static void it821x_passthru_dev_select(struct ata_port *ap,
+  *	usual happenings kick off
+  */
+ 
+-static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int it821x_smart_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	switch(qc->tf.command)
+ 	{
+@@ -427,14 +427,14 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		case ATA_CMD_ID_ATA:
+ 		/* Arguably should just no-op this one */
+ 		case ATA_CMD_SET_FEATURES:
+-			return ata_qc_issue_prot(qc);
++			return ata_sff_qc_issue(qc);
+ 	}
+ 	printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
+ 	return AC_ERR_DEV;
+ }
+ 
+ /**
+- *	it821x_passthru_qc_issue_prot	-	wrap qc issue prot
++ *	it821x_passthru_qc_issue	-	wrap qc issue prot
+  *	@qc: command
+  *
+  *	Wrap the command issue sequence for the IT821x. We need to
+@@ -442,10 +442,10 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
+  *	usual happenings kick off
+  */
+ 
+-static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int it821x_passthru_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	it821x_passthru_dev_select(qc->ap, qc->dev->devno);
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ /**
+@@ -632,89 +632,34 @@ static int it821x_port_start(struct ata_port *ap)
+ }
+ 
+ static struct scsi_host_template it821x_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations it821x_smart_port_ops = {
+-	.set_mode	= it821x_smart_set_mode,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.mode_filter	= ata_pci_default_filter,
++	.inherits	= &ata_bmdma_port_ops,
+ 
+-	.check_status 	= ata_check_status,
+ 	.check_atapi_dma= it821x_check_atapi_dma,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-	.dev_config	= it821x_dev_config,
++	.qc_issue	= it821x_smart_qc_issue,
+ 
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ 	.cable_detect	= it821x_ident_hack,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= it821x_smart_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
++	.set_mode	= it821x_smart_set_mode,
++	.dev_config	= it821x_dev_config,
+ 
+ 	.port_start	= it821x_port_start,
+ };
+ 
+ static struct ata_port_operations it821x_passthru_port_ops = {
+-	.set_piomode	= it821x_passthru_set_piomode,
+-	.set_dmamode	= it821x_passthru_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
++	.inherits	= &ata_bmdma_port_ops,
+ 
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+ 	.check_atapi_dma= it821x_check_atapi_dma,
+-	.dev_select 	= it821x_passthru_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_unknown,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
++	.sff_dev_select	= it821x_passthru_dev_select,
+ 	.bmdma_start 	= it821x_passthru_bmdma_start,
+ 	.bmdma_stop	= it821x_passthru_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= it821x_passthru_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
++	.qc_issue	= it821x_passthru_qc_issue,
+ 
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_handler	= ata_interrupt,
+-	.irq_on		= ata_irq_on,
++	.cable_detect	= ata_cable_unknown,
++	.set_piomode	= it821x_passthru_set_piomode,
++	.set_dmamode	= it821x_passthru_set_dmamode,
+ 
+ 	.port_start	= it821x_port_start,
+ };
+@@ -742,14 +687,12 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	u8 conf;
+ 
+ 	static const struct ata_port_info info_smart = {
+-		.sht = &it821x_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+ 		.port_ops = &it821x_smart_port_ops
+ 	};
+ 	static const struct ata_port_info info_passthru = {
+-		.sht = &it821x_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -759,6 +702,11 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 
+ 	const struct ata_port_info *ppi[] = { NULL, NULL };
+ 	static char *mode[2] = { "pass through", "smart" };
++	int rc;
++
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
+ 
+ 	/* Force the card into bypass mode if so requested */
+ 	if (it8212_noraid) {
+@@ -774,16 +722,23 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	else
+ 		ppi[0] = &info_smart;
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &it821x_sht, NULL);
+ }
+ 
+ #ifdef CONFIG_PM
+ static int it821x_reinit_one(struct pci_dev *pdev)
+ {
++	struct ata_host *host = dev_get_drvdata(&pdev->dev);
++	int rc;
++
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
+ 	/* Resume - turn raid back off if need be */
+ 	if (it8212_noraid)
+ 		it821x_disable_raid(pdev);
+-	return ata_pci_device_resume(pdev);
++	ata_host_resume(host);
++	return rc;
+ }
+ #endif
+ 
+diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
+index 030878f..de8d186 100644
+--- a/drivers/ata/pata_ixp4xx_cf.c
++++ b/drivers/ata/pata_ixp4xx_cf.c
+@@ -88,48 +88,14 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
+ }
+ 
+ static struct scsi_host_template ixp4xx_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations ixp4xx_port_ops = {
+-	.set_mode		= ixp4xx_set_mode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.exec_command		= ata_exec_command,
+-	.check_status 		= ata_check_status,
+-	.dev_select 		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-
+-	.qc_prep 		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ixp4xx_mmio_data_xfer,
++	.inherits		= &ata_sff_port_ops,
++	.sff_data_xfer		= ixp4xx_mmio_data_xfer,
+ 	.cable_detect		= ata_cable_40wire,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_port_start,
++	.set_mode		= ixp4xx_set_mode,
+ };
+ 
+ static void ixp4xx_setup_port(struct ata_port *ap,
+@@ -144,7 +110,7 @@ static void ixp4xx_setup_port(struct ata_port *ap,
+ 	ioaddr->altstatus_addr	= data->cs1 + 0x06;
+ 	ioaddr->ctl_addr	= data->cs1 + 0x06;
+ 
+-	ata_std_ports(ioaddr);
++	ata_sff_std_ports(ioaddr);
+ 
+ #ifndef __ARMEB__
+ 
+@@ -220,7 +186,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
+ 	dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+ 
+ 	/* activate host */
+-	return ata_host_activate(host, irq, ata_interrupt, 0, &ixp4xx_sht);
++	return ata_host_activate(host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);
+ }
+ 
+ static __devexit int ixp4xx_pata_remove(struct platform_device *dev)
+@@ -255,6 +221,7 @@ MODULE_AUTHOR("Alessandro Zummo <a.zummo at towertech.it>");
+ MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_ALIAS("platform:" DRV_NAME);
+ 
+ module_init(ixp4xx_pata_init);
+ module_exit(ixp4xx_pata_exit);
+diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
+index 00bbbbd..73b7596 100644
+--- a/drivers/ata/pata_jmicron.c
++++ b/drivers/ata/pata_jmicron.c
+@@ -102,73 +102,18 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline)
+ 		ap->cbl = ATA_CBL_SATA;
+ 		break;
+ 	}
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	jmicron_error_handler - Setup and error handler
+- *	@ap: Port to handle
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void jmicron_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, jmicron_pre_reset, ata_std_softreset, NULL,
+-			   ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /* No PIO or DMA methods needed for this device */
+ 
+ static struct scsi_host_template jmicron_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	/* Use standard CHS mapping rules */
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations jmicron_ops = {
+-	/* Task file is PCI ATA format, use helpers */
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= jmicron_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-
+-	/* BMDMA handling is PCI ATA format, use helpers */
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	/* IRQ-related hooks */
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	/* Generic PATA PCI ATA helpers */
+-	.port_start		= ata_port_start,
++static struct ata_port_operations jmicron_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.prereset		= jmicron_pre_reset,
+ };
+ 
+ 
+@@ -189,7 +134,6 @@ static const struct ata_port_operations jmicron_ops = {
+ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht		= &jmicron_sht,
+ 		.flags	= ATA_FLAG_SLAVE_POSS,
+ 
+ 		.pio_mask	= 0x1f,
+@@ -200,7 +144,7 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
+ 	};
+ 	const struct ata_port_info *ppi[] = { &info, NULL };
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &jmicron_sht, NULL);
+ }
+ 
+ static const struct pci_device_id jmicron_pci_tbl[] = {
+diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
+index 50fe08e..7af4b29 100644
+--- a/drivers/ata/pata_legacy.c
++++ b/drivers/ata/pata_legacy.c
+@@ -208,21 +208,12 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
+ }
+ 
+ static struct scsi_host_template legacy_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
++};
++
++static const struct ata_port_operations legacy_base_port_ops = {
++	.inherits	= &ata_sff_port_ops,
++	.cable_detect	= ata_cable_40wire,
+ };
+ 
+ /*
+@@ -234,55 +225,14 @@ static struct scsi_host_template legacy_sht = {
+  */
+ 
+ static struct ata_port_operations simple_port_ops = {
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer_noirq,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.inherits	= &legacy_base_port_ops,
++	.sff_data_xfer	= ata_sff_data_xfer_noirq,
+ };
+ 
+ static struct ata_port_operations legacy_port_ops = {
++	.inherits	= &legacy_base_port_ops,
++	.sff_data_xfer	= ata_sff_data_xfer_noirq,
+ 	.set_mode	= legacy_set_mode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer_noirq,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+@@ -367,36 +317,15 @@ static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
+ 		}
+ 		local_irq_restore(flags);
+ 	} else
+-		buflen = ata_data_xfer_noirq(dev, buf, buflen, rw);
++		buflen = ata_sff_data_xfer_noirq(dev, buf, buflen, rw);
+ 
+ 	return buflen;
+ }
+ 
+ static struct ata_port_operations pdc20230_port_ops = {
++	.inherits	= &legacy_base_port_ops,
+ 	.set_piomode	= pdc20230_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= pdc_data_xfer_vlb,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.sff_data_xfer	= pdc_data_xfer_vlb,
+ };
+ 
+ /*
+@@ -427,30 +356,8 @@ static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct ata_port_operations ht6560a_port_ops = {
++	.inherits	= &legacy_base_port_ops,
+ 	.set_piomode	= ht6560a_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,	/* Check vlb/noirq */
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+@@ -492,30 +399,8 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct ata_port_operations ht6560b_port_ops = {
++	.inherits	= &legacy_base_port_ops,
+ 	.set_piomode	= ht6560b_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,    /* FIXME: Check 32bit and noirq */
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+@@ -613,30 +498,8 @@ static void opti82c611a_set_piomode(struct ata_port *ap,
+ 
+ 
+ static struct ata_port_operations opti82c611a_port_ops = {
++	.inherits	= &legacy_base_port_ops,
+ 	.set_piomode	= opti82c611a_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+@@ -716,7 +579,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	opt82c465mv_qc_issue_prot	-	command issue
++ *	opt82c465mv_qc_issue		-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+@@ -730,7 +593,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+  *	FIXME: dual channel needs ->serialize support
+  */
+ 
+-static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int opti82c46x_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -741,34 +604,13 @@ static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
+ 	    && ap->host->private_data != NULL)
+ 		opti82c46x_set_piomode(ap, adev);
+ 
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static struct ata_port_operations opti82c46x_port_ops = {
++	.inherits	= &legacy_base_port_ops,
+ 	.set_piomode	= opti82c46x_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= opti82c46x_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.qc_issue	= opti82c46x_qc_issue,
+ };
+ 
+ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -802,7 +644,7 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
+  *	@irq: interrupt line
+  *
+  *	In dual channel mode the 6580 has one clock per channel and we have
+- *	to software clockswitch in qc_issue_prot.
++ *	to software clockswitch in qc_issue.
+  */
+ 
+ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -868,14 +710,14 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	qdi_qc_issue_prot	-	command issue
++ *	qdi_qc_issue		-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+  *	this interface so that we can load the correct ATA timings.
+  */
+ 
+-static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -888,7 +730,7 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
+ 							2 * ap->port_no);
+ 		}
+ 	}
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
+@@ -917,7 +759,7 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
+ 		}
+ 		return (buflen + 3) & ~3;
+ 	} else
+-		return ata_data_xfer(adev, buf, buflen, rw);
++		return ata_sff_data_xfer(adev, buf, buflen, rw);
+ }
+ 
+ static int qdi_port(struct platform_device *dev,
+@@ -930,84 +772,22 @@ static int qdi_port(struct platform_device *dev,
+ }
+ 
+ static struct ata_port_operations qdi6500_port_ops = {
++	.inherits	= &legacy_base_port_ops,
+ 	.set_piomode	= qdi6500_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= qdi_qc_issue_prot,
+-
+-	.data_xfer	= vlb32_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.qc_issue	= qdi_qc_issue,
++	.sff_data_xfer	= vlb32_data_xfer,
+ };
+ 
+ static struct ata_port_operations qdi6580_port_ops = {
++	.inherits	= &legacy_base_port_ops,
+ 	.set_piomode	= qdi6580_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= vlb32_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.sff_data_xfer	= vlb32_data_xfer,
+ };
+ 
+ static struct ata_port_operations qdi6580dp_port_ops = {
++	.inherits	= &legacy_base_port_ops,
+ 	.set_piomode	= qdi6580dp_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= qdi_qc_issue_prot,
+-
+-	.data_xfer	= vlb32_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.sff_data_xfer	= vlb32_data_xfer,
+ };
+ 
+ static DEFINE_SPINLOCK(winbond_lock);
+@@ -1076,29 +856,9 @@ static int winbond_port(struct platform_device *dev,
+ }
+ 
+ static struct ata_port_operations winbond_port_ops = {
++	.inherits	= &legacy_base_port_ops,
+ 	.set_piomode	= winbond_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= vlb32_data_xfer,
+-
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.sff_data_xfer	= vlb32_data_xfer,
+ };
+ 
+ static struct legacy_controller controllers[] = {
+@@ -1256,13 +1016,13 @@ static __init int legacy_init_one(struct legacy_probe *probe)
+ 	ap->ioaddr.cmd_addr = io_addr;
+ 	ap->ioaddr.altstatus_addr = ctrl_addr;
+ 	ap->ioaddr.ctl_addr = ctrl_addr;
+-	ata_std_ports(&ap->ioaddr);
++	ata_sff_std_ports(&ap->ioaddr);
+ 	ap->host->private_data = ld;
+ 
+ 	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, io + 0x0206);
+ 
+-	ret = ata_host_activate(host, probe->irq, ata_interrupt, 0,
+-								&legacy_sht);
++	ret = ata_host_activate(host, probe->irq, ata_sff_interrupt, 0,
++				&legacy_sht);
+ 	if (ret)
+ 		goto fail;
+ 	ld->platform_dev = pdev;
+diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
+index a81f25d..24a011b 100644
+--- a/drivers/ata/pata_marvell.c
++++ b/drivers/ata/pata_marvell.c
+@@ -55,7 +55,7 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	    (!(devices & 0x10)))	/* PATA enable ? */
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ static int marvell_cable_detect(struct ata_port *ap)
+@@ -75,71 +75,16 @@ static int marvell_cable_detect(struct ata_port *ap)
+ 	return 0;	/* Our BUG macro needs the right markup */
+ }
+ 
+-/**
+- *	marvell_error_handler - Setup and error handler
+- *	@ap: Port to handle
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void marvell_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, NULL,
+-			   ata_std_postreset);
+-}
+-
+ /* No PIO or DMA methods needed for this device */
+ 
+ static struct scsi_host_template marvell_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	/* Use standard CHS mapping rules */
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations marvell_ops = {
+-	/* Task file is PCI ATA format, use helpers */
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= marvell_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
++static struct ata_port_operations marvell_ops = {
++	.inherits		= &ata_bmdma_port_ops,
+ 	.cable_detect		= marvell_cable_detect,
+-
+-	/* BMDMA handling is PCI ATA format, use helpers */
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	/* Timeout handling */
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	/* Generic PATA PCI ATA helpers */
+-	.port_start		= ata_sff_port_start,
++	.prereset		= marvell_pre_reset,
+ };
+ 
+ 
+@@ -160,7 +105,6 @@ static const struct ata_port_operations marvell_ops = {
+ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht		= &marvell_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 
+ 		.pio_mask	= 0x1f,
+@@ -170,7 +114,6 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
+ 		.port_ops	= &marvell_ops,
+ 	};
+ 	static const struct ata_port_info info_sata = {
+-		.sht		= &marvell_sht,
+ 		/* Slave possible as its magically mapped not real */
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 
+@@ -185,7 +128,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
+ 	if (pdev->device == 0x6101)
+ 		ppi[1] = &ata_dummy_port_info;
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
+ }
+ 
+ static const struct pci_device_id marvell_pci_tbl[] = {
+diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
+index 5413ebf..bc79df6 100644
+--- a/drivers/ata/pata_mpc52xx.c
++++ b/drivers/ata/pata_mpc52xx.c
+@@ -252,53 +252,19 @@ mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device)
+ 	if (device != priv->csel)
+ 		mpc52xx_ata_apply_timings(priv, device);
+ 
+-	ata_std_dev_select(ap,device);
++	ata_sff_dev_select(ap,device);
+ }
+ 
+-static void
+-mpc52xx_ata_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+-			ata_std_postreset);
+-}
+-
+-
+-
+ static struct scsi_host_template mpc52xx_ata_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.max_sectors		= ATA_MAX_SECTORS,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations mpc52xx_ata_port_ops = {
+-	.set_piomode		= mpc52xx_ata_set_piomode,
+-	.dev_select		= mpc52xx_ata_dev_select,
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= mpc52xx_ata_error_handler,
++	.inherits		= &ata_sff_port_ops,
++	.sff_dev_select		= mpc52xx_ata_dev_select,
+ 	.cable_detect		= ata_cable_40wire,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-	.port_start		= ata_port_start,
++	.set_piomode		= mpc52xx_ata_set_piomode,
++	.post_internal_cmd	= ATA_OP_NULL,
+ };
+ 
+ static int __devinit
+@@ -339,7 +305,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
+ 	ata_port_desc(ap, "ata_regs 0x%lx", raw_ata_regs);
+ 
+ 	/* activate host */
+-	return ata_host_activate(host, priv->ata_irq, ata_interrupt, 0,
++	return ata_host_activate(host, priv->ata_irq, ata_sff_interrupt, 0,
+ 				 &mpc52xx_ata_sht);
+ }
+ 
+diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
+index c0d9e0c..7d7e3fd 100644
+--- a/drivers/ata/pata_mpiix.c
++++ b/drivers/ata/pata_mpiix.c
+@@ -55,21 +55,7 @@ static int mpiix_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &mpiix_enable_bits))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	mpiix_error_handler		-	probe reset
+- *	@ap: ATA port
+- *
+- *	Perform the ATA probe and bus reset sequence plus specific handling
+- *	for this hardware. The MPIIX has the enable bits in a different place
+- *	to PIIX4 and friends. As a pure PIO device it has no cable detect
+- */
+-
+-static void mpiix_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, mpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -83,8 +69,8 @@ static void mpiix_error_handler(struct ata_port *ap)
+  *
+  *	This would get very ugly because we can only program timing for one
+  *	device at a time, the other gets PIO0. Fortunately libata calls
+- *	our qc_issue_prot command before a command is issued so we can
+- *	flip the timings back and forth to reduce the pain.
++ *	our qc_issue command before a command is issued so we can flip the
++ *	timings back and forth to reduce the pain.
+  */
+ 
+ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -124,7 +110,7 @@ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	mpiix_qc_issue_prot	-	command issue
++ *	mpiix_qc_issue		-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+@@ -134,7 +120,7 @@ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+  *	be made PIO0.
+  */
+ 
+-static unsigned int mpiix_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int mpiix_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -147,50 +133,19 @@ static unsigned int mpiix_qc_issue_prot(struct ata_queued_cmd *qc)
+ 	if (adev->pio_mode && adev != ap->private_data)
+ 		mpiix_set_piomode(ap, adev);
+ 
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static struct scsi_host_template mpiix_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations mpiix_port_ops = {
+-	.set_piomode	= mpiix_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= mpiix_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
++	.qc_issue	= mpiix_qc_issue,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= mpiix_qc_issue_prot,
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_piomode	= mpiix_set_piomode,
++	.prereset	= mpiix_pre_reset,
+ };
+ 
+ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+@@ -252,10 +207,10 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	ap->ioaddr.altstatus_addr = ctl_addr;
+ 
+ 	/* Let libata fill in the port details */
+-	ata_std_ports(&ap->ioaddr);
++	ata_sff_std_ports(&ap->ioaddr);
+ 
+ 	/* activate host */
+-	return ata_host_activate(host, irq, ata_interrupt, IRQF_SHARED,
++	return ata_host_activate(host, irq, ata_sff_interrupt, IRQF_SHARED,
+ 				 &mpiix_sht);
+ }
+ 
+diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
+index 25c922a..d9719c8 100644
+--- a/drivers/ata/pata_netcell.c
++++ b/drivers/ata/pata_netcell.c
+@@ -21,54 +21,12 @@
+ /* No PIO or DMA methods needed for this device */
+ 
+ static struct scsi_host_template netcell_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	/* Use standard CHS mapping rules */
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations netcell_ops = {
+-	/* Task file is PCI ATA format, use helpers */
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
++static struct ata_port_operations netcell_ops = {
++	.inherits	= &ata_bmdma_port_ops,
+ 	.cable_detect		= ata_cable_80wire,
+-
+-	/* BMDMA handling is PCI ATA format, use helpers */
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	/* IRQ-related hooks */
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	/* Generic PATA PCI ATA helpers */
+-	.port_start		= ata_sff_port_start,
+ };
+ 
+ 
+@@ -90,7 +48,6 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ 	static int printed_version;
+ 	static const struct ata_port_info info = {
+-		.sht		= &netcell_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		/* Actually we don't really care about these as the
+ 		   firmware deals with it */
+@@ -100,16 +57,21 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ 		.port_ops	= &netcell_ops,
+ 	};
+ 	const struct ata_port_info *port_info[] = { &info, NULL };
++	int rc;
+ 
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+ 			   "version " DRV_VERSION "\n");
+ 
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
++
+ 	/* Any chip specific setup/optimisation/messages here */
+-	ata_pci_clear_simplex(pdev);
++	ata_pci_bmdma_clear_simplex(pdev);
+ 
+ 	/* And let the library code do the work */
+-	return ata_pci_init_one(pdev, port_info);
++	return ata_pci_sff_init_one(pdev, port_info, &netcell_sht, NULL);
+ }
+ 
+ static const struct pci_device_id netcell_pci_tbl[] = {
+diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
+index 15dd649..565e67c 100644
+--- a/drivers/ata/pata_ninja32.c
++++ b/drivers/ata/pata_ninja32.c
+@@ -73,60 +73,20 @@ static void ninja32_dev_select(struct ata_port *ap, unsigned int device)
+ 	struct ata_device *adev = &ap->link.device[device];
+ 	if (ap->private_data != adev) {
+ 		iowrite8(0xd6, ap->ioaddr.bmdma_addr + 0x1f);
+-		ata_std_dev_select(ap, device);
++		ata_sff_dev_select(ap, device);
+ 		ninja32_set_piomode(ap, adev);
+ 	}
+ }
+ 
+ static struct scsi_host_template ninja32_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations ninja32_port_ops = {
+-	.set_piomode	= ninja32_set_piomode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ninja32_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_bmdma_port_ops,
++	.sff_dev_select = ninja32_dev_select,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_piomode	= ninja32_set_piomode,
+ };
+ 
+ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+@@ -172,7 +132,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	ap->ioaddr.ctl_addr = base + 0x1E;
+ 	ap->ioaddr.altstatus_addr = base + 0x1E;
+ 	ap->ioaddr.bmdma_addr = base;
+-	ata_std_ports(&ap->ioaddr);
++	ata_sff_std_ports(&ap->ioaddr);
+ 
+ 	iowrite8(0x05, base + 0x01);	/* Enable interrupt lines */
+ 	iowrite8(0xBE, base + 0x02);	/* Burst, ?? setup */
+@@ -182,7 +142,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	iowrite8(0xa4, base + 0x1c);	/* Unknown */
+ 	iowrite8(0x83, base + 0x1d);	/* BMDMA control: WAIT0 */
+ 	/* FIXME: Should we disable them at remove ? */
+-	return ata_host_activate(host, dev->irq, ata_interrupt,
++	return ata_host_activate(host, dev->irq, ata_sff_interrupt,
+ 				 IRQF_SHARED, &ninja32_sht);
+ }
+ 
+diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
+index 9fe66fd..76d2455 100644
+--- a/drivers/ata/pata_ns87410.c
++++ b/drivers/ata/pata_ns87410.c
+@@ -50,21 +50,7 @@ static int ns87410_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	ns87410_error_handler		-	probe reset
+- *	@ap: ATA port
+- *
+- *	Perform the ATA probe and bus reset sequence plus specific handling
+- *	for this hardware. The MPIIX has the enable bits in a different place
+- *	to PIIX4 and friends. As a pure PIO device it has no cable detect
+- */
+-
+-static void ns87410_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, ns87410_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -119,7 +105,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	ns87410_qc_issue_prot	-	command issue
++ *	ns87410_qc_issue	-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+@@ -127,7 +113,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
+  *	necessary.
+  */
+ 
+-static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int ns87410_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -140,64 +126,30 @@ static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc)
+ 	if (adev->pio_mode && adev != ap->private_data)
+ 		ns87410_set_piomode(ap, adev);
+ 
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static struct scsi_host_template ns87410_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations ns87410_port_ops = {
+-	.set_piomode	= ns87410_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ns87410_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
++	.qc_issue	= ns87410_qc_issue,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ns87410_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_piomode	= ns87410_set_piomode,
++	.prereset	= ns87410_pre_reset,
+ };
+ 
+ static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &ns87410_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x0F,
+ 		.port_ops = &ns87410_port_ops
+ 	};
+ 	const struct ata_port_info *ppi[] = { &info, NULL };
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &ns87410_sht, NULL);
+ }
+ 
+ static const struct pci_device_id ns87410[] = {
+diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
+index d0e2e50..ae92b00 100644
+--- a/drivers/ata/pata_ns87415.c
++++ b/drivers/ata/pata_ns87415.c
+@@ -138,7 +138,7 @@ static void ns87415_bmdma_setup(struct ata_queued_cmd *qc)
+ 		dmactl |= ATA_DMA_WR;
+ 	iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+ 	/* issue r/w command */
+-	ap->ops->exec_command(ap, &qc->tf);
++	ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+ 
+ /**
+@@ -172,14 +172,14 @@ static void ns87415_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+ 
+ /**
+- *	ns87415_bmdma_irq_clear		-	Clear interrupt
++ *	ns87415_irq_clear		-	Clear interrupt
+  *	@ap: Channel to clear
+  *
+  *	Erratum: Due to a chip bug regisers 02 and 0A bit 1 and 2 (the
+  *	error bits) are reset by writing to register 00 or 08.
+  */
+ 
+-static void ns87415_bmdma_irq_clear(struct ata_port *ap)
++static void ns87415_irq_clear(struct ata_port *ap)
+ {
+ 	void __iomem *mmio = ap->ioaddr.bmdma_addr;
+ 
+@@ -297,90 +297,32 @@ static u8 ns87560_bmdma_status(struct ata_port *ap)
+ {
+ 	return ns87560_read_buggy(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ }
+-
+-static const struct ata_port_operations ns87560_pata_ops = {
+-	.set_piomode		= ns87415_set_piomode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ns87560_tf_read,
+-	.check_status		= ns87560_check_status,
+-	.check_atapi_dma	= ns87415_check_atapi_dma,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd 	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= ata_cable_40wire,
+-
+-	.bmdma_setup		= ns87415_bmdma_setup,
+-	.bmdma_start		= ns87415_bmdma_start,
+-	.bmdma_stop		= ns87415_bmdma_stop,
+-	.bmdma_status		= ns87560_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ns87415_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
+-};
+-
+ #endif		/* 87560 SuperIO Support */
+ 
++static struct ata_port_operations ns87415_pata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
+ 
+-static const struct ata_port_operations ns87415_pata_ops = {
+-	.set_piomode		= ns87415_set_piomode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+ 	.check_atapi_dma	= ns87415_check_atapi_dma,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd 	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= ata_cable_40wire,
+-
+ 	.bmdma_setup		= ns87415_bmdma_setup,
+ 	.bmdma_start		= ns87415_bmdma_start,
+ 	.bmdma_stop		= ns87415_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
++	.sff_irq_clear		= ns87415_irq_clear,
+ 
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ns87415_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
++	.cable_detect		= ata_cable_40wire,
++	.set_piomode		= ns87415_set_piomode,
++};
+ 
+-	.port_start		= ata_sff_port_start,
++#if defined(CONFIG_SUPERIO)
++static struct ata_port_operations ns87560_pata_ops = {
++	.inherits		= &ns87415_pata_ops,
++	.sff_tf_read		= ns87560_tf_read,
++	.sff_check_status	= ns87560_check_status,
++	.bmdma_status		= ns87560_bmdma_status,
+ };
++#endif
+ 
+ static struct scsi_host_template ns87415_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ 
+@@ -403,16 +345,15 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ 	static int printed_version;
+ 	static const struct ata_port_info info = {
+-		.sht		= &ns87415_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.port_ops	= &ns87415_pata_ops,
+ 	};
+ 	const struct ata_port_info *ppi[] = { &info, NULL };
++	int rc;
+ #if defined(CONFIG_SUPERIO)
+ 	static const struct ata_port_info info87560 = {
+-		.sht		= &ns87415_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+@@ -425,11 +366,16 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+ 			   "version " DRV_VERSION "\n");
++
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
++
+ 	/* Select 512 byte sectors */
+ 	pci_write_config_byte(pdev, 0x55, 0xEE);
+ 	/* Select PIO0 8bit clocking */
+ 	pci_write_config_byte(pdev, 0x54, 0xB7);
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &ns87415_sht, NULL);
+ }
+ 
+ static const struct pci_device_id ns87415_pci_tbl[] = {
+diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
+index 44da09a..e678af3 100644
+--- a/drivers/ata/pata_oldpiix.c
++++ b/drivers/ata/pata_oldpiix.c
+@@ -47,21 +47,7 @@ static int oldpiix_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	oldpiix_pata_error_handler - Probe specified port on PATA host controller
+- *	@ap: Port to probe
+- *	@classes:
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void oldpiix_pata_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, oldpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -195,7 +181,7 @@ static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	oldpiix_qc_issue_prot	-	command issue
++ *	oldpiix_qc_issue	-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+@@ -205,7 +191,7 @@ static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+  *	be made PIO0.
+  */
+ 
+-static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int oldpiix_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -215,58 +201,21 @@ static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		if (adev->dma_mode)
+ 			oldpiix_set_dmamode(ap, adev);
+ 	}
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ 
+ static struct scsi_host_template oldpiix_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations oldpiix_pata_ops = {
++static struct ata_port_operations oldpiix_pata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.qc_issue		= oldpiix_qc_issue,
++	.cable_detect		= ata_cable_40wire,
+ 	.set_piomode		= oldpiix_set_piomode,
+ 	.set_dmamode		= oldpiix_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= oldpiix_pata_error_handler,
+-	.post_internal_cmd 	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= ata_cable_40wire,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= oldpiix_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
++	.prereset		= oldpiix_pre_reset,
+ };
+ 
+ 
+@@ -289,7 +238,6 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ 	static int printed_version;
+ 	static const struct ata_port_info info = {
+-		.sht		= &oldpiix_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma1-2 */
+@@ -301,7 +249,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+ 			   "version " DRV_VERSION "\n");
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &oldpiix_sht, NULL);
+ }
+ 
+ static const struct pci_device_id oldpiix_pci_tbl[] = {
+diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
+index 8f79447..fb2cf66 100644
+--- a/drivers/ata/pata_opti.c
++++ b/drivers/ata/pata_opti.c
+@@ -64,22 +64,7 @@ static int opti_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	opti_probe_reset		-	probe reset
+- *	@ap: ATA port
+- *
+- *	Perform the ATA probe and bus reset sequence plus specific handling
+- *	for this hardware. The Opti needs little handling - we have no UDMA66
+- *	capability that needs cable detection. All we must do is check the port
+- *	is enabled.
+- */
+-
+-static void opti_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, opti_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -165,58 +150,19 @@ static void opti_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template opti_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations opti_port_ops = {
+-	.set_piomode	= opti_set_piomode,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= opti_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_piomode	= opti_set_piomode,
++	.prereset	= opti_pre_reset,
+ };
+ 
+ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &opti_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.port_ops = &opti_port_ops
+@@ -227,7 +173,7 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+ 
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &opti_sht, NULL);
+ }
+ 
+ static const struct pci_device_id opti[] = {
+diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
+index f9b485a..4cd7444 100644
+--- a/drivers/ata/pata_optidma.c
++++ b/drivers/ata/pata_optidma.c
+@@ -64,22 +64,7 @@ static int optidma_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	optidma_probe_reset		-	probe reset
+- *	@ap: ATA port
+- *
+- *	Perform the ATA probe and bus reset sequence plus specific handling
+- *	for this hardware. The Opti needs little handling - we have no UDMA66
+- *	capability that needs cable detection. All we must do is check the port
+- *	is enabled.
+- */
+-
+-static void optidma_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, optidma_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -350,89 +335,22 @@ static int optidma_set_mode(struct ata_link *link, struct ata_device **r_failed)
+ }
+ 
+ static struct scsi_host_template optidma_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations optidma_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.cable_detect	= ata_cable_40wire,
+ 	.set_piomode	= optidma_set_pio_mode,
+ 	.set_dmamode	= optidma_set_dma_mode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.error_handler	= optidma_error_handler,
+ 	.set_mode	= optidma_set_mode,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.prereset	= optidma_pre_reset,
+ };
+ 
+ static struct ata_port_operations optiplus_port_ops = {
++	.inherits	= &optidma_port_ops,
+ 	.set_piomode	= optiplus_set_pio_mode,
+ 	.set_dmamode	= optiplus_set_dma_mode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.error_handler	= optidma_error_handler,
+-	.set_mode	= optidma_set_mode,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /**
+@@ -481,14 +399,12 @@ done_nomsg:		/* Wrong chip revision */
+ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info_82c700 = {
+-		.sht = &optidma_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+ 		.port_ops = &optidma_port_ops
+ 	};
+ 	static const struct ata_port_info info_82c700_udma = {
+-		.sht = &optidma_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -497,10 +413,15 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	};
+ 	const struct ata_port_info *ppi[] = { &info_82c700, NULL };
+ 	static int printed_version;
++	int rc;
+ 
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+ 
++	rc = pcim_enable_device(dev);
++	if (rc)
++		return rc;
++
+ 	/* Fixed location chipset magic */
+ 	inw(0x1F1);
+ 	inw(0x1F1);
+@@ -509,7 +430,7 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	if (optiplus_with_udma(dev))
+ 		ppi[0] = &info_82c700_udma;
+ 
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &optidma_sht, NULL);
+ }
+ 
+ static const struct pci_device_id optidma[] = {
+diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
+index 3e7f6a9..3d39f9d 100644
+--- a/drivers/ata/pata_pcmcia.c
++++ b/drivers/ata/pata_pcmcia.c
+@@ -128,71 +128,21 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
+ 
+ 
+ static struct scsi_host_template pcmcia_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations pcmcia_port_ops = {
+-	.set_mode	= pcmcia_set_mode,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
++	.sff_data_xfer	= ata_sff_data_xfer_noirq,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer_noirq,
+-
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_mode	= pcmcia_set_mode,
+ };
+ 
+ static struct ata_port_operations pcmcia_8bit_port_ops = {
+-	.set_mode	= pcmcia_set_mode_8bit,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
++	.sff_data_xfer	= ata_data_xfer_8bit,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer_8bit,
+-
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_mode	= pcmcia_set_mode_8bit,
+ };
+ 
+ #define CS_CHECK(fn, ret) \
+@@ -373,13 +323,13 @@ next_entry:
+ 		ap->ioaddr.cmd_addr = io_addr + 0x10 * p;
+ 		ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p;
+ 		ap->ioaddr.ctl_addr = ctl_addr + 0x10 * p;
+-		ata_std_ports(&ap->ioaddr);
++		ata_sff_std_ports(&ap->ioaddr);
+ 
+ 		ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
+ 	}
+ 
+ 	/* activate */
+-	ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
++	ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_sff_interrupt,
+ 				IRQF_SHARED, &pcmcia_sht);
+ 	if (ret)
+ 		goto failed;
+diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
+index 511c89b..0e1c2c1 100644
+--- a/drivers/ata/pata_pdc2027x.c
++++ b/drivers/ata/pata_pdc2027x.c
+@@ -63,7 +63,7 @@ enum {
+ };
+ 
+ static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+-static void pdc2027x_error_handler(struct ata_port *ap);
++static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);
+ static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
+ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+ static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
+@@ -129,84 +129,22 @@ static struct pci_driver pdc2027x_pci_driver = {
+ };
+ 
+ static struct scsi_host_template pdc2027x_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations pdc2027x_pata100_ops = {
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
++	.inherits		= &ata_bmdma_port_ops,
+ 	.check_atapi_dma	= pdc2027x_check_atapi_dma,
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= pdc2027x_error_handler,
+-	.post_internal_cmd 	= ata_bmdma_post_internal_cmd,
+ 	.cable_detect		= pdc2027x_cable_detect,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
++	.prereset		= pdc2027x_prereset,
+ };
+ 
+ static struct ata_port_operations pdc2027x_pata133_ops = {
++	.inherits		= &pdc2027x_pata100_ops,
++	.mode_filter		= pdc2027x_mode_filter,
+ 	.set_piomode		= pdc2027x_set_piomode,
+ 	.set_dmamode		= pdc2027x_set_dmamode,
+ 	.set_mode		= pdc2027x_set_mode,
+-	.mode_filter		= pdc2027x_mode_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.check_atapi_dma	= pdc2027x_check_atapi_dma,
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= pdc2027x_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= pdc2027x_cable_detect,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
+ };
+ 
+ static struct ata_port_info pdc2027x_port_info[] = {
+@@ -310,22 +248,7 @@ static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline)
+ 	/* Check whether port enabled */
+ 	if (!pdc2027x_port_enabled(link->ap))
+ 		return -ENOENT;
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- *	pdc2027x_error_handler - Perform reset on PATA port and classify
+- *	@ap: Port to reset
+- *
+- *	Reset PATA phy and classify attached devices.
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void pdc2027x_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, pdc2027x_prereset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+@@ -342,7 +265,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
+ 	struct ata_device *pair = ata_dev_pair(adev);
+ 
+ 	if (adev->class != ATA_DEV_ATA || adev->devno == 0 || pair == NULL)
+-		return ata_pci_default_filter(adev, mask);
++		return ata_bmdma_mode_filter(adev, mask);
+ 
+ 	/* Check for slave of a Maxtor at UDMA6 */
+ 	ata_id_c_string(pair->id, model_num, ATA_ID_PROD,
+@@ -351,7 +274,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
+ 	if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6)
+ 		mask &= ~ (1 << (6 + ATA_SHIFT_UDMA));
+ 
+-	return ata_pci_default_filter(adev, mask);
++	return ata_bmdma_mode_filter(adev, mask);
+ }
+ 
+ /**
+@@ -836,8 +759,8 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
+ 		return -EIO;
+ 
+ 	pci_set_master(pdev);
+-	return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+-				 &pdc2027x_sht);
++	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++				 IRQF_SHARED, &pdc2027x_sht);
+ }
+ 
+ /**
+diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
+index 3ed8667..d267306 100644
+--- a/drivers/ata/pata_pdc202xx_old.c
++++ b/drivers/ata/pata_pdc202xx_old.c
+@@ -262,94 +262,34 @@ static int pdc2026x_check_atapi_dma(struct ata_queued_cmd *qc)
+ }
+ 
+ static struct scsi_host_template pdc202xx_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations pdc2024x_port_ops = {
+-	.set_piomode	= pdc202xx_set_piomode,
+-	.set_dmamode	= pdc202xx_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.inherits		= &ata_bmdma_port_ops,
++
++	.cable_detect		= ata_cable_40wire,
++	.set_piomode		= pdc202xx_set_piomode,
++	.set_dmamode		= pdc202xx_set_dmamode,
+ };
+ 
+ static struct ata_port_operations pdc2026x_port_ops = {
+-	.set_piomode	= pdc202xx_set_piomode,
+-	.set_dmamode	= pdc202xx_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-	.dev_config	= pdc2026x_dev_config,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= pdc2026x_cable_detect,
+-
+-	.check_atapi_dma= pdc2026x_check_atapi_dma,
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= pdc2026x_bmdma_start,
+-	.bmdma_stop	= pdc2026x_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= pdc2026x_port_start,
++	.inherits		= &pdc2024x_port_ops,
++
++	.check_atapi_dma	= pdc2026x_check_atapi_dma,
++	.bmdma_start		= pdc2026x_bmdma_start,
++	.bmdma_stop		= pdc2026x_bmdma_stop,
++
++	.cable_detect		= pdc2026x_cable_detect,
++	.dev_config		= pdc2026x_dev_config,
++
++	.port_start		= pdc2026x_port_start,
+ };
+ 
+ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info[3] = {
+ 		{
+-			.sht = &pdc202xx_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -357,7 +297,6 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ 			.port_ops = &pdc2024x_port_ops
+ 		},
+ 		{
+-			.sht = &pdc202xx_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -365,7 +304,6 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ 			.port_ops = &pdc2026x_port_ops
+ 		},
+ 		{
+-			.sht = &pdc202xx_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -386,7 +324,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ 				return -ENODEV;
+ 		}
+ 	}
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &pdc202xx_sht, NULL);
+ }
+ 
+ static const struct pci_device_id pdc202xx[] = {
+diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
+index aad7adc..8f65ad6 100644
+--- a/drivers/ata/pata_platform.c
++++ b/drivers/ata/pata_platform.c
+@@ -46,50 +46,16 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu
+ 	return 0;
+ }
+ 
+-static int ata_dummy_ret0(struct ata_port *ap)	{ return 0; }
+-
+ static struct scsi_host_template pata_platform_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations pata_platform_port_ops = {
+-	.set_mode		= pata_platform_set_mode,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
++	.inherits		= &ata_sff_port_ops,
++	.sff_data_xfer		= ata_sff_data_xfer_noirq,
+ 	.cable_detect		= ata_cable_unknown,
+-
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-
+-	.data_xfer		= ata_data_xfer_noirq,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_dummy_ret0,
++	.set_mode		= pata_platform_set_mode,
++	.port_start		= ATA_OP_NULL,
+ };
+ 
+ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
+@@ -210,7 +176,7 @@ int __devinit __pata_platform_probe(struct device *dev,
+ 		      (unsigned long long)ctl_res->start);
+ 
+ 	/* activate */
+-	return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
++	return ata_host_activate(host, irq, irq ? ata_sff_interrupt : NULL,
+ 				 irq_flags, &pata_platform_sht);
+ }
+ EXPORT_SYMBOL_GPL(__pata_platform_probe);
+@@ -311,3 +277,4 @@ MODULE_AUTHOR("Paul Mundt");
+ MODULE_DESCRIPTION("low-level driver for platform device ATA");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
+index 9f308ed..bf45cf0 100644
+--- a/drivers/ata/pata_qdi.c
++++ b/drivers/ata/pata_qdi.c
+@@ -102,14 +102,14 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	qdi_qc_issue_prot	-	command issue
++ *	qdi_qc_issue		-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+  *	this interface so that we can load the correct ATA timings.
+  */
+ 
+-static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -121,7 +121,7 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
+ 			outb(qdi->clock[adev->devno], qdi->timing);
+ 		}
+ 	}
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
+@@ -148,79 +148,26 @@ static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
+ 			buflen += 4 - slop;
+ 		}
+ 	} else
+-		buflen = ata_data_xfer(dev, buf, buflen, rw);
++		buflen = ata_sff_data_xfer(dev, buf, buflen, rw);
+ 
+ 	return buflen;
+ }
+ 
+ static struct scsi_host_template qdi_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations qdi6500_port_ops = {
+-	.set_piomode	= qdi6500_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
++	.qc_issue	= qdi_qc_issue,
++	.sff_data_xfer	= qdi_data_xfer,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= qdi_qc_issue_prot,
+-
+-	.data_xfer	= qdi_data_xfer,
+-
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_piomode	= qdi6500_set_piomode,
+ };
+ 
+ static struct ata_port_operations qdi6580_port_ops = {
++	.inherits	= &qdi6500_port_ops,
+ 	.set_piomode	= qdi6580_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= qdi_qc_issue_prot,
+-
+-	.data_xfer	= qdi_data_xfer,
+-
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /**
+@@ -276,7 +223,7 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
+ 	ap->ioaddr.cmd_addr = io_addr;
+ 	ap->ioaddr.altstatus_addr = ctl_addr;
+ 	ap->ioaddr.ctl_addr = ctl_addr;
+-	ata_std_ports(&ap->ioaddr);
++	ata_sff_std_ports(&ap->ioaddr);
+ 
+ 	ata_port_desc(ap, "cmd %lx ctl %lx", io, ctl);
+ 
+@@ -292,7 +239,7 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
+ 	printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io);
+ 
+ 	/* activate */
+-	ret = ata_host_activate(host, irq, ata_interrupt, 0, &qdi_sht);
++	ret = ata_host_activate(host, irq, ata_sff_interrupt, 0, &qdi_sht);
+ 	if (ret)
+ 		goto fail;
+ 
+diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
+index 8109b08..1c0d9fa 100644
+--- a/drivers/ata/pata_radisys.c
++++ b/drivers/ata/pata_radisys.c
+@@ -156,7 +156,7 @@ static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	radisys_qc_issue_prot	-	command issue
++ *	radisys_qc_issue	-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+@@ -166,7 +166,7 @@ static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+  *	be made PIO0.
+  */
+ 
+-static unsigned int radisys_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int radisys_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -180,58 +180,20 @@ static unsigned int radisys_qc_issue_prot(struct ata_queued_cmd *qc)
+ 				radisys_set_piomode(ap, adev);
+ 		}
+ 	}
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ 
+ static struct scsi_host_template radisys_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations radisys_pata_ops = {
++static struct ata_port_operations radisys_pata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.qc_issue		= radisys_qc_issue,
++	.cable_detect		= ata_cable_unknown,
+ 	.set_piomode		= radisys_set_piomode,
+ 	.set_dmamode		= radisys_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= ata_cable_unknown,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= radisys_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
+ };
+ 
+ 
+@@ -254,7 +216,6 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ 	static int printed_version;
+ 	static const struct ata_port_info info = {
+-		.sht		= &radisys_sht,
+ 		.flags		= ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma1-2 */
+@@ -267,7 +228,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+ 			   "version " DRV_VERSION "\n");
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &radisys_sht, NULL);
+ }
+ 
+ static const struct pci_device_id radisys_pci_tbl[] = {
+diff --git a/drivers/ata/pata_rb500_cf.c b/drivers/ata/pata_rb500_cf.c
+index 4ce9b03..4345174 100644
+--- a/drivers/ata/pata_rb500_cf.c
++++ b/drivers/ata/pata_rb500_cf.c
+@@ -57,7 +57,7 @@ static inline void rb500_pata_finish_io(struct ata_port *ap)
+ 	struct ata_host *ah = ap->host;
+ 	struct rb500_cf_info *info = ah->private_data;
+ 
+-	ata_altstatus(ap);
++	ata_sff_altstatus(ap);
+ 	ndelay(RB500_CF_IO_DELAY);
+ 
+ 	set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+@@ -109,7 +109,7 @@ static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
+ 	if (gpio_get_value(info->gpio_line)) {
+ 		set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
+ 		if (!info->frozen)
+-			ata_interrupt(info->irq, dev_instance);
++			ata_sff_interrupt(info->irq, dev_instance);
+ 	} else {
+ 		set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+ 	}
+@@ -117,58 +117,18 @@ static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void rb500_pata_irq_clear(struct ata_port *ap)
+-{
+-}
+-
+-static int rb500_pata_port_start(struct ata_port *ap)
+-{
+-	return 0;
+-}
+-
+ static struct ata_port_operations rb500_pata_port_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-
+-	.exec_command		= rb500_pata_exec_command,
+-	.check_status 		= ata_check_status,
+-	.dev_select 		= ata_std_dev_select,
+-
+-	.data_xfer		= rb500_pata_data_xfer,
+-
+-	.qc_prep 		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-
++	.inherits		= &ata_sff_port_ops,
++	.sff_exec_command	= rb500_pata_exec_command,
++	.sff_data_xfer		= rb500_pata_data_xfer,
+ 	.freeze			= rb500_pata_freeze,
+ 	.thaw			= rb500_pata_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-
+-	.irq_handler		= rb500_pata_irq_handler,
+-	.irq_clear		= rb500_pata_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= rb500_pata_port_start,
+ };
+ 
+ /* ------------------------------------------------------------------------ */
+ 
+ static struct scsi_host_template rb500_pata_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+-	.proc_name		= DRV_NAME,
+-
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ /* ------------------------------------------------------------------------ */
+@@ -188,7 +148,7 @@ static void rb500_pata_setup_ports(struct ata_host *ah)
+ 	ap->ioaddr.ctl_addr	= info->iobase + RB500_CF_REG_CTRL;
+ 	ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL;
+ 
+-	ata_std_ports(&ap->ioaddr);
++	ata_sff_std_ports(&ap->ioaddr);
+ 
+ 	ap->ioaddr.data_addr	= info->iobase + RB500_CF_REG_DATA;
+ }
+@@ -279,6 +239,9 @@ static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:" DRV_NAME);
++
+ static struct platform_driver rb500_pata_platform_driver = {
+ 	.probe		= rb500_pata_driver_probe,
+ 	.remove		= __devexit_p(rb500_pata_driver_remove),
+diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
+index ba8a31c..7dfd1f3 100644
+--- a/drivers/ata/pata_rz1000.c
++++ b/drivers/ata/pata_rz1000.c
+@@ -53,53 +53,13 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused)
+ 
+ 
+ static struct scsi_host_template rz1000_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations rz1000_port_ops = {
+-	.set_mode	= rz1000_set_mode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_mode	= rz1000_set_mode,
+ };
+ 
+ static int rz1000_fifo_disable(struct pci_dev *pdev)
+@@ -129,7 +89,6 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ {
+ 	static int printed_version;
+ 	static const struct ata_port_info info = {
+-		.sht = &rz1000_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.port_ops = &rz1000_port_ops
+@@ -140,7 +99,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ 		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ 
+ 	if (rz1000_fifo_disable(pdev) == 0)
+-		return ata_pci_init_one(pdev, ppi);
++		return ata_pci_sff_init_one(pdev, ppi, &rz1000_sht, NULL);
+ 
+ 	printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n");
+ 	/* Not safe to use so skip */
+diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
+index 725a858..cbab397 100644
+--- a/drivers/ata/pata_sc1200.c
++++ b/drivers/ata/pata_sc1200.c
+@@ -151,7 +151,7 @@ static void sc1200_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ /**
+- *	sc1200_qc_issue_prot	-	command issue
++ *	sc1200_qc_issue		-	command issue
+  *	@qc: command pending
+  *
+  *	Called when the libata layer is about to issue a command. We wrap
+@@ -160,7 +160,7 @@ static void sc1200_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+  *	one MWDMA/UDMA bit.
+  */
+ 
+-static unsigned int sc1200_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_device *adev = qc->dev;
+@@ -175,59 +175,21 @@ static unsigned int sc1200_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		    	sc1200_set_dmamode(ap, adev);
+ 	}
+ 
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static struct scsi_host_template sc1200_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
++	.sg_tablesize	= LIBATA_DUMB_MAX_PRD,
+ };
+ 
+ static struct ata_port_operations sc1200_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.qc_prep 	= ata_sff_dumb_qc_prep,
++	.qc_issue	= sc1200_qc_issue,
++	.cable_detect	= ata_cable_40wire,
+ 	.set_piomode	= sc1200_set_piomode,
+ 	.set_dmamode	= sc1200_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_dumb_qc_prep,
+-	.qc_issue	= sc1200_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /**
+@@ -242,7 +204,6 @@ static struct ata_port_operations sc1200_port_ops = {
+ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &sc1200_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -252,7 +213,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	/* Can't enable port 2 yet, see top comments */
+ 	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
+ 
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL);
+ }
+ 
+ static const struct pci_device_id sc1200[] = {
+diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
+index 6c016de..e965b25 100644
+--- a/drivers/ata/pata_scc.c
++++ b/drivers/ata/pata_scc.c
+@@ -266,7 +266,7 @@ unsigned long scc_mode_filter(struct ata_device *adev, unsigned long mask)
+ 		printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME);
+ 		mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ 	}
+-	return ata_pci_default_filter(adev, mask);
++	return ata_bmdma_mode_filter(adev, mask);
+ }
+ 
+ /**
+@@ -274,7 +274,7 @@ unsigned long scc_mode_filter(struct ata_device *adev, unsigned long mask)
+  *	@ap: Port to which output is sent
+  *	@tf: ATA taskfile register set
+  *
+- *	Note: Original code is ata_tf_load().
++ *	Note: Original code is ata_sff_tf_load().
+  */
+ 
+ static void scc_tf_load (struct ata_port *ap, const struct ata_taskfile *tf)
+@@ -341,7 +341,7 @@ static u8 scc_check_status (struct ata_port *ap)
+  *	@ap: Port from which input is read
+  *	@tf: ATA taskfile register set for storing input
+  *
+- *	Note: Original code is ata_tf_read().
++ *	Note: Original code is ata_sff_tf_read().
+  */
+ 
+ static void scc_tf_read (struct ata_port *ap, struct ata_taskfile *tf)
+@@ -373,7 +373,7 @@ static void scc_tf_read (struct ata_port *ap, struct ata_taskfile *tf)
+  *	@ap: port to which command is being issued
+  *	@tf: ATA taskfile register set
+  *
+- *	Note: Original code is ata_exec_command().
++ *	Note: Original code is ata_sff_exec_command().
+  */
+ 
+ static void scc_exec_command (struct ata_port *ap,
+@@ -382,7 +382,7 @@ static void scc_exec_command (struct ata_port *ap,
+ 	DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+ 
+ 	out_be32(ap->ioaddr.command_addr, tf->command);
+-	ata_pause(ap);
++	ata_sff_pause(ap);
+ }
+ 
+ /**
+@@ -396,14 +396,14 @@ static u8 scc_check_altstatus (struct ata_port *ap)
+ }
+ 
+ /**
+- *	scc_std_dev_select - Select device 0/1 on ATA bus
++ *	scc_dev_select - Select device 0/1 on ATA bus
+  *	@ap: ATA channel to manipulate
+  *	@device: ATA device (numbered from zero) to select
+  *
+- *	Note: Original code is ata_std_dev_select().
++ *	Note: Original code is ata_sff_dev_select().
+  */
+ 
+-static void scc_std_dev_select (struct ata_port *ap, unsigned int device)
++static void scc_dev_select (struct ata_port *ap, unsigned int device)
+ {
+ 	u8 tmp;
+ 
+@@ -413,7 +413,7 @@ static void scc_std_dev_select (struct ata_port *ap, unsigned int device)
+ 		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+ 
+ 	out_be32(ap->ioaddr.device_addr, tmp);
+-	ata_pause(ap);
++	ata_sff_pause(ap);
+ }
+ 
+ /**
+@@ -441,7 +441,7 @@ static void scc_bmdma_setup (struct ata_queued_cmd *qc)
+ 	out_be32(mmio + SCC_DMA_CMD, dmactl);
+ 
+ 	/* issue r/w command */
+-	ap->ops->exec_command(ap, &qc->tf);
++	ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+ 
+ /**
+@@ -476,7 +476,7 @@ static unsigned int scc_devchk (struct ata_port *ap,
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 	u8 nsect, lbal;
+ 
+-	ap->ops->dev_select(ap, device);
++	ap->ops->sff_dev_select(ap, device);
+ 
+ 	out_be32(ioaddr->nsect_addr, 0x55);
+ 	out_be32(ioaddr->lbal_addr, 0xaa);
+@@ -497,57 +497,78 @@ static unsigned int scc_devchk (struct ata_port *ap,
+ }
+ 
+ /**
+- *	scc_bus_post_reset - PATA device post reset
++ *	scc_wait_after_reset - wait for devices to become ready after reset
+  *
+- *	Note: Original code is ata_bus_post_reset().
++ *	Note: Original code is ata_sff_wait_after_reset
+  */
+ 
+-static int scc_bus_post_reset(struct ata_port *ap, unsigned int devmask,
+-                              unsigned long deadline)
++int scc_wait_after_reset(struct ata_link *link, unsigned int devmask,
++			 unsigned long deadline)
+ {
++	struct ata_port *ap = link->ap;
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 	unsigned int dev0 = devmask & (1 << 0);
+ 	unsigned int dev1 = devmask & (1 << 1);
+-	int rc;
+-
+-	/* if device 0 was found in ata_devchk, wait for its
+-	 * BSY bit to clear
++	int rc, ret = 0;
++
++	/* Spec mandates ">= 2ms" before checking status.  We wait
++	 * 150ms, because that was the magic delay used for ATAPI
++	 * devices in Hale Landis's ATADRVR, for the period of time
++	 * between when the ATA command register is written, and then
++	 * status is checked.  Because waiting for "a while" before
++	 * checking status is fine, post SRST, we perform this magic
++	 * delay here as well.
++	 *
++	 * Old drivers/ide uses the 2mS rule and then waits for ready.
+ 	 */
+-	if (dev0) {
+-		rc = ata_wait_ready(ap, deadline);
+-		if (rc && rc != -ENODEV)
+-			return rc;
+-	}
++	msleep(150);
+ 
+-	/* if device 1 was found in ata_devchk, wait for
+-	 * register access, then wait for BSY to clear
++	/* always check readiness of the master device */
++	rc = ata_sff_wait_ready(link, deadline);
++	/* -ENODEV means the odd clown forgot the D7 pulldown resistor
++	 * and TF status is 0xff, bail out on it too.
+ 	 */
+-	while (dev1) {
+-		u8 nsect, lbal;
++	if (rc)
++		return rc;
+ 
+-		ap->ops->dev_select(ap, 1);
+-		nsect = in_be32(ioaddr->nsect_addr);
+-		lbal = in_be32(ioaddr->lbal_addr);
+-		if ((nsect == 1) && (lbal == 1))
+-			break;
+-		if (time_after(jiffies, deadline))
+-			return -EBUSY;
+-		msleep(50);	/* give drive a breather */
+-	}
++	/* if device 1 was found in ata_devchk, wait for register
++	 * access briefly, then wait for BSY to clear.
++	 */
+ 	if (dev1) {
+-		rc = ata_wait_ready(ap, deadline);
+-		if (rc && rc != -ENODEV)
+-			return rc;
++		int i;
++
++		ap->ops->sff_dev_select(ap, 1);
++
++		/* Wait for register access.  Some ATAPI devices fail
++		 * to set nsect/lbal after reset, so don't waste too
++		 * much time on it.  We're gonna wait for !BSY anyway.
++		 */
++		for (i = 0; i < 2; i++) {
++			u8 nsect, lbal;
++
++			nsect = in_be32(ioaddr->nsect_addr);
++			lbal = in_be32(ioaddr->lbal_addr);
++			if ((nsect == 1) && (lbal == 1))
++				break;
++			msleep(50);	/* give drive a breather */
++		}
++
++		rc = ata_sff_wait_ready(link, deadline);
++		if (rc) {
++			if (rc != -ENODEV)
++				return rc;
++			ret = rc;
++		}
+ 	}
+ 
+ 	/* is all this really necessary? */
+-	ap->ops->dev_select(ap, 0);
++	ap->ops->sff_dev_select(ap, 0);
+ 	if (dev1)
+-		ap->ops->dev_select(ap, 1);
++		ap->ops->sff_dev_select(ap, 1);
+ 	if (dev0)
+-		ap->ops->dev_select(ap, 0);
++		ap->ops->sff_dev_select(ap, 0);
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ /**
+@@ -570,32 +591,22 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
+ 	udelay(20);
+ 	out_be32(ioaddr->ctl_addr, ap->ctl);
+ 
+-	/* wait a while before checking status */
+-	ata_wait_after_reset(ap, deadline);
+-
+-	/* Before we perform post reset processing we want to see if
+-	 * the bus shows 0xFF because the odd clown forgets the D7
+-	 * pulldown resistor.
+-	 */
+-	if (scc_check_status(ap) == 0xFF)
+-		return 0;
+-
+-	scc_bus_post_reset(ap, devmask, deadline);
++	scc_wait_after_reset(&ap->link, devmask, deadline);
+ 
+ 	return 0;
+ }
+ 
+ /**
+- *	scc_std_softreset - reset host port via ATA SRST
++ *	scc_softreset - reset host port via ATA SRST
+  *	@ap: port to reset
+  *	@classes: resulting classes of attached devices
+  *	@deadline: deadline jiffies for the operation
+  *
+- *	Note: Original code is ata_std_softreset().
++ *	Note: Original code is ata_sff_softreset().
+  */
+ 
+-static int scc_std_softreset(struct ata_link *link, unsigned int *classes,
+-                             unsigned long deadline)
++static int scc_softreset(struct ata_link *link, unsigned int *classes,
++			 unsigned long deadline)
+ {
+ 	struct ata_port *ap = link->ap;
+ 	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+@@ -604,11 +615,6 @@ static int scc_std_softreset(struct ata_link *link, unsigned int *classes,
+ 
+ 	DPRINTK("ENTER\n");
+ 
+-	if (ata_link_offline(link)) {
+-		classes[0] = ATA_DEV_NONE;
+-		goto out;
+-	}
+-
+ 	/* determine if device 0/1 are present */
+ 	if (scc_devchk(ap, 0))
+ 		devmask |= (1 << 0);
+@@ -616,7 +622,7 @@ static int scc_std_softreset(struct ata_link *link, unsigned int *classes,
+ 		devmask |= (1 << 1);
+ 
+ 	/* select device 0 again */
+-	ap->ops->dev_select(ap, 0);
++	ap->ops->sff_dev_select(ap, 0);
+ 
+ 	/* issue bus reset */
+ 	DPRINTK("about to softreset, devmask=%x\n", devmask);
+@@ -628,13 +634,12 @@ static int scc_std_softreset(struct ata_link *link, unsigned int *classes,
+ 	}
+ 
+ 	/* determine by signature whether we have ATA or ATAPI devices */
+-	classes[0] = ata_dev_try_classify(&ap->link.device[0],
++	classes[0] = ata_sff_dev_classify(&ap->link.device[0],
+ 					  devmask & (1 << 0), &err);
+ 	if (slave_possible && err != 0x81)
+-		classes[1] = ata_dev_try_classify(&ap->link.device[1],
++		classes[1] = ata_sff_dev_classify(&ap->link.device[1],
+ 						  devmask & (1 << 1), &err);
+ 
+- out:
+ 	DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+ 	return 0;
+ }
+@@ -695,7 +700,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
+ 			printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME);
+ 			out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT);
+ 			/* TBD: SW reset */
+-			scc_std_softreset(&ap->link, &classes, deadline);
++			scc_softreset(&ap->link, &classes, deadline);
+ 			continue;
+ 		}
+ 
+@@ -721,7 +726,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
+ 		 in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
+ 
+ 	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+-	ata_altstatus(ap);	/* dummy read */
++	ata_sff_altstatus(ap);	/* dummy read */
+ }
+ 
+ /**
+@@ -742,7 +747,7 @@ static u8 scc_bmdma_status (struct ata_port *ap)
+ 		return host_stat;
+ 
+ 	/* errata A252,A308 workaround: Step4 */
+-	if ((ata_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ))
++	if ((ata_sff_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ))
+ 		return (host_stat | ATA_DMA_INTR);
+ 
+ 	/* errata A308 workaround Step5 */
+@@ -773,7 +778,7 @@ static u8 scc_bmdma_status (struct ata_port *ap)
+  *	@buflen: buffer length
+  *	@rw: read/write
+  *
+- *	Note: Original code is ata_data_xfer().
++ *	Note: Original code is ata_sff_data_xfer().
+  */
+ 
+ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
+@@ -782,28 +787,28 @@ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
+ 	struct ata_port *ap = dev->link->ap;
+ 	unsigned int words = buflen >> 1;
+ 	unsigned int i;
+-	u16 *buf16 = (u16 *) buf;
++	__le16 *buf16 = (__le16 *) buf;
+ 	void __iomem *mmio = ap->ioaddr.data_addr;
+ 
+ 	/* Transfer multiple of 2 bytes */
+ 	if (rw == READ)
+ 		for (i = 0; i < words; i++)
+-			buf16[i] = le16_to_cpu(in_be32(mmio));
++			buf16[i] = cpu_to_le16(in_be32(mmio));
+ 	else
+ 		for (i = 0; i < words; i++)
+-			out_be32(mmio, cpu_to_le16(buf16[i]));
++			out_be32(mmio, le16_to_cpu(buf16[i]));
+ 
+ 	/* Transfer trailing 1 byte, if any. */
+ 	if (unlikely(buflen & 0x01)) {
+-		u16 align_buf[1] = { 0 };
++		__le16 align_buf[1] = { 0 };
+ 		unsigned char *trailing_buf = buf + buflen - 1;
+ 
+ 		if (rw == READ) {
+-			align_buf[0] = le16_to_cpu(in_be32(mmio));
++			align_buf[0] = cpu_to_le16(in_be32(mmio));
+ 			memcpy(trailing_buf, align_buf, 1);
+ 		} else {
+ 			memcpy(align_buf, trailing_buf, 1);
+-			out_be32(mmio, cpu_to_le16(align_buf[0]));
++			out_be32(mmio, le16_to_cpu(align_buf[0]));
+ 		}
+ 		words++;
+ 	}
+@@ -815,7 +820,7 @@ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
+  *	scc_irq_on - Enable interrupts on a port.
+  *	@ap: Port on which interrupts are enabled.
+  *
+- *	Note: Original code is ata_irq_on().
++ *	Note: Original code is ata_sff_irq_on().
+  */
+ 
+ static u8 scc_irq_on (struct ata_port *ap)
+@@ -829,19 +834,19 @@ static u8 scc_irq_on (struct ata_port *ap)
+ 	out_be32(ioaddr->ctl_addr, ap->ctl);
+ 	tmp = ata_wait_idle(ap);
+ 
+-	ap->ops->irq_clear(ap);
++	ap->ops->sff_irq_clear(ap);
+ 
+ 	return tmp;
+ }
+ 
+ /**
+- *	scc_bmdma_freeze - Freeze BMDMA controller port
++ *	scc_freeze - Freeze BMDMA controller port
+  *	@ap: port to freeze
+  *
+- *	Note: Original code is ata_bmdma_freeze().
++ *	Note: Original code is ata_sff_freeze().
+  */
+ 
+-static void scc_bmdma_freeze (struct ata_port *ap)
++static void scc_freeze (struct ata_port *ap)
+ {
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 
+@@ -854,9 +859,9 @@ static void scc_bmdma_freeze (struct ata_port *ap)
+ 	 * ATA_NIEN manipulation.  Also, many controllers fail to mask
+ 	 * previously pending IRQ on ATA_NIEN assertion.  Clear it.
+ 	 */
+-	ata_chk_status(ap);
++	ap->ops->sff_check_status(ap);
+ 
+-	ap->ops->irq_clear(ap);
++	ap->ops->sff_irq_clear(ap);
+ }
+ 
+ /**
+@@ -868,18 +873,18 @@ static void scc_bmdma_freeze (struct ata_port *ap)
+ static int scc_pata_prereset(struct ata_link *link, unsigned long deadline)
+ {
+ 	link->ap->cbl = ATA_CBL_PATA80;
+-	return ata_std_prereset(link, deadline);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ /**
+- *	scc_std_postreset - standard postreset callback
++ *	scc_postreset - standard postreset callback
+  *	@ap: the target ata_port
+  *	@classes: classes of attached devices
+  *
+- *	Note: Original code is ata_std_postreset().
++ *	Note: Original code is ata_sff_postreset().
+  */
+ 
+-static void scc_std_postreset(struct ata_link *link, unsigned int *classes)
++static void scc_postreset(struct ata_link *link, unsigned int *classes)
+ {
+ 	struct ata_port *ap = link->ap;
+ 
+@@ -887,9 +892,9 @@ static void scc_std_postreset(struct ata_link *link, unsigned int *classes)
+ 
+ 	/* is double-select really necessary? */
+ 	if (classes[0] != ATA_DEV_NONE)
+-		ap->ops->dev_select(ap, 1);
++		ap->ops->sff_dev_select(ap, 1);
+ 	if (classes[1] != ATA_DEV_NONE)
+-		ap->ops->dev_select(ap, 0);
++		ap->ops->sff_dev_select(ap, 0);
+ 
+ 	/* bail out if no device is present */
+ 	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+@@ -905,24 +910,13 @@ static void scc_std_postreset(struct ata_link *link, unsigned int *classes)
+ }
+ 
+ /**
+- *	scc_error_handler - Stock error handler for BMDMA controller
+- *	@ap: port to handle error for
+- */
+-
+-static void scc_error_handler (struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, scc_pata_prereset, scc_std_softreset, NULL,
+-			   scc_std_postreset);
+-}
+-
+-/**
+- *	scc_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
++ *	scc_irq_clear - Clear PCI IDE BMDMA interrupt.
+  *	@ap: Port associated with this ATA transaction.
+  *
+- *	Note: Original code is ata_bmdma_irq_clear().
++ *	Note: Original code is ata_sff_irq_clear().
+  */
+ 
+-static void scc_bmdma_irq_clear (struct ata_port *ap)
++static void scc_irq_clear (struct ata_port *ap)
+ {
+ 	void __iomem *mmio = ap->ioaddr.bmdma_addr;
+ 
+@@ -968,52 +962,37 @@ static void scc_port_stop (struct ata_port *ap)
+ }
+ 
+ static struct scsi_host_template scc_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations scc_pata_ops = {
++static struct ata_port_operations scc_pata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++
+ 	.set_piomode		= scc_set_piomode,
+ 	.set_dmamode		= scc_set_dmamode,
+ 	.mode_filter		= scc_mode_filter,
+ 
+-	.tf_load		= scc_tf_load,
+-	.tf_read		= scc_tf_read,
+-	.exec_command		= scc_exec_command,
+-	.check_status		= scc_check_status,
+-	.check_altstatus	= scc_check_altstatus,
+-	.dev_select		= scc_std_dev_select,
++	.sff_tf_load		= scc_tf_load,
++	.sff_tf_read		= scc_tf_read,
++	.sff_exec_command	= scc_exec_command,
++	.sff_check_status	= scc_check_status,
++	.sff_check_altstatus	= scc_check_altstatus,
++	.sff_dev_select		= scc_dev_select,
+ 
+ 	.bmdma_setup		= scc_bmdma_setup,
+ 	.bmdma_start		= scc_bmdma_start,
+ 	.bmdma_stop		= scc_bmdma_stop,
+ 	.bmdma_status		= scc_bmdma_status,
+-	.data_xfer		= scc_data_xfer,
+-
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-
+-	.freeze			= scc_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
++	.sff_data_xfer		= scc_data_xfer,
+ 
+-	.error_handler		= scc_error_handler,
++	.freeze			= scc_freeze,
++	.prereset		= scc_pata_prereset,
++	.softreset		= scc_softreset,
++	.postreset		= scc_postreset,
+ 	.post_internal_cmd	= scc_bmdma_stop,
+ 
+-	.irq_clear		= scc_bmdma_irq_clear,
+-	.irq_on			= scc_irq_on,
++	.sff_irq_clear		= scc_irq_clear,
++	.sff_irq_on		= scc_irq_on,
+ 
+ 	.port_start		= scc_port_start,
+ 	.port_stop		= scc_port_stop,
+@@ -1166,8 +1145,8 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	if (rc)
+ 		return rc;
+ 
+-	return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+-				 &scc_sht);
++	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++				 IRQF_SHARED, &scc_sht);
+ }
+ 
+ static struct pci_driver scc_pci_driver = {
+diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
+index a589c0f..ffd26d0 100644
+--- a/drivers/ata/pata_serverworks.c
++++ b/drivers/ata/pata_serverworks.c
+@@ -199,7 +199,7 @@ static unsigned long serverworks_osb4_filter(struct ata_device *adev, unsigned l
+ {
+ 	if (adev->class == ATA_DEV_ATA)
+ 		mask &= ~ATA_MASK_UDMA;
+-	return ata_pci_default_filter(adev, mask);
++	return ata_bmdma_mode_filter(adev, mask);
+ }
+ 
+ 
+@@ -219,7 +219,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
+ 
+ 	/* Disk, UDMA */
+ 	if (adev->class != ATA_DEV_ATA)
+-		return ata_pci_default_filter(adev, mask);
++		return ata_bmdma_mode_filter(adev, mask);
+ 
+ 	/* Actually do need to check */
+ 	ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
+@@ -228,7 +228,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
+ 		if (!strcmp(p, model_num))
+ 			mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ 	}
+-	return ata_pci_default_filter(adev, mask);
++	return ata_bmdma_mode_filter(adev, mask);
+ }
+ 
+ /**
+@@ -298,89 +298,20 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev
+ }
+ 
+ static struct scsi_host_template serverworks_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations serverworks_osb4_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.cable_detect	= serverworks_cable_detect,
++	.mode_filter	= serverworks_osb4_filter,
+ 	.set_piomode	= serverworks_set_piomode,
+ 	.set_dmamode	= serverworks_set_dmamode,
+-	.mode_filter	= serverworks_osb4_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= serverworks_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ static struct ata_port_operations serverworks_csb_port_ops = {
+-	.set_piomode	= serverworks_set_piomode,
+-	.set_dmamode	= serverworks_set_dmamode,
++	.inherits	= &serverworks_osb4_port_ops,
+ 	.mode_filter	= serverworks_csb_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= serverworks_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ static int serverworks_fixup_osb4(struct pci_dev *pdev)
+@@ -468,28 +399,24 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
+ {
+ 	static const struct ata_port_info info[4] = {
+ 		{ /* OSB4 */
+-			.sht = &serverworks_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+ 			.udma_mask = 0x07,
+ 			.port_ops = &serverworks_osb4_port_ops
+ 		}, { /* OSB4 no UDMA */
+-			.sht = &serverworks_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+ 			.udma_mask = 0x00,
+ 			.port_ops = &serverworks_osb4_port_ops
+ 		}, { /* CSB5 */
+-			.sht = &serverworks_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+ 			.udma_mask = ATA_UDMA4,
+ 			.port_ops = &serverworks_csb_port_ops
+ 		}, { /* CSB5 - later revisions*/
+-			.sht = &serverworks_sht,
+ 			.flags = ATA_FLAG_SLAVE_POSS,
+ 			.pio_mask = 0x1f,
+ 			.mwdma_mask = 0x07,
+@@ -498,6 +425,11 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
+ 		}
+ 	};
+ 	const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL };
++	int rc;
++
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
+ 
+ 	/* Force master latency timer to 64 PCI clocks */
+ 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+@@ -527,24 +459,30 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
+ 		serverworks_fixup_ht1000(pdev);
+ 
+ 	if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
+-		ata_pci_clear_simplex(pdev);
++		ata_pci_bmdma_clear_simplex(pdev);
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &serverworks_sht, NULL);
+ }
+ 
+ #ifdef CONFIG_PM
+ static int serverworks_reinit_one(struct pci_dev *pdev)
+ {
++	struct ata_host *host = dev_get_drvdata(&pdev->dev);
++	int rc;
++
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
++
+ 	/* Force master latency timer to 64 PCI clocks */
+ 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+ 
+-	switch (pdev->device)
+-	{
++	switch (pdev->device) {
+ 		case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
+ 			serverworks_fixup_osb4(pdev);
+ 			break;
+ 		case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+-			ata_pci_clear_simplex(pdev);
++			ata_pci_bmdma_clear_simplex(pdev);
+ 			/* fall through */
+ 		case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
+ 		case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
+@@ -554,7 +492,9 @@ static int serverworks_reinit_one(struct pci_dev *pdev)
+ 			serverworks_fixup_ht1000(pdev);
+ 			break;
+ 	}
+-	return ata_pci_device_resume(pdev);
++
++	ata_host_resume(host);
++	return 0;
+ }
+ #endif
+ 
+diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
+index 7c5b2dd..720b864 100644
+--- a/drivers/ata/pata_sil680.c
++++ b/drivers/ata/pata_sil680.c
+@@ -192,54 +192,14 @@ static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template sil680_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations sil680_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.cable_detect	= sil680_cable_detect,
+ 	.set_piomode	= sil680_set_piomode,
+ 	.set_dmamode	= sil680_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= sil680_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
+ };
+ 
+ /**
+@@ -322,7 +282,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
+ 				     const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &sil680_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -330,7 +289,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
+ 		.port_ops = &sil680_port_ops
+ 	};
+ 	static const struct ata_port_info info_slow = {
+-		.sht = &sil680_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -346,6 +304,10 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ 
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
++
+ 	switch (sil680_init_chip(pdev, &try_mmio)) {
+ 		case 0:
+ 			ppi[0] = &info_slow;
+@@ -388,28 +350,33 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
+ 	host->ports[0]->ioaddr.cmd_addr = mmio_base + 0x80;
+ 	host->ports[0]->ioaddr.ctl_addr = mmio_base + 0x8a;
+ 	host->ports[0]->ioaddr.altstatus_addr = mmio_base + 0x8a;
+-	ata_std_ports(&host->ports[0]->ioaddr);
++	ata_sff_std_ports(&host->ports[0]->ioaddr);
+ 	host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x08;
+ 	host->ports[1]->ioaddr.cmd_addr = mmio_base + 0xc0;
+ 	host->ports[1]->ioaddr.ctl_addr = mmio_base + 0xca;
+ 	host->ports[1]->ioaddr.altstatus_addr = mmio_base + 0xca;
+-	ata_std_ports(&host->ports[1]->ioaddr);
++	ata_sff_std_ports(&host->ports[1]->ioaddr);
+ 
+ 	/* Register & activate */
+-	return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+-				 &sil680_sht);
++	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++				 IRQF_SHARED, &sil680_sht);
+ 
+ use_ioports:
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &sil680_sht, NULL);
+ }
+ 
+ #ifdef CONFIG_PM
+ static int sil680_reinit_one(struct pci_dev *pdev)
+ {
+-	int try_mmio;
++	struct ata_host *host = dev_get_drvdata(&pdev->dev);
++	int try_mmio, rc;
+ 
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
+ 	sil680_init_chip(pdev, &try_mmio);
+-	return ata_pci_device_resume(pdev);
++	ata_host_resume(host);
++	return 0;
+ }
+ #endif
+ 
+diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
+index dc7e915..e82c66e 100644
+--- a/drivers/ata/pata_sis.c
++++ b/drivers/ata/pata_sis.c
+@@ -156,24 +156,11 @@ static int sis_pre_reset(struct ata_link *link, unsigned long deadline)
+ 	/* Clear the FIFO settings. We can't enable the FIFO until
+ 	   we know we are poking at a disk */
+ 	pci_write_config_byte(pdev, 0x4B, 0);
+-	return ata_std_prereset(link, deadline);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ 
+ /**
+- *	sis_error_handler - Probe specified port on PATA host controller
+- *	@ap: Port to probe
+- *
+- *	LOCKING:
+- *	None (inherited from caller).
+- */
+-
+-static void sis_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, sis_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+-}
+-
+-/**
+  *	sis_set_fifo	-	Set RWP fifo bits for this device
+  *	@ap: Port
+  *	@adev: Device
+@@ -514,217 +501,57 @@ static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template sis_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations sis_133_ops = {
++static struct ata_port_operations sis_133_for_sata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
+ 	.set_piomode		= sis_133_set_piomode,
+ 	.set_dmamode		= sis_133_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= sis_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+ 	.cable_detect		= sis_133_cable_detect,
++};
+ 
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
++static struct ata_port_operations sis_base_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.prereset		= sis_pre_reset,
+ };
+ 
+-static const struct ata_port_operations sis_133_for_sata_ops = {
++static struct ata_port_operations sis_133_ops = {
++	.inherits		= &sis_base_ops,
+ 	.set_piomode		= sis_133_set_piomode,
+ 	.set_dmamode		= sis_133_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+ 	.cable_detect		= sis_133_cable_detect,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
+ };
+ 
+-static const struct ata_port_operations sis_133_early_ops = {
++static struct ata_port_operations sis_133_early_ops = {
++	.inherits		= &sis_base_ops,
+ 	.set_piomode		= sis_100_set_piomode,
+ 	.set_dmamode		= sis_133_early_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= sis_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+ 	.cable_detect		= sis_66_cable_detect,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
+ };
+ 
+-static const struct ata_port_operations sis_100_ops = {
++static struct ata_port_operations sis_100_ops = {
++	.inherits		= &sis_base_ops,
+ 	.set_piomode		= sis_100_set_piomode,
+ 	.set_dmamode		= sis_100_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= sis_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+ 	.cable_detect		= sis_66_cable_detect,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
+ };
+ 
+-static const struct ata_port_operations sis_66_ops = {
++static struct ata_port_operations sis_66_ops = {
++	.inherits		= &sis_base_ops,
+ 	.set_piomode		= sis_old_set_piomode,
+ 	.set_dmamode		= sis_66_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+ 	.cable_detect		= sis_66_cable_detect,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= sis_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
+ };
+ 
+-static const struct ata_port_operations sis_old_ops = {
++static struct ata_port_operations sis_old_ops = {
++	.inherits		= &sis_base_ops,
+ 	.set_piomode		= sis_old_set_piomode,
+ 	.set_dmamode		= sis_old_set_dmamode,
+-	.mode_filter		= ata_pci_default_filter,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= sis_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+ 	.cable_detect		= ata_cable_40wire,
+-
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_handler		= ata_interrupt,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_sff_port_start,
+ };
+ 
+ static const struct ata_port_info sis_info = {
+-	.sht		= &sis_sht,
+ 	.flags		= ATA_FLAG_SLAVE_POSS,
+ 	.pio_mask	= 0x1f,	/* pio0-4 */
+ 	.mwdma_mask	= 0x07,
+@@ -732,7 +559,6 @@ static const struct ata_port_info sis_info = {
+ 	.port_ops	= &sis_old_ops,
+ };
+ static const struct ata_port_info sis_info33 = {
+-	.sht		= &sis_sht,
+ 	.flags		= ATA_FLAG_SLAVE_POSS,
+ 	.pio_mask	= 0x1f,	/* pio0-4 */
+ 	.mwdma_mask	= 0x07,
+@@ -740,42 +566,36 @@ static const struct ata_port_info sis_info33 = {
+ 	.port_ops	= &sis_old_ops,
+ };
+ static const struct ata_port_info sis_info66 = {
+-	.sht		= &sis_sht,
+ 	.flags		= ATA_FLAG_SLAVE_POSS,
+ 	.pio_mask	= 0x1f,	/* pio0-4 */
+ 	.udma_mask	= ATA_UDMA4,	/* UDMA 66 */
+ 	.port_ops	= &sis_66_ops,
+ };
+ static const struct ata_port_info sis_info100 = {
+-	.sht		= &sis_sht,
+ 	.flags		= ATA_FLAG_SLAVE_POSS,
+ 	.pio_mask	= 0x1f,	/* pio0-4 */
+ 	.udma_mask	= ATA_UDMA5,
+ 	.port_ops	= &sis_100_ops,
+ };
+ static const struct ata_port_info sis_info100_early = {
+-	.sht		= &sis_sht,
+ 	.flags		= ATA_FLAG_SLAVE_POSS,
+ 	.udma_mask	= ATA_UDMA5,
+ 	.pio_mask	= 0x1f,	/* pio0-4 */
+ 	.port_ops	= &sis_66_ops,
+ };
+ static const struct ata_port_info sis_info133 = {
+-	.sht		= &sis_sht,
+ 	.flags		= ATA_FLAG_SLAVE_POSS,
+ 	.pio_mask	= 0x1f,	/* pio0-4 */
+ 	.udma_mask	= ATA_UDMA6,
+ 	.port_ops	= &sis_133_ops,
+ };
+ const struct ata_port_info sis_info133_for_sata = {
+-	.sht		= &sis_sht,
+ 	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ 	.pio_mask	= 0x1f,	/* pio0-4 */
+ 	.udma_mask	= ATA_UDMA6,
+ 	.port_ops	= &sis_133_for_sata_ops,
+ };
+ static const struct ata_port_info sis_info133_early = {
+-	.sht		= &sis_sht,
+ 	.flags		= ATA_FLAG_SLAVE_POSS,
+ 	.pio_mask	= 0x1f,	/* pio0-4 */
+ 	.udma_mask	= ATA_UDMA6,
+@@ -857,11 +677,11 @@ static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)
+ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	static int printed_version;
+-	struct ata_port_info port;
+-	const struct ata_port_info *ppi[] = { &port, NULL };
++	const struct ata_port_info *ppi[] = { NULL, NULL };
+ 	struct pci_dev *host = NULL;
+ 	struct sis_chipset *chipset = NULL;
+ 	struct sis_chipset *sets;
++	int rc;
+ 
+ 	static struct sis_chipset sis_chipsets[] = {
+ 
+@@ -914,8 +734,11 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+ 			   "version " DRV_VERSION "\n");
+ 
+-	/* We have to find the bridge first */
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
+ 
++	/* We have to find the bridge first */
+ 	for (sets = &sis_chipsets[0]; sets->device; sets++) {
+ 		host = pci_get_device(PCI_VENDOR_ID_SI, sets->device, NULL);
+ 		if (host != NULL) {
+@@ -994,12 +817,11 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	if (chipset == NULL)
+ 		return -ENODEV;
+ 
+-	port = *chipset->info;
+-	port.private_data = chipset;
++	ppi[0] = chipset->info;
+ 
+ 	sis_fixup(pdev, chipset);
+ 
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &sis_sht, chipset);
+ }
+ 
+ static const struct pci_device_id sis_pci_tbl[] = {
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index 81ef207..70d94fb 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -60,13 +60,7 @@ static int sl82c105_pre_reset(struct ata_link *link, unsigned long deadline)
+ 
+ 	if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-
+-static void sl82c105_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, sl82c105_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ 
+@@ -235,55 +229,17 @@ static int sl82c105_qc_defer(struct ata_queued_cmd *qc)
+ }
+ 
+ static struct scsi_host_template sl82c105_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations sl82c105_port_ops = {
+-	.set_piomode	= sl82c105_set_piomode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= sl82c105_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
++	.inherits	= &ata_bmdma_port_ops,
++	.qc_defer	= sl82c105_qc_defer,
+ 	.bmdma_start 	= sl82c105_bmdma_start,
+ 	.bmdma_stop	= sl82c105_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_defer	= sl82c105_qc_defer,
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.cable_detect	= ata_cable_40wire,
++	.set_piomode	= sl82c105_set_piomode,
++	.prereset	= sl82c105_pre_reset,
+ };
+ 
+ /**
+@@ -327,14 +283,12 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info_dma = {
+-		.sht = &sl82c105_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+ 		.port_ops = &sl82c105_port_ops
+ 	};
+ 	static const struct ata_port_info info_early = {
+-		.sht = &sl82c105_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.port_ops = &sl82c105_port_ops
+@@ -344,6 +298,11 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ 					       NULL };
+ 	u32 val;
+ 	int rev;
++	int rc;
++
++	rc = pcim_enable_device(dev);
++	if (rc)
++		return rc;
+ 
+ 	rev = sl82c105_bridge_revision(dev);
+ 
+@@ -358,7 +317,7 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ 	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
+ 	pci_write_config_dword(dev, 0x40, val);
+ 
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &sl82c105_sht, NULL);
+ }
+ 
+ static const struct pci_device_id sl82c105[] = {
+diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
+index 403eafc..b181261 100644
+--- a/drivers/ata/pata_triflex.c
++++ b/drivers/ata/pata_triflex.c
+@@ -66,16 +66,11 @@ static int triflex_prereset(struct ata_link *link, unsigned long deadline)
+ 	if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no]))
+ 		return -ENOENT;
+ 
+-	return ata_std_prereset(link, deadline);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ 
+ 
+-static void triflex_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, triflex_prereset, ata_std_softreset, NULL, ata_std_postreset);
+-}
+-
+ /**
+  *	triflex_load_timing		-	timing configuration
+  *	@ap: ATA interface
+@@ -180,60 +175,21 @@ static void triflex_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+ 
+ static struct scsi_host_template triflex_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations triflex_port_ops = {
+-	.set_piomode	= triflex_set_piomode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= triflex_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_40wire,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
++	.inherits	= &ata_bmdma_port_ops,
+ 	.bmdma_start 	= triflex_bmdma_start,
+ 	.bmdma_stop	= triflex_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.cable_detect	= ata_cable_40wire,
++	.set_piomode	= triflex_set_piomode,
++	.prereset	= triflex_prereset,
+ };
+ 
+ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	static const struct ata_port_info info = {
+-		.sht = &triflex_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -245,7 +201,7 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+ 
+-	return ata_pci_init_one(dev, ppi);
++	return ata_pci_sff_init_one(dev, ppi, &triflex_sht, NULL);
+ }
+ 
+ static const struct pci_device_id triflex[] = {
+diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
+index d119a68..d484074 100644
+--- a/drivers/ata/pata_via.c
++++ b/drivers/ata/pata_via.c
+@@ -210,23 +210,11 @@ static int via_pre_reset(struct ata_link *link, unsigned long deadline)
+ 			return -ENOENT;
+ 	}
+ 
+-	return ata_std_prereset(link, deadline);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ 
+ /**
+- *	via_error_handler		-	reset for VIA chips
+- *	@ap: ATA port
+- *
+- *	Handle the reset callback for the later chips with cable detect
+- */
+-
+-static void via_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, via_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+-}
+-
+-/**
+  *	via_do_set_mode	-	set initial PIO mode data
+  *	@ap: ATA interface
+  *	@adev: ATA device
+@@ -335,89 +323,20 @@ static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+ 
+ static struct scsi_host_template via_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations via_port_ops = {
++	.inherits	= &ata_bmdma_port_ops,
++	.cable_detect	= via_cable_detect,
+ 	.set_piomode	= via_set_piomode,
+ 	.set_dmamode	= via_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= via_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= via_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.prereset	= via_pre_reset,
+ };
+ 
+ static struct ata_port_operations via_port_ops_noirq = {
+-	.set_piomode	= via_set_piomode,
+-	.set_dmamode	= via_set_dmamode,
+-	.mode_filter	= ata_pci_default_filter,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= via_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= via_cable_detect,
+-
+-	.bmdma_setup 	= ata_bmdma_setup,
+-	.bmdma_start 	= ata_bmdma_start,
+-	.bmdma_stop	= ata_bmdma_stop,
+-	.bmdma_status 	= ata_bmdma_status,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= ata_data_xfer_noirq,
+-
+-	.irq_handler	= ata_interrupt,
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.inherits	= &via_port_ops,
++	.sff_data_xfer	= ata_sff_data_xfer_noirq,
+ };
+ 
+ /**
+@@ -467,7 +386,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ 	/* Early VIA without UDMA support */
+ 	static const struct ata_port_info via_mwdma_info = {
+-		.sht = &via_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -475,7 +393,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* Ditto with IRQ masking required */
+ 	static const struct ata_port_info via_mwdma_info_borked = {
+-		.sht = &via_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -483,7 +400,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* VIA UDMA 33 devices (and borked 66) */
+ 	static const struct ata_port_info via_udma33_info = {
+-		.sht = &via_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -492,7 +408,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* VIA UDMA 66 devices */
+ 	static const struct ata_port_info via_udma66_info = {
+-		.sht = &via_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -501,7 +416,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* VIA UDMA 100 devices */
+ 	static const struct ata_port_info via_udma100_info = {
+-		.sht = &via_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+@@ -510,24 +424,27 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	};
+ 	/* UDMA133 with bad AST (All current 133) */
+ 	static const struct ata_port_info via_udma133_info = {
+-		.sht = &via_sht,
+ 		.flags = ATA_FLAG_SLAVE_POSS,
+ 		.pio_mask = 0x1f,
+ 		.mwdma_mask = 0x07,
+ 		.udma_mask = ATA_UDMA6,	/* FIXME: should check north bridge */
+ 		.port_ops = &via_port_ops
+ 	};
+-	struct ata_port_info type;
+-	const struct ata_port_info *ppi[] = { &type, NULL };
++	const struct ata_port_info *ppi[] = { NULL, NULL };
+ 	struct pci_dev *isa = NULL;
+ 	const struct via_isa_bridge *config;
+ 	static int printed_version;
+ 	u8 enable;
+ 	u32 timing;
++	int rc;
+ 
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ 
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
++
+ 	/* To find out how the IDE will behave and what features we
+ 	   actually have to look at the bridge not the IDE controller */
+ 	for (config = via_isa_bridges; config->id; config++)
+@@ -561,25 +478,25 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	switch(config->flags & VIA_UDMA) {
+ 		case VIA_UDMA_NONE:
+ 			if (config->flags & VIA_NO_UNMASK)
+-				type = via_mwdma_info_borked;
++				ppi[0] = &via_mwdma_info_borked;
+ 			else
+-				type = via_mwdma_info;
++				ppi[0] = &via_mwdma_info;
+ 			break;
+ 		case VIA_UDMA_33:
+-			type = via_udma33_info;
++			ppi[0] = &via_udma33_info;
+ 			break;
+ 		case VIA_UDMA_66:
+-			type = via_udma66_info;
++			ppi[0] = &via_udma66_info;
+ 			/* The 66 MHz devices require we enable the clock */
+ 			pci_read_config_dword(pdev, 0x50, &timing);
+ 			timing |= 0x80008;
+ 			pci_write_config_dword(pdev, 0x50, timing);
+ 			break;
+ 		case VIA_UDMA_100:
+-			type = via_udma100_info;
++			ppi[0] = &via_udma100_info;
+ 			break;
+ 		case VIA_UDMA_133:
+-			type = via_udma133_info;
++			ppi[0] = &via_udma133_info;
+ 			break;
+ 		default:
+ 			WARN_ON(1);
+@@ -594,9 +511,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	}
+ 
+ 	/* We have established the device type, now fire it up */
+-	type.private_data = (void *)config;
+-
+-	return ata_pci_init_one(pdev, ppi);
++	return ata_pci_sff_init_one(pdev, ppi, &via_sht, (void *)config);
+ }
+ 
+ #ifdef CONFIG_PM
+@@ -615,6 +530,11 @@ static int via_reinit_one(struct pci_dev *pdev)
+ 	u32 timing;
+ 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ 	const struct via_isa_bridge *config = host->private_data;
++	int rc;
++
++	rc = ata_pci_device_do_resume(pdev);
++	if (rc)
++		return rc;
+ 
+ 	via_config_fifo(pdev, config->flags);
+ 
+@@ -630,7 +550,9 @@ static int via_reinit_one(struct pci_dev *pdev)
+ 		timing &= ~0x80008;
+ 		pci_write_config_dword(pdev, 0x50, timing);
+ 	}
+-	return ata_pci_device_resume(pdev);
++
++	ata_host_resume(host);
++	return 0;
+ }
+ #endif
+ 
+diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
+index 99c92ed..6e52a35 100644
+--- a/drivers/ata/pata_winbond.c
++++ b/drivers/ata/pata_winbond.c
+@@ -116,53 +116,20 @@ static unsigned int winbond_data_xfer(struct ata_device *dev,
+ 			buflen += 4 - slop;
+ 		}
+ 	} else
+-		buflen = ata_data_xfer(dev, buf, buflen, rw);
++		buflen = ata_sff_data_xfer(dev, buf, buflen, rw);
+ 
+ 	return buflen;
+ }
+ 
+ static struct scsi_host_template winbond_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_PIO_SHT(DRV_NAME),
+ };
+ 
+ static struct ata_port_operations winbond_port_ops = {
+-	.set_piomode	= winbond_set_piomode,
+-
+-	.tf_load	= ata_tf_load,
+-	.tf_read	= ata_tf_read,
+-	.check_status 	= ata_check_status,
+-	.exec_command	= ata_exec_command,
+-	.dev_select 	= ata_std_dev_select,
+-
+-	.freeze		= ata_bmdma_freeze,
+-	.thaw		= ata_bmdma_thaw,
+-	.error_handler	= ata_bmdma_error_handler,
+-	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.inherits	= &ata_sff_port_ops,
++	.sff_data_xfer	= winbond_data_xfer,
+ 	.cable_detect	= ata_cable_40wire,
+-
+-	.qc_prep 	= ata_qc_prep,
+-	.qc_issue	= ata_qc_issue_prot,
+-
+-	.data_xfer	= winbond_data_xfer,
+-
+-	.irq_clear	= ata_bmdma_irq_clear,
+-	.irq_on		= ata_irq_on,
+-
+-	.port_start	= ata_sff_port_start,
++	.set_piomode	= winbond_set_piomode,
+ };
+ 
+ /**
+@@ -231,7 +198,7 @@ static __init int winbond_init_one(unsigned long port)
+ 		ap->ioaddr.cmd_addr = cmd_addr;
+ 		ap->ioaddr.altstatus_addr = ctl_addr;
+ 		ap->ioaddr.ctl_addr = ctl_addr;
+-		ata_std_ports(&ap->ioaddr);
++		ata_sff_std_ports(&ap->ioaddr);
+ 
+ 		/* hook in a private data structure per channel */
+ 		host->private_data = &winbond_data[nr_winbond_host];
+@@ -239,7 +206,7 @@ static __init int winbond_init_one(unsigned long port)
+ 		winbond_data[nr_winbond_host].platform_dev = pdev;
+ 
+ 		/* activate */
+-		rc = ata_host_activate(host, 14 + i, ata_interrupt, 0,
++		rc = ata_host_activate(host, 14 + i, ata_sff_interrupt, 0,
+ 				       &winbond_sht);
+ 		if (rc)
+ 			goto err_unregister;
+diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
+index 8e1b7e9..be53545 100644
+--- a/drivers/ata/pdc_adma.c
++++ b/drivers/ata/pdc_adma.c
+@@ -131,56 +131,33 @@ struct adma_port_priv {
+ static int adma_ata_init_one(struct pci_dev *pdev,
+ 				const struct pci_device_id *ent);
+ static int adma_port_start(struct ata_port *ap);
+-static void adma_host_stop(struct ata_host *host);
+ static void adma_port_stop(struct ata_port *ap);
+ static void adma_qc_prep(struct ata_queued_cmd *qc);
+ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
+ static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
+-static void adma_bmdma_stop(struct ata_queued_cmd *qc);
+-static u8 adma_bmdma_status(struct ata_port *ap);
+-static void adma_irq_clear(struct ata_port *ap);
+ static void adma_freeze(struct ata_port *ap);
+ static void adma_thaw(struct ata_port *ap);
+-static void adma_error_handler(struct ata_port *ap);
++static int adma_prereset(struct ata_link *link, unsigned long deadline);
+ 
+ static struct scsi_host_template adma_ata_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+-	.proc_name		= DRV_NAME,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
++	ATA_BASE_SHT(DRV_NAME),
+ 	.sg_tablesize		= LIBATA_MAX_PRD,
+ 	.dma_boundary		= ADMA_DMA_BOUNDARY,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.use_clustering		= ENABLE_CLUSTERING,
+-	.emulated		= ATA_SHT_EMULATED,
+ };
+ 
+-static const struct ata_port_operations adma_ata_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.exec_command		= ata_exec_command,
+-	.check_status		= ata_check_status,
+-	.dev_select		= ata_std_dev_select,
++static struct ata_port_operations adma_ata_ops = {
++	.inherits		= &ata_sff_port_ops,
++
+ 	.check_atapi_dma	= adma_check_atapi_dma,
+-	.data_xfer		= ata_data_xfer,
+ 	.qc_prep		= adma_qc_prep,
+ 	.qc_issue		= adma_qc_issue,
++
+ 	.freeze			= adma_freeze,
+ 	.thaw			= adma_thaw,
+-	.error_handler		= adma_error_handler,
+-	.irq_clear		= adma_irq_clear,
+-	.irq_on			= ata_irq_on,
++	.prereset		= adma_prereset,
++
+ 	.port_start		= adma_port_start,
+ 	.port_stop		= adma_port_stop,
+-	.host_stop		= adma_host_stop,
+-	.bmdma_stop		= adma_bmdma_stop,
+-	.bmdma_status		= adma_bmdma_status,
+ };
+ 
+ static struct ata_port_info adma_port_info[] = {
+@@ -213,21 +190,6 @@ static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
+ 	return 1;	/* ATAPI DMA not yet supported */
+ }
+ 
+-static void adma_bmdma_stop(struct ata_queued_cmd *qc)
+-{
+-	/* nothing */
+-}
+-
+-static u8 adma_bmdma_status(struct ata_port *ap)
+-{
+-	return 0;
+-}
+-
+-static void adma_irq_clear(struct ata_port *ap)
+-{
+-	/* nothing */
+-}
+-
+ static void adma_reset_engine(struct ata_port *ap)
+ {
+ 	void __iomem *chan = ADMA_PORT_REGS(ap);
+@@ -246,7 +208,7 @@ static void adma_reinit_engine(struct ata_port *ap)
+ 
+ 	/* mask/clear ATA interrupts */
+ 	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
+-	ata_check_status(ap);
++	ata_sff_check_status(ap);
+ 
+ 	/* reset the ADMA engine */
+ 	adma_reset_engine(ap);
+@@ -281,7 +243,7 @@ static void adma_freeze(struct ata_port *ap)
+ 
+ 	/* mask/clear ATA interrupts */
+ 	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
+-	ata_check_status(ap);
++	ata_sff_check_status(ap);
+ 
+ 	/* reset ADMA to idle state */
+ 	writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
+@@ -304,13 +266,7 @@ static int adma_prereset(struct ata_link *link, unsigned long deadline)
+ 		pp->state = adma_state_mmio;
+ 	adma_reinit_engine(ap);
+ 
+-	return ata_std_prereset(link, deadline);
+-}
+-
+-static void adma_error_handler(struct ata_port *ap)
+-{
+-	ata_do_eh(ap, adma_prereset, ata_std_softreset, NULL,
+-		  ata_std_postreset);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ static int adma_fill_sg(struct ata_queued_cmd *qc)
+@@ -366,7 +322,7 @@ static void adma_qc_prep(struct ata_queued_cmd *qc)
+ 
+ 	adma_enter_reg_mode(qc->ap);
+ 	if (qc->tf.protocol != ATA_PROT_DMA) {
+-		ata_qc_prep(qc);
++		ata_sff_qc_prep(qc);
+ 		return;
+ 	}
+ 
+@@ -465,7 +421,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
+ 	}
+ 
+ 	pp->state = adma_state_mmio;
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static inline unsigned int adma_intr_pkt(struct ata_host *host)
+@@ -536,7 +492,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host *host)
+ 			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
+ 
+ 				/* check main status, clearing INTRQ */
+-				u8 status = ata_check_status(ap);
++				u8 status = ata_sff_check_status(ap);
+ 				if ((status & ATA_BUSY))
+ 					continue;
+ 				DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+@@ -633,14 +589,6 @@ static void adma_port_stop(struct ata_port *ap)
+ 	adma_reset_engine(ap);
+ }
+ 
+-static void adma_host_stop(struct ata_host *host)
+-{
+-	unsigned int port_no;
+-
+-	for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+-		adma_reset_engine(host->ports[port_no]);
+-}
+-
+ static void adma_host_init(struct ata_host *host, unsigned int chip_id)
+ {
+ 	unsigned int port_no;
+diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
+index 9d1e3ca..fddd346 100644
+--- a/drivers/ata/sata_fsl.c
++++ b/drivers/ata/sata_fsl.c
+@@ -35,7 +35,6 @@ enum {
+ 	SATA_FSL_HOST_FLAGS	= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ 				ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ 				ATA_FLAG_NCQ),
+-	SATA_FSL_HOST_LFLAGS	= ATA_LFLAG_SKIP_D2H_BSY,
+ 
+ 	SATA_FSL_MAX_CMDS	= SATA_FSL_QUEUE_DEPTH,
+ 	SATA_FSL_CMD_HDR_SIZE	= 16,	/* 4 DWORDS */
+@@ -245,17 +244,6 @@ struct sata_fsl_port_priv {
+ 	dma_addr_t cmdslot_paddr;
+ 	struct command_desc *cmdentry;
+ 	dma_addr_t cmdentry_paddr;
+-
+-	/*
+-	 * SATA FSL controller has a Status FIS which should contain the
+-	 * received D2H FIS & taskfile registers. This SFIS is present in
+-	 * the command descriptor, and to have a ready reference to it,
+-	 * we are caching it here, quite similar to what is done in H/W on
+-	 * AHCI compliant devices by copying taskfile fields to a 32-bit
+-	 * register.
+-	 */
+-
+-	struct ata_taskfile tf;
+ };
+ 
+ /*
+@@ -465,6 +453,20 @@ static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc)
+ 	return 0;
+ }
+ 
++static bool sata_fsl_qc_fill_rtf(struct ata_queued_cmd *qc)
++{
++	struct sata_fsl_port_priv *pp = qc->ap->private_data;
++	struct sata_fsl_host_priv *host_priv = qc->ap->host->private_data;
++	void __iomem *hcr_base = host_priv->hcr_base;
++	unsigned int tag = sata_fsl_tag(qc->tag, hcr_base);
++	struct command_desc *cd;
++
++	cd = pp->cmdentry + tag;
++
++	ata_tf_from_fis(cd->sfis, &qc->result_tf);
++	return true;
++}
++
+ static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
+ 			       u32 val)
+ {
+@@ -556,38 +558,6 @@ static void sata_fsl_thaw(struct ata_port *ap)
+ 		ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS));
+ }
+ 
+-/*
+- * NOTE : 1st D2H FIS from device does not update sfis in command descriptor.
+- */
+-static inline void sata_fsl_cache_taskfile_from_d2h_fis(struct ata_queued_cmd
+-							*qc,
+-							struct ata_port *ap)
+-{
+-	struct sata_fsl_port_priv *pp = ap->private_data;
+-	struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+-	void __iomem *hcr_base = host_priv->hcr_base;
+-	unsigned int tag = sata_fsl_tag(qc->tag, hcr_base);
+-	struct command_desc *cd;
+-
+-	cd = pp->cmdentry + tag;
+-
+-	ata_tf_from_fis(cd->sfis, &pp->tf);
+-}
+-
+-static u8 sata_fsl_check_status(struct ata_port *ap)
+-{
+-	struct sata_fsl_port_priv *pp = ap->private_data;
+-
+-	return pp->tf.command;
+-}
+-
+-static void sata_fsl_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+-	struct sata_fsl_port_priv *pp = ap->private_data;
+-
+-	*tf = pp->tf;
+-}
+-
+ static int sata_fsl_port_start(struct ata_port *ap)
+ {
+ 	struct device *dev = ap->host->dev;
+@@ -708,6 +678,15 @@ static unsigned int sata_fsl_dev_classify(struct ata_port *ap)
+ 	return ata_dev_classify(&tf);
+ }
+ 
++static int sata_fsl_prereset(struct ata_linke *link, unsigned long deadline)
++{
++	/* FIXME: Never skip softreset, sata_fsl_softreset() is
++	 * combination of soft and hard resets.  sata_fsl_softreset()
++	 * needs to be splitted into soft and hard resets.
++	 */
++	return 0;
++}
++
+ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
+ 			      unsigned long deadline)
+ {
+@@ -913,16 +892,6 @@ err:
+ 	return -EIO;
+ }
+ 
+-static void sata_fsl_error_handler(struct ata_port *ap)
+-{
+-
+-	DPRINTK("in xx_error_handler\n");
+-
+-	/* perform recovery */
+-	ata_do_eh(ap, ata_std_prereset, sata_fsl_softreset, sata_std_hardreset,
+-		  ata_std_postreset);
+-}
+-
+ static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
+ {
+ 	if (qc->flags & ATA_QCFLAG_FAILED)
+@@ -934,11 +903,6 @@ static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
+ 	}
+ }
+ 
+-static void sata_fsl_irq_clear(struct ata_port *ap)
+-{
+-	/* unused */
+-}
+-
+ static void sata_fsl_error_intr(struct ata_port *ap)
+ {
+ 	struct ata_link *link = &ap->link;
+@@ -996,7 +960,7 @@ static void sata_fsl_error_intr(struct ata_port *ap)
+ 	/* handle fatal errors */
+ 	if (hstatus & FATAL_ERROR_DECODE) {
+ 		err_mask |= AC_ERR_ATA_BUS;
+-		action |= ATA_EH_SOFTRESET;
++		action |= ATA_EH_RESET;
+ 		/* how will fatal error interrupts be completed ?? */
+ 		freeze = 1;
+ 	}
+@@ -1013,10 +977,9 @@ static void sata_fsl_error_intr(struct ata_port *ap)
+ 	/* record error info */
+ 	qc = ata_qc_from_tag(ap, link->active_tag);
+ 
+-	if (qc) {
+-		sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap);
++	if (qc)
+ 		qc->err_mask |= err_mask;
+-	} else
++	else
+ 		ehi->err_mask |= err_mask;
+ 
+ 	ehi->action |= action;
+@@ -1029,14 +992,6 @@ static void sata_fsl_error_intr(struct ata_port *ap)
+ 		ata_port_abort(ap);
+ }
+ 
+-static void sata_fsl_qc_complete(struct ata_queued_cmd *qc)
+-{
+-	if (qc->flags & ATA_QCFLAG_RESULT_TF) {
+-		DPRINTK("xx_qc_complete called\n");
+-		sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap);
+-	}
+-}
+-
+ static void sata_fsl_host_intr(struct ata_port *ap)
+ {
+ 	struct ata_link *link = &ap->link;
+@@ -1077,10 +1032,8 @@ static void sata_fsl_host_intr(struct ata_port *ap)
+ 		for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
+ 			if (qc_active & (1 << i)) {
+ 				qc = ata_qc_from_tag(ap, i);
+-				if (qc) {
+-					sata_fsl_qc_complete(qc);
++				if (qc)
+ 					ata_qc_complete(qc);
+-				}
+ 				DPRINTK
+ 				    ("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
+ 				     i, ioread32(hcr_base + CC),
+@@ -1096,10 +1049,8 @@ static void sata_fsl_host_intr(struct ata_port *ap)
+ 		DPRINTK("completing non-ncq cmd, tag=%d,CC=0x%x\n",
+ 			link->active_tag, ioread32(hcr_base + CC));
+ 
+-		if (qc) {
+-			sata_fsl_qc_complete(qc);
++		if (qc)
+ 			ata_qc_complete(qc);
+-		}
+ 	} else {
+ 		/* Spurious Interrupt!! */
+ 		DPRINTK("spurious interrupt!!, CC = 0x%x\n",
+@@ -1197,41 +1148,26 @@ static int sata_fsl_init_controller(struct ata_host *host)
+  * scsi mid-layer and libata interface structures
+  */
+ static struct scsi_host_template sata_fsl_sht = {
+-	.module = THIS_MODULE,
+-	.name = "sata_fsl",
+-	.ioctl = ata_scsi_ioctl,
+-	.queuecommand = ata_scsi_queuecmd,
+-	.change_queue_depth = ata_scsi_change_queue_depth,
++	ATA_NCQ_SHT("sata_fsl"),
+ 	.can_queue = SATA_FSL_QUEUE_DEPTH,
+-	.this_id = ATA_SHT_THIS_ID,
+ 	.sg_tablesize = SATA_FSL_MAX_PRD_USABLE,
+-	.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+-	.emulated = ATA_SHT_EMULATED,
+-	.use_clustering = ATA_SHT_USE_CLUSTERING,
+-	.proc_name = "sata_fsl",
+ 	.dma_boundary = ATA_DMA_BOUNDARY,
+-	.slave_configure = ata_scsi_slave_config,
+-	.slave_destroy = ata_scsi_slave_destroy,
+-	.bios_param = ata_std_bios_param,
+ };
+ 
+ static const struct ata_port_operations sata_fsl_ops = {
+-	.check_status = sata_fsl_check_status,
+-	.check_altstatus = sata_fsl_check_status,
+-	.dev_select = ata_noop_dev_select,
+-
+-	.tf_read = sata_fsl_tf_read,
++	.inherits = &sata_port_ops,
+ 
+ 	.qc_prep = sata_fsl_qc_prep,
+ 	.qc_issue = sata_fsl_qc_issue,
+-	.irq_clear = sata_fsl_irq_clear,
++	.qc_fill_rtf = sata_fsl_qc_fill_rtf,
+ 
+ 	.scr_read = sata_fsl_scr_read,
+ 	.scr_write = sata_fsl_scr_write,
+ 
+ 	.freeze = sata_fsl_freeze,
+ 	.thaw = sata_fsl_thaw,
+-	.error_handler = sata_fsl_error_handler,
++	.prereset = sata_fsl_prereset,
++	.softreset = sata_fsl_softreset,
+ 	.post_internal_cmd = sata_fsl_post_internal_cmd,
+ 
+ 	.port_start = sata_fsl_port_start,
+@@ -1241,7 +1177,6 @@ static const struct ata_port_operations sata_fsl_ops = {
+ static const struct ata_port_info sata_fsl_port_info[] = {
+ 	{
+ 	 .flags = SATA_FSL_HOST_FLAGS,
+-	 .link_flags = SATA_FSL_HOST_LFLAGS,
+ 	 .pio_mask = 0x1f,	/* pio 0-4 */
+ 	 .udma_mask = 0x7f,	/* udma 0-6 */
+ 	 .port_ops = &sata_fsl_ops,
+@@ -1297,11 +1232,6 @@ static int sata_fsl_probe(struct of_device *ofdev,
+ 	/* host->iomap is not used currently */
+ 	host->private_data = host_priv;
+ 
+-	/* setup port(s) */
+-
+-	host->ports[0]->ioaddr.cmd_addr = host_priv->hcr_base;
+-	host->ports[0]->ioaddr.scr_addr = host_priv->ssr_base;
+-
+ 	/* initialize host controller */
+ 	sata_fsl_init_controller(host);
+ 
+diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
+index 59e65ed..d27bb9a 100644
+--- a/drivers/ata/sata_inic162x.c
++++ b/drivers/ata/sata_inic162x.c
+@@ -109,21 +109,7 @@ struct inic_port_priv {
+ };
+ 
+ static struct scsi_host_template inic_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static const int scr_map[] = {
+@@ -236,7 +222,7 @@ static void inic_bmdma_setup(struct ata_queued_cmd *qc)
+ 	writeb(pp->cached_prdctl, port_base + PORT_PRD_CTL);
+ 
+ 	/* issue r/w command */
+-	ap->ops->exec_command(ap, &qc->tf);
++	ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+ 
+ static void inic_bmdma_start(struct ata_queued_cmd *qc)
+@@ -266,11 +252,6 @@ static u8 inic_bmdma_status(struct ata_port *ap)
+ 	return ATA_DMA_INTR;
+ }
+ 
+-static void inic_irq_clear(struct ata_port *ap)
+-{
+-	/* noop */
+-}
+-
+ static void inic_host_intr(struct ata_port *ap)
+ {
+ 	void __iomem *port_base = inic_port_base(ap);
+@@ -286,14 +267,14 @@ static void inic_host_intr(struct ata_port *ap)
+ 			ata_qc_from_tag(ap, ap->link.active_tag);
+ 
+ 		if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
+-			ata_chk_status(ap);	/* clear ATA interrupt */
++			ap->ops->sff_check_status(ap); /* clear ATA interrupt */
+ 			return;
+ 		}
+ 
+-		if (likely(ata_host_intr(ap, qc)))
++		if (likely(ata_sff_host_intr(ap, qc)))
+ 			return;
+ 
+-		ata_chk_status(ap);	/* clear ATA interrupt */
++		ap->ops->sff_check_status(ap); /* clear ATA interrupt */
+ 		ata_port_printk(ap, KERN_WARNING, "unhandled "
+ 				"interrupt, irq_stat=%x\n", irq_stat);
+ 		return;
+@@ -370,12 +351,12 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
+ 	 */
+ 	if (unlikely(qc->tf.command == ATA_CMD_ID_ATA ||
+ 		     qc->tf.command == ATA_CMD_ID_ATAPI)) {
+-		u8 stat = ata_chk_status(ap);
++		u8 stat = ap->ops->sff_check_status(ap);
+ 		if (stat == 0x7f || stat == 0xff)
+ 			return AC_ERR_HSM;
+ 	}
+ 
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static void inic_freeze(struct ata_port *ap)
+@@ -384,7 +365,7 @@ static void inic_freeze(struct ata_port *ap)
+ 
+ 	__inic_set_pirq_mask(ap, PIRQ_MASK_FREEZE);
+ 
+-	ata_chk_status(ap);
++	ap->ops->sff_check_status(ap);
+ 	writeb(0xff, port_base + PORT_IRQ_STAT);
+ 
+ 	readb(port_base + PORT_IRQ_STAT); /* flush */
+@@ -394,7 +375,7 @@ static void inic_thaw(struct ata_port *ap)
+ {
+ 	void __iomem *port_base = inic_port_base(ap);
+ 
+-	ata_chk_status(ap);
++	ap->ops->sff_check_status(ap);
+ 	writeb(0xff, port_base + PORT_IRQ_STAT);
+ 
+ 	__inic_set_pirq_mask(ap, PIRQ_MASK_OTHER);
+@@ -436,10 +417,8 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
+ 	if (ata_link_online(link)) {
+ 		struct ata_taskfile tf;
+ 
+-		/* wait a while before checking status */
+-		ata_wait_after_reset(ap, deadline);
+-
+-		rc = ata_wait_ready(ap, deadline);
++		/* wait for link to become ready */
++		rc = ata_sff_wait_after_reset(link, 1, deadline);
+ 		/* link occupied, -ENODEV too is an error */
+ 		if (rc) {
+ 			ata_link_printk(link, KERN_WARNING, "device not ready "
+@@ -447,10 +426,8 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
+ 			return rc;
+ 		}
+ 
+-		ata_tf_read(ap, &tf);
++		ata_sff_tf_read(ap, &tf);
+ 		*class = ata_dev_classify(&tf);
+-		if (*class == ATA_DEV_UNKNOWN)
+-			*class = ATA_DEV_NONE;
+ 	}
+ 
+ 	return 0;
+@@ -471,8 +448,7 @@ static void inic_error_handler(struct ata_port *ap)
+ 	spin_unlock_irqrestore(ap->lock, flags);
+ 
+ 	/* PIO and DMA engines have been stopped, perform recovery */
+-	ata_do_eh(ap, ata_std_prereset, NULL, inic_hardreset,
+-		  ata_std_postreset);
++	ata_std_error_handler(ap);
+ }
+ 
+ static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
+@@ -541,35 +517,26 @@ static int inic_port_start(struct ata_port *ap)
+ }
+ 
+ static struct ata_port_operations inic_port_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.scr_read		= inic_scr_read,
+-	.scr_write		= inic_scr_write,
++	.inherits		= &ata_sff_port_ops,
+ 
+ 	.bmdma_setup		= inic_bmdma_setup,
+ 	.bmdma_start		= inic_bmdma_start,
+ 	.bmdma_stop		= inic_bmdma_stop,
+ 	.bmdma_status		= inic_bmdma_status,
+-
+-	.irq_clear		= inic_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.qc_prep	 	= ata_qc_prep,
+ 	.qc_issue		= inic_qc_issue,
+-	.data_xfer		= ata_data_xfer,
+ 
+ 	.freeze			= inic_freeze,
+ 	.thaw			= inic_thaw,
++	.softreset		= ATA_OP_NULL,	/* softreset is broken */
++	.hardreset		= inic_hardreset,
+ 	.error_handler		= inic_error_handler,
+ 	.post_internal_cmd	= inic_post_internal_cmd,
+ 	.dev_config		= inic_dev_config,
+ 
+-	.port_resume		= inic_port_resume,
++	.scr_read		= inic_scr_read,
++	.scr_write		= inic_scr_write,
+ 
++	.port_resume		= inic_port_resume,
+ 	.port_start		= inic_port_start,
+ };
+ 
+@@ -692,7 +659,7 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 			((unsigned long)iomap[2 * i + 1] | ATA_PCI_CTL_OFS);
+ 		port->scr_addr = iomap[MMIO_BAR] + offset + PORT_SCR;
+ 
+-		ata_std_ports(port);
++		ata_sff_std_ports(port);
+ 
+ 		ata_port_pbar_desc(ap, MMIO_BAR, -1, "mmio");
+ 		ata_port_pbar_desc(ap, MMIO_BAR, offset, "port");
+diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
+index 6ebebde..26a6337 100644
+--- a/drivers/ata/sata_mv.c
++++ b/drivers/ata/sata_mv.c
+@@ -1,6 +1,7 @@
+ /*
+  * sata_mv.c - Marvell SATA support
+  *
++ * Copyright 2008: Marvell Corporation, all rights reserved.
+  * Copyright 2005: EMC Corporation, all rights reserved.
+  * Copyright 2005 Red Hat, Inc.  All rights reserved.
+  *
+@@ -22,45 +23,34 @@
+  */
+ 
+ /*
+-  sata_mv TODO list:
+-
+-  1) Needs a full errata audit for all chipsets.  I implemented most
+-  of the errata workarounds found in the Marvell vendor driver, but
+-  I distinctly remember a couple workarounds (one related to PCI-X)
+-  are still needed.
+-
+-  2) Improve/fix IRQ and error handling sequences.
+-
+-  3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
+-
+-  4) Think about TCQ support here, and for libata in general
+-  with controllers that suppport it via host-queuing hardware
+-  (a software-only implementation could be a nightmare).
+-
+-  5) Investigate problems with PCI Message Signalled Interrupts (MSI).
+-
+-  6) Add port multiplier support (intermediate)
+-
+-  8) Develop a low-power-consumption strategy, and implement it.
+-
+-  9) [Experiment, low priority] See if ATAPI can be supported using
+-  "unknown FIS" or "vendor-specific FIS" support, or something creative
+-  like that.
+-
+-  10) [Experiment, low priority] Investigate interrupt coalescing.
+-  Quite often, especially with PCI Message Signalled Interrupts (MSI),
+-  the overhead reduced by interrupt mitigation is quite often not
+-  worth the latency cost.
+-
+-  11) [Experiment, Marvell value added] Is it possible to use target
+-  mode to cross-connect two Linux boxes with Marvell cards?  If so,
+-  creating LibATA target mode support would be very interesting.
+-
+-  Target mode, for those without docs, is the ability to directly
+-  connect two SATA controllers.
+-
+-*/
+-
++ * sata_mv TODO list:
++ *
++ * --> Errata workaround for NCQ device errors.
++ *
++ * --> More errata workarounds for PCI-X.
++ *
++ * --> Complete a full errata audit for all chipsets to identify others.
++ *
++ * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it).
++ *
++ * --> Investigate problems with PCI Message Signalled Interrupts (MSI).
++ *
++ * --> Cache frequently-accessed registers in mv_port_priv to reduce overhead.
++ *
++ * --> Develop a low-power-consumption strategy, and implement it.
++ *
++ * --> [Experiment, low priority] Investigate interrupt coalescing.
++ *       Quite often, especially with PCI Message Signalled Interrupts (MSI),
++ *       the overhead reduced by interrupt mitigation is quite often not
++ *       worth the latency cost.
++ *
++ * --> [Experiment, Marvell value added] Is it possible to use target
++ *       mode to cross-connect two Linux boxes with Marvell cards?  If so,
++ *       creating LibATA target mode support would be very interesting.
++ *
++ *       Target mode, for those without docs, is the ability to directly
++ *       connect two SATA ports.
++ */
+ 
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -74,6 +64,7 @@
+ #include <linux/device.h>
+ #include <linux/platform_device.h>
+ #include <linux/ata_platform.h>
++#include <linux/mbus.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_device.h>
+@@ -121,17 +112,17 @@ enum {
+ 	MV_MAX_SG_CT		= 256,
+ 	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
+ 
+-	MV_PORTS_PER_HC		= 4,
+-	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
++	/* Determine hc from 0-7 port: hc = port >> MV_PORT_HC_SHIFT */
+ 	MV_PORT_HC_SHIFT	= 2,
+-	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
+-	MV_PORT_MASK		= 3,
++	MV_PORTS_PER_HC		= (1 << MV_PORT_HC_SHIFT), /* 4 */
++	/* Determine hc port from 0-7 port: hardport = port & MV_PORT_MASK */
++	MV_PORT_MASK		= (MV_PORTS_PER_HC - 1),   /* 3 */
+ 
+ 	/* Host Flags */
+ 	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
+ 	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
+ 	/* SoC integrated controllers, no PCI interface */
+-	MV_FLAG_SOC = (1 << 28),
++	MV_FLAG_SOC		= (1 << 28),
+ 
+ 	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ 				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+@@ -141,6 +132,7 @@ enum {
+ 	CRQB_FLAG_READ		= (1 << 0),
+ 	CRQB_TAG_SHIFT		= 1,
+ 	CRQB_IOID_SHIFT		= 6,	/* CRQB Gen-II/IIE IO Id shift */
++	CRQB_PMP_SHIFT		= 12,	/* CRQB Gen-II/IIE PMP shift */
+ 	CRQB_HOSTQ_SHIFT	= 17,	/* CRQB Gen-II/IIE HostQueTag shift */
+ 	CRQB_CMD_ADDR_SHIFT	= 8,
+ 	CRQB_CMD_CS		= (0x2 << 11),
+@@ -184,8 +176,8 @@ enum {
+ 	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
+ 	HC_SOC_MAIN_IRQ_CAUSE_OFS = 0x20020,
+ 	HC_SOC_MAIN_IRQ_MASK_OFS = 0x20024,
+-	PORT0_ERR		= (1 << 0),	/* shift by port # */
+-	PORT0_DONE		= (1 << 1),	/* shift by port # */
++	ERR_IRQ			= (1 << 0),	/* shift by port # */
++	DONE_IRQ		= (1 << 1),	/* shift by port # */
+ 	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
+ 	HC_SHIFT		= 9,		/* bits 9-17 = HC1's ports */
+ 	PCI_ERR			= (1 << 18),
+@@ -199,8 +191,9 @@ enum {
+ 	TWSI_INT		= (1 << 24),
+ 	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
+ 	HC_MAIN_RSVD_5		= (0x1fff << 19), /* bits 31-19 */
+-	HC_MAIN_RSVD_SOC 	= (0x3fffffb << 6),     /* bits 31-9, 7-6 */
++	HC_MAIN_RSVD_SOC	= (0x3fffffb << 6),     /* bits 31-9, 7-6 */
+ 	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
++				   PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
+ 				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
+ 				   HC_MAIN_RSVD),
+ 	HC_MAIN_MASKED_IRQS_5	= (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
+@@ -211,8 +204,8 @@ enum {
+ 	HC_CFG_OFS		= 0,
+ 
+ 	HC_IRQ_CAUSE_OFS	= 0x14,
+-	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
+-	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
++	DMA_IRQ			= (1 << 0),	/* shift by port # */
++	HC_COAL_IRQ		= (1 << 4),	/* IRQ coalescing */
+ 	DEV_IRQ			= (1 << 8),	/* shift by port # */
+ 
+ 	/* Shadow block registers */
+@@ -223,13 +216,24 @@ enum {
+ 	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
+ 	SATA_ACTIVE_OFS		= 0x350,
+ 	SATA_FIS_IRQ_CAUSE_OFS	= 0x364,
++
++	LTMODE_OFS		= 0x30c,
++	LTMODE_BIT8		= (1 << 8),	/* unknown, but necessary */
++
+ 	PHY_MODE3		= 0x310,
+ 	PHY_MODE4		= 0x314,
+ 	PHY_MODE2		= 0x330,
++	SATA_IFCTL_OFS		= 0x344,
++	SATA_IFSTAT_OFS		= 0x34c,
++	VENDOR_UNIQUE_FIS_OFS	= 0x35c,
++
++	FIS_CFG_OFS		= 0x360,
++	FIS_CFG_SINGLE_SYNC	= (1 << 16),	/* SYNC on DMA activation */
++
+ 	MV5_PHY_MODE		= 0x74,
+ 	MV5_LT_MODE		= 0x30,
+ 	MV5_PHY_CTL		= 0x0C,
+-	SATA_INTERFACE_CTL	= 0x050,
++	SATA_INTERFACE_CFG	= 0x050,
+ 
+ 	MV_M2_PREAMP_MASK	= 0x7e0,
+ 
+@@ -240,6 +244,8 @@ enum {
+ 	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),	/* continue on error */
+ 	EDMA_CFG_RD_BRST_EXT	= (1 << 11),	/* read burst 512B */
+ 	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),	/* write buffer 512B */
++	EDMA_CFG_EDMA_FBS	= (1 << 16),	/* EDMA FIS-Based Switching */
++	EDMA_CFG_FBS		= (1 << 26),	/* FIS-Based Switching */
+ 
+ 	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
+ 	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
+@@ -298,6 +304,7 @@ enum {
+ 				  EDMA_ERR_LNK_DATA_RX |
+ 				  EDMA_ERR_LNK_DATA_TX |
+ 				  EDMA_ERR_TRANS_PROTO,
++
+ 	EDMA_EH_FREEZE_5	= EDMA_ERR_D_PAR |
+ 				  EDMA_ERR_PRD_PAR |
+ 				  EDMA_ERR_DEV_DCON |
+@@ -329,6 +336,8 @@ enum {
+ 	EDMA_IORDY_TMOUT	= 0x34,
+ 	EDMA_ARB_CFG		= 0x38,
+ 
++	GEN_II_NCQ_MAX_SECTORS	= 256,		/* max sects/io on Gen2 w/NCQ */
++
+ 	/* Host private flags (hp_flags) */
+ 	MV_HP_FLAG_MSI		= (1 << 0),
+ 	MV_HP_ERRATA_50XXB0	= (1 << 1),
+@@ -344,7 +353,6 @@ enum {
+ 	/* Port private flags (pp_flags) */
+ 	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */
+ 	MV_PP_FLAG_NCQ_EN	= (1 << 1),	/* is EDMA set up for NCQ? */
+-	MV_PP_FLAG_HAD_A_RESET	= (1 << 2),	/* 1st hard reset complete? */
+ };
+ 
+ #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
+@@ -352,6 +360,9 @@ enum {
+ #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
+ #define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
+ 
++#define WINDOW_CTRL(i)		(0x20030 + ((i) << 4))
++#define WINDOW_BASE(i)		(0x20034 + ((i) << 4))
++
+ enum {
+ 	/* DMA boundary 0xffff is required by the s/g splitting
+ 	 * we need on /length/ in mv_fill-sg().
+@@ -461,7 +472,6 @@ struct mv_hw_ops {
+ 	void (*reset_bus)(struct ata_host *host, void __iomem *mmio);
+ };
+ 
+-static void mv_irq_clear(struct ata_port *ap);
+ static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
+ static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+ static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
+@@ -471,7 +481,8 @@ static void mv_port_stop(struct ata_port *ap);
+ static void mv_qc_prep(struct ata_queued_cmd *qc);
+ static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
+ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
+-static void mv_error_handler(struct ata_port *ap);
++static int mv_hardreset(struct ata_link *link, unsigned int *class,
++			unsigned long deadline);
+ static void mv_eh_freeze(struct ata_port *ap);
+ static void mv_eh_thaw(struct ata_port *ap);
+ static void mv6_dev_config(struct ata_device *dev);
+@@ -504,72 +515,46 @@ static void mv_soc_reset_flash(struct mv_host_priv *hpriv,
+ 				      void __iomem *mmio);
+ static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio);
+ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio);
+-static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
++static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 			     unsigned int port_no);
+-static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
+-			void __iomem *port_mmio, int want_ncq);
+-static int __mv_stop_dma(struct ata_port *ap);
++static int mv_stop_edma(struct ata_port *ap);
++static int mv_stop_edma_engine(void __iomem *port_mmio);
++static void mv_edma_cfg(struct ata_port *ap, int want_ncq);
++
++static void mv_pmp_select(struct ata_port *ap, int pmp);
++static int mv_pmp_hardreset(struct ata_link *link, unsigned int *class,
++				unsigned long deadline);
++static int  mv_softreset(struct ata_link *link, unsigned int *class,
++				unsigned long deadline);
+ 
+ /* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
+  * because we have to allow room for worst case splitting of
+  * PRDs for 64K boundaries in mv_fill_sg().
+  */
+ static struct scsi_host_template mv5_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
++	ATA_BASE_SHT(DRV_NAME),
+ 	.sg_tablesize		= MV_MAX_SG_CT / 2,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= 1,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= MV_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+ static struct scsi_host_template mv6_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.change_queue_depth	= ata_scsi_change_queue_depth,
++	ATA_NCQ_SHT(DRV_NAME),
+ 	.can_queue		= MV_MAX_Q_DEPTH - 1,
+-	.this_id		= ATA_SHT_THIS_ID,
+ 	.sg_tablesize		= MV_MAX_SG_CT / 2,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= 1,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= MV_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+-static const struct ata_port_operations mv5_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.cable_detect		= ata_cable_sata,
++static struct ata_port_operations mv5_ops = {
++	.inherits		= &ata_sff_port_ops,
+ 
+ 	.qc_prep		= mv_qc_prep,
+ 	.qc_issue		= mv_qc_issue,
+-	.data_xfer		= ata_data_xfer,
+ 
+-	.irq_clear		= mv_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.error_handler		= mv_error_handler,
+ 	.freeze			= mv_eh_freeze,
+ 	.thaw			= mv_eh_thaw,
++	.hardreset		= mv_hardreset,
++	.error_handler		= ata_std_error_handler, /* avoid SFF EH */
++	.post_internal_cmd	= ATA_OP_NULL,
+ 
+ 	.scr_read		= mv5_scr_read,
+ 	.scr_write		= mv5_scr_write,
+@@ -578,61 +563,24 @@ static const struct ata_port_operations mv5_ops = {
+ 	.port_stop		= mv_port_stop,
+ };
+ 
+-static const struct ata_port_operations mv6_ops = {
++static struct ata_port_operations mv6_ops = {
++	.inherits		= &mv5_ops,
++	.qc_defer		= sata_pmp_qc_defer_cmd_switch,
+ 	.dev_config             = mv6_dev_config,
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.cable_detect		= ata_cable_sata,
+-
+-	.qc_prep		= mv_qc_prep,
+-	.qc_issue		= mv_qc_issue,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_clear		= mv_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.error_handler		= mv_error_handler,
+-	.freeze			= mv_eh_freeze,
+-	.thaw			= mv_eh_thaw,
+-	.qc_defer		= ata_std_qc_defer,
+-
+ 	.scr_read		= mv_scr_read,
+ 	.scr_write		= mv_scr_write,
+ 
+-	.port_start		= mv_port_start,
+-	.port_stop		= mv_port_stop,
++	.pmp_hardreset		= mv_pmp_hardreset,
++	.pmp_softreset		= mv_softreset,
++	.softreset		= mv_softreset,
++	.error_handler		= sata_pmp_error_handler,
+ };
+ 
+-static const struct ata_port_operations mv_iie_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.cable_detect		= ata_cable_sata,
+-
++static struct ata_port_operations mv_iie_ops = {
++	.inherits		= &mv6_ops,
++	.qc_defer		= ata_std_qc_defer, /* FIS-based switching */
++	.dev_config		= ATA_OP_NULL,
+ 	.qc_prep		= mv_qc_prep_iie,
+-	.qc_issue		= mv_qc_issue,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.irq_clear		= mv_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.error_handler		= mv_error_handler,
+-	.freeze			= mv_eh_freeze,
+-	.thaw			= mv_eh_thaw,
+-	.qc_defer		= ata_std_qc_defer,
+-
+-	.scr_read		= mv_scr_read,
+-	.scr_write		= mv_scr_write,
+-
+-	.port_start		= mv_port_start,
+-	.port_stop		= mv_port_stop,
+ };
+ 
+ static const struct ata_port_info mv_port_info[] = {
+@@ -656,6 +604,7 @@ static const struct ata_port_info mv_port_info[] = {
+ 	},
+ 	{  /* chip_604x */
+ 		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++				  ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
+ 				  ATA_FLAG_NCQ,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -663,6 +612,7 @@ static const struct ata_port_info mv_port_info[] = {
+ 	},
+ 	{  /* chip_608x */
+ 		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++				  ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
+ 				  ATA_FLAG_NCQ | MV_FLAG_DUAL_HC,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -670,6 +620,7 @@ static const struct ata_port_info mv_port_info[] = {
+ 	},
+ 	{  /* chip_6042 */
+ 		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++				  ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
+ 				  ATA_FLAG_NCQ,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -677,16 +628,19 @@ static const struct ata_port_info mv_port_info[] = {
+ 	},
+ 	{  /* chip_7042 */
+ 		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++				  ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
+ 				  ATA_FLAG_NCQ,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &mv_iie_ops,
+ 	},
+ 	{  /* chip_soc */
+-		.flags = MV_COMMON_FLAGS | MV_FLAG_SOC,
+-		.pio_mask = 0x1f,      /* pio0-4 */
+-		.udma_mask = ATA_UDMA6,
+-		.port_ops = &mv_iie_ops,
++		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++				  ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
++				  ATA_FLAG_NCQ | MV_FLAG_SOC,
++		.pio_mask	= 0x1f,	/* pio0-4 */
++		.udma_mask	= ATA_UDMA6,
++		.port_ops	= &mv_iie_ops,
+ 	},
+ };
+ 
+@@ -757,11 +711,6 @@ static inline void writelfl(unsigned long data, void __iomem *addr)
+ 	(void) readl(addr);	/* flush to avoid PCI posted write */
+ }
+ 
+-static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
+-{
+-	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
+-}
+-
+ static inline unsigned int mv_hc_from_port(unsigned int port)
+ {
+ 	return port >> MV_PORT_HC_SHIFT;
+@@ -772,6 +721,29 @@ static inline unsigned int mv_hardport_from_port(unsigned int port)
+ 	return port & MV_PORT_MASK;
+ }
+ 
++/*
++ * Consolidate some rather tricky bit shift calculations.
++ * This is hot-path stuff, so not a function.
++ * Simple code, with two return values, so macro rather than inline.
++ *
++ * port is the sole input, in range 0..7.
++ * shift is one output, for use with the main_cause and main_mask registers.
++ * hardport is the other output, in range 0..3
++ *
++ * Note that port and hardport may be the same variable in some cases.
++ */
++#define MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport)	\
++{								\
++	shift    = mv_hc_from_port(port) * HC_SHIFT;		\
++	hardport = mv_hardport_from_port(port);			\
++	shift   += hardport * 2;				\
++}
++
++static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
++{
++	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
++}
++
+ static inline void __iomem *mv_hc_base_from_port(void __iomem *base,
+ 						 unsigned int port)
+ {
+@@ -785,6 +757,14 @@ static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
+ 		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
+ }
+ 
++static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
++{
++	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
++	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
++
++	return hc_mmio + ofs;
++}
++
+ static inline void __iomem *mv_host_base(struct ata_host *host)
+ {
+ 	struct mv_host_priv *hpriv = host->private_data;
+@@ -801,10 +781,6 @@ static inline int mv_get_hc_count(unsigned long port_flags)
+ 	return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
+ }
+ 
+-static void mv_irq_clear(struct ata_port *ap)
+-{
+-}
+-
+ static void mv_set_edma_ptrs(void __iomem *port_mmio,
+ 			     struct mv_host_priv *hpriv,
+ 			     struct mv_port_priv *pp)
+@@ -814,7 +790,8 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
+ 	/*
+ 	 * initialize request queue
+ 	 */
+-	index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
++	pp->req_idx &= MV_MAX_Q_DEPTH_MASK;	/* paranoia */
++	index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
+ 
+ 	WARN_ON(pp->crqb_dma & 0x3ff);
+ 	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
+@@ -830,7 +807,8 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
+ 	/*
+ 	 * initialize response queue
+ 	 */
+-	index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
++	pp->resp_idx &= MV_MAX_Q_DEPTH_MASK;	/* paranoia */
++	index = pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT;
+ 
+ 	WARN_ON(pp->crpb_dma & 0xff);
+ 	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+@@ -864,13 +842,13 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
+ 	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+ 		int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0);
+ 		if (want_ncq != using_ncq)
+-			__mv_stop_dma(ap);
++			mv_stop_edma(ap);
+ 	}
+ 	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
+ 		struct mv_host_priv *hpriv = ap->host->private_data;
+-		int hard_port = mv_hardport_from_port(ap->port_no);
++		int hardport = mv_hardport_from_port(ap->port_no);
+ 		void __iomem *hc_mmio = mv_hc_base_from_port(
+-					mv_host_base(ap->host), hard_port);
++					mv_host_base(ap->host), hardport);
+ 		u32 hc_irq_cause, ipending;
+ 
+ 		/* clear EDMA event indicators, if any */
+@@ -878,14 +856,13 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
+ 
+ 		/* clear EDMA interrupt indicator, if any */
+ 		hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+-		ipending = (DEV_IRQ << hard_port) |
+-				(CRPB_DMA_DONE << hard_port);
++		ipending = (DEV_IRQ | DMA_IRQ) << hardport;
+ 		if (hc_irq_cause & ipending) {
+ 			writelfl(hc_irq_cause & ~ipending,
+ 				 hc_mmio + HC_IRQ_CAUSE_OFS);
+ 		}
+ 
+-		mv_edma_cfg(pp, hpriv, port_mmio, want_ncq);
++		mv_edma_cfg(ap, want_ncq);
+ 
+ 		/* clear FIS IRQ Cause */
+ 		writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
+@@ -895,62 +872,45 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
+ 		writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
+ 		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
+ 	}
+-	WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
+ }
+ 
+ /**
+- *      __mv_stop_dma - Disable eDMA engine
+- *      @ap: ATA channel to manipulate
+- *
+- *      Verify the local cache of the eDMA state is accurate with a
+- *      WARN_ON.
++ *      mv_stop_edma_engine - Disable eDMA engine
++ *      @port_mmio: io base address
+  *
+  *      LOCKING:
+  *      Inherited from caller.
+  */
+-static int __mv_stop_dma(struct ata_port *ap)
++static int mv_stop_edma_engine(void __iomem *port_mmio)
+ {
+-	void __iomem *port_mmio = mv_ap_base(ap);
+-	struct mv_port_priv *pp	= ap->private_data;
+-	u32 reg;
+-	int i, err = 0;
++	int i;
+ 
+-	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+-		/* Disable EDMA if active.   The disable bit auto clears.
+-		 */
+-		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+-		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+-	} else {
+-		WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
+-	}
++	/* Disable eDMA.  The disable bit auto clears. */
++	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+ 
+-	/* now properly wait for the eDMA to stop */
+-	for (i = 1000; i > 0; i--) {
+-		reg = readl(port_mmio + EDMA_CMD_OFS);
++	/* Wait for the chip to confirm eDMA is off. */
++	for (i = 10000; i > 0; i--) {
++		u32 reg = readl(port_mmio + EDMA_CMD_OFS);
+ 		if (!(reg & EDMA_EN))
+-			break;
+-
+-		udelay(100);
+-	}
+-
+-	if (reg & EDMA_EN) {
+-		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
+-		err = -EIO;
++			return 0;
++		udelay(10);
+ 	}
+-
+-	return err;
++	return -EIO;
+ }
+ 
+-static int mv_stop_dma(struct ata_port *ap)
++static int mv_stop_edma(struct ata_port *ap)
+ {
+-	unsigned long flags;
+-	int rc;
+-
+-	spin_lock_irqsave(&ap->host->lock, flags);
+-	rc = __mv_stop_dma(ap);
+-	spin_unlock_irqrestore(&ap->host->lock, flags);
++	void __iomem *port_mmio = mv_ap_base(ap);
++	struct mv_port_priv *pp = ap->private_data;
+ 
+-	return rc;
++	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN))
++		return 0;
++	pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
++	if (mv_stop_edma_engine(port_mmio)) {
++		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
++		return -EIO;
++	}
++	return 0;
+ }
+ 
+ #ifdef ATA_DEBUG
+@@ -1074,18 +1034,56 @@ static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+ static void mv6_dev_config(struct ata_device *adev)
+ {
+ 	/*
++	 * Deal with Gen-II ("mv6") hardware quirks/restrictions:
++	 *
++	 * Gen-II does not support NCQ over a port multiplier
++	 *  (no FIS-based switching).
++	 *
+ 	 * We don't have hob_nsect when doing NCQ commands on Gen-II.
+ 	 * See mv_qc_prep() for more info.
+ 	 */
+-	if (adev->flags & ATA_DFLAG_NCQ)
+-		if (adev->max_sectors > ATA_MAX_SECTORS)
+-			adev->max_sectors = ATA_MAX_SECTORS;
++	if (adev->flags & ATA_DFLAG_NCQ) {
++		if (sata_pmp_attached(adev->link->ap)) {
++			adev->flags &= ~ATA_DFLAG_NCQ;
++			ata_dev_printk(adev, KERN_INFO,
++				"NCQ disabled for command-based switching\n");
++		} else if (adev->max_sectors > GEN_II_NCQ_MAX_SECTORS) {
++			adev->max_sectors = GEN_II_NCQ_MAX_SECTORS;
++			ata_dev_printk(adev, KERN_INFO,
++				"max_sectors limited to %u for NCQ\n",
++				adev->max_sectors);
++		}
++	}
++}
++
++static void mv_config_fbs(void __iomem *port_mmio, int enable_fbs)
++{
++	u32 old_fcfg, new_fcfg, old_ltmode, new_ltmode;
++	/*
++	 * Various bit settings required for operation
++	 * in FIS-based switching (fbs) mode on GenIIe:
++	 */
++	old_fcfg   = readl(port_mmio + FIS_CFG_OFS);
++	old_ltmode = readl(port_mmio + LTMODE_OFS);
++	if (enable_fbs) {
++		new_fcfg   = old_fcfg   |  FIS_CFG_SINGLE_SYNC;
++		new_ltmode = old_ltmode |  LTMODE_BIT8;
++	} else { /* disable fbs */
++		new_fcfg   = old_fcfg   & ~FIS_CFG_SINGLE_SYNC;
++		new_ltmode = old_ltmode & ~LTMODE_BIT8;
++	}
++	if (new_fcfg != old_fcfg)
++		writelfl(new_fcfg, port_mmio + FIS_CFG_OFS);
++	if (new_ltmode != old_ltmode)
++		writelfl(new_ltmode, port_mmio + LTMODE_OFS);
+ }
+ 
+-static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
+-			void __iomem *port_mmio, int want_ncq)
++static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
+ {
+ 	u32 cfg;
++	struct mv_port_priv *pp    = ap->private_data;
++	struct mv_host_priv *hpriv = ap->host->private_data;
++	void __iomem *port_mmio    = mv_ap_base(ap);
+ 
+ 	/* set up non-NCQ EDMA configuration */
+ 	cfg = EDMA_CFG_Q_DEPTH;		/* always 0x1f for *all* chips */
+@@ -1101,6 +1099,13 @@ static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
+ 		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
+ 		cfg |= (1 << 18);	/* enab early completion */
+ 		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
++
++		if (want_ncq && sata_pmp_attached(ap)) {
++			cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */
++			mv_config_fbs(port_mmio, 1);
++		} else {
++			mv_config_fbs(port_mmio, 0);
++		}
+ 	}
+ 
+ 	if (want_ncq) {
+@@ -1156,8 +1161,6 @@ static int mv_port_start(struct ata_port *ap)
+ 	struct device *dev = ap->host->dev;
+ 	struct mv_host_priv *hpriv = ap->host->private_data;
+ 	struct mv_port_priv *pp;
+-	void __iomem *port_mmio = mv_ap_base(ap);
+-	unsigned long flags;
+ 	int tag;
+ 
+ 	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+@@ -1190,18 +1193,6 @@ static int mv_port_start(struct ata_port *ap)
+ 			pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
+ 		}
+ 	}
+-
+-	spin_lock_irqsave(&ap->host->lock, flags);
+-
+-	mv_edma_cfg(pp, hpriv, port_mmio, 0);
+-	mv_set_edma_ptrs(port_mmio, hpriv, pp);
+-
+-	spin_unlock_irqrestore(&ap->host->lock, flags);
+-
+-	/* Don't turn on EDMA here...do it before DMA commands only.  Else
+-	 * we'll be unable to send non-data, PIO, etc due to restricted access
+-	 * to shadow regs.
+-	 */
+ 	return 0;
+ 
+ out_port_free_dma_mem:
+@@ -1220,7 +1211,7 @@ out_port_free_dma_mem:
+  */
+ static void mv_port_stop(struct ata_port *ap)
+ {
+-	mv_stop_dma(ap);
++	mv_stop_edma(ap);
+ 	mv_port_free_dma_mem(ap);
+ }
+ 
+@@ -1306,9 +1297,10 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
+ 		flags |= CRQB_FLAG_READ;
+ 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
+ 	flags |= qc->tag << CRQB_TAG_SHIFT;
++	flags |= (qc->dev->link->pmp & 0xf) << CRQB_PMP_SHIFT;
+ 
+ 	/* get current queue index from software */
+-	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
++	in_index = pp->req_idx;
+ 
+ 	pp->crqb[in_index].sg_addr =
+ 		cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
+@@ -1390,17 +1382,17 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
+ 	    (qc->tf.protocol != ATA_PROT_NCQ))
+ 		return;
+ 
+-	/* Fill in Gen IIE command request block
+-	 */
++	/* Fill in Gen IIE command request block */
+ 	if (!(qc->tf.flags & ATA_TFLAG_WRITE))
+ 		flags |= CRQB_FLAG_READ;
+ 
+ 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
+ 	flags |= qc->tag << CRQB_TAG_SHIFT;
+ 	flags |= qc->tag << CRQB_HOSTQ_SHIFT;
++	flags |= (qc->dev->link->pmp & 0xf) << CRQB_PMP_SHIFT;
+ 
+ 	/* get current queue index from software */
+-	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
++	in_index = pp->req_idx;
+ 
+ 	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
+ 	crqb->addr = cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
+@@ -1455,19 +1447,20 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
+ 
+ 	if ((qc->tf.protocol != ATA_PROT_DMA) &&
+ 	    (qc->tf.protocol != ATA_PROT_NCQ)) {
+-		/* We're about to send a non-EDMA capable command to the
++		/*
++		 * We're about to send a non-EDMA capable command to the
+ 		 * port.  Turn off EDMA so there won't be problems accessing
+ 		 * shadow block, etc registers.
+ 		 */
+-		__mv_stop_dma(ap);
+-		return ata_qc_issue_prot(qc);
++		mv_stop_edma(ap);
++		mv_pmp_select(ap, qc->dev->link->pmp);
++		return ata_sff_qc_issue(qc);
+ 	}
+ 
+ 	mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
+ 
+-	pp->req_idx++;
+-
+-	in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
++	pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
++	in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
+ 
+ 	/* and write the request in pointer to kick the EDMA to life */
+ 	writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
+@@ -1476,16 +1469,51 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
+ 	return 0;
+ }
+ 
++static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap)
++{
++	struct mv_port_priv *pp = ap->private_data;
++	struct ata_queued_cmd *qc;
++
++	if (pp->pp_flags & MV_PP_FLAG_NCQ_EN)
++		return NULL;
++	qc = ata_qc_from_tag(ap, ap->link.active_tag);
++	if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
++		qc = NULL;
++	return qc;
++}
++
++static void mv_unexpected_intr(struct ata_port *ap)
++{
++	struct mv_port_priv *pp = ap->private_data;
++	struct ata_eh_info *ehi = &ap->link.eh_info;
++	char *when = "";
++
++	/*
++	 * We got a device interrupt from something that
++	 * was supposed to be using EDMA or polling.
++	 */
++	ata_ehi_clear_desc(ehi);
++	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
++		when = " while EDMA enabled";
++	} else {
++		struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
++		if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
++			when = " while polling";
++	}
++	ata_ehi_push_desc(ehi, "unexpected device interrupt%s", when);
++	ehi->err_mask |= AC_ERR_OTHER;
++	ehi->action   |= ATA_EH_RESET;
++	ata_port_freeze(ap);
++}
++
+ /**
+  *      mv_err_intr - Handle error interrupts on the port
+  *      @ap: ATA channel to manipulate
+- *      @reset_allowed: bool: 0 == don't trigger from reset here
++ *      @qc: affected command (non-NCQ), or NULL
+  *
+- *      In most cases, just clear the interrupt and move on.  However,
+- *      some cases require an eDMA reset, which is done right before
+- *      the COMRESET in mv_phy_reset().  The SERR case requires a
+- *      clear of pending errors in the SATA SERROR register.  Finally,
+- *      if the port disabled DMA, update our cached copy to match.
++ *      Most cases require a full reset of the chip's state machine,
++ *      which also performs a COMRESET.
++ *      Also, if the port disabled DMA, update our cached copy to match.
+  *
+  *      LOCKING:
+  *      Inherited from caller.
+@@ -1496,75 +1524,73 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+ 	u32 edma_err_cause, eh_freeze_mask, serr = 0;
+ 	struct mv_port_priv *pp = ap->private_data;
+ 	struct mv_host_priv *hpriv = ap->host->private_data;
+-	unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
+ 	unsigned int action = 0, err_mask = 0;
+ 	struct ata_eh_info *ehi = &ap->link.eh_info;
+ 
+ 	ata_ehi_clear_desc(ehi);
+ 
+-	if (!edma_enabled) {
+-		/* just a guess: do we need to do this? should we
+-		 * expand this, and do it in all cases?
+-		 */
+-		sata_scr_read(&ap->link, SCR_ERROR, &serr);
+-		sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
+-	}
+-
++	/*
++	 * Read and clear the err_cause bits.  This won't actually
++	 * clear for some errors (eg. SError), but we will be doing
++	 * a hard reset in those cases regardless, which *will* clear it.
++	 */
+ 	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
++	writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+ 
+-	ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
++	ata_ehi_push_desc(ehi, "edma_err_cause=%08x", edma_err_cause);
+ 
+ 	/*
+-	 * all generations share these EDMA error cause bits
++	 * All generations share these EDMA error cause bits:
+ 	 */
+-
+ 	if (edma_err_cause & EDMA_ERR_DEV)
+ 		err_mask |= AC_ERR_DEV;
+ 	if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
+ 			EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
+ 			EDMA_ERR_INTRL_PAR)) {
+ 		err_mask |= AC_ERR_ATA_BUS;
+-		action |= ATA_EH_HARDRESET;
++		action |= ATA_EH_RESET;
+ 		ata_ehi_push_desc(ehi, "parity error");
+ 	}
+ 	if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
+ 		ata_ehi_hotplugged(ehi);
+ 		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
+ 			"dev disconnect" : "dev connect");
+-		action |= ATA_EH_HARDRESET;
++		action |= ATA_EH_RESET;
+ 	}
+ 
++	/*
++	 * Gen-I has a different SELF_DIS bit,
++	 * different FREEZE bits, and no SERR bit:
++	 */
+ 	if (IS_GEN_I(hpriv)) {
+ 		eh_freeze_mask = EDMA_EH_FREEZE_5;
+-
+ 		if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
+-			pp = ap->private_data;
+ 			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ 			ata_ehi_push_desc(ehi, "EDMA self-disable");
+ 		}
+ 	} else {
+ 		eh_freeze_mask = EDMA_EH_FREEZE;
+-
+ 		if (edma_err_cause & EDMA_ERR_SELF_DIS) {
+-			pp = ap->private_data;
+ 			pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ 			ata_ehi_push_desc(ehi, "EDMA self-disable");
+ 		}
+-
+ 		if (edma_err_cause & EDMA_ERR_SERR) {
+-			sata_scr_read(&ap->link, SCR_ERROR, &serr);
+-			sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
+-			err_mask = AC_ERR_ATA_BUS;
+-			action |= ATA_EH_HARDRESET;
++			/*
++			 * Ensure that we read our own SCR, not a pmp link SCR:
++			 */
++			ap->ops->scr_read(ap, SCR_ERROR, &serr);
++			/*
++			 * Don't clear SError here; leave it for libata-eh:
++			 */
++			ata_ehi_push_desc(ehi, "SError=%08x", serr);
++			err_mask |= AC_ERR_ATA_BUS;
++			action |= ATA_EH_RESET;
+ 		}
+ 	}
+ 
+-	/* Clear EDMA now that SERR cleanup done */
+-	writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+-
+ 	if (!err_mask) {
+ 		err_mask = AC_ERR_OTHER;
+-		action |= ATA_EH_HARDRESET;
++		action |= ATA_EH_RESET;
+ 	}
+ 
+ 	ehi->serror |= serr;
+@@ -1581,178 +1607,151 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+ 		ata_port_abort(ap);
+ }
+ 
+-static void mv_intr_pio(struct ata_port *ap)
++static void mv_process_crpb_response(struct ata_port *ap,
++		struct mv_crpb *response, unsigned int tag, int ncq_enabled)
+ {
+-	struct ata_queued_cmd *qc;
+-	u8 ata_status;
++	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
+ 
+-	/* ignore spurious intr if drive still BUSY */
+-	ata_status = readb(ap->ioaddr.status_addr);
+-	if (unlikely(ata_status & ATA_BUSY))
+-		return;
+-
+-	/* get active ATA command */
+-	qc = ata_qc_from_tag(ap, ap->link.active_tag);
+-	if (unlikely(!qc))			/* no active tag */
+-		return;
+-	if (qc->tf.flags & ATA_TFLAG_POLLING)	/* polling; we don't own qc */
+-		return;
+-
+-	/* and finally, complete the ATA command */
+-	qc->err_mask |= ac_err_mask(ata_status);
+-	ata_qc_complete(qc);
++	if (qc) {
++		u8 ata_status;
++		u16 edma_status = le16_to_cpu(response->flags);
++		/*
++		 * edma_status from a response queue entry:
++		 *   LSB is from EDMA_ERR_IRQ_CAUSE_OFS (non-NCQ only).
++		 *   MSB is saved ATA status from command completion.
++		 */
++		if (!ncq_enabled) {
++			u8 err_cause = edma_status & 0xff & ~EDMA_ERR_DEV;
++			if (err_cause) {
++				/*
++				 * Error will be seen/handled by mv_err_intr().
++				 * So do nothing at all here.
++				 */
++				return;
++			}
++		}
++		ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
++		qc->err_mask |= ac_err_mask(ata_status);
++		ata_qc_complete(qc);
++	} else {
++		ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
++				__func__, tag);
++	}
+ }
+ 
+-static void mv_intr_edma(struct ata_port *ap)
++static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp)
+ {
+ 	void __iomem *port_mmio = mv_ap_base(ap);
+ 	struct mv_host_priv *hpriv = ap->host->private_data;
+-	struct mv_port_priv *pp = ap->private_data;
+-	struct ata_queued_cmd *qc;
+-	u32 out_index, in_index;
++	u32 in_index;
+ 	bool work_done = false;
++	int ncq_enabled = (pp->pp_flags & MV_PP_FLAG_NCQ_EN);
+ 
+-	/* get h/w response queue pointer */
++	/* Get the hardware queue position index */
+ 	in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
+ 			>> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+ 
+-	while (1) {
+-		u16 status;
++	/* Process new responses from since the last time we looked */
++	while (in_index != pp->resp_idx) {
+ 		unsigned int tag;
++		struct mv_crpb *response = &pp->crpb[pp->resp_idx];
+ 
+-		/* get s/w response queue last-read pointer, and compare */
+-		out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
+-		if (in_index == out_index)
+-			break;
++		pp->resp_idx = (pp->resp_idx + 1) & MV_MAX_Q_DEPTH_MASK;
+ 
+-		/* 50xx: get active ATA command */
+-		if (IS_GEN_I(hpriv))
++		if (IS_GEN_I(hpriv)) {
++			/* 50xx: no NCQ, only one command active at a time */
+ 			tag = ap->link.active_tag;
+-
+-		/* Gen II/IIE: get active ATA command via tag, to enable
+-		 * support for queueing.  this works transparently for
+-		 * queued and non-queued modes.
+-		 */
+-		else
+-			tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f;
+-
+-		qc = ata_qc_from_tag(ap, tag);
+-
+-		/* For non-NCQ mode, the lower 8 bits of status
+-		 * are from EDMA_ERR_IRQ_CAUSE_OFS,
+-		 * which should be zero if all went well.
+-		 */
+-		status = le16_to_cpu(pp->crpb[out_index].flags);
+-		if ((status & 0xff) && !(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
+-			mv_err_intr(ap, qc);
+-			return;
+-		}
+-
+-		/* and finally, complete the ATA command */
+-		if (qc) {
+-			qc->err_mask |=
+-				ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
+-			ata_qc_complete(qc);
++		} else {
++			/* Gen II/IIE: get command tag from CRPB entry */
++			tag = le16_to_cpu(response->id) & 0x1f;
+ 		}
+-
+-		/* advance software response queue pointer, to
+-		 * indicate (after the loop completes) to hardware
+-		 * that we have consumed a response queue entry.
+-		 */
++		mv_process_crpb_response(ap, response, tag, ncq_enabled);
+ 		work_done = true;
+-		pp->resp_idx++;
+ 	}
+ 
++	/* Update the software queue position index in hardware */
+ 	if (work_done)
+ 		writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
+-			 (out_index << EDMA_RSP_Q_PTR_SHIFT),
++			 (pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT),
+ 			 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+ }
+ 
+ /**
+  *      mv_host_intr - Handle all interrupts on the given host controller
+  *      @host: host specific structure
+- *      @relevant: port error bits relevant to this host controller
+- *      @hc: which host controller we're to look at
+- *
+- *      Read then write clear the HC interrupt status then walk each
+- *      port connected to the HC and see if it needs servicing.  Port
+- *      success ints are reported in the HC interrupt status reg, the
+- *      port error ints are reported in the higher level main
+- *      interrupt status register and thus are passed in via the
+- *      'relevant' argument.
++ *      @main_cause: Main interrupt cause register for the chip.
+  *
+  *      LOCKING:
+  *      Inherited from caller.
+  */
+-static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
++static int mv_host_intr(struct ata_host *host, u32 main_cause)
+ {
+ 	struct mv_host_priv *hpriv = host->private_data;
+-	void __iomem *mmio = hpriv->base;
+-	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+-	u32 hc_irq_cause;
+-	int port, port0, last_port;
+-
+-	if (hc == 0)
+-		port0 = 0;
+-	else
+-		port0 = MV_PORTS_PER_HC;
++	void __iomem *mmio = hpriv->base, *hc_mmio = NULL;
++	u32 hc_irq_cause = 0;
++	unsigned int handled = 0, port;
+ 
+-	if (HAS_PCI(host))
+-		last_port = port0 + MV_PORTS_PER_HC;
+-	else
+-		last_port = port0 + hpriv->n_ports;
+-	/* we'll need the HC success int register in most cases */
+-	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+-	if (!hc_irq_cause)
+-		return;
+-
+-	writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+-
+-	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
+-		hc, relevant, hc_irq_cause);
+-
+-	for (port = port0; port < last_port; port++) {
++	for (port = 0; port < hpriv->n_ports; port++) {
+ 		struct ata_port *ap = host->ports[port];
+ 		struct mv_port_priv *pp;
+-		int have_err_bits, hard_port, shift;
+-
+-		if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
++		unsigned int shift, hardport, port_cause;
++		/*
++		 * When we move to the second hc, flag our cached
++		 * copies of hc_mmio (and hc_irq_cause) as invalid again.
++		 */
++		if (port == MV_PORTS_PER_HC)
++			hc_mmio = NULL;
++		/*
++		 * Do nothing if port is not interrupting or is disabled:
++		 */
++		MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
++		port_cause = (main_cause >> shift) & (DONE_IRQ | ERR_IRQ);
++		if (!port_cause || !ap || (ap->flags & ATA_FLAG_DISABLED))
+ 			continue;
+-
+-		pp = ap->private_data;
+-
+-		shift = port << 1;		/* (port * 2) */
+-		if (port >= MV_PORTS_PER_HC) {
+-			shift++;	/* skip bit 8 in the HC Main IRQ reg */
++		/*
++		 * Each hc within the host has its own hc_irq_cause register.
++		 * We defer reading it until we know we need it, right now:
++		 *
++		 * FIXME later: we don't really need to read this register
++		 * (some logic changes required below if we go that way),
++		 * because it doesn't tell us anything new.  But we do need
++		 * to write to it, outside the top of this loop,
++		 * to reset the interrupt triggers for next time.
++		 */
++		if (!hc_mmio) {
++			hc_mmio = mv_hc_base_from_port(mmio, port);
++			hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
++			writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
++			handled = 1;
+ 		}
+-		have_err_bits = ((PORT0_ERR << shift) & relevant);
+-
+-		if (unlikely(have_err_bits)) {
+-			struct ata_queued_cmd *qc;
+-
+-			qc = ata_qc_from_tag(ap, ap->link.active_tag);
+-			if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
+-				continue;
+-
+-			mv_err_intr(ap, qc);
+-			continue;
++		/*
++		 * Process completed CRPB response(s) before other events.
++		 */
++		pp = ap->private_data;
++		if (hc_irq_cause & (DMA_IRQ << hardport)) {
++			if (pp->pp_flags & MV_PP_FLAG_EDMA_EN)
++				mv_process_crpb_entries(ap, pp);
+ 		}
+-
+-		hard_port = mv_hardport_from_port(port); /* range 0..3 */
+-
+-		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+-			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
+-				mv_intr_edma(ap);
+-		} else {
+-			if ((DEV_IRQ << hard_port) & hc_irq_cause)
+-				mv_intr_pio(ap);
++		/*
++		 * Handle chip-reported errors, or continue on to handle PIO.
++		 */
++		if (unlikely(port_cause & ERR_IRQ)) {
++			mv_err_intr(ap, mv_get_active_qc(ap));
++		} else if (hc_irq_cause & (DEV_IRQ << hardport)) {
++			if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
++				struct ata_queued_cmd *qc = mv_get_active_qc(ap);
++				if (qc) {
++					ata_sff_host_intr(ap, qc);
++					continue;
++				}
++			}
++			mv_unexpected_intr(ap);
+ 		}
+ 	}
+-	VPRINTK("EXIT\n");
++	return handled;
+ }
+ 
+-static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
++static int mv_pci_error(struct ata_host *host, void __iomem *mmio)
+ {
+ 	struct mv_host_priv *hpriv = host->private_data;
+ 	struct ata_port *ap;
+@@ -1780,7 +1779,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
+ 				ata_ehi_push_desc(ehi,
+ 					"PCI err cause 0x%08x", err_cause);
+ 			err_mask = AC_ERR_HOST_BUS;
+-			ehi->action = ATA_EH_HARDRESET;
++			ehi->action = ATA_EH_RESET;
+ 			qc = ata_qc_from_tag(ap, ap->link.active_tag);
+ 			if (qc)
+ 				qc->err_mask |= err_mask;
+@@ -1790,6 +1789,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
+ 			ata_port_freeze(ap);
+ 		}
+ 	}
++	return 1;	/* handled */
+ }
+ 
+ /**
+@@ -1810,51 +1810,26 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
+ {
+ 	struct ata_host *host = dev_instance;
+ 	struct mv_host_priv *hpriv = host->private_data;
+-	unsigned int hc, handled = 0, n_hcs;
+-	void __iomem *mmio = hpriv->base;
+-	u32 irq_stat, irq_mask;
++	unsigned int handled = 0;
++	u32 main_cause, main_mask;
+ 
+ 	spin_lock(&host->lock);
+-
+-	irq_stat = readl(hpriv->main_cause_reg_addr);
+-	irq_mask = readl(hpriv->main_mask_reg_addr);
+-
+-	/* check the cases where we either have nothing pending or have read
+-	 * a bogus register value which can indicate HW removal or PCI fault
++	main_cause = readl(hpriv->main_cause_reg_addr);
++	main_mask  = readl(hpriv->main_mask_reg_addr);
++	/*
++	 * Deal with cases where we either have nothing pending, or have read
++	 * a bogus register value which can indicate HW removal or PCI fault.
+ 	 */
+-	if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
+-		goto out_unlock;
+-
+-	n_hcs = mv_get_hc_count(host->ports[0]->flags);
+-
+-	if (unlikely((irq_stat & PCI_ERR) && HAS_PCI(host))) {
+-		mv_pci_error(host, mmio);
+-		handled = 1;
+-		goto out_unlock;	/* skip all other HC irq handling */
+-	}
+-
+-	for (hc = 0; hc < n_hcs; hc++) {
+-		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
+-		if (relevant) {
+-			mv_host_intr(host, relevant, hc);
+-			handled = 1;
+-		}
++	if ((main_cause & main_mask) && (main_cause != 0xffffffffU)) {
++		if (unlikely((main_cause & PCI_ERR) && HAS_PCI(host)))
++			handled = mv_pci_error(host, hpriv->base);
++		else
++			handled = mv_host_intr(host, main_cause);
+ 	}
+-
+-out_unlock:
+ 	spin_unlock(&host->lock);
+-
+ 	return IRQ_RETVAL(handled);
+ }
+ 
+-static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
+-{
+-	void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
+-	unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
+-
+-	return hc_mmio + ofs;
+-}
+-
+ static unsigned int mv5_scr_offset(unsigned int sc_reg_in)
+ {
+ 	unsigned int ofs;
+@@ -1980,9 +1955,12 @@ static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
+ {
+ 	void __iomem *port_mmio = mv_port_base(mmio, port);
+ 
+-	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+-
+-	mv_channel_reset(hpriv, mmio, port);
++	/*
++	 * The datasheet warns against setting ATA_RST when EDMA is active
++	 * (but doesn't say what the problem might be).  So we first try
++	 * to disable the EDMA engine before doing the ATA_RST operation.
++	 */
++	mv_reset_channel(hpriv, mmio, port);
+ 
+ 	ZERO(0x028);	/* command */
+ 	writel(0x11f, port_mmio + EDMA_CFG_OFS);
+@@ -2200,14 +2178,15 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 		m4 = readl(port_mmio + PHY_MODE4);
+ 
+ 		if (hp_flags & MV_HP_ERRATA_60X1B2)
+-			tmp = readl(port_mmio + 0x310);
++			tmp = readl(port_mmio + PHY_MODE3);
+ 
++		/* workaround for errata FEr SATA#10 (part 1) */
+ 		m4 = (m4 & ~(1 << 1)) | (1 << 0);
+ 
+ 		writel(m4, port_mmio + PHY_MODE4);
+ 
+ 		if (hp_flags & MV_HP_ERRATA_60X1B2)
+-			writel(tmp, port_mmio + 0x310);
++			writel(tmp, port_mmio + PHY_MODE3);
+ 	}
+ 
+ 	/* Revert values of pre-emphasis and signal amps to the saved ones */
+@@ -2255,9 +2234,12 @@ static void mv_soc_reset_hc_port(struct mv_host_priv *hpriv,
+ {
+ 	void __iomem *port_mmio = mv_port_base(mmio, port);
+ 
+-	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+-
+-	mv_channel_reset(hpriv, mmio, port);
++	/*
++	 * The datasheet warns against setting ATA_RST when EDMA is active
++	 * (but doesn't say what the problem might be).  So we first try
++	 * to disable the EDMA engine before doing the ATA_RST operation.
++	 */
++	mv_reset_channel(hpriv, mmio, port);
+ 
+ 	ZERO(0x028);		/* command */
+ 	writel(0x101f, port_mmio + EDMA_CFG_OFS);
+@@ -2314,25 +2296,39 @@ static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio)
+ 	return;
+ }
+ 
+-static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
++static void mv_setup_ifctl(void __iomem *port_mmio, int want_gen2i)
++{
++	u32 ifctl = readl(port_mmio + SATA_INTERFACE_CFG);
++
++	ifctl = (ifctl & 0xf7f) | 0x9b1000;	/* from chip spec */
++	if (want_gen2i)
++		ifctl |= (1 << 7);		/* enable gen2i speed */
++	writelfl(ifctl, port_mmio + SATA_INTERFACE_CFG);
++}
++
++/*
++ * Caller must ensure that EDMA is not active,
++ * by first doing mv_stop_edma() where needed.
++ */
++static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 			     unsigned int port_no)
+ {
+ 	void __iomem *port_mmio = mv_port_base(mmio, port_no);
+ 
++	mv_stop_edma_engine(port_mmio);
+ 	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
+ 
+-	if (IS_GEN_II(hpriv)) {
+-		u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
+-		ifctl |= (1 << 7);		/* enable gen2i speed */
+-		ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
+-		writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
++	if (!IS_GEN_I(hpriv)) {
++		/* Enable 3.0gb/s link speed */
++		mv_setup_ifctl(port_mmio, 1);
+ 	}
+-
+-	udelay(25);		/* allow reset propagation */
+-
+-	/* Spec never mentions clearing the bit.  Marvell's driver does
+-	 * clear the bit, however.
++	/*
++	 * Strobing ATA_RST here causes a hard reset of the SATA transport,
++	 * link, and physical layers.  It resets all SATA interface registers
++	 * (except for SATA_INTERFACE_CFG), and issues a COMRESET to the dev.
+ 	 */
++	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
++	udelay(25);	/* allow reset propagation */
+ 	writelfl(0, port_mmio + EDMA_CMD_OFS);
+ 
+ 	hpriv->ops->phy_errata(hpriv, mmio, port_no);
+@@ -2341,136 +2337,32 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 		mdelay(1);
+ }
+ 
+-/**
+- *      mv_phy_reset - Perform eDMA reset followed by COMRESET
+- *      @ap: ATA channel to manipulate
+- *
+- *      Part of this is taken from __sata_phy_reset and modified to
+- *      not sleep since this routine gets called from interrupt level.
+- *
+- *      LOCKING:
+- *      Inherited from caller.  This is coded to safe to call at
+- *      interrupt level, i.e. it does not sleep.
+- */
+-static void mv_phy_reset(struct ata_port *ap, unsigned int *class,
+-			 unsigned long deadline)
++static void mv_pmp_select(struct ata_port *ap, int pmp)
+ {
+-	struct mv_port_priv *pp	= ap->private_data;
+-	struct mv_host_priv *hpriv = ap->host->private_data;
+-	void __iomem *port_mmio = mv_ap_base(ap);
+-	int retry = 5;
+-	u32 sstatus;
+-
+-	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
+-
+-#ifdef DEBUG
+-	{
+-		u32 sstatus, serror, scontrol;
+-
+-		mv_scr_read(ap, SCR_STATUS, &sstatus);
+-		mv_scr_read(ap, SCR_ERROR, &serror);
+-		mv_scr_read(ap, SCR_CONTROL, &scontrol);
+-		DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
+-			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
+-	}
+-#endif
+-
+-	/* Issue COMRESET via SControl */
+-comreset_retry:
+-	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
+-	msleep(1);
+-
+-	sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
+-	msleep(20);
+-
+-	do {
+-		sata_scr_read(&ap->link, SCR_STATUS, &sstatus);
+-		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
+-			break;
+-
+-		msleep(1);
+-	} while (time_before(jiffies, deadline));
+-
+-	/* work around errata */
+-	if (IS_GEN_II(hpriv) &&
+-	    (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
+-	    (retry-- > 0))
+-		goto comreset_retry;
+-
+-#ifdef DEBUG
+-	{
+-		u32 sstatus, serror, scontrol;
+-
+-		mv_scr_read(ap, SCR_STATUS, &sstatus);
+-		mv_scr_read(ap, SCR_ERROR, &serror);
+-		mv_scr_read(ap, SCR_CONTROL, &scontrol);
+-		DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
+-			"SCtrl 0x%08x\n", sstatus, serror, scontrol);
+-	}
+-#endif
+-
+-	if (ata_link_offline(&ap->link)) {
+-		*class = ATA_DEV_NONE;
+-		return;
+-	}
++	if (sata_pmp_supported(ap)) {
++		void __iomem *port_mmio = mv_ap_base(ap);
++		u32 reg = readl(port_mmio + SATA_IFCTL_OFS);
++		int old = reg & 0xf;
+ 
+-	/* even after SStatus reflects that device is ready,
+-	 * it seems to take a while for link to be fully
+-	 * established (and thus Status no longer 0x80/0x7F),
+-	 * so we poll a bit for that, here.
+-	 */
+-	retry = 20;
+-	while (1) {
+-		u8 drv_stat = ata_check_status(ap);
+-		if ((drv_stat != 0x80) && (drv_stat != 0x7f))
+-			break;
+-		msleep(500);
+-		if (retry-- <= 0)
+-			break;
+-		if (time_after(jiffies, deadline))
+-			break;
++		if (old != pmp) {
++			reg = (reg & ~0xf) | pmp;
++			writelfl(reg, port_mmio + SATA_IFCTL_OFS);
++		}
+ 	}
+-
+-	/* FIXME: if we passed the deadline, the following
+-	 * code probably produces an invalid result
+-	 */
+-
+-	/* finally, read device signature from TF registers */
+-	*class = ata_dev_try_classify(ap->link.device, 1, NULL);
+-
+-	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+-
+-	WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
+-
+-	VPRINTK("EXIT\n");
+ }
+ 
+-static int mv_prereset(struct ata_link *link, unsigned long deadline)
++static int mv_pmp_hardreset(struct ata_link *link, unsigned int *class,
++				unsigned long deadline)
+ {
+-	struct ata_port *ap = link->ap;
+-	struct mv_port_priv *pp	= ap->private_data;
+-	struct ata_eh_context *ehc = &link->eh_context;
+-	int rc;
+-
+-	rc = mv_stop_dma(ap);
+-	if (rc)
+-		ehc->i.action |= ATA_EH_HARDRESET;
+-
+-	if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
+-		pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
+-		ehc->i.action |= ATA_EH_HARDRESET;
+-	}
+-
+-	/* if we're about to do hardreset, nothing more to do */
+-	if (ehc->i.action & ATA_EH_HARDRESET)
+-		return 0;
+-
+-	if (ata_link_online(link))
+-		rc = ata_wait_ready(ap, deadline);
+-	else
+-		rc = -ENODEV;
++	mv_pmp_select(link->ap, sata_srst_pmp(link));
++	return sata_std_hardreset(link, class, deadline);
++}
+ 
+-	return rc;
++static int mv_softreset(struct ata_link *link, unsigned int *class,
++				unsigned long deadline)
++{
++	mv_pmp_select(link->ap, sata_srst_pmp(link));
++	return ata_sff_softreset(link, class, deadline);
+ }
+ 
+ static int mv_hardreset(struct ata_link *link, unsigned int *class,
+@@ -2478,97 +2370,77 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
+ {
+ 	struct ata_port *ap = link->ap;
+ 	struct mv_host_priv *hpriv = ap->host->private_data;
++	struct mv_port_priv *pp = ap->private_data;
+ 	void __iomem *mmio = hpriv->base;
++	int rc, attempts = 0, extra = 0;
++	u32 sstatus;
++	bool online;
+ 
+-	mv_stop_dma(ap);
+-
+-	mv_channel_reset(hpriv, mmio, ap->port_no);
+-
+-	mv_phy_reset(ap, class, deadline);
+-
+-	return 0;
+-}
+-
+-static void mv_postreset(struct ata_link *link, unsigned int *classes)
+-{
+-	struct ata_port *ap = link->ap;
+-	u32 serr;
+-
+-	/* print link status */
+-	sata_print_link_status(link);
+-
+-	/* clear SError */
+-	sata_scr_read(link, SCR_ERROR, &serr);
+-	sata_scr_write_flush(link, SCR_ERROR, serr);
++	mv_reset_channel(hpriv, mmio, ap->port_no);
++	pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ 
+-	/* bail out if no device is present */
+-	if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+-		DPRINTK("EXIT, no device\n");
+-		return;
+-	}
++	/* Workaround for errata FEr SATA#10 (part 2) */
++	do {
++		const unsigned long *timing =
++				sata_ehc_deb_timing(&link->eh_context);
+ 
+-	/* set up device control */
+-	iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+-}
++		rc = sata_link_hardreset(link, timing, deadline + extra,
++					 &online, NULL);
++		if (rc)
++			return rc;
++		sata_scr_read(link, SCR_STATUS, &sstatus);
++		if (!IS_GEN_I(hpriv) && ++attempts >= 5 && sstatus == 0x121) {
++			/* Force 1.5gb/s link speed and try again */
++			mv_setup_ifctl(mv_ap_base(ap), 0);
++			if (time_after(jiffies + HZ, deadline))
++				extra = HZ; /* only extend it once, max */
++		}
++	} while (sstatus != 0x0 && sstatus != 0x113 && sstatus != 0x123);
+ 
+-static void mv_error_handler(struct ata_port *ap)
+-{
+-	ata_do_eh(ap, mv_prereset, ata_std_softreset,
+-		  mv_hardreset, mv_postreset);
++	return rc;
+ }
+ 
+ static void mv_eh_freeze(struct ata_port *ap)
+ {
+ 	struct mv_host_priv *hpriv = ap->host->private_data;
+-	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+-	u32 tmp, mask;
+-	unsigned int shift;
++	unsigned int shift, hardport, port = ap->port_no;
++	u32 main_mask;
+ 
+ 	/* FIXME: handle coalescing completion events properly */
+ 
+-	shift = ap->port_no * 2;
+-	if (hc > 0)
+-		shift++;
+-
+-	mask = 0x3 << shift;
++	mv_stop_edma(ap);
++	MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
+ 
+ 	/* disable assertion of portN err, done events */
+-	tmp = readl(hpriv->main_mask_reg_addr);
+-	writelfl(tmp & ~mask, hpriv->main_mask_reg_addr);
++	main_mask = readl(hpriv->main_mask_reg_addr);
++	main_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
++	writelfl(main_mask, hpriv->main_mask_reg_addr);
+ }
+ 
+ static void mv_eh_thaw(struct ata_port *ap)
+ {
+ 	struct mv_host_priv *hpriv = ap->host->private_data;
+-	void __iomem *mmio = hpriv->base;
+-	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+-	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
++	unsigned int shift, hardport, port = ap->port_no;
++	void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port);
+ 	void __iomem *port_mmio = mv_ap_base(ap);
+-	u32 tmp, mask, hc_irq_cause;
+-	unsigned int shift, hc_port_no = ap->port_no;
++	u32 main_mask, hc_irq_cause;
+ 
+ 	/* FIXME: handle coalescing completion events properly */
+ 
+-	shift = ap->port_no * 2;
+-	if (hc > 0) {
+-		shift++;
+-		hc_port_no -= 4;
+-	}
+-
+-	mask = 0x3 << shift;
++	MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
+ 
+ 	/* clear EDMA errors on this port */
+ 	writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+ 
+ 	/* clear pending irq events */
+ 	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+-	hc_irq_cause &= ~(1 << hc_port_no);	/* clear CRPB-done */
+-	hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
+-	writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
++	hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport);
++	writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+ 
+ 	/* enable assertion of portN err, done events */
+-	tmp = readl(hpriv->main_mask_reg_addr);
+-	writelfl(tmp | mask, hpriv->main_mask_reg_addr);
++	main_mask = readl(hpriv->main_mask_reg_addr);
++	main_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
++	writelfl(main_mask, hpriv->main_mask_reg_addr);
+ }
+ 
+ /**
+@@ -2779,19 +2651,17 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+ 
+ 	rc = mv_chip_id(host, board_idx);
+ 	if (rc)
+-	goto done;
++		goto done;
+ 
+ 	if (HAS_PCI(host)) {
+-		hpriv->main_cause_reg_addr = hpriv->base +
+-		  HC_MAIN_IRQ_CAUSE_OFS;
+-		hpriv->main_mask_reg_addr = hpriv->base + HC_MAIN_IRQ_MASK_OFS;
++		hpriv->main_cause_reg_addr = mmio + HC_MAIN_IRQ_CAUSE_OFS;
++		hpriv->main_mask_reg_addr  = mmio + HC_MAIN_IRQ_MASK_OFS;
+ 	} else {
+-		hpriv->main_cause_reg_addr = hpriv->base +
+-		  HC_SOC_MAIN_IRQ_CAUSE_OFS;
+-		hpriv->main_mask_reg_addr = hpriv->base +
+-		  HC_SOC_MAIN_IRQ_MASK_OFS;
++		hpriv->main_cause_reg_addr = mmio + HC_SOC_MAIN_IRQ_CAUSE_OFS;
++		hpriv->main_mask_reg_addr  = mmio + HC_SOC_MAIN_IRQ_MASK_OFS;
+ 	}
+-	/* global interrupt mask */
++
++	/* global interrupt mask: 0 == mask everything */
+ 	writel(0, hpriv->main_mask_reg_addr);
+ 
+ 	n_hc = mv_get_hc_count(host->ports[0]->flags);
+@@ -2808,19 +2678,6 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+ 	hpriv->ops->enable_leds(hpriv, mmio);
+ 
+ 	for (port = 0; port < host->n_ports; port++) {
+-		if (IS_GEN_II(hpriv)) {
+-			void __iomem *port_mmio = mv_port_base(mmio, port);
+-
+-			u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
+-			ifctl |= (1 << 7);		/* enable gen2i speed */
+-			ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
+-			writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
+-		}
+-
+-		hpriv->ops->phy_errata(hpriv, mmio, port);
+-	}
+-
+-	for (port = 0; port < host->n_ports; port++) {
+ 		struct ata_port *ap = host->ports[port];
+ 		void __iomem *port_mmio = mv_port_base(mmio, port);
+ 
+@@ -2897,6 +2754,27 @@ static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
+ 	return 0;
+ }
+ 
++static void mv_conf_mbus_windows(struct mv_host_priv *hpriv,
++				 struct mbus_dram_target_info *dram)
++{
++	int i;
++
++	for (i = 0; i < 4; i++) {
++		writel(0, hpriv->base + WINDOW_CTRL(i));
++		writel(0, hpriv->base + WINDOW_BASE(i));
++	}
++
++	for (i = 0; i < dram->num_cs; i++) {
++		struct mbus_dram_window *cs = dram->cs + i;
++
++		writel(((cs->size - 1) & 0xffff0000) |
++			(cs->mbus_attr << 8) |
++			(dram->mbus_dram_target_id << 4) | 1,
++			hpriv->base + WINDOW_CTRL(i));
++		writel(cs->base, hpriv->base + WINDOW_BASE(i));
++	}
++}
++
+ /**
+  *      mv_platform_probe - handle a positive probe of an soc Marvell
+  *      host
+@@ -2951,6 +2829,12 @@ static int mv_platform_probe(struct platform_device *pdev)
+ 				   res->end - res->start + 1);
+ 	hpriv->base -= MV_SATAHC0_REG_BASE;
+ 
++	/*
++	 * (Re-)program MBUS remapping windows if we are asked to.
++	 */
++	if (mv_platform_data->dram != NULL)
++		mv_conf_mbus_windows(hpriv, mv_platform_data->dram);
++
+ 	rc = mv_create_dma_pools(hpriv, &pdev->dev);
+ 	if (rc)
+ 		return rc;
+@@ -3192,7 +3076,7 @@ MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
+ MODULE_LICENSE("GPL");
+ MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
+ MODULE_VERSION(DRV_VERSION);
+-MODULE_ALIAS("platform:sata_mv");
++MODULE_ALIAS("platform:" DRV_NAME);
+ 
+ #ifdef CONFIG_PCI
+ module_param(msi, int, 0444);
+diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
+index ed5473b..858f706 100644
+--- a/drivers/ata/sata_nv.c
++++ b/drivers/ata/sata_nv.c
+@@ -309,7 +309,8 @@ static void nv_nf2_freeze(struct ata_port *ap);
+ static void nv_nf2_thaw(struct ata_port *ap);
+ static void nv_ck804_freeze(struct ata_port *ap);
+ static void nv_ck804_thaw(struct ata_port *ap);
+-static void nv_error_handler(struct ata_port *ap);
++static int nv_hardreset(struct ata_link *link, unsigned int *class,
++			unsigned long deadline);
+ static int nv_adma_slave_config(struct scsi_device *sdev);
+ static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
+ static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
+@@ -385,157 +386,60 @@ static struct pci_driver nv_pci_driver = {
+ };
+ 
+ static struct scsi_host_template nv_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ static struct scsi_host_template nv_adma_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.change_queue_depth	= ata_scsi_change_queue_depth,
++	ATA_NCQ_SHT(DRV_NAME),
+ 	.can_queue		= NV_ADMA_MAX_CPBS,
+-	.this_id		= ATA_SHT_THIS_ID,
+ 	.sg_tablesize		= NV_ADMA_SGTBL_TOTAL_LEN,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= NV_ADMA_DMA_BOUNDARY,
+ 	.slave_configure	= nv_adma_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+ static struct scsi_host_template nv_swncq_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.change_queue_depth	= ata_scsi_change_queue_depth,
++	ATA_NCQ_SHT(DRV_NAME),
+ 	.can_queue		= ATA_MAX_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+ 	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= ATA_DMA_BOUNDARY,
+ 	.slave_configure	= nv_swncq_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+-static const struct ata_port_operations nv_generic_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.exec_command		= ata_exec_command,
+-	.check_status		= ata_check_status,
+-	.dev_select		= ata_std_dev_select,
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= nv_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.data_xfer		= ata_data_xfer,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
++static struct ata_port_operations nv_generic_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.hardreset		= nv_hardreset,
+ 	.scr_read		= nv_scr_read,
+ 	.scr_write		= nv_scr_write,
+-	.port_start		= ata_port_start,
+ };
+ 
+-static const struct ata_port_operations nv_nf2_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.exec_command		= ata_exec_command,
+-	.check_status		= ata_check_status,
+-	.dev_select		= ata_std_dev_select,
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
++static struct ata_port_operations nv_nf2_ops = {
++	.inherits		= &nv_generic_ops,
+ 	.freeze			= nv_nf2_freeze,
+ 	.thaw			= nv_nf2_thaw,
+-	.error_handler		= nv_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.data_xfer		= ata_data_xfer,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-	.scr_read		= nv_scr_read,
+-	.scr_write		= nv_scr_write,
+-	.port_start		= ata_port_start,
+ };
+ 
+-static const struct ata_port_operations nv_ck804_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.exec_command		= ata_exec_command,
+-	.check_status		= ata_check_status,
+-	.dev_select		= ata_std_dev_select,
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
++static struct ata_port_operations nv_ck804_ops = {
++	.inherits		= &nv_generic_ops,
+ 	.freeze			= nv_ck804_freeze,
+ 	.thaw			= nv_ck804_thaw,
+-	.error_handler		= nv_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.data_xfer		= ata_data_xfer,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-	.scr_read		= nv_scr_read,
+-	.scr_write		= nv_scr_write,
+-	.port_start		= ata_port_start,
+ 	.host_stop		= nv_ck804_host_stop,
+ };
+ 
+-static const struct ata_port_operations nv_adma_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= nv_adma_tf_read,
++static struct ata_port_operations nv_adma_ops = {
++	.inherits		= &nv_generic_ops,
++
+ 	.check_atapi_dma	= nv_adma_check_atapi_dma,
+-	.exec_command		= ata_exec_command,
+-	.check_status		= ata_check_status,
+-	.dev_select		= ata_std_dev_select,
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
++	.sff_tf_read		= nv_adma_tf_read,
+ 	.qc_defer		= ata_std_qc_defer,
+ 	.qc_prep		= nv_adma_qc_prep,
+ 	.qc_issue		= nv_adma_qc_issue,
++	.sff_irq_clear		= nv_adma_irq_clear,
++
+ 	.freeze			= nv_adma_freeze,
+ 	.thaw			= nv_adma_thaw,
+ 	.error_handler		= nv_adma_error_handler,
+ 	.post_internal_cmd	= nv_adma_post_internal_cmd,
+-	.data_xfer		= ata_data_xfer,
+-	.irq_clear		= nv_adma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-	.scr_read		= nv_scr_read,
+-	.scr_write		= nv_scr_write,
++
+ 	.port_start		= nv_adma_port_start,
+ 	.port_stop		= nv_adma_port_stop,
+ #ifdef CONFIG_PM
+@@ -545,28 +449,17 @@ static const struct ata_port_operations nv_adma_ops = {
+ 	.host_stop		= nv_adma_host_stop,
+ };
+ 
+-static const struct ata_port_operations nv_swncq_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.exec_command		= ata_exec_command,
+-	.check_status		= ata_check_status,
+-	.dev_select		= ata_std_dev_select,
+-	.bmdma_setup		= ata_bmdma_setup,
+-	.bmdma_start		= ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
++static struct ata_port_operations nv_swncq_ops = {
++	.inherits		= &nv_generic_ops,
++
+ 	.qc_defer		= ata_std_qc_defer,
+ 	.qc_prep		= nv_swncq_qc_prep,
+ 	.qc_issue		= nv_swncq_qc_issue,
++
+ 	.freeze			= nv_mcp55_freeze,
+ 	.thaw			= nv_mcp55_thaw,
+ 	.error_handler		= nv_swncq_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.data_xfer		= ata_data_xfer,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-	.scr_read		= nv_scr_read,
+-	.scr_write		= nv_scr_write,
++
+ #ifdef CONFIG_PM
+ 	.port_suspend		= nv_swncq_port_suspend,
+ 	.port_resume		= nv_swncq_port_resume,
+@@ -574,63 +467,61 @@ static const struct ata_port_operations nv_swncq_ops = {
+ 	.port_start		= nv_swncq_port_start,
+ };
+ 
++struct nv_pi_priv {
++	irq_handler_t			irq_handler;
++	struct scsi_host_template	*sht;
++};
++
++#define NV_PI_PRIV(_irq_handler, _sht) \
++	&(struct nv_pi_priv){ .irq_handler = _irq_handler, .sht = _sht }
++
+ static const struct ata_port_info nv_port_info[] = {
+ 	/* generic */
+ 	{
+-		.sht		= &nv_sht,
+ 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
+ 		.pio_mask	= NV_PIO_MASK,
+ 		.mwdma_mask	= NV_MWDMA_MASK,
+ 		.udma_mask	= NV_UDMA_MASK,
+ 		.port_ops	= &nv_generic_ops,
+-		.irq_handler	= nv_generic_interrupt,
++		.private_data	= NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
+ 	},
+ 	/* nforce2/3 */
+ 	{
+-		.sht		= &nv_sht,
+ 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
+ 		.pio_mask	= NV_PIO_MASK,
+ 		.mwdma_mask	= NV_MWDMA_MASK,
+ 		.udma_mask	= NV_UDMA_MASK,
+ 		.port_ops	= &nv_nf2_ops,
+-		.irq_handler	= nv_nf2_interrupt,
++		.private_data	= NV_PI_PRIV(nv_nf2_interrupt, &nv_sht),
+ 	},
+ 	/* ck804 */
+ 	{
+-		.sht		= &nv_sht,
+ 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
+ 		.pio_mask	= NV_PIO_MASK,
+ 		.mwdma_mask	= NV_MWDMA_MASK,
+ 		.udma_mask	= NV_UDMA_MASK,
+ 		.port_ops	= &nv_ck804_ops,
+-		.irq_handler	= nv_ck804_interrupt,
++		.private_data	= NV_PI_PRIV(nv_ck804_interrupt, &nv_sht),
+ 	},
+ 	/* ADMA */
+ 	{
+-		.sht		= &nv_adma_sht,
+ 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ 				  ATA_FLAG_MMIO | ATA_FLAG_NCQ,
+-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
+ 		.pio_mask	= NV_PIO_MASK,
+ 		.mwdma_mask	= NV_MWDMA_MASK,
+ 		.udma_mask	= NV_UDMA_MASK,
+ 		.port_ops	= &nv_adma_ops,
+-		.irq_handler	= nv_adma_interrupt,
++		.private_data	= NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht),
+ 	},
+ 	/* SWNCQ */
+ 	{
+-		.sht		= &nv_swncq_sht,
+ 		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ 				  ATA_FLAG_NCQ,
+-		.link_flags	= ATA_LFLAG_HRST_TO_RESUME,
+ 		.pio_mask	= NV_PIO_MASK,
+ 		.mwdma_mask	= NV_MWDMA_MASK,
+ 		.udma_mask	= NV_UDMA_MASK,
+ 		.port_ops	= &nv_swncq_ops,
+-		.irq_handler	= nv_swncq_interrupt,
++		.private_data	= NV_PI_PRIV(nv_swncq_interrupt, &nv_swncq_sht),
+ 	},
+ };
+ 
+@@ -640,8 +531,8 @@ MODULE_LICENSE("GPL");
+ MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
+ MODULE_VERSION(DRV_VERSION);
+ 
+-static int adma_enabled = 1;
+-static int swncq_enabled;
++static int adma_enabled;
++static int swncq_enabled = 1;
+ 
+ static void nv_adma_register_mode(struct ata_port *ap)
+ {
+@@ -839,7 +730,7 @@ static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ 	   ADMA mode could abort outstanding commands. */
+ 	nv_adma_register_mode(ap);
+ 
+-	ata_tf_read(ap, tf);
++	ata_sff_tf_read(ap, tf);
+ }
+ 
+ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
+@@ -929,7 +820,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
+ 					"notifier for tag %d with no cmd?\n",
+ 					cpb_num);
+ 			ehi->err_mask |= AC_ERR_HSM;
+-			ehi->action |= ATA_EH_SOFTRESET;
++			ehi->action |= ATA_EH_RESET;
+ 			ata_port_freeze(ap);
+ 			return 1;
+ 		}
+@@ -953,12 +844,12 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
+ 
+ 	/* DEV interrupt w/ no active qc? */
+ 	if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
+-		ata_check_status(ap);
++		ata_sff_check_status(ap);
+ 		return 1;
+ 	}
+ 
+ 	/* handle interrupt */
+-	return ata_host_intr(ap, qc);
++	return ata_sff_host_intr(ap, qc);
+ }
+ 
+ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
+@@ -1137,7 +1028,7 @@ static void nv_adma_irq_clear(struct ata_port *ap)
+ 	u32 notifier_clears[2];
+ 
+ 	if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
+-		ata_bmdma_irq_clear(ap);
++		ata_sff_irq_clear(ap);
+ 		return;
+ 	}
+ 
+@@ -1168,7 +1059,7 @@ static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
+ 	struct nv_adma_port_priv *pp = qc->ap->private_data;
+ 
+ 	if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
+-		ata_bmdma_post_internal_cmd(qc);
++		ata_sff_post_internal_cmd(qc);
+ }
+ 
+ static int nv_adma_port_start(struct ata_port *ap)
+@@ -1445,7 +1336,7 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
+ 		BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
+ 			(qc->flags & ATA_QCFLAG_DMAMAP));
+ 		nv_adma_register_mode(qc->ap);
+-		ata_qc_prep(qc);
++		ata_sff_qc_prep(qc);
+ 		return;
+ 	}
+ 
+@@ -1504,7 +1395,7 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
+ 		BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
+ 			(qc->flags & ATA_QCFLAG_DMAMAP));
+ 		nv_adma_register_mode(qc->ap);
+-		return ata_qc_issue_prot(qc);
++		return ata_sff_qc_issue(qc);
+ 	} else
+ 		nv_adma_mode(qc->ap);
+ 
+@@ -1545,11 +1436,11 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
+ 
+ 			qc = ata_qc_from_tag(ap, ap->link.active_tag);
+ 			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
+-				handled += ata_host_intr(ap, qc);
++				handled += ata_sff_host_intr(ap, qc);
+ 			else
+ 				// No request pending?  Clear interrupt status
+ 				// anyway, in case there's one pending.
+-				ap->ops->check_status(ap);
++				ap->ops->sff_check_status(ap);
+ 		}
+ 
+ 	}
+@@ -1680,7 +1571,7 @@ static void nv_mcp55_freeze(struct ata_port *ap)
+ 	mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
+ 	mask &= ~(NV_INT_ALL_MCP55 << shift);
+ 	writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
+-	ata_bmdma_freeze(ap);
++	ata_sff_freeze(ap);
+ }
+ 
+ static void nv_mcp55_thaw(struct ata_port *ap)
+@@ -1694,25 +1585,22 @@ static void nv_mcp55_thaw(struct ata_port *ap)
+ 	mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
+ 	mask |= (NV_INT_MASK_MCP55 << shift);
+ 	writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
+-	ata_bmdma_thaw(ap);
++	ata_sff_thaw(ap);
+ }
+ 
+ static int nv_hardreset(struct ata_link *link, unsigned int *class,
+ 			unsigned long deadline)
+ {
+-	unsigned int dummy;
++	int rc;
+ 
+ 	/* SATA hardreset fails to retrieve proper device signature on
+-	 * some controllers.  Don't classify on hardreset.  For more
+-	 * info, see http://bugzilla.kernel.org/show_bug.cgi?id=3352
++	 * some controllers.  Request follow up SRST.  For more info,
++	 * see http://bugzilla.kernel.org/show_bug.cgi?id=3352
+ 	 */
+-	return sata_std_hardreset(link, &dummy, deadline);
+-}
+-
+-static void nv_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+-			   nv_hardreset, ata_std_postreset);
++	rc = sata_sff_hardreset(link, class, deadline);
++	if (rc)
++		return rc;
++	return -EAGAIN;
+ }
+ 
+ static void nv_adma_error_handler(struct ata_port *ap)
+@@ -1768,8 +1656,7 @@ static void nv_adma_error_handler(struct ata_port *ap)
+ 		readw(mmio + NV_ADMA_CTL);	/* flush posted write */
+ 	}
+ 
+-	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+-			   nv_hardreset, ata_std_postreset);
++	ata_sff_error_handler(ap);
+ }
+ 
+ static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc)
+@@ -1855,7 +1742,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
+ 		pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits);
+ 
+ 	ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n",
+-			ap->ops->check_status(ap),
++			ap->ops->sff_check_status(ap),
+ 			ioread8(ap->ioaddr.error_addr));
+ 
+ 	sactive = readl(pp->sactive_block);
+@@ -1881,7 +1768,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
+ 	}
+ 
+ 	nv_swncq_pp_reinit(ap);
+-	ap->ops->irq_clear(ap);
++	ap->ops->sff_irq_clear(ap);
+ 	__ata_bmdma_stop(ap);
+ 	nv_swncq_irq_clear(ap, 0xffff);
+ }
+@@ -1892,11 +1779,10 @@ static void nv_swncq_error_handler(struct ata_port *ap)
+ 
+ 	if (ap->link.sactive) {
+ 		nv_swncq_ncq_stop(ap);
+-		ehc->i.action |= ATA_EH_HARDRESET;
++		ehc->i.action |= ATA_EH_RESET;
+ 	}
+ 
+-	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+-			   nv_hardreset, ata_std_postreset);
++	ata_sff_error_handler(ap);
+ }
+ 
+ #ifdef CONFIG_PM
+@@ -2042,7 +1928,7 @@ static int nv_swncq_port_start(struct ata_port *ap)
+ static void nv_swncq_qc_prep(struct ata_queued_cmd *qc)
+ {
+ 	if (qc->tf.protocol != ATA_PROT_NCQ) {
+-		ata_qc_prep(qc);
++		ata_sff_qc_prep(qc);
+ 		return;
+ 	}
+ 
+@@ -2104,8 +1990,8 @@ static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
+ 	pp->dmafis_bits &= ~(1 << qc->tag);
+ 	pp->qc_active |= (0x1 << qc->tag);
+ 
+-	ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
+-	ap->ops->exec_command(ap, &qc->tf);
++	ap->ops->sff_tf_load(ap, &qc->tf);	 /* load tf registers */
++	ap->ops->sff_exec_command(ap, &qc->tf);
+ 
+ 	DPRINTK("Issued tag %u\n", qc->tag);
+ 
+@@ -2118,7 +2004,7 @@ static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc)
+ 	struct nv_swncq_port_priv *pp = ap->private_data;
+ 
+ 	if (qc->tf.protocol != ATA_PROT_NCQ)
+-		return ata_qc_issue_prot(qc);
++		return ata_sff_qc_issue(qc);
+ 
+ 	DPRINTK("Enter\n");
+ 
+@@ -2173,11 +2059,11 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
+ 		ata_ehi_clear_desc(ehi);
+ 		ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+ 		ehi->err_mask |= AC_ERR_HOST_BUS;
+-		ehi->action |= ATA_EH_SOFTRESET;
++		ehi->action |= ATA_EH_RESET;
+ 		return -EINVAL;
+ 	}
+ 
+-	ap->ops->irq_clear(ap);
++	ap->ops->sff_irq_clear(ap);
+ 	__ata_bmdma_stop(ap);
+ 
+ 	sactive = readl(pp->sactive_block);
+@@ -2188,7 +2074,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
+ 		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_HARDRESET;
++		ehi->action |= ATA_EH_RESET;
+ 		return -EINVAL;
+ 	}
+ 	for (i = 0; i < ATA_MAX_QUEUE; i++) {
+@@ -2299,7 +2185,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
+ 	u8 ata_stat;
+ 	int rc = 0;
+ 
+-	ata_stat = ap->ops->check_status(ap);
++	ata_stat = ap->ops->sff_check_status(ap);
+ 	nv_swncq_irq_clear(ap, fis);
+ 	if (!fis)
+ 		return;
+@@ -2324,7 +2210,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
+ 		ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis);
+ 		ehi->err_mask |= AC_ERR_DEV;
+ 		ehi->serror |= serror;
+-		ehi->action |= ATA_EH_SOFTRESET;
++		ehi->action |= ATA_EH_RESET;
+ 		ata_port_freeze(ap);
+ 		return;
+ 	}
+@@ -2356,13 +2242,13 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
+ 		if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) {
+ 			ata_ehi_push_desc(ehi, "illegal fis transaction");
+ 			ehi->err_mask |= AC_ERR_HSM;
+-			ehi->action |= ATA_EH_HARDRESET;
++			ehi->action |= ATA_EH_RESET;
+ 			goto irq_error;
+ 		}
+ 
+ 		if (!(fis & NV_SWNCQ_IRQ_DMASETUP) &&
+ 		    !(pp->ncq_flags & ncq_saw_dmas)) {
+-			ata_stat = ap->ops->check_status(ap);
++			ata_stat = ap->ops->sff_check_status(ap);
+ 			if (ata_stat & ATA_BUSY)
+ 				goto irq_exit;
+ 
+@@ -2429,6 +2315,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	static int printed_version;
+ 	const struct ata_port_info *ppi[] = { NULL, NULL };
++	struct nv_pi_priv *ipriv;
+ 	struct ata_host *host;
+ 	struct nv_host_priv *hpriv;
+ 	int rc;
+@@ -2465,7 +2352,8 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	}
+ 
+ 	ppi[0] = &nv_port_info[type];
+-	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++	ipriv = ppi[0]->private_data;
++	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ 	if (rc)
+ 		return rc;
+ 
+@@ -2503,8 +2391,8 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		nv_swncq_host_init(host);
+ 
+ 	pci_set_master(pdev);
+-	return ata_host_activate(host, pdev->irq, ppi[0]->irq_handler,
+-				 IRQF_SHARED, ppi[0]->sht);
++	return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
++				 IRQF_SHARED, ipriv->sht);
+ }
+ 
+ #ifdef CONFIG_PM
+@@ -2600,5 +2488,5 @@ module_exit(nv_exit);
+ module_param_named(adma, adma_enabled, bool, 0444);
+ MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");
+ module_param_named(swncq, swncq_enabled, bool, 0444);
+-MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: false)");
++MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
+ 
+diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
+index 11c1afe..5a10dc5 100644
+--- a/drivers/ata/sata_promise.c
++++ b/drivers/ata/sata_promise.c
+@@ -143,103 +143,57 @@ static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile
+ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
+ static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc);
+ static void pdc_irq_clear(struct ata_port *ap);
+-static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
++static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc);
+ static void pdc_freeze(struct ata_port *ap);
+ static void pdc_sata_freeze(struct ata_port *ap);
+ static void pdc_thaw(struct ata_port *ap);
+ static void pdc_sata_thaw(struct ata_port *ap);
+-static void pdc_pata_error_handler(struct ata_port *ap);
+-static void pdc_sata_error_handler(struct ata_port *ap);
++static void pdc_error_handler(struct ata_port *ap);
+ static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
+ static int pdc_pata_cable_detect(struct ata_port *ap);
+ static int pdc_sata_cable_detect(struct ata_port *ap);
+ 
+ static struct scsi_host_template pdc_ata_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
++	ATA_BASE_SHT(DRV_NAME),
+ 	.sg_tablesize		= PDC_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+-static const struct ata_port_operations pdc_sata_ops = {
+-	.tf_load		= pdc_tf_load_mmio,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= pdc_exec_command_mmio,
+-	.dev_select		= ata_std_dev_select,
+-	.check_atapi_dma	= pdc_check_atapi_dma,
++static const struct ata_port_operations pdc_common_ops = {
++	.inherits		= &ata_sff_port_ops,
+ 
++	.sff_tf_load		= pdc_tf_load_mmio,
++	.sff_exec_command	= pdc_exec_command_mmio,
++	.check_atapi_dma	= pdc_check_atapi_dma,
+ 	.qc_prep		= pdc_qc_prep,
+-	.qc_issue		= pdc_qc_issue_prot,
+-	.freeze			= pdc_sata_freeze,
+-	.thaw			= pdc_sata_thaw,
+-	.error_handler		= pdc_sata_error_handler,
+-	.post_internal_cmd	= pdc_post_internal_cmd,
+-	.cable_detect		= pdc_sata_cable_detect,
+-	.data_xfer		= ata_data_xfer,
+-	.irq_clear		= pdc_irq_clear,
+-	.irq_on			= ata_irq_on,
++	.qc_issue		= pdc_qc_issue,
++	.sff_irq_clear		= pdc_irq_clear,
+ 
+-	.scr_read		= pdc_sata_scr_read,
+-	.scr_write		= pdc_sata_scr_write,
+-	.port_start		= pdc_sata_port_start,
++	.post_internal_cmd	= pdc_post_internal_cmd,
++	.error_handler		= pdc_error_handler,
+ };
+ 
+-/* First-generation chips need a more restrictive ->check_atapi_dma op */
+-static const struct ata_port_operations pdc_old_sata_ops = {
+-	.tf_load		= pdc_tf_load_mmio,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= pdc_exec_command_mmio,
+-	.dev_select		= ata_std_dev_select,
+-	.check_atapi_dma	= pdc_old_sata_check_atapi_dma,
+-
+-	.qc_prep		= pdc_qc_prep,
+-	.qc_issue		= pdc_qc_issue_prot,
++static struct ata_port_operations pdc_sata_ops = {
++	.inherits		= &pdc_common_ops,
++	.cable_detect		= pdc_sata_cable_detect,
+ 	.freeze			= pdc_sata_freeze,
+ 	.thaw			= pdc_sata_thaw,
+-	.error_handler		= pdc_sata_error_handler,
+-	.post_internal_cmd	= pdc_post_internal_cmd,
+-	.cable_detect		= pdc_sata_cable_detect,
+-	.data_xfer		= ata_data_xfer,
+-	.irq_clear		= pdc_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+ 	.scr_read		= pdc_sata_scr_read,
+ 	.scr_write		= pdc_sata_scr_write,
+ 	.port_start		= pdc_sata_port_start,
+ };
+ 
+-static const struct ata_port_operations pdc_pata_ops = {
+-	.tf_load		= pdc_tf_load_mmio,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= pdc_exec_command_mmio,
+-	.dev_select		= ata_std_dev_select,
+-	.check_atapi_dma	= pdc_check_atapi_dma,
++/* First-generation chips need a more restrictive ->check_atapi_dma op */
++static struct ata_port_operations pdc_old_sata_ops = {
++	.inherits		= &pdc_sata_ops,
++	.check_atapi_dma	= pdc_old_sata_check_atapi_dma,
++};
+ 
+-	.qc_prep		= pdc_qc_prep,
+-	.qc_issue		= pdc_qc_issue_prot,
++static struct ata_port_operations pdc_pata_ops = {
++	.inherits		= &pdc_common_ops,
++	.cable_detect		= pdc_pata_cable_detect,
+ 	.freeze			= pdc_freeze,
+ 	.thaw			= pdc_thaw,
+-	.error_handler		= pdc_pata_error_handler,
+-	.post_internal_cmd	= pdc_post_internal_cmd,
+-	.cable_detect		= pdc_pata_cable_detect,
+-	.data_xfer		= ata_data_xfer,
+-	.irq_clear		= pdc_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+ 	.port_start		= pdc_common_port_start,
+ };
+ 
+@@ -451,7 +405,7 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
+ 	u8 *cdb = qc->cdb;
+ 	struct pdc_port_priv *pp = ap->private_data;
+ 	u8 *buf = pp->pkt;
+-	u32 *buf32 = (u32 *) buf;
++	__le32 *buf32 = (__le32 *) buf;
+ 	unsigned int dev_sel, feature;
+ 
+ 	/* set control bits (byte 0), zero delay seq id (byte 3),
+@@ -738,24 +692,12 @@ static void pdc_sata_thaw(struct ata_port *ap)
+ 	readl(host_mmio + hotplug_offset); /* flush */
+ }
+ 
+-static void pdc_common_error_handler(struct ata_port *ap, ata_reset_fn_t hardreset)
++static void pdc_error_handler(struct ata_port *ap)
+ {
+ 	if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ 		pdc_reset_port(ap);
+ 
+-	/* perform recovery */
+-	ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
+-		  ata_std_postreset);
+-}
+-
+-static void pdc_pata_error_handler(struct ata_port *ap)
+-{
+-	pdc_common_error_handler(ap, NULL);
+-}
+-
+-static void pdc_sata_error_handler(struct ata_port *ap)
+-{
+-	pdc_common_error_handler(ap, sata_std_hardreset);
++	ata_std_error_handler(ap);
+ }
+ 
+ static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
+@@ -952,7 +894,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
+ 	readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
+ }
+ 
+-static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	switch (qc->tf.protocol) {
+ 	case ATAPI_PROT_NODATA:
+@@ -972,20 +914,20 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		break;
+ 	}
+ 
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ 	WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+-	ata_tf_load(ap, tf);
++	ata_sff_tf_load(ap, tf);
+ }
+ 
+ static void pdc_exec_command_mmio(struct ata_port *ap,
+ 				  const struct ata_taskfile *tf)
+ {
+ 	WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+-	ata_exec_command(ap, tf);
++	ata_sff_exec_command(ap, tf);
+ }
+ 
+ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)
+diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
+index 91cc12c..1600107 100644
+--- a/drivers/ata/sata_qstor.c
++++ b/drivers/ata/sata_qstor.c
+@@ -121,50 +121,38 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
+ static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
+ static void qs_bmdma_stop(struct ata_queued_cmd *qc);
+ static u8 qs_bmdma_status(struct ata_port *ap);
+-static void qs_irq_clear(struct ata_port *ap);
+ static void qs_freeze(struct ata_port *ap);
+ static void qs_thaw(struct ata_port *ap);
++static int qs_prereset(struct ata_link *link, unsigned long deadline);
+ static void qs_error_handler(struct ata_port *ap);
+ 
+ static struct scsi_host_template qs_ata_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
++	ATA_BASE_SHT(DRV_NAME),
+ 	.sg_tablesize		= QS_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ENABLE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= QS_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+-static const struct ata_port_operations qs_ata_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
++static struct ata_port_operations qs_ata_ops = {
++	.inherits		= &ata_sff_port_ops,
++
+ 	.check_atapi_dma	= qs_check_atapi_dma,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
++	.bmdma_stop		= qs_bmdma_stop,
++	.bmdma_status		= qs_bmdma_status,
+ 	.qc_prep		= qs_qc_prep,
+ 	.qc_issue		= qs_qc_issue,
+-	.data_xfer		= ata_data_xfer,
++
+ 	.freeze			= qs_freeze,
+ 	.thaw			= qs_thaw,
++	.prereset		= qs_prereset,
++	.softreset		= ATA_OP_NULL,
+ 	.error_handler		= qs_error_handler,
+-	.irq_clear		= qs_irq_clear,
+-	.irq_on			= ata_irq_on,
++	.post_internal_cmd	= ATA_OP_NULL,
++
+ 	.scr_read		= qs_scr_read,
+ 	.scr_write		= qs_scr_write,
++
+ 	.port_start		= qs_port_start,
+ 	.host_stop		= qs_host_stop,
+-	.bmdma_stop		= qs_bmdma_stop,
+-	.bmdma_status		= qs_bmdma_status,
+ };
+ 
+ static const struct ata_port_info qs_port_info[] = {
+@@ -211,11 +199,6 @@ static u8 qs_bmdma_status(struct ata_port *ap)
+ 	return 0;
+ }
+ 
+-static void qs_irq_clear(struct ata_port *ap)
+-{
+-	/* nothing */
+-}
+-
+ static inline void qs_enter_reg_mode(struct ata_port *ap)
+ {
+ 	u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
+@@ -256,7 +239,7 @@ static int qs_prereset(struct ata_link *link, unsigned long deadline)
+ 	struct ata_port *ap = link->ap;
+ 
+ 	qs_reset_channel_logic(ap);
+-	return ata_std_prereset(link, deadline);
++	return ata_sff_prereset(link, deadline);
+ }
+ 
+ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+@@ -270,8 +253,7 @@ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+ static void qs_error_handler(struct ata_port *ap)
+ {
+ 	qs_enter_reg_mode(ap);
+-	ata_do_eh(ap, qs_prereset, NULL, sata_std_hardreset,
+-		  ata_std_postreset);
++	ata_std_error_handler(ap);
+ }
+ 
+ static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+@@ -321,7 +303,7 @@ static void qs_qc_prep(struct ata_queued_cmd *qc)
+ 
+ 	qs_enter_reg_mode(qc->ap);
+ 	if (qc->tf.protocol != ATA_PROT_DMA) {
+-		ata_qc_prep(qc);
++		ata_sff_qc_prep(qc);
+ 		return;
+ 	}
+ 
+@@ -380,7 +362,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
+ 	}
+ 
+ 	pp->state = qs_state_mmio;
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static void qs_do_or_die(struct ata_queued_cmd *qc, u8 status)
+@@ -469,7 +451,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
+ 				 * and pretend we knew it was ours.. (ugh).
+ 				 * This does not affect packet mode.
+ 				 */
+-				ata_check_status(ap);
++				ata_sff_check_status(ap);
+ 				handled = 1;
+ 				continue;
+ 			}
+@@ -477,7 +459,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
+ 			if (!pp || pp->state != qs_state_mmio)
+ 				continue;
+ 			if (!(qc->tf.flags & ATA_TFLAG_POLLING))
+-				handled |= ata_host_intr(ap, qc);
++				handled |= ata_sff_host_intr(ap, qc);
+ 		}
+ 	}
+ 	return handled;
+diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
+index 0b8191b..88bf421 100644
+--- a/drivers/ata/sata_sil.c
++++ b/drivers/ata/sata_sil.c
+@@ -60,7 +60,6 @@ enum {
+ 
+ 	SIL_DFL_PORT_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ 				  ATA_FLAG_MMIO,
+-	SIL_DFL_LINK_FLAGS	= ATA_LFLAG_HRST_TO_RESUME,
+ 
+ 	/*
+ 	 * Controller IDs
+@@ -168,54 +167,23 @@ static struct pci_driver sil_pci_driver = {
+ };
+ 
+ static struct scsi_host_template sil_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations sil_ops = {
++static struct ata_port_operations sil_ops = {
++	.inherits		= &ata_bmdma_port_ops,
+ 	.dev_config		= sil_dev_config,
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+ 	.set_mode		= sil_set_mode,
+-	.bmdma_setup            = ata_bmdma_setup,
+-	.bmdma_start            = ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+ 	.freeze			= sil_freeze,
+ 	.thaw			= sil_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+ 	.scr_read		= sil_scr_read,
+ 	.scr_write		= sil_scr_write,
+-	.port_start		= ata_port_start,
+ };
+ 
+ static const struct ata_port_info sil_port_info[] = {
+ 	/* sil_3112 */
+ 	{
+ 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
+-		.link_flags	= SIL_DFL_LINK_FLAGS,
+ 		.pio_mask	= 0x1f,			/* pio0-4 */
+ 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA5,
+@@ -225,7 +193,6 @@ static const struct ata_port_info sil_port_info[] = {
+ 	{
+ 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE |
+ 				  SIL_FLAG_NO_SATA_IRQ,
+-		.link_flags	= SIL_DFL_LINK_FLAGS,
+ 		.pio_mask	= 0x1f,			/* pio0-4 */
+ 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA5,
+@@ -234,7 +201,6 @@ static const struct ata_port_info sil_port_info[] = {
+ 	/* sil_3512 */
+ 	{
+ 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
+-		.link_flags	= SIL_DFL_LINK_FLAGS,
+ 		.pio_mask	= 0x1f,			/* pio0-4 */
+ 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA5,
+@@ -243,7 +209,6 @@ static const struct ata_port_info sil_port_info[] = {
+ 	/* sil_3114 */
+ 	{
+ 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
+-		.link_flags	= SIL_DFL_LINK_FLAGS,
+ 		.pio_mask	= 0x1f,			/* pio0-4 */
+ 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA5,
+@@ -404,7 +369,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+ 
+ 	if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
+ 		/* this sometimes happens, just clear IRQ */
+-		ata_chk_status(ap);
++		ap->ops->sff_check_status(ap);
+ 		return;
+ 	}
+ 
+@@ -440,15 +405,15 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+ 	}
+ 
+ 	/* check main status, clearing INTRQ */
+-	status = ata_chk_status(ap);
++	status = ap->ops->sff_check_status(ap);
+ 	if (unlikely(status & ATA_BUSY))
+ 		goto err_hsm;
+ 
+ 	/* ack bmdma irq events */
+-	ata_bmdma_irq_clear(ap);
++	ata_sff_irq_clear(ap);
+ 
+ 	/* kick HSM in the ass */
+-	ata_hsm_move(ap, qc, status, 0);
++	ata_sff_hsm_move(ap, qc, status, 0);
+ 
+ 	if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
+ 		ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
+@@ -515,8 +480,8 @@ static void sil_thaw(struct ata_port *ap)
+ 	u32 tmp;
+ 
+ 	/* clear IRQ */
+-	ata_chk_status(ap);
+-	ata_bmdma_irq_clear(ap);
++	ap->ops->sff_check_status(ap);
++	ata_sff_irq_clear(ap);
+ 
+ 	/* turn on SATA IRQ if supported */
+ 	if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ))
+@@ -690,7 +655,7 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		ioaddr->ctl_addr = mmio_base + sil_port[i].ctl;
+ 		ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma;
+ 		ioaddr->scr_addr = mmio_base + sil_port[i].scr;
+-		ata_std_ports(ioaddr);
++		ata_sff_std_ports(ioaddr);
+ 
+ 		ata_port_pbar_desc(ap, SIL_MMIO_BAR, -1, "mmio");
+ 		ata_port_pbar_desc(ap, SIL_MMIO_BAR, sil_port[i].tf, "tf");
+diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
+index df7988d..27a1101 100644
+--- a/drivers/ata/sata_sil24.c
++++ b/drivers/ata/sata_sil24.c
+@@ -254,7 +254,6 @@ enum {
+ 				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ 				  ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
+ 				  ATA_FLAG_AN | ATA_FLAG_PMP,
+-	SIL24_COMMON_LFLAGS	= ATA_LFLAG_SKIP_D2H_BSY,
+ 	SIL24_FLAG_PCIX_IRQ_WOC	= (1 << 24), /* IRQ loss errata on PCI-X */
+ 
+ 	IRQ_STAT_4PORTS		= 0xf,
+@@ -286,45 +285,45 @@ static struct sil24_cerr_info {
+ 				    "device error via D2H FIS" },
+ 	[PORT_CERR_SDB]		= { AC_ERR_DEV, 0,
+ 				    "device error via SDB FIS" },
+-	[PORT_CERR_DATA]	= { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_DATA]	= { AC_ERR_ATA_BUS, ATA_EH_RESET,
+ 				    "error in data FIS" },
+-	[PORT_CERR_SEND]	= { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_SEND]	= { AC_ERR_ATA_BUS, ATA_EH_RESET,
+ 				    "failed to transmit command FIS" },
+-	[PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
++	[PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_RESET,
+ 				     "protocol mismatch" },
+-	[PORT_CERR_DIRECTION]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
++	[PORT_CERR_DIRECTION]	= { AC_ERR_HSM, ATA_EH_RESET,
+ 				    "data directon mismatch" },
+-	[PORT_CERR_UNDERRUN]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
++	[PORT_CERR_UNDERRUN]	= { AC_ERR_HSM, ATA_EH_RESET,
+ 				    "ran out of SGEs while writing" },
+-	[PORT_CERR_OVERRUN]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
++	[PORT_CERR_OVERRUN]	= { AC_ERR_HSM, ATA_EH_RESET,
+ 				    "ran out of SGEs while reading" },
+-	[PORT_CERR_PKT_PROT]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
++	[PORT_CERR_PKT_PROT]	= { AC_ERR_HSM, ATA_EH_RESET,
+ 				    "invalid data directon for ATAPI CDB" },
+-	[PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
++	[PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET,
+ 				     "SGT not on qword boundary" },
+-	[PORT_CERR_SGT_TGTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_SGT_TGTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "PCI target abort while fetching SGT" },
+-	[PORT_CERR_SGT_MSTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_SGT_MSTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "PCI master abort while fetching SGT" },
+-	[PORT_CERR_SGT_PCIPERR]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_SGT_PCIPERR]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "PCI parity error while fetching SGT" },
+-	[PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
++	[PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET,
+ 				     "PRB not on qword boundary" },
+-	[PORT_CERR_CMD_TGTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_CMD_TGTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "PCI target abort while fetching PRB" },
+-	[PORT_CERR_CMD_MSTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_CMD_MSTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "PCI master abort while fetching PRB" },
+-	[PORT_CERR_CMD_PCIPERR]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_CMD_PCIPERR]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "PCI parity error while fetching PRB" },
+-	[PORT_CERR_XFR_UNDEF]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_XFR_UNDEF]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "undefined error while transferring data" },
+-	[PORT_CERR_XFR_TGTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_XFR_TGTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "PCI target abort while transferring data" },
+-	[PORT_CERR_XFR_MSTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_XFR_MSTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "PCI master abort while transferring data" },
+-	[PORT_CERR_XFR_PCIPERR]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++	[PORT_CERR_XFR_PCIPERR]	= { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ 				    "PCI parity error while transferring data" },
+-	[PORT_CERR_SENDSERVICE]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
++	[PORT_CERR_SENDSERVICE]	= { AC_ERR_HSM, ATA_EH_RESET,
+ 				    "FIS received while sending service FIS" },
+ };
+ 
+@@ -337,23 +336,26 @@ static struct sil24_cerr_info {
+ struct sil24_port_priv {
+ 	union sil24_cmd_block *cmd_block;	/* 32 cmd blocks */
+ 	dma_addr_t cmd_block_dma;		/* DMA base addr for them */
+-	struct ata_taskfile tf;			/* Cached taskfile registers */
+ 	int do_port_rst;
+ };
+ 
+ static void sil24_dev_config(struct ata_device *dev);
+-static u8 sil24_check_status(struct ata_port *ap);
+ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val);
+ static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
+-static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+ static int sil24_qc_defer(struct ata_queued_cmd *qc);
+ static void sil24_qc_prep(struct ata_queued_cmd *qc);
+ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
+-static void sil24_irq_clear(struct ata_port *ap);
++static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc);
+ static void sil24_pmp_attach(struct ata_port *ap);
+ static void sil24_pmp_detach(struct ata_port *ap);
+ static void sil24_freeze(struct ata_port *ap);
+ static void sil24_thaw(struct ata_port *ap);
++static int sil24_softreset(struct ata_link *link, unsigned int *class,
++			   unsigned long deadline);
++static int sil24_hardreset(struct ata_link *link, unsigned int *class,
++			   unsigned long deadline);
++static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
++			       unsigned long deadline);
+ static void sil24_error_handler(struct ata_port *ap);
+ static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);
+ static int sil24_port_start(struct ata_port *ap);
+@@ -386,52 +388,36 @@ static struct pci_driver sil24_pci_driver = {
+ };
+ 
+ static struct scsi_host_template sil24_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.change_queue_depth	= ata_scsi_change_queue_depth,
++	ATA_NCQ_SHT(DRV_NAME),
+ 	.can_queue		= SIL24_MAX_CMDS,
+-	.this_id		= ATA_SHT_THIS_ID,
+ 	.sg_tablesize		= SIL24_MAX_SGE,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+-static const struct ata_port_operations sil24_ops = {
+-	.dev_config		= sil24_dev_config,
+-
+-	.check_status		= sil24_check_status,
+-	.check_altstatus	= sil24_check_status,
+-	.dev_select		= ata_noop_dev_select,
+-
+-	.tf_read		= sil24_tf_read,
++static struct ata_port_operations sil24_ops = {
++	.inherits		= &sata_pmp_port_ops,
+ 
+ 	.qc_defer		= sil24_qc_defer,
+ 	.qc_prep		= sil24_qc_prep,
+ 	.qc_issue		= sil24_qc_issue,
++	.qc_fill_rtf		= sil24_qc_fill_rtf,
+ 
+-	.irq_clear		= sil24_irq_clear,
++	.freeze			= sil24_freeze,
++	.thaw			= sil24_thaw,
++	.softreset		= sil24_softreset,
++	.hardreset		= sil24_hardreset,
++	.pmp_softreset		= sil24_softreset,
++	.pmp_hardreset		= sil24_pmp_hardreset,
++	.error_handler		= sil24_error_handler,
++	.post_internal_cmd	= sil24_post_internal_cmd,
++	.dev_config		= sil24_dev_config,
+ 
+ 	.scr_read		= sil24_scr_read,
+ 	.scr_write		= sil24_scr_write,
+-
+ 	.pmp_attach		= sil24_pmp_attach,
+ 	.pmp_detach		= sil24_pmp_detach,
+ 
+-	.freeze			= sil24_freeze,
+-	.thaw			= sil24_thaw,
+-	.error_handler		= sil24_error_handler,
+-	.post_internal_cmd	= sil24_post_internal_cmd,
+-
+ 	.port_start		= sil24_port_start,
+-
+ #ifdef CONFIG_PM
+ 	.port_resume		= sil24_port_resume,
+ #endif
+@@ -449,7 +435,6 @@ static const struct ata_port_info sil24_port_info[] = {
+ 	{
+ 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
+ 				  SIL24_FLAG_PCIX_IRQ_WOC,
+-		.link_flags	= SIL24_COMMON_LFLAGS,
+ 		.pio_mask	= 0x1f,			/* pio0-4 */
+ 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
+@@ -458,7 +443,6 @@ static const struct ata_port_info sil24_port_info[] = {
+ 	/* sil_3132 */
+ 	{
+ 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
+-		.link_flags	= SIL24_COMMON_LFLAGS,
+ 		.pio_mask	= 0x1f,			/* pio0-4 */
+ 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
+@@ -467,7 +451,6 @@ static const struct ata_port_info sil24_port_info[] = {
+ 	/* sil_3131/sil_3531 */
+ 	{
+ 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
+-		.link_flags	= SIL24_COMMON_LFLAGS,
+ 		.pio_mask	= 0x1f,			/* pio0-4 */
+ 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
+@@ -482,9 +465,19 @@ static int sil24_tag(int tag)
+ 	return tag;
+ }
+ 
++static unsigned long sil24_port_offset(struct ata_port *ap)
++{
++	return ap->port_no * PORT_REGS_SIZE;
++}
++
++static void __iomem *sil24_port_base(struct ata_port *ap)
++{
++	return ap->host->iomap[SIL24_PORT_BAR] + sil24_port_offset(ap);
++}
++
+ static void sil24_dev_config(struct ata_device *dev)
+ {
+-	void __iomem *port = dev->link->ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(dev->link->ap);
+ 
+ 	if (dev->cdb_len == 16)
+ 		writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
+@@ -494,7 +487,7 @@ static void sil24_dev_config(struct ata_device *dev)
+ 
+ static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 	struct sil24_prb __iomem *prb;
+ 	u8 fis[6 * 4];
+ 
+@@ -503,12 +496,6 @@ static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf)
+ 	ata_tf_from_fis(fis, tf);
+ }
+ 
+-static u8 sil24_check_status(struct ata_port *ap)
+-{
+-	struct sil24_port_priv *pp = ap->private_data;
+-	return pp->tf.command;
+-}
+-
+ static int sil24_scr_map[] = {
+ 	[SCR_CONTROL]	= 0,
+ 	[SCR_STATUS]	= 1,
+@@ -518,7 +505,7 @@ static int sil24_scr_map[] = {
+ 
+ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
+ {
+-	void __iomem *scr_addr = ap->ioaddr.scr_addr;
++	void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL;
+ 
+ 	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+ 		void __iomem *addr;
+@@ -531,7 +518,7 @@ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
+ 
+ static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+ {
+-	void __iomem *scr_addr = ap->ioaddr.scr_addr;
++	void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL;
+ 
+ 	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+ 		void __iomem *addr;
+@@ -542,15 +529,9 @@ static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+ 	return -EINVAL;
+ }
+ 
+-static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+-	struct sil24_port_priv *pp = ap->private_data;
+-	*tf = pp->tf;
+-}
+-
+ static void sil24_config_port(struct ata_port *ap)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 
+ 	/* configure IRQ WoC */
+ 	if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
+@@ -575,7 +556,7 @@ static void sil24_config_port(struct ata_port *ap)
+ 
+ static void sil24_config_pmp(struct ata_port *ap, int attached)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 
+ 	if (attached)
+ 		writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT);
+@@ -585,7 +566,7 @@ static void sil24_config_pmp(struct ata_port *ap, int attached)
+ 
+ static void sil24_clear_pmp(struct ata_port *ap)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 	int i;
+ 
+ 	writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR);
+@@ -600,12 +581,12 @@ static void sil24_clear_pmp(struct ata_port *ap)
+ 
+ static int sil24_init_port(struct ata_port *ap)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 	struct sil24_port_priv *pp = ap->private_data;
+ 	u32 tmp;
+ 
+ 	/* clear PMP error status */
+-	if (ap->nr_pmp_links)
++	if (sata_pmp_attached(ap))
+ 		sil24_clear_pmp(ap);
+ 
+ 	writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
+@@ -616,7 +597,7 @@ static int sil24_init_port(struct ata_port *ap)
+ 
+ 	if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) {
+ 		pp->do_port_rst = 1;
+-		ap->link.eh_context.i.action |= ATA_EH_HARDRESET;
++		ap->link.eh_context.i.action |= ATA_EH_RESET;
+ 		return -EIO;
+ 	}
+ 
+@@ -628,7 +609,7 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
+ 				 int is_cmd, u32 ctrl,
+ 				 unsigned long timeout_msec)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 	struct sil24_port_priv *pp = ap->private_data;
+ 	struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
+ 	dma_addr_t paddr = pp->cmd_block_dma;
+@@ -670,10 +651,11 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
+ 	return rc;
+ }
+ 
+-static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
+-			      int pmp, unsigned long deadline)
++static int sil24_softreset(struct ata_link *link, unsigned int *class,
++			   unsigned long deadline)
+ {
+ 	struct ata_port *ap = link->ap;
++	int pmp = sata_srst_pmp(link);
+ 	unsigned long timeout_msec = 0;
+ 	struct ata_taskfile tf;
+ 	const char *reason;
+@@ -681,12 +663,6 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
+ 
+ 	DPRINTK("ENTER\n");
+ 
+-	if (ata_link_offline(link)) {
+-		DPRINTK("PHY reports no device\n");
+-		*class = ATA_DEV_NONE;
+-		goto out;
+-	}
+-
+ 	/* put the port into known state */
+ 	if (sil24_init_port(ap)) {
+ 		reason = "port not ready";
+@@ -711,10 +687,6 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
+ 	sil24_read_tf(ap, 0, &tf);
+ 	*class = ata_dev_classify(&tf);
+ 
+-	if (*class == ATA_DEV_UNKNOWN)
+-		*class = ATA_DEV_NONE;
+-
+- out:
+ 	DPRINTK("EXIT, class=%u\n", *class);
+ 	return 0;
+ 
+@@ -723,17 +695,11 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
+ 	return -EIO;
+ }
+ 
+-static int sil24_softreset(struct ata_link *link, unsigned int *class,
+-			   unsigned long deadline)
+-{
+-	return sil24_do_softreset(link, class, SATA_PMP_CTRL_PORT, deadline);
+-}
+-
+ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
+ 			   unsigned long deadline)
+ {
+ 	struct ata_port *ap = link->ap;
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 	struct sil24_port_priv *pp = ap->private_data;
+ 	int did_port_rst = 0;
+ 	const char *reason;
+@@ -911,7 +877,7 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct sil24_port_priv *pp = ap->private_data;
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 	unsigned int tag = sil24_tag(qc->tag);
+ 	dma_addr_t paddr;
+ 	void __iomem *activate;
+@@ -925,9 +891,10 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
+ 	return 0;
+ }
+ 
+-static void sil24_irq_clear(struct ata_port *ap)
++static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc)
+ {
+-	/* unused */
++	sil24_read_tf(qc->ap, qc->tag, &qc->result_tf);
++	return true;
+ }
+ 
+ static void sil24_pmp_attach(struct ata_port *ap)
+@@ -942,12 +909,6 @@ static void sil24_pmp_detach(struct ata_port *ap)
+ 	sil24_config_pmp(ap, 0);
+ }
+ 
+-static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class,
+-			       unsigned long deadline)
+-{
+-	return sil24_do_softreset(link, class, link->pmp, deadline);
+-}
+-
+ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
+ 			       unsigned long deadline)
+ {
+@@ -960,12 +921,12 @@ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
+ 		return rc;
+ 	}
+ 
+-	return sata_pmp_std_hardreset(link, class, deadline);
++	return sata_std_hardreset(link, class, deadline);
+ }
+ 
+ static void sil24_freeze(struct ata_port *ap)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 
+ 	/* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear
+ 	 * PORT_IRQ_ENABLE instead.
+@@ -975,7 +936,7 @@ static void sil24_freeze(struct ata_port *ap)
+ 
+ static void sil24_thaw(struct ata_port *ap)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 	u32 tmp;
+ 
+ 	/* clear IRQ */
+@@ -988,7 +949,7 @@ static void sil24_thaw(struct ata_port *ap)
+ 
+ static void sil24_error_intr(struct ata_port *ap)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 	struct sil24_port_priv *pp = ap->private_data;
+ 	struct ata_queued_cmd *qc = NULL;
+ 	struct ata_link *link;
+@@ -1022,7 +983,7 @@ static void sil24_error_intr(struct ata_port *ap)
+ 
+ 	if (irq_stat & PORT_IRQ_UNK_FIS) {
+ 		ehi->err_mask |= AC_ERR_HSM;
+-		ehi->action |= ATA_EH_SOFTRESET;
++		ehi->action |= ATA_EH_RESET;
+ 		ata_ehi_push_desc(ehi, "unknown FIS");
+ 		freeze = 1;
+ 	}
+@@ -1043,14 +1004,14 @@ static void sil24_error_intr(struct ata_port *ap)
+ 		 */
+ 		if (ap->nr_active_links >= 3) {
+ 			ehi->err_mask |= AC_ERR_OTHER;
+-			ehi->action |= ATA_EH_HARDRESET;
++			ehi->action |= ATA_EH_RESET;
+ 			ata_ehi_push_desc(ehi, "PMP DMA CS errata");
+ 			pp->do_port_rst = 1;
+ 			freeze = 1;
+ 		}
+ 
+ 		/* find out the offending link and qc */
+-		if (ap->nr_pmp_links) {
++		if (sata_pmp_attached(ap)) {
+ 			context = readl(port + PORT_CONTEXT);
+ 			pmp = (context >> 5) & 0xf;
+ 
+@@ -1064,7 +1025,7 @@ static void sil24_error_intr(struct ata_port *ap)
+ 						  irq_stat);
+ 			} else {
+ 				err_mask |= AC_ERR_HSM;
+-				action |= ATA_EH_HARDRESET;
++				action |= ATA_EH_RESET;
+ 				freeze = 1;
+ 			}
+ 		} else
+@@ -1078,28 +1039,27 @@ static void sil24_error_intr(struct ata_port *ap)
+ 		if (ci && ci->desc) {
+ 			err_mask |= ci->err_mask;
+ 			action |= ci->action;
+-			if (action & ATA_EH_RESET_MASK)
++			if (action & ATA_EH_RESET)
+ 				freeze = 1;
+ 			ata_ehi_push_desc(ehi, "%s", ci->desc);
+ 		} else {
+ 			err_mask |= AC_ERR_OTHER;
+-			action |= ATA_EH_SOFTRESET;
++			action |= ATA_EH_RESET;
+ 			freeze = 1;
+ 			ata_ehi_push_desc(ehi, "unknown command error %d",
+ 					  cerr);
+ 		}
+ 
+ 		/* record error info */
+-		if (qc) {
+-			sil24_read_tf(ap, qc->tag, &pp->tf);
++		if (qc)
+ 			qc->err_mask |= err_mask;
+-		} else
++		else
+ 			ehi->err_mask |= err_mask;
+ 
+ 		ehi->action |= action;
+ 
+ 		/* if PMP, resume */
+-		if (ap->nr_pmp_links)
++		if (sata_pmp_attached(ap))
+ 			writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT);
+ 	}
+ 
+@@ -1114,18 +1074,9 @@ static void sil24_error_intr(struct ata_port *ap)
+ 	}
+ }
+ 
+-static void sil24_finish_qc(struct ata_queued_cmd *qc)
+-{
+-	struct ata_port *ap = qc->ap;
+-	struct sil24_port_priv *pp = ap->private_data;
+-
+-	if (qc->flags & ATA_QCFLAG_RESULT_TF)
+-		sil24_read_tf(ap, qc->tag, &pp->tf);
+-}
+-
+ static inline void sil24_host_intr(struct ata_port *ap)
+ {
+-	void __iomem *port = ap->ioaddr.cmd_addr;
++	void __iomem *port = sil24_port_base(ap);
+ 	u32 slot_stat, qc_active;
+ 	int rc;
+ 
+@@ -1147,13 +1098,13 @@ static inline void sil24_host_intr(struct ata_port *ap)
+ 	}
+ 
+ 	qc_active = slot_stat & ~HOST_SSTAT_ATTN;
+-	rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
++	rc = ata_qc_complete_multiple(ap, qc_active);
+ 	if (rc > 0)
+ 		return;
+ 	if (rc < 0) {
+ 		struct ata_eh_info *ehi = &ap->link.eh_info;
+ 		ehi->err_mask |= AC_ERR_HSM;
+-		ehi->action |= ATA_EH_SOFTRESET;
++		ehi->action |= ATA_EH_RESET;
+ 		ata_port_freeze(ap);
+ 		return;
+ 	}
+@@ -1209,11 +1160,7 @@ static void sil24_error_handler(struct ata_port *ap)
+ 	if (sil24_init_port(ap))
+ 		ata_eh_freeze_port(ap);
+ 
+-	/* perform recovery */
+-	sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
+-		       ata_std_postreset, sata_pmp_std_prereset,
+-		       sil24_pmp_softreset, sil24_pmp_hardreset,
+-		       sata_pmp_std_postreset);
++	sata_pmp_error_handler(ap);
+ 
+ 	pp->do_port_rst = 0;
+ }
+@@ -1239,8 +1186,6 @@ static int sil24_port_start(struct ata_port *ap)
+ 	if (!pp)
+ 		return -ENOMEM;
+ 
+-	pp->tf.command = ATA_DRDY;
+-
+ 	cb = dmam_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
+ 	if (!cb)
+ 		return -ENOMEM;
+@@ -1251,6 +1196,9 @@ static int sil24_port_start(struct ata_port *ap)
+ 
+ 	ap->private_data = pp;
+ 
++	ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host");
++	ata_port_pbar_desc(ap, SIL24_PORT_BAR, sil24_port_offset(ap), "port");
++
+ 	return 0;
+ }
+ 
+@@ -1269,7 +1217,8 @@ static void sil24_init_controller(struct ata_host *host)
+ 	/* init ports */
+ 	for (i = 0; i < host->n_ports; i++) {
+ 		struct ata_port *ap = host->ports[i];
+-		void __iomem *port = ap->ioaddr.cmd_addr;
++		void __iomem *port = sil24_port_base(ap);
++
+ 
+ 		/* Initial PHY setting */
+ 		writel(0x20c, port + PORT_PHY_CFG);
+@@ -1302,7 +1251,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	const struct ata_port_info *ppi[] = { &pi, NULL };
+ 	void __iomem * const *iomap;
+ 	struct ata_host *host;
+-	int i, rc;
++	int rc;
+ 	u32 tmp;
+ 
+ 	/* cause link error if sil24_cmd_block is sized wrongly */
+@@ -1342,18 +1291,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		return -ENOMEM;
+ 	host->iomap = iomap;
+ 
+-	for (i = 0; i < host->n_ports; i++) {
+-		struct ata_port *ap = host->ports[i];
+-		size_t offset = ap->port_no * PORT_REGS_SIZE;
+-		void __iomem *port = iomap[SIL24_PORT_BAR] + offset;
+-
+-		host->ports[i]->ioaddr.cmd_addr = port;
+-		host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL;
+-
+-		ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host");
+-		ata_port_pbar_desc(ap, SIL24_PORT_BAR, offset, "port");
+-	}
+-
+ 	/* configure and activate the device */
+ 	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ 		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
+index a01260a..1010b30 100644
+--- a/drivers/ata/sata_sis.c
++++ b/drivers/ata/sata_sis.c
+@@ -86,45 +86,13 @@ static struct pci_driver sis_pci_driver = {
+ };
+ 
+ static struct scsi_host_template sis_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations sis_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-	.bmdma_setup            = ata_bmdma_setup,
+-	.bmdma_start            = ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
++static struct ata_port_operations sis_ops = {
++	.inherits		= &ata_bmdma_port_ops,
+ 	.scr_read		= sis_scr_read,
+ 	.scr_write		= sis_scr_write,
+-	.port_start		= ata_port_start,
+ };
+ 
+ static const struct ata_port_info sis_port_info = {
+@@ -174,7 +142,7 @@ static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+ 	u8 pmr;
+ 
+ 	if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
+-		return 0xffffffff;
++		return -EINVAL;
+ 
+ 	pci_read_config_byte(pdev, SIS_PMR, &pmr);
+ 
+@@ -190,14 +158,14 @@ static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+ 	return 0;
+ }
+ 
+-static void sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
++static int sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+ {
+ 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ 	unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
+ 	u8 pmr;
+ 
+ 	if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
+-		return;
++		return -EINVAL;
+ 
+ 	pci_read_config_byte(pdev, SIS_PMR, &pmr);
+ 
+@@ -206,6 +174,8 @@ static void sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+ 	if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+ 	    (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
+ 		pci_write_config_dword(pdev, cfg_addr+0x10, val);
++
++	return 0;
+ }
+ 
+ static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+@@ -243,14 +213,14 @@ static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+ 	pci_read_config_byte(pdev, SIS_PMR, &pmr);
+ 
+ 	if (ap->flags & SIS_FLAG_CFGSCR)
+-		sis_scr_cfg_write(ap, sc_reg, val);
++		return sis_scr_cfg_write(ap, sc_reg, val);
+ 	else {
+ 		iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+ 		if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+ 		    (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
+ 			iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
++		return 0;
+ 	}
+-	return 0;
+ }
+ 
+ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -341,7 +311,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		break;
+ 	}
+ 
+-	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ 	if (rc)
+ 		return rc;
+ 
+@@ -359,8 +329,8 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	pci_set_master(pdev);
+ 	pci_intx(pdev, 1);
+-	return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+-				 &sis_sht);
++	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++				 IRQF_SHARED, &sis_sht);
+ }
+ 
+ static int __init sis_init(void)
+diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
+index 019e367..16aa683 100644
+--- a/drivers/ata/sata_svw.c
++++ b/drivers/ata/sata_svw.c
+@@ -233,7 +233,7 @@ static void k2_bmdma_setup_mmio(struct ata_queued_cmd *qc)
+ 
+ 	/* issue r/w command if this is not a ATA DMA command*/
+ 	if (qc->tf.protocol != ATA_PROT_DMA)
+-		ap->ops->exec_command(ap, &qc->tf);
++		ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+ 
+ /**
+@@ -269,7 +269,7 @@ static void k2_bmdma_start_mmio(struct ata_queued_cmd *qc)
+ 	   and the start command. */
+ 	/* issue r/w command if the access is to ATA*/
+ 	if (qc->tf.protocol == ATA_PROT_DMA)
+-		ap->ops->exec_command(ap, &qc->tf);
++		ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+ 
+ 
+@@ -327,50 +327,23 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
+ 
+ 
+ static struct scsi_host_template k2_sata_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
++	ATA_BMDMA_SHT(DRV_NAME),
+ #ifdef CONFIG_PPC_OF
+ 	.proc_info		= k2_sata_proc_info,
+ #endif
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+ 
+-static const struct ata_port_operations k2_sata_ops = {
+-	.tf_load		= k2_sata_tf_load,
+-	.tf_read		= k2_sata_tf_read,
+-	.check_status		= k2_stat_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
++static struct ata_port_operations k2_sata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.sff_tf_load		= k2_sata_tf_load,
++	.sff_tf_read		= k2_sata_tf_read,
++	.sff_check_status	= k2_stat_check_status,
+ 	.check_atapi_dma	= k2_sata_check_atapi_dma,
+ 	.bmdma_setup		= k2_bmdma_setup_mmio,
+ 	.bmdma_start		= k2_bmdma_start_mmio,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+ 	.scr_read		= k2_sata_scr_read,
+ 	.scr_write		= k2_sata_scr_write,
+-	.port_start		= ata_port_start,
+ };
+ 
+ static const struct ata_port_info k2_port_info[] = {
+@@ -519,8 +492,8 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en
+ 	writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
+ 
+ 	pci_set_master(pdev);
+-	return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+-				 &k2_sata_sht);
++	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++				 IRQF_SHARED, &k2_sata_sht);
+ }
+ 
+ /* 0x240 is device ID for Apple K2 device
+diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
+index e3d56bc..ec04b8d 100644
+--- a/drivers/ata/sata_sx4.c
++++ b/drivers/ata/sata_sx4.c
+@@ -232,40 +232,30 @@ static void pdc20621_get_from_dimm(struct ata_host *host,
+ static void pdc20621_put_to_dimm(struct ata_host *host,
+ 				 void *psource, u32 offset, u32 size);
+ static void pdc20621_irq_clear(struct ata_port *ap);
+-static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
++static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc);
+ 
+ 
+ static struct scsi_host_template pdc_sata_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
++	ATA_BASE_SHT(DRV_NAME),
+ 	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
+ };
+ 
+-static const struct ata_port_operations pdc_20621_ops = {
+-	.tf_load		= pdc_tf_load_mmio,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= pdc_exec_command_mmio,
+-	.dev_select		= ata_std_dev_select,
++/* TODO: inherit from base port_ops after converting to new EH */
++static struct ata_port_operations pdc_20621_ops = {
++	.sff_tf_load		= pdc_tf_load_mmio,
++	.sff_tf_read		= ata_sff_tf_read,
++	.sff_check_status	= ata_sff_check_status,
++	.sff_exec_command	= pdc_exec_command_mmio,
++	.sff_dev_select		= ata_sff_dev_select,
+ 	.phy_reset		= pdc_20621_phy_reset,
+ 	.qc_prep		= pdc20621_qc_prep,
+-	.qc_issue		= pdc20621_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
++	.qc_issue		= pdc20621_qc_issue,
++	.qc_fill_rtf		= ata_sff_qc_fill_rtf,
++	.sff_data_xfer		= ata_sff_data_xfer,
+ 	.eng_timeout		= pdc_eng_timeout,
+-	.irq_clear		= pdc20621_irq_clear,
+-	.irq_on			= ata_irq_on,
++	.sff_irq_clear		= pdc20621_irq_clear,
++	.sff_irq_on		= ata_sff_irq_on,
+ 	.port_start		= pdc_port_start,
+ };
+ 
+@@ -475,7 +465,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
+ 	void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
+ 	unsigned int portno = ap->port_no;
+ 	unsigned int i, si, idx, total_len = 0, sgt_len;
+-	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
++	__le32 *buf = (__le32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
+ 
+ 	WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+ 
+@@ -693,7 +683,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
+ 	}
+ }
+ 
+-static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	switch (qc->tf.protocol) {
+ 	case ATA_PROT_DMA:
+@@ -709,7 +699,7 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		break;
+ 	}
+ 
+-	return ata_qc_issue_prot(qc);
++	return ata_sff_qc_issue(qc);
+ }
+ 
+ static inline unsigned int pdc20621_host_intr(struct ata_port *ap,
+@@ -781,7 +771,7 @@ static inline unsigned int pdc20621_host_intr(struct ata_port *ap,
+ 	/* command completion, but no data xfer */
+ 	} else if (qc->tf.protocol == ATA_PROT_NODATA) {
+ 
+-		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
++		status = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+ 		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+ 		qc->err_mask |= ac_err_mask(status);
+ 		ata_qc_complete(qc);
+@@ -890,7 +880,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
+ 		break;
+ 
+ 	default:
+-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
++		drv_stat = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+ 
+ 		ata_port_printk(ap, KERN_ERR,
+ 				"unknown timeout, cmd 0x%x stat 0x%x\n",
+@@ -909,7 +899,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ 	WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ 		tf->protocol == ATA_PROT_NODATA);
+-	ata_tf_load(ap, tf);
++	ata_sff_tf_load(ap, tf);
+ }
+ 
+ 
+@@ -917,7 +907,7 @@ static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile
+ {
+ 	WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ 		tf->protocol == ATA_PROT_NODATA);
+-	ata_exec_command(ap, tf);
++	ata_sff_exec_command(ap, tf);
+ }
+ 
+ 
+diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
+index e710e71..f277cea 100644
+--- a/drivers/ata/sata_uli.c
++++ b/drivers/ata/sata_uli.c
+@@ -76,50 +76,13 @@ static struct pci_driver uli_pci_driver = {
+ };
+ 
+ static struct scsi_host_template uli_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations uli_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.bmdma_setup            = ata_bmdma_setup,
+-	.bmdma_start            = ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
++static struct ata_port_operations uli_ops = {
++	.inherits		= &ata_bmdma_port_ops,
+ 	.scr_read		= uli_scr_read,
+ 	.scr_write		= uli_scr_write,
+-
+-	.port_start		= ata_port_start,
+ };
+ 
+ static const struct ata_port_info uli_port_info = {
+@@ -212,11 +175,11 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	host->private_data = hpriv;
+ 
+ 	/* the first two ports are standard SFF */
+-	rc = ata_pci_init_sff_host(host);
++	rc = ata_pci_sff_init_host(host);
+ 	if (rc)
+ 		return rc;
+ 
+-	rc = ata_pci_init_bmdma(host);
++	rc = ata_pci_bmdma_init(host);
+ 	if (rc)
+ 		return rc;
+ 
+@@ -237,7 +200,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 			((unsigned long)iomap[1] | ATA_PCI_CTL_OFS) + 4;
+ 		ioaddr->bmdma_addr = iomap[4] + 16;
+ 		hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4;
+-		ata_std_ports(ioaddr);
++		ata_sff_std_ports(ioaddr);
+ 
+ 		ata_port_desc(host->ports[2],
+ 			"cmd 0x%llx ctl 0x%llx bmdma 0x%llx",
+@@ -252,7 +215,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 			((unsigned long)iomap[3] | ATA_PCI_CTL_OFS) + 4;
+ 		ioaddr->bmdma_addr = iomap[4] + 24;
+ 		hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5;
+-		ata_std_ports(ioaddr);
++		ata_sff_std_ports(ioaddr);
+ 
+ 		ata_port_desc(host->ports[2],
+ 			"cmd 0x%llx ctl 0x%llx bmdma 0x%llx",
+@@ -279,8 +242,8 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	pci_set_master(pdev);
+ 	pci_intx(pdev, 1);
+-	return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+-				 &uli_sht);
++	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++				 IRQF_SHARED, &uli_sht);
+ }
+ 
+ static int __init uli_init(void)
+diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
+index 0d03f44..96deeb3 100644
+--- a/drivers/ata/sata_via.c
++++ b/drivers/ata/sata_via.c
+@@ -71,7 +71,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+ static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
+ static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+ static void svia_noop_freeze(struct ata_port *ap);
+-static void vt6420_error_handler(struct ata_port *ap);
++static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
+ static int vt6421_pata_cable_detect(struct ata_port *ap);
+ static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev);
+ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
+@@ -100,110 +100,26 @@ static struct pci_driver svia_pci_driver = {
+ };
+ 
+ static struct scsi_host_template svia_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+-static const struct ata_port_operations vt6420_sata_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.bmdma_setup            = ata_bmdma_setup,
+-	.bmdma_start            = ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
++static struct ata_port_operations vt6420_sata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
+ 	.freeze			= svia_noop_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= vt6420_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_port_start,
++	.prereset		= vt6420_prereset,
+ };
+ 
+-static const struct ata_port_operations vt6421_pata_ops = {
++static struct ata_port_operations vt6421_pata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.cable_detect		= vt6421_pata_cable_detect,
+ 	.set_piomode		= vt6421_set_pio_mode,
+ 	.set_dmamode		= vt6421_set_dma_mode,
+-
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.bmdma_setup            = ata_bmdma_setup,
+-	.bmdma_start            = ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= vt6421_pata_cable_detect,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
+-	.port_start		= ata_port_start,
+ };
+ 
+-static const struct ata_port_operations vt6421_sata_ops = {
+-	.tf_load		= ata_tf_load,
+-	.tf_read		= ata_tf_read,
+-	.check_status		= ata_check_status,
+-	.exec_command		= ata_exec_command,
+-	.dev_select		= ata_std_dev_select,
+-
+-	.bmdma_setup            = ata_bmdma_setup,
+-	.bmdma_start            = ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
+-
+-	.freeze			= ata_bmdma_freeze,
+-	.thaw			= ata_bmdma_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.cable_detect		= ata_cable_sata,
+-
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+-
++static struct ata_port_operations vt6421_sata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
+ 	.scr_read		= svia_scr_read,
+ 	.scr_write		= svia_scr_write,
+-
+-	.port_start		= ata_port_start,
+ };
+ 
+ static const struct ata_port_info vt6420_port_info = {
+@@ -257,8 +173,8 @@ static void svia_noop_freeze(struct ata_port *ap)
+ 	/* Some VIA controllers choke if ATA_NIEN is manipulated in
+ 	 * certain way.  Leave it alone and just clear pending IRQ.
+ 	 */
+-	ata_chk_status(ap);
+-	ata_bmdma_irq_clear(ap);
++	ap->ops->sff_check_status(ap);
++	ata_sff_irq_clear(ap);
+ }
+ 
+ /**
+@@ -320,23 +236,17 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
+ 
+ 	if (!online) {
+ 		/* tell EH to bail */
+-		ehc->i.action &= ~ATA_EH_RESET_MASK;
++		ehc->i.action &= ~ATA_EH_RESET;
+ 		return 0;
+ 	}
+ 
+  skip_scr:
+ 	/* wait for !BSY */
+-	ata_wait_ready(ap, deadline);
++	ata_sff_wait_ready(link, deadline);
+ 
+ 	return 0;
+ }
+ 
+-static void vt6420_error_handler(struct ata_port *ap)
+-{
+-	ata_bmdma_drive_eh(ap, vt6420_prereset, ata_std_softreset, NULL,
+-			   ata_std_postreset);
+-}
+-
+ static int vt6421_pata_cable_detect(struct ata_port *ap)
+ {
+ 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+@@ -394,7 +304,7 @@ static void vt6421_init_addrs(struct ata_port *ap)
+ 	ioaddr->bmdma_addr = bmdma_addr;
+ 	ioaddr->scr_addr = vt6421_scr_addr(iomap[5], ap->port_no);
+ 
+-	ata_std_ports(ioaddr);
++	ata_sff_std_ports(ioaddr);
+ 
+ 	ata_port_pbar_desc(ap, ap->port_no, -1, "port");
+ 	ata_port_pbar_desc(ap, 4, ap->port_no * 8, "bmdma");
+@@ -406,7 +316,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
+ 	struct ata_host *host;
+ 	int rc;
+ 
+-	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ 	if (rc)
+ 		return rc;
+ 	*r_host = host;
+@@ -538,8 +448,8 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	svia_configure(pdev);
+ 
+ 	pci_set_master(pdev);
+-	return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+-				 &svia_sht);
++	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++				 IRQF_SHARED, &svia_sht);
+ }
+ 
+ static int __init svia_init(void)
+diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
+index 95ae3ed..f3d635c 100644
+--- a/drivers/ata/sata_vsc.c
++++ b/drivers/ata/sata_vsc.c
+@@ -200,7 +200,7 @@ static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 	u16 nsect, lbal, lbam, lbah, feature;
+ 
+-	tf->command = ata_check_status(ap);
++	tf->command = ata_sff_check_status(ap);
+ 	tf->device = readw(ioaddr->device_addr);
+ 	feature = readw(ioaddr->error_addr);
+ 	nsect = readw(ioaddr->nsect_addr);
+@@ -243,7 +243,7 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap)
+ 
+ 	qc = ata_qc_from_tag(ap, ap->link.active_tag);
+ 	if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING)))
+-		handled = ata_host_intr(ap, qc);
++		handled = ata_sff_host_intr(ap, qc);
+ 
+ 	/* We received an interrupt during a polled command,
+ 	 * or some other spurious condition.  Interrupt reporting
+@@ -251,7 +251,7 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap)
+ 	 * simply clear the interrupt
+ 	 */
+ 	if (unlikely(!handled))
+-		ata_chk_status(ap);
++		ap->ops->sff_check_status(ap);
+ }
+ 
+ /*
+@@ -300,46 +300,18 @@ out:
+ 
+ 
+ static struct scsi_host_template vsc_sata_sht = {
+-	.module			= THIS_MODULE,
+-	.name			= DRV_NAME,
+-	.ioctl			= ata_scsi_ioctl,
+-	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
+-	.this_id		= ATA_SHT_THIS_ID,
+-	.sg_tablesize		= LIBATA_MAX_PRD,
+-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+-	.emulated		= ATA_SHT_EMULATED,
+-	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+-	.proc_name		= DRV_NAME,
+-	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= ata_scsi_slave_config,
+-	.slave_destroy		= ata_scsi_slave_destroy,
+-	.bios_param		= ata_std_bios_param,
++	ATA_BMDMA_SHT(DRV_NAME),
+ };
+ 
+ 
+-static const struct ata_port_operations vsc_sata_ops = {
+-	.tf_load		= vsc_sata_tf_load,
+-	.tf_read		= vsc_sata_tf_read,
+-	.exec_command		= ata_exec_command,
+-	.check_status		= ata_check_status,
+-	.dev_select		= ata_std_dev_select,
+-	.bmdma_setup            = ata_bmdma_setup,
+-	.bmdma_start            = ata_bmdma_start,
+-	.bmdma_stop		= ata_bmdma_stop,
+-	.bmdma_status		= ata_bmdma_status,
+-	.qc_prep		= ata_qc_prep,
+-	.qc_issue		= ata_qc_issue_prot,
+-	.data_xfer		= ata_data_xfer,
++static struct ata_port_operations vsc_sata_ops = {
++	.inherits		= &ata_bmdma_port_ops,
++	.sff_tf_load		= vsc_sata_tf_load,
++	.sff_tf_read		= vsc_sata_tf_read,
+ 	.freeze			= vsc_freeze,
+ 	.thaw			= vsc_thaw,
+-	.error_handler		= ata_bmdma_error_handler,
+-	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	.irq_clear		= ata_bmdma_irq_clear,
+-	.irq_on			= ata_irq_on,
+ 	.scr_read		= vsc_sata_scr_read,
+ 	.scr_write		= vsc_sata_scr_write,
+-	.port_start		= ata_port_start,
+ };
+ 
+ static void __devinit vsc_sata_setup_port(struct ata_ioports *port,
+diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
+index 7b44a59..5aa12b0 100644
+--- a/drivers/atm/ambassador.c
++++ b/drivers/atm/ambassador.c
+@@ -437,7 +437,7 @@ static inline void dump_skb (char * prefix, unsigned int vc, struct sk_buff * sk
+ 
+ /* see limitations under Hardware Features */
+ 
+-static inline int check_area (void * start, size_t length) {
++static int check_area (void * start, size_t length) {
+   // assumes length > 0
+   const u32 fourmegmask = -1 << 22;
+   const u32 twofivesixmask = -1 << 8;
+@@ -456,7 +456,7 @@ static inline int check_area (void * start, size_t length) {
+ 
+ /********** free an skb (as per ATM device driver documentation) **********/
+ 
+-static inline void amb_kfree_skb (struct sk_buff * skb) {
++static void amb_kfree_skb (struct sk_buff * skb) {
+   if (ATM_SKB(skb)->vcc->pop) {
+     ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb);
+   } else {
+@@ -466,7 +466,7 @@ static inline void amb_kfree_skb (struct sk_buff * skb) {
+ 
+ /********** TX completion **********/
+ 
+-static inline void tx_complete (amb_dev * dev, tx_out * tx) {
++static void tx_complete (amb_dev * dev, tx_out * tx) {
+   tx_simple * tx_descr = bus_to_virt (tx->handle);
+   struct sk_buff * skb = tx_descr->skb;
+   
+@@ -643,7 +643,7 @@ static int command_do (amb_dev * dev, command * cmd) {
+ 
+ /********** TX queue pair **********/
+ 
+-static inline int tx_give (amb_dev * dev, tx_in * tx) {
++static int tx_give (amb_dev * dev, tx_in * tx) {
+   amb_txq * txq = &dev->txq;
+   unsigned long flags;
+   
+@@ -675,7 +675,7 @@ static inline int tx_give (amb_dev * dev, tx_in * tx) {
+   }
+ }
+ 
+-static inline int tx_take (amb_dev * dev) {
++static int tx_take (amb_dev * dev) {
+   amb_txq * txq = &dev->txq;
+   unsigned long flags;
+   
+@@ -703,7 +703,7 @@ static inline int tx_take (amb_dev * dev) {
+ 
+ /********** RX queue pairs **********/
+ 
+-static inline int rx_give (amb_dev * dev, rx_in * rx, unsigned char pool) {
++static int rx_give (amb_dev * dev, rx_in * rx, unsigned char pool) {
+   amb_rxq * rxq = &dev->rxq[pool];
+   unsigned long flags;
+   
+@@ -728,7 +728,7 @@ static inline int rx_give (amb_dev * dev, rx_in * rx, unsigned char pool) {
+   }
+ }
+ 
+-static inline int rx_take (amb_dev * dev, unsigned char pool) {
++static int rx_take (amb_dev * dev, unsigned char pool) {
+   amb_rxq * rxq = &dev->rxq[pool];
+   unsigned long flags;
+   
+@@ -761,7 +761,7 @@ static inline int rx_take (amb_dev * dev, unsigned char pool) {
+ /********** RX Pool handling **********/
+ 
+ /* pre: buffers_wanted = 0, post: pending = 0 */
+-static inline void drain_rx_pool (amb_dev * dev, unsigned char pool) {
++static void drain_rx_pool (amb_dev * dev, unsigned char pool) {
+   amb_rxq * rxq = &dev->rxq[pool];
+   
+   PRINTD (DBG_FLOW|DBG_POOL, "drain_rx_pool %p %hu", dev, pool);
+@@ -796,7 +796,7 @@ static void drain_rx_pools (amb_dev * dev) {
+     drain_rx_pool (dev, pool);
+ }
+ 
+-static inline void fill_rx_pool (amb_dev * dev, unsigned char pool,
++static void fill_rx_pool (amb_dev * dev, unsigned char pool,
+                                  gfp_t priority)
+ {
+   rx_in rx;
+@@ -846,7 +846,7 @@ static void fill_rx_pools (amb_dev * dev) {
+ 
+ /********** enable host interrupts **********/
+ 
+-static inline void interrupts_on (amb_dev * dev) {
++static void interrupts_on (amb_dev * dev) {
+   wr_plain (dev, offsetof(amb_mem, interrupt_control),
+ 	    rd_plain (dev, offsetof(amb_mem, interrupt_control))
+ 	    | AMB_INTERRUPT_BITS);
+@@ -854,7 +854,7 @@ static inline void interrupts_on (amb_dev * dev) {
+ 
+ /********** disable host interrupts **********/
+ 
+-static inline void interrupts_off (amb_dev * dev) {
++static void interrupts_off (amb_dev * dev) {
+   wr_plain (dev, offsetof(amb_mem, interrupt_control),
+ 	    rd_plain (dev, offsetof(amb_mem, interrupt_control))
+ 	    &~ AMB_INTERRUPT_BITS);
+diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
+index 9b2cf25..c0ac728 100644
+--- a/drivers/atm/horizon.c
++++ b/drivers/atm/horizon.c
+@@ -424,7 +424,7 @@ static inline void FLUSH_RX_CHANNEL (hrz_dev * dev, u16 channel) {
+   return;
+ }
+ 
+-static inline void WAIT_FLUSH_RX_COMPLETE (hrz_dev * dev) {
++static void WAIT_FLUSH_RX_COMPLETE (hrz_dev * dev) {
+   while (rd_regw (dev, RX_CHANNEL_PORT_OFF) & FLUSH_CHANNEL)
+     ;
+   return;
+@@ -435,7 +435,7 @@ static inline void SELECT_RX_CHANNEL (hrz_dev * dev, u16 channel) {
+   return;
+ }
+ 
+-static inline void WAIT_UPDATE_COMPLETE (hrz_dev * dev) {
++static void WAIT_UPDATE_COMPLETE (hrz_dev * dev) {
+   while (rd_regw (dev, RX_CHANNEL_PORT_OFF) & RX_CHANNEL_UPDATE_IN_PROGRESS)
+     ;
+   return;
+@@ -796,7 +796,7 @@ static void hrz_change_vc_qos (ATM_RXER * rxer, MAAL_QOS * qos) {
+ 
+ /********** free an skb (as per ATM device driver documentation) **********/
+ 
+-static inline void hrz_kfree_skb (struct sk_buff * skb) {
++static void hrz_kfree_skb (struct sk_buff * skb) {
+   if (ATM_SKB(skb)->vcc->pop) {
+     ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb);
+   } else {
+@@ -1076,7 +1076,7 @@ static void rx_schedule (hrz_dev * dev, int irq) {
+ 
+ /********** handle RX bus master complete events **********/
+ 
+-static inline void rx_bus_master_complete_handler (hrz_dev * dev) {
++static void rx_bus_master_complete_handler (hrz_dev * dev) {
+   if (test_bit (rx_busy, &dev->flags)) {
+     rx_schedule (dev, 1);
+   } else {
+@@ -1089,7 +1089,7 @@ static inline void rx_bus_master_complete_handler (hrz_dev * dev) {
+ 
+ /********** (queue to) become the next TX thread **********/
+ 
+-static inline int tx_hold (hrz_dev * dev) {
++static int tx_hold (hrz_dev * dev) {
+   PRINTD (DBG_TX, "sleeping at tx lock %p %lu", dev, dev->flags);
+   wait_event_interruptible(dev->tx_queue, (!test_and_set_bit(tx_busy, &dev->flags)));
+   PRINTD (DBG_TX, "woken at tx lock %p %lu", dev, dev->flags);
+@@ -1232,7 +1232,7 @@ static void tx_schedule (hrz_dev * const dev, int irq) {
+ 
+ /********** handle TX bus master complete events **********/
+ 
+-static inline void tx_bus_master_complete_handler (hrz_dev * dev) {
++static void tx_bus_master_complete_handler (hrz_dev * dev) {
+   if (test_bit (tx_busy, &dev->flags)) {
+     tx_schedule (dev, 1);
+   } else {
+@@ -1246,7 +1246,7 @@ static inline void tx_bus_master_complete_handler (hrz_dev * dev) {
+ /********** move RX Q pointer to next item in circular buffer **********/
+ 
+ // called only from IRQ sub-handler
+-static inline u32 rx_queue_entry_next (hrz_dev * dev) {
++static u32 rx_queue_entry_next (hrz_dev * dev) {
+   u32 rx_queue_entry;
+   spin_lock (&dev->mem_lock);
+   rx_queue_entry = rd_mem (dev, &dev->rx_q_entry->entry);
+@@ -1270,7 +1270,7 @@ static inline void rx_disabled_handler (hrz_dev * dev) {
+ /********** handle RX data received by device **********/
+ 
+ // called from IRQ handler
+-static inline void rx_data_av_handler (hrz_dev * dev) {
++static void rx_data_av_handler (hrz_dev * dev) {
+   u32 rx_queue_entry;
+   u32 rx_queue_entry_flags;
+   u16 rx_len;
+@@ -1394,7 +1394,7 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id)
+   irq_ok = 0;
+   while ((int_source = rd_regl (dev, INT_SOURCE_REG_OFF)
+ 	  & INTERESTING_INTERRUPTS)) {
+-    // In the interests of fairness, the (inline) handlers below are
++    // In the interests of fairness, the handlers below are
+     // called in sequence and without immediate return to the head of
+     // the while loop. This is only of issue for slow hosts (or when
+     // debugging messages are on). Really slow hosts may find a fast
+@@ -1458,7 +1458,7 @@ static void do_housekeeping (unsigned long arg) {
+ /********** find an idle channel for TX and set it up **********/
+ 
+ // called with tx_busy set
+-static inline short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) {
++static short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) {
+   unsigned short idle_channels;
+   short tx_channel = -1;
+   unsigned int spin_count;
+@@ -1777,13 +1777,13 @@ static void hrz_reset (const hrz_dev * dev) {
+ 
+ /********** read the burnt in address **********/
+ 
+-static inline void WRITE_IT_WAIT (const hrz_dev *dev, u32 ctrl)
++static void WRITE_IT_WAIT (const hrz_dev *dev, u32 ctrl)
+ {
+ 	wr_regl (dev, CONTROL_0_REG, ctrl);
+ 	udelay (5);
+ }
+   
+-static inline void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
++static void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
+ {
+ 	// DI must be valid around rising SK edge
+ 	WRITE_IT_WAIT(dev, ctrl & ~SEEPROM_SK);
+diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
+index 670c093..5c28ca7 100644
+--- a/drivers/atm/iphase.c
++++ b/drivers/atm/iphase.c
+@@ -60,7 +60,8 @@
+ #include <asm/uaccess.h>  
+ #include <asm/string.h>  
+ #include <asm/byteorder.h>  
+-#include <linux/vmalloc.h>  
++#include <linux/vmalloc.h>
++#include <linux/jiffies.h>
+ #include "iphase.h"		  
+ #include "suni.h"		  
+ #define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))  
+@@ -189,7 +190,7 @@ static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {
+   int ltimeout;
+ 
+   ia_hack_tcq (dev);
+-  if(((jiffies - timer)>50)||((dev->ffL.tcq_rd==dev->host_tcq_wr))){      
++  if((time_after(jiffies,timer+50)) || ((dev->ffL.tcq_rd==dev->host_tcq_wr))) {
+      timer = jiffies; 
+      i=0;
+      while (i < dev->num_tx_desc) {
+@@ -1225,7 +1226,7 @@ static void rx_intr(struct atm_dev *dev)
+         iadev->rx_tmp_jif = jiffies; 
+         iadev->rxing = 0;
+      } 
+-     else if (((jiffies - iadev->rx_tmp_jif) > 50) && 
++     else if ((time_after(jiffies, iadev->rx_tmp_jif + 50)) &&
+                ((iadev->rx_pkt_cnt - iadev->rx_tmp_cnt) == 0)) {
+         for (i = 1; i <= iadev->num_rx_desc; i++)
+                free_desc(dev, i);
+diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
+index 0c205b0..38c769f 100644
+--- a/drivers/atm/nicstar.c
++++ b/drivers/atm/nicstar.c
+@@ -125,85 +125,6 @@
+ #define ATM_SKB(s) (&(s)->atm)
+ #endif
+ 
+-   /* Spinlock debugging stuff */
+-#ifdef NS_DEBUG_SPINLOCKS /* See nicstar.h */
+-#define ns_grab_int_lock(card,flags) \
+- do { \
+-    unsigned long nsdsf, nsdsf2; \
+-    local_irq_save(flags); \
+-    save_flags(nsdsf); cli();\
+-    if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \
+-                                (flags)&(1<<9)?"en":"dis"); \
+-    if (spin_is_locked(&(card)->int_lock) && \
+-        (card)->cpu_int == smp_processor_id()) { \
+-       printk("nicstar.c: line %d (cpu %d) int_lock already locked at line %d (cpu %d)\n", \
+-              __LINE__, smp_processor_id(), (card)->has_int_lock, \
+-              (card)->cpu_int); \
+-       printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+-    } \
+-    if (spin_is_locked(&(card)->res_lock) && \
+-        (card)->cpu_res == smp_processor_id()) { \
+-       printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying int)\n", \
+-              __LINE__, smp_processor_id(), (card)->has_res_lock, \
+-              (card)->cpu_res); \
+-       printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+-    } \
+-    spin_lock_irq(&(card)->int_lock); \
+-    (card)->has_int_lock = __LINE__; \
+-    (card)->cpu_int = smp_processor_id(); \
+-    restore_flags(nsdsf); } while (0)
+-#define ns_grab_res_lock(card,flags) \
+- do { \
+-    unsigned long nsdsf, nsdsf2; \
+-    local_irq_save(flags); \
+-    save_flags(nsdsf); cli();\
+-    if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \
+-                                (flags)&(1<<9)?"en":"dis"); \
+-    if (spin_is_locked(&(card)->res_lock) && \
+-        (card)->cpu_res == smp_processor_id()) { \
+-       printk("nicstar.c: line %d (cpu %d) res_lock already locked at line %d (cpu %d)\n", \
+-              __LINE__, smp_processor_id(), (card)->has_res_lock, \
+-              (card)->cpu_res); \
+-       printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+-    } \
+-    spin_lock_irq(&(card)->res_lock); \
+-    (card)->has_res_lock = __LINE__; \
+-    (card)->cpu_res = smp_processor_id(); \
+-    restore_flags(nsdsf); } while (0)
+-#define ns_grab_scq_lock(card,scq,flags) \
+- do { \
+-    unsigned long nsdsf, nsdsf2; \
+-    local_irq_save(flags); \
+-    save_flags(nsdsf); cli();\
+-    if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \
+-                                (flags)&(1<<9)?"en":"dis"); \
+-    if (spin_is_locked(&(scq)->lock) && \
+-        (scq)->cpu_lock == smp_processor_id()) { \
+-       printk("nicstar.c: line %d (cpu %d) this scq_lock already locked at line %d (cpu %d)\n", \
+-              __LINE__, smp_processor_id(), (scq)->has_lock, \
+-              (scq)->cpu_lock); \
+-       printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+-    } \
+-    if (spin_is_locked(&(card)->res_lock) && \
+-        (card)->cpu_res == smp_processor_id()) { \
+-       printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying scq)\n", \
+-              __LINE__, smp_processor_id(), (card)->has_res_lock, \
+-              (card)->cpu_res); \
+-       printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+-    } \
+-    spin_lock_irq(&(scq)->lock); \
+-    (scq)->has_lock = __LINE__; \
+-    (scq)->cpu_lock = smp_processor_id(); \
+-    restore_flags(nsdsf); } while (0)
+-#else /* !NS_DEBUG_SPINLOCKS */
+-#define ns_grab_int_lock(card,flags) \
+-        spin_lock_irqsave(&(card)->int_lock,(flags))
+-#define ns_grab_res_lock(card,flags) \
+-        spin_lock_irqsave(&(card)->res_lock,(flags))
+-#define ns_grab_scq_lock(card,scq,flags) \
+-        spin_lock_irqsave(&(scq)->lock,flags)
+-#endif /* NS_DEBUG_SPINLOCKS */
+-
+ 
+ /* Function declarations ******************************************************/
+ 
+@@ -422,7 +343,7 @@ static u32 ns_read_sram(ns_dev *card, u32 sram_address)
+    sram_address <<= 2;
+    sram_address &= 0x0007FFFC;	/* address must be dword aligned */
+    sram_address |= 0x50000000;	/* SRAM read command */
+-   ns_grab_res_lock(card, flags);
++   spin_lock_irqsave(&card->res_lock, flags);
+    while (CMD_BUSY(card));
+    writel(sram_address, card->membase + CMD);
+    while (CMD_BUSY(card));
+@@ -440,7 +361,7 @@ static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count)
+    count--;	/* count range now is 0..3 instead of 1..4 */
+    c = count;
+    c <<= 2;	/* to use increments of 4 */
+-   ns_grab_res_lock(card, flags);
++   spin_lock_irqsave(&card->res_lock, flags);
+    while (CMD_BUSY(card));
+    for (i = 0; i <= c; i += 4)
+       writel(*(value++), card->membase + i);
+@@ -1166,7 +1087,7 @@ static void push_rxbufs(ns_dev *card, struct sk_buff *skb)
+             card->lbfqc += 2;
+       }
+ 
+-      ns_grab_res_lock(card, flags);
++      spin_lock_irqsave(&card->res_lock, flags);
+ 
+       while (CMD_BUSY(card));
+       writel(addr2, card->membase + DR3);
+@@ -1206,7 +1127,7 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id)
+ 
+    PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index);
+ 
+-   ns_grab_int_lock(card, flags);
++   spin_lock_irqsave(&card->int_lock, flags);
+    
+    stat_r = readl(card->membase + STAT);
+ 
+@@ -1585,7 +1506,7 @@ static void ns_close(struct atm_vcc *vcc)
+       unsigned long flags;
+       
+       addr = NS_RCT + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE;
+-      ns_grab_res_lock(card, flags);
++      spin_lock_irqsave(&card->res_lock, flags);
+       while(CMD_BUSY(card));
+       writel(NS_CMD_CLOSE_CONNECTION | addr << 2, card->membase + CMD);
+       spin_unlock_irqrestore(&card->res_lock, flags);
+@@ -1607,7 +1528,7 @@ static void ns_close(struct atm_vcc *vcc)
+ 	                       NS_SKB(iovb)->iovcnt);
+          NS_SKB(iovb)->iovcnt = 0;
+          NS_SKB(iovb)->vcc = NULL;
+-         ns_grab_int_lock(card, flags);
++         spin_lock_irqsave(&card->int_lock, flags);
+          recycle_iov_buf(card, iovb);
+          spin_unlock_irqrestore(&card->int_lock, flags);
+          vc->rx_iov = NULL;
+@@ -1629,7 +1550,7 @@ static void ns_close(struct atm_vcc *vcc)
+ 
+       for (;;)
+       {
+-         ns_grab_scq_lock(card, scq, flags);
++         spin_lock_irqsave(&scq->lock, flags);
+          scqep = scq->next;
+          if (scqep == scq->base)
+             scqep = scq->last;
+@@ -1691,7 +1612,7 @@ static void ns_close(struct atm_vcc *vcc)
+      unsigned long flags;
+      scq_info *scq = card->scq0;
+ 
+-     ns_grab_scq_lock(card, scq, flags);
++     spin_lock_irqsave(&scq->lock, flags);
+ 
+      for(i = 0; i < scq->num_entries; i++) {
+        if(scq->skb[i] && ATM_SKB(scq->skb[i])->vcc == vcc) {
+@@ -1892,7 +1813,7 @@ static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd,
+    u32 data;
+    int index;
+    
+-   ns_grab_scq_lock(card, scq, flags);
++   spin_lock_irqsave(&scq->lock, flags);
+    while (scq->tail == scq->next)
+    {
+       if (in_interrupt()) {
+@@ -1904,7 +1825,7 @@ static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd,
+       scq->full = 1;
+       spin_unlock_irqrestore(&scq->lock, flags);
+       interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT);
+-      ns_grab_scq_lock(card, scq, flags);
++      spin_lock_irqsave(&scq->lock, flags);
+ 
+       if (scq->full) {
+          spin_unlock_irqrestore(&scq->lock, flags);
+@@ -1953,7 +1874,7 @@ static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd,
+          if (has_run++) break;
+          spin_unlock_irqrestore(&scq->lock, flags);
+          interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT);
+-         ns_grab_scq_lock(card, scq, flags);
++         spin_lock_irqsave(&scq->lock, flags);
+       }
+ 
+       if (!scq->full)
+@@ -2090,7 +2011,7 @@ static void drain_scq(ns_dev *card, scq_info *scq, int pos)
+       return;
+    }
+ 
+-   ns_grab_scq_lock(card, scq, flags);
++   spin_lock_irqsave(&scq->lock, flags);
+    i = (int) (scq->tail - scq->base);
+    if (++i == scq->num_entries)
+       i = 0;
+@@ -2898,7 +2819,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
+ 	       {
+                   struct sk_buff *hb;
+ 
+-                  ns_grab_int_lock(card, flags);
++                  spin_lock_irqsave(&card->int_lock, flags);
+ 		  hb = skb_dequeue(&card->hbpool.queue);
+ 		  card->hbpool.count--;
+                   spin_unlock_irqrestore(&card->int_lock, flags);
+@@ -2917,7 +2838,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
+                   if (hb == NULL)
+                      return -ENOMEM;
+                   NS_SKB_CB(hb)->buf_type = BUF_NONE;
+-                  ns_grab_int_lock(card, flags);
++                  spin_lock_irqsave(&card->int_lock, flags);
+                   skb_queue_tail(&card->hbpool.queue, hb);
+                   card->hbpool.count++;
+                   spin_unlock_irqrestore(&card->int_lock, flags);
+@@ -2929,7 +2850,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
+ 	       {
+ 	          struct sk_buff *iovb;
+ 
+-                  ns_grab_int_lock(card, flags);
++                  spin_lock_irqsave(&card->int_lock, flags);
+ 		  iovb = skb_dequeue(&card->iovpool.queue);
+ 		  card->iovpool.count--;
+                   spin_unlock_irqrestore(&card->int_lock, flags);
+@@ -2948,7 +2869,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
+                   if (iovb == NULL)
+                      return -ENOMEM;
+                   NS_SKB_CB(iovb)->buf_type = BUF_NONE;
+-                  ns_grab_int_lock(card, flags);
++                  spin_lock_irqsave(&card->int_lock, flags);
+                   skb_queue_tail(&card->iovpool.queue, iovb);
+                   card->iovpool.count++;
+                   spin_unlock_irqrestore(&card->int_lock, flags);
+@@ -2995,7 +2916,7 @@ static void ns_poll(unsigned long arg)
+       /* Probably it isn't worth spinning */
+          continue;
+       }
+-      ns_grab_int_lock(card, flags);
++      spin_lock_irqsave(&card->int_lock, flags);
+ 
+       stat_w = 0;
+       stat_r = readl(card->membase + STAT);
+@@ -3062,7 +2983,7 @@ static void ns_phy_put(struct atm_dev *dev, unsigned char value,
+    unsigned long flags;
+ 
+    card = dev->dev_data;
+-   ns_grab_res_lock(card, flags);
++   spin_lock_irqsave(&card->res_lock, flags);
+    while(CMD_BUSY(card));
+    writel((unsigned long) value, card->membase + DR0);
+    writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF),
+@@ -3079,7 +3000,7 @@ static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr)
+    unsigned long data;
+ 
+    card = dev->dev_data;
+-   ns_grab_res_lock(card, flags);
++   spin_lock_irqsave(&card->res_lock, flags);
+    while(CMD_BUSY(card));
+    writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF),
+           card->membase + CMD);
+diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h
+index 5997bcb..6010e3d 100644
+--- a/drivers/atm/nicstar.h
++++ b/drivers/atm/nicstar.h
+@@ -28,8 +28,6 @@
+ 
+ /* Options ********************************************************************/
+ 
+-#undef NS_DEBUG_SPINLOCKS
+-
+ #define NS_MAX_CARDS 4		/* Maximum number of NICStAR based cards
+ 				   controlled by the device driver. Must
+                                    be <= 5 */
+@@ -721,10 +719,6 @@ typedef struct scq_info
+    wait_queue_head_t scqfull_waitq;
+    volatile char full;			/* SCQ full indicator */
+    spinlock_t lock;			/* SCQ spinlock */
+-#ifdef NS_DEBUG_SPINLOCKS
+-   volatile long has_lock;
+-   volatile int cpu_lock;
+-#endif /* NS_DEBUG_SPINLOCKS */
+ } scq_info;
+ 
+ 
+@@ -810,12 +804,6 @@ typedef struct ns_dev
+    unsigned intcnt;			/* Interrupt counter */
+    spinlock_t int_lock;		/* Interrupt lock */
+    spinlock_t res_lock;		/* Card resource lock */
+-#ifdef NS_DEBUG_SPINLOCKS
+-   volatile long has_int_lock;
+-   volatile int cpu_int;
+-   volatile long has_res_lock;
+-   volatile int cpu_res;
+-#endif /* NS_DEBUG_SPINLOCKS */
+ } ns_dev;
+ 
+ 
+diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
+index 3b43e8a..f57652d 100644
+--- a/drivers/base/attribute_container.c
++++ b/drivers/base/attribute_container.c
+@@ -27,21 +27,21 @@
+ struct internal_container {
+ 	struct klist_node node;
+ 	struct attribute_container *cont;
+-	struct class_device classdev;
++	struct device classdev;
+ };
+ 
+ static void internal_container_klist_get(struct klist_node *n)
+ {
+ 	struct internal_container *ic =
+ 		container_of(n, struct internal_container, node);
+-	class_device_get(&ic->classdev);
++	get_device(&ic->classdev);
+ }
+ 
+ static void internal_container_klist_put(struct klist_node *n)
+ {
+ 	struct internal_container *ic =
+ 		container_of(n, struct internal_container, node);
+-	class_device_put(&ic->classdev);
++	put_device(&ic->classdev);
+ }
+ 
+ 
+@@ -53,7 +53,7 @@ static void internal_container_klist_put(struct klist_node *n)
+  * Returns the container associated with this classdev.
+  */
+ struct attribute_container *
+-attribute_container_classdev_to_container(struct class_device *classdev)
++attribute_container_classdev_to_container(struct device *classdev)
+ {
+ 	struct internal_container *ic =
+ 		container_of(classdev, struct internal_container, classdev);
+@@ -110,11 +110,11 @@ attribute_container_unregister(struct attribute_container *cont)
+ EXPORT_SYMBOL_GPL(attribute_container_unregister);
+ 
+ /* private function used as class release */
+-static void attribute_container_release(struct class_device *classdev)
++static void attribute_container_release(struct device *classdev)
+ {
+ 	struct internal_container *ic 
+ 		= container_of(classdev, struct internal_container, classdev);
+-	struct device *dev = classdev->dev;
++	struct device *dev = classdev->parent;
+ 
+ 	kfree(ic);
+ 	put_device(dev);
+@@ -129,12 +129,12 @@ static void attribute_container_release(struct class_device *classdev)
+  * This function allocates storage for the class device(s) to be
+  * attached to dev (one for each matching attribute_container).  If no
+  * fn is provided, the code will simply register the class device via
+- * class_device_add.  If a function is provided, it is expected to add
++ * device_add.  If a function is provided, it is expected to add
+  * the class device at the appropriate time.  One of the things that
+  * might be necessary is to allocate and initialise the classdev and
+  * then add it a later time.  To do this, call this routine for
+  * allocation and initialisation and then use
+- * attribute_container_device_trigger() to call class_device_add() on
++ * attribute_container_device_trigger() to call device_add() on
+  * it.  Note: after this, the class device contains a reference to dev
+  * which is not relinquished until the release of the classdev.
+  */
+@@ -142,7 +142,7 @@ void
+ attribute_container_add_device(struct device *dev,
+ 			       int (*fn)(struct attribute_container *,
+ 					 struct device *,
+-					 struct class_device *))
++					 struct device *))
+ {
+ 	struct attribute_container *cont;
+ 
+@@ -163,11 +163,11 @@ attribute_container_add_device(struct device *dev,
+ 		}
+ 
+ 		ic->cont = cont;
+-		class_device_initialize(&ic->classdev);
+-		ic->classdev.dev = get_device(dev);
++		device_initialize(&ic->classdev);
++		ic->classdev.parent = get_device(dev);
+ 		ic->classdev.class = cont->class;
+-		cont->class->release = attribute_container_release;
+-		strcpy(ic->classdev.class_id, dev->bus_id);
++		cont->class->dev_release = attribute_container_release;
++		strcpy(ic->classdev.bus_id, dev->bus_id);
+ 		if (fn)
+ 			fn(cont, dev, &ic->classdev);
+ 		else
+@@ -195,20 +195,19 @@ attribute_container_add_device(struct device *dev,
+  * @fn:	  A function to call to remove the device
+  *
+  * This routine triggers device removal.  If fn is NULL, then it is
+- * simply done via class_device_unregister (note that if something
++ * simply done via device_unregister (note that if something
+  * still has a reference to the classdev, then the memory occupied
+  * will not be freed until the classdev is released).  If you want a
+  * two phase release: remove from visibility and then delete the
+  * device, then you should use this routine with a fn that calls
+- * class_device_del() and then use
+- * attribute_container_device_trigger() to do the final put on the
+- * classdev.
++ * device_del() and then use attribute_container_device_trigger()
++ * to do the final put on the classdev.
+  */
+ void
+ attribute_container_remove_device(struct device *dev,
+ 				  void (*fn)(struct attribute_container *,
+ 					     struct device *,
+-					     struct class_device *))
++					     struct device *))
+ {
+ 	struct attribute_container *cont;
+ 
+@@ -224,14 +223,14 @@ attribute_container_remove_device(struct device *dev,
+ 			continue;
+ 
+ 		klist_for_each_entry(ic, &cont->containers, node, &iter) {
+-			if (dev != ic->classdev.dev)
++			if (dev != ic->classdev.parent)
+ 				continue;
+ 			klist_del(&ic->node);
+ 			if (fn)
+ 				fn(cont, dev, &ic->classdev);
+ 			else {
+ 				attribute_container_remove_attrs(&ic->classdev);
+-				class_device_unregister(&ic->classdev);
++				device_unregister(&ic->classdev);
+ 			}
+ 		}
+ 	}
+@@ -252,7 +251,7 @@ void
+ attribute_container_device_trigger(struct device *dev, 
+ 				   int (*fn)(struct attribute_container *,
+ 					     struct device *,
+-					     struct class_device *))
++					     struct device *))
+ {
+ 	struct attribute_container *cont;
+ 
+@@ -270,7 +269,7 @@ attribute_container_device_trigger(struct device *dev,
+ 		}
+ 
+ 		klist_for_each_entry(ic, &cont->containers, node, &iter) {
+-			if (dev == ic->classdev.dev)
++			if (dev == ic->classdev.parent)
+ 				fn(cont, dev, &ic->classdev);
+ 		}
+ 	}
+@@ -313,11 +312,11 @@ attribute_container_trigger(struct device *dev,
+  * attributes listed in the container
+  */
+ int
+-attribute_container_add_attrs(struct class_device *classdev)
++attribute_container_add_attrs(struct device *classdev)
+ {
+ 	struct attribute_container *cont =
+ 		attribute_container_classdev_to_container(classdev);
+-	struct class_device_attribute **attrs =	cont->attrs;
++	struct device_attribute **attrs = cont->attrs;
+ 	int i, error;
+ 
+ 	BUG_ON(attrs && cont->grp);
+@@ -329,7 +328,7 @@ attribute_container_add_attrs(struct class_device *classdev)
+ 		return sysfs_create_group(&classdev->kobj, cont->grp);
+ 
+ 	for (i = 0; attrs[i]; i++) {
+-		error = class_device_create_file(classdev, attrs[i]);
++		error = device_create_file(classdev, attrs[i]);
+ 		if (error)
+ 			return error;
+ 	}
+@@ -338,18 +337,18 @@ attribute_container_add_attrs(struct class_device *classdev)
+ }
+ 
+ /**
+- * attribute_container_add_class_device - same function as class_device_add
++ * attribute_container_add_class_device - same function as device_add
+  *
+  * @classdev:	the class device to add
+  *
+- * This performs essentially the same function as class_device_add except for
++ * This performs essentially the same function as device_add except for
+  * attribute containers, namely add the classdev to the system and then
+  * create the attribute files
+  */
+ int
+-attribute_container_add_class_device(struct class_device *classdev)
++attribute_container_add_class_device(struct device *classdev)
+ {
+-	int error = class_device_add(classdev);
++	int error = device_add(classdev);
+ 	if (error)
+ 		return error;
+ 	return attribute_container_add_attrs(classdev);
+@@ -364,7 +363,7 @@ attribute_container_add_class_device(struct class_device *classdev)
+ int
+ attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ 					     struct device *dev,
+-					     struct class_device *classdev)
++					     struct device *classdev)
+ {
+ 	return attribute_container_add_class_device(classdev);
+ }
+@@ -376,11 +375,11 @@ attribute_container_add_class_device_adapter(struct attribute_container *cont,
+  *
+  */
+ void
+-attribute_container_remove_attrs(struct class_device *classdev)
++attribute_container_remove_attrs(struct device *classdev)
+ {
+ 	struct attribute_container *cont =
+ 		attribute_container_classdev_to_container(classdev);
+-	struct class_device_attribute **attrs =	cont->attrs;
++	struct device_attribute **attrs = cont->attrs;
+ 	int i;
+ 
+ 	if (!attrs && !cont->grp)
+@@ -392,7 +391,7 @@ attribute_container_remove_attrs(struct class_device *classdev)
+ 	}
+ 
+ 	for (i = 0; attrs[i]; i++)
+-		class_device_remove_file(classdev, attrs[i]);
++		device_remove_file(classdev, attrs[i]);
+ }
+ 
+ /**
+@@ -401,13 +400,13 @@ attribute_container_remove_attrs(struct class_device *classdev)
+  * @classdev: the class device
+  *
+  * This function simply removes all the attribute files and then calls
+- * class_device_del.
++ * device_del.
+  */
+ void
+-attribute_container_class_device_del(struct class_device *classdev)
++attribute_container_class_device_del(struct device *classdev)
+ {
+ 	attribute_container_remove_attrs(classdev);
+-	class_device_del(classdev);
++	device_del(classdev);
+ }
+ 
+ /**
+@@ -419,16 +418,16 @@ attribute_container_class_device_del(struct class_device *classdev)
+  * Looks up the device in the container's list of class devices and returns
+  * the corresponding class_device.
+  */
+-struct class_device *
++struct device *
+ attribute_container_find_class_device(struct attribute_container *cont,
+ 				      struct device *dev)
+ {
+-	struct class_device *cdev = NULL;
++	struct device *cdev = NULL;
+ 	struct internal_container *ic;
+ 	struct klist_iter iter;
+ 
+ 	klist_for_each_entry(ic, &cont->containers, node, &iter) {
+-		if (ic->classdev.dev == dev) {
++		if (ic->classdev.parent == dev) {
+ 			cdev = &ic->classdev;
+ 			/* FIXME: must exit iterator then break */
+ 			klist_iter_exit(&iter);
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index 2d207ad..ef522ae 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -79,7 +79,7 @@ static void driver_release(struct kobject *kobj)
+ {
+ 	struct driver_private *drv_priv = to_driver(kobj);
+ 
+-	pr_debug("driver: '%s': %s\n", kobject_name(kobj), __FUNCTION__);
++	pr_debug("driver: '%s': %s\n", kobject_name(kobj), __func__);
+ 	kfree(drv_priv);
+ }
+ 
+@@ -505,14 +505,11 @@ void bus_attach_device(struct device *dev)
+ 	int ret = 0;
+ 
+ 	if (bus) {
+-		dev->is_registered = 1;
+ 		if (bus->p->drivers_autoprobe)
+ 			ret = device_attach(dev);
+ 		WARN_ON(ret < 0);
+ 		if (ret >= 0)
+ 			klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
+-		else
+-			dev->is_registered = 0;
+ 	}
+ }
+ 
+@@ -533,10 +530,9 @@ void bus_remove_device(struct device *dev)
+ 		sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
+ 				  dev->bus_id);
+ 		device_remove_attrs(dev->bus, dev);
+-		if (dev->is_registered) {
+-			dev->is_registered = 0;
++		if (klist_node_attached(&dev->knode_bus))
+ 			klist_del(&dev->knode_bus);
+-		}
++
+ 		pr_debug("bus: '%s': remove device %s\n",
+ 			 dev->bus->name, dev->bus_id);
+ 		device_release_driver(dev);
+@@ -682,19 +678,19 @@ int bus_add_driver(struct device_driver *drv)
+ 	error = driver_create_file(drv, &driver_attr_uevent);
+ 	if (error) {
+ 		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
+-			__FUNCTION__, drv->name);
++			__func__, drv->name);
+ 	}
+ 	error = driver_add_attrs(bus, drv);
+ 	if (error) {
+ 		/* How the hell do we get out of this pickle? Give up */
+ 		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
+-			__FUNCTION__, drv->name);
++			__func__, drv->name);
+ 	}
+ 	error = add_bind_files(drv);
+ 	if (error) {
+ 		/* Ditto */
+ 		printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
+-			__FUNCTION__, drv->name);
++			__func__, drv->name);
+ 	}
+ 
+ 	kobject_uevent(&priv->kobj, KOBJ_ADD);
+diff --git a/drivers/base/class.c b/drivers/base/class.c
+index 9d91537..b490179 100644
+--- a/drivers/base/class.c
++++ b/drivers/base/class.c
+@@ -175,13 +175,13 @@ void class_unregister(struct class *cls)
+ 
+ static void class_create_release(struct class *cls)
+ {
+-	pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
++	pr_debug("%s called for %s\n", __func__, cls->name);
+ 	kfree(cls);
+ }
+ 
+ static void class_device_create_release(struct class_device *class_dev)
+ {
+-	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
++	pr_debug("%s called for %s\n", __func__, class_dev->class_id);
+ 	kfree(class_dev);
+ }
+ 
+@@ -189,7 +189,7 @@ static void class_device_create_release(struct class_device *class_dev)
+ static int class_device_create_uevent(struct class_device *class_dev,
+ 				      struct kobj_uevent_env *env)
+ {
+-	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
++	pr_debug("%s called for %s\n", __func__, class_dev->class_id);
+ 	return 0;
+ }
+ 
+@@ -415,7 +415,7 @@ static int class_uevent(struct kset *kset, struct kobject *kobj,
+ 	struct device *dev = class_dev->dev;
+ 	int retval = 0;
+ 
+-	pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
++	pr_debug("%s - name = %s\n", __func__, class_dev->class_id);
+ 
+ 	if (MAJOR(class_dev->devt)) {
+ 		add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 24198ad..9248e09 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -20,7 +20,7 @@
+ #include <linux/notifier.h>
+ #include <linux/genhd.h>
+ #include <linux/kallsyms.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ 
+ #include "base.h"
+ #include "power/power.h"
+@@ -207,7 +207,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ 		retval = dev->bus->uevent(dev, env);
+ 		if (retval)
+ 			pr_debug("device: '%s': %s: bus uevent() returned %d\n",
+-				 dev->bus_id, __FUNCTION__, retval);
++				 dev->bus_id, __func__, retval);
+ 	}
+ 
+ 	/* have the class specific function add its stuff */
+@@ -216,7 +216,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ 		if (retval)
+ 			pr_debug("device: '%s': %s: class uevent() "
+ 				 "returned %d\n", dev->bus_id,
+-				 __FUNCTION__, retval);
++				 __func__, retval);
+ 	}
+ 
+ 	/* have the device type specific fuction add its stuff */
+@@ -225,7 +225,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ 		if (retval)
+ 			pr_debug("device: '%s': %s: dev_type uevent() "
+ 				 "returned %d\n", dev->bus_id,
+-				 __FUNCTION__, retval);
++				 __func__, retval);
+ 	}
+ 
+ 	return retval;
+@@ -782,7 +782,7 @@ int device_add(struct device *dev)
+ 		goto Done;
+ 	}
+ 
+-	pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
++	pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+ 
+ 	parent = get_device(dev->parent);
+ 	setup_parent(dev, parent);
+@@ -817,13 +817,12 @@ int device_add(struct device *dev)
+ 	error = device_add_attrs(dev);
+ 	if (error)
+ 		goto AttrsError;
+-	error = dpm_sysfs_add(dev);
+-	if (error)
+-		goto PMError;
+-	device_pm_add(dev);
+ 	error = bus_add_device(dev);
+ 	if (error)
+ 		goto BusError;
++	error = device_pm_add(dev);
++	if (error)
++		goto PMError;
+ 	kobject_uevent(&dev->kobj, KOBJ_ADD);
+ 	bus_attach_device(dev);
+ 	if (parent)
+@@ -843,9 +842,9 @@ int device_add(struct device *dev)
+  Done:
+ 	put_device(dev);
+ 	return error;
+- BusError:
+-	device_pm_remove(dev);
+  PMError:
++	bus_remove_device(dev);
++ BusError:
+ 	if (dev->bus)
+ 		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ 					     BUS_NOTIFY_DEL_DEVICE, dev);
+@@ -981,7 +980,7 @@ void device_del(struct device *dev)
+  */
+ void device_unregister(struct device *dev)
+ {
+-	pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
++	pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+ 	device_del(dev);
+ 	put_device(dev);
+ }
+@@ -1076,7 +1075,7 @@ EXPORT_SYMBOL_GPL(device_remove_file);
+ 
+ static void device_create_release(struct device *dev)
+ {
+-	pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
++	pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+ 	kfree(dev);
+ }
+ 
+@@ -1164,35 +1163,6 @@ void device_destroy(struct class *class, dev_t devt)
+ }
+ EXPORT_SYMBOL_GPL(device_destroy);
+ 
+-#ifdef CONFIG_PM_SLEEP
+-/**
+- * destroy_suspended_device - asks the PM core to remove a suspended device
+- * @class: pointer to the struct class that this device was registered with
+- * @devt: the dev_t of the device that was previously registered
+- *
+- * This call notifies the PM core of the necessity to unregister a suspended
+- * device created with a call to device_create() (devices cannot be
+- * unregistered directly while suspended, since the PM core holds their
+- * semaphores at that time).
+- *
+- * It can only be called within the scope of a system sleep transition.  In
+- * practice this means it has to be directly or indirectly invoked either by
+- * a suspend or resume method, or by the PM core (e.g. via
+- * disable_nonboot_cpus() or enable_nonboot_cpus()).
+- */
+-void destroy_suspended_device(struct class *class, dev_t devt)
+-{
+-	struct device *dev;
+-
+-	dev = class_find_device(class, &devt, __match_devt);
+-	if (dev) {
+-		device_pm_schedule_removal(dev);
+-		put_device(dev);
+-	}
+-}
+-EXPORT_SYMBOL_GPL(destroy_suspended_device);
+-#endif /* CONFIG_PM_SLEEP */
+-
+ /**
+  * device_rename - renames a device
+  * @dev: the pointer to the struct device to be renamed
+@@ -1210,7 +1180,7 @@ int device_rename(struct device *dev, char *new_name)
+ 		return -EINVAL;
+ 
+ 	pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id,
+-		 __FUNCTION__, new_name);
++		 __func__, new_name);
+ 
+ #ifdef CONFIG_SYSFS_DEPRECATED
+ 	if ((dev->class) && (dev->parent))
+@@ -1249,7 +1219,7 @@ int device_rename(struct device *dev, char *new_name)
+ 					  dev->bus_id);
+ 		if (error) {
+ 			dev_err(dev, "%s: sysfs_create_symlink failed (%d)\n",
+-				__FUNCTION__, error);
++				__func__, error);
+ 		}
+ 	}
+ #endif
+@@ -1325,7 +1295,7 @@ int device_move(struct device *dev, struct device *new_parent)
+ 	new_parent_kobj = get_device_parent(dev, new_parent);
+ 
+ 	pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id,
+-		 __FUNCTION__, new_parent ? new_parent->bus_id : "<NULL>");
++		 __func__, new_parent ? new_parent->bus_id : "<NULL>");
+ 	error = kobject_move(&dev->kobj, new_parent_kobj);
+ 	if (error) {
+ 		cleanup_glue_dir(dev, new_parent_kobj);
+diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
+index 499b003..6fe4174 100644
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -28,7 +28,7 @@ static ssize_t show_online(struct sys_device *dev, char *buf)
+ 	return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
+ }
+ 
+-static ssize_t store_online(struct sys_device *dev, const char *buf,
++static ssize_t __ref store_online(struct sys_device *dev, const char *buf,
+ 			    size_t count)
+ {
+ 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+@@ -55,7 +55,7 @@ static ssize_t store_online(struct sys_device *dev, const char *buf,
+ }
+ static SYSDEV_ATTR(online, 0644, show_online, store_online);
+ 
+-static void __devinit register_cpu_control(struct cpu *cpu)
++static void __cpuinit register_cpu_control(struct cpu *cpu)
+ {
+ 	sysdev_create_file(&cpu->sysdev, &attr_online);
+ }
+@@ -103,6 +103,51 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
+ #endif
+ 
+ /*
++ * Print cpu online, possible, present, and system maps
++ */
++static ssize_t print_cpus_map(char *buf, cpumask_t *map)
++{
++	int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *map);
++
++	buf[n++] = '\n';
++	buf[n] = '\0';
++	return n;
++}
++
++#define	print_cpus_func(type) \
++static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf)	\
++{									\
++	return print_cpus_map(buf, &cpu_##type##_map);			\
++}									\
++struct sysdev_class_attribute attr_##type##_map = 			\
++	_SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
++
++print_cpus_func(online);
++print_cpus_func(possible);
++print_cpus_func(present);
++
++struct sysdev_class_attribute *cpu_state_attr[] = {
++	&attr_online_map,
++	&attr_possible_map,
++	&attr_present_map,
++};
++
++static int cpu_states_init(void)
++{
++	int i;
++	int err = 0;
++
++	for (i = 0;  i < ARRAY_SIZE(cpu_state_attr); i++) {
++		int ret;
++		ret = sysdev_class_create_file(&cpu_sysdev_class,
++						cpu_state_attr[i]);
++		if (!err)
++			err = ret;
++	}
++	return err;
++}
++
++/*
+  * register_cpu - Setup a sysfs device for a CPU.
+  * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
+  *	  sysfs for this CPU.
+@@ -147,6 +192,9 @@ int __init cpu_dev_init(void)
+ 	int err;
+ 
+ 	err = sysdev_class_register(&cpu_sysdev_class);
++	if (!err)
++		err = cpu_states_init();
++
+ #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+ 	if (!err)
+ 		err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
+diff --git a/drivers/base/dd.c b/drivers/base/dd.c
+index a5cde94..3ac443b 100644
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -30,12 +30,12 @@ static void driver_bound(struct device *dev)
+ {
+ 	if (klist_node_attached(&dev->knode_driver)) {
+ 		printk(KERN_WARNING "%s: device %s already bound\n",
+-			__FUNCTION__, kobject_name(&dev->kobj));
++			__func__, kobject_name(&dev->kobj));
+ 		return;
+ 	}
+ 
+ 	pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->bus_id,
+-		 __FUNCTION__, dev->driver->name);
++		 __func__, dev->driver->name);
+ 
+ 	if (dev->bus)
+ 		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+@@ -104,13 +104,13 @@ static int really_probe(struct device *dev, struct device_driver *drv)
+ 
+ 	atomic_inc(&probe_count);
+ 	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
+-		 drv->bus->name, __FUNCTION__, drv->name, dev->bus_id);
++		 drv->bus->name, __func__, drv->name, dev->bus_id);
+ 	WARN_ON(!list_empty(&dev->devres_head));
+ 
+ 	dev->driver = drv;
+ 	if (driver_sysfs_add(dev)) {
+ 		printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
+-			__FUNCTION__, dev->bus_id);
++			__func__, dev->bus_id);
+ 		goto probe_failed;
+ 	}
+ 
+@@ -127,7 +127,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
+ 	driver_bound(dev);
+ 	ret = 1;
+ 	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
+-		 drv->bus->name, __FUNCTION__, dev->bus_id, drv->name);
++		 drv->bus->name, __func__, dev->bus_id, drv->name);
+ 	goto done;
+ 
+ probe_failed:
+@@ -160,7 +160,7 @@ done:
+  */
+ int driver_probe_done(void)
+ {
+-	pr_debug("%s: probe_count = %d\n", __FUNCTION__,
++	pr_debug("%s: probe_count = %d\n", __func__,
+ 		 atomic_read(&probe_count));
+ 	if (atomic_read(&probe_count))
+ 		return -EBUSY;
+@@ -194,7 +194,7 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
+ 		goto done;
+ 
+ 	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
+-		 drv->bus->name, __FUNCTION__, dev->bus_id, drv->name);
++		 drv->bus->name, __func__, dev->bus_id, drv->name);
+ 
+ 	ret = really_probe(dev, drv);
+ 
+diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
+index 4a1b9bf..1fef7df 100644
+--- a/drivers/base/firmware_class.c
++++ b/drivers/base/firmware_class.c
+@@ -156,7 +156,7 @@ static ssize_t firmware_loading_store(struct device *dev,
+ 		}
+ 		/* fallthrough */
+ 	default:
+-		printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__,
++		printk(KERN_ERR "%s: unexpected value (%d)\n", __func__,
+ 		       loading);
+ 		/* fallthrough */
+ 	case -1:
+@@ -209,7 +209,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
+ 	new_size = ALIGN(min_size, PAGE_SIZE);
+ 	new_data = vmalloc(new_size);
+ 	if (!new_data) {
+-		printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__);
++		printk(KERN_ERR "%s: unable to alloc buffer\n", __func__);
+ 		/* Make sure that we don't keep incomplete data */
+ 		fw_load_abort(fw_priv);
+ 		return -ENOMEM;
+@@ -307,7 +307,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
+ 	*dev_p = NULL;
+ 
+ 	if (!fw_priv || !f_dev) {
+-		printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
++		printk(KERN_ERR "%s: kmalloc failed\n", __func__);
+ 		retval = -ENOMEM;
+ 		goto error_kfree;
+ 	}
+@@ -328,7 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
+ 	retval = device_register(f_dev);
+ 	if (retval) {
+ 		printk(KERN_ERR "%s: device_register failed\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		goto error_kfree;
+ 	}
+ 	*dev_p = f_dev;
+@@ -362,14 +362,14 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p,
+ 	retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);
+ 	if (retval) {
+ 		printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		goto error_unreg;
+ 	}
+ 
+ 	retval = device_create_file(f_dev, &dev_attr_loading);
+ 	if (retval) {
+ 		printk(KERN_ERR "%s: device_create_file failed\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		goto error_unreg;
+ 	}
+ 
+@@ -399,7 +399,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
+ 	*firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
+ 	if (!firmware) {
+ 		printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		retval = -ENOMEM;
+ 		goto out;
+ 	}
+@@ -570,13 +570,13 @@ firmware_class_init(void)
+ 	int error;
+ 	error = class_register(&firmware_class);
+ 	if (error) {
+-		printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__);
++		printk(KERN_ERR "%s: class_register failed\n", __func__);
+ 		return error;
+ 	}
+ 	error = class_create_file(&firmware_class, &class_attr_timeout);
+ 	if (error) {
+ 		printk(KERN_ERR "%s: class_create_file failed\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		class_unregister(&firmware_class);
+ 	}
+ 	return error;
+diff --git a/drivers/base/memory.c b/drivers/base/memory.c
+index 7ae413f..8ce6de5 100644
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -20,6 +20,7 @@
+ #include <linux/kobject.h>
+ #include <linux/memory_hotplug.h>
+ #include <linux/mm.h>
++#include <linux/mutex.h>
+ #include <asm/atomic.h>
+ #include <asm/uaccess.h>
+ 
+@@ -61,8 +62,8 @@ void unregister_memory_notifier(struct notifier_block *nb)
+ /*
+  * register_memory - Setup a sysfs device for a memory block
+  */
+-int register_memory(struct memory_block *memory, struct mem_section *section,
+-		struct node *root)
++static
++int register_memory(struct memory_block *memory, struct mem_section *section)
+ {
+ 	int error;
+ 
+@@ -70,26 +71,18 @@ int register_memory(struct memory_block *memory, struct mem_section *section,
+ 	memory->sysdev.id = __section_nr(section);
+ 
+ 	error = sysdev_register(&memory->sysdev);
+-
+-	if (root && !error)
+-		error = sysfs_create_link(&root->sysdev.kobj,
+-					  &memory->sysdev.kobj,
+-					  kobject_name(&memory->sysdev.kobj));
+-
+ 	return error;
+ }
+ 
+ static void
+-unregister_memory(struct memory_block *memory, struct mem_section *section,
+-		struct node *root)
++unregister_memory(struct memory_block *memory, struct mem_section *section)
+ {
+ 	BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
+ 	BUG_ON(memory->sysdev.id != __section_nr(section));
+ 
++	/* drop the ref. we got in remove_memory_block() */
++	kobject_put(&memory->sysdev.kobj);
+ 	sysdev_unregister(&memory->sysdev);
+-	if (root)
+-		sysfs_remove_link(&root->sysdev.kobj,
+-				  kobject_name(&memory->sysdev.kobj));
+ }
+ 
+ /*
+@@ -193,7 +186,7 @@ memory_block_action(struct memory_block *mem, unsigned long action)
+ 			break;
+ 		default:
+ 			printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
+-					__FUNCTION__, mem, action, action);
++					__func__, mem, action, action);
+ 			WARN_ON(1);
+ 			ret = -EINVAL;
+ 	}
+@@ -205,7 +198,7 @@ static int memory_block_change_state(struct memory_block *mem,
+ 		unsigned long to_state, unsigned long from_state_req)
+ {
+ 	int ret = 0;
+-	down(&mem->state_sem);
++	mutex_lock(&mem->state_mutex);
+ 
+ 	if (mem->state != from_state_req) {
+ 		ret = -EINVAL;
+@@ -217,7 +210,7 @@ static int memory_block_change_state(struct memory_block *mem,
+ 		mem->state = to_state;
+ 
+ out:
+-	up(&mem->state_sem);
++	mutex_unlock(&mem->state_mutex);
+ 	return ret;
+ }
+ 
+@@ -341,10 +334,10 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
+ 
+ 	mem->phys_index = __section_nr(section);
+ 	mem->state = state;
+-	init_MUTEX(&mem->state_sem);
++	mutex_init(&mem->state_mutex);
+ 	mem->phys_device = phys_device;
+ 
+-	ret = register_memory(mem, section, NULL);
++	ret = register_memory(mem, section);
+ 	if (!ret)
+ 		ret = mem_create_simple_file(mem, phys_index);
+ 	if (!ret)
+@@ -395,7 +388,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
+ 	mem_remove_simple_file(mem, phys_index);
+ 	mem_remove_simple_file(mem, state);
+ 	mem_remove_simple_file(mem, phys_device);
+-	unregister_memory(mem, section, NULL);
++	unregister_memory(mem, section);
+ 
+ 	return 0;
+ }
+@@ -451,6 +444,6 @@ int __init memory_dev_init(void)
+ 		ret = err;
+ out:
+ 	if (ret)
+-		printk(KERN_ERR "%s() failed: %d\n", __FUNCTION__, ret);
++		printk(KERN_ERR "%s() failed: %d\n", __func__, ret);
+ 	return ret;
+ }
+diff --git a/drivers/base/node.c b/drivers/base/node.c
+index e59861f..12fde2d 100644
+--- a/drivers/base/node.c
++++ b/drivers/base/node.c
+@@ -19,21 +19,34 @@ static struct sysdev_class node_class = {
+ };
+ 
+ 
+-static ssize_t node_read_cpumap(struct sys_device * dev, char * buf)
++static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
+ {
+ 	struct node *node_dev = to_node(dev);
+-	cpumask_t mask = node_to_cpumask(node_dev->sysdev.id);
++	node_to_cpumask_ptr(mask, node_dev->sysdev.id);
+ 	int len;
+ 
+-	/* 2004/06/03: buf currently PAGE_SIZE, need > 1 char per 4 bits. */
+-	BUILD_BUG_ON(MAX_NUMNODES/4 > PAGE_SIZE/2);
++	/* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */
++	BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1));
+ 
+-	len = cpumask_scnprintf(buf, PAGE_SIZE-1, mask);
+-	len += sprintf(buf + len, "\n");
++	len = type?
++		cpulist_scnprintf(buf, PAGE_SIZE-2, *mask):
++		cpumask_scnprintf(buf, PAGE_SIZE-2, *mask);
++ 	buf[len++] = '\n';
++ 	buf[len] = '\0';
+ 	return len;
+ }
+ 
+-static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumap, NULL);
++static inline ssize_t node_read_cpumask(struct sys_device *dev, char *buf)
++{
++	return node_read_cpumap(dev, 0, buf);
++}
++static inline ssize_t node_read_cpulist(struct sys_device *dev, char *buf)
++{
++	return node_read_cpumap(dev, 1, buf);
++}
++
++static SYSDEV_ATTR(cpumap,  S_IRUGO, node_read_cpumask, NULL);
++static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
+ 
+ #define K(x) ((x) << (PAGE_SHIFT - 10))
+ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
+@@ -149,6 +162,7 @@ int register_node(struct node *node, int num, struct node *parent)
+ 
+ 	if (!error){
+ 		sysdev_create_file(&node->sysdev, &attr_cpumap);
++		sysdev_create_file(&node->sysdev, &attr_cpulist);
+ 		sysdev_create_file(&node->sysdev, &attr_meminfo);
+ 		sysdev_create_file(&node->sysdev, &attr_numastat);
+ 		sysdev_create_file(&node->sysdev, &attr_distance);
+@@ -166,6 +180,7 @@ int register_node(struct node *node, int num, struct node *parent)
+ void unregister_node(struct node *node)
+ {
+ 	sysdev_remove_file(&node->sysdev, &attr_cpumap);
++	sysdev_remove_file(&node->sysdev, &attr_cpulist);
+ 	sysdev_remove_file(&node->sysdev, &attr_meminfo);
+ 	sysdev_remove_file(&node->sysdev, &attr_numastat);
+ 	sysdev_remove_file(&node->sysdev, &attr_distance);
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index d887d5c..7b76fd3 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -50,26 +50,37 @@
+ LIST_HEAD(dpm_active);
+ static LIST_HEAD(dpm_off);
+ static LIST_HEAD(dpm_off_irq);
+-static LIST_HEAD(dpm_destroy);
+ 
+ static DEFINE_MUTEX(dpm_list_mtx);
+ 
+-static DECLARE_RWSEM(pm_sleep_rwsem);
+-
+-int (*platform_enable_wakeup)(struct device *dev, int is_on);
++/* 'true' if all devices have been suspended, protected by dpm_list_mtx */
++static bool all_sleeping;
+ 
+ /**
+  *	device_pm_add - add a device to the list of active devices
+  *	@dev:	Device to be added to the list
+  */
+-void device_pm_add(struct device *dev)
++int device_pm_add(struct device *dev)
+ {
++	int error;
++
+ 	pr_debug("PM: Adding info for %s:%s\n",
+ 		 dev->bus ? dev->bus->name : "No Bus",
+ 		 kobject_name(&dev->kobj));
+ 	mutex_lock(&dpm_list_mtx);
+-	list_add_tail(&dev->power.entry, &dpm_active);
++	if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) {
++		if (dev->parent->power.sleeping)
++			dev_warn(dev, "parent %s is sleeping\n",
++				dev->parent->bus_id);
++		else
++			dev_warn(dev, "all devices are sleeping\n");
++		WARN_ON(true);
++	}
++	error = dpm_sysfs_add(dev);
++	if (!error)
++		list_add_tail(&dev->power.entry, &dpm_active);
+ 	mutex_unlock(&dpm_list_mtx);
++	return error;
+ }
+ 
+ /**
+@@ -89,50 +100,6 @@ void device_pm_remove(struct device *dev)
+ 	mutex_unlock(&dpm_list_mtx);
+ }
+ 
+-/**
+- *	device_pm_schedule_removal - schedule the removal of a suspended device
+- *	@dev:	Device to destroy
+- *
+- *	Moves the device to the dpm_destroy list for further processing by
+- *	unregister_dropped_devices().
+- */
+-void device_pm_schedule_removal(struct device *dev)
+-{
+-	pr_debug("PM: Preparing for removal: %s:%s\n",
+-		dev->bus ? dev->bus->name : "No Bus",
+-		kobject_name(&dev->kobj));
+-	mutex_lock(&dpm_list_mtx);
+-	list_move_tail(&dev->power.entry, &dpm_destroy);
+-	mutex_unlock(&dpm_list_mtx);
+-}
+-EXPORT_SYMBOL_GPL(device_pm_schedule_removal);
+-
+-/**
+- *	pm_sleep_lock - mutual exclusion for registration and suspend
+- *
+- *	Returns 0 if no suspend is underway and device registration
+- *	may proceed, otherwise -EBUSY.
+- */
+-int pm_sleep_lock(void)
+-{
+-	if (down_read_trylock(&pm_sleep_rwsem))
+-		return 0;
+-
+-	return -EBUSY;
+-}
+-
+-/**
+- *	pm_sleep_unlock - mutual exclusion for registration and suspend
+- *
+- *	This routine undoes the effect of device_pm_add_lock
+- *	when a device's registration is complete.
+- */
+-void pm_sleep_unlock(void)
+-{
+-	up_read(&pm_sleep_rwsem);
+-}
+-
+-
+ /*------------------------- Resume routines -------------------------*/
+ 
+ /**
+@@ -242,11 +209,13 @@ static int resume_device(struct device *dev)
+ static void dpm_resume(void)
+ {
+ 	mutex_lock(&dpm_list_mtx);
++	all_sleeping = false;
+ 	while(!list_empty(&dpm_off)) {
+ 		struct list_head *entry = dpm_off.next;
+ 		struct device *dev = to_device(entry);
+ 
+ 		list_move_tail(entry, &dpm_active);
++		dev->power.sleeping = false;
+ 		mutex_unlock(&dpm_list_mtx);
+ 		resume_device(dev);
+ 		mutex_lock(&dpm_list_mtx);
+@@ -255,26 +224,6 @@ static void dpm_resume(void)
+ }
+ 
+ /**
+- *	unregister_dropped_devices - Unregister devices scheduled for removal
+- *
+- *	Unregister all devices on the dpm_destroy list.
+- */
+-static void unregister_dropped_devices(void)
+-{
+-	mutex_lock(&dpm_list_mtx);
+-	while (!list_empty(&dpm_destroy)) {
+-		struct list_head *entry = dpm_destroy.next;
+-		struct device *dev = to_device(entry);
+-
+-		mutex_unlock(&dpm_list_mtx);
+-		/* This also removes the device from the list */
+-		device_unregister(dev);
+-		mutex_lock(&dpm_list_mtx);
+-	}
+-	mutex_unlock(&dpm_list_mtx);
+-}
+-
+-/**
+  *	device_resume - Restore state of each device in system.
+  *
+  *	Resume all the devices, unlock them all, and allow new
+@@ -284,8 +233,6 @@ void device_resume(void)
+ {
+ 	might_sleep();
+ 	dpm_resume();
+-	unregister_dropped_devices();
+-	up_write(&pm_sleep_rwsem);
+ }
+ EXPORT_SYMBOL_GPL(device_resume);
+ 
+@@ -377,11 +324,6 @@ static int suspend_device(struct device *dev, pm_message_t state)
+ 
+ 	down(&dev->sem);
+ 
+-	if (dev->power.power_state.event) {
+-		dev_dbg(dev, "PM: suspend %d-->%d\n",
+-			dev->power.power_state.event, state.event);
+-	}
+-
+ 	if (dev->class && dev->class->suspend) {
+ 		suspend_device_dbg(dev, state, "class ");
+ 		error = dev->class->suspend(dev, state);
+@@ -426,6 +368,9 @@ static int dpm_suspend(pm_message_t state)
+ 		struct list_head *entry = dpm_active.prev;
+ 		struct device *dev = to_device(entry);
+ 
++		WARN_ON(dev->parent && dev->parent->power.sleeping);
++
++		dev->power.sleeping = true;
+ 		mutex_unlock(&dpm_list_mtx);
+ 		error = suspend_device(dev, state);
+ 		mutex_lock(&dpm_list_mtx);
+@@ -437,11 +382,14 @@ static int dpm_suspend(pm_message_t state)
+ 					(error == -EAGAIN ?
+ 					" (please convert to suspend_late)" :
+ 					""));
++			dev->power.sleeping = false;
+ 			break;
+ 		}
+ 		if (!list_empty(&dev->power.entry))
+ 			list_move(&dev->power.entry, &dpm_off);
+ 	}
++	if (!error)
++		all_sleeping = true;
+ 	mutex_unlock(&dpm_list_mtx);
+ 
+ 	return error;
+@@ -459,7 +407,6 @@ int device_suspend(pm_message_t state)
+ 	int error;
+ 
+ 	might_sleep();
+-	down_write(&pm_sleep_rwsem);
+ 	error = dpm_suspend(state);
+ 	if (error)
+ 		device_resume();
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index e32d3bd..a6894f2 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -11,30 +11,13 @@ static inline struct device *to_device(struct list_head *entry)
+ 	return container_of(entry, struct device, power.entry);
+ }
+ 
+-extern void device_pm_add(struct device *);
++extern int device_pm_add(struct device *);
+ extern void device_pm_remove(struct device *);
+-extern int pm_sleep_lock(void);
+-extern void pm_sleep_unlock(void);
+ 
+ #else /* CONFIG_PM_SLEEP */
+ 
+-
+-static inline void device_pm_add(struct device *dev)
+-{
+-}
+-
+-static inline void device_pm_remove(struct device *dev)
+-{
+-}
+-
+-static inline int pm_sleep_lock(void)
+-{
+-	return 0;
+-}
+-
+-static inline void pm_sleep_unlock(void)
+-{
+-}
++static inline int device_pm_add(struct device *dev) { return 0; }
++static inline void device_pm_remove(struct device *dev) {}
+ 
+ #endif
+ 
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index f2ed179..d11f74b 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -6,6 +6,8 @@
+ #include <linux/string.h>
+ #include "power.h"
+ 
++int (*platform_enable_wakeup)(struct device *dev, int is_on);
++
+ 
+ /*
+  *	wakeup - Report/change current wakeup option for device
+diff --git a/drivers/base/sys.c b/drivers/base/sys.c
+index 8e13fd9..4fbb56b 100644
+--- a/drivers/base/sys.c
++++ b/drivers/base/sys.c
+@@ -167,6 +167,22 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
+ {
+ 	int err = 0;
+ 
++	if (!cls) {
++		printk(KERN_WARNING "sysdev: invalid class passed to "
++			"sysdev_driver_register!\n");
++		WARN_ON(1);
++		return -EINVAL;
++	}
++
++	/* Check whether this driver has already been added to a class. */
++	if ((drv->entry.next != drv->entry.prev) ||
++	    (drv->entry.next != NULL)) {
++		printk(KERN_WARNING "sysdev: class %s: driver (%p) has already"
++			" been registered to a class, something is wrong, but "
++			"will forge on!\n", cls->name, drv);
++		WARN_ON(1);
++	}
++
+ 	mutex_lock(&sysdev_drivers_lock);
+ 	if (cls && kset_get(&cls->kset)) {
+ 		list_add_tail(&drv->entry, &cls->drivers);
+@@ -179,7 +195,7 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
+ 		}
+ 	} else {
+ 		err = -EINVAL;
+-		printk(KERN_ERR "%s: invalid device class\n", __FUNCTION__);
++		printk(KERN_ERR "%s: invalid device class\n", __func__);
+ 		WARN_ON(1);
+ 	}
+ 	mutex_unlock(&sysdev_drivers_lock);
+diff --git a/drivers/base/topology.c b/drivers/base/topology.c
+index e1d3ad4..fdf4044 100644
+--- a/drivers/base/topology.c
++++ b/drivers/base/topology.c
+@@ -40,15 +40,38 @@ static ssize_t show_##name(struct sys_device *dev, char *buf)	\
+ 	return sprintf(buf, "%d\n", topology_##name(cpu));	\
+ }
+ 
+-#define define_siblings_show_func(name)					\
+-static ssize_t show_##name(struct sys_device *dev, char *buf)		\
++static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf)
++{
++	ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
++	int n = 0;
++
++	if (len > 1) {
++		n = type?
++			cpulist_scnprintf(buf, len-2, *mask):
++			cpumask_scnprintf(buf, len-2, *mask);
++		buf[n++] = '\n';
++		buf[n] = '\0';
++	}
++	return n;
++}
++
++#define define_siblings_show_map(name)					\
++static inline ssize_t show_##name(struct sys_device *dev, char *buf)	\
+ {									\
+-	ssize_t len = -1;						\
+ 	unsigned int cpu = dev->id;					\
+-	len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu));	\
+-	return (len + sprintf(buf + len, "\n"));			\
++	return show_cpumap(0, &(topology_##name(cpu)), buf);		\
+ }
+ 
++#define define_siblings_show_list(name)					\
++static inline ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
++{									\
++	unsigned int cpu = dev->id;					\
++	return show_cpumap(1, &(topology_##name(cpu)), buf);		\
++}
++
++#define define_siblings_show_func(name)		\
++	define_siblings_show_map(name); define_siblings_show_list(name)
++
+ #ifdef	topology_physical_package_id
+ define_id_show_func(physical_package_id);
+ define_one_ro(physical_package_id);
+@@ -68,7 +91,9 @@ define_one_ro(core_id);
+ #ifdef topology_thread_siblings
+ define_siblings_show_func(thread_siblings);
+ define_one_ro(thread_siblings);
+-#define ref_thread_siblings_attr	&attr_thread_siblings.attr,
++define_one_ro(thread_siblings_list);
++#define ref_thread_siblings_attr	\
++		&attr_thread_siblings.attr, &attr_thread_siblings_list.attr,
+ #else
+ #define ref_thread_siblings_attr
+ #endif
+@@ -76,7 +101,9 @@ define_one_ro(thread_siblings);
+ #ifdef topology_core_siblings
+ define_siblings_show_func(core_siblings);
+ define_one_ro(core_siblings);
+-#define ref_core_siblings_attr		&attr_core_siblings.attr,
++define_one_ro(core_siblings_list);
++#define ref_core_siblings_attr		\
++		&attr_core_siblings.attr, &attr_core_siblings_list.attr,
+ #else
+ #define ref_core_siblings_attr
+ #endif
+diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
+index 40bca48..84997ef 100644
+--- a/drivers/base/transport_class.c
++++ b/drivers/base/transport_class.c
+@@ -66,7 +66,7 @@ EXPORT_SYMBOL_GPL(transport_class_unregister);
+ 
+ static int anon_transport_dummy_function(struct transport_container *tc,
+ 					 struct device *dev,
+-					 struct class_device *cdev)
++					 struct device *cdev)
+ {
+ 	/* do nothing */
+ 	return 0;
+@@ -108,13 +108,14 @@ EXPORT_SYMBOL_GPL(anon_transport_class_register);
+  */
+ void anon_transport_class_unregister(struct anon_transport_class *atc)
+ {
+-	attribute_container_unregister(&atc->container);
++	if (unlikely(attribute_container_unregister(&atc->container)))
++		BUG();
+ }
+ EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
+ 
+ static int transport_setup_classdev(struct attribute_container *cont,
+ 				    struct device *dev,
+-				    struct class_device *classdev)
++				    struct device *classdev)
+ {
+ 	struct transport_class *tclass = class_to_transport_class(cont->class);
+ 	struct transport_container *tcont = attribute_container_to_transport_container(cont);
+@@ -148,7 +149,7 @@ EXPORT_SYMBOL_GPL(transport_setup_device);
+ 
+ static int transport_add_class_device(struct attribute_container *cont,
+ 				      struct device *dev,
+-				      struct class_device *classdev)
++				      struct device *classdev)
+ {
+ 	int error = attribute_container_add_class_device(classdev);
+ 	struct transport_container *tcont = 
+@@ -180,7 +181,7 @@ EXPORT_SYMBOL_GPL(transport_add_device);
+ 
+ static int transport_configure(struct attribute_container *cont,
+ 			       struct device *dev,
+-			       struct class_device *cdev)
++			       struct device *cdev)
+ {
+ 	struct transport_class *tclass = class_to_transport_class(cont->class);
+ 	struct transport_container *tcont = attribute_container_to_transport_container(cont);
+@@ -211,7 +212,7 @@ EXPORT_SYMBOL_GPL(transport_configure_device);
+ 
+ static int transport_remove_classdev(struct attribute_container *cont,
+ 				     struct device *dev,
+-				     struct class_device *classdev)
++				     struct device *classdev)
+ {
+ 	struct transport_container *tcont = 
+ 		attribute_container_to_transport_container(cont);
+@@ -250,12 +251,12 @@ EXPORT_SYMBOL_GPL(transport_remove_device);
+ 
+ static void transport_destroy_classdev(struct attribute_container *cont,
+ 				      struct device *dev,
+-				      struct class_device *classdev)
++				      struct device *classdev)
+ {
+ 	struct transport_class *tclass = class_to_transport_class(cont->class);
+ 
+ 	if (tclass->remove != anon_transport_dummy_function)
+-		class_device_put(classdev);
++		put_device(classdev);
+ }
+ 
+ 
+diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
+index 8460ef7..18d243c 100644
+--- a/drivers/block/aoe/aoenet.c
++++ b/drivers/block/aoe/aoenet.c
+@@ -115,7 +115,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
+ 	struct aoe_hdr *h;
+ 	u32 n;
+ 
+-	if (ifp->nd_net != &init_net)
++	if (dev_net(ifp) != &init_net)
+ 		goto exit;
+ 
+ 	skb = skb_share_check(skb, GFP_ATOMIC);
+diff --git a/drivers/block/brd.c b/drivers/block/brd.c
+index 8536480..7bd7663 100644
+--- a/drivers/block/brd.c
++++ b/drivers/block/brd.c
+@@ -108,7 +108,7 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector)
+ #ifndef CONFIG_BLK_DEV_XIP
+ 	gfp_flags |= __GFP_HIGHMEM;
+ #endif
+-	page = alloc_page(GFP_NOIO | __GFP_HIGHMEM | __GFP_ZERO);
++	page = alloc_page(gfp_flags);
+ 	if (!page)
+ 		return NULL;
+ 
+diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
+index 9c9627e..cf6083a 100644
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -1349,6 +1349,10 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
+ 		spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ 		h->drv[drv_index].busy_configuring = 1;
+ 		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
++
++		/* deregister_disk sets h->drv[drv_index].queue = NULL */
++		/* which keeps the interrupt handler from starting */
++		/* the queue. */
+ 		ret = deregister_disk(h->gendisk[drv_index],
+ 				      &h->drv[drv_index], 0);
+ 		h->drv[drv_index].busy_configuring = 0;
+@@ -1419,6 +1423,10 @@ geo_inq:
+ 		blk_queue_hardsect_size(disk->queue,
+ 					hba[ctlr]->drv[drv_index].block_size);
+ 
++		/* Make sure all queue data is written out before */
++		/* setting h->drv[drv_index].queue, as setting this */
++		/* allows the interrupt handler to start the queue */
++		wmb();
+ 		h->drv[drv_index].queue = disk->queue;
+ 		add_disk(disk);
+ 	}
+@@ -3520,10 +3528,17 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
+ 			continue;
+ 		blk_queue_hardsect_size(q, drv->block_size);
+ 		set_capacity(disk, drv->nr_blocks);
+-		add_disk(disk);
+ 		j++;
+ 	} while (j <= hba[i]->highest_lun);
+ 
++	/* Make sure all queue data is written out before */
++	/* interrupt handler, triggered by add_disk,  */
++	/* is allowed to start them. */
++	wmb();
++
++	for (j = 0; j <= hba[i]->highest_lun; j++)
++		add_disk(hba[i]->gendisk[j]);
++
+ 	return 1;
+ 
+       clean4:
+diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
+index 45ac093..e4bf9a1 100644
+--- a/drivers/block/cciss_scsi.c
++++ b/drivers/block/cciss_scsi.c
+@@ -1349,9 +1349,9 @@ cciss_unregister_scsi(int ctlr)
+ 	/* set scsi_host to NULL so our detect routine will 
+ 	   find us on register */
+ 	sa->scsi_host = NULL;
++	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ 	scsi_cmd_stack_free(ctlr);
+ 	kfree(sa);
+-	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ }
+ 
+ static int 
+diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
+index 2411678..8b6bb76 100644
+--- a/drivers/block/cryptoloop.c
++++ b/drivers/block/cryptoloop.c
+@@ -27,7 +27,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/loop.h>
+ #include <linux/scatterlist.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index 91ebb00..f7f1635 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -82,6 +82,9 @@
+ static LIST_HEAD(loop_devices);
+ static DEFINE_MUTEX(loop_devices_mutex);
+ 
++static int max_part;
++static int part_shift;
++
+ /*
+  * Transfer functions
+  */
+@@ -692,6 +695,8 @@ static int loop_change_fd(struct loop_device *lo, struct file *lo_file,
+ 		goto out_putf;
+ 
+ 	fput(old_file);
++	if (max_part > 0)
++		ioctl_by_bdev(bdev, BLKRRPART, 0);
+ 	return 0;
+ 
+  out_putf:
+@@ -819,6 +824,8 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
+ 	}
+ 	lo->lo_state = Lo_bound;
+ 	wake_up_process(lo->lo_thread);
++	if (max_part > 0)
++		ioctl_by_bdev(bdev, BLKRRPART, 0);
+ 	return 0;
+ 
+ out_clr:
+@@ -919,6 +926,8 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
+ 	fput(filp);
+ 	/* This is safe: open() is still holding a reference. */
+ 	module_put(THIS_MODULE);
++	if (max_part > 0)
++		ioctl_by_bdev(bdev, BLKRRPART, 0);
+ 	return 0;
+ }
+ 
+@@ -1360,6 +1369,8 @@ static struct block_device_operations lo_fops = {
+ static int max_loop;
+ module_param(max_loop, int, 0);
+ MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
++module_param(max_part, int, 0);
++MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
+ 
+@@ -1412,7 +1423,7 @@ static struct loop_device *loop_alloc(int i)
+ 	if (!lo->lo_queue)
+ 		goto out_free_dev;
+ 
+-	disk = lo->lo_disk = alloc_disk(1);
++	disk = lo->lo_disk = alloc_disk(1 << part_shift);
+ 	if (!disk)
+ 		goto out_free_queue;
+ 
+@@ -1422,7 +1433,7 @@ static struct loop_device *loop_alloc(int i)
+ 	init_waitqueue_head(&lo->lo_event);
+ 	spin_lock_init(&lo->lo_lock);
+ 	disk->major		= LOOP_MAJOR;
+-	disk->first_minor	= i;
++	disk->first_minor	= i << part_shift;
+ 	disk->fops		= &lo_fops;
+ 	disk->private_data	= lo;
+ 	disk->queue		= lo->lo_queue;
+@@ -1502,7 +1513,12 @@ static int __init loop_init(void)
+ 	 *     themselves and have kernel automatically instantiate actual
+ 	 *     device on-demand.
+ 	 */
+-	if (max_loop > 1UL << MINORBITS)
++
++	part_shift = 0;
++	if (max_part > 0)
++		part_shift = fls(max_part);
++
++	if (max_loop > 1UL << (MINORBITS - part_shift))
+ 		return -EINVAL;
+ 
+ 	if (max_loop) {
+@@ -1510,7 +1526,7 @@ static int __init loop_init(void)
+ 		range = max_loop;
+ 	} else {
+ 		nr = 8;
+-		range = 1UL << MINORBITS;
++		range = 1UL << (MINORBITS - part_shift);
+ 	}
+ 
+ 	if (register_blkdev(LOOP_MAJOR, "loop"))
+@@ -1549,7 +1565,7 @@ static void __exit loop_exit(void)
+ 	unsigned long range;
+ 	struct loop_device *lo, *next;
+ 
+-	range = max_loop ? max_loop :  1UL << MINORBITS;
++	range = max_loop ? max_loop :  1UL << (MINORBITS - part_shift);
+ 
+ 	list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
+ 		loop_del_one(lo);
+diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
+index cd5674b..a18e1ca 100644
+--- a/drivers/block/sx8.c
++++ b/drivers/block/sx8.c
+@@ -79,9 +79,9 @@ MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30
+ 
+ /* note: prints function name for you */
+ #ifdef CARM_DEBUG
+-#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
++#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
+ #ifdef CARM_VERBOSE_DEBUG
+-#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
++#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
+ #else
+ #define VPRINTK(fmt, args...)
+ #endif	/* CARM_VERBOSE_DEBUG */
+@@ -96,7 +96,7 @@ MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30
+ #define assert(expr) \
+         if(unlikely(!(expr))) {                                   \
+         printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
+-        #expr,__FILE__,__FUNCTION__,__LINE__);          \
++	#expr, __FILE__, __func__, __LINE__);          \
+         }
+ #endif
+ 
+diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
+index 41ca721..ebfe038 100644
+--- a/drivers/block/viodasd.c
++++ b/drivers/block/viodasd.c
+@@ -69,7 +69,7 @@ MODULE_LICENSE("GPL");
+ enum {
+ 	PARTITION_SHIFT = 3,
+ 	MAX_DISKNO = HVMAXARCHITECTEDVIRTUALDISKS,
+-	MAX_DISK_NAME = sizeof(((struct gendisk *)0)->disk_name)
++	MAX_DISK_NAME = FIELD_SIZEOF(struct gendisk, disk_name)
+ };
+ 
+ static DEFINE_SPINLOCK(viodasd_spinlock);
+diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
+index 9c6f3f9..d771da8 100644
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -47,6 +47,7 @@
+ 
+ #include <xen/interface/grant_table.h>
+ #include <xen/interface/io/blkif.h>
++#include <xen/interface/io/protocols.h>
+ 
+ #include <asm/xen/hypervisor.h>
+ 
+@@ -74,7 +75,6 @@ static struct block_device_operations xlvbd_block_fops;
+ struct blkfront_info
+ {
+ 	struct xenbus_device *xbdev;
+-	dev_t dev;
+ 	struct gendisk *gd;
+ 	int vdevice;
+ 	blkif_vdev_t handle;
+@@ -88,6 +88,7 @@ struct blkfront_info
+ 	struct blk_shadow shadow[BLK_RING_SIZE];
+ 	unsigned long shadow_free;
+ 	int feature_barrier;
++	int is_ready;
+ 
+ 	/**
+ 	 * The number of people holding this device open.  We won't allow a
+@@ -614,6 +615,12 @@ again:
+ 		message = "writing event-channel";
+ 		goto abort_transaction;
+ 	}
++	err = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
++			    XEN_IO_PROTO_ABI_NATIVE);
++	if (err) {
++		message = "writing protocol";
++		goto abort_transaction;
++	}
+ 
+ 	err = xenbus_transaction_end(xbt, 0);
+ 	if (err) {
+@@ -833,6 +840,8 @@ static void blkfront_connect(struct blkfront_info *info)
+ 	spin_unlock_irq(&blkif_io_lock);
+ 
+ 	add_disk(info->gd);
++
++	info->is_ready = 1;
+ }
+ 
+ /**
+@@ -896,7 +905,7 @@ static void backend_changed(struct xenbus_device *dev,
+ 		break;
+ 
+ 	case XenbusStateClosing:
+-		bd = bdget(info->dev);
++		bd = bdget_disk(info->gd, 0);
+ 		if (bd == NULL)
+ 			xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
+ 
+@@ -925,6 +934,13 @@ static int blkfront_remove(struct xenbus_device *dev)
+ 	return 0;
+ }
+ 
++static int blkfront_is_ready(struct xenbus_device *dev)
++{
++	struct blkfront_info *info = dev->dev.driver_data;
++
++	return info->is_ready;
++}
++
+ static int blkif_open(struct inode *inode, struct file *filep)
+ {
+ 	struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
+@@ -971,6 +987,7 @@ static struct xenbus_driver blkfront = {
+ 	.remove = blkfront_remove,
+ 	.resume = blkfront_resume,
+ 	.otherend_changed = backend_changed,
++	.is_ready = blkfront_is_ready,
+ };
+ 
+ static int __init xlblk_init(void)
+@@ -998,3 +1015,5 @@ module_exit(xlblk_exit);
+ MODULE_DESCRIPTION("Xen virtual block device frontend");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS_BLOCKDEV_MAJOR(XENVBD_MAJOR);
++MODULE_ALIAS("xen:vbd");
++MODULE_ALIAS("xenblk");
+diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
+index 8b884f8..192522e 100644
+--- a/drivers/bluetooth/hci_usb.c
++++ b/drivers/bluetooth/hci_usb.c
+@@ -62,13 +62,13 @@
+ #define URB_ZERO_PACKET 0
+ #endif
+ 
+-static int ignore = 0;
+-static int ignore_dga = 0;
+-static int ignore_csr = 0;
+-static int ignore_sniffer = 0;
+-static int disable_scofix = 0;
+-static int force_scofix = 0;
+-static int reset = 0;
++static int ignore;
++static int ignore_dga;
++static int ignore_csr;
++static int ignore_sniffer;
++static int disable_scofix;
++static int force_scofix;
++static int reset;
+ 
+ #ifdef CONFIG_BT_HCIUSB_SCO
+ static int isoc = 2;
+@@ -265,7 +265,7 @@ static int hci_usb_intr_rx_submit(struct hci_usb *husb)
+ 		BT_ERR("%s intr rx submit failed urb %p err %d",
+ 				husb->hdev->name, urb, err);
+ 		_urb_unlink(_urb);
+-		_urb_free(_urb);
++		kfree(_urb);
+ 		kfree(buf);
+ 	}
+ 	return err;
+@@ -302,7 +302,7 @@ static int hci_usb_bulk_rx_submit(struct hci_usb *husb)
+ 		BT_ERR("%s bulk rx submit failed urb %p err %d",
+ 				husb->hdev->name, urb, err);
+ 		_urb_unlink(_urb);
+-		_urb_free(_urb);
++		kfree(_urb);
+ 		kfree(buf);
+ 	}
+ 	return err;
+@@ -353,7 +353,7 @@ static int hci_usb_isoc_rx_submit(struct hci_usb *husb)
+ 		BT_ERR("%s isoc rx submit failed urb %p err %d",
+ 				husb->hdev->name, urb, err);
+ 		_urb_unlink(_urb);
+-		_urb_free(_urb);
++		kfree(_urb);
+ 		kfree(buf);
+ 	}
+ 	return err;
+@@ -431,7 +431,7 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb)
+ 					husb->hdev->name, _urb, _urb->type, urb);
+ 			kfree(urb->setup_packet);
+ 			kfree(urb->transfer_buffer);
+-			_urb_free(_urb);
++			kfree(_urb);
+ 		}
+ 	}
+ }
+@@ -490,7 +490,7 @@ static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
+ 
+ 		dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
+ 		if (!dr) {
+-			_urb_free(_urb);
++			kfree(_urb);
+ 			return -ENOMEM;
+ 		}
+ 	} else
+diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
+index 56cd3a9..414080a 100644
+--- a/drivers/bluetooth/hci_usb.h
++++ b/drivers/bluetooth/hci_usb.h
+@@ -60,11 +60,6 @@ struct _urb {
+ 	struct urb        urb;
+ };
+ 
+-static inline void _urb_free(struct _urb *_urb)
+-{
+-	kfree(_urb);
+-}
+-
+ static inline void _urb_queue_init(struct _urb_queue *q)
+ {
+ 	INIT_LIST_HEAD(&q->head);
+diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
+index 12f5bae..ac38290 100644
+--- a/drivers/cdrom/cdrom.c
++++ b/drivers/cdrom/cdrom.c
+@@ -360,10 +360,9 @@ static int cdrom_mrw_exit(struct cdrom_device_info *cdi);
+ 
+ static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di);
+ 
+-#ifdef CONFIG_SYSCTL
+ static void cdrom_sysctl_register(void);
+-#endif /* CONFIG_SYSCTL */ 
+-static struct cdrom_device_info *topCdromPtr;
++
++static LIST_HEAD(cdrom_list);
+ 
+ static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
+ 				      struct packet_command *cgc)
+@@ -394,13 +393,11 @@ int register_cdrom(struct cdrom_device_info *cdi)
+ 	cdinfo(CD_OPEN, "entering register_cdrom\n"); 
+ 
+ 	if (cdo->open == NULL || cdo->release == NULL)
+-		return -2;
++		return -EINVAL;
+ 	if (!banner_printed) {
+ 		printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n");
+ 		banner_printed = 1;
+-#ifdef CONFIG_SYSCTL
+ 		cdrom_sysctl_register();
+-#endif /* CONFIG_SYSCTL */ 
+ 	}
+ 
+ 	ENSURE(drive_status, CDC_DRIVE_STATUS );
+@@ -439,35 +436,18 @@ int register_cdrom(struct cdrom_device_info *cdi)
+ 
+ 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
+ 	mutex_lock(&cdrom_mutex);
+-	cdi->next = topCdromPtr; 	
+-	topCdromPtr = cdi;
++	list_add(&cdi->list, &cdrom_list);
+ 	mutex_unlock(&cdrom_mutex);
+ 	return 0;
+ }
+ #undef ENSURE
+ 
+-int unregister_cdrom(struct cdrom_device_info *unreg)
++void unregister_cdrom(struct cdrom_device_info *cdi)
+ {
+-	struct cdrom_device_info *cdi, *prev;
+ 	cdinfo(CD_OPEN, "entering unregister_cdrom\n"); 
+ 
+-	prev = NULL;
+ 	mutex_lock(&cdrom_mutex);
+-	cdi = topCdromPtr;
+-	while (cdi && cdi != unreg) {
+-		prev = cdi;
+-		cdi = cdi->next;
+-	}
+-
+-	if (cdi == NULL) {
+-		mutex_unlock(&cdrom_mutex);
+-		return -2;
+-	}
+-	if (prev)
+-		prev->next = cdi->next;
+-	else
+-		topCdromPtr = cdi->next;
+-
++	list_del(&cdi->list);
+ 	mutex_unlock(&cdrom_mutex);
+ 
+ 	if (cdi->exit)
+@@ -475,34 +455,43 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
+ 
+ 	cdi->ops->n_minors--;
+ 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
+-	return 0;
+ }
+ 
+ int cdrom_get_media_event(struct cdrom_device_info *cdi,
+ 			  struct media_event_desc *med)
+ {
+ 	struct packet_command cgc;
+-	unsigned char buffer[8];
+-	struct event_header *eh = (struct event_header *) buffer;
++	unsigned char *buffer;
++	struct event_header *eh;
++	int ret = 1;
+ 
+-	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++	buffer = kmalloc(8, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
++
++	eh = (struct event_header *)buffer;
++
++	init_cdrom_command(&cgc, buffer, 8, CGC_DATA_READ);
+ 	cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
+ 	cgc.cmd[1] = 1;		/* IMMED */
+ 	cgc.cmd[4] = 1 << 4;	/* media event */
+-	cgc.cmd[8] = sizeof(buffer);
++	cgc.cmd[8] = 8;
+ 	cgc.quiet = 1;
+ 
+ 	if (cdi->ops->generic_packet(cdi, &cgc))
+-		return 1;
++		goto err;
+ 
+ 	if (be16_to_cpu(eh->data_len) < sizeof(*med))
+-		return 1;
++		goto err;
+ 
+ 	if (eh->nea || eh->notification_class != 0x4)
+-		return 1;
++		goto err;
+ 
+-	memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
+-	return 0;
++	memcpy(med, buffer + sizeof(*eh), sizeof(*med));
++	ret = 0;
++err:
++	kfree(buffer);
++	return ret;
+ }
+ 
+ /*
+@@ -512,68 +501,82 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi,
+ static int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi)
+ {
+ 	struct packet_command cgc;
+-	char buffer[16];
++	char *buffer;
++	int ret = 1;
+ 
+-	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++	buffer = kmalloc(16, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
++
++	init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+ 
+ 	cgc.timeout = HZ;
+ 	cgc.quiet = 1;
+ 
+ 	if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) {
+ 		cdi->mrw_mode_page = MRW_MODE_PC;
+-		return 0;
++		ret = 0;
+ 	} else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) {
+ 		cdi->mrw_mode_page = MRW_MODE_PC_PRE1;
+-		return 0;
++		ret = 0;
+ 	}
+-
+-	return 1;
++	kfree(buffer);
++	return ret;
+ }
+ 
+ static int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write)
+ {
+ 	struct packet_command cgc;
+ 	struct mrw_feature_desc *mfd;
+-	unsigned char buffer[16];
++	unsigned char *buffer;
+ 	int ret;
+ 
+ 	*write = 0;
++	buffer = kmalloc(16, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
+ 
+-	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++	init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+ 
+ 	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+ 	cgc.cmd[3] = CDF_MRW;
+-	cgc.cmd[8] = sizeof(buffer);
++	cgc.cmd[8] = 16;
+ 	cgc.quiet = 1;
+ 
+ 	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+-		return ret;
++		goto err;
+ 
+ 	mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
+-	if (be16_to_cpu(mfd->feature_code) != CDF_MRW)
+-		return 1;
++	if (be16_to_cpu(mfd->feature_code) != CDF_MRW) {
++		ret = 1;
++		goto err;
++	}
+ 	*write = mfd->write;
+ 
+ 	if ((ret = cdrom_mrw_probe_pc(cdi))) {
+ 		*write = 0;
+-		return ret;
+ 	}
+-
+-	return 0;
++err:
++	kfree(buffer);
++	return ret;
+ }
+ 
+ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
+ {
+ 	struct packet_command cgc;
+-	unsigned char buffer[12];
++	unsigned char *buffer;
+ 	int ret;
+ 
+ 	printk(KERN_INFO "cdrom: %sstarting format\n", cont ? "Re" : "");
+ 
++	buffer = kmalloc(12, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
++
+ 	/*
+ 	 * FmtData bit set (bit 4), format type is 1
+ 	 */
+-	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_WRITE);
++	init_cdrom_command(&cgc, buffer, 12, CGC_DATA_WRITE);
+ 	cgc.cmd[0] = GPCMD_FORMAT_UNIT;
+ 	cgc.cmd[1] = (1 << 4) | 1;
+ 
+@@ -600,6 +603,7 @@ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
+ 	if (ret)
+ 		printk(KERN_INFO "cdrom: bgformat failed\n");
+ 
++	kfree(buffer);
+ 	return ret;
+ }
+ 
+@@ -659,16 +663,17 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
+ {
+ 	struct packet_command cgc;
+ 	struct mode_page_header *mph;
+-	char buffer[16];
++	char *buffer;
+ 	int ret, offset, size;
+ 
+-	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++	buffer = kmalloc(16, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
+ 
+-	cgc.buffer = buffer;
+-	cgc.buflen = sizeof(buffer);
++	init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+ 
+ 	if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
+-		return ret;
++		goto err;
+ 
+ 	mph = (struct mode_page_header *) buffer;
+ 	offset = be16_to_cpu(mph->desc_length);
+@@ -678,55 +683,70 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
+ 	cgc.buflen = size;
+ 
+ 	if ((ret = cdrom_mode_select(cdi, &cgc)))
+-		return ret;
++		goto err;
+ 
+ 	printk(KERN_INFO "cdrom: %s: mrw address space %s selected\n", cdi->name, mrw_address_space[space]);
+-	return 0;
++	ret = 0;
++err:
++	kfree(buffer);
++	return ret;
+ }
+ 
+ static int cdrom_get_random_writable(struct cdrom_device_info *cdi,
+ 			      struct rwrt_feature_desc *rfd)
+ {
+ 	struct packet_command cgc;
+-	char buffer[24];
++	char *buffer;
+ 	int ret;
+ 
+-	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++	buffer = kmalloc(24, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
++
++	init_cdrom_command(&cgc, buffer, 24, CGC_DATA_READ);
+ 
+ 	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;	/* often 0x46 */
+ 	cgc.cmd[3] = CDF_RWRT;			/* often 0x0020 */
+-	cgc.cmd[8] = sizeof(buffer);		/* often 0x18 */
++	cgc.cmd[8] = 24;		        /* often 0x18 */
+ 	cgc.quiet = 1;
+ 
+ 	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+-		return ret;
++		goto err;
+ 
+ 	memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
+-	return 0;
++	ret = 0;
++err:
++	kfree(buffer);
++	return ret;
+ }
+ 
+ static int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
+ {
+ 	struct packet_command cgc;
+-	char buffer[16];
++	char *buffer;
+ 	__be16 *feature_code;
+ 	int ret;
+ 
+-	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++	buffer = kmalloc(16, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
++
++	init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+ 
+ 	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+ 	cgc.cmd[3] = CDF_HWDM;
+-	cgc.cmd[8] = sizeof(buffer);
++	cgc.cmd[8] = 16;
+ 	cgc.quiet = 1;
+ 
+ 	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+-		return ret;
++		goto err;
+ 
+ 	feature_code = (__be16 *) &buffer[sizeof(struct feature_header)];
+ 	if (be16_to_cpu(*feature_code) == CDF_HWDM)
+-		return 0;
+-
+-	return 1;
++		ret = 0;
++err:
++	kfree(buffer);
++	return ret;
+ }
+ 
+ 
+@@ -817,10 +837,14 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
+ static int mo_open_write(struct cdrom_device_info *cdi)
+ {
+ 	struct packet_command cgc;
+-	char buffer[255];
++	char *buffer;
+ 	int ret;
+ 
+-	init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ);
++	buffer = kmalloc(255, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
++
++	init_cdrom_command(&cgc, buffer, 4, CGC_DATA_READ);
+ 	cgc.quiet = 1;
+ 
+ 	/*
+@@ -837,10 +861,15 @@ static int mo_open_write(struct cdrom_device_info *cdi)
+ 	}
+ 
+ 	/* drive gave us no info, let the user go ahead */
+-	if (ret)
+-		return 0;
++	if (ret) {
++		ret = 0;
++		goto err;
++	}
+ 
+-	return buffer[3] & 0x80;
++	ret = buffer[3] & 0x80;
++err:
++	kfree(buffer);
++	return ret;
+ }
+ 
+ static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
+@@ -863,15 +892,19 @@ static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
+ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
+ {
+ 	struct packet_command cgc;
+-	char buffer[32];
++	char *buffer;
+ 	int ret, mmc3_profile;
+ 
+-	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++	buffer = kmalloc(32, GFP_KERNEL);
++	if (!buffer)
++		return;
++
++	init_cdrom_command(&cgc, buffer, 32, CGC_DATA_READ);
+ 
+ 	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+ 	cgc.cmd[1] = 0;
+ 	cgc.cmd[2] = cgc.cmd[3] = 0;		/* Starting Feature Number */
+-	cgc.cmd[8] = sizeof(buffer);		/* Allocation Length */
++	cgc.cmd[8] = 32;		        /* Allocation Length */
+ 	cgc.quiet = 1;
+ 
+ 	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+@@ -880,6 +913,7 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
+ 		mmc3_profile = (buffer[6] << 8) | buffer[7];
+ 
+ 	cdi->mmc3_profile = mmc3_profile;
++	kfree(buffer);
+ }
+ 
+ static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi)
+@@ -1594,12 +1628,15 @@ static void setup_send_key(struct packet_command *cgc, unsigned agid, unsigned t
+ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ {
+ 	int ret;
+-	u_char buf[20];
++	u_char *buf;
+ 	struct packet_command cgc;
+ 	struct cdrom_device_ops *cdo = cdi->ops;
+-	rpc_state_t rpc_state;
++	rpc_state_t *rpc_state;
++
++	buf = kzalloc(20, GFP_KERNEL);
++	if (!buf)
++		return -ENOMEM;
+ 
+-	memset(buf, 0, sizeof(buf));
+ 	init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
+ 
+ 	switch (ai->type) {
+@@ -1610,7 +1647,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ 		setup_report_key(&cgc, ai->lsa.agid, 0);
+ 
+ 		if ((ret = cdo->generic_packet(cdi, &cgc)))
+-			return ret;
++			goto err;
+ 
+ 		ai->lsa.agid = buf[7] >> 6;
+ 		/* Returning data, let host change state */
+@@ -1621,7 +1658,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ 		setup_report_key(&cgc, ai->lsk.agid, 2);
+ 
+ 		if ((ret = cdo->generic_packet(cdi, &cgc)))
+-			return ret;
++			goto err;
+ 
+ 		copy_key(ai->lsk.key, &buf[4]);
+ 		/* Returning data, let host change state */
+@@ -1632,7 +1669,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ 		setup_report_key(&cgc, ai->lsc.agid, 1);
+ 
+ 		if ((ret = cdo->generic_packet(cdi, &cgc)))
+-			return ret;
++			goto err;
+ 
+ 		copy_chal(ai->lsc.chal, &buf[4]);
+ 		/* Returning data, let host change state */
+@@ -1649,7 +1686,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ 		cgc.cmd[2] = ai->lstk.lba >> 24;
+ 
+ 		if ((ret = cdo->generic_packet(cdi, &cgc)))
+-			return ret;
++			goto err;
+ 
+ 		ai->lstk.cpm = (buf[4] >> 7) & 1;
+ 		ai->lstk.cp_sec = (buf[4] >> 6) & 1;
+@@ -1663,7 +1700,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ 		setup_report_key(&cgc, ai->lsasf.agid, 5);
+ 		
+ 		if ((ret = cdo->generic_packet(cdi, &cgc)))
+-			return ret;
++			goto err;
+ 
+ 		ai->lsasf.asf = buf[7] & 1;
+ 		break;
+@@ -1676,7 +1713,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ 		copy_chal(&buf[4], ai->hsc.chal);
+ 
+ 		if ((ret = cdo->generic_packet(cdi, &cgc)))
+-			return ret;
++			goto err;
+ 
+ 		ai->type = DVD_LU_SEND_KEY1;
+ 		break;
+@@ -1689,7 +1726,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ 
+ 		if ((ret = cdo->generic_packet(cdi, &cgc))) {
+ 			ai->type = DVD_AUTH_FAILURE;
+-			return ret;
++			goto err;
+ 		}
+ 		ai->type = DVD_AUTH_ESTABLISHED;
+ 		break;
+@@ -1700,24 +1737,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ 		cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); 
+ 		setup_report_key(&cgc, ai->lsa.agid, 0x3f);
+ 		if ((ret = cdo->generic_packet(cdi, &cgc)))
+-			return ret;
++			goto err;
+ 		break;
+ 
+ 	/* Get region settings */
+ 	case DVD_LU_SEND_RPC_STATE:
+ 		cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
+ 		setup_report_key(&cgc, 0, 8);
+-		memset(&rpc_state, 0, sizeof(rpc_state_t));
+-		cgc.buffer = (char *) &rpc_state;
+ 
+ 		if ((ret = cdo->generic_packet(cdi, &cgc)))
+-			return ret;
++			goto err;
+ 
+-		ai->lrpcs.type = rpc_state.type_code;
+-		ai->lrpcs.vra = rpc_state.vra;
+-		ai->lrpcs.ucca = rpc_state.ucca;
+-		ai->lrpcs.region_mask = rpc_state.region_mask;
+-		ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
++		rpc_state = (rpc_state_t *)buf;
++		ai->lrpcs.type = rpc_state->type_code;
++		ai->lrpcs.vra = rpc_state->vra;
++		ai->lrpcs.ucca = rpc_state->ucca;
++		ai->lrpcs.region_mask = rpc_state->region_mask;
++		ai->lrpcs.rpc_scheme = rpc_state->rpc_scheme;
+ 		break;
+ 
+ 	/* Set region settings */
+@@ -1728,20 +1764,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ 		buf[4] = ai->hrpcs.pdrc;
+ 
+ 		if ((ret = cdo->generic_packet(cdi, &cgc)))
+-			return ret;
++			goto err;
+ 		break;
+ 
+ 	default:
+ 		cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
+-		return -ENOTTY;
++		ret = -ENOTTY;
++		goto err;
+ 	}
+-
+-	return 0;
++	ret = 0;
++err:
++	kfree(buf);
++	return ret;
+ }
+ 
+ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
+ {
+-	unsigned char buf[21], *base;
++	unsigned char *buf, *base;
+ 	struct dvd_layer *layer;
+ 	struct packet_command cgc;
+ 	struct cdrom_device_ops *cdo = cdi->ops;
+@@ -1750,7 +1789,11 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
+ 	if (layer_num >= DVD_LAYERS)
+ 		return -EINVAL;
+ 
+-	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
++	buf = kmalloc(21, GFP_KERNEL);
++	if (!buf)
++		return -ENOMEM;
++
++	init_cdrom_command(&cgc, buf, 21, CGC_DATA_READ);
+ 	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
+ 	cgc.cmd[6] = layer_num;
+ 	cgc.cmd[7] = s->type;
+@@ -1762,7 +1805,7 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
+ 	cgc.quiet = 1;
+ 
+ 	if ((ret = cdo->generic_packet(cdi, &cgc)))
+-		return ret;
++		goto err;
+ 
+ 	base = &buf[4];
+ 	layer = &s->physical.layer[layer_num];
+@@ -1786,17 +1829,24 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
+ 	layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
+ 	layer->bca = base[16] >> 7;
+ 
+-	return 0;
++	ret = 0;
++err:
++	kfree(buf);
++	return ret;
+ }
+ 
+ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
+ {
+ 	int ret;
+-	u_char buf[8];
++	u_char *buf;
+ 	struct packet_command cgc;
+ 	struct cdrom_device_ops *cdo = cdi->ops;
+ 
+-	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
++	buf = kmalloc(8, GFP_KERNEL);
++	if (!buf)
++		return -ENOMEM;
++
++	init_cdrom_command(&cgc, buf, 8, CGC_DATA_READ);
+ 	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
+ 	cgc.cmd[6] = s->copyright.layer_num;
+ 	cgc.cmd[7] = s->type;
+@@ -1804,12 +1854,15 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
+ 	cgc.cmd[9] = cgc.buflen & 0xff;
+ 
+ 	if ((ret = cdo->generic_packet(cdi, &cgc)))
+-		return ret;
++		goto err;
+ 
+ 	s->copyright.cpst = buf[4];
+ 	s->copyright.rmi = buf[5];
+ 
+-	return 0;
++	ret = 0;
++err:
++	kfree(buf);
++	return ret;
+ }
+ 
+ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
+@@ -1841,26 +1894,33 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
+ static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
+ {
+ 	int ret;
+-	u_char buf[4 + 188];
++	u_char *buf;
+ 	struct packet_command cgc;
+ 	struct cdrom_device_ops *cdo = cdi->ops;
+ 
+-	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
++	buf = kmalloc(4 + 188, GFP_KERNEL);
++	if (!buf)
++		return -ENOMEM;
++
++	init_cdrom_command(&cgc, buf, 4 + 188, CGC_DATA_READ);
+ 	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
+ 	cgc.cmd[7] = s->type;
+ 	cgc.cmd[9] = cgc.buflen & 0xff;
+ 
+ 	if ((ret = cdo->generic_packet(cdi, &cgc)))
+-		return ret;
++		goto err;
+ 
+ 	s->bca.len = buf[0] << 8 | buf[1];
+ 	if (s->bca.len < 12 || s->bca.len > 188) {
+ 		cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len);
+-		return -EIO;
++		ret = -EIO;
++		goto err;
+ 	}
+ 	memcpy(s->bca.value, &buf[4], s->bca.len);
+-
+-	return 0;
++	ret = 0;
++err:
++	kfree(buf);
++	return ret;
+ }
+ 
+ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
+@@ -1960,9 +2020,13 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
+ {
+ 	struct cdrom_device_ops *cdo = cdi->ops;
+ 	struct packet_command cgc;
+-	char buffer[32];
++	char *buffer;
+ 	int ret;
+ 
++	buffer = kmalloc(32, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
++
+ 	init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+ 	cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
+ 	cgc.cmd[1] = 2;     /* MSF addressing */
+@@ -1971,7 +2035,7 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
+ 	cgc.cmd[8] = 16;
+ 
+ 	if ((ret = cdo->generic_packet(cdi, &cgc)))
+-		return ret;
++		goto err;
+ 
+ 	subchnl->cdsc_audiostatus = cgc.buffer[1];
+ 	subchnl->cdsc_format = CDROM_MSF;
+@@ -1986,7 +2050,10 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
+ 	subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
+ 	subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
+ 
+-	return 0;
++	ret = 0;
++err:
++	kfree(buffer);
++	return ret;
+ }
+ 
+ /*
+@@ -3309,7 +3376,7 @@ static int cdrom_print_info(const char *header, int val, char *info,
+ 
+ 	*pos += ret;
+ 
+-	for (cdi = topCdromPtr; cdi; cdi = cdi->next) {
++	list_for_each_entry(cdi, &cdrom_list, list) {
+ 		switch (option) {
+ 		case CTL_NAME:
+ 			ret = scnprintf(info + *pos, max_size - *pos,
+@@ -3430,7 +3497,8 @@ static void cdrom_update_settings(void)
+ {
+ 	struct cdrom_device_info *cdi;
+ 
+-	for (cdi = topCdromPtr; cdi != NULL; cdi = cdi->next) {
++	mutex_lock(&cdrom_mutex);
++	list_for_each_entry(cdi, &cdrom_list, list) {
+ 		if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY))
+ 			cdi->options |= CDO_AUTO_CLOSE;
+ 		else if (!autoclose)
+@@ -3448,6 +3516,7 @@ static void cdrom_update_settings(void)
+ 		else
+ 			cdi->options &= ~CDO_CHECK_TYPE;
+ 	}
++	mutex_unlock(&cdrom_mutex);
+ }
+ 
+ static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp,
+@@ -3571,22 +3640,29 @@ static void cdrom_sysctl_unregister(void)
+ 		unregister_sysctl_table(cdrom_sysctl_header);
+ }
+ 
++#else /* CONFIG_SYSCTL */
++
++static void cdrom_sysctl_register(void)
++{
++}
++
++static void cdrom_sysctl_unregister(void)
++{
++}
++
+ #endif /* CONFIG_SYSCTL */
+ 
+ static int __init cdrom_init(void)
+ {
+-#ifdef CONFIG_SYSCTL
+ 	cdrom_sysctl_register();
+-#endif
++
+ 	return 0;
+ }
+ 
+ static void __exit cdrom_exit(void)
+ {
+ 	printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
+-#ifdef CONFIG_SYSCTL
+ 	cdrom_sysctl_unregister();
+-#endif
+ }
+ 
+ module_init(cdrom_init);
+diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
+index 4e2bbcc..71ec426 100644
+--- a/drivers/cdrom/gdrom.c
++++ b/drivers/cdrom/gdrom.c
+@@ -827,7 +827,9 @@ static int __devexit remove_gdrom(struct platform_device *devptr)
+ 	del_gendisk(gd.disk);
+ 	if (gdrom_major)
+ 		unregister_blkdev(gdrom_major, GDROM_DEV_NAME);
+-	return unregister_cdrom(gd.cd_info);
++	unregister_cdrom(gd.cd_info);
++
++	return 0;
+ }
+ 
+ static struct platform_driver gdrom_driver = {
+diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
+index cac06bc..b74b6c2 100644
+--- a/drivers/cdrom/viocd.c
++++ b/drivers/cdrom/viocd.c
+@@ -650,10 +650,7 @@ static int viocd_remove(struct vio_dev *vdev)
+ {
+ 	struct disk_info *d = &viocd_diskinfo[vdev->unit_address];
+ 
+-	if (unregister_cdrom(&d->viocd_info) != 0)
+-		printk(VIOCD_KERN_WARNING
+-				"Cannot unregister viocd CD-ROM %s!\n",
+-				d->viocd_info.name);
++	unregister_cdrom(&d->viocd_info);
+ 	del_gendisk(d->viocd_disk);
+ 	blk_cleanup_queue(d->viocd_disk->queue);
+ 	put_disk(d->viocd_disk);
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 47c6be8..2906ee7 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -481,6 +481,34 @@ config BRIQ_PANEL
+ 
+ 	  It's safe to say N here.
+ 
++config BFIN_OTP
++	tristate "Blackfin On-Chip OTP Memory Support"
++	depends on BLACKFIN && (BF52x || BF54x)
++	default y
++	help
++	  If you say Y here, you will get support for a character device
++	  interface into the One Time Programmable memory pages that are
++	  stored on the Blackfin processor.  This will not get you access
++	  to the secure memory pages however.  You will need to write your
++	  own secure code and reader for that.
++
++	  To compile this driver as a module, choose M here: the module
++	  will be called bfin-otp.
++
++	  If unsure, it is safe to say Y.
++
++config BFIN_OTP_WRITE_ENABLE
++	bool "Enable writing support of OTP pages"
++	depends on BFIN_OTP
++	default n
++	help
++	  If you say Y here, you will enable support for writing of the
++	  OTP pages.  This is dangerous by nature as you can only program
++	  the pages once, so only enable this option when you actually
++	  need it so as to not inadvertently clobber data.
++
++	  If unsure, say N.
++
+ config PRINTER
+ 	tristate "Parallel printer support"
+ 	depends on PARPORT
+@@ -706,7 +734,7 @@ config NVRAM
+ 
+ config RTC
+ 	tristate "Enhanced Real Time Clock Support"
+-	depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390
++	depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390 && !AVR32
+ 	---help---
+ 	  If you say Y here and create a character special file /dev/rtc with
+ 	  major number 10 and minor number 135 using mknod ("man mknod"), you
+@@ -776,7 +804,7 @@ config SGI_IP27_RTC
+ 
+ config GEN_RTC
+ 	tristate "Generic /dev/rtc emulation"
+-	depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH
++	depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32
+ 	---help---
+ 	  If you say Y here and create a character special file /dev/rtc with
+ 	  major number 10 and minor number 135 using mknod ("man mknod"), you
+diff --git a/drivers/char/Makefile b/drivers/char/Makefile
+index 5407b76..4c1c584 100644
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -59,6 +59,7 @@ obj-$(CONFIG_VIOTAPE)		+= viotape.o
+ obj-$(CONFIG_HVCS)		+= hvcs.o
+ obj-$(CONFIG_SGI_MBCS)		+= mbcs.o
+ obj-$(CONFIG_BRIQ_PANEL)	+= briq_panel.o
++obj-$(CONFIG_BFIN_OTP)		+= bfin-otp.o
+ 
+ obj-$(CONFIG_PRINTER)		+= lp.o
+ obj-$(CONFIG_TIPAR)		+= tipar.o
+diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
+index d286699..96bdb92 100644
+--- a/drivers/char/agp/amd-k7-agp.c
++++ b/drivers/char/agp/amd-k7-agp.c
+@@ -436,8 +436,9 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
+ 	   system controller may experience noise due to strong drive strengths
+ 	 */
+ 	if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) {
+-		u8 cap_ptr=0;
+ 		struct pci_dev *gfxcard=NULL;
++
++		cap_ptr = 0;
+ 		while (!cap_ptr) {
+ 			gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard);
+ 			if (!gfxcard) {
+diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
+index 55d7a82..857b262 100644
+--- a/drivers/char/agp/frontend.c
++++ b/drivers/char/agp/frontend.c
+@@ -967,7 +967,7 @@ int agpioc_chipset_flush_wrap(struct agp_file_private *priv)
+ 	return 0;
+ }
+ 
+-static int agp_ioctl(struct inode *inode, struct file *file,
++static long agp_ioctl(struct file *file,
+ 		     unsigned int cmd, unsigned long arg)
+ {
+ 	struct agp_file_private *curr_priv = file->private_data;
+@@ -1058,7 +1058,7 @@ static const struct file_operations agp_fops =
+ 	.llseek		= no_llseek,
+ 	.read		= agp_read,
+ 	.write		= agp_write,
+-	.ioctl		= agp_ioctl,
++	.unlocked_ioctl	= agp_ioctl,
+ #ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= compat_agp_ioctl,
+ #endif
+diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
+new file mode 100644
+index 0000000..0a01329
+--- /dev/null
++++ b/drivers/char/bfin-otp.c
+@@ -0,0 +1,189 @@
++/*
++ * Blackfin On-Chip OTP Memory Interface
++ *  Supports BF52x/BF54x
++ *
++ * Copyright 2007-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ */
++
++#include <linux/device.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/types.h>
++
++#include <asm/blackfin.h>
++#include <asm/uaccess.h>
++
++#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
++#define stampit() stamp("here i am")
++#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
++
++#define DRIVER_NAME "bfin-otp"
++#define PFX DRIVER_NAME ": "
++
++static DEFINE_MUTEX(bfin_otp_lock);
++
++/* OTP Boot ROM functions */
++#define _BOOTROM_OTP_COMMAND           0xEF000018
++#define _BOOTROM_OTP_READ              0xEF00001A
++#define _BOOTROM_OTP_WRITE             0xEF00001C
++
++static u32 (* const otp_command)(u32 command, u32 value) = (void *)_BOOTROM_OTP_COMMAND;
++static u32 (* const otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_READ;
++static u32 (* const otp_write)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_WRITE;
++
++/* otp_command(): defines for "command" */
++#define OTP_INIT             0x00000001
++#define OTP_CLOSE            0x00000002
++
++/* otp_{read,write}(): defines for "flags" */
++#define OTP_LOWER_HALF       0x00000000 /* select upper/lower 64-bit half (bit 0) */
++#define OTP_UPPER_HALF       0x00000001
++#define OTP_NO_ECC           0x00000010 /* do not use ECC */
++#define OTP_LOCK             0x00000020 /* sets page protection bit for page */
++#define OTP_ACCESS_READ      0x00001000
++#define OTP_ACCESS_READWRITE 0x00002000
++
++/* Return values for all functions */
++#define OTP_SUCCESS          0x00000000
++#define OTP_MASTER_ERROR     0x001
++#define OTP_WRITE_ERROR      0x003
++#define OTP_READ_ERROR       0x005
++#define OTP_ACC_VIO_ERROR    0x009
++#define OTP_DATA_MULT_ERROR  0x011
++#define OTP_ECC_MULT_ERROR   0x021
++#define OTP_PREV_WR_ERROR    0x041
++#define OTP_DATA_SB_WARN     0x100
++#define OTP_ECC_SB_WARN      0x200
++
++/**
++ *	bfin_otp_read - Read OTP pages
++ *
++ *	All reads must be in half page chunks (half page == 64 bits).
++ */
++static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count, loff_t *pos)
++{
++	ssize_t bytes_done;
++	u32 page, flags, ret;
++	u64 content;
++
++	stampit();
++
++	if (count % sizeof(u64))
++		return -EMSGSIZE;
++
++	if (mutex_lock_interruptible(&bfin_otp_lock))
++		return -ERESTARTSYS;
++
++	bytes_done = 0;
++	page = *pos / (sizeof(u64) * 2);
++	while (bytes_done < count) {
++		flags = (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
++		stamp("processing page %i (%s)", page, (flags == OTP_UPPER_HALF ? "upper" : "lower"));
++		ret = otp_read(page, flags, &content);
++		if (ret & OTP_MASTER_ERROR) {
++			bytes_done = -EIO;
++			break;
++		}
++		if (copy_to_user(buff + bytes_done, &content, sizeof(content))) {
++			bytes_done = -EFAULT;
++			break;
++		}
++		if (flags == OTP_UPPER_HALF)
++			++page;
++		bytes_done += sizeof(content);
++		*pos += sizeof(content);
++	}
++
++	mutex_unlock(&bfin_otp_lock);
++
++	return bytes_done;
++}
++
++#ifdef CONFIG_BFIN_OTP_WRITE_ENABLE
++/**
++ *	bfin_otp_write - Write OTP pages
++ *
++ *	All writes must be in half page chunks (half page == 64 bits).
++ */
++static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos)
++{
++	stampit();
++
++	if (count % sizeof(u64))
++		return -EMSGSIZE;
++
++	if (mutex_lock_interruptible(&bfin_otp_lock))
++		return -ERESTARTSYS;
++
++	/* need otp_init() documentation before this can be implemented */
++
++	mutex_unlock(&bfin_otp_lock);
++
++	return -EINVAL;
++}
++#else
++# define bfin_otp_write NULL
++#endif
++
++static struct file_operations bfin_otp_fops = {
++	.owner    = THIS_MODULE,
++	.read     = bfin_otp_read,
++	.write    = bfin_otp_write,
++};
++
++static struct miscdevice bfin_otp_misc_device = {
++	.minor    = MISC_DYNAMIC_MINOR,
++	.name     = DRIVER_NAME,
++	.fops     = &bfin_otp_fops,
++};
++
++/**
++ *	bfin_otp_init - Initialize module
++ *
++ *	Registers the device and notifier handler. Actual device
++ *	initialization is handled by bfin_otp_open().
++ */
++static int __init bfin_otp_init(void)
++{
++	int ret;
++
++	stampit();
++
++	ret = misc_register(&bfin_otp_misc_device);
++	if (ret) {
++		pr_init(KERN_ERR PFX "unable to register a misc device\n");
++		return ret;
++	}
++
++	pr_init(KERN_INFO PFX "initialized\n");
++
++	return 0;
++}
++
++/**
++ *	bfin_otp_exit - Deinitialize module
++ *
++ *	Unregisters the device and notifier handler. Actual device
++ *	deinitialization is handled by bfin_otp_close().
++ */
++static void __exit bfin_otp_exit(void)
++{
++	stampit();
++
++	misc_deregister(&bfin_otp_misc_device);
++}
++
++module_init(bfin_otp_init);
++module_exit(bfin_otp_exit);
++
++MODULE_AUTHOR("Mike Frysinger <vapier at gentoo.org>");
++MODULE_DESCRIPTION("Blackfin OTP Memory Interface");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
+index 141f4df..b710426 100644
+--- a/drivers/char/drm/ati_pcigart.c
++++ b/drivers/char/drm/ati_pcigart.c
+@@ -167,13 +167,6 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
+ 			page_base += ATI_PCIGART_PAGE_SIZE;
+ 		}
+ 	}
+-
+-	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
+-		dma_sync_single_for_device(&dev->pdev->dev,
+-					   bus_address,
+-					   max_pages * sizeof(u32),
+-					   PCI_DMA_TODEVICE);
+-
+ 	ret = 1;
+ 
+ #if defined(__i386__) || defined(__x86_64__)
+diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
+index 3a05c6d..6874f31 100644
+--- a/drivers/char/drm/drm.h
++++ b/drivers/char/drm/drm.h
+@@ -471,6 +471,7 @@ struct drm_irq_busid {
+ enum drm_vblank_seq_type {
+ 	_DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */
+ 	_DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */
++	_DRM_VBLANK_FLIP = 0x8000000,	/**< Scheduled buffer swap should flip */
+ 	_DRM_VBLANK_NEXTONMISS = 0x10000000,	/**< If missed, wait for next vblank */
+ 	_DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
+ 	_DRM_VBLANK_SIGNAL = 0x40000000	/**< Send signal instead of blocking */
+@@ -503,6 +504,21 @@ union drm_wait_vblank {
+ 	struct drm_wait_vblank_reply reply;
+ };
+ 
++enum drm_modeset_ctl_cmd {
++	_DRM_PRE_MODESET = 1,
++	_DRM_POST_MODESET = 2,
++};
++
++/**
++ * DRM_IOCTL_MODESET_CTL ioctl argument type
++ *
++ * \sa drmModesetCtl().
++ */
++struct drm_modeset_ctl {
++	unsigned long arg;
++	enum drm_modeset_ctl_cmd cmd;
++};
++
+ /**
+  * DRM_IOCTL_AGP_ENABLE ioctl argument type.
+  *
+@@ -587,6 +603,7 @@ struct drm_set_version {
+ #define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
+ #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
+ #define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, struct drm_set_version)
++#define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08, struct drm_modeset_ctl)
+ 
+ #define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, struct drm_unique)
+ #define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, struct drm_auth)
+diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
+index 8ea9dd1..ecee354 100644
+--- a/drivers/char/drm/drmP.h
++++ b/drivers/char/drm/drmP.h
+@@ -100,10 +100,8 @@ struct drm_device;
+ #define DRIVER_HAVE_DMA    0x20
+ #define DRIVER_HAVE_IRQ    0x40
+ #define DRIVER_IRQ_SHARED  0x80
+-#define DRIVER_IRQ_VBL     0x100
+ #define DRIVER_DMA_QUEUE   0x200
+ #define DRIVER_FB_DMA      0x400
+-#define DRIVER_IRQ_VBL2    0x800
+ 
+ /***********************************************************************/
+ /** \name Begin the DRM... */
+@@ -379,13 +377,12 @@ struct drm_buf_entry {
+ struct drm_file {
+ 	int authenticated;
+ 	int master;
+-	int minor;
+ 	pid_t pid;
+ 	uid_t uid;
+ 	drm_magic_t magic;
+ 	unsigned long ioctl_count;
+ 	struct list_head lhead;
+-	struct drm_head *head;
++	struct drm_minor *minor;
+ 	int remove_auth_on_close;
+ 	unsigned long lock_count;
+ 	struct file *filp;
+@@ -580,10 +577,52 @@ struct drm_driver {
+ 	int (*context_dtor) (struct drm_device *dev, int context);
+ 	int (*kernel_context_switch) (struct drm_device *dev, int old,
+ 				      int new);
+-	void (*kernel_context_switch_unlock) (struct drm_device *dev);
+-	int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
+-	int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
+-	int (*dri_library_name) (struct drm_device *dev, char *buf);
++	void (*kernel_context_switch_unlock) (struct drm_device * dev);
++	/**
++	 * get_vblank_counter - get raw hardware vblank counter
++	 * @dev: DRM device
++	 * @crtc: counter to fetch
++	 *
++	 * Driver callback for fetching a raw hardware vblank counter
++	 * for @crtc.  If a device doesn't have a hardware counter, the
++	 * driver can simply return the value of drm_vblank_count and
++	 * make the enable_vblank() and disable_vblank() hooks into no-ops,
++	 * leaving interrupts enabled at all times.
++	 *
++	 * Wraparound handling and loss of events due to modesetting is dealt
++	 * with in the DRM core code.
++	 *
++	 * RETURNS
++	 * Raw vblank counter value.
++	 */
++	u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
++
++	/**
++	 * enable_vblank - enable vblank interrupt events
++	 * @dev: DRM device
++	 * @crtc: which irq to enable
++	 *
++	 * Enable vblank interrupts for @crtc.  If the device doesn't have
++	 * a hardware vblank counter, this routine should be a no-op, since
++	 * interrupts will have to stay on to keep the count accurate.
++	 *
++	 * RETURNS
++	 * Zero on success, appropriate errno if the given @crtc's vblank
++	 * interrupt cannot be enabled.
++	 */
++	int (*enable_vblank) (struct drm_device *dev, int crtc);
++
++	/**
++	 * disable_vblank - disable vblank interrupt events
++	 * @dev: DRM device
++	 * @crtc: which irq to enable
++	 *
++	 * Disable vblank interrupts for @crtc.  If the device doesn't have
++	 * a hardware vblank counter, this routine should be a no-op, since
++	 * interrupts will have to stay on to keep the count accurate.
++	 */
++	void (*disable_vblank) (struct drm_device *dev, int crtc);
++	int (*dri_library_name) (struct drm_device *dev, char * buf);
+ 
+ 	/**
+ 	 * Called by \c drm_device_is_agp.  Typically used to determine if a
+@@ -602,7 +641,7 @@ struct drm_driver {
+ 
+ 	irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
+ 	void (*irq_preinstall) (struct drm_device *dev);
+-	void (*irq_postinstall) (struct drm_device *dev);
++	int (*irq_postinstall) (struct drm_device *dev);
+ 	void (*irq_uninstall) (struct drm_device *dev);
+ 	void (*reclaim_buffers) (struct drm_device *dev,
+ 				 struct drm_file * file_priv);
+@@ -630,17 +669,19 @@ struct drm_driver {
+ 	struct pci_driver pci_driver;
+ };
+ 
++#define DRM_MINOR_UNASSIGNED 0
++#define DRM_MINOR_LEGACY 1
++
+ /**
+- * DRM head structure. This structure represent a video head on a card
+- * that may contain multiple heads. Embed one per head of these in the
+- * private drm_device structure.
++ * DRM minor structure. This structure represents a drm minor number.
+  */
+-struct drm_head {
+-	int minor;			/**< Minor device number */
++struct drm_minor {
++	int index;			/**< Minor device number */
++	int type;                       /**< Control or render */
++	dev_t device;			/**< Device number for mknod */
++	struct device kdev;		/**< Linux device */
+ 	struct drm_device *dev;
+ 	struct proc_dir_entry *dev_root;  /**< proc directory entry */
+-	dev_t device;			/**< Device number for mknod */
+-	struct class_device *dev_class;
+ };
+ 
+ /**
+@@ -648,7 +689,6 @@ struct drm_head {
+  * may contain multiple heads.
+  */
+ struct drm_device {
+-	struct device dev;		/**< Linux device */
+ 	char *unique;			/**< Unique identifier: e.g., busid */
+ 	int unique_len;			/**< Length of unique field */
+ 	char *devname;			/**< For /proc/interrupts */
+@@ -730,13 +770,21 @@ struct drm_device {
+ 	/** \name VBLANK IRQ support */
+ 	/*@{ */
+ 
+-	wait_queue_head_t vbl_queue;	/**< VBLANK wait queue */
+-	atomic_t vbl_received;
+-	atomic_t vbl_received2;		/**< number of secondary VBLANK interrupts */
++	wait_queue_head_t *vbl_queue;	/**< VBLANK wait queue */
++	atomic_t *_vblank_count;	/**< number of VBLANK interrupts (driver must alloc the right number of counters) */
+ 	spinlock_t vbl_lock;
+-	struct list_head vbl_sigs;		/**< signal list to send on VBLANK */
+-	struct list_head vbl_sigs2;	/**< signals to send on secondary VBLANK */
+-	unsigned int vbl_pending;
++	struct list_head *vbl_sigs;		/**< signal list to send on VBLANK */
++	atomic_t vbl_signal_pending;	/* number of signals pending on all crtcs*/
++	atomic_t *vblank_refcount;	/* number of users of vblank interrupts per crtc */
++	u32 *last_vblank;		/* protected by dev->vbl_lock, used */
++					/* for wraparound handling */
++	u32 *vblank_offset;		/* used to track how many vblanks */
++	int *vblank_enabled;		/* so we don't call enable more than
++					   once per disable */
++	u32 *vblank_premodeset;		/*  were lost during modeset */
++	struct timer_list vblank_disable_timer;
++
++	unsigned long max_vblank_count; /**< size of vblank counter register */
+ 	spinlock_t tasklet_lock;	/**< For drm_locked_tasklet */
+ 	void (*locked_tasklet_func)(struct drm_device *dev);
+ 
+@@ -756,6 +804,7 @@ struct drm_device {
+ #ifdef __alpha__
+ 	struct pci_controller *hose;
+ #endif
++	int num_crtcs;			/**< Number of CRTCs on this device */
+ 	struct drm_sg_mem *sg;	/**< Scatter gather memory */
+ 	void *dev_private;		/**< device private data */
+ 	struct drm_sigdata sigdata;	   /**< For block_all_signals */
+@@ -764,7 +813,7 @@ struct drm_device {
+ 	struct drm_driver *driver;
+ 	drm_local_map_t *agp_buffer_map;
+ 	unsigned int agp_buffer_token;
+-	struct drm_head primary;		/**< primary screen head */
++	struct drm_minor *primary;		/**< render type primary screen head */
+ 
+ 	/** \name Drawable information */
+ 	/*@{ */
+@@ -990,11 +1039,19 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
+ extern void drm_driver_irq_postinstall(struct drm_device *dev);
+ extern void drm_driver_irq_uninstall(struct drm_device *dev);
+ 
+-extern int drm_wait_vblank(struct drm_device *dev, void *data,
+-			   struct drm_file *file_priv);
+-extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
+-extern void drm_vbl_send_signals(struct drm_device *dev);
++extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
++extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp);
++extern int drm_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq);
+ extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
++extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
++extern void drm_update_vblank_count(struct drm_device *dev, int crtc);
++extern void drm_handle_vblank(struct drm_device *dev, int crtc);
++extern int drm_vblank_get(struct drm_device *dev, int crtc);
++extern void drm_vblank_put(struct drm_device *dev, int crtc);
++
++				/* Modesetting support */
++extern int drm_modeset_ctl(struct drm_device *dev, void *data,
++			   struct drm_file *file_priv);
+ 
+ 				/* AGP/GART support (drm_agpsupport.h) */
+ extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+@@ -1031,23 +1088,20 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
+ extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+ 		       struct drm_driver *driver);
+ extern int drm_put_dev(struct drm_device *dev);
+-extern int drm_put_head(struct drm_head *head);
++extern int drm_put_minor(struct drm_minor **minor);
+ extern unsigned int drm_debug;
+-extern unsigned int drm_cards_limit;
+-extern struct drm_head **drm_heads;
++
+ extern struct class *drm_class;
+ extern struct proc_dir_entry *drm_proc_root;
+ 
++extern struct idr drm_minors_idr;
++
+ extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
+ 
+ 				/* Proc support (drm_proc.h) */
+-extern int drm_proc_init(struct drm_device *dev,
+-			 int minor,
+-			 struct proc_dir_entry *root,
+-			 struct proc_dir_entry **dev_root);
+-extern int drm_proc_cleanup(int minor,
+-			    struct proc_dir_entry *root,
+-			    struct proc_dir_entry *dev_root);
++extern int drm_proc_init(struct drm_minor *minor, int minor_id,
++			 struct proc_dir_entry *root);
++extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
+ 
+ 				/* Scatter Gather Support (drm_scatter.h) */
+ extern void drm_sg_cleanup(struct drm_sg_mem * entry);
+@@ -1072,8 +1126,8 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
+ struct drm_sysfs_class;
+ extern struct class *drm_sysfs_create(struct module *owner, char *name);
+ extern void drm_sysfs_destroy(void);
+-extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head);
+-extern void drm_sysfs_device_remove(struct drm_device *dev);
++extern int drm_sysfs_device_add(struct drm_minor *minor);
++extern void drm_sysfs_device_remove(struct drm_minor *minor);
+ 
+ /*
+  * Basic memory manager support (drm_mm.c)
+diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
+index 9468c78..aefa5ac 100644
+--- a/drivers/char/drm/drm_agpsupport.c
++++ b/drivers/char/drm/drm_agpsupport.c
+@@ -122,7 +122,7 @@ EXPORT_SYMBOL(drm_agp_acquire);
+ int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+ 			  struct drm_file *file_priv)
+ {
+-	return drm_agp_acquire((struct drm_device *) file_priv->head->dev);
++	return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
+ }
+ 
+ /**
+diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
+index 0e7af53..fc54140 100644
+--- a/drivers/char/drm/drm_drv.c
++++ b/drivers/char/drm/drm_drv.c
+@@ -313,35 +313,36 @@ static void drm_cleanup(struct drm_device * dev)
+ 	drm_ht_remove(&dev->map_hash);
+ 	drm_ctxbitmap_cleanup(dev);
+ 
+-	drm_put_head(&dev->primary);
++	drm_put_minor(&dev->primary);
+ 	if (drm_put_dev(dev))
+ 		DRM_ERROR("Cannot unload module\n");
+ }
+ 
+-void drm_exit(struct drm_driver *driver)
++int drm_minors_cleanup(int id, void *ptr, void *data)
+ {
+-	int i;
+-	struct drm_device *dev = NULL;
+-	struct drm_head *head;
++	struct drm_minor *minor = ptr;
++	struct drm_device *dev;
++	struct drm_driver *driver = data;
++
++	dev = minor->dev;
++	if (minor->dev->driver != driver)
++		return 0;
++
++	if (minor->type != DRM_MINOR_LEGACY)
++		return 0;
+ 
++	if (dev)
++		pci_dev_put(dev->pdev);
++	drm_cleanup(dev);
++	return 1;
++}
++
++void drm_exit(struct drm_driver *driver)
++{
+ 	DRM_DEBUG("\n");
+ 
+-	for (i = 0; i < drm_cards_limit; i++) {
+-		head = drm_heads[i];
+-		if (!head)
+-			continue;
+-		if (!head->dev)
+-			continue;
+-		if (head->dev->driver != driver)
+-			continue;
+-		dev = head->dev;
+-		if (dev) {
+-			/* release the pci driver */
+-			if (dev->pdev)
+-				pci_dev_put(dev->pdev);
+-			drm_cleanup(dev);
+-		}
+-	}
++	idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver);
++
+ 	DRM_INFO("Module unloaded\n");
+ }
+ 
+@@ -357,13 +358,7 @@ static int __init drm_core_init(void)
+ {
+ 	int ret = -ENOMEM;
+ 
+-	drm_cards_limit =
+-	    (drm_cards_limit <
+-	     DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
+-	drm_heads =
+-	    drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB);
+-	if (!drm_heads)
+-		goto err_p1;
++	idr_init(&drm_minors_idr);
+ 
+ 	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
+ 		goto err_p1;
+@@ -391,7 +386,8 @@ err_p3:
+ 	drm_sysfs_destroy();
+ err_p2:
+ 	unregister_chrdev(DRM_MAJOR, "drm");
+-	drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
++
++	idr_destroy(&drm_minors_idr);
+ err_p1:
+ 	return ret;
+ }
+@@ -403,7 +399,7 @@ static void __exit drm_core_exit(void)
+ 
+ 	unregister_chrdev(DRM_MAJOR, "drm");
+ 
+-	drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
++	idr_destroy(&drm_minors_idr);
+ }
+ 
+ module_init(drm_core_init);
+@@ -452,7 +448,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
+ 	      unsigned int cmd, unsigned long arg)
+ {
+ 	struct drm_file *file_priv = filp->private_data;
+-	struct drm_device *dev = file_priv->head->dev;
++	struct drm_device *dev = file_priv->minor->dev;
+ 	struct drm_ioctl_desc *ioctl;
+ 	drm_ioctl_t *func;
+ 	unsigned int nr = DRM_IOCTL_NR(cmd);
+@@ -465,7 +461,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
+ 
+ 	DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
+ 		  task_pid_nr(current), cmd, nr,
+-		  (long)old_encode_dev(file_priv->head->device),
++		  (long)old_encode_dev(file_priv->minor->device),
+ 		  file_priv->authenticated);
+ 
+ 	if ((nr >= DRM_CORE_IOCTL_COUNT) &&
+diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
+index f09d4b5..68f0da8 100644
+--- a/drivers/char/drm/drm_fops.c
++++ b/drivers/char/drm/drm_fops.c
+@@ -129,16 +129,15 @@ static int drm_setup(struct drm_device * dev)
+ int drm_open(struct inode *inode, struct file *filp)
+ {
+ 	struct drm_device *dev = NULL;
+-	int minor = iminor(inode);
++	int minor_id = iminor(inode);
++	struct drm_minor *minor;
+ 	int retcode = 0;
+ 
+-	if (!((minor >= 0) && (minor < drm_cards_limit)))
++	minor = idr_find(&drm_minors_idr, minor_id);
++	if (!minor)
+ 		return -ENODEV;
+ 
+-	if (!drm_heads[minor])
+-		return -ENODEV;
+-
+-	if (!(dev = drm_heads[minor]->dev))
++	if (!(dev = minor->dev))
+ 		return -ENODEV;
+ 
+ 	retcode = drm_open_helper(inode, filp, dev);
+@@ -168,19 +167,18 @@ EXPORT_SYMBOL(drm_open);
+ int drm_stub_open(struct inode *inode, struct file *filp)
+ {
+ 	struct drm_device *dev = NULL;
+-	int minor = iminor(inode);
++	struct drm_minor *minor;
++	int minor_id = iminor(inode);
+ 	int err = -ENODEV;
+ 	const struct file_operations *old_fops;
+ 
+ 	DRM_DEBUG("\n");
+ 
+-	if (!((minor >= 0) && (minor < drm_cards_limit)))
+-		return -ENODEV;
+-
+-	if (!drm_heads[minor])
++	minor = idr_find(&drm_minors_idr, minor_id);
++	if (!minor)
+ 		return -ENODEV;
+ 
+-	if (!(dev = drm_heads[minor]->dev))
++	if (!(dev = minor->dev))
+ 		return -ENODEV;
+ 
+ 	old_fops = filp->f_op;
+@@ -225,7 +223,7 @@ static int drm_cpu_valid(void)
+ static int drm_open_helper(struct inode *inode, struct file *filp,
+ 			   struct drm_device * dev)
+ {
+-	int minor = iminor(inode);
++	int minor_id = iminor(inode);
+ 	struct drm_file *priv;
+ 	int ret;
+ 
+@@ -234,7 +232,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
+ 	if (!drm_cpu_valid())
+ 		return -EINVAL;
+ 
+-	DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor);
++	DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
+ 
+ 	priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+ 	if (!priv)
+@@ -245,8 +243,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
+ 	priv->filp = filp;
+ 	priv->uid = current->euid;
+ 	priv->pid = task_pid_nr(current);
+-	priv->minor = minor;
+-	priv->head = drm_heads[minor];
++	priv->minor = idr_find(&drm_minors_idr, minor_id);
+ 	priv->ioctl_count = 0;
+ 	/* for compatibility root is always authenticated */
+ 	priv->authenticated = capable(CAP_SYS_ADMIN);
+@@ -297,11 +294,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
+ int drm_fasync(int fd, struct file *filp, int on)
+ {
+ 	struct drm_file *priv = filp->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 	int retcode;
+ 
+ 	DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
+-		  (long)old_encode_dev(priv->head->device));
++		  (long)old_encode_dev(priv->minor->device));
+ 	retcode = fasync_helper(fd, filp, on, &dev->buf_async);
+ 	if (retcode < 0)
+ 		return retcode;
+@@ -324,7 +321,7 @@ EXPORT_SYMBOL(drm_fasync);
+ int drm_release(struct inode *inode, struct file *filp)
+ {
+ 	struct drm_file *file_priv = filp->private_data;
+-	struct drm_device *dev = file_priv->head->dev;
++	struct drm_device *dev = file_priv->minor->dev;
+ 	int retcode = 0;
+ 	unsigned long irqflags;
+ 
+@@ -341,14 +338,14 @@ int drm_release(struct inode *inode, struct file *filp)
+ 
+ 	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+ 		  task_pid_nr(current),
+-		  (long)old_encode_dev(file_priv->head->device),
++		  (long)old_encode_dev(file_priv->minor->device),
+ 		  dev->open_count);
+ 
+ 	if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
+ 		if (drm_i_have_hw_lock(dev, file_priv)) {
+ 			dev->driver->reclaim_buffers_locked(dev, file_priv);
+ 		} else {
+-			unsigned long _end=jiffies + 3*DRM_HZ;
++			unsigned long endtime = jiffies + 3 * DRM_HZ;
+ 			int locked = 0;
+ 
+ 			drm_idlelock_take(&dev->lock);
+@@ -366,7 +363,7 @@ int drm_release(struct inode *inode, struct file *filp)
+ 				if (locked)
+ 					break;
+ 				schedule();
+-			} while (!time_after_eq(jiffies, _end));
++			} while (!time_after_eq(jiffies, endtime));
+ 
+ 			if (!locked) {
+ 				DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
+diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
+index 089c015..286f9d6 100644
+--- a/drivers/char/drm/drm_irq.c
++++ b/drivers/char/drm/drm_irq.c
+@@ -71,6 +71,117 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
+ 	return 0;
+ }
+ 
++static void vblank_disable_fn(unsigned long arg)
++{
++	struct drm_device *dev = (struct drm_device *)arg;
++	unsigned long irqflags;
++	int i;
++
++	for (i = 0; i < dev->num_crtcs; i++) {
++		spin_lock_irqsave(&dev->vbl_lock, irqflags);
++		if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
++		    dev->vblank_enabled[i]) {
++			dev->driver->disable_vblank(dev, i);
++			dev->vblank_enabled[i] = 0;
++		}
++		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
++	}
++}
++
++static void drm_vblank_cleanup(struct drm_device *dev)
++{
++	/* Bail if the driver didn't call drm_vblank_init() */
++	if (dev->num_crtcs == 0)
++		return;
++
++	del_timer(&dev->vblank_disable_timer);
++
++	vblank_disable_fn((unsigned long)dev);
++
++	drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
++		 DRM_MEM_DRIVER);
++	drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
++		 DRM_MEM_DRIVER);
++	drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
++		 dev->num_crtcs, DRM_MEM_DRIVER);
++	drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
++		 dev->num_crtcs, DRM_MEM_DRIVER);
++	drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
++		 dev->num_crtcs, DRM_MEM_DRIVER);
++	drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
++		 DRM_MEM_DRIVER);
++	drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
++		 dev->num_crtcs, DRM_MEM_DRIVER);
++	drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs,
++		 DRM_MEM_DRIVER);
++
++	dev->num_crtcs = 0;
++}
++
++int drm_vblank_init(struct drm_device *dev, int num_crtcs)
++{
++	int i, ret = -ENOMEM;
++
++	setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
++		    (unsigned long)dev);
++	spin_lock_init(&dev->vbl_lock);
++	atomic_set(&dev->vbl_signal_pending, 0);
++	dev->num_crtcs = num_crtcs;
++
++	dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
++				   DRM_MEM_DRIVER);
++	if (!dev->vbl_queue)
++		goto err;
++
++	dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
++				  DRM_MEM_DRIVER);
++	if (!dev->vbl_sigs)
++		goto err;
++
++	dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
++				      DRM_MEM_DRIVER);
++	if (!dev->_vblank_count)
++		goto err;
++
++	dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
++					 DRM_MEM_DRIVER);
++	if (!dev->vblank_refcount)
++		goto err;
++
++	dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
++					 DRM_MEM_DRIVER);
++	if (!dev->vblank_enabled)
++		goto err;
++
++	dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
++	if (!dev->last_vblank)
++		goto err;
++
++	dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32),
++					    DRM_MEM_DRIVER);
++	if (!dev->vblank_premodeset)
++		goto err;
++
++	dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
++	if (!dev->vblank_offset)
++		goto err;
++
++	/* Zero per-crtc vblank stuff */
++	for (i = 0; i < num_crtcs; i++) {
++		init_waitqueue_head(&dev->vbl_queue[i]);
++		INIT_LIST_HEAD(&dev->vbl_sigs[i]);
++		atomic_set(&dev->_vblank_count[i], 0);
++		atomic_set(&dev->vblank_refcount[i], 0);
++	}
++
++	return 0;
++
++err:
++	drm_vblank_cleanup(dev);
++	return ret;
++}
++EXPORT_SYMBOL(drm_vblank_init);
++
+ /**
+  * Install IRQ handler.
+  *
+@@ -109,17 +220,6 @@ static int drm_irq_install(struct drm_device * dev)
+ 
+ 	DRM_DEBUG("irq=%d\n", dev->irq);
+ 
+-	if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
+-		init_waitqueue_head(&dev->vbl_queue);
+-
+-		spin_lock_init(&dev->vbl_lock);
+-
+-		INIT_LIST_HEAD(&dev->vbl_sigs);
+-		INIT_LIST_HEAD(&dev->vbl_sigs2);
+-
+-		dev->vbl_pending = 0;
+-	}
+-
+ 	/* Before installing handler */
+ 	dev->driver->irq_preinstall(dev);
+ 
+@@ -137,9 +237,14 @@ static int drm_irq_install(struct drm_device * dev)
+ 	}
+ 
+ 	/* After installing handler */
+-	dev->driver->irq_postinstall(dev);
++	ret = dev->driver->irq_postinstall(dev);
++	if (ret < 0) {
++		mutex_lock(&dev->struct_mutex);
++		dev->irq_enabled = 0;
++		mutex_unlock(&dev->struct_mutex);
++	}
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ /**
+@@ -170,6 +275,8 @@ int drm_irq_uninstall(struct drm_device * dev)
+ 
+ 	free_irq(dev->irq, dev);
+ 
++	drm_vblank_cleanup(dev);
++
+ 	dev->locked_tasklet_func = NULL;
+ 
+ 	return 0;
+@@ -214,6 +321,148 @@ int drm_control(struct drm_device *dev, void *data,
+ }
+ 
+ /**
++ * drm_vblank_count - retrieve "cooked" vblank counter value
++ * @dev: DRM device
++ * @crtc: which counter to retrieve
++ *
++ * Fetches the "cooked" vblank count value that represents the number of
++ * vblank events since the system was booted, including lost events due to
++ * modesetting activity.
++ */
++u32 drm_vblank_count(struct drm_device *dev, int crtc)
++{
++	return atomic_read(&dev->_vblank_count[crtc]) +
++		dev->vblank_offset[crtc];
++}
++EXPORT_SYMBOL(drm_vblank_count);
++
++/**
++ * drm_update_vblank_count - update the master vblank counter
++ * @dev: DRM device
++ * @crtc: counter to update
++ *
++ * Call back into the driver to update the appropriate vblank counter
++ * (specified by @crtc).  Deal with wraparound, if it occurred, and
++ * update the last read value so we can deal with wraparound on the next
++ * call if necessary.
++ */
++void drm_update_vblank_count(struct drm_device *dev, int crtc)
++{
++	unsigned long irqflags;
++	u32 cur_vblank, diff;
++
++	/*
++	 * Interrupts were disabled prior to this call, so deal with counter
++	 * wrap if needed.
++	 * NOTE!  It's possible we lost a full dev->max_vblank_count events
++	 * here if the register is small or we had vblank interrupts off for
++	 * a long time.
++	 */
++	cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
++	spin_lock_irqsave(&dev->vbl_lock, irqflags);
++	if (cur_vblank < dev->last_vblank[crtc]) {
++		diff = dev->max_vblank_count -
++			dev->last_vblank[crtc];
++		diff += cur_vblank;
++	} else {
++		diff = cur_vblank - dev->last_vblank[crtc];
++	}
++	dev->last_vblank[crtc] = cur_vblank;
++	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
++
++	atomic_add(diff, &dev->_vblank_count[crtc]);
++}
++EXPORT_SYMBOL(drm_update_vblank_count);
++
++/**
++ * drm_vblank_get - get a reference count on vblank events
++ * @dev: DRM device
++ * @crtc: which CRTC to own
++ *
++ * Acquire a reference count on vblank events to avoid having them disabled
++ * while in use.  Note callers will probably want to update the master counter
++ * using drm_update_vblank_count() above before calling this routine so that
++ * wakeups occur on the right vblank event.
++ *
++ * RETURNS
++ * Zero on success, nonzero on failure.
++ */
++int drm_vblank_get(struct drm_device *dev, int crtc)
++{
++	unsigned long irqflags;
++	int ret = 0;
++
++	spin_lock_irqsave(&dev->vbl_lock, irqflags);
++	/* Going from 0->1 means we have to enable interrupts again */
++	if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
++	    !dev->vblank_enabled[crtc]) {
++		ret = dev->driver->enable_vblank(dev, crtc);
++		if (ret)
++			atomic_dec(&dev->vblank_refcount[crtc]);
++		else
++			dev->vblank_enabled[crtc] = 1;
++	}
++	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
++
++	return ret;
++}
++EXPORT_SYMBOL(drm_vblank_get);
++
++/**
++ * drm_vblank_put - give up ownership of vblank events
++ * @dev: DRM device
++ * @crtc: which counter to give up
++ *
++ * Release ownership of a given vblank counter, turning off interrupts
++ * if possible.
++ */
++void drm_vblank_put(struct drm_device *dev, int crtc)
++{
++	/* Last user schedules interrupt disable */
++	if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
++	    mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
++}
++EXPORT_SYMBOL(drm_vblank_put);
++
++/**
++ * drm_modeset_ctl - handle vblank event counter changes across mode switch
++ * @DRM_IOCTL_ARGS: standard ioctl arguments
++ *
++ * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
++ * ioctls around modesetting so that any lost vblank events are accounted for.
++ */
++int drm_modeset_ctl(struct drm_device *dev, void *data,
++		    struct drm_file *file_priv)
++{
++	struct drm_modeset_ctl *modeset = data;
++	int crtc, ret = 0;
++	u32 new;
++
++	crtc = modeset->arg;
++	if (crtc >= dev->num_crtcs) {
++		ret = -EINVAL;
++		goto out;
++	}
++
++	switch (modeset->cmd) {
++	case _DRM_PRE_MODESET:
++		dev->vblank_premodeset[crtc] =
++			dev->driver->get_vblank_counter(dev, crtc);
++		break;
++	case _DRM_POST_MODESET:
++		new = dev->driver->get_vblank_counter(dev, crtc);
++		dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new;
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++out:
++	return ret;
++}
++
++/**
+  * Wait for VBLANK.
+  *
+  * \param inode device inode.
+@@ -232,12 +481,13 @@ int drm_control(struct drm_device *dev, void *data,
+  *
+  * If a signal is not requested, then calls vblank_wait().
+  */
+-int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
++int drm_wait_vblank(struct drm_device *dev, void *data,
++		    struct drm_file *file_priv)
+ {
+ 	union drm_wait_vblank *vblwait = data;
+ 	struct timeval now;
+ 	int ret = 0;
+-	unsigned int flags, seq;
++	unsigned int flags, seq, crtc;
+ 
+ 	if ((!dev->irq) || (!dev->irq_enabled))
+ 		return -EINVAL;
+@@ -251,13 +501,13 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+ 	}
+ 
+ 	flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
++	crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+ 
+-	if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
+-				    DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
++	if (crtc >= dev->num_crtcs)
+ 		return -EINVAL;
+ 
+-	seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
+-			  : &dev->vbl_received);
++	drm_update_vblank_count(dev, crtc);
++	seq = drm_vblank_count(dev, crtc);
+ 
+ 	switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
+ 	case _DRM_VBLANK_RELATIVE:
+@@ -276,8 +526,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+ 
+ 	if (flags & _DRM_VBLANK_SIGNAL) {
+ 		unsigned long irqflags;
+-		struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
+-				      ? &dev->vbl_sigs2 : &dev->vbl_sigs;
++		struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
+ 		struct drm_vbl_sig *vbl_sig;
+ 
+ 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
+@@ -298,22 +547,26 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+ 			}
+ 		}
+ 
+-		if (dev->vbl_pending >= 100) {
++		if (atomic_read(&dev->vbl_signal_pending) >= 100) {
+ 			spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ 			return -EBUSY;
+ 		}
+ 
+-		dev->vbl_pending++;
+-
+ 		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ 
+-		if (!
+-		    (vbl_sig =
+-		     drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
++		vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
++				     DRM_MEM_DRIVER);
++		if (!vbl_sig)
+ 			return -ENOMEM;
++
++		ret = drm_vblank_get(dev, crtc);
++		if (ret) {
++			drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
++				 DRM_MEM_DRIVER);
++			return ret;
+ 		}
+ 
+-		memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
++		atomic_inc(&dev->vbl_signal_pending);
+ 
+ 		vbl_sig->sequence = vblwait->request.sequence;
+ 		vbl_sig->info.si_signo = vblwait->request.signal;
+@@ -327,17 +580,20 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+ 
+ 		vblwait->reply.sequence = seq;
+ 	} else {
+-		if (flags & _DRM_VBLANK_SECONDARY) {
+-			if (dev->driver->vblank_wait2)
+-				ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
+-		} else if (dev->driver->vblank_wait)
+-			ret =
+-			    dev->driver->vblank_wait(dev,
+-						     &vblwait->request.sequence);
+-
++		unsigned long cur_vblank;
++
++		ret = drm_vblank_get(dev, crtc);
++		if (ret)
++			return ret;
++		DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
++			    (((cur_vblank = drm_vblank_count(dev, crtc))
++			      - vblwait->request.sequence) <= (1 << 23)));
++		drm_vblank_put(dev, crtc);
+ 		do_gettimeofday(&now);
++
+ 		vblwait->reply.tval_sec = now.tv_sec;
+ 		vblwait->reply.tval_usec = now.tv_usec;
++		vblwait->reply.sequence = cur_vblank;
+ 	}
+ 
+       done:
+@@ -348,44 +604,57 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+  * Send the VBLANK signals.
+  *
+  * \param dev DRM device.
++ * \param crtc CRTC where the vblank event occurred
+  *
+  * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
+  *
+  * If a signal is not requested, then calls vblank_wait().
+  */
+-void drm_vbl_send_signals(struct drm_device * dev)
++static void drm_vbl_send_signals(struct drm_device * dev, int crtc)
+ {
++	struct drm_vbl_sig *vbl_sig, *tmp;
++	struct list_head *vbl_sigs;
++	unsigned int vbl_seq;
+ 	unsigned long flags;
+-	int i;
+ 
+ 	spin_lock_irqsave(&dev->vbl_lock, flags);
+ 
+-	for (i = 0; i < 2; i++) {
+-		struct drm_vbl_sig *vbl_sig, *tmp;
+-		struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+-		unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
+-						   &dev->vbl_received);
++	vbl_sigs = &dev->vbl_sigs[crtc];
++	vbl_seq = drm_vblank_count(dev, crtc);
+ 
+-		list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
+-			if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+-				vbl_sig->info.si_code = vbl_seq;
+-				send_sig_info(vbl_sig->info.si_signo,
+-					      &vbl_sig->info, vbl_sig->task);
++	list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
++	    if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
++		vbl_sig->info.si_code = vbl_seq;
++		send_sig_info(vbl_sig->info.si_signo,
++			      &vbl_sig->info, vbl_sig->task);
+ 
+-				list_del(&vbl_sig->head);
++		list_del(&vbl_sig->head);
+ 
+-				drm_free(vbl_sig, sizeof(*vbl_sig),
+-					 DRM_MEM_DRIVER);
+-
+-				dev->vbl_pending--;
+-			}
+-		}
++		drm_free(vbl_sig, sizeof(*vbl_sig),
++			 DRM_MEM_DRIVER);
++		atomic_dec(&dev->vbl_signal_pending);
++		drm_vblank_put(dev, crtc);
++	    }
+ 	}
+ 
+ 	spin_unlock_irqrestore(&dev->vbl_lock, flags);
+ }
+ 
+-EXPORT_SYMBOL(drm_vbl_send_signals);
++/**
++ * drm_handle_vblank - handle a vblank event
++ * @dev: DRM device
++ * @crtc: where this event occurred
++ *
++ * Drivers should call this routine in their vblank interrupt handlers to
++ * update the vblank counter and send any signals that may be pending.
++ */
++void drm_handle_vblank(struct drm_device *dev, int crtc)
++{
++	drm_update_vblank_count(dev, crtc);
++	DRM_WAKEUP(&dev->vbl_queue[crtc]);
++	drm_vbl_send_signals(dev, crtc);
++}
++EXPORT_SYMBOL(drm_handle_vblank);
+ 
+ /**
+  * Tasklet wrapper function.
+diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
+index d9b560f..93b1e04 100644
+--- a/drivers/char/drm/drm_proc.c
++++ b/drivers/char/drm/drm_proc.c
+@@ -87,34 +87,35 @@ static struct drm_proc_list {
+  * "/proc/dri/%minor%/", and each entry in proc_list as
+  * "/proc/dri/%minor%/%name%".
+  */
+-int drm_proc_init(struct drm_device * dev, int minor,
+-		  struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
++int drm_proc_init(struct drm_minor *minor, int minor_id,
++		  struct proc_dir_entry *root)
+ {
+ 	struct proc_dir_entry *ent;
+ 	int i, j;
+ 	char name[64];
+ 
+-	sprintf(name, "%d", minor);
+-	*dev_root = proc_mkdir(name, root);
+-	if (!*dev_root) {
++	sprintf(name, "%d", minor_id);
++	minor->dev_root = proc_mkdir(name, root);
++	if (!minor->dev_root) {
+ 		DRM_ERROR("Cannot create /proc/dri/%s\n", name);
+ 		return -1;
+ 	}
+ 
+ 	for (i = 0; i < DRM_PROC_ENTRIES; i++) {
+ 		ent = create_proc_entry(drm_proc_list[i].name,
+-					S_IFREG | S_IRUGO, *dev_root);
++					S_IFREG | S_IRUGO, minor->dev_root);
+ 		if (!ent) {
+ 			DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
+ 				  name, drm_proc_list[i].name);
+ 			for (j = 0; j < i; j++)
+ 				remove_proc_entry(drm_proc_list[i].name,
+-						  *dev_root);
++						  minor->dev_root);
+ 			remove_proc_entry(name, root);
++			minor->dev_root = NULL;
+ 			return -1;
+ 		}
+ 		ent->read_proc = drm_proc_list[i].f;
+-		ent->data = dev;
++		ent->data = minor;
+ 	}
+ 
+ 	return 0;
+@@ -130,18 +131,17 @@ int drm_proc_init(struct drm_device * dev, int minor,
+  *
+  * Remove all proc entries created by proc_init().
+  */
+-int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
+-		     struct proc_dir_entry *dev_root)
++int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
+ {
+ 	int i;
+ 	char name[64];
+ 
+-	if (!root || !dev_root)
++	if (!root || !minor->dev_root)
+ 		return 0;
+ 
+ 	for (i = 0; i < DRM_PROC_ENTRIES; i++)
+-		remove_proc_entry(drm_proc_list[i].name, dev_root);
+-	sprintf(name, "%d", minor);
++		remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
++	sprintf(name, "%d", minor->index);
+ 	remove_proc_entry(name, root);
+ 
+ 	return 0;
+@@ -163,7 +163,8 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
+ static int drm_name_info(char *buf, char **start, off_t offset, int request,
+ 			 int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int len = 0;
+ 
+ 	if (offset > DRM_PROC_LIMIT) {
+@@ -205,7 +206,8 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
+ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
+ 			int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int len = 0;
+ 	struct drm_map *map;
+ 	struct drm_map_list *r_list;
+@@ -261,7 +263,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
+ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
+ 		       int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int ret;
+ 
+ 	mutex_lock(&dev->struct_mutex);
+@@ -284,7 +287,8 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
+ static int drm__queues_info(char *buf, char **start, off_t offset,
+ 			    int request, int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int len = 0;
+ 	int i;
+ 	struct drm_queue *q;
+@@ -334,7 +338,8 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
+ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
+ 			   int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int ret;
+ 
+ 	mutex_lock(&dev->struct_mutex);
+@@ -357,7 +362,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
+ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
+ 			  int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int len = 0;
+ 	struct drm_device_dma *dma = dev->dma;
+ 	int i;
+@@ -406,7 +412,8 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
+ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
+ 			 int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int ret;
+ 
+ 	mutex_lock(&dev->struct_mutex);
+@@ -429,7 +436,8 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
+ static int drm__clients_info(char *buf, char **start, off_t offset,
+ 			     int request, int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int len = 0;
+ 	struct drm_file *priv;
+ 
+@@ -445,7 +453,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
+ 	list_for_each_entry(priv, &dev->filelist, lhead) {
+ 		DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
+ 			       priv->authenticated ? 'y' : 'n',
+-			       priv->minor,
++			       priv->minor->index,
+ 			       priv->pid,
+ 			       priv->uid, priv->magic, priv->ioctl_count);
+ 	}
+@@ -462,7 +470,8 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
+ static int drm_clients_info(char *buf, char **start, off_t offset,
+ 			    int request, int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int ret;
+ 
+ 	mutex_lock(&dev->struct_mutex);
+@@ -476,7 +485,8 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
+ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
+ 			 int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int len = 0;
+ 	struct drm_vma_entry *pt;
+ 	struct vm_area_struct *vma;
+@@ -535,7 +545,8 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
+ static int drm_vma_info(char *buf, char **start, off_t offset, int request,
+ 			int *eof, void *data)
+ {
+-	struct drm_device *dev = (struct drm_device *) data;
++	struct drm_minor *minor = (struct drm_minor *) data;
++	struct drm_device *dev = minor->dev;
+ 	int ret;
+ 
+ 	mutex_lock(&dev->struct_mutex);
+diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
+index d93a217..c2f584f 100644
+--- a/drivers/char/drm/drm_stub.c
++++ b/drivers/char/drm/drm_stub.c
+@@ -36,23 +36,49 @@
+ #include "drmP.h"
+ #include "drm_core.h"
+ 
+-unsigned int drm_cards_limit = 16;	/* Enough for one machine */
+ unsigned int drm_debug = 0;	/* 1 to enable debug output */
+ EXPORT_SYMBOL(drm_debug);
+ 
+ MODULE_AUTHOR(CORE_AUTHOR);
+ MODULE_DESCRIPTION(CORE_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+-MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
+ MODULE_PARM_DESC(debug, "Enable debug output");
+ 
+-module_param_named(cards_limit, drm_cards_limit, int, 0444);
+ module_param_named(debug, drm_debug, int, 0600);
+ 
+-struct drm_head **drm_heads;
++struct idr drm_minors_idr;
++
+ struct class *drm_class;
+ struct proc_dir_entry *drm_proc_root;
+ 
++static int drm_minor_get_id(struct drm_device *dev, int type)
++{
++	int new_id;
++	int ret;
++	int base = 0, limit = 63;
++
++again:
++	if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
++		DRM_ERROR("Out of memory expanding drawable idr\n");
++		return -ENOMEM;
++	}
++	mutex_lock(&dev->struct_mutex);
++	ret = idr_get_new_above(&drm_minors_idr, NULL,
++				base, &new_id);
++	mutex_unlock(&dev->struct_mutex);
++	if (ret == -EAGAIN) {
++		goto again;
++	} else if (ret) {
++		return ret;
++	}
++
++	if (new_id >= limit) {
++		idr_remove(&drm_minors_idr, new_id);
++		return -EINVAL;
++	}
++	return new_id;
++}
++
+ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
+ 			   const struct pci_device_id *ent,
+ 			   struct drm_driver *driver)
+@@ -145,48 +171,60 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
+  * create the proc init entry via proc_init(). This routines assigns
+  * minor numbers to secondary heads of multi-headed cards
+  */
+-static int drm_get_head(struct drm_device * dev, struct drm_head * head)
++static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
+ {
+-	struct drm_head **heads = drm_heads;
++	struct drm_minor *new_minor;
+ 	int ret;
+-	int minor;
++	int minor_id;
+ 
+ 	DRM_DEBUG("\n");
+ 
+-	for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
+-		if (!*heads) {
+-
+-			*head = (struct drm_head) {
+-			.dev = dev,.device =
+-				    MKDEV(DRM_MAJOR, minor),.minor = minor,};
+-
+-			if ((ret =
+-			     drm_proc_init(dev, minor, drm_proc_root,
+-					   &head->dev_root))) {
+-				printk(KERN_ERR
+-				       "DRM: Failed to initialize /proc/dri.\n");
+-				goto err_g1;
+-			}
+-
+-			ret = drm_sysfs_device_add(dev, head);
+-			if (ret) {
+-				printk(KERN_ERR
+-				       "DRM: Error sysfs_device_add.\n");
+-				goto err_g2;
+-			}
+-			*heads = head;
+-
+-			DRM_DEBUG("new minor assigned %d\n", minor);
+-			return 0;
++	minor_id = drm_minor_get_id(dev, type);
++	if (minor_id < 0)
++		return minor_id;
++
++	new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
++	if (!new_minor) {
++		ret = -ENOMEM;
++		goto err_idr;
++	}
++
++	new_minor->type = type;
++	new_minor->device = MKDEV(DRM_MAJOR, minor_id);
++	new_minor->dev = dev;
++	new_minor->index = minor_id;
++
++	idr_replace(&drm_minors_idr, new_minor, minor_id);
++
++	if (type == DRM_MINOR_LEGACY) {
++		ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
++		if (ret) {
++			DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
++			goto err_mem;
+ 		}
++	} else
++		new_minor->dev_root = NULL;
++
++	ret = drm_sysfs_device_add(new_minor);
++	if (ret) {
++		printk(KERN_ERR
++		       "DRM: Error sysfs_device_add.\n");
++		goto err_g2;
+ 	}
+-	DRM_ERROR("out of minors\n");
+-	return -ENOMEM;
+-      err_g2:
+-	drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
+-      err_g1:
+-	*head = (struct drm_head) {
+-	.dev = NULL};
++	*minor = new_minor;
++
++	DRM_DEBUG("new minor assigned %d\n", minor_id);
++	return 0;
++
++
++err_g2:
++	if (new_minor->type == DRM_MINOR_LEGACY)
++		drm_proc_cleanup(new_minor, drm_proc_root);
++err_mem:
++	kfree(new_minor);
++err_idr:
++	idr_remove(&drm_minors_idr, minor_id);
++	*minor = NULL;
+ 	return ret;
+ }
+ 
+@@ -222,12 +260,12 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+ 		printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+ 		goto err_g2;
+ 	}
+-	if ((ret = drm_get_head(dev, &dev->primary)))
++	if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
+ 		goto err_g2;
+ 
+ 	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+ 		 driver->name, driver->major, driver->minor, driver->patchlevel,
+-		 driver->date, dev->primary.minor);
++		 driver->date, dev->primary->index);
+ 
+ 	return 0;
+ 
+@@ -276,18 +314,18 @@ int drm_put_dev(struct drm_device * dev)
+  * last minor released.
+  *
+  */
+-int drm_put_head(struct drm_head * head)
++int drm_put_minor(struct drm_minor **minor_p)
+ {
+-	int minor = head->minor;
+-
+-	DRM_DEBUG("release secondary minor %d\n", minor);
+-
+-	drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
+-	drm_sysfs_device_remove(head->dev);
++	struct drm_minor *minor = *minor_p;
++	DRM_DEBUG("release secondary minor %d\n", minor->index);
+ 
+-	*head = (struct drm_head) {.dev = NULL};
++	if (minor->type == DRM_MINOR_LEGACY)
++		drm_proc_cleanup(minor, drm_proc_root);
++	drm_sysfs_device_remove(minor);
+ 
+-	drm_heads[minor] = NULL;
++	idr_remove(&drm_minors_idr, minor->index);
+ 
++	kfree(minor);
++	*minor_p = NULL;
+ 	return 0;
+ }
+diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
+index 05ed504..7a1d9a7 100644
+--- a/drivers/char/drm/drm_sysfs.c
++++ b/drivers/char/drm/drm_sysfs.c
+@@ -19,7 +19,7 @@
+ #include "drm_core.h"
+ #include "drmP.h"
+ 
+-#define to_drm_device(d) container_of(d, struct drm_device, dev)
++#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
+ 
+ /**
+  * drm_sysfs_suspend - DRM class suspend hook
+@@ -31,7 +31,8 @@
+  */
+ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
+ {
+-	struct drm_device *drm_dev = to_drm_device(dev);
++	struct drm_minor *drm_minor = to_drm_minor(dev);
++	struct drm_device *drm_dev = drm_minor->dev;
+ 
+ 	printk(KERN_ERR "%s\n", __FUNCTION__);
+ 
+@@ -50,7 +51,8 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
+  */
+ static int drm_sysfs_resume(struct device *dev)
+ {
+-	struct drm_device *drm_dev = to_drm_device(dev);
++	struct drm_minor *drm_minor = to_drm_minor(dev);
++	struct drm_device *drm_dev = drm_minor->dev;
+ 
+ 	if (drm_dev->driver->resume)
+ 		return drm_dev->driver->resume(drm_dev);
+@@ -120,10 +122,11 @@ void drm_sysfs_destroy(void)
+ static ssize_t show_dri(struct device *device, struct device_attribute *attr,
+ 			char *buf)
+ {
+-	struct drm_device *dev = to_drm_device(device);
+-	if (dev->driver->dri_library_name)
+-		return dev->driver->dri_library_name(dev, buf);
+-	return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
++	struct drm_minor *drm_minor = to_drm_minor(device);
++	struct drm_device *drm_dev = drm_minor->dev;
++	if (drm_dev->driver->dri_library_name)
++		return drm_dev->driver->dri_library_name(drm_dev, buf);
++	return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name);
+ }
+ 
+ static struct device_attribute device_attrs[] = {
+@@ -152,25 +155,28 @@ static void drm_sysfs_device_release(struct device *dev)
+  * as the parent for the Linux device, and make sure it has a file containing
+  * the driver we're using (for userspace compatibility).
+  */
+-int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
++int drm_sysfs_device_add(struct drm_minor *minor)
+ {
+ 	int err;
+ 	int i, j;
++	char *minor_str;
+ 
+-	dev->dev.parent = &dev->pdev->dev;
+-	dev->dev.class = drm_class;
+-	dev->dev.release = drm_sysfs_device_release;
+-	dev->dev.devt = head->device;
+-	snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor);
++	minor->kdev.parent = &minor->dev->pdev->dev;
++	minor->kdev.class = drm_class;
++	minor->kdev.release = drm_sysfs_device_release;
++	minor->kdev.devt = minor->device;
++	minor_str = "card%d";
+ 
+-	err = device_register(&dev->dev);
++	snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
++
++	err = device_register(&minor->kdev);
+ 	if (err) {
+ 		DRM_ERROR("device add failed: %d\n", err);
+ 		goto err_out;
+ 	}
+ 
+ 	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+-		err = device_create_file(&dev->dev, &device_attrs[i]);
++		err = device_create_file(&minor->kdev, &device_attrs[i]);
+ 		if (err)
+ 			goto err_out_files;
+ 	}
+@@ -180,8 +186,8 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
+ err_out_files:
+ 	if (i > 0)
+ 		for (j = 0; j < i; j++)
+-			device_remove_file(&dev->dev, &device_attrs[i]);
+-	device_unregister(&dev->dev);
++			device_remove_file(&minor->kdev, &device_attrs[i]);
++	device_unregister(&minor->kdev);
+ err_out:
+ 
+ 	return err;
+@@ -194,11 +200,11 @@ err_out:
+  * This call unregisters and cleans up a class device that was created with a
+  * call to drm_sysfs_device_add()
+  */
+-void drm_sysfs_device_remove(struct drm_device *dev)
++void drm_sysfs_device_remove(struct drm_minor *minor)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+-		device_remove_file(&dev->dev, &device_attrs[i]);
+-	device_unregister(&dev->dev);
++		device_remove_file(&minor->kdev, &device_attrs[i]);
++	device_unregister(&minor->kdev);
+ }
+diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
+index 945df72..c234c6f 100644
+--- a/drivers/char/drm/drm_vm.c
++++ b/drivers/char/drm/drm_vm.c
+@@ -90,7 +90,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
+ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ 	struct drm_file *priv = vma->vm_file->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 	struct drm_map *map = NULL;
+ 	struct drm_map_list *r_list;
+ 	struct drm_hash_item *hash;
+@@ -207,7 +207,7 @@ static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ static void drm_vm_shm_close(struct vm_area_struct *vma)
+ {
+ 	struct drm_file *priv = vma->vm_file->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 	struct drm_vma_entry *pt, *temp;
+ 	struct drm_map *map;
+ 	struct drm_map_list *r_list;
+@@ -286,7 +286,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
+ static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ 	struct drm_file *priv = vma->vm_file->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 	struct drm_device_dma *dma = dev->dma;
+ 	unsigned long offset;
+ 	unsigned long page_nr;
+@@ -321,7 +321,7 @@ static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ 	struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+ 	struct drm_file *priv = vma->vm_file->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 	struct drm_sg_mem *entry = dev->sg;
+ 	unsigned long offset;
+ 	unsigned long map_offset;
+@@ -402,7 +402,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
+ static void drm_vm_open_locked(struct vm_area_struct *vma)
+ {
+ 	struct drm_file *priv = vma->vm_file->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 	struct drm_vma_entry *vma_entry;
+ 
+ 	DRM_DEBUG("0x%08lx,0x%08lx\n",
+@@ -420,7 +420,7 @@ static void drm_vm_open_locked(struct vm_area_struct *vma)
+ static void drm_vm_open(struct vm_area_struct *vma)
+ {
+ 	struct drm_file *priv = vma->vm_file->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 
+ 	mutex_lock(&dev->struct_mutex);
+ 	drm_vm_open_locked(vma);
+@@ -438,7 +438,7 @@ static void drm_vm_open(struct vm_area_struct *vma)
+ static void drm_vm_close(struct vm_area_struct *vma)
+ {
+ 	struct drm_file *priv = vma->vm_file->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 	struct drm_vma_entry *pt, *temp;
+ 
+ 	DRM_DEBUG("0x%08lx,0x%08lx\n",
+@@ -473,7 +473,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
+ 	struct drm_device_dma *dma;
+ 	unsigned long length = vma->vm_end - vma->vm_start;
+ 
+-	dev = priv->head->dev;
++	dev = priv->minor->dev;
+ 	dma = dev->dma;
+ 	DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
+ 		  vma->vm_start, vma->vm_end, vma->vm_pgoff);
+@@ -543,7 +543,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
+ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
+ {
+ 	struct drm_file *priv = filp->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 	struct drm_map *map = NULL;
+ 	unsigned long offset = 0;
+ 	struct drm_hash_item *hash;
+@@ -640,12 +640,12 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
+ 		/* Don't let this area swap.  Change when
+ 		   DRM_KERNEL advisory is supported. */
+ 		vma->vm_flags |= VM_RESERVED;
+-		vma->vm_page_prot = drm_dma_prot(map->type, vma);
+ 		break;
+ 	case _DRM_SCATTER_GATHER:
+ 		vma->vm_ops = &drm_vm_sg_ops;
+ 		vma->vm_private_data = (void *)map;
+ 		vma->vm_flags |= VM_RESERVED;
++		vma->vm_page_prot = drm_dma_prot(map->type, vma);
+ 		break;
+ 	default:
+ 		return -EINVAL;	/* This should never happen. */
+@@ -661,7 +661,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
+ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+ 	struct drm_file *priv = filp->private_data;
+-	struct drm_device *dev = priv->head->dev;
++	struct drm_device *dev = priv->minor->dev;
+ 	int ret;
+ 
+ 	mutex_lock(&dev->struct_mutex);
+diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
+index 8d7ea81..e5de8ea 100644
+--- a/drivers/char/drm/i810_dma.c
++++ b/drivers/char/drm/i810_dma.c
+@@ -94,7 +94,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+ 	drm_i810_buf_priv_t *buf_priv;
+ 
+ 	lock_kernel();
+-	dev = priv->head->dev;
++	dev = priv->minor->dev;
+ 	dev_priv = dev->dev_private;
+ 	buf = dev_priv->mmap_buffer;
+ 	buf_priv = buf->dev_private;
+@@ -122,7 +122,7 @@ static const struct file_operations i810_buffer_fops = {
+ 
+ static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
+ {
+-	struct drm_device *dev = file_priv->head->dev;
++	struct drm_device *dev = file_priv->minor->dev;
+ 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ 	drm_i810_private_t *dev_priv = dev->dev_private;
+ 	const struct file_operations *old_fops;
+diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
+index 9df0810..60c9376 100644
+--- a/drivers/char/drm/i830_dma.c
++++ b/drivers/char/drm/i830_dma.c
+@@ -96,7 +96,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+ 	drm_i830_buf_priv_t *buf_priv;
+ 
+ 	lock_kernel();
+-	dev = priv->head->dev;
++	dev = priv->minor->dev;
+ 	dev_priv = dev->dev_private;
+ 	buf = dev_priv->mmap_buffer;
+ 	buf_priv = buf->dev_private;
+@@ -124,7 +124,7 @@ static const struct file_operations i830_buffer_fops = {
+ 
+ static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
+ {
+-	struct drm_device *dev = file_priv->head->dev;
++	struct drm_device *dev = file_priv->minor->dev;
+ 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+ 	drm_i830_private_t *dev_priv = dev->dev_private;
+ 	const struct file_operations *old_fops;
+diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
+index a043bb1..ef7bf14 100644
+--- a/drivers/char/drm/i915_dma.c
++++ b/drivers/char/drm/i915_dma.c
+@@ -415,10 +415,13 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
+ 	drm_i915_private_t *dev_priv = dev->dev_private;
+ 	RING_LOCALS;
+ 
+-	dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
++	if (++dev_priv->counter > BREADCRUMB_MASK) {
++		 dev_priv->counter = 1;
++		 DRM_DEBUG("Breadcrumb counter wrapped around\n");
++	}
+ 
+-	if (dev_priv->counter > 0x7FFFFFFFUL)
+-		dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
++	if (dev_priv->sarea_priv)
++		dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
+ 
+ 	BEGIN_LP_RING(4);
+ 	OUT_RING(CMD_STORE_DWORD_IDX);
+@@ -428,6 +431,26 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
+ 	ADVANCE_LP_RING();
+ }
+ 
++int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
++{
++	drm_i915_private_t *dev_priv = dev->dev_private;
++	uint32_t flush_cmd = CMD_MI_FLUSH;
++	RING_LOCALS;
++
++	flush_cmd |= flush;
++
++	i915_kernel_lost_context(dev);
++
++	BEGIN_LP_RING(4);
++	OUT_RING(flush_cmd);
++	OUT_RING(0);
++	OUT_RING(0);
++	OUT_RING(0);
++	ADVANCE_LP_RING();
++
++	return 0;
++}
++
+ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
+ 				   drm_i915_cmdbuffer_t * cmd)
+ {
+@@ -511,52 +534,74 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
+ 	return 0;
+ }
+ 
+-static int i915_dispatch_flip(struct drm_device * dev)
++static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
+ {
+ 	drm_i915_private_t *dev_priv = dev->dev_private;
++	u32 num_pages, current_page, next_page, dspbase;
++	int shift = 2 * plane, x, y;
+ 	RING_LOCALS;
+ 
+-	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+-		  __FUNCTION__,
+-		  dev_priv->current_page,
+-		  dev_priv->sarea_priv->pf_current_page);
++	/* Calculate display base offset */
++	num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
++	current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3;
++	next_page = (current_page + 1) % num_pages;
+ 
+-	i915_kernel_lost_context(dev);
+-
+-	BEGIN_LP_RING(2);
+-	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+-	OUT_RING(0);
+-	ADVANCE_LP_RING();
++	switch (next_page) {
++	default:
++	case 0:
++		dspbase = dev_priv->sarea_priv->front_offset;
++		break;
++	case 1:
++		dspbase = dev_priv->sarea_priv->back_offset;
++		break;
++	case 2:
++		dspbase = dev_priv->sarea_priv->third_offset;
++		break;
++	}
+ 
+-	BEGIN_LP_RING(6);
+-	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
+-	OUT_RING(0);
+-	if (dev_priv->current_page == 0) {
+-		OUT_RING(dev_priv->back_offset);
+-		dev_priv->current_page = 1;
++	if (plane == 0) {
++		x = dev_priv->sarea_priv->planeA_x;
++		y = dev_priv->sarea_priv->planeA_y;
+ 	} else {
+-		OUT_RING(dev_priv->front_offset);
+-		dev_priv->current_page = 0;
++		x = dev_priv->sarea_priv->planeB_x;
++		y = dev_priv->sarea_priv->planeB_y;
+ 	}
+-	OUT_RING(0);
+-	ADVANCE_LP_RING();
+ 
+-	BEGIN_LP_RING(2);
+-	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
+-	OUT_RING(0);
+-	ADVANCE_LP_RING();
++	dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp;
+ 
+-	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
++	DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page,
++		  dspbase);
+ 
+ 	BEGIN_LP_RING(4);
+-	OUT_RING(CMD_STORE_DWORD_IDX);
+-	OUT_RING(20);
+-	OUT_RING(dev_priv->counter);
+-	OUT_RING(0);
++	OUT_RING(sync ? 0 :
++		 (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP :
++				       MI_WAIT_FOR_PLANE_A_FLIP)));
++	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) |
++		 (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
++	OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
++	OUT_RING(dspbase);
+ 	ADVANCE_LP_RING();
+ 
+-	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+-	return 0;
++	dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift);
++	dev_priv->sarea_priv->pf_current_page |= next_page << shift;
++}
++
++void i915_dispatch_flip(struct drm_device * dev, int planes, int sync)
++{
++	drm_i915_private_t *dev_priv = dev->dev_private;
++	int i;
++
++	DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n",
++		  planes, dev_priv->sarea_priv->pf_current_page);
++
++	i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
++
++	for (i = 0; i < 2; i++)
++		if (planes & (1 << i))
++			i915_do_dispatch_flip(dev, i, sync);
++
++	i915_emit_breadcrumb(dev);
++
+ }
+ 
+ static int i915_quiescent(struct drm_device * dev)
+@@ -579,7 +624,6 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
+ 			    struct drm_file *file_priv)
+ {
+ 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+-	u32 *hw_status = dev_priv->hw_status_page;
+ 	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+ 	    dev_priv->sarea_priv;
+ 	drm_i915_batchbuffer_t *batch = data;
+@@ -602,7 +646,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
+ 
+ 	ret = i915_dispatch_batchbuffer(dev, batch);
+ 
+-	sarea_priv->last_dispatch = (int)hw_status[5];
++	sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+ 	return ret;
+ }
+ 
+@@ -610,7 +654,6 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
+ 			  struct drm_file *file_priv)
+ {
+ 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+-	u32 *hw_status = dev_priv->hw_status_page;
+ 	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+ 	    dev_priv->sarea_priv;
+ 	drm_i915_cmdbuffer_t *cmdbuf = data;
+@@ -635,18 +678,51 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
+ 		return ret;
+ 	}
+ 
+-	sarea_priv->last_dispatch = (int)hw_status[5];
++	sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
++	return 0;
++}
++
++static int i915_do_cleanup_pageflip(struct drm_device * dev)
++{
++	drm_i915_private_t *dev_priv = dev->dev_private;
++	int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
++
++	DRM_DEBUG("\n");
++
++	for (i = 0, planes = 0; i < 2; i++)
++		if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
++			dev_priv->sarea_priv->pf_current_page =
++				(dev_priv->sarea_priv->pf_current_page &
++				 ~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i));
++
++			planes |= 1 << i;
++		}
++
++	if (planes)
++		i915_dispatch_flip(dev, planes, 0);
++
+ 	return 0;
+ }
+ 
+ static int i915_flip_bufs(struct drm_device *dev, void *data,
+ 			  struct drm_file *file_priv)
+ {
+-	DRM_DEBUG("%s\n", __FUNCTION__);
++	drm_i915_flip_t *param = data;
++
++	DRM_DEBUG("\n");
+ 
+ 	LOCK_TEST_WITH_RETURN(dev, file_priv);
+ 
+-	return i915_dispatch_flip(dev);
++	/* This is really planes */
++	if (param->pipes & ~0x3) {
++		DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n",
++			  param->pipes);
++		return -EINVAL;
++	}
++
++	i915_dispatch_flip(dev, param->pipes, 0);
++
++	return 0;
+ }
+ 
+ static int i915_getparam(struct drm_device *dev, void *data,
+@@ -807,6 +883,8 @@ void i915_driver_lastclose(struct drm_device * dev)
+ 	if (!dev_priv)
+ 		return;
+ 
++	if (drm_getsarea(dev) && dev_priv->sarea_priv)
++		i915_do_cleanup_pageflip(dev);
+ 	if (dev_priv->agp_heap)
+ 		i915_mem_takedown(&(dev_priv->agp_heap));
+ 
+diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
+index 05c66cf..0431c00 100644
+--- a/drivers/char/drm/i915_drm.h
++++ b/drivers/char/drm/i915_drm.h
+@@ -105,14 +105,29 @@ typedef struct _drm_i915_sarea {
+ 	unsigned int rotated_tiled;
+ 	unsigned int rotated2_tiled;
+ 
+-	int pipeA_x;
+-	int pipeA_y;
+-	int pipeA_w;
+-	int pipeA_h;
+-	int pipeB_x;
+-	int pipeB_y;
+-	int pipeB_w;
+-	int pipeB_h;
++	int planeA_x;
++	int planeA_y;
++	int planeA_w;
++	int planeA_h;
++	int planeB_x;
++	int planeB_y;
++	int planeB_w;
++	int planeB_h;
++
++	/* Triple buffering */
++	drm_handle_t third_handle;
++	int third_offset;
++	int third_size;
++	unsigned int third_tiled;
++
++	/* buffer object handles for the static buffers.  May change
++	 * over the lifetime of the client, though it doesn't in our current
++	 * implementation.
++	 */
++	unsigned int front_bo_handle;
++	unsigned int back_bo_handle;
++	unsigned int third_bo_handle;
++	unsigned int depth_bo_handle;
+ } drm_i915_sarea_t;
+ 
+ /* Flags for perf_boxes
+@@ -146,7 +161,7 @@ typedef struct _drm_i915_sarea {
+ 
+ #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
+ #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
+-#define DRM_IOCTL_I915_FLIP		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
++#define DRM_IOCTL_I915_FLIP		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FLIP, drm_i915_flip_t)
+ #define DRM_IOCTL_I915_BATCHBUFFER	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
+ #define DRM_IOCTL_I915_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
+ #define DRM_IOCTL_I915_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
+@@ -161,6 +176,18 @@ typedef struct _drm_i915_sarea {
+ #define DRM_IOCTL_I915_GET_VBLANK_PIPE	DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
+ #define DRM_IOCTL_I915_VBLANK_SWAP	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
+ 
++/* Asynchronous page flipping:
++ */
++typedef struct drm_i915_flip {
++	/*
++	 * This is really talking about planes, and we could rename it
++	 * except for the fact that some of the duplicated i915_drm.h files
++	 * out there check for HAVE_I915_FLIP and so might pick up this
++	 * version.
++	 */
++	int pipes;
++} drm_i915_flip_t;
++
+ /* Allow drivers to submit batchbuffers directly to hardware, relying
+  * on the security mechanisms provided by hardware.
+  */
+diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
+index b2b451d..bb8f1b2 100644
+--- a/drivers/char/drm/i915_drv.c
++++ b/drivers/char/drm/i915_drv.c
+@@ -533,8 +533,7 @@ static struct drm_driver driver = {
+ 	 */
+ 	.driver_features =
+ 	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
+-	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
+-	    DRIVER_IRQ_VBL2,
++	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ 	.load = i915_driver_load,
+ 	.unload = i915_driver_unload,
+ 	.lastclose = i915_driver_lastclose,
+@@ -542,8 +541,9 @@ static struct drm_driver driver = {
+ 	.suspend = i915_suspend,
+ 	.resume = i915_resume,
+ 	.device_is_agp = i915_driver_device_is_agp,
+-	.vblank_wait = i915_driver_vblank_wait,
+-	.vblank_wait2 = i915_driver_vblank_wait2,
++	.get_vblank_counter = i915_get_vblank_counter,
++	.enable_vblank = i915_enable_vblank,
++	.disable_vblank = i915_disable_vblank,
+ 	.irq_preinstall = i915_driver_irq_preinstall,
+ 	.irq_postinstall = i915_driver_irq_postinstall,
+ 	.irq_uninstall = i915_driver_irq_uninstall,
+diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
+index 675d88b..c614d78 100644
+--- a/drivers/char/drm/i915_drv.h
++++ b/drivers/char/drm/i915_drv.h
+@@ -76,8 +76,9 @@ struct mem_block {
+ typedef struct _drm_i915_vbl_swap {
+ 	struct list_head head;
+ 	drm_drawable_t drw_id;
+-	unsigned int pipe;
++	unsigned int plane;
+ 	unsigned int sequence;
++	int flip;
+ } drm_i915_vbl_swap_t;
+ 
+ typedef struct drm_i915_private {
+@@ -90,7 +91,7 @@ typedef struct drm_i915_private {
+ 	drm_dma_handle_t *status_page_dmah;
+ 	void *hw_status_page;
+ 	dma_addr_t dma_status_page;
+-	unsigned long counter;
++	uint32_t counter;
+ 	unsigned int status_gfx_addr;
+ 	drm_local_map_t hws_map;
+ 
+@@ -103,13 +104,18 @@ typedef struct drm_i915_private {
+ 
+ 	wait_queue_head_t irq_queue;
+ 	atomic_t irq_received;
+-	atomic_t irq_emitted;
++	atomic_t irq_emited;
+ 
+ 	int tex_lru_log_granularity;
+ 	int allow_batchbuffer;
+ 	struct mem_block *agp_heap;
+ 	unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
+ 	int vblank_pipe;
++	spinlock_t user_irq_lock;
++	int user_irq_refcount;
++	int fence_irq_on;
++	uint32_t irq_enable_reg;
++	int irq_enabled;
+ 
+ 	spinlock_t swaps_lock;
+ 	drm_i915_vbl_swap_t vbl_swaps;
+@@ -216,7 +222,7 @@ extern void i915_driver_preclose(struct drm_device *dev,
+ extern int i915_driver_device_is_agp(struct drm_device * dev);
+ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+ 			      unsigned long arg);
+-
++extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync);
+ /* i915_irq.c */
+ extern int i915_irq_emit(struct drm_device *dev, void *data,
+ 			 struct drm_file *file_priv);
+@@ -227,7 +233,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc
+ extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
+ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void i915_driver_irq_preinstall(struct drm_device * dev);
+-extern void i915_driver_irq_postinstall(struct drm_device * dev);
++extern int i915_driver_irq_postinstall(struct drm_device * dev);
+ extern void i915_driver_irq_uninstall(struct drm_device * dev);
+ extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
+ 				struct drm_file *file_priv);
+@@ -235,6 +241,9 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
+ 				struct drm_file *file_priv);
+ extern int i915_vblank_swap(struct drm_device *dev, void *data,
+ 			    struct drm_file *file_priv);
++extern int i915_enable_vblank(struct drm_device *dev, int crtc);
++extern void i915_disable_vblank(struct drm_device *dev, int crtc);
++extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
+ 
+ /* i915_mem.c */
+ extern int i915_mem_alloc(struct drm_device *dev, void *data,
+@@ -379,21 +388,91 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
+ 
+ /* Interrupt bits:
+  */
+-#define USER_INT_FLAG    (1<<1)
+-#define VSYNC_PIPEB_FLAG (1<<5)
+-#define VSYNC_PIPEA_FLAG (1<<7)
+-#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
++#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT		(1<<18)
++#define I915_DISPLAY_PORT_INTERRUPT			(1<<17)
++#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT	(1<<15)
++#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT	(1<<14)
++#define I915_HWB_OOM_INTERRUPT				(1<<13) /* binner out of memory */
++#define I915_SYNC_STATUS_INTERRUPT			(1<<12)
++#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT	(1<<11)
++#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT	(1<<10)
++#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT	(1<<9)
++#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT	(1<<8)
++#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT		(1<<7)
++#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT		(1<<6)
++#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT		(1<<5)
++#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT		(1<<4)
++#define I915_DEBUG_INTERRUPT				(1<<2)
++#define I915_USER_INTERRUPT				(1<<1)
++
+ 
+ #define I915REG_HWSTAM		0x02098
+ #define I915REG_INT_IDENTITY_R	0x020a4
+ #define I915REG_INT_MASK_R	0x020a8
+ #define I915REG_INT_ENABLE_R	0x020a0
++#define I915REG_INSTPM	        0x020c0
++
++#define PIPEADSL		0x70000
++#define PIPEBDSL		0x71000
+ 
+ #define I915REG_PIPEASTAT	0x70024
+ #define I915REG_PIPEBSTAT	0x71024
++/*
++ * The two pipe frame counter registers are not synchronized, so
++ * reading a stable value is somewhat tricky. The following code
++ * should work:
++ *
++ *  do {
++ *    high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
++ *             PIPE_FRAME_HIGH_SHIFT;
++ *    low1 =  ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
++ *             PIPE_FRAME_LOW_SHIFT);
++ *    high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
++ *             PIPE_FRAME_HIGH_SHIFT);
++ *  } while (high1 != high2);
++ *  frame = (high1 << 8) | low1;
++ */
++#define PIPEAFRAMEHIGH          0x70040
++#define PIPEBFRAMEHIGH		0x71040
++#define PIPE_FRAME_HIGH_MASK    0x0000ffff
++#define PIPE_FRAME_HIGH_SHIFT   0
++#define PIPEAFRAMEPIXEL         0x70044
++#define PIPEBFRAMEPIXEL		0x71044
+ 
+-#define I915_VBLANK_INTERRUPT_ENABLE	(1UL<<17)
+-#define I915_VBLANK_CLEAR		(1UL<<1)
++#define PIPE_FRAME_LOW_MASK     0xff000000
++#define PIPE_FRAME_LOW_SHIFT    24
++/*
++ * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
++ * and is 24 bits wide.
++ */
++#define PIPE_PIXEL_MASK         0x00ffffff
++#define PIPE_PIXEL_SHIFT        0
++
++#define I915_FIFO_UNDERRUN_STATUS		(1UL<<31)
++#define I915_CRC_ERROR_ENABLE			(1UL<<29)
++#define I915_CRC_DONE_ENABLE			(1UL<<28)
++#define I915_GMBUS_EVENT_ENABLE			(1UL<<27)
++#define I915_VSYNC_INTERRUPT_ENABLE		(1UL<<25)
++#define I915_DISPLAY_LINE_COMPARE_ENABLE	(1UL<<24)
++#define I915_DPST_EVENT_ENABLE			(1UL<<23)
++#define I915_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)
++#define I915_ODD_FIELD_INTERRUPT_ENABLE		(1UL<<21)
++#define I915_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)
++#define I915_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18)	/* 965 or later */
++#define I915_VBLANK_INTERRUPT_ENABLE		(1UL<<17)
++#define I915_OVERLAY_UPDATED_ENABLE		(1UL<<16)
++#define I915_CRC_ERROR_INTERRUPT_STATUS		(1UL<<13)
++#define I915_CRC_DONE_INTERRUPT_STATUS		(1UL<<12)
++#define I915_GMBUS_INTERRUPT_STATUS		(1UL<<11)
++#define I915_VSYNC_INTERRUPT_STATUS		(1UL<<9)
++#define I915_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8)
++#define I915_DPST_EVENT_STATUS			(1UL<<7)
++#define I915_LEGACY_BLC_EVENT_STATUS		(1UL<<6)
++#define I915_ODD_FIELD_INTERRUPT_STATUS		(1UL<<5)
++#define I915_EVEN_FIELD_INTERRUPT_STATUS	(1UL<<4)
++#define I915_START_VBLANK_INTERRUPT_STATUS	(1UL<<2)	/* 965 or later */
++#define I915_VBLANK_INTERRUPT_STATUS		(1UL<<1)
++#define I915_OVERLAY_UPDATED_STATUS		(1UL<<0)
+ 
+ #define SRX_INDEX		0x3c4
+ #define SRX_DATA		0x3c5
+@@ -566,6 +645,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
+ #define XY_SRC_COPY_BLT_CMD		((2<<29)|(0x53<<22)|6)
+ #define XY_SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
+ #define XY_SRC_COPY_BLT_WRITE_RGB	(1<<20)
++#define XY_SRC_COPY_BLT_SRC_TILED	(1<<15)
++#define XY_SRC_COPY_BLT_DST_TILED	(1<<11)
+ 
+ #define MI_BATCH_BUFFER		((0x30<<23)|1)
+ #define MI_BATCH_BUFFER_START	(0x31<<23)
+diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
+index 92653b3..023ce66 100644
+--- a/drivers/char/drm/i915_irq.c
++++ b/drivers/char/drm/i915_irq.c
+@@ -38,6 +38,109 @@
+ #define MAX_NOPID ((u32)~0)
+ 
+ /**
++ * i915_get_pipe - return the the pipe associated with a given plane
++ * @dev: DRM device
++ * @plane: plane to look for
++ *
++ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
++ * rather than a pipe number, since they may not always be equal.  This routine
++ * maps the given @plane back to a pipe number.
++ */
++static int
++i915_get_pipe(struct drm_device *dev, int plane)
++{
++	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++	u32 dspcntr;
++
++	dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
++
++	return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
++}
++
++/**
++ * i915_get_plane - return the the plane associated with a given pipe
++ * @dev: DRM device
++ * @pipe: pipe to look for
++ *
++ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
++ * rather than a plane number, since they may not always be equal.  This routine
++ * maps the given @pipe back to a plane number.
++ */
++static int
++i915_get_plane(struct drm_device *dev, int pipe)
++{
++	if (i915_get_pipe(dev, 0) == pipe)
++		return 0;
++	return 1;
++}
++
++/**
++ * i915_pipe_enabled - check if a pipe is enabled
++ * @dev: DRM device
++ * @pipe: pipe to check
++ *
++ * Reading certain registers when the pipe is disabled can hang the chip.
++ * Use this routine to make sure the PLL is running and the pipe is active
++ * before reading such registers if unsure.
++ */
++static int
++i915_pipe_enabled(struct drm_device *dev, int pipe)
++{
++	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++	unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
++
++	if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
++		return 1;
++
++	return 0;
++}
++
++/**
++ * Emit a synchronous flip.
++ *
++ * This function must be called with the drawable spinlock held.
++ */
++static void
++i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
++			 int plane)
++{
++	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
++	u16 x1, y1, x2, y2;
++	int pf_planes = 1 << plane;
++
++	/* If the window is visible on the other plane, we have to flip on that
++	 * plane as well.
++	 */
++	if (plane == 1) {
++		x1 = sarea_priv->planeA_x;
++		y1 = sarea_priv->planeA_y;
++		x2 = x1 + sarea_priv->planeA_w;
++		y2 = y1 + sarea_priv->planeA_h;
++	} else {
++		x1 = sarea_priv->planeB_x;
++		y1 = sarea_priv->planeB_y;
++		x2 = x1 + sarea_priv->planeB_w;
++		y2 = y1 + sarea_priv->planeB_h;
++	}
++
++	if (x2 > 0 && y2 > 0) {
++		int i, num_rects = drw->num_rects;
++		struct drm_clip_rect *rect = drw->rects;
++
++		for (i = 0; i < num_rects; i++)
++			if (!(rect[i].x1 >= x2 || rect[i].y1 >= y2 ||
++			      rect[i].x2 <= x1 || rect[i].y2 <= y1)) {
++				pf_planes = 0x3;
++
++				break;
++			}
++	}
++
++	i915_dispatch_flip(dev, pf_planes, 1);
++}
++
++/**
+  * Emit blits for scheduled buffer swaps.
+  *
+  * This function will be called with the HW lock held.
+@@ -45,40 +148,59 @@
+ static void i915_vblank_tasklet(struct drm_device *dev)
+ {
+ 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+-	unsigned long irqflags;
+ 	struct list_head *list, *tmp, hits, *hit;
+-	int nhits, nrects, slice[2], upper[2], lower[2], i;
+-	unsigned counter[2] = { atomic_read(&dev->vbl_received),
+-				atomic_read(&dev->vbl_received2) };
++	int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
++	unsigned counter[2];
+ 	struct drm_drawable_info *drw;
+ 	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+-	u32 cpp = dev_priv->cpp;
++	u32 cpp = dev_priv->cpp,  offsets[3];
+ 	u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
+ 				XY_SRC_COPY_BLT_WRITE_ALPHA |
+ 				XY_SRC_COPY_BLT_WRITE_RGB)
+ 			     : XY_SRC_COPY_BLT_CMD;
+-	u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
+-			  (cpp << 23) | (1 << 24);
++	u32 src_pitch = sarea_priv->pitch * cpp;
++	u32 dst_pitch = sarea_priv->pitch * cpp;
++	/* COPY rop (0xcc), map cpp to magic color depth constants */
++	u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
+ 	RING_LOCALS;
+ 
++	if (sarea_priv->front_tiled) {
++		cmd |= XY_SRC_COPY_BLT_DST_TILED;
++		dst_pitch >>= 2;
++	}
++	if (sarea_priv->back_tiled) {
++		cmd |= XY_SRC_COPY_BLT_SRC_TILED;
++		src_pitch >>= 2;
++	}
++
++	counter[0] = drm_vblank_count(dev, 0);
++	counter[1] = drm_vblank_count(dev, 1);
++
+ 	DRM_DEBUG("\n");
+ 
+ 	INIT_LIST_HEAD(&hits);
+ 
+ 	nhits = nrects = 0;
+ 
+-	spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
++	/* No irqsave/restore necessary.  This tasklet may be run in an
++	 * interrupt context or normal context, but we don't have to worry
++	 * about getting interrupted by something acquiring the lock, because
++	 * we are the interrupt context thing that acquires the lock.
++	 */
++	spin_lock(&dev_priv->swaps_lock);
+ 
+ 	/* Find buffer swaps scheduled for this vertical blank */
+ 	list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
+ 		drm_i915_vbl_swap_t *vbl_swap =
+ 			list_entry(list, drm_i915_vbl_swap_t, head);
++		int pipe = i915_get_pipe(dev, vbl_swap->plane);
+ 
+-		if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
++		if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
+ 			continue;
+ 
+ 		list_del(list);
+ 		dev_priv->swaps_pending--;
++		drm_vblank_put(dev, pipe);
+ 
+ 		spin_unlock(&dev_priv->swaps_lock);
+ 		spin_lock(&dev->drw_lock);
+@@ -116,33 +238,23 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ 		spin_lock(&dev_priv->swaps_lock);
+ 	}
+ 
+-	if (nhits == 0) {
+-		spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+-		return;
+-	}
+-
+ 	spin_unlock(&dev_priv->swaps_lock);
+ 
+-	i915_kernel_lost_context(dev);
+-
+-	BEGIN_LP_RING(6);
+-
+-	OUT_RING(GFX_OP_DRAWRECT_INFO);
+-	OUT_RING(0);
+-	OUT_RING(0);
+-	OUT_RING(sarea_priv->width | sarea_priv->height << 16);
+-	OUT_RING(sarea_priv->width | sarea_priv->height << 16);
+-	OUT_RING(0);
+-
+-	ADVANCE_LP_RING();
++	if (nhits == 0)
++		return;
+ 
+-	sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
++	i915_kernel_lost_context(dev);
+ 
+ 	upper[0] = upper[1] = 0;
+-	slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
+-	slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
+-	lower[0] = sarea_priv->pipeA_y + slice[0];
+-	lower[1] = sarea_priv->pipeB_y + slice[0];
++	slice[0] = max(sarea_priv->planeA_h / nhits, 1);
++	slice[1] = max(sarea_priv->planeB_h / nhits, 1);
++	lower[0] = sarea_priv->planeA_y + slice[0];
++	lower[1] = sarea_priv->planeB_y + slice[0];
++
++	offsets[0] = sarea_priv->front_offset;
++	offsets[1] = sarea_priv->back_offset;
++	offsets[2] = sarea_priv->third_offset;
++	num_pages = sarea_priv->third_handle ? 3 : 2;
+ 
+ 	spin_lock(&dev->drw_lock);
+ 
+@@ -154,6 +266,8 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ 	for (i = 0; i++ < nhits;
+ 	     upper[0] = lower[0], lower[0] += slice[0],
+ 	     upper[1] = lower[1], lower[1] += slice[1]) {
++		int init_drawrect = 1;
++
+ 		if (i == nhits)
+ 			lower[0] = lower[1] = sarea_priv->height;
+ 
+@@ -161,7 +275,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ 			drm_i915_vbl_swap_t *swap_hit =
+ 				list_entry(hit, drm_i915_vbl_swap_t, head);
+ 			struct drm_clip_rect *rect;
+-			int num_rects, pipe;
++			int num_rects, plane, front, back;
+ 			unsigned short top, bottom;
+ 
+ 			drw = drm_get_drawable_info(dev, swap_hit->drw_id);
+@@ -169,10 +283,50 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ 			if (!drw)
+ 				continue;
+ 
++			plane = swap_hit->plane;
++
++			if (swap_hit->flip) {
++				i915_dispatch_vsync_flip(dev, drw, plane);
++				continue;
++			}
++
++			if (init_drawrect) {
++				int width  = sarea_priv->width;
++				int height = sarea_priv->height;
++				if (IS_I965G(dev)) {
++					BEGIN_LP_RING(4);
++
++					OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
++					OUT_RING(0);
++					OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
++					OUT_RING(0);
++
++					ADVANCE_LP_RING();
++				} else {
++					BEGIN_LP_RING(6);
++
++					OUT_RING(GFX_OP_DRAWRECT_INFO);
++					OUT_RING(0);
++					OUT_RING(0);
++					OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
++					OUT_RING(0);
++					OUT_RING(0);
++
++					ADVANCE_LP_RING();
++				}
++
++				sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
++
++				init_drawrect = 0;
++			}
++
+ 			rect = drw->rects;
+-			pipe = swap_hit->pipe;
+-			top = upper[pipe];
+-			bottom = lower[pipe];
++			top = upper[plane];
++			bottom = lower[plane];
++
++			front = (dev_priv->sarea_priv->pf_current_page >>
++				 (2 * plane)) & 0x3;
++			back = (front + 1) % num_pages;
+ 
+ 			for (num_rects = drw->num_rects; num_rects--; rect++) {
+ 				int y1 = max(rect->y1, top);
+@@ -184,20 +338,20 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ 				BEGIN_LP_RING(8);
+ 
+ 				OUT_RING(cmd);
+-				OUT_RING(pitchropcpp);
++				OUT_RING(ropcpp | dst_pitch);
+ 				OUT_RING((y1 << 16) | rect->x1);
+ 				OUT_RING((y2 << 16) | rect->x2);
+-				OUT_RING(sarea_priv->front_offset);
++				OUT_RING(offsets[front]);
+ 				OUT_RING((y1 << 16) | rect->x1);
+-				OUT_RING(pitchropcpp & 0xffff);
+-				OUT_RING(sarea_priv->back_offset);
++				OUT_RING(src_pitch);
++				OUT_RING(offsets[back]);
+ 
+ 				ADVANCE_LP_RING();
+ 			}
+ 		}
+ 	}
+ 
+-	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
++	spin_unlock(&dev->drw_lock);
+ 
+ 	list_for_each_safe(hit, tmp, &hits) {
+ 		drm_i915_vbl_swap_t *swap_hit =
+@@ -209,67 +363,112 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ 	}
+ }
+ 
++u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
++{
++	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++	unsigned long high_frame;
++	unsigned long low_frame;
++	u32 high1, high2, low, count;
++	int pipe;
++
++	pipe = i915_get_pipe(dev, plane);
++	high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
++	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
++
++	if (!i915_pipe_enabled(dev, pipe)) {
++	    printk(KERN_ERR "trying to get vblank count for disabled "
++		   "pipe %d\n", pipe);
++	    return 0;
++	}
++
++	/*
++	 * High & low register fields aren't synchronized, so make sure
++	 * we get a low value that's stable across two reads of the high
++	 * register.
++	 */
++	do {
++		high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
++			 PIPE_FRAME_HIGH_SHIFT);
++		low =  ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
++			PIPE_FRAME_LOW_SHIFT);
++		high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
++			 PIPE_FRAME_HIGH_SHIFT);
++	} while (high1 != high2);
++
++	count = (high1 << 8) | low;
++
++	/* count may be reset by other driver(e.g. 2D driver),
++	   we have no way to know if it is wrapped or resetted
++	   when count is zero. do a rough guess.
++	*/
++	if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2)
++		dev->last_vblank[pipe] = 0;
++
++	return count;
++}
++
+ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+ 	struct drm_device *dev = (struct drm_device *) arg;
+ 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+-	u16 temp;
++	u32 iir;
+ 	u32 pipea_stats, pipeb_stats;
+-
+-	pipea_stats = I915_READ(I915REG_PIPEASTAT);
+-	pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+-
+-	temp = I915_READ16(I915REG_INT_IDENTITY_R);
+-
+-	temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
+-
+-	DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
+-
+-	if (temp == 0)
++	int vblank = 0;
++
++	iir = I915_READ(I915REG_INT_IDENTITY_R);
++	if (iir == 0) {
++		DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
++			   iir,
++			   I915_READ(I915REG_INT_MASK_R),
++			   I915_READ(I915REG_INT_ENABLE_R),
++			   I915_READ(I915REG_PIPEASTAT),
++			   I915_READ(I915REG_PIPEBSTAT));
+ 		return IRQ_NONE;
++	}
+ 
+-	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+-	(void) I915_READ16(I915REG_INT_IDENTITY_R);
+-	DRM_READMEMORYBARRIER();
+-
+-	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
++	/*
++	 * Clear the PIPE(A|B)STAT regs before the IIR otherwise
++	 * we may get extra interrupts.
++	 */
++	if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
++		pipea_stats = I915_READ(I915REG_PIPEASTAT);
++		if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
++				   I915_VBLANK_INTERRUPT_STATUS))
++		{
++			vblank++;
++			drm_handle_vblank(dev, i915_get_plane(dev, 0));
++		}
++		I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
++	}
++	if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
++		pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
++		if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
++				   I915_VBLANK_INTERRUPT_STATUS))
++		{
++			vblank++;
++			drm_handle_vblank(dev, i915_get_plane(dev, 1));
++		}
++		I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
++	}
+ 
+-	if (temp & USER_INT_FLAG)
+-		DRM_WAKEUP(&dev_priv->irq_queue);
++	if (dev_priv->sarea_priv)
++	    dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+ 
+-	if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
+-		int vblank_pipe = dev_priv->vblank_pipe;
+-
+-		if ((vblank_pipe &
+-		     (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
+-		    == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
+-			if (temp & VSYNC_PIPEA_FLAG)
+-				atomic_inc(&dev->vbl_received);
+-			if (temp & VSYNC_PIPEB_FLAG)
+-				atomic_inc(&dev->vbl_received2);
+-		} else if (((temp & VSYNC_PIPEA_FLAG) &&
+-			    (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
+-			   ((temp & VSYNC_PIPEB_FLAG) &&
+-			    (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
+-			atomic_inc(&dev->vbl_received);
+-
+-		DRM_WAKEUP(&dev->vbl_queue);
+-		drm_vbl_send_signals(dev);
++	I915_WRITE(I915REG_INT_IDENTITY_R, iir);
++	(void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */
+ 
++	if (iir & I915_USER_INTERRUPT) {
++		DRM_WAKEUP(&dev_priv->irq_queue);
++	}
++	if (vblank) {
+ 		if (dev_priv->swaps_pending > 0)
+ 			drm_locked_tasklet(dev, i915_vblank_tasklet);
+-		I915_WRITE(I915REG_PIPEASTAT,
+-			pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
+-			I915_VBLANK_CLEAR);
+-		I915_WRITE(I915REG_PIPEBSTAT,
+-			pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
+-			I915_VBLANK_CLEAR);
+ 	}
+ 
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int i915_emit_irq(struct drm_device * dev)
++static int i915_emit_irq(struct drm_device *dev)
+ {
+ 	drm_i915_private_t *dev_priv = dev->dev_private;
+ 	RING_LOCALS;
+@@ -316,42 +515,12 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
+ 			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
+ 	}
+ 
+-	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+-	return ret;
+-}
+-
+-static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
+-				      atomic_t *counter)
+-{
+-	drm_i915_private_t *dev_priv = dev->dev_private;
+-	unsigned int cur_vblank;
+-	int ret = 0;
+-
+-	if (!dev_priv) {
+-		DRM_ERROR("called with no initialization\n");
+-		return -EINVAL;
+-	}
+-
+-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+-		    (((cur_vblank = atomic_read(counter))
+-			- *sequence) <= (1<<23)));
+-
+-	*sequence = cur_vblank;
+-
++	if (dev_priv->sarea_priv)
++		dev_priv->sarea_priv->last_dispatch =
++			READ_BREADCRUMB(dev_priv);
+ 	return ret;
+ }
+ 
+-
+-int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
+-{
+-	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
+-}
+-
+-int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
+-{
+-	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
+-}
+-
+ /* Needs the lock as it touches the ring.
+  */
+ int i915_irq_emit(struct drm_device *dev, void *data,
+@@ -394,18 +563,96 @@ int i915_irq_wait(struct drm_device *dev, void *data,
+ 	return i915_wait_irq(dev, irqwait->irq_seq);
+ }
+ 
++int i915_enable_vblank(struct drm_device *dev, int plane)
++{
++	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++	int pipe = i915_get_pipe(dev, plane);
++	u32	pipestat_reg = 0;
++	u32	pipestat;
++
++	switch (pipe) {
++	case 0:
++		pipestat_reg = I915REG_PIPEASTAT;
++		dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
++		break;
++	case 1:
++		pipestat_reg = I915REG_PIPEBSTAT;
++		dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
++		break;
++	default:
++		DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
++			  pipe);
++		break;
++	}
++
++	if (pipestat_reg)
++	{
++		pipestat = I915_READ (pipestat_reg);
++		/*
++		 * Older chips didn't have the start vblank interrupt,
++		 * but
++		 */
++		if (IS_I965G (dev))
++			pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE;
++		else
++			pipestat |= I915_VBLANK_INTERRUPT_ENABLE;
++		/*
++		 * Clear any pending status
++		 */
++		pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
++			     I915_VBLANK_INTERRUPT_STATUS);
++		I915_WRITE(pipestat_reg, pipestat);
++	}
++	I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
++
++	return 0;
++}
++
++void i915_disable_vblank(struct drm_device *dev, int plane)
++{
++	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++	int pipe = i915_get_pipe(dev, plane);
++	u32	pipestat_reg = 0;
++	u32	pipestat;
++
++	switch (pipe) {
++	case 0:
++		pipestat_reg = I915REG_PIPEASTAT;
++		dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
++		break;
++	case 1:
++		pipestat_reg = I915REG_PIPEBSTAT;
++		dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
++		break;
++	default:
++		DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
++			  pipe);
++		break;
++	}
++
++	I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
++	if (pipestat_reg)
++	{
++		pipestat = I915_READ (pipestat_reg);
++		pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE |
++			      I915_VBLANK_INTERRUPT_ENABLE);
++		/*
++		 * Clear any pending status
++		 */
++		pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
++			     I915_VBLANK_INTERRUPT_STATUS);
++		I915_WRITE(pipestat_reg, pipestat);
++	}
++}
++
+ static void i915_enable_interrupt (struct drm_device *dev)
+ {
+ 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+-	u16 flag;
+ 
+-	flag = 0;
+-	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
+-		flag |= VSYNC_PIPEA_FLAG;
+-	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
+-		flag |= VSYNC_PIPEB_FLAG;
++	dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
+ 
+-	I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
++	I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
++	dev_priv->irq_enabled = 1;
+ }
+ 
+ /* Set the vblank monitor pipe
+@@ -428,8 +675,6 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
+ 
+ 	dev_priv->vblank_pipe = pipe->pipe;
+ 
+-	i915_enable_interrupt (dev);
+-
+ 	return 0;
+ }
+ 
+@@ -447,9 +692,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
+ 
+ 	flag = I915_READ(I915REG_INT_ENABLE_R);
+ 	pipe->pipe = 0;
+-	if (flag & VSYNC_PIPEA_FLAG)
++	if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)
+ 		pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
+-	if (flag & VSYNC_PIPEB_FLAG)
++	if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+ 		pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
+ 
+ 	return 0;
+@@ -464,27 +709,30 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+ 	drm_i915_private_t *dev_priv = dev->dev_private;
+ 	drm_i915_vblank_swap_t *swap = data;
+ 	drm_i915_vbl_swap_t *vbl_swap;
+-	unsigned int pipe, seqtype, curseq;
++	unsigned int pipe, seqtype, curseq, plane;
+ 	unsigned long irqflags;
+ 	struct list_head *list;
++	int ret;
+ 
+ 	if (!dev_priv) {
+ 		DRM_ERROR("%s called with no initialization\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+-	if (dev_priv->sarea_priv->rotation) {
++	if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) {
+ 		DRM_DEBUG("Rotation not supported\n");
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
+-			     _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
++			     _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS |
++			     _DRM_VBLANK_FLIP)) {
+ 		DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
+ 		return -EINVAL;
+ 	}
+ 
+-	pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
++	plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
++	pipe = i915_get_pipe(dev, plane);
+ 
+ 	seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
+ 
+@@ -495,6 +743,11 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+ 
+ 	spin_lock_irqsave(&dev->drw_lock, irqflags);
+ 
++	/* It makes no sense to schedule a swap for a drawable that doesn't have
++	 * valid information at this point. E.g. this could mean that the X
++	 * server is too old to push drawable information to the DRM, in which
++	 * case all such swaps would become ineffective.
++	 */
+ 	if (!drm_get_drawable_info(dev, swap->drawable)) {
+ 		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ 		DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
+@@ -503,7 +756,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+ 
+ 	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ 
+-	curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
++	drm_update_vblank_count(dev, pipe);
++	curseq = drm_vblank_count(dev, pipe);
+ 
+ 	if (seqtype == _DRM_VBLANK_RELATIVE)
+ 		swap->sequence += curseq;
+@@ -517,14 +771,43 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+ 		}
+ 	}
+ 
++	if (swap->seqtype & _DRM_VBLANK_FLIP) {
++		swap->sequence--;
++
++		if ((curseq - swap->sequence) <= (1<<23)) {
++			struct drm_drawable_info *drw;
++
++			LOCK_TEST_WITH_RETURN(dev, file_priv);
++
++			spin_lock_irqsave(&dev->drw_lock, irqflags);
++
++			drw = drm_get_drawable_info(dev, swap->drawable);
++
++			if (!drw) {
++				spin_unlock_irqrestore(&dev->drw_lock,
++				    irqflags);
++				DRM_DEBUG("Invalid drawable ID %d\n",
++					  swap->drawable);
++				return -EINVAL;
++			}
++
++			i915_dispatch_vsync_flip(dev, drw, plane);
++
++			spin_unlock_irqrestore(&dev->drw_lock, irqflags);
++
++			return 0;
++		}
++	}
++
+ 	spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+ 
+ 	list_for_each(list, &dev_priv->vbl_swaps.head) {
+ 		vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
+ 
+ 		if (vbl_swap->drw_id == swap->drawable &&
+-		    vbl_swap->pipe == pipe &&
++		    vbl_swap->plane == plane &&
+ 		    vbl_swap->sequence == swap->sequence) {
++			vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
+ 			spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+ 			DRM_DEBUG("Already scheduled\n");
+ 			return 0;
+@@ -547,9 +830,19 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+ 
+ 	DRM_DEBUG("\n");
+ 
++	ret = drm_vblank_get(dev, pipe);
++	if (ret) {
++		drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
++		return ret;
++	}
++
+ 	vbl_swap->drw_id = swap->drawable;
+-	vbl_swap->pipe = pipe;
++	vbl_swap->plane = plane;
+ 	vbl_swap->sequence = swap->sequence;
++	vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
++
++	if (vbl_swap->flip)
++		swap->sequence++;
+ 
+ 	spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+ 
+@@ -567,37 +860,57 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
+ {
+ 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ 
+-	I915_WRITE16(I915REG_HWSTAM, 0xfffe);
++	I915_WRITE16(I915REG_HWSTAM, 0xeffe);
+ 	I915_WRITE16(I915REG_INT_MASK_R, 0x0);
+ 	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+ }
+ 
+-void i915_driver_irq_postinstall(struct drm_device * dev)
++int i915_driver_irq_postinstall(struct drm_device * dev)
+ {
+ 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++	int ret, num_pipes = 2;
+ 
+ 	spin_lock_init(&dev_priv->swaps_lock);
+ 	INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+ 	dev_priv->swaps_pending = 0;
+ 
+-	if (!dev_priv->vblank_pipe)
+-		dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
++	dev_priv->user_irq_refcount = 0;
++	dev_priv->irq_enable_reg = 0;
++
++	ret = drm_vblank_init(dev, num_pipes);
++	if (ret)
++		return ret;
++
++	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
++
+ 	i915_enable_interrupt(dev);
+ 	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
++
++	/*
++	 * Initialize the hardware status page IRQ location.
++	 */
++
++	I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
++	return 0;
+ }
+ 
+ void i915_driver_irq_uninstall(struct drm_device * dev)
+ {
+ 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+-	u16 temp;
++	u32 temp;
+ 
+ 	if (!dev_priv)
+ 		return;
+ 
+-	I915_WRITE16(I915REG_HWSTAM, 0xffff);
+-	I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
+-	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+-
+-	temp = I915_READ16(I915REG_INT_IDENTITY_R);
+-	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
++	dev_priv->irq_enabled = 0;
++	I915_WRITE(I915REG_HWSTAM, 0xffffffff);
++	I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
++	I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
++
++	temp = I915_READ(I915REG_PIPEASTAT);
++	I915_WRITE(I915REG_PIPEASTAT, temp);
++	temp = I915_READ(I915REG_PIPEBSTAT);
++	I915_WRITE(I915REG_PIPEBSTAT, temp);
++	temp = I915_READ(I915REG_INT_IDENTITY_R);
++	I915_WRITE(I915REG_INT_IDENTITY_R, temp);
+ }
+diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
+index 5572939..6b37909 100644
+--- a/drivers/char/drm/mga_drv.c
++++ b/drivers/char/drm/mga_drv.c
+@@ -45,15 +45,16 @@ static struct pci_device_id pciidlist[] = {
+ static struct drm_driver driver = {
+ 	.driver_features =
+ 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
+-	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+-	    DRIVER_IRQ_VBL,
++	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ 	.dev_priv_size = sizeof(drm_mga_buf_priv_t),
+ 	.load = mga_driver_load,
+ 	.unload = mga_driver_unload,
+ 	.lastclose = mga_driver_lastclose,
+ 	.dma_quiescent = mga_driver_dma_quiescent,
+ 	.device_is_agp = mga_driver_device_is_agp,
+-	.vblank_wait = mga_driver_vblank_wait,
++	.get_vblank_counter = mga_get_vblank_counter,
++	.enable_vblank = mga_enable_vblank,
++	.disable_vblank = mga_disable_vblank,
+ 	.irq_preinstall = mga_driver_irq_preinstall,
+ 	.irq_postinstall = mga_driver_irq_postinstall,
+ 	.irq_uninstall = mga_driver_irq_uninstall,
+diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
+index f6ebd24..8f7291f 100644
+--- a/drivers/char/drm/mga_drv.h
++++ b/drivers/char/drm/mga_drv.h
+@@ -120,6 +120,7 @@ typedef struct drm_mga_private {
+ 	u32 clear_cmd;
+ 	u32 maccess;
+ 
++	atomic_t vbl_received;		/**< Number of vblanks received. */
+ 	wait_queue_head_t fence_queue;
+ 	atomic_t last_fence_retired;
+ 	u32 next_fence_to_post;
+@@ -181,11 +182,14 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
+ extern int mga_warp_init(drm_mga_private_t * dev_priv);
+ 
+ 				/* mga_irq.c */
++extern int mga_enable_vblank(struct drm_device *dev, int crtc);
++extern void mga_disable_vblank(struct drm_device *dev, int crtc);
++extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
+ extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
+ extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+ extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void mga_driver_irq_preinstall(struct drm_device * dev);
+-extern void mga_driver_irq_postinstall(struct drm_device * dev);
++extern int mga_driver_irq_postinstall(struct drm_device * dev);
+ extern void mga_driver_irq_uninstall(struct drm_device * dev);
+ extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
+ 			     unsigned long arg);
+diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
+index 9302cb8..06852fb 100644
+--- a/drivers/char/drm/mga_irq.c
++++ b/drivers/char/drm/mga_irq.c
+@@ -35,6 +35,20 @@
+ #include "mga_drm.h"
+ #include "mga_drv.h"
+ 
++u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
++{
++	const drm_mga_private_t *const dev_priv =
++		(drm_mga_private_t *) dev->dev_private;
++
++	if (crtc != 0) {
++		return 0;
++	}
++
++
++	return atomic_read(&dev_priv->vbl_received);
++}
++
++
+ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+ 	struct drm_device *dev = (struct drm_device *) arg;
+@@ -47,9 +61,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+ 	/* VBLANK interrupt */
+ 	if (status & MGA_VLINEPEN) {
+ 		MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
+-		atomic_inc(&dev->vbl_received);
+-		DRM_WAKEUP(&dev->vbl_queue);
+-		drm_vbl_send_signals(dev);
++		atomic_inc(&dev_priv->vbl_received);
++		drm_handle_vblank(dev, 0);
+ 		handled = 1;
+ 	}
+ 
+@@ -78,22 +91,34 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+ 	return IRQ_NONE;
+ }
+ 
+-int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
++int mga_enable_vblank(struct drm_device *dev, int crtc)
+ {
+-	unsigned int cur_vblank;
+-	int ret = 0;
++	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ 
+-	/* Assume that the user has missed the current sequence number
+-	 * by about a day rather than she wants to wait for years
+-	 * using vertical blanks...
+-	 */
+-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+-		    (((cur_vblank = atomic_read(&dev->vbl_received))
+-		      - *sequence) <= (1 << 23)));
++	if (crtc != 0) {
++		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
++			  crtc);
++		return 0;
++	}
+ 
+-	*sequence = cur_vblank;
++	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
++	return 0;
++}
+ 
+-	return ret;
++
++void mga_disable_vblank(struct drm_device *dev, int crtc)
++{
++	if (crtc != 0) {
++		DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
++			  crtc);
++	}
++
++	/* Do *NOT* disable the vertical refresh interrupt.  MGA doesn't have
++	 * a nice hardware counter that tracks the number of refreshes when
++	 * the interrupt is disabled, and the kernel doesn't know the refresh
++	 * rate to calculate an estimate.
++	 */
++	/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
+ }
+ 
+ int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
+@@ -125,14 +150,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
+ 	MGA_WRITE(MGA_ICLEAR, ~0);
+ }
+ 
+-void mga_driver_irq_postinstall(struct drm_device * dev)
++int mga_driver_irq_postinstall(struct drm_device * dev)
+ {
+ 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
++	int ret;
++
++	ret = drm_vblank_init(dev, 1);
++	if (ret)
++		return ret;
+ 
+ 	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
+ 
+-	/* Turn on vertical blank interrupt and soft trap interrupt. */
+-	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
++	/* Turn on soft trap interrupt.  Vertical blank interrupts are enabled
++	 * in mga_enable_vblank.
++	 */
++	MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
++	return 0;
+ }
+ 
+ void mga_driver_irq_uninstall(struct drm_device * dev)
+diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
+index 6108e75..2888aa0 100644
+--- a/drivers/char/drm/r128_drv.c
++++ b/drivers/char/drm/r128_drv.c
+@@ -43,12 +43,13 @@ static struct pci_device_id pciidlist[] = {
+ static struct drm_driver driver = {
+ 	.driver_features =
+ 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
+-	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+-	    DRIVER_IRQ_VBL,
++	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ 	.dev_priv_size = sizeof(drm_r128_buf_priv_t),
+ 	.preclose = r128_driver_preclose,
+ 	.lastclose = r128_driver_lastclose,
+-	.vblank_wait = r128_driver_vblank_wait,
++	.get_vblank_counter = r128_get_vblank_counter,
++	.enable_vblank = r128_enable_vblank,
++	.disable_vblank = r128_disable_vblank,
+ 	.irq_preinstall = r128_driver_irq_preinstall,
+ 	.irq_postinstall = r128_driver_irq_postinstall,
+ 	.irq_uninstall = r128_driver_irq_uninstall,
+diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
+index 011105e..80af9e0 100644
+--- a/drivers/char/drm/r128_drv.h
++++ b/drivers/char/drm/r128_drv.h
+@@ -97,6 +97,8 @@ typedef struct drm_r128_private {
+ 	u32 crtc_offset;
+ 	u32 crtc_offset_cntl;
+ 
++	atomic_t vbl_received;
++
+ 	u32 color_fmt;
+ 	unsigned int front_offset;
+ 	unsigned int front_pitch;
+@@ -149,11 +151,12 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
+ extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
+ extern int r128_do_cleanup_cce(struct drm_device * dev);
+ 
+-extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+-
++extern int r128_enable_vblank(struct drm_device *dev, int crtc);
++extern void r128_disable_vblank(struct drm_device *dev, int crtc);
++extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
+ extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void r128_driver_irq_preinstall(struct drm_device * dev);
+-extern void r128_driver_irq_postinstall(struct drm_device * dev);
++extern int r128_driver_irq_postinstall(struct drm_device * dev);
+ extern void r128_driver_irq_uninstall(struct drm_device * dev);
+ extern void r128_driver_lastclose(struct drm_device * dev);
+ extern void r128_driver_preclose(struct drm_device * dev,
+diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
+index c76fdca..5b95bd8 100644
+--- a/drivers/char/drm/r128_irq.c
++++ b/drivers/char/drm/r128_irq.c
+@@ -35,6 +35,16 @@
+ #include "r128_drm.h"
+ #include "r128_drv.h"
+ 
++u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
++{
++	const drm_r128_private_t *dev_priv = dev->dev_private;
++
++	if (crtc != 0)
++		return 0;
++
++	return atomic_read(&dev_priv->vbl_received);
++}
++
+ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+ 	struct drm_device *dev = (struct drm_device *) arg;
+@@ -46,30 +56,38 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+ 	/* VBLANK interrupt */
+ 	if (status & R128_CRTC_VBLANK_INT) {
+ 		R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+-		atomic_inc(&dev->vbl_received);
+-		DRM_WAKEUP(&dev->vbl_queue);
+-		drm_vbl_send_signals(dev);
++		atomic_inc(&dev_priv->vbl_received);
++		drm_handle_vblank(dev, 0);
+ 		return IRQ_HANDLED;
+ 	}
+ 	return IRQ_NONE;
+ }
+ 
+-int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
++int r128_enable_vblank(struct drm_device *dev, int crtc)
+ {
+-	unsigned int cur_vblank;
+-	int ret = 0;
++	drm_r128_private_t *dev_priv = dev->dev_private;
+ 
+-	/* Assume that the user has missed the current sequence number
+-	 * by about a day rather than she wants to wait for years
+-	 * using vertical blanks...
+-	 */
+-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+-		    (((cur_vblank = atomic_read(&dev->vbl_received))
+-		      - *sequence) <= (1 << 23)));
++	if (crtc != 0) {
++		DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
++		return -EINVAL;
++	}
+ 
+-	*sequence = cur_vblank;
++	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
++	return 0;
++}
++
++void r128_disable_vblank(struct drm_device *dev, int crtc)
++{
++	if (crtc != 0)
++		DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
+ 
+-	return ret;
++	/*
++	 * FIXME: implement proper interrupt disable by using the vblank
++	 * counter register (if available)
++	 *
++	 * R128_WRITE(R128_GEN_INT_CNTL,
++	 *            R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
++	 */
+ }
+ 
+ void r128_driver_irq_preinstall(struct drm_device * dev)
+@@ -82,12 +100,9 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
+ 	R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+ }
+ 
+-void r128_driver_irq_postinstall(struct drm_device * dev)
++int r128_driver_irq_postinstall(struct drm_device * dev)
+ {
+-	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+-
+-	/* Turn on VBL interrupt */
+-	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
++	return drm_vblank_init(dev, 1);
+ }
+ 
+ void r128_driver_irq_uninstall(struct drm_device * dev)
+diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
+index 349ac3d..a261031 100644
+--- a/drivers/char/drm/radeon_drv.c
++++ b/drivers/char/drm/radeon_drv.c
+@@ -59,8 +59,7 @@ static struct pci_device_id pciidlist[] = {
+ static struct drm_driver driver = {
+ 	.driver_features =
+ 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
+-	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
+-	    DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
++	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
+ 	.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
+ 	.load = radeon_driver_load,
+ 	.firstopen = radeon_driver_firstopen,
+@@ -69,8 +68,9 @@ static struct drm_driver driver = {
+ 	.postclose = radeon_driver_postclose,
+ 	.lastclose = radeon_driver_lastclose,
+ 	.unload = radeon_driver_unload,
+-	.vblank_wait = radeon_driver_vblank_wait,
+-	.vblank_wait2 = radeon_driver_vblank_wait2,
++	.get_vblank_counter = radeon_get_vblank_counter,
++	.enable_vblank = radeon_enable_vblank,
++	.disable_vblank = radeon_disable_vblank,
+ 	.dri_library_name = dri_library_name,
+ 	.irq_preinstall = radeon_driver_irq_preinstall,
+ 	.irq_postinstall = radeon_driver_irq_postinstall,
+diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
+index 173ae62..b791420 100644
+--- a/drivers/char/drm/radeon_drv.h
++++ b/drivers/char/drm/radeon_drv.h
+@@ -304,6 +304,9 @@ typedef struct drm_radeon_private {
+ 
+ 	u32 scratch_ages[5];
+ 
++	unsigned int crtc_last_cnt;
++	unsigned int crtc2_last_cnt;
++
+ 	/* starting from here on, data is preserved accross an open */
+ 	uint32_t flags;		/* see radeon_chip_flags */
+ 	unsigned long fb_aper_offset;
+@@ -374,13 +377,13 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *
+ extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
+ 
+ extern void radeon_do_release(struct drm_device * dev);
+-extern int radeon_driver_vblank_wait(struct drm_device * dev,
+-				     unsigned int *sequence);
+-extern int radeon_driver_vblank_wait2(struct drm_device * dev,
+-				      unsigned int *sequence);
++extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
++extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
++extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
++extern void radeon_do_release(struct drm_device * dev);
+ extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void radeon_driver_irq_preinstall(struct drm_device * dev);
+-extern void radeon_driver_irq_postinstall(struct drm_device * dev);
++extern int radeon_driver_irq_postinstall(struct drm_device * dev);
+ extern void radeon_driver_irq_uninstall(struct drm_device * dev);
+ extern int radeon_vblank_crtc_get(struct drm_device *dev);
+ extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
+@@ -558,6 +561,12 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
+ 				? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
+ 				: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+ 
++#define RADEON_CRTC_CRNT_FRAME 0x0214
++#define RADEON_CRTC2_CRNT_FRAME 0x0314
++
++#define RADEON_CRTC_STATUS		0x005c
++#define RADEON_CRTC2_STATUS		0x03fc
++
+ #define RADEON_GEN_INT_CNTL		0x0040
+ #	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
+ #	define RADEON_CRTC2_VBLANK_MASK		(1 << 9)
+diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
+index 009af38..507d6b7 100644
+--- a/drivers/char/drm/radeon_irq.c
++++ b/drivers/char/drm/radeon_irq.c
+@@ -35,12 +35,61 @@
+ #include "radeon_drm.h"
+ #include "radeon_drv.h"
+ 
+-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
+-					      u32 mask)
++static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
+ {
+-	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
++	drm_radeon_private_t *dev_priv = dev->dev_private;
++
++	if (state)
++		dev_priv->irq_enable_reg |= mask;
++	else
++		dev_priv->irq_enable_reg &= ~mask;
++
++	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
++}
++
++int radeon_enable_vblank(struct drm_device *dev, int crtc)
++{
++	switch (crtc) {
++	case 0:
++		radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
++		break;
++	case 1:
++		radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
++		break;
++	default:
++		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
++			  crtc);
++		return EINVAL;
++	}
++
++	return 0;
++}
++
++void radeon_disable_vblank(struct drm_device *dev, int crtc)
++{
++	switch (crtc) {
++	case 0:
++		radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
++		break;
++	case 1:
++		radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
++		break;
++	default:
++		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
++			  crtc);
++		break;
++	}
++}
++
++static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv)
++{
++	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) &
++		(RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
++		 RADEON_CRTC2_VBLANK_STAT);
++
+ 	if (irqs)
+ 		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
++
+ 	return irqs;
+ }
+ 
+@@ -72,39 +121,21 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
+ 	/* Only consider the bits we're interested in - others could be used
+ 	 * outside the DRM
+ 	 */
+-	stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+-						  RADEON_CRTC_VBLANK_STAT |
+-						  RADEON_CRTC2_VBLANK_STAT));
++	stat = radeon_acknowledge_irqs(dev_priv);
+ 	if (!stat)
+ 		return IRQ_NONE;
+ 
+ 	stat &= dev_priv->irq_enable_reg;
+ 
+ 	/* SW interrupt */
+-	if (stat & RADEON_SW_INT_TEST) {
++	if (stat & RADEON_SW_INT_TEST)
+ 		DRM_WAKEUP(&dev_priv->swi_queue);
+-	}
+ 
+ 	/* VBLANK interrupt */
+-	if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
+-		int vblank_crtc = dev_priv->vblank_crtc;
+-
+-		if ((vblank_crtc &
+-		     (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
+-		    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+-			if (stat & RADEON_CRTC_VBLANK_STAT)
+-				atomic_inc(&dev->vbl_received);
+-			if (stat & RADEON_CRTC2_VBLANK_STAT)
+-				atomic_inc(&dev->vbl_received2);
+-		} else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
+-			   (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
+-			   ((stat & RADEON_CRTC2_VBLANK_STAT) &&
+-			    (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
+-			atomic_inc(&dev->vbl_received);
+-
+-		DRM_WAKEUP(&dev->vbl_queue);
+-		drm_vbl_send_signals(dev);
+-	}
++	if (stat & RADEON_CRTC_VBLANK_STAT)
++		drm_handle_vblank(dev, 0);
++	if (stat & RADEON_CRTC2_VBLANK_STAT)
++		drm_handle_vblank(dev, 1);
+ 
+ 	return IRQ_HANDLED;
+ }
+@@ -144,54 +175,27 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
+ 	return ret;
+ }
+ 
+-static int radeon_driver_vblank_do_wait(struct drm_device * dev,
+-					unsigned int *sequence, int crtc)
++u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
+ {
+-	drm_radeon_private_t *dev_priv =
+-	    (drm_radeon_private_t *) dev->dev_private;
+-	unsigned int cur_vblank;
+-	int ret = 0;
+-	int ack = 0;
+-	atomic_t *counter;
++	drm_radeon_private_t *dev_priv = dev->dev_private;
++	u32 crtc_cnt_reg, crtc_status_reg;
++
+ 	if (!dev_priv) {
+ 		DRM_ERROR("called with no initialization\n");
+ 		return -EINVAL;
+ 	}
+ 
+-	if (crtc == DRM_RADEON_VBLANK_CRTC1) {
+-		counter = &dev->vbl_received;
+-		ack |= RADEON_CRTC_VBLANK_STAT;
+-	} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
+-		counter = &dev->vbl_received2;
+-		ack |= RADEON_CRTC2_VBLANK_STAT;
+-	} else
++	if (crtc == 0) {
++		crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME;
++		crtc_status_reg = RADEON_CRTC_STATUS;
++	} else if (crtc == 1) {
++		crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME;
++		crtc_status_reg = RADEON_CRTC2_STATUS;
++	} else {
+ 		return -EINVAL;
++	}
+ 
+-	radeon_acknowledge_irqs(dev_priv, ack);
+-
+-	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+-
+-	/* Assume that the user has missed the current sequence number
+-	 * by about a day rather than she wants to wait for years
+-	 * using vertical blanks...
+-	 */
+-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+-		    (((cur_vblank = atomic_read(counter))
+-		      - *sequence) <= (1 << 23)));
+-
+-	*sequence = cur_vblank;
+-
+-	return ret;
+-}
+-
+-int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
+-{
+-	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
+-}
+-
+-int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
+-{
+-	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
++	return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1);
+ }
+ 
+ /* Needs the lock as it touches the ring.
+@@ -234,21 +238,6 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
+ 	return radeon_wait_irq(dev, irqwait->irq_seq);
+ }
+ 
+-static void radeon_enable_interrupt(struct drm_device *dev)
+-{
+-	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+-
+-	dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
+-	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
+-		dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
+-
+-	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
+-		dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
+-
+-	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+-	dev_priv->irq_enabled = 1;
+-}
+-
+ /* drm_dma.h hooks
+ */
+ void radeon_driver_irq_preinstall(struct drm_device * dev)
+@@ -260,20 +249,27 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
+ 	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+ 
+ 	/* Clear bits if they're already high */
+-	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+-					   RADEON_CRTC_VBLANK_STAT |
+-					   RADEON_CRTC2_VBLANK_STAT));
++	radeon_acknowledge_irqs(dev_priv);
+ }
+ 
+-void radeon_driver_irq_postinstall(struct drm_device * dev)
++int radeon_driver_irq_postinstall(struct drm_device * dev)
+ {
+ 	drm_radeon_private_t *dev_priv =
+ 	    (drm_radeon_private_t *) dev->dev_private;
++	int ret;
+ 
+ 	atomic_set(&dev_priv->swi_emitted, 0);
+ 	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
+ 
+-	radeon_enable_interrupt(dev);
++	ret = drm_vblank_init(dev, 2);
++	if (ret)
++		return ret;
++
++	dev->max_vblank_count = 0x001fffff;
++
++	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
++
++	return 0;
+ }
+ 
+ void radeon_driver_irq_uninstall(struct drm_device * dev)
+@@ -315,6 +311,5 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
+ 		return -EINVAL;
+ 	}
+ 	dev_priv->vblank_crtc = (unsigned int)value;
+-	radeon_enable_interrupt(dev);
+ 	return 0;
+ }
+diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
+index 80c01cd..37870a4 100644
+--- a/drivers/char/drm/via_drv.c
++++ b/drivers/char/drm/via_drv.c
+@@ -40,11 +40,13 @@ static struct pci_device_id pciidlist[] = {
+ static struct drm_driver driver = {
+ 	.driver_features =
+ 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
+-	    DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
++	    DRIVER_IRQ_SHARED,
+ 	.load = via_driver_load,
+ 	.unload = via_driver_unload,
+ 	.context_dtor = via_final_context,
+-	.vblank_wait = via_driver_vblank_wait,
++	.get_vblank_counter = via_get_vblank_counter,
++	.enable_vblank = via_enable_vblank,
++	.disable_vblank = via_disable_vblank,
+ 	.irq_preinstall = via_driver_irq_preinstall,
+ 	.irq_postinstall = via_driver_irq_postinstall,
+ 	.irq_uninstall = via_driver_irq_uninstall,
+diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
+index 2daae81..fe67030 100644
+--- a/drivers/char/drm/via_drv.h
++++ b/drivers/char/drm/via_drv.h
+@@ -75,6 +75,7 @@ typedef struct drm_via_private {
+ 	struct timeval last_vblank;
+ 	int last_vblank_valid;
+ 	unsigned usec_per_vblank;
++	atomic_t vbl_received;
+ 	drm_via_state_t hc_state;
+ 	char pci_buf[VIA_PCI_BUF_SIZE];
+ 	const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
+@@ -130,11 +131,13 @@ extern int via_init_context(struct drm_device * dev, int context);
+ extern int via_final_context(struct drm_device * dev, int context);
+ 
+ extern int via_do_cleanup_map(struct drm_device * dev);
+-extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
++extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
++extern int via_enable_vblank(struct drm_device *dev, int crtc);
++extern void via_disable_vblank(struct drm_device *dev, int crtc);
+ 
+ extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void via_driver_irq_preinstall(struct drm_device * dev);
+-extern void via_driver_irq_postinstall(struct drm_device * dev);
++extern int via_driver_irq_postinstall(struct drm_device * dev);
+ extern void via_driver_irq_uninstall(struct drm_device * dev);
+ 
+ extern int via_dma_cleanup(struct drm_device * dev);
+diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
+index c6bb978..f1ab6fc 100644
+--- a/drivers/char/drm/via_irq.c
++++ b/drivers/char/drm/via_irq.c
+@@ -92,8 +92,17 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
+ static unsigned time_diff(struct timeval *now, struct timeval *then)
+ {
+ 	return (now->tv_usec >= then->tv_usec) ?
+-	    now->tv_usec - then->tv_usec :
+-	    1000000 - (then->tv_usec - now->tv_usec);
++		now->tv_usec - then->tv_usec :
++		1000000 - (then->tv_usec - now->tv_usec);
++}
++
++u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
++{
++	drm_via_private_t *dev_priv = dev->dev_private;
++	if (crtc != 0)
++		return 0;
++
++	return atomic_read(&dev_priv->vbl_received);
+ }
+ 
+ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+@@ -108,8 +117,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+ 
+ 	status = VIA_READ(VIA_REG_INTERRUPT);
+ 	if (status & VIA_IRQ_VBLANK_PENDING) {
+-		atomic_inc(&dev->vbl_received);
+-		if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
++		atomic_inc(&dev_priv->vbl_received);
++		if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
+ 			do_gettimeofday(&cur_vblank);
+ 			if (dev_priv->last_vblank_valid) {
+ 				dev_priv->usec_per_vblank =
+@@ -119,12 +128,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+ 			dev_priv->last_vblank = cur_vblank;
+ 			dev_priv->last_vblank_valid = 1;
+ 		}
+-		if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
++		if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
+ 			DRM_DEBUG("US per vblank is: %u\n",
+ 				  dev_priv->usec_per_vblank);
+ 		}
+-		DRM_WAKEUP(&dev->vbl_queue);
+-		drm_vbl_send_signals(dev);
++		drm_handle_vblank(dev, 0);
+ 		handled = 1;
+ 	}
+ 
+@@ -163,31 +171,34 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
+ 	}
+ }
+ 
+-int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
++int via_enable_vblank(struct drm_device *dev, int crtc)
+ {
+-	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+-	unsigned int cur_vblank;
+-	int ret = 0;
++	drm_via_private_t *dev_priv = dev->dev_private;
++	u32 status;
+ 
+-	DRM_DEBUG("\n");
+-	if (!dev_priv) {
+-		DRM_ERROR("called with no initialization\n");
++	if (crtc != 0) {
++		DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
+ 		return -EINVAL;
+ 	}
+ 
+-	viadrv_acknowledge_irqs(dev_priv);
++	status = VIA_READ(VIA_REG_INTERRUPT);
++	VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
+ 
+-	/* Assume that the user has missed the current sequence number
+-	 * by about a day rather than she wants to wait for years
+-	 * using vertical blanks...
+-	 */
++	VIA_WRITE8(0x83d4, 0x11);
++	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+ 
+-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+-		    (((cur_vblank = atomic_read(&dev->vbl_received)) -
+-		      *sequence) <= (1 << 23)));
++	return 0;
++}
+ 
+-	*sequence = cur_vblank;
+-	return ret;
++void via_disable_vblank(struct drm_device *dev, int crtc)
++{
++	drm_via_private_t *dev_priv = dev->dev_private;
++
++	VIA_WRITE8(0x83d4, 0x11);
++	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
++
++	if (crtc != 0)
++		DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
+ }
+ 
+ static int
+@@ -292,23 +303,25 @@ void via_driver_irq_preinstall(struct drm_device * dev)
+ 	}
+ }
+ 
+-void via_driver_irq_postinstall(struct drm_device * dev)
++int via_driver_irq_postinstall(struct drm_device * dev)
+ {
+ 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ 	u32 status;
+ 
+-	DRM_DEBUG("\n");
+-	if (dev_priv) {
+-		status = VIA_READ(VIA_REG_INTERRUPT);
+-		VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+-			  | dev_priv->irq_enable_mask);
++	DRM_DEBUG("via_driver_irq_postinstall\n");
++	if (!dev_priv)
++		return -EINVAL;
+ 
+-		/* Some magic, oh for some data sheets ! */
++	drm_vblank_init(dev, 1);
++	status = VIA_READ(VIA_REG_INTERRUPT);
++	VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
++		  | dev_priv->irq_enable_mask);
+ 
+-		VIA_WRITE8(0x83d4, 0x11);
+-		VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
++	/* Some magic, oh for some data sheets ! */
++	VIA_WRITE8(0x83d4, 0x11);
++	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+ 
+-	}
++	return 0;
+ }
+ 
+ void via_driver_irq_uninstall(struct drm_device * dev)
+diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
+index 8facf3e..7ed7da1 100644
+--- a/drivers/char/generic_serial.c
++++ b/drivers/char/generic_serial.c
+@@ -28,7 +28,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/tty_flip.h>
+ #include <linux/delay.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #define DEBUG 
+diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c
+index e74bb94..91cdb35 100644
+--- a/drivers/char/hvc_beat.c
++++ b/drivers/char/hvc_beat.c
+@@ -78,8 +78,8 @@ static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt)
+ 	for (rest = cnt; rest > 0; rest -= nlen) {
+ 		nlen = (rest > 16) ? 16 : rest;
+ 		memcpy(kb, buf, nlen);
+-		beat_put_term_char(vtermno, rest, kb[0], kb[1]);
+-		rest -= nlen;
++		beat_put_term_char(vtermno, nlen, kb[0], kb[1]);
++		buf += nlen;
+ 	}
+ 	return cnt;
+ }
+diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
+index 84cdf90..662d60e 100644
+--- a/drivers/char/hw_random/core.c
++++ b/drivers/char/hw_random/core.c
+@@ -116,6 +116,10 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
+ 		err = -EAGAIN;
+ 		if (!bytes_read && (filp->f_flags & O_NONBLOCK))
+ 			goto out;
++		if (bytes_read < 0) {
++			err = bytes_read;
++			goto out;
++		}
+ 
+ 		err = -EFAULT;
+ 		while (bytes_read && size) {
+@@ -234,11 +238,11 @@ static DEVICE_ATTR(rng_available, S_IRUGO,
+ 		   NULL);
+ 
+ 
+-static void unregister_miscdev(bool suspended)
++static void unregister_miscdev(void)
+ {
+ 	device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
+ 	device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
+-	__misc_deregister(&rng_miscdev, suspended);
++	misc_deregister(&rng_miscdev);
+ }
+ 
+ static int register_miscdev(void)
+@@ -313,7 +317,7 @@ out:
+ }
+ EXPORT_SYMBOL_GPL(hwrng_register);
+ 
+-void __hwrng_unregister(struct hwrng *rng, bool suspended)
++void hwrng_unregister(struct hwrng *rng)
+ {
+ 	int err;
+ 
+@@ -332,11 +336,11 @@ void __hwrng_unregister(struct hwrng *rng, bool suspended)
+ 		}
+ 	}
+ 	if (list_empty(&rng_list))
+-		unregister_miscdev(suspended);
++		unregister_miscdev();
+ 
+ 	mutex_unlock(&rng_mutex);
+ }
+-EXPORT_SYMBOL_GPL(__hwrng_unregister);
++EXPORT_SYMBOL_GPL(hwrng_unregister);
+ 
+ 
+ MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
+diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
+index 7e31995..51738bd 100644
+--- a/drivers/char/hw_random/omap-rng.c
++++ b/drivers/char/hw_random/omap-rng.c
+@@ -1,7 +1,5 @@
+ /*
+- * drivers/char/hw_random/omap-rng.c
+- *
+- * RNG driver for TI OMAP CPU family
++ * omap-rng.c - RNG driver for TI OMAP CPU family
+  *
+  * Author: Deepak Saxena <dsaxena at plexity.net>
+  *
+@@ -15,11 +13,6 @@
+  * 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.
+- *
+- * TODO:
+- *
+- * - Make status updated be interrupt driven so we don't poll
+- *
+  */
+ 
+ #include <linux/module.h>
+@@ -55,17 +48,16 @@ static void __iomem *rng_base;
+ static struct clk *rng_ick;
+ static struct platform_device *rng_dev;
+ 
+-static u32 omap_rng_read_reg(int reg)
++static inline u32 omap_rng_read_reg(int reg)
+ {
+ 	return __raw_readl(rng_base + reg);
+ }
+ 
+-static void omap_rng_write_reg(int reg, u32 val)
++static inline void omap_rng_write_reg(int reg, u32 val)
+ {
+ 	__raw_writel(val, rng_base + reg);
+ }
+ 
+-/* REVISIT: Does the status bit really work on 16xx? */
+ static int omap_rng_data_present(struct hwrng *rng, int wait)
+ {
+ 	int data, i;
+@@ -74,6 +66,11 @@ static int omap_rng_data_present(struct hwrng *rng, int wait)
+ 		data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
+ 		if (data || !wait)
+ 			break;
++		/* RNG produces data fast enough (2+ MBit/sec, even
++		 * during "rngtest" loads, that these delays don't
++		 * seem to trigger.  We *could* use the RNG IRQ, but
++		 * that'd be higher overhead ... so why bother?
++		 */
+ 		udelay(10);
+ 	}
+ 	return data;
+@@ -101,7 +98,8 @@ static int __init omap_rng_probe(struct platform_device *pdev)
+ 	 * A bit ugly, and it will never actually happen but there can
+ 	 * be only one RNG and this catches any bork
+ 	 */
+-	BUG_ON(rng_dev);
++	if (rng_dev)
++		return -EBUSY;
+ 
+ 	if (cpu_is_omap24xx()) {
+ 		rng_ick = clk_get(NULL, "rng_ick");
+@@ -124,7 +122,7 @@ static int __init omap_rng_probe(struct platform_device *pdev)
+ 		return -EBUSY;
+ 
+ 	dev_set_drvdata(&pdev->dev, mem);
+-	rng_base = (u32 __iomem *)io_p2v(res->start);
++	rng_base = (u32 __force __iomem *)io_p2v(res->start);
+ 
+ 	ret = hwrng_register(&omap_rng_ops);
+ 	if (ret) {
+@@ -182,6 +180,8 @@ static int omap_rng_resume(struct platform_device *pdev)
+ 
+ #endif
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:omap_rng");
+ 
+ static struct platform_driver omap_rng_driver = {
+ 	.driver = {
+diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
+index 4dbd342..60b934a 100644
+--- a/drivers/char/keyboard.c
++++ b/drivers/char/keyboard.c
+@@ -42,6 +42,7 @@
+ #include <linux/input.h>
+ #include <linux/reboot.h>
+ #include <linux/notifier.h>
++#include <linux/jiffies.h>
+ 
+ extern void ctrl_alt_del(void);
+ 
+@@ -928,7 +929,8 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
+ 	if (up_flag) {
+ 		if (brl_timeout) {
+ 			if (!committing ||
+-			    jiffies - releasestart > (brl_timeout * HZ) / 1000) {
++			    time_after(jiffies,
++				       releasestart + msecs_to_jiffies(brl_timeout))) {
+ 				committing = pressed;
+ 				releasestart = jiffies;
+ 			}
+@@ -1033,7 +1035,8 @@ DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
+ #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
+     defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
+     defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
+-    (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
++    (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\
++    defined(CONFIG_AVR32)
+ 
+ #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
+ 			((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
+@@ -1237,6 +1240,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
+ 	}
+ 
+ 	param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
++	param.ledstate = kbd->ledflagstate;
+ 	key_map = key_maps[shift_final];
+ 
+ 	if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, &param) == NOTIFY_STOP || !key_map) {
+@@ -1285,6 +1289,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
+ 
+ 	(*k_handler[type])(vc, keysym & 0xff, !down);
+ 
++	param.ledstate = kbd->ledflagstate;
+ 	atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
+ 
+ 	if (type != KT_SLOCK)
+diff --git a/drivers/char/mem.c b/drivers/char/mem.c
+index 20070b7..e83623e 100644
+--- a/drivers/char/mem.c
++++ b/drivers/char/mem.c
+@@ -41,36 +41,7 @@
+  */
+ static inline int uncached_access(struct file *file, unsigned long addr)
+ {
+-#if defined(__i386__) && !defined(__arch_um__)
+-	/*
+-	 * On the PPro and successors, the MTRRs are used to set
+-	 * memory types for physical addresses outside main memory,
+-	 * so blindly setting PCD or PWT on those pages is wrong.
+-	 * For Pentiums and earlier, the surround logic should disable
+-	 * caching for the high addresses through the KEN pin, but
+-	 * we maintain the tradition of paranoia in this code.
+-	 */
+-	if (file->f_flags & O_SYNC)
+-		return 1;
+- 	return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
+-		  test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
+-		  test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
+-		  test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
+-	  && addr >= __pa(high_memory);
+-#elif defined(__x86_64__) && !defined(__arch_um__)
+-	/* 
+-	 * This is broken because it can generate memory type aliases,
+-	 * which can cause cache corruptions
+-	 * But it is only available for root and we have to be bug-to-bug
+-	 * compatible with i386.
+-	 */
+-	if (file->f_flags & O_SYNC)
+-		return 1;
+-	/* same behaviour as i386. PAT always set to cached and MTRRs control the
+-	   caching behaviour. 
+-	   Hopefully a full PAT implementation will fix that soon. */	   
+-	return 0;
+-#elif defined(CONFIG_IA64)
++#if defined(CONFIG_IA64)
+ 	/*
+ 	 * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
+ 	 */
+@@ -108,6 +79,36 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+ }
+ #endif
+ 
++#ifdef CONFIG_NONPROMISC_DEVMEM
++static inline int range_is_allowed(unsigned long pfn, unsigned long size)
++{
++	u64 from = ((u64)pfn) << PAGE_SHIFT;
++	u64 to = from + size;
++	u64 cursor = from;
++
++	while (cursor < to) {
++		if (!devmem_is_allowed(pfn)) {
++			printk(KERN_INFO
++		"Program %s tried to access /dev/mem between %Lx->%Lx.\n",
++				current->comm, from, to);
++			return 0;
++		}
++		cursor += PAGE_SIZE;
++		pfn++;
++	}
++	return 1;
++}
++#else
++static inline int range_is_allowed(unsigned long pfn, unsigned long size)
++{
++	return 1;
++}
++#endif
++
++void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr)
++{
++}
++
+ /*
+  * This funcion reads the *physical* memory. The f_pos points directly to the 
+  * memory location. 
+@@ -150,15 +151,25 @@ static ssize_t read_mem(struct file * file, char __user * buf,
+ 
+ 		sz = min_t(unsigned long, sz, count);
+ 
++		if (!range_is_allowed(p >> PAGE_SHIFT, count))
++			return -EPERM;
++
+ 		/*
+ 		 * On ia64 if a page has been mapped somewhere as
+ 		 * uncached, then it must also be accessed uncached
+ 		 * by the kernel or data corruption may occur
+ 		 */
+ 		ptr = xlate_dev_mem_ptr(p);
++		if (!ptr)
++			return -EFAULT;
+ 
+-		if (copy_to_user(buf, ptr, sz))
++		if (copy_to_user(buf, ptr, sz)) {
++			unxlate_dev_mem_ptr(p, ptr);
+ 			return -EFAULT;
++		}
++
++		unxlate_dev_mem_ptr(p, ptr);
++
+ 		buf += sz;
+ 		p += sz;
+ 		count -= sz;
+@@ -207,20 +218,32 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
+ 
+ 		sz = min_t(unsigned long, sz, count);
+ 
++		if (!range_is_allowed(p >> PAGE_SHIFT, sz))
++			return -EPERM;
++
+ 		/*
+ 		 * On ia64 if a page has been mapped somewhere as
+ 		 * uncached, then it must also be accessed uncached
+ 		 * by the kernel or data corruption may occur
+ 		 */
+ 		ptr = xlate_dev_mem_ptr(p);
++		if (!ptr) {
++			if (written)
++				break;
++			return -EFAULT;
++		}
+ 
+ 		copied = copy_from_user(ptr, buf, sz);
+ 		if (copied) {
+ 			written += sz - copied;
++			unxlate_dev_mem_ptr(p, ptr);
+ 			if (written)
+ 				break;
+ 			return -EFAULT;
+ 		}
++
++		unxlate_dev_mem_ptr(p, ptr);
++
+ 		buf += sz;
+ 		p += sz;
+ 		count -= sz;
+@@ -231,6 +254,12 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
+ 	return written;
+ }
+ 
++int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file,
++	unsigned long pfn, unsigned long size, pgprot_t *vma_prot)
++{
++	return 1;
++}
++
+ #ifndef __HAVE_PHYS_MEM_ACCESS_PROT
+ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ 				     unsigned long size, pgprot_t vma_prot)
+@@ -271,6 +300,35 @@ static inline int private_mapping_ok(struct vm_area_struct *vma)
+ }
+ #endif
+ 
++void __attribute__((weak))
++map_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
++{
++	/* nothing. architectures can override. */
++}
++
++void __attribute__((weak))
++unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
++{
++	/* nothing. architectures can override. */
++}
++
++static void mmap_mem_open(struct vm_area_struct *vma)
++{
++	map_devmem(vma->vm_pgoff,  vma->vm_end - vma->vm_start,
++			vma->vm_page_prot);
++}
++
++static void mmap_mem_close(struct vm_area_struct *vma)
++{
++	unmap_devmem(vma->vm_pgoff,  vma->vm_end - vma->vm_start,
++			vma->vm_page_prot);
++}
++
++static struct vm_operations_struct mmap_mem_ops = {
++	.open  = mmap_mem_open,
++	.close = mmap_mem_close
++};
++
+ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
+ {
+ 	size_t size = vma->vm_end - vma->vm_start;
+@@ -281,17 +339,28 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
+ 	if (!private_mapping_ok(vma))
+ 		return -ENOSYS;
+ 
++	if (!range_is_allowed(vma->vm_pgoff, size))
++		return -EPERM;
++
++	if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
++						&vma->vm_page_prot))
++		return -EINVAL;
++
+ 	vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
+ 						 size,
+ 						 vma->vm_page_prot);
+ 
++	vma->vm_ops = &mmap_mem_ops;
++
+ 	/* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
+ 	if (remap_pfn_range(vma,
+ 			    vma->vm_start,
+ 			    vma->vm_pgoff,
+ 			    size,
+-			    vma->vm_page_prot))
++			    vma->vm_page_prot)) {
++		unmap_devmem(vma->vm_pgoff, size, vma->vm_page_prot);
+ 		return -EAGAIN;
++	}
+ 	return 0;
+ }
+ 
+diff --git a/drivers/char/misc.c b/drivers/char/misc.c
+index a39101f..4d058da 100644
+--- a/drivers/char/misc.c
++++ b/drivers/char/misc.c
+@@ -232,9 +232,8 @@ int misc_register(struct miscdevice * misc)
+ }
+ 
+ /**
+- *	__misc_deregister - unregister a miscellaneous device
++ *	misc_deregister - unregister a miscellaneous device
+  *	@misc: device to unregister
+- *	@suspended: to be set if the function is used during suspend/resume
+  *
+  *	Unregister a miscellaneous device that was previously
+  *	successfully registered with misc_register(). Success
+@@ -242,7 +241,7 @@ int misc_register(struct miscdevice * misc)
+  *	indicates an error.
+  */
+ 
+-int __misc_deregister(struct miscdevice *misc, bool suspended)
++int misc_deregister(struct miscdevice *misc)
+ {
+ 	int i = misc->minor;
+ 
+@@ -251,11 +250,7 @@ int __misc_deregister(struct miscdevice *misc, bool suspended)
+ 
+ 	mutex_lock(&misc_mtx);
+ 	list_del(&misc->list);
+-	if (suspended)
+-		destroy_suspended_device(misc_class,
+-					MKDEV(MISC_MAJOR, misc->minor));
+-	else
+-		device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
++	device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
+ 	if (i < DYNAMIC_MINORS && i>0) {
+ 		misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
+ 	}
+@@ -264,7 +259,7 @@ int __misc_deregister(struct miscdevice *misc, bool suspended)
+ }
+ 
+ EXPORT_SYMBOL(misc_register);
+-EXPORT_SYMBOL(__misc_deregister);
++EXPORT_SYMBOL(misc_deregister);
+ 
+ static int __init misc_init(void)
+ {
+diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
+index 279ff50..4e84d23 100644
+--- a/drivers/char/pcmcia/synclink_cs.c
++++ b/drivers/char/pcmcia/synclink_cs.c
+@@ -1225,17 +1225,15 @@ static void ri_change(MGSLPC_INFO *info)
+  * irq     interrupt number that caused interrupt
+  * dev_id  device ID supplied during interrupt registration
+  */
+-static irqreturn_t mgslpc_isr(int irq, void *dev_id)
++static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
+ {
+-	MGSLPC_INFO * info = (MGSLPC_INFO *)dev_id;
++	MGSLPC_INFO *info = dev_id;
+ 	unsigned short isr;
+ 	unsigned char gis, pis;
+ 	int count=0;
+ 
+ 	if (debug_level >= DEBUG_LEVEL_ISR)
+-		printk("mgslpc_isr(%d) entry.\n", irq);
+-	if (!info)
+-		return IRQ_NONE;
++		printk("mgslpc_isr(%d) entry.\n", info->irq_level);
+ 
+ 	if (!(info->p_dev->_locked))
+ 		return IRQ_HANDLED;
+@@ -1327,7 +1325,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
+ 
+ 	if (debug_level >= DEBUG_LEVEL_ISR)
+ 		printk("%s(%d):mgslpc_isr(%d)exit.\n",
+-		       __FILE__,__LINE__,irq);
++		       __FILE__, __LINE__, info->irq_level);
+ 
+ 	return IRQ_HANDLED;
+ }
+diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
+index eca2b95..d956dd3 100644
+--- a/drivers/char/rio/rioboot.c
++++ b/drivers/char/rio/rioboot.c
+@@ -35,7 +35,6 @@
+ #include <linux/termios.h>
+ #include <linux/serial.h>
+ #include <linux/vmalloc.h>
+-#include <asm/semaphore.h>
+ #include <linux/generic_serial.h>
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
+diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
+index 7321d00..bf36959 100644
+--- a/drivers/char/rio/riocmd.c
++++ b/drivers/char/rio/riocmd.c
+@@ -41,7 +41,6 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c	1.2";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
+index 7ce7761..d8eb2bc 100644
+--- a/drivers/char/rio/rioctrl.c
++++ b/drivers/char/rio/rioctrl.c
+@@ -40,7 +40,6 @@ static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c	1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
+index 0794844..add1718 100644
+--- a/drivers/char/rio/rioinit.c
++++ b/drivers/char/rio/rioinit.c
+@@ -40,7 +40,6 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c	1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
+index ebc7634..4734e26 100644
+--- a/drivers/char/rio/riointr.c
++++ b/drivers/char/rio/riointr.c
+@@ -42,7 +42,6 @@ static char *_riointr_c_sccs_ = "@(#)riointr.c	1.2";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
+index bb498d2..da276ed 100644
+--- a/drivers/char/rio/rioparam.c
++++ b/drivers/char/rio/rioparam.c
+@@ -41,7 +41,6 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c	1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
+index a99f3d9..85091ff 100644
+--- a/drivers/char/rio/rioroute.c
++++ b/drivers/char/rio/rioroute.c
+@@ -39,7 +39,6 @@ static char *_rioroute_c_sccs_ = "@(#)rioroute.c	1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
+index 9b52892..2b24488 100644
+--- a/drivers/char/rio/riotable.c
++++ b/drivers/char/rio/riotable.c
+@@ -42,7 +42,6 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c	1.2";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
+index cfa5436..1cb8580 100644
+--- a/drivers/char/rio/riotty.c
++++ b/drivers/char/rio/riotty.c
+@@ -44,7 +44,6 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c	1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/termios.h>
+diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h
+index 8a98169..4be62ed 100644
+--- a/drivers/char/snsc.h
++++ b/drivers/char/snsc.h
+@@ -22,8 +22,8 @@
+ #include <linux/kobject.h>
+ #include <linux/fs.h>
+ #include <linux/cdev.h>
++#include <linux/semaphore.h>
+ #include <asm/sn/types.h>
+-#include <asm/semaphore.h>
+ 
+ #define CHUNKSIZE 127
+ 
+diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
+index 921c6d2..c03ad16 100644
+--- a/drivers/char/sonypi.c
++++ b/drivers/char/sonypi.c
+@@ -1147,7 +1147,7 @@ static int sonypi_acpi_remove(struct acpi_device *device, int type)
+ 	return 0;
+ }
+ 
+-const static struct acpi_device_id sonypi_device_ids[] = {
++static const struct acpi_device_id sonypi_device_ids[] = {
+ 	{"SNY6001", 0},
+ 	{"", 0},
+ };
+diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
+index 5ff83df..4b5b5b7 100644
+--- a/drivers/char/specialix.c
++++ b/drivers/char/specialix.c
+@@ -443,8 +443,7 @@ void missed_irq (unsigned long data)
+ 	spin_unlock_irqrestore(&bp->lock, flags);
+ 	if (irq) {
+ 		printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
+-		sx_interrupt (((struct specialix_board *)data)->irq,
+-				(void*)data);
++		sx_interrupt (-1, bp);
+ 	}
+ 	mod_timer(&missed_irq_timer, jiffies + sx_poll);
+ }
+@@ -862,23 +861,22 @@ static inline void sx_check_modem(struct specialix_board * bp)
+ 
+ 
+ /* The main interrupt processing routine */
+-static irqreturn_t sx_interrupt(int irq, void *dev_id)
++static irqreturn_t sx_interrupt(int dummy, void *dev_id)
+ {
+ 	unsigned char status;
+ 	unsigned char ack;
+-	struct specialix_board *bp;
++	struct specialix_board *bp = dev_id;
+ 	unsigned long loop = 0;
+ 	int saved_reg;
+ 	unsigned long flags;
+ 
+ 	func_enter();
+ 
+-	bp = dev_id;
+ 	spin_lock_irqsave(&bp->lock, flags);
+ 
+ 	dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
+ 	if (!(bp->flags & SX_BOARD_ACTIVE)) {
+-		dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
++		dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq);
+ 		spin_unlock_irqrestore(&bp->lock, flags);
+ 		func_exit();
+ 		return IRQ_NONE;
+diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
+index feac54e..874aaa0 100644
+--- a/drivers/char/stallion.c
++++ b/drivers/char/stallion.c
+@@ -1645,7 +1645,7 @@ static irqreturn_t stl_intr(int irq, void *dev_id)
+ {
+ 	struct stlbrd *brdp = dev_id;
+ 
+-	pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
++	pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
+ 
+ 	return IRQ_RETVAL((* brdp->isr)(brdp));
+ }
+diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
+index ddc74d1..a3237d4 100644
+--- a/drivers/char/synclink.c
++++ b/drivers/char/synclink.c
+@@ -1695,20 +1695,16 @@ static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
+  * 	
+  * Return Value: None
+  */
+-static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
++static irqreturn_t mgsl_interrupt(int dummy, void *dev_id)
+ {
+-	struct mgsl_struct * info;
++	struct mgsl_struct *info = dev_id;
+ 	u16 UscVector;
+ 	u16 DmaVector;
+ 
+ 	if ( debug_level >= DEBUG_LEVEL_ISR )	
+-		printk("%s(%d):mgsl_interrupt(%d)entry.\n",
+-			__FILE__,__LINE__,irq);
++		printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)entry.\n",
++			__FILE__, __LINE__, info->irq_level);
+ 
+-	info = (struct mgsl_struct *)dev_id;	
+-	if (!info)
+-		return IRQ_NONE;
+-		
+ 	spin_lock(&info->irq_spinlock);
+ 
+ 	for(;;) {
+@@ -1732,8 +1728,8 @@ static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
+ 			mgsl_isr_receive_dma(info);
+ 
+ 		if ( info->isr_overflow ) {
+-			printk(KERN_ERR"%s(%d):%s isr overflow irq=%d\n",
+-				__FILE__,__LINE__,info->device_name, irq);
++			printk(KERN_ERR "%s(%d):%s isr overflow irq=%d\n",
++				__FILE__, __LINE__, info->device_name, info->irq_level);
+ 			usc_DisableMasterIrqBit(info);
+ 			usc_DisableDmaInterrupts(info,DICR_MASTER);
+ 			break;
+@@ -1755,8 +1751,9 @@ static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
+ 	spin_unlock(&info->irq_spinlock);
+ 	
+ 	if ( debug_level >= DEBUG_LEVEL_ISR )	
+-		printk("%s(%d):mgsl_interrupt(%d)exit.\n",
+-			__FILE__,__LINE__,irq);
++		printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)exit.\n",
++			__FILE__, __LINE__, info->irq_level);
++
+ 	return IRQ_HANDLED;
+ }	/* end of mgsl_interrupt() */
+ 
+diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
+index 1f954ac..3c89266 100644
+--- a/drivers/char/synclink_gt.c
++++ b/drivers/char/synclink_gt.c
+@@ -491,7 +491,6 @@ static void isr_serial(struct slgt_info *info);
+ static void isr_rdma(struct slgt_info *info);
+ static void isr_txeom(struct slgt_info *info, unsigned short status);
+ static void isr_tdma(struct slgt_info *info);
+-static irqreturn_t slgt_interrupt(int irq, void *dev_id);
+ 
+ static int  alloc_dma_bufs(struct slgt_info *info);
+ static void free_dma_bufs(struct slgt_info *info);
+@@ -2326,17 +2325,13 @@ static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int
+  * 	irq	interrupt number
+  * 	dev_id	device ID supplied during interrupt registration
+  */
+-static irqreturn_t slgt_interrupt(int irq, void *dev_id)
++static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
+ {
+-	struct slgt_info *info;
++	struct slgt_info *info = dev_id;
+ 	unsigned int gsr;
+ 	unsigned int i;
+ 
+-	DBGISR(("slgt_interrupt irq=%d entry\n", irq));
+-
+-	info = dev_id;
+-	if (!info)
+-		return IRQ_NONE;
++	DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level));
+ 
+ 	spin_lock(&info->lock);
+ 
+@@ -2385,7 +2380,7 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id)
+ 
+ 	spin_unlock(&info->lock);
+ 
+-	DBGISR(("slgt_interrupt irq=%d exit\n", irq));
++	DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level));
+ 	return IRQ_HANDLED;
+ }
+ 
+diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
+index f3e7807..c96062e 100644
+--- a/drivers/char/synclinkmp.c
++++ b/drivers/char/synclinkmp.c
+@@ -2586,9 +2586,9 @@ void isr_io_pin( SLMP_INFO *info, u16 status )
+  * 	dev_id		device ID supplied during interrupt registration
+  * 	regs		interrupted processor context
+  */
+-static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
++static irqreturn_t synclinkmp_interrupt(int dummy, void *dev_id)
+ {
+-	SLMP_INFO * info;
++	SLMP_INFO *info = dev_id;
+ 	unsigned char status, status0, status1=0;
+ 	unsigned char dmastatus, dmastatus0, dmastatus1=0;
+ 	unsigned char timerstatus0, timerstatus1=0;
+@@ -2597,12 +2597,8 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
+ 	unsigned short tmp;
+ 
+ 	if ( debug_level >= DEBUG_LEVEL_ISR )
+-		printk("%s(%d): synclinkmp_interrupt(%d)entry.\n",
+-			__FILE__,__LINE__,irq);
+-
+-	info = (SLMP_INFO *)dev_id;
+-	if (!info)
+-		return IRQ_NONE;
++		printk(KERN_DEBUG "%s(%d): synclinkmp_interrupt(%d)entry.\n",
++			__FILE__, __LINE__, info->irq_level);
+ 
+ 	spin_lock(&info->lock);
+ 
+@@ -2615,9 +2611,9 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
+ 		timerstatus0 = read_reg(info, ISR2);
+ 
+ 		if ( debug_level >= DEBUG_LEVEL_ISR )
+-			printk("%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n",
+-				__FILE__,__LINE__,info->device_name,
+-				status0,dmastatus0,timerstatus0);
++			printk(KERN_DEBUG "%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n",
++				__FILE__, __LINE__, info->device_name,
++				status0, dmastatus0, timerstatus0);
+ 
+ 		if (info->port_count == 4) {
+ 			/* get status for SCA1 (ports 2-3) */
+@@ -2702,8 +2698,8 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
+ 	spin_unlock(&info->lock);
+ 
+ 	if ( debug_level >= DEBUG_LEVEL_ISR )
+-		printk("%s(%d):synclinkmp_interrupt(%d)exit.\n",
+-			__FILE__,__LINE__,irq);
++		printk(KERN_DEBUG "%s(%d):synclinkmp_interrupt(%d)exit.\n",
++			__FILE__, __LINE__, info->irq_level);
+ 	return IRQ_HANDLED;
+ }
+ 
+diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
+index 81503d9..13a4bdd 100644
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -399,7 +399,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-static irqreturn_t tis_int_handler(int irq, void *dev_id)
++static irqreturn_t tis_int_handler(int dummy, void *dev_id)
+ {
+ 	struct tpm_chip *chip = dev_id;
+ 	u32 interrupt;
+diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
+index 613ec81..4d3c701 100644
+--- a/drivers/char/tty_io.c
++++ b/drivers/char/tty_io.c
+@@ -1155,6 +1155,48 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
+ 	return NULL;
+ }
+ 
++#ifdef CONFIG_CONSOLE_POLL
++
++/**
++ *	tty_find_polling_driver	-	find device of a polled tty
++ *	@name: name string to match
++ *	@line: pointer to resulting tty line nr
++ *
++ *	This routine returns a tty driver structure, given a name
++ *	and the condition that the tty driver is capable of polled
++ *	operation.
++ */
++struct tty_driver *tty_find_polling_driver(char *name, int *line)
++{
++	struct tty_driver *p, *res = NULL;
++	int tty_line = 0;
++	char *str;
++
++	mutex_lock(&tty_mutex);
++	/* Search through the tty devices to look for a match */
++	list_for_each_entry(p, &tty_drivers, tty_drivers) {
++		str = name + strlen(p->name);
++		tty_line = simple_strtoul(str, &str, 10);
++		if (*str == ',')
++			str++;
++		if (*str == '\0')
++			str = 0;
++
++		if (tty_line >= 0 && tty_line <= p->num && p->poll_init &&
++				!p->poll_init(p, tty_line, str)) {
++
++			res = p;
++			*line = tty_line;
++			break;
++		}
++	}
++	mutex_unlock(&tty_mutex);
++
++	return res;
++}
++EXPORT_SYMBOL_GPL(tty_find_polling_driver);
++#endif
++
+ /**
+  *	tty_check_change	-	check for POSIX terminal changes
+  *	@tty: tty to check
+@@ -3850,6 +3892,11 @@ void tty_set_operations(struct tty_driver *driver,
+ 	driver->write_proc = op->write_proc;
+ 	driver->tiocmget = op->tiocmget;
+ 	driver->tiocmset = op->tiocmset;
++#ifdef CONFIG_CONSOLE_POLL
++	driver->poll_init = op->poll_init;
++	driver->poll_get_char = op->poll_get_char;
++	driver->poll_put_char = op->poll_put_char;
++#endif
+ }
+ 
+ 
+diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c
+index f577dae..aa7f796 100644
+--- a/drivers/char/xilinx_hwicap/buffer_icap.c
++++ b/drivers/char/xilinx_hwicap/buffer_icap.c
+@@ -74,7 +74,7 @@
+ 
+ /**
+  * buffer_icap_get_status - Get the contents of the status register.
+- * @base_address: is the base address of the device
++ * @drvdata: a pointer to the drvdata.
+  *
+  * The status register contains the ICAP status and the done bit.
+  *
+@@ -88,9 +88,9 @@
+  * D1 - Always 1
+  * D0 - Done bit
+  **/
+-static inline u32 buffer_icap_get_status(void __iomem *base_address)
++u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata)
+ {
+-	return in_be32(base_address + XHI_STATUS_REG_OFFSET);
++	return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET);
+ }
+ 
+ /**
+@@ -117,20 +117,8 @@ static inline u32 buffer_icap_get_bram(void __iomem *base_address,
+  **/
+ static inline bool buffer_icap_busy(void __iomem *base_address)
+ {
+-	return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED;
+-}
+-
+-/**
+- * buffer_icap_busy - Return true if the icap device is not busy
+- * @base_address: is the base address of the device
+- *
+- * The queries the low order bit of the status register, which
+- * indicates whether the current configuration or readback operation
+- * has completed.
+- **/
+-static inline bool buffer_icap_done(void __iomem *base_address)
+-{
+-	return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED;
++	u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET);
++	return (status & 1) == XHI_NOT_FINISHED;
+ }
+ 
+ /**
+diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h
+index 0318495..c5b1840 100644
+--- a/drivers/char/xilinx_hwicap/buffer_icap.h
++++ b/drivers/char/xilinx_hwicap/buffer_icap.h
+@@ -44,8 +44,6 @@
+ #include <asm/io.h>
+ #include "xilinx_hwicap.h"
+ 
+-void buffer_icap_reset(struct hwicap_drvdata *drvdata);
+-
+ /* Loads a partial bitstream from system memory. */
+ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
+ 			     u32 Size);
+@@ -54,4 +52,7 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
+ int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
+ 			     u32 Size);
+ 
++u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata);
++void buffer_icap_reset(struct hwicap_drvdata *drvdata);
++
+ #endif
+diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c
+index 6f45dbd..776b505 100644
+--- a/drivers/char/xilinx_hwicap/fifo_icap.c
++++ b/drivers/char/xilinx_hwicap/fifo_icap.c
+@@ -78,13 +78,6 @@
+ #define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */
+ #define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */
+ 
+-/* Status Register (SR) */
+-#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */
+-#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */
+-#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */
+-#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */
+-#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask  */
+-
+ 
+ #define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */
+ #define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */
+@@ -152,13 +145,35 @@ static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)
+ }
+ 
+ /**
++ * fifo_icap_get_status - Get the contents of the status register.
++ * @drvdata: a pointer to the drvdata.
++ *
++ * The status register contains the ICAP status and the done bit.
++ *
++ * D8 - cfgerr
++ * D7 - dalign
++ * D6 - rip
++ * D5 - in_abort_l
++ * D4 - Always 1
++ * D3 - Always 1
++ * D2 - Always 1
++ * D1 - Always 1
++ * D0 - Done bit
++ **/
++u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata)
++{
++	u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
++	dev_dbg(drvdata->dev, "Getting status = %x\n", status);
++	return status;
++}
++
++/**
+  * fifo_icap_busy - Return true if the ICAP is still processing a transaction.
+  * @drvdata: a pointer to the drvdata.
+  **/
+ static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
+ {
+ 	u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
+-	dev_dbg(drvdata->dev, "Getting status = %x\n", status);
+ 	return (status & XHI_SR_DONE_MASK) ? 0 : 1;
+ }
+ 
+diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h
+index 4d3068d..ffabd3b 100644
+--- a/drivers/char/xilinx_hwicap/fifo_icap.h
++++ b/drivers/char/xilinx_hwicap/fifo_icap.h
+@@ -56,6 +56,7 @@ int fifo_icap_set_configuration(
+ 		u32 *FrameBuffer,
+ 		u32 NumWords);
+ 
++u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata);
+ void fifo_icap_reset(struct hwicap_drvdata *drvdata);
+ void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata);
+ 
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+index 2284fa2..dfe6907 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+@@ -36,7 +36,7 @@
+  *****************************************************************************/
+ 
+ /*
+- * This is the code behind /dev/xilinx_icap -- it allows a user-space
++ * This is the code behind /dev/icap* -- it allows a user-space
+  * application to use the Xilinx ICAP subsystem.
+  *
+  * The following operations are possible:
+@@ -67,7 +67,7 @@
+  * user-space application code that uses this device.  The simplest
+  * way to use this interface is simply:
+  *
+- * cp foo.bit /dev/xilinx_icap
++ * cp foo.bit /dev/icap0
+  *
+  * Note that unless foo.bit is an appropriately constructed partial
+  * bitstream, this has a high likelyhood of overwriting the design
+@@ -105,18 +105,14 @@
+ #include "buffer_icap.h"
+ #include "fifo_icap.h"
+ 
+-#define DRIVER_NAME "xilinx_icap"
++#define DRIVER_NAME "icap"
+ 
+ #define HWICAP_REGS   (0x10000)
+ 
+-/* dynamically allocate device number */
+-static int xhwicap_major;
+-static int xhwicap_minor;
++#define XHWICAP_MAJOR 259
++#define XHWICAP_MINOR 0
+ #define HWICAP_DEVICES 1
+ 
+-module_param(xhwicap_major, int, S_IRUGO);
+-module_param(xhwicap_minor, int, S_IRUGO);
+-
+ /* An array, which is set to true when the device is registered. */
+ static bool probed_devices[HWICAP_DEVICES];
+ static struct mutex icap_sem;
+@@ -250,8 +246,26 @@ static int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,
+ 	 * Create the data to be written to the ICAP.
+ 	 */
+ 	buffer[index++] = XHI_DUMMY_PACKET;
++	buffer[index++] = XHI_NOOP_PACKET;
+ 	buffer[index++] = XHI_SYNC_PACKET;
+ 	buffer[index++] = XHI_NOOP_PACKET;
++	buffer[index++] = XHI_NOOP_PACKET;
++
++	/*
++	 * Write the data to the FIFO and initiate the transfer of data present
++	 * in the FIFO to the ICAP device.
++	 */
++	status = drvdata->config->set_configuration(drvdata,
++						    &buffer[0], index);
++	if (status)
++		return status;
++
++	/* If the syncword was not found, then we need to start over. */
++	status = drvdata->config->get_status(drvdata);
++	if ((status & XHI_SR_DALIGN_MASK) != XHI_SR_DALIGN_MASK)
++		return -EIO;
++
++	index = 0;
+ 	buffer[index++] = hwicap_type_1_read(reg) | 1;
+ 	buffer[index++] = XHI_NOOP_PACKET;
+ 	buffer[index++] = XHI_NOOP_PACKET;
+@@ -587,7 +601,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
+ 	probed_devices[id] = 1;
+ 	mutex_unlock(&icap_sem);
+ 
+-	devt = MKDEV(xhwicap_major, xhwicap_minor + id);
++	devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id);
+ 
+ 	drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);
+ 	if (!drvdata) {
+@@ -664,12 +678,14 @@ static int __devinit hwicap_setup(struct device *dev, int id,
+ static struct hwicap_driver_config buffer_icap_config = {
+ 	.get_configuration = buffer_icap_get_configuration,
+ 	.set_configuration = buffer_icap_set_configuration,
++	.get_status = buffer_icap_get_status,
+ 	.reset = buffer_icap_reset,
+ };
+ 
+ static struct hwicap_driver_config fifo_icap_config = {
+ 	.get_configuration = fifo_icap_get_configuration,
+ 	.set_configuration = fifo_icap_set_configuration,
++	.get_status = fifo_icap_get_status,
+ 	.reset = fifo_icap_reset,
+ };
+ 
+@@ -690,7 +706,7 @@ static int __devexit hwicap_remove(struct device *dev)
+ 	dev_set_drvdata(dev, NULL);
+ 
+ 	mutex_lock(&icap_sem);
+-	probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0;
++	probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
+ 	mutex_unlock(&icap_sem);
+ 	return 0;		/* success */
+ }
+@@ -787,7 +803,7 @@ static int __devexit hwicap_of_remove(struct of_device *op)
+ }
+ 
+ /* Match table for of_platform binding */
+-static const struct of_device_id __devinit hwicap_of_match[] = {
++static const struct of_device_id __devinitconst hwicap_of_match[] = {
+ 	{ .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
+ 	{ .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
+ 	{},
+@@ -830,23 +846,12 @@ static int __init hwicap_module_init(void)
+ 	icap_class = class_create(THIS_MODULE, "xilinx_config");
+ 	mutex_init(&icap_sem);
+ 
+-	if (xhwicap_major) {
+-		devt = MKDEV(xhwicap_major, xhwicap_minor);
+-		retval = register_chrdev_region(
+-				devt,
+-				HWICAP_DEVICES,
+-				DRIVER_NAME);
+-		if (retval < 0)
+-			return retval;
+-	} else {
+-		retval = alloc_chrdev_region(&devt,
+-				xhwicap_minor,
+-				HWICAP_DEVICES,
+-				DRIVER_NAME);
+-		if (retval < 0)
+-			return retval;
+-		xhwicap_major = MAJOR(devt);
+-	}
++	devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
++	retval = register_chrdev_region(devt,
++					HWICAP_DEVICES,
++					DRIVER_NAME);
++	if (retval < 0)
++		return retval;
+ 
+ 	retval = platform_driver_register(&hwicap_platform_driver);
+ 
+@@ -871,7 +876,7 @@ static int __init hwicap_module_init(void)
+ 
+ static void __exit hwicap_module_cleanup(void)
+ {
+-	dev_t devt = MKDEV(xhwicap_major, xhwicap_minor);
++	dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
+ 
+ 	class_destroy(icap_class);
+ 
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
+index 405fee7..1f9c8b0 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
+@@ -65,10 +65,27 @@ struct hwicap_drvdata {
+ };
+ 
+ struct hwicap_driver_config {
++	/* Read configuration data given by size into the data buffer.
++	   Return 0 if successful. */
+ 	int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data,
+ 			u32 size);
++	/* Write configuration data given by size from the data buffer.
++	   Return 0 if successful. */
+ 	int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data,
+ 			u32 size);
++	/* Get the status register, bit pattern given by:
++	 * D8 - 0 = configuration error
++	 * D7 - 1 = alignment found
++	 * D6 - 1 = readback in progress
++	 * D5 - 0 = abort in progress
++	 * D4 - Always 1
++	 * D3 - Always 1
++	 * D2 - Always 1
++	 * D1 - Always 1
++	 * D0 - 1 = operation completed
++	 */
++	u32 (*get_status)(struct hwicap_drvdata *drvdata);
++	/* Reset the hw */
+ 	void (*reset)(struct hwicap_drvdata *drvdata);
+ };
+ 
+@@ -163,6 +180,13 @@ struct config_registers {
+ /* Constant to use for CRC check when CRC has been disabled */
+ #define XHI_DISABLED_AUTO_CRC       0x0000DEFCUL
+ 
++/* Meanings of the bits returned by get_status */
++#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */
++#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */
++#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */
++#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */
++#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask  */
++
+ /**
+  * hwicap_type_1_read - Generates a Type 1 read packet header.
+  * @reg: is the address of the register to be read back.
+diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
+index a522254..1525882 100644
+--- a/drivers/clocksource/Makefile
++++ b/drivers/clocksource/Makefile
+@@ -1,3 +1,4 @@
++obj-$(CONFIG_ATMEL_TCB_CLKSRC)	+= tcb_clksrc.o
+ obj-$(CONFIG_X86_CYCLONE_TIMER)	+= cyclone.o
+ obj-$(CONFIG_X86_PM_TIMER)	+= acpi_pm.o
+ obj-$(CONFIG_SCx200HR_TIMER)	+= scx200_hrt.o
+diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
+new file mode 100644
+index 0000000..f450588
+--- /dev/null
++++ b/drivers/clocksource/tcb_clksrc.c
+@@ -0,0 +1,302 @@
++#include <linux/init.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/ioport.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++#include <linux/atmel_tc.h>
++
++
++/*
++ * We're configured to use a specific TC block, one that's not hooked
++ * up to external hardware, to provide a time solution:
++ *
++ *   - Two channels combine to create a free-running 32 bit counter
++ *     with a base rate of 5+ MHz, packaged as a clocksource (with
++ *     resolution better than 200 nsec).
++ *
++ *   - The third channel may be used to provide a 16-bit clockevent
++ *     source, used in either periodic or oneshot mode.  This runs
++ *     at 32 KiHZ, and can handle delays of up to two seconds.
++ *
++ * A boot clocksource and clockevent source are also currently needed,
++ * unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so
++ * this code can be used when init_timers() is called, well before most
++ * devices are set up.  (Some low end AT91 parts, which can run uClinux,
++ * have only the timers in one TC block... they currently don't support
++ * the tclib code, because of that initialization issue.)
++ *
++ * REVISIT behavior during system suspend states... we should disable
++ * all clocks and save the power.  Easily done for clockevent devices,
++ * but clocksources won't necessarily get the needed notifications.
++ * For deeper system sleep states, this will be mandatory...
++ */
++
++static void __iomem *tcaddr;
++
++static cycle_t tc_get_cycles(void)
++{
++	unsigned long	flags;
++	u32		lower, upper;
++
++	raw_local_irq_save(flags);
++	do {
++		upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV));
++		lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
++	} while (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)));
++
++	raw_local_irq_restore(flags);
++	return (upper << 16) | lower;
++}
++
++static struct clocksource clksrc = {
++	.name           = "tcb_clksrc",
++	.rating         = 200,
++	.read           = tc_get_cycles,
++	.mask           = CLOCKSOURCE_MASK(32),
++	.shift          = 18,
++	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++#ifdef CONFIG_GENERIC_CLOCKEVENTS
++
++struct tc_clkevt_device {
++	struct clock_event_device	clkevt;
++	struct clk			*clk;
++	void __iomem			*regs;
++};
++
++static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
++{
++	return container_of(clkevt, struct tc_clkevt_device, clkevt);
++}
++
++/* For now, we always use the 32K clock ... this optimizes for NO_HZ,
++ * because using one of the divided clocks would usually mean the
++ * tick rate can never be less than several dozen Hz (vs 0.5 Hz).
++ *
++ * A divided clock could be good for high resolution timers, since
++ * 30.5 usec resolution can seem "low".
++ */
++static u32 timer_clock;
++
++static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
++{
++	struct tc_clkevt_device *tcd = to_tc_clkevt(d);
++	void __iomem		*regs = tcd->regs;
++
++	if (tcd->clkevt.mode == CLOCK_EVT_MODE_PERIODIC
++			|| tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) {
++		__raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
++		__raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
++		clk_disable(tcd->clk);
++	}
++
++	switch (m) {
++
++	/* By not making the gentime core emulate periodic mode on top
++	 * of oneshot, we get lower overhead and improved accuracy.
++	 */
++	case CLOCK_EVT_MODE_PERIODIC:
++		clk_enable(tcd->clk);
++
++		/* slow clock, count up to RC, then irq and restart */
++		__raw_writel(timer_clock
++				| ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
++				regs + ATMEL_TC_REG(2, CMR));
++		__raw_writel((32768 + HZ/2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
++
++		/* Enable clock and interrupts on RC compare */
++		__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
++
++		/* go go gadget! */
++		__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
++				regs + ATMEL_TC_REG(2, CCR));
++		break;
++
++	case CLOCK_EVT_MODE_ONESHOT:
++		clk_enable(tcd->clk);
++
++		/* slow clock, count up to RC, then irq and stop */
++		__raw_writel(timer_clock | ATMEL_TC_CPCSTOP
++				| ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
++				regs + ATMEL_TC_REG(2, CMR));
++		__raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
++
++		/* set_next_event() configures and starts the timer */
++		break;
++
++	default:
++		break;
++	}
++}
++
++static int tc_next_event(unsigned long delta, struct clock_event_device *d)
++{
++	__raw_writel(delta, tcaddr + ATMEL_TC_REG(2, RC));
++
++	/* go go gadget! */
++	__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
++			tcaddr + ATMEL_TC_REG(2, CCR));
++	return 0;
++}
++
++static struct tc_clkevt_device clkevt = {
++	.clkevt	= {
++		.name		= "tc_clkevt",
++		.features	= CLOCK_EVT_FEAT_PERIODIC
++					| CLOCK_EVT_FEAT_ONESHOT,
++		.shift		= 32,
++		/* Should be lower than at91rm9200's system timer */
++		.rating		= 125,
++		.cpumask	= CPU_MASK_CPU0,
++		.set_next_event	= tc_next_event,
++		.set_mode	= tc_mode,
++	},
++};
++
++static irqreturn_t ch2_irq(int irq, void *handle)
++{
++	struct tc_clkevt_device	*dev = handle;
++	unsigned int		sr;
++
++	sr = __raw_readl(dev->regs + ATMEL_TC_REG(2, SR));
++	if (sr & ATMEL_TC_CPCS) {
++		dev->clkevt.event_handler(&dev->clkevt);
++		return IRQ_HANDLED;
++	}
++
++	return IRQ_NONE;
++}
++
++static struct irqaction tc_irqaction = {
++	.name		= "tc_clkevt",
++	.flags		= IRQF_TIMER | IRQF_DISABLED,
++	.handler	= ch2_irq,
++};
++
++static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
++{
++	struct clk *t2_clk = tc->clk[2];
++	int irq = tc->irq[2];
++
++	clkevt.regs = tc->regs;
++	clkevt.clk = t2_clk;
++	tc_irqaction.dev_id = &clkevt;
++
++	timer_clock = clk32k_divisor_idx;
++
++	clkevt.clkevt.mult = div_sc(32768, NSEC_PER_SEC, clkevt.clkevt.shift);
++	clkevt.clkevt.max_delta_ns
++		= clockevent_delta2ns(0xffff, &clkevt.clkevt);
++	clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1;
++
++	setup_irq(irq, &tc_irqaction);
++
++	clockevents_register_device(&clkevt.clkevt);
++}
++
++#else /* !CONFIG_GENERIC_CLOCKEVENTS */
++
++static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
++{
++	/* NOTHING */
++}
++
++#endif
++
++static int __init tcb_clksrc_init(void)
++{
++	static char bootinfo[] __initdata
++		= KERN_DEBUG "%s: tc%d at %d.%03d MHz\n";
++
++	struct platform_device *pdev;
++	struct atmel_tc *tc;
++	struct clk *t0_clk;
++	u32 rate, divided_rate = 0;
++	int best_divisor_idx = -1;
++	int clk32k_divisor_idx = -1;
++	int i;
++
++	tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name);
++	if (!tc) {
++		pr_debug("can't alloc TC for clocksource\n");
++		return -ENODEV;
++	}
++	tcaddr = tc->regs;
++	pdev = tc->pdev;
++
++	t0_clk = tc->clk[0];
++	clk_enable(t0_clk);
++
++	/* How fast will we be counting?  Pick something over 5 MHz.  */
++	rate = (u32) clk_get_rate(t0_clk);
++	for (i = 0; i < 5; i++) {
++		unsigned divisor = atmel_tc_divisors[i];
++		unsigned tmp;
++
++		/* remember 32 KiHz clock for later */
++		if (!divisor) {
++			clk32k_divisor_idx = i;
++			continue;
++		}
++
++		tmp = rate / divisor;
++		pr_debug("TC: %u / %-3u [%d] --> %u\n", rate, divisor, i, tmp);
++		if (best_divisor_idx > 0) {
++			if (tmp < 5 * 1000 * 1000)
++				continue;
++		}
++		divided_rate = tmp;
++		best_divisor_idx = i;
++	}
++
++	clksrc.mult = clocksource_hz2mult(divided_rate, clksrc.shift);
++
++	printk(bootinfo, clksrc.name, CONFIG_ATMEL_TCB_CLKSRC_BLOCK,
++			divided_rate / 1000000,
++			((divided_rate + 500000) % 1000000) / 1000);
++
++	/* tclib will give us three clocks no matter what the
++	 * underlying platform supports.
++	 */
++	clk_enable(tc->clk[1]);
++
++	/* channel 0:  waveform mode, input mclk/8, clock TIOA0 on overflow */
++	__raw_writel(best_divisor_idx			/* likely divide-by-8 */
++			| ATMEL_TC_WAVE
++			| ATMEL_TC_WAVESEL_UP		/* free-run */
++			| ATMEL_TC_ACPA_SET		/* TIOA0 rises at 0 */
++			| ATMEL_TC_ACPC_CLEAR,		/* (duty cycle 50%) */
++			tcaddr + ATMEL_TC_REG(0, CMR));
++	__raw_writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA));
++	__raw_writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC));
++	__raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR));	/* no irqs */
++	__raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
++
++	/* channel 1:  waveform mode, input TIOA0 */
++	__raw_writel(ATMEL_TC_XC1			/* input: TIOA0 */
++			| ATMEL_TC_WAVE
++			| ATMEL_TC_WAVESEL_UP,		/* free-run */
++			tcaddr + ATMEL_TC_REG(1, CMR));
++	__raw_writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR));	/* no irqs */
++	__raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR));
++
++	/* chain channel 0 to channel 1, then reset all the timers */
++	__raw_writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR);
++	__raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
++
++	/* and away we go! */
++	clocksource_register(&clksrc);
++
++	/* channel 2:  periodic and oneshot timer support */
++	setup_clkevents(tc, clk32k_divisor_idx);
++
++	return 0;
++}
++arch_initcall(tcb_clksrc_init);
+diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
+index 6b658d8..43b71b6 100644
+--- a/drivers/crypto/Kconfig
++++ b/drivers/crypto/Kconfig
+@@ -27,6 +27,7 @@ config CRYPTO_DEV_PADLOCK_AES
+ 	tristate "PadLock driver for AES algorithm"
+ 	depends on CRYPTO_DEV_PADLOCK
+ 	select CRYPTO_BLKCIPHER
++	select CRYPTO_AES
+ 	help
+ 	  Use VIA PadLock for AES algorithm.
+ 
+@@ -64,6 +65,7 @@ config ZCRYPT
+ 	tristate "Support for PCI-attached cryptographic adapters"
+ 	depends on S390
+ 	select ZCRYPT_MONOLITHIC if ZCRYPT="y"
++	select HW_RANDOM
+ 	help
+ 	  Select this option if you want to use a PCI-attached cryptographic
+ 	  adapter like:
+@@ -100,6 +102,19 @@ config CRYPTO_SHA256_S390
+ 	  This version of SHA implements a 256 bit hash with 128 bits of
+ 	  security against collision attacks.
+ 
++config CRYPTO_SHA512_S390
++	tristate "SHA384 and SHA512 digest algorithm"
++	depends on S390
++	select CRYPTO_ALGAPI
++	help
++	  This is the s390 hardware accelerated implementation of the
++	  SHA512 secure hash standard.
++
++	  This version of SHA implements a 512 bit hash with 256 bits of
++	  security against collision attacks. The code also includes SHA-384,
++	  a 384 bit hash with 192 bits of security against collision attacks.
++
++
+ config CRYPTO_DES_S390
+ 	tristate "DES and Triple DES cipher algorithms"
+ 	depends on S390
+diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
+index 2f3ad3f..bb30eb9 100644
+--- a/drivers/crypto/padlock-aes.c
++++ b/drivers/crypto/padlock-aes.c
+@@ -5,42 +5,6 @@
+  *
+  * Copyright (c) 2004  Michal Ludvig <michal at logix.cz>
+  *
+- * Key expansion routine taken from crypto/aes_generic.c
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * ---------------------------------------------------------------------------
+- * Copyright (c) 2002, Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
+- * All rights reserved.
+- *
+- * LICENSE TERMS
+- *
+- * The free distribution and use of this software in both source and binary
+- * form is allowed (with or without changes) provided that:
+- *
+- *   1. distributions of this source code include the above copyright
+- *      notice, this list of conditions and the following disclaimer;
+- *
+- *   2. distributions in binary form include the above copyright
+- *      notice, this list of conditions and the following disclaimer
+- *      in the documentation and/or other associated materials;
+- *
+- *   3. the copyright holder's name is not used to endorse products
+- *      built using this software without specific written permission.
+- *
+- * ALTERNATIVELY, provided that this notice is retained in full, this product
+- * may be distributed under the terms of the GNU General Public License (GPL),
+- * in which case the provisions of the GPL apply INSTEAD OF those given above.
+- *
+- * DISCLAIMER
+- *
+- * This software is provided 'as is' with no explicit or implied warranties
+- * in respect of its properties, including, but not limited to, correctness
+- * and/or fitness for purpose.
+- * ---------------------------------------------------------------------------
+  */
+ 
+ #include <crypto/algapi.h>
+@@ -54,9 +18,6 @@
+ #include <asm/byteorder.h>
+ #include "padlock.h"
+ 
+-#define AES_EXTENDED_KEY_SIZE	64	/* in uint32_t units */
+-#define AES_EXTENDED_KEY_SIZE_B	(AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))
+-
+ /* Control word. */
+ struct cword {
+ 	unsigned int __attribute__ ((__packed__))
+@@ -70,218 +31,23 @@ struct cword {
+ 
+ /* Whenever making any changes to the following
+  * structure *make sure* you keep E, d_data
+- * and cword aligned on 16 Bytes boundaries!!! */
++ * and cword aligned on 16 Bytes boundaries and
++ * the Hardware can access 16 * 16 bytes of E and d_data
++ * (only the first 15 * 16 bytes matter but the HW reads
++ * more).
++ */
+ struct aes_ctx {
++	u32 E[AES_MAX_KEYLENGTH_U32]
++		__attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
++	u32 d_data[AES_MAX_KEYLENGTH_U32]
++		__attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+ 	struct {
+ 		struct cword encrypt;
+ 		struct cword decrypt;
+ 	} cword;
+ 	u32 *D;
+-	int key_length;
+-	u32 E[AES_EXTENDED_KEY_SIZE]
+-		__attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+-	u32 d_data[AES_EXTENDED_KEY_SIZE]
+-		__attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+ };
+ 
+-/* ====== Key management routines ====== */
+-
+-static inline uint32_t
+-generic_rotr32 (const uint32_t x, const unsigned bits)
+-{
+-	const unsigned n = bits % 32;
+-	return (x >> n) | (x << (32 - n));
+-}
+-
+-static inline uint32_t
+-generic_rotl32 (const uint32_t x, const unsigned bits)
+-{
+-	const unsigned n = bits % 32;
+-	return (x << n) | (x >> (32 - n));
+-}
+-
+-#define rotl generic_rotl32
+-#define rotr generic_rotr32
+-
+-/*
+- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) 
+- */
+-static inline uint8_t
+-byte(const uint32_t x, const unsigned n)
+-{
+-	return x >> (n << 3);
+-}
+-
+-#define E_KEY ctx->E
+-#define D_KEY ctx->D
+-
+-static uint8_t pow_tab[256];
+-static uint8_t log_tab[256];
+-static uint8_t sbx_tab[256];
+-static uint8_t isb_tab[256];
+-static uint32_t rco_tab[10];
+-static uint32_t ft_tab[4][256];
+-static uint32_t it_tab[4][256];
+-
+-static uint32_t fl_tab[4][256];
+-static uint32_t il_tab[4][256];
+-
+-static inline uint8_t
+-f_mult (uint8_t a, uint8_t b)
+-{
+-	uint8_t aa = log_tab[a], cc = aa + log_tab[b];
+-
+-	return pow_tab[cc + (cc < aa ? 1 : 0)];
+-}
+-
+-#define ff_mult(a,b)    (a && b ? f_mult(a, b) : 0)
+-
+-#define f_rn(bo, bi, n, k)					\
+-    bo[n] =  ft_tab[0][byte(bi[n],0)] ^				\
+-             ft_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+-             ft_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+-             ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+-
+-#define i_rn(bo, bi, n, k)					\
+-    bo[n] =  it_tab[0][byte(bi[n],0)] ^				\
+-             it_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+-             it_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+-             it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+-
+-#define ls_box(x)				\
+-    ( fl_tab[0][byte(x, 0)] ^			\
+-      fl_tab[1][byte(x, 1)] ^			\
+-      fl_tab[2][byte(x, 2)] ^			\
+-      fl_tab[3][byte(x, 3)] )
+-
+-#define f_rl(bo, bi, n, k)					\
+-    bo[n] =  fl_tab[0][byte(bi[n],0)] ^				\
+-             fl_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+-             fl_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+-             fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+-
+-#define i_rl(bo, bi, n, k)					\
+-    bo[n] =  il_tab[0][byte(bi[n],0)] ^				\
+-             il_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+-             il_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+-             il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+-
+-static void
+-gen_tabs (void)
+-{
+-	uint32_t i, t;
+-	uint8_t p, q;
+-
+-	/* log and power tables for GF(2**8) finite field with
+-	   0x011b as modular polynomial - the simplest prmitive
+-	   root is 0x03, used here to generate the tables */
+-
+-	for (i = 0, p = 1; i < 256; ++i) {
+-		pow_tab[i] = (uint8_t) p;
+-		log_tab[p] = (uint8_t) i;
+-
+-		p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+-	}
+-
+-	log_tab[1] = 0;
+-
+-	for (i = 0, p = 1; i < 10; ++i) {
+-		rco_tab[i] = p;
+-
+-		p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+-	}
+-
+-	for (i = 0; i < 256; ++i) {
+-		p = (i ? pow_tab[255 - log_tab[i]] : 0);
+-		q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
+-		p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
+-		sbx_tab[i] = p;
+-		isb_tab[p] = (uint8_t) i;
+-	}
+-
+-	for (i = 0; i < 256; ++i) {
+-		p = sbx_tab[i];
+-
+-		t = p;
+-		fl_tab[0][i] = t;
+-		fl_tab[1][i] = rotl (t, 8);
+-		fl_tab[2][i] = rotl (t, 16);
+-		fl_tab[3][i] = rotl (t, 24);
+-
+-		t = ((uint32_t) ff_mult (2, p)) |
+-		    ((uint32_t) p << 8) |
+-		    ((uint32_t) p << 16) | ((uint32_t) ff_mult (3, p) << 24);
+-
+-		ft_tab[0][i] = t;
+-		ft_tab[1][i] = rotl (t, 8);
+-		ft_tab[2][i] = rotl (t, 16);
+-		ft_tab[3][i] = rotl (t, 24);
+-
+-		p = isb_tab[i];
+-
+-		t = p;
+-		il_tab[0][i] = t;
+-		il_tab[1][i] = rotl (t, 8);
+-		il_tab[2][i] = rotl (t, 16);
+-		il_tab[3][i] = rotl (t, 24);
+-
+-		t = ((uint32_t) ff_mult (14, p)) |
+-		    ((uint32_t) ff_mult (9, p) << 8) |
+-		    ((uint32_t) ff_mult (13, p) << 16) |
+-		    ((uint32_t) ff_mult (11, p) << 24);
+-
+-		it_tab[0][i] = t;
+-		it_tab[1][i] = rotl (t, 8);
+-		it_tab[2][i] = rotl (t, 16);
+-		it_tab[3][i] = rotl (t, 24);
+-	}
+-}
+-
+-#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+-
+-#define imix_col(y,x)       \
+-    u   = star_x(x);        \
+-    v   = star_x(u);        \
+-    w   = star_x(v);        \
+-    t   = w ^ (x);          \
+-   (y)  = u ^ v ^ w;        \
+-   (y) ^= rotr(u ^ t,  8) ^ \
+-          rotr(v ^ t, 16) ^ \
+-          rotr(t,24)
+-
+-/* initialise the key schedule from the user supplied key */
+-
+-#define loop4(i)                                    \
+-{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+-    t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;    \
+-    t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;    \
+-    t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;    \
+-    t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t;    \
+-}
+-
+-#define loop6(i)                                    \
+-{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+-    t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;    \
+-    t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;    \
+-    t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;    \
+-    t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t;    \
+-    t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t;   \
+-    t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t;   \
+-}
+-
+-#define loop8(i)                                    \
+-{   t = rotr(t,  8); ; t = ls_box(t) ^ rco_tab[i];  \
+-    t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;    \
+-    t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;    \
+-    t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;   \
+-    t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t;   \
+-    t  = E_KEY[8 * i + 4] ^ ls_box(t);    \
+-    E_KEY[8 * i + 12] = t;                \
+-    t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t;   \
+-    t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t;   \
+-    t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;   \
+-}
+-
+ /* Tells whether the ACE is capable to generate
+    the extended key for a given key_len. */
+ static inline int
+@@ -321,17 +87,13 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 	struct aes_ctx *ctx = aes_ctx(tfm);
+ 	const __le32 *key = (const __le32 *)in_key;
+ 	u32 *flags = &tfm->crt_flags;
+-	uint32_t i, t, u, v, w;
+-	uint32_t P[AES_EXTENDED_KEY_SIZE];
+-	uint32_t rounds;
++	struct crypto_aes_ctx gen_aes;
+ 
+ 	if (key_len % 8) {
+ 		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ 		return -EINVAL;
+ 	}
+ 
+-	ctx->key_length = key_len;
+-
+ 	/*
+ 	 * If the hardware is capable of generating the extended key
+ 	 * itself we must supply the plain key for both encryption
+@@ -339,10 +101,10 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 	 */
+ 	ctx->D = ctx->E;
+ 
+-	E_KEY[0] = le32_to_cpu(key[0]);
+-	E_KEY[1] = le32_to_cpu(key[1]);
+-	E_KEY[2] = le32_to_cpu(key[2]);
+-	E_KEY[3] = le32_to_cpu(key[3]);
++	ctx->E[0] = le32_to_cpu(key[0]);
++	ctx->E[1] = le32_to_cpu(key[1]);
++	ctx->E[2] = le32_to_cpu(key[2]);
++	ctx->E[3] = le32_to_cpu(key[3]);
+ 
+ 	/* Prepare control words. */
+ 	memset(&ctx->cword, 0, sizeof(ctx->cword));
+@@ -361,56 +123,13 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 	ctx->cword.encrypt.keygen = 1;
+ 	ctx->cword.decrypt.keygen = 1;
+ 
+-	switch (key_len) {
+-	case 16:
+-		t = E_KEY[3];
+-		for (i = 0; i < 10; ++i)
+-			loop4 (i);
+-		break;
+-
+-	case 24:
+-		E_KEY[4] = le32_to_cpu(key[4]);
+-		t = E_KEY[5] = le32_to_cpu(key[5]);
+-		for (i = 0; i < 8; ++i)
+-			loop6 (i);
+-		break;
+-
+-	case 32:
+-		E_KEY[4] = le32_to_cpu(key[4]);
+-		E_KEY[5] = le32_to_cpu(key[5]);
+-		E_KEY[6] = le32_to_cpu(key[6]);
+-		t = E_KEY[7] = le32_to_cpu(key[7]);
+-		for (i = 0; i < 7; ++i)
+-			loop8 (i);
+-		break;
+-	}
+-
+-	D_KEY[0] = E_KEY[0];
+-	D_KEY[1] = E_KEY[1];
+-	D_KEY[2] = E_KEY[2];
+-	D_KEY[3] = E_KEY[3];
+-
+-	for (i = 4; i < key_len + 24; ++i) {
+-		imix_col (D_KEY[i], E_KEY[i]);
+-	}
+-
+-	/* PadLock needs a different format of the decryption key. */
+-	rounds = 10 + (key_len - 16) / 4;
+-
+-	for (i = 0; i < rounds; i++) {
+-		P[((i + 1) * 4) + 0] = D_KEY[((rounds - i - 1) * 4) + 0];
+-		P[((i + 1) * 4) + 1] = D_KEY[((rounds - i - 1) * 4) + 1];
+-		P[((i + 1) * 4) + 2] = D_KEY[((rounds - i - 1) * 4) + 2];
+-		P[((i + 1) * 4) + 3] = D_KEY[((rounds - i - 1) * 4) + 3];
++	if (crypto_aes_expand_key(&gen_aes, in_key, key_len)) {
++		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++		return -EINVAL;
+ 	}
+ 
+-	P[0] = E_KEY[(rounds * 4) + 0];
+-	P[1] = E_KEY[(rounds * 4) + 1];
+-	P[2] = E_KEY[(rounds * 4) + 2];
+-	P[3] = E_KEY[(rounds * 4) + 3];
+-
+-	memcpy(D_KEY, P, AES_EXTENDED_KEY_SIZE_B);
+-
++	memcpy(ctx->E, gen_aes.key_enc, AES_MAX_KEYLENGTH);
++	memcpy(ctx->D, gen_aes.key_dec, AES_MAX_KEYLENGTH);
+ 	return 0;
+ }
+ 
+@@ -675,7 +394,6 @@ static int __init padlock_init(void)
+ 		return -ENODEV;
+ 	}
+ 
+-	gen_tabs();
+ 	if ((ret = crypto_register_alg(&aes_alg)))
+ 		goto aes_err;
+ 
+diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
+index 27340a7..6239c3d 100644
+--- a/drivers/dma/Kconfig
++++ b/drivers/dma/Kconfig
+@@ -46,14 +46,6 @@ config FSL_DMA
+ 	  MPC8560/40, MPC8555, MPC8548 and MPC8641 processors.
+ 	  The MPC8349, MPC8360 is also supported.
+ 
+-config FSL_DMA_SELFTEST
+-	bool "Enable the self test for each DMA channel"
+-	depends on FSL_DMA
+-	default y
+-	---help---
+-	  Enable the self test for each DMA channel. A self test will be
+-	  performed after the channel probed to ensure the DMA works well.
+-
+ config DMA_ENGINE
+ 	bool
+ 
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index 8db0e7f..97b329e 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -42,9 +42,9 @@
+  *
+  * Each device has a kref, which is initialized to 1 when the device is
+  * registered. A kref_get is done for each device registered.  When the
+- * device is released, the coresponding kref_put is done in the release
++ * device is released, the corresponding kref_put is done in the release
+  * method. Every time one of the device's channels is allocated to a client,
+- * a kref_get occurs.  When the channel is freed, the coresponding kref_put
++ * a kref_get occurs.  When the channel is freed, the corresponding kref_put
+  * happens. The device's release function does a completion, so
+  * unregister_device does a remove event, device_unregister, a kref_put
+  * for the first reference, then waits on the completion for all other
+@@ -53,7 +53,7 @@
+  * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
+  * with a kref and a per_cpu local_t.  A dma_chan_get is called when a client
+  * signals that it wants to use a channel, and dma_chan_put is called when
+- * a channel is removed or a client using it is unregesitered.  A client can
++ * a channel is removed or a client using it is unregistered.  A client can
+  * take extra references per outstanding transaction, as is the case with
+  * the NET DMA client.  The release function does a kref_put on the device.
+  *	-ChrisL, DanW
+@@ -362,7 +362,6 @@ int dma_async_device_register(struct dma_device *device)
+ 
+ 	BUG_ON(!device->device_alloc_chan_resources);
+ 	BUG_ON(!device->device_free_chan_resources);
+-	BUG_ON(!device->device_dependency_added);
+ 	BUG_ON(!device->device_is_tx_complete);
+ 	BUG_ON(!device->device_issue_pending);
+ 	BUG_ON(!device->dev);
+@@ -479,7 +478,8 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+ 
+ 	dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
+ 	dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
+-	tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
++	tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
++					 DMA_CTRL_ACK);
+ 
+ 	if (!tx) {
+ 		dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
+@@ -487,7 +487,6 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+ 		return -ENOMEM;
+ 	}
+ 
+-	tx->ack = 1;
+ 	tx->callback = NULL;
+ 	cookie = tx->tx_submit(tx);
+ 
+@@ -525,7 +524,8 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+ 
+ 	dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
+ 	dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
+-	tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
++	tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
++					 DMA_CTRL_ACK);
+ 
+ 	if (!tx) {
+ 		dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
+@@ -533,7 +533,6 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+ 		return -ENOMEM;
+ 	}
+ 
+-	tx->ack = 1;
+ 	tx->callback = NULL;
+ 	cookie = tx->tx_submit(tx);
+ 
+@@ -574,7 +573,8 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+ 	dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
+ 	dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len,
+ 				DMA_FROM_DEVICE);
+-	tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
++	tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
++					 DMA_CTRL_ACK);
+ 
+ 	if (!tx) {
+ 		dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE);
+@@ -582,7 +582,6 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+ 		return -ENOMEM;
+ 	}
+ 
+-	tx->ack = 1;
+ 	tx->callback = NULL;
+ 	cookie = tx->tx_submit(tx);
+ 
+@@ -600,8 +599,6 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+ {
+ 	tx->chan = chan;
+ 	spin_lock_init(&tx->lock);
+-	INIT_LIST_HEAD(&tx->depend_node);
+-	INIT_LIST_HEAD(&tx->depend_list);
+ }
+ EXPORT_SYMBOL(dma_async_tx_descriptor_init);
+ 
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index df16368..054eabf 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -412,7 +412,7 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
+ }
+ 
+ static struct dma_async_tx_descriptor *
+-fsl_dma_prep_interrupt(struct dma_chan *chan)
++fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
+ {
+ 	struct fsl_dma_chan *fsl_chan;
+ 	struct fsl_desc_sw *new;
+@@ -429,7 +429,7 @@ fsl_dma_prep_interrupt(struct dma_chan *chan)
+ 	}
+ 
+ 	new->async_tx.cookie = -EBUSY;
+-	new->async_tx.ack = 0;
++	new->async_tx.flags = flags;
+ 
+ 	/* Insert the link descriptor to the LD ring */
+ 	list_add_tail(&new->node, &new->async_tx.tx_list);
+@@ -482,7 +482,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 			set_desc_next(fsl_chan, &prev->hw, new->async_tx.phys);
+ 
+ 		new->async_tx.cookie = 0;
+-		new->async_tx.ack = 1;
++		async_tx_ack(&new->async_tx);
+ 
+ 		prev = new;
+ 		len -= copy;
+@@ -493,7 +493,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ 		list_add_tail(&new->node, &first->async_tx.tx_list);
+ 	} while (len);
+ 
+-	new->async_tx.ack = 0; /* client is in control of this ack */
++	new->async_tx.flags = flags; /* client is in control of this ack */
+ 	new->async_tx.cookie = -EBUSY;
+ 
+ 	/* Set End-of-link to the last link descriptor of new list*/
+@@ -658,13 +658,6 @@ static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
+ 	fsl_chan_xfer_ld_queue(fsl_chan);
+ }
+ 
+-static void fsl_dma_dependency_added(struct dma_chan *chan)
+-{
+-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+-
+-	fsl_chan_ld_cleanup(fsl_chan);
+-}
+-
+ /**
+  * fsl_dma_is_complete - Determine the DMA status
+  * @fsl_chan : Freescale DMA channel
+@@ -696,6 +689,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ {
+ 	struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
+ 	u32 stat;
++	int update_cookie = 0;
++	int xfer_ld_q = 0;
+ 
+ 	stat = get_sr(fsl_chan);
+ 	dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n",
+@@ -720,8 +715,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ 			 * Now, update the completed cookie, and continue the
+ 			 * next uncompleted transfer.
+ 			 */
+-			fsl_dma_update_completed_cookie(fsl_chan);
+-			fsl_chan_xfer_ld_queue(fsl_chan);
++			update_cookie = 1;
++			xfer_ld_q = 1;
+ 		}
+ 		stat &= ~FSL_DMA_SR_PE;
+ 	}
+@@ -734,19 +729,33 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ 		dev_dbg(fsl_chan->dev, "event: clndar %p, nlndar %p\n",
+ 			(void *)get_cdar(fsl_chan), (void *)get_ndar(fsl_chan));
+ 		stat &= ~FSL_DMA_SR_EOSI;
+-		fsl_dma_update_completed_cookie(fsl_chan);
++		update_cookie = 1;
++	}
++
++	/* For MPC8349, EOCDI event need to update cookie
++	 * and start the next transfer if it exist.
++	 */
++	if (stat & FSL_DMA_SR_EOCDI) {
++		dev_dbg(fsl_chan->dev, "event: End-of-Chain link INT\n");
++		stat &= ~FSL_DMA_SR_EOCDI;
++		update_cookie = 1;
++		xfer_ld_q = 1;
+ 	}
+ 
+ 	/* If it current transfer is the end-of-transfer,
+ 	 * we should clear the Channel Start bit for
+ 	 * prepare next transfer.
+ 	 */
+-	if (stat & (FSL_DMA_SR_EOLNI | FSL_DMA_SR_EOCDI)) {
++	if (stat & FSL_DMA_SR_EOLNI) {
+ 		dev_dbg(fsl_chan->dev, "event: End-of-link INT\n");
+ 		stat &= ~FSL_DMA_SR_EOLNI;
+-		fsl_chan_xfer_ld_queue(fsl_chan);
++		xfer_ld_q = 1;
+ 	}
+ 
++	if (update_cookie)
++		fsl_dma_update_completed_cookie(fsl_chan);
++	if (xfer_ld_q)
++		fsl_chan_xfer_ld_queue(fsl_chan);
+ 	if (stat)
+ 		dev_dbg(fsl_chan->dev, "event: unhandled sr 0x%02x\n",
+ 					stat);
+@@ -776,15 +785,13 @@ static void dma_do_tasklet(unsigned long data)
+ 	fsl_chan_ld_cleanup(fsl_chan);
+ }
+ 
+-#ifdef FSL_DMA_CALLBACKTEST
+-static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan)
++static void fsl_dma_callback_test(void *param)
+ {
++	struct fsl_dma_chan *fsl_chan = param;
+ 	if (fsl_chan)
+-		dev_info(fsl_chan->dev, "selftest: callback is ok!\n");
++		dev_dbg(fsl_chan->dev, "selftest: callback is ok!\n");
+ }
+-#endif
+ 
+-#ifdef CONFIG_FSL_DMA_SELFTEST
+ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ {
+ 	struct dma_chan *chan;
+@@ -867,7 +874,7 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ 	async_tx_ack(tx3);
+ 
+ 	/* Interrupt tx test */
+-	tx1 = fsl_dma_prep_interrupt(chan);
++	tx1 = fsl_dma_prep_interrupt(chan, 0);
+ 	async_tx_ack(tx1);
+ 	cookie = fsl_dma_tx_submit(tx1);
+ 
+@@ -875,13 +882,11 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ 	cookie = fsl_dma_tx_submit(tx3);
+ 	cookie = fsl_dma_tx_submit(tx2);
+ 
+-#ifdef FSL_DMA_CALLBACKTEST
+ 	if (dma_has_cap(DMA_INTERRUPT, ((struct fsl_dma_device *)
+ 	    dev_get_drvdata(fsl_chan->dev->parent))->common.cap_mask)) {
+ 		tx3->callback = fsl_dma_callback_test;
+ 		tx3->callback_param = fsl_chan;
+ 	}
+-#endif
+ 	fsl_dma_memcpy_issue_pending(chan);
+ 	msleep(2);
+ 
+@@ -906,7 +911,6 @@ out:
+ 	kfree(src);
+ 	return err;
+ }
+-#endif
+ 
+ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
+ 			const struct of_device_id *match)
+@@ -997,11 +1001,9 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
+ 		}
+ 	}
+ 
+-#ifdef CONFIG_FSL_DMA_SELFTEST
+ 	err = fsl_dma_self_test(new_fsl_chan);
+ 	if (err)
+ 		goto err;
+-#endif
+ 
+ 	dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
+ 				match->compatible, new_fsl_chan->irq);
+@@ -1080,7 +1082,6 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ 	fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
+ 	fdev->common.device_is_tx_complete = fsl_dma_is_complete;
+ 	fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
+-	fdev->common.device_dependency_added = fsl_dma_dependency_added;
+ 	fdev->common.dev = &dev->dev;
+ 
+ 	irq = irq_of_parse_and_map(dev->node, 0);
+diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
+index 4017d9e..318e8a2 100644
+--- a/drivers/dma/ioat_dma.c
++++ b/drivers/dma/ioat_dma.c
+@@ -212,14 +212,14 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	u32 copy;
+ 	size_t len;
+ 	dma_addr_t src, dst;
+-	int orig_ack;
++	unsigned long orig_flags;
+ 	unsigned int desc_count = 0;
+ 
+ 	/* src and dest and len are stored in the initial descriptor */
+ 	len = first->len;
+ 	src = first->src;
+ 	dst = first->dst;
+-	orig_ack = first->async_tx.ack;
++	orig_flags = first->async_tx.flags;
+ 	new = first;
+ 
+ 	spin_lock_bh(&ioat_chan->desc_lock);
+@@ -228,7 +228,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	do {
+ 		copy = min_t(size_t, len, ioat_chan->xfercap);
+ 
+-		new->async_tx.ack = 1;
++		async_tx_ack(&new->async_tx);
+ 
+ 		hw = new->hw;
+ 		hw->size = copy;
+@@ -264,7 +264,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	}
+ 
+ 	new->tx_cnt = desc_count;
+-	new->async_tx.ack = orig_ack; /* client is in control of this ack */
++	new->async_tx.flags = orig_flags; /* client is in control of this ack */
+ 
+ 	/* store the original values for use in later cleanup */
+ 	if (new != first) {
+@@ -304,14 +304,14 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	u32 copy;
+ 	size_t len;
+ 	dma_addr_t src, dst;
+-	int orig_ack;
++	unsigned long orig_flags;
+ 	unsigned int desc_count = 0;
+ 
+ 	/* src and dest and len are stored in the initial descriptor */
+ 	len = first->len;
+ 	src = first->src;
+ 	dst = first->dst;
+-	orig_ack = first->async_tx.ack;
++	orig_flags = first->async_tx.flags;
+ 	new = first;
+ 
+ 	/*
+@@ -321,7 +321,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	do {
+ 		copy = min_t(size_t, len, ioat_chan->xfercap);
+ 
+-		new->async_tx.ack = 1;
++		async_tx_ack(&new->async_tx);
+ 
+ 		hw = new->hw;
+ 		hw->size = copy;
+@@ -349,7 +349,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ 	}
+ 
+ 	new->tx_cnt = desc_count;
+-	new->async_tx.ack = orig_ack; /* client is in control of this ack */
++	new->async_tx.flags = orig_flags; /* client is in control of this ack */
+ 
+ 	/* store the original values for use in later cleanup */
+ 	if (new != first) {
+@@ -714,7 +714,7 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
+ 		new->len = len;
+ 		new->dst = dma_dest;
+ 		new->src = dma_src;
+-		new->async_tx.ack = 0;
++		new->async_tx.flags = flags;
+ 		return &new->async_tx;
+ 	} else
+ 		return NULL;
+@@ -742,7 +742,7 @@ static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
+ 		new->len = len;
+ 		new->dst = dma_dest;
+ 		new->src = dma_src;
+-		new->async_tx.ack = 0;
++		new->async_tx.flags = flags;
+ 		return &new->async_tx;
+ 	} else
+ 		return NULL;
+@@ -842,7 +842,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
+ 				 * a completed entry, but not the last, so clean
+ 				 * up if the client is done with the descriptor
+ 				 */
+-				if (desc->async_tx.ack) {
++				if (async_tx_test_ack(&desc->async_tx)) {
+ 					list_del(&desc->node);
+ 					list_add_tail(&desc->node,
+ 						      &ioat_chan->free_desc);
+@@ -924,17 +924,6 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
+ 	spin_unlock_bh(&ioat_chan->cleanup_lock);
+ }
+ 
+-static void ioat_dma_dependency_added(struct dma_chan *chan)
+-{
+-	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+-	spin_lock_bh(&ioat_chan->desc_lock);
+-	if (ioat_chan->pending == 0) {
+-		spin_unlock_bh(&ioat_chan->desc_lock);
+-		ioat_dma_memcpy_cleanup(ioat_chan);
+-	} else
+-		spin_unlock_bh(&ioat_chan->desc_lock);
+-}
+-
+ /**
+  * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
+  * @chan: IOAT DMA channel handle
+@@ -990,7 +979,7 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
+ 	desc->hw->size = 0;
+ 	desc->hw->src_addr = 0;
+ 	desc->hw->dst_addr = 0;
+-	desc->async_tx.ack = 1;
++	async_tx_ack(&desc->async_tx);
+ 	switch (ioat_chan->device->version) {
+ 	case IOAT_VER_1_2:
+ 		desc->hw->next = 0;
+@@ -1316,7 +1305,6 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
+ 
+ 	dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
+ 	device->common.device_is_tx_complete = ioat_dma_is_complete;
+-	device->common.device_dependency_added = ioat_dma_dependency_added;
+ 	switch (device->version) {
+ 	case IOAT_VER_1_2:
+ 		device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy;
+diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
+index f82b090..762b729 100644
+--- a/drivers/dma/iop-adma.c
++++ b/drivers/dma/iop-adma.c
+@@ -63,7 +63,6 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+ 	struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
+ {
+ 	BUG_ON(desc->async_tx.cookie < 0);
+-	spin_lock_bh(&desc->async_tx.lock);
+ 	if (desc->async_tx.cookie > 0) {
+ 		cookie = desc->async_tx.cookie;
+ 		desc->async_tx.cookie = 0;
+@@ -101,7 +100,6 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+ 
+ 	/* run dependent operations */
+ 	async_tx_run_dependencies(&desc->async_tx);
+-	spin_unlock_bh(&desc->async_tx.lock);
+ 
+ 	return cookie;
+ }
+@@ -113,7 +111,7 @@ iop_adma_clean_slot(struct iop_adma_desc_slot *desc,
+ 	/* the client is allowed to attach dependent operations
+ 	 * until 'ack' is set
+ 	 */
+-	if (!desc->async_tx.ack)
++	if (!async_tx_test_ack(&desc->async_tx))
+ 		return 0;
+ 
+ 	/* leave the last descriptor in the chain
+@@ -150,7 +148,7 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+ 			"this_desc: %#x next_desc: %#x ack: %d\n",
+ 			iter->async_tx.cookie, iter->idx, busy,
+ 			iter->async_tx.phys, iop_desc_get_next_desc(iter),
+-			iter->async_tx.ack);
++			async_tx_test_ack(&iter->async_tx));
+ 		prefetch(_iter);
+ 		prefetch(&_iter->async_tx);
+ 
+@@ -257,8 +255,6 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+ 
+ 	BUG_ON(!seen_current);
+ 
+-	iop_chan_idle(busy, iop_chan);
+-
+ 	if (cookie > 0) {
+ 		iop_chan->completed_cookie = cookie;
+ 		pr_debug("\tcompleted cookie %d\n", cookie);
+@@ -275,8 +271,11 @@ iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+ 
+ static void iop_adma_tasklet(unsigned long data)
+ {
+-	struct iop_adma_chan *chan = (struct iop_adma_chan *) data;
+-	__iop_adma_slot_cleanup(chan);
++	struct iop_adma_chan *iop_chan = (struct iop_adma_chan *) data;
++
++	spin_lock(&iop_chan->lock);
++	__iop_adma_slot_cleanup(iop_chan);
++	spin_unlock(&iop_chan->lock);
+ }
+ 
+ static struct iop_adma_desc_slot *
+@@ -339,9 +338,7 @@ retry:
+ 
+ 				/* pre-ack all but the last descriptor */
+ 				if (num_slots != slots_per_op)
+-					iter->async_tx.ack = 1;
+-				else
+-					iter->async_tx.ack = 0;
++					async_tx_ack(&iter->async_tx);
+ 
+ 				list_add_tail(&iter->chain_node, &chain);
+ 				alloc_tail = iter;
+@@ -514,7 +511,7 @@ static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+ }
+ 
+ static struct dma_async_tx_descriptor *
+-iop_adma_prep_dma_interrupt(struct dma_chan *chan)
++iop_adma_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags)
+ {
+ 	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ 	struct iop_adma_desc_slot *sw_desc, *grp_start;
+@@ -529,6 +526,7 @@ iop_adma_prep_dma_interrupt(struct dma_chan *chan)
+ 		grp_start = sw_desc->group_head;
+ 		iop_desc_init_interrupt(grp_start, iop_chan);
+ 		grp_start->unmap_len = 0;
++		sw_desc->async_tx.flags = flags;
+ 	}
+ 	spin_unlock_bh(&iop_chan->lock);
+ 
+@@ -561,6 +559,7 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
+ 		iop_desc_set_memcpy_src_addr(grp_start, dma_src);
+ 		sw_desc->unmap_src_cnt = 1;
+ 		sw_desc->unmap_len = len;
++		sw_desc->async_tx.flags = flags;
+ 	}
+ 	spin_unlock_bh(&iop_chan->lock);
+ 
+@@ -593,6 +592,7 @@ iop_adma_prep_dma_memset(struct dma_chan *chan, dma_addr_t dma_dest,
+ 		iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
+ 		sw_desc->unmap_src_cnt = 1;
+ 		sw_desc->unmap_len = len;
++		sw_desc->async_tx.flags = flags;
+ 	}
+ 	spin_unlock_bh(&iop_chan->lock);
+ 
+@@ -626,6 +626,7 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,
+ 		iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
+ 		sw_desc->unmap_src_cnt = src_cnt;
+ 		sw_desc->unmap_len = len;
++		sw_desc->async_tx.flags = flags;
+ 		while (src_cnt--)
+ 			iop_desc_set_xor_src_addr(grp_start, src_cnt,
+ 						  dma_src[src_cnt]);
+@@ -662,6 +663,7 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
+ 			__func__, grp_start->xor_check_result);
+ 		sw_desc->unmap_src_cnt = src_cnt;
+ 		sw_desc->unmap_len = len;
++		sw_desc->async_tx.flags = flags;
+ 		while (src_cnt--)
+ 			iop_desc_set_zero_sum_src_addr(grp_start, src_cnt,
+ 						       dma_src[src_cnt]);
+@@ -671,12 +673,6 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
+ 	return sw_desc ? &sw_desc->async_tx : NULL;
+ }
+ 
+-static void iop_adma_dependency_added(struct dma_chan *chan)
+-{
+-	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+-	tasklet_schedule(&iop_chan->irq_tasklet);
+-}
+-
+ static void iop_adma_free_chan_resources(struct dma_chan *chan)
+ {
+ 	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+@@ -854,11 +850,11 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+ 	src_dma = dma_map_single(dma_chan->device->dev, src,
+ 				IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
+ 	tx = iop_adma_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
+-				      IOP_ADMA_TEST_SIZE, 1);
++				      IOP_ADMA_TEST_SIZE,
++				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ 
+ 	cookie = iop_adma_tx_submit(tx);
+ 	iop_adma_issue_pending(dma_chan);
+-	async_tx_ack(tx);
+ 	msleep(1);
+ 
+ 	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+@@ -954,11 +950,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ 		dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+ 					   0, PAGE_SIZE, DMA_TO_DEVICE);
+ 	tx = iop_adma_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
+-				   IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE, 1);
++				   IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE,
++				   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ 
+ 	cookie = iop_adma_tx_submit(tx);
+ 	iop_adma_issue_pending(dma_chan);
+-	async_tx_ack(tx);
+ 	msleep(8);
+ 
+ 	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+@@ -1001,11 +997,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ 					   DMA_TO_DEVICE);
+ 	tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs,
+ 					IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
+-					&zero_sum_result, 1);
++					&zero_sum_result,
++					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ 
+ 	cookie = iop_adma_tx_submit(tx);
+ 	iop_adma_issue_pending(dma_chan);
+-	async_tx_ack(tx);
+ 	msleep(8);
+ 
+ 	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+@@ -1025,11 +1021,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ 	/* test memset */
+ 	dma_addr = dma_map_page(dma_chan->device->dev, dest, 0,
+ 			PAGE_SIZE, DMA_FROM_DEVICE);
+-	tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE, 1);
++	tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE,
++				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ 
+ 	cookie = iop_adma_tx_submit(tx);
+ 	iop_adma_issue_pending(dma_chan);
+-	async_tx_ack(tx);
+ 	msleep(8);
+ 
+ 	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+@@ -1057,11 +1053,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ 					   DMA_TO_DEVICE);
+ 	tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs,
+ 					IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
+-					&zero_sum_result, 1);
++					&zero_sum_result,
++					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ 
+ 	cookie = iop_adma_tx_submit(tx);
+ 	iop_adma_issue_pending(dma_chan);
+-	async_tx_ack(tx);
+ 	msleep(8);
+ 
+ 	if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+@@ -1177,7 +1173,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
+ 	dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
+ 	dma_dev->device_is_tx_complete = iop_adma_is_complete;
+ 	dma_dev->device_issue_pending = iop_adma_issue_pending;
+-	dma_dev->device_dependency_added = iop_adma_dependency_added;
+ 	dma_dev->dev = &pdev->dev;
+ 
+ 	/* set prep routines based on capability */
+@@ -1232,9 +1227,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	spin_lock_init(&iop_chan->lock);
+-	init_timer(&iop_chan->cleanup_watchdog);
+-	iop_chan->cleanup_watchdog.data = (unsigned long) iop_chan;
+-	iop_chan->cleanup_watchdog.function = iop_adma_tasklet;
+ 	INIT_LIST_HEAD(&iop_chan->chain);
+ 	INIT_LIST_HEAD(&iop_chan->all_slots);
+ 	INIT_RCU_HEAD(&iop_chan->common.rcu);
+@@ -1298,7 +1290,7 @@ static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
+ 		grp_start = sw_desc->group_head;
+ 
+ 		list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+-		sw_desc->async_tx.ack = 1;
++		async_tx_ack(&sw_desc->async_tx);
+ 		iop_desc_init_memcpy(grp_start, 0);
+ 		iop_desc_set_byte_count(grp_start, iop_chan, 0);
+ 		iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+@@ -1354,7 +1346,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
+ 	if (sw_desc) {
+ 		grp_start = sw_desc->group_head;
+ 		list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+-		sw_desc->async_tx.ack = 1;
++		async_tx_ack(&sw_desc->async_tx);
+ 		iop_desc_init_null_xor(grp_start, 2, 0);
+ 		iop_desc_set_byte_count(grp_start, iop_chan, 0);
+ 		iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
+index 25bdc2d..fb4d391 100644
+--- a/drivers/firewire/Kconfig
++++ b/drivers/firewire/Kconfig
+@@ -54,6 +54,11 @@ config FIREWIRE_OHCI
+ 	  directive, use "install modulename /bin/true" for the modules to be
+ 	  blacklisted.
+ 
++config FIREWIRE_OHCI_DEBUG
++	bool
++	depends on FIREWIRE_OHCI
++	default y
++
+ config FIREWIRE_SBP2
+ 	tristate "Support for storage devices (SBP-2 protocol driver)"
+ 	depends on FIREWIRE && SCSI
+diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
+index a034627..5b4c0d9 100644
+--- a/drivers/firewire/fw-card.c
++++ b/drivers/firewire/fw-card.c
+@@ -167,7 +167,6 @@ fw_core_add_descriptor(struct fw_descriptor *desc)
+ 
+ 	return 0;
+ }
+-EXPORT_SYMBOL(fw_core_add_descriptor);
+ 
+ void
+ fw_core_remove_descriptor(struct fw_descriptor *desc)
+@@ -182,7 +181,6 @@ fw_core_remove_descriptor(struct fw_descriptor *desc)
+ 
+ 	mutex_unlock(&card_mutex);
+ }
+-EXPORT_SYMBOL(fw_core_remove_descriptor);
+ 
+ static const char gap_count_table[] = {
+ 	63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
+@@ -220,7 +218,7 @@ fw_card_bm_work(struct work_struct *work)
+ 	struct bm_data bmd;
+ 	unsigned long flags;
+ 	int root_id, new_root_id, irm_id, gap_count, generation, grace;
+-	int do_reset = 0;
++	bool do_reset = false;
+ 
+ 	spin_lock_irqsave(&card->lock, flags);
+ 	local_node = card->local_node;
+@@ -331,7 +329,7 @@ fw_card_bm_work(struct work_struct *work)
+ 		 */
+ 		spin_unlock_irqrestore(&card->lock, flags);
+ 		goto out;
+-	} else if (root_device->config_rom[2] & BIB_CMC) {
++	} else if (root_device->cmc) {
+ 		/*
+ 		 * FIXME: I suppose we should set the cmstr bit in the
+ 		 * STATE_CLEAR register of this node, as described in
+@@ -360,14 +358,14 @@ fw_card_bm_work(struct work_struct *work)
+ 		gap_count = 63;
+ 
+ 	/*
+-	 * Finally, figure out if we should do a reset or not.  If we've
+-	 * done less that 5 resets with the same physical topology and we
++	 * Finally, figure out if we should do a reset or not.  If we have
++	 * done less than 5 resets with the same physical topology and we
+ 	 * have either a new root or a new gap count setting, let's do it.
+ 	 */
+ 
+ 	if (card->bm_retries++ < 5 &&
+ 	    (card->gap_count != gap_count || new_root_id != root_id))
+-		do_reset = 1;
++		do_reset = true;
+ 
+ 	spin_unlock_irqrestore(&card->lock, flags);
+ 
+@@ -398,7 +396,6 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver,
+ {
+ 	static atomic_t index = ATOMIC_INIT(-1);
+ 
+-	kref_init(&card->kref);
+ 	atomic_set(&card->device_count, 0);
+ 	card->index = atomic_inc_return(&index);
+ 	card->driver = driver;
+@@ -429,12 +426,6 @@ fw_card_add(struct fw_card *card,
+ 	card->link_speed = link_speed;
+ 	card->guid = guid;
+ 
+-	/*
+-	 * The subsystem grabs a reference when the card is added and
+-	 * drops it when the driver calls fw_core_remove_card.
+-	 */
+-	fw_card_get(card);
+-
+ 	mutex_lock(&card_mutex);
+ 	config_rom = generate_config_rom(card, &length);
+ 	list_add_tail(&card->link, &card_list);
+@@ -540,40 +531,9 @@ fw_core_remove_card(struct fw_card *card)
+ 	cancel_delayed_work_sync(&card->work);
+ 	fw_flush_transactions(card);
+ 	del_timer_sync(&card->flush_timer);
+-
+-	fw_card_put(card);
+ }
+ EXPORT_SYMBOL(fw_core_remove_card);
+ 
+-struct fw_card *
+-fw_card_get(struct fw_card *card)
+-{
+-	kref_get(&card->kref);
+-
+-	return card;
+-}
+-EXPORT_SYMBOL(fw_card_get);
+-
+-static void
+-release_card(struct kref *kref)
+-{
+-	struct fw_card *card = container_of(kref, struct fw_card, kref);
+-
+-	kfree(card);
+-}
+-
+-/*
+- * An assumption for fw_card_put() is that the card driver allocates
+- * the fw_card struct with kalloc and that it has been shut down
+- * before the last ref is dropped.
+- */
+-void
+-fw_card_put(struct fw_card *card)
+-{
+-	kref_put(&card->kref, release_card);
+-}
+-EXPORT_SYMBOL(fw_card_put);
+-
+ int
+ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
+ {
+diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
+index 46bc197..4a54192 100644
+--- a/drivers/firewire/fw-cdev.c
++++ b/drivers/firewire/fw-cdev.c
+@@ -269,21 +269,28 @@ static int ioctl_get_info(struct client *client, void *buffer)
+ {
+ 	struct fw_cdev_get_info *get_info = buffer;
+ 	struct fw_cdev_event_bus_reset bus_reset;
++	unsigned long ret = 0;
+ 
+ 	client->version = get_info->version;
+ 	get_info->version = FW_CDEV_VERSION;
+ 
++	down_read(&fw_device_rwsem);
++
+ 	if (get_info->rom != 0) {
+ 		void __user *uptr = u64_to_uptr(get_info->rom);
+ 		size_t want = get_info->rom_length;
+ 		size_t have = client->device->config_rom_length * 4;
+ 
+-		if (copy_to_user(uptr, client->device->config_rom,
+-				 min(want, have)))
+-			return -EFAULT;
++		ret = copy_to_user(uptr, client->device->config_rom,
++				   min(want, have));
+ 	}
+ 	get_info->rom_length = client->device->config_rom_length * 4;
+ 
++	up_read(&fw_device_rwsem);
++
++	if (ret != 0)
++		return -EFAULT;
++
+ 	client->bus_reset_closure = get_info->bus_reset_closure;
+ 	if (get_info->bus_reset != 0) {
+ 		void __user *uptr = u64_to_uptr(get_info->bus_reset);
+diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
+index 870125a..d9c8daf 100644
+--- a/drivers/firewire/fw-device.c
++++ b/drivers/firewire/fw-device.c
+@@ -25,8 +25,9 @@
+ #include <linux/device.h>
+ #include <linux/delay.h>
+ #include <linux/idr.h>
++#include <linux/string.h>
+ #include <linux/rwsem.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/system.h>
+ #include <linux/ctype.h>
+ #include "fw-transaction.h"
+@@ -160,9 +161,9 @@ static void fw_device_release(struct device *dev)
+ 	 * Take the card lock so we don't set this to NULL while a
+ 	 * FW_NODE_UPDATED callback is being handled.
+ 	 */
+-	spin_lock_irqsave(&device->card->lock, flags);
++	spin_lock_irqsave(&card->lock, flags);
+ 	device->node->data = NULL;
+-	spin_unlock_irqrestore(&device->card->lock, flags);
++	spin_unlock_irqrestore(&card->lock, flags);
+ 
+ 	fw_node_put(device->node);
+ 	kfree(device->config_rom);
+@@ -195,7 +196,9 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
+ 		container_of(dattr, struct config_rom_attribute, attr);
+ 	struct fw_csr_iterator ci;
+ 	u32 *dir;
+-	int key, value;
++	int key, value, ret = -ENOENT;
++
++	down_read(&fw_device_rwsem);
+ 
+ 	if (is_fw_unit(dev))
+ 		dir = fw_unit(dev)->directory;
+@@ -204,11 +207,15 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
+ 
+ 	fw_csr_iterator_init(&ci, dir);
+ 	while (fw_csr_iterator_next(&ci, &key, &value))
+-		if (attr->key == key)
+-			return snprintf(buf, buf ? PAGE_SIZE : 0,
+-					"0x%06x\n", value);
++		if (attr->key == key) {
++			ret = snprintf(buf, buf ? PAGE_SIZE : 0,
++				       "0x%06x\n", value);
++			break;
++		}
++
++	up_read(&fw_device_rwsem);
+ 
+-	return -ENOENT;
++	return ret;
+ }
+ 
+ #define IMMEDIATE_ATTR(name, key)				\
+@@ -221,9 +228,11 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+ 		container_of(dattr, struct config_rom_attribute, attr);
+ 	struct fw_csr_iterator ci;
+ 	u32 *dir, *block = NULL, *p, *end;
+-	int length, key, value, last_key = 0;
++	int length, key, value, last_key = 0, ret = -ENOENT;
+ 	char *b;
+ 
++	down_read(&fw_device_rwsem);
++
+ 	if (is_fw_unit(dev))
+ 		dir = fw_unit(dev)->directory;
+ 	else
+@@ -238,18 +247,20 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+ 	}
+ 
+ 	if (block == NULL)
+-		return -ENOENT;
++		goto out;
+ 
+ 	length = min(block[0] >> 16, 256U);
+ 	if (length < 3)
+-		return -ENOENT;
++		goto out;
+ 
+ 	if (block[1] != 0 || block[2] != 0)
+ 		/* Unknown encoding. */
+-		return -ENOENT;
++		goto out;
+ 
+-	if (buf == NULL)
+-		return length * 4;
++	if (buf == NULL) {
++		ret = length * 4;
++		goto out;
++	}
+ 
+ 	b = buf;
+ 	end = &block[length + 1];
+@@ -259,8 +270,11 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+ 	/* Strip trailing whitespace and add newline. */
+ 	while (b--, (isspace(*b) || *b == '\0') && b > buf);
+ 	strcpy(b + 1, "\n");
++	ret = b + 2 - buf;
++ out:
++	up_read(&fw_device_rwsem);
+ 
+-	return b + 2 - buf;
++	return ret;
+ }
+ 
+ #define TEXT_LEAF_ATTR(name, key)				\
+@@ -337,19 +351,28 @@ static ssize_t
+ config_rom_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ 	struct fw_device *device = fw_device(dev);
++	size_t length;
+ 
+-	memcpy(buf, device->config_rom, device->config_rom_length * 4);
++	down_read(&fw_device_rwsem);
++	length = device->config_rom_length * 4;
++	memcpy(buf, device->config_rom, length);
++	up_read(&fw_device_rwsem);
+ 
+-	return device->config_rom_length * 4;
++	return length;
+ }
+ 
+ static ssize_t
+ guid_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ 	struct fw_device *device = fw_device(dev);
++	int ret;
++
++	down_read(&fw_device_rwsem);
++	ret = snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
++		       device->config_rom[3], device->config_rom[4]);
++	up_read(&fw_device_rwsem);
+ 
+-	return snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
+-			device->config_rom[3], device->config_rom[4]);
++	return ret;
+ }
+ 
+ static struct device_attribute fw_device_attributes[] = {
+@@ -388,7 +411,7 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
+ 
+ 	init_completion(&callback_data.done);
+ 
+-	offset = 0xfffff0000400ULL + index * 4;
++	offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
+ 	fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
+ 			device->node_id, generation, device->max_speed,
+ 			offset, NULL, 4, complete_transaction, &callback_data);
+@@ -400,6 +423,9 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
+ 	return callback_data.rcode;
+ }
+ 
++#define READ_BIB_ROM_SIZE	256
++#define READ_BIB_STACK_SIZE	16
++
+ /*
+  * Read the bus info block, perform a speed probe, and read all of the rest of
+  * the config ROM.  We do all this with a cached bus generation.  If the bus
+@@ -409,16 +435,23 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
+  */
+ static int read_bus_info_block(struct fw_device *device, int generation)
+ {
+-	static u32 rom[256];
+-	u32 stack[16], sp, key;
+-	int i, end, length;
++	u32 *rom, *stack, *old_rom, *new_rom;
++	u32 sp, key;
++	int i, end, length, ret = -1;
++
++	rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE +
++		      sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL);
++	if (rom == NULL)
++		return -ENOMEM;
++
++	stack = &rom[READ_BIB_ROM_SIZE];
+ 
+ 	device->max_speed = SCODE_100;
+ 
+ 	/* First read the bus info block. */
+ 	for (i = 0; i < 5; i++) {
+ 		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+-			return -1;
++			goto out;
+ 		/*
+ 		 * As per IEEE1212 7.2, during power-up, devices can
+ 		 * reply with a 0 for the first quadlet of the config
+@@ -428,7 +461,7 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ 		 * retry mechanism will try again later.
+ 		 */
+ 		if (i == 0 && rom[i] == 0)
+-			return -1;
++			goto out;
+ 	}
+ 
+ 	device->max_speed = device->node->max_speed;
+@@ -478,26 +511,26 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ 		 */
+ 		key = stack[--sp];
+ 		i = key & 0xffffff;
+-		if (i >= ARRAY_SIZE(rom))
++		if (i >= READ_BIB_ROM_SIZE)
+ 			/*
+ 			 * The reference points outside the standard
+ 			 * config rom area, something's fishy.
+ 			 */
+-			return -1;
++			goto out;
+ 
+ 		/* Read header quadlet for the block to get the length. */
+ 		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+-			return -1;
++			goto out;
+ 		end = i + (rom[i] >> 16) + 1;
+ 		i++;
+-		if (end > ARRAY_SIZE(rom))
++		if (end > READ_BIB_ROM_SIZE)
+ 			/*
+ 			 * This block extends outside standard config
+ 			 * area (and the array we're reading it
+ 			 * into).  That's broken, so ignore this
+ 			 * device.
+ 			 */
+-			return -1;
++			goto out;
+ 
+ 		/*
+ 		 * Now read in the block.  If this is a directory
+@@ -507,9 +540,9 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ 		while (i < end) {
+ 			if (read_rom(device, generation, i, &rom[i]) !=
+ 			    RCODE_COMPLETE)
+-				return -1;
++				goto out;
+ 			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
+-			    sp < ARRAY_SIZE(stack))
++			    sp < READ_BIB_STACK_SIZE)
+ 				stack[sp++] = i + rom[i];
+ 			i++;
+ 		}
+@@ -517,13 +550,23 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ 			length = i;
+ 	}
+ 
+-	device->config_rom = kmalloc(length * 4, GFP_KERNEL);
+-	if (device->config_rom == NULL)
+-		return -1;
+-	memcpy(device->config_rom, rom, length * 4);
++	old_rom = device->config_rom;
++	new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
++	if (new_rom == NULL)
++		goto out;
++
++	down_write(&fw_device_rwsem);
++	device->config_rom = new_rom;
+ 	device->config_rom_length = length;
++	up_write(&fw_device_rwsem);
+ 
+-	return 0;
++	kfree(old_rom);
++	ret = 0;
++	device->cmc = rom[2] & 1 << 30;
++ out:
++	kfree(rom);
++
++	return ret;
+ }
+ 
+ static void fw_unit_release(struct device *dev)
+@@ -592,7 +635,14 @@ static int shutdown_unit(struct device *device, void *data)
+ 	return 0;
+ }
+ 
+-static DECLARE_RWSEM(idr_rwsem);
++/*
++ * fw_device_rwsem acts as dual purpose mutex:
++ *   - serializes accesses to fw_device_idr,
++ *   - serializes accesses to fw_device.config_rom/.config_rom_length and
++ *     fw_unit.directory, unless those accesses happen at safe occasions
++ */
++DECLARE_RWSEM(fw_device_rwsem);
++
+ static DEFINE_IDR(fw_device_idr);
+ int fw_cdev_major;
+ 
+@@ -600,11 +650,11 @@ struct fw_device *fw_device_get_by_devt(dev_t devt)
+ {
+ 	struct fw_device *device;
+ 
+-	down_read(&idr_rwsem);
++	down_read(&fw_device_rwsem);
+ 	device = idr_find(&fw_device_idr, MINOR(devt));
+ 	if (device)
+ 		fw_device_get(device);
+-	up_read(&idr_rwsem);
++	up_read(&fw_device_rwsem);
+ 
+ 	return device;
+ }
+@@ -619,9 +669,9 @@ static void fw_device_shutdown(struct work_struct *work)
+ 	device_for_each_child(&device->device, NULL, shutdown_unit);
+ 	device_unregister(&device->device);
+ 
+-	down_write(&idr_rwsem);
++	down_write(&fw_device_rwsem);
+ 	idr_remove(&fw_device_idr, minor);
+-	up_write(&idr_rwsem);
++	up_write(&fw_device_rwsem);
+ 	fw_device_put(device);
+ }
+ 
+@@ -674,10 +724,10 @@ static void fw_device_init(struct work_struct *work)
+ 	err = -ENOMEM;
+ 
+ 	fw_device_get(device);
+-	down_write(&idr_rwsem);
++	down_write(&fw_device_rwsem);
+ 	if (idr_pre_get(&fw_device_idr, GFP_KERNEL))
+ 		err = idr_get_new(&fw_device_idr, device, &minor);
+-	up_write(&idr_rwsem);
++	up_write(&fw_device_rwsem);
+ 
+ 	if (err < 0)
+ 		goto error;
+@@ -711,7 +761,7 @@ static void fw_device_init(struct work_struct *work)
+ 	if (atomic_cmpxchg(&device->state,
+ 		    FW_DEVICE_INITIALIZING,
+ 		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) {
+-		fw_device_shutdown(&device->work.work);
++		fw_device_shutdown(work);
+ 	} else {
+ 		if (device->config_rom_retries)
+ 			fw_notify("created device %s: GUID %08x%08x, S%d00, "
+@@ -725,6 +775,7 @@ static void fw_device_init(struct work_struct *work)
+ 				  device->device.bus_id,
+ 				  device->config_rom[3], device->config_rom[4],
+ 				  1 << device->max_speed);
++		device->config_rom_retries = 0;
+ 	}
+ 
+ 	/*
+@@ -739,9 +790,9 @@ static void fw_device_init(struct work_struct *work)
+ 	return;
+ 
+  error_with_cdev:
+-	down_write(&idr_rwsem);
++	down_write(&fw_device_rwsem);
+ 	idr_remove(&fw_device_idr, minor);
+-	up_write(&idr_rwsem);
++	up_write(&fw_device_rwsem);
+  error:
+ 	fw_device_put(device);		/* fw_device_idr's reference */
+ 
+@@ -771,6 +822,106 @@ static void fw_device_update(struct work_struct *work)
+ 	device_for_each_child(&device->device, NULL, update_unit);
+ }
+ 
++enum {
++	REREAD_BIB_ERROR,
++	REREAD_BIB_GONE,
++	REREAD_BIB_UNCHANGED,
++	REREAD_BIB_CHANGED,
++};
++
++/* Reread and compare bus info block and header of root directory */
++static int reread_bus_info_block(struct fw_device *device, int generation)
++{
++	u32 q;
++	int i;
++
++	for (i = 0; i < 6; i++) {
++		if (read_rom(device, generation, i, &q) != RCODE_COMPLETE)
++			return REREAD_BIB_ERROR;
++
++		if (i == 0 && q == 0)
++			return REREAD_BIB_GONE;
++
++		if (i > device->config_rom_length || q != device->config_rom[i])
++			return REREAD_BIB_CHANGED;
++	}
++
++	return REREAD_BIB_UNCHANGED;
++}
++
++static void fw_device_refresh(struct work_struct *work)
++{
++	struct fw_device *device =
++		container_of(work, struct fw_device, work.work);
++	struct fw_card *card = device->card;
++	int node_id = device->node_id;
++
++	switch (reread_bus_info_block(device, device->generation)) {
++	case REREAD_BIB_ERROR:
++		if (device->config_rom_retries < MAX_RETRIES / 2 &&
++		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
++			device->config_rom_retries++;
++			schedule_delayed_work(&device->work, RETRY_DELAY / 2);
++
++			return;
++		}
++		goto give_up;
++
++	case REREAD_BIB_GONE:
++		goto gone;
++
++	case REREAD_BIB_UNCHANGED:
++		if (atomic_cmpxchg(&device->state,
++			    FW_DEVICE_INITIALIZING,
++			    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
++			goto gone;
++
++		fw_device_update(work);
++		device->config_rom_retries = 0;
++		goto out;
++
++	case REREAD_BIB_CHANGED:
++		break;
++	}
++
++	/*
++	 * Something changed.  We keep things simple and don't investigate
++	 * further.  We just destroy all previous units and create new ones.
++	 */
++	device_for_each_child(&device->device, NULL, shutdown_unit);
++
++	if (read_bus_info_block(device, device->generation) < 0) {
++		if (device->config_rom_retries < MAX_RETRIES &&
++		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
++			device->config_rom_retries++;
++			schedule_delayed_work(&device->work, RETRY_DELAY);
++
++			return;
++		}
++		goto give_up;
++	}
++
++	create_units(device);
++
++	if (atomic_cmpxchg(&device->state,
++		    FW_DEVICE_INITIALIZING,
++		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
++		goto gone;
++
++	fw_notify("refreshed device %s\n", device->device.bus_id);
++	device->config_rom_retries = 0;
++	goto out;
++
++ give_up:
++	fw_notify("giving up on refresh of device %s\n", device->device.bus_id);
++ gone:
++	atomic_set(&device->state, FW_DEVICE_SHUTDOWN);
++	fw_device_shutdown(work);
++ out:
++	if (node_id == card->root_node->node_id)
++		schedule_delayed_work(&card->work, 0);
++}
++
+ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ {
+ 	struct fw_device *device;
+@@ -780,7 +931,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ 	case FW_NODE_LINK_ON:
+ 		if (!node->link_on)
+ 			break;
+-
++ create:
+ 		device = kzalloc(sizeof(*device), GFP_ATOMIC);
+ 		if (device == NULL)
+ 			break;
+@@ -819,6 +970,23 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ 		schedule_delayed_work(&device->work, INITIAL_DELAY);
+ 		break;
+ 
++	case FW_NODE_INITIATED_RESET:
++		device = node->data;
++		if (device == NULL)
++			goto create;
++
++		device->node_id = node->node_id;
++		smp_wmb();  /* update node_id before generation */
++		device->generation = card->generation;
++		if (atomic_cmpxchg(&device->state,
++			    FW_DEVICE_RUNNING,
++			    FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
++			PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
++			schedule_delayed_work(&device->work,
++				node == card->local_node ? 0 : INITIAL_DELAY);
++		}
++		break;
++
+ 	case FW_NODE_UPDATED:
+ 		if (!node->link_on || node->data == NULL)
+ 			break;
+diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
+index 78ecd39..5f131f5 100644
+--- a/drivers/firewire/fw-device.h
++++ b/drivers/firewire/fw-device.h
+@@ -21,6 +21,7 @@
+ 
+ #include <linux/fs.h>
+ #include <linux/cdev.h>
++#include <linux/rwsem.h>
+ #include <asm/atomic.h>
+ 
+ enum fw_device_state {
+@@ -46,6 +47,11 @@ struct fw_attribute_group {
+  * fw_device.node_id is guaranteed to be current too.
+  *
+  * The same applies to fw_device.card->node_id vs. fw_device.generation.
++ *
++ * fw_device.config_rom and fw_device.config_rom_length may be accessed during
++ * the lifetime of any fw_unit belonging to the fw_device, before device_del()
++ * was called on the last fw_unit.  Alternatively, they may be accessed while
++ * holding fw_device_rwsem.
+  */
+ struct fw_device {
+ 	atomic_t state;
+@@ -53,6 +59,7 @@ struct fw_device {
+ 	int node_id;
+ 	int generation;
+ 	unsigned max_speed;
++	bool cmc;
+ 	struct fw_card *card;
+ 	struct device device;
+ 	struct list_head link;
+@@ -64,28 +71,24 @@ struct fw_device {
+ 	struct fw_attribute_group attribute_group;
+ };
+ 
+-static inline struct fw_device *
+-fw_device(struct device *dev)
++static inline struct fw_device *fw_device(struct device *dev)
+ {
+ 	return container_of(dev, struct fw_device, device);
+ }
+ 
+-static inline int
+-fw_device_is_shutdown(struct fw_device *device)
++static inline int fw_device_is_shutdown(struct fw_device *device)
+ {
+ 	return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN;
+ }
+ 
+-static inline struct fw_device *
+-fw_device_get(struct fw_device *device)
++static inline struct fw_device *fw_device_get(struct fw_device *device)
+ {
+ 	get_device(&device->device);
+ 
+ 	return device;
+ }
+ 
+-static inline void
+-fw_device_put(struct fw_device *device)
++static inline void fw_device_put(struct fw_device *device)
+ {
+ 	put_device(&device->device);
+ }
+@@ -96,20 +99,35 @@ int fw_device_enable_phys_dma(struct fw_device *device);
+ void fw_device_cdev_update(struct fw_device *device);
+ void fw_device_cdev_remove(struct fw_device *device);
+ 
++extern struct rw_semaphore fw_device_rwsem;
+ extern int fw_cdev_major;
+ 
++/*
++ * fw_unit.directory must not be accessed after device_del(&fw_unit.device).
++ */
+ struct fw_unit {
+ 	struct device device;
+ 	u32 *directory;
+ 	struct fw_attribute_group attribute_group;
+ };
+ 
+-static inline struct fw_unit *
+-fw_unit(struct device *dev)
++static inline struct fw_unit *fw_unit(struct device *dev)
+ {
+ 	return container_of(dev, struct fw_unit, device);
+ }
+ 
++static inline struct fw_unit *fw_unit_get(struct fw_unit *unit)
++{
++	get_device(&unit->device);
++
++	return unit;
++}
++
++static inline void fw_unit_put(struct fw_unit *unit)
++{
++	put_device(&unit->device);
++}
++
+ #define CSR_OFFSET	0x40
+ #define CSR_LEAF	0x80
+ #define CSR_DIRECTORY	0xc0
+diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c
+index 2b640e9..bcbe794 100644
+--- a/drivers/firewire/fw-iso.c
++++ b/drivers/firewire/fw-iso.c
+@@ -126,7 +126,6 @@ fw_iso_context_create(struct fw_card *card, int type,
+ 
+ 	return ctx;
+ }
+-EXPORT_SYMBOL(fw_iso_context_create);
+ 
+ void fw_iso_context_destroy(struct fw_iso_context *ctx)
+ {
+@@ -134,14 +133,12 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx)
+ 
+ 	card->driver->free_iso_context(ctx);
+ }
+-EXPORT_SYMBOL(fw_iso_context_destroy);
+ 
+ int
+ fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags)
+ {
+ 	return ctx->card->driver->start_iso(ctx, cycle, sync, tags);
+ }
+-EXPORT_SYMBOL(fw_iso_context_start);
+ 
+ int
+ fw_iso_context_queue(struct fw_iso_context *ctx,
+@@ -153,11 +150,9 @@ fw_iso_context_queue(struct fw_iso_context *ctx,
+ 
+ 	return card->driver->queue_iso(ctx, packet, buffer, payload);
+ }
+-EXPORT_SYMBOL(fw_iso_context_queue);
+ 
+ int
+ fw_iso_context_stop(struct fw_iso_context *ctx)
+ {
+ 	return ctx->card->driver->stop_iso(ctx);
+ }
+-EXPORT_SYMBOL(fw_iso_context_stop);
+diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
+index ca6d51e..4f02c55 100644
+--- a/drivers/firewire/fw-ohci.c
++++ b/drivers/firewire/fw-ohci.c
+@@ -27,6 +27,7 @@
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/module.h>
++#include <linux/moduleparam.h>
+ #include <linux/pci.h>
+ #include <linux/spinlock.h>
+ 
+@@ -177,9 +178,10 @@ struct fw_ohci {
+ 	struct tasklet_struct bus_reset_tasklet;
+ 	int node_id;
+ 	int generation;
+-	int request_generation;
++	int request_generation;	/* for timestamping incoming requests */
+ 	u32 bus_seconds;
+ 	bool old_uninorth;
++	bool bus_reset_packet_quirk;
+ 
+ 	/*
+ 	 * Spinlock for accessing fw_ohci data.  Never call out of
+@@ -237,6 +239,196 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
+ 
+ static char ohci_driver_name[] = KBUILD_MODNAME;
+ 
++#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
++
++#define OHCI_PARAM_DEBUG_AT_AR		1
++#define OHCI_PARAM_DEBUG_SELFIDS	2
++#define OHCI_PARAM_DEBUG_IRQS		4
++#define OHCI_PARAM_DEBUG_BUSRESETS	8 /* only effective before chip init */
++
++static int param_debug;
++module_param_named(debug, param_debug, int, 0644);
++MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
++	", AT/AR events = "	__stringify(OHCI_PARAM_DEBUG_AT_AR)
++	", self-IDs = "		__stringify(OHCI_PARAM_DEBUG_SELFIDS)
++	", IRQs = "		__stringify(OHCI_PARAM_DEBUG_IRQS)
++	", busReset events = "	__stringify(OHCI_PARAM_DEBUG_BUSRESETS)
++	", or a combination, or all = -1)");
++
++static void log_irqs(u32 evt)
++{
++	if (likely(!(param_debug &
++			(OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS))))
++		return;
++
++	if (!(param_debug & OHCI_PARAM_DEBUG_IRQS) &&
++	    !(evt & OHCI1394_busReset))
++		return;
++
++	printk(KERN_DEBUG KBUILD_MODNAME ": IRQ "
++	       "%08x%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
++	       evt,
++	       evt & OHCI1394_selfIDComplete	? " selfID"		: "",
++	       evt & OHCI1394_RQPkt		? " AR_req"		: "",
++	       evt & OHCI1394_RSPkt		? " AR_resp"		: "",
++	       evt & OHCI1394_reqTxComplete	? " AT_req"		: "",
++	       evt & OHCI1394_respTxComplete	? " AT_resp"		: "",
++	       evt & OHCI1394_isochRx		? " IR"			: "",
++	       evt & OHCI1394_isochTx		? " IT"			: "",
++	       evt & OHCI1394_postedWriteErr	? " postedWriteErr"	: "",
++	       evt & OHCI1394_cycleTooLong	? " cycleTooLong"	: "",
++	       evt & OHCI1394_cycle64Seconds	? " cycle64Seconds"	: "",
++	       evt & OHCI1394_regAccessFail	? " regAccessFail"	: "",
++	       evt & OHCI1394_busReset		? " busReset"		: "",
++	       evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
++		       OHCI1394_RSPkt | OHCI1394_reqTxComplete |
++		       OHCI1394_respTxComplete | OHCI1394_isochRx |
++		       OHCI1394_isochTx | OHCI1394_postedWriteErr |
++		       OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds |
++		       OHCI1394_regAccessFail | OHCI1394_busReset)
++						? " ?"			: "");
++}
++
++static const char *speed[] = {
++	[0] = "S100", [1] = "S200", [2] = "S400",    [3] = "beta",
++};
++static const char *power[] = {
++	[0] = "+0W",  [1] = "+15W", [2] = "+30W",    [3] = "+45W",
++	[4] = "-3W",  [5] = " ?W",  [6] = "-3..-6W", [7] = "-3..-10W",
++};
++static const char port[] = { '.', '-', 'p', 'c', };
++
++static char _p(u32 *s, int shift)
++{
++	return port[*s >> shift & 3];
++}
++
++static void log_selfids(int node_id, int generation, int self_id_count, u32 *s)
++{
++	if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS)))
++		return;
++
++	printk(KERN_DEBUG KBUILD_MODNAME ": %d selfIDs, generation %d, "
++	       "local node ID %04x\n", self_id_count, generation, node_id);
++
++	for (; self_id_count--; ++s)
++		if ((*s & 1 << 23) == 0)
++			printk(KERN_DEBUG "selfID 0: %08x, phy %d [%c%c%c] "
++			       "%s gc=%d %s %s%s%s\n",
++			       *s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2),
++			       speed[*s >> 14 & 3], *s >> 16 & 63,
++			       power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "",
++			       *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : "");
++		else
++			printk(KERN_DEBUG "selfID n: %08x, phy %d "
++			       "[%c%c%c%c%c%c%c%c]\n",
++			       *s, *s >> 24 & 63,
++			       _p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10),
++			       _p(s,  8), _p(s,  6), _p(s,  4), _p(s,  2));
++}
++
++static const char *evts[] = {
++	[0x00] = "evt_no_status",	[0x01] = "-reserved-",
++	[0x02] = "evt_long_packet",	[0x03] = "evt_missing_ack",
++	[0x04] = "evt_underrun",	[0x05] = "evt_overrun",
++	[0x06] = "evt_descriptor_read",	[0x07] = "evt_data_read",
++	[0x08] = "evt_data_write",	[0x09] = "evt_bus_reset",
++	[0x0a] = "evt_timeout",		[0x0b] = "evt_tcode_err",
++	[0x0c] = "-reserved-",		[0x0d] = "-reserved-",
++	[0x0e] = "evt_unknown",		[0x0f] = "evt_flushed",
++	[0x10] = "-reserved-",		[0x11] = "ack_complete",
++	[0x12] = "ack_pending ",	[0x13] = "-reserved-",
++	[0x14] = "ack_busy_X",		[0x15] = "ack_busy_A",
++	[0x16] = "ack_busy_B",		[0x17] = "-reserved-",
++	[0x18] = "-reserved-",		[0x19] = "-reserved-",
++	[0x1a] = "-reserved-",		[0x1b] = "ack_tardy",
++	[0x1c] = "-reserved-",		[0x1d] = "ack_data_error",
++	[0x1e] = "ack_type_error",	[0x1f] = "-reserved-",
++	[0x20] = "pending/cancelled",
++};
++static const char *tcodes[] = {
++	[0x0] = "QW req",		[0x1] = "BW req",
++	[0x2] = "W resp",		[0x3] = "-reserved-",
++	[0x4] = "QR req",		[0x5] = "BR req",
++	[0x6] = "QR resp",		[0x7] = "BR resp",
++	[0x8] = "cycle start",		[0x9] = "Lk req",
++	[0xa] = "async stream packet",	[0xb] = "Lk resp",
++	[0xc] = "-reserved-",		[0xd] = "-reserved-",
++	[0xe] = "link internal",	[0xf] = "-reserved-",
++};
++static const char *phys[] = {
++	[0x0] = "phy config packet",	[0x1] = "link-on packet",
++	[0x2] = "self-id packet",	[0x3] = "-reserved-",
++};
++
++static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
++{
++	int tcode = header[0] >> 4 & 0xf;
++	char specific[12];
++
++	if (likely(!(param_debug & OHCI_PARAM_DEBUG_AT_AR)))
++		return;
++
++	if (unlikely(evt >= ARRAY_SIZE(evts)))
++			evt = 0x1f;
++
++	if (evt == OHCI1394_evt_bus_reset) {
++		printk(KERN_DEBUG "A%c evt_bus_reset, generation %d\n",
++		       dir, (header[2] >> 16) & 0xff);
++		return;
++	}
++
++	if (header[0] == ~header[1]) {
++		printk(KERN_DEBUG "A%c %s, %s, %08x\n",
++		       dir, evts[evt], phys[header[0] >> 30 & 0x3],
++		       header[0]);
++		return;
++	}
++
++	switch (tcode) {
++	case 0x0: case 0x6: case 0x8:
++		snprintf(specific, sizeof(specific), " = %08x",
++			 be32_to_cpu((__force __be32)header[3]));
++		break;
++	case 0x1: case 0x5: case 0x7: case 0x9: case 0xb:
++		snprintf(specific, sizeof(specific), " %x,%x",
++			 header[3] >> 16, header[3] & 0xffff);
++		break;
++	default:
++		specific[0] = '\0';
++	}
++
++	switch (tcode) {
++	case 0xe: case 0xa:
++		printk(KERN_DEBUG "A%c %s, %s\n",
++		       dir, evts[evt], tcodes[tcode]);
++		break;
++	case 0x0: case 0x1: case 0x4: case 0x5: case 0x9:
++		printk(KERN_DEBUG "A%c spd %x tl %02x, "
++		       "%04x -> %04x, %s, "
++		       "%s, %04x%08x%s\n",
++		       dir, speed, header[0] >> 10 & 0x3f,
++		       header[1] >> 16, header[0] >> 16, evts[evt],
++		       tcodes[tcode], header[1] & 0xffff, header[2], specific);
++		break;
++	default:
++		printk(KERN_DEBUG "A%c spd %x tl %02x, "
++		       "%04x -> %04x, %s, "
++		       "%s%s\n",
++		       dir, speed, header[0] >> 10 & 0x3f,
++		       header[1] >> 16, header[0] >> 16, evts[evt],
++		       tcodes[tcode], specific);
++	}
++}
++
++#else
++
++#define log_irqs(evt)
++#define log_selfids(node_id, generation, self_id_count, sid)
++#define log_ar_at_event(dir, speed, header, evt)
++
++#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
++
+ static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data)
+ {
+ 	writel(data, ohci->registers + offset);
+@@ -320,6 +512,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+ 	struct fw_ohci *ohci = ctx->ohci;
+ 	struct fw_packet p;
+ 	u32 status, length, tcode;
++	int evt;
+ 
+ 	p.header[0] = cond_le32_to_cpu(buffer[0]);
+ 	p.header[1] = cond_le32_to_cpu(buffer[1]);
+@@ -362,12 +555,15 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+ 	/* FIXME: What to do about evt_* errors? */
+ 	length = (p.header_length + p.payload_length + 3) / 4;
+ 	status = cond_le32_to_cpu(buffer[length]);
++	evt    = (status >> 16) & 0x1f;
+ 
+-	p.ack        = ((status >> 16) & 0x1f) - 16;
++	p.ack        = evt - 16;
+ 	p.speed      = (status >> 21) & 0x7;
+ 	p.timestamp  = status & 0xffff;
+ 	p.generation = ohci->request_generation;
+ 
++	log_ar_at_event('R', p.speed, p.header, evt);
++
+ 	/*
+ 	 * The OHCI bus reset handler synthesizes a phy packet with
+ 	 * the new generation number when a bus reset happens (see
+@@ -376,14 +572,19 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+ 	 * generation.  We only need this for requests; for responses
+ 	 * we use the unique tlabel for finding the matching
+ 	 * request.
++	 *
++	 * Alas some chips sometimes emit bus reset packets with a
++	 * wrong generation.  We set the correct generation for these
++	 * at a slightly incorrect time (in bus_reset_tasklet).
+ 	 */
+-
+-	if (p.ack + 16 == 0x09)
+-		ohci->request_generation = (p.header[2] >> 16) & 0xff;
+-	else if (ctx == &ohci->ar_request_ctx)
++	if (evt == OHCI1394_evt_bus_reset) {
++		if (!ohci->bus_reset_packet_quirk)
++			ohci->request_generation = (p.header[2] >> 16) & 0xff;
++	} else if (ctx == &ohci->ar_request_ctx) {
+ 		fw_core_handle_request(&ohci->card, &p);
+-	else
++	} else {
+ 		fw_core_handle_response(&ohci->card, &p);
++	}
+ 
+ 	return buffer + length + 1;
+ }
+@@ -770,8 +971,19 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
+ 				     DESCRIPTOR_IRQ_ALWAYS |
+ 				     DESCRIPTOR_BRANCH_ALWAYS);
+ 
+-	/* FIXME: Document how the locking works. */
+-	if (ohci->generation != packet->generation) {
++	/*
++	 * If the controller and packet generations don't match, we need to
++	 * bail out and try again.  If IntEvent.busReset is set, the AT context
++	 * is halted, so appending to the context and trying to run it is
++	 * futile.  Most controllers do the right thing and just flush the AT
++	 * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but
++	 * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
++	 * up stalling out.  So we just bail out in software and try again
++	 * later, and everyone is happy.
++	 * FIXME: Document how the locking works.
++	 */
++	if (ohci->generation != packet->generation ||
++	    reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
+ 		if (packet->payload_length > 0)
+ 			dma_unmap_single(ohci->card.device, payload_bus,
+ 					 packet->payload_length, DMA_TO_DEVICE);
+@@ -817,6 +1029,8 @@ static int handle_at_packet(struct context *context,
+ 	evt = le16_to_cpu(last->transfer_status) & 0x1f;
+ 	packet->timestamp = le16_to_cpu(last->res_count);
+ 
++	log_ar_at_event('T', packet->speed, packet->header, evt);
++
+ 	switch (evt) {
+ 	case OHCI1394_evt_timeout:
+ 		/* Async response transmit timed out. */
+@@ -1019,20 +1233,30 @@ static void bus_reset_tasklet(unsigned long data)
+ 	ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
+ 			       OHCI1394_NodeID_nodeNumber);
+ 
++	reg = reg_read(ohci, OHCI1394_SelfIDCount);
++	if (reg & OHCI1394_SelfIDCount_selfIDError) {
++		fw_notify("inconsistent self IDs\n");
++		return;
++	}
+ 	/*
+ 	 * The count in the SelfIDCount register is the number of
+ 	 * bytes in the self ID receive buffer.  Since we also receive
+ 	 * the inverted quadlets and a header quadlet, we shift one
+ 	 * bit extra to get the actual number of self IDs.
+ 	 */
+-
+-	self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff;
++	self_id_count = (reg >> 3) & 0x3ff;
++	if (self_id_count == 0) {
++		fw_notify("inconsistent self IDs\n");
++		return;
++	}
+ 	generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
+ 	rmb();
+ 
+ 	for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
+-		if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1])
+-			fw_error("inconsistent self IDs\n");
++		if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) {
++			fw_notify("inconsistent self IDs\n");
++			return;
++		}
+ 		ohci->self_id_buffer[j] =
+ 				cond_le32_to_cpu(ohci->self_id_cpu[i]);
+ 	}
+@@ -1067,6 +1291,9 @@ static void bus_reset_tasklet(unsigned long data)
+ 	context_stop(&ohci->at_response_ctx);
+ 	reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
+ 
++	if (ohci->bus_reset_packet_quirk)
++		ohci->request_generation = generation;
++
+ 	/*
+ 	 * This next bit is unrelated to the AT context stuff but we
+ 	 * have to do it under the spinlock also.  If a new config rom
+@@ -1097,12 +1324,20 @@ static void bus_reset_tasklet(unsigned long data)
+ 		reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->next_header);
+ 	}
+ 
++#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
++	reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
++	reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
++#endif
++
+ 	spin_unlock_irqrestore(&ohci->lock, flags);
+ 
+ 	if (free_rom)
+ 		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+ 				  free_rom, free_rom_bus);
+ 
++	log_selfids(ohci->node_id, generation,
++		    self_id_count, ohci->self_id_buffer);
++
+ 	fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation,
+ 				 self_id_count, ohci->self_id_buffer);
+ }
+@@ -1118,7 +1353,9 @@ static irqreturn_t irq_handler(int irq, void *data)
+ 	if (!event || !~event)
+ 		return IRQ_NONE;
+ 
+-	reg_write(ohci, OHCI1394_IntEventClear, event);
++	/* busReset must not be cleared yet, see OHCI 1.1 clause 7.2.3.2 */
++	reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
++	log_irqs(event);
+ 
+ 	if (event & OHCI1394_selfIDComplete)
+ 		tasklet_schedule(&ohci->bus_reset_tasklet);
+@@ -1153,6 +1390,10 @@ static irqreturn_t irq_handler(int irq, void *data)
+ 		iso_event &= ~(1 << i);
+ 	}
+ 
++	if (unlikely(event & OHCI1394_regAccessFail))
++		fw_error("Register access failure - "
++			 "please notify linux1394-devel at lists.sf.net\n");
++
+ 	if (unlikely(event & OHCI1394_postedWriteErr))
+ 		fw_error("PCI posted write error\n");
+ 
+@@ -1192,6 +1433,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ {
+ 	struct fw_ohci *ohci = fw_ohci(card);
+ 	struct pci_dev *dev = to_pci_dev(card->device);
++	u32 lps;
++	int i;
+ 
+ 	if (software_reset(ohci)) {
+ 		fw_error("Failed to reset ohci card.\n");
+@@ -1203,13 +1446,24 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ 	 * most of the registers.  In fact, on some cards (ALI M5251),
+ 	 * accessing registers in the SClk domain without LPS enabled
+ 	 * will lock up the machine.  Wait 50msec to make sure we have
+-	 * full link enabled.
++	 * full link enabled.  However, with some cards (well, at least
++	 * a JMicron PCIe card), we have to try again sometimes.
+ 	 */
+ 	reg_write(ohci, OHCI1394_HCControlSet,
+ 		  OHCI1394_HCControl_LPS |
+ 		  OHCI1394_HCControl_postedWriteEnable);
+ 	flush_writes(ohci);
+-	msleep(50);
++
++	for (lps = 0, i = 0; !lps && i < 3; i++) {
++		msleep(50);
++		lps = reg_read(ohci, OHCI1394_HCControlSet) &
++		      OHCI1394_HCControl_LPS;
++	}
++
++	if (!lps) {
++		fw_error("Failed to set Link Power Status\n");
++		return -EIO;
++	}
+ 
+ 	reg_write(ohci, OHCI1394_HCControlClear,
+ 		  OHCI1394_HCControl_noByteSwapData);
+@@ -1237,7 +1491,10 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ 		  OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
+ 		  OHCI1394_isochRx | OHCI1394_isochTx |
+ 		  OHCI1394_postedWriteErr | OHCI1394_cycleTooLong |
+-		  OHCI1394_cycle64Seconds | OHCI1394_masterIntEnable);
++		  OHCI1394_cycle64Seconds | OHCI1394_regAccessFail |
++		  OHCI1394_masterIntEnable);
++	if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
++		reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
+ 
+ 	/* Activate link_on bit and contender bit in our self ID packets.*/
+ 	if (ohci_update_phy_reg(card, 4, 0,
+@@ -1421,6 +1678,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
+ 	if (packet->ack != 0)
+ 		goto out;
+ 
++	log_ar_at_event('T', packet->speed, packet->header, 0x20);
+ 	driver_data->packet = NULL;
+ 	packet->ack = RCODE_CANCELLED;
+ 	packet->callback(packet, &ohci->card, packet->ack);
+@@ -1435,6 +1693,9 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
+ static int
+ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
+ {
++#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
++	return 0;
++#else
+ 	struct fw_ohci *ohci = fw_ohci(card);
+ 	unsigned long flags;
+ 	int n, retval = 0;
+@@ -1466,6 +1727,7 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
+  out:
+ 	spin_unlock_irqrestore(&ohci->lock, flags);
+ 	return retval;
++#endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */
+ }
+ 
+ static u64
+@@ -2045,17 +2307,9 @@ static const struct fw_card_driver ohci_driver = {
+ 	.stop_iso		= ohci_stop_iso,
+ };
+ 
+-static int __devinit
+-pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+-{
+-	struct fw_ohci *ohci;
+-	u32 bus_options, max_receive, link_speed;
+-	u64 guid;
+-	int err;
+-	size_t size;
+-
+ #ifdef CONFIG_PPC_PMAC
+-	/* Necessary on some machines if fw-ohci was loaded/ unloaded before */
++static void ohci_pmac_on(struct pci_dev *dev)
++{
+ 	if (machine_is(powermac)) {
+ 		struct device_node *ofn = pci_device_to_OF_node(dev);
+ 
+@@ -2064,8 +2318,33 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ 			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+ 		}
+ 	}
++}
++
++static void ohci_pmac_off(struct pci_dev *dev)
++{
++	if (machine_is(powermac)) {
++		struct device_node *ofn = pci_device_to_OF_node(dev);
++
++		if (ofn) {
++			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
++			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
++		}
++	}
++}
++#else
++#define ohci_pmac_on(dev)
++#define ohci_pmac_off(dev)
+ #endif /* CONFIG_PPC_PMAC */
+ 
++static int __devinit
++pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
++{
++	struct fw_ohci *ohci;
++	u32 bus_options, max_receive, link_speed;
++	u64 guid;
++	int err;
++	size_t size;
++
+ 	ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
+ 	if (ohci == NULL) {
+ 		fw_error("Could not malloc fw_ohci data.\n");
+@@ -2074,10 +2353,12 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ 
+ 	fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
+ 
++	ohci_pmac_on(dev);
++
+ 	err = pci_enable_device(dev);
+ 	if (err) {
+ 		fw_error("Failed to enable OHCI hardware.\n");
+-		goto fail_put_card;
++		goto fail_free;
+ 	}
+ 
+ 	pci_set_master(dev);
+@@ -2088,6 +2369,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ 	ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
+ 			     dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
+ #endif
++	ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
++
+ 	spin_lock_init(&ohci->lock);
+ 
+ 	tasklet_init(&ohci->bus_reset_tasklet,
+@@ -2173,8 +2456,9 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ 	pci_release_region(dev, 0);
+  fail_disable:
+ 	pci_disable_device(dev);
+- fail_put_card:
+-	fw_card_put(&ohci->card);
++ fail_free:
++	kfree(&ohci->card);
++	ohci_pmac_off(dev);
+ 
+ 	return err;
+ }
+@@ -2202,72 +2486,42 @@ static void pci_remove(struct pci_dev *dev)
+ 	pci_iounmap(dev, ohci->registers);
+ 	pci_release_region(dev, 0);
+ 	pci_disable_device(dev);
+-	fw_card_put(&ohci->card);
+-
+-#ifdef CONFIG_PPC_PMAC
+-	/* On UniNorth, power down the cable and turn off the chip clock
+-	 * to save power on laptops */
+-	if (machine_is(powermac)) {
+-		struct device_node *ofn = pci_device_to_OF_node(dev);
+-
+-		if (ofn) {
+-			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+-			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
+-		}
+-	}
+-#endif /* CONFIG_PPC_PMAC */
++	kfree(&ohci->card);
++	ohci_pmac_off(dev);
+ 
+ 	fw_notify("Removed fw-ohci device.\n");
+ }
+ 
+ #ifdef CONFIG_PM
+-static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
++static int pci_suspend(struct pci_dev *dev, pm_message_t state)
+ {
+-	struct fw_ohci *ohci = pci_get_drvdata(pdev);
++	struct fw_ohci *ohci = pci_get_drvdata(dev);
+ 	int err;
+ 
+ 	software_reset(ohci);
+-	free_irq(pdev->irq, ohci);
+-	err = pci_save_state(pdev);
++	free_irq(dev->irq, ohci);
++	err = pci_save_state(dev);
+ 	if (err) {
+ 		fw_error("pci_save_state failed\n");
+ 		return err;
+ 	}
+-	err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
++	err = pci_set_power_state(dev, pci_choose_state(dev, state));
+ 	if (err)
+ 		fw_error("pci_set_power_state failed with %d\n", err);
+-
+-/* PowerMac suspend code comes last */
+-#ifdef CONFIG_PPC_PMAC
+-	if (machine_is(powermac)) {
+-		struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+-		if (ofn)
+-			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+-	}
+-#endif /* CONFIG_PPC_PMAC */
++	ohci_pmac_off(dev);
+ 
+ 	return 0;
+ }
+ 
+-static int pci_resume(struct pci_dev *pdev)
++static int pci_resume(struct pci_dev *dev)
+ {
+-	struct fw_ohci *ohci = pci_get_drvdata(pdev);
++	struct fw_ohci *ohci = pci_get_drvdata(dev);
+ 	int err;
+ 
+-/* PowerMac resume code comes first */
+-#ifdef CONFIG_PPC_PMAC
+-	if (machine_is(powermac)) {
+-		struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+-		if (ofn)
+-			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+-	}
+-#endif /* CONFIG_PPC_PMAC */
+-
+-	pci_set_power_state(pdev, PCI_D0);
+-	pci_restore_state(pdev);
+-	err = pci_enable_device(pdev);
++	ohci_pmac_on(dev);
++	pci_set_power_state(dev, PCI_D0);
++	pci_restore_state(dev);
++	err = pci_enable_device(dev);
+ 	if (err) {
+ 		fw_error("pci_enable_device failed\n");
+ 		return err;
+diff --git a/drivers/firewire/fw-ohci.h b/drivers/firewire/fw-ohci.h
+index dec4f04..a2fbb62 100644
+--- a/drivers/firewire/fw-ohci.h
++++ b/drivers/firewire/fw-ohci.h
+@@ -30,6 +30,7 @@
+ #define  OHCI1394_HCControl_softReset		0x00010000
+ #define OHCI1394_SelfIDBuffer                 0x064
+ #define OHCI1394_SelfIDCount                  0x068
++#define  OHCI1394_SelfIDCount_selfIDError	0x80000000
+ #define OHCI1394_IRMultiChanMaskHiSet         0x070
+ #define OHCI1394_IRMultiChanMaskHiClear       0x074
+ #define OHCI1394_IRMultiChanMaskLoSet         0x078
+@@ -124,6 +125,7 @@
+ #define OHCI1394_lockRespErr		0x00000200
+ #define OHCI1394_selfIDComplete		0x00010000
+ #define OHCI1394_busReset		0x00020000
++#define OHCI1394_regAccessFail		0x00040000
+ #define OHCI1394_phy			0x00080000
+ #define OHCI1394_cycleSynch		0x00100000
+ #define OHCI1394_cycle64Seconds		0x00200000
+diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
+index 62b4e47..2a99937 100644
+--- a/drivers/firewire/fw-sbp2.c
++++ b/drivers/firewire/fw-sbp2.c
+@@ -153,6 +153,7 @@ struct sbp2_target {
+ 	struct list_head lu_list;
+ 
+ 	u64 management_agent_address;
++	u64 guid;
+ 	int directory_id;
+ 	int node_id;
+ 	int address_high;
+@@ -173,10 +174,8 @@ struct sbp2_target {
+ #define SBP2_ORB_TIMEOUT		2000U	/* Timeout in ms */
+ #define SBP2_ORB_NULL			0x80000000
+ #define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
+-#define SBP2_RETRY_LIMIT		0xf	/* 15 retries */
+-
+-#define SBP2_DIRECTION_TO_MEDIA		0x0
+-#define SBP2_DIRECTION_FROM_MEDIA	0x1
++#define SBP2_RETRY_LIMIT		0xf		/* 15 retries */
++#define SBP2_CYCLE_LIMIT		(0xc8 << 12)	/* 200 125us cycles */
+ 
+ /* Unit directory keys */
+ #define SBP2_CSR_UNIT_CHARACTERISTICS	0x3a
+@@ -224,8 +223,8 @@ struct sbp2_status {
+ };
+ 
+ struct sbp2_pointer {
+-	u32 high;
+-	u32 low;
++	__be32 high;
++	__be32 low;
+ };
+ 
+ struct sbp2_orb {
+@@ -253,8 +252,8 @@ struct sbp2_management_orb {
+ 	struct {
+ 		struct sbp2_pointer password;
+ 		struct sbp2_pointer response;
+-		u32 misc;
+-		u32 length;
++		__be32 misc;
++		__be32 length;
+ 		struct sbp2_pointer status_fifo;
+ 	} request;
+ 	__be32 response[4];
+@@ -263,20 +262,17 @@ struct sbp2_management_orb {
+ 	struct sbp2_status status;
+ };
+ 
+-#define LOGIN_RESPONSE_GET_LOGIN_ID(v)	((v).misc & 0xffff)
+-#define LOGIN_RESPONSE_GET_LENGTH(v)	(((v).misc >> 16) & 0xffff)
+-
+ struct sbp2_login_response {
+-	u32 misc;
++	__be32 misc;
+ 	struct sbp2_pointer command_block_agent;
+-	u32 reconnect_hold;
++	__be32 reconnect_hold;
+ };
+ #define COMMAND_ORB_DATA_SIZE(v)	((v))
+ #define COMMAND_ORB_PAGE_SIZE(v)	((v) << 16)
+ #define COMMAND_ORB_PAGE_TABLE_PRESENT	((1) << 19)
+ #define COMMAND_ORB_MAX_PAYLOAD(v)	((v) << 20)
+ #define COMMAND_ORB_SPEED(v)		((v) << 24)
+-#define COMMAND_ORB_DIRECTION(v)	((v) << 27)
++#define COMMAND_ORB_DIRECTION		((1) << 27)
+ #define COMMAND_ORB_REQUEST_FORMAT(v)	((v) << 29)
+ #define COMMAND_ORB_NOTIFY		((1) << 31)
+ 
+@@ -285,7 +281,7 @@ struct sbp2_command_orb {
+ 	struct {
+ 		struct sbp2_pointer next;
+ 		struct sbp2_pointer data_descriptor;
+-		u32 misc;
++		__be32 misc;
+ 		u8 command_block[12];
+ 	} request;
+ 	struct scsi_cmnd *cmd;
+@@ -459,8 +455,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
+ 	unsigned long flags;
+ 
+ 	orb->pointer.high = 0;
+-	orb->pointer.low = orb->request_bus;
+-	fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer));
++	orb->pointer.low = cpu_to_be32(orb->request_bus);
+ 
+ 	spin_lock_irqsave(&device->card->lock, flags);
+ 	list_add_tail(&orb->link, &lu->orb_list);
+@@ -536,31 +531,31 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+ 	if (dma_mapping_error(orb->response_bus))
+ 		goto fail_mapping_response;
+ 
+-	orb->request.response.high    = 0;
+-	orb->request.response.low     = orb->response_bus;
++	orb->request.response.high = 0;
++	orb->request.response.low  = cpu_to_be32(orb->response_bus);
+ 
+-	orb->request.misc =
++	orb->request.misc = cpu_to_be32(
+ 		MANAGEMENT_ORB_NOTIFY |
+ 		MANAGEMENT_ORB_FUNCTION(function) |
+-		MANAGEMENT_ORB_LUN(lun_or_login_id);
+-	orb->request.length =
+-		MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response));
++		MANAGEMENT_ORB_LUN(lun_or_login_id));
++	orb->request.length = cpu_to_be32(
++		MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)));
+ 
+-	orb->request.status_fifo.high = lu->address_handler.offset >> 32;
+-	orb->request.status_fifo.low  = lu->address_handler.offset;
++	orb->request.status_fifo.high =
++		cpu_to_be32(lu->address_handler.offset >> 32);
++	orb->request.status_fifo.low  =
++		cpu_to_be32(lu->address_handler.offset);
+ 
+ 	if (function == SBP2_LOGIN_REQUEST) {
+ 		/* Ask for 2^2 == 4 seconds reconnect grace period */
+-		orb->request.misc |=
++		orb->request.misc |= cpu_to_be32(
+ 			MANAGEMENT_ORB_RECONNECT(2) |
+-			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login);
++			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login));
+ 		timeout = lu->tgt->mgt_orb_timeout;
+ 	} else {
+ 		timeout = SBP2_ORB_TIMEOUT;
+ 	}
+ 
+-	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+-
+ 	init_completion(&orb->done);
+ 	orb->base.callback = complete_management_orb;
+ 
+@@ -605,8 +600,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+ 			 sizeof(orb->response), DMA_FROM_DEVICE);
+  fail_mapping_response:
+ 	if (response)
+-		fw_memcpy_from_be32(response,
+-				    orb->response, sizeof(orb->response));
++		memcpy(response, orb->response, sizeof(orb->response));
+ 	kref_put(&orb->base.kref, free_orb);
+ 
+ 	return retval;
+@@ -701,10 +695,8 @@ static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
+ 	if (!tgt->dont_block && !lu->blocked &&
+ 	    lu->generation != card->generation) {
+ 		lu->blocked = true;
+-		if (++tgt->blocked == 1) {
++		if (++tgt->blocked == 1)
+ 			scsi_block_requests(shost);
+-			fw_notify("blocked %s\n", lu->tgt->bus_id);
+-		}
+ 	}
+ 	spin_unlock_irqrestore(&card->lock, flags);
+ }
+@@ -731,10 +723,8 @@ static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
+ 	}
+ 	spin_unlock_irqrestore(&card->lock, flags);
+ 
+-	if (unblock) {
++	if (unblock)
+ 		scsi_unblock_requests(shost);
+-		fw_notify("unblocked %s\n", lu->tgt->bus_id);
+-	}
+ }
+ 
+ /*
+@@ -796,7 +786,7 @@ static void sbp2_release_target(struct kref *kref)
+ 	scsi_remove_host(shost);
+ 	fw_notify("released %s\n", tgt->bus_id);
+ 
+-	put_device(&tgt->unit->device);
++	fw_unit_put(tgt->unit);
+ 	scsi_host_put(shost);
+ 	fw_device_put(device);
+ }
+@@ -825,6 +815,22 @@ complete_set_busy_timeout(struct fw_card *card, int rcode,
+ 	complete(done);
+ }
+ 
++/*
++ * Write retransmit retry values into the BUSY_TIMEOUT register.
++ * - The single-phase retry protocol is supported by all SBP-2 devices, but the
++ *   default retry_limit value is 0 (i.e. never retry transmission). We write a
++ *   saner value after logging into the device.
++ * - The dual-phase retry protocol is optional to implement, and if not
++ *   supported, writes to the dual-phase portion of the register will be
++ *   ignored. We try to write the original 1394-1995 default here.
++ * - In the case of devices that are also SBP-3-compliant, all writes are
++ *   ignored, as the register is read-only, but contains single-phase retry of
++ *   15, which is what we're trying to set for all SBP-2 device anyway, so this
++ *   write attempt is safe and yields more consistent behavior for all devices.
++ *
++ * See section 8.3.2.3.5 of the 1394-1995 spec, section 6.2 of the SBP-2 spec,
++ * and section 6.4 of the SBP-3 spec for further details.
++ */
+ static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
+ {
+ 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+@@ -832,8 +838,7 @@ static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
+ 	struct fw_transaction t;
+ 	static __be32 busy_timeout;
+ 
+-	/* FIXME: we should try to set dual-phase cycle_limit too */
+-	busy_timeout = cpu_to_be32(SBP2_RETRY_LIMIT);
++	busy_timeout = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
+ 
+ 	fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST,
+ 			lu->tgt->node_id, lu->generation, device->max_speed,
+@@ -885,11 +890,10 @@ static void sbp2_login(struct work_struct *work)
+ 	tgt->address_high = local_node_id << 16;
+ 	sbp2_set_generation(lu, generation);
+ 
+-	/* Get command block agent offset and login id. */
+ 	lu->command_block_agent_address =
+-		((u64) (response.command_block_agent.high & 0xffff) << 32) |
+-		response.command_block_agent.low;
+-	lu->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response);
++		((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff)
++		      << 32) | be32_to_cpu(response.command_block_agent.low);
++	lu->login_id = be32_to_cpu(response.misc) & 0xffff;
+ 
+ 	fw_notify("%s: logged in to LUN %04x (%d retries)\n",
+ 		  tgt->bus_id, lu->lun, lu->retries);
+@@ -1111,6 +1115,7 @@ static int sbp2_probe(struct device *dev)
+ 	kref_init(&tgt->kref);
+ 	INIT_LIST_HEAD(&tgt->lu_list);
+ 	tgt->bus_id = unit->device.bus_id;
++	tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
+ 
+ 	if (fw_device_enable_phys_dma(device) < 0)
+ 		goto fail_shost_put;
+@@ -1119,6 +1124,7 @@ static int sbp2_probe(struct device *dev)
+ 		goto fail_shost_put;
+ 
+ 	fw_device_get(device);
++	fw_unit_get(unit);
+ 
+ 	/* Initialize to values that won't match anything in our table. */
+ 	firmware_revision = 0xff000000;
+@@ -1134,8 +1140,6 @@ static int sbp2_probe(struct device *dev)
+ 
+ 	sbp2_init_workarounds(tgt, model, firmware_revision);
+ 
+-	get_device(&unit->device);
+-
+ 	/* Do the login in a workqueue so we can easily reschedule retries. */
+ 	list_for_each_entry(lu, &tgt->lu_list, link)
+ 		sbp2_queue_work(lu, 0);
+@@ -1367,9 +1371,12 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ 	 * tables.
+ 	 */
+ 	if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) {
+-		orb->request.data_descriptor.high = lu->tgt->address_high;
+-		orb->request.data_descriptor.low  = sg_dma_address(sg);
+-		orb->request.misc |= COMMAND_ORB_DATA_SIZE(sg_dma_len(sg));
++		orb->request.data_descriptor.high =
++			cpu_to_be32(lu->tgt->address_high);
++		orb->request.data_descriptor.low  =
++			cpu_to_be32(sg_dma_address(sg));
++		orb->request.misc |=
++			cpu_to_be32(COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)));
+ 		return 0;
+ 	}
+ 
+@@ -1390,16 +1397,14 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ 				goto fail_page_table;
+ 			}
+ 			l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
+-			orb->page_table[j].low = sg_addr;
+-			orb->page_table[j].high = (l << 16);
++			orb->page_table[j].low = cpu_to_be32(sg_addr);
++			orb->page_table[j].high = cpu_to_be32(l << 16);
+ 			sg_addr += l;
+ 			sg_len -= l;
+ 			j++;
+ 		}
+ 	}
+ 
+-	fw_memcpy_to_be32(orb->page_table, orb->page_table,
+-			  sizeof(orb->page_table[0]) * j);
+ 	orb->page_table_bus =
+ 		dma_map_single(device->card->device, orb->page_table,
+ 			       sizeof(orb->page_table), DMA_TO_DEVICE);
+@@ -1413,11 +1418,10 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ 	 * initiator (i.e. us), but data_descriptor can refer to data
+ 	 * on other nodes so we need to put our ID in descriptor.high.
+ 	 */
+-	orb->request.data_descriptor.high = lu->tgt->address_high;
+-	orb->request.data_descriptor.low  = orb->page_table_bus;
+-	orb->request.misc |=
+-		COMMAND_ORB_PAGE_TABLE_PRESENT |
+-		COMMAND_ORB_DATA_SIZE(j);
++	orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high);
++	orb->request.data_descriptor.low  = cpu_to_be32(orb->page_table_bus);
++	orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
++					 COMMAND_ORB_DATA_SIZE(j));
+ 
+ 	return 0;
+ 
+@@ -1463,8 +1467,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
+ 	orb->done = done;
+ 	orb->cmd  = cmd;
+ 
+-	orb->request.next.high   = SBP2_ORB_NULL;
+-	orb->request.next.low    = 0x0;
++	orb->request.next.high   = cpu_to_be32(SBP2_ORB_NULL);
+ 	/*
+ 	 * At speed 100 we can do 512 bytes per packet, at speed 200,
+ 	 * 1024 bytes per packet etc.  The SBP-2 max_payload field
+@@ -1473,25 +1476,17 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
+ 	 */
+ 	max_payload = min(device->max_speed + 7,
+ 			  device->card->max_receive - 1);
+-	orb->request.misc =
++	orb->request.misc = cpu_to_be32(
+ 		COMMAND_ORB_MAX_PAYLOAD(max_payload) |
+ 		COMMAND_ORB_SPEED(device->max_speed) |
+-		COMMAND_ORB_NOTIFY;
++		COMMAND_ORB_NOTIFY);
+ 
+ 	if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+-		orb->request.misc |=
+-			COMMAND_ORB_DIRECTION(SBP2_DIRECTION_FROM_MEDIA);
+-	else if (cmd->sc_data_direction == DMA_TO_DEVICE)
+-		orb->request.misc |=
+-			COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
++		orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION);
+ 
+ 	if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
+ 		goto out;
+ 
+-	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+-
+-	memset(orb->request.command_block,
+-	       0, sizeof(orb->request.command_block));
+ 	memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+ 
+ 	orb->base.callback = complete_command_orb;
+@@ -1519,11 +1514,8 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
+ 
+ 	sdev->allow_restart = 1;
+ 
+-	/*
+-	 * Update the dma alignment (minimum alignment requirements for
+-	 * start and end of DMA transfers) to be a sector
+-	 */
+-	blk_queue_update_dma_alignment(sdev->request_queue, 511);
++	/* SBP-2 requires quadlet alignment of the data buffers. */
++	blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
+ 
+ 	if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+ 		sdev->inquiry_len = 36;
+@@ -1581,16 +1573,14 @@ sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
+ {
+ 	struct scsi_device *sdev = to_scsi_device(dev);
+ 	struct sbp2_logical_unit *lu;
+-	struct fw_device *device;
+ 
+ 	if (!sdev)
+ 		return 0;
+ 
+ 	lu = sdev->hostdata;
+-	device = fw_device(lu->tgt->unit->device.parent);
+ 
+-	return sprintf(buf, "%08x%08x:%06x:%04x\n",
+-			device->config_rom[3], device->config_rom[4],
++	return sprintf(buf, "%016llx:%06x:%04x\n",
++			(unsigned long long)lu->tgt->guid,
+ 			lu->tgt->directory_id, lu->lun);
+ }
+ 
+diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
+index d2c7a3d..213b0ff 100644
+--- a/drivers/firewire/fw-topology.c
++++ b/drivers/firewire/fw-topology.c
+@@ -108,6 +108,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color)
+ 	node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid);
+ 	node->link_on = SELF_ID_LINK_ON(sid);
+ 	node->phy_speed = SELF_ID_PHY_SPEED(sid);
++	node->initiated_reset = SELF_ID_PHY_INITIATOR(sid);
+ 	node->port_count = port_count;
+ 
+ 	atomic_set(&node->ref_count, 1);
+@@ -289,12 +290,11 @@ static struct fw_node *build_tree(struct fw_card *card,
+ 			beta_repeaters_present = true;
+ 
+ 		/*
+-		 * If all PHYs does not report the same gap count
+-		 * setting, we fall back to 63 which will force a gap
+-		 * count reconfiguration and a reset.
++		 * If PHYs report different gap counts, set an invalid count
++		 * which will force a gap count reconfiguration and a reset.
+ 		 */
+ 		if (SELF_ID_GAP_COUNT(q) != gap_count)
+-			gap_count = 63;
++			gap_count = 0;
+ 
+ 		update_hop_count(node);
+ 
+@@ -431,6 +431,8 @@ update_tree(struct fw_card *card, struct fw_node *root)
+ 			event = FW_NODE_LINK_OFF;
+ 		else if (!node0->link_on && node1->link_on)
+ 			event = FW_NODE_LINK_ON;
++		else if (node1->initiated_reset && node1->link_on)
++			event = FW_NODE_INITIATED_RESET;
+ 		else
+ 			event = FW_NODE_UPDATED;
+ 
+diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
+index cedc1ec..addb9f8 100644
+--- a/drivers/firewire/fw-topology.h
++++ b/drivers/firewire/fw-topology.h
+@@ -20,11 +20,12 @@
+ #define __fw_topology_h
+ 
+ enum {
+-	FW_NODE_CREATED =   0x00,
+-	FW_NODE_UPDATED =   0x01,
+-	FW_NODE_DESTROYED = 0x02,
+-	FW_NODE_LINK_ON =   0x03,
+-	FW_NODE_LINK_OFF =  0x04,
++	FW_NODE_CREATED,
++	FW_NODE_UPDATED,
++	FW_NODE_DESTROYED,
++	FW_NODE_LINK_ON,
++	FW_NODE_LINK_OFF,
++	FW_NODE_INITIATED_RESET,
+ };
+ 
+ struct fw_node {
+diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
+index e6f1bda..ccf0e4c 100644
+--- a/drivers/firewire/fw-transaction.c
++++ b/drivers/firewire/fw-transaction.c
+@@ -18,6 +18,7 @@
+  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+ 
++#include <linux/completion.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -28,7 +29,6 @@
+ #include <linux/list.h>
+ #include <linux/kthread.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ 
+ #include "fw-transaction.h"
+ #include "fw-topology.h"
+@@ -294,42 +294,40 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
+ }
+ EXPORT_SYMBOL(fw_send_request);
+ 
++struct fw_phy_packet {
++	struct fw_packet packet;
++	struct completion done;
++};
++
+ static void
+ transmit_phy_packet_callback(struct fw_packet *packet,
+ 			     struct fw_card *card, int status)
+ {
+-	kfree(packet);
+-}
+-
+-static void send_phy_packet(struct fw_card *card, u32 data, int generation)
+-{
+-	struct fw_packet *packet;
+-
+-	packet = kzalloc(sizeof(*packet), GFP_ATOMIC);
+-	if (packet == NULL)
+-		return;
+-
+-	packet->header[0] = data;
+-	packet->header[1] = ~data;
+-	packet->header_length = 8;
+-	packet->payload_length = 0;
+-	packet->speed = SCODE_100;
+-	packet->generation = generation;
+-	packet->callback = transmit_phy_packet_callback;
++	struct fw_phy_packet *p =
++			container_of(packet, struct fw_phy_packet, packet);
+ 
+-	card->driver->send_request(card, packet);
++	complete(&p->done);
+ }
+ 
+ void fw_send_phy_config(struct fw_card *card,
+ 			int node_id, int generation, int gap_count)
+ {
+-	u32 q;
+-
+-	q = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
+-		PHY_CONFIG_ROOT_ID(node_id) |
+-		PHY_CONFIG_GAP_COUNT(gap_count);
+-
+-	send_phy_packet(card, q, generation);
++	struct fw_phy_packet p;
++	u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
++		   PHY_CONFIG_ROOT_ID(node_id) |
++		   PHY_CONFIG_GAP_COUNT(gap_count);
++
++	p.packet.header[0] = data;
++	p.packet.header[1] = ~data;
++	p.packet.header_length = 8;
++	p.packet.payload_length = 0;
++	p.packet.speed = SCODE_100;
++	p.packet.generation = generation;
++	p.packet.callback = transmit_phy_packet_callback;
++	init_completion(&p.done);
++
++	card->driver->send_request(card, &p.packet);
++	wait_for_completion(&p.done);
+ }
+ 
+ void fw_flush_transactions(struct fw_card *card)
+@@ -389,21 +387,21 @@ lookup_enclosing_address_handler(struct list_head *list,
+ static DEFINE_SPINLOCK(address_handler_lock);
+ static LIST_HEAD(address_handler_list);
+ 
+-const struct fw_address_region fw_low_memory_region =
+-	{ .start = 0x000000000000ULL, .end = 0x000100000000ULL,  };
+ const struct fw_address_region fw_high_memory_region =
+ 	{ .start = 0x000100000000ULL, .end = 0xffffe0000000ULL,  };
++EXPORT_SYMBOL(fw_high_memory_region);
++
++#if 0
++const struct fw_address_region fw_low_memory_region =
++	{ .start = 0x000000000000ULL, .end = 0x000100000000ULL,  };
+ const struct fw_address_region fw_private_region =
+ 	{ .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL,  };
+ const struct fw_address_region fw_csr_region =
+-	{ .start = 0xfffff0000000ULL, .end = 0xfffff0000800ULL,  };
++	{ .start = CSR_REGISTER_BASE,
++	  .end   = CSR_REGISTER_BASE | CSR_CONFIG_ROM_END,  };
+ const struct fw_address_region fw_unit_space_region =
+ 	{ .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, };
+-EXPORT_SYMBOL(fw_low_memory_region);
+-EXPORT_SYMBOL(fw_high_memory_region);
+-EXPORT_SYMBOL(fw_private_region);
+-EXPORT_SYMBOL(fw_csr_region);
+-EXPORT_SYMBOL(fw_unit_space_region);
++#endif  /*  0  */
+ 
+ /**
+  * Allocate a range of addresses in the node space of the OHCI
+@@ -747,7 +745,8 @@ fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
+ EXPORT_SYMBOL(fw_core_handle_response);
+ 
+ static const struct fw_address_region topology_map_region =
+-	{ .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, };
++	{ .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP,
++	  .end   = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, };
+ 
+ static void
+ handle_topology_map(struct fw_card *card, struct fw_request *request,
+@@ -785,7 +784,8 @@ static struct fw_address_handler topology_map = {
+ };
+ 
+ static const struct fw_address_region registers_region =
+-	{ .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, };
++	{ .start = CSR_REGISTER_BASE,
++	  .end   = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };
+ 
+ static void
+ handle_registers(struct fw_card *card, struct fw_request *request,
+@@ -794,7 +794,7 @@ handle_registers(struct fw_card *card, struct fw_request *request,
+ 		 unsigned long long offset,
+ 		 void *payload, size_t length, void *callback_data)
+ {
+-	int reg = offset - CSR_REGISTER_BASE;
++	int reg = offset & ~CSR_REGISTER_BASE;
+ 	unsigned long long bus_time;
+ 	__be32 *data = payload;
+ 
+diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
+index a43bb22..04d3854 100644
+--- a/drivers/firewire/fw-transaction.h
++++ b/drivers/firewire/fw-transaction.h
+@@ -201,11 +201,7 @@ struct fw_address_region {
+ 	u64 end;
+ };
+ 
+-extern const struct fw_address_region fw_low_memory_region;
+ extern const struct fw_address_region fw_high_memory_region;
+-extern const struct fw_address_region fw_private_region;
+-extern const struct fw_address_region fw_csr_region;
+-extern const struct fw_address_region fw_unit_space_region;
+ 
+ int fw_core_add_address_handler(struct fw_address_handler *handler,
+ 				const struct fw_address_region *region);
+@@ -221,12 +217,9 @@ struct fw_card {
+ 	const struct fw_card_driver *driver;
+ 	struct device *device;
+ 	atomic_t device_count;
+-	struct kref kref;
+ 
+ 	int node_id;
+ 	int generation;
+-	/* This is the generation used for timestamping incoming requests. */
+-	int request_generation;
+ 	int current_tlabel, tlabel_mask;
+ 	struct list_head transaction_list;
+ 	struct timer_list flush_timer;
+@@ -263,9 +256,6 @@ struct fw_card {
+ 	int bm_generation;
+ };
+ 
+-struct fw_card *fw_card_get(struct fw_card *card);
+-void fw_card_put(struct fw_card *card);
+-
+ /*
+  * The iso packet format allows for an immediate header/payload part
+  * stored in 'header' immediately after the packet info plus an
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index 05f02a3..40ffd76 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -93,4 +93,24 @@ config DMIID
+ 	  information from userspace through /sys/class/dmi/id/ or if you want
+ 	  DMI-based module auto-loading.
+ 
++config ISCSI_IBFT_FIND
++	bool "iSCSI Boot Firmware Table Attributes"
++	depends on X86
++	default n
++	help
++	  This option enables the kernel to find the region of memory
++	  in which the ISCSI Boot Firmware Table (iBFT) resides. This
++	  is necessary for iSCSI Boot Firmware Table Attributes module to work
++	  properly.
++
++config ISCSI_IBFT
++	tristate "iSCSI Boot Firmware Table Attributes module"
++	depends on ISCSI_IBFT_FIND
++	default	n
++	help
++	  This option enables support for detection and exposing of iSCSI
++	  Boot Firmware Table (iBFT) via sysfs to userspace. If you wish to
++	  detect iSCSI boot parameters dynamically during system boot, say Y.
++	  Otherwise, say N.
++
+ endmenu
+diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
+index 8d4ebc8..4c91471 100644
+--- a/drivers/firmware/Makefile
++++ b/drivers/firmware/Makefile
+@@ -8,3 +8,5 @@ obj-$(CONFIG_EFI_PCDP)		+= pcdp.o
+ obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
+ obj-$(CONFIG_DCDBAS)		+= dcdbas.o
+ obj-$(CONFIG_DMIID)		+= dmi-id.o
++obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
++obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
+diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
+index 1636806..f235940 100644
+--- a/drivers/firmware/dcdbas.c
++++ b/drivers/firmware/dcdbas.c
+@@ -35,7 +35,6 @@
+ #include <linux/types.h>
+ #include <linux/mutex.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ 
+ #include "dcdbas.h"
+ 
+@@ -265,7 +264,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
+ 
+ 	/* SMI requires CPU 0 */
+ 	old_mask = current->cpus_allowed;
+-	set_cpus_allowed(current, cpumask_of_cpu(0));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu(0));
+ 	if (smp_processor_id() != 0) {
+ 		dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
+ 			__FUNCTION__);
+@@ -285,7 +284,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
+ 	);
+ 
+ out:
+-	set_cpus_allowed(current, old_mask);
++	set_cpus_allowed_ptr(current, &old_mask);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
+new file mode 100644
+index 0000000..8024e3b
+--- /dev/null
++++ b/drivers/firmware/iscsi_ibft.c
+@@ -0,0 +1,982 @@
++/*
++ *  Copyright 2007 Red Hat, Inc.
++ *  by Peter Jones <pjones at redhat.com>
++ *  Copyright 2008 IBM, Inc.
++ *  by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *  Copyright 2008
++ *  by Konrad Rzeszutek <ketuzsezr at darnok.org>
++ *
++ * This code exposes the iSCSI Boot Format Table to userland via sysfs.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * Changelog:
++ *
++ *  14 Mar 2008 - Konrad Rzeszutek <ketuzsezr at darnok.org>
++ *    Updated comments and copyrights. (v0.4.9)
++ *
++ *  11 Feb 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *    Converted to using ibft_addr. (v0.4.8)
++ *
++ *   8 Feb 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *    Combined two functions in one: reserve_ibft_region. (v0.4.7)
++ *
++ *  30 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   Added logic to handle IPv6 addresses. (v0.4.6)
++ *
++ *  25 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   Added logic to handle badly not-to-spec iBFT. (v0.4.5)
++ *
++ *   4 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   Added __init to function declarations. (v0.4.4)
++ *
++ *  21 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   Updated kobject registration, combined unregister functions in one
++ *   and code and style cleanup. (v0.4.3)
++ *
++ *   5 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   Added end-markers to enums and re-organized kobject registration. (v0.4.2)
++ *
++ *   4 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   Created 'device' sysfs link to the NIC and style cleanup. (v0.4.1)
++ *
++ *  28 Nov 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   Added sysfs-ibft documentation, moved 'find_ibft' function to
++ *   in its own file and added text attributes for every struct field.  (v0.4)
++ *
++ *  21 Nov 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   Added text attributes emulating OpenFirmware /proc/device-tree naming.
++ *   Removed binary /sysfs interface (v0.3)
++ *
++ *  29 Aug 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   Added functionality in setup.c to reserve iBFT region. (v0.2)
++ *
++ *  27 Aug 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *   First version exposing iBFT data via a binary /sysfs. (v0.1)
++ *
++ */
++
++
++#include <linux/blkdev.h>
++#include <linux/capability.h>
++#include <linux/ctype.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/iscsi_ibft.h>
++#include <linux/limits.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/string.h>
++#include <linux/types.h>
++
++#define IBFT_ISCSI_VERSION "0.4.9"
++#define IBFT_ISCSI_DATE "2008-Mar-14"
++
++MODULE_AUTHOR("Peter Jones <pjones at redhat.com> and \
++Konrad Rzeszutek <ketuzsezr at darnok.org>");
++MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(IBFT_ISCSI_VERSION);
++
++struct ibft_hdr {
++	u8 id;
++	u8 version;
++	u16 length;
++	u8 index;
++	u8 flags;
++} __attribute__((__packed__));
++
++struct ibft_control {
++	struct ibft_hdr hdr;
++	u16 extensions;
++	u16 initiator_off;
++	u16 nic0_off;
++	u16 tgt0_off;
++	u16 nic1_off;
++	u16 tgt1_off;
++} __attribute__((__packed__));
++
++struct ibft_initiator {
++	struct ibft_hdr hdr;
++	char isns_server[16];
++	char slp_server[16];
++	char pri_radius_server[16];
++	char sec_radius_server[16];
++	u16 initiator_name_len;
++	u16 initiator_name_off;
++} __attribute__((__packed__));
++
++struct ibft_nic {
++	struct ibft_hdr hdr;
++	char ip_addr[16];
++	u8 subnet_mask_prefix;
++	u8 origin;
++	char gateway[16];
++	char primary_dns[16];
++	char secondary_dns[16];
++	char dhcp[16];
++	u16 vlan;
++	char mac[6];
++	u16 pci_bdf;
++	u16 hostname_len;
++	u16 hostname_off;
++} __attribute__((__packed__));
++
++struct ibft_tgt {
++	struct ibft_hdr hdr;
++	char ip_addr[16];
++	u16 port;
++	char lun[8];
++	u8 chap_type;
++	u8 nic_assoc;
++	u16 tgt_name_len;
++	u16 tgt_name_off;
++	u16 chap_name_len;
++	u16 chap_name_off;
++	u16 chap_secret_len;
++	u16 chap_secret_off;
++	u16 rev_chap_name_len;
++	u16 rev_chap_name_off;
++	u16 rev_chap_secret_len;
++	u16 rev_chap_secret_off;
++} __attribute__((__packed__));
++
++/*
++ * The kobject different types and its names.
++ *
++*/
++enum ibft_id {
++	id_reserved = 0, /* We don't support. */
++	id_control = 1, /* Should show up only once and is not exported. */
++	id_initiator = 2,
++	id_nic = 3,
++	id_target = 4,
++	id_extensions = 5, /* We don't support. */
++	id_end_marker,
++};
++
++/*
++ * We do not support the other types, hence the usage of NULL.
++ * This maps to the enum ibft_id.
++ */
++static const char *ibft_id_names[] =
++	{NULL, NULL, "initiator", "ethernet%d", "target%d", NULL, NULL};
++
++/*
++ * The text attributes names for each of the kobjects.
++*/
++enum ibft_eth_properties_enum {
++	ibft_eth_index,
++	ibft_eth_flags,
++	ibft_eth_ip_addr,
++	ibft_eth_subnet_mask,
++	ibft_eth_origin,
++	ibft_eth_gateway,
++	ibft_eth_primary_dns,
++	ibft_eth_secondary_dns,
++	ibft_eth_dhcp,
++	ibft_eth_vlan,
++	ibft_eth_mac,
++	/* ibft_eth_pci_bdf - this is replaced by link to the device itself. */
++	ibft_eth_hostname,
++	ibft_eth_end_marker,
++};
++
++static const char *ibft_eth_properties[] =
++	{"index", "flags", "ip-addr", "subnet-mask", "origin", "gateway",
++	"primary-dns", "secondary-dns", "dhcp", "vlan", "mac", "hostname",
++	NULL};
++
++enum ibft_tgt_properties_enum {
++	ibft_tgt_index,
++	ibft_tgt_flags,
++	ibft_tgt_ip_addr,
++	ibft_tgt_port,
++	ibft_tgt_lun,
++	ibft_tgt_chap_type,
++	ibft_tgt_nic_assoc,
++	ibft_tgt_name,
++	ibft_tgt_chap_name,
++	ibft_tgt_chap_secret,
++	ibft_tgt_rev_chap_name,
++	ibft_tgt_rev_chap_secret,
++	ibft_tgt_end_marker,
++};
++
++static const char *ibft_tgt_properties[] =
++	{"index", "flags", "ip-addr", "port", "lun", "chap-type", "nic-assoc",
++	"target-name", "chap-name", "chap-secret", "rev-chap-name",
++	"rev-chap-name-secret", NULL};
++
++enum ibft_initiator_properties_enum {
++	ibft_init_index,
++	ibft_init_flags,
++	ibft_init_isns_server,
++	ibft_init_slp_server,
++	ibft_init_pri_radius_server,
++	ibft_init_sec_radius_server,
++	ibft_init_initiator_name,
++	ibft_init_end_marker,
++};
++
++static const char *ibft_initiator_properties[] =
++	{"index", "flags", "isns-server", "slp-server", "pri-radius-server",
++	"sec-radius-server", "initiator-name", NULL};
++
++/*
++ * The kobject and attribute structures.
++ */
++
++struct ibft_kobject {
++	struct ibft_table_header *header;
++	union {
++		struct ibft_initiator *initiator;
++		struct ibft_nic *nic;
++		struct ibft_tgt *tgt;
++		struct ibft_hdr *hdr;
++	};
++	struct kobject kobj;
++	struct list_head node;
++};
++
++struct ibft_attribute {
++	struct attribute attr;
++	ssize_t (*show) (struct  ibft_kobject *entry,
++			 struct ibft_attribute *attr, char *buf);
++	union {
++		struct ibft_initiator *initiator;
++		struct ibft_nic *nic;
++		struct ibft_tgt *tgt;
++		struct ibft_hdr *hdr;
++	};
++	struct kobject *kobj;
++	int type; /* The enum of the type. This can be any value of:
++		ibft_eth_properties_enum, ibft_tgt_properties_enum,
++		or ibft_initiator_properties_enum. */
++	struct list_head node;
++};
++
++static LIST_HEAD(ibft_attr_list);
++static LIST_HEAD(ibft_kobject_list);
++
++static const char nulls[16];
++
++/*
++ * Helper functions to parse data properly.
++ */
++static ssize_t sprintf_ipaddr(char *buf, u8 *ip)
++{
++	char *str = buf;
++
++	if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 &&
++	    ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && ip[7] == 0 &&
++	    ip[8] == 0 && ip[9] == 0 && ip[10] == 0xff && ip[11] == 0xff) {
++		/*
++		 * IPV4
++		 */
++		str += sprintf(buf, NIPQUAD_FMT, ip[12],
++			       ip[13], ip[14], ip[15]);
++	} else {
++		/*
++		 * IPv6
++		 */
++		str += sprintf(str, NIP6_FMT, ntohs(ip[0]), ntohs(ip[1]),
++			       ntohs(ip[2]), ntohs(ip[3]), ntohs(ip[4]),
++			       ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]));
++	}
++	str += sprintf(str, "\n");
++	return str - buf;
++}
++
++static ssize_t sprintf_string(char *str, int len, char *buf)
++{
++	return sprintf(str, "%.*s\n", len, buf);
++}
++
++/*
++ * Helper function to verify the IBFT header.
++ */
++static int ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length)
++{
++	if (hdr->id != id) {
++		printk(KERN_ERR "iBFT error: We expected the " \
++				"field header.id to have %d but " \
++				"found %d instead!\n", id, hdr->id);
++		return -ENODEV;
++	}
++	if (hdr->length != length) {
++		printk(KERN_ERR "iBFT error: We expected the " \
++				"field header.length to have %d but " \
++				"found %d instead!\n", length, hdr->length);
++		return -ENODEV;
++	}
++
++	return 0;
++}
++
++static void ibft_release(struct kobject *kobj)
++{
++	struct ibft_kobject *ibft =
++		container_of(kobj, struct ibft_kobject, kobj);
++	kfree(ibft);
++}
++
++/*
++ *  Routines for parsing the iBFT data to be human readable.
++ */
++ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
++				  struct ibft_attribute *attr,
++				  char *buf)
++{
++	struct ibft_initiator *initiator = entry->initiator;
++	void *ibft_loc = entry->header;
++	char *str = buf;
++
++	if (!initiator)
++		return 0;
++
++	switch (attr->type) {
++	case ibft_init_index:
++		str += sprintf(str, "%d\n", initiator->hdr.index);
++		break;
++	case ibft_init_flags:
++		str += sprintf(str, "%d\n", initiator->hdr.flags);
++		break;
++	case ibft_init_isns_server:
++		str += sprintf_ipaddr(str, initiator->isns_server);
++		break;
++	case ibft_init_slp_server:
++		str += sprintf_ipaddr(str, initiator->slp_server);
++		break;
++	case ibft_init_pri_radius_server:
++		str += sprintf_ipaddr(str, initiator->pri_radius_server);
++		break;
++	case ibft_init_sec_radius_server:
++		str += sprintf_ipaddr(str, initiator->sec_radius_server);
++		break;
++	case ibft_init_initiator_name:
++		str += sprintf_string(str, initiator->initiator_name_len,
++				      (char *)ibft_loc +
++				      initiator->initiator_name_off);
++		break;
++	default:
++		break;
++	}
++
++	return str - buf;
++}
++
++ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
++			    struct ibft_attribute *attr,
++			    char *buf)
++{
++	struct ibft_nic *nic = entry->nic;
++	void *ibft_loc = entry->header;
++	char *str = buf;
++	char *mac;
++	int val;
++
++	if (!nic)
++		return 0;
++
++	switch (attr->type) {
++	case ibft_eth_index:
++		str += sprintf(str, "%d\n", nic->hdr.index);
++		break;
++	case ibft_eth_flags:
++		str += sprintf(str, "%d\n", nic->hdr.flags);
++		break;
++	case ibft_eth_ip_addr:
++		str += sprintf_ipaddr(str, nic->ip_addr);
++		break;
++	case ibft_eth_subnet_mask:
++		val = ~((1 << (32-nic->subnet_mask_prefix))-1);
++		str += sprintf(str, NIPQUAD_FMT,
++			       (u8)(val >> 24), (u8)(val >> 16),
++			       (u8)(val >> 8), (u8)(val));
++		break;
++	case ibft_eth_origin:
++		str += sprintf(str, "%d\n", nic->origin);
++		break;
++	case ibft_eth_gateway:
++		str += sprintf_ipaddr(str, nic->gateway);
++		break;
++	case ibft_eth_primary_dns:
++		str += sprintf_ipaddr(str, nic->primary_dns);
++		break;
++	case ibft_eth_secondary_dns:
++		str += sprintf_ipaddr(str, nic->secondary_dns);
++		break;
++	case ibft_eth_dhcp:
++		str += sprintf_ipaddr(str, nic->dhcp);
++		break;
++	case ibft_eth_vlan:
++		str += sprintf(str, "%d\n", nic->vlan);
++		break;
++	case ibft_eth_mac:
++		mac = nic->mac;
++		str += sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x\n",
++			       (u8)mac[0], (u8)mac[1], (u8)mac[2],
++			       (u8)mac[3], (u8)mac[4], (u8)mac[5]);
++		break;
++	case ibft_eth_hostname:
++		str += sprintf_string(str, nic->hostname_len,
++				      (char *)ibft_loc + nic->hostname_off);
++		break;
++	default:
++		break;
++	}
++
++	return str - buf;
++};
++
++ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
++			       struct ibft_attribute *attr,
++			       char *buf)
++{
++	struct ibft_tgt *tgt = entry->tgt;
++	void *ibft_loc = entry->header;
++	char *str = buf;
++	int i;
++
++	if (!tgt)
++		return 0;
++
++	switch (attr->type) {
++	case ibft_tgt_index:
++		str += sprintf(str, "%d\n", tgt->hdr.index);
++		break;
++	case ibft_tgt_flags:
++		str += sprintf(str, "%d\n", tgt->hdr.flags);
++		break;
++	case ibft_tgt_ip_addr:
++		str += sprintf_ipaddr(str, tgt->ip_addr);
++		break;
++	case ibft_tgt_port:
++		str += sprintf(str, "%d\n", tgt->port);
++		break;
++	case ibft_tgt_lun:
++		for (i = 0; i < 8; i++)
++			str += sprintf(str, "%x", (u8)tgt->lun[i]);
++		str += sprintf(str, "\n");
++		break;
++	case ibft_tgt_nic_assoc:
++		str += sprintf(str, "%d\n", tgt->nic_assoc);
++		break;
++	case ibft_tgt_chap_type:
++		str += sprintf(str, "%d\n", tgt->chap_type);
++		break;
++	case ibft_tgt_name:
++		str += sprintf_string(str, tgt->tgt_name_len,
++				      (char *)ibft_loc + tgt->tgt_name_off);
++		break;
++	case ibft_tgt_chap_name:
++		str += sprintf_string(str, tgt->chap_name_len,
++				      (char *)ibft_loc + tgt->chap_name_off);
++		break;
++	case ibft_tgt_chap_secret:
++		str += sprintf_string(str, tgt->chap_secret_len,
++				      (char *)ibft_loc + tgt->chap_secret_off);
++		break;
++	case ibft_tgt_rev_chap_name:
++		str += sprintf_string(str, tgt->rev_chap_name_len,
++				      (char *)ibft_loc +
++				      tgt->rev_chap_name_off);
++		break;
++	case ibft_tgt_rev_chap_secret:
++		str += sprintf_string(str, tgt->rev_chap_secret_len,
++				      (char *)ibft_loc +
++				      tgt->rev_chap_secret_off);
++		break;
++	default:
++		break;
++	}
++
++	return str - buf;
++}
++
++/*
++ * The routine called for all sysfs attributes.
++ */
++static ssize_t ibft_show_attribute(struct kobject *kobj,
++				    struct attribute *attr,
++				    char *buf)
++{
++	struct ibft_kobject *dev =
++		container_of(kobj, struct ibft_kobject, kobj);
++	struct ibft_attribute *ibft_attr =
++		container_of(attr, struct ibft_attribute, attr);
++	ssize_t ret = -EIO;
++	char *str = buf;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EACCES;
++
++	if (ibft_attr->show)
++		ret = ibft_attr->show(dev, ibft_attr, str);
++
++	return ret;
++}
++
++static struct sysfs_ops ibft_attr_ops = {
++	.show = ibft_show_attribute,
++};
++
++static struct kobj_type ibft_ktype = {
++	.release = ibft_release,
++	.sysfs_ops = &ibft_attr_ops,
++};
++
++static struct kset *ibft_kset;
++
++static int __init ibft_check_device(void)
++{
++	int len;
++	u8 *pos;
++	u8 csum = 0;
++
++	len = ibft_addr->length;
++
++	/* Sanity checking of iBFT. */
++	if (ibft_addr->revision != 1) {
++		printk(KERN_ERR "iBFT module supports only revision 1, " \
++				"while this is %d.\n", ibft_addr->revision);
++		return -ENOENT;
++	}
++	for (pos = (u8 *)ibft_addr; pos < (u8 *)ibft_addr + len; pos++)
++		csum += *pos;
++
++	if (csum) {
++		printk(KERN_ERR "iBFT has incorrect checksum (0x%x)!\n", csum);
++		return -ENOENT;
++	}
++
++	return 0;
++}
++
++/*
++ * Helper function for ibft_register_kobjects.
++ */
++static int __init ibft_create_kobject(struct ibft_table_header *header,
++				       struct ibft_hdr *hdr,
++				       struct list_head *list)
++{
++	struct ibft_kobject *ibft_kobj = NULL;
++	struct ibft_nic *nic = (struct ibft_nic *)hdr;
++	struct pci_dev *pci_dev;
++	int rc = 0;
++
++	ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL);
++	if (!ibft_kobj)
++		return -ENOMEM;
++
++	ibft_kobj->header = header;
++	ibft_kobj->hdr = hdr;
++
++	switch (hdr->id) {
++	case id_initiator:
++		rc = ibft_verify_hdr("initiator", hdr, id_initiator,
++				     sizeof(*ibft_kobj->initiator));
++		break;
++	case id_nic:
++		rc = ibft_verify_hdr("ethernet", hdr, id_nic,
++				     sizeof(*ibft_kobj->nic));
++		break;
++	case id_target:
++		rc = ibft_verify_hdr("target", hdr, id_target,
++				     sizeof(*ibft_kobj->tgt));
++		break;
++	case id_reserved:
++	case id_control:
++	case id_extensions:
++		/* Fields which we don't support. Ignore them */
++		rc = 1;
++		break;
++	default:
++		printk(KERN_ERR "iBFT has unknown structure type (%d). " \
++				"Report this bug to %.6s!\n", hdr->id,
++				header->oem_id);
++		rc = 1;
++		break;
++	}
++
++	if (rc) {
++		/* Skip adding this kobject, but exit with non-fatal error. */
++		kfree(ibft_kobj);
++		goto out_invalid_struct;
++	}
++
++	ibft_kobj->kobj.kset = ibft_kset;
++
++	rc = kobject_init_and_add(&ibft_kobj->kobj, &ibft_ktype,
++				  NULL, ibft_id_names[hdr->id], hdr->index);
++
++	if (rc) {
++		kfree(ibft_kobj);
++		goto out;
++	}
++
++	kobject_uevent(&ibft_kobj->kobj, KOBJ_ADD);
++
++	if (hdr->id == id_nic) {
++		/*
++		* We don't search for the device in other domains than
++		* zero. This is because on x86 platforms the BIOS
++		* executes only devices which are in domain 0. Furthermore, the
++		* iBFT spec doesn't have a domain id field :-(
++		*/
++		pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8,
++					       (nic->pci_bdf & 0xff));
++		if (pci_dev) {
++			rc = sysfs_create_link(&ibft_kobj->kobj,
++					       &pci_dev->dev.kobj, "device");
++			pci_dev_put(pci_dev);
++		}
++	}
++
++	/* Nothing broke so lets add it to the list. */
++	list_add_tail(&ibft_kobj->node, list);
++out:
++	return rc;
++out_invalid_struct:
++	/* Unsupported structs are skipped. */
++	return 0;
++}
++
++/*
++ * Scan the IBFT table structure for the NIC and Target fields. When
++ * found add them on the passed-in list. We do not support the other
++ * fields at this point, so they are skipped.
++ */
++static int __init ibft_register_kobjects(struct ibft_table_header *header,
++					  struct list_head *list)
++{
++	struct ibft_control *control = NULL;
++	void *ptr, *end;
++	int rc = 0;
++	u16 offset;
++	u16 eot_offset;
++
++	control = (void *)header + sizeof(*header);
++	end = (void *)control + control->hdr.length;
++	eot_offset = (void *)header + header->length -
++		     (void *)control - sizeof(*header);
++	rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control,
++			     sizeof(*control));
++
++	/* iBFT table safety checking */
++	rc |= ((control->hdr.index) ? -ENODEV : 0);
++	if (rc) {
++		printk(KERN_ERR "iBFT error: Control header is invalid!\n");
++		return rc;
++	}
++	for (ptr = &control->initiator_off; ptr < end; ptr += sizeof(u16)) {
++		offset = *(u16 *)ptr;
++		if (offset && offset < header->length && offset < eot_offset) {
++			rc = ibft_create_kobject(header,
++						 (void *)header + offset,
++						 list);
++			if (rc)
++				break;
++		}
++	}
++
++	return rc;
++}
++
++static void ibft_unregister(struct list_head *attr_list,
++			     struct list_head *kobj_list)
++{
++	struct ibft_kobject *data = NULL, *n;
++	struct ibft_attribute *attr = NULL, *m;
++
++	list_for_each_entry_safe(attr, m, attr_list, node) {
++		sysfs_remove_file(attr->kobj, &attr->attr);
++		list_del(&attr->node);
++		kfree(attr);
++	};
++	list_del_init(attr_list);
++
++	list_for_each_entry_safe(data, n, kobj_list, node) {
++		list_del(&data->node);
++		if (data->hdr->id == id_nic)
++			sysfs_remove_link(&data->kobj, "device");
++		kobject_put(&data->kobj);
++	};
++	list_del_init(kobj_list);
++}
++
++static int __init ibft_create_attribute(struct ibft_kobject *kobj_data,
++					 int type,
++					 const char *name,
++					 ssize_t (*show)(struct ibft_kobject *,
++							 struct ibft_attribute*,
++							 char *buf),
++					 struct list_head *list)
++{
++	struct ibft_attribute *attr = NULL;
++	struct ibft_hdr *hdr = kobj_data->hdr;
++
++	attr = kmalloc(sizeof(*attr), GFP_KERNEL);
++	if (!attr)
++		return -ENOMEM;
++
++	attr->attr.name = name;
++	attr->attr.mode = S_IRUSR;
++	attr->attr.owner = THIS_MODULE;
++
++	attr->hdr = hdr;
++	attr->show = show;
++	attr->kobj = &kobj_data->kobj;
++	attr->type = type;
++
++	list_add_tail(&attr->node, list);
++
++	return 0;
++}
++
++/*
++ * Helper routiners to check to determine if the entry is valid
++ * in the proper iBFT structure.
++ */
++static int __init ibft_check_nic_for(struct ibft_nic *nic, int entry)
++{
++	int rc = 0;
++
++	switch (entry) {
++	case ibft_eth_index:
++	case ibft_eth_flags:
++		rc = 1;
++		break;
++	case ibft_eth_ip_addr:
++		if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++			rc = 1;
++		break;
++	case ibft_eth_subnet_mask:
++		if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++			rc = 1;
++		break;
++	case ibft_eth_origin:
++		rc = 1;
++		break;
++	case ibft_eth_gateway:
++		if (memcmp(nic->gateway, nulls, sizeof(nic->gateway)))
++			rc = 1;
++		break;
++	case ibft_eth_primary_dns:
++		if (memcmp(nic->primary_dns, nulls,
++			   sizeof(nic->primary_dns)))
++			rc = 1;
++		break;
++	case ibft_eth_secondary_dns:
++		if (memcmp(nic->secondary_dns, nulls,
++			   sizeof(nic->secondary_dns)))
++			rc = 1;
++		break;
++	case ibft_eth_dhcp:
++		if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++			rc = 1;
++		break;
++	case ibft_eth_vlan:
++	case ibft_eth_mac:
++		rc = 1;
++		break;
++	case ibft_eth_hostname:
++		if (nic->hostname_off)
++			rc = 1;
++		break;
++	default:
++		break;
++	}
++
++	return rc;
++}
++
++static int __init ibft_check_tgt_for(struct ibft_tgt *tgt, int entry)
++{
++	int rc = 0;
++
++	switch (entry) {
++	case ibft_tgt_index:
++	case ibft_tgt_flags:
++	case ibft_tgt_ip_addr:
++	case ibft_tgt_port:
++	case ibft_tgt_lun:
++	case ibft_tgt_nic_assoc:
++	case ibft_tgt_chap_type:
++		rc = 1;
++	case ibft_tgt_name:
++		if (tgt->tgt_name_len)
++			rc = 1;
++		break;
++	case ibft_tgt_chap_name:
++	case ibft_tgt_chap_secret:
++		if (tgt->chap_name_len)
++			rc = 1;
++		break;
++	case ibft_tgt_rev_chap_name:
++	case ibft_tgt_rev_chap_secret:
++		if (tgt->rev_chap_name_len)
++			rc = 1;
++		break;
++	default:
++		break;
++	}
++
++	return rc;
++}
++
++static int __init ibft_check_initiator_for(struct ibft_initiator *init,
++					    int entry)
++{
++	int rc = 0;
++
++	switch (entry) {
++	case ibft_init_index:
++	case ibft_init_flags:
++		rc = 1;
++		break;
++	case ibft_init_isns_server:
++		if (memcmp(init->isns_server, nulls,
++			   sizeof(init->isns_server)))
++			rc = 1;
++		break;
++	case ibft_init_slp_server:
++		if (memcmp(init->slp_server, nulls,
++			   sizeof(init->slp_server)))
++			rc = 1;
++		break;
++	case ibft_init_pri_radius_server:
++		if (memcmp(init->pri_radius_server, nulls,
++			   sizeof(init->pri_radius_server)))
++			rc = 1;
++		break;
++	case ibft_init_sec_radius_server:
++		if (memcmp(init->sec_radius_server, nulls,
++			   sizeof(init->sec_radius_server)))
++			rc = 1;
++		break;
++	case ibft_init_initiator_name:
++		if (init->initiator_name_len)
++			rc = 1;
++		break;
++	default:
++		break;
++	}
++
++	return rc;
++}
++
++/*
++ *  Register the attributes for all of the kobjects.
++ */
++static int __init ibft_register_attributes(struct list_head *kobject_list,
++					    struct list_head *attr_list)
++{
++	int rc = 0, i = 0;
++	struct ibft_kobject *data = NULL;
++	struct ibft_attribute *attr = NULL, *m;
++
++	list_for_each_entry(data, kobject_list, node) {
++		switch (data->hdr->id) {
++		case id_nic:
++			for (i = 0; i < ibft_eth_end_marker && !rc; i++)
++				if (ibft_check_nic_for(data->nic, i))
++					rc = ibft_create_attribute(data, i,
++						ibft_eth_properties[i],
++						ibft_attr_show_nic, attr_list);
++			break;
++		case id_target:
++			for (i = 0; i < ibft_tgt_end_marker && !rc; i++)
++				if (ibft_check_tgt_for(data->tgt, i))
++					rc = ibft_create_attribute(data, i,
++						ibft_tgt_properties[i],
++						ibft_attr_show_target,
++						attr_list);
++			break;
++		case id_initiator:
++			for (i = 0; i < ibft_init_end_marker && !rc; i++)
++				if (ibft_check_initiator_for(
++					data->initiator, i))
++					rc = ibft_create_attribute(data, i,
++						ibft_initiator_properties[i],
++						ibft_attr_show_initiator,
++						attr_list);
++			break;
++		default:
++			break;
++		}
++		if (rc)
++			break;
++	}
++	list_for_each_entry_safe(attr, m, attr_list, node) {
++		rc = sysfs_create_file(attr->kobj, &attr->attr);
++		if (rc) {
++			list_del(&attr->node);
++			kfree(attr);
++			break;
++		}
++	}
++
++	return rc;
++}
++
++/*
++ * ibft_init() - creates sysfs tree entries for the iBFT data.
++ */
++static int __init ibft_init(void)
++{
++	int rc = 0;
++
++	ibft_kset = kset_create_and_add("ibft", NULL, firmware_kobj);
++	if (!ibft_kset)
++		return -ENOMEM;
++
++	if (ibft_addr) {
++		printk(KERN_INFO "iBFT detected at 0x%lx.\n",
++		       virt_to_phys((void *)ibft_addr));
++
++		rc = ibft_check_device();
++		if (rc)
++			goto out_firmware_unregister;
++
++		/* Scan the IBFT for data and register the kobjects. */
++		rc = ibft_register_kobjects(ibft_addr, &ibft_kobject_list);
++		if (rc)
++			goto out_free;
++
++		/* Register the attributes */
++		rc = ibft_register_attributes(&ibft_kobject_list,
++					      &ibft_attr_list);
++		if (rc)
++			goto out_free;
++	} else
++		printk(KERN_INFO "No iBFT detected.\n");
++
++	return 0;
++
++out_free:
++	ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
++out_firmware_unregister:
++	kset_unregister(ibft_kset);
++	return rc;
++}
++
++static void __exit ibft_exit(void)
++{
++	ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
++	kset_unregister(ibft_kset);
++}
++
++module_init(ibft_init);
++module_exit(ibft_exit);
+diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c
+new file mode 100644
+index 0000000..d0e5fa4
+--- /dev/null
++++ b/drivers/firmware/iscsi_ibft_find.c
+@@ -0,0 +1,84 @@
++/*
++ *  Copyright 2007 Red Hat, Inc.
++ *  by Peter Jones <pjones at redhat.com>
++ *  Copyright 2007 IBM, Inc.
++ *  by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *  Copyright 2008
++ *  by Konrad Rzeszutek <ketuzsezr at darnok.org>
++ *
++ * This code finds the iSCSI Boot Format Table.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/bootmem.h>
++#include <linux/blkdev.h>
++#include <linux/ctype.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/limits.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/string.h>
++#include <linux/types.h>
++
++#include <asm/mmzone.h>
++
++/*
++ * Physical location of iSCSI Boot Format Table.
++ */
++struct ibft_table_header *ibft_addr;
++EXPORT_SYMBOL_GPL(ibft_addr);
++
++#define IBFT_SIGN "iBFT"
++#define IBFT_SIGN_LEN 4
++#define IBFT_START 0x80000 /* 512kB */
++#define IBFT_END 0x100000 /* 1MB */
++#define VGA_MEM 0xA0000 /* VGA buffer */
++#define VGA_SIZE 0x20000 /* 128kB */
++
++
++/*
++ * Routine used to find the iSCSI Boot Format Table. The logical
++ * kernel address is set in the ibft_addr global variable.
++ */
++void __init reserve_ibft_region(void)
++{
++	unsigned long pos;
++	unsigned int len = 0;
++	void *virt;
++
++	ibft_addr = 0;
++
++	for (pos = IBFT_START; pos < IBFT_END; pos += 16) {
++		/* The table can't be inside the VGA BIOS reserved space,
++		 * so skip that area */
++		if (pos == VGA_MEM)
++			pos += VGA_SIZE;
++		virt = phys_to_virt(pos);
++		if (memcmp(virt, IBFT_SIGN, IBFT_SIGN_LEN) == 0) {
++			unsigned long *addr =
++			    (unsigned long *)phys_to_virt(pos + 4);
++			len = *addr;
++			/* if the length of the table extends past 1M,
++			 * the table cannot be valid. */
++			if (pos + len <= (IBFT_END-1)) {
++				ibft_addr = (struct ibft_table_header *)virt;
++				break;
++			}
++		}
++	}
++	if (ibft_addr)
++		reserve_bootmem(pos, PAGE_ALIGN(len), BOOTMEM_DEFAULT);
++}
++EXPORT_SYMBOL_GPL(reserve_ibft_region);
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index f0b00ec..e03c67d 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -44,8 +44,8 @@
+ 
+ #ifdef CONFIG_HID_DEBUG
+ int hid_debug = 0;
+-module_param_named(debug, hid_debug, bool, 0600);
+-MODULE_PARM_DESC(debug, "Turn HID debugging mode on and off");
++module_param_named(debug, hid_debug, int, 0600);
++MODULE_PARM_DESC(debug, "HID debugging (0=off, 1=probing info, 2=continuous data dumping)");
+ EXPORT_SYMBOL_GPL(hid_debug);
+ #endif
+ 
+@@ -97,7 +97,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
+ 	field->index = report->maxfield++;
+ 	report->field[field->index] = field;
+ 	field->usage = (struct hid_usage *)(field + 1);
+-	field->value = (unsigned *)(field->usage + usages);
++	field->value = (s32 *)(field->usage + usages);
+ 	field->report = report;
+ 
+ 	return field;
+@@ -830,7 +830,8 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s
+  * reporting to the layer).
+  */
+ 
+-void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
++static void hid_input_field(struct hid_device *hid, struct hid_field *field,
++			    __u8 *data, int interrupt)
+ {
+ 	unsigned n;
+ 	unsigned count = field->report_count;
+@@ -876,7 +877,6 @@ void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data
+ exit:
+ 	kfree(value);
+ }
+-EXPORT_SYMBOL_GPL(hid_input_field);
+ 
+ /*
+  * Output the field into the report.
+@@ -988,8 +988,13 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
+ 
+ 	if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
+ 		hid->hiddev_report_event(hid, report);
+-	if (hid->claimed & HID_CLAIMED_HIDRAW)
+-		hidraw_report_event(hid, data, size);
++	if (hid->claimed & HID_CLAIMED_HIDRAW) {
++		/* numbered reports need to be passed with the report num */
++		if (report_enum->numbered)
++			hidraw_report_event(hid, data - 1, size + 1);
++		else
++			hidraw_report_event(hid, data, size);
++	}
+ 
+ 	for (n = 0; n < report->maxfield; n++)
+ 		hid_input_field(hid, report->field[n], data, interrupt);
+diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
+index 5c24fe4..f88714b 100644
+--- a/drivers/hid/hid-debug.c
++++ b/drivers/hid/hid-debug.c
+@@ -498,7 +498,7 @@ void hid_dump_device(struct hid_device *device) {
+ EXPORT_SYMBOL_GPL(hid_dump_device);
+ 
+ void hid_dump_input(struct hid_usage *usage, __s32 value) {
+-	if (!hid_debug)
++	if (hid_debug < 2)
+ 		return;
+ 
+ 	printk(KERN_DEBUG "hid-debug: input ");
+diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
+index dceadd0..4c2052c 100644
+--- a/drivers/hid/hid-input-quirks.c
++++ b/drivers/hid/hid-input-quirks.c
+@@ -276,6 +276,21 @@ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
+ 	return 1;
+ }
+ 
++static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
++{
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
++		return 0;
++
++	switch (usage->hid & HID_USAGE) {
++		case 0x2003: map_key_clear(KEY_ZOOMIN);		break;
++		case 0x2103: map_key_clear(KEY_ZOOMOUT);	break;
++		default:
++			return 0;
++	}
++	return 1;
++}
++
+ #define VENDOR_ID_BELKIN			0x1020
+ #define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD	0x0006
+ 
+@@ -306,6 +321,9 @@ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
+ #define VENDOR_ID_PETALYNX			0x18b1
+ #define DEVICE_ID_PETALYNX_MAXTER_REMOTE	0x0037
+ 
++#define VENDOR_ID_SUNPLUS			0x04fc
++#define DEVICE_ID_SUNPLUS_WDESKTOP		0x05d8
++
+ static const struct hid_input_blacklist {
+ 	__u16 idVendor;
+ 	__u16 idProduct;
+@@ -332,8 +350,10 @@ static const struct hid_input_blacklist {
+ 	{ VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e },
+ 
+ 	{ VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote },
+-	
+-	{ 0, 0, 0 }
++
++	{ VENDOR_ID_SUNPLUS, DEVICE_ID_SUNPLUS_WDESKTOP, quirk_sunplus_wdesktop },
++
++	{ 0, 0, NULL }
+ };
+ 
+ int hidinput_mapping_quirks(struct hid_usage *usage, 
+diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
+index 7160fa6..18f0910 100644
+--- a/drivers/hid/usbhid/Kconfig
++++ b/drivers/hid/usbhid/Kconfig
+@@ -71,6 +71,14 @@ config LOGITECH_FF
+ 	  Note: if you say N here, this device will still be supported, but without
+ 	  force feedback.
+ 
++config LOGIRUMBLEPAD2_FF
++	bool "Logitech Rumblepad 2 support"
++	depends on HID_FF
++	select INPUT_FF_MEMLESS if USB_HID
++	help
++	  Say Y here if you want to enable force feedback support for Logitech
++	  Rumblepad 2 devices.
++
+ config PANTHERLORD_FF
+ 	bool "PantherLord/GreenAsia based device support"
+ 	depends on HID_FF
+@@ -80,8 +88,8 @@ config PANTHERLORD_FF
+ 	  or adapter and want to enable force feedback support for it.
+ 
+ config THRUSTMASTER_FF
+-	bool "ThrustMaster devices support (EXPERIMENTAL)"
+-	depends on HID_FF && EXPERIMENTAL
++	bool "ThrustMaster devices support"
++	depends on HID_FF
+ 	select INPUT_FF_MEMLESS if USB_HID
+ 	help
+ 	  Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
+diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile
+index 8e6ab5b..00a7b70 100644
+--- a/drivers/hid/usbhid/Makefile
++++ b/drivers/hid/usbhid/Makefile
+@@ -16,6 +16,9 @@ endif
+ ifeq ($(CONFIG_LOGITECH_FF),y)
+ 	usbhid-objs	+= hid-lgff.o
+ endif
++ifeq ($(CONFIG_LOGIRUMBLEPAD2_FF),y)
++	usbhid-objs	+= hid-lg2ff.o
++endif
+ ifeq ($(CONFIG_PANTHERLORD_FF),y)
+ 	usbhid-objs	+= hid-plff.o
+ endif
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index d95979f..e0d805f 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -82,6 +82,7 @@ static int hid_start_in(struct hid_device *hid)
+ 
+ 	spin_lock_irqsave(&usbhid->inlock, flags);
+ 	if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
++			!test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
+ 			!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
+ 		rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
+ 		if (rc != 0)
+@@ -155,7 +156,7 @@ static void hid_io_error(struct hid_device *hid)
+ 	spin_lock_irqsave(&usbhid->inlock, flags);
+ 
+ 	/* Stop when disconnected */
+-	if (usb_get_intfdata(usbhid->intf) == NULL)
++	if (test_bit(HID_DISCONNECTED, &usbhid->iofl))
+ 		goto done;
+ 
+ 	/* If it has been a while since the last error, we'll assume
+@@ -341,7 +342,7 @@ static void hid_irq_out(struct urb *urb)
+ 	if (usbhid->outhead != usbhid->outtail) {
+ 		if (hid_submit_out(hid)) {
+ 			clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+-			wake_up(&hid->wait);
++			wake_up(&usbhid->wait);
+ 		}
+ 		spin_unlock_irqrestore(&usbhid->outlock, flags);
+ 		return;
+@@ -349,7 +350,7 @@ static void hid_irq_out(struct urb *urb)
+ 
+ 	clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+ 	spin_unlock_irqrestore(&usbhid->outlock, flags);
+-	wake_up(&hid->wait);
++	wake_up(&usbhid->wait);
+ }
+ 
+ /*
+@@ -391,7 +392,7 @@ static void hid_ctrl(struct urb *urb)
+ 	if (usbhid->ctrlhead != usbhid->ctrltail) {
+ 		if (hid_submit_ctrl(hid)) {
+ 			clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+-			wake_up(&hid->wait);
++			wake_up(&usbhid->wait);
+ 		}
+ 		spin_unlock_irqrestore(&usbhid->ctrllock, flags);
+ 		return;
+@@ -399,7 +400,7 @@ static void hid_ctrl(struct urb *urb)
+ 
+ 	clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+ 	spin_unlock_irqrestore(&usbhid->ctrllock, flags);
+-	wake_up(&hid->wait);
++	wake_up(&usbhid->wait);
+ }
+ 
+ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+@@ -478,8 +479,9 @@ int usbhid_wait_io(struct hid_device *hid)
+ {
+ 	struct usbhid_device *usbhid = hid->driver_data;
+ 
+-	if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
+-					!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
++	if (!wait_event_timeout(usbhid->wait,
++				(!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
++				!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
+ 					10*HZ)) {
+ 		dbg_hid("timeout waiting for ctrl or out queue to clear\n");
+ 		return -1;
+@@ -610,10 +612,11 @@ static void usbhid_set_leds(struct hid_device *hid)
+ /*
+  * Traverse the supplied list of reports and find the longest
+  */
+-static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
++static void hid_find_max_report(struct hid_device *hid, unsigned int type,
++		unsigned int *max)
+ {
+ 	struct hid_report *report;
+-	int size;
++	unsigned int size;
+ 
+ 	list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
+ 		size = ((report->size - 1) >> 3) + 1;
+@@ -705,9 +708,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 	struct hid_descriptor *hdesc;
+ 	struct hid_device *hid;
+ 	u32 quirks = 0;
+-	unsigned rsize = 0;
++	unsigned int insize = 0, rsize = 0;
+ 	char *rdesc;
+-	int n, len, insize = 0;
++	int n, len;
+ 	struct usbhid_device *usbhid;
+ 
+ 	quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
+@@ -800,6 +803,22 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 		goto fail;
+ 	}
+ 
++	hid->name[0] = 0;
++
++	if (dev->manufacturer)
++		strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
++
++	if (dev->product) {
++		if (dev->manufacturer)
++			strlcat(hid->name, " ", sizeof(hid->name));
++		strlcat(hid->name, dev->product, sizeof(hid->name));
++	}
++
++	if (!strlen(hid->name))
++		snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
++			 le16_to_cpu(dev->descriptor.idVendor),
++			 le16_to_cpu(dev->descriptor.idProduct));
++
+ 	for (n = 0; n < interface->desc.bNumEndpoints; n++) {
+ 
+ 		struct usb_endpoint_descriptor *endpoint;
+@@ -812,6 +831,14 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 
+ 		interval = endpoint->bInterval;
+ 
++		/* Some vendors give fullspeed interval on highspeed devides */
++		if (quirks & HID_QUIRK_FULLSPEED_INTERVAL  &&
++		    dev->speed == USB_SPEED_HIGH) {
++			interval = fls(endpoint->bInterval*8);
++			printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n",
++			       hid->name, endpoint->bInterval, interval);
++		}
++
+ 		/* Change the polling interval of mice. */
+ 		if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
+ 			interval = hid_mousepoll_interval;
+@@ -844,8 +871,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 		goto fail;
+ 	}
+ 
+-	init_waitqueue_head(&hid->wait);
+-
++	init_waitqueue_head(&usbhid->wait);
+ 	INIT_WORK(&usbhid->reset_work, hid_reset);
+ 	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+ 
+@@ -859,22 +885,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ 	usbhid->intf = intf;
+ 	usbhid->ifnum = interface->desc.bInterfaceNumber;
+ 
+-	hid->name[0] = 0;
+-
+-	if (dev->manufacturer)
+-		strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
+-
+-	if (dev->product) {
+-		if (dev->manufacturer)
+-			strlcat(hid->name, " ", sizeof(hid->name));
+-		strlcat(hid->name, dev->product, sizeof(hid->name));
+-	}
+-
+-	if (!strlen(hid->name))
+-		snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
+-			 le16_to_cpu(dev->descriptor.idVendor),
+-			 le16_to_cpu(dev->descriptor.idProduct));
+-
+ 	hid->bus = BUS_USB;
+ 	hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
+ 	hid->product = le16_to_cpu(dev->descriptor.idProduct);
+@@ -932,6 +942,7 @@ static void hid_disconnect(struct usb_interface *intf)
+ 
+ 	spin_lock_irq(&usbhid->inlock);	/* Sync with error handler */
+ 	usb_set_intfdata(intf, NULL);
++	set_bit(HID_DISCONNECTED, &usbhid->iofl);
+ 	spin_unlock_irq(&usbhid->inlock);
+ 	usb_kill_urb(usbhid->urbin);
+ 	usb_kill_urb(usbhid->urbout);
+diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c
+index 4c210e1..1d0dac5 100644
+--- a/drivers/hid/usbhid/hid-ff.c
++++ b/drivers/hid/usbhid/hid-ff.c
+@@ -59,6 +59,9 @@ static struct hid_ff_initializer inits[] = {
+ 	{ 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
+ 	{ 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
+ #endif
++#ifdef CONFIG_LOGIRUMBLEPAD2_FF
++	{ 0x46d, 0xc218, hid_lg2ff_init }, /* Logitech Rumblepad 2 */
++#endif
+ #ifdef CONFIG_PANTHERLORD_FF
+ 	{ 0x810, 0x0001, hid_plff_init }, /* "Twin USB Joystick" */
+ 	{ 0xe8f, 0x0003, hid_plff_init }, /* "GreenAsia Inc.    USB Joystick     " */
+diff --git a/drivers/hid/usbhid/hid-lg2ff.c b/drivers/hid/usbhid/hid-lg2ff.c
+new file mode 100644
+index 0000000..d469bd0
+--- /dev/null
++++ b/drivers/hid/usbhid/hid-lg2ff.c
+@@ -0,0 +1,114 @@
++/*
++ *  Force feedback support for Logitech Rumblepad 2
++ *
++ *  Copyright (c) 2008 Anssi Hannula <anssi.hannula at gmail.com>
++ */
++
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++
++#include <linux/input.h>
++#include <linux/usb.h>
++#include <linux/hid.h>
++#include "usbhid.h"
++
++struct lg2ff_device {
++	struct hid_report *report;
++};
++
++static int play_effect(struct input_dev *dev, void *data,
++			 struct ff_effect *effect)
++{
++	struct hid_device *hid = input_get_drvdata(dev);
++	struct lg2ff_device *lg2ff = data;
++	int weak, strong;
++
++	strong = effect->u.rumble.strong_magnitude;
++	weak = effect->u.rumble.weak_magnitude;
++
++	if (weak || strong) {
++		weak = weak * 0xff / 0xffff;
++		strong = strong * 0xff / 0xffff;
++
++		lg2ff->report->field[0]->value[0] = 0x51;
++		lg2ff->report->field[0]->value[2] = weak;
++		lg2ff->report->field[0]->value[4] = strong;
++	} else {
++		lg2ff->report->field[0]->value[0] = 0xf3;
++		lg2ff->report->field[0]->value[2] = 0x00;
++		lg2ff->report->field[0]->value[4] = 0x00;
++	}
++
++	usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT);
++	return 0;
++}
++
++int hid_lg2ff_init(struct hid_device *hid)
++{
++	struct lg2ff_device *lg2ff;
++	struct hid_report *report;
++	struct hid_input *hidinput = list_entry(hid->inputs.next,
++						struct hid_input, list);
++	struct list_head *report_list =
++			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
++	struct input_dev *dev = hidinput->input;
++	int error;
++
++	if (list_empty(report_list)) {
++		printk(KERN_ERR "hid-lg2ff: no output report found\n");
++		return -ENODEV;
++	}
++
++	report = list_entry(report_list->next, struct hid_report, list);
++
++	if (report->maxfield < 1) {
++		printk(KERN_ERR "hid-lg2ff: output report is empty\n");
++		return -ENODEV;
++	}
++	if (report->field[0]->report_count < 7) {
++		printk(KERN_ERR "hid-lg2ff: not enough values in the field\n");
++		return -ENODEV;
++	}
++
++	lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
++	if (!lg2ff)
++		return -ENOMEM;
++
++	set_bit(FF_RUMBLE, dev->ffbit);
++
++	error = input_ff_create_memless(dev, lg2ff, play_effect);
++	if (error) {
++		kfree(lg2ff);
++		return error;
++	}
++
++	lg2ff->report = report;
++	report->field[0]->value[0] = 0xf3;
++	report->field[0]->value[1] = 0x00;
++	report->field[0]->value[2] = 0x00;
++	report->field[0]->value[3] = 0x00;
++	report->field[0]->value[4] = 0x00;
++	report->field[0]->value[5] = 0x00;
++	report->field[0]->value[6] = 0x00;
++
++	usbhid_submit_report(hid, report, USB_DIR_OUT);
++
++	printk(KERN_INFO "Force feedback for Logitech Rumblepad 2 by "
++	       "Anssi Hannula <anssi.hannula at gmail.com>\n");
++
++	return 0;
++}
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index e29a057..d3f8d91 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -32,6 +32,9 @@
+ #define USB_VENDOR_ID_ADS_TECH 		0x06e1
+ #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X	0xa155
+ 
++#define USB_VENDOR_ID_AFATECH		0x15a4
++#define USB_DEVICE_ID_AFATECH_AF9016	0x9016
++
+ #define USB_VENDOR_ID_AIPTEK		0x08ca
+ #define USB_DEVICE_ID_AIPTEK_01		0x0001
+ #define USB_DEVICE_ID_AIPTEK_10		0x0010
+@@ -124,6 +127,9 @@
+ #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+ #define USB_DEVICE_ID_DELORME_EM_LT20	0x0200
+ 
++#define USB_VENDOR_ID_DMI		0x0c0b
++#define USB_DEVICE_ID_DMI_ENC		0x5fab
++
+ #define USB_VENDOR_ID_ELO		0x04E7
+ #define USB_DEVICE_ID_ELO_TS2700	0x0020
+ 
+@@ -199,17 +205,6 @@
+ #define USB_DEVICE_ID_GTCO_502		0x0502
+ #define USB_DEVICE_ID_GTCO_503		0x0503
+ #define USB_DEVICE_ID_GTCO_504		0x0504
+-#define USB_DEVICE_ID_GTCO_600		0x0600
+-#define USB_DEVICE_ID_GTCO_601		0x0601
+-#define USB_DEVICE_ID_GTCO_602		0x0602
+-#define USB_DEVICE_ID_GTCO_603		0x0603
+-#define USB_DEVICE_ID_GTCO_604		0x0604
+-#define USB_DEVICE_ID_GTCO_605		0x0605
+-#define USB_DEVICE_ID_GTCO_606		0x0606
+-#define USB_DEVICE_ID_GTCO_607		0x0607
+-#define USB_DEVICE_ID_GTCO_608		0x0608
+-#define USB_DEVICE_ID_GTCO_609		0x0609
+-#define USB_DEVICE_ID_GTCO_609		0x0609
+ #define USB_DEVICE_ID_GTCO_1000		0x1000
+ #define USB_DEVICE_ID_GTCO_1001		0x1001
+ #define USB_DEVICE_ID_GTCO_1002		0x1002
+@@ -320,6 +315,7 @@
+ #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
+ #define USB_DEVICE_ID_MX3000_RECEIVER	0xc513
+ #define USB_DEVICE_ID_DINOVO_EDGE	0xc714
++#define USB_DEVICE_ID_DINOVO_MINI	0xc71f
+ 
+ #define USB_VENDOR_ID_MCC		0x09db
+ #define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
+@@ -332,6 +328,7 @@
+ #define USB_VENDOR_ID_MICROSOFT		0x045e
+ #define USB_DEVICE_ID_SIDEWINDER_GV	0x003b
+ #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
++#define USB_DEVICE_ID_DESKTOP_RECV_1028 0x00f9
+ #define USB_DEVICE_ID_MS_NE4K		0x00db
+ #define USB_DEVICE_ID_MS_LK6K		0x00f9
+ 
+@@ -377,6 +374,9 @@
+ #define USB_VENDOR_ID_SUN		0x0430
+ #define USB_DEVICE_ID_RARITAN_KVM_DONGLE	0xcdab
+ 
++#define USB_VENDOR_ID_SUNPLUS		0x04fc
++#define USB_DEVICE_ID_SUNPLUS_WDESKTOP	0x05d8
++
+ #define USB_VENDOR_ID_TOPMAX		0x0663
+ #define USB_DEVICE_ID_TOPMAX_COBRAPAD	0x0103
+ 
+@@ -405,6 +405,9 @@
+ #define USB_VENDOR_ID_YEALINK		0x6993
+ #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K	0xb001
+ 
++#define USB_VENDOR_ID_KYE		0x0458
++#define USB_DEVICE_ID_KYE_GPEN_560	0x5003
++
+ /*
+  * Alphabetically sorted blacklist by quirk type.
+  */
+@@ -435,9 +438,13 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
+ 	
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
++	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI, HID_QUIRK_DUPLICATE_USAGES },
++
++	{ USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL },
+ 
+ 	{ USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
++	{ USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
+ 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
+ 
+ 	{ USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT },
+@@ -518,16 +525,6 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_600, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_601, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_602, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_603, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_604, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_605, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_606, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_607, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_608, HID_QUIRK_IGNORE },
+-	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_609, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE },
+@@ -601,6 +598,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, 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_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
+@@ -608,7 +606,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
+-	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
++	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
+ 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+ 
+ 	{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+@@ -703,6 +701,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_63, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_64, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY, HID_QUIRK_IGNORE },
++	{ USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560, HID_QUIRK_IGNORE },
+ 
+ 	{ 0, 0 }
+ };
+@@ -719,6 +718,7 @@ static const struct hid_rdesc_blacklist {
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
++	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_DESKTOP_RECV_1028, HID_QUIRK_RDESC_MICROSOFT_RECV_1028 },
+ 
+ 	{ USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
+ 
+@@ -728,6 +728,8 @@ static const struct hid_rdesc_blacklist {
+ 
+ 	{ USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE },
+ 
++	{ USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP, HID_QUIRK_RDESC_SUNPLUS_WDESKTOP },
++
+ 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+ 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+ 
+@@ -793,8 +795,8 @@ static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor,
+  *
+  * Returns: 0 OK, -error on failure.
+  */
+-int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
+-		const u32 quirks)
++static int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
++				const u32 quirks)
+ {
+ 	struct quirks_list_struct *q_new, *q;
+ 	int list_edited = 0;
+@@ -1002,6 +1004,17 @@ static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
+ 	}
+ }
+ 
++static void usbhid_fixup_sunplus_wdesktop(unsigned char *rdesc, int rsize)
++{
++	if (rsize >= 107 && rdesc[104] == 0x26
++			 && rdesc[105] == 0x80
++			 && rdesc[106] == 0x03) {
++		printk(KERN_INFO "Fixing up Sunplus Wireless Desktop report descriptor\n");
++		rdesc[105] = rdesc[110] = 0x03;
++		rdesc[106] = rdesc[111] = 0x21;
++	}
++}
++
+ /*
+  * Samsung IrDA remote controller (reports as Cypress USB Mouse).
+  *
+@@ -1089,6 +1102,28 @@ static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rs
+ 	}
+ }
+ 
++/*
++ * Microsoft Wireless Desktop Receiver (Model 1028) has several
++ * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
++ */
++static void usbhid_fixup_microsoft_descriptor(unsigned char *rdesc, int rsize)
++{
++	if (rsize == 571 && rdesc[284] == 0x19
++	                 && rdesc[286] == 0x2a
++	                 && rdesc[304] == 0x19
++	                 && rdesc[306] == 0x29
++	                 && rdesc[352] == 0x1a
++	                 && rdesc[355] == 0x2a
++			 && rdesc[557] == 0x19
++			 && rdesc[559] == 0x29) {
++		printk(KERN_INFO "Fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
++		rdesc[284] = rdesc[304] = rdesc[558] = 0x35;
++		rdesc[352] = 0x36;
++		rdesc[286] = rdesc[355] = 0x46;
++		rdesc[306] = rdesc[559] = 0x45;
++	}
++}
++
+ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
+ {
+ 	if ((quirks & HID_QUIRK_RDESC_CYMOTION))
+@@ -1112,6 +1147,11 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned
+ 	if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE)
+ 		usbhid_fixup_samsung_irda_descriptor(rdesc, rsize);
+ 
++	if (quirks & HID_QUIRK_RDESC_MICROSOFT_RECV_1028)
++		usbhid_fixup_microsoft_descriptor(rdesc, rsize);
++
++	if (quirks & HID_QUIRK_RDESC_SUNPLUS_WDESKTOP)
++		usbhid_fixup_sunplus_wdesktop(rdesc, rsize);
+ }
+ 
+ /**
+@@ -1150,5 +1190,4 @@ void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
+ 		else if (paramVendor == idVendor && paramProduct == idProduct)
+ 			__usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
+ 	}
+-
+ }
+diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
+index 5fc4019..95cc192 100644
+--- a/drivers/hid/usbhid/hiddev.c
++++ b/drivers/hid/usbhid/hiddev.c
+@@ -393,6 +393,153 @@ static unsigned int hiddev_poll(struct file *file, poll_table *wait)
+ /*
+  * "ioctl" file op
+  */
++static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, void __user *user_arg)
++{
++	struct hid_device *hid = hiddev->hid;
++	struct hiddev_report_info rinfo;
++	struct hiddev_usage_ref_multi *uref_multi = NULL;
++	struct hiddev_usage_ref *uref;
++	struct hid_report *report;
++	struct hid_field *field;
++	int i;
++
++	uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
++	if (!uref_multi)
++		return -ENOMEM;
++	uref = &uref_multi->uref;
++	if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
++		if (copy_from_user(uref_multi, user_arg,
++				   sizeof(*uref_multi)))
++			goto fault;
++	} else {
++		if (copy_from_user(uref, user_arg, sizeof(*uref)))
++			goto fault;
++	}
++
++	switch (cmd) {
++	case HIDIOCGUCODE:
++		rinfo.report_type = uref->report_type;
++		rinfo.report_id = uref->report_id;
++		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
++			goto inval;
++
++		if (uref->field_index >= report->maxfield)
++			goto inval;
++
++		field = report->field[uref->field_index];
++		if (uref->usage_index >= field->maxusage)
++			goto inval;
++
++		uref->usage_code = field->usage[uref->usage_index].hid;
++
++		if (copy_to_user(user_arg, uref, sizeof(*uref)))
++			goto fault;
++
++		kfree(uref_multi);
++		return 0;
++
++	default:
++		if (cmd != HIDIOCGUSAGE &&
++		    cmd != HIDIOCGUSAGES &&
++		    uref->report_type == HID_REPORT_TYPE_INPUT)
++			goto inval;
++
++		if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
++			field = hiddev_lookup_usage(hid, uref);
++			if (field == NULL)
++				goto inval;
++		} else {
++			rinfo.report_type = uref->report_type;
++			rinfo.report_id = uref->report_id;
++			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
++				goto inval;
++
++			if (uref->field_index >= report->maxfield)
++				goto inval;
++
++			field = report->field[uref->field_index];
++
++			if (cmd == HIDIOCGCOLLECTIONINDEX) {
++				if (uref->usage_index >= field->maxusage)
++					goto inval;
++			} else if (uref->usage_index >= field->report_count)
++				goto inval;
++
++			else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
++				 (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
++				  uref->usage_index + uref_multi->num_values > field->report_count))
++				goto inval;
++			}
++
++		switch (cmd) {
++		case HIDIOCGUSAGE:
++			uref->value = field->value[uref->usage_index];
++			if (copy_to_user(user_arg, uref, sizeof(*uref)))
++				goto fault;
++			goto goodreturn;
++
++		case HIDIOCSUSAGE:
++			field->value[uref->usage_index] = uref->value;
++			goto goodreturn;
++
++		case HIDIOCGCOLLECTIONINDEX:
++			kfree(uref_multi);
++			return field->usage[uref->usage_index].collection_index;
++		case HIDIOCGUSAGES:
++			for (i = 0; i < uref_multi->num_values; i++)
++				uref_multi->values[i] =
++				    field->value[uref->usage_index + i];
++			if (copy_to_user(user_arg, uref_multi,
++					 sizeof(*uref_multi)))
++				goto fault;
++			goto goodreturn;
++		case HIDIOCSUSAGES:
++			for (i = 0; i < uref_multi->num_values; i++)
++				field->value[uref->usage_index + i] =
++				    uref_multi->values[i];
++			goto goodreturn;
++		}
++
++goodreturn:
++		kfree(uref_multi);
++		return 0;
++fault:
++		kfree(uref_multi);
++		return -EFAULT;
++inval:
++		kfree(uref_multi);
++		return -EINVAL;
++	}
++}
++
++static noinline int hiddev_ioctl_string(struct hiddev *hiddev, unsigned int cmd, void __user *user_arg)
++{
++	struct hid_device *hid = hiddev->hid;
++	struct usb_device *dev = hid_to_usb_dev(hid);
++	int idx, len;
++	char *buf;
++
++	if (get_user(idx, (int __user *)user_arg))
++		return -EFAULT;
++
++	if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
++		return -ENOMEM;
++
++	if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
++		kfree(buf);
++		return -EINVAL;
++	}
++
++	if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
++		kfree(buf);
++		return -EFAULT;
++	}
++
++	kfree(buf);
++
++	return len;
++}
++
+ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ {
+ 	struct hiddev_list *list = file->private_data;
+@@ -402,8 +549,6 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
+ 	struct hiddev_collection_info cinfo;
+ 	struct hiddev_report_info rinfo;
+ 	struct hiddev_field_info finfo;
+-	struct hiddev_usage_ref_multi *uref_multi = NULL;
+-	struct hiddev_usage_ref *uref;
+ 	struct hiddev_devinfo dinfo;
+ 	struct hid_report *report;
+ 	struct hid_field *field;
+@@ -470,30 +615,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
+ 		}
+ 
+ 	case HIDIOCGSTRING:
+-		{
+-			int idx, len;
+-			char *buf;
+-
+-			if (get_user(idx, (int __user *)arg))
+-				return -EFAULT;
+-
+-			if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
+-				return -ENOMEM;
+-
+-			if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
+-				kfree(buf);
+-				return -EINVAL;
+-			}
+-
+-			if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
+-				kfree(buf);
+-				return -EFAULT;
+-			}
+-
+-			kfree(buf);
+-
+-			return len;
+-		}
++		return hiddev_ioctl_string(hiddev, cmd, user_arg);
+ 
+ 	case HIDIOCINITREPORT:
+ 		usbhid_init_reports(hid);
+@@ -578,121 +700,13 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
+ 		return 0;
+ 
+ 	case HIDIOCGUCODE:
+-		uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
+-		if (!uref_multi)
+-			return -ENOMEM;
+-		uref = &uref_multi->uref;
+-		if (copy_from_user(uref, user_arg, sizeof(*uref)))
+-			goto fault;
+-
+-		rinfo.report_type = uref->report_type;
+-		rinfo.report_id = uref->report_id;
+-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+-			goto inval;
+-
+-		if (uref->field_index >= report->maxfield)
+-			goto inval;
+-
+-		field = report->field[uref->field_index];
+-		if (uref->usage_index >= field->maxusage)
+-			goto inval;
+-
+-		uref->usage_code = field->usage[uref->usage_index].hid;
+-
+-		if (copy_to_user(user_arg, uref, sizeof(*uref)))
+-			goto fault;
+-
+-		kfree(uref_multi);
+-		return 0;
+-
++		/* fall through */
+ 	case HIDIOCGUSAGE:
+ 	case HIDIOCSUSAGE:
+ 	case HIDIOCGUSAGES:
+ 	case HIDIOCSUSAGES:
+ 	case HIDIOCGCOLLECTIONINDEX:
+-		uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
+-		if (!uref_multi)
+-			return -ENOMEM;
+-		uref = &uref_multi->uref;
+-		if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
+-			if (copy_from_user(uref_multi, user_arg,
+-					   sizeof(*uref_multi)))
+-				goto fault;
+-		} else {
+-			if (copy_from_user(uref, user_arg, sizeof(*uref)))
+-				goto fault;
+-		}
+-
+-		if (cmd != HIDIOCGUSAGE &&
+-		    cmd != HIDIOCGUSAGES &&
+-		    uref->report_type == HID_REPORT_TYPE_INPUT)
+-			goto inval;
+-
+-		if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
+-			field = hiddev_lookup_usage(hid, uref);
+-			if (field == NULL)
+-				goto inval;
+-		} else {
+-			rinfo.report_type = uref->report_type;
+-			rinfo.report_id = uref->report_id;
+-			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+-				goto inval;
+-
+-			if (uref->field_index >= report->maxfield)
+-				goto inval;
+-
+-			field = report->field[uref->field_index];
+-
+-			if (cmd == HIDIOCGCOLLECTIONINDEX) {
+-				if (uref->usage_index >= field->maxusage)
+-					goto inval;
+-			} else if (uref->usage_index >= field->report_count)
+-				goto inval;
+-
+-			else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+-				 (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+-				  uref->usage_index + uref_multi->num_values > field->report_count))
+-				goto inval;
+-			}
+-
+-		switch (cmd) {
+-			case HIDIOCGUSAGE:
+-				uref->value = field->value[uref->usage_index];
+-				if (copy_to_user(user_arg, uref, sizeof(*uref)))
+-					goto fault;
+-				goto goodreturn;
+-
+-			case HIDIOCSUSAGE:
+-				field->value[uref->usage_index] = uref->value;
+-				goto goodreturn;
+-
+-			case HIDIOCGCOLLECTIONINDEX:
+-				kfree(uref_multi);
+-				return field->usage[uref->usage_index].collection_index;
+-			case HIDIOCGUSAGES:
+-				for (i = 0; i < uref_multi->num_values; i++)
+-					uref_multi->values[i] =
+-					    field->value[uref->usage_index + i];
+-				if (copy_to_user(user_arg, uref_multi,
+-						 sizeof(*uref_multi)))
+-					goto fault;
+-				goto goodreturn;
+-			case HIDIOCSUSAGES:
+-				for (i = 0; i < uref_multi->num_values; i++)
+-					field->value[uref->usage_index + i] =
+-					    uref_multi->values[i];
+-				goto goodreturn;
+-		}
+-
+-goodreturn:
+-		kfree(uref_multi);
+-		return 0;
+-fault:
+-		kfree(uref_multi);
+-		return -EFAULT;
+-inval:
+-		kfree(uref_multi);
+-		return -EINVAL;
++		return hiddev_ioctl_usage(hiddev, cmd, user_arg);
+ 
+ 	case HIDIOCGCOLLECTIONINFO:
+ 		if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
+diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
+index 0023f96..62d2d7c 100644
+--- a/drivers/hid/usbhid/usbhid.h
++++ b/drivers/hid/usbhid/usbhid.h
+@@ -28,6 +28,7 @@
+ #include <linux/slab.h>
+ #include <linux/list.h>
+ #include <linux/timer.h>
++#include <linux/wait.h>
+ #include <linux/workqueue.h>
+ #include <linux/input.h>
+ 
+@@ -77,7 +78,7 @@ struct usbhid_device {
+ 	unsigned long stop_retry;                                       /* Time to give up, in jiffies */
+ 	unsigned int retry_delay;                                       /* Delay length in ms */
+ 	struct work_struct reset_work;                                  /* Task context for resets */
+-
++	wait_queue_head_t wait;						/* For sleeping */
+ };
+ 
+ #define	hid_to_usb_dev(hid_dev) \
+diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
+index 014dfa5..7137a17 100644
+--- a/drivers/i2c/algos/Kconfig
++++ b/drivers/i2c/algos/Kconfig
+@@ -1,45 +1,16 @@
+ #
+-# Character device configuration
++# I2C algorithm drivers configuration
+ #
+ 
+-menu "I2C Algorithms"
+-
+ config I2C_ALGOBIT
+-	tristate "I2C bit-banging interfaces"
+-	help
+-	  This allows you to use a range of I2C adapters called bit-banging
+-	  adapters.  Say Y if you own an I2C adapter belonging to this class
+-	  and then say Y to the specific driver for you adapter below.
+-
+-	  This support is also available as a module.  If so, the module 
+-	  will be called i2c-algo-bit.
++	tristate
+ 
+ config I2C_ALGOPCF
+-	tristate "I2C PCF 8584 interfaces"
+-	help
+-	  This allows you to use a range of I2C adapters called PCF adapters.
+-	  Say Y if you own an I2C adapter belonging to this class and then say
+-	  Y to the specific driver for you adapter below.
+-
+-	  This support is also available as a module.  If so, the module 
+-	  will be called i2c-algo-pcf.
++	tristate
+ 
+ config I2C_ALGOPCA
+-	tristate "I2C PCA 9564 interfaces"
+-	help
+-	  This allows you to use a range of I2C adapters called PCA adapters.
+-	  Say Y if you own an I2C adapter belonging to this class and then say
+-	  Y to the specific driver for you adapter below.
+-
+-	  This support is also available as a module.  If so, the module 
+-	  will be called i2c-algo-pca.
++	tristate
+ 
+ config I2C_ALGO_SGI
+-	tristate "I2C SGI interfaces"
++	tristate
+ 	depends on SGI_IP22 || SGI_IP32 || X86_VISWS
+-	help
+-	  Supports the SGI interfaces like the ones found on SGI Indy VINO
+-	  or SGI O2 MACE.
+-
+-endmenu
+-
+diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
+index 2a16211..e954a20 100644
+--- a/drivers/i2c/algos/i2c-algo-pca.c
++++ b/drivers/i2c/algos/i2c-algo-pca.c
+@@ -1,6 +1,7 @@
+ /*
+- *  i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters                
++ *  i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
+  *    Copyright (C) 2004 Arcom Control Systems
++ *    Copyright (C) 2008 Pengutronix
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+@@ -21,14 +22,10 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/delay.h>
+-#include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-pca.h>
+-#include "i2c-algo-pca.h"
+-
+-#define DRIVER "i2c-algo-pca"
+ 
+ #define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0)
+ #define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
+@@ -36,15 +33,15 @@
+ 
+ static int i2c_debug;
+ 
+-#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
+-#define pca_inw(adap, reg) adap->read_byte(adap, reg)
++#define pca_outw(adap, reg, val) adap->write_byte(adap->data, reg, val)
++#define pca_inw(adap, reg) adap->read_byte(adap->data, reg)
+ 
+ #define pca_status(adap) pca_inw(adap, I2C_PCA_STA)
+-#define pca_clock(adap) adap->get_clock(adap)
+-#define pca_own(adap) adap->get_own(adap)
++#define pca_clock(adap) adap->i2c_clock
+ #define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
+ #define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
+-#define pca_wait(adap) adap->wait_for_interrupt(adap)
++#define pca_wait(adap) adap->wait_for_completion(adap->data)
++#define pca_reset(adap) adap->reset_chip(adap->data)
+ 
+ /*
+  * Generate a start condition on the i2c bus.
+@@ -99,7 +96,7 @@ static void pca_stop(struct i2c_algo_pca_data *adap)
+  *
+  * returns after the address has been sent
+  */
+-static void pca_address(struct i2c_algo_pca_data *adap, 
++static void pca_address(struct i2c_algo_pca_data *adap,
+ 			struct i2c_msg *msg)
+ {
+ 	int sta = pca_get_con(adap);
+@@ -108,9 +105,9 @@ static void pca_address(struct i2c_algo_pca_data *adap,
+ 	addr = ( (0x7f & msg->addr) << 1 );
+ 	if (msg->flags & I2C_M_RD )
+ 		addr |= 1;
+-	DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n", 
++	DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
+ 	     msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
+-	
++
+ 	pca_outw(adap, I2C_PCA_DAT, addr);
+ 
+ 	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
+@@ -124,7 +121,7 @@ static void pca_address(struct i2c_algo_pca_data *adap,
+  *
+  * Returns after the byte has been transmitted
+  */
+-static void pca_tx_byte(struct i2c_algo_pca_data *adap, 
++static void pca_tx_byte(struct i2c_algo_pca_data *adap,
+ 			__u8 b)
+ {
+ 	int sta = pca_get_con(adap);
+@@ -142,19 +139,19 @@ static void pca_tx_byte(struct i2c_algo_pca_data *adap,
+  *
+  * returns immediately.
+  */
+-static void pca_rx_byte(struct i2c_algo_pca_data *adap, 
++static void pca_rx_byte(struct i2c_algo_pca_data *adap,
+ 			__u8 *b, int ack)
+ {
+ 	*b = pca_inw(adap, I2C_PCA_DAT);
+ 	DEB2("=== READ %#04x %s\n", *b, ack ? "ACK" : "NACK");
+ }
+ 
+-/* 
++/*
+  * Setup ACK or NACK for next received byte and wait for it to arrive.
+  *
+  * Returns after next byte has arrived.
+  */
+-static void pca_rx_ack(struct i2c_algo_pca_data *adap, 
++static void pca_rx_ack(struct i2c_algo_pca_data *adap,
+ 		       int ack)
+ {
+ 	int sta = pca_get_con(adap);
+@@ -168,15 +165,6 @@ static void pca_rx_ack(struct i2c_algo_pca_data *adap,
+ 	pca_wait(adap);
+ }
+ 
+-/* 
+- * Reset the i2c bus / SIO 
+- */
+-static void pca_reset(struct i2c_algo_pca_data *adap)
+-{
+-	/* apparently only an external reset will do it. not a lot can be done */
+-	printk(KERN_ERR DRIVER ": Haven't figured out how to do a reset yet\n");
+-}
+-
+ static int pca_xfer(struct i2c_adapter *i2c_adap,
+                     struct i2c_msg *msgs,
+                     int num)
+@@ -187,7 +175,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ 	int numbytes = 0;
+ 	int state;
+ 	int ret;
+-	int timeout = 100;
++	int timeout = i2c_adap->timeout;
+ 
+ 	while ((state = pca_status(adap)) != 0xf8 && timeout--) {
+ 		msleep(10);
+@@ -203,14 +191,14 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ 		for (curmsg = 0; curmsg < num; curmsg++) {
+ 			int addr, i;
+ 			msg = &msgs[curmsg];
+-			
++
+ 			addr = (0x7f & msg->addr) ;
+-		
++
+ 			if (msg->flags & I2C_M_RD )
+-				printk(KERN_INFO "    [%02d] RD %d bytes from %#02x [%#02x, ...]\n", 
++				printk(KERN_INFO "    [%02d] RD %d bytes from %#02x [%#02x, ...]\n",
+ 				       curmsg, msg->len, addr, (addr<<1) | 1);
+ 			else {
+-				printk(KERN_INFO "    [%02d] WR %d bytes to %#02x [%#02x%s", 
++				printk(KERN_INFO "    [%02d] WR %d bytes to %#02x [%#02x%s",
+ 				       curmsg, msg->len, addr, addr<<1,
+ 				       msg->len == 0 ? "" : ", ");
+ 				for(i=0; i < msg->len; i++)
+@@ -237,7 +225,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ 		case 0x10: /* A repeated start condition has been transmitted */
+ 			pca_address(adap, msg);
+ 			break;
+-			
++
+ 		case 0x18: /* SLA+W has been transmitted; ACK has been received */
+ 		case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */
+ 			if (numbytes < msg->len) {
+@@ -287,7 +275,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ 		case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
+ 			DEB2("Arbitration lost\n");
+ 			goto out;
+-			
++
+ 		case 0x58: /* Data byte has been received; NOT ACK has been returned */
+ 			if ( numbytes == msg->len - 1 ) {
+ 				pca_rx_byte(adap, &msg->buf[numbytes], 0);
+@@ -317,16 +305,16 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ 			pca_reset(adap);
+ 			goto out;
+ 		default:
+-			printk(KERN_ERR DRIVER ": unhandled SIO state 0x%02x\n", state);
++			dev_err(&i2c_adap->dev, "unhandled SIO state 0x%02x\n", state);
+ 			break;
+ 		}
+-		
++
+ 	}
+ 
+ 	ret = curmsg;
+  out:
+ 	DEB1(KERN_CRIT "}}} transfered %d/%d messages. "
+-	     "status is %#04x. control is %#04x\n", 
++	     "status is %#04x. control is %#04x\n",
+ 	     curmsg, num, pca_status(adap),
+ 	     pca_get_con(adap));
+ 	return ret;
+@@ -337,53 +325,65 @@ static u32 pca_func(struct i2c_adapter *adap)
+         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ }
+ 
+-static int pca_init(struct i2c_algo_pca_data *adap)
++static const struct i2c_algorithm pca_algo = {
++	.master_xfer	= pca_xfer,
++	.functionality	= pca_func,
++};
++
++static int pca_init(struct i2c_adapter *adap)
+ {
+ 	static int freqs[] = {330,288,217,146,88,59,44,36};
+-	int own, clock;
++	int clock;
++	struct i2c_algo_pca_data *pca_data = adap->algo_data;
++
++	if (pca_data->i2c_clock > 7) {
++		printk(KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n",
++			adap->name);
++		pca_data->i2c_clock = I2C_PCA_CON_59kHz;
++	}
++
++	adap->algo = &pca_algo;
+ 
+-	own = pca_own(adap);
+-	clock = pca_clock(adap);
+-	DEB1(KERN_INFO DRIVER ": own address is %#04x\n", own);
+-	DEB1(KERN_INFO DRIVER ": clock freqeuncy is %dkHz\n", freqs[clock]);
++	pca_reset(pca_data);
+ 
+-	pca_outw(adap, I2C_PCA_ADR, own << 1);
++	clock = pca_clock(pca_data);
++	DEB1(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, freqs[clock]);
+ 
+-	pca_set_con(adap, I2C_PCA_CON_ENSIO | clock);
+-	udelay(500); /* 500 µs for oscilator to stabilise */
++	pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
++	udelay(500); /* 500 us for oscilator to stabilise */
+ 
+ 	return 0;
+ }
+ 
+-static const struct i2c_algorithm pca_algo = {
+-	.master_xfer	= pca_xfer,
+-	.functionality	= pca_func,
+-};
+-
+-/* 
+- * registering functions to load algorithms at runtime 
++/*
++ * registering functions to load algorithms at runtime
+  */
+ int i2c_pca_add_bus(struct i2c_adapter *adap)
+ {
+-	struct i2c_algo_pca_data *pca_adap = adap->algo_data;
+ 	int rval;
+ 
+-	/* register new adapter to i2c module... */
+-	adap->algo = &pca_algo;
++	rval = pca_init(adap);
++	if (rval)
++		return rval;
+ 
+-	adap->timeout = 100;		/* default values, should	*/
+-	adap->retries = 3;		/* be replaced by defines	*/
++	return i2c_add_adapter(adap);
++}
++EXPORT_SYMBOL(i2c_pca_add_bus);
+ 
+-	if ((rval = pca_init(pca_adap)))
+-		return rval;
++int i2c_pca_add_numbered_bus(struct i2c_adapter *adap)
++{
++	int rval;
+ 
+-	rval = i2c_add_adapter(adap);
++	rval = pca_init(adap);
++	if (rval)
++		return rval;
+ 
+-	return rval;
++	return i2c_add_numbered_adapter(adap);
+ }
+-EXPORT_SYMBOL(i2c_pca_add_bus);
++EXPORT_SYMBOL(i2c_pca_add_numbered_bus);
+ 
+-MODULE_AUTHOR("Ian Campbell <icampbell at arcom.com>");
++MODULE_AUTHOR("Ian Campbell <icampbell at arcom.com>, "
++	"Wolfram Sang <w.sang at pengutronix.de>");
+ MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
+ MODULE_LICENSE("GPL");
+ 
+diff --git a/drivers/i2c/algos/i2c-algo-pca.h b/drivers/i2c/algos/i2c-algo-pca.h
+deleted file mode 100644
+index 2fee07e..0000000
+--- a/drivers/i2c/algos/i2c-algo-pca.h
++++ /dev/null
+@@ -1,26 +0,0 @@
+-#ifndef I2C_PCA9564_H
+-#define I2C_PCA9564_H 1
+-
+-#define I2C_PCA_STA		0x00 /* STATUS  Read Only  */
+-#define I2C_PCA_TO		0x00 /* TIMEOUT Write Only */
+-#define I2C_PCA_DAT		0x01 /* DATA    Read/Write */
+-#define I2C_PCA_ADR		0x02 /* OWN ADR Read/Write */
+-#define I2C_PCA_CON		0x03 /* CONTROL Read/Write */
+-
+-#define I2C_PCA_CON_AA		0x80 /* Assert Acknowledge */
+-#define I2C_PCA_CON_ENSIO	0x40 /* Enable */
+-#define I2C_PCA_CON_STA		0x20 /* Start */
+-#define I2C_PCA_CON_STO		0x10 /* Stop */
+-#define I2C_PCA_CON_SI		0x08 /* Serial Interrupt */
+-#define I2C_PCA_CON_CR		0x07 /* Clock Rate (MASK) */
+-
+-#define I2C_PCA_CON_330kHz	0x00
+-#define I2C_PCA_CON_288kHz	0x01
+-#define I2C_PCA_CON_217kHz	0x02
+-#define I2C_PCA_CON_146kHz	0x03
+-#define I2C_PCA_CON_88kHz	0x04
+-#define I2C_PCA_CON_59kHz	0x05
+-#define I2C_PCA_CON_44kHz	0x06
+-#define I2C_PCA_CON_36kHz	0x07
+-
+-#endif /* I2C_PCA9564_H */
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 5fa9c3c..48438cc 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -100,9 +100,12 @@ config I2C_AU1550
+ 
+ config I2C_BLACKFIN_TWI
+ 	tristate "Blackfin TWI I2C support"
+-	depends on BF534 || BF536 || BF537
++	depends on BLACKFIN
+ 	help
+-	  This is the TWI I2C device driver for Blackfin 534/536/537/54x.
++	  This is the TWI I2C device driver for Blackfin BF522, BF525,
++	  BF527, BF534, BF536, BF537 and BF54x. For other Blackfin processors,
++	  please don't use this driver.
++
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called i2c-bfin-twi.
+ 
+@@ -135,7 +138,7 @@ config I2C_ELEKTOR
+ 	  This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
+ 	  such an adapter.
+ 
+-	  This support is also available as a module.  If so, the module 
++	  This support is also available as a module.  If so, the module
+ 	  will be called i2c-elektor.
+ 
+ config I2C_GPIO
+@@ -190,7 +193,7 @@ config I2C_I810
+ 	select I2C_ALGOBIT
+ 	help
+ 	  If you say yes to this option, support will be included for the Intel
+-	  810/815 family of mainboard I2C interfaces.  Specifically, the 
++	  810/815 family of mainboard I2C interfaces.  Specifically, the
+ 	  following versions of the chipset are supported:
+ 	    i810AA
+ 	    i810AB
+@@ -246,10 +249,10 @@ config I2C_PIIX4
+ 
+ config I2C_IBM_IIC
+ 	tristate "IBM PPC 4xx on-chip I2C interface"
+-	depends on IBM_OCP
++	depends on 4xx
+ 	help
+-	  Say Y here if you want to use IIC peripheral found on 
+-	  embedded IBM PPC 4xx based systems. 
++	  Say Y here if you want to use IIC peripheral found on
++	  embedded IBM PPC 4xx based systems.
+ 
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called i2c-ibm_iic.
+@@ -269,7 +272,7 @@ config I2C_IXP2000
+ 	depends on ARCH_IXP2000
+ 	select I2C_ALGOBIT
+ 	help
+-	  Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based 
++	  Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
+ 	  system and are using GPIO lines for an I2C bus.
+ 
+ 	  This support is also available as a module. If so, the module
+@@ -354,7 +357,7 @@ config I2C_PARPORT
+ 	  on the parport driver.  This is meant for embedded systems. Don't say
+ 	  Y here if you intend to say Y or M there.
+ 
+-	  This support is also available as a module.  If so, the module 
++	  This support is also available as a module.  If so, the module
+ 	  will be called i2c-parport.
+ 
+ config I2C_PARPORT_LIGHT
+@@ -372,12 +375,12 @@ config I2C_PARPORT_LIGHT
+ 	  the clean but heavy parport handling is not an option.  The
+ 	  drawback is a reduced portability and the impossibility to
+ 	  daisy-chain other parallel port devices.
+-	  
++
+ 	  Don't say Y here if you said Y or M to i2c-parport.  Saying M to
+ 	  both is possible but both modules should not be loaded at the same
+ 	  time.
+ 
+-	  This support is also available as a module.  If so, the module 
++	  This support is also available as a module.  If so, the module
+ 	  will be called i2c-parport-light.
+ 
+ config I2C_PASEMI
+@@ -401,7 +404,7 @@ config I2C_PROSAVAGE
+ 
+ 	  This driver is deprecated in favor of the savagefb driver.
+ 
+-	  This support is also available as a module.  If so, the module 
++	  This support is also available as a module.  If so, the module
+ 	  will be called i2c-prosavage.
+ 
+ config I2C_S3C2410
+@@ -417,7 +420,7 @@ config I2C_SAVAGE4
+ 	depends on PCI
+ 	select I2C_ALGOBIT
+ 	help
+-	  If you say yes to this option, support will be included for the 
++	  If you say yes to this option, support will be included for the
+ 	  S3 Savage 4 I2C interface.
+ 
+ 	  This driver is deprecated in favor of the savagefb driver.
+@@ -452,7 +455,7 @@ config SCx200_I2C
+ 
+ 	  If you don't know what to do here, say N.
+ 
+-	  This support is also available as a module.  If so, the module 
++	  This support is also available as a module.  If so, the module
+ 	  will be called scx200_i2c.
+ 
+ 	  This driver is deprecated and will be dropped soon. Use i2c-gpio
+@@ -483,14 +486,14 @@ config SCx200_ACB
+ 
+ 	  If you don't know what to do here, say N.
+ 
+-	  This support is also available as a module.  If so, the module 
++	  This support is also available as a module.  If so, the module
+ 	  will be called scx200_acb.
+ 
+ config I2C_SIS5595
+ 	tristate "SiS 5595"
+ 	depends on PCI
+ 	help
+-	  If you say yes to this option, support will be included for the 
++	  If you say yes to this option, support will be included for the
+ 	  SiS5595 SMBus (a subset of I2C) interface.
+ 
+ 	  This driver can also be built as a module.  If so, the module
+@@ -500,7 +503,7 @@ config I2C_SIS630
+ 	tristate "SiS 630/730"
+ 	depends on PCI
+ 	help
+-	  If you say yes to this option, support will be included for the 
++	  If you say yes to this option, support will be included for the
+ 	  SiS630 and SiS730 SMBus (a subset of I2C) interface.
+ 
+ 	  This driver can also be built as a module.  If so, the module
+@@ -632,9 +635,9 @@ config I2C_PCA_ISA
+ 	select I2C_ALGOPCA
+ 	default n
+ 	help
+-	  This driver supports ISA boards using the Philips PCA 9564
+-	  Parallel bus to I2C bus controller
+-	  
++	  This driver supports ISA boards using the Philips PCA9564
++	  parallel bus to I2C bus controller.
++
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called i2c-pca-isa.
+ 
+@@ -643,9 +646,20 @@ config I2C_PCA_ISA
+ 	  delays when I2C/SMBus chip drivers are loaded (e.g. at boot
+ 	  time).  If unsure, say N.
+ 
++config I2C_PCA_PLATFORM
++	tristate "PCA9564 as platform device"
++	select I2C_ALGOPCA
++	default n
++	help
++	  This driver supports a memory mapped Philips PCA9564
++	  parallel bus to I2C bus controller.
++
++	  This driver can also be built as a module.  If so, the module
++	  will be called i2c-pca-platform.
++
+ config I2C_MV64XXX
+ 	tristate "Marvell mv64xxx I2C Controller"
+-	depends on (MV64X60 || ARCH_ORION) && EXPERIMENTAL
++	depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
+ 	help
+ 	  If you say yes to this option, support will be included for the
+ 	  built-in I2C interface on the Marvell 64xxx line of host bridges.
+@@ -672,4 +686,23 @@ config I2C_PMCMSP
+ 	  This driver can also be built as module. If so, the module
+ 	  will be called i2c-pmcmsp.
+ 
++config I2C_SH7760
++	tristate "Renesas SH7760 I2C Controller"
++	depends on CPU_SUBTYPE_SH7760
++	help
++	  This driver supports the 2 I2C interfaces on the Renesas SH7760.
++
++	  This driver can also be built as a module.  If so, the module
++	  will be called i2c-sh7760.
++
++config I2C_SH_MOBILE
++	tristate "SuperH Mobile I2C Controller"
++	depends on SUPERH
++	help
++	  If you say yes to this option, support will be included for the
++	  built-in I2C interface on the Renesas SH-Mobile processor.
++
++	  This driver can also be built as a module.  If so, the module
++	  will be called i2c-sh_mobile.
++
+ endmenu
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index ea7068f..e8c882a 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
+ obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
+ obj-$(CONFIG_I2C_PASEMI)	+= i2c-pasemi.o
+ obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
++obj-$(CONFIG_I2C_PCA_PLATFORM)	+= i2c-pca-platform.o
+ obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
+ obj-$(CONFIG_I2C_PMCMSP)	+= i2c-pmcmsp.o
+ obj-$(CONFIG_I2C_PNX)		+= i2c-pnx.o
+@@ -37,6 +38,8 @@ obj-$(CONFIG_I2C_PROSAVAGE)	+= i2c-prosavage.o
+ obj-$(CONFIG_I2C_PXA)		+= i2c-pxa.o
+ obj-$(CONFIG_I2C_S3C2410)	+= i2c-s3c2410.o
+ obj-$(CONFIG_I2C_SAVAGE4)	+= i2c-savage4.o
++obj-$(CONFIG_I2C_SH7760)	+= i2c-sh7760.o
++obj-$(CONFIG_I2C_SH_MOBILE)	+= i2c-sh_mobile.o
+ obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o
+ obj-$(CONFIG_I2C_SIMTEC)	+= i2c-simtec.o
+ obj-$(CONFIG_I2C_SIS5595)	+= i2c-sis5595.o
+diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
+index c09b036..73d6194 100644
+--- a/drivers/i2c/busses/i2c-at91.c
++++ b/drivers/i2c/busses/i2c-at91.c
+@@ -298,7 +298,7 @@ static int at91_i2c_resume(struct platform_device *pdev)
+ #endif
+ 
+ /* work with "modprobe at91_i2c" from hotplugging or coldplugging */
+-MODULE_ALIAS("at91_i2c");
++MODULE_ALIAS("platform:at91_i2c");
+ 
+ static struct platform_driver at91_i2c_driver = {
+ 	.probe		= at91_i2c_probe,
+diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
+index 1953b26..491718f 100644
+--- a/drivers/i2c/busses/i2c-au1550.c
++++ b/drivers/i2c/busses/i2c-au1550.c
+@@ -472,6 +472,7 @@ i2c_au1550_exit(void)
+ MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
+ MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:au1xpsc_smbus");
+ 
+ module_init (i2c_au1550_init);
+ module_exit (i2c_au1550_exit);
+diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
+index 7dbdaeb..48d084b 100644
+--- a/drivers/i2c/busses/i2c-bfin-twi.c
++++ b/drivers/i2c/busses/i2c-bfin-twi.c
+@@ -1,25 +1,11 @@
+ /*
+- * drivers/i2c/busses/i2c-bfin-twi.c
++ * Blackfin On-Chip Two Wire Interface Driver
+  *
+- * Description: Driver for Blackfin Two Wire Interface
++ * Copyright 2005-2007 Analog Devices Inc.
+  *
+- * Author:      sonicz  <sonic.zhang at analog.com>
++ * Enter bugs at http://blackfin.uclinux.org/
+  *
+- * Copyright (c) 2005-2007 Analog Devices, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ * Licensed under the GPL-2 or later.
+  */
+ 
+ #include <linux/module.h>
+@@ -34,14 +20,16 @@
+ #include <linux/platform_device.h>
+ 
+ #include <asm/blackfin.h>
++#include <asm/portmux.h>
+ #include <asm/irq.h>
+ 
+ #define POLL_TIMEOUT       (2 * HZ)
+ 
+ /* SMBus mode*/
+-#define TWI_I2C_MODE_STANDARD		0x01
+-#define TWI_I2C_MODE_STANDARDSUB	0x02
+-#define TWI_I2C_MODE_COMBINED		0x04
++#define TWI_I2C_MODE_STANDARD		1
++#define TWI_I2C_MODE_STANDARDSUB	2
++#define TWI_I2C_MODE_COMBINED		3
++#define TWI_I2C_MODE_REPEAT		4
+ 
+ struct bfin_twi_iface {
+ 	int			irq;
+@@ -58,39 +46,74 @@ struct bfin_twi_iface {
+ 	struct timer_list	timeout_timer;
+ 	struct i2c_adapter	adap;
+ 	struct completion	complete;
++	struct i2c_msg 		*pmsg;
++	int			msg_num;
++	int			cur_msg;
++	void __iomem		*regs_base;
+ };
+ 
+-static struct bfin_twi_iface twi_iface;
++
++#define DEFINE_TWI_REG(reg, off) \
++static inline u16 read_##reg(struct bfin_twi_iface *iface) \
++	{ return bfin_read16(iface->regs_base + (off)); } \
++static inline void write_##reg(struct bfin_twi_iface *iface, u16 v) \
++	{ bfin_write16(iface->regs_base + (off), v); }
++
++DEFINE_TWI_REG(CLKDIV, 0x00)
++DEFINE_TWI_REG(CONTROL, 0x04)
++DEFINE_TWI_REG(SLAVE_CTL, 0x08)
++DEFINE_TWI_REG(SLAVE_STAT, 0x0C)
++DEFINE_TWI_REG(SLAVE_ADDR, 0x10)
++DEFINE_TWI_REG(MASTER_CTL, 0x14)
++DEFINE_TWI_REG(MASTER_STAT, 0x18)
++DEFINE_TWI_REG(MASTER_ADDR, 0x1C)
++DEFINE_TWI_REG(INT_STAT, 0x20)
++DEFINE_TWI_REG(INT_MASK, 0x24)
++DEFINE_TWI_REG(FIFO_CTL, 0x28)
++DEFINE_TWI_REG(FIFO_STAT, 0x2C)
++DEFINE_TWI_REG(XMT_DATA8, 0x80)
++DEFINE_TWI_REG(XMT_DATA16, 0x84)
++DEFINE_TWI_REG(RCV_DATA8, 0x88)
++DEFINE_TWI_REG(RCV_DATA16, 0x8C)
++
++static const u16 pin_req[2][3] = {
++	{P_TWI0_SCL, P_TWI0_SDA, 0},
++	{P_TWI1_SCL, P_TWI1_SDA, 0},
++};
+ 
+ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+ {
+-	unsigned short twi_int_status = bfin_read_TWI_INT_STAT();
+-	unsigned short mast_stat = bfin_read_TWI_MASTER_STAT();
++	unsigned short twi_int_status = read_INT_STAT(iface);
++	unsigned short mast_stat = read_MASTER_STAT(iface);
+ 
+ 	if (twi_int_status & XMTSERV) {
+ 		/* Transmit next data */
+ 		if (iface->writeNum > 0) {
+-			bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
++			write_XMT_DATA8(iface, *(iface->transPtr++));
+ 			iface->writeNum--;
+ 		}
+ 		/* start receive immediately after complete sending in
+ 		 * combine mode.
+ 		 */
+-		else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+-			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+-				| MDIR | RSTART);
+-		} else if (iface->manual_stop)
+-			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+-				| STOP);
++		else if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
++			write_MASTER_CTL(iface,
++				read_MASTER_CTL(iface) | MDIR | RSTART);
++		else if (iface->manual_stop)
++			write_MASTER_CTL(iface,
++				read_MASTER_CTL(iface) | STOP);
++		else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
++				iface->cur_msg+1 < iface->msg_num)
++			write_MASTER_CTL(iface,
++				read_MASTER_CTL(iface) | RSTART);
+ 		SSYNC();
+ 		/* Clear status */
+-		bfin_write_TWI_INT_STAT(XMTSERV);
++		write_INT_STAT(iface, XMTSERV);
+ 		SSYNC();
+ 	}
+ 	if (twi_int_status & RCVSERV) {
+ 		if (iface->readNum > 0) {
+ 			/* Receive next data */
+-			*(iface->transPtr) = bfin_read_TWI_RCV_DATA8();
++			*(iface->transPtr) = read_RCV_DATA8(iface);
+ 			if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+ 				/* Change combine mode into sub mode after
+ 				 * read first data.
+@@ -105,28 +128,33 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+ 			iface->transPtr++;
+ 			iface->readNum--;
+ 		} else if (iface->manual_stop) {
+-			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+-				| STOP);
++			write_MASTER_CTL(iface,
++				read_MASTER_CTL(iface) | STOP);
++			SSYNC();
++		} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
++				iface->cur_msg+1 < iface->msg_num) {
++			write_MASTER_CTL(iface,
++				read_MASTER_CTL(iface) | RSTART);
+ 			SSYNC();
+ 		}
+ 		/* Clear interrupt source */
+-		bfin_write_TWI_INT_STAT(RCVSERV);
++		write_INT_STAT(iface, RCVSERV);
+ 		SSYNC();
+ 	}
+ 	if (twi_int_status & MERR) {
+-		bfin_write_TWI_INT_STAT(MERR);
+-		bfin_write_TWI_INT_MASK(0);
+-		bfin_write_TWI_MASTER_STAT(0x3e);
+-		bfin_write_TWI_MASTER_CTL(0);
++		write_INT_STAT(iface, MERR);
++		write_INT_MASK(iface, 0);
++		write_MASTER_STAT(iface, 0x3e);
++		write_MASTER_CTL(iface, 0);
+ 		SSYNC();
+-		iface->result = -1;
++		iface->result = -EIO;
+ 		/* if both err and complete int stats are set, return proper
+ 		 * results.
+ 		 */
+ 		if (twi_int_status & MCOMP) {
+-			bfin_write_TWI_INT_STAT(MCOMP);
+-			bfin_write_TWI_INT_MASK(0);
+-			bfin_write_TWI_MASTER_CTL(0);
++			write_INT_STAT(iface, MCOMP);
++			write_INT_MASK(iface, 0);
++			write_MASTER_CTL(iface, 0);
+ 			SSYNC();
+ 			/* If it is a quick transfer, only address bug no data,
+ 			 * not an err, return 1.
+@@ -143,7 +171,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+ 		return;
+ 	}
+ 	if (twi_int_status & MCOMP) {
+-		bfin_write_TWI_INT_STAT(MCOMP);
++		write_INT_STAT(iface, MCOMP);
+ 		SSYNC();
+ 		if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+ 			if (iface->readNum == 0) {
+@@ -152,28 +180,63 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+ 				 */
+ 				iface->readNum = 1;
+ 				iface->manual_stop = 1;
+-				bfin_write_TWI_MASTER_CTL(
+-					bfin_read_TWI_MASTER_CTL()
+-					| (0xff << 6));
++				write_MASTER_CTL(iface,
++					read_MASTER_CTL(iface) | (0xff << 6));
+ 			} else {
+ 				/* set the readd number in other
+ 				 * combine mode.
+ 				 */
+-				bfin_write_TWI_MASTER_CTL(
+-					(bfin_read_TWI_MASTER_CTL() &
++				write_MASTER_CTL(iface,
++					(read_MASTER_CTL(iface) &
+ 					(~(0xff << 6))) |
+-					( iface->readNum << 6));
++					(iface->readNum << 6));
++			}
++			/* remove restart bit and enable master receive */
++			write_MASTER_CTL(iface,
++				read_MASTER_CTL(iface) & ~RSTART);
++			write_MASTER_CTL(iface,
++				read_MASTER_CTL(iface) | MEN | MDIR);
++			SSYNC();
++		} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
++				iface->cur_msg+1 < iface->msg_num) {
++			iface->cur_msg++;
++			iface->transPtr = iface->pmsg[iface->cur_msg].buf;
++			iface->writeNum = iface->readNum =
++				iface->pmsg[iface->cur_msg].len;
++			/* Set Transmit device address */
++			write_MASTER_ADDR(iface,
++				iface->pmsg[iface->cur_msg].addr);
++			if (iface->pmsg[iface->cur_msg].flags & I2C_M_RD)
++				iface->read_write = I2C_SMBUS_READ;
++			else {
++				iface->read_write = I2C_SMBUS_WRITE;
++				/* Transmit first data */
++				if (iface->writeNum > 0) {
++					write_XMT_DATA8(iface,
++						*(iface->transPtr++));
++					iface->writeNum--;
++					SSYNC();
++				}
++			}
++
++			if (iface->pmsg[iface->cur_msg].len <= 255)
++				write_MASTER_CTL(iface,
++				iface->pmsg[iface->cur_msg].len << 6);
++			else {
++				write_MASTER_CTL(iface, 0xff << 6);
++				iface->manual_stop = 1;
+ 			}
+ 			/* remove restart bit and enable master receive */
+-			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() &
+-				~RSTART);
+-			bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
+-				MEN | MDIR);
++			write_MASTER_CTL(iface,
++				read_MASTER_CTL(iface) & ~RSTART);
++			write_MASTER_CTL(iface, read_MASTER_CTL(iface) |
++				MEN | ((iface->read_write == I2C_SMBUS_READ) ?
++				MDIR : 0));
+ 			SSYNC();
+ 		} else {
+ 			iface->result = 1;
+-			bfin_write_TWI_INT_MASK(0);
+-			bfin_write_TWI_MASTER_CTL(0);
++			write_INT_MASK(iface, 0);
++			write_MASTER_CTL(iface, 0);
+ 			SSYNC();
+ 			complete(&iface->complete);
+ 		}
+@@ -221,91 +284,85 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
+ {
+ 	struct bfin_twi_iface *iface = adap->algo_data;
+ 	struct i2c_msg *pmsg;
+-	int i, ret;
+ 	int rc = 0;
+ 
+-	if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
++	if (!(read_CONTROL(iface) & TWI_ENA))
+ 		return -ENXIO;
+ 
+-	while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
++	while (read_MASTER_STAT(iface) & BUSBUSY)
+ 		yield();
++
++	iface->pmsg = msgs;
++	iface->msg_num = num;
++	iface->cur_msg = 0;
++
++	pmsg = &msgs[0];
++	if (pmsg->flags & I2C_M_TEN) {
++		dev_err(&adap->dev, "10 bits addr not supported!\n");
++		return -EINVAL;
+ 	}
+ 
+-	ret = 0;
+-	for (i = 0; rc >= 0 && i < num; i++) {
+-		pmsg = &msgs[i];
+-		if (pmsg->flags & I2C_M_TEN) {
+-			dev_err(&(adap->dev), "i2c-bfin-twi: 10 bits addr "
+-				"not supported !\n");
+-			rc = -EINVAL;
+-			break;
+-		}
++	iface->cur_mode = TWI_I2C_MODE_REPEAT;
++	iface->manual_stop = 0;
++	iface->transPtr = pmsg->buf;
++	iface->writeNum = iface->readNum = pmsg->len;
++	iface->result = 0;
++	iface->timeout_count = 10;
++	init_completion(&(iface->complete));
++	/* Set Transmit device address */
++	write_MASTER_ADDR(iface, pmsg->addr);
+ 
+-		iface->cur_mode = TWI_I2C_MODE_STANDARD;
+-		iface->manual_stop = 0;
+-		iface->transPtr = pmsg->buf;
+-		iface->writeNum = iface->readNum = pmsg->len;
+-		iface->result = 0;
+-		iface->timeout_count = 10;
+-		/* Set Transmit device address */
+-		bfin_write_TWI_MASTER_ADDR(pmsg->addr);
+-
+-		/* FIFO Initiation. Data in FIFO should be
+-		 *  discarded before start a new operation.
+-		 */
+-		bfin_write_TWI_FIFO_CTL(0x3);
+-		SSYNC();
+-		bfin_write_TWI_FIFO_CTL(0);
+-		SSYNC();
++	/* FIFO Initiation. Data in FIFO should be
++	 *  discarded before start a new operation.
++	 */
++	write_FIFO_CTL(iface, 0x3);
++	SSYNC();
++	write_FIFO_CTL(iface, 0);
++	SSYNC();
+ 
+-		if (pmsg->flags & I2C_M_RD)
+-			iface->read_write = I2C_SMBUS_READ;
+-		else {
+-			iface->read_write = I2C_SMBUS_WRITE;
+-			/* Transmit first data */
+-			if (iface->writeNum > 0) {
+-				bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
+-				iface->writeNum--;
+-				SSYNC();
+-			}
++	if (pmsg->flags & I2C_M_RD)
++		iface->read_write = I2C_SMBUS_READ;
++	else {
++		iface->read_write = I2C_SMBUS_WRITE;
++		/* Transmit first data */
++		if (iface->writeNum > 0) {
++			write_XMT_DATA8(iface, *(iface->transPtr++));
++			iface->writeNum--;
++			SSYNC();
+ 		}
++	}
+ 
+-		/* clear int stat */
+-		bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
++	/* clear int stat */
++	write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV);
+ 
+-		/* Interrupt mask . Enable XMT, RCV interrupt */
+-		bfin_write_TWI_INT_MASK(MCOMP | MERR |
+-			((iface->read_write == I2C_SMBUS_READ)?
+-			RCVSERV : XMTSERV));
+-		SSYNC();
++	/* Interrupt mask . Enable XMT, RCV interrupt */
++	write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV);
++	SSYNC();
+ 
+-		if (pmsg->len > 0 && pmsg->len <= 255)
+-			bfin_write_TWI_MASTER_CTL(pmsg->len << 6);
+-		else if (pmsg->len > 255) {
+-			bfin_write_TWI_MASTER_CTL(0xff << 6);
+-			iface->manual_stop = 1;
+-		} else
+-			break;
++	if (pmsg->len <= 255)
++		write_MASTER_CTL(iface, pmsg->len << 6);
++	else {
++		write_MASTER_CTL(iface, 0xff << 6);
++		iface->manual_stop = 1;
++	}
+ 
+-		iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+-		add_timer(&iface->timeout_timer);
++	iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
++	add_timer(&iface->timeout_timer);
+ 
+-		/* Master enable */
+-		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+-			((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
+-			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+-		SSYNC();
++	/* Master enable */
++	write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
++		((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
++		((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
++	SSYNC();
+ 
+-		wait_for_completion(&iface->complete);
++	wait_for_completion(&iface->complete);
+ 
+-		rc = iface->result;
+-		if (rc == 1)
+-			ret++;
+-		else if (rc == -1)
+-			break;
+-	}
++	rc = iface->result;
+ 
+-	return ret;
++	if (rc == 1)
++		return num;
++	else
++		return rc;
+ }
+ 
+ /*
+@@ -319,12 +376,11 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ 	struct bfin_twi_iface *iface = adap->algo_data;
+ 	int rc = 0;
+ 
+-	if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
++	if (!(read_CONTROL(iface) & TWI_ENA))
+ 		return -ENXIO;
+ 
+-	while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
++	while (read_MASTER_STAT(iface) & BUSBUSY)
+ 		yield();
+-	}
+ 
+ 	iface->writeNum = 0;
+ 	iface->readNum = 0;
+@@ -392,19 +448,20 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ 	iface->read_write = read_write;
+ 	iface->command = command;
+ 	iface->timeout_count = 10;
++	init_completion(&(iface->complete));
+ 
+ 	/* FIFO Initiation. Data in FIFO should be discarded before
+ 	 * start a new operation.
+ 	 */
+-	bfin_write_TWI_FIFO_CTL(0x3);
++	write_FIFO_CTL(iface, 0x3);
+ 	SSYNC();
+-	bfin_write_TWI_FIFO_CTL(0);
++	write_FIFO_CTL(iface, 0);
+ 
+ 	/* clear int stat */
+-	bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
++	write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV);
+ 
+ 	/* Set Transmit device address */
+-	bfin_write_TWI_MASTER_ADDR(addr);
++	write_MASTER_ADDR(iface, addr);
+ 	SSYNC();
+ 
+ 	iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+@@ -412,60 +469,64 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ 
+ 	switch (iface->cur_mode) {
+ 	case TWI_I2C_MODE_STANDARDSUB:
+-		bfin_write_TWI_XMT_DATA8(iface->command);
+-		bfin_write_TWI_INT_MASK(MCOMP | MERR |
++		write_XMT_DATA8(iface, iface->command);
++		write_INT_MASK(iface, MCOMP | MERR |
+ 			((iface->read_write == I2C_SMBUS_READ) ?
+ 			RCVSERV : XMTSERV));
+ 		SSYNC();
+ 
+ 		if (iface->writeNum + 1 <= 255)
+-			bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
++			write_MASTER_CTL(iface, (iface->writeNum + 1) << 6);
+ 		else {
+-			bfin_write_TWI_MASTER_CTL(0xff << 6);
++			write_MASTER_CTL(iface, 0xff << 6);
+ 			iface->manual_stop = 1;
+ 		}
+ 		/* Master enable */
+-		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
++		write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
+ 			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+ 		break;
+ 	case TWI_I2C_MODE_COMBINED:
+-		bfin_write_TWI_XMT_DATA8(iface->command);
+-		bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV);
++		write_XMT_DATA8(iface, iface->command);
++		write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV);
+ 		SSYNC();
+ 
+ 		if (iface->writeNum > 0)
+-			bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
++			write_MASTER_CTL(iface, (iface->writeNum + 1) << 6);
+ 		else
+-			bfin_write_TWI_MASTER_CTL(0x1 << 6);
++			write_MASTER_CTL(iface, 0x1 << 6);
+ 		/* Master enable */
+-		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
++		write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
+ 			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+ 		break;
+ 	default:
+-		bfin_write_TWI_MASTER_CTL(0);
++		write_MASTER_CTL(iface, 0);
+ 		if (size != I2C_SMBUS_QUICK) {
+ 			/* Don't access xmit data register when this is a
+ 			 * read operation.
+ 			 */
+ 			if (iface->read_write != I2C_SMBUS_READ) {
+ 				if (iface->writeNum > 0) {
+-					bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
++					write_XMT_DATA8(iface,
++						*(iface->transPtr++));
+ 					if (iface->writeNum <= 255)
+-						bfin_write_TWI_MASTER_CTL(iface->writeNum << 6);
++						write_MASTER_CTL(iface,
++							iface->writeNum << 6);
+ 					else {
+-						bfin_write_TWI_MASTER_CTL(0xff << 6);
++						write_MASTER_CTL(iface,
++							0xff << 6);
+ 						iface->manual_stop = 1;
+ 					}
+ 					iface->writeNum--;
+ 				} else {
+-					bfin_write_TWI_XMT_DATA8(iface->command);
+-					bfin_write_TWI_MASTER_CTL(1 << 6);
++					write_XMT_DATA8(iface, iface->command);
++					write_MASTER_CTL(iface, 1 << 6);
+ 				}
+ 			} else {
+ 				if (iface->readNum > 0 && iface->readNum <= 255)
+-					bfin_write_TWI_MASTER_CTL(iface->readNum << 6);
++					write_MASTER_CTL(iface,
++						iface->readNum << 6);
+ 				else if (iface->readNum > 255) {
+-					bfin_write_TWI_MASTER_CTL(0xff << 6);
++					write_MASTER_CTL(iface, 0xff << 6);
+ 					iface->manual_stop = 1;
+ 				} else {
+ 					del_timer(&iface->timeout_timer);
+@@ -473,13 +534,13 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ 				}
+ 			}
+ 		}
+-		bfin_write_TWI_INT_MASK(MCOMP | MERR |
++		write_INT_MASK(iface, MCOMP | MERR |
+ 			((iface->read_write == I2C_SMBUS_READ) ?
+ 			RCVSERV : XMTSERV));
+ 		SSYNC();
+ 
+ 		/* Master enable */
+-		bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
++		write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
+ 			((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
+ 			((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
+ 		break;
+@@ -514,10 +575,10 @@ static struct i2c_algorithm bfin_twi_algorithm = {
+ 
+ static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
+ {
+-/*	struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
++	struct bfin_twi_iface *iface = platform_get_drvdata(dev);
+ 
+ 	/* Disable TWI */
+-	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() & ~TWI_ENA);
++	write_CONTROL(iface, read_CONTROL(iface) & ~TWI_ENA);
+ 	SSYNC();
+ 
+ 	return 0;
+@@ -525,24 +586,52 @@ static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
+ 
+ static int i2c_bfin_twi_resume(struct platform_device *dev)
+ {
+-/*	struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
++	struct bfin_twi_iface *iface = platform_get_drvdata(dev);
+ 
+ 	/* Enable TWI */
+-	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
++	write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
+ 	SSYNC();
+ 
+ 	return 0;
+ }
+ 
+-static int i2c_bfin_twi_probe(struct platform_device *dev)
++static int i2c_bfin_twi_probe(struct platform_device *pdev)
+ {
+-	struct bfin_twi_iface *iface = &twi_iface;
++	struct bfin_twi_iface *iface;
+ 	struct i2c_adapter *p_adap;
++	struct resource *res;
+ 	int rc;
+ 
++	iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL);
++	if (!iface) {
++		dev_err(&pdev->dev, "Cannot allocate memory\n");
++		rc = -ENOMEM;
++		goto out_error_nomem;
++	}
++
+ 	spin_lock_init(&(iface->lock));
+-	init_completion(&(iface->complete));
+-	iface->irq = IRQ_TWI;
++
++	/* Find and map our resources */
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (res == NULL) {
++		dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
++		rc = -ENOENT;
++		goto out_error_get_res;
++	}
++
++	iface->regs_base = ioremap(res->start, res->end - res->start + 1);
++	if (iface->regs_base == NULL) {
++		dev_err(&pdev->dev, "Cannot map IO\n");
++		rc = -ENXIO;
++		goto out_error_ioremap;
++	}
++
++	iface->irq = platform_get_irq(pdev, 0);
++	if (iface->irq < 0) {
++		dev_err(&pdev->dev, "No IRQ specified\n");
++		rc = -ENOENT;
++		goto out_error_no_irq;
++	}
+ 
+ 	init_timer(&(iface->timeout_timer));
+ 	iface->timeout_timer.function = bfin_twi_timeout;
+@@ -550,39 +639,63 @@ static int i2c_bfin_twi_probe(struct platform_device *dev)
+ 
+ 	p_adap = &iface->adap;
+ 	p_adap->id = I2C_HW_BLACKFIN;
+-	p_adap->nr = dev->id;
+-	strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
++	p_adap->nr = pdev->id;
++	strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name));
+ 	p_adap->algo = &bfin_twi_algorithm;
+ 	p_adap->algo_data = iface;
+ 	p_adap->class = I2C_CLASS_ALL;
+-	p_adap->dev.parent = &dev->dev;
++	p_adap->dev.parent = &pdev->dev;
++
++	rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi");
++	if (rc) {
++		dev_err(&pdev->dev, "Can't setup pin mux!\n");
++		goto out_error_pin_mux;
++	}
+ 
+ 	rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
+-		IRQF_DISABLED, dev->name, iface);
++		IRQF_DISABLED, pdev->name, iface);
+ 	if (rc) {
+-		dev_err(&(p_adap->dev), "i2c-bfin-twi: can't get IRQ %d !\n",
+-			iface->irq);
+-		return -ENODEV;
++		dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
++		rc = -ENODEV;
++		goto out_error_req_irq;
+ 	}
+ 
+ 	/* Set TWI internal clock as 10MHz */
+-	bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
++	write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
+ 
+ 	/* Set Twi interface clock as specified */
+-	bfin_write_TWI_CLKDIV((( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
+-			<< 8) | (( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
++	write_CLKDIV(iface, ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
++			<< 8) | ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
+ 			& 0xFF));
+ 
+ 	/* Enable TWI */
+-	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
++	write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
+ 	SSYNC();
+ 
+ 	rc = i2c_add_numbered_adapter(p_adap);
+-	if (rc < 0)
+-		free_irq(iface->irq, iface);
+-	else
+-		platform_set_drvdata(dev, iface);
++	if (rc < 0) {
++		dev_err(&pdev->dev, "Can't add i2c adapter!\n");
++		goto out_error_add_adapter;
++	}
++
++	platform_set_drvdata(pdev, iface);
+ 
++	dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Contoller, "
++		"regs_base@%p\n", iface->regs_base);
++
++	return 0;
++
++out_error_add_adapter:
++	free_irq(iface->irq, iface);
++out_error_req_irq:
++out_error_no_irq:
++	peripheral_free_list(pin_req[pdev->id]);
++out_error_pin_mux:
++	iounmap(iface->regs_base);
++out_error_ioremap:
++out_error_get_res:
++	kfree(iface);
++out_error_nomem:
+ 	return rc;
+ }
+ 
+@@ -594,6 +707,9 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
+ 
+ 	i2c_del_adapter(&(iface->adap));
+ 	free_irq(iface->irq, iface);
++	peripheral_free_list(pin_req[pdev->id]);
++	iounmap(iface->regs_base);
++	kfree(iface);
+ 
+ 	return 0;
+ }
+@@ -611,8 +727,6 @@ static struct platform_driver i2c_bfin_twi_driver = {
+ 
+ static int __init i2c_bfin_twi_init(void)
+ {
+-	pr_info("I2C: Blackfin I2C TWI driver\n");
+-
+ 	return platform_driver_register(&i2c_bfin_twi_driver);
+ }
+ 
+@@ -621,9 +735,10 @@ static void __exit i2c_bfin_twi_exit(void)
+ 	platform_driver_unregister(&i2c_bfin_twi_driver);
+ }
+ 
+-MODULE_AUTHOR("Sonic Zhang <sonic.zhang at analog.com>");
+-MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI");
+-MODULE_LICENSE("GPL");
+-
+ module_init(i2c_bfin_twi_init);
+ module_exit(i2c_bfin_twi_exit);
++
++MODULE_AUTHOR("Bryan Wu, Sonic Zhang");
++MODULE_DESCRIPTION("Blackfin BF5xx on-chip I2C TWI Contoller Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:i2c-bfin-twi");
+diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
+index fde2634..7ecbfc4 100644
+--- a/drivers/i2c/busses/i2c-davinci.c
++++ b/drivers/i2c/busses/i2c-davinci.c
+@@ -328,7 +328,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+ 	int i;
+ 	int ret;
+ 
+-	dev_dbg(dev->dev, "%s: msgs: %d\n", __FUNCTION__, num);
++	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
+ 
+ 	ret = i2c_davinci_wait_bus_not_busy(dev, 1);
+ 	if (ret < 0) {
+@@ -342,7 +342,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+ 			return ret;
+ 	}
+ 
+-	dev_dbg(dev->dev, "%s:%d ret: %d\n", __FUNCTION__, __LINE__, ret);
++	dev_dbg(dev->dev, "%s:%d ret: %d\n", __func__, __LINE__, ret);
+ 
+ 	return num;
+ }
+@@ -364,7 +364,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
+ 	u16 w;
+ 
+ 	while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
+-		dev_dbg(dev->dev, "%s: stat=0x%x\n", __FUNCTION__, stat);
++		dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
+ 		if (count++ == 100) {
+ 			dev_warn(dev->dev, "Too much work in one IRQ\n");
+ 			break;
+@@ -553,6 +553,9 @@ static int davinci_i2c_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:i2c_davinci");
++
+ static struct platform_driver davinci_i2c_driver = {
+ 	.probe		= davinci_i2c_probe,
+ 	.remove		= davinci_i2c_remove,
+diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
+index 3ca19fc..7c1b762 100644
+--- a/drivers/i2c/busses/i2c-gpio.c
++++ b/drivers/i2c/busses/i2c-gpio.c
+@@ -220,3 +220,4 @@ module_exit(i2c_gpio_exit);
+ MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen at atmel.com>");
+ MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:i2c-gpio");
+diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
+index 22bb247..85dbf34 100644
+--- a/drivers/i2c/busses/i2c-ibm_iic.c
++++ b/drivers/i2c/busses/i2c-ibm_iic.c
+@@ -6,6 +6,9 @@
+  * Copyright (c) 2003, 2004 Zultys Technologies.
+  * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+  *
++ * Copyright (c) 2008 PIKA Technologies
++ * Sean MacLennan <smaclennan at pikatech.com>
++ *
+  * Based on original work by
+  * 	Ian DaSilva  <idasilva at mvista.com>
+  *      Armin Kuster <akuster at mvista.com>
+@@ -39,12 +42,17 @@
+ #include <asm/io.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-id.h>
++
++#ifdef CONFIG_IBM_OCP
+ #include <asm/ocp.h>
+ #include <asm/ibm4xx.h>
++#else
++#include <linux/of_platform.h>
++#endif
+ 
+ #include "i2c-ibm_iic.h"
+ 
+-#define DRIVER_VERSION "2.1"
++#define DRIVER_VERSION "2.2"
+ 
+ MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
+ MODULE_LICENSE("GPL");
+@@ -650,13 +658,14 @@ static inline u8 iic_clckdiv(unsigned int opb)
+ 	opb /= 1000000;
+ 
+ 	if (opb < 20 || opb > 150){
+-		printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
++		printk(KERN_WARNING "ibm-iic: invalid OPB clock frequency %u MHz\n",
+ 			opb);
+ 		opb = opb < 20 ? 20 : 150;
+ 	}
+ 	return (u8)((opb + 9) / 10 - 1);
+ }
+ 
++#ifdef CONFIG_IBM_OCP
+ /*
+  * Register single IIC interface
+  */
+@@ -672,7 +681,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ 			ocp->def->index);
+ 
+ 	if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
+-		printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n",
++		printk(KERN_ERR "ibm-iic%d: failed to allocate device data\n",
+ 			ocp->def->index);
+ 		return -ENOMEM;
+ 	}
+@@ -687,7 +696,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ 	}
+ 
+ 	if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
+-		printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
++		printk(KERN_ERR "ibm-iic%d: failed to ioremap device registers\n",
+ 			dev->idx);
+ 		ret = -ENXIO;
+ 		goto fail2;
+@@ -745,7 +754,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ 	adap->nr = dev->idx >= 0 ? dev->idx : 0;
+ 
+ 	if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
+-		printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n",
++		printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n",
+ 			dev->idx);
+ 		goto fail;
+ 	}
+@@ -778,7 +787,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
+ 	struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
+ 	BUG_ON(dev == NULL);
+ 	if (i2c_del_adapter(&dev->adap)){
+-		printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n",
++		printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n",
+ 			dev->idx);
+ 		/* That's *very* bad, just shutdown IRQ ... */
+ 		if (dev->irq >= 0){
+@@ -828,5 +837,181 @@ static void __exit iic_exit(void)
+ 	ocp_unregister_driver(&ibm_iic_driver);
+ }
+ 
++#else  /* !CONFIG_IBM_OCP */
++
++static int __devinit iic_request_irq(struct of_device *ofdev,
++				     struct ibm_iic_private *dev)
++{
++	struct device_node *np = ofdev->node;
++	int irq;
++
++	if (iic_force_poll)
++		return NO_IRQ;
++
++	irq = irq_of_parse_and_map(np, 0);
++	if (irq == NO_IRQ) {
++		dev_err(&ofdev->dev, "irq_of_parse_and_map failed\n");
++		return NO_IRQ;
++	}
++
++	/* Disable interrupts until we finish initialization, assumes
++	 *  level-sensitive IRQ setup...
++	 */
++	iic_interrupt_mode(dev, 0);
++	if (request_irq(irq, iic_handler, 0, "IBM IIC", dev)) {
++		dev_err(&ofdev->dev, "request_irq %d failed\n", irq);
++		/* Fallback to the polling mode */
++		return NO_IRQ;
++	}
++
++	return irq;
++}
++
++/*
++ * Register single IIC interface
++ */
++static int __devinit iic_probe(struct of_device *ofdev,
++			       const struct of_device_id *match)
++{
++	struct device_node *np = ofdev->node;
++	struct ibm_iic_private *dev;
++	struct i2c_adapter *adap;
++	const u32 *indexp, *freq;
++	int ret;
++
++	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++	if (!dev) {
++		dev_err(&ofdev->dev, "failed to allocate device data\n");
++		return -ENOMEM;
++	}
++
++	dev_set_drvdata(&ofdev->dev, dev);
++
++	indexp = of_get_property(np, "index", NULL);
++	if (!indexp) {
++		dev_err(&ofdev->dev, "no index specified\n");
++		ret = -EINVAL;
++		goto error_cleanup;
++	}
++	dev->idx = *indexp;
++
++	dev->vaddr = of_iomap(np, 0);
++	if (dev->vaddr == NULL) {
++		dev_err(&ofdev->dev, "failed to iomap device\n");
++		ret = -ENXIO;
++		goto error_cleanup;
++	}
++
++	init_waitqueue_head(&dev->wq);
++
++	dev->irq = iic_request_irq(ofdev, dev);
++	if (dev->irq == NO_IRQ)
++		dev_warn(&ofdev->dev, "using polling mode\n");
++
++	/* Board specific settings */
++	if (iic_force_fast || of_get_property(np, "fast-mode", NULL))
++		dev->fast_mode = 1;
++
++	freq = of_get_property(np, "clock-frequency", NULL);
++	if (freq == NULL) {
++		freq = of_get_property(np->parent, "clock-frequency", NULL);
++		if (freq == NULL) {
++			dev_err(&ofdev->dev, "Unable to get bus frequency\n");
++			ret = -EINVAL;
++			goto error_cleanup;
++		}
++	}
++
++	dev->clckdiv = iic_clckdiv(*freq);
++	dev_dbg(&ofdev->dev, "clckdiv = %d\n", dev->clckdiv);
++
++	/* Initialize IIC interface */
++	iic_dev_init(dev);
++
++	/* Register it with i2c layer */
++	adap = &dev->adap;
++	adap->dev.parent = &ofdev->dev;
++	strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
++	i2c_set_adapdata(adap, dev);
++	adap->id = I2C_HW_OCP;
++	adap->class = I2C_CLASS_HWMON;
++	adap->algo = &iic_algo;
++	adap->timeout = 1;
++	adap->nr = dev->idx;
++
++	ret = i2c_add_numbered_adapter(adap);
++	if (ret  < 0) {
++		dev_err(&ofdev->dev, "failed to register i2c adapter\n");
++		goto error_cleanup;
++	}
++
++	dev_info(&ofdev->dev, "using %s mode\n",
++		 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
++
++	return 0;
++
++error_cleanup:
++	if (dev->irq != NO_IRQ) {
++		iic_interrupt_mode(dev, 0);
++		free_irq(dev->irq, dev);
++	}
++
++	if (dev->vaddr)
++		iounmap(dev->vaddr);
++
++	dev_set_drvdata(&ofdev->dev, NULL);
++	kfree(dev);
++	return ret;
++}
++
++/*
++ * Cleanup initialized IIC interface
++ */
++static int __devexit iic_remove(struct of_device *ofdev)
++{
++	struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev);
++
++	dev_set_drvdata(&ofdev->dev, NULL);
++
++	i2c_del_adapter(&dev->adap);
++
++	if (dev->irq != NO_IRQ) {
++		iic_interrupt_mode(dev, 0);
++		free_irq(dev->irq, dev);
++	}
++
++	iounmap(dev->vaddr);
++	kfree(dev);
++
++	return 0;
++}
++
++static const struct of_device_id ibm_iic_match[] = {
++	{ .compatible = "ibm,iic-405ex", },
++	{ .compatible = "ibm,iic-405gp", },
++	{ .compatible = "ibm,iic-440gp", },
++	{ .compatible = "ibm,iic-440gpx", },
++	{ .compatible = "ibm,iic-440grx", },
++	{}
++};
++
++static struct of_platform_driver ibm_iic_driver = {
++	.name	= "ibm-iic",
++	.match_table = ibm_iic_match,
++	.probe	= iic_probe,
++	.remove	= __devexit_p(iic_remove),
++};
++
++static int __init iic_init(void)
++{
++	return of_register_platform_driver(&ibm_iic_driver);
++}
++
++static void __exit iic_exit(void)
++{
++	of_unregister_platform_driver(&ibm_iic_driver);
++}
++#endif /* CONFIG_IBM_OCP */
++
+ module_init(iic_init);
+ module_exit(iic_exit);
+diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
+index ab41400..39884e7 100644
+--- a/drivers/i2c/busses/i2c-iop3xx.c
++++ b/drivers/i2c/busses/i2c-iop3xx.c
+@@ -550,3 +550,4 @@ module_exit (i2c_iop3xx_exit);
+ MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
+ MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:IOP3xx-I2C");
+diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
+index 6352121..5af9e65 100644
+--- a/drivers/i2c/busses/i2c-ixp2000.c
++++ b/drivers/i2c/busses/i2c-ixp2000.c
+@@ -164,4 +164,5 @@ module_exit(ixp2000_i2c_exit);
+ MODULE_AUTHOR ("Deepak Saxena <dsaxena at plexity.net>");
+ MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:IXP2000-I2C");
+ 
+diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
+index bbe787b..18beb0a 100644
+--- a/drivers/i2c/busses/i2c-mpc.c
++++ b/drivers/i2c/busses/i2c-mpc.c
+@@ -392,6 +392,9 @@ static int fsl_i2c_remove(struct platform_device *pdev)
+ 	return 0;
+ };
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:fsl-i2c");
++
+ /* Structure for a device driver */
+ static struct platform_driver fsl_i2c_driver = {
+ 	.probe = fsl_i2c_probe,
+diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
+index e417c2c..f145692 100644
+--- a/drivers/i2c/busses/i2c-ocores.c
++++ b/drivers/i2c/busses/i2c-ocores.c
+@@ -312,6 +312,9 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:ocores-i2c");
++
+ static struct platform_driver ocores_i2c_driver = {
+ 	.probe  = ocores_i2c_probe,
+ 	.remove = __devexit_p(ocores_i2c_remove),
+diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
+index 7ba3177..e7eb7bf 100644
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -693,3 +693,4 @@ module_exit(omap_i2c_exit_driver);
+ MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
+ MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:i2c_omap");
+diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
+index 496ee87..a119784 100644
+--- a/drivers/i2c/busses/i2c-pca-isa.c
++++ b/drivers/i2c/busses/i2c-pca-isa.c
+@@ -1,6 +1,7 @@
+ /*
+  *  i2c-pca-isa.c driver for PCA9564 on ISA boards
+  *    Copyright (C) 2004 Arcom Control Systems
++ *    Copyright (C) 2008 Pengutronix
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+@@ -22,11 +23,9 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/delay.h>
+-#include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/wait.h>
+-
+ #include <linux/isa.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-pca.h>
+@@ -34,13 +33,9 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ 
+-#include "../algos/i2c-algo-pca.h"
+-
++#define DRIVER "i2c-pca-isa"
+ #define IO_SIZE 4
+ 
+-#undef DEBUG_IO
+-//#define DEBUG_IO
+-
+ static unsigned long base   = 0x330;
+ static int irq 	  = 10;
+ 
+@@ -48,22 +43,9 @@ static int irq 	  = 10;
+  * in the actual clock rate */
+ static int clock  = I2C_PCA_CON_59kHz;
+ 
+-static int own    = 0x55;
+-
+ static wait_queue_head_t pca_wait;
+ 
+-static int pca_isa_getown(struct i2c_algo_pca_data *adap)
+-{
+-	return (own);
+-}
+-
+-static int pca_isa_getclock(struct i2c_algo_pca_data *adap)
+-{
+-	return (clock);
+-}
+-
+-static void
+-pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
++static void pca_isa_writebyte(void *pd, int reg, int val)
+ {
+ #ifdef DEBUG_IO
+ 	static char *names[] = { "T/O", "DAT", "ADR", "CON" };
+@@ -72,44 +54,49 @@ pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
+ 	outb(val, base+reg);
+ }
+ 
+-static int
+-pca_isa_readbyte(struct i2c_algo_pca_data *adap, int reg)
++static int pca_isa_readbyte(void *pd, int reg)
+ {
+ 	int res = inb(base+reg);
+ #ifdef DEBUG_IO
+ 	{
+-		static char *names[] = { "STA", "DAT", "ADR", "CON" };	
++		static char *names[] = { "STA", "DAT", "ADR", "CON" };
+ 		printk("*** read  %s => %#04x\n", names[reg], res);
+ 	}
+ #endif
+ 	return res;
+ }
+ 
+-static int pca_isa_waitforinterrupt(struct i2c_algo_pca_data *adap)
++static int pca_isa_waitforcompletion(void *pd)
+ {
+ 	int ret = 0;
+ 
+ 	if (irq > -1) {
+ 		ret = wait_event_interruptible(pca_wait,
+-					       pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI);
++					       pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI);
+ 	} else {
+-		while ((pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) 
++		while ((pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
+ 			udelay(100);
+ 	}
+ 	return ret;
+ }
+ 
++static void pca_isa_resetchip(void *pd)
++{
++	/* apparently only an external reset will do it. not a lot can be done */
++	printk(KERN_WARNING DRIVER ": Haven't figured out how to do a reset yet\n");
++}
++
+ static irqreturn_t pca_handler(int this_irq, void *dev_id) {
+ 	wake_up_interruptible(&pca_wait);
+ 	return IRQ_HANDLED;
+ }
+ 
+ static struct i2c_algo_pca_data pca_isa_data = {
+-	.get_own		= pca_isa_getown,
+-	.get_clock		= pca_isa_getclock,
++	/* .data intentionally left NULL, not needed with ISA */
+ 	.write_byte		= pca_isa_writebyte,
+ 	.read_byte		= pca_isa_readbyte,
+-	.wait_for_interrupt	= pca_isa_waitforinterrupt,
++	.wait_for_completion	= pca_isa_waitforcompletion,
++	.reset_chip		= pca_isa_resetchip,
+ };
+ 
+ static struct i2c_adapter pca_isa_ops = {
+@@ -117,6 +104,7 @@ static struct i2c_adapter pca_isa_ops = {
+ 	.id		= I2C_HW_A_ISA,
+ 	.algo_data	= &pca_isa_data,
+ 	.name		= "PCA9564 ISA Adapter",
++	.timeout	= 100,
+ };
+ 
+ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
+@@ -144,6 +132,7 @@ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
+ 		}
+ 	}
+ 
++	pca_isa_data.i2c_clock = clock;
+ 	if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
+ 		dev_err(dev, "Failed to add i2c bus\n");
+ 		goto out_irq;
+@@ -178,7 +167,7 @@ static struct isa_driver pca_isa_driver = {
+ 	.remove		= __devexit_p(pca_isa_remove),
+ 	.driver = {
+ 		.owner	= THIS_MODULE,
+-		.name	= "i2c-pca-isa",
++		.name	= DRIVER,
+ 	}
+ };
+ 
+@@ -204,7 +193,5 @@ MODULE_PARM_DESC(irq, "IRQ");
+ module_param(clock, int, 0);
+ MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet");
+ 
+-module_param(own, int, 0); /* the driver can't do slave mode, so there's no real point in this */
+-
+ module_init(pca_isa_init);
+ module_exit(pca_isa_exit);
+diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
+new file mode 100644
+index 0000000..9d75f51
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-pca-platform.c
+@@ -0,0 +1,298 @@
++/*
++ *  i2c_pca_platform.c
++ *
++ *  Platform driver for the PCA9564 I2C controller.
++ *
++ *  Copyright (C) 2008 Pengutronix
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/i2c.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/i2c-algo-pca.h>
++#include <linux/i2c-pca-platform.h>
++#include <linux/gpio.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#define res_len(r)		((r)->end - (r)->start + 1)
++
++struct i2c_pca_pf_data {
++	void __iomem			*reg_base;
++	int				irq;	/* if 0, use polling */
++	int				gpio;
++	wait_queue_head_t		wait;
++	struct i2c_adapter		adap;
++	struct i2c_algo_pca_data	algo_data;
++	unsigned long			io_base;
++	unsigned long			io_size;
++};
++
++/* Read/Write functions for different register alignments */
++
++static int i2c_pca_pf_readbyte8(void *pd, int reg)
++{
++	struct i2c_pca_pf_data *i2c = pd;
++	return ioread8(i2c->reg_base + reg);
++}
++
++static int i2c_pca_pf_readbyte16(void *pd, int reg)
++{
++	struct i2c_pca_pf_data *i2c = pd;
++	return ioread8(i2c->reg_base + reg * 2);
++}
++
++static int i2c_pca_pf_readbyte32(void *pd, int reg)
++{
++	struct i2c_pca_pf_data *i2c = pd;
++	return ioread8(i2c->reg_base + reg * 4);
++}
++
++static void i2c_pca_pf_writebyte8(void *pd, int reg, int val)
++{
++	struct i2c_pca_pf_data *i2c = pd;
++	iowrite8(val, i2c->reg_base + reg);
++}
++
++static void i2c_pca_pf_writebyte16(void *pd, int reg, int val)
++{
++	struct i2c_pca_pf_data *i2c = pd;
++	iowrite8(val, i2c->reg_base + reg * 2);
++}
++
++static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)
++{
++	struct i2c_pca_pf_data *i2c = pd;
++	iowrite8(val, i2c->reg_base + reg * 4);
++}
++
++
++static int i2c_pca_pf_waitforcompletion(void *pd)
++{
++	struct i2c_pca_pf_data *i2c = pd;
++	int ret = 0;
++
++	if (i2c->irq) {
++		ret = wait_event_interruptible(i2c->wait,
++			i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
++			& I2C_PCA_CON_SI);
++	} else {
++		/*
++		 * Do polling...
++		 * XXX: Could get stuck in extreme cases!
++		 *      Maybe add timeout, but using irqs is preferred anyhow.
++		 */
++		while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
++				& I2C_PCA_CON_SI) == 0)
++			udelay(100);
++	}
++
++	return ret;
++}
++
++static void i2c_pca_pf_dummyreset(void *pd)
++{
++	struct i2c_pca_pf_data *i2c = pd;
++	printk(KERN_WARNING "%s: No reset-pin found. Chip may get stuck!\n",
++		i2c->adap.name);
++}
++
++static void i2c_pca_pf_resetchip(void *pd)
++{
++	struct i2c_pca_pf_data *i2c = pd;
++
++	gpio_set_value(i2c->gpio, 0);
++	ndelay(100);
++	gpio_set_value(i2c->gpio, 1);
++}
++
++static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id)
++{
++	struct i2c_pca_pf_data *i2c = dev_id;
++
++	if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
++		return IRQ_NONE;
++
++	wake_up_interruptible(&i2c->wait);
++
++	return IRQ_HANDLED;
++}
++
++
++static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
++{
++	struct i2c_pca_pf_data *i2c;
++	struct resource *res;
++	struct i2c_pca9564_pf_platform_data *platform_data =
++				pdev->dev.platform_data;
++	int ret = 0;
++	int irq;
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	irq = platform_get_irq(pdev, 0);
++	/* If irq is 0, we do polling. */
++
++	if (res == NULL) {
++		ret = -ENODEV;
++		goto e_print;
++	}
++
++	if (!request_mem_region(res->start, res_len(res), res->name)) {
++		ret = -ENOMEM;
++		goto e_print;
++	}
++
++	i2c = kzalloc(sizeof(struct i2c_pca_pf_data), GFP_KERNEL);
++	if (!i2c) {
++		ret = -ENOMEM;
++		goto e_alloc;
++	}
++
++	init_waitqueue_head(&i2c->wait);
++
++	i2c->reg_base = ioremap(res->start, res_len(res));
++	if (!i2c->reg_base) {
++		ret = -EIO;
++		goto e_remap;
++	}
++	i2c->io_base = res->start;
++	i2c->io_size = res_len(res);
++	i2c->irq = irq;
++
++	i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
++	i2c->adap.owner = THIS_MODULE;
++	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "PCA9564 at 0x%08lx",
++		(unsigned long) res->start);
++	i2c->adap.algo_data = &i2c->algo_data;
++	i2c->adap.dev.parent = &pdev->dev;
++	i2c->adap.timeout = platform_data->timeout;
++
++	i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
++	i2c->algo_data.data = i2c;
++
++	switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
++	case IORESOURCE_MEM_32BIT:
++		i2c->algo_data.write_byte = i2c_pca_pf_writebyte32;
++		i2c->algo_data.read_byte = i2c_pca_pf_readbyte32;
++		break;
++	case IORESOURCE_MEM_16BIT:
++		i2c->algo_data.write_byte = i2c_pca_pf_writebyte16;
++		i2c->algo_data.read_byte = i2c_pca_pf_readbyte16;
++		break;
++	case IORESOURCE_MEM_8BIT:
++	default:
++		i2c->algo_data.write_byte = i2c_pca_pf_writebyte8;
++		i2c->algo_data.read_byte = i2c_pca_pf_readbyte8;
++		break;
++	}
++
++	i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
++
++	i2c->gpio = platform_data->gpio;
++	i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset;
++
++	/* Use gpio_is_valid() when in mainline */
++	if (i2c->gpio > -1) {
++		ret = gpio_request(i2c->gpio, i2c->adap.name);
++		if (ret == 0) {
++			gpio_direction_output(i2c->gpio, 1);
++			i2c->algo_data.reset_chip = i2c_pca_pf_resetchip;
++		} else {
++			printk(KERN_WARNING "%s: Registering gpio failed!\n",
++				i2c->adap.name);
++			i2c->gpio = ret;
++		}
++	}
++
++	if (irq) {
++		ret = request_irq(irq, i2c_pca_pf_handler,
++			IRQF_TRIGGER_FALLING, i2c->adap.name, i2c);
++		if (ret)
++			goto e_reqirq;
++	}
++
++	if (i2c_pca_add_numbered_bus(&i2c->adap) < 0) {
++		ret = -ENODEV;
++		goto e_adapt;
++	}
++
++	platform_set_drvdata(pdev, i2c);
++
++	printk(KERN_INFO "%s registered.\n", i2c->adap.name);
++
++	return 0;
++
++e_adapt:
++	if (irq)
++		free_irq(irq, i2c);
++e_reqirq:
++	if (i2c->gpio > -1)
++		gpio_free(i2c->gpio);
++
++	iounmap(i2c->reg_base);
++e_remap:
++	kfree(i2c);
++e_alloc:
++	release_mem_region(res->start, res_len(res));
++e_print:
++	printk(KERN_ERR "Registering PCA9564 FAILED! (%d)\n", ret);
++	return ret;
++}
++
++static int __devexit i2c_pca_pf_remove(struct platform_device *pdev)
++{
++	struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev);
++	platform_set_drvdata(pdev, NULL);
++
++	i2c_del_adapter(&i2c->adap);
++
++	if (i2c->irq)
++		free_irq(i2c->irq, i2c);
++
++	if (i2c->gpio > -1)
++		gpio_free(i2c->gpio);
++
++	iounmap(i2c->reg_base);
++	release_mem_region(i2c->io_base, i2c->io_size);
++	kfree(i2c);
++
++	return 0;
++}
++
++static struct platform_driver i2c_pca_pf_driver = {
++	.probe = i2c_pca_pf_probe,
++	.remove = __devexit_p(i2c_pca_pf_remove),
++	.driver = {
++		.name = "i2c-pca-platform",
++		.owner = THIS_MODULE,
++	},
++};
++
++static int __init i2c_pca_pf_init(void)
++{
++	return platform_driver_register(&i2c_pca_pf_driver);
++}
++
++static void __exit i2c_pca_pf_exit(void)
++{
++	platform_driver_unregister(&i2c_pca_pf_driver);
++}
++
++MODULE_AUTHOR("Wolfram Sang <w.sang at pengutronix.de>");
++MODULE_DESCRIPTION("I2C-PCA9564 platform driver");
++MODULE_LICENSE("GPL");
++
++module_init(i2c_pca_pf_init);
++module_exit(i2c_pca_pf_exit);
++
+diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
+index b03af56..63b3e2c 100644
+--- a/drivers/i2c/busses/i2c-pmcmsp.c
++++ b/drivers/i2c/busses/i2c-pmcmsp.c
+@@ -467,7 +467,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
+ 	    (cmd->read_len == 0 || cmd->write_len == 0))) {
+ 		dev_err(&pmcmsptwi_adapter.dev,
+ 			"%s: Cannot transfer less than 1 byte\n",
+-			__FUNCTION__);
++			__func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -475,7 +475,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
+ 	    cmd->write_len > MSP_MAX_BYTES_PER_RW) {
+ 		dev_err(&pmcmsptwi_adapter.dev,
+ 			"%s: Cannot transfer more than %d bytes\n",
+-			__FUNCTION__, MSP_MAX_BYTES_PER_RW);
++			__func__, MSP_MAX_BYTES_PER_RW);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -627,6 +627,9 @@ static struct i2c_adapter pmcmsptwi_adapter = {
+ 	.name		= DRV_NAME,
+ };
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:" DRV_NAME);
++
+ static struct platform_driver pmcmsptwi_driver = {
+ 	.probe  = pmcmsptwi_probe,
+ 	.remove	= __devexit_p(pmcmsptwi_remove),
+diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
+index f8d0dff..1ca2108 100644
+--- a/drivers/i2c/busses/i2c-pnx.c
++++ b/drivers/i2c/busses/i2c-pnx.c
+@@ -76,7 +76,7 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
+ {
+ 	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+ 
+-	dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __FUNCTION__,
++	dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __func__,
+ 		slave_addr, alg_data->mif.mode);
+ 
+ 	/* Check for 7 bit slave addresses only */
+@@ -110,14 +110,14 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
+ 	iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
+ 		  I2C_REG_STS(alg_data));
+ 
+-	dev_dbg(&adap->dev, "%s(): sending %#x\n", __FUNCTION__,
++	dev_dbg(&adap->dev, "%s(): sending %#x\n", __func__,
+ 		(slave_addr << 1) | start_bit | alg_data->mif.mode);
+ 
+ 	/* Write the slave address, START bit and R/W bit */
+ 	iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
+ 		  I2C_REG_TX(alg_data));
+ 
+-	dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__);
++	dev_dbg(&adap->dev, "%s(): exit\n", __func__);
+ 
+ 	return 0;
+ }
+@@ -135,7 +135,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
+ 	long timeout = 1000;
+ 
+ 	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+-		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++		__func__, ioread32(I2C_REG_STS(alg_data)));
+ 
+ 	/* Write a STOP bit to TX FIFO */
+ 	iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
+@@ -149,7 +149,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
+ 	}
+ 
+ 	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+-		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++		__func__, ioread32(I2C_REG_STS(alg_data)));
+ }
+ 
+ /**
+@@ -164,7 +164,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+ 	u32 val;
+ 
+ 	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+-		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++		__func__, ioread32(I2C_REG_STS(alg_data)));
+ 
+ 	if (alg_data->mif.len > 0) {
+ 		/* We still have something to talk about... */
+@@ -179,7 +179,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+ 		alg_data->mif.len--;
+ 		iowrite32(val, I2C_REG_TX(alg_data));
+ 
+-		dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __FUNCTION__,
++		dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __func__,
+ 			val, alg_data->mif.len + 1);
+ 
+ 		if (alg_data->mif.len == 0) {
+@@ -197,7 +197,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+ 			del_timer_sync(&alg_data->mif.timer);
+ 
+ 			dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n",
+-				__FUNCTION__);
++				__func__);
+ 
+ 			complete(&alg_data->mif.complete);
+ 		}
+@@ -213,13 +213,13 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+ 		/* Stop timer. */
+ 		del_timer_sync(&alg_data->mif.timer);
+ 		dev_dbg(&adap->dev, "%s(): Waking up xfer routine after "
+-			"zero-xfer.\n", __FUNCTION__);
++			"zero-xfer.\n", __func__);
+ 
+ 		complete(&alg_data->mif.complete);
+ 	}
+ 
+ 	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+-		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++		__func__, ioread32(I2C_REG_STS(alg_data)));
+ 
+ 	return 0;
+ }
+@@ -237,14 +237,14 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
+ 	u32 ctl = 0;
+ 
+ 	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+-		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++		__func__, ioread32(I2C_REG_STS(alg_data)));
+ 
+ 	/* Check, whether there is already data,
+ 	 * or we didn't 'ask' for it yet.
+ 	 */
+ 	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
+ 		dev_dbg(&adap->dev, "%s(): Write dummy data to fill "
+-			"Rx-fifo...\n", __FUNCTION__);
++			"Rx-fifo...\n", __func__);
+ 
+ 		if (alg_data->mif.len == 1) {
+ 			/* Last byte, do not acknowledge next rcv. */
+@@ -276,7 +276,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
+ 	if (alg_data->mif.len > 0) {
+ 		val = ioread32(I2C_REG_RX(alg_data));
+ 		*alg_data->mif.buf++ = (u8) (val & 0xff);
+-		dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __FUNCTION__, val,
++		dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __func__, val,
+ 			alg_data->mif.len);
+ 
+ 		alg_data->mif.len--;
+@@ -300,7 +300,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
+ 	}
+ 
+ 	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+-		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++		__func__, ioread32(I2C_REG_STS(alg_data)));
+ 
+ 	return 0;
+ }
+@@ -312,7 +312,7 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
+ 	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+ 
+ 	dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n",
+-		__FUNCTION__,
++		__func__,
+ 		ioread32(I2C_REG_STS(alg_data)),
+ 		ioread32(I2C_REG_CTL(alg_data)),
+ 		alg_data->mif.mode);
+@@ -336,7 +336,7 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
+ 		/* Slave did not acknowledge, generate a STOP */
+ 		dev_dbg(&adap->dev, "%s(): "
+ 			"Slave did not acknowledge, generating a STOP.\n",
+-			__FUNCTION__);
++			__func__);
+ 		i2c_pnx_stop(adap);
+ 
+ 		/* Disable master interrupts. */
+@@ -375,7 +375,7 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
+ 	iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
+ 
+ 	dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n",
+-		 __FUNCTION__, ioread32(I2C_REG_STS(alg_data)),
++		 __func__, ioread32(I2C_REG_STS(alg_data)),
+ 		 ioread32(I2C_REG_CTL(alg_data)));
+ 
+ 	return IRQ_HANDLED;
+@@ -447,7 +447,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ 	u32 stat = ioread32(I2C_REG_STS(alg_data));
+ 
+ 	dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n",
+-		__FUNCTION__, num, ioread32(I2C_REG_STS(alg_data)));
++		__func__, num, ioread32(I2C_REG_STS(alg_data)));
+ 
+ 	bus_reset_if_active(adap);
+ 
+@@ -473,7 +473,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ 		alg_data->mif.ret = 0;
+ 		alg_data->last = (i == num - 1);
+ 
+-		dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __FUNCTION__,
++		dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __func__,
+ 			alg_data->mif.mode,
+ 			alg_data->mif.len);
+ 
+@@ -498,7 +498,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ 		if (!(rc = alg_data->mif.ret))
+ 			completed++;
+ 		dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n",
+-			__FUNCTION__, rc);
++			__func__, rc);
+ 
+ 		/* Clear TDI and AFI bits in case they are set. */
+ 		if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
+@@ -522,7 +522,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ 	alg_data->mif.len = 0;
+ 
+ 	dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n",
+-		__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++		__func__, ioread32(I2C_REG_STS(alg_data)));
+ 
+ 	if (completed != num)
+ 		return ((rc < 0) ? rc : -EREMOTEIO);
+@@ -563,7 +563,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
+ 
+ 	if (!i2c_pnx || !i2c_pnx->adapter) {
+ 		dev_err(&pdev->dev, "%s: no platform data supplied\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		ret = -EINVAL;
+ 		goto out;
+ 	}
+@@ -697,6 +697,7 @@ static void __exit i2c_adap_pnx_exit(void)
+ MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source at mvista.com>");
+ MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pnx-i2c");
+ 
+ /* We need to make sure I2C is initialized before USB */
+ subsys_initcall(i2c_adap_pnx_init);
+diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
+index 7813127..22f6d5c 100644
+--- a/drivers/i2c/busses/i2c-powermac.c
++++ b/drivers/i2c/busses/i2c-powermac.c
+@@ -263,6 +263,9 @@ static int __devexit i2c_powermac_probe(struct platform_device *dev)
+ }
+ 
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:i2c-powermac");
++
+ static struct platform_driver i2c_powermac_driver = {
+ 	.probe = i2c_powermac_probe,
+ 	.remove = __devexit_p(i2c_powermac_remove),
+diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
+index 2d2087a..eb69fba 100644
+--- a/drivers/i2c/busses/i2c-pxa.c
++++ b/drivers/i2c/busses/i2c-pxa.c
+@@ -39,6 +39,7 @@
+ #include <asm/io.h>
+ #include <asm/arch/i2c.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ 
+ struct pxa_i2c {
+ 	spinlock_t		lock;
+@@ -154,7 +155,7 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
+ 		readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
+ }
+ 
+-#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
++#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __func__)
+ #else
+ #define i2c_debug	0
+ 
+@@ -1131,6 +1132,7 @@ static void __exit i2c_adap_pxa_exit(void)
+ }
+ 
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pxa2xx-i2c");
+ 
+ module_init(i2c_adap_pxa_init);
+ module_exit(i2c_adap_pxa_exit);
+diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
+index c44ada5..1305ef1 100644
+--- a/drivers/i2c/busses/i2c-s3c2410.c
++++ b/drivers/i2c/busses/i2c-s3c2410.c
+@@ -276,12 +276,12 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
+ 	switch (i2c->state) {
+ 
+ 	case STATE_IDLE:
+-		dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __FUNCTION__);
++		dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__);
+ 		goto out;
+ 		break;
+ 
+ 	case STATE_STOP:
+-		dev_err(i2c->dev, "%s: called in STATE_STOP\n", __FUNCTION__);
++		dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
+ 		s3c24xx_i2c_disable_irq(i2c);		
+ 		goto out_ack;
+ 
+@@ -948,3 +948,4 @@ module_exit(i2c_adap_s3c_exit);
+ MODULE_DESCRIPTION("S3C24XX I2C Bus driver");
+ MODULE_AUTHOR("Ben Dooks, <ben at simtec.co.uk>");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:s3c2410-i2c");
+diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
+new file mode 100644
+index 0000000..5e0e254
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-sh7760.c
+@@ -0,0 +1,577 @@
++/*
++ * I2C bus driver for the SH7760 I2C Interfaces.
++ *
++ * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau at msc-ge.com>
++ *
++ * licensed under the terms outlined in the file COPYING.
++ *
++ */
++
++#include <linux/completion.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/i2c.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#include <asm/clock.h>
++#include <asm/i2c-sh7760.h>
++#include <asm/io.h>
++
++/* register offsets */
++#define I2CSCR		0x0		/* slave ctrl		*/
++#define I2CMCR		0x4		/* master ctrl		*/
++#define I2CSSR		0x8		/* slave status		*/
++#define I2CMSR		0xC		/* master status	*/
++#define I2CSIER		0x10		/* slave irq enable	*/
++#define I2CMIER		0x14		/* master irq enable	*/
++#define I2CCCR		0x18		/* clock dividers	*/
++#define I2CSAR		0x1c		/* slave address	*/
++#define I2CMAR		0x20		/* master address	*/
++#define I2CRXTX		0x24		/* data port		*/
++#define I2CFCR		0x28		/* fifo control		*/
++#define I2CFSR		0x2C		/* fifo status		*/
++#define I2CFIER		0x30		/* fifo irq enable	*/
++#define I2CRFDR		0x34		/* rx fifo count	*/
++#define I2CTFDR		0x38		/* tx fifo count	*/
++
++#define REGSIZE		0x3C
++
++#define MCR_MDBS	0x80		/* non-fifo mode switch	*/
++#define MCR_FSCL	0x40		/* override SCL pin	*/
++#define MCR_FSDA	0x20		/* override SDA pin	*/
++#define MCR_OBPC	0x10		/* override pins	*/
++#define MCR_MIE		0x08		/* master if enable	*/
++#define MCR_TSBE	0x04
++#define MCR_FSB		0x02		/* force stop bit	*/
++#define MCR_ESG		0x01		/* en startbit gen.	*/
++
++#define MSR_MNR		0x40		/* nack received	*/
++#define MSR_MAL		0x20		/* arbitration lost	*/
++#define MSR_MST		0x10		/* sent a stop		*/
++#define MSR_MDE		0x08
++#define MSR_MDT		0x04
++#define MSR_MDR		0x02
++#define MSR_MAT		0x01		/* slave addr xfer done	*/
++
++#define MIE_MNRE	0x40		/* nack irq en		*/
++#define MIE_MALE	0x20		/* arblos irq en	*/
++#define MIE_MSTE	0x10		/* stop irq en		*/
++#define MIE_MDEE	0x08
++#define MIE_MDTE	0x04
++#define MIE_MDRE	0x02
++#define MIE_MATE	0x01		/* address sent irq en	*/
++
++#define FCR_RFRST	0x02		/* reset rx fifo	*/
++#define FCR_TFRST	0x01		/* reset tx fifo	*/
++
++#define FSR_TEND	0x04		/* last byte sent	*/
++#define FSR_RDF		0x02		/* rx fifo trigger	*/
++#define FSR_TDFE	0x01		/* tx fifo empty	*/
++
++#define FIER_TEIE	0x04		/* tx fifo empty irq en	*/
++#define FIER_RXIE	0x02		/* rx fifo trig irq en	*/
++#define FIER_TXIE	0x01		/* tx fifo trig irq en	*/
++
++#define FIFO_SIZE	16
++
++struct cami2c {
++	void __iomem *iobase;
++	struct i2c_adapter adap;
++
++	/* message processing */
++	struct i2c_msg	*msg;
++#define IDF_SEND	1
++#define IDF_RECV	2
++#define IDF_STOP	4
++	int		flags;
++
++#define IDS_DONE	1
++#define IDS_ARBLOST	2
++#define IDS_NACK	4
++	int		status;
++	struct completion xfer_done;
++
++	int irq;
++	struct resource *ioarea;
++};
++
++static inline void OUT32(struct cami2c *cam, int reg, unsigned long val)
++{
++	ctrl_outl(val, (unsigned long)cam->iobase + reg);
++}
++
++static inline unsigned long IN32(struct cami2c *cam, int reg)
++{
++	return ctrl_inl((unsigned long)cam->iobase + reg);
++}
++
++static irqreturn_t sh7760_i2c_irq(int irq, void *ptr)
++{
++	struct cami2c *id = ptr;
++	struct i2c_msg *msg = id->msg;
++	char *data = msg->buf;
++	unsigned long msr, fsr, fier, len;
++
++	msr = IN32(id, I2CMSR);
++	fsr = IN32(id, I2CFSR);
++
++	/* arbitration lost */
++	if (msr & MSR_MAL) {
++		OUT32(id, I2CMCR, 0);
++		OUT32(id, I2CSCR, 0);
++		OUT32(id, I2CSAR, 0);
++		id->status |= IDS_DONE | IDS_ARBLOST;
++		goto out;
++	}
++
++	if (msr & MSR_MNR) {
++		/* NACK handling is very screwed up.  After receiving a
++		 * NAK IRQ one has to wait a bit  before writing to any
++		 * registers, or the ctl will lock up. After that delay
++		 * do a normal i2c stop. Then wait at least 1 ms before
++		 * attempting another transfer or ctl will stop working
++		 */
++		udelay(100);	/* wait or risk ctl hang */
++		OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++		OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
++		OUT32(id, I2CFIER, 0);
++		OUT32(id, I2CMIER, MIE_MSTE);
++		OUT32(id, I2CSCR, 0);
++		OUT32(id, I2CSAR, 0);
++		id->status |= IDS_NACK;
++		msr &= ~MSR_MAT;
++		fsr = 0;
++		/* In some cases the MST bit is also set. */
++	}
++
++	/* i2c-stop was sent */
++	if (msr & MSR_MST) {
++		id->status |= IDS_DONE;
++		goto out;
++	}
++
++	/* i2c slave addr was sent; set to "normal" operation */
++	if (msr & MSR_MAT)
++		OUT32(id, I2CMCR, MCR_MIE);
++
++	fier = IN32(id, I2CFIER);
++
++	if (fsr & FSR_RDF) {
++		len = IN32(id, I2CRFDR);
++		if (msg->len <= len) {
++			if (id->flags & IDF_STOP) {
++				OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
++				OUT32(id, I2CFIER, 0);
++				/* manual says: wait >= 0.5 SCL times */
++				udelay(5);
++				/* next int should be MST */
++			} else {
++				id->status |= IDS_DONE;
++				/* keep the RDF bit: ctrl holds SCL low
++				 * until the setup for the next i2c_msg
++				 * clears this bit.
++				 */
++				fsr &= ~FSR_RDF;
++			}
++		}
++		while (msg->len && len) {
++			*data++ = IN32(id, I2CRXTX);
++			msg->len--;
++			len--;
++		}
++
++		if (msg->len) {
++			len = (msg->len >= FIFO_SIZE) ? FIFO_SIZE - 1
++						      : msg->len - 1;
++
++			OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xf) << 4));
++		}
++
++	} else if (id->flags & IDF_SEND) {
++		if ((fsr & FSR_TEND) && (msg->len < 1)) {
++			if (id->flags & IDF_STOP) {
++				OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
++			} else {
++				id->status |= IDS_DONE;
++				/* keep the TEND bit: ctl holds SCL low
++				 * until the setup for the next i2c_msg
++				 * clears this bit.
++				 */
++				fsr &= ~FSR_TEND;
++			}
++		}
++		if (fsr & FSR_TDFE) {
++			while (msg->len && (IN32(id, I2CTFDR) < FIFO_SIZE)) {
++				OUT32(id, I2CRXTX, *data++);
++				msg->len--;
++			}
++
++			if (msg->len < 1) {
++				fier &= ~FIER_TXIE;
++				OUT32(id, I2CFIER, fier);
++			} else {
++				len = (msg->len >= FIFO_SIZE) ? 2 : 0;
++				OUT32(id, I2CFCR,
++					  FCR_RFRST | ((len & 3) << 2));
++			}
++		}
++	}
++out:
++	if (id->status & IDS_DONE) {
++		OUT32(id, I2CMIER, 0);
++		OUT32(id, I2CFIER, 0);
++		id->msg = NULL;
++		complete(&id->xfer_done);
++	}
++	/* clear status flags and ctrl resumes work */
++	OUT32(id, I2CMSR, ~msr);
++	OUT32(id, I2CFSR, ~fsr);
++	OUT32(id, I2CSSR, 0);
++
++	return IRQ_HANDLED;
++}
++
++
++/* prepare and start a master receive operation */
++static void sh7760_i2c_mrecv(struct cami2c *id)
++{
++	int len;
++
++	id->flags |= IDF_RECV;
++
++	/* set the slave addr reg; otherwise rcv wont work! */
++	OUT32(id, I2CSAR, 0xfe);
++	OUT32(id, I2CMAR, (id->msg->addr << 1) | 1);
++
++	/* adjust rx fifo trigger */
++	if (id->msg->len >= FIFO_SIZE)
++		len = FIFO_SIZE - 1;	/* trigger at fifo full */
++	else
++		len = id->msg->len - 1;	/* trigger before all received */
++
++	OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++	OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xF) << 4));
++
++	OUT32(id, I2CMSR, 0);
++	OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
++	OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
++	OUT32(id, I2CFIER, FIER_RXIE);
++}
++
++/* prepare and start a master send operation */
++static void sh7760_i2c_msend(struct cami2c *id)
++{
++	int len;
++
++	id->flags |= IDF_SEND;
++
++	/* set the slave addr reg; otherwise xmit wont work! */
++	OUT32(id, I2CSAR, 0xfe);
++	OUT32(id, I2CMAR, (id->msg->addr << 1) | 0);
++
++	/* adjust tx fifo trigger */
++	if (id->msg->len >= FIFO_SIZE)
++		len = 2;	/* trig: 2 bytes left in TX fifo */
++	else
++		len = 0;	/* trig: 8 bytes left in TX fifo */
++
++	OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++	OUT32(id, I2CFCR, FCR_RFRST | ((len & 3) << 2));
++
++	while (id->msg->len && IN32(id, I2CTFDR) < FIFO_SIZE) {
++		OUT32(id, I2CRXTX, *(id->msg->buf));
++		(id->msg->len)--;
++		(id->msg->buf)++;
++	}
++
++	OUT32(id, I2CMSR, 0);
++	OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
++	OUT32(id, I2CFSR, 0);
++	OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
++	OUT32(id, I2CFIER, FIER_TEIE | (id->msg->len ? FIER_TXIE : 0));
++}
++
++static inline int sh7760_i2c_busy_check(struct cami2c *id)
++{
++	return (IN32(id, I2CMCR) & MCR_FSDA);
++}
++
++static int sh7760_i2c_master_xfer(struct i2c_adapter *adap,
++				  struct i2c_msg *msgs,
++				  int num)
++{
++	struct cami2c *id = adap->algo_data;
++	int i, retr;
++
++	if (sh7760_i2c_busy_check(id)) {
++		dev_err(&adap->dev, "sh7760-i2c%d: bus busy!\n", adap->nr);
++		return -EBUSY;
++	}
++
++	i = 0;
++	while (i < num) {
++		retr = adap->retries;
++retry:
++		id->flags = ((i == (num-1)) ? IDF_STOP : 0);
++		id->status = 0;
++		id->msg = msgs;
++		init_completion(&id->xfer_done);
++
++		if (msgs->flags & I2C_M_RD)
++			sh7760_i2c_mrecv(id);
++		else
++			sh7760_i2c_msend(id);
++
++		wait_for_completion(&id->xfer_done);
++
++		if (id->status == 0) {
++			num = -EIO;
++			break;
++		}
++
++		if (id->status & IDS_NACK) {
++			/* wait a bit or i2c module stops working */
++			mdelay(1);
++			num = -EREMOTEIO;
++			break;
++		}
++
++		if (id->status & IDS_ARBLOST) {
++			if (retr--) {
++				mdelay(2);
++				goto retry;
++			}
++			num = -EREMOTEIO;
++			break;
++		}
++
++		msgs++;
++		i++;
++	}
++
++	id->msg = NULL;
++	id->flags = 0;
++	id->status = 0;
++
++	OUT32(id, I2CMCR, 0);
++	OUT32(id, I2CMSR, 0);
++	OUT32(id, I2CMIER, 0);
++	OUT32(id, I2CFIER, 0);
++
++	/* reset slave module registers too: master mode enables slave
++	 * module for receive ops (ack, data). Without this reset,
++	 * eternal bus activity might be reported after NACK / ARBLOST.
++	 */
++	OUT32(id, I2CSCR, 0);
++	OUT32(id, I2CSAR, 0);
++	OUT32(id, I2CSSR, 0);
++
++	return num;
++}
++
++static u32 sh7760_i2c_func(struct i2c_adapter *adap)
++{
++	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
++}
++
++static const struct i2c_algorithm sh7760_i2c_algo = {
++	.master_xfer	= sh7760_i2c_master_xfer,
++	.functionality	= sh7760_i2c_func,
++};
++
++/* calculate CCR register setting for a desired scl clock.  SCL clock is
++ * derived from I2C module clock  (iclk)  which in turn is derived from
++ * peripheral module clock (mclk, usually around 33MHz):
++ * iclk = mclk/(CDF + 1).  iclk must be < 20MHz.
++ * scl = iclk/(SCGD*8 + 20).
++ */
++static int __devinit calc_CCR(unsigned long scl_hz)
++{
++	struct clk *mclk;
++	unsigned long mck, m1, dff, odff, iclk;
++	signed char cdf, cdfm;
++	int scgd, scgdm, scgds;
++
++	mclk = clk_get(NULL, "module_clk");
++	if (IS_ERR(mclk)) {
++		return PTR_ERR(mclk);
++	} else {
++		mck = mclk->rate;
++		clk_put(mclk);
++	}
++
++	odff = scl_hz;
++	scgdm = cdfm = m1 = 0;
++	for (cdf = 3; cdf >= 0; cdf--) {
++		iclk = mck / (1 + cdf);
++		if (iclk >= 20000000)
++			continue;
++		scgds = ((iclk / scl_hz) - 20) >> 3;
++		for (scgd = scgds; (scgd < 63) && scgd <= scgds + 1; scgd++) {
++			m1 = iclk / (20 + (scgd << 3));
++			dff = abs(scl_hz - m1);
++			if (dff < odff) {
++				odff = dff;
++				cdfm = cdf;
++				scgdm = scgd;
++			}
++		}
++	}
++	/* fail if more than 25% off of requested SCL */
++	if (odff > (scl_hz >> 2))
++		return -EINVAL;
++
++	/* create a CCR register value */
++	return ((scgdm << 2) | cdfm);
++}
++
++static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
++{
++	struct sh7760_i2c_platdata *pd;
++	struct resource *res;
++	struct cami2c *id;
++	int ret;
++
++	pd = pdev->dev.platform_data;
++	if (!pd) {
++		dev_err(&pdev->dev, "no platform_data!\n");
++		ret = -ENODEV;
++		goto out0;
++	}
++
++	id = kzalloc(sizeof(struct cami2c), GFP_KERNEL);
++	if (!id) {
++		dev_err(&pdev->dev, "no mem for private data\n");
++		ret = -ENOMEM;
++		goto out0;
++	}
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!res) {
++		dev_err(&pdev->dev, "no mmio resources\n");
++		ret = -ENODEV;
++		goto out1;
++	}
++
++	id->ioarea = request_mem_region(res->start, REGSIZE, pdev->name);
++	if (!id->ioarea) {
++		dev_err(&pdev->dev, "mmio already reserved\n");
++		ret = -EBUSY;
++		goto out1;
++	}
++
++	id->iobase = ioremap(res->start, REGSIZE);
++	if (!id->iobase) {
++		dev_err(&pdev->dev, "cannot ioremap\n");
++		ret = -ENODEV;
++		goto out2;
++	}
++
++	id->irq = platform_get_irq(pdev, 0);
++
++	id->adap.nr = pdev->id;
++	id->adap.algo = &sh7760_i2c_algo;
++	id->adap.class = I2C_CLASS_ALL;
++	id->adap.retries = 3;
++	id->adap.algo_data = id;
++	id->adap.dev.parent = &pdev->dev;
++	snprintf(id->adap.name, sizeof(id->adap.name),
++		"SH7760 I2C at %08lx", (unsigned long)res->start);
++
++	OUT32(id, I2CMCR, 0);
++	OUT32(id, I2CMSR, 0);
++	OUT32(id, I2CMIER, 0);
++	OUT32(id, I2CMAR, 0);
++	OUT32(id, I2CSIER, 0);
++	OUT32(id, I2CSAR, 0);
++	OUT32(id, I2CSCR, 0);
++	OUT32(id, I2CSSR, 0);
++	OUT32(id, I2CFIER, 0);
++	OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++	OUT32(id, I2CFSR, 0);
++
++	ret = calc_CCR(pd->speed_khz * 1000);
++	if (ret < 0) {
++		dev_err(&pdev->dev, "invalid SCL clock: %dkHz\n",
++			pd->speed_khz);
++		goto out3;
++	}
++	OUT32(id, I2CCCR, ret);
++
++	if (request_irq(id->irq, sh7760_i2c_irq, IRQF_DISABLED,
++			SH7760_I2C_DEVNAME, id)) {
++		dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
++		ret = -EBUSY;
++		goto out3;
++	}
++
++	ret = i2c_add_numbered_adapter(&id->adap);
++	if (ret < 0) {
++		dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
++		goto out4;
++	}
++
++	platform_set_drvdata(pdev, id);
++
++	dev_info(&pdev->dev, "%d kHz mmio %08x irq %d\n",
++		 pd->speed_khz, res->start, id->irq);
++
++	return 0;
++
++out4:
++	free_irq(id->irq, id);
++out3:
++	iounmap(id->iobase);
++out2:
++	release_resource(id->ioarea);
++	kfree(id->ioarea);
++out1:
++	kfree(id);
++out0:
++	return ret;
++}
++
++static int __devexit sh7760_i2c_remove(struct platform_device *pdev)
++{
++	struct cami2c *id = platform_get_drvdata(pdev);
++
++	i2c_del_adapter(&id->adap);
++	free_irq(id->irq, id);
++	iounmap(id->iobase);
++	release_resource(id->ioarea);
++	kfree(id->ioarea);
++	kfree(id);
++	platform_set_drvdata(pdev, NULL);
++
++	return 0;
++}
++
++static struct platform_driver sh7760_i2c_drv = {
++	.driver	= {
++		.name	= SH7760_I2C_DEVNAME,
++		.owner	= THIS_MODULE,
++	},
++	.probe		= sh7760_i2c_probe,
++	.remove		= __devexit_p(sh7760_i2c_remove),
++};
++
++static int __init sh7760_i2c_init(void)
++{
++	return platform_driver_register(&sh7760_i2c_drv);
++}
++
++static void __exit sh7760_i2c_exit(void)
++{
++	platform_driver_unregister(&sh7760_i2c_drv);
++}
++
++module_init(sh7760_i2c_init);
++module_exit(sh7760_i2c_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SH7760 I2C bus driver");
++MODULE_AUTHOR("Manuel Lauss <mano at roarinelk.homelinux.net>");
+diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
+new file mode 100644
+index 0000000..840e634
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-sh_mobile.c
+@@ -0,0 +1,500 @@
++/*
++ * SuperH Mobile I2C Controller
++ *
++ * Copyright (C) 2008 Magnus Damm
++ *
++ * Portions of the code based on out-of-tree driver i2c-sh7343.c
++ * Copyright (c) 2006 Carlos Munoz <carlos at kenati.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; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++
++enum sh_mobile_i2c_op {
++	OP_START = 0,
++	OP_TX_ONLY,
++	OP_TX_STOP,
++	OP_TX_TO_RX,
++	OP_RX_ONLY,
++	OP_RX_STOP,
++};
++
++struct sh_mobile_i2c_data {
++	struct device *dev;
++	void __iomem *reg;
++	struct i2c_adapter adap;
++
++	struct clk *clk;
++	u_int8_t iccl;
++	u_int8_t icch;
++
++	spinlock_t lock;
++	wait_queue_head_t wait;
++	struct i2c_msg *msg;
++	int pos;
++	int sr;
++};
++
++#define NORMAL_SPEED		100000 /* FAST_SPEED 400000 */
++
++/* Register offsets */
++#define ICDR(pd)		(pd->reg + 0x00)
++#define ICCR(pd)		(pd->reg + 0x04)
++#define ICSR(pd)		(pd->reg + 0x08)
++#define ICIC(pd)		(pd->reg + 0x0c)
++#define ICCL(pd)		(pd->reg + 0x10)
++#define ICCH(pd)		(pd->reg + 0x14)
++
++/* Register bits */
++#define ICCR_ICE		0x80
++#define ICCR_RACK		0x40
++#define ICCR_TRS		0x10
++#define ICCR_BBSY		0x04
++#define ICCR_SCP		0x01
++
++#define ICSR_SCLM		0x80
++#define ICSR_SDAM		0x40
++#define SW_DONE			0x20
++#define ICSR_BUSY		0x10
++#define ICSR_AL			0x08
++#define ICSR_TACK		0x04
++#define ICSR_WAIT		0x02
++#define ICSR_DTE		0x01
++
++#define ICIC_ALE		0x08
++#define ICIC_TACKE		0x04
++#define ICIC_WAITE		0x02
++#define ICIC_DTEE		0x01
++
++static void activate_ch(struct sh_mobile_i2c_data *pd)
++{
++	/* Make sure the clock is enabled */
++	clk_enable(pd->clk);
++
++	/* Enable channel and configure rx ack */
++	iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
++
++	/* Mask all interrupts */
++	iowrite8(0, ICIC(pd));
++
++	/* Set the clock */
++	iowrite8(pd->iccl, ICCL(pd));
++	iowrite8(pd->icch, ICCH(pd));
++}
++
++static void deactivate_ch(struct sh_mobile_i2c_data *pd)
++{
++	/* Clear/disable interrupts */
++	iowrite8(0, ICSR(pd));
++	iowrite8(0, ICIC(pd));
++
++	/* Disable channel */
++	iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
++
++	/* Disable clock */
++	clk_disable(pd->clk);
++}
++
++static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
++			    enum sh_mobile_i2c_op op, unsigned char data)
++{
++	unsigned char ret = 0;
++	unsigned long flags;
++
++	dev_dbg(pd->dev, "op %d, data in 0x%02x\n", op, data);
++
++	spin_lock_irqsave(&pd->lock, flags);
++
++	switch (op) {
++	case OP_START:
++		iowrite8(0x94, ICCR(pd));
++		break;
++	case OP_TX_ONLY:
++		iowrite8(data, ICDR(pd));
++		break;
++	case OP_TX_STOP:
++		iowrite8(data, ICDR(pd));
++		iowrite8(0x90, ICCR(pd));
++		iowrite8(ICIC_ALE | ICIC_TACKE, ICIC(pd));
++		break;
++	case OP_TX_TO_RX:
++		iowrite8(data, ICDR(pd));
++		iowrite8(0x81, ICCR(pd));
++		break;
++	case OP_RX_ONLY:
++		ret = ioread8(ICDR(pd));
++		break;
++	case OP_RX_STOP:
++		ret = ioread8(ICDR(pd));
++		iowrite8(0xc0, ICCR(pd));
++		break;
++	}
++
++	spin_unlock_irqrestore(&pd->lock, flags);
++
++	dev_dbg(pd->dev, "op %d, data out 0x%02x\n", op, ret);
++	return ret;
++}
++
++static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
++{
++	struct platform_device *dev = dev_id;
++	struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++	struct i2c_msg *msg = pd->msg;
++	unsigned char data, sr;
++	int wakeup = 0;
++
++	sr = ioread8(ICSR(pd));
++	pd->sr |= sr;
++
++	dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
++	       (msg->flags & I2C_M_RD) ? "read" : "write",
++	       pd->pos, msg->len);
++
++	if (sr & (ICSR_AL | ICSR_TACK)) {
++		iowrite8(0, ICIC(pd)); /* disable interrupts */
++		wakeup = 1;
++		goto do_wakeup;
++	}
++
++	if (pd->pos == msg->len) {
++		i2c_op(pd, OP_RX_ONLY, 0);
++		wakeup = 1;
++		goto do_wakeup;
++	}
++
++	if (pd->pos == -1) {
++		data = (msg->addr & 0x7f) << 1;
++		data |= (msg->flags & I2C_M_RD) ? 1 : 0;
++	} else
++		data = msg->buf[pd->pos];
++
++	if ((pd->pos == -1) || !(msg->flags & I2C_M_RD)) {
++		if (msg->flags & I2C_M_RD)
++			i2c_op(pd, OP_TX_TO_RX, data);
++		else if (pd->pos == (msg->len - 1)) {
++			i2c_op(pd, OP_TX_STOP, data);
++			wakeup = 1;
++		} else
++			i2c_op(pd, OP_TX_ONLY, data);
++	} else {
++		if (pd->pos == (msg->len - 1))
++			data = i2c_op(pd, OP_RX_STOP, 0);
++		else
++			data = i2c_op(pd, OP_RX_ONLY, 0);
++
++		msg->buf[pd->pos] = data;
++	}
++	pd->pos++;
++
++ do_wakeup:
++	if (wakeup) {
++		pd->sr |= SW_DONE;
++		wake_up(&pd->wait);
++	}
++
++	return IRQ_HANDLED;
++}
++
++static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
++{
++	/* Initialize channel registers */
++	iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
++
++	/* Enable channel and configure rx ack */
++	iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
++
++	/* Set the clock */
++	iowrite8(pd->iccl, ICCL(pd));
++	iowrite8(pd->icch, ICCH(pd));
++
++	pd->msg = usr_msg;
++	pd->pos = -1;
++	pd->sr = 0;
++
++	/* Enable all interrupts except wait */
++	iowrite8(ioread8(ICIC(pd)) | ICIC_ALE | ICIC_TACKE | ICIC_DTEE,
++		 ICIC(pd));
++	return 0;
++}
++
++static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
++			      struct i2c_msg *msgs,
++			      int num)
++{
++	struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
++	struct i2c_msg	*msg;
++	int err = 0;
++	u_int8_t val;
++	int i, k, retry_count;
++
++	activate_ch(pd);
++
++	/* Process all messages */
++	for (i = 0; i < num; i++) {
++		msg = &msgs[i];
++
++		err = start_ch(pd, msg);
++		if (err)
++			break;
++
++		i2c_op(pd, OP_START, 0);
++
++		/* The interrupt handler takes care of the rest... */
++		k = wait_event_timeout(pd->wait,
++				       pd->sr & (ICSR_TACK | SW_DONE),
++				       5 * HZ);
++		if (!k)
++			dev_err(pd->dev, "Transfer request timed out\n");
++
++		retry_count = 10;
++again:
++		val = ioread8(ICSR(pd));
++
++		dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
++
++		if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
++			err = -EIO;
++			break;
++		}
++
++		/* the interrupt handler may wake us up before the
++		 * transfer is finished, so poll the hardware
++		 * until we're done.
++		 */
++
++		if (!(!(val & ICSR_BUSY) && (val & ICSR_SCLM) &&
++		      (val & ICSR_SDAM))) {
++			msleep(1);
++			if (retry_count--)
++				goto again;
++
++			err = -EIO;
++			dev_err(pd->dev, "Polling timed out\n");
++			break;
++		}
++	}
++
++	deactivate_ch(pd);
++
++	if (!err)
++		err = num;
++	return err;
++}
++
++static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter)
++{
++	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
++}
++
++static struct i2c_algorithm sh_mobile_i2c_algorithm = {
++	.functionality	= sh_mobile_i2c_func,
++	.master_xfer	= sh_mobile_i2c_xfer,
++};
++
++static void sh_mobile_i2c_setup_channel(struct platform_device *dev)
++{
++	struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++	unsigned long peripheral_clk = clk_get_rate(pd->clk);
++	u_int32_t num;
++	u_int32_t denom;
++	u_int32_t tmp;
++
++	spin_lock_init(&pd->lock);
++	init_waitqueue_head(&pd->wait);
++
++	/* Calculate the value for iccl. From the data sheet:
++	 * iccl = (p clock / transfer rate) * (L / (L + H))
++	 * where L and H are the SCL low/high ratio (5/4 in this case).
++	 * We also round off the result.
++	 */
++	num = peripheral_clk * 5;
++	denom = NORMAL_SPEED * 9;
++	tmp = num * 10 / denom;
++	if (tmp % 10 >= 5)
++		pd->iccl = (u_int8_t)((num/denom) + 1);
++	else
++		pd->iccl = (u_int8_t)(num/denom);
++
++	/* Calculate the value for icch. From the data sheet:
++	   icch = (p clock / transfer rate) * (H / (L + H)) */
++	num = peripheral_clk * 4;
++	tmp = num * 10 / denom;
++	if (tmp % 10 >= 5)
++		pd->icch = (u_int8_t)((num/denom) + 1);
++	else
++		pd->icch = (u_int8_t)(num/denom);
++}
++
++static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
++{
++	struct resource *res;
++	int ret = -ENXIO;
++	int q, m;
++	int k = 0;
++	int n = 0;
++
++	while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
++		for (n = res->start; hook && n <= res->end; n++) {
++			if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
++					dev->dev.bus_id, dev))
++				goto rollback;
++		}
++		k++;
++	}
++
++	if (hook)
++		return k > 0 ? 0 : -ENOENT;
++
++	k--;
++	ret = 0;
++
++ rollback:
++	for (q = k; k >= 0; k--) {
++		for (m = n; m >= res->start; m--)
++			free_irq(m, dev);
++
++		res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1);
++		m = res->end;
++	}
++
++	return ret;
++}
++
++static int sh_mobile_i2c_probe(struct platform_device *dev)
++{
++	struct sh_mobile_i2c_data *pd;
++	struct i2c_adapter *adap;
++	struct resource *res;
++	int size;
++	int ret;
++
++	pd = kzalloc(sizeof(struct sh_mobile_i2c_data), GFP_KERNEL);
++	if (pd == NULL) {
++		dev_err(&dev->dev, "cannot allocate private data\n");
++		return -ENOMEM;
++	}
++
++	pd->clk = clk_get(&dev->dev, "peripheral_clk");
++	if (IS_ERR(pd->clk)) {
++		dev_err(&dev->dev, "cannot get peripheral clock\n");
++		ret = PTR_ERR(pd->clk);
++		goto err;
++	}
++
++	ret = sh_mobile_i2c_hook_irqs(dev, 1);
++	if (ret) {
++		dev_err(&dev->dev, "cannot request IRQ\n");
++		goto err_clk;
++	}
++
++	pd->dev = &dev->dev;
++	platform_set_drvdata(dev, pd);
++
++	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
++	if (res == NULL) {
++		dev_err(&dev->dev, "cannot find IO resource\n");
++		ret = -ENOENT;
++		goto err_irq;
++	}
++
++	size = (res->end - res->start) + 1;
++
++	pd->reg = ioremap(res->start, size);
++	if (pd->reg == NULL) {
++		dev_err(&dev->dev, "cannot map IO\n");
++		ret = -ENXIO;
++		goto err_irq;
++	}
++
++	/* setup the private data */
++	adap = &pd->adap;
++	i2c_set_adapdata(adap, pd);
++
++	adap->owner = THIS_MODULE;
++	adap->algo = &sh_mobile_i2c_algorithm;
++	adap->dev.parent = &dev->dev;
++	adap->retries = 5;
++	adap->nr = dev->id;
++
++	strlcpy(adap->name, dev->name, sizeof(adap->name));
++
++	sh_mobile_i2c_setup_channel(dev);
++
++	ret = i2c_add_numbered_adapter(adap);
++	if (ret < 0) {
++		dev_err(&dev->dev, "cannot add numbered adapter\n");
++		goto err_all;
++	}
++
++	return 0;
++
++ err_all:
++	iounmap(pd->reg);
++ err_irq:
++	sh_mobile_i2c_hook_irqs(dev, 0);
++ err_clk:
++	clk_put(pd->clk);
++ err:
++	kfree(pd);
++	return ret;
++}
++
++static int sh_mobile_i2c_remove(struct platform_device *dev)
++{
++	struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++
++	i2c_del_adapter(&pd->adap);
++	iounmap(pd->reg);
++	sh_mobile_i2c_hook_irqs(dev, 0);
++	clk_put(pd->clk);
++	kfree(pd);
++	return 0;
++}
++
++static struct platform_driver sh_mobile_i2c_driver = {
++	.driver		= {
++		.name		= "i2c-sh_mobile",
++		.owner		= THIS_MODULE,
++	},
++	.probe		= sh_mobile_i2c_probe,
++	.remove		= sh_mobile_i2c_remove,
++};
++
++static int __init sh_mobile_i2c_adap_init(void)
++{
++	return platform_driver_register(&sh_mobile_i2c_driver);
++}
++
++static void __exit sh_mobile_i2c_adap_exit(void)
++{
++	platform_driver_unregister(&sh_mobile_i2c_driver);
++}
++
++module_init(sh_mobile_i2c_adap_init);
++module_exit(sh_mobile_i2c_adap_exit);
++
++MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
++MODULE_AUTHOR("Magnus Damm");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
+index 10af8d3..042fda2 100644
+--- a/drivers/i2c/busses/i2c-simtec.c
++++ b/drivers/i2c/busses/i2c-simtec.c
+@@ -159,6 +159,9 @@ static int simtec_i2c_remove(struct platform_device *dev)
+ 
+ /* device driver */
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:simtec-i2c");
++
+ static struct platform_driver simtec_i2c_driver = {
+ 	.driver		= {
+ 		.name		= "simtec-i2c",
+diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c
+index 081d957..4678bab 100644
+--- a/drivers/i2c/busses/i2c-versatile.c
++++ b/drivers/i2c/busses/i2c-versatile.c
+@@ -151,3 +151,4 @@ module_exit(i2c_versatile_exit);
+ 
+ MODULE_DESCRIPTION("ARM Versatile I2C bus driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:versatile-i2c");
+diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
+index f5e7a70..61abe0f 100644
+--- a/drivers/i2c/busses/scx200_acb.c
++++ b/drivers/i2c/busses/scx200_acb.c
+@@ -527,7 +527,7 @@ static int __init scx200_create_isa(const char *text, unsigned long base,
+ 	if (iface == NULL)
+ 		return -ENOMEM;
+ 
+-	if (request_region(base, 8, iface->adapter.name) == 0) {
++	if (!request_region(base, 8, iface->adapter.name)) {
+ 		printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
+ 		       base, base + 8 - 1);
+ 		rc = -EBUSY;
+diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
+index b21593f..2da2edf 100644
+--- a/drivers/i2c/chips/Kconfig
++++ b/drivers/i2c/chips/Kconfig
+@@ -93,6 +93,7 @@ config ISP1301_OMAP
+ 
+ config TPS65010
+ 	tristate "TPS6501x Power Management chips"
++	depends on HAVE_GPIO_LIB
+ 	default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
+ 	help
+ 	  If you say yes here you get support for the TPS6501x series of
+diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
+index 2a31601..b1b45dd 100644
+--- a/drivers/i2c/chips/isp1301_omap.c
++++ b/drivers/i2c/chips/isp1301_omap.c
+@@ -658,7 +658,7 @@ pulldown:
+ 		OTG_CTRL_REG |= OTG_PULLUP;
+ 	}
+ 
+-	check_state(isp, __FUNCTION__);
++	check_state(isp, __func__);
+ 	dump_regs(isp, "otg->isp1301");
+ }
+ 
+@@ -782,7 +782,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
+ 		if (otg_ctrl & OTG_DRIVER_SEL) {
+ 			switch (isp->otg.state) {
+ 			case OTG_STATE_A_IDLE:
+-				b_idle(isp, __FUNCTION__);
++				b_idle(isp, __func__);
+ 				break;
+ 			default:
+ 				break;
+@@ -826,7 +826,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
+ 						isp->otg.host->otg_port);
+ 	}
+ 
+-	check_state(isp, __FUNCTION__);
++	check_state(isp, __func__);
+ 	return ret;
+ }
+ 
+@@ -837,7 +837,7 @@ static int otg_init(struct isp1301 *isp)
+ 	if (!otg_dev)
+ 		return -ENODEV;
+ 
+-	dump_regs(isp, __FUNCTION__);
++	dump_regs(isp, __func__);
+ 	/* some of these values are board-specific... */
+ 	OTG_SYSCON_2_REG |= OTG_EN
+ 		/* for B-device: */
+@@ -853,9 +853,9 @@ static int otg_init(struct isp1301 *isp)
+ 	update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
+ 	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+ 
+-	check_state(isp, __FUNCTION__);
++	check_state(isp, __func__);
+ 	pr_debug("otg: %s, %s %06x\n",
+-			state_name(isp), __FUNCTION__, OTG_CTRL_REG);
++			state_name(isp), __func__, OTG_CTRL_REG);
+ 
+ 	OTG_IRQ_EN_REG = DRIVER_SWITCH | OPRT_CHG
+ 			| B_SRP_TMROUT | B_HNP_FAIL
+@@ -1041,11 +1041,11 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)
+ 						OTG1_DP_PULLDOWN);
+ 			isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
+ 						OTG1_DP_PULLUP);
+-			dump_regs(isp, __FUNCTION__);
++			dump_regs(isp, __func__);
+ #endif
+ 			/* FALLTHROUGH */
+ 		case OTG_STATE_B_SRP_INIT:
+-			b_idle(isp, __FUNCTION__);
++			b_idle(isp, __func__);
+ 			OTG_CTRL_REG &= OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+ 			/* FALLTHROUGH */
+ 		case OTG_STATE_B_IDLE:
+@@ -1077,7 +1077,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)
+ 	 */
+ 	update_otg1(isp, isp_stat);
+ 	update_otg2(isp, isp_bstat);
+-	check_state(isp, __FUNCTION__);
++	check_state(isp, __func__);
+ #endif
+ 
+ 	dump_regs(isp, "isp1301->otg");
+@@ -1310,7 +1310,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+ 	 */
+ 	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV);
+ 
+-	dump_regs(isp, __FUNCTION__);
++	dump_regs(isp, __func__);
+ 
+ 	return 0;
+ 
+@@ -1365,7 +1365,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
+ 	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+ 		INTR_VBUS_VLD);
+ 	dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
+-	dump_regs(isp, __FUNCTION__);
++	dump_regs(isp, __func__);
+ 
+ 	/* If this has a Mini-AB connector, this mode is highly
+ 	 * nonstandard ... but can be handy for testing, so long
+@@ -1416,7 +1416,7 @@ isp1301_start_srp(struct otg_transceiver *dev)
+ 
+ 	pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), OTG_CTRL_REG);
+ #ifdef	CONFIG_USB_OTG
+-	check_state(isp, __FUNCTION__);
++	check_state(isp, __func__);
+ #endif
+ 	return 0;
+ }
+@@ -1463,7 +1463,7 @@ isp1301_start_hnp(struct otg_transceiver *dev)
+ 	}
+ 	pr_debug("otg: HNP %s, %06x ...\n",
+ 		state_name(isp), OTG_CTRL_REG);
+-	check_state(isp, __FUNCTION__);
++	check_state(isp, __func__);
+ 	return 0;
+ #else
+ 	/* srp-only */
+@@ -1601,7 +1601,7 @@ fail2:
+ 	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+ #endif
+ 
+-	dump_regs(isp, __FUNCTION__);
++	dump_regs(isp, __func__);
+ 
+ #ifdef	VERBOSE
+ 	mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
+diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
+index 4154a91..b67f69c 100644
+--- a/drivers/i2c/chips/tps65010.c
++++ b/drivers/i2c/chips/tps65010.c
+@@ -30,9 +30,13 @@
+ #include <linux/debugfs.h>
+ #include <linux/seq_file.h>
+ #include <linux/mutex.h>
++#include <linux/platform_device.h>
+ 
+ #include <linux/i2c/tps65010.h>
+ 
++#include <asm/gpio.h>
++
++
+ /*-------------------------------------------------------------------------*/
+ 
+ #define	DRIVER_VERSION	"2 May 2005"
+@@ -84,7 +88,9 @@ struct tps65010 {
+ 	u8			chgstatus, regstatus, chgconf;
+ 	u8			nmask1, nmask2;
+ 
+-	/* not currently tracking GPIO state */
++	u8			outmask;
++	struct gpio_chip	chip;
++	struct platform_device	*leds;
+ };
+ 
+ #define	POWER_POLL_DELAY	msecs_to_jiffies(5000)
+@@ -449,12 +455,72 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
++/* offsets 0..3 == GPIO1..GPIO4
++ * offsets 4..5 == LED1/nPG, LED2 (we set one of the non-BLINK modes)
++ */
++static void
++tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++	if (offset < 4)
++		tps65010_set_gpio_out_value(offset + 1, value);
++	else
++		tps65010_set_led(offset - 3, value ? ON : OFF);
++}
++
++static int
++tps65010_output(struct gpio_chip *chip, unsigned offset, int value)
++{
++	/* GPIOs may be input-only */
++	if (offset < 4) {
++		struct tps65010		*tps;
++
++		tps = container_of(chip, struct tps65010, chip);
++		if (!(tps->outmask & (1 << offset)))
++			return -EINVAL;
++		tps65010_set_gpio_out_value(offset + 1, value);
++	} else
++		tps65010_set_led(offset - 3, value ? ON : OFF);
++
++	return 0;
++}
++
++static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++	int			value;
++	struct tps65010		*tps;
++
++	tps = container_of(chip, struct tps65010, chip);
++
++	if (offset < 4) {
++		value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO);
++		if (value < 0)
++			return 0;
++		if (value & (1 << (offset + 4)))	/* output */
++			return !(value & (1 << offset));
++		else					/* input */
++			return (value & (1 << offset));
++	}
++
++	/* REVISIT we *could* report LED1/nPG and LED2 state ... */
++	return 0;
++}
++
++
++/*-------------------------------------------------------------------------*/
++
+ static struct tps65010 *the_tps;
+ 
+ static int __exit tps65010_remove(struct i2c_client *client)
+ {
+ 	struct tps65010		*tps = i2c_get_clientdata(client);
++	struct tps65010_board	*board = client->dev.platform_data;
+ 
++	if (board && board->teardown) {
++		int status = board->teardown(client, board->context);
++		if (status < 0)
++			dev_dbg(&client->dev, "board %s %s err %d\n",
++				"teardown", client->name, status);
++	}
+ 	if (client->irq > 0)
+ 		free_irq(client->irq, tps);
+ 	cancel_delayed_work(&tps->work);
+@@ -469,6 +535,7 @@ static int tps65010_probe(struct i2c_client *client)
+ {
+ 	struct tps65010		*tps;
+ 	int			status;
++	struct tps65010_board	*board = client->dev.platform_data;
+ 
+ 	if (the_tps) {
+ 		dev_dbg(&client->dev, "only one tps6501x chip allowed\n");
+@@ -577,6 +644,38 @@ static int tps65010_probe(struct i2c_client *client)
+ 
+ 	tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
+ 				tps, DEBUG_FOPS);
++
++	/* optionally register GPIOs */
++	if (board && board->base > 0) {
++		tps->outmask = board->outmask;
++
++		tps->chip.label = client->name;
++
++		tps->chip.set = tps65010_gpio_set;
++		tps->chip.direction_output = tps65010_output;
++
++		/* NOTE:  only partial support for inputs; nyet IRQs */
++		tps->chip.get = tps65010_gpio_get;
++
++		tps->chip.base = board->base;
++		tps->chip.ngpio = 6;
++		tps->chip.can_sleep = 1;
++
++		status = gpiochip_add(&tps->chip);
++		if (status < 0)
++			dev_err(&client->dev, "can't add gpiochip, err %d\n",
++					status);
++		else if (board->setup) {
++			status = board->setup(client, board->context);
++			if (status < 0) {
++				dev_dbg(&client->dev,
++					"board %s %s err %d\n",
++					"setup", client->name, status);
++				status = 0;
++			}
++		}
++	}
++
+ 	return 0;
+ fail1:
+ 	kfree(tps);
+diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
+index 8b645c6..6c7fa8d 100644
+--- a/drivers/i2c/i2c-core.c
++++ b/drivers/i2c/i2c-core.c
+@@ -35,8 +35,8 @@
+ #include <linux/completion.h>
+ #include <linux/hardirq.h>
+ #include <linux/irqflags.h>
++#include <linux/semaphore.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ 
+ #include "i2c-core.h"
+ 
+@@ -1506,7 +1506,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
+ 		read_write = I2C_SMBUS_READ;
+ 		if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
+ 			dev_err(&adapter->dev, "%s called with invalid "
+-				"block proc call size (%d)\n", __FUNCTION__,
++				"block proc call size (%d)\n", __func__,
+ 				data->block[0]);
+ 			return -1;
+ 		}
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index 393e679..d34c14c 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -200,16 +200,176 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
+ 	return device_for_each_child(&adapter->dev, &addr, i2cdev_check);
+ }
+ 
+-static int i2cdev_ioctl(struct inode *inode, struct file *file,
+-		unsigned int cmd, unsigned long arg)
++static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
++		unsigned long arg)
+ {
+-	struct i2c_client *client = (struct i2c_client *)file->private_data;
+ 	struct i2c_rdwr_ioctl_data rdwr_arg;
+-	struct i2c_smbus_ioctl_data data_arg;
+-	union i2c_smbus_data temp;
+ 	struct i2c_msg *rdwr_pa;
+ 	u8 __user **data_ptrs;
+-	int i,datasize,res;
++	int i, res;
++
++	if (copy_from_user(&rdwr_arg,
++			   (struct i2c_rdwr_ioctl_data __user *)arg,
++			   sizeof(rdwr_arg)))
++		return -EFAULT;
++
++	/* Put an arbitrary limit on the number of messages that can
++	 * be sent at once */
++	if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
++		return -EINVAL;
++
++	rdwr_pa = (struct i2c_msg *)
++		kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
++		GFP_KERNEL);
++	if (!rdwr_pa)
++		return -ENOMEM;
++
++	if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
++			   rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
++		kfree(rdwr_pa);
++		return -EFAULT;
++	}
++
++	data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
++	if (data_ptrs == NULL) {
++		kfree(rdwr_pa);
++		return -ENOMEM;
++	}
++
++	res = 0;
++	for (i = 0; i < rdwr_arg.nmsgs; i++) {
++		/* Limit the size of the message to a sane amount;
++		 * and don't let length change either. */
++		if ((rdwr_pa[i].len > 8192) ||
++		    (rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
++			res = -EINVAL;
++			break;
++		}
++		data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
++		rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
++		if (rdwr_pa[i].buf == NULL) {
++			res = -ENOMEM;
++			break;
++		}
++		if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i],
++				   rdwr_pa[i].len)) {
++				++i; /* Needs to be kfreed too */
++				res = -EFAULT;
++			break;
++		}
++	}
++	if (res < 0) {
++		int j;
++		for (j = 0; j < i; ++j)
++			kfree(rdwr_pa[j].buf);
++		kfree(data_ptrs);
++		kfree(rdwr_pa);
++		return res;
++	}
++
++	res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);
++	while (i-- > 0) {
++		if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
++			if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,
++					 rdwr_pa[i].len))
++				res = -EFAULT;
++		}
++		kfree(rdwr_pa[i].buf);
++	}
++	kfree(data_ptrs);
++	kfree(rdwr_pa);
++	return res;
++}
++
++static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
++		unsigned long arg)
++{
++	struct i2c_smbus_ioctl_data data_arg;
++	union i2c_smbus_data temp;
++	int datasize, res;
++
++	if (copy_from_user(&data_arg,
++			   (struct i2c_smbus_ioctl_data __user *) arg,
++			   sizeof(struct i2c_smbus_ioctl_data)))
++		return -EFAULT;
++	if ((data_arg.size != I2C_SMBUS_BYTE) &&
++	    (data_arg.size != I2C_SMBUS_QUICK) &&
++	    (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
++	    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
++	    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
++	    (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
++	    (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
++	    (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
++	    (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
++		dev_dbg(&client->adapter->dev,
++			"size out of range (%x) in ioctl I2C_SMBUS.\n",
++			data_arg.size);
++		return -EINVAL;
++	}
++	/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
++	   so the check is valid if size==I2C_SMBUS_QUICK too. */
++	if ((data_arg.read_write != I2C_SMBUS_READ) &&
++	    (data_arg.read_write != I2C_SMBUS_WRITE)) {
++		dev_dbg(&client->adapter->dev,
++			"read_write out of range (%x) in ioctl I2C_SMBUS.\n",
++			data_arg.read_write);
++		return -EINVAL;
++	}
++
++	/* Note that command values are always valid! */
++
++	if ((data_arg.size == I2C_SMBUS_QUICK) ||
++	    ((data_arg.size == I2C_SMBUS_BYTE) &&
++	    (data_arg.read_write == I2C_SMBUS_WRITE)))
++		/* These are special: we do not use data */
++		return i2c_smbus_xfer(client->adapter, client->addr,
++				      client->flags, data_arg.read_write,
++				      data_arg.command, data_arg.size, NULL);
++
++	if (data_arg.data == NULL) {
++		dev_dbg(&client->adapter->dev,
++			"data is NULL pointer in ioctl I2C_SMBUS.\n");
++		return -EINVAL;
++	}
++
++	if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
++	    (data_arg.size == I2C_SMBUS_BYTE))
++		datasize = sizeof(data_arg.data->byte);
++	else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
++		 (data_arg.size == I2C_SMBUS_PROC_CALL))
++		datasize = sizeof(data_arg.data->word);
++	else /* size == smbus block, i2c block, or block proc. call */
++		datasize = sizeof(data_arg.data->block);
++
++	if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
++	    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
++	    (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
++	    (data_arg.read_write == I2C_SMBUS_WRITE)) {
++		if (copy_from_user(&temp, data_arg.data, datasize))
++			return -EFAULT;
++	}
++	if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
++		/* Convert old I2C block commands to the new
++		   convention. This preserves binary compatibility. */
++		data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
++		if (data_arg.read_write == I2C_SMBUS_READ)
++			temp.block[0] = I2C_SMBUS_BLOCK_MAX;
++	}
++	res = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
++	      data_arg.read_write, data_arg.command, data_arg.size, &temp);
++	if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
++		     (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
++		     (data_arg.read_write == I2C_SMBUS_READ))) {
++		if (copy_to_user(data_arg.data, &temp, datasize))
++			return -EFAULT;
++	}
++	return res;
++}
++
++static int i2cdev_ioctl(struct inode *inode, struct file *file,
++		unsigned int cmd, unsigned long arg)
++{
++	struct i2c_client *client = (struct i2c_client *)file->private_data;
+ 	unsigned long funcs;
+ 
+ 	dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
+@@ -253,164 +413,11 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
+ 		return put_user(funcs, (unsigned long __user *)arg);
+ 
+ 	case I2C_RDWR:
+-		if (copy_from_user(&rdwr_arg,
+-				   (struct i2c_rdwr_ioctl_data __user *)arg,
+-				   sizeof(rdwr_arg)))
+-			return -EFAULT;
+-
+-		/* Put an arbitrary limit on the number of messages that can
+-		 * be sent at once */
+-		if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
+-			return -EINVAL;
+-
+-		rdwr_pa = (struct i2c_msg *)
+-			kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
+-			GFP_KERNEL);
+-
+-		if (rdwr_pa == NULL) return -ENOMEM;
+-
+-		if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
+-				   rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
+-			kfree(rdwr_pa);
+-			return -EFAULT;
+-		}
+-
+-		data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
+-		if (data_ptrs == NULL) {
+-			kfree(rdwr_pa);
+-			return -ENOMEM;
+-		}
+-
+-		res = 0;
+-		for( i=0; i<rdwr_arg.nmsgs; i++ ) {
+-			/* Limit the size of the message to a sane amount;
+-			 * and don't let length change either. */
+-			if ((rdwr_pa[i].len > 8192) ||
+-			    (rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
+-				res = -EINVAL;
+-				break;
+-			}
+-			data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
+-			rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
+-			if(rdwr_pa[i].buf == NULL) {
+-				res = -ENOMEM;
+-				break;
+-			}
+-			if(copy_from_user(rdwr_pa[i].buf,
+-				data_ptrs[i],
+-				rdwr_pa[i].len)) {
+-					++i; /* Needs to be kfreed too */
+-					res = -EFAULT;
+-				break;
+-			}
+-		}
+-		if (res < 0) {
+-			int j;
+-			for (j = 0; j < i; ++j)
+-				kfree(rdwr_pa[j].buf);
+-			kfree(data_ptrs);
+-			kfree(rdwr_pa);
+-			return res;
+-		}
+-
+-		res = i2c_transfer(client->adapter,
+-			rdwr_pa,
+-			rdwr_arg.nmsgs);
+-		while(i-- > 0) {
+-			if( res>=0 && (rdwr_pa[i].flags & I2C_M_RD)) {
+-				if(copy_to_user(
+-					data_ptrs[i],
+-					rdwr_pa[i].buf,
+-					rdwr_pa[i].len)) {
+-					res = -EFAULT;
+-				}
+-			}
+-			kfree(rdwr_pa[i].buf);
+-		}
+-		kfree(data_ptrs);
+-		kfree(rdwr_pa);
+-		return res;
++		return i2cdev_ioctl_rdrw(client, arg);
+ 
+ 	case I2C_SMBUS:
+-		if (copy_from_user(&data_arg,
+-		                   (struct i2c_smbus_ioctl_data __user *) arg,
+-		                   sizeof(struct i2c_smbus_ioctl_data)))
+-			return -EFAULT;
+-		if ((data_arg.size != I2C_SMBUS_BYTE) &&
+-		    (data_arg.size != I2C_SMBUS_QUICK) &&
+-		    (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
+-		    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
+-		    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
+-		    (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
+-		    (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
+-		    (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
+-		    (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
+-			dev_dbg(&client->adapter->dev,
+-				"size out of range (%x) in ioctl I2C_SMBUS.\n",
+-				data_arg.size);
+-			return -EINVAL;
+-		}
+-		/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
+-		   so the check is valid if size==I2C_SMBUS_QUICK too. */
+-		if ((data_arg.read_write != I2C_SMBUS_READ) &&
+-		    (data_arg.read_write != I2C_SMBUS_WRITE)) {
+-			dev_dbg(&client->adapter->dev,
+-				"read_write out of range (%x) in ioctl I2C_SMBUS.\n",
+-				data_arg.read_write);
+-			return -EINVAL;
+-		}
+-
+-		/* Note that command values are always valid! */
+-
+-		if ((data_arg.size == I2C_SMBUS_QUICK) ||
+-		    ((data_arg.size == I2C_SMBUS_BYTE) &&
+-		    (data_arg.read_write == I2C_SMBUS_WRITE)))
+-			/* These are special: we do not use data */
+-			return i2c_smbus_xfer(client->adapter, client->addr,
+-					      client->flags,
+-					      data_arg.read_write,
+-					      data_arg.command,
+-					      data_arg.size, NULL);
+-
+-		if (data_arg.data == NULL) {
+-			dev_dbg(&client->adapter->dev,
+-				"data is NULL pointer in ioctl I2C_SMBUS.\n");
+-			return -EINVAL;
+-		}
++		return i2cdev_ioctl_smbus(client, arg);
+ 
+-		if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
+-		    (data_arg.size == I2C_SMBUS_BYTE))
+-			datasize = sizeof(data_arg.data->byte);
+-		else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
+-		         (data_arg.size == I2C_SMBUS_PROC_CALL))
+-			datasize = sizeof(data_arg.data->word);
+-		else /* size == smbus block, i2c block, or block proc. call */
+-			datasize = sizeof(data_arg.data->block);
+-
+-		if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+-		    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+-		    (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
+-		    (data_arg.read_write == I2C_SMBUS_WRITE)) {
+-			if (copy_from_user(&temp, data_arg.data, datasize))
+-				return -EFAULT;
+-		}
+-		if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
+-			/* Convert old I2C block commands to the new
+-			   convention. This preserves binary compatibility. */
+-			data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
+-			if (data_arg.read_write == I2C_SMBUS_READ)
+-				temp.block[0] = I2C_SMBUS_BLOCK_MAX;
+-		}
+-		res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
+-		      data_arg.read_write,
+-		      data_arg.command,data_arg.size,&temp);
+-		if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+-		              (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+-			      (data_arg.read_write == I2C_SMBUS_READ))) {
+-			if (copy_to_user(data_arg.data, &temp, datasize))
+-				return -EFAULT;
+-		}
+-		return res;
+ 	case I2C_RETRIES:
+ 		client->adapter->retries = arg;
+ 		break;
+diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
+index eed6d8e..3f9e100 100644
+--- a/drivers/ide/Kconfig
++++ b/drivers/ide/Kconfig
+@@ -122,24 +122,6 @@ config BLK_DEV_IDE_SATA
+ 
+ 	  If unsure, say N.
+ 
+-config BLK_DEV_HD_IDE
+-	bool "Use old disk-only driver on primary interface"
+-	depends on (X86 || SH_MPC1211)
+-	---help---
+-	  There are two drivers for MFM/RLL/IDE disks.  Most people use just
+-	  the new enhanced driver by itself.  This option however installs the
+-	  old hard disk driver to control the primary IDE/disk interface in
+-	  the system, leaving the new enhanced IDE driver to take care of only
+-	  the 2nd/3rd/4th IDE interfaces.  Doing this will prevent you from
+-	  having an IDE/ATAPI CD-ROM or tape drive connected to the primary
+-	  IDE interface.  Choosing this option may be useful for older systems
+-	  which have MFM/RLL/ESDI controller+drives at the primary port
+-	  address (0x1f0), along with IDE drives at the secondary/3rd/4th port
+-	  addresses.
+-
+-	  Normally, just say N here; you will then use the new driver for all
+-	  4 interfaces.
+-
+ config BLK_DEV_IDEDISK
+ 	tristate "Include IDE/ATA-2 DISK support"
+ 	---help---
+@@ -325,6 +307,7 @@ comment "IDE chipset support/bugfixes"
+ 
+ config IDE_GENERIC
+ 	tristate "generic/default IDE chipset support"
++	depends on ALPHA || X86 || IA64 || M32R || MIPS || PPC32
+ 	help
+ 	  If unsure, say N.
+ 
+@@ -416,12 +399,6 @@ config BLK_DEV_OFFBOARD
+ 	  This can improve the usability of some boot managers such as lilo
+ 	  when booting from a drive on an off-board controller.
+ 
+-	  If you say Y here, and you actually want to reverse the device scan
+-	  order as explained above, you also need to issue the kernel command
+-	  line option "ide=reverse". (Try "man bootparam" or see the
+-	  documentation of your boot loader (lilo or loadlin) about how to
+-	  pass options to the kernel at boot time.)
+-
+ 	  Note that, if you do this, the order of the hd* devices will be
+ 	  rearranged which may require modification of fstab and other files.
+ 
+@@ -615,8 +592,7 @@ config BLK_DEV_HPT366
+ 	  reference to device 0x80. The other solution is to say Y to "Boot
+ 	  off-board chipsets first support" (CONFIG_BLK_DEV_OFFBOARD) unless
+ 	  your mother board has the chipset natively mounted. Regardless one
+-	  should use the fore mentioned option and call at LILO or include
+-	  "ide=reverse" in LILO's append-line.
++	  should use the fore mentioned option and call at LILO.
+ 
+ 	  This driver requires dynamic tuning of the chipset during the
+ 	  ide-probe at boot. It is reported to support DVD II drives, by the
+@@ -1049,19 +1025,19 @@ config IDE_EXT_DIRECT
+ endchoice
+ 
+ # no isa -> no vlb
+-if ISA
++if ISA && (ALPHA || X86 || MIPS)
+ 
+ comment "Other IDE chipsets support"
+ comment "Note: most of these also require special kernel boot parameters"
+ 
+ config BLK_DEV_4DRIVES
+-	bool "Generic 4 drives/port support"
++	tristate "Generic 4 drives/port support"
+ 	help
+ 	  Certain older chipsets, including the Tekram 690CD, use a single set
+ 	  of I/O ports at 0x1f0 to control up to four drives, instead of the
+ 	  customary two drives per port. Support for this can be enabled at
+-	  runtime using the "ide0=four" kernel boot parameter if you say Y
+-	  here.
++	  runtime using the "ide-4drives.probe" kernel boot parameter if you
++	  say Y here.
+ 
+ config BLK_DEV_ALI14XX
+ 	tristate "ALI M14xx support"
+@@ -1114,14 +1090,10 @@ config BLK_DEV_IDEDMA
+ 	def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \
+ 		 BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ 
+-config IDE_ARCH_OBSOLETE_INIT
+-	def_bool ALPHA || (ARM && !ARCH_L7200) || BLACKFIN || X86 || IA64 || M32R || MIPS || PARISC || PPC || (SUPERH64 && BLK_DEV_IDEPCI) || SPARC
+-
+ endif
+ 
+ config BLK_DEV_HD_ONLY
+ 	bool "Old hard disk (MFM/RLL/IDE) driver"
+-	depends on BLK_DEV_IDE=n
+ 	help
+ 	  There are two drivers for MFM/RLL/IDE hard disks. Most people use
+ 	  the newer enhanced driver, but this old one is still around for two
+@@ -1133,12 +1105,16 @@ config BLK_DEV_HD_ONLY
+ 	  for systems with only older MFM/RLL/ESDI drives. Choosing the old
+ 	  driver can save 13 KB or so of kernel memory.
+ 
++	  If you want to use this driver together with the new one you have
++	  to use "hda=noprobe hdb=noprobe" kernel parameters to prevent the new
++	  driver from probing the primary interface.
++
+ 	  If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver
+ 	  instead of this one. For more detailed information, read the
+ 	  Disk-HOWTO, available from
+ 	  <http://www.tldp.org/docs.html#howto>.
+ 
+ config BLK_DEV_HD
+-	def_bool BLK_DEV_HD_IDE || BLK_DEV_HD_ONLY
++	def_bool BLK_DEV_HD_ONLY
+ 
+ endif # IDE
+diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
+index a4a4323..571544c 100644
+--- a/drivers/ide/Makefile
++++ b/drivers/ide/Makefile
+@@ -36,9 +36,9 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y)
+ endif
+ 
+ obj-$(CONFIG_BLK_DEV_IDE)		+= cris/ ppc/
+-obj-$(CONFIG_BLK_DEV_IDEPNP)		+= ide-pnp.o
+ obj-$(CONFIG_IDE_H8300)			+= h8300/
+ obj-$(CONFIG_IDE_GENERIC)		+= ide-generic.o
++obj-$(CONFIG_BLK_DEV_IDEPNP)		+= ide-pnp.o
+ 
+ ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
+ 
+diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
+index 161d30c..a80b957 100644
+--- a/drivers/ide/arm/bast-ide.c
++++ b/drivers/ide/arm/bast-ide.c
+@@ -21,6 +21,8 @@
+ #include <asm/arch/bast-map.h>
+ #include <asm/arch/bast-irq.h>
+ 
++#define DRV_NAME "bast-ide"
++
+ static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
+ {
+ 	ide_hwif_t *hwif;
+@@ -41,18 +43,19 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
+ 	hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
+ 	hw.irq = irq;
+ 
+-	hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	hwif = ide_find_port();
+ 	if (hwif == NULL)
+ 		goto out;
+ 
+ 	i = hwif->index;
+ 
+ 	if (hwif->present)
+-		ide_unregister(i, 0, 0);
+-	else if (!hwif->hold)
++		ide_unregister(i);
++	else
+ 		ide_init_port_data(hwif, i);
+ 
+ 	ide_init_port_hw(hwif, &hw);
++	hwif->mmio = 1;
+ 	hwif->quirkproc = NULL;
+ 
+ 	idx[0] = i;
+@@ -64,6 +67,8 @@ out:
+ 
+ static int __init bastide_init(void)
+ {
++	unsigned long base = BAST_VA_IDEPRI + BAST_IDE_CS;
++
+ 	/* we can treat the VR1000 and the BAST the same */
+ 
+ 	if (!(machine_is_bast() || machine_is_vr1000()))
+@@ -71,6 +76,11 @@ static int __init bastide_init(void)
+ 
+ 	printk("BAST: IDE driver, (c) 2003-2004 Simtec Electronics\n");
+ 
++	if (!request_mem_region(base, 0x400000, DRV_NAME)) {
++		printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
++		return -EBUSY;
++	}
++
+ 	bastide_register(BAST_VA_IDEPRI, BAST_VA_IDEPRIAUX, IRQ_IDE0);
+ 	bastide_register(BAST_VA_IDESEC, BAST_VA_IDESECAUX, IRQ_IDE1);
+ 
+diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
+index e816b0f..fd12bbe 100644
+--- a/drivers/ide/arm/icside.c
++++ b/drivers/ide/arm/icside.c
+@@ -400,7 +400,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
+ 	unsigned long port = (unsigned long)base + info->dataoffset;
+ 	ide_hwif_t *hwif;
+ 
+-	hwif = ide_find_port(port);
++	hwif = ide_find_port();
+ 	if (hwif) {
+ 		int i;
+ 
+diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
+index be9ff73..82643df 100644
+--- a/drivers/ide/arm/ide_arm.c
++++ b/drivers/ide/arm/ide_arm.c
+@@ -34,7 +34,7 @@ static int __init ide_arm_init(void)
+ 	ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
+ 	hw.irq = IDE_ARM_IRQ;
+ 
+-	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	hwif = ide_find_port();
+ 	if (hwif) {
+ 		ide_init_port_hw(hwif, &hw);
+ 		idx[0] = hwif->index;
+diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c
+index 8e1f6bd..666df77 100644
+--- a/drivers/ide/arm/palm_bk3710.c
++++ b/drivers/ide/arm/palm_bk3710.c
+@@ -96,11 +96,11 @@ static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
+ 	u16 val16;
+ 
+ 	/* DMA Data Setup */
+-	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
+-			/ ide_palm_clk - 1;
+-	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
+-	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
+-			/ ide_palm_clk - 1;
++	t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
++			  ide_palm_clk) - 1;
++	tenv = DIV_ROUND_UP(20, ide_palm_clk) - 1;
++	trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
++			   ide_palm_clk) - 1;
+ 
+ 	/* udmatim Register */
+ 	val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
+@@ -141,8 +141,8 @@ static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
+ 	cycletime = max_t(int, t->cycle, min_cycle);
+ 
+ 	/* DMA Data Setup */
+-	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+-	td = (t->active + ide_palm_clk - 1) / ide_palm_clk;
++	t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
++	td = DIV_ROUND_UP(t->active, ide_palm_clk);
+ 	tkw = t0 - td - 1;
+ 	td -= 1;
+ 
+@@ -168,9 +168,9 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
+ 	struct ide_timing *t;
+ 
+ 	/* PIO Data Setup */
+-	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+-	t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
+-	      ide_palm_clk - 1)	/ ide_palm_clk;
++	t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
++	t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
++			  ide_palm_clk);
+ 
+ 	t2i = t0 - t2 - 1;
+ 	t2 -= 1;
+@@ -192,8 +192,8 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
+ 
+ 	/* TASKFILE Setup */
+ 	t = ide_timing_find_mode(XFER_PIO_0 + mode);
+-	t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
+-	t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
++	t0 = DIV_ROUND_UP(t->cyc8b, ide_palm_clk);
++	t2 = DIV_ROUND_UP(t->act8b, ide_palm_clk);
+ 
+ 	t2i = t0 - t2 - 1;
+ 	t2 -= 1;
+@@ -378,15 +378,15 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+ 	hw.irq = irq->start;
+ 	hw.chipset = ide_palm3710;
+ 
+-	hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	hwif = ide_find_port();
+ 	if (hwif == NULL)
+ 		goto out;
+ 
+ 	i = hwif->index;
+ 
+ 	if (hwif->present)
+-		ide_unregister(i, 0, 0);
+-	else if (!hwif->hold)
++		ide_unregister(i);
++	else
+ 		ide_init_port_data(hwif, i);
+ 
+ 	ide_init_port_hw(hwif, &hw);
+@@ -409,9 +409,13 @@ out:
+ 	return -ENODEV;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:palm_bk3710");
++
+ static struct platform_driver platform_bk_driver = {
+ 	.driver = {
+ 		.name = "palm_bk3710",
++		.owner = THIS_MODULE,
+ 	},
+ 	.probe = palm_bk3710_probe,
+ 	.remove = NULL,
+diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
+index efba00d..2c3d0ec 100644
+--- a/drivers/ide/arm/rapide.c
++++ b/drivers/ide/arm/rapide.c
+@@ -44,7 +44,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
+ 		goto release;
+ 	}
+ 
+-	hwif = ide_find_port((unsigned long)base);
++	hwif = ide_find_port();
+ 	if (hwif) {
+ 		memset(&hw, 0, sizeof(hw));
+ 		rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
+@@ -76,7 +76,7 @@ static void __devexit rapide_remove(struct expansion_card *ec)
+ 
+ 	ecard_set_drvdata(ec, NULL);
+ 
+-	ide_unregister(hwif->index, 0, 0);
++	ide_unregister(hwif->index);
+ 
+ 	ecard_release_resources(ec);
+ }
+diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
+index c8ffbaf..790a775 100644
+--- a/drivers/ide/cris/ide-cris.c
++++ b/drivers/ide/cris/ide-cris.c
+@@ -228,7 +228,10 @@ cris_ide_fill_descriptor(cris_dma_descr_type *d, void* buf, unsigned int len, in
+ static void
+ cris_ide_start_dma(ide_drive_t *drive, cris_dma_descr_type *d, int dir,int type,int len)
+ {
+-	reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int, IDE_DATA_REG);
++	ide_hwif_t *hwif = drive->hwif;
++
++	reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int,
++					       hwif->io_ports[IDE_DATA_OFFSET]);
+ 	reg_ata_rw_trf_cnt trf_cnt = {0};
+ 
+ 	mycontext.saved_data = (dma_descr_data*)virt_to_phys(d);
+@@ -264,8 +267,12 @@ cris_ide_wait_dma(int dir)
+ 
+ static int cris_dma_test_irq(ide_drive_t *drive)
+ {
++	ide_hwif_t *hwif = drive->hwif;
+ 	int intr = REG_RD_INT(ata, regi_ata, r_intr);
+-	reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int, IDE_DATA_REG);
++
++	reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int,
++					       hwif->io_ports[IDE_DATA_OFFSET]);
++
+ 	return intr & (1 << ctrl2.sel) ? 1 : 0;
+ }
+ 
+@@ -523,7 +530,8 @@ static void cris_ide_start_dma(ide_drive_t *drive, cris_dma_descr_type *d, int d
+ 	                          IO_STATE(R_ATA_CTRL_DATA, handsh, dma);
+ 	*R_ATA_CTRL_DATA =
+ 		cmd |
+-		IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) |
++		IO_FIELD(R_ATA_CTRL_DATA, data,
++			 drive->hwif->io_ports[IDE_DATA_OFFSET]) |
+ 		IO_STATE(R_ATA_CTRL_DATA, src_dst,  dma)  |
+ 		IO_STATE(R_ATA_CTRL_DATA, multi,    on)   |
+ 		IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+@@ -541,7 +549,9 @@ cris_ide_wait_dma(int dir)
+ static int cris_dma_test_irq(ide_drive_t *drive)
+ {
+ 	int intr = *R_IRQ_MASK0_RD;
+-	int bus = IO_EXTRACT(R_ATA_CTRL_DATA, sel, IDE_DATA_REG);
++	int bus = IO_EXTRACT(R_ATA_CTRL_DATA, sel,
++			     drive->hwif->io_ports[IDE_DATA_OFFSET]);
++
+ 	return intr & (1 << (bus + IO_BITNR(R_IRQ_MASK0_RD, ata_irq0))) ? 1 : 0;
+ }
+ 
+@@ -794,7 +804,7 @@ static int __init init_e100_ide(void)
+ 
+ 		cris_setup_ports(&hw, cris_ide_base_address(h));
+ 
+-		hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++		hwif = ide_find_port();
+ 		if (hwif == NULL)
+ 			continue;
+ 		ide_init_port_data(hwif, hwif->index);
+diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
+index 4108ec4..92b02b9 100644
+--- a/drivers/ide/h8300/ide-h8300.c
++++ b/drivers/ide/h8300/ide-h8300.c
+@@ -99,8 +99,7 @@ static int __init h8300_ide_init(void)
+ 
+ 	hw_setup(&hw);
+ 
+-	/* register if */
+-	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	hwif = ide_find_port();
+ 	if (hwif == NULL) {
+ 		printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
+ 		return -ENOENT;
+diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
+index e07b189..0f6fb6b 100644
+--- a/drivers/ide/ide-acpi.c
++++ b/drivers/ide/ide-acpi.c
+@@ -710,6 +710,8 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
+ 	for (i = 0; i < MAX_DRIVES; i++) {
+ 		drive = &hwif->drives[i];
+ 
++		memset(drive->acpidata, 0, sizeof(*drive->acpidata));
++
+ 		if (!drive->present)
+ 			continue;
+ 
+diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
+index c8d0e87..1afd95a 100644
+--- a/drivers/ide/ide-cd.c
++++ b/drivers/ide/ide-cd.c
+@@ -13,8 +13,8 @@
+  *
+  * Suggestions are welcome. Patches that work are more welcome though. ;-)
+  * For those wishing to work on this driver, please be sure you download
+- * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI 
+- * (SFF-8020i rev 2.6) standards. These documents can be obtained by 
++ * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
++ * (SFF-8020i rev 2.6) standards. These documents can be obtained by
+  * anonymous ftp from:
+  * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
+  * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
+@@ -51,7 +51,7 @@
+ 
+ static DEFINE_MUTEX(idecd_ref_mutex);
+ 
+-#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) 
++#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
+ 
+ #define ide_cd_g(disk) \
+ 	container_of((disk)->private_data, struct cdrom_info, driver)
+@@ -83,13 +83,12 @@ static void ide_cd_put(struct cdrom_info *cd)
+ 
+ /* Mark that we've seen a media change, and invalidate our internal
+    buffers. */
+-static void cdrom_saw_media_change (ide_drive_t *drive)
++static void cdrom_saw_media_change(ide_drive_t *drive)
+ {
+ 	struct cdrom_info *cd = drive->driver_data;
+ 
+ 	cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
+ 	cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+-	cd->nsectors_buffered = 0;
+ }
+ 
+ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
+@@ -101,38 +100,39 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
+ 		return 0;
+ 
+ 	switch (sense->sense_key) {
+-		case NO_SENSE: case RECOVERED_ERROR:
+-			break;
+-		case NOT_READY:
+-			/*
+-			 * don't care about tray state messages for
+-			 * e.g. capacity commands or in-progress or
+-			 * becoming ready
+-			 */
+-			if (sense->asc == 0x3a || sense->asc == 0x04)
+-				break;
+-			log = 1;
+-			break;
+-		case ILLEGAL_REQUEST:
+-			/*
+-			 * don't log START_STOP unit with LoEj set, since
+-			 * we cannot reliably check if drive can auto-close
+-			 */
+-			if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
+-				break;
+-			log = 1;
+-			break;
+-		case UNIT_ATTENTION:
+-			/*
+-			 * Make good and sure we've seen this potential media
+-			 * change. Some drives (i.e. Creative) fail to present
+-			 * the correct sense key in the error register.
+-			 */
+-			cdrom_saw_media_change(drive);
++	case NO_SENSE:
++	case RECOVERED_ERROR:
++		break;
++	case NOT_READY:
++		/*
++		 * don't care about tray state messages for
++		 * e.g. capacity commands or in-progress or
++		 * becoming ready
++		 */
++		if (sense->asc == 0x3a || sense->asc == 0x04)
+ 			break;
+-		default:
+-			log = 1;
++		log = 1;
++		break;
++	case ILLEGAL_REQUEST:
++		/*
++		 * don't log START_STOP unit with LoEj set, since
++		 * we cannot reliably check if drive can auto-close
++		 */
++		if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
+ 			break;
++		log = 1;
++		break;
++	case UNIT_ATTENTION:
++		/*
++		 * Make good and sure we've seen this potential media
++		 * change. Some drives (i.e. Creative) fail to present
++		 * the correct sense key in the error register.
++		 */
++		cdrom_saw_media_change(drive);
++		break;
++	default:
++		log = 1;
++		break;
+ 	}
+ 	return log;
+ }
+@@ -159,8 +159,8 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
+ 		if (sense->sense_key == 0x05 && sense->asc == 0x24)
+ 			return;
+ 
+- 	if (sense->error_code == 0x70) {	/* Current Error */
+- 		switch(sense->sense_key) {
++	if (sense->error_code == 0x70) {	/* Current Error */
++		switch (sense->sense_key) {
+ 		case MEDIUM_ERROR:
+ 		case VOLUME_OVERFLOW:
+ 		case ILLEGAL_REQUEST:
+@@ -179,7 +179,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
+ 				bio_sectors = 4;
+ 			if (drive->queue->hardsect_size == 2048)
+ 				sector <<= 2;	/* Device sector size is 2K */
+-			sector &= ~(bio_sectors -1);
++			sector &= ~(bio_sectors - 1);
+ 			valid = (sector - failed_command->sector) << 9;
+ 
+ 			if (valid < 0)
+@@ -188,8 +188,8 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
+ 				drive->probed_capacity - sector < 4 * 75) {
+ 				set_capacity(info->disk, sector);
+ 			}
+- 		}
+- 	}
++		}
++	}
+ 
+ 	ide_cd_log_error(drive->name, failed_command, sense);
+ }
+@@ -230,7 +230,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
+ 	(void) ide_do_drive_cmd(drive, rq, ide_preempt);
+ }
+ 
+-static void cdrom_end_request (ide_drive_t *drive, int uptodate)
++static void cdrom_end_request(ide_drive_t *drive, int uptodate)
+ {
+ 	struct request *rq = HWGROUP(drive)->rq;
+ 	int nsectors = rq->hard_cur_sectors;
+@@ -293,7 +293,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ {
+ 	struct request *rq = HWGROUP(drive)->rq;
+ 	int stat, err, sense_key;
+-	
++
+ 	/* Check for errors. */
+ 	stat = ide_read_status(drive);
+ 
+@@ -334,26 +334,26 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 
+ 		/* Check for tray open. */
+ 		if (sense_key == NOT_READY) {
+-			cdrom_saw_media_change (drive);
++			cdrom_saw_media_change(drive);
+ 		} else if (sense_key == UNIT_ATTENTION) {
+ 			/* Check for media change. */
+-			cdrom_saw_media_change (drive);
++			cdrom_saw_media_change(drive);
+ 			/*printk("%s: media changed\n",drive->name);*/
+ 			return 0;
+- 		} else if ((sense_key == ILLEGAL_REQUEST) &&
+- 			   (rq->cmd[0] == GPCMD_START_STOP_UNIT)) {
+- 			/*
+- 			 * Don't print error message for this condition--
+- 			 * SFF8090i indicates that 5/24/00 is the correct
+- 			 * response to a request to close the tray if the
+- 			 * drive doesn't have that capability.
+- 			 * cdrom_log_sense() knows this!
+- 			 */
++		} else if (sense_key == ILLEGAL_REQUEST &&
++			   rq->cmd[0] == GPCMD_START_STOP_UNIT) {
++			/*
++			 * Don't print error message for this condition--
++			 * SFF8090i indicates that 5/24/00 is the correct
++			 * response to a request to close the tray if the
++			 * drive doesn't have that capability.
++			 * cdrom_log_sense() knows this!
++			 */
+ 		} else if (!(rq->cmd_flags & REQ_QUIET)) {
+ 			/* Otherwise, print an error. */
+ 			ide_dump_status(drive, "packet command error", stat);
+ 		}
+-		
++
+ 		rq->cmd_flags |= REQ_FAILED;
+ 
+ 		/*
+@@ -374,10 +374,10 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 		if (sense_key == NOT_READY) {
+ 			/* Tray open. */
+ 			if (rq_data_dir(rq) == READ) {
+-				cdrom_saw_media_change (drive);
++				cdrom_saw_media_change(drive);
+ 
+ 				/* Fail the request. */
+-				printk ("%s: tray open\n", drive->name);
++				printk("%s: tray open\n", drive->name);
+ 				do_end_request = 1;
+ 			} else {
+ 				struct cdrom_info *info = drive->driver_data;
+@@ -399,7 +399,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 					 */
+ 					spin_lock_irqsave(&ide_lock, flags);
+ 					blk_plug_device(drive->queue);
+-					spin_unlock_irqrestore(&ide_lock,flags);
++					spin_unlock_irqrestore(&ide_lock, flags);
+ 					return 1;
+ 				}
+ 			}
+@@ -407,25 +407,31 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 			/* Media change. */
+ 			cdrom_saw_media_change (drive);
+ 
+-			/* Arrange to retry the request.
+-			   But be sure to give up if we've retried
+-			   too many times. */
++			/*
++			 * Arrange to retry the request.
++			 * But be sure to give up if we've retried
++			 * too many times.
++			 */
+ 			if (++rq->errors > ERROR_MAX)
+ 				do_end_request = 1;
+ 		} else if (sense_key == ILLEGAL_REQUEST ||
+ 			   sense_key == DATA_PROTECT) {
+-			/* No point in retrying after an illegal
+-			   request or data protect error.*/
+-			ide_dump_status_no_sense (drive, "command error", stat);
++			/*
++			 * No point in retrying after an illegal
++			 * request or data protect error.
++			 */
++			ide_dump_status_no_sense(drive, "command error", stat);
+ 			do_end_request = 1;
+ 		} else if (sense_key == MEDIUM_ERROR) {
+-			/* No point in re-trying a zillion times on a bad 
+-			 * sector...  If we got here the error is not correctable */
+-			ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
++			/*
++			 * No point in re-trying a zillion times on a bad
++			 * sector... If we got here the error is not correctable
++			 */
++			ide_dump_status_no_sense(drive, "media error (bad sector)", stat);
+ 			do_end_request = 1;
+ 		} else if (sense_key == BLANK_CHECK) {
+ 			/* Disk appears blank ?? */
+-			ide_dump_status_no_sense (drive, "media error (blank)", stat);
++			ide_dump_status_no_sense(drive, "media error (blank)", stat);
+ 			do_end_request = 1;
+ 		} else if ((err & ~ABRT_ERR) != 0) {
+ 			/* Go to the default handler
+@@ -486,18 +492,18 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
+ 	 * ide_timer_expiry keep polling us for these.
+ 	 */
+ 	switch (rq->cmd[0]) {
+-		case GPCMD_BLANK:
+-		case GPCMD_FORMAT_UNIT:
+-		case GPCMD_RESERVE_RZONE_TRACK:
+-		case GPCMD_CLOSE_TRACK:
+-		case GPCMD_FLUSH_CACHE:
+-			wait = ATAPI_WAIT_PC;
+-			break;
+-		default:
+-			if (!(rq->cmd_flags & REQ_QUIET))
+-				printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
+-			wait = 0;
+-			break;
++	case GPCMD_BLANK:
++	case GPCMD_FORMAT_UNIT:
++	case GPCMD_RESERVE_RZONE_TRACK:
++	case GPCMD_CLOSE_TRACK:
++	case GPCMD_FLUSH_CACHE:
++		wait = ATAPI_WAIT_PC;
++		break;
++	default:
++		if (!(rq->cmd_flags & REQ_QUIET))
++			printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
++		wait = 0;
++		break;
+ 	}
+ 	return wait;
+ }
+@@ -542,7 +548,8 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+ 
+ 		/* packet command */
+ 		spin_lock_irqsave(&ide_lock, flags);
+-		hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG);
++		hwif->OUTBSYNC(drive, WIN_PACKETCMD,
++			       hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 		ndelay(400);
+ 		spin_unlock_irqrestore(&ide_lock, flags);
+ 
+@@ -556,7 +563,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+    HANDLER is the interrupt handler to call when the command completes
+    or there's data ready. */
+ #define ATAPI_MIN_CDB_BYTES 12
+-static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
++static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
+ 					  struct request *rq,
+ 					  ide_handler_t *handler)
+ {
+@@ -625,47 +632,6 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
+ }
+ 
+ /*
+- * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
+- * buffer.  Once the first sector is added, any subsequent sectors are
+- * assumed to be continuous (until the buffer is cleared).  For the first
+- * sector added, SECTOR is its sector number.  (SECTOR is then ignored until
+- * the buffer is cleared.)
+- */
+-static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
+-                                  int sectors_to_transfer)
+-{
+-	struct cdrom_info *info = drive->driver_data;
+-
+-	/* Number of sectors to read into the buffer. */
+-	int sectors_to_buffer = min_t(int, sectors_to_transfer,
+-				     (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -
+-				       info->nsectors_buffered);
+-
+-	char *dest;
+-
+-	/* If we couldn't get a buffer, don't try to buffer anything... */
+-	if (info->buffer == NULL)
+-		sectors_to_buffer = 0;
+-
+-	/* If this is the first sector in the buffer, remember its number. */
+-	if (info->nsectors_buffered == 0)
+-		info->sector_buffered = sector;
+-
+-	/* Read the data into the buffer. */
+-	dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE;
+-	while (sectors_to_buffer > 0) {
+-		HWIF(drive)->atapi_input_bytes(drive, dest, SECTOR_SIZE);
+-		--sectors_to_buffer;
+-		--sectors_to_transfer;
+-		++info->nsectors_buffered;
+-		dest += SECTOR_SIZE;
+-	}
+-
+-	/* Throw away any remaining data. */
+-	ide_cd_drain_data(drive, sectors_to_transfer);
+-}
+-
+-/*
+  * Check the contents of the interrupt reason register from the cdrom
+  * and attempt to recover if there are problems.  Returns  0 if everything's
+  * ok; nonzero if the request has been terminated.
+@@ -685,7 +651,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
+ 
+ 		/* Whoops... */
+ 		printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
+-				drive->name, __FUNCTION__);
++				drive->name, __func__);
+ 
+ 		xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
+ 		ide_cd_pad_transfer(drive, xf, len);
+@@ -698,7 +664,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
+ 	} else {
+ 		/* Drive wants a command packet, or invalid ireason... */
+ 		printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
+-				drive->name, __FUNCTION__, ireason);
++				drive->name, __func__, ireason);
+ 	}
+ 
+ 	if (rq->cmd_type == REQ_TYPE_ATA_PC)
+@@ -720,7 +686,7 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
+ 		return 0;
+ 
+ 	printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
+-			drive->name, __FUNCTION__, len);
++			drive->name, __func__, len);
+ 
+ 	if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
+ 		printk(KERN_ERR "  This drive is not supported by "
+@@ -733,65 +699,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
+ 	return 1;
+ }
+ 
+-/*
+- * Try to satisfy some of the current read request from our cached data.
+- * Returns nonzero if the request has been completed, zero otherwise.
+- */
+-static int cdrom_read_from_buffer (ide_drive_t *drive)
+-{
+-	struct cdrom_info *info = drive->driver_data;
+-	struct request *rq = HWGROUP(drive)->rq;
+-	unsigned short sectors_per_frame;
+-
+-	sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+-
+-	/* Can't do anything if there's no buffer. */
+-	if (info->buffer == NULL) return 0;
+-
+-	/* Loop while this request needs data and the next block is present
+-	   in our cache. */
+-	while (rq->nr_sectors > 0 &&
+-	       rq->sector >= info->sector_buffered &&
+-	       rq->sector < info->sector_buffered + info->nsectors_buffered) {
+-		if (rq->current_nr_sectors == 0)
+-			cdrom_end_request(drive, 1);
+-
+-		memcpy (rq->buffer,
+-			info->buffer +
+-			(rq->sector - info->sector_buffered) * SECTOR_SIZE,
+-			SECTOR_SIZE);
+-		rq->buffer += SECTOR_SIZE;
+-		--rq->current_nr_sectors;
+-		--rq->nr_sectors;
+-		++rq->sector;
+-	}
+-
+-	/* If we've satisfied the current request,
+-	   terminate it successfully. */
+-	if (rq->nr_sectors == 0) {
+-		cdrom_end_request(drive, 1);
+-		return -1;
+-	}
+-
+-	/* Move on to the next buffer if needed. */
+-	if (rq->current_nr_sectors == 0)
+-		cdrom_end_request(drive, 1);
+-
+-	/* If this condition does not hold, then the kluge i use to
+-	   represent the number of sectors to skip at the start of a transfer
+-	   will fail.  I think that this will never happen, but let's be
+-	   paranoid and check. */
+-	if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) &&
+-	    (rq->sector & (sectors_per_frame - 1))) {
+-		printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
+-			drive->name, (long)rq->sector);
+-		cdrom_end_request(drive, 0);
+-		return -1;
+-	}
+-
+-	return 0;
+-}
+-
+ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
+ 
+ /*
+@@ -824,7 +731,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+ 			if (rq->current_nr_sectors !=
+ 			    bio_cur_sectors(rq->bio)) {
+ 				printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
+-						drive->name, __FUNCTION__,
++						drive->name, __func__,
+ 						rq->current_nr_sectors);
+ 				cdrom_end_request(drive, 0);
+ 				return ide_stopped;
+@@ -848,7 +755,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+ #define IDECD_SEEK_TIMER	(5 * WAIT_MIN_SLEEP)	/* 100 ms */
+ #define IDECD_SEEK_TIMEOUT	(2 * WAIT_CMD)		/* 20 sec */
+ 
+-static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
++static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
+ {
+ 	struct cdrom_info *info = drive->driver_data;
+ 	int stat;
+@@ -865,14 +772,14 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
+ 			 * this condition is far too common, to bother
+ 			 * users about it
+ 			 */
+-			/* printk("%s: disabled DSC seek overlap\n", drive->name);*/ 
++			/* printk("%s: disabled DSC seek overlap\n", drive->name);*/
+ 			drive->dsc_overlap = 0;
+ 		}
+ 	}
+ 	return ide_stopped;
+ }
+ 
+-static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
++static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
+ {
+ 	struct request *rq = HWGROUP(drive)->rq;
+ 	sector_t frame = rq->sector;
+@@ -887,7 +794,7 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
+ 	return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
+ }
+ 
+-static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
++static ide_startstop_t cdrom_start_seek(ide_drive_t *drive, unsigned int block)
+ {
+ 	struct cdrom_info *info = drive->driver_data;
+ 
+@@ -896,9 +803,11 @@ static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
+ 	return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation);
+ }
+ 
+-/* Fix up a possibly partially-processed request so that we can
+-   start it over entirely, or even put it back on the request queue. */
+-static void restore_request (struct request *rq)
++/*
++ * Fix up a possibly partially-processed request so that we can
++ * start it over entirely, or even put it back on the request queue.
++ */
++static void restore_request(struct request *rq)
+ {
+ 	if (rq->buffer != bio_data(rq->bio)) {
+ 		sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;
+@@ -949,7 +858,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
+ 		error = ide_do_drive_cmd(drive, rq, ide_wait);
+ 		time = jiffies - time;
+ 
+-		/* FIXME: we should probably abort/retry or something 
++		/* FIXME: we should probably abort/retry or something
+ 		 * in case of failure */
+ 		if (rq->cmd_flags & REQ_FAILED) {
+ 			/* The request failed.  Retry if it was due to a unit
+@@ -992,6 +901,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
+ 
+ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ {
++	ide_hwif_t *hwif = drive->hwif;
+ 	struct cdrom_info *info = drive->driver_data;
+ 	struct request *rq = HWGROUP(drive)->rq;
+ 	xfer_func_t *xferfunc;
+@@ -1032,9 +942,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ 	/*
+ 	 * ok we fall to pio :/
+ 	 */
+-	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
+-	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
+-	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
++	ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]) & 0x3;
++	lowcyl  = hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
++	highcyl = hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]);
+ 
+ 	len = lowcyl + (256 * highcyl);
+ 
+@@ -1055,7 +965,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ 			if (rq->current_nr_sectors > 0) {
+ 				printk(KERN_ERR "%s: %s: data underrun "
+ 						"(%d blocks)\n",
+-						drive->name, __FUNCTION__,
++						drive->name, __func__,
+ 						rq->current_nr_sectors);
+ 				if (!write)
+ 					rq->cmd_flags |= REQ_FAILED;
+@@ -1132,11 +1042,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ 		if (!ptr) {
+ 			if (blk_fs_request(rq) && !write)
+ 				/*
+-				 * If the buffers are full, cache the rest
+-				 * of the data in our internal buffer.
+-				 */
+-				cdrom_buffer_sectors(drive, rq->sector,
+-						     thislen >> 9);
++				 * If the buffers are full, pipe the rest into
++				 * oblivion. */
++				ide_cd_drain_data(drive, thislen >> 9);
+ 			else {
+ 				printk(KERN_ERR "%s: confused, missing data\n",
+ 						drive->name);
+@@ -1241,10 +1149,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
+ 		 * weirdness which might be present in the request packet.
+ 		 */
+ 		restore_request(rq);
+-
+-		/* Satisfy whatever we can of this request from our cache. */
+-		if (cdrom_read_from_buffer(drive))
+-			return ide_stopped;
+ 	}
+ 
+ 	/*
+@@ -1260,9 +1164,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
+ 	} else
+ 		cd->dma = drive->using_dma;
+ 
+-	/* Clear the local sector buffer. */
+-	cd->nsectors_buffered = 0;
+-
+ 	if (write)
+ 		cd->devinfo.media_written = 1;
+ 
+@@ -1318,7 +1219,7 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+  * cdrom driver request routine.
+  */
+ static ide_startstop_t
+-ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
++ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq, sector_t block)
+ {
+ 	ide_startstop_t action;
+ 	struct cdrom_info *info = drive->driver_data;
+@@ -1333,13 +1234,13 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+ 					ide_stall_queue(drive, IDECD_SEEK_TIMER);
+ 					return ide_stopped;
+ 				}
+-				printk (KERN_ERR "%s: DSC timeout\n", drive->name);
++				printk(KERN_ERR "%s: DSC timeout\n", drive->name);
+ 			}
+ 			info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
+ 		}
+-		if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
++		if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
+ 			action = cdrom_start_seek(drive, block);
+-		} else
++		else
+ 			action = cdrom_start_rw(drive, rq);
+ 		info->last_block = block;
+ 		return action;
+@@ -1372,7 +1273,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+  */
+ 
+ static
+-void msf_from_bcd (struct atapi_msf *msf)
++void msf_from_bcd(struct atapi_msf *msf)
+ {
+ 	msf->minute = BCD2BIN(msf->minute);
+ 	msf->second = BCD2BIN(msf->second);
+@@ -1472,7 +1373,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 		/* Try to allocate space. */
+ 		toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
+ 		if (toc == NULL) {
+-			printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
++			printk(KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
+ 			return -ENOMEM;
+ 		}
+ 		info->toc = toc;
+@@ -1567,9 +1468,9 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 				toc->ent[i].track = BCD2BIN(toc->ent[i].track);
+ 			msf_from_bcd(&toc->ent[i].addr.msf);
+ 		}
+-		toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
+-						   toc->ent[i].addr.msf.second,
+-						   toc->ent[i].addr.msf.frame);
++		toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute,
++						  toc->ent[i].addr.msf.second,
++						  toc->ent[i].addr.msf.frame);
+ 	}
+ 
+ 	/* Read the multisession information. */
+@@ -1593,9 +1494,9 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 		if (stat)
+ 			return stat;
+ 
+-		msf_from_bcd (&ms_tmp.ent.addr.msf);
++		msf_from_bcd(&ms_tmp.ent.addr.msf);
+ 		toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
+-					  	   ms_tmp.ent.addr.msf.second,
++						   ms_tmp.ent.addr.msf.second,
+ 						   ms_tmp.ent.addr.msf.frame);
+ 	}
+ 
+@@ -1677,7 +1578,7 @@ static struct cdrom_device_ops ide_cdrom_dops = {
+ 	.generic_packet		= ide_cdrom_packet,
+ };
+ 
+-static int ide_cdrom_register (ide_drive_t *drive, int nslots)
++static int ide_cdrom_register(ide_drive_t *drive, int nslots)
+ {
+ 	struct cdrom_info *info = drive->driver_data;
+ 	struct cdrom_device_info *devinfo = &info->devinfo;
+@@ -1696,7 +1597,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
+ }
+ 
+ static
+-int ide_cdrom_probe_capabilities (ide_drive_t *drive)
++int ide_cdrom_probe_capabilities(ide_drive_t *drive)
+ {
+ 	struct cdrom_info *cd = drive->driver_data;
+ 	struct cdrom_device_info *cdi = &cd->devinfo;
+@@ -1868,7 +1769,7 @@ static int ide_cdrom_prep_pc(struct request *rq)
+ 		rq->errors = ILLEGAL_REQUEST;
+ 		return BLKPREP_KILL;
+ 	}
+-	
++
+ 	return BLKPREP_OK;
+ }
+ 
+@@ -1946,7 +1847,7 @@ static unsigned int ide_cd_flags(struct hd_driveid *id)
+ }
+ 
+ static
+-int ide_cdrom_setup (ide_drive_t *drive)
++int ide_cdrom_setup(ide_drive_t *drive)
+ {
+ 	struct cdrom_info *cd = drive->driver_data;
+ 	struct cdrom_device_info *cdi = &cd->devinfo;
+@@ -1977,7 +1878,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
+ 	else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
+ 		cdi->sanyo_slot = 3;	/* 3 => use CD in slot 0 */
+ 
+-	nslots = ide_cdrom_probe_capabilities (drive);
++	nslots = ide_cdrom_probe_capabilities(drive);
+ 
+ 	/*
+ 	 * set correct block size
+@@ -1989,7 +1890,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
+ 		drive->dsc_overlap = (drive->next != drive);
+ 
+ 	if (ide_cdrom_register(drive, nslots)) {
+-		printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
++		printk(KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
+ 		cd->devinfo.handle = NULL;
+ 		return 1;
+ 	}
+@@ -1997,19 +1898,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_IDE_PROC_FS
+-static
+-sector_t ide_cdrom_capacity (ide_drive_t *drive)
+-{
+-	unsigned long capacity, sectors_per_frame;
+-
+-	if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
+-		return 0;
+-
+-	return capacity * sectors_per_frame;
+-}
+-#endif
+-
+ static void ide_cd_remove(ide_drive_t *drive)
+ {
+ 	struct cdrom_info *info = drive->driver_data;
+@@ -2028,11 +1916,9 @@ static void ide_cd_release(struct kref *kref)
+ 	ide_drive_t *drive = info->drive;
+ 	struct gendisk *g = info->disk;
+ 
+-	kfree(info->buffer);
+ 	kfree(info->toc);
+-	if (devinfo->handle == drive && unregister_cdrom(devinfo))
+-		printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
+-				"driver.\n", __FUNCTION__, drive->name);
++	if (devinfo->handle == drive)
++		unregister_cdrom(devinfo);
+ 	drive->dsc_overlap = 0;
+ 	drive->driver_data = NULL;
+ 	blk_queue_prep_rq(drive->queue, NULL);
+@@ -2044,14 +1930,24 @@ static void ide_cd_release(struct kref *kref)
+ static int ide_cd_probe(ide_drive_t *);
+ 
+ #ifdef CONFIG_IDE_PROC_FS
++static sector_t ide_cdrom_capacity(ide_drive_t *drive)
++{
++	unsigned long capacity, sectors_per_frame;
++
++	if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
++		return 0;
++
++	return capacity * sectors_per_frame;
++}
++
+ static int proc_idecd_read_capacity
+ 	(char *page, char **start, off_t off, int count, int *eof, void *data)
+ {
+ 	ide_drive_t *drive = data;
+ 	int len;
+ 
+-	len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	len = sprintf(page, "%llu\n", (long long)ide_cdrom_capacity(drive));
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ static ide_proc_entry_t idecd_proc[] = {
+@@ -2080,20 +1976,17 @@ static ide_driver_t ide_cdrom_driver = {
+ #endif
+ };
+ 
+-static int idecd_open(struct inode * inode, struct file * file)
++static int idecd_open(struct inode *inode, struct file *file)
+ {
+ 	struct gendisk *disk = inode->i_bdev->bd_disk;
+ 	struct cdrom_info *info;
+ 	int rc = -ENOMEM;
+ 
+-	if (!(info = ide_cd_get(disk)))
++	info = ide_cd_get(disk);
++	if (!info)
+ 		return -ENXIO;
+ 
+-	if (!info->buffer)
+-		info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
+-
+-	if (info->buffer)
+-		rc = cdrom_open(&info->devinfo, inode, file);
++	rc = cdrom_open(&info->devinfo, inode, file);
+ 
+ 	if (rc < 0)
+ 		ide_cd_put(info);
+@@ -2101,12 +1994,12 @@ static int idecd_open(struct inode * inode, struct file * file)
+ 	return rc;
+ }
+ 
+-static int idecd_release(struct inode * inode, struct file * file)
++static int idecd_release(struct inode *inode, struct file *file)
+ {
+ 	struct gendisk *disk = inode->i_bdev->bd_disk;
+ 	struct cdrom_info *info = ide_cd_g(disk);
+ 
+-	cdrom_release (&info->devinfo, file);
++	cdrom_release(&info->devinfo, file);
+ 
+ 	ide_cd_put(info);
+ 
+@@ -2138,7 +2031,7 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
+ 	struct packet_command cgc;
+ 	char buffer[16];
+ 	int stat;
+- 	char spindown;
++	char spindown;
+ 
+ 	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
+ 
+@@ -2147,12 +2040,12 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
+ 		return stat;
+ 
+ 	spindown = buffer[11] & 0x0f;
+-	if (copy_to_user((void __user *)arg, &spindown, sizeof (char)))
++	if (copy_to_user((void __user *)arg, &spindown, sizeof(char)))
+ 		return -EFAULT;
+ 	return 0;
+ }
+ 
+-static int idecd_ioctl (struct inode *inode, struct file *file,
++static int idecd_ioctl(struct inode *inode, struct file *file,
+ 			unsigned int cmd, unsigned long arg)
+ {
+ 	struct block_device *bdev = inode->i_bdev;
+@@ -2160,13 +2053,13 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
+ 	int err;
+ 
+ 	switch (cmd) {
+- 	case CDROMSETSPINDOWN:
++	case CDROMSETSPINDOWN:
+ 		return idecd_set_spindown(&info->devinfo, arg);
+- 	case CDROMGETSPINDOWN:
++	case CDROMGETSPINDOWN:
+ 		return idecd_get_spindown(&info->devinfo, arg);
+ 	default:
+ 		break;
+- 	}
++	}
+ 
+ 	err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
+ 	if (err == -EINVAL)
+@@ -2192,16 +2085,16 @@ static int idecd_revalidate_disk(struct gendisk *disk)
+ }
+ 
+ static struct block_device_operations idecd_ops = {
+-	.owner		= THIS_MODULE,
+-	.open		= idecd_open,
+-	.release	= idecd_release,
+-	.ioctl		= idecd_ioctl,
+-	.media_changed	= idecd_media_changed,
+-	.revalidate_disk= idecd_revalidate_disk
++	.owner			= THIS_MODULE,
++	.open			= idecd_open,
++	.release		= idecd_release,
++	.ioctl			= idecd_ioctl,
++	.media_changed		= idecd_media_changed,
++	.revalidate_disk	= idecd_revalidate_disk
+ };
+ 
+ /* options */
+-static char *ignore = NULL;
++static char *ignore;
+ 
+ module_param(ignore, charp, 0400);
+ MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
+diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
+index 22e3751..a58801c 100644
+--- a/drivers/ide/ide-cd.h
++++ b/drivers/ide/ide-cd.h
+@@ -119,10 +119,6 @@ struct cdrom_info {
+ 
+ 	struct atapi_toc *toc;
+ 
+-	unsigned long	sector_buffered;
+-	unsigned long	nsectors_buffered;
+-	unsigned char	*buffer;
+-
+ 	/* The result of the last successful request sense command
+ 	   on this device. */
+ 	struct request_sense sense_data;
+diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
+index 39501d1..8e08d08 100644
+--- a/drivers/ide/ide-disk.c
++++ b/drivers/ide/ide-disk.c
+@@ -16,8 +16,6 @@
+ 
+ #define IDEDISK_VERSION	"1.18"
+ 
+-//#define DEBUG
+-
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+@@ -88,7 +86,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp)
+  *
+  * It is called only once for each drive.
+  */
+-static int lba_capacity_is_ok (struct hd_driveid *id)
++static int lba_capacity_is_ok(struct hd_driveid *id)
+ {
+ 	unsigned long lba_sects, chs_sects, head, tail;
+ 
+@@ -176,7 +174,8 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
+  * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
+  * using LBA if supported, or CHS otherwise, to address sectors.
+  */
+-static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
++static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
++					sector_t block)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+ 	unsigned int dma	= drive->using_dma;
+@@ -228,7 +227,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+ 			tf->device = (block >> 8) & 0xf;
+ 		}
+ 	} else {
+-		unsigned int sect,head,cyl,track;
++		unsigned int sect, head, cyl, track;
++
+ 		track = (int)block / drive->sect;
+ 		sect  = (int)block % drive->sect + 1;
+ 		head  = track % drive->head;
+@@ -271,7 +271,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+  * 1073741822 == 549756 MB or 48bit addressing fake drive
+  */
+ 
+-static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
++static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
++				      sector_t block)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+ 
+@@ -452,7 +453,7 @@ static void idedisk_check_hpa(ide_drive_t *drive)
+  * in above order (i.e., if value of higher priority is available,
+  * reset will be ignored).
+  */
+-static void init_idedisk_capacity (ide_drive_t  *drive)
++static void init_idedisk_capacity(ide_drive_t *drive)
+ {
+ 	struct hd_driveid *id = drive->id;
+ 	/*
+@@ -479,7 +480,7 @@ static void init_idedisk_capacity (ide_drive_t  *drive)
+ 	}
+ }
+ 
+-static sector_t idedisk_capacity (ide_drive_t *drive)
++static sector_t idedisk_capacity(ide_drive_t *drive)
+ {
+ 	return drive->capacity64 - drive->sect0;
+ }
+@@ -524,10 +525,11 @@ static int proc_idedisk_read_cache
+ 	int		len;
+ 
+ 	if (drive->id_read)
+-		len = sprintf(out,"%i\n", drive->id->buf_size / 2);
++		len = sprintf(out, "%i\n", drive->id->buf_size / 2);
+ 	else
+-		len = sprintf(out,"(none)\n");
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++		len = sprintf(out, "(none)\n");
++
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ static int proc_idedisk_read_capacity
+@@ -536,54 +538,52 @@ static int proc_idedisk_read_capacity
+ 	ide_drive_t*drive = (ide_drive_t *)data;
+ 	int len;
+ 
+-	len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive));
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
++
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+-static int proc_idedisk_read_smart_thresholds
+-	(char *page, char **start, off_t off, int count, int *eof, void *data)
++static int proc_idedisk_read_smart(char *page, char **start, off_t off,
++				   int count, int *eof, void *data, u8 sub_cmd)
+ {
+ 	ide_drive_t	*drive = (ide_drive_t *)data;
+ 	int		len = 0, i = 0;
+ 
+-	if (get_smart_data(drive, page, SMART_READ_THRESHOLDS) == 0) {
++	if (get_smart_data(drive, page, sub_cmd) == 0) {
+ 		unsigned short *val = (unsigned short *) page;
+ 		char *out = ((char *)val) + (SECTOR_WORDS * 4);
+ 		page = out;
+ 		do {
+-			out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
++			out += sprintf(out, "%04x%c", le16_to_cpu(*val),
++				       (++i & 7) ? ' ' : '\n');
+ 			val += 1;
+ 		} while (i < (SECTOR_WORDS * 2));
+ 		len = out - page;
+ 	}
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+-static int proc_idedisk_read_smart_values
++static int proc_idedisk_read_sv
+ 	(char *page, char **start, off_t off, int count, int *eof, void *data)
+ {
+-	ide_drive_t	*drive = (ide_drive_t *)data;
+-	int		len = 0, i = 0;
++	return proc_idedisk_read_smart(page, start, off, count, eof, data,
++				       SMART_READ_VALUES);
++}
+ 
+-	if (get_smart_data(drive, page, SMART_READ_VALUES) == 0) {
+-		unsigned short *val = (unsigned short *) page;
+-		char *out = ((char *)val) + (SECTOR_WORDS * 4);
+-		page = out;
+-		do {
+-			out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+-			val += 1;
+-		} while (i < (SECTOR_WORDS * 2));
+-		len = out - page;
+-	}
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++static int proc_idedisk_read_st
++	(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++	return proc_idedisk_read_smart(page, start, off, count, eof, data,
++				       SMART_READ_THRESHOLDS);
+ }
+ 
+ static ide_proc_entry_t idedisk_proc[] = {
+-	{ "cache",		S_IFREG|S_IRUGO,	proc_idedisk_read_cache,		NULL },
+-	{ "capacity",		S_IFREG|S_IRUGO,	proc_idedisk_read_capacity,		NULL },
+-	{ "geometry",		S_IFREG|S_IRUGO,	proc_ide_read_geometry,			NULL },
+-	{ "smart_values",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_values,		NULL },
+-	{ "smart_thresholds",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_thresholds,	NULL },
++	{ "cache",	  S_IFREG|S_IRUGO, proc_idedisk_read_cache,    NULL },
++	{ "capacity",	  S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
++	{ "geometry",	  S_IFREG|S_IRUGO, proc_ide_read_geometry,     NULL },
++	{ "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv,       NULL },
++	{ "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st,   NULL },
+ 	{ NULL, 0, NULL, NULL }
+ };
+ #endif	/* CONFIG_IDE_PROC_FS */
+@@ -625,12 +625,13 @@ static int set_multcount(ide_drive_t *drive, int arg)
+ 	if (drive->special.b.set_multmode)
+ 		return -EBUSY;
+ 
+-	ide_init_drive_cmd (&rq);
++	ide_init_drive_cmd(&rq);
+ 	rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+ 
+ 	drive->mult_req = arg;
+ 	drive->special.b.set_multmode = 1;
+-	(void) ide_do_drive_cmd (drive, &rq, ide_wait);
++	(void)ide_do_drive_cmd(drive, &rq, ide_wait);
++
+ 	return (drive->mult_count == arg) ? 0 : -EIO;
+ }
+ 
+@@ -706,7 +707,7 @@ static int write_cache(ide_drive_t *drive, int arg)
+ 	return err;
+ }
+ 
+-static int do_idedisk_flushcache (ide_drive_t *drive)
++static int do_idedisk_flushcache(ide_drive_t *drive)
+ {
+ 	ide_task_t args;
+ 
+@@ -719,7 +720,7 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
+ 	return ide_no_data_taskfile(drive, &args);
+ }
+ 
+-static int set_acoustic (ide_drive_t *drive, int arg)
++static int set_acoustic(ide_drive_t *drive, int arg)
+ {
+ 	ide_task_t args;
+ 
+@@ -753,7 +754,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg)
+ 		return 0;
+ 
+ 	if (!idedisk_supports_lba48(drive->id))
+-                return -EIO;
++		return -EIO;
+ 	drive->addressing = arg;
+ 	return 0;
+ }
+@@ -763,23 +764,35 @@ static void idedisk_add_settings(ide_drive_t *drive)
+ {
+ 	struct hd_driveid *id = drive->id;
+ 
+-	ide_add_setting(drive,	"bios_cyl",	SETTING_RW,	TYPE_INT,	0,	65535,			1,	1,	&drive->bios_cyl,	NULL);
+-	ide_add_setting(drive,	"bios_head",	SETTING_RW,	TYPE_BYTE,	0,	255,			1,	1,	&drive->bios_head,	NULL);
+-	ide_add_setting(drive,	"bios_sect",	SETTING_RW,	TYPE_BYTE,	0,	63,			1,	1,	&drive->bios_sect,	NULL);
+-	ide_add_setting(drive,	"address",	SETTING_RW,	TYPE_BYTE,	0,	2,			1,	1,	&drive->addressing,	set_lba_addressing);
+-	ide_add_setting(drive,	"multcount",	SETTING_RW,	TYPE_BYTE,	0,	id->max_multsect,	1,	1,	&drive->mult_count,	set_multcount);
+-	ide_add_setting(drive,	"nowerr",	SETTING_RW,	TYPE_BYTE,	0,	1,			1,	1,	&drive->nowerr,		set_nowerr);
+-	ide_add_setting(drive,	"lun",		SETTING_RW,	TYPE_INT,	0,	7,			1,	1,	&drive->lun,		NULL);
+-	ide_add_setting(drive,	"wcache",	SETTING_RW,	TYPE_BYTE,	0,	1,			1,	1,	&drive->wcache,		write_cache);
+-	ide_add_setting(drive,	"acoustic",	SETTING_RW,	TYPE_BYTE,	0,	254,			1,	1,	&drive->acoustic,	set_acoustic);
+- 	ide_add_setting(drive,	"failures",	SETTING_RW,	TYPE_INT,	0,	65535,			1,	1,	&drive->failures,	NULL);
+- 	ide_add_setting(drive,	"max_failures",	SETTING_RW,	TYPE_INT,	0,	65535,			1,	1,	&drive->max_failures,	NULL);
++	ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
++			&drive->bios_cyl, NULL);
++	ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
++			&drive->bios_head, NULL);
++	ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
++			&drive->bios_sect, NULL);
++	ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
++			&drive->addressing, set_lba_addressing);
++	ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
++			id->max_multsect, 1, 1, &drive->mult_count,
++			set_multcount);
++	ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
++			&drive->nowerr, set_nowerr);
++	ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
++			&drive->lun, NULL);
++	ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
++			&drive->wcache, write_cache);
++	ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
++			&drive->acoustic, set_acoustic);
++	ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
++			&drive->failures, NULL);
++	ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
++			1, 1, &drive->max_failures, NULL);
+ }
+ #else
+ static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
+ #endif
+ 
+-static void idedisk_setup (ide_drive_t *drive)
++static void idedisk_setup(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	struct hd_driveid *id = drive->id;
+@@ -792,11 +805,10 @@ static void idedisk_setup (ide_drive_t *drive)
+ 
+ 	if (drive->removable) {
+ 		/*
+-		 * Removable disks (eg. SYQUEST); ignore 'WD' drives 
++		 * Removable disks (eg. SYQUEST); ignore 'WD' drives
+ 		 */
+-		if (id->model[0] != 'W' || id->model[1] != 'D') {
++		if (id->model[0] != 'W' || id->model[1] != 'D')
+ 			drive->doorlocking = 1;
+-		}
+ 	}
+ 
+ 	(void)set_lba_addressing(drive, 1);
+@@ -810,10 +822,11 @@ static void idedisk_setup (ide_drive_t *drive)
+ 		blk_queue_max_sectors(drive->queue, max_s);
+ 	}
+ 
+-	printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
++	printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
++			 drive->queue->max_sectors / 2);
+ 
+ 	/* calculate drive capacity, and select LBA if possible */
+-	init_idedisk_capacity (drive);
++	init_idedisk_capacity(drive);
+ 
+ 	/* limit drive capacity to 137GB if LBA48 cannot be used */
+ 	if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
+@@ -826,9 +839,9 @@ static void idedisk_setup (ide_drive_t *drive)
+ 
+ 	if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
+ 		if (drive->capacity64 > 1ULL << 28) {
+-			printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will"
+-					 " be used for accessing sectors > %u\n",
+-					 drive->name, 1 << 28);
++			printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
++					 " will be used for accessing sectors "
++					 "> %u\n", drive->name, 1 << 28);
+ 		} else
+ 			drive->addressing = 0;
+ 	}
+@@ -837,7 +850,8 @@ static void idedisk_setup (ide_drive_t *drive)
+ 	 * if possible, give fdisk access to more of the drive,
+ 	 * by correcting bios_cyls:
+ 	 */
+-	capacity = idedisk_capacity (drive);
++	capacity = idedisk_capacity(drive);
++
+ 	if (!drive->forced_geom) {
+ 
+ 		if (idedisk_supports_lba48(drive->id)) {
+@@ -993,7 +1007,8 @@ static int idedisk_open(struct inode *inode, struct file *filp)
+ 	struct ide_disk_obj *idkp;
+ 	ide_drive_t *drive;
+ 
+-	if (!(idkp = ide_disk_get(disk)))
++	idkp = ide_disk_get(disk);
++	if (idkp == NULL)
+ 		return -ENXIO;
+ 
+ 	drive = idkp->drive;
+@@ -1115,13 +1130,13 @@ static int idedisk_revalidate_disk(struct gendisk *disk)
+ }
+ 
+ static struct block_device_operations idedisk_ops = {
+-	.owner		= THIS_MODULE,
+-	.open		= idedisk_open,
+-	.release	= idedisk_release,
+-	.ioctl		= idedisk_ioctl,
+-	.getgeo		= idedisk_getgeo,
+-	.media_changed	= idedisk_media_changed,
+-	.revalidate_disk= idedisk_revalidate_disk
++	.owner			= THIS_MODULE,
++	.open			= idedisk_open,
++	.release		= idedisk_release,
++	.ioctl			= idedisk_ioctl,
++	.getgeo			= idedisk_getgeo,
++	.media_changed		= idedisk_media_changed,
++	.revalidate_disk	= idedisk_revalidate_disk
+ };
+ 
+ MODULE_DESCRIPTION("ATA DISK Driver");
+@@ -1184,7 +1199,7 @@ failed:
+ 	return -ENODEV;
+ }
+ 
+-static void __exit idedisk_exit (void)
++static void __exit idedisk_exit(void)
+ {
+ 	driver_unregister(&idedisk_driver.gen_driver);
+ }
+diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
+index d61e578..8757e5e 100644
+--- a/drivers/ide/ide-dma.c
++++ b/drivers/ide/ide-dma.c
+@@ -703,17 +703,8 @@ static int ide_tune_dma(ide_drive_t *drive)
+ 
+ 	speed = ide_max_dma_mode(drive);
+ 
+-	if (!speed) {
+-		 /* is this really correct/needed? */
+-		if ((hwif->host_flags & IDE_HFLAG_CY82C693) &&
+-		    ide_dma_good_drive(drive))
+-			return 1;
+-		else
+-			return 0;
+-	}
+-
+-	if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+-		return 1;
++	if (!speed)
++		return 0;
+ 
+ 	if (ide_set_dma_mode(drive, speed))
+ 		return 0;
+diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
+index faf22d7..ed19a8b 100644
+--- a/drivers/ide/ide-floppy.c
++++ b/drivers/ide/ide-floppy.c
+@@ -78,40 +78,6 @@
+  */
+ #define IDEFLOPPY_PC_STACK		(10 + IDEFLOPPY_MAX_PC_RETRIES)
+ 
+-typedef struct idefloppy_packet_command_s {
+-	u8 c[12];				/* Actual packet bytes */
+-	int retries;				/* On each retry, we increment
+-						   retries */
+-	int error;				/* Error code */
+-	int request_transfer;			/* Bytes to transfer */
+-	int actually_transferred;		/* Bytes actually transferred */
+-	int buffer_size;			/* Size of our data buffer */
+-	int b_count;				/* Missing/Available data on
+-						   the current buffer */
+-	struct request *rq;			/* The corresponding request */
+-	u8 *buffer;				/* Data buffer */
+-	u8 *current_position;			/* Pointer into above buffer */
+-	void (*callback) (ide_drive_t *);	/* Called when this packet
+-						   command is completed */
+-	u8 pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE];	/* Temporary buffer */
+-	unsigned long flags;			/* Status/Action bit flags: long
+-						   for set_bit */
+-} idefloppy_pc_t;
+-
+-/* Packet command flag bits. */
+-enum {
+-	/* 1 when we prefer to use DMA if possible */
+-	PC_FLAG_DMA_RECOMMENDED	= (1 << 0),
+-	/* 1 while DMA in progress */
+-	PC_FLAG_DMA_IN_PROGRESS	= (1 << 1),
+-	/* 1 when encountered problem during DMA */
+-	PC_FLAG_DMA_ERROR	= (1 << 2),
+-	/* Data direction */
+-	PC_FLAG_WRITING		= (1 << 3),
+-	/* Suppress error reporting */
+-	PC_FLAG_SUPPRESS_ERROR	= (1 << 4),
+-};
+-
+ /* format capacities descriptor codes */
+ #define CAPACITY_INVALID	0x00
+ #define CAPACITY_UNFORMATTED	0x01
+@@ -131,11 +97,11 @@ typedef struct ide_floppy_obj {
+ 	unsigned int	openers;	/* protected by BKL for now */
+ 
+ 	/* Current packet command */
+-	idefloppy_pc_t *pc;
++	struct ide_atapi_pc *pc;
+ 	/* Last failed packet command */
+-	idefloppy_pc_t *failed_pc;
++	struct ide_atapi_pc *failed_pc;
+ 	/* Packet command stack */
+-	idefloppy_pc_t pc_stack[IDEFLOPPY_PC_STACK];
++	struct ide_atapi_pc pc_stack[IDEFLOPPY_PC_STACK];
+ 	/* Next free packet command storage space */
+ 	int pc_stack_index;
+ 	struct request rq_stack[IDEFLOPPY_PC_STACK];
+@@ -195,32 +161,6 @@ enum {
+ #define	IDEFLOPPY_ERROR_GENERAL		101
+ 
+ /*
+- * The following is used to format the general configuration word of the
+- * ATAPI IDENTIFY DEVICE command.
+- */
+-struct idefloppy_id_gcw {
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+-	unsigned packet_size		:2;	/* Packet Size */
+-	unsigned reserved234		:3;	/* Reserved */
+-	unsigned drq_type		:2;	/* Command packet DRQ type */
+-	unsigned removable		:1;	/* Removable media */
+-	unsigned device_type		:5;	/* Device type */
+-	unsigned reserved13		:1;	/* Reserved */
+-	unsigned protocol		:2;	/* Protocol type */
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+-	unsigned protocol		:2;	/* Protocol type */
+-	unsigned reserved13		:1;	/* Reserved */
+-	unsigned device_type		:5;	/* Device type */
+-	unsigned removable		:1;	/* Removable media */
+-	unsigned drq_type		:2;	/* Command packet DRQ type */
+-	unsigned reserved234		:3;	/* Reserved */
+-	unsigned packet_size		:2;	/* Packet Size */
+-#else
+-#error "Bitfield endianness not defined! Check your byteorder.h"
+-#endif
+-};
+-
+-/*
+  * Pages of the SELECT SENSE / MODE SENSE packet commands.
+  * See SFF-8070i spec.
+  */
+@@ -256,27 +196,10 @@ static void ide_floppy_put(struct ide_floppy_obj *floppy)
+ }
+ 
+ /*
+- * Too bad. The drive wants to send us data which we are not ready to accept.
+- * Just throw it away.
+- */
+-static void idefloppy_discard_data(ide_drive_t *drive, unsigned int bcount)
+-{
+-	while (bcount--)
+-		(void) HWIF(drive)->INB(IDE_DATA_REG);
+-}
+-
+-static void idefloppy_write_zeros(ide_drive_t *drive, unsigned int bcount)
+-{
+-	while (bcount--)
+-		HWIF(drive)->OUTB(0, IDE_DATA_REG);
+-}
+-
+-
+-/*
+  * Used to finish servicing a request. For read/write requests, we will call
+  * ide_end_request to pass to the next buffer.
+  */
+-static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
++static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	struct request *rq = HWGROUP(drive)->rq;
+@@ -305,7 +228,7 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
+ 	return 0;
+ }
+ 
+-static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc,
++static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ 				  unsigned int bcount, int direction)
+ {
+ 	struct request *rq = pc->rq;
+@@ -333,26 +256,26 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc,
+ 		done += count;
+ 	}
+ 
+-	idefloppy_do_end_request(drive, 1, done >> 9);
++	idefloppy_end_request(drive, 1, done >> 9);
+ 
+ 	if (bcount) {
+ 		printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
+ 				drive->name, __func__, bcount);
+ 		if (direction)
+-			idefloppy_write_zeros(drive, bcount);
++			ide_atapi_write_zeros(drive, bcount);
+ 		else
+-			idefloppy_discard_data(drive, bcount);
+-
++			ide_atapi_discard_data(drive, bcount);
+ 	}
+ }
+ 
+-static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc)
++static void idefloppy_update_buffers(ide_drive_t *drive,
++				struct ide_atapi_pc *pc)
+ {
+ 	struct request *rq = pc->rq;
+ 	struct bio *bio = rq->bio;
+ 
+ 	while ((bio = rq->bio) != NULL)
+-		idefloppy_do_end_request(drive, 1, 0);
++		idefloppy_end_request(drive, 1, 0);
+ }
+ 
+ /*
+@@ -360,7 +283,7 @@ static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc)
+  * the current request so that it will be processed immediately, on the next
+  * pass through the driver.
+  */
+-static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc,
++static void idefloppy_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ 		struct request *rq)
+ {
+ 	struct ide_floppy_obj *floppy = drive->driver_data;
+@@ -372,7 +295,7 @@ static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc,
+ 	(void) ide_do_drive_cmd(drive, rq, ide_preempt);
+ }
+ 
+-static idefloppy_pc_t *idefloppy_next_pc_storage(ide_drive_t *drive)
++static struct ide_atapi_pc *idefloppy_next_pc_storage(ide_drive_t *drive)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 
+@@ -393,7 +316,7 @@ static struct request *idefloppy_next_rq_storage(ide_drive_t *drive)
+ static void idefloppy_request_sense_callback(ide_drive_t *drive)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	u8 *buf = floppy->pc->buffer;
++	u8 *buf = floppy->pc->buf;
+ 
+ 	debug_log("Reached %s\n", __func__);
+ 
+@@ -418,11 +341,11 @@ static void idefloppy_request_sense_callback(ide_drive_t *drive)
+ 					floppy->ascq);
+ 
+ 
+-		idefloppy_do_end_request(drive, 1, 0);
++		idefloppy_end_request(drive, 1, 0);
+ 	} else {
+ 		printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting"
+ 				" request!\n");
+-		idefloppy_do_end_request(drive, 0, 0);
++		idefloppy_end_request(drive, 0, 0);
+ 	}
+ }
+ 
+@@ -433,27 +356,27 @@ static void idefloppy_pc_callback(ide_drive_t *drive)
+ 
+ 	debug_log("Reached %s\n", __func__);
+ 
+-	idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0);
++	idefloppy_end_request(drive, floppy->pc->error ? 0 : 1, 0);
+ }
+ 
+-static void idefloppy_init_pc(idefloppy_pc_t *pc)
++static void idefloppy_init_pc(struct ide_atapi_pc *pc)
+ {
+ 	memset(pc->c, 0, 12);
+ 	pc->retries = 0;
+ 	pc->flags = 0;
+-	pc->request_transfer = 0;
+-	pc->buffer = pc->pc_buffer;
+-	pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE;
+-	pc->callback = &idefloppy_pc_callback;
++	pc->req_xfer = 0;
++	pc->buf = pc->pc_buf;
++	pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE;
++	pc->idefloppy_callback = &idefloppy_pc_callback;
+ }
+ 
+-static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc)
++static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
+ {
+ 	idefloppy_init_pc(pc);
+ 	pc->c[0] = GPCMD_REQUEST_SENSE;
+ 	pc->c[4] = 255;
+-	pc->request_transfer = 18;
+-	pc->callback = &idefloppy_request_sense_callback;
++	pc->req_xfer = 18;
++	pc->idefloppy_callback = &idefloppy_request_sense_callback;
+ }
+ 
+ /*
+@@ -462,7 +385,7 @@ static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc)
+  */
+ static void idefloppy_retry_pc(ide_drive_t *drive)
+ {
+-	idefloppy_pc_t *pc;
++	struct ide_atapi_pc *pc;
+ 	struct request *rq;
+ 
+ 	(void)ide_read_error(drive);
+@@ -473,11 +396,11 @@ static void idefloppy_retry_pc(ide_drive_t *drive)
+ }
+ 
+ /* The usual interrupt handler called during a packet command. */
+-static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
++static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	ide_hwif_t *hwif = drive->hwif;
+-	idefloppy_pc_t *pc = floppy->pc;
++	struct ide_atapi_pc *pc = floppy->pc;
+ 	struct request *rq = pc->rq;
+ 	xfer_func_t *xferfunc;
+ 	unsigned int temp;
+@@ -494,7 +417,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ 					rq_data_dir(rq) ? "write" : "read");
+ 			pc->flags |= PC_FLAG_DMA_ERROR;
+ 		} else {
+-			pc->actually_transferred = pc->request_transfer;
++			pc->xferred = pc->req_xfer;
+ 			idefloppy_update_buffers(drive, pc);
+ 		}
+ 		debug_log("DMA finished\n");
+@@ -506,7 +429,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ 	/* No more interrupts */
+ 	if ((stat & DRQ_STAT) == 0) {
+ 		debug_log("Packet command completed, %d bytes transferred\n",
+-				pc->actually_transferred);
++				pc->xferred);
+ 		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+ 
+ 		local_irq_enable_in_hardirq();
+@@ -529,7 +452,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ 		if (floppy->failed_pc == pc)
+ 			floppy->failed_pc = NULL;
+ 		/* Command finished - Call the callback function */
+-		pc->callback(drive);
++		pc->idefloppy_callback(drive);
+ 		return ide_stopped;
+ 	}
+ 
+@@ -542,10 +465,10 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ 	}
+ 
+ 	/* Get the number of bytes to transfer */
+-	bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
+-		  hwif->INB(IDE_BCOUNTL_REG);
++	bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
++		  hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
+ 	/* on this interrupt */
+-	ireason = hwif->INB(IDE_IREASON_REG);
++	ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ 
+ 	if (ireason & CD) {
+ 		printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__);
+@@ -561,13 +484,13 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ 	}
+ 	if (!(pc->flags & PC_FLAG_WRITING)) {
+ 		/* Reading - Check that we have enough space */
+-		temp = pc->actually_transferred + bcount;
+-		if (temp > pc->request_transfer) {
+-			if (temp > pc->buffer_size) {
++		temp = pc->xferred + bcount;
++		if (temp > pc->req_xfer) {
++			if (temp > pc->buf_size) {
+ 				printk(KERN_ERR "ide-floppy: The floppy wants "
+ 					"to send us more data than expected "
+ 					"- discarding data\n");
+-				idefloppy_discard_data(drive, bcount);
++				ide_atapi_discard_data(drive, bcount);
+ 
+ 				ide_set_handler(drive,
+ 						&idefloppy_pc_intr,
+@@ -584,15 +507,15 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ 	else
+ 		xferfunc = hwif->atapi_input_bytes;
+ 
+-	if (pc->buffer)
+-		xferfunc(drive, pc->current_position, bcount);
++	if (pc->buf)
++		xferfunc(drive, pc->cur_pos, bcount);
+ 	else
+ 		ide_floppy_io_buffers(drive, pc, bcount,
+ 				      !!(pc->flags & PC_FLAG_WRITING));
+ 
+ 	/* Update the current position */
+-	pc->actually_transferred += bcount;
+-	pc->current_position += bcount;
++	pc->xferred += bcount;
++	pc->cur_pos += bcount;
+ 
+ 	/* And set the interrupt handler again */
+ 	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
+@@ -606,6 +529,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+  */
+ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
+ {
++	ide_hwif_t *hwif = drive->hwif;
+ 	ide_startstop_t startstop;
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	u8 ireason;
+@@ -615,7 +539,7 @@ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
+ 				"initiated yet DRQ isn't asserted\n");
+ 		return startstop;
+ 	}
+-	ireason = drive->hwif->INB(IDE_IREASON_REG);
++	ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ 	if ((ireason & CD) == 0 || (ireason & IO)) {
+ 		printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
+ 				"issuing a packet command\n");
+@@ -652,6 +576,7 @@ static int idefloppy_transfer_pc2(ide_drive_t *drive)
+ 
+ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
+ {
++	ide_hwif_t *hwif = drive->hwif;
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	ide_startstop_t startstop;
+ 	u8 ireason;
+@@ -661,7 +586,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
+ 				"initiated yet DRQ isn't asserted\n");
+ 		return startstop;
+ 	}
+-	ireason = drive->hwif->INB(IDE_IREASON_REG);
++	ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ 	if ((ireason & CD) == 0 || (ireason & IO)) {
+ 		printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
+ 				"while issuing a packet command\n");
+@@ -682,7 +607,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
+ }
+ 
+ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
+-				    idefloppy_pc_t *pc)
++				    struct ide_atapi_pc *pc)
+ {
+ 	/* supress error messages resulting from Medium not present */
+ 	if (floppy->sense_key == 0x02 &&
+@@ -698,7 +623,7 @@ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
+ }
+ 
+ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+-		idefloppy_pc_t *pc)
++		struct ide_atapi_pc *pc)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	ide_hwif_t *hwif = drive->hwif;
+@@ -719,7 +644,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ 		pc->error = IDEFLOPPY_ERROR_GENERAL;
+ 
+ 		floppy->failed_pc = NULL;
+-		pc->callback(drive);
++		pc->idefloppy_callback(drive);
+ 		return ide_stopped;
+ 	}
+ 
+@@ -727,9 +652,9 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ 
+ 	pc->retries++;
+ 	/* We haven't transferred any data yet */
+-	pc->actually_transferred = 0;
+-	pc->current_position = pc->buffer;
+-	bcount = min(pc->request_transfer, 63 * 1024);
++	pc->xferred = 0;
++	pc->cur_pos = pc->buf;
++	bcount = min(pc->req_xfer, 63 * 1024);
+ 
+ 	if (pc->flags & PC_FLAG_DMA_ERROR) {
+ 		pc->flags &= ~PC_FLAG_DMA_ERROR;
+@@ -757,7 +682,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ 		/* immediate */
+ 		pkt_xfer_routine = &idefloppy_transfer_pc;
+ 	}
+-	
++
+ 	if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) {
+ 		/* Issue the packet command */
+ 		ide_execute_command(drive, WIN_PACKETCMD,
+@@ -767,7 +692,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ 		return ide_started;
+ 	} else {
+ 		/* Issue the packet command */
+-		HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
++		hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 		return (*pkt_xfer_routine) (drive);
+ 	}
+ }
+@@ -776,11 +701,11 @@ static void idefloppy_rw_callback(ide_drive_t *drive)
+ {
+ 	debug_log("Reached %s\n", __func__);
+ 
+-	idefloppy_do_end_request(drive, 1, 0);
++	idefloppy_end_request(drive, 1, 0);
+ 	return;
+ }
+ 
+-static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent)
++static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent)
+ {
+ 	debug_log("creating prevent removal command, prevent = %d\n", prevent);
+ 
+@@ -789,39 +714,39 @@ static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent)
+ 	pc->c[4] = prevent;
+ }
+ 
+-static void idefloppy_create_read_capacity_cmd(idefloppy_pc_t *pc)
++static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
+ {
+ 	idefloppy_init_pc(pc);
+ 	pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
+ 	pc->c[7] = 255;
+ 	pc->c[8] = 255;
+-	pc->request_transfer = 255;
++	pc->req_xfer = 255;
+ }
+ 
+-static void idefloppy_create_format_unit_cmd(idefloppy_pc_t *pc, int b, int l,
+-					      int flags)
++static void idefloppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
++		int l, int flags)
+ {
+ 	idefloppy_init_pc(pc);
+ 	pc->c[0] = GPCMD_FORMAT_UNIT;
+ 	pc->c[1] = 0x17;
+ 
+-	memset(pc->buffer, 0, 12);
+-	pc->buffer[1] = 0xA2;
++	memset(pc->buf, 0, 12);
++	pc->buf[1] = 0xA2;
+ 	/* Default format list header, u8 1: FOV/DCRT/IMM bits set */
+ 
+ 	if (flags & 1)				/* Verify bit on... */
+-		pc->buffer[1] ^= 0x20;		/* ... turn off DCRT bit */
+-	pc->buffer[3] = 8;
++		pc->buf[1] ^= 0x20;		/* ... turn off DCRT bit */
++	pc->buf[3] = 8;
+ 
+-	put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buffer[4]));
+-	put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buffer[8]));
+-	pc->buffer_size = 12;
++	put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4]));
++	put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8]));
++	pc->buf_size = 12;
+ 	pc->flags |= PC_FLAG_WRITING;
+ }
+ 
+ /* A mode sense command is used to "sense" floppy parameters. */
+-static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code,
+-		u8 type)
++static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc,
++		u8 page_code, u8 type)
+ {
+ 	u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
+ 
+@@ -842,24 +767,24 @@ static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code,
+ 				"in create_mode_sense_cmd\n");
+ 	}
+ 	put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
+-	pc->request_transfer = length;
++	pc->req_xfer = length;
+ }
+ 
+-static void idefloppy_create_start_stop_cmd(idefloppy_pc_t *pc, int start)
++static void idefloppy_create_start_stop_cmd(struct ide_atapi_pc *pc, int start)
+ {
+ 	idefloppy_init_pc(pc);
+ 	pc->c[0] = GPCMD_START_STOP_UNIT;
+ 	pc->c[4] = start;
+ }
+ 
+-static void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc)
++static void idefloppy_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
+ {
+ 	idefloppy_init_pc(pc);
+ 	pc->c[0] = GPCMD_TEST_UNIT_READY;
+ }
+ 
+ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
+-				    idefloppy_pc_t *pc, struct request *rq,
++				    struct ide_atapi_pc *pc, struct request *rq,
+ 				    unsigned long sector)
+ {
+ 	int block = sector / floppy->bs_factor;
+@@ -874,41 +799,41 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
+ 	put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
+ 	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
+ 
+-	pc->callback = &idefloppy_rw_callback;
++	pc->idefloppy_callback = &idefloppy_rw_callback;
+ 	pc->rq = rq;
+ 	pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
+ 	if (rq->cmd_flags & REQ_RW)
+ 		pc->flags |= PC_FLAG_WRITING;
+-	pc->buffer = NULL;
+-	pc->request_transfer = pc->buffer_size = blocks * floppy->block_size;
++	pc->buf = NULL;
++	pc->req_xfer = pc->buf_size = blocks * floppy->block_size;
+ 	pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ }
+ 
+ static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
+-		idefloppy_pc_t *pc, struct request *rq)
++		struct ide_atapi_pc *pc, struct request *rq)
+ {
+ 	idefloppy_init_pc(pc);
+-	pc->callback = &idefloppy_rw_callback;
++	pc->idefloppy_callback = &idefloppy_rw_callback;
+ 	memcpy(pc->c, rq->cmd, sizeof(pc->c));
+ 	pc->rq = rq;
+ 	pc->b_count = rq->data_len;
+ 	if (rq->data_len && rq_data_dir(rq) == WRITE)
+ 		pc->flags |= PC_FLAG_WRITING;
+-	pc->buffer = rq->data;
++	pc->buf = rq->data;
+ 	if (rq->bio)
+ 		pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ 	/*
+ 	 * possibly problematic, doesn't look like ide-floppy correctly
+ 	 * handled scattered requests if dma fails...
+ 	 */
+-	pc->request_transfer = pc->buffer_size = rq->data_len;
++	pc->req_xfer = pc->buf_size = rq->data_len;
+ }
+ 
+ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
+ 		struct request *rq, sector_t block_s)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	idefloppy_pc_t *pc;
++	struct ide_atapi_pc *pc;
+ 	unsigned long block = (unsigned long)block_s;
+ 
+ 	debug_log("dev: %s, cmd_type: %x, errors: %d\n",
+@@ -924,7 +849,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
+ 		else
+ 			printk(KERN_ERR "ide-floppy: %s: I/O error\n",
+ 				drive->name);
+-		idefloppy_do_end_request(drive, 0, 0);
++		idefloppy_end_request(drive, 0, 0);
+ 		return ide_stopped;
+ 	}
+ 	if (blk_fs_request(rq)) {
+@@ -932,20 +857,20 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
+ 		    (rq->nr_sectors % floppy->bs_factor)) {
+ 			printk(KERN_ERR "%s: unsupported r/w request size\n",
+ 					drive->name);
+-			idefloppy_do_end_request(drive, 0, 0);
++			idefloppy_end_request(drive, 0, 0);
+ 			return ide_stopped;
+ 		}
+ 		pc = idefloppy_next_pc_storage(drive);
+ 		idefloppy_create_rw_cmd(floppy, pc, rq, block);
+ 	} else if (blk_special_request(rq)) {
+-		pc = (idefloppy_pc_t *) rq->buffer;
++		pc = (struct ide_atapi_pc *) rq->buffer;
+ 	} else if (blk_pc_request(rq)) {
+ 		pc = idefloppy_next_pc_storage(drive);
+ 		idefloppy_blockpc_cmd(floppy, pc, rq);
+ 	} else {
+ 		blk_dump_rq_flags(rq,
+ 			"ide-floppy: unsupported command in queue");
+-		idefloppy_do_end_request(drive, 0, 0);
++		idefloppy_end_request(drive, 0, 0);
+ 		return ide_stopped;
+ 	}
+ 
+@@ -957,7 +882,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
+  * Add a special packet command request to the tail of the request queue,
+  * and wait for it to be serviced.
+  */
+-static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc)
++static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
+ {
+ 	struct ide_floppy_obj *floppy = drive->driver_data;
+ 	struct request rq;
+@@ -977,7 +902,7 @@ static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc)
+ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	idefloppy_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	u8 *page;
+ 	int capacity, lba_capacity;
+ 	u16 transfer_rate, sector_size, cyls, rpm;
+@@ -991,16 +916,16 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
+ 				" parameters\n");
+ 		return 1;
+ 	}
+-	floppy->wp = !!(pc.buffer[3] & 0x80);
++	floppy->wp = !!(pc.buf[3] & 0x80);
+ 	set_disk_ro(floppy->disk, floppy->wp);
+-	page = &pc.buffer[8];
++	page = &pc.buf[8];
+ 
+-	transfer_rate = be16_to_cpu(*(u16 *)&pc.buffer[8 + 2]);
+-	sector_size   = be16_to_cpu(*(u16 *)&pc.buffer[8 + 6]);
+-	cyls          = be16_to_cpu(*(u16 *)&pc.buffer[8 + 8]);
+-	rpm           = be16_to_cpu(*(u16 *)&pc.buffer[8 + 28]);
+-	heads         = pc.buffer[8 + 4];
+-	sectors       = pc.buffer[8 + 5];
++	transfer_rate = be16_to_cpu(*(u16 *)&pc.buf[8 + 2]);
++	sector_size   = be16_to_cpu(*(u16 *)&pc.buf[8 + 6]);
++	cyls          = be16_to_cpu(*(u16 *)&pc.buf[8 + 8]);
++	rpm           = be16_to_cpu(*(u16 *)&pc.buf[8 + 28]);
++	heads         = pc.buf[8 + 4];
++	sectors       = pc.buf[8 + 5];
+ 
+ 	capacity = cyls * heads * sectors * sector_size;
+ 
+@@ -1029,7 +954,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
+ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	idefloppy_pc_t pc;
++	struct ide_atapi_pc pc;
+ 
+ 	floppy->srfp = 0;
+ 	idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE,
+@@ -1039,7 +964,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
+ 	if (idefloppy_queue_pc_tail(drive, &pc))
+ 		return 1;
+ 
+-	floppy->srfp = pc.buffer[8 + 2] & 0x40;
++	floppy->srfp = pc.buf[8 + 2] & 0x40;
+ 	return (0);
+ }
+ 
+@@ -1050,7 +975,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
+ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	idefloppy_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	u8 *cap_desc;
+ 	u8 header_len, desc_cnt;
+ 	int i, rc = 1, blocks, length;
+@@ -1066,15 +991,15 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ 		printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+ 		return 1;
+ 	}
+-	header_len = pc.buffer[3];
+-	cap_desc = &pc.buffer[4];
++	header_len = pc.buf[3];
++	cap_desc = &pc.buf[4];
+ 	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
+ 
+ 	for (i = 0; i < desc_cnt; i++) {
+ 		unsigned int desc_start = 4 + i*8;
+ 
+-		blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
+-		length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
++		blocks = be32_to_cpu(*(u32 *)&pc.buf[desc_start]);
++		length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]);
+ 
+ 		debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
+ 				i, blocks * length / 1024, blocks, length);
+@@ -1085,7 +1010,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ 		 * the code below is valid only for the 1st descriptor, ie i=0
+ 		 */
+ 
+-		switch (pc.buffer[desc_start + 4] & 0x03) {
++		switch (pc.buf[desc_start + 4] & 0x03) {
+ 		/* Clik! drive returns this instead of CAPACITY_CURRENT */
+ 		case CAPACITY_UNFORMATTED:
+ 			if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+@@ -1130,7 +1055,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ 			break;
+ 		}
+ 		debug_log("Descriptor 0 Code: %d\n",
+-			  pc.buffer[desc_start + 4] & 0x03);
++			  pc.buf[desc_start + 4] & 0x03);
+ 	}
+ 
+ 	/* Clik! disk does not support get_flexible_disk_page */
+@@ -1162,7 +1087,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ 
+ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ {
+-	idefloppy_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	u8 header_len, desc_cnt;
+ 	int i, blocks, length, u_array_size, u_index;
+ 	int __user *argp;
+@@ -1178,7 +1103,7 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ 		printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+ 		return (-EIO);
+ 	}
+-	header_len = pc.buffer[3];
++	header_len = pc.buf[3];
+ 	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
+ 
+ 	u_index = 0;
+@@ -1195,8 +1120,8 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ 		if (u_index >= u_array_size)
+ 			break;	/* User-supplied buffer too small */
+ 
+-		blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
+-		length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
++		blocks = be32_to_cpu(*(u32 *)&pc.buf[desc_start]);
++		length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]);
+ 
+ 		if (put_user(blocks, argp))
+ 			return(-EFAULT);
+@@ -1227,7 +1152,7 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	idefloppy_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	int progress_indication = 0x10000;
+ 
+ 	if (floppy->srfp) {
+@@ -1271,33 +1196,39 @@ static sector_t idefloppy_capacity(ide_drive_t *drive)
+  */
+ static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id)
+ {
+-	struct idefloppy_id_gcw gcw;
++	u8 gcw[2];
++	u8 device_type, protocol, removable, drq_type, packet_size;
+ 
+ 	*((u16 *) &gcw) = id->config;
+ 
++	device_type =  gcw[1] & 0x1F;
++	removable   = (gcw[0] & 0x80) >> 7;
++	protocol    = (gcw[1] & 0xC0) >> 6;
++	drq_type    = (gcw[0] & 0x60) >> 5;
++	packet_size =  gcw[0] & 0x03;
++
+ #ifdef CONFIG_PPC
+ 	/* kludge for Apple PowerBook internal zip */
+-	if ((gcw.device_type == 5) &&
+-	    !strstr(id->model, "CD-ROM") &&
+-	    strstr(id->model, "ZIP"))
+-		gcw.device_type = 0;
++	if (device_type == 5 &&
++	    !strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP"))
++		device_type = 0;
+ #endif
+ 
+-	if (gcw.protocol != 2)
++	if (protocol != 2)
+ 		printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n",
+-				gcw.protocol);
+-	else if (gcw.device_type != 0)
++			protocol);
++	else if (device_type != 0)
+ 		printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set "
+-				"to floppy\n", gcw.device_type);
+-	else if (!gcw.removable)
++				"to floppy\n", device_type);
++	else if (!removable)
+ 		printk(KERN_ERR "ide-floppy: The removable flag is not set\n");
+-	else if (gcw.drq_type == 3) {
++	else if (drq_type == 3)
+ 		printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not "
+-				"supported\n", gcw.drq_type);
+-	} else if (gcw.packet_size != 0) {
++				"supported\n", drq_type);
++	else if (packet_size != 0)
+ 		printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 "
+-				"bytes long\n", gcw.packet_size);
+-	} else
++				"bytes\n", packet_size);
++	else
+ 		return 1;
+ 	return 0;
+ }
+@@ -1322,11 +1253,12 @@ static inline void idefloppy_add_settings(ide_drive_t *drive) { ; }
+ 
+ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
+ {
+-	struct idefloppy_id_gcw gcw;
++	u8 gcw[2];
+ 
+ 	*((u16 *) &gcw) = drive->id->config;
+ 	floppy->pc = floppy->pc_stack;
+-	if (gcw.drq_type == 1)
++
++	if (((gcw[0] & 0x60) >> 5) == 1)
+ 		floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT;
+ 	/*
+ 	 * We used to check revisions here. At this point however I'm giving up.
+@@ -1413,7 +1345,7 @@ static ide_driver_t idefloppy_driver = {
+ 	.media			= ide_floppy,
+ 	.supports_dsc_overlap	= 0,
+ 	.do_request		= idefloppy_do_request,
+-	.end_request		= idefloppy_do_end_request,
++	.end_request		= idefloppy_end_request,
+ 	.error			= __ide_error,
+ 	.abort			= __ide_abort,
+ #ifdef CONFIG_IDE_PROC_FS
+@@ -1426,7 +1358,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
+ 	struct gendisk *disk = inode->i_bdev->bd_disk;
+ 	struct ide_floppy_obj *floppy;
+ 	ide_drive_t *drive;
+-	idefloppy_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	int ret = 0;
+ 
+ 	debug_log("Reached %s\n", __func__);
+@@ -1489,7 +1421,7 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
+ 	struct gendisk *disk = inode->i_bdev->bd_disk;
+ 	struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ 	ide_drive_t *drive = floppy->drive;
+-	idefloppy_pc_t pc;
++	struct ide_atapi_pc pc;
+ 
+ 	debug_log("Reached %s\n", __func__);
+ 
+@@ -1521,8 +1453,8 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+ 	return 0;
+ }
+ 
+-static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc,
+-			       unsigned long arg, unsigned int cmd)
++static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy,
++		struct ide_atapi_pc *pc, unsigned long arg, unsigned int cmd)
+ {
+ 	if (floppy->openers > 1)
+ 		return -EBUSY;
+@@ -1551,7 +1483,7 @@ static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
+ 				  int __user *arg)
+ {
+ 	int blocks, length, flags, err = 0;
+-	idefloppy_pc_t pc;
++	struct ide_atapi_pc pc;
+ 
+ 	if (floppy->openers > 1) {
+ 		/* Don't format if someone is using the disk */
+@@ -1602,7 +1534,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
+ 	struct block_device *bdev = inode->i_bdev;
+ 	struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+ 	ide_drive_t *drive = floppy->drive;
+-	idefloppy_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	void __user *argp = (void __user *)arg;
+ 	int err;
+ 
+@@ -1664,13 +1596,13 @@ static int idefloppy_revalidate_disk(struct gendisk *disk)
+ }
+ 
+ static struct block_device_operations idefloppy_ops = {
+-	.owner		= THIS_MODULE,
+-	.open		= idefloppy_open,
+-	.release	= idefloppy_release,
+-	.ioctl		= idefloppy_ioctl,
+-	.getgeo		= idefloppy_getgeo,
+-	.media_changed	= idefloppy_media_changed,
+-	.revalidate_disk= idefloppy_revalidate_disk
++	.owner			= THIS_MODULE,
++	.open			= idefloppy_open,
++	.release		= idefloppy_release,
++	.ioctl			= idefloppy_ioctl,
++	.getgeo			= idefloppy_getgeo,
++	.media_changed		= idefloppy_media_changed,
++	.revalidate_disk	= idefloppy_revalidate_disk
+ };
+ 
+ static int ide_floppy_probe(ide_drive_t *drive)
+diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
+index 9ebec08..19f63e3 100644
+--- a/drivers/ide/ide-generic.c
++++ b/drivers/ide/ide-generic.c
+@@ -1,33 +1,126 @@
+ /*
+  * generic/default IDE host driver
+  *
+- * Copyright (C) 2004 Bartlomiej Zolnierkiewicz
++ * Copyright (C) 2004, 2008 Bartlomiej Zolnierkiewicz
+  * This code was split off from ide.c.  See it for original copyrights.
+  *
+  * May be copied or modified under the terms of the GNU General Public License.
+  */
+ 
++/*
++ * For special cases new interfaces may be added using sysfs, i.e.
++ *
++ *	echo -n "0x168:0x36e:10" > /sys/class/ide_generic/add
++ *
++ * will add an interface using I/O ports 0x168-0x16f/0x36e and IRQ 10.
++ */
++
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/ide.h>
+ 
++#define DRV_NAME	"ide_generic"
++
++static ssize_t store_add(struct class *cls, const char *buf, size_t n)
++{
++	ide_hwif_t *hwif;
++	unsigned int base, ctl;
++	int irq;
++	hw_regs_t hw;
++	u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
++
++	if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
++		return -EINVAL;
++
++	hwif = ide_find_port();
++	if (hwif == NULL)
++		return -ENOENT;
++
++	memset(&hw, 0, sizeof(hw));
++	ide_std_init_ports(&hw, base, ctl);
++	hw.irq = irq;
++	hw.chipset = ide_generic;
++
++	ide_init_port_hw(hwif, &hw);
++
++	idx[0] = hwif->index;
++
++	ide_device_add(idx, NULL);
++
++	return n;
++};
++
++static struct class_attribute ide_generic_class_attrs[] = {
++	__ATTR(add, S_IWUSR, NULL, store_add),
++	__ATTR_NULL
++};
++
++static void ide_generic_class_release(struct class *cls)
++{
++	kfree(cls);
++}
++
++static int __init ide_generic_sysfs_init(void)
++{
++	struct class *cls;
++	int rc;
++
++	cls = kzalloc(sizeof(*cls), GFP_KERNEL);
++	if (!cls)
++		return -ENOMEM;
++
++	cls->name = DRV_NAME;
++	cls->owner = THIS_MODULE;
++	cls->class_release = ide_generic_class_release;
++	cls->class_attrs = ide_generic_class_attrs;
++
++	rc = class_register(cls);
++	if (rc) {
++		kfree(cls);
++		return rc;
++	}
++
++	return 0;
++}
++
+ static int __init ide_generic_init(void)
+ {
+ 	u8 idx[MAX_HWIFS];
+ 	int i;
+ 
+ 	for (i = 0; i < MAX_HWIFS; i++) {
+-		ide_hwif_t *hwif = &ide_hwifs[i];
++		ide_hwif_t *hwif;
++		unsigned long io_addr = ide_default_io_base(i);
++		hw_regs_t hw;
++
++		if (io_addr) {
++			/*
++			 * Skip probing if the corresponding
++			 * slot is already occupied.
++			 */
++			hwif = ide_find_port();
++			if (hwif == NULL || hwif->index != i) {
++				idx[i] = 0xff;
++				continue;
++			}
++
++			memset(&hw, 0, sizeof(hw));
++			ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
++			hw.irq = ide_default_irq(io_addr);
++			ide_init_port_hw(hwif, &hw);
+ 
+-		if (hwif->io_ports[IDE_DATA_OFFSET] && !hwif->present)
+ 			idx[i] = i;
+-		else
++		} else
+ 			idx[i] = 0xff;
+ 	}
+ 
+ 	ide_device_add_all(idx, NULL);
+ 
++	if (ide_generic_sysfs_init())
++		printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
++					 "class\n");
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
+index 7153796..51d181e 100644
+--- a/drivers/ide/ide-io.c
++++ b/drivers/ide/ide-io.c
+@@ -301,39 +301,45 @@ void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+ 	struct ide_taskfile *tf = &task->tf;
+ 
+ 	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+-		u16 data = hwif->INW(IDE_DATA_REG);
++		u16 data = hwif->INW(hwif->io_ports[IDE_DATA_OFFSET]);
+ 
+ 		tf->data = data & 0xff;
+ 		tf->hob_data = (data >> 8) & 0xff;
+ 	}
+ 
+ 	/* be sure we're looking at the low order bits */
+-	hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
++	hwif->OUTB(drive->ctl & ~0x80, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ 
+ 	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+-		tf->nsect  = hwif->INB(IDE_NSECTOR_REG);
++		tf->nsect  = hwif->INB(hwif->io_ports[IDE_NSECTOR_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+-		tf->lbal   = hwif->INB(IDE_SECTOR_REG);
++		tf->lbal   = hwif->INB(hwif->io_ports[IDE_SECTOR_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+-		tf->lbam   = hwif->INB(IDE_LCYL_REG);
++		tf->lbam   = hwif->INB(hwif->io_ports[IDE_LCYL_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+-		tf->lbah   = hwif->INB(IDE_HCYL_REG);
++		tf->lbah   = hwif->INB(hwif->io_ports[IDE_HCYL_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+-		tf->device = hwif->INB(IDE_SELECT_REG);
++		tf->device = hwif->INB(hwif->io_ports[IDE_SELECT_OFFSET]);
+ 
+ 	if (task->tf_flags & IDE_TFLAG_LBA48) {
+-		hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
++		hwif->OUTB(drive->ctl | 0x80,
++			   hwif->io_ports[IDE_CONTROL_OFFSET]);
+ 
+ 		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+-			tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
++			tf->hob_feature =
++				hwif->INB(hwif->io_ports[IDE_FEATURE_OFFSET]);
+ 		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+-			tf->hob_nsect   = hwif->INB(IDE_NSECTOR_REG);
++			tf->hob_nsect   =
++				hwif->INB(hwif->io_ports[IDE_NSECTOR_OFFSET]);
+ 		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+-			tf->hob_lbal    = hwif->INB(IDE_SECTOR_REG);
++			tf->hob_lbal    =
++				hwif->INB(hwif->io_ports[IDE_SECTOR_OFFSET]);
+ 		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+-			tf->hob_lbam    = hwif->INB(IDE_LCYL_REG);
++			tf->hob_lbam    =
++				hwif->INB(hwif->io_ports[IDE_LCYL_OFFSET]);
+ 		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+-			tf->hob_lbah    = hwif->INB(IDE_HCYL_REG);
++			tf->hob_lbah    =
++				hwif->INB(hwif->io_ports[IDE_HCYL_OFFSET]);
+ 	}
+ }
+ 
+@@ -448,7 +454,8 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
+ 		if (err == ABRT_ERR) {
+ 			if (drive->select.b.lba &&
+ 			    /* some newer drives don't support WIN_SPECIFY */
+-			    hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)
++			    hwif->INB(hwif->io_ports[IDE_COMMAND_OFFSET]) ==
++				WIN_SPECIFY)
+ 				return ide_stopped;
+ 		} else if ((err & BAD_CRC) == BAD_CRC) {
+ 			/* UDMA crc error, just retry the operation */
+@@ -500,7 +507,8 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
+ 
+ 	if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ 		/* force an abort */
+-		hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
++		hwif->OUTB(WIN_IDLEIMMEDIATE,
++			   hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 
+ 	if (rq->errors >= ERROR_MAX) {
+ 		ide_kill_rq(drive, rq);
+@@ -718,10 +726,6 @@ static ide_startstop_t do_special (ide_drive_t *drive)
+ 		s->b.set_tune = 0;
+ 
+ 		if (set_pio_mode_abuse(drive->hwif, req_pio)) {
+-
+-			if (hwif->set_pio_mode == NULL)
+-				return ide_stopped;
+-
+ 			/*
+ 			 * take ide_lock for drive->[no_]unmask/[no_]io_32bit
+ 			 */
+diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
+index e77cee0..4594421 100644
+--- a/drivers/ide/ide-iops.c
++++ b/drivers/ide/ide-iops.c
+@@ -158,9 +158,12 @@ EXPORT_SYMBOL(default_hwif_mmiops);
+ 
+ void SELECT_DRIVE (ide_drive_t *drive)
+ {
+-	if (HWIF(drive)->selectproc)
+-		HWIF(drive)->selectproc(drive);
+-	HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
++	ide_hwif_t *hwif = drive->hwif;
++
++	if (hwif->selectproc)
++		hwif->selectproc(drive);
++
++	hwif->OUTB(drive->select.all, hwif->io_ports[IDE_SELECT_OFFSET]);
+ }
+ 
+ void SELECT_MASK (ide_drive_t *drive, int mask)
+@@ -194,15 +197,18 @@ static void ata_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
+ 	if (io_32bit) {
+ 		if (io_32bit & 2) {
+ 			unsigned long flags;
++
+ 			local_irq_save(flags);
+-			ata_vlb_sync(drive, IDE_NSECTOR_REG);
+-			hwif->INSL(IDE_DATA_REG, buffer, wcount);
++			ata_vlb_sync(drive, hwif->io_ports[IDE_NSECTOR_OFFSET]);
++			hwif->INSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++				   wcount);
+ 			local_irq_restore(flags);
+ 		} else
+-			hwif->INSL(IDE_DATA_REG, buffer, wcount);
+-	} else {
+-		hwif->INSW(IDE_DATA_REG, buffer, wcount<<1);
+-	}
++			hwif->INSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++				   wcount);
++	} else
++		hwif->INSW(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++			   wcount << 1);
+ }
+ 
+ /*
+@@ -216,15 +222,18 @@ static void ata_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
+ 	if (io_32bit) {
+ 		if (io_32bit & 2) {
+ 			unsigned long flags;
++
+ 			local_irq_save(flags);
+-			ata_vlb_sync(drive, IDE_NSECTOR_REG);
+-			hwif->OUTSL(IDE_DATA_REG, buffer, wcount);
++			ata_vlb_sync(drive, hwif->io_ports[IDE_NSECTOR_OFFSET]);
++			hwif->OUTSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++				    wcount);
+ 			local_irq_restore(flags);
+ 		} else
+-			hwif->OUTSL(IDE_DATA_REG, buffer, wcount);
+-	} else {
+-		hwif->OUTSW(IDE_DATA_REG, buffer, wcount<<1);
+-	}
++			hwif->OUTSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++				    wcount);
++	} else
++		hwif->OUTSW(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++			    wcount << 1);
+ }
+ 
+ /*
+@@ -243,13 +252,15 @@ static void atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
+ #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
+ 	if (MACH_IS_ATARI || MACH_IS_Q40) {
+ 		/* Atari has a byte-swapped IDE interface */
+-		insw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
++		insw_swapw(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++			   bytecount / 2);
+ 		return;
+ 	}
+ #endif /* CONFIG_ATARI || CONFIG_Q40 */
+ 	hwif->ata_input_data(drive, buffer, bytecount / 4);
+ 	if ((bytecount & 0x03) >= 2)
+-		hwif->INSW(IDE_DATA_REG, ((u8 *)buffer)+(bytecount & ~0x03), 1);
++		hwif->INSW(hwif->io_ports[IDE_DATA_OFFSET],
++			   (u8 *)buffer + (bytecount & ~0x03), 1);
+ }
+ 
+ static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
+@@ -260,13 +271,15 @@ static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
+ #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
+ 	if (MACH_IS_ATARI || MACH_IS_Q40) {
+ 		/* Atari has a byte-swapped IDE interface */
+-		outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
++		outsw_swapw(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++			    bytecount / 2);
+ 		return;
+ 	}
+ #endif /* CONFIG_ATARI || CONFIG_Q40 */
+ 	hwif->ata_output_data(drive, buffer, bytecount / 4);
+ 	if ((bytecount & 0x03) >= 2)
+-		hwif->OUTSW(IDE_DATA_REG, ((u8*)buffer)+(bytecount & ~0x03), 1);
++		hwif->OUTSW(hwif->io_ports[IDE_DATA_OFFSET],
++			    (u8 *)buffer + (bytecount & ~0x03), 1);
+ }
+ 
+ void default_hwif_transport(ide_hwif_t *hwif)
+@@ -429,7 +442,7 @@ int drive_is_ready (ide_drive_t *drive)
+ 	 * an interrupt with another pci card/device.  We make no assumptions
+ 	 * about possible isa-pnp and pci-pnp issues yet.
+ 	 */
+-	if (IDE_CONTROL_REG)
++	if (hwif->io_ports[IDE_CONTROL_OFFSET])
+ 		stat = ide_read_altstatus(drive);
+ 	else
+ 		/* Note: this may clear a pending IRQ!! */
+@@ -631,7 +644,7 @@ int ide_driveid_update(ide_drive_t *drive)
+ 	SELECT_MASK(drive, 1);
+ 	ide_set_irq(drive, 1);
+ 	msleep(50);
+-	hwif->OUTB(WIN_IDENTIFY, IDE_COMMAND_REG);
++	hwif->OUTB(WIN_IDENTIFY, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 	timeout = jiffies + WAIT_WORSTCASE;
+ 	do {
+ 		if (time_after(jiffies, timeout)) {
+@@ -718,9 +731,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
+ 	SELECT_MASK(drive, 0);
+ 	udelay(1);
+ 	ide_set_irq(drive, 0);
+-	hwif->OUTB(speed, IDE_NSECTOR_REG);
+-	hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG);
+-	hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG);
++	hwif->OUTB(speed, hwif->io_ports[IDE_NSECTOR_OFFSET]);
++	hwif->OUTB(SETFEATURES_XFER, hwif->io_ports[IDE_FEATURE_OFFSET]);
++	hwif->OUTBSYNC(drive, WIN_SETFEATURES,
++		       hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 	if (drive->quirk_list == 2)
+ 		ide_set_irq(drive, 1);
+ 
+@@ -828,7 +842,7 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
+ 
+ 	spin_lock_irqsave(&ide_lock, flags);
+ 	__ide_set_handler(drive, handler, timeout, expiry);
+-	hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);
++	hwif->OUTBSYNC(drive, cmd, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 	/*
+ 	 * Drive takes 400nS to respond, we must avoid the IRQ being
+ 	 * serviced before that.
+@@ -1009,7 +1023,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ 	unsigned long flags;
+ 	ide_hwif_t *hwif;
+ 	ide_hwgroup_t *hwgroup;
+-	
++	u8 ctl;
++
+ 	spin_lock_irqsave(&ide_lock, flags);
+ 	hwif = HWIF(drive);
+ 	hwgroup = HWGROUP(drive);
+@@ -1023,7 +1038,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ 		pre_reset(drive);
+ 		SELECT_DRIVE(drive);
+ 		udelay (20);
+-		hwif->OUTBSYNC(drive, WIN_SRST, IDE_COMMAND_REG);
++		hwif->OUTBSYNC(drive, WIN_SRST,
++			       hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 		ndelay(400);
+ 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+ 		hwgroup->polling = 1;
+@@ -1039,7 +1055,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ 	for (unit = 0; unit < MAX_DRIVES; ++unit)
+ 		pre_reset(&hwif->drives[unit]);
+ 
+-	if (!IDE_CONTROL_REG) {
++	if (hwif->io_ports[IDE_CONTROL_OFFSET] == 0) {
+ 		spin_unlock_irqrestore(&ide_lock, flags);
+ 		return ide_stopped;
+ 	}
+@@ -1054,16 +1070,14 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ 	 * recover from reset very quickly, saving us the first 50ms wait time.
+ 	 */
+ 	/* set SRST and nIEN */
+-	hwif->OUTBSYNC(drive, drive->ctl|6,IDE_CONTROL_REG);
++	hwif->OUTBSYNC(drive, drive->ctl|6, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ 	/* more than enough time */
+ 	udelay(10);
+-	if (drive->quirk_list == 2) {
+-		/* clear SRST and nIEN */
+-		hwif->OUTBSYNC(drive, drive->ctl, IDE_CONTROL_REG);
+-	} else {
+-		/* clear SRST, leave nIEN */
+-		hwif->OUTBSYNC(drive, drive->ctl|2, IDE_CONTROL_REG);
+-	}
++	if (drive->quirk_list == 2)
++		ctl = drive->ctl;	/* clear SRST and nIEN */
++	else
++		ctl = drive->ctl | 2;	/* clear SRST, leave nIEN */
++	hwif->OUTBSYNC(drive, ctl, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ 	/* more than enough time */
+ 	udelay(10);
+ 	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
+index 7031a8d..c859de7 100644
+--- a/drivers/ide/ide-lib.c
++++ b/drivers/ide/ide-lib.c
+@@ -274,16 +274,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
+ 		if (overridden)
+ 			printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
+ 					 drive->name);
+-
+-		/*
+-		 * Conservative "downgrade" for all pre-ATA2 drives
+-		 */
+-		if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_DOWNGRADE) == 0 &&
+-		    pio_mode && pio_mode < 4) {
+-			pio_mode--;
+-			printk(KERN_INFO "%s: applying conservative "
+-					 "PIO \"downgrade\"\n", drive->name);
+-		}
+ 	}
+ 
+ 	if (pio_mode > max_mode)
+@@ -300,7 +290,8 @@ void ide_set_pio(ide_drive_t *drive, u8 req_pio)
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	u8 host_pio, pio;
+ 
+-	if (hwif->set_pio_mode == NULL)
++	if (hwif->set_pio_mode == NULL ||
++	    (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ 		return;
+ 
+ 	BUG_ON(hwif->pio_mask == 0x00);
+@@ -353,6 +344,9 @@ int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 
++	if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
++		return 0;
++
+ 	if (hwif->set_pio_mode == NULL)
+ 		return -1;
+ 
+@@ -380,6 +374,9 @@ int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 
++	if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
++		return 0;
++
+ 	if (hwif->set_dma_mode == NULL)
+ 		return -1;
+ 
+@@ -410,7 +407,8 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 
+-	if (hwif->set_dma_mode == NULL)
++	if (hwif->set_dma_mode == NULL ||
++	    (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ 		return -1;
+ 
+ 	rate = ide_rate_filter(drive, rate);
+diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
+index c14bb53..8a178a5 100644
+--- a/drivers/ide/ide-pnp.c
++++ b/drivers/ide/ide-pnp.c
+@@ -11,7 +11,7 @@
+  *
+  * You should have received a copy of the GNU General Public License
+  * (for example /usr/src/linux/COPYING); if not, write to the Free
+- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+ 
+ #include <linux/init.h>
+@@ -20,12 +20,12 @@
+ 
+ /* Add your devices here :)) */
+ static struct pnp_device_id idepnp_devices[] = {
+-  	/* Generic ESDI/IDE/ATA compatible hard disk controller */
++	/* Generic ESDI/IDE/ATA compatible hard disk controller */
+ 	{.id = "PNP0600", .driver_data = 0},
+ 	{.id = ""}
+ };
+ 
+-static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
++static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
+ {
+ 	hw_regs_t hw;
+ 	ide_hwif_t *hwif;
+@@ -38,7 +38,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+ 				pnp_port_start(dev, 1));
+ 	hw.irq = pnp_irq(dev, 0);
+ 
+-	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	hwif = ide_find_port();
+ 	if (hwif) {
+ 		u8 index = hwif->index;
+ 		u8 idx[4] = { index, 0xff, 0xff, 0xff };
+@@ -47,7 +47,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+ 		ide_init_port_hw(hwif, &hw);
+ 
+ 		printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
+-		pnp_set_drvdata(dev,hwif);
++		pnp_set_drvdata(dev, hwif);
+ 
+ 		ide_device_add(idx, NULL);
+ 
+@@ -57,12 +57,12 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+ 	return -1;
+ }
+ 
+-static void idepnp_remove(struct pnp_dev * dev)
++static void idepnp_remove(struct pnp_dev *dev)
+ {
+ 	ide_hwif_t *hwif = pnp_get_drvdata(dev);
+ 
+ 	if (hwif)
+-		ide_unregister(hwif->index, 0, 0);
++		ide_unregister(hwif->index);
+ 	else
+ 		printk(KERN_ERR "idepnp: Unable to remove device, please report.\n");
+ }
+diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
+index 47a1149..8754297 100644
+--- a/drivers/ide/ide-probe.c
++++ b/drivers/ide/ide-probe.c
+@@ -271,7 +271,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ 	/* take a deep breath */
+ 	msleep(50);
+ 
+-	if (IDE_CONTROL_REG) {
++	if (hwif->io_ports[IDE_CONTROL_OFFSET]) {
+ 		a = ide_read_altstatus(drive);
+ 		s = ide_read_status(drive);
+ 		if ((a ^ s) & ~INDEX_STAT)
+@@ -289,10 +289,10 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ 	 */
+ 	if ((cmd == WIN_PIDENTIFY))
+ 		/* disable dma & overlap */
+-		hwif->OUTB(0, IDE_FEATURE_REG);
++		hwif->OUTB(0, hwif->io_ports[IDE_FEATURE_OFFSET]);
+ 
+ 	/* ask drive for ID */
+-	hwif->OUTB(cmd, IDE_COMMAND_REG);
++	hwif->OUTB(cmd, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 
+ 	timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
+ 	timeout += jiffies;
+@@ -353,7 +353,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
+ 	 * interrupts during the identify-phase that
+ 	 * the irq handler isn't expecting.
+ 	 */
+-	if (IDE_CONTROL_REG) {
++	if (hwif->io_ports[IDE_CONTROL_OFFSET]) {
+ 		if (!hwif->irq) {
+ 			autoprobe = 1;
+ 			cookie = probe_irq_on();
+@@ -445,7 +445,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
+ 	msleep(50);
+ 	SELECT_DRIVE(drive);
+ 	msleep(50);
+-	if (hwif->INB(IDE_SELECT_REG) != drive->select.all && !drive->present) {
++	if (hwif->INB(hwif->io_ports[IDE_SELECT_OFFSET]) != drive->select.all &&
++	    !drive->present) {
+ 		if (drive->select.b.unit != 0) {
+ 			/* exit with drive0 selected */
+ 			SELECT_DRIVE(&hwif->drives[0]);
+@@ -477,9 +478,11 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
+ 			printk(KERN_ERR "%s: no response (status = 0x%02x), "
+ 					"resetting drive\n", drive->name, stat);
+ 			msleep(50);
+-			hwif->OUTB(drive->select.all, IDE_SELECT_REG);
++			hwif->OUTB(drive->select.all,
++				   hwif->io_ports[IDE_SELECT_OFFSET]);
+ 			msleep(50);
+-			hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
++			hwif->OUTB(WIN_SRST,
++				   hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 			(void)ide_busy_sleep(hwif);
+ 			rc = try_to_identify(drive, cmd);
+ 		}
+@@ -515,7 +518,7 @@ static void enable_nest (ide_drive_t *drive)
+ 	printk("%s: enabling %s -- ", hwif->name, drive->id->model);
+ 	SELECT_DRIVE(drive);
+ 	msleep(50);
+-	hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
++	hwif->OUTB(EXABYTE_ENABLE_NEST, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 
+ 	if (ide_busy_sleep(hwif)) {
+ 		printk(KERN_CONT "failed (timeout)\n");
+@@ -623,7 +626,7 @@ static void hwif_release_dev (struct device *dev)
+ 	complete(&hwif->gendev_rel_comp);
+ }
+ 
+-static void ide_register_port(ide_hwif_t *hwif)
++static int ide_register_port(ide_hwif_t *hwif)
+ {
+ 	int ret;
+ 
+@@ -639,9 +642,23 @@ static void ide_register_port(ide_hwif_t *hwif)
+ 	}
+ 	hwif->gendev.release = hwif_release_dev;
+ 	ret = device_register(&hwif->gendev);
+-	if (ret < 0)
++	if (ret < 0) {
+ 		printk(KERN_WARNING "IDE: %s: device_register error: %d\n",
+ 			__FUNCTION__, ret);
++		goto out;
++	}
++
++	get_device(&hwif->gendev);
++
++	hwif->portdev = device_create(ide_port_class, &hwif->gendev,
++				      MKDEV(0, 0), hwif->name);
++	if (IS_ERR(hwif->portdev)) {
++		ret = PTR_ERR(hwif->portdev);
++		device_unregister(&hwif->gendev);
++	}
++	dev_set_drvdata(hwif->portdev, hwif);
++out:
++	return ret;
+ }
+ 
+ /**
+@@ -949,6 +966,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
+ {
+ 	int i;
+ 
++	mutex_lock(&ide_cfg_mtx);
+ 	for (i = 0; i < MAX_DRIVES; i++) {
+ 		ide_drive_t *drive = &hwif->drives[i];
+ 
+@@ -963,6 +981,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
+ 
+ 		ide_add_drive_to_hwgroup(drive);
+ 	}
++	mutex_unlock(&ide_cfg_mtx);
+ }
+ 
+ /*
+@@ -1088,8 +1107,6 @@ static int init_irq (ide_hwif_t *hwif)
+ 			hwif->sharing_irq ? "shar" : "serializ", match->name);
+ 	printk("\n");
+ 
+-	ide_port_setup_devices(hwif);
+-
+ 	mutex_unlock(&ide_cfg_mtx);
+ 	return 0;
+ out_unlink:
+@@ -1199,6 +1216,8 @@ static void drive_release_dev (struct device *dev)
+ {
+ 	ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
+ 
++	ide_proc_unregister_device(drive);
++
+ 	spin_lock_irq(&ide_lock);
+ 	ide_remove_drive_from_hwgroup(drive);
+ 	kfree(drive->id);
+@@ -1214,6 +1233,10 @@ static void drive_release_dev (struct device *dev)
+ 	complete(&drive->gendev_rel_comp);
+ }
+ 
++#ifndef ide_default_irq
++#define ide_default_irq(irq) 0
++#endif
++
+ static int hwif_init(ide_hwif_t *hwif)
+ {
+ 	int old_irq;
+@@ -1225,13 +1248,6 @@ static int hwif_init(ide_hwif_t *hwif)
+ 			return 0;
+ 		}
+ 	}
+-#ifdef CONFIG_BLK_DEV_HD
+-	if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
+-		printk("%s: CANNOT SHARE IRQ WITH OLD "
+-			"HARDDISK DRIVER (hd.c)\n", hwif->name);
+-		return 0;
+-	}
+-#endif /* CONFIG_BLK_DEV_HD */
+ 
+ 	if (register_blkdev(hwif->major, hwif->name))
+ 		return 0;
+@@ -1366,13 +1382,116 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
+ 	/* call chipset specific routine for each enabled port */
+ 	if (d->init_hwif)
+ 		d->init_hwif(hwif);
++}
+ 
++static void ide_port_cable_detect(ide_hwif_t *hwif)
++{
+ 	if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) {
+ 		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ 			hwif->cbl = hwif->cable_detect(hwif);
+ 	}
+ }
+ 
++static ssize_t store_delete_devices(struct device *portdev,
++				    struct device_attribute *attr,
++				    const char *buf, size_t n)
++{
++	ide_hwif_t *hwif = dev_get_drvdata(portdev);
++
++	if (strncmp(buf, "1", n))
++		return -EINVAL;
++
++	ide_port_unregister_devices(hwif);
++
++	return n;
++};
++
++static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);
++
++static ssize_t store_scan(struct device *portdev,
++			  struct device_attribute *attr,
++			  const char *buf, size_t n)
++{
++	ide_hwif_t *hwif = dev_get_drvdata(portdev);
++
++	if (strncmp(buf, "1", n))
++		return -EINVAL;
++
++	ide_port_unregister_devices(hwif);
++	ide_port_scan(hwif);
++
++	return n;
++};
++
++static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
++
++static struct device_attribute *ide_port_attrs[] = {
++	&dev_attr_delete_devices,
++	&dev_attr_scan,
++	NULL
++};
++
++static int ide_sysfs_register_port(ide_hwif_t *hwif)
++{
++	int i, rc;
++
++	for (i = 0; ide_port_attrs[i]; i++) {
++		rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
++		if (rc)
++			break;
++	}
++
++	return rc;
++}
++
++/**
++ *	ide_find_port_slot	-	find free ide_hwifs[] slot
++ *	@d: IDE port info
++ *
++ *	Return the new hwif.  If we are out of free slots return NULL.
++ */
++
++ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
++{
++	ide_hwif_t *hwif;
++	int i;
++	u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
++
++	/*
++	 * Claim an unassigned slot.
++	 *
++	 * Give preference to claiming other slots before claiming ide0/ide1,
++	 * just in case there's another interface yet-to-be-scanned
++	 * which uses ports 0x1f0/0x170 (the ide0/ide1 defaults).
++	 *
++	 * Unless there is a bootable card that does not use the standard
++	 * ports 0x1f0/0x170 (the ide0/ide1 defaults).
++	 */
++	if (bootable) {
++		i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;
++
++		for (; i < MAX_HWIFS; i++) {
++			hwif = &ide_hwifs[i];
++			if (hwif->chipset == ide_unknown)
++				return hwif;
++		}
++	} else {
++		for (i = 2; i < MAX_HWIFS; i++) {
++			hwif = &ide_hwifs[i];
++			if (hwif->chipset == ide_unknown)
++				return hwif;
++		}
++		for (i = 0; i < 2 && i < MAX_HWIFS; i++) {
++			hwif = &ide_hwifs[i];
++			if (hwif->chipset == ide_unknown)
++				return hwif;
++		}
++	}
++
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(ide_find_port_slot);
++
+ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ {
+ 	ide_hwif_t *hwif, *mate = NULL;
+@@ -1394,6 +1513,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ 		mate = (i & 1) ? NULL : hwif;
+ 
+ 		ide_init_port(hwif, i & 1, d);
++		ide_port_cable_detect(hwif);
+ 		ide_port_init_devices(hwif);
+ 	}
+ 
+@@ -1441,6 +1561,8 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ 			continue;
+ 		}
+ 
++		ide_port_setup_devices(hwif);
++
+ 		ide_acpi_init(hwif);
+ 		ide_acpi_port_init_devices(hwif);
+ 	}
+@@ -1452,8 +1574,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ 		hwif = &ide_hwifs[idx[i]];
+ 
+ 		if (hwif->present) {
+-			if (hwif->chipset == ide_unknown ||
+-			    hwif->chipset == ide_forced)
++			if (hwif->chipset == ide_unknown)
+ 				hwif->chipset = ide_generic;
+ 			hwif_register_devices(hwif);
+ 		}
+@@ -1466,6 +1587,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ 		hwif = &ide_hwifs[idx[i]];
+ 
+ 		if (hwif->present) {
++			ide_sysfs_register_port(hwif);
+ 			ide_proc_register_port(hwif);
+ 			ide_proc_port_register_devices(hwif);
+ 		}
+@@ -1486,3 +1608,21 @@ int ide_device_add(u8 idx[4], const struct ide_port_info *d)
+ 	return ide_device_add_all(idx_all, d);
+ }
+ EXPORT_SYMBOL_GPL(ide_device_add);
++
++void ide_port_scan(ide_hwif_t *hwif)
++{
++	ide_port_cable_detect(hwif);
++	ide_port_init_devices(hwif);
++
++	if (ide_probe_port(hwif) < 0)
++		return;
++
++	hwif->present = 1;
++
++	ide_port_tune_devices(hwif);
++	ide_acpi_port_init_devices(hwif);
++	ide_port_setup_devices(hwif);
++	hwif_register_devices(hwif);
++	ide_proc_port_register_devices(hwif);
++}
++EXPORT_SYMBOL_GPL(ide_port_scan);
+diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
+index bab88ca..5d3562b 100644
+--- a/drivers/ide/ide-proc.c
++++ b/drivers/ide/ide-proc.c
+@@ -46,32 +46,29 @@ static int proc_ide_read_imodel
+ 	int		len;
+ 	const char	*name;
+ 
+-	/*
+-	 * Neither ide_unknown nor ide_forced should be set at this point.
+-	 */
+ 	switch (hwif->chipset) {
+-		case ide_generic:	name = "generic";	break;
+-		case ide_pci:		name = "pci";		break;
+-		case ide_cmd640:	name = "cmd640";	break;
+-		case ide_dtc2278:	name = "dtc2278";	break;
+-		case ide_ali14xx:	name = "ali14xx";	break;
+-		case ide_qd65xx:	name = "qd65xx";	break;
+-		case ide_umc8672:	name = "umc8672";	break;
+-		case ide_ht6560b:	name = "ht6560b";	break;
+-		case ide_rz1000:	name = "rz1000";	break;
+-		case ide_trm290:	name = "trm290";	break;
+-		case ide_cmd646:	name = "cmd646";	break;
+-		case ide_cy82c693:	name = "cy82c693";	break;
+-		case ide_4drives:	name = "4drives";	break;
+-		case ide_pmac:		name = "mac-io";	break;
+-		case ide_au1xxx:	name = "au1xxx";	break;
+-		case ide_palm3710:      name = "palm3710";      break;
+-		case ide_etrax100:	name = "etrax100";	break;
+-		case ide_acorn:		name = "acorn";		break;
+-		default:		name = "(unknown)";	break;
++	case ide_generic:	name = "generic";	break;
++	case ide_pci:		name = "pci";		break;
++	case ide_cmd640:	name = "cmd640";	break;
++	case ide_dtc2278:	name = "dtc2278";	break;
++	case ide_ali14xx:	name = "ali14xx";	break;
++	case ide_qd65xx:	name = "qd65xx";	break;
++	case ide_umc8672:	name = "umc8672";	break;
++	case ide_ht6560b:	name = "ht6560b";	break;
++	case ide_rz1000:	name = "rz1000";	break;
++	case ide_trm290:	name = "trm290";	break;
++	case ide_cmd646:	name = "cmd646";	break;
++	case ide_cy82c693:	name = "cy82c693";	break;
++	case ide_4drives:	name = "4drives";	break;
++	case ide_pmac:		name = "mac-io";	break;
++	case ide_au1xxx:	name = "au1xxx";	break;
++	case ide_palm3710:      name = "palm3710";      break;
++	case ide_etrax100:	name = "etrax100";	break;
++	case ide_acorn:		name = "acorn";		break;
++	default:		name = "(unknown)";	break;
+ 	}
+ 	len = sprintf(page, "%s\n", name);
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ static int proc_ide_read_mate
+@@ -84,7 +81,7 @@ static int proc_ide_read_mate
+ 		len = sprintf(page, "%s\n", hwif->mate->name);
+ 	else
+ 		len = sprintf(page, "(none)\n");
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ static int proc_ide_read_channel
+@@ -96,7 +93,7 @@ static int proc_ide_read_channel
+ 	page[0] = hwif->channel ? '1' : '0';
+ 	page[1] = '\n';
+ 	len = 2;
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ static int proc_ide_read_identify
+@@ -123,7 +120,7 @@ static int proc_ide_read_identify
+ 			len = out - page;
+ 		}
+ 	}
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ /**
+@@ -200,7 +197,7 @@ EXPORT_SYMBOL(ide_add_setting);
+  *	The caller must hold the setting semaphore.
+  */
+ 
+-static void __ide_remove_setting (ide_drive_t *drive, char *name)
++static void __ide_remove_setting(ide_drive_t *drive, char *name)
+ {
+ 	ide_settings_t **p, *setting;
+ 
+@@ -208,7 +205,8 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
+ 
+ 	while ((*p) && strcmp((*p)->name, name))
+ 		p = &((*p)->next);
+-	if ((setting = (*p)) == NULL)
++	setting = (*p);
++	if (setting == NULL)
+ 		return;
+ 
+ 	(*p) = setting->next;
+@@ -226,7 +224,7 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
+  *	caller must hold ide_setting_mtx.
+  */
+ 
+-static void auto_remove_settings (ide_drive_t *drive)
++static void auto_remove_settings(ide_drive_t *drive)
+ {
+ 	ide_settings_t *setting;
+ repeat:
+@@ -282,16 +280,16 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
+ 
+ 	if ((setting->rw & SETTING_READ)) {
+ 		spin_lock_irqsave(&ide_lock, flags);
+-		switch(setting->data_type) {
+-			case TYPE_BYTE:
+-				val = *((u8 *) setting->data);
+-				break;
+-			case TYPE_SHORT:
+-				val = *((u16 *) setting->data);
+-				break;
+-			case TYPE_INT:
+-				val = *((u32 *) setting->data);
+-				break;
++		switch (setting->data_type) {
++		case TYPE_BYTE:
++			val = *((u8 *) setting->data);
++			break;
++		case TYPE_SHORT:
++			val = *((u16 *) setting->data);
++			break;
++		case TYPE_INT:
++			val = *((u32 *) setting->data);
++			break;
+ 		}
+ 		spin_unlock_irqrestore(&ide_lock, flags);
+ 	}
+@@ -329,15 +327,15 @@ static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int va
+ 	if (ide_spin_wait_hwgroup(drive))
+ 		return -EBUSY;
+ 	switch (setting->data_type) {
+-		case TYPE_BYTE:
+-			*((u8 *) setting->data) = val;
+-			break;
+-		case TYPE_SHORT:
+-			*((u16 *) setting->data) = val;
+-			break;
+-		case TYPE_INT:
+-			*((u32 *) setting->data) = val;
+-			break;
++	case TYPE_BYTE:
++		*((u8 *) setting->data) = val;
++		break;
++	case TYPE_SHORT:
++		*((u16 *) setting->data) = val;
++		break;
++	case TYPE_INT:
++		*((u32 *) setting->data) = val;
++		break;
+ 	}
+ 	spin_unlock_irq(&ide_lock);
+ 	return 0;
+@@ -393,7 +391,7 @@ void ide_add_generic_settings (ide_drive_t *drive)
+ 
+ static void proc_ide_settings_warn(void)
+ {
+-	static int warned = 0;
++	static int warned;
+ 
+ 	if (warned)
+ 		return;
+@@ -416,11 +414,12 @@ static int proc_ide_read_settings
+ 	mutex_lock(&ide_setting_mtx);
+ 	out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
+ 	out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
+-	while(setting) {
++	while (setting) {
+ 		mul_factor = setting->mul_factor;
+ 		div_factor = setting->div_factor;
+ 		out += sprintf(out, "%-24s", setting->name);
+-		if ((rc = ide_read_setting(drive, setting)) >= 0)
++		rc = ide_read_setting(drive, setting);
++		if (rc >= 0)
+ 			out += sprintf(out, "%-16d", rc * mul_factor / div_factor);
+ 		else
+ 			out += sprintf(out, "%-16s", "write-only");
+@@ -434,7 +433,7 @@ static int proc_ide_read_settings
+ 	}
+ 	len = out - page;
+ 	mutex_unlock(&ide_setting_mtx);
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ #define MAX_LEN	30
+@@ -515,8 +514,7 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
+ 
+ 			mutex_lock(&ide_setting_mtx);
+ 			setting = ide_find_setting_by_name(drive, name);
+-			if (!setting)
+-			{
++			if (!setting) {
+ 				mutex_unlock(&ide_setting_mtx);
+ 				goto parse_error;
+ 			}
+@@ -536,8 +534,8 @@ parse_error:
+ int proc_ide_read_capacity
+ 	(char *page, char **start, off_t off, int count, int *eof, void *data)
+ {
+-	int len = sprintf(page,"%llu\n", (long long)0x7fffffff);
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	int len = sprintf(page, "%llu\n", (long long)0x7fffffff);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
+@@ -549,13 +547,13 @@ int proc_ide_read_geometry
+ 	char		*out = page;
+ 	int		len;
+ 
+-	out += sprintf(out,"physical     %d/%d/%d\n",
++	out += sprintf(out, "physical     %d/%d/%d\n",
+ 			drive->cyl, drive->head, drive->sect);
+-	out += sprintf(out,"logical      %d/%d/%d\n",
++	out += sprintf(out, "logical      %d/%d/%d\n",
+ 			drive->bios_cyl, drive->bios_head, drive->bios_sect);
+ 
+ 	len = out - page;
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ EXPORT_SYMBOL(proc_ide_read_geometry);
+@@ -569,7 +567,7 @@ static int proc_ide_read_dmodel
+ 
+ 	len = sprintf(page, "%.40s\n",
+ 		(id && id->model[0]) ? (char *)id->model : "(none)");
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ static int proc_ide_read_driver
+@@ -586,7 +584,7 @@ static int proc_ide_read_driver
+ 				dev->driver->name, ide_drv->version);
+ 	} else
+ 		len = sprintf(page, "ide-default version 0.9.newide\n");
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
+@@ -642,30 +640,26 @@ static int proc_ide_read_media
+ 	int		len;
+ 
+ 	switch (drive->media) {
+-		case ide_disk:	media = "disk\n";
+-				break;
+-		case ide_cdrom:	media = "cdrom\n";
+-				break;
+-		case ide_tape:	media = "tape\n";
+-				break;
+-		case ide_floppy:media = "floppy\n";
+-				break;
+-		case ide_optical:media = "optical\n";
+-				break;
+-		default:	media = "UNKNOWN\n";
+-				break;
++	case ide_disk:		media = "disk\n";	break;
++	case ide_cdrom:		media = "cdrom\n";	break;
++	case ide_tape:		media = "tape\n";	break;
++	case ide_floppy:	media = "floppy\n";	break;
++	case ide_optical:	media = "optical\n";	break;
++	default:		media = "UNKNOWN\n";	break;
+ 	}
+-	strcpy(page,media);
++	strcpy(page, media);
+ 	len = strlen(media);
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+ 
+ static ide_proc_entry_t generic_drive_entries[] = {
+-	{ "driver",	S_IFREG|S_IRUGO,	proc_ide_read_driver,	proc_ide_write_driver },
+-	{ "identify",	S_IFREG|S_IRUSR,	proc_ide_read_identify,	NULL },
+-	{ "media",	S_IFREG|S_IRUGO,	proc_ide_read_media,	NULL },
+-	{ "model",	S_IFREG|S_IRUGO,	proc_ide_read_dmodel,	NULL },
+-	{ "settings",	S_IFREG|S_IRUSR|S_IWUSR,proc_ide_read_settings,	proc_ide_write_settings },
++	{ "driver",	S_IFREG|S_IRUGO,	 proc_ide_read_driver,
++						 proc_ide_write_driver },
++	{ "identify",	S_IFREG|S_IRUSR,	 proc_ide_read_identify, NULL },
++	{ "media",	S_IFREG|S_IRUGO,	 proc_ide_read_media,    NULL },
++	{ "model",	S_IFREG|S_IRUGO,	 proc_ide_read_dmodel,   NULL },
++	{ "settings",	S_IFREG|S_IRUSR|S_IWUSR, proc_ide_read_settings,
++						 proc_ide_write_settings },
+ 	{ NULL,	0, NULL, NULL }
+ };
+ 
+@@ -737,7 +731,6 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
+ 	spin_unlock_irqrestore(&ide_lock, flags);
+ 	mutex_unlock(&ide_setting_mtx);
+ }
+-
+ EXPORT_SYMBOL(ide_proc_unregister_driver);
+ 
+ void ide_proc_port_register_devices(ide_hwif_t *hwif)
+@@ -758,33 +751,22 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
+ 		drive->proc = proc_mkdir(drive->name, parent);
+ 		if (drive->proc)
+ 			ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
+-		sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name);
++		sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name);
+ 		ent = proc_symlink(drive->name, proc_ide_root, name);
+ 		if (!ent) return;
+ 	}
+ }
+ 
+-static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
++void ide_proc_unregister_device(ide_drive_t *drive)
+ {
+ 	if (drive->proc) {
+ 		ide_remove_proc_entries(drive->proc, generic_drive_entries);
+ 		remove_proc_entry(drive->name, proc_ide_root);
+-		remove_proc_entry(drive->name, hwif->proc);
++		remove_proc_entry(drive->name, drive->hwif->proc);
+ 		drive->proc = NULL;
+ 	}
+ }
+ 
+-static void destroy_proc_ide_drives(ide_hwif_t *hwif)
+-{
+-	int	d;
+-
+-	for (d = 0; d < MAX_DRIVES; d++) {
+-		ide_drive_t *drive = &hwif->drives[d];
+-		if (drive->proc)
+-			destroy_proc_ide_device(hwif, drive);
+-	}
+-}
+-
+ static ide_proc_entry_t hwif_entries[] = {
+ 	{ "channel",	S_IFREG|S_IRUGO,	proc_ide_read_channel,	NULL },
+ 	{ "mate",	S_IFREG|S_IRUGO,	proc_ide_read_mate,	NULL },
+@@ -809,14 +791,12 @@ void ide_pci_create_host_proc(const char *name, get_info_t *get_info)
+ {
+ 	create_proc_info_entry(name, 0, proc_ide_root, get_info);
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_pci_create_host_proc);
+ #endif
+ 
+ void ide_proc_unregister_port(ide_hwif_t *hwif)
+ {
+ 	if (hwif->proc) {
+-		destroy_proc_ide_drives(hwif);
+ 		ide_remove_proc_entries(hwif->proc, hwif_entries);
+ 		remove_proc_entry(hwif->name, proc_ide_root);
+ 		hwif->proc = NULL;
+diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c
+index 93d2e41..98888da 100644
+--- a/drivers/ide/ide-scan-pci.c
++++ b/drivers/ide/ide-scan-pci.c
+@@ -88,13 +88,8 @@ static int __init ide_scan_pcibus(void)
+ 	struct list_head *l, *n;
+ 
+ 	pre_init = 0;
+-	if (!ide_scan_direction)
+-		while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
+-			ide_scan_pcidev(dev);
+-	else
+-		while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID,
+-						     dev)))
+-			ide_scan_pcidev(dev);
++	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
++		ide_scan_pcidev(dev);
+ 
+ 	/*
+ 	 *	Hand the drivers over to the PCI layer now we
+diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
+index 0598ecf..f43fd07 100644
+--- a/drivers/ide/ide-tape.c
++++ b/drivers/ide/ide-tape.c
+@@ -181,49 +181,63 @@ struct idetape_bh {
+ 	char *b_data;
+ };
+ 
+-typedef struct idetape_packet_command_s {
+-	/* Actual packet bytes */
+-	u8 c[12];
+-	/* On each retry, we increment retries */
+-	int retries;
+-	/* Error code */
+-	int error;
+-	/* Bytes to transfer */
+-	int request_transfer;
+-	/* Bytes actually transferred */
+-	int actually_transferred;
+-	/* Size of our data buffer */
+-	int buffer_size;
+-	struct idetape_bh *bh;
+-	char *b_data;
+-	int b_count;
+-	/* Data buffer */
+-	u8 *buffer;
+-	/* Pointer into the above buffer */
+-	u8 *current_position;
+-	/* Called when this packet command is completed */
+-	ide_startstop_t (*callback) (ide_drive_t *);
+-	/* Temporary buffer */
+-	u8 pc_buffer[IDETAPE_PC_BUFFER_SIZE];
+-	/* Status/Action bit flags: long for set_bit */
+-	unsigned long flags;
+-} idetape_pc_t;
++/* Tape door status */
++#define DOOR_UNLOCKED			0
++#define DOOR_LOCKED			1
++#define DOOR_EXPLICITLY_LOCKED		2
++
++/* Some defines for the SPACE command */
++#define IDETAPE_SPACE_OVER_FILEMARK	1
++#define IDETAPE_SPACE_TO_EOD		3
++
++/* Some defines for the LOAD UNLOAD command */
++#define IDETAPE_LU_LOAD_MASK		1
++#define IDETAPE_LU_RETENSION_MASK	2
++#define IDETAPE_LU_EOT_MASK		4
+ 
+ /*
+- *	Packet command flag bits.
++ * Special requests for our block device strategy routine.
++ *
++ * In order to service a character device command, we add special requests to
++ * the tail of our block device request queue and wait for their completion.
+  */
+-/* Set when an error is considered normal - We won't retry */
+-#define	PC_ABORT			0
+-/* 1 When polling for DSC on a media access command */
+-#define PC_WAIT_FOR_DSC			1
+-/* 1 when we prefer to use DMA if possible */
+-#define PC_DMA_RECOMMENDED		2
+-/* 1 while DMA in progress */
+-#define	PC_DMA_IN_PROGRESS		3
+-/* 1 when encountered problem during DMA */
+-#define	PC_DMA_ERROR			4
+-/* Data direction */
+-#define	PC_WRITING			5
++
++enum {
++	REQ_IDETAPE_PC1		= (1 << 0), /* packet command (first stage) */
++	REQ_IDETAPE_PC2		= (1 << 1), /* packet command (second stage) */
++	REQ_IDETAPE_READ	= (1 << 2),
++	REQ_IDETAPE_WRITE	= (1 << 3),
++};
++
++/* Error codes returned in rq->errors to the higher part of the driver. */
++#define IDETAPE_ERROR_GENERAL		101
++#define IDETAPE_ERROR_FILEMARK		102
++#define IDETAPE_ERROR_EOD		103
++
++/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
++#define IDETAPE_BLOCK_DESCRIPTOR	0
++#define IDETAPE_CAPABILITIES_PAGE	0x2a
++
++/* Tape flag bits values. */
++enum {
++	IDETAPE_FLAG_IGNORE_DSC		= (1 << 0),
++	/* 0 When the tape position is unknown */
++	IDETAPE_FLAG_ADDRESS_VALID	= (1 <<	1),
++	/* Device already opened */
++	IDETAPE_FLAG_BUSY			= (1 << 2),
++	/* Error detected in a pipeline stage */
++	IDETAPE_FLAG_PIPELINE_ERR	= (1 <<	3),
++	/* Attempt to auto-detect the current user block size */
++	IDETAPE_FLAG_DETECT_BS		= (1 << 4),
++	/* Currently on a filemark */
++	IDETAPE_FLAG_FILEMARK		= (1 << 5),
++	/* DRQ interrupt device */
++	IDETAPE_FLAG_DRQ_INTERRUPT	= (1 << 6),
++	/* pipeline active */
++	IDETAPE_FLAG_PIPELINE_ACTIVE	= (1 << 7),
++	/* 0 = no tape is loaded, so we don't rewind after ejecting */
++	IDETAPE_FLAG_MEDIUM_PRESENT	= (1 << 8),
++};
+ 
+ /* A pipeline stage. */
+ typedef struct idetape_stage_s {
+@@ -258,11 +272,11 @@ typedef struct ide_tape_obj {
+ 	 *	retry, to get detailed information on what went wrong.
+ 	 */
+ 	/* Current packet command */
+-	idetape_pc_t *pc;
++	struct ide_atapi_pc *pc;
+ 	/* Last failed packet command */
+-	idetape_pc_t *failed_pc;
++	struct ide_atapi_pc *failed_pc;
+ 	/* Packet command stack */
+-	idetape_pc_t pc_stack[IDETAPE_PC_STACK];
++	struct ide_atapi_pc pc_stack[IDETAPE_PC_STACK];
+ 	/* Next free packet command storage space */
+ 	int pc_stack_index;
+ 	struct request rq_stack[IDETAPE_PC_STACK];
+@@ -446,58 +460,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
+ 	mutex_unlock(&idetape_ref_mutex);
+ }
+ 
+-/* Tape door status */
+-#define DOOR_UNLOCKED			0
+-#define DOOR_LOCKED			1
+-#define DOOR_EXPLICITLY_LOCKED		2
+-
+-/*
+- *	Tape flag bits values.
+- */
+-#define IDETAPE_IGNORE_DSC		0
+-#define IDETAPE_ADDRESS_VALID		1	/* 0 When the tape position is unknown */
+-#define IDETAPE_BUSY			2	/* Device already opened */
+-#define IDETAPE_PIPELINE_ERROR		3	/* Error detected in a pipeline stage */
+-#define IDETAPE_DETECT_BS		4	/* Attempt to auto-detect the current user block size */
+-#define IDETAPE_FILEMARK		5	/* Currently on a filemark */
+-#define IDETAPE_DRQ_INTERRUPT		6	/* DRQ interrupt device */
+-#define IDETAPE_READ_ERROR		7
+-#define IDETAPE_PIPELINE_ACTIVE		8	/* pipeline active */
+-/* 0 = no tape is loaded, so we don't rewind after ejecting */
+-#define IDETAPE_MEDIUM_PRESENT		9
+-
+-/* Some defines for the SPACE command */
+-#define IDETAPE_SPACE_OVER_FILEMARK	1
+-#define IDETAPE_SPACE_TO_EOD		3
+-
+-/* Some defines for the LOAD UNLOAD command */
+-#define IDETAPE_LU_LOAD_MASK		1
+-#define IDETAPE_LU_RETENSION_MASK	2
+-#define IDETAPE_LU_EOT_MASK		4
+-
+-/*
+- * Special requests for our block device strategy routine.
+- *
+- * In order to service a character device command, we add special requests to
+- * the tail of our block device request queue and wait for their completion.
+- */
+-
+-enum {
+-	REQ_IDETAPE_PC1		= (1 << 0), /* packet command (first stage) */
+-	REQ_IDETAPE_PC2		= (1 << 1), /* packet command (second stage) */
+-	REQ_IDETAPE_READ	= (1 << 2),
+-	REQ_IDETAPE_WRITE	= (1 << 3),
+-};
+-
+-/* Error codes returned in rq->errors to the higher part of the driver. */
+-#define	IDETAPE_ERROR_GENERAL		101
+-#define	IDETAPE_ERROR_FILEMARK		102
+-#define	IDETAPE_ERROR_EOD		103
+-
+-/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
+-#define IDETAPE_BLOCK_DESCRIPTOR	0
+-#define	IDETAPE_CAPABILITIES_PAGE	0x2a
+-
+ /*
+  * The variables below are used for the character device interface. Additional
+  * state variables are defined in our ide_drive_t structure.
+@@ -518,17 +480,7 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
+ 	return tape;
+ }
+ 
+-/*
+- * Too bad. The drive wants to send us data which we are not ready to accept.
+- * Just throw it away.
+- */
+-static void idetape_discard_data(ide_drive_t *drive, unsigned int bcount)
+-{
+-	while (bcount--)
+-		(void) HWIF(drive)->INB(IDE_DATA_REG);
+-}
+-
+-static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
++static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ 				  unsigned int bcount)
+ {
+ 	struct idetape_bh *bh = pc->bh;
+@@ -538,7 +490,7 @@ static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
+ 		if (bh == NULL) {
+ 			printk(KERN_ERR "ide-tape: bh == NULL in "
+ 				"idetape_input_buffers\n");
+-			idetape_discard_data(drive, bcount);
++			ide_atapi_discard_data(drive, bcount);
+ 			return;
+ 		}
+ 		count = min(
+@@ -557,7 +509,7 @@ static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
+ 	pc->bh = bh;
+ }
+ 
+-static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
++static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ 				   unsigned int bcount)
+ {
+ 	struct idetape_bh *bh = pc->bh;
+@@ -585,13 +537,13 @@ static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
+ 	}
+ }
+ 
+-static void idetape_update_buffers(idetape_pc_t *pc)
++static void idetape_update_buffers(struct ide_atapi_pc *pc)
+ {
+ 	struct idetape_bh *bh = pc->bh;
+ 	int count;
+-	unsigned int bcount = pc->actually_transferred;
++	unsigned int bcount = pc->xferred;
+ 
+-	if (test_bit(PC_WRITING, &pc->flags))
++	if (pc->flags & PC_FLAG_WRITING)
+ 		return;
+ 	while (bcount) {
+ 		if (bh == NULL) {
+@@ -614,7 +566,7 @@ static void idetape_update_buffers(idetape_pc_t *pc)
+  *	driver. A storage space for a maximum of IDETAPE_PC_STACK packet
+  *	commands is allocated at initialization time.
+  */
+-static idetape_pc_t *idetape_next_pc_storage(ide_drive_t *drive)
++static struct ide_atapi_pc *idetape_next_pc_storage(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 
+@@ -649,14 +601,14 @@ static struct request *idetape_next_rq_storage(ide_drive_t *drive)
+ 	return (&tape->rq_stack[tape->rq_stack_index++]);
+ }
+ 
+-static void idetape_init_pc(idetape_pc_t *pc)
++static void idetape_init_pc(struct ide_atapi_pc *pc)
+ {
+ 	memset(pc->c, 0, 12);
+ 	pc->retries = 0;
+ 	pc->flags = 0;
+-	pc->request_transfer = 0;
+-	pc->buffer = pc->pc_buffer;
+-	pc->buffer_size = IDETAPE_PC_BUFFER_SIZE;
++	pc->req_xfer = 0;
++	pc->buf = pc->pc_buf;
++	pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
+ 	pc->bh = NULL;
+ 	pc->b_data = NULL;
+ }
+@@ -668,7 +620,7 @@ static void idetape_init_pc(idetape_pc_t *pc)
+ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t *pc = tape->failed_pc;
++	struct ide_atapi_pc *pc = tape->failed_pc;
+ 
+ 	tape->sense_key = sense[2] & 0xF;
+ 	tape->asc       = sense[12];
+@@ -677,9 +629,9 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
+ 	debug_log(DBG_ERR, "pc = %x, sense key = %x, asc = %x, ascq = %x\n",
+ 		 pc->c[0], tape->sense_key, tape->asc, tape->ascq);
+ 
+-	/* Correct pc->actually_transferred by asking the tape.	 */
+-	if (test_bit(PC_DMA_ERROR, &pc->flags)) {
+-		pc->actually_transferred = pc->request_transfer -
++	/* Correct pc->xferred by asking the tape.	 */
++	if (pc->flags & PC_FLAG_DMA_ERROR) {
++		pc->xferred = pc->req_xfer -
+ 			tape->blk_size *
+ 			be32_to_cpu(get_unaligned((u32 *)&sense[3]));
+ 		idetape_update_buffers(pc);
+@@ -697,27 +649,27 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
+ 			/* don't report an error, everything's ok */
+ 			pc->error = 0;
+ 			/* don't retry read/write */
+-			set_bit(PC_ABORT, &pc->flags);
++			pc->flags |= PC_FLAG_ABORT;
+ 		}
+ 	}
+ 	if (pc->c[0] == READ_6 && (sense[2] & 0x80)) {
+ 		pc->error = IDETAPE_ERROR_FILEMARK;
+-		set_bit(PC_ABORT, &pc->flags);
++		pc->flags |= PC_FLAG_ABORT;
+ 	}
+ 	if (pc->c[0] == WRITE_6) {
+ 		if ((sense[2] & 0x40) || (tape->sense_key == 0xd
+ 		     && tape->asc == 0x0 && tape->ascq == 0x2)) {
+ 			pc->error = IDETAPE_ERROR_EOD;
+-			set_bit(PC_ABORT, &pc->flags);
++			pc->flags |= PC_FLAG_ABORT;
+ 		}
+ 	}
+ 	if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
+ 		if (tape->sense_key == 8) {
+ 			pc->error = IDETAPE_ERROR_EOD;
+-			set_bit(PC_ABORT, &pc->flags);
++			pc->flags |= PC_FLAG_ABORT;
+ 		}
+-		if (!test_bit(PC_ABORT, &pc->flags) &&
+-		    pc->actually_transferred)
++		if (!(pc->flags & PC_FLAG_ABORT) &&
++		    pc->xferred)
+ 			pc->retries = IDETAPE_MAX_PC_RETRIES + 1;
+ 	}
+ }
+@@ -872,14 +824,16 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
+ 		if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
+ 			remove_stage = 1;
+ 			if (error) {
+-				set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++				set_bit(IDETAPE_FLAG_PIPELINE_ERR,
++					&tape->flags);
+ 				if (error == IDETAPE_ERROR_EOD)
+ 					idetape_abort_pipeline(drive,
+ 								active_stage);
+ 			}
+ 		} else if (rq->cmd[0] & REQ_IDETAPE_READ) {
+ 			if (error == IDETAPE_ERROR_EOD) {
+-				set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++				set_bit(IDETAPE_FLAG_PIPELINE_ERR,
++					&tape->flags);
+ 				idetape_abort_pipeline(drive, active_stage);
+ 			}
+ 		}
+@@ -912,7 +866,7 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
+ 	if (remove_stage)
+ 		idetape_remove_stage_head(drive);
+ 	if (tape->active_data_rq == NULL)
+-		clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
++		clear_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags);
+ 	spin_unlock_irqrestore(&tape->lock, flags);
+ 	return 0;
+ }
+@@ -924,7 +878,7 @@ static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive)
+ 	debug_log(DBG_PROCS, "Enter %s\n", __func__);
+ 
+ 	if (!tape->pc->error) {
+-		idetape_analyze_error(drive, tape->pc->buffer);
++		idetape_analyze_error(drive, tape->pc->buf);
+ 		idetape_end_request(drive, 1, 0);
+ 	} else {
+ 		printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - "
+@@ -934,13 +888,13 @@ static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive)
+ 	return ide_stopped;
+ }
+ 
+-static void idetape_create_request_sense_cmd(idetape_pc_t *pc)
++static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = REQUEST_SENSE;
+ 	pc->c[4] = 20;
+-	pc->request_transfer = 20;
+-	pc->callback = &idetape_request_sense_callback;
++	pc->req_xfer = 20;
++	pc->idetape_callback = &idetape_request_sense_callback;
+ }
+ 
+ static void idetape_init_rq(struct request *rq, u8 cmd)
+@@ -965,7 +919,7 @@ static void idetape_init_rq(struct request *rq, u8 cmd)
+  * handling functions should queue request to the lower level part and wait for
+  * their completion using idetape_queue_pc_tail or idetape_queue_rw_tail.
+  */
+-static void idetape_queue_pc_head(ide_drive_t *drive, idetape_pc_t *pc,
++static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ 				  struct request *rq)
+ {
+ 	struct ide_tape_obj *tape = drive->driver_data;
+@@ -984,14 +938,14 @@ static void idetape_queue_pc_head(ide_drive_t *drive, idetape_pc_t *pc,
+ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t *pc;
++	struct ide_atapi_pc *pc;
+ 	struct request *rq;
+ 
+ 	(void)ide_read_error(drive);
+ 	pc = idetape_next_pc_storage(drive);
+ 	rq = idetape_next_rq_storage(drive);
+ 	idetape_create_request_sense_cmd(pc);
+-	set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
++	set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ 	idetape_queue_pc_head(drive, pc, rq);
+ 	return ide_stopped;
+ }
+@@ -1010,7 +964,7 @@ static void idetape_postpone_request(ide_drive_t *drive)
+ 	ide_stall_queue(drive, tape->dsc_poll_freq);
+ }
+ 
+-typedef void idetape_io_buf(ide_drive_t *, idetape_pc_t *, unsigned int);
++typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int);
+ 
+ /*
+  * This is the usual interrupt handler which will be called during a packet
+@@ -1023,7 +977,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t *pc = tape->pc;
++	struct ide_atapi_pc *pc = tape->pc;
+ 	xfer_func_t *xferfunc;
+ 	idetape_io_buf *iobuf;
+ 	unsigned int temp;
+@@ -1038,7 +992,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ 	/* Clear the interrupt */
+ 	stat = ide_read_status(drive);
+ 
+-	if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
++	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
+ 		if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
+ 			/*
+ 			 * A DMA error is sometimes expected. For example,
+@@ -1061,9 +1015,9 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ 			 * data transfer will occur, but no DMA error.
+ 			 * (AS, 19 Apr 2001)
+ 			 */
+-			set_bit(PC_DMA_ERROR, &pc->flags);
++			pc->flags |= PC_FLAG_DMA_ERROR;
+ 		} else {
+-			pc->actually_transferred = pc->request_transfer;
++			pc->xferred = pc->req_xfer;
+ 			idetape_update_buffers(pc);
+ 		}
+ 		debug_log(DBG_PROCS, "DMA finished\n");
+@@ -1073,9 +1027,9 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ 	/* No more interrupts */
+ 	if ((stat & DRQ_STAT) == 0) {
+ 		debug_log(DBG_SENSE, "Packet command completed, %d bytes"
+-				" transferred\n", pc->actually_transferred);
++				" transferred\n", pc->xferred);
+ 
+-		clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
++		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+ 		local_irq_enable();
+ 
+ #if SIMULATE_ERRORS
+@@ -1088,7 +1042,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ #endif
+ 		if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
+ 			stat &= ~ERR_STAT;
+-		if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
++		if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
+ 			/* Error detected */
+ 			debug_log(DBG_ERR, "%s: I/O error\n", tape->name);
+ 
+@@ -1104,7 +1058,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ 			return idetape_retry_pc(drive);
+ 		}
+ 		pc->error = 0;
+-		if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) &&
++		if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
+ 		    (stat & SEEK_STAT) == 0) {
+ 			/* Media access command */
+ 			tape->dsc_polling_start = jiffies;
+@@ -1117,9 +1071,11 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ 		if (tape->failed_pc == pc)
+ 			tape->failed_pc = NULL;
+ 		/* Command finished - Call the callback function */
+-		return pc->callback(drive);
++		return pc->idetape_callback(drive);
+ 	}
+-	if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
++
++	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
++		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+ 		printk(KERN_ERR "ide-tape: The tape wants to issue more "
+ 				"interrupts in DMA mode\n");
+ 		printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
+@@ -1127,16 +1083,16 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ 		return ide_do_reset(drive);
+ 	}
+ 	/* Get the number of bytes to transfer on this interrupt. */
+-	bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
+-		  hwif->INB(IDE_BCOUNTL_REG);
++	bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
++		  hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
+ 
+-	ireason = hwif->INB(IDE_IREASON_REG);
++	ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ 
+ 	if (ireason & CD) {
+ 		printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__);
+ 		return ide_do_reset(drive);
+ 	}
+-	if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
++	if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
+ 		/* Hopefully, we will never get here */
+ 		printk(KERN_ERR "ide-tape: We wanted to %s, ",
+ 				(ireason & IO) ? "Write" : "Read");
+@@ -1144,15 +1100,15 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ 				(ireason & IO) ? "Read" : "Write");
+ 		return ide_do_reset(drive);
+ 	}
+-	if (!test_bit(PC_WRITING, &pc->flags)) {
++	if (!(pc->flags & PC_FLAG_WRITING)) {
+ 		/* Reading - Check that we have enough space */
+-		temp = pc->actually_transferred + bcount;
+-		if (temp > pc->request_transfer) {
+-			if (temp > pc->buffer_size) {
++		temp = pc->xferred + bcount;
++		if (temp > pc->req_xfer) {
++			if (temp > pc->buf_size) {
+ 				printk(KERN_ERR "ide-tape: The tape wants to "
+ 					"send us more data than expected "
+ 					"- discarding data\n");
+-				idetape_discard_data(drive, bcount);
++				ide_atapi_discard_data(drive, bcount);
+ 				ide_set_handler(drive, &idetape_pc_intr,
+ 						IDETAPE_WAIT_CMD, NULL);
+ 				return ide_started;
+@@ -1170,11 +1126,11 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ 	if (pc->bh)
+ 		iobuf(drive, pc, bcount);
+ 	else
+-		xferfunc(drive, pc->current_position, bcount);
++		xferfunc(drive, pc->cur_pos, bcount);
+ 
+ 	/* Update the current position */
+-	pc->actually_transferred += bcount;
+-	pc->current_position += bcount;
++	pc->xferred += bcount;
++	pc->cur_pos += bcount;
+ 
+ 	debug_log(DBG_SENSE, "[cmd %x] transferred %d bytes on that intr.\n",
+ 			pc->c[0], bcount);
+@@ -1224,7 +1180,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t *pc = tape->pc;
++	struct ide_atapi_pc *pc = tape->pc;
+ 	int retries = 100;
+ 	ide_startstop_t startstop;
+ 	u8 ireason;
+@@ -1234,12 +1190,12 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ 				"yet DRQ isn't asserted\n");
+ 		return startstop;
+ 	}
+-	ireason = hwif->INB(IDE_IREASON_REG);
++	ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ 	while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
+ 		printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
+ 				"a packet command, retrying\n");
+ 		udelay(100);
+-		ireason = hwif->INB(IDE_IREASON_REG);
++		ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ 		if (retries == 0) {
+ 			printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
+ 					"issuing a packet command, ignoring\n");
+@@ -1256,7 +1212,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ 	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+ 	/* Begin DMA, if necessary */
+-	if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags))
++	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS)
+ 		hwif->dma_start(drive);
+ #endif
+ 	/* Send the actual packet */
+@@ -1264,7 +1220,8 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ 	return ide_started;
+ }
+ 
+-static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
++static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
++		struct ide_atapi_pc *pc)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	idetape_tape_t *tape = drive->driver_data;
+@@ -1283,13 +1240,13 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
+ 	tape->pc = pc;
+ 
+ 	if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
+-	    test_bit(PC_ABORT, &pc->flags)) {
++		(pc->flags & PC_FLAG_ABORT)) {
+ 		/*
+ 		 * We will "abort" retrying a packet command in case legitimate
+ 		 * error code was received (crossing a filemark, or end of the
+ 		 * media, for example).
+ 		 */
+-		if (!test_bit(PC_ABORT, &pc->flags)) {
++		if (!(pc->flags & PC_FLAG_ABORT)) {
+ 			if (!(pc->c[0] == TEST_UNIT_READY &&
+ 			      tape->sense_key == 2 && tape->asc == 4 &&
+ 			     (tape->ascq == 1 || tape->ascq == 8))) {
+@@ -1304,36 +1261,38 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
+ 			pc->error = IDETAPE_ERROR_GENERAL;
+ 		}
+ 		tape->failed_pc = NULL;
+-		return pc->callback(drive);
++		return pc->idetape_callback(drive);
+ 	}
+ 	debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
+ 
+ 	pc->retries++;
+ 	/* We haven't transferred any data yet */
+-	pc->actually_transferred = 0;
+-	pc->current_position = pc->buffer;
++	pc->xferred = 0;
++	pc->cur_pos = pc->buf;
+ 	/* Request to transfer the entire buffer at once */
+-	bcount = pc->request_transfer;
++	bcount = pc->req_xfer;
+ 
+-	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
++	if (pc->flags & PC_FLAG_DMA_ERROR) {
++		pc->flags &= ~PC_FLAG_DMA_ERROR;
+ 		printk(KERN_WARNING "ide-tape: DMA disabled, "
+ 				"reverting to PIO\n");
+ 		ide_dma_off(drive);
+ 	}
+-	if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
++	if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
+ 		dma_ok = !hwif->dma_setup(drive);
+ 
+ 	ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
+ 			   IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
+ 
+-	if (dma_ok)			/* Will begin DMA later */
+-		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
+-	if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
++	if (dma_ok)
++		/* Will begin DMA later */
++		pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
++	if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags)) {
+ 		ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc,
+ 				    IDETAPE_WAIT_CMD, NULL);
+ 		return ide_started;
+ 	} else {
+-		hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
++		hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 		return idetape_transfer_pc(drive);
+ 	}
+ }
+@@ -1349,7 +1308,7 @@ static ide_startstop_t idetape_pc_callback(ide_drive_t *drive)
+ }
+ 
+ /* A mode sense command is used to "sense" tape parameters. */
+-static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code)
++static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = MODE_SENSE;
+@@ -1368,12 +1327,12 @@ static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code)
+ 	/* We will just discard data in that case */
+ 	pc->c[4] = 255;
+ 	if (page_code == IDETAPE_BLOCK_DESCRIPTOR)
+-		pc->request_transfer = 12;
++		pc->req_xfer = 12;
+ 	else if (page_code == IDETAPE_CAPABILITIES_PAGE)
+-		pc->request_transfer = 24;
++		pc->req_xfer = 24;
+ 	else
+-		pc->request_transfer = 50;
+-	pc->callback = &idetape_pc_callback;
++		pc->req_xfer = 50;
++	pc->idetape_callback = &idetape_pc_callback;
+ }
+ 
+ static void idetape_calculate_speeds(ide_drive_t *drive)
+@@ -1442,7 +1401,7 @@ static void idetape_calculate_speeds(ide_drive_t *drive)
+ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t *pc = tape->pc;
++	struct ide_atapi_pc *pc = tape->pc;
+ 	u8 stat;
+ 
+ 	stat = ide_read_status(drive);
+@@ -1463,14 +1422,14 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
+ 		pc->error = IDETAPE_ERROR_GENERAL;
+ 		tape->failed_pc = NULL;
+ 	}
+-	return pc->callback(drive);
++	return pc->idetape_callback(drive);
+ }
+ 
+ static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	struct request *rq = HWGROUP(drive)->rq;
+-	int blocks = tape->pc->actually_transferred / tape->blk_size;
++	int blocks = tape->pc->xferred / tape->blk_size;
+ 
+ 	tape->avg_size += blocks * tape->blk_size;
+ 	tape->insert_size += blocks * tape->blk_size;
+@@ -1502,47 +1461,49 @@ static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
+ 	return ide_stopped;
+ }
+ 
+-static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
++static void idetape_create_read_cmd(idetape_tape_t *tape,
++		struct ide_atapi_pc *pc,
+ 		unsigned int length, struct idetape_bh *bh)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = READ_6;
+ 	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
+ 	pc->c[1] = 1;
+-	pc->callback = &idetape_rw_callback;
++	pc->idetape_callback = &idetape_rw_callback;
+ 	pc->bh = bh;
+ 	atomic_set(&bh->b_count, 0);
+-	pc->buffer = NULL;
+-	pc->buffer_size = length * tape->blk_size;
+-	pc->request_transfer = pc->buffer_size;
+-	if (pc->request_transfer == tape->stage_size)
+-		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
++	pc->buf = NULL;
++	pc->buf_size = length * tape->blk_size;
++	pc->req_xfer = pc->buf_size;
++	if (pc->req_xfer == tape->stage_size)
++		pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ }
+ 
+-static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
++static void idetape_create_write_cmd(idetape_tape_t *tape,
++		struct ide_atapi_pc *pc,
+ 		unsigned int length, struct idetape_bh *bh)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = WRITE_6;
+ 	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
+ 	pc->c[1] = 1;
+-	pc->callback = &idetape_rw_callback;
+-	set_bit(PC_WRITING, &pc->flags);
++	pc->idetape_callback = &idetape_rw_callback;
++	pc->flags |= PC_FLAG_WRITING;
+ 	pc->bh = bh;
+ 	pc->b_data = bh->b_data;
+ 	pc->b_count = atomic_read(&bh->b_count);
+-	pc->buffer = NULL;
+-	pc->buffer_size = length * tape->blk_size;
+-	pc->request_transfer = pc->buffer_size;
+-	if (pc->request_transfer == tape->stage_size)
+-		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
++	pc->buf = NULL;
++	pc->buf_size = length * tape->blk_size;
++	pc->req_xfer = pc->buf_size;
++	if (pc->req_xfer == tape->stage_size)
++		pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ }
+ 
+ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 					  struct request *rq, sector_t block)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t *pc = NULL;
++	struct ide_atapi_pc *pc = NULL;
+ 	struct request *postponed_rq = tape->postponed_rq;
+ 	u8 stat;
+ 
+@@ -1579,10 +1540,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 	stat = ide_read_status(drive);
+ 
+ 	if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
+-		set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
++		set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ 
+ 	if (drive->post_reset == 1) {
+-		set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
++		set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ 		drive->post_reset = 0;
+ 	}
+ 
+@@ -1590,7 +1551,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 		tape->insert_speed = tape->insert_size / 1024 * HZ /
+ 					(jiffies - tape->insert_time);
+ 	idetape_calculate_speeds(drive);
+-	if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) &&
++	if (!test_and_clear_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags) &&
+ 	    (stat & SEEK_STAT) == 0) {
+ 		if (postponed_rq == NULL) {
+ 			tape->dsc_polling_start = jiffies;
+@@ -1629,7 +1590,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 		goto out;
+ 	}
+ 	if (rq->cmd[0] & REQ_IDETAPE_PC1) {
+-		pc = (idetape_pc_t *) rq->buffer;
++		pc = (struct ide_atapi_pc *) rq->buffer;
+ 		rq->cmd[0] &= ~(REQ_IDETAPE_PC1);
+ 		rq->cmd[0] |= REQ_IDETAPE_PC2;
+ 		goto out;
+@@ -1648,7 +1609,7 @@ static inline int idetape_pipeline_active(idetape_tape_t *tape)
+ {
+ 	int rc1, rc2;
+ 
+-	rc1 = test_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
++	rc1 = test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags);
+ 	rc2 = (tape->active_data_rq != NULL);
+ 	return rc1;
+ }
+@@ -1881,7 +1842,7 @@ static void idetape_wait_for_request(ide_drive_t *drive, struct request *rq)
+ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	u8 *readpos = tape->pc->buffer;
++	u8 *readpos = tape->pc->buf;
+ 
+ 	debug_log(DBG_PROCS, "Enter %s\n", __func__);
+ 
+@@ -1894,7 +1855,7 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+ 		if (readpos[0] & 0x4) {
+ 			printk(KERN_INFO "ide-tape: Block location is unknown"
+ 					 "to the tape\n");
+-			clear_bit(IDETAPE_ADDRESS_VALID, &tape->flags);
++			clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+ 			idetape_end_request(drive, 0, 0);
+ 		} else {
+ 			debug_log(DBG_SENSE, "Block Location - %u\n",
+@@ -1903,7 +1864,7 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+ 			tape->partition = readpos[1];
+ 			tape->first_frame =
+ 				be32_to_cpu(*(u32 *)&readpos[4]);
+-			set_bit(IDETAPE_ADDRESS_VALID, &tape->flags);
++			set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+ 			idetape_end_request(drive, 1, 0);
+ 		}
+ 	} else {
+@@ -1917,20 +1878,20 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+  * writing a filemark otherwise.
+  */
+ static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
+-		idetape_pc_t *pc, int write_filemark)
++		struct ide_atapi_pc *pc, int write_filemark)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = WRITE_FILEMARKS;
+ 	pc->c[4] = write_filemark;
+-	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+-	pc->callback = &idetape_pc_callback;
++	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++	pc->idetape_callback = &idetape_pc_callback;
+ }
+ 
+-static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc)
++static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = TEST_UNIT_READY;
+-	pc->callback = &idetape_pc_callback;
++	pc->idetape_callback = &idetape_pc_callback;
+ }
+ 
+ /*
+@@ -1946,7 +1907,7 @@ static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc)
+  * to the request list without waiting for it to be serviced! In that case, we
+  * usually use idetape_queue_pc_head().
+  */
+-static int __idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
++static int __idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
+ {
+ 	struct ide_tape_obj *tape = drive->driver_data;
+ 	struct request rq;
+@@ -1957,24 +1918,24 @@ static int __idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
+ 	return ide_do_drive_cmd(drive, &rq, ide_wait);
+ }
+ 
+-static void idetape_create_load_unload_cmd(ide_drive_t *drive, idetape_pc_t *pc,
+-		int cmd)
++static void idetape_create_load_unload_cmd(ide_drive_t *drive,
++		struct ide_atapi_pc *pc, int cmd)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = START_STOP;
+ 	pc->c[4] = cmd;
+-	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+-	pc->callback = &idetape_pc_callback;
++	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++	pc->idetape_callback = &idetape_pc_callback;
+ }
+ 
+ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	int load_attempted = 0;
+ 
+ 	/* Wait for the tape to become ready */
+-	set_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
++	set_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ 	timeout += jiffies;
+ 	while (time_before(jiffies, timeout)) {
+ 		idetape_create_test_unit_ready_cmd(&pc);
+@@ -1998,14 +1959,14 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
+ 	return -EIO;
+ }
+ 
+-static int idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
++static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
+ {
+ 	return __idetape_queue_pc_tail(drive, pc);
+ }
+ 
+ static int idetape_flush_tape_buffers(ide_drive_t *drive)
+ {
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	int rc;
+ 
+ 	idetape_create_write_filemark_cmd(drive, &pc, 0);
+@@ -2016,18 +1977,18 @@ static int idetape_flush_tape_buffers(ide_drive_t *drive)
+ 	return 0;
+ }
+ 
+-static void idetape_create_read_position_cmd(idetape_pc_t *pc)
++static void idetape_create_read_position_cmd(struct ide_atapi_pc *pc)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = READ_POSITION;
+-	pc->request_transfer = 20;
+-	pc->callback = &idetape_read_position_callback;
++	pc->req_xfer = 20;
++	pc->idetape_callback = &idetape_read_position_callback;
+ }
+ 
+ static int idetape_read_position(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	int position;
+ 
+ 	debug_log(DBG_PROCS, "Enter %s\n", __func__);
+@@ -2039,7 +2000,8 @@ static int idetape_read_position(ide_drive_t *drive)
+ 	return position;
+ }
+ 
+-static void idetape_create_locate_cmd(ide_drive_t *drive, idetape_pc_t *pc,
++static void idetape_create_locate_cmd(ide_drive_t *drive,
++		struct ide_atapi_pc *pc,
+ 		unsigned int block, u8 partition, int skip)
+ {
+ 	idetape_init_pc(pc);
+@@ -2047,12 +2009,12 @@ static void idetape_create_locate_cmd(ide_drive_t *drive, idetape_pc_t *pc,
+ 	pc->c[1] = 2;
+ 	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
+ 	pc->c[8] = partition;
+-	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+-	pc->callback = &idetape_pc_callback;
++	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++	pc->idetape_callback = &idetape_pc_callback;
+ }
+ 
+-static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc,
+-				      int prevent)
++static int idetape_create_prevent_cmd(ide_drive_t *drive,
++		struct ide_atapi_pc *pc, int prevent)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 
+@@ -2063,7 +2025,7 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc,
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = ALLOW_MEDIUM_REMOVAL;
+ 	pc->c[4] = prevent;
+-	pc->callback = &idetape_pc_callback;
++	pc->idetape_callback = &idetape_pc_callback;
+ 	return 1;
+ }
+ 
+@@ -2078,7 +2040,7 @@ static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+ 
+ 	/* Remove merge stage. */
+ 	cnt = tape->merge_stage_size / tape->blk_size;
+-	if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
++	if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ 		++cnt;		/* Filemarks count as 1 sector */
+ 	tape->merge_stage_size = 0;
+ 	if (tape->merge_stage != NULL) {
+@@ -2087,7 +2049,7 @@ static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+ 	}
+ 
+ 	/* Clear pipeline flags. */
+-	clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++	clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
+ 	tape->chrdev_dir = IDETAPE_DIR_NONE;
+ 
+ 	/* Remove pipeline stages. */
+@@ -2124,7 +2086,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	int retval;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 
+ 	if (tape->chrdev_dir == IDETAPE_DIR_READ)
+ 		__idetape_discard_read_pipeline(drive);
+@@ -2201,46 +2163,47 @@ static void idetape_plug_pipeline(ide_drive_t *drive)
+ 	if (tape->next_stage == NULL)
+ 		return;
+ 	if (!idetape_pipeline_active(tape)) {
+-		set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
++		set_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags);
+ 		idetape_activate_next_stage(drive);
+ 		(void) ide_do_drive_cmd(drive, tape->active_data_rq, ide_end);
+ 	}
+ }
+ 
+-static void idetape_create_inquiry_cmd(idetape_pc_t *pc)
++static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = INQUIRY;
+ 	pc->c[4] = 254;
+-	pc->request_transfer = 254;
+-	pc->callback = &idetape_pc_callback;
++	pc->req_xfer = 254;
++	pc->idetape_callback = &idetape_pc_callback;
+ }
+ 
+-static void idetape_create_rewind_cmd(ide_drive_t *drive, idetape_pc_t *pc)
++static void idetape_create_rewind_cmd(ide_drive_t *drive,
++		struct ide_atapi_pc *pc)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = REZERO_UNIT;
+-	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+-	pc->callback = &idetape_pc_callback;
++	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++	pc->idetape_callback = &idetape_pc_callback;
+ }
+ 
+-static void idetape_create_erase_cmd(idetape_pc_t *pc)
++static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = ERASE;
+ 	pc->c[1] = 1;
+-	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+-	pc->callback = &idetape_pc_callback;
++	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++	pc->idetape_callback = &idetape_pc_callback;
+ }
+ 
+-static void idetape_create_space_cmd(idetape_pc_t *pc, int count, u8 cmd)
++static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
+ {
+ 	idetape_init_pc(pc);
+ 	pc->c[0] = SPACE;
+ 	put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
+ 	pc->c[1] = cmd;
+-	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+-	pc->callback = &idetape_pc_callback;
++	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++	pc->idetape_callback = &idetape_pc_callback;
+ }
+ 
+ static void idetape_wait_first_stage(ide_drive_t *drive)
+@@ -2326,7 +2289,7 @@ static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
+ 			idetape_plug_pipeline(drive);
+ 		}
+ 	}
+-	if (test_and_clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
++	if (test_and_clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags))
+ 		/* Return a deferred error */
+ 		return -EIO;
+ 	return blocks;
+@@ -2402,7 +2365,7 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
+ 		__idetape_kfree_stage(tape->merge_stage);
+ 		tape->merge_stage = NULL;
+ 	}
+-	clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++	clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
+ 	tape->chrdev_dir = IDETAPE_DIR_NONE;
+ 
+ 	/*
+@@ -2490,7 +2453,7 @@ static int idetape_init_read(ide_drive_t *drive, int max_stages)
+ 	rq.sector = tape->first_frame;
+ 	rq.nr_sectors = blocks;
+ 	rq.current_nr_sectors = blocks;
+-	if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) &&
++	if (!test_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags) &&
+ 	    tape->nr_stages < max_stages) {
+ 		new_stage = idetape_kmalloc_stage(tape);
+ 		while (new_stage != NULL) {
+@@ -2527,13 +2490,13 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
+ 	debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
+ 
+ 	/* If we are at a filemark, return a read length of 0 */
+-	if (test_bit(IDETAPE_FILEMARK, &tape->flags))
++	if (test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ 		return 0;
+ 
+ 	/* Wait for the next block to reach the head of the pipeline. */
+ 	idetape_init_read(drive, tape->max_stages);
+ 	if (tape->first_stage == NULL) {
+-		if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
++		if (test_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags))
+ 			return 0;
+ 		return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
+ 					tape->merge_stage->bh);
+@@ -2550,7 +2513,7 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
+ 	else {
+ 		idetape_switch_buffers(tape, tape->first_stage);
+ 		if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+-			set_bit(IDETAPE_FILEMARK, &tape->flags);
++			set_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
+ 		spin_lock_irqsave(&tape->lock, flags);
+ 		idetape_remove_stage_head(drive);
+ 		spin_unlock_irqrestore(&tape->lock, flags);
+@@ -2618,7 +2581,7 @@ static int idetape_pipeline_size(ide_drive_t *drive)
+ static int idetape_rewind_tape(ide_drive_t *drive)
+ {
+ 	int retval;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	idetape_tape_t *tape;
+ 	tape = drive->driver_data;
+ 
+@@ -2681,7 +2644,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
+ 					int mt_count)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	unsigned long flags;
+ 	int retval, count = 0;
+ 	int sprev = !!(tape->caps[4] & 0x20);
+@@ -2697,12 +2660,13 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
+ 	if (tape->chrdev_dir == IDETAPE_DIR_READ) {
+ 		/* its a read-ahead buffer, scan it for crossed filemarks. */
+ 		tape->merge_stage_size = 0;
+-		if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
++		if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ 			++count;
+ 		while (tape->first_stage != NULL) {
+ 			if (count == mt_count) {
+ 				if (mt_op == MTFSFM)
+-					set_bit(IDETAPE_FILEMARK, &tape->flags);
++					set_bit(IDETAPE_FLAG_FILEMARK,
++						&tape->flags);
+ 				return 0;
+ 			}
+ 			spin_lock_irqsave(&tape->lock, flags);
+@@ -2786,7 +2750,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
+ 	debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
+ 
+ 	if (tape->chrdev_dir != IDETAPE_DIR_READ) {
+-		if (test_bit(IDETAPE_DETECT_BS, &tape->flags))
++		if (test_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags))
+ 			if (count > tape->blk_size &&
+ 			    (count % tape->blk_size) == 0)
+ 				tape->user_bs_factor = count / tape->blk_size;
+@@ -2829,7 +2793,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
+ 		tape->merge_stage_size = bytes_read-temp;
+ 	}
+ finish:
+-	if (!actually_read && test_bit(IDETAPE_FILEMARK, &tape->flags)) {
++	if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) {
+ 		debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
+ 
+ 		idetape_space_over_filemarks(drive, MTFSF, 1);
+@@ -2938,7 +2902,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
+ 
+ static int idetape_write_filemark(ide_drive_t *drive)
+ {
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 
+ 	/* Write a filemark */
+ 	idetape_create_write_filemark_cmd(drive, &pc, 1);
+@@ -2966,7 +2930,7 @@ static int idetape_write_filemark(ide_drive_t *drive)
+ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	int i, retval;
+ 
+ 	debug_log(DBG_ERR, "Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",
+@@ -3022,7 +2986,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ 					      !IDETAPE_LU_LOAD_MASK);
+ 		retval = idetape_queue_pc_tail(drive, &pc);
+ 		if (!retval)
+-			clear_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
++			clear_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ 		return retval;
+ 	case MTNOP:
+ 		idetape_discard_read_pipeline(drive, 0);
+@@ -3045,9 +3009,9 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ 			    mt_count % tape->blk_size)
+ 				return -EIO;
+ 			tape->user_bs_factor = mt_count / tape->blk_size;
+-			clear_bit(IDETAPE_DETECT_BS, &tape->flags);
++			clear_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ 		} else
+-			set_bit(IDETAPE_DETECT_BS, &tape->flags);
++			set_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ 		return 0;
+ 	case MTSEEK:
+ 		idetape_discard_read_pipeline(drive, 0);
+@@ -3149,7 +3113,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
+ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 
+ 	idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
+ 	if (idetape_queue_pc_tail(drive, &pc)) {
+@@ -3161,10 +3125,10 @@ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
+ 		}
+ 		return;
+ 	}
+-	tape->blk_size = (pc.buffer[4 + 5] << 16) +
+-				(pc.buffer[4 + 6] << 8)  +
+-				 pc.buffer[4 + 7];
+-	tape->drv_write_prot = (pc.buffer[2] & 0x80) >> 7;
++	tape->blk_size = (pc.buf[4 + 5] << 16) +
++				(pc.buf[4 + 6] << 8)  +
++				 pc.buf[4 + 7];
++	tape->drv_write_prot = (pc.buf[2] & 0x80) >> 7;
+ }
+ 
+ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+@@ -3172,7 +3136,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+ 	unsigned int minor = iminor(inode), i = minor & ~0xc0;
+ 	ide_drive_t *drive;
+ 	idetape_tape_t *tape;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	int retval;
+ 
+ 	if (i >= MAX_HWIFS * MAX_DRIVES)
+@@ -3195,24 +3159,24 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+ 
+ 	filp->private_data = tape;
+ 
+-	if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) {
++	if (test_and_set_bit(IDETAPE_FLAG_BUSY, &tape->flags)) {
+ 		retval = -EBUSY;
+ 		goto out_put_tape;
+ 	}
+ 
+ 	retval = idetape_wait_ready(drive, 60 * HZ);
+ 	if (retval) {
+-		clear_bit(IDETAPE_BUSY, &tape->flags);
++		clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ 		printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
+ 		goto out_put_tape;
+ 	}
+ 
+ 	idetape_read_position(drive);
+-	if (!test_bit(IDETAPE_ADDRESS_VALID, &tape->flags))
++	if (!test_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags))
+ 		(void)idetape_rewind_tape(drive);
+ 
+ 	if (tape->chrdev_dir != IDETAPE_DIR_READ)
+-		clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++		clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
+ 
+ 	/* Read block size and write protect status from drive. */
+ 	ide_tape_get_bsize_from_bdesc(drive);
+@@ -3227,7 +3191,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+ 	if (tape->write_prot) {
+ 		if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
+ 		    (filp->f_flags & O_ACCMODE) == O_RDWR) {
+-			clear_bit(IDETAPE_BUSY, &tape->flags);
++			clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ 			retval = -EROFS;
+ 			goto out_put_tape;
+ 		}
+@@ -3272,7 +3236,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
+ {
+ 	struct ide_tape_obj *tape = ide_tape_f(filp);
+ 	ide_drive_t *drive = tape->drive;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	unsigned int minor = iminor(inode);
+ 
+ 	lock_kernel();
+@@ -3292,7 +3256,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
+ 		__idetape_kfree_stage(tape->cache_stage);
+ 		tape->cache_stage = NULL;
+ 	}
+-	if (minor < 128 && test_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags))
++	if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags))
+ 		(void) idetape_rewind_tape(drive);
+ 	if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
+ 		if (tape->door_locked == DOOR_LOCKED) {
+@@ -3302,7 +3266,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
+ 			}
+ 		}
+ 	}
+-	clear_bit(IDETAPE_BUSY, &tape->flags);
++	clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ 	ide_tape_put(tape);
+ 	unlock_kernel();
+ 	return 0;
+@@ -3350,7 +3314,7 @@ static int idetape_identify_device(ide_drive_t *drive)
+ static void idetape_get_inquiry_results(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	char fw_rev[6], vendor_id[10], product_id[18];
+ 
+ 	idetape_create_inquiry_cmd(&pc);
+@@ -3359,9 +3323,9 @@ static void idetape_get_inquiry_results(ide_drive_t *drive)
+ 				tape->name);
+ 		return;
+ 	}
+-	memcpy(vendor_id, &pc.buffer[8], 8);
+-	memcpy(product_id, &pc.buffer[16], 16);
+-	memcpy(fw_rev, &pc.buffer[32], 4);
++	memcpy(vendor_id, &pc.buf[8], 8);
++	memcpy(product_id, &pc.buf[16], 16);
++	memcpy(fw_rev, &pc.buf[32], 4);
+ 
+ 	ide_fixstring(vendor_id, 10, 0);
+ 	ide_fixstring(product_id, 18, 0);
+@@ -3378,7 +3342,7 @@ static void idetape_get_inquiry_results(ide_drive_t *drive)
+ static void idetape_get_mode_sense_results(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t pc;
++	struct ide_atapi_pc pc;
+ 	u8 *caps;
+ 	u8 speed, max_speed;
+ 
+@@ -3392,7 +3356,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
+ 		put_unaligned(6*52, (u16 *)&tape->caps[16]);
+ 		return;
+ 	}
+-	caps = pc.buffer + 4 + pc.buffer[3];
++	caps = pc.buf + 4 + pc.buf[3];
+ 
+ 	/* convert to host order and save for later use */
+ 	speed = be16_to_cpu(*(u16 *)&caps[14]);
+@@ -3506,7 +3470,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
+ 
+ 	/* Command packet DRQ type */
+ 	if (((gcw[0] & 0x60) >> 5) == 1)
+-		set_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags);
++		set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags);
+ 
+ 	tape->min_pipeline = 10;
+ 	tape->max_pipeline = 10;
+diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
+index 4c86a8d..155cc90 100644
+--- a/drivers/ide/ide-taskfile.c
++++ b/drivers/ide/ide-taskfile.c
+@@ -59,32 +59,34 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+ 		SELECT_MASK(drive, 0);
+ 
+ 	if (task->tf_flags & IDE_TFLAG_OUT_DATA)
+-		hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG);
++		hwif->OUTW((tf->hob_data << 8) | tf->data,
++			   hwif->io_ports[IDE_DATA_OFFSET]);
+ 
+ 	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+-		hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG);
++		hwif->OUTB(tf->hob_feature, hwif->io_ports[IDE_FEATURE_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+-		hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG);
++		hwif->OUTB(tf->hob_nsect, hwif->io_ports[IDE_NSECTOR_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+-		hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG);
++		hwif->OUTB(tf->hob_lbal, hwif->io_ports[IDE_SECTOR_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+-		hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG);
++		hwif->OUTB(tf->hob_lbam, hwif->io_ports[IDE_LCYL_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+-		hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG);
++		hwif->OUTB(tf->hob_lbah, hwif->io_ports[IDE_HCYL_OFFSET]);
+ 
+ 	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+-		hwif->OUTB(tf->feature, IDE_FEATURE_REG);
++		hwif->OUTB(tf->feature, hwif->io_ports[IDE_FEATURE_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+-		hwif->OUTB(tf->nsect, IDE_NSECTOR_REG);
++		hwif->OUTB(tf->nsect, hwif->io_ports[IDE_NSECTOR_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+-		hwif->OUTB(tf->lbal, IDE_SECTOR_REG);
++		hwif->OUTB(tf->lbal, hwif->io_ports[IDE_SECTOR_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+-		hwif->OUTB(tf->lbam, IDE_LCYL_REG);
++		hwif->OUTB(tf->lbam, hwif->io_ports[IDE_LCYL_OFFSET]);
+ 	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+-		hwif->OUTB(tf->lbah, IDE_HCYL_REG);
++		hwif->OUTB(tf->lbah, hwif->io_ports[IDE_HCYL_OFFSET]);
+ 
+ 	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+-		hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG);
++		hwif->OUTB((tf->device & HIHI) | drive->select.all,
++			   hwif->io_ports[IDE_SELECT_OFFSET]);
+ }
+ 
+ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
+@@ -152,7 +154,8 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ 	switch (task->data_phase) {
+ 	case TASKFILE_MULTI_OUT:
+ 	case TASKFILE_OUT:
+-		hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG);
++		hwif->OUTBSYNC(drive, tf->command,
++			       hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 		ndelay(400);	/* FIXME */
+ 		return pre_task_out_intr(drive, task->rq);
+ 	case TASKFILE_MULTI_IN:
+diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
+index fc69fe2..d868ca4 100644
+--- a/drivers/ide/ide.c
++++ b/drivers/ide/ide.c
+@@ -78,6 +78,8 @@
+ /* default maximum number of failures */
+ #define IDE_DEFAULT_MAX_FAILURES 	1
+ 
++struct class *ide_port_class;
++
+ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
+ 					IDE2_MAJOR, IDE3_MAJOR,
+ 					IDE4_MAJOR, IDE5_MAJOR,
+@@ -90,10 +92,6 @@ static int system_bus_speed;	/* holds what we think is VESA/PCI bus speed */
+ DEFINE_MUTEX(ide_cfg_mtx);
+  __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
+ 
+-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+-int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
+-#endif
+-
+ int noautodma = 0;
+ 
+ #ifdef CONFIG_BLK_DEV_IDEACPI
+@@ -102,20 +100,15 @@ int ide_noacpitfs = 1;
+ int ide_noacpionboot = 1;
+ #endif
+ 
+-/*
+- * This is declared extern in ide.h, for access by other IDE modules:
+- */
+ ide_hwif_t ide_hwifs[MAX_HWIFS];	/* master data repository */
+ 
+-EXPORT_SYMBOL(ide_hwifs);
++static void ide_port_init_devices_data(ide_hwif_t *);
+ 
+ /*
+  * Do not even *think* about calling this!
+  */
+ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
+ {
+-	unsigned int unit;
+-
+ 	/* bulk initialize hwif & drive info with zeros */
+ 	memset(hwif, 0, sizeof(ide_hwif_t));
+ 
+@@ -134,8 +127,20 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
+ 
+ 	default_hwif_iops(hwif);
+ 	default_hwif_transport(hwif);
++
++	ide_port_init_devices_data(hwif);
++}
++EXPORT_SYMBOL_GPL(ide_init_port_data);
++
++static void ide_port_init_devices_data(ide_hwif_t *hwif)
++{
++	int unit;
++
+ 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ 		ide_drive_t *drive = &hwif->drives[unit];
++		u8 j = (hwif->index * MAX_DRIVES) + unit;
++
++		memset(drive, 0, sizeof(*drive));
+ 
+ 		drive->media			= ide_disk;
+ 		drive->select.all		= (unit<<4)|0xa0;
+@@ -147,32 +152,13 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
+ 		drive->special.b.set_geometry	= 1;
+ 		drive->name[0]			= 'h';
+ 		drive->name[1]			= 'd';
+-		drive->name[2]			= 'a' + (index * MAX_DRIVES) + unit;
++		drive->name[2]			= 'a' + j;
+ 		drive->max_failures		= IDE_DEFAULT_MAX_FAILURES;
+-		drive->using_dma		= 0;
+-		drive->vdma			= 0;
++
+ 		INIT_LIST_HEAD(&drive->list);
+ 		init_completion(&drive->gendev_rel_comp);
+ 	}
+ }
+-EXPORT_SYMBOL_GPL(ide_init_port_data);
+-
+-static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
+-{
+-	hw_regs_t hw;
+-
+-	memset(&hw, 0, sizeof(hw_regs_t));
+-
+-	ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
+-
+-	memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
+-
+-	hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+-#ifdef CONFIG_BLK_DEV_HD
+-	if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
+-		hwif->noprobe = 1;	/* may be overridden by ide_setup() */
+-#endif
+-}
+ 
+ /*
+  * init_ide_data() sets reasonable default values into all fields
+@@ -194,7 +180,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
+ #define MAGIC_COOKIE 0x12345678
+ static void __init init_ide_data (void)
+ {
+-	ide_hwif_t *hwif;
+ 	unsigned int index;
+ 	static unsigned long magic_cookie = MAGIC_COOKIE;
+ 
+@@ -204,13 +189,9 @@ static void __init init_ide_data (void)
+ 
+ 	/* Initialise all interface structures */
+ 	for (index = 0; index < MAX_HWIFS; ++index) {
+-		hwif = &ide_hwifs[index];
++		ide_hwif_t *hwif = &ide_hwifs[index];
++
+ 		ide_init_port_data(hwif, index);
+-		init_hwif_default(hwif, index);
+-#if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI)
+-		hwif->irq =
+-			ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
+-#endif
+ 	}
+ }
+ 
+@@ -246,30 +227,6 @@ static int ide_system_bus_speed(void)
+ 	return pci_dev_present(pci_default) ? 33 : 50;
+ }
+ 
+-ide_hwif_t * ide_find_port(unsigned long base)
+-{
+-	ide_hwif_t *hwif;
+-	int i;
+-
+-	for (i = 0; i < MAX_HWIFS; i++) {
+-		hwif = &ide_hwifs[i];
+-		if (hwif->io_ports[IDE_DATA_OFFSET] == base)
+-			goto found;
+-	}
+-
+-	for (i = 0; i < MAX_HWIFS; i++) {
+-		hwif = &ide_hwifs[i];
+-		if (hwif->io_ports[IDE_DATA_OFFSET] == 0)
+-			goto found;
+-	}
+-
+-	hwif = NULL;
+-found:
+-	return hwif;
+-}
+-
+-EXPORT_SYMBOL_GPL(ide_find_port);
+-
+ static struct resource* hwif_request_region(ide_hwif_t *hwif,
+ 					    unsigned long addr, int num)
+ {
+@@ -294,29 +251,21 @@ static struct resource* hwif_request_region(ide_hwif_t *hwif,
+ int ide_hwif_request_regions(ide_hwif_t *hwif)
+ {
+ 	unsigned long addr;
+-	unsigned int i;
+ 
+ 	if (hwif->mmio)
+ 		return 0;
++
+ 	addr = hwif->io_ports[IDE_CONTROL_OFFSET];
++
+ 	if (addr && !hwif_request_region(hwif, addr, 1))
+ 		goto control_region_busy;
+-	hwif->straight8 = 0;
++
+ 	addr = hwif->io_ports[IDE_DATA_OFFSET];
+-	if ((addr | 7) == hwif->io_ports[IDE_STATUS_OFFSET]) {
+-		if (!hwif_request_region(hwif, addr, 8))
+-			goto data_region_busy;
+-		hwif->straight8 = 1;
+-		return 0;
+-	}
+-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+-		addr = hwif->io_ports[i];
+-		if (!hwif_request_region(hwif, addr, 1)) {
+-			while (--i)
+-				release_region(addr, 1);
+-			goto data_region_busy;
+-		}
+-	}
++	BUG_ON((addr | 7) != hwif->io_ports[IDE_STATUS_OFFSET]);
++
++	if (!hwif_request_region(hwif, addr, 8))
++		goto data_region_busy;
++
+ 	return 0;
+ 
+ data_region_busy:
+@@ -342,121 +291,13 @@ control_region_busy:
+ 
+ void ide_hwif_release_regions(ide_hwif_t *hwif)
+ {
+-	u32 i = 0;
+-
+ 	if (hwif->mmio)
+ 		return;
++
+ 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
+ 		release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
+-	if (hwif->straight8) {
+-		release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
+-		return;
+-	}
+-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+-		if (hwif->io_ports[i])
+-			release_region(hwif->io_ports[i], 1);
+-}
+-
+-/**
+- *	ide_hwif_restore	-	restore hwif to template
+- *	@hwif: hwif to update
+- *	@tmp_hwif: template
+- *
+- *	Restore hwif to a previous state by copying most settings
+- *	from the template.
+- */
+-
+-static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
+-{
+-	hwif->hwgroup			= tmp_hwif->hwgroup;
+-
+-	hwif->gendev.parent		= tmp_hwif->gendev.parent;
+-
+-	hwif->proc			= tmp_hwif->proc;
+-
+-	hwif->major			= tmp_hwif->major;
+-	hwif->straight8			= tmp_hwif->straight8;
+-	hwif->bus_state			= tmp_hwif->bus_state;
+ 
+-	hwif->host_flags		= tmp_hwif->host_flags;
+-
+-	hwif->pio_mask			= tmp_hwif->pio_mask;
+-
+-	hwif->ultra_mask		= tmp_hwif->ultra_mask;
+-	hwif->mwdma_mask		= tmp_hwif->mwdma_mask;
+-	hwif->swdma_mask		= tmp_hwif->swdma_mask;
+-
+-	hwif->cbl			= tmp_hwif->cbl;
+-
+-	hwif->chipset			= tmp_hwif->chipset;
+-	hwif->hold			= tmp_hwif->hold;
+-
+-	hwif->dev			= tmp_hwif->dev;
+-
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-	hwif->cds			= tmp_hwif->cds;
+-#endif
+-
+-	hwif->set_pio_mode		= tmp_hwif->set_pio_mode;
+-	hwif->set_dma_mode		= tmp_hwif->set_dma_mode;
+-	hwif->mdma_filter		= tmp_hwif->mdma_filter;
+-	hwif->udma_filter		= tmp_hwif->udma_filter;
+-	hwif->selectproc		= tmp_hwif->selectproc;
+-	hwif->reset_poll		= tmp_hwif->reset_poll;
+-	hwif->pre_reset			= tmp_hwif->pre_reset;
+-	hwif->resetproc			= tmp_hwif->resetproc;
+-	hwif->maskproc			= tmp_hwif->maskproc;
+-	hwif->quirkproc			= tmp_hwif->quirkproc;
+-	hwif->busproc			= tmp_hwif->busproc;
+-
+-	hwif->ata_input_data		= tmp_hwif->ata_input_data;
+-	hwif->ata_output_data		= tmp_hwif->ata_output_data;
+-	hwif->atapi_input_bytes		= tmp_hwif->atapi_input_bytes;
+-	hwif->atapi_output_bytes	= tmp_hwif->atapi_output_bytes;
+-
+-	hwif->dma_host_set		= tmp_hwif->dma_host_set;
+-	hwif->dma_setup			= tmp_hwif->dma_setup;
+-	hwif->dma_exec_cmd		= tmp_hwif->dma_exec_cmd;
+-	hwif->dma_start			= tmp_hwif->dma_start;
+-	hwif->ide_dma_end		= tmp_hwif->ide_dma_end;
+-	hwif->ide_dma_test_irq		= tmp_hwif->ide_dma_test_irq;
+-	hwif->ide_dma_clear_irq		= tmp_hwif->ide_dma_clear_irq;
+-	hwif->dma_lost_irq		= tmp_hwif->dma_lost_irq;
+-	hwif->dma_timeout		= tmp_hwif->dma_timeout;
+-
+-	hwif->OUTB			= tmp_hwif->OUTB;
+-	hwif->OUTBSYNC			= tmp_hwif->OUTBSYNC;
+-	hwif->OUTW			= tmp_hwif->OUTW;
+-	hwif->OUTSW			= tmp_hwif->OUTSW;
+-	hwif->OUTSL			= tmp_hwif->OUTSL;
+-
+-	hwif->INB			= tmp_hwif->INB;
+-	hwif->INW			= tmp_hwif->INW;
+-	hwif->INSW			= tmp_hwif->INSW;
+-	hwif->INSL			= tmp_hwif->INSL;
+-
+-	hwif->sg_max_nents		= tmp_hwif->sg_max_nents;
+-
+-	hwif->mmio			= tmp_hwif->mmio;
+-	hwif->rqsize			= tmp_hwif->rqsize;
+-
+-#ifndef CONFIG_BLK_DEV_IDECS
+-	hwif->irq			= tmp_hwif->irq;
+-#endif
+-
+-	hwif->dma_base			= tmp_hwif->dma_base;
+-	hwif->dma_command		= tmp_hwif->dma_command;
+-	hwif->dma_vendor1		= tmp_hwif->dma_vendor1;
+-	hwif->dma_status		= tmp_hwif->dma_status;
+-	hwif->dma_vendor3		= tmp_hwif->dma_vendor3;
+-	hwif->dma_prdtable		= tmp_hwif->dma_prdtable;
+-
+-	hwif->config_data		= tmp_hwif->config_data;
+-	hwif->select_data		= tmp_hwif->select_data;
+-	hwif->extra_base		= tmp_hwif->extra_base;
+-	hwif->extra_ports		= tmp_hwif->extra_ports;
+-
+-	hwif->hwif_data			= tmp_hwif->hwif_data;
++	release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
+ }
+ 
+ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+@@ -494,11 +335,38 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+ 	spin_unlock_irq(&ide_lock);
+ }
+ 
++/* Called with ide_lock held. */
++static void __ide_port_unregister_devices(ide_hwif_t *hwif)
++{
++	int i;
++
++	for (i = 0; i < MAX_DRIVES; i++) {
++		ide_drive_t *drive = &hwif->drives[i];
++
++		if (drive->present) {
++			spin_unlock_irq(&ide_lock);
++			device_unregister(&drive->gendev);
++			wait_for_completion(&drive->gendev_rel_comp);
++			spin_lock_irq(&ide_lock);
++		}
++	}
++}
++
++void ide_port_unregister_devices(ide_hwif_t *hwif)
++{
++	mutex_lock(&ide_cfg_mtx);
++	spin_lock_irq(&ide_lock);
++	__ide_port_unregister_devices(hwif);
++	hwif->present = 0;
++	ide_port_init_devices_data(hwif);
++	spin_unlock_irq(&ide_lock);
++	mutex_unlock(&ide_cfg_mtx);
++}
++EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
++
+ /**
+  *	ide_unregister		-	free an IDE interface
+  *	@index: index of interface (will change soon to a pointer)
+- *	@init_default: init default hwif flag
+- *	@restore: restore hwif flag
+  *
+  *	Perform the final unregister of an IDE interface. At the moment
+  *	we don't refcount interfaces so this will also get split up.
+@@ -518,13 +386,11 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+  *	This is raving bonkers.
+  */
+ 
+-void ide_unregister(unsigned int index, int init_default, int restore)
++void ide_unregister(unsigned int index)
+ {
+-	ide_drive_t *drive;
+ 	ide_hwif_t *hwif, *g;
+-	static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */
+ 	ide_hwgroup_t *hwgroup;
+-	int irq_count = 0, unit;
++	int irq_count = 0;
+ 
+ 	BUG_ON(index >= MAX_HWIFS);
+ 
+@@ -535,15 +401,7 @@ void ide_unregister(unsigned int index, int init_default, int restore)
+ 	hwif = &ide_hwifs[index];
+ 	if (!hwif->present)
+ 		goto abort;
+-	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+-		drive = &hwif->drives[unit];
+-		if (!drive->present)
+-			continue;
+-		spin_unlock_irq(&ide_lock);
+-		device_unregister(&drive->gendev);
+-		wait_for_completion(&drive->gendev_rel_comp);
+-		spin_lock_irq(&ide_lock);
+-	}
++	__ide_port_unregister_devices(hwif);
+ 	hwif->present = 0;
+ 
+ 	spin_unlock_irq(&ide_lock);
+@@ -565,6 +423,7 @@ void ide_unregister(unsigned int index, int init_default, int restore)
+ 
+ 	ide_remove_port_from_hwgroup(hwif);
+ 
++	device_unregister(hwif->portdev);
+ 	device_unregister(&hwif->gendev);
+ 	wait_for_completion(&hwif->gendev_rel_comp);
+ 
+@@ -576,34 +435,14 @@ void ide_unregister(unsigned int index, int init_default, int restore)
+ 	unregister_blkdev(hwif->major, hwif->name);
+ 	spin_lock_irq(&ide_lock);
+ 
+-	if (hwif->dma_base) {
+-		(void) ide_release_dma(hwif);
+-
+-		hwif->dma_base = 0;
+-		hwif->dma_command = 0;
+-		hwif->dma_vendor1 = 0;
+-		hwif->dma_status = 0;
+-		hwif->dma_vendor3 = 0;
+-		hwif->dma_prdtable = 0;
+-
+-		hwif->extra_base  = 0;
+-		hwif->extra_ports = 0;
+-	}
++	if (hwif->dma_base)
++		(void)ide_release_dma(hwif);
+ 
+ 	ide_hwif_release_regions(hwif);
+ 
+-	/* copy original settings */
+-	tmp_hwif = *hwif;
+-
+ 	/* restore hwif data to pristine status */
+ 	ide_init_port_data(hwif, index);
+ 
+-	if (init_default)
+-		init_hwif_default(hwif, index);
+-
+-	if (restore)
+-		ide_hwif_restore(hwif, &tmp_hwif);
+-
+ abort:
+ 	spin_unlock_irq(&ide_lock);
+ 	mutex_unlock(&ide_cfg_mtx);
+@@ -622,79 +461,6 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
+ }
+ EXPORT_SYMBOL_GPL(ide_init_port_hw);
+ 
+-ide_hwif_t *ide_deprecated_find_port(unsigned long base)
+-{
+-	ide_hwif_t *hwif;
+-	int i;
+-
+-	for (i = 0; i < MAX_HWIFS; i++) {
+-		hwif = &ide_hwifs[i];
+-		if (hwif->io_ports[IDE_DATA_OFFSET] == base)
+-			goto found;
+-	}
+-
+-	for (i = 0; i < MAX_HWIFS; i++) {
+-		hwif = &ide_hwifs[i];
+-		if (hwif->hold)
+-			continue;
+-		if (!hwif->present && hwif->mate == NULL)
+-			goto found;
+-	}
+-
+-	hwif = NULL;
+-found:
+-	return hwif;
+-}
+-EXPORT_SYMBOL_GPL(ide_deprecated_find_port);
+-
+-/**
+- *	ide_register_hw		-	register IDE interface
+- *	@hw: hardware registers
+- *	@quirkproc: quirkproc function
+- *	@hwifp: pointer to returned hwif
+- *
+- *	Register an IDE interface, specifying exactly the registers etc.
+- *
+- *	Returns -1 on error.
+- */
+-
+-int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *),
+-		    ide_hwif_t **hwifp)
+-{
+-	int index, retry = 1;
+-	ide_hwif_t *hwif;
+-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+-
+-	do {
+-		hwif = ide_deprecated_find_port(hw->io_ports[IDE_DATA_OFFSET]);
+-		if (hwif)
+-			goto found;
+-		for (index = 0; index < MAX_HWIFS; index++)
+-			ide_unregister(index, 1, 1);
+-	} while (retry--);
+-	return -1;
+-found:
+-	index = hwif->index;
+-	if (hwif->present)
+-		ide_unregister(index, 0, 1);
+-	else if (!hwif->hold)
+-		ide_init_port_data(hwif, index);
+-
+-	ide_init_port_hw(hwif, hw);
+-	hwif->quirkproc = quirkproc;
+-
+-	idx[0] = index;
+-
+-	ide_device_add(idx, NULL);
+-
+-	if (hwifp)
+-		*hwifp = hwif;
+-
+-	return hwif->present ? index : -1;
+-}
+-
+-EXPORT_SYMBOL(ide_register_hw);
+-
+ /*
+  *	Locks for IDE setting functionality
+  */
+@@ -818,11 +584,13 @@ out:
+ int set_pio_mode(ide_drive_t *drive, int arg)
+ {
+ 	struct request rq;
++	ide_hwif_t *hwif = drive->hwif;
+ 
+ 	if (arg < 0 || arg > 255)
+ 		return -EINVAL;
+ 
+-	if (drive->hwif->set_pio_mode == NULL)
++	if (hwif->set_pio_mode == NULL ||
++	    (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ 		return -ENOSYS;
+ 
+ 	if (drive->special.b.set_tune)
+@@ -997,27 +765,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
+ 			if (!capable(CAP_SYS_RAWIO))
+ 				return -EACCES;
+ 			return ide_task_ioctl(drive, cmd, arg);
+-
+-		case HDIO_SCAN_HWIF:
+-		{
+-			hw_regs_t hw;
+-			int args[3];
+-			if (!capable(CAP_SYS_RAWIO)) return -EACCES;
+-			if (copy_from_user(args, p, 3 * sizeof(int)))
+-				return -EFAULT;
+-			memset(&hw, 0, sizeof(hw));
+-			ide_init_hwif_ports(&hw, (unsigned long) args[0],
+-					    (unsigned long) args[1], NULL);
+-			hw.irq = args[2];
+-			if (ide_register_hw(&hw, NULL, NULL) == -1)
+-				return -EIO;
+-			return 0;
+-		}
+-	        case HDIO_UNREGISTER_HWIF:
+-			if (!capable(CAP_SYS_RAWIO)) return -EACCES;
+-			/* (arg > MAX_HWIFS) checked in function */
+-			ide_unregister(arg, 1, 1);
+-			return 0;
+ 		case HDIO_SET_NICE:
+ 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ 			if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
+@@ -1071,8 +818,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
+ 		case HDIO_SET_BUSSTATE:
+ 			if (!capable(CAP_SYS_ADMIN))
+ 				return -EACCES;
+-			if (HWIF(drive)->busproc)
+-				return HWIF(drive)->busproc(drive, (int)arg);
+ 			return -EOPNOTSUPP;
+ 		default:
+ 			return -EINVAL;
+@@ -1173,8 +918,9 @@ extern int probe_dtc2278;
+ extern int probe_ht6560b;
+ extern int probe_qd65xx;
+ extern int cmd640_vlb;
++extern int probe_4drives;
+ 
+-static int __initdata is_chipset_set[MAX_HWIFS];
++static int __initdata is_chipset_set;
+ 
+ /*
+  * ide_setup() gets called VERY EARLY during initialization,
+@@ -1217,14 +963,6 @@ static int __init ide_setup(char *s)
+ 		goto obsolete_option;
+ 	}
+ 
+-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+-	if (!strcmp(s, "ide=reverse")) {
+-		ide_scan_direction = 1;
+-		printk(" : Enabled support for IDE inverse scan order.\n");
+-		goto obsolete_option;
+-	}
+-#endif
+-
+ #ifdef CONFIG_BLK_DEV_IDEACPI
+ 	if (!strcmp(s, "ide=noacpi")) {
+ 		//printk(" : Disable IDE ACPI support.\n");
+@@ -1335,13 +1073,11 @@ static int __init ide_setup(char *s)
+ 		 * (-8, -9, -10) are reserved to ease the hardcoding.
+ 		 */
+ 		static const char *ide_words[] = {
+-			"noprobe", "serialize", "minus3", "minus4",
++			"minus1", "serialize", "minus3", "minus4",
+ 			"reset", "minus6", "ata66", "minus8", "minus9",
+ 			"minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb",
+ 			"dtc2278", "umc8672", "ali14xx", NULL };
+ 
+-		hw_regs_t hwregs;
+-
+ 		hw = s[3] - '0';
+ 		hwif = &ide_hwifs[hw];
+ 		i = match_parm(&s[4], ide_words, vals, 3);
+@@ -1350,19 +1086,14 @@ static int __init ide_setup(char *s)
+ 		 * Cryptic check to ensure chipset not already set for hwif.
+ 		 * Note: we can't depend on hwif->chipset here.
+ 		 */
+-		if ((i >= -18 && i <= -11) || (i > 0 && i <= 3)) {
++		if (i >= -18 && i <= -11) {
+ 			/* chipset already specified */
+-			if (is_chipset_set[hw])
++			if (is_chipset_set)
+ 				goto bad_option;
+-			if (i > -18 && i <= -11) {
+-				/* these drivers are for "ide0=" only */
+-				if (hw != 0)
+-					goto bad_hwif;
+-				/* chipset already specified for 2nd port */
+-				if (is_chipset_set[hw+1])
+-					goto bad_option;
+-			}
+-			is_chipset_set[hw] = 1;
++			/* these drivers are for "ide0=" only */
++			if (hw != 0)
++				goto bad_hwif;
++			is_chipset_set = 1;
+ 			printk("\n");
+ 		}
+ 
+@@ -1399,19 +1130,9 @@ static int __init ide_setup(char *s)
+ #endif
+ #ifdef CONFIG_BLK_DEV_4DRIVES
+ 			case -11: /* "four" drives on one set of ports */
+-			{
+-				ide_hwif_t *mate = &ide_hwifs[hw^1];
+-				mate->drives[0].select.all ^= 0x20;
+-				mate->drives[1].select.all ^= 0x20;
+-				hwif->chipset = mate->chipset = ide_4drives;
+-				mate->irq = hwif->irq;
+-				memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports));
+-				hwif->mate = mate;
+-				mate->mate = hwif;
+-				hwif->serialized = mate->serialized = 1;
++				probe_4drives = 1;
+ 				goto obsolete_option;
+-			}
+-#endif /* CONFIG_BLK_DEV_4DRIVES */
++#endif
+ 			case -10: /* minus10 */
+ 			case -9: /* minus9 */
+ 			case -8: /* minus8 */
+@@ -1439,24 +1160,12 @@ static int __init ide_setup(char *s)
+ 				hwif->serialized = hwif->mate->serialized = 1;
+ 				goto obsolete_option;
+ 
+-			case -1: /* "noprobe" */
+-				hwif->noprobe = 1;
+-				goto obsolete_option;
+-
+-			case 1:	/* base */
+-				vals[1] = vals[0] + 0x206; /* default ctl */
+-			case 2: /* base,ctl */
+-				vals[2] = 0;	/* default irq = probe for it */
+-			case 3: /* base,ctl,irq */
+-				memset(&hwregs, 0, sizeof(hwregs));
+-				ide_init_hwif_ports(&hwregs, vals[0], vals[1], &hwif->irq);
+-				memcpy(hwif->io_ports, hwregs.io_ports, sizeof(hwif->io_ports));
+-				hwif->irq      = vals[2];
+-				hwif->noprobe  = 0;
+-				hwif->chipset  = ide_forced;
+-				goto obsolete_option;
+-
+-			case 0: goto bad_option;
++			case -1:
++			case 0:
++			case 1:
++			case 2:
++			case 3:
++				goto bad_option;
+ 			default:
+ 				printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n");
+ 				return 1;
+@@ -1601,6 +1310,13 @@ struct bus_type ide_bus_type = {
+ 
+ EXPORT_SYMBOL_GPL(ide_bus_type);
+ 
++static void ide_port_class_release(struct device *portdev)
++{
++	ide_hwif_t *hwif = dev_get_drvdata(portdev);
++
++	put_device(&hwif->gendev);
++}
++
+ /*
+  * This is gets invoked once during initialization, to set *everything* up
+  */
+@@ -1621,11 +1337,23 @@ static int __init ide_init(void)
+ 		return ret;
+ 	}
+ 
++	ide_port_class = class_create(THIS_MODULE, "ide_port");
++	if (IS_ERR(ide_port_class)) {
++		ret = PTR_ERR(ide_port_class);
++		goto out_port_class;
++	}
++	ide_port_class->dev_release = ide_port_class_release;
++
+ 	init_ide_data();
+ 
+ 	proc_ide_create();
+ 
+ 	return 0;
++
++out_port_class:
++	bus_unregister(&ide_bus_type);
++
++	return ret;
+ }
+ 
+ #ifdef MODULE
+@@ -1658,10 +1386,12 @@ void __exit cleanup_module (void)
+ 	int index;
+ 
+ 	for (index = 0; index < MAX_HWIFS; ++index)
+-		ide_unregister(index, 0, 0);
++		ide_unregister(index);
+ 
+ 	proc_ide_destroy();
+ 
++	class_destroy(ide_port_class);
++
+ 	bus_unregister(&ide_bus_type);
+ }
+ 
+diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
+index 7043ec7..6939329 100644
+--- a/drivers/ide/legacy/Makefile
++++ b/drivers/ide/legacy/Makefile
+@@ -6,6 +6,7 @@ obj-$(CONFIG_BLK_DEV_UMC8672)		+= umc8672.o
+ obj-$(CONFIG_BLK_DEV_DTC2278)		+= dtc2278.o
+ obj-$(CONFIG_BLK_DEV_HT6560B)		+= ht6560b.o
+ obj-$(CONFIG_BLK_DEV_QD65XX)		+= qd65xx.o
++obj-$(CONFIG_BLK_DEV_4DRIVES)		+= ide-4drives.o
+ 
+ obj-$(CONFIG_BLK_DEV_GAYLE)		+= gayle.o
+ obj-$(CONFIG_BLK_DEV_FALCON_IDE)	+= falconide.o
+diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
+index d4d1a6b..33bb7b8 100644
+--- a/drivers/ide/legacy/ali14xx.c
++++ b/drivers/ide/legacy/ali14xx.c
+@@ -86,7 +86,7 @@ static u8 regOff;	/* output to base port to close registers */
+ /*
+  * Read a controller register.
+  */
+-static inline u8 inReg (u8 reg)
++static inline u8 inReg(u8 reg)
+ {
+ 	outb_p(reg, regPort);
+ 	return inb(dataPort);
+@@ -95,7 +95,7 @@ static inline u8 inReg (u8 reg)
+ /*
+  * Write a controller register.
+  */
+-static void outReg (u8 data, u8 reg)
++static void outReg(u8 data, u8 reg)
+ {
+ 	outb_p(reg, regPort);
+ 	outb_p(data, dataPort);
+@@ -143,7 +143,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ /*
+  * Auto-detect the IDE controller port.
+  */
+-static int __init findPort (void)
++static int __init findPort(void)
+ {
+ 	int i;
+ 	u8 t;
+@@ -175,7 +175,8 @@ static int __init findPort (void)
+ /*
+  * Initialize controller registers with default values.
+  */
+-static int __init initRegisters (void) {
++static int __init initRegisters(void)
++{
+ 	const RegInitializer *p;
+ 	u8 t;
+ 	unsigned long flags;
+@@ -199,7 +200,9 @@ static const struct ide_port_info ali14xx_port_info = {
+ 
+ static int __init ali14xx_probe(void)
+ {
+-	static u8 idx[4] = { 0, 1, 0xff, 0xff };
++	ide_hwif_t *hwif, *mate;
++	static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	hw_regs_t hw[2];
+ 
+ 	printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
+ 			  basePort, regOn);
+@@ -210,15 +213,34 @@ static int __init ali14xx_probe(void)
+ 		return 1;
+ 	}
+ 
+-	ide_hwifs[0].set_pio_mode = &ali14xx_set_pio_mode;
+-	ide_hwifs[1].set_pio_mode = &ali14xx_set_pio_mode;
++	memset(&hw, 0, sizeof(hw));
++
++	ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++	hw[0].irq = 14;
++
++	ide_std_init_ports(&hw[1], 0x170, 0x376);
++	hw[1].irq = 15;
++
++	hwif = ide_find_port();
++	if (hwif) {
++		ide_init_port_hw(hwif, &hw[0]);
++		hwif->set_pio_mode = &ali14xx_set_pio_mode;
++		idx[0] = hwif->index;
++	}
++
++	mate = ide_find_port();
++	if (mate) {
++		ide_init_port_hw(mate, &hw[1]);
++		mate->set_pio_mode = &ali14xx_set_pio_mode;
++		idx[1] = mate->index;
++	}
+ 
+ 	ide_device_add(idx, &ali14xx_port_info);
+ 
+ 	return 0;
+ }
+ 
+-int probe_ali14xx = 0;
++int probe_ali14xx;
+ 
+ module_param_named(probe, probe_ali14xx, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
+diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
+index fdd3791..6956eb8 100644
+--- a/drivers/ide/legacy/buddha.c
++++ b/drivers/ide/legacy/buddha.c
+@@ -221,7 +221,7 @@ fail_base2:
+ 
+ 			buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
+ 
+-			hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++			hwif = ide_find_port();
+ 			if (hwif) {
+ 				u8 index = hwif->index;
+ 
+diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
+index 73396f7..9c6b324 100644
+--- a/drivers/ide/legacy/dtc2278.c
++++ b/drivers/ide/legacy/dtc2278.c
+@@ -102,13 +102,8 @@ static int __init dtc2278_probe(void)
+ {
+ 	unsigned long flags;
+ 	ide_hwif_t *hwif, *mate;
+-	static u8 idx[4] = { 0, 1, 0xff, 0xff };
+-
+-	hwif = &ide_hwifs[0];
+-	mate = &ide_hwifs[1];
+-
+-	if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown)
+-		return 1;
++	static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	hw_regs_t hw[2];
+ 
+ 	local_irq_save(flags);
+ 	/*
+@@ -128,7 +123,26 @@ static int __init dtc2278_probe(void)
+ #endif
+ 	local_irq_restore(flags);
+ 
+-	hwif->set_pio_mode = &dtc2278_set_pio_mode;
++	memset(&hw, 0, sizeof(hw));
++
++	ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++	hw[0].irq = 14;
++
++	ide_std_init_ports(&hw[1], 0x170, 0x376);
++	hw[1].irq = 15;
++
++	hwif = ide_find_port();
++	if (hwif) {
++		ide_init_port_hw(hwif, &hw[0]);
++		hwif->set_pio_mode = dtc2278_set_pio_mode;
++		idx[0] = hwif->index;
++	}
++
++	mate = ide_find_port();
++	if (mate) {
++		ide_init_port_hw(mate, &hw[1]);
++		idx[1] = mate->index;
++	}
+ 
+ 	ide_device_add(idx, &dtc2278_port_info);
+ 
+diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
+index e950afa..8c9c9f7 100644
+--- a/drivers/ide/legacy/falconide.c
++++ b/drivers/ide/legacy/falconide.c
+@@ -22,6 +22,7 @@
+ #include <asm/atariints.h>
+ #include <asm/atari_stdma.h>
+ 
++#define DRV_NAME "falconide"
+ 
+     /*
+      *  Base of the IDE interface
+@@ -74,15 +75,21 @@ static int __init falconide_init(void)
+ 
+ 	printk(KERN_INFO "ide: Falcon IDE controller\n");
+ 
++	if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) {
++		printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
++		return -EBUSY;
++	}
++
+ 	falconide_setup_ports(&hw);
+ 
+-	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	hwif = ide_find_port();
+ 	if (hwif) {
+ 		u8 index = hwif->index;
+ 		u8 idx[4] = { index, 0xff, 0xff, 0xff };
+ 
+ 		ide_init_port_data(hwif, index);
+ 		ide_init_port_hw(hwif, &hw);
++		hwif->mmio = 1;
+ 
+ 		ide_get_lock(NULL, NULL);
+ 		ide_device_add(idx, NULL);
+diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
+index e3b4638..fcc8d52 100644
+--- a/drivers/ide/legacy/gayle.c
++++ b/drivers/ide/legacy/gayle.c
+@@ -175,7 +175,7 @@ found:
+ 
+ 	gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
+ 
+-	hwif = ide_find_port(base);
++	hwif = ide_find_port();
+ 	if (hwif) {
+ 	    u8 index = hwif->index;
+ 
+diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
+index 0b0d867..abdedf5 100644
+--- a/drivers/ide/legacy/hd.c
++++ b/drivers/ide/legacy/hd.c
+@@ -122,12 +122,12 @@ static int hd_error;
+  *  This struct defines the HD's and their types.
+  */
+ struct hd_i_struct {
+-	unsigned int head,sect,cyl,wpcom,lzone,ctl;
++	unsigned int head, sect, cyl, wpcom, lzone, ctl;
+ 	int unit;
+ 	int recalibrate;
+ 	int special_op;
+ };
+-	
++
+ #ifdef HD_TYPE
+ static struct hd_i_struct hd_info[] = { HD_TYPE };
+ static int NR_HD = ARRAY_SIZE(hd_info);
+@@ -168,7 +168,7 @@ unsigned long read_timer(void)
+ 
+ 	spin_lock_irqsave(&i8253_lock, flags);
+ 	t = jiffies * 11932;
+-    	outb_p(0, 0x43);
++	outb_p(0, 0x43);
+ 	i = inb_p(0x40);
+ 	i |= inb(0x40) << 8;
+ 	spin_unlock_irqrestore(&i8253_lock, flags);
+@@ -183,7 +183,7 @@ static void __init hd_setup(char *str, int *ints)
+ 	if (ints[0] != 3)
+ 		return;
+ 	if (hd_info[0].head != 0)
+-		hdind=1;
++		hdind = 1;
+ 	hd_info[hdind].head = ints[2];
+ 	hd_info[hdind].sect = ints[3];
+ 	hd_info[hdind].cyl = ints[1];
+@@ -193,7 +193,7 @@ static void __init hd_setup(char *str, int *ints)
+ 	NR_HD = hdind+1;
+ }
+ 
+-static void dump_status (const char *msg, unsigned int stat)
++static void dump_status(const char *msg, unsigned int stat)
+ {
+ 	char *name = "hd?";
+ 	if (CURRENT)
+@@ -291,7 +291,6 @@ static int controller_ready(unsigned int drive, unsigned int head)
+ 	return 0;
+ }
+ 
+-		
+ static void hd_out(struct hd_i_struct *disk,
+ 		   unsigned int nsect,
+ 		   unsigned int sect,
+@@ -313,15 +312,15 @@ static void hd_out(struct hd_i_struct *disk,
+ 		return;
+ 	}
+ 	SET_HANDLER(intr_addr);
+-	outb_p(disk->ctl,HD_CMD);
+-	port=HD_DATA;
+-	outb_p(disk->wpcom>>2,++port);
+-	outb_p(nsect,++port);
+-	outb_p(sect,++port);
+-	outb_p(cyl,++port);
+-	outb_p(cyl>>8,++port);
+-	outb_p(0xA0|(disk->unit<<4)|head,++port);
+-	outb_p(cmd,++port);
++	outb_p(disk->ctl, HD_CMD);
++	port = HD_DATA;
++	outb_p(disk->wpcom >> 2, ++port);
++	outb_p(nsect, ++port);
++	outb_p(sect, ++port);
++	outb_p(cyl, ++port);
++	outb_p(cyl >> 8, ++port);
++	outb_p(0xA0 | (disk->unit << 4) | head, ++port);
++	outb_p(cmd, ++port);
+ }
+ 
+ static void hd_request (void);
+@@ -344,14 +343,14 @@ static void reset_controller(void)
+ {
+ 	int	i;
+ 
+-	outb_p(4,HD_CMD);
+-	for(i = 0; i < 1000; i++) barrier();
+-	outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
+-	for(i = 0; i < 1000; i++) barrier();
++	outb_p(4, HD_CMD);
++	for (i = 0; i < 1000; i++) barrier();
++	outb_p(hd_info[0].ctl & 0x0f, HD_CMD);
++	for (i = 0; i < 1000; i++) barrier();
+ 	if (drive_busy())
+ 		printk("hd: controller still busy\n");
+ 	else if ((hd_error = inb(HD_ERROR)) != 1)
+-		printk("hd: controller reset failed: %02x\n",hd_error);
++		printk("hd: controller reset failed: %02x\n", hd_error);
+ }
+ 
+ static void reset_hd(void)
+@@ -371,8 +370,8 @@ repeat:
+ 	if (++i < NR_HD) {
+ 		struct hd_i_struct *disk = &hd_info[i];
+ 		disk->special_op = disk->recalibrate = 1;
+-		hd_out(disk,disk->sect,disk->sect,disk->head-1,
+-			disk->cyl,WIN_SPECIFY,&reset_hd);
++		hd_out(disk, disk->sect, disk->sect, disk->head-1,
++			disk->cyl, WIN_SPECIFY, &reset_hd);
+ 		if (reset)
+ 			goto repeat;
+ 	} else
+@@ -393,7 +392,7 @@ static void unexpected_hd_interrupt(void)
+ 	unsigned int stat = inb_p(HD_STATUS);
+ 
+ 	if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
+-		dump_status ("unexpected interrupt", stat);
++		dump_status("unexpected interrupt", stat);
+ 		SET_TIMER;
+ 	}
+ }
+@@ -453,7 +452,7 @@ static void read_intr(void)
+ 	return;
+ ok_to_read:
+ 	req = CURRENT;
+-	insw(HD_DATA,req->buffer,256);
++	insw(HD_DATA, req->buffer, 256);
+ 	req->sector++;
+ 	req->buffer += 512;
+ 	req->errors = 0;
+@@ -507,7 +506,7 @@ ok_to_write:
+ 		end_request(req, 1);
+ 	if (i > 0) {
+ 		SET_HANDLER(&write_intr);
+-		outsw(HD_DATA,req->buffer,256);
++		outsw(HD_DATA, req->buffer, 256);
+ 		local_irq_enable();
+ 	} else {
+ #if (HD_DELAY > 0)
+@@ -560,11 +559,11 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req)
+ {
+ 	if (disk->recalibrate) {
+ 		disk->recalibrate = 0;
+-		hd_out(disk,disk->sect,0,0,0,WIN_RESTORE,&recal_intr);
++		hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr);
+ 		return reset;
+ 	}
+ 	if (disk->head > 16) {
+-		printk ("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
++		printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
+ 		end_request(req, 0);
+ 	}
+ 	disk->special_op = 0;
+@@ -633,19 +632,21 @@ repeat:
+ 	if (blk_fs_request(req)) {
+ 		switch (rq_data_dir(req)) {
+ 		case READ:
+-			hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr);
++			hd_out(disk, nsect, sec, head, cyl, WIN_READ,
++				&read_intr);
+ 			if (reset)
+ 				goto repeat;
+ 			break;
+ 		case WRITE:
+-			hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
++			hd_out(disk, nsect, sec, head, cyl, WIN_WRITE,
++				&write_intr);
+ 			if (reset)
+ 				goto repeat;
+ 			if (wait_DRQ()) {
+ 				bad_rw_intr();
+ 				goto repeat;
+ 			}
+-			outsw(HD_DATA,req->buffer,256);
++			outsw(HD_DATA, req->buffer, 256);
+ 			break;
+ 		default:
+ 			printk("unknown hd-command\n");
+@@ -655,7 +656,7 @@ repeat:
+ 	}
+ }
+ 
+-static void do_hd_request (struct request_queue * q)
++static void do_hd_request(struct request_queue *q)
+ {
+ 	disable_irq(HD_IRQ);
+ 	hd_request();
+@@ -708,12 +709,12 @@ static int __init hd_init(void)
+ {
+ 	int drive;
+ 
+-	if (register_blkdev(MAJOR_NR,"hd"))
++	if (register_blkdev(MAJOR_NR, "hd"))
+ 		return -1;
+ 
+ 	hd_queue = blk_init_queue(do_hd_request, &hd_lock);
+ 	if (!hd_queue) {
+-		unregister_blkdev(MAJOR_NR,"hd");
++		unregister_blkdev(MAJOR_NR, "hd");
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -742,7 +743,7 @@ static int __init hd_init(void)
+ 		goto out;
+ 	}
+ 
+-	for (drive=0 ; drive < NR_HD ; drive++) {
++	for (drive = 0 ; drive < NR_HD ; drive++) {
+ 		struct gendisk *disk = alloc_disk(64);
+ 		struct hd_i_struct *p = &hd_info[drive];
+ 		if (!disk)
+@@ -756,7 +757,7 @@ static int __init hd_init(void)
+ 		disk->queue = hd_queue;
+ 		p->unit = drive;
+ 		hd_gendisk[drive] = disk;
+-		printk ("%s: %luMB, CHS=%d/%d/%d\n",
++		printk("%s: %luMB, CHS=%d/%d/%d\n",
+ 			disk->disk_name, (unsigned long)get_capacity(disk)/2048,
+ 			p->cyl, p->head, p->sect);
+ 	}
+@@ -776,7 +777,7 @@ static int __init hd_init(void)
+ 	}
+ 
+ 	/* Let them fly */
+-	for(drive=0; drive < NR_HD; drive++)
++	for (drive = 0; drive < NR_HD; drive++)
+ 		add_disk(hd_gendisk[drive]);
+ 
+ 	return 0;
+@@ -791,7 +792,7 @@ out1:
+ 	NR_HD = 0;
+ out:
+ 	del_timer(&device_timer);
+-	unregister_blkdev(MAJOR_NR,"hd");
++	unregister_blkdev(MAJOR_NR, "hd");
+ 	blk_cleanup_queue(hd_queue);
+ 	return -1;
+ Enomem:
+@@ -800,7 +801,8 @@ Enomem:
+ 	goto out;
+ }
+ 
+-static int __init parse_hd_setup (char *line) {
++static int __init parse_hd_setup(char *line)
++{
+ 	int ints[6];
+ 
+ 	(void) get_options(line, ARRAY_SIZE(ints), ints);
+diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
+index 78ca68e..60f52f5 100644
+--- a/drivers/ide/legacy/ht6560b.c
++++ b/drivers/ide/legacy/ht6560b.c
+@@ -35,6 +35,7 @@
+  *  Try:  http://www.maf.iki.fi/~maf/ht6560b/
+  */
+ 
++#define DRV_NAME	"ht6560b"
+ #define HT6560B_VERSION "v0.08"
+ 
+ #include <linux/module.h>
+@@ -82,7 +83,7 @@
+  * out how they setup those cycle time interfacing values, as they at Holtek
+  * call them. IDESETUP.COM that is supplied with the drivers figures out
+  * optimal values and fetches those values to drivers. I found out that
+- * they use IDE_SELECT_REG to fetch timings to the ide board right after
++ * they use Select register to fetch timings to the ide board right after
+  * interface switching. After that it was quite easy to add code to
+  * ht6560b.c.
+  *
+@@ -127,6 +128,7 @@
+  */
+ static void ht6560b_selectproc (ide_drive_t *drive)
+ {
++	ide_hwif_t *hwif = drive->hwif;
+ 	unsigned long flags;
+ 	static u8 current_select = 0;
+ 	static u8 current_timing = 0;
+@@ -155,8 +157,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
+ 		/*
+ 		 * Set timing for this drive:
+ 		 */
+-		outb(timing, IDE_SELECT_REG);
+-		(void)inb(IDE_STATUS_REG);
++		outb(timing, hwif->io_ports[IDE_SELECT_OFFSET]);
++		(void)inb(hwif->io_ports[IDE_STATUS_OFFSET]);
+ #ifdef DEBUG
+ 		printk("ht6560b: %s: select=%#x timing=%#x\n",
+ 			drive->name, select, timing);
+@@ -193,9 +195,9 @@ static int __init try_to_init_ht6560b(void)
+ 	 * Ht6560b autodetected
+ 	 */
+ 	outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
+-	outb(HT_TIMING_DEFAULT, 0x1f6);  /* IDE_SELECT_REG */
+-	(void) inb(0x1f7);               /* IDE_STATUS_REG */
+-	
++	outb(HT_TIMING_DEFAULT, 0x1f6);	/* Select register */
++	(void)inb(0x1f7);		/* Status register */
++
+ 	printk("ht6560b " HT6560B_VERSION
+ 	       ": chipset detected and initialized"
+ #ifdef DEBUG
+@@ -338,15 +340,13 @@ static const struct ide_port_info ht6560b_port_info __initdata = {
+ static int __init ht6560b_init(void)
+ {
+ 	ide_hwif_t *hwif, *mate;
+-	static u8 idx[4] = { 0, 1, 0xff, 0xff };
++	static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	hw_regs_t hw[2];
+ 
+ 	if (probe_ht6560b == 0)
+ 		return -ENODEV;
+ 
+-	hwif = &ide_hwifs[0];
+-	mate = &ide_hwifs[1];
+-
+-	if (!request_region(HT_CONFIG_PORT, 1, hwif->name)) {
++	if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) {
+ 		printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
+ 			__FUNCTION__);
+ 		return -ENODEV;
+@@ -357,14 +357,31 @@ static int __init ht6560b_init(void)
+ 		goto release_region;
+ 	}
+ 
+-	hwif->selectproc = &ht6560b_selectproc;
+-	hwif->set_pio_mode = &ht6560b_set_pio_mode;
++	memset(&hw, 0, sizeof(hw));
++
++	ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++	hw[0].irq = 14;
+ 
+-	mate->selectproc = &ht6560b_selectproc;
+-	mate->set_pio_mode = &ht6560b_set_pio_mode;
++	ide_std_init_ports(&hw[1], 0x170, 0x376);
++	hw[1].irq = 15;
+ 
+-	hwif->port_init_devs = ht6560b_port_init_devs;
+-	mate->port_init_devs = ht6560b_port_init_devs;
++	hwif = ide_find_port();
++	if (hwif) {
++		ide_init_port_hw(hwif, &hw[0]);
++		hwif->selectproc     = ht6560b_selectproc;
++		hwif->set_pio_mode   = ht6560b_set_pio_mode;
++		hwif->port_init_devs = ht6560b_port_init_devs;
++		idx[0] = hwif->index;
++	}
++
++	mate = ide_find_port();
++	if (mate) {
++		ide_init_port_hw(mate, &hw[1]);
++		mate->selectproc     = ht6560b_selectproc;
++		mate->set_pio_mode   = ht6560b_set_pio_mode;
++		mate->port_init_devs = ht6560b_port_init_devs;
++		idx[1] = mate->index;
++	}
+ 
+ 	ide_device_add(idx, &ht6560b_port_info);
+ 
+diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
+new file mode 100644
+index 0000000..c352f12
+--- /dev/null
++++ b/drivers/ide/legacy/ide-4drives.c
+@@ -0,0 +1,56 @@
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/ide.h>
++
++int probe_4drives;
++
++module_param_named(probe, probe_4drives, bool, 0);
++MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
++
++static int __init ide_4drives_init(void)
++{
++	ide_hwif_t *hwif, *mate;
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	hw_regs_t hw;
++
++	if (probe_4drives == 0)
++		return -ENODEV;
++
++	memset(&hw, 0, sizeof(hw));
++
++	ide_std_init_ports(&hw, 0x1f0, 0x3f6);
++	hw.irq = 14;
++	hw.chipset = ide_4drives;
++
++	hwif = ide_find_port();
++	if (hwif) {
++		ide_init_port_hw(hwif, &hw);
++		idx[0] = hwif->index;
++	}
++
++	mate = ide_find_port();
++	if (mate) {
++		ide_init_port_hw(mate, &hw);
++		mate->drives[0].select.all ^= 0x20;
++		mate->drives[1].select.all ^= 0x20;
++		idx[1] = mate->index;
++
++		if (hwif) {
++			hwif->mate = mate;
++			mate->mate = hwif;
++			hwif->serialized = mate->serialized = 1;
++		}
++	}
++
++	ide_device_add(idx, NULL);
++
++	return 0;
++}
++
++module_init(ide_4drives_init);
++
++MODULE_AUTHOR("Bartlomiej Zolnierkiewicz");
++MODULE_DESCRIPTION("generic IDE chipset with 4 drives/port support");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
+index 15ccf69..b97b8d5 100644
+--- a/drivers/ide/legacy/ide-cs.c
++++ b/drivers/ide/legacy/ide-cs.c
+@@ -156,15 +156,15 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq
+     hw.chipset = ide_pci;
+     hw.dev = &handle->dev;
+ 
+-    hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++    hwif = ide_find_port();
+     if (hwif == NULL)
+ 	return -1;
+ 
+     i = hwif->index;
+ 
+     if (hwif->present)
+-	ide_unregister(i, 0, 0);
+-    else if (!hwif->hold)
++	ide_unregister(i);
++    else
+ 	ide_init_port_data(hwif, i);
+ 
+     ide_init_port_hw(hwif, &hw);
+@@ -360,7 +360,7 @@ void ide_release(struct pcmcia_device *link)
+     if (info->ndev) {
+ 	/* FIXME: if this fails we need to queue the cleanup somehow
+ 	   -- need to investigate the required PCMCIA magic */
+-	ide_unregister(info->hd, 0, 0);
++	ide_unregister(info->hd);
+     }
+     info->ndev = 0;
+ 
+diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
+index 688fcae..bf24077 100644
+--- a/drivers/ide/legacy/ide_platform.c
++++ b/drivers/ide/legacy/ide_platform.c
+@@ -89,7 +89,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
+ 			res_alt->start, res_alt->end - res_alt->start + 1);
+ 	}
+ 
+-	hwif = ide_find_port((unsigned long)base);
++	hwif = ide_find_port();
+ 	if (!hwif) {
+ 		ret = -ENODEV;
+ 		goto out;
+@@ -100,11 +100,10 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
+ 	hw.dev = &pdev->dev;
+ 
+ 	ide_init_port_hw(hwif, &hw);
++	hwif->mmio = 1;
+ 
+-	if (mmio) {
+-		hwif->mmio = 1;
++	if (mmio)
+ 		default_hwif_mmiops(hwif);
+-	}
+ 
+ 	idx[0] = hwif->index;
+ 
+@@ -122,7 +121,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
+ {
+ 	ide_hwif_t *hwif = pdev->dev.driver_data;
+ 
+-	ide_unregister(hwif->index, 0, 0);
++	ide_unregister(hwif->index);
+ 
+ 	return 0;
+ }
+@@ -130,6 +129,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
+ static struct platform_driver platform_ide_driver = {
+ 	.driver = {
+ 		.name = "pata_platform",
++		.owner = THIS_MODULE,
+ 	},
+ 	.probe = plat_ide_probe,
+ 	.remove = __devexit_p(plat_ide_remove),
+@@ -147,6 +147,7 @@ static void __exit platform_ide_exit(void)
+ 
+ MODULE_DESCRIPTION("Platform IDE driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pata_platform");
+ 
+ module_init(platform_ide_init);
+ module_exit(platform_ide_exit);
+diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
+index eaf5dbe..7429b80 100644
+--- a/drivers/ide/legacy/macide.c
++++ b/drivers/ide/legacy/macide.c
+@@ -120,7 +120,7 @@ static int __init macide_init(void)
+ 
+ 	macide_setup_ports(&hw, base, irq, ack_intr);
+ 
+-	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	hwif = ide_find_port();
+ 	if (hwif) {
+ 		u8 index = hwif->index;
+ 		u8 idx[4] = { index, 0xff, 0xff, 0xff };
+diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
+index 2da2875..fcbff0e 100644
+--- a/drivers/ide/legacy/q40ide.c
++++ b/drivers/ide/legacy/q40ide.c
+@@ -137,7 +137,7 @@ static int __init q40ide_init(void)
+ //			m68kide_iops,
+ 			q40ide_default_irq(pcide_bases[i]));
+ 
+-	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	hwif = ide_find_port();
+ 	if (hwif) {
+ 		ide_init_port_data(hwif, hwif->index);
+ 		ide_init_port_hw(hwif, &hw);
+diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
+index 2f4f47a..6e820c7 100644
+--- a/drivers/ide/legacy/qd65xx.c
++++ b/drivers/ide/legacy/qd65xx.c
+@@ -88,12 +88,12 @@
+ static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
+ 
+ /*
+- * qd_select:
++ * qd65xx_select:
+  *
+- * This routine is invoked from ide.c to prepare for access to a given drive.
++ * This routine is invoked to prepare for access to a given drive.
+  */
+ 
+-static void qd_select (ide_drive_t *drive)
++static void qd65xx_select(ide_drive_t *drive)
+ {
+ 	u8 index = ((	(QD_TIMREG(drive)) & 0x80 ) >> 7) |
+ 			(QD_TIMREG(drive) & 0x02);
+@@ -168,36 +168,15 @@ static int qd_find_disk_type (ide_drive_t *drive,
+ }
+ 
+ /*
+- * qd_timing_ok:
+- *
+- * check whether timings don't conflict
+- */
+-
+-static int qd_timing_ok (ide_drive_t drives[])
+-{
+-	return (IDE_IMPLY(drives[0].present && drives[1].present,
+-			IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1),
+-			          QD_TIMING(drives) == QD_TIMING(drives+1))));
+-	/* if same timing register, must be same timing */
+-}
+-
+-/*
+  * qd_set_timing:
+  *
+- * records the timing, and enables selectproc as needed
++ * records the timing
+  */
+ 
+ static void qd_set_timing (ide_drive_t *drive, u8 timing)
+ {
+-	ide_hwif_t *hwif = HWIF(drive);
+-
+ 	drive->drive_data &= 0xff00;
+ 	drive->drive_data |= timing;
+-	if (qd_timing_ok(hwif->drives)) {
+-		qd_select(drive); /* selects once */
+-		hwif->selectproc = NULL;
+-	} else
+-		hwif->selectproc = &qd_select;
+ 
+ 	printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
+ }
+@@ -225,10 +204,11 @@ static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 
+ static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+-	int base = HWIF(drive)->select_data;
++	ide_hwif_t *hwif = drive->hwif;
+ 	unsigned int cycle_time;
+ 	int active_time   = 175;
+ 	int recovery_time = 415; /* worst case values from the dos driver */
++	u8 base = (hwif->config_data & 0xff00) >> 8;
+ 
+ 	if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
+ 		cycle_time = ide_pio_cycle_time(drive, pio);
+@@ -299,21 +279,10 @@ static int __init qd_testreg(int port)
+ 	return (readreg != QD_TESTVAL);
+ }
+ 
+-/*
+- * qd_setup:
+- *
+- * called to setup an ata channel : adjusts attributes & links for tuning
+- */
+-
+-static void __init qd_setup(ide_hwif_t *hwif, int base, int config)
+-{
+-	hwif->select_data = base;
+-	hwif->config_data = config;
+-}
+-
+ static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
+ {
+-	u8 base = hwif->select_data, config = QD_CONFIG(hwif);
++	u8 base = (hwif->config_data & 0xff00) >> 8;
++	u8 config = QD_CONFIG(hwif);
+ 
+ 	hwif->drives[0].drive_data = QD6500_DEF_DATA;
+ 	hwif->drives[1].drive_data = QD6500_DEF_DATA;
+@@ -322,9 +291,10 @@ static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
+ static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
+ {
+ 	u16 t1, t2;
+-	u8 base = hwif->select_data, config = QD_CONFIG(hwif);
++	u8 base = (hwif->config_data & 0xff00) >> 8;
++	u8 config = QD_CONFIG(hwif);
+ 
+-	if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
++	if (hwif->host_flags & IDE_HFLAG_SINGLE) {
+ 		t1 = QD6580_DEF_DATA;
+ 		t2 = QD6580_DEF_DATA2;
+ 	} else
+@@ -352,41 +322,62 @@ static const struct ide_port_info qd65xx_port_info __initdata = {
+ static int __init qd_probe(int base)
+ {
+ 	ide_hwif_t *hwif;
++	u8 config, unit;
+ 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+-	u8 config;
+-	u8 unit;
++	hw_regs_t hw[2];
++	struct ide_port_info d = qd65xx_port_info;
+ 
+ 	config = inb(QD_CONFIG_PORT);
+ 
+ 	if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
+-		return 1;
++		return -ENODEV;
+ 
+ 	unit = ! (config & QD_CONFIG_IDE_BASEPORT);
+ 
++	if (unit)
++		d.host_flags |= IDE_HFLAG_QD_2ND_PORT;
++
++	memset(&hw, 0, sizeof(hw));
++
++	ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++	hw[0].irq = 14;
++
++	ide_std_init_ports(&hw[1], 0x170, 0x376);
++	hw[1].irq = 15;
++
+ 	if ((config & 0xf0) == QD_CONFIG_QD6500) {
+ 
+-		if (qd_testreg(base)) return 1;		/* bad register */
++		if (qd_testreg(base))
++			 return -ENODEV;	/* bad register */
+ 
+ 		/* qd6500 found */
+ 
+-		hwif = &ide_hwifs[unit];
+-		printk(KERN_NOTICE "%s: qd6500 at %#x\n", hwif->name, base);
+-		printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
+-			config, QD_ID3);
+-		
+ 		if (config & QD_CONFIG_DISABLED) {
+ 			printk(KERN_WARNING "qd6500 is disabled !\n");
+-			return 1;
++			return -ENODEV;
+ 		}
+ 
+-		qd_setup(hwif, base, config);
++		printk(KERN_NOTICE "qd6500 at %#x\n", base);
++		printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
++			config, QD_ID3);
++
++		d.host_flags |= IDE_HFLAG_SINGLE;
++
++		hwif = ide_find_port_slot(&d);
++		if (hwif == NULL)
++			return -ENOENT;
++
++		ide_init_port_hw(hwif, &hw[unit]);
++
++		hwif->config_data = (base << 8) | config;
+ 
+ 		hwif->port_init_devs = qd6500_port_init_devs;
+-		hwif->set_pio_mode = &qd6500_set_pio_mode;
++		hwif->set_pio_mode   = qd6500_set_pio_mode;
++		hwif->selectproc     = qd65xx_select;
+ 
+-		idx[unit] = unit;
++		idx[unit] = hwif->index;
+ 
+-		ide_device_add(idx, &qd65xx_port_info);
++		ide_device_add(idx, &d);
+ 
+ 		return 1;
+ 	}
+@@ -396,8 +387,8 @@ static int __init qd_probe(int base)
+ 
+ 		u8 control;
+ 
+-		if (qd_testreg(base) || qd_testreg(base+0x02)) return 1;
+-			/* bad registers */
++		if (qd_testreg(base) || qd_testreg(base + 0x02))
++			return -ENODEV;	/* bad registers */
+ 
+ 		/* qd6580 found */
+ 
+@@ -412,41 +403,52 @@ static int __init qd_probe(int base)
+ 		if (control & QD_CONTR_SEC_DISABLED) {
+ 			/* secondary disabled */
+ 
+-			hwif = &ide_hwifs[unit];
+-			printk(KERN_INFO "%s: qd6580: single IDE board\n",
+-					 hwif->name);
++			printk(KERN_INFO "qd6580: single IDE board\n");
++
++			d.host_flags |= IDE_HFLAG_SINGLE;
++
++			hwif = ide_find_port_slot(&d);
++			if (hwif == NULL)
++				return -ENOENT;
+ 
+-			qd_setup(hwif, base, config | (control << 8));
++			ide_init_port_hw(hwif, &hw[unit]);
++
++			hwif->config_data = (base << 8) | config;
+ 
+ 			hwif->port_init_devs = qd6580_port_init_devs;
+-			hwif->set_pio_mode = &qd6580_set_pio_mode;
++			hwif->set_pio_mode   = qd6580_set_pio_mode;
++			hwif->selectproc     = qd65xx_select;
+ 
+-			idx[unit] = unit;
++			idx[unit] = hwif->index;
+ 
+-			ide_device_add(idx, &qd65xx_port_info);
++			ide_device_add(idx, &d);
+ 
+ 			return 1;
+ 		} else {
+ 			ide_hwif_t *mate;
+ 
+-			hwif = &ide_hwifs[0];
+-			mate = &ide_hwifs[1];
+ 			/* secondary enabled */
+-			printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
+-					hwif->name, mate->name);
+-
+-			qd_setup(hwif, base, config | (control << 8));
+-
+-			hwif->port_init_devs = qd6580_port_init_devs;
+-			hwif->set_pio_mode = &qd6580_set_pio_mode;
+-
+-			qd_setup(mate, base, config | (control << 8));
+-
+-			mate->port_init_devs = qd6580_port_init_devs;
+-			mate->set_pio_mode = &qd6580_set_pio_mode;
+-
+-			idx[0] = 0;
+-			idx[1] = 1;
++			printk(KERN_INFO "qd6580: dual IDE board\n");
++
++			hwif = ide_find_port();
++			if (hwif) {
++				ide_init_port_hw(hwif, &hw[0]);
++				hwif->config_data = (base << 8) | config;
++				hwif->port_init_devs = qd6580_port_init_devs;
++				hwif->set_pio_mode   = qd6580_set_pio_mode;
++				hwif->selectproc     = qd65xx_select;
++				idx[0] = hwif->index;
++			}
++
++			mate = ide_find_port();
++			if (mate) {
++				ide_init_port_hw(mate, &hw[1]);
++				mate->config_data = (base << 8) | config;
++				mate->port_init_devs = qd6580_port_init_devs;
++				mate->set_pio_mode   = qd6580_set_pio_mode;
++				mate->selectproc     = qd65xx_select;
++				idx[1] = mate->index;
++			}
+ 
+ 			ide_device_add(idx, &qd65xx_port_info);
+ 
+@@ -454,7 +456,7 @@ static int __init qd_probe(int base)
+ 		}
+ 	}
+ 	/* no qd65xx found */
+-	return 1;
++	return -ENODEV;
+ }
+ 
+ int probe_qd65xx = 0;
+@@ -464,14 +466,18 @@ MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
+ 
+ static int __init qd65xx_init(void)
+ {
++	int rc1, rc2 = -ENODEV;
++
+ 	if (probe_qd65xx == 0)
+ 		return -ENODEV;
+ 
+-	if (qd_probe(0x30))
+-		qd_probe(0xb0);
+-	if (ide_hwifs[0].chipset != ide_qd65xx &&
+-	    ide_hwifs[1].chipset != ide_qd65xx)
++	rc1 = qd_probe(0x30);
++	if (rc1)
++		rc2 = qd_probe(0xb0);
++
++	if (rc1 < 0 && rc2 < 0)
+ 		return -ENODEV;
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
+index 28dd50a..c83dea8 100644
+--- a/drivers/ide/legacy/qd65xx.h
++++ b/drivers/ide/legacy/qd65xx.h
+@@ -30,7 +30,6 @@
+ #define QD_ID3			((config & QD_CONFIG_ID3)!=0)
+ 
+ #define QD_CONFIG(hwif)		((hwif)->config_data & 0x00ff)
+-#define QD_CONTROL(hwif)	(((hwif)->config_data & 0xff00) >> 8)
+ 
+ #define QD_TIMING(drive)	(byte)(((drive)->drive_data) & 0x00ff)
+ #define QD_TIMREG(drive)	(byte)((((drive)->drive_data) & 0xff00) >> 8)
+diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
+index 5696ba0..4d90bad 100644
+--- a/drivers/ide/legacy/umc8672.c
++++ b/drivers/ide/legacy/umc8672.c
+@@ -19,7 +19,7 @@
+  */
+ 
+ /*
+- * VLB Controller Support from 
++ * VLB Controller Support from
+  * Wolfram Podien
+  * Rohoefe 3
+  * D28832 Achim
+@@ -32,7 +32,7 @@
+  * #define UMC_DRIVE0 11
+  * in the beginning of the driver, which sets the speed of drive 0 to 11 (there
+  * are some lines present). 0 - 11 are allowed speed values. These values are
+- * the results from the DOS speed test program supplied from UMC. 11 is the 
++ * the results from the DOS speed test program supplied from UMC. 11 is the
+  * highest speed (about PIO mode 3)
+  */
+ #define REALLY_SLOW_IO		/* some systems can safely undef this */
+@@ -60,62 +60,62 @@
+ #define UMC_DRIVE3      1              /* In case of crash reduce speed */
+ 
+ static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
+-static const u8 pio_to_umc [5] = {0,3,7,10,11};	/* rough guesses */
++static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11};	/* rough guesses */
+ 
+ /*       0    1    2    3    4    5    6    7    8    9    10   11      */
+ static const u8 speedtab [3][12] = {
+-	{0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
+-	{0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
+-	{0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};
++	{0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
++	{0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
++	{0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0}
++};
+ 
+-static void out_umc (char port,char wert)
++static void out_umc(char port, char wert)
+ {
+-	outb_p(port,0x108);
+-	outb_p(wert,0x109);
++	outb_p(port, 0x108);
++	outb_p(wert, 0x109);
+ }
+ 
+-static inline u8 in_umc (char port)
++static inline u8 in_umc(char port)
+ {
+-	outb_p(port,0x108);
++	outb_p(port, 0x108);
+ 	return inb_p(0x109);
+ }
+ 
+-static void umc_set_speeds (u8 speeds[])
++static void umc_set_speeds(u8 speeds[])
+ {
+ 	int i, tmp;
+ 
+-	outb_p(0x5A,0x108); /* enable umc */
++	outb_p(0x5A, 0x108); /* enable umc */
+ 
+-	out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
+-	out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
++	out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
++	out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
+ 	tmp = 0;
+-	for (i = 3; i >= 0; i--) {
++	for (i = 3; i >= 0; i--)
+ 		tmp = (tmp << 2) | speedtab[1][speeds[i]];
++	out_umc(0xdc, tmp);
++	for (i = 0; i < 4; i++) {
++		out_umc(0xd0 + i, speedtab[2][speeds[i]]);
++		out_umc(0xd8 + i, speedtab[2][speeds[i]]);
+ 	}
+-	out_umc (0xdc,tmp);
+-	for (i = 0;i < 4; i++) {
+-		out_umc (0xd0+i,speedtab[2][speeds[i]]);
+-		out_umc (0xd8+i,speedtab[2][speeds[i]]);
+-	}
+-	outb_p(0xa5,0x108); /* disable umc */
++	outb_p(0xa5, 0x108); /* disable umc */
+ 
+-	printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
++	printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
+ 		speeds[0], speeds[1], speeds[2], speeds[3]);
+ }
+ 
+ static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
++	ide_hwif_t *hwif = drive->hwif;
+ 	unsigned long flags;
+-	ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
+ 
+ 	printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
+ 		drive->name, pio, pio_to_umc[pio]);
+ 	spin_lock_irqsave(&ide_lock, flags);
+-	if (hwgroup && hwgroup->handler != NULL) {
++	if (hwif->mate && hwif->mate->hwgroup->handler) {
+ 		printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
+ 	} else {
+ 		current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
+-		umc_set_speeds (current_speeds);
++		umc_set_speeds(current_speeds);
+ 	}
+ 	spin_unlock_irqrestore(&ide_lock, flags);
+ }
+@@ -128,35 +128,56 @@ static const struct ide_port_info umc8672_port_info __initdata = {
+ 
+ static int __init umc8672_probe(void)
+ {
++	ide_hwif_t *hwif, *mate;
+ 	unsigned long flags;
+-	static u8 idx[4] = { 0, 1, 0xff, 0xff };
++	static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	hw_regs_t hw[2];
+ 
+ 	if (!request_region(0x108, 2, "umc8672")) {
+ 		printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n");
+ 		return 1;
+ 	}
+ 	local_irq_save(flags);
+-	outb_p(0x5A,0x108); /* enable umc */
++	outb_p(0x5A, 0x108); /* enable umc */
+ 	if (in_umc (0xd5) != 0xa0) {
+ 		local_irq_restore(flags);
+ 		printk(KERN_ERR "umc8672: not found\n");
+ 		release_region(0x108, 2);
+-		return 1;  
++		return 1;
+ 	}
+-	outb_p(0xa5,0x108); /* disable umc */
++	outb_p(0xa5, 0x108); /* disable umc */
+ 
+-	umc_set_speeds (current_speeds);
++	umc_set_speeds(current_speeds);
+ 	local_irq_restore(flags);
+ 
+-	ide_hwifs[0].set_pio_mode = &umc_set_pio_mode;
+-	ide_hwifs[1].set_pio_mode = &umc_set_pio_mode;
++	memset(&hw, 0, sizeof(hw));
++
++	ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++	hw[0].irq = 14;
++
++	ide_std_init_ports(&hw[1], 0x170, 0x376);
++	hw[1].irq = 15;
++
++	hwif = ide_find_port();
++	if (hwif) {
++		ide_init_port_hw(hwif, &hw[0]);
++		hwif->set_pio_mode = umc_set_pio_mode;
++		idx[0] = hwif->index;
++	}
++
++	mate = ide_find_port();
++	if (mate) {
++		ide_init_port_hw(mate, &hw[1]);
++		mate->set_pio_mode = umc_set_pio_mode;
++		idx[1] = mate->index;
++	}
+ 
+ 	ide_device_add(idx, &umc8672_port_info);
+ 
+ 	return 0;
+ }
+ 
+-int probe_umc8672 = 0;
++int probe_umc8672;
+ 
+ module_param_named(probe, probe_umc8672, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
+diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
+index 85c016b..a8cd003 100644
+--- a/drivers/ide/mips/au1xxx-ide.c
++++ b/drivers/ide/mips/au1xxx-ide.c
+@@ -599,9 +599,11 @@ static int au_ide_probe(struct device *dev)
+ 		goto out;
+ 	}
+ 
+-	/* FIXME:  This might possibly break PCMCIA IDE devices */
+-
+-	hwif                            = &ide_hwifs[pdev->id];
++	hwif = ide_find_port();
++	if (hwif == NULL) {
++		ret = -ENOENT;
++		goto out;
++	}
+ 
+ 	memset(&hw, 0, sizeof(hw));
+ 	auide_setup_ports(&hw, ahwif);
+@@ -613,9 +615,6 @@ static int au_ide_probe(struct device *dev)
+ 
+ 	hwif->dev = dev;
+ 
+-	/* hold should be on in all cases */
+-	hwif->hold                      = 1;
+-
+ 	hwif->mmio  = 1;
+ 
+ 	/* If the user has selected DDMA assisted copies,
+@@ -673,7 +672,7 @@ static int au_ide_remove(struct device *dev)
+ 	ide_hwif_t *hwif = dev_get_drvdata(dev);
+ 	_auide_hwif *ahwif = &auide_hwif;
+ 
+-	ide_unregister(hwif->index, 0, 0);
++	ide_unregister(hwif->index);
+ 
+ 	iounmap((void *)ahwif->regbase);
+ 
+diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
+index 956259f..bbe8d58 100644
+--- a/drivers/ide/mips/swarm.c
++++ b/drivers/ide/mips/swarm.c
+@@ -76,17 +76,12 @@ static int __devinit swarm_ide_probe(struct device *dev)
+ 	if (!SIBYTE_HAVE_IDE)
+ 		return -ENODEV;
+ 
+-	/* Find an empty slot.  */
+-	for (i = 0; i < MAX_HWIFS; i++)
+-		if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET])
+-			break;
+-	if (i >= MAX_HWIFS) {
++	hwif = ide_find_port();
++	if (hwif == NULL) {
+ 		printk(KERN_ERR DRV_NAME ": no free slot for interface\n");
+ 		return -ENOMEM;
+ 	}
+ 
+-	hwif = ide_hwifs + i;
+-
+ 	base = ioremap(A_IO_EXT_BASE, 0x800);
+ 	offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
+ 	size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
+diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
+index cfb3265..c9ba15a 100644
+--- a/drivers/ide/pci/aec62xx.c
++++ b/drivers/ide/pci/aec62xx.c
+@@ -220,7 +220,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ 		.init_hwif	= init_hwif_aec62xx,
+ 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+ 		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
+-				  IDE_HFLAG_ABUSE_SET_DMA_MODE,
++				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
++				  IDE_HFLAG_NON_BOOTABLE,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA4,
+diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
+index b3b6f51..3fa2d9f 100644
+--- a/drivers/ide/pci/alim15x3.c
++++ b/drivers/ide/pci/alim15x3.c
+@@ -750,7 +750,6 @@ static const struct ide_port_info ali15x3_chipset __devinitdata = {
+ 	.init_chipset	= init_chipset_ali15x3,
+ 	.init_hwif	= init_hwif_ali15x3,
+ 	.init_dma	= init_dma_ali15x3,
+-	.host_flags	= IDE_HFLAG_BOOTABLE,
+ 	.pio_mask	= ATA_PIO5,
+ 	.swdma_mask	= ATA_SWDMA2,
+ 	.mwdma_mask	= ATA_MWDMA2,
+diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
+index 2ef890c..ff684d3 100644
+--- a/drivers/ide/pci/amd74xx.c
++++ b/drivers/ide/pci/amd74xx.c
+@@ -219,12 +219,10 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
+ 
+ #define IDE_HFLAGS_AMD \
+ 	(IDE_HFLAG_PIO_NO_BLACKLIST | \
+-	 IDE_HFLAG_PIO_NO_DOWNGRADE | \
+ 	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+ 	 IDE_HFLAG_POST_SET_MODE | \
+ 	 IDE_HFLAG_IO_32BIT | \
+-	 IDE_HFLAG_UNMASK_IRQS | \
+-	 IDE_HFLAG_BOOTABLE)
++	 IDE_HFLAG_UNMASK_IRQS)
+ 
+ #define DECLARE_AMD_DEV(name_str, swdma, udma)				\
+ 	{								\
+diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
+index 7e037c8..91722f8 100644
+--- a/drivers/ide/pci/atiixp.c
++++ b/drivers/ide/pci/atiixp.c
+@@ -151,7 +151,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
+ 		.name		= "ATIIXP",
+ 		.init_hwif	= init_hwif_atiixp,
+ 		.enablebits	= {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
+-		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAG_LEGACY_IRQS,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA5,
+@@ -159,8 +159,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
+ 		.name		= "SB600_PATA",
+ 		.init_hwif	= init_hwif_atiixp,
+ 		.enablebits	= {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
+- 		.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS |
+-				  IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA5,
+diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
+index 29fbc5e..b076dbf 100644
+--- a/drivers/ide/pci/cmd640.c
++++ b/drivers/ide/pci/cmd640.c
+@@ -4,7 +4,7 @@
+ 
+ /*
+  *  Original authors:	abramov at cecmow.enet.dec.com (Igor Abramov)
+- *  			mlord at pobox.com (Mark Lord)
++ *			mlord at pobox.com (Mark Lord)
+  *
+  *  See linux/MAINTAINERS for address of current maintainer.
+  *
+@@ -98,7 +98,7 @@
+ 
+ #define CMD640_PREFETCH_MASKS 1
+ 
+-//#define CMD640_DUMP_REGS
++/*#define CMD640_DUMP_REGS */
+ 
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+@@ -112,7 +112,7 @@
+ /*
+  * This flag is set in ide.c by the parameter:  ide0=cmd640_vlb
+  */
+-int cmd640_vlb = 0;
++int cmd640_vlb;
+ 
+ /*
+  * CMD640 specific registers definition.
+@@ -185,7 +185,6 @@ static DEFINE_SPINLOCK(cmd640_lock);
+  * These are initialized to point at the devices we control
+  */
+ static ide_hwif_t  *cmd_hwif0, *cmd_hwif1;
+-static ide_drive_t *cmd_drives[4];
+ 
+ /*
+  * Interface to access cmd640x registers
+@@ -207,13 +206,13 @@ static unsigned int cmd640_chip_version;
+ 
+ /* PCI method 1 access */
+ 
+-static void put_cmd640_reg_pci1 (u16 reg, u8 val)
++static void put_cmd640_reg_pci1(u16 reg, u8 val)
+ {
+ 	outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
+ 	outb_p(val, (reg & 3) | 0xcfc);
+ }
+ 
+-static u8 get_cmd640_reg_pci1 (u16 reg)
++static u8 get_cmd640_reg_pci1(u16 reg)
+ {
+ 	outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
+ 	return inb_p((reg & 3) | 0xcfc);
+@@ -221,14 +220,14 @@ static u8 get_cmd640_reg_pci1 (u16 reg)
+ 
+ /* PCI method 2 access (from CMD datasheet) */
+ 
+-static void put_cmd640_reg_pci2 (u16 reg, u8 val)
++static void put_cmd640_reg_pci2(u16 reg, u8 val)
+ {
+ 	outb_p(0x10, 0xcf8);
+ 	outb_p(val, cmd640_key + reg);
+ 	outb_p(0, 0xcf8);
+ }
+ 
+-static u8 get_cmd640_reg_pci2 (u16 reg)
++static u8 get_cmd640_reg_pci2(u16 reg)
+ {
+ 	u8 b;
+ 
+@@ -240,13 +239,13 @@ static u8 get_cmd640_reg_pci2 (u16 reg)
+ 
+ /* VLB access */
+ 
+-static void put_cmd640_reg_vlb (u16 reg, u8 val)
++static void put_cmd640_reg_vlb(u16 reg, u8 val)
+ {
+ 	outb_p(reg, cmd640_key);
+ 	outb_p(val, cmd640_key + 4);
+ }
+ 
+-static u8 get_cmd640_reg_vlb (u16 reg)
++static u8 get_cmd640_reg_vlb(u16 reg)
+ {
+ 	outb_p(reg, cmd640_key);
+ 	return inb_p(cmd640_key + 4);
+@@ -268,11 +267,11 @@ static void put_cmd640_reg(u16 reg, u8 val)
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&cmd640_lock, flags);
+-	__put_cmd640_reg(reg,val);
++	__put_cmd640_reg(reg, val);
+ 	spin_unlock_irqrestore(&cmd640_lock, flags);
+ }
+ 
+-static int __init match_pci_cmd640_device (void)
++static int __init match_pci_cmd640_device(void)
+ {
+ 	const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
+ 	unsigned int i;
+@@ -292,7 +291,7 @@ static int __init match_pci_cmd640_device (void)
+ /*
+  * Probe for CMD640x -- pci method 1
+  */
+-static int __init probe_for_cmd640_pci1 (void)
++static int __init probe_for_cmd640_pci1(void)
+ {
+ 	__get_cmd640_reg = get_cmd640_reg_pci1;
+ 	__put_cmd640_reg = put_cmd640_reg_pci1;
+@@ -308,7 +307,7 @@ static int __init probe_for_cmd640_pci1 (void)
+ /*
+  * Probe for CMD640x -- pci method 2
+  */
+-static int __init probe_for_cmd640_pci2 (void)
++static int __init probe_for_cmd640_pci2(void)
+ {
+ 	__get_cmd640_reg = get_cmd640_reg_pci2;
+ 	__put_cmd640_reg = put_cmd640_reg_pci2;
+@@ -322,7 +321,7 @@ static int __init probe_for_cmd640_pci2 (void)
+ /*
+  * Probe for CMD640x -- vlb
+  */
+-static int __init probe_for_cmd640_vlb (void)
++static int __init probe_for_cmd640_vlb(void)
+ {
+ 	u8 b;
+ 
+@@ -343,7 +342,7 @@ static int __init probe_for_cmd640_vlb (void)
+  *  Returns 1 if an IDE interface/drive exists at 0x170,
+  *  Returns 0 otherwise.
+  */
+-static int __init secondary_port_responding (void)
++static int __init secondary_port_responding(void)
+ {
+ 	unsigned long flags;
+ 
+@@ -367,7 +366,7 @@ static int __init secondary_port_responding (void)
+ /*
+  * Dump out all cmd640 registers.  May be called from ide.c
+  */
+-static void cmd640_dump_regs (void)
++static void cmd640_dump_regs(void)
+ {
+ 	unsigned int reg = cmd640_vlb ? 0x50 : 0x00;
+ 
+@@ -386,9 +385,8 @@ static void cmd640_dump_regs (void)
+  * Check whether prefetch is on for a drive,
+  * and initialize the unmask flags for safe operation.
+  */
+-static void __init check_prefetch (unsigned int index)
++static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
+ {
+-	ide_drive_t *drive = cmd_drives[index];
+ 	u8 b = get_cmd640_reg(prefetch_regs[index]);
+ 
+ 	if (b & prefetch_masks[index]) {	/* is prefetch off? */
+@@ -404,38 +402,13 @@ static void __init check_prefetch (unsigned int index)
+ 	}
+ }
+ 
+-/*
+- * Figure out which devices we control
+- */
+-static void __init setup_device_ptrs (void)
+-{
+-	unsigned int i;
+-
+-	cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */
+-	cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */
+-	for (i = 0; i < MAX_HWIFS; i++) {
+-		ide_hwif_t *hwif = &ide_hwifs[i];
+-		if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) {
+-			if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0)
+-				cmd_hwif0 = hwif;
+-			else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170)
+-				cmd_hwif1 = hwif;
+-		}
+-	}
+-	cmd_drives[0] = &cmd_hwif0->drives[0];
+-	cmd_drives[1] = &cmd_hwif0->drives[1];
+-	cmd_drives[2] = &cmd_hwif1->drives[0];
+-	cmd_drives[3] = &cmd_hwif1->drives[1];
+-}
+-
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ 
+ /*
+  * Sets prefetch mode for a drive.
+  */
+-static void set_prefetch_mode (unsigned int index, int mode)
++static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
+ {
+-	ide_drive_t *drive = cmd_drives[index];
+ 	unsigned long flags;
+ 	int reg = prefetch_regs[index];
+ 	u8 b;
+@@ -462,7 +435,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
+ /*
+  * Dump out current drive clocks settings
+  */
+-static void display_clocks (unsigned int index)
++static void display_clocks(unsigned int index)
+ {
+ 	u8 active_count, recovery_count;
+ 
+@@ -481,7 +454,7 @@ static void display_clocks (unsigned int index)
+  * Pack active and recovery counts into single byte representation
+  * used by controller
+  */
+-static inline u8 pack_nibbles (u8 upper, u8 lower)
++static inline u8 pack_nibbles(u8 upper, u8 lower)
+ {
+ 	return ((upper & 0x0f) << 4) | (lower & 0x0f);
+ }
+@@ -489,7 +462,7 @@ static inline u8 pack_nibbles (u8 upper, u8 lower)
+ /*
+  * This routine retrieves the initial drive timings from the chipset.
+  */
+-static void __init retrieve_drive_counts (unsigned int index)
++static void __init retrieve_drive_counts(unsigned int index)
+ {
+ 	u8 b;
+ 
+@@ -498,10 +471,10 @@ static void __init retrieve_drive_counts (unsigned int index)
+ 	 */
+ 	b = get_cmd640_reg(arttim_regs[index]) & ~0x3f;
+ 	switch (b) {
+-		case 0x00: b = 4; break;
+-		case 0x80: b = 3; break;
+-		case 0x40: b = 2; break;
+-		default:   b = 5; break;
++	case 0x00: b = 4; break;
++	case 0x80: b = 3; break;
++	case 0x40: b = 2; break;
++	default:   b = 5; break;
+ 	}
+ 	setup_counts[index] = b;
+ 
+@@ -518,7 +491,7 @@ static void __init retrieve_drive_counts (unsigned int index)
+  * This routine writes the prepared setup/active/recovery counts
+  * for a drive into the cmd640 chipset registers to active them.
+  */
+-static void program_drive_counts (unsigned int index)
++static void program_drive_counts(ide_drive_t *drive, unsigned int index)
+ {
+ 	unsigned long flags;
+ 	u8 setup_count    = setup_counts[index];
+@@ -532,8 +505,11 @@ static void program_drive_counts (unsigned int index)
+ 	 * so we merge the timings, using the slowest value for each timing.
+ 	 */
+ 	if (index > 1) {
+-		unsigned int mate;
+-		if (cmd_drives[mate = index ^ 1]->present) {
++		ide_hwif_t *hwif = drive->hwif;
++		ide_drive_t *peer = &hwif->drives[!drive->select.b.unit];
++		unsigned int mate = index ^ 1;
++
++		if (peer->present) {
+ 			if (setup_count < setup_counts[mate])
+ 				setup_count = setup_counts[mate];
+ 			if (active_count < active_counts[mate])
+@@ -547,11 +523,11 @@ static void program_drive_counts (unsigned int index)
+ 	 * Convert setup_count to internal chipset representation
+ 	 */
+ 	switch (setup_count) {
+-		case 4:	 setup_count = 0x00; break;
+-		case 3:	 setup_count = 0x80; break;
+-		case 1:
+-		case 2:	 setup_count = 0x40; break;
+-		default: setup_count = 0xc0; /* case 5 */
++	case 4:	 setup_count = 0x00; break;
++	case 3:	 setup_count = 0x80; break;
++	case 1:
++	case 2:	 setup_count = 0x40; break;
++	default: setup_count = 0xc0; /* case 5 */
+ 	}
+ 
+ 	/*
+@@ -572,7 +548,8 @@ static void program_drive_counts (unsigned int index)
+ /*
+  * Set a specific pio_mode for a drive
+  */
+-static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time)
++static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
++			    u8 pio_mode, unsigned int cycle_time)
+ {
+ 	int setup_time, active_time, recovery_time, clock_time;
+ 	u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
+@@ -584,15 +561,15 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
+ 	active_time = ide_pio_timings[pio_mode].active_time;
+ 	recovery_time = cycle_time - (setup_time + active_time);
+ 	clock_time = 1000 / bus_speed;
+-	cycle_count = (cycle_time + clock_time - 1) / clock_time;
++	cycle_count = DIV_ROUND_UP(cycle_time, clock_time);
+ 
+-	setup_count = (setup_time + clock_time - 1) / clock_time;
++	setup_count = DIV_ROUND_UP(setup_time, clock_time);
+ 
+-	active_count = (active_time + clock_time - 1) / clock_time;
++	active_count = DIV_ROUND_UP(active_time, clock_time);
+ 	if (active_count < 2)
+ 		active_count = 2; /* minimum allowed by cmd640 */
+ 
+-	recovery_count = (recovery_time + clock_time - 1) / clock_time;
++	recovery_count = DIV_ROUND_UP(recovery_time, clock_time);
+ 	recovery_count2 = cycle_count - (setup_count + active_count);
+ 	if (recovery_count2 > recovery_count)
+ 		recovery_count = recovery_count2;
+@@ -621,7 +598,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
+ 	 *	1) this is the wrong place to do it (proper is do_special() in ide.c)
+ 	 * 	2) in practice this is rarely, if ever, necessary
+ 	 */
+-	program_drive_counts (index);
++	program_drive_counts(drive, index);
+ }
+ 
+ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
+@@ -629,32 +606,26 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	unsigned int index = 0, cycle_time;
+ 	u8 b;
+ 
+-	while (drive != cmd_drives[index]) {
+-		if (++index > 3) {
+-			printk(KERN_ERR "%s: bad news in %s\n",
+-					drive->name, __FUNCTION__);
+-			return;
+-		}
+-	}
+ 	switch (pio) {
+-		case 6: /* set fast-devsel off */
+-		case 7: /* set fast-devsel on */
+-			b = get_cmd640_reg(CNTRL) & ~0x27;
+-			if (pio & 1)
+-				b |= 0x27;
+-			put_cmd640_reg(CNTRL, b);
+-			printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, (pio & 1) ? "en" : "dis");
+-			return;
+-
+-		case 8: /* set prefetch off */
+-		case 9: /* set prefetch on */
+-			set_prefetch_mode(index, pio & 1);
+-			printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis");
+-			return;
++	case 6: /* set fast-devsel off */
++	case 7: /* set fast-devsel on */
++		b = get_cmd640_reg(CNTRL) & ~0x27;
++		if (pio & 1)
++			b |= 0x27;
++		put_cmd640_reg(CNTRL, b);
++		printk("%s: %sabled cmd640 fast host timing (devsel)\n",
++			drive->name, (pio & 1) ? "en" : "dis");
++		return;
++	case 8: /* set prefetch off */
++	case 9: /* set prefetch on */
++		set_prefetch_mode(drive, index, pio & 1);
++		printk("%s: %sabled cmd640 prefetch\n",
++			drive->name, (pio & 1) ? "en" : "dis");
++		return;
+ 	}
+ 
+ 	cycle_time = ide_pio_cycle_time(drive, pio);
+-	cmd640_set_mode(index, pio, cycle_time);
++	cmd640_set_mode(drive, index, pio, cycle_time);
+ 
+ 	printk("%s: selected cmd640 PIO mode%d (%dns)",
+ 		drive->name, pio, cycle_time);
+@@ -724,6 +695,7 @@ static int __init cmd640x_init(void)
+ 	unsigned int index;
+ 	u8 b, cfr;
+ 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	hw_regs_t hw[2];
+ 
+ 	if (cmd640_vlb && probe_for_cmd640_vlb()) {
+ 		bus_type = "VLB";
+@@ -758,21 +730,34 @@ static int __init cmd640x_init(void)
+ 	cfr = get_cmd640_reg(CFR);
+ 	cmd640_chip_version = cfr & CFR_DEVREV;
+ 	if (cmd640_chip_version == 0) {
+-		printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
++		printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
+ 		return 0;
+ 	}
+ 
++	memset(&hw, 0, sizeof(hw));
++
++	ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++	hw[0].irq = 14;
++
++	ide_std_init_ports(&hw[1], 0x170, 0x376);
++	hw[1].irq = 15;
++
++	printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
++			 "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
++
++	cmd_hwif0 = ide_find_port();
++
+ 	/*
+ 	 * Initialize data for primary port
+ 	 */
+-	setup_device_ptrs ();
+-	printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n",
+-	       cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr);
++	if (cmd_hwif0) {
++		ide_init_port_hw(cmd_hwif0, &hw[0]);
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+-	cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
++		cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+ 
+-	idx[0] = cmd_hwif0->index;
++		idx[0] = cmd_hwif0->index;
++	}
+ 
+ 	/*
+ 	 * Ensure compatibility by always using the slowest timings
+@@ -784,11 +769,13 @@ static int __init cmd640x_init(void)
+ 	put_cmd640_reg(CMDTIM, 0);
+ 	put_cmd640_reg(BRST, 0x40);
+ 
++	cmd_hwif1 = ide_find_port();
++
+ 	/*
+ 	 * Try to enable the secondary interface, if not already enabled
+ 	 */
+-	if (cmd_hwif1->noprobe ||
+-	    (cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe)) {
++	if (cmd_hwif1 &&
++	    cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) {
+ 		port2 = "not probed";
+ 	} else {
+ 		b = get_cmd640_reg(CNTRL);
+@@ -819,14 +806,15 @@ static int __init cmd640x_init(void)
+ 	/*
+ 	 * Initialize data for secondary cmd640 port, if enabled
+ 	 */
+-	if (second_port_cmd640) {
++	if (second_port_cmd640 && cmd_hwif1) {
++		ide_init_port_hw(cmd_hwif1, &hw[1]);
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ 		cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+ 
+ 		idx[1] = cmd_hwif1->index;
+ 	}
+-	printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
++	printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
+ 			 second_port_cmd640 ? "" : "not ", port2);
+ 
+ 	/*
+@@ -834,18 +822,30 @@ static int __init cmd640x_init(void)
+ 	 * Do not unnecessarily disturb any prior BIOS setup of these.
+ 	 */
+ 	for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) {
+-		ide_drive_t *drive = cmd_drives[index];
++		ide_drive_t *drive;
++
++		if (index > 1) {
++			if (cmd_hwif1 == NULL)
++				continue;
++			drive = &cmd_hwif1->drives[index & 1];
++		} else  {
++			if (cmd_hwif0 == NULL)
++				continue;
++			drive = &cmd_hwif0->drives[index & 1];
++		}
++
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ 		if (drive->autotune || ((index > 1) && second_port_toggled)) {
+-	 		/*
+-	 		 * Reset timing to the slowest speed and turn off prefetch.
+-			 * This way, the drive identify code has a better chance.
++			/*
++			 * Reset timing to the slowest speed and turn off
++			 * prefetch.  This way, the drive identify code has
++			 * a better chance.
+ 			 */
+ 			setup_counts    [index] = 4;	/* max possible */
+ 			active_counts   [index] = 16;	/* max possible */
+ 			recovery_counts [index] = 16;	/* max possible */
+-			program_drive_counts (index);
+-			set_prefetch_mode (index, 0);
++			program_drive_counts(drive, index);
++			set_prefetch_mode(drive, index, 0);
+ 			printk("cmd640: drive%d timings/prefetch cleared\n", index);
+ 		} else {
+ 			/*
+@@ -853,7 +853,7 @@ static int __init cmd640x_init(void)
+ 			 * This preserves any prior BIOS setup.
+ 			 */
+ 			retrieve_drive_counts (index);
+-			check_prefetch (index);
++			check_prefetch(drive, index);
+ 			printk("cmd640: drive%d timings/prefetch(%s) preserved",
+ 				index, drive->no_io_32bit ? "off" : "on");
+ 			display_clocks(index);
+@@ -862,7 +862,7 @@ static int __init cmd640x_init(void)
+ 		/*
+ 		 * Set the drive unmask flags to match the prefetch setting
+ 		 */
+-		check_prefetch (index);
++		check_prefetch(drive, index);
+ 		printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
+ 			index, drive->no_io_32bit ? "off" : "on");
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
+index edabe62..8baccfe 100644
+--- a/drivers/ide/pci/cmd64x.c
++++ b/drivers/ide/pci/cmd64x.c
+@@ -440,8 +440,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ 		.init_hwif	= init_hwif_cmd64x,
+ 		.enablebits	= {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
+ 		.host_flags	= IDE_HFLAG_CLEAR_SIMPLEX |
+-				  IDE_HFLAG_ABUSE_PREFETCH |
+-				  IDE_HFLAG_BOOTABLE,
++				  IDE_HFLAG_ABUSE_PREFETCH,
+ 		.pio_mask	= ATA_PIO5,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= 0x00, /* no udma */
+@@ -451,7 +450,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ 		.init_hwif	= init_hwif_cmd64x,
+ 		.enablebits	= {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+ 		.chipset	= ide_cmd646,
+-		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH,
+ 		.pio_mask	= ATA_PIO5,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA2,
+@@ -460,7 +459,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ 		.init_chipset	= init_chipset_cmd64x,
+ 		.init_hwif	= init_hwif_cmd64x,
+ 		.enablebits	= {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+-		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH,
+ 		.pio_mask	= ATA_PIO5,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA4,
+@@ -469,7 +468,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ 		.init_chipset	= init_chipset_cmd64x,
+ 		.init_hwif	= init_hwif_cmd64x,
+ 		.enablebits	= {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+-		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH,
+ 		.pio_mask	= ATA_PIO5,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA5,
+diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
+index 1c163e4..01b37ec 100644
+--- a/drivers/ide/pci/cs5520.c
++++ b/drivers/ide/pci/cs5520.c
+@@ -122,8 +122,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
+ 				  IDE_HFLAG_CS5520 |		\
+ 				  IDE_HFLAG_VDMA |		\
+ 				  IDE_HFLAG_NO_ATAPI_DMA |	\
+-				  IDE_HFLAG_ABUSE_SET_DMA_MODE |\
+-				  IDE_HFLAG_BOOTABLE,		\
++				  IDE_HFLAG_ABUSE_SET_DMA_MODE, \
+ 		.pio_mask	= ATA_PIO4,			\
+ 	}
+ 
+diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
+index 941a134..56a369c 100644
+--- a/drivers/ide/pci/cs5530.c
++++ b/drivers/ide/pci/cs5530.c
+@@ -249,8 +249,7 @@ static const struct ide_port_info cs5530_chipset __devinitdata = {
+ 	.init_chipset	= init_chipset_cs5530,
+ 	.init_hwif	= init_hwif_cs5530,
+ 	.host_flags	= IDE_HFLAG_SERIALIZE |
+-			  IDE_HFLAG_POST_SET_MODE |
+-			  IDE_HFLAG_BOOTABLE,
++			  IDE_HFLAG_POST_SET_MODE,
+ 	.pio_mask	= ATA_PIO4,
+ 	.mwdma_mask	= ATA_MWDMA2,
+ 	.udma_mask	= ATA_UDMA2,
+diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
+index d7b5ea9..c9685f2 100644
+--- a/drivers/ide/pci/cs5535.c
++++ b/drivers/ide/pci/cs5535.c
+@@ -186,7 +186,7 @@ static const struct ide_port_info cs5535_chipset __devinitdata = {
+ 	.name		= "CS5535",
+ 	.init_hwif	= init_hwif_cs5535,
+ 	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
+-			  IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE,
++			  IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ 	.pio_mask	= ATA_PIO4,
+ 	.mwdma_mask	= ATA_MWDMA2,
+ 	.udma_mask	= ATA_UDMA4,
+diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
+index 724cbac..08eab7e 100644
+--- a/drivers/ide/pci/cy82c693.c
++++ b/drivers/ide/pci/cy82c693.c
+@@ -6,7 +6,7 @@
+  *
+  * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
+  * Writing the driver was quite simple, since most of the job is
+- * done by the generic pci-ide support. 
++ * done by the generic pci-ide support.
+  * The hard part was finding the CY82C693's datasheet on Cypress's
+  * web page :-(. But Altavista solved this problem :-).
+  *
+@@ -15,12 +15,12 @@
+  * - I recently got a 16.8G IBM DTTA, so I was able to test it with
+  *   a large and fast disk - the results look great, so I'd say the
+  *   driver is working fine :-)
+- *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA 
+- * - this is my first linux driver, so there's probably a lot  of room 
++ *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA
++ * - this is my first linux driver, so there's probably a lot  of room
+  *   for optimizations and bug fixing, so feel free to do it.
+  * - use idebus=xx parameter to set PCI bus speed - needed to calc
+  *   timings for PIO modes (default will be 40)
+- * - if using PIO mode it's a good idea to set the PIO mode and 
++ * - if using PIO mode it's a good idea to set the PIO mode and
+  *   32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
+  * - I had some problems with my IBM DHEA with PIO modes < 2
+  *   (lost interrupts) ?????
+@@ -110,11 +110,11 @@ typedef struct pio_clocks_s {
+  * calc clocks using bus_speed
+  * returns (rounded up) time in bus clocks for time in ns
+  */
+-static int calc_clk (int time, int bus_speed)
++static int calc_clk(int time, int bus_speed)
+ {
+ 	int clocks;
+ 
+-	clocks = (time*bus_speed+999)/1000 -1;
++	clocks = (time*bus_speed+999)/1000 - 1;
+ 
+ 	if (clocks < 0)
+ 		clocks = 0;
+@@ -132,8 +132,8 @@ static int calc_clk (int time, int bus_speed)
+  * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
+  *       for mode 3 and 4 drives 8 and 16-bit timings are the same
+  *
+- */ 
+-static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
++ */
++static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
+ {
+ 	int clk1, clk2;
+ 	int bus_speed = system_bus_clock();	/* get speed of PCI bus */
+@@ -158,7 +158,7 @@ static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
+ 	clk1 = (clk1<<4)|clk2;	/* combine active and recovery clocks */
+ 
+ 	/* note: we use the same values for 16bit IOR and IOW
+-         *	those are all the same, since I don't have other
++	 *	those are all the same, since I don't have other
+ 	 *	timings than those from ide-lib.c
+ 	 */
+ 
+@@ -186,7 +186,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ 	outb(index, CY82_INDEX_PORT);
+ 	data = inb(CY82_DATA_PORT);
+ 
+-	printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
++	printk(KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
+ 		drive->name, HWIF(drive)->channel, drive->select.b.unit,
+ 		(data&0x3), ((data>>2)&1));
+ #endif /* CY82C693_DEBUG_LOGS */
+@@ -202,7 +202,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ 		mode & 3, single);
+ #endif /* CY82C693_DEBUG_INFO */
+ 
+-	/* 
++	/*
+ 	 * note: below we set the value for Bus Master IDE TimeOut Register
+ 	 * I'm not absolutly sure what this does, but it solved my problem
+ 	 * with IDE DMA and sound, so I now can play sound and work with
+@@ -216,8 +216,8 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ 	outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
+ 	outb(data, CY82_DATA_PORT);
+ 
+-#if CY82C693_DEBUG_INFO	
+-	printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
++#if CY82C693_DEBUG_INFO
++	printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
+ 		drive->name, data);
+ #endif /* CY82C693_DEBUG_INFO */
+ }
+@@ -242,14 +242,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 
+ #if CY82C693_DEBUG_LOGS
+ 	/* for debug let's show the register values */
+-	
+-       	if (drive->select.b.unit == 0) {
++
++	if (drive->select.b.unit == 0) {
+ 		/*
+-		 * get master drive registers               	
++		 * get master drive registers
+ 		 * address setup control register
+ 		 * is 32 bit !!!
+-		 */ 
+-	  	pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);                
++		 */
++		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+ 		addrCtrl &= 0x0F;
+ 
+ 		/* now let's get the remaining registers */
+@@ -261,7 +261,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 		 * set slave drive registers
+ 		 * address setup control register
+ 		 * is 32 bit !!!
+-		 */ 
++		 */
+ 		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+ 
+ 		addrCtrl &= 0xF0;
+@@ -288,9 +288,9 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 		 * set master drive
+ 		 * address setup control register
+ 		 * is 32 bit !!!
+-		 */ 
++		 */
+ 		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+-		
++
+ 		addrCtrl &= (~0xF);
+ 		addrCtrl |= (unsigned int)pclk.address_time;
+ 		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
+@@ -299,14 +299,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 		pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
+ 		pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
+ 		pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
+-		
++
+ 		addrCtrl &= 0xF;
+ 	} else {
+ 		/*
+ 		 * set slave drive
+ 		 * address setup control register
+ 		 * is 32 bit !!!
+-		 */ 
++		 */
+ 		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+ 
+ 		addrCtrl &= (~0xF0);
+@@ -320,7 +320,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 
+ 		addrCtrl >>= 4;
+ 		addrCtrl &= 0xF;
+-	}	
++	}
+ 
+ #if CY82C693_DEBUG_INFO
+ 	printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
+@@ -340,41 +340,41 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
+ 
+ #ifdef CY82C693_SETDMA_CLOCK
+ 	u8 data = 0;
+-#endif /* CY82C693_SETDMA_CLOCK */ 
++#endif /* CY82C693_SETDMA_CLOCK */
+ 
+ 	/* write info about this verion of the driver */
+ 	printk(KERN_INFO CY82_VERSION "\n");
+ 
+ #ifdef CY82C693_SETDMA_CLOCK
+        /* okay let's set the DMA clock speed */
+-        
+-        outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+-        data = inb(CY82_DATA_PORT);
++
++	outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
++	data = inb(CY82_DATA_PORT);
+ 
+ #if CY82C693_DEBUG_INFO
+ 	printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n",
+ 		name, data);
+ #endif /* CY82C693_DEBUG_INFO */
+ 
+-        /*
++	/*
+ 	 * for some reason sometimes the DMA controller
+ 	 * speed is set to ATCLK/2 ???? - we fix this here
+-	 * 
++	 *
+ 	 * note: i don't know what causes this strange behaviour,
+ 	 *       but even changing the dma speed doesn't solve it :-(
+-	 *       the ide performance is still only half the normal speed 
+-	 * 
++	 *       the ide performance is still only half the normal speed
++	 *
+ 	 *       if anybody knows what goes wrong with my machine, please
+ 	 *       let me know - ASK
+-         */
++	 */
+ 
+ 	data |= 0x03;
+ 
+-        outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+-        outb(data, CY82_DATA_PORT);
++	outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
++	outb(data, CY82_DATA_PORT);
+ 
+ #if CY82C693_DEBUG_INFO
+-	printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
++	printk(KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
+ 		name, data);
+ #endif /* CY82C693_DEBUG_INFO */
+ 
+@@ -410,8 +410,7 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = {
+ 	.init_iops	= init_iops_cy82c693,
+ 	.init_hwif	= init_hwif_cy82c693,
+ 	.chipset	= ide_cy82c693,
+-	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_CY82C693 |
+-			  IDE_HFLAG_BOOTABLE,
++	.host_flags	= IDE_HFLAG_SINGLE,
+ 	.pio_mask	= ATA_PIO4,
+ 	.swdma_mask	= ATA_SWDMA2,
+ 	.mwdma_mask	= ATA_MWDMA2,
+@@ -424,7 +423,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
+ 
+ 	/* CY82C693 is more than only a IDE controller.
+ 	   Function 1 is primary IDE channel, function 2 - secondary. */
+-        if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
++	if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
+ 	    PCI_FUNC(dev->devfn) == 1) {
+ 		dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
+ 		ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
+diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
+index 3f9cd64..753b86f 100644
+--- a/drivers/ide/pci/delkin_cb.c
++++ b/drivers/ide/pci/delkin_cb.c
+@@ -71,25 +71,25 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
+ 		if (setup[i])
+ 			outb(setup[i], base + i);
+ 	}
+-	pci_release_regions(dev);	/* IDE layer handles regions itself */
+ 
+ 	memset(&hw, 0, sizeof(hw));
+ 	ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
+ 	hw.irq = dev->irq;
+ 	hw.chipset = ide_pci;		/* this enables IRQ sharing */
+ 
+-	hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	hwif = ide_find_port();
+ 	if (hwif == NULL)
+ 		goto out_disable;
+ 
+ 	i = hwif->index;
+ 
+ 	if (hwif->present)
+-		ide_unregister(i, 0, 0);
+-	else if (!hwif->hold)
++		ide_unregister(i);
++	else
+ 		ide_init_port_data(hwif, i);
+ 
+ 	ide_init_port_hw(hwif, &hw);
++	hwif->mmio = 1;
+ 	hwif->quirkproc = &ide_undecoded_slave;
+ 
+ 	idx[0] = i;
+@@ -110,6 +110,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
+ 
+ out_disable:
+ 	printk(KERN_ERR "delkin_cb: no IDE devices found\n");
++	pci_release_regions(dev);
+ 	pci_disable_device(dev);
+ 	return -ENODEV;
+ }
+@@ -120,8 +121,9 @@ delkin_cb_remove (struct pci_dev *dev)
+ 	ide_hwif_t *hwif = pci_get_drvdata(dev);
+ 
+ 	if (hwif)
+-		ide_unregister(hwif->index, 0, 0);
++		ide_unregister(hwif->index);
+ 
++	pci_release_regions(dev);
+ 	pci_disable_device(dev);
+ }
+ 
+diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
+index 7fd83a9..041720e 100644
+--- a/drivers/ide/pci/generic.c
++++ b/drivers/ide/pci/generic.c
+@@ -38,8 +38,7 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
+ 	{ \
+ 		.name		= name_str, \
+ 		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
+-				  extra_flags | \
+-				  IDE_HFLAG_BOOTABLE, \
++				  extra_flags, \
+ 		.swdma_mask	= ATA_SWDMA2, \
+ 		.mwdma_mask	= ATA_MWDMA2, \
+ 		.udma_mask	= ATA_UDMA6, \
+@@ -50,9 +49,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
+ 
+ 	{	/* 1 */
+ 		.name		= "NS87410",
+-		.enablebits	= {{0x43,0x08,0x08}, {0x47,0x08,0x08}},
+-		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+-				  IDE_HFLAG_BOOTABLE,
++		.enablebits	= { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
++		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA,
+ 		.swdma_mask	= ATA_SWDMA2,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA6,
+@@ -99,7 +97,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
+  *	Called when the PCI registration layer (or the IDE initialization)
+  *	finds a device matching our IDE device tables.
+  */
+- 
++
+ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	const struct ide_port_info *d = &generic_chipsets[id->driver_data];
+diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
+index 9f01da4..9f2fc30 100644
+--- a/drivers/ide/pci/hpt34x.c
++++ b/drivers/ide/pci/hpt34x.c
+@@ -133,7 +133,7 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
+ 		.init_chipset	= init_chipset_hpt34x,
+ 		.init_hwif	= init_hwif_hpt34x,
+ 		.extra		= 16,
+-		.host_flags	= IDE_HFLAGS_HPT34X,
++		.host_flags	= IDE_HFLAGS_HPT34X | IDE_HFLAG_NON_BOOTABLE,
+ 		.pio_mask	= ATA_PIO5,
+ 	},
+ 	{ /* 1 */
+diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
+index 6357bb6..a490906 100644
+--- a/drivers/ide/pci/hpt366.c
++++ b/drivers/ide/pci/hpt366.c
+@@ -760,7 +760,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
+ 		}
+ 	} else
+ 		outb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+-		     IDE_CONTROL_REG);
++		     hwif->io_ports[IDE_CONTROL_OFFSET]);
+ }
+ 
+ /*
+@@ -929,64 +929,6 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
+ 	hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21);
+ }
+ 
+-/* 
+- * Set/get power state for a drive.
+- * NOTE: affects both drives on each channel.
+- *
+- * When we turn the power back on, we need to re-initialize things.
+- */
+-#define TRISTATE_BIT  0x8000
+-
+-static int hpt3xx_busproc(ide_drive_t *drive, int state)
+-{
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+-	u8  mcr_addr		= hwif->select_data + 2;
+-	u8  resetmask		= hwif->channel ? 0x80 : 0x40;
+-	u8  bsr2		= 0;
+-	u16 mcr			= 0;
+-
+-	hwif->bus_state = state;
+-
+-	/* Grab the status. */
+-	pci_read_config_word(dev, mcr_addr, &mcr);
+-	pci_read_config_byte(dev, 0x59, &bsr2);
+-
+-	/*
+-	 * Set the state. We don't set it if we don't need to do so.
+-	 * Make sure that the drive knows that it has failed if it's off.
+-	 */
+-	switch (state) {
+-	case BUSSTATE_ON:
+-		if (!(bsr2 & resetmask))
+-			return 0;
+-		hwif->drives[0].failures = hwif->drives[1].failures = 0;
+-
+-		pci_write_config_byte(dev, 0x59, bsr2 & ~resetmask);
+-		pci_write_config_word(dev, mcr_addr, mcr & ~TRISTATE_BIT);
+-		return 0;
+-	case BUSSTATE_OFF:
+-		if ((bsr2 & resetmask) && !(mcr & TRISTATE_BIT))
+-			return 0;
+-		mcr &= ~TRISTATE_BIT;
+-		break;
+-	case BUSSTATE_TRISTATE:
+-		if ((bsr2 & resetmask) &&  (mcr & TRISTATE_BIT))
+-			return 0;
+-		mcr |= TRISTATE_BIT;
+-		break;
+-	default:
+-		return -EINVAL;
+-	}
+-
+-	hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+-	hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+-
+-	pci_write_config_word(dev, mcr_addr, mcr);
+-	pci_write_config_byte(dev, 0x59, bsr2 | resetmask);
+-	return 0;
+-}
+-
+ /**
+  *	hpt37x_calibrate_dpll	-	calibrate the DPLL
+  *	@dev: PCI device
+@@ -1334,7 +1276,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+ 
+ 	hwif->quirkproc		= &hpt3xx_quirkproc;
+ 	hwif->maskproc		= &hpt3xx_maskproc;
+-	hwif->busproc		= &hpt3xx_busproc;
+ 
+ 	hwif->udma_filter	= &hpt3xx_udma_filter;
+ 	hwif->mdma_filter	= &hpt3xx_mdma_filter;
+@@ -1616,7 +1557,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
+ 			hpt374_init(dev, dev2);
+ 		else {
+ 			if (hpt36x_init(dev, dev2))
+-				d.host_flags |= IDE_HFLAG_BOOTABLE;
++				d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
+ 		}
+ 
+ 		ret = ide_setup_pci_devices(dev, dev2, &d);
+diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
+index e3427ea..5b5b0cc 100644
+--- a/drivers/ide/pci/it8213.c
++++ b/drivers/ide/pci/it8213.c
+@@ -35,7 +35,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	static DEFINE_SPINLOCK(tune_lock);
+ 	int control = 0;
+ 
+-	static const u8 timings[][2]= {
++	static const u8 timings[][2] = {
+ 					{ 0, 0 },
+ 					{ 0, 0 },
+ 					{ 1, 0 },
+@@ -105,11 +105,10 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 
+ 		if (!(reg48 & u_flag))
+ 			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+-		if (speed >= XFER_UDMA_5) {
++		if (speed >= XFER_UDMA_5)
+ 			pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+-		} else {
++		else
+ 			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+-		}
+ 
+ 		if ((reg4a & a_speed) != u_speed)
+ 			pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
+@@ -170,9 +169,8 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
+ 	{						\
+ 		.name		= name_str,		\
+ 		.init_hwif	= init_hwif_it8213,	\
+-		.enablebits	= {{0x41,0x80,0x80}}, \
+-		.host_flags	= IDE_HFLAG_SINGLE |	\
+-				  IDE_HFLAG_BOOTABLE,	\
++		.enablebits	= { {0x41, 0x80, 0x80} }, \
++		.host_flags	= IDE_HFLAG_SINGLE,	\
+ 		.pio_mask	= ATA_PIO4,		\
+ 		.swdma_mask	= ATA_SWDMA2_ONLY,	\
+ 		.mwdma_mask	= ATA_MWDMA12_ONLY,	\
+diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
+index d8a1674..a38ec47 100644
+--- a/drivers/ide/pci/it821x.c
++++ b/drivers/ide/pci/it821x.c
+@@ -523,16 +523,12 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
+ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
+ {
+ 	struct pci_dev *dev = to_pci_dev(hwif->dev);
+-	struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
++	struct it821x_dev **itdevs = (struct it821x_dev **)pci_get_drvdata(dev);
++	struct it821x_dev *idev = itdevs[hwif->channel];
+ 	u8 conf;
+ 
+ 	hwif->quirkproc = &it821x_quirkproc;
+ 
+-	if (idev == NULL) {
+-		printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
+-		return;
+-	}
+-
+ 	ide_set_hwifdata(hwif, idev);
+ 
+ 	pci_read_config_byte(dev, 0x50, &conf);
+@@ -623,7 +619,6 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
+ 		.name		= name_str,		\
+ 		.init_chipset	= init_chipset_it821x,	\
+ 		.init_hwif	= init_hwif_it821x,	\
+-		.host_flags	= IDE_HFLAG_BOOTABLE,	\
+ 		.pio_mask	= ATA_PIO4,		\
+ 	}
+ 
+@@ -642,6 +637,22 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
+ 
+ static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	struct it821x_dev *itdevs[2] = { NULL, NULL} , *itdev;
++	unsigned int i;
++
++	for (i = 0; i < 2; i++) {
++		itdev = kzalloc(sizeof(*itdev), GFP_KERNEL);
++		if (itdev == NULL) {
++			kfree(itdevs[0]);
++			printk(KERN_ERR "it821x: out of memory\n");
++			return -ENOMEM;
++		}
++
++		itdevs[i] = itdev;
++	}
++
++	pci_set_drvdata(dev, itdevs);
++
+ 	return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
+ }
+ 
+diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
+index a56bcb4..673f7dc 100644
+--- a/drivers/ide/pci/jmicron.c
++++ b/drivers/ide/pci/jmicron.c
+@@ -63,8 +63,7 @@ static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
+ 	 *	actually do our cable checking etc. Thankfully we don't need
+ 	 *	to do the plumbing for other cases.
+ 	 */
+-	switch (port_map[port])
+-	{
++	switch (port_map[port]) {
+ 	case PORT_PATA0:
+ 		if (control & (1 << 3))	/* 40/80 pin primary */
+ 			return ATA_CBL_PATA40;
+@@ -114,7 +113,6 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
+ static const struct ide_port_info jmicron_chipset __devinitdata = {
+ 	.name		= "JMB",
+ 	.init_hwif	= init_hwif_jmicron,
+-	.host_flags	= IDE_HFLAG_BOOTABLE,
+ 	.enablebits	= { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
+ 	.pio_mask	= ATA_PIO5,
+ 	.mwdma_mask	= ATA_MWDMA2,
+diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
+index bf0d3b2..3015d69 100644
+--- a/drivers/ide/pci/ns87415.c
++++ b/drivers/ide/pci/ns87415.c
+@@ -181,6 +181,10 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive)
+ 	return 1;
+ }
+ 
++#ifndef ide_default_irq
++#define ide_default_irq(irq) 0
++#endif
++
+ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+ {
+ 	struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -261,8 +265,7 @@ static const struct ide_port_info ns87415_chipset __devinitdata = {
+ #endif
+ 	.init_hwif	= init_hwif_ns87415,
+ 	.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+-			  IDE_HFLAG_NO_ATAPI_DMA |
+-			  IDE_HFLAG_BOOTABLE,
++			  IDE_HFLAG_NO_ATAPI_DMA,
+ };
+ 
+ static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
+index 46e8748..88a4dd9 100644
+--- a/drivers/ide/pci/opti621.c
++++ b/drivers/ide/pci/opti621.c
+@@ -57,9 +57,9 @@
+  * (use idebus=xx to select PCI bus speed).
+  *
+  * Version 0.1, Nov 8, 1996
+- * by Jaromir Koutek, for 2.1.8. 
++ * by Jaromir Koutek, for 2.1.8.
+  * Initial version of driver.
+- * 
++ *
+  * Version 0.2
+  * Number 0.2 skipped.
+  *
+@@ -75,7 +75,7 @@
+  * by Jaromir Koutek
+  * Updates for use with (again) new IDE block driver.
+  * Update of documentation.
+- * 
++ *
+  * Version 0.6, Jan 2, 1999
+  * by Jaromir Koutek
+  * Reversed to version 0.3 of the driver, because
+@@ -208,29 +208,34 @@ typedef struct pio_clocks_s {
+ 
+ static void compute_clocks(int pio, pio_clocks_t *clks)
+ {
+-        if (pio != PIO_NOT_EXIST) {
+-        	int adr_setup, data_pls;
++	if (pio != PIO_NOT_EXIST) {
++		int adr_setup, data_pls;
+ 		int bus_speed = system_bus_clock();
+ 
+- 	       	adr_setup = ide_pio_timings[pio].setup_time;
+-  	      	data_pls = ide_pio_timings[pio].active_time;
+-	  	clks->address_time = cmpt_clk(adr_setup, bus_speed);
+-	     	clks->data_time = cmpt_clk(data_pls, bus_speed);
+-     		clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
+-     			- adr_setup-data_pls, bus_speed);
+-     		if (clks->address_time<1) clks->address_time = 1;
+-     		if (clks->address_time>4) clks->address_time = 4;
+-     		if (clks->data_time<1) clks->data_time = 1;
+-     		if (clks->data_time>16) clks->data_time = 16;
+-     		if (clks->recovery_time<2) clks->recovery_time = 2;
+-     		if (clks->recovery_time>17) clks->recovery_time = 17;
++		adr_setup = ide_pio_timings[pio].setup_time;
++		data_pls = ide_pio_timings[pio].active_time;
++		clks->address_time = cmpt_clk(adr_setup, bus_speed);
++		clks->data_time = cmpt_clk(data_pls, bus_speed);
++		clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
++			- adr_setup-data_pls, bus_speed);
++		if (clks->address_time < 1)
++			clks->address_time = 1;
++		if (clks->address_time > 4)
++			clks->address_time = 4;
++		if (clks->data_time < 1)
++			clks->data_time = 1;
++		if (clks->data_time > 16)
++			clks->data_time = 16;
++		if (clks->recovery_time < 2)
++			clks->recovery_time = 2;
++		if (clks->recovery_time > 17)
++			clks->recovery_time = 17;
+ 	} else {
+ 		clks->address_time = 1;
+ 		clks->data_time = 1;
+ 		clks->recovery_time = 2;
+ 		/* minimal values */
+ 	}
+- 
+ }
+ 
+ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+@@ -247,8 +252,8 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 
+ 	/* sets drive->drive_data for both drives */
+ 	compute_pios(drive, pio);
+- 	pio1 = hwif->drives[0].drive_data;
+- 	pio2 = hwif->drives[1].drive_data;
++	pio1 = hwif->drives[0].drive_data;
++	pio2 = hwif->drives[1].drive_data;
+ 
+ 	compute_clocks(pio1, &first);
+ 	compute_clocks(pio2, &second);
+@@ -275,7 +280,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 
+ 	spin_lock_irqsave(&opti621_lock, flags);
+ 
+-     	reg_base = hwif->io_ports[IDE_DATA_OFFSET];
++	reg_base = hwif->io_ports[IDE_DATA_OFFSET];
+ 
+ 	/* allow Register-B */
+ 	outb(0xc0, reg_base + CNTRL_REG);
+@@ -324,7 +329,7 @@ static void __devinit opti621_port_init_devs(ide_hwif_t *hwif)
+ /*
+  * init_hwif_opti621() is called once for each hwif found at boot.
+  */
+-static void __devinit init_hwif_opti621 (ide_hwif_t *hwif)
++static void __devinit init_hwif_opti621(ide_hwif_t *hwif)
+ {
+ 	hwif->port_init_devs = opti621_port_init_devs;
+ 	hwif->set_pio_mode = &opti621_set_pio_mode;
+@@ -334,18 +339,16 @@ static const struct ide_port_info opti621_chipsets[] __devinitdata = {
+ 	{	/* 0 */
+ 		.name		= "OPTI621",
+ 		.init_hwif	= init_hwif_opti621,
+-		.enablebits	= {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
+-		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+-				  IDE_HFLAG_BOOTABLE,
++		.enablebits	= { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
++		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA,
+ 		.pio_mask	= ATA_PIO3,
+ 		.swdma_mask	= ATA_SWDMA2,
+ 		.mwdma_mask	= ATA_MWDMA2,
+-	},{	/* 1 */
++	}, {	/* 1 */
+ 		.name		= "OPTI621X",
+ 		.init_hwif	= init_hwif_opti621,
+-		.enablebits	= {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
+-		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+-				  IDE_HFLAG_BOOTABLE,
++		.enablebits	= { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
++		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA,
+ 		.pio_mask	= ATA_PIO3,
+ 		.swdma_mask	= ATA_SWDMA2,
+ 		.mwdma_mask	= ATA_MWDMA2,
+diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
+index decef0f..89d74ff 100644
+--- a/drivers/ide/pci/piix.c
++++ b/drivers/ide/pci/piix.c
+@@ -307,9 +307,9 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif)
+ }
+ 
+ #ifndef CONFIG_IA64
+- #define IDE_HFLAGS_PIIX (IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE)
++ #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
+ #else
+- #define IDE_HFLAGS_PIIX IDE_HFLAG_BOOTABLE
++ #define IDE_HFLAGS_PIIX 0
+ #endif
+ 
+ #define DECLARE_PIIX_DEV(name_str, udma) \
+diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
+index 5167661..532154a 100644
+--- a/drivers/ide/pci/rz1000.c
++++ b/drivers/ide/pci/rz1000.c
+@@ -43,7 +43,7 @@ static const struct ide_port_info rz1000_chipset __devinitdata = {
+ 	.name		= "RZ100x",
+ 	.init_hwif	= init_hwif_rz1000,
+ 	.chipset	= ide_rz1000,
+-	.host_flags	= IDE_HFLAG_NO_DMA | IDE_HFLAG_BOOTABLE,
++	.host_flags	= IDE_HFLAG_NO_DMA,
+ };
+ 
+ static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
+index 561aa47..44985c8 100644
+--- a/drivers/ide/pci/sc1200.c
++++ b/drivers/ide/pci/sc1200.c
+@@ -307,8 +307,7 @@ static const struct ide_port_info sc1200_chipset __devinitdata = {
+ 	.init_hwif	= init_hwif_sc1200,
+ 	.host_flags	= IDE_HFLAG_SERIALIZE |
+ 			  IDE_HFLAG_POST_SET_MODE |
+-			  IDE_HFLAG_ABUSE_DMA_MODES |
+-			  IDE_HFLAG_BOOTABLE,
++			  IDE_HFLAG_ABUSE_DMA_MODES,
+ 	.pio_mask	= ATA_PIO4,
+ 	.mwdma_mask	= ATA_MWDMA2,
+ 	.udma_mask	= ATA_UDMA2,
+diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
+index 238e3e1..5214579 100644
+--- a/drivers/ide/pci/scc_pata.c
++++ b/drivers/ide/pci/scc_pata.c
+@@ -65,7 +65,7 @@
+ 
+ static struct scc_ports {
+ 	unsigned long ctl, dma;
+-	unsigned char hwif_id;  /* for removing hwif from system */
++	ide_hwif_t *hwif;  /* for removing port from system */
+ } scc_ports[MAX_HWIFS];
+ 
+ /* PIO transfer mode  table */
+@@ -334,7 +334,8 @@ static int scc_ide_dma_end(ide_drive_t * drive)
+ 
+ 	/* errata A308 workaround: Step5 (check data loss) */
+ 	/* We don't check non ide_disk because it is limited to UDMA4 */
+-	if (!(in_be32((void __iomem *)IDE_ALTSTATUS_REG) & ERR_STAT) &&
++	if (!(in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET])
++	      & ERR_STAT) &&
+ 	    drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
+ 		reg = in_be32((void __iomem *)intsts_port);
+ 		if (!(reg & INTSTS_ACTEINT)) {
+@@ -437,7 +438,8 @@ static int scc_dma_test_irq(ide_drive_t *drive)
+ 	u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014);
+ 
+ 	/* SCC errata A252,A308 workaround: Step4 */
+-	if ((in_be32((void __iomem *)IDE_ALTSTATUS_REG) & ERR_STAT) &&
++	if ((in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET])
++	     & ERR_STAT) &&
+ 	    (int_stat & INTSTS_INTRQ))
+ 		return 1;
+ 
+@@ -523,6 +525,39 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
+ 	return -ENOMEM;
+ }
+ 
++static int scc_ide_setup_pci_device(struct pci_dev *dev,
++				    const struct ide_port_info *d)
++{
++	struct scc_ports *ports = pci_get_drvdata(dev);
++	ide_hwif_t *hwif = NULL;
++	hw_regs_t hw;
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	int i;
++
++	hwif = ide_find_port();
++	if (hwif == NULL) {
++		printk(KERN_ERR "%s: too many IDE interfaces, "
++				"no room in table\n", SCC_PATA_NAME);
++		return -ENOMEM;
++	}
++
++	memset(&hw, 0, sizeof(hw));
++	for (i = IDE_DATA_OFFSET; i <= IDE_CONTROL_OFFSET; i++)
++		hw.io_ports[i] = ports->dma + 0x20 + i * 4;
++	hw.irq = dev->irq;
++	hw.dev = &dev->dev;
++	hw.chipset = ide_pci;
++	ide_init_port_hw(hwif, &hw);
++	hwif->dev = &dev->dev;
++	hwif->cds = d;
++
++	idx[0] = hwif->index;
++
++	ide_device_add(idx, d);
++
++	return 0;
++}
++
+ /**
+  *	init_setup_scc	-	set up an SCC PATA Controller
+  *	@dev: PCI device
+@@ -545,10 +580,13 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
+ 	struct scc_ports *ports;
+ 	int rc;
+ 
++	rc = pci_enable_device(dev);
++	if (rc)
++		goto end;
++
+ 	rc = setup_mmio_scc(dev, d->name);
+-	if (rc < 0) {
+-		return rc;
+-	}
++	if (rc < 0)
++		goto end;
+ 
+ 	ports = pci_get_drvdata(dev);
+ 	ctl_base = ports->ctl;
+@@ -583,7 +621,10 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
+ 	out_be32((void*)mode_port, MODE_JCUSFEN);
+ 	out_be32((void*)intmask_port, INTMASK_MSK);
+ 
+-	return ide_setup_pci_device(dev, d);
++	rc = scc_ide_setup_pci_device(dev, d);
++
++ end:
++	return rc;
+ }
+ 
+ /**
+@@ -610,17 +651,6 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
+ 	hwif->OUTSW = scc_ide_outsw;
+ 	hwif->OUTSL = scc_ide_outsl;
+ 
+-	hwif->io_ports[IDE_DATA_OFFSET] = dma_base + 0x20;
+-	hwif->io_ports[IDE_ERROR_OFFSET] = dma_base + 0x24;
+-	hwif->io_ports[IDE_NSECTOR_OFFSET] = dma_base + 0x28;
+-	hwif->io_ports[IDE_SECTOR_OFFSET] = dma_base + 0x2c;
+-	hwif->io_ports[IDE_LCYL_OFFSET] = dma_base + 0x30;
+-	hwif->io_ports[IDE_HCYL_OFFSET] = dma_base + 0x34;
+-	hwif->io_ports[IDE_SELECT_OFFSET] = dma_base + 0x38;
+-	hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
+-	hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
+-
+-	hwif->irq = dev->irq;
+ 	hwif->dma_base = dma_base;
+ 	hwif->config_data = ports->ctl;
+ 	hwif->mmio = 1;
+@@ -662,7 +692,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+ {
+ 	struct scc_ports *ports = ide_get_hwifdata(hwif);
+ 
+-	ports->hwif_id = hwif->index;
++	ports->hwif = hwif;
+ 
+ 	hwif->dma_command = hwif->dma_base;
+ 	hwif->dma_status = hwif->dma_base + 0x04;
+@@ -691,8 +721,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+       .name		= name_str,			\
+       .init_iops	= init_iops_scc,		\
+       .init_hwif	= init_hwif_scc,		\
+-      .host_flags	= IDE_HFLAG_SINGLE |		\
+-			  IDE_HFLAG_BOOTABLE,		\
++      .host_flags	= IDE_HFLAG_SINGLE,		\
+       .pio_mask		= ATA_PIO4,			\
+   }
+ 
+@@ -724,7 +753,7 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i
+ static void __devexit scc_remove(struct pci_dev *dev)
+ {
+ 	struct scc_ports *ports = pci_get_drvdata(dev);
+-	ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id];
++	ide_hwif_t *hwif = ports->hwif;
+ 	unsigned long ctl_base = pci_resource_start(dev, 0);
+ 	unsigned long dma_base = pci_resource_start(dev, 1);
+ 	unsigned long ctl_size = pci_resource_len(dev, 0);
+@@ -736,7 +765,7 @@ static void __devexit scc_remove(struct pci_dev *dev)
+ 		hwif->dmatable_cpu = NULL;
+ 	}
+ 
+-	ide_unregister(hwif->index, 0, 0);
++	ide_unregister(hwif->index);
+ 
+ 	hwif->chipset = ide_unknown;
+ 	iounmap((void*)ports->dma);
+diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
+index c11880b..cfe9274 100644
+--- a/drivers/ide/pci/serverworks.c
++++ b/drivers/ide/pci/serverworks.c
+@@ -350,8 +350,7 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
+ 
+ #define IDE_HFLAGS_SVWKS \
+ 	(IDE_HFLAG_LEGACY_IRQS | \
+-	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+-	 IDE_HFLAG_BOOTABLE)
++	 IDE_HFLAG_ABUSE_SET_DMA_MODE)
+ 
+ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ 	{	/* 0 */
+@@ -418,7 +417,7 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
+ 	else if (idx == 2 || idx == 3) {
+ 		if ((PCI_FUNC(dev->devfn) & 1) == 0) {
+ 			if (pci_resource_start(dev, 0) != 0x01f1)
+-				d.host_flags &= ~IDE_HFLAG_BOOTABLE;
++				d.host_flags |= IDE_HFLAG_NON_BOOTABLE;
+ 			d.host_flags |= IDE_HFLAG_SINGLE;
+ 		} else
+ 			d.host_flags &= ~IDE_HFLAG_SINGLE;
+diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
+index 0546264..6bd9523 100644
+--- a/drivers/ide/pci/sgiioc4.c
++++ b/drivers/ide/pci/sgiioc4.c
+@@ -112,10 +112,9 @@ static void
+ sgiioc4_maskproc(ide_drive_t * drive, int mask)
+ {
+ 	writeb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+-	       (void __iomem *)IDE_CONTROL_REG);
++	       (void __iomem *)drive->hwif->io_ports[IDE_CONTROL_OFFSET]);
+ }
+ 
+-
+ static int
+ sgiioc4_checkirq(ide_hwif_t * hwif)
+ {
+@@ -142,18 +141,18 @@ sgiioc4_clearirq(ide_drive_t * drive)
+ 	intr_reg = readl((void __iomem *)other_ir);
+ 	if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
+ 		/*
+-		 * Using sgiioc4_INB to read the IDE_STATUS_REG has a side effect
+-		 * of clearing the interrupt.  The first read should clear it
+-		 * if it is set.  The second read should return a "clear" status
+-		 * if it got cleared.  If not, then spin for a bit trying to
+-		 * clear it.
++		 * Using sgiioc4_INB to read the Status register has a side
++		 * effect of clearing the interrupt.  The first read should
++		 * clear it if it is set.  The second read should return
++		 * a "clear" status if it got cleared.  If not, then spin
++		 * for a bit trying to clear it.
+ 		 */
+-		u8 stat = sgiioc4_INB(IDE_STATUS_REG);
++		u8 stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+ 		int count = 0;
+-		stat = sgiioc4_INB(IDE_STATUS_REG);
++		stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+ 		while ((stat & 0x80) && (count++ < 100)) {
+ 			udelay(1);
+-			stat = sgiioc4_INB(IDE_STATUS_REG);
++			stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+ 		}
+ 
+ 		if (intr_reg & 0x02) {
+@@ -562,7 +561,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
+ 						clear interrupts */
+ 	hwif->maskproc = &sgiioc4_maskproc;	/* Mask on/off NIEN register */
+ 	hwif->quirkproc = NULL;
+-	hwif->busproc = NULL;
+ 
+ 	hwif->INB = &sgiioc4_INB;
+ 
+@@ -592,20 +590,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+ 	unsigned long bar0, cmd_phys_base, ctl;
+ 	void __iomem *virt_base;
+ 	ide_hwif_t *hwif;
+-	int h;
+ 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 	hw_regs_t hw;
+ 	struct ide_port_info d = sgiioc4_port_info;
+ 
+-	/*
+-	 * Find an empty HWIF; if none available, return -ENOMEM.
+-	 */
+-	for (h = 0; h < MAX_HWIFS; ++h) {
+-		hwif = &ide_hwifs[h];
+-		if (hwif->chipset == ide_unknown)
+-			break;
+-	}
+-	if (h == MAX_HWIFS) {
++	hwif = ide_find_port();
++	if (hwif == NULL) {
+ 		printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n",
+ 				DRV_NAME);
+ 		return -ENOMEM;
+diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
+index 8d624af..c9ecab8 100644
+--- a/drivers/ide/pci/siimage.c
++++ b/drivers/ide/pci/siimage.c
+@@ -370,48 +370,6 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
+ }
+ 
+ /**
+- *	sil_sata_busproc	-	bus isolation IOCTL
+- *	@drive: drive to isolate/restore
+- *	@state: bus state to set
+- *
+- *	Used by the SII3112 to handle bus isolation. As this is a 
+- *	SATA controller the work required is quite limited, we 
+- *	just have to clean up the statistics
+- */
+-
+-static int sil_sata_busproc(ide_drive_t * drive, int state)
+-{
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+-	u32 stat_config		= 0;
+-	unsigned long addr	= siimage_selreg(hwif, 0);
+-
+-	if (hwif->mmio)
+-		stat_config = readl((void __iomem *)addr);
+-	else
+-		pci_read_config_dword(dev, addr, &stat_config);
+-
+-	switch (state) {
+-		case BUSSTATE_ON:
+-			hwif->drives[0].failures = 0;
+-			hwif->drives[1].failures = 0;
+-			break;
+-		case BUSSTATE_OFF:
+-			hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+-			hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+-			break;
+-		case BUSSTATE_TRISTATE:
+-			hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+-			hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+-			break;
+-		default:
+-			return -EINVAL;
+-	}
+-	hwif->bus_state = state;
+-	return 0;
+-}
+-
+-/**
+  *	sil_sata_reset_poll	-	wait for SATA reset
+  *	@drive: drive we are resetting
+  *
+@@ -818,7 +776,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
+ 	if (sata) {
+ 		static int first = 1;
+ 
+-		hwif->busproc = &sil_sata_busproc;
+ 		hwif->reset_poll = &sil_sata_reset_poll;
+ 		hwif->pre_reset = &sil_sata_pre_reset;
+ 		hwif->udma_filter = &sil_sata_udma_filter;
+@@ -851,7 +808,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
+ 		.init_chipset	= init_chipset_siimage,	\
+ 		.init_iops	= init_iops_siimage,	\
+ 		.init_hwif	= init_hwif_siimage,	\
+-		.host_flags	= IDE_HFLAG_BOOTABLE,	\
+ 		.pio_mask	= ATA_PIO4,		\
+ 		.mwdma_mask	= ATA_MWDMA2,		\
+ 		.udma_mask	= ATA_UDMA6,		\
+diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
+index 512bb4c..181b647 100644
+--- a/drivers/ide/pci/sis5513.c
++++ b/drivers/ide/pci/sis5513.c
+@@ -59,10 +59,10 @@
+ #define ATA_16		0x01
+ #define ATA_33		0x02
+ #define ATA_66		0x03
+-#define ATA_100a	0x04 // SiS730/SiS550 is ATA100 with ATA66 layout
++#define ATA_100a	0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */
+ #define ATA_100		0x05
+-#define ATA_133a	0x06 // SiS961b with 133 support
+-#define ATA_133		0x07 // SiS962/963
++#define ATA_133a	0x06 /* SiS961b with 133 support */
++#define ATA_133		0x07 /* SiS962/963 */
+ 
+ static u8 chipset_family;
+ 
+@@ -111,69 +111,70 @@ static const struct {
+    Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
+ 
+ /* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
+-static u8 cycle_time_offset[] = {0,0,5,4,4,0,0};
+-static u8 cycle_time_range[] = {0,0,2,3,3,4,4};
++static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 };
++static u8 cycle_time_range[]  = { 0, 0, 2, 3, 3, 4, 4 };
+ static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
+-	{0,0,0,0,0,0,0}, /* no udma */
+-	{0,0,0,0,0,0,0}, /* no udma */
+-	{3,2,1,0,0,0,0}, /* ATA_33 */
+-	{7,5,3,2,1,0,0}, /* ATA_66 */
+-	{7,5,3,2,1,0,0}, /* ATA_100a (730 specific), differences are on cycle_time range and offset */
+-	{11,7,5,4,2,1,0}, /* ATA_100 */
+-	{15,10,7,5,3,2,1}, /* ATA_133a (earliest 691 southbridges) */
+-	{15,10,7,5,3,2,1}, /* ATA_133 */
++	{  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
++	{  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
++	{  3,  2, 1, 0, 0, 0, 0 }, /* ATA_33 */
++	{  7,  5, 3, 2, 1, 0, 0 }, /* ATA_66 */
++	{  7,  5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific),
++				      different cycle_time range and offset */
++	{ 11,  7, 5, 4, 2, 1, 0 }, /* ATA_100 */
++	{ 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */
++	{ 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */
+ };
+ /* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133
+    See SiS962 data sheet for more detail */
+ static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
+-	{0,0,0,0,0,0,0}, /* no udma */
+-	{0,0,0,0,0,0,0}, /* no udma */
+-	{2,1,1,0,0,0,0},
+-	{4,3,2,1,0,0,0},
+-	{4,3,2,1,0,0,0},
+-	{6,4,3,1,1,1,0},
+-	{9,6,4,2,2,2,2},
+-	{9,6,4,2,2,2,2},
++	{ 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
++	{ 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
++	{ 2, 1, 1, 0, 0, 0, 0 },
++	{ 4, 3, 2, 1, 0, 0, 0 },
++	{ 4, 3, 2, 1, 0, 0, 0 },
++	{ 6, 4, 3, 1, 1, 1, 0 },
++	{ 9, 6, 4, 2, 2, 2, 2 },
++	{ 9, 6, 4, 2, 2, 2, 2 },
+ };
+ /* Initialize time, Active time, Recovery time vary across
+    IDE clock settings. These 3 arrays hold the register value
+    for PIO0/1/2/3/4 and DMA0/1/2 mode in order */
+ static u8 ini_time_value[][8] = {
+-	{0,0,0,0,0,0,0,0},
+-	{0,0,0,0,0,0,0,0},
+-	{2,1,0,0,0,1,0,0},
+-	{4,3,1,1,1,3,1,1},
+-	{4,3,1,1,1,3,1,1},
+-	{6,4,2,2,2,4,2,2},
+-	{9,6,3,3,3,6,3,3},
+-	{9,6,3,3,3,6,3,3},
++	{ 0, 0, 0, 0, 0, 0, 0, 0 },
++	{ 0, 0, 0, 0, 0, 0, 0, 0 },
++	{ 2, 1, 0, 0, 0, 1, 0, 0 },
++	{ 4, 3, 1, 1, 1, 3, 1, 1 },
++	{ 4, 3, 1, 1, 1, 3, 1, 1 },
++	{ 6, 4, 2, 2, 2, 4, 2, 2 },
++	{ 9, 6, 3, 3, 3, 6, 3, 3 },
++	{ 9, 6, 3, 3, 3, 6, 3, 3 },
+ };
+ static u8 act_time_value[][8] = {
+-	{0,0,0,0,0,0,0,0},
+-	{0,0,0,0,0,0,0,0},
+-	{9,9,9,2,2,7,2,2},
+-	{19,19,19,5,4,14,5,4},
+-	{19,19,19,5,4,14,5,4},
+-	{28,28,28,7,6,21,7,6},
+-	{38,38,38,10,9,28,10,9},
+-	{38,38,38,10,9,28,10,9},
++	{  0,  0,  0,  0, 0,  0,  0, 0 },
++	{  0,  0,  0,  0, 0,  0,  0, 0 },
++	{  9,  9,  9,  2, 2,  7,  2, 2 },
++	{ 19, 19, 19,  5, 4, 14,  5, 4 },
++	{ 19, 19, 19,  5, 4, 14,  5, 4 },
++	{ 28, 28, 28,  7, 6, 21,  7, 6 },
++	{ 38, 38, 38, 10, 9, 28, 10, 9 },
++	{ 38, 38, 38, 10, 9, 28, 10, 9 },
+ };
+ static u8 rco_time_value[][8] = {
+-	{0,0,0,0,0,0,0,0},
+-	{0,0,0,0,0,0,0,0},
+-	{9,2,0,2,0,7,1,1},
+-	{19,5,1,5,2,16,3,2},
+-	{19,5,1,5,2,16,3,2},
+-	{30,9,3,9,4,25,6,4},
+-	{40,12,4,12,5,34,12,5},
+-	{40,12,4,12,5,34,12,5},
++	{  0,  0, 0,  0, 0,  0,  0, 0 },
++	{  0,  0, 0,  0, 0,  0,  0, 0 },
++	{  9,  2, 0,  2, 0,  7,  1, 1 },
++	{ 19,  5, 1,  5, 2, 16,  3, 2 },
++	{ 19,  5, 1,  5, 2, 16,  3, 2 },
++	{ 30,  9, 3,  9, 4, 25,  6, 4 },
++	{ 40, 12, 4, 12, 5, 34, 12, 5 },
++	{ 40, 12, 4, 12, 5, 34, 12, 5 },
+ };
+ 
+ /*
+  * Printing configuration
+  */
+ /* Used for chipset type printing at boot time */
+-static char* chipset_capability[] = {
++static char *chipset_capability[] = {
+ 	"ATA", "ATA 16",
+ 	"ATA 33", "ATA 66",
+ 	"ATA 100 (1st gen)", "ATA 100 (2nd gen)",
+@@ -272,7 +273,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode)
+ 		sis_ata133_program_timings(drive, mode);
+ }
+ 
+-static void config_drive_art_rwp (ide_drive_t *drive)
++static void config_drive_art_rwp(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+ 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+@@ -358,8 +359,7 @@ static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
+ 	return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
+ }
+ 
+-/* Chip detection and general config */
+-static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name)
++static int __devinit sis_find_family(struct pci_dev *dev)
+ {
+ 	struct pci_dev *host;
+ 	int i = 0;
+@@ -381,7 +381,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
+ 				chipset_family = ATA_100a;
+ 		}
+ 		pci_dev_put(host);
+-	
++
+ 		printk(KERN_INFO "SIS5513: %s %s controller\n",
+ 			 SiSHostChipInfo[i].name, chipset_capability[chipset_family]);
+ 	}
+@@ -440,63 +440,60 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
+ 			}
+ 	}
+ 
+-	if (!chipset_family)
+-		return -1;
++	return chipset_family;
++}
+ 
++static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev,
++						   const char *name)
++{
+ 	/* Make general config ops here
+ 	   1/ tell IDE channels to operate in Compatibility mode only
+ 	   2/ tell old chips to allow per drive IDE timings */
+ 
+-	{
+-		u8 reg;
+-		u16 regw;
+-
+-		switch(chipset_family) {
+-			case ATA_133:
+-				/* SiS962 operation mode */
+-				pci_read_config_word(dev, 0x50, &regw);
+-				if (regw & 0x08)
+-					pci_write_config_word(dev, 0x50, regw&0xfff7);
+-				pci_read_config_word(dev, 0x52, &regw);
+-				if (regw & 0x08)
+-					pci_write_config_word(dev, 0x52, regw&0xfff7);
+-				break;
+-			case ATA_133a:
+-			case ATA_100:
+-				/* Fixup latency */
+-				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+-				/* Set compatibility bit */
+-				pci_read_config_byte(dev, 0x49, &reg);
+-				if (!(reg & 0x01)) {
+-					pci_write_config_byte(dev, 0x49, reg|0x01);
+-				}
+-				break;
+-			case ATA_100a:
+-			case ATA_66:
+-				/* Fixup latency */
+-				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
+-
+-				/* On ATA_66 chips the bit was elsewhere */
+-				pci_read_config_byte(dev, 0x52, &reg);
+-				if (!(reg & 0x04)) {
+-					pci_write_config_byte(dev, 0x52, reg|0x04);
+-				}
+-				break;
+-			case ATA_33:
+-				/* On ATA_33 we didn't have a single bit to set */
+-				pci_read_config_byte(dev, 0x09, &reg);
+-				if ((reg & 0x0f) != 0x00) {
+-					pci_write_config_byte(dev, 0x09, reg&0xf0);
+-				}
+-			case ATA_16:
+-				/* force per drive recovery and active timings
+-				   needed on ATA_33 and below chips */
+-				pci_read_config_byte(dev, 0x52, &reg);
+-				if (!(reg & 0x08)) {
+-					pci_write_config_byte(dev, 0x52, reg|0x08);
+-				}
+-				break;
+-		}
++	u8 reg;
++	u16 regw;
++
++	switch (chipset_family) {
++	case ATA_133:
++		/* SiS962 operation mode */
++		pci_read_config_word(dev, 0x50, &regw);
++		if (regw & 0x08)
++			pci_write_config_word(dev, 0x50, regw&0xfff7);
++		pci_read_config_word(dev, 0x52, &regw);
++		if (regw & 0x08)
++			pci_write_config_word(dev, 0x52, regw&0xfff7);
++		break;
++	case ATA_133a:
++	case ATA_100:
++		/* Fixup latency */
++		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
++		/* Set compatibility bit */
++		pci_read_config_byte(dev, 0x49, &reg);
++		if (!(reg & 0x01))
++			pci_write_config_byte(dev, 0x49, reg|0x01);
++		break;
++	case ATA_100a:
++	case ATA_66:
++		/* Fixup latency */
++		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
++
++		/* On ATA_66 chips the bit was elsewhere */
++		pci_read_config_byte(dev, 0x52, &reg);
++		if (!(reg & 0x04))
++			pci_write_config_byte(dev, 0x52, reg|0x04);
++		break;
++	case ATA_33:
++		/* On ATA_33 we didn't have a single bit to set */
++		pci_read_config_byte(dev, 0x09, &reg);
++		if ((reg & 0x0f) != 0x00)
++			pci_write_config_byte(dev, 0x09, reg&0xf0);
++	case ATA_16:
++		/* force per drive recovery and active timings
++		   needed on ATA_33 and below chips */
++		pci_read_config_byte(dev, 0x52, &reg);
++		if (!(reg & 0x08))
++			pci_write_config_byte(dev, 0x52, reg|0x08);
++		break;
+ 	}
+ 
+ 	return 0;
+@@ -546,10 +543,8 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
+ 	return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ }
+ 
+-static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
++static void __devinit init_hwif_sis5513(ide_hwif_t *hwif)
+ {
+-	u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
+-
+ 	hwif->set_pio_mode = &sis_set_pio_mode;
+ 	hwif->set_dma_mode = &sis_set_dma_mode;
+ 
+@@ -557,27 +552,29 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
+ 		hwif->udma_filter = sis5513_ata133_udma_filter;
+ 
+ 	hwif->cable_detect = ata66_sis5513;
+-
+-	if (hwif->dma_base == 0)
+-		return;
+-
+-	hwif->ultra_mask = udma_rates[chipset_family];
+ }
+ 
+ static const struct ide_port_info sis5513_chipset __devinitdata = {
+ 	.name		= "SIS5513",
+ 	.init_chipset	= init_chipset_sis5513,
+ 	.init_hwif	= init_hwif_sis5513,
+-	.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+-	.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA |
+-			  IDE_HFLAG_BOOTABLE,
++	.enablebits	= { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
++	.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
+ 	.pio_mask	= ATA_PIO4,
+ 	.mwdma_mask	= ATA_MWDMA2,
+ };
+ 
+ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+-	return ide_setup_pci_device(dev, &sis5513_chipset);
++	struct ide_port_info d = sis5513_chipset;
++	u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
++
++	if (sis_find_family(dev) == 0)
++		return -ENOTSUPP;
++
++	d.udma_mask = udma_rates[chipset_family];
++
++	return ide_setup_pci_device(dev, &d);
+ }
+ 
+ static const struct pci_device_id sis5513_pci_tbl[] = {
+diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
+index ee261ae..40b3eeb 100644
+--- a/drivers/ide/pci/sl82c105.c
++++ b/drivers/ide/pci/sl82c105.c
+@@ -328,8 +328,11 @@ static const struct ide_port_info sl82c105_chipset __devinitdata = {
+ 	.enablebits	= {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
+ 	.host_flags	= IDE_HFLAG_IO_32BIT |
+ 			  IDE_HFLAG_UNMASK_IRQS |
+-			  IDE_HFLAG_NO_AUTODMA |
+-			  IDE_HFLAG_BOOTABLE,
++/* FIXME: check for Compatibility mode in generic IDE PCI code */
++#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT)
++			  IDE_HFLAG_FORCE_LEGACY_IRQS |
++#endif
++			  IDE_HFLAG_NO_AUTODMA,
+ 	.pio_mask	= ATA_PIO5,
+ };
+ 
+diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
+index 65f4c2f..eab557c 100644
+--- a/drivers/ide/pci/slc90e66.c
++++ b/drivers/ide/pci/slc90e66.c
+@@ -27,9 +27,9 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	unsigned long flags;
+ 	u16 master_data;
+ 	u8 slave_data;
+- 	int control = 0;
++	int control = 0;
+ 				     /* ISP  RTC */
+-	static const u8 timings[][2]= {
++	static const u8 timings[][2] = {
+ 					{ 0, 0 },
+ 					{ 0, 0 },
+ 					{ 1, 0 },
+@@ -136,8 +136,8 @@ static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif)
+ static const struct ide_port_info slc90e66_chipset __devinitdata = {
+ 	.name		= "SLC90E66",
+ 	.init_hwif	= init_hwif_slc90e66,
+-	.enablebits	= {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+-	.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
++	.enablebits	= { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
++	.host_flags	= IDE_HFLAG_LEGACY_IRQS,
+ 	.pio_mask	= ATA_PIO4,
+ 	.swdma_mask	= ATA_SWDMA2_ONLY,
+ 	.mwdma_mask	= ATA_MWDMA12_ONLY,
+diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
+index 2ef2ed2..c154351 100644
+--- a/drivers/ide/pci/tc86c001.c
++++ b/drivers/ide/pci/tc86c001.c
+@@ -18,20 +18,20 @@ static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
+ 	u16 mode, scr		= inw(scr_port);
+ 
+ 	switch (speed) {
+-		case XFER_UDMA_4:	mode = 0x00c0; break;
+-		case XFER_UDMA_3:	mode = 0x00b0; break;
+-		case XFER_UDMA_2:	mode = 0x00a0; break;
+-		case XFER_UDMA_1:	mode = 0x0090; break;
+-		case XFER_UDMA_0:	mode = 0x0080; break;
+-		case XFER_MW_DMA_2:	mode = 0x0070; break;
+-		case XFER_MW_DMA_1:	mode = 0x0060; break;
+-		case XFER_MW_DMA_0:	mode = 0x0050; break;
+-		case XFER_PIO_4:	mode = 0x0400; break;
+-		case XFER_PIO_3:	mode = 0x0300; break;
+-		case XFER_PIO_2:	mode = 0x0200; break;
+-		case XFER_PIO_1:	mode = 0x0100; break;
+-		case XFER_PIO_0:
+-		default:		mode = 0x0000; break;
++	case XFER_UDMA_4:	mode = 0x00c0; break;
++	case XFER_UDMA_3:	mode = 0x00b0; break;
++	case XFER_UDMA_2:	mode = 0x00a0; break;
++	case XFER_UDMA_1:	mode = 0x0090; break;
++	case XFER_UDMA_0:	mode = 0x0080; break;
++	case XFER_MW_DMA_2:	mode = 0x0070; break;
++	case XFER_MW_DMA_1:	mode = 0x0060; break;
++	case XFER_MW_DMA_0:	mode = 0x0050; break;
++	case XFER_PIO_4:	mode = 0x0400; break;
++	case XFER_PIO_3:	mode = 0x0300; break;
++	case XFER_PIO_2:	mode = 0x0200; break;
++	case XFER_PIO_1:	mode = 0x0100; break;
++	case XFER_PIO_0:
++	default:		mode = 0x0000; break;
+ 	}
+ 
+ 	scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
+@@ -126,40 +126,6 @@ static void tc86c001_dma_start(ide_drive_t *drive)
+ 	ide_dma_start(drive);
+ }
+ 
+-static int tc86c001_busproc(ide_drive_t *drive, int state)
+-{
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	unsigned long sc_base	= hwif->config_data;
+-	u16 scr1;
+-
+-	/* System Control 1 Register bit 11 (ATA Hard Reset) read */
+-	scr1 = inw(sc_base + 0x00);
+-
+-	switch (state) {
+-		case BUSSTATE_ON:
+-			if (!(scr1 & 0x0800))
+-				return 0;
+-			scr1 &= ~0x0800;
+-
+-			hwif->drives[0].failures = hwif->drives[1].failures = 0;
+-			break;
+-		case BUSSTATE_OFF:
+-			if (scr1 & 0x0800)
+-				return 0;
+-			scr1 |= 0x0800;
+-
+-			hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+-			hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+-			break;
+-		default:
+-			return -EINVAL;
+-	}
+-
+-	/* System Control 1 Register bit 11 (ATA Hard Reset) write */
+-	outw(scr1, sc_base + 0x00);
+-	return 0;
+-}
+-
+ static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif)
+ {
+ 	struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -194,8 +160,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
+ 	hwif->set_pio_mode = &tc86c001_set_pio_mode;
+ 	hwif->set_dma_mode = &tc86c001_set_mode;
+ 
+-	hwif->busproc	= &tc86c001_busproc;
+-
+ 	hwif->cable_detect = tc86c001_cable_detect;
+ 
+ 	if (!hwif->dma_base)
+diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
+index a67d02a..3316b19 100644
+--- a/drivers/ide/pci/triflex.c
++++ b/drivers/ide/pci/triflex.c
+@@ -97,7 +97,6 @@ static const struct ide_port_info triflex_device __devinitdata = {
+ 	.name		= "TRIFLEX",
+ 	.init_hwif	= init_hwif_triflex,
+ 	.enablebits	= {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
+-	.host_flags	= IDE_HFLAG_BOOTABLE,
+ 	.pio_mask	= ATA_PIO4,
+ 	.swdma_mask	= ATA_SWDMA2,
+ 	.mwdma_mask	= ATA_MWDMA2,
+diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
+index de750f7..2b8f3a2 100644
+--- a/drivers/ide/pci/trm290.c
++++ b/drivers/ide/pci/trm290.c
+@@ -337,7 +337,6 @@ static const struct ide_port_info trm290_chipset __devinitdata = {
+ 			  IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ #endif
+ 			  IDE_HFLAG_NO_AUTODMA |
+-			  IDE_HFLAG_BOOTABLE |
+ 			  IDE_HFLAG_NO_LBA48,
+ };
+ 
+diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
+index 9004e75..cff3caf 100644
+--- a/drivers/ide/pci/via82cxxx.c
++++ b/drivers/ide/pci/via82cxxx.c
+@@ -429,11 +429,9 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
+ 	.init_hwif	= init_hwif_via82cxxx,
+ 	.enablebits	= { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
+ 	.host_flags	= IDE_HFLAG_PIO_NO_BLACKLIST |
+-			  IDE_HFLAG_PIO_NO_DOWNGRADE |
+ 			  IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ 			  IDE_HFLAG_POST_SET_MODE |
+-			  IDE_HFLAG_IO_32BIT |
+-			  IDE_HFLAG_BOOTABLE,
++			  IDE_HFLAG_IO_32BIT,
+ 	.pio_mask	= ATA_PIO5,
+ 	.swdma_mask	= ATA_SWDMA2,
+ 	.mwdma_mask	= ATA_MWDMA2,
+diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
+index ebaba01..467656f 100644
+--- a/drivers/ide/ppc/mpc8xx.c
++++ b/drivers/ide/ppc/mpc8xx.c
+@@ -36,6 +36,8 @@
+ #include <asm/machdep.h>
+ #include <asm/irq.h>
+ 
++#define DRV_NAME "ide-mpc8xx"
++
+ static int identify  (volatile u8 *p);
+ static void print_fixed (volatile u8 *p);
+ static void print_funcid (int func);
+@@ -99,32 +101,6 @@ static int _slot_ = -1;			/* will be read from PCMCIA registers   */
+ /* Make clock cycles and always round up */
+ #define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U )
+ 
+-
+-
+-/*
+- * IDE stuff.
+- */
+-static int
+-m8xx_ide_default_irq(unsigned long base)
+-{
+-#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+-	if (base >= MAX_HWIFS)
+-		return 0;
+-
+-	printk("[%d] m8xx_ide_default_irq %d\n",__LINE__,ioport_dsc[base].irq);
+-	
+-	return (ioport_dsc[base].irq);
+-#else
+-        return 9;
+-#endif
+-}
+-
+-static unsigned long
+-m8xx_ide_default_io_base(int index)
+-{
+-        return index;
+-}
+-
+ #define M8XX_PCMCIA_CD2(slot)      (0x10000000 >> (slot << 4))
+ #define M8XX_PCMCIA_CD1(slot)      (0x08000000 >> (slot << 4))
+ 
+@@ -149,12 +125,11 @@ static int pcmcia_schlvl = PCMCIA_SCHLVL;
+  */
+ 
+ /*
+- * m8xx_ide_init_hwif_ports for a direct IDE interface _using_
++ * m8xx_ide_init_ports() for a direct IDE interface _using_
++ * MPC8xx's internal PCMCIA interface
+  */
+ #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
+-static void
+-m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, 
+-		unsigned long ctrl_port, int *irq)
++static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
+ {
+ 	unsigned long *p = hw->io_ports;
+ 	int i;
+@@ -173,8 +148,6 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ 	unsigned long base;
+ 
+ 	*p = 0;
+-	if (irq)
+-		*irq = 0;
+ 
+ 	pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
+ 
+@@ -211,6 +184,13 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ 			pcmcia_phy_base, pcmcia_phy_end,
+ 			pcmcia_phy_end - pcmcia_phy_base);
+ 
++		if (!request_mem_region(pcmcia_phy_base,
++					pcmcia_phy_end - pcmcia_phy_base,
++					DRV_NAME)) {
++			printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
++			return -EBUSY;
++		}
++
+ 		pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base,
+ 						   pcmcia_phy_end-pcmcia_phy_base);
+ 
+@@ -248,9 +228,6 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ 		}
+ 	}
+ 
+-	if (data_port >= MAX_HWIFS)
+-		return;
+-
+ 	if (_slot_ == -1) {
+ 		printk ("PCMCIA slot has not been defined! Using A as default\n");
+ 		_slot_ = 0;
+@@ -268,7 +245,7 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ 	if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) {
+ 		printk ("No card in slot %c: PIPR=%08x\n",
+ 			'A' + _slot_, (u32) pcmp->pcmc_pipr);
+-		return;		/* No card in slot */
++		return -ENODEV;		/* No card in slot */
+ 	}
+ 
+ 	check_ide_device (pcmcia_base);
+@@ -292,11 +269,13 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ 	 	*p++ = base + ioport_dsc[data_port].reg_off[i];
+ 	}
+ 
+-	if (irq) {
++	hw->irq = ioport_dsc[data_port].irq;
++	hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
++
+ #ifdef CONFIG_IDE_8xx_PCCARD
++	{
+ 		unsigned int reg;
+ 
+-		*irq = ioport_dsc[data_port].irq;
+ 		if (_slot_)
+ 			pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb;
+ 		else
+@@ -306,14 +285,8 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ 		reg |= mk_int_int_mask (pcmcia_schlvl) << 24;
+ 		reg |= mk_int_int_mask (pcmcia_schlvl) << 16;
+ 		*pgcrx = reg;
+-#else	/* direct connected IDE drive, i.e. external IRQ, not the PCMCIA irq */
+-		*irq = ioport_dsc[data_port].irq;
+-#endif	/* CONFIG_IDE_8xx_PCCARD */
+ 	}
+-
+-	ide_hwifs[data_port].pio_mask = ATA_PIO4;
+-	ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
+-	ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
++#endif	/* CONFIG_IDE_8xx_PCCARD */
+ 
+ 	/* Enable Harddisk Interrupt,
+ 	 * and make it edge sensitive
+@@ -329,16 +302,17 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ 	/* Enable falling edge irq */
+ 	pcmp->pcmc_per = 0x100000 >> (16 * _slot_);
+ #endif	/* CONFIG_IDE_8xx_PCCARD */
+-}	/* m8xx_ide_init_hwif_ports() using 8xx internal PCMCIA interface */
++
++	return 0;
++}
+ #endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */
+ 
+ /*
+- * m8xx_ide_init_hwif_ports for a direct IDE interface _not_ using
++ * m8xx_ide_init_ports() for a direct IDE interface _not_ using
+  * MPC8xx's internal PCMCIA interface
+  */
+ #if defined(CONFIG_IDE_EXT_DIRECT)
+-void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+-	unsigned long data_port, unsigned long ctrl_port, int *irq)
++static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
+ {
+ 	unsigned long *p = hw->io_ports;
+ 	int i;
+@@ -349,8 +323,6 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ 	unsigned long base;
+ 
+ 	*p = 0;
+-	if (irq)
+-		*irq = 0;
+ 
+ 	if (!ide_base) {
+ 
+@@ -363,7 +335,12 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ 		printk ("IDE phys mem : %08x...%08x (size %08x)\n",
+ 			ide_phy_base, ide_phy_end,
+ 			ide_phy_end - ide_phy_base);
+-		
++
++		if (!request_mem_region(ide_phy_base, 0x200, DRV_NAME)) {
++			printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
++			return -EBUSY;
++		}
++
+ 		ide_base=(unsigned long)ioremap(ide_phy_base,
+ 						ide_phy_end-ide_phy_base);
+ 
+@@ -372,9 +349,6 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ #endif
+ 	}
+ 
+-	if (data_port >= MAX_HWIFS)
+-		return;
+-
+ 	base = ide_base + ioport_dsc[data_port].base_off;
+ #ifdef DEBUG
+ 	printk ("base: %08x + %08x = %08x\n",
+@@ -392,14 +366,9 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ 	 	*p++ = base + ioport_dsc[data_port].reg_off[i];
+ 	}
+ 
+-	if (irq) {
+-		/* direct connected IDE drive, i.e. external IRQ */
+-		*irq = ioport_dsc[data_port].irq;
+-	}
+-
+-	ide_hwifs[data_port].pio_mask = ATA_PIO4;
+-	ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
+-	ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
++	/* direct connected IDE drive, i.e. external IRQ */
++	hw->irq = ioport_dsc[data_port].irq;
++	hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
+ 
+ 	/* Enable Harddisk Interrupt,
+ 	 * and make it edge sensitive
+@@ -407,8 +376,9 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ 	/* (11-18) Set edge detect for irq, no wakeup from low power mode */
+ 	((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
+ 			(0x80000000 >> ioport_dsc[data_port].irq);
+-}	/* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */ 
+ 
++	return 0;
++}
+ #endif	/* CONFIG_IDE_8xx_DIRECT */
+ 
+ 
+@@ -829,21 +799,35 @@ static int identify  (volatile u8 *p)
+ 	return (0);	/* don't know */
+ }
+ 
+-void m8xx_ide_init(void)
+-{
+-	ppc_ide_md.default_irq          = m8xx_ide_default_irq;
+-	ppc_ide_md.default_io_base      = m8xx_ide_default_io_base;
+-	ppc_ide_md.ide_init_hwif        = m8xx_ide_init_hwif_ports;
+-}
+-
+ static int __init mpc8xx_ide_probe(void)
+ {
++	hw_regs_t hw;
+ 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 
+ #ifdef IDE0_BASE_OFFSET
+-	idx[0] = 0;
++	memset(&hw, 0, sizeof(hw));
++	if (!m8xx_ide_init_ports(&hw, 0)) {
++		ide_hwif_t *hwif = &ide_hwifs[0];
++
++		ide_init_port_hw(hwif, &hw);
++		hwif->mmio = 1;
++		hwif->pio_mask = ATA_PIO4;
++		hwif->set_pio_mode = m8xx_ide_set_pio_mode;
++
++		idx[0] = 0;
++	}
+ #ifdef IDE1_BASE_OFFSET
+-	idx[1] = 1;
++	memset(&hw, 0, sizeof(hw));
++	if (!m8xx_ide_init_ports(&hw, 1)) {
++		ide_hwif_t *mate = &ide_hwifs[1];
++
++		ide_init_port_hw(mate, &hw);
++		mate->mmio = 1;
++		mate->pio_mask = ATA_PIO4;
++		mate->set_pio_mode = m8xx_ide_set_pio_mode;
++
++		idx[1] = 1;
++	}
+ #endif
+ #endif
+ 
+diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
+index d9ca52e..177961e 100644
+--- a/drivers/ide/ppc/pmac.c
++++ b/drivers/ide/ppc/pmac.c
+@@ -79,9 +79,6 @@ typedef struct pmac_ide_hwif {
+ 	
+ } pmac_ide_hwif_t;
+ 
+-static pmac_ide_hwif_t pmac_ide[MAX_HWIFS];
+-static int pmac_ide_count;
+-
+ enum {
+ 	controller_ohare,	/* OHare based */
+ 	controller_heathrow,	/* Heathrow/Paddington */
+@@ -419,38 +416,8 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
+ 
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+ 
+-/*
+- * N.B. this can't be an initfunc, because the media-bay task can
+- * call ide_[un]register at any time.
+- */
+-void
+-pmac_ide_init_hwif_ports(hw_regs_t *hw,
+-			      unsigned long data_port, unsigned long ctrl_port,
+-			      int *irq)
+-{
+-	int i, ix;
+-
+-	if (data_port == 0)
+-		return;
+-
+-	for (ix = 0; ix < MAX_HWIFS; ++ix)
+-		if (data_port == pmac_ide[ix].regbase)
+-			break;
+-
+-	if (ix >= MAX_HWIFS)
+-		return;		/* not an IDE PMAC interface */
+-
+-	for (i = 0; i < 8; ++i)
+-		hw->io_ports[i] = data_port + i * 0x10;
+-	hw->io_ports[8] = data_port + 0x160;
+-
+-	if (irq != NULL)
+-		*irq = pmac_ide[ix].irq;
+-
+-	hw->dev = &pmac_ide[ix].mdev->ofdev.dev;
+-}
+-
+-#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))
++#define PMAC_IDE_REG(x) \
++	((void __iomem *)((drive)->hwif->io_ports[IDE_DATA_OFFSET] + (x)))
+ 
+ /*
+  * Apply the timings of the proper unit (master/slave) to the shared
+@@ -886,58 +853,6 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
+ 	pmif->timings[2] = pmif->timings[3] = value2;
+ }
+ 
+-unsigned long
+-pmac_ide_get_base(int index)
+-{
+-	return pmac_ide[index].regbase;
+-}
+-
+-int
+-pmac_ide_check_base(unsigned long base)
+-{
+-	int ix;
+-	
+- 	for (ix = 0; ix < MAX_HWIFS; ++ix)
+-		if (base == pmac_ide[ix].regbase)
+-			return ix;
+-	return -1;
+-}
+-
+-int
+-pmac_ide_get_irq(unsigned long base)
+-{
+-	int ix;
+-
+-	for (ix = 0; ix < MAX_HWIFS; ++ix)
+-		if (base == pmac_ide[ix].regbase)
+-			return pmac_ide[ix].irq;
+-	return 0;
+-}
+-
+-static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+-
+-dev_t __init
+-pmac_find_ide_boot(char *bootdevice, int n)
+-{
+-	int i;
+-	
+-	/*
+-	 * Look through the list of IDE interfaces for this one.
+-	 */
+-	for (i = 0; i < pmac_ide_count; ++i) {
+-		char *name;
+-		if (!pmac_ide[i].node || !pmac_ide[i].node->full_name)
+-			continue;
+-		name = pmac_ide[i].node->full_name;
+-		if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
+-			/* XXX should cope with the 2nd drive as well... */
+-			return MKDEV(ide_majors[i], 0);
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+ /* Suspend call back, should be called after the child devices
+  * have actually been suspended
+  */
+@@ -1006,7 +921,6 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
+ static const struct ide_port_info pmac_port_info = {
+ 	.chipset		= ide_pmac,
+ 	.host_flags		= IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
+-				  IDE_HFLAG_PIO_NO_DOWNGRADE |
+ 				  IDE_HFLAG_POST_SET_MODE |
+ 				  IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+ 				  IDE_HFLAG_UNMASK_IRQS,
+@@ -1088,7 +1002,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+ 	if (np->parent && np->parent->name
+ 	    && strcasecmp(np->parent->name, "media-bay") == 0) {
+ #ifdef CONFIG_PMAC_MEDIABAY
+-		media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index);
++		media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq,
++					hwif);
+ #endif /* CONFIG_PMAC_MEDIABAY */
+ 		pmif->mediabay = 1;
+ 		if (!bidp)
+@@ -1119,7 +1034,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+ 	hwif->hwif_data = pmif;
+ 	ide_init_port_hw(hwif, hw);
+ 	hwif->noprobe = pmif->mediabay;
+-	hwif->hold = pmif->mediabay;
+ 	hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ 	hwif->set_pio_mode = pmac_ide_set_pio_mode;
+ 	if (pmif->kind == controller_un_ata6
+@@ -1154,6 +1068,15 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+ 	return 0;
+ }
+ 
++static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base)
++{
++	int i;
++
++	for (i = 0; i < 8; ++i)
++		hw->io_ports[i] = base + i * 0x10;
++	hw->io_ports[8] = base + 0x160;
++}
++
+ /*
+  * Attach to a macio probed interface
+  */
+@@ -1162,35 +1085,36 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ {
+ 	void __iomem *base;
+ 	unsigned long regbase;
+-	int irq;
+ 	ide_hwif_t *hwif;
+ 	pmac_ide_hwif_t *pmif;
+-	int i, rc;
++	int irq, rc;
+ 	hw_regs_t hw;
+ 
+-	i = 0;
+-	while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
+-	    || pmac_ide[i].node != NULL))
+-		++i;
+-	if (i >= MAX_HWIFS) {
++	pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
++	if (pmif == NULL)
++		return -ENOMEM;
++
++	hwif = ide_find_port();
++	if (hwif == NULL) {
+ 		printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n");
+ 		printk(KERN_ERR "          %s\n", mdev->ofdev.node->full_name);
+-		return -ENODEV;
++		rc = -ENODEV;
++		goto out_free_pmif;
+ 	}
+ 
+-	pmif = &pmac_ide[i];
+-	hwif = &ide_hwifs[i];
+-
+ 	if (macio_resource_count(mdev) == 0) {
+-		printk(KERN_WARNING "ide%d: no address for %s\n",
+-		       i, mdev->ofdev.node->full_name);
+-		return -ENXIO;
++		printk(KERN_WARNING "ide-pmac: no address for %s\n",
++				    mdev->ofdev.node->full_name);
++		rc = -ENXIO;
++		goto out_free_pmif;
+ 	}
+ 
+ 	/* Request memory resource for IO ports */
+ 	if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) {
+-		printk(KERN_ERR "ide%d: can't request mmio resource !\n", i);
+-		return -EBUSY;
++		printk(KERN_ERR "ide-pmac: can't request MMIO resource for "
++				"%s!\n", mdev->ofdev.node->full_name);
++		rc = -EBUSY;
++		goto out_free_pmif;
+ 	}
+ 			
+ 	/* XXX This is bogus. Should be fixed in the registry by checking
+@@ -1199,8 +1123,8 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ 	 * where that happens though...
+ 	 */
+ 	if (macio_irq_count(mdev) == 0) {
+-		printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n",
+-			i, mdev->ofdev.node->full_name);
++		printk(KERN_WARNING "ide-pmac: no intrs for device %s, using "
++				    "13\n", mdev->ofdev.node->full_name);
+ 		irq = irq_create_mapping(NULL, 13);
+ 	} else
+ 		irq = macio_irq(mdev, 0);
+@@ -1218,7 +1142,9 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+ 	if (macio_resource_count(mdev) >= 2) {
+ 		if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
+-			printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i);
++			printk(KERN_WARNING "ide-pmac: can't request DMA "
++					    "resource for %s!\n",
++					    mdev->ofdev.node->full_name);
+ 		else
+ 			pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
+ 	} else
+@@ -1227,7 +1153,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ 	dev_set_drvdata(&mdev->ofdev.dev, hwif);
+ 
+ 	memset(&hw, 0, sizeof(hw));
+-	pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
++	pmac_ide_init_ports(&hw, pmif->regbase);
+ 	hw.irq = irq;
+ 	hw.dev = &mdev->ofdev.dev;
+ 
+@@ -1240,11 +1166,15 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ 			iounmap(pmif->dma_regs);
+ 			macio_release_resource(mdev, 1);
+ 		}
+-		memset(pmif, 0, sizeof(*pmif));
+ 		macio_release_resource(mdev, 0);
++		kfree(pmif);
+ 	}
+ 
+ 	return rc;
++
++out_free_pmif:
++	kfree(pmif);
++	return rc;
+ }
+ 
+ static int
+@@ -1289,7 +1219,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	pmac_ide_hwif_t *pmif;
+ 	void __iomem *base;
+ 	unsigned long rbase, rlen;
+-	int i, rc;
++	int rc;
+ 	hw_regs_t hw;
+ 
+ 	np = pci_device_to_OF_node(pdev);
+@@ -1297,30 +1227,32 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n");
+ 		return -ENODEV;
+ 	}
+-	i = 0;
+-	while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
+-	    || pmac_ide[i].node != NULL))
+-		++i;
+-	if (i >= MAX_HWIFS) {
++
++	pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
++	if (pmif == NULL)
++		return -ENOMEM;
++
++	hwif = ide_find_port();
++	if (hwif == NULL) {
+ 		printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n");
+ 		printk(KERN_ERR "          %s\n", np->full_name);
+-		return -ENODEV;
++		rc = -ENODEV;
++		goto out_free_pmif;
+ 	}
+ 
+-	pmif = &pmac_ide[i];
+-	hwif = &ide_hwifs[i];
+-
+ 	if (pci_enable_device(pdev)) {
+-		printk(KERN_WARNING "ide%i: Can't enable PCI device for %s\n",
+-			i, np->full_name);
+-		return -ENXIO;
++		printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
++				    "%s\n", np->full_name);
++		rc = -ENXIO;
++		goto out_free_pmif;
+ 	}
+ 	pci_set_master(pdev);
+ 			
+ 	if (pci_request_regions(pdev, "Kauai ATA")) {
+-		printk(KERN_ERR "ide%d: Cannot obtain PCI resources for %s\n",
+-			i, np->full_name);
+-		return -ENXIO;
++		printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources for "
++				"%s\n", np->full_name);
++		rc = -ENXIO;
++		goto out_free_pmif;
+ 	}
+ 
+ 	hwif->dev = &pdev->dev;
+@@ -1341,7 +1273,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	pci_set_drvdata(pdev, hwif);
+ 
+ 	memset(&hw, 0, sizeof(hw));
+-	pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
++	pmac_ide_init_ports(&hw, pmif->regbase);
+ 	hw.irq = pdev->irq;
+ 	hw.dev = &pdev->dev;
+ 
+@@ -1350,11 +1282,15 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		/* The inteface is released to the common IDE layer */
+ 		pci_set_drvdata(pdev, NULL);
+ 		iounmap(base);
+-		memset(pmif, 0, sizeof(*pmif));
+ 		pci_release_regions(pdev);
++		kfree(pmif);
+ 	}
+ 
+ 	return rc;
++
++out_free_pmif:
++	kfree(pmif);
++	return rc;
+ }
+ 
+ static int
+diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
+index 634e3f6..6302010 100644
+--- a/drivers/ide/setup-pci.c
++++ b/drivers/ide/setup-pci.c
+@@ -20,84 +20,6 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ 
+-
+-/**
+- *	ide_match_hwif	-	match a PCI IDE against an ide_hwif
+- *	@io_base: I/O base of device
+- *	@bootable: set if its bootable
+- *	@name: name of device
+- *
+- *	Match a PCI IDE port against an entry in ide_hwifs[],
+- *	based on io_base port if possible. Return the matching hwif,
+- *	or a new hwif. If we find an error (clashing, out of devices, etc)
+- *	return NULL
+- *
+- *	FIXME: we need to handle mmio matches here too
+- */
+-
+-static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name)
+-{
+-	int h;
+-	ide_hwif_t *hwif;
+-
+-	/*
+-	 * Look for a hwif with matching io_base specified using
+-	 * parameters to ide_setup().
+-	 */
+-	for (h = 0; h < MAX_HWIFS; ++h) {
+-		hwif = &ide_hwifs[h];
+-		if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
+-			if (hwif->chipset == ide_forced)
+-				return hwif; /* a perfect match */
+-		}
+-	}
+-	/*
+-	 * Look for a hwif with matching io_base default value.
+-	 * If chipset is "ide_unknown", then claim that hwif slot.
+-	 * Otherwise, some other chipset has already claimed it..  :(
+-	 */
+-	for (h = 0; h < MAX_HWIFS; ++h) {
+-		hwif = &ide_hwifs[h];
+-		if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
+-			if (hwif->chipset == ide_unknown)
+-				return hwif; /* match */
+-			printk(KERN_ERR "%s: port 0x%04lx already claimed by %s\n",
+-				name, io_base, hwif->name);
+-			return NULL;	/* already claimed */
+-		}
+-	}
+-	/*
+-	 * Okay, there is no hwif matching our io_base,
+-	 * so we'll just claim an unassigned slot.
+-	 * Give preference to claiming other slots before claiming ide0/ide1,
+-	 * just in case there's another interface yet-to-be-scanned
+-	 * which uses ports 1f0/170 (the ide0/ide1 defaults).
+-	 *
+-	 * Unless there is a bootable card that does not use the standard
+-	 * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag.
+-	 */
+-	if (bootable) {
+-		for (h = 0; h < MAX_HWIFS; ++h) {
+-			hwif = &ide_hwifs[h];
+-			if (hwif->chipset == ide_unknown)
+-				return hwif;	/* pick an unused entry */
+-		}
+-	} else {
+-		for (h = 2; h < MAX_HWIFS; ++h) {
+-			hwif = ide_hwifs + h;
+-			if (hwif->chipset == ide_unknown)
+-				return hwif;	/* pick an unused entry */
+-		}
+-	}
+-	for (h = 0; h < 2 && h < MAX_HWIFS; ++h) {
+-		hwif = ide_hwifs + h;
+-		if (hwif->chipset == ide_unknown)
+-			return hwif;	/* pick an unused entry */
+-	}
+-	printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", name);
+-	return NULL;
+-}
+-
+ /**
+  *	ide_setup_pci_baseregs	-	place a PCI IDE controller native
+  *	@dev: PCI device of interface to switch native
+@@ -105,13 +27,13 @@ static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char
+  *
+  *	We attempt to place the PCI interface into PCI native mode. If
+  *	we succeed the BARs are ok and the controller is in PCI mode.
+- *	Returns 0 on success or an errno code. 
++ *	Returns 0 on success or an errno code.
+  *
+  *	FIXME: if we program the interface and then fail to set the BARS
+  *	we don't switch it back to legacy mode. Do we actually care ??
+  */
+- 
+-static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
++
++static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
+ {
+ 	u8 progif = 0;
+ 
+@@ -218,7 +140,6 @@ void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
+ 			 " PCI slot %s\n", d->name, dev->vendor, dev->device,
+ 			 dev->revision, pci_name(dev));
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
+ 
+ 
+@@ -231,7 +152,7 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
+  *	but if that fails then we only need IO space. The PCI code should
+  *	have setup the proper resources for us already for controllers in
+  *	legacy mode.
+- *	
++ *
+  *	Returns zero on success or an error code
+  */
+ 
+@@ -290,8 +211,8 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
+ 	 * Maybe the user deliberately *disabled* the device,
+ 	 * but we'll eventually ignore it again if no drives respond.
+ 	 */
+-	if (ide_setup_pci_baseregs(dev, d->name) || pci_write_config_word(dev, PCI_COMMAND, pcicmd|PCI_COMMAND_IO)) 
+-	{
++	if (ide_setup_pci_baseregs(dev, d->name) ||
++	    pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
+ 		printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name);
+ 		return -ENODEV;
+ 	}
+@@ -312,26 +233,24 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
+  *	@d: IDE port info
+  *	@bar: BAR number
+  *
+- *	Checks if a BAR is configured and points to MMIO space. If so
+- *	print an error and return an error code. Otherwise return 0
++ *	Checks if a BAR is configured and points to MMIO space. If so,
++ *	return an error code. Otherwise return 0
+  */
+ 
+-static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, int bar)
++static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d,
++			       int bar)
+ {
+ 	ulong flags = pci_resource_flags(dev, bar);
+-	
++
+ 	/* Unconfigured ? */
+ 	if (!flags || pci_resource_len(dev, bar) == 0)
+ 		return 0;
+ 
+-	/* I/O space */		
+-	if(flags & PCI_BASE_ADDRESS_IO_MASK)
++	/* I/O space */
++	if (flags & IORESOURCE_IO)
+ 		return 0;
+-		
++
+ 	/* Bad */
+-	printk(KERN_ERR "%s: IO baseregs (BIOS) are reported "
+-			"as MEM, report to "
+-			"<andre at linux-ide.org>.\n", d->name);
+ 	return -EINVAL;
+ }
+ 
+@@ -355,15 +274,16 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
+ {
+ 	unsigned long ctl = 0, base = 0;
+ 	ide_hwif_t *hwif;
+-	u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0;
+-	u8 oldnoprobe = 0;
+ 	struct hw_regs_s hw;
+ 
+ 	if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
+-		/*  Possibly we should fail if these checks report true */
+-		ide_pci_check_iomem(dev, d, 2*port);
+-		ide_pci_check_iomem(dev, d, 2*port+1);
+- 
++		if (ide_pci_check_iomem(dev, d, 2 * port) ||
++		    ide_pci_check_iomem(dev, d, 2 * port + 1)) {
++			printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported "
++					"as MEM for port %d!\n", d->name, port);
++			return NULL;
++		}
++
+ 		ctl  = pci_resource_start(dev, 2*port+1);
+ 		base = pci_resource_start(dev, 2*port);
+ 		if ((ctl && !base) || (base && !ctl)) {
+@@ -372,29 +292,27 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
+ 			return NULL;
+ 		}
+ 	}
+-	if (!ctl)
+-	{
++	if (!ctl) {
+ 		/* Use default values */
+ 		ctl = port ? 0x374 : 0x3f4;
+ 		base = port ? 0x170 : 0x1f0;
+ 	}
+-	if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL)
+-		return NULL;	/* no room in ide_hwifs[] */
++
++	hwif = ide_find_port_slot(d);
++	if (hwif == NULL) {
++		printk(KERN_ERR "%s: too many IDE interfaces, no room in "
++				"table\n", d->name);
++		return NULL;
++	}
+ 
+ 	memset(&hw, 0, sizeof(hw));
+-	hw.irq = hwif->irq ? hwif->irq : irq;
++	hw.irq = irq;
+ 	hw.dev = &dev->dev;
+ 	hw.chipset = d->chipset ? d->chipset : ide_pci;
+ 	ide_std_init_ports(&hw, base, ctl | 2);
+ 
+-	if (hwif->io_ports[IDE_DATA_OFFSET] == base &&
+-	    hwif->io_ports[IDE_CONTROL_OFFSET] == (ctl | 2))
+-		oldnoprobe = hwif->noprobe;
+-
+ 	ide_init_port_hw(hwif, &hw);
+ 
+-	hwif->noprobe = oldnoprobe;
+-
+ 	hwif->dev = &dev->dev;
+ 	hwif->cds = d;
+ 
+@@ -425,9 +343,9 @@ void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
+ 		unsigned long dma_base = ide_get_or_set_dma_base(d, hwif);
+ 		if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
+ 			/*
+- 			 * Set up BM-DMA capability
++			 * Set up BM-DMA capability
+ 			 * (PnP BIOS should have done this)
+- 			 */
++			 */
+ 			pci_set_master(dev);
+ 			if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
+ 				printk(KERN_ERR "%s: %s error updating PCICMD\n",
+@@ -532,7 +450,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
+ 		*(idx + port) = hwif->index;
+ 	}
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
+ 
+ /*
+@@ -615,7 +532,6 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
+ 
+ 	return ret;
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_setup_pci_device);
+ 
+ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
+@@ -639,5 +555,4 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
+ out:
+ 	return ret;
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
+diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c
+index 52ac83e..c90be40 100644
+--- a/drivers/ieee1394/csr.c
++++ b/drivers/ieee1394/csr.c
+@@ -133,8 +133,7 @@ static void host_reset(struct hpsb_host *host)
+                 host->csr.state &= ~0x100;
+         }
+ 
+-        host->csr.topology_map[1] =
+-                cpu_to_be32(be32_to_cpu(host->csr.topology_map[1]) + 1);
++	be32_add_cpu(&host->csr.topology_map[1], 1);
+         host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16
+                                                 | host->selfid_count);
+         host->csr.topology_map[0] =
+@@ -142,8 +141,7 @@ static void host_reset(struct hpsb_host *host)
+                             | csr_crc16(host->csr.topology_map + 1,
+                                         host->selfid_count + 2));
+ 
+-        host->csr.speed_map[1] =
+-                cpu_to_be32(be32_to_cpu(host->csr.speed_map[1]) + 1);
++	be32_add_cpu(&host->csr.speed_map[1], 1);
+         host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16
+                                              | csr_crc16(host->csr.speed_map+1,
+                                                          0x3f1));
+diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
+index 6572211..9d19aec 100644
+--- a/drivers/ieee1394/dv1394.c
++++ b/drivers/ieee1394/dv1394.c
+@@ -2167,6 +2167,7 @@ static const struct file_operations dv1394_fops=
+ /*
+  * Export information about protocols/devices supported by this driver.
+  */
++#ifdef MODULE
+ static struct ieee1394_device_id dv1394_id_table[] = {
+ 	{
+ 		.match_flags	= IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+@@ -2177,10 +2178,10 @@ static struct ieee1394_device_id dv1394_id_table[] = {
+ };
+ 
+ MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
++#endif /* MODULE */
+ 
+ static struct hpsb_protocol_driver dv1394_driver = {
+-	.name		= "dv1394",
+-	.id_table	= dv1394_id_table,
++	.name = "dv1394",
+ };
+ 
+ 
+@@ -2568,7 +2569,6 @@ static int __init dv1394_init_module(void)
+ 
+ 	cdev_init(&dv1394_cdev, &dv1394_fops);
+ 	dv1394_cdev.owner = THIS_MODULE;
+-	kobject_set_name(&dv1394_cdev.kobj, "dv1394");
+ 	ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
+ 	if (ret) {
+ 		printk(KERN_ERR "dv1394: unable to register character device\n");
+diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
+index b642546..fa2bfec 100644
+--- a/drivers/ieee1394/highlevel.c
++++ b/drivers/ieee1394/highlevel.c
+@@ -339,7 +339,7 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
+ 	if ((alignment & 3) || (alignment > 0x800000000000ULL) ||
+ 	    (hweight64(alignment) != 1)) {
+ 		HPSB_ERR("%s called with invalid alignment: 0x%048llx",
+-			 __FUNCTION__, (unsigned long long)alignment);
++			 __func__, (unsigned long long)alignment);
+ 		return retval;
+ 	}
+ 
+@@ -354,7 +354,7 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
+ 	if (((start|end) & ~align_mask) || (start >= end) ||
+ 	    (end > CSR1212_ALL_SPACE_END)) {
+ 		HPSB_ERR("%s called with invalid addresses "
+-			 "(start = %012Lx  end = %012Lx)", __FUNCTION__,
++			 "(start = %012Lx  end = %012Lx)", __func__,
+ 			 (unsigned long long)start,(unsigned long long)end);
+ 		return retval;
+ 	}
+@@ -422,7 +422,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
+ 
+ 	if (((start|end) & 3) || (start >= end) ||
+ 	    (end > CSR1212_ALL_SPACE_END)) {
+-		HPSB_ERR("%s called with invalid addresses", __FUNCTION__);
++		HPSB_ERR("%s called with invalid addresses", __func__);
+ 		return 0;
+ 	}
+ 
+diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
+index 36c747b..dcdb71a 100644
+--- a/drivers/ieee1394/ieee1394_core.c
++++ b/drivers/ieee1394/ieee1394_core.c
+@@ -242,7 +242,7 @@ int hpsb_bus_reset(struct hpsb_host *host)
+ {
+ 	if (host->in_bus_reset) {
+ 		HPSB_NOTICE("%s called while bus reset already in progress",
+-			    __FUNCTION__);
++			    __func__);
+ 		return 1;
+ 	}
+ 
+@@ -373,6 +373,8 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
+ 			if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
+ 
+ 			speedcap[n] = sid->speed;
++			if (speedcap[n] > host->csr.lnk_spd)
++				speedcap[n] = host->csr.lnk_spd;
+ 			n--;
+ 		}
+ 	}
+diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h
+index b94e55e..b5de5f2 100644
+--- a/drivers/ieee1394/iso.h
++++ b/drivers/ieee1394/iso.h
+@@ -123,6 +123,8 @@ struct hpsb_iso {
+ 
+ 	/* how many times the buffer has overflowed or underflowed */
+ 	atomic_t overflows;
++	/* how many cycles were skipped for a given context */
++	atomic_t skips;
+ 
+ 	/* Current number of bytes lost in discarded packets */
+ 	int bytes_discarded;
+diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
+index 511e432..29d833e 100644
+--- a/drivers/ieee1394/nodemgr.c
++++ b/drivers/ieee1394/nodemgr.c
+@@ -18,8 +18,8 @@
+ #include <linux/moduleparam.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ 
+ #include "csr.h"
+ #include "highlevel.h"
+@@ -701,7 +701,11 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
+ 		return 0;
+ 
+ 	driver = container_of(drv, struct hpsb_protocol_driver, driver);
+-	for (id = driver->id_table; id->match_flags != 0; id++) {
++	id = driver->id_table;
++	if (!id)
++		return 0;
++
++	for (; id->match_flags != 0; id++) {
+ 		if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
+ 		    id->vendor_id != ud->vendor_id)
+ 			continue;
+diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
+index 969de2a..e509e13 100644
+--- a/drivers/ieee1394/ohci1394.c
++++ b/drivers/ieee1394/ohci1394.c
+@@ -149,7 +149,7 @@ printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id ,
+ /* Module Parameters */
+ static int phys_dma = 1;
+ module_param(phys_dma, int, 0444);
+-MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
++MODULE_PARM_DESC(phys_dma, "Enable physical DMA (default = 1).");
+ 
+ static void dma_trm_tasklet(unsigned long data);
+ static void dma_trm_reset(struct dma_trm_ctx *d);
+@@ -708,7 +708,7 @@ static void insert_packet(struct ti_ohci *ohci,
+                                 /* FIXME: do something about it */
+                                 PRINT(KERN_ERR,
+                                       "%s: packet data addr: %p size %Zd bytes "
+-                                      "cross page boundary", __FUNCTION__,
++				      "cross page boundary", __func__,
+                                       packet->data, packet->data_size);
+                         }
+ #endif
+@@ -1723,6 +1723,8 @@ struct ohci_iso_xmit {
+ 	struct dma_prog_region prog;
+ 	struct ohci1394_iso_tasklet task;
+ 	int task_active;
++	int last_cycle;
++	atomic_t skips;
+ 
+ 	u32 ContextControlSet;
+ 	u32 ContextControlClear;
+@@ -1759,6 +1761,8 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso)
+ 	iso->hostdata = xmit;
+ 	xmit->ohci = iso->host->hostdata;
+ 	xmit->task_active = 0;
++	xmit->last_cycle = -1;
++	atomic_set(&iso->skips, 0);
+ 
+ 	dma_prog_region_init(&xmit->prog);
+ 
+@@ -1856,6 +1860,26 @@ static void ohci_iso_xmit_task(unsigned long data)
+ 		/* parse cycle */
+ 		cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
+ 
++		if (xmit->last_cycle > -1) {
++			int cycle_diff = cycle - xmit->last_cycle;
++			int skip;
++
++			/* unwrap */
++			if (cycle_diff < 0) {
++				cycle_diff += 8000;
++				if (cycle_diff < 0)
++					PRINT(KERN_ERR, "bogus cycle diff %d\n",
++					      cycle_diff);
++			}
++
++			skip = cycle_diff - 1;
++			if (skip > 0) {
++				DBGMSG("skipped %d cycles without packet loss", skip);
++				atomic_add(skip, &iso->skips);
++			}
++		}
++		xmit->last_cycle = cycle;
++
+ 		/* tell the subsystem the packet has gone out */
+ 		hpsb_iso_packet_sent(iso, cycle, event != 0x11);
+ 
+@@ -1943,6 +1967,16 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
+ 	prev->output_last.branchAddress = cpu_to_le32(
+ 		dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
+ 
++	/*
++	 * Link the skip address to this descriptor itself. This causes a
++	 * context to skip a cycle whenever lost cycles or FIFO overruns occur,
++	 * without dropping the data at that point the application should then
++	 * decide whether this is an error condition or not. Some protocols
++	 * can deal with this by dropping some rate-matching padding packets.
++	 */
++	next->output_more_immediate.branchAddress =
++			prev->output_last.branchAddress;
++
+ 	/* disable interrupt, unless required by the IRQ interval */
+ 	if (prev_i % iso->irq_interval) {
+ 		prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
+@@ -2089,10 +2123,8 @@ static void dma_trm_reset(struct dma_trm_ctx *d)
+ 
+ 	spin_lock_irqsave(&d->lock, flags);
+ 
+-	list_splice(&d->fifo_list, &packet_list);
+-	list_splice(&d->pending_list, &packet_list);
+-	INIT_LIST_HEAD(&d->fifo_list);
+-	INIT_LIST_HEAD(&d->pending_list);
++	list_splice_init(&d->fifo_list, &packet_list);
++	list_splice_init(&d->pending_list, &packet_list);
+ 
+ 	d->branchAddrPtr = NULL;
+ 	d->sent_ind = d->prg_ind;
+@@ -2787,7 +2819,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+ 	d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC);
+ 
+ 	if (d->buf_cpu == NULL || d->buf_bus == NULL) {
+-		PRINT(KERN_ERR, "Failed to allocate dma buffer");
++		PRINT(KERN_ERR, "Failed to allocate %s", "DMA buffer");
+ 		free_dma_rcv_ctx(d);
+ 		return -ENOMEM;
+ 	}
+@@ -2796,7 +2828,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+ 	d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC);
+ 
+ 	if (d->prg_cpu == NULL || d->prg_bus == NULL) {
+-		PRINT(KERN_ERR, "Failed to allocate dma prg");
++		PRINT(KERN_ERR, "Failed to allocate %s", "DMA prg");
+ 		free_dma_rcv_ctx(d);
+ 		return -ENOMEM;
+ 	}
+@@ -2804,7 +2836,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+ 	d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC);
+ 
+ 	if (d->spb == NULL) {
+-		PRINT(KERN_ERR, "Failed to allocate split buffer");
++		PRINT(KERN_ERR, "Failed to allocate %s", "split buffer");
+ 		free_dma_rcv_ctx(d);
+ 		return -ENOMEM;
+ 	}
+@@ -2830,7 +2862,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+ 			memset(d->buf_cpu[i], 0, d->buf_size);
+ 		} else {
+ 			PRINT(KERN_ERR,
+-			      "Failed to allocate dma buffer");
++			      "Failed to allocate %s", "DMA buffer");
+ 			free_dma_rcv_ctx(d);
+ 			return -ENOMEM;
+ 		}
+@@ -2841,7 +2873,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+                         memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
+ 		} else {
+ 			PRINT(KERN_ERR,
+-			      "Failed to allocate dma prg");
++			      "Failed to allocate %s", "DMA prg");
+ 			free_dma_rcv_ctx(d);
+ 			return -ENOMEM;
+ 		}
+@@ -2902,7 +2934,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
+ 	d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL);
+ 
+ 	if (d->prg_cpu == NULL || d->prg_bus == NULL) {
+-		PRINT(KERN_ERR, "Failed to allocate at dma prg");
++		PRINT(KERN_ERR, "Failed to allocate %s", "AT DMA prg");
+ 		free_dma_trm_ctx(d);
+ 		return -ENOMEM;
+ 	}
+@@ -2925,7 +2957,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
+                         memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
+ 		} else {
+ 			PRINT(KERN_ERR,
+-			      "Failed to allocate at dma prg");
++			      "Failed to allocate %s", "AT DMA prg");
+ 			free_dma_trm_ctx(d);
+ 			return -ENOMEM;
+ 		}
+@@ -2986,22 +3018,9 @@ static struct hpsb_host_driver ohci1394_driver = {
+  * PCI Driver Interface functions  *
+  ***********************************/
+ 
+-#define FAIL(err, fmt, args...)			\
+-do {						\
+-	PRINT_G(KERN_ERR, fmt , ## args);	\
+-        ohci1394_pci_remove(dev);               \
+-	return err;				\
+-} while (0)
+-
+-static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+-					const struct pci_device_id *ent)
+-{
+-	struct hpsb_host *host;
+-	struct ti_ohci *ohci;	/* shortcut to currently handled device */
+-	resource_size_t ohci_base;
+-
+ #ifdef CONFIG_PPC_PMAC
+-	/* Necessary on some machines if ohci1394 was loaded/ unloaded before */
++static void ohci1394_pmac_on(struct pci_dev *dev)
++{
+ 	if (machine_is(powermac)) {
+ 		struct device_node *ofn = pci_device_to_OF_node(dev);
+ 
+@@ -3010,15 +3029,45 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ 			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+ 		}
+ 	}
++}
++
++static void ohci1394_pmac_off(struct pci_dev *dev)
++{
++	if (machine_is(powermac)) {
++		struct device_node *ofn = pci_device_to_OF_node(dev);
++
++		if (ofn) {
++			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
++			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
++		}
++	}
++}
++#else
++#define ohci1394_pmac_on(dev)
++#define ohci1394_pmac_off(dev)
+ #endif /* CONFIG_PPC_PMAC */
+ 
+-        if (pci_enable_device(dev))
+-		FAIL(-ENXIO, "Failed to enable OHCI hardware");
++static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
++					const struct pci_device_id *ent)
++{
++	struct hpsb_host *host;
++	struct ti_ohci *ohci;	/* shortcut to currently handled device */
++	resource_size_t ohci_base;
++	int err = -ENOMEM;
++
++	ohci1394_pmac_on(dev);
++	if (pci_enable_device(dev)) {
++		PRINT_G(KERN_ERR, "Failed to enable OHCI hardware");
++		err = -ENXIO;
++		goto err;
++	}
+         pci_set_master(dev);
+ 
+ 	host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci), &dev->dev);
+-	if (!host) FAIL(-ENOMEM, "Failed to allocate host structure");
+-
++	if (!host) {
++		PRINT_G(KERN_ERR, "Failed to allocate %s", "host structure");
++		goto err;
++	}
+ 	ohci = host->hostdata;
+ 	ohci->dev = dev;
+ 	ohci->host = host;
+@@ -3067,15 +3116,20 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ 		      (unsigned long long)pci_resource_len(dev, 0));
+ 
+ 	if (!request_mem_region(ohci_base, OHCI1394_REGISTER_SIZE,
+-				OHCI1394_DRIVER_NAME))
+-		FAIL(-ENOMEM, "MMIO resource (0x%llx - 0x%llx) unavailable",
++				OHCI1394_DRIVER_NAME)) {
++		PRINT_G(KERN_ERR, "MMIO resource (0x%llx - 0x%llx) unavailable",
+ 			(unsigned long long)ohci_base,
+ 			(unsigned long long)ohci_base + OHCI1394_REGISTER_SIZE);
++		goto err;
++	}
+ 	ohci->init_state = OHCI_INIT_HAVE_MEM_REGION;
+ 
+ 	ohci->registers = ioremap(ohci_base, OHCI1394_REGISTER_SIZE);
+-	if (ohci->registers == NULL)
+-		FAIL(-ENXIO, "Failed to remap registers - card not accessible");
++	if (ohci->registers == NULL) {
++		PRINT_G(KERN_ERR, "Failed to remap registers");
++		err = -ENXIO;
++		goto err;
++	}
+ 	ohci->init_state = OHCI_INIT_HAVE_IOMAPPING;
+ 	DBGMSG("Remapped memory spaces reg 0x%p", ohci->registers);
+ 
+@@ -3083,16 +3137,20 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ 	ohci->csr_config_rom_cpu =
+ 		pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
+ 				     &ohci->csr_config_rom_bus);
+-	if (ohci->csr_config_rom_cpu == NULL)
+-		FAIL(-ENOMEM, "Failed to allocate buffer config rom");
++	if (ohci->csr_config_rom_cpu == NULL) {
++		PRINT_G(KERN_ERR, "Failed to allocate %s", "buffer config rom");
++		goto err;
++	}
+ 	ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
+ 
+ 	/* self-id dma buffer allocation */
+ 	ohci->selfid_buf_cpu =
+ 		pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
+                       &ohci->selfid_buf_bus);
+-	if (ohci->selfid_buf_cpu == NULL)
+-		FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
++	if (ohci->selfid_buf_cpu == NULL) {
++		PRINT_G(KERN_ERR, "Failed to allocate %s", "self-ID buffer");
++		goto err;
++	}
+ 	ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
+ 
+ 	if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff)
+@@ -3108,28 +3166,32 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ 	if (alloc_dma_rcv_ctx(ohci, &ohci->ar_req_context,
+ 			      DMA_CTX_ASYNC_REQ, 0, AR_REQ_NUM_DESC,
+ 			      AR_REQ_BUF_SIZE, AR_REQ_SPLIT_BUF_SIZE,
+-			      OHCI1394_AsReqRcvContextBase) < 0)
+-		FAIL(-ENOMEM, "Failed to allocate AR Req context");
+-
++			      OHCI1394_AsReqRcvContextBase) < 0) {
++		PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Req context");
++		goto err;
++	}
+ 	/* AR DMA response context allocation */
+ 	if (alloc_dma_rcv_ctx(ohci, &ohci->ar_resp_context,
+ 			      DMA_CTX_ASYNC_RESP, 0, AR_RESP_NUM_DESC,
+ 			      AR_RESP_BUF_SIZE, AR_RESP_SPLIT_BUF_SIZE,
+-			      OHCI1394_AsRspRcvContextBase) < 0)
+-		FAIL(-ENOMEM, "Failed to allocate AR Resp context");
+-
++			      OHCI1394_AsRspRcvContextBase) < 0) {
++		PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Resp context");
++		goto err;
++	}
+ 	/* AT DMA request context */
+ 	if (alloc_dma_trm_ctx(ohci, &ohci->at_req_context,
+ 			      DMA_CTX_ASYNC_REQ, 0, AT_REQ_NUM_DESC,
+-			      OHCI1394_AsReqTrContextBase) < 0)
+-		FAIL(-ENOMEM, "Failed to allocate AT Req context");
+-
++			      OHCI1394_AsReqTrContextBase) < 0) {
++		PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Req context");
++		goto err;
++	}
+ 	/* AT DMA response context */
+ 	if (alloc_dma_trm_ctx(ohci, &ohci->at_resp_context,
+ 			      DMA_CTX_ASYNC_RESP, 1, AT_RESP_NUM_DESC,
+-			      OHCI1394_AsRspTrContextBase) < 0)
+-		FAIL(-ENOMEM, "Failed to allocate AT Resp context");
+-
++			      OHCI1394_AsRspTrContextBase) < 0) {
++		PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Resp context");
++		goto err;
++	}
+ 	/* Start off with a soft reset, to clear everything to a sane
+ 	 * state. */
+ 	ohci_soft_reset(ohci);
+@@ -3172,9 +3234,10 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ 	 * by that point.
+ 	 */
+ 	if (request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
+-			 OHCI1394_DRIVER_NAME, ohci))
+-		FAIL(-ENOMEM, "Failed to allocate shared interrupt %d", dev->irq);
+-
++			 OHCI1394_DRIVER_NAME, ohci)) {
++		PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
++		goto err;
++	}
+ 	ohci->init_state = OHCI_INIT_HAVE_IRQ;
+ 	ohci_initialize(ohci);
+ 
+@@ -3194,25 +3257,28 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ 	host->middle_addr_space = OHCI1394_MIDDLE_ADDRESS_SPACE;
+ 
+ 	/* Tell the highlevel this host is ready */
+-	if (hpsb_add_host(host))
+-		FAIL(-ENOMEM, "Failed to register host with highlevel");
+-
++	if (hpsb_add_host(host)) {
++		PRINT_G(KERN_ERR, "Failed to register host with highlevel");
++		goto err;
++	}
+ 	ohci->init_state = OHCI_INIT_DONE;
+ 
+ 	return 0;
+-#undef FAIL
++err:
++	ohci1394_pci_remove(dev);
++	return err;
+ }
+ 
+-static void ohci1394_pci_remove(struct pci_dev *pdev)
++static void ohci1394_pci_remove(struct pci_dev *dev)
+ {
+ 	struct ti_ohci *ohci;
+-	struct device *dev;
++	struct device *device;
+ 
+-	ohci = pci_get_drvdata(pdev);
++	ohci = pci_get_drvdata(dev);
+ 	if (!ohci)
+-		return;
++		goto out;
+ 
+-	dev = get_device(&ohci->host->device);
++	device = get_device(&ohci->host->device);
+ 
+ 	switch (ohci->init_state) {
+ 	case OHCI_INIT_DONE:
+@@ -3246,7 +3312,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
+ 		/* Soft reset before we start - this disables
+ 		 * interrupts and clears linkEnable and LPS. */
+ 		ohci_soft_reset(ohci);
+-		free_irq(ohci->dev->irq, ohci);
++		free_irq(dev->irq, ohci);
+ 
+ 	case OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE:
+ 		/* The ohci_soft_reset() stops all DMA contexts, so we
+@@ -3257,12 +3323,12 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
+ 		free_dma_trm_ctx(&ohci->at_resp_context);
+ 
+ 	case OHCI_INIT_HAVE_SELFID_BUFFER:
+-		pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
++		pci_free_consistent(dev, OHCI1394_SI_DMA_BUF_SIZE,
+ 				    ohci->selfid_buf_cpu,
+ 				    ohci->selfid_buf_bus);
+ 
+ 	case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
+-		pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
++		pci_free_consistent(dev, OHCI_CONFIG_ROM_LEN,
+ 				    ohci->csr_config_rom_cpu,
+ 				    ohci->csr_config_rom_bus);
+ 
+@@ -3270,35 +3336,24 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
+ 		iounmap(ohci->registers);
+ 
+ 	case OHCI_INIT_HAVE_MEM_REGION:
+-		release_mem_region(pci_resource_start(ohci->dev, 0),
++		release_mem_region(pci_resource_start(dev, 0),
+ 				   OHCI1394_REGISTER_SIZE);
+ 
+-#ifdef CONFIG_PPC_PMAC
+-	/* On UniNorth, power down the cable and turn off the chip clock
+-	 * to save power on laptops */
+-	if (machine_is(powermac)) {
+-		struct device_node* ofn = pci_device_to_OF_node(ohci->dev);
+-
+-		if (ofn) {
+-			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+-			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
+-		}
+-	}
+-#endif /* CONFIG_PPC_PMAC */
+-
+ 	case OHCI_INIT_ALLOC_HOST:
+-		pci_set_drvdata(ohci->dev, NULL);
++		pci_set_drvdata(dev, NULL);
+ 	}
+ 
+-	if (dev)
+-		put_device(dev);
++	if (device)
++		put_device(device);
++out:
++	ohci1394_pmac_off(dev);
+ }
+ 
+ #ifdef CONFIG_PM
+-static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state)
++static int ohci1394_pci_suspend(struct pci_dev *dev, pm_message_t state)
+ {
+ 	int err;
+-	struct ti_ohci *ohci = pci_get_drvdata(pdev);
++	struct ti_ohci *ohci = pci_get_drvdata(dev);
+ 
+ 	if (!ohci) {
+ 		printk(KERN_ERR "%s: tried to suspend nonexisting host\n",
+@@ -3326,32 +3381,23 @@ static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+ 	ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
+ 	ohci_soft_reset(ohci);
+ 
+-	err = pci_save_state(pdev);
++	err = pci_save_state(dev);
+ 	if (err) {
+ 		PRINT(KERN_ERR, "pci_save_state failed with %d", err);
+ 		return err;
+ 	}
+-	err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
++	err = pci_set_power_state(dev, pci_choose_state(dev, state));
+ 	if (err)
+ 		DBGMSG("pci_set_power_state failed with %d", err);
+-
+-/* PowerMac suspend code comes last */
+-#ifdef CONFIG_PPC_PMAC
+-	if (machine_is(powermac)) {
+-		struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+-		if (ofn)
+-			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+-	}
+-#endif /* CONFIG_PPC_PMAC */
++	ohci1394_pmac_off(dev);
+ 
+ 	return 0;
+ }
+ 
+-static int ohci1394_pci_resume(struct pci_dev *pdev)
++static int ohci1394_pci_resume(struct pci_dev *dev)
+ {
+ 	int err;
+-	struct ti_ohci *ohci = pci_get_drvdata(pdev);
++	struct ti_ohci *ohci = pci_get_drvdata(dev);
+ 
+ 	if (!ohci) {
+ 		printk(KERN_ERR "%s: tried to resume nonexisting host\n",
+@@ -3360,19 +3406,10 @@ static int ohci1394_pci_resume(struct pci_dev *pdev)
+ 	}
+ 	DBGMSG("resume called");
+ 
+-/* PowerMac resume code comes first */
+-#ifdef CONFIG_PPC_PMAC
+-	if (machine_is(powermac)) {
+-		struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+-		if (ofn)
+-			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+-	}
+-#endif /* CONFIG_PPC_PMAC */
+-
+-	pci_set_power_state(pdev, PCI_D0);
+-	pci_restore_state(pdev);
+-	err = pci_enable_device(pdev);
++	ohci1394_pmac_on(dev);
++	pci_set_power_state(dev, PCI_D0);
++	pci_restore_state(dev);
++	err = pci_enable_device(dev);
+ 	if (err) {
+ 		PRINT(KERN_ERR, "pci_enable_device failed with %d", err);
+ 		return err;
+diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
+index 8af01ab..7aee1ac 100644
+--- a/drivers/ieee1394/pcilynx.c
++++ b/drivers/ieee1394/pcilynx.c
+@@ -226,7 +226,7 @@ static int get_phy_reg(struct ti_lynx *lynx, int addr)
+         if (addr > 15) {
+                 PRINT(KERN_ERR, lynx->id,
+                       "%s: PHY register address %d out of range",
+-		      __FUNCTION__, addr);
++		      __func__, addr);
+                 return -1;
+         }
+ 
+@@ -238,7 +238,7 @@ static int get_phy_reg(struct ti_lynx *lynx, int addr)
+ 
+                 if (i > 10000) {
+                         PRINT(KERN_ERR, lynx->id, "%s: runaway loop, aborting",
+-			      __FUNCTION__);
++			      __func__);
+                         retval = -1;
+                         break;
+                 }
+@@ -261,13 +261,13 @@ static int set_phy_reg(struct ti_lynx *lynx, int addr, int val)
+ 
+         if (addr > 15) {
+                 PRINT(KERN_ERR, lynx->id,
+-                      "%s: PHY register address %d out of range", __FUNCTION__, addr);
++		      "%s: PHY register address %d out of range", __func__, addr);
+                 return -1;
+         }
+ 
+         if (val > 0xff) {
+                 PRINT(KERN_ERR, lynx->id,
+-                      "%s: PHY register value %d out of range", __FUNCTION__, val);
++		      "%s: PHY register value %d out of range", __func__, val);
+                 return -1;
+         }
+ 
+@@ -287,7 +287,7 @@ static int sel_phy_reg_page(struct ti_lynx *lynx, int page)
+ 
+         if (page > 7) {
+                 PRINT(KERN_ERR, lynx->id,
+-                      "%s: PHY page %d out of range", __FUNCTION__, page);
++		      "%s: PHY page %d out of range", __func__, page);
+                 return -1;
+         }
+ 
+@@ -309,7 +309,7 @@ static int sel_phy_reg_port(struct ti_lynx *lynx, int port)
+ 
+         if (port > 15) {
+                 PRINT(KERN_ERR, lynx->id,
+-                      "%s: PHY port %d out of range", __FUNCTION__, port);
++		      "%s: PHY port %d out of range", __func__, port);
+                 return -1;
+         }
+ 
+@@ -738,8 +738,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
+                 spin_lock_irqsave(&lynx->async.queue_lock, flags);
+ 
+                 reg_write(lynx, DMA_CHAN_CTRL(CHANNEL_ASYNC_SEND), 0);
+-		list_splice(&lynx->async.queue, &packet_list);
+-		INIT_LIST_HEAD(&lynx->async.queue);
++		list_splice_init(&lynx->async.queue, &packet_list);
+ 
+                 if (list_empty(&lynx->async.pcl_queue)) {
+                         spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
+diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
+index 37e7e10..ec2a0ad 100644
+--- a/drivers/ieee1394/raw1394.c
++++ b/drivers/ieee1394/raw1394.c
+@@ -2356,13 +2356,16 @@ static void rawiso_activity_cb(struct hpsb_iso *iso)
+ static void raw1394_iso_fill_status(struct hpsb_iso *iso,
+ 				    struct raw1394_iso_status *stat)
+ {
++	int overflows = atomic_read(&iso->overflows);
++	int skips = atomic_read(&iso->skips);
++
+ 	stat->config.data_buf_size = iso->buf_size;
+ 	stat->config.buf_packets = iso->buf_packets;
+ 	stat->config.channel = iso->channel;
+ 	stat->config.speed = iso->speed;
+ 	stat->config.irq_interval = iso->irq_interval;
+ 	stat->n_packets = hpsb_iso_n_ready(iso);
+-	stat->overflows = atomic_read(&iso->overflows);
++	stat->overflows = ((skips & 0xFFFF) << 16) | ((overflows & 0xFFFF));
+ 	stat->xmit_cycle = iso->xmit_cycle;
+ }
+ 
+@@ -2437,6 +2440,8 @@ static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
+ 
+ 	/* reset overflow counter */
+ 	atomic_set(&iso->overflows, 0);
++	/* reset skip counter */
++	atomic_set(&iso->skips, 0);
+ 
+ 	return 0;
+ }
+@@ -2935,6 +2940,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
+ /*
+  * Export information about protocols/devices supported by this driver.
+  */
++#ifdef MODULE
+ static struct ieee1394_device_id raw1394_id_table[] = {
+ 	{
+ 	 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+@@ -2956,10 +2962,10 @@ static struct ieee1394_device_id raw1394_id_table[] = {
+ };
+ 
+ MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
++#endif /* MODULE */
+ 
+ static struct hpsb_protocol_driver raw1394_driver = {
+ 	.name = "raw1394",
+-	.id_table = raw1394_id_table,
+ };
+ 
+ /******************************************************************************/
+@@ -3004,7 +3010,6 @@ static int __init init_raw1394(void)
+ 
+ 	cdev_init(&raw1394_cdev, &raw1394_fops);
+ 	raw1394_cdev.owner = THIS_MODULE;
+-	kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
+ 	ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1);
+ 	if (ret) {
+ 		HPSB_ERR("raw1394 failed to register minor device block");
+diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
+index f53f72d..16b9d0a 100644
+--- a/drivers/ieee1394/sbp2.c
++++ b/drivers/ieee1394/sbp2.c
+@@ -615,7 +615,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
+ 		cmd->Current_SCpnt = Current_SCpnt;
+ 		list_add_tail(&cmd->list, &lu->cmd_orb_inuse);
+ 	} else
+-		SBP2_ERR("%s: no orbs available", __FUNCTION__);
++		SBP2_ERR("%s: no orbs available", __func__);
+ 	spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
+ 	return cmd;
+ }
+@@ -1294,7 +1294,7 @@ static int sbp2_set_busy_timeout(struct sbp2_lu *lu)
+ 
+ 	data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
+ 	if (hpsb_node_write(lu->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))
+-		SBP2_ERR("%s error", __FUNCTION__);
++		SBP2_ERR("%s error", __func__);
+ 	return 0;
+ }
+ 
+@@ -1985,11 +1985,8 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
+ 	lu->sdev = sdev;
+ 	sdev->allow_restart = 1;
+ 
+-	/*
+-	 * Update the dma alignment (minimum alignment requirements for
+-	 * start and end of DMA transfers) to be a sector
+-	 */
+-	blk_queue_update_dma_alignment(sdev->request_queue, 511);
++	/* SBP-2 requires quadlet alignment of the data buffers. */
++	blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
+ 
+ 	if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+ 		sdev->inquiry_len = 36;
+diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
+index bd28adf..e24772d 100644
+--- a/drivers/ieee1394/video1394.c
++++ b/drivers/ieee1394/video1394.c
+@@ -1293,6 +1293,7 @@ static const struct file_operations video1394_fops=
+ /*
+  * Export information about protocols/devices supported by this driver.
+  */
++#ifdef MODULE
+ static struct ieee1394_device_id video1394_id_table[] = {
+ 	{
+ 		.match_flags	= IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+@@ -1313,10 +1314,10 @@ static struct ieee1394_device_id video1394_id_table[] = {
+ };
+ 
+ MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
++#endif /* MODULE */
+ 
+ static struct hpsb_protocol_driver video1394_driver = {
+-	.name		= VIDEO1394_DRIVER_NAME,
+-	.id_table	= video1394_id_table,
++	.name = VIDEO1394_DRIVER_NAME,
+ };
+ 
+ 
+@@ -1504,7 +1505,6 @@ static int __init video1394_init_module (void)
+ 
+ 	cdev_init(&video1394_cdev, &video1394_fops);
+ 	video1394_cdev.owner = THIS_MODULE;
+-	kobject_set_name(&video1394_cdev.kobj, VIDEO1394_DRIVER_NAME);
+ 	ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16);
+ 	if (ret) {
+ 		PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
+diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
+index faa7ce3..a47fe64 100644
+--- a/drivers/infiniband/core/cm.c
++++ b/drivers/infiniband/core/cm.c
+@@ -467,6 +467,31 @@ static int cm_compare_private_data(u8 *private_data,
+ 	return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE);
+ }
+ 
++/*
++ * Trivial helpers to strip endian annotation and compare; the
++ * endianness doesn't actually matter since we just need a stable
++ * order for the RB tree.
++ */
++static int be32_lt(__be32 a, __be32 b)
++{
++	return (__force u32) a < (__force u32) b;
++}
++
++static int be32_gt(__be32 a, __be32 b)
++{
++	return (__force u32) a > (__force u32) b;
++}
++
++static int be64_lt(__be64 a, __be64 b)
++{
++	return (__force u64) a < (__force u64) b;
++}
++
++static int be64_gt(__be64 a, __be64 b)
++{
++	return (__force u64) a > (__force u64) b;
++}
++
+ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
+ {
+ 	struct rb_node **link = &cm.listen_service_table.rb_node;
+@@ -492,9 +517,9 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
+ 			link = &(*link)->rb_left;
+ 		else if (cm_id_priv->id.device > cur_cm_id_priv->id.device)
+ 			link = &(*link)->rb_right;
+-		else if (service_id < cur_cm_id_priv->id.service_id)
++		else if (be64_lt(service_id, cur_cm_id_priv->id.service_id))
+ 			link = &(*link)->rb_left;
+-		else if (service_id > cur_cm_id_priv->id.service_id)
++		else if (be64_gt(service_id, cur_cm_id_priv->id.service_id))
+ 			link = &(*link)->rb_right;
+ 		else if (data_cmp < 0)
+ 			link = &(*link)->rb_left;
+@@ -527,9 +552,9 @@ static struct cm_id_private * cm_find_listen(struct ib_device *device,
+ 			node = node->rb_left;
+ 		else if (device > cm_id_priv->id.device)
+ 			node = node->rb_right;
+-		else if (service_id < cm_id_priv->id.service_id)
++		else if (be64_lt(service_id, cm_id_priv->id.service_id))
+ 			node = node->rb_left;
+-		else if (service_id > cm_id_priv->id.service_id)
++		else if (be64_gt(service_id, cm_id_priv->id.service_id))
+ 			node = node->rb_right;
+ 		else if (data_cmp < 0)
+ 			node = node->rb_left;
+@@ -552,13 +577,13 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
+ 		parent = *link;
+ 		cur_timewait_info = rb_entry(parent, struct cm_timewait_info,
+ 					     remote_id_node);
+-		if (remote_id < cur_timewait_info->work.remote_id)
++		if (be32_lt(remote_id, cur_timewait_info->work.remote_id))
+ 			link = &(*link)->rb_left;
+-		else if (remote_id > cur_timewait_info->work.remote_id)
++		else if (be32_gt(remote_id, cur_timewait_info->work.remote_id))
+ 			link = &(*link)->rb_right;
+-		else if (remote_ca_guid < cur_timewait_info->remote_ca_guid)
++		else if (be64_lt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
+ 			link = &(*link)->rb_left;
+-		else if (remote_ca_guid > cur_timewait_info->remote_ca_guid)
++		else if (be64_gt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
+ 			link = &(*link)->rb_right;
+ 		else
+ 			return cur_timewait_info;
+@@ -578,13 +603,13 @@ static struct cm_timewait_info * cm_find_remote_id(__be64 remote_ca_guid,
+ 	while (node) {
+ 		timewait_info = rb_entry(node, struct cm_timewait_info,
+ 					 remote_id_node);
+-		if (remote_id < timewait_info->work.remote_id)
++		if (be32_lt(remote_id, timewait_info->work.remote_id))
+ 			node = node->rb_left;
+-		else if (remote_id > timewait_info->work.remote_id)
++		else if (be32_gt(remote_id, timewait_info->work.remote_id))
+ 			node = node->rb_right;
+-		else if (remote_ca_guid < timewait_info->remote_ca_guid)
++		else if (be64_lt(remote_ca_guid, timewait_info->remote_ca_guid))
+ 			node = node->rb_left;
+-		else if (remote_ca_guid > timewait_info->remote_ca_guid)
++		else if (be64_gt(remote_ca_guid, timewait_info->remote_ca_guid))
+ 			node = node->rb_right;
+ 		else
+ 			return timewait_info;
+@@ -605,13 +630,13 @@ static struct cm_timewait_info * cm_insert_remote_qpn(struct cm_timewait_info
+ 		parent = *link;
+ 		cur_timewait_info = rb_entry(parent, struct cm_timewait_info,
+ 					     remote_qp_node);
+-		if (remote_qpn < cur_timewait_info->remote_qpn)
++		if (be32_lt(remote_qpn, cur_timewait_info->remote_qpn))
+ 			link = &(*link)->rb_left;
+-		else if (remote_qpn > cur_timewait_info->remote_qpn)
++		else if (be32_gt(remote_qpn, cur_timewait_info->remote_qpn))
+ 			link = &(*link)->rb_right;
+-		else if (remote_ca_guid < cur_timewait_info->remote_ca_guid)
++		else if (be64_lt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
+ 			link = &(*link)->rb_left;
+-		else if (remote_ca_guid > cur_timewait_info->remote_ca_guid)
++		else if (be64_gt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
+ 			link = &(*link)->rb_right;
+ 		else
+ 			return cur_timewait_info;
+@@ -635,9 +660,9 @@ static struct cm_id_private * cm_insert_remote_sidr(struct cm_id_private
+ 		parent = *link;
+ 		cur_cm_id_priv = rb_entry(parent, struct cm_id_private,
+ 					  sidr_id_node);
+-		if (remote_id < cur_cm_id_priv->id.remote_id)
++		if (be32_lt(remote_id, cur_cm_id_priv->id.remote_id))
+ 			link = &(*link)->rb_left;
+-		else if (remote_id > cur_cm_id_priv->id.remote_id)
++		else if (be32_gt(remote_id, cur_cm_id_priv->id.remote_id))
+ 			link = &(*link)->rb_right;
+ 		else {
+ 			int cmp;
+@@ -2848,7 +2873,7 @@ static void cm_format_sidr_req(struct cm_sidr_req_msg *sidr_req_msg,
+ 	cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID,
+ 			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR));
+ 	sidr_req_msg->request_id = cm_id_priv->id.local_id;
+-	sidr_req_msg->pkey = cpu_to_be16(param->path->pkey);
++	sidr_req_msg->pkey = param->path->pkey;
+ 	sidr_req_msg->service_id = param->service_id;
+ 
+ 	if (param->private_data && param->private_data_len)
+diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
+index d81c156..671f137 100644
+--- a/drivers/infiniband/core/cma.c
++++ b/drivers/infiniband/core/cma.c
+@@ -1289,7 +1289,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
+ 	new_cm_id = rdma_create_id(listen_id->id.event_handler,
+ 				   listen_id->id.context,
+ 				   RDMA_PS_TCP);
+-	if (!new_cm_id) {
++	if (IS_ERR(new_cm_id)) {
+ 		ret = -ENOMEM;
+ 		goto out;
+ 	}
+diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
+index 06d502c..1286dc1 100644
+--- a/drivers/infiniband/core/fmr_pool.c
++++ b/drivers/infiniband/core/fmr_pool.c
+@@ -158,8 +158,7 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
+ #endif
+ 	}
+ 
+-	list_splice(&pool->dirty_list, &unmap_list);
+-	INIT_LIST_HEAD(&pool->dirty_list);
++	list_splice_init(&pool->dirty_list, &unmap_list);
+ 	pool->dirty_len = 0;
+ 
+ 	spin_unlock_irq(&pool->pool_lock);
+diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
+index 5a4b2e6..9575655 100644
+--- a/drivers/infiniband/core/sysfs.c
++++ b/drivers/infiniband/core/sysfs.c
+@@ -427,17 +427,17 @@ static struct kobj_type port_type = {
+ 	.default_attrs = port_default_attrs
+ };
+ 
+-static void ib_device_release(struct class_device *cdev)
++static void ib_device_release(struct device *device)
+ {
+-	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++	struct ib_device *dev = container_of(device, struct ib_device, dev);
+ 
+ 	kfree(dev);
+ }
+ 
+-static int ib_device_uevent(struct class_device *cdev,
++static int ib_device_uevent(struct device *device,
+ 			    struct kobj_uevent_env *env)
+ {
+-	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++	struct ib_device *dev = container_of(device, struct ib_device, dev);
+ 
+ 	if (add_uevent_var(env, "NAME=%s", dev->name))
+ 		return -ENOMEM;
+@@ -567,9 +567,10 @@ err_put:
+ 	return ret;
+ }
+ 
+-static ssize_t show_node_type(struct class_device *cdev, char *buf)
++static ssize_t show_node_type(struct device *device,
++			      struct device_attribute *attr, char *buf)
+ {
+-	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++	struct ib_device *dev = container_of(device, struct ib_device, dev);
+ 
+ 	if (!ibdev_is_alive(dev))
+ 		return -ENODEV;
+@@ -583,9 +584,10 @@ static ssize_t show_node_type(struct class_device *cdev, char *buf)
+ 	}
+ }
+ 
+-static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
++static ssize_t show_sys_image_guid(struct device *device,
++				   struct device_attribute *dev_attr, char *buf)
+ {
+-	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++	struct ib_device *dev = container_of(device, struct ib_device, dev);
+ 	struct ib_device_attr attr;
+ 	ssize_t ret;
+ 
+@@ -603,9 +605,10 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
+ 		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[3]));
+ }
+ 
+-static ssize_t show_node_guid(struct class_device *cdev, char *buf)
++static ssize_t show_node_guid(struct device *device,
++			      struct device_attribute *attr, char *buf)
+ {
+-	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++	struct ib_device *dev = container_of(device, struct ib_device, dev);
+ 
+ 	if (!ibdev_is_alive(dev))
+ 		return -ENODEV;
+@@ -617,17 +620,19 @@ static ssize_t show_node_guid(struct class_device *cdev, char *buf)
+ 		       be16_to_cpu(((__be16 *) &dev->node_guid)[3]));
+ }
+ 
+-static ssize_t show_node_desc(struct class_device *cdev, char *buf)
++static ssize_t show_node_desc(struct device *device,
++			      struct device_attribute *attr, char *buf)
+ {
+-	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++	struct ib_device *dev = container_of(device, struct ib_device, dev);
+ 
+ 	return sprintf(buf, "%.64s\n", dev->node_desc);
+ }
+ 
+-static ssize_t set_node_desc(struct class_device *cdev, const char *buf,
+-			      size_t count)
++static ssize_t set_node_desc(struct device *device,
++			     struct device_attribute *attr,
++			     const char *buf, size_t count)
+ {
+-	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++	struct ib_device *dev = container_of(device, struct ib_device, dev);
+ 	struct ib_device_modify desc = {};
+ 	int ret;
+ 
+@@ -642,44 +647,43 @@ static ssize_t set_node_desc(struct class_device *cdev, const char *buf,
+ 	return count;
+ }
+ 
+-static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
+-static CLASS_DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);
+-static CLASS_DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);
+-static CLASS_DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc,
+-			 set_node_desc);
+-
+-static struct class_device_attribute *ib_class_attributes[] = {
+-	&class_device_attr_node_type,
+-	&class_device_attr_sys_image_guid,
+-	&class_device_attr_node_guid,
+-	&class_device_attr_node_desc
++static DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
++static DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);
++static DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);
++static DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, set_node_desc);
++
++static struct device_attribute *ib_class_attributes[] = {
++	&dev_attr_node_type,
++	&dev_attr_sys_image_guid,
++	&dev_attr_node_guid,
++	&dev_attr_node_desc
+ };
+ 
+ static struct class ib_class = {
+ 	.name    = "infiniband",
+-	.release = ib_device_release,
+-	.uevent = ib_device_uevent,
++	.dev_release = ib_device_release,
++	.dev_uevent = ib_device_uevent,
+ };
+ 
+ int ib_device_register_sysfs(struct ib_device *device)
+ {
+-	struct class_device *class_dev = &device->class_dev;
++	struct device *class_dev = &device->dev;
+ 	int ret;
+ 	int i;
+ 
+ 	class_dev->class      = &ib_class;
+-	class_dev->class_data = device;
+-	class_dev->dev	      = device->dma_device;
+-	strlcpy(class_dev->class_id, device->name, BUS_ID_SIZE);
++	class_dev->driver_data = device;
++	class_dev->parent     = device->dma_device;
++	strlcpy(class_dev->bus_id, device->name, BUS_ID_SIZE);
+ 
+ 	INIT_LIST_HEAD(&device->port_list);
+ 
+-	ret = class_device_register(class_dev);
++	ret = device_register(class_dev);
+ 	if (ret)
+ 		goto err;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) {
+-		ret = class_device_create_file(class_dev, ib_class_attributes[i]);
++		ret = device_create_file(class_dev, ib_class_attributes[i]);
+ 		if (ret)
+ 			goto err_unregister;
+ 	}
+@@ -723,7 +727,7 @@ err_put:
+ 	kobject_put(&class_dev->kobj);
+ 
+ err_unregister:
+-	class_device_unregister(class_dev);
++	device_unregister(class_dev);
+ 
+ err:
+ 	return ret;
+@@ -744,7 +748,7 @@ void ib_device_unregister_sysfs(struct ib_device *device)
+ 	}
+ 
+ 	kobject_put(device->ports_parent);
+-	class_device_unregister(&device->class_dev);
++	device_unregister(&device->dev);
+ }
+ 
+ int ib_sysfs_setup(void)
+diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
+index 4291ab4..d7a6881 100644
+--- a/drivers/infiniband/core/ucm.c
++++ b/drivers/infiniband/core/ucm.c
+@@ -58,8 +58,8 @@ MODULE_LICENSE("Dual BSD/GPL");
+ 
+ struct ib_ucm_device {
+ 	int			devnum;
+-	struct cdev		dev;
+-	struct class_device	class_dev;
++	struct cdev		cdev;
++	struct device		dev;
+ 	struct ib_device	*ib_dev;
+ };
+ 
+@@ -1171,7 +1171,7 @@ static int ib_ucm_open(struct inode *inode, struct file *filp)
+ 
+ 	filp->private_data = file;
+ 	file->filp = filp;
+-	file->device = container_of(inode->i_cdev, struct ib_ucm_device, dev);
++	file->device = container_of(inode->i_cdev, struct ib_ucm_device, cdev);
+ 
+ 	return 0;
+ }
+@@ -1202,14 +1202,14 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
+ 	return 0;
+ }
+ 
+-static void ucm_release_class_dev(struct class_device *class_dev)
++static void ib_ucm_release_dev(struct device *dev)
+ {
+-	struct ib_ucm_device *dev;
++	struct ib_ucm_device *ucm_dev;
+ 
+-	dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+-	cdev_del(&dev->dev);
+-	clear_bit(dev->devnum, dev_map);
+-	kfree(dev);
++	ucm_dev = container_of(dev, struct ib_ucm_device, dev);
++	cdev_del(&ucm_dev->cdev);
++	clear_bit(ucm_dev->devnum, dev_map);
++	kfree(ucm_dev);
+ }
+ 
+ static const struct file_operations ucm_fops = {
+@@ -1220,14 +1220,15 @@ static const struct file_operations ucm_fops = {
+ 	.poll    = ib_ucm_poll,
+ };
+ 
+-static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
++static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct ib_ucm_device *dev;
++	struct ib_ucm_device *ucm_dev;
+ 
+-	dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+-	return sprintf(buf, "%s\n", dev->ib_dev->name);
++	ucm_dev = container_of(dev, struct ib_ucm_device, dev);
++	return sprintf(buf, "%s\n", ucm_dev->ib_dev->name);
+ }
+-static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
++static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+ 
+ static void ib_ucm_add_one(struct ib_device *device)
+ {
+@@ -1249,32 +1250,31 @@ static void ib_ucm_add_one(struct ib_device *device)
+ 
+ 	set_bit(ucm_dev->devnum, dev_map);
+ 
+-	cdev_init(&ucm_dev->dev, &ucm_fops);
+-	ucm_dev->dev.owner = THIS_MODULE;
+-	kobject_set_name(&ucm_dev->dev.kobj, "ucm%d", ucm_dev->devnum);
+-	if (cdev_add(&ucm_dev->dev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
++	cdev_init(&ucm_dev->cdev, &ucm_fops);
++	ucm_dev->cdev.owner = THIS_MODULE;
++	kobject_set_name(&ucm_dev->cdev.kobj, "ucm%d", ucm_dev->devnum);
++	if (cdev_add(&ucm_dev->cdev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
+ 		goto err;
+ 
+-	ucm_dev->class_dev.class = &cm_class;
+-	ucm_dev->class_dev.dev = device->dma_device;
+-	ucm_dev->class_dev.devt = ucm_dev->dev.dev;
+-	ucm_dev->class_dev.release = ucm_release_class_dev;
+-	snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
++	ucm_dev->dev.class = &cm_class;
++	ucm_dev->dev.parent = device->dma_device;
++	ucm_dev->dev.devt = ucm_dev->cdev.dev;
++	ucm_dev->dev.release = ib_ucm_release_dev;
++	snprintf(ucm_dev->dev.bus_id, BUS_ID_SIZE, "ucm%d",
+ 		 ucm_dev->devnum);
+-	if (class_device_register(&ucm_dev->class_dev))
++	if (device_register(&ucm_dev->dev))
+ 		goto err_cdev;
+ 
+-	if (class_device_create_file(&ucm_dev->class_dev,
+-				     &class_device_attr_ibdev))
+-		goto err_class;
++	if (device_create_file(&ucm_dev->dev, &dev_attr_ibdev))
++		goto err_dev;
+ 
+ 	ib_set_client_data(device, &ucm_client, ucm_dev);
+ 	return;
+ 
+-err_class:
+-	class_device_unregister(&ucm_dev->class_dev);
++err_dev:
++	device_unregister(&ucm_dev->dev);
+ err_cdev:
+-	cdev_del(&ucm_dev->dev);
++	cdev_del(&ucm_dev->cdev);
+ 	clear_bit(ucm_dev->devnum, dev_map);
+ err:
+ 	kfree(ucm_dev);
+@@ -1288,7 +1288,7 @@ static void ib_ucm_remove_one(struct ib_device *device)
+ 	if (!ucm_dev)
+ 		return;
+ 
+-	class_device_unregister(&ucm_dev->class_dev);
++	device_unregister(&ucm_dev->dev);
+ }
+ 
+ static ssize_t show_abi_version(struct class *class, char *buf)
+diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
+index 15937eb..ca4cf3a 100644
+--- a/drivers/infiniband/core/ucma.c
++++ b/drivers/infiniband/core/ucma.c
+@@ -614,7 +614,7 @@ static ssize_t ucma_query_route(struct ucma_file *file,
+ 	if (!ctx->cm_id->device)
+ 		goto out;
+ 
+-	resp.node_guid = ctx->cm_id->device->node_guid;
++	resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
+ 	resp.port_num = ctx->cm_id->port_num;
+ 	switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
+ 	case RDMA_TRANSPORT_IB:
+diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
+index 4e91510..3aa2db5 100644
+--- a/drivers/infiniband/core/user_mad.c
++++ b/drivers/infiniband/core/user_mad.c
+@@ -46,9 +46,9 @@
+ #include <linux/mutex.h>
+ #include <linux/kref.h>
+ #include <linux/compat.h>
++#include <linux/semaphore.h>
+ 
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ 
+ #include <rdma/ib_mad.h>
+ #include <rdma/ib_user_mad.h>
+@@ -88,11 +88,11 @@ enum {
+  */
+ 
+ struct ib_umad_port {
+-	struct cdev           *dev;
+-	struct class_device   *class_dev;
++	struct cdev           *cdev;
++	struct device	      *dev;
+ 
+-	struct cdev           *sm_dev;
+-	struct class_device   *sm_class_dev;
++	struct cdev           *sm_cdev;
++	struct device	      *sm_dev;
+ 	struct semaphore       sm_sem;
+ 
+ 	struct mutex	       file_mutex;
+@@ -948,27 +948,29 @@ static struct ib_client umad_client = {
+ 	.remove = ib_umad_remove_one
+ };
+ 
+-static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
++static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct ib_umad_port *port = class_get_devdata(class_dev);
++	struct ib_umad_port *port = dev_get_drvdata(dev);
+ 
+ 	if (!port)
+ 		return -ENODEV;
+ 
+ 	return sprintf(buf, "%s\n", port->ib_dev->name);
+ }
+-static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
++static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+ 
+-static ssize_t show_port(struct class_device *class_dev, char *buf)
++static ssize_t show_port(struct device *dev, struct device_attribute *attr,
++			 char *buf)
+ {
+-	struct ib_umad_port *port = class_get_devdata(class_dev);
++	struct ib_umad_port *port = dev_get_drvdata(dev);
+ 
+ 	if (!port)
+ 		return -ENODEV;
+ 
+ 	return sprintf(buf, "%d\n", port->port_num);
+ }
+-static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
++static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
+ 
+ static ssize_t show_abi_version(struct class *class, char *buf)
+ {
+@@ -994,48 +996,47 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
+ 	mutex_init(&port->file_mutex);
+ 	INIT_LIST_HEAD(&port->file_list);
+ 
+-	port->dev = cdev_alloc();
+-	if (!port->dev)
++	port->cdev = cdev_alloc();
++	if (!port->cdev)
+ 		return -1;
+-	port->dev->owner = THIS_MODULE;
+-	port->dev->ops   = &umad_fops;
+-	kobject_set_name(&port->dev->kobj, "umad%d", port->dev_num);
+-	if (cdev_add(port->dev, base_dev + port->dev_num, 1))
++	port->cdev->owner = THIS_MODULE;
++	port->cdev->ops   = &umad_fops;
++	kobject_set_name(&port->cdev->kobj, "umad%d", port->dev_num);
++	if (cdev_add(port->cdev, base_dev + port->dev_num, 1))
+ 		goto err_cdev;
+ 
+-	port->class_dev = class_device_create(umad_class, NULL, port->dev->dev,
+-					      device->dma_device,
+-					      "umad%d", port->dev_num);
+-	if (IS_ERR(port->class_dev))
++	port->dev = device_create(umad_class, device->dma_device,
++				  port->cdev->dev, "umad%d", port->dev_num);
++	if (IS_ERR(port->dev))
+ 		goto err_cdev;
+ 
+-	if (class_device_create_file(port->class_dev, &class_device_attr_ibdev))
+-		goto err_class;
+-	if (class_device_create_file(port->class_dev, &class_device_attr_port))
+-		goto err_class;
+-
+-	port->sm_dev = cdev_alloc();
+-	if (!port->sm_dev)
+-		goto err_class;
+-	port->sm_dev->owner = THIS_MODULE;
+-	port->sm_dev->ops   = &umad_sm_fops;
+-	kobject_set_name(&port->sm_dev->kobj, "issm%d", port->dev_num);
+-	if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
++	if (device_create_file(port->dev, &dev_attr_ibdev))
++		goto err_dev;
++	if (device_create_file(port->dev, &dev_attr_port))
++		goto err_dev;
++
++	port->sm_cdev = cdev_alloc();
++	if (!port->sm_cdev)
++		goto err_dev;
++	port->sm_cdev->owner = THIS_MODULE;
++	port->sm_cdev->ops   = &umad_sm_fops;
++	kobject_set_name(&port->sm_cdev->kobj, "issm%d", port->dev_num);
++	if (cdev_add(port->sm_cdev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
+ 		goto err_sm_cdev;
+ 
+-	port->sm_class_dev = class_device_create(umad_class, NULL, port->sm_dev->dev,
+-						 device->dma_device,
+-						 "issm%d", port->dev_num);
+-	if (IS_ERR(port->sm_class_dev))
++	port->sm_dev = device_create(umad_class, device->dma_device,
++				     port->sm_cdev->dev,
++				     "issm%d", port->dev_num);
++	if (IS_ERR(port->sm_dev))
+ 		goto err_sm_cdev;
+ 
+-	class_set_devdata(port->class_dev,    port);
+-	class_set_devdata(port->sm_class_dev, port);
++	dev_set_drvdata(port->dev,    port);
++	dev_set_drvdata(port->sm_dev, port);
+ 
+-	if (class_device_create_file(port->sm_class_dev, &class_device_attr_ibdev))
+-		goto err_sm_class;
+-	if (class_device_create_file(port->sm_class_dev, &class_device_attr_port))
+-		goto err_sm_class;
++	if (device_create_file(port->sm_dev, &dev_attr_ibdev))
++		goto err_sm_dev;
++	if (device_create_file(port->sm_dev, &dev_attr_port))
++		goto err_sm_dev;
+ 
+ 	spin_lock(&port_lock);
+ 	umad_port[port->dev_num] = port;
+@@ -1043,17 +1044,17 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
+ 
+ 	return 0;
+ 
+-err_sm_class:
+-	class_device_destroy(umad_class, port->sm_dev->dev);
++err_sm_dev:
++	device_destroy(umad_class, port->sm_cdev->dev);
+ 
+ err_sm_cdev:
+-	cdev_del(port->sm_dev);
++	cdev_del(port->sm_cdev);
+ 
+-err_class:
+-	class_device_destroy(umad_class, port->dev->dev);
++err_dev:
++	device_destroy(umad_class, port->cdev->dev);
+ 
+ err_cdev:
+-	cdev_del(port->dev);
++	cdev_del(port->cdev);
+ 	clear_bit(port->dev_num, dev_map);
+ 
+ 	return -1;
+@@ -1065,14 +1066,14 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
+ 	int already_dead;
+ 	int id;
+ 
+-	class_set_devdata(port->class_dev,    NULL);
+-	class_set_devdata(port->sm_class_dev, NULL);
++	dev_set_drvdata(port->dev,    NULL);
++	dev_set_drvdata(port->sm_dev, NULL);
+ 
+-	class_device_destroy(umad_class, port->dev->dev);
+-	class_device_destroy(umad_class, port->sm_dev->dev);
++	device_destroy(umad_class, port->cdev->dev);
++	device_destroy(umad_class, port->sm_cdev->dev);
+ 
+-	cdev_del(port->dev);
+-	cdev_del(port->sm_dev);
++	cdev_del(port->cdev);
++	cdev_del(port->sm_cdev);
+ 
+ 	spin_lock(&port_lock);
+ 	umad_port[port->dev_num] = NULL;
+diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
+index c75eb6c..376a57c 100644
+--- a/drivers/infiniband/core/uverbs.h
++++ b/drivers/infiniband/core/uverbs.h
+@@ -73,21 +73,21 @@ struct ib_uverbs_device {
+ 	struct kref				ref;
+ 	struct completion			comp;
+ 	int					devnum;
+-	struct cdev			       *dev;
+-	struct class_device		       *class_dev;
++	struct cdev			       *cdev;
++	struct device			       *dev;
+ 	struct ib_device		       *ib_dev;
+ 	int					num_comp_vectors;
+ };
+ 
+ struct ib_uverbs_event_file {
+ 	struct kref				ref;
+-	struct file			       *file;
+ 	struct ib_uverbs_file		       *uverbs_file;
+ 	spinlock_t				lock;
+-	int					is_async;
+ 	wait_queue_head_t			poll_wait;
+ 	struct fasync_struct		       *async_queue;
+ 	struct list_head			event_list;
++	int					is_async;
++	int					is_closed;
+ };
+ 
+ struct ib_uverbs_file {
+diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
+index 495c803..2c3bff5 100644
+--- a/drivers/infiniband/core/uverbs_cmd.c
++++ b/drivers/infiniband/core/uverbs_cmd.c
+@@ -1065,6 +1065,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
+ 	attr.srq           = srq;
+ 	attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
+ 	attr.qp_type       = cmd.qp_type;
++	attr.create_flags  = 0;
+ 
+ 	attr.cap.max_send_wr     = cmd.max_send_wr;
+ 	attr.cap.max_recv_wr     = cmd.max_recv_wr;
+@@ -1462,7 +1463,6 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
+ 		next->num_sge    = user_wr->num_sge;
+ 		next->opcode     = user_wr->opcode;
+ 		next->send_flags = user_wr->send_flags;
+-		next->imm_data   = (__be32 __force) user_wr->imm_data;
+ 
+ 		if (is_ud) {
+ 			next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
+@@ -1475,14 +1475,24 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
+ 			next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
+ 		} else {
+ 			switch (next->opcode) {
+-			case IB_WR_RDMA_WRITE:
+ 			case IB_WR_RDMA_WRITE_WITH_IMM:
++				next->ex.imm_data =
++					(__be32 __force) user_wr->ex.imm_data;
++			case IB_WR_RDMA_WRITE:
+ 			case IB_WR_RDMA_READ:
+ 				next->wr.rdma.remote_addr =
+ 					user_wr->wr.rdma.remote_addr;
+ 				next->wr.rdma.rkey        =
+ 					user_wr->wr.rdma.rkey;
+ 				break;
++			case IB_WR_SEND_WITH_IMM:
++				next->ex.imm_data =
++					(__be32 __force) user_wr->ex.imm_data;
++				break;
++			case IB_WR_SEND_WITH_INV:
++				next->ex.invalidate_rkey =
++					user_wr->ex.invalidate_rkey;
++				break;
+ 			case IB_WR_ATOMIC_CMP_AND_SWP:
+ 			case IB_WR_ATOMIC_FETCH_AND_ADD:
+ 				next->wr.atomic.remote_addr =
+diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
+index 7c2ac39..cc1afa2 100644
+--- a/drivers/infiniband/core/uverbs_main.c
++++ b/drivers/infiniband/core/uverbs_main.c
+@@ -352,7 +352,7 @@ static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
+ 	struct ib_uverbs_event *entry, *tmp;
+ 
+ 	spin_lock_irq(&file->lock);
+-	file->file = NULL;
++	file->is_closed = 1;
+ 	list_for_each_entry_safe(entry, tmp, &file->event_list, list) {
+ 		if (entry->counter)
+ 			list_del(&entry->obj_list);
+@@ -390,7 +390,7 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
+ 		return;
+ 
+ 	spin_lock_irqsave(&file->lock, flags);
+-	if (!file->file) {
++	if (file->is_closed) {
+ 		spin_unlock_irqrestore(&file->lock, flags);
+ 		return;
+ 	}
+@@ -423,7 +423,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&file->async_file->lock, flags);
+-	if (!file->async_file->file) {
++	if (!file->async_file->is_closed) {
+ 		spin_unlock_irqrestore(&file->async_file->lock, flags);
+ 		return;
+ 	}
+@@ -509,6 +509,7 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+ 	ev_file->uverbs_file = uverbs_file;
+ 	ev_file->async_queue = NULL;
+ 	ev_file->is_async    = is_async;
++	ev_file->is_closed   = 0;
+ 
+ 	*fd = get_unused_fd();
+ 	if (*fd < 0) {
+@@ -516,25 +517,18 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+ 		goto err;
+ 	}
+ 
+-	filp = get_empty_filp();
+-	if (!filp) {
+-		ret = -ENFILE;
+-		goto err_fd;
+-	}
+-
+-	ev_file->file      = filp;
+-
+ 	/*
+ 	 * fops_get() can't fail here, because we're coming from a
+ 	 * system call on a uverbs file, which will already have a
+ 	 * module reference.
+ 	 */
+-	filp->f_op 	   = fops_get(&uverbs_event_fops);
+-	filp->f_path.mnt 	   = mntget(uverbs_event_mnt);
+-	filp->f_path.dentry 	   = dget(uverbs_event_mnt->mnt_root);
+-	filp->f_mapping    = filp->f_path.dentry->d_inode->i_mapping;
+-	filp->f_flags      = O_RDONLY;
+-	filp->f_mode       = FMODE_READ;
++	filp = alloc_file(uverbs_event_mnt, dget(uverbs_event_mnt->mnt_root),
++			  FMODE_READ, fops_get(&uverbs_event_fops));
++	if (!filp) {
++		ret = -ENFILE;
++		goto err_fd;
++	}
++
+ 	filp->private_data = ev_file;
+ 
+ 	return filp;
+@@ -696,27 +690,29 @@ static struct ib_client uverbs_client = {
+ 	.remove = ib_uverbs_remove_one
+ };
+ 
+-static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
++static ssize_t show_ibdev(struct device *device, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct ib_uverbs_device *dev = class_get_devdata(class_dev);
++	struct ib_uverbs_device *dev = dev_get_drvdata(device);
+ 
+ 	if (!dev)
+ 		return -ENODEV;
+ 
+ 	return sprintf(buf, "%s\n", dev->ib_dev->name);
+ }
+-static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
++static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+ 
+-static ssize_t show_dev_abi_version(struct class_device *class_dev, char *buf)
++static ssize_t show_dev_abi_version(struct device *device,
++				    struct device_attribute *attr, char *buf)
+ {
+-	struct ib_uverbs_device *dev = class_get_devdata(class_dev);
++	struct ib_uverbs_device *dev = dev_get_drvdata(device);
+ 
+ 	if (!dev)
+ 		return -ENODEV;
+ 
+ 	return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
+ }
+-static CLASS_DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
++static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
+ 
+ static ssize_t show_abi_version(struct class *class, char *buf)
+ {
+@@ -750,27 +746,26 @@ static void ib_uverbs_add_one(struct ib_device *device)
+ 	uverbs_dev->ib_dev           = device;
+ 	uverbs_dev->num_comp_vectors = device->num_comp_vectors;
+ 
+-	uverbs_dev->dev = cdev_alloc();
+-	if (!uverbs_dev->dev)
++	uverbs_dev->cdev = cdev_alloc();
++	if (!uverbs_dev->cdev)
+ 		goto err;
+-	uverbs_dev->dev->owner = THIS_MODULE;
+-	uverbs_dev->dev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
+-	kobject_set_name(&uverbs_dev->dev->kobj, "uverbs%d", uverbs_dev->devnum);
+-	if (cdev_add(uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
++	uverbs_dev->cdev->owner = THIS_MODULE;
++	uverbs_dev->cdev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
++	kobject_set_name(&uverbs_dev->cdev->kobj, "uverbs%d", uverbs_dev->devnum);
++	if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+ 		goto err_cdev;
+ 
+-	uverbs_dev->class_dev = class_device_create(uverbs_class, NULL,
+-						    uverbs_dev->dev->dev,
+-						    device->dma_device,
+-						    "uverbs%d", uverbs_dev->devnum);
+-	if (IS_ERR(uverbs_dev->class_dev))
++	uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
++					uverbs_dev->cdev->dev,
++					"uverbs%d", uverbs_dev->devnum);
++	if (IS_ERR(uverbs_dev->dev))
+ 		goto err_cdev;
+ 
+-	class_set_devdata(uverbs_dev->class_dev, uverbs_dev);
++	dev_set_drvdata(uverbs_dev->dev, uverbs_dev);
+ 
+-	if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_ibdev))
++	if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev))
+ 		goto err_class;
+-	if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_abi_version))
++	if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
+ 		goto err_class;
+ 
+ 	spin_lock(&map_lock);
+@@ -782,10 +777,10 @@ static void ib_uverbs_add_one(struct ib_device *device)
+ 	return;
+ 
+ err_class:
+-	class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
++	device_destroy(uverbs_class, uverbs_dev->cdev->dev);
+ 
+ err_cdev:
+-	cdev_del(uverbs_dev->dev);
++	cdev_del(uverbs_dev->cdev);
+ 	clear_bit(uverbs_dev->devnum, dev_map);
+ 
+ err:
+@@ -802,9 +797,9 @@ static void ib_uverbs_remove_one(struct ib_device *device)
+ 	if (!uverbs_dev)
+ 		return;
+ 
+-	class_set_devdata(uverbs_dev->class_dev, NULL);
+-	class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
+-	cdev_del(uverbs_dev->dev);
++	dev_set_drvdata(uverbs_dev->dev, NULL);
++	device_destroy(uverbs_class, uverbs_dev->cdev->dev);
++	cdev_del(uverbs_dev->cdev);
+ 
+ 	spin_lock(&map_lock);
+ 	dev_table[uverbs_dev->devnum] = NULL;
+diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
+index 86ed8af..0504208 100644
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -248,7 +248,9 @@ int ib_modify_srq(struct ib_srq *srq,
+ 		  struct ib_srq_attr *srq_attr,
+ 		  enum ib_srq_attr_mask srq_attr_mask)
+ {
+-	return srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL);
++	return srq->device->modify_srq ?
++		srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL) :
++		-ENOSYS;
+ }
+ EXPORT_SYMBOL(ib_modify_srq);
+ 
+@@ -628,6 +630,13 @@ struct ib_cq *ib_create_cq(struct ib_device *device,
+ }
+ EXPORT_SYMBOL(ib_create_cq);
+ 
++int ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
++{
++	return cq->device->modify_cq ?
++		cq->device->modify_cq(cq, cq_count, cq_period) : -ENOSYS;
++}
++EXPORT_SYMBOL(ib_modify_cq);
++
+ int ib_destroy_cq(struct ib_cq *cq)
+ {
+ 	if (atomic_read(&cq->usecnt))
+@@ -672,6 +681,9 @@ struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd,
+ {
+ 	struct ib_mr *mr;
+ 
++	if (!pd->device->reg_phys_mr)
++		return ERR_PTR(-ENOSYS);
++
+ 	mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf,
+ 				     mr_access_flags, iova_start);
+ 
+diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
+index f283a9f..113f3c0 100644
+--- a/drivers/infiniband/hw/amso1100/c2.c
++++ b/drivers/infiniband/hw/amso1100/c2.c
+@@ -130,10 +130,10 @@ static int c2_tx_ring_alloc(struct c2_ring *tx_ring, void *vaddr,
+ 		tx_desc->status = 0;
+ 
+ 		/* Set TXP_HTXD_UNINIT */
+-		__raw_writeq(cpu_to_be64(0x1122334455667788ULL),
++		__raw_writeq((__force u64) cpu_to_be64(0x1122334455667788ULL),
+ 			     (void __iomem *) txp_desc + C2_TXP_ADDR);
+ 		__raw_writew(0, (void __iomem *) txp_desc + C2_TXP_LEN);
+-		__raw_writew(cpu_to_be16(TXP_HTXD_UNINIT),
++		__raw_writew((__force u16) cpu_to_be16(TXP_HTXD_UNINIT),
+ 			     (void __iomem *) txp_desc + C2_TXP_FLAGS);
+ 
+ 		elem->skb = NULL;
+@@ -179,13 +179,13 @@ static int c2_rx_ring_alloc(struct c2_ring *rx_ring, void *vaddr,
+ 		rx_desc->status = 0;
+ 
+ 		/* Set RXP_HRXD_UNINIT */
+-		__raw_writew(cpu_to_be16(RXP_HRXD_OK),
++		__raw_writew((__force u16) cpu_to_be16(RXP_HRXD_OK),
+ 		       (void __iomem *) rxp_desc + C2_RXP_STATUS);
+ 		__raw_writew(0, (void __iomem *) rxp_desc + C2_RXP_COUNT);
+ 		__raw_writew(0, (void __iomem *) rxp_desc + C2_RXP_LEN);
+-		__raw_writeq(cpu_to_be64(0x99aabbccddeeffULL),
++		__raw_writeq((__force u64) cpu_to_be64(0x99aabbccddeeffULL),
+ 			     (void __iomem *) rxp_desc + C2_RXP_ADDR);
+-		__raw_writew(cpu_to_be16(RXP_HRXD_UNINIT),
++		__raw_writew((__force u16) cpu_to_be16(RXP_HRXD_UNINIT),
+ 			     (void __iomem *) rxp_desc + C2_RXP_FLAGS);
+ 
+ 		elem->skb = NULL;
+@@ -239,10 +239,11 @@ static inline int c2_rx_alloc(struct c2_port *c2_port, struct c2_element *elem)
+ 	rxp_hdr->flags = RXP_HRXD_READY;
+ 
+ 	__raw_writew(0, elem->hw_desc + C2_RXP_STATUS);
+-	__raw_writew(cpu_to_be16((u16) maplen - sizeof(*rxp_hdr)),
++	__raw_writew((__force u16) cpu_to_be16((u16) maplen - sizeof(*rxp_hdr)),
+ 		     elem->hw_desc + C2_RXP_LEN);
+-	__raw_writeq(cpu_to_be64(mapaddr), elem->hw_desc + C2_RXP_ADDR);
+-	__raw_writew(cpu_to_be16(RXP_HRXD_READY), elem->hw_desc + C2_RXP_FLAGS);
++	__raw_writeq((__force u64) cpu_to_be64(mapaddr), elem->hw_desc + C2_RXP_ADDR);
++	__raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY),
++		     elem->hw_desc + C2_RXP_FLAGS);
+ 
+ 	elem->skb = skb;
+ 	elem->mapaddr = mapaddr;
+@@ -290,9 +291,9 @@ static void c2_rx_clean(struct c2_port *c2_port)
+ 		__raw_writew(0, elem->hw_desc + C2_RXP_STATUS);
+ 		__raw_writew(0, elem->hw_desc + C2_RXP_COUNT);
+ 		__raw_writew(0, elem->hw_desc + C2_RXP_LEN);
+-		__raw_writeq(cpu_to_be64(0x99aabbccddeeffULL),
++		__raw_writeq((__force u64) cpu_to_be64(0x99aabbccddeeffULL),
+ 			     elem->hw_desc + C2_RXP_ADDR);
+-		__raw_writew(cpu_to_be16(RXP_HRXD_UNINIT),
++		__raw_writew((__force u16) cpu_to_be16(RXP_HRXD_UNINIT),
+ 			     elem->hw_desc + C2_RXP_FLAGS);
+ 
+ 		if (elem->skb) {
+@@ -346,16 +347,16 @@ static void c2_tx_clean(struct c2_port *c2_port)
+ 					     elem->hw_desc + C2_TXP_LEN);
+ 				__raw_writeq(0,
+ 					     elem->hw_desc + C2_TXP_ADDR);
+-				__raw_writew(cpu_to_be16(TXP_HTXD_DONE),
++				__raw_writew((__force u16) cpu_to_be16(TXP_HTXD_DONE),
+ 					     elem->hw_desc + C2_TXP_FLAGS);
+ 				c2_port->netstats.tx_dropped++;
+ 				break;
+ 			} else {
+ 				__raw_writew(0,
+ 					     elem->hw_desc + C2_TXP_LEN);
+-				__raw_writeq(cpu_to_be64(0x1122334455667788ULL),
++				__raw_writeq((__force u64) cpu_to_be64(0x1122334455667788ULL),
+ 					     elem->hw_desc + C2_TXP_ADDR);
+-				__raw_writew(cpu_to_be16(TXP_HTXD_UNINIT),
++				__raw_writew((__force u16) cpu_to_be16(TXP_HTXD_UNINIT),
+ 					     elem->hw_desc + C2_TXP_FLAGS);
+ 			}
+ 
+@@ -390,7 +391,7 @@ static void c2_tx_interrupt(struct net_device *netdev)
+ 	for (elem = tx_ring->to_clean; elem != tx_ring->to_use;
+ 	     elem = elem->next) {
+ 		txp_htxd.flags =
+-		    be16_to_cpu(readw(elem->hw_desc + C2_TXP_FLAGS));
++		    be16_to_cpu((__force __be16) readw(elem->hw_desc + C2_TXP_FLAGS));
+ 
+ 		if (txp_htxd.flags != TXP_HTXD_DONE)
+ 			break;
+@@ -398,7 +399,7 @@ static void c2_tx_interrupt(struct net_device *netdev)
+ 		if (netif_msg_tx_done(c2_port)) {
+ 			/* PCI reads are expensive in fast path */
+ 			txp_htxd.len =
+-			    be16_to_cpu(readw(elem->hw_desc + C2_TXP_LEN));
++			    be16_to_cpu((__force __be16) readw(elem->hw_desc + C2_TXP_LEN));
+ 			pr_debug("%s: tx done slot %3Zu status 0x%x len "
+ 				"%5u bytes\n",
+ 				netdev->name, elem - tx_ring->start,
+@@ -448,10 +449,12 @@ static void c2_rx_error(struct c2_port *c2_port, struct c2_element *elem)
+ 	/* Write the descriptor to the adapter's rx ring */
+ 	__raw_writew(0, elem->hw_desc + C2_RXP_STATUS);
+ 	__raw_writew(0, elem->hw_desc + C2_RXP_COUNT);
+-	__raw_writew(cpu_to_be16((u16) elem->maplen - sizeof(*rxp_hdr)),
++	__raw_writew((__force u16) cpu_to_be16((u16) elem->maplen - sizeof(*rxp_hdr)),
+ 		     elem->hw_desc + C2_RXP_LEN);
+-	__raw_writeq(cpu_to_be64(elem->mapaddr), elem->hw_desc + C2_RXP_ADDR);
+-	__raw_writew(cpu_to_be16(RXP_HRXD_READY), elem->hw_desc + C2_RXP_FLAGS);
++	__raw_writeq((__force u64) cpu_to_be64(elem->mapaddr),
++		     elem->hw_desc + C2_RXP_ADDR);
++	__raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY),
++		     elem->hw_desc + C2_RXP_FLAGS);
+ 
+ 	pr_debug("packet dropped\n");
+ 	c2_port->netstats.rx_dropped++;
+@@ -653,7 +656,7 @@ static int c2_up(struct net_device *netdev)
+ 	     i++, elem++) {
+ 		rxp_hdr = (struct c2_rxp_hdr *) elem->skb->data;
+ 		rxp_hdr->flags = 0;
+-		__raw_writew(cpu_to_be16(RXP_HRXD_READY),
++		__raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY),
+ 			     elem->hw_desc + C2_RXP_FLAGS);
+ 	}
+ 
+@@ -787,9 +790,12 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 	elem->maplen = maplen;
+ 
+ 	/* Tell HW to xmit */
+-	__raw_writeq(cpu_to_be64(mapaddr), elem->hw_desc + C2_TXP_ADDR);
+-	__raw_writew(cpu_to_be16(maplen), elem->hw_desc + C2_TXP_LEN);
+-	__raw_writew(cpu_to_be16(TXP_HTXD_READY), elem->hw_desc + C2_TXP_FLAGS);
++	__raw_writeq((__force u64) cpu_to_be64(mapaddr),
++		     elem->hw_desc + C2_TXP_ADDR);
++	__raw_writew((__force u16) cpu_to_be16(maplen),
++		     elem->hw_desc + C2_TXP_LEN);
++	__raw_writew((__force u16) cpu_to_be16(TXP_HTXD_READY),
++		     elem->hw_desc + C2_TXP_FLAGS);
+ 
+ 	c2_port->netstats.tx_packets++;
+ 	c2_port->netstats.tx_bytes += maplen;
+@@ -810,11 +816,11 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 			elem->maplen = maplen;
+ 
+ 			/* Tell HW to xmit */
+-			__raw_writeq(cpu_to_be64(mapaddr),
++			__raw_writeq((__force u64) cpu_to_be64(mapaddr),
+ 				     elem->hw_desc + C2_TXP_ADDR);
+-			__raw_writew(cpu_to_be16(maplen),
++			__raw_writew((__force u16) cpu_to_be16(maplen),
+ 				     elem->hw_desc + C2_TXP_LEN);
+-			__raw_writew(cpu_to_be16(TXP_HTXD_READY),
++			__raw_writew((__force u16) cpu_to_be16(TXP_HTXD_READY),
+ 				     elem->hw_desc + C2_TXP_FLAGS);
+ 
+ 			c2_port->netstats.tx_packets++;
+@@ -1005,7 +1011,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ 	/* Remap the adapter PCI registers in BAR4 */
+ 	mmio_regs = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET,
+ 				    sizeof(struct c2_adapter_pci_regs));
+-	if (mmio_regs == 0UL) {
++	if (!mmio_regs) {
+ 		printk(KERN_ERR PFX
+ 			"Unable to remap adapter PCI registers in BAR4\n");
+ 		ret = -EIO;
+@@ -1029,10 +1035,10 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ 	}
+ 
+ 	/* Validate the adapter version */
+-	if (be32_to_cpu(readl(mmio_regs + C2_REGS_VERS)) != C2_VERSION) {
++	if (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_VERS)) != C2_VERSION) {
+ 		printk(KERN_ERR PFX "Version mismatch "
+ 			"[fw=%u, c2=%u], Adapter not claimed\n",
+-			be32_to_cpu(readl(mmio_regs + C2_REGS_VERS)),
++			be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_VERS)),
+ 			C2_VERSION);
+ 		ret = -EINVAL;
+ 		iounmap(mmio_regs);
+@@ -1040,12 +1046,12 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ 	}
+ 
+ 	/* Validate the adapter IVN */
+-	if (be32_to_cpu(readl(mmio_regs + C2_REGS_IVN)) != C2_IVN) {
++	if (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_IVN)) != C2_IVN) {
+ 		printk(KERN_ERR PFX "Downlevel FIrmware level. You should be using "
+ 		       "the OpenIB device support kit. "
+ 		       "[fw=0x%x, c2=0x%x], Adapter not claimed\n",
+-			be32_to_cpu(readl(mmio_regs + C2_REGS_IVN)),
+-			C2_IVN);
++		       be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_IVN)),
++		       C2_IVN);
+ 		ret = -EINVAL;
+ 		iounmap(mmio_regs);
+ 		goto bail2;
+@@ -1068,7 +1074,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ 
+ 	/* Get the last RX index */
+ 	c2dev->cur_rx =
+-	    (be32_to_cpu(readl(mmio_regs + C2_REGS_HRX_CUR)) -
++	    (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_HRX_CUR)) -
+ 	     0xffffc000) / sizeof(struct c2_rxp_desc);
+ 
+ 	/* Request an interrupt line for the driver */
+@@ -1090,7 +1096,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ 	}
+ 
+ 	/* Save off the actual size prior to unmapping mmio_regs */
+-	kva_map_size = be32_to_cpu(readl(mmio_regs + C2_REGS_PCI_WINSIZE));
++	kva_map_size = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_PCI_WINSIZE));
+ 
+ 	/* Unmap the adapter PCI registers in BAR4 */
+ 	iounmap(mmio_regs);
+@@ -1109,7 +1115,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ 	/* Remap the adapter HRXDQ PA space to kernel VA space */
+ 	c2dev->mmio_rxp_ring = ioremap_nocache(reg4_start + C2_RXP_HRXDQ_OFFSET,
+ 					       C2_RXP_HRXDQ_SIZE);
+-	if (c2dev->mmio_rxp_ring == 0UL) {
++	if (!c2dev->mmio_rxp_ring) {
+ 		printk(KERN_ERR PFX "Unable to remap MMIO HRXDQ region\n");
+ 		ret = -EIO;
+ 		goto bail6;
+@@ -1118,7 +1124,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ 	/* Remap the adapter HTXDQ PA space to kernel VA space */
+ 	c2dev->mmio_txp_ring = ioremap_nocache(reg4_start + C2_TXP_HTXDQ_OFFSET,
+ 					       C2_TXP_HTXDQ_SIZE);
+-	if (c2dev->mmio_txp_ring == 0UL) {
++	if (!c2dev->mmio_txp_ring) {
+ 		printk(KERN_ERR PFX "Unable to remap MMIO HTXDQ region\n");
+ 		ret = -EIO;
+ 		goto bail7;
+@@ -1129,7 +1135,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ 
+ 	/* Remap the PCI registers in adapter BAR0 to kernel VA space */
+ 	c2dev->regs = ioremap_nocache(reg0_start, reg0_len);
+-	if (c2dev->regs == 0UL) {
++	if (!c2dev->regs) {
+ 		printk(KERN_ERR PFX "Unable to remap BAR0\n");
+ 		ret = -EIO;
+ 		goto bail8;
+@@ -1139,7 +1145,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ 	c2dev->pa = reg4_start + C2_PCI_REGS_OFFSET;
+ 	c2dev->kva = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET,
+ 				     kva_map_size);
+-	if (c2dev->kva == 0UL) {
++	if (!c2dev->kva) {
+ 		printk(KERN_ERR PFX "Unable to remap BAR4\n");
+ 		ret = -EIO;
+ 		goto bail9;
+diff --git a/drivers/infiniband/hw/amso1100/c2.h b/drivers/infiniband/hw/amso1100/c2.h
+index fa58200..d12a24a 100644
+--- a/drivers/infiniband/hw/amso1100/c2.h
++++ b/drivers/infiniband/hw/amso1100/c2.h
+@@ -40,7 +40,6 @@
+ #include <linux/pci.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/idr.h>
+-#include <asm/semaphore.h>
+ 
+ #include "c2_provider.h"
+ #include "c2_mq.h"
+@@ -346,7 +345,7 @@ struct c2_dev {
+ 	//	spinlock_t aeq_lock;
+ 	//	spinlock_t rnic_lock;
+ 
+-	u16 *hint_count;
++	__be16 *hint_count;
+ 	dma_addr_t hint_count_dma;
+ 	u16 hints_read;
+ 
+@@ -425,10 +424,10 @@ static inline void __raw_writeq(u64 val, void __iomem * addr)
+ #endif
+ 
+ #define C2_SET_CUR_RX(c2dev, cur_rx) \
+-	__raw_writel(cpu_to_be32(cur_rx), c2dev->mmio_txp_ring + 4092)
++	__raw_writel((__force u32) cpu_to_be32(cur_rx), c2dev->mmio_txp_ring + 4092)
+ 
+ #define C2_GET_CUR_RX(c2dev) \
+-	be32_to_cpu(readl(c2dev->mmio_txp_ring + 4092))
++	be32_to_cpu((__force __be32) readl(c2dev->mmio_txp_ring + 4092))
+ 
+ static inline struct c2_dev *to_c2dev(struct ib_device *ibdev)
+ {
+@@ -485,8 +484,8 @@ extern void c2_unregister_device(struct c2_dev *c2dev);
+ extern int c2_rnic_init(struct c2_dev *c2dev);
+ extern void c2_rnic_term(struct c2_dev *c2dev);
+ extern void c2_rnic_interrupt(struct c2_dev *c2dev);
+-extern int c2_del_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask);
+-extern int c2_add_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask);
++extern int c2_del_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask);
++extern int c2_add_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask);
+ 
+ /* QPs */
+ extern int c2_alloc_qp(struct c2_dev *c2dev, struct c2_pd *pd,
+@@ -545,7 +544,7 @@ extern void c2_ae_event(struct c2_dev *c2dev, u32 mq_index);
+ extern int c2_init_mqsp_pool(struct c2_dev *c2dev, gfp_t gfp_mask,
+ 			     struct sp_chunk **root);
+ extern void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root);
+-extern u16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
+-			  dma_addr_t *dma_addr, gfp_t gfp_mask);
+-extern void c2_free_mqsp(u16 * mqsp);
++extern __be16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
++			     dma_addr_t *dma_addr, gfp_t gfp_mask);
++extern void c2_free_mqsp(__be16* mqsp);
+ #endif
+diff --git a/drivers/infiniband/hw/amso1100/c2_ae.c b/drivers/infiniband/hw/amso1100/c2_ae.c
+index a31439b..62af742 100644
+--- a/drivers/infiniband/hw/amso1100/c2_ae.c
++++ b/drivers/infiniband/hw/amso1100/c2_ae.c
+@@ -61,7 +61,7 @@ static int c2_convert_cm_status(u32 c2_status)
+ 	default:
+ 		printk(KERN_ERR PFX
+ 		       "%s - Unable to convert CM status: %d\n",
+-		       __FUNCTION__, c2_status);
++		       __func__, c2_status);
+ 		return -EIO;
+ 	}
+ }
+@@ -193,9 +193,9 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
+ 		pr_debug("%s: event = %s, user_context=%llx, "
+ 			"resource_type=%x, "
+ 			"resource=%x, qp_state=%s\n",
+-			__FUNCTION__,
++			__func__,
+ 			to_event_str(event_id),
+-			(unsigned long long) be64_to_cpu(wr->ae.ae_generic.user_context),
++			(unsigned long long) wr->ae.ae_generic.user_context,
+ 			be32_to_cpu(wr->ae.ae_generic.resource_type),
+ 			be32_to_cpu(wr->ae.ae_generic.resource),
+ 			to_qp_state_str(be32_to_cpu(wr->ae.ae_generic.qp_state)));
+@@ -259,7 +259,7 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
+ 			BUG_ON(1);
+ 			pr_debug("%s:%d Unexpected event_id=%d on QP=%p, "
+ 				"CM_ID=%p\n",
+-				__FUNCTION__, __LINE__,
++				__func__, __LINE__,
+ 				event_id, qp, cm_id);
+ 			break;
+ 		}
+@@ -276,7 +276,7 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
+ 		pr_debug("C2_RES_IND_EP event_id=%d\n", event_id);
+ 		if (event_id != CCAE_CONNECTION_REQUEST) {
+ 			pr_debug("%s: Invalid event_id: %d\n",
+-				__FUNCTION__, event_id);
++				__func__, event_id);
+ 			break;
+ 		}
+ 		cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
+diff --git a/drivers/infiniband/hw/amso1100/c2_alloc.c b/drivers/infiniband/hw/amso1100/c2_alloc.c
+index 0315f99..e911016 100644
+--- a/drivers/infiniband/hw/amso1100/c2_alloc.c
++++ b/drivers/infiniband/hw/amso1100/c2_alloc.c
+@@ -87,8 +87,8 @@ void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root)
+ 	}
+ }
+ 
+-u16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
+-		   dma_addr_t *dma_addr, gfp_t gfp_mask)
++__be16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
++		      dma_addr_t *dma_addr, gfp_t gfp_mask)
+ {
+ 	u16 mqsp;
+ 
+@@ -113,14 +113,14 @@ u16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
+ 		*dma_addr = head->dma_addr +
+ 			    ((unsigned long) &(head->shared_ptr[mqsp]) -
+ 			     (unsigned long) head);
+-		pr_debug("%s addr %p dma_addr %llx\n", __FUNCTION__,
++		pr_debug("%s addr %p dma_addr %llx\n", __func__,
+ 			 &(head->shared_ptr[mqsp]), (unsigned long long) *dma_addr);
+-		return &(head->shared_ptr[mqsp]);
++		return (__force __be16 *) &(head->shared_ptr[mqsp]);
+ 	}
+ 	return NULL;
+ }
+ 
+-void c2_free_mqsp(u16 * mqsp)
++void c2_free_mqsp(__be16 *mqsp)
+ {
+ 	struct sp_chunk *head;
+ 	u16 idx;
+@@ -129,7 +129,7 @@ void c2_free_mqsp(u16 * mqsp)
+ 	head = (struct sp_chunk *) ((unsigned long) mqsp & PAGE_MASK);
+ 
+ 	/* Link head to new mqsp */
+-	*mqsp = head->head;
++	*mqsp = (__force __be16) head->head;
+ 
+ 	/* Compute the shared_ptr index */
+ 	idx = ((unsigned long) mqsp & ~PAGE_MASK) >> 1;
+diff --git a/drivers/infiniband/hw/amso1100/c2_cq.c b/drivers/infiniband/hw/amso1100/c2_cq.c
+index d2b3366..bb17cce 100644
+--- a/drivers/infiniband/hw/amso1100/c2_cq.c
++++ b/drivers/infiniband/hw/amso1100/c2_cq.c
+@@ -422,8 +422,8 @@ void c2_free_cq(struct c2_dev *c2dev, struct c2_cq *cq)
+ 		goto bail1;
+ 
+ 	reply = (struct c2wr_cq_destroy_rep *) (unsigned long) (vq_req->reply_msg);
+-
+-	vq_repbuf_free(c2dev, reply);
++	if (reply)
++		vq_repbuf_free(c2dev, reply);
+       bail1:
+ 	vq_req_free(c2dev, vq_req);
+       bail0:
+diff --git a/drivers/infiniband/hw/amso1100/c2_intr.c b/drivers/infiniband/hw/amso1100/c2_intr.c
+index 0d0bc33..3b50954 100644
+--- a/drivers/infiniband/hw/amso1100/c2_intr.c
++++ b/drivers/infiniband/hw/amso1100/c2_intr.c
+@@ -174,7 +174,11 @@ static void handle_vq(struct c2_dev *c2dev, u32 mq_index)
+ 		return;
+ 	}
+ 
+-	err = c2_errno(reply_msg);
++	if (reply_msg)
++		err = c2_errno(reply_msg);
++	else
++		err = -ENOMEM;
++
+ 	if (!err) switch (req->event) {
+ 	case IW_CM_EVENT_ESTABLISHED:
+ 		c2_set_qp_state(req->qp,
+diff --git a/drivers/infiniband/hw/amso1100/c2_mm.c b/drivers/infiniband/hw/amso1100/c2_mm.c
+index 1e4f464..b506fe2 100644
+--- a/drivers/infiniband/hw/amso1100/c2_mm.c
++++ b/drivers/infiniband/hw/amso1100/c2_mm.c
+@@ -45,7 +45,7 @@
+  *	  Reply buffer _is_ freed by this function.
+  */
+ static int
+-send_pbl_messages(struct c2_dev *c2dev, u32 stag_index,
++send_pbl_messages(struct c2_dev *c2dev, __be32 stag_index,
+ 		  unsigned long va, u32 pbl_depth,
+ 		  struct c2_vq_req *vq_req, int pbl_type)
+ {
+diff --git a/drivers/infiniband/hw/amso1100/c2_mq.c b/drivers/infiniband/hw/amso1100/c2_mq.c
+index b88a755..0cddc49 100644
+--- a/drivers/infiniband/hw/amso1100/c2_mq.c
++++ b/drivers/infiniband/hw/amso1100/c2_mq.c
+@@ -64,7 +64,7 @@ void c2_mq_produce(struct c2_mq *q)
+ 		q->priv = (q->priv + 1) % q->q_size;
+ 		q->hint_count++;
+ 		/* Update peer's offset. */
+-		__raw_writew(cpu_to_be16(q->priv), &q->peer->shared);
++		__raw_writew((__force u16) cpu_to_be16(q->priv), &q->peer->shared);
+ 	}
+ }
+ 
+@@ -105,7 +105,7 @@ void c2_mq_free(struct c2_mq *q)
+ #endif
+ 		q->priv = (q->priv + 1) % q->q_size;
+ 		/* Update peer's offset. */
+-		__raw_writew(cpu_to_be16(q->priv), &q->peer->shared);
++		__raw_writew((__force u16) cpu_to_be16(q->priv), &q->peer->shared);
+ 	}
+ }
+ 
+diff --git a/drivers/infiniband/hw/amso1100/c2_mq.h b/drivers/infiniband/hw/amso1100/c2_mq.h
+index 9185bbb..acede00 100644
+--- a/drivers/infiniband/hw/amso1100/c2_mq.h
++++ b/drivers/infiniband/hw/amso1100/c2_mq.h
+@@ -75,7 +75,7 @@ struct c2_mq {
+ 	u16 hint_count;
+ 	u16 priv;
+ 	struct c2_mq_shared __iomem *peer;
+-	u16 *shared;
++	__be16 *shared;
+ 	dma_addr_t shared_dma;
+ 	u32 q_size;
+ 	u32 msg_size;
+diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
+index 7a6cece..6af2c0f 100644
+--- a/drivers/infiniband/hw/amso1100/c2_provider.c
++++ b/drivers/infiniband/hw/amso1100/c2_provider.c
+@@ -67,7 +67,7 @@ static int c2_query_device(struct ib_device *ibdev,
+ {
+ 	struct c2_dev *c2dev = to_c2dev(ibdev);
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	*props = c2dev->props;
+ 	return 0;
+@@ -76,7 +76,7 @@ static int c2_query_device(struct ib_device *ibdev,
+ static int c2_query_port(struct ib_device *ibdev,
+ 			 u8 port, struct ib_port_attr *props)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	props->max_mtu = IB_MTU_4096;
+ 	props->lid = 0;
+@@ -102,14 +102,14 @@ static int c2_modify_port(struct ib_device *ibdev,
+ 			  u8 port, int port_modify_mask,
+ 			  struct ib_port_modify *props)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return 0;
+ }
+ 
+ static int c2_query_pkey(struct ib_device *ibdev,
+ 			 u8 port, u16 index, u16 * pkey)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	*pkey = 0;
+ 	return 0;
+ }
+@@ -119,7 +119,7 @@ static int c2_query_gid(struct ib_device *ibdev, u8 port,
+ {
+ 	struct c2_dev *c2dev = to_c2dev(ibdev);
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	memset(&(gid->raw[0]), 0, sizeof(gid->raw));
+ 	memcpy(&(gid->raw[0]), c2dev->pseudo_netdev->dev_addr, 6);
+ 
+@@ -134,7 +134,7 @@ static struct ib_ucontext *c2_alloc_ucontext(struct ib_device *ibdev,
+ {
+ 	struct c2_ucontext *context;
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	context = kmalloc(sizeof(*context), GFP_KERNEL);
+ 	if (!context)
+ 		return ERR_PTR(-ENOMEM);
+@@ -144,14 +144,14 @@ static struct ib_ucontext *c2_alloc_ucontext(struct ib_device *ibdev,
+ 
+ static int c2_dealloc_ucontext(struct ib_ucontext *context)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	kfree(context);
+ 	return 0;
+ }
+ 
+ static int c2_mmap_uar(struct ib_ucontext *context, struct vm_area_struct *vma)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return -ENOSYS;
+ }
+ 
+@@ -162,7 +162,7 @@ static struct ib_pd *c2_alloc_pd(struct ib_device *ibdev,
+ 	struct c2_pd *pd;
+ 	int err;
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	pd = kmalloc(sizeof(*pd), GFP_KERNEL);
+ 	if (!pd)
+@@ -187,7 +187,7 @@ static struct ib_pd *c2_alloc_pd(struct ib_device *ibdev,
+ 
+ static int c2_dealloc_pd(struct ib_pd *pd)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	c2_pd_free(to_c2dev(pd->device), to_c2pd(pd));
+ 	kfree(pd);
+ 
+@@ -196,13 +196,13 @@ static int c2_dealloc_pd(struct ib_pd *pd)
+ 
+ static struct ib_ah *c2_ah_create(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return ERR_PTR(-ENOSYS);
+ }
+ 
+ static int c2_ah_destroy(struct ib_ah *ah)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return -ENOSYS;
+ }
+ 
+@@ -230,7 +230,7 @@ struct ib_qp *c2_get_qp(struct ib_device *device, int qpn)
+ 
+ 	qp = c2_find_qpn(c2dev, qpn);
+ 	pr_debug("%s Returning QP=%p for QPN=%d, device=%p, refcount=%d\n",
+-		__FUNCTION__, qp, qpn, device,
++		__func__, qp, qpn, device,
+ 		(qp?atomic_read(&qp->refcount):0));
+ 
+ 	return (qp?&qp->ibqp:NULL);
+@@ -243,13 +243,16 @@ static struct ib_qp *c2_create_qp(struct ib_pd *pd,
+ 	struct c2_qp *qp;
+ 	int err;
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
++
++	if (init_attr->create_flags)
++		return ERR_PTR(-EINVAL);
+ 
+ 	switch (init_attr->qp_type) {
+ 	case IB_QPT_RC:
+ 		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
+ 		if (!qp) {
+-			pr_debug("%s: Unable to allocate QP\n", __FUNCTION__);
++			pr_debug("%s: Unable to allocate QP\n", __func__);
+ 			return ERR_PTR(-ENOMEM);
+ 		}
+ 		spin_lock_init(&qp->lock);
+@@ -266,7 +269,7 @@ static struct ib_qp *c2_create_qp(struct ib_pd *pd,
+ 
+ 		break;
+ 	default:
+-		pr_debug("%s: Invalid QP type: %d\n", __FUNCTION__,
++		pr_debug("%s: Invalid QP type: %d\n", __func__,
+ 			init_attr->qp_type);
+ 		return ERR_PTR(-EINVAL);
+ 		break;
+@@ -285,7 +288,7 @@ static int c2_destroy_qp(struct ib_qp *ib_qp)
+ 	struct c2_qp *qp = to_c2qp(ib_qp);
+ 
+ 	pr_debug("%s:%u qp=%p,qp->state=%d\n",
+-		__FUNCTION__, __LINE__,ib_qp,qp->state);
++		__func__, __LINE__, ib_qp, qp->state);
+ 	c2_free_qp(to_c2dev(ib_qp->device), qp);
+ 	kfree(qp);
+ 	return 0;
+@@ -300,13 +303,13 @@ static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries, int vect
+ 
+ 	cq = kmalloc(sizeof(*cq), GFP_KERNEL);
+ 	if (!cq) {
+-		pr_debug("%s: Unable to allocate CQ\n", __FUNCTION__);
++		pr_debug("%s: Unable to allocate CQ\n", __func__);
+ 		return ERR_PTR(-ENOMEM);
+ 	}
+ 
+ 	err = c2_init_cq(to_c2dev(ibdev), entries, NULL, cq);
+ 	if (err) {
+-		pr_debug("%s: error initializing CQ\n", __FUNCTION__);
++		pr_debug("%s: error initializing CQ\n", __func__);
+ 		kfree(cq);
+ 		return ERR_PTR(err);
+ 	}
+@@ -318,7 +321,7 @@ static int c2_destroy_cq(struct ib_cq *ib_cq)
+ {
+ 	struct c2_cq *cq = to_c2cq(ib_cq);
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	c2_free_cq(to_c2dev(ib_cq->device), cq);
+ 	kfree(cq);
+@@ -400,7 +403,7 @@ static struct ib_mr *c2_reg_phys_mr(struct ib_pd *ib_pd,
+ 	mr->umem = NULL;
+ 	pr_debug("%s - page shift %d, pbl_depth %d, total_len %u, "
+ 		"*iova_start %llx, first pa %llx, last pa %llx\n",
+-		__FUNCTION__, page_shift, pbl_depth, total_len,
++		__func__, page_shift, pbl_depth, total_len,
+ 		(unsigned long long) *iova_start,
+ 	       	(unsigned long long) page_list[0],
+ 	       	(unsigned long long) page_list[pbl_depth-1]);
+@@ -422,7 +425,7 @@ static struct ib_mr *c2_get_dma_mr(struct ib_pd *pd, int acc)
+ 	struct ib_phys_buf bl;
+ 	u64 kva = 0;
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	/* AMSO1100 limit */
+ 	bl.size = 0xffffffff;
+@@ -442,7 +445,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ 	struct c2_pd *c2pd = to_c2pd(pd);
+ 	struct c2_mr *c2mr;
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	c2mr = kmalloc(sizeof(*c2mr), GFP_KERNEL);
+ 	if (!c2mr)
+@@ -506,7 +509,7 @@ static int c2_dereg_mr(struct ib_mr *ib_mr)
+ 	struct c2_mr *mr = to_c2mr(ib_mr);
+ 	int err;
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	err = c2_stag_dealloc(to_c2dev(ib_mr->device), ib_mr->lkey);
+ 	if (err)
+@@ -520,45 +523,49 @@ static int c2_dereg_mr(struct ib_mr *ib_mr)
+ 	return err;
+ }
+ 
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+-	struct c2_dev *dev = container_of(cdev, struct c2_dev, ibdev.class_dev);
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
+-	return sprintf(buf, "%x\n", dev->props.hw_ver);
++	struct c2_dev *c2dev = container_of(dev, struct c2_dev, ibdev.dev);
++	pr_debug("%s:%u\n", __func__, __LINE__);
++	return sprintf(buf, "%x\n", c2dev->props.hw_ver);
+ }
+ 
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
++			   char *buf)
+ {
+-	struct c2_dev *dev = container_of(cdev, struct c2_dev, ibdev.class_dev);
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	struct c2_dev *c2dev = container_of(dev, struct c2_dev, ibdev.dev);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return sprintf(buf, "%x.%x.%x\n",
+-		       (int) (dev->props.fw_ver >> 32),
+-		       (int) (dev->props.fw_ver >> 16) & 0xffff,
+-		       (int) (dev->props.fw_ver & 0xffff));
++		       (int) (c2dev->props.fw_ver >> 32),
++		       (int) (c2dev->props.fw_ver >> 16) & 0xffff,
++		       (int) (c2dev->props.fw_ver & 0xffff));
+ }
+ 
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return sprintf(buf, "AMSO1100\n");
+ }
+ 
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return sprintf(buf, "%.*s\n", 32, "AMSO1100 Board ID");
+ }
+ 
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
+ 
+-static struct class_device_attribute *c2_class_attributes[] = {
+-	&class_device_attr_hw_rev,
+-	&class_device_attr_fw_ver,
+-	&class_device_attr_hca_type,
+-	&class_device_attr_board_id
++static struct device_attribute *c2_dev_attributes[] = {
++	&dev_attr_hw_rev,
++	&dev_attr_fw_ver,
++	&dev_attr_hca_type,
++	&dev_attr_board_id
+ };
+ 
+ static int c2_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+@@ -575,13 +582,13 @@ static int c2_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ 
+ static int c2_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return -ENOSYS;
+ }
+ 
+ static int c2_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return -ENOSYS;
+ }
+ 
+@@ -592,13 +599,13 @@ static int c2_process_mad(struct ib_device *ibdev,
+ 			  struct ib_grh *in_grh,
+ 			  struct ib_mad *in_mad, struct ib_mad *out_mad)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	return -ENOSYS;
+ }
+ 
+ static int c2_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	/* Request a connection */
+ 	return c2_llp_connect(cm_id, iw_param);
+@@ -606,7 +613,7 @@ static int c2_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
+ 
+ static int c2_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	/* Accept the new connection */
+ 	return c2_llp_accept(cm_id, iw_param);
+@@ -616,7 +623,7 @@ static int c2_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
+ {
+ 	int err;
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	err = c2_llp_reject(cm_id, pdata, pdata_len);
+ 	return err;
+@@ -626,10 +633,10 @@ static int c2_service_create(struct iw_cm_id *cm_id, int backlog)
+ {
+ 	int err;
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	err = c2_llp_service_create(cm_id, backlog);
+ 	pr_debug("%s:%u err=%d\n",
+-		__FUNCTION__, __LINE__,
++		__func__, __LINE__,
+ 		err);
+ 	return err;
+ }
+@@ -637,7 +644,7 @@ static int c2_service_create(struct iw_cm_id *cm_id, int backlog)
+ static int c2_service_destroy(struct iw_cm_id *cm_id)
+ {
+ 	int err;
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 
+ 	err = c2_llp_service_destroy(cm_id);
+ 
+@@ -743,7 +750,7 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
+ 	netdev = alloc_netdev(sizeof(*netdev), name, setup);
+ 	if (!netdev) {
+ 		printk(KERN_ERR PFX "%s -  etherdev alloc failed",
+-			__FUNCTION__);
++			__func__);
+ 		return NULL;
+ 	}
+ 
+@@ -780,7 +787,7 @@ int c2_register_device(struct c2_dev *dev)
+ 	if (ret)
+ 		goto out2;
+ 
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	strlcpy(dev->ibdev.name, "amso%d", IB_DEVICE_NAME_MAX);
+ 	dev->ibdev.owner = THIS_MODULE;
+ 	dev->ibdev.uverbs_cmd_mask =
+@@ -858,9 +865,9 @@ int c2_register_device(struct c2_dev *dev)
+ 	if (ret)
+ 		goto out1;
+ 
+-	for (i = 0; i < ARRAY_SIZE(c2_class_attributes); ++i) {
+-		ret = class_device_create_file(&dev->ibdev.class_dev,
+-					       c2_class_attributes[i]);
++	for (i = 0; i < ARRAY_SIZE(c2_dev_attributes); ++i) {
++		ret = device_create_file(&dev->ibdev.dev,
++					       c2_dev_attributes[i]);
+ 		if (ret)
+ 			goto out0;
+ 	}
+@@ -873,13 +880,13 @@ out1:
+ out2:
+ 	free_netdev(dev->pseudo_netdev);
+ out3:
+-	pr_debug("%s:%u ret=%d\n", __FUNCTION__, __LINE__, ret);
++	pr_debug("%s:%u ret=%d\n", __func__, __LINE__, ret);
+ 	return ret;
+ }
+ 
+ void c2_unregister_device(struct c2_dev *dev)
+ {
+-	pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++	pr_debug("%s:%u\n", __func__, __LINE__);
+ 	unregister_netdev(dev->pseudo_netdev);
+ 	free_netdev(dev->pseudo_netdev);
+ 	ib_unregister_device(&dev->ibdev);
+diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c
+index 01d0786..a6d8944 100644
+--- a/drivers/infiniband/hw/amso1100/c2_qp.c
++++ b/drivers/infiniband/hw/amso1100/c2_qp.c
+@@ -121,7 +121,7 @@ void c2_set_qp_state(struct c2_qp *qp, int c2_state)
+ 	int new_state = to_ib_state(c2_state);
+ 
+ 	pr_debug("%s: qp[%p] state modify %s --> %s\n",
+-	       __FUNCTION__,
++	       __func__,
+ 		qp,
+ 		to_ib_state_str(qp->state),
+ 		to_ib_state_str(new_state));
+@@ -141,7 +141,7 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
+ 	int err;
+ 
+ 	pr_debug("%s:%d qp=%p, %s --> %s\n",
+-		__FUNCTION__, __LINE__,
++		__func__, __LINE__,
+ 		qp,
+ 		to_ib_state_str(qp->state),
+ 		to_ib_state_str(attr->qp_state));
+@@ -224,7 +224,7 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
+ 		qp->state = next_state;
+ #ifdef DEBUG
+ 	else
+-		pr_debug("%s: c2_errno=%d\n", __FUNCTION__, err);
++		pr_debug("%s: c2_errno=%d\n", __func__, err);
+ #endif
+ 	/*
+ 	 * If we're going to error and generating the event here, then
+@@ -243,7 +243,7 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
+ 	vq_req_free(c2dev, vq_req);
+ 
+ 	pr_debug("%s:%d qp=%p, cur_state=%s\n",
+-		__FUNCTION__, __LINE__,
++		__func__, __LINE__,
+ 		qp,
+ 		to_ib_state_str(qp->state));
+ 	return err;
+@@ -811,16 +811,24 @@ int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
+ 
+ 		switch (ib_wr->opcode) {
+ 		case IB_WR_SEND:
+-			if (ib_wr->send_flags & IB_SEND_SOLICITED) {
+-				c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE);
+-				msg_size = sizeof(struct c2wr_send_req);
++		case IB_WR_SEND_WITH_INV:
++			if (ib_wr->opcode == IB_WR_SEND) {
++				if (ib_wr->send_flags & IB_SEND_SOLICITED)
++					c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE);
++				else
++					c2_wr_set_id(&wr, C2_WR_TYPE_SEND);
++				wr.sqwr.send.remote_stag = 0;
+ 			} else {
+-				c2_wr_set_id(&wr, C2_WR_TYPE_SEND);
+-				msg_size = sizeof(struct c2wr_send_req);
++				if (ib_wr->send_flags & IB_SEND_SOLICITED)
++					c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE_INV);
++				else
++					c2_wr_set_id(&wr, C2_WR_TYPE_SEND_INV);
++				wr.sqwr.send.remote_stag =
++					cpu_to_be32(ib_wr->ex.invalidate_rkey);
+ 			}
+ 
+-			wr.sqwr.send.remote_stag = 0;
+-			msg_size += sizeof(struct c2_data_addr) * ib_wr->num_sge;
++			msg_size = sizeof(struct c2wr_send_req) +
++				sizeof(struct c2_data_addr) * ib_wr->num_sge;
+ 			if (ib_wr->num_sge > qp->send_sgl_depth) {
+ 				err = -EINVAL;
+ 				break;
+diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c
+index 1687c51..9a054c6 100644
+--- a/drivers/infiniband/hw/amso1100/c2_rnic.c
++++ b/drivers/infiniband/hw/amso1100/c2_rnic.c
+@@ -208,7 +208,7 @@ static int c2_rnic_query(struct c2_dev *c2dev, struct ib_device_attr *props)
+ /*
+  * Add an IP address to the RNIC interface
+  */
+-int c2_add_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask)
++int c2_add_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask)
+ {
+ 	struct c2_vq_req *vq_req;
+ 	struct c2wr_rnic_setconfig_req *wr;
+@@ -270,7 +270,7 @@ int c2_add_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask)
+ /*
+  * Delete an IP address from the RNIC interface
+  */
+-int c2_del_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask)
++int c2_del_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask)
+ {
+ 	struct c2_vq_req *vq_req;
+ 	struct c2wr_rnic_setconfig_req *wr;
+@@ -455,7 +455,8 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ 	     IB_DEVICE_CURR_QP_STATE_MOD |
+ 	     IB_DEVICE_SYS_IMAGE_GUID |
+ 	     IB_DEVICE_ZERO_STAG |
+-	     IB_DEVICE_SEND_W_INV | IB_DEVICE_MEM_WINDOW);
++	     IB_DEVICE_MEM_WINDOW |
++	     IB_DEVICE_SEND_W_INV);
+ 
+ 	/* Allocate the qptr_array */
+ 	c2dev->qptr_array = vmalloc(C2_MAX_CQS * sizeof(void *));
+@@ -506,17 +507,17 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ 	mmio_regs = c2dev->kva;
+ 	/* Initialize the Verbs Request Queue */
+ 	c2_mq_req_init(&c2dev->req_vq, 0,
+-		       be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_QSIZE)),
+-		       be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_MSGSIZE)),
++		       be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_QSIZE)),
++		       be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_MSGSIZE)),
+ 		       mmio_regs +
+-		       be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_POOLSTART)),
++		       be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_POOLSTART)),
+ 		       mmio_regs +
+-		       be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_SHARED)),
++		       be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_SHARED)),
+ 		       C2_MQ_ADAPTER_TARGET);
+ 
+ 	/* Initialize the Verbs Reply Queue */
+-	qsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_QSIZE));
+-	msgsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_MSGSIZE));
++	qsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q1_QSIZE));
++	msgsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q1_MSGSIZE));
+ 	q1_pages = dma_alloc_coherent(&c2dev->pcidev->dev, qsize * msgsize,
+ 				      &c2dev->rep_vq.host_dma, GFP_KERNEL);
+ 	if (!q1_pages) {
+@@ -524,7 +525,7 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ 		goto bail1;
+ 	}
+ 	pci_unmap_addr_set(&c2dev->rep_vq, mapping, c2dev->rep_vq.host_dma);
+-	pr_debug("%s rep_vq va %p dma %llx\n", __FUNCTION__, q1_pages,
++	pr_debug("%s rep_vq va %p dma %llx\n", __func__, q1_pages,
+ 		 (unsigned long long) c2dev->rep_vq.host_dma);
+ 	c2_mq_rep_init(&c2dev->rep_vq,
+ 		   1,
+@@ -532,12 +533,12 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ 		   msgsize,
+ 		   q1_pages,
+ 		   mmio_regs +
+-		   be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_SHARED)),
++		   be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q1_SHARED)),
+ 		   C2_MQ_HOST_TARGET);
+ 
+ 	/* Initialize the Asynchronus Event Queue */
+-	qsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_QSIZE));
+-	msgsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_MSGSIZE));
++	qsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q2_QSIZE));
++	msgsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q2_MSGSIZE));
+ 	q2_pages = dma_alloc_coherent(&c2dev->pcidev->dev, qsize * msgsize,
+ 				      &c2dev->aeq.host_dma, GFP_KERNEL);
+ 	if (!q2_pages) {
+@@ -545,7 +546,7 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ 		goto bail2;
+ 	}
+ 	pci_unmap_addr_set(&c2dev->aeq, mapping, c2dev->aeq.host_dma);
+-	pr_debug("%s aeq va %p dma %llx\n", __FUNCTION__, q2_pages,
++	pr_debug("%s aeq va %p dma %llx\n", __func__, q2_pages,
+ 		 (unsigned long long) c2dev->aeq.host_dma);
+ 	c2_mq_rep_init(&c2dev->aeq,
+ 		       2,
+@@ -553,7 +554,7 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ 		       msgsize,
+ 		       q2_pages,
+ 		       mmio_regs +
+-		       be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_SHARED)),
++		       be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q2_SHARED)),
+ 		       C2_MQ_HOST_TARGET);
+ 
+ 	/* Initialize the verbs request allocator */
+diff --git a/drivers/infiniband/hw/amso1100/c2_vq.c b/drivers/infiniband/hw/amso1100/c2_vq.c
+index cfdacb1..9ce7819 100644
+--- a/drivers/infiniband/hw/amso1100/c2_vq.c
++++ b/drivers/infiniband/hw/amso1100/c2_vq.c
+@@ -197,7 +197,7 @@ int vq_send_wr(struct c2_dev *c2dev, union c2wr *wr)
+ 	 */
+ 	while (msg == NULL) {
+ 		pr_debug("%s:%d no available msg in VQ, waiting...\n",
+-		       __FUNCTION__, __LINE__);
++		       __func__, __LINE__);
+ 		init_waitqueue_entry(&__wait, current);
+ 		add_wait_queue(&c2dev->req_vq_wo, &__wait);
+ 		spin_unlock(&c2dev->vqlock);
+diff --git a/drivers/infiniband/hw/amso1100/c2_wr.h b/drivers/infiniband/hw/amso1100/c2_wr.h
+index 3ec6c43..c65fbdd 100644
+--- a/drivers/infiniband/hw/amso1100/c2_wr.h
++++ b/drivers/infiniband/hw/amso1100/c2_wr.h
+@@ -180,8 +180,8 @@ enum c2_wr_type {
+ };
+ 
+ struct c2_netaddr {
+-	u32 ip_addr;
+-	u32 netmask;
++	__be32 ip_addr;
++	__be32 netmask;
+ 	u32 mtu;
+ };
+ 
+@@ -199,9 +199,9 @@ struct c2_route {
+  * A Scatter Gather Entry.
+  */
+ struct c2_data_addr {
+-	u32 stag;
+-	u32 length;
+-	u64 to;
++	__be32 stag;
++	__be32 length;
++	__be64 to;
+ };
+ 
+ /*
+@@ -274,7 +274,7 @@ struct c2wr_hdr {
+ 	 * from the host to adapter by libccil, but we copy it anyway
+ 	 * to make the memcpy to the adapter better aligned.
+ 	 */
+-	u32 wqe_count;
++	__be32 wqe_count;
+ 
+ 	/* Put these fields next so that later 32- and 64-bit
+ 	 * quantities are naturally aligned.
+@@ -316,8 +316,8 @@ enum c2_rnic_flags {
+ struct c2wr_rnic_open_req {
+ 	struct c2wr_hdr hdr;
+ 	u64 user_context;
+-	u16 flags;		/* See enum c2_rnic_flags */
+-	u16 port_num;
++	__be16 flags;		/* See enum c2_rnic_flags */
++	__be16 port_num;
+ } __attribute__((packed));
+ 
+ struct c2wr_rnic_open_rep {
+@@ -341,30 +341,30 @@ struct c2wr_rnic_query_req {
+ struct c2wr_rnic_query_rep {
+ 	struct c2wr_hdr hdr;
+ 	u64 user_context;
+-	u32 vendor_id;
+-	u32 part_number;
+-	u32 hw_version;
+-	u32 fw_ver_major;
+-	u32 fw_ver_minor;
+-	u32 fw_ver_patch;
++	__be32 vendor_id;
++	__be32 part_number;
++	__be32 hw_version;
++	__be32 fw_ver_major;
++	__be32 fw_ver_minor;
++	__be32 fw_ver_patch;
+ 	char fw_ver_build_str[WR_BUILD_STR_LEN];
+-	u32 max_qps;
+-	u32 max_qp_depth;
++	__be32 max_qps;
++	__be32 max_qp_depth;
+ 	u32 max_srq_depth;
+ 	u32 max_send_sgl_depth;
+ 	u32 max_rdma_sgl_depth;
+-	u32 max_cqs;
+-	u32 max_cq_depth;
++	__be32 max_cqs;
++	__be32 max_cq_depth;
+ 	u32 max_cq_event_handlers;
+-	u32 max_mrs;
++	__be32 max_mrs;
+ 	u32 max_pbl_depth;
+-	u32 max_pds;
+-	u32 max_global_ird;
++	__be32 max_pds;
++	__be32 max_global_ird;
+ 	u32 max_global_ord;
+-	u32 max_qp_ird;
+-	u32 max_qp_ord;
++	__be32 max_qp_ird;
++	__be32 max_qp_ord;
+ 	u32 flags;
+-	u32 max_mws;
++	__be32 max_mws;
+ 	u32 pbe_range_low;
+ 	u32 pbe_range_high;
+ 	u32 max_srqs;
+@@ -405,7 +405,7 @@ union c2wr_rnic_getconfig {
+ struct c2wr_rnic_setconfig_req {
+ 	struct c2wr_hdr hdr;
+ 	u32 rnic_handle;
+-	u32 option;		/* See c2_setconfig_cmd_t */
++	__be32 option;		/* See c2_setconfig_cmd_t */
+ 	/* variable data and pad. See c2_netaddr and c2_route */
+ 	u8 data[0];
+ } __attribute__((packed)) ;
+@@ -441,18 +441,18 @@ union c2wr_rnic_close {
+  */
+ struct c2wr_cq_create_req {
+ 	struct c2wr_hdr hdr;
+-	u64 shared_ht;
++	__be64 shared_ht;
+ 	u64 user_context;
+-	u64 msg_pool;
++	__be64 msg_pool;
+ 	u32 rnic_handle;
+-	u32 msg_size;
+-	u32 depth;
++	__be32 msg_size;
++	__be32 depth;
+ } __attribute__((packed)) ;
+ 
+ struct c2wr_cq_create_rep {
+ 	struct c2wr_hdr hdr;
+-	u32 mq_index;
+-	u32 adapter_shared;
++	__be32 mq_index;
++	__be32 adapter_shared;
+ 	u32 cq_handle;
+ } __attribute__((packed)) ;
+ 
+@@ -585,40 +585,40 @@ enum c2wr_qp_flags {
+ 
+ struct c2wr_qp_create_req {
+ 	struct c2wr_hdr hdr;
+-	u64 shared_sq_ht;
+-	u64 shared_rq_ht;
++	__be64 shared_sq_ht;
++	__be64 shared_rq_ht;
+ 	u64 user_context;
+ 	u32 rnic_handle;
+ 	u32 sq_cq_handle;
+ 	u32 rq_cq_handle;
+-	u32 sq_depth;
+-	u32 rq_depth;
++	__be32 sq_depth;
++	__be32 rq_depth;
+ 	u32 srq_handle;
+ 	u32 srq_limit;
+-	u32 flags;		/* see enum c2wr_qp_flags */
+-	u32 send_sgl_depth;
+-	u32 recv_sgl_depth;
+-	u32 rdma_write_sgl_depth;
+-	u32 ord;
+-	u32 ird;
++	__be32 flags;		/* see enum c2wr_qp_flags */
++	__be32 send_sgl_depth;
++	__be32 recv_sgl_depth;
++	__be32 rdma_write_sgl_depth;
++	__be32 ord;
++	__be32 ird;
+ 	u32 pd_id;
+ } __attribute__((packed)) ;
+ 
+ struct c2wr_qp_create_rep {
+ 	struct c2wr_hdr hdr;
+-	u32 sq_depth;
+-	u32 rq_depth;
++	__be32 sq_depth;
++	__be32 rq_depth;
+ 	u32 send_sgl_depth;
+ 	u32 recv_sgl_depth;
+ 	u32 rdma_write_sgl_depth;
+ 	u32 ord;
+ 	u32 ird;
+-	u32 sq_msg_size;
+-	u32 sq_mq_index;
+-	u32 sq_mq_start;
+-	u32 rq_msg_size;
+-	u32 rq_mq_index;
+-	u32 rq_mq_start;
++	__be32 sq_msg_size;
++	__be32 sq_mq_index;
++	__be32 sq_mq_start;
++	__be32 rq_msg_size;
++	__be32 rq_mq_index;
++	__be32 rq_mq_start;
+ 	u32 qp_handle;
+ } __attribute__((packed)) ;
+ 
+@@ -667,11 +667,11 @@ struct c2wr_qp_modify_req {
+ 	u32 stream_msg_length;
+ 	u32 rnic_handle;
+ 	u32 qp_handle;
+-	u32 next_qp_state;
+-	u32 ord;
+-	u32 ird;
+-	u32 sq_depth;
+-	u32 rq_depth;
++	__be32 next_qp_state;
++	__be32 ord;
++	__be32 ird;
++	__be32 sq_depth;
++	__be32 rq_depth;
+ 	u32 llp_ep_handle;
+ } __attribute__((packed)) ;
+ 
+@@ -721,10 +721,10 @@ struct c2wr_qp_connect_req {
+ 	struct c2wr_hdr hdr;
+ 	u32 rnic_handle;
+ 	u32 qp_handle;
+-	u32 remote_addr;
+-	u16 remote_port;
++	__be32 remote_addr;
++	__be16 remote_port;
+ 	u16 pad;
+-	u32 private_data_length;
++	__be32 private_data_length;
+ 	u8 private_data[0];	/* Private data in-line. */
+ } __attribute__((packed)) ;
+ 
+@@ -759,25 +759,25 @@ union c2wr_nsmr_stag_alloc {
+ 
+ struct c2wr_nsmr_register_req {
+ 	struct c2wr_hdr hdr;
+-	u64 va;
++	__be64 va;
+ 	u32 rnic_handle;
+-	u16 flags;
++	__be16 flags;
+ 	u8 stag_key;
+ 	u8 pad;
+ 	u32 pd_id;
+-	u32 pbl_depth;
+-	u32 pbe_size;
+-	u32 fbo;
+-	u32 length;
+-	u32 addrs_length;
++	__be32 pbl_depth;
++	__be32 pbe_size;
++	__be32 fbo;
++	__be32 length;
++	__be32 addrs_length;
+ 	/* array of paddrs (must be aligned on a 64bit boundary) */
+-	u64 paddrs[0];
++	__be64 paddrs[0];
+ } __attribute__((packed)) ;
+ 
+ struct c2wr_nsmr_register_rep {
+ 	struct c2wr_hdr hdr;
+ 	u32 pbl_depth;
+-	u32 stag_index;
++	__be32 stag_index;
+ } __attribute__((packed)) ;
+ 
+ union c2wr_nsmr_register {
+@@ -788,11 +788,11 @@ union c2wr_nsmr_register {
+ struct c2wr_nsmr_pbl_req {
+ 	struct c2wr_hdr hdr;
+ 	u32 rnic_handle;
+-	u32 flags;
+-	u32 stag_index;
+-	u32 addrs_length;
++	__be32 flags;
++	__be32 stag_index;
++	__be32 addrs_length;
+ 	/* array of paddrs (must be aligned on a 64bit boundary) */
+-	u64 paddrs[0];
++	__be64 paddrs[0];
+ } __attribute__((packed)) ;
+ 
+ struct c2wr_nsmr_pbl_rep {
+@@ -847,7 +847,7 @@ union c2wr_mw_query {
+ struct c2wr_stag_dealloc_req {
+ 	struct c2wr_hdr hdr;
+ 	u32 rnic_handle;
+-	u32 stag_index;
++	__be32 stag_index;
+ } __attribute__((packed)) ;
+ 
+ struct c2wr_stag_dealloc_rep {
+@@ -949,7 +949,7 @@ struct c2wr_ce {
+ 	u64 qp_user_context;	/* c2_user_qp_t * */
+ 	u32 qp_state;		/* Current QP State */
+ 	u32 handle;		/* QPID or EP Handle */
+-	u32 bytes_rcvd;		/* valid for RECV WCs */
++	__be32 bytes_rcvd;		/* valid for RECV WCs */
+ 	u32 stag;
+ } __attribute__((packed)) ;
+ 
+@@ -984,8 +984,8 @@ struct c2_rq_hdr {
+  */
+ struct c2wr_send_req {
+ 	struct c2_sq_hdr sq_hdr;
+-	u32 sge_len;
+-	u32 remote_stag;
++	__be32 sge_len;
++	__be32 remote_stag;
+ 	u8 data[0];		/* SGE array */
+ } __attribute__((packed));
+ 
+@@ -996,9 +996,9 @@ union c2wr_send {
+ 
+ struct c2wr_rdma_write_req {
+ 	struct c2_sq_hdr sq_hdr;
+-	u64 remote_to;
+-	u32 remote_stag;
+-	u32 sge_len;
++	__be64 remote_to;
++	__be32 remote_stag;
++	__be32 sge_len;
+ 	u8 data[0];		/* SGE array */
+ } __attribute__((packed));
+ 
+@@ -1009,11 +1009,11 @@ union c2wr_rdma_write {
+ 
+ struct c2wr_rdma_read_req {
+ 	struct c2_sq_hdr sq_hdr;
+-	u64 local_to;
+-	u64 remote_to;
+-	u32 local_stag;
+-	u32 remote_stag;
+-	u32 length;
++	__be64 local_to;
++	__be64 remote_to;
++	__be32 local_stag;
++	__be32 remote_stag;
++	__be32 length;
+ } __attribute__((packed));
+ 
+ union c2wr_rdma_read {
+@@ -1113,9 +1113,9 @@ union c2wr_recv {
+ struct c2wr_ae_hdr {
+ 	struct c2wr_hdr hdr;
+ 	u64 user_context;	/* user context for this res. */
+-	u32 resource_type;	/* see enum c2_resource_indicator */
+-	u32 resource;		/* handle for resource */
+-	u32 qp_state;		/* current QP State */
++	__be32 resource_type;	/* see enum c2_resource_indicator */
++	__be32 resource;	/* handle for resource */
++	__be32 qp_state;	/* current QP State */
+ } __attribute__((packed));
+ 
+ /*
+@@ -1124,11 +1124,11 @@ struct c2wr_ae_hdr {
+  */
+ struct c2wr_ae_active_connect_results {
+ 	struct c2wr_ae_hdr ae_hdr;
+-	u32 laddr;
+-	u32 raddr;
+-	u16 lport;
+-	u16 rport;
+-	u32 private_data_length;
++	__be32 laddr;
++	__be32 raddr;
++	__be16 lport;
++	__be16 rport;
++	__be32 private_data_length;
+ 	u8 private_data[0];	/* data is in-line in the msg. */
+ } __attribute__((packed));
+ 
+@@ -1142,11 +1142,11 @@ struct c2wr_ae_active_connect_results {
+ struct c2wr_ae_connection_request {
+ 	struct c2wr_ae_hdr ae_hdr;
+ 	u32 cr_handle;		/* connreq handle (sock ptr) */
+-	u32 laddr;
+-	u32 raddr;
+-	u16 lport;
+-	u16 rport;
+-	u32 private_data_length;
++	__be32 laddr;
++	__be32 raddr;
++	__be16 lport;
++	__be16 rport;
++	__be32 private_data_length;
+ 	u8 private_data[0];	/* data is in-line in the msg. */
+ } __attribute__((packed));
+ 
+@@ -1158,12 +1158,12 @@ union c2wr_ae {
+ 
+ struct c2wr_init_req {
+ 	struct c2wr_hdr hdr;
+-	u64 hint_count;
+-	u64 q0_host_shared;
+-	u64 q1_host_shared;
+-	u64 q1_host_msg_pool;
+-	u64 q2_host_shared;
+-	u64 q2_host_msg_pool;
++	__be64 hint_count;
++	__be64 q0_host_shared;
++	__be64 q1_host_shared;
++	__be64 q1_host_msg_pool;
++	__be64 q2_host_shared;
++	__be64 q2_host_msg_pool;
+ } __attribute__((packed));
+ 
+ struct c2wr_init_rep {
+@@ -1276,10 +1276,10 @@ struct c2wr_ep_listen_create_req {
+ 	struct c2wr_hdr hdr;
+ 	u64 user_context;	/* returned in AEs. */
+ 	u32 rnic_handle;
+-	u32 local_addr;		/* local addr, or 0  */
+-	u16 local_port;		/* 0 means "pick one" */
++	__be32 local_addr;		/* local addr, or 0  */
++	__be16 local_port;		/* 0 means "pick one" */
+ 	u16 pad;
+-	u32 backlog;		/* tradional tcp listen bl */
++	__be32 backlog;		/* tradional tcp listen bl */
+ } __attribute__((packed));
+ 
+ struct c2wr_ep_listen_create_rep {
+@@ -1340,7 +1340,7 @@ struct c2wr_cr_accept_req {
+ 	u32 rnic_handle;
+ 	u32 qp_handle;		/* QP to bind to this LLP conn */
+ 	u32 ep_handle;		/* LLP  handle to accept */
+-	u32 private_data_length;
++	__be32 private_data_length;
+ 	u8 private_data[0];	/* data in-line in msg. */
+ } __attribute__((packed));
+ 
+@@ -1508,7 +1508,7 @@ static __inline__ void c2_wr_set_sge_count(void *wr, u8 sge_count)
+ {
+ 	((struct c2wr_hdr *) wr)->sge_count = sge_count;
+ }
+-static __inline__ u32 c2_wr_get_wqe_count(void *wr)
++static __inline__ __be32 c2_wr_get_wqe_count(void *wr)
+ {
+ 	return ((struct c2wr_hdr *) wr)->wqe_count;
+ }
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_dbg.c b/drivers/infiniband/hw/cxgb3/cxio_dbg.c
+index 75f7b16..a8d24d5 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_dbg.c
++++ b/drivers/infiniband/hw/cxgb3/cxio_dbg.c
+@@ -45,16 +45,16 @@ void cxio_dump_tpt(struct cxio_rdev *rdev, u32 stag)
+ 
+ 	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+ 	if (!m) {
+-		PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
++		PDBG("%s couldn't allocate memory.\n", __func__);
+ 		return;
+ 	}
+ 	m->mem_id = MEM_PMRX;
+ 	m->addr = (stag>>8) * 32 + rdev->rnic_info.tpt_base;
+ 	m->len = size;
+-	PDBG("%s TPT addr 0x%x len %d\n", __FUNCTION__, m->addr, m->len);
++	PDBG("%s TPT addr 0x%x len %d\n", __func__, m->addr, m->len);
+ 	rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+ 	if (rc) {
+-		PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
++		PDBG("%s toectl returned error %d\n", __func__, rc);
+ 		kfree(m);
+ 		return;
+ 	}
+@@ -82,17 +82,17 @@ void cxio_dump_pbl(struct cxio_rdev *rdev, u32 pbl_addr, uint len, u8 shift)
+ 
+ 	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+ 	if (!m) {
+-		PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
++		PDBG("%s couldn't allocate memory.\n", __func__);
+ 		return;
+ 	}
+ 	m->mem_id = MEM_PMRX;
+ 	m->addr = pbl_addr;
+ 	m->len = size;
+ 	PDBG("%s PBL addr 0x%x len %d depth %d\n",
+-		__FUNCTION__, m->addr, m->len, npages);
++		__func__, m->addr, m->len, npages);
+ 	rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+ 	if (rc) {
+-		PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
++		PDBG("%s toectl returned error %d\n", __func__, rc);
+ 		kfree(m);
+ 		return;
+ 	}
+@@ -144,16 +144,16 @@ void cxio_dump_rqt(struct cxio_rdev *rdev, u32 hwtid, int nents)
+ 
+ 	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+ 	if (!m) {
+-		PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
++		PDBG("%s couldn't allocate memory.\n", __func__);
+ 		return;
+ 	}
+ 	m->mem_id = MEM_PMRX;
+ 	m->addr = ((hwtid)<<10) + rdev->rnic_info.rqt_base;
+ 	m->len = size;
+-	PDBG("%s RQT addr 0x%x len %d\n", __FUNCTION__, m->addr, m->len);
++	PDBG("%s RQT addr 0x%x len %d\n", __func__, m->addr, m->len);
+ 	rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+ 	if (rc) {
+-		PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
++		PDBG("%s toectl returned error %d\n", __func__, rc);
+ 		kfree(m);
+ 		return;
+ 	}
+@@ -177,16 +177,16 @@ void cxio_dump_tcb(struct cxio_rdev *rdev, u32 hwtid)
+ 
+ 	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+ 	if (!m) {
+-		PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
++		PDBG("%s couldn't allocate memory.\n", __func__);
+ 		return;
+ 	}
+ 	m->mem_id = MEM_CM;
+ 	m->addr = hwtid * size;
+ 	m->len = size;
+-	PDBG("%s TCB %d len %d\n", __FUNCTION__, m->addr, m->len);
++	PDBG("%s TCB %d len %d\n", __func__, m->addr, m->len);
+ 	rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+ 	if (rc) {
+-		PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
++		PDBG("%s toectl returned error %d\n", __func__, rc);
+ 		kfree(m);
+ 		return;
+ 	}
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
+index 03c5ff6..66eb703 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
++++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
+@@ -140,7 +140,7 @@ static int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)
+ 	struct t3_modify_qp_wr *wqe;
+ 	struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);
+ 	if (!skb) {
+-		PDBG("%s alloc_skb failed\n", __FUNCTION__);
++		PDBG("%s alloc_skb failed\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
+@@ -225,7 +225,7 @@ static u32 get_qpid(struct cxio_rdev *rdev_p, struct cxio_ucontext *uctx)
+ 	}
+ out:
+ 	mutex_unlock(&uctx->lock);
+-	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
++	PDBG("%s qpid 0x%x\n", __func__, qpid);
+ 	return qpid;
+ }
+ 
+@@ -237,7 +237,7 @@ static void put_qpid(struct cxio_rdev *rdev_p, u32 qpid,
+ 	entry = kmalloc(sizeof *entry, GFP_KERNEL);
+ 	if (!entry)
+ 		return;
+-	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
++	PDBG("%s qpid 0x%x\n", __func__, qpid);
+ 	entry->qpid = qpid;
+ 	mutex_lock(&uctx->lock);
+ 	list_add_tail(&entry->entry, &uctx->qpids);
+@@ -300,7 +300,7 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,
+ 	if (!kernel_domain)
+ 		wq->udb = (u64)rdev_p->rnic_info.udbell_physbase +
+ 					(wq->qpid << rdev_p->qpshift);
+-	PDBG("%s qpid 0x%x doorbell 0x%p udb 0x%llx\n", __FUNCTION__,
++	PDBG("%s qpid 0x%x doorbell 0x%p udb 0x%llx\n", __func__,
+ 	     wq->qpid, wq->doorbell, (unsigned long long) wq->udb);
+ 	return 0;
+ err4:
+@@ -345,7 +345,7 @@ static void insert_recv_cqe(struct t3_wq *wq, struct t3_cq *cq)
+ {
+ 	struct t3_cqe cqe;
+ 
+-	PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __FUNCTION__,
++	PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __func__,
+ 	     wq, cq, cq->sw_rptr, cq->sw_wptr);
+ 	memset(&cqe, 0, sizeof(cqe));
+ 	cqe.header = cpu_to_be32(V_CQE_STATUS(TPT_ERR_SWFLUSH) |
+@@ -363,10 +363,10 @@ void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count)
+ {
+ 	u32 ptr;
+ 
+-	PDBG("%s wq %p cq %p\n", __FUNCTION__, wq, cq);
++	PDBG("%s wq %p cq %p\n", __func__, wq, cq);
+ 
+ 	/* flush RQ */
+-	PDBG("%s rq_rptr %u rq_wptr %u skip count %u\n", __FUNCTION__,
++	PDBG("%s rq_rptr %u rq_wptr %u skip count %u\n", __func__,
+ 	    wq->rq_rptr, wq->rq_wptr, count);
+ 	ptr = wq->rq_rptr + count;
+ 	while (ptr++ != wq->rq_wptr)
+@@ -378,7 +378,7 @@ static void insert_sq_cqe(struct t3_wq *wq, struct t3_cq *cq,
+ {
+ 	struct t3_cqe cqe;
+ 
+-	PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __FUNCTION__,
++	PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __func__,
+ 	     wq, cq, cq->sw_rptr, cq->sw_wptr);
+ 	memset(&cqe, 0, sizeof(cqe));
+ 	cqe.header = cpu_to_be32(V_CQE_STATUS(TPT_ERR_SWFLUSH) |
+@@ -415,11 +415,11 @@ void cxio_flush_hw_cq(struct t3_cq *cq)
+ {
+ 	struct t3_cqe *cqe, *swcqe;
+ 
+-	PDBG("%s cq %p cqid 0x%x\n", __FUNCTION__, cq, cq->cqid);
++	PDBG("%s cq %p cqid 0x%x\n", __func__, cq, cq->cqid);
+ 	cqe = cxio_next_hw_cqe(cq);
+ 	while (cqe) {
+ 		PDBG("%s flushing hwcq rptr 0x%x to swcq wptr 0x%x\n",
+-		     __FUNCTION__, cq->rptr, cq->sw_wptr);
++		     __func__, cq->rptr, cq->sw_wptr);
+ 		swcqe = cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2);
+ 		*swcqe = *cqe;
+ 		swcqe->header |= cpu_to_be32(V_CQE_SWCQE(1));
+@@ -461,7 +461,7 @@ void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+ 			(*count)++;
+ 		ptr++;
+ 	}
+-	PDBG("%s cq %p count %d\n", __FUNCTION__, cq, *count);
++	PDBG("%s cq %p count %d\n", __func__, cq, *count);
+ }
+ 
+ void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+@@ -470,7 +470,7 @@ void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+ 	u32 ptr;
+ 
+ 	*count = 0;
+-	PDBG("%s count zero %d\n", __FUNCTION__, *count);
++	PDBG("%s count zero %d\n", __func__, *count);
+ 	ptr = cq->sw_rptr;
+ 	while (!Q_EMPTY(ptr, cq->sw_wptr)) {
+ 		cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2));
+@@ -479,7 +479,7 @@ void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+ 			(*count)++;
+ 		ptr++;
+ 	}
+-	PDBG("%s cq %p count %d\n", __FUNCTION__, cq, *count);
++	PDBG("%s cq %p count %d\n", __func__, cq, *count);
+ }
+ 
+ static int cxio_hal_init_ctrl_cq(struct cxio_rdev *rdev_p)
+@@ -506,12 +506,12 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
+ 
+ 	skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);
+ 	if (!skb) {
+-		PDBG("%s alloc_skb failed\n", __FUNCTION__);
++		PDBG("%s alloc_skb failed\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	err = cxio_hal_init_ctrl_cq(rdev_p);
+ 	if (err) {
+-		PDBG("%s err %d initializing ctrl_cq\n", __FUNCTION__, err);
++		PDBG("%s err %d initializing ctrl_cq\n", __func__, err);
+ 		goto err;
+ 	}
+ 	rdev_p->ctrl_qp.workq = dma_alloc_coherent(
+@@ -521,7 +521,7 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
+ 					&(rdev_p->ctrl_qp.dma_addr),
+ 					GFP_KERNEL);
+ 	if (!rdev_p->ctrl_qp.workq) {
+-		PDBG("%s dma_alloc_coherent failed\n", __FUNCTION__);
++		PDBG("%s dma_alloc_coherent failed\n", __func__);
+ 		err = -ENOMEM;
+ 		goto err;
+ 	}
+@@ -591,25 +591,25 @@ static int cxio_hal_ctrl_qp_write_mem(struct cxio_rdev *rdev_p, u32 addr,
+ 	addr &= 0x7FFFFFF;
+ 	nr_wqe = len % 96 ? len / 96 + 1 : len / 96;	/* 96B max per WQE */
+ 	PDBG("%s wptr 0x%x rptr 0x%x len %d, nr_wqe %d data %p addr 0x%0x\n",
+-	     __FUNCTION__, rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, len,
++	     __func__, rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, len,
+ 	     nr_wqe, data, addr);
+ 	utx_len = 3;		/* in 32B unit */
+ 	for (i = 0; i < nr_wqe; i++) {
+ 		if (Q_FULL(rdev_p->ctrl_qp.rptr, rdev_p->ctrl_qp.wptr,
+ 		           T3_CTRL_QP_SIZE_LOG2)) {
+ 			PDBG("%s ctrl_qp full wtpr 0x%0x rptr 0x%0x, "
+-			     "wait for more space i %d\n", __FUNCTION__,
++			     "wait for more space i %d\n", __func__,
+ 			     rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, i);
+ 			if (wait_event_interruptible(rdev_p->ctrl_qp.waitq,
+ 					     !Q_FULL(rdev_p->ctrl_qp.rptr,
+ 						     rdev_p->ctrl_qp.wptr,
+ 						     T3_CTRL_QP_SIZE_LOG2))) {
+ 				PDBG("%s ctrl_qp workq interrupted\n",
+-				     __FUNCTION__);
++				     __func__);
+ 				return -ERESTARTSYS;
+ 			}
+ 			PDBG("%s ctrl_qp wakeup, continue posting work request "
+-			     "i %d\n", __FUNCTION__, i);
++			     "i %d\n", __func__, i);
+ 		}
+ 		wqe = (__be64 *)(rdev_p->ctrl_qp.workq + (rdev_p->ctrl_qp.wptr %
+ 						(1 << T3_CTRL_QP_SIZE_LOG2)));
+@@ -630,7 +630,7 @@ static int cxio_hal_ctrl_qp_write_mem(struct cxio_rdev *rdev_p, u32 addr,
+ 		if ((i != 0) &&
+ 		    (i % (((1 << T3_CTRL_QP_SIZE_LOG2)) >> 1) == 0)) {
+ 			flag = T3_COMPLETION_FLAG;
+-			PDBG("%s force completion at i %d\n", __FUNCTION__, i);
++			PDBG("%s force completion at i %d\n", __func__, i);
+ 		}
+ 
+ 		/* build the utx mem command */
+@@ -701,7 +701,7 @@ static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry,
+ 		*stag = (stag_idx << 8) | ((*stag) & 0xFF);
+ 	}
+ 	PDBG("%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x\n",
+-	     __FUNCTION__, stag_state, type, pdid, stag_idx);
++	     __func__, stag_state, type, pdid, stag_idx);
+ 
+ 	if (reset_tpt_entry)
+ 		cxio_hal_pblpool_free(rdev_p, *pbl_addr, *pbl_size << 3);
+@@ -718,7 +718,7 @@ static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry,
+ 	if (pbl) {
+ 
+ 		PDBG("%s *pdb_addr 0x%x, pbl_base 0x%x, pbl_size %d\n",
+-		     __FUNCTION__, *pbl_addr, rdev_p->rnic_info.pbl_base,
++		     __func__, *pbl_addr, rdev_p->rnic_info.pbl_base,
+ 		     *pbl_size);
+ 		err = cxio_hal_ctrl_qp_write_mem(rdev_p,
+ 				(*pbl_addr >> 5),
+@@ -814,7 +814,7 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
+ 	struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_ATOMIC);
+ 	if (!skb)
+ 		return -ENOMEM;
+-	PDBG("%s rdev_p %p\n", __FUNCTION__, rdev_p);
++	PDBG("%s rdev_p %p\n", __func__, rdev_p);
+ 	wqe = (struct t3_rdma_init_wr *) __skb_put(skb, sizeof(*wqe));
+ 	wqe->wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_INIT));
+ 	wqe->wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(attr->tid) |
+@@ -856,7 +856,7 @@ static int cxio_hal_ev_handler(struct t3cdev *t3cdev_p, struct sk_buff *skb)
+ 	struct respQ_msg_t *rsp_msg = (struct respQ_msg_t *) skb->data;
+ 	PDBG("%d: %s cq_id 0x%x cq_ptr 0x%x genbit %0x overflow %0x an %0x"
+ 	     " se %0x notify %0x cqbranch %0x creditth %0x\n",
+-	     cnt, __FUNCTION__, RSPQ_CQID(rsp_msg), RSPQ_CQPTR(rsp_msg),
++	     cnt, __func__, RSPQ_CQID(rsp_msg), RSPQ_CQPTR(rsp_msg),
+ 	     RSPQ_GENBIT(rsp_msg), RSPQ_OVERFLOW(rsp_msg), RSPQ_AN(rsp_msg),
+ 	     RSPQ_SE(rsp_msg), RSPQ_NOTIFY(rsp_msg), RSPQ_CQBRANCH(rsp_msg),
+ 	     RSPQ_CREDIT_THRESH(rsp_msg));
+@@ -868,7 +868,7 @@ static int cxio_hal_ev_handler(struct t3cdev *t3cdev_p, struct sk_buff *skb)
+ 	     CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+ 	rdev_p = (struct cxio_rdev *)t3cdev_p->ulp;
+ 	if (!rdev_p) {
+-		PDBG("%s called by t3cdev %p with null ulp\n", __FUNCTION__,
++		PDBG("%s called by t3cdev %p with null ulp\n", __func__,
+ 		     t3cdev_p);
+ 		return 0;
+ 	}
+@@ -908,13 +908,13 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ 		strncpy(rdev_p->dev_name, rdev_p->t3cdev_p->name,
+ 			T3_MAX_DEV_NAME_LEN);
+ 	} else {
+-		PDBG("%s t3cdev_p or dev_name must be set\n", __FUNCTION__);
++		PDBG("%s t3cdev_p or dev_name must be set\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	list_add_tail(&rdev_p->entry, &rdev_list);
+ 
+-	PDBG("%s opening rnic dev %s\n", __FUNCTION__, rdev_p->dev_name);
++	PDBG("%s opening rnic dev %s\n", __func__, rdev_p->dev_name);
+ 	memset(&rdev_p->ctrl_qp, 0, sizeof(rdev_p->ctrl_qp));
+ 	if (!rdev_p->t3cdev_p)
+ 		rdev_p->t3cdev_p = dev2t3cdev(netdev_p);
+@@ -923,14 +923,14 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ 					 &(rdev_p->rnic_info));
+ 	if (err) {
+ 		printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n",
+-		     __FUNCTION__, rdev_p->t3cdev_p, err);
++		     __func__, rdev_p->t3cdev_p, err);
+ 		goto err1;
+ 	}
+ 	err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, GET_PORTS,
+ 				    &(rdev_p->port_info));
+ 	if (err) {
+ 		printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n",
+-		     __FUNCTION__, rdev_p->t3cdev_p, err);
++		     __func__, rdev_p->t3cdev_p, err);
+ 		goto err1;
+ 	}
+ 
+@@ -947,7 +947,7 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ 	rdev_p->qpmask = (65536 >> ilog2(rdev_p->qpnr)) - 1;
+ 	PDBG("%s rnic %s info: tpt_base 0x%0x tpt_top 0x%0x num stags %d "
+ 	     "pbl_base 0x%0x pbl_top 0x%0x rqt_base 0x%0x, rqt_top 0x%0x\n",
+-	     __FUNCTION__, rdev_p->dev_name, rdev_p->rnic_info.tpt_base,
++	     __func__, rdev_p->dev_name, rdev_p->rnic_info.tpt_base,
+ 	     rdev_p->rnic_info.tpt_top, cxio_num_stags(rdev_p),
+ 	     rdev_p->rnic_info.pbl_base,
+ 	     rdev_p->rnic_info.pbl_top, rdev_p->rnic_info.rqt_base,
+@@ -961,7 +961,7 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ 	err = cxio_hal_init_ctrl_qp(rdev_p);
+ 	if (err) {
+ 		printk(KERN_ERR "%s error %d initializing ctrl_qp.\n",
+-		       __FUNCTION__, err);
++		       __func__, err);
+ 		goto err1;
+ 	}
+ 	err = cxio_hal_init_resource(rdev_p, cxio_num_stags(rdev_p), 0,
+@@ -969,19 +969,19 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ 				     T3_MAX_NUM_PD);
+ 	if (err) {
+ 		printk(KERN_ERR "%s error %d initializing hal resources.\n",
+-		       __FUNCTION__, err);
++		       __func__, err);
+ 		goto err2;
+ 	}
+ 	err = cxio_hal_pblpool_create(rdev_p);
+ 	if (err) {
+ 		printk(KERN_ERR "%s error %d initializing pbl mem pool.\n",
+-		       __FUNCTION__, err);
++		       __func__, err);
+ 		goto err3;
+ 	}
+ 	err = cxio_hal_rqtpool_create(rdev_p);
+ 	if (err) {
+ 		printk(KERN_ERR "%s error %d initializing rqt mem pool.\n",
+-		       __FUNCTION__, err);
++		       __func__, err);
+ 		goto err4;
+ 	}
+ 	return 0;
+@@ -1043,7 +1043,7 @@ static void flush_completed_wrs(struct t3_wq *wq, struct t3_cq *cq)
+ 			 * Insert this completed cqe into the swcq.
+ 			 */
+ 			PDBG("%s moving cqe into swcq sq idx %ld cq idx %ld\n",
+-			     __FUNCTION__, Q_PTR2IDX(ptr,  wq->sq_size_log2),
++			     __func__, Q_PTR2IDX(ptr,  wq->sq_size_log2),
+ 			     Q_PTR2IDX(cq->sw_wptr, cq->size_log2));
+ 			sqp->cqe.header |= htonl(V_CQE_SWCQE(1));
+ 			*(cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2))
+@@ -1112,7 +1112,7 @@ int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
+ 
+ 	PDBG("%s CQE OOO %d qpid 0x%0x genbit %d type %d status 0x%0x"
+ 	     " opcode 0x%0x len 0x%0x wrid_hi_stag 0x%x wrid_low_msn 0x%x\n",
+-	     __FUNCTION__, CQE_OOO(*hw_cqe), CQE_QPID(*hw_cqe),
++	     __func__, CQE_OOO(*hw_cqe), CQE_QPID(*hw_cqe),
+ 	     CQE_GENBIT(*hw_cqe), CQE_TYPE(*hw_cqe), CQE_STATUS(*hw_cqe),
+ 	     CQE_OPCODE(*hw_cqe), CQE_LEN(*hw_cqe), CQE_WRID_HI(*hw_cqe),
+ 	     CQE_WRID_LOW(*hw_cqe));
+@@ -1215,7 +1215,7 @@ int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
+ 		struct t3_swsq *sqp;
+ 
+ 		PDBG("%s out of order completion going in swsq at idx %ld\n",
+-		     __FUNCTION__,
++		     __func__,
+ 		     Q_PTR2IDX(CQE_WRID_SQ_WPTR(*hw_cqe), wq->sq_size_log2));
+ 		sqp = wq->sq +
+ 		      Q_PTR2IDX(CQE_WRID_SQ_WPTR(*hw_cqe), wq->sq_size_log2);
+@@ -1234,13 +1234,13 @@ proc_cqe:
+ 	 */
+ 	if (SQ_TYPE(*hw_cqe)) {
+ 		wq->sq_rptr = CQE_WRID_SQ_WPTR(*hw_cqe);
+-		PDBG("%s completing sq idx %ld\n", __FUNCTION__,
++		PDBG("%s completing sq idx %ld\n", __func__,
+ 		     Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2));
+ 		*cookie = (wq->sq +
+ 			   Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2))->wr_id;
+ 		wq->sq_rptr++;
+ 	} else {
+-		PDBG("%s completing rq idx %ld\n", __FUNCTION__,
++		PDBG("%s completing rq idx %ld\n", __func__,
+ 		     Q_PTR2IDX(wq->rq_rptr, wq->rq_size_log2));
+ 		*cookie = *(wq->rq + Q_PTR2IDX(wq->rq_rptr, wq->rq_size_log2));
+ 		wq->rq_rptr++;
+@@ -1255,11 +1255,11 @@ flush_wq:
+ skip_cqe:
+ 	if (SW_CQE(*hw_cqe)) {
+ 		PDBG("%s cq %p cqid 0x%x skip sw cqe sw_rptr 0x%x\n",
+-		     __FUNCTION__, cq, cq->cqid, cq->sw_rptr);
++		     __func__, cq, cq->cqid, cq->sw_rptr);
+ 		++cq->sw_rptr;
+ 	} else {
+ 		PDBG("%s cq %p cqid 0x%x skip hw cqe rptr 0x%x\n",
+-		     __FUNCTION__, cq, cq->cqid, cq->rptr);
++		     __func__, cq, cq->cqid, cq->rptr);
+ 		++cq->rptr;
+ 
+ 		/*
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c
+index d3095ae..45ed4f2 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_resource.c
++++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c
+@@ -206,13 +206,13 @@ void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag)
+ u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp)
+ {
+ 	u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo);
+-	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
++	PDBG("%s qpid 0x%x\n", __func__, qpid);
+ 	return qpid;
+ }
+ 
+ void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid)
+ {
+-	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
++	PDBG("%s qpid 0x%x\n", __func__, qpid);
+ 	cxio_hal_put_resource(rscp->qpid_fifo, qpid);
+ }
+ 
+@@ -255,13 +255,13 @@ void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp)
+ u32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size)
+ {
+ 	unsigned long addr = gen_pool_alloc(rdev_p->pbl_pool, size);
+-	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, (u32)addr, size);
++	PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
+ 	return (u32)addr;
+ }
+ 
+ void cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
+ {
+-	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, addr, size);
++	PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
+ 	gen_pool_free(rdev_p->pbl_pool, (unsigned long)addr, size);
+ }
+ 
+@@ -292,13 +292,13 @@ void cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p)
+ u32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size)
+ {
+ 	unsigned long addr = gen_pool_alloc(rdev_p->rqt_pool, size << 6);
+-	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, (u32)addr, size << 6);
++	PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6);
+ 	return (u32)addr;
+ }
+ 
+ void cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
+ {
+-	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, addr, size << 6);
++	PDBG("%s addr 0x%x size %d\n", __func__, addr, size << 6);
+ 	gen_pool_free(rdev_p->rqt_pool, (unsigned long)addr, size << 6);
+ }
+ 
+diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c
+index 0315c9d..6ba4138 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch.c
++++ b/drivers/infiniband/hw/cxgb3/iwch.c
+@@ -65,7 +65,7 @@ static DEFINE_MUTEX(dev_mutex);
+ 
+ static void rnic_init(struct iwch_dev *rnicp)
+ {
+-	PDBG("%s iwch_dev %p\n", __FUNCTION__,  rnicp);
++	PDBG("%s iwch_dev %p\n", __func__,  rnicp);
+ 	idr_init(&rnicp->cqidr);
+ 	idr_init(&rnicp->qpidr);
+ 	idr_init(&rnicp->mmidr);
+@@ -106,7 +106,7 @@ static void open_rnic_dev(struct t3cdev *tdev)
+ 	struct iwch_dev *rnicp;
+ 	static int vers_printed;
+ 
+-	PDBG("%s t3cdev %p\n", __FUNCTION__,  tdev);
++	PDBG("%s t3cdev %p\n", __func__,  tdev);
+ 	if (!vers_printed++)
+ 		printk(KERN_INFO MOD "Chelsio T3 RDMA Driver - version %s\n",
+ 		       DRV_VERSION);
+@@ -144,7 +144,7 @@ static void open_rnic_dev(struct t3cdev *tdev)
+ static void close_rnic_dev(struct t3cdev *tdev)
+ {
+ 	struct iwch_dev *dev, *tmp;
+-	PDBG("%s t3cdev %p\n", __FUNCTION__,  tdev);
++	PDBG("%s t3cdev %p\n", __func__,  tdev);
+ 	mutex_lock(&dev_mutex);
+ 	list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
+ 		if (dev->rdev.t3cdev_p == tdev) {
+diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h
+index caf4e60..9ad9b1e 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch.h
++++ b/drivers/infiniband/hw/cxgb3/iwch.h
+@@ -147,7 +147,7 @@ static inline int insert_handle(struct iwch_dev *rhp, struct idr *idr,
+ 				void *handle, u32 id)
+ {
+ 	int ret;
+-	u32 newid;
++	int newid;
+ 
+ 	do {
+ 		if (!idr_pre_get(idr, GFP_KERNEL)) {
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
+index 99f2f2a..72ca360 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
+@@ -110,9 +110,9 @@ static void connect_reply_upcall(struct iwch_ep *ep, int status);
+ 
+ static void start_ep_timer(struct iwch_ep *ep)
+ {
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	if (timer_pending(&ep->timer)) {
+-		PDBG("%s stopped / restarted timer ep %p\n", __FUNCTION__, ep);
++		PDBG("%s stopped / restarted timer ep %p\n", __func__, ep);
+ 		del_timer_sync(&ep->timer);
+ 	} else
+ 		get_ep(&ep->com);
+@@ -124,7 +124,7 @@ static void start_ep_timer(struct iwch_ep *ep)
+ 
+ static void stop_ep_timer(struct iwch_ep *ep)
+ {
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	del_timer_sync(&ep->timer);
+ 	put_ep(&ep->com);
+ }
+@@ -190,7 +190,7 @@ int iwch_resume_tid(struct iwch_ep *ep)
+ 
+ static void set_emss(struct iwch_ep *ep, u16 opt)
+ {
+-	PDBG("%s ep %p opt %u\n", __FUNCTION__, ep, opt);
++	PDBG("%s ep %p opt %u\n", __func__, ep, opt);
+ 	ep->emss = T3C_DATA(ep->com.tdev)->mtus[G_TCPOPT_MSS(opt)] - 40;
+ 	if (G_TCPOPT_TSTAMP(opt))
+ 		ep->emss -= 12;
+@@ -220,7 +220,7 @@ static void state_set(struct iwch_ep_common *epc, enum iwch_ep_state new)
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&epc->lock, flags);
+-	PDBG("%s - %s -> %s\n", __FUNCTION__, states[epc->state], states[new]);
++	PDBG("%s - %s -> %s\n", __func__, states[epc->state], states[new]);
+ 	__state_set(epc, new);
+ 	spin_unlock_irqrestore(&epc->lock, flags);
+ 	return;
+@@ -236,7 +236,7 @@ static void *alloc_ep(int size, gfp_t gfp)
+ 		spin_lock_init(&epc->lock);
+ 		init_waitqueue_head(&epc->waitq);
+ 	}
+-	PDBG("%s alloc ep %p\n", __FUNCTION__, epc);
++	PDBG("%s alloc ep %p\n", __func__, epc);
+ 	return epc;
+ }
+ 
+@@ -244,13 +244,13 @@ void __free_ep(struct kref *kref)
+ {
+ 	struct iwch_ep_common *epc;
+ 	epc = container_of(kref, struct iwch_ep_common, kref);
+-	PDBG("%s ep %p state %s\n", __FUNCTION__, epc, states[state_read(epc)]);
++	PDBG("%s ep %p state %s\n", __func__, epc, states[state_read(epc)]);
+ 	kfree(epc);
+ }
+ 
+ static void release_ep_resources(struct iwch_ep *ep)
+ {
+-	PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, ep->hwtid);
++	PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
+ 	cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
+ 	dst_release(ep->dst);
+ 	l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+@@ -349,7 +349,7 @@ static unsigned int find_best_mtu(const struct t3c_data *d, unsigned short mtu)
+ 
+ static void arp_failure_discard(struct t3cdev *dev, struct sk_buff *skb)
+ {
+-	PDBG("%s t3cdev %p\n", __FUNCTION__, dev);
++	PDBG("%s t3cdev %p\n", __func__, dev);
+ 	kfree_skb(skb);
+ }
+ 
+@@ -370,7 +370,7 @@ static void abort_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
+ {
+ 	struct cpl_abort_req *req = cplhdr(skb);
+ 
+-	PDBG("%s t3cdev %p\n", __FUNCTION__, dev);
++	PDBG("%s t3cdev %p\n", __func__, dev);
+ 	req->cmd = CPL_ABORT_NO_RST;
+ 	cxgb3_ofld_send(dev, skb);
+ }
+@@ -380,10 +380,10 @@ static int send_halfclose(struct iwch_ep *ep, gfp_t gfp)
+ 	struct cpl_close_con_req *req;
+ 	struct sk_buff *skb;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	skb = get_skb(NULL, sizeof(*req), gfp);
+ 	if (!skb) {
+-		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	skb->priority = CPL_PRIORITY_DATA;
+@@ -400,11 +400,11 @@ static int send_abort(struct iwch_ep *ep, struct sk_buff *skb, gfp_t gfp)
+ {
+ 	struct cpl_abort_req *req;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	skb = get_skb(skb, sizeof(*req), gfp);
+ 	if (!skb) {
+ 		printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return -ENOMEM;
+ 	}
+ 	skb->priority = CPL_PRIORITY_DATA;
+@@ -426,12 +426,12 @@ static int send_connect(struct iwch_ep *ep)
+ 	unsigned int mtu_idx;
+ 	int wscale;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 
+ 	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+ 	if (!skb) {
+ 		printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return -ENOMEM;
+ 	}
+ 	mtu_idx = find_best_mtu(T3C_DATA(ep->com.tdev), dst_mtu(ep->dst));
+@@ -470,7 +470,7 @@ static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb)
+ 	struct mpa_message *mpa;
+ 	int len;
+ 
+-	PDBG("%s ep %p pd_len %d\n", __FUNCTION__, ep, ep->plen);
++	PDBG("%s ep %p pd_len %d\n", __func__, ep, ep->plen);
+ 
+ 	BUG_ON(skb_cloned(skb));
+ 
+@@ -530,13 +530,13 @@ static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen)
+ 	struct mpa_message *mpa;
+ 	struct sk_buff *skb;
+ 
+-	PDBG("%s ep %p plen %d\n", __FUNCTION__, ep, plen);
++	PDBG("%s ep %p plen %d\n", __func__, ep, plen);
+ 
+ 	mpalen = sizeof(*mpa) + plen;
+ 
+ 	skb = get_skb(NULL, mpalen + sizeof(*req), GFP_KERNEL);
+ 	if (!skb) {
+-		printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	skb_reserve(skb, sizeof(*req));
+@@ -580,13 +580,13 @@ static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen)
+ 	int len;
+ 	struct sk_buff *skb;
+ 
+-	PDBG("%s ep %p plen %d\n", __FUNCTION__, ep, plen);
++	PDBG("%s ep %p plen %d\n", __func__, ep, plen);
+ 
+ 	mpalen = sizeof(*mpa) + plen;
+ 
+ 	skb = get_skb(NULL, mpalen + sizeof(*req), GFP_KERNEL);
+ 	if (!skb) {
+-		printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	skb->priority = CPL_PRIORITY_DATA;
+@@ -630,7 +630,7 @@ static int act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	struct cpl_act_establish *req = cplhdr(skb);
+ 	unsigned int tid = GET_TID(req);
+ 
+-	PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, tid);
++	PDBG("%s ep %p tid %d\n", __func__, ep, tid);
+ 
+ 	dst_confirm(ep->dst);
+ 
+@@ -663,7 +663,7 @@ static void close_complete_upcall(struct iwch_ep *ep)
+ {
+ 	struct iw_cm_event event;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	memset(&event, 0, sizeof(event));
+ 	event.event = IW_CM_EVENT_CLOSE;
+ 	if (ep->com.cm_id) {
+@@ -680,7 +680,7 @@ static void peer_close_upcall(struct iwch_ep *ep)
+ {
+ 	struct iw_cm_event event;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	memset(&event, 0, sizeof(event));
+ 	event.event = IW_CM_EVENT_DISCONNECT;
+ 	if (ep->com.cm_id) {
+@@ -694,7 +694,7 @@ static void peer_abort_upcall(struct iwch_ep *ep)
+ {
+ 	struct iw_cm_event event;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	memset(&event, 0, sizeof(event));
+ 	event.event = IW_CM_EVENT_CLOSE;
+ 	event.status = -ECONNRESET;
+@@ -712,7 +712,7 @@ static void connect_reply_upcall(struct iwch_ep *ep, int status)
+ {
+ 	struct iw_cm_event event;
+ 
+-	PDBG("%s ep %p status %d\n", __FUNCTION__, ep, status);
++	PDBG("%s ep %p status %d\n", __func__, ep, status);
+ 	memset(&event, 0, sizeof(event));
+ 	event.event = IW_CM_EVENT_CONNECT_REPLY;
+ 	event.status = status;
+@@ -724,7 +724,7 @@ static void connect_reply_upcall(struct iwch_ep *ep, int status)
+ 		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+ 	}
+ 	if (ep->com.cm_id) {
+-		PDBG("%s ep %p tid %d status %d\n", __FUNCTION__, ep,
++		PDBG("%s ep %p tid %d status %d\n", __func__, ep,
+ 		     ep->hwtid, status);
+ 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+ 	}
+@@ -739,7 +739,7 @@ static void connect_request_upcall(struct iwch_ep *ep)
+ {
+ 	struct iw_cm_event event;
+ 
+-	PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, ep->hwtid);
++	PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
+ 	memset(&event, 0, sizeof(event));
+ 	event.event = IW_CM_EVENT_CONNECT_REQUEST;
+ 	event.local_addr = ep->com.local_addr;
+@@ -759,11 +759,11 @@ static void established_upcall(struct iwch_ep *ep)
+ {
+ 	struct iw_cm_event event;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	memset(&event, 0, sizeof(event));
+ 	event.event = IW_CM_EVENT_ESTABLISHED;
+ 	if (ep->com.cm_id) {
+-		PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, ep->hwtid);
++		PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
+ 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+ 	}
+ }
+@@ -773,7 +773,7 @@ static int update_rx_credits(struct iwch_ep *ep, u32 credits)
+ 	struct cpl_rx_data_ack *req;
+ 	struct sk_buff *skb;
+ 
+-	PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
++	PDBG("%s ep %p credits %u\n", __func__, ep, credits);
+ 	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+ 	if (!skb) {
+ 		printk(KERN_ERR MOD "update_rx_credits - cannot alloc skb!\n");
+@@ -797,7 +797,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
+ 	enum iwch_qp_attr_mask mask;
+ 	int err;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 
+ 	/*
+ 	 * Stop mpa timer.  If it expired, then the state has
+@@ -884,7 +884,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
+ 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
+ 	ep->mpa_attr.version = mpa_rev;
+ 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
+-	     "xmit_marker_enabled=%d, version=%d\n", __FUNCTION__,
++	     "xmit_marker_enabled=%d, version=%d\n", __func__,
+ 	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
+ 	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+ 
+@@ -915,7 +915,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ 	struct mpa_message *mpa;
+ 	u16 plen;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 
+ 	/*
+ 	 * Stop mpa timer.  If it expired, then the state has
+@@ -935,7 +935,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ 		return;
+ 	}
+ 
+-	PDBG("%s enter (%s line %u)\n", __FUNCTION__, __FILE__, __LINE__);
++	PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
+ 
+ 	/*
+ 	 * Copy the new data into our accumulation buffer.
+@@ -950,7 +950,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ 	 */
+ 	if (ep->mpa_pkt_len < sizeof(*mpa))
+ 		return;
+-	PDBG("%s enter (%s line %u)\n", __FUNCTION__, __FILE__, __LINE__);
++	PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
+ 	mpa = (struct mpa_message *) ep->mpa_pkt;
+ 
+ 	/*
+@@ -1000,7 +1000,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
+ 	ep->mpa_attr.version = mpa_rev;
+ 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
+-	     "xmit_marker_enabled=%d, version=%d\n", __FUNCTION__,
++	     "xmit_marker_enabled=%d, version=%d\n", __func__,
+ 	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
+ 	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+ 
+@@ -1017,7 +1017,7 @@ static int rx_data(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	struct cpl_rx_data *hdr = cplhdr(skb);
+ 	unsigned int dlen = ntohs(hdr->len);
+ 
+-	PDBG("%s ep %p dlen %u\n", __FUNCTION__, ep, dlen);
++	PDBG("%s ep %p dlen %u\n", __func__, ep, dlen);
+ 
+ 	skb_pull(skb, sizeof(*hdr));
+ 	skb_trim(skb, dlen);
+@@ -1037,7 +1037,7 @@ static int rx_data(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	default:
+ 		printk(KERN_ERR MOD "%s Unexpected streaming data."
+ 		       " ep %p state %d tid %d\n",
+-		       __FUNCTION__, ep, state_read(&ep->com), ep->hwtid);
++		       __func__, ep, state_read(&ep->com), ep->hwtid);
+ 
+ 		/*
+ 		 * The ep will timeout and inform the ULP of the failure.
+@@ -1063,7 +1063,7 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	struct cpl_wr_ack *hdr = cplhdr(skb);
+ 	unsigned int credits = ntohs(hdr->credits);
+ 
+-	PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
++	PDBG("%s ep %p credits %u\n", __func__, ep, credits);
+ 
+ 	if (credits == 0)
+ 		return CPL_RET_BUF_DONE;
+@@ -1084,7 +1084,7 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ {
+ 	struct iwch_ep *ep = ctx;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 
+ 	/*
+ 	 * We get 2 abort replies from the HW.  The first one must
+@@ -1115,7 +1115,7 @@ static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	struct iwch_ep *ep = ctx;
+ 	struct cpl_act_open_rpl *rpl = cplhdr(skb);
+ 
+-	PDBG("%s ep %p status %u errno %d\n", __FUNCTION__, ep, rpl->status,
++	PDBG("%s ep %p status %u errno %d\n", __func__, ep, rpl->status,
+ 	     status2errno(rpl->status));
+ 	connect_reply_upcall(ep, status2errno(rpl->status));
+ 	state_set(&ep->com, DEAD);
+@@ -1133,7 +1133,7 @@ static int listen_start(struct iwch_listen_ep *ep)
+ 	struct sk_buff *skb;
+ 	struct cpl_pass_open_req *req;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+ 	if (!skb) {
+ 		printk(KERN_ERR MOD "t3c_listen_start failed to alloc skb!\n");
+@@ -1162,7 +1162,7 @@ static int pass_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	struct iwch_listen_ep *ep = ctx;
+ 	struct cpl_pass_open_rpl *rpl = cplhdr(skb);
+ 
+-	PDBG("%s ep %p status %d error %d\n", __FUNCTION__, ep,
++	PDBG("%s ep %p status %d error %d\n", __func__, ep,
+ 	     rpl->status, status2errno(rpl->status));
+ 	ep->com.rpl_err = status2errno(rpl->status);
+ 	ep->com.rpl_done = 1;
+@@ -1176,10 +1176,10 @@ static int listen_stop(struct iwch_listen_ep *ep)
+ 	struct sk_buff *skb;
+ 	struct cpl_close_listserv_req *req;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+ 	if (!skb) {
+-		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	req = (struct cpl_close_listserv_req *) skb_put(skb, sizeof(*req));
+@@ -1197,7 +1197,7 @@ static int close_listsrv_rpl(struct t3cdev *tdev, struct sk_buff *skb,
+ 	struct iwch_listen_ep *ep = ctx;
+ 	struct cpl_close_listserv_rpl *rpl = cplhdr(skb);
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	ep->com.rpl_err = status2errno(rpl->status);
+ 	ep->com.rpl_done = 1;
+ 	wake_up(&ep->com.waitq);
+@@ -1211,7 +1211,7 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb)
+ 	u32 opt0h, opt0l, opt2;
+ 	int wscale;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	BUG_ON(skb_cloned(skb));
+ 	skb_trim(skb, sizeof(*rpl));
+ 	skb_get(skb);
+@@ -1244,7 +1244,7 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb)
+ static void reject_cr(struct t3cdev *tdev, u32 hwtid, __be32 peer_ip,
+ 		      struct sk_buff *skb)
+ {
+-	PDBG("%s t3cdev %p tid %u peer_ip %x\n", __FUNCTION__, tdev, hwtid,
++	PDBG("%s t3cdev %p tid %u peer_ip %x\n", __func__, tdev, hwtid,
+ 	     peer_ip);
+ 	BUG_ON(skb_cloned(skb));
+ 	skb_trim(skb, sizeof(struct cpl_tid_release));
+@@ -1279,11 +1279,11 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	struct rtable *rt;
+ 	struct iff_mac tim;
+ 
+-	PDBG("%s parent ep %p tid %u\n", __FUNCTION__, parent_ep, hwtid);
++	PDBG("%s parent ep %p tid %u\n", __func__, parent_ep, hwtid);
+ 
+ 	if (state_read(&parent_ep->com) != LISTEN) {
+ 		printk(KERN_ERR "%s - listening ep not in LISTEN\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		goto reject;
+ 	}
+ 
+@@ -1295,7 +1295,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	if (tdev->ctl(tdev, GET_IFF_FROM_MAC, &tim) < 0 || !tim.dev) {
+ 		printk(KERN_ERR
+ 			"%s bad dst mac %02x %02x %02x %02x %02x %02x\n",
+-			__FUNCTION__,
++			__func__,
+ 			req->dst_mac[0],
+ 			req->dst_mac[1],
+ 			req->dst_mac[2],
+@@ -1313,21 +1313,21 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 			req->peer_port, G_PASS_OPEN_TOS(ntohl(req->tos_tid)));
+ 	if (!rt) {
+ 		printk(KERN_ERR MOD "%s - failed to find dst entry!\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		goto reject;
+ 	}
+ 	dst = &rt->u.dst;
+ 	l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
+ 	if (!l2t) {
+ 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		dst_release(dst);
+ 		goto reject;
+ 	}
+ 	child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL);
+ 	if (!child_ep) {
+ 		printk(KERN_ERR MOD "%s - failed to allocate ep entry!\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		l2t_release(L2DATA(tdev), l2t);
+ 		dst_release(dst);
+ 		goto reject;
+@@ -1362,7 +1362,7 @@ static int pass_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	struct iwch_ep *ep = ctx;
+ 	struct cpl_pass_establish *req = cplhdr(skb);
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	ep->snd_seq = ntohl(req->snd_isn);
+ 	ep->rcv_seq = ntohl(req->rcv_isn);
+ 
+@@ -1383,7 +1383,7 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	int disconnect = 1;
+ 	int release = 0;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	dst_confirm(ep->dst);
+ 
+ 	spin_lock_irqsave(&ep->com.lock, flags);
+@@ -1473,7 +1473,7 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	int state;
+ 
+ 	if (is_neg_adv_abort(req->status)) {
+-		PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
++		PDBG("%s neg_adv_abort ep %p tid %d\n", __func__, ep,
+ 		     ep->hwtid);
+ 		t3_l2t_send_event(ep->com.tdev, ep->l2t);
+ 		return CPL_RET_BUF_DONE;
+@@ -1489,7 +1489,7 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	}
+ 
+ 	state = state_read(&ep->com);
+-	PDBG("%s ep %p state %u\n", __FUNCTION__, ep, state);
++	PDBG("%s ep %p state %u\n", __func__, ep, state);
+ 	switch (state) {
+ 	case CONNECTING:
+ 		break;
+@@ -1528,14 +1528,14 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 			if (ret)
+ 				printk(KERN_ERR MOD
+ 				       "%s - qp <- error failed!\n",
+-				       __FUNCTION__);
++				       __func__);
+ 		}
+ 		peer_abort_upcall(ep);
+ 		break;
+ 	case ABORTING:
+ 		break;
+ 	case DEAD:
+-		PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __FUNCTION__);
++		PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__);
+ 		return CPL_RET_BUF_DONE;
+ 	default:
+ 		BUG_ON(1);
+@@ -1546,7 +1546,7 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
+ 	if (!rpl_skb) {
+ 		printk(KERN_ERR MOD "%s - cannot allocate skb!\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		dst_release(ep->dst);
+ 		l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+ 		put_ep(&ep->com);
+@@ -1573,7 +1573,7 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	unsigned long flags;
+ 	int release = 0;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	BUG_ON(!ep);
+ 
+ 	/* The cm_id may be null if we failed to connect */
+@@ -1624,9 +1624,9 @@ static int terminate(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ {
+ 	struct iwch_ep *ep = ctx;
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	skb_pull(skb, sizeof(struct cpl_rdma_terminate));
+-	PDBG("%s saving %d bytes of term msg\n", __FUNCTION__, skb->len);
++	PDBG("%s saving %d bytes of term msg\n", __func__, skb->len);
+ 	skb_copy_from_linear_data(skb, ep->com.qp->attr.terminate_buffer,
+ 				  skb->len);
+ 	ep->com.qp->attr.terminate_msg_len = skb->len;
+@@ -1639,13 +1639,13 @@ static int ec_status(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	struct cpl_rdma_ec_status *rep = cplhdr(skb);
+ 	struct iwch_ep *ep = ctx;
+ 
+-	PDBG("%s ep %p tid %u status %d\n", __FUNCTION__, ep, ep->hwtid,
++	PDBG("%s ep %p tid %u status %d\n", __func__, ep, ep->hwtid,
+ 	     rep->status);
+ 	if (rep->status) {
+ 		struct iwch_qp_attributes attrs;
+ 
+ 		printk(KERN_ERR MOD "%s BAD CLOSE - Aborting tid %u\n",
+-		       __FUNCTION__, ep->hwtid);
++		       __func__, ep->hwtid);
+ 		stop_ep_timer(ep);
+ 		attrs.next_state = IWCH_QP_STATE_ERROR;
+ 		iwch_modify_qp(ep->com.qp->rhp,
+@@ -1663,7 +1663,7 @@ static void ep_timeout(unsigned long arg)
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&ep->com.lock, flags);
+-	PDBG("%s ep %p tid %u state %d\n", __FUNCTION__, ep, ep->hwtid,
++	PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid,
+ 	     ep->com.state);
+ 	switch (ep->com.state) {
+ 	case MPA_REQ_SENT:
+@@ -1693,7 +1693,7 @@ int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
+ {
+ 	int err;
+ 	struct iwch_ep *ep = to_ep(cm_id);
+-	PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
++	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
+ 
+ 	if (state_read(&ep->com) == DEAD) {
+ 		put_ep(&ep->com);
+@@ -1718,7 +1718,7 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ 	struct iwch_dev *h = to_iwch_dev(cm_id->device);
+ 	struct iwch_qp *qp = get_qhp(h, conn_param->qpn);
+ 
+-	PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
++	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
+ 	if (state_read(&ep->com) == DEAD)
+ 		return -ECONNRESET;
+ 
+@@ -1739,7 +1739,7 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ 	ep->com.rpl_err = 0;
+ 	ep->ird = conn_param->ird;
+ 	ep->ord = conn_param->ord;
+-	PDBG("%s %d ird %d ord %d\n", __FUNCTION__, __LINE__, ep->ird, ep->ord);
++	PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
+ 
+ 	get_ep(&ep->com);
+ 
+@@ -1810,7 +1810,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ 
+ 	ep = alloc_ep(sizeof(*ep), GFP_KERNEL);
+ 	if (!ep) {
+-		printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__);
+ 		err = -ENOMEM;
+ 		goto out;
+ 	}
+@@ -1827,7 +1827,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ 	ep->com.cm_id = cm_id;
+ 	ep->com.qp = get_qhp(h, conn_param->qpn);
+ 	BUG_ON(!ep->com.qp);
+-	PDBG("%s qpn 0x%x qp %p cm_id %p\n", __FUNCTION__, conn_param->qpn,
++	PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn,
+ 	     ep->com.qp, cm_id);
+ 
+ 	/*
+@@ -1835,7 +1835,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ 	 */
+ 	ep->atid = cxgb3_alloc_atid(h->rdev.t3cdev_p, &t3c_client, ep);
+ 	if (ep->atid == -1) {
+-		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
+ 		err = -ENOMEM;
+ 		goto fail2;
+ 	}
+@@ -1847,7 +1847,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ 			cm_id->local_addr.sin_port,
+ 			cm_id->remote_addr.sin_port, IPTOS_LOWDELAY);
+ 	if (!rt) {
+-		printk(KERN_ERR MOD "%s - cannot find route.\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
+ 		err = -EHOSTUNREACH;
+ 		goto fail3;
+ 	}
+@@ -1857,7 +1857,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ 	ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
+ 			     ep->dst->neighbour->dev);
+ 	if (!ep->l2t) {
+-		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
+ 		err = -ENOMEM;
+ 		goto fail4;
+ 	}
+@@ -1894,11 +1894,11 @@ int iwch_create_listen(struct iw_cm_id *cm_id, int backlog)
+ 
+ 	ep = alloc_ep(sizeof(*ep), GFP_KERNEL);
+ 	if (!ep) {
+-		printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__);
+ 		err = -ENOMEM;
+ 		goto fail1;
+ 	}
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 	ep->com.tdev = h->rdev.t3cdev_p;
+ 	cm_id->add_ref(cm_id);
+ 	ep->com.cm_id = cm_id;
+@@ -1910,7 +1910,7 @@ int iwch_create_listen(struct iw_cm_id *cm_id, int backlog)
+ 	 */
+ 	ep->stid = cxgb3_alloc_stid(h->rdev.t3cdev_p, &t3c_client, ep);
+ 	if (ep->stid == -1) {
+-		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __FUNCTION__);
++		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
+ 		err = -ENOMEM;
+ 		goto fail2;
+ 	}
+@@ -1942,7 +1942,7 @@ int iwch_destroy_listen(struct iw_cm_id *cm_id)
+ 	int err;
+ 	struct iwch_listen_ep *ep = to_listen_ep(cm_id);
+ 
+-	PDBG("%s ep %p\n", __FUNCTION__, ep);
++	PDBG("%s ep %p\n", __func__, ep);
+ 
+ 	might_sleep();
+ 	state_set(&ep->com, DEAD);
+@@ -1965,11 +1965,11 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp)
+ 
+ 	spin_lock_irqsave(&ep->com.lock, flags);
+ 
+-	PDBG("%s ep %p state %s, abrupt %d\n", __FUNCTION__, ep,
++	PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep,
+ 	     states[ep->com.state], abrupt);
+ 
+ 	if (ep->com.state == DEAD) {
+-		PDBG("%s already dead ep %p\n", __FUNCTION__, ep);
++		PDBG("%s already dead ep %p\n", __func__, ep);
+ 		goto out;
+ 	}
+ 
+@@ -2020,7 +2020,7 @@ int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
+ 	if (ep->dst != old)
+ 		return 0;
+ 
+-	PDBG("%s ep %p redirect to dst %p l2t %p\n", __FUNCTION__, ep, new,
++	PDBG("%s ep %p redirect to dst %p l2t %p\n", __func__, ep, new,
+ 	     l2t);
+ 	dst_hold(new);
+ 	l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
+index 6107e7c..2bb7fbd 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
++++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
+@@ -54,13 +54,13 @@
+ #define MPA_FLAGS_MASK		0xE0
+ 
+ #define put_ep(ep) { \
+-	PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __FUNCTION__, __LINE__,  \
++	PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__,  \
+ 	     ep, atomic_read(&((ep)->kref.refcount))); \
+ 	kref_put(&((ep)->kref), __free_ep); \
+ }
+ 
+ #define get_ep(ep) { \
+-	PDBG("get_ep (via %s:%u) ep %p, refcnt %d\n", __FUNCTION__, __LINE__, \
++	PDBG("get_ep (via %s:%u) ep %p, refcnt %d\n", __func__, __LINE__, \
+ 	     ep, atomic_read(&((ep)->kref.refcount))); \
+ 	kref_get(&((ep)->kref));  \
+ }
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_cq.c b/drivers/infiniband/hw/cxgb3/iwch_cq.c
+index d7624c1..4ee8ccd 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_cq.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_cq.c
+@@ -67,7 +67,7 @@ static int iwch_poll_cq_one(struct iwch_dev *rhp, struct iwch_cq *chp,
+ 	ret = cxio_poll_cq(wq, &(chp->cq), &cqe, &cqe_flushed, &cookie,
+ 				   &credit);
+ 	if (t3a_device(chp->rhp) && credit) {
+-		PDBG("%s updating %d cq credits on id %d\n", __FUNCTION__,
++		PDBG("%s updating %d cq credits on id %d\n", __func__,
+ 		     credit, chp->cq.cqid);
+ 		cxio_hal_cq_op(&rhp->rdev, &chp->cq, CQ_CREDIT_UPDATE, credit);
+ 	}
+@@ -83,7 +83,7 @@ static int iwch_poll_cq_one(struct iwch_dev *rhp, struct iwch_cq *chp,
+ 	wc->vendor_err = CQE_STATUS(cqe);
+ 
+ 	PDBG("%s qpid 0x%x type %d opcode %d status 0x%x wrid hi 0x%x "
+-	     "lo 0x%x cookie 0x%llx\n", __FUNCTION__,
++	     "lo 0x%x cookie 0x%llx\n", __func__,
+ 	     CQE_QPID(cqe), CQE_TYPE(cqe),
+ 	     CQE_OPCODE(cqe), CQE_STATUS(cqe), CQE_WRID_HI(cqe),
+ 	     CQE_WRID_LOW(cqe), (unsigned long long) cookie);
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
+index b406766..7b67a67 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_ev.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
+@@ -52,7 +52,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
+ 
+ 	if (!qhp) {
+ 		printk(KERN_ERR "%s unaffiliated error 0x%x qpid 0x%x\n",
+-		       __FUNCTION__, CQE_STATUS(rsp_msg->cqe),
++		       __func__, CQE_STATUS(rsp_msg->cqe),
+ 		       CQE_QPID(rsp_msg->cqe));
+ 		spin_unlock(&rnicp->lock);
+ 		return;
+@@ -61,14 +61,14 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
+ 	if ((qhp->attr.state == IWCH_QP_STATE_ERROR) ||
+ 	    (qhp->attr.state == IWCH_QP_STATE_TERMINATE)) {
+ 		PDBG("%s AE received after RTS - "
+-		     "qp state %d qpid 0x%x status 0x%x\n", __FUNCTION__,
++		     "qp state %d qpid 0x%x status 0x%x\n", __func__,
+ 		     qhp->attr.state, qhp->wq.qpid, CQE_STATUS(rsp_msg->cqe));
+ 		spin_unlock(&rnicp->lock);
+ 		return;
+ 	}
+ 
+ 	printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x "
+-	       "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
++	       "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __func__,
+ 	       CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
+ 	       CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
+ 	       CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+@@ -132,10 +132,10 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
+ 	    (CQE_STATUS(rsp_msg->cqe) == 0)) {
+ 		if (SQ_TYPE(rsp_msg->cqe)) {
+ 			PDBG("%s QPID 0x%x ep %p disconnecting\n",
+-			     __FUNCTION__, qhp->wq.qpid, qhp->ep);
++			     __func__, qhp->wq.qpid, qhp->ep);
+ 			iwch_ep_disconnect(qhp->ep, 0, GFP_ATOMIC);
+ 		} else {
+-			PDBG("%s post REQ_ERR AE QPID 0x%x\n", __FUNCTION__,
++			PDBG("%s post REQ_ERR AE QPID 0x%x\n", __func__,
+ 			     qhp->wq.qpid);
+ 			post_qp_event(rnicp, chp, rsp_msg,
+ 				      IB_EVENT_QP_REQ_ERR, 0);
+@@ -180,7 +180,7 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
+ 	case TPT_ERR_INVALIDATE_SHARED_MR:
+ 	case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:
+ 		printk(KERN_ERR "%s - CQE Err qpid 0x%x opcode %d status 0x%x "
+-		       "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
++		       "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __func__,
+ 		       CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
+ 		       CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
+ 		       CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_mem.c b/drivers/infiniband/hw/cxgb3/iwch_mem.c
+index b8797c6..58c3d61 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_mem.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_mem.c
+@@ -62,7 +62,7 @@ int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php,
+ 	mmid = stag >> 8;
+ 	mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
+ 	insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+-	PDBG("%s mmid 0x%x mhp %p\n", __FUNCTION__, mmid, mhp);
++	PDBG("%s mmid 0x%x mhp %p\n", __func__, mmid, mhp);
+ 	return 0;
+ }
+ 
+@@ -96,7 +96,7 @@ int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php,
+ 	mmid = stag >> 8;
+ 	mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
+ 	insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+-	PDBG("%s mmid 0x%x mhp %p\n", __FUNCTION__, mmid, mhp);
++	PDBG("%s mmid 0x%x mhp %p\n", __func__, mmid, mhp);
+ 	return 0;
+ }
+ 
+@@ -163,7 +163,7 @@ int build_phys_page_list(struct ib_phys_buf *buffer_list,
+ 			    ((u64) j << *shift));
+ 
+ 	PDBG("%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d\n",
+-	     __FUNCTION__, (unsigned long long) *iova_start,
++	     __func__, (unsigned long long) *iova_start,
+ 	     (unsigned long long) mask, *shift, (unsigned long long) *total_size,
+ 	     *npages);
+ 
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
+index b2ea921..ab4695c 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
+@@ -101,7 +101,7 @@ static int iwch_dealloc_ucontext(struct ib_ucontext *context)
+ 	struct iwch_ucontext *ucontext = to_iwch_ucontext(context);
+ 	struct iwch_mm_entry *mm, *tmp;
+ 
+-	PDBG("%s context %p\n", __FUNCTION__, context);
++	PDBG("%s context %p\n", __func__, context);
+ 	list_for_each_entry_safe(mm, tmp, &ucontext->mmaps, entry)
+ 		kfree(mm);
+ 	cxio_release_ucontext(&rhp->rdev, &ucontext->uctx);
+@@ -115,7 +115,7 @@ static struct ib_ucontext *iwch_alloc_ucontext(struct ib_device *ibdev,
+ 	struct iwch_ucontext *context;
+ 	struct iwch_dev *rhp = to_iwch_dev(ibdev);
+ 
+-	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++	PDBG("%s ibdev %p\n", __func__, ibdev);
+ 	context = kzalloc(sizeof(*context), GFP_KERNEL);
+ 	if (!context)
+ 		return ERR_PTR(-ENOMEM);
+@@ -129,7 +129,7 @@ static int iwch_destroy_cq(struct ib_cq *ib_cq)
+ {
+ 	struct iwch_cq *chp;
+ 
+-	PDBG("%s ib_cq %p\n", __FUNCTION__, ib_cq);
++	PDBG("%s ib_cq %p\n", __func__, ib_cq);
+ 	chp = to_iwch_cq(ib_cq);
+ 
+ 	remove_handle(chp->rhp, &chp->rhp->cqidr, chp->cq.cqid);
+@@ -151,7 +151,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
+ 	struct iwch_create_cq_req ureq;
+ 	struct iwch_ucontext *ucontext = NULL;
+ 
+-	PDBG("%s ib_dev %p entries %d\n", __FUNCTION__, ibdev, entries);
++	PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries);
+ 	rhp = to_iwch_dev(ibdev);
+ 	chp = kzalloc(sizeof(*chp), GFP_KERNEL);
+ 	if (!chp)
+@@ -233,7 +233,7 @@ static int iwch_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
+ 	struct t3_cq oldcq, newcq;
+ 	int ret;
+ 
+-	PDBG("%s ib_cq %p cqe %d\n", __FUNCTION__, cq, cqe);
++	PDBG("%s ib_cq %p cqe %d\n", __func__, cq, cqe);
+ 
+ 	/* We don't downsize... */
+ 	if (cqe <= cq->cqe)
+@@ -281,7 +281,7 @@ static int iwch_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
+ 	ret = cxio_destroy_cq(&chp->rhp->rdev, &oldcq);
+ 	if (ret) {
+ 		printk(KERN_ERR MOD "%s - cxio_destroy_cq failed %d\n",
+-			__FUNCTION__, ret);
++			__func__, ret);
+ 	}
+ 
+ 	/* add user hooks here */
+@@ -316,7 +316,7 @@ static int iwch_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
+ 		chp->cq.rptr = rptr;
+ 	} else
+ 		spin_lock_irqsave(&chp->lock, flag);
+-	PDBG("%s rptr 0x%x\n", __FUNCTION__, chp->cq.rptr);
++	PDBG("%s rptr 0x%x\n", __func__, chp->cq.rptr);
+ 	err = cxio_hal_cq_op(&rhp->rdev, &chp->cq, cq_op, 0);
+ 	spin_unlock_irqrestore(&chp->lock, flag);
+ 	if (err < 0)
+@@ -337,7 +337,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ 	struct iwch_ucontext *ucontext;
+ 	u64 addr;
+ 
+-	PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __FUNCTION__, vma->vm_pgoff,
++	PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __func__, vma->vm_pgoff,
+ 	     key, len);
+ 
+ 	if (vma->vm_start & (PAGE_SIZE-1)) {
+@@ -390,7 +390,7 @@ static int iwch_deallocate_pd(struct ib_pd *pd)
+ 
+ 	php = to_iwch_pd(pd);
+ 	rhp = php->rhp;
+-	PDBG("%s ibpd %p pdid 0x%x\n", __FUNCTION__, pd, php->pdid);
++	PDBG("%s ibpd %p pdid 0x%x\n", __func__, pd, php->pdid);
+ 	cxio_hal_put_pdid(rhp->rdev.rscp, php->pdid);
+ 	kfree(php);
+ 	return 0;
+@@ -404,7 +404,7 @@ static struct ib_pd *iwch_allocate_pd(struct ib_device *ibdev,
+ 	u32 pdid;
+ 	struct iwch_dev *rhp;
+ 
+-	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++	PDBG("%s ibdev %p\n", __func__, ibdev);
+ 	rhp = (struct iwch_dev *) ibdev;
+ 	pdid = cxio_hal_get_pdid(rhp->rdev.rscp);
+ 	if (!pdid)
+@@ -422,7 +422,7 @@ static struct ib_pd *iwch_allocate_pd(struct ib_device *ibdev,
+ 			return ERR_PTR(-EFAULT);
+ 		}
+ 	}
+-	PDBG("%s pdid 0x%0x ptr 0x%p\n", __FUNCTION__, pdid, php);
++	PDBG("%s pdid 0x%0x ptr 0x%p\n", __func__, pdid, php);
+ 	return &php->ibpd;
+ }
+ 
+@@ -432,7 +432,7 @@ static int iwch_dereg_mr(struct ib_mr *ib_mr)
+ 	struct iwch_mr *mhp;
+ 	u32 mmid;
+ 
+-	PDBG("%s ib_mr %p\n", __FUNCTION__, ib_mr);
++	PDBG("%s ib_mr %p\n", __func__, ib_mr);
+ 	/* There can be no memory windows */
+ 	if (atomic_read(&ib_mr->usecnt))
+ 		return -EINVAL;
+@@ -447,7 +447,7 @@ static int iwch_dereg_mr(struct ib_mr *ib_mr)
+ 		kfree((void *) (unsigned long) mhp->kva);
+ 	if (mhp->umem)
+ 		ib_umem_release(mhp->umem);
+-	PDBG("%s mmid 0x%x ptr %p\n", __FUNCTION__, mmid, mhp);
++	PDBG("%s mmid 0x%x ptr %p\n", __func__, mmid, mhp);
+ 	kfree(mhp);
+ 	return 0;
+ }
+@@ -467,7 +467,7 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd,
+ 	struct iwch_mr *mhp;
+ 	int ret;
+ 
+-	PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++	PDBG("%s ib_pd %p\n", __func__, pd);
+ 	php = to_iwch_pd(pd);
+ 	rhp = php->rhp;
+ 
+@@ -531,7 +531,7 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
+ 	int npages;
+ 	int ret;
+ 
+-	PDBG("%s ib_mr %p ib_pd %p\n", __FUNCTION__, mr, pd);
++	PDBG("%s ib_mr %p ib_pd %p\n", __func__, mr, pd);
+ 
+ 	/* There can be no memory windows */
+ 	if (atomic_read(&mr->usecnt))
+@@ -594,7 +594,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ 	struct iwch_mr *mhp;
+ 	struct iwch_reg_user_mr_resp uresp;
+ 
+-	PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++	PDBG("%s ib_pd %p\n", __func__, pd);
+ 
+ 	php = to_iwch_pd(pd);
+ 	rhp = php->rhp;
+@@ -649,7 +649,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ 	if (udata && !t3a_device(rhp)) {
+ 		uresp.pbl_addr = (mhp->attr.pbl_addr -
+ 	                         rhp->rdev.rnic_info.pbl_base) >> 3;
+-		PDBG("%s user resp pbl_addr 0x%x\n", __FUNCTION__,
++		PDBG("%s user resp pbl_addr 0x%x\n", __func__,
+ 		     uresp.pbl_addr);
+ 
+ 		if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) {
+@@ -673,7 +673,7 @@ static struct ib_mr *iwch_get_dma_mr(struct ib_pd *pd, int acc)
+ 	u64 kva;
+ 	struct ib_mr *ibmr;
+ 
+-	PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++	PDBG("%s ib_pd %p\n", __func__, pd);
+ 
+ 	/*
+ 	 * T3 only supports 32 bits of size.
+@@ -710,7 +710,7 @@ static struct ib_mw *iwch_alloc_mw(struct ib_pd *pd)
+ 	mhp->attr.stag = stag;
+ 	mmid = (stag) >> 8;
+ 	insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+-	PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __FUNCTION__, mmid, mhp, stag);
++	PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __func__, mmid, mhp, stag);
+ 	return &(mhp->ibmw);
+ }
+ 
+@@ -726,7 +726,7 @@ static int iwch_dealloc_mw(struct ib_mw *mw)
+ 	cxio_deallocate_window(&rhp->rdev, mhp->attr.stag);
+ 	remove_handle(rhp, &rhp->mmidr, mmid);
+ 	kfree(mhp);
+-	PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __FUNCTION__, mw, mmid, mhp);
++	PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __func__, mw, mmid, mhp);
+ 	return 0;
+ }
+ 
+@@ -754,7 +754,7 @@ static int iwch_destroy_qp(struct ib_qp *ib_qp)
+ 	cxio_destroy_qp(&rhp->rdev, &qhp->wq,
+ 			ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
+ 
+-	PDBG("%s ib_qp %p qpid 0x%0x qhp %p\n", __FUNCTION__,
++	PDBG("%s ib_qp %p qpid 0x%0x qhp %p\n", __func__,
+ 	     ib_qp, qhp->wq.qpid, qhp);
+ 	kfree(qhp);
+ 	return 0;
+@@ -773,7 +773,7 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
+ 	int wqsize, sqsize, rqsize;
+ 	struct iwch_ucontext *ucontext;
+ 
+-	PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++	PDBG("%s ib_pd %p\n", __func__, pd);
+ 	if (attrs->qp_type != IB_QPT_RC)
+ 		return ERR_PTR(-EINVAL);
+ 	php = to_iwch_pd(pd);
+@@ -805,7 +805,7 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
+ 	 */
+ 	sqsize = roundup_pow_of_two(attrs->cap.max_send_wr);
+ 	wqsize = roundup_pow_of_two(rqsize + sqsize);
+-	PDBG("%s wqsize %d sqsize %d rqsize %d\n", __FUNCTION__,
++	PDBG("%s wqsize %d sqsize %d rqsize %d\n", __func__,
+ 	     wqsize, sqsize, rqsize);
+ 	qhp = kzalloc(sizeof(*qhp), GFP_KERNEL);
+ 	if (!qhp)
+@@ -898,7 +898,7 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
+ 	init_timer(&(qhp->timer));
+ 	PDBG("%s sq_num_entries %d, rq_num_entries %d "
+ 	     "qpid 0x%0x qhp %p dma_addr 0x%llx size %d\n",
+-	     __FUNCTION__, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
++	     __func__, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
+ 	     qhp->wq.qpid, qhp, (unsigned long long) qhp->wq.dma_addr,
+ 	     1 << qhp->wq.size_log2);
+ 	return &qhp->ibqp;
+@@ -912,7 +912,7 @@ static int iwch_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ 	enum iwch_qp_attr_mask mask = 0;
+ 	struct iwch_qp_attributes attrs;
+ 
+-	PDBG("%s ib_qp %p\n", __FUNCTION__, ibqp);
++	PDBG("%s ib_qp %p\n", __func__, ibqp);
+ 
+ 	/* iwarp does not support the RTR state */
+ 	if ((attr_mask & IB_QP_STATE) && (attr->qp_state == IB_QPS_RTR))
+@@ -945,20 +945,20 @@ static int iwch_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ 
+ void iwch_qp_add_ref(struct ib_qp *qp)
+ {
+-	PDBG("%s ib_qp %p\n", __FUNCTION__, qp);
++	PDBG("%s ib_qp %p\n", __func__, qp);
+ 	atomic_inc(&(to_iwch_qp(qp)->refcnt));
+ }
+ 
+ void iwch_qp_rem_ref(struct ib_qp *qp)
+ {
+-	PDBG("%s ib_qp %p\n", __FUNCTION__, qp);
++	PDBG("%s ib_qp %p\n", __func__, qp);
+ 	if (atomic_dec_and_test(&(to_iwch_qp(qp)->refcnt)))
+ 	        wake_up(&(to_iwch_qp(qp)->wait));
+ }
+ 
+ static struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn)
+ {
+-	PDBG("%s ib_dev %p qpn 0x%x\n", __FUNCTION__, dev, qpn);
++	PDBG("%s ib_dev %p qpn 0x%x\n", __func__, dev, qpn);
+ 	return (struct ib_qp *)get_qhp(to_iwch_dev(dev), qpn);
+ }
+ 
+@@ -966,7 +966,7 @@ static struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn)
+ static int iwch_query_pkey(struct ib_device *ibdev,
+ 			   u8 port, u16 index, u16 * pkey)
+ {
+-	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++	PDBG("%s ibdev %p\n", __func__, ibdev);
+ 	*pkey = 0;
+ 	return 0;
+ }
+@@ -977,7 +977,7 @@ static int iwch_query_gid(struct ib_device *ibdev, u8 port,
+ 	struct iwch_dev *dev;
+ 
+ 	PDBG("%s ibdev %p, port %d, index %d, gid %p\n",
+-	       __FUNCTION__, ibdev, port, index, gid);
++	       __func__, ibdev, port, index, gid);
+ 	dev = to_iwch_dev(ibdev);
+ 	BUG_ON(port == 0 || port > 2);
+ 	memset(&(gid->raw[0]), 0, sizeof(gid->raw));
+@@ -990,7 +990,7 @@ static int iwch_query_device(struct ib_device *ibdev,
+ {
+ 
+ 	struct iwch_dev *dev;
+-	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++	PDBG("%s ibdev %p\n", __func__, ibdev);
+ 
+ 	dev = to_iwch_dev(ibdev);
+ 	memset(props, 0, sizeof *props);
+@@ -1017,7 +1017,7 @@ static int iwch_query_device(struct ib_device *ibdev,
+ static int iwch_query_port(struct ib_device *ibdev,
+ 			   u8 port, struct ib_port_attr *props)
+ {
+-	PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++	PDBG("%s ibdev %p\n", __func__, ibdev);
+ 	props->max_mtu = IB_MTU_4096;
+ 	props->lid = 0;
+ 	props->lmc = 0;
+@@ -1041,61 +1041,60 @@ static int iwch_query_port(struct ib_device *ibdev,
+ 	return 0;
+ }
+ 
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+-	struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+-					    ibdev.class_dev);
+-	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
+-	return sprintf(buf, "%d\n", dev->rdev.t3cdev_p->type);
++	struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
++						 ibdev.dev);
++	PDBG("%s dev 0x%p\n", __func__, dev);
++	return sprintf(buf, "%d\n", iwch_dev->rdev.t3cdev_p->type);
+ }
+ 
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+-					    ibdev.class_dev);
++	struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
++						 ibdev.dev);
+ 	struct ethtool_drvinfo info;
+-	struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
++	struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
+ 
+-	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
+-	rtnl_lock();
++	PDBG("%s dev 0x%p\n", __func__, dev);
+ 	lldev->ethtool_ops->get_drvinfo(lldev, &info);
+-	rtnl_unlock();
+ 	return sprintf(buf, "%s\n", info.fw_version);
+ }
+ 
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+-	struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+-					    ibdev.class_dev);
++	struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
++						 ibdev.dev);
+ 	struct ethtool_drvinfo info;
+-	struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
++	struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
+ 
+-	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
+-	rtnl_lock();
++	PDBG("%s dev 0x%p\n", __func__, dev);
+ 	lldev->ethtool_ops->get_drvinfo(lldev, &info);
+-	rtnl_unlock();
+ 	return sprintf(buf, "%s\n", info.driver);
+ }
+ 
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+-					    ibdev.class_dev);
+-	PDBG("%s class dev 0x%p\n", __FUNCTION__, dev);
+-	return sprintf(buf, "%x.%x\n", dev->rdev.rnic_info.pdev->vendor,
+-		                       dev->rdev.rnic_info.pdev->device);
++	struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
++						 ibdev.dev);
++	PDBG("%s dev 0x%p\n", __func__, dev);
++	return sprintf(buf, "%x.%x\n", iwch_dev->rdev.rnic_info.pdev->vendor,
++		       iwch_dev->rdev.rnic_info.pdev->device);
+ }
+ 
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
+ 
+-static struct class_device_attribute *iwch_class_attributes[] = {
+-	&class_device_attr_hw_rev,
+-	&class_device_attr_fw_ver,
+-	&class_device_attr_hca_type,
+-	&class_device_attr_board_id
++static struct device_attribute *iwch_class_attributes[] = {
++	&dev_attr_hw_rev,
++	&dev_attr_fw_ver,
++	&dev_attr_hca_type,
++	&dev_attr_board_id
+ };
+ 
+ int iwch_register_device(struct iwch_dev *dev)
+@@ -1103,14 +1102,13 @@ int iwch_register_device(struct iwch_dev *dev)
+ 	int ret;
+ 	int i;
+ 
+-	PDBG("%s iwch_dev %p\n", __FUNCTION__, dev);
++	PDBG("%s iwch_dev %p\n", __func__, dev);
+ 	strlcpy(dev->ibdev.name, "cxgb3_%d", IB_DEVICE_NAME_MAX);
+ 	memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid));
+ 	memcpy(&dev->ibdev.node_guid, dev->rdev.t3cdev_p->lldev->dev_addr, 6);
+ 	dev->ibdev.owner = THIS_MODULE;
+ 	dev->device_cap_flags =
+-	    (IB_DEVICE_ZERO_STAG |
+-	     IB_DEVICE_SEND_W_INV | IB_DEVICE_MEM_WINDOW);
++	    (IB_DEVICE_ZERO_STAG | IB_DEVICE_MEM_WINDOW);
+ 
+ 	dev->ibdev.uverbs_cmd_mask =
+ 	    (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
+@@ -1190,8 +1188,8 @@ int iwch_register_device(struct iwch_dev *dev)
+ 		goto bail1;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(iwch_class_attributes); ++i) {
+-		ret = class_device_create_file(&dev->ibdev.class_dev,
+-					       iwch_class_attributes[i]);
++		ret = device_create_file(&dev->ibdev.dev,
++					 iwch_class_attributes[i]);
+ 		if (ret) {
+ 			goto bail2;
+ 		}
+@@ -1207,10 +1205,10 @@ void iwch_unregister_device(struct iwch_dev *dev)
+ {
+ 	int i;
+ 
+-	PDBG("%s iwch_dev %p\n", __FUNCTION__, dev);
++	PDBG("%s iwch_dev %p\n", __func__, dev);
+ 	for (i = 0; i < ARRAY_SIZE(iwch_class_attributes); ++i)
+-		class_device_remove_file(&dev->ibdev.class_dev,
+-					 iwch_class_attributes[i]);
++		device_remove_file(&dev->ibdev.dev,
++				   iwch_class_attributes[i]);
+ 	ib_unregister_device(&dev->ibdev);
+ 	return;
+ }
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
+index 48833f3..61356f9 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
++++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
+@@ -213,7 +213,7 @@ static inline struct iwch_mm_entry *remove_mmap(struct iwch_ucontext *ucontext,
+ 		if (mm->key == key && mm->len == len) {
+ 			list_del_init(&mm->entry);
+ 			spin_unlock(&ucontext->mmap_lock);
+-			PDBG("%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__,
++			PDBG("%s key 0x%x addr 0x%llx len %d\n", __func__,
+ 			     key, (unsigned long long) mm->addr, mm->len);
+ 			return mm;
+ 		}
+@@ -226,7 +226,7 @@ static inline void insert_mmap(struct iwch_ucontext *ucontext,
+ 			       struct iwch_mm_entry *mm)
+ {
+ 	spin_lock(&ucontext->mmap_lock);
+-	PDBG("%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__,
++	PDBG("%s key 0x%x addr 0x%llx len %d\n", __func__,
+ 	     mm->key, (unsigned long long) mm->addr, mm->len);
+ 	list_add_tail(&mm->entry, &ucontext->mmaps);
+ 	spin_unlock(&ucontext->mmap_lock);
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
+index ea2cdd7..8891c3b 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
+@@ -72,7 +72,7 @@ static int iwch_build_rdma_send(union t3_wr *wqe, struct ib_send_wr *wr,
+ 	wqe->send.reserved[2] = 0;
+ 	if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+ 		plen = 4;
+-		wqe->send.sgl[0].stag = wr->imm_data;
++		wqe->send.sgl[0].stag = wr->ex.imm_data;
+ 		wqe->send.sgl[0].len = __constant_cpu_to_be32(0);
+ 		wqe->send.num_sgle = __constant_cpu_to_be32(0);
+ 		*flit_cnt = 5;
+@@ -112,7 +112,7 @@ static int iwch_build_rdma_write(union t3_wr *wqe, struct ib_send_wr *wr,
+ 
+ 	if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
+ 		plen = 4;
+-		wqe->write.sgl[0].stag = wr->imm_data;
++		wqe->write.sgl[0].stag = wr->ex.imm_data;
+ 		wqe->write.sgl[0].len = __constant_cpu_to_be32(0);
+ 		wqe->write.num_sgle = __constant_cpu_to_be32(0);
+ 		*flit_cnt = 6;
+@@ -168,30 +168,30 @@ static int iwch_sgl2pbl_map(struct iwch_dev *rhp, struct ib_sge *sg_list,
+ 
+ 		mhp = get_mhp(rhp, (sg_list[i].lkey) >> 8);
+ 		if (!mhp) {
+-			PDBG("%s %d\n", __FUNCTION__, __LINE__);
++			PDBG("%s %d\n", __func__, __LINE__);
+ 			return -EIO;
+ 		}
+ 		if (!mhp->attr.state) {
+-			PDBG("%s %d\n", __FUNCTION__, __LINE__);
++			PDBG("%s %d\n", __func__, __LINE__);
+ 			return -EIO;
+ 		}
+ 		if (mhp->attr.zbva) {
+-			PDBG("%s %d\n", __FUNCTION__, __LINE__);
++			PDBG("%s %d\n", __func__, __LINE__);
+ 			return -EIO;
+ 		}
+ 
+ 		if (sg_list[i].addr < mhp->attr.va_fbo) {
+-			PDBG("%s %d\n", __FUNCTION__, __LINE__);
++			PDBG("%s %d\n", __func__, __LINE__);
+ 			return -EINVAL;
+ 		}
+ 		if (sg_list[i].addr + ((u64) sg_list[i].length) <
+ 		    sg_list[i].addr) {
+-			PDBG("%s %d\n", __FUNCTION__, __LINE__);
++			PDBG("%s %d\n", __func__, __LINE__);
+ 			return -EINVAL;
+ 		}
+ 		if (sg_list[i].addr + ((u64) sg_list[i].length) >
+ 		    mhp->attr.va_fbo + ((u64) mhp->attr.len)) {
+-			PDBG("%s %d\n", __FUNCTION__, __LINE__);
++			PDBG("%s %d\n", __func__, __LINE__);
+ 			return -EINVAL;
+ 		}
+ 		offset = sg_list[i].addr - mhp->attr.va_fbo;
+@@ -290,7 +290,7 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ 				qhp->wq.oldest_read = sqp;
+ 			break;
+ 		default:
+-			PDBG("%s post of type=%d TBD!\n", __FUNCTION__,
++			PDBG("%s post of type=%d TBD!\n", __func__,
+ 			     wr->opcode);
+ 			err = -EINVAL;
+ 		}
+@@ -309,7 +309,7 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ 			       Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2),
+ 			       0, t3_wr_flit_cnt);
+ 		PDBG("%s cookie 0x%llx wq idx 0x%x swsq idx %ld opcode %d\n",
+-		     __FUNCTION__, (unsigned long long) wr->wr_id, idx,
++		     __func__, (unsigned long long) wr->wr_id, idx,
+ 		     Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2),
+ 		     sqp->opcode);
+ 		wr = wr->next;
+@@ -361,7 +361,7 @@ int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ 			       Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2),
+ 			       0, sizeof(struct t3_receive_wr) >> 3);
+ 		PDBG("%s cookie 0x%llx idx 0x%x rq_wptr 0x%x rw_rptr 0x%x "
+-		     "wqe %p \n", __FUNCTION__, (unsigned long long) wr->wr_id,
++		     "wqe %p \n", __func__, (unsigned long long) wr->wr_id,
+ 		     idx, qhp->wq.rq_wptr, qhp->wq.rq_rptr, wqe);
+ 		++(qhp->wq.rq_wptr);
+ 		++(qhp->wq.wptr);
+@@ -407,7 +407,7 @@ int iwch_bind_mw(struct ib_qp *qp,
+ 		return -ENOMEM;
+ 	}
+ 	idx = Q_PTR2IDX(qhp->wq.wptr, qhp->wq.size_log2);
+-	PDBG("%s: idx 0x%0x, mw 0x%p, mw_bind 0x%p\n", __FUNCTION__, idx,
++	PDBG("%s: idx 0x%0x, mw 0x%p, mw_bind 0x%p\n", __func__, idx,
+ 	     mw, mw_bind);
+ 	wqe = (union t3_wr *) (qhp->wq.queue + idx);
+ 
+@@ -595,10 +595,10 @@ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg)
+ 	struct terminate_message *term;
+ 	struct sk_buff *skb;
+ 
+-	PDBG("%s %d\n", __FUNCTION__, __LINE__);
++	PDBG("%s %d\n", __func__, __LINE__);
+ 	skb = alloc_skb(40, GFP_ATOMIC);
+ 	if (!skb) {
+-		printk(KERN_ERR "%s cannot send TERMINATE!\n", __FUNCTION__);
++		printk(KERN_ERR "%s cannot send TERMINATE!\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	wqe = (union t3_wr *)skb_put(skb, 40);
+@@ -629,7 +629,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+ 	rchp = get_chp(qhp->rhp, qhp->attr.rcq);
+ 	schp = get_chp(qhp->rhp, qhp->attr.scq);
+ 
+-	PDBG("%s qhp %p rchp %p schp %p\n", __FUNCTION__, qhp, rchp, schp);
++	PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
+ 	/* take a ref on the qhp since we must release the lock */
+ 	atomic_inc(&qhp->refcnt);
+ 	spin_unlock_irqrestore(&qhp->lock, *flag);
+@@ -720,11 +720,11 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ 	init_attr.flags |= capable(CAP_NET_BIND_SERVICE) ? PRIV_QP : 0;
+ 	init_attr.irs = qhp->ep->rcv_seq;
+ 	PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
+-	     "flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
++	     "flags 0x%x qpcaps 0x%x\n", __func__,
+ 	     init_attr.rq_addr, init_attr.rq_size,
+ 	     init_attr.flags, init_attr.qpcaps);
+ 	ret = cxio_rdma_init(&rhp->rdev, &init_attr);
+-	PDBG("%s ret %d\n", __FUNCTION__, ret);
++	PDBG("%s ret %d\n", __func__, ret);
+ 	return ret;
+ }
+ 
+@@ -742,7 +742,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ 	int free = 0;
+ 	struct iwch_ep *ep = NULL;
+ 
+-	PDBG("%s qhp %p qpid 0x%x ep %p state %d -> %d\n", __FUNCTION__,
++	PDBG("%s qhp %p qpid 0x%x ep %p state %d -> %d\n", __func__,
+ 	     qhp, qhp->wq.qpid, qhp->ep, qhp->attr.state,
+ 	     (mask & IWCH_QP_ATTR_NEXT_STATE) ? attrs->next_state : -1);
+ 
+@@ -899,14 +899,14 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ 		break;
+ 	default:
+ 		printk(KERN_ERR "%s in a bad state %d\n",
+-		       __FUNCTION__, qhp->attr.state);
++		       __func__, qhp->attr.state);
+ 		ret = -EINVAL;
+ 		goto err;
+ 		break;
+ 	}
+ 	goto out;
+ err:
+-	PDBG("%s disassociating ep %p qpid 0x%x\n", __FUNCTION__, qhp->ep,
++	PDBG("%s disassociating ep %p qpid 0x%x\n", __func__, qhp->ep,
+ 	     qhp->wq.qpid);
+ 
+ 	/* disassociate the LLP connection */
+@@ -939,7 +939,7 @@ out:
+ 	if (free)
+ 		put_ep(&ep->com);
+ 
+-	PDBG("%s exit state %d\n", __FUNCTION__, qhp->attr.state);
++	PDBG("%s exit state %d\n", __func__, qhp->attr.state);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
+index 194c1c3..56735ea 100644
+--- a/drivers/infiniband/hw/ehca/ehca_av.c
++++ b/drivers/infiniband/hw/ehca/ehca_av.c
+@@ -41,9 +41,6 @@
+  * POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+-
+-#include <asm/current.h>
+-
+ #include "ehca_tools.h"
+ #include "ehca_iverbs.h"
+ #include "hcp_if.h"
+@@ -170,17 +167,8 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ {
+ 	struct ehca_av *av;
+ 	struct ehca_ud_av new_ehca_av;
+-	struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+ 	struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca,
+ 					      ib_device);
+-	u32 cur_pid = current->tgid;
+-
+-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+-	    my_pd->ownpid != cur_pid) {
+-		ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		return -EINVAL;
+-	}
+ 
+ 	memset(&new_ehca_av, 0, sizeof(new_ehca_av));
+ 	new_ehca_av.sl = ah_attr->sl;
+@@ -242,15 +230,6 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ {
+ 	struct ehca_av *av = container_of(ah, struct ehca_av, ib_ah);
+-	struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+-	u32 cur_pid = current->tgid;
+-
+-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+-	    my_pd->ownpid != cur_pid) {
+-		ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		return -EINVAL;
+-	}
+ 
+ 	memcpy(&ah_attr->grh.dgid, &av->av.grh.word_3,
+ 	       sizeof(ah_attr->grh.dgid));
+@@ -273,16 +252,6 @@ int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ 
+ int ehca_destroy_ah(struct ib_ah *ah)
+ {
+-	struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+-	u32 cur_pid = current->tgid;
+-
+-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+-	    my_pd->ownpid != cur_pid) {
+-		ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		return -EINVAL;
+-	}
+-
+ 	kmem_cache_free(av_cache, container_of(ah, struct ehca_av, ib_ah));
+ 
+ 	return 0;
+diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
+index 92cce8a..0d13fe0 100644
+--- a/drivers/infiniband/hw/ehca/ehca_classes.h
++++ b/drivers/infiniband/hw/ehca/ehca_classes.h
+@@ -132,7 +132,6 @@ struct ehca_shca {
+ struct ehca_pd {
+ 	struct ib_pd ib_pd;
+ 	struct ipz_pd fw_pd;
+-	u32 ownpid;
+ 	/* small queue mgmt */
+ 	struct mutex lock;
+ 	struct list_head free[2];
+@@ -215,7 +214,6 @@ struct ehca_cq {
+ 	atomic_t nr_events; /* #events seen */
+ 	wait_queue_head_t wait_completion;
+ 	spinlock_t task_lock;
+-	u32 ownpid;
+ 	/* mmap counter for resources mapped into user space */
+ 	u32 mm_count_queue;
+ 	u32 mm_count_galpa;
+diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
+index 0467c15..ec0cfcf 100644
+--- a/drivers/infiniband/hw/ehca/ehca_cq.c
++++ b/drivers/infiniband/hw/ehca/ehca_cq.c
+@@ -43,8 +43,6 @@
+  * POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+-#include <asm/current.h>
+-
+ #include "ehca_iverbs.h"
+ #include "ehca_classes.h"
+ #include "ehca_irq.h"
+@@ -148,7 +146,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
+ 	spin_lock_init(&my_cq->task_lock);
+ 	atomic_set(&my_cq->nr_events, 0);
+ 	init_waitqueue_head(&my_cq->wait_completion);
+-	my_cq->ownpid = current->tgid;
+ 
+ 	cq = &my_cq->ib_cq;
+ 
+@@ -320,7 +317,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+ 	struct ehca_shca *shca = container_of(device, struct ehca_shca,
+ 					      ib_device);
+ 	struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+-	u32 cur_pid = current->tgid;
+ 	unsigned long flags;
+ 
+ 	if (cq->uobject) {
+@@ -329,12 +325,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+ 				 "user space cq_num=%x", my_cq->cq_number);
+ 			return -EINVAL;
+ 		}
+-		if (my_cq->ownpid != cur_pid) {
+-			ehca_err(device, "Invalid caller pid=%x ownpid=%x "
+-				 "cq_num=%x",
+-				 cur_pid, my_cq->ownpid, my_cq->cq_number);
+-			return -EINVAL;
+-		}
+ 	}
+ 
+ 	/*
+@@ -374,15 +364,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+ 
+ int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
+ {
+-	struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+-	u32 cur_pid = current->tgid;
+-
+-	if (cq->uobject && my_cq->ownpid != cur_pid) {
+-		ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_cq->ownpid);
+-		return -EINVAL;
+-	}
+-
+ 	/* TODO: proper resize needs to be done */
+ 	ehca_err(cq->device, "not implemented yet");
+ 
+diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
+index 5bd7b59..2515cbd 100644
+--- a/drivers/infiniband/hw/ehca/ehca_hca.c
++++ b/drivers/infiniband/hw/ehca/ehca_hca.c
+@@ -43,6 +43,11 @@
+ #include "ehca_iverbs.h"
+ #include "hcp_if.h"
+ 
++static unsigned int limit_uint(unsigned int value)
++{
++	return min_t(unsigned int, value, INT_MAX);
++}
++
+ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
+ {
+ 	int i, ret = 0;
+@@ -83,37 +88,40 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
+ 	props->vendor_id       = rblock->vendor_id >> 8;
+ 	props->vendor_part_id  = rblock->vendor_part_id >> 16;
+ 	props->hw_ver          = rblock->hw_ver;
+-	props->max_qp          = min_t(unsigned, rblock->max_qp, INT_MAX);
+-	props->max_qp_wr       = min_t(unsigned, rblock->max_wqes_wq, INT_MAX);
+-	props->max_sge         = min_t(unsigned, rblock->max_sge, INT_MAX);
+-	props->max_sge_rd      = min_t(unsigned, rblock->max_sge_rd, INT_MAX);
+-	props->max_cq          = min_t(unsigned, rblock->max_cq, INT_MAX);
+-	props->max_cqe         = min_t(unsigned, rblock->max_cqe, INT_MAX);
+-	props->max_mr          = min_t(unsigned, rblock->max_mr, INT_MAX);
+-	props->max_mw          = min_t(unsigned, rblock->max_mw, INT_MAX);
+-	props->max_pd          = min_t(unsigned, rblock->max_pd, INT_MAX);
+-	props->max_ah          = min_t(unsigned, rblock->max_ah, INT_MAX);
+-	props->max_fmr         = min_t(unsigned, rblock->max_mr, INT_MAX);
++	props->max_qp          = limit_uint(rblock->max_qp);
++	props->max_qp_wr       = limit_uint(rblock->max_wqes_wq);
++	props->max_sge         = limit_uint(rblock->max_sge);
++	props->max_sge_rd      = limit_uint(rblock->max_sge_rd);
++	props->max_cq          = limit_uint(rblock->max_cq);
++	props->max_cqe         = limit_uint(rblock->max_cqe);
++	props->max_mr          = limit_uint(rblock->max_mr);
++	props->max_mw          = limit_uint(rblock->max_mw);
++	props->max_pd          = limit_uint(rblock->max_pd);
++	props->max_ah          = limit_uint(rblock->max_ah);
++	props->max_ee          = limit_uint(rblock->max_rd_ee_context);
++	props->max_rdd         = limit_uint(rblock->max_rd_domain);
++	props->max_fmr         = limit_uint(rblock->max_mr);
++	props->local_ca_ack_delay  = limit_uint(rblock->local_ca_ack_delay);
++	props->max_qp_rd_atom  = limit_uint(rblock->max_rr_qp);
++	props->max_ee_rd_atom  = limit_uint(rblock->max_rr_ee_context);
++	props->max_res_rd_atom = limit_uint(rblock->max_rr_hca);
++	props->max_qp_init_rd_atom = limit_uint(rblock->max_act_wqs_qp);
++	props->max_ee_init_rd_atom = limit_uint(rblock->max_act_wqs_ee_context);
+ 
+ 	if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+-		props->max_srq         = props->max_qp;
+-		props->max_srq_wr      = props->max_qp_wr;
++		props->max_srq         = limit_uint(props->max_qp);
++		props->max_srq_wr      = limit_uint(props->max_qp_wr);
+ 		props->max_srq_sge     = 3;
+ 	}
+ 
+-	props->max_pkeys       = 16;
+-	props->local_ca_ack_delay
+-		= rblock->local_ca_ack_delay;
+-	props->max_raw_ipv6_qp
+-		= min_t(unsigned, rblock->max_raw_ipv6_qp, INT_MAX);
+-	props->max_raw_ethy_qp
+-		= min_t(unsigned, rblock->max_raw_ethy_qp, INT_MAX);
+-	props->max_mcast_grp
+-		= min_t(unsigned, rblock->max_mcast_grp, INT_MAX);
+-	props->max_mcast_qp_attach
+-		= min_t(unsigned, rblock->max_mcast_qp_attach, INT_MAX);
++	props->max_pkeys           = 16;
++	props->local_ca_ack_delay  = limit_uint(rblock->local_ca_ack_delay);
++	props->max_raw_ipv6_qp     = limit_uint(rblock->max_raw_ipv6_qp);
++	props->max_raw_ethy_qp     = limit_uint(rblock->max_raw_ethy_qp);
++	props->max_mcast_grp       = limit_uint(rblock->max_mcast_grp);
++	props->max_mcast_qp_attach = limit_uint(rblock->max_mcast_qp_attach);
+ 	props->max_total_mcast_qp_attach
+-		= min_t(unsigned, rblock->max_total_mcast_qp_attach, INT_MAX);
++		= limit_uint(rblock->max_total_mcast_qp_attach);
+ 
+ 	/* translate device capabilities */
+ 	props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
+@@ -128,6 +136,46 @@ query_device1:
+ 	return ret;
+ }
+ 
++static int map_mtu(struct ehca_shca *shca, u32 fw_mtu)
++{
++	switch (fw_mtu) {
++	case 0x1:
++		return IB_MTU_256;
++	case 0x2:
++		return IB_MTU_512;
++	case 0x3:
++		return IB_MTU_1024;
++	case 0x4:
++		return IB_MTU_2048;
++	case 0x5:
++		return IB_MTU_4096;
++	default:
++		ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
++			 fw_mtu);
++		return 0;
++	}
++}
++
++static int map_number_of_vls(struct ehca_shca *shca, u32 vl_cap)
++{
++	switch (vl_cap) {
++	case 0x1:
++		return 1;
++	case 0x2:
++		return 2;
++	case 0x3:
++		return 4;
++	case 0x4:
++		return 8;
++	case 0x5:
++		return 15;
++	default:
++		ehca_err(&shca->ib_device, "invalid Vl Capability: %x.",
++			 vl_cap);
++		return 0;
++	}
++}
++
+ int ehca_query_port(struct ib_device *ibdev,
+ 		    u8 port, struct ib_port_attr *props)
+ {
+@@ -152,31 +200,13 @@ int ehca_query_port(struct ib_device *ibdev,
+ 
+ 	memset(props, 0, sizeof(struct ib_port_attr));
+ 
+-	switch (rblock->max_mtu) {
+-	case 0x1:
+-		props->active_mtu = props->max_mtu = IB_MTU_256;
+-		break;
+-	case 0x2:
+-		props->active_mtu = props->max_mtu = IB_MTU_512;
+-		break;
+-	case 0x3:
+-		props->active_mtu = props->max_mtu = IB_MTU_1024;
+-		break;
+-	case 0x4:
+-		props->active_mtu = props->max_mtu = IB_MTU_2048;
+-		break;
+-	case 0x5:
+-		props->active_mtu = props->max_mtu = IB_MTU_4096;
+-		break;
+-	default:
+-		ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
+-			 rblock->max_mtu);
+-		break;
+-	}
+-
++	props->active_mtu = props->max_mtu = map_mtu(shca, rblock->max_mtu);
+ 	props->port_cap_flags  = rblock->capability_mask;
+ 	props->gid_tbl_len     = rblock->gid_tbl_len;
+-	props->max_msg_sz      = rblock->max_msg_sz;
++	if (rblock->max_msg_sz)
++		props->max_msg_sz      = rblock->max_msg_sz;
++	else
++		props->max_msg_sz      = 0x1 << 31;
+ 	props->bad_pkey_cntr   = rblock->bad_pkey_cntr;
+ 	props->qkey_viol_cntr  = rblock->qkey_viol_cntr;
+ 	props->pkey_tbl_len    = rblock->pkey_tbl_len;
+@@ -186,6 +216,7 @@ int ehca_query_port(struct ib_device *ibdev,
+ 	props->sm_sl           = rblock->sm_sl;
+ 	props->subnet_timeout  = rblock->subnet_timeout;
+ 	props->init_type_reply = rblock->init_type_reply;
++	props->max_vl_num      = map_number_of_vls(shca, rblock->vl_cap);
+ 
+ 	if (rblock->state && rblock->phys_width) {
+ 		props->phys_state      = rblock->phys_pstate;
+@@ -314,7 +345,7 @@ query_gid1:
+ 	return ret;
+ }
+ 
+-const u32 allowed_port_caps = (
++static const u32 allowed_port_caps = (
+ 	IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP |
+ 	IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP |
+ 	IB_PORT_VENDOR_CLASS_SUP);
+diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
+index a86ebcc..65b3362 100644
+--- a/drivers/infiniband/hw/ehca/ehca_main.c
++++ b/drivers/infiniband/hw/ehca/ehca_main.c
+@@ -57,16 +57,17 @@ MODULE_AUTHOR("Christoph Raisch <raisch at de.ibm.com>");
+ MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
+ MODULE_VERSION(HCAD_VERSION);
+ 
+-int ehca_open_aqp1     = 0;
++static int ehca_open_aqp1     = 0;
++static int ehca_hw_level      = 0;
++static int ehca_poll_all_eqs  = 1;
++static int ehca_mr_largepage  = 1;
++
+ int ehca_debug_level   = 0;
+-int ehca_hw_level      = 0;
+ int ehca_nr_ports      = 2;
+ int ehca_use_hp_mr     = 0;
+ int ehca_port_act_time = 30;
+-int ehca_poll_all_eqs  = 1;
+ int ehca_static_rate   = -1;
+ int ehca_scaling_code  = 0;
+-int ehca_mr_largepage  = 1;
+ int ehca_lock_hcalls   = -1;
+ 
+ module_param_named(open_aqp1,     ehca_open_aqp1,     int, S_IRUGO);
+@@ -396,7 +397,7 @@ init_node_guid1:
+ 	return ret;
+ }
+ 
+-int ehca_init_device(struct ehca_shca *shca)
++static int ehca_init_device(struct ehca_shca *shca)
+ {
+ 	int ret;
+ 
+@@ -579,8 +580,8 @@ static ssize_t ehca_store_debug_level(struct device_driver *ddp,
+ 	return 1;
+ }
+ 
+-DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
+-	    ehca_show_debug_level, ehca_store_debug_level);
++static DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
++		   ehca_show_debug_level, ehca_store_debug_level);
+ 
+ static struct attribute *ehca_drv_attrs[] = {
+ 	&driver_attr_debug_level.attr,
+@@ -941,7 +942,7 @@ void ehca_poll_eqs(unsigned long data)
+ 	spin_unlock(&shca_list_lock);
+ }
+ 
+-int __init ehca_module_init(void)
++static int __init ehca_module_init(void)
+ {
+ 	int ret;
+ 
+@@ -988,7 +989,7 @@ module_init1:
+ 	return ret;
+ };
+ 
+-void __exit ehca_module_exit(void)
++static void __exit ehca_module_exit(void)
+ {
+ 	if (ehca_poll_all_eqs == 1)
+ 		del_timer_sync(&poll_eqs_timer);
+diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+index e239bbf..f26997f 100644
+--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
++++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+@@ -40,8 +40,6 @@
+  * POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+-#include <asm/current.h>
+-
+ #include <rdma/ib_umem.h>
+ 
+ #include "ehca_iverbs.h"
+@@ -419,7 +417,6 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
+ 	struct ehca_shca *shca =
+ 		container_of(mr->device, struct ehca_shca, ib_device);
+ 	struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+-	struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+ 	u64 new_size;
+ 	u64 *new_start;
+ 	u32 new_acl;
+@@ -429,15 +426,6 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
+ 	u32 num_kpages = 0;
+ 	u32 num_hwpages = 0;
+ 	struct ehca_mr_pginfo pginfo;
+-	u32 cur_pid = current->tgid;
+-
+-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+-	    (my_pd->ownpid != cur_pid)) {
+-		ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		ret = -EINVAL;
+-		goto rereg_phys_mr_exit0;
+-	}
+ 
+ 	if (!(mr_rereg_mask & IB_MR_REREG_TRANS)) {
+ 		/* TODO not supported, because PHYP rereg hCall needs pages */
+@@ -577,19 +565,9 @@ int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
+ 	struct ehca_shca *shca =
+ 		container_of(mr->device, struct ehca_shca, ib_device);
+ 	struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+-	struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+-	u32 cur_pid = current->tgid;
+ 	unsigned long sl_flags;
+ 	struct ehca_mr_hipzout_parms hipzout;
+ 
+-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+-	    (my_pd->ownpid != cur_pid)) {
+-		ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		ret = -EINVAL;
+-		goto query_mr_exit0;
+-	}
+-
+ 	if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
+ 		ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
+ 			 "e_mr->flags=%x", mr, e_mr, e_mr->flags);
+@@ -634,16 +612,6 @@ int ehca_dereg_mr(struct ib_mr *mr)
+ 	struct ehca_shca *shca =
+ 		container_of(mr->device, struct ehca_shca, ib_device);
+ 	struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+-	struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+-	u32 cur_pid = current->tgid;
+-
+-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+-	    (my_pd->ownpid != cur_pid)) {
+-		ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		ret = -EINVAL;
+-		goto dereg_mr_exit0;
+-	}
+ 
+ 	if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
+ 		ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
+@@ -1952,9 +1920,8 @@ next_kpage:
+ 	return ret;
+ }
+ 
+-int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
+-			  u32 number,
+-			  u64 *kpage)
++static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
++				 u32 number, u64 *kpage)
+ {
+ 	int ret = 0;
+ 	struct ib_phys_buf *pbuf;
+@@ -2012,9 +1979,8 @@ int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
+ 	return ret;
+ }
+ 
+-int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
+-			 u32 number,
+-			 u64 *kpage)
++static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
++				u32 number, u64 *kpage)
+ {
+ 	int ret = 0;
+ 	u64 *fmrlist;
+diff --git a/drivers/infiniband/hw/ehca/ehca_pd.c b/drivers/infiniband/hw/ehca/ehca_pd.c
+index 43bcf08..2fe5548 100644
+--- a/drivers/infiniband/hw/ehca/ehca_pd.c
++++ b/drivers/infiniband/hw/ehca/ehca_pd.c
+@@ -38,8 +38,6 @@
+  * POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+-#include <asm/current.h>
+-
+ #include "ehca_tools.h"
+ #include "ehca_iverbs.h"
+ 
+@@ -58,7 +56,6 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
+ 		return ERR_PTR(-ENOMEM);
+ 	}
+ 
+-	pd->ownpid = current->tgid;
+ 	for (i = 0; i < 2; i++) {
+ 		INIT_LIST_HEAD(&pd->free[i]);
+ 		INIT_LIST_HEAD(&pd->full[i]);
+@@ -85,18 +82,10 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
+ 
+ int ehca_dealloc_pd(struct ib_pd *pd)
+ {
+-	u32 cur_pid = current->tgid;
+ 	struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
+ 	int i, leftovers = 0;
+ 	struct ipz_small_queue_page *page, *tmp;
+ 
+-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+-	    my_pd->ownpid != cur_pid) {
+-		ehca_err(pd->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		return -EINVAL;
+-	}
+-
+ 	for (i = 0; i < 2; i++) {
+ 		list_splice(&my_pd->full[i], &my_pd->free[i]);
+ 		list_for_each_entry_safe(page, tmp, &my_pd->free[i], list) {
+diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
+index 1012f15..3eb14a5 100644
+--- a/drivers/infiniband/hw/ehca/ehca_qp.c
++++ b/drivers/infiniband/hw/ehca/ehca_qp.c
+@@ -43,9 +43,6 @@
+  * POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+-
+-#include <asm/current.h>
+-
+ #include "ehca_classes.h"
+ #include "ehca_tools.h"
+ #include "ehca_qes.h"
+@@ -424,6 +421,9 @@ static struct ehca_qp *internal_create_qp(
+ 	u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
+ 	unsigned long flags;
+ 
++	if (init_attr->create_flags)
++		return ERR_PTR(-EINVAL);
++
+ 	memset(&parms, 0, sizeof(parms));
+ 	qp_type = init_attr->qp_type;
+ 
+@@ -1526,16 +1526,6 @@ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ 	struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
+ 					      ib_device);
+ 	struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
+-	struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+-					     ib_pd);
+-	u32 cur_pid = current->tgid;
+-
+-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+-	    my_pd->ownpid != cur_pid) {
+-		ehca_err(ibqp->pd->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		return -EINVAL;
+-	}
+ 
+ 	/* The if-block below caches qp_attr to be modified for GSI and SMI
+ 	 * qps during the initialization by ib_mad. When the respective port
+@@ -1636,23 +1626,13 @@ int ehca_query_qp(struct ib_qp *qp,
+ 		  int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
+ {
+ 	struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
+-	struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+-					     ib_pd);
+ 	struct ehca_shca *shca = container_of(qp->device, struct ehca_shca,
+ 					      ib_device);
+ 	struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+ 	struct hcp_modify_qp_control_block *qpcb;
+-	u32 cur_pid = current->tgid;
+ 	int cnt, ret = 0;
+ 	u64 h_ret;
+ 
+-	if (my_pd->ib_pd.uobject  && my_pd->ib_pd.uobject->context  &&
+-	    my_pd->ownpid != cur_pid) {
+-		ehca_err(qp->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		return -EINVAL;
+-	}
+-
+ 	if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) {
+ 		ehca_err(qp->device, "Invalid attribute mask "
+ 			 "ehca_qp=%p qp_num=%x qp_attr_mask=%x ",
+@@ -1797,8 +1777,6 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ {
+ 	struct ehca_qp *my_qp =
+ 		container_of(ibsrq, struct ehca_qp, ib_srq);
+-	struct ehca_pd *my_pd =
+-		container_of(ibsrq->pd, struct ehca_pd, ib_pd);
+ 	struct ehca_shca *shca =
+ 		container_of(ibsrq->pd->device, struct ehca_shca, ib_device);
+ 	struct hcp_modify_qp_control_block *mqpcb;
+@@ -1806,14 +1784,6 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ 	u64 h_ret;
+ 	int ret = 0;
+ 
+-	u32 cur_pid = current->tgid;
+-	if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+-	    my_pd->ownpid != cur_pid) {
+-		ehca_err(ibsrq->pd->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		return -EINVAL;
+-	}
+-
+ 	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ 	if (!mqpcb) {
+ 		ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
+@@ -1864,22 +1834,13 @@ modify_srq_exit0:
+ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
+ {
+ 	struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq);
+-	struct ehca_pd *my_pd = container_of(srq->pd, struct ehca_pd, ib_pd);
+ 	struct ehca_shca *shca = container_of(srq->device, struct ehca_shca,
+ 					      ib_device);
+ 	struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+ 	struct hcp_modify_qp_control_block *qpcb;
+-	u32 cur_pid = current->tgid;
+ 	int ret = 0;
+ 	u64 h_ret;
+ 
+-	if (my_pd->ib_pd.uobject  && my_pd->ib_pd.uobject->context  &&
+-	    my_pd->ownpid != cur_pid) {
+-		ehca_err(srq->device, "Invalid caller pid=%x ownpid=%x",
+-			 cur_pid, my_pd->ownpid);
+-		return -EINVAL;
+-	}
+-
+ 	qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ 	if (!qpcb) {
+ 		ehca_err(srq->device, "Out of memory for qpcb "
+@@ -1919,7 +1880,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ 	struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+ 					     ib_pd);
+ 	struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1];
+-	u32 cur_pid = current->tgid;
+ 	u32 qp_num = my_qp->real_qp_num;
+ 	int ret;
+ 	u64 h_ret;
+@@ -1934,11 +1894,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ 				 "user space qp_num=%x", qp_num);
+ 			return -EINVAL;
+ 		}
+-		if (my_pd->ownpid != cur_pid) {
+-			ehca_err(dev, "Invalid caller pid=%x ownpid=%x",
+-				 cur_pid, my_pd->ownpid);
+-			return -EINVAL;
+-		}
+ 	}
+ 
+ 	if (my_qp->send_cq) {
+diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
+index 2ce8cff..a20bbf4 100644
+--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
++++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
+@@ -188,7 +188,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
+ 	if (send_wr->opcode == IB_WR_SEND_WITH_IMM ||
+ 	    send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
+ 		/* this might not work as long as HW does not support it */
+-		wqe_p->immediate_data = be32_to_cpu(send_wr->imm_data);
++		wqe_p->immediate_data = be32_to_cpu(send_wr->ex.imm_data);
+ 		wqe_p->wr_flag |= WQE_WRFLAG_IMM_DATA_PRESENT;
+ 	}
+ 
+diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
+index 4a8346a..ec950bf 100644
+--- a/drivers/infiniband/hw/ehca/ehca_tools.h
++++ b/drivers/infiniband/hw/ehca/ehca_tools.h
+@@ -73,37 +73,37 @@ extern int ehca_debug_level;
+ 		if (unlikely(ehca_debug_level)) \
+ 			dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \
+ 				   "PU%04x EHCA_DBG:%s " format "\n", \
+-				   raw_smp_processor_id(), __FUNCTION__, \
++				   raw_smp_processor_id(), __func__, \
+ 				   ## arg); \
+ 	} while (0)
+ 
+ #define ehca_info(ib_dev, format, arg...) \
+ 	dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \
+-		 raw_smp_processor_id(), __FUNCTION__, ## arg)
++		 raw_smp_processor_id(), __func__, ## arg)
+ 
+ #define ehca_warn(ib_dev, format, arg...) \
+ 	dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \
+-		 raw_smp_processor_id(), __FUNCTION__, ## arg)
++		 raw_smp_processor_id(), __func__, ## arg)
+ 
+ #define ehca_err(ib_dev, format, arg...) \
+ 	dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \
+-		raw_smp_processor_id(), __FUNCTION__, ## arg)
++		raw_smp_processor_id(), __func__, ## arg)
+ 
+ /* use this one only if no ib_dev available */
+ #define ehca_gen_dbg(format, arg...) \
+ 	do { \
+ 		if (unlikely(ehca_debug_level)) \
+ 			printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n", \
+-			       raw_smp_processor_id(), __FUNCTION__, ## arg); \
++			       raw_smp_processor_id(), __func__, ## arg); \
+ 	} while (0)
+ 
+ #define ehca_gen_warn(format, arg...) \
+ 	printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
+-	       raw_smp_processor_id(), __FUNCTION__, ## arg)
++	       raw_smp_processor_id(), __func__, ## arg)
+ 
+ #define ehca_gen_err(format, arg...) \
+ 	printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \
+-	       raw_smp_processor_id(), __FUNCTION__, ## arg)
++	       raw_smp_processor_id(), __func__, ## arg)
+ 
+ /**
+  * ehca_dmp - printk a memory block, whose length is n*8 bytes.
+@@ -118,7 +118,7 @@ extern int ehca_debug_level;
+ 		for (x = 0; x < l; x += 16) { \
+ 			printk(KERN_INFO "EHCA_DMP:%s " format \
+ 			       " adr=%p ofs=%04x %016lx %016lx\n", \
+-			       __FUNCTION__, ##args, deb, x, \
++			       __func__, ##args, deb, x, \
+ 			       *((u64 *)&deb[0]), *((u64 *)&deb[8])); \
+ 			deb += 16; \
+ 		} \
+diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
+index 5234d6c..1b07f2b 100644
+--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
++++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
+@@ -40,8 +40,6 @@
+  * POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+-#include <asm/current.h>
+-
+ #include "ehca_classes.h"
+ #include "ehca_iverbs.h"
+ #include "ehca_mrmw.h"
+@@ -253,11 +251,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ 	u32 idr_handle = fileoffset & 0x1FFFFFF;
+ 	u32 q_type = (fileoffset >> 27) & 0x1;	  /* CQ, QP,...        */
+ 	u32 rsrc_type = (fileoffset >> 25) & 0x3; /* sq,rq,cmnd_window */
+-	u32 cur_pid = current->tgid;
+ 	u32 ret;
+ 	struct ehca_cq *cq;
+ 	struct ehca_qp *qp;
+-	struct ehca_pd *pd;
+ 	struct ib_uobject *uobject;
+ 
+ 	switch (q_type) {
+@@ -270,13 +266,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ 		if (!cq)
+ 			return -EINVAL;
+ 
+-		if (cq->ownpid != cur_pid) {
+-			ehca_err(cq->ib_cq.device,
+-				 "Invalid caller pid=%x ownpid=%x",
+-				 cur_pid, cq->ownpid);
+-			return -ENOMEM;
+-		}
+-
+ 		if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
+ 			return -EINVAL;
+ 
+@@ -298,14 +287,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ 		if (!qp)
+ 			return -EINVAL;
+ 
+-		pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd);
+-		if (pd->ownpid != cur_pid) {
+-			ehca_err(qp->ib_qp.device,
+-				 "Invalid caller pid=%x ownpid=%x",
+-				 cur_pid, pd->ownpid);
+-			return -ENOMEM;
+-		}
+-
+ 		uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
+ 		if (!uobject || uobject->context != context)
+ 			return -EINVAL;
+diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig
+index 044da58..3c7968f 100644
+--- a/drivers/infiniband/hw/ipath/Kconfig
++++ b/drivers/infiniband/hw/ipath/Kconfig
+@@ -1,6 +1,6 @@
+ config INFINIBAND_IPATH
+ 	tristate "QLogic InfiniPath Driver"
+-	depends on (PCI_MSI || HT_IRQ) && 64BIT && NET
++	depends on 64BIT && NET
+ 	---help---
+ 	This is a driver for QLogic InfiniPath host channel adapters,
+ 	including InfiniBand verbs support.  This driver allows these
+diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile
+index fe67388..bf94500 100644
+--- a/drivers/infiniband/hw/ipath/Makefile
++++ b/drivers/infiniband/hw/ipath/Makefile
+@@ -20,14 +20,19 @@ ib_ipath-y := \
+ 	ipath_qp.o \
+ 	ipath_rc.o \
+ 	ipath_ruc.o \
++	ipath_sdma.o \
+ 	ipath_srq.o \
+ 	ipath_stats.o \
+ 	ipath_sysfs.o \
+ 	ipath_uc.o \
+ 	ipath_ud.o \
+ 	ipath_user_pages.o \
++	ipath_user_sdma.o \
+ 	ipath_verbs_mcast.o \
+-	ipath_verbs.o
++	ipath_verbs.o \
++	ipath_iba7220.o \
++	ipath_sd7220.o \
++	ipath_sd7220_img.o
+ 
+ ib_ipath-$(CONFIG_HT_IRQ) += ipath_iba6110.o
+ ib_ipath-$(CONFIG_PCI_MSI) += ipath_iba6120.o
+diff --git a/drivers/infiniband/hw/ipath/ipath_7220.h b/drivers/infiniband/hw/ipath/ipath_7220.h
+new file mode 100644
+index 0000000..74fa5cc
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_7220.h
+@@ -0,0 +1,57 @@
++#ifndef _IPATH_7220_H
++#define _IPATH_7220_H
++/*
++ * Copyright (c) 2007 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/*
++ * This header file provides the declarations and common definitions
++ * for (mostly) manipulation of the SerDes blocks within the IBA7220.
++ * the functions declared should only be called from within other
++ * 7220-related files such as ipath_iba7220.c or ipath_sd7220.c.
++ */
++int ipath_sd7220_presets(struct ipath_devdata *dd);
++int ipath_sd7220_init(struct ipath_devdata *dd, int was_reset);
++int ipath_sd7220_prog_ld(struct ipath_devdata *dd, int sdnum, u8 *img,
++	int len, int offset);
++int ipath_sd7220_prog_vfy(struct ipath_devdata *dd, int sdnum, const u8 *img,
++	int len, int offset);
++/*
++ * Below used for sdnum parameter, selecting one of the two sections
++ * used for PCIe, or the single SerDes used for IB, which is the
++ * only one currently used
++ */
++#define IB_7220_SERDES 2
++
++int ipath_sd7220_ib_load(struct ipath_devdata *dd);
++int ipath_sd7220_ib_vfy(struct ipath_devdata *dd);
++
++#endif /* _IPATH_7220_H */
+diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
+index 591901a..28cfe97 100644
+--- a/drivers/infiniband/hw/ipath/ipath_common.h
++++ b/drivers/infiniband/hw/ipath/ipath_common.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -80,6 +80,8 @@
+ #define IPATH_IB_LINKDOWN_DISABLE	5
+ #define IPATH_IB_LINK_LOOPBACK	6 /* enable local loopback */
+ #define IPATH_IB_LINK_EXTERNAL	7 /* normal, disable local loopback */
++#define IPATH_IB_LINK_NO_HRTBT	8 /* disable Heartbeat, e.g. for loopback */
++#define IPATH_IB_LINK_HRTBT	9 /* enable heartbeat, normal, non-loopback */
+ 
+ /*
+  * These 3 values (SDR and DDR may be ORed for auto-speed
+@@ -198,7 +200,8 @@ typedef enum _ipath_ureg {
+ #define IPATH_RUNTIME_FORCE_WC_ORDER	0x4
+ #define IPATH_RUNTIME_RCVHDR_COPY	0x8
+ #define IPATH_RUNTIME_MASTER	0x10
+-/* 0x20 and 0x40 are no longer used, but are reserved for ABI compatibility */
++#define IPATH_RUNTIME_NODMA_RTAIL 0x80
++#define IPATH_RUNTIME_SDMA	      0x200
+ #define IPATH_RUNTIME_FORCE_PIOAVAIL 0x400
+ #define IPATH_RUNTIME_PIO_REGSWAPPED 0x800
+ 
+@@ -444,8 +447,9 @@ struct ipath_user_info {
+ #define IPATH_CMD_PIOAVAILUPD	27	/* force an update of PIOAvail reg */
+ #define IPATH_CMD_POLL_TYPE	28	/* set the kind of polling we want */
+ #define IPATH_CMD_ARMLAUNCH_CTRL	29 /* armlaunch detection control */
+-
+-#define IPATH_CMD_MAX		29
++/* 30 is unused */
++#define IPATH_CMD_SDMA_INFLIGHT 31	/* sdma inflight counter request */
++#define IPATH_CMD_SDMA_COMPLETE 32	/* sdma completion counter request */
+ 
+ /*
+  * Poll types
+@@ -483,6 +487,17 @@ struct ipath_cmd {
+ 	union {
+ 		struct ipath_tid_info tid_info;
+ 		struct ipath_user_info user_info;
++
++		/*
++		 * address in userspace where we should put the sdma
++		 * inflight counter
++		 */
++		__u64 sdma_inflight;
++		/*
++		 * address in userspace where we should put the sdma
++		 * completion counter
++		 */
++		__u64 sdma_complete;
+ 		/* address in userspace of struct ipath_port_info to
+ 		   write result to */
+ 		__u64 port_info;
+@@ -537,7 +552,7 @@ struct ipath_diag_pkt {
+ 
+ /* The second diag_pkt struct is the expanded version that allows
+  * more control over the packet, specifically, by allowing a custom
+- * pbc (+ extra) qword, so that special modes and deliberate
++ * pbc (+ static rate) qword, so that special modes and deliberate
+  * changes to CRCs can be used. The elements were also re-ordered
+  * for better alignment and to avoid padding issues.
+  */
+@@ -662,8 +677,12 @@ struct infinipath_counters {
+ #define INFINIPATH_RHF_LENGTH_SHIFT 0
+ #define INFINIPATH_RHF_RCVTYPE_MASK 0x7
+ #define INFINIPATH_RHF_RCVTYPE_SHIFT 11
+-#define INFINIPATH_RHF_EGRINDEX_MASK 0x7FF
++#define INFINIPATH_RHF_EGRINDEX_MASK 0xFFF
+ #define INFINIPATH_RHF_EGRINDEX_SHIFT 16
++#define INFINIPATH_RHF_SEQ_MASK 0xF
++#define INFINIPATH_RHF_SEQ_SHIFT 0
++#define INFINIPATH_RHF_HDRQ_OFFSET_MASK 0x7FF
++#define INFINIPATH_RHF_HDRQ_OFFSET_SHIFT 4
+ #define INFINIPATH_RHF_H_ICRCERR   0x80000000
+ #define INFINIPATH_RHF_H_VCRCERR   0x40000000
+ #define INFINIPATH_RHF_H_PARITYERR 0x20000000
+@@ -673,6 +692,8 @@ struct infinipath_counters {
+ #define INFINIPATH_RHF_H_TIDERR    0x02000000
+ #define INFINIPATH_RHF_H_MKERR     0x01000000
+ #define INFINIPATH_RHF_H_IBERR     0x00800000
++#define INFINIPATH_RHF_H_ERR_MASK  0xFF800000
++#define INFINIPATH_RHF_L_USE_EGR   0x80000000
+ #define INFINIPATH_RHF_L_SWA       0x00008000
+ #define INFINIPATH_RHF_L_SWB       0x00004000
+ 
+@@ -696,6 +717,7 @@ struct infinipath_counters {
+ /* SendPIO per-buffer control */
+ #define INFINIPATH_SP_TEST    0x40
+ #define INFINIPATH_SP_TESTEBP 0x20
++#define INFINIPATH_SP_TRIGGER_SHIFT  15
+ 
+ /* SendPIOAvail bits */
+ #define INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT 1
+@@ -762,6 +784,7 @@ struct ether_header {
+ #define IPATH_MSN_MASK 0xFFFFFF
+ #define IPATH_QPN_MASK 0xFFFFFF
+ #define IPATH_MULTICAST_LID_BASE 0xC000
++#define IPATH_EAGER_TID_ID INFINIPATH_I_TID_MASK
+ #define IPATH_MULTICAST_QPN 0xFFFFFF
+ 
+ /* Receive Header Queue: receive type (from infinipath) */
+@@ -781,7 +804,7 @@ struct ether_header {
+  */
+ static inline __u32 ipath_hdrget_err_flags(const __le32 * rbuf)
+ {
+-	return __le32_to_cpu(rbuf[1]);
++	return __le32_to_cpu(rbuf[1]) & INFINIPATH_RHF_H_ERR_MASK;
+ }
+ 
+ static inline __u32 ipath_hdrget_rcv_type(const __le32 * rbuf)
+@@ -802,6 +825,23 @@ static inline __u32 ipath_hdrget_index(const __le32 * rbuf)
+ 	    & INFINIPATH_RHF_EGRINDEX_MASK;
+ }
+ 
++static inline __u32 ipath_hdrget_seq(const __le32 *rbuf)
++{
++	return (__le32_to_cpu(rbuf[1]) >> INFINIPATH_RHF_SEQ_SHIFT)
++		& INFINIPATH_RHF_SEQ_MASK;
++}
++
++static inline __u32 ipath_hdrget_offset(const __le32 *rbuf)
++{
++	return (__le32_to_cpu(rbuf[1]) >> INFINIPATH_RHF_HDRQ_OFFSET_SHIFT)
++		& INFINIPATH_RHF_HDRQ_OFFSET_MASK;
++}
++
++static inline __u32 ipath_hdrget_use_egr_buf(const __le32 *rbuf)
++{
++	return __le32_to_cpu(rbuf[0]) & INFINIPATH_RHF_L_USE_EGR;
++}
++
+ static inline __u32 ipath_hdrget_ipath_ver(__le32 hdrword)
+ {
+ 	return (__le32_to_cpu(hdrword) >> INFINIPATH_I_VERS_SHIFT)
+diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
+index d6f6953..65926cd 100644
+--- a/drivers/infiniband/hw/ipath/ipath_debug.h
++++ b/drivers/infiniband/hw/ipath/ipath_debug.h
+@@ -66,6 +66,7 @@
+ #define __IPATH_IPATHERR    0x40000	/* Ethernet (IPATH) errors */
+ #define __IPATH_IPATHPD     0x80000	/* Ethernet (IPATH) packet dump */
+ #define __IPATH_IPATHTABLE  0x100000	/* Ethernet (IPATH) table dump */
++#define __IPATH_LINKVERBDBG 0x200000	/* very verbose linkchange debug */
+ 
+ #else				/* _IPATH_DEBUGGING */
+ 
+@@ -89,6 +90,7 @@
+ #define __IPATH_IPATHERR  0x0	/* Ethernet (IPATH) errors on   */
+ #define __IPATH_IPATHPD   0x0	/* Ethernet (IPATH) packet dump on   */
+ #define __IPATH_IPATHTABLE 0x0	/* Ethernet (IPATH) packet dump on   */
++#define __IPATH_LINKVERBDBG 0x0	/* very verbose linkchange debug */
+ 
+ #endif				/* _IPATH_DEBUGGING */
+ 
+diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
+index 4137c77..d4ce8b6 100644
+--- a/drivers/infiniband/hw/ipath/ipath_diag.c
++++ b/drivers/infiniband/hw/ipath/ipath_diag.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -79,7 +79,7 @@ static const struct file_operations diagpkt_file_ops = {
+ 
+ static atomic_t diagpkt_count = ATOMIC_INIT(0);
+ static struct cdev *diagpkt_cdev;
+-static struct class_device *diagpkt_class_dev;
++static struct device *diagpkt_dev;
+ 
+ int ipath_diag_add(struct ipath_devdata *dd)
+ {
+@@ -89,7 +89,7 @@ int ipath_diag_add(struct ipath_devdata *dd)
+ 	if (atomic_inc_return(&diagpkt_count) == 1) {
+ 		ret = ipath_cdev_init(IPATH_DIAGPKT_MINOR,
+ 				      "ipath_diagpkt", &diagpkt_file_ops,
+-				      &diagpkt_cdev, &diagpkt_class_dev);
++				      &diagpkt_cdev, &diagpkt_dev);
+ 
+ 		if (ret) {
+ 			ipath_dev_err(dd, "Couldn't create ipath_diagpkt "
+@@ -102,7 +102,7 @@ int ipath_diag_add(struct ipath_devdata *dd)
+ 
+ 	ret = ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
+ 			      &diag_file_ops, &dd->diag_cdev,
+-			      &dd->diag_class_dev);
++			      &dd->diag_dev);
+ 	if (ret)
+ 		ipath_dev_err(dd, "Couldn't create %s device: %d",
+ 			      name, ret);
+@@ -114,9 +114,9 @@ done:
+ void ipath_diag_remove(struct ipath_devdata *dd)
+ {
+ 	if (atomic_dec_and_test(&diagpkt_count))
+-		ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_class_dev);
++		ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_dev);
+ 
+-	ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev);
++	ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_dev);
+ }
+ 
+ /**
+@@ -330,13 +330,19 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
+ 	struct ipath_devdata *dd;
+ 	ssize_t ret = 0;
+ 	u64 val;
++	u32 l_state, lt_state; /* LinkState, LinkTrainingState */
+ 
+-	if (count != sizeof(dp)) {
++	if (count < sizeof(odp)) {
+ 		ret = -EINVAL;
+ 		goto bail;
+ 	}
+ 
+-	if (copy_from_user(&dp, data, sizeof(dp))) {
++	if (count == sizeof(dp)) {
++		if (copy_from_user(&dp, data, sizeof(dp))) {
++			ret = -EFAULT;
++			goto bail;
++		}
++	} else if (copy_from_user(&odp, data, sizeof(odp))) {
+ 		ret = -EFAULT;
+ 		goto bail;
+ 	}
+@@ -396,10 +402,17 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
+ 		ret = -ENODEV;
+ 		goto bail;
+ 	}
+-	/* Check link state, but not if we have custom PBC */
+-	val = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+-	if (!dp.pbc_wd && val != IPATH_IBSTATE_INIT &&
+-		val != IPATH_IBSTATE_ARM && val != IPATH_IBSTATE_ACTIVE) {
++	/*
++	 * Want to skip check for l_state if using custom PBC,
++	 * because we might be trying to force an SM packet out.
++	 * first-cut, skip _all_ state checking in that case.
++	 */
++	val = ipath_ib_state(dd, dd->ipath_lastibcstat);
++	lt_state = ipath_ib_linktrstate(dd, dd->ipath_lastibcstat);
++	l_state = ipath_ib_linkstate(dd, dd->ipath_lastibcstat);
++	if (!dp.pbc_wd && (lt_state != INFINIPATH_IBCS_LT_STATE_LINKUP ||
++	    (val != dd->ib_init && val != dd->ib_arm &&
++	    val != dd->ib_active))) {
+ 		ipath_cdbg(VERBOSE, "unit %u not ready (state %llx)\n",
+ 			   dd->ipath_unit, (unsigned long long) val);
+ 		ret = -EINVAL;
+@@ -431,15 +444,17 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
+ 		goto bail;
+ 	}
+ 
+-	piobuf = ipath_getpiobuf(dd, &pbufn);
++	plen >>= 2;		/* in dwords */
++
++	piobuf = ipath_getpiobuf(dd, plen, &pbufn);
+ 	if (!piobuf) {
+ 		ipath_cdbg(VERBOSE, "No PIO buffers avail unit for %u\n",
+ 			   dd->ipath_unit);
+ 		ret = -EBUSY;
+ 		goto bail;
+ 	}
+-
+-	plen >>= 2;		/* in dwords */
++	/* disarm it just to be extra sure */
++	ipath_disarm_piobufs(dd, pbufn, 1);
+ 
+ 	if (ipath_debug & __IPATH_PKTDBG)
+ 		ipath_cdbg(VERBOSE, "unit %u 0x%x+1w pio%d\n",
+diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
+index ca4d0ac..acf30c0 100644
+--- a/drivers/infiniband/hw/ipath/ipath_driver.c
++++ b/drivers/infiniband/hw/ipath/ipath_driver.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -41,7 +41,6 @@
+ 
+ #include "ipath_kernel.h"
+ #include "ipath_verbs.h"
+-#include "ipath_common.h"
+ 
+ static void ipath_update_pio_bufs(struct ipath_devdata *);
+ 
+@@ -73,10 +72,27 @@ module_param_named(debug, ipath_debug, uint, S_IWUSR | S_IRUGO);
+ MODULE_PARM_DESC(debug, "mask for debug prints");
+ EXPORT_SYMBOL_GPL(ipath_debug);
+ 
++unsigned ipath_mtu4096 = 1; /* max 4KB IB mtu by default, if supported */
++module_param_named(mtu4096, ipath_mtu4096, uint, S_IRUGO);
++MODULE_PARM_DESC(mtu4096, "enable MTU of 4096 bytes, if supported");
++
++static unsigned ipath_hol_timeout_ms = 13000;
++module_param_named(hol_timeout_ms, ipath_hol_timeout_ms, uint, S_IRUGO);
++MODULE_PARM_DESC(hol_timeout_ms,
++	"duration of user app suspension after link failure");
++
++unsigned ipath_linkrecovery = 1;
++module_param_named(linkrecovery, ipath_linkrecovery, uint, S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(linkrecovery, "enable workaround for link recovery issue");
++
+ MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("QLogic <support at pathscale.com>");
++MODULE_AUTHOR("QLogic <support at qlogic.com>");
+ MODULE_DESCRIPTION("QLogic InfiniPath driver");
+ 
++/*
++ * Table to translate the LINKTRAININGSTATE portion of
++ * IBCStatus to a human-readable form.
++ */
+ const char *ipath_ibcstatus_str[] = {
+ 	"Disabled",
+ 	"LinkUp",
+@@ -91,9 +107,20 @@ const char *ipath_ibcstatus_str[] = {
+ 	"CfgWaitRmt",
+ 	"CfgIdle",
+ 	"RecovRetrain",
+-	"LState0xD",		/* unused */
++	"CfgTxRevLane",		/* unused before IBA7220 */
+ 	"RecovWaitRmt",
+ 	"RecovIdle",
++	/* below were added for IBA7220 */
++	"CfgEnhanced",
++	"CfgTest",
++	"CfgWaitRmtTest",
++	"CfgWaitCfgEnhanced",
++	"SendTS_T",
++	"SendTstIdles",
++	"RcvTS_T",
++	"SendTst_TS1s",
++	"LTState18", "LTState19", "LTState1A", "LTState1B",
++	"LTState1C", "LTState1D", "LTState1E", "LTState1F"
+ };
+ 
+ static void __devexit ipath_remove_one(struct pci_dev *);
+@@ -102,8 +129,10 @@ static int __devinit ipath_init_one(struct pci_dev *,
+ 
+ /* Only needed for registration, nothing else needs this info */
+ #define PCI_VENDOR_ID_PATHSCALE 0x1fc1
++#define PCI_VENDOR_ID_QLOGIC 0x1077
+ #define PCI_DEVICE_ID_INFINIPATH_HT 0xd
+ #define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
++#define PCI_DEVICE_ID_INFINIPATH_7220 0x7220
+ 
+ /* Number of seconds before our card status check...  */
+ #define STATUS_TIMEOUT 60
+@@ -111,6 +140,7 @@ static int __devinit ipath_init_one(struct pci_dev *,
+ static const struct pci_device_id ipath_pci_tbl[] = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_INFINIPATH_7220) },
+ 	{ 0, }
+ };
+ 
+@@ -126,19 +156,6 @@ static struct pci_driver ipath_driver = {
+ 	},
+ };
+ 
+-static void ipath_check_status(struct work_struct *work)
+-{
+-	struct ipath_devdata *dd = container_of(work, struct ipath_devdata,
+-						status_work.work);
+-
+-	/*
+-	 * If we don't have any interrupts, let the user know and
+-	 * don't bother checking again.
+-	 */
+-	if (dd->ipath_int_counter == 0)
+-		dev_err(&dd->pcidev->dev, "No interrupts detected.\n");
+-}
+-
+ static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
+ 			     u32 *bar0, u32 *bar1)
+ {
+@@ -206,8 +223,6 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
+ 	dd->pcidev = pdev;
+ 	pci_set_drvdata(pdev, dd);
+ 
+-	INIT_DELAYED_WORK(&dd->status_work, ipath_check_status);
+-
+ 	list_add(&dd->ipath_list, &ipath_dev_list);
+ 
+ bail_unlock:
+@@ -234,12 +249,12 @@ struct ipath_devdata *ipath_lookup(int unit)
+ 	return dd;
+ }
+ 
+-int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp)
++int ipath_count_units(int *npresentp, int *nupp, int *maxportsp)
+ {
+ 	int nunits, npresent, nup;
+ 	struct ipath_devdata *dd;
+ 	unsigned long flags;
+-	u32 maxports;
++	int maxports;
+ 
+ 	nunits = npresent = nup = maxports = 0;
+ 
+@@ -304,7 +319,7 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
+ 	u32 *addr;
+ 	u64 msecs, emsecs;
+ 
+-	piobuf = ipath_getpiobuf(dd, &pbnum);
++	piobuf = ipath_getpiobuf(dd, 0, &pbnum);
+ 	if (!piobuf) {
+ 		dev_info(&dd->pcidev->dev,
+ 			"No PIObufs for checking perf, skipping\n");
+@@ -336,7 +351,14 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
+ 
+ 	ipath_disable_armlaunch(dd);
+ 
+-	writeq(0, piobuf); /* length 0, no dwords actually sent */
++	/*
++	 * length 0, no dwords actually sent, and mark as VL15
++	 * on chips where that may matter (due to IB flowcontrol)
++	 */
++	if ((dd->ipath_flags & IPATH_HAS_PBC_CNT))
++		writeq(1UL << 63, piobuf);
++	else
++		writeq(0, piobuf);
+ 	ipath_flush_wc();
+ 
+ 	/*
+@@ -377,6 +399,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ 	struct ipath_devdata *dd;
+ 	unsigned long long addr;
+ 	u32 bar0 = 0, bar1 = 0;
++	u8 rev;
+ 
+ 	dd = ipath_alloc_devdata(pdev);
+ 	if (IS_ERR(dd)) {
+@@ -408,7 +431,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ 	}
+ 	addr = pci_resource_start(pdev, 0);
+ 	len = pci_resource_len(pdev, 0);
+-	ipath_cdbg(VERBOSE, "regbase (0) %llx len %d pdev->irq %d, vend %x/%x "
++	ipath_cdbg(VERBOSE, "regbase (0) %llx len %d irq %d, vend %x/%x "
+ 		   "driver_data %lx\n", addr, len, pdev->irq, ent->vendor,
+ 		   ent->device, ent->driver_data);
+ 
+@@ -512,6 +535,13 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ 			      "CONFIG_PCI_MSI is not enabled\n", ent->device);
+ 		return -ENODEV;
+ #endif
++	case PCI_DEVICE_ID_INFINIPATH_7220:
++#ifndef CONFIG_PCI_MSI
++		ipath_dbg("CONFIG_PCI_MSI is not enabled, "
++			  "using INTx for unit %u\n", dd->ipath_unit);
++#endif
++		ipath_init_iba7220_funcs(dd);
++		break;
+ 	default:
+ 		ipath_dev_err(dd, "Found unknown QLogic deviceid 0x%x, "
+ 			      "failing\n", ent->device);
+@@ -533,7 +563,13 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ 		goto bail_regions;
+ 	}
+ 
+-	dd->ipath_pcirev = pdev->revision;
++	ret = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
++	if (ret) {
++		ipath_dev_err(dd, "Failed to read PCI revision ID unit "
++			      "%u: err %d\n", dd->ipath_unit, -ret);
++		goto bail_regions;	/* shouldn't ever happen */
++	}
++	dd->ipath_pcirev = rev;
+ 
+ #if defined(__powerpc__)
+ 	/* There isn't a generic way to specify writethrough mappings */
+@@ -556,14 +592,6 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ 	ipath_cdbg(VERBOSE, "mapped io addr %llx to kregbase %p\n",
+ 		   addr, dd->ipath_kregbase);
+ 
+-	/*
+-	 * clear ipath_flags here instead of in ipath_init_chip as it is set
+-	 * by ipath_setup_htconfig.
+-	 */
+-	dd->ipath_flags = 0;
+-	dd->ipath_lli_counter = 0;
+-	dd->ipath_lli_errors = 0;
+-
+ 	if (dd->ipath_f_bus(dd, pdev))
+ 		ipath_dev_err(dd, "Failed to setup config space; "
+ 			      "continuing anyway\n");
+@@ -608,13 +636,11 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ 	ipath_diag_add(dd);
+ 	ipath_register_ib_device(dd);
+ 
+-	/* Check that card status in STATUS_TIMEOUT seconds. */
+-	schedule_delayed_work(&dd->status_work, HZ * STATUS_TIMEOUT);
+-
+ 	goto bail;
+ 
+ bail_irqsetup:
+-	if (pdev->irq) free_irq(pdev->irq, dd);
++	if (pdev->irq)
++		free_irq(pdev->irq, dd);
+ 
+ bail_iounmap:
+ 	iounmap((volatile void __iomem *) dd->ipath_kregbase);
+@@ -654,6 +680,10 @@ static void __devexit cleanup_device(struct ipath_devdata *dd)
+ 		ipath_disable_wc(dd);
+ 	}
+ 
++	if (dd->ipath_spectriggerhit)
++		dev_info(&dd->pcidev->dev, "%lu special trigger hits\n",
++			 dd->ipath_spectriggerhit);
++
+ 	if (dd->ipath_pioavailregs_dma) {
+ 		dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
+ 				  (void *) dd->ipath_pioavailregs_dma,
+@@ -706,6 +736,8 @@ static void __devexit cleanup_device(struct ipath_devdata *dd)
+ 		tmpp = dd->ipath_pageshadow;
+ 		dd->ipath_pageshadow = NULL;
+ 		vfree(tmpp);
++
++		dd->ipath_egrtidbase = NULL;
+ 	}
+ 
+ 	/*
+@@ -738,7 +770,6 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev)
+ 	 */
+ 	ipath_shutdown_device(dd);
+ 
+-	cancel_delayed_work(&dd->status_work);
+ 	flush_scheduled_work();
+ 
+ 	if (dd->verbs_dev)
+@@ -823,20 +854,8 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
+ 		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ 		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ 	}
+-
+-	/*
+-	 * Disable PIOAVAILUPD, then re-enable, reading scratch in
+-	 * between.  This seems to avoid a chip timing race that causes
+-	 * pioavail updates to memory to stop.  We xor as we don't
+-	 * know the state of the bit when we're called.
+-	 */
+-	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-		dd->ipath_sendctrl ^ INFINIPATH_S_PIOBUFAVAILUPD);
+-	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-			 dd->ipath_sendctrl);
+-	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++	/* on some older chips, update may not happen after cancel */
++	ipath_force_pio_avail_update(dd);
+ }
+ 
+ /**
+@@ -873,18 +892,52 @@ int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs)
+ 			   (unsigned long long) ipath_read_kreg64(
+ 				   dd, dd->ipath_kregs->kr_ibcctrl),
+ 			   (unsigned long long) val,
+-			   ipath_ibcstatus_str[val & 0xf]);
++			   ipath_ibcstatus_str[val & dd->ibcs_lts_mask]);
+ 	}
+ 	return (dd->ipath_flags & state) ? 0 : -ETIMEDOUT;
+ }
+ 
++static void decode_sdma_errs(struct ipath_devdata *dd, ipath_err_t err,
++	char *buf, size_t blen)
++{
++	static const struct {
++		ipath_err_t err;
++		const char *msg;
++	} errs[] = {
++		{ INFINIPATH_E_SDMAGENMISMATCH, "SDmaGenMismatch" },
++		{ INFINIPATH_E_SDMAOUTOFBOUND, "SDmaOutOfBound" },
++		{ INFINIPATH_E_SDMATAILOUTOFBOUND, "SDmaTailOutOfBound" },
++		{ INFINIPATH_E_SDMABASE, "SDmaBase" },
++		{ INFINIPATH_E_SDMA1STDESC, "SDma1stDesc" },
++		{ INFINIPATH_E_SDMARPYTAG, "SDmaRpyTag" },
++		{ INFINIPATH_E_SDMADWEN, "SDmaDwEn" },
++		{ INFINIPATH_E_SDMAMISSINGDW, "SDmaMissingDw" },
++		{ INFINIPATH_E_SDMAUNEXPDATA, "SDmaUnexpData" },
++		{ INFINIPATH_E_SDMADESCADDRMISALIGN, "SDmaDescAddrMisalign" },
++		{ INFINIPATH_E_SENDBUFMISUSE, "SendBufMisuse" },
++		{ INFINIPATH_E_SDMADISABLED, "SDmaDisabled" },
++	};
++	int i;
++	int expected;
++	size_t bidx = 0;
++
++	for (i = 0; i < ARRAY_SIZE(errs); i++) {
++		expected = (errs[i].err != INFINIPATH_E_SDMADISABLED) ? 0 :
++			test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status);
++		if ((err & errs[i].err) && !expected)
++			bidx += snprintf(buf + bidx, blen - bidx,
++					 "%s ", errs[i].msg);
++	}
++}
++
+ /*
+  * Decode the error status into strings, deciding whether to always
+  * print * it or not depending on "normal packet errors" vs everything
+  * else.   Return 1 if "real" errors, otherwise 0 if only packet
+  * errors, so caller can decide what to print with the string.
+  */
+-int ipath_decode_err(char *buf, size_t blen, ipath_err_t err)
++int ipath_decode_err(struct ipath_devdata *dd, char *buf, size_t blen,
++	ipath_err_t err)
+ {
+ 	int iserr = 1;
+ 	*buf = '\0';
+@@ -922,6 +975,8 @@ int ipath_decode_err(char *buf, size_t blen, ipath_err_t err)
+ 		strlcat(buf, "rbadversion ", blen);
+ 	if (err & INFINIPATH_E_RHDR)
+ 		strlcat(buf, "rhdr ", blen);
++	if (err & INFINIPATH_E_SENDSPECIALTRIGGER)
++		strlcat(buf, "sendspecialtrigger ", blen);
+ 	if (err & INFINIPATH_E_RLONGPKTLEN)
+ 		strlcat(buf, "rlongpktlen ", blen);
+ 	if (err & INFINIPATH_E_RMAXPKTLEN)
+@@ -964,6 +1019,10 @@ int ipath_decode_err(char *buf, size_t blen, ipath_err_t err)
+ 		strlcat(buf, "hardware ", blen);
+ 	if (err & INFINIPATH_E_RESET)
+ 		strlcat(buf, "reset ", blen);
++	if (err & INFINIPATH_E_SDMAERRS)
++		decode_sdma_errs(dd, err, buf, blen);
++	if (err & INFINIPATH_E_INVALIDEEPCMD)
++		strlcat(buf, "invalideepromcmd ", blen);
+ done:
+ 	return iserr;
+ }
+@@ -1076,18 +1135,17 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
+ 			     u32 eflags,
+ 			     u32 l,
+ 			     u32 etail,
+-			     u64 *rc)
++			     __le32 *rhf_addr,
++			     struct ipath_message_header *hdr)
+ {
+ 	char emsg[128];
+-	struct ipath_message_header *hdr;
+ 
+ 	get_rhf_errstring(eflags, emsg, sizeof emsg);
+-	hdr = (struct ipath_message_header *)&rc[1];
+ 	ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u "
+ 		   "tlen=%x opcode=%x egridx=%x: %s\n",
+ 		   eflags, l,
+-		   ipath_hdrget_rcv_type((__le32 *) rc),
+-		   ipath_hdrget_length_in_bytes((__le32 *) rc),
++		   ipath_hdrget_rcv_type(rhf_addr),
++		   ipath_hdrget_length_in_bytes(rhf_addr),
+ 		   be32_to_cpu(hdr->bth[0]) >> 24,
+ 		   etail, emsg);
+ 
+@@ -1112,55 +1170,52 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
+  */
+ void ipath_kreceive(struct ipath_portdata *pd)
+ {
+-	u64 *rc;
+ 	struct ipath_devdata *dd = pd->port_dd;
++	__le32 *rhf_addr;
+ 	void *ebuf;
+ 	const u32 rsize = dd->ipath_rcvhdrentsize;	/* words */
+ 	const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize;	/* words */
+ 	u32 etail = -1, l, hdrqtail;
+ 	struct ipath_message_header *hdr;
+-	u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0;
++	u32 eflags, i, etype, tlen, pkttot = 0, updegr = 0, reloop = 0;
+ 	static u64 totcalls;	/* stats, may eventually remove */
+-
+-	if (!dd->ipath_hdrqtailptr) {
+-		ipath_dev_err(dd,
+-			      "hdrqtailptr not set, can't do receives\n");
+-		goto bail;
+-	}
++	int last;
+ 
+ 	l = pd->port_head;
+-	hdrqtail = ipath_get_rcvhdrtail(pd);
+-	if (l == hdrqtail)
+-		goto bail;
+-
+-reloop:
+-	for (i = 0; l != hdrqtail; i++) {
+-		u32 qp;
+-		u8 *bthbytes;
++	rhf_addr = (__le32 *) pd->port_rcvhdrq + l + dd->ipath_rhf_offset;
++	if (dd->ipath_flags & IPATH_NODMA_RTAIL) {
++		u32 seq = ipath_hdrget_seq(rhf_addr);
+ 
+-		rc = (u64 *) (pd->port_rcvhdrq + (l << 2));
+-		hdr = (struct ipath_message_header *)&rc[1];
+-		/*
+-		 * could make a network order version of IPATH_KD_QP, and
+-		 * do the obvious shift before masking to speed this up.
+-		 */
+-		qp = ntohl(hdr->bth[1]) & 0xffffff;
+-		bthbytes = (u8 *) hdr->bth;
++		if (seq != pd->port_seq_cnt)
++			goto bail;
++		hdrqtail = 0;
++	} else {
++		hdrqtail = ipath_get_rcvhdrtail(pd);
++		if (l == hdrqtail)
++			goto bail;
++		smp_rmb();
++	}
+ 
+-		eflags = ipath_hdrget_err_flags((__le32 *) rc);
+-		etype = ipath_hdrget_rcv_type((__le32 *) rc);
++reloop:
++	for (last = 0, i = 1; !last; i++) {
++		hdr = dd->ipath_f_get_msgheader(dd, rhf_addr);
++		eflags = ipath_hdrget_err_flags(rhf_addr);
++		etype = ipath_hdrget_rcv_type(rhf_addr);
+ 		/* total length */
+-		tlen = ipath_hdrget_length_in_bytes((__le32 *) rc);
++		tlen = ipath_hdrget_length_in_bytes(rhf_addr);
+ 		ebuf = NULL;
+-		if (etype != RCVHQ_RCV_TYPE_EXPECTED) {
++		if ((dd->ipath_flags & IPATH_NODMA_RTAIL) ?
++		    ipath_hdrget_use_egr_buf(rhf_addr) :
++		    (etype != RCVHQ_RCV_TYPE_EXPECTED)) {
+ 			/*
+-			 * it turns out that the chips uses an eager buffer
++			 * It turns out that the chip uses an eager buffer
+ 			 * for all non-expected packets, whether it "needs"
+ 			 * one or not.  So always get the index, but don't
+ 			 * set ebuf (so we try to copy data) unless the
+ 			 * length requires it.
+ 			 */
+-			etail = ipath_hdrget_index((__le32 *) rc);
++			etail = ipath_hdrget_index(rhf_addr);
++			updegr = 1;
+ 			if (tlen > sizeof(*hdr) ||
+ 			    etype == RCVHQ_RCV_TYPE_NON_KD)
+ 				ebuf = ipath_get_egrbuf(dd, etail);
+@@ -1171,75 +1226,91 @@ reloop:
+ 		 * packets; only ipathhdrerr should be set.
+ 		 */
+ 
+-		if (etype != RCVHQ_RCV_TYPE_NON_KD && etype !=
+-		    RCVHQ_RCV_TYPE_ERROR && ipath_hdrget_ipath_ver(
+-			    hdr->iph.ver_port_tid_offset) !=
+-		    IPS_PROTO_VERSION) {
++		if (etype != RCVHQ_RCV_TYPE_NON_KD &&
++		    etype != RCVHQ_RCV_TYPE_ERROR &&
++		    ipath_hdrget_ipath_ver(hdr->iph.ver_port_tid_offset) !=
++		    IPS_PROTO_VERSION)
+ 			ipath_cdbg(PKT, "Bad InfiniPath protocol version "
+ 				   "%x\n", etype);
+-		}
+ 
+ 		if (unlikely(eflags))
+-			ipath_rcv_hdrerr(dd, eflags, l, etail, rc);
++			ipath_rcv_hdrerr(dd, eflags, l, etail, rhf_addr, hdr);
+ 		else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
+-			ipath_ib_rcv(dd->verbs_dev, rc + 1, ebuf, tlen);
++			ipath_ib_rcv(dd->verbs_dev, (u32 *)hdr, ebuf, tlen);
+ 			if (dd->ipath_lli_counter)
+ 				dd->ipath_lli_counter--;
++		} else if (etype == RCVHQ_RCV_TYPE_EAGER) {
++			u8 opcode = be32_to_cpu(hdr->bth[0]) >> 24;
++			u32 qp = be32_to_cpu(hdr->bth[1]) & 0xffffff;
+ 			ipath_cdbg(PKT, "typ %x, opcode %x (eager, "
+ 				   "qp=%x), len %x; ignored\n",
+-				   etype, bthbytes[0], qp, tlen);
++				   etype, opcode, qp, tlen);
+ 		}
+-		else if (etype == RCVHQ_RCV_TYPE_EAGER)
+-			ipath_cdbg(PKT, "typ %x, opcode %x (eager, "
+-				   "qp=%x), len %x; ignored\n",
+-				   etype, bthbytes[0], qp, tlen);
+ 		else if (etype == RCVHQ_RCV_TYPE_EXPECTED)
+ 			ipath_dbg("Bug: Expected TID, opcode %x; ignored\n",
+-				  be32_to_cpu(hdr->bth[0]) & 0xff);
++				  be32_to_cpu(hdr->bth[0]) >> 24);
+ 		else {
+ 			/*
+ 			 * error packet, type of error unknown.
+ 			 * Probably type 3, but we don't know, so don't
+ 			 * even try to print the opcode, etc.
++			 * Usually caused by a "bad packet", that has no
++			 * BTH, when the LRH says it should.
+ 			 */
+-			ipath_dbg("Error Pkt, but no eflags! egrbuf %x, "
+-				  "len %x\nhdrq@%lx;hdrq+%x rhf: %llx; "
+-				  "hdr %llx %llx %llx %llx %llx\n",
+-				  etail, tlen, (unsigned long) rc, l,
+-				  (unsigned long long) rc[0],
+-				  (unsigned long long) rc[1],
+-				  (unsigned long long) rc[2],
+-				  (unsigned long long) rc[3],
+-				  (unsigned long long) rc[4],
+-				  (unsigned long long) rc[5]);
++			ipath_cdbg(ERRPKT, "Error Pkt, but no eflags! egrbuf"
++				  " %x, len %x hdrq+%x rhf: %Lx\n",
++				  etail, tlen, l,
++				  le64_to_cpu(*(__le64 *) rhf_addr));
++			if (ipath_debug & __IPATH_ERRPKTDBG) {
++				u32 j, *d, dw = rsize-2;
++				if (rsize > (tlen>>2))
++					dw = tlen>>2;
++				d = (u32 *)hdr;
++				printk(KERN_DEBUG "EPkt rcvhdr(%x dw):\n",
++					dw);
++				for (j = 0; j < dw; j++)
++					printk(KERN_DEBUG "%8x%s", d[j],
++						(j%8) == 7 ? "\n" : " ");
++				printk(KERN_DEBUG ".\n");
++			}
+ 		}
+ 		l += rsize;
+ 		if (l >= maxcnt)
+ 			l = 0;
+-		if (etype != RCVHQ_RCV_TYPE_EXPECTED)
+-		    updegr = 1;
++		rhf_addr = (__le32 *) pd->port_rcvhdrq +
++			l + dd->ipath_rhf_offset;
++		if (dd->ipath_flags & IPATH_NODMA_RTAIL) {
++			u32 seq = ipath_hdrget_seq(rhf_addr);
++
++			if (++pd->port_seq_cnt > 13)
++				pd->port_seq_cnt = 1;
++			if (seq != pd->port_seq_cnt)
++				last = 1;
++		} else if (l == hdrqtail)
++			last = 1;
+ 		/*
+ 		 * update head regs on last packet, and every 16 packets.
+ 		 * Reduce bus traffic, while still trying to prevent
+ 		 * rcvhdrq overflows, for when the queue is nearly full
+ 		 */
+-		if (l == hdrqtail || (i && !(i&0xf))) {
+-			u64 lval;
+-			if (l == hdrqtail)
+-				/* request IBA6120 interrupt only on last */
+-				lval = dd->ipath_rhdrhead_intr_off | l;
+-			else
+-				lval = l;
+-			(void)ipath_write_ureg(dd, ur_rcvhdrhead, lval, 0);
++		if (last || !(i & 0xf)) {
++			u64 lval = l;
++
++			/* request IBA6120 and 7220 interrupt only on last */
++			if (last)
++				lval |= dd->ipath_rhdrhead_intr_off;
++			ipath_write_ureg(dd, ur_rcvhdrhead, lval,
++				pd->port_port);
+ 			if (updegr) {
+-				(void)ipath_write_ureg(dd, ur_rcvegrindexhead,
+-						       etail, 0);
++				ipath_write_ureg(dd, ur_rcvegrindexhead,
++						 etail, pd->port_port);
+ 				updegr = 0;
+ 			}
+ 		}
+ 	}
+ 
+-	if (!dd->ipath_rhdrhead_intr_off && !reloop) {
++	if (!dd->ipath_rhdrhead_intr_off && !reloop &&
++	    !(dd->ipath_flags & IPATH_NODMA_RTAIL)) {
+ 		/* IBA6110 workaround; we can have a race clearing chip
+ 		 * interrupt with another interrupt about to be delivered,
+ 		 * and can clear it before it is delivered on the GPIO
+@@ -1301,7 +1372,6 @@ static void ipath_update_pio_bufs(struct ipath_devdata *dd)
+ 	 * happens when all buffers are in use, so only cpu overhead, not
+ 	 * latency or bandwidth is affected.
+ 	 */
+-#define _IPATH_ALL_CHECKBITS 0x5555555555555555ULL
+ 	if (!dd->ipath_pioavailregs_dma) {
+ 		ipath_dbg("Update shadow pioavail, but regs_dma NULL!\n");
+ 		return;
+@@ -1346,7 +1416,7 @@ static void ipath_update_pio_bufs(struct ipath_devdata *dd)
+ 			piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i ^ 1]);
+ 		else
+ 			piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i]);
+-		pchg = _IPATH_ALL_CHECKBITS &
++		pchg = dd->ipath_pioavailkernel[i] &
+ 			~(dd->ipath_pioavailshadow[i] ^ piov);
+ 		pchbusy = pchg << INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT;
+ 		if (pchg && (pchbusy & dd->ipath_pioavailshadow[i])) {
+@@ -1397,27 +1467,63 @@ int ipath_setrcvhdrsize(struct ipath_devdata *dd, unsigned rhdrsize)
+ 	return ret;
+ }
+ 
+-/**
+- * ipath_getpiobuf - find an available pio buffer
+- * @dd: the infinipath device
+- * @pbufnum: the buffer number is placed here
++/*
++ * debugging code and stats updates if no pio buffers available.
++ */
++static noinline void no_pio_bufs(struct ipath_devdata *dd)
++{
++	unsigned long *shadow = dd->ipath_pioavailshadow;
++	__le64 *dma = (__le64 *)dd->ipath_pioavailregs_dma;
++
++	dd->ipath_upd_pio_shadow = 1;
++
++	/*
++	 * not atomic, but if we lose a stat count in a while, that's OK
++	 */
++	ipath_stats.sps_nopiobufs++;
++	if (!(++dd->ipath_consec_nopiobuf % 100000)) {
++		ipath_dbg("%u pio sends with no bufavail; dmacopy: "
++			"%llx %llx %llx %llx; shadow:  %lx %lx %lx %lx\n",
++			dd->ipath_consec_nopiobuf,
++			(unsigned long long) le64_to_cpu(dma[0]),
++			(unsigned long long) le64_to_cpu(dma[1]),
++			(unsigned long long) le64_to_cpu(dma[2]),
++			(unsigned long long) le64_to_cpu(dma[3]),
++			shadow[0], shadow[1], shadow[2], shadow[3]);
++		/*
++		 * 4 buffers per byte, 4 registers above, cover rest
++		 * below
++		 */
++		if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) >
++		    (sizeof(shadow[0]) * 4 * 4))
++			ipath_dbg("2nd group: dmacopy: %llx %llx "
++				  "%llx %llx; shadow: %lx %lx %lx %lx\n",
++				  (unsigned long long)le64_to_cpu(dma[4]),
++				  (unsigned long long)le64_to_cpu(dma[5]),
++				  (unsigned long long)le64_to_cpu(dma[6]),
++				  (unsigned long long)le64_to_cpu(dma[7]),
++				  shadow[4], shadow[5], shadow[6],
++				  shadow[7]);
++	}
++}
++
++/*
++ * common code for normal driver pio buffer allocation, and reserved
++ * allocation.
+  *
+  * do appropriate marking as busy, etc.
+  * returns buffer number if one found (>=0), negative number is error.
+- * Used by ipath_layer_send
+  */
+-u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum)
++static u32 __iomem *ipath_getpiobuf_range(struct ipath_devdata *dd,
++	u32 *pbufnum, u32 first, u32 last, u32 firsti)
+ {
+-	int i, j, starti, updated = 0;
+-	unsigned piobcnt, iter;
++	int i, j, updated = 0;
++	unsigned piobcnt;
+ 	unsigned long flags;
+ 	unsigned long *shadow = dd->ipath_pioavailshadow;
+ 	u32 __iomem *buf;
+ 
+-	piobcnt = (unsigned)(dd->ipath_piobcnt2k
+-			     + dd->ipath_piobcnt4k);
+-	starti = dd->ipath_lastport_piobuf;
+-	iter = piobcnt - starti;
++	piobcnt = last - first;
+ 	if (dd->ipath_upd_pio_shadow) {
+ 		/*
+ 		 * Minor optimization.  If we had no buffers on last call,
+@@ -1425,12 +1531,10 @@ u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum)
+ 		 * if no buffers were updated, to be paranoid
+ 		 */
+ 		ipath_update_pio_bufs(dd);
+-		/* we scanned here, don't do it at end of scan */
+-		updated = 1;
+-		i = starti;
++		updated++;
++		i = first;
+ 	} else
+-		i = dd->ipath_lastpioindex;
+-
++		i = firsti;
+ rescan:
+ 	/*
+ 	 * while test_and_set_bit() is atomic, we do that and then the
+@@ -1438,104 +1542,141 @@ rescan:
+ 	 * of the remaining armlaunch errors.
+ 	 */
+ 	spin_lock_irqsave(&ipath_pioavail_lock, flags);
+-	for (j = 0; j < iter; j++, i++) {
+-		if (i >= piobcnt)
+-			i = starti;
+-		/*
+-		 * To avoid bus lock overhead, we first find a candidate
+-		 * buffer, then do the test and set, and continue if that
+-		 * fails.
+-		 */
+-		if (test_bit((2 * i) + 1, shadow) ||
+-		    test_and_set_bit((2 * i) + 1, shadow))
++	for (j = 0; j < piobcnt; j++, i++) {
++		if (i >= last)
++			i = first;
++		if (__test_and_set_bit((2 * i) + 1, shadow))
+ 			continue;
+ 		/* flip generation bit */
+-		change_bit(2 * i, shadow);
++		__change_bit(2 * i, shadow);
+ 		break;
+ 	}
+ 	spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
+ 
+-	if (j == iter) {
+-		volatile __le64 *dma = dd->ipath_pioavailregs_dma;
+-
+-		/*
+-		 * first time through; shadow exhausted, but may be real
+-		 * buffers available, so go see; if any updated, rescan
+-		 * (once)
+-		 */
++	if (j == piobcnt) {
+ 		if (!updated) {
++			/*
++			 * first time through; shadow exhausted, but may be
++			 * buffers available, try an update and then rescan.
++			 */
+ 			ipath_update_pio_bufs(dd);
+-			updated = 1;
+-			i = starti;
++			updated++;
++			i = first;
+ 			goto rescan;
+-		}
+-		dd->ipath_upd_pio_shadow = 1;
+-		/*
+-		 * not atomic, but if we lose one once in a while, that's OK
+-		 */
+-		ipath_stats.sps_nopiobufs++;
+-		if (!(++dd->ipath_consec_nopiobuf % 100000)) {
+-			ipath_dbg(
+-				"%u pio sends with no bufavail; dmacopy: "
+-				"%llx %llx %llx %llx; shadow:  "
+-				"%lx %lx %lx %lx\n",
+-				dd->ipath_consec_nopiobuf,
+-				(unsigned long long) le64_to_cpu(dma[0]),
+-				(unsigned long long) le64_to_cpu(dma[1]),
+-				(unsigned long long) le64_to_cpu(dma[2]),
+-				(unsigned long long) le64_to_cpu(dma[3]),
+-				shadow[0], shadow[1], shadow[2],
+-				shadow[3]);
++		} else if (updated == 1 && piobcnt <=
++			((dd->ipath_sendctrl
++			>> INFINIPATH_S_UPDTHRESH_SHIFT) &
++			INFINIPATH_S_UPDTHRESH_MASK)) {
+ 			/*
+-			 * 4 buffers per byte, 4 registers above, cover rest
+-			 * below
++			 * for chips supporting and using the update
++			 * threshold we need to force an update of the
++			 * in-memory copy if the count is less than the
++			 * thershold, then check one more time.
+ 			 */
+-			if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) >
+-			    (sizeof(shadow[0]) * 4 * 4))
+-				ipath_dbg("2nd group: dmacopy: %llx %llx "
+-					  "%llx %llx; shadow: %lx %lx "
+-					  "%lx %lx\n",
+-					  (unsigned long long)
+-					  le64_to_cpu(dma[4]),
+-					  (unsigned long long)
+-					  le64_to_cpu(dma[5]),
+-					  (unsigned long long)
+-					  le64_to_cpu(dma[6]),
+-					  (unsigned long long)
+-					  le64_to_cpu(dma[7]),
+-					  shadow[4], shadow[5],
+-					  shadow[6], shadow[7]);
++			ipath_force_pio_avail_update(dd);
++			ipath_update_pio_bufs(dd);
++			updated++;
++			i = first;
++			goto rescan;
+ 		}
++
++		no_pio_bufs(dd);
+ 		buf = NULL;
+-		goto bail;
++	} else {
++		if (i < dd->ipath_piobcnt2k)
++			buf = (u32 __iomem *) (dd->ipath_pio2kbase +
++					       i * dd->ipath_palign);
++		else
++			buf = (u32 __iomem *)
++				(dd->ipath_pio4kbase +
++				 (i - dd->ipath_piobcnt2k) * dd->ipath_4kalign);
++		if (pbufnum)
++			*pbufnum = i;
+ 	}
+ 
+-	/*
+-	 * set next starting place.  Since it's just an optimization,
+-	 * it doesn't matter who wins on this, so no locking
+-	 */
+-	dd->ipath_lastpioindex = i + 1;
+-	if (dd->ipath_upd_pio_shadow)
+-		dd->ipath_upd_pio_shadow = 0;
+-	if (dd->ipath_consec_nopiobuf)
+-		dd->ipath_consec_nopiobuf = 0;
+-	if (i < dd->ipath_piobcnt2k)
+-		buf = (u32 __iomem *) (dd->ipath_pio2kbase +
+-				       i * dd->ipath_palign);
+-	else
+-		buf = (u32 __iomem *)
+-			(dd->ipath_pio4kbase +
+-			 (i - dd->ipath_piobcnt2k) * dd->ipath_4kalign);
+-	ipath_cdbg(VERBOSE, "Return piobuf%u %uk @ %p\n",
+-		   i, (i < dd->ipath_piobcnt2k) ? 2 : 4, buf);
+-	if (pbufnum)
+-		*pbufnum = i;
++	return buf;
++}
+ 
+-bail:
++/**
++ * ipath_getpiobuf - find an available pio buffer
++ * @dd: the infinipath device
++ * @plen: the size of the PIO buffer needed in 32-bit words
++ * @pbufnum: the buffer number is placed here
++ */
++u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 plen, u32 *pbufnum)
++{
++	u32 __iomem *buf;
++	u32 pnum, nbufs;
++	u32 first, lasti;
++
++	if (plen + 1 >= IPATH_SMALLBUF_DWORDS) {
++		first = dd->ipath_piobcnt2k;
++		lasti = dd->ipath_lastpioindexl;
++	} else {
++		first = 0;
++		lasti = dd->ipath_lastpioindex;
++	}
++	nbufs = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
++	buf = ipath_getpiobuf_range(dd, &pnum, first, nbufs, lasti);
++
++	if (buf) {
++		/*
++		 * Set next starting place.  It's just an optimization,
++		 * it doesn't matter who wins on this, so no locking
++		 */
++		if (plen + 1 >= IPATH_SMALLBUF_DWORDS)
++			dd->ipath_lastpioindexl = pnum + 1;
++		else
++			dd->ipath_lastpioindex = pnum + 1;
++		if (dd->ipath_upd_pio_shadow)
++			dd->ipath_upd_pio_shadow = 0;
++		if (dd->ipath_consec_nopiobuf)
++			dd->ipath_consec_nopiobuf = 0;
++		ipath_cdbg(VERBOSE, "Return piobuf%u %uk @ %p\n",
++			   pnum, (pnum < dd->ipath_piobcnt2k) ? 2 : 4, buf);
++		if (pbufnum)
++			*pbufnum = pnum;
++
++	}
+ 	return buf;
+ }
+ 
+ /**
++ * ipath_chg_pioavailkernel - change which send buffers are available for kernel
++ * @dd: the infinipath device
++ * @start: the starting send buffer number
++ * @len: the number of send buffers
++ * @avail: true if the buffers are available for kernel use, false otherwise
++ */
++void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start,
++			      unsigned len, int avail)
++{
++	unsigned long flags;
++	unsigned end;
++
++	/* There are two bits per send buffer (busy and generation) */
++	start *= 2;
++	len *= 2;
++	end = start + len;
++
++	/* Set or clear the generation bits. */
++	spin_lock_irqsave(&ipath_pioavail_lock, flags);
++	while (start < end) {
++		if (avail) {
++			__clear_bit(start + INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT,
++				dd->ipath_pioavailshadow);
++			__set_bit(start, dd->ipath_pioavailkernel);
++		} else {
++			__set_bit(start + INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT,
++				dd->ipath_pioavailshadow);
++			__clear_bit(start, dd->ipath_pioavailkernel);
++		}
++		start += 2;
++	}
++	spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
++}
++
++/**
+  * ipath_create_rcvhdrq - create a receive header queue
+  * @dd: the infinipath device
+  * @pd: the port data
+@@ -1566,19 +1707,27 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+ 			ret = -ENOMEM;
+ 			goto bail;
+ 		}
+-		pd->port_rcvhdrtail_kvaddr = dma_alloc_coherent(
+-			&dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail, GFP_KERNEL);
+-		if (!pd->port_rcvhdrtail_kvaddr) {
+-			ipath_dev_err(dd, "attempt to allocate 1 page "
+-				      "for port %u rcvhdrqtailaddr failed\n",
+-				      pd->port_port);
+-			ret = -ENOMEM;
+-			dma_free_coherent(&dd->pcidev->dev, amt,
+-					  pd->port_rcvhdrq, pd->port_rcvhdrq_phys);
+-			pd->port_rcvhdrq = NULL;
+-			goto bail;
++
++		if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) {
++			pd->port_rcvhdrtail_kvaddr = dma_alloc_coherent(
++				&dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail,
++				GFP_KERNEL);
++			if (!pd->port_rcvhdrtail_kvaddr) {
++				ipath_dev_err(dd, "attempt to allocate 1 page "
++					"for port %u rcvhdrqtailaddr "
++					"failed\n", pd->port_port);
++				ret = -ENOMEM;
++				dma_free_coherent(&dd->pcidev->dev, amt,
++					pd->port_rcvhdrq,
++					pd->port_rcvhdrq_phys);
++				pd->port_rcvhdrq = NULL;
++				goto bail;
++			}
++			pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail;
++			ipath_cdbg(VERBOSE, "port %d hdrtailaddr, %llx "
++				   "physical\n", pd->port_port,
++				   (unsigned long long) phys_hdrqtail);
+ 		}
+-		pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail;
+ 
+ 		pd->port_rcvhdrq_size = amt;
+ 
+@@ -1588,10 +1737,6 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+ 			   (unsigned long) pd->port_rcvhdrq_phys,
+ 			   (unsigned long) pd->port_rcvhdrq_size,
+ 			   pd->port_port);
+-
+-		ipath_cdbg(VERBOSE, "port %d hdrtailaddr, %llx physical\n",
+-			   pd->port_port,
+-			   (unsigned long long) phys_hdrqtail);
+ 	}
+ 	else
+ 		ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; "
+@@ -1615,7 +1760,6 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+ 	ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr,
+ 			      pd->port_port, pd->port_rcvhdrq_phys);
+ 
+-	ret = 0;
+ bail:
+ 	return ret;
+ }
+@@ -1632,52 +1776,149 @@ bail:
+  */
+ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl)
+ {
++	unsigned long flags;
++
++	if (dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) {
++		ipath_cdbg(VERBOSE, "Ignore while in autonegotiation\n");
++		goto bail;
++	}
++	/*
++	 * If we have SDMA, and it's not disabled, we have to kick off the
++	 * abort state machine, provided we aren't already aborting.
++	 * If we are in the process of aborting SDMA (!DISABLED, but ABORTING),
++	 * we skip the rest of this routine. It is already "in progress"
++	 */
++	if (dd->ipath_flags & IPATH_HAS_SEND_DMA) {
++		int skip_cancel;
++		u64 *statp = &dd->ipath_sdma_status;
++
++		spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++		skip_cancel =
++			!test_bit(IPATH_SDMA_DISABLED, statp) &&
++			test_and_set_bit(IPATH_SDMA_ABORTING, statp);
++		spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++		if (skip_cancel)
++			goto bail;
++	}
++
+ 	ipath_dbg("Cancelling all in-progress send buffers\n");
+-	dd->ipath_lastcancel = jiffies+HZ/2; /* skip armlaunch errs a bit */
++
++	/* skip armlaunch errs for a while */
++	dd->ipath_lastcancel = jiffies + HZ / 2;
++
+ 	/*
+-	 * the abort bit is auto-clearing.  We read scratch to be sure
+-	 * that cancels and the abort have taken effect in the chip.
++	 * The abort bit is auto-clearing.  We also don't want pioavail
++	 * update happening during this, and we don't want any other
++	 * sends going out, so turn those off for the duration.  We read
++	 * the scratch register to be sure that cancels and the abort
++	 * have taken effect in the chip.  Otherwise two parts are same
++	 * as ipath_force_pio_avail_update()
+ 	 */
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	dd->ipath_sendctrl &= ~(INFINIPATH_S_PIOBUFAVAILUPD
++		| INFINIPATH_S_PIOENABLE);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-		INFINIPATH_S_ABORT);
++		dd->ipath_sendctrl | INFINIPATH_S_ABORT);
+ 	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++	/* disarm all send buffers */
+ 	ipath_disarm_piobufs(dd, 0,
+-		(unsigned)(dd->ipath_piobcnt2k + dd->ipath_piobcnt4k));
+-	if (restore_sendctrl) /* else done by caller later */
++		dd->ipath_piobcnt2k + dd->ipath_piobcnt4k);
++
++	if (restore_sendctrl) {
++		/* else done by caller later if needed */
++		spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++		dd->ipath_sendctrl |= INFINIPATH_S_PIOBUFAVAILUPD |
++			INFINIPATH_S_PIOENABLE;
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-				 dd->ipath_sendctrl);
++			dd->ipath_sendctrl);
++		/* and again, be sure all have hit the chip */
++		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++	}
+ 
+-	/* and again, be sure all have hit the chip */
+-	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	if ((dd->ipath_flags & IPATH_HAS_SEND_DMA) &&
++	    !test_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status) &&
++	    test_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status)) {
++		spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++		/* only wait so long for intr */
++		dd->ipath_sdma_abort_intr_timeout = jiffies + HZ;
++		dd->ipath_sdma_reset_wait = 200;
++		__set_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status);
++		if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++			tasklet_hi_schedule(&dd->ipath_sdma_abort_task);
++		spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++	}
++bail:;
+ }
+ 
++/*
++ * Force an update of in-memory copy of the pioavail registers, when
++ * needed for any of a variety of reasons.  We read the scratch register
++ * to make it highly likely that the update will have happened by the
++ * time we return.  If already off (as in cancel_sends above), this
++ * routine is a nop, on the assumption that the caller will "do the
++ * right thing".
++ */
++void ipath_force_pio_avail_update(struct ipath_devdata *dd)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	if (dd->ipath_sendctrl & INFINIPATH_S_PIOBUFAVAILUPD) {
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++			dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
++		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++			dd->ipath_sendctrl);
++		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	}
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++}
+ 
+-static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
++static void ipath_set_ib_lstate(struct ipath_devdata *dd, int linkcmd,
++				int linitcmd)
+ {
++	u64 mod_wd;
+ 	static const char *what[4] = {
+ 		[0] = "NOP",
+ 		[INFINIPATH_IBCC_LINKCMD_DOWN] = "DOWN",
+ 		[INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED",
+ 		[INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE"
+ 	};
+-	int linkcmd = (which >> INFINIPATH_IBCC_LINKCMD_SHIFT) &
+-			INFINIPATH_IBCC_LINKCMD_MASK;
+-
+-	ipath_cdbg(VERBOSE, "Trying to move unit %u to %s, current ltstate "
+-		   "is %s\n", dd->ipath_unit,
+-		   what[linkcmd],
+-		   ipath_ibcstatus_str[
+-			   (ipath_read_kreg64
+-			    (dd, dd->ipath_kregs->kr_ibcstatus) >>
+-			    INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+-			   INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
+-	/* flush all queued sends when going to DOWN to be sure that
+-	 * they don't block MAD packets */
+-	if (linkcmd == INFINIPATH_IBCC_LINKCMD_DOWN)
+-		ipath_cancel_sends(dd, 1);
++
++	if (linitcmd == INFINIPATH_IBCC_LINKINITCMD_DISABLE) {
++		/*
++		 * If we are told to disable, note that so link-recovery
++		 * code does not attempt to bring us back up.
++		 */
++		preempt_disable();
++		dd->ipath_flags |= IPATH_IB_LINK_DISABLED;
++		preempt_enable();
++	} else if (linitcmd) {
++		/*
++		 * Any other linkinitcmd will lead to LINKDOWN and then
++		 * to INIT (if all is well), so clear flag to let
++		 * link-recovery code attempt to bring us back up.
++		 */
++		preempt_disable();
++		dd->ipath_flags &= ~IPATH_IB_LINK_DISABLED;
++		preempt_enable();
++	}
++
++	mod_wd = (linkcmd << dd->ibcc_lc_shift) |
++		(linitcmd << INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++	ipath_cdbg(VERBOSE,
++		"Moving unit %u to %s (initcmd=0x%x), current ltstate is %s\n",
++		dd->ipath_unit, what[linkcmd], linitcmd,
++		ipath_ibcstatus_str[ipath_ib_linktrstate(dd,
++			ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus))]);
+ 
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+-			 dd->ipath_ibcctrl | which);
++			 dd->ipath_ibcctrl | mod_wd);
++	/* read from chip so write is flushed */
++	(void) ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+ }
+ 
+ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+@@ -1687,30 +1928,28 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+ 
+ 	switch (newstate) {
+ 	case IPATH_IB_LINKDOWN_ONLY:
+-		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN <<
+-				    INFINIPATH_IBCC_LINKCMD_SHIFT);
++		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN, 0);
+ 		/* don't wait */
+ 		ret = 0;
+ 		goto bail;
+ 
+ 	case IPATH_IB_LINKDOWN:
+-		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL <<
+-				    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN,
++					INFINIPATH_IBCC_LINKINITCMD_POLL);
+ 		/* don't wait */
+ 		ret = 0;
+ 		goto bail;
+ 
+ 	case IPATH_IB_LINKDOWN_SLEEP:
+-		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_SLEEP <<
+-				    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN,
++					INFINIPATH_IBCC_LINKINITCMD_SLEEP);
+ 		/* don't wait */
+ 		ret = 0;
+ 		goto bail;
+ 
+ 	case IPATH_IB_LINKDOWN_DISABLE:
+-		ipath_set_ib_lstate(dd,
+-				    INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+-				    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN,
++					INFINIPATH_IBCC_LINKINITCMD_DISABLE);
+ 		/* don't wait */
+ 		ret = 0;
+ 		goto bail;
+@@ -1725,8 +1964,8 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+ 			ret = -EINVAL;
+ 			goto bail;
+ 		}
+-		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED <<
+-				    INFINIPATH_IBCC_LINKCMD_SHIFT);
++		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED, 0);
++
+ 		/*
+ 		 * Since the port can transition to ACTIVE by receiving
+ 		 * a non VL 15 packet, wait for either state.
+@@ -1743,8 +1982,7 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+ 			ret = -EINVAL;
+ 			goto bail;
+ 		}
+-		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE <<
+-				    INFINIPATH_IBCC_LINKCMD_SHIFT);
++		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE, 0);
+ 		lstate = IPATH_LINKACTIVE;
+ 		break;
+ 
+@@ -1753,16 +1991,41 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+ 		dd->ipath_ibcctrl |= INFINIPATH_IBCC_LOOPBACK;
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ 				 dd->ipath_ibcctrl);
++
++		/* turn heartbeat off, as it causes loopback to fail */
++		dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT,
++				       IPATH_IB_HRTBT_OFF);
++		/* don't wait */
+ 		ret = 0;
+-		goto bail; // no state change to wait for
++		goto bail;
+ 
+ 	case IPATH_IB_LINK_EXTERNAL:
+-		dev_info(&dd->pcidev->dev, "Disabling IB local loopback (normal)\n");
++		dev_info(&dd->pcidev->dev,
++			"Disabling IB local loopback (normal)\n");
++		dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT,
++				       IPATH_IB_HRTBT_ON);
+ 		dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LOOPBACK;
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ 				 dd->ipath_ibcctrl);
++		/* don't wait */
+ 		ret = 0;
+-		goto bail; // no state change to wait for
++		goto bail;
++
++	/*
++	 * Heartbeat can be explicitly enabled by the user via
++	 * "hrtbt_enable" "file", and if disabled, trying to enable here
++	 * will have no effect.  Implicit changes (heartbeat off when
++	 * loopback on, and vice versa) are included to ease testing.
++	 */
++	case IPATH_IB_LINK_HRTBT:
++		ret = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT,
++			IPATH_IB_HRTBT_ON);
++		goto bail;
++
++	case IPATH_IB_LINK_NO_HRTBT:
++		ret = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT,
++			IPATH_IB_HRTBT_OFF);
++		goto bail;
+ 
+ 	default:
+ 		ipath_dbg("Invalid linkstate 0x%x requested\n", newstate);
+@@ -1785,7 +2048,7 @@ bail:
+  * sanity checking on this, and we don't deal with what happens to
+  * programs that are already running when the size changes.
+  * NOTE: changing the MTU will usually cause the IBC to go back to
+- * link initialize (IPATH_IBSTATE_INIT) state...
++ * link INIT state...
+  */
+ int ipath_set_mtu(struct ipath_devdata *dd, u16 arg)
+ {
+@@ -1800,7 +2063,7 @@ int ipath_set_mtu(struct ipath_devdata *dd, u16 arg)
+ 	 * piosize).  We check that it's one of the valid IB sizes.
+ 	 */
+ 	if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 &&
+-	    arg != 4096) {
++	    (arg != 4096 || !ipath_mtu4096)) {
+ 		ipath_dbg("Trying to set invalid mtu %u, failing\n", arg);
+ 		ret = -EINVAL;
+ 		goto bail;
+@@ -1816,6 +2079,8 @@ int ipath_set_mtu(struct ipath_devdata *dd, u16 arg)
+ 	if (arg >= (piosize - IPATH_PIO_MAXIBHDR)) {
+ 		/* Only if it's not the initial value (or reset to it) */
+ 		if (piosize != dd->ipath_init_ibmaxlen) {
++			if (arg > piosize && arg <= dd->ipath_init_ibmaxlen)
++				piosize = dd->ipath_init_ibmaxlen;
+ 			dd->ipath_ibmaxlen = piosize;
+ 			changed = 1;
+ 		}
+@@ -1829,24 +2094,17 @@ int ipath_set_mtu(struct ipath_devdata *dd, u16 arg)
+ 	}
+ 
+ 	if (changed) {
++		u64 ibc = dd->ipath_ibcctrl, ibdw;
+ 		/*
+-		 * set the IBC maxpktlength to the size of our pio
+-		 * buffers in words
++		 * update our housekeeping variables, and set IBC max
++		 * size, same as init code; max IBC is max we allow in
++		 * buffer, less the qword pbc, plus 1 for ICRC, in dwords
+ 		 */
+-		u64 ibc = dd->ipath_ibcctrl;
++		dd->ipath_ibmaxlen = piosize - 2 * sizeof(u32);
++		ibdw = (dd->ipath_ibmaxlen >> 2) + 1;
+ 		ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK <<
+-			 INFINIPATH_IBCC_MAXPKTLEN_SHIFT);
+-
+-		piosize = piosize - 2 * sizeof(u32);    /* ignore pbc */
+-		dd->ipath_ibmaxlen = piosize;
+-		piosize /= sizeof(u32); /* in words */
+-		/*
+-		 * for ICRC, which we only send in diag test pkt mode, and
+-		 * we don't need to worry about that for mtu
+-		 */
+-		piosize += 1;
+-
+-		ibc |= piosize << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
++			 dd->ibcc_mpl_shift);
++		ibc |= ibdw << dd->ibcc_mpl_shift;
+ 		dd->ipath_ibcctrl = ibc;
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ 				 dd->ipath_ibcctrl);
+@@ -1859,11 +2117,16 @@ bail:
+ 	return ret;
+ }
+ 
+-int ipath_set_lid(struct ipath_devdata *dd, u32 arg, u8 lmc)
++int ipath_set_lid(struct ipath_devdata *dd, u32 lid, u8 lmc)
+ {
+-	dd->ipath_lid = arg;
++	dd->ipath_lid = lid;
+ 	dd->ipath_lmc = lmc;
+ 
++	dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LIDLMC, lid |
++		(~((1U << lmc) - 1)) << 16);
++
++	dev_info(&dd->pcidev->dev, "We got a lid: 0x%x\n", lid);
++
+ 	return 0;
+ }
+ 
+@@ -1925,10 +2188,8 @@ static void ipath_run_led_override(unsigned long opaque)
+ 	 * but leave that to per-chip functions.
+ 	 */
+ 	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+-	ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+-		  INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+-	lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+-		 INFINIPATH_IBCS_LINKSTATE_MASK;
++	ltstate = ipath_ib_linktrstate(dd, val);
++	lstate = ipath_ib_linkstate(dd, val);
+ 
+ 	dd->ipath_f_setextled(dd, lstate, ltstate);
+ 	mod_timer(&dd->ipath_led_override_timer, jiffies + timeoff);
+@@ -1969,9 +2230,8 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
+ 		dd->ipath_led_override_timer.data = (unsigned long) dd;
+ 		dd->ipath_led_override_timer.expires = jiffies + 1;
+ 		add_timer(&dd->ipath_led_override_timer);
+-	} else {
++	} else
+ 		atomic_dec(&dd->ipath_led_override_timer_active);
+-	}
+ }
+ 
+ /**
+@@ -1989,6 +2249,8 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+ 
+ 	ipath_dbg("Shutting down the device\n");
+ 
++	ipath_hol_up(dd); /* make sure user processes aren't suspended */
++
+ 	dd->ipath_flags |= IPATH_LINKUNK;
+ 	dd->ipath_flags &= ~(IPATH_INITTED | IPATH_LINKDOWN |
+ 			     IPATH_LINKINIT | IPATH_LINKARMED |
+@@ -2003,6 +2265,9 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ 			 dd->ipath_rcvctrl);
+ 
++	if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++		teardown_sdma(dd);
++
+ 	/*
+ 	 * gracefully stop all sends allowing any in progress to trickle out
+ 	 * first.
+@@ -2020,10 +2285,16 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+ 	 */
+ 	udelay(5);
+ 
+-	ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+-			    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++	dd->ipath_f_setextled(dd, 0, 0); /* make sure LEDs are off */
++
++	ipath_set_ib_lstate(dd, 0, INFINIPATH_IBCC_LINKINITCMD_DISABLE);
+ 	ipath_cancel_sends(dd, 0);
+ 
++	/*
++	 * we are shutting down, so tell components that care.  We don't do
++	 * this on just a link state change, much like ethernet, a cable
++	 * unplug, etc. doesn't change driver state
++	 */
+ 	signal_ib_event(dd, IB_EVENT_PORT_ERR);
+ 
+ 	/* disable IBC */
+@@ -2038,10 +2309,20 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+ 	 */
+ 	dd->ipath_f_quiet_serdes(dd);
+ 
++	/* stop all the timers that might still be running */
++	del_timer_sync(&dd->ipath_hol_timer);
+ 	if (dd->ipath_stats_timer_active) {
+ 		del_timer_sync(&dd->ipath_stats_timer);
+ 		dd->ipath_stats_timer_active = 0;
+ 	}
++	if (dd->ipath_intrchk_timer.data) {
++		del_timer_sync(&dd->ipath_intrchk_timer);
++		dd->ipath_intrchk_timer.data = 0;
++	}
++	if (atomic_read(&dd->ipath_led_override_timer_active)) {
++		del_timer_sync(&dd->ipath_led_override_timer);
++		atomic_set(&dd->ipath_led_override_timer_active, 0);
++	}
+ 
+ 	/*
+ 	 * clear all interrupts and errors, so that the next time the driver
+@@ -2115,13 +2396,13 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd)
+ 		ipath_cdbg(VERBOSE, "free closed port %d "
+ 			   "ipath_port0_skbinfo @ %p\n", pd->port_port,
+ 			   skbinfo);
+-		for (e = 0; e < dd->ipath_rcvegrcnt; e++)
+-		if (skbinfo[e].skb) {
+-			pci_unmap_single(dd->pcidev, skbinfo[e].phys,
+-					 dd->ipath_ibmaxlen,
+-					 PCI_DMA_FROMDEVICE);
+-			dev_kfree_skb(skbinfo[e].skb);
+-		}
++		for (e = 0; e < dd->ipath_p0_rcvegrcnt; e++)
++			if (skbinfo[e].skb) {
++				pci_unmap_single(dd->pcidev, skbinfo[e].phys,
++						 dd->ipath_ibmaxlen,
++						 PCI_DMA_FROMDEVICE);
++				dev_kfree_skb(skbinfo[e].skb);
++			}
+ 		vfree(skbinfo);
+ 	}
+ 	kfree(pd->port_tid_pg_list);
+@@ -2144,6 +2425,7 @@ static int __init infinipath_init(void)
+ 	 */
+ 	idr_init(&unit_table);
+ 	if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
++		printk(KERN_ERR IPATH_DRV_NAME ": idr_pre_get() failed\n");
+ 		ret = -ENOMEM;
+ 		goto bail;
+ 	}
+@@ -2235,13 +2517,18 @@ int ipath_reset_device(int unit)
+ 			}
+ 		}
+ 
++	if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++		teardown_sdma(dd);
++
+ 	dd->ipath_flags &= ~IPATH_INITTED;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL);
+ 	ret = dd->ipath_f_reset(dd);
+-	if (ret != 1)
+-		ipath_dbg("reset was not successful\n");
+-	ipath_dbg("Trying to reinitialize unit %u after reset attempt\n",
+-		  unit);
+-	ret = ipath_init_chip(dd, 1);
++	if (ret == 1) {
++		ipath_dbg("Reinitializing unit %u after reset attempt\n",
++			  unit);
++		ret = ipath_init_chip(dd, 1);
++	} else
++		ret = -EAGAIN;
+ 	if (ret)
+ 		ipath_dev_err(dd, "Reinitialize unit %u after "
+ 			      "reset failed with %d\n", unit, ret);
+@@ -2253,13 +2540,121 @@ bail:
+ 	return ret;
+ }
+ 
++/*
++ * send a signal to all the processes that have the driver open
++ * through the normal interfaces (i.e., everything other than diags
++ * interface).  Returns number of signalled processes.
++ */
++static int ipath_signal_procs(struct ipath_devdata *dd, int sig)
++{
++	int i, sub, any = 0;
++	pid_t pid;
++
++	if (!dd->ipath_pd)
++		return 0;
++	for (i = 1; i < dd->ipath_cfgports; i++) {
++		if (!dd->ipath_pd[i] || !dd->ipath_pd[i]->port_cnt ||
++		    !dd->ipath_pd[i]->port_pid)
++			continue;
++		pid = dd->ipath_pd[i]->port_pid;
++		dev_info(&dd->pcidev->dev, "context %d in use "
++			  "(PID %u), sending signal %d\n",
++			  i, pid, sig);
++		kill_proc(pid, sig, 1);
++		any++;
++		for (sub = 0; sub < INFINIPATH_MAX_SUBPORT; sub++) {
++			pid = dd->ipath_pd[i]->port_subpid[sub];
++			if (!pid)
++				continue;
++			dev_info(&dd->pcidev->dev, "sub-context "
++				"%d:%d in use (PID %u), sending "
++				"signal %d\n", i, sub, pid, sig);
++			kill_proc(pid, sig, 1);
++			any++;
++		}
++	}
++	return any;
++}
++
++static void ipath_hol_signal_down(struct ipath_devdata *dd)
++{
++	if (ipath_signal_procs(dd, SIGSTOP))
++		ipath_dbg("Stopped some processes\n");
++	ipath_cancel_sends(dd, 1);
++}
++
++
++static void ipath_hol_signal_up(struct ipath_devdata *dd)
++{
++	if (ipath_signal_procs(dd, SIGCONT))
++		ipath_dbg("Continued some processes\n");
++}
++
++/*
++ * link is down, stop any users processes, and flush pending sends
++ * to prevent HoL blocking, then start the HoL timer that
++ * periodically continues, then stop procs, so they can detect
++ * link down if they want, and do something about it.
++ * Timer may already be running, so use __mod_timer, not add_timer.
++ */
++void ipath_hol_down(struct ipath_devdata *dd)
++{
++	dd->ipath_hol_state = IPATH_HOL_DOWN;
++	ipath_hol_signal_down(dd);
++	dd->ipath_hol_next = IPATH_HOL_DOWNCONT;
++	dd->ipath_hol_timer.expires = jiffies +
++		msecs_to_jiffies(ipath_hol_timeout_ms);
++	__mod_timer(&dd->ipath_hol_timer, dd->ipath_hol_timer.expires);
++}
++
++/*
++ * link is up, continue any user processes, and ensure timer
++ * is a nop, if running.  Let timer keep running, if set; it
++ * will nop when it sees the link is up
++ */
++void ipath_hol_up(struct ipath_devdata *dd)
++{
++	ipath_hol_signal_up(dd);
++	dd->ipath_hol_state = IPATH_HOL_UP;
++}
++
++/*
++ * toggle the running/not running state of user proceses
++ * to prevent HoL blocking on chip resources, but still allow
++ * user processes to do link down special case handling.
++ * Should only be called via the timer
++ */
++void ipath_hol_event(unsigned long opaque)
++{
++	struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++
++	if (dd->ipath_hol_next == IPATH_HOL_DOWNSTOP
++		&& dd->ipath_hol_state != IPATH_HOL_UP) {
++		dd->ipath_hol_next = IPATH_HOL_DOWNCONT;
++		ipath_dbg("Stopping processes\n");
++		ipath_hol_signal_down(dd);
++	} else { /* may do "extra" if also in ipath_hol_up() */
++		dd->ipath_hol_next = IPATH_HOL_DOWNSTOP;
++		ipath_dbg("Continuing processes\n");
++		ipath_hol_signal_up(dd);
++	}
++	if (dd->ipath_hol_state == IPATH_HOL_UP)
++		ipath_dbg("link's up, don't resched timer\n");
++	else {
++		dd->ipath_hol_timer.expires = jiffies +
++			msecs_to_jiffies(ipath_hol_timeout_ms);
++		__mod_timer(&dd->ipath_hol_timer,
++			dd->ipath_hol_timer.expires);
++	}
++}
++
+ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv)
+ {
+ 	u64 val;
+-	if ( new_pol_inv > INFINIPATH_XGXS_RX_POL_MASK ) {
++
++	if (new_pol_inv > INFINIPATH_XGXS_RX_POL_MASK)
+ 		return -1;
+-	}
+-	if ( dd->ipath_rx_pol_inv != new_pol_inv ) {
++	if (dd->ipath_rx_pol_inv != new_pol_inv) {
+ 		dd->ipath_rx_pol_inv = new_pol_inv;
+ 		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+ 		val &= ~(INFINIPATH_XGXS_RX_POL_MASK <<
+diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
+index e28a42f..dc37277 100644
+--- a/drivers/infiniband/hw/ipath/ipath_eeprom.c
++++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -62,6 +62,33 @@
+  * accessing eeprom contents from within the kernel, only via sysfs.
+  */
+ 
++/* Added functionality for IBA7220-based cards */
++#define IPATH_EEPROM_DEV_V1 0xA0
++#define IPATH_EEPROM_DEV_V2 0xA2
++#define IPATH_TEMP_DEV 0x98
++#define IPATH_BAD_DEV (IPATH_EEPROM_DEV_V2+2)
++#define IPATH_NO_DEV (0xFF)
++
++/*
++ * The number of I2C chains is proliferating. Table below brings
++ * some order to the madness. The basic principle is that the
++ * table is scanned from the top, and a "probe" is made to the
++ * device probe_dev. If that succeeds, the chain is considered
++ * to be of that type, and dd->i2c_chain_type is set to the index+1
++ * of the entry.
++ * The +1 is so static initialization can mean "unknown, do probe."
++ */
++static struct i2c_chain_desc {
++	u8 probe_dev;	/* If seen at probe, chain is this type */
++	u8 eeprom_dev;	/* Dev addr (if any) for EEPROM */
++	u8 temp_dev;	/* Dev Addr (if any) for Temp-sense */
++} i2c_chains[] = {
++	{ IPATH_BAD_DEV, IPATH_NO_DEV, IPATH_NO_DEV }, /* pre-iba7220 bds */
++	{ IPATH_EEPROM_DEV_V1, IPATH_EEPROM_DEV_V1, IPATH_TEMP_DEV}, /* V1 */
++	{ IPATH_EEPROM_DEV_V2, IPATH_EEPROM_DEV_V2, IPATH_TEMP_DEV}, /* V2 */
++	{ IPATH_NO_DEV }
++};
++
+ enum i2c_type {
+ 	i2c_line_scl = 0,
+ 	i2c_line_sda
+@@ -75,13 +102,6 @@ enum i2c_state {
+ #define READ_CMD 1
+ #define WRITE_CMD 0
+ 
+-static int eeprom_init;
+-
+-/*
+- * The gpioval manipulation really should be protected by spinlocks
+- * or be converted to use atomic operations.
+- */
+-
+ /**
+  * i2c_gpio_set - set a GPIO line
+  * @dd: the infinipath device
+@@ -241,6 +261,27 @@ static int i2c_ackrcv(struct ipath_devdata *dd)
+ }
+ 
+ /**
++ * rd_byte - read a byte, leaving ACK, STOP, etc up to caller
++ * @dd: the infinipath device
++ *
++ * Returns byte shifted out of device
++ */
++static int rd_byte(struct ipath_devdata *dd)
++{
++	int bit_cntr, data;
++
++	data = 0;
++
++	for (bit_cntr = 7; bit_cntr >= 0; --bit_cntr) {
++		data <<= 1;
++		scl_out(dd, i2c_line_high);
++		data |= sda_in(dd, 0);
++		scl_out(dd, i2c_line_low);
++	}
++	return data;
++}
++
++/**
+  * wr_byte - write a byte, one bit at a time
+  * @dd: the infinipath device
+  * @data: the byte to write
+@@ -331,7 +372,6 @@ static int eeprom_reset(struct ipath_devdata *dd)
+ 	ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg "
+ 		   "is %llx\n", (unsigned long long) *gpioval);
+ 
+-	eeprom_init = 1;
+ 	/*
+ 	 * This is to get the i2c into a known state, by first going low,
+ 	 * then tristate sda (and then tristate scl as first thing
+@@ -340,12 +380,17 @@ static int eeprom_reset(struct ipath_devdata *dd)
+ 	scl_out(dd, i2c_line_low);
+ 	sda_out(dd, i2c_line_high);
+ 
++	/* Clock up to 9 cycles looking for SDA hi, then issue START and STOP */
+ 	while (clock_cycles_left--) {
+ 		scl_out(dd, i2c_line_high);
+ 
++		/* SDA seen high, issue START by dropping it while SCL high */
+ 		if (sda_in(dd, 0)) {
+ 			sda_out(dd, i2c_line_low);
+ 			scl_out(dd, i2c_line_low);
++			/* ATMEL spec says must be followed by STOP. */
++			scl_out(dd, i2c_line_high);
++			sda_out(dd, i2c_line_high);
+ 			ret = 0;
+ 			goto bail;
+ 		}
+@@ -359,29 +404,121 @@ bail:
+ 	return ret;
+ }
+ 
+-/**
+- * ipath_eeprom_read - receives bytes from the eeprom via I2C
+- * @dd: the infinipath device
+- * @eeprom_offset: address to read from
+- * @buffer: where to store result
+- * @len: number of bytes to receive
++/*
++ * Probe for I2C device at specified address. Returns 0 for "success"
++ * to match rest of this file.
++ * Leave bus in "reasonable" state for further commands.
+  */
++static int i2c_probe(struct ipath_devdata *dd, int devaddr)
++{
++	int ret = 0;
++
++	ret = eeprom_reset(dd);
++	if (ret) {
++		ipath_dev_err(dd, "Failed reset probing device 0x%02X\n",
++			      devaddr);
++		return ret;
++	}
++	/*
++	 * Reset no longer leaves bus in start condition, so normal
++	 * i2c_startcmd() will do.
++	 */
++	ret = i2c_startcmd(dd, devaddr | READ_CMD);
++	if (ret)
++		ipath_cdbg(VERBOSE, "Failed startcmd for device 0x%02X\n",
++			   devaddr);
++	else {
++		/*
++		 * Device did respond. Complete a single-byte read, because some
++		 * devices apparently cannot handle STOP immediately after they
++		 * ACK the start-cmd.
++		 */
++		int data;
++		data = rd_byte(dd);
++		stop_cmd(dd);
++		ipath_cdbg(VERBOSE, "Response from device 0x%02X\n", devaddr);
++	}
++	return ret;
++}
++
++/*
++ * Returns the "i2c type". This is a pointer to a struct that describes
++ * the I2C chain on this board. To minimize impact on struct ipath_devdata,
++ * the (small integer) index into the table is actually memoized, rather
++ * then the pointer.
++ * Memoization is because the type is determined on the first call per chip.
++ * An alternative would be to move type determination to early
++ * init code.
++ */
++static struct i2c_chain_desc *ipath_i2c_type(struct ipath_devdata *dd)
++{
++	int idx;
++
++	/* Get memoized index, from previous successful probes */
++	idx = dd->ipath_i2c_chain_type - 1;
++	if (idx >= 0 && idx < (ARRAY_SIZE(i2c_chains) - 1))
++		goto done;
++
++	idx = 0;
++	while (i2c_chains[idx].probe_dev != IPATH_NO_DEV) {
++		/* if probe succeeds, this is type */
++		if (!i2c_probe(dd, i2c_chains[idx].probe_dev))
++			break;
++		++idx;
++	}
++
++	/*
++	 * Old EEPROM (first entry) may require a reset after probe,
++	 * rather than being able to "start" after "stop"
++	 */
++	if (idx == 0)
++		eeprom_reset(dd);
++
++	if (i2c_chains[idx].probe_dev == IPATH_NO_DEV)
++		idx = -1;
++	else
++		dd->ipath_i2c_chain_type = idx + 1;
++done:
++	return (idx >= 0) ? i2c_chains + idx : NULL;
++}
+ 
+ static int ipath_eeprom_internal_read(struct ipath_devdata *dd,
+ 					u8 eeprom_offset, void *buffer, int len)
+ {
+-	/* compiler complains unless initialized */
+-	u8 single_byte = 0;
+-	int bit_cntr;
+ 	int ret;
++	struct i2c_chain_desc *icd;
++	u8 *bp = buffer;
+ 
+-	if (!eeprom_init)
+-		eeprom_reset(dd);
+-
+-	eeprom_offset = (eeprom_offset << 1) | READ_CMD;
++	ret = 1;
++	icd = ipath_i2c_type(dd);
++	if (!icd)
++		goto bail;
+ 
+-	if (i2c_startcmd(dd, eeprom_offset)) {
+-		ipath_dbg("Failed startcmd\n");
++	if (icd->eeprom_dev == IPATH_NO_DEV) {
++		/* legacy not-really-I2C */
++		ipath_cdbg(VERBOSE, "Start command only address\n");
++		eeprom_offset = (eeprom_offset << 1) | READ_CMD;
++		ret = i2c_startcmd(dd, eeprom_offset);
++	} else {
++		/* Actual I2C */
++		ipath_cdbg(VERBOSE, "Start command uses devaddr\n");
++		if (i2c_startcmd(dd, icd->eeprom_dev | WRITE_CMD)) {
++			ipath_dbg("Failed EEPROM startcmd\n");
++			stop_cmd(dd);
++			ret = 1;
++			goto bail;
++		}
++		ret = wr_byte(dd, eeprom_offset);
++		stop_cmd(dd);
++		if (ret) {
++			ipath_dev_err(dd, "Failed to write EEPROM address\n");
++			ret = 1;
++			goto bail;
++		}
++		ret = i2c_startcmd(dd, icd->eeprom_dev | READ_CMD);
++	}
++	if (ret) {
++		ipath_dbg("Failed startcmd for dev %02X\n", icd->eeprom_dev);
+ 		stop_cmd(dd);
+ 		ret = 1;
+ 		goto bail;
+@@ -392,22 +529,11 @@ static int ipath_eeprom_internal_read(struct ipath_devdata *dd,
+ 	 * incrementing the address.
+ 	 */
+ 	while (len-- > 0) {
+-		/* get data */
+-		single_byte = 0;
+-		for (bit_cntr = 8; bit_cntr; bit_cntr--) {
+-			u8 bit;
+-			scl_out(dd, i2c_line_high);
+-			bit = sda_in(dd, 0);
+-			single_byte |= bit << (bit_cntr - 1);
+-			scl_out(dd, i2c_line_low);
+-		}
+-
++		/* get and store data */
++		*bp++ = rd_byte(dd);
+ 		/* send ack if not the last byte */
+ 		if (len)
+ 			send_ack(dd);
+-
+-		*((u8 *) buffer) = single_byte;
+-		buffer++;
+ 	}
+ 
+ 	stop_cmd(dd);
+@@ -418,31 +544,40 @@ bail:
+ 	return ret;
+ }
+ 
+-
+-/**
+- * ipath_eeprom_write - writes data to the eeprom via I2C
+- * @dd: the infinipath device
+- * @eeprom_offset: where to place data
+- * @buffer: data to write
+- * @len: number of bytes to write
+- */
+ static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offset,
+ 				       const void *buffer, int len)
+ {
+-	u8 single_byte;
+ 	int sub_len;
+ 	const u8 *bp = buffer;
+ 	int max_wait_time, i;
+ 	int ret;
++	struct i2c_chain_desc *icd;
+ 
+-	if (!eeprom_init)
+-		eeprom_reset(dd);
++	ret = 1;
++	icd = ipath_i2c_type(dd);
++	if (!icd)
++		goto bail;
+ 
+ 	while (len > 0) {
+-		if (i2c_startcmd(dd, (eeprom_offset << 1) | WRITE_CMD)) {
+-			ipath_dbg("Failed to start cmd offset %u\n",
+-				  eeprom_offset);
+-			goto failed_write;
++		if (icd->eeprom_dev == IPATH_NO_DEV) {
++			if (i2c_startcmd(dd,
++					 (eeprom_offset << 1) | WRITE_CMD)) {
++				ipath_dbg("Failed to start cmd offset %u\n",
++					eeprom_offset);
++				goto failed_write;
++			}
++		} else {
++			/* Real I2C */
++			if (i2c_startcmd(dd, icd->eeprom_dev | WRITE_CMD)) {
++				ipath_dbg("Failed EEPROM startcmd\n");
++				goto failed_write;
++			}
++			ret = wr_byte(dd, eeprom_offset);
++			if (ret) {
++				ipath_dev_err(dd, "Failed to write EEPROM "
++					      "address\n");
++				goto failed_write;
++			}
+ 		}
+ 
+ 		sub_len = min(len, 4);
+@@ -468,9 +603,11 @@ static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offse
+ 		 * the writes have completed.   We do this inline to avoid
+ 		 * the debug prints that are in the real read routine
+ 		 * if the startcmd fails.
++		 * We also use the proper device address, so it doesn't matter
++		 * whether we have real eeprom_dev. legacy likes any address.
+ 		 */
+ 		max_wait_time = 100;
+-		while (i2c_startcmd(dd, READ_CMD)) {
++		while (i2c_startcmd(dd, icd->eeprom_dev | READ_CMD)) {
+ 			stop_cmd(dd);
+ 			if (!--max_wait_time) {
+ 				ipath_dbg("Did not get successful read to "
+@@ -478,15 +615,8 @@ static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offse
+ 				goto failed_write;
+ 			}
+ 		}
+-		/* now read the zero byte */
+-		for (i = single_byte = 0; i < 8; i++) {
+-			u8 bit;
+-			scl_out(dd, i2c_line_high);
+-			bit = sda_in(dd, 0);
+-			scl_out(dd, i2c_line_low);
+-			single_byte <<= 1;
+-			single_byte |= bit;
+-		}
++		/* now read (and ignore) the resulting byte */
++		rd_byte(dd);
+ 		stop_cmd(dd);
+ 	}
+ 
+@@ -501,9 +631,12 @@ bail:
+ 	return ret;
+ }
+ 
+-/*
+- * The public entry-points ipath_eeprom_read() and ipath_eeprom_write()
+- * are now just wrappers around the internal functions.
++/**
++ * ipath_eeprom_read - receives bytes from the eeprom via I2C
++ * @dd: the infinipath device
++ * @eeprom_offset: address to read from
++ * @buffer: where to store result
++ * @len: number of bytes to receive
+  */
+ int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+ 			void *buff, int len)
+@@ -519,6 +652,13 @@ int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+ 	return ret;
+ }
+ 
++/**
++ * ipath_eeprom_write - writes data to the eeprom via I2C
++ * @dd: the infinipath device
++ * @eeprom_offset: where to place data
++ * @buffer: data to write
++ * @len: number of bytes to write
++ */
+ int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
+ 			const void *buff, int len)
+ {
+@@ -820,7 +960,7 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
+ 	 * if we log an hour at 31 minutes, then we would need to set
+ 	 * active_time to -29 to accurately count the _next_ hour.
+ 	 */
+-	if (new_time > 3600) {
++	if (new_time >= 3600) {
+ 		new_hrs = new_time / 3600;
+ 		atomic_sub((new_hrs * 3600), &dd->ipath_active_time);
+ 		new_hrs += dd->ipath_eep_hrs;
+@@ -885,3 +1025,159 @@ void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr)
+ 	spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+ 	return;
+ }
++
++static int ipath_tempsense_internal_read(struct ipath_devdata *dd, u8 regnum)
++{
++	int ret;
++	struct i2c_chain_desc *icd;
++
++	ret = -ENOENT;
++
++	icd = ipath_i2c_type(dd);
++	if (!icd)
++		goto bail;
++
++	if (icd->temp_dev == IPATH_NO_DEV) {
++		/* tempsense only exists on new, real-I2C boards */
++		ret = -ENXIO;
++		goto bail;
++	}
++
++	if (i2c_startcmd(dd, icd->temp_dev | WRITE_CMD)) {
++		ipath_dbg("Failed tempsense startcmd\n");
++		stop_cmd(dd);
++		ret = -ENXIO;
++		goto bail;
++	}
++	ret = wr_byte(dd, regnum);
++	stop_cmd(dd);
++	if (ret) {
++		ipath_dev_err(dd, "Failed tempsense WR command %02X\n",
++			      regnum);
++		ret = -ENXIO;
++		goto bail;
++	}
++	if (i2c_startcmd(dd, icd->temp_dev | READ_CMD)) {
++		ipath_dbg("Failed tempsense RD startcmd\n");
++		stop_cmd(dd);
++		ret = -ENXIO;
++		goto bail;
++	}
++	/*
++	 * We can only clock out one byte per command, sensibly
++	 */
++	ret = rd_byte(dd);
++	stop_cmd(dd);
++
++bail:
++	return ret;
++}
++
++#define VALID_TS_RD_REG_MASK 0xBF
++
++/**
++ * ipath_tempsense_read - read register of temp sensor via I2C
++ * @dd: the infinipath device
++ * @regnum: register to read from
++ *
++ * returns reg contents (0..255) or < 0 for error
++ */
++int ipath_tempsense_read(struct ipath_devdata *dd, u8 regnum)
++{
++	int ret;
++
++	if (regnum > 7)
++		return -EINVAL;
++
++	/* return a bogus value for (the one) register we do not have */
++	if (!((1 << regnum) & VALID_TS_RD_REG_MASK))
++		return 0;
++
++	ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
++	if (!ret) {
++		ret = ipath_tempsense_internal_read(dd, regnum);
++		mutex_unlock(&dd->ipath_eep_lock);
++	}
++
++	/*
++	 * There are three possibilities here:
++	 * ret is actual value (0..255)
++	 * ret is -ENXIO or -EINVAL from code in this file
++	 * ret is -EINTR from mutex_lock_interruptible.
++	 */
++	return ret;
++}
++
++static int ipath_tempsense_internal_write(struct ipath_devdata *dd,
++					  u8 regnum, u8 data)
++{
++	int ret = -ENOENT;
++	struct i2c_chain_desc *icd;
++
++	icd = ipath_i2c_type(dd);
++	if (!icd)
++		goto bail;
++
++	if (icd->temp_dev == IPATH_NO_DEV) {
++		/* tempsense only exists on new, real-I2C boards */
++		ret = -ENXIO;
++		goto bail;
++	}
++	if (i2c_startcmd(dd, icd->temp_dev | WRITE_CMD)) {
++		ipath_dbg("Failed tempsense startcmd\n");
++		stop_cmd(dd);
++		ret = -ENXIO;
++		goto bail;
++	}
++	ret = wr_byte(dd, regnum);
++	if (ret) {
++		stop_cmd(dd);
++		ipath_dev_err(dd, "Failed to write tempsense command %02X\n",
++			      regnum);
++		ret = -ENXIO;
++		goto bail;
++	}
++	ret = wr_byte(dd, data);
++	stop_cmd(dd);
++	ret = i2c_startcmd(dd, icd->temp_dev | READ_CMD);
++	if (ret) {
++		ipath_dev_err(dd, "Failed tempsense data wrt to %02X\n",
++			      regnum);
++		ret = -ENXIO;
++	}
++
++bail:
++	return ret;
++}
++
++#define VALID_TS_WR_REG_MASK ((1 << 9) | (1 << 0xB) | (1 << 0xD))
++
++/**
++ * ipath_tempsense_write - write register of temp sensor via I2C
++ * @dd: the infinipath device
++ * @regnum: register to write
++ * @data: data to write
++ *
++ * returns 0 for success or < 0 for error
++ */
++int ipath_tempsense_write(struct ipath_devdata *dd, u8 regnum, u8 data)
++{
++	int ret;
++
++	if (regnum > 15 || !((1 << regnum) & VALID_TS_WR_REG_MASK))
++		return -EINVAL;
++
++	ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
++	if (!ret) {
++		ret = ipath_tempsense_internal_write(dd, regnum, data);
++		mutex_unlock(&dd->ipath_eep_lock);
++	}
++
++	/*
++	 * There are three possibilities here:
++	 * ret is 0 for success
++	 * ret is -ENXIO or -EINVAL from code in this file
++	 * ret is -EINTR from mutex_lock_interruptible.
++	 */
++	return ret;
++}
+diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
+index 7e025c8..8b17522 100644
+--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
++++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -36,21 +36,28 @@
+ #include <linux/cdev.h>
+ #include <linux/swap.h>
+ #include <linux/vmalloc.h>
++#include <linux/highmem.h>
++#include <linux/io.h>
++#include <linux/jiffies.h>
+ #include <asm/pgtable.h>
+ 
+ #include "ipath_kernel.h"
+ #include "ipath_common.h"
++#include "ipath_user_sdma.h"
+ 
+ static int ipath_open(struct inode *, struct file *);
+ static int ipath_close(struct inode *, struct file *);
+ static ssize_t ipath_write(struct file *, const char __user *, size_t,
+ 			   loff_t *);
++static ssize_t ipath_writev(struct kiocb *, const struct iovec *,
++			    unsigned long , loff_t);
+ static unsigned int ipath_poll(struct file *, struct poll_table_struct *);
+ static int ipath_mmap(struct file *, struct vm_area_struct *);
+ 
+ static const struct file_operations ipath_file_ops = {
+ 	.owner = THIS_MODULE,
+ 	.write = ipath_write,
++	.aio_write = ipath_writev,
+ 	.open = ipath_open,
+ 	.release = ipath_close,
+ 	.poll = ipath_poll,
+@@ -184,6 +191,29 @@ static int ipath_get_base_info(struct file *fp,
+ 		kinfo->spi_piobufbase = (u64) pd->port_piobufs +
+ 			dd->ipath_palign * kinfo->spi_piocnt * slave;
+ 	}
++
++	/*
++	 * Set the PIO avail update threshold to no larger
++	 * than the number of buffers per process. Note that
++	 * we decrease it here, but won't ever increase it.
++	 */
++	if (dd->ipath_pioupd_thresh &&
++	    kinfo->spi_piocnt < dd->ipath_pioupd_thresh) {
++		unsigned long flags;
++
++		dd->ipath_pioupd_thresh = kinfo->spi_piocnt;
++		ipath_dbg("Decreased pio update threshold to %u\n",
++			dd->ipath_pioupd_thresh);
++		spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++		dd->ipath_sendctrl &= ~(INFINIPATH_S_UPDTHRESH_MASK
++			<< INFINIPATH_S_UPDTHRESH_SHIFT);
++		dd->ipath_sendctrl |= dd->ipath_pioupd_thresh
++			<< INFINIPATH_S_UPDTHRESH_SHIFT;
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++			dd->ipath_sendctrl);
++		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++	}
++
+ 	if (shared) {
+ 		kinfo->spi_port_uregbase = (u64) dd->ipath_uregbase +
+ 			dd->ipath_ureg_align * pd->port_port;
+@@ -219,7 +249,12 @@ static int ipath_get_base_info(struct file *fp,
+ 	kinfo->spi_pioalign = dd->ipath_palign;
+ 
+ 	kinfo->spi_qpair = IPATH_KD_QP;
+-	kinfo->spi_piosize = dd->ipath_ibmaxlen;
++	/*
++	 * user mode PIO buffers are always 2KB, even when 4KB can
++	 * be received, and sent via the kernel; this is ibmaxlen
++	 * for 2K MTU.
++	 */
++	kinfo->spi_piosize = dd->ipath_piosize2k - 2 * sizeof(u32);
+ 	kinfo->spi_mtu = dd->ipath_ibmaxlen;	/* maxlen, not ibmtu */
+ 	kinfo->spi_port = pd->port_port;
+ 	kinfo->spi_subport = subport_fp(fp);
+@@ -1598,6 +1633,9 @@ static int try_alloc_port(struct ipath_devdata *dd, int port,
+ 		port_fp(fp) = pd;
+ 		pd->port_pid = current->pid;
+ 		strncpy(pd->port_comm, current->comm, sizeof(pd->port_comm));
++		ipath_chg_pioavailkernel(dd,
++			dd->ipath_pbufsport * (pd->port_port - 1),
++			dd->ipath_pbufsport, 0);
+ 		ipath_stats.sps_ports++;
+ 		ret = 0;
+ 	} else
+@@ -1760,7 +1798,7 @@ static int find_shared_port(struct file *fp,
+ 	for (ndev = 0; ndev < devmax; ndev++) {
+ 		struct ipath_devdata *dd = ipath_lookup(ndev);
+ 
+-		if (!dd)
++		if (!usable(dd))
+ 			continue;
+ 		for (i = 1; i < dd->ipath_cfgports; i++) {
+ 			struct ipath_portdata *pd = dd->ipath_pd[i];
+@@ -1839,10 +1877,9 @@ static int ipath_assign_port(struct file *fp,
+ 	if (ipath_compatible_subports(swmajor, swminor) &&
+ 	    uinfo->spu_subport_cnt &&
+ 	    (ret = find_shared_port(fp, uinfo))) {
+-		mutex_unlock(&ipath_mutex);
+ 		if (ret > 0)
+ 			ret = 0;
+-		goto done;
++		goto done_chk_sdma;
+ 	}
+ 
+ 	i_minor = iminor(fp->f_path.dentry->d_inode) - IPATH_USER_MINOR_BASE;
+@@ -1854,6 +1891,21 @@ static int ipath_assign_port(struct file *fp,
+ 	else
+ 		ret = find_best_unit(fp, uinfo);
+ 
++done_chk_sdma:
++	if (!ret) {
++		struct ipath_filedata *fd = fp->private_data;
++		const struct ipath_portdata *pd = fd->pd;
++		const struct ipath_devdata *dd = pd->port_dd;
++
++		fd->pq = ipath_user_sdma_queue_create(&dd->pcidev->dev,
++						      dd->ipath_unit,
++						      pd->port_port,
++						      fd->subport);
++
++		if (!fd->pq)
++			ret = -ENOMEM;
++	}
++
+ 	mutex_unlock(&ipath_mutex);
+ 
+ done:
+@@ -1922,22 +1974,25 @@ static int ipath_do_user_init(struct file *fp,
+ 	pd->port_hdrqfull_poll = pd->port_hdrqfull;
+ 
+ 	/*
+-	 * now enable the port; the tail registers will be written to memory
+-	 * by the chip as soon as it sees the write to
+-	 * dd->ipath_kregs->kr_rcvctrl.  The update only happens on
+-	 * transition from 0 to 1, so clear it first, then set it as part of
+-	 * enabling the port.  This will (very briefly) affect any other
+-	 * open ports, but it shouldn't be long enough to be an issue.
+-	 * We explictly set the in-memory copy to 0 beforehand, so we don't
+-	 * have to wait to be sure the DMA update has happened.
++	 * Now enable the port for receive.
++	 * For chips that are set to DMA the tail register to memory
++	 * when they change (and when the update bit transitions from
++	 * 0 to 1.  So for those chips, we turn it off and then back on.
++	 * This will (very briefly) affect any other open ports, but the
++	 * duration is very short, and therefore isn't an issue.  We
++	 * explictly set the in-memory tail copy to 0 beforehand, so we
++	 * don't have to wait to be sure the DMA update has happened
++	 * (chip resets head/tail to 0 on transition to enable).
+ 	 */
+-	if (pd->port_rcvhdrtail_kvaddr)
+-		ipath_clear_rcvhdrtail(pd);
+ 	set_bit(dd->ipath_r_portenable_shift + pd->port_port,
+ 		&dd->ipath_rcvctrl);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
++	if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) {
++		if (pd->port_rcvhdrtail_kvaddr)
++			ipath_clear_rcvhdrtail(pd);
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ 			dd->ipath_rcvctrl &
+ 			~(1ULL << dd->ipath_r_tailupd_shift));
++	}
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ 			 dd->ipath_rcvctrl);
+ 	/* Notify any waiting slaves */
+@@ -1965,14 +2020,15 @@ static void unlock_expected_tids(struct ipath_portdata *pd)
+ 	ipath_cdbg(VERBOSE, "Port %u unlocking any locked expTID pages\n",
+ 		   pd->port_port);
+ 	for (i = port_tidbase; i < maxtid; i++) {
+-		if (!dd->ipath_pageshadow[i])
++		struct page *ps = dd->ipath_pageshadow[i];
++
++		if (!ps)
+ 			continue;
+ 
++		dd->ipath_pageshadow[i] = NULL;
+ 		pci_unmap_page(dd->pcidev, dd->ipath_physshadow[i],
+ 			PAGE_SIZE, PCI_DMA_FROMDEVICE);
+-		ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i],
+-						  1);
+-		dd->ipath_pageshadow[i] = NULL;
++		ipath_release_user_pages_on_close(&ps, 1);
+ 		cnt++;
+ 		ipath_stats.sps_pageunlocks++;
+ 	}
+@@ -2007,6 +2063,13 @@ static int ipath_close(struct inode *in, struct file *fp)
+ 		mutex_unlock(&ipath_mutex);
+ 		goto bail;
+ 	}
++
++	dd = pd->port_dd;
++
++	/* drain user sdma queue */
++	ipath_user_sdma_queue_drain(dd, fd->pq);
++	ipath_user_sdma_queue_destroy(fd->pq);
++
+ 	if (--pd->port_cnt) {
+ 		/*
+ 		 * XXX If the master closes the port before the slave(s),
+@@ -2019,7 +2082,6 @@ static int ipath_close(struct inode *in, struct file *fp)
+ 		goto bail;
+ 	}
+ 	port = pd->port_port;
+-	dd = pd->port_dd;
+ 
+ 	if (pd->port_hdrqfull) {
+ 		ipath_cdbg(PROC, "%s[%u] had %u rcvhdrqfull errors "
+@@ -2039,7 +2101,7 @@ static int ipath_close(struct inode *in, struct file *fp)
+ 			pd->port_rcvnowait = pd->port_pionowait = 0;
+ 	}
+ 	if (pd->port_flag) {
+-		ipath_dbg("port %u port_flag still set to 0x%lx\n",
++		ipath_cdbg(PROC, "port %u port_flag set: 0x%lx\n",
+ 			  pd->port_port, pd->port_flag);
+ 		pd->port_flag = 0;
+ 	}
+@@ -2076,6 +2138,7 @@ static int ipath_close(struct inode *in, struct file *fp)
+ 
+ 		i = dd->ipath_pbufsport * (port - 1);
+ 		ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
++		ipath_chg_pioavailkernel(dd, i, dd->ipath_pbufsport, 1);
+ 
+ 		dd->ipath_f_clear_tids(dd, pd->port_port);
+ 
+@@ -2140,17 +2203,31 @@ static int ipath_get_slave_info(struct ipath_portdata *pd,
+ 	return ret;
+ }
+ 
+-static int ipath_force_pio_avail_update(struct ipath_devdata *dd)
++static int ipath_sdma_get_inflight(struct ipath_user_sdma_queue *pq,
++				   u32 __user *inflightp)
+ {
+-	unsigned long flags;
++	const u32 val = ipath_user_sdma_inflight_counter(pq);
+ 
+-	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-		dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
+-	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
+-	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+-	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++	if (put_user(val, inflightp))
++		return -EFAULT;
++
++	return 0;
++}
++
++static int ipath_sdma_get_complete(struct ipath_devdata *dd,
++				   struct ipath_user_sdma_queue *pq,
++				   u32 __user *completep)
++{
++	u32 val;
++	int err;
++
++	err = ipath_user_sdma_make_progress(dd, pq);
++	if (err < 0)
++		return err;
++
++	val = ipath_user_sdma_complete_counter(pq);
++	if (put_user(val, completep))
++		return -EFAULT;
+ 
+ 	return 0;
+ }
+@@ -2229,6 +2306,16 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
+ 		dest = &cmd.cmd.armlaunch_ctrl;
+ 		src = &ucmd->cmd.armlaunch_ctrl;
+ 		break;
++	case IPATH_CMD_SDMA_INFLIGHT:
++		copy = sizeof(cmd.cmd.sdma_inflight);
++		dest = &cmd.cmd.sdma_inflight;
++		src = &ucmd->cmd.sdma_inflight;
++		break;
++	case IPATH_CMD_SDMA_COMPLETE:
++		copy = sizeof(cmd.cmd.sdma_complete);
++		dest = &cmd.cmd.sdma_complete;
++		src = &ucmd->cmd.sdma_complete;
++		break;
+ 	default:
+ 		ret = -EINVAL;
+ 		goto bail;
+@@ -2299,7 +2386,7 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
+ 					   cmd.cmd.slave_mask_addr);
+ 		break;
+ 	case IPATH_CMD_PIOAVAILUPD:
+-		ret = ipath_force_pio_avail_update(pd->port_dd);
++		ipath_force_pio_avail_update(pd->port_dd);
+ 		break;
+ 	case IPATH_CMD_POLL_TYPE:
+ 		pd->poll_type = cmd.cmd.poll_type;
+@@ -2310,6 +2397,17 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
+ 		else
+ 			ipath_disable_armlaunch(pd->port_dd);
+ 		break;
++	case IPATH_CMD_SDMA_INFLIGHT:
++		ret = ipath_sdma_get_inflight(user_sdma_queue_fp(fp),
++					      (u32 __user *) (unsigned long)
++					      cmd.cmd.sdma_inflight);
++		break;
++	case IPATH_CMD_SDMA_COMPLETE:
++		ret = ipath_sdma_get_complete(pd->port_dd,
++					      user_sdma_queue_fp(fp),
++					      (u32 __user *) (unsigned long)
++					      cmd.cmd.sdma_complete);
++		break;
+ 	}
+ 
+ 	if (ret >= 0)
+@@ -2319,14 +2417,28 @@ bail:
+ 	return ret;
+ }
+ 
++static ssize_t ipath_writev(struct kiocb *iocb, const struct iovec *iov,
++			    unsigned long dim, loff_t off)
++{
++	struct file *filp = iocb->ki_filp;
++	struct ipath_filedata *fp = filp->private_data;
++	struct ipath_portdata *pd = port_fp(filp);
++	struct ipath_user_sdma_queue *pq = fp->pq;
++
++	if (!dim)
++		return -EINVAL;
++
++	return ipath_user_sdma_writev(pd->port_dd, pq, iov, dim);
++}
++
+ static struct class *ipath_class;
+ 
+ static int init_cdev(int minor, char *name, const struct file_operations *fops,
+-		     struct cdev **cdevp, struct class_device **class_devp)
++		     struct cdev **cdevp, struct device **devp)
+ {
+ 	const dev_t dev = MKDEV(IPATH_MAJOR, minor);
+ 	struct cdev *cdev = NULL;
+-	struct class_device *class_dev = NULL;
++	struct device *device = NULL;
+ 	int ret;
+ 
+ 	cdev = cdev_alloc();
+@@ -2350,12 +2462,12 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
+ 		goto err_cdev;
+ 	}
+ 
+-	class_dev = class_device_create(ipath_class, NULL, dev, NULL, name);
++	device = device_create(ipath_class, NULL, dev, name);
+ 
+-	if (IS_ERR(class_dev)) {
+-		ret = PTR_ERR(class_dev);
++	if (IS_ERR(device)) {
++		ret = PTR_ERR(device);
+ 		printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
+-		       "class_dev for minor %d, %s (err %d)\n",
++		       "device for minor %d, %s (err %d)\n",
+ 		       minor, name, -ret);
+ 		goto err_cdev;
+ 	}
+@@ -2369,29 +2481,29 @@ err_cdev:
+ done:
+ 	if (ret >= 0) {
+ 		*cdevp = cdev;
+-		*class_devp = class_dev;
++		*devp = device;
+ 	} else {
+ 		*cdevp = NULL;
+-		*class_devp = NULL;
++		*devp = NULL;
+ 	}
+ 
+ 	return ret;
+ }
+ 
+ int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
+-		    struct cdev **cdevp, struct class_device **class_devp)
++		    struct cdev **cdevp, struct device **devp)
+ {
+-	return init_cdev(minor, name, fops, cdevp, class_devp);
++	return init_cdev(minor, name, fops, cdevp, devp);
+ }
+ 
+ static void cleanup_cdev(struct cdev **cdevp,
+-			 struct class_device **class_devp)
++			 struct device **devp)
+ {
+-	struct class_device *class_dev = *class_devp;
++	struct device *dev = *devp;
+ 
+-	if (class_dev) {
+-		class_device_unregister(class_dev);
+-		*class_devp = NULL;
++	if (dev) {
++		device_unregister(dev);
++		*devp = NULL;
+ 	}
+ 
+ 	if (*cdevp) {
+@@ -2401,13 +2513,13 @@ static void cleanup_cdev(struct cdev **cdevp,
+ }
+ 
+ void ipath_cdev_cleanup(struct cdev **cdevp,
+-			struct class_device **class_devp)
++			struct device **devp)
+ {
+-	cleanup_cdev(cdevp, class_devp);
++	cleanup_cdev(cdevp, devp);
+ }
+ 
+ static struct cdev *wildcard_cdev;
+-static struct class_device *wildcard_class_dev;
++static struct device *wildcard_dev;
+ 
+ static const dev_t dev = MKDEV(IPATH_MAJOR, 0);
+ 
+@@ -2464,7 +2576,7 @@ int ipath_user_add(struct ipath_devdata *dd)
+ 			goto bail;
+ 		}
+ 		ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev,
+-				&wildcard_class_dev);
++				&wildcard_dev);
+ 		if (ret < 0) {
+ 			ipath_dev_err(dd, "Could not create wildcard "
+ 				      "minor: error %d\n", -ret);
+@@ -2477,7 +2589,7 @@ int ipath_user_add(struct ipath_devdata *dd)
+ 	snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit);
+ 
+ 	ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops,
+-			&dd->user_cdev, &dd->user_class_dev);
++			&dd->user_cdev, &dd->user_dev);
+ 	if (ret < 0)
+ 		ipath_dev_err(dd, "Could not create user minor %d, %s\n",
+ 			      dd->ipath_unit + 1, name);
+@@ -2492,13 +2604,13 @@ bail:
+ 
+ void ipath_user_remove(struct ipath_devdata *dd)
+ {
+-	cleanup_cdev(&dd->user_cdev, &dd->user_class_dev);
++	cleanup_cdev(&dd->user_cdev, &dd->user_dev);
+ 
+ 	if (atomic_dec_return(&user_count) == 0) {
+ 		if (atomic_read(&user_setup) == 0)
+ 			goto bail;
+ 
+-		cleanup_cdev(&wildcard_cdev, &wildcard_class_dev);
++		cleanup_cdev(&wildcard_cdev, &wildcard_dev);
+ 		user_cleanup();
+ 
+ 		atomic_set(&user_setup, 0);
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
+index 9e2ced3..02831ad 100644
+--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
++++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
+@@ -40,6 +40,7 @@
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/htirq.h>
++#include <rdma/ib_verbs.h>
+ 
+ #include "ipath_kernel.h"
+ #include "ipath_registers.h"
+@@ -305,7 +306,9 @@ static const struct ipath_cregs ipath_ht_cregs = {
+ 
+ /* kr_intstatus, kr_intclear, kr_intmask bits */
+ #define INFINIPATH_I_RCVURG_MASK ((1U<<9)-1)
++#define INFINIPATH_I_RCVURG_SHIFT 0
+ #define INFINIPATH_I_RCVAVAIL_MASK ((1U<<9)-1)
++#define INFINIPATH_I_RCVAVAIL_SHIFT 12
+ 
+ /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+ #define INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT 0
+@@ -476,7 +479,13 @@ static const struct ipath_hwerror_msgs ipath_6110_hwerror_msgs[] = {
+ #define RXE_EAGER_PARITY (INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID \
+ 			  << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)
+ 
+-static int ipath_ht_txe_recover(struct ipath_devdata *);
++static void ipath_ht_txe_recover(struct ipath_devdata *dd)
++{
++	++ipath_stats.sps_txeparity;
++	dev_info(&dd->pcidev->dev,
++		"Recovering from TXE PIO parity error\n");
++}
++
+ 
+ /**
+  * ipath_ht_handle_hwerrors - display hardware errors.
+@@ -557,11 +566,11 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ 		 * occur if a processor speculative read is done to the PIO
+ 		 * buffer while we are sending a packet, for example.
+ 		 */
+-		if ((hwerrs & TXE_PIO_PARITY) && ipath_ht_txe_recover(dd))
++		if (hwerrs & TXE_PIO_PARITY) {
++			ipath_ht_txe_recover(dd);
+ 			hwerrs &= ~TXE_PIO_PARITY;
+-		if (hwerrs & RXE_EAGER_PARITY)
+-			ipath_dev_err(dd, "RXE parity, Eager TID error is not "
+-				"recoverable\n");
++		}
++
+ 		if (!hwerrs) {
+ 			ipath_dbg("Clearing freezemode on ignored or "
+ 				  "recovered hardware error\n");
+@@ -735,11 +744,10 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
+ 	 */
+ 	dd->ipath_flags |= IPATH_32BITCOUNTERS;
+ 	dd->ipath_flags |= IPATH_GPIO_INTR;
+-	if (dd->ipath_htspeed != 800)
++	if (dd->ipath_lbus_speed != 800)
+ 		ipath_dev_err(dd,
+ 			      "Incorrectly configured for HT @ %uMHz\n",
+-			      dd->ipath_htspeed);
+-	ret = 0;
++			      dd->ipath_lbus_speed);
+ 
+ 	/*
+ 	 * set here, not in ipath_init_*_funcs because we have to do
+@@ -839,7 +847,7 @@ static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+ 			/*
+ 			 * now write them back to clear the error.
+ 			 */
+-			pci_write_config_byte(pdev, link_off,
++			pci_write_config_word(pdev, link_off,
+ 					      linkctrl & (0xf << 8));
+ 		}
+ 	}
+@@ -904,7 +912,7 @@ static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+ 			break;
+ 		}
+ 
+-		dd->ipath_htwidth = width;
++		dd->ipath_lbus_width = width;
+ 
+ 		if (linkwidth != 0x11) {
+ 			ipath_dev_err(dd, "Not configured for 16 bit HT "
+@@ -952,8 +960,13 @@ static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+ 			speed = 200;
+ 			break;
+ 		}
+-		dd->ipath_htspeed = speed;
++		dd->ipath_lbus_speed = speed;
+ 	}
++
++	snprintf(dd->ipath_lbus_info, sizeof(dd->ipath_lbus_info),
++		"HyperTransport,%uMHz,x%u\n",
++		dd->ipath_lbus_speed,
++		dd->ipath_lbus_width);
+ }
+ 
+ static int ipath_ht_intconfig(struct ipath_devdata *dd)
+@@ -1653,22 +1666,6 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
+ }
+ 
+ 
+-static int ipath_ht_txe_recover(struct ipath_devdata *dd)
+-{
+-	int cnt = ++ipath_stats.sps_txeparity;
+-	if (cnt >= IPATH_MAX_PARITY_ATTEMPTS)  {
+-		if (cnt == IPATH_MAX_PARITY_ATTEMPTS)
+-			ipath_dev_err(dd,
+-				"Too many attempts to recover from "
+-				"TXE parity, giving up\n");
+-		return 0;
+-	}
+-	dev_info(&dd->pcidev->dev,
+-		"Recovering from TXE PIO parity error\n");
+-	return 1;
+-}
+-
+-
+ /**
+  * ipath_init_ht_get_base_info - set chip-specific flags for user code
+  * @dd: the infinipath device
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
+index c7a2f50..421cc2a 100644
+--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
++++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -38,7 +38,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+-
++#include <rdma/ib_verbs.h>
+ 
+ #include "ipath_kernel.h"
+ #include "ipath_registers.h"
+@@ -311,9 +311,14 @@ static const struct ipath_cregs ipath_pe_cregs = {
+ 	.cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt)
+ };
+ 
++/* kr_control bits */
++#define INFINIPATH_C_RESET 1U
++
+ /* kr_intstatus, kr_intclear, kr_intmask bits */
+ #define INFINIPATH_I_RCVURG_MASK ((1U<<5)-1)
++#define INFINIPATH_I_RCVURG_SHIFT 0
+ #define INFINIPATH_I_RCVAVAIL_MASK ((1U<<5)-1)
++#define INFINIPATH_I_RCVAVAIL_SHIFT 12
+ 
+ /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+ #define INFINIPATH_HWE_PCIEMEMPARITYERR_MASK  0x000000000000003fULL
+@@ -338,6 +343,9 @@ static const struct ipath_cregs ipath_pe_cregs = {
+ #define INFINIPATH_EXTS_MEMBIST_ENDTEST     0x0000000000004000
+ #define INFINIPATH_EXTS_MEMBIST_FOUND       0x0000000000008000
+ 
++/* kr_xgxsconfig bits */
++#define INFINIPATH_XGXS_RESET          0x5ULL
++
+ #define _IPATH_GPIO_SDA_NUM 1
+ #define _IPATH_GPIO_SCL_NUM 0
+ 
+@@ -346,6 +354,16 @@ static const struct ipath_cregs ipath_pe_cregs = {
+ #define IPATH_GPIO_SCL (1ULL << \
+ 	(_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+ 
++#define INFINIPATH_RT_BUFSIZE_MASK 0xe0000000ULL
++#define INFINIPATH_RT_BUFSIZE_SHIFTVAL(tid) \
++	((((tid) & INFINIPATH_RT_BUFSIZE_MASK) >> 29) + 11 - 1)
++#define INFINIPATH_RT_BUFSIZE(tid) (1 << INFINIPATH_RT_BUFSIZE_SHIFTVAL(tid))
++#define INFINIPATH_RT_IS_VALID(tid) \
++	(((tid) & INFINIPATH_RT_BUFSIZE_MASK) && \
++	 ((((tid) & INFINIPATH_RT_BUFSIZE_MASK) != INFINIPATH_RT_BUFSIZE_MASK)))
++#define INFINIPATH_RT_ADDR_MASK 0x1FFFFFFFULL /* 29 bits valid */
++#define INFINIPATH_RT_ADDR_SHIFT 10
++
+ #define INFINIPATH_R_INTRAVAIL_SHIFT 16
+ #define INFINIPATH_R_TAILUPD_SHIFT 31
+ 
+@@ -372,6 +390,8 @@ static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
+ #define TXE_PIO_PARITY ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF | \
+ 		        INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) \
+ 		        << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)
++#define RXE_EAGER_PARITY (INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID \
++			  << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)
+ 
+ static void ipath_pe_put_tid_2(struct ipath_devdata *, u64 __iomem *,
+ 			       u32, unsigned long);
+@@ -450,10 +470,8 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ 	 * make sure we get this much out, unless told to be quiet,
+ 	 * or it's occurred within the last 5 seconds
+ 	 */
+-	if ((hwerrs & ~(dd->ipath_lasthwerror |
+-			((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
+-			  INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
+-			 << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT))) ||
++	if ((hwerrs & ~(dd->ipath_lasthwerror | TXE_PIO_PARITY |
++			RXE_EAGER_PARITY)) ||
+ 	    (ipath_debug & __IPATH_VERBDBG))
+ 		dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
+ 			 "(cleared)\n", (unsigned long long) hwerrs);
+@@ -465,7 +483,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ 			      (hwerrs & ~dd->ipath_hwe_bitsextant));
+ 
+ 	ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
+-	if (ctrl & INFINIPATH_C_FREEZEMODE) {
++	if ((ctrl & INFINIPATH_C_FREEZEMODE) && !ipath_diag_inuse) {
+ 		/*
+ 		 * parity errors in send memory are recoverable,
+ 		 * just cancel the send (if indicated in * sendbuffererror),
+@@ -540,12 +558,40 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ 				 dd->ipath_hwerrmask);
+ 	}
+ 
+-	if (*msg)
++	if (hwerrs) {
++		/*
++		 * if any set that we aren't ignoring; only
++		 * make the complaint once, in case it's stuck
++		 * or recurring, and we get here multiple
++		 * times.
++		 */
+ 		ipath_dev_err(dd, "%s hardware error\n", msg);
+-	if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) {
++		if (dd->ipath_flags & IPATH_INITTED) {
++			ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);
++			ipath_setup_pe_setextled(dd,
++				INFINIPATH_IBCS_L_STATE_DOWN,
++				INFINIPATH_IBCS_LT_STATE_DISABLED);
++			ipath_dev_err(dd, "Fatal Hardware Error (freeze "
++					  "mode), no longer usable, SN %.16s\n",
++					  dd->ipath_serial);
++			isfatal = 1;
++		}
++		*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
++		/* mark as having had error */
++		*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ 		/*
+-		 * for /sys status file ; if no trailing } is copied, we'll
+-		 * know it was truncated.
++		 * mark as not usable, at a minimum until driver
++		 * is reloaded, probably until reboot, since no
++		 * other reset is possible.
++		 */
++		dd->ipath_flags &= ~IPATH_INITTED;
++	} else
++		*msg = 0; /* recovered from all of them */
++
++	if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg && msg) {
++		/*
++		 * for /sys status file ; if no trailing brace is copied,
++		 * we'll know it was truncated.
+ 		 */
+ 		snprintf(dd->ipath_freezemsg, dd->ipath_freezelen,
+ 			 "{%s}", msg);
+@@ -610,7 +656,6 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
+ 			dd->ipath_f_put_tid = ipath_pe_put_tid_2;
+ 	}
+ 
+-
+ 	/*
+ 	 * set here, not in ipath_init_*_funcs because we have to do
+ 	 * it after we can read chip registers.
+@@ -838,7 +883,7 @@ static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst,
+ 	extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
+ 				       INFINIPATH_EXTC_LED2PRIPORT_ON);
+ 
+-	if (ltst & INFINIPATH_IBCS_LT_STATE_LINKUP)
++	if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)
+ 		extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
+ 	if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ 		extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
+@@ -863,6 +908,62 @@ static void ipath_setup_pe_cleanup(struct ipath_devdata *dd)
+ 	pci_disable_msi(dd->pcidev);
+ }
+ 
++static void ipath_6120_pcie_params(struct ipath_devdata *dd)
++{
++	u16 linkstat, speed;
++	int pos;
++
++	pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
++	if (!pos) {
++		ipath_dev_err(dd, "Can't find PCI Express capability!\n");
++		goto bail;
++	}
++
++	pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,
++			     &linkstat);
++	/*
++	 * speed is bits 0-4, linkwidth is bits 4-8
++	 * no defines for them in headers
++	 */
++	speed = linkstat & 0xf;
++	linkstat >>= 4;
++	linkstat &= 0x1f;
++	dd->ipath_lbus_width = linkstat;
++
++	switch (speed) {
++	case 1:
++		dd->ipath_lbus_speed = 2500; /* Gen1, 2.5GHz */
++		break;
++	case 2:
++		dd->ipath_lbus_speed = 5000; /* Gen1, 5GHz */
++		break;
++	default: /* not defined, assume gen1 */
++		dd->ipath_lbus_speed = 2500;
++		break;
++	}
++
++	if (linkstat < 8)
++		ipath_dev_err(dd,
++			"PCIe width %u (x8 HCA), performance reduced\n",
++			linkstat);
++	else
++		ipath_cdbg(VERBOSE, "PCIe speed %u width %u (x8 HCA)\n",
++			dd->ipath_lbus_speed, linkstat);
++
++	if (speed != 1)
++		ipath_dev_err(dd,
++			"PCIe linkspeed %u is incorrect; "
++			"should be 1 (2500)!\n", speed);
++bail:
++	/* fill in string, even on errors */
++	snprintf(dd->ipath_lbus_info, sizeof(dd->ipath_lbus_info),
++		"PCIe,%uMHz,x%u\n",
++		dd->ipath_lbus_speed,
++		dd->ipath_lbus_width);
++
++	return;
++}
++
+ /**
+  * ipath_setup_pe_config - setup PCIe config related stuff
+  * @dd: the infinipath device
+@@ -920,19 +1021,8 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd,
+ 	} else
+ 		ipath_dev_err(dd, "Can't find MSI capability, "
+ 			      "can't save MSI settings for reset\n");
+-	if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP))) {
+-		u16 linkstat;
+-		pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,
+-				     &linkstat);
+-		linkstat >>= 4;
+-		linkstat &= 0x1f;
+-		if (linkstat != 8)
+-			ipath_dev_err(dd, "PCIe width %u, "
+-				      "performance reduced\n", linkstat);
+-	}
+-	else
+-		ipath_dev_err(dd, "Can't find PCI Express "
+-			      "capability!\n");
++
++	ipath_6120_pcie_params(dd);
+ 
+ 	dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
+ 	dd->ipath_link_speed_supported = IPATH_IB_SDR;
+@@ -1065,10 +1155,7 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
+ 		INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+ 		INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
+ 
+-	dd->ipath_eep_st_masks[2].errs_to_log =
+-		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
+-
+-
++	dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
+ 	dd->delay_mult = 2; /* SDR, 4X, can't change */
+ }
+ 
+@@ -1142,6 +1229,9 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd)
+ 	u64 val;
+ 	int i;
+ 	int ret;
++	u16 cmdval;
++
++	pci_read_config_word(dd->pcidev, PCI_COMMAND, &cmdval);
+ 
+ 	/* Use ERROR so it shows up in logs, etc. */
+ 	ipath_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->ipath_unit);
+@@ -1169,10 +1259,14 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd)
+ 			ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n",
+ 				      r);
+ 		/* now re-enable memory access */
++		pci_write_config_word(dd->pcidev, PCI_COMMAND, cmdval);
+ 		if ((r = pci_enable_device(dd->pcidev)))
+ 			ipath_dev_err(dd, "pci_enable_device failed after "
+ 				      "reset: %d\n", r);
+-		/* whether it worked or not, mark as present, again */
++		/*
++		 * whether it fully enabled or not, mark as present,
++		 * again (but not INITTED)
++		 */
+ 		dd->ipath_flags |= IPATH_PRESENT;
+ 		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
+ 		if (val == dd->ipath_revision) {
+@@ -1190,6 +1284,8 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd)
+ 	ret = 0; /* failed */
+ 
+ bail:
++	if (ret)
++		ipath_6120_pcie_params(dd);
+ 	return ret;
+ }
+ 
+@@ -1209,16 +1305,21 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ {
+ 	u32 __iomem *tidp32 = (u32 __iomem *)tidptr;
+ 	unsigned long flags = 0; /* keep gcc quiet */
++	int tidx;
++	spinlock_t *tidlockp;
++
++	if (!dd->ipath_kregbase)
++		return;
+ 
+ 	if (pa != dd->ipath_tidinvalid) {
+ 		if (pa & ((1U << 11) - 1)) {
+ 			dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "
+-				 "not 4KB aligned!\n", pa);
++				 "not 2KB aligned!\n", pa);
+ 			return;
+ 		}
+ 		pa >>= 11;
+ 		/* paranoia check */
+-		if (pa & (7<<29))
++		if (pa & ~INFINIPATH_RT_ADDR_MASK)
+ 			ipath_dev_err(dd,
+ 				      "BUG: Physical page address 0x%lx "
+ 				      "has bits set in 31-29\n", pa);
+@@ -1238,14 +1339,22 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ 	 * call can be done from interrupt level for the port 0 eager TIDs,
+ 	 * so we have to use irqsave locks.
+ 	 */
+-	spin_lock_irqsave(&dd->ipath_tid_lock, flags);
++	/*
++	 * Assumes tidptr always > ipath_egrtidbase
++	 * if type == RCVHQ_RCV_TYPE_EAGER.
++	 */
++	tidx = tidptr - dd->ipath_egrtidbase;
++
++	tidlockp = (type == RCVHQ_RCV_TYPE_EAGER && tidx < dd->ipath_rcvegrcnt)
++		? &dd->ipath_kernel_tid_lock : &dd->ipath_user_tid_lock;
++	spin_lock_irqsave(tidlockp, flags);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xfeeddeaf);
+-	if (dd->ipath_kregbase)
+-		writel(pa, tidp32);
++	writel(pa, tidp32);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xdeadbeef);
+ 	mmiowb();
+-	spin_unlock_irqrestore(&dd->ipath_tid_lock, flags);
++	spin_unlock_irqrestore(tidlockp, flags);
+ }
++
+ /**
+  * ipath_pe_put_tid_2 - write a TID in chip, Revision 2 or higher
+  * @dd: the infinipath device
+@@ -1261,6 +1370,10 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ 			     u32 type, unsigned long pa)
+ {
+ 	u32 __iomem *tidp32 = (u32 __iomem *)tidptr;
++	u32 tidx;
++
++	if (!dd->ipath_kregbase)
++		return;
+ 
+ 	if (pa != dd->ipath_tidinvalid) {
+ 		if (pa & ((1U << 11) - 1)) {
+@@ -1270,7 +1383,7 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ 		}
+ 		pa >>= 11;
+ 		/* paranoia check */
+-		if (pa & (7<<29))
++		if (pa & ~INFINIPATH_RT_ADDR_MASK)
+ 			ipath_dev_err(dd,
+ 				      "BUG: Physical page address 0x%lx "
+ 				      "has bits set in 31-29\n", pa);
+@@ -1280,8 +1393,8 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ 		else /* for now, always full 4KB page */
+ 			pa |= 2 << 29;
+ 	}
+-	if (dd->ipath_kregbase)
+-		writel(pa, tidp32);
++	tidx = tidptr - dd->ipath_egrtidbase;
++	writel(pa, tidp32);
+ 	mmiowb();
+ }
+ 
+@@ -1379,17 +1492,13 @@ static int ipath_pe_early_init(struct ipath_devdata *dd)
+ 	dd->ipath_egrtidbase = (u64 __iomem *)
+ 		((char __iomem *) dd->ipath_kregbase + dd->ipath_rcvegrbase);
+ 
+-	/*
+-	 * To truly support a 4KB MTU (for usermode), we need to
+-	 * bump this to a larger value.  For now, we use them for
+-	 * the kernel only.
+-	 */
+-	dd->ipath_rcvegrbufsize = 2048;
++	dd->ipath_rcvegrbufsize = ipath_mtu4096 ? 4096 : 2048;
+ 	/*
+ 	 * the min() check here is currently a nop, but it may not always
+ 	 * be, depending on just how we do ipath_rcvegrbufsize
+ 	 */
+-	dd->ipath_ibmaxlen = min(dd->ipath_piosize2k,
++	dd->ipath_ibmaxlen = min(ipath_mtu4096 ? dd->ipath_piosize4k :
++				 dd->ipath_piosize2k,
+ 				 dd->ipath_rcvegrbufsize +
+ 				 (dd->ipath_rcvhdrentsize << 2));
+ 	dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba7220.c b/drivers/infiniband/hw/ipath/ipath_iba7220.c
+new file mode 100644
+index 0000000..e3ec0d1
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_iba7220.c
+@@ -0,0 +1,2566 @@
++/*
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++/*
++ * This file contains all of the code that is specific to the
++ * InfiniPath 7220 chip (except that specific to the SerDes)
++ */
++
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <rdma/ib_verbs.h>
++
++#include "ipath_kernel.h"
++#include "ipath_registers.h"
++#include "ipath_7220.h"
++
++static void ipath_setup_7220_setextled(struct ipath_devdata *, u64, u64);
++
++static unsigned ipath_compat_ddr_negotiate = 1;
++
++module_param_named(compat_ddr_negotiate, ipath_compat_ddr_negotiate, uint,
++			S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(compat_ddr_negotiate,
++		"Attempt pre-IBTA 1.2 DDR speed negotiation");
++
++static unsigned ipath_sdma_fetch_arb = 1;
++module_param_named(fetch_arb, ipath_sdma_fetch_arb, uint, S_IRUGO);
++MODULE_PARM_DESC(fetch_arb, "IBA7220: change SDMA descriptor arbitration");
++
++/*
++ * This file contains almost all the chip-specific register information and
++ * access functions for the QLogic InfiniPath 7220 PCI-Express chip, with the
++ * exception of SerDes support, which in in ipath_sd7220.c.
++ *
++ * This lists the InfiniPath registers, in the actual chip layout.
++ * This structure should never be directly accessed.
++ */
++struct _infinipath_do_not_use_kernel_regs {
++	unsigned long long Revision;
++	unsigned long long Control;
++	unsigned long long PageAlign;
++	unsigned long long PortCnt;
++	unsigned long long DebugPortSelect;
++	unsigned long long DebugSigsIntSel; /* was Reserved0;*/
++	unsigned long long SendRegBase;
++	unsigned long long UserRegBase;
++	unsigned long long CounterRegBase;
++	unsigned long long Scratch;
++	unsigned long long EEPROMAddrCmd; /* was Reserved1; */
++	unsigned long long EEPROMData; /* was Reserved2; */
++	unsigned long long IntBlocked;
++	unsigned long long IntMask;
++	unsigned long long IntStatus;
++	unsigned long long IntClear;
++	unsigned long long ErrorMask;
++	unsigned long long ErrorStatus;
++	unsigned long long ErrorClear;
++	unsigned long long HwErrMask;
++	unsigned long long HwErrStatus;
++	unsigned long long HwErrClear;
++	unsigned long long HwDiagCtrl;
++	unsigned long long MDIO;
++	unsigned long long IBCStatus;
++	unsigned long long IBCCtrl;
++	unsigned long long ExtStatus;
++	unsigned long long ExtCtrl;
++	unsigned long long GPIOOut;
++	unsigned long long GPIOMask;
++	unsigned long long GPIOStatus;
++	unsigned long long GPIOClear;
++	unsigned long long RcvCtrl;
++	unsigned long long RcvBTHQP;
++	unsigned long long RcvHdrSize;
++	unsigned long long RcvHdrCnt;
++	unsigned long long RcvHdrEntSize;
++	unsigned long long RcvTIDBase;
++	unsigned long long RcvTIDCnt;
++	unsigned long long RcvEgrBase;
++	unsigned long long RcvEgrCnt;
++	unsigned long long RcvBufBase;
++	unsigned long long RcvBufSize;
++	unsigned long long RxIntMemBase;
++	unsigned long long RxIntMemSize;
++	unsigned long long RcvPartitionKey;
++	unsigned long long RcvQPMulticastPort;
++	unsigned long long RcvPktLEDCnt;
++	unsigned long long IBCDDRCtrl;
++	unsigned long long HRTBT_GUID;
++	unsigned long long IB_SDTEST_IF_TX;
++	unsigned long long IB_SDTEST_IF_RX;
++	unsigned long long IBCDDRCtrl2;
++	unsigned long long IBCDDRStatus;
++	unsigned long long JIntReload;
++	unsigned long long IBNCModeCtrl;
++	unsigned long long SendCtrl;
++	unsigned long long SendBufBase;
++	unsigned long long SendBufSize;
++	unsigned long long SendBufCnt;
++	unsigned long long SendAvailAddr;
++	unsigned long long TxIntMemBase;
++	unsigned long long TxIntMemSize;
++	unsigned long long SendDmaBase;
++	unsigned long long SendDmaLenGen;
++	unsigned long long SendDmaTail;
++	unsigned long long SendDmaHead;
++	unsigned long long SendDmaHeadAddr;
++	unsigned long long SendDmaBufMask0;
++	unsigned long long SendDmaBufMask1;
++	unsigned long long SendDmaBufMask2;
++	unsigned long long SendDmaStatus;
++	unsigned long long SendBufferError;
++	unsigned long long SendBufferErrorCONT1;
++	unsigned long long SendBufErr2; /* was Reserved6SBE[0/6] */
++	unsigned long long Reserved6L[2];
++	unsigned long long AvailUpdCount;
++	unsigned long long RcvHdrAddr0;
++	unsigned long long RcvHdrAddrs[16]; /* Why enumerate? */
++	unsigned long long Reserved7hdtl; /* Align next to 300 */
++	unsigned long long RcvHdrTailAddr0; /* 300, like others */
++	unsigned long long RcvHdrTailAddrs[16];
++	unsigned long long Reserved9SW[7]; /* was [8]; we have 17 ports */
++	unsigned long long IbsdEpbAccCtl; /* IB Serdes EPB access control */
++	unsigned long long IbsdEpbTransReg; /* IB Serdes EPB Transaction */
++	unsigned long long Reserved10sds; /* was SerdesStatus on */
++	unsigned long long XGXSConfig;
++	unsigned long long IBSerDesCtrl; /* Was IBPLLCfg on Monty */
++	unsigned long long EEPCtlStat; /* for "boot" EEPROM/FLASH */
++	unsigned long long EEPAddrCmd;
++	unsigned long long EEPData;
++	unsigned long long PcieEpbAccCtl;
++	unsigned long long PcieEpbTransCtl;
++	unsigned long long EfuseCtl; /* E-Fuse control */
++	unsigned long long EfuseData[4];
++	unsigned long long ProcMon;
++	/* this chip moves following two from previous 200, 208 */
++	unsigned long long PCIeRBufTestReg0;
++	unsigned long long PCIeRBufTestReg1;
++	/* added for this chip */
++	unsigned long long PCIeRBufTestReg2;
++	unsigned long long PCIeRBufTestReg3;
++	/* added for this chip, debug only */
++	unsigned long long SPC_JTAG_ACCESS_REG;
++	unsigned long long LAControlReg;
++	unsigned long long GPIODebugSelReg;
++	unsigned long long DebugPortValueReg;
++	/* added for this chip, DMA */
++	unsigned long long SendDmaBufUsed[3];
++	unsigned long long SendDmaReqTagUsed;
++	/*
++	 * added for this chip, EFUSE: note that these program 64-bit
++	 * words 2 and 3 */
++	unsigned long long efuse_pgm_data[2];
++	unsigned long long Reserved11LAalign[10]; /* Skip 4B0..4F8 */
++	/* we have 30 regs for DDS and RXEQ in IB SERDES */
++	unsigned long long SerDesDDSRXEQ[30];
++	unsigned long long Reserved12LAalign[2]; /* Skip 5F0, 5F8 */
++	/* added for LA debug support */
++	unsigned long long LAMemory[32];
++};
++
++struct _infinipath_do_not_use_counters {
++	__u64 LBIntCnt;
++	__u64 LBFlowStallCnt;
++	__u64 TxSDmaDescCnt;	/* was Reserved1 */
++	__u64 TxUnsupVLErrCnt;
++	__u64 TxDataPktCnt;
++	__u64 TxFlowPktCnt;
++	__u64 TxDwordCnt;
++	__u64 TxLenErrCnt;
++	__u64 TxMaxMinLenErrCnt;
++	__u64 TxUnderrunCnt;
++	__u64 TxFlowStallCnt;
++	__u64 TxDroppedPktCnt;
++	__u64 RxDroppedPktCnt;
++	__u64 RxDataPktCnt;
++	__u64 RxFlowPktCnt;
++	__u64 RxDwordCnt;
++	__u64 RxLenErrCnt;
++	__u64 RxMaxMinLenErrCnt;
++	__u64 RxICRCErrCnt;
++	__u64 RxVCRCErrCnt;
++	__u64 RxFlowCtrlErrCnt;
++	__u64 RxBadFormatCnt;
++	__u64 RxLinkProblemCnt;
++	__u64 RxEBPCnt;
++	__u64 RxLPCRCErrCnt;
++	__u64 RxBufOvflCnt;
++	__u64 RxTIDFullErrCnt;
++	__u64 RxTIDValidErrCnt;
++	__u64 RxPKeyMismatchCnt;
++	__u64 RxP0HdrEgrOvflCnt;
++	__u64 RxP1HdrEgrOvflCnt;
++	__u64 RxP2HdrEgrOvflCnt;
++	__u64 RxP3HdrEgrOvflCnt;
++	__u64 RxP4HdrEgrOvflCnt;
++	__u64 RxP5HdrEgrOvflCnt;
++	__u64 RxP6HdrEgrOvflCnt;
++	__u64 RxP7HdrEgrOvflCnt;
++	__u64 RxP8HdrEgrOvflCnt;
++	__u64 RxP9HdrEgrOvflCnt;	/* was Reserved6 */
++	__u64 RxP10HdrEgrOvflCnt;	/* was Reserved7 */
++	__u64 RxP11HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP12HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP13HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP14HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP15HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP16HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 IBStatusChangeCnt;
++	__u64 IBLinkErrRecoveryCnt;
++	__u64 IBLinkDownedCnt;
++	__u64 IBSymbolErrCnt;
++	/* The following are new for IBA7220 */
++	__u64 RxVL15DroppedPktCnt;
++	__u64 RxOtherLocalPhyErrCnt;
++	__u64 PcieRetryBufDiagQwordCnt;
++	__u64 ExcessBufferOvflCnt;
++	__u64 LocalLinkIntegrityErrCnt;
++	__u64 RxVlErrCnt;
++	__u64 RxDlidFltrCnt;
++	__u64 Reserved8[7];
++	__u64 PSStat;
++	__u64 PSStart;
++	__u64 PSInterval;
++	__u64 PSRcvDataCount;
++	__u64 PSRcvPktsCount;
++	__u64 PSXmitDataCount;
++	__u64 PSXmitPktsCount;
++	__u64 PSXmitWaitCount;
++};
++
++#define IPATH_KREG_OFFSET(field) (offsetof( \
++	struct _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
++#define IPATH_CREG_OFFSET(field) (offsetof( \
++	struct _infinipath_do_not_use_counters, field) / sizeof(u64))
++
++static const struct ipath_kregs ipath_7220_kregs = {
++	.kr_control = IPATH_KREG_OFFSET(Control),
++	.kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase),
++	.kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect),
++	.kr_errorclear = IPATH_KREG_OFFSET(ErrorClear),
++	.kr_errormask = IPATH_KREG_OFFSET(ErrorMask),
++	.kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus),
++	.kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl),
++	.kr_extstatus = IPATH_KREG_OFFSET(ExtStatus),
++	.kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear),
++	.kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask),
++	.kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut),
++	.kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus),
++	.kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl),
++	.kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear),
++	.kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask),
++	.kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus),
++	.kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl),
++	.kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus),
++	.kr_intblocked = IPATH_KREG_OFFSET(IntBlocked),
++	.kr_intclear = IPATH_KREG_OFFSET(IntClear),
++	.kr_intmask = IPATH_KREG_OFFSET(IntMask),
++	.kr_intstatus = IPATH_KREG_OFFSET(IntStatus),
++	.kr_mdio = IPATH_KREG_OFFSET(MDIO),
++	.kr_pagealign = IPATH_KREG_OFFSET(PageAlign),
++	.kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey),
++	.kr_portcnt = IPATH_KREG_OFFSET(PortCnt),
++	.kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP),
++	.kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase),
++	.kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize),
++	.kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl),
++	.kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase),
++	.kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt),
++	.kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt),
++	.kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize),
++	.kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize),
++	.kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase),
++	.kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize),
++	.kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase),
++	.kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt),
++	.kr_revision = IPATH_KREG_OFFSET(Revision),
++	.kr_scratch = IPATH_KREG_OFFSET(Scratch),
++	.kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError),
++	.kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl),
++	.kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendAvailAddr),
++	.kr_sendpiobufbase = IPATH_KREG_OFFSET(SendBufBase),
++	.kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendBufCnt),
++	.kr_sendpiosize = IPATH_KREG_OFFSET(SendBufSize),
++	.kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase),
++	.kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase),
++	.kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize),
++	.kr_userregbase = IPATH_KREG_OFFSET(UserRegBase),
++
++	.kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),
++
++	/* send dma related regs */
++	.kr_senddmabase = IPATH_KREG_OFFSET(SendDmaBase),
++	.kr_senddmalengen = IPATH_KREG_OFFSET(SendDmaLenGen),
++	.kr_senddmatail = IPATH_KREG_OFFSET(SendDmaTail),
++	.kr_senddmahead = IPATH_KREG_OFFSET(SendDmaHead),
++	.kr_senddmaheadaddr = IPATH_KREG_OFFSET(SendDmaHeadAddr),
++	.kr_senddmabufmask0 = IPATH_KREG_OFFSET(SendDmaBufMask0),
++	.kr_senddmabufmask1 = IPATH_KREG_OFFSET(SendDmaBufMask1),
++	.kr_senddmabufmask2 = IPATH_KREG_OFFSET(SendDmaBufMask2),
++	.kr_senddmastatus = IPATH_KREG_OFFSET(SendDmaStatus),
++
++	/* SerDes related regs */
++	.kr_ibserdesctrl = IPATH_KREG_OFFSET(IBSerDesCtrl),
++	.kr_ib_epbacc = IPATH_KREG_OFFSET(IbsdEpbAccCtl),
++	.kr_ib_epbtrans = IPATH_KREG_OFFSET(IbsdEpbTransReg),
++	.kr_pcie_epbacc = IPATH_KREG_OFFSET(PcieEpbAccCtl),
++	.kr_pcie_epbtrans = IPATH_KREG_OFFSET(PcieEpbTransCtl),
++	.kr_ib_ddsrxeq = IPATH_KREG_OFFSET(SerDesDDSRXEQ),
++
++	/*
++	 * These should not be used directly via ipath_read_kreg64(),
++	 * use them with ipath_read_kreg64_port()
++	 */
++	.kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0),
++	.kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0),
++
++	/*
++	 * The rcvpktled register controls one of the debug port signals, so
++	 * a packet activity LED can be connected to it.
++	 */
++	.kr_rcvpktledcnt = IPATH_KREG_OFFSET(RcvPktLEDCnt),
++	.kr_pcierbuftestreg0 = IPATH_KREG_OFFSET(PCIeRBufTestReg0),
++	.kr_pcierbuftestreg1 = IPATH_KREG_OFFSET(PCIeRBufTestReg1),
++
++	.kr_hrtbt_guid = IPATH_KREG_OFFSET(HRTBT_GUID),
++	.kr_ibcddrctrl = IPATH_KREG_OFFSET(IBCDDRCtrl),
++	.kr_ibcddrstatus = IPATH_KREG_OFFSET(IBCDDRStatus),
++	.kr_jintreload = IPATH_KREG_OFFSET(JIntReload)
++};
++
++static const struct ipath_cregs ipath_7220_cregs = {
++	.cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt),
++	.cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt),
++	.cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt),
++	.cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt),
++	.cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt),
++	.cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt),
++	.cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt),
++	.cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt),
++	.cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt),
++	.cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt),
++	.cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt),
++	.cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt),
++	.cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt),
++	.cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt),
++	.cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt),
++	.cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt),
++	.cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt),
++	.cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt),
++	.cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt),
++	.cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt),
++	.cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt),
++	.cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt),
++	.cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt),
++	.cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt),
++	.cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt),
++	.cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt),
++	.cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt),
++	.cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt),
++	.cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt),
++	.cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt),
++	.cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt),
++	.cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt),
++	.cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt),
++	.cr_vl15droppedpktcnt = IPATH_CREG_OFFSET(RxVL15DroppedPktCnt),
++	.cr_rxotherlocalphyerrcnt =
++		IPATH_CREG_OFFSET(RxOtherLocalPhyErrCnt),
++	.cr_excessbufferovflcnt = IPATH_CREG_OFFSET(ExcessBufferOvflCnt),
++	.cr_locallinkintegrityerrcnt =
++		IPATH_CREG_OFFSET(LocalLinkIntegrityErrCnt),
++	.cr_rxvlerrcnt = IPATH_CREG_OFFSET(RxVlErrCnt),
++	.cr_rxdlidfltrcnt = IPATH_CREG_OFFSET(RxDlidFltrCnt),
++	.cr_psstat = IPATH_CREG_OFFSET(PSStat),
++	.cr_psstart = IPATH_CREG_OFFSET(PSStart),
++	.cr_psinterval = IPATH_CREG_OFFSET(PSInterval),
++	.cr_psrcvdatacount = IPATH_CREG_OFFSET(PSRcvDataCount),
++	.cr_psrcvpktscount = IPATH_CREG_OFFSET(PSRcvPktsCount),
++	.cr_psxmitdatacount = IPATH_CREG_OFFSET(PSXmitDataCount),
++	.cr_psxmitpktscount = IPATH_CREG_OFFSET(PSXmitPktsCount),
++	.cr_psxmitwaitcount = IPATH_CREG_OFFSET(PSXmitWaitCount),
++};
++
++/* kr_control bits */
++#define INFINIPATH_C_RESET (1U<<7)
++
++/* kr_intstatus, kr_intclear, kr_intmask bits */
++#define INFINIPATH_I_RCVURG_MASK ((1ULL<<17)-1)
++#define INFINIPATH_I_RCVURG_SHIFT 32
++#define INFINIPATH_I_RCVAVAIL_MASK ((1ULL<<17)-1)
++#define INFINIPATH_I_RCVAVAIL_SHIFT 0
++#define INFINIPATH_I_SERDESTRIMDONE (1ULL<<27)
++
++/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
++#define INFINIPATH_HWE_PCIEMEMPARITYERR_MASK  0x00000000000000ffULL
++#define INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT 0
++#define INFINIPATH_HWE_PCIEPOISONEDTLP      0x0000000010000000ULL
++#define INFINIPATH_HWE_PCIECPLTIMEOUT       0x0000000020000000ULL
++#define INFINIPATH_HWE_PCIEBUSPARITYXTLH    0x0000000040000000ULL
++#define INFINIPATH_HWE_PCIEBUSPARITYXADM    0x0000000080000000ULL
++#define INFINIPATH_HWE_PCIEBUSPARITYRADM    0x0000000100000000ULL
++#define INFINIPATH_HWE_COREPLL_FBSLIP       0x0080000000000000ULL
++#define INFINIPATH_HWE_COREPLL_RFSLIP       0x0100000000000000ULL
++#define INFINIPATH_HWE_PCIE1PLLFAILED       0x0400000000000000ULL
++#define INFINIPATH_HWE_PCIE0PLLFAILED       0x0800000000000000ULL
++#define INFINIPATH_HWE_SERDESPLLFAILED      0x1000000000000000ULL
++/* specific to this chip */
++#define INFINIPATH_HWE_PCIECPLDATAQUEUEERR         0x0000000000000040ULL
++#define INFINIPATH_HWE_PCIECPLHDRQUEUEERR          0x0000000000000080ULL
++#define INFINIPATH_HWE_SDMAMEMREADERR              0x0000000010000000ULL
++#define INFINIPATH_HWE_CLK_UC_PLLNOTLOCKED	   0x2000000000000000ULL
++#define INFINIPATH_HWE_PCIESERDESQ0PCLKNOTDETECT   0x0100000000000000ULL
++#define INFINIPATH_HWE_PCIESERDESQ1PCLKNOTDETECT   0x0200000000000000ULL
++#define INFINIPATH_HWE_PCIESERDESQ2PCLKNOTDETECT   0x0400000000000000ULL
++#define INFINIPATH_HWE_PCIESERDESQ3PCLKNOTDETECT   0x0800000000000000ULL
++#define INFINIPATH_HWE_DDSRXEQMEMORYPARITYERR	   0x0000008000000000ULL
++#define INFINIPATH_HWE_IB_UC_MEMORYPARITYERR	   0x0000004000000000ULL
++#define INFINIPATH_HWE_PCIE_UC_OCT0MEMORYPARITYERR 0x0000001000000000ULL
++#define INFINIPATH_HWE_PCIE_UC_OCT1MEMORYPARITYERR 0x0000002000000000ULL
++
++#define IBA7220_IBCS_LINKTRAININGSTATE_MASK 0x1F
++#define IBA7220_IBCS_LINKSTATE_SHIFT 5
++#define IBA7220_IBCS_LINKSPEED_SHIFT 8
++#define IBA7220_IBCS_LINKWIDTH_SHIFT 9
++
++#define IBA7220_IBCC_LINKINITCMD_MASK 0x7ULL
++#define IBA7220_IBCC_LINKCMD_SHIFT 19
++#define IBA7220_IBCC_MAXPKTLEN_SHIFT 21
++
++/* kr_ibcddrctrl bits */
++#define IBA7220_IBC_DLIDLMC_MASK	0xFFFFFFFFUL
++#define IBA7220_IBC_DLIDLMC_SHIFT	32
++#define IBA7220_IBC_HRTBT_MASK	3
++#define IBA7220_IBC_HRTBT_SHIFT	16
++#define IBA7220_IBC_HRTBT_ENB	0x10000UL
++#define IBA7220_IBC_LANE_REV_SUPPORTED (1<<8)
++#define IBA7220_IBC_LREV_MASK	1
++#define IBA7220_IBC_LREV_SHIFT	8
++#define IBA7220_IBC_RXPOL_MASK	1
++#define IBA7220_IBC_RXPOL_SHIFT	7
++#define IBA7220_IBC_WIDTH_SHIFT	5
++#define IBA7220_IBC_WIDTH_MASK	0x3
++#define IBA7220_IBC_WIDTH_1X_ONLY	(0<<IBA7220_IBC_WIDTH_SHIFT)
++#define IBA7220_IBC_WIDTH_4X_ONLY	(1<<IBA7220_IBC_WIDTH_SHIFT)
++#define IBA7220_IBC_WIDTH_AUTONEG	(2<<IBA7220_IBC_WIDTH_SHIFT)
++#define IBA7220_IBC_SPEED_AUTONEG	(1<<1)
++#define IBA7220_IBC_SPEED_SDR		(1<<2)
++#define IBA7220_IBC_SPEED_DDR		(1<<3)
++#define IBA7220_IBC_SPEED_AUTONEG_MASK  (0x7<<1)
++#define IBA7220_IBC_IBTA_1_2_MASK	(1)
++
++/* kr_ibcddrstatus */
++/* link latency shift is 0, don't bother defining */
++#define IBA7220_DDRSTAT_LINKLAT_MASK    0x3ffffff
++
++/* kr_extstatus bits */
++#define INFINIPATH_EXTS_FREQSEL 0x2
++#define INFINIPATH_EXTS_SERDESSEL 0x4
++#define INFINIPATH_EXTS_MEMBIST_ENDTEST     0x0000000000004000
++#define INFINIPATH_EXTS_MEMBIST_DISABLED    0x0000000000008000
++
++/* kr_xgxsconfig bits */
++#define INFINIPATH_XGXS_RESET          0x5ULL
++#define INFINIPATH_XGXS_FC_SAFE        (1ULL<<63)
++
++/* kr_rcvpktledcnt */
++#define IBA7220_LEDBLINK_ON_SHIFT 32 /* 4ns period on after packet */
++#define IBA7220_LEDBLINK_OFF_SHIFT 0 /* 4ns period off before next on */
++
++#define _IPATH_GPIO_SDA_NUM 1
++#define _IPATH_GPIO_SCL_NUM 0
++
++#define IPATH_GPIO_SDA (1ULL << \
++	(_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
++#define IPATH_GPIO_SCL (1ULL << \
++	(_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
++
++#define IBA7220_R_INTRAVAIL_SHIFT 17
++#define IBA7220_R_TAILUPD_SHIFT 35
++#define IBA7220_R_PORTCFG_SHIFT 36
++
++#define INFINIPATH_JINT_PACKETSHIFT 16
++#define INFINIPATH_JINT_DEFAULT_IDLE_TICKS  0
++#define INFINIPATH_JINT_DEFAULT_MAX_PACKETS 0
++
++#define IBA7220_HDRHEAD_PKTINT_SHIFT 32 /* interrupt cnt in upper 32 bits */
++
++/*
++ * the size bits give us 2^N, in KB units.  0 marks as invalid,
++ * and 7 is reserved.  We currently use only 2KB and 4KB
++ */
++#define IBA7220_TID_SZ_SHIFT 37 /* shift to 3bit size selector */
++#define IBA7220_TID_SZ_2K (1UL<<IBA7220_TID_SZ_SHIFT) /* 2KB */
++#define IBA7220_TID_SZ_4K (2UL<<IBA7220_TID_SZ_SHIFT) /* 4KB */
++#define IBA7220_TID_PA_SHIFT 11U /* TID addr in chip stored w/o low bits */
++
++#define IPATH_AUTONEG_TRIES 5 /* sequential retries to negotiate DDR */
++
++static char int_type[16] = "auto";
++module_param_string(interrupt_type, int_type, sizeof(int_type), 0444);
++MODULE_PARM_DESC(int_type, " interrupt_type=auto|force_msi|force_intx\n");
++
++/* packet rate matching delay; chip has support */
++static u8 rate_to_delay[2][2] = {
++	/* 1x, 4x */
++	{   8, 2 }, /* SDR */
++	{   4, 1 }  /* DDR */
++};
++
++/* 7220 specific hardware errors... */
++static const struct ipath_hwerror_msgs ipath_7220_hwerror_msgs[] = {
++	INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
++	INFINIPATH_HWE_MSG(PCIECPLTIMEOUT, "PCIe completion timeout"),
++	/*
++	 * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
++	 * parity or memory parity error failures, because most likely we
++	 * won't be able to talk to the core of the chip.  Nonetheless, we
++	 * might see them, if they are in parts of the PCIe core that aren't
++	 * essential.
++	 */
++	INFINIPATH_HWE_MSG(PCIE1PLLFAILED, "PCIePLL1"),
++	INFINIPATH_HWE_MSG(PCIE0PLLFAILED, "PCIePLL0"),
++	INFINIPATH_HWE_MSG(PCIEBUSPARITYXTLH, "PCIe XTLH core parity"),
++	INFINIPATH_HWE_MSG(PCIEBUSPARITYXADM, "PCIe ADM TX core parity"),
++	INFINIPATH_HWE_MSG(PCIEBUSPARITYRADM, "PCIe ADM RX core parity"),
++	INFINIPATH_HWE_MSG(RXDSYNCMEMPARITYERR, "Rx Dsync"),
++	INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"),
++	INFINIPATH_HWE_MSG(PCIECPLDATAQUEUEERR, "PCIe cpl header queue"),
++	INFINIPATH_HWE_MSG(PCIECPLHDRQUEUEERR, "PCIe cpl data queue"),
++	INFINIPATH_HWE_MSG(SDMAMEMREADERR, "Send DMA memory read"),
++	INFINIPATH_HWE_MSG(CLK_UC_PLLNOTLOCKED, "uC PLL clock not locked"),
++	INFINIPATH_HWE_MSG(PCIESERDESQ0PCLKNOTDETECT,
++		"PCIe serdes Q0 no clock"),
++	INFINIPATH_HWE_MSG(PCIESERDESQ1PCLKNOTDETECT,
++		"PCIe serdes Q1 no clock"),
++	INFINIPATH_HWE_MSG(PCIESERDESQ2PCLKNOTDETECT,
++		"PCIe serdes Q2 no clock"),
++	INFINIPATH_HWE_MSG(PCIESERDESQ3PCLKNOTDETECT,
++		"PCIe serdes Q3 no clock"),
++	INFINIPATH_HWE_MSG(DDSRXEQMEMORYPARITYERR,
++		"DDS RXEQ memory parity"),
++	INFINIPATH_HWE_MSG(IB_UC_MEMORYPARITYERR, "IB uC memory parity"),
++	INFINIPATH_HWE_MSG(PCIE_UC_OCT0MEMORYPARITYERR,
++		"PCIe uC oct0 memory parity"),
++	INFINIPATH_HWE_MSG(PCIE_UC_OCT1MEMORYPARITYERR,
++		"PCIe uC oct1 memory parity"),
++};
++
++static void autoneg_work(struct work_struct *);
++
++/*
++ * the offset is different for different configured port numbers, since
++ * port0 is fixed in size, but others can vary.   Make it a function to
++ * make the issue more obvious.
++*/
++static inline u32 port_egrtid_idx(struct ipath_devdata *dd, unsigned port)
++{
++	 return port ? dd->ipath_p0_rcvegrcnt +
++		 (port-1) * dd->ipath_rcvegrcnt : 0;
++}
++
++static void ipath_7220_txe_recover(struct ipath_devdata *dd)
++{
++	++ipath_stats.sps_txeparity;
++
++	dev_info(&dd->pcidev->dev,
++		"Recovering from TXE PIO parity error\n");
++	ipath_disarm_senderrbufs(dd, 1);
++}
++
++
++/**
++ * ipath_7220_handle_hwerrors - display hardware errors.
++ * @dd: the infinipath device
++ * @msg: the output buffer
++ * @msgl: the size of the output buffer
++ *
++ * Use same msg buffer as regular errors to avoid excessive stack
++ * use.  Most hardware errors are catastrophic, but for right now,
++ * we'll print them and continue.  We reuse the same message buffer as
++ * ipath_handle_errors() to avoid excessive stack usage.
++ */
++static void ipath_7220_handle_hwerrors(struct ipath_devdata *dd, char *msg,
++				       size_t msgl)
++{
++	ipath_err_t hwerrs;
++	u32 bits, ctrl;
++	int isfatal = 0;
++	char bitsmsg[64];
++	int log_idx;
++
++	hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
++	if (!hwerrs) {
++		/*
++		 * better than printing cofusing messages
++		 * This seems to be related to clearing the crc error, or
++		 * the pll error during init.
++		 */
++		ipath_cdbg(VERBOSE, "Called but no hardware errors set\n");
++		goto bail;
++	} else if (hwerrs == ~0ULL) {
++		ipath_dev_err(dd, "Read of hardware error status failed "
++			      "(all bits set); ignoring\n");
++		goto bail;
++	}
++	ipath_stats.sps_hwerrs++;
++
++	/*
++	 * Always clear the error status register, except MEMBISTFAIL,
++	 * regardless of whether we continue or stop using the chip.
++	 * We want that set so we know it failed, even across driver reload.
++	 * We'll still ignore it in the hwerrmask.  We do this partly for
++	 * diagnostics, but also for support.
++	 */
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
++			 hwerrs&~INFINIPATH_HWE_MEMBISTFAILED);
++
++	hwerrs &= dd->ipath_hwerrmask;
++
++	/* We log some errors to EEPROM, check if we have any of those. */
++	for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx)
++		if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log)
++			ipath_inc_eeprom_err(dd, log_idx, 1);
++	/*
++	 * Make sure we get this much out, unless told to be quiet,
++	 * or it's occurred within the last 5 seconds.
++	 */
++	if ((hwerrs & ~(dd->ipath_lasthwerror |
++			((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
++			  INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
++			 << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT))) ||
++	    (ipath_debug & __IPATH_VERBDBG))
++		dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
++			 "(cleared)\n", (unsigned long long) hwerrs);
++	dd->ipath_lasthwerror |= hwerrs;
++
++	if (hwerrs & ~dd->ipath_hwe_bitsextant)
++		ipath_dev_err(dd, "hwerror interrupt with unknown errors "
++			      "%llx set\n", (unsigned long long)
++			      (hwerrs & ~dd->ipath_hwe_bitsextant));
++
++	if (hwerrs & INFINIPATH_HWE_IB_UC_MEMORYPARITYERR)
++		ipath_sd7220_clr_ibpar(dd);
++
++	ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
++	if ((ctrl & INFINIPATH_C_FREEZEMODE) && !ipath_diag_inuse) {
++		/*
++		 * Parity errors in send memory are recoverable,
++		 * just cancel the send (if indicated in * sendbuffererror),
++		 * count the occurrence, unfreeze (if no other handled
++		 * hardware error bits are set), and continue.
++		 */
++		if (hwerrs & ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
++			       INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
++			      << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
++			ipath_7220_txe_recover(dd);
++			hwerrs &= ~((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
++				     INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
++				    << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT);
++			if (!hwerrs) {
++				/* else leave in freeze mode */
++				ipath_write_kreg(dd,
++						 dd->ipath_kregs->kr_control,
++						 dd->ipath_control);
++				goto bail;
++			}
++		}
++		if (hwerrs) {
++			/*
++			 * If any set that we aren't ignoring only make the
++			 * complaint once, in case it's stuck or recurring,
++			 * and we get here multiple times
++			 * Force link down, so switch knows, and
++			 * LEDs are turned off.
++			 */
++			if (dd->ipath_flags & IPATH_INITTED) {
++				ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);
++				ipath_setup_7220_setextled(dd,
++					INFINIPATH_IBCS_L_STATE_DOWN,
++					INFINIPATH_IBCS_LT_STATE_DISABLED);
++				ipath_dev_err(dd, "Fatal Hardware Error "
++					      "(freeze mode), no longer"
++					      " usable, SN %.16s\n",
++						  dd->ipath_serial);
++				isfatal = 1;
++			}
++			/*
++			 * Mark as having had an error for driver, and also
++			 * for /sys and status word mapped to user programs.
++			 * This marks unit as not usable, until reset.
++			 */
++			*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
++			*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
++			dd->ipath_flags &= ~IPATH_INITTED;
++		} else {
++			ipath_dbg("Clearing freezemode on ignored hardware "
++				  "error\n");
++			ipath_clear_freeze(dd);
++		}
++	}
++
++	*msg = '\0';
++
++	if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {
++		strlcat(msg, "[Memory BIST test failed, "
++			"InfiniPath hardware unusable]", msgl);
++		/* ignore from now on, so disable until driver reloaded */
++		*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
++		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++				 dd->ipath_hwerrmask);
++	}
++
++	ipath_format_hwerrors(hwerrs,
++			      ipath_7220_hwerror_msgs,
++			      ARRAY_SIZE(ipath_7220_hwerror_msgs),
++			      msg, msgl);
++
++	if (hwerrs & (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK
++		      << INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT)) {
++		bits = (u32) ((hwerrs >>
++			       INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) &
++			      INFINIPATH_HWE_PCIEMEMPARITYERR_MASK);
++		snprintf(bitsmsg, sizeof bitsmsg,
++			 "[PCIe Mem Parity Errs %x] ", bits);
++		strlcat(msg, bitsmsg, msgl);
++	}
++
++#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP |	\
++			 INFINIPATH_HWE_COREPLL_RFSLIP)
++
++	if (hwerrs & _IPATH_PLL_FAIL) {
++		snprintf(bitsmsg, sizeof bitsmsg,
++			 "[PLL failed (%llx), InfiniPath hardware unusable]",
++			 (unsigned long long) hwerrs & _IPATH_PLL_FAIL);
++		strlcat(msg, bitsmsg, msgl);
++		/* ignore from now on, so disable until driver reloaded */
++		dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++				 dd->ipath_hwerrmask);
++	}
++
++	if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
++		/*
++		 * If it occurs, it is left masked since the eternal
++		 * interface is unused.
++		 */
++		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++				 dd->ipath_hwerrmask);
++	}
++
++	ipath_dev_err(dd, "%s hardware error\n", msg);
++	/*
++	 * For /sys status file. if no trailing } is copied, we'll
++	 * know it was truncated.
++	 */
++	if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg)
++		snprintf(dd->ipath_freezemsg, dd->ipath_freezelen,
++			 "{%s}", msg);
++bail:;
++}
++
++/**
++ * ipath_7220_boardname - fill in the board name
++ * @dd: the infinipath device
++ * @name: the output buffer
++ * @namelen: the size of the output buffer
++ *
++ * info is based on the board revision register
++ */
++static int ipath_7220_boardname(struct ipath_devdata *dd, char *name,
++	size_t namelen)
++{
++	char *n = NULL;
++	u8 boardrev = dd->ipath_boardrev;
++	int ret;
++
++	if (boardrev == 15) {
++		/*
++		 * Emulator sometimes comes up all-ones, rather than zero.
++		 */
++		boardrev = 0;
++		dd->ipath_boardrev = boardrev;
++	}
++	switch (boardrev) {
++	case 0:
++		n = "InfiniPath_7220_Emulation";
++		break;
++	case 1:
++		n = "InfiniPath_QLE7240";
++		break;
++	case 2:
++		n = "InfiniPath_QLE7280";
++		break;
++	case 3:
++		n = "InfiniPath_QLE7242";
++		break;
++	case 4:
++		n = "InfiniPath_QEM7240";
++		break;
++	case 5:
++		n = "InfiniPath_QMI7240";
++		break;
++	case 6:
++		n = "InfiniPath_QMI7264";
++		break;
++	case 7:
++		n = "InfiniPath_QMH7240";
++		break;
++	case 8:
++		n = "InfiniPath_QME7240";
++		break;
++	case 9:
++		n = "InfiniPath_QLE7250";
++		break;
++	case 10:
++		n = "InfiniPath_QLE7290";
++		break;
++	case 11:
++		n = "InfiniPath_QEM7250";
++		break;
++	case 12:
++		n = "InfiniPath_QLE-Bringup";
++		break;
++	default:
++		ipath_dev_err(dd,
++			      "Don't yet know about board with ID %u\n",
++			      boardrev);
++		snprintf(name, namelen, "Unknown_InfiniPath_PCIe_%u",
++			 boardrev);
++		break;
++	}
++	if (n)
++		snprintf(name, namelen, "%s", n);
++
++	if (dd->ipath_majrev != 5 || !dd->ipath_minrev ||
++		dd->ipath_minrev > 2) {
++		ipath_dev_err(dd, "Unsupported InfiniPath hardware "
++			      "revision %u.%u!\n",
++			      dd->ipath_majrev, dd->ipath_minrev);
++		ret = 1;
++	} else if (dd->ipath_minrev == 1) {
++		/* Rev1 chips are prototype. Complain, but allow use */
++		ipath_dev_err(dd, "Unsupported hardware "
++			      "revision %u.%u, Contact support at qlogic.com\n",
++			      dd->ipath_majrev, dd->ipath_minrev);
++		ret = 0;
++	} else
++		ret = 0;
++
++	/*
++	 * Set here not in ipath_init_*_funcs because we have to do
++	 * it after we can read chip registers.
++	 */
++	dd->ipath_ureg_align = 0x10000;  /* 64KB alignment */
++
++	return ret;
++}
++
++/**
++ * ipath_7220_init_hwerrors - enable hardware errors
++ * @dd: the infinipath device
++ *
++ * now that we have finished initializing everything that might reasonably
++ * cause a hardware error, and cleared those errors bits as they occur,
++ * we can enable hardware errors in the mask (potentially enabling
++ * freeze mode), and enable hardware errors as errors (along with
++ * everything else) in errormask
++ */
++static void ipath_7220_init_hwerrors(struct ipath_devdata *dd)
++{
++	ipath_err_t val;
++	u64 extsval;
++
++	extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
++
++	if (!(extsval & (INFINIPATH_EXTS_MEMBIST_ENDTEST |
++			INFINIPATH_EXTS_MEMBIST_DISABLED)))
++		ipath_dev_err(dd, "MemBIST did not complete!\n");
++	if (extsval & INFINIPATH_EXTS_MEMBIST_DISABLED)
++		dev_info(&dd->pcidev->dev, "MemBIST is disabled.\n");
++
++	val = ~0ULL;	/* barring bugs, all hwerrors become interrupts, */
++
++	if (!dd->ipath_boardrev)	/* no PLL for Emulator */
++		val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
++
++	if (dd->ipath_minrev == 1)
++		val &= ~(1ULL << 42); /* TXE LaunchFIFO Parity rev1 issue */
++
++	val &= ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR;
++	dd->ipath_hwerrmask = val;
++
++	/*
++	 * special trigger "error" is for debugging purposes. It
++	 * works around a processor/chipset problem.  The error
++	 * interrupt allows us to count occurrences, but we don't
++	 * want to pay the overhead for normal use.  Emulation only
++	 */
++	if (!dd->ipath_boardrev)
++		dd->ipath_maskederrs = INFINIPATH_E_SENDSPECIALTRIGGER;
++}
++
++/*
++ * All detailed interaction with the SerDes has been moved to ipath_sd7220.c
++ *
++ * The portion of IBA7220-specific bringup_serdes() that actually deals with
++ * registers and memory within the SerDes itself is ipath_sd7220_init().
++ */
++
++/**
++ * ipath_7220_bringup_serdes - bring up the serdes
++ * @dd: the infinipath device
++ */
++static int ipath_7220_bringup_serdes(struct ipath_devdata *dd)
++{
++	int ret = 0;
++	u64 val, prev_val, guid;
++	int was_reset;		/* Note whether uC was reset */
++
++	ipath_dbg("Trying to bringup serdes\n");
++
++	if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) &
++	    INFINIPATH_HWE_SERDESPLLFAILED) {
++		ipath_dbg("At start, serdes PLL failed bit set "
++			  "in hwerrstatus, clearing and continuing\n");
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
++				 INFINIPATH_HWE_SERDESPLLFAILED);
++	}
++
++	if (!dd->ipath_ibcddrctrl) {
++		/* not on re-init after reset */
++		dd->ipath_ibcddrctrl =
++			ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcddrctrl);
++
++		if (dd->ipath_link_speed_enabled ==
++			(IPATH_IB_SDR | IPATH_IB_DDR))
++			dd->ipath_ibcddrctrl |=
++				IBA7220_IBC_SPEED_AUTONEG_MASK |
++				IBA7220_IBC_IBTA_1_2_MASK;
++		else
++			dd->ipath_ibcddrctrl |=
++				dd->ipath_link_speed_enabled == IPATH_IB_DDR
++				?  IBA7220_IBC_SPEED_DDR :
++				IBA7220_IBC_SPEED_SDR;
++		if ((dd->ipath_link_width_enabled & (IB_WIDTH_1X |
++			IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X))
++			dd->ipath_ibcddrctrl |= IBA7220_IBC_WIDTH_AUTONEG;
++		else
++			dd->ipath_ibcddrctrl |=
++				dd->ipath_link_width_enabled == IB_WIDTH_4X
++				? IBA7220_IBC_WIDTH_4X_ONLY :
++				IBA7220_IBC_WIDTH_1X_ONLY;
++
++		/* always enable these on driver reload, not sticky */
++		dd->ipath_ibcddrctrl |=
++			IBA7220_IBC_RXPOL_MASK << IBA7220_IBC_RXPOL_SHIFT;
++		dd->ipath_ibcddrctrl |=
++			IBA7220_IBC_HRTBT_MASK << IBA7220_IBC_HRTBT_SHIFT;
++		/*
++		 * automatic lane reversal detection for receive
++		 * doesn't work correctly in rev 1, so disable it
++		 * on that rev, otherwise enable (disabling not
++		 * sticky across reload for >rev1)
++		 */
++		if (dd->ipath_minrev == 1)
++			dd->ipath_ibcddrctrl &=
++			~IBA7220_IBC_LANE_REV_SUPPORTED;
++		else
++			dd->ipath_ibcddrctrl |=
++				IBA7220_IBC_LANE_REV_SUPPORTED;
++	}
++
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcddrctrl,
++			dd->ipath_ibcddrctrl);
++
++	ipath_write_kreg(dd, IPATH_KREG_OFFSET(IBNCModeCtrl), 0Ull);
++
++	/* IBA7220 has SERDES MPU reset in D0 of what _was_ IBPLLCfg */
++	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibserdesctrl);
++	/* remember if uC was in Reset or not, for dactrim */
++	was_reset = (val & 1);
++	ipath_cdbg(VERBOSE, "IBReset %s xgxsconfig %llx\n",
++		   was_reset ? "Asserted" : "Negated", (unsigned long long)
++		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
++
++	if (dd->ipath_boardrev) {
++		/*
++		 * Hardware is not emulator, and may have been reset. Init it.
++		 * Below will release reset, but needs to know if chip was
++		 * originally in reset, to only trim DACs on first time
++		 * after chip reset or powercycle (not driver reload)
++		 */
++		ret = ipath_sd7220_init(dd, was_reset);
++	}
++
++	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
++	prev_val = val;
++	val |= INFINIPATH_XGXS_FC_SAFE;
++	if (val != prev_val) {
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++	}
++	if (val & INFINIPATH_XGXS_RESET)
++		val &= ~INFINIPATH_XGXS_RESET;
++	if (val != prev_val)
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++
++	ipath_cdbg(VERBOSE, "done: xgxs=%llx from %llx\n",
++		   (unsigned long long)
++		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig),
++		   prev_val);
++
++	guid = be64_to_cpu(dd->ipath_guid);
++
++	if (!guid) {
++		/* have to have something, so use likely unique tsc */
++		guid = get_cycles();
++		ipath_dbg("No GUID for heartbeat, faking %llx\n",
++			(unsigned long long)guid);
++	} else
++		ipath_cdbg(VERBOSE, "Wrote %llX to HRTBT_GUID\n", guid);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_hrtbt_guid, guid);
++	return ret;
++}
++
++static void ipath_7220_config_jint(struct ipath_devdata *dd,
++				   u16 idle_ticks, u16 max_packets)
++{
++
++	/*
++	 * We can request a receive interrupt for 1 or more packets
++	 * from current offset.
++	 */
++	if (idle_ticks == 0 || max_packets == 0)
++		/* interrupt after one packet if no mitigation */
++		dd->ipath_rhdrhead_intr_off =
++			1ULL << IBA7220_HDRHEAD_PKTINT_SHIFT;
++	else
++		/* Turn off RcvHdrHead interrupts if using mitigation */
++		dd->ipath_rhdrhead_intr_off = 0ULL;
++
++	/* refresh kernel RcvHdrHead registers... */
++	ipath_write_ureg(dd, ur_rcvhdrhead,
++			 dd->ipath_rhdrhead_intr_off |
++			 dd->ipath_pd[0]->port_head, 0);
++
++	dd->ipath_jint_max_packets = max_packets;
++	dd->ipath_jint_idle_ticks = idle_ticks;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_jintreload,
++			 ((u64) max_packets << INFINIPATH_JINT_PACKETSHIFT) |
++			 idle_ticks);
++}
++
++/**
++ * ipath_7220_quiet_serdes - set serdes to txidle
++ * @dd: the infinipath device
++ * Called when driver is being unloaded
++ */
++static void ipath_7220_quiet_serdes(struct ipath_devdata *dd)
++{
++	u64 val;
++	dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG;
++	wake_up(&dd->ipath_autoneg_wait);
++	cancel_delayed_work(&dd->ipath_autoneg_work);
++	flush_scheduled_work();
++	ipath_shutdown_relock_poll(dd);
++	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
++	val |= INFINIPATH_XGXS_RESET;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++}
++
++static int ipath_7220_intconfig(struct ipath_devdata *dd)
++{
++	ipath_7220_config_jint(dd, dd->ipath_jint_idle_ticks,
++			       dd->ipath_jint_max_packets);
++	return 0;
++}
++
++/**
++ * ipath_setup_7220_setextled - set the state of the two external LEDs
++ * @dd: the infinipath device
++ * @lst: the L state
++ * @ltst: the LT state
++ *
++ * These LEDs indicate the physical and logical state of IB link.
++ * For this chip (at least with recommended board pinouts), LED1
++ * is Yellow (logical state) and LED2 is Green (physical state),
++ *
++ * Note:  We try to match the Mellanox HCA LED behavior as best
++ * we can.  Green indicates physical link state is OK (something is
++ * plugged in, and we can train).
++ * Amber indicates the link is logically up (ACTIVE).
++ * Mellanox further blinks the amber LED to indicate data packet
++ * activity, but we have no hardware support for that, so it would
++ * require waking up every 10-20 msecs and checking the counters
++ * on the chip, and then turning the LED off if appropriate.  That's
++ * visible overhead, so not something we will do.
++ *
++ */
++static void ipath_setup_7220_setextled(struct ipath_devdata *dd, u64 lst,
++				       u64 ltst)
++{
++	u64 extctl, ledblink = 0;
++	unsigned long flags = 0;
++
++	/* the diags use the LED to indicate diag info, so we leave
++	 * the external LED alone when the diags are running */
++	if (ipath_diag_inuse)
++		return;
++
++	/* Allow override of LED display for, e.g. Locating system in rack */
++	if (dd->ipath_led_override) {
++		ltst = (dd->ipath_led_override & IPATH_LED_PHYS)
++			? INFINIPATH_IBCS_LT_STATE_LINKUP
++			: INFINIPATH_IBCS_LT_STATE_DISABLED;
++		lst = (dd->ipath_led_override & IPATH_LED_LOG)
++			? INFINIPATH_IBCS_L_STATE_ACTIVE
++			: INFINIPATH_IBCS_L_STATE_DOWN;
++	}
++
++	spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
++	extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
++				       INFINIPATH_EXTC_LED2PRIPORT_ON);
++	if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP) {
++		extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
++		/*
++		 * counts are in chip clock (4ns) periods.
++		 * This is 1/16 sec (66.6ms) on,
++		 * 3/16 sec (187.5 ms) off, with packets rcvd
++		 */
++		ledblink = ((66600*1000UL/4) << IBA7220_LEDBLINK_ON_SHIFT)
++			| ((187500*1000UL/4) << IBA7220_LEDBLINK_OFF_SHIFT);
++	}
++	if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
++		extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
++	dd->ipath_extctrl = extctl;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
++	spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
++
++	if (ledblink) /* blink the LED on packet receive */
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvpktledcnt,
++			ledblink);
++}
++
++/*
++ * Similar to pci_intx(pdev, 1), except that we make sure
++ * msi is off...
++ */
++static void ipath_enable_intx(struct pci_dev *pdev)
++{
++	u16 cw, new;
++	int pos;
++
++	/* first, turn on INTx */
++	pci_read_config_word(pdev, PCI_COMMAND, &cw);
++	new = cw & ~PCI_COMMAND_INTX_DISABLE;
++	if (new != cw)
++		pci_write_config_word(pdev, PCI_COMMAND, new);
++
++	/* then turn off MSI */
++	pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
++	if (pos) {
++		pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &cw);
++		new = cw & ~PCI_MSI_FLAGS_ENABLE;
++		if (new != cw)
++			pci_write_config_word(pdev, pos + PCI_MSI_FLAGS, new);
++	}
++}
++
++static int ipath_msi_enabled(struct pci_dev *pdev)
++{
++	int pos, ret = 0;
++
++	pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
++	if (pos) {
++		u16 cw;
++
++		pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &cw);
++		ret = !!(cw & PCI_MSI_FLAGS_ENABLE);
++	}
++	return ret;
++}
++
++/*
++ * disable msi interrupt if enabled, and clear the flag.
++ * flag is used primarily for the fallback to INTx, but
++ * is also used in reinit after reset as a flag.
++ */
++static void ipath_7220_nomsi(struct ipath_devdata *dd)
++{
++	dd->ipath_msi_lo = 0;
++
++	if (ipath_msi_enabled(dd->pcidev)) {
++		/*
++		 * free, but don't zero; later kernels require
++		 * it be freed before disable_msi, so the intx
++		 * setup has to request it again.
++		 */
++		 if (dd->ipath_irq)
++			free_irq(dd->ipath_irq, dd);
++		pci_disable_msi(dd->pcidev);
++	}
++}
++
++/*
++ * ipath_setup_7220_cleanup - clean up any per-chip chip-specific stuff
++ * @dd: the infinipath device
++ *
++ * Nothing but msi interrupt cleanup for now.
++ *
++ * This is called during driver unload.
++ */
++static void ipath_setup_7220_cleanup(struct ipath_devdata *dd)
++{
++	ipath_7220_nomsi(dd);
++}
++
++
++static void ipath_7220_pcie_params(struct ipath_devdata *dd, u32 boardrev)
++{
++	u16 linkstat, minwidth, speed;
++	int pos;
++
++	pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
++	if (!pos) {
++		ipath_dev_err(dd, "Can't find PCI Express capability!\n");
++		goto bail;
++	}
++
++	pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,
++			     &linkstat);
++	/*
++	 * speed is bits 0-4, linkwidth is bits 4-8
++	 * no defines for them in headers
++	 */
++	speed = linkstat & 0xf;
++	linkstat >>= 4;
++	linkstat &= 0x1f;
++	dd->ipath_lbus_width = linkstat;
++	switch (boardrev) {
++	case 0:
++	case 2:
++	case 10:
++	case 12:
++		minwidth = 16; /* x16 capable boards */
++		break;
++	default:
++		minwidth = 8; /* x8 capable boards */
++		break;
++	}
++
++	switch (speed) {
++	case 1:
++		dd->ipath_lbus_speed = 2500; /* Gen1, 2.5GHz */
++		break;
++	case 2:
++		dd->ipath_lbus_speed = 5000; /* Gen1, 5GHz */
++		break;
++	default: /* not defined, assume gen1 */
++		dd->ipath_lbus_speed = 2500;
++		break;
++	}
++
++	if (linkstat < minwidth)
++		ipath_dev_err(dd,
++			"PCIe width %u (x%u HCA), performance "
++			"reduced\n", linkstat, minwidth);
++	else
++		ipath_cdbg(VERBOSE, "PCIe speed %u width %u (x%u HCA)\n",
++			dd->ipath_lbus_speed, linkstat, minwidth);
++
++	if (speed != 1)
++		ipath_dev_err(dd,
++			"PCIe linkspeed %u is incorrect; "
++			"should be 1 (2500)!\n", speed);
++
++bail:
++	/* fill in string, even on errors */
++	snprintf(dd->ipath_lbus_info, sizeof(dd->ipath_lbus_info),
++		"PCIe,%uMHz,x%u\n",
++		dd->ipath_lbus_speed,
++		dd->ipath_lbus_width);
++	return;
++}
++
++
++/**
++ * ipath_setup_7220_config - setup PCIe config related stuff
++ * @dd: the infinipath device
++ * @pdev: the PCI device
++ *
++ * The pci_enable_msi() call will fail on systems with MSI quirks
++ * such as those with AMD8131, even if the device of interest is not
++ * attached to that device, (in the 2.6.13 - 2.6.15 kernels, at least, fixed
++ * late in 2.6.16).
++ * All that can be done is to edit the kernel source to remove the quirk
++ * check until that is fixed.
++ * We do not need to call enable_msi() for our HyperTransport chip,
++ * even though it uses MSI, and we want to avoid the quirk warning, so
++ * So we call enable_msi only for PCIe.  If we do end up needing
++ * pci_enable_msi at some point in the future for HT, we'll move the
++ * call back into the main init_one code.
++ * We save the msi lo and hi values, so we can restore them after
++ * chip reset (the kernel PCI infrastructure doesn't yet handle that
++ * correctly).
++ */
++static int ipath_setup_7220_config(struct ipath_devdata *dd,
++				   struct pci_dev *pdev)
++{
++	int pos, ret = -1;
++	u32 boardrev;
++
++	dd->ipath_msi_lo = 0;	/* used as a flag during reset processing */
++
++	pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
++	if (!strcmp(int_type, "force_msi") || !strcmp(int_type, "auto"))
++		ret = pci_enable_msi(pdev);
++	if (ret) {
++		if (!strcmp(int_type, "force_msi")) {
++			ipath_dev_err(dd, "pci_enable_msi failed: %d, "
++				      "force_msi is on, so not continuing.\n",
++				      ret);
++			return ret;
++		}
++
++		ipath_enable_intx(pdev);
++		if (!strcmp(int_type, "auto"))
++			ipath_dev_err(dd, "pci_enable_msi failed: %d, "
++				      "falling back to INTx\n", ret);
++	} else if (pos) {
++		u16 control;
++		pci_read_config_dword(pdev, pos + PCI_MSI_ADDRESS_LO,
++				      &dd->ipath_msi_lo);
++		pci_read_config_dword(pdev, pos + PCI_MSI_ADDRESS_HI,
++				      &dd->ipath_msi_hi);
++		pci_read_config_word(pdev, pos + PCI_MSI_FLAGS,
++				     &control);
++		/* now save the data (vector) info */
++		pci_read_config_word(pdev,
++				     pos + ((control & PCI_MSI_FLAGS_64BIT)
++					    ? PCI_MSI_DATA_64 :
++					    PCI_MSI_DATA_32),
++				     &dd->ipath_msi_data);
++	} else
++		ipath_dev_err(dd, "Can't find MSI capability, "
++			      "can't save MSI settings for reset\n");
++
++	dd->ipath_irq = pdev->irq;
++
++	/*
++	 * We save the cachelinesize also, although it doesn't
++	 * really matter.
++	 */
++	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,
++			     &dd->ipath_pci_cacheline);
++
++	/*
++	 * this function called early, ipath_boardrev not set yet.  Can't
++	 * use ipath_read_kreg64() yet, too early in init, so use readq()
++	 */
++	boardrev = (readq(&dd->ipath_kregbase[dd->ipath_kregs->kr_revision])
++		 >> INFINIPATH_R_BOARDID_SHIFT) & INFINIPATH_R_BOARDID_MASK;
++
++	ipath_7220_pcie_params(dd, boardrev);
++
++	dd->ipath_flags |= IPATH_NODMA_RTAIL | IPATH_HAS_SEND_DMA |
++		IPATH_HAS_PBC_CNT | IPATH_HAS_THRESH_UPDATE;
++	dd->ipath_pioupd_thresh = 4U; /* set default update threshold */
++	return 0;
++}
++
++static void ipath_init_7220_variables(struct ipath_devdata *dd)
++{
++	/*
++	 * setup the register offsets, since they are different for each
++	 * chip
++	 */
++	dd->ipath_kregs = &ipath_7220_kregs;
++	dd->ipath_cregs = &ipath_7220_cregs;
++
++	/*
++	 * bits for selecting i2c direction and values,
++	 * used for I2C serial flash
++	 */
++	dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
++	dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
++	dd->ipath_gpio_sda = IPATH_GPIO_SDA;
++	dd->ipath_gpio_scl = IPATH_GPIO_SCL;
++
++	/*
++	 * Fill in data for field-values that change in IBA7220.
++	 * We dynamically specify only the mask for LINKTRAININGSTATE
++	 * and only the shift for LINKSTATE, as they are the only ones
++	 * that change.  Also precalculate the 3 link states of interest
++	 * and the combined mask.
++	 */
++	dd->ibcs_ls_shift = IBA7220_IBCS_LINKSTATE_SHIFT;
++	dd->ibcs_lts_mask = IBA7220_IBCS_LINKTRAININGSTATE_MASK;
++	dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
++		dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
++	dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++		(INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
++	dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++		(INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
++	dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++		(INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
++
++	/*
++	 * Fill in data for ibcc field-values that change in IBA7220.
++	 * We dynamically specify only the mask for LINKINITCMD
++	 * and only the shift for LINKCMD and MAXPKTLEN, as they are
++	 * the only ones that change.
++	 */
++	dd->ibcc_lic_mask = IBA7220_IBCC_LINKINITCMD_MASK;
++	dd->ibcc_lc_shift = IBA7220_IBCC_LINKCMD_SHIFT;
++	dd->ibcc_mpl_shift = IBA7220_IBCC_MAXPKTLEN_SHIFT;
++
++	/* Fill in shifts for RcvCtrl. */
++	dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
++	dd->ipath_r_intravail_shift = IBA7220_R_INTRAVAIL_SHIFT;
++	dd->ipath_r_tailupd_shift = IBA7220_R_TAILUPD_SHIFT;
++	dd->ipath_r_portcfg_shift = IBA7220_R_PORTCFG_SHIFT;
++
++	/* variables for sanity checking interrupt and errors */
++	dd->ipath_hwe_bitsextant =
++		(INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
++		 INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |
++		(INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
++		 INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) |
++		(INFINIPATH_HWE_PCIEMEMPARITYERR_MASK <<
++		 INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) |
++		INFINIPATH_HWE_PCIE1PLLFAILED |
++		INFINIPATH_HWE_PCIE0PLLFAILED |
++		INFINIPATH_HWE_PCIEPOISONEDTLP |
++		INFINIPATH_HWE_PCIECPLTIMEOUT |
++		INFINIPATH_HWE_PCIEBUSPARITYXTLH |
++		INFINIPATH_HWE_PCIEBUSPARITYXADM |
++		INFINIPATH_HWE_PCIEBUSPARITYRADM |
++		INFINIPATH_HWE_MEMBISTFAILED |
++		INFINIPATH_HWE_COREPLL_FBSLIP |
++		INFINIPATH_HWE_COREPLL_RFSLIP |
++		INFINIPATH_HWE_SERDESPLLFAILED |
++		INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
++		INFINIPATH_HWE_IBCBUSFRSPCPARITYERR |
++		INFINIPATH_HWE_PCIECPLDATAQUEUEERR |
++		INFINIPATH_HWE_PCIECPLHDRQUEUEERR |
++		INFINIPATH_HWE_SDMAMEMREADERR |
++		INFINIPATH_HWE_CLK_UC_PLLNOTLOCKED |
++		INFINIPATH_HWE_PCIESERDESQ0PCLKNOTDETECT |
++		INFINIPATH_HWE_PCIESERDESQ1PCLKNOTDETECT |
++		INFINIPATH_HWE_PCIESERDESQ2PCLKNOTDETECT |
++		INFINIPATH_HWE_PCIESERDESQ3PCLKNOTDETECT |
++		INFINIPATH_HWE_DDSRXEQMEMORYPARITYERR |
++		INFINIPATH_HWE_IB_UC_MEMORYPARITYERR |
++		INFINIPATH_HWE_PCIE_UC_OCT0MEMORYPARITYERR |
++		INFINIPATH_HWE_PCIE_UC_OCT1MEMORYPARITYERR;
++	dd->ipath_i_bitsextant =
++		INFINIPATH_I_SDMAINT | INFINIPATH_I_SDMADISABLED |
++		(INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
++		(INFINIPATH_I_RCVAVAIL_MASK <<
++		 INFINIPATH_I_RCVAVAIL_SHIFT) |
++		INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
++		INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO |
++		INFINIPATH_I_JINT | INFINIPATH_I_SERDESTRIMDONE;
++	dd->ipath_e_bitsextant =
++		INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
++		INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
++		INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
++		INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR |
++		INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |
++		INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |
++		INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
++		INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |
++		INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |
++		INFINIPATH_E_SENDSPECIALTRIGGER |
++		INFINIPATH_E_SDMADISABLED | INFINIPATH_E_SMINPKTLEN |
++		INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SUNDERRUN |
++		INFINIPATH_E_SPKTLEN | INFINIPATH_E_SDROPPEDSMPPKT |
++		INFINIPATH_E_SDROPPEDDATAPKT |
++		INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |
++		INFINIPATH_E_SUNSUPVL | INFINIPATH_E_SENDBUFMISUSE |
++		INFINIPATH_E_SDMAGENMISMATCH | INFINIPATH_E_SDMAOUTOFBOUND |
++		INFINIPATH_E_SDMATAILOUTOFBOUND | INFINIPATH_E_SDMABASE |
++		INFINIPATH_E_SDMA1STDESC | INFINIPATH_E_SDMARPYTAG |
++		INFINIPATH_E_SDMADWEN | INFINIPATH_E_SDMAMISSINGDW |
++		INFINIPATH_E_SDMAUNEXPDATA |
++		INFINIPATH_E_IBSTATUSCHANGED | INFINIPATH_E_INVALIDADDR |
++		INFINIPATH_E_RESET | INFINIPATH_E_HARDWARE |
++		INFINIPATH_E_SDMADESCADDRMISALIGN |
++		INFINIPATH_E_INVALIDEEPCMD;
++
++	dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
++	dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
++	dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
++	dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
++	dd->ipath_flags |= IPATH_INTREG_64 | IPATH_HAS_MULT_IB_SPEED
++		| IPATH_HAS_LINK_LATENCY;
++
++	/*
++	 * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
++	 * 2 is Some Misc, 3 is reserved for future.
++	 */
++	dd->ipath_eep_st_masks[0].hwerrs_to_log =
++		INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
++		INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT;
++
++	dd->ipath_eep_st_masks[1].hwerrs_to_log =
++		INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
++		INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
++
++	dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
++
++	ipath_linkrecovery = 0;
++
++	init_waitqueue_head(&dd->ipath_autoneg_wait);
++	INIT_DELAYED_WORK(&dd->ipath_autoneg_work,  autoneg_work);
++
++	dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
++	dd->ipath_link_speed_supported = IPATH_IB_SDR | IPATH_IB_DDR;
++
++	dd->ipath_link_width_enabled = dd->ipath_link_width_supported;
++	dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
++	/*
++	 * set the initial values to reasonable default, will be set
++	 * for real when link is up.
++	 */
++	dd->ipath_link_width_active = IB_WIDTH_4X;
++	dd->ipath_link_speed_active = IPATH_IB_SDR;
++	dd->delay_mult = rate_to_delay[0][1];
++}
++
++
++/*
++ * Setup the MSI stuff again after a reset.  I'd like to just call
++ * pci_enable_msi() and request_irq() again, but when I do that,
++ * the MSI enable bit doesn't get set in the command word, and
++ * we switch to to a different interrupt vector, which is confusing,
++ * so I instead just do it all inline.  Perhaps somehow can tie this
++ * into the PCIe hotplug support at some point
++ * Note, because I'm doing it all here, I don't call pci_disable_msi()
++ * or free_irq() at the start of ipath_setup_7220_reset().
++ */
++static int ipath_reinit_msi(struct ipath_devdata *dd)
++{
++	int ret = 0;
++
++	int pos;
++	u16 control;
++	if (!dd->ipath_msi_lo) /* Using intX, or init problem */
++		goto bail;
++
++	pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI);
++	if (!pos) {
++		ipath_dev_err(dd, "Can't find MSI capability, "
++			      "can't restore MSI settings\n");
++		goto bail;
++	}
++	ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
++		   dd->ipath_msi_lo, pos + PCI_MSI_ADDRESS_LO);
++	pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,
++			       dd->ipath_msi_lo);
++	ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
++		   dd->ipath_msi_hi, pos + PCI_MSI_ADDRESS_HI);
++	pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,
++			       dd->ipath_msi_hi);
++	pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS, &control);
++	if (!(control & PCI_MSI_FLAGS_ENABLE)) {
++		ipath_cdbg(VERBOSE, "MSI control at off %x was %x, "
++			   "setting MSI enable (%x)\n", pos + PCI_MSI_FLAGS,
++			   control, control | PCI_MSI_FLAGS_ENABLE);
++		control |= PCI_MSI_FLAGS_ENABLE;
++		pci_write_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,
++				      control);
++	}
++	/* now rewrite the data (vector) info */
++	pci_write_config_word(dd->pcidev, pos +
++			      ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),
++			      dd->ipath_msi_data);
++	ret = 1;
++
++bail:
++	if (!ret) {
++		ipath_dbg("Using INTx, MSI disabled or not configured\n");
++		ipath_enable_intx(dd->pcidev);
++		ret = 1;
++	}
++	/*
++	 * We restore the cachelinesize also, although it doesn't really
++	 * matter.
++	 */
++	pci_write_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,
++			      dd->ipath_pci_cacheline);
++	/* and now set the pci master bit again */
++	pci_set_master(dd->pcidev);
++
++	return ret;
++}
++
++/*
++ * This routine sleeps, so it can only be called from user context, not
++ * from interrupt context.  If we need interrupt context, we can split
++ * it into two routines.
++ */
++static int ipath_setup_7220_reset(struct ipath_devdata *dd)
++{
++	u64 val;
++	int i;
++	int ret;
++	u16 cmdval;
++
++	pci_read_config_word(dd->pcidev, PCI_COMMAND, &cmdval);
++
++	/* Use dev_err so it shows up in logs, etc. */
++	ipath_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->ipath_unit);
++
++	/* keep chip from being accessed in a few places */
++	dd->ipath_flags &= ~(IPATH_INITTED | IPATH_PRESENT);
++	val = dd->ipath_control | INFINIPATH_C_RESET;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, val);
++	mb();
++
++	for (i = 1; i <= 5; i++) {
++		int r;
++
++		/*
++		 * Allow MBIST, etc. to complete; longer on each retry.
++		 * We sometimes get machine checks from bus timeout if no
++		 * response, so for now, make it *really* long.
++		 */
++		msleep(1000 + (1 + i) * 2000);
++		r = pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0,
++					   dd->ipath_pcibar0);
++		if (r)
++			ipath_dev_err(dd, "rewrite of BAR0 failed: %d\n", r);
++		r = pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_1,
++					   dd->ipath_pcibar1);
++		if (r)
++			ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n", r);
++		/* now re-enable memory access */
++		pci_write_config_word(dd->pcidev, PCI_COMMAND, cmdval);
++		r = pci_enable_device(dd->pcidev);
++		if (r)
++			ipath_dev_err(dd, "pci_enable_device failed after "
++				      "reset: %d\n", r);
++		/*
++		 * whether it fully enabled or not, mark as present,
++		 * again (but not INITTED)
++		 */
++		dd->ipath_flags |= IPATH_PRESENT;
++		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
++		if (val == dd->ipath_revision) {
++			ipath_cdbg(VERBOSE, "Got matching revision "
++				   "register %llx on try %d\n",
++				   (unsigned long long) val, i);
++			ret = ipath_reinit_msi(dd);
++			goto bail;
++		}
++		/* Probably getting -1 back */
++		ipath_dbg("Didn't get expected revision register, "
++			  "got %llx, try %d\n", (unsigned long long) val,
++			  i + 1);
++	}
++	ret = 0; /* failed */
++
++bail:
++	if (ret)
++		ipath_7220_pcie_params(dd, dd->ipath_boardrev);
++
++	return ret;
++}
++
++/**
++ * ipath_7220_put_tid - write a TID to the chip
++ * @dd: the infinipath device
++ * @tidptr: pointer to the expected TID (in chip) to udpate
++ * @tidtype: 0 for eager, 1 for expected
++ * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
++ *
++ * This exists as a separate routine to allow for selection of the
++ * appropriate "flavor". The static calls in cleanup just use the
++ * revision-agnostic form, as they are not performance critical.
++ */
++static void ipath_7220_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
++			     u32 type, unsigned long pa)
++{
++	if (pa != dd->ipath_tidinvalid) {
++		u64 chippa = pa >> IBA7220_TID_PA_SHIFT;
++
++		/* paranoia checks */
++		if (pa != (chippa << IBA7220_TID_PA_SHIFT)) {
++			dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "
++				 "not 2KB aligned!\n", pa);
++			return;
++		}
++		if (pa >= (1UL << IBA7220_TID_SZ_SHIFT)) {
++			ipath_dev_err(dd,
++				      "BUG: Physical page address 0x%lx "
++				      "larger than supported\n", pa);
++			return;
++		}
++
++		if (type == RCVHQ_RCV_TYPE_EAGER)
++			chippa |= dd->ipath_tidtemplate;
++		else /* for now, always full 4KB page */
++			chippa |= IBA7220_TID_SZ_4K;
++		writeq(chippa, tidptr);
++	} else
++		writeq(pa, tidptr);
++	mmiowb();
++}
++
++/**
++ * ipath_7220_clear_tid - clear all TID entries for a port, expected and eager
++ * @dd: the infinipath device
++ * @port: the port
++ *
++ * clear all TID entries for a port, expected and eager.
++ * Used from ipath_close().  On this chip, TIDs are only 32 bits,
++ * not 64, but they are still on 64 bit boundaries, so tidbase
++ * is declared as u64 * for the pointer math, even though we write 32 bits
++ */
++static void ipath_7220_clear_tids(struct ipath_devdata *dd, unsigned port)
++{
++	u64 __iomem *tidbase;
++	unsigned long tidinv;
++	int i;
++
++	if (!dd->ipath_kregbase)
++		return;
++
++	ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);
++
++	tidinv = dd->ipath_tidinvalid;
++	tidbase = (u64 __iomem *)
++		((char __iomem *)(dd->ipath_kregbase) +
++		 dd->ipath_rcvtidbase +
++		 port * dd->ipath_rcvtidcnt * sizeof(*tidbase));
++
++	for (i = 0; i < dd->ipath_rcvtidcnt; i++)
++		ipath_7220_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
++				   tidinv);
++
++	tidbase = (u64 __iomem *)
++		((char __iomem *)(dd->ipath_kregbase) +
++		 dd->ipath_rcvegrbase + port_egrtid_idx(dd, port)
++		 * sizeof(*tidbase));
++
++	for (i = port ? dd->ipath_rcvegrcnt : dd->ipath_p0_rcvegrcnt; i; i--)
++		ipath_7220_put_tid(dd, &tidbase[i-1], RCVHQ_RCV_TYPE_EAGER,
++			tidinv);
++}
++
++/**
++ * ipath_7220_tidtemplate - setup constants for TID updates
++ * @dd: the infinipath device
++ *
++ * We setup stuff that we use a lot, to avoid calculating each time
++ */
++static void ipath_7220_tidtemplate(struct ipath_devdata *dd)
++{
++	/* For now, we always allocate 4KB buffers (at init) so we can
++	 * receive max size packets.  We may want a module parameter to
++	 * specify 2KB or 4KB and/or make be per port instead of per device
++	 * for those who want to reduce memory footprint.  Note that the
++	 * ipath_rcvhdrentsize size must be large enough to hold the largest
++	 * IB header (currently 96 bytes) that we expect to handle (plus of
++	 * course the 2 dwords of RHF).
++	 */
++	if (dd->ipath_rcvegrbufsize == 2048)
++		dd->ipath_tidtemplate = IBA7220_TID_SZ_2K;
++	else if (dd->ipath_rcvegrbufsize == 4096)
++		dd->ipath_tidtemplate = IBA7220_TID_SZ_4K;
++	else {
++		dev_info(&dd->pcidev->dev, "BUG: unsupported egrbufsize "
++			 "%u, using %u\n", dd->ipath_rcvegrbufsize,
++			 4096);
++		dd->ipath_tidtemplate = IBA7220_TID_SZ_4K;
++	}
++	dd->ipath_tidinvalid = 0;
++}
++
++static int ipath_7220_early_init(struct ipath_devdata *dd)
++{
++	u32 i, s;
++
++	if (strcmp(int_type, "auto") &&
++	    strcmp(int_type, "force_msi") &&
++	    strcmp(int_type, "force_intx")) {
++		ipath_dev_err(dd, "Invalid interrupt_type: '%s', expecting "
++			      "auto, force_msi or force_intx\n", int_type);
++		return -EINVAL;
++	}
++
++	/*
++	 * Control[4] has been added to change the arbitration within
++	 * the SDMA engine between favoring data fetches over descriptor
++	 * fetches.  ipath_sdma_fetch_arb==0 gives data fetches priority.
++	 */
++	if (ipath_sdma_fetch_arb && (dd->ipath_minrev > 1))
++		dd->ipath_control |= 1<<4;
++
++	dd->ipath_flags |= IPATH_4BYTE_TID;
++
++	/*
++	 * For openfabrics, we need to be able to handle an IB header of
++	 * 24 dwords.  HT chip has arbitrary sized receive buffers, so we
++	 * made them the same size as the PIO buffers.  This chip does not
++	 * handle arbitrary size buffers, so we need the header large enough
++	 * to handle largest IB header, but still have room for a 2KB MTU
++	 * standard IB packet.
++	 */
++	dd->ipath_rcvhdrentsize = 24;
++	dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
++	dd->ipath_rhf_offset =
++		dd->ipath_rcvhdrentsize - sizeof(u64) / sizeof(u32);
++
++	dd->ipath_rcvegrbufsize = ipath_mtu4096 ? 4096 : 2048;
++	/*
++	 * the min() check here is currently a nop, but it may not always
++	 * be, depending on just how we do ipath_rcvegrbufsize
++	 */
++	dd->ipath_ibmaxlen = min(ipath_mtu4096 ? dd->ipath_piosize4k :
++				 dd->ipath_piosize2k,
++				 dd->ipath_rcvegrbufsize +
++				 (dd->ipath_rcvhdrentsize << 2));
++	dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
++
++	ipath_7220_config_jint(dd, INFINIPATH_JINT_DEFAULT_IDLE_TICKS,
++			       INFINIPATH_JINT_DEFAULT_MAX_PACKETS);
++
++	if (dd->ipath_boardrev) /* no eeprom on emulator */
++		ipath_get_eeprom_info(dd);
++
++	/* start of code to check and print procmon */
++	s = ipath_read_kreg32(dd, IPATH_KREG_OFFSET(ProcMon));
++	s &= ~(1U<<31); /* clear done bit */
++	s |= 1U<<14; /* clear counter (write 1 to clear) */
++	ipath_write_kreg(dd, IPATH_KREG_OFFSET(ProcMon), s);
++	/* make sure clear_counter low long enough before start */
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++
++	s &= ~(1U<<14); /* allow counter to count (before starting) */
++	ipath_write_kreg(dd, IPATH_KREG_OFFSET(ProcMon), s);
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++	s = ipath_read_kreg32(dd, IPATH_KREG_OFFSET(ProcMon));
++
++	s |= 1U<<15; /* start the counter */
++	s &= ~(1U<<31); /* clear done bit */
++	s &= ~0x7ffU; /* clear frequency bits */
++	s |= 0xe29; /* set frequency bits, in case cleared */
++	ipath_write_kreg(dd, IPATH_KREG_OFFSET(ProcMon), s);
++
++	s = 0;
++	for (i = 500; i > 0 && !(s&(1ULL<<31)); i--) {
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++		s = ipath_read_kreg32(dd, IPATH_KREG_OFFSET(ProcMon));
++	}
++	if (!(s&(1U<<31)))
++		ipath_dev_err(dd, "ProcMon register not valid: 0x%x\n", s);
++	else
++		ipath_dbg("ProcMon=0x%x, count=0x%x\n", s, (s>>16)&0x1ff);
++
++	return 0;
++}
++
++/**
++ * ipath_init_7220_get_base_info - set chip-specific flags for user code
++ * @pd: the infinipath port
++ * @kbase: ipath_base_info pointer
++ *
++ * We set the PCIE flag because the lower bandwidth on PCIe vs
++ * HyperTransport can affect some user packet algorithims.
++ */
++static int ipath_7220_get_base_info(struct ipath_portdata *pd, void *kbase)
++{
++	struct ipath_base_info *kinfo = kbase;
++
++	kinfo->spi_runtime_flags |=
++		IPATH_RUNTIME_PCIE | IPATH_RUNTIME_NODMA_RTAIL |
++		IPATH_RUNTIME_SDMA;
++
++	return 0;
++}
++
++static void ipath_7220_free_irq(struct ipath_devdata *dd)
++{
++	free_irq(dd->ipath_irq, dd);
++	dd->ipath_irq = 0;
++}
++
++static struct ipath_message_header *
++ipath_7220_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
++{
++	u32 offset = ipath_hdrget_offset(rhf_addr);
++
++	return (struct ipath_message_header *)
++		(rhf_addr - dd->ipath_rhf_offset + offset);
++}
++
++static void ipath_7220_config_ports(struct ipath_devdata *dd, ushort cfgports)
++{
++	u32 nchipports;
++
++	nchipports = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
++	if (!cfgports) {
++		int ncpus = num_online_cpus();
++
++		if (ncpus <= 4)
++			dd->ipath_portcnt = 5;
++		else if (ncpus <= 8)
++			dd->ipath_portcnt = 9;
++		if (dd->ipath_portcnt)
++			ipath_dbg("Auto-configured for %u ports, %d cpus "
++				"online\n", dd->ipath_portcnt, ncpus);
++	} else if (cfgports <= nchipports)
++		dd->ipath_portcnt = cfgports;
++	if (!dd->ipath_portcnt) /* none of the above, set to max */
++		dd->ipath_portcnt = nchipports;
++	/*
++	 * chip can be configured for 5, 9, or 17 ports, and choice
++	 * affects number of eager TIDs per port (1K, 2K, 4K).
++	 */
++	if (dd->ipath_portcnt > 9)
++		dd->ipath_rcvctrl |= 2ULL << IBA7220_R_PORTCFG_SHIFT;
++	else if (dd->ipath_portcnt > 5)
++		dd->ipath_rcvctrl |= 1ULL << IBA7220_R_PORTCFG_SHIFT;
++	/* else configure for default 5 receive ports */
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
++			 dd->ipath_rcvctrl);
++	dd->ipath_p0_rcvegrcnt = 2048; /* always */
++	if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++		dd->ipath_pioreserved = 1; /* reserve a buffer */
++}
++
++
++static int ipath_7220_get_ib_cfg(struct ipath_devdata *dd, int which)
++{
++	int lsb, ret = 0;
++	u64 maskr; /* right-justified mask */
++
++	switch (which) {
++	case IPATH_IB_CFG_HRTBT: /* Get Heartbeat off/enable/auto */
++		lsb = IBA7220_IBC_HRTBT_SHIFT;
++		maskr = IBA7220_IBC_HRTBT_MASK;
++		break;
++
++	case IPATH_IB_CFG_LWID_ENB: /* Get allowed Link-width */
++		ret = dd->ipath_link_width_enabled;
++		goto done;
++
++	case IPATH_IB_CFG_LWID: /* Get currently active Link-width */
++		ret = dd->ipath_link_width_active;
++		goto done;
++
++	case IPATH_IB_CFG_SPD_ENB: /* Get allowed Link speeds */
++		ret = dd->ipath_link_speed_enabled;
++		goto done;
++
++	case IPATH_IB_CFG_SPD: /* Get current Link spd */
++		ret = dd->ipath_link_speed_active;
++		goto done;
++
++	case IPATH_IB_CFG_RXPOL_ENB: /* Get Auto-RX-polarity enable */
++		lsb = IBA7220_IBC_RXPOL_SHIFT;
++		maskr = IBA7220_IBC_RXPOL_MASK;
++		break;
++
++	case IPATH_IB_CFG_LREV_ENB: /* Get Auto-Lane-reversal enable */
++		lsb = IBA7220_IBC_LREV_SHIFT;
++		maskr = IBA7220_IBC_LREV_MASK;
++		break;
++
++	case IPATH_IB_CFG_LINKLATENCY:
++		ret = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcddrstatus)
++			& IBA7220_DDRSTAT_LINKLAT_MASK;
++		goto done;
++
++	default:
++		ret = -ENOTSUPP;
++		goto done;
++	}
++	ret = (int)((dd->ipath_ibcddrctrl >> lsb) & maskr);
++done:
++	return ret;
++}
++
++static int ipath_7220_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
++{
++	int lsb, ret = 0, setforce = 0;
++	u64 maskr; /* right-justified mask */
++
++	switch (which) {
++	case IPATH_IB_CFG_LIDLMC:
++		/*
++		 * Set LID and LMC. Combined to avoid possible hazard
++		 * caller puts LMC in 16MSbits, DLID in 16LSbits of val
++		 */
++		lsb = IBA7220_IBC_DLIDLMC_SHIFT;
++		maskr = IBA7220_IBC_DLIDLMC_MASK;
++		break;
++
++	case IPATH_IB_CFG_HRTBT: /* set Heartbeat off/enable/auto */
++		if (val & IPATH_IB_HRTBT_ON &&
++			(dd->ipath_flags & IPATH_NO_HRTBT))
++			goto bail;
++		lsb = IBA7220_IBC_HRTBT_SHIFT;
++		maskr = IBA7220_IBC_HRTBT_MASK;
++		break;
++
++	case IPATH_IB_CFG_LWID_ENB: /* set allowed Link-width */
++		/*
++		 * As with speed, only write the actual register if
++		 * the link is currently down, otherwise takes effect
++		 * on next link change.
++		 */
++		dd->ipath_link_width_enabled = val;
++		if ((dd->ipath_flags & (IPATH_LINKDOWN|IPATH_LINKINIT)) !=
++			IPATH_LINKDOWN)
++			goto bail;
++		/*
++		 * We set the IPATH_IB_FORCE_NOTIFY bit so updown
++		 * will get called because we want update
++		 * link_width_active, and the change may not take
++		 * effect for some time (if we are in POLL), so this
++		 * flag will force the updown routine to be called
++		 * on the next ibstatuschange down interrupt, even
++		 * if it's not an down->up transition.
++		 */
++		val--; /* convert from IB to chip */
++		maskr = IBA7220_IBC_WIDTH_MASK;
++		lsb = IBA7220_IBC_WIDTH_SHIFT;
++		setforce = 1;
++		dd->ipath_flags |= IPATH_IB_FORCE_NOTIFY;
++		break;
++
++	case IPATH_IB_CFG_SPD_ENB: /* set allowed Link speeds */
++		/*
++		 * If we turn off IB1.2, need to preset SerDes defaults,
++		 * but not right now. Set a flag for the next time
++		 * we command the link down.  As with width, only write the
++		 * actual register if the link is currently down, otherwise
++		 * takes effect on next link change.  Since setting is being
++		 * explictly requested (via MAD or sysfs), clear autoneg
++		 * failure status if speed autoneg is enabled.
++		 */
++		dd->ipath_link_speed_enabled = val;
++		if (dd->ipath_ibcddrctrl & IBA7220_IBC_IBTA_1_2_MASK &&
++		    !(val & (val - 1)))
++			dd->ipath_presets_needed = 1;
++		if ((dd->ipath_flags & (IPATH_LINKDOWN|IPATH_LINKINIT)) !=
++			IPATH_LINKDOWN)
++			goto bail;
++		/*
++		 * We set the IPATH_IB_FORCE_NOTIFY bit so updown
++		 * will get called because we want update
++		 * link_speed_active, and the change may not take
++		 * effect for some time (if we are in POLL), so this
++		 * flag will force the updown routine to be called
++		 * on the next ibstatuschange down interrupt, even
++		 * if it's not an down->up transition.  When setting
++		 * speed autoneg, clear AUTONEG_FAILED.
++		 */
++		if (val == (IPATH_IB_SDR | IPATH_IB_DDR)) {
++			val = IBA7220_IBC_SPEED_AUTONEG_MASK |
++				IBA7220_IBC_IBTA_1_2_MASK;
++			dd->ipath_flags &= ~IPATH_IB_AUTONEG_FAILED;
++		} else
++			val = val == IPATH_IB_DDR ?  IBA7220_IBC_SPEED_DDR
++				: IBA7220_IBC_SPEED_SDR;
++		maskr = IBA7220_IBC_SPEED_AUTONEG_MASK |
++			IBA7220_IBC_IBTA_1_2_MASK;
++		lsb = 0; /* speed bits are low bits */
++		setforce = 1;
++		break;
++
++	case IPATH_IB_CFG_RXPOL_ENB: /* set Auto-RX-polarity enable */
++		lsb = IBA7220_IBC_RXPOL_SHIFT;
++		maskr = IBA7220_IBC_RXPOL_MASK;
++		break;
++
++	case IPATH_IB_CFG_LREV_ENB: /* set Auto-Lane-reversal enable */
++		lsb = IBA7220_IBC_LREV_SHIFT;
++		maskr = IBA7220_IBC_LREV_MASK;
++		break;
++
++	default:
++		ret = -ENOTSUPP;
++		goto bail;
++	}
++	dd->ipath_ibcddrctrl &= ~(maskr << lsb);
++	dd->ipath_ibcddrctrl |= (((u64) val & maskr) << lsb);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcddrctrl,
++			 dd->ipath_ibcddrctrl);
++	if (setforce)
++		dd->ipath_flags |= IPATH_IB_FORCE_NOTIFY;
++bail:
++	return ret;
++}
++
++static void ipath_7220_read_counters(struct ipath_devdata *dd,
++				     struct infinipath_counters *cntrs)
++{
++	u64 *counters = (u64 *) cntrs;
++	int i;
++
++	for (i = 0; i < sizeof(*cntrs) / sizeof(u64); i++)
++		counters[i] = ipath_snap_cntr(dd, i);
++}
++
++/* if we are using MSI, try to fallback to INTx */
++static int ipath_7220_intr_fallback(struct ipath_devdata *dd)
++{
++	if (dd->ipath_msi_lo) {
++		dev_info(&dd->pcidev->dev, "MSI interrupt not detected,"
++			" trying INTx interrupts\n");
++		ipath_7220_nomsi(dd);
++		ipath_enable_intx(dd->pcidev);
++		/*
++		 * some newer kernels require free_irq before disable_msi,
++		 * and irq can be changed during disable and intx enable
++		 * and we need to therefore use the pcidev->irq value,
++		 * not our saved MSI value.
++		 */
++		dd->ipath_irq = dd->pcidev->irq;
++		if (request_irq(dd->ipath_irq, ipath_intr, IRQF_SHARED,
++			IPATH_DRV_NAME, dd))
++			ipath_dev_err(dd,
++				"Could not re-request_irq for INTx\n");
++		return 1;
++	}
++	return 0;
++}
++
++/*
++ * reset the XGXS (between serdes and IBC).  Slightly less intrusive
++ * than resetting the IBC or external link state, and useful in some
++ * cases to cause some retraining.  To do this right, we reset IBC
++ * as well.
++ */
++static void ipath_7220_xgxs_reset(struct ipath_devdata *dd)
++{
++	u64 val, prev_val;
++
++	prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
++	val = prev_val | INFINIPATH_XGXS_RESET;
++	prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
++			 dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
++			 dd->ipath_control);
++}
++
++
++/* Still needs cleanup, too much hardwired stuff */
++static void autoneg_send(struct ipath_devdata *dd,
++	u32 *hdr, u32 dcnt, u32 *data)
++{
++	int i;
++	u64 cnt;
++	u32 __iomem *piobuf;
++	u32 pnum;
++
++	i = 0;
++	cnt = 7 + dcnt + 1; /* 7 dword header, dword data, icrc */
++	while (!(piobuf = ipath_getpiobuf(dd, cnt, &pnum))) {
++		if (i++ > 15) {
++			ipath_dbg("Couldn't get pio buffer for send\n");
++			return;
++		}
++		udelay(2);
++	}
++	if (dd->ipath_flags&IPATH_HAS_PBC_CNT)
++		cnt |= 0x80000000UL<<32; /* mark as VL15 */
++	writeq(cnt, piobuf);
++	ipath_flush_wc();
++	__iowrite32_copy(piobuf + 2, hdr, 7);
++	__iowrite32_copy(piobuf + 9, data, dcnt);
++	ipath_flush_wc();
++}
++
++/*
++ * _start packet gets sent twice at start, _done gets sent twice at end
++ */
++static void ipath_autoneg_send(struct ipath_devdata *dd, int which)
++{
++	static u32 swapped;
++	u32 dw, i, hcnt, dcnt, *data;
++	static u32 hdr[7] = { 0xf002ffff, 0x48ffff, 0x6400abba };
++	static u32 madpayload_start[0x40] = {
++		0x1810103, 0x1, 0x0, 0x0, 0x2c90000, 0x2c9, 0x0, 0x0,
++		0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++		0x1, 0x1388, 0x15e, 0x1, /* rest 0's */
++		};
++	static u32 madpayload_done[0x40] = {
++		0x1810103, 0x1, 0x0, 0x0, 0x2c90000, 0x2c9, 0x0, 0x0,
++		0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++		0x40000001, 0x1388, 0x15e, /* rest 0's */
++		};
++	dcnt = sizeof(madpayload_start)/sizeof(madpayload_start[0]);
++	hcnt = sizeof(hdr)/sizeof(hdr[0]);
++	if (!swapped) {
++		/* for maintainability, do it at runtime */
++		for (i = 0; i < hcnt; i++) {
++			dw = (__force u32) cpu_to_be32(hdr[i]);
++			hdr[i] = dw;
++		}
++		for (i = 0; i < dcnt; i++) {
++			dw = (__force u32) cpu_to_be32(madpayload_start[i]);
++			madpayload_start[i] = dw;
++			dw = (__force u32) cpu_to_be32(madpayload_done[i]);
++			madpayload_done[i] = dw;
++		}
++		swapped = 1;
++	}
++
++	data = which ? madpayload_done : madpayload_start;
++	ipath_cdbg(PKT, "Sending %s special MADs\n", which?"done":"start");
++
++	autoneg_send(dd, hdr, dcnt, data);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	udelay(2);
++	autoneg_send(dd, hdr, dcnt, data);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	udelay(2);
++}
++
++
++
++/*
++ * Do the absolute minimum to cause an IB speed change, and make it
++ * ready, but don't actually trigger the change.   The caller will
++ * do that when ready (if link is in Polling training state, it will
++ * happen immediately, otherwise when link next goes down)
++ *
++ * This routine should only be used as part of the DDR autonegotation
++ * code for devices that are not compliant with IB 1.2 (or code that
++ * fixes things up for same).
++ *
++ * When link has gone down, and autoneg enabled, or autoneg has
++ * failed and we give up until next time we set both speeds, and
++ * then we want IBTA enabled as well as "use max enabled speed.
++ */
++static void set_speed_fast(struct ipath_devdata *dd, u32 speed)
++{
++	dd->ipath_ibcddrctrl &= ~(IBA7220_IBC_SPEED_AUTONEG_MASK |
++		IBA7220_IBC_IBTA_1_2_MASK |
++		(IBA7220_IBC_WIDTH_MASK << IBA7220_IBC_WIDTH_SHIFT));
++
++	if (speed == (IPATH_IB_SDR | IPATH_IB_DDR))
++		dd->ipath_ibcddrctrl |= IBA7220_IBC_SPEED_AUTONEG_MASK |
++			IBA7220_IBC_IBTA_1_2_MASK;
++	else
++		dd->ipath_ibcddrctrl |= speed == IPATH_IB_DDR ?
++			IBA7220_IBC_SPEED_DDR : IBA7220_IBC_SPEED_SDR;
++
++	/*
++	 * Convert from IB-style 1 = 1x, 2 = 4x, 3 = auto
++	 * to chip-centric       0 = 1x, 1 = 4x, 2 = auto
++	 */
++	dd->ipath_ibcddrctrl |= (u64)(dd->ipath_link_width_enabled - 1) <<
++		IBA7220_IBC_WIDTH_SHIFT;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcddrctrl,
++			dd->ipath_ibcddrctrl);
++	ipath_cdbg(VERBOSE, "setup for IB speed (%x) done\n", speed);
++}
++
++
++/*
++ * this routine is only used when we are not talking to another
++ * IB 1.2-compliant device that we think can do DDR.
++ * (This includes all existing switch chips as of Oct 2007.)
++ * 1.2-compliant devices go directly to DDR prior to reaching INIT
++ */
++static void try_auto_neg(struct ipath_devdata *dd)
++{
++	/*
++	 * required for older non-IB1.2 DDR switches.  Newer
++	 * non-IB-compliant switches don't need it, but so far,
++	 * aren't bothered by it either.  "Magic constant"
++	 */
++	ipath_write_kreg(dd, IPATH_KREG_OFFSET(IBNCModeCtrl),
++		0x3b9dc07);
++	dd->ipath_flags |= IPATH_IB_AUTONEG_INPROG;
++	ipath_autoneg_send(dd, 0);
++	set_speed_fast(dd, IPATH_IB_DDR);
++	ipath_toggle_rclkrls(dd);
++	/* 2 msec is minimum length of a poll cycle */
++	schedule_delayed_work(&dd->ipath_autoneg_work,
++		msecs_to_jiffies(2));
++}
++
++
++static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
++{
++	int ret = 0;
++	u32 ltstate = ipath_ib_linkstate(dd, ibcs);
++
++	dd->ipath_link_width_active =
++		((ibcs >> IBA7220_IBCS_LINKWIDTH_SHIFT) & 1) ?
++		    IB_WIDTH_4X : IB_WIDTH_1X;
++	dd->ipath_link_speed_active =
++		((ibcs >> IBA7220_IBCS_LINKSPEED_SHIFT) & 1) ?
++		    IPATH_IB_DDR : IPATH_IB_SDR;
++
++	if (!ibup) {
++		/*
++		 * when link goes down we don't want aeq running, so it
++		 * won't't interfere with IBC training, etc., and we need
++		 * to go back to the static SerDes preset values
++		 */
++		if (dd->ipath_x1_fix_tries &&
++			 ltstate <= INFINIPATH_IBCS_LT_STATE_SLEEPQUIET &&
++			ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP)
++			dd->ipath_x1_fix_tries = 0;
++		if (!(dd->ipath_flags & (IPATH_IB_AUTONEG_FAILED |
++			IPATH_IB_AUTONEG_INPROG)))
++			set_speed_fast(dd, dd->ipath_link_speed_enabled);
++		if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)) {
++			ipath_cdbg(VERBOSE, "Setting RXEQ defaults\n");
++			ipath_sd7220_presets(dd);
++		}
++		/* this might better in ipath_sd7220_presets() */
++		ipath_set_relock_poll(dd, ibup);
++	} else {
++		if (ipath_compat_ddr_negotiate &&
++		    !(dd->ipath_flags & (IPATH_IB_AUTONEG_FAILED |
++			IPATH_IB_AUTONEG_INPROG)) &&
++			dd->ipath_link_speed_active == IPATH_IB_SDR &&
++			(dd->ipath_link_speed_enabled &
++			    (IPATH_IB_DDR | IPATH_IB_SDR)) ==
++			    (IPATH_IB_DDR | IPATH_IB_SDR) &&
++			dd->ipath_autoneg_tries < IPATH_AUTONEG_TRIES) {
++			/* we are SDR, and DDR auto-negotiation enabled */
++			++dd->ipath_autoneg_tries;
++			ipath_dbg("DDR negotiation try, %u/%u\n",
++				dd->ipath_autoneg_tries,
++				IPATH_AUTONEG_TRIES);
++			try_auto_neg(dd);
++			ret = 1; /* no other IB status change processing */
++		} else if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)
++			&& dd->ipath_link_speed_active == IPATH_IB_SDR) {
++			ipath_autoneg_send(dd, 1);
++			set_speed_fast(dd, IPATH_IB_DDR);
++			udelay(2);
++			ipath_toggle_rclkrls(dd);
++			ret = 1; /* no other IB status change processing */
++		} else {
++			if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) &&
++				(dd->ipath_link_speed_active & IPATH_IB_DDR)) {
++				ipath_dbg("Got to INIT with DDR autoneg\n");
++				dd->ipath_flags &= ~(IPATH_IB_AUTONEG_INPROG
++					| IPATH_IB_AUTONEG_FAILED);
++				dd->ipath_autoneg_tries = 0;
++				/* re-enable SDR, for next link down */
++				set_speed_fast(dd,
++					dd->ipath_link_speed_enabled);
++				wake_up(&dd->ipath_autoneg_wait);
++			} else if (dd->ipath_flags & IPATH_IB_AUTONEG_FAILED) {
++				/*
++				 * clear autoneg failure flag, and do setup
++				 * so we'll try next time link goes down and
++				 * back to INIT (possibly connected to different
++				 * device).
++				 */
++				ipath_dbg("INIT %sDR after autoneg failure\n",
++					(dd->ipath_link_speed_active &
++					  IPATH_IB_DDR) ? "D" : "S");
++				dd->ipath_flags &= ~IPATH_IB_AUTONEG_FAILED;
++				dd->ipath_ibcddrctrl |=
++					IBA7220_IBC_IBTA_1_2_MASK;
++				ipath_write_kreg(dd,
++					IPATH_KREG_OFFSET(IBNCModeCtrl), 0);
++			}
++		}
++		/*
++		 * if we are in 1X, and are in autoneg width, it
++		 * could be due to an xgxs problem, so if we haven't
++		 * already tried, try twice to get to 4X; if we
++		 * tried, and couldn't, report it, since it will
++		 * probably not be what is desired.
++		 */
++		if ((dd->ipath_link_width_enabled & (IB_WIDTH_1X |
++			IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X)
++			&& dd->ipath_link_width_active == IB_WIDTH_1X
++			&& dd->ipath_x1_fix_tries < 3) {
++			if (++dd->ipath_x1_fix_tries == 3)
++				dev_info(&dd->pcidev->dev,
++					"IB link is in 1X mode\n");
++			else {
++				ipath_cdbg(VERBOSE, "IB 1X in "
++					"auto-width, try %u to be "
++					"sure it's really 1X; "
++					"ltstate %u\n",
++					 dd->ipath_x1_fix_tries,
++					 ltstate);
++				dd->ipath_f_xgxs_reset(dd);
++				ret = 1; /* skip other processing */
++			}
++		}
++
++		if (!ret) {
++			dd->delay_mult = rate_to_delay
++			    [(ibcs >> IBA7220_IBCS_LINKSPEED_SHIFT) & 1]
++			    [(ibcs >> IBA7220_IBCS_LINKWIDTH_SHIFT) & 1];
++
++			ipath_set_relock_poll(dd, ibup);
++		}
++	}
++
++	if (!ret)
++		ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs),
++			ltstate);
++	return ret;
++}
++
++
++/*
++ * Handle the empirically determined mechanism for auto-negotiation
++ * of DDR speed with switches.
++ */
++static void autoneg_work(struct work_struct *work)
++{
++	struct ipath_devdata *dd;
++	u64 startms;
++	u32 lastlts, i;
++
++	dd = container_of(work, struct ipath_devdata,
++		ipath_autoneg_work.work);
++
++	startms = jiffies_to_msecs(jiffies);
++
++	/*
++	 * busy wait for this first part, it should be at most a
++	 * few hundred usec, since we scheduled ourselves for 2msec.
++	 */
++	for (i = 0; i < 25; i++) {
++		lastlts = ipath_ib_linktrstate(dd, dd->ipath_lastibcstat);
++		if (lastlts == INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
++			ipath_set_linkstate(dd, IPATH_IB_LINKDOWN_DISABLE);
++			break;
++		}
++		udelay(100);
++	}
++
++	if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG))
++		goto done; /* we got there early or told to stop */
++
++	/* we expect this to timeout */
++	if (wait_event_timeout(dd->ipath_autoneg_wait,
++		!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG),
++		msecs_to_jiffies(90)))
++		goto done;
++
++	ipath_toggle_rclkrls(dd);
++
++	/* we expect this to timeout */
++	if (wait_event_timeout(dd->ipath_autoneg_wait,
++		!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG),
++		msecs_to_jiffies(1700)))
++		goto done;
++
++	set_speed_fast(dd, IPATH_IB_SDR);
++	ipath_toggle_rclkrls(dd);
++
++	/*
++	 * wait up to 250 msec for link to train and get to INIT at DDR;
++	 * this should terminate early
++	 */
++	wait_event_timeout(dd->ipath_autoneg_wait,
++		!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG),
++		msecs_to_jiffies(250));
++done:
++	if (dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) {
++		ipath_dbg("Did not get to DDR INIT (%x) after %Lu msecs\n",
++			ipath_ib_state(dd, dd->ipath_lastibcstat),
++			jiffies_to_msecs(jiffies)-startms);
++		dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG;
++		if (dd->ipath_autoneg_tries == IPATH_AUTONEG_TRIES) {
++			dd->ipath_flags |= IPATH_IB_AUTONEG_FAILED;
++			ipath_dbg("Giving up on DDR until next IB "
++				"link Down\n");
++			dd->ipath_autoneg_tries = 0;
++		}
++		set_speed_fast(dd, dd->ipath_link_speed_enabled);
++	}
++}
++
++
++/**
++ * ipath_init_iba7220_funcs - set up the chip-specific function pointers
++ * @dd: the infinipath device
++ *
++ * This is global, and is called directly at init to set up the
++ * chip-specific function pointers for later use.
++ */
++void ipath_init_iba7220_funcs(struct ipath_devdata *dd)
++{
++	dd->ipath_f_intrsetup = ipath_7220_intconfig;
++	dd->ipath_f_bus = ipath_setup_7220_config;
++	dd->ipath_f_reset = ipath_setup_7220_reset;
++	dd->ipath_f_get_boardname = ipath_7220_boardname;
++	dd->ipath_f_init_hwerrors = ipath_7220_init_hwerrors;
++	dd->ipath_f_early_init = ipath_7220_early_init;
++	dd->ipath_f_handle_hwerrors = ipath_7220_handle_hwerrors;
++	dd->ipath_f_quiet_serdes = ipath_7220_quiet_serdes;
++	dd->ipath_f_bringup_serdes = ipath_7220_bringup_serdes;
++	dd->ipath_f_clear_tids = ipath_7220_clear_tids;
++	dd->ipath_f_put_tid = ipath_7220_put_tid;
++	dd->ipath_f_cleanup = ipath_setup_7220_cleanup;
++	dd->ipath_f_setextled = ipath_setup_7220_setextled;
++	dd->ipath_f_get_base_info = ipath_7220_get_base_info;
++	dd->ipath_f_free_irq = ipath_7220_free_irq;
++	dd->ipath_f_tidtemplate = ipath_7220_tidtemplate;
++	dd->ipath_f_intr_fallback = ipath_7220_intr_fallback;
++	dd->ipath_f_xgxs_reset = ipath_7220_xgxs_reset;
++	dd->ipath_f_get_ib_cfg = ipath_7220_get_ib_cfg;
++	dd->ipath_f_set_ib_cfg = ipath_7220_set_ib_cfg;
++	dd->ipath_f_config_jint = ipath_7220_config_jint;
++	dd->ipath_f_config_ports = ipath_7220_config_ports;
++	dd->ipath_f_read_counters = ipath_7220_read_counters;
++	dd->ipath_f_get_msgheader = ipath_7220_get_msgheader;
++	dd->ipath_f_ib_updown = ipath_7220_ib_updown;
++
++	/* initialize chip-specific variables */
++	ipath_init_7220_variables(dd);
++}
+diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
+index 4471674..27dd894 100644
+--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
++++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -155,24 +155,13 @@ static int bringup_link(struct ipath_devdata *dd)
+ 			 dd->ipath_control);
+ 
+ 	/*
+-	 * Note that prior to try 14 or 15 of IB, the credit scaling
+-	 * wasn't working, because it was swapped for writes with the
+-	 * 1 bit default linkstate field
++	 * set initial max size pkt IBC will send, including ICRC; it's the
++	 * PIO buffer size in dwords, less 1; also see ipath_set_mtu()
+ 	 */
++	val = (dd->ipath_ibmaxlen >> 2) + 1;
++	ibc = val << dd->ibcc_mpl_shift;
+ 
+-	/* ignore pbc and align word */
+-	val = dd->ipath_piosize2k - 2 * sizeof(u32);
+-	/*
+-	 * for ICRC, which we only send in diag test pkt mode, and we
+-	 * don't need to worry about that for mtu
+-	 */
+-	val += 1;
+-	/*
+-	 * Set the IBC maxpktlength to the size of our pio buffers the
+-	 * maxpktlength is in words.  This is *not* the IB data MTU.
+-	 */
+-	ibc = (val / sizeof(u32)) << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+-	/* in KB */
++	/* flowcontrolwatermark is in units of KBytes */
+ 	ibc |= 0x5ULL << INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT;
+ 	/*
+ 	 * How often flowctrl sent.  More or less in usecs; balance against
+@@ -191,10 +180,13 @@ static int bringup_link(struct ipath_devdata *dd)
+ 	/*
+ 	 * Want to start out with both LINKCMD and LINKINITCMD in NOP
+ 	 * (0 and 0).  Don't put linkinitcmd in ipath_ibcctrl, want that
+-	 * to stay a NOP
++	 * to stay a NOP. Flag that we are disabled, for the (unlikely)
++	 * case that some recovery path is trying to bring the link up
++	 * before we are ready.
+ 	 */
+ 	ibc |= INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+ 		INFINIPATH_IBCC_LINKINITCMD_SHIFT;
++	dd->ipath_flags |= IPATH_IB_LINK_DISABLED;
+ 	ipath_cdbg(VERBOSE, "Writing 0x%llx to ibcctrl\n",
+ 		   (unsigned long long) ibc);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, ibc);
+@@ -227,17 +219,26 @@ static struct ipath_portdata *create_portdata0(struct ipath_devdata *dd)
+ 		pd->port_cnt = 1;
+ 		/* The port 0 pkey table is used by the layer interface. */
+ 		pd->port_pkeys[0] = IPATH_DEFAULT_P_KEY;
++		pd->port_seq_cnt = 1;
+ 	}
+ 	return pd;
+ }
+ 
+-static int init_chip_first(struct ipath_devdata *dd,
+-			   struct ipath_portdata **pdp)
++static int init_chip_first(struct ipath_devdata *dd)
+ {
+-	struct ipath_portdata *pd = NULL;
++	struct ipath_portdata *pd;
+ 	int ret = 0;
+ 	u64 val;
+ 
++	spin_lock_init(&dd->ipath_kernel_tid_lock);
++	spin_lock_init(&dd->ipath_user_tid_lock);
++	spin_lock_init(&dd->ipath_sendctrl_lock);
++	spin_lock_init(&dd->ipath_sdma_lock);
++	spin_lock_init(&dd->ipath_gpio_lock);
++	spin_lock_init(&dd->ipath_eep_st_lock);
++	spin_lock_init(&dd->ipath_sdepb_lock);
++	mutex_init(&dd->ipath_eep_lock);
++
+ 	/*
+ 	 * skip cfgports stuff because we are not allocating memory,
+ 	 * and we don't want problems if the portcnt changed due to
+@@ -250,12 +251,14 @@ static int init_chip_first(struct ipath_devdata *dd,
+ 	else if (ipath_cfgports <= dd->ipath_portcnt) {
+ 		dd->ipath_cfgports = ipath_cfgports;
+ 		ipath_dbg("Configured to use %u ports out of %u in chip\n",
+-			  dd->ipath_cfgports, dd->ipath_portcnt);
++			  dd->ipath_cfgports, ipath_read_kreg32(dd,
++			  dd->ipath_kregs->kr_portcnt));
+ 	} else {
+ 		dd->ipath_cfgports = dd->ipath_portcnt;
+ 		ipath_dbg("Tried to configured to use %u ports; chip "
+ 			  "only supports %u\n", ipath_cfgports,
+-			  dd->ipath_portcnt);
++			  ipath_read_kreg32(dd,
++				  dd->ipath_kregs->kr_portcnt));
+ 	}
+ 	/*
+ 	 * Allocate full portcnt array, rather than just cfgports, because
+@@ -295,12 +298,9 @@ static int init_chip_first(struct ipath_devdata *dd,
+ 	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize);
+ 	dd->ipath_piosize2k = val & ~0U;
+ 	dd->ipath_piosize4k = val >> 32;
+-	/*
+-	 * Note: the chips support a maximum MTU of 4096, but the driver
+-	 * hasn't implemented this feature yet, so set the initial value
+-	 * to 2048.
+-	 */
+-	dd->ipath_ibmtu = 2048;
++	if (dd->ipath_piosize4k == 0 && ipath_mtu4096)
++		ipath_mtu4096 = 0; /* 4KB not supported by this chip */
++	dd->ipath_ibmtu = ipath_mtu4096 ? 4096 : 2048;
+ 	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt);
+ 	dd->ipath_piobcnt2k = val & ~0U;
+ 	dd->ipath_piobcnt4k = val >> 32;
+@@ -328,43 +328,46 @@ static int init_chip_first(struct ipath_devdata *dd,
+ 	else ipath_dbg("%u 2k piobufs @ %p\n",
+ 		       dd->ipath_piobcnt2k, dd->ipath_pio2kbase);
+ 
+-	spin_lock_init(&dd->ipath_tid_lock);
+-	spin_lock_init(&dd->ipath_sendctrl_lock);
+-	spin_lock_init(&dd->ipath_gpio_lock);
+-	spin_lock_init(&dd->ipath_eep_st_lock);
+-	mutex_init(&dd->ipath_eep_lock);
+-
+ done:
+-	*pdp = pd;
+ 	return ret;
+ }
+ 
+ /**
+  * init_chip_reset - re-initialize after a reset, or enable
+  * @dd: the infinipath device
+- * @pdp: output for port data
+  *
+  * sanity check at least some of the values after reset, and
+  * ensure no receive or transmit (explictly, in case reset
+  * failed
+  */
+-static int init_chip_reset(struct ipath_devdata *dd,
+-			   struct ipath_portdata **pdp)
++static int init_chip_reset(struct ipath_devdata *dd)
+ {
+ 	u32 rtmp;
++	int i;
++	unsigned long flags;
++
++	/*
++	 * ensure chip does no sends or receives, tail updates, or
++	 * pioavail updates while we re-initialize
++	 */
++	dd->ipath_rcvctrl &= ~(1ULL << dd->ipath_r_tailupd_shift);
++	for (i = 0; i < dd->ipath_portcnt; i++) {
++		clear_bit(dd->ipath_r_portenable_shift + i,
++			  &dd->ipath_rcvctrl);
++		clear_bit(dd->ipath_r_intravail_shift + i,
++			  &dd->ipath_rcvctrl);
++	}
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
++		dd->ipath_rcvctrl);
+ 
+-	*pdp = dd->ipath_pd[0];
+-	/* ensure chip does no sends or receives while we re-initialize */
+-	dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl);
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	dd->ipath_sendctrl = 0U; /* no sdma, etc */
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, dd->ipath_control);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL);
+ 
+-	rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
+-	if (dd->ipath_portcnt != rtmp)
+-		dev_info(&dd->pcidev->dev, "portcnt was %u before "
+-			 "reset, now %u, using original\n",
+-			 dd->ipath_portcnt, rtmp);
+ 	rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
+ 	if (rtmp != dd->ipath_rcvtidcnt)
+ 		dev_info(&dd->pcidev->dev, "tidcnt was %u before "
+@@ -467,10 +470,10 @@ static void init_shadow_tids(struct ipath_devdata *dd)
+ 	dd->ipath_physshadow = addrs;
+ }
+ 
+-static void enable_chip(struct ipath_devdata *dd,
+-			struct ipath_portdata *pd, int reinit)
++static void enable_chip(struct ipath_devdata *dd, int reinit)
+ {
+ 	u32 val;
++	u64 rcvmask;
+ 	unsigned long flags;
+ 	int i;
+ 
+@@ -484,17 +487,28 @@ static void enable_chip(struct ipath_devdata *dd,
+ 	/* Enable PIO send, and update of PIOavail regs to memory. */
+ 	dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE |
+ 		INFINIPATH_S_PIOBUFAVAILUPD;
++
++	/*
++	 * Set the PIO avail update threshold to host memory
++	 * on chips that support it.
++	 */
++	if (dd->ipath_pioupd_thresh)
++		dd->ipath_sendctrl |= dd->ipath_pioupd_thresh
++			<< INFINIPATH_S_UPDTHRESH_SHIFT;
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
+ 	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ 	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ 
+ 	/*
+-	 * enable port 0 receive, and receive interrupt.  other ports
+-	 * done as user opens and inits them.
++	 * Enable kernel ports' receive and receive interrupt.
++	 * Other ports done as user opens and inits them.
+ 	 */
+-	dd->ipath_rcvctrl = (1ULL << dd->ipath_r_tailupd_shift) |
+-		(1ULL << dd->ipath_r_portenable_shift) |
+-		(1ULL << dd->ipath_r_intravail_shift);
++	rcvmask = 1ULL;
++	dd->ipath_rcvctrl |= (rcvmask << dd->ipath_r_portenable_shift) |
++		(rcvmask << dd->ipath_r_intravail_shift);
++	if (!(dd->ipath_flags & IPATH_NODMA_RTAIL))
++		dd->ipath_rcvctrl |= (1ULL << dd->ipath_r_tailupd_shift);
++
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ 			 dd->ipath_rcvctrl);
+ 
+@@ -505,16 +519,16 @@ static void enable_chip(struct ipath_devdata *dd,
+ 	dd->ipath_flags |= IPATH_INITTED;
+ 
+ 	/*
+-	 * init our shadow copies of head from tail values, and write
+-	 * head values to match.
++	 * Init our shadow copies of head from tail values,
++	 * and write head values to match.
+ 	 */
+ 	val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0);
+-	(void)ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
++	ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
+ 
+ 	/* Initialize so we interrupt on next packet received */
+-	(void)ipath_write_ureg(dd, ur_rcvhdrhead,
+-			       dd->ipath_rhdrhead_intr_off |
+-			       dd->ipath_pd[0]->port_head, 0);
++	ipath_write_ureg(dd, ur_rcvhdrhead,
++			 dd->ipath_rhdrhead_intr_off |
++			 dd->ipath_pd[0]->port_head, 0);
+ 
+ 	/*
+ 	 * by now pioavail updates to memory should have occurred, so
+@@ -523,25 +537,26 @@ static void enable_chip(struct ipath_devdata *dd,
+ 	 * initial values of the generation bit correct.
+ 	 */
+ 	for (i = 0; i < dd->ipath_pioavregs; i++) {
+-		__le64 val;
++		__le64 pioavail;
+ 
+ 		/*
+ 		 * Chip Errata bug 6641; even and odd qwords>3 are swapped.
+ 		 */
+ 		if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS))
+-			val = dd->ipath_pioavailregs_dma[i ^ 1];
++			pioavail = dd->ipath_pioavailregs_dma[i ^ 1];
+ 		else
+-			val = dd->ipath_pioavailregs_dma[i];
+-		dd->ipath_pioavailshadow[i] = le64_to_cpu(val);
++			pioavail = dd->ipath_pioavailregs_dma[i];
++		dd->ipath_pioavailshadow[i] = le64_to_cpu(pioavail) |
++			(~dd->ipath_pioavailkernel[i] <<
++			INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT);
+ 	}
+ 	/* can get counters, stats, etc. */
+ 	dd->ipath_flags |= IPATH_PRESENT;
+ }
+ 
+-static int init_housekeeping(struct ipath_devdata *dd,
+-			     struct ipath_portdata **pdp, int reinit)
++static int init_housekeeping(struct ipath_devdata *dd, int reinit)
+ {
+-	char boardn[32];
++	char boardn[40];
+ 	int ret = 0;
+ 
+ 	/*
+@@ -600,18 +615,9 @@ static int init_housekeeping(struct ipath_devdata *dd,
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
+ 			 INFINIPATH_E_RESET);
+ 
+-	if (reinit)
+-		ret = init_chip_reset(dd, pdp);
+-	else
+-		ret = init_chip_first(dd, pdp);
+-
+-	if (ret)
+-		goto done;
+-
+-	ipath_cdbg(VERBOSE, "Revision %llx (PCI %x), %u ports, %u tids, "
+-		   "%u egrtids\n", (unsigned long long) dd->ipath_revision,
+-		   dd->ipath_pcirev, dd->ipath_portcnt, dd->ipath_rcvtidcnt,
+-		   dd->ipath_rcvegrcnt);
++	ipath_cdbg(VERBOSE, "Revision %llx (PCI %x)\n",
++		   (unsigned long long) dd->ipath_revision,
++		   dd->ipath_pcirev);
+ 
+ 	if (((dd->ipath_revision >> INFINIPATH_R_SOFTWARE_SHIFT) &
+ 	     INFINIPATH_R_SOFTWARE_MASK) != IPATH_CHIP_SWVERSION) {
+@@ -650,10 +656,39 @@ static int init_housekeeping(struct ipath_devdata *dd,
+ 
+ 	ipath_dbg("%s", dd->ipath_boardversion);
+ 
++	if (ret)
++		goto done;
++
++	if (reinit)
++		ret = init_chip_reset(dd);
++	else
++		ret = init_chip_first(dd);
++
+ done:
+ 	return ret;
+ }
+ 
++static void verify_interrupt(unsigned long opaque)
++{
++	struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
++
++	if (!dd)
++		return; /* being torn down */
++
++	/*
++	 * If we don't have any interrupts, let the user know and
++	 * don't bother checking again.
++	 */
++	if (dd->ipath_int_counter == 0) {
++		if (!dd->ipath_f_intr_fallback(dd))
++			dev_err(&dd->pcidev->dev, "No interrupts detected, "
++				"not usable.\n");
++		else /* re-arm the timer to see if fallback works */
++			mod_timer(&dd->ipath_intrchk_timer, jiffies + HZ/2);
++	} else
++		ipath_cdbg(VERBOSE, "%u interrupts at timer check\n",
++			dd->ipath_int_counter);
++}
+ 
+ /**
+  * ipath_init_chip - do the actual initialization sequence on the chip
+@@ -676,11 +711,11 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 	u32 val32, kpiobufs;
+ 	u32 piobufs, uports;
+ 	u64 val;
+-	struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
++	struct ipath_portdata *pd;
+ 	gfp_t gfp_flags = GFP_USER | __GFP_COMP;
+ 	unsigned long flags;
+ 
+-	ret = init_housekeeping(dd, &pd, reinit);
++	ret = init_housekeeping(dd, reinit);
+ 	if (ret)
+ 		goto done;
+ 
+@@ -700,7 +735,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 	 * we now use routines that backend onto __get_free_pages, the
+ 	 * rest would be wasted.
+ 	 */
+-	dd->ipath_rcvhdrcnt = dd->ipath_rcvegrcnt;
++	dd->ipath_rcvhdrcnt = max(dd->ipath_p0_rcvegrcnt, dd->ipath_rcvegrcnt);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrcnt,
+ 			 dd->ipath_rcvhdrcnt);
+ 
+@@ -731,8 +766,8 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 	if (kpiobufs + (uports * IPATH_MIN_USER_PORT_BUFCNT) > piobufs) {
+ 		int i = (int) piobufs -
+ 			(int) (uports * IPATH_MIN_USER_PORT_BUFCNT);
+-		if (i < 0)
+-			i = 0;
++		if (i < 1)
++			i = 1;
+ 		dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs of "
+ 			 "%d for kernel leaves too few for %d user ports "
+ 			 "(%d each); using %u\n", kpiobufs,
+@@ -751,24 +786,40 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 		ipath_dbg("allocating %u pbufs/port leaves %u unused, "
+ 			  "add to kernel\n", dd->ipath_pbufsport, val32);
+ 		dd->ipath_lastport_piobuf -= val32;
++		kpiobufs += val32;
+ 		ipath_dbg("%u pbufs/port leaves %u unused, add to kernel\n",
+ 			  dd->ipath_pbufsport, val32);
+ 	}
+-	dd->ipath_lastpioindex = dd->ipath_lastport_piobuf;
++	dd->ipath_lastpioindex = 0;
++	dd->ipath_lastpioindexl = dd->ipath_piobcnt2k;
++	ipath_chg_pioavailkernel(dd, 0, piobufs, 1);
+ 	ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u "
+ 		   "each for %u user ports\n", kpiobufs,
+ 		   piobufs, dd->ipath_pbufsport, uports);
++	if (dd->ipath_pioupd_thresh) {
++		if (dd->ipath_pbufsport < dd->ipath_pioupd_thresh)
++			dd->ipath_pioupd_thresh = dd->ipath_pbufsport;
++		if (kpiobufs < dd->ipath_pioupd_thresh)
++			dd->ipath_pioupd_thresh = kpiobufs;
++	}
++
++	ret = dd->ipath_f_early_init(dd);
++	if (ret) {
++		ipath_dev_err(dd, "Early initialization failure\n");
++		goto done;
++	}
+ 
+-	dd->ipath_f_early_init(dd);
+ 	/*
+-	 * cancel any possible active sends from early driver load.
++	 * Cancel any possible active sends from early driver load.
+ 	 * Follows early_init because some chips have to initialize
+ 	 * PIO buffers in early_init to avoid false parity errors.
+ 	 */
+ 	ipath_cancel_sends(dd, 0);
+ 
+-	/* early_init sets rcvhdrentsize and rcvhdrsize, so this must be
+-	 * done after early_init */
++	/*
++	 * Early_init sets rcvhdrentsize and rcvhdrsize, so this must be
++	 * done after early_init.
++	 */
+ 	dd->ipath_hdrqlast =
+ 		dd->ipath_rcvhdrentsize * (dd->ipath_rcvhdrcnt - 1);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrentsize,
+@@ -783,8 +834,8 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 			goto done;
+ 	}
+ 
+-	(void)ipath_write_kreg(dd, dd->ipath_kregs->kr_sendpioavailaddr,
+-			       dd->ipath_pioavailregs_phys);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendpioavailaddr,
++			 dd->ipath_pioavailregs_phys);
+ 	/*
+ 	 * this is to detect s/w errors, which the h/w works around by
+ 	 * ignoring the low 6 bits of address, if it wasn't aligned.
+@@ -843,58 +894,65 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 	/* enable errors that are masked, at least this first time. */
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+ 			 ~dd->ipath_maskederrs);
+-	dd->ipath_errormask = ipath_read_kreg64(dd,
+-		dd->ipath_kregs->kr_errormask);
++	dd->ipath_maskederrs = 0; /* don't re-enable ignored in timer */
++	dd->ipath_errormask =
++		ipath_read_kreg64(dd, dd->ipath_kregs->kr_errormask);
+ 	/* clear any interrupts up to this point (ints still not enabled) */
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+ 
++	dd->ipath_f_tidtemplate(dd);
++
+ 	/*
+ 	 * Set up the port 0 (kernel) rcvhdr q and egr TIDs.  If doing
+ 	 * re-init, the simplest way to handle this is to free
+ 	 * existing, and re-allocate.
+ 	 * Need to re-create rest of port 0 portdata as well.
+ 	 */
++	pd = dd->ipath_pd[0];
+ 	if (reinit) {
+-		/* Alloc and init new ipath_portdata for port0,
++		struct ipath_portdata *npd;
++
++		/*
++		 * Alloc and init new ipath_portdata for port0,
+ 		 * Then free old pd. Could lead to fragmentation, but also
+ 		 * makes later support for hot-swap easier.
+ 		 */
+-		struct ipath_portdata *npd;
+ 		npd = create_portdata0(dd);
+ 		if (npd) {
+ 			ipath_free_pddata(dd, pd);
+-			dd->ipath_pd[0] = pd = npd;
++			dd->ipath_pd[0] = npd;
++			pd = npd;
+ 		} else {
+-			ipath_dev_err(dd, "Unable to allocate portdata for"
+-				      "  port 0, failing\n");
++			ipath_dev_err(dd, "Unable to allocate portdata"
++				      " for port 0, failing\n");
+ 			ret = -ENOMEM;
+ 			goto done;
+ 		}
+ 	}
+-	dd->ipath_f_tidtemplate(dd);
+ 	ret = ipath_create_rcvhdrq(dd, pd);
+-	if (!ret) {
+-		dd->ipath_hdrqtailptr =
+-			(volatile __le64 *)pd->port_rcvhdrtail_kvaddr;
++	if (!ret)
+ 		ret = create_port0_egr(dd);
+-	}
+-	if (ret)
+-		ipath_dev_err(dd, "failed to allocate port 0 (kernel) "
++	if (ret) {
++		ipath_dev_err(dd, "failed to allocate kernel port's "
+ 			      "rcvhdrq and/or egr bufs\n");
++		goto done;
++	}
+ 	else
+-		enable_chip(dd, pd, reinit);
+-
++		enable_chip(dd, reinit);
+ 
+-	if (!ret && !reinit) {
+-	    /* used when we close a port, for DMA already in flight at close */
++	if (!reinit) {
++		/*
++		 * Used when we close a port, for DMA already in flight
++		 * at close.
++		 */
+ 		dd->ipath_dummy_hdrq = dma_alloc_coherent(
+-			&dd->pcidev->dev, pd->port_rcvhdrq_size,
++			&dd->pcidev->dev, dd->ipath_pd[0]->port_rcvhdrq_size,
+ 			&dd->ipath_dummy_hdrq_phys,
+ 			gfp_flags);
+-		if (!dd->ipath_dummy_hdrq ) {
++		if (!dd->ipath_dummy_hdrq) {
+ 			dev_info(&dd->pcidev->dev,
+ 				"Couldn't allocate 0x%lx bytes for dummy hdrq\n",
+-				pd->port_rcvhdrq_size);
++				dd->ipath_pd[0]->port_rcvhdrq_size);
+ 			/* fallback to just 0'ing */
+ 			dd->ipath_dummy_hdrq_phys = 0UL;
+ 		}
+@@ -906,7 +964,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 	 */
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
+ 
+-	if(!dd->ipath_stats_timer_active) {
++	if (!dd->ipath_stats_timer_active) {
+ 		/*
+ 		 * first init, or after an admin disable/enable
+ 		 * set up stats retrieval timer, even if we had errors
+@@ -922,6 +980,16 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 		dd->ipath_stats_timer_active = 1;
+ 	}
+ 
++	/* Set up SendDMA if chip supports it */
++	if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++		ret = setup_sdma(dd);
++
++	/* Set up HoL state */
++	init_timer(&dd->ipath_hol_timer);
++	dd->ipath_hol_timer.function = ipath_hol_event;
++	dd->ipath_hol_timer.data = (unsigned long)dd;
++	dd->ipath_hol_state = IPATH_HOL_UP;
++
+ done:
+ 	if (!ret) {
+ 		*dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT;
+@@ -934,6 +1002,20 @@ done:
+ 					 0ULL);
+ 			/* chip is usable; mark it as initialized */
+ 			*dd->ipath_statusp |= IPATH_STATUS_INITTED;
++
++			/*
++			 * setup to verify we get an interrupt, and fallback
++			 * to an alternate if necessary and possible
++			 */
++			if (!reinit) {
++				init_timer(&dd->ipath_intrchk_timer);
++				dd->ipath_intrchk_timer.function =
++					verify_interrupt;
++				dd->ipath_intrchk_timer.data =
++					(unsigned long) dd;
++			}
++			dd->ipath_intrchk_timer.expires = jiffies + HZ/2;
++			add_timer(&dd->ipath_intrchk_timer);
+ 		} else
+ 			ipath_dev_err(dd, "No interrupts enabled, couldn't "
+ 				      "setup interrupt address\n");
+diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
+index 92e58c9..1b58f47 100644
+--- a/drivers/infiniband/hw/ipath/ipath_intr.c
++++ b/drivers/infiniband/hw/ipath/ipath_intr.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -32,6 +32,7 @@
+  */
+ 
+ #include <linux/pci.h>
++#include <linux/delay.h>
+ 
+ #include "ipath_kernel.h"
+ #include "ipath_verbs.h"
+@@ -59,9 +60,11 @@ static void ipath_clrpiobuf(struct ipath_devdata *dd, u32 pnum)
+ 	dev_info(&dd->pcidev->dev,
+ 		"Rewrite PIO buffer %u, to recover from parity error\n",
+ 		pnum);
+-	*pbuf = dwcnt+1; /* no flush required, since already in freeze */
+-	while(--dwcnt)
+-		*pbuf++ = 0;
++
++	/* no flush required, since already in freeze */
++	writel(dwcnt + 1, pbuf);
++	while (--dwcnt)
++		writel(0, pbuf++);
+ }
+ 
+ /*
+@@ -70,7 +73,7 @@ static void ipath_clrpiobuf(struct ipath_devdata *dd, u32 pnum)
+  * If rewrite is true, and bits are set in the sendbufferror registers,
+  * we'll write to the buffer, for error recovery on parity errors.
+  */
+-static void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
++void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
+ {
+ 	u32 piobcnt;
+ 	unsigned long sbuf[4];
+@@ -84,12 +87,14 @@ static void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
+ 		dd, dd->ipath_kregs->kr_sendbuffererror);
+ 	sbuf[1] = ipath_read_kreg64(
+ 		dd, dd->ipath_kregs->kr_sendbuffererror + 1);
+-	if (piobcnt > 128) {
++	if (piobcnt > 128)
+ 		sbuf[2] = ipath_read_kreg64(
+ 			dd, dd->ipath_kregs->kr_sendbuffererror + 2);
++	if (piobcnt > 192)
+ 		sbuf[3] = ipath_read_kreg64(
+ 			dd, dd->ipath_kregs->kr_sendbuffererror + 3);
+-	}
++	else
++		sbuf[3] = 0;
+ 
+ 	if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
+ 		int i;
+@@ -254,24 +259,20 @@ void ipath_format_hwerrors(u64 hwerrs,
+ }
+ 
+ /* return the strings for the most common link states */
+-static char *ib_linkstate(u32 linkstate)
++static char *ib_linkstate(struct ipath_devdata *dd, u64 ibcs)
+ {
+ 	char *ret;
++	u32 state;
+ 
+-	switch (linkstate) {
+-	case IPATH_IBSTATE_INIT:
++	state = ipath_ib_state(dd, ibcs);
++	if (state == dd->ib_init)
+ 		ret = "Init";
+-		break;
+-	case IPATH_IBSTATE_ARM:
++	else if (state == dd->ib_arm)
+ 		ret = "Arm";
+-		break;
+-	case IPATH_IBSTATE_ACTIVE:
++	else if (state == dd->ib_active)
+ 		ret = "Active";
+-		break;
+-	default:
++	else
+ 		ret = "Down";
+-	}
+-
+ 	return ret;
+ }
+ 
+@@ -286,103 +287,172 @@ void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev)
+ }
+ 
+ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
+-				     ipath_err_t errs, int noprint)
++				     ipath_err_t errs)
+ {
+-	u64 val;
+-	u32 ltstate, lstate;
++	u32 ltstate, lstate, ibstate, lastlstate;
++	u32 init = dd->ib_init;
++	u32 arm = dd->ib_arm;
++	u32 active = dd->ib_active;
++	const u64 ibcs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
++
++	lstate = ipath_ib_linkstate(dd, ibcs); /* linkstate */
++	ibstate = ipath_ib_state(dd, ibcs);
++	/* linkstate at last interrupt */
++	lastlstate = ipath_ib_linkstate(dd, dd->ipath_lastibcstat);
++	ltstate = ipath_ib_linktrstate(dd, ibcs); /* linktrainingtate */
+ 
+ 	/*
+-	 * even if diags are enabled, we want to notice LINKINIT, etc.
+-	 * We just don't want to change the LED state, or
+-	 * dd->ipath_kregs->kr_ibcctrl
++	 * Since going into a recovery state causes the link state to go
++	 * down and since recovery is transitory, it is better if we "miss"
++	 * ever seeing the link training state go into recovery (i.e.,
++	 * ignore this transition for link state special handling purposes)
++	 * without even updating ipath_lastibcstat.
+ 	 */
+-	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+-	lstate = val & IPATH_IBSTATE_MASK;
++	if ((ltstate == INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN) ||
++	    (ltstate == INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT) ||
++	    (ltstate == INFINIPATH_IBCS_LT_STATE_RECOVERIDLE))
++		goto done;
+ 
+ 	/*
+-	 * this is confusing enough when it happens that I want to always put it
+-	 * on the console and in the logs.  If it was a requested state change,
+-	 * we'll have already cleared the flags, so we won't print this warning
++	 * if linkstate transitions into INIT from any of the various down
++	 * states, or if it transitions from any of the up (INIT or better)
++	 * states into any of the down states (except link recovery), then
++	 * call the chip-specific code to take appropriate actions.
+ 	 */
+-	if ((lstate != IPATH_IBSTATE_ARM && lstate != IPATH_IBSTATE_ACTIVE)
+-		&& (dd->ipath_flags & (IPATH_LINKARMED | IPATH_LINKACTIVE))) {
+-		dev_info(&dd->pcidev->dev, "Link state changed from %s to %s\n",
+-				 (dd->ipath_flags & IPATH_LINKARMED) ? "ARM" : "ACTIVE",
+-				 ib_linkstate(lstate));
+-		/*
+-		 * Flush all queued sends when link went to DOWN or INIT,
+-		 * to be sure that they don't block SMA and other MAD packets
+-		 */
+-		ipath_cancel_sends(dd, 1);
+-	}
+-	else if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM ||
+-	    lstate == IPATH_IBSTATE_ACTIVE) {
+-		/*
+-		 * only print at SMA if there is a change, debug if not
+-		 * (sometimes we want to know that, usually not).
+-		 */
+-		if (lstate == ((unsigned) dd->ipath_lastibcstat
+-			       & IPATH_IBSTATE_MASK)) {
+-			ipath_dbg("Status change intr but no change (%s)\n",
+-				  ib_linkstate(lstate));
++	if (lstate >= INFINIPATH_IBCS_L_STATE_INIT &&
++		lastlstate == INFINIPATH_IBCS_L_STATE_DOWN) {
++		/* transitioned to UP */
++		if (dd->ipath_f_ib_updown(dd, 1, ibcs)) {
++			/* link came up, so we must no longer be disabled */
++			dd->ipath_flags &= ~IPATH_IB_LINK_DISABLED;
++			ipath_cdbg(LINKVERB, "LinkUp handled, skipped\n");
++			goto skip_ibchange; /* chip-code handled */
++		}
++	} else if ((lastlstate >= INFINIPATH_IBCS_L_STATE_INIT ||
++		(dd->ipath_flags & IPATH_IB_FORCE_NOTIFY)) &&
++		ltstate <= INFINIPATH_IBCS_LT_STATE_CFGWAITRMT &&
++		ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
++		int handled;
++		handled = dd->ipath_f_ib_updown(dd, 0, ibcs);
++		dd->ipath_flags &= ~IPATH_IB_FORCE_NOTIFY;
++		if (handled) {
++			ipath_cdbg(LINKVERB, "LinkDown handled, skipped\n");
++			goto skip_ibchange; /* chip-code handled */
+ 		}
+-		else
+-			ipath_cdbg(VERBOSE, "Unit %u link state %s, last "
+-				   "was %s\n", dd->ipath_unit,
+-				   ib_linkstate(lstate),
+-				   ib_linkstate((unsigned)
+-						dd->ipath_lastibcstat
+-						& IPATH_IBSTATE_MASK));
+ 	}
+-	else {
+-		lstate = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+-		if (lstate == IPATH_IBSTATE_INIT ||
+-		    lstate == IPATH_IBSTATE_ARM ||
+-		    lstate == IPATH_IBSTATE_ACTIVE)
+-			ipath_cdbg(VERBOSE, "Unit %u link state down"
+-				   " (state 0x%x), from %s\n",
+-				   dd->ipath_unit,
+-				   (u32)val & IPATH_IBSTATE_MASK,
+-				   ib_linkstate(lstate));
+-		else
+-			ipath_cdbg(VERBOSE, "Unit %u link state changed "
+-				   "to 0x%x from down (%x)\n",
+-				   dd->ipath_unit, (u32) val, lstate);
++
++	/*
++	 * Significant enough to always print and get into logs, if it was
++	 * unexpected.  If it was a requested state change, we'll have
++	 * already cleared the flags, so we won't print this warning
++	 */
++	if ((ibstate != arm && ibstate != active) &&
++	    (dd->ipath_flags & (IPATH_LINKARMED | IPATH_LINKACTIVE))) {
++		dev_info(&dd->pcidev->dev, "Link state changed from %s "
++			 "to %s\n", (dd->ipath_flags & IPATH_LINKARMED) ?
++			 "ARM" : "ACTIVE", ib_linkstate(dd, ibcs));
+ 	}
+-	ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+-		INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+-	lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+-		INFINIPATH_IBCS_LINKSTATE_MASK;
+ 
+ 	if (ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE ||
+ 	    ltstate == INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+-		u32 last_ltstate;
+-
++		u32 lastlts;
++		lastlts = ipath_ib_linktrstate(dd, dd->ipath_lastibcstat);
+ 		/*
+-		 * Ignore cycling back and forth from Polling.Active
+-		 * to Polling.Quiet while waiting for the other end of
+-		 * the link to come up. We will cycle back and forth
+-		 * between them if no cable is plugged in,
+-		 * the other device is powered off or disabled, etc.
++		 * Ignore cycling back and forth from Polling.Active to
++		 * Polling.Quiet while waiting for the other end of the link
++		 * to come up, except to try and decide if we are connected
++		 * to a live IB device or not.  We will cycle back and
++		 * forth between them if no cable is plugged in, the other
++		 * device is powered off or disabled, etc.
+ 		 */
+-		last_ltstate = (dd->ipath_lastibcstat >>
+-				INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT)
+-			& INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+-		if (last_ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE
+-		    || last_ltstate ==
+-		    INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+-			if (dd->ipath_ibpollcnt > 40) {
++		if (lastlts == INFINIPATH_IBCS_LT_STATE_POLLACTIVE ||
++		    lastlts == INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
++			if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) &&
++			     (++dd->ipath_ibpollcnt == 40)) {
+ 				dd->ipath_flags |= IPATH_NOCABLE;
+ 				*dd->ipath_statusp |=
+ 					IPATH_STATUS_IB_NOCABLE;
+-			} else
+-				dd->ipath_ibpollcnt++;
++				ipath_cdbg(LINKVERB, "Set NOCABLE\n");
++			}
++			ipath_cdbg(LINKVERB, "POLL change to %s (%x)\n",
++				ipath_ibcstatus_str[ltstate], ibstate);
+ 			goto skip_ibchange;
+ 		}
+ 	}
+-	dd->ipath_ibpollcnt = 0;	/* some state other than 2 or 3 */
++
++	dd->ipath_ibpollcnt = 0; /* not poll*, now */
+ 	ipath_stats.sps_iblink++;
+-	if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
++
++	if (ibstate != init && dd->ipath_lastlinkrecov && ipath_linkrecovery) {
++		u64 linkrecov;
++		linkrecov = ipath_snap_cntr(dd,
++			dd->ipath_cregs->cr_iblinkerrrecovcnt);
++		if (linkrecov != dd->ipath_lastlinkrecov) {
++			ipath_dbg("IB linkrecov up %Lx (%s %s) recov %Lu\n",
++				ibcs, ib_linkstate(dd, ibcs),
++				ipath_ibcstatus_str[ltstate],
++				linkrecov);
++			/* and no more until active again */
++			dd->ipath_lastlinkrecov = 0;
++			ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);
++			goto skip_ibchange;
++		}
++	}
++
++	if (ibstate == init || ibstate == arm || ibstate == active) {
++		*dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE;
++		if (ibstate == init || ibstate == arm) {
++			*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
++			if (dd->ipath_flags & IPATH_LINKACTIVE)
++				signal_ib_event(dd, IB_EVENT_PORT_ERR);
++		}
++		if (ibstate == arm) {
++			dd->ipath_flags |= IPATH_LINKARMED;
++			dd->ipath_flags &= ~(IPATH_LINKUNK |
++				IPATH_LINKINIT | IPATH_LINKDOWN |
++				IPATH_LINKACTIVE | IPATH_NOCABLE);
++			ipath_hol_down(dd);
++		} else  if (ibstate == init) {
++			/*
++			 * set INIT and DOWN.  Down is checked by
++			 * most of the other code, but INIT is
++			 * useful to know in a few places.
++			 */
++			dd->ipath_flags |= IPATH_LINKINIT |
++				IPATH_LINKDOWN;
++			dd->ipath_flags &= ~(IPATH_LINKUNK |
++				IPATH_LINKARMED | IPATH_LINKACTIVE |
++				IPATH_NOCABLE);
++			ipath_hol_down(dd);
++		} else {  /* active */
++			dd->ipath_lastlinkrecov = ipath_snap_cntr(dd,
++				dd->ipath_cregs->cr_iblinkerrrecovcnt);
++			*dd->ipath_statusp |=
++				IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
++			dd->ipath_flags |= IPATH_LINKACTIVE;
++			dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
++				| IPATH_LINKDOWN | IPATH_LINKARMED |
++				IPATH_NOCABLE);
++			if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++				ipath_restart_sdma(dd);
++			signal_ib_event(dd, IB_EVENT_PORT_ACTIVE);
++			/* LED active not handled in chip _f_updown */
++			dd->ipath_f_setextled(dd, lstate, ltstate);
++			ipath_hol_up(dd);
++		}
++
++		/*
++		 * print after we've already done the work, so as not to
++		 * delay the state changes and notifications, for debugging
++		 */
++		if (lstate == lastlstate)
++			ipath_cdbg(LINKVERB, "Unchanged from last: %s "
++				"(%x)\n", ib_linkstate(dd, ibcs), ibstate);
++		else
++			ipath_cdbg(VERBOSE, "Unit %u: link up to %s %s (%x)\n",
++				  dd->ipath_unit, ib_linkstate(dd, ibcs),
++				  ipath_ibcstatus_str[ltstate],  ibstate);
++	} else { /* down */
+ 		if (dd->ipath_flags & IPATH_LINKACTIVE)
+ 			signal_ib_event(dd, IB_EVENT_PORT_ERR);
+ 		dd->ipath_flags |= IPATH_LINKDOWN;
+@@ -391,69 +461,28 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
+ 				     IPATH_LINKARMED);
+ 		*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ 		dd->ipath_lli_counter = 0;
+-		if (!noprint) {
+-			if (((dd->ipath_lastibcstat >>
+-			      INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+-			     INFINIPATH_IBCS_LINKSTATE_MASK)
+-			    == INFINIPATH_IBCS_L_STATE_ACTIVE)
+-				/* if from up to down be more vocal */
+-				ipath_cdbg(VERBOSE,
+-					   "Unit %u link now down (%s)\n",
+-					   dd->ipath_unit,
+-					   ipath_ibcstatus_str[ltstate]);
+-			else
+-				ipath_cdbg(VERBOSE, "Unit %u link is "
+-					   "down (%s)\n", dd->ipath_unit,
+-					   ipath_ibcstatus_str[ltstate]);
+-		}
+ 
+-		dd->ipath_f_setextled(dd, lstate, ltstate);
+-	} else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ACTIVE) {
+-		dd->ipath_flags |= IPATH_LINKACTIVE;
+-		dd->ipath_flags &=
+-			~(IPATH_LINKUNK | IPATH_LINKINIT | IPATH_LINKDOWN |
+-			  IPATH_LINKARMED | IPATH_NOCABLE);
+-		*dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE;
+-		*dd->ipath_statusp |=
+-			IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
+-		dd->ipath_f_setextled(dd, lstate, ltstate);
+-		signal_ib_event(dd, IB_EVENT_PORT_ACTIVE);
+-	} else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) {
+-		if (dd->ipath_flags & IPATH_LINKACTIVE)
+-			signal_ib_event(dd, IB_EVENT_PORT_ERR);
+-		/*
+-		 * set INIT and DOWN.  Down is checked by most of the other
+-		 * code, but INIT is useful to know in a few places.
+-		 */
+-		dd->ipath_flags |= IPATH_LINKINIT | IPATH_LINKDOWN;
+-		dd->ipath_flags &=
+-			~(IPATH_LINKUNK | IPATH_LINKACTIVE | IPATH_LINKARMED
+-			  | IPATH_NOCABLE);
+-		*dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+-					| IPATH_STATUS_IB_READY);
+-		dd->ipath_f_setextled(dd, lstate, ltstate);
+-	} else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) {
+-		if (dd->ipath_flags & IPATH_LINKACTIVE)
+-			signal_ib_event(dd, IB_EVENT_PORT_ERR);
+-		dd->ipath_flags |= IPATH_LINKARMED;
+-		dd->ipath_flags &=
+-			~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT |
+-			  IPATH_LINKACTIVE | IPATH_NOCABLE);
+-		*dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+-					| IPATH_STATUS_IB_READY);
+-		dd->ipath_f_setextled(dd, lstate, ltstate);
+-	} else {
+-		if (!noprint)
+-			ipath_dbg("IBstatuschange unit %u: %s (%x)\n",
+-				  dd->ipath_unit,
+-				  ipath_ibcstatus_str[ltstate], ltstate);
++		if (lastlstate != INFINIPATH_IBCS_L_STATE_DOWN)
++			ipath_cdbg(VERBOSE, "Unit %u link state down "
++				   "(state 0x%x), from %s\n",
++				   dd->ipath_unit, lstate,
++				   ib_linkstate(dd, dd->ipath_lastibcstat));
++		else
++			ipath_cdbg(LINKVERB, "Unit %u link state changed "
++				   "to %s (0x%x) from down (%x)\n",
++				   dd->ipath_unit,
++				   ipath_ibcstatus_str[ltstate],
++				   ibstate, lastlstate);
+ 	}
++
+ skip_ibchange:
+-	dd->ipath_lastibcstat = val;
++	dd->ipath_lastibcstat = ibcs;
++done:
++	return;
+ }
+ 
+ static void handle_supp_msgs(struct ipath_devdata *dd,
+-			     unsigned supp_msgs, char *msg, int msgsz)
++			     unsigned supp_msgs, char *msg, u32 msgsz)
+ {
+ 	/*
+ 	 * Print the message unless it's ibc status change only, which
+@@ -461,12 +490,19 @@ static void handle_supp_msgs(struct ipath_devdata *dd,
+ 	 */
+ 	if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) {
+ 		int iserr;
+-		iserr = ipath_decode_err(msg, msgsz,
++		ipath_err_t mask;
++		iserr = ipath_decode_err(dd, msg, msgsz,
+ 					 dd->ipath_lasterror &
+ 					 ~INFINIPATH_E_IBSTATUSCHANGED);
+-		if (dd->ipath_lasterror &
+-			~(INFINIPATH_E_RRCVEGRFULL |
+-			INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS))
++
++		mask = INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
++			INFINIPATH_E_PKTERRS | INFINIPATH_E_SDMADISABLED;
++
++		/* if we're in debug, then don't mask SDMADISABLED msgs */
++		if (ipath_debug & __IPATH_DBG)
++			mask &= ~INFINIPATH_E_SDMADISABLED;
++
++		if (dd->ipath_lasterror & ~mask)
+ 			ipath_dev_err(dd, "Suppressed %u messages for "
+ 				      "fast-repeating errors (%s) (%llx)\n",
+ 				      supp_msgs, msg,
+@@ -493,7 +529,7 @@ static void handle_supp_msgs(struct ipath_devdata *dd,
+ 
+ static unsigned handle_frequent_errors(struct ipath_devdata *dd,
+ 				       ipath_err_t errs, char *msg,
+-				       int msgsz, int *noprint)
++				       u32 msgsz, int *noprint)
+ {
+ 	unsigned long nc;
+ 	static unsigned long nextmsg_time;
+@@ -523,19 +559,125 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd,
+ 	return supp_msgs;
+ }
+ 
++static void handle_sdma_errors(struct ipath_devdata *dd, ipath_err_t errs)
++{
++	unsigned long flags;
++	int expected;
++
++	if (ipath_debug & __IPATH_DBG) {
++		char msg[128];
++		ipath_decode_err(dd, msg, sizeof msg, errs &
++			INFINIPATH_E_SDMAERRS);
++		ipath_dbg("errors %lx (%s)\n", (unsigned long)errs, msg);
++	}
++	if (ipath_debug & __IPATH_VERBDBG) {
++		unsigned long tl, hd, status, lengen;
++		tl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmatail);
++		hd = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmahead);
++		status = ipath_read_kreg64(dd
++			, dd->ipath_kregs->kr_senddmastatus);
++		lengen = ipath_read_kreg64(dd,
++			dd->ipath_kregs->kr_senddmalengen);
++		ipath_cdbg(VERBOSE, "sdma tl 0x%lx hd 0x%lx status 0x%lx "
++			"lengen 0x%lx\n", tl, hd, status, lengen);
++	}
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++	__set_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status);
++	expected = test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status);
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++	if (!expected)
++		ipath_cancel_sends(dd, 1);
++}
++
++static void handle_sdma_intr(struct ipath_devdata *dd, u64 istat)
++{
++	unsigned long flags;
++	int expected;
++
++	if ((istat & INFINIPATH_I_SDMAINT) &&
++	    !test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++		ipath_sdma_intr(dd);
++
++	if (istat & INFINIPATH_I_SDMADISABLED) {
++		expected = test_bit(IPATH_SDMA_ABORTING,
++			&dd->ipath_sdma_status);
++		ipath_dbg("%s SDmaDisabled intr\n",
++			expected ? "expected" : "unexpected");
++		spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++		__set_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status);
++		spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++		if (!expected)
++			ipath_cancel_sends(dd, 1);
++		if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++			tasklet_hi_schedule(&dd->ipath_sdma_abort_task);
++	}
++}
++
++static int handle_hdrq_full(struct ipath_devdata *dd)
++{
++	int chkerrpkts = 0;
++	u32 hd, tl;
++	u32 i;
++
++	ipath_stats.sps_hdrqfull++;
++	for (i = 0; i < dd->ipath_cfgports; i++) {
++		struct ipath_portdata *pd = dd->ipath_pd[i];
++
++		if (i == 0) {
++			/*
++			 * For kernel receive queues, we just want to know
++			 * if there are packets in the queue that we can
++			 * process.
++			 */
++			if (pd->port_head != ipath_get_hdrqtail(pd))
++				chkerrpkts |= 1 << i;
++			continue;
++		}
++
++		/* Skip if user context is not open */
++		if (!pd || !pd->port_cnt)
++			continue;
++
++		/* Don't report the same point multiple times. */
++		if (dd->ipath_flags & IPATH_NODMA_RTAIL)
++			tl = ipath_read_ureg32(dd, ur_rcvhdrtail, i);
++		else
++			tl = ipath_get_rcvhdrtail(pd);
++		if (tl == pd->port_lastrcvhdrqtail)
++			continue;
++
++		hd = ipath_read_ureg32(dd, ur_rcvhdrhead, i);
++		if (hd == (tl + 1) || (!hd && tl == dd->ipath_hdrqlast)) {
++			pd->port_lastrcvhdrqtail = tl;
++			pd->port_hdrqfull++;
++			/* flush hdrqfull so that poll() sees it */
++			wmb();
++			wake_up_interruptible(&pd->port_wait);
++		}
++	}
++
++	return chkerrpkts;
++}
++
+ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ {
+ 	char msg[128];
+ 	u64 ignore_this_time = 0;
+-	int i, iserr = 0;
++	u64 iserr = 0;
+ 	int chkerrpkts = 0, noprint = 0;
+ 	unsigned supp_msgs;
+ 	int log_idx;
+ 
+-	supp_msgs = handle_frequent_errors(dd, errs, msg, sizeof msg, &noprint);
++	/*
++	 * don't report errors that are masked, either at init
++	 * (not set in ipath_errormask), or temporarily (set in
++	 * ipath_maskederrs)
++	 */
++	errs &= dd->ipath_errormask & ~dd->ipath_maskederrs;
+ 
+-	/* don't report errors that are masked */
+-	errs &= ~dd->ipath_maskederrs;
++	supp_msgs = handle_frequent_errors(dd, errs, msg, (u32)sizeof msg,
++		&noprint);
+ 
+ 	/* do these first, they are most important */
+ 	if (errs & INFINIPATH_E_HARDWARE) {
+@@ -550,6 +692,9 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 		}
+ 	}
+ 
++	if (errs & INFINIPATH_E_SDMAERRS)
++		handle_sdma_errors(dd, errs);
++
+ 	if (!noprint && (errs & ~dd->ipath_e_bitsextant))
+ 		ipath_dev_err(dd, "error interrupt with unknown errors "
+ 			      "%llx set\n", (unsigned long long)
+@@ -580,18 +725,19 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 		 * ones on this particular interrupt, which also isn't great
+ 		 */
+ 		dd->ipath_maskederrs |= dd->ipath_lasterror | errs;
++
+ 		dd->ipath_errormask &= ~dd->ipath_maskederrs;
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+-			dd->ipath_errormask);
+-		s_iserr = ipath_decode_err(msg, sizeof msg,
+-			dd->ipath_maskederrs);
++				 dd->ipath_errormask);
++		s_iserr = ipath_decode_err(dd, msg, sizeof msg,
++					   dd->ipath_maskederrs);
+ 
+ 		if (dd->ipath_maskederrs &
+-			~(INFINIPATH_E_RRCVEGRFULL |
+-			INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS))
++		    ~(INFINIPATH_E_RRCVEGRFULL |
++		      INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS))
+ 			ipath_dev_err(dd, "Temporarily disabling "
+ 			    "error(s) %llx reporting; too frequent (%s)\n",
+-				(unsigned long long)dd->ipath_maskederrs,
++				(unsigned long long) dd->ipath_maskederrs,
+ 				msg);
+ 		else {
+ 			/*
+@@ -633,26 +779,43 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 			  INFINIPATH_E_IBSTATUSCHANGED);
+ 	}
+ 
+-	/* likely due to cancel, so suppress */
++	if (errs & INFINIPATH_E_SENDSPECIALTRIGGER) {
++		dd->ipath_spectriggerhit++;
++		ipath_dbg("%lu special trigger hits\n",
++			dd->ipath_spectriggerhit);
++	}
++
++	/* likely due to cancel; so suppress message unless verbose */
+ 	if ((errs & (INFINIPATH_E_SPKTLEN | INFINIPATH_E_SPIOARMLAUNCH)) &&
+ 		dd->ipath_lastcancel > jiffies) {
+-		ipath_dbg("Suppressed armlaunch/spktlen after error send cancel\n");
++		/* armlaunch takes precedence; it often causes both. */
++		ipath_cdbg(VERBOSE,
++			"Suppressed %s error (%llx) after sendbuf cancel\n",
++			(errs &  INFINIPATH_E_SPIOARMLAUNCH) ?
++			"armlaunch" : "sendpktlen", (unsigned long long)errs);
+ 		errs &= ~(INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SPKTLEN);
+ 	}
+ 
+ 	if (!errs)
+ 		return 0;
+ 
+-	if (!noprint)
++	if (!noprint) {
++		ipath_err_t mask;
+ 		/*
+-		 * the ones we mask off are handled specially below or above
++		 * The ones we mask off are handled specially below
++		 * or above.  Also mask SDMADISABLED by default as it
++		 * is too chatty.
+ 		 */
+-		ipath_decode_err(msg, sizeof msg,
+-				 errs & ~(INFINIPATH_E_IBSTATUSCHANGED |
+-					  INFINIPATH_E_RRCVEGRFULL |
+-					  INFINIPATH_E_RRCVHDRFULL |
+-					  INFINIPATH_E_HARDWARE));
+-	else
++		mask = INFINIPATH_E_IBSTATUSCHANGED |
++			INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
++			INFINIPATH_E_HARDWARE | INFINIPATH_E_SDMADISABLED;
++
++		/* if we're in debug, then don't mask SDMADISABLED msgs */
++		if (ipath_debug & __IPATH_DBG)
++			mask &= ~INFINIPATH_E_SDMADISABLED;
++
++		ipath_decode_err(dd, msg, sizeof msg, errs & ~mask);
++	} else
+ 		/* so we don't need if (!noprint) at strlcat's below */
+ 		*msg = 0;
+ 
+@@ -677,40 +840,8 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 	 * fast_stats, no more than every 5 seconds, user ports get printed
+ 	 * on close
+ 	 */
+-	if (errs & INFINIPATH_E_RRCVHDRFULL) {
+-		u32 hd, tl;
+-		ipath_stats.sps_hdrqfull++;
+-		for (i = 0; i < dd->ipath_cfgports; i++) {
+-			struct ipath_portdata *pd = dd->ipath_pd[i];
+-			if (i == 0) {
+-				hd = pd->port_head;
+-				tl = (u32) le64_to_cpu(
+-					*dd->ipath_hdrqtailptr);
+-			} else if (pd && pd->port_cnt &&
+-				   pd->port_rcvhdrtail_kvaddr) {
+-				/*
+-				 * don't report same point multiple times,
+-				 * except kernel
+-				 */
+-				tl = *(u64 *) pd->port_rcvhdrtail_kvaddr;
+-				if (tl == pd->port_lastrcvhdrqtail)
+-					continue;
+-				hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
+-						       i);
+-			} else
+-				continue;
+-			if (hd == (tl + 1) ||
+-			    (!hd && tl == dd->ipath_hdrqlast)) {
+-				if (i == 0)
+-					chkerrpkts = 1;
+-				pd->port_lastrcvhdrqtail = tl;
+-				pd->port_hdrqfull++;
+-				/* flush hdrqfull so that poll() sees it */
+-				wmb();
+-				wake_up_interruptible(&pd->port_wait);
+-			}
+-		}
+-	}
++	if (errs & INFINIPATH_E_RRCVHDRFULL)
++		chkerrpkts |= handle_hdrq_full(dd);
+ 	if (errs & INFINIPATH_E_RRCVEGRFULL) {
+ 		struct ipath_portdata *pd = dd->ipath_pd[0];
+ 
+@@ -721,9 +852,8 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 		 * vs user)
+ 		 */
+ 		ipath_stats.sps_etidfull++;
+-		if (pd->port_head !=
+-		    (u32) le64_to_cpu(*dd->ipath_hdrqtailptr))
+-			chkerrpkts = 1;
++		if (pd->port_head != ipath_get_hdrqtail(pd))
++			chkerrpkts |= 1;
+ 	}
+ 
+ 	/*
+@@ -741,16 +871,13 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 		dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
+ 				     | IPATH_LINKARMED | IPATH_LINKACTIVE);
+ 		*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+-		if (!noprint) {
+-			u64 st = ipath_read_kreg64(
+-				dd, dd->ipath_kregs->kr_ibcstatus);
+ 
+-			ipath_dbg("Lost link, link now down (%s)\n",
+-				  ipath_ibcstatus_str[st & 0xf]);
+-		}
++		ipath_dbg("Lost link, link now down (%s)\n",
++			ipath_ibcstatus_str[ipath_read_kreg64(dd,
++			dd->ipath_kregs->kr_ibcstatus) & 0xf]);
+ 	}
+ 	if (errs & INFINIPATH_E_IBSTATUSCHANGED)
+-		handle_e_ibstatuschanged(dd, errs, noprint);
++		handle_e_ibstatuschanged(dd, errs);
+ 
+ 	if (errs & INFINIPATH_E_RESET) {
+ 		if (!noprint)
+@@ -765,9 +892,6 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 	if (!noprint && *msg) {
+ 		if (iserr)
+ 			ipath_dev_err(dd, "%s error\n", msg);
+-		else
+-			dev_info(&dd->pcidev->dev, "%s packet problems\n",
+-				msg);
+ 	}
+ 	if (dd->ipath_state_wanted & dd->ipath_flags) {
+ 		ipath_cdbg(VERBOSE, "driver wanted state %x, iflags now %x, "
+@@ -779,7 +903,6 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 	return chkerrpkts;
+ }
+ 
+-
+ /*
+  * try to cleanup as much as possible for anything that might have gone
+  * wrong while in freeze mode, such as pio buffers being written by user
+@@ -796,8 +919,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ void ipath_clear_freeze(struct ipath_devdata *dd)
+ {
+ 	int i, im;
+-	__le64 val;
+-	unsigned long flags;
++	u64 val;
+ 
+ 	/* disable error interrupts, to avoid confusion */
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
+@@ -816,14 +938,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
+ 			 dd->ipath_control);
+ 
+ 	/* ensure pio avail updates continue */
+-	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-		 dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
+-	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-			 dd->ipath_sendctrl);
+-	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+-	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++	ipath_force_pio_avail_update(dd);
+ 
+ 	/*
+ 	 * We just enabled pioavailupdate, so dma copy is almost certainly
+@@ -831,10 +946,13 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
+ 	 */
+ 	for (i = 0; i < dd->ipath_pioavregs; i++) {
+ 		/* deal with 6110 chip bug */
+-		im = i > 3 ? i ^ 1 : i;
++		im = (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS)) ?
++			i ^ 1 : i;
+ 		val = ipath_read_kreg64(dd, (0x1000 / sizeof(u64)) + im);
+-		dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
+-			= le64_to_cpu(val);
++		dd->ipath_pioavailregs_dma[i] = cpu_to_le64(val);
++		dd->ipath_pioavailshadow[i] = val |
++			(~dd->ipath_pioavailkernel[i] <<
++			INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT);
+ 	}
+ 
+ 	/*
+@@ -950,7 +1068,7 @@ set:
+  * process was waiting for a packet to arrive, and didn't want
+  * to poll
+  */
+-static void handle_urcv(struct ipath_devdata *dd, u32 istat)
++static void handle_urcv(struct ipath_devdata *dd, u64 istat)
+ {
+ 	u64 portr;
+ 	int i;
+@@ -966,12 +1084,13 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ 	 * and ipath_poll_next()...
+ 	 */
+ 	rmb();
+-	portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
+-		 dd->ipath_i_rcvavail_mask)
+-		| ((istat >> INFINIPATH_I_RCVURG_SHIFT) &
+-		   dd->ipath_i_rcvurg_mask);
++	portr = ((istat >> dd->ipath_i_rcvavail_shift) &
++		 dd->ipath_i_rcvavail_mask) |
++		((istat >> dd->ipath_i_rcvurg_shift) &
++		 dd->ipath_i_rcvurg_mask);
+ 	for (i = 1; i < dd->ipath_cfgports; i++) {
+ 		struct ipath_portdata *pd = dd->ipath_pd[i];
++
+ 		if (portr & (1 << i) && pd && pd->port_cnt) {
+ 			if (test_and_clear_bit(IPATH_PORT_WAITING_RCV,
+ 					       &pd->port_flag)) {
+@@ -988,7 +1107,7 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ 	}
+ 	if (rcvdint) {
+ 		/* only want to take one interrupt, so turn off the rcv
+-		 * interrupt for all the ports that we did the wakeup on
++		 * interrupt for all the ports that we set the rcv_waiting
+ 		 * (but never for kernel port)
+ 		 */
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+@@ -999,12 +1118,11 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ irqreturn_t ipath_intr(int irq, void *data)
+ {
+ 	struct ipath_devdata *dd = data;
+-	u32 istat, chk0rcv = 0;
++	u64 istat, chk0rcv = 0;
+ 	ipath_err_t estat = 0;
+ 	irqreturn_t ret;
+ 	static unsigned unexpected = 0;
+-	static const u32 port0rbits = (1U<<INFINIPATH_I_RCVAVAIL_SHIFT) |
+-		 (1U<<INFINIPATH_I_RCVURG_SHIFT);
++	u64 kportrbits;
+ 
+ 	ipath_stats.sps_ints++;
+ 
+@@ -1053,17 +1171,17 @@ irqreturn_t ipath_intr(int irq, void *data)
+ 
+ 	if (unlikely(istat & ~dd->ipath_i_bitsextant))
+ 		ipath_dev_err(dd,
+-			      "interrupt with unknown interrupts %x set\n",
+-			      istat & (u32) ~ dd->ipath_i_bitsextant);
+-	else
+-		ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat);
++			      "interrupt with unknown interrupts %Lx set\n",
++			      istat & ~dd->ipath_i_bitsextant);
++	else if (istat & ~INFINIPATH_I_ERROR) /* errors do own printing */
++		ipath_cdbg(VERBOSE, "intr stat=0x%Lx\n", istat);
+ 
+-	if (unlikely(istat & INFINIPATH_I_ERROR)) {
++	if (istat & INFINIPATH_I_ERROR) {
+ 		ipath_stats.sps_errints++;
+ 		estat = ipath_read_kreg64(dd,
+ 					  dd->ipath_kregs->kr_errorstatus);
+ 		if (!estat)
+-			dev_info(&dd->pcidev->dev, "error interrupt (%x), "
++			dev_info(&dd->pcidev->dev, "error interrupt (%Lx), "
+ 				 "but no error bits set!\n", istat);
+ 		else if (estat == -1LL)
+ 			/*
+@@ -1073,9 +1191,7 @@ irqreturn_t ipath_intr(int irq, void *data)
+ 			ipath_dev_err(dd, "Read of error status failed "
+ 				      "(all bits set); ignoring\n");
+ 		else
+-			if (handle_errors(dd, estat))
+-				/* force calling ipath_kreceive() */
+-				chk0rcv = 1;
++			chk0rcv |= handle_errors(dd, estat);
+ 	}
+ 
+ 	if (istat & INFINIPATH_I_GPIO) {
+@@ -1093,8 +1209,7 @@ irqreturn_t ipath_intr(int irq, void *data)
+ 
+ 		gpiostatus = ipath_read_kreg32(
+ 			dd, dd->ipath_kregs->kr_gpio_status);
+-		/* First the error-counter case.
+-		 */
++		/* First the error-counter case. */
+ 		if ((gpiostatus & IPATH_GPIO_ERRINTR_MASK) &&
+ 		    (dd->ipath_flags & IPATH_GPIO_ERRINTRS)) {
+ 			/* want to clear the bits we see asserted. */
+@@ -1156,7 +1271,6 @@ irqreturn_t ipath_intr(int irq, void *data)
+ 					(u64) to_clear);
+ 		}
+ 	}
+-	chk0rcv |= istat & port0rbits;
+ 
+ 	/*
+ 	 * Clear the interrupt bits we found set, unless they are receive
+@@ -1169,22 +1283,25 @@ irqreturn_t ipath_intr(int irq, void *data)
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat);
+ 
+ 	/*
+-	 * handle port0 receive  before checking for pio buffers available,
+-	 * since receives can overflow; piobuf waiters can afford a few
+-	 * extra cycles, since they were waiting anyway, and user's waiting
+-	 * for receive are at the bottom.
++	 * Handle kernel receive queues before checking for pio buffers
++	 * available since receives can overflow; piobuf waiters can afford
++	 * a few extra cycles, since they were waiting anyway, and user's
++	 * waiting for receive are at the bottom.
+ 	 */
+-	if (chk0rcv) {
++	kportrbits = (1ULL << dd->ipath_i_rcvavail_shift) |
++		(1ULL << dd->ipath_i_rcvurg_shift);
++	if (chk0rcv || (istat & kportrbits)) {
++		istat &= ~kportrbits;
+ 		ipath_kreceive(dd->ipath_pd[0]);
+-		istat &= ~port0rbits;
+ 	}
+ 
+-	if (istat & ((dd->ipath_i_rcvavail_mask <<
+-		      INFINIPATH_I_RCVAVAIL_SHIFT)
+-		     | (dd->ipath_i_rcvurg_mask <<
+-			INFINIPATH_I_RCVURG_SHIFT)))
++	if (istat & ((dd->ipath_i_rcvavail_mask << dd->ipath_i_rcvavail_shift) |
++		     (dd->ipath_i_rcvurg_mask << dd->ipath_i_rcvurg_shift)))
+ 		handle_urcv(dd, istat);
+ 
++	if (istat & (INFINIPATH_I_SDMAINT | INFINIPATH_I_SDMADISABLED))
++		handle_sdma_intr(dd, istat);
++
+ 	if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
+ 		unsigned long flags;
+ 
+@@ -1195,7 +1312,10 @@ irqreturn_t ipath_intr(int irq, void *data)
+ 		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ 		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ 
+-		handle_layer_pioavail(dd);
++		if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA))
++			handle_layer_pioavail(dd);
++		else
++			ipath_dbg("unexpected BUFAVAIL intr\n");
+ 	}
+ 
+ 	ret = IRQ_HANDLED;
+diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
+index ecf3f7f..202337a 100644
+--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
++++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
+@@ -1,7 +1,7 @@
+ #ifndef _IPATH_KERNEL_H
+ #define _IPATH_KERNEL_H
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -42,6 +42,8 @@
+ #include <linux/pci.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/mutex.h>
++#include <linux/list.h>
++#include <linux/scatterlist.h>
+ #include <asm/io.h>
+ #include <rdma/ib_verbs.h>
+ 
+@@ -175,9 +177,13 @@ struct ipath_portdata {
+ 	u16 poll_type;
+ 	/* port rcvhdrq head offset */
+ 	u32 port_head;
++	/* receive packet sequence counter */
++	u32 port_seq_cnt;
+ };
+ 
+ struct sk_buff;
++struct ipath_sge_state;
++struct ipath_verbs_txreq;
+ 
+ /*
+  * control information for layered drivers
+@@ -191,6 +197,40 @@ struct ipath_skbinfo {
+ 	dma_addr_t phys;
+ };
+ 
++struct ipath_sdma_txreq {
++	int                 flags;
++	int                 sg_count;
++	union {
++		struct scatterlist *sg;
++		void *map_addr;
++	};
++	void              (*callback)(void *, int);
++	void               *callback_cookie;
++	int                 callback_status;
++	u16                 start_idx;  /* sdma private */
++	u16                 next_descq_idx;  /* sdma private */
++	struct list_head    list;       /* sdma private */
++};
++
++struct ipath_sdma_desc {
++	__le64 qw[2];
++};
++
++#define IPATH_SDMA_TXREQ_F_USELARGEBUF  0x1
++#define IPATH_SDMA_TXREQ_F_HEADTOHOST   0x2
++#define IPATH_SDMA_TXREQ_F_INTREQ       0x4
++#define IPATH_SDMA_TXREQ_F_FREEBUF      0x8
++#define IPATH_SDMA_TXREQ_F_FREEDESC     0x10
++#define IPATH_SDMA_TXREQ_F_VL15         0x20
++
++#define IPATH_SDMA_TXREQ_S_OK        0
++#define IPATH_SDMA_TXREQ_S_SENDERROR 1
++#define IPATH_SDMA_TXREQ_S_ABORTED   2
++#define IPATH_SDMA_TXREQ_S_SHUTDOWN  3
++
++/* max dwords in small buffer packet */
++#define IPATH_SMALLBUF_DWORDS (dd->ipath_piosize2k >> 2)
++
+ /*
+  * Possible IB config parameters for ipath_f_get/set_ib_cfg()
+  */
+@@ -221,11 +261,6 @@ struct ipath_devdata {
+ 	unsigned long ipath_physaddr;
+ 	/* base of memory alloced for ipath_kregbase, for free */
+ 	u64 *ipath_kregalloc;
+-	/*
+-	 * virtual address where port0 rcvhdrqtail updated for this unit.
+-	 * only written to by the chip, not the driver.
+-	 */
+-	volatile __le64 *ipath_hdrqtailptr;
+ 	/* ipath_cfgports pointers */
+ 	struct ipath_portdata **ipath_pd;
+ 	/* sk_buffs used by port 0 eager receive queue */
+@@ -283,6 +318,7 @@ struct ipath_devdata {
+ 	/* per chip actions needed for IB Link up/down changes */
+ 	int (*ipath_f_ib_updown)(struct ipath_devdata *, int, u64);
+ 
++	unsigned ipath_lastegr_idx;
+ 	struct ipath_ibdev *verbs_dev;
+ 	struct timer_list verbs_timer;
+ 	/* total dwords sent (summed from counter) */
+@@ -309,6 +345,7 @@ struct ipath_devdata {
+ 	ipath_err_t ipath_lasthwerror;
+ 	/* errors masked because they occur too fast */
+ 	ipath_err_t ipath_maskederrs;
++	u64 ipath_lastlinkrecov; /* link recoveries at last ACTIVE */
+ 	/* time in jiffies at which to re-enable maskederrs */
+ 	unsigned long ipath_unmasktime;
+ 	/* count of egrfull errors, combined for all ports */
+@@ -347,6 +384,7 @@ struct ipath_devdata {
+ 	u32 ipath_lastrpkts;
+ 	/* pio bufs allocated per port */
+ 	u32 ipath_pbufsport;
++	u32 ipath_pioupd_thresh; /* update threshold, some chips */
+ 	/*
+ 	 * number of ports configured as max; zero is set to number chip
+ 	 * supports, less gives more pio bufs/port, etc.
+@@ -365,6 +403,7 @@ struct ipath_devdata {
+ 	 * get to multiple devices
+ 	 */
+ 	u32 ipath_lastpioindex;
++	u32 ipath_lastpioindexl;
+ 	/* max length of freezemsg */
+ 	u32 ipath_freezelen;
+ 	/*
+@@ -381,6 +420,15 @@ struct ipath_devdata {
+ 	u32 ipath_pcibar0;
+ 	/* so we can rewrite it after a chip reset */
+ 	u32 ipath_pcibar1;
++	u32 ipath_x1_fix_tries;
++	u32 ipath_autoneg_tries;
++	u32 serdes_first_init_done;
++
++	struct ipath_relock {
++		atomic_t ipath_relock_timer_active;
++		struct timer_list ipath_relock_timer;
++		unsigned int ipath_relock_interval; /* in jiffies */
++	} ipath_relock_singleton;
+ 
+ 	/* interrupt number */
+ 	int ipath_irq;
+@@ -403,7 +451,7 @@ struct ipath_devdata {
+ 	u64 __iomem *ipath_egrtidbase;
+ 	/* lock to workaround chip bug 9437 and others */
+ 	spinlock_t ipath_kernel_tid_lock;
+-	spinlock_t ipath_tid_lock;
++	spinlock_t ipath_user_tid_lock;
+ 	spinlock_t ipath_sendctrl_lock;
+ 
+ 	/*
+@@ -418,15 +466,52 @@ struct ipath_devdata {
+ 	struct pci_dev *pcidev;
+ 	struct cdev *user_cdev;
+ 	struct cdev *diag_cdev;
+-	struct class_device *user_class_dev;
+-	struct class_device *diag_class_dev;
++	struct device *user_dev;
++	struct device *diag_dev;
+ 	/* timer used to prevent stats overflow, error throttling, etc. */
+ 	struct timer_list ipath_stats_timer;
++	/* timer to verify interrupts work, and fallback if possible */
++	struct timer_list ipath_intrchk_timer;
+ 	void *ipath_dummy_hdrq;	/* used after port close */
+ 	dma_addr_t ipath_dummy_hdrq_phys;
+ 
++	/* SendDMA related entries */
++	spinlock_t            ipath_sdma_lock;
++	u64                   ipath_sdma_status;
++	unsigned long         ipath_sdma_abort_jiffies;
++	unsigned long         ipath_sdma_abort_intr_timeout;
++	unsigned long         ipath_sdma_buf_jiffies;
++	struct ipath_sdma_desc *ipath_sdma_descq;
++	u64		      ipath_sdma_descq_added;
++	u64		      ipath_sdma_descq_removed;
++	int		      ipath_sdma_desc_nreserved;
++	u16                   ipath_sdma_descq_cnt;
++	u16                   ipath_sdma_descq_tail;
++	u16                   ipath_sdma_descq_head;
++	u16                   ipath_sdma_next_intr;
++	u16                   ipath_sdma_reset_wait;
++	u8                    ipath_sdma_generation;
++	struct tasklet_struct ipath_sdma_abort_task;
++	struct tasklet_struct ipath_sdma_notify_task;
++	struct list_head      ipath_sdma_activelist;
++	struct list_head      ipath_sdma_notifylist;
++	atomic_t              ipath_sdma_vl15_count;
++	struct timer_list     ipath_sdma_vl15_timer;
++
++	dma_addr_t       ipath_sdma_descq_phys;
++	volatile __le64 *ipath_sdma_head_dma;
++	dma_addr_t       ipath_sdma_head_phys;
++
+ 	unsigned long ipath_ureg_align; /* user register alignment */
+ 
++	struct delayed_work ipath_autoneg_work;
++	wait_queue_head_t ipath_autoneg_wait;
++
++	/* HoL blocking / user app forward-progress state */
++	unsigned          ipath_hol_state;
++	unsigned          ipath_hol_next;
++	struct timer_list ipath_hol_timer;
++
+ 	/*
+ 	 * Shadow copies of registers; size indicates read access size.
+ 	 * Most of them are readonly, but some are write-only register,
+@@ -447,6 +532,8 @@ struct ipath_devdata {
+ 	 * init time.
+ 	 */
+ 	unsigned long ipath_pioavailshadow[8];
++	/* bitmap of send buffers available for the kernel to use with PIO. */
++	unsigned long ipath_pioavailkernel[8];
+ 	/* shadow of kr_gpio_out, for rmw ops */
+ 	u64 ipath_gpio_out;
+ 	/* shadow the gpio mask register */
+@@ -472,6 +559,8 @@ struct ipath_devdata {
+ 	u64 ipath_intconfig;
+ 	/* kr_sendpiobufbase value */
+ 	u64 ipath_piobufbase;
++	/* kr_ibcddrctrl shadow */
++	u64 ipath_ibcddrctrl;
+ 
+ 	/* these are the "32 bit" regs */
+ 
+@@ -488,7 +577,10 @@ struct ipath_devdata {
+ 	unsigned long ipath_rcvctrl;
+ 	/* shadow kr_sendctrl */
+ 	unsigned long ipath_sendctrl;
+-	unsigned long ipath_lastcancel; /* to not count armlaunch after cancel */
++	/* to not count armlaunch after cancel */
++	unsigned long ipath_lastcancel;
++	/* count cases where special trigger was needed (double write) */
++	unsigned long ipath_spectriggerhit;
+ 
+ 	/* value we put in kr_rcvhdrcnt */
+ 	u32 ipath_rcvhdrcnt;
+@@ -510,6 +602,7 @@ struct ipath_devdata {
+ 	u32 ipath_piobcnt4k;
+ 	/* size in bytes of "4KB" PIO buffers */
+ 	u32 ipath_piosize4k;
++	u32 ipath_pioreserved; /* reserved special-inkernel; */
+ 	/* kr_rcvegrbase value */
+ 	u32 ipath_rcvegrbase;
+ 	/* kr_rcvegrcnt value */
+@@ -546,10 +639,10 @@ struct ipath_devdata {
+ 	u32 ipath_init_ibmaxlen;
+ 	/* size of each rcvegrbuffer */
+ 	u32 ipath_rcvegrbufsize;
+-	/* width (2,4,8,16,32) from HT config reg */
+-	u32 ipath_htwidth;
+-	/* HT speed (200,400,800,1000) from HT config */
+-	u32 ipath_htspeed;
++	/* localbus width (1, 2,4,8,16,32) from config space  */
++	u32 ipath_lbus_width;
++	/* localbus speed (HT: 200,400,800,1000; PCIe 2500) */
++	u32 ipath_lbus_speed;
+ 	/*
+ 	 * number of sequential ibcstatus change for polling active/quiet
+ 	 * (i.e., link not coming up).
+@@ -573,21 +666,14 @@ struct ipath_devdata {
+ 	 */
+ 	u8 ipath_serial[16];
+ 	/* human readable board version */
+-	u8 ipath_boardversion[80];
++	u8 ipath_boardversion[96];
++	u8 ipath_lbus_info[32]; /* human readable localbus info */
+ 	/* chip major rev, from ipath_revision */
+ 	u8 ipath_majrev;
+ 	/* chip minor rev, from ipath_revision */
+ 	u8 ipath_minrev;
+ 	/* board rev, from ipath_revision */
+ 	u8 ipath_boardrev;
+-
+-	u8 ipath_r_portenable_shift;
+-	u8 ipath_r_intravail_shift;
+-	u8 ipath_r_tailupd_shift;
+-	u8 ipath_r_portcfg_shift;
+-
+-	/* unit # of this chip, if present */
+-	int ipath_unit;
+ 	/* saved for restore after reset */
+ 	u8 ipath_pci_cacheline;
+ 	/* LID mask control */
+@@ -603,6 +689,14 @@ struct ipath_devdata {
+ 	/* Rx Polarity inversion (compensate for ~tx on partner) */
+ 	u8 ipath_rx_pol_inv;
+ 
++	u8 ipath_r_portenable_shift;
++	u8 ipath_r_intravail_shift;
++	u8 ipath_r_tailupd_shift;
++	u8 ipath_r_portcfg_shift;
++
++	/* unit # of this chip, if present */
++	int ipath_unit;
++
+ 	/* local link integrity counter */
+ 	u32 ipath_lli_counter;
+ 	/* local link integrity errors */
+@@ -617,9 +711,6 @@ struct ipath_devdata {
+ 	u32 ipath_overrun_thresh_errs;
+ 	u32 ipath_lli_errs;
+ 
+-	/* status check work */
+-	struct delayed_work status_work;
+-
+ 	/*
+ 	 * Not all devices managed by a driver instance are the same
+ 	 * type, so these fields must be per-device.
+@@ -632,8 +723,8 @@ struct ipath_devdata {
+ 	 * Below should be computable from number of ports,
+ 	 * since they are never modified.
+ 	 */
+-	u32 ipath_i_rcvavail_mask;
+-	u32 ipath_i_rcvurg_mask;
++	u64 ipath_i_rcvavail_mask;
++	u64 ipath_i_rcvurg_mask;
+ 	u16 ipath_i_rcvurg_shift;
+ 	u16 ipath_i_rcvavail_shift;
+ 
+@@ -641,8 +732,9 @@ struct ipath_devdata {
+ 	 * Register bits for selecting i2c direction and values, used for
+ 	 * I2C serial flash.
+ 	 */
+-	u16 ipath_gpio_sda_num;
+-	u16 ipath_gpio_scl_num;
++	u8 ipath_gpio_sda_num;
++	u8 ipath_gpio_scl_num;
++	u8 ipath_i2c_chain_type;
+ 	u64 ipath_gpio_sda;
+ 	u64 ipath_gpio_scl;
+ 
+@@ -703,13 +795,51 @@ struct ipath_devdata {
+ 	/* interrupt mitigation reload register info */
+ 	u16 ipath_jint_idle_ticks;	/* idle clock ticks */
+ 	u16 ipath_jint_max_packets;	/* max packets across all ports */
++
++	/*
++	 * lock for access to SerDes, and flags to sequence preset
++	 * versus steady-state. 7220-only at the moment.
++	 */
++	spinlock_t ipath_sdepb_lock;
++	u8 ipath_presets_needed; /* Set if presets to be restored next DOWN */
+ };
+ 
++/* ipath_hol_state values (stopping/starting user proc, send flushing) */
++#define IPATH_HOL_UP       0
++#define IPATH_HOL_DOWN     1
++/* ipath_hol_next toggle values, used when hol_state IPATH_HOL_DOWN */
++#define IPATH_HOL_DOWNSTOP 0
++#define IPATH_HOL_DOWNCONT 1
++
++/* bit positions for sdma_status */
++#define IPATH_SDMA_ABORTING  0
++#define IPATH_SDMA_DISARMED  1
++#define IPATH_SDMA_DISABLED  2
++#define IPATH_SDMA_LAYERBUF  3
++#define IPATH_SDMA_RUNNING  62
++#define IPATH_SDMA_SHUTDOWN 63
++
++/* bit combinations that correspond to abort states */
++#define IPATH_SDMA_ABORT_NONE 0
++#define IPATH_SDMA_ABORT_ABORTING (1UL << IPATH_SDMA_ABORTING)
++#define IPATH_SDMA_ABORT_DISARMED ((1UL << IPATH_SDMA_ABORTING) | \
++	(1UL << IPATH_SDMA_DISARMED))
++#define IPATH_SDMA_ABORT_DISABLED ((1UL << IPATH_SDMA_ABORTING) | \
++	(1UL << IPATH_SDMA_DISABLED))
++#define IPATH_SDMA_ABORT_ABORTED ((1UL << IPATH_SDMA_ABORTING) | \
++	(1UL << IPATH_SDMA_DISARMED) | (1UL << IPATH_SDMA_DISABLED))
++#define IPATH_SDMA_ABORT_MASK ((1UL<<IPATH_SDMA_ABORTING) | \
++	(1UL << IPATH_SDMA_DISARMED) | (1UL << IPATH_SDMA_DISABLED))
++
++#define IPATH_SDMA_BUF_NONE 0
++#define IPATH_SDMA_BUF_MASK (1UL<<IPATH_SDMA_LAYERBUF)
++
+ /* Private data for file operations */
+ struct ipath_filedata {
+ 	struct ipath_portdata *pd;
+ 	unsigned subport;
+ 	unsigned tidcursor;
++	struct ipath_user_sdma_queue *pq;
+ };
+ extern struct list_head ipath_dev_list;
+ extern spinlock_t ipath_devs_lock;
+@@ -718,15 +848,15 @@ extern struct ipath_devdata *ipath_lookup(int unit);
+ int ipath_init_chip(struct ipath_devdata *, int);
+ int ipath_enable_wc(struct ipath_devdata *dd);
+ void ipath_disable_wc(struct ipath_devdata *dd);
+-int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
++int ipath_count_units(int *npresentp, int *nupp, int *maxportsp);
+ void ipath_shutdown_device(struct ipath_devdata *);
+ void ipath_clear_freeze(struct ipath_devdata *);
+ 
+ struct file_operations;
+ int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
+-		    struct cdev **cdevp, struct class_device **class_devp);
++		    struct cdev **cdevp, struct device **devp);
+ void ipath_cdev_cleanup(struct cdev **cdevp,
+-			struct class_device **class_devp);
++			struct device **devp);
+ 
+ int ipath_diag_add(struct ipath_devdata *);
+ void ipath_diag_remove(struct ipath_devdata *);
+@@ -741,7 +871,8 @@ struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t);
+ extern int ipath_diag_inuse;
+ 
+ irqreturn_t ipath_intr(int irq, void *devid);
+-int ipath_decode_err(char *buf, size_t blen, ipath_err_t err);
++int ipath_decode_err(struct ipath_devdata *dd, char *buf, size_t blen,
++		     ipath_err_t err);
+ #if __IPATH_INFO || __IPATH_DBG
+ extern const char *ipath_ibcstatus_str[];
+ #endif
+@@ -774,6 +905,13 @@ int ipath_set_lid(struct ipath_devdata *, u32, u8);
+ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
+ void ipath_enable_armlaunch(struct ipath_devdata *);
+ void ipath_disable_armlaunch(struct ipath_devdata *);
++void ipath_hol_down(struct ipath_devdata *);
++void ipath_hol_up(struct ipath_devdata *);
++void ipath_hol_event(unsigned long);
++void ipath_toggle_rclkrls(struct ipath_devdata *);
++void ipath_sd7220_clr_ibpar(struct ipath_devdata *);
++void ipath_set_relock_poll(struct ipath_devdata *, int);
++void ipath_shutdown_relock_poll(struct ipath_devdata *);
+ 
+ /* for use in system calls, where we want to know device type, etc. */
+ #define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
+@@ -781,11 +919,15 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
+ 	((struct ipath_filedata *)(fp)->private_data)->subport
+ #define tidcursor_fp(fp) \
+ 	((struct ipath_filedata *)(fp)->private_data)->tidcursor
++#define user_sdma_queue_fp(fp) \
++	((struct ipath_filedata *)(fp)->private_data)->pq
+ 
+ /*
+  * values for ipath_flags
+  */
+-/* The chip is up and initted */
++		/* chip can report link latency (IB 1.2) */
++#define IPATH_HAS_LINK_LATENCY 0x1
++		/* The chip is up and initted */
+ #define IPATH_INITTED       0x2
+ 		/* set if any user code has set kr_rcvhdrsize */
+ #define IPATH_RCVHDRSZ_SET  0x4
+@@ -809,6 +951,8 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
+ #define IPATH_LINKUNK       0x400
+ 		/* Write combining flush needed for PIO */
+ #define IPATH_PIO_FLUSH_WC  0x1000
++		/* DMA Receive tail pointer */
++#define IPATH_NODMA_RTAIL   0x2000
+ 		/* no IB cable, or no device on IB cable */
+ #define IPATH_NOCABLE       0x4000
+ 		/* Supports port zero per packet receive interrupts via
+@@ -819,16 +963,26 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
+ 		/* packet/word counters are 32 bit, else those 4 counters
+ 		 * are 64bit */
+ #define IPATH_32BITCOUNTERS 0x20000
+-		/* can miss port0 rx interrupts */
+ 		/* Interrupt register is 64 bits */
+ #define IPATH_INTREG_64     0x40000
++		/* can miss port0 rx interrupts */
+ #define IPATH_DISABLED      0x80000 /* administratively disabled */
+ 		/* Use GPIO interrupts for new counters */
+ #define IPATH_GPIO_ERRINTRS 0x100000
+ #define IPATH_SWAP_PIOBUFS  0x200000
++		/* Supports Send DMA */
++#define IPATH_HAS_SEND_DMA  0x400000
++		/* Supports Send Count (not just word count) in PBC */
++#define IPATH_HAS_PBC_CNT   0x800000
+ 		/* Suppress heartbeat, even if turning off loopback */
+ #define IPATH_NO_HRTBT      0x1000000
++#define IPATH_HAS_THRESH_UPDATE 0x4000000
+ #define IPATH_HAS_MULT_IB_SPEED 0x8000000
++#define IPATH_IB_AUTONEG_INPROG 0x10000000
++#define IPATH_IB_AUTONEG_FAILED 0x20000000
++		/* Linkdown-disable intentionally, Do not attempt to bring up */
++#define IPATH_IB_LINK_DISABLED 0x40000000
++#define IPATH_IB_FORCE_NOTIFY 0x80000000 /* force notify on next ib change */
+ 
+ /* Bits in GPIO for the added interrupts */
+ #define IPATH_GPIO_PORT0_BIT 2
+@@ -847,13 +1001,18 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
+ 
+ /* free up any allocated data at closes */
+ void ipath_free_data(struct ipath_portdata *dd);
+-u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
++u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32, u32 *);
++void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start,
++				unsigned len, int avail);
++void ipath_init_iba7220_funcs(struct ipath_devdata *);
+ void ipath_init_iba6120_funcs(struct ipath_devdata *);
+ void ipath_init_iba6110_funcs(struct ipath_devdata *);
+ void ipath_get_eeprom_info(struct ipath_devdata *);
+ int ipath_update_eeprom_log(struct ipath_devdata *dd);
+ void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
+ u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
++void ipath_disarm_senderrbufs(struct ipath_devdata *, int);
++void ipath_force_pio_avail_update(struct ipath_devdata *);
+ void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev);
+ 
+ /*
+@@ -865,6 +1024,34 @@ void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev);
+ #define IPATH_LED_LOG 2  /* Logical (link) YELLOW LED */
+ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
+ 
++/* send dma routines */
++int setup_sdma(struct ipath_devdata *);
++void teardown_sdma(struct ipath_devdata *);
++void ipath_restart_sdma(struct ipath_devdata *);
++void ipath_sdma_intr(struct ipath_devdata *);
++int ipath_sdma_verbs_send(struct ipath_devdata *, struct ipath_sge_state *,
++			  u32, struct ipath_verbs_txreq *);
++/* ipath_sdma_lock should be locked before calling this. */
++int ipath_sdma_make_progress(struct ipath_devdata *dd);
++
++/* must be called under ipath_sdma_lock */
++static inline u16 ipath_sdma_descq_freecnt(const struct ipath_devdata *dd)
++{
++	return dd->ipath_sdma_descq_cnt -
++		(dd->ipath_sdma_descq_added - dd->ipath_sdma_descq_removed) -
++		1 - dd->ipath_sdma_desc_nreserved;
++}
++
++static inline void ipath_sdma_desc_reserve(struct ipath_devdata *dd, u16 cnt)
++{
++	dd->ipath_sdma_desc_nreserved += cnt;
++}
++
++static inline void ipath_sdma_desc_unreserve(struct ipath_devdata *dd, u16 cnt)
++{
++	dd->ipath_sdma_desc_nreserved -= cnt;
++}
++
+ /*
+  * number of words used for protocol header if not set by ipath_userinit();
+  */
+@@ -875,6 +1062,8 @@ void ipath_release_user_pages(struct page **, size_t);
+ void ipath_release_user_pages_on_close(struct page **, size_t);
+ int ipath_eeprom_read(struct ipath_devdata *, u8, void *, int);
+ int ipath_eeprom_write(struct ipath_devdata *, u8, const void *, int);
++int ipath_tempsense_read(struct ipath_devdata *, u8 regnum);
++int ipath_tempsense_write(struct ipath_devdata *, u8 regnum, u8 data);
+ 
+ /* these are used for the registers that vary with port */
+ void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg,
+@@ -891,8 +1080,7 @@ void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg,
+ 
+ /*
+  * At the moment, none of the s-registers are writable, so no
+- * ipath_write_sreg(), and none of the c-registers are writable, so no
+- * ipath_write_creg().
++ * ipath_write_sreg().
+  */
+ 
+ /**
+@@ -1001,6 +1189,27 @@ static inline u32 ipath_get_rcvhdrtail(const struct ipath_portdata *pd)
+ 				pd->port_rcvhdrtail_kvaddr));
+ }
+ 
++static inline u32 ipath_get_hdrqtail(const struct ipath_portdata *pd)
++{
++	const struct ipath_devdata *dd = pd->port_dd;
++	u32 hdrqtail;
++
++	if (dd->ipath_flags & IPATH_NODMA_RTAIL) {
++		__le32 *rhf_addr;
++		u32 seq;
++
++		rhf_addr = (__le32 *) pd->port_rcvhdrq +
++			pd->port_head + dd->ipath_rhf_offset;
++		seq = ipath_hdrget_seq(rhf_addr);
++		hdrqtail = pd->port_head;
++		if (seq == pd->port_seq_cnt)
++			hdrqtail++;
++	} else
++		hdrqtail = ipath_get_rcvhdrtail(pd);
++
++	return hdrqtail;
++}
++
+ static inline u64 ipath_read_ireg(const struct ipath_devdata *dd, ipath_kreg r)
+ {
+ 	return (dd->ipath_flags & IPATH_INTREG_64) ?
+@@ -1029,6 +1238,21 @@ static inline u32 ipath_ib_linktrstate(struct ipath_devdata *dd, u64 ibcs)
+ }
+ 
+ /*
++ * from contents of IBCStatus (or a saved copy), return logical link state
++ * combination of link state and linktraining state (down, active, init,
++ * arm, etc.
++ */
++static inline u32 ipath_ib_state(struct ipath_devdata *dd, u64 ibcs)
++{
++	u32 ibs;
++	ibs = (u32)(ibcs >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
++		dd->ibcs_lts_mask;
++	ibs |= (u32)(ibcs &
++		(INFINIPATH_IBCS_LINKSTATE_MASK << dd->ibcs_ls_shift));
++	return ibs;
++}
++
++/*
+  * sysfs interface.
+  */
+ 
+@@ -1053,6 +1277,7 @@ int ipathfs_remove_device(struct ipath_devdata *);
+ dma_addr_t ipath_map_page(struct pci_dev *, struct page *, unsigned long,
+ 			  size_t, int);
+ dma_addr_t ipath_map_single(struct pci_dev *, void *, size_t, int);
++const char *ipath_get_unit_name(int unit);
+ 
+ /*
+  * Flush write combining store buffers (if present) and perform a write
+@@ -1065,11 +1290,8 @@ dma_addr_t ipath_map_single(struct pci_dev *, void *, size_t, int);
+ #endif
+ 
+ extern unsigned ipath_debug; /* debugging bit mask */
+-
+-#define IPATH_MAX_PARITY_ATTEMPTS 10000 /* max times to try recovery */
+-
+-const char *ipath_get_unit_name(int unit);
+-
++extern unsigned ipath_linkrecovery;
++extern unsigned ipath_mtu4096;
+ extern struct mutex ipath_mutex;
+ 
+ #define IPATH_DRV_NAME		"ib_ipath"
+@@ -1096,7 +1318,7 @@ extern struct mutex ipath_mutex;
+ 
+ # define __IPATH_DBG_WHICH(which,fmt,...) \
+ 	do { \
+-		if(unlikely(ipath_debug&(which))) \
++		if (unlikely(ipath_debug & (which))) \
+ 			printk(KERN_DEBUG IPATH_DRV_NAME ": %s: " fmt, \
+ 			       __func__,##__VA_ARGS__); \
+ 	} while(0)
+diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
+index b34b91d..1ff46ae 100644
+--- a/drivers/infiniband/hw/ipath/ipath_mad.c
++++ b/drivers/infiniband/hw/ipath/ipath_mad.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -146,6 +146,15 @@ static int recv_subn_get_guidinfo(struct ib_smp *smp,
+ 	return reply(smp);
+ }
+ 
++static void set_link_width_enabled(struct ipath_devdata *dd, u32 w)
++{
++	(void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, w);
++}
++
++static void set_link_speed_enabled(struct ipath_devdata *dd, u32 s)
++{
++	(void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, s);
++}
+ 
+ static int get_overrunthreshold(struct ipath_devdata *dd)
+ {
+@@ -226,6 +235,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ 				  struct ib_device *ibdev, u8 port)
+ {
+ 	struct ipath_ibdev *dev;
++	struct ipath_devdata *dd;
+ 	struct ib_port_info *pip = (struct ib_port_info *)smp->data;
+ 	u16 lid;
+ 	u8 ibcstat;
+@@ -239,6 +249,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ 	}
+ 
+ 	dev = to_idev(ibdev);
++	dd = dev->dd;
+ 
+ 	/* Clear all fields.  Only set the non-zero fields. */
+ 	memset(smp->data, 0, sizeof(smp->data));
+@@ -248,25 +259,28 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ 	    dev->mkeyprot == 0)
+ 		pip->mkey = dev->mkey;
+ 	pip->gid_prefix = dev->gid_prefix;
+-	lid = dev->dd->ipath_lid;
++	lid = dd->ipath_lid;
+ 	pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE;
+ 	pip->sm_lid = cpu_to_be16(dev->sm_lid);
+ 	pip->cap_mask = cpu_to_be32(dev->port_cap_flags);
+ 	/* pip->diag_code; */
+ 	pip->mkey_lease_period = cpu_to_be16(dev->mkey_lease_period);
+ 	pip->local_port_num = port;
+-	pip->link_width_enabled = dev->link_width_enabled;
+-	pip->link_width_supported = 3;	/* 1x or 4x */
+-	pip->link_width_active = 2;	/* 4x */
+-	pip->linkspeed_portstate = 0x10;	/* 2.5Gbps */
+-	ibcstat = dev->dd->ipath_lastibcstat;
+-	pip->linkspeed_portstate |= ((ibcstat >> 4) & 0x3) + 1;
++	pip->link_width_enabled = dd->ipath_link_width_enabled;
++	pip->link_width_supported = dd->ipath_link_width_supported;
++	pip->link_width_active = dd->ipath_link_width_active;
++	pip->linkspeed_portstate = dd->ipath_link_speed_supported << 4;
++	ibcstat = dd->ipath_lastibcstat;
++	/* map LinkState to IB portinfo values.  */
++	pip->linkspeed_portstate |= ipath_ib_linkstate(dd, ibcstat) + 1;
++
+ 	pip->portphysstate_linkdown =
+-		(ipath_cvt_physportstate[ibcstat & 0xf] << 4) |
+-		(get_linkdowndefaultstate(dev->dd) ? 1 : 2);
+-	pip->mkeyprot_resv_lmc = (dev->mkeyprot << 6) | dev->dd->ipath_lmc;
+-	pip->linkspeedactive_enabled = 0x11;	/* 2.5Gbps, 2.5Gbps */
+-	switch (dev->dd->ipath_ibmtu) {
++		(ipath_cvt_physportstate[ibcstat & dd->ibcs_lts_mask] << 4) |
++		(get_linkdowndefaultstate(dd) ? 1 : 2);
++	pip->mkeyprot_resv_lmc = (dev->mkeyprot << 6) | dd->ipath_lmc;
++	pip->linkspeedactive_enabled = (dd->ipath_link_speed_active << 4) |
++		dd->ipath_link_speed_enabled;
++	switch (dd->ipath_ibmtu) {
+ 	case 4096:
+ 		mtu = IB_MTU_4096;
+ 		break;
+@@ -292,19 +306,15 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ 	/* pip->vl_arb_high_cap; // only one VL */
+ 	/* pip->vl_arb_low_cap; // only one VL */
+ 	/* InitTypeReply = 0 */
+-	/*
+-	 * Note: the chips support a maximum MTU of 4096, but the driver
+-	 * hasn't implemented this feature yet, so set the maximum value
+-	 * to 2048.
+-	 */
+-	pip->inittypereply_mtucap = IB_MTU_2048;
+-	// HCAs ignore VLStallCount and HOQLife
++	/* our mtu cap depends on whether 4K MTU enabled or not */
++	pip->inittypereply_mtucap = ipath_mtu4096 ? IB_MTU_4096 : IB_MTU_2048;
++	/* HCAs ignore VLStallCount and HOQLife */
+ 	/* pip->vlstallcnt_hoqlife; */
+ 	pip->operationalvl_pei_peo_fpi_fpo = 0x10;	/* OVLs = 1 */
+ 	pip->mkey_violations = cpu_to_be16(dev->mkey_violations);
+ 	/* P_KeyViolations are counted by hardware. */
+ 	pip->pkey_violations =
+-		cpu_to_be16((ipath_get_cr_errpkey(dev->dd) -
++		cpu_to_be16((ipath_get_cr_errpkey(dd) -
+ 			     dev->z_pkey_violations) & 0xFFFF);
+ 	pip->qkey_violations = cpu_to_be16(dev->qkey_violations);
+ 	/* Only the hardware GUID is supported for now */
+@@ -313,10 +323,17 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ 	/* 32.768 usec. response time (guessing) */
+ 	pip->resv_resptimevalue = 3;
+ 	pip->localphyerrors_overrunerrors =
+-		(get_phyerrthreshold(dev->dd) << 4) |
+-		get_overrunthreshold(dev->dd);
++		(get_phyerrthreshold(dd) << 4) |
++		get_overrunthreshold(dd);
+ 	/* pip->max_credit_hint; */
+-	/* pip->link_roundtrip_latency[3]; */
++	if (dev->port_cap_flags & IB_PORT_LINK_LATENCY_SUP) {
++		u32 v;
++
++		v = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LINKLATENCY);
++		pip->link_roundtrip_latency[0] = v >> 16;
++		pip->link_roundtrip_latency[1] = v >> 8;
++		pip->link_roundtrip_latency[2] = v;
++	}
+ 
+ 	ret = reply(smp);
+ 
+@@ -444,19 +461,25 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
+ 		ib_dispatch_event(&event);
+ 	}
+ 
+-	/* Only 4x supported but allow 1x or 4x to be set (see 14.2.6.6). */
++	/* Allow 1x or 4x to be set (see 14.2.6.6). */
+ 	lwe = pip->link_width_enabled;
+-	if ((lwe >= 4 && lwe <= 8) || (lwe >= 0xC && lwe <= 0xFE))
+-		goto err;
+-	if (lwe == 0xFF)
+-		dev->link_width_enabled = 3;	/* 1x or 4x */
+-	else if (lwe)
+-		dev->link_width_enabled = lwe;
++	if (lwe) {
++		if (lwe == 0xFF)
++			lwe = dd->ipath_link_width_supported;
++		else if (lwe >= 16 || (lwe & ~dd->ipath_link_width_supported))
++			goto err;
++		set_link_width_enabled(dd, lwe);
++	}
+ 
+-	/* Only 2.5 Gbs supported. */
++	/* Allow 2.5 or 5.0 Gbs. */
+ 	lse = pip->linkspeedactive_enabled & 0xF;
+-	if (lse >= 2 && lse <= 0xE)
+-		goto err;
++	if (lse) {
++		if (lse == 15)
++			lse = dd->ipath_link_speed_supported;
++		else if (lse >= 8 || (lse & ~dd->ipath_link_speed_supported))
++			goto err;
++		set_link_speed_enabled(dd, lse);
++	}
+ 
+ 	/* Set link down default state. */
+ 	switch (pip->portphysstate_linkdown & 0xF) {
+@@ -491,6 +514,8 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
+ 		mtu = 2048;
+ 		break;
+ 	case IB_MTU_4096:
++		if (!ipath_mtu4096)
++			goto err;
+ 		mtu = 4096;
+ 		break;
+ 	default:
+@@ -565,6 +590,10 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
+ 		else
+ 			goto err;
+ 		ipath_set_linkstate(dd, lstate);
++		if (lstate == IPATH_IB_LINKDOWN_DISABLE) {
++			ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
++			goto done;
++		}
+ 		ipath_wait_linkstate(dd, IPATH_LINKINIT | IPATH_LINKARMED |
+ 				IPATH_LINKACTIVE, 1000);
+ 		break;
+@@ -948,10 +977,14 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+ 	 * nsec.  0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec.  Sample
+ 	 * intervals are counted in ticks.  Since we use Linux timers, that
+ 	 * count in jiffies, we can't sample for less than 1000 ticks if HZ
+-	 * == 1000 (4000 ticks if HZ is 250).
++	 * == 1000 (4000 ticks if HZ is 250).  link_speed_active returns 2 for
++	 * DDR, 1 for SDR, set the tick to 1 for DDR, 0 for SDR on chips that
++	 * have hardware support for delaying packets.
+ 	 */
+-	/* XXX This is WRONG. */
+-	p->tick = 250;		/* 1 usec. */
++	if (crp->cr_psstat)
++		p->tick = dev->dd->ipath_link_speed_active - 1;
++	else
++		p->tick = 250;		/* 1 usec. */
+ 	p->counter_width = 4;	/* 32 bit counters */
+ 	p->counter_mask0_9 = COUNTER_MASK0_9;
+ 	spin_lock_irqsave(&dev->pending_lock, flags);
+@@ -1364,7 +1397,8 @@ static int process_subn(struct ib_device *ibdev, int mad_flags,
+ 	}
+ 
+ 	/* Is the mkey in the process of expiring? */
+-	if (dev->mkey_lease_timeout && jiffies >= dev->mkey_lease_timeout) {
++	if (dev->mkey_lease_timeout &&
++	    time_after_eq(jiffies, dev->mkey_lease_timeout)) {
+ 		/* Clear timeout and mkey protection field. */
+ 		dev->mkey_lease_timeout = 0;
+ 		dev->mkeyprot = 0;
+diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
+index 087ed31..dd5b6e9 100644
+--- a/drivers/infiniband/hw/ipath/ipath_qp.c
++++ b/drivers/infiniband/hw/ipath/ipath_qp.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -340,6 +340,7 @@ static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type)
+ 	qp->s_flags &= IPATH_S_SIGNAL_REQ_WR;
+ 	qp->s_hdrwords = 0;
+ 	qp->s_wqe = NULL;
++	qp->s_pkt_delay = 0;
+ 	qp->s_psn = 0;
+ 	qp->r_psn = 0;
+ 	qp->r_msn = 0;
+@@ -392,7 +393,6 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
+ 		  qp->ibqp.qp_num, qp->remote_qpn, err);
+ 
+ 	spin_lock(&dev->pending_lock);
+-	/* XXX What if its already removed by the timeout code? */
+ 	if (!list_empty(&qp->timerwait))
+ 		list_del_init(&qp->timerwait);
+ 	if (!list_empty(&qp->piowait))
+@@ -516,13 +516,13 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ 			goto inval;
+ 
+ 	/*
+-	 * Note: the chips support a maximum MTU of 4096, but the driver
+-	 * hasn't implemented this feature yet, so don't allow Path MTU
+-	 * values greater than 2048.
++	 * don't allow invalid Path MTU values or greater than 2048
++	 * unless we are configured for a 4KB MTU
+ 	 */
+-	if (attr_mask & IB_QP_PATH_MTU)
+-		if (attr->path_mtu > IB_MTU_2048)
+-			goto inval;
++	if ((attr_mask & IB_QP_PATH_MTU) &&
++		(ib_mtu_enum_to_int(attr->path_mtu) == -1 ||
++		(attr->path_mtu > IB_MTU_2048 && !ipath_mtu4096)))
++		goto inval;
+ 
+ 	if (attr_mask & IB_QP_PATH_MIG_STATE)
+ 		if (attr->path_mig_state != IB_MIG_MIGRATED &&
+@@ -564,8 +564,10 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ 	if (attr_mask & IB_QP_ACCESS_FLAGS)
+ 		qp->qp_access_flags = attr->qp_access_flags;
+ 
+-	if (attr_mask & IB_QP_AV)
++	if (attr_mask & IB_QP_AV) {
+ 		qp->remote_ah_attr = attr->ah_attr;
++		qp->s_dmult = ipath_ib_rate_to_mult(attr->ah_attr.static_rate);
++	}
+ 
+ 	if (attr_mask & IB_QP_PATH_MTU)
+ 		qp->path_mtu = attr->path_mtu;
+@@ -748,22 +750,33 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ 	size_t sz;
+ 	struct ib_qp *ret;
+ 
+-	if (init_attr->cap.max_send_sge > ib_ipath_max_sges ||
+-	    init_attr->cap.max_recv_sge > ib_ipath_max_sges ||
+-	    init_attr->cap.max_send_wr > ib_ipath_max_qp_wrs ||
+-	    init_attr->cap.max_recv_wr > ib_ipath_max_qp_wrs) {
+-		ret = ERR_PTR(-ENOMEM);
++	if (init_attr->create_flags) {
++		ret = ERR_PTR(-EINVAL);
+ 		goto bail;
+ 	}
+ 
+-	if (init_attr->cap.max_send_sge +
+-	    init_attr->cap.max_recv_sge +
+-	    init_attr->cap.max_send_wr +
+-	    init_attr->cap.max_recv_wr == 0) {
++	if (init_attr->cap.max_send_sge > ib_ipath_max_sges ||
++	    init_attr->cap.max_send_wr > ib_ipath_max_qp_wrs) {
+ 		ret = ERR_PTR(-EINVAL);
+ 		goto bail;
+ 	}
+ 
++	/* Check receive queue parameters if no SRQ is specified. */
++	if (!init_attr->srq) {
++		if (init_attr->cap.max_recv_sge > ib_ipath_max_sges ||
++		    init_attr->cap.max_recv_wr > ib_ipath_max_qp_wrs) {
++			ret = ERR_PTR(-EINVAL);
++			goto bail;
++		}
++		if (init_attr->cap.max_send_sge +
++		    init_attr->cap.max_send_wr +
++		    init_attr->cap.max_recv_sge +
++		    init_attr->cap.max_recv_wr == 0) {
++			ret = ERR_PTR(-EINVAL);
++			goto bail;
++		}
++	}
++
+ 	switch (init_attr->qp_type) {
+ 	case IB_QPT_UC:
+ 	case IB_QPT_RC:
+@@ -840,6 +853,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ 			goto bail_qp;
+ 		}
+ 		qp->ip = NULL;
++		qp->s_tx = NULL;
+ 		ipath_reset_qp(qp, init_attr->qp_type);
+ 		break;
+ 
+@@ -945,12 +959,20 @@ int ipath_destroy_qp(struct ib_qp *ibqp)
+ 	/* Stop the sending tasklet. */
+ 	tasklet_kill(&qp->s_task);
+ 
++	if (qp->s_tx) {
++		atomic_dec(&qp->refcount);
++		if (qp->s_tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF)
++			kfree(qp->s_tx->txreq.map_addr);
++	}
++
+ 	/* Make sure the QP isn't on the timeout list. */
+ 	spin_lock_irqsave(&dev->pending_lock, flags);
+ 	if (!list_empty(&qp->timerwait))
+ 		list_del_init(&qp->timerwait);
+ 	if (!list_empty(&qp->piowait))
+ 		list_del_init(&qp->piowait);
++	if (qp->s_tx)
++		list_add(&qp->s_tx->txreq.list, &dev->txreq_free);
+ 	spin_unlock_irqrestore(&dev->pending_lock, flags);
+ 
+ 	/*
+@@ -1021,7 +1043,6 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc)
+ 		  qp->ibqp.qp_num, qp->remote_qpn, wc->status);
+ 
+ 	spin_lock(&dev->pending_lock);
+-	/* XXX What if its already removed by the timeout code? */
+ 	if (!list_empty(&qp->timerwait))
+ 		list_del_init(&qp->timerwait);
+ 	if (!list_empty(&qp->piowait))
+diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
+index 40f3e37..c405dfb 100644
+--- a/drivers/infiniband/hw/ipath/ipath_rc.c
++++ b/drivers/infiniband/hw/ipath/ipath_rc.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -31,6 +31,8 @@
+  * SOFTWARE.
+  */
+ 
++#include <linux/io.h>
++
+ #include "ipath_verbs.h"
+ #include "ipath_kernel.h"
+ 
+@@ -306,7 +308,7 @@ int ipath_make_rc_req(struct ipath_qp *qp)
+ 			else {
+ 				qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE);
+ 				/* Immediate data comes after the BTH */
+-				ohdr->u.imm_data = wqe->wr.imm_data;
++				ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ 				hwords += 1;
+ 			}
+ 			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+@@ -344,7 +346,7 @@ int ipath_make_rc_req(struct ipath_qp *qp)
+ 				qp->s_state =
+ 					OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+ 				/* Immediate data comes after RETH */
+-				ohdr->u.rc.imm_data = wqe->wr.imm_data;
++				ohdr->u.rc.imm_data = wqe->wr.ex.imm_data;
+ 				hwords += 1;
+ 				if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ 					bth0 |= 1 << 23;
+@@ -488,7 +490,7 @@ int ipath_make_rc_req(struct ipath_qp *qp)
+ 		else {
+ 			qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+ 			/* Immediate data comes after the BTH */
+-			ohdr->u.imm_data = wqe->wr.imm_data;
++			ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ 			hwords += 1;
+ 		}
+ 		if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+@@ -524,7 +526,7 @@ int ipath_make_rc_req(struct ipath_qp *qp)
+ 		else {
+ 			qp->s_state = OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+ 			/* Immediate data comes after the BTH */
+-			ohdr->u.imm_data = wqe->wr.imm_data;
++			ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ 			hwords += 1;
+ 			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ 				bth0 |= 1 << 23;
+@@ -585,19 +587,39 @@ bail:
+ static void send_rc_ack(struct ipath_qp *qp)
+ {
+ 	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
++	struct ipath_devdata *dd;
+ 	u16 lrh0;
+ 	u32 bth0;
+ 	u32 hwords;
++	u32 __iomem *piobuf;
+ 	struct ipath_ib_header hdr;
+ 	struct ipath_other_headers *ohdr;
+ 	unsigned long flags;
+ 
++	spin_lock_irqsave(&qp->s_lock, flags);
++
+ 	/* Don't send ACK or NAK if a RDMA read or atomic is pending. */
+ 	if (qp->r_head_ack_queue != qp->s_tail_ack_queue ||
+ 	    (qp->s_flags & IPATH_S_ACK_PENDING) ||
+ 	    qp->s_ack_state != OP(ACKNOWLEDGE))
+ 		goto queue_ack;
+ 
++	spin_unlock_irqrestore(&qp->s_lock, flags);
++
++	dd = dev->dd;
++	piobuf = ipath_getpiobuf(dd, 0, NULL);
++	if (!piobuf) {
++		/*
++		 * We are out of PIO buffers at the moment.
++		 * Pass responsibility for sending the ACK to the
++		 * send tasklet so that when a PIO buffer becomes
++		 * available, the ACK is sent ahead of other outgoing
++		 * packets.
++		 */
++		spin_lock_irqsave(&qp->s_lock, flags);
++		goto queue_ack;
++	}
++
+ 	/* Construct the header. */
+ 	ohdr = &hdr.u.oth;
+ 	lrh0 = IPATH_LRH_BTH;
+@@ -611,7 +633,7 @@ static void send_rc_ack(struct ipath_qp *qp)
+ 		lrh0 = IPATH_LRH_GRH;
+ 	}
+ 	/* read pkey_index w/o lock (its atomic) */
+-	bth0 = ipath_get_pkey(dev->dd, qp->s_pkey_index) |
++	bth0 = ipath_get_pkey(dd, qp->s_pkey_index) |
+ 		(OP(ACKNOWLEDGE) << 24) | (1 << 22);
+ 	if (qp->r_nak_state)
+ 		ohdr->u.aeth = cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) |
+@@ -623,30 +645,29 @@ static void send_rc_ack(struct ipath_qp *qp)
+ 	hdr.lrh[0] = cpu_to_be16(lrh0);
+ 	hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+ 	hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC);
+-	hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid);
++	hdr.lrh[3] = cpu_to_be16(dd->ipath_lid);
+ 	ohdr->bth[0] = cpu_to_be32(bth0);
+ 	ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+ 	ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & IPATH_PSN_MASK);
+ 
+-	/*
+-	 * If we can send the ACK, clear the ACK state.
+-	 */
+-	if (ipath_verbs_send(qp, &hdr, hwords, NULL, 0) == 0) {
+-		dev->n_unicast_xmit++;
+-		goto done;
+-	}
++	writeq(hwords + 1, piobuf);
+ 
+-	/*
+-	 * We are out of PIO buffers at the moment.
+-	 * Pass responsibility for sending the ACK to the
+-	 * send tasklet so that when a PIO buffer becomes
+-	 * available, the ACK is sent ahead of other outgoing
+-	 * packets.
+-	 */
+-	dev->n_rc_qacks++;
++	if (dd->ipath_flags & IPATH_PIO_FLUSH_WC) {
++		u32 *hdrp = (u32 *) &hdr;
++
++		ipath_flush_wc();
++		__iowrite32_copy(piobuf + 2, hdrp, hwords - 1);
++		ipath_flush_wc();
++		__raw_writel(hdrp[hwords - 1], piobuf + hwords + 1);
++	} else
++		__iowrite32_copy(piobuf + 2, (u32 *) &hdr, hwords);
++
++	ipath_flush_wc();
++
++	dev->n_unicast_xmit++;
++	goto done;
+ 
+ queue_ack:
+-	spin_lock_irqsave(&qp->s_lock, flags);
+ 	dev->n_rc_qacks++;
+ 	qp->s_flags |= IPATH_S_ACK_PENDING;
+ 	qp->s_nak_state = qp->r_nak_state;
+diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
+index 92ad73a..8f44d0c 100644
+--- a/drivers/infiniband/hw/ipath/ipath_registers.h
++++ b/drivers/infiniband/hw/ipath/ipath_registers.h
+@@ -63,67 +63,92 @@
+ /* kr_control bits */
+ #define INFINIPATH_C_FREEZEMODE 0x00000002
+ #define INFINIPATH_C_LINKENABLE 0x00000004
+-#define INFINIPATH_C_RESET 0x00000001
+ 
+ /* kr_sendctrl bits */
+ #define INFINIPATH_S_DISARMPIOBUF_SHIFT 16
++#define INFINIPATH_S_UPDTHRESH_SHIFT 24
++#define INFINIPATH_S_UPDTHRESH_MASK 0x1f
+ 
+ #define IPATH_S_ABORT		0
+ #define IPATH_S_PIOINTBUFAVAIL	1
+ #define IPATH_S_PIOBUFAVAILUPD	2
+ #define IPATH_S_PIOENABLE	3
++#define IPATH_S_SDMAINTENABLE	9
++#define IPATH_S_SDMASINGLEDESCRIPTOR	10
++#define IPATH_S_SDMAENABLE	11
++#define IPATH_S_SDMAHALT	12
+ #define IPATH_S_DISARM		31
+ 
+ #define INFINIPATH_S_ABORT		(1U << IPATH_S_ABORT)
+ #define INFINIPATH_S_PIOINTBUFAVAIL	(1U << IPATH_S_PIOINTBUFAVAIL)
+ #define INFINIPATH_S_PIOBUFAVAILUPD	(1U << IPATH_S_PIOBUFAVAILUPD)
+ #define INFINIPATH_S_PIOENABLE		(1U << IPATH_S_PIOENABLE)
++#define INFINIPATH_S_SDMAINTENABLE	(1U << IPATH_S_SDMAINTENABLE)
++#define INFINIPATH_S_SDMASINGLEDESCRIPTOR \
++					(1U << IPATH_S_SDMASINGLEDESCRIPTOR)
++#define INFINIPATH_S_SDMAENABLE		(1U << IPATH_S_SDMAENABLE)
++#define INFINIPATH_S_SDMAHALT		(1U << IPATH_S_SDMAHALT)
+ #define INFINIPATH_S_DISARM		(1U << IPATH_S_DISARM)
+ 
+-/* kr_rcvctrl bits */
++/* kr_rcvctrl bits that are the same on multiple chips */
+ #define INFINIPATH_R_PORTENABLE_SHIFT 0
+ #define INFINIPATH_R_QPMAP_ENABLE (1ULL << 38)
+ 
+ /* kr_intstatus, kr_intclear, kr_intmask bits */
+-#define INFINIPATH_I_RCVURG_SHIFT 0
+-#define INFINIPATH_I_RCVAVAIL_SHIFT 12
+-#define INFINIPATH_I_ERROR        0x80000000
+-#define INFINIPATH_I_SPIOSENT     0x40000000
+-#define INFINIPATH_I_SPIOBUFAVAIL 0x20000000
+-#define INFINIPATH_I_GPIO         0x10000000
++#define INFINIPATH_I_SDMAINT		0x8000000000000000ULL
++#define INFINIPATH_I_SDMADISABLED	0x4000000000000000ULL
++#define INFINIPATH_I_ERROR		0x0000000080000000ULL
++#define INFINIPATH_I_SPIOSENT		0x0000000040000000ULL
++#define INFINIPATH_I_SPIOBUFAVAIL	0x0000000020000000ULL
++#define INFINIPATH_I_GPIO		0x0000000010000000ULL
++#define INFINIPATH_I_JINT		0x0000000004000000ULL
+ 
+ /* kr_errorstatus, kr_errorclear, kr_errormask bits */
+-#define INFINIPATH_E_RFORMATERR      0x0000000000000001ULL
+-#define INFINIPATH_E_RVCRC           0x0000000000000002ULL
+-#define INFINIPATH_E_RICRC           0x0000000000000004ULL
+-#define INFINIPATH_E_RMINPKTLEN      0x0000000000000008ULL
+-#define INFINIPATH_E_RMAXPKTLEN      0x0000000000000010ULL
+-#define INFINIPATH_E_RLONGPKTLEN     0x0000000000000020ULL
+-#define INFINIPATH_E_RSHORTPKTLEN    0x0000000000000040ULL
+-#define INFINIPATH_E_RUNEXPCHAR      0x0000000000000080ULL
+-#define INFINIPATH_E_RUNSUPVL        0x0000000000000100ULL
+-#define INFINIPATH_E_REBP            0x0000000000000200ULL
+-#define INFINIPATH_E_RIBFLOW         0x0000000000000400ULL
+-#define INFINIPATH_E_RBADVERSION     0x0000000000000800ULL
+-#define INFINIPATH_E_RRCVEGRFULL     0x0000000000001000ULL
+-#define INFINIPATH_E_RRCVHDRFULL     0x0000000000002000ULL
+-#define INFINIPATH_E_RBADTID         0x0000000000004000ULL
+-#define INFINIPATH_E_RHDRLEN         0x0000000000008000ULL
+-#define INFINIPATH_E_RHDR            0x0000000000010000ULL
+-#define INFINIPATH_E_RIBLOSTLINK     0x0000000000020000ULL
+-#define INFINIPATH_E_SMINPKTLEN      0x0000000020000000ULL
+-#define INFINIPATH_E_SMAXPKTLEN      0x0000000040000000ULL
+-#define INFINIPATH_E_SUNDERRUN       0x0000000080000000ULL
+-#define INFINIPATH_E_SPKTLEN         0x0000000100000000ULL
+-#define INFINIPATH_E_SDROPPEDSMPPKT  0x0000000200000000ULL
+-#define INFINIPATH_E_SDROPPEDDATAPKT 0x0000000400000000ULL
+-#define INFINIPATH_E_SPIOARMLAUNCH   0x0000000800000000ULL
+-#define INFINIPATH_E_SUNEXPERRPKTNUM 0x0000001000000000ULL
+-#define INFINIPATH_E_SUNSUPVL        0x0000002000000000ULL
+-#define INFINIPATH_E_IBSTATUSCHANGED 0x0001000000000000ULL
+-#define INFINIPATH_E_INVALIDADDR     0x0002000000000000ULL
+-#define INFINIPATH_E_RESET           0x0004000000000000ULL
+-#define INFINIPATH_E_HARDWARE        0x0008000000000000ULL
++#define INFINIPATH_E_RFORMATERR			0x0000000000000001ULL
++#define INFINIPATH_E_RVCRC			0x0000000000000002ULL
++#define INFINIPATH_E_RICRC			0x0000000000000004ULL
++#define INFINIPATH_E_RMINPKTLEN			0x0000000000000008ULL
++#define INFINIPATH_E_RMAXPKTLEN			0x0000000000000010ULL
++#define INFINIPATH_E_RLONGPKTLEN		0x0000000000000020ULL
++#define INFINIPATH_E_RSHORTPKTLEN		0x0000000000000040ULL
++#define INFINIPATH_E_RUNEXPCHAR			0x0000000000000080ULL
++#define INFINIPATH_E_RUNSUPVL			0x0000000000000100ULL
++#define INFINIPATH_E_REBP			0x0000000000000200ULL
++#define INFINIPATH_E_RIBFLOW			0x0000000000000400ULL
++#define INFINIPATH_E_RBADVERSION		0x0000000000000800ULL
++#define INFINIPATH_E_RRCVEGRFULL		0x0000000000001000ULL
++#define INFINIPATH_E_RRCVHDRFULL		0x0000000000002000ULL
++#define INFINIPATH_E_RBADTID			0x0000000000004000ULL
++#define INFINIPATH_E_RHDRLEN			0x0000000000008000ULL
++#define INFINIPATH_E_RHDR			0x0000000000010000ULL
++#define INFINIPATH_E_RIBLOSTLINK		0x0000000000020000ULL
++#define INFINIPATH_E_SENDSPECIALTRIGGER		0x0000000008000000ULL
++#define INFINIPATH_E_SDMADISABLED		0x0000000010000000ULL
++#define INFINIPATH_E_SMINPKTLEN			0x0000000020000000ULL
++#define INFINIPATH_E_SMAXPKTLEN			0x0000000040000000ULL
++#define INFINIPATH_E_SUNDERRUN			0x0000000080000000ULL
++#define INFINIPATH_E_SPKTLEN			0x0000000100000000ULL
++#define INFINIPATH_E_SDROPPEDSMPPKT		0x0000000200000000ULL
++#define INFINIPATH_E_SDROPPEDDATAPKT		0x0000000400000000ULL
++#define INFINIPATH_E_SPIOARMLAUNCH		0x0000000800000000ULL
++#define INFINIPATH_E_SUNEXPERRPKTNUM		0x0000001000000000ULL
++#define INFINIPATH_E_SUNSUPVL			0x0000002000000000ULL
++#define INFINIPATH_E_SENDBUFMISUSE		0x0000004000000000ULL
++#define INFINIPATH_E_SDMAGENMISMATCH		0x0000008000000000ULL
++#define INFINIPATH_E_SDMAOUTOFBOUND		0x0000010000000000ULL
++#define INFINIPATH_E_SDMATAILOUTOFBOUND		0x0000020000000000ULL
++#define INFINIPATH_E_SDMABASE			0x0000040000000000ULL
++#define INFINIPATH_E_SDMA1STDESC		0x0000080000000000ULL
++#define INFINIPATH_E_SDMARPYTAG			0x0000100000000000ULL
++#define INFINIPATH_E_SDMADWEN			0x0000200000000000ULL
++#define INFINIPATH_E_SDMAMISSINGDW		0x0000400000000000ULL
++#define INFINIPATH_E_SDMAUNEXPDATA		0x0000800000000000ULL
++#define INFINIPATH_E_IBSTATUSCHANGED		0x0001000000000000ULL
++#define INFINIPATH_E_INVALIDADDR		0x0002000000000000ULL
++#define INFINIPATH_E_RESET			0x0004000000000000ULL
++#define INFINIPATH_E_HARDWARE			0x0008000000000000ULL
++#define INFINIPATH_E_SDMADESCADDRMISALIGN	0x0010000000000000ULL
++#define INFINIPATH_E_INVALIDEEPCMD		0x0020000000000000ULL
+ 
+ /*
+  * this is used to print "common" packet errors only when the
+@@ -134,6 +159,17 @@
+ 		| INFINIPATH_E_RICRC | INFINIPATH_E_RSHORTPKTLEN \
+ 		| INFINIPATH_E_REBP )
+ 
++/* Convenience for decoding Send DMA errors */
++#define INFINIPATH_E_SDMAERRS ( \
++	INFINIPATH_E_SDMAGENMISMATCH | INFINIPATH_E_SDMAOUTOFBOUND | \
++	INFINIPATH_E_SDMATAILOUTOFBOUND | INFINIPATH_E_SDMABASE | \
++	INFINIPATH_E_SDMA1STDESC | INFINIPATH_E_SDMARPYTAG | \
++	INFINIPATH_E_SDMADWEN | INFINIPATH_E_SDMAMISSINGDW | \
++	INFINIPATH_E_SDMAUNEXPDATA | \
++	INFINIPATH_E_SDMADESCADDRMISALIGN | \
++	INFINIPATH_E_SDMADISABLED | \
++	INFINIPATH_E_SENDBUFMISUSE)
++
+ /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+ /* TXEMEMPARITYERR bit 0: PIObuf, 1: PIOpbc, 2: launchfifo
+  * RXEMEMPARITYERR bit 0: rcvbuf, 1: lookupq, 2:  expTID, 3: eagerTID
+@@ -158,7 +194,7 @@
+ #define INFINIPATH_HWE_RXEMEMPARITYERR_HDRINFO  0x40ULL
+ /* waldo specific -- find the rest in ipath_6110.c */
+ #define INFINIPATH_HWE_RXDSYNCMEMPARITYERR  0x0000000400000000ULL
+-/* monty specific -- find the rest in ipath_6120.c */
++/* 6120/7220 specific -- find the rest in ipath_6120.c and ipath_7220.c */
+ #define INFINIPATH_HWE_MEMBISTFAILED	0x0040000000000000ULL
+ 
+ /* kr_hwdiagctrl bits */
+@@ -185,8 +221,8 @@
+ #define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3
+ #define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16
+ #define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL
+-#define INFINIPATH_IBCC_LINKCMD_DOWN 1	/* move to 0x11 */
+-#define INFINIPATH_IBCC_LINKCMD_ARMED 2	/* move to 0x21 */
++#define INFINIPATH_IBCC_LINKCMD_DOWN 1		/* move to 0x11 */
++#define INFINIPATH_IBCC_LINKCMD_ARMED 2		/* move to 0x21 */
+ #define INFINIPATH_IBCC_LINKCMD_ACTIVE 3	/* move to 0x31 */
+ #define INFINIPATH_IBCC_LINKCMD_SHIFT 18
+ #define INFINIPATH_IBCC_MAXPKTLEN_MASK 0x7FFULL
+@@ -201,10 +237,9 @@
+ #define INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE 0x4000000000000000ULL
+ 
+ /* kr_ibcstatus bits */
+-#define INFINIPATH_IBCS_LINKTRAININGSTATE_MASK 0xF
+ #define INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT 0
+ #define INFINIPATH_IBCS_LINKSTATE_MASK 0x7
+-#define INFINIPATH_IBCS_LINKSTATE_SHIFT 4
++
+ #define INFINIPATH_IBCS_TXREADY       0x40000000
+ #define INFINIPATH_IBCS_TXCREDITOK    0x80000000
+ /* link training states (shift by
+@@ -222,30 +257,13 @@
+ #define INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN	0x0c
+ #define INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT	0x0e
+ #define INFINIPATH_IBCS_LT_STATE_RECOVERIDLE	0x0f
+-/* link state machine states (shift by INFINIPATH_IBCS_LINKSTATE_SHIFT) */
++/* link state machine states (shift by ibcs_ls_shift) */
+ #define INFINIPATH_IBCS_L_STATE_DOWN		0x0
+ #define INFINIPATH_IBCS_L_STATE_INIT		0x1
+ #define INFINIPATH_IBCS_L_STATE_ARM		0x2
+ #define INFINIPATH_IBCS_L_STATE_ACTIVE		0x3
+ #define INFINIPATH_IBCS_L_STATE_ACT_DEFER	0x4
+ 
+-/* combination link status states that we use with some frequency */
+-#define IPATH_IBSTATE_MASK ((INFINIPATH_IBCS_LINKTRAININGSTATE_MASK \
+-		<< INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) | \
+-		(INFINIPATH_IBCS_LINKSTATE_MASK \
+-		<<INFINIPATH_IBCS_LINKSTATE_SHIFT))
+-#define IPATH_IBSTATE_INIT ((INFINIPATH_IBCS_L_STATE_INIT \
+-		<< INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+-		(INFINIPATH_IBCS_LT_STATE_LINKUP \
+-		<<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+-#define IPATH_IBSTATE_ARM ((INFINIPATH_IBCS_L_STATE_ARM \
+-		<< INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+-		(INFINIPATH_IBCS_LT_STATE_LINKUP \
+-		<<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+-#define IPATH_IBSTATE_ACTIVE ((INFINIPATH_IBCS_L_STATE_ACTIVE \
+-		<< INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+-		(INFINIPATH_IBCS_LT_STATE_LINKUP \
+-		<<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+ 
+ /* kr_extstatus bits */
+ #define INFINIPATH_EXTS_SERDESPLLLOCK 0x1
+@@ -286,8 +304,7 @@
+ /* L1 Power down; use with RXDETECT, Otherwise not used on IB side */
+ #define INFINIPATH_SERDC0_L1PWR_DN	 0xF0ULL
+ 
+-/* kr_xgxsconfig bits */
+-#define INFINIPATH_XGXS_RESET          0x7ULL
++/* common kr_xgxsconfig bits (or safe in all, even if not implemented) */
+ #define INFINIPATH_XGXS_RX_POL_SHIFT 19
+ #define INFINIPATH_XGXS_RX_POL_MASK 0xfULL
+ 
+@@ -417,6 +434,29 @@ struct ipath_kregs {
+ 	ipath_kreg kr_pcieq1serdesconfig0;
+ 	ipath_kreg kr_pcieq1serdesconfig1;
+ 	ipath_kreg kr_pcieq1serdesstatus;
++	ipath_kreg kr_hrtbt_guid;
++	ipath_kreg kr_ibcddrctrl;
++	ipath_kreg kr_ibcddrstatus;
++	ipath_kreg kr_jintreload;
++
++	/* send dma related regs */
++	ipath_kreg kr_senddmabase;
++	ipath_kreg kr_senddmalengen;
++	ipath_kreg kr_senddmatail;
++	ipath_kreg kr_senddmahead;
++	ipath_kreg kr_senddmaheadaddr;
++	ipath_kreg kr_senddmabufmask0;
++	ipath_kreg kr_senddmabufmask1;
++	ipath_kreg kr_senddmabufmask2;
++	ipath_kreg kr_senddmastatus;
++
++	/* SerDes related regs (IBA7220-only) */
++	ipath_kreg kr_ibserdesctrl;
++	ipath_kreg kr_ib_epbacc;
++	ipath_kreg kr_ib_epbtrans;
++	ipath_kreg kr_pcie_epbacc;
++	ipath_kreg kr_pcie_epbtrans;
++	ipath_kreg kr_ib_ddsrxeq;
+ };
+ 
+ struct ipath_cregs {
+diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
+index a59bdbd..8ac5c1d 100644
+--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
++++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
+@@ -310,7 +310,7 @@ again:
+ 	switch (wqe->wr.opcode) {
+ 	case IB_WR_SEND_WITH_IMM:
+ 		wc.wc_flags = IB_WC_WITH_IMM;
+-		wc.imm_data = wqe->wr.imm_data;
++		wc.imm_data = wqe->wr.ex.imm_data;
+ 		/* FALLTHROUGH */
+ 	case IB_WR_SEND:
+ 		if (!ipath_get_rwqe(qp, 0)) {
+@@ -339,7 +339,7 @@ again:
+ 			goto err;
+ 		}
+ 		wc.wc_flags = IB_WC_WITH_IMM;
+-		wc.imm_data = wqe->wr.imm_data;
++		wc.imm_data = wqe->wr.ex.imm_data;
+ 		if (!ipath_get_rwqe(qp, 1))
+ 			goto rnr_nak;
+ 		/* FALLTHROUGH */
+@@ -483,14 +483,16 @@ done:
+ 
+ static void want_buffer(struct ipath_devdata *dd)
+ {
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+-	dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-			 dd->ipath_sendctrl);
+-	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+-	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++	if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA)) {
++		unsigned long flags;
++
++		spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++		dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++				 dd->ipath_sendctrl);
++		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++	}
+ }
+ 
+ /**
+diff --git a/drivers/infiniband/hw/ipath/ipath_sd7220.c b/drivers/infiniband/hw/ipath/ipath_sd7220.c
+new file mode 100644
+index 0000000..aa47eb5
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_sd7220.c
+@@ -0,0 +1,1462 @@
++/*
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++/*
++ * This file contains all of the code that is specific to the SerDes
++ * on the InfiniPath 7220 chip.
++ */
++
++#include <linux/pci.h>
++#include <linux/delay.h>
++
++#include "ipath_kernel.h"
++#include "ipath_registers.h"
++#include "ipath_7220.h"
++
++/*
++ * The IBSerDesMappTable is a memory that holds values to be stored in
++ * various SerDes registers by IBC. It is not part of the normal kregs
++ * map and is used in exactly one place, hence the #define below.
++ */
++#define KR_IBSerDesMappTable (0x94000 / (sizeof(uint64_t)))
++
++/*
++ * Below used for sdnum parameter, selecting one of the two sections
++ * used for PCIe, or the single SerDes used for IB.
++ */
++#define PCIE_SERDES0 0
++#define PCIE_SERDES1 1
++
++/*
++ * The EPB requires addressing in a particular form. EPB_LOC() is intended
++ * to make #definitions a little more readable.
++ */
++#define EPB_ADDR_SHF 8
++#define EPB_LOC(chn, elt, reg) \
++	(((elt & 0xf) | ((chn & 7) << 4) | ((reg & 0x3f) << 9)) << \
++	 EPB_ADDR_SHF)
++#define EPB_IB_QUAD0_CS_SHF (25)
++#define EPB_IB_QUAD0_CS (1U <<  EPB_IB_QUAD0_CS_SHF)
++#define EPB_IB_UC_CS_SHF (26)
++#define EPB_PCIE_UC_CS_SHF (27)
++#define EPB_GLOBAL_WR (1U << (EPB_ADDR_SHF + 8))
++
++/* Forward declarations. */
++static int ipath_sd7220_reg_mod(struct ipath_devdata *dd, int sdnum, u32 loc,
++				u32 data, u32 mask);
++static int ibsd_mod_allchnls(struct ipath_devdata *dd, int loc, int val,
++			     int mask);
++static int ipath_sd_trimdone_poll(struct ipath_devdata *dd);
++static void ipath_sd_trimdone_monitor(struct ipath_devdata *dd,
++				      const char *where);
++static int ipath_sd_setvals(struct ipath_devdata *dd);
++static int ipath_sd_early(struct ipath_devdata *dd);
++static int ipath_sd_dactrim(struct ipath_devdata *dd);
++/* Set the registers that IBC may muck with to their default "preset" values */
++int ipath_sd7220_presets(struct ipath_devdata *dd);
++static int ipath_internal_presets(struct ipath_devdata *dd);
++/* Tweak the register (CMUCTRL5) that contains the TRIMSELF controls */
++static int ipath_sd_trimself(struct ipath_devdata *dd, int val);
++static int epb_access(struct ipath_devdata *dd, int sdnum, int claim);
++
++void ipath_set_relock_poll(struct ipath_devdata *dd, int ibup);
++
++/*
++ * Below keeps track of whether the "once per power-on" initialization has
++ * been done, because uC code Version 1.32.17 or higher allows the uC to
++ * be reset at will, and Automatic Equalization may require it. So the
++ * state of the reset "pin", as reflected in was_reset parameter to
++ * ipath_sd7220_init() is no longer valid. Instead, we check for the
++ * actual uC code having been loaded.
++ */
++static int ipath_ibsd_ucode_loaded(struct ipath_devdata *dd)
++{
++	if (!dd->serdes_first_init_done && (ipath_sd7220_ib_vfy(dd) > 0))
++		dd->serdes_first_init_done = 1;
++	return dd->serdes_first_init_done;
++}
++
++/* repeat #define for local use. "Real" #define is in ipath_iba7220.c */
++#define INFINIPATH_HWE_IB_UC_MEMORYPARITYERR      0x0000004000000000ULL
++#define IB_MPREG5 (EPB_LOC(6, 0, 0xE) | (1L << EPB_IB_UC_CS_SHF))
++#define IB_MPREG6 (EPB_LOC(6, 0, 0xF) | (1U << EPB_IB_UC_CS_SHF))
++#define UC_PAR_CLR_D 8
++#define UC_PAR_CLR_M 0xC
++#define IB_CTRL2(chn) (EPB_LOC(chn, 7, 3) | EPB_IB_QUAD0_CS)
++#define START_EQ1(chan) EPB_LOC(chan, 7, 0x27)
++
++void ipath_sd7220_clr_ibpar(struct ipath_devdata *dd)
++{
++	int ret;
++
++	/* clear, then re-enable parity errs */
++	ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6,
++		UC_PAR_CLR_D, UC_PAR_CLR_M);
++	if (ret < 0) {
++		ipath_dev_err(dd, "Failed clearing IBSerDes Parity err\n");
++		goto bail;
++	}
++	ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0,
++		UC_PAR_CLR_M);
++
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++	udelay(4);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
++		INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++bail:
++	return;
++}
++
++/*
++ * After a reset or other unusual event, the epb interface may need
++ * to be re-synchronized, between the host and the uC.
++ * returns <0 for failure to resync within IBSD_RESYNC_TRIES (not expected)
++ */
++#define IBSD_RESYNC_TRIES 3
++#define IB_PGUDP(chn) (EPB_LOC((chn), 2, 1) | EPB_IB_QUAD0_CS)
++#define IB_CMUDONE(chn) (EPB_LOC((chn), 7, 0xF) | EPB_IB_QUAD0_CS)
++
++static int ipath_resync_ibepb(struct ipath_devdata *dd)
++{
++	int ret, pat, tries, chn;
++	u32 loc;
++
++	ret = -1;
++	chn = 0;
++	for (tries = 0; tries < (4 * IBSD_RESYNC_TRIES); ++tries) {
++		loc = IB_PGUDP(chn);
++		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
++		if (ret < 0) {
++			ipath_dev_err(dd, "Failed read in resync\n");
++			continue;
++		}
++		if (ret != 0xF0 && ret != 0x55 && tries == 0)
++			ipath_dev_err(dd, "unexpected pattern in resync\n");
++		pat = ret ^ 0xA5; /* alternate F0 and 55 */
++		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, pat, 0xFF);
++		if (ret < 0) {
++			ipath_dev_err(dd, "Failed write in resync\n");
++			continue;
++		}
++		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
++		if (ret < 0) {
++			ipath_dev_err(dd, "Failed re-read in resync\n");
++			continue;
++		}
++		if (ret != pat) {
++			ipath_dev_err(dd, "Failed compare1 in resync\n");
++			continue;
++		}
++		loc = IB_CMUDONE(chn);
++		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
++		if (ret < 0) {
++			ipath_dev_err(dd, "Failed CMUDONE rd in resync\n");
++			continue;
++		}
++		if ((ret & 0x70) != ((chn << 4) | 0x40)) {
++			ipath_dev_err(dd, "Bad CMUDONE value %02X, chn %d\n",
++				ret, chn);
++			continue;
++		}
++		if (++chn == 4)
++			break;  /* Success */
++	}
++	ipath_cdbg(VERBOSE, "Resync in %d tries\n", tries);
++	return (ret > 0) ? 0 : ret;
++}
++
++/*
++ * Localize the stuff that should be done to change IB uC reset
++ * returns <0 for errors.
++ */
++static int ipath_ibsd_reset(struct ipath_devdata *dd, int assert_rst)
++{
++	u64 rst_val;
++	int ret = 0;
++	unsigned long flags;
++
++	rst_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibserdesctrl);
++	if (assert_rst) {
++		/*
++		 * Vendor recommends "interrupting" uC before reset, to
++		 * minimize possible glitches.
++		 */
++		spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
++		epb_access(dd, IB_7220_SERDES, 1);
++		rst_val |= 1ULL;
++		/* Squelch possible parity error from _asserting_ reset */
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++			dd->ipath_hwerrmask &
++			~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val);
++		/* flush write, delay to ensure it took effect */
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++		udelay(2);
++		/* once it's reset, can remove interrupt */
++		epb_access(dd, IB_7220_SERDES, -1);
++		spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++	} else {
++		/*
++		 * Before we de-assert reset, we need to deal with
++		 * possible glitch on the Parity-error line.
++		 * Suppress it around the reset, both in chip-level
++		 * hwerrmask and in IB uC control reg. uC will allow
++		 * it again during startup.
++		 */
++		u64 val;
++		rst_val &= ~(1ULL);
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++			dd->ipath_hwerrmask &
++			~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
++
++		ret = ipath_resync_ibepb(dd);
++		if (ret < 0)
++			ipath_dev_err(dd, "unable to re-sync IB EPB\n");
++
++		/* set uC control regs to suppress parity errs */
++		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG5, 1, 1);
++		if (ret < 0)
++			goto bail;
++		/* IB uC code past Version 1.32.17 allow suppression of wdog */
++		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80,
++			0x80);
++		if (ret < 0) {
++			ipath_dev_err(dd, "Failed to set WDOG disable\n");
++			goto bail;
++		}
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val);
++		/* flush write, delay for startup */
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++		udelay(1);
++		/* clear, then re-enable parity errs */
++		ipath_sd7220_clr_ibpar(dd);
++		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
++		if (val & INFINIPATH_HWE_IB_UC_MEMORYPARITYERR) {
++			ipath_dev_err(dd, "IBUC Parity still set after RST\n");
++			dd->ipath_hwerrmask &=
++				~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR;
++		}
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++			dd->ipath_hwerrmask);
++	}
++
++bail:
++	return ret;
++}
++
++static void ipath_sd_trimdone_monitor(struct ipath_devdata *dd,
++       const char *where)
++{
++	int ret, chn, baduns;
++	u64 val;
++
++	if (!where)
++		where = "?";
++
++	/* give time for reset to settle out in EPB */
++	udelay(2);
++
++	ret = ipath_resync_ibepb(dd);
++	if (ret < 0)
++		ipath_dev_err(dd, "not able to re-sync IB EPB (%s)\n", where);
++
++	/* Do "sacrificial read" to get EPB in sane state after reset */
++	ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(0), 0, 0);
++	if (ret < 0)
++		ipath_dev_err(dd, "Failed TRIMDONE 1st read, (%s)\n", where);
++
++	/* Check/show "summary" Trim-done bit in IBCStatus */
++	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
++	if (val & (1ULL << 11))
++		ipath_cdbg(VERBOSE, "IBCS TRIMDONE set (%s)\n", where);
++	else
++		ipath_dev_err(dd, "IBCS TRIMDONE clear (%s)\n", where);
++
++	udelay(2);
++
++	ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80);
++	if (ret < 0)
++		ipath_dev_err(dd, "Failed Dummy RMW, (%s)\n", where);
++	udelay(10);
++
++	baduns = 0;
++
++	for (chn = 3; chn >= 0; --chn) {
++		/* Read CTRL reg for each channel to check TRIMDONE */
++		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++			IB_CTRL2(chn), 0, 0);
++		if (ret < 0)
++			ipath_dev_err(dd, "Failed checking TRIMDONE, chn %d"
++				" (%s)\n", chn, where);
++
++		if (!(ret & 0x10)) {
++			int probe;
++			baduns |= (1 << chn);
++			ipath_dev_err(dd, "TRIMDONE cleared on chn %d (%02X)."
++				" (%s)\n", chn, ret, where);
++			probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++				IB_PGUDP(0), 0, 0);
++			ipath_dev_err(dd, "probe is %d (%02X)\n",
++				probe, probe);
++			probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++				IB_CTRL2(chn), 0, 0);
++			ipath_dev_err(dd, "re-read: %d (%02X)\n",
++				probe, probe);
++			ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++				IB_CTRL2(chn), 0x10, 0x10);
++			if (ret < 0)
++				ipath_dev_err(dd,
++					"Err on TRIMDONE rewrite1\n");
++		}
++	}
++	for (chn = 3; chn >= 0; --chn) {
++		/* Read CTRL reg for each channel to check TRIMDONE */
++		if (baduns & (1 << chn)) {
++			ipath_dev_err(dd,
++				"Reseting TRIMDONE on chn %d (%s)\n",
++				chn, where);
++			ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++				IB_CTRL2(chn), 0x10, 0x10);
++			if (ret < 0)
++				ipath_dev_err(dd, "Failed re-setting "
++					"TRIMDONE, chn %d (%s)\n",
++					chn, where);
++		}
++	}
++}
++
++/*
++ * Below is portion of IBA7220-specific bringup_serdes() that actually
++ * deals with registers and memory within the SerDes itself.
++ * Post IB uC code version 1.32.17, was_reset being 1 is not really
++ * informative, so we double-check.
++ */
++int ipath_sd7220_init(struct ipath_devdata *dd, int was_reset)
++{
++	int ret = 1; /* default to failure */
++	int first_reset;
++	int val_stat;
++
++	if (!was_reset) {
++		/* entered with reset not asserted, we need to do it */
++		ipath_ibsd_reset(dd, 1);
++		ipath_sd_trimdone_monitor(dd, "Driver-reload");
++	}
++
++	/* Substitute our deduced value for was_reset */
++	ret = ipath_ibsd_ucode_loaded(dd);
++	if (ret < 0) {
++		ret = 1;
++		goto done;
++	}
++	first_reset = !ret; /* First reset if IBSD uCode not yet loaded */
++
++	/*
++	 * Alter some regs per vendor latest doc, reset-defaults
++	 * are not right for IB.
++	 */
++	ret = ipath_sd_early(dd);
++	if (ret < 0) {
++		ipath_dev_err(dd, "Failed to set IB SERDES early defaults\n");
++		ret = 1;
++		goto done;
++	}
++
++	/*
++	 * Set DAC manual trim IB.
++	 * We only do this once after chip has been reset (usually
++	 * same as once per system boot).
++	 */
++	if (first_reset) {
++		ret = ipath_sd_dactrim(dd);
++		if (ret < 0) {
++			ipath_dev_err(dd, "Failed IB SERDES DAC trim\n");
++			ret = 1;
++			goto done;
++		}
++	}
++
++	/*
++	 * Set various registers (DDS and RXEQ) that will be
++	 * controlled by IBC (in 1.2 mode) to reasonable preset values
++	 * Calling the "internal" version avoids the "check for needed"
++	 * and "trimdone monitor" that might be counter-productive.
++	 */
++	ret = ipath_internal_presets(dd);
++	if (ret < 0) {
++		ipath_dev_err(dd, "Failed to set IB SERDES presets\n");
++		ret = 1;
++		goto done;
++	}
++	ret = ipath_sd_trimself(dd, 0x80);
++	if (ret < 0) {
++		ipath_dev_err(dd, "Failed to set IB SERDES TRIMSELF\n");
++		ret = 1;
++		goto done;
++	}
++
++	/* Load image, then try to verify */
++	ret = 0;	/* Assume success */
++	if (first_reset) {
++		int vfy;
++		int trim_done;
++		ipath_dbg("SerDes uC was reset, reloading PRAM\n");
++		ret = ipath_sd7220_ib_load(dd);
++		if (ret < 0) {
++			ipath_dev_err(dd, "Failed to load IB SERDES image\n");
++			ret = 1;
++			goto done;
++		}
++
++		/* Loaded image, try to verify */
++		vfy = ipath_sd7220_ib_vfy(dd);
++		if (vfy != ret) {
++			ipath_dev_err(dd, "SERDES PRAM VFY failed\n");
++			ret = 1;
++			goto done;
++		}
++		/*
++		 * Loaded and verified. Almost good...
++		 * hold "success" in ret
++		 */
++		ret = 0;
++
++		/*
++		 * Prev steps all worked, continue bringup
++		 * De-assert RESET to uC, only in first reset, to allow
++		 * trimming.
++		 *
++		 * Since our default setup sets START_EQ1 to
++		 * PRESET, we need to clear that for this very first run.
++		 */
++		ret = ibsd_mod_allchnls(dd, START_EQ1(0), 0, 0x38);
++		if (ret < 0) {
++			ipath_dev_err(dd, "Failed clearing START_EQ1\n");
++			ret = 1;
++			goto done;
++		}
++
++		ipath_ibsd_reset(dd, 0);
++		/*
++		 * If this is not the first reset, trimdone should be set
++		 * already.
++		 */
++		trim_done = ipath_sd_trimdone_poll(dd);
++		/*
++		 * Whether or not trimdone succeeded, we need to put the
++		 * uC back into reset to avoid a possible fight with the
++		 * IBC state-machine.
++		 */
++		ipath_ibsd_reset(dd, 1);
++
++		if (!trim_done) {
++			ipath_dev_err(dd, "No TRIMDONE seen\n");
++			ret = 1;
++			goto done;
++		}
++
++		ipath_sd_trimdone_monitor(dd, "First-reset");
++		/* Remember so we do not re-do the load, dactrim, etc. */
++		dd->serdes_first_init_done = 1;
++	}
++	/*
++	 * Setup for channel training and load values for
++	 * RxEq and DDS in tables used by IBC in IB1.2 mode
++	 */
++
++	val_stat = ipath_sd_setvals(dd);
++	if (val_stat < 0)
++		ret = 1;
++done:
++	/* start relock timer regardless, but start at 1 second */
++	ipath_set_relock_poll(dd, -1);
++	return ret;
++}
++
++#define EPB_ACC_REQ 1
++#define EPB_ACC_GNT 0x100
++#define EPB_DATA_MASK 0xFF
++#define EPB_RD (1ULL << 24)
++#define EPB_TRANS_RDY (1ULL << 31)
++#define EPB_TRANS_ERR (1ULL << 30)
++#define EPB_TRANS_TRIES 5
++
++/*
++ * query, claim, release ownership of the EPB (External Parallel Bus)
++ * for a specified SERDES.
++ * the "claim" parameter is >0 to claim, <0 to release, 0 to query.
++ * Returns <0 for errors, >0 if we had ownership, else 0.
++ */
++static int epb_access(struct ipath_devdata *dd, int sdnum, int claim)
++{
++	u16 acc;
++	u64 accval;
++	int owned = 0;
++	u64 oct_sel = 0;
++
++	switch (sdnum) {
++	case IB_7220_SERDES :
++		/*
++		 * The IB SERDES "ownership" is fairly simple. A single each
++		 * request/grant.
++		 */
++		acc = dd->ipath_kregs->kr_ib_epbacc;
++		break;
++	case PCIE_SERDES0 :
++	case PCIE_SERDES1 :
++		/* PCIe SERDES has two "octants", need to select which */
++		acc = dd->ipath_kregs->kr_pcie_epbacc;
++		oct_sel = (2 << (sdnum - PCIE_SERDES0));
++		break;
++	default :
++		return 0;
++	}
++
++	/* Make sure any outstanding transaction was seen */
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++	udelay(15);
++
++	accval = ipath_read_kreg32(dd, acc);
++
++	owned = !!(accval & EPB_ACC_GNT);
++	if (claim < 0) {
++		/* Need to release */
++		u64 pollval;
++		/*
++		 * The only writeable bits are the request and CS.
++		 * Both should be clear
++		 */
++		u64 newval = 0;
++		ipath_write_kreg(dd, acc, newval);
++		/* First read after write is not trustworthy */
++		pollval = ipath_read_kreg32(dd, acc);
++		udelay(5);
++		pollval = ipath_read_kreg32(dd, acc);
++		if (pollval & EPB_ACC_GNT)
++			owned = -1;
++	} else if (claim > 0) {
++		/* Need to claim */
++		u64 pollval;
++		u64 newval = EPB_ACC_REQ | oct_sel;
++		ipath_write_kreg(dd, acc, newval);
++		/* First read after write is not trustworthy */
++		pollval = ipath_read_kreg32(dd, acc);
++		udelay(5);
++		pollval = ipath_read_kreg32(dd, acc);
++		if (!(pollval & EPB_ACC_GNT))
++			owned = -1;
++	}
++	return owned;
++}
++
++/*
++ * Lemma to deal with race condition of write..read to epb regs
++ */
++static int epb_trans(struct ipath_devdata *dd, u16 reg, u64 i_val, u64 *o_vp)
++{
++	int tries;
++	u64 transval;
++
++
++	ipath_write_kreg(dd, reg, i_val);
++	/* Throw away first read, as RDY bit may be stale */
++	transval = ipath_read_kreg64(dd, reg);
++
++	for (tries = EPB_TRANS_TRIES; tries; --tries) {
++		transval = ipath_read_kreg32(dd, reg);
++		if (transval & EPB_TRANS_RDY)
++			break;
++		udelay(5);
++	}
++	if (transval & EPB_TRANS_ERR)
++		return -1;
++	if (tries > 0 && o_vp)
++		*o_vp = transval;
++	return tries;
++}
++
++/**
++ *
++ * ipath_sd7220_reg_mod - modify SERDES register
++ * @dd: the infinipath device
++ * @sdnum: which SERDES to access
++ * @loc: location - channel, element, register, as packed by EPB_LOC() macro.
++ * @wd: Write Data - value to set in register
++ * @mask: ones where data should be spliced into reg.
++ *
++ * Basic register read/modify/write, with un-needed acesses elided. That is,
++ * a mask of zero will prevent write, while a mask of 0xFF will prevent read.
++ * returns current (presumed, if a write was done) contents of selected
++ * register, or <0 if errors.
++ */
++static int ipath_sd7220_reg_mod(struct ipath_devdata *dd, int sdnum, u32 loc,
++				u32 wd, u32 mask)
++{
++	u16 trans;
++	u64 transval;
++	int owned;
++	int tries, ret;
++	unsigned long flags;
++
++	switch (sdnum) {
++	case IB_7220_SERDES :
++		trans = dd->ipath_kregs->kr_ib_epbtrans;
++		break;
++	case PCIE_SERDES0 :
++	case PCIE_SERDES1 :
++		trans = dd->ipath_kregs->kr_pcie_epbtrans;
++		break;
++	default :
++		return -1;
++	}
++
++	/*
++	 * All access is locked in software (vs other host threads) and
++	 * hardware (vs uC access).
++	 */
++	spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
++
++	owned = epb_access(dd, sdnum, 1);
++	if (owned < 0) {
++		spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++		return -1;
++	}
++	ret = 0;
++	for (tries = EPB_TRANS_TRIES; tries; --tries) {
++		transval = ipath_read_kreg32(dd, trans);
++		if (transval & EPB_TRANS_RDY)
++			break;
++		udelay(5);
++	}
++
++	if (tries > 0) {
++		tries = 1;	/* to make read-skip work */
++		if (mask != 0xFF) {
++			/*
++			 * Not a pure write, so need to read.
++			 * loc encodes chip-select as well as address
++			 */
++			transval = loc | EPB_RD;
++			tries = epb_trans(dd, trans, transval, &transval);
++		}
++		if (tries > 0 && mask != 0) {
++			/*
++			 * Not a pure read, so need to write.
++			 */
++			wd = (wd & mask) | (transval & ~mask);
++			transval = loc | (wd & EPB_DATA_MASK);
++			tries = epb_trans(dd, trans, transval, &transval);
++		}
++	}
++	/* else, failed to see ready, what error-handling? */
++
++	/*
++	 * Release bus. Failure is an error.
++	 */
++	if (epb_access(dd, sdnum, -1) < 0)
++		ret = -1;
++	else
++		ret = transval & EPB_DATA_MASK;
++
++	spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++	if (tries <= 0)
++		ret = -1;
++	return ret;
++}
++
++#define EPB_ROM_R (2)
++#define EPB_ROM_W (1)
++/*
++ * Below, all uC-related, use appropriate UC_CS, depending
++ * on which SerDes is used.
++ */
++#define EPB_UC_CTL EPB_LOC(6, 0, 0)
++#define EPB_MADDRL EPB_LOC(6, 0, 2)
++#define EPB_MADDRH EPB_LOC(6, 0, 3)
++#define EPB_ROMDATA EPB_LOC(6, 0, 4)
++#define EPB_RAMDATA EPB_LOC(6, 0, 5)
++
++/* Transfer date to/from uC Program RAM of IB or PCIe SerDes */
++static int ipath_sd7220_ram_xfer(struct ipath_devdata *dd, int sdnum, u32 loc,
++			       u8 *buf, int cnt, int rd_notwr)
++{
++	u16 trans;
++	u64 transval;
++	u64 csbit;
++	int owned;
++	int tries;
++	int sofar;
++	int addr;
++	int ret;
++	unsigned long flags;
++	const char *op;
++
++	/* Pick appropriate transaction reg and "Chip select" for this serdes */
++	switch (sdnum) {
++	case IB_7220_SERDES :
++		csbit = 1ULL << EPB_IB_UC_CS_SHF;
++		trans = dd->ipath_kregs->kr_ib_epbtrans;
++		break;
++	case PCIE_SERDES0 :
++	case PCIE_SERDES1 :
++		/* PCIe SERDES has uC "chip select" in different bit, too */
++		csbit = 1ULL << EPB_PCIE_UC_CS_SHF;
++		trans = dd->ipath_kregs->kr_pcie_epbtrans;
++		break;
++	default :
++		return -1;
++	}
++
++	op = rd_notwr ? "Rd" : "Wr";
++	spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
++
++	owned = epb_access(dd, sdnum, 1);
++	if (owned < 0) {
++		spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++		ipath_dbg("Could not get %s access to %s EPB: %X, loc %X\n",
++			op, (sdnum == IB_7220_SERDES) ? "IB" : "PCIe",
++			owned, loc);
++		return -1;
++	}
++
++	/*
++	 * In future code, we may need to distinguish several address ranges,
++	 * and select various memories based on this. For now, just trim
++	 * "loc" (location including address and memory select) to
++	 * "addr" (address within memory). we will only support PRAM
++	 * The memory is 8KB.
++	 */
++	addr = loc & 0x1FFF;
++	for (tries = EPB_TRANS_TRIES; tries; --tries) {
++		transval = ipath_read_kreg32(dd, trans);
++		if (transval & EPB_TRANS_RDY)
++			break;
++		udelay(5);
++	}
++
++	sofar = 0;
++	if (tries <= 0)
++		ipath_dbg("No initial RDY on EPB access request\n");
++	else {
++		/*
++		 * Every "memory" access is doubly-indirect.
++		 * We set two bytes of address, then read/write
++		 * one or mores bytes of data.
++		 */
++
++		/* First, we set control to "Read" or "Write" */
++		transval = csbit | EPB_UC_CTL |
++			(rd_notwr ? EPB_ROM_R : EPB_ROM_W);
++		tries = epb_trans(dd, trans, transval, &transval);
++		if (tries <= 0)
++			ipath_dbg("No EPB response to uC %s cmd\n", op);
++		while (tries > 0 && sofar < cnt) {
++			if (!sofar) {
++				/* Only set address at start of chunk */
++				int addrbyte = (addr + sofar) >> 8;
++				transval = csbit | EPB_MADDRH | addrbyte;
++				tries = epb_trans(dd, trans, transval,
++						  &transval);
++				if (tries <= 0) {
++					ipath_dbg("No EPB response ADDRH\n");
++					break;
++				}
++				addrbyte = (addr + sofar) & 0xFF;
++				transval = csbit | EPB_MADDRL | addrbyte;
++				tries = epb_trans(dd, trans, transval,
++						 &transval);
++				if (tries <= 0) {
++					ipath_dbg("No EPB response ADDRL\n");
++					break;
++				}
++			}
++
++			if (rd_notwr)
++				transval = csbit | EPB_ROMDATA | EPB_RD;
++			else
++				transval = csbit | EPB_ROMDATA | buf[sofar];
++			tries = epb_trans(dd, trans, transval, &transval);
++			if (tries <= 0) {
++				ipath_dbg("No EPB response DATA\n");
++				break;
++			}
++			if (rd_notwr)
++				buf[sofar] = transval & EPB_DATA_MASK;
++			++sofar;
++		}
++		/* Finally, clear control-bit for Read or Write */
++		transval = csbit | EPB_UC_CTL;
++		tries = epb_trans(dd, trans, transval, &transval);
++		if (tries <= 0)
++			ipath_dbg("No EPB response to drop of uC %s cmd\n", op);
++	}
++
++	ret = sofar;
++	/* Release bus. Failure is an error */
++	if (epb_access(dd, sdnum, -1) < 0)
++		ret = -1;
++
++	spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++	if (tries <= 0) {
++		ipath_dbg("SERDES PRAM %s failed after %d bytes\n", op, sofar);
++		ret = -1;
++	}
++	return ret;
++}
++
++#define PROG_CHUNK 64
++
++int ipath_sd7220_prog_ld(struct ipath_devdata *dd, int sdnum,
++	u8 *img, int len, int offset)
++{
++	int cnt, sofar, req;
++
++	sofar = 0;
++	while (sofar < len) {
++		req = len - sofar;
++		if (req > PROG_CHUNK)
++			req = PROG_CHUNK;
++		cnt = ipath_sd7220_ram_xfer(dd, sdnum, offset + sofar,
++					  img + sofar, req, 0);
++		if (cnt < req) {
++			sofar = -1;
++			break;
++		}
++		sofar += req;
++	}
++	return sofar;
++}
++
++#define VFY_CHUNK 64
++#define SD_PRAM_ERROR_LIMIT 42
++
++int ipath_sd7220_prog_vfy(struct ipath_devdata *dd, int sdnum,
++	const u8 *img, int len, int offset)
++{
++	int cnt, sofar, req, idx, errors;
++	unsigned char readback[VFY_CHUNK];
++
++	errors = 0;
++	sofar = 0;
++	while (sofar < len) {
++		req = len - sofar;
++		if (req > VFY_CHUNK)
++			req = VFY_CHUNK;
++		cnt = ipath_sd7220_ram_xfer(dd, sdnum, sofar + offset,
++					  readback, req, 1);
++		if (cnt < req) {
++			/* failed in read itself */
++			sofar = -1;
++			break;
++		}
++		for (idx = 0; idx < cnt; ++idx) {
++			if (readback[idx] != img[idx+sofar])
++				++errors;
++		}
++		sofar += cnt;
++	}
++	return errors ? -errors : sofar;
++}
++
++/* IRQ not set up at this point in init, so we poll. */
++#define IB_SERDES_TRIM_DONE (1ULL << 11)
++#define TRIM_TMO (30)
++
++static int ipath_sd_trimdone_poll(struct ipath_devdata *dd)
++{
++	int trim_tmo, ret;
++	uint64_t val;
++
++	/*
++	 * Default to failure, so IBC will not start
++	 * without IB_SERDES_TRIM_DONE.
++	 */
++	ret = 0;
++	for (trim_tmo = 0; trim_tmo < TRIM_TMO; ++trim_tmo) {
++		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
++		if (val & IB_SERDES_TRIM_DONE) {
++			ipath_cdbg(VERBOSE, "TRIMDONE after %d\n", trim_tmo);
++			ret = 1;
++			break;
++		}
++		msleep(10);
++	}
++	if (trim_tmo >= TRIM_TMO) {
++		ipath_dev_err(dd, "No TRIMDONE in %d tries\n", trim_tmo);
++		ret = 0;
++	}
++	return ret;
++}
++
++#define TX_FAST_ELT (9)
++
++/*
++ * Set the "negotiation" values for SERDES. These are used by the IB1.2
++ * link negotiation. Macros below are attempt to keep the values a
++ * little more human-editable.
++ * First, values related to Drive De-emphasis Settings.
++ */
++
++#define NUM_DDS_REGS 6
++#define DDS_REG_MAP 0x76A910 /* LSB-first list of regs (in elt 9) to mod */
++
++#define DDS_VAL(amp_d, main_d, ipst_d, ipre_d, amp_s, main_s, ipst_s, ipre_s) \
++	{ { ((amp_d & 0x1F) << 1) | 1, ((amp_s & 0x1F) << 1) | 1, \
++	  (main_d << 3) | 4 | (ipre_d >> 2), \
++	  (main_s << 3) | 4 | (ipre_s >> 2), \
++	  ((ipst_d & 0xF) << 1) | ((ipre_d & 3) << 6) | 0x21, \
++	  ((ipst_s & 0xF) << 1) | ((ipre_s & 3) << 6) | 0x21 } }
++
++static struct dds_init {
++	uint8_t reg_vals[NUM_DDS_REGS];
++} dds_init_vals[] = {
++	/*       DDR(FDR)       SDR(HDR)   */
++	/* Vendor recommends below for 3m cable */
++#define DDS_3M 0
++	DDS_VAL(31, 19, 12, 0, 29, 22,  9, 0),
++	DDS_VAL(31, 12, 15, 4, 31, 15, 15, 1),
++	DDS_VAL(31, 13, 15, 3, 31, 16, 15, 0),
++	DDS_VAL(31, 14, 15, 2, 31, 17, 14, 0),
++	DDS_VAL(31, 15, 15, 1, 31, 18, 13, 0),
++	DDS_VAL(31, 16, 15, 0, 31, 19, 12, 0),
++	DDS_VAL(31, 17, 14, 0, 31, 20, 11, 0),
++	DDS_VAL(31, 18, 13, 0, 30, 21, 10, 0),
++	DDS_VAL(31, 20, 11, 0, 28, 23,  8, 0),
++	DDS_VAL(31, 21, 10, 0, 27, 24,  7, 0),
++	DDS_VAL(31, 22,  9, 0, 26, 25,  6, 0),
++	DDS_VAL(30, 23,  8, 0, 25, 26,  5, 0),
++	DDS_VAL(29, 24,  7, 0, 23, 27,  4, 0),
++	/* Vendor recommends below for 1m cable */
++#define DDS_1M 13
++	DDS_VAL(28, 25,  6, 0, 21, 28,  3, 0),
++	DDS_VAL(27, 26,  5, 0, 19, 29,  2, 0),
++	DDS_VAL(25, 27,  4, 0, 17, 30,  1, 0)
++};
++
++/*
++ * Next, values related to Receive Equalization.
++ * In comments, FDR (Full) is IB DDR, HDR (Half) is IB SDR
++ */
++/* Hardware packs an element number and register address thus: */
++#define RXEQ_INIT_RDESC(elt, addr) (((elt) & 0xF) | ((addr) << 4))
++#define RXEQ_VAL(elt, adr, val0, val1, val2, val3) \
++	{RXEQ_INIT_RDESC((elt), (adr)), {(val0), (val1), (val2), (val3)} }
++
++#define RXEQ_VAL_ALL(elt, adr, val)  \
++	{RXEQ_INIT_RDESC((elt), (adr)), {(val), (val), (val), (val)} }
++
++#define RXEQ_SDR_DFELTH 0
++#define RXEQ_SDR_TLTH 0
++#define RXEQ_SDR_G1CNT_Z1CNT 0x11
++#define RXEQ_SDR_ZCNT 23
++
++static struct rxeq_init {
++	u16 rdesc;	/* in form used in SerDesDDSRXEQ */
++	u8  rdata[4];
++} rxeq_init_vals[] = {
++	/* Set Rcv Eq. to Preset node */
++	RXEQ_VAL_ALL(7, 0x27, 0x10),
++	/* Set DFELTHFDR/HDR thresholds */
++	RXEQ_VAL(7, 8,    0, 0, 0, 0), /* FDR */
++	RXEQ_VAL(7, 0x21, 0, 0, 0, 0), /* HDR */
++	/* Set TLTHFDR/HDR theshold */
++	RXEQ_VAL(7, 9,    2, 2, 2, 2), /* FDR */
++	RXEQ_VAL(7, 0x23, 2, 2, 2, 2), /* HDR */
++	/* Set Preamp setting 2 (ZFR/ZCNT) */
++	RXEQ_VAL(7, 0x1B, 12, 12, 12, 12), /* FDR */
++	RXEQ_VAL(7, 0x1C, 12, 12, 12, 12), /* HDR */
++	/* Set Preamp DC gain and Setting 1 (GFR/GHR) */
++	RXEQ_VAL(7, 0x1E, 0x10, 0x10, 0x10, 0x10), /* FDR */
++	RXEQ_VAL(7, 0x1F, 0x10, 0x10, 0x10, 0x10), /* HDR */
++	/* Toggle RELOCK (in VCDL_CTRL0) to lock to data */
++	RXEQ_VAL_ALL(6, 6, 0x20), /* Set D5 High */
++	RXEQ_VAL_ALL(6, 6, 0), /* Set D5 Low */
++};
++
++/* There are 17 values from vendor, but IBC only accesses the first 16 */
++#define DDS_ROWS (16)
++#define RXEQ_ROWS ARRAY_SIZE(rxeq_init_vals)
++
++static int ipath_sd_setvals(struct ipath_devdata *dd)
++{
++	int idx, midx;
++	int min_idx;	 /* Minimum index for this portion of table */
++	uint32_t dds_reg_map;
++	u64 __iomem *taddr, *iaddr;
++	uint64_t data;
++	uint64_t sdctl;
++
++	taddr = dd->ipath_kregbase + KR_IBSerDesMappTable;
++	iaddr = dd->ipath_kregbase + dd->ipath_kregs->kr_ib_ddsrxeq;
++
++	/*
++	 * Init the DDS section of the table.
++	 * Each "row" of the table provokes NUM_DDS_REG writes, to the
++	 * registers indicated in DDS_REG_MAP.
++	 */
++	sdctl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibserdesctrl);
++	sdctl = (sdctl & ~(0x1f << 8)) | (NUM_DDS_REGS << 8);
++	sdctl = (sdctl & ~(0x1f << 13)) | (RXEQ_ROWS << 13);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, sdctl);
++
++	/*
++	 * Iterate down table within loop for each register to store.
++	 */
++	dds_reg_map = DDS_REG_MAP;
++	for (idx = 0; idx < NUM_DDS_REGS; ++idx) {
++		data = ((dds_reg_map & 0xF) << 4) | TX_FAST_ELT;
++		writeq(data, iaddr + idx);
++		mmiowb();
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++		dds_reg_map >>= 4;
++		for (midx = 0; midx < DDS_ROWS; ++midx) {
++			u64 __iomem *daddr = taddr + ((midx << 4) + idx);
++			data = dds_init_vals[midx].reg_vals[idx];
++			writeq(data, daddr);
++			mmiowb();
++			ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++		} /* End inner for (vals for this reg, each row) */
++	} /* end outer for (regs to be stored) */
++
++	/*
++	 * Init the RXEQ section of the table. As explained above the table
++	 * rxeq_init_vals[], this runs in a different order, as the pattern
++	 * of register references is more complex, but there are only
++	 * four "data" values per register.
++	 */
++	min_idx = idx; /* RXEQ indices pick up where DDS left off */
++	taddr += 0x100; /* RXEQ data is in second half of table */
++	/* Iterate through RXEQ register addresses */
++	for (idx = 0; idx < RXEQ_ROWS; ++idx) {
++		int didx; /* "destination" */
++		int vidx;
++
++		/* didx is offset by min_idx to address RXEQ range of regs */
++		didx = idx + min_idx;
++		/* Store the next RXEQ register address */
++		writeq(rxeq_init_vals[idx].rdesc, iaddr + didx);
++		mmiowb();
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++		/* Iterate through RXEQ values */
++		for (vidx = 0; vidx < 4; vidx++) {
++			data = rxeq_init_vals[idx].rdata[vidx];
++			writeq(data, taddr + (vidx << 6) + idx);
++			mmiowb();
++			ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++		}
++	} /* end outer for (Reg-writes for RXEQ) */
++	return 0;
++}
++
++#define CMUCTRL5 EPB_LOC(7, 0, 0x15)
++#define RXHSCTRL0(chan) EPB_LOC(chan, 6, 0)
++#define VCDL_DAC2(chan) EPB_LOC(chan, 6, 5)
++#define VCDL_CTRL0(chan) EPB_LOC(chan, 6, 6)
++#define VCDL_CTRL2(chan) EPB_LOC(chan, 6, 8)
++#define START_EQ2(chan) EPB_LOC(chan, 7, 0x28)
++
++static int ibsd_sto_noisy(struct ipath_devdata *dd, int loc, int val, int mask)
++{
++	int ret = -1;
++	int sloc; /* shifted loc, for messages */
++
++	loc |= (1U << EPB_IB_QUAD0_CS_SHF);
++	sloc = loc >> EPB_ADDR_SHF;
++
++	ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, val, mask);
++	if (ret < 0)
++		ipath_dev_err(dd, "Write failed: elt %d,"
++			" addr 0x%X, chnl %d, val 0x%02X, mask 0x%02X\n",
++			(sloc & 0xF), (sloc >> 9) & 0x3f, (sloc >> 4) & 7,
++			val & 0xFF, mask & 0xFF);
++	return ret;
++}
++
++/*
++ * Repeat a "store" across all channels of the IB SerDes.
++ * Although nominally it inherits the "read value" of the last
++ * channel it modified, the only really useful return is <0 for
++ * failure, >= 0 for success. The parameter 'loc' is assumed to
++ * be the location for the channel-0 copy of the register to
++ * be modified.
++ */
++static int ibsd_mod_allchnls(struct ipath_devdata *dd, int loc, int val,
++	int mask)
++{
++	int ret = -1;
++	int chnl;
++
++	if (loc & EPB_GLOBAL_WR) {
++		/*
++		 * Our caller has assured us that we can set all four
++		 * channels at once. Trust that. If mask is not 0xFF,
++		 * we will read the _specified_ channel for our starting
++		 * value.
++		 */
++		loc |= (1U << EPB_IB_QUAD0_CS_SHF);
++		chnl = (loc >> (4 + EPB_ADDR_SHF)) & 7;
++		if (mask != 0xFF) {
++			ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++				loc & ~EPB_GLOBAL_WR, 0, 0);
++			if (ret < 0) {
++				int sloc = loc >> EPB_ADDR_SHF;
++				ipath_dev_err(dd, "pre-read failed: elt %d,"
++					" addr 0x%X, chnl %d\n", (sloc & 0xF),
++					(sloc >> 9) & 0x3f, chnl);
++				return ret;
++			}
++			val = (ret & ~mask) | (val & mask);
++		}
++		loc &=  ~(7 << (4+EPB_ADDR_SHF));
++		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, val, 0xFF);
++		if (ret < 0) {
++			int sloc = loc >> EPB_ADDR_SHF;
++			ipath_dev_err(dd, "Global WR failed: elt %d,"
++				" addr 0x%X, val %02X\n",
++				(sloc & 0xF), (sloc >> 9) & 0x3f, val);
++		}
++		return ret;
++	}
++	/* Clear "channel" and set CS so we can simply iterate */
++	loc &=  ~(7 << (4+EPB_ADDR_SHF));
++	loc |= (1U << EPB_IB_QUAD0_CS_SHF);
++	for (chnl = 0; chnl < 4; ++chnl) {
++		int cloc;
++		cloc = loc | (chnl << (4+EPB_ADDR_SHF));
++		ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, cloc, val, mask);
++		if (ret < 0) {
++			int sloc = loc >> EPB_ADDR_SHF;
++			ipath_dev_err(dd, "Write failed: elt %d,"
++				" addr 0x%X, chnl %d, val 0x%02X,"
++				" mask 0x%02X\n",
++				(sloc & 0xF), (sloc >> 9) & 0x3f, chnl,
++				val & 0xFF, mask & 0xFF);
++			break;
++		}
++	}
++	return ret;
++}
++
++/*
++ * Set the Tx values normally modified by IBC in IB1.2 mode to default
++ * values, as gotten from first row of init table.
++ */
++static int set_dds_vals(struct ipath_devdata *dd, struct dds_init *ddi)
++{
++	int ret;
++	int idx, reg, data;
++	uint32_t regmap;
++
++	regmap = DDS_REG_MAP;
++	for (idx = 0; idx < NUM_DDS_REGS; ++idx) {
++		reg = (regmap & 0xF);
++		regmap >>= 4;
++		data = ddi->reg_vals[idx];
++		/* Vendor says RMW not needed for these regs, use 0xFF mask */
++		ret = ibsd_mod_allchnls(dd, EPB_LOC(0, 9, reg), data, 0xFF);
++		if (ret < 0)
++			break;
++	}
++	return ret;
++}
++
++/*
++ * Set the Rx values normally modified by IBC in IB1.2 mode to default
++ * values, as gotten from selected column of init table.
++ */
++static int set_rxeq_vals(struct ipath_devdata *dd, int vsel)
++{
++	int ret;
++	int ridx;
++	int cnt = ARRAY_SIZE(rxeq_init_vals);
++
++	for (ridx = 0; ridx < cnt; ++ridx) {
++		int elt, reg, val, loc;
++		elt = rxeq_init_vals[ridx].rdesc & 0xF;
++		reg = rxeq_init_vals[ridx].rdesc >> 4;
++		loc = EPB_LOC(0, elt, reg);
++		val = rxeq_init_vals[ridx].rdata[vsel];
++		/* mask of 0xFF, because hardware does full-byte store. */
++		ret = ibsd_mod_allchnls(dd, loc, val, 0xFF);
++		if (ret < 0)
++			break;
++	}
++	return ret;
++}
++
++/*
++ * Set the default values (row 0) for DDR Driver Demphasis.
++ * we do this initially and whenever we turn off IB-1.2
++ * The "default" values for Rx equalization are also stored to
++ * SerDes registers. Formerly (and still default), we used set 2.
++ * For experimenting with cables and link-partners, we allow changing
++ * that via a module parameter.
++ */
++static unsigned ipath_rxeq_set = 2;
++module_param_named(rxeq_default_set, ipath_rxeq_set, uint,
++	S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(rxeq_default_set,
++	"Which set [0..3] of Rx Equalization values is default");
++
++static int ipath_internal_presets(struct ipath_devdata *dd)
++{
++	int ret = 0;
++
++	ret = set_dds_vals(dd, dds_init_vals + DDS_3M);
++
++	if (ret < 0)
++		ipath_dev_err(dd, "Failed to set default DDS values\n");
++	ret = set_rxeq_vals(dd, ipath_rxeq_set & 3);
++	if (ret < 0)
++		ipath_dev_err(dd, "Failed to set default RXEQ values\n");
++	return ret;
++}
++
++int ipath_sd7220_presets(struct ipath_devdata *dd)
++{
++	int ret = 0;
++
++	if (!dd->ipath_presets_needed)
++		return ret;
++	dd->ipath_presets_needed = 0;
++	/* Assert uC reset, so we don't clash with it. */
++	ipath_ibsd_reset(dd, 1);
++	udelay(2);
++	ipath_sd_trimdone_monitor(dd, "link-down");
++
++	ret = ipath_internal_presets(dd);
++return ret;
++}
++
++static int ipath_sd_trimself(struct ipath_devdata *dd, int val)
++{
++	return ibsd_sto_noisy(dd, CMUCTRL5, val, 0xFF);
++}
++
++static int ipath_sd_early(struct ipath_devdata *dd)
++{
++	int ret = -1; /* Default failed */
++	int chnl;
++
++	for (chnl = 0; chnl < 4; ++chnl) {
++		ret = ibsd_sto_noisy(dd, RXHSCTRL0(chnl), 0xD4, 0xFF);
++		if (ret < 0)
++			goto bail;
++	}
++	for (chnl = 0; chnl < 4; ++chnl) {
++		ret = ibsd_sto_noisy(dd, VCDL_DAC2(chnl), 0x2D, 0xFF);
++		if (ret < 0)
++			goto bail;
++	}
++	/* more fine-tuning of what will be default */
++	for (chnl = 0; chnl < 4; ++chnl) {
++		ret = ibsd_sto_noisy(dd, VCDL_CTRL2(chnl), 3, 0xF);
++		if (ret < 0)
++			goto bail;
++	}
++	for (chnl = 0; chnl < 4; ++chnl) {
++		ret = ibsd_sto_noisy(dd, START_EQ1(chnl), 0x10, 0xFF);
++		if (ret < 0)
++			goto bail;
++	}
++	for (chnl = 0; chnl < 4; ++chnl) {
++		ret = ibsd_sto_noisy(dd, START_EQ2(chnl), 0x30, 0xFF);
++		if (ret < 0)
++			goto bail;
++	}
++bail:
++	return ret;
++}
++
++#define BACTRL(chnl) EPB_LOC(chnl, 6, 0x0E)
++#define LDOUTCTRL1(chnl) EPB_LOC(chnl, 7, 6)
++#define RXHSSTATUS(chnl) EPB_LOC(chnl, 6, 0xF)
++
++static int ipath_sd_dactrim(struct ipath_devdata *dd)
++{
++	int ret = -1; /* Default failed */
++	int chnl;
++
++	for (chnl = 0; chnl < 4; ++chnl) {
++		ret = ibsd_sto_noisy(dd, BACTRL(chnl), 0x40, 0xFF);
++		if (ret < 0)
++			goto bail;
++	}
++	for (chnl = 0; chnl < 4; ++chnl) {
++		ret = ibsd_sto_noisy(dd, LDOUTCTRL1(chnl), 0x04, 0xFF);
++		if (ret < 0)
++			goto bail;
++	}
++	for (chnl = 0; chnl < 4; ++chnl) {
++		ret = ibsd_sto_noisy(dd, RXHSSTATUS(chnl), 0x04, 0xFF);
++		if (ret < 0)
++			goto bail;
++	}
++	/*
++	 * delay for max possible number of steps, with slop.
++	 * Each step is about 4usec.
++	 */
++	udelay(415);
++	for (chnl = 0; chnl < 4; ++chnl) {
++		ret = ibsd_sto_noisy(dd, LDOUTCTRL1(chnl), 0x00, 0xFF);
++		if (ret < 0)
++			goto bail;
++	}
++bail:
++	return ret;
++}
++
++#define RELOCK_FIRST_MS 3
++#define RXLSPPM(chan) EPB_LOC(chan, 0, 2)
++void ipath_toggle_rclkrls(struct ipath_devdata *dd)
++{
++	int loc = RXLSPPM(0) | EPB_GLOBAL_WR;
++	int ret;
++
++	ret = ibsd_mod_allchnls(dd, loc, 0, 0x80);
++	if (ret < 0)
++		ipath_dev_err(dd, "RCLKRLS failed to clear D7\n");
++	else {
++		udelay(1);
++		ibsd_mod_allchnls(dd, loc, 0x80, 0x80);
++	}
++	/* And again for good measure */
++	udelay(1);
++	ret = ibsd_mod_allchnls(dd, loc, 0, 0x80);
++	if (ret < 0)
++		ipath_dev_err(dd, "RCLKRLS failed to clear D7\n");
++	else {
++		udelay(1);
++		ibsd_mod_allchnls(dd, loc, 0x80, 0x80);
++	}
++	/* Now reset xgxs and IBC to complete the recovery */
++	dd->ipath_f_xgxs_reset(dd);
++}
++
++/*
++ * Shut down the timer that polls for relock occasions, if needed
++ * this is "hooked" from ipath_7220_quiet_serdes(), which is called
++ * just before ipath_shutdown_device() in ipath_driver.c shuts down all
++ * the other timers
++ */
++void ipath_shutdown_relock_poll(struct ipath_devdata *dd)
++{
++	struct ipath_relock *irp = &dd->ipath_relock_singleton;
++	if (atomic_read(&irp->ipath_relock_timer_active)) {
++		del_timer_sync(&irp->ipath_relock_timer);
++		atomic_set(&irp->ipath_relock_timer_active, 0);
++	}
++}
++
++static unsigned ipath_relock_by_timer = 1;
++module_param_named(relock_by_timer, ipath_relock_by_timer, uint,
++	S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(relock_by_timer, "Allow relock attempt if link not up");
++
++static void ipath_run_relock(unsigned long opaque)
++{
++	struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++	struct ipath_relock *irp = &dd->ipath_relock_singleton;
++	u64 val, ltstate;
++
++	if (!(dd->ipath_flags & IPATH_INITTED)) {
++		/* Not yet up, just reenable the timer for later */
++		irp->ipath_relock_interval = HZ;
++		mod_timer(&irp->ipath_relock_timer, jiffies + HZ);
++		return;
++	}
++
++	/*
++	 * Check link-training state for "stuck" state.
++	 * if found, try relock and schedule another try at
++	 * exponentially growing delay, maxed at one second.
++	 * if not stuck, our work is done.
++	 */
++	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
++	ltstate = ipath_ib_linktrstate(dd, val);
++
++	if (ltstate <= INFINIPATH_IBCS_LT_STATE_CFGWAITRMT
++		&& ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
++		int timeoff;
++		/* Not up yet. Try again, if allowed by module-param */
++		if (ipath_relock_by_timer) {
++			if (dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)
++				ipath_cdbg(VERBOSE, "Skip RELOCK in AUTONEG\n");
++			else if (!(dd->ipath_flags & IPATH_IB_LINK_DISABLED)) {
++				ipath_cdbg(VERBOSE, "RELOCK\n");
++				ipath_toggle_rclkrls(dd);
++			}
++		}
++		/* re-set timer for next check */
++		timeoff = irp->ipath_relock_interval << 1;
++		if (timeoff > HZ)
++			timeoff = HZ;
++		irp->ipath_relock_interval = timeoff;
++
++		mod_timer(&irp->ipath_relock_timer, jiffies + timeoff);
++	} else {
++		/* Up, so no more need to check so often */
++		mod_timer(&irp->ipath_relock_timer, jiffies + HZ);
++	}
++}
++
++void ipath_set_relock_poll(struct ipath_devdata *dd, int ibup)
++{
++	struct ipath_relock *irp = &dd->ipath_relock_singleton;
++
++	if (ibup > 0) {
++		/* we are now up, so relax timer to 1 second interval */
++		if (atomic_read(&irp->ipath_relock_timer_active))
++			mod_timer(&irp->ipath_relock_timer, jiffies + HZ);
++	} else {
++		/* Transition to down, (re-)set timer to short interval. */
++		int timeout;
++		timeout = (HZ * ((ibup == -1) ? 1000 : RELOCK_FIRST_MS))/1000;
++		if (timeout == 0)
++			timeout = 1;
++		/* If timer has not yet been started, do so. */
++		if (atomic_inc_return(&irp->ipath_relock_timer_active) == 1) {
++			init_timer(&irp->ipath_relock_timer);
++			irp->ipath_relock_timer.function = ipath_run_relock;
++			irp->ipath_relock_timer.data = (unsigned long) dd;
++			irp->ipath_relock_interval = timeout;
++			irp->ipath_relock_timer.expires = jiffies + timeout;
++			add_timer(&irp->ipath_relock_timer);
++		} else {
++			irp->ipath_relock_interval = timeout;
++			mod_timer(&irp->ipath_relock_timer, jiffies + timeout);
++			atomic_dec(&irp->ipath_relock_timer_active);
++		}
++	}
++}
++
+diff --git a/drivers/infiniband/hw/ipath/ipath_sd7220_img.c b/drivers/infiniband/hw/ipath/ipath_sd7220_img.c
+new file mode 100644
+index 0000000..5ef59da
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_sd7220_img.c
+@@ -0,0 +1,1082 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/*
++ * This file contains the memory image from the vendor, to be copied into
++ * the IB SERDES of the IBA7220 during initialization.
++ * The file also includes the two functions which use this image.
++ */
++#include <linux/pci.h>
++#include <linux/delay.h>
++
++#include "ipath_kernel.h"
++#include "ipath_registers.h"
++#include "ipath_7220.h"
++
++static unsigned char ipath_sd7220_ib_img[] = {
++/*0000*/0x02, 0x0A, 0x29, 0x02, 0x0A, 0x87, 0xE5, 0xE6,
++	0x30, 0xE6, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
++/*0010*/0x00, 0xE5, 0xE2, 0x30, 0xE4, 0x04, 0x7E, 0x01,
++	0x80, 0x02, 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x08,
++/*0020*/0x53, 0xF9, 0xF7, 0xE4, 0xF5, 0xFE, 0x80, 0x08,
++	0x7F, 0x0A, 0x12, 0x17, 0x31, 0x12, 0x0E, 0xA2,
++/*0030*/0x75, 0xFC, 0x08, 0xE4, 0xF5, 0xFD, 0xE5, 0xE7,
++	0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0x22, 0x00,
++/*0040*/0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x75,
++	0x51, 0x01, 0xE4, 0xF5, 0x52, 0xF5, 0x53, 0xF5,
++/*0050*/0x52, 0xF5, 0x7E, 0x7F, 0x04, 0x02, 0x04, 0x38,
++	0xC2, 0x36, 0x05, 0x52, 0xE5, 0x52, 0xD3, 0x94,
++/*0060*/0x0C, 0x40, 0x05, 0x75, 0x52, 0x01, 0xD2, 0x36,
++	0x90, 0x07, 0x0C, 0x74, 0x07, 0xF0, 0xA3, 0x74,
++/*0070*/0xFF, 0xF0, 0xE4, 0xF5, 0x0C, 0xA3, 0xF0, 0x90,
++	0x07, 0x14, 0xF0, 0xA3, 0xF0, 0x75, 0x0B, 0x20,
++/*0080*/0xF5, 0x09, 0xE4, 0xF5, 0x08, 0xE5, 0x08, 0xD3,
++	0x94, 0x30, 0x40, 0x03, 0x02, 0x04, 0x04, 0x12,
++/*0090*/0x00, 0x06, 0x15, 0x0B, 0xE5, 0x08, 0x70, 0x04,
++	0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x09,
++/*00A0*/0x70, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00,
++	0xEE, 0x5F, 0x60, 0x05, 0x12, 0x18, 0x71, 0xD2,
++/*00B0*/0x35, 0x53, 0xE1, 0xF7, 0xE5, 0x08, 0x45, 0x09,
++	0xFF, 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24,
++/*00C0*/0x83, 0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83,
++	0xEF, 0xF0, 0x85, 0xE2, 0x20, 0xE5, 0x52, 0xD3,
++/*00D0*/0x94, 0x01, 0x40, 0x0D, 0x12, 0x19, 0xF3, 0xE0,
++	0x54, 0xA0, 0x64, 0x40, 0x70, 0x03, 0x02, 0x03,
++/*00E0*/0xFB, 0x53, 0xF9, 0xF8, 0x90, 0x94, 0x70, 0xE4,
++	0xF0, 0xE0, 0xF5, 0x10, 0xAF, 0x09, 0x12, 0x1E,
++/*00F0*/0xB3, 0xAF, 0x08, 0xEF, 0x44, 0x08, 0xF5, 0x82,
++	0x75, 0x83, 0x80, 0xE0, 0xF5, 0x29, 0xEF, 0x44,
++/*0100*/0x07, 0x12, 0x1A, 0x3C, 0xF5, 0x22, 0x54, 0x40,
++	0xD3, 0x94, 0x00, 0x40, 0x1E, 0xE5, 0x29, 0x54,
++/*0110*/0xF0, 0x70, 0x21, 0x12, 0x19, 0xF3, 0xE0, 0x44,
++	0x80, 0xF0, 0xE5, 0x22, 0x54, 0x30, 0x65, 0x08,
++/*0120*/0x70, 0x09, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xBF,
++	0xF0, 0x80, 0x09, 0x12, 0x19, 0xF3, 0x74, 0x40,
++/*0130*/0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12, 0x75,
++	0x83, 0xAE, 0x74, 0xFF, 0xF0, 0xAF, 0x08, 0x7E,
++/*0140*/0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0xE0, 0xFD,
++	0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x81,
++/*0150*/0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83, 0xED,
++	0xF0, 0x90, 0x07, 0x0E, 0xE0, 0x04, 0xF0, 0xEF,
++/*0160*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0x98, 0xE0,
++	0xF5, 0x28, 0x12, 0x1A, 0x23, 0x40, 0x0C, 0x12,
++/*0170*/0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12, 0x1A, 0x32,
++	0x02, 0x03, 0xF6, 0xAF, 0x08, 0x7E, 0x00, 0x74,
++/*0180*/0x80, 0xCD, 0xEF, 0xCD, 0x8D, 0x82, 0xF5, 0x83,
++	0xE0, 0x30, 0xE0, 0x0A, 0x12, 0x19, 0xF3, 0xE0,
++/*0190*/0x44, 0x20, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x19,
++	0xF3, 0xE0, 0x54, 0xDF, 0xF0, 0xEE, 0x44, 0xAE,
++/*01A0*/0x12, 0x1A, 0x43, 0x30, 0xE4, 0x03, 0x02, 0x03,
++	0xFB, 0x74, 0x9E, 0x12, 0x1A, 0x05, 0x20, 0xE0,
++/*01B0*/0x03, 0x02, 0x03, 0xFB, 0x8F, 0x82, 0x8E, 0x83,
++	0xE0, 0x20, 0xE0, 0x03, 0x02, 0x03, 0xFB, 0x12,
++/*01C0*/0x19, 0xF3, 0xE0, 0x44, 0x10, 0xF0, 0xE5, 0xE3,
++	0x20, 0xE7, 0x08, 0xE5, 0x08, 0x12, 0x1A, 0x3A,
++/*01D0*/0x44, 0x04, 0xF0, 0xAF, 0x08, 0x7E, 0x00, 0xEF,
++	0x12, 0x1A, 0x3A, 0x20, 0xE2, 0x34, 0x12, 0x19,
++/*01E0*/0xF3, 0xE0, 0x44, 0x08, 0xF0, 0xE5, 0xE4, 0x30,
++	0xE6, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
++/*01F0*/0xE5, 0x7E, 0xC3, 0x94, 0x04, 0x50, 0x04, 0x7C,
++	0x01, 0x80, 0x02, 0x7C, 0x00, 0xEC, 0x4D, 0x60,
++/*0200*/0x05, 0xC2, 0x35, 0x02, 0x03, 0xFB, 0xEE, 0x44,
++	0xD2, 0x12, 0x1A, 0x43, 0x44, 0x40, 0xF0, 0x02,
++/*0210*/0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xF7,
++	0xF0, 0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0,
++/*0220*/0x54, 0xBF, 0xF0, 0x90, 0x07, 0x14, 0xE0, 0x04,
++	0xF0, 0xE5, 0x7E, 0x70, 0x03, 0x75, 0x7E, 0x01,
++/*0230*/0xAF, 0x08, 0x7E, 0x00, 0x12, 0x1A, 0x23, 0x40,
++	0x12, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12,
++/*0240*/0x19, 0xF2, 0xE0, 0x54, 0x02, 0x12, 0x1A, 0x32,
++	0x02, 0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x44,
++/*0250*/0x02, 0x12, 0x19, 0xF2, 0xE0, 0x54, 0xFE, 0xF0,
++	0xC2, 0x35, 0xEE, 0x44, 0x8A, 0x8F, 0x82, 0xF5,
++/*0260*/0x83, 0xE0, 0xF5, 0x17, 0x54, 0x8F, 0x44, 0x40,
++	0xF0, 0x74, 0x90, 0xFC, 0xE5, 0x08, 0x44, 0x07,
++/*0270*/0xFD, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0x54, 0x3F,
++	0x90, 0x07, 0x02, 0xF0, 0xE0, 0x54, 0xC0, 0x8D,
++/*0280*/0x82, 0x8C, 0x83, 0xF0, 0x74, 0x92, 0x12, 0x1A,
++	0x05, 0x90, 0x07, 0x03, 0x12, 0x1A, 0x19, 0x74,
++/*0290*/0x82, 0x12, 0x1A, 0x05, 0x90, 0x07, 0x04, 0x12,
++	0x1A, 0x19, 0x74, 0xB4, 0x12, 0x1A, 0x05, 0x90,
++/*02A0*/0x07, 0x05, 0x12, 0x1A, 0x19, 0x74, 0x94, 0xFE,
++	0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A, 0xF5,
++/*02B0*/0x10, 0x30, 0xE0, 0x04, 0xD2, 0x37, 0x80, 0x02,
++	0xC2, 0x37, 0xE5, 0x10, 0x54, 0x7F, 0x8F, 0x82,
++/*02C0*/0x8E, 0x83, 0xF0, 0x30, 0x44, 0x30, 0x12, 0x1A,
++	0x03, 0x54, 0x80, 0xD3, 0x94, 0x00, 0x40, 0x04,
++/*02D0*/0xD2, 0x39, 0x80, 0x02, 0xC2, 0x39, 0x8F, 0x82,
++	0x8E, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0x12, 0x1A,
++/*02E0*/0x03, 0x54, 0x40, 0xD3, 0x94, 0x00, 0x40, 0x04,
++	0xD2, 0x3A, 0x80, 0x02, 0xC2, 0x3A, 0x8F, 0x82,
++/*02F0*/0x8E, 0x83, 0xE0, 0x44, 0x40, 0xF0, 0x74, 0x92,
++	0xFE, 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A,
++/*0300*/0x30, 0xE7, 0x04, 0xD2, 0x38, 0x80, 0x02, 0xC2,
++	0x38, 0x8F, 0x82, 0x8E, 0x83, 0xE0, 0x54, 0x7F,
++/*0310*/0xF0, 0x12, 0x1E, 0x46, 0xE4, 0xF5, 0x0A, 0x20,
++	0x03, 0x02, 0x80, 0x03, 0x30, 0x43, 0x03, 0x12,
++/*0320*/0x19, 0x95, 0x20, 0x02, 0x02, 0x80, 0x03, 0x30,
++	0x42, 0x03, 0x12, 0x0C, 0x8F, 0x30, 0x30, 0x06,
++/*0330*/0x12, 0x19, 0x95, 0x12, 0x0C, 0x8F, 0x12, 0x0D,
++	0x47, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xFB, 0xF0,
++/*0340*/0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, 0x46, 0x43,
++	0xE1, 0x08, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x04,
++/*0350*/0xF0, 0xE5, 0xE4, 0x20, 0xE7, 0x2A, 0x12, 0x1A,
++	0x12, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
++/*0360*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
++	0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
++/*0370*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
++	0x5E, 0x60, 0x05, 0x12, 0x1D, 0xD7, 0x80, 0x17,
++/*0380*/0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x44,
++	0x08, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12,
++/*0390*/0x75, 0x83, 0xD2, 0xE0, 0x54, 0xF7, 0xF0, 0x12,
++	0x1E, 0x46, 0x7F, 0x08, 0x12, 0x17, 0x31, 0x74,
++/*03A0*/0x8E, 0xFE, 0x12, 0x1A, 0x12, 0x8E, 0x83, 0xE0,
++	0xF5, 0x10, 0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44,
++/*03B0*/0x01, 0xFF, 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07,
++	0xF5, 0x82, 0xEF, 0xF0, 0xE5, 0x10, 0x54, 0xFE,
++/*03C0*/0xFF, 0xED, 0x44, 0x07, 0xF5, 0x82, 0xEF, 0x12,
++	0x1A, 0x11, 0x75, 0x83, 0x86, 0xE0, 0x44, 0x10,
++/*03D0*/0x12, 0x1A, 0x11, 0xE0, 0x44, 0x10, 0xF0, 0x12,
++	0x19, 0xF3, 0xE0, 0x54, 0xFD, 0x44, 0x01, 0xFF,
++/*03E0*/0x12, 0x19, 0xF3, 0xEF, 0x12, 0x1A, 0x32, 0x30,
++	0x32, 0x0C, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
++/*03F0*/0x75, 0x83, 0x82, 0x74, 0x05, 0xF0, 0xAF, 0x0B,
++	0x12, 0x18, 0xD7, 0x74, 0x10, 0x25, 0x08, 0xF5,
++/*0400*/0x08, 0x02, 0x00, 0x85, 0x05, 0x09, 0xE5, 0x09,
++	0xD3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x00, 0x82,
++/*0410*/0xE5, 0x7E, 0xD3, 0x94, 0x00, 0x40, 0x04, 0x7F,
++	0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x7E, 0xC3,
++/*0420*/0x94, 0xFA, 0x50, 0x04, 0x7E, 0x01, 0x80, 0x02,
++	0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x02, 0x05, 0x7E,
++/*0430*/0x30, 0x35, 0x0B, 0x43, 0xE1, 0x01, 0x7F, 0x09,
++	0x12, 0x17, 0x31, 0x02, 0x00, 0x58, 0x53, 0xE1,
++/*0440*/0xFE, 0x02, 0x00, 0x58, 0x8E, 0x6A, 0x8F, 0x6B,
++	0x8C, 0x6C, 0x8D, 0x6D, 0x75, 0x6E, 0x01, 0x75,
++/*0450*/0x6F, 0x01, 0x75, 0x70, 0x01, 0xE4, 0xF5, 0x73,
++	0xF5, 0x74, 0xF5, 0x75, 0x90, 0x07, 0x2F, 0xF0,
++/*0460*/0xF5, 0x3C, 0xF5, 0x3E, 0xF5, 0x46, 0xF5, 0x47,
++	0xF5, 0x3D, 0xF5, 0x3F, 0xF5, 0x6F, 0xE5, 0x6F,
++/*0470*/0x70, 0x0F, 0xE5, 0x6B, 0x45, 0x6A, 0x12, 0x07,
++	0x2A, 0x75, 0x83, 0x80, 0x74, 0x3A, 0xF0, 0x80,
++/*0480*/0x09, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74,
++	0x1A, 0xF0, 0xE4, 0xF5, 0x6E, 0xC3, 0x74, 0x3F,
++/*0490*/0x95, 0x6E, 0xFF, 0x12, 0x08, 0x65, 0x75, 0x83,
++	0x82, 0xEF, 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x08,
++/*04A0*/0xC6, 0xE5, 0x33, 0xF0, 0x12, 0x08, 0xFA, 0x12,
++	0x08, 0xB1, 0x40, 0xE1, 0xE5, 0x6F, 0x70, 0x0B,
++/*04B0*/0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74, 0x36,
++	0xF0, 0x80, 0x09, 0x12, 0x07, 0x2A, 0x75, 0x83,
++/*04C0*/0x80, 0x74, 0x16, 0xF0, 0x75, 0x6E, 0x01, 0x12,
++	0x07, 0x2A, 0x75, 0x83, 0xB4, 0xE5, 0x6E, 0xF0,
++/*04D0*/0x12, 0x1A, 0x4D, 0x74, 0x3F, 0x25, 0x6E, 0xF5,
++	0x82, 0xE4, 0x34, 0x00, 0xF5, 0x83, 0xE5, 0x33,
++/*04E0*/0xF0, 0x74, 0xBF, 0x25, 0x6E, 0xF5, 0x82, 0xE4,
++	0x34, 0x00, 0x12, 0x08, 0xB1, 0x40, 0xD8, 0xE4,
++/*04F0*/0xF5, 0x70, 0xF5, 0x46, 0xF5, 0x47, 0xF5, 0x6E,
++	0x12, 0x08, 0xFA, 0xF5, 0x83, 0xE0, 0xFE, 0x12,
++/*0500*/0x08, 0xC6, 0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF,
++	0xEC, 0x3E, 0xFE, 0xAD, 0x3B, 0xD3, 0xEF, 0x9D,
++/*0510*/0xEE, 0x9C, 0x50, 0x04, 0x7B, 0x01, 0x80, 0x02,
++	0x7B, 0x00, 0xE5, 0x70, 0x70, 0x04, 0x7A, 0x01,
++/*0520*/0x80, 0x02, 0x7A, 0x00, 0xEB, 0x5A, 0x60, 0x06,
++	0x85, 0x6E, 0x46, 0x75, 0x70, 0x01, 0xD3, 0xEF,
++/*0530*/0x9D, 0xEE, 0x9C, 0x50, 0x04, 0x7F, 0x01, 0x80,
++	0x02, 0x7F, 0x00, 0xE5, 0x70, 0xB4, 0x01, 0x04,
++/*0540*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, 0x5E,
++	0x60, 0x03, 0x85, 0x6E, 0x47, 0x05, 0x6E, 0xE5,
++/*0550*/0x6E, 0x64, 0x7F, 0x70, 0xA3, 0xE5, 0x46, 0x60,
++	0x05, 0xE5, 0x47, 0xB4, 0x7E, 0x03, 0x85, 0x46,
++/*0560*/0x47, 0xE5, 0x6F, 0x70, 0x08, 0x85, 0x46, 0x76,
++	0x85, 0x47, 0x77, 0x80, 0x0E, 0xC3, 0x74, 0x7F,
++/*0570*/0x95, 0x46, 0xF5, 0x78, 0xC3, 0x74, 0x7F, 0x95,
++	0x47, 0xF5, 0x79, 0xE5, 0x6F, 0x70, 0x37, 0xE5,
++/*0580*/0x46, 0x65, 0x47, 0x70, 0x0C, 0x75, 0x73, 0x01,
++	0x75, 0x74, 0x01, 0xF5, 0x3C, 0xF5, 0x3D, 0x80,
++/*0590*/0x35, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5, 0x47, 0x95,
++	0x46, 0xF5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
++/*05A0*/0x46, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
++	0xE4, 0xF5, 0x3D, 0x80, 0x40, 0xC3, 0x74, 0x3F,
++/*05B0*/0x95, 0x72, 0xF5, 0x3D, 0x80, 0x37, 0xE5, 0x46,
++	0x65, 0x47, 0x70, 0x0F, 0x75, 0x73, 0x01, 0x75,
++/*05C0*/0x75, 0x01, 0xF5, 0x3E, 0xF5, 0x3F, 0x75, 0x4E,
++	0x01, 0x80, 0x22, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5,
++/*05D0*/0x47, 0x95, 0x46, 0xF5, 0x3E, 0xC3, 0x13, 0xF5,
++	0x71, 0x25, 0x46, 0xF5, 0x72, 0xD3, 0x94, 0x3F,
++/*05E0*/0x50, 0x05, 0xE4, 0xF5, 0x3F, 0x80, 0x06, 0xE5,
++	0x72, 0x24, 0xC1, 0xF5, 0x3F, 0x05, 0x6F, 0xE5,
++/*05F0*/0x6F, 0xC3, 0x94, 0x02, 0x50, 0x03, 0x02, 0x04,
++	0x6E, 0xE5, 0x6D, 0x45, 0x6C, 0x70, 0x02, 0x80,
++/*0600*/0x04, 0xE5, 0x74, 0x45, 0x75, 0x90, 0x07, 0x2F,
++	0xF0, 0x7F, 0x01, 0xE5, 0x3E, 0x60, 0x04, 0xE5,
++/*0610*/0x3C, 0x70, 0x14, 0xE4, 0xF5, 0x3C, 0xF5, 0x3D,
++	0xF5, 0x3E, 0xF5, 0x3F, 0x12, 0x08, 0xD2, 0x70,
++/*0620*/0x04, 0xF0, 0x02, 0x06, 0xA4, 0x80, 0x7A, 0xE5,
++	0x3C, 0xC3, 0x95, 0x3E, 0x40, 0x07, 0xE5, 0x3C,
++/*0630*/0x95, 0x3E, 0xFF, 0x80, 0x06, 0xC3, 0xE5, 0x3E,
++	0x95, 0x3C, 0xFF, 0xE5, 0x76, 0xD3, 0x95, 0x79,
++/*0640*/0x40, 0x05, 0x85, 0x76, 0x7A, 0x80, 0x03, 0x85,
++	0x79, 0x7A, 0xE5, 0x77, 0xC3, 0x95, 0x78, 0x50,
++/*0650*/0x05, 0x85, 0x77, 0x7B, 0x80, 0x03, 0x85, 0x78,
++	0x7B, 0xE5, 0x7B, 0xD3, 0x95, 0x7A, 0x40, 0x30,
++/*0660*/0xE5, 0x7B, 0x95, 0x7A, 0xF5, 0x3C, 0xF5, 0x3E,
++	0xC3, 0xE5, 0x7B, 0x95, 0x7A, 0x90, 0x07, 0x19,
++/*0670*/0xF0, 0xE5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
++	0x7A, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
++/*0680*/0xE4, 0xF5, 0x3D, 0x80, 0x1F, 0xC3, 0x74, 0x3F,
++	0x95, 0x72, 0xF5, 0x3D, 0xF5, 0x3F, 0x80, 0x14,
++/*0690*/0xE4, 0xF5, 0x3C, 0xF5, 0x3E, 0x90, 0x07, 0x19,
++	0xF0, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
++/*06A0*/0x03, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x65, 0x75,
++	0x83, 0xD0, 0xE0, 0x54, 0x0F, 0xFE, 0xAD, 0x3C,
++/*06B0*/0x70, 0x02, 0x7E, 0x07, 0xBE, 0x0F, 0x02, 0x7E,
++	0x80, 0xEE, 0xFB, 0xEF, 0xD3, 0x9B, 0x74, 0x80,
++/*06C0*/0xF8, 0x98, 0x40, 0x1F, 0xE4, 0xF5, 0x3C, 0xF5,
++	0x3E, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
++/*06D0*/0x12, 0x74, 0x01, 0xF0, 0xE5, 0x08, 0xFB, 0xEB,
++	0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xD2, 0xE0,
++/*06E0*/0x44, 0x10, 0xF0, 0xE5, 0x08, 0xFB, 0xEB, 0x44,
++	0x09, 0xF5, 0x82, 0x75, 0x83, 0x9E, 0xED, 0xF0,
++/*06F0*/0xEB, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xCA,
++	0xED, 0xF0, 0x12, 0x08, 0x65, 0x75, 0x83, 0xCC,
++/*0700*/0xEF, 0xF0, 0x22, 0xE5, 0x08, 0x44, 0x07, 0xF5,
++	0x82, 0x75, 0x83, 0xBC, 0xE0, 0x54, 0xF0, 0xF0,
++/*0710*/0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83,
++	0xBE, 0xE0, 0x54, 0xF0, 0xF0, 0xE5, 0x08, 0x44,
++/*0720*/0x07, 0xF5, 0x82, 0x75, 0x83, 0xC0, 0xE0, 0x54,
++	0xF0, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
++/*0730*/0x22, 0xF0, 0x90, 0x07, 0x28, 0xE0, 0xFE, 0xA3,
++	0xE0, 0xF5, 0x82, 0x8E, 0x83, 0x22, 0x85, 0x42,
++/*0740*/0x42, 0x85, 0x41, 0x41, 0x85, 0x40, 0x40, 0x74,
++	0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E, 0xF5,
++/*0750*/0x83, 0xE5, 0x42, 0xF0, 0x74, 0xE0, 0x2F, 0xF5,
++	0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xE5,
++/*0760*/0x42, 0x29, 0xFD, 0xE4, 0x33, 0xFC, 0xE5, 0x3C,
++	0xC3, 0x9D, 0xEC, 0x64, 0x80, 0xF8, 0x74, 0x80,
++/*0770*/0x98, 0x22, 0xF5, 0x83, 0xE0, 0x90, 0x07, 0x22,
++	0x54, 0x1F, 0xFD, 0xE0, 0xFA, 0xA3, 0xE0, 0xF5,
++/*0780*/0x82, 0x8A, 0x83, 0xED, 0xF0, 0x22, 0x90, 0x07,
++	0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xF5, 0x82, 0x8C,
++/*0790*/0x83, 0x22, 0x90, 0x07, 0x24, 0xFF, 0xED, 0x44,
++	0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, 0x85,
++/*07A0*/0x38, 0x38, 0x85, 0x39, 0x39, 0x85, 0x3A, 0x3A,
++	0x74, 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E,
++/*07B0*/0xF5, 0x83, 0x22, 0x90, 0x07, 0x26, 0xFF, 0xED,
++	0x44, 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22,
++/*07C0*/0xF0, 0x74, 0xA0, 0x2F, 0xF5, 0x82, 0x74, 0x02,
++	0x3E, 0xF5, 0x83, 0x22, 0x74, 0xC0, 0x25, 0x11,
++/*07D0*/0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0x22,
++	0x74, 0x00, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
++/*07E0*/0x02, 0xF5, 0x83, 0x22, 0x74, 0x60, 0x25, 0x11,
++	0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
++/*07F0*/0x74, 0x80, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
++	0x03, 0xF5, 0x83, 0x22, 0x74, 0xE0, 0x25, 0x11,
++/*0800*/0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
++	0x74, 0x40, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
++/*0810*/0x06, 0xF5, 0x83, 0x22, 0x74, 0x80, 0x2F, 0xF5,
++	0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xAF,
++/*0820*/0x08, 0x7E, 0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82,
++	0x22, 0xF5, 0x83, 0xE5, 0x82, 0x44, 0x07, 0xF5,
++/*0830*/0x82, 0xE5, 0x40, 0xF0, 0x22, 0x74, 0x40, 0x25,
++	0x11, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
++/*0840*/0x22, 0x74, 0xC0, 0x25, 0x11, 0xF5, 0x82, 0xE4,
++	0x34, 0x03, 0xF5, 0x83, 0x22, 0x74, 0x00, 0x25,
++/*0850*/0x11, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83,
++	0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
++/*0860*/0x34, 0x06, 0xF5, 0x83, 0x22, 0xE5, 0x08, 0xFD,
++	0xED, 0x44, 0x07, 0xF5, 0x82, 0x22, 0xE5, 0x41,
++/*0870*/0xF0, 0xE5, 0x65, 0x64, 0x01, 0x45, 0x64, 0x22,
++	0x7E, 0x00, 0xFB, 0x7A, 0x00, 0xFD, 0x7C, 0x00,
++/*0880*/0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
++	0x34, 0x02, 0x22, 0x74, 0xA0, 0x25, 0x11, 0xF5,
++/*0890*/0x82, 0xE4, 0x34, 0x03, 0x22, 0x85, 0x3E, 0x42,
++	0x85, 0x3F, 0x41, 0x8F, 0x40, 0x22, 0x85, 0x3C,
++/*08A0*/0x42, 0x85, 0x3D, 0x41, 0x8F, 0x40, 0x22, 0x75,
++	0x45, 0x3F, 0x90, 0x07, 0x20, 0xE4, 0xF0, 0xA3,
++/*08B0*/0x22, 0xF5, 0x83, 0xE5, 0x32, 0xF0, 0x05, 0x6E,
++	0xE5, 0x6E, 0xC3, 0x94, 0x40, 0x22, 0xF0, 0xE5,
++/*08C0*/0x08, 0x44, 0x06, 0xF5, 0x82, 0x22, 0x74, 0x00,
++	0x25, 0x6E, 0xF5, 0x82, 0xE4, 0x34, 0x00, 0xF5,
++/*08D0*/0x83, 0x22, 0xE5, 0x6D, 0x45, 0x6C, 0x90, 0x07,
++	0x2F, 0x22, 0xE4, 0xF9, 0xE5, 0x3C, 0xD3, 0x95,
++/*08E0*/0x3E, 0x22, 0x74, 0x80, 0x2E, 0xF5, 0x82, 0xE4,
++	0x34, 0x02, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0xA0,
++/*08F0*/0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
++	0xE0, 0x22, 0x74, 0x80, 0x25, 0x6E, 0xF5, 0x82,
++/*0900*/0xE4, 0x34, 0x00, 0x22, 0x25, 0x42, 0xFD, 0xE4,
++	0x33, 0xFC, 0x22, 0x85, 0x42, 0x42, 0x85, 0x41,
++/*0910*/0x41, 0x85, 0x40, 0x40, 0x22, 0xED, 0x4C, 0x60,
++	0x03, 0x02, 0x09, 0xE5, 0xEF, 0x4E, 0x70, 0x37,
++/*0920*/0x90, 0x07, 0x26, 0x12, 0x07, 0x89, 0xE0, 0xFD,
++	0x12, 0x07, 0xCC, 0xED, 0xF0, 0x90, 0x07, 0x28,
++/*0930*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xD8,
++	0xED, 0xF0, 0x12, 0x07, 0x86, 0xE0, 0x54, 0x1F,
++/*0940*/0xFD, 0x12, 0x08, 0x81, 0xF5, 0x83, 0xED, 0xF0,
++	0x90, 0x07, 0x24, 0x12, 0x07, 0x89, 0xE0, 0x54,
++/*0950*/0x1F, 0xFD, 0x12, 0x08, 0x35, 0xED, 0xF0, 0xEF,
++	0x64, 0x04, 0x4E, 0x70, 0x37, 0x90, 0x07, 0x26,
++/*0960*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xE4,
++	0xED, 0xF0, 0x90, 0x07, 0x28, 0x12, 0x07, 0x89,
++/*0970*/0xE0, 0xFD, 0x12, 0x07, 0xF0, 0xED, 0xF0, 0x12,
++	0x07, 0x86, 0xE0, 0x54, 0x1F, 0xFD, 0x12, 0x08,
++/*0980*/0x8B, 0xF5, 0x83, 0xED, 0xF0, 0x90, 0x07, 0x24,
++	0x12, 0x07, 0x89, 0xE0, 0x54, 0x1F, 0xFD, 0x12,
++/*0990*/0x08, 0x41, 0xED, 0xF0, 0xEF, 0x64, 0x01, 0x4E,
++	0x70, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
++/*09A0*/0xEF, 0x64, 0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01,
++	0x80, 0x02, 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x78,
++/*09B0*/0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE0, 0xFF,
++	0x12, 0x07, 0xFC, 0xEF, 0x12, 0x07, 0x31, 0xE0,
++/*09C0*/0xFF, 0x12, 0x08, 0x08, 0xEF, 0xF0, 0x90, 0x07,
++	0x22, 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF,
++/*09D0*/0x12, 0x08, 0x4D, 0xEF, 0xF0, 0x90, 0x07, 0x24,
++	0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
++/*09E0*/0x08, 0x59, 0xEF, 0xF0, 0x22, 0x12, 0x07, 0xCC,
++	0xE4, 0xF0, 0x12, 0x07, 0xD8, 0xE4, 0xF0, 0x12,
++/*09F0*/0x08, 0x81, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08,
++	0x35, 0x74, 0x14, 0xF0, 0x12, 0x07, 0xE4, 0xE4,
++/*0A00*/0xF0, 0x12, 0x07, 0xF0, 0xE4, 0xF0, 0x12, 0x08,
++	0x8B, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08, 0x41,
++/*0A10*/0x74, 0x14, 0xF0, 0x12, 0x07, 0xFC, 0xE4, 0xF0,
++	0x12, 0x08, 0x08, 0xE4, 0xF0, 0x12, 0x08, 0x4D,
++/*0A20*/0xE4, 0xF0, 0x12, 0x08, 0x59, 0x74, 0x14, 0xF0,
++	0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFC, 0x10, 0xE4,
++/*0A30*/0xF5, 0xFD, 0x75, 0xFE, 0x30, 0xF5, 0xFF, 0xE5,
++	0xE7, 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0xE5,
++/*0A40*/0xE6, 0x20, 0xE7, 0x0B, 0x78, 0xFF, 0xE4, 0xF6,
++	0xD8, 0xFD, 0x53, 0xE6, 0xFE, 0x80, 0x09, 0x78,
++/*0A50*/0x08, 0xE4, 0xF6, 0xD8, 0xFD, 0x53, 0xE6, 0xFE,
++	0x75, 0x81, 0x80, 0xE4, 0xF5, 0xA8, 0xD2, 0xA8,
++/*0A60*/0xC2, 0xA9, 0xD2, 0xAF, 0xE5, 0xE2, 0x20, 0xE5,
++	0x05, 0x20, 0xE6, 0x02, 0x80, 0x03, 0x43, 0xE1,
++/*0A70*/0x02, 0xE5, 0xE2, 0x20, 0xE0, 0x0E, 0x90, 0x00,
++	0x00, 0x7F, 0x00, 0x7E, 0x08, 0xE4, 0xF0, 0xA3,
++/*0A80*/0xDF, 0xFC, 0xDE, 0xFA, 0x02, 0x0A, 0xDB, 0x43,
++	0xFA, 0x01, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83,
++/*0A90*/0xC0, 0x82, 0xC0, 0xD0, 0x12, 0x1C, 0xE7, 0xD0,
++	0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0,
++/*0AA0*/0xE0, 0x53, 0xFA, 0xFE, 0x32, 0x02, 0x1B, 0x55,
++	0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xF6,
++/*0AB0*/0x08, 0xDF, 0xF9, 0x80, 0x29, 0xE4, 0x93, 0xA3,
++	0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33,
++/*0AC0*/0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40,
++	0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF,
++/*0AD0*/0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08, 0x10,
++	0x20, 0x40, 0x80, 0x90, 0x00, 0x3F, 0xE4, 0x7E,
++/*0AE0*/0x01, 0x93, 0x60, 0xC1, 0xA3, 0xFF, 0x54, 0x3F,
++	0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93,
++/*0AF0*/0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25,
++	0xE0, 0x60, 0xAD, 0x40, 0xB8, 0x80, 0xFE, 0x8C,
++/*0B00*/0x64, 0x8D, 0x65, 0x8A, 0x66, 0x8B, 0x67, 0xE4,
++	0xF5, 0x69, 0xEF, 0x4E, 0x70, 0x03, 0x02, 0x1D,
++/*0B10*/0x55, 0xE4, 0xF5, 0x68, 0xE5, 0x67, 0x45, 0x66,
++	0x70, 0x32, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90,
++/*0B20*/0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE4,
++	0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4, 0x12,
++/*0B30*/0x08, 0x70, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
++	0x83, 0x92, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*0B40*/0xC6, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8,
++	0xE4, 0xF0, 0x80, 0x11, 0x90, 0x07, 0x26, 0x12,
++/*0B50*/0x07, 0x35, 0xE4, 0x12, 0x08, 0x70, 0x70, 0x05,
++	0x12, 0x07, 0x32, 0xE4, 0xF0, 0x12, 0x1D, 0x55,
++/*0B60*/0x12, 0x1E, 0xBF, 0xE5, 0x67, 0x45, 0x66, 0x70,
++	0x33, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90, 0xE5,
++/*0B70*/0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
++	0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x12,
++/*0B80*/0x08, 0x6E, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
++	0x83, 0x92, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
++/*0B90*/0x83, 0xC6, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
++	0x83, 0xC8, 0x80, 0x0E, 0x90, 0x07, 0x26, 0x12,
++/*0BA0*/0x07, 0x35, 0x12, 0x08, 0x6E, 0x70, 0x06, 0x12,
++	0x07, 0x32, 0xE5, 0x40, 0xF0, 0xAF, 0x69, 0x7E,
++/*0BB0*/0x00, 0xAD, 0x67, 0xAC, 0x66, 0x12, 0x04, 0x44,
++	0x12, 0x07, 0x2A, 0x75, 0x83, 0xCA, 0xE0, 0xD3,
++/*0BC0*/0x94, 0x00, 0x50, 0x0C, 0x05, 0x68, 0xE5, 0x68,
++	0xC3, 0x94, 0x05, 0x50, 0x03, 0x02, 0x0B, 0x14,
++/*0BD0*/0x22, 0x8C, 0x60, 0x8D, 0x61, 0x12, 0x08, 0xDA,
++	0x74, 0x20, 0x40, 0x0D, 0x2F, 0xF5, 0x82, 0x74,
++/*0BE0*/0x03, 0x3E, 0xF5, 0x83, 0xE5, 0x3E, 0xF0, 0x80,
++	0x0B, 0x2F, 0xF5, 0x82, 0x74, 0x03, 0x3E, 0xF5,
++/*0BF0*/0x83, 0xE5, 0x3C, 0xF0, 0xE5, 0x3C, 0xD3, 0x95,
++	0x3E, 0x40, 0x3C, 0xE5, 0x61, 0x45, 0x60, 0x70,
++/*0C00*/0x10, 0xE9, 0x12, 0x09, 0x04, 0xE5, 0x3E, 0x12,
++	0x07, 0x68, 0x40, 0x3B, 0x12, 0x08, 0x95, 0x80,
++/*0C10*/0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40, 0x1D,
++	0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05, 0x85,
++/*0C20*/0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F,
++	0x3A, 0x12, 0x08, 0x14, 0xE5, 0x3E, 0x12, 0x07,
++/*0C30*/0xC0, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x43, 0xE5,
++	0x61, 0x45, 0x60, 0x70, 0x19, 0x12, 0x07, 0x5F,
++/*0C40*/0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x27, 0x12,
++	0x09, 0x0B, 0x12, 0x08, 0x14, 0xE5, 0x42, 0x12,
++/*0C50*/0x07, 0xC0, 0xE5, 0x41, 0xF0, 0x22, 0xE5, 0x3C,
++	0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C, 0x38,
++/*0C60*/0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39, 0x80,
++	0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x08,
++/*0C70*/0x14, 0xE5, 0x3C, 0x12, 0x07, 0xC0, 0xE5, 0x3D,
++	0xF0, 0x22, 0x85, 0x38, 0x38, 0x85, 0x39, 0x39,
++/*0C80*/0x85, 0x3A, 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x38,
++	0x12, 0x07, 0xC0, 0xE5, 0x39, 0xF0, 0x22, 0x7F,
++/*0C90*/0x06, 0x12, 0x17, 0x31, 0x12, 0x1D, 0x23, 0x12,
++	0x0E, 0x04, 0x12, 0x0E, 0x33, 0xE0, 0x44, 0x0A,
++/*0CA0*/0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E, 0x04, 0x12,
++	0x0E, 0x0B, 0xEF, 0xF0, 0xE5, 0x28, 0x30, 0xE5,
++/*0CB0*/0x03, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x05, 0x75,
++	0x14, 0x20, 0x80, 0x03, 0x75, 0x14, 0x08, 0x12,
++/*0CC0*/0x0E, 0x04, 0x75, 0x83, 0x8A, 0xE5, 0x14, 0xF0,
++	0xB4, 0xFF, 0x05, 0x75, 0x12, 0x80, 0x80, 0x06,
++/*0CD0*/0xE5, 0x14, 0xC3, 0x13, 0xF5, 0x12, 0xE4, 0xF5,
++	0x16, 0xF5, 0x7F, 0x12, 0x19, 0x36, 0x12, 0x13,
++/*0CE0*/0xA3, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x50, 0x09,
++	0x05, 0x16, 0xE5, 0x16, 0xC3, 0x94, 0x14, 0x40,
++/*0CF0*/0xEA, 0xE5, 0xE4, 0x20, 0xE7, 0x28, 0x12, 0x0E,
++	0x04, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
++/*0D00*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
++	0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
++/*0D10*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
++	0x5E, 0x60, 0x03, 0x12, 0x1D, 0xD7, 0xE5, 0x7F,
++/*0D20*/0xC3, 0x94, 0x11, 0x40, 0x14, 0x12, 0x0E, 0x04,
++	0x75, 0x83, 0xD2, 0xE0, 0x44, 0x80, 0xF0, 0xE5,
++/*0D30*/0xE4, 0x20, 0xE7, 0x0F, 0x12, 0x1D, 0xD7, 0x80,
++	0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0xD2, 0xE0,
++/*0D40*/0x54, 0x7F, 0xF0, 0x12, 0x1D, 0x23, 0x22, 0x74,
++	0x8A, 0x85, 0x08, 0x82, 0xF5, 0x83, 0xE5, 0x17,
++/*0D50*/0xF0, 0x12, 0x0E, 0x3A, 0xE4, 0xF0, 0x90, 0x07,
++	0x02, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x90,
++/*0D60*/0xEF, 0xF0, 0x74, 0x92, 0xFE, 0xE5, 0x08, 0x44,
++	0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x54,
++/*0D70*/0xC0, 0xFD, 0x90, 0x07, 0x03, 0xE0, 0x54, 0x3F,
++	0x4D, 0x8F, 0x82, 0x8E, 0x83, 0xF0, 0x90, 0x07,
++/*0D80*/0x04, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x82,
++	0xEF, 0xF0, 0x90, 0x07, 0x05, 0xE0, 0xFF, 0xED,
++/*0D90*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xB4, 0xEF,
++	0x12, 0x0E, 0x03, 0x75, 0x83, 0x80, 0xE0, 0x54,
++/*0DA0*/0xBF, 0xF0, 0x30, 0x37, 0x0A, 0x12, 0x0E, 0x91,
++	0x75, 0x83, 0x94, 0xE0, 0x44, 0x80, 0xF0, 0x30,
++/*0DB0*/0x38, 0x0A, 0x12, 0x0E, 0x91, 0x75, 0x83, 0x92,
++	0xE0, 0x44, 0x80, 0xF0, 0xE5, 0x28, 0x30, 0xE4,
++/*0DC0*/0x1A, 0x20, 0x39, 0x0A, 0x12, 0x0E, 0x04, 0x75,
++	0x83, 0x88, 0xE0, 0x54, 0x7F, 0xF0, 0x20, 0x3A,
++/*0DD0*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x88, 0xE0,
++	0x54, 0xBF, 0xF0, 0x74, 0x8C, 0xFE, 0x12, 0x0E,
++/*0DE0*/0x04, 0x8E, 0x83, 0xE0, 0x54, 0x0F, 0x12, 0x0E,
++	0x03, 0x75, 0x83, 0x86, 0xE0, 0x54, 0xBF, 0xF0,
++/*0DF0*/0xE5, 0x08, 0x44, 0x06, 0x12, 0x0D, 0xFD, 0x75,
++	0x83, 0x8A, 0xE4, 0xF0, 0x22, 0xF5, 0x82, 0x75,
++/*0E00*/0x83, 0x82, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07,
++	0xF5, 0x82, 0x22, 0x8E, 0x83, 0xE0, 0xF5, 0x10,
++/*0E10*/0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44, 0x01, 0xFF,
++	0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07, 0xF5, 0x82,
++/*0E20*/0x22, 0xE5, 0x15, 0xC4, 0x54, 0x07, 0xFF, 0xE5,
++	0x08, 0xFD, 0xED, 0x44, 0x08, 0xF5, 0x82, 0x75,
++/*0E30*/0x83, 0x82, 0x22, 0x75, 0x83, 0x80, 0xE0, 0x44,
++	0x40, 0xF0, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
++/*0E40*/0x75, 0x83, 0x8A, 0x22, 0xE5, 0x16, 0x25, 0xE0,
++	0x25, 0xE0, 0x24, 0xAF, 0xF5, 0x82, 0xE4, 0x34,
++/*0E50*/0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0D, 0x22,
++	0x43, 0xE1, 0x10, 0x43, 0xE1, 0x80, 0x53, 0xE1,
++/*0E60*/0xFD, 0x85, 0xE1, 0x10, 0x22, 0xE5, 0x16, 0x25,
++	0xE0, 0x25, 0xE0, 0x24, 0xB2, 0xF5, 0x82, 0xE4,
++/*0E70*/0x34, 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0x22, 0x85,
++	0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15, 0xF0,
++/*0E80*/0x22, 0xE5, 0xE2, 0x54, 0x20, 0xD3, 0x94, 0x00,
++	0x22, 0xE5, 0xE2, 0x54, 0x40, 0xD3, 0x94, 0x00,
++/*0E90*/0x22, 0xE5, 0x08, 0x44, 0x06, 0xF5, 0x82, 0x22,
++	0xFD, 0xE5, 0x08, 0xFB, 0xEB, 0x44, 0x07, 0xF5,
++/*0EA0*/0x82, 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFE, 0x30,
++	0x22, 0xEF, 0x4E, 0x70, 0x26, 0x12, 0x07, 0xCC,
++/*0EB0*/0xE0, 0xFD, 0x90, 0x07, 0x26, 0x12, 0x07, 0x7B,
++	0x12, 0x07, 0xD8, 0xE0, 0xFD, 0x90, 0x07, 0x28,
++/*0EC0*/0x12, 0x07, 0x7B, 0x12, 0x08, 0x81, 0x12, 0x07,
++	0x72, 0x12, 0x08, 0x35, 0xE0, 0x90, 0x07, 0x24,
++/*0ED0*/0x12, 0x07, 0x78, 0xEF, 0x64, 0x04, 0x4E, 0x70,
++	0x29, 0x12, 0x07, 0xE4, 0xE0, 0xFD, 0x90, 0x07,
++/*0EE0*/0x26, 0x12, 0x07, 0x7B, 0x12, 0x07, 0xF0, 0xE0,
++	0xFD, 0x90, 0x07, 0x28, 0x12, 0x07, 0x7B, 0x12,
++/*0EF0*/0x08, 0x8B, 0x12, 0x07, 0x72, 0x12, 0x08, 0x41,
++	0xE0, 0x54, 0x1F, 0xFD, 0x90, 0x07, 0x24, 0x12,
++/*0F00*/0x07, 0x7B, 0xEF, 0x64, 0x01, 0x4E, 0x70, 0x04,
++	0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0xEF, 0x64,
++/*0F10*/0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02,
++	0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x35, 0x12, 0x07,
++/*0F20*/0xFC, 0xE0, 0xFF, 0x90, 0x07, 0x26, 0x12, 0x07,
++	0x89, 0xEF, 0xF0, 0x12, 0x08, 0x08, 0xE0, 0xFF,
++/*0F30*/0x90, 0x07, 0x28, 0x12, 0x07, 0x89, 0xEF, 0xF0,
++	0x12, 0x08, 0x4D, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
++/*0F40*/0x07, 0x86, 0xEF, 0xF0, 0x12, 0x08, 0x59, 0xE0,
++	0x54, 0x1F, 0xFF, 0x90, 0x07, 0x24, 0x12, 0x07,
++/*0F50*/0x89, 0xEF, 0xF0, 0x22, 0xE4, 0xF5, 0x53, 0x12,
++	0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
++/*0F60*/0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40, 0x04, 0x7E,
++	0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x70,
++/*0F70*/0x03, 0x02, 0x0F, 0xF6, 0x85, 0xE1, 0x10, 0x43,
++	0xE1, 0x02, 0x53, 0xE1, 0x0F, 0x85, 0xE1, 0x10,
++/*0F80*/0xE4, 0xF5, 0x51, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
++	0x52, 0x12, 0x0E, 0x89, 0x40, 0x1D, 0xAD, 0x52,
++/*0F90*/0xAF, 0x51, 0x12, 0x11, 0x18, 0xEF, 0x60, 0x08,
++	0x85, 0xE1, 0x10, 0x43, 0xE1, 0x40, 0x80, 0x0B,
++/*0FA0*/0x53, 0xE1, 0xBF, 0x12, 0x0E, 0x58, 0x12, 0x00,
++	0x06, 0x80, 0xFB, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
++/*0FB0*/0x51, 0xE5, 0xE4, 0x54, 0x3F, 0xF5, 0x52, 0x12,
++	0x0E, 0x81, 0x40, 0x1D, 0xAD, 0x52, 0xAF, 0x51,
++/*0FC0*/0x12, 0x11, 0x18, 0xEF, 0x60, 0x08, 0x85, 0xE1,
++	0x10, 0x43, 0xE1, 0x20, 0x80, 0x0B, 0x53, 0xE1,
++/*0FD0*/0xDF, 0x12, 0x0E, 0x58, 0x12, 0x00, 0x06, 0x80,
++	0xFB, 0x12, 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01,
++/*0FE0*/0x80, 0x02, 0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40,
++	0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
++/*0FF0*/0x4F, 0x60, 0x03, 0x12, 0x0E, 0x5B, 0x22, 0x12,
++	0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x22,
++/*1000*/0x02, 0x11, 0x00, 0x02, 0x10, 0x40, 0x02, 0x10,
++	0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1010*/0x01, 0x20, 0x01, 0x20, 0xE4, 0xF5, 0x57, 0x12,
++	0x16, 0xBD, 0x12, 0x16, 0x44, 0xE4, 0x12, 0x10,
++/*1020*/0x56, 0x12, 0x14, 0xB7, 0x90, 0x07, 0x26, 0x12,
++	0x07, 0x35, 0xE4, 0x12, 0x07, 0x31, 0xE4, 0xF0,
++/*1030*/0x12, 0x10, 0x56, 0x12, 0x14, 0xB7, 0x90, 0x07,
++	0x26, 0x12, 0x07, 0x35, 0xE5, 0x41, 0x12, 0x07,
++/*1040*/0x31, 0xE5, 0x40, 0xF0, 0xAF, 0x57, 0x7E, 0x00,
++	0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
++/*1050*/0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xFF, 0x90,
++	0x07, 0x20, 0xA3, 0xE0, 0xFD, 0xE4, 0xF5, 0x56,
++/*1060*/0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x12,
++	0x11, 0x51, 0x7F, 0x0F, 0x7D, 0x18, 0xE4, 0xF5,
++/*1070*/0x56, 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA,
++	0x12, 0x15, 0x41, 0xAF, 0x56, 0x7E, 0x00, 0x12,
++/*1080*/0x1A, 0xFF, 0xE4, 0xFF, 0xF5, 0x56, 0x7D, 0x1F,
++	0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x22,
++/*1090*/0x22, 0xE4, 0xF5, 0x55, 0xE5, 0x08, 0xFD, 0x74,
++	0xA0, 0xF5, 0x56, 0xED, 0x44, 0x07, 0xF5, 0x57,
++/*10A0*/0xE5, 0x28, 0x30, 0xE5, 0x03, 0xD3, 0x80, 0x01,
++	0xC3, 0x40, 0x05, 0x7F, 0x28, 0xEF, 0x80, 0x04,
++/*10B0*/0x7F, 0x14, 0xEF, 0xC3, 0x13, 0xF5, 0x54, 0xE4,
++	0xF9, 0x12, 0x0E, 0x18, 0x75, 0x83, 0x8E, 0xE0,
++/*10C0*/0xF5, 0x10, 0xCE, 0xEF, 0xCE, 0xEE, 0xD3, 0x94,
++	0x00, 0x40, 0x26, 0xE5, 0x10, 0x54, 0xFE, 0x12,
++/*10D0*/0x0E, 0x98, 0x75, 0x83, 0x8E, 0xED, 0xF0, 0xE5,
++	0x10, 0x44, 0x01, 0xFD, 0xEB, 0x44, 0x07, 0xF5,
++/*10E0*/0x82, 0xED, 0xF0, 0x85, 0x57, 0x82, 0x85, 0x56,
++	0x83, 0xE0, 0x30, 0xE3, 0x01, 0x09, 0x1E, 0x80,
++/*10F0*/0xD4, 0xC2, 0x34, 0xE9, 0xC3, 0x95, 0x54, 0x40,
++	0x02, 0xD2, 0x34, 0x22, 0x02, 0x00, 0x06, 0x22,
++/*1100*/0x30, 0x30, 0x11, 0x90, 0x10, 0x00, 0xE4, 0x93,
++	0xF5, 0x10, 0x90, 0x10, 0x10, 0xE4, 0x93, 0xF5,
++/*1110*/0x10, 0x12, 0x10, 0x90, 0x12, 0x11, 0x50, 0x22,
++	0xE4, 0xFC, 0xC3, 0xED, 0x9F, 0xFA, 0xEF, 0xF5,
++/*1120*/0x83, 0x75, 0x82, 0x00, 0x79, 0xFF, 0xE4, 0x93,
++	0xCC, 0x6C, 0xCC, 0xA3, 0xD9, 0xF8, 0xDA, 0xF6,
++/*1130*/0xE5, 0xE2, 0x30, 0xE4, 0x02, 0x8C, 0xE5, 0xED,
++	0x24, 0xFF, 0xFF, 0xEF, 0x75, 0x82, 0xFF, 0xF5,
++/*1140*/0x83, 0xE4, 0x93, 0x6C, 0x70, 0x03, 0x7F, 0x01,
++	0x22, 0x7F, 0x00, 0x22, 0x22, 0x11, 0x00, 0x00,
++/*1150*/0x22, 0x8E, 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D,
++	0x5B, 0x8A, 0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01,
++/*1160*/0xE4, 0xF5, 0x5F, 0xF5, 0x60, 0xF5, 0x62, 0x12,
++	0x07, 0x2A, 0x75, 0x83, 0xD0, 0xE0, 0xFF, 0xC4,
++/*1170*/0x54, 0x0F, 0xF5, 0x61, 0x12, 0x1E, 0xA5, 0x85,
++	0x59, 0x5E, 0xD3, 0xE5, 0x5E, 0x95, 0x5B, 0xE5,
++/*1180*/0x5A, 0x12, 0x07, 0x6B, 0x50, 0x4B, 0x12, 0x07,
++	0x03, 0x75, 0x83, 0xBC, 0xE0, 0x45, 0x5E, 0x12,
++/*1190*/0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x45, 0x5E,
++	0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0, 0x45,
++/*11A0*/0x5E, 0xF0, 0xAF, 0x5F, 0xE5, 0x60, 0x12, 0x08,
++	0x78, 0x12, 0x0A, 0xFF, 0xAF, 0x62, 0x7E, 0x00,
++/*11B0*/0xAD, 0x5D, 0xAC, 0x5C, 0x12, 0x04, 0x44, 0xE5,
++	0x61, 0xAF, 0x5E, 0x7E, 0x00, 0xB4, 0x03, 0x05,
++/*11C0*/0x12, 0x1E, 0x21, 0x80, 0x07, 0xAD, 0x5D, 0xAC,
++	0x5C, 0x12, 0x13, 0x17, 0x05, 0x5E, 0x02, 0x11,
++/*11D0*/0x7A, 0x12, 0x07, 0x03, 0x75, 0x83, 0xBC, 0xE0,
++	0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBE,
++/*11E0*/0xE0, 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83,
++	0xC0, 0xE0, 0x45, 0x40, 0xF0, 0x22, 0x8E, 0x58,
++/*11F0*/0x8F, 0x59, 0x75, 0x5A, 0x01, 0x79, 0x01, 0x75,
++	0x5B, 0x01, 0xE4, 0xFB, 0x12, 0x07, 0x2A, 0x75,
++/*1200*/0x83, 0xAE, 0xE0, 0x54, 0x1A, 0xFF, 0x12, 0x08,
++	0x65, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0xFE, 0xEF,
++/*1210*/0x70, 0x0C, 0xEE, 0x65, 0x35, 0x70, 0x07, 0x90,
++	0x07, 0x2F, 0xE0, 0xB4, 0x01, 0x0D, 0xAF, 0x35,
++/*1220*/0x7E, 0x00, 0x12, 0x0E, 0xA9, 0xCF, 0xEB, 0xCF,
++	0x02, 0x1E, 0x60, 0xE5, 0x59, 0x64, 0x02, 0x45,
++/*1230*/0x58, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
++	0x00, 0xE5, 0x59, 0x45, 0x58, 0x70, 0x04, 0x7E,
++/*1240*/0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60,
++	0x23, 0x85, 0x41, 0x49, 0x85, 0x40, 0x4B, 0xE5,
++/*1250*/0x59, 0x45, 0x58, 0x70, 0x2C, 0xAF, 0x5A, 0xFE,
++	0xCD, 0xE9, 0xCD, 0xFC, 0xAB, 0x59, 0xAA, 0x58,
++/*1260*/0x12, 0x0A, 0xFF, 0xAF, 0x5B, 0x7E, 0x00, 0x12,
++	0x1E, 0x60, 0x80, 0x15, 0xAF, 0x5B, 0x7E, 0x00,
++/*1270*/0x12, 0x1E, 0x60, 0x90, 0x07, 0x26, 0x12, 0x07,
++	0x35, 0xE5, 0x49, 0x12, 0x07, 0x31, 0xE5, 0x4B,
++/*1280*/0xF0, 0xE4, 0xFD, 0xAF, 0x35, 0xFE, 0xFC, 0x12,
++	0x09, 0x15, 0x22, 0x8C, 0x64, 0x8D, 0x65, 0x12,
++/*1290*/0x08, 0xDA, 0x40, 0x3C, 0xE5, 0x65, 0x45, 0x64,
++	0x70, 0x10, 0x12, 0x09, 0x04, 0xC3, 0xE5, 0x3E,
++/*12A0*/0x12, 0x07, 0x69, 0x40, 0x3B, 0x12, 0x08, 0x95,
++	0x80, 0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40,
++/*12B0*/0x1D, 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05,
++	0x85, 0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39,
++/*12C0*/0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3E, 0x12,
++	0x07, 0x53, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x3B,
++/*12D0*/0xE5, 0x65, 0x45, 0x64, 0x70, 0x11, 0x12, 0x07,
++	0x5F, 0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x1F,
++/*12E0*/0x12, 0x07, 0x3E, 0xE5, 0x41, 0xF0, 0x22, 0xE5,
++	0x3C, 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C,
++/*12F0*/0x38, 0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39,
++	0x80, 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12,
++/*1300*/0x07, 0xA8, 0xE5, 0x3C, 0x12, 0x07, 0x53, 0xE5,
++	0x3D, 0xF0, 0x22, 0x12, 0x07, 0x9F, 0xE5, 0x38,
++/*1310*/0x12, 0x07, 0x53, 0xE5, 0x39, 0xF0, 0x22, 0x8C,
++	0x63, 0x8D, 0x64, 0x12, 0x08, 0xDA, 0x40, 0x3C,
++/*1320*/0xE5, 0x64, 0x45, 0x63, 0x70, 0x10, 0x12, 0x09,
++	0x04, 0xC3, 0xE5, 0x3E, 0x12, 0x07, 0x69, 0x40,
++/*1330*/0x3B, 0x12, 0x08, 0x95, 0x80, 0x18, 0xE5, 0x3E,
++	0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3E, 0x38,
++/*1340*/0xE5, 0x3E, 0x60, 0x05, 0x85, 0x3F, 0x39, 0x80,
++	0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x07,
++/*1350*/0xA8, 0xE5, 0x3E, 0x12, 0x07, 0x53, 0xE5, 0x3F,
++	0xF0, 0x22, 0x80, 0x3B, 0xE5, 0x64, 0x45, 0x63,
++/*1360*/0x70, 0x11, 0x12, 0x07, 0x5F, 0x40, 0x05, 0x12,
++	0x08, 0x9E, 0x80, 0x1F, 0x12, 0x07, 0x3E, 0xE5,
++/*1370*/0x41, 0xF0, 0x22, 0xE5, 0x3C, 0xC3, 0x95, 0x38,
++	0x40, 0x1D, 0x85, 0x3C, 0x38, 0xE5, 0x3C, 0x60,
++/*1380*/0x05, 0x85, 0x3D, 0x39, 0x80, 0x03, 0x85, 0x39,
++	0x39, 0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3C,
++/*1390*/0x12, 0x07, 0x53, 0xE5, 0x3D, 0xF0, 0x22, 0x12,
++	0x07, 0x9F, 0xE5, 0x38, 0x12, 0x07, 0x53, 0xE5,
++/*13A0*/0x39, 0xF0, 0x22, 0xE5, 0x0D, 0xFE, 0xE5, 0x08,
++	0x8E, 0x54, 0x44, 0x05, 0xF5, 0x55, 0x75, 0x15,
++/*13B0*/0x0F, 0xF5, 0x82, 0x12, 0x0E, 0x7A, 0x12, 0x17,
++	0xA3, 0x20, 0x31, 0x05, 0x75, 0x15, 0x03, 0x80,
++/*13C0*/0x03, 0x75, 0x15, 0x0B, 0xE5, 0x0A, 0xC3, 0x94,
++	0x01, 0x50, 0x38, 0x12, 0x14, 0x20, 0x20, 0x31,
++/*13D0*/0x06, 0x05, 0x15, 0x05, 0x15, 0x80, 0x04, 0x15,
++	0x15, 0x15, 0x15, 0xE5, 0x0A, 0xC3, 0x94, 0x01,
++/*13E0*/0x50, 0x21, 0x12, 0x14, 0x20, 0x20, 0x31, 0x04,
++	0x05, 0x15, 0x80, 0x02, 0x15, 0x15, 0xE5, 0x0A,
++/*13F0*/0xC3, 0x94, 0x01, 0x50, 0x0E, 0x12, 0x0E, 0x77,
++	0x12, 0x17, 0xA3, 0x20, 0x31, 0x05, 0x05, 0x15,
++/*1400*/0x12, 0x0E, 0x77, 0xE5, 0x15, 0xB4, 0x08, 0x04,
++	0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x15,
++/*1410*/0xB4, 0x07, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E,
++	0x00, 0xEE, 0x4F, 0x60, 0x02, 0x05, 0x7F, 0x22,
++/*1420*/0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15,
++	0xF0, 0x12, 0x17, 0xA3, 0x22, 0x12, 0x07, 0x2A,
++/*1430*/0x75, 0x83, 0xAE, 0x74, 0xFF, 0x12, 0x07, 0x29,
++	0xE0, 0x54, 0x1A, 0xF5, 0x34, 0xE0, 0xC4, 0x13,
++/*1440*/0x54, 0x07, 0xF5, 0x35, 0x24, 0xFE, 0x60, 0x24,
++	0x24, 0xFE, 0x60, 0x3C, 0x24, 0x04, 0x70, 0x63,
++/*1450*/0x75, 0x31, 0x2D, 0xE5, 0x08, 0xFD, 0x74, 0xB6,
++	0x12, 0x07, 0x92, 0x74, 0xBC, 0x90, 0x07, 0x22,
++/*1460*/0x12, 0x07, 0x95, 0x74, 0x90, 0x12, 0x07, 0xB3,
++	0x74, 0x92, 0x80, 0x3C, 0x75, 0x31, 0x3A, 0xE5,
++/*1470*/0x08, 0xFD, 0x74, 0xBA, 0x12, 0x07, 0x92, 0x74,
++	0xC0, 0x90, 0x07, 0x22, 0x12, 0x07, 0xB6, 0x74,
++/*1480*/0xC4, 0x12, 0x07, 0xB3, 0x74, 0xC8, 0x80, 0x20,
++	0x75, 0x31, 0x35, 0xE5, 0x08, 0xFD, 0x74, 0xB8,
++/*1490*/0x12, 0x07, 0x92, 0x74, 0xBE, 0xFF, 0xED, 0x44,
++	0x07, 0x90, 0x07, 0x22, 0xCF, 0xF0, 0xA3, 0xEF,
++/*14A0*/0xF0, 0x74, 0xC2, 0x12, 0x07, 0xB3, 0x74, 0xC6,
++	0xFF, 0xED, 0x44, 0x07, 0xA3, 0xCF, 0xF0, 0xA3,
++/*14B0*/0xEF, 0xF0, 0x22, 0x75, 0x34, 0x01, 0x22, 0x8E,
++	0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D, 0x5B, 0x8A,
++/*14C0*/0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01, 0xE4, 0xF5,
++	0x5F, 0x12, 0x1E, 0xA5, 0x85, 0x59, 0x5E, 0xD3,
++/*14D0*/0xE5, 0x5E, 0x95, 0x5B, 0xE5, 0x5A, 0x12, 0x07,
++	0x6B, 0x50, 0x57, 0xE5, 0x5D, 0x45, 0x5C, 0x70,
++/*14E0*/0x30, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x92, 0xE5,
++	0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE5,
++/*14F0*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8, 0xE5,
++	0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0x90, 0xE5,
++/*1500*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
++	0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x80,
++/*1510*/0x03, 0x12, 0x07, 0x32, 0xE5, 0x5E, 0xF0, 0xAF,
++	0x5F, 0x7E, 0x00, 0xAD, 0x5D, 0xAC, 0x5C, 0x12,
++/*1520*/0x04, 0x44, 0xAF, 0x5E, 0x7E, 0x00, 0xAD, 0x5D,
++	0xAC, 0x5C, 0x12, 0x0B, 0xD1, 0x05, 0x5E, 0x02,
++/*1530*/0x14, 0xCF, 0xAB, 0x5D, 0xAA, 0x5C, 0xAD, 0x5B,
++	0xAC, 0x5A, 0xAF, 0x59, 0xAE, 0x58, 0x02, 0x1B,
++/*1540*/0xFB, 0x8C, 0x5C, 0x8D, 0x5D, 0x8A, 0x5E, 0x8B,
++	0x5F, 0x75, 0x60, 0x01, 0xE4, 0xF5, 0x61, 0xF5,
++/*1550*/0x62, 0xF5, 0x63, 0x12, 0x1E, 0xA5, 0x8F, 0x60,
++	0xD3, 0xE5, 0x60, 0x95, 0x5D, 0xE5, 0x5C, 0x12,
++/*1560*/0x07, 0x6B, 0x50, 0x61, 0xE5, 0x5F, 0x45, 0x5E,
++	0x70, 0x27, 0x12, 0x07, 0x2A, 0x75, 0x83, 0xB6,
++/*1570*/0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xB8,
++	0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBA,
++/*1580*/0xE5, 0x60, 0xF0, 0xAF, 0x61, 0x7E, 0x00, 0xE5,
++	0x62, 0x12, 0x08, 0x7A, 0x12, 0x0A, 0xFF, 0x80,
++/*1590*/0x19, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE5,
++	0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0x8E, 0xE4,
++/*15A0*/0x12, 0x07, 0x29, 0x74, 0x01, 0x12, 0x07, 0x29,
++	0xE4, 0xF0, 0xAF, 0x63, 0x7E, 0x00, 0xAD, 0x5F,
++/*15B0*/0xAC, 0x5E, 0x12, 0x04, 0x44, 0xAF, 0x60, 0x7E,
++	0x00, 0xAD, 0x5F, 0xAC, 0x5E, 0x12, 0x12, 0x8B,
++/*15C0*/0x05, 0x60, 0x02, 0x15, 0x58, 0x22, 0x90, 0x11,
++	0x4D, 0xE4, 0x93, 0x90, 0x07, 0x2E, 0xF0, 0x12,
++/*15D0*/0x08, 0x1F, 0x75, 0x83, 0xAE, 0xE0, 0x54, 0x1A,
++	0xF5, 0x34, 0x70, 0x67, 0xEF, 0x44, 0x07, 0xF5,
++/*15E0*/0x82, 0x75, 0x83, 0xCE, 0xE0, 0xFF, 0x13, 0x13,
++	0x13, 0x54, 0x07, 0xF5, 0x36, 0x54, 0x0F, 0xD3,
++/*15F0*/0x94, 0x00, 0x40, 0x06, 0x12, 0x14, 0x2D, 0x12,
++	0x1B, 0xA9, 0xE5, 0x36, 0x54, 0x0F, 0x24, 0xFE,
++/*1600*/0x60, 0x0C, 0x14, 0x60, 0x0C, 0x14, 0x60, 0x19,
++	0x24, 0x03, 0x70, 0x37, 0x80, 0x10, 0x02, 0x1E,
++/*1610*/0x91, 0x12, 0x1E, 0x91, 0x12, 0x07, 0x2A, 0x75,
++	0x83, 0xCE, 0xE0, 0x54, 0xEF, 0xF0, 0x02, 0x1D,
++/*1620*/0xAE, 0x12, 0x10, 0x14, 0xE4, 0xF5, 0x55, 0x12,
++	0x1D, 0x85, 0x05, 0x55, 0xE5, 0x55, 0xC3, 0x94,
++/*1630*/0x05, 0x40, 0xF4, 0x12, 0x07, 0x2A, 0x75, 0x83,
++	0xCE, 0xE0, 0x54, 0xC7, 0x12, 0x07, 0x29, 0xE0,
++/*1640*/0x44, 0x08, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
++	0x59, 0xAF, 0x08, 0xEF, 0x44, 0x07, 0xF5, 0x82,
++/*1650*/0x75, 0x83, 0xD0, 0xE0, 0xFD, 0xC4, 0x54, 0x0F,
++	0xF5, 0x5A, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0x75,
++/*1660*/0x83, 0x80, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x21,
++	0x75, 0x83, 0x82, 0xE5, 0x45, 0xF0, 0xEF, 0x44,
++/*1670*/0x07, 0xF5, 0x82, 0x75, 0x83, 0x8A, 0x74, 0xFF,
++	0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x07, 0x2A, 0x75,
++/*1680*/0x83, 0xBC, 0xE0, 0x54, 0xEF, 0x12, 0x07, 0x29,
++	0x75, 0x83, 0xBE, 0xE0, 0x54, 0xEF, 0x12, 0x07,
++/*1690*/0x29, 0x75, 0x83, 0xC0, 0xE0, 0x54, 0xEF, 0x12,
++	0x07, 0x29, 0x75, 0x83, 0xBC, 0xE0, 0x44, 0x10,
++/*16A0*/0x12, 0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x44,
++	0x10, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0,
++/*16B0*/0x44, 0x10, 0xF0, 0xAF, 0x58, 0xE5, 0x59, 0x12,
++	0x08, 0x78, 0x02, 0x0A, 0xFF, 0xE4, 0xF5, 0x58,
++/*16C0*/0x7D, 0x01, 0xF5, 0x59, 0xAF, 0x35, 0xFE, 0xFC,
++	0x12, 0x09, 0x15, 0x12, 0x07, 0x2A, 0x75, 0x83,
++/*16D0*/0xB6, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++	0xB8, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*16E0*/0xBA, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++	0xBC, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*16F0*/0xBE, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++	0xC0, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*1700*/0x90, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2,
++	0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4,
++/*1710*/0x12, 0x07, 0x29, 0x75, 0x83, 0x92, 0xE4, 0x12,
++	0x07, 0x29, 0x75, 0x83, 0xC6, 0xE4, 0x12, 0x07,
++/*1720*/0x29, 0x75, 0x83, 0xC8, 0xE4, 0xF0, 0xAF, 0x58,
++	0xFE, 0xE5, 0x59, 0x12, 0x08, 0x7A, 0x02, 0x0A,
++/*1730*/0xFF, 0xE5, 0xE2, 0x30, 0xE4, 0x6C, 0xE5, 0xE7,
++	0x54, 0xC0, 0x64, 0x40, 0x70, 0x64, 0xE5, 0x09,
++/*1740*/0xC4, 0x54, 0x30, 0xFE, 0xE5, 0x08, 0x25, 0xE0,
++	0x25, 0xE0, 0x54, 0xC0, 0x4E, 0xFE, 0xEF, 0x54,
++/*1750*/0x3F, 0x4E, 0xFD, 0xE5, 0x2B, 0xAE, 0x2A, 0x78,
++	0x02, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9,
++/*1760*/0xF5, 0x82, 0x8E, 0x83, 0xED, 0xF0, 0xE5, 0x2B,
++	0xAE, 0x2A, 0x78, 0x02, 0xC3, 0x33, 0xCE, 0x33,
++/*1770*/0xCE, 0xD8, 0xF9, 0xFF, 0xF5, 0x82, 0x8E, 0x83,
++	0xA3, 0xE5, 0xFE, 0xF0, 0x8F, 0x82, 0x8E, 0x83,
++/*1780*/0xA3, 0xA3, 0xE5, 0xFD, 0xF0, 0x8F, 0x82, 0x8E,
++	0x83, 0xA3, 0xA3, 0xA3, 0xE5, 0xFC, 0xF0, 0xC3,
++/*1790*/0xE5, 0x2B, 0x94, 0xFA, 0xE5, 0x2A, 0x94, 0x00,
++	0x50, 0x08, 0x05, 0x2B, 0xE5, 0x2B, 0x70, 0x02,
++/*17A0*/0x05, 0x2A, 0x22, 0xE4, 0xFF, 0xE4, 0xF5, 0x58,
++	0xF5, 0x56, 0xF5, 0x57, 0x74, 0x82, 0xFC, 0x12,
++/*17B0*/0x0E, 0x04, 0x8C, 0x83, 0xE0, 0xF5, 0x10, 0x54,
++	0x7F, 0xF0, 0xE5, 0x10, 0x44, 0x80, 0x12, 0x0E,
++/*17C0*/0x98, 0xED, 0xF0, 0x7E, 0x0A, 0x12, 0x0E, 0x04,
++	0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0, 0x26, 0xDE,
++/*17D0*/0xF4, 0x05, 0x57, 0xE5, 0x57, 0x70, 0x02, 0x05,
++	0x56, 0xE5, 0x14, 0x24, 0x01, 0xFD, 0xE4, 0x33,
++/*17E0*/0xFC, 0xD3, 0xE5, 0x57, 0x9D, 0xE5, 0x56, 0x9C,
++	0x40, 0xD9, 0xE5, 0x0A, 0x94, 0x20, 0x50, 0x02,
++/*17F0*/0x05, 0x0A, 0x43, 0xE1, 0x08, 0xC2, 0x31, 0x12,
++	0x0E, 0x04, 0x75, 0x83, 0xA6, 0xE0, 0x55, 0x12,
++/*1800*/0x65, 0x12, 0x70, 0x03, 0xD2, 0x31, 0x22, 0xC2,
++	0x31, 0x22, 0x90, 0x07, 0x26, 0xE0, 0xFA, 0xA3,
++/*1810*/0xE0, 0xF5, 0x82, 0x8A, 0x83, 0xE0, 0xF5, 0x41,
++	0xE5, 0x39, 0xC3, 0x95, 0x41, 0x40, 0x26, 0xE5,
++/*1820*/0x39, 0x95, 0x41, 0xC3, 0x9F, 0xEE, 0x12, 0x07,
++	0x6B, 0x40, 0x04, 0x7C, 0x01, 0x80, 0x02, 0x7C,
++/*1830*/0x00, 0xE5, 0x41, 0x64, 0x3F, 0x60, 0x04, 0x7B,
++	0x01, 0x80, 0x02, 0x7B, 0x00, 0xEC, 0x5B, 0x60,
++/*1840*/0x29, 0x05, 0x41, 0x80, 0x28, 0xC3, 0xE5, 0x41,
++	0x95, 0x39, 0xC3, 0x9F, 0xEE, 0x12, 0x07, 0x6B,
++/*1850*/0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00,
++	0xE5, 0x41, 0x60, 0x04, 0x7E, 0x01, 0x80, 0x02,
++/*1860*/0x7E, 0x00, 0xEF, 0x5E, 0x60, 0x04, 0x15, 0x41,
++	0x80, 0x03, 0x85, 0x39, 0x41, 0x85, 0x3A, 0x40,
++/*1870*/0x22, 0xE5, 0xE2, 0x30, 0xE4, 0x60, 0xE5, 0xE1,
++	0x30, 0xE2, 0x5B, 0xE5, 0x09, 0x70, 0x04, 0x7F,
++/*1880*/0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x08, 0x70,
++	0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
++/*1890*/0x5F, 0x60, 0x43, 0x53, 0xF9, 0xF8, 0xE5, 0xE2,
++	0x30, 0xE4, 0x3B, 0xE5, 0xE1, 0x30, 0xE2, 0x2E,
++/*18A0*/0x43, 0xFA, 0x02, 0x53, 0xFA, 0xFB, 0xE4, 0xF5,
++	0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0xE5,
++/*18B0*/0xE1, 0x30, 0xE2, 0xE7, 0x90, 0x94, 0x70, 0xE0,
++	0x65, 0x10, 0x60, 0x03, 0x43, 0xFA, 0x04, 0x05,
++/*18C0*/0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0x70,
++	0xE6, 0x12, 0x00, 0x06, 0x80, 0xE1, 0x53, 0xFA,
++/*18D0*/0xFD, 0x53, 0xFA, 0xFB, 0x80, 0xC0, 0x22, 0x8F,
++	0x54, 0x12, 0x00, 0x06, 0xE5, 0xE1, 0x30, 0xE0,
++/*18E0*/0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5,
++	0x7E, 0xD3, 0x94, 0x05, 0x40, 0x04, 0x7E, 0x01,
++/*18F0*/0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60, 0x3D,
++	0x85, 0x54, 0x11, 0xE5, 0xE2, 0x20, 0xE1, 0x32,
++/*1900*/0x74, 0xCE, 0x12, 0x1A, 0x05, 0x30, 0xE7, 0x04,
++	0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0x8F, 0x82,
++/*1910*/0x8E, 0x83, 0xE0, 0x30, 0xE6, 0x04, 0x7F, 0x01,
++	0x80, 0x02, 0x7F, 0x00, 0xEF, 0x5D, 0x70, 0x15,
++/*1920*/0x12, 0x15, 0xC6, 0x74, 0xCE, 0x12, 0x1A, 0x05,
++	0x30, 0xE6, 0x07, 0xE0, 0x44, 0x80, 0xF0, 0x43,
++/*1930*/0xF9, 0x80, 0x12, 0x18, 0x71, 0x22, 0x12, 0x0E,
++	0x44, 0xE5, 0x16, 0x25, 0xE0, 0x25, 0xE0, 0x24,
++/*1940*/0xB0, 0xF5, 0x82, 0xE4, 0x34, 0x1A, 0xF5, 0x83,
++	0xE4, 0x93, 0xF5, 0x0F, 0xE5, 0x16, 0x25, 0xE0,
++/*1950*/0x25, 0xE0, 0x24, 0xB1, 0xF5, 0x82, 0xE4, 0x34,
++	0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0E, 0x12,
++/*1960*/0x0E, 0x65, 0xF5, 0x10, 0xE5, 0x0F, 0x54, 0xF0,
++	0x12, 0x0E, 0x17, 0x75, 0x83, 0x8C, 0xEF, 0xF0,
++/*1970*/0xE5, 0x0F, 0x30, 0xE0, 0x0C, 0x12, 0x0E, 0x04,
++	0x75, 0x83, 0x86, 0xE0, 0x44, 0x40, 0xF0, 0x80,
++/*1980*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x86, 0xE0,
++	0x54, 0xBF, 0xF0, 0x12, 0x0E, 0x91, 0x75, 0x83,
++/*1990*/0x82, 0xE5, 0x0E, 0xF0, 0x22, 0x7F, 0x05, 0x12,
++	0x17, 0x31, 0x12, 0x0E, 0x04, 0x12, 0x0E, 0x33,
++/*19A0*/0x74, 0x02, 0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E,
++	0x04, 0x12, 0x0E, 0x0B, 0xEF, 0xF0, 0x75, 0x15,
++/*19B0*/0x70, 0x12, 0x0F, 0xF7, 0x20, 0x34, 0x05, 0x75,
++	0x15, 0x10, 0x80, 0x03, 0x75, 0x15, 0x50, 0x12,
++/*19C0*/0x0F, 0xF7, 0x20, 0x34, 0x04, 0x74, 0x10, 0x80,
++	0x02, 0x74, 0xF0, 0x25, 0x15, 0xF5, 0x15, 0x12,
++/*19D0*/0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x20,
++	0x34, 0x17, 0xE5, 0x15, 0x64, 0x30, 0x60, 0x0C,
++/*19E0*/0x74, 0x10, 0x25, 0x15, 0xF5, 0x15, 0xB4, 0x80,
++	0x03, 0xE4, 0xF5, 0x15, 0x12, 0x0E, 0x21, 0xEF,
++/*19F0*/0xF0, 0x22, 0xF0, 0xE5, 0x0B, 0x25, 0xE0, 0x25,
++	0xE0, 0x24, 0x82, 0xF5, 0x82, 0xE4, 0x34, 0x07,
++/*1A00*/0xF5, 0x83, 0x22, 0x74, 0x88, 0xFE, 0xE5, 0x08,
++	0x44, 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0,
++/*1A10*/0x22, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
++	0x22, 0xF0, 0xE0, 0x54, 0xC0, 0x8F, 0x82, 0x8E,
++/*1A20*/0x83, 0xF0, 0x22, 0xEF, 0x44, 0x07, 0xF5, 0x82,
++	0x75, 0x83, 0x86, 0xE0, 0x54, 0x10, 0xD3, 0x94,
++/*1A30*/0x00, 0x22, 0xF0, 0x90, 0x07, 0x15, 0xE0, 0x04,
++	0xF0, 0x22, 0x44, 0x06, 0xF5, 0x82, 0x75, 0x83,
++/*1A40*/0x9E, 0xE0, 0x22, 0xFE, 0xEF, 0x44, 0x07, 0xF5,
++	0x82, 0x8E, 0x83, 0xE0, 0x22, 0xE4, 0x90, 0x07,
++/*1A50*/0x2A, 0xF0, 0xA3, 0xF0, 0x12, 0x07, 0x2A, 0x75,
++	0x83, 0x82, 0xE0, 0x54, 0x7F, 0x12, 0x07, 0x29,
++/*1A60*/0xE0, 0x44, 0x80, 0xF0, 0x12, 0x10, 0xFC, 0x12,
++	0x08, 0x1F, 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0,
++/*1A70*/0x1A, 0x90, 0x07, 0x2B, 0xE0, 0x04, 0xF0, 0x70,
++	0x06, 0x90, 0x07, 0x2A, 0xE0, 0x04, 0xF0, 0x90,
++/*1A80*/0x07, 0x2A, 0xE0, 0xB4, 0x10, 0xE1, 0xA3, 0xE0,
++	0xB4, 0x00, 0xDC, 0xEE, 0x44, 0xA6, 0xFC, 0xEF,
++/*1A90*/0x44, 0x07, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0xF5,
++	0x32, 0xEE, 0x44, 0xA8, 0xFE, 0xEF, 0x44, 0x07,
++/*1AA0*/0xF5, 0x82, 0x8E, 0x83, 0xE0, 0xF5, 0x33, 0x22,
++	0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x90,
++/*1AB0*/0x00, 0x20, 0x0F, 0x92, 0x00, 0x21, 0x0F, 0x94,
++	0x00, 0x22, 0x0F, 0x96, 0x00, 0x23, 0x0F, 0x98,
++/*1AC0*/0x00, 0x24, 0x0F, 0x9A, 0x00, 0x25, 0x0F, 0x9C,
++	0x00, 0x26, 0x0F, 0x9E, 0x00, 0x27, 0x0F, 0xA0,
++/*1AD0*/0x01, 0x20, 0x01, 0xA2, 0x01, 0x21, 0x01, 0xA4,
++	0x01, 0x22, 0x01, 0xA6, 0x01, 0x23, 0x01, 0xA8,
++/*1AE0*/0x01, 0x24, 0x01, 0xAA, 0x01, 0x25, 0x01, 0xAC,
++	0x01, 0x26, 0x01, 0xAE, 0x01, 0x27, 0x01, 0xB0,
++/*1AF0*/0x01, 0x28, 0x01, 0xB4, 0x00, 0x28, 0x0F, 0xB6,
++	0x40, 0x28, 0x0F, 0xB8, 0x61, 0x28, 0x01, 0xCB,
++/*1B00*/0xEF, 0xCB, 0xCA, 0xEE, 0xCA, 0x7F, 0x01, 0xE4,
++	0xFD, 0xEB, 0x4A, 0x70, 0x24, 0xE5, 0x08, 0xF5,
++/*1B10*/0x82, 0x74, 0xB6, 0x12, 0x08, 0x29, 0xE5, 0x08,
++	0xF5, 0x82, 0x74, 0xB8, 0x12, 0x08, 0x29, 0xE5,
++/*1B20*/0x08, 0xF5, 0x82, 0x74, 0xBA, 0x12, 0x08, 0x29,
++	0x7E, 0x00, 0x7C, 0x00, 0x12, 0x0A, 0xFF, 0x80,
++/*1B30*/0x12, 0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE5,
++	0x41, 0xF0, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35,
++/*1B40*/0xE5, 0x40, 0xF0, 0x12, 0x07, 0x2A, 0x75, 0x83,
++	0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74, 0x01, 0x12,
++/*1B50*/0x07, 0x29, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x26,
++	0xF5, 0x27, 0x53, 0xE1, 0xFE, 0xF5, 0x2A, 0x75,
++/*1B60*/0x2B, 0x01, 0xF5, 0x08, 0x7F, 0x01, 0x12, 0x17,
++	0x31, 0x30, 0x30, 0x1C, 0x90, 0x1A, 0xA9, 0xE4,
++/*1B70*/0x93, 0xF5, 0x10, 0x90, 0x1F, 0xF9, 0xE4, 0x93,
++	0xF5, 0x10, 0x90, 0x00, 0x41, 0xE4, 0x93, 0xF5,
++/*1B80*/0x10, 0x90, 0x1E, 0xCA, 0xE4, 0x93, 0xF5, 0x10,
++	0x7F, 0x02, 0x12, 0x17, 0x31, 0x12, 0x0F, 0x54,
++/*1B90*/0x7F, 0x03, 0x12, 0x17, 0x31, 0x12, 0x00, 0x06,
++	0xE5, 0xE2, 0x30, 0xE7, 0x09, 0x12, 0x10, 0x00,
++/*1BA0*/0x30, 0x30, 0x03, 0x12, 0x11, 0x00, 0x02, 0x00,
++	0x47, 0x12, 0x08, 0x1F, 0x75, 0x83, 0xD0, 0xE0,
++/*1BB0*/0xC4, 0x54, 0x0F, 0xFD, 0x75, 0x43, 0x01, 0x75,
++	0x44, 0xFF, 0x12, 0x08, 0xAA, 0x74, 0x04, 0xF0,
++/*1BC0*/0x75, 0x3B, 0x01, 0xED, 0x14, 0x60, 0x0C, 0x14,
++	0x60, 0x0B, 0x14, 0x60, 0x0F, 0x24, 0x03, 0x70,
++/*1BD0*/0x0B, 0x80, 0x09, 0x80, 0x00, 0x12, 0x08, 0xA7,
++	0x04, 0xF0, 0x80, 0x06, 0x12, 0x08, 0xA7, 0x74,
++/*1BE0*/0x04, 0xF0, 0xEE, 0x44, 0x82, 0xFE, 0xEF, 0x44,
++	0x07, 0xF5, 0x82, 0x8E, 0x83, 0xE5, 0x45, 0x12,
++/*1BF0*/0x08, 0xBE, 0x75, 0x83, 0x82, 0xE5, 0x31, 0xF0,
++	0x02, 0x11, 0x4C, 0x8E, 0x60, 0x8F, 0x61, 0x12,
++/*1C00*/0x1E, 0xA5, 0xE4, 0xFF, 0xCE, 0xED, 0xCE, 0xEE,
++	0xD3, 0x95, 0x61, 0xE5, 0x60, 0x12, 0x07, 0x6B,
++/*1C10*/0x40, 0x39, 0x74, 0x20, 0x2E, 0xF5, 0x82, 0xE4,
++	0x34, 0x03, 0xF5, 0x83, 0xE0, 0x70, 0x03, 0xFF,
++/*1C20*/0x80, 0x26, 0x12, 0x08, 0xE2, 0xFD, 0xC3, 0x9F,
++	0x40, 0x1E, 0xCF, 0xED, 0xCF, 0xEB, 0x4A, 0x70,
++/*1C30*/0x0B, 0x8D, 0x42, 0x12, 0x08, 0xEE, 0xF5, 0x41,
++	0x8E, 0x40, 0x80, 0x0C, 0x12, 0x08, 0xE2, 0xF5,
++/*1C40*/0x38, 0x12, 0x08, 0xEE, 0xF5, 0x39, 0x8E, 0x3A,
++	0x1E, 0x80, 0xBC, 0x22, 0x75, 0x58, 0x01, 0xE5,
++/*1C50*/0x35, 0x70, 0x0C, 0x12, 0x07, 0xCC, 0xE0, 0xF5,
++	0x4A, 0x12, 0x07, 0xD8, 0xE0, 0xF5, 0x4C, 0xE5,
++/*1C60*/0x35, 0xB4, 0x04, 0x0C, 0x12, 0x07, 0xE4, 0xE0,
++	0xF5, 0x4A, 0x12, 0x07, 0xF0, 0xE0, 0xF5, 0x4C,
++/*1C70*/0xE5, 0x35, 0xB4, 0x01, 0x04, 0x7F, 0x01, 0x80,
++	0x02, 0x7F, 0x00, 0xE5, 0x35, 0xB4, 0x02, 0x04,
++/*1C80*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F,
++	0x60, 0x0C, 0x12, 0x07, 0xFC, 0xE0, 0xF5, 0x4A,
++/*1C90*/0x12, 0x08, 0x08, 0xE0, 0xF5, 0x4C, 0x85, 0x41,
++	0x49, 0x85, 0x40, 0x4B, 0x22, 0x75, 0x5B, 0x01,
++/*1CA0*/0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE0, 0x54,
++	0x1F, 0xFF, 0xD3, 0x94, 0x02, 0x50, 0x04, 0x8F,
++/*1CB0*/0x58, 0x80, 0x05, 0xEF, 0x24, 0xFE, 0xF5, 0x58,
++	0xEF, 0xC3, 0x94, 0x18, 0x40, 0x05, 0x75, 0x59,
++/*1CC0*/0x18, 0x80, 0x04, 0xEF, 0x04, 0xF5, 0x59, 0x85,
++	0x43, 0x5A, 0xAF, 0x58, 0x7E, 0x00, 0xAD, 0x59,
++/*1CD0*/0x7C, 0x00, 0xAB, 0x5B, 0x7A, 0x00, 0x12, 0x15,
++	0x41, 0xAF, 0x5A, 0x7E, 0x00, 0x12, 0x18, 0x0A,
++/*1CE0*/0xAF, 0x5B, 0x7E, 0x00, 0x02, 0x1A, 0xFF, 0xE5,
++	0xE2, 0x30, 0xE7, 0x0E, 0x12, 0x10, 0x03, 0xC2,
++/*1CF0*/0x30, 0x30, 0x30, 0x03, 0x12, 0x10, 0xFF, 0x20,
++	0x33, 0x28, 0xE5, 0xE7, 0x30, 0xE7, 0x05, 0x12,
++/*1D00*/0x0E, 0xA2, 0x80, 0x0D, 0xE5, 0xFE, 0xC3, 0x94,
++	0x20, 0x50, 0x06, 0x12, 0x0E, 0xA2, 0x43, 0xF9,
++/*1D10*/0x08, 0xE5, 0xF2, 0x30, 0xE7, 0x03, 0x53, 0xF9,
++	0x7F, 0xE5, 0xF1, 0x54, 0x70, 0xD3, 0x94, 0x00,
++/*1D20*/0x50, 0xD8, 0x22, 0x12, 0x0E, 0x04, 0x75, 0x83,
++	0x80, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0x12,
++/*1D30*/0x0D, 0xFD, 0x75, 0x83, 0x84, 0x12, 0x0E, 0x02,
++	0x75, 0x83, 0x86, 0x12, 0x0E, 0x02, 0x75, 0x83,
++/*1D40*/0x8C, 0xE0, 0x54, 0xF3, 0x12, 0x0E, 0x03, 0x75,
++	0x83, 0x8E, 0x12, 0x0E, 0x02, 0x75, 0x83, 0x94,
++/*1D50*/0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x12, 0x07, 0x2A,
++	0x75, 0x83, 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74,
++/*1D60*/0x01, 0x12, 0x07, 0x29, 0xE4, 0x12, 0x08, 0xBE,
++	0x75, 0x83, 0x8C, 0xE0, 0x44, 0x20, 0x12, 0x08,
++/*1D70*/0xBE, 0xE0, 0x54, 0xDF, 0xF0, 0x74, 0x84, 0x85,
++	0x08, 0x82, 0xF5, 0x83, 0xE0, 0x54, 0x7F, 0xF0,
++/*1D80*/0xE0, 0x44, 0x80, 0xF0, 0x22, 0x75, 0x56, 0x01,
++	0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE, 0xFC,
++/*1D90*/0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12, 0x1E,
++	0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E, 0x00,
++/*1DA0*/0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
++	0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0x75, 0x56,
++/*1DB0*/0x01, 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE,
++	0xFC, 0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12,
++/*1DC0*/0x1E, 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E,
++	0x00, 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44,
++/*1DD0*/0xAF, 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xE4,
++	0xF5, 0x16, 0x12, 0x0E, 0x44, 0xFE, 0xE5, 0x08,
++/*1DE0*/0x44, 0x05, 0xFF, 0x12, 0x0E, 0x65, 0x8F, 0x82,
++	0x8E, 0x83, 0xF0, 0x05, 0x16, 0xE5, 0x16, 0xC3,
++/*1DF0*/0x94, 0x14, 0x40, 0xE6, 0xE5, 0x08, 0x12, 0x0E,
++	0x2B, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
++/*1E00*/0x59, 0xF5, 0x5A, 0xFF, 0xFE, 0xAD, 0x58, 0xFC,
++	0x12, 0x09, 0x15, 0x7F, 0x04, 0x7E, 0x00, 0xAD,
++/*1E10*/0x58, 0x7C, 0x00, 0x12, 0x09, 0x15, 0x7F, 0x02,
++	0x7E, 0x00, 0xAD, 0x58, 0x7C, 0x00, 0x02, 0x09,
++/*1E20*/0x15, 0xE5, 0x3C, 0x25, 0x3E, 0xFC, 0xE5, 0x42,
++	0x24, 0x00, 0xFB, 0xE4, 0x33, 0xFA, 0xEC, 0xC3,
++/*1E30*/0x9B, 0xEA, 0x12, 0x07, 0x6B, 0x40, 0x0B, 0x8C,
++	0x42, 0xE5, 0x3D, 0x25, 0x3F, 0xF5, 0x41, 0x8F,
++/*1E40*/0x40, 0x22, 0x12, 0x09, 0x0B, 0x22, 0x74, 0x84,
++	0xF5, 0x18, 0x85, 0x08, 0x19, 0x85, 0x19, 0x82,
++/*1E50*/0x85, 0x18, 0x83, 0xE0, 0x54, 0x7F, 0xF0, 0xE0,
++	0x44, 0x80, 0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22,
++/*1E60*/0xEF, 0x4E, 0x70, 0x0B, 0x12, 0x07, 0x2A, 0x75,
++	0x83, 0xD2, 0xE0, 0x54, 0xDF, 0xF0, 0x22, 0x12,
++/*1E70*/0x07, 0x2A, 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x20,
++	0xF0, 0x22, 0x75, 0x58, 0x01, 0x90, 0x07, 0x26,
++/*1E80*/0x12, 0x07, 0x35, 0xE0, 0x54, 0x3F, 0xF5, 0x41,
++	0x12, 0x07, 0x32, 0xE0, 0x54, 0x3F, 0xF5, 0x40,
++/*1E90*/0x22, 0x75, 0x56, 0x02, 0xE4, 0xF5, 0x57, 0x12,
++	0x1D, 0xFC, 0xAF, 0x57, 0x7E, 0x00, 0xAD, 0x56,
++/*1EA0*/0x7C, 0x00, 0x02, 0x04, 0x44, 0xE4, 0xF5, 0x42,
++	0xF5, 0x41, 0xF5, 0x40, 0xF5, 0x38, 0xF5, 0x39,
++/*1EB0*/0xF5, 0x3A, 0x22, 0xEF, 0x54, 0x07, 0xFF, 0xE5,
++	0xF9, 0x54, 0xF8, 0x4F, 0xF5, 0xF9, 0x22, 0x7F,
++/*1EC0*/0x01, 0xE4, 0xFE, 0x0F, 0x0E, 0xBE, 0xFF, 0xFB,
++	0x22, 0x01, 0x20, 0x00, 0x01, 0x04, 0x20, 0x00,
++/*1ED0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1EE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1EF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F00*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F10*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F20*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F30*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F40*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F50*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F60*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F70*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F80*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F90*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FA0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FB0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FC0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FD0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x81
++};
++
++int ipath_sd7220_ib_load(struct ipath_devdata *dd)
++{
++	return ipath_sd7220_prog_ld(dd, IB_7220_SERDES, ipath_sd7220_ib_img,
++		sizeof(ipath_sd7220_ib_img), 0);
++}
++
++int ipath_sd7220_ib_vfy(struct ipath_devdata *dd)
++{
++	return ipath_sd7220_prog_vfy(dd, IB_7220_SERDES, ipath_sd7220_ib_img,
++		sizeof(ipath_sd7220_ib_img), 0);
++}
+diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c
+new file mode 100644
+index 0000000..1974df7
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_sdma.c
+@@ -0,0 +1,790 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * 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/spinlock.h>
++
++#include "ipath_kernel.h"
++#include "ipath_verbs.h"
++#include "ipath_common.h"
++
++#define SDMA_DESCQ_SZ PAGE_SIZE /* 256 entries per 4KB page */
++
++static void vl15_watchdog_enq(struct ipath_devdata *dd)
++{
++	/* ipath_sdma_lock must already be held */
++	if (atomic_inc_return(&dd->ipath_sdma_vl15_count) == 1) {
++		unsigned long interval = (HZ + 19) / 20;
++		dd->ipath_sdma_vl15_timer.expires = jiffies + interval;
++		add_timer(&dd->ipath_sdma_vl15_timer);
++	}
++}
++
++static void vl15_watchdog_deq(struct ipath_devdata *dd)
++{
++	/* ipath_sdma_lock must already be held */
++	if (atomic_dec_return(&dd->ipath_sdma_vl15_count) != 0) {
++		unsigned long interval = (HZ + 19) / 20;
++		mod_timer(&dd->ipath_sdma_vl15_timer, jiffies + interval);
++	} else {
++		del_timer(&dd->ipath_sdma_vl15_timer);
++	}
++}
++
++static void vl15_watchdog_timeout(unsigned long opaque)
++{
++	struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++
++	if (atomic_read(&dd->ipath_sdma_vl15_count) != 0) {
++		ipath_dbg("vl15 watchdog timeout - clearing\n");
++		ipath_cancel_sends(dd, 1);
++		ipath_hol_down(dd);
++	} else {
++		ipath_dbg("vl15 watchdog timeout - "
++			  "condition already cleared\n");
++	}
++}
++
++static void unmap_desc(struct ipath_devdata *dd, unsigned head)
++{
++	__le64 *descqp = &dd->ipath_sdma_descq[head].qw[0];
++	u64 desc[2];
++	dma_addr_t addr;
++	size_t len;
++
++	desc[0] = le64_to_cpu(descqp[0]);
++	desc[1] = le64_to_cpu(descqp[1]);
++
++	addr = (desc[1] << 32) | (desc[0] >> 32);
++	len = (desc[0] >> 14) & (0x7ffULL << 2);
++	dma_unmap_single(&dd->pcidev->dev, addr, len, DMA_TO_DEVICE);
++}
++
++/*
++ * ipath_sdma_lock should be locked before calling this.
++ */
++int ipath_sdma_make_progress(struct ipath_devdata *dd)
++{
++	struct list_head *lp = NULL;
++	struct ipath_sdma_txreq *txp = NULL;
++	u16 dmahead;
++	u16 start_idx = 0;
++	int progress = 0;
++
++	if (!list_empty(&dd->ipath_sdma_activelist)) {
++		lp = dd->ipath_sdma_activelist.next;
++		txp = list_entry(lp, struct ipath_sdma_txreq, list);
++		start_idx = txp->start_idx;
++	}
++
++	/*
++	 * Read the SDMA head register in order to know that the
++	 * interrupt clear has been written to the chip.
++	 * Otherwise, we may not get an interrupt for the last
++	 * descriptor in the queue.
++	 */
++	dmahead = (u16)ipath_read_kreg32(dd, dd->ipath_kregs->kr_senddmahead);
++	/* sanity check return value for error handling (chip reset, etc.) */
++	if (dmahead >= dd->ipath_sdma_descq_cnt)
++		goto done;
++
++	while (dd->ipath_sdma_descq_head != dmahead) {
++		if (txp && txp->flags & IPATH_SDMA_TXREQ_F_FREEDESC &&
++		    dd->ipath_sdma_descq_head == start_idx) {
++			unmap_desc(dd, dd->ipath_sdma_descq_head);
++			start_idx++;
++			if (start_idx == dd->ipath_sdma_descq_cnt)
++				start_idx = 0;
++		}
++
++		/* increment free count and head */
++		dd->ipath_sdma_descq_removed++;
++		if (++dd->ipath_sdma_descq_head == dd->ipath_sdma_descq_cnt)
++			dd->ipath_sdma_descq_head = 0;
++
++		if (txp && txp->next_descq_idx == dd->ipath_sdma_descq_head) {
++			/* move to notify list */
++			if (txp->flags & IPATH_SDMA_TXREQ_F_VL15)
++				vl15_watchdog_deq(dd);
++			list_move_tail(lp, &dd->ipath_sdma_notifylist);
++			if (!list_empty(&dd->ipath_sdma_activelist)) {
++				lp = dd->ipath_sdma_activelist.next;
++				txp = list_entry(lp, struct ipath_sdma_txreq,
++						 list);
++				start_idx = txp->start_idx;
++			} else {
++				lp = NULL;
++				txp = NULL;
++			}
++		}
++		progress = 1;
++	}
++
++	if (progress)
++		tasklet_hi_schedule(&dd->ipath_sdma_notify_task);
++
++done:
++	return progress;
++}
++
++static void ipath_sdma_notify(struct ipath_devdata *dd, struct list_head *list)
++{
++	struct ipath_sdma_txreq *txp, *txp_next;
++
++	list_for_each_entry_safe(txp, txp_next, list, list) {
++		list_del_init(&txp->list);
++
++		if (txp->callback)
++			(*txp->callback)(txp->callback_cookie,
++					 txp->callback_status);
++	}
++}
++
++static void sdma_notify_taskbody(struct ipath_devdata *dd)
++{
++	unsigned long flags;
++	struct list_head list;
++
++	INIT_LIST_HEAD(&list);
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++	list_splice_init(&dd->ipath_sdma_notifylist, &list);
++
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++	ipath_sdma_notify(dd, &list);
++
++	/*
++	 * The IB verbs layer needs to see the callback before getting
++	 * the call to ipath_ib_piobufavail() because the callback
++	 * handles releasing resources the next send will need.
++	 * Otherwise, we could do these calls in
++	 * ipath_sdma_make_progress().
++	 */
++	ipath_ib_piobufavail(dd->verbs_dev);
++}
++
++static void sdma_notify_task(unsigned long opaque)
++{
++	struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++
++	if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++		sdma_notify_taskbody(dd);
++}
++
++static void dump_sdma_state(struct ipath_devdata *dd)
++{
++	unsigned long reg;
++
++	reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmastatus);
++	ipath_cdbg(VERBOSE, "kr_senddmastatus: 0x%016lx\n", reg);
++
++	reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendctrl);
++	ipath_cdbg(VERBOSE, "kr_sendctrl: 0x%016lx\n", reg);
++
++	reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask0);
++	ipath_cdbg(VERBOSE, "kr_senddmabufmask0: 0x%016lx\n", reg);
++
++	reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask1);
++	ipath_cdbg(VERBOSE, "kr_senddmabufmask1: 0x%016lx\n", reg);
++
++	reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask2);
++	ipath_cdbg(VERBOSE, "kr_senddmabufmask2: 0x%016lx\n", reg);
++
++	reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmatail);
++	ipath_cdbg(VERBOSE, "kr_senddmatail: 0x%016lx\n", reg);
++
++	reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmahead);
++	ipath_cdbg(VERBOSE, "kr_senddmahead: 0x%016lx\n", reg);
++}
++
++static void sdma_abort_task(unsigned long opaque)
++{
++	struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
++	u64 status;
++	unsigned long flags;
++
++	if (test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++		return;
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++	status = dd->ipath_sdma_status & IPATH_SDMA_ABORT_MASK;
++
++	/* nothing to do */
++	if (status == IPATH_SDMA_ABORT_NONE)
++		goto unlock;
++
++	/* ipath_sdma_abort() is done, waiting for interrupt */
++	if (status == IPATH_SDMA_ABORT_DISARMED) {
++		if (jiffies < dd->ipath_sdma_abort_intr_timeout)
++			goto resched_noprint;
++		/* give up, intr got lost somewhere */
++		ipath_dbg("give up waiting for SDMADISABLED intr\n");
++		__set_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status);
++		status = IPATH_SDMA_ABORT_ABORTED;
++	}
++
++	/* everything is stopped, time to clean up and restart */
++	if (status == IPATH_SDMA_ABORT_ABORTED) {
++		struct ipath_sdma_txreq *txp, *txpnext;
++		u64 hwstatus;
++		int notify = 0;
++
++		hwstatus = ipath_read_kreg64(dd,
++				dd->ipath_kregs->kr_senddmastatus);
++
++		if (/* ScoreBoardDrainInProg */
++		    test_bit(63, &hwstatus) ||
++		    /* AbortInProg */
++		    test_bit(62, &hwstatus) ||
++		    /* InternalSDmaEnable */
++		    test_bit(61, &hwstatus) ||
++		    /* ScbEmpty */
++		    !test_bit(30, &hwstatus)) {
++			if (dd->ipath_sdma_reset_wait > 0) {
++				/* not done shutting down sdma */
++				--dd->ipath_sdma_reset_wait;
++				goto resched;
++			}
++			ipath_cdbg(VERBOSE, "gave up waiting for quiescent "
++				"status after SDMA reset, continuing\n");
++			dump_sdma_state(dd);
++		}
++
++		/* dequeue all "sent" requests */
++		list_for_each_entry_safe(txp, txpnext,
++					 &dd->ipath_sdma_activelist, list) {
++			txp->callback_status = IPATH_SDMA_TXREQ_S_ABORTED;
++			if (txp->flags & IPATH_SDMA_TXREQ_F_VL15)
++				vl15_watchdog_deq(dd);
++			list_move_tail(&txp->list, &dd->ipath_sdma_notifylist);
++			notify = 1;
++		}
++		if (notify)
++			tasklet_hi_schedule(&dd->ipath_sdma_notify_task);
++
++		/* reset our notion of head and tail */
++		dd->ipath_sdma_descq_tail = 0;
++		dd->ipath_sdma_descq_head = 0;
++		dd->ipath_sdma_head_dma[0] = 0;
++		dd->ipath_sdma_generation = 0;
++		dd->ipath_sdma_descq_removed = dd->ipath_sdma_descq_added;
++
++		/* Reset SendDmaLenGen */
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen,
++			(u64) dd->ipath_sdma_descq_cnt | (1ULL << 18));
++
++		/* done with sdma state for a bit */
++		spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++		/*
++		 * Don't restart sdma here. Wait until link is up to ACTIVE.
++		 * VL15 MADs used to bring the link up use PIO, and multiple
++		 * link transitions otherwise cause the sdma engine to be
++		 * stopped and started multiple times.
++		 * The disable is done here, including the shadow, so the
++		 * state is kept consistent.
++		 * See ipath_restart_sdma() for the actual starting of sdma.
++		 */
++		spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++		dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE;
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++				 dd->ipath_sendctrl);
++		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++		/* make sure I see next message */
++		dd->ipath_sdma_abort_jiffies = 0;
++
++		goto done;
++	}
++
++resched:
++	/*
++	 * for now, keep spinning
++	 * JAG - this is bad to just have default be a loop without
++	 * state change
++	 */
++	if (jiffies > dd->ipath_sdma_abort_jiffies) {
++		ipath_dbg("looping with status 0x%016llx\n",
++			  dd->ipath_sdma_status);
++		dd->ipath_sdma_abort_jiffies = jiffies + 5 * HZ;
++	}
++resched_noprint:
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++	if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++		tasklet_hi_schedule(&dd->ipath_sdma_abort_task);
++	return;
++
++unlock:
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++done:
++	return;
++}
++
++/*
++ * This is called from interrupt context.
++ */
++void ipath_sdma_intr(struct ipath_devdata *dd)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++	(void) ipath_sdma_make_progress(dd);
++
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++}
++
++static int alloc_sdma(struct ipath_devdata *dd)
++{
++	int ret = 0;
++
++	/* Allocate memory for SendDMA descriptor FIFO */
++	dd->ipath_sdma_descq = dma_alloc_coherent(&dd->pcidev->dev,
++		SDMA_DESCQ_SZ, &dd->ipath_sdma_descq_phys, GFP_KERNEL);
++
++	if (!dd->ipath_sdma_descq) {
++		ipath_dev_err(dd, "failed to allocate SendDMA descriptor "
++			"FIFO memory\n");
++		ret = -ENOMEM;
++		goto done;
++	}
++
++	dd->ipath_sdma_descq_cnt =
++		SDMA_DESCQ_SZ / sizeof(struct ipath_sdma_desc);
++
++	/* Allocate memory for DMA of head register to memory */
++	dd->ipath_sdma_head_dma = dma_alloc_coherent(&dd->pcidev->dev,
++		PAGE_SIZE, &dd->ipath_sdma_head_phys, GFP_KERNEL);
++	if (!dd->ipath_sdma_head_dma) {
++		ipath_dev_err(dd, "failed to allocate SendDMA head memory\n");
++		ret = -ENOMEM;
++		goto cleanup_descq;
++	}
++	dd->ipath_sdma_head_dma[0] = 0;
++
++	init_timer(&dd->ipath_sdma_vl15_timer);
++	dd->ipath_sdma_vl15_timer.function = vl15_watchdog_timeout;
++	dd->ipath_sdma_vl15_timer.data = (unsigned long)dd;
++	atomic_set(&dd->ipath_sdma_vl15_count, 0);
++
++	goto done;
++
++cleanup_descq:
++	dma_free_coherent(&dd->pcidev->dev, SDMA_DESCQ_SZ,
++		(void *)dd->ipath_sdma_descq, dd->ipath_sdma_descq_phys);
++	dd->ipath_sdma_descq = NULL;
++	dd->ipath_sdma_descq_phys = 0;
++done:
++	return ret;
++}
++
++int setup_sdma(struct ipath_devdata *dd)
++{
++	int ret = 0;
++	unsigned i, n;
++	u64 tmp64;
++	u64 senddmabufmask[3] = { 0 };
++	unsigned long flags;
++
++	ret = alloc_sdma(dd);
++	if (ret)
++		goto done;
++
++	if (!dd->ipath_sdma_descq) {
++		ipath_dev_err(dd, "SendDMA memory not allocated\n");
++		goto done;
++	}
++
++	dd->ipath_sdma_status = 0;
++	dd->ipath_sdma_abort_jiffies = 0;
++	dd->ipath_sdma_generation = 0;
++	dd->ipath_sdma_descq_tail = 0;
++	dd->ipath_sdma_descq_head = 0;
++	dd->ipath_sdma_descq_removed = 0;
++	dd->ipath_sdma_descq_added = 0;
++
++	/* Set SendDmaBase */
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabase,
++			 dd->ipath_sdma_descq_phys);
++	/* Set SendDmaLenGen */
++	tmp64 = dd->ipath_sdma_descq_cnt;
++	tmp64 |= 1<<18; /* enable generation checking */
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen, tmp64);
++	/* Set SendDmaTail */
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail,
++			 dd->ipath_sdma_descq_tail);
++	/* Set SendDmaHeadAddr */
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmaheadaddr,
++			 dd->ipath_sdma_head_phys);
++
++	/* Reserve all the former "kernel" piobufs */
++	n = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - dd->ipath_pioreserved;
++	for (i = dd->ipath_lastport_piobuf; i < n; ++i) {
++		unsigned word = i / 64;
++		unsigned bit = i & 63;
++		BUG_ON(word >= 3);
++		senddmabufmask[word] |= 1ULL << bit;
++	}
++	ipath_chg_pioavailkernel(dd, dd->ipath_lastport_piobuf,
++		n - dd->ipath_lastport_piobuf, 0);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask0,
++			 senddmabufmask[0]);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask1,
++			 senddmabufmask[1]);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask2,
++			 senddmabufmask[2]);
++
++	INIT_LIST_HEAD(&dd->ipath_sdma_activelist);
++	INIT_LIST_HEAD(&dd->ipath_sdma_notifylist);
++
++	tasklet_init(&dd->ipath_sdma_notify_task, sdma_notify_task,
++		     (unsigned long) dd);
++	tasklet_init(&dd->ipath_sdma_abort_task, sdma_abort_task,
++		     (unsigned long) dd);
++
++	/*
++	 * No use to turn on SDMA here, as link is probably not ACTIVE
++	 * Just mark it RUNNING and enable the interrupt, and let the
++	 * ipath_restart_sdma() on link transition to ACTIVE actually
++	 * enable it.
++	 */
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	dd->ipath_sendctrl |= INFINIPATH_S_SDMAINTENABLE;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	__set_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++done:
++	return ret;
++}
++
++void teardown_sdma(struct ipath_devdata *dd)
++{
++	struct ipath_sdma_txreq *txp, *txpnext;
++	unsigned long flags;
++	dma_addr_t sdma_head_phys = 0;
++	dma_addr_t sdma_descq_phys = 0;
++	void *sdma_descq = NULL;
++	void *sdma_head_dma = NULL;
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++	__clear_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status);
++	__set_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status);
++	__set_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status);
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++	tasklet_kill(&dd->ipath_sdma_abort_task);
++	tasklet_kill(&dd->ipath_sdma_notify_task);
++
++	/* turn off sdma */
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++		dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++	/* dequeue all "sent" requests */
++	list_for_each_entry_safe(txp, txpnext, &dd->ipath_sdma_activelist,
++				 list) {
++		txp->callback_status = IPATH_SDMA_TXREQ_S_SHUTDOWN;
++		if (txp->flags & IPATH_SDMA_TXREQ_F_VL15)
++			vl15_watchdog_deq(dd);
++		list_move_tail(&txp->list, &dd->ipath_sdma_notifylist);
++	}
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++	sdma_notify_taskbody(dd);
++
++	del_timer_sync(&dd->ipath_sdma_vl15_timer);
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++	dd->ipath_sdma_abort_jiffies = 0;
++
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabase, 0);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen, 0);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, 0);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmaheadaddr, 0);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask0, 0);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask1, 0);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask2, 0);
++
++	if (dd->ipath_sdma_head_dma) {
++		sdma_head_dma = (void *) dd->ipath_sdma_head_dma;
++		sdma_head_phys = dd->ipath_sdma_head_phys;
++		dd->ipath_sdma_head_dma = NULL;
++		dd->ipath_sdma_head_phys = 0;
++	}
++
++	if (dd->ipath_sdma_descq) {
++		sdma_descq = dd->ipath_sdma_descq;
++		sdma_descq_phys = dd->ipath_sdma_descq_phys;
++		dd->ipath_sdma_descq = NULL;
++		dd->ipath_sdma_descq_phys = 0;
++	}
++
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++	if (sdma_head_dma)
++		dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
++				  sdma_head_dma, sdma_head_phys);
++
++	if (sdma_descq)
++		dma_free_coherent(&dd->pcidev->dev, SDMA_DESCQ_SZ,
++				  sdma_descq, sdma_descq_phys);
++}
++
++/*
++ * [Re]start SDMA, if we use it, and it's not already OK.
++ * This is called on transition to link ACTIVE, either the first or
++ * subsequent times.
++ */
++void ipath_restart_sdma(struct ipath_devdata *dd)
++{
++	unsigned long flags;
++	int needed = 1;
++
++	if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA))
++		goto bail;
++
++	/*
++	 * First, make sure we should, which is to say,
++	 * check that we are "RUNNING" (not in teardown)
++	 * and not "SHUTDOWN"
++	 */
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++	if (!test_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status)
++		|| test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++			needed = 0;
++	else {
++		__clear_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status);
++		__clear_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status);
++		__clear_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status);
++	}
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++	if (!needed) {
++		ipath_dbg("invalid attempt to restart SDMA, status 0x%016llx\n",
++			dd->ipath_sdma_status);
++		goto bail;
++	}
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	/*
++	 * First clear, just to be safe. Enable is only done
++	 * in chip on 0->1 transition
++	 */
++	dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	dd->ipath_sendctrl |= INFINIPATH_S_SDMAENABLE;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++bail:
++	return;
++}
++
++static inline void make_sdma_desc(struct ipath_devdata *dd,
++	u64 *sdmadesc, u64 addr, u64 dwlen, u64 dwoffset)
++{
++	WARN_ON(addr & 3);
++	/* SDmaPhyAddr[47:32] */
++	sdmadesc[1] = addr >> 32;
++	/* SDmaPhyAddr[31:0] */
++	sdmadesc[0] = (addr & 0xfffffffcULL) << 32;
++	/* SDmaGeneration[1:0] */
++	sdmadesc[0] |= (dd->ipath_sdma_generation & 3ULL) << 30;
++	/* SDmaDwordCount[10:0] */
++	sdmadesc[0] |= (dwlen & 0x7ffULL) << 16;
++	/* SDmaBufOffset[12:2] */
++	sdmadesc[0] |= dwoffset & 0x7ffULL;
++}
++
++/*
++ * This function queues one IB packet onto the send DMA queue per call.
++ * The caller is responsible for checking:
++ * 1) The number of send DMA descriptor entries is less than the size of
++ *    the descriptor queue.
++ * 2) The IB SGE addresses and lengths are 32-bit aligned
++ *    (except possibly the last SGE's length)
++ * 3) The SGE addresses are suitable for passing to dma_map_single().
++ */
++int ipath_sdma_verbs_send(struct ipath_devdata *dd,
++	struct ipath_sge_state *ss, u32 dwords,
++	struct ipath_verbs_txreq *tx)
++{
++
++	unsigned long flags;
++	struct ipath_sge *sge;
++	int ret = 0;
++	u16 tail;
++	__le64 *descqp;
++	u64 sdmadesc[2];
++	u32 dwoffset;
++	dma_addr_t addr;
++
++	if ((tx->map_len + (dwords<<2)) > dd->ipath_ibmaxlen) {
++		ipath_dbg("packet size %X > ibmax %X, fail\n",
++			tx->map_len + (dwords<<2), dd->ipath_ibmaxlen);
++		ret = -EMSGSIZE;
++		goto fail;
++	}
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++retry:
++	if (unlikely(test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status))) {
++		ret = -EBUSY;
++		goto unlock;
++	}
++
++	if (tx->txreq.sg_count > ipath_sdma_descq_freecnt(dd)) {
++		if (ipath_sdma_make_progress(dd))
++			goto retry;
++		ret = -ENOBUFS;
++		goto unlock;
++	}
++
++	addr = dma_map_single(&dd->pcidev->dev, tx->txreq.map_addr,
++			      tx->map_len, DMA_TO_DEVICE);
++	if (dma_mapping_error(addr)) {
++		ret = -EIO;
++		goto unlock;
++	}
++
++	dwoffset = tx->map_len >> 2;
++	make_sdma_desc(dd, sdmadesc, (u64) addr, dwoffset, 0);
++
++	/* SDmaFirstDesc */
++	sdmadesc[0] |= 1ULL << 12;
++	if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF)
++		sdmadesc[0] |= 1ULL << 14;	/* SDmaUseLargeBuf */
++
++	/* write to the descq */
++	tail = dd->ipath_sdma_descq_tail;
++	descqp = &dd->ipath_sdma_descq[tail].qw[0];
++	*descqp++ = cpu_to_le64(sdmadesc[0]);
++	*descqp++ = cpu_to_le64(sdmadesc[1]);
++
++	if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEDESC)
++		tx->txreq.start_idx = tail;
++
++	/* increment the tail */
++	if (++tail == dd->ipath_sdma_descq_cnt) {
++		tail = 0;
++		descqp = &dd->ipath_sdma_descq[0].qw[0];
++		++dd->ipath_sdma_generation;
++	}
++
++	sge = &ss->sge;
++	while (dwords) {
++		u32 dw;
++		u32 len;
++
++		len = dwords << 2;
++		if (len > sge->length)
++			len = sge->length;
++		if (len > sge->sge_length)
++			len = sge->sge_length;
++		BUG_ON(len == 0);
++		dw = (len + 3) >> 2;
++		addr = dma_map_single(&dd->pcidev->dev, sge->vaddr, dw << 2,
++				      DMA_TO_DEVICE);
++		make_sdma_desc(dd, sdmadesc, (u64) addr, dw, dwoffset);
++		/* SDmaUseLargeBuf has to be set in every descriptor */
++		if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF)
++			sdmadesc[0] |= 1ULL << 14;
++		/* write to the descq */
++		*descqp++ = cpu_to_le64(sdmadesc[0]);
++		*descqp++ = cpu_to_le64(sdmadesc[1]);
++
++		/* increment the tail */
++		if (++tail == dd->ipath_sdma_descq_cnt) {
++			tail = 0;
++			descqp = &dd->ipath_sdma_descq[0].qw[0];
++			++dd->ipath_sdma_generation;
++		}
++		sge->vaddr += len;
++		sge->length -= len;
++		sge->sge_length -= len;
++		if (sge->sge_length == 0) {
++			if (--ss->num_sge)
++				*sge = *ss->sg_list++;
++		} else if (sge->length == 0 && sge->mr != NULL) {
++			if (++sge->n >= IPATH_SEGSZ) {
++				if (++sge->m >= sge->mr->mapsz)
++					break;
++				sge->n = 0;
++			}
++			sge->vaddr =
++				sge->mr->map[sge->m]->segs[sge->n].vaddr;
++			sge->length =
++				sge->mr->map[sge->m]->segs[sge->n].length;
++		}
++
++		dwoffset += dw;
++		dwords -= dw;
++	}
++
++	if (!tail)
++		descqp = &dd->ipath_sdma_descq[dd->ipath_sdma_descq_cnt].qw[0];
++	descqp -= 2;
++	/* SDmaLastDesc */
++	descqp[0] |= __constant_cpu_to_le64(1ULL << 11);
++	if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_INTREQ) {
++		/* SDmaIntReq */
++		descqp[0] |= __constant_cpu_to_le64(1ULL << 15);
++	}
++
++	/* Commit writes to memory and advance the tail on the chip */
++	wmb();
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, tail);
++
++	tx->txreq.next_descq_idx = tail;
++	tx->txreq.callback_status = IPATH_SDMA_TXREQ_S_OK;
++	dd->ipath_sdma_descq_tail = tail;
++	dd->ipath_sdma_descq_added += tx->txreq.sg_count;
++	list_add_tail(&tx->txreq.list, &dd->ipath_sdma_activelist);
++	if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_VL15)
++		vl15_watchdog_enq(dd);
++
++unlock:
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++fail:
++	return ret;
++}
+diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
+index f772102..e3d80ca 100644
+--- a/drivers/infiniband/hw/ipath/ipath_srq.c
++++ b/drivers/infiniband/hw/ipath/ipath_srq.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -245,7 +245,8 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ 						 sizeof(offset_addr));
+ 			if (ret)
+ 				goto bail_free;
+-			udata->outbuf = (void __user *) offset_addr;
++			udata->outbuf =
++				(void __user *) (unsigned long) offset_addr;
+ 			ret = ib_copy_to_udata(udata, &offset,
+ 					       sizeof(offset));
+ 			if (ret)
+diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
+index d2725cd..c8e3d65 100644
+--- a/drivers/infiniband/hw/ipath/ipath_stats.c
++++ b/drivers/infiniband/hw/ipath/ipath_stats.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -136,6 +136,7 @@ static void ipath_qcheck(struct ipath_devdata *dd)
+ 	struct ipath_portdata *pd = dd->ipath_pd[0];
+ 	size_t blen = 0;
+ 	char buf[128];
++	u32 hdrqtail;
+ 
+ 	*buf = 0;
+ 	if (pd->port_hdrqfull != dd->ipath_p0_hdrqfull) {
+@@ -174,17 +175,18 @@ static void ipath_qcheck(struct ipath_devdata *dd)
+ 	if (blen)
+ 		ipath_dbg("%s\n", buf);
+ 
+-	if (pd->port_head != (u32)
+-	    le64_to_cpu(*dd->ipath_hdrqtailptr)) {
++	hdrqtail = ipath_get_hdrqtail(pd);
++	if (pd->port_head != hdrqtail) {
+ 		if (dd->ipath_lastport0rcv_cnt ==
+ 		    ipath_stats.sps_port0pkts) {
+ 			ipath_cdbg(PKT, "missing rcv interrupts? "
+-				   "port0 hd=%llx tl=%x; port0pkts %llx\n",
+-				   (unsigned long long)
+-				   le64_to_cpu(*dd->ipath_hdrqtailptr),
+-				   pd->port_head,
++				   "port0 hd=%x tl=%x; port0pkts %llx; write"
++				   " hd (w/intr)\n",
++				   pd->port_head, hdrqtail,
+ 				   (unsigned long long)
+ 				   ipath_stats.sps_port0pkts);
++			ipath_write_ureg(dd, ur_rcvhdrhead, hdrqtail |
++				dd->ipath_rhdrhead_intr_off, pd->port_port);
+ 		}
+ 		dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts;
+ 	}
+@@ -290,11 +292,11 @@ void ipath_get_faststats(unsigned long opaque)
+ 	    && time_after(jiffies, dd->ipath_unmasktime)) {
+ 		char ebuf[256];
+ 		int iserr;
+-		iserr = ipath_decode_err(ebuf, sizeof ebuf,
+-			dd->ipath_maskederrs);
++		iserr = ipath_decode_err(dd, ebuf, sizeof ebuf,
++					 dd->ipath_maskederrs);
+ 		if (dd->ipath_maskederrs &
+-				~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
+-				INFINIPATH_E_PKTERRS ))
++		    ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
++		      INFINIPATH_E_PKTERRS))
+ 			ipath_dev_err(dd, "Re-enabling masked errors "
+ 				      "(%s)\n", ebuf);
+ 		else {
+@@ -306,17 +308,18 @@ void ipath_get_faststats(unsigned long opaque)
+ 			 * level.
+ 			 */
+ 			if (iserr)
+-					ipath_dbg("Re-enabling queue full errors (%s)\n",
+-							ebuf);
++				ipath_dbg(
++					"Re-enabling queue full errors (%s)\n",
++					ebuf);
+ 			else
+ 				ipath_cdbg(ERRPKT, "Re-enabling packet"
+-						" problem interrupt (%s)\n", ebuf);
++					" problem interrupt (%s)\n", ebuf);
+ 		}
+ 
+ 		/* re-enable masked errors */
+ 		dd->ipath_errormask |= dd->ipath_maskederrs;
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+-			dd->ipath_errormask);
++				 dd->ipath_errormask);
+ 		dd->ipath_maskederrs = 0;
+ 	}
+ 
+diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
+index 56dfc8a..a6c8efb 100644
+--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
++++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -34,6 +34,7 @@
+ #include <linux/ctype.h>
+ 
+ #include "ipath_kernel.h"
++#include "ipath_verbs.h"
+ #include "ipath_common.h"
+ 
+ /**
+@@ -163,6 +164,15 @@ static ssize_t show_boardversion(struct device *dev,
+ 	return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
+ }
+ 
++static ssize_t show_localbus_info(struct device *dev,
++			       struct device_attribute *attr,
++			       char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	/* The string printed here is already newline-terminated. */
++	return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_lbus_info);
++}
++
+ static ssize_t show_lmc(struct device *dev,
+ 			struct device_attribute *attr,
+ 			char *buf)
+@@ -311,6 +321,8 @@ static ssize_t store_guid(struct device *dev,
+ 
+ 	dd->ipath_guid = new_guid;
+ 	dd->ipath_nguid = 1;
++	if (dd->verbs_dev)
++		dd->verbs_dev->ibdev.node_guid = new_guid;
+ 
+ 	ret = strlen(buf);
+ 	goto bail;
+@@ -919,21 +931,21 @@ static ssize_t store_rx_polinv_enb(struct device *dev,
+ 	u16 val;
+ 
+ 	ret = ipath_parse_ushort(buf, &val);
+-	if (ret < 0 || val > 1)
+-		goto invalid;
++	if (ret >= 0 && val > 1) {
++		ipath_dev_err(dd,
++			"attempt to set invalid Rx Polarity (enable)\n");
++		ret = -EINVAL;
++		goto bail;
++	}
+ 
+ 	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB, val);
+-	if (r < 0) {
++	if (r < 0)
+ 		ret = r;
+-		goto bail;
+-	}
+ 
+-	goto bail;
+-invalid:
+-	ipath_dev_err(dd, "attempt to set invalid Rx Polarity (enable)\n");
+ bail:
+ 	return ret;
+ }
++
+ /*
+  * Get/Set RX lane-reversal enable. 0=no, 1=yes.
+  */
+@@ -988,6 +1000,75 @@ static struct attribute_group driver_attr_group = {
+ 	.attrs = driver_attributes
+ };
+ 
++static ssize_t store_tempsense(struct device *dev,
++			       struct device_attribute *attr,
++			       const char *buf,
++			       size_t count)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret, stat;
++	u16 val;
++
++	ret = ipath_parse_ushort(buf, &val);
++	if (ret <= 0) {
++		ipath_dev_err(dd, "attempt to set invalid tempsense config\n");
++		goto bail;
++	}
++	/* If anything but the highest limit, enable T_CRIT_A "interrupt" */
++	stat = ipath_tempsense_write(dd, 9, (val == 0x7f7f) ? 0x80 : 0);
++	if (stat) {
++		ipath_dev_err(dd, "Unable to set tempsense config\n");
++		ret = -1;
++		goto bail;
++	}
++	stat = ipath_tempsense_write(dd, 0xB, (u8) (val & 0xFF));
++	if (stat) {
++		ipath_dev_err(dd, "Unable to set local Tcrit\n");
++		ret = -1;
++		goto bail;
++	}
++	stat = ipath_tempsense_write(dd, 0xD, (u8) (val >> 8));
++	if (stat) {
++		ipath_dev_err(dd, "Unable to set remote Tcrit\n");
++		ret = -1;
++		goto bail;
++	}
++
++bail:
++	return ret;
++}
++
++/*
++ * dump tempsense regs. in decimal, to ease shell-scripts.
++ */
++static ssize_t show_tempsense(struct device *dev,
++			      struct device_attribute *attr,
++			      char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret;
++	int idx;
++	u8 regvals[8];
++
++	ret = -ENXIO;
++	for (idx = 0; idx < 8; ++idx) {
++		if (idx == 6)
++			continue;
++		ret = ipath_tempsense_read(dd, idx);
++		if (ret < 0)
++			break;
++		regvals[idx] = ret;
++	}
++	if (idx == 8)
++		ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n",
++			*(signed char *)(regvals),
++			*(signed char *)(regvals + 1),
++			regvals[2], regvals[3],
++			*(signed char *)(regvals + 5),
++			*(signed char *)(regvals + 7));
++	return ret;
++}
++
+ struct attribute_group *ipath_driver_attr_groups[] = {
+ 	&driver_attr_group,
+ 	NULL,
+@@ -1011,10 +1092,13 @@ static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
+ static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
+ static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
+ static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
++static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL);
+ static DEVICE_ATTR(jint_max_packets, S_IWUSR | S_IRUGO,
+ 		   show_jint_max_packets, store_jint_max_packets);
+ static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO,
+ 		   show_jint_idle_ticks, store_jint_idle_ticks);
++static DEVICE_ATTR(tempsense, S_IWUSR | S_IRUGO,
++		   show_tempsense, store_tempsense);
+ 
+ static struct attribute *dev_attributes[] = {
+ 	&dev_attr_guid.attr,
+@@ -1034,6 +1118,8 @@ static struct attribute *dev_attributes[] = {
+ 	&dev_attr_rx_pol_inv.attr,
+ 	&dev_attr_led_override.attr,
+ 	&dev_attr_logged_errors.attr,
++	&dev_attr_tempsense.attr,
++	&dev_attr_localbus_info.attr,
+ 	NULL
+ };
+ 
+diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c
+index 2dd8de2..bfe8926 100644
+--- a/drivers/infiniband/hw/ipath/ipath_uc.c
++++ b/drivers/infiniband/hw/ipath/ipath_uc.c
+@@ -94,7 +94,7 @@ int ipath_make_uc_req(struct ipath_qp *qp)
+ 				qp->s_state =
+ 					OP(SEND_ONLY_WITH_IMMEDIATE);
+ 				/* Immediate data comes after the BTH */
+-				ohdr->u.imm_data = wqe->wr.imm_data;
++				ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ 				hwords += 1;
+ 			}
+ 			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+@@ -123,7 +123,7 @@ int ipath_make_uc_req(struct ipath_qp *qp)
+ 				qp->s_state =
+ 					OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+ 				/* Immediate data comes after the RETH */
+-				ohdr->u.rc.imm_data = wqe->wr.imm_data;
++				ohdr->u.rc.imm_data = wqe->wr.ex.imm_data;
+ 				hwords += 1;
+ 				if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ 					bth0 |= 1 << 23;
+@@ -152,7 +152,7 @@ int ipath_make_uc_req(struct ipath_qp *qp)
+ 		else {
+ 			qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+ 			/* Immediate data comes after the BTH */
+-			ohdr->u.imm_data = wqe->wr.imm_data;
++			ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ 			hwords += 1;
+ 		}
+ 		if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+@@ -177,7 +177,7 @@ int ipath_make_uc_req(struct ipath_qp *qp)
+ 			qp->s_state =
+ 				OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+ 			/* Immediate data comes after the BTH */
+-			ohdr->u.imm_data = wqe->wr.imm_data;
++			ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ 			hwords += 1;
+ 			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ 				bth0 |= 1 << 23;
+diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
+index de67eed..8b6a261 100644
+--- a/drivers/infiniband/hw/ipath/ipath_ud.c
++++ b/drivers/infiniband/hw/ipath/ipath_ud.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -95,7 +95,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe)
+ 
+ 	if (swqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
+ 		wc.wc_flags = IB_WC_WITH_IMM;
+-		wc.imm_data = swqe->wr.imm_data;
++		wc.imm_data = swqe->wr.ex.imm_data;
+ 	} else {
+ 		wc.wc_flags = 0;
+ 		wc.imm_data = 0;
+@@ -303,6 +303,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
+ 	qp->s_hdrwords = 7;
+ 	qp->s_cur_size = wqe->length;
+ 	qp->s_cur_sge = &qp->s_sge;
++	qp->s_dmult = ah_attr->static_rate;
+ 	qp->s_wqe = wqe;
+ 	qp->s_sge.sge = wqe->sg_list[0];
+ 	qp->s_sge.sg_list = wqe->sg_list + 1;
+@@ -326,7 +327,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
+ 	}
+ 	if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
+ 		qp->s_hdrwords++;
+-		ohdr->u.ud.imm_data = wqe->wr.imm_data;
++		ohdr->u.ud.imm_data = wqe->wr.ex.imm_data;
+ 		bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
+ 	} else
+ 		bth0 = IB_OPCODE_UD_SEND_ONLY << 24;
+diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.c b/drivers/infiniband/hw/ipath/ipath_user_sdma.c
+new file mode 100644
+index 0000000..86e0169
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.c
+@@ -0,0 +1,879 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * 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/mm.h>
++#include <linux/types.h>
++#include <linux/device.h>
++#include <linux/dmapool.h>
++#include <linux/slab.h>
++#include <linux/list.h>
++#include <linux/highmem.h>
++#include <linux/io.h>
++#include <linux/uio.h>
++#include <linux/rbtree.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++
++#include "ipath_kernel.h"
++#include "ipath_user_sdma.h"
++
++/* minimum size of header */
++#define IPATH_USER_SDMA_MIN_HEADER_LENGTH	64
++/* expected size of headers (for dma_pool) */
++#define IPATH_USER_SDMA_EXP_HEADER_LENGTH	64
++/* length mask in PBC (lower 11 bits) */
++#define IPATH_PBC_LENGTH_MASK			((1 << 11) - 1)
++
++struct ipath_user_sdma_pkt {
++	u8 naddr;		/* dimension of addr (1..3) ... */
++	u32 counter;		/* sdma pkts queued counter for this entry */
++	u64 added;		/* global descq number of entries */
++
++	struct {
++		u32 offset;			/* offset for kvaddr, addr */
++		u32 length;			/* length in page */
++		u8  put_page;			/* should we put_page? */
++		u8  dma_mapped;			/* is page dma_mapped? */
++		struct page *page;		/* may be NULL (coherent mem) */
++		void *kvaddr;			/* FIXME: only for pio hack */
++		dma_addr_t addr;
++	} addr[4];   /* max pages, any more and we coalesce */
++	struct list_head list;	/* list element */
++};
++
++struct ipath_user_sdma_queue {
++	/*
++	 * pkts sent to dma engine are queued on this
++	 * list head.  the type of the elements of this
++	 * list are struct ipath_user_sdma_pkt...
++	 */
++	struct list_head sent;
++
++	/* headers with expected length are allocated from here... */
++	char header_cache_name[64];
++	struct dma_pool *header_cache;
++
++	/* packets are allocated from the slab cache... */
++	char pkt_slab_name[64];
++	struct kmem_cache *pkt_slab;
++
++	/* as packets go on the queued queue, they are counted... */
++	u32 counter;
++	u32 sent_counter;
++
++	/* dma page table */
++	struct rb_root dma_pages_root;
++
++	/* protect everything above... */
++	struct mutex lock;
++};
++
++struct ipath_user_sdma_queue *
++ipath_user_sdma_queue_create(struct device *dev, int unit, int port, int sport)
++{
++	struct ipath_user_sdma_queue *pq =
++		kmalloc(sizeof(struct ipath_user_sdma_queue), GFP_KERNEL);
++
++	if (!pq)
++		goto done;
++
++	pq->counter = 0;
++	pq->sent_counter = 0;
++	INIT_LIST_HEAD(&pq->sent);
++
++	mutex_init(&pq->lock);
++
++	snprintf(pq->pkt_slab_name, sizeof(pq->pkt_slab_name),
++		 "ipath-user-sdma-pkts-%u-%02u.%02u", unit, port, sport);
++	pq->pkt_slab = kmem_cache_create(pq->pkt_slab_name,
++					 sizeof(struct ipath_user_sdma_pkt),
++					 0, 0, NULL);
++
++	if (!pq->pkt_slab)
++		goto err_kfree;
++
++	snprintf(pq->header_cache_name, sizeof(pq->header_cache_name),
++		 "ipath-user-sdma-headers-%u-%02u.%02u", unit, port, sport);
++	pq->header_cache = dma_pool_create(pq->header_cache_name,
++					   dev,
++					   IPATH_USER_SDMA_EXP_HEADER_LENGTH,
++					   4, 0);
++	if (!pq->header_cache)
++		goto err_slab;
++
++	pq->dma_pages_root = RB_ROOT;
++
++	goto done;
++
++err_slab:
++	kmem_cache_destroy(pq->pkt_slab);
++err_kfree:
++	kfree(pq);
++	pq = NULL;
++
++done:
++	return pq;
++}
++
++static void ipath_user_sdma_init_frag(struct ipath_user_sdma_pkt *pkt,
++				      int i, size_t offset, size_t len,
++				      int put_page, int dma_mapped,
++				      struct page *page,
++				      void *kvaddr, dma_addr_t dma_addr)
++{
++	pkt->addr[i].offset = offset;
++	pkt->addr[i].length = len;
++	pkt->addr[i].put_page = put_page;
++	pkt->addr[i].dma_mapped = dma_mapped;
++	pkt->addr[i].page = page;
++	pkt->addr[i].kvaddr = kvaddr;
++	pkt->addr[i].addr = dma_addr;
++}
++
++static void ipath_user_sdma_init_header(struct ipath_user_sdma_pkt *pkt,
++					u32 counter, size_t offset,
++					size_t len, int dma_mapped,
++					struct page *page,
++					void *kvaddr, dma_addr_t dma_addr)
++{
++	pkt->naddr = 1;
++	pkt->counter = counter;
++	ipath_user_sdma_init_frag(pkt, 0, offset, len, 0, dma_mapped, page,
++				  kvaddr, dma_addr);
++}
++
++/* we've too many pages in the iovec, coalesce to a single page */
++static int ipath_user_sdma_coalesce(const struct ipath_devdata *dd,
++				    struct ipath_user_sdma_pkt *pkt,
++				    const struct iovec *iov,
++				    unsigned long niov) {
++	int ret = 0;
++	struct page *page = alloc_page(GFP_KERNEL);
++	void *mpage_save;
++	char *mpage;
++	int i;
++	int len = 0;
++	dma_addr_t dma_addr;
++
++	if (!page) {
++		ret = -ENOMEM;
++		goto done;
++	}
++
++	mpage = kmap(page);
++	mpage_save = mpage;
++	for (i = 0; i < niov; i++) {
++		int cfur;
++
++		cfur = copy_from_user(mpage,
++				      iov[i].iov_base, iov[i].iov_len);
++		if (cfur) {
++			ret = -EFAULT;
++			goto free_unmap;
++		}
++
++		mpage += iov[i].iov_len;
++		len += iov[i].iov_len;
++	}
++
++	dma_addr = dma_map_page(&dd->pcidev->dev, page, 0, len,
++				DMA_TO_DEVICE);
++	if (dma_mapping_error(dma_addr)) {
++		ret = -ENOMEM;
++		goto free_unmap;
++	}
++
++	ipath_user_sdma_init_frag(pkt, 1, 0, len, 0, 1, page, mpage_save,
++				  dma_addr);
++	pkt->naddr = 2;
++
++	goto done;
++
++free_unmap:
++	kunmap(page);
++	__free_page(page);
++done:
++	return ret;
++}
++
++/* how many pages in this iovec element? */
++static int ipath_user_sdma_num_pages(const struct iovec *iov)
++{
++	const unsigned long addr  = (unsigned long) iov->iov_base;
++	const unsigned long  len  = iov->iov_len;
++	const unsigned long spage = addr & PAGE_MASK;
++	const unsigned long epage = (addr + len - 1) & PAGE_MASK;
++
++	return 1 + ((epage - spage) >> PAGE_SHIFT);
++}
++
++/* truncate length to page boundry */
++static int ipath_user_sdma_page_length(unsigned long addr, unsigned long len)
++{
++	const unsigned long offset = addr & ~PAGE_MASK;
++
++	return ((offset + len) > PAGE_SIZE) ? (PAGE_SIZE - offset) : len;
++}
++
++static void ipath_user_sdma_free_pkt_frag(struct device *dev,
++					  struct ipath_user_sdma_queue *pq,
++					  struct ipath_user_sdma_pkt *pkt,
++					  int frag)
++{
++	const int i = frag;
++
++	if (pkt->addr[i].page) {
++		if (pkt->addr[i].dma_mapped)
++			dma_unmap_page(dev,
++				       pkt->addr[i].addr,
++				       pkt->addr[i].length,
++				       DMA_TO_DEVICE);
++
++		if (pkt->addr[i].kvaddr)
++			kunmap(pkt->addr[i].page);
++
++		if (pkt->addr[i].put_page)
++			put_page(pkt->addr[i].page);
++		else
++			__free_page(pkt->addr[i].page);
++	} else if (pkt->addr[i].kvaddr)
++		/* free coherent mem from cache... */
++		dma_pool_free(pq->header_cache,
++			      pkt->addr[i].kvaddr, pkt->addr[i].addr);
++}
++
++/* return number of pages pinned... */
++static int ipath_user_sdma_pin_pages(const struct ipath_devdata *dd,
++				     struct ipath_user_sdma_pkt *pkt,
++				     unsigned long addr, int tlen, int npages)
++{
++	struct page *pages[2];
++	int j;
++	int ret;
++
++	ret = get_user_pages(current, current->mm, addr,
++			     npages, 0, 1, pages, NULL);
++
++	if (ret != npages) {
++		int i;
++
++		for (i = 0; i < ret; i++)
++			put_page(pages[i]);
++
++		ret = -ENOMEM;
++		goto done;
++	}
++
++	for (j = 0; j < npages; j++) {
++		/* map the pages... */
++		const int flen =
++			ipath_user_sdma_page_length(addr, tlen);
++		dma_addr_t dma_addr =
++			dma_map_page(&dd->pcidev->dev,
++				     pages[j], 0, flen, DMA_TO_DEVICE);
++		unsigned long fofs = addr & ~PAGE_MASK;
++
++		if (dma_mapping_error(dma_addr)) {
++			ret = -ENOMEM;
++			goto done;
++		}
++
++		ipath_user_sdma_init_frag(pkt, pkt->naddr, fofs, flen, 1, 1,
++					  pages[j], kmap(pages[j]),
++					  dma_addr);
++
++		pkt->naddr++;
++		addr += flen;
++		tlen -= flen;
++	}
++
++done:
++	return ret;
++}
++
++static int ipath_user_sdma_pin_pkt(const struct ipath_devdata *dd,
++				   struct ipath_user_sdma_queue *pq,
++				   struct ipath_user_sdma_pkt *pkt,
++				   const struct iovec *iov,
++				   unsigned long niov)
++{
++	int ret = 0;
++	unsigned long idx;
++
++	for (idx = 0; idx < niov; idx++) {
++		const int npages = ipath_user_sdma_num_pages(iov + idx);
++		const unsigned long addr = (unsigned long) iov[idx].iov_base;
++
++		ret = ipath_user_sdma_pin_pages(dd, pkt,
++						addr, iov[idx].iov_len,
++						npages);
++		if (ret < 0)
++			goto free_pkt;
++	}
++
++	goto done;
++
++free_pkt:
++	for (idx = 0; idx < pkt->naddr; idx++)
++		ipath_user_sdma_free_pkt_frag(&dd->pcidev->dev, pq, pkt, idx);
++
++done:
++	return ret;
++}
++
++static int ipath_user_sdma_init_payload(const struct ipath_devdata *dd,
++					struct ipath_user_sdma_queue *pq,
++					struct ipath_user_sdma_pkt *pkt,
++					const struct iovec *iov,
++					unsigned long niov, int npages)
++{
++	int ret = 0;
++
++	if (npages >= ARRAY_SIZE(pkt->addr))
++		ret = ipath_user_sdma_coalesce(dd, pkt, iov, niov);
++	else
++		ret = ipath_user_sdma_pin_pkt(dd, pq, pkt, iov, niov);
++
++	return ret;
++}
++
++/* free a packet list -- return counter value of last packet */
++static void ipath_user_sdma_free_pkt_list(struct device *dev,
++					  struct ipath_user_sdma_queue *pq,
++					  struct list_head *list)
++{
++	struct ipath_user_sdma_pkt *pkt, *pkt_next;
++
++	list_for_each_entry_safe(pkt, pkt_next, list, list) {
++		int i;
++
++		for (i = 0; i < pkt->naddr; i++)
++			ipath_user_sdma_free_pkt_frag(dev, pq, pkt, i);
++
++		kmem_cache_free(pq->pkt_slab, pkt);
++	}
++}
++
++/*
++ * copy headers, coalesce etc -- pq->lock must be held
++ *
++ * we queue all the packets to list, returning the
++ * number of bytes total.  list must be empty initially,
++ * as, if there is an error we clean it...
++ */
++static int ipath_user_sdma_queue_pkts(const struct ipath_devdata *dd,
++				      struct ipath_user_sdma_queue *pq,
++				      struct list_head *list,
++				      const struct iovec *iov,
++				      unsigned long niov,
++				      int maxpkts)
++{
++	unsigned long idx = 0;
++	int ret = 0;
++	int npkts = 0;
++	struct page *page = NULL;
++	__le32 *pbc;
++	dma_addr_t dma_addr;
++	struct ipath_user_sdma_pkt *pkt = NULL;
++	size_t len;
++	size_t nw;
++	u32 counter = pq->counter;
++	int dma_mapped = 0;
++
++	while (idx < niov && npkts < maxpkts) {
++		const unsigned long addr = (unsigned long) iov[idx].iov_base;
++		const unsigned long idx_save = idx;
++		unsigned pktnw;
++		unsigned pktnwc;
++		int nfrags = 0;
++		int npages = 0;
++		int cfur;
++
++		dma_mapped = 0;
++		len = iov[idx].iov_len;
++		nw = len >> 2;
++		page = NULL;
++
++		pkt = kmem_cache_alloc(pq->pkt_slab, GFP_KERNEL);
++		if (!pkt) {
++			ret = -ENOMEM;
++			goto free_list;
++		}
++
++		if (len < IPATH_USER_SDMA_MIN_HEADER_LENGTH ||
++		    len > PAGE_SIZE || len & 3 || addr & 3) {
++			ret = -EINVAL;
++			goto free_pkt;
++		}
++
++		if (len == IPATH_USER_SDMA_EXP_HEADER_LENGTH)
++			pbc = dma_pool_alloc(pq->header_cache, GFP_KERNEL,
++					     &dma_addr);
++		else
++			pbc = NULL;
++
++		if (!pbc) {
++			page = alloc_page(GFP_KERNEL);
++			if (!page) {
++				ret = -ENOMEM;
++				goto free_pkt;
++			}
++			pbc = kmap(page);
++		}
++
++		cfur = copy_from_user(pbc, iov[idx].iov_base, len);
++		if (cfur) {
++			ret = -EFAULT;
++			goto free_pbc;
++		}
++
++		/*
++		 * this assignment is a bit strange.  it's because the
++		 * the pbc counts the number of 32 bit words in the full
++		 * packet _except_ the first word of the pbc itself...
++		 */
++		pktnwc = nw - 1;
++
++		/*
++		 * pktnw computation yields the number of 32 bit words
++		 * that the caller has indicated in the PBC.  note that
++		 * this is one less than the total number of words that
++		 * goes to the send DMA engine as the first 32 bit word
++		 * of the PBC itself is not counted.  Armed with this count,
++		 * we can verify that the packet is consistent with the
++		 * iovec lengths.
++		 */
++		pktnw = le32_to_cpu(*pbc) & IPATH_PBC_LENGTH_MASK;
++		if (pktnw < pktnwc || pktnw > pktnwc + (PAGE_SIZE >> 2)) {
++			ret = -EINVAL;
++			goto free_pbc;
++		}
++
++
++		idx++;
++		while (pktnwc < pktnw && idx < niov) {
++			const size_t slen = iov[idx].iov_len;
++			const unsigned long faddr =
++				(unsigned long) iov[idx].iov_base;
++
++			if (slen & 3 || faddr & 3 || !slen ||
++			    slen > PAGE_SIZE) {
++				ret = -EINVAL;
++				goto free_pbc;
++			}
++
++			npages++;
++			if ((faddr & PAGE_MASK) !=
++			    ((faddr + slen - 1) & PAGE_MASK))
++				npages++;
++
++			pktnwc += slen >> 2;
++			idx++;
++			nfrags++;
++		}
++
++		if (pktnwc != pktnw) {
++			ret = -EINVAL;
++			goto free_pbc;
++		}
++
++		if (page) {
++			dma_addr = dma_map_page(&dd->pcidev->dev,
++						page, 0, len, DMA_TO_DEVICE);
++			if (dma_mapping_error(dma_addr)) {
++				ret = -ENOMEM;
++				goto free_pbc;
++			}
++
++			dma_mapped = 1;
++		}
++
++		ipath_user_sdma_init_header(pkt, counter, 0, len, dma_mapped,
++					    page, pbc, dma_addr);
++
++		if (nfrags) {
++			ret = ipath_user_sdma_init_payload(dd, pq, pkt,
++							   iov + idx_save + 1,
++							   nfrags, npages);
++			if (ret < 0)
++				goto free_pbc_dma;
++		}
++
++		counter++;
++		npkts++;
++
++		list_add_tail(&pkt->list, list);
++	}
++
++	ret = idx;
++	goto done;
++
++free_pbc_dma:
++	if (dma_mapped)
++		dma_unmap_page(&dd->pcidev->dev, dma_addr, len, DMA_TO_DEVICE);
++free_pbc:
++	if (page) {
++		kunmap(page);
++		__free_page(page);
++	} else
++		dma_pool_free(pq->header_cache, pbc, dma_addr);
++free_pkt:
++	kmem_cache_free(pq->pkt_slab, pkt);
++free_list:
++	ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, list);
++done:
++	return ret;
++}
++
++static void ipath_user_sdma_set_complete_counter(struct ipath_user_sdma_queue *pq,
++						 u32 c)
++{
++	pq->sent_counter = c;
++}
++
++/* try to clean out queue -- needs pq->lock */
++static int ipath_user_sdma_queue_clean(const struct ipath_devdata *dd,
++				       struct ipath_user_sdma_queue *pq)
++{
++	struct list_head free_list;
++	struct ipath_user_sdma_pkt *pkt;
++	struct ipath_user_sdma_pkt *pkt_prev;
++	int ret = 0;
++
++	INIT_LIST_HEAD(&free_list);
++
++	list_for_each_entry_safe(pkt, pkt_prev, &pq->sent, list) {
++		s64 descd = dd->ipath_sdma_descq_removed - pkt->added;
++
++		if (descd < 0)
++			break;
++
++		list_move_tail(&pkt->list, &free_list);
++
++		/* one more packet cleaned */
++		ret++;
++	}
++
++	if (!list_empty(&free_list)) {
++		u32 counter;
++
++		pkt = list_entry(free_list.prev,
++				 struct ipath_user_sdma_pkt, list);
++		counter = pkt->counter;
++
++		ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &free_list);
++		ipath_user_sdma_set_complete_counter(pq, counter);
++	}
++
++	return ret;
++}
++
++void ipath_user_sdma_queue_destroy(struct ipath_user_sdma_queue *pq)
++{
++	if (!pq)
++		return;
++
++	kmem_cache_destroy(pq->pkt_slab);
++	dma_pool_destroy(pq->header_cache);
++	kfree(pq);
++}
++
++/* clean descriptor queue, returns > 0 if some elements cleaned */
++static int ipath_user_sdma_hwqueue_clean(struct ipath_devdata *dd)
++{
++	int ret;
++	unsigned long flags;
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++	ret = ipath_sdma_make_progress(dd);
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++	return ret;
++}
++
++/* we're in close, drain packets so that we can cleanup successfully... */
++void ipath_user_sdma_queue_drain(struct ipath_devdata *dd,
++				 struct ipath_user_sdma_queue *pq)
++{
++	int i;
++
++	if (!pq)
++		return;
++
++	for (i = 0; i < 100; i++) {
++		mutex_lock(&pq->lock);
++		if (list_empty(&pq->sent)) {
++			mutex_unlock(&pq->lock);
++			break;
++		}
++		ipath_user_sdma_hwqueue_clean(dd);
++		ipath_user_sdma_queue_clean(dd, pq);
++		mutex_unlock(&pq->lock);
++		msleep(10);
++	}
++
++	if (!list_empty(&pq->sent)) {
++		struct list_head free_list;
++
++		printk(KERN_INFO "drain: lists not empty: forcing!\n");
++		INIT_LIST_HEAD(&free_list);
++		mutex_lock(&pq->lock);
++		list_splice_init(&pq->sent, &free_list);
++		ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &free_list);
++		mutex_unlock(&pq->lock);
++	}
++}
++
++static inline __le64 ipath_sdma_make_desc0(struct ipath_devdata *dd,
++					   u64 addr, u64 dwlen, u64 dwoffset)
++{
++	return cpu_to_le64(/* SDmaPhyAddr[31:0] */
++			   ((addr & 0xfffffffcULL) << 32) |
++			   /* SDmaGeneration[1:0] */
++			   ((dd->ipath_sdma_generation & 3ULL) << 30) |
++			   /* SDmaDwordCount[10:0] */
++			   ((dwlen & 0x7ffULL) << 16) |
++			   /* SDmaBufOffset[12:2] */
++			   (dwoffset & 0x7ffULL));
++}
++
++static inline __le64 ipath_sdma_make_first_desc0(__le64 descq)
++{
++	return descq | __constant_cpu_to_le64(1ULL << 12);
++}
++
++static inline __le64 ipath_sdma_make_last_desc0(__le64 descq)
++{
++					      /* last */  /* dma head */
++	return descq | __constant_cpu_to_le64(1ULL << 11 | 1ULL << 13);
++}
++
++static inline __le64 ipath_sdma_make_desc1(u64 addr)
++{
++	/* SDmaPhyAddr[47:32] */
++	return cpu_to_le64(addr >> 32);
++}
++
++static void ipath_user_sdma_send_frag(struct ipath_devdata *dd,
++				      struct ipath_user_sdma_pkt *pkt, int idx,
++				      unsigned ofs, u16 tail)
++{
++	const u64 addr = (u64) pkt->addr[idx].addr +
++		(u64) pkt->addr[idx].offset;
++	const u64 dwlen = (u64) pkt->addr[idx].length / 4;
++	__le64 *descqp;
++	__le64 descq0;
++
++	descqp = &dd->ipath_sdma_descq[tail].qw[0];
++
++	descq0 = ipath_sdma_make_desc0(dd, addr, dwlen, ofs);
++	if (idx == 0)
++		descq0 = ipath_sdma_make_first_desc0(descq0);
++	if (idx == pkt->naddr - 1)
++		descq0 = ipath_sdma_make_last_desc0(descq0);
++
++	descqp[0] = descq0;
++	descqp[1] = ipath_sdma_make_desc1(addr);
++}
++
++/* pq->lock must be held, get packets on the wire... */
++static int ipath_user_sdma_push_pkts(struct ipath_devdata *dd,
++				     struct ipath_user_sdma_queue *pq,
++				     struct list_head *pktlist)
++{
++	int ret = 0;
++	unsigned long flags;
++	u16 tail;
++
++	if (list_empty(pktlist))
++		return 0;
++
++	if (unlikely(!(dd->ipath_flags & IPATH_LINKACTIVE)))
++		return -ECOMM;
++
++	spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++	if (unlikely(dd->ipath_sdma_status & IPATH_SDMA_ABORT_MASK)) {
++		ret = -ECOMM;
++		goto unlock;
++	}
++
++	tail = dd->ipath_sdma_descq_tail;
++	while (!list_empty(pktlist)) {
++		struct ipath_user_sdma_pkt *pkt =
++			list_entry(pktlist->next, struct ipath_user_sdma_pkt,
++				   list);
++		int i;
++		unsigned ofs = 0;
++		u16 dtail = tail;
++
++		if (pkt->naddr > ipath_sdma_descq_freecnt(dd))
++			goto unlock_check_tail;
++
++		for (i = 0; i < pkt->naddr; i++) {
++			ipath_user_sdma_send_frag(dd, pkt, i, ofs, tail);
++			ofs += pkt->addr[i].length >> 2;
++
++			if (++tail == dd->ipath_sdma_descq_cnt) {
++				tail = 0;
++				++dd->ipath_sdma_generation;
++			}
++		}
++
++		if ((ofs<<2) > dd->ipath_ibmaxlen) {
++			ipath_dbg("packet size %X > ibmax %X, fail\n",
++				ofs<<2, dd->ipath_ibmaxlen);
++			ret = -EMSGSIZE;
++			goto unlock;
++		}
++
++		/*
++		 * if the packet is >= 2KB mtu equivalent, we have to use
++		 * the large buffers, and have to mark each descriptor as
++		 * part of a large buffer packet.
++		 */
++		if (ofs >= IPATH_SMALLBUF_DWORDS) {
++			for (i = 0; i < pkt->naddr; i++) {
++				dd->ipath_sdma_descq[dtail].qw[0] |=
++					__constant_cpu_to_le64(1ULL << 14);
++				if (++dtail == dd->ipath_sdma_descq_cnt)
++					dtail = 0;
++			}
++		}
++
++		dd->ipath_sdma_descq_added += pkt->naddr;
++		pkt->added = dd->ipath_sdma_descq_added;
++		list_move_tail(&pkt->list, &pq->sent);
++		ret++;
++	}
++
++unlock_check_tail:
++	/* advance the tail on the chip if necessary */
++	if (dd->ipath_sdma_descq_tail != tail) {
++		wmb();
++		ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, tail);
++		dd->ipath_sdma_descq_tail = tail;
++	}
++
++unlock:
++	spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++	return ret;
++}
++
++int ipath_user_sdma_writev(struct ipath_devdata *dd,
++			   struct ipath_user_sdma_queue *pq,
++			   const struct iovec *iov,
++			   unsigned long dim)
++{
++	int ret = 0;
++	struct list_head list;
++	int npkts = 0;
++
++	INIT_LIST_HEAD(&list);
++
++	mutex_lock(&pq->lock);
++
++	if (dd->ipath_sdma_descq_added != dd->ipath_sdma_descq_removed) {
++		ipath_user_sdma_hwqueue_clean(dd);
++		ipath_user_sdma_queue_clean(dd, pq);
++	}
++
++	while (dim) {
++		const int mxp = 8;
++
++		down_write(&current->mm->mmap_sem);
++		ret = ipath_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp);
++		up_write(&current->mm->mmap_sem);
++
++		if (ret <= 0)
++			goto done_unlock;
++		else {
++			dim -= ret;
++			iov += ret;
++		}
++
++		/* force packets onto the sdma hw queue... */
++		if (!list_empty(&list)) {
++			/*
++			 * lazily clean hw queue.  the 4 is a guess of about
++			 * how many sdma descriptors a packet will take (it
++			 * doesn't have to be perfect).
++			 */
++			if (ipath_sdma_descq_freecnt(dd) < ret * 4) {
++				ipath_user_sdma_hwqueue_clean(dd);
++				ipath_user_sdma_queue_clean(dd, pq);
++			}
++
++			ret = ipath_user_sdma_push_pkts(dd, pq, &list);
++			if (ret < 0)
++				goto done_unlock;
++			else {
++				npkts += ret;
++				pq->counter += ret;
++
++				if (!list_empty(&list))
++					goto done_unlock;
++			}
++		}
++	}
++
++done_unlock:
++	if (!list_empty(&list))
++		ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &list);
++	mutex_unlock(&pq->lock);
++
++	return (ret < 0) ? ret : npkts;
++}
++
++int ipath_user_sdma_make_progress(struct ipath_devdata *dd,
++				  struct ipath_user_sdma_queue *pq)
++{
++	int ret = 0;
++
++	mutex_lock(&pq->lock);
++	ipath_user_sdma_hwqueue_clean(dd);
++	ret = ipath_user_sdma_queue_clean(dd, pq);
++	mutex_unlock(&pq->lock);
++
++	return ret;
++}
++
++u32 ipath_user_sdma_complete_counter(const struct ipath_user_sdma_queue *pq)
++{
++	return pq->sent_counter;
++}
++
++u32 ipath_user_sdma_inflight_counter(struct ipath_user_sdma_queue *pq)
++{
++	return pq->counter;
++}
++
+diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.h b/drivers/infiniband/hw/ipath/ipath_user_sdma.h
+new file mode 100644
+index 0000000..e70946c
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.h
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * 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/device.h>
++
++struct ipath_user_sdma_queue;
++
++struct ipath_user_sdma_queue *
++ipath_user_sdma_queue_create(struct device *dev, int unit, int port, int sport);
++void ipath_user_sdma_queue_destroy(struct ipath_user_sdma_queue *pq);
++
++int ipath_user_sdma_writev(struct ipath_devdata *dd,
++			   struct ipath_user_sdma_queue *pq,
++			   const struct iovec *iov,
++			   unsigned long dim);
++
++int ipath_user_sdma_make_progress(struct ipath_devdata *dd,
++				  struct ipath_user_sdma_queue *pq);
++
++int ipath_user_sdma_pkt_sent(const struct ipath_user_sdma_queue *pq,
++			     u32 counter);
++void ipath_user_sdma_queue_drain(struct ipath_devdata *dd,
++				 struct ipath_user_sdma_queue *pq);
++
++u32 ipath_user_sdma_complete_counter(const struct ipath_user_sdma_queue *pq);
++u32 ipath_user_sdma_inflight_counter(struct ipath_user_sdma_queue *pq);
+diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
+index 32d8f88..e63927c 100644
+--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
++++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -109,7 +109,7 @@ MODULE_PARM_DESC(max_srq_wrs, "Maximum number of SRQ WRs support");
+ 
+ static unsigned int ib_ipath_disable_sma;
+ module_param_named(disable_sma, ib_ipath_disable_sma, uint, S_IWUSR | S_IRUGO);
+-MODULE_PARM_DESC(ib_ipath_disable_sma, "Disable the SMA");
++MODULE_PARM_DESC(disable_sma, "Disable the SMA");
+ 
+ const int ib_ipath_state_ops[IB_QPS_ERR + 1] = {
+ 	[IB_QPS_RESET] = 0,
+@@ -242,6 +242,93 @@ static void ipath_flush_wqe(struct ipath_qp *qp, struct ib_send_wr *wr)
+ 	ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
+ }
+ 
++/*
++ * Count the number of DMA descriptors needed to send length bytes of data.
++ * Don't modify the ipath_sge_state to get the count.
++ * Return zero if any of the segments is not aligned.
++ */
++static u32 ipath_count_sge(struct ipath_sge_state *ss, u32 length)
++{
++	struct ipath_sge *sg_list = ss->sg_list;
++	struct ipath_sge sge = ss->sge;
++	u8 num_sge = ss->num_sge;
++	u32 ndesc = 1;	/* count the header */
++
++	while (length) {
++		u32 len = sge.length;
++
++		if (len > length)
++			len = length;
++		if (len > sge.sge_length)
++			len = sge.sge_length;
++		BUG_ON(len == 0);
++		if (((long) sge.vaddr & (sizeof(u32) - 1)) ||
++		    (len != length && (len & (sizeof(u32) - 1)))) {
++			ndesc = 0;
++			break;
++		}
++		ndesc++;
++		sge.vaddr += len;
++		sge.length -= len;
++		sge.sge_length -= len;
++		if (sge.sge_length == 0) {
++			if (--num_sge)
++				sge = *sg_list++;
++		} else if (sge.length == 0 && sge.mr != NULL) {
++			if (++sge.n >= IPATH_SEGSZ) {
++				if (++sge.m >= sge.mr->mapsz)
++					break;
++				sge.n = 0;
++			}
++			sge.vaddr =
++				sge.mr->map[sge.m]->segs[sge.n].vaddr;
++			sge.length =
++				sge.mr->map[sge.m]->segs[sge.n].length;
++		}
++		length -= len;
++	}
++	return ndesc;
++}
++
++/*
++ * Copy from the SGEs to the data buffer.
++ */
++static void ipath_copy_from_sge(void *data, struct ipath_sge_state *ss,
++				u32 length)
++{
++	struct ipath_sge *sge = &ss->sge;
++
++	while (length) {
++		u32 len = sge->length;
++
++		if (len > length)
++			len = length;
++		if (len > sge->sge_length)
++			len = sge->sge_length;
++		BUG_ON(len == 0);
++		memcpy(data, sge->vaddr, len);
++		sge->vaddr += len;
++		sge->length -= len;
++		sge->sge_length -= len;
++		if (sge->sge_length == 0) {
++			if (--ss->num_sge)
++				*sge = *ss->sg_list++;
++		} else if (sge->length == 0 && sge->mr != NULL) {
++			if (++sge->n >= IPATH_SEGSZ) {
++				if (++sge->m >= sge->mr->mapsz)
++					break;
++				sge->n = 0;
++			}
++			sge->vaddr =
++				sge->mr->map[sge->m]->segs[sge->n].vaddr;
++			sge->length =
++				sge->mr->map[sge->m]->segs[sge->n].length;
++		}
++		data += len;
++		length -= len;
++	}
++}
++
+ /**
+  * ipath_post_one_send - post one RC, UC, or UD send work request
+  * @qp: the QP to post on
+@@ -866,27 +953,257 @@ static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss,
+ 		__raw_writel(last, piobuf);
+ }
+ 
+-static int ipath_verbs_send_pio(struct ipath_qp *qp, u32 *hdr, u32 hdrwords,
++/*
++ * Convert IB rate to delay multiplier.
++ */
++unsigned ipath_ib_rate_to_mult(enum ib_rate rate)
++{
++	switch (rate) {
++	case IB_RATE_2_5_GBPS: return 8;
++	case IB_RATE_5_GBPS:   return 4;
++	case IB_RATE_10_GBPS:  return 2;
++	case IB_RATE_20_GBPS:  return 1;
++	default:	       return 0;
++	}
++}
++
++/*
++ * Convert delay multiplier to IB rate
++ */
++static enum ib_rate ipath_mult_to_ib_rate(unsigned mult)
++{
++	switch (mult) {
++	case 8:  return IB_RATE_2_5_GBPS;
++	case 4:  return IB_RATE_5_GBPS;
++	case 2:  return IB_RATE_10_GBPS;
++	case 1:  return IB_RATE_20_GBPS;
++	default: return IB_RATE_PORT_CURRENT;
++	}
++}
++
++static inline struct ipath_verbs_txreq *get_txreq(struct ipath_ibdev *dev)
++{
++	struct ipath_verbs_txreq *tx = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&dev->pending_lock, flags);
++	if (!list_empty(&dev->txreq_free)) {
++		struct list_head *l = dev->txreq_free.next;
++
++		list_del(l);
++		tx = list_entry(l, struct ipath_verbs_txreq, txreq.list);
++	}
++	spin_unlock_irqrestore(&dev->pending_lock, flags);
++	return tx;
++}
++
++static inline void put_txreq(struct ipath_ibdev *dev,
++			     struct ipath_verbs_txreq *tx)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&dev->pending_lock, flags);
++	list_add(&tx->txreq.list, &dev->txreq_free);
++	spin_unlock_irqrestore(&dev->pending_lock, flags);
++}
++
++static void sdma_complete(void *cookie, int status)
++{
++	struct ipath_verbs_txreq *tx = cookie;
++	struct ipath_qp *qp = tx->qp;
++	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
++
++	/* Generate a completion queue entry if needed */
++	if (qp->ibqp.qp_type != IB_QPT_RC && tx->wqe) {
++		enum ib_wc_status ibs = status == IPATH_SDMA_TXREQ_S_OK ?
++			IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR;
++
++		ipath_send_complete(qp, tx->wqe, ibs);
++	}
++
++	if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF)
++		kfree(tx->txreq.map_addr);
++	put_txreq(dev, tx);
++
++	if (atomic_dec_and_test(&qp->refcount))
++		wake_up(&qp->wait);
++}
++
++/*
++ * Compute the number of clock cycles of delay before sending the next packet.
++ * The multipliers reflect the number of clocks for the fastest rate so
++ * one tick at 4xDDR is 8 ticks at 1xSDR.
++ * If the destination port will take longer to receive a packet than
++ * the outgoing link can send it, we need to delay sending the next packet
++ * by the difference in time it takes the receiver to receive and the sender
++ * to send this packet.
++ * Note that this delay is always correct for UC and RC but not always
++ * optimal for UD. For UD, the destination HCA can be different for each
++ * packet, in which case, we could send packets to a different destination
++ * while "waiting" for the delay. The overhead for doing this without
++ * HW support is more than just paying the cost of delaying some packets
++ * unnecessarily.
++ */
++static inline unsigned ipath_pkt_delay(u32 plen, u8 snd_mult, u8 rcv_mult)
++{
++	return (rcv_mult > snd_mult) ?
++		(plen * (rcv_mult - snd_mult) + 1) >> 1 : 0;
++}
++
++static int ipath_verbs_send_dma(struct ipath_qp *qp,
++				struct ipath_ib_header *hdr, u32 hdrwords,
++				struct ipath_sge_state *ss, u32 len,
++				u32 plen, u32 dwords)
++{
++	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
++	struct ipath_devdata *dd = dev->dd;
++	struct ipath_verbs_txreq *tx;
++	u32 *piobuf;
++	u32 control;
++	u32 ndesc;
++	int ret;
++
++	tx = qp->s_tx;
++	if (tx) {
++		qp->s_tx = NULL;
++		/* resend previously constructed packet */
++		ret = ipath_sdma_verbs_send(dd, tx->ss, tx->len, tx);
++		if (ret)
++			qp->s_tx = tx;
++		goto bail;
++	}
++
++	tx = get_txreq(dev);
++	if (!tx) {
++		ret = -EBUSY;
++		goto bail;
++	}
++
++	/*
++	 * Get the saved delay count we computed for the previous packet
++	 * and save the delay count for this packet to be used next time
++	 * we get here.
++	 */
++	control = qp->s_pkt_delay;
++	qp->s_pkt_delay = ipath_pkt_delay(plen, dd->delay_mult, qp->s_dmult);
++
++	tx->qp = qp;
++	atomic_inc(&qp->refcount);
++	tx->wqe = qp->s_wqe;
++	tx->txreq.callback = sdma_complete;
++	tx->txreq.callback_cookie = tx;
++	tx->txreq.flags = IPATH_SDMA_TXREQ_F_HEADTOHOST |
++		IPATH_SDMA_TXREQ_F_INTREQ | IPATH_SDMA_TXREQ_F_FREEDESC;
++	if (plen + 1 >= IPATH_SMALLBUF_DWORDS)
++		tx->txreq.flags |= IPATH_SDMA_TXREQ_F_USELARGEBUF;
++
++	/* VL15 packets bypass credit check */
++	if ((be16_to_cpu(hdr->lrh[0]) >> 12) == 15) {
++		control |= 1ULL << 31;
++		tx->txreq.flags |= IPATH_SDMA_TXREQ_F_VL15;
++	}
++
++	if (len) {
++		/*
++		 * Don't try to DMA if it takes more descriptors than
++		 * the queue holds.
++		 */
++		ndesc = ipath_count_sge(ss, len);
++		if (ndesc >= dd->ipath_sdma_descq_cnt)
++			ndesc = 0;
++	} else
++		ndesc = 1;
++	if (ndesc) {
++		tx->hdr.pbc[0] = cpu_to_le32(plen);
++		tx->hdr.pbc[1] = cpu_to_le32(control);
++		memcpy(&tx->hdr.hdr, hdr, hdrwords << 2);
++		tx->txreq.sg_count = ndesc;
++		tx->map_len = (hdrwords + 2) << 2;
++		tx->txreq.map_addr = &tx->hdr;
++		ret = ipath_sdma_verbs_send(dd, ss, dwords, tx);
++		if (ret) {
++			/* save ss and length in dwords */
++			tx->ss = ss;
++			tx->len = dwords;
++			qp->s_tx = tx;
++		}
++		goto bail;
++	}
++
++	/* Allocate a buffer and copy the header and payload to it. */
++	tx->map_len = (plen + 1) << 2;
++	piobuf = kmalloc(tx->map_len, GFP_ATOMIC);
++	if (unlikely(piobuf == NULL)) {
++		ret = -EBUSY;
++		goto err_tx;
++	}
++	tx->txreq.map_addr = piobuf;
++	tx->txreq.flags |= IPATH_SDMA_TXREQ_F_FREEBUF;
++	tx->txreq.sg_count = 1;
++
++	*piobuf++ = (__force u32) cpu_to_le32(plen);
++	*piobuf++ = (__force u32) cpu_to_le32(control);
++	memcpy(piobuf, hdr, hdrwords << 2);
++	ipath_copy_from_sge(piobuf + hdrwords, ss, len);
++
++	ret = ipath_sdma_verbs_send(dd, NULL, 0, tx);
++	/*
++	 * If we couldn't queue the DMA request, save the info
++	 * and try again later rather than destroying the
++	 * buffer and undoing the side effects of the copy.
++	 */
++	if (ret) {
++		tx->ss = NULL;
++		tx->len = 0;
++		qp->s_tx = tx;
++	}
++	dev->n_unaligned++;
++	goto bail;
++
++err_tx:
++	if (atomic_dec_and_test(&qp->refcount))
++		wake_up(&qp->wait);
++	put_txreq(dev, tx);
++bail:
++	return ret;
++}
++
++static int ipath_verbs_send_pio(struct ipath_qp *qp,
++				struct ipath_ib_header *ibhdr, u32 hdrwords,
+ 				struct ipath_sge_state *ss, u32 len,
+ 				u32 plen, u32 dwords)
+ {
+ 	struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd;
++	u32 *hdr = (u32 *) ibhdr;
+ 	u32 __iomem *piobuf;
+ 	unsigned flush_wc;
++	u32 control;
+ 	int ret;
+ 
+-	piobuf = ipath_getpiobuf(dd, NULL);
++	piobuf = ipath_getpiobuf(dd, plen, NULL);
+ 	if (unlikely(piobuf == NULL)) {
+ 		ret = -EBUSY;
+ 		goto bail;
+ 	}
+ 
+ 	/*
+-	 * Write len to control qword, no flags.
++	 * Get the saved delay count we computed for the previous packet
++	 * and save the delay count for this packet to be used next time
++	 * we get here.
++	 */
++	control = qp->s_pkt_delay;
++	qp->s_pkt_delay = ipath_pkt_delay(plen, dd->delay_mult, qp->s_dmult);
++
++	/* VL15 packets bypass credit check */
++	if ((be16_to_cpu(ibhdr->lrh[0]) >> 12) == 15)
++		control |= 1ULL << 31;
++
++	/*
++	 * Write the length to the control qword plus any needed flags.
+ 	 * We have to flush after the PBC for correctness on some cpus
+ 	 * or WC buffer can be written out of order.
+ 	 */
+-	writeq(plen, piobuf);
++	writeq(((u64) control << 32) | plen, piobuf);
+ 	piobuf += 2;
+ 
+ 	flush_wc = dd->ipath_flags & IPATH_PIO_FLUSH_WC;
+@@ -961,15 +1278,25 @@ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
+ 	 */
+ 	plen = hdrwords + dwords + 1;
+ 
+-	/* Drop non-VL15 packets if we are not in the active state */
+-	if (!(dd->ipath_flags & IPATH_LINKACTIVE) &&
+-	    qp->ibqp.qp_type != IB_QPT_SMI) {
++	/*
++	 * VL15 packets (IB_QPT_SMI) will always use PIO, so we
++	 * can defer SDMA restart until link goes ACTIVE without
++	 * worrying about just how we got there.
++	 */
++	if (qp->ibqp.qp_type == IB_QPT_SMI)
++		ret = ipath_verbs_send_pio(qp, hdr, hdrwords, ss, len,
++					   plen, dwords);
++	/* All non-VL15 packets are dropped if link is not ACTIVE */
++	else if (!(dd->ipath_flags & IPATH_LINKACTIVE)) {
+ 		if (qp->s_wqe)
+ 			ipath_send_complete(qp, qp->s_wqe, IB_WC_SUCCESS);
+ 		ret = 0;
+-	} else
+-		ret = ipath_verbs_send_pio(qp, (u32 *) hdr, hdrwords,
+-					   ss, len, plen, dwords);
++	} else if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++		ret = ipath_verbs_send_dma(qp, hdr, hdrwords, ss, len,
++					   plen, dwords);
++	else
++		ret = ipath_verbs_send_pio(qp, hdr, hdrwords, ss, len,
++					   plen, dwords);
+ 
+ 	return ret;
+ }
+@@ -1038,6 +1365,12 @@ int ipath_get_counters(struct ipath_devdata *dd,
+ 		ipath_snap_cntr(dd, crp->cr_errlpcrccnt) +
+ 		ipath_snap_cntr(dd, crp->cr_badformatcnt) +
+ 		dd->ipath_rxfc_unsupvl_errs;
++	if (crp->cr_rxotherlocalphyerrcnt)
++		cntrs->port_rcv_errors +=
++			ipath_snap_cntr(dd, crp->cr_rxotherlocalphyerrcnt);
++	if (crp->cr_rxvlerrcnt)
++		cntrs->port_rcv_errors +=
++			ipath_snap_cntr(dd, crp->cr_rxvlerrcnt);
+ 	cntrs->port_rcv_remphys_errors =
+ 		ipath_snap_cntr(dd, crp->cr_rcvebpcnt);
+ 	cntrs->port_xmit_discards = ipath_snap_cntr(dd, crp->cr_unsupvlcnt);
+@@ -1046,9 +1379,16 @@ int ipath_get_counters(struct ipath_devdata *dd,
+ 	cntrs->port_xmit_packets = ipath_snap_cntr(dd, crp->cr_pktsendcnt);
+ 	cntrs->port_rcv_packets = ipath_snap_cntr(dd, crp->cr_pktrcvcnt);
+ 	cntrs->local_link_integrity_errors =
+-		(dd->ipath_flags & IPATH_GPIO_ERRINTRS) ?
+-		dd->ipath_lli_errs : dd->ipath_lli_errors;
+-	cntrs->excessive_buffer_overrun_errors = dd->ipath_overrun_thresh_errs;
++		crp->cr_locallinkintegrityerrcnt ?
++		ipath_snap_cntr(dd, crp->cr_locallinkintegrityerrcnt) :
++		((dd->ipath_flags & IPATH_GPIO_ERRINTRS) ?
++		 dd->ipath_lli_errs : dd->ipath_lli_errors);
++	cntrs->excessive_buffer_overrun_errors =
++		crp->cr_excessbufferovflcnt ?
++		ipath_snap_cntr(dd, crp->cr_excessbufferovflcnt) :
++		dd->ipath_overrun_thresh_errs;
++	cntrs->vl15_dropped = crp->cr_vl15droppedpktcnt ?
++		ipath_snap_cntr(dd, crp->cr_vl15droppedpktcnt) : 0;
+ 
+ 	ret = 0;
+ 
+@@ -1183,7 +1523,9 @@ static int ipath_query_port(struct ib_device *ibdev,
+ 	props->sm_lid = dev->sm_lid;
+ 	props->sm_sl = dev->sm_sl;
+ 	ibcstat = dd->ipath_lastibcstat;
+-	props->state = ((ibcstat >> 4) & 0x3) + 1;
++	/* map LinkState to IB portinfo values.  */
++	props->state = ipath_ib_linkstate(dd, ibcstat) + 1;
++
+ 	/* See phys_state_show() */
+ 	props->phys_state = /* MEA: assumes shift == 0 */
+ 		ipath_cvt_physportstate[dd->ipath_lastibcstat &
+@@ -1195,18 +1537,13 @@ static int ipath_query_port(struct ib_device *ibdev,
+ 	props->bad_pkey_cntr = ipath_get_cr_errpkey(dd) -
+ 		dev->z_pkey_violations;
+ 	props->qkey_viol_cntr = dev->qkey_violations;
+-	props->active_width = IB_WIDTH_4X;
++	props->active_width = dd->ipath_link_width_active;
+ 	/* See rate_show() */
+-	props->active_speed = 1;	/* Regular 10Mbs speed. */
++	props->active_speed = dd->ipath_link_speed_active;
+ 	props->max_vl_num = 1;		/* VLCap = VL0 */
+ 	props->init_type_reply = 0;
+ 
+-	/*
+-	 * Note: the chip supports a maximum MTU of 4096, but the driver
+-	 * hasn't implemented this feature yet, so set the maximum value
+-	 * to 2048.
+-	 */
+-	props->max_mtu = IB_MTU_2048;
++	props->max_mtu = ipath_mtu4096 ? IB_MTU_4096 : IB_MTU_2048;
+ 	switch (dd->ipath_ibmtu) {
+ 	case 4096:
+ 		mtu = IB_MTU_4096;
+@@ -1399,6 +1736,7 @@ static struct ib_ah *ipath_create_ah(struct ib_pd *pd,
+ 
+ 	/* ib_create_ah() will initialize ah->ibah. */
+ 	ah->attr = *ah_attr;
++	ah->attr.static_rate = ipath_ib_rate_to_mult(ah_attr->static_rate);
+ 
+ 	ret = &ah->ibah;
+ 
+@@ -1432,6 +1770,7 @@ static int ipath_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
+ 	struct ipath_ah *ah = to_iah(ibah);
+ 
+ 	*ah_attr = ah->attr;
++	ah_attr->static_rate = ipath_mult_to_ib_rate(ah->attr.static_rate);
+ 
+ 	return 0;
+ }
+@@ -1581,6 +1920,8 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
+ 	struct ipath_verbs_counters cntrs;
+ 	struct ipath_ibdev *idev;
+ 	struct ib_device *dev;
++	struct ipath_verbs_txreq *tx;
++	unsigned i;
+ 	int ret;
+ 
+ 	idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev);
+@@ -1591,6 +1932,17 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
+ 
+ 	dev = &idev->ibdev;
+ 
++	if (dd->ipath_sdma_descq_cnt) {
++		tx = kmalloc(dd->ipath_sdma_descq_cnt * sizeof *tx,
++			     GFP_KERNEL);
++		if (tx == NULL) {
++			ret = -ENOMEM;
++			goto err_tx;
++		}
++	} else
++		tx = NULL;
++	idev->txreq_bufs = tx;
++
+ 	/* Only need to initialize non-zero fields. */
+ 	spin_lock_init(&idev->n_pds_lock);
+ 	spin_lock_init(&idev->n_ahs_lock);
+@@ -1631,15 +1983,17 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
+ 	INIT_LIST_HEAD(&idev->pending[2]);
+ 	INIT_LIST_HEAD(&idev->piowait);
+ 	INIT_LIST_HEAD(&idev->rnrwait);
++	INIT_LIST_HEAD(&idev->txreq_free);
+ 	idev->pending_index = 0;
+ 	idev->port_cap_flags =
+ 		IB_PORT_SYS_IMAGE_GUID_SUP | IB_PORT_CLIENT_REG_SUP;
++	if (dd->ipath_flags & IPATH_HAS_LINK_LATENCY)
++		idev->port_cap_flags |= IB_PORT_LINK_LATENCY_SUP;
+ 	idev->pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA;
+ 	idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA;
+ 	idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS;
+ 	idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS;
+ 	idev->pma_counter_select[4] = IB_PMA_PORT_XMIT_WAIT;
+-	idev->link_width_enabled = 3;	/* 1x or 4x */
+ 
+ 	/* Snapshot current HW counters to "clear" them. */
+ 	ipath_get_counters(dd, &cntrs);
+@@ -1661,6 +2015,9 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
+ 		cntrs.excessive_buffer_overrun_errors;
+ 	idev->z_vl15_dropped = cntrs.vl15_dropped;
+ 
++	for (i = 0; i < dd->ipath_sdma_descq_cnt; i++, tx++)
++		list_add(&tx->txreq.list, &idev->txreq_free);
++
+ 	/*
+ 	 * The system image GUID is supposed to be the same for all
+ 	 * IB HCAs in a single system but since there can be other
+@@ -1774,6 +2131,8 @@ err_reg:
+ err_lk:
+ 	kfree(idev->qp_table.table);
+ err_qp:
++	kfree(idev->txreq_bufs);
++err_tx:
+ 	ib_dealloc_device(dev);
+ 	ipath_dev_err(dd, "cannot register verbs: %d!\n", -ret);
+ 	idev = NULL;
+@@ -1808,21 +2167,24 @@ void ipath_unregister_ib_device(struct ipath_ibdev *dev)
+ 	ipath_free_all_qps(&dev->qp_table);
+ 	kfree(dev->qp_table.table);
+ 	kfree(dev->lk_table.table);
++	kfree(dev->txreq_bufs);
+ 	ib_dealloc_device(ibdev);
+ }
+ 
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *device, struct device_attribute *attr,
++			char *buf)
+ {
+ 	struct ipath_ibdev *dev =
+-		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
++		container_of(device, struct ipath_ibdev, ibdev.dev);
+ 
+ 	return sprintf(buf, "%x\n", dev->dd->ipath_pcirev);
+ }
+ 
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *device, struct device_attribute *attr,
++			char *buf)
+ {
+ 	struct ipath_ibdev *dev =
+-		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
++		container_of(device, struct ipath_ibdev, ibdev.dev);
+ 	int ret;
+ 
+ 	ret = dev->dd->ipath_f_get_boardname(dev->dd, buf, 128);
+@@ -1835,10 +2197,11 @@ bail:
+ 	return ret;
+ }
+ 
+-static ssize_t show_stats(struct class_device *cdev, char *buf)
++static ssize_t show_stats(struct device *device, struct device_attribute *attr,
++			  char *buf)
+ {
+ 	struct ipath_ibdev *dev =
+-		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
++		container_of(device, struct ipath_ibdev, ibdev.dev);
+ 	int i;
+ 	int len;
+ 
+@@ -1855,13 +2218,15 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
+ 		      "RC stalls   %d\n"
+ 		      "piobuf wait %d\n"
+ 		      "no piobuf   %d\n"
++		      "unaligned   %d\n"
+ 		      "PKT drops   %d\n"
+ 		      "WQE errs    %d\n",
+ 		      dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
+ 		      dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
+ 		      dev->n_other_naks, dev->n_timeouts,
+ 		      dev->n_rdma_dup_busy, dev->n_rc_stalls, dev->n_piowait,
+-		      dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
++		      dev->n_no_piobuf, dev->n_unaligned,
++		      dev->n_pkt_drops, dev->n_wqe_errs);
+ 	for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
+ 		const struct ipath_opcode_stats *si = &dev->opstats[i];
+ 
+@@ -1874,16 +2239,16 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
+ 	return len;
+ }
+ 
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
+ 
+-static struct class_device_attribute *ipath_class_attributes[] = {
+-	&class_device_attr_hw_rev,
+-	&class_device_attr_hca_type,
+-	&class_device_attr_board_id,
+-	&class_device_attr_stats
++static struct device_attribute *ipath_class_attributes[] = {
++	&dev_attr_hw_rev,
++	&dev_attr_hca_type,
++	&dev_attr_board_id,
++	&dev_attr_stats
+ };
+ 
+ static int ipath_verbs_register_sysfs(struct ib_device *dev)
+@@ -1892,8 +2257,8 @@ static int ipath_verbs_register_sysfs(struct ib_device *dev)
+ 	int ret;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)
+-		if (class_device_create_file(&dev->class_dev,
+-					     ipath_class_attributes[i])) {
++		if (device_create_file(&dev->dev,
++				       ipath_class_attributes[i])) {
+ 			ret = 1;
+ 			goto bail;
+ 		}
+diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
+index 3d59736..6514aa8 100644
+--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
++++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+@@ -138,6 +138,11 @@ struct ipath_ib_header {
+ 	} u;
+ } __attribute__ ((packed));
+ 
++struct ipath_pio_header {
++	__le32 pbc[2];
++	struct ipath_ib_header hdr;
++} __attribute__ ((packed));
++
+ /*
+  * There is one struct ipath_mcast for each multicast GID.
+  * All attached QPs are then stored as a list of
+@@ -319,6 +324,7 @@ struct ipath_sge_state {
+ 	struct ipath_sge *sg_list;      /* next SGE to be used if any */
+ 	struct ipath_sge sge;   /* progress state for the current SGE */
+ 	u8 num_sge;
++	u8 static_rate;
+ };
+ 
+ /*
+@@ -356,6 +362,7 @@ struct ipath_qp {
+ 	struct tasklet_struct s_task;
+ 	struct ipath_mmap_info *ip;
+ 	struct ipath_sge_state *s_cur_sge;
++	struct ipath_verbs_txreq *s_tx;
+ 	struct ipath_sge_state s_sge;	/* current send request data */
+ 	struct ipath_ack_entry s_ack_queue[IPATH_MAX_RDMA_ATOMIC + 1];
+ 	struct ipath_sge_state s_ack_rdma_sge;
+@@ -363,7 +370,8 @@ struct ipath_qp {
+ 	struct ipath_sge_state r_sge;	/* current receive data */
+ 	spinlock_t s_lock;
+ 	unsigned long s_busy;
+-	u32 s_hdrwords;		/* size of s_hdr in 32 bit words */
++	u16 s_pkt_delay;
++	u16 s_hdrwords;		/* size of s_hdr in 32 bit words */
+ 	u32 s_cur_size;		/* size of send packet in bytes */
+ 	u32 s_len;		/* total length of s_sge */
+ 	u32 s_rdma_read_len;	/* total length of s_rdma_read_sge */
+@@ -387,7 +395,6 @@ struct ipath_qp {
+ 	u8 r_nak_state;		/* non-zero if NAK is pending */
+ 	u8 r_min_rnr_timer;	/* retry timeout value for RNR NAKs */
+ 	u8 r_reuse_sge;		/* for UC receive errors */
+-	u8 r_sge_inx;		/* current index into sg_list */
+ 	u8 r_wrid_valid;	/* r_wrid set but CQ entry not yet made */
+ 	u8 r_max_rd_atomic;	/* max number of RDMA read/atomic to receive */
+ 	u8 r_head_ack_queue;	/* index into s_ack_queue[] */
+@@ -403,6 +410,7 @@ struct ipath_qp {
+ 	u8 s_num_rd_atomic;	/* number of RDMA read/atomic pending */
+ 	u8 s_tail_ack_queue;	/* index into s_ack_queue[] */
+ 	u8 s_flags;
++	u8 s_dmult;
+ 	u8 timeout;		/* Timeout for this QP */
+ 	enum ib_mtu path_mtu;
+ 	u32 remote_qpn;
+@@ -510,6 +518,8 @@ struct ipath_ibdev {
+ 	struct ipath_lkey_table lk_table;
+ 	struct list_head pending[3];	/* FIFO of QPs waiting for ACKs */
+ 	struct list_head piowait;	/* list for wait PIO buf */
++	struct list_head txreq_free;
++	void *txreq_bufs;
+ 	/* list of QPs waiting for RNR timer */
+ 	struct list_head rnrwait;
+ 	spinlock_t pending_lock;
+@@ -570,6 +580,7 @@ struct ipath_ibdev {
+ 	u32 n_rdma_dup_busy;
+ 	u32 n_piowait;
+ 	u32 n_no_piobuf;
++	u32 n_unaligned;
+ 	u32 port_cap_flags;
+ 	u32 pma_sample_start;
+ 	u32 pma_sample_interval;
+@@ -581,7 +592,6 @@ struct ipath_ibdev {
+ 	u16 pending_index;	/* which pending queue is active */
+ 	u8 pma_sample_status;
+ 	u8 subnet_timeout;
+-	u8 link_width_enabled;
+ 	u8 vl_high_limit;
+ 	struct ipath_opcode_stats opstats[128];
+ };
+@@ -602,6 +612,16 @@ struct ipath_verbs_counters {
+ 	u32 vl15_dropped;
+ };
+ 
++struct ipath_verbs_txreq {
++	struct ipath_qp         *qp;
++	struct ipath_swqe       *wqe;
++	u32                      map_len;
++	u32                      len;
++	struct ipath_sge_state  *ss;
++	struct ipath_pio_header  hdr;
++	struct ipath_sdma_txreq  txreq;
++};
++
+ static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)
+ {
+ 	return container_of(ibmr, struct ipath_mr, ibmr);
+@@ -694,11 +714,11 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc);
+ 
+ void ipath_get_credit(struct ipath_qp *qp, u32 aeth);
+ 
++unsigned ipath_ib_rate_to_mult(enum ib_rate rate);
++
+ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
+ 		     u32 hdrwords, struct ipath_sge_state *ss, u32 len);
+ 
+-void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
+-
+ void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length);
+ 
+ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length);
+diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
+index 7360bba..3557e7e 100644
+--- a/drivers/infiniband/hw/mlx4/cq.c
++++ b/drivers/infiniband/hw/mlx4/cq.c
+@@ -85,6 +85,82 @@ static struct mlx4_cqe *next_cqe_sw(struct mlx4_ib_cq *cq)
+ 	return get_sw_cqe(cq, cq->mcq.cons_index);
+ }
+ 
++int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
++{
++	struct mlx4_ib_cq *mcq = to_mcq(cq);
++	struct mlx4_ib_dev *dev = to_mdev(cq->device);
++
++	return mlx4_cq_modify(dev->dev, &mcq->mcq, cq_count, cq_period);
++}
++
++static int mlx4_ib_alloc_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *buf, int nent)
++{
++	int err;
++
++	err = mlx4_buf_alloc(dev->dev, nent * sizeof(struct mlx4_cqe),
++			     PAGE_SIZE * 2, &buf->buf);
++
++	if (err)
++		goto out;
++
++	err = mlx4_mtt_init(dev->dev, buf->buf.npages, buf->buf.page_shift,
++				    &buf->mtt);
++	if (err)
++		goto err_buf;
++
++	err = mlx4_buf_write_mtt(dev->dev, &buf->mtt, &buf->buf);
++	if (err)
++		goto err_mtt;
++
++	return 0;
++
++err_mtt:
++	mlx4_mtt_cleanup(dev->dev, &buf->mtt);
++
++err_buf:
++	mlx4_buf_free(dev->dev, nent * sizeof(struct mlx4_cqe),
++			      &buf->buf);
++
++out:
++	return err;
++}
++
++static void mlx4_ib_free_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *buf, int cqe)
++{
++	mlx4_buf_free(dev->dev, (cqe + 1) * sizeof(struct mlx4_cqe), &buf->buf);
++}
++
++static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_ucontext *context,
++			       struct mlx4_ib_cq_buf *buf, struct ib_umem **umem,
++			       u64 buf_addr, int cqe)
++{
++	int err;
++
++	*umem = ib_umem_get(context, buf_addr, cqe * sizeof (struct mlx4_cqe),
++			    IB_ACCESS_LOCAL_WRITE);
++	if (IS_ERR(*umem))
++		return PTR_ERR(*umem);
++
++	err = mlx4_mtt_init(dev->dev, ib_umem_page_count(*umem),
++			    ilog2((*umem)->page_size), &buf->mtt);
++	if (err)
++		goto err_buf;
++
++	err = mlx4_ib_umem_write_mtt(dev, &buf->mtt, *umem);
++	if (err)
++		goto err_mtt;
++
++	return 0;
++
++err_mtt:
++	mlx4_mtt_cleanup(dev->dev, &buf->mtt);
++
++err_buf:
++	ib_umem_release(*umem);
++
++	return err;
++}
++
+ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector,
+ 				struct ib_ucontext *context,
+ 				struct ib_udata *udata)
+@@ -92,7 +168,6 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
+ 	struct mlx4_ib_dev *dev = to_mdev(ibdev);
+ 	struct mlx4_ib_cq *cq;
+ 	struct mlx4_uar *uar;
+-	int buf_size;
+ 	int err;
+ 
+ 	if (entries < 1 || entries > dev->dev->caps.max_cqes)
+@@ -104,8 +179,10 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
+ 
+ 	entries      = roundup_pow_of_two(entries + 1);
+ 	cq->ibcq.cqe = entries - 1;
+-	buf_size     = entries * sizeof (struct mlx4_cqe);
++	mutex_init(&cq->resize_mutex);
+ 	spin_lock_init(&cq->lock);
++	cq->resize_buf = NULL;
++	cq->resize_umem = NULL;
+ 
+ 	if (context) {
+ 		struct mlx4_ib_create_cq ucmd;
+@@ -115,21 +192,10 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
+ 			goto err_cq;
+ 		}
+ 
+-		cq->umem = ib_umem_get(context, ucmd.buf_addr, buf_size,
+-				       IB_ACCESS_LOCAL_WRITE);
+-		if (IS_ERR(cq->umem)) {
+-			err = PTR_ERR(cq->umem);
+-			goto err_cq;
+-		}
+-
+-		err = mlx4_mtt_init(dev->dev, ib_umem_page_count(cq->umem),
+-				    ilog2(cq->umem->page_size), &cq->buf.mtt);
+-		if (err)
+-			goto err_buf;
+-
+-		err = mlx4_ib_umem_write_mtt(dev, &cq->buf.mtt, cq->umem);
++		err = mlx4_ib_get_cq_umem(dev, context, &cq->buf, &cq->umem,
++					  ucmd.buf_addr, entries);
+ 		if (err)
+-			goto err_mtt;
++			goto err_cq;
+ 
+ 		err = mlx4_ib_db_map_user(to_mucontext(context), ucmd.db_addr,
+ 					  &cq->db);
+@@ -147,19 +213,9 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
+ 		*cq->mcq.set_ci_db = 0;
+ 		*cq->mcq.arm_db    = 0;
+ 
+-		if (mlx4_buf_alloc(dev->dev, buf_size, PAGE_SIZE * 2, &cq->buf.buf)) {
+-			err = -ENOMEM;
+-			goto err_db;
+-		}
+-
+-		err = mlx4_mtt_init(dev->dev, cq->buf.buf.npages, cq->buf.buf.page_shift,
+-				    &cq->buf.mtt);
++		err = mlx4_ib_alloc_cq_buf(dev, &cq->buf, entries);
+ 		if (err)
+-			goto err_buf;
+-
+-		err = mlx4_buf_write_mtt(dev->dev, &cq->buf.mtt, &cq->buf.buf);
+-		if (err)
+-			goto err_mtt;
++			goto err_db;
+ 
+ 		uar = &dev->priv_uar;
+ 	}
+@@ -187,12 +243,10 @@ err_dbmap:
+ err_mtt:
+ 	mlx4_mtt_cleanup(dev->dev, &cq->buf.mtt);
+ 
+-err_buf:
+ 	if (context)
+ 		ib_umem_release(cq->umem);
+ 	else
+-		mlx4_buf_free(dev->dev, entries * sizeof (struct mlx4_cqe),
+-			      &cq->buf.buf);
++		mlx4_ib_free_cq_buf(dev, &cq->buf, entries);
+ 
+ err_db:
+ 	if (!context)
+@@ -204,6 +258,170 @@ err_cq:
+ 	return ERR_PTR(err);
+ }
+ 
++static int mlx4_alloc_resize_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq *cq,
++				  int entries)
++{
++	int err;
++
++	if (cq->resize_buf)
++		return -EBUSY;
++
++	cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
++	if (!cq->resize_buf)
++		return -ENOMEM;
++
++	err = mlx4_ib_alloc_cq_buf(dev, &cq->resize_buf->buf, entries);
++	if (err) {
++		kfree(cq->resize_buf);
++		cq->resize_buf = NULL;
++		return err;
++	}
++
++	cq->resize_buf->cqe = entries - 1;
++
++	return 0;
++}
++
++static int mlx4_alloc_resize_umem(struct mlx4_ib_dev *dev, struct mlx4_ib_cq *cq,
++				   int entries, struct ib_udata *udata)
++{
++	struct mlx4_ib_resize_cq ucmd;
++	int err;
++
++	if (cq->resize_umem)
++		return -EBUSY;
++
++	if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
++		return -EFAULT;
++
++	cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
++	if (!cq->resize_buf)
++		return -ENOMEM;
++
++	err = mlx4_ib_get_cq_umem(dev, cq->umem->context, &cq->resize_buf->buf,
++				  &cq->resize_umem, ucmd.buf_addr, entries);
++	if (err) {
++		kfree(cq->resize_buf);
++		cq->resize_buf = NULL;
++		return err;
++	}
++
++	cq->resize_buf->cqe = entries - 1;
++
++	return 0;
++}
++
++static int mlx4_ib_get_outstanding_cqes(struct mlx4_ib_cq *cq)
++{
++	u32 i;
++
++	i = cq->mcq.cons_index;
++	while (get_sw_cqe(cq, i & cq->ibcq.cqe))
++		++i;
++
++	return i - cq->mcq.cons_index;
++}
++
++static void mlx4_ib_cq_resize_copy_cqes(struct mlx4_ib_cq *cq)
++{
++	struct mlx4_cqe *cqe;
++	int i;
++
++	i = cq->mcq.cons_index;
++	cqe = get_cqe(cq, i & cq->ibcq.cqe);
++	while ((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) != MLX4_CQE_OPCODE_RESIZE) {
++		memcpy(get_cqe_from_buf(&cq->resize_buf->buf,
++					(i + 1) & cq->resize_buf->cqe),
++			get_cqe(cq, i & cq->ibcq.cqe), sizeof(struct mlx4_cqe));
++		cqe = get_cqe(cq, ++i & cq->ibcq.cqe);
++	}
++	++cq->mcq.cons_index;
++}
++
++int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
++{
++	struct mlx4_ib_dev *dev = to_mdev(ibcq->device);
++	struct mlx4_ib_cq *cq = to_mcq(ibcq);
++	int outst_cqe;
++	int err;
++
++	mutex_lock(&cq->resize_mutex);
++
++	if (entries < 1 || entries > dev->dev->caps.max_cqes) {
++		err = -EINVAL;
++		goto out;
++	}
++
++	entries = roundup_pow_of_two(entries + 1);
++	if (entries == ibcq->cqe + 1) {
++		err = 0;
++		goto out;
++	}
++
++	if (ibcq->uobject) {
++		err = mlx4_alloc_resize_umem(dev, cq, entries, udata);
++		if (err)
++			goto out;
++	} else {
++		/* Can't be smaller then the number of outstanding CQEs */
++		outst_cqe = mlx4_ib_get_outstanding_cqes(cq);
++		if (entries < outst_cqe + 1) {
++			err = 0;
++			goto out;
++		}
++
++		err = mlx4_alloc_resize_buf(dev, cq, entries);
++		if (err)
++			goto out;
++	}
++
++	err = mlx4_cq_resize(dev->dev, &cq->mcq, entries, &cq->resize_buf->buf.mtt);
++	if (err)
++		goto err_buf;
++
++	if (ibcq->uobject) {
++		cq->buf      = cq->resize_buf->buf;
++		cq->ibcq.cqe = cq->resize_buf->cqe;
++		ib_umem_release(cq->umem);
++		cq->umem     = cq->resize_umem;
++
++		kfree(cq->resize_buf);
++		cq->resize_buf = NULL;
++		cq->resize_umem = NULL;
++	} else {
++		spin_lock_irq(&cq->lock);
++		if (cq->resize_buf) {
++			mlx4_ib_cq_resize_copy_cqes(cq);
++			mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
++			cq->buf      = cq->resize_buf->buf;
++			cq->ibcq.cqe = cq->resize_buf->cqe;
++
++			kfree(cq->resize_buf);
++			cq->resize_buf = NULL;
++		}
++		spin_unlock_irq(&cq->lock);
++	}
++
++	goto out;
++
++err_buf:
++	if (!ibcq->uobject)
++		mlx4_ib_free_cq_buf(dev, &cq->resize_buf->buf,
++				    cq->resize_buf->cqe);
++
++	kfree(cq->resize_buf);
++	cq->resize_buf = NULL;
++
++	if (cq->resize_umem) {
++		ib_umem_release(cq->resize_umem);
++		cq->resize_umem = NULL;
++	}
++
++out:
++	mutex_unlock(&cq->resize_mutex);
++	return err;
++}
++
+ int mlx4_ib_destroy_cq(struct ib_cq *cq)
+ {
+ 	struct mlx4_ib_dev *dev = to_mdev(cq->device);
+@@ -216,8 +434,7 @@ int mlx4_ib_destroy_cq(struct ib_cq *cq)
+ 		mlx4_ib_db_unmap_user(to_mucontext(cq->uobject->context), &mcq->db);
+ 		ib_umem_release(mcq->umem);
+ 	} else {
+-		mlx4_buf_free(dev->dev, (cq->cqe + 1) * sizeof (struct mlx4_cqe),
+-			      &mcq->buf.buf);
++		mlx4_ib_free_cq_buf(dev, &mcq->buf, cq->cqe + 1);
+ 		mlx4_ib_db_free(dev, &mcq->db);
+ 	}
+ 
+@@ -297,6 +514,20 @@ static void mlx4_ib_handle_error_cqe(struct mlx4_err_cqe *cqe,
+ 	wc->vendor_err = cqe->vendor_err_syndrome;
+ }
+ 
++static int mlx4_ib_ipoib_csum_ok(__be32 status, __be16 checksum)
++{
++	return ((status & cpu_to_be32(MLX4_CQE_IPOIB_STATUS_IPV4	|
++				      MLX4_CQE_IPOIB_STATUS_IPV4F	|
++				      MLX4_CQE_IPOIB_STATUS_IPV4OPT	|
++				      MLX4_CQE_IPOIB_STATUS_IPV6	|
++				      MLX4_CQE_IPOIB_STATUS_IPOK)) ==
++		cpu_to_be32(MLX4_CQE_IPOIB_STATUS_IPV4	|
++			    MLX4_CQE_IPOIB_STATUS_IPOK))		&&
++		(status & cpu_to_be32(MLX4_CQE_IPOIB_STATUS_UDP	|
++				      MLX4_CQE_IPOIB_STATUS_TCP))	&&
++		checksum == cpu_to_be16(0xffff);
++}
++
+ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ 			    struct mlx4_ib_qp **cur_qp,
+ 			    struct ib_wc *wc)
+@@ -310,6 +541,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ 	u32 g_mlpath_rqpn;
+ 	u16 wqe_ctr;
+ 
++repoll:
+ 	cqe = next_cqe_sw(cq);
+ 	if (!cqe)
+ 		return -EAGAIN;
+@@ -332,6 +564,22 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ 		return -EINVAL;
+ 	}
+ 
++	/* Resize CQ in progress */
++	if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == MLX4_CQE_OPCODE_RESIZE)) {
++		if (cq->resize_buf) {
++			struct mlx4_ib_dev *dev = to_mdev(cq->ibcq.device);
++
++			mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
++			cq->buf      = cq->resize_buf->buf;
++			cq->ibcq.cqe = cq->resize_buf->cqe;
++
++			kfree(cq->resize_buf);
++			cq->resize_buf = NULL;
++		}
++
++		goto repoll;
++	}
++
+ 	if (!*cur_qp ||
+ 	    (be32_to_cpu(cqe->my_qpn) & 0xffffff) != (*cur_qp)->mqp.qpn) {
+ 		/*
+@@ -406,6 +654,9 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ 		case MLX4_OPCODE_BIND_MW:
+ 			wc->opcode    = IB_WC_BIND_MW;
+ 			break;
++		case MLX4_OPCODE_LSO:
++			wc->opcode    = IB_WC_LSO;
++			break;
+ 		}
+ 	} else {
+ 		wc->byte_len = be32_to_cpu(cqe->byte_cnt);
+@@ -434,6 +685,8 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ 		wc->dlid_path_bits = (g_mlpath_rqpn >> 24) & 0x7f;
+ 		wc->wc_flags	  |= g_mlpath_rqpn & 0x80000000 ? IB_WC_GRH : 0;
+ 		wc->pkey_index     = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f;
++		wc->csum_ok	   = mlx4_ib_ipoib_csum_ok(cqe->ipoib_status,
++							   cqe->checksum);
+ 	}
+ 
+ 	return 0;
+diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
+index 0ed02b7..4c1e72f 100644
+--- a/drivers/infiniband/hw/mlx4/mad.c
++++ b/drivers/infiniband/hw/mlx4/mad.c
+@@ -165,7 +165,7 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad)
+ 			event.device	       = ibdev;
+ 			event.element.port_num = port_num;
+ 
+-			if(pinfo->clientrereg_resv_subnetto & 0x80)
++			if (pinfo->clientrereg_resv_subnetto & 0x80)
+ 				event.event    = IB_EVENT_CLIENT_REREGISTER;
+ 			else
+ 				event.event    = IB_EVENT_LID_CHANGE;
+diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
+index 96a39b5..4d9b5ac 100644
+--- a/drivers/infiniband/hw/mlx4/main.c
++++ b/drivers/infiniband/hw/mlx4/main.c
+@@ -44,8 +44,8 @@
+ #include "user.h"
+ 
+ #define DRV_NAME	"mlx4_ib"
+-#define DRV_VERSION	"0.01"
+-#define DRV_RELDATE	"May 1, 2006"
++#define DRV_VERSION	"1.0"
++#define DRV_RELDATE	"April 4, 2008"
+ 
+ MODULE_AUTHOR("Roland Dreier");
+ MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver");
+@@ -99,6 +99,10 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
+ 		props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
+ 	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UD_AV_PORT)
+ 		props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
++	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
++		props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
++	if (dev->dev->caps.max_gso_sz)
++		props->device_cap_flags |= IB_DEVICE_UD_TSO;
+ 
+ 	props->vendor_id	   = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
+ 		0xffffff;
+@@ -477,42 +481,51 @@ out:
+ 	return err;
+ }
+ 
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *device, struct device_attribute *attr,
++			char *buf)
+ {
+-	struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev, ib_dev.class_dev);
++	struct mlx4_ib_dev *dev =
++		container_of(device, struct mlx4_ib_dev, ib_dev.dev);
+ 	return sprintf(buf, "MT%d\n", dev->dev->pdev->device);
+ }
+ 
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
++			   char *buf)
+ {
+-	struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev, ib_dev.class_dev);
++	struct mlx4_ib_dev *dev =
++		container_of(device, struct mlx4_ib_dev, ib_dev.dev);
+ 	return sprintf(buf, "%d.%d.%d\n", (int) (dev->dev->caps.fw_ver >> 32),
+ 		       (int) (dev->dev->caps.fw_ver >> 16) & 0xffff,
+ 		       (int) dev->dev->caps.fw_ver & 0xffff);
+ }
+ 
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *device, struct device_attribute *attr,
++			char *buf)
+ {
+-	struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev, ib_dev.class_dev);
++	struct mlx4_ib_dev *dev =
++		container_of(device, struct mlx4_ib_dev, ib_dev.dev);
+ 	return sprintf(buf, "%x\n", dev->dev->rev_id);
+ }
+ 
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *device, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev, ib_dev.class_dev);
+-	return sprintf(buf, "%.*s\n", MLX4_BOARD_ID_LEN, dev->dev->board_id);
++	struct mlx4_ib_dev *dev =
++		container_of(device, struct mlx4_ib_dev, ib_dev.dev);
++	return sprintf(buf, "%.*s\n", MLX4_BOARD_ID_LEN,
++		       dev->dev->board_id);
+ }
+ 
+-static CLASS_DEVICE_ATTR(hw_rev,   S_IRUGO, show_rev,    NULL);
+-static CLASS_DEVICE_ATTR(fw_ver,   S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca,    NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board,  NULL);
++static DEVICE_ATTR(hw_rev,   S_IRUGO, show_rev,    NULL);
++static DEVICE_ATTR(fw_ver,   S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca,    NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board,  NULL);
+ 
+-static struct class_device_attribute *mlx4_class_attributes[] = {
+-	&class_device_attr_hw_rev,
+-	&class_device_attr_fw_ver,
+-	&class_device_attr_hca_type,
+-	&class_device_attr_board_id
++static struct device_attribute *mlx4_class_attributes[] = {
++	&dev_attr_hw_rev,
++	&dev_attr_fw_ver,
++	&dev_attr_hca_type,
++	&dev_attr_board_id
+ };
+ 
+ static void *mlx4_ib_add(struct mlx4_dev *dev)
+@@ -567,6 +580,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
+ 		(1ull << IB_USER_VERBS_CMD_DEREG_MR)		|
+ 		(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL)	|
+ 		(1ull << IB_USER_VERBS_CMD_CREATE_CQ)		|
++		(1ull << IB_USER_VERBS_CMD_RESIZE_CQ)		|
+ 		(1ull << IB_USER_VERBS_CMD_DESTROY_CQ)		|
+ 		(1ull << IB_USER_VERBS_CMD_CREATE_QP)		|
+ 		(1ull << IB_USER_VERBS_CMD_MODIFY_QP)		|
+@@ -605,6 +619,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
+ 	ibdev->ib_dev.post_send		= mlx4_ib_post_send;
+ 	ibdev->ib_dev.post_recv		= mlx4_ib_post_recv;
+ 	ibdev->ib_dev.create_cq		= mlx4_ib_create_cq;
++	ibdev->ib_dev.modify_cq		= mlx4_ib_modify_cq;
++	ibdev->ib_dev.resize_cq		= mlx4_ib_resize_cq;
+ 	ibdev->ib_dev.destroy_cq	= mlx4_ib_destroy_cq;
+ 	ibdev->ib_dev.poll_cq		= mlx4_ib_poll_cq;
+ 	ibdev->ib_dev.req_notify_cq	= mlx4_ib_arm_cq;
+@@ -633,8 +649,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
+ 		goto err_reg;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(mlx4_class_attributes); ++i) {
+-		if (class_device_create_file(&ibdev->ib_dev.class_dev,
+-					       mlx4_class_attributes[i]))
++		if (device_create_file(&ibdev->ib_dev.dev,
++				       mlx4_class_attributes[i]))
+ 			goto err_reg;
+ 	}
+ 
+@@ -675,18 +691,20 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
+ }
+ 
+ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
+-			  enum mlx4_dev_event event, int subtype,
+-			  int port)
++			  enum mlx4_dev_event event, int port)
+ {
+ 	struct ib_event ibev;
+ 
+ 	switch (event) {
+-	case MLX4_EVENT_TYPE_PORT_CHANGE:
+-		ibev.event = subtype == MLX4_PORT_CHANGE_SUBTYPE_ACTIVE ?
+-			IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
++	case MLX4_DEV_EVENT_PORT_UP:
++		ibev.event = IB_EVENT_PORT_ACTIVE;
+ 		break;
+ 
+-	case MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR:
++	case MLX4_DEV_EVENT_PORT_DOWN:
++		ibev.event = IB_EVENT_PORT_ERR;
++		break;
++
++	case MLX4_DEV_EVENT_CATASTROPHIC_ERROR:
+ 		ibev.event = IB_EVENT_DEVICE_FATAL;
+ 		break;
+ 
+diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
+index 3726e45..9e63732 100644
+--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
++++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
+@@ -78,13 +78,21 @@ struct mlx4_ib_cq_buf {
+ 	struct mlx4_mtt		mtt;
+ };
+ 
++struct mlx4_ib_cq_resize {
++	struct mlx4_ib_cq_buf	buf;
++	int			cqe;
++};
++
+ struct mlx4_ib_cq {
+ 	struct ib_cq		ibcq;
+ 	struct mlx4_cq		mcq;
+ 	struct mlx4_ib_cq_buf	buf;
++	struct mlx4_ib_cq_resize *resize_buf;
+ 	struct mlx4_ib_db	db;
+ 	spinlock_t		lock;
++	struct mutex		resize_mutex;
+ 	struct ib_umem	       *umem;
++	struct ib_umem	       *resize_umem;
+ };
+ 
+ struct mlx4_ib_mr {
+@@ -110,6 +118,10 @@ struct mlx4_ib_wq {
+ 	unsigned		tail;
+ };
+ 
++enum mlx4_ib_qp_flags {
++	MLX4_IB_QP_LSO		= 1 << 0
++};
++
+ struct mlx4_ib_qp {
+ 	struct ib_qp		ibqp;
+ 	struct mlx4_qp		mqp;
+@@ -129,6 +141,7 @@ struct mlx4_ib_qp {
+ 	struct mlx4_mtt		mtt;
+ 	int			buf_size;
+ 	struct mutex		mutex;
++	u32			flags;
+ 	u8			port;
+ 	u8			alt_port;
+ 	u8			atomic_rd_en;
+@@ -249,6 +262,8 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ 				  struct ib_udata *udata);
+ int mlx4_ib_dereg_mr(struct ib_mr *mr);
+ 
++int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
++int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata);
+ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector,
+ 				struct ib_ucontext *context,
+ 				struct ib_udata *udata);
+diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
+index 958e205..b75efae 100644
+--- a/drivers/infiniband/hw/mlx4/qp.c
++++ b/drivers/infiniband/hw/mlx4/qp.c
+@@ -71,6 +71,7 @@ enum {
+ 
+ static const __be32 mlx4_ib_opcode[] = {
+ 	[IB_WR_SEND]			= __constant_cpu_to_be32(MLX4_OPCODE_SEND),
++	[IB_WR_LSO]			= __constant_cpu_to_be32(MLX4_OPCODE_LSO),
+ 	[IB_WR_SEND_WITH_IMM]		= __constant_cpu_to_be32(MLX4_OPCODE_SEND_IMM),
+ 	[IB_WR_RDMA_WRITE]		= __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE),
+ 	[IB_WR_RDMA_WRITE_WITH_IMM]	= __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE_IMM),
+@@ -122,7 +123,7 @@ static void *get_send_wqe(struct mlx4_ib_qp *qp, int n)
+  */
+ static void stamp_send_wqe(struct mlx4_ib_qp *qp, int n, int size)
+ {
+-	u32 *wqe;
++	__be32 *wqe;
+ 	int i;
+ 	int s;
+ 	int ind;
+@@ -143,7 +144,7 @@ static void stamp_send_wqe(struct mlx4_ib_qp *qp, int n, int size)
+ 		buf = get_send_wqe(qp, n & (qp->sq.wqe_cnt - 1));
+ 		for (i = 64; i < s; i += 64) {
+ 			wqe = buf + i;
+-			*wqe = 0xffffffff;
++			*wqe = cpu_to_be32(0xffffffff);
+ 		}
+ 	}
+ }
+@@ -242,7 +243,7 @@ static void mlx4_ib_qp_event(struct mlx4_qp *qp, enum mlx4_event type)
+ 	}
+ }
+ 
+-static int send_wqe_overhead(enum ib_qp_type type)
++static int send_wqe_overhead(enum ib_qp_type type, u32 flags)
+ {
+ 	/*
+ 	 * UD WQEs must have a datagram segment.
+@@ -253,7 +254,8 @@ static int send_wqe_overhead(enum ib_qp_type type)
+ 	switch (type) {
+ 	case IB_QPT_UD:
+ 		return sizeof (struct mlx4_wqe_ctrl_seg) +
+-			sizeof (struct mlx4_wqe_datagram_seg);
++			sizeof (struct mlx4_wqe_datagram_seg) +
++			((flags & MLX4_IB_QP_LSO) ? 64 : 0);
+ 	case IB_QPT_UC:
+ 		return sizeof (struct mlx4_wqe_ctrl_seg) +
+ 			sizeof (struct mlx4_wqe_raddr_seg);
+@@ -315,7 +317,7 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+ 	/* Sanity check SQ size before proceeding */
+ 	if (cap->max_send_wr	 > dev->dev->caps.max_wqes  ||
+ 	    cap->max_send_sge	 > dev->dev->caps.max_sq_sg ||
+-	    cap->max_inline_data + send_wqe_overhead(type) +
++	    cap->max_inline_data + send_wqe_overhead(type, qp->flags) +
+ 	    sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz)
+ 		return -EINVAL;
+ 
+@@ -329,7 +331,7 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+ 
+ 	s = max(cap->max_send_sge * sizeof (struct mlx4_wqe_data_seg),
+ 		cap->max_inline_data + sizeof (struct mlx4_wqe_inline_seg)) +
+-		send_wqe_overhead(type);
++		send_wqe_overhead(type, qp->flags);
+ 
+ 	/*
+ 	 * Hermon supports shrinking WQEs, such that a single work
+@@ -394,7 +396,8 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+ 	}
+ 
+ 	qp->sq.max_gs = ((qp->sq_max_wqes_per_wr << qp->sq.wqe_shift) -
+-			 send_wqe_overhead(type)) / sizeof (struct mlx4_wqe_data_seg);
++			 send_wqe_overhead(type, qp->flags)) /
++		sizeof (struct mlx4_wqe_data_seg);
+ 
+ 	qp->buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
+ 		(qp->sq.wqe_cnt << qp->sq.wqe_shift);
+@@ -503,6 +506,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
+ 	} else {
+ 		qp->sq_no_prefetch = 0;
+ 
++		if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)
++			qp->flags |= MLX4_IB_QP_LSO;
++
+ 		err = set_kernel_sq_size(dev, &init_attr->cap, init_attr->qp_type, qp);
+ 		if (err)
+ 			goto err;
+@@ -673,6 +679,13 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
+ 	struct mlx4_ib_qp *qp;
+ 	int err;
+ 
++	/* We only support LSO, and only for kernel UD QPs. */
++	if (init_attr->create_flags & ~IB_QP_CREATE_IPOIB_UD_LSO)
++		return ERR_PTR(-EINVAL);
++	if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO &&
++	    (pd->uobject || init_attr->qp_type != IB_QPT_UD))
++		return ERR_PTR(-EINVAL);
++
+ 	switch (init_attr->qp_type) {
+ 	case IB_QPT_RC:
+ 	case IB_QPT_UC:
+@@ -876,10 +889,15 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
+ 		}
+ 	}
+ 
+-	if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI ||
+-	    ibqp->qp_type == IB_QPT_UD)
++	if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI)
+ 		context->mtu_msgmax = (IB_MTU_4096 << 5) | 11;
+-	else if (attr_mask & IB_QP_PATH_MTU) {
++	else if (ibqp->qp_type == IB_QPT_UD) {
++		if (qp->flags & MLX4_IB_QP_LSO)
++			context->mtu_msgmax = (IB_MTU_4096 << 5) |
++					      ilog2(dev->dev->caps.max_gso_sz);
++		else
++			context->mtu_msgmax = (IB_MTU_4096 << 5) | 11;
++	} else if (attr_mask & IB_QP_PATH_MTU) {
+ 		if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_4096) {
+ 			printk(KERN_ERR "path MTU (%u) is invalid\n",
+ 			       attr->path_mtu);
+@@ -1182,7 +1200,7 @@ out:
+ }
+ 
+ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
+-			    void *wqe)
++			    void *wqe, unsigned *mlx_seg_len)
+ {
+ 	struct ib_device *ib_dev = &to_mdev(sqp->qp.ibqp.device)->ib_dev;
+ 	struct mlx4_wqe_mlx_seg *mlx = wqe;
+@@ -1231,7 +1249,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
+ 	case IB_WR_SEND_WITH_IMM:
+ 		sqp->ud_header.bth.opcode	 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
+ 		sqp->ud_header.immediate_present = 1;
+-		sqp->ud_header.immediate_data    = wr->imm_data;
++		sqp->ud_header.immediate_data    = wr->ex.imm_data;
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -1303,7 +1321,9 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
+ 		i = 2;
+ 	}
+ 
+-	return ALIGN(i * sizeof (struct mlx4_wqe_inline_seg) + header_size, 16);
++	*mlx_seg_len =
++		ALIGN(i * sizeof (struct mlx4_wqe_inline_seg) + header_size, 16);
++	return 0;
+ }
+ 
+ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq)
+@@ -1396,6 +1416,34 @@ static void __set_data_seg(struct mlx4_wqe_data_seg *dseg, struct ib_sge *sg)
+ 	dseg->addr       = cpu_to_be64(sg->addr);
+ }
+ 
++static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
++			 struct mlx4_ib_qp *qp, unsigned *lso_seg_len)
++{
++	unsigned halign = ALIGN(sizeof *wqe + wr->wr.ud.hlen, 16);
++
++	/*
++	 * This is a temporary limitation and will be removed in
++	 * a forthcoming FW release:
++	 */
++	if (unlikely(halign > 64))
++		return -EINVAL;
++
++	if (unlikely(!(qp->flags & MLX4_IB_QP_LSO) &&
++		     wr->num_sge > qp->sq.max_gs - (halign >> 4)))
++		return -EINVAL;
++
++	memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
++
++	/* make sure LSO header is written before overwriting stamping */
++	wmb();
++
++	wqe->mss_hdr_size = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
++					wr->wr.ud.hlen);
++
++	*lso_seg_len = halign;
++	return 0;
++}
++
+ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ 		      struct ib_send_wr **bad_wr)
+ {
+@@ -1409,6 +1457,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ 	unsigned ind;
+ 	int uninitialized_var(stamp);
+ 	int uninitialized_var(size);
++	unsigned seglen;
+ 	int i;
+ 
+ 	spin_lock_irqsave(&qp->sq.lock, flags);
+@@ -1436,11 +1485,14 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ 			 cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE) : 0) |
+ 			(wr->send_flags & IB_SEND_SOLICITED ?
+ 			 cpu_to_be32(MLX4_WQE_CTRL_SOLICITED) : 0) |
++			((wr->send_flags & IB_SEND_IP_CSUM) ?
++			 cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM |
++				     MLX4_WQE_CTRL_TCP_UDP_CSUM) : 0) |
+ 			qp->sq_signal_bits;
+ 
+ 		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+ 		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+-			ctrl->imm = wr->imm_data;
++			ctrl->imm = wr->ex.imm_data;
+ 		else
+ 			ctrl->imm = 0;
+ 
+@@ -1484,19 +1536,27 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ 			set_datagram_seg(wqe, wr);
+ 			wqe  += sizeof (struct mlx4_wqe_datagram_seg);
+ 			size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
++
++			if (wr->opcode == IB_WR_LSO) {
++				err = build_lso_seg(wqe, wr, qp, &seglen);
++				if (unlikely(err)) {
++					*bad_wr = wr;
++					goto out;
++				}
++				wqe  += seglen;
++				size += seglen / 16;
++			}
+ 			break;
+ 
+ 		case IB_QPT_SMI:
+ 		case IB_QPT_GSI:
+-			err = build_mlx_header(to_msqp(qp), wr, ctrl);
+-			if (err < 0) {
++			err = build_mlx_header(to_msqp(qp), wr, ctrl, &seglen);
++			if (unlikely(err)) {
+ 				*bad_wr = wr;
+ 				goto out;
+ 			}
+-			wqe  += err;
+-			size += err / 16;
+-
+-			err = 0;
++			wqe  += seglen;
++			size += seglen / 16;
+ 			break;
+ 
+ 		default:
+@@ -1725,7 +1785,9 @@ int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr
+ 	struct mlx4_ib_qp *qp = to_mqp(ibqp);
+ 	struct mlx4_qp_context context;
+ 	int mlx4_state;
+-	int err;
++	int err = 0;
++
++	mutex_lock(&qp->mutex);
+ 
+ 	if (qp->state == IB_QPS_RESET) {
+ 		qp_attr->qp_state = IB_QPS_RESET;
+@@ -1733,12 +1795,15 @@ int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr
+ 	}
+ 
+ 	err = mlx4_qp_query(dev->dev, &qp->mqp, &context);
+-	if (err)
+-		return -EINVAL;
++	if (err) {
++		err = -EINVAL;
++		goto out;
++	}
+ 
+ 	mlx4_state = be32_to_cpu(context.flags) >> 28;
+ 
+-	qp_attr->qp_state	     = to_ib_qp_state(mlx4_state);
++	qp->state		     = to_ib_qp_state(mlx4_state);
++	qp_attr->qp_state	     = qp->state;
+ 	qp_attr->path_mtu	     = context.mtu_msgmax >> 5;
+ 	qp_attr->path_mig_state	     =
+ 		to_ib_mig_state((be32_to_cpu(context.flags) >> 11) & 0x3);
+@@ -1797,6 +1862,8 @@ done:
+ 
+ 	qp_init_attr->cap	     = qp_attr->cap;
+ 
+-	return 0;
++out:
++	mutex_unlock(&qp->mutex);
++	return err;
+ }
+ 
+diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
+index 09a30dd..54d230e 100644
+--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
++++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
+@@ -219,7 +219,7 @@ static void mthca_cmd_post_dbell(struct mthca_dev *dev,
+ 	__raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT)                |
+ 					       (1 << HCA_E_BIT)                 |
+ 					       (op_modifier << HCR_OPMOD_SHIFT) |
+-					        op),                      ptr + offs[6]);
++						op),			  ptr + offs[6]);
+ 	wmb();
+ 	__raw_writel((__force u32) 0,                                     ptr + offs[7]);
+ 	wmb();
+@@ -1339,6 +1339,10 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
+ 	/* Check port for UD address vector: */
+ 	*(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1);
+ 
++	/* Enable IPoIB checksumming if we can: */
++	if (dev->device_cap_flags & IB_DEVICE_UD_IP_CSUM)
++		*(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(7 << 3);
++
+ 	/* We leave wqe_quota, responder_exu, etc as 0 (default) */
+ 
+ 	/* QPC/EEC/CQC/EQC/RDB attributes */
+diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
+index 2f976f2..8928ca4 100644
+--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
++++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
+@@ -103,6 +103,7 @@ enum {
+ 	DEV_LIM_FLAG_RAW_IPV6           = 1 << 4,
+ 	DEV_LIM_FLAG_RAW_ETHER          = 1 << 5,
+ 	DEV_LIM_FLAG_SRQ                = 1 << 6,
++	DEV_LIM_FLAG_IPOIB_CSUM		= 1 << 7,
+ 	DEV_LIM_FLAG_BAD_PKEY_CNTR      = 1 << 8,
+ 	DEV_LIM_FLAG_BAD_QKEY_CNTR      = 1 << 9,
+ 	DEV_LIM_FLAG_MW                 = 1 << 16,
+diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
+index 1e1e336..20401d2 100644
+--- a/drivers/infiniband/hw/mthca/mthca_cq.c
++++ b/drivers/infiniband/hw/mthca/mthca_cq.c
+@@ -119,7 +119,8 @@ struct mthca_cqe {
+ 	__be32 my_qpn;
+ 	__be32 my_ee;
+ 	__be32 rqpn;
+-	__be16 sl_g_mlpath;
++	u8     sl_ipok;
++	u8     g_mlpath;
+ 	__be16 rlid;
+ 	__be32 imm_etype_pkey_eec;
+ 	__be32 byte_cnt;
+@@ -493,6 +494,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
+ 	int is_send;
+ 	int free_cqe = 1;
+ 	int err = 0;
++	u16 checksum;
+ 
+ 	cqe = next_cqe_sw(cq);
+ 	if (!cqe)
+@@ -635,12 +637,14 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
+ 			break;
+ 		}
+ 		entry->slid 	   = be16_to_cpu(cqe->rlid);
+-		entry->sl   	   = be16_to_cpu(cqe->sl_g_mlpath) >> 12;
++		entry->sl   	   = cqe->sl_ipok >> 4;
+ 		entry->src_qp 	   = be32_to_cpu(cqe->rqpn) & 0xffffff;
+-		entry->dlid_path_bits = be16_to_cpu(cqe->sl_g_mlpath) & 0x7f;
++		entry->dlid_path_bits = cqe->g_mlpath & 0x7f;
+ 		entry->pkey_index  = be32_to_cpu(cqe->imm_etype_pkey_eec) >> 16;
+-		entry->wc_flags   |= be16_to_cpu(cqe->sl_g_mlpath) & 0x80 ?
+-					IB_WC_GRH : 0;
++		entry->wc_flags   |= cqe->g_mlpath & 0x80 ? IB_WC_GRH : 0;
++		checksum = (be32_to_cpu(cqe->rqpn) >> 24) |
++				((be32_to_cpu(cqe->my_ee) >> 16) & 0xff00);
++		entry->csum_ok = (cqe->sl_ipok & 1 && checksum == 0xffff);
+ 	}
+ 
+ 	entry->status = IB_WC_SUCCESS;
+diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
+index 7bbdd1f..7bc32f8 100644
+--- a/drivers/infiniband/hw/mthca/mthca_dev.h
++++ b/drivers/infiniband/hw/mthca/mthca_dev.h
+@@ -46,16 +46,15 @@
+ #include <linux/timer.h>
+ #include <linux/mutex.h>
+ #include <linux/list.h>
+-
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ 
+ #include "mthca_provider.h"
+ #include "mthca_doorbell.h"
+ 
+ #define DRV_NAME	"ib_mthca"
+ #define PFX		DRV_NAME ": "
+-#define DRV_VERSION	"0.08"
+-#define DRV_RELDATE	"February 14, 2006"
++#define DRV_VERSION	"1.0"
++#define DRV_RELDATE	"April 4, 2008"
+ 
+ enum {
+ 	MTHCA_FLAG_DDR_HIDDEN = 1 << 1,
+@@ -390,11 +389,11 @@ extern void __buggy_use_of_MTHCA_PUT(void);
+ 	do {                                                          \
+ 		void *__p = (char *) (source) + (offset);             \
+ 		switch (sizeof (dest)) {                              \
+-			case 1: (dest) = *(u8 *) __p;       break;    \
+-			case 2: (dest) = be16_to_cpup(__p); break;    \
+-			case 4: (dest) = be32_to_cpup(__p); break;    \
+-			case 8: (dest) = be64_to_cpup(__p); break;    \
+-			default: __buggy_use_of_MTHCA_GET();          \
++		case 1: (dest) = *(u8 *) __p;       break;	      \
++		case 2: (dest) = be16_to_cpup(__p); break;	      \
++		case 4: (dest) = be32_to_cpup(__p); break;	      \
++		case 8: (dest) = be64_to_cpup(__p); break;	      \
++		default: __buggy_use_of_MTHCA_GET();		      \
+ 		}                                                     \
+ 	} while (0)
+ 
+diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
+index b60eb5d..8bde7f9 100644
+--- a/drivers/infiniband/hw/mthca/mthca_eq.c
++++ b/drivers/infiniband/hw/mthca/mthca_eq.c
+@@ -232,9 +232,9 @@ static inline struct mthca_eqe *get_eqe(struct mthca_eq *eq, u32 entry)
+ 	return eq->page_list[off / PAGE_SIZE].buf + off % PAGE_SIZE;
+ }
+ 
+-static inline struct mthca_eqe* next_eqe_sw(struct mthca_eq *eq)
++static inline struct mthca_eqe *next_eqe_sw(struct mthca_eq *eq)
+ {
+-	struct mthca_eqe* eqe;
++	struct mthca_eqe *eqe;
+ 	eqe = get_eqe(eq, eq->cons_index);
+ 	return (MTHCA_EQ_ENTRY_OWNER_HW & eqe->owner) ? NULL : eqe;
+ }
+diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
+index acfa41d..8b7e83e 100644
+--- a/drivers/infiniband/hw/mthca/mthca_mad.c
++++ b/drivers/infiniband/hw/mthca/mthca_mad.c
+@@ -125,7 +125,7 @@ static void smp_snoop(struct ib_device *ibdev,
+ 			event.device           = ibdev;
+ 			event.element.port_num = port_num;
+ 
+-			if(pinfo->clientrereg_resv_subnetto & 0x80)
++			if (pinfo->clientrereg_resv_subnetto & 0x80)
+ 				event.event    = IB_EVENT_CLIENT_REREGISTER;
+ 			else
+ 				event.event    = IB_EVENT_LID_CHANGE;
+diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
+index cd3d8ad..9ebadd6 100644
+--- a/drivers/infiniband/hw/mthca/mthca_main.c
++++ b/drivers/infiniband/hw/mthca/mthca_main.c
+@@ -267,11 +267,16 @@ static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
+ 	if (dev_lim->flags & DEV_LIM_FLAG_SRQ)
+ 		mdev->mthca_flags |= MTHCA_FLAG_SRQ;
+ 
++	if (mthca_is_memfree(mdev))
++		if (dev_lim->flags & DEV_LIM_FLAG_IPOIB_CSUM)
++			mdev->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
++
+ 	return 0;
+ }
+ 
+ static int mthca_init_tavor(struct mthca_dev *mdev)
+ {
++	s64 size;
+ 	u8 status;
+ 	int err;
+ 	struct mthca_dev_lim        dev_lim;
+@@ -324,9 +329,11 @@ static int mthca_init_tavor(struct mthca_dev *mdev)
+ 	if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ 		profile.num_srq = dev_lim.max_srqs;
+ 
+-	err = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
+-	if (err < 0)
++	size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
++	if (size < 0) {
++		err = size;
+ 		goto err_disable;
++	}
+ 
+ 	err = mthca_INIT_HCA(mdev, &init_hca, &status);
+ 	if (err) {
+@@ -605,7 +612,7 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
+ 	struct mthca_dev_lim        dev_lim;
+ 	struct mthca_profile        profile;
+ 	struct mthca_init_hca_param init_hca;
+-	u64 icm_size;
++	s64 icm_size;
+ 	u8 status;
+ 	int err;
+ 
+@@ -653,7 +660,7 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
+ 		profile.num_srq = dev_lim.max_srqs;
+ 
+ 	icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
+-	if ((int) icm_size < 0) {
++	if (icm_size < 0) {
+ 		err = icm_size;
+ 		goto err_stop_fw;
+ 	}
+diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
+index 252db08..b224079 100644
+--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
++++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
+@@ -359,12 +359,14 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
+ 					      int use_lowmem, int use_coherent)
+ {
+ 	struct mthca_icm_table *table;
++	int obj_per_chunk;
+ 	int num_icm;
+ 	unsigned chunk_size;
+ 	int i;
+ 	u8 status;
+ 
+-	num_icm = (obj_size * nobj + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE;
++	obj_per_chunk = MTHCA_TABLE_CHUNK_SIZE / obj_size;
++	num_icm = DIV_ROUND_UP(nobj, obj_per_chunk);
+ 
+ 	table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL);
+ 	if (!table)
+@@ -412,7 +414,7 @@ err:
+ 		if (table->icm[i]) {
+ 			mthca_UNMAP_ICM(dev, virt + i * MTHCA_TABLE_CHUNK_SIZE,
+ 					MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
+-				        &status);
++					&status);
+ 			mthca_free_icm(dev, table->icm[i], table->coherent);
+ 		}
+ 
+diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
+index 26bf86d..605a8d5 100644
+--- a/drivers/infiniband/hw/mthca/mthca_profile.c
++++ b/drivers/infiniband/hw/mthca/mthca_profile.c
+@@ -63,7 +63,7 @@ enum {
+ 	MTHCA_NUM_PDS = 1 << 15
+ };
+ 
+-u64 mthca_make_profile(struct mthca_dev *dev,
++s64 mthca_make_profile(struct mthca_dev *dev,
+ 		       struct mthca_profile *request,
+ 		       struct mthca_dev_lim *dev_lim,
+ 		       struct mthca_init_hca_param *init_hca)
+@@ -77,7 +77,7 @@ u64 mthca_make_profile(struct mthca_dev *dev,
+ 	};
+ 
+ 	u64 mem_base, mem_avail;
+-	u64 total_size = 0;
++	s64 total_size = 0;
+ 	struct mthca_resource *profile;
+ 	struct mthca_resource tmp;
+ 	int i, j;
+diff --git a/drivers/infiniband/hw/mthca/mthca_profile.h b/drivers/infiniband/hw/mthca/mthca_profile.h
+index 9464180..e76cb62 100644
+--- a/drivers/infiniband/hw/mthca/mthca_profile.h
++++ b/drivers/infiniband/hw/mthca/mthca_profile.h
+@@ -53,7 +53,7 @@ struct mthca_profile {
+ 	int fmr_reserved_mtts;
+ };
+ 
+-u64 mthca_make_profile(struct mthca_dev *mdev,
++s64 mthca_make_profile(struct mthca_dev *mdev,
+ 		       struct mthca_profile *request,
+ 		       struct mthca_dev_lim *dev_lim,
+ 		       struct mthca_init_hca_param *init_hca);
+diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
+index 9e491df..696e1f3 100644
+--- a/drivers/infiniband/hw/mthca/mthca_provider.c
++++ b/drivers/infiniband/hw/mthca/mthca_provider.c
+@@ -60,7 +60,7 @@ static int mthca_query_device(struct ib_device *ibdev,
+ 	struct ib_smp *in_mad  = NULL;
+ 	struct ib_smp *out_mad = NULL;
+ 	int err = -ENOMEM;
+-	struct mthca_dev* mdev = to_mdev(ibdev);
++	struct mthca_dev *mdev = to_mdev(ibdev);
+ 
+ 	u8 status;
+ 
+@@ -540,6 +540,9 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
+ 	struct mthca_qp *qp;
+ 	int err;
+ 
++	if (init_attr->create_flags)
++		return ERR_PTR(-EINVAL);
++
+ 	switch (init_attr->qp_type) {
+ 	case IB_QPT_RC:
+ 	case IB_QPT_UC:
+@@ -1167,23 +1170,29 @@ static int mthca_unmap_fmr(struct list_head *fmr_list)
+ 	return 0;
+ }
+ 
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *device, struct device_attribute *attr,
++			char *buf)
+ {
+-	struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
++	struct mthca_dev *dev =
++		container_of(device, struct mthca_dev, ib_dev.dev);
+ 	return sprintf(buf, "%x\n", dev->rev_id);
+ }
+ 
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
++			   char *buf)
+ {
+-	struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
++	struct mthca_dev *dev =
++		container_of(device, struct mthca_dev, ib_dev.dev);
+ 	return sprintf(buf, "%d.%d.%d\n", (int) (dev->fw_ver >> 32),
+ 		       (int) (dev->fw_ver >> 16) & 0xffff,
+ 		       (int) dev->fw_ver & 0xffff);
+ }
+ 
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *device, struct device_attribute *attr,
++			char *buf)
+ {
+-	struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
++	struct mthca_dev *dev =
++		container_of(device, struct mthca_dev, ib_dev.dev);
+ 	switch (dev->pdev->device) {
+ 	case PCI_DEVICE_ID_MELLANOX_TAVOR:
+ 		return sprintf(buf, "MT23108\n");
+@@ -1199,22 +1208,24 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
+ 	}
+ }
+ 
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *device, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
++	struct mthca_dev *dev =
++		container_of(device, struct mthca_dev, ib_dev.dev);
+ 	return sprintf(buf, "%.*s\n", MTHCA_BOARD_ID_LEN, dev->board_id);
+ }
+ 
+-static CLASS_DEVICE_ATTR(hw_rev,   S_IRUGO, show_rev,    NULL);
+-static CLASS_DEVICE_ATTR(fw_ver,   S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca,    NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board,  NULL);
++static DEVICE_ATTR(hw_rev,   S_IRUGO, show_rev,    NULL);
++static DEVICE_ATTR(fw_ver,   S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca,    NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board,  NULL);
+ 
+-static struct class_device_attribute *mthca_class_attributes[] = {
+-	&class_device_attr_hw_rev,
+-	&class_device_attr_fw_ver,
+-	&class_device_attr_hca_type,
+-	&class_device_attr_board_id
++static struct device_attribute *mthca_dev_attributes[] = {
++	&dev_attr_hw_rev,
++	&dev_attr_fw_ver,
++	&dev_attr_hca_type,
++	&dev_attr_board_id
+ };
+ 
+ static int mthca_init_node_data(struct mthca_dev *dev)
+@@ -1376,9 +1387,9 @@ int mthca_register_device(struct mthca_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
+-	for (i = 0; i < ARRAY_SIZE(mthca_class_attributes); ++i) {
+-		ret = class_device_create_file(&dev->ib_dev.class_dev,
+-					       mthca_class_attributes[i]);
++	for (i = 0; i < ARRAY_SIZE(mthca_dev_attributes); ++i) {
++		ret = device_create_file(&dev->ib_dev.dev,
++					 mthca_dev_attributes[i]);
+ 		if (ret) {
+ 			ib_unregister_device(&dev->ib_dev);
+ 			return ret;
+diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
+index db5595b..09dc361 100644
+--- a/drivers/infiniband/hw/mthca/mthca_qp.c
++++ b/drivers/infiniband/hw/mthca/mthca_qp.c
+@@ -437,29 +437,34 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
+ 	int mthca_state;
+ 	u8 status;
+ 
++	mutex_lock(&qp->mutex);
++
+ 	if (qp->state == IB_QPS_RESET) {
+ 		qp_attr->qp_state = IB_QPS_RESET;
+ 		goto done;
+ 	}
+ 
+ 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
+-	if (IS_ERR(mailbox))
+-		return PTR_ERR(mailbox);
++	if (IS_ERR(mailbox)) {
++		err = PTR_ERR(mailbox);
++		goto out;
++	}
+ 
+ 	err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox, &status);
+ 	if (err)
+-		goto out;
++		goto out_mailbox;
+ 	if (status) {
+ 		mthca_warn(dev, "QUERY_QP returned status %02x\n", status);
+ 		err = -EINVAL;
+-		goto out;
++		goto out_mailbox;
+ 	}
+ 
+ 	qp_param    = mailbox->buf;
+ 	context     = &qp_param->context;
+ 	mthca_state = be32_to_cpu(context->flags) >> 28;
+ 
+-	qp_attr->qp_state 	     = to_ib_qp_state(mthca_state);
++	qp->state		     = to_ib_qp_state(mthca_state);
++	qp_attr->qp_state	     = qp->state;
+ 	qp_attr->path_mtu 	     = context->mtu_msgmax >> 5;
+ 	qp_attr->path_mig_state      =
+ 		to_ib_mig_state((be32_to_cpu(context->flags) >> 11) & 0x3);
+@@ -506,8 +511,11 @@ done:
+ 
+ 	qp_init_attr->cap	     = qp_attr->cap;
+ 
+-out:
++out_mailbox:
+ 	mthca_free_mailbox(dev, mailbox);
++
++out:
++	mutex_unlock(&qp->mutex);
+ 	return err;
+ }
+ 
+@@ -1532,7 +1540,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
+ 	case IB_WR_SEND_WITH_IMM:
+ 		sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
+ 		sqp->ud_header.immediate_present = 1;
+-		sqp->ud_header.immediate_data = wr->imm_data;
++		sqp->ud_header.immediate_data = wr->ex.imm_data;
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -1679,7 +1687,7 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ 			cpu_to_be32(1);
+ 		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+ 		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+-			((struct mthca_next_seg *) wqe)->imm = wr->imm_data;
++			((struct mthca_next_seg *) wqe)->imm = wr->ex.imm_data;
+ 
+ 		wqe += sizeof (struct mthca_next_seg);
+ 		size = sizeof (struct mthca_next_seg) / 16;
+@@ -2015,10 +2023,12 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ 			 cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0) |
+ 			((wr->send_flags & IB_SEND_SOLICITED) ?
+ 			 cpu_to_be32(MTHCA_NEXT_SOLICIT) : 0)   |
++			((wr->send_flags & IB_SEND_IP_CSUM) ?
++			 cpu_to_be32(MTHCA_NEXT_IP_CSUM | MTHCA_NEXT_TCP_UDP_CSUM) : 0) |
+ 			cpu_to_be32(1);
+ 		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+ 		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+-			((struct mthca_next_seg *) wqe)->imm = wr->imm_data;
++			((struct mthca_next_seg *) wqe)->imm = wr->ex.imm_data;
+ 
+ 		wqe += sizeof (struct mthca_next_seg);
+ 		size = sizeof (struct mthca_next_seg) / 16;
+diff --git a/drivers/infiniband/hw/mthca/mthca_wqe.h b/drivers/infiniband/hw/mthca/mthca_wqe.h
+index f6a66fe..b3551a8 100644
+--- a/drivers/infiniband/hw/mthca/mthca_wqe.h
++++ b/drivers/infiniband/hw/mthca/mthca_wqe.h
+@@ -38,14 +38,16 @@
+ #include <linux/types.h>
+ 
+ enum {
+-	MTHCA_NEXT_DBD       = 1 << 7,
+-	MTHCA_NEXT_FENCE     = 1 << 6,
+-	MTHCA_NEXT_CQ_UPDATE = 1 << 3,
+-	MTHCA_NEXT_EVENT_GEN = 1 << 2,
+-	MTHCA_NEXT_SOLICIT   = 1 << 1,
+-
+-	MTHCA_MLX_VL15       = 1 << 17,
+-	MTHCA_MLX_SLR        = 1 << 16
++	MTHCA_NEXT_DBD		= 1 << 7,
++	MTHCA_NEXT_FENCE	= 1 << 6,
++	MTHCA_NEXT_CQ_UPDATE	= 1 << 3,
++	MTHCA_NEXT_EVENT_GEN	= 1 << 2,
++	MTHCA_NEXT_SOLICIT	= 1 << 1,
++	MTHCA_NEXT_IP_CSUM	= 1 << 4,
++	MTHCA_NEXT_TCP_UDP_CSUM = 1 << 5,
++
++	MTHCA_MLX_VL15		= 1 << 17,
++	MTHCA_MLX_SLR		= 1 << 16
+ };
+ 
+ enum {
+diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
+index b2112f5..b046262 100644
+--- a/drivers/infiniband/hw/nes/nes.c
++++ b/drivers/infiniband/hw/nes/nes.c
+@@ -65,7 +65,6 @@ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_VERSION(DRV_VERSION);
+ 
+ int max_mtu = 9000;
+-int nics_per_function = 1;
+ int interrupt_mod_interval = 0;
+ 
+ 
+@@ -93,22 +92,10 @@ module_param_named(debug_level, nes_debug_level, uint, 0644);
+ MODULE_PARM_DESC(debug_level, "Enable debug output level");
+ 
+ LIST_HEAD(nes_adapter_list);
+-LIST_HEAD(nes_dev_list);
++static LIST_HEAD(nes_dev_list);
+ 
+ atomic_t qps_destroyed;
+-atomic_t cqp_reqs_allocated;
+-atomic_t cqp_reqs_freed;
+-atomic_t cqp_reqs_dynallocated;
+-atomic_t cqp_reqs_dynfreed;
+-atomic_t cqp_reqs_queued;
+-atomic_t cqp_reqs_redriven;
+-
+-static void nes_print_macaddr(struct net_device *netdev);
+-static irqreturn_t nes_interrupt(int, void *);
+-static int __devinit nes_probe(struct pci_dev *, const struct pci_device_id *);
+-static void __devexit nes_remove(struct pci_dev *);
+-static int __init nes_init_module(void);
+-static void __exit nes_exit_module(void);
++
+ static unsigned int ee_flsh_adapter;
+ static unsigned int sysfs_nonidx_addr;
+ static unsigned int sysfs_idx_addr;
+@@ -310,7 +297,7 @@ void nes_rem_ref(struct ib_qp *ibqp)
+ 
+ 	if (atomic_read(&nesqp->refcount) == 0) {
+ 		printk(KERN_INFO PFX "%s: Reference count already 0 for QP%d, last aeq = 0x%04X.\n",
+-				__FUNCTION__, ibqp->qp_num, nesqp->last_aeq);
++				__func__, ibqp->qp_num, nesqp->last_aeq);
+ 		BUG();
+ 	}
+ 
+@@ -751,13 +738,13 @@ static void __devexit nes_remove(struct pci_dev *pcidev)
+ 
+ 	list_del(&nesdev->list);
+ 	nes_destroy_cqp(nesdev);
++
++	free_irq(pcidev->irq, nesdev);
+ 	tasklet_kill(&nesdev->dpc_tasklet);
+ 
+ 	/* Deallocate the Adapter Structure */
+ 	nes_destroy_adapter(nesdev->nesadapter);
+ 
+-	free_irq(pcidev->irq, nesdev);
+-
+ 	if (nesdev->msi_enabled) {
+ 		pci_disable_msi(pcidev);
+ 	}
+diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
+index a48b288..cdf2e9a 100644
+--- a/drivers/infiniband/hw/nes/nes.h
++++ b/drivers/infiniband/hw/nes/nes.h
+@@ -43,7 +43,6 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/workqueue.h>
+ #include <linux/slab.h>
+-#include <asm/semaphore.h>
+ #include <linux/version.h>
+ #include <asm/io.h>
+ #include <linux/crc32c.h>
+@@ -143,12 +142,12 @@
+ #ifdef CONFIG_INFINIBAND_NES_DEBUG
+ #define nes_debug(level, fmt, args...) \
+ 	if (level & nes_debug_level) \
+-		printk(KERN_ERR PFX "%s[%u]: " fmt, __FUNCTION__, __LINE__, ##args)
++		printk(KERN_ERR PFX "%s[%u]: " fmt, __func__, __LINE__, ##args)
+ 
+ #define assert(expr)                                                \
+ if (!(expr)) {                                                       \
+ 	printk(KERN_ERR PFX "Assertion failed! %s, %s, %s, line %d\n",  \
+-		   #expr, __FILE__, __FUNCTION__, __LINE__);                \
++		   #expr, __FILE__, __func__, __LINE__);                \
+ }
+ 
+ #define NES_EVENT_TIMEOUT   1200000
+@@ -166,7 +165,6 @@ if (!(expr)) {                                                       \
+ #include "nes_cm.h"
+ 
+ extern int max_mtu;
+-extern int nics_per_function;
+ #define max_frame_len (max_mtu+ETH_HLEN)
+ extern int interrupt_mod_interval;
+ extern int nes_if_count;
+@@ -177,9 +175,6 @@ extern unsigned int nes_drv_opt;
+ extern unsigned int nes_debug_level;
+ 
+ extern struct list_head nes_adapter_list;
+-extern struct list_head nes_dev_list;
+-
+-extern struct nes_cm_core *g_cm_core;
+ 
+ extern atomic_t cm_connects;
+ extern atomic_t cm_accepts;
+@@ -209,7 +204,6 @@ extern atomic_t cm_nodes_destroyed;
+ extern atomic_t cm_accel_dropped_pkts;
+ extern atomic_t cm_resets_recvd;
+ 
+-extern u32 crit_err_count;
+ extern u32 int_mod_timer_init;
+ extern u32 int_mod_cq_depth_256;
+ extern u32 int_mod_cq_depth_128;
+@@ -219,14 +213,6 @@ extern u32 int_mod_cq_depth_16;
+ extern u32 int_mod_cq_depth_4;
+ extern u32 int_mod_cq_depth_1;
+ 
+-extern atomic_t cqp_reqs_allocated;
+-extern atomic_t cqp_reqs_freed;
+-extern atomic_t cqp_reqs_dynallocated;
+-extern atomic_t cqp_reqs_dynfreed;
+-extern atomic_t cqp_reqs_queued;
+-extern atomic_t cqp_reqs_redriven;
+-
+-
+ struct nes_device {
+ 	struct nes_adapter	   *nesadapter;
+ 	void __iomem           *regs;
+@@ -412,7 +398,7 @@ static inline int nes_alloc_resource(struct nes_adapter *nesadapter,
+ 	if (resource_num >= max_resources) {
+ 		resource_num = find_first_zero_bit(resource_array, max_resources);
+ 		if (resource_num >= max_resources) {
+-			printk(KERN_ERR PFX "%s: No available resourcess.\n", __FUNCTION__);
++			printk(KERN_ERR PFX "%s: No available resourcess.\n", __func__);
+ 			spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
+ 			return -EMFILE;
+ 		}
+@@ -510,9 +496,6 @@ struct ib_qp *nes_get_qp(struct ib_device *, int);
+ /* nes_hw.c */
+ struct nes_adapter *nes_init_adapter(struct nes_device *, u8);
+ void  nes_nic_init_timer_defaults(struct nes_device *, u8);
+-unsigned int nes_reset_adapter_ne020(struct nes_device *, u8 *);
+-int nes_init_serdes(struct nes_device *, u8, u8, u8);
+-void nes_init_csr_ne020(struct nes_device *, u8, u8);
+ void nes_destroy_adapter(struct nes_adapter *);
+ int nes_init_cqp(struct nes_device *);
+ int nes_init_phy(struct nes_device *);
+@@ -520,20 +503,12 @@ int nes_init_nic_qp(struct nes_device *, struct net_device *);
+ void nes_destroy_nic_qp(struct nes_vnic *);
+ int nes_napi_isr(struct nes_device *);
+ void nes_dpc(unsigned long);
+-void nes_process_ceq(struct nes_device *, struct nes_hw_ceq *);
+-void nes_process_aeq(struct nes_device *, struct nes_hw_aeq *);
+-void nes_process_mac_intr(struct nes_device *, u32);
+-void nes_nic_napi_ce_handler(struct nes_device *, struct nes_hw_nic_cq *);
+ void nes_nic_ce_handler(struct nes_device *, struct nes_hw_nic_cq *);
+-void nes_cqp_ce_handler(struct nes_device *, struct nes_hw_cq *);
+-void nes_process_iwarp_aeqe(struct nes_device *, struct nes_hw_aeqe *);
+ void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *);
+ int nes_destroy_cqp(struct nes_device *);
+ int nes_nic_cm_xmit(struct sk_buff *, struct net_device *);
+ 
+ /* nes_nic.c */
+-void nes_netdev_set_multicast_list(struct net_device *);
+-void nes_netdev_exit(struct nes_vnic *);
+ struct net_device *nes_netdev_init(struct nes_device *, void __iomem *);
+ void nes_netdev_destroy(struct net_device *);
+ int nes_nic_cm_xmit(struct sk_buff *, struct net_device *);
+@@ -544,7 +519,6 @@ int nes_cm_recv(struct sk_buff *, struct net_device *);
+ void nes_update_arp(unsigned char *, u32, u32, u16, u16);
+ void nes_manage_arp_cache(struct net_device *, unsigned char *, u32, u32);
+ void nes_sock_release(struct nes_qp *, unsigned long *);
+-struct nes_cm_core *nes_cm_alloc_core(void);
+ void flush_wqes(struct nes_device *nesdev, struct nes_qp *, u32, u32);
+ int nes_manage_apbvt(struct nes_vnic *, u32, u32, u32);
+ int nes_cm_disconn(struct nes_qp *);
+@@ -556,7 +530,6 @@ int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *);
+ struct nes_ib_device *nes_init_ofa_device(struct net_device *);
+ void nes_destroy_ofa_device(struct nes_ib_device *);
+ int nes_register_ofa_device(struct nes_ib_device *);
+-void nes_unregister_ofa_device(struct nes_ib_device *);
+ 
+ /* nes_util.c */
+ int nes_read_eeprom_values(struct nes_device *, struct nes_adapter *);
+diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
+index 0bef878..d073862 100644
+--- a/drivers/infiniband/hw/nes/nes_cm.c
++++ b/drivers/infiniband/hw/nes/nes_cm.c
+@@ -80,7 +80,30 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
+ static int add_ref_cm_node(struct nes_cm_node *);
+ static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
+ static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
+-
++static struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *,
++				     void *, u32, void *, u32, u8);
++static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node);
++
++static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *,
++					   struct nes_vnic *,
++					   struct ietf_mpa_frame *,
++					   struct nes_cm_info *);
++static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
++			  struct nes_cm_node *);
++static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
++			  struct nes_cm_node *);
++static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
++static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
++			    struct sk_buff *);
++static int mini_cm_dealloc_core(struct nes_cm_core *);
++static int mini_cm_get(struct nes_cm_core *);
++static int mini_cm_set(struct nes_cm_core *, u32, u32);
++static int nes_cm_disconn_true(struct nes_qp *);
++static int nes_cm_post_event(struct nes_cm_event *event);
++static int nes_disconnect(struct nes_qp *nesqp, int abrupt);
++static void nes_disconnect_worker(struct work_struct *work);
++static int send_ack(struct nes_cm_node *cm_node);
++static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb);
+ 
+ /* External CM API Interface */
+ /* instance of function pointers for client API */
+@@ -99,7 +122,7 @@ static struct nes_cm_ops nes_cm_api = {
+ 	mini_cm_set
+ };
+ 
+-struct nes_cm_core *g_cm_core;
++static struct nes_cm_core *g_cm_core;
+ 
+ atomic_t cm_connects;
+ atomic_t cm_accepts;
+@@ -149,7 +172,7 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
+ /**
+  * send_mpa_request
+  */
+-int send_mpa_request(struct nes_cm_node *cm_node)
++static int send_mpa_request(struct nes_cm_node *cm_node)
+ {
+ 	struct sk_buff *skb;
+ 	int ret;
+@@ -243,8 +266,9 @@ static int handle_exception_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb
+  * form_cm_frame - get a free packet and build empty frame Use
+  * node info to build.
+  */
+-struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm_node,
+-		void *options, u32 optionsize, void *data, u32 datasize, u8 flags)
++static struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm_node,
++				     void *options, u32 optionsize, void *data,
++				     u32 datasize, u8 flags)
+ {
+ 	struct tcphdr *tcph;
+ 	struct iphdr *iph;
+@@ -342,7 +366,6 @@ static void print_core(struct nes_cm_core *core)
+ 	if (!core)
+ 		return;
+ 	nes_debug(NES_DBG_CM, "---------------------------------------------\n");
+-	nes_debug(NES_DBG_CM, "Session ID    : %u \n", atomic_read(&core->session_id));
+ 
+ 	nes_debug(NES_DBG_CM, "State         : %u \n",  core->state);
+ 
+@@ -395,7 +418,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ 	}
+ 
+ 	if (type == NES_TIMER_TYPE_SEND) {
+-		new_send->seq_num = htonl(tcp_hdr(skb)->seq);
++		new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
+ 		atomic_inc(&new_send->skb->users);
+ 
+ 		ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);
+@@ -420,7 +443,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ 		spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
+ 	}
+ 	if (type == NES_TIMER_TYPE_RECV) {
+-		new_send->seq_num = htonl(tcp_hdr(skb)->seq);
++		new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
+ 		new_send->timetosend = jiffies;
+ 		spin_lock_irqsave(&cm_node->recv_list_lock, flags);
+ 		list_add_tail(&new_send->list, &cm_node->recv_list);
+@@ -442,7 +465,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ /**
+  * nes_cm_timer_tick
+  */
+-void nes_cm_timer_tick(unsigned long pass)
++static void nes_cm_timer_tick(unsigned long pass)
+ {
+ 	unsigned long flags, qplockflags;
+ 	unsigned long nexttimeout = jiffies + NES_LONG_TIME;
+@@ -644,7 +667,7 @@ void nes_cm_timer_tick(unsigned long pass)
+ /**
+  * send_syn
+  */
+-int send_syn(struct nes_cm_node *cm_node, u32 sendack)
++static int send_syn(struct nes_cm_node *cm_node, u32 sendack)
+ {
+ 	int ret;
+ 	int flags = SET_SYN;
+@@ -710,7 +733,7 @@ int send_syn(struct nes_cm_node *cm_node, u32 sendack)
+ /**
+  * send_reset
+  */
+-int send_reset(struct nes_cm_node *cm_node)
++static int send_reset(struct nes_cm_node *cm_node)
+ {
+ 	int ret;
+ 	struct sk_buff *skb = get_free_pkt(cm_node);
+@@ -732,7 +755,7 @@ int send_reset(struct nes_cm_node *cm_node)
+ /**
+  * send_ack
+  */
+-int send_ack(struct nes_cm_node *cm_node)
++static int send_ack(struct nes_cm_node *cm_node)
+ {
+ 	int ret;
+ 	struct sk_buff *skb = get_free_pkt(cm_node);
+@@ -752,7 +775,7 @@ int send_ack(struct nes_cm_node *cm_node)
+ /**
+  * send_fin
+  */
+-int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
++static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
+ {
+ 	int ret;
+ 
+@@ -775,7 +798,7 @@ int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
+ /**
+  * get_free_pkt
+  */
+-struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node)
++static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node)
+ {
+ 	struct sk_buff *skb, *new_skb;
+ 
+@@ -820,7 +843,6 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
+ {
+ 	unsigned long flags;
+ 	u32 hashkey;
+-	struct list_head *list_pos;
+ 	struct list_head *hte;
+ 	struct nes_cm_node *cm_node;
+ 
+@@ -835,8 +857,7 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
+ 
+ 	/* walk list and find cm_node associated with this session ID */
+ 	spin_lock_irqsave(&cm_core->ht_lock, flags);
+-	list_for_each(list_pos, hte) {
+-		cm_node = container_of(list_pos, struct nes_cm_node, list);
++	list_for_each_entry(cm_node, hte, list) {
+ 		/* compare quad, return node handle if a match */
+ 		nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n",
+ 				cm_node->loc_addr, cm_node->loc_port,
+@@ -864,13 +885,11 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
+ 		nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
+ {
+ 	unsigned long flags;
+-	struct list_head *listen_list;
+ 	struct nes_cm_listener *listen_node;
+ 
+ 	/* walk list and find cm_node associated with this session ID */
+ 	spin_lock_irqsave(&cm_core->listen_list_lock, flags);
+-	list_for_each(listen_list, &cm_core->listen_list.list) {
+-		listen_node = container_of(listen_list, struct nes_cm_listener, list);
++	list_for_each_entry(listen_node, &cm_core->listen_list.list, list) {
+ 		/* compare node pair, return node handle if a match */
+ 		if (((listen_node->loc_addr == dst_addr) ||
+ 				listen_node->loc_addr == 0x00000000) &&
+@@ -1014,7 +1033,7 @@ static void nes_addr_send_arp(u32 dst_ip)
+ 	fl.nl_u.ip4_u.daddr = htonl(dst_ip);
+ 	if (ip_route_output_key(&init_net, &rt, &fl)) {
+ 		printk("%s: ip_route_output_key failed for 0x%08X\n",
+-				__FUNCTION__, dst_ip);
++				__func__, dst_ip);
+ 		return;
+ 	}
+ 
+@@ -1077,8 +1096,6 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
+ 	cm_node->tcp_cntxt.rcv_nxt = 0;
+ 	/* get a unique session ID , add thread_id to an upcounter to handle race */
+ 	atomic_inc(&cm_core->node_cnt);
+-	atomic_inc(&cm_core->session_id);
+-	cm_node->session_id = (u32)(atomic_read(&cm_core->session_id) + current->tgid);
+ 	cm_node->conn_type = cm_info->conn_type;
+ 	cm_node->apbvt_set = 0;
+ 	cm_node->accept_pend = 0;
+@@ -1239,7 +1256,7 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 opti
+ 				continue;
+ 			case OPTION_NUMBER_MSS:
+ 				nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d Size: %d\n",
+-						__FUNCTION__,
++						__func__,
+ 						all_options->as_mss.length, offset, optionsize);
+ 				got_mss_option = 1;
+ 				if (all_options->as_mss.length != 4) {
+@@ -1272,8 +1289,8 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 opti
+ /**
+  * process_packet
+  */
+-int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
+-		struct nes_cm_core *cm_core)
++static int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
++			  struct nes_cm_core *cm_core)
+ {
+ 	int optionsize;
+ 	int datasize;
+@@ -1360,7 +1377,7 @@ int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ 	if (optionsize) {
+ 		u8 *optionsloc = (u8 *)&tcph[1];
+ 		if (process_options(cm_node, optionsloc, optionsize, (u32)tcph->syn)) {
+-			nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", __FUNCTION__, cm_node);
++			nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", __func__, cm_node);
+ 			send_reset(cm_node);
+ 			if (cm_node->state != NES_CM_STATE_SYN_SENT)
+ 			rem_ref_cm_node(cm_core, cm_node);
+@@ -1605,9 +1622,7 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
+ 	listener->cm_core = cm_core;
+ 	listener->nesvnic = nesvnic;
+ 	atomic_inc(&cm_core->node_cnt);
+-	atomic_inc(&cm_core->session_id);
+ 
+-	listener->session_id = (u32)(atomic_read(&cm_core->session_id) + current->tgid);
+ 	listener->conn_type = cm_info->conn_type;
+ 	listener->backlog = cm_info->backlog;
+ 	listener->listener_state = NES_CM_LISTENER_ACTIVE_STATE;
+@@ -1631,9 +1646,10 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
+ /**
+  * mini_cm_connect - make a connection node with params
+  */
+-struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
+-		struct nes_vnic *nesvnic, struct ietf_mpa_frame *mpa_frame,
+-		struct nes_cm_info *cm_info)
++static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
++					   struct nes_vnic *nesvnic,
++					   struct ietf_mpa_frame *mpa_frame,
++					   struct nes_cm_info *cm_info)
+ {
+ 	int ret = 0;
+ 	struct nes_cm_node *cm_node;
+@@ -1717,8 +1733,8 @@ struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
+  * mini_cm_accept - accept a connection
+  * This function is never called
+  */
+-int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame,
+-		struct nes_cm_node *cm_node)
++static int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame,
++			  struct nes_cm_node *cm_node)
+ {
+ 	return 0;
+ }
+@@ -1727,9 +1743,9 @@ int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame
+ /**
+  * mini_cm_reject - reject and teardown a connection
+  */
+-int mini_cm_reject(struct nes_cm_core *cm_core,
+-		struct ietf_mpa_frame *mpa_frame,
+-		struct nes_cm_node *cm_node)
++static int mini_cm_reject(struct nes_cm_core *cm_core,
++			  struct ietf_mpa_frame *mpa_frame,
++			  struct nes_cm_node *cm_node)
+ {
+ 	int ret = 0;
+ 	struct sk_buff *skb;
+@@ -1761,7 +1777,7 @@ int mini_cm_reject(struct nes_cm_core *cm_core,
+ /**
+  * mini_cm_close
+  */
+-int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
++static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
+ {
+ 	int ret = 0;
+ 
+@@ -1808,8 +1824,8 @@ int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
+  * recv_pkt - recv an ETHERNET packet, and process it through CM
+  * node state machine
+  */
+-int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic,
+-		struct sk_buff *skb)
++static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic,
++			    struct sk_buff *skb)
+ {
+ 	struct nes_cm_node *cm_node = NULL;
+ 	struct nes_cm_listener *listener = NULL;
+@@ -1898,7 +1914,7 @@ int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic,
+ /**
+  * nes_cm_alloc_core - allocate a top level instance of a cm core
+  */
+-struct nes_cm_core *nes_cm_alloc_core(void)
++static struct nes_cm_core *nes_cm_alloc_core(void)
+ {
+ 	int i;
+ 
+@@ -1919,7 +1935,6 @@ struct nes_cm_core *nes_cm_alloc_core(void)
+ 	cm_core->state = NES_CM_STATE_INITED;
+ 	cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS;
+ 
+-	atomic_set(&cm_core->session_id, 0);
+ 	atomic_set(&cm_core->events_posted, 0);
+ 
+ 	/* init the packet lists */
+@@ -1958,7 +1973,7 @@ struct nes_cm_core *nes_cm_alloc_core(void)
+ /**
+  * mini_cm_dealloc_core - deallocate a top level instance of a cm core
+  */
+-int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
++static int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
+ {
+ 	nes_debug(NES_DBG_CM, "De-Alloc CM Core (%p)\n", cm_core);
+ 
+@@ -1983,7 +1998,7 @@ int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
+ /**
+  * mini_cm_get
+  */
+-int mini_cm_get(struct nes_cm_core *cm_core)
++static int mini_cm_get(struct nes_cm_core *cm_core)
+ {
+ 	return cm_core->state;
+ }
+@@ -1992,7 +2007,7 @@ int mini_cm_get(struct nes_cm_core *cm_core)
+ /**
+  * mini_cm_set
+  */
+-int mini_cm_set(struct nes_cm_core *cm_core, u32 type, u32 value)
++static int mini_cm_set(struct nes_cm_core *cm_core, u32 type, u32 value)
+ {
+ 	int ret = 0;
+ 
+@@ -2109,7 +2124,7 @@ int nes_cm_disconn(struct nes_qp *nesqp)
+ /**
+  * nes_disconnect_worker
+  */
+-void nes_disconnect_worker(struct work_struct *work)
++static void nes_disconnect_worker(struct work_struct *work)
+ {
+ 	struct nes_qp *nesqp = container_of(work, struct nes_qp, disconn_work);
+ 
+@@ -2122,7 +2137,7 @@ void nes_disconnect_worker(struct work_struct *work)
+ /**
+  * nes_cm_disconn_true
+  */
+-int nes_cm_disconn_true(struct nes_qp *nesqp)
++static int nes_cm_disconn_true(struct nes_qp *nesqp)
+ {
+ 	unsigned long flags;
+ 	int ret = 0;
+@@ -2265,7 +2280,7 @@ int nes_cm_disconn_true(struct nes_qp *nesqp)
+ /**
+  * nes_disconnect
+  */
+-int nes_disconnect(struct nes_qp *nesqp, int abrupt)
++static int nes_disconnect(struct nes_qp *nesqp, int abrupt)
+ {
+ 	int ret = 0;
+ 	struct nes_vnic *nesvnic;
+@@ -2482,7 +2497,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ 	}
+ 	if (ret)
+ 		printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
+-				__FUNCTION__, __LINE__, ret);
++				__func__, __LINE__, ret);
+ 
+ 	return 0;
+ }
+@@ -2650,7 +2665,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
+ 	cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);
+ 	if (!cm_node) {
+ 		printk("%s[%u] Error returned from listen API call\n",
+-				__FUNCTION__, __LINE__);
++				__func__, __LINE__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -2740,7 +2755,7 @@ int nes_cm_stop(void)
+  * cm_event_connected
+  * handle a connected event, setup QPs and HW
+  */
+-void cm_event_connected(struct nes_cm_event *event)
++static void cm_event_connected(struct nes_cm_event *event)
+ {
+ 	u64 u64temp;
+ 	struct nes_qp *nesqp;
+@@ -2864,7 +2879,7 @@ void cm_event_connected(struct nes_cm_event *event)
+ 
+ 	if (ret)
+ 		printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
+-				__FUNCTION__, __LINE__, ret);
++				__func__, __LINE__, ret);
+ 	nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = %lu\n",
+ 			nesqp->hwqp.qp_id, jiffies );
+ 
+@@ -2877,7 +2892,7 @@ void cm_event_connected(struct nes_cm_event *event)
+ /**
+  * cm_event_connect_error
+  */
+-void cm_event_connect_error(struct nes_cm_event *event)
++static void cm_event_connect_error(struct nes_cm_event *event)
+ {
+ 	struct nes_qp *nesqp;
+ 	struct iw_cm_id *cm_id;
+@@ -2919,7 +2934,7 @@ void cm_event_connect_error(struct nes_cm_event *event)
+ 	nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
+ 	if (ret)
+ 		printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
+-				__FUNCTION__, __LINE__, ret);
++				__func__, __LINE__, ret);
+ 	nes_rem_ref(&nesqp->ibqp);
+ 		cm_id->rem_ref(cm_id);
+ 
+@@ -2930,7 +2945,7 @@ void cm_event_connect_error(struct nes_cm_event *event)
+ /**
+  * cm_event_reset
+  */
+-void cm_event_reset(struct nes_cm_event *event)
++static void cm_event_reset(struct nes_cm_event *event)
+ {
+ 	struct nes_qp *nesqp;
+ 	struct iw_cm_id *cm_id;
+@@ -2973,7 +2988,7 @@ void cm_event_reset(struct nes_cm_event *event)
+ /**
+  * cm_event_mpa_req
+  */
+-void cm_event_mpa_req(struct nes_cm_event *event)
++static void cm_event_mpa_req(struct nes_cm_event *event)
+ {
+ 	struct iw_cm_id   *cm_id;
+ 	struct iw_cm_event cm_event;
+@@ -3007,7 +3022,7 @@ void cm_event_mpa_req(struct nes_cm_event *event)
+ 	ret = cm_id->event_handler(cm_id, &cm_event);
+ 	if (ret)
+ 		printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
+-				__FUNCTION__, __LINE__, ret);
++				__func__, __LINE__, ret);
+ 
+ 	return;
+ }
+@@ -3019,7 +3034,7 @@ static void nes_cm_event_handler(struct work_struct *);
+  * nes_cm_post_event
+  * post an event to the cm event handler
+  */
+-int nes_cm_post_event(struct nes_cm_event *event)
++static int nes_cm_post_event(struct nes_cm_event *event)
+ {
+ 	atomic_inc(&event->cm_node->cm_core->events_posted);
+ 	add_ref_cm_node(event->cm_node);
+diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
+index a59f0a7..7717cb2 100644
+--- a/drivers/infiniband/hw/nes/nes_cm.h
++++ b/drivers/infiniband/hw/nes/nes_cm.h
+@@ -225,7 +225,6 @@ enum nes_cm_listener_state {
+ 
+ struct nes_cm_listener {
+ 	struct list_head           list;
+-	u64                        session_id;
+ 	struct nes_cm_core         *cm_core;
+ 	u8                         loc_mac[ETH_ALEN];
+ 	nes_addr_t                 loc_addr;
+@@ -242,7 +241,6 @@ struct nes_cm_listener {
+ 
+ /* per connection node and node state information */
+ struct nes_cm_node {
+-	u64                       session_id;
+ 	u32                       hashkey;
+ 
+ 	nes_addr_t                loc_addr, rem_addr;
+@@ -327,7 +325,6 @@ struct nes_cm_event {
+ 
+ struct nes_cm_core {
+ 	enum nes_cm_node_state  state;
+-	atomic_t                session_id;
+ 
+ 	atomic_t                listen_node_cnt;
+ 	struct nes_cm_node      listen_list;
+@@ -383,35 +380,10 @@ struct nes_cm_ops {
+ 	int (*set)(struct nes_cm_core *, u32, u32);
+ };
+ 
+-
+-int send_mpa_request(struct nes_cm_node *);
+-struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *,
+-		void *, u32, void *, u32, u8);
+ int schedule_nes_timer(struct nes_cm_node *, struct sk_buff *,
+ 		enum nes_timer_type, int, int);
+-void nes_cm_timer_tick(unsigned long);
+-int send_syn(struct nes_cm_node *, u32);
+-int send_reset(struct nes_cm_node *);
+-int send_ack(struct nes_cm_node *);
+-int send_fin(struct nes_cm_node *, struct sk_buff *);
+-struct sk_buff *get_free_pkt(struct nes_cm_node *);
+-int process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *);
+-
+-struct nes_cm_node * mini_cm_connect(struct nes_cm_core *,
+-		struct nes_vnic *, struct ietf_mpa_frame *, struct nes_cm_info *);
+-int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, struct nes_cm_node *);
+-int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, struct nes_cm_node *);
+-int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
+-int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *);
+-struct nes_cm_core *mini_cm_alloc_core(struct nes_cm_info *);
+-int mini_cm_dealloc_core(struct nes_cm_core *);
+-int mini_cm_get(struct nes_cm_core *);
+-int mini_cm_set(struct nes_cm_core *, u32, u32);
+ 
+ int nes_cm_disconn(struct nes_qp *);
+-void nes_disconnect_worker(struct work_struct *);
+-int nes_cm_disconn_true(struct nes_qp *);
+-int nes_disconnect(struct nes_qp *, int);
+ 
+ int nes_accept(struct iw_cm_id *, struct iw_cm_conn_param *);
+ int nes_reject(struct iw_cm_id *, const void *, u8);
+@@ -423,11 +395,4 @@ int nes_cm_recv(struct sk_buff *, struct net_device *);
+ int nes_cm_start(void);
+ int nes_cm_stop(void);
+ 
+-/* CM event handler functions */
+-void cm_event_connected(struct nes_cm_event *);
+-void cm_event_connect_error(struct nes_cm_event *);
+-void cm_event_reset(struct nes_cm_event *);
+-void cm_event_mpa_req(struct nes_cm_event *);
+-int nes_cm_post_event(struct nes_cm_event *);
+-
+ #endif			/* NES_CM_H */
+diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
+index 49e53e4..aa53aab 100644
+--- a/drivers/infiniband/hw/nes/nes_hw.c
++++ b/drivers/infiniband/hw/nes/nes_hw.c
+@@ -41,7 +41,7 @@
+ 
+ #include "nes.h"
+ 
+-u32 crit_err_count = 0;
++static u32 crit_err_count;
+ u32 int_mod_timer_init;
+ u32 int_mod_cq_depth_256;
+ u32 int_mod_cq_depth_128;
+@@ -53,6 +53,17 @@ u32 int_mod_cq_depth_1;
+ 
+ #include "nes_cm.h"
+ 
++static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq);
++static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count);
++static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
++			   u8 OneG_Mode);
++static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq);
++static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq);
++static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq);
++static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
++				   struct nes_hw_aeqe *aeqe);
++static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number);
++static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode);
+ 
+ #ifdef CONFIG_INFINIBAND_NES_DEBUG
+ static unsigned char *nes_iwarp_state_str[] = {
+@@ -370,7 +381,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
+ 		nesadapter->et_use_adaptive_rx_coalesce = 1;
+ 		nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
+ 		nesadapter->et_rx_coalesce_usecs_irq = 0;
+-		printk(PFX "%s: Using Adaptive Interrupt Moderation\n", __FUNCTION__);
++		printk(PFX "%s: Using Adaptive Interrupt Moderation\n", __func__);
+ 	}
+ 	/* Setup and enable the periodic timer */
+ 	if (nesadapter->et_rx_coalesce_usecs_irq)
+@@ -382,7 +393,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
+ 	nesadapter->base_pd = 1;
+ 
+ 	nesadapter->device_cap_flags =
+-			IB_DEVICE_ZERO_STAG | IB_DEVICE_SEND_W_INV | IB_DEVICE_MEM_WINDOW;
++		IB_DEVICE_ZERO_STAG | IB_DEVICE_MEM_WINDOW;
+ 
+ 	nesadapter->allocated_qps = (unsigned long *)&(((unsigned char *)nesadapter)
+ 			[(sizeof(struct nes_adapter)+(sizeof(unsigned long)-1))&(~(sizeof(unsigned long)-1))]);
+@@ -572,7 +583,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
+ 		if (vendor_id == 0xffff)
+ 			break;
+ 	}
+-	nes_debug(NES_DBG_INIT, "%s %d functions found for %s.\n", __FUNCTION__,
++	nes_debug(NES_DBG_INIT, "%s %d functions found for %s.\n", __func__,
+ 		func_index, pci_name(nesdev->pcidev));
+ 	nesadapter->adapter_fcn_count = func_index;
+ 
+@@ -583,7 +594,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
+ /**
+  * nes_reset_adapter_ne020
+  */
+-unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
++static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
+ {
+ 	u32 port_count;
+ 	u32 u32temp;
+@@ -691,7 +702,8 @@ unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
+ /**
+  * nes_init_serdes
+  */
+-int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, u8  OneG_Mode)
++static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
++			   u8 OneG_Mode)
+ {
+ 	int i;
+ 	u32 u32temp;
+@@ -739,7 +751,7 @@ int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, u8  One
+ 				& 0x0000000f)) != 0x0000000f) && (i++ < 5000))
+ 				mdelay(1);
+ 			if (i >= 5000) {
+-				printk("%s: Init: serdes 1 not ready, status=%x\n", __FUNCTION__, u32temp);
++				printk("%s: Init: serdes 1 not ready, status=%x\n", __func__, u32temp);
+ 				/* return 1; */
+ 			}
+ 			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x000bdef7);
+@@ -760,7 +772,7 @@ int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, u8  One
+  * nes_init_csr_ne020
+  * Initialize registers for ne020 hardware
+  */
+-void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)
++static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)
+ {
+ 	u32 u32temp;
+ 
+@@ -1204,7 +1216,7 @@ int nes_init_phy(struct nes_device *nesdev)
+ 	if (nesadapter->OneG_Mode) {
+ 		nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index);
+ 		if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_1G) {
+-			printk(PFX "%s: Programming mdc config for 1G\n", __FUNCTION__);
++			printk(PFX "%s: Programming mdc config for 1G\n", __func__);
+ 			tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
+ 			tx_config |= 0x04;
+ 			nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
+@@ -1358,7 +1370,7 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
+ static void nes_rq_wqes_timeout(unsigned long parm)
+ {
+ 	struct nes_vnic *nesvnic = (struct nes_vnic *)parm;
+-	printk("%s: Timer fired.\n", __FUNCTION__);
++	printk("%s: Timer fired.\n", __func__);
+ 	atomic_set(&nesvnic->rx_skb_timer_running, 0);
+ 	if (atomic_read(&nesvnic->rx_skbs_needed))
+ 		nes_replenish_nic_rq(nesvnic);
+@@ -1909,7 +1921,7 @@ void nes_dpc(unsigned long param)
+ /**
+  * nes_process_ceq
+  */
+-void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
++static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
+ {
+ 	u64 u64temp;
+ 	struct nes_hw_cq *cq;
+@@ -1949,7 +1961,7 @@ void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
+ /**
+  * nes_process_aeq
+  */
+-void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
++static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
+ {
+ //	u64 u64temp;
+ 	u32 head;
+@@ -2060,7 +2072,7 @@ static void nes_reset_link(struct nes_device *nesdev, u32 mac_index)
+ /**
+  * nes_process_mac_intr
+  */
+-void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
++static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ {
+ 	unsigned long flags;
+ 	u32 pcs_control_status;
+@@ -2163,7 +2175,7 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ 				temp_phy_data = phy_data;
+ 			} while (1);
+ 			nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
+-				__FUNCTION__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP");
++				__func__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP");
+ 
+ 		} else {
+ 			phy_data = (0x0f0f0000 == (pcs_control_status & 0x0f1f0000)) ? 4 : 0;
+@@ -2205,7 +2217,7 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ 
+ 
+ 
+-void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
++static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ {
+ 	struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
+ 
+@@ -2428,7 +2440,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ /**
+  * nes_cqp_ce_handler
+  */
+-void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
++static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
+ {
+ 	u64 u64temp;
+ 	unsigned long flags;
+@@ -2567,7 +2579,8 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
+ /**
+  * nes_process_iwarp_aeqe
+  */
+-void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe)
++static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
++				   struct nes_hw_aeqe *aeqe)
+ {
+ 	u64 context;
+ 	u64 aeqe_context = 0;
+@@ -2819,7 +2832,7 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe)
+ 					le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
+ 			if (resource_allocated) {
+ 				printk(KERN_ERR PFX "%s: Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u\n",
+-						__FUNCTION__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
++						__func__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
+ 			}
+ 			break;
+ 		case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
+diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
+index eee77da..01cd0ef 100644
+--- a/drivers/infiniband/hw/nes/nes_nic.c
++++ b/drivers/infiniband/hw/nes/nes_nic.c
+@@ -92,15 +92,6 @@ static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
+ 		| NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
+ static int debug = -1;
+ 
+-
+-static int nes_netdev_open(struct net_device *);
+-static int nes_netdev_stop(struct net_device *);
+-static int nes_netdev_start_xmit(struct sk_buff *, struct net_device *);
+-static struct net_device_stats *nes_netdev_get_stats(struct net_device *);
+-static void nes_netdev_tx_timeout(struct net_device *);
+-static int nes_netdev_set_mac_address(struct net_device *, void *);
+-static int nes_netdev_change_mtu(struct net_device *, int);
+-
+ /**
+  * nes_netdev_poll
+  */
+@@ -802,7 +793,7 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
+ 
+ 	memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len);
+ 	printk(PFX "%s: Address length = %d, Address = %02X%02X%02X%02X%02X%02X..\n",
+-		   __FUNCTION__, netdev->addr_len,
++		   __func__, netdev->addr_len,
+ 		   mac_addr->sa_data[0], mac_addr->sa_data[1],
+ 		   mac_addr->sa_data[2], mac_addr->sa_data[3],
+ 		   mac_addr->sa_data[4], mac_addr->sa_data[5]);
+@@ -832,7 +823,7 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
+ /**
+  * nes_netdev_set_multicast_list
+  */
+-void nes_netdev_set_multicast_list(struct net_device *netdev)
++static void nes_netdev_set_multicast_list(struct net_device *netdev)
+ {
+ 	struct nes_vnic *nesvnic = netdev_priv(netdev);
+ 	struct nes_device *nesdev = nesvnic->nesdev;
+@@ -947,28 +938,6 @@ static int nes_netdev_change_mtu(struct	net_device *netdev,	int	new_mtu)
+ 	return ret;
+ }
+ 
+-
+-/**
+- * nes_netdev_exit - destroy network device
+- */
+-void nes_netdev_exit(struct nes_vnic *nesvnic)
+-{
+-	struct net_device *netdev = nesvnic->netdev;
+-	struct nes_ib_device *nesibdev = nesvnic->nesibdev;
+-
+-	nes_debug(NES_DBG_SHUTDOWN, "\n");
+-
+-	// destroy the ibdevice if RDMA enabled
+-	if ((nesvnic->rdma_enabled)&&(nesvnic->of_device_registered)) {
+-		nes_destroy_ofa_device( nesibdev );
+-		nesvnic->of_device_registered = 0;
+-		nesvnic->nesibdev = NULL;
+-	}
+-	unregister_netdev(netdev);
+-	nes_debug(NES_DBG_SHUTDOWN, "\n");
+-}
+-
+-
+ #define NES_ETHTOOL_STAT_COUNT 55
+ static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] = {
+ 	"Link Change Interrupts",
+diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
+index c4ec6ac..f9db07c 100644
+--- a/drivers/infiniband/hw/nes/nes_utils.c
++++ b/drivers/infiniband/hw/nes/nes_utils.c
+@@ -566,7 +566,7 @@ struct nes_cqp_request *nes_get_cqp_request(struct nes_device *nesdev)
+ 				cqp_request);
+ 	} else
+ 		printk(KERN_ERR PFX "%s: Could not allocated a CQP request.\n",
+-			   __FUNCTION__);
++			   __func__);
+ 
+ 	return cqp_request;
+ }
+diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
+index a651e9d..f9a5d43 100644
+--- a/drivers/infiniband/hw/nes/nes_verbs.c
++++ b/drivers/infiniband/hw/nes/nes_verbs.c
+@@ -49,6 +49,7 @@ atomic_t mod_qp_timouts;
+ atomic_t qps_created;
+ atomic_t sw_qps_destroyed;
+ 
++static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);
+ 
+ /**
+  * nes_alloc_mw
+@@ -1043,10 +1044,10 @@ static int nes_setup_virt_qp(struct nes_qp *nesqp, struct nes_pbl *nespbl,
+ 	u8 sq_pbl_entries;
+ 
+ 	pbl_entries = nespbl->pbl_size >> 3;
+-	nes_debug(NES_DBG_QP, "Userspace PBL, pbl_size=%u, pbl_entries = %d pbl_vbase=%p, pbl_pbase=%p\n",
++	nes_debug(NES_DBG_QP, "Userspace PBL, pbl_size=%u, pbl_entries = %d pbl_vbase=%p, pbl_pbase=%lx\n",
+ 			nespbl->pbl_size, pbl_entries,
+ 			(void *)nespbl->pbl_vbase,
+-			(void *)nespbl->pbl_pbase);
++			(unsigned long) nespbl->pbl_pbase);
+ 	pbl = (__le64 *) nespbl->pbl_vbase; /* points to first pbl entry */
+ 	/* now lets set the sq_vbase as well as rq_vbase addrs we will assign */
+ 	/* the first pbl to be fro the rq_vbase... */
+@@ -1074,9 +1075,9 @@ static int nes_setup_virt_qp(struct nes_qp *nesqp, struct nes_pbl *nespbl,
+ 	/* nesqp->hwqp.rq_vbase = bus_to_virt(*pbl); */
+ 	/*nesqp->hwqp.rq_vbase = phys_to_virt(*pbl); */
+ 
+-	nes_debug(NES_DBG_QP, "QP sq_vbase= %p sq_pbase=%p rq_vbase=%p rq_pbase=%p\n",
+-			nesqp->hwqp.sq_vbase, (void *)nesqp->hwqp.sq_pbase,
+-			nesqp->hwqp.rq_vbase, (void *)nesqp->hwqp.rq_pbase);
++	nes_debug(NES_DBG_QP, "QP sq_vbase= %p sq_pbase=%lx rq_vbase=%p rq_pbase=%lx\n",
++		  nesqp->hwqp.sq_vbase, (unsigned long) nesqp->hwqp.sq_pbase,
++		  nesqp->hwqp.rq_vbase, (unsigned long) nesqp->hwqp.rq_pbase);
+ 	spin_lock_irqsave(&nesadapter->pbl_lock, flags);
+ 	if (!nesadapter->free_256pbl) {
+ 		pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
+@@ -1251,6 +1252,9 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
+ 	u8 rq_encoded_size;
+ 	/* int counter; */
+ 
++	if (init_attr->create_flags)
++		return ERR_PTR(-EINVAL);
++
+ 	atomic_inc(&qps_created);
+ 	switch (init_attr->qp_type) {
+ 		case IB_QPT_RC:
+@@ -1908,13 +1912,13 @@ static int nes_destroy_cq(struct ib_cq *ib_cq)
+ 		nesadapter->free_256pbl++;
+ 		if (nesadapter->free_256pbl > nesadapter->max_256pbl) {
+ 			printk(KERN_ERR PFX "%s: free 256B PBLs(%u) has exceeded the max(%u)\n",
+-					__FUNCTION__, nesadapter->free_256pbl, nesadapter->max_256pbl);
++					__func__, nesadapter->free_256pbl, nesadapter->max_256pbl);
+ 		}
+ 	} else if (nescq->virtual_cq == 2) {
+ 		nesadapter->free_4kpbl++;
+ 		if (nesadapter->free_4kpbl > nesadapter->max_4kpbl) {
+ 			printk(KERN_ERR PFX "%s: free 4K PBLs(%u) has exceeded the max(%u)\n",
+-					__FUNCTION__, nesadapter->free_4kpbl, nesadapter->max_4kpbl);
++					__func__, nesadapter->free_4kpbl, nesadapter->max_4kpbl);
+ 		}
+ 		opcode |= NES_CQP_CQ_4KB_CHUNK;
+ 	}
+@@ -2653,10 +2657,10 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ 
+ 			nespbl->pbl_vbase = (u64 *)pbl;
+ 			nespbl->user_base = start;
+-			nes_debug(NES_DBG_MR, "Allocated PBL memory, %u bytes, pbl_pbase=%p,"
++			nes_debug(NES_DBG_MR, "Allocated PBL memory, %u bytes, pbl_pbase=%lx,"
+ 					" pbl_vbase=%p user_base=0x%lx\n",
+-					nespbl->pbl_size, (void *)nespbl->pbl_pbase,
+-					(void*)nespbl->pbl_vbase, nespbl->user_base);
++				  nespbl->pbl_size, (unsigned long) nespbl->pbl_pbase,
++				  (void *) nespbl->pbl_vbase, nespbl->user_base);
+ 
+ 			list_for_each_entry(chunk, &region->chunk_list, list) {
+ 				for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) {
+@@ -2796,10 +2800,11 @@ static int nes_dereg_mr(struct ib_mr *ib_mr)
+ /**
+  * show_rev
+  */
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+ 	struct nes_ib_device *nesibdev =
+-			container_of(cdev, struct nes_ib_device, ibdev.class_dev);
++			container_of(dev, struct nes_ib_device, ibdev.dev);
+ 	struct nes_vnic *nesvnic = nesibdev->nesvnic;
+ 
+ 	nes_debug(NES_DBG_INIT, "\n");
+@@ -2810,10 +2815,11 @@ static ssize_t show_rev(struct class_device *cdev, char *buf)
+ /**
+  * show_fw_ver
+  */
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
++			   char *buf)
+ {
+ 	struct nes_ib_device *nesibdev =
+-			container_of(cdev, struct nes_ib_device, ibdev.class_dev);
++			container_of(dev, struct nes_ib_device, ibdev.dev);
+ 	struct nes_vnic *nesvnic = nesibdev->nesvnic;
+ 
+ 	nes_debug(NES_DBG_INIT, "\n");
+@@ -2827,7 +2833,8 @@ static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
+ /**
+  * show_hca
+  */
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
++		        char *buf)
+ {
+ 	nes_debug(NES_DBG_INIT, "\n");
+ 	return sprintf(buf, "NES020\n");
+@@ -2837,23 +2844,24 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
+ /**
+  * show_board
+  */
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+ 	nes_debug(NES_DBG_INIT, "\n");
+ 	return sprintf(buf, "%.*s\n", 32, "NES020 Board ID");
+ }
+ 
+ 
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
+ 
+-static struct class_device_attribute *nes_class_attributes[] = {
+-	&class_device_attr_hw_rev,
+-	&class_device_attr_fw_ver,
+-	&class_device_attr_hca_type,
+-	&class_device_attr_board_id
++static struct device_attribute *nes_dev_attributes[] = {
++	&dev_attr_hw_rev,
++	&dev_attr_fw_ver,
++	&dev_attr_hca_type,
++	&dev_attr_board_id
+ };
+ 
+ 
+@@ -3778,7 +3786,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
+ 	nesibdev->ibdev.phys_port_cnt = 1;
+ 	nesibdev->ibdev.num_comp_vectors = 1;
+ 	nesibdev->ibdev.dma_device = &nesdev->pcidev->dev;
+-	nesibdev->ibdev.class_dev.dev = &nesdev->pcidev->dev;
++	nesibdev->ibdev.dev.parent = &nesdev->pcidev->dev;
+ 	nesibdev->ibdev.query_device = nes_query_device;
+ 	nesibdev->ibdev.query_port = nes_query_port;
+ 	nesibdev->ibdev.modify_port = nes_modify_port;
+@@ -3873,13 +3881,13 @@ int nes_register_ofa_device(struct nes_ib_device *nesibdev)
+ 	nesibdev->max_qp = (nesadapter->max_qp-NES_FIRST_QPN) / nesadapter->port_count;
+ 	nesibdev->max_pd = nesadapter->max_pd / nesadapter->port_count;
+ 
+-	for (i = 0; i < ARRAY_SIZE(nes_class_attributes); ++i) {
+-		ret = class_device_create_file(&nesibdev->ibdev.class_dev, nes_class_attributes[i]);
++	for (i = 0; i < ARRAY_SIZE(nes_dev_attributes); ++i) {
++		ret = device_create_file(&nesibdev->ibdev.dev, nes_dev_attributes[i]);
+ 		if (ret) {
+ 			while (i > 0) {
+ 				i--;
+-				class_device_remove_file(&nesibdev->ibdev.class_dev,
+-						nes_class_attributes[i]);
++				device_remove_file(&nesibdev->ibdev.dev,
++						   nes_dev_attributes[i]);
+ 			}
+ 			ib_unregister_device(&nesibdev->ibdev);
+ 			return ret;
+@@ -3895,16 +3903,13 @@ int nes_register_ofa_device(struct nes_ib_device *nesibdev)
+ /**
+  * nes_unregister_ofa_device
+  */
+-void nes_unregister_ofa_device(struct nes_ib_device *nesibdev)
++static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev)
+ {
+ 	struct nes_vnic *nesvnic = nesibdev->nesvnic;
+ 	int i;
+ 
+-	if (nesibdev == NULL)
+-		return;
+-
+-	for (i = 0; i < ARRAY_SIZE(nes_class_attributes); ++i) {
+-		class_device_remove_file(&nesibdev->ibdev.class_dev, nes_class_attributes[i]);
++	for (i = 0; i < ARRAY_SIZE(nes_dev_attributes); ++i) {
++		device_remove_file(&nesibdev->ibdev.dev, nes_dev_attributes[i]);
+ 	}
+ 
+ 	if (nesvnic->of_device_registered) {
+diff --git a/drivers/infiniband/ulp/ipoib/Makefile b/drivers/infiniband/ulp/ipoib/Makefile
+index 98ee38e..3090100 100644
+--- a/drivers/infiniband/ulp/ipoib/Makefile
++++ b/drivers/infiniband/ulp/ipoib/Makefile
+@@ -4,7 +4,8 @@ ib_ipoib-y					:= ipoib_main.o \
+ 						   ipoib_ib.o \
+ 						   ipoib_multicast.o \
+ 						   ipoib_verbs.o \
+-						   ipoib_vlan.o
++						   ipoib_vlan.o \
++						   ipoib_ethtool.o
+ ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM)		+= ipoib_cm.o
+ ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG)	+= ipoib_fs.o
+ 
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
+index 054fab8..73b2b17 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib.h
++++ b/drivers/infiniband/ulp/ipoib/ipoib.h
+@@ -87,6 +87,7 @@ enum {
+ 	IPOIB_MCAST_STARTED	  = 8,
+ 	IPOIB_FLAG_ADMIN_CM	  = 9,
+ 	IPOIB_FLAG_UMCAST	  = 10,
++	IPOIB_FLAG_CSUM		  = 11,
+ 
+ 	IPOIB_MAX_BACKOFF_SECONDS = 16,
+ 
+@@ -241,6 +242,11 @@ struct ipoib_cm_dev_priv {
+ 	int			num_frags;
+ };
+ 
++struct ipoib_ethtool_st {
++	u16     coalesce_usecs;
++	u16     max_coalesced_frames;
++};
++
+ /*
+  * Device private locking: tx_lock protects members used in TX fast
+  * path (and we use LLTX so upper layers don't do extra locking).
+@@ -318,6 +324,8 @@ struct ipoib_dev_priv {
+ 	struct dentry *mcg_dentry;
+ 	struct dentry *path_dentry;
+ #endif
++	int	hca_caps;
++	struct ipoib_ethtool_st ethtool;
+ };
+ 
+ struct ipoib_ah {
+@@ -458,6 +466,8 @@ void ipoib_pkey_poll(struct work_struct *work);
+ int ipoib_pkey_dev_delay_open(struct net_device *dev);
+ void ipoib_drain_cq(struct net_device *dev);
+ 
++void ipoib_set_ethtool_ops(struct net_device *dev);
++
+ #ifdef CONFIG_INFINIBAND_IPOIB_CM
+ 
+ #define IPOIB_FLAGS_RC		0x80
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+index 2490b2d..9db7b0b 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+@@ -1007,9 +1007,9 @@ static int ipoib_cm_modify_tx_init(struct net_device *dev,
+ 	struct ipoib_dev_priv *priv = netdev_priv(dev);
+ 	struct ib_qp_attr qp_attr;
+ 	int qp_attr_mask, ret;
+-	ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &qp_attr.pkey_index);
++	ret = ib_find_pkey(priv->ca, priv->port, priv->pkey, &qp_attr.pkey_index);
+ 	if (ret) {
+-		ipoib_warn(priv, "pkey 0x%x not in cache: %d\n", priv->pkey, ret);
++		ipoib_warn(priv, "pkey 0x%x not found: %d\n", priv->pkey, ret);
+ 		return ret;
+ 	}
+ 
+@@ -1383,6 +1383,10 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
+ 		set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+ 		ipoib_warn(priv, "enabling connected mode "
+ 			   "will cause multicast packet drops\n");
++
++		dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO);
++		priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
++
+ 		ipoib_flush_paths(dev);
+ 		return count;
+ 	}
+@@ -1391,6 +1395,13 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
+ 		clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+ 		dev->mtu = min(priv->mcast_mtu, dev->mtu);
+ 		ipoib_flush_paths(dev);
++
++		if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) {
++			dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
++			if (priv->hca_caps & IB_DEVICE_UD_TSO)
++				dev->features |= NETIF_F_TSO;
++		}
++
+ 		return count;
+ 	}
+ 
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+new file mode 100644
+index 0000000..9a47428
+--- /dev/null
++++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+@@ -0,0 +1,99 @@
++/*
++ * 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 "ipoib.h"
++
++static void ipoib_get_drvinfo(struct net_device *netdev,
++			      struct ethtool_drvinfo *drvinfo)
++{
++	strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
++}
++
++static int ipoib_get_coalesce(struct net_device *dev,
++			      struct ethtool_coalesce *coal)
++{
++	struct ipoib_dev_priv *priv = netdev_priv(dev);
++
++	coal->rx_coalesce_usecs = priv->ethtool.coalesce_usecs;
++	coal->tx_coalesce_usecs = priv->ethtool.coalesce_usecs;
++	coal->rx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
++	coal->tx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
++
++	return 0;
++}
++
++static int ipoib_set_coalesce(struct net_device *dev,
++			      struct ethtool_coalesce *coal)
++{
++	struct ipoib_dev_priv *priv = netdev_priv(dev);
++	int ret;
++
++	/*
++	 * Since IPoIB uses a single CQ for both rx and tx, we assume
++	 * that rx params dictate the configuration.  These values are
++	 * saved in the private data and returned when ipoib_get_coalesce()
++	 * is called.
++	 */
++	if (coal->rx_coalesce_usecs       > 0xffff ||
++	    coal->rx_max_coalesced_frames > 0xffff)
++		return -EINVAL;
++
++	ret = ib_modify_cq(priv->cq, coal->rx_max_coalesced_frames,
++			   coal->rx_coalesce_usecs);
++	if (ret && ret != -ENOSYS) {
++		ipoib_warn(priv, "failed modifying CQ (%d)\n", ret);
++		return ret;
++	}
++
++	coal->tx_coalesce_usecs       = coal->rx_coalesce_usecs;
++	coal->tx_max_coalesced_frames = coal->rx_max_coalesced_frames;
++	priv->ethtool.coalesce_usecs       = coal->rx_coalesce_usecs;
++	priv->ethtool.max_coalesced_frames = coal->rx_max_coalesced_frames;
++
++	return 0;
++}
++
++static const struct ethtool_ops ipoib_ethtool_ops = {
++	.get_drvinfo		= ipoib_get_drvinfo,
++	.get_tso		= ethtool_op_get_tso,
++	.get_coalesce		= ipoib_get_coalesce,
++	.set_coalesce		= ipoib_set_coalesce,
++};
++
++void ipoib_set_ethtool_ops(struct net_device *dev)
++{
++	SET_ETHTOOL_OPS(dev, &ipoib_ethtool_ops);
++}
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+index 08c4396..0205eb7 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+@@ -39,6 +39,8 @@
+ #include <linux/dma-mapping.h>
+ 
+ #include <rdma/ib_cache.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
+ 
+ #include "ipoib.h"
+ 
+@@ -231,6 +233,10 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
+ 	skb->dev = dev;
+ 	/* XXX get correct PACKET_ type here */
+ 	skb->pkt_type = PACKET_HOST;
++
++	if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
++		skb->ip_summed = CHECKSUM_UNNECESSARY;
++
+ 	netif_receive_skb(skb);
+ 
+ repost:
+@@ -245,29 +251,37 @@ static int ipoib_dma_map_tx(struct ib_device *ca,
+ 	struct sk_buff *skb = tx_req->skb;
+ 	u64 *mapping = tx_req->mapping;
+ 	int i;
++	int off;
+ 
+-	mapping[0] = ib_dma_map_single(ca, skb->data, skb_headlen(skb),
+-				       DMA_TO_DEVICE);
+-	if (unlikely(ib_dma_mapping_error(ca, mapping[0])))
+-		return -EIO;
++	if (skb_headlen(skb)) {
++		mapping[0] = ib_dma_map_single(ca, skb->data, skb_headlen(skb),
++					       DMA_TO_DEVICE);
++		if (unlikely(ib_dma_mapping_error(ca, mapping[0])))
++			return -EIO;
++
++		off = 1;
++	} else
++		off = 0;
+ 
+ 	for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
+ 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+-		mapping[i + 1] = ib_dma_map_page(ca, frag->page,
++		mapping[i + off] = ib_dma_map_page(ca, frag->page,
+ 						 frag->page_offset, frag->size,
+ 						 DMA_TO_DEVICE);
+-		if (unlikely(ib_dma_mapping_error(ca, mapping[i + 1])))
++		if (unlikely(ib_dma_mapping_error(ca, mapping[i + off])))
+ 			goto partial_error;
+ 	}
+ 	return 0;
+ 
+ partial_error:
+-	ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
+-
+ 	for (; i > 0; --i) {
+ 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
+-		ib_dma_unmap_page(ca, mapping[i], frag->size, DMA_TO_DEVICE);
++		ib_dma_unmap_page(ca, mapping[i - !off], frag->size, DMA_TO_DEVICE);
+ 	}
++
++	if (off)
++		ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
++
+ 	return -EIO;
+ }
+ 
+@@ -277,12 +291,17 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca,
+ 	struct sk_buff *skb = tx_req->skb;
+ 	u64 *mapping = tx_req->mapping;
+ 	int i;
++	int off;
+ 
+-	ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
++	if (skb_headlen(skb)) {
++		ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
++		off = 1;
++	} else
++		off = 0;
+ 
+ 	for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
+ 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+-		ib_dma_unmap_page(ca, mapping[i + 1], frag->size,
++		ib_dma_unmap_page(ca, mapping[i + off], frag->size,
+ 				  DMA_TO_DEVICE);
+ 	}
+ }
+@@ -388,24 +407,40 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
+ static inline int post_send(struct ipoib_dev_priv *priv,
+ 			    unsigned int wr_id,
+ 			    struct ib_ah *address, u32 qpn,
+-			    u64 *mapping, int headlen,
+-			    skb_frag_t *frags,
+-			    int nr_frags)
++			    struct ipoib_tx_buf *tx_req,
++			    void *head, int hlen)
+ {
+ 	struct ib_send_wr *bad_wr;
+-	int i;
++	int i, off;
++	struct sk_buff *skb = tx_req->skb;
++	skb_frag_t *frags = skb_shinfo(skb)->frags;
++	int nr_frags = skb_shinfo(skb)->nr_frags;
++	u64 *mapping = tx_req->mapping;
++
++	if (skb_headlen(skb)) {
++		priv->tx_sge[0].addr         = mapping[0];
++		priv->tx_sge[0].length       = skb_headlen(skb);
++		off = 1;
++	} else
++		off = 0;
+ 
+-	priv->tx_sge[0].addr	     = mapping[0];
+-	priv->tx_sge[0].length       = headlen;
+ 	for (i = 0; i < nr_frags; ++i) {
+-		priv->tx_sge[i + 1].addr = mapping[i + 1];
+-		priv->tx_sge[i + 1].length = frags[i].size;
++		priv->tx_sge[i + off].addr = mapping[i + off];
++		priv->tx_sge[i + off].length = frags[i].size;
+ 	}
+-	priv->tx_wr.num_sge	     = nr_frags + 1;
++	priv->tx_wr.num_sge	     = nr_frags + off;
+ 	priv->tx_wr.wr_id 	     = wr_id;
+ 	priv->tx_wr.wr.ud.remote_qpn = qpn;
+ 	priv->tx_wr.wr.ud.ah 	     = address;
+ 
++	if (head) {
++		priv->tx_wr.wr.ud.mss	 = skb_shinfo(skb)->gso_size;
++		priv->tx_wr.wr.ud.header = head;
++		priv->tx_wr.wr.ud.hlen	 = hlen;
++		priv->tx_wr.opcode	 = IB_WR_LSO;
++	} else
++		priv->tx_wr.opcode	 = IB_WR_SEND;
++
+ 	return ib_post_send(priv->qp, &priv->tx_wr, &bad_wr);
+ }
+ 
+@@ -414,14 +449,30 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
+ {
+ 	struct ipoib_dev_priv *priv = netdev_priv(dev);
+ 	struct ipoib_tx_buf *tx_req;
+-
+-	if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) {
+-		ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
+-			   skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN);
+-		++dev->stats.tx_dropped;
+-		++dev->stats.tx_errors;
+-		ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu);
+-		return;
++	int hlen;
++	void *phead;
++
++	if (skb_is_gso(skb)) {
++		hlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
++		phead = skb->data;
++		if (unlikely(!skb_pull(skb, hlen))) {
++			ipoib_warn(priv, "linear data too small\n");
++			++dev->stats.tx_dropped;
++			++dev->stats.tx_errors;
++			dev_kfree_skb_any(skb);
++			return;
++		}
++	} else {
++		if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) {
++			ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
++				   skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN);
++			++dev->stats.tx_dropped;
++			++dev->stats.tx_errors;
++			ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu);
++			return;
++		}
++		phead = NULL;
++		hlen  = 0;
+ 	}
+ 
+ 	ipoib_dbg_data(priv, "sending packet, length=%d address=%p qpn=0x%06x\n",
+@@ -442,10 +493,13 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
+ 		return;
+ 	}
+ 
++	if (skb->ip_summed == CHECKSUM_PARTIAL)
++		priv->tx_wr.send_flags |= IB_SEND_IP_CSUM;
++	else
++		priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
++
+ 	if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
+-			       address->ah, qpn,
+-			       tx_req->mapping, skb_headlen(skb),
+-			       skb_shinfo(skb)->frags, skb_shinfo(skb)->nr_frags))) {
++			       address->ah, qpn, tx_req, phead, hlen))) {
+ 		ipoib_warn(priv, "post_send failed\n");
+ 		++dev->stats.tx_errors;
+ 		ipoib_dma_unmap_tx(priv->ca, tx_req);
+@@ -540,7 +594,7 @@ static void ipoib_pkey_dev_check_presence(struct net_device *dev)
+ 	struct ipoib_dev_priv *priv = netdev_priv(dev);
+ 	u16 pkey_index = 0;
+ 
+-	if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index))
++	if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index))
+ 		clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ 	else
+ 		set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+@@ -781,13 +835,13 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
+ 			clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ 			ipoib_ib_dev_down(dev, 0);
+ 			ipoib_ib_dev_stop(dev, 0);
+-			ipoib_pkey_dev_delay_open(dev);
+-			return;
++			if (ipoib_pkey_dev_delay_open(dev))
++				return;
+ 		}
+-		set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ 
+ 		/* restart QP only if P_Key index is changed */
+-		if (new_index == priv->pkey_index) {
++		if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
++		    new_index == priv->pkey_index) {
+ 			ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
+ 			return;
+ 		}
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+index 5728204..bd07f02 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+@@ -359,8 +359,7 @@ void ipoib_flush_paths(struct net_device *dev)
+ 	spin_lock_irq(&priv->tx_lock);
+ 	spin_lock(&priv->lock);
+ 
+-	list_splice(&priv->path_list, &remove_list);
+-	INIT_LIST_HEAD(&priv->path_list);
++	list_splice_init(&priv->path_list, &remove_list);
+ 
+ 	list_for_each_entry(path, &remove_list, list)
+ 		rb_erase(&path->rb_node, &priv->path_tree);
+@@ -952,6 +951,8 @@ static void ipoib_setup(struct net_device *dev)
+ 	dev->set_multicast_list	 = ipoib_set_mcast_list;
+ 	dev->neigh_setup	 = ipoib_neigh_setup_dev;
+ 
++	ipoib_set_ethtool_ops(dev);
++
+ 	netif_napi_add(dev, &priv->napi, ipoib_poll, 100);
+ 
+ 	dev->watchdog_timeo	 = HZ;
+@@ -1105,6 +1106,7 @@ static struct net_device *ipoib_add_port(const char *format,
+ 					 struct ib_device *hca, u8 port)
+ {
+ 	struct ipoib_dev_priv *priv;
++	struct ib_device_attr *device_attr;
+ 	int result = -ENOMEM;
+ 
+ 	priv = ipoib_intf_alloc(format);
+@@ -1120,6 +1122,29 @@ static struct net_device *ipoib_add_port(const char *format,
+ 		goto device_init_failed;
+ 	}
+ 
++	device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
++	if (!device_attr) {
++		printk(KERN_WARNING "%s: allocation of %zu bytes failed\n",
++		       hca->name, sizeof *device_attr);
++		goto device_init_failed;
++	}
++
++	result = ib_query_device(hca, device_attr);
++	if (result) {
++		printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n",
++		       hca->name, result);
++		kfree(device_attr);
++		goto device_init_failed;
++	}
++	priv->hca_caps = device_attr->device_cap_flags;
++
++	kfree(device_attr);
++
++	if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
++		set_bit(IPOIB_FLAG_CSUM, &priv->flags);
++		priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
++	}
++
+ 	/*
+ 	 * Set the full membership bit, so that we join the right
+ 	 * broadcast group, etc.
+@@ -1137,7 +1162,6 @@ static struct net_device *ipoib_add_port(const char *format,
+ 	} else
+ 		memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
+ 
+-
+ 	result = ipoib_dev_init(priv->dev, hca, port);
+ 	if (result < 0) {
+ 		printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n",
+@@ -1155,6 +1179,9 @@ static struct net_device *ipoib_add_port(const char *format,
+ 		goto event_failed;
+ 	}
+ 
++	if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO)
++		priv->dev->features |= NETIF_F_TSO;
++
+ 	result = register_netdev(priv->dev);
+ 	if (result) {
+ 		printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n",
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+index a3aeb91..8a20e37 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+@@ -192,6 +192,9 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
+ 	init_attr.send_cq = priv->cq;
+ 	init_attr.recv_cq = priv->cq;
+ 
++	if (priv->hca_caps & IB_DEVICE_UD_TSO)
++		init_attr.create_flags = IB_QP_CREATE_IPOIB_UD_LSO;
++
+ 	if (dev->features & NETIF_F_SG)
+ 		init_attr.cap.max_send_sge = MAX_SKB_FRAGS + 1;
+ 
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index 83247f1..08dc81c 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -405,7 +405,7 @@ int iser_send_data_out(struct iscsi_conn     *conn,
+ 	struct iser_dto *send_dto = NULL;
+ 	unsigned long buf_offset;
+ 	unsigned long data_seg_len;
+-	unsigned int itt;
++	uint32_t itt;
+ 	int err = 0;
+ 
+ 	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+@@ -416,7 +416,7 @@ int iser_send_data_out(struct iscsi_conn     *conn,
+ 	if (iser_check_xmit(conn, ctask))
+ 		return -ENOBUFS;
+ 
+-	itt = ntohl(hdr->itt);
++	itt = (__force uint32_t)hdr->itt;
+ 	data_seg_len = ntoh24(hdr->dlength);
+ 	buf_offset   = ntohl(hdr->offset);
+ 
+diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
+index 993f0a8..d19cfe6 100644
+--- a/drivers/infiniband/ulp/iser/iser_verbs.c
++++ b/drivers/infiniband/ulp/iser/iser_verbs.c
+@@ -473,11 +473,8 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
+ 		iser_connect_error(cma_id);
+ 		break;
+ 	case RDMA_CM_EVENT_DISCONNECTED:
+-		iser_disconnected_handler(cma_id);
+-		break;
+ 	case RDMA_CM_EVENT_DEVICE_REMOVAL:
+-		iser_err("Device removal is currently unsupported\n");
+-		BUG();
++		iser_disconnected_handler(cma_id);
+ 		break;
+ 	default:
+ 		iser_err("Unexpected RDMA CM event (%d)\n", event->event);
+diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
+index fd4a49f..4351457 100644
+--- a/drivers/infiniband/ulp/srp/ib_srp.c
++++ b/drivers/infiniband/ulp/srp/ib_srp.c
+@@ -68,7 +68,7 @@ static int srp_max_iu_len;
+ 
+ module_param(srp_sg_tablesize, int, 0444);
+ MODULE_PARM_DESC(srp_sg_tablesize,
+-		 "Max number of gather/scatter entries per I/O (default is 12)");
++		 "Max number of gather/scatter entries per I/O (default is 12, max 255)");
+ 
+ static int topspin_workarounds = 1;
+ 
+@@ -139,8 +139,9 @@ static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
+ 	if (!iu->buf)
+ 		goto out_free_iu;
+ 
+-	iu->dma = ib_dma_map_single(host->dev->dev, iu->buf, size, direction);
+-	if (ib_dma_mapping_error(host->dev->dev, iu->dma))
++	iu->dma = ib_dma_map_single(host->srp_dev->dev, iu->buf, size,
++				    direction);
++	if (ib_dma_mapping_error(host->srp_dev->dev, iu->dma))
+ 		goto out_free_buf;
+ 
+ 	iu->size      = size;
+@@ -161,7 +162,8 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
+ 	if (!iu)
+ 		return;
+ 
+-	ib_dma_unmap_single(host->dev->dev, iu->dma, iu->size, iu->direction);
++	ib_dma_unmap_single(host->srp_dev->dev, iu->dma, iu->size,
++			    iu->direction);
+ 	kfree(iu->buf);
+ 	kfree(iu);
+ }
+@@ -181,7 +183,7 @@ static int srp_init_qp(struct srp_target_port *target,
+ 	if (!attr)
+ 		return -ENOMEM;
+ 
+-	ret = ib_find_cached_pkey(target->srp_host->dev->dev,
++	ret = ib_find_cached_pkey(target->srp_host->srp_dev->dev,
+ 				  target->srp_host->port,
+ 				  be16_to_cpu(target->path.pkey),
+ 				  &attr->pkey_index);
+@@ -208,7 +210,7 @@ static int srp_new_cm_id(struct srp_target_port *target)
+ {
+ 	struct ib_cm_id *new_cm_id;
+ 
+-	new_cm_id = ib_create_cm_id(target->srp_host->dev->dev,
++	new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev,
+ 				    srp_cm_handler, target);
+ 	if (IS_ERR(new_cm_id))
+ 		return PTR_ERR(new_cm_id);
+@@ -229,8 +231,8 @@ static int srp_create_target_ib(struct srp_target_port *target)
+ 	if (!init_attr)
+ 		return -ENOMEM;
+ 
+-	target->cq = ib_create_cq(target->srp_host->dev->dev, srp_completion,
+-				  NULL, target, SRP_CQ_SIZE, 0);
++	target->cq = ib_create_cq(target->srp_host->srp_dev->dev,
++				  srp_completion, NULL, target, SRP_CQ_SIZE, 0);
+ 	if (IS_ERR(target->cq)) {
+ 		ret = PTR_ERR(target->cq);
+ 		goto out;
+@@ -248,7 +250,7 @@ static int srp_create_target_ib(struct srp_target_port *target)
+ 	init_attr->send_cq             = target->cq;
+ 	init_attr->recv_cq             = target->cq;
+ 
+-	target->qp = ib_create_qp(target->srp_host->dev->pd, init_attr);
++	target->qp = ib_create_qp(target->srp_host->srp_dev->pd, init_attr);
+ 	if (IS_ERR(target->qp)) {
+ 		ret = PTR_ERR(target->qp);
+ 		ib_destroy_cq(target->cq);
+@@ -302,7 +304,7 @@ static int srp_lookup_path(struct srp_target_port *target)
+ 	init_completion(&target->done);
+ 
+ 	target->path_query_id = ib_sa_path_rec_get(&srp_sa_client,
+-						   target->srp_host->dev->dev,
++						   target->srp_host->srp_dev->dev,
+ 						   target->srp_host->port,
+ 						   &target->path,
+ 						   IB_SA_PATH_REC_SERVICE_ID	|
+@@ -403,7 +405,7 @@ static int srp_send_req(struct srp_target_port *target)
+ 			     (unsigned long long) be64_to_cpu(target->ioc_guid));
+ 		memset(req->priv.initiator_port_id, 0, 8);
+ 		memcpy(req->priv.initiator_port_id + 8,
+-		       &target->srp_host->dev->dev->node_guid, 8);
++		       &target->srp_host->srp_dev->dev->node_guid, 8);
+ 	}
+ 
+ 	status = ib_send_cm_req(target->cm_id, &req->param);
+@@ -520,7 +522,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
+ 		req->fmr = NULL;
+ 	}
+ 
+-	ib_dma_unmap_sg(target->srp_host->dev->dev, scsi_sglist(scmnd),
++	ib_dma_unmap_sg(target->srp_host->srp_dev->dev, scsi_sglist(scmnd),
+ 			scsi_sg_count(scmnd), scmnd->sc_data_direction);
+ }
+ 
+@@ -628,7 +630,7 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
+ 	int page_cnt;
+ 	int i, j;
+ 	int ret;
+-	struct srp_device *dev = target->srp_host->dev;
++	struct srp_device *dev = target->srp_host->srp_dev;
+ 	struct ib_device *ibdev = dev->dev;
+ 	struct scatterlist *sg;
+ 
+@@ -723,7 +725,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
+ 	nents = scsi_sg_count(scmnd);
+ 	scat  = scsi_sglist(scmnd);
+ 
+-	dev = target->srp_host->dev;
++	dev = target->srp_host->srp_dev;
+ 	ibdev = dev->dev;
+ 
+ 	count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction);
+@@ -779,7 +781,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
+ 		buf->table_desc.va  =
+ 			cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf);
+ 		buf->table_desc.key =
+-			cpu_to_be32(target->srp_host->dev->mr->rkey);
++			cpu_to_be32(target->srp_host->srp_dev->mr->rkey);
+ 		buf->table_desc.len =
+ 			cpu_to_be32(count * sizeof (struct srp_direct_buf));
+ 
+@@ -855,7 +857,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
+ 
+ 	iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV];
+ 
+-	dev = target->srp_host->dev->dev;
++	dev = target->srp_host->srp_dev->dev;
+ 	ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len,
+ 				   DMA_FROM_DEVICE);
+ 
+@@ -937,7 +939,7 @@ static int __srp_post_recv(struct srp_target_port *target)
+ 
+ 	list.addr   = iu->dma;
+ 	list.length = iu->size;
+-	list.lkey   = target->srp_host->dev->mr->lkey;
++	list.lkey   = target->srp_host->srp_dev->mr->lkey;
+ 
+ 	wr.next     = NULL;
+ 	wr.sg_list  = &list;
+@@ -996,7 +998,7 @@ static int __srp_post_send(struct srp_target_port *target,
+ 
+ 	list.addr   = iu->dma;
+ 	list.length = len;
+-	list.lkey   = target->srp_host->dev->mr->lkey;
++	list.lkey   = target->srp_host->srp_dev->mr->lkey;
+ 
+ 	wr.next       = NULL;
+ 	wr.wr_id      = target->tx_head & SRP_SQ_SIZE;
+@@ -1039,7 +1041,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
+ 	if (!iu)
+ 		goto err;
+ 
+-	dev = target->srp_host->dev->dev;
++	dev = target->srp_host->srp_dev->dev;
+ 	ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
+ 				   DMA_TO_DEVICE);
+ 
+@@ -1456,9 +1458,10 @@ static int srp_reset_host(struct scsi_cmnd *scmnd)
+ 	return ret;
+ }
+ 
+-static ssize_t show_id_ext(struct class_device *cdev, char *buf)
++static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
++			   char *buf)
+ {
+-	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ 
+ 	if (target->state == SRP_TARGET_DEAD ||
+ 	    target->state == SRP_TARGET_REMOVED)
+@@ -1468,9 +1471,10 @@ static ssize_t show_id_ext(struct class_device *cdev, char *buf)
+ 		       (unsigned long long) be64_to_cpu(target->id_ext));
+ }
+ 
+-static ssize_t show_ioc_guid(struct class_device *cdev, char *buf)
++static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
++			     char *buf)
+ {
+-	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ 
+ 	if (target->state == SRP_TARGET_DEAD ||
+ 	    target->state == SRP_TARGET_REMOVED)
+@@ -1480,9 +1484,10 @@ static ssize_t show_ioc_guid(struct class_device *cdev, char *buf)
+ 		       (unsigned long long) be64_to_cpu(target->ioc_guid));
+ }
+ 
+-static ssize_t show_service_id(struct class_device *cdev, char *buf)
++static ssize_t show_service_id(struct device *dev,
++			       struct device_attribute *attr, char *buf)
+ {
+-	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ 
+ 	if (target->state == SRP_TARGET_DEAD ||
+ 	    target->state == SRP_TARGET_REMOVED)
+@@ -1492,9 +1497,10 @@ static ssize_t show_service_id(struct class_device *cdev, char *buf)
+ 		       (unsigned long long) be64_to_cpu(target->service_id));
+ }
+ 
+-static ssize_t show_pkey(struct class_device *cdev, char *buf)
++static ssize_t show_pkey(struct device *dev, struct device_attribute *attr,
++			 char *buf)
+ {
+-	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ 
+ 	if (target->state == SRP_TARGET_DEAD ||
+ 	    target->state == SRP_TARGET_REMOVED)
+@@ -1503,9 +1509,10 @@ static ssize_t show_pkey(struct class_device *cdev, char *buf)
+ 	return sprintf(buf, "0x%04x\n", be16_to_cpu(target->path.pkey));
+ }
+ 
+-static ssize_t show_dgid(struct class_device *cdev, char *buf)
++static ssize_t show_dgid(struct device *dev, struct device_attribute *attr,
++			 char *buf)
+ {
+-	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ 
+ 	if (target->state == SRP_TARGET_DEAD ||
+ 	    target->state == SRP_TARGET_REMOVED)
+@@ -1522,9 +1529,10 @@ static ssize_t show_dgid(struct class_device *cdev, char *buf)
+ 		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[7]));
+ }
+ 
+-static ssize_t show_orig_dgid(struct class_device *cdev, char *buf)
++static ssize_t show_orig_dgid(struct device *dev,
++			      struct device_attribute *attr, char *buf)
+ {
+-	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ 
+ 	if (target->state == SRP_TARGET_DEAD ||
+ 	    target->state == SRP_TARGET_REMOVED)
+@@ -1541,9 +1549,10 @@ static ssize_t show_orig_dgid(struct class_device *cdev, char *buf)
+ 		       be16_to_cpu(target->orig_dgid[7]));
+ }
+ 
+-static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf)
++static ssize_t show_zero_req_lim(struct device *dev,
++				 struct device_attribute *attr, char *buf)
+ {
+-	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ 
+ 	if (target->state == SRP_TARGET_DEAD ||
+ 	    target->state == SRP_TARGET_REMOVED)
+@@ -1552,40 +1561,42 @@ static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf)
+ 	return sprintf(buf, "%d\n", target->zero_req_lim);
+ }
+ 
+-static ssize_t show_local_ib_port(struct class_device *cdev, char *buf)
++static ssize_t show_local_ib_port(struct device *dev,
++				  struct device_attribute *attr, char *buf)
+ {
+-	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ 
+ 	return sprintf(buf, "%d\n", target->srp_host->port);
+ }
+ 
+-static ssize_t show_local_ib_device(struct class_device *cdev, char *buf)
++static ssize_t show_local_ib_device(struct device *dev,
++				    struct device_attribute *attr, char *buf)
+ {
+-	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ 
+-	return sprintf(buf, "%s\n", target->srp_host->dev->dev->name);
++	return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name);
+ }
+ 
+-static CLASS_DEVICE_ATTR(id_ext,	  S_IRUGO, show_id_ext,		 NULL);
+-static CLASS_DEVICE_ATTR(ioc_guid,	  S_IRUGO, show_ioc_guid,	 NULL);
+-static CLASS_DEVICE_ATTR(service_id,	  S_IRUGO, show_service_id,	 NULL);
+-static CLASS_DEVICE_ATTR(pkey,		  S_IRUGO, show_pkey,		 NULL);
+-static CLASS_DEVICE_ATTR(dgid,		  S_IRUGO, show_dgid,		 NULL);
+-static CLASS_DEVICE_ATTR(orig_dgid,	  S_IRUGO, show_orig_dgid,	 NULL);
+-static CLASS_DEVICE_ATTR(zero_req_lim,	  S_IRUGO, show_zero_req_lim,	 NULL);
+-static CLASS_DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,	 NULL);
+-static CLASS_DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
+-
+-static struct class_device_attribute *srp_host_attrs[] = {
+-	&class_device_attr_id_ext,
+-	&class_device_attr_ioc_guid,
+-	&class_device_attr_service_id,
+-	&class_device_attr_pkey,
+-	&class_device_attr_dgid,
+-	&class_device_attr_orig_dgid,
+-	&class_device_attr_zero_req_lim,
+-	&class_device_attr_local_ib_port,
+-	&class_device_attr_local_ib_device,
++static DEVICE_ATTR(id_ext,	    S_IRUGO, show_id_ext,	   NULL);
++static DEVICE_ATTR(ioc_guid,	    S_IRUGO, show_ioc_guid,	   NULL);
++static DEVICE_ATTR(service_id,	    S_IRUGO, show_service_id,	   NULL);
++static DEVICE_ATTR(pkey,	    S_IRUGO, show_pkey,		   NULL);
++static DEVICE_ATTR(dgid,	    S_IRUGO, show_dgid,		   NULL);
++static DEVICE_ATTR(orig_dgid,	    S_IRUGO, show_orig_dgid,	   NULL);
++static DEVICE_ATTR(zero_req_lim,    S_IRUGO, show_zero_req_lim,	   NULL);
++static DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,   NULL);
++static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
++
++static struct device_attribute *srp_host_attrs[] = {
++	&dev_attr_id_ext,
++	&dev_attr_ioc_guid,
++	&dev_attr_service_id,
++	&dev_attr_pkey,
++	&dev_attr_dgid,
++	&dev_attr_orig_dgid,
++	&dev_attr_zero_req_lim,
++	&dev_attr_local_ib_port,
++	&dev_attr_local_ib_device,
+ 	NULL
+ };
+ 
+@@ -1613,7 +1624,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
+ 	sprintf(target->target_name, "SRP.T10:%016llX",
+ 		 (unsigned long long) be64_to_cpu(target->id_ext));
+ 
+-	if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device))
++	if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dma_device))
+ 		return -ENODEV;
+ 
+ 	memcpy(ids.port_id, &target->id_ext, 8);
+@@ -1637,17 +1648,17 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
+ 	return 0;
+ }
+ 
+-static void srp_release_class_dev(struct class_device *class_dev)
++static void srp_release_dev(struct device *dev)
+ {
+ 	struct srp_host *host =
+-		container_of(class_dev, struct srp_host, class_dev);
++		container_of(dev, struct srp_host, dev);
+ 
+ 	complete(&host->released);
+ }
+ 
+ static struct class srp_class = {
+ 	.name    = "infiniband_srp",
+-	.release = srp_release_class_dev
++	.dev_release = srp_release_dev
+ };
+ 
+ /*
+@@ -1835,11 +1846,12 @@ out:
+ 	return ret;
+ }
+ 
+-static ssize_t srp_create_target(struct class_device *class_dev,
++static ssize_t srp_create_target(struct device *dev,
++				 struct device_attribute *attr,
+ 				 const char *buf, size_t count)
+ {
+ 	struct srp_host *host =
+-		container_of(class_dev, struct srp_host, class_dev);
++		container_of(dev, struct srp_host, dev);
+ 	struct Scsi_Host *target_host;
+ 	struct srp_target_port *target;
+ 	int ret;
+@@ -1871,7 +1883,8 @@ static ssize_t srp_create_target(struct class_device *class_dev,
+ 	if (ret)
+ 		goto err;
+ 
+-	ib_get_cached_gid(host->dev->dev, host->port, 0, &target->path.sgid);
++	ib_get_cached_gid(host->srp_dev->dev, host->port, 0,
++			  &target->path.sgid);
+ 
+ 	shost_printk(KERN_DEBUG, target->scsi_host, PFX
+ 		     "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
+@@ -1926,27 +1939,27 @@ err:
+ 	return ret;
+ }
+ 
+-static CLASS_DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
++static DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
+ 
+-static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
++static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct srp_host *host =
+-		container_of(class_dev, struct srp_host, class_dev);
++	struct srp_host *host = container_of(dev, struct srp_host, dev);
+ 
+-	return sprintf(buf, "%s\n", host->dev->dev->name);
++	return sprintf(buf, "%s\n", host->srp_dev->dev->name);
+ }
+ 
+-static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
++static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+ 
+-static ssize_t show_port(struct class_device *class_dev, char *buf)
++static ssize_t show_port(struct device *dev, struct device_attribute *attr,
++			 char *buf)
+ {
+-	struct srp_host *host =
+-		container_of(class_dev, struct srp_host, class_dev);
++	struct srp_host *host = container_of(dev, struct srp_host, dev);
+ 
+ 	return sprintf(buf, "%d\n", host->port);
+ }
+ 
+-static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
++static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
+ 
+ static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
+ {
+@@ -1959,27 +1972,27 @@ static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
+ 	INIT_LIST_HEAD(&host->target_list);
+ 	spin_lock_init(&host->target_lock);
+ 	init_completion(&host->released);
+-	host->dev  = device;
++	host->srp_dev = device;
+ 	host->port = port;
+ 
+-	host->class_dev.class = &srp_class;
+-	host->class_dev.dev   = device->dev->dma_device;
+-	snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d",
++	host->dev.class = &srp_class;
++	host->dev.parent = device->dev->dma_device;
++	snprintf(host->dev.bus_id, BUS_ID_SIZE, "srp-%s-%d",
+ 		 device->dev->name, port);
+ 
+-	if (class_device_register(&host->class_dev))
++	if (device_register(&host->dev))
+ 		goto free_host;
+-	if (class_device_create_file(&host->class_dev, &class_device_attr_add_target))
++	if (device_create_file(&host->dev, &dev_attr_add_target))
+ 		goto err_class;
+-	if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev))
++	if (device_create_file(&host->dev, &dev_attr_ibdev))
+ 		goto err_class;
+-	if (class_device_create_file(&host->class_dev, &class_device_attr_port))
++	if (device_create_file(&host->dev, &dev_attr_port))
+ 		goto err_class;
+ 
+ 	return host;
+ 
+ err_class:
+-	class_device_unregister(&host->class_dev);
++	device_unregister(&host->dev);
+ 
+ free_host:
+ 	kfree(host);
+@@ -2084,7 +2097,7 @@ static void srp_remove_one(struct ib_device *device)
+ 	srp_dev = ib_get_client_data(device, &srp_client);
+ 
+ 	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
+-		class_device_unregister(&host->class_dev);
++		device_unregister(&host->dev);
+ 		/*
+ 		 * Wait for the sysfs entry to go away, so that no new
+ 		 * target ports can be created.
+@@ -2138,6 +2151,11 @@ static int __init srp_init_module(void)
+ {
+ 	int ret;
+ 
++	if (srp_sg_tablesize > 255) {
++		printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
++		srp_sg_tablesize = 255;
++	}
++
+ 	ib_srp_transport_template =
+ 		srp_attach_transport(&ib_srp_transport_functions);
+ 	if (!ib_srp_transport_template)
+diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
+index cb6eb81..63d2ae7 100644
+--- a/drivers/infiniband/ulp/srp/ib_srp.h
++++ b/drivers/infiniband/ulp/srp/ib_srp.h
+@@ -97,9 +97,9 @@ struct srp_device {
+ };
+ 
+ struct srp_host {
+-	struct srp_device      *dev;
++	struct srp_device      *srp_dev;
+ 	u8			port;
+-	struct class_device	class_dev;
++	struct device		dev;
+ 	struct list_head	target_list;
+ 	spinlock_t		target_lock;
+ 	struct completion	released;
+diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
+index 9dea14d..5f9d860 100644
+--- a/drivers/input/Kconfig
++++ b/drivers/input/Kconfig
+@@ -149,6 +149,15 @@ config INPUT_APMPOWER
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called apm-power.
+ 
++config XEN_KBDDEV_FRONTEND
++	tristate "Xen virtual keyboard and mouse support"
++	depends on XEN_FBDEV_FRONTEND
++	default y
++	help
++	  This driver implements the front-end of the Xen virtual
++	  keyboard and mouse device driver.  It communicates with a back-end
++	  in another domain.
++
+ comment "Input Device Drivers"
+ 
+ source "drivers/input/keyboard/Kconfig"
+diff --git a/drivers/input/Makefile b/drivers/input/Makefile
+index 2ae87b1..98c4f9a 100644
+--- a/drivers/input/Makefile
++++ b/drivers/input/Makefile
+@@ -23,3 +23,5 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN)	+= touchscreen/
+ obj-$(CONFIG_INPUT_MISC)	+= misc/
+ 
+ obj-$(CONFIG_INPUT_APMPOWER)	+= apm-power.o
++
++obj-$(CONFIG_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
+diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
+index 490918a..0d3ce7a 100644
+--- a/drivers/input/input-polldev.c
++++ b/drivers/input/input-polldev.c
+@@ -73,7 +73,7 @@ static void input_polled_device_work(struct work_struct *work)
+ 
+ static int input_open_polled_device(struct input_dev *input)
+ {
+-	struct input_polled_dev *dev = input->private;
++	struct input_polled_dev *dev = input_get_drvdata(input);
+ 	int error;
+ 
+ 	error = input_polldev_start_workqueue();
+@@ -91,7 +91,7 @@ static int input_open_polled_device(struct input_dev *input)
+ 
+ static void input_close_polled_device(struct input_dev *input)
+ {
+-	struct input_polled_dev *dev = input->private;
++	struct input_polled_dev *dev = input_get_drvdata(input);
+ 
+ 	cancel_delayed_work_sync(&dev->work);
+ 	input_polldev_stop_workqueue();
+@@ -151,10 +151,10 @@ int input_register_polled_device(struct input_polled_dev *dev)
+ {
+ 	struct input_dev *input = dev->input;
+ 
++	input_set_drvdata(input, dev);
+ 	INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
+ 	if (!dev->poll_interval)
+ 		dev->poll_interval = 500;
+-	input->private = dev;
+ 	input->open = input_open_polled_device;
+ 	input->close = input_close_polled_device;
+ 
+diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
+index 7c662ee..be5c14a 100644
+--- a/drivers/input/joystick/Kconfig
++++ b/drivers/input/joystick/Kconfig
+@@ -193,6 +193,18 @@ config JOYSTICK_TWIDJOY
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called twidjoy.
+ 
++config JOYSTICK_ZHENHUA
++	tristate "5-byte Zhenhua RC transmitter"
++	select SERIO
++	help
++	  Say Y here if you have a Zhen Hua PPM-4CH transmitter which is
++	  supplied with a ready to fly micro electric indoor helicopters
++	  such as EasyCopter, Lama, MiniCopter, DragonFly or Jabo and want
++	  to use it via serial cable as a joystick.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called zhenhua.
++
+ config JOYSTICK_DB9
+ 	tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
+ 	depends on PARPORT
+diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
+index e855abb..fdbf8c4 100644
+--- a/drivers/input/joystick/Makefile
++++ b/drivers/input/joystick/Makefile
+@@ -15,6 +15,7 @@ obj-$(CONFIG_JOYSTICK_GF2K)		+= gf2k.o
+ obj-$(CONFIG_JOYSTICK_GRIP)		+= grip.o
+ obj-$(CONFIG_JOYSTICK_GRIP_MP)		+= grip_mp.o
+ obj-$(CONFIG_JOYSTICK_GUILLEMOT)	+= guillemot.o
++obj-$(CONFIG_JOYSTICK_IFORCE)		+= iforce/
+ obj-$(CONFIG_JOYSTICK_INTERACT)		+= interact.o
+ obj-$(CONFIG_JOYSTICK_JOYDUMP)		+= joydump.o
+ obj-$(CONFIG_JOYSTICK_MAGELLAN)		+= magellan.o
+@@ -27,5 +28,5 @@ obj-$(CONFIG_JOYSTICK_TURBOGRAFX)	+= turbografx.o
+ obj-$(CONFIG_JOYSTICK_TWIDJOY)		+= twidjoy.o
+ obj-$(CONFIG_JOYSTICK_WARRIOR)		+= warrior.o
+ obj-$(CONFIG_JOYSTICK_XPAD)		+= xpad.o
++obj-$(CONFIG_JOYSTICK_ZHENHUA)		+= zhenhua.o
+ 
+-obj-$(CONFIG_JOYSTICK_IFORCE)		+= iforce/
+diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
+index 0380597..4b07bda 100644
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -1,5 +1,5 @@
+ /*
+- * X-Box gamepad - v0.0.6
++ * X-Box gamepad driver
+  *
+  * Copyright (c) 2002 Marko Friedemann <mfr at bmx-chemnitz.de>
+  *               2004 Oliver Schwartz <Oliver.Schwartz at gmx.de>,
+@@ -68,6 +68,8 @@
+  *  - dance pads will map D-PAD to buttons, not axes
+  *  - pass the module paramater 'dpad_to_buttons' to force
+  *    the D-PAD to map to buttons if your pad is not detected
++ *
++ * Later changes can be tracked in SCM.
+  */
+ 
+ #include <linux/kernel.h>
+@@ -77,7 +79,6 @@
+ #include <linux/module.h>
+ #include <linux/usb/input.h>
+ 
+-#define DRIVER_VERSION "v0.0.6"
+ #define DRIVER_AUTHOR "Marko Friedemann <mfr at bmx-chemnitz.de>"
+ #define DRIVER_DESC "X-Box pad driver"
+ 
+@@ -87,10 +88,12 @@
+    but we map them to axes when possible to simplify things */
+ #define MAP_DPAD_TO_BUTTONS    0
+ #define MAP_DPAD_TO_AXES       1
+-#define MAP_DPAD_UNKNOWN       -1
++#define MAP_DPAD_UNKNOWN       2
+ 
+ #define XTYPE_XBOX        0
+ #define XTYPE_XBOX360     1
++#define XTYPE_XBOX360W    2
++#define XTYPE_UNKNOWN     3
+ 
+ static int dpad_to_buttons;
+ module_param(dpad_to_buttons, bool, S_IRUGO);
+@@ -107,8 +110,10 @@ static const struct xpad_device {
+ 	{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ 	{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ 	{ 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
++	{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
+ 	{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ 	{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
++	{ 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+ 	{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ 	{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ 	{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+@@ -135,18 +140,26 @@ static const struct xpad_device {
+ 	{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ 	{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ 	{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
++	{ 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+ 	{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ 	{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+ 	{ 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+-	{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX }
++	{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN }
+ };
+ 
+-static const signed short xpad_btn[] = {
+-	BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z,	/* "analog" buttons */
++/* buttons shared with xbox and xbox360 */
++static const signed short xpad_common_btn[] = {
++	BTN_A, BTN_B, BTN_X, BTN_Y,			/* "analog" buttons */
+ 	BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR,	/* start/back/sticks */
+ 	-1						/* terminating entry */
+ };
+ 
++/* original xbox controllers only */
++static const signed short xpad_btn[] = {
++	BTN_C, BTN_Z,		/* "analog" buttons */
++	-1			/* terminating entry */
++};
++
+ /* only used if MAP_DPAD_TO_BUTTONS */
+ static const signed short xpad_btn_pad[] = {
+ 	BTN_LEFT, BTN_RIGHT,		/* d-pad left, right */
+@@ -173,12 +186,27 @@ static const signed short xpad_abs_pad[] = {
+ 	-1			/* terminating entry */
+ };
+ 
+-/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
+- * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
+- * but we need only one of them. */
++/* Xbox 360 has a vendor-specific class, so we cannot match it with only
++ * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
++ * match against vendor id as well. Wired Xbox 360 devices have protocol 1,
++ * wireless controllers have protocol 129. */
++#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
++	.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
++	.idVendor = (vend), \
++	.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
++	.bInterfaceSubClass = 93, \
++	.bInterfaceProtocol = (pr)
++#define XPAD_XBOX360_VENDOR(vend) \
++	{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
++	{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }
++
+ static struct usb_device_id xpad_table [] = {
+ 	{ USB_INTERFACE_INFO('X', 'B', 0) },	/* X-Box USB-IF not approved class */
+-	{ USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) },	/* X-Box 360 controller */
++	XPAD_XBOX360_VENDOR(0x045e),		/* Microsoft X-Box 360 controllers */
++	XPAD_XBOX360_VENDOR(0x046d),		/* Logitech X-Box 360 style controllers */
++	XPAD_XBOX360_VENDOR(0x0738),		/* Mad Catz X-Box 360 controllers */
++	XPAD_XBOX360_VENDOR(0x0e6f),		/* 0x0e6f X-Box 360 controllers */
++	XPAD_XBOX360_VENDOR(0x1430),		/* RedOctane X-Box 360 controllers */
+ 	{ }
+ };
+ 
+@@ -188,10 +216,15 @@ struct usb_xpad {
+ 	struct input_dev *dev;		/* input device interface */
+ 	struct usb_device *udev;	/* usb device */
+ 
++	int pad_present;
++
+ 	struct urb *irq_in;		/* urb for interrupt in report */
+ 	unsigned char *idata;		/* input data */
+ 	dma_addr_t idata_dma;
+ 
++	struct urb *bulk_out;
++	unsigned char *bdata;
++
+ #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
+ 	struct urb *irq_out;		/* urb for interrupt out report */
+ 	unsigned char *odata;		/* output data */
+@@ -227,13 +260,13 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
+ 	input_report_abs(dev, ABS_X,
+ 			 (__s16) le16_to_cpup((__le16 *)(data + 12)));
+ 	input_report_abs(dev, ABS_Y,
+-			 (__s16) le16_to_cpup((__le16 *)(data + 14)));
++			 ~(__s16) le16_to_cpup((__le16 *)(data + 14)));
+ 
+ 	/* right stick */
+ 	input_report_abs(dev, ABS_RX,
+ 			 (__s16) le16_to_cpup((__le16 *)(data + 16)));
+ 	input_report_abs(dev, ABS_RY,
+-			 (__s16) le16_to_cpup((__le16 *)(data + 18)));
++			 ~(__s16) le16_to_cpup((__le16 *)(data + 18)));
+ 
+ 	/* triggers left/right */
+ 	input_report_abs(dev, ABS_Z, data[10]);
+@@ -321,13 +354,13 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
+ 	input_report_abs(dev, ABS_X,
+ 			 (__s16) le16_to_cpup((__le16 *)(data + 6)));
+ 	input_report_abs(dev, ABS_Y,
+-			 (__s16) le16_to_cpup((__le16 *)(data + 8)));
++			 ~(__s16) le16_to_cpup((__le16 *)(data + 8)));
+ 
+ 	/* right stick */
+ 	input_report_abs(dev, ABS_RX,
+ 			 (__s16) le16_to_cpup((__le16 *)(data + 10)));
+ 	input_report_abs(dev, ABS_RY,
+-			 (__s16) le16_to_cpup((__le16 *)(data + 12)));
++			 ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
+ 
+ 	/* triggers left/right */
+ 	input_report_abs(dev, ABS_Z, data[4]);
+@@ -336,12 +369,47 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
+ 	input_sync(dev);
+ }
+ 
++/*
++ * xpad360w_process_packet
++ *
++ * Completes a request by converting the data into events for the
++ * input subsystem. It is version for xbox 360 wireless controller.
++ *
++ * Byte.Bit
++ * 00.1 - Status change: The controller or headset has connected/disconnected
++ *                       Bits 01.7 and 01.6 are valid
++ * 01.7 - Controller present
++ * 01.6 - Headset present
++ * 01.1 - Pad state (Bytes 4+) valid
++ *
++ */
++
++static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
++{
++	/* Presence change */
++	if (data[0] & 0x08) {
++		if (data[1] & 0x80) {
++			xpad->pad_present = 1;
++			usb_submit_urb(xpad->bulk_out, GFP_ATOMIC);
++		} else
++			xpad->pad_present = 0;
++	}
++
++	/* Valid pad data */
++	if (!(data[1] & 0x1))
++		return;
++
++	xpad360_process_packet(xpad, cmd, &data[4]);
++}
++
+ static void xpad_irq_in(struct urb *urb)
+ {
+ 	struct usb_xpad *xpad = urb->context;
+-	int retval;
++	int retval, status;
+ 
+-	switch (urb->status) {
++	status = urb->status;
++
++	switch (status) {
+ 	case 0:
+ 		/* success */
+ 		break;
+@@ -350,18 +418,24 @@ static void xpad_irq_in(struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-			__FUNCTION__, urb->status);
++			__FUNCTION__, status);
+ 		return;
+ 	default:
+ 		dbg("%s - nonzero urb status received: %d",
+-			__FUNCTION__, urb->status);
++			__FUNCTION__, status);
+ 		goto exit;
+ 	}
+ 
+-	if (xpad->xtype == XTYPE_XBOX360)
++	switch (xpad->xtype) {
++	case XTYPE_XBOX360:
+ 		xpad360_process_packet(xpad, 0, xpad->idata);
+-	else
++		break;
++	case XTYPE_XBOX360W:
++		xpad360w_process_packet(xpad, 0, xpad->idata);
++		break;
++	default:
+ 		xpad_process_packet(xpad, 0, xpad->idata);
++	}
+ 
+ exit:
+ 	retval = usb_submit_urb (urb, GFP_ATOMIC);
+@@ -373,9 +447,11 @@ exit:
+ #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
+ static void xpad_irq_out(struct urb *urb)
+ {
+-	int retval;
++	int retval, status;
+ 
+-	switch (urb->status) {
++	status = urb->status;
++
++	switch (status) {
+ 		case 0:
+ 		/* success */
+ 		break;
+@@ -384,11 +460,11 @@ static void xpad_irq_out(struct urb *urb)
+ 		case -ESHUTDOWN:
+ 			/* this urb is terminated, clean up */
+ 			dbg("%s - urb shutting down with status: %d",
+-				__FUNCTION__, urb->status);
++				__FUNCTION__, status);
+ 			return;
+ 		default:
+ 			dbg("%s - nonzero urb status received: %d",
+-				__FUNCTION__, urb->status);
++				__FUNCTION__, status);
+ 			goto exit;
+ 	}
+ 
+@@ -399,6 +475,23 @@ exit:
+ 		    __FUNCTION__, retval);
+ }
+ 
++static void xpad_bulk_out(struct urb *urb)
++{
++	switch (urb->status) {
++	case 0:
++		/* success */
++		break;
++	case -ECONNRESET:
++	case -ENOENT:
++	case -ESHUTDOWN:
++		/* this urb is terminated, clean up */
++		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
++		break;
++	default:
++		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
++	}
++}
++
+ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
+ {
+ 	struct usb_endpoint_descriptor *ep_irq_out;
+@@ -408,7 +501,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
+ 		return 0;
+ 
+ 	xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
+-				       GFP_ATOMIC, &xpad->odata_dma );
++				       GFP_KERNEL, &xpad->odata_dma);
+ 	if (!xpad->odata)
+ 		goto fail1;
+ 
+@@ -469,6 +562,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
+ 		xpad->odata[5] = 0x00;
+ 		xpad->odata[6] = 0x00;
+ 		xpad->odata[7] = 0x00;
++		xpad->irq_out->transfer_buffer_length = 8;
+ 		usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+ 	}
+ 
+@@ -477,6 +571,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
+ 
+ static int xpad_init_ff(struct usb_xpad *xpad)
+ {
++	if (xpad->xtype != XTYPE_XBOX360)
++		return 0;
++
+ 	input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
+ 
+ 	return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
+@@ -502,6 +599,7 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
+ 		xpad->odata[0] = 0x01;
+ 		xpad->odata[1] = 0x03;
+ 		xpad->odata[2] = command;
++		xpad->irq_out->transfer_buffer_length = 3;
+ 		usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+ 		mutex_unlock(&xpad->odata_mutex);
+ 	}
+@@ -574,6 +672,10 @@ static int xpad_open(struct input_dev *dev)
+ {
+ 	struct usb_xpad *xpad = input_get_drvdata(dev);
+ 
++	/* URB was submitted in probe */
++	if(xpad->xtype == XTYPE_XBOX360W)
++		return 0;
++
+ 	xpad->irq_in->dev = xpad->udev;
+ 	if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
+ 		return -EIO;
+@@ -585,7 +687,8 @@ static void xpad_close(struct input_dev *dev)
+ {
+ 	struct usb_xpad *xpad = input_get_drvdata(dev);
+ 
+-	usb_kill_urb(xpad->irq_in);
++	if(xpad->xtype != XTYPE_XBOX360W)
++		usb_kill_urb(xpad->irq_in);
+ 	xpad_stop_output(xpad);
+ }
+ 
+@@ -632,7 +735,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
+ 		goto fail1;
+ 
+ 	xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
+-				       GFP_ATOMIC, &xpad->idata_dma);
++				       GFP_KERNEL, &xpad->idata_dma);
+ 	if (!xpad->idata)
+ 		goto fail1;
+ 
+@@ -644,7 +747,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
+ 	xpad->dpad_mapping = xpad_device[i].dpad_mapping;
+ 	xpad->xtype = xpad_device[i].xtype;
+ 	if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
+-		xpad->dpad_mapping = dpad_to_buttons;
++		xpad->dpad_mapping = !dpad_to_buttons;
++	if (xpad->xtype == XTYPE_UNKNOWN) {
++		if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
++			if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
++				xpad->xtype = XTYPE_XBOX360W;
++			else
++				xpad->xtype = XTYPE_XBOX360;
++		} else
++			xpad->xtype = XTYPE_XBOX;
++	}
+ 	xpad->dev = input_dev;
+ 	usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
+ 	strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
+@@ -662,11 +774,14 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
+ 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ 
+ 	/* set up buttons */
+-	for (i = 0; xpad_btn[i] >= 0; i++)
+-		set_bit(xpad_btn[i], input_dev->keybit);
+-	if (xpad->xtype == XTYPE_XBOX360)
++	for (i = 0; xpad_common_btn[i] >= 0; i++)
++		set_bit(xpad_common_btn[i], input_dev->keybit);
++	if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W))
+ 		for (i = 0; xpad360_btn[i] >= 0; i++)
+ 			set_bit(xpad360_btn[i], input_dev->keybit);
++	else
++		for (i = 0; xpad_btn[i] >= 0; i++)
++			set_bit(xpad_btn[i], input_dev->keybit);
+ 	if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
+ 		for (i = 0; xpad_btn_pad[i] >= 0; i++)
+ 			set_bit(xpad_btn_pad[i], input_dev->keybit);
+@@ -703,8 +818,57 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
+ 		goto fail4;
+ 
+ 	usb_set_intfdata(intf, xpad);
++
++	/*
++	 * Submit the int URB immediatly rather than waiting for open
++	 * because we get status messages from the device whether
++	 * or not any controllers are attached.  In fact, it's
++	 * exactly the message that a controller has arrived that
++	 * we're waiting for.
++	 */
++	if (xpad->xtype == XTYPE_XBOX360W) {
++		xpad->irq_in->dev = xpad->udev;
++		error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
++		if (error)
++			goto fail4;
++
++		/*
++		 * Setup the message to set the LEDs on the
++		 * controller when it shows up
++		 */
++		xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL);
++		if(!xpad->bulk_out)
++			goto fail5;
++
++		xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL);
++		if(!xpad->bdata)
++			goto fail6;
++
++		xpad->bdata[2] = 0x08;
++		switch (intf->cur_altsetting->desc.bInterfaceNumber) {
++		case 0:
++			xpad->bdata[3] = 0x42;
++			break;
++		case 2:
++			xpad->bdata[3] = 0x43;
++			break;
++		case 4:
++			xpad->bdata[3] = 0x44;
++			break;
++		case 6:
++			xpad->bdata[3] = 0x45;
++		}
++
++		ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
++		usb_fill_bulk_urb(xpad->bulk_out, udev,
++				usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
++				xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
++	}
++
+ 	return 0;
+ 
++ fail6:	usb_free_urb(xpad->bulk_out);
++ fail5:	usb_kill_urb(xpad->irq_in);
+  fail4:	usb_free_urb(xpad->irq_in);
+  fail3:	xpad_deinit_output(xpad);
+  fail2:	usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+@@ -723,6 +887,11 @@ static void xpad_disconnect(struct usb_interface *intf)
+ 		xpad_led_disconnect(xpad);
+ 		input_unregister_device(xpad->dev);
+ 		xpad_deinit_output(xpad);
++		if (xpad->xtype == XTYPE_XBOX360W) {
++			usb_kill_urb(xpad->bulk_out);
++			usb_free_urb(xpad->bulk_out);
++			usb_kill_urb(xpad->irq_in);
++		}
+ 		usb_free_urb(xpad->irq_in);
+ 		usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
+ 				xpad->idata, xpad->idata_dma);
+@@ -741,7 +910,7 @@ static int __init usb_xpad_init(void)
+ {
+ 	int result = usb_register(&xpad_driver);
+ 	if (result == 0)
+-		info(DRIVER_DESC ":" DRIVER_VERSION);
++		info(DRIVER_DESC);
+ 	return result;
+ }
+ 
+diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c
+new file mode 100644
+index 0000000..b585312
+--- /dev/null
++++ b/drivers/input/joystick/zhenhua.c
+@@ -0,0 +1,243 @@
++/*
++ *  derived from "twidjoy.c"
++ *
++ *  Copyright (c) 2008 Martin Kebert
++ *  Copyright (c) 2001 Arndt Schoenewald
++ *  Copyright (c) 2000-2001 Vojtech Pavlik
++ *  Copyright (c) 2000 Mark Fletcher
++ *
++ */
++
++/*
++ * Driver to use 4CH RC transmitter using Zhen Hua 5-byte protocol (Walkera Lama,
++ * EasyCopter etc.) as a joystick under Linux.
++ *
++ * RC transmitters using Zhen Hua 5-byte protocol are cheap four channels
++ * transmitters for control a RC planes or RC helicopters with possibility to
++ * connect on a serial port.
++ * Data coming from transmitter is in this order:
++ * 1. byte = synchronisation byte
++ * 2. byte = X axis
++ * 3. byte = Y axis
++ * 4. byte = RZ axis
++ * 5. byte = Z axis
++ * (and this is repeated)
++ *
++ * For questions or feedback regarding this driver module please contact:
++ * Martin Kebert <gkmarty at gmail.com> - but I am not a C-programmer nor kernel
++ * coder :-(
++ */
++
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/input.h>
++#include <linux/serio.h>
++#include <linux/init.h>
++
++#define DRIVER_DESC	"RC transmitter with 5-byte Zhen Hua protocol joystick driver"
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
++
++/*
++ * Constants.
++ */
++
++#define ZHENHUA_MAX_LENGTH 5
++
++/*
++ * Zhen Hua data.
++ */
++
++struct zhenhua {
++	struct input_dev *dev;
++	int idx;
++	unsigned char data[ZHENHUA_MAX_LENGTH];
++	char phys[32];
++};
++
++
++/* bits in all incoming bytes needs to be "reversed" */
++static int zhenhua_bitreverse(int x)
++{
++	x = ((x & 0xaa) >> 1) | ((x & 0x55) << 1);
++	x = ((x & 0xcc) >> 2) | ((x & 0x33) << 2);
++	x = ((x & 0xf0) >> 4) | ((x & 0x0f) << 4);
++	return x;
++}
++
++/*
++ * zhenhua_process_packet() decodes packets the driver receives from the
++ * RC transmitter. It updates the data accordingly.
++ */
++
++static void zhenhua_process_packet(struct zhenhua *zhenhua)
++{
++	struct input_dev *dev = zhenhua->dev;
++	unsigned char *data = zhenhua->data;
++
++	input_report_abs(dev, ABS_Y, data[1]);
++	input_report_abs(dev, ABS_X, data[2]);
++	input_report_abs(dev, ABS_RZ, data[3]);
++	input_report_abs(dev, ABS_Z, data[4]);
++
++	input_sync(dev);
++}
++
++/*
++ * zhenhua_interrupt() is called by the low level driver when characters
++ * are ready for us. We then buffer them for further processing, or call the
++ * packet processing routine.
++ */
++
++static irqreturn_t zhenhua_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
++{
++	struct zhenhua *zhenhua = serio_get_drvdata(serio);
++
++	/* All Zhen Hua packets are 5 bytes. The fact that the first byte
++	 * is allways 0xf7 and all others are in range 0x32 - 0xc8 (50-200)
++	 * can be used to check and regain sync. */
++
++	if (data == 0xef)
++		zhenhua->idx = 0;	/* this byte starts a new packet */
++	else if (zhenhua->idx == 0)
++		return IRQ_HANDLED;	/* wrong MSB -- ignore this byte */
++
++	if (zhenhua->idx < ZHENHUA_MAX_LENGTH)
++		zhenhua->data[zhenhua->idx++] = zhenhua_bitreverse(data);
++
++	if (zhenhua->idx == ZHENHUA_MAX_LENGTH) {
++		zhenhua_process_packet(zhenhua);
++		zhenhua->idx = 0;
++	}
++
++	return IRQ_HANDLED;
++}
++
++/*
++ * zhenhua_disconnect() is the opposite of zhenhua_connect()
++ */
++
++static void zhenhua_disconnect(struct serio *serio)
++{
++	struct zhenhua *zhenhua = serio_get_drvdata(serio);
++
++	serio_close(serio);
++	serio_set_drvdata(serio, NULL);
++	input_unregister_device(zhenhua->dev);
++	kfree(zhenhua);
++}
++
++/*
++ * zhenhua_connect() is the routine that is called when someone adds a
++ * new serio device. It looks for the Twiddler, and if found, registers
++ * it as an input device.
++ */
++
++static int zhenhua_connect(struct serio *serio, struct serio_driver *drv)
++{
++	struct zhenhua *zhenhua;
++	struct input_dev *input_dev;
++	int err = -ENOMEM;
++
++	zhenhua = kzalloc(sizeof(struct zhenhua), GFP_KERNEL);
++	input_dev = input_allocate_device();
++	if (!zhenhua || !input_dev)
++		goto fail1;
++
++	zhenhua->dev = input_dev;
++	snprintf(zhenhua->phys, sizeof(zhenhua->phys), "%s/input0", serio->phys);
++
++	input_dev->name = "Zhen Hua 5-byte device";
++	input_dev->phys = zhenhua->phys;
++	input_dev->id.bustype = BUS_RS232;
++	input_dev->id.vendor = SERIO_ZHENHUA;
++	input_dev->id.product = 0x0001;
++	input_dev->id.version = 0x0100;
++	input_dev->dev.parent = &serio->dev;
++
++	input_dev->evbit[0] = BIT(EV_ABS);
++	input_set_abs_params(input_dev, ABS_X, 50, 200, 0, 0);
++	input_set_abs_params(input_dev, ABS_Y, 50, 200, 0, 0);
++	input_set_abs_params(input_dev, ABS_Z, 50, 200, 0, 0);
++	input_set_abs_params(input_dev, ABS_RZ, 50, 200, 0, 0);
++
++	serio_set_drvdata(serio, zhenhua);
++
++	err = serio_open(serio, drv);
++	if (err)
++		goto fail2;
++
++	err = input_register_device(zhenhua->dev);
++	if (err)
++		goto fail3;
++
++	return 0;
++
++ fail3:	serio_close(serio);
++ fail2:	serio_set_drvdata(serio, NULL);
++ fail1:	input_free_device(input_dev);
++	kfree(zhenhua);
++	return err;
++}
++
++/*
++ * The serio driver structure.
++ */
++
++static struct serio_device_id zhenhua_serio_ids[] = {
++	{
++		.type	= SERIO_RS232,
++		.proto	= SERIO_ZHENHUA,
++		.id	= SERIO_ANY,
++		.extra	= SERIO_ANY,
++	},
++	{ 0 }
++};
++
++MODULE_DEVICE_TABLE(serio, zhenhua_serio_ids);
++
++static struct serio_driver zhenhua_drv = {
++	.driver		= {
++		.name	= "zhenhua",
++	},
++	.description	= DRIVER_DESC,
++	.id_table	= zhenhua_serio_ids,
++	.interrupt	= zhenhua_interrupt,
++	.connect	= zhenhua_connect,
++	.disconnect	= zhenhua_disconnect,
++};
++
++/*
++ * The functions for inserting/removing us as a module.
++ */
++
++static int __init zhenhua_init(void)
++{
++	return serio_register_driver(&zhenhua_drv);
++}
++
++static void __exit zhenhua_exit(void)
++{
++	serio_unregister_driver(&zhenhua_drv);
++}
++
++module_init(zhenhua_init);
++module_exit(zhenhua_exit);
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index 8ea709b..efd70a9 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -314,4 +314,13 @@ config KEYBOARD_BFIN
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called bf54x-keys.
+ 
++config KEYBOARD_SH_KEYSC
++	tristate "SuperH KEYSC keypad support"
++	depends on SUPERH
++	help
++	  Say Y here if you want to use a keypad attached to the KEYSC block
++	  on SuperH processors such as sh7722 and sh7343.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called sh_keysc.
+ endif
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index e741f40..0edc8f2 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -26,3 +26,4 @@ obj-$(CONFIG_KEYBOARD_HP6XX)		+= jornada680_kbd.o
+ obj-$(CONFIG_KEYBOARD_HP7XX)		+= jornada720_kbd.o
+ obj-$(CONFIG_KEYBOARD_MAPLE)		+= maple_keyb.o
+ obj-$(CONFIG_KEYBOARD_BFIN)		+= bf54x-keys.o
++obj-$(CONFIG_KEYBOARD_SH_KEYSC)		+= sh_keysc.o
+diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c
+index 72abc19..a293e8b 100644
+--- a/drivers/input/keyboard/aaed2000_kbd.c
++++ b/drivers/input/keyboard/aaed2000_kbd.c
+@@ -156,11 +156,15 @@ static int __devexit aaedkbd_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:aaed2000-keyboard");
++
+ static struct platform_driver aaedkbd_driver = {
+ 	.probe		= aaedkbd_probe,
+ 	.remove		= __devexit_p(aaedkbd_remove),
+ 	.driver		= {
+ 		.name	= "aaed2000-keyboard",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
+index 05e3494..54ed8e2 100644
+--- a/drivers/input/keyboard/bf54x-keys.c
++++ b/drivers/input/keyboard/bf54x-keys.c
+@@ -312,6 +312,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev)
+ 
+ 	bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
+ 
++	device_init_wakeup(&pdev->dev, 1);
++
+ 	printk(KERN_ERR DRV_NAME
+ 		": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq);
+ 
+@@ -354,12 +356,40 @@ static int __devexit bfin_kpad_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_PM
++static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
++
++	if (device_may_wakeup(&pdev->dev))
++		enable_irq_wake(bf54x_kpad->irq);
++
++	return 0;
++}
++
++static int bfin_kpad_resume(struct platform_device *pdev)
++{
++	struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
++
++	if (device_may_wakeup(&pdev->dev))
++		disable_irq_wake(bf54x_kpad->irq);
++
++	return 0;
++}
++#else
++# define bfin_kpad_suspend NULL
++# define bfin_kpad_resume  NULL
++#endif
++
+ struct platform_driver bfin_kpad_device_driver = {
+-	.probe		= bfin_kpad_probe,
+-	.remove		= __devexit_p(bfin_kpad_remove),
+ 	.driver		= {
+ 		.name	= DRV_NAME,
+-	}
++		.owner	= THIS_MODULE,
++	},
++	.probe		= bfin_kpad_probe,
++	.remove		= __devexit_p(bfin_kpad_remove),
++	.suspend	= bfin_kpad_suspend,
++	.resume		= bfin_kpad_resume,
+ };
+ 
+ static int __init bfin_kpad_init(void)
+@@ -378,3 +408,4 @@ module_exit(bfin_kpad_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Michael Hennerich <hennerich at blackfin.uclinux.org>");
+ MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
++MODULE_ALIAS("platform:bf54x-keys");
+diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
+index 790fed3..29fbec6 100644
+--- a/drivers/input/keyboard/corgikbd.c
++++ b/drivers/input/keyboard/corgikbd.c
+@@ -23,6 +23,7 @@
+ #include <asm/arch/corgi.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/hardware/scoop.h>
+ 
+ #define KB_ROWS				8
+@@ -392,6 +393,7 @@ static struct platform_driver corgikbd_driver = {
+ 	.resume		= corgikbd_resume,
+ 	.driver		= {
+ 		.name	= "corgi-keyboard",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -411,3 +413,4 @@ module_exit(corgikbd_exit);
+ MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
+ MODULE_DESCRIPTION("Corgi Keyboard Driver");
+ MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("platform:corgi-keyboard");
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index 6a9ca4b..bbd00c3 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -43,10 +43,11 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
+ 
+ 			input_event(input, type, button->code, !!state);
+ 			input_sync(input);
++			return IRQ_HANDLED;
+ 		}
+ 	}
+ 
+-	return IRQ_HANDLED;
++	return IRQ_NONE;
+ }
+ 
+ static int __devinit gpio_keys_probe(struct platform_device *pdev)
+@@ -213,6 +214,7 @@ struct platform_driver gpio_keys_device_driver = {
+ 	.resume		= gpio_keys_resume,
+ 	.driver		= {
+ 		.name	= "gpio-keys",
++		.owner	= THIS_MODULE,
+ 	}
+ };
+ 
+@@ -232,3 +234,4 @@ module_exit(gpio_keys_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Phil Blundell <pb at handhelds.org>");
+ MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
++MODULE_ALIAS("platform:gpio-keys");
+diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
+index a23633a..9387da3 100644
+--- a/drivers/input/keyboard/jornada680_kbd.c
++++ b/drivers/input/keyboard/jornada680_kbd.c
+@@ -254,6 +254,7 @@ static int __devexit jornada680kbd_remove(struct platform_device *pdev)
+ static struct platform_driver jornada680kbd_driver = {
+ 	.driver	= {
+ 		.name	= "jornada680_kbd",
++		.owner	= THIS_MODULE,
+ 	},
+ 	.probe	= jornada680kbd_probe,
+ 	.remove	= __devexit_p(jornada680kbd_remove),
+@@ -275,3 +276,4 @@ module_exit(jornada680kbd_exit);
+ MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson at gmail.com>");
+ MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");
+ MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("platform:jornada680_kbd");
+diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
+index 986f93c..a1164a0 100644
+--- a/drivers/input/keyboard/jornada720_kbd.c
++++ b/drivers/input/keyboard/jornada720_kbd.c
+@@ -162,9 +162,13 @@ static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:jornada720_kbd");
++
+ static struct platform_driver jornada720_kbd_driver = {
+ 	.driver  = {
+ 		.name    = "jornada720_kbd",
++		.owner	= THIS_MODULE,
+ 	 },
+ 	.probe   = jornada720_kbd_probe,
+ 	.remove  = __devexit_p(jornada720_kbd_remove),
+diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
+index 5a0ca18..9caed30 100644
+--- a/drivers/input/keyboard/locomokbd.c
++++ b/drivers/input/keyboard/locomokbd.c
+@@ -1,14 +1,12 @@
+ /*
+- *  Copyright (c) 2005 John Lenz
++ * LoCoMo keyboard driver for Linux-based ARM PDAs:
++ * 	- SHARP Zaurus Collie (SL-5500)
++ * 	- SHARP Zaurus Poodle (SL-5600)
+  *
++ * Copyright (c) 2005 John Lenz
+  * Based on from xtkbd.c
+- */
+-
+-/*
+- * LoCoMo keyboard driver for Linux/ARM
+- */
+-
+-/*
++ *
++ *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+@@ -47,7 +45,8 @@ MODULE_LICENSE("GPL");
+ #define KEY_CONTACT		KEY_F18
+ #define KEY_CENTER		KEY_F15
+ 
+-static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
++static const unsigned char
++locomokbd_keycode[LOCOMOKBD_NUMKEYS] __devinitconst = {
+ 	0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0,				/* 0 - 9 */
+ 	0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT,			/* 10 - 19 */
+ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,						/* 20 - 29 */
+@@ -67,22 +66,21 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
+ #define KB_COLS			8
+ #define KB_ROWMASK(r)		(1 << (r))
+ #define SCANCODE(c,r)		( ((c)<<4) + (r) + 1 )
+-#define	NR_SCANCODES		128
+ 
+ #define KB_DELAY		8
+ #define SCAN_INTERVAL		(HZ/10)
+-#define LOCOMOKBD_PRESSED	1
+ 
+ struct locomokbd {
+ 	unsigned char keycode[LOCOMOKBD_NUMKEYS];
+ 	struct input_dev *input;
+ 	char phys[32];
+ 
+-	struct locomo_dev *ldev;
+ 	unsigned long base;
+ 	spinlock_t lock;
+ 
+ 	struct timer_list timer;
++	unsigned long suspend_jiffies;
++	unsigned int count_cancel;
+ };
+ 
+ /* helper functions for reading the keyboard matrix */
+@@ -128,7 +126,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col)
+ /* Scan the hardware keyboard and push any changes up through the input layer */
+ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
+ {
+-	unsigned int row, col, rowd, scancode;
++	unsigned int row, col, rowd;
+ 	unsigned long flags;
+ 	unsigned int num_pressed;
+ 	unsigned long membase = locomokbd->base;
+@@ -145,13 +143,33 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
+ 
+ 		rowd = ~locomo_readl(membase + LOCOMO_KIB);
+ 		for (row = 0; row < KB_ROWS; row++) {
++			unsigned int scancode, pressed, key;
++
+ 			scancode = SCANCODE(col, row);
+-			if (rowd & KB_ROWMASK(row)) {
+-				num_pressed += 1;
+-				input_report_key(locomokbd->input, locomokbd->keycode[scancode], 1);
+-			} else {
+-				input_report_key(locomokbd->input, locomokbd->keycode[scancode], 0);
+-			}
++			pressed = rowd & KB_ROWMASK(row);
++			key = locomokbd->keycode[scancode];
++
++			input_report_key(locomokbd->input, key, pressed);
++			if (likely(!pressed))
++				continue;
++
++			num_pressed++;
++
++			/* The "Cancel/ESC" key is labeled "On/Off" on
++			 * Collie and Poodle and should suspend the device
++			 * if it was pressed for more than a second. */
++			if (unlikely(key == KEY_ESC)) {
++				if (!time_after(jiffies,
++					locomokbd->suspend_jiffies + HZ))
++					continue;
++				if (locomokbd->count_cancel++
++					!= (HZ/SCAN_INTERVAL + 1))
++					continue;
++				input_event(locomokbd->input, EV_PWR,
++					KEY_SUSPEND, 1);
++				locomokbd->suspend_jiffies = jiffies;
++			} else
++				locomokbd->count_cancel = 0;
+ 		}
+ 		locomokbd_reset_col(membase, col);
+ 	}
+@@ -162,6 +180,8 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
+ 	/* if any keys are pressed, enable the timer */
+ 	if (num_pressed)
+ 		mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
++	else
++		locomokbd->count_cancel = 0;
+ 
+ 	spin_unlock_irqrestore(&locomokbd->lock, flags);
+ }
+@@ -186,10 +206,11 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
+ static void locomokbd_timer_callback(unsigned long data)
+ {
+ 	struct locomokbd *locomokbd = (struct locomokbd *) data;
++
+ 	locomokbd_scankeyboard(locomokbd);
+ }
+ 
+-static int locomokbd_probe(struct locomo_dev *dev)
++static int __devinit locomokbd_probe(struct locomo_dev *dev)
+ {
+ 	struct locomokbd *locomokbd;
+ 	struct input_dev *input_dev;
+@@ -211,7 +232,6 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ 		goto err_free_mem;
+ 	}
+ 
+-	locomokbd->ldev = dev;
+ 	locomo_set_drvdata(dev, locomokbd);
+ 
+ 	locomokbd->base = (unsigned long) dev->mapbase;
+@@ -222,6 +242,8 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ 	locomokbd->timer.function = locomokbd_timer_callback;
+ 	locomokbd->timer.data = (unsigned long) locomokbd;
+ 
++	locomokbd->suspend_jiffies = jiffies;
++
+ 	locomokbd->input = input_dev;
+ 	strcpy(locomokbd->phys, "locomokbd/input0");
+ 
+@@ -233,9 +255,10 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ 	input_dev->id.version = 0x0100;
+ 	input_dev->dev.parent = &dev->dev;
+ 
+-	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
++	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
++				BIT_MASK(EV_PWR);
+ 	input_dev->keycode = locomokbd->keycode;
+-	input_dev->keycodesize = sizeof(unsigned char);
++	input_dev->keycodesize = sizeof(locomokbd_keycode[0]);
+ 	input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode);
+ 
+ 	memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
+@@ -268,7 +291,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ 	return err;
+ }
+ 
+-static int locomokbd_remove(struct locomo_dev *dev)
++static int __devexit locomokbd_remove(struct locomo_dev *dev)
+ {
+ 	struct locomokbd *locomokbd = locomo_get_drvdata(dev);
+ 
+@@ -292,7 +315,7 @@ static struct locomo_driver keyboard_driver = {
+ 	},
+ 	.devid	= LOCOMO_DEVID_KEYBOARD,
+ 	.probe	= locomokbd_probe,
+-	.remove	= locomokbd_remove,
++	.remove	= __devexit_p(locomokbd_remove),
+ };
+ 
+ static int __init locomokbd_init(void)
+diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
+index babc913..10afd20 100644
+--- a/drivers/input/keyboard/omap-keypad.c
++++ b/drivers/input/keyboard/omap-keypad.c
+@@ -352,6 +352,9 @@ static int __init omap_kp_probe(struct platform_device *pdev)
+ 			}
+ 			omap_set_gpio_direction(row_gpios[row_idx], 1);
+ 		}
++	} else {
++		col_idx = 0;
++		row_idx = 0;
+ 	}
+ 
+ 	setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
+@@ -415,10 +418,10 @@ err4:
+ err3:
+ 	device_remove_file(&pdev->dev, &dev_attr_enable);
+ err2:
+-	for (i = row_idx-1; i >=0; i--)
++	for (i = row_idx - 1; i >=0; i--)
+ 		omap_free_gpio(row_gpios[i]);
+ err1:
+-	for (i = col_idx-1; i >=0; i--)
++	for (i = col_idx - 1; i >=0; i--)
+ 		omap_free_gpio(col_gpios[i]);
+ 
+ 	kfree(omap_kp);
+@@ -464,6 +467,7 @@ static struct platform_driver omap_kp_driver = {
+ 	.resume		= omap_kp_resume,
+ 	.driver		= {
+ 		.name	= "omap-keypad",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -484,3 +488,4 @@ module_exit(omap_kp_exit);
+ MODULE_AUTHOR("Timo Teräs");
+ MODULE_DESCRIPTION("OMAP Keypad Driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:omap-keypad");
+diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
+index 4e651c1..3dea0c5 100644
+--- a/drivers/input/keyboard/pxa27x_keypad.c
++++ b/drivers/input/keyboard/pxa27x_keypad.c
+@@ -545,6 +545,9 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:pxa27x-keypad");
++
+ static struct platform_driver pxa27x_keypad_driver = {
+ 	.probe		= pxa27x_keypad_probe,
+ 	.remove		= __devexit_p(pxa27x_keypad_remove),
+@@ -552,6 +555,7 @@ static struct platform_driver pxa27x_keypad_driver = {
+ 	.resume		= pxa27x_keypad_resume,
+ 	.driver		= {
+ 		.name	= "pxa27x-keypad",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
+new file mode 100644
+index 0000000..8486abc
+--- /dev/null
++++ b/drivers/input/keyboard/sh_keysc.c
+@@ -0,0 +1,280 @@
++/*
++ * SuperH KEYSC Keypad Driver
++ *
++ * Copyright (C) 2008 Magnus Damm
++ *
++ * Based on gpio_keys.c, Copyright 2005 Phil Blundell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/input.h>
++#include <linux/io.h>
++#include <asm/sh_keysc.h>
++
++#define KYCR1_OFFS   0x00
++#define KYCR2_OFFS   0x04
++#define KYINDR_OFFS  0x08
++#define KYOUTDR_OFFS 0x0c
++
++#define KYCR2_IRQ_LEVEL    0x10
++#define KYCR2_IRQ_DISABLED 0x00
++
++static const struct {
++	unsigned char kymd, keyout, keyin;
++} sh_keysc_mode[] = {
++	[SH_KEYSC_MODE_1] = { 0, 6, 5 },
++	[SH_KEYSC_MODE_2] = { 1, 5, 6 },
++	[SH_KEYSC_MODE_3] = { 2, 4, 7 },
++};
++
++struct sh_keysc_priv {
++	void __iomem *iomem_base;
++	unsigned long last_keys;
++	struct input_dev *input;
++	struct sh_keysc_info pdata;
++};
++
++static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
++{
++	struct platform_device *pdev = dev_id;
++	struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
++	struct sh_keysc_info *pdata = &priv->pdata;
++	unsigned long keys, keys1, keys0, mask;
++	unsigned char keyin_set, tmp;
++	int i, k;
++
++	dev_dbg(&pdev->dev, "isr!\n");
++
++	keys1 = ~0;
++	keys0 = 0;
++
++	do {
++		keys = 0;
++		keyin_set = 0;
++
++		iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
++
++		for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) {
++			iowrite16(0xfff ^ (3 << (i * 2)),
++				  priv->iomem_base + KYOUTDR_OFFS);
++			udelay(pdata->delay);
++			tmp = ioread16(priv->iomem_base + KYINDR_OFFS);
++			keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i);
++			tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1;
++			keyin_set |= tmp;
++		}
++
++		iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
++		iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8),
++			  priv->iomem_base + KYCR2_OFFS);
++
++		keys ^= ~0;
++		keys &= (1 << (sh_keysc_mode[pdata->mode].keyin *
++			       sh_keysc_mode[pdata->mode].keyout)) - 1;
++		keys1 &= keys;
++		keys0 |= keys;
++
++		dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys);
++
++	} while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01);
++
++	dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n",
++		priv->last_keys, keys0, keys1);
++
++	for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
++		k = pdata->keycodes[i];
++		if (!k)
++			continue;
++
++		mask = 1 << i;
++
++		if (!((priv->last_keys ^ keys0) & mask))
++			continue;
++
++		if ((keys1 | keys0) & mask) {
++			input_event(priv->input, EV_KEY, k, 1);
++			priv->last_keys |= mask;
++		}
++
++		if (!(keys1 & mask)) {
++			input_event(priv->input, EV_KEY, k, 0);
++			priv->last_keys &= ~mask;
++		}
++
++	}
++	input_sync(priv->input);
++
++	return IRQ_HANDLED;
++}
++
++#define res_size(res) ((res)->end - (res)->start + 1)
++
++static int __devinit sh_keysc_probe(struct platform_device *pdev)
++{
++	struct sh_keysc_priv *priv;
++	struct sh_keysc_info *pdata;
++	struct resource *res;
++	struct input_dev *input;
++	int i, k;
++	int irq, error;
++
++	if (!pdev->dev.platform_data) {
++		dev_err(&pdev->dev, "no platform data defined\n");
++		error = -EINVAL;
++		goto err0;
++	}
++
++	error = -ENXIO;
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (res == NULL) {
++		dev_err(&pdev->dev, "failed to get I/O memory\n");
++		goto err0;
++	}
++
++	irq = platform_get_irq(pdev, 0);
++	if (irq < 0) {
++		dev_err(&pdev->dev, "failed to get irq\n");
++		goto err0;
++	}
++
++	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++	if (priv == NULL) {
++		dev_err(&pdev->dev, "failed to allocate driver data\n");
++		error = -ENOMEM;
++		goto err0;
++	}
++
++	platform_set_drvdata(pdev, priv);
++	memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata));
++	pdata = &priv->pdata;
++
++	res = request_mem_region(res->start, res_size(res), pdev->name);
++	if (res == NULL) {
++		dev_err(&pdev->dev, "failed to request I/O memory\n");
++		error = -EBUSY;
++		goto err1;
++	}
++
++	priv->iomem_base = ioremap_nocache(res->start, res_size(res));
++	if (priv->iomem_base == NULL) {
++		dev_err(&pdev->dev, "failed to remap I/O memory\n");
++		error = -ENXIO;
++		goto err2;
++	}
++
++	priv->input = input_allocate_device();
++	if (!priv->input) {
++		dev_err(&pdev->dev, "failed to allocate input device\n");
++		error = -ENOMEM;
++		goto err3;
++	}
++
++	input = priv->input;
++	input->evbit[0] = BIT_MASK(EV_KEY);
++
++	input->name = pdev->name;
++	input->phys = "sh-keysc-keys/input0";
++	input->dev.parent = &pdev->dev;
++
++	input->id.bustype = BUS_HOST;
++	input->id.vendor = 0x0001;
++	input->id.product = 0x0001;
++	input->id.version = 0x0100;
++
++	error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev);
++	if (error) {
++		dev_err(&pdev->dev, "failed to request IRQ\n");
++		goto err4;
++	}
++
++	for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
++		k = pdata->keycodes[i];
++		if (k)
++			input_set_capability(input, EV_KEY, k);
++	}
++
++	error = input_register_device(input);
++	if (error) {
++		dev_err(&pdev->dev, "failed to register input device\n");
++		goto err5;
++	}
++
++	iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) |
++		  pdata->scan_timing, priv->iomem_base + KYCR1_OFFS);
++	iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
++	iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS);
++	return 0;
++ err5:
++	free_irq(irq, pdev);
++ err4:
++	input_free_device(input);
++ err3:
++	iounmap(priv->iomem_base);
++ err2:
++	release_mem_region(res->start, res_size(res));
++ err1:
++	platform_set_drvdata(pdev, NULL);
++	kfree(priv);
++ err0:
++	return error;
++}
++
++static int __devexit sh_keysc_remove(struct platform_device *pdev)
++{
++	struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
++	struct resource *res;
++
++	iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
++
++	input_unregister_device(priv->input);
++	free_irq(platform_get_irq(pdev, 0), pdev);
++	iounmap(priv->iomem_base);
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	release_mem_region(res->start, res_size(res));
++
++	platform_set_drvdata(pdev, NULL);
++	kfree(priv);
++	return 0;
++}
++
++
++#define sh_keysc_suspend NULL
++#define sh_keysc_resume NULL
++
++struct platform_driver sh_keysc_device_driver = {
++	.probe		= sh_keysc_probe,
++	.remove		= __devexit_p(sh_keysc_remove),
++	.suspend	= sh_keysc_suspend,
++	.resume		= sh_keysc_resume,
++	.driver		= {
++		.name	= "sh_keysc",
++	}
++};
++
++static int __init sh_keysc_init(void)
++{
++	return platform_driver_register(&sh_keysc_device_driver);
++}
++
++static void __exit sh_keysc_exit(void)
++{
++	platform_driver_unregister(&sh_keysc_device_driver);
++}
++
++module_init(sh_keysc_init);
++module_exit(sh_keysc_exit);
++
++MODULE_AUTHOR("Magnus Damm");
++MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
+index 1d59a2d..61e401b 100644
+--- a/drivers/input/keyboard/spitzkbd.c
++++ b/drivers/input/keyboard/spitzkbd.c
+@@ -23,6 +23,7 @@
+ #include <asm/arch/spitz.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ 
+ #define KB_ROWS			7
+ #define KB_COLS			11
+@@ -494,3 +495,4 @@ module_exit(spitzkbd_exit);
+ MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
+ MODULE_DESCRIPTION("Spitz Keyboard Driver");
+ MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("platform:spitz-keyboard");
+diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c
+index 3884d1e..94e444b 100644
+--- a/drivers/input/keyboard/tosakbd.c
++++ b/drivers/input/keyboard/tosakbd.c
+@@ -52,7 +52,7 @@ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_
+ struct tosakbd {
+ 	unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)];
+ 	struct input_dev *input;
+-
++	int suspended;
+ 	spinlock_t lock; /* protect kbd scanning */
+ 	struct timer_list timer;
+ };
+@@ -133,6 +133,9 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
+ 
+ 	spin_lock_irqsave(&tosakbd->lock, flags);
+ 
++	if (tosakbd->suspended)
++		goto out;
++
+ 	for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) {
+ 		/*
+ 		 * Discharge the output driver capacitatance
+@@ -174,6 +177,7 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
+ 	if (num_pressed)
+ 		mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL);
+ 
++ out:
+ 	spin_unlock_irqrestore(&tosakbd->lock, flags);
+ }
+ 
+@@ -200,6 +204,7 @@ static irqreturn_t tosakbd_interrupt(int irq, void *__dev)
+ static void tosakbd_timer_callback(unsigned long __dev)
+ {
+ 	struct platform_device *dev = (struct platform_device *)__dev;
++
+ 	tosakbd_scankeyboard(dev);
+ }
+ 
+@@ -207,6 +212,13 @@ static void tosakbd_timer_callback(unsigned long __dev)
+ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ 	struct tosakbd *tosakbd = platform_get_drvdata(dev);
++	unsigned long flags;
++
++	spin_lock_irqsave(&tosakbd->lock, flags);
++	PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT);
++	PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT);
++	tosakbd->suspended = 1;
++	spin_unlock_irqrestore(&tosakbd->lock, flags);
+ 
+ 	del_timer_sync(&tosakbd->timer);
+ 
+@@ -215,6 +227,9 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
+ 
+ static int tosakbd_resume(struct platform_device *dev)
+ {
++	struct tosakbd *tosakbd = platform_get_drvdata(dev);
++
++	tosakbd->suspended = 0;
+ 	tosakbd_scankeyboard(dev);
+ 
+ 	return 0;
+@@ -365,8 +380,8 @@ fail:
+ 	return error;
+ }
+ 
+-static int __devexit tosakbd_remove(struct platform_device *dev) {
+-
++static int __devexit tosakbd_remove(struct platform_device *dev)
++{
+ 	int i;
+ 	struct tosakbd *tosakbd = platform_get_drvdata(dev);
+ 
+@@ -394,6 +409,7 @@ static struct platform_driver tosakbd_driver = {
+ 	.resume		= tosakbd_resume,
+ 	.driver		= {
+ 		.name	= "tosa-keyboard",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -413,3 +429,4 @@ module_exit(tosakbd_exit);
+ MODULE_AUTHOR("Dirk Opfer <Dirk at Opfer-Online.de>");
+ MODULE_DESCRIPTION("Tosa Keyboard Driver");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:tosa-keyboard");
+diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
+index c5263d6..92b6834 100644
+--- a/drivers/input/misc/Kconfig
++++ b/drivers/input/misc/Kconfig
+@@ -15,6 +15,7 @@ if INPUT_MISC
+ config INPUT_PCSPKR
+ 	tristate "PC Speaker support"
+ 	depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
++	depends on SND_PCSP=n
+ 	help
+ 	  Say Y here if you want the standard PC Speaker to be used for
+ 	  bells and whistles.
+diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
+index 5511ef0..6a1f48b 100644
+--- a/drivers/input/misc/cobalt_btns.c
++++ b/drivers/input/misc/cobalt_btns.c
+@@ -148,6 +148,9 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:Cobalt buttons");
++
+ static struct platform_driver cobalt_buttons_driver = {
+ 	.probe	= cobalt_buttons_probe,
+ 	.remove	= __devexit_p(cobalt_buttons_remove),
+diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
+index 0936d6b..3392901 100644
+--- a/drivers/input/mouse/gpio_mouse.c
++++ b/drivers/input/mouse/gpio_mouse.c
+@@ -171,10 +171,14 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:gpio_mouse");
++
+ struct platform_driver gpio_mouse_device_driver = {
+ 	.remove		= __devexit_p(gpio_mouse_remove),
+ 	.driver		= {
+ 		.name	= "gpio_mouse",
++		.owner	= THIS_MODULE,
+ 	}
+ };
+ 
+diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
+index b88569e..ec4b661 100644
+--- a/drivers/input/serio/Kconfig
++++ b/drivers/input/serio/Kconfig
+@@ -88,6 +88,16 @@ config SERIO_RPCKBD
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called rpckbd.
+ 
++config SERIO_AT32PSIF
++	tristate "AVR32 PSIF PS/2 keyboard and mouse controller"
++	depends on AVR32
++	help
++	  Say Y here if you want to use the PSIF peripheral on AVR32 devices
++	  and connect a PS/2 keyboard and/or mouse to it.
++
++	  To compile this driver as a module, choose M here: the module will
++	  be called at32psif.
++
+ config SERIO_AMBAKMI
+ 	tristate "AMBA KMI keyboard controller"
+ 	depends on ARM_AMBA
+diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
+index 4155197..38b8868 100644
+--- a/drivers/input/serio/Makefile
++++ b/drivers/input/serio/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_SERIO_CT82C710)	+= ct82c710.o
+ obj-$(CONFIG_SERIO_RPCKBD)	+= rpckbd.o
+ obj-$(CONFIG_SERIO_SA1111)	+= sa1111ps2.o
+ obj-$(CONFIG_SERIO_AMBAKMI)	+= ambakmi.o
++obj-$(CONFIG_SERIO_AT32PSIF)	+= at32psif.o
+ obj-$(CONFIG_SERIO_Q40KBD)	+= q40kbd.o
+ obj-$(CONFIG_SERIO_GSCPS2)	+= gscps2.o
+ obj-$(CONFIG_HP_SDC)		+= hp_sdc.o
+diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c
+new file mode 100644
+index 0000000..41fda8c
+--- /dev/null
++++ b/drivers/input/serio/at32psif.c
+@@ -0,0 +1,375 @@
++/*
++ * Copyright (C) 2007 Atmel Corporation
++ *
++ * Driver for the AT32AP700X PS/2 controller (PSIF).
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/serio.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++
++/* PSIF register offsets */
++#define PSIF_CR				0x00
++#define PSIF_RHR			0x04
++#define PSIF_THR			0x08
++#define PSIF_SR				0x10
++#define PSIF_IER			0x14
++#define PSIF_IDR			0x18
++#define PSIF_IMR			0x1c
++#define PSIF_PSR			0x24
++
++/* Bitfields in control register. */
++#define PSIF_CR_RXDIS_OFFSET		1
++#define PSIF_CR_RXDIS_SIZE		1
++#define PSIF_CR_RXEN_OFFSET		0
++#define PSIF_CR_RXEN_SIZE		1
++#define PSIF_CR_SWRST_OFFSET		15
++#define PSIF_CR_SWRST_SIZE		1
++#define PSIF_CR_TXDIS_OFFSET		9
++#define PSIF_CR_TXDIS_SIZE		1
++#define PSIF_CR_TXEN_OFFSET		8
++#define PSIF_CR_TXEN_SIZE		1
++
++/* Bitfields in interrupt disable, enable, mask and status register. */
++#define PSIF_NACK_OFFSET		8
++#define PSIF_NACK_SIZE			1
++#define PSIF_OVRUN_OFFSET		5
++#define PSIF_OVRUN_SIZE			1
++#define PSIF_PARITY_OFFSET		9
++#define PSIF_PARITY_SIZE		1
++#define PSIF_RXRDY_OFFSET		4
++#define PSIF_RXRDY_SIZE			1
++#define PSIF_TXEMPTY_OFFSET		1
++#define PSIF_TXEMPTY_SIZE		1
++#define PSIF_TXRDY_OFFSET		0
++#define PSIF_TXRDY_SIZE			1
++
++/* Bitfields in prescale register. */
++#define PSIF_PSR_PRSCV_OFFSET		0
++#define PSIF_PSR_PRSCV_SIZE		12
++
++/* Bitfields in receive hold register. */
++#define PSIF_RHR_RXDATA_OFFSET		0
++#define PSIF_RHR_RXDATA_SIZE		8
++
++/* Bitfields in transmit hold register. */
++#define PSIF_THR_TXDATA_OFFSET		0
++#define PSIF_THR_TXDATA_SIZE		8
++
++/* Bit manipulation macros */
++#define PSIF_BIT(name)					\
++	(1 << PSIF_##name##_OFFSET)
++
++#define PSIF_BF(name, value)				\
++	(((value) & ((1 << PSIF_##name##_SIZE) - 1))	\
++	 << PSIF_##name##_OFFSET)
++
++#define PSIF_BFEXT(name, value)				\
++	(((value) >> PSIF_##name##_OFFSET)		\
++	 & ((1 << PSIF_##name##_SIZE) - 1))
++
++#define PSIF_BFINS(name, value, old)			\
++	(((old) & ~(((1 << PSIF_##name##_SIZE) - 1)	\
++		    << PSIF_##name##_OFFSET))		\
++	 | PSIF_BF(name, value))
++
++/* Register access macros */
++#define psif_readl(port, reg)				\
++	__raw_readl((port)->regs + PSIF_##reg)
++
++#define psif_writel(port, reg, value)			\
++	__raw_writel((value), (port)->regs + PSIF_##reg)
++
++struct psif {
++	struct platform_device	*pdev;
++	struct clk		*pclk;
++	struct serio		*io;
++	void __iomem		*regs;
++	unsigned int		irq;
++	unsigned int		open;
++	/* Prevent concurrent writes to PSIF THR. */
++	spinlock_t		lock;
++};
++
++static irqreturn_t psif_interrupt(int irq, void *_ptr)
++{
++	struct psif *psif = _ptr;
++	int retval = IRQ_NONE;
++	unsigned int io_flags = 0;
++	unsigned long status;
++
++	status = psif_readl(psif, SR);
++
++	if (status & PSIF_BIT(RXRDY)) {
++		unsigned char val = (unsigned char) psif_readl(psif, RHR);
++
++		if (status & PSIF_BIT(PARITY))
++			io_flags |= SERIO_PARITY;
++		if (status & PSIF_BIT(OVRUN))
++			dev_err(&psif->pdev->dev, "overrun read error\n");
++
++		serio_interrupt(psif->io, val, io_flags);
++
++		retval = IRQ_HANDLED;
++	}
++
++	return retval;
++}
++
++static int psif_write(struct serio *io, unsigned char val)
++{
++	struct psif *psif = io->port_data;
++	unsigned long flags;
++	int timeout = 10;
++	int retval = 0;
++
++	spin_lock_irqsave(&psif->lock, flags);
++
++	while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--)
++		msleep(10);
++
++	if (timeout >= 0) {
++		psif_writel(psif, THR, val);
++	} else {
++		dev_dbg(&psif->pdev->dev, "timeout writing to THR\n");
++		retval = -EBUSY;
++	}
++
++	spin_unlock_irqrestore(&psif->lock, flags);
++
++	return retval;
++}
++
++static int psif_open(struct serio *io)
++{
++	struct psif *psif = io->port_data;
++	int retval;
++
++	retval = clk_enable(psif->pclk);
++	if (retval)
++		goto out;
++
++	psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN));
++	psif_writel(psif, IER, PSIF_BIT(RXRDY));
++
++	psif->open = 1;
++out:
++	return retval;
++}
++
++static void psif_close(struct serio *io)
++{
++	struct psif *psif = io->port_data;
++
++	psif->open = 0;
++
++	psif_writel(psif, IDR, ~0UL);
++	psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++
++	clk_disable(psif->pclk);
++}
++
++static void psif_set_prescaler(struct psif *psif)
++{
++	unsigned long prscv;
++	unsigned long rate = clk_get_rate(psif->pclk);
++
++	/* PRSCV = Pulse length (100 us) * PSIF module frequency. */
++	prscv = 100 * (rate / 1000000UL);
++
++	if (prscv > ((1<<PSIF_PSR_PRSCV_SIZE) - 1)) {
++		prscv = (1<<PSIF_PSR_PRSCV_SIZE) - 1;
++		dev_dbg(&psif->pdev->dev, "pclk too fast, "
++				"prescaler set to max\n");
++	}
++
++	clk_enable(psif->pclk);
++	psif_writel(psif, PSR, prscv);
++	clk_disable(psif->pclk);
++}
++
++static int __init psif_probe(struct platform_device *pdev)
++{
++	struct resource *regs;
++	struct psif *psif;
++	struct serio *io;
++	struct clk *pclk;
++	int irq;
++	int ret;
++
++	psif = kzalloc(sizeof(struct psif), GFP_KERNEL);
++	if (!psif) {
++		dev_dbg(&pdev->dev, "out of memory\n");
++		ret = -ENOMEM;
++		goto out;
++	}
++	psif->pdev = pdev;
++
++	io = kzalloc(sizeof(struct serio), GFP_KERNEL);
++	if (!io) {
++		dev_dbg(&pdev->dev, "out of memory\n");
++		ret = -ENOMEM;
++		goto out_free_psif;
++	}
++	psif->io = io;
++
++	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!regs) {
++		dev_dbg(&pdev->dev, "no mmio resources defined\n");
++		ret = -ENOMEM;
++		goto out_free_io;
++	}
++
++	psif->regs = ioremap(regs->start, regs->end - regs->start + 1);
++	if (!psif->regs) {
++		ret = -ENOMEM;
++		dev_dbg(&pdev->dev, "could not map I/O memory\n");
++		goto out_free_io;
++	}
++
++	pclk = clk_get(&pdev->dev, "pclk");
++	if (IS_ERR(pclk)) {
++		dev_dbg(&pdev->dev, "could not get peripheral clock\n");
++		ret = PTR_ERR(pclk);
++		goto out_iounmap;
++	}
++	psif->pclk = pclk;
++
++	/* Reset the PSIF to enter at a known state. */
++	ret = clk_enable(pclk);
++	if (ret) {
++		dev_dbg(&pdev->dev, "could not enable pclk\n");
++		goto out_put_clk;
++	}
++	psif_writel(psif, CR, PSIF_BIT(CR_SWRST));
++	clk_disable(pclk);
++
++	irq = platform_get_irq(pdev, 0);
++	if (irq < 0) {
++		dev_dbg(&pdev->dev, "could not get irq\n");
++		ret = -ENXIO;
++		goto out_put_clk;
++	}
++	ret = request_irq(irq, psif_interrupt, IRQF_SHARED, "at32psif", psif);
++	if (ret) {
++		dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
++		goto out_put_clk;
++	}
++	psif->irq = irq;
++
++	io->id.type	= SERIO_8042;
++	io->write	= psif_write;
++	io->open	= psif_open;
++	io->close	= psif_close;
++	snprintf(io->name, sizeof(io->name), "AVR32 PS/2 port%d", pdev->id);
++	snprintf(io->phys, sizeof(io->phys), "at32psif/serio%d", pdev->id);
++	io->port_data	= psif;
++	io->dev.parent	= &pdev->dev;
++
++	psif_set_prescaler(psif);
++
++	spin_lock_init(&psif->lock);
++	serio_register_port(psif->io);
++	platform_set_drvdata(pdev, psif);
++
++	dev_info(&pdev->dev, "Atmel AVR32 PSIF PS/2 driver on 0x%08x irq %d\n",
++			(int)psif->regs, psif->irq);
++
++	return 0;
++
++out_put_clk:
++	clk_put(psif->pclk);
++out_iounmap:
++	iounmap(psif->regs);
++out_free_io:
++	kfree(io);
++out_free_psif:
++	kfree(psif);
++out:
++	return ret;
++}
++
++static int __exit psif_remove(struct platform_device *pdev)
++{
++	struct psif *psif = platform_get_drvdata(pdev);
++
++	psif_writel(psif, IDR, ~0UL);
++	psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++
++	serio_unregister_port(psif->io);
++	iounmap(psif->regs);
++	free_irq(psif->irq, psif);
++	clk_put(psif->pclk);
++	kfree(psif);
++
++	platform_set_drvdata(pdev, NULL);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int psif_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	struct psif *psif = platform_get_drvdata(pdev);
++
++	if (psif->open) {
++		psif_writel(psif, CR, PSIF_BIT(CR_RXDIS) | PSIF_BIT(CR_TXDIS));
++		clk_disable(psif->pclk);
++	}
++
++	return 0;
++}
++
++static int psif_resume(struct platform_device *pdev)
++{
++	struct psif *psif = platform_get_drvdata(pdev);
++
++	if (psif->open) {
++		clk_enable(psif->pclk);
++		psif_set_prescaler(psif);
++		psif_writel(psif, CR, PSIF_BIT(CR_RXEN) | PSIF_BIT(CR_TXEN));
++	}
++
++	return 0;
++}
++#else
++#define psif_suspend	NULL
++#define psif_resume	NULL
++#endif
++
++static struct platform_driver psif_driver = {
++	.remove		= __exit_p(psif_remove),
++	.driver		= {
++		.name	= "atmel_psif",
++	},
++	.suspend	= psif_suspend,
++	.resume		= psif_resume,
++};
++
++static int __init psif_init(void)
++{
++	return platform_driver_probe(&psif_driver, psif_probe);
++}
++
++static void __exit psif_exit(void)
++{
++	platform_driver_unregister(&psif_driver);
++}
++
++module_init(psif_init);
++module_exit(psif_exit);
++
++MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>");
++MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
+index c45ea74..f1fd3b6 100644
+--- a/drivers/input/serio/hp_sdc_mlc.c
++++ b/drivers/input/serio/hp_sdc_mlc.c
+@@ -40,7 +40,7 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ 
+ #define PREFIX "HP SDC MLC: "
+ 
+diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
+index 60931ac..5ece9f5 100644
+--- a/drivers/input/serio/i8042-x86ia64io.h
++++ b/drivers/input/serio/i8042-x86ia64io.h
+@@ -370,10 +370,10 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
+ 	if (pnp_irq_valid(dev,0))
+ 		i8042_pnp_kbd_irq = pnp_irq(dev, 0);
+ 
+-	strncpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
++	strlcpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
+ 	if (strlen(pnp_dev_name(dev))) {
+-		strncat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
+-		strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
++		strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
++		strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
+ 	}
+ 
+ 	i8042_pnp_kbd_devices++;
+@@ -391,10 +391,10 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
+ 	if (pnp_irq_valid(dev, 0))
+ 		i8042_pnp_aux_irq = pnp_irq(dev, 0);
+ 
+-	strncpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
++	strlcpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
+ 	if (strlen(pnp_dev_name(dev))) {
+-		strncat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
+-		strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
++		strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
++		strlcat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
+ 	}
+ 
+ 	i8042_pnp_aux_devices++;
+diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
+index 49f8431..34c59d9 100644
+--- a/drivers/input/serio/rpckbd.c
++++ b/drivers/input/serio/rpckbd.c
+@@ -45,6 +45,7 @@
+ MODULE_AUTHOR("Vojtech Pavlik, Russell King");
+ MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:kart");
+ 
+ static int rpckbd_write(struct serio *port, unsigned char val)
+ {
+@@ -140,6 +141,7 @@ static struct platform_driver rpckbd_driver = {
+ 	.remove		= __devexit_p(rpckbd_remove),
+ 	.driver		= {
+ 		.name	= "kart",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig
+index d371c0b..effb49e 100644
+--- a/drivers/input/tablet/Kconfig
++++ b/drivers/input/tablet/Kconfig
+@@ -25,14 +25,14 @@ config TABLET_USB_ACECAD
+ 	  module will be called acecad.
+ 
+ config TABLET_USB_AIPTEK
+-	tristate "Aiptek 6000U/8000U tablet support (USB)"
++	tristate "Aiptek 6000U/8000U and Genius G_PEN tablet support (USB)"
+ 	depends on USB_ARCH_HAS_HCD
+ 	select USB
+ 	help
+-	  Say Y here if you want to use the USB version of the Aiptek 6000U
+-	  or Aiptek 8000U tablet.  Make sure to say Y to "Mouse support"
+-	  (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+-	  (CONFIG_INPUT_EVDEV) as well.
++	  Say Y here if you want to use the USB version of the Aiptek 6000U,
++	  Aiptek 8000U or Genius G-PEN 560 tablet.  Make sure to say Y to
++	  "Mouse support" (CONFIG_INPUT_MOUSEDEV) and/or "Event interface
++	  support" (CONFIG_INPUT_EVDEV) as well.
+ 
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called aiptek.
+diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
+index 94683f5..1d759f6 100644
+--- a/drivers/input/tablet/aiptek.c
++++ b/drivers/input/tablet/aiptek.c
+@@ -184,6 +184,7 @@
+  */
+ 
+ #define USB_VENDOR_ID_AIPTEK				0x08ca
++#define USB_VENDOR_ID_KYE				0x0458
+ #define USB_REQ_GET_REPORT				0x01
+ #define USB_REQ_SET_REPORT				0x09
+ 
+@@ -832,6 +833,7 @@ static const struct usb_device_id aiptek_ids[] = {
+ 	{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x22)},
+ 	{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x23)},
+ 	{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x24)},
++	{USB_DEVICE(USB_VENDOR_ID_KYE, 0x5003)},
+ 	{}
+ };
+ 
+diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
+index acf9830..706619d 100644
+--- a/drivers/input/tablet/wacom.h
++++ b/drivers/input/tablet/wacom.h
+@@ -101,8 +101,11 @@ struct wacom {
+ 	dma_addr_t data_dma;
+ 	struct input_dev *dev;
+ 	struct usb_device *usbdev;
++	struct usb_interface *intf;
+ 	struct urb *irq;
+ 	struct wacom_wac * wacom_wac;
++	struct mutex lock;
++	int open:1;
+ 	char phys[32];
+ };
+ 
+diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
+index 41caaef..71cc0c1 100644
+--- a/drivers/input/tablet/wacom_sys.c
++++ b/drivers/input/tablet/wacom_sys.c
+@@ -70,6 +70,7 @@ static void wacom_sys_irq(struct urb *urb)
+ 		input_sync(get_input_dev(&wcombo));
+ 
+  exit:
++	usb_mark_last_busy(wacom->usbdev);
+ 	retval = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (retval)
+ 		err ("%s - usb_submit_urb failed with result %d",
+@@ -124,10 +125,25 @@ static int wacom_open(struct input_dev *dev)
+ {
+ 	struct wacom *wacom = input_get_drvdata(dev);
+ 
++	mutex_lock(&wacom->lock);
++
+ 	wacom->irq->dev = wacom->usbdev;
+-	if (usb_submit_urb(wacom->irq, GFP_KERNEL))
++
++	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;
++	}
++
++	wacom->open = 1;
++	wacom->intf->needs_remote_wakeup = 1;
+ 
++	mutex_unlock(&wacom->lock);
+ 	return 0;
+ }
+ 
+@@ -135,7 +151,11 @@ static void wacom_close(struct input_dev *dev)
+ {
+ 	struct wacom *wacom = input_get_drvdata(dev);
+ 
++	mutex_lock(&wacom->lock);
+ 	usb_kill_urb(wacom->irq);
++	wacom->open = 0;
++	wacom->intf->needs_remote_wakeup = 0;
++	mutex_unlock(&wacom->lock);
+ }
+ 
+ void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+@@ -243,6 +263,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
+ 
+ 	wacom->usbdev = dev;
+ 	wacom->dev = input_dev;
++	wacom->intf = intf;
++	mutex_init(&wacom->lock);
+ 	usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
+ 	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
+ 
+@@ -304,23 +326,57 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
+ 
+ static void wacom_disconnect(struct usb_interface *intf)
+ {
+-	struct wacom *wacom = usb_get_intfdata (intf);
++	struct wacom *wacom = usb_get_intfdata(intf);
+ 
+ 	usb_set_intfdata(intf, NULL);
+-	if (wacom) {
+-		usb_kill_urb(wacom->irq);
+-		input_unregister_device(wacom->dev);
+-		usb_free_urb(wacom->irq);
+-		usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
+-		kfree(wacom->wacom_wac);
+-		kfree(wacom);
+-	}
++
++	usb_kill_urb(wacom->irq);
++	input_unregister_device(wacom->dev);
++	usb_free_urb(wacom->irq);
++	usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
++	kfree(wacom->wacom_wac);
++	kfree(wacom);
++}
++
++static int wacom_suspend(struct usb_interface *intf, pm_message_t message)
++{
++	struct wacom *wacom = usb_get_intfdata(intf);
++
++	mutex_lock(&wacom->lock);
++	usb_kill_urb(wacom->irq);
++	mutex_unlock(&wacom->lock);
++
++	return 0;
++}
++
++static int wacom_resume(struct usb_interface *intf)
++{
++	struct wacom *wacom = usb_get_intfdata(intf);
++	int rv;
++
++	mutex_lock(&wacom->lock);
++	if (wacom->open)
++		rv = usb_submit_urb(wacom->irq, GFP_NOIO);
++	else
++		rv = 0;
++	mutex_unlock(&wacom->lock);
++
++	return rv;
++}
++
++static int wacom_reset_resume(struct usb_interface *intf)
++{
++	return wacom_resume(intf);
+ }
+ 
+ static struct usb_driver wacom_driver = {
+ 	.name =		"wacom",
+ 	.probe =	wacom_probe,
+ 	.disconnect =	wacom_disconnect,
++	.suspend =	wacom_suspend,
++	.resume =	wacom_resume,
++	.reset_resume =	wacom_reset_resume,
++	.supports_autosuspend = 1,
+ };
+ 
+ static int __init wacom_init(void)
+diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
+index ffe3384..192513e 100644
+--- a/drivers/input/tablet/wacom_wac.c
++++ b/drivers/input/tablet/wacom_wac.c
+@@ -649,6 +649,7 @@ static struct wacom_features wacom_features[] = {
+ 	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
+ 	{ "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
+ 	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
++	{ "Wacom Cintiq 20WSX",  10, 86680, 54180, 1023, 63, WACOM_BEE },
+ 	{ "Wacom Cintiq 12WX",   10, 53020, 33440, 1023, 63, WACOM_BEE },
+ 	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
+ 	{ }
+@@ -702,6 +703,7 @@ static struct usb_device_id wacom_ids[] = {
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
++	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
+ 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
+ 	{ }
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index 90e8e92..565ec71 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -185,6 +185,59 @@ config TOUCHSCREEN_UCB1400
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called ucb1400_ts.
+ 
++config TOUCHSCREEN_WM97XX
++	tristate "Support for WM97xx AC97 touchscreen controllers"
++	depends on AC97_BUS
++	help
++	  Say Y here if you have a Wolfson Microelectronics WM97xx
++	  touchscreen connected to your system. Note that this option
++	  only enables core driver, you will also need to select
++	  support for appropriate chip below.
++
++	  If unsure, say N.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called wm97xx-ts.
++
++config TOUCHSCREEN_WM9705
++	bool "WM9705 Touchscreen interface support"
++	depends on TOUCHSCREEN_WM97XX
++	help
++	  Say Y here if you have a Wolfson Microelectronics WM9705
++	  touchscreen controller connected to your system.
++
++	  If unsure, say N.
++
++config TOUCHSCREEN_WM9712
++	bool "WM9712 Touchscreen interface support"
++	depends on TOUCHSCREEN_WM97XX
++	help
++	  Say Y here if you have a Wolfson Microelectronics WM9712
++	  touchscreen controller connected to your system.
++
++	  If unsure, say N.
++
++config TOUCHSCREEN_WM9713
++	bool "WM9713 Touchscreen interface support"
++	depends on TOUCHSCREEN_WM97XX
++	help
++	  Say Y here if you have a Wolfson Microelectronics WM9713 touchscreen
++	  controller connected to your system.
++
++	  If unsure, say N.
++
++config TOUCHSCREEN_WM97XX_MAINSTONE
++	tristate "WM97xx Mainstone accelerated touch"
++	depends on TOUCHSCREEN_WM97XX && ARCH_PXA
++	help
++	  Say Y here for support for streaming mode with WM97xx touchscreens
++	  on Mainstone systems.
++
++	  If unsure, say N.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called mainstone-wm97xx.
++
+ config TOUCHSCREEN_USB_COMPOSITE
+ 	tristate "USB Touchscreen Driver"
+ 	depends on USB_ARCH_HAS_HCD
+diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
+index 35d4097..3c096d7 100644
+--- a/drivers/input/touchscreen/Makefile
++++ b/drivers/input/touchscreen/Makefile
+@@ -4,6 +4,8 @@
+ 
+ # Each configuration option enables a list of files.
+ 
++wm97xx-ts-y := wm97xx-core.o
++
+ obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
+ obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
+ obj-$(CONFIG_TOUCHSCREEN_CORGI)		+= corgi_ts.o
+@@ -19,3 +21,8 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
+ obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
++obj-$(CONFIG_TOUCHSCREEN_WM97XX)	+= wm97xx-ts.o
++wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)	+= wm9705.o
++wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)	+= wm9712.o
++wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713)	+= wm9713.o
++obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)	+= mainstone-wm97xx.o
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 57a1c28..907a45f 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -28,13 +28,6 @@
+ #include <linux/spi/ads7846.h>
+ #include <asm/irq.h>
+ 
+-#ifdef	CONFIG_ARM
+-#include <asm/mach-types.h>
+-#ifdef	CONFIG_ARCH_OMAP
+-#include <asm/arch/gpio.h>
+-#endif
+-#endif
+-
+ 
+ /*
+  * This code has been heavily tested on a Nokia 770, and lightly
+@@ -87,6 +80,7 @@ struct ads7846 {
+ #endif
+ 
+ 	u16			model;
++	u16			vref_mv;
+ 	u16			vref_delay_usecs;
+ 	u16			x_plate_ohms;
+ 	u16			pressure_max;
+@@ -184,9 +178,6 @@ struct ads7846 {
+  * The range is GND..vREF. The ads7843 and ads7835 must use external vREF;
+  * ads7846 lets that pin be unconnected, to use internal vREF.
+  */
+-static unsigned vREF_mV;
+-module_param(vREF_mV, uint, 0);
+-MODULE_PARM_DESC(vREF_mV, "external vREF voltage, in milliVolts");
+ 
+ struct ser_req {
+ 	u8			ref_on;
+@@ -213,7 +204,6 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
+ 	struct ads7846		*ts = dev_get_drvdata(dev);
+ 	struct ser_req		*req = kzalloc(sizeof *req, GFP_KERNEL);
+ 	int			status;
+-	int			uninitialized_var(sample);
+ 	int			use_internal;
+ 
+ 	if (!req)
+@@ -270,13 +260,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
+ 
+ 	if (status == 0) {
+ 		/* on-wire is a must-ignore bit, a BE12 value, then padding */
+-		sample = be16_to_cpu(req->sample);
+-		sample = sample >> 3;
+-		sample &= 0x0fff;
++		status = be16_to_cpu(req->sample);
++		status = status >> 3;
++		status &= 0x0fff;
+ 	}
+ 
+ 	kfree(req);
+-	return status ? status : sample;
++	return status;
+ }
+ 
+ #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE)
+@@ -317,7 +307,7 @@ static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v)
+ 	unsigned retval = v;
+ 
+ 	/* external resistors may scale vAUX into 0..vREF */
+-	retval *= vREF_mV;
++	retval *= ts->vref_mv;
+ 	retval = retval >> 12;
+ 	return retval;
+ }
+@@ -375,14 +365,14 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
+ 	/* hwmon sensors need a reference voltage */
+ 	switch (ts->model) {
+ 	case 7846:
+-		if (!vREF_mV) {
++		if (!ts->vref_mv) {
+ 			dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n");
+-			vREF_mV = 2500;
++			ts->vref_mv = 2500;
+ 		}
+ 		break;
+ 	case 7845:
+ 	case 7843:
+-		if (!vREF_mV) {
++		if (!ts->vref_mv) {
+ 			dev_warn(&spi->dev,
+ 				"external vREF for ADS%d not specified\n",
+ 				ts->model);
+@@ -875,6 +865,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
+ 
+ 	ts->spi = spi;
+ 	ts->input = input_dev;
++	ts->vref_mv = pdata->vref_mv;
+ 
+ 	hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ 	ts->timer.function = ads7846_timer;
+@@ -1174,31 +1165,6 @@ static struct spi_driver ads7846_driver = {
+ 
+ static int __init ads7846_init(void)
+ {
+-	/* grr, board-specific init should stay out of drivers!! */
+-
+-#ifdef	CONFIG_ARCH_OMAP
+-	if (machine_is_omap_osk()) {
+-		/* GPIO4 = PENIRQ; GPIO6 = BUSY */
+-		omap_request_gpio(4);
+-		omap_set_gpio_direction(4, 1);
+-		omap_request_gpio(6);
+-		omap_set_gpio_direction(6, 1);
+-	}
+-	// also TI 1510 Innovator, bitbanging through FPGA
+-	// also Nokia 770
+-	// also Palm Tungsten T2
+-#endif
+-
+-	// PXA:
+-	// also Dell Axim X50
+-	// also HP iPaq H191x/H192x/H415x/H435x
+-	// also Intel Lubbock (additional to UCB1400; as temperature sensor)
+-	// also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)
+-
+-	// Atmel at91sam9261-EK uses ads7843
+-
+-	// also various AMD Au1x00 devel boards
+-
+ 	return spi_register_driver(&ads7846_driver);
+ }
+ module_init(ads7846_init);
+@@ -1206,14 +1172,6 @@ module_init(ads7846_init);
+ static void __exit ads7846_exit(void)
+ {
+ 	spi_unregister_driver(&ads7846_driver);
+-
+-#ifdef	CONFIG_ARCH_OMAP
+-	if (machine_is_omap_osk()) {
+-		omap_free_gpio(4);
+-		omap_free_gpio(6);
+-	}
+-#endif
+-
+ }
+ module_exit(ads7846_exit);
+ 
+diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
+index 99d92f5..4e9d8ee 100644
+--- a/drivers/input/touchscreen/corgi_ts.c
++++ b/drivers/input/touchscreen/corgi_ts.c
+@@ -22,6 +22,7 @@
+ #include <asm/arch/sharpsl.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ 
+ 
+ #define PWR_MODE_ACTIVE		0
+@@ -361,6 +362,7 @@ static struct platform_driver corgits_driver = {
+ 	.resume		= corgits_resume,
+ 	.driver		= {
+ 		.name	= "corgi-ts",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -380,3 +382,4 @@ module_exit(corgits_exit);
+ MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
+ MODULE_DESCRIPTION("Corgi TouchScreen Driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:corgi-ts");
+diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
+index 42a1c9a..7422421 100644
+--- a/drivers/input/touchscreen/jornada720_ts.c
++++ b/drivers/input/touchscreen/jornada720_ts.c
+@@ -160,11 +160,15 @@ static int __devexit jornada720_ts_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:jornada_ts");
++
+ static struct platform_driver jornada720_ts_driver = {
+ 	.probe		= jornada720_ts_probe,
+ 	.remove		= __devexit_p(jornada720_ts_remove),
+ 	.driver		= {
+ 		.name	= "jornada_ts",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
+new file mode 100644
+index 0000000..a79f029
+--- /dev/null
++++ b/drivers/input/touchscreen/mainstone-wm97xx.c
+@@ -0,0 +1,302 @@
++/*
++ * mainstone-wm97xx.c  --  Mainstone Continuous Touch screen driver for
++ *                         Wolfson WM97xx AC97 Codecs.
++ *
++ * Copyright 2004, 2007 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ *                   Andrew Zabolotny <zap at homelink.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.
++ *
++ * Notes:
++ *     This is a wm97xx extended touch driver to capture touch
++ *     data in a continuous manner on the Intel XScale archictecture
++ *
++ *  Features:
++ *       - codecs supported:- WM9705, WM9712, WM9713
++ *       - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/wm97xx.h>
++#include <linux/io.h>
++#include <asm/arch/pxa-regs.h>
++
++#define VERSION		"0.13"
++
++struct continuous {
++	u16 id;    /* codec id */
++	u8 code;   /* continuous code */
++	u8 reads;  /* number of coord reads per read cycle */
++	u32 speed; /* number of coords per second */
++};
++
++#define WM_READS(sp) ((sp / HZ) + 1)
++
++static const struct continuous cinfo[] = {
++	{WM9705_ID2, 0, WM_READS(94), 94},
++	{WM9705_ID2, 1, WM_READS(188), 188},
++	{WM9705_ID2, 2, WM_READS(375), 375},
++	{WM9705_ID2, 3, WM_READS(750), 750},
++	{WM9712_ID2, 0, WM_READS(94), 94},
++	{WM9712_ID2, 1, WM_READS(188), 188},
++	{WM9712_ID2, 2, WM_READS(375), 375},
++	{WM9712_ID2, 3, WM_READS(750), 750},
++	{WM9713_ID2, 0, WM_READS(94), 94},
++	{WM9713_ID2, 1, WM_READS(120), 120},
++	{WM9713_ID2, 2, WM_READS(154), 154},
++	{WM9713_ID2, 3, WM_READS(188), 188},
++};
++
++/* continuous speed index */
++static int sp_idx;
++static u16 last, tries;
++
++/*
++ * Pen sampling frequency (Hz) in continuous mode.
++ */
++static int cont_rate = 200;
++module_param(cont_rate, int, 0);
++MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
++
++/*
++ * Pen down detection.
++ *
++ * This driver can either poll or use an interrupt to indicate a pen down
++ * event. If the irq request fails then it will fall back to polling mode.
++ */
++static int pen_int;
++module_param(pen_int, int, 0);
++MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
++
++/*
++ * Pressure readback.
++ *
++ * Set to 1 to read back pen down pressure
++ */
++static int pressure;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
++
++/*
++ * AC97 touch data slot.
++ *
++ * Touch screen readback data ac97 slot
++ */
++static int ac97_touch_slot = 5;
++module_param(ac97_touch_slot, int, 0);
++MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
++
++
++/* flush AC97 slot 5 FIFO on pxa machines */
++#ifdef CONFIG_PXA27x
++static void wm97xx_acc_pen_up(struct wm97xx *wm)
++{
++	schedule_timeout_uninterruptible(1);
++
++	while (MISR & (1 << 2))
++		MODR;
++}
++#else
++static void wm97xx_acc_pen_up(struct wm97xx *wm)
++{
++	int count = 16;
++	schedule_timeout_uninterruptible(1);
++
++	while (count < 16) {
++		MODR;
++		count--;
++	}
++}
++#endif
++
++static int wm97xx_acc_pen_down(struct wm97xx *wm)
++{
++	u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
++	int reads = 0;
++
++	/* When the AC97 queue has been drained we need to allow time
++	 * to buffer up samples otherwise we end up spinning polling
++	 * for samples.  The controller can't have a suitably low
++	 * threashold set to use the notifications it gives.
++	 */
++	schedule_timeout_uninterruptible(1);
++
++	if (tries > 5) {
++		tries = 0;
++		return RC_PENUP;
++	}
++
++	x = MODR;
++	if (x == last) {
++		tries++;
++		return RC_AGAIN;
++	}
++	last = x;
++	do {
++		if (reads)
++			x = MODR;
++		y = MODR;
++		if (pressure)
++			p = MODR;
++
++		/* are samples valid */
++		if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
++		    (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
++		    (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
++			goto up;
++
++		/* coordinate is good */
++		tries = 0;
++		input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
++		input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
++		input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
++		input_sync(wm->input_dev);
++		reads++;
++	} while (reads < cinfo[sp_idx].reads);
++up:
++	return RC_PENDOWN | RC_AGAIN;
++}
++
++static int wm97xx_acc_startup(struct wm97xx *wm)
++{
++	int idx = 0;
++
++	/* check we have a codec */
++	if (wm->ac97 == NULL)
++		return -ENODEV;
++
++	/* Go you big red fire engine */
++	for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
++		if (wm->id != cinfo[idx].id)
++			continue;
++		sp_idx = idx;
++		if (cont_rate <= cinfo[idx].speed)
++			break;
++	}
++	wm->acc_rate = cinfo[sp_idx].code;
++	wm->acc_slot = ac97_touch_slot;
++	dev_info(wm->dev,
++		 "mainstone accelerated touchscreen driver, %d samples/sec\n",
++		 cinfo[sp_idx].speed);
++
++	/* codec specific irq config */
++	if (pen_int) {
++		switch (wm->id) {
++		case WM9705_ID2:
++			wm->pen_irq = IRQ_GPIO(4);
++			set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE);
++			break;
++		case WM9712_ID2:
++		case WM9713_ID2:
++			/* enable pen down interrupt */
++			/* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
++			wm->pen_irq = MAINSTONE_AC97_IRQ;
++			wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
++					   WM97XX_GPIO_POL_HIGH,
++					   WM97XX_GPIO_STICKY,
++					   WM97XX_GPIO_WAKE);
++			wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
++					   WM97XX_GPIO_POL_HIGH,
++					   WM97XX_GPIO_NOTSTICKY,
++					   WM97XX_GPIO_NOWAKE);
++			break;
++		default:
++			dev_err(wm->dev,
++				"pen down irq not supported on this device\n");
++			pen_int = 0;
++			break;
++		}
++	}
++
++	return 0;
++}
++
++static void wm97xx_acc_shutdown(struct wm97xx *wm)
++{
++	/* codec specific deconfig */
++	if (pen_int) {
++		switch (wm->id & 0xffff) {
++		case WM9705_ID2:
++			wm->pen_irq = 0;
++			break;
++		case WM9712_ID2:
++		case WM9713_ID2:
++			/* disable interrupt */
++			wm->pen_irq = 0;
++			break;
++		}
++	}
++}
++
++static void wm97xx_irq_enable(struct wm97xx *wm, int enable)
++{
++	if (enable)
++		enable_irq(wm->pen_irq);
++	else
++		disable_irq(wm->pen_irq);
++}
++
++static struct wm97xx_mach_ops mainstone_mach_ops = {
++	.acc_enabled = 1,
++	.acc_pen_up = wm97xx_acc_pen_up,
++	.acc_pen_down = wm97xx_acc_pen_down,
++	.acc_startup = wm97xx_acc_startup,
++	.acc_shutdown = wm97xx_acc_shutdown,
++	.irq_enable = wm97xx_irq_enable,
++	.irq_gpio = WM97XX_GPIO_2,
++};
++
++static int mainstone_wm97xx_probe(struct platform_device *pdev)
++{
++	struct wm97xx *wm = platform_get_drvdata(pdev);
++
++	return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
++}
++
++static int mainstone_wm97xx_remove(struct platform_device *pdev)
++{
++	struct wm97xx *wm = platform_get_drvdata(pdev);
++
++	wm97xx_unregister_mach_ops(wm);
++	return 0;
++}
++
++static struct platform_driver mainstone_wm97xx_driver = {
++	.probe = mainstone_wm97xx_probe,
++	.remove = mainstone_wm97xx_remove,
++	.driver = {
++		.name = "wm97xx-touch",
++	},
++};
++
++static int __init mainstone_wm97xx_init(void)
++{
++	return platform_driver_register(&mainstone_wm97xx_driver);
++}
++
++static void __exit mainstone_wm97xx_exit(void)
++{
++	platform_driver_unregister(&mainstone_wm97xx_driver);
++}
++
++module_init(mainstone_wm97xx_init);
++module_exit(mainstone_wm97xx_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
+index 607f993..bce018e 100644
+--- a/drivers/input/touchscreen/ucb1400_ts.c
++++ b/drivers/input/touchscreen/ucb1400_ts.c
+@@ -427,10 +427,6 @@ static int ucb1400_detect_irq(struct ucb1400 *ucb)
+ 	unsigned long mask, timeout;
+ 
+ 	mask = probe_irq_on();
+-	if (!mask) {
+-		probe_irq_off(mask);
+-		return -EBUSY;
+-	}
+ 
+ 	/* Enable the ADC interrupt. */
+ 	ucb1400_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
+diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
+index 63f9664..3a0a8ca 100644
+--- a/drivers/input/touchscreen/usbtouchscreen.c
++++ b/drivers/input/touchscreen/usbtouchscreen.c
+@@ -396,9 +396,12 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+ {
+ 	struct usb_device *dev = usbtouch->udev;
+-	int ret;
+-	unsigned char buf[2];
++	int ret = -ENOMEM;
++	unsigned char *buf;
+ 
++	buf = kmalloc(2, GFP_KERNEL);
++	if (!buf)
++		goto err_nobuf;
+ 	/* reset */
+ 	buf[0] = buf[1] = 0xFF;
+ 	ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+@@ -406,9 +409,11 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+ 	                      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 	                      0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ 	if (ret < 0)
+-		return ret;
+-	if (buf[0] != 0x06 || buf[1] != 0x00)
+-		return -ENODEV;
++		goto err_out;
++	if (buf[0] != 0x06 || buf[1] != 0x00) {
++		ret = -ENODEV;
++		goto err_out;
++	}
+ 
+ 	/* set coordinate output rate */
+ 	buf[0] = buf[1] = 0xFF;
+@@ -417,20 +422,22 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+ 	                      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 	                      TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ 	if (ret < 0)
+-		return ret;
++		goto err_out;
+ 	if ((buf[0] != 0x06 || buf[1] != 0x00) &&
+-	    (buf[0] != 0x15 || buf[1] != 0x01))
+-		return -ENODEV;
++	    (buf[0] != 0x15 || buf[1] != 0x01)) {
++		ret = -ENODEV;
++		goto err_out;
++	}
+ 
+ 	/* start sending data */
+ 	ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ 	                      TSC10_CMD_DATA1,
+ 	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 	                      0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+-	if (ret < 0)
+-		return ret;
+-
+-	return 0;
++err_out:
++	kfree(buf);
++err_nobuf:
++	return ret;
+ }
+ 
+ 
+diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
+new file mode 100644
+index 0000000..978e1a1
+--- /dev/null
++++ b/drivers/input/touchscreen/wm9705.c
+@@ -0,0 +1,353 @@
++/*
++ * wm9705.c  --  Codec driver for Wolfson WM9705 AC97 Codec.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ *                   Andrew Zabolotny <zap at homelink.ru>
++ *                   Russell King <rmk at arm.linux.org.uk>
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME			"wm97xx"
++#define WM9705_VERSION		"1.00"
++#define DEFAULT_PRESSURE	0xb0c0
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ *     pil = 1 to use 200uA and
++ *     pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 4;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Pen detect comparator threshold.
++ *
++ * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
++ * i.e. 1 =  Vmid/15 threshold
++ *      15 =  Vmid/1 threshold
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down events.
++ */
++static int pdd = 8;
++module_param(pdd, int, 0);
++MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++	21,    /* 1 AC97 Link frames */
++	42,    /* 2                  */
++	84,    /* 4                  */
++	167,   /* 8                  */
++	333,   /* 16                 */
++	667,   /* 32                 */
++	1000,  /* 48                 */
++	1333,  /* 64                 */
++	2000,  /* 96                 */
++	2667,  /* 128                */
++	3333,  /* 160                */
++	4000,  /* 192                */
++	4667,  /* 224                */
++	5333,  /* 256                */
++	6000,  /* 288                */
++	0      /* No delay, switch matrix always on */
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++	udelay(3 * AC97_LINK_FRAME + delay_table[d]);
++}
++
++/*
++ * set up the physical settings of the WM9705
++ */
++static void wm9705_phy_init(struct wm97xx *wm)
++{
++	u16 dig1 = 0, dig2 = WM97XX_RPR;
++
++	/*
++	* mute VIDEO and AUX as they share X and Y touchscreen
++	* inputs on the WM9705
++	*/
++	wm97xx_reg_write(wm, AC97_AUX, 0x8000);
++	wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
++
++	/* touchpanel pressure current*/
++	if (pil == 2) {
++		dig2 |= WM9705_PIL;
++		dev_dbg(wm->dev,
++			"setting pressure measurement current to 400uA.");
++	} else if (pil)
++		dev_dbg(wm->dev,
++			"setting pressure measurement current to 200uA.");
++	if (!pil)
++		pressure = 0;
++
++	/* polling mode sample settling delay */
++	if (delay != 4) {
++		if (delay < 0 || delay > 15) {
++			dev_dbg(wm->dev, "supplied delay out of range.");
++			delay = 4;
++		}
++	}
++	dig1 &= 0xff0f;
++	dig1 |= WM97XX_DELAY(delay);
++	dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
++		delay_table[delay]);
++
++	/* WM9705 pdd */
++	dig2 |= (pdd & 0x000f);
++	dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
++
++	/* mask */
++	dig2 |= ((mask & 0x3) << 4);
++
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++}
++
++static void wm9705_dig_enable(struct wm97xx *wm, int enable)
++{
++	if (enable) {
++		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
++				 wm->dig[2] | WM97XX_PRP_DET_DIG);
++		wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++	} else
++		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
++				 wm->dig[2] & ~WM97XX_PRP_DET_DIG);
++}
++
++static void wm9705_aux_prepare(struct wm97xx *wm)
++{
++	memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
++}
++
++static void wm9705_dig_restore(struct wm97xx *wm)
++{
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
++}
++
++static inline int is_pden(struct wm97xx *wm)
++{
++	return wm->dig[2] & WM9705_PDEN;
++}
++
++/*
++ * Read a sample from the WM9705 adc in polling mode.
++ */
++static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
++{
++	int timeout = 5 * delay;
++
++	if (!wm->pen_probably_down) {
++		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++		if (!(data & WM97XX_PEN_DOWN))
++			return RC_PENUP;
++		wm->pen_probably_down = 1;
++	}
++
++	/* set up digitiser */
++	if (adcsel & 0x8000)
++		adcsel = ((adcsel & 0x7fff) + 3) << 12;
++
++	if (wm->mach_ops && wm->mach_ops->pre_sample)
++		wm->mach_ops->pre_sample(adcsel);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
++			 adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
++
++	/* wait 3 AC97 time slots + delay for conversion */
++	poll_delay(delay);
++
++	/* wait for POLL to go low */
++	while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
++	       && timeout) {
++		udelay(AC97_LINK_FRAME);
++		timeout--;
++	}
++
++	if (timeout == 0) {
++		/* If PDEN is set, we can get a timeout when pen goes up */
++		if (is_pden(wm))
++			wm->pen_probably_down = 0;
++		else
++			dev_dbg(wm->dev, "adc sample timeout");
++		return RC_PENUP;
++	}
++
++	*sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++	if (wm->mach_ops && wm->mach_ops->post_sample)
++		wm->mach_ops->post_sample(adcsel);
++
++	/* check we have correct sample */
++	if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
++		dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
++		*sample & WM97XX_ADCSEL_MASK);
++		return RC_PENUP;
++	}
++
++	if (!(*sample & WM97XX_PEN_DOWN)) {
++		wm->pen_probably_down = 0;
++		return RC_PENUP;
++	}
++
++	return RC_VALID;
++}
++
++/*
++ * Sample the WM9705 touchscreen in polling mode
++ */
++static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
++{
++	int rc;
++
++	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
++	if (rc != RC_VALID)
++		return rc;
++	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
++	if (rc != RC_VALID)
++		return rc;
++	if (pil) {
++		rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p);
++		if (rc != RC_VALID)
++			return rc;
++	} else
++		data->p = DEFAULT_PRESSURE;
++
++	return RC_VALID;
++}
++
++/*
++ * Enable WM9705 continuous mode, i.e. touch data is streamed across
++ * an AC97 slot
++ */
++static int wm9705_acc_enable(struct wm97xx *wm, int enable)
++{
++	u16 dig1, dig2;
++	int ret = 0;
++
++	dig1 = wm->dig[1];
++	dig2 = wm->dig[2];
++
++	if (enable) {
++		/* continous mode */
++		if (wm->mach_ops->acc_startup &&
++		    (ret = wm->mach_ops->acc_startup(wm)) < 0)
++			return ret;
++		dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
++			  WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
++		dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
++			WM97XX_DELAY(delay) |
++			WM97XX_SLT(wm->acc_slot) |
++			WM97XX_RATE(wm->acc_rate);
++		if (pil)
++			dig1 |= WM97XX_ADCSEL_PRES;
++		dig2 |= WM9705_PDEN;
++	} else {
++		dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
++		dig2 &= ~WM9705_PDEN;
++		if (wm->mach_ops->acc_shutdown)
++			wm->mach_ops->acc_shutdown(wm);
++	}
++
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++
++	return ret;
++}
++
++struct wm97xx_codec_drv wm9705_codec = {
++	.id = WM9705_ID2,
++	.name = "wm9705",
++	.poll_sample = wm9705_poll_sample,
++	.poll_touch = wm9705_poll_touch,
++	.acc_enable = wm9705_acc_enable,
++	.phy_init = wm9705_phy_init,
++	.dig_enable = wm9705_dig_enable,
++	.dig_restore = wm9705_dig_restore,
++	.aux_prepare = wm9705_aux_prepare,
++};
++EXPORT_SYMBOL_GPL(wm9705_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
+new file mode 100644
+index 0000000..0b6e4cf
+--- /dev/null
++++ b/drivers/input/touchscreen/wm9712.c
+@@ -0,0 +1,462 @@
++/*
++ * wm9712.c  --  Codec driver for Wolfson WM9712 AC97 Codecs.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ *                   Andrew Zabolotny <zap at homelink.ru>
++ *                   Russell King <rmk at arm.linux.org.uk>
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME			"wm97xx"
++#define WM9712_VERSION		"1.00"
++#define DEFAULT_PRESSURE	0xb0c0
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set internal pull up for pen detect.
++ *
++ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
++ * i.e. pull up resistance = 64k Ohms / rpu.
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down event.
++ */
++static int rpu = 8;
++module_param(rpu, int, 0);
++MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ *     pil = 1 to use 200uA and
++ *     pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 3;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Set five_wire = 1 to use a 5 wire touchscreen.
++ *
++ * NOTE: Five wire mode does not allow for readback of pressure.
++ */
++static int five_wire;
++module_param(five_wire, int, 0);
++MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * Coordinate Polling Enable.
++ *
++ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
++ * for every poll.
++ */
++static int coord;
++module_param(coord, int, 0);
++MODULE_PARM_DESC(coord, "Polling coordinate mode");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++	21,    /* 1 AC97 Link frames */
++	42,    /* 2 */
++	84,    /* 4 */
++	167,   /* 8 */
++	333,   /* 16 */
++	667,   /* 32 */
++	1000,  /* 48 */
++	1333,  /* 64 */
++	2000,  /* 96 */
++	2667,  /* 128 */
++	3333,  /* 160 */
++	4000,  /* 192 */
++	4667,  /* 224 */
++	5333,  /* 256 */
++	6000,  /* 288 */
++	0      /* No delay, switch matrix always on */
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++	udelay(3 * AC97_LINK_FRAME + delay_table[d]);
++}
++
++/*
++ * set up the physical settings of the WM9712
++ */
++static void wm9712_phy_init(struct wm97xx *wm)
++{
++	u16 dig1 = 0;
++	u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
++
++	/* WM9712 rpu */
++	if (rpu) {
++		dig2 &= 0xffc0;
++		dig2 |= WM9712_RPU(rpu);
++		dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms",
++			64000 / rpu);
++	}
++
++	/* touchpanel pressure current*/
++	if (pil == 2) {
++		dig2 |= WM9712_PIL;
++		dev_dbg(wm->dev,
++			"setting pressure measurement current to 400uA.");
++	} else if (pil)
++		dev_dbg(wm->dev,
++			"setting pressure measurement current to 200uA.");
++	if (!pil)
++		pressure = 0;
++
++	/* WM9712 five wire */
++	if (five_wire) {
++		dig2 |= WM9712_45W;
++		dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
++	}
++
++	/* polling mode sample settling delay */
++	if (delay < 0 || delay > 15) {
++		dev_dbg(wm->dev, "supplied delay out of range.");
++		delay = 4;
++	}
++	dig1 &= 0xff0f;
++	dig1 |= WM97XX_DELAY(delay);
++	dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
++		delay_table[delay]);
++
++	/* mask */
++	dig2 |= ((mask & 0x3) << 6);
++	if (mask) {
++		u16 reg;
++		/* Set GPIO4 as Mask Pin*/
++		reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
++		wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
++		reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++		wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
++	}
++
++	/* wait - coord mode */
++	if (coord)
++		dig2 |= WM9712_WAIT;
++
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++}
++
++static void wm9712_dig_enable(struct wm97xx *wm, int enable)
++{
++	u16 dig2 = wm->dig[2];
++
++	if (enable) {
++		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
++				 dig2 | WM97XX_PRP_DET_DIG);
++		wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++	} else
++		wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
++				 dig2 & ~WM97XX_PRP_DET_DIG);
++}
++
++static void wm9712_aux_prepare(struct wm97xx *wm)
++{
++	memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
++}
++
++static void wm9712_dig_restore(struct wm97xx *wm)
++{
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
++}
++
++static inline int is_pden(struct wm97xx *wm)
++{
++	return wm->dig[2] & WM9712_PDEN;
++}
++
++/*
++ * Read a sample from the WM9712 adc in polling mode.
++ */
++static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
++{
++	int timeout = 5 * delay;
++
++	if (!wm->pen_probably_down) {
++		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++		if (!(data & WM97XX_PEN_DOWN))
++			return RC_PENUP;
++		wm->pen_probably_down = 1;
++	}
++
++	/* set up digitiser */
++	if (adcsel & 0x8000)
++		adcsel = ((adcsel & 0x7fff) + 3) << 12;
++
++	if (wm->mach_ops && wm->mach_ops->pre_sample)
++		wm->mach_ops->pre_sample(adcsel);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
++			 adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
++
++	/* wait 3 AC97 time slots + delay for conversion */
++	poll_delay(delay);
++
++	/* wait for POLL to go low */
++	while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
++	       && timeout) {
++		udelay(AC97_LINK_FRAME);
++		timeout--;
++	}
++
++	if (timeout <= 0) {
++		/* If PDEN is set, we can get a timeout when pen goes up */
++		if (is_pden(wm))
++			wm->pen_probably_down = 0;
++		else
++			dev_dbg(wm->dev, "adc sample timeout");
++		return RC_PENUP;
++	}
++
++	*sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++	if (wm->mach_ops && wm->mach_ops->post_sample)
++		wm->mach_ops->post_sample(adcsel);
++
++	/* check we have correct sample */
++	if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
++		dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
++		*sample & WM97XX_ADCSEL_MASK);
++		return RC_PENUP;
++	}
++
++	if (!(*sample & WM97XX_PEN_DOWN)) {
++		wm->pen_probably_down = 0;
++		return RC_PENUP;
++	}
++
++	return RC_VALID;
++}
++
++/*
++ * Read a coord from the WM9712 adc in polling mode.
++ */
++static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
++{
++	int timeout = 5 * delay;
++
++	if (!wm->pen_probably_down) {
++		u16 data_rd = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++		if (!(data_rd & WM97XX_PEN_DOWN))
++			return RC_PENUP;
++		wm->pen_probably_down = 1;
++	}
++
++	/* set up digitiser */
++	if (wm->mach_ops && wm->mach_ops->pre_sample)
++		wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
++		WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
++
++	/* wait 3 AC97 time slots + delay for conversion and read x */
++	poll_delay(delay);
++	data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++	/* wait for POLL to go low */
++	while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
++	       && timeout) {
++		udelay(AC97_LINK_FRAME);
++		timeout--;
++	}
++
++	if (timeout <= 0) {
++		/* If PDEN is set, we can get a timeout when pen goes up */
++		if (is_pden(wm))
++			wm->pen_probably_down = 0;
++		else
++			dev_dbg(wm->dev, "adc sample timeout");
++		return RC_PENUP;
++	}
++
++	/* read back y data */
++	data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++	if (pil)
++		data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++	else
++		data->p = DEFAULT_PRESSURE;
++
++	if (wm->mach_ops && wm->mach_ops->post_sample)
++		wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++
++	/* check we have correct sample */
++	if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
++		goto err;
++	if (pil && !(data->p & WM97XX_ADCSEL_PRES))
++		goto err;
++
++	if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
++		wm->pen_probably_down = 0;
++		return RC_PENUP;
++	}
++	return RC_VALID;
++err:
++	return 0;
++}
++
++/*
++ * Sample the WM9712 touchscreen in polling mode
++ */
++static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
++{
++	int rc;
++
++	if (coord) {
++		rc = wm9712_poll_coord(wm, data);
++		if (rc != RC_VALID)
++			return rc;
++	} else {
++		rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
++		if (rc != RC_VALID)
++			return rc;
++
++		rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
++		if (rc != RC_VALID)
++			return rc;
++
++		if (pil && !five_wire) {
++			rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES,
++						&data->p);
++			if (rc != RC_VALID)
++				return rc;
++		} else
++			data->p = DEFAULT_PRESSURE;
++	}
++	return RC_VALID;
++}
++
++/*
++ * Enable WM9712 continuous mode, i.e. touch data is streamed across
++ * an AC97 slot
++ */
++static int wm9712_acc_enable(struct wm97xx *wm, int enable)
++{
++	u16 dig1, dig2;
++	int ret = 0;
++
++	dig1 = wm->dig[1];
++	dig2 = wm->dig[2];
++
++	if (enable) {
++		/* continous mode */
++		if (wm->mach_ops->acc_startup) {
++			ret = wm->mach_ops->acc_startup(wm);
++			if (ret < 0)
++				return ret;
++		}
++		dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
++			WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
++		dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
++			WM97XX_DELAY(delay) |
++			WM97XX_SLT(wm->acc_slot) |
++			WM97XX_RATE(wm->acc_rate);
++		if (pil)
++			dig1 |= WM97XX_ADCSEL_PRES;
++		dig2 |= WM9712_PDEN;
++	} else {
++		dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
++		dig2 &= ~WM9712_PDEN;
++		if (wm->mach_ops->acc_shutdown)
++			wm->mach_ops->acc_shutdown(wm);
++	}
++
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++
++	return 0;
++}
++
++struct wm97xx_codec_drv wm9712_codec = {
++	.id = WM9712_ID2,
++	.name = "wm9712",
++	.poll_sample = wm9712_poll_sample,
++	.poll_touch = wm9712_poll_touch,
++	.acc_enable = wm9712_acc_enable,
++	.phy_init = wm9712_phy_init,
++	.dig_enable = wm9712_dig_enable,
++	.dig_restore = wm9712_dig_restore,
++	.aux_prepare = wm9712_aux_prepare,
++};
++EXPORT_SYMBOL_GPL(wm9712_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
+new file mode 100644
+index 0000000..01278bd
+--- /dev/null
++++ b/drivers/input/touchscreen/wm9713.c
+@@ -0,0 +1,460 @@
++/*
++ * wm9713.c  --  Codec touch driver for Wolfson WM9713 AC97 Codec.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ *                   Andrew Zabolotny <zap at homelink.ru>
++ *                   Russell King <rmk at arm.linux.org.uk>
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME			"wm97xx"
++#define WM9713_VERSION		"1.00"
++#define DEFAULT_PRESSURE	0xb0c0
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set internal pull up for pen detect.
++ *
++ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
++ * i.e. pull up resistance = 64k Ohms / rpu.
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down event.
++ */
++static int rpu = 8;
++module_param(rpu, int, 0);
++MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ *     pil = 1 to use 200uA and
++ *     pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 4;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * Coordinate Polling Enable.
++ *
++ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
++ * for every poll.
++ */
++static int coord;
++module_param(coord, int, 0);
++MODULE_PARM_DESC(coord, "Polling coordinate mode");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++	21,    /* 1 AC97 Link frames */
++	42,    /* 2 */
++	84,    /* 4 */
++	167,   /* 8 */
++	333,   /* 16 */
++	667,   /* 32 */
++	1000,  /* 48 */
++	1333,  /* 64 */
++	2000,  /* 96 */
++	2667,  /* 128 */
++	3333,  /* 160 */
++	4000,  /* 192 */
++	4667,  /* 224 */
++	5333,  /* 256 */
++	6000,  /* 288 */
++	0      /* No delay, switch matrix always on */
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++	udelay(3 * AC97_LINK_FRAME + delay_table[d]);
++}
++
++/*
++ * set up the physical settings of the WM9713
++ */
++static void wm9713_phy_init(struct wm97xx *wm)
++{
++	u16 dig1 = 0, dig2, dig3;
++
++	/* default values */
++	dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5);
++	dig3 = WM9712_RPU(1);
++
++	/* rpu */
++	if (rpu) {
++		dig3 &= 0xffc0;
++		dig3 |= WM9712_RPU(rpu);
++		dev_info(wm->dev, "setting pen detect pull-up to %d Ohms\n",
++			 64000 / rpu);
++	}
++
++	/* touchpanel pressure */
++	if (pil == 2) {
++		dig3 |= WM9712_PIL;
++		dev_info(wm->dev,
++			 "setting pressure measurement current to 400uA.");
++	} else if (pil)
++		dev_info(wm->dev,
++			 "setting pressure measurement current to 200uA.");
++	if (!pil)
++		pressure = 0;
++
++	/* sample settling delay */
++	if (delay < 0 || delay > 15) {
++		dev_info(wm->dev, "supplied delay out of range.");
++		delay = 4;
++		dev_info(wm->dev, "setting adc sample delay to %d u Secs.",
++			 delay_table[delay]);
++	}
++	dig2 &= 0xff0f;
++	dig2 |= WM97XX_DELAY(delay);
++
++	/* mask */
++	dig3 |= ((mask & 0x3) << 4);
++	if (coord)
++		dig3 |= WM9713_WAIT;
++
++	wm->misc = wm97xx_reg_read(wm, 0x5a);
++
++	wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
++	wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0);
++}
++
++static void wm9713_dig_enable(struct wm97xx *wm, int enable)
++{
++	u16 val;
++
++	if (enable) {
++		val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
++		wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff);
++		wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] |
++				 WM97XX_PRP_DET_DIG);
++		wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++	} else {
++		wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] &
++					~WM97XX_PRP_DET_DIG);
++		val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
++		wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000);
++	}
++}
++
++static void wm9713_dig_restore(struct wm97xx *wm)
++{
++	wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]);
++}
++
++static void wm9713_aux_prepare(struct wm97xx *wm)
++{
++	memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++	wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG);
++}
++
++static inline int is_pden(struct wm97xx *wm)
++{
++	return wm->dig[2] & WM9713_PDEN;
++}
++
++/*
++ * Read a sample from the WM9713 adc in polling mode.
++ */
++static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
++{
++	u16 dig1;
++	int timeout = 5 * delay;
++
++	if (!wm->pen_probably_down) {
++		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++		if (!(data & WM97XX_PEN_DOWN))
++			return RC_PENUP;
++		wm->pen_probably_down = 1;
++	}
++
++	/* set up digitiser */
++	if (adcsel & 0x8000)
++		adcsel = 1 << ((adcsel & 0x7fff) + 3);
++
++	dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
++	dig1 &= ~WM9713_ADCSEL_MASK;
++
++	if (wm->mach_ops && wm->mach_ops->pre_sample)
++		wm->mach_ops->pre_sample(adcsel);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL);
++
++	/* wait 3 AC97 time slots + delay for conversion */
++	poll_delay(delay);
++
++	/* wait for POLL to go low */
++	while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) &&
++		timeout) {
++		udelay(AC97_LINK_FRAME);
++		timeout--;
++	}
++
++	if (timeout <= 0) {
++		/* If PDEN is set, we can get a timeout when pen goes up */
++		if (is_pden(wm))
++			wm->pen_probably_down = 0;
++		else
++			dev_dbg(wm->dev, "adc sample timeout");
++		return RC_PENUP;
++	}
++
++	*sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++	if (wm->mach_ops && wm->mach_ops->post_sample)
++		wm->mach_ops->post_sample(adcsel);
++
++	/* check we have correct sample */
++	if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
++		dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
++			*sample & WM97XX_ADCSRC_MASK);
++		return RC_PENUP;
++	}
++
++	if (!(*sample & WM97XX_PEN_DOWN)) {
++		wm->pen_probably_down = 0;
++		return RC_PENUP;
++	}
++
++	return RC_VALID;
++}
++
++/*
++ * Read a coordinate from the WM9713 adc in polling mode.
++ */
++static int wm9713_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
++{
++	u16 dig1;
++	int timeout = 5 * delay;
++
++	if (!wm->pen_probably_down) {
++		u16 val = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++		if (!(val & WM97XX_PEN_DOWN))
++			return RC_PENUP;
++		wm->pen_probably_down = 1;
++	}
++
++	/* set up digitiser */
++	dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
++	dig1 &= ~WM9713_ADCSEL_MASK;
++	if (pil)
++		dig1 |= WM9713_ADCSEL_PRES;
++
++	if (wm->mach_ops && wm->mach_ops->pre_sample)
++		wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG1,
++			 dig1 | WM9713_POLL | WM9713_COO);
++
++	/* wait 3 AC97 time slots + delay for conversion */
++	poll_delay(delay);
++	data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++	/* wait for POLL to go low */
++	while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL)
++	       && timeout) {
++		udelay(AC97_LINK_FRAME);
++		timeout--;
++	}
++
++	if (timeout <= 0) {
++		/* If PDEN is set, we can get a timeout when pen goes up */
++		if (is_pden(wm))
++			wm->pen_probably_down = 0;
++		else
++			dev_dbg(wm->dev, "adc sample timeout");
++		return RC_PENUP;
++	}
++
++	/* read back data */
++	data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++	if (pil)
++		data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++	else
++		data->p = DEFAULT_PRESSURE;
++
++	if (wm->mach_ops && wm->mach_ops->post_sample)
++		wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++
++	/* check we have correct sample */
++	if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
++		goto err;
++	if (pil && !(data->p & WM97XX_ADCSEL_PRES))
++		goto err;
++
++	if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
++		wm->pen_probably_down = 0;
++		return RC_PENUP;
++	}
++	return RC_VALID;
++err:
++	return 0;
++}
++
++/*
++ * Sample the WM9713 touchscreen in polling mode
++ */
++static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
++{
++	int rc;
++
++	if (coord) {
++		rc = wm9713_poll_coord(wm, data);
++		if (rc != RC_VALID)
++			return rc;
++	} else {
++		rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x);
++		if (rc != RC_VALID)
++			return rc;
++		rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y);
++		if (rc != RC_VALID)
++			return rc;
++		if (pil) {
++			rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES,
++						&data->p);
++			if (rc != RC_VALID)
++				return rc;
++		} else
++			data->p = DEFAULT_PRESSURE;
++	}
++	return RC_VALID;
++}
++
++/*
++ * Enable WM9713 continuous mode, i.e. touch data is streamed across
++ * an AC97 slot
++ */
++static int wm9713_acc_enable(struct wm97xx *wm, int enable)
++{
++	u16 dig1, dig2, dig3;
++	int ret = 0;
++
++	dig1 = wm->dig[0];
++	dig2 = wm->dig[1];
++	dig3 = wm->dig[2];
++
++	if (enable) {
++		/* continous mode */
++		if (wm->mach_ops->acc_startup &&
++			(ret = wm->mach_ops->acc_startup(wm)) < 0)
++			return ret;
++
++		dig1 &= ~WM9713_ADCSEL_MASK;
++		dig1 |= WM9713_CTC | WM9713_COO | WM9713_ADCSEL_X |
++			WM9713_ADCSEL_Y;
++		if (pil)
++			dig1 |= WM9713_ADCSEL_PRES;
++		dig2 &= ~(WM97XX_DELAY_MASK | WM97XX_SLT_MASK  |
++			WM97XX_CM_RATE_MASK);
++		dig2 |= WM97XX_SLEN | WM97XX_DELAY(delay) |
++		WM97XX_SLT(wm->acc_slot) | WM97XX_RATE(wm->acc_rate);
++		dig3 |= WM9713_PDEN;
++	} else {
++		dig1 &= ~(WM9713_CTC | WM9713_COO);
++		dig2 &= ~WM97XX_SLEN;
++		dig3 &= ~WM9713_PDEN;
++		if (wm->mach_ops->acc_shutdown)
++			wm->mach_ops->acc_shutdown(wm);
++	}
++
++	wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
++
++	return ret;
++}
++
++struct wm97xx_codec_drv wm9713_codec = {
++	.id = WM9713_ID2,
++	.name = "wm9713",
++	.poll_sample = wm9713_poll_sample,
++	.poll_touch = wm9713_poll_touch,
++	.acc_enable = wm9713_acc_enable,
++	.phy_init = wm9713_phy_init,
++	.dig_enable = wm9713_dig_enable,
++	.dig_restore = wm9713_dig_restore,
++	.aux_prepare = wm9713_aux_prepare,
++};
++EXPORT_SYMBOL_GPL(wm9713_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
+new file mode 100644
+index 0000000..e9c7ea4
+--- /dev/null
++++ b/drivers/input/touchscreen/wm97xx-core.c
+@@ -0,0 +1,829 @@
++/*
++ * wm97xx-core.c  --  Touch screen driver core for Wolfson WM9705, WM9712
++ *                    and WM9713 AC97 Codecs.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ *                   Andrew Zabolotny <zap at homelink.ru>
++ *                   Russell King <rmk at arm.linux.org.uk>
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ * Notes:
++ *
++ *  Features:
++ *       - supports WM9705, WM9712, WM9713
++ *       - polling mode
++ *       - continuous mode (arch-dependent)
++ *       - adjustable rpu/dpp settings
++ *       - adjustable pressure current
++ *       - adjustable sample settle delay
++ *       - 4 and 5 wire touchscreens (5 wire is WM9712 only)
++ *       - pen down detection
++ *       - battery monitor
++ *       - sample AUX adcs
++ *       - power management
++ *       - codec GPIO
++ *       - codec event notification
++ * Todo
++ *       - Support for async sampling control for noisy LCDs.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++#include <linux/pm.h>
++#include <linux/interrupt.h>
++#include <linux/bitops.h>
++#include <linux/workqueue.h>
++#include <linux/wm97xx.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
++
++#define TS_NAME			"wm97xx"
++#define WM_CORE_VERSION		"1.00"
++#define DEFAULT_PRESSURE	0xb0c0
++
++
++/*
++ * Touchscreen absolute values
++ *
++ * These parameters are used to help the input layer discard out of
++ * range readings and reduce jitter etc.
++ *
++ *   o min, max:- indicate the min and max values your touch screen returns
++ *   o fuzz:- use a higher number to reduce jitter
++ *
++ * The default values correspond to Mainstone II in QVGA mode
++ *
++ * Please read
++ * Documentation/input/input-programming.txt for more details.
++ */
++
++static int abs_x[3] = {350, 3900, 5};
++module_param_array(abs_x, int, NULL, 0);
++MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
++
++static int abs_y[3] = {320, 3750, 40};
++module_param_array(abs_y, int, NULL, 0);
++MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
++
++static int abs_p[3] = {0, 150, 4};
++module_param_array(abs_p, int, NULL, 0);
++MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
++
++/*
++ * wm97xx IO access, all IO locking done by AC97 layer
++ */
++int wm97xx_reg_read(struct wm97xx *wm, u16 reg)
++{
++	if (wm->ac97)
++		return wm->ac97->bus->ops->read(wm->ac97, reg);
++	else
++		return -1;
++}
++EXPORT_SYMBOL_GPL(wm97xx_reg_read);
++
++void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val)
++{
++	/* cache digitiser registers */
++	if (reg >= AC97_WM9713_DIG1 && reg <= AC97_WM9713_DIG3)
++		wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val;
++
++	/* cache gpio regs */
++	if (reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE)
++		wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val;
++
++	/* wm9713 irq reg */
++	if (reg == 0x5a)
++		wm->misc = val;
++
++	if (wm->ac97)
++		wm->ac97->bus->ops->write(wm->ac97, reg, val);
++}
++EXPORT_SYMBOL_GPL(wm97xx_reg_write);
++
++/**
++ * wm97xx_read_aux_adc - Read the aux adc.
++ * @wm: wm97xx device.
++ * @adcsel: codec ADC to be read
++ *
++ * Reads the selected AUX ADC.
++ */
++
++int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
++{
++	int power_adc = 0, auxval;
++	u16 power = 0;
++
++	/* get codec */
++	mutex_lock(&wm->codec_mutex);
++
++	/* When the touchscreen is not in use, we may have to power up
++	 * the AUX ADC before we can use sample the AUX inputs->
++	 */
++	if (wm->id == WM9713_ID2 &&
++	    (power = wm97xx_reg_read(wm, AC97_EXTENDED_MID)) & 0x8000) {
++		power_adc = 1;
++		wm97xx_reg_write(wm, AC97_EXTENDED_MID, power & 0x7fff);
++	}
++
++	/* Prepare the codec for AUX reading */
++	wm->codec->aux_prepare(wm);
++
++	/* Turn polling mode on to read AUX ADC */
++	wm->pen_probably_down = 1;
++	wm->codec->poll_sample(wm, adcsel, &auxval);
++
++	if (power_adc)
++		wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
++
++	wm->codec->dig_restore(wm);
++
++	wm->pen_probably_down = 0;
++
++	mutex_unlock(&wm->codec_mutex);
++	return auxval & 0xfff;
++}
++EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
++
++/**
++ * wm97xx_get_gpio - Get the status of a codec GPIO.
++ * @wm: wm97xx device.
++ * @gpio: gpio
++ *
++ * Get the status of a codec GPIO pin
++ */
++
++enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio)
++{
++	u16 status;
++	enum wm97xx_gpio_status ret;
++
++	mutex_lock(&wm->codec_mutex);
++	status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++
++	if (status & gpio)
++		ret = WM97XX_GPIO_HIGH;
++	else
++		ret = WM97XX_GPIO_LOW;
++
++	mutex_unlock(&wm->codec_mutex);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(wm97xx_get_gpio);
++
++/**
++ * wm97xx_set_gpio - Set the status of a codec GPIO.
++ * @wm: wm97xx device.
++ * @gpio: gpio
++ *
++ *
++ * Set the status of a codec GPIO pin
++ */
++
++void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
++				enum wm97xx_gpio_status status)
++{
++	u16 reg;
++
++	mutex_lock(&wm->codec_mutex);
++	reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++
++	if (status & WM97XX_GPIO_HIGH)
++		reg |= gpio;
++	else
++		reg &= ~gpio;
++
++	if (wm->id == WM9712_ID2)
++		wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
++	else
++		wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
++	mutex_unlock(&wm->codec_mutex);
++}
++EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
++
++/*
++ * Codec GPIO pin configuration, this sets pin direction, polarity,
++ * stickyness and wake up.
++ */
++void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, enum wm97xx_gpio_dir dir,
++		   enum wm97xx_gpio_pol pol, enum wm97xx_gpio_sticky sticky,
++		   enum wm97xx_gpio_wake wake)
++{
++	u16 reg;
++
++	mutex_lock(&wm->codec_mutex);
++	reg = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
++
++	if (pol == WM97XX_GPIO_POL_HIGH)
++		reg |= gpio;
++	else
++		reg &= ~gpio;
++
++	wm97xx_reg_write(wm, AC97_GPIO_POLARITY, reg);
++	reg = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
++
++	if (sticky == WM97XX_GPIO_STICKY)
++		reg |= gpio;
++	else
++		reg &= ~gpio;
++
++	wm97xx_reg_write(wm, AC97_GPIO_STICKY, reg);
++	reg = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
++
++	if (wake == WM97XX_GPIO_WAKE)
++		reg |= gpio;
++	else
++		reg &= ~gpio;
++
++	wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, reg);
++	reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++
++	if (dir == WM97XX_GPIO_IN)
++		reg |= gpio;
++	else
++		reg &= ~gpio;
++
++	wm97xx_reg_write(wm, AC97_GPIO_CFG, reg);
++	mutex_unlock(&wm->codec_mutex);
++}
++EXPORT_SYMBOL_GPL(wm97xx_config_gpio);
++
++/*
++ * Configure the WM97XX_PRP value to use while system is suspended.
++ * If a value other than 0 is set then WM97xx pen detection will be
++ * left enabled in the configured mode while the system is in suspend,
++ * the device has users and suspend has not been disabled via the
++ * wakeup sysfs entries.
++ *
++ * @wm:   WM97xx device to configure
++ * @mode: WM97XX_PRP value to configure while suspended
++ */
++void wm97xx_set_suspend_mode(struct wm97xx *wm, u16 mode)
++{
++	wm->suspend_mode = mode;
++	device_init_wakeup(&wm->input_dev->dev, mode != 0);
++}
++EXPORT_SYMBOL_GPL(wm97xx_set_suspend_mode);
++
++/*
++ * Handle a pen down interrupt.
++ */
++static void wm97xx_pen_irq_worker(struct work_struct *work)
++{
++	struct wm97xx *wm = container_of(work, struct wm97xx, pen_event_work);
++	int pen_was_down = wm->pen_is_down;
++
++	/* do we need to enable the touch panel reader */
++	if (wm->id == WM9705_ID2) {
++		if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) &
++					WM97XX_PEN_DOWN)
++			wm->pen_is_down = 1;
++		else
++			wm->pen_is_down = 0;
++	} else {
++		u16 status, pol;
++		mutex_lock(&wm->codec_mutex);
++		status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++		pol = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
++
++		if (WM97XX_GPIO_13 & pol & status) {
++			wm->pen_is_down = 1;
++			wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol &
++						~WM97XX_GPIO_13);
++		} else {
++			wm->pen_is_down = 0;
++			wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol |
++					 WM97XX_GPIO_13);
++		}
++
++		if (wm->id == WM9712_ID2)
++			wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status &
++						~WM97XX_GPIO_13) << 1);
++		else
++			wm97xx_reg_write(wm, AC97_GPIO_STATUS, status &
++						~WM97XX_GPIO_13);
++		mutex_unlock(&wm->codec_mutex);
++	}
++
++	/* If the system is not using continuous mode or it provides a
++	 * pen down operation then we need to schedule polls while the
++	 * pen is down.  Otherwise the machine driver is responsible
++	 * for scheduling reads.
++	 */
++	if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) {
++		if (wm->pen_is_down && !pen_was_down) {
++			/* Data is not availiable immediately on pen down */
++			queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1);
++		}
++
++		/* Let ts_reader report the pen up for debounce. */
++		if (!wm->pen_is_down && pen_was_down)
++			wm->pen_is_down = 1;
++	}
++
++	if (!wm->pen_is_down && wm->mach_ops->acc_enabled)
++		wm->mach_ops->acc_pen_up(wm);
++
++	wm->mach_ops->irq_enable(wm, 1);
++}
++
++/*
++ * Codec PENDOWN irq handler
++ *
++ * We have to disable the codec interrupt in the handler because it
++ * can take upto 1ms to clear the interrupt source. We schedule a task
++ * in a work queue to do the actual interaction with the chip.  The
++ * interrupt is then enabled again in the slow handler when the source
++ * has been cleared.
++ */
++static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
++{
++	struct wm97xx *wm = dev_id;
++
++	if (!work_pending(&wm->pen_event_work)) {
++		wm->mach_ops->irq_enable(wm, 0);
++		queue_work(wm->ts_workq, &wm->pen_event_work);
++	}
++
++	return IRQ_HANDLED;
++}
++
++/*
++ * initialise pen IRQ handler and workqueue
++ */
++static int wm97xx_init_pen_irq(struct wm97xx *wm)
++{
++	u16 reg;
++
++	/* If an interrupt is supplied an IRQ enable operation must also be
++	 * provided. */
++	BUG_ON(!wm->mach_ops->irq_enable);
++
++	if (request_irq(wm->pen_irq, wm97xx_pen_interrupt,
++			IRQF_SHARED | IRQF_SAMPLE_RANDOM,
++			"wm97xx-pen", wm)) {
++		dev_err(wm->dev,
++			"Failed to register pen down interrupt, polling");
++		wm->pen_irq = 0;
++		return -EINVAL;
++	}
++
++	/* Configure GPIO as interrupt source on WM971x */
++	if (wm->id != WM9705_ID2) {
++		BUG_ON(!wm->mach_ops->irq_gpio);
++		reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
++		wm97xx_reg_write(wm, AC97_MISC_AFE,
++				reg & ~(wm->mach_ops->irq_gpio));
++		reg = wm97xx_reg_read(wm, 0x5a);
++		wm97xx_reg_write(wm, 0x5a, reg & ~0x0001);
++	}
++
++	return 0;
++}
++
++static int wm97xx_read_samples(struct wm97xx *wm)
++{
++	struct wm97xx_data data;
++	int rc;
++
++	mutex_lock(&wm->codec_mutex);
++
++	if (wm->mach_ops && wm->mach_ops->acc_enabled)
++		rc = wm->mach_ops->acc_pen_down(wm);
++	else
++		rc = wm->codec->poll_touch(wm, &data);
++
++	if (rc & RC_PENUP) {
++		if (wm->pen_is_down) {
++			wm->pen_is_down = 0;
++			dev_dbg(wm->dev, "pen up\n");
++			input_report_abs(wm->input_dev, ABS_PRESSURE, 0);
++			input_sync(wm->input_dev);
++		} else if (!(rc & RC_AGAIN)) {
++			/* We need high frequency updates only while
++			* pen is down, the user never will be able to
++			* touch screen faster than a few times per
++			* second... On the other hand, when the user
++			* is actively working with the touchscreen we
++			* don't want to lose the quick response. So we
++			* will slowly increase sleep time after the
++			* pen is up and quicky restore it to ~one task
++			* switch when pen is down again.
++			*/
++			if (wm->ts_reader_interval < HZ / 10)
++				wm->ts_reader_interval++;
++		}
++
++	} else if (rc & RC_VALID) {
++		dev_dbg(wm->dev,
++			"pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n",
++			data.x >> 12, data.x & 0xfff, data.y >> 12,
++			data.y & 0xfff, data.p >> 12, data.p & 0xfff);
++		input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
++		input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);
++		input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
++		input_sync(wm->input_dev);
++		wm->pen_is_down = 1;
++		wm->ts_reader_interval = wm->ts_reader_min_interval;
++	} else if (rc & RC_PENDOWN) {
++		dev_dbg(wm->dev, "pen down\n");
++		wm->pen_is_down = 1;
++		wm->ts_reader_interval = wm->ts_reader_min_interval;
++	}
++
++	mutex_unlock(&wm->codec_mutex);
++	return rc;
++}
++
++/*
++* The touchscreen sample reader.
++*/
++static void wm97xx_ts_reader(struct work_struct *work)
++{
++	int rc;
++	struct wm97xx *wm = container_of(work, struct wm97xx, ts_reader.work);
++
++	BUG_ON(!wm->codec);
++
++	do {
++		rc = wm97xx_read_samples(wm);
++	} while (rc & RC_AGAIN);
++
++	if (wm->pen_is_down || !wm->pen_irq)
++		queue_delayed_work(wm->ts_workq, &wm->ts_reader,
++				   wm->ts_reader_interval);
++}
++
++/**
++ * wm97xx_ts_input_open - Open the touch screen input device.
++ * @idev:	Input device to be opened.
++ *
++ * Called by the input sub system to open a wm97xx touchscreen device.
++ * Starts the touchscreen thread and touch digitiser.
++ */
++static int wm97xx_ts_input_open(struct input_dev *idev)
++{
++	struct wm97xx *wm = input_get_drvdata(idev);
++
++	wm->ts_workq = create_singlethread_workqueue("kwm97xx");
++	if (wm->ts_workq == NULL) {
++		dev_err(wm->dev,
++			"Failed to create workqueue\n");
++		return -EINVAL;
++	}
++
++	/* start digitiser */
++	if (wm->mach_ops && wm->mach_ops->acc_enabled)
++		wm->codec->acc_enable(wm, 1);
++	wm->codec->dig_enable(wm, 1);
++
++	INIT_DELAYED_WORK(&wm->ts_reader, wm97xx_ts_reader);
++	INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker);
++
++	wm->ts_reader_min_interval = HZ >= 100 ? HZ / 100 : 1;
++	if (wm->ts_reader_min_interval < 1)
++		wm->ts_reader_min_interval = 1;
++	wm->ts_reader_interval = wm->ts_reader_min_interval;
++
++	wm->pen_is_down = 0;
++	if (wm->pen_irq)
++		wm97xx_init_pen_irq(wm);
++	else
++		dev_err(wm->dev, "No IRQ specified\n");
++
++	/* If we either don't have an interrupt for pen down events or
++	 * failed to acquire it then we need to poll.
++	 */
++	if (wm->pen_irq == 0)
++		queue_delayed_work(wm->ts_workq, &wm->ts_reader,
++				   wm->ts_reader_interval);
++
++	return 0;
++}
++
++/**
++ * wm97xx_ts_input_close - Close the touch screen input device.
++ * @idev:	Input device to be closed.
++ *
++ * Called by the input sub system to close a wm97xx touchscreen
++ * device.  Kills the touchscreen thread and stops the touch
++ * digitiser.
++ */
++
++static void wm97xx_ts_input_close(struct input_dev *idev)
++{
++	struct wm97xx *wm = input_get_drvdata(idev);
++	u16 reg;
++
++	if (wm->pen_irq) {
++		/* Return the interrupt to GPIO usage (disabling it) */
++		if (wm->id != WM9705_ID2) {
++			BUG_ON(!wm->mach_ops->irq_gpio);
++			reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
++			wm97xx_reg_write(wm, AC97_MISC_AFE,
++					 reg | wm->mach_ops->irq_gpio);
++		}
++
++		free_irq(wm->pen_irq, wm);
++	}
++
++	wm->pen_is_down = 0;
++
++	/* Balance out interrupt disables/enables */
++	if (cancel_work_sync(&wm->pen_event_work))
++		wm->mach_ops->irq_enable(wm, 1);
++
++	/* ts_reader rearms itself so we need to explicitly stop it
++	 * before we destroy the workqueue.
++	 */
++	cancel_delayed_work_sync(&wm->ts_reader);
++
++	destroy_workqueue(wm->ts_workq);
++
++	/* stop digitiser */
++	wm->codec->dig_enable(wm, 0);
++	if (wm->mach_ops && wm->mach_ops->acc_enabled)
++		wm->codec->acc_enable(wm, 0);
++}
++
++static int wm97xx_probe(struct device *dev)
++{
++	struct wm97xx *wm;
++	int ret = 0, id = 0;
++
++	wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL);
++	if (!wm)
++		return -ENOMEM;
++	mutex_init(&wm->codec_mutex);
++
++	wm->dev = dev;
++	dev->driver_data = wm;
++	wm->ac97 = to_ac97_t(dev);
++
++	/* check that we have a supported codec */
++	id = wm97xx_reg_read(wm, AC97_VENDOR_ID1);
++	if (id != WM97XX_ID1) {
++		dev_err(dev, "Device with vendor %04x is not a wm97xx\n", id);
++		ret = -ENODEV;
++		goto alloc_err;
++	}
++
++	wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2);
++
++	dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff);
++
++	switch (wm->id & 0xff) {
++#ifdef CONFIG_TOUCHSCREEN_WM9705
++	case 0x05:
++		wm->codec = &wm9705_codec;
++		break;
++#endif
++#ifdef CONFIG_TOUCHSCREEN_WM9712
++	case 0x12:
++		wm->codec = &wm9712_codec;
++		break;
++#endif
++#ifdef CONFIG_TOUCHSCREEN_WM9713
++	case 0x13:
++		wm->codec = &wm9713_codec;
++		break;
++#endif
++	default:
++		dev_err(wm->dev, "Support for wm97%02x not compiled in.\n",
++			wm->id & 0xff);
++		ret = -ENODEV;
++		goto alloc_err;
++	}
++
++	wm->input_dev = input_allocate_device();
++	if (wm->input_dev == NULL) {
++		ret = -ENOMEM;
++		goto alloc_err;
++	}
++
++	/* set up touch configuration */
++	wm->input_dev->name = "wm97xx touchscreen";
++	wm->input_dev->open = wm97xx_ts_input_open;
++	wm->input_dev->close = wm97xx_ts_input_close;
++	set_bit(EV_ABS, wm->input_dev->evbit);
++	set_bit(ABS_X, wm->input_dev->absbit);
++	set_bit(ABS_Y, wm->input_dev->absbit);
++	set_bit(ABS_PRESSURE, wm->input_dev->absbit);
++	input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1],
++			     abs_x[2], 0);
++	input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1],
++			     abs_y[2], 0);
++	input_set_abs_params(wm->input_dev, ABS_PRESSURE, abs_p[0], abs_p[1],
++			     abs_p[2], 0);
++	input_set_drvdata(wm->input_dev, wm);
++	wm->input_dev->dev.parent = dev;
++	ret = input_register_device(wm->input_dev);
++	if (ret < 0)
++		goto dev_alloc_err;
++
++	/* set up physical characteristics */
++	wm->codec->phy_init(wm);
++
++	/* load gpio cache */
++	wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++	wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
++	wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
++	wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
++	wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++	wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
++
++	/* register our battery device */
++	wm->battery_dev = platform_device_alloc("wm97xx-battery", -1);
++	if (!wm->battery_dev) {
++		ret = -ENOMEM;
++		goto batt_err;
++	}
++	platform_set_drvdata(wm->battery_dev, wm);
++	wm->battery_dev->dev.parent = dev;
++	ret = platform_device_add(wm->battery_dev);
++	if (ret < 0)
++		goto batt_reg_err;
++
++	/* register our extended touch device (for machine specific
++	 * extensions) */
++	wm->touch_dev = platform_device_alloc("wm97xx-touch", -1);
++	if (!wm->touch_dev) {
++		ret = -ENOMEM;
++		goto touch_err;
++	}
++	platform_set_drvdata(wm->touch_dev, wm);
++	wm->touch_dev->dev.parent = dev;
++	ret = platform_device_add(wm->touch_dev);
++	if (ret < 0)
++		goto touch_reg_err;
++
++	return ret;
++
++ touch_reg_err:
++	platform_device_put(wm->touch_dev);
++ touch_err:
++	platform_device_unregister(wm->battery_dev);
++	wm->battery_dev = NULL;
++ batt_reg_err:
++	platform_device_put(wm->battery_dev);
++ batt_err:
++	input_unregister_device(wm->input_dev);
++	wm->input_dev = NULL;
++ dev_alloc_err:
++	input_free_device(wm->input_dev);
++ alloc_err:
++	kfree(wm);
++
++	return ret;
++}
++
++static int wm97xx_remove(struct device *dev)
++{
++	struct wm97xx *wm = dev_get_drvdata(dev);
++
++	platform_device_unregister(wm->battery_dev);
++	platform_device_unregister(wm->touch_dev);
++	input_unregister_device(wm->input_dev);
++	kfree(wm);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int wm97xx_suspend(struct device *dev, pm_message_t state)
++{
++	struct wm97xx *wm = dev_get_drvdata(dev);
++	u16 reg;
++	int suspend_mode;
++
++	if (device_may_wakeup(&wm->input_dev->dev))
++		suspend_mode = wm->suspend_mode;
++	else
++		suspend_mode = 0;
++
++	if (wm->input_dev->users)
++		cancel_delayed_work_sync(&wm->ts_reader);
++
++	/* Power down the digitiser (bypassing the cache for resume) */
++	reg = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER2);
++	reg &= ~WM97XX_PRP_DET_DIG;
++	if (wm->input_dev->users)
++		reg |= suspend_mode;
++	wm->ac97->bus->ops->write(wm->ac97, AC97_WM97XX_DIGITISER2, reg);
++
++	/* WM9713 has an additional power bit - turn it off if there
++	 * are no users or if suspend mode is zero. */
++	if (wm->id == WM9713_ID2 &&
++	    (!wm->input_dev->users || !suspend_mode)) {
++		reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) | 0x8000;
++		wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
++	}
++
++	return 0;
++}
++
++static int wm97xx_resume(struct device *dev)
++{
++	struct wm97xx *wm = dev_get_drvdata(dev);
++
++	/* restore digitiser and gpios */
++	if (wm->id == WM9713_ID2) {
++		wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
++		wm97xx_reg_write(wm, 0x5a, wm->misc);
++		if (wm->input_dev->users) {
++			u16 reg;
++			reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
++			wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
++		}
++	}
++
++	wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]);
++	wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]);
++
++	wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]);
++	wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]);
++	wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]);
++	wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]);
++	wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
++	wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
++
++	if (wm->input_dev->users && !wm->pen_irq) {
++		wm->ts_reader_interval = wm->ts_reader_min_interval;
++		queue_delayed_work(wm->ts_workq, &wm->ts_reader,
++				   wm->ts_reader_interval);
++	}
++
++	return 0;
++}
++
++#else
++#define wm97xx_suspend		NULL
++#define wm97xx_resume		NULL
++#endif
++
++/*
++ * Machine specific operations
++ */
++int wm97xx_register_mach_ops(struct wm97xx *wm,
++			     struct wm97xx_mach_ops *mach_ops)
++{
++	mutex_lock(&wm->codec_mutex);
++	if (wm->mach_ops) {
++		mutex_unlock(&wm->codec_mutex);
++		return -EINVAL;
++	}
++	wm->mach_ops = mach_ops;
++	mutex_unlock(&wm->codec_mutex);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
++
++void wm97xx_unregister_mach_ops(struct wm97xx *wm)
++{
++	mutex_lock(&wm->codec_mutex);
++	wm->mach_ops = NULL;
++	mutex_unlock(&wm->codec_mutex);
++}
++EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
++
++static struct device_driver wm97xx_driver = {
++	.name =		"ac97",
++	.bus =		&ac97_bus_type,
++	.owner =	THIS_MODULE,
++	.probe =	wm97xx_probe,
++	.remove =	wm97xx_remove,
++	.suspend =	wm97xx_suspend,
++	.resume =	wm97xx_resume,
++};
++
++static int __init wm97xx_init(void)
++{
++	return driver_register(&wm97xx_driver);
++}
++
++static void __exit wm97xx_exit(void)
++{
++	driver_unregister(&wm97xx_driver);
++}
++
++module_init(wm97xx_init);
++module_exit(wm97xx_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
+new file mode 100644
+index 0000000..0f47f46
+--- /dev/null
++++ b/drivers/input/xen-kbdfront.c
+@@ -0,0 +1,340 @@
++/*
++ * Xen para-virtual input device
++ *
++ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
++ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
++ *
++ *  Based on linux/drivers/input/mouse/sermouse.c
++ *
++ *  This file is subject to the terms and conditions of the GNU General Public
++ *  License. See the file COPYING in the main directory of this archive for
++ *  more details.
++ */
++
++/*
++ * TODO:
++ *
++ * Switch to grant tables together with xen-fbfront.c.
++ */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/input.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/events.h>
++#include <xen/page.h>
++#include <xen/interface/io/fbif.h>
++#include <xen/interface/io/kbdif.h>
++#include <xen/xenbus.h>
++
++struct xenkbd_info {
++	struct input_dev *kbd;
++	struct input_dev *ptr;
++	struct xenkbd_page *page;
++	int irq;
++	struct xenbus_device *xbdev;
++	char phys[32];
++};
++
++static int xenkbd_remove(struct xenbus_device *);
++static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
++static void xenkbd_disconnect_backend(struct xenkbd_info *);
++
++/*
++ * Note: if you need to send out events, see xenfb_do_update() for how
++ * to do that.
++ */
++
++static irqreturn_t input_handler(int rq, void *dev_id)
++{
++	struct xenkbd_info *info = dev_id;
++	struct xenkbd_page *page = info->page;
++	__u32 cons, prod;
++
++	prod = page->in_prod;
++	if (prod == page->in_cons)
++		return IRQ_HANDLED;
++	rmb();			/* ensure we see ring contents up to prod */
++	for (cons = page->in_cons; cons != prod; cons++) {
++		union xenkbd_in_event *event;
++		struct input_dev *dev;
++		event = &XENKBD_IN_RING_REF(page, cons);
++
++		dev = info->ptr;
++		switch (event->type) {
++		case XENKBD_TYPE_MOTION:
++			input_report_rel(dev, REL_X, event->motion.rel_x);
++			input_report_rel(dev, REL_Y, event->motion.rel_y);
++			break;
++		case XENKBD_TYPE_KEY:
++			dev = NULL;
++			if (test_bit(event->key.keycode, info->kbd->keybit))
++				dev = info->kbd;
++			if (test_bit(event->key.keycode, info->ptr->keybit))
++				dev = info->ptr;
++			if (dev)
++				input_report_key(dev, event->key.keycode,
++						 event->key.pressed);
++			else
++				printk(KERN_WARNING
++				       "xenkbd: unhandled keycode 0x%x\n",
++				       event->key.keycode);
++			break;
++		case XENKBD_TYPE_POS:
++			input_report_abs(dev, ABS_X, event->pos.abs_x);
++			input_report_abs(dev, ABS_Y, event->pos.abs_y);
++			break;
++		}
++		if (dev)
++			input_sync(dev);
++	}
++	mb();			/* ensure we got ring contents */
++	page->in_cons = cons;
++	notify_remote_via_irq(info->irq);
++
++	return IRQ_HANDLED;
++}
++
++static int __devinit xenkbd_probe(struct xenbus_device *dev,
++				  const struct xenbus_device_id *id)
++{
++	int ret, i;
++	struct xenkbd_info *info;
++	struct input_dev *kbd, *ptr;
++
++	info = kzalloc(sizeof(*info), GFP_KERNEL);
++	if (!info) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
++		return -ENOMEM;
++	}
++	dev->dev.driver_data = info;
++	info->xbdev = dev;
++	info->irq = -1;
++	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
++
++	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
++	if (!info->page)
++		goto error_nomem;
++
++	/* keyboard */
++	kbd = input_allocate_device();
++	if (!kbd)
++		goto error_nomem;
++	kbd->name = "Xen Virtual Keyboard";
++	kbd->phys = info->phys;
++	kbd->id.bustype = BUS_PCI;
++	kbd->id.vendor = 0x5853;
++	kbd->id.product = 0xffff;
++	kbd->evbit[0] = BIT(EV_KEY);
++	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
++		set_bit(i, kbd->keybit);
++	for (i = KEY_OK; i < KEY_MAX; i++)
++		set_bit(i, kbd->keybit);
++
++	ret = input_register_device(kbd);
++	if (ret) {
++		input_free_device(kbd);
++		xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
++		goto error;
++	}
++	info->kbd = kbd;
++
++	/* pointing device */
++	ptr = input_allocate_device();
++	if (!ptr)
++		goto error_nomem;
++	ptr->name = "Xen Virtual Pointer";
++	ptr->phys = info->phys;
++	ptr->id.bustype = BUS_PCI;
++	ptr->id.vendor = 0x5853;
++	ptr->id.product = 0xfffe;
++	ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
++	for (i = BTN_LEFT; i <= BTN_TASK; i++)
++		set_bit(i, ptr->keybit);
++	ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y);
++	input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
++	input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
++
++	ret = input_register_device(ptr);
++	if (ret) {
++		input_free_device(ptr);
++		xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
++		goto error;
++	}
++	info->ptr = ptr;
++
++	ret = xenkbd_connect_backend(dev, info);
++	if (ret < 0)
++		goto error;
++
++	return 0;
++
++ error_nomem:
++	ret = -ENOMEM;
++	xenbus_dev_fatal(dev, ret, "allocating device memory");
++ error:
++	xenkbd_remove(dev);
++	return ret;
++}
++
++static int xenkbd_resume(struct xenbus_device *dev)
++{
++	struct xenkbd_info *info = dev->dev.driver_data;
++
++	xenkbd_disconnect_backend(info);
++	memset(info->page, 0, PAGE_SIZE);
++	return xenkbd_connect_backend(dev, info);
++}
++
++static int xenkbd_remove(struct xenbus_device *dev)
++{
++	struct xenkbd_info *info = dev->dev.driver_data;
++
++	xenkbd_disconnect_backend(info);
++	if (info->kbd)
++		input_unregister_device(info->kbd);
++	if (info->ptr)
++		input_unregister_device(info->ptr);
++	free_page((unsigned long)info->page);
++	kfree(info);
++	return 0;
++}
++
++static int xenkbd_connect_backend(struct xenbus_device *dev,
++				  struct xenkbd_info *info)
++{
++	int ret, evtchn;
++	struct xenbus_transaction xbt;
++
++	ret = xenbus_alloc_evtchn(dev, &evtchn);
++	if (ret)
++		return ret;
++	ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
++					0, dev->devicetype, info);
++	if (ret < 0) {
++		xenbus_free_evtchn(dev, evtchn);
++		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
++		return ret;
++	}
++	info->irq = ret;
++
++ again:
++	ret = xenbus_transaction_start(&xbt);
++	if (ret) {
++		xenbus_dev_fatal(dev, ret, "starting transaction");
++		return ret;
++	}
++	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
++			    virt_to_mfn(info->page));
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++			    evtchn);
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_transaction_end(xbt, 0);
++	if (ret) {
++		if (ret == -EAGAIN)
++			goto again;
++		xenbus_dev_fatal(dev, ret, "completing transaction");
++		return ret;
++	}
++
++	xenbus_switch_state(dev, XenbusStateInitialised);
++	return 0;
++
++ error_xenbus:
++	xenbus_transaction_end(xbt, 1);
++	xenbus_dev_fatal(dev, ret, "writing xenstore");
++	return ret;
++}
++
++static void xenkbd_disconnect_backend(struct xenkbd_info *info)
++{
++	if (info->irq >= 0)
++		unbind_from_irqhandler(info->irq, info);
++	info->irq = -1;
++}
++
++static void xenkbd_backend_changed(struct xenbus_device *dev,
++				   enum xenbus_state backend_state)
++{
++	struct xenkbd_info *info = dev->dev.driver_data;
++	int ret, val;
++
++	switch (backend_state) {
++	case XenbusStateInitialising:
++	case XenbusStateInitialised:
++	case XenbusStateUnknown:
++	case XenbusStateClosed:
++		break;
++
++	case XenbusStateInitWait:
++InitWait:
++		ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
++				   "feature-abs-pointer", "%d", &val);
++		if (ret < 0)
++			val = 0;
++		if (val) {
++			ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
++					    "request-abs-pointer", "1");
++			if (ret)
++				printk(KERN_WARNING
++				       "xenkbd: can't request abs-pointer");
++		}
++		xenbus_switch_state(dev, XenbusStateConnected);
++		break;
++
++	case XenbusStateConnected:
++		/*
++		 * Work around xenbus race condition: If backend goes
++		 * through InitWait to Connected fast enough, we can
++		 * get Connected twice here.
++		 */
++		if (dev->state != XenbusStateConnected)
++			goto InitWait; /* no InitWait seen yet, fudge it */
++		break;
++
++	case XenbusStateClosing:
++		xenbus_frontend_closed(dev);
++		break;
++	}
++}
++
++static struct xenbus_device_id xenkbd_ids[] = {
++	{ "vkbd" },
++	{ "" }
++};
++
++static struct xenbus_driver xenkbd = {
++	.name = "vkbd",
++	.owner = THIS_MODULE,
++	.ids = xenkbd_ids,
++	.probe = xenkbd_probe,
++	.remove = xenkbd_remove,
++	.resume = xenkbd_resume,
++	.otherend_changed = xenkbd_backend_changed,
++};
++
++static int __init xenkbd_init(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	/* Nothing to do if running in dom0. */
++	if (is_initial_xendomain())
++		return -ENODEV;
++
++	return xenbus_register_frontend(&xenkbd);
++}
++
++static void __exit xenkbd_cleanup(void)
++{
++	xenbus_unregister_driver(&xenkbd);
++}
++
++module_init(xenkbd_init);
++module_exit(xenkbd_cleanup);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
+index 61e69e9..b96f318 100644
+--- a/drivers/isdn/hisax/asuscom.c
++++ b/drivers/isdn/hisax/asuscom.c
+@@ -20,8 +20,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ 
+-extern const char *CardType[];
+-
+ static const char *Asuscom_revision = "$Revision: 1.14.2.4 $";
+ 
+ #define byteout(addr,val) outb(val,addr)
+@@ -376,8 +374,7 @@ setup_asuscom(struct IsdnCard *card)
+ 	cs->irq = card->para[0];
+ 	if (!request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s config port %x-%x already in use\n",
+-		       CardType[card->typ],
++		       "HiSax: ISDNLink config port %x-%x already in use\n",
+ 		       cs->hw.asus.cfg_reg,
+ 		       cs->hw.asus.cfg_reg + bytecnt);
+ 		return (0);
+diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
+index d9028e9..eb6b432 100644
+--- a/drivers/isdn/hisax/avm_a1.c
++++ b/drivers/isdn/hisax/avm_a1.c
+@@ -16,7 +16,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ 
+-extern const char *CardType[];
+ static const char *avm_revision = "$Revision: 2.15.2.4 $";
+ 
+ #define	 AVM_A1_STAT_ISAC	0x01
+@@ -200,16 +199,14 @@ setup_avm_a1(struct IsdnCard *card)
+ 	cs->irq = card->para[0];
+ 	if (!request_region(cs->hw.avm.cfg_reg, 8, "avm cfg")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s config port %x-%x already in use\n",
+-		       CardType[card->typ],
++		       "HiSax: AVM A1 config port %x-%x already in use\n",
+ 		       cs->hw.avm.cfg_reg,
+ 		       cs->hw.avm.cfg_reg + 8);
+ 		return (0);
+ 	}
+ 	if (!request_region(cs->hw.avm.isac + 32, 32, "HiSax isac")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s isac ports %x-%x already in use\n",
+-		       CardType[cs->typ],
++		       "HiSax: AVM A1 isac ports %x-%x already in use\n",
+ 		       cs->hw.avm.isac + 32,
+ 		       cs->hw.avm.isac + 64);
+ 		release_ioregs(cs, 0);
+@@ -217,16 +214,14 @@ setup_avm_a1(struct IsdnCard *card)
+ 	}
+ 	if (!request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s isac fifo port %x already in use\n",
+-		       CardType[cs->typ],
++		       "HiSax: AVM A1 isac fifo port %x already in use\n",
+ 		       cs->hw.avm.isacfifo);
+ 		release_ioregs(cs, 1);
+ 		return (0);
+ 	}
+ 	if (!request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s hscx A ports %x-%x already in use\n",
+-		       CardType[cs->typ],
++		       "HiSax: AVM A1 hscx A ports %x-%x already in use\n",
+ 		       cs->hw.avm.hscx[0] + 32,
+ 		       cs->hw.avm.hscx[0] + 64);
+ 		release_ioregs(cs, 3);
+@@ -234,16 +229,14 @@ setup_avm_a1(struct IsdnCard *card)
+ 	}
+ 	if (!request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s hscx A fifo port %x already in use\n",
+-		       CardType[cs->typ],
++		       "HiSax: AVM A1 hscx A fifo port %x already in use\n",
+ 		       cs->hw.avm.hscxfifo[0]);
+ 		release_ioregs(cs, 7);
+ 		return (0);
+ 	}
+ 	if (!request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s hscx B ports %x-%x already in use\n",
+-		       CardType[cs->typ],
++		       "HiSax: AVM A1 hscx B ports %x-%x already in use\n",
+ 		       cs->hw.avm.hscx[1] + 32,
+ 		       cs->hw.avm.hscx[1] + 64);
+ 		release_ioregs(cs, 0xf);
+@@ -251,8 +244,7 @@ setup_avm_a1(struct IsdnCard *card)
+ 	}
+ 	if (!request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s hscx B fifo port %x already in use\n",
+-		       CardType[cs->typ],
++		       "HiSax: AVM A1 hscx B fifo port %x already in use\n",
+ 		       cs->hw.avm.hscxfifo[1]);
+ 		release_ioregs(cs, 0x1f);
+ 		return (0);
+@@ -284,9 +276,8 @@ setup_avm_a1(struct IsdnCard *card)
+ 	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
+ 	       cs->hw.avm.cfg_reg, val);
+ 
+-	printk(KERN_INFO
+-	       "HiSax: %s config irq:%d cfg:0x%X\n",
+-	       CardType[cs->typ], cs->irq,
++	printk(KERN_INFO "HiSax: AVM A1 config irq:%d cfg:0x%X\n",
++	       cs->irq,
+ 	       cs->hw.avm.cfg_reg);
+ 	printk(KERN_INFO
+ 	       "HiSax: isac:0x%X/0x%X\n",
+diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
+index 3d1bdc8..9ca2ee5 100644
+--- a/drivers/isdn/hisax/bkm_a4t.c
++++ b/drivers/isdn/hisax/bkm_a4t.c
+@@ -20,8 +20,6 @@
+ #include <linux/pci.h>
+ #include "bkm_ax.h"
+ 
+-extern const char *CardType[];
+-
+ static const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
+ 
+ 
+@@ -284,15 +282,16 @@ static int __devinit a4t_cs_init(struct IsdnCard *card,
+ 	I20_REGISTER_FILE *pI20_Regs;
+ 
+ 	if (!cs->irq) {		/* IRQ range check ?? */
+-		printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
++		printk(KERN_WARNING "HiSax: Telekom A4T: No IRQ\n");
+ 		return (0);
+ 	}
+ 	cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096);
+ 	/* Check suspecious address */
+ 	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+ 	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
+-		printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
+-		       CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
++		printk(KERN_WARNING "HiSax: Telekom A4T address "
++		       "%lx-%lx suspicious\n",
++		       cs->hw.ax.base, cs->hw.ax.base + 4096);
+ 		iounmap((void *) cs->hw.ax.base);
+ 		cs->hw.ax.base = 0;
+ 		return (0);
+@@ -302,8 +301,9 @@ static int __devinit a4t_cs_init(struct IsdnCard *card,
+ 	cs->hw.ax.isac_ale = GCS_1;
+ 	cs->hw.ax.jade_ale = GCS_3;
+ 
+-	printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
+-	       CardType[card->typ], cs->hw.ax.base, cs->irq);
++	printk(KERN_INFO "HiSax: Telekom A4T: Card configured at "
++	       "0x%lX IRQ %d\n",
++	       cs->hw.ax.base, cs->irq);
+ 
+ 	setup_isac(cs);
+ 	cs->readisac = &ReadISAC;
+@@ -349,11 +349,12 @@ setup_bkm_a4t(struct IsdnCard *card)
+ 			break;
+ 	}
+ 	if (!found) {
+-		printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
++		printk(KERN_WARNING "HiSax: Telekom A4T: Card not found\n");
+ 		return (0);
+ 	}
+ 	if (!pci_memaddr) {
+-		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
++		printk(KERN_WARNING "HiSax: Telekom A4T: "
++		       "No Memory base address\n");
+ 		return (0);
+ 	}
+ 
+diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
+index 99ef3b4..e1ff471 100644
+--- a/drivers/isdn/hisax/bkm_a8.c
++++ b/drivers/isdn/hisax/bkm_a8.c
+@@ -22,8 +22,6 @@
+ 
+ #define	ATTEMPT_PCI_REMAPPING	/* Required for PLX rev 1 */
+ 
+-extern const char *CardType[];
+-
+ static const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $";
+ 
+ static const char *sct_quadro_subtypes[] =
+@@ -181,8 +179,7 @@ bkm_interrupt_ipac(int intno, void *dev_id)
+ 		goto Start_IPAC;
+ 	}
+ 	if (!icnt)
+-		printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n",
+-		       CardType[cs->typ],
++		printk(KERN_WARNING "HiSax: Scitel Quadro (%s) IRQ LOOP\n",
+ 		       sct_quadro_subtypes[cs->subtyp]);
+ 	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF);
+ 	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0);
+@@ -296,8 +293,8 @@ setup_sct_quadro(struct IsdnCard *card)
+ 	if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4)
+ 		cs->subtyp = card->para[0];
+ 	else {
+-		printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n",
+-			CardType[card->typ]);
++		printk(KERN_WARNING "HiSax: Scitel Quadro: Invalid "
++		       "subcontroller in configuration, default to 1\n");
+ 		return (0);
+ 	}
+ 	if ((cs->subtyp != SCT_1) && ((sub_sys_id != PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) ||
+@@ -322,16 +319,16 @@ setup_sct_quadro(struct IsdnCard *card)
+ 			}
+ 		}
+ 		if (!found) {
+-			printk(KERN_WARNING "HiSax: %s (%s): Card not found\n",
+-				CardType[card->typ],
++			printk(KERN_WARNING "HiSax: Scitel Quadro (%s): "
++				"Card not found\n",
+ 				sct_quadro_subtypes[cs->subtyp]);
+ 			return (0);
+ 		}
+ #ifdef ATTEMPT_PCI_REMAPPING
+ /* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
+ 		if ((pci_ioaddr1 & 0x80) && (dev_a8->revision == 1)) {
+-			printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
+-				CardType[card->typ],
++			printk(KERN_WARNING "HiSax: Scitel Quadro (%s): "
++				"PLX rev 1, remapping required!\n",
+ 				sct_quadro_subtypes[cs->subtyp]);
+ 			/* Restart PCI negotiation */
+ 			pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, (u_int) - 1);
+@@ -344,8 +341,7 @@ setup_sct_quadro(struct IsdnCard *card)
+ #endif /* End HACK */
+ 	}
+ 	if (!pci_irq) {		/* IRQ range check ?? */
+-		printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n",
+-		       CardType[card->typ],
++		printk(KERN_WARNING "HiSax: Scitel Quadro (%s): No IRQ\n",
+ 		       sct_quadro_subtypes[cs->subtyp]);
+ 		return (0);
+ 	}
+@@ -355,8 +351,8 @@ setup_sct_quadro(struct IsdnCard *card)
+ 	pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_4, &pci_ioaddr4);
+ 	pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_5, &pci_ioaddr5);
+ 	if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) {
+-		printk(KERN_WARNING "HiSax: %s (%s): No IO base address(es)\n",
+-		       CardType[card->typ],
++		printk(KERN_WARNING "HiSax: Scitel Quadro (%s): "
++		       "No IO base address(es)\n",
+ 		       sct_quadro_subtypes[cs->subtyp]);
+ 		return (0);
+ 	}
+@@ -411,8 +407,8 @@ setup_sct_quadro(struct IsdnCard *card)
+ 	/* For isac and hscx data path */
+ 	cs->hw.ax.data_adr = cs->hw.ax.base + 4;
+ 
+-	printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n",
+-	       CardType[card->typ],
++	printk(KERN_INFO "HiSax: Scitel Quadro (%s) configured at "
++	       "0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n",
+ 	       sct_quadro_subtypes[cs->subtyp],
+ 	       cs->hw.ax.plx_adr,
+ 	       cs->hw.ax.base,
+@@ -432,8 +428,7 @@ setup_sct_quadro(struct IsdnCard *card)
+ 	cs->cardmsg = &BKM_card_msg;
+ 	cs->irq_func = &bkm_interrupt_ipac;
+ 
+-	printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n",
+-		CardType[card->typ],
++	printk(KERN_INFO "HiSax: Scitel Quadro (%s): IPAC Version %d\n",
+ 		sct_quadro_subtypes[cs->subtyp],
+ 		readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID));
+ 	return (1);
+diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
+index a0ee43c..84d75a3 100644
+--- a/drivers/isdn/hisax/config.c
++++ b/drivers/isdn/hisax/config.c
+@@ -1169,7 +1169,9 @@ outf_cs:
+ /* Used from an exported function but calls __devinit functions.
+  * Tell modpost not to warn (__ref)
+  */
+-static int __ref checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
++static int __ref checkcard(int cardnr, char *id, int *busy_flag,
++			   struct module *lockowner,
++			   hisax_setup_func_t card_setup)
+ {
+ 	int ret;
+ 	struct IsdnCard *card = cards + cardnr;
+@@ -1187,7 +1189,7 @@ static int __ref checkcard(int cardnr, char *id, int *busy_flag, struct module *
+ 	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
+ 	       "NONE", cs->iif.id, cs->myid);
+ 
+-	ret = hisax_cs_setup_card(card);
++	ret = card_setup(card);
+ 	if (!ret) {
+ 		ll_unload(cs);
+ 		goto outf_cs;
+@@ -1241,7 +1243,8 @@ static int HiSax_inithardware(int *busy_flag)
+ 			else
+ 				sprintf(ids, "%s%d", id, i);
+ 		}
+-		if (checkcard(i, ids, busy_flag, THIS_MODULE)) {
++		if (checkcard(i, ids, busy_flag, THIS_MODULE,
++			      hisax_cs_setup_card)) {
+ 			foundcards++;
+ 			i++;
+ 		} else {
+@@ -1549,7 +1552,8 @@ int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
+ 		sprintf(ids, "HiSax%d", nrcards);
+ 	else
+ 		sprintf(ids, "HiSax");
+-	if (!checkcard(nrcards, ids, busy_flag, THIS_MODULE))
++	if (!checkcard(nrcards, ids, busy_flag, THIS_MODULE,
++		       hisax_cs_setup_card))
+ 		goto error;
+ 
+ 	ret = nrcards;
+@@ -1595,7 +1599,7 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
+ 	cards[i].protocol = protocol;
+ 	sprintf(id, "%s%d", name, i);
+ 	nrcards++;
+-	retval = checkcard(i, id, NULL, hisax_d_if->owner);
++	retval = checkcard(i, id, NULL, hisax_d_if->owner, hisax_cs_setup_card);
+ 	if (retval == 0) { // yuck
+ 		cards[i].typ = 0;
+ 		nrcards--;
+diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
+index d272d8c..2c3691f 100644
+--- a/drivers/isdn/hisax/elsa.c
++++ b/drivers/isdn/hisax/elsa.c
+@@ -299,7 +299,7 @@ elsa_interrupt(int intno, void *dev_id)
+ 		val = serial_inp(cs, UART_IIR);
+ 		if (!(val & UART_IIR_NO_INT)) {
+ 			debugl1(cs,"IIR %02x", val);
+-			rs_interrupt_elsa(intno, cs);
++			rs_interrupt_elsa(cs);
+ 		}
+ 	}
+ #endif
+@@ -379,7 +379,7 @@ elsa_interrupt_ipac(int intno, void *dev_id)
+ 		val = serial_inp(cs, UART_IIR);
+ 		if (!(val & UART_IIR_NO_INT)) {
+ 			debugl1(cs,"IIR %02x", val);
+-			rs_interrupt_elsa(intno, cs);
++			rs_interrupt_elsa(cs);
+ 		}
+ 	}
+ #endif
+diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
+index 1642dca..f181db4 100644
+--- a/drivers/isdn/hisax/elsa_ser.c
++++ b/drivers/isdn/hisax/elsa_ser.c
+@@ -384,13 +384,13 @@ static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
+ }
+ 
+ 
+-static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
++static void rs_interrupt_elsa(struct IsdnCardState *cs)
+ {
+ 	int status, iir, msr;
+ 	int pass_counter = 0;
+ 	
+ #ifdef SERIAL_DEBUG_INTR
+-	printk("rs_interrupt_single(%d)...", irq);
++	printk(KERN_DEBUG "rs_interrupt_single(%d)...", cs->irq);
+ #endif
+ 
+ 	do {
+diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
+index f66620a..0ea3b46 100644
+--- a/drivers/isdn/hisax/gazel.c
++++ b/drivers/isdn/hisax/gazel.c
+@@ -19,7 +19,6 @@
+ #include "ipac.h"
+ #include <linux/pci.h>
+ 
+-extern const char *CardType[];
+ static const char *gazel_revision = "$Revision: 2.19.2.4 $";
+ 
+ #define R647      1
+@@ -479,8 +478,8 @@ reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
+ 	return 0;
+ 
+       error:
+-	printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n",
+-	       CardType[cs->typ], adr, adr + len);
++	printk(KERN_WARNING "Gazel: io ports 0x%x-0x%x already in use\n",
++	       adr, adr + len);
+ 	return 1;
+ }
+ 
+diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
+index fba8b62..f126566 100644
+--- a/drivers/isdn/hisax/hfc_pci.c
++++ b/drivers/isdn/hisax/hfc_pci.c
+@@ -22,8 +22,6 @@
+ #include <linux/pci.h>
+ #include <linux/interrupt.h>
+ 
+-extern const char *CardType[];
+-
+ static const char *hfcpci_revision = "$Revision: 1.48.2.4 $";
+ 
+ /* table entry in the PCI devices list */
+diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
+index 05482d2..f4a2138 100644
+--- a/drivers/isdn/hisax/hfc_sx.c
++++ b/drivers/isdn/hisax/hfc_sx.c
+@@ -18,8 +18,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/isapnp.h>
+ 
+-extern const char *CardType[];
+-
+ static const char *hfcsx_revision = "$Revision: 1.12.2.5 $";
+ 
+ /***************************************/
+diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
+index 34733c9..e8d429f 100644
+--- a/drivers/isdn/hisax/hisax.h
++++ b/drivers/isdn/hisax/hisax.h
+@@ -925,7 +925,7 @@ struct IsdnCardState {
+ 	int		(*cardmsg) (struct IsdnCardState *, int, void *);
+ 	void		(*setstack_d) (struct PStack *, struct IsdnCardState *);
+ 	void		(*DC_Close) (struct IsdnCardState *);
+-	int		(*irq_func) (int, void *);
++	irq_handler_t	irq_func;
+ 	int		(*auxcmd) (struct IsdnCardState *, isdn_ctrl *);
+ 	struct Channel	channel[2+MAX_WAITING_CALLS];
+ 	struct BCState	bcs[2+MAX_WAITING_CALLS];
+diff --git a/drivers/isdn/hisax/hisax_cfg.h b/drivers/isdn/hisax/hisax_cfg.h
+index ca3fe62..17a2fea 100644
+--- a/drivers/isdn/hisax/hisax_cfg.h
++++ b/drivers/isdn/hisax/hisax_cfg.h
+@@ -60,5 +60,7 @@ struct IsdnCard {
+ 	IsdnCardState_t	*cs;
+ };
+ 
++typedef int (*hisax_setup_func_t)(struct IsdnCard *card);
++
+ extern void	HiSax_closecard(int);
+ extern int	hisax_init_pcmcia(void *, int *, IsdnCard_t *);
+diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
+index 55de069..ca41617 100644
+--- a/drivers/isdn/hisax/isurf.c
++++ b/drivers/isdn/hisax/isurf.c
+@@ -17,8 +17,6 @@
+ #include "isdnl1.h"
+ #include <linux/isapnp.h>
+ 
+-extern const char *CardType[];
+-
+ static const char *ISurf_revision = "$Revision: 1.12.2.4 $";
+ 
+ #define byteout(addr,val) outb(val,addr)
+@@ -251,22 +249,19 @@ setup_isurf(struct IsdnCard *card)
+ 			return(0);
+ 		}
+ #else
+-		printk(KERN_WARNING "HiSax: %s port/mem not set\n",
+-			CardType[card->typ]);
++		printk(KERN_WARNING "HiSax: Siemens I-Surf port/mem not set\n");
+ 		return (0);
+ #endif
+ 	}
+ 	if (!request_region(cs->hw.isurf.reset, 1, "isurf isdn")) {
+ 		printk(KERN_WARNING
+-			"HiSax: %s config port %x already in use\n",
+-			CardType[card->typ],
++			"HiSax: Siemens I-Surf config port %x already in use\n",
+ 			cs->hw.isurf.reset);
+ 			return (0);
+ 	}
+ 	if (!request_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE, "isurf iomem")) {
+-		printk(KERN_WARNING
+-			"HiSax: %s memory region %lx-%lx already in use\n",
+-			CardType[card->typ],
++		printk(KERN_WARNING "HiSax: Siemens I-Surf memory region "
++			"%lx-%lx already in use\n",
+ 			cs->hw.isurf.phymem,
+ 			cs->hw.isurf.phymem + ISURF_IOMEM_SIZE);
+ 		release_region(cs->hw.isurf.reset, 1);
+diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
+index 252d79d..2d18d4f 100644
+--- a/drivers/isdn/hisax/ix1_micro.c
++++ b/drivers/isdn/hisax/ix1_micro.c
+@@ -24,7 +24,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ 
+-extern const char *CardType[];
+ static const char *ix1_revision = "$Revision: 2.12.2.4 $";
+ 
+ #define byteout(addr,val) outb(val,addr)
+@@ -288,15 +287,15 @@ setup_ix1micro(struct IsdnCard *card)
+ 	if (cs->hw.ix1.cfg_reg) {
+ 		if (!request_region(cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) {
+ 			printk(KERN_WARNING
+-			  "HiSax: %s config port %x-%x already in use\n",
+-			       CardType[card->typ],
++			  "HiSax: ITK ix1-micro Rev.2 config port "
++			  "%x-%x already in use\n",
+ 			       cs->hw.ix1.cfg_reg,
+ 			       cs->hw.ix1.cfg_reg + 4);
+ 			return (0);
+ 		}
+ 	}
+-	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+-		CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
++	printk(KERN_INFO "HiSax: ITK ix1-micro Rev.2 config irq:%d io:0x%X\n",
++		cs->irq, cs->hw.ix1.cfg_reg);
+ 	setup_isac(cs);
+ 	cs->readisac = &ReadISAC;
+ 	cs->writeisac = &WriteISAC;
+diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
+index a81d175..2539430 100644
+--- a/drivers/isdn/hisax/mic.c
++++ b/drivers/isdn/hisax/mic.c
+@@ -16,8 +16,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ 
+-extern const char *CardType[];
+-
+ static const char *mic_revision = "$Revision: 1.12.2.4 $";
+ 
+ #define byteout(addr,val) outb(val,addr)
+@@ -210,8 +208,7 @@ setup_mic(struct IsdnCard *card)
+ 
+ 	if (!request_region(cs->hw.mic.cfg_reg, bytecnt, "mic isdn")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s config port %x-%x already in use\n",
+-		       CardType[card->typ],
++		       "HiSax: ith mic config port %x-%x already in use\n",
+ 		       cs->hw.mic.cfg_reg,
+ 		       cs->hw.mic.cfg_reg + bytecnt);
+ 		return (0);
+diff --git a/drivers/isdn/hisax/netjet.h b/drivers/isdn/hisax/netjet.h
+index 4d89d3e..68e504d 100644
+--- a/drivers/isdn/hisax/netjet.h
++++ b/drivers/isdn/hisax/netjet.h
+@@ -12,8 +12,6 @@
+  *
+  */
+ 
+-extern const char *CardType[];
+-
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+ 
+diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
+index bd99211..421b8e6 100644
+--- a/drivers/isdn/hisax/niccy.c
++++ b/drivers/isdn/hisax/niccy.c
+@@ -21,7 +21,6 @@
+ #include <linux/pci.h>
+ #include <linux/isapnp.h>
+ 
+-extern const char *CardType[];
+ static const char *niccy_revision = "$Revision: 1.21.2.4 $";
+ 
+ #define byteout(addr,val) outb(val,addr)
+@@ -284,14 +283,14 @@ int __devinit setup_niccy(struct IsdnCard *card)
+ 		cs->subtyp = NICCY_PNP;
+ 		cs->irq = card->para[0];
+ 		if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) {
+-			printk(KERN_WARNING "HiSax: %s data port %x-%x "
+-				"already in use\n", CardType[card->typ],
++			printk(KERN_WARNING "HiSax: NICCY data port %x-%x "
++				"already in use\n",
+ 				cs->hw.niccy.isac, cs->hw.niccy.isac + 1);
+ 			return 0;
+ 		}
+ 		if (!request_region(cs->hw.niccy.isac_ale, 2, "niccy addr")) {
+-			printk(KERN_WARNING "HiSax: %s address port %x-%x "
+-				"already in use\n", CardType[card->typ],
++			printk(KERN_WARNING "HiSax: NICCY address port %x-%x "
++				"already in use\n",
+ 				cs->hw.niccy.isac_ale,
+ 				cs->hw.niccy.isac_ale + 1);
+ 			release_region(cs->hw.niccy.isac, 2);
+@@ -339,15 +338,13 @@ int __devinit setup_niccy(struct IsdnCard *card)
+ 		cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
+ 		if (!request_region(cs->hw.niccy.isac, 4, "niccy")) {
+ 			printk(KERN_WARNING
+-			       "HiSax: %s data port %x-%x already in use\n",
+-			       CardType[card->typ],
++			       "HiSax: NICCY data port %x-%x already in use\n",
+ 			       cs->hw.niccy.isac, cs->hw.niccy.isac + 4);
+ 			return 0;
+ 		}
+ 		if (!request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) {
+ 			printk(KERN_WARNING
+-			       "HiSax: %s pci port %x-%x already in use\n",
+-			       CardType[card->typ],
++			       "HiSax: NICCY pci port %x-%x already in use\n",
+ 			       cs->hw.niccy.cfg_reg,
+ 			       cs->hw.niccy.cfg_reg + 0x40);
+ 			release_region(cs->hw.niccy.isac, 4);
+@@ -359,8 +356,8 @@ int __devinit setup_niccy(struct IsdnCard *card)
+ 		return 0;
+ #endif				/* CONFIG_PCI_LEGACY */
+ 	}
+-	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
+-		CardType[cs->typ], (cs->subtyp == 1) ? "PnP" : "PCI",
++	printk(KERN_INFO "HiSax: NICCY %s config irq:%d data:0x%X ale:0x%X\n",
++		(cs->subtyp == 1) ? "PnP" : "PCI",
+ 		cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
+ 	setup_isac(cs);
+ 	cs->readisac = &ReadISAC;
+diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
+index a895dfe..8d36ccc 100644
+--- a/drivers/isdn/hisax/nj_s.c
++++ b/drivers/isdn/hisax/nj_s.c
+@@ -235,8 +235,7 @@ static int __devinit njs_cs_init_rest(struct IsdnCard *card,
+ 		cs->subtyp ? "TJ320" : "TJ300", cs->hw.njet.base, cs->irq);
+ 	if (!request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s config port %#lx-%#lx already in use\n",
+-		       CardType[card->typ],
++		       "HiSax: NETjet-S config port %#lx-%#lx already in use\n",
+ 		       cs->hw.njet.base,
+ 		       cs->hw.njet.base + bytecnt);
+ 		return (0);
+diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
+index f017d38..d306c94 100644
+--- a/drivers/isdn/hisax/nj_u.c
++++ b/drivers/isdn/hisax/nj_u.c
+@@ -197,8 +197,8 @@ static int __devinit nju_cs_init_rest(struct IsdnCard *card,
+ 		cs->hw.njet.base, cs->irq);
+ 	if (!request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s config port %#lx-%#lx already in use\n",
+-		       CardType[card->typ],
++		       "HiSax: NETspider-U config port %#lx-%#lx "
++		       "already in use\n",
+ 		       cs->hw.njet.base,
+ 		       cs->hw.njet.base + bytecnt);
+ 		return (0);
+diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
+index 150ef68..16d00b5 100644
+--- a/drivers/isdn/hisax/s0box.c
++++ b/drivers/isdn/hisax/s0box.c
+@@ -16,7 +16,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ 
+-extern const char *CardType[];
+ static const char *s0box_revision = "$Revision: 2.6.2.4 $";
+ 
+ static inline void
+@@ -231,19 +230,15 @@ setup_s0box(struct IsdnCard *card)
+ 	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
+ 	cs->irq = card->para[0];
+ 	if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) {
+-		printk(KERN_WARNING
+-		       "HiSax: %s ports %x-%x already in use\n",
+-		       CardType[cs->typ],
++		printk(KERN_WARNING "HiSax: S0Box ports %x-%x already in use\n",
+                        cs->hw.teles3.cfg_reg,
+                        cs->hw.teles3.cfg_reg + 7);
+ 		return 0;
+ 	}
+-	printk(KERN_INFO
+-		"HiSax: %s config irq:%d isac:0x%x  cfg:0x%x\n",
+-		CardType[cs->typ], cs->irq,
++	printk(KERN_INFO "HiSax: S0Box config irq:%d isac:0x%x  cfg:0x%x\n",
++		cs->irq,
+ 		cs->hw.teles3.isac, cs->hw.teles3.cfg_reg);
+-	printk(KERN_INFO
+-		"HiSax: hscx A:0x%x  hscx B:0x%x\n",
++	printk(KERN_INFO "HiSax: hscx A:0x%x  hscx B:0x%x\n",
+ 		cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
+ 	setup_isac(cs);
+ 	cs->readisac = &ReadISAC;
+diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
+index c99b166..b34a81d 100644
+--- a/drivers/isdn/hisax/saphir.c
++++ b/drivers/isdn/hisax/saphir.c
+@@ -18,7 +18,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ 
+-extern const char *CardType[];
+ static char *saphir_rev = "$Revision: 1.10.2.4 $";
+ 
+ #define byteout(addr,val) outb(val,addr)
+@@ -260,15 +259,14 @@ setup_saphir(struct IsdnCard *card)
+ 	cs->irq = card->para[0];
+ 	if (!request_region(cs->hw.saphir.cfg_reg, 6, "saphir")) {
+ 		printk(KERN_WARNING
+-			"HiSax: %s config port %x-%x already in use\n",
+-			CardType[card->typ],
++			"HiSax: HST Saphir config port %x-%x already in use\n",
+ 			cs->hw.saphir.cfg_reg,
+ 			cs->hw.saphir.cfg_reg + 5);
+ 		return (0);
+ 	}
+ 
+-	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+-		CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
++	printk(KERN_INFO "HiSax: HST Saphir config irq:%d io:0x%X\n",
++	       cs->irq, cs->hw.saphir.cfg_reg);
+ 
+ 	setup_isac(cs);
+ 	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
+diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
+index 0220950..0a53759 100644
+--- a/drivers/isdn/hisax/sportster.c
++++ b/drivers/isdn/hisax/sportster.c
+@@ -18,7 +18,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ 
+-extern const char *CardType[];
+ static const char *sportster_revision = "$Revision: 1.16.2.4 $";
+ 
+ #define byteout(addr,val) outb(val,addr)
+@@ -192,9 +191,9 @@ get_io_range(struct IsdnCardState *cs)
+ 	for (i=0;i<64;i++) {
+ 		adr = cs->hw.spt.cfg_reg + i *1024;
+ 		if (!request_region(adr, 8, "sportster")) {
+-			printk(KERN_WARNING
+-				"HiSax: %s config port %x-%x already in use\n",
+-				CardType[cs->typ], adr, adr + 8);
++			printk(KERN_WARNING "HiSax: USR Sportster config port "
++				"%x-%x already in use\n",
++				adr, adr + 8);
+ 			break;
+ 		} 
+ 	}
+@@ -247,8 +246,8 @@ setup_sportster(struct IsdnCard *card)
+ 			printk(KERN_WARNING "Sportster: wrong IRQ\n");
+ 			return(0);
+ 	}
+-	printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
+-		CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg);
++	printk(KERN_INFO "HiSax: USR Sportster config irq:%d cfg:0x%X\n",
++		cs->irq, cs->hw.spt.cfg_reg);
+ 	setup_isac(cs);
+ 	cs->readisac = &ReadISAC;
+ 	cs->writeisac = &WriteISAC;
+diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
+index 0909662..b0ce4ae 100644
+--- a/drivers/isdn/hisax/teleint.c
++++ b/drivers/isdn/hisax/teleint.c
+@@ -16,8 +16,6 @@
+ #include "hfc_2bs0.h"
+ #include "isdnl1.h"
+ 
+-extern const char *CardType[];
+-
+ static const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
+ 
+ #define byteout(addr,val) outb(val,addr)
+@@ -286,8 +284,7 @@ setup_TeleInt(struct IsdnCard *card)
+ 	init_timer(&cs->hw.hfc.timer);
+ 	if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) {
+ 		printk(KERN_WARNING
+-		       "HiSax: %s config port %x-%x already in use\n",
+-		       CardType[card->typ],
++		       "HiSax: TeleInt config port %x-%x already in use\n",
+ 		       cs->hw.hfc.addr,
+ 		       cs->hw.hfc.addr + 2);
+ 		return (0);
+diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
+index 4393003..28b08de 100644
+--- a/drivers/isdn/hisax/telespci.c
++++ b/drivers/isdn/hisax/telespci.c
+@@ -19,7 +19,6 @@
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+ 
+-extern const char *CardType[];
+ static const char *telespci_revision = "$Revision: 2.23.2.3 $";
+ 
+ #define ZORAN_PO_RQ_PEN	0x02000000
+@@ -329,8 +328,8 @@ setup_telespci(struct IsdnCard *card)
+ 	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
+ 
+ 	printk(KERN_INFO
+-	       "HiSax: %s config irq:%d mem:%p\n",
+-	       CardType[cs->typ], cs->irq,
++	       "HiSax: Teles PCI config irq:%d mem:%p\n",
++	       cs->irq,
+ 	       cs->hw.teles0.membase);
+ 
+ 	setup_isac(cs);
+diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
+index 39129b9..bb1c8dd 100644
+--- a/drivers/isdn/hisax/w6692.c
++++ b/drivers/isdn/hisax/w6692.c
+@@ -38,8 +38,6 @@ static const PCI_ENTRY id_list[] =
+ #define W6692_DYNALINK 1
+ #define W6692_USR      2
+ 
+-extern const char *CardType[];
+-
+ static const char *w6692_revision = "$Revision: 1.18.2.4 $";
+ 
+ #define DBUSY_TIMER_VALUE 80
+diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
+index 859814f..86a369b 100644
+--- a/drivers/leds/Kconfig
++++ b/drivers/leds/Kconfig
+@@ -1,6 +1,5 @@
+ menuconfig NEW_LEDS
+ 	bool "LED Support"
+-	depends on HAS_IOMEM
+ 	help
+ 	  Say Y to enable Linux LED support.  This allows control of supported
+ 	  LEDs from both userspace and optionally, by kernel events (triggers).
+@@ -46,13 +45,6 @@ config LEDS_SPITZ
+ 	  This option enables support for the LEDs on Sharp Zaurus
+ 	  SL-Cxx00 series (C1000, C3000, C3100).
+ 
+-config LEDS_TOSA
+-	tristate "LED Support for the Sharp SL-6000 series"
+-	depends on LEDS_CLASS && PXA_SHARPSL
+-	help
+-	  This option enables support for the LEDs on Sharp Zaurus
+-	  SL-6000 series.
+-
+ config LEDS_S3C24XX
+ 	tristate "LED Support for Samsung S3C24XX GPIO LEDs"
+ 	depends on LEDS_CLASS && ARCH_S3C2410
+@@ -73,6 +65,12 @@ config LEDS_NET48XX
+ 	  This option enables support for the Soekris net4801 and net4826 error
+ 	  LED.
+ 
++config LEDS_FSG
++	tristate "LED Support for the Freecom FSG-3"
++	depends on LEDS_CLASS && MACH_FSG
++	help
++	  This option enables support for the LEDs on the Freecom FSG-3.
++
+ config LEDS_WRAP
+ 	tristate "LED Support for the WRAP series LEDs"
+ 	depends on LEDS_CLASS && SCx200_GPIO
+@@ -135,6 +133,7 @@ config LEDS_CLEVO_MAIL
+ 
+ 	  This module can drive the mail LED for the following notebooks:
+ 
++	  	Clevo D400P
+ 	  	Clevo D410J
+ 	  	Clevo D410V
+ 	  	Clevo D400V/D470V (not tested, but might work)
+@@ -142,6 +141,9 @@ config LEDS_CLEVO_MAIL
+ 	  	Clevo M5x0N (not tested, but might work)
+ 	  	Positivo Mobile (Clevo M5x0V)
+ 
++	  If your model is not listed here you can try the "nodetect"
++	  module paramter.
++
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called leds-clevo-mail.
+ 
+@@ -181,4 +183,11 @@ config LEDS_TRIGGER_HEARTBEAT
+ 	  load average.
+ 	  If unsure, say Y.
+ 
++config LEDS_TRIGGER_DEFAULT_ON
++	tristate "LED Default ON Trigger"
++	depends on LEDS_TRIGGERS
++	help
++	  This allows LEDs to be initialised in the ON state.
++	  If unsure, say Y.
++
+ endif # NEW_LEDS
+diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
+index 84ced3b..973d626 100644
+--- a/drivers/leds/Makefile
++++ b/drivers/leds/Makefile
+@@ -9,7 +9,6 @@ obj-$(CONFIG_LEDS_ATMEL_PWM)		+= leds-atmel-pwm.o
+ obj-$(CONFIG_LEDS_CORGI)		+= leds-corgi.o
+ obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
+ obj-$(CONFIG_LEDS_SPITZ)		+= leds-spitz.o
+-obj-$(CONFIG_LEDS_TOSA)			+= leds-tosa.o
+ obj-$(CONFIG_LEDS_S3C24XX)		+= leds-s3c24xx.o
+ obj-$(CONFIG_LEDS_AMS_DELTA)		+= leds-ams-delta.o
+ obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o
+@@ -21,8 +20,10 @@ obj-$(CONFIG_LEDS_GPIO)			+= leds-gpio.o
+ obj-$(CONFIG_LEDS_CM_X270)              += leds-cm-x270.o
+ obj-$(CONFIG_LEDS_CLEVO_MAIL)		+= leds-clevo-mail.o
+ obj-$(CONFIG_LEDS_HP6XX)		+= leds-hp6xx.o
++obj-$(CONFIG_LEDS_FSG)			+= leds-fsg.o
+ 
+ # LED Triggers
+ obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o
+ obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)	+= ledtrig-ide-disk.o
+ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+= ledtrig-heartbeat.o
++obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
+diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
+index 4a93878..ac05a92 100644
+--- a/drivers/leds/led-class.c
++++ b/drivers/leds/led-class.c
+@@ -24,6 +24,12 @@
+ 
+ static struct class *leds_class;
+ 
++static void led_update_brightness(struct led_classdev *led_cdev)
++{
++	if (led_cdev->brightness_get)
++		led_cdev->brightness = led_cdev->brightness_get(led_cdev);
++}
++
+ static ssize_t led_brightness_show(struct device *dev, 
+ 		struct device_attribute *attr, char *buf)
+ {
+@@ -31,6 +37,7 @@ static ssize_t led_brightness_show(struct device *dev,
+ 	ssize_t ret = 0;
+ 
+ 	/* no lock needed for this */
++	led_update_brightness(led_cdev);
+ 	sprintf(buf, "%u\n", led_cdev->brightness);
+ 	ret = strlen(buf) + 1;
+ 
+@@ -51,6 +58,9 @@ static ssize_t led_brightness_store(struct device *dev,
+ 
+ 	if (count == size) {
+ 		ret = count;
++
++		if (state == LED_OFF)
++			led_trigger_remove(led_cdev);
+ 		led_set_brightness(led_cdev, state);
+ 	}
+ 
+@@ -110,6 +120,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
+ 	list_add_tail(&led_cdev->node, &leds_list);
+ 	up_write(&leds_list_lock);
+ 
++	led_update_brightness(led_cdev);
++
+ #ifdef CONFIG_LEDS_TRIGGERS
+ 	init_rwsem(&led_cdev->trigger_lock);
+ 
+@@ -139,12 +151,10 @@ EXPORT_SYMBOL_GPL(led_classdev_register);
+ /**
+  * __led_classdev_unregister - unregisters a object of led_properties class.
+  * @led_cdev: the led device to unregister
+- * @suspended: indicates whether system-wide suspend or resume is in progress
+  *
+  * Unregisters a previously registered via led_classdev_register object.
+  */
+-void __led_classdev_unregister(struct led_classdev *led_cdev,
+-				      bool suspended)
++void led_classdev_unregister(struct led_classdev *led_cdev)
+ {
+ 	device_remove_file(led_cdev->dev, &dev_attr_brightness);
+ #ifdef CONFIG_LEDS_TRIGGERS
+@@ -155,16 +165,13 @@ void __led_classdev_unregister(struct led_classdev *led_cdev,
+ 	up_write(&led_cdev->trigger_lock);
+ #endif
+ 
+-	if (suspended)
+-		device_pm_schedule_removal(led_cdev->dev);
+-	else
+-		device_unregister(led_cdev->dev);
++	device_unregister(led_cdev->dev);
+ 
+ 	down_write(&leds_list_lock);
+ 	list_del(&led_cdev->node);
+ 	up_write(&leds_list_lock);
+ }
+-EXPORT_SYMBOL_GPL(__led_classdev_unregister);
++EXPORT_SYMBOL_GPL(led_classdev_unregister);
+ 
+ static int __init leds_init(void)
+ {
+diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
+index 5d1ca10..016d19f 100644
+--- a/drivers/leds/led-core.c
++++ b/drivers/leds/led-core.c
+@@ -19,7 +19,7 @@
+ #include "leds.h"
+ 
+ DECLARE_RWSEM(leds_list_lock);
+-LIST_HEAD(leds_list);
++EXPORT_SYMBOL_GPL(leds_list_lock);
+ 
++LIST_HEAD(leds_list);
+ EXPORT_SYMBOL_GPL(leds_list);
+-EXPORT_SYMBOL_GPL(leds_list_lock);
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index 13c9026..0f242b3 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -29,6 +29,8 @@
+ static DECLARE_RWSEM(triggers_list_lock);
+ static LIST_HEAD(trigger_list);
+ 
++ /* Used by LED Class */
++
+ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+ 		const char *buf, size_t count)
+ {
+@@ -45,9 +47,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+ 		trigger_name[len - 1] = '\0';
+ 
+ 	if (!strcmp(trigger_name, "none")) {
+-		down_write(&led_cdev->trigger_lock);
+-		led_trigger_set(led_cdev, NULL);
+-		up_write(&led_cdev->trigger_lock);
++		led_trigger_remove(led_cdev);
+ 		return count;
+ 	}
+ 
+@@ -66,7 +66,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+ 
+ 	return -EINVAL;
+ }
+-
++EXPORT_SYMBOL_GPL(led_trigger_store);
+ 
+ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
+ 		char *buf)
+@@ -96,24 +96,7 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
+ 	len += sprintf(len+buf, "\n");
+ 	return len;
+ }
+-
+-void led_trigger_event(struct led_trigger *trigger,
+-			enum led_brightness brightness)
+-{
+-	struct list_head *entry;
+-
+-	if (!trigger)
+-		return;
+-
+-	read_lock(&trigger->leddev_list_lock);
+-	list_for_each(entry, &trigger->led_cdevs) {
+-		struct led_classdev *led_cdev;
+-
+-		led_cdev = list_entry(entry, struct led_classdev, trig_list);
+-		led_set_brightness(led_cdev, brightness);
+-	}
+-	read_unlock(&trigger->leddev_list_lock);
+-}
++EXPORT_SYMBOL_GPL(led_trigger_show);
+ 
+ /* Caller must ensure led_cdev->trigger_lock held */
+ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
+@@ -124,7 +107,8 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
+ 	if (led_cdev->trigger) {
+ 		write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags);
+ 		list_del(&led_cdev->trig_list);
+-		write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
++		write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock,
++			flags);
+ 		if (led_cdev->trigger->deactivate)
+ 			led_cdev->trigger->deactivate(led_cdev);
+ 		led_set_brightness(led_cdev, LED_OFF);
+@@ -138,6 +122,15 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
+ 	}
+ 	led_cdev->trigger = trigger;
+ }
++EXPORT_SYMBOL_GPL(led_trigger_set);
++
++void led_trigger_remove(struct led_classdev *led_cdev)
++{
++	down_write(&led_cdev->trigger_lock);
++	led_trigger_set(led_cdev, NULL);
++	up_write(&led_cdev->trigger_lock);
++}
++EXPORT_SYMBOL_GPL(led_trigger_remove);
+ 
+ void led_trigger_set_default(struct led_classdev *led_cdev)
+ {
+@@ -155,6 +148,9 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
+ 	up_write(&led_cdev->trigger_lock);
+ 	up_read(&triggers_list_lock);
+ }
++EXPORT_SYMBOL_GPL(led_trigger_set_default);
++
++/* LED Trigger Interface */
+ 
+ int led_trigger_register(struct led_trigger *trigger)
+ {
+@@ -181,26 +177,7 @@ int led_trigger_register(struct led_trigger *trigger)
+ 
+ 	return 0;
+ }
+-
+-void led_trigger_register_simple(const char *name, struct led_trigger **tp)
+-{
+-	struct led_trigger *trigger;
+-	int err;
+-
+-	trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+-
+-	if (trigger) {
+-		trigger->name = name;
+-		err = led_trigger_register(trigger);
+-		if (err < 0)
+-			printk(KERN_WARNING "LED trigger %s failed to register"
+-				" (%d)\n", name, err);
+-	} else
+-		printk(KERN_WARNING "LED trigger %s failed to register"
+-			" (no memory)\n", name);
+-
+-	*tp = trigger;
+-}
++EXPORT_SYMBOL_GPL(led_trigger_register);
+ 
+ void led_trigger_unregister(struct led_trigger *trigger)
+ {
+@@ -221,6 +198,49 @@ void led_trigger_unregister(struct led_trigger *trigger)
+ 	}
+ 	up_read(&leds_list_lock);
+ }
++EXPORT_SYMBOL_GPL(led_trigger_unregister);
++
++/* Simple LED Tigger Interface */
++
++void led_trigger_event(struct led_trigger *trigger,
++			enum led_brightness brightness)
++{
++	struct list_head *entry;
++
++	if (!trigger)
++		return;
++
++	read_lock(&trigger->leddev_list_lock);
++	list_for_each(entry, &trigger->led_cdevs) {
++		struct led_classdev *led_cdev;
++
++		led_cdev = list_entry(entry, struct led_classdev, trig_list);
++		led_set_brightness(led_cdev, brightness);
++	}
++	read_unlock(&trigger->leddev_list_lock);
++}
++EXPORT_SYMBOL_GPL(led_trigger_event);
++
++void led_trigger_register_simple(const char *name, struct led_trigger **tp)
++{
++	struct led_trigger *trigger;
++	int err;
++
++	trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++
++	if (trigger) {
++		trigger->name = name;
++		err = led_trigger_register(trigger);
++		if (err < 0)
++			printk(KERN_WARNING "LED trigger %s failed to register"
++				" (%d)\n", name, err);
++	} else
++		printk(KERN_WARNING "LED trigger %s failed to register"
++			" (no memory)\n", name);
++
++	*tp = trigger;
++}
++EXPORT_SYMBOL_GPL(led_trigger_register_simple);
+ 
+ void led_trigger_unregister_simple(struct led_trigger *trigger)
+ {
+@@ -228,21 +248,7 @@ void led_trigger_unregister_simple(struct led_trigger *trigger)
+ 		led_trigger_unregister(trigger);
+ 	kfree(trigger);
+ }
+-
+-/* Used by LED Class */
+-EXPORT_SYMBOL_GPL(led_trigger_set);
+-EXPORT_SYMBOL_GPL(led_trigger_set_default);
+-EXPORT_SYMBOL_GPL(led_trigger_show);
+-EXPORT_SYMBOL_GPL(led_trigger_store);
+-
+-/* LED Trigger Interface */
+-EXPORT_SYMBOL_GPL(led_trigger_register);
+-EXPORT_SYMBOL_GPL(led_trigger_unregister);
+-
+-/* Simple LED Tigger Interface */
+-EXPORT_SYMBOL_GPL(led_trigger_register_simple);
+ EXPORT_SYMBOL_GPL(led_trigger_unregister_simple);
+-EXPORT_SYMBOL_GPL(led_trigger_event);
+ 
+ MODULE_AUTHOR("Richard Purdie");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
+index 5750b08..eb3415e 100644
+--- a/drivers/leds/leds-clevo-mail.c
++++ b/drivers/leds/leds-clevo-mail.c
+@@ -14,7 +14,7 @@
+ #define CLEVO_MAIL_LED_BLINK_1HZ	0x008A
+ #define CLEVO_MAIL_LED_BLINK_0_5HZ	0x0083
+ 
+-MODULE_AUTHOR("Márton Németh <nm127 at freemail.hu>");
++MODULE_AUTHOR("Márton Németh <nm127 at freemail.hu>");
+ MODULE_DESCRIPTION("Clevo mail LED driver");
+ MODULE_LICENSE("GPL");
+ 
+@@ -69,6 +69,16 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
+ 	},
+ 	{
+ 		.callback = clevo_mail_led_dmi_callback,
++		.ident = "Clevo D400P",
++		.matches = {
++			DMI_MATCH(DMI_BOARD_VENDOR, "Clevo"),
++			DMI_MATCH(DMI_BOARD_NAME, "D400P"),
++			DMI_MATCH(DMI_BOARD_VERSION, "Rev.A"),
++			DMI_MATCH(DMI_PRODUCT_VERSION, "0106")
++		}
++	},
++	{
++		.callback = clevo_mail_led_dmi_callback,
+ 		.ident = "Clevo D410V",
+ 		.matches = {
+ 			DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."),
+@@ -93,8 +103,8 @@ static void clevo_mail_led_set(struct led_classdev *led_cdev,
+ }
+ 
+ static int clevo_mail_led_blink(struct led_classdev *led_cdev,
+-				unsigned long* delay_on,
+-				unsigned long* delay_off)
++				unsigned long *delay_on,
++				unsigned long *delay_off)
+ {
+ 	int status = -EINVAL;
+ 
+diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
+index 096881a..059aa29 100644
+--- a/drivers/leds/leds-cobalt-qube.c
++++ b/drivers/leds/leds-cobalt-qube.c
+@@ -18,7 +18,7 @@ static void __iomem *led_port;
+ static u8 led_value;
+ 
+ static void qube_front_led_set(struct led_classdev *led_cdev,
+-                               enum led_brightness brightness)
++			       enum led_brightness brightness)
+ {
+ 	if (brightness)
+ 		led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT;
+diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
+index 6ebfff3..ff0e8c3 100644
+--- a/drivers/leds/leds-cobalt-raq.c
++++ b/drivers/leds/leds-cobalt-raq.c
+@@ -15,7 +15,7 @@
+  *
+  *  You should have received a copy of the GNU 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
++ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include <linux/init.h>
+ #include <linux/io.h>
+@@ -33,7 +33,7 @@ static u8 led_value;
+ static DEFINE_SPINLOCK(led_value_lock);
+ 
+ static void raq_web_led_set(struct led_classdev *led_cdev,
+-                            enum led_brightness brightness)
++			    enum led_brightness brightness)
+ {
+ 	unsigned long flags;
+ 
+@@ -54,7 +54,7 @@ static struct led_classdev raq_web_led = {
+ };
+ 
+ static void raq_power_off_led_set(struct led_classdev *led_cdev,
+-                                  enum led_brightness brightness)
++				  enum led_brightness brightness)
+ {
+ 	unsigned long flags;
+ 
+diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c
+index 29e931f..a709704 100644
+--- a/drivers/leds/leds-corgi.c
++++ b/drivers/leds/leds-corgi.c
+@@ -21,7 +21,8 @@
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/hardware/scoop.h>
+ 
+-static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void corgiled_amber_set(struct led_classdev *led_cdev,
++			       enum led_brightness value)
+ {
+ 	if (value)
+ 		GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
+@@ -29,7 +30,8 @@ static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightnes
+ 		GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
+ }
+ 
+-static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void corgiled_green_set(struct led_classdev *led_cdev,
++			       enum led_brightness value)
+ {
+ 	if (value)
+ 		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+@@ -53,7 +55,8 @@ static struct led_classdev corgi_green_led = {
+ static int corgiled_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ #ifdef CONFIG_LEDS_TRIGGERS
+-	if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
++	if (corgi_amber_led.trigger &&
++	    strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
+ #endif
+ 		led_classdev_suspend(&corgi_amber_led);
+ 	led_classdev_suspend(&corgi_green_led);
+@@ -110,7 +113,7 @@ static int __init corgiled_init(void)
+ 
+ static void __exit corgiled_exit(void)
+ {
+- 	platform_driver_unregister(&corgiled_driver);
++	platform_driver_unregister(&corgiled_driver);
+ }
+ 
+ module_init(corgiled_init);
+diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
+new file mode 100644
+index 0000000..a7421b8
+--- /dev/null
++++ b/drivers/leds/leds-fsg.c
+@@ -0,0 +1,261 @@
++/*
++ * LED Driver for the Freecom FSG-3
++ *
++ * Copyright (c) 2008 Rod Whitby <rod at whitby.id.au>
++ *
++ * Author: Rod Whitby <rod at whitby.id.au>
++ *
++ * Based on leds-spitz.c
++ * Copyright 2005-2006 Openedhand Ltd.
++ * Author: Richard Purdie <rpurdie at openedhand.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++#include <asm/arch/hardware.h>
++#include <asm/io.h>
++
++static short __iomem *latch_address;
++static unsigned short latch_value;
++
++
++static void fsg_led_wlan_set(struct led_classdev *led_cdev,
++			     enum led_brightness value)
++{
++	if (value) {
++		latch_value &= ~(1 << FSG_LED_WLAN_BIT);
++		*latch_address = latch_value;
++	} else {
++		latch_value |=  (1 << FSG_LED_WLAN_BIT);
++		*latch_address = latch_value;
++	}
++}
++
++static void fsg_led_wan_set(struct led_classdev *led_cdev,
++			    enum led_brightness value)
++{
++	if (value) {
++		latch_value &= ~(1 << FSG_LED_WAN_BIT);
++		*latch_address = latch_value;
++	} else {
++		latch_value |=  (1 << FSG_LED_WAN_BIT);
++		*latch_address = latch_value;
++	}
++}
++
++static void fsg_led_sata_set(struct led_classdev *led_cdev,
++			     enum led_brightness value)
++{
++	if (value) {
++		latch_value &= ~(1 << FSG_LED_SATA_BIT);
++		*latch_address = latch_value;
++	} else {
++		latch_value |=  (1 << FSG_LED_SATA_BIT);
++		*latch_address = latch_value;
++	}
++}
++
++static void fsg_led_usb_set(struct led_classdev *led_cdev,
++			    enum led_brightness value)
++{
++	if (value) {
++		latch_value &= ~(1 << FSG_LED_USB_BIT);
++		*latch_address = latch_value;
++	} else {
++		latch_value |=  (1 << FSG_LED_USB_BIT);
++		*latch_address = latch_value;
++	}
++}
++
++static void fsg_led_sync_set(struct led_classdev *led_cdev,
++			     enum led_brightness value)
++{
++	if (value) {
++		latch_value &= ~(1 << FSG_LED_SYNC_BIT);
++		*latch_address = latch_value;
++	} else {
++		latch_value |=  (1 << FSG_LED_SYNC_BIT);
++		*latch_address = latch_value;
++	}
++}
++
++static void fsg_led_ring_set(struct led_classdev *led_cdev,
++			     enum led_brightness value)
++{
++	if (value) {
++		latch_value &= ~(1 << FSG_LED_RING_BIT);
++		*latch_address = latch_value;
++	} else {
++		latch_value |=  (1 << FSG_LED_RING_BIT);
++		*latch_address = latch_value;
++	}
++}
++
++
++
++static struct led_classdev fsg_wlan_led = {
++	.name			= "fsg:blue:wlan",
++	.brightness_set		= fsg_led_wlan_set,
++};
++
++static struct led_classdev fsg_wan_led = {
++	.name			= "fsg:blue:wan",
++	.brightness_set		= fsg_led_wan_set,
++};
++
++static struct led_classdev fsg_sata_led = {
++	.name			= "fsg:blue:sata",
++	.brightness_set		= fsg_led_sata_set,
++};
++
++static struct led_classdev fsg_usb_led = {
++	.name			= "fsg:blue:usb",
++	.brightness_set		= fsg_led_usb_set,
++};
++
++static struct led_classdev fsg_sync_led = {
++	.name			= "fsg:blue:sync",
++	.brightness_set		= fsg_led_sync_set,
++};
++
++static struct led_classdev fsg_ring_led = {
++	.name			= "fsg:blue:ring",
++	.brightness_set		= fsg_led_ring_set,
++};
++
++
++
++#ifdef CONFIG_PM
++static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
++{
++	led_classdev_suspend(&fsg_wlan_led);
++	led_classdev_suspend(&fsg_wan_led);
++	led_classdev_suspend(&fsg_sata_led);
++	led_classdev_suspend(&fsg_usb_led);
++	led_classdev_suspend(&fsg_sync_led);
++	led_classdev_suspend(&fsg_ring_led);
++	return 0;
++}
++
++static int fsg_led_resume(struct platform_device *dev)
++{
++	led_classdev_resume(&fsg_wlan_led);
++	led_classdev_resume(&fsg_wan_led);
++	led_classdev_resume(&fsg_sata_led);
++	led_classdev_resume(&fsg_usb_led);
++	led_classdev_resume(&fsg_sync_led);
++	led_classdev_resume(&fsg_ring_led);
++	return 0;
++}
++#endif
++
++
++static int fsg_led_probe(struct platform_device *pdev)
++{
++	int ret;
++
++	ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
++	if (ret < 0)
++		goto failwlan;
++
++	ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
++	if (ret < 0)
++		goto failwan;
++
++	ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
++	if (ret < 0)
++		goto failsata;
++
++	ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
++	if (ret < 0)
++		goto failusb;
++
++	ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
++	if (ret < 0)
++		goto failsync;
++
++	ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
++	if (ret < 0)
++		goto failring;
++
++	/* Map the LED chip select address space */
++	latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
++	if (!latch_address) {
++		ret = -ENOMEM;
++		goto failremap;
++	}
++
++	latch_value = 0xffff;
++	*latch_address = latch_value;
++
++	return ret;
++
++ failremap:
++	led_classdev_unregister(&fsg_ring_led);
++ failring:
++	led_classdev_unregister(&fsg_sync_led);
++ failsync:
++	led_classdev_unregister(&fsg_usb_led);
++ failusb:
++	led_classdev_unregister(&fsg_sata_led);
++ failsata:
++	led_classdev_unregister(&fsg_wan_led);
++ failwan:
++	led_classdev_unregister(&fsg_wlan_led);
++ failwlan:
++
++	return ret;
++}
++
++static int fsg_led_remove(struct platform_device *pdev)
++{
++	iounmap(latch_address);
++
++	led_classdev_unregister(&fsg_wlan_led);
++	led_classdev_unregister(&fsg_wan_led);
++	led_classdev_unregister(&fsg_sata_led);
++	led_classdev_unregister(&fsg_usb_led);
++	led_classdev_unregister(&fsg_sync_led);
++	led_classdev_unregister(&fsg_ring_led);
++
++	return 0;
++}
++
++
++static struct platform_driver fsg_led_driver = {
++	.probe		= fsg_led_probe,
++	.remove		= fsg_led_remove,
++#ifdef CONFIG_PM
++	.suspend	= fsg_led_suspend,
++	.resume		= fsg_led_resume,
++#endif
++	.driver		= {
++		.name		= "fsg-led",
++	},
++};
++
++
++static int __init fsg_led_init(void)
++{
++	return platform_driver_register(&fsg_led_driver);
++}
++
++static void __exit fsg_led_exit(void)
++{
++	platform_driver_unregister(&fsg_led_driver);
++}
++
++
++module_init(fsg_led_init);
++module_exit(fsg_led_exit);
++
++MODULE_AUTHOR("Rod Whitby <rod at whitby.id.au>");
++MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
+index 1aae8b3..b13bd29 100644
+--- a/drivers/leds/leds-gpio.c
++++ b/drivers/leds/leds-gpio.c
+@@ -24,6 +24,8 @@ struct gpio_led_data {
+ 	u8 new_level;
+ 	u8 can_sleep;
+ 	u8 active_low;
++	int (*platform_gpio_blink_set)(unsigned gpio,
++			unsigned long *delay_on, unsigned long *delay_off);
+ };
+ 
+ static void gpio_led_work(struct work_struct *work)
+@@ -60,6 +62,15 @@ static void gpio_led_set(struct led_classdev *led_cdev,
+ 		gpio_set_value(led_dat->gpio, level);
+ }
+ 
++static int gpio_blink_set(struct led_classdev *led_cdev,
++	unsigned long *delay_on, unsigned long *delay_off)
++{
++	struct gpio_led_data *led_dat =
++		container_of(led_cdev, struct gpio_led_data, cdev);
++
++	return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off);
++}
++
+ static int gpio_led_probe(struct platform_device *pdev)
+ {
+ 	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+@@ -88,6 +99,10 @@ static int gpio_led_probe(struct platform_device *pdev)
+ 		led_dat->gpio = cur_led->gpio;
+ 		led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
+ 		led_dat->active_low = cur_led->active_low;
++		if (pdata->gpio_blink_set) {
++			led_dat->platform_gpio_blink_set = pdata->gpio_blink_set;
++			led_dat->cdev.blink_set = gpio_blink_set;
++		}
+ 		led_dat->cdev.brightness_set = gpio_led_set;
+ 		led_dat->cdev.brightness = LED_OFF;
+ 
+diff --git a/drivers/leds/leds-h1940.c b/drivers/leds/leds-h1940.c
+index 6e51c9b..bcec422 100644
+--- a/drivers/leds/leds-h1940.c
++++ b/drivers/leds/leds-h1940.c
+@@ -26,20 +26,20 @@
+ void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value)
+ {
+ 	switch (value) {
+-		case LED_HALF:
+-			h1940_latch_control(0,H1940_LATCH_LED_FLASH);
+-			s3c2410_gpio_setpin(S3C2410_GPA7,1);
+-			break;
+-		case LED_FULL:
+-			h1940_latch_control(0,H1940_LATCH_LED_GREEN);
+-			s3c2410_gpio_setpin(S3C2410_GPA7,1);
+-			break;
+-		default:
+-		case LED_OFF:
+-			h1940_latch_control(H1940_LATCH_LED_FLASH,0);
+-			h1940_latch_control(H1940_LATCH_LED_GREEN,0);
+-			s3c2410_gpio_setpin(S3C2410_GPA7,0);
+-			break;
++	case LED_HALF:
++		h1940_latch_control(0, H1940_LATCH_LED_FLASH);
++		s3c2410_gpio_setpin(S3C2410_GPA7, 1);
++		break;
++	case LED_FULL:
++		h1940_latch_control(0, H1940_LATCH_LED_GREEN);
++		s3c2410_gpio_setpin(S3C2410_GPA7, 1);
++		break;
++	default:
++	case LED_OFF:
++		h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
++		h1940_latch_control(H1940_LATCH_LED_GREEN, 0);
++		s3c2410_gpio_setpin(S3C2410_GPA7, 0);
++		break;
+ 	}
+ }
+ 
+@@ -55,20 +55,20 @@ static struct led_classdev h1940_greenled = {
+ void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value)
+ {
+ 	switch (value) {
+-		case LED_HALF:
+-			h1940_latch_control(0,H1940_LATCH_LED_FLASH);
+-			s3c2410_gpio_setpin(S3C2410_GPA1,1);
+-			break;
+-		case LED_FULL:
+-			h1940_latch_control(0,H1940_LATCH_LED_RED);
+-			s3c2410_gpio_setpin(S3C2410_GPA1,1);
+-			break;
+-		default:
+-		case LED_OFF:
+-			h1940_latch_control(H1940_LATCH_LED_FLASH,0);
+-			h1940_latch_control(H1940_LATCH_LED_RED,0);
+-			s3c2410_gpio_setpin(S3C2410_GPA1,0);
+-			break;
++	case LED_HALF:
++		h1940_latch_control(0, H1940_LATCH_LED_FLASH);
++		s3c2410_gpio_setpin(S3C2410_GPA1, 1);
++		break;
++	case LED_FULL:
++		h1940_latch_control(0, H1940_LATCH_LED_RED);
++		s3c2410_gpio_setpin(S3C2410_GPA1, 1);
++		break;
++	default:
++	case LED_OFF:
++		h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
++		h1940_latch_control(H1940_LATCH_LED_RED, 0);
++		s3c2410_gpio_setpin(S3C2410_GPA1, 0);
++		break;
+ 	}
+ }
+ 
+@@ -86,11 +86,11 @@ void h1940_blueled_set(struct led_classdev *led_dev, enum led_brightness value)
+ {
+ 	if (value) {
+ 		/* flashing Blue */
+-		h1940_latch_control(0,H1940_LATCH_LED_FLASH);
+-		s3c2410_gpio_setpin(S3C2410_GPA3,1);
++		h1940_latch_control(0, H1940_LATCH_LED_FLASH);
++		s3c2410_gpio_setpin(S3C2410_GPA3, 1);
+ 	} else {
+-		h1940_latch_control(H1940_LATCH_LED_FLASH,0);
+-		s3c2410_gpio_setpin(S3C2410_GPA3,0);
++		h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
++		s3c2410_gpio_setpin(S3C2410_GPA3, 0);
+ 	}
+ 
+ }
+diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
+index 870f5a3..844d597 100644
+--- a/drivers/leds/leds-hp6xx.c
++++ b/drivers/leds/leds-hp6xx.c
+@@ -17,7 +17,8 @@
+ #include <asm/hd64461.h>
+ #include <asm/hp6xx.h>
+ 
+-static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void hp6xxled_green_set(struct led_classdev *led_cdev,
++			       enum led_brightness value)
+ {
+ 	u8 v8;
+ 
+@@ -28,7 +29,8 @@ static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightnes
+ 		outb(v8 | PKDR_LED_GREEN, PKDR);
+ }
+ 
+-static void hp6xxled_red_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void hp6xxled_red_set(struct led_classdev *led_cdev,
++			     enum led_brightness value)
+ {
+ 	u16 v16;
+ 
+diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
+index 0d10e11..d4f5021 100644
+--- a/drivers/leds/leds-s3c24xx.c
++++ b/drivers/leds/leds-s3c24xx.c
+@@ -51,7 +51,7 @@ static void s3c24xx_led_set(struct led_classdev *led_cdev,
+ 
+ 	if (pd->flags & S3C24XX_LEDF_TRISTATE)
+ 		s3c2410_gpio_cfgpin(pd->gpio,
+-				    value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
++			value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
+ 
+ }
+ 
+@@ -151,7 +151,7 @@ static int __init s3c24xx_led_init(void)
+ 
+ static void __exit s3c24xx_led_exit(void)
+ {
+- 	platform_driver_unregister(&s3c24xx_led_driver);
++	platform_driver_unregister(&s3c24xx_led_driver);
+ }
+ 
+ module_init(s3c24xx_led_init);
+diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c
+index 87007cc..e75e854 100644
+--- a/drivers/leds/leds-spitz.c
++++ b/drivers/leds/leds-spitz.c
+@@ -21,7 +21,8 @@
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/spitz.h>
+ 
+-static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void spitzled_amber_set(struct led_classdev *led_cdev,
++			       enum led_brightness value)
+ {
+ 	if (value)
+ 		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
+@@ -29,7 +30,8 @@ static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightnes
+ 		reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
+ }
+ 
+-static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void spitzled_green_set(struct led_classdev *led_cdev,
++			       enum led_brightness value)
+ {
+ 	if (value)
+ 		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
+@@ -53,7 +55,8 @@ static struct led_classdev spitz_green_led = {
+ static int spitzled_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ #ifdef CONFIG_LEDS_TRIGGERS
+-	if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
++	if (spitz_amber_led.trigger &&
++	    strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
+ #endif
+ 		led_classdev_suspend(&spitz_amber_led);
+ 	led_classdev_suspend(&spitz_green_led);
+@@ -116,7 +119,7 @@ static int __init spitzled_init(void)
+ 
+ static void __exit spitzled_exit(void)
+ {
+- 	platform_driver_unregister(&spitzled_driver);
++	platform_driver_unregister(&spitzled_driver);
+ }
+ 
+ module_init(spitzled_init);
+diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c
+deleted file mode 100644
+index 7ebecc4..0000000
+--- a/drivers/leds/leds-tosa.c
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/*
+- * LED Triggers Core
+- *
+- * Copyright 2005 Dirk Opfer
+- *
+- * Author: Dirk Opfer <Dirk at Opfer-Online.de>
+- *	based on spitz.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/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/leds.h>
+-#include <asm/hardware/scoop.h>
+-#include <asm/mach-types.h>
+-#include <asm/arch/hardware.h>
+-#include <asm/arch/pxa-regs.h>
+-#include <asm/arch/tosa.h>
+-
+-static void tosaled_amber_set(struct led_classdev *led_cdev,
+-				enum led_brightness value)
+-{
+-	if (value)
+-		set_scoop_gpio(&tosascoop_jc_device.dev,
+-				TOSA_SCOOP_JC_CHRG_ERR_LED);
+-	else
+-		reset_scoop_gpio(&tosascoop_jc_device.dev,
+-				TOSA_SCOOP_JC_CHRG_ERR_LED);
+-}
+-
+-static void tosaled_green_set(struct led_classdev *led_cdev,
+-				enum led_brightness value)
+-{
+-	if (value)
+-		set_scoop_gpio(&tosascoop_jc_device.dev,
+-				TOSA_SCOOP_JC_NOTE_LED);
+-	else
+-		reset_scoop_gpio(&tosascoop_jc_device.dev,
+-				TOSA_SCOOP_JC_NOTE_LED);
+-}
+-
+-static struct led_classdev tosa_amber_led = {
+-	.name			= "tosa:amber:charge",
+-	.default_trigger	= "sharpsl-charge",
+-	.brightness_set		= tosaled_amber_set,
+-};
+-
+-static struct led_classdev tosa_green_led = {
+-	.name			= "tosa:green:mail",
+-	.default_trigger	= "nand-disk",
+-	.brightness_set		= tosaled_green_set,
+-};
+-
+-#ifdef CONFIG_PM
+-static int tosaled_suspend(struct platform_device *dev, pm_message_t state)
+-{
+-#ifdef CONFIG_LEDS_TRIGGERS
+-	if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name,
+-						"sharpsl-charge"))
+-#endif
+-		led_classdev_suspend(&tosa_amber_led);
+-	led_classdev_suspend(&tosa_green_led);
+-	return 0;
+-}
+-
+-static int tosaled_resume(struct platform_device *dev)
+-{
+-	led_classdev_resume(&tosa_amber_led);
+-	led_classdev_resume(&tosa_green_led);
+-	return 0;
+-}
+-#else
+-#define tosaled_suspend NULL
+-#define tosaled_resume NULL
+-#endif
+-
+-static int tosaled_probe(struct platform_device *pdev)
+-{
+-	int ret;
+-
+-	ret = led_classdev_register(&pdev->dev, &tosa_amber_led);
+-	if (ret < 0)
+-		return ret;
+-
+-	ret = led_classdev_register(&pdev->dev, &tosa_green_led);
+-	if (ret < 0)
+-		led_classdev_unregister(&tosa_amber_led);
+-
+-	return ret;
+-}
+-
+-static int tosaled_remove(struct platform_device *pdev)
+-{
+-	led_classdev_unregister(&tosa_amber_led);
+-	led_classdev_unregister(&tosa_green_led);
+-
+-	return 0;
+-}
+-
+-static struct platform_driver tosaled_driver = {
+-	.probe		= tosaled_probe,
+-	.remove		= tosaled_remove,
+-	.suspend	= tosaled_suspend,
+-	.resume		= tosaled_resume,
+-	.driver		= {
+-		.name		= "tosa-led",
+-		.owner		= THIS_MODULE,
+-	},
+-};
+-
+-static int __init tosaled_init(void)
+-{
+-	return platform_driver_register(&tosaled_driver);
+-}
+-
+-static void __exit tosaled_exit(void)
+-{
+- 	platform_driver_unregister(&tosaled_driver);
+-}
+-
+-module_init(tosaled_init);
+-module_exit(tosaled_exit);
+-
+-MODULE_AUTHOR("Dirk Opfer <Dirk at Opfer-Online.de>");
+-MODULE_DESCRIPTION("Tosa LED driver");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:tosa-led");
+diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
+index 12b6fe9..5edbf52 100644
+--- a/drivers/leds/leds.h
++++ b/drivers/leds/leds.h
+@@ -27,6 +27,11 @@ static inline void led_set_brightness(struct led_classdev *led_cdev,
+ 		led_cdev->brightness_set(led_cdev, value);
+ }
+ 
++static inline int led_get_brightness(struct led_classdev *led_cdev)
++{
++	return led_cdev->brightness;
++}
++
+ extern struct rw_semaphore leds_list_lock;
+ extern struct list_head leds_list;
+ 
+@@ -34,9 +39,11 @@ extern struct list_head leds_list;
+ void led_trigger_set_default(struct led_classdev *led_cdev);
+ void led_trigger_set(struct led_classdev *led_cdev,
+ 			struct led_trigger *trigger);
++void led_trigger_remove(struct led_classdev *led_cdev);
+ #else
+-#define led_trigger_set_default(x) do {} while(0)
+-#define led_trigger_set(x, y) do {} while(0)
++#define led_trigger_set_default(x) do {} while (0)
++#define led_trigger_set(x, y) do {} while (0)
++#define led_trigger_remove(x) do {} while (0)
+ #endif
+ 
+ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+diff --git a/drivers/leds/ledtrig-default-on.c b/drivers/leds/ledtrig-default-on.c
+new file mode 100644
+index 0000000..92995e4
+--- /dev/null
++++ b/drivers/leds/ledtrig-default-on.c
+@@ -0,0 +1,45 @@
++/*
++ * LED Kernel Default ON Trigger
++ *
++ * Copyright 2008 Nick Forbes <nick.forbes at incepta.com>
++ *
++ * Based on Richard Purdie's ledtrig-timer.c.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/leds.h>
++#include "leds.h"
++
++static void defon_trig_activate(struct led_classdev *led_cdev)
++{
++	led_set_brightness(led_cdev, LED_FULL);
++}
++
++static struct led_trigger defon_led_trigger = {
++	.name     = "default-on",
++	.activate = defon_trig_activate,
++};
++
++static int __init defon_trig_init(void)
++{
++	return led_trigger_register(&defon_led_trigger);
++}
++
++static void __exit defon_trig_exit(void)
++{
++	led_trigger_unregister(&defon_led_trigger);
++}
++
++module_init(defon_trig_init);
++module_exit(defon_trig_exit);
++
++MODULE_AUTHOR("Nick Forbes <nick.forbes at incepta.com>");
++MODULE_DESCRIPTION("Default-ON LED trigger");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c
+index 54b155c..883a577 100644
+--- a/drivers/leds/ledtrig-ide-disk.c
++++ b/drivers/leds/ledtrig-ide-disk.c
+@@ -38,7 +38,7 @@ static void ledtrig_ide_timerfunc(unsigned long data)
+ 	if (ide_lastactivity != ide_activity) {
+ 		ide_lastactivity = ide_activity;
+ 		led_trigger_event(ledtrig_ide, LED_FULL);
+-	    	mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
++		mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
+ 	} else {
+ 		led_trigger_event(ledtrig_ide, LED_OFF);
+ 	}
+diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
+index 82c55d6..5c99f4f 100644
+--- a/drivers/leds/ledtrig-timer.c
++++ b/drivers/leds/ledtrig-timer.c
+@@ -25,6 +25,9 @@
+ #include "leds.h"
+ 
+ struct timer_trig_data {
++	int brightness_on;		/* LED brightness during "on" period.
++					 * (LED_OFF < brightness_on <= LED_FULL)
++					 */
+ 	unsigned long delay_on;		/* milliseconds on */
+ 	unsigned long delay_off;	/* milliseconds off */
+ 	struct timer_list timer;
+@@ -34,17 +37,26 @@ static void led_timer_function(unsigned long data)
+ {
+ 	struct led_classdev *led_cdev = (struct led_classdev *) data;
+ 	struct timer_trig_data *timer_data = led_cdev->trigger_data;
+-	unsigned long brightness = LED_OFF;
+-	unsigned long delay = timer_data->delay_off;
++	unsigned long brightness;
++	unsigned long delay;
+ 
+ 	if (!timer_data->delay_on || !timer_data->delay_off) {
+ 		led_set_brightness(led_cdev, LED_OFF);
+ 		return;
+ 	}
+ 
+-	if (!led_cdev->brightness) {
+-		brightness = LED_FULL;
++	brightness = led_get_brightness(led_cdev);
++	if (!brightness) {
++		/* Time to switch the LED on. */
++		brightness = timer_data->brightness_on;
+ 		delay = timer_data->delay_on;
++	} else {
++		/* Store the current brightness value to be able
++		 * to restore it when the delay_off period is over.
++		 */
++		timer_data->brightness_on = brightness;
++		brightness = LED_OFF;
++		delay = timer_data->delay_off;
+ 	}
+ 
+ 	led_set_brightness(led_cdev, brightness);
+@@ -52,7 +64,7 @@ static void led_timer_function(unsigned long data)
+ 	mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay));
+ }
+ 
+-static ssize_t led_delay_on_show(struct device *dev, 
++static ssize_t led_delay_on_show(struct device *dev,
+ 		struct device_attribute *attr, char *buf)
+ {
+ 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+@@ -63,7 +75,7 @@ static ssize_t led_delay_on_show(struct device *dev,
+ 	return strlen(buf) + 1;
+ }
+ 
+-static ssize_t led_delay_on_store(struct device *dev, 
++static ssize_t led_delay_on_store(struct device *dev,
+ 		struct device_attribute *attr, const char *buf, size_t size)
+ {
+ 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+@@ -87,7 +99,7 @@ static ssize_t led_delay_on_store(struct device *dev,
+ 			/* try to activate hardware acceleration, if any */
+ 			if (!led_cdev->blink_set ||
+ 			    led_cdev->blink_set(led_cdev,
+-				&timer_data->delay_on, &timer_data->delay_off)) {
++			      &timer_data->delay_on, &timer_data->delay_off)) {
+ 				/* no hardware acceleration, blink via timer */
+ 				mod_timer(&timer_data->timer, jiffies + 1);
+ 			}
+@@ -98,7 +110,7 @@ static ssize_t led_delay_on_store(struct device *dev,
+ 	return ret;
+ }
+ 
+-static ssize_t led_delay_off_show(struct device *dev, 
++static ssize_t led_delay_off_show(struct device *dev,
+ 		struct device_attribute *attr, char *buf)
+ {
+ 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+@@ -109,7 +121,7 @@ static ssize_t led_delay_off_show(struct device *dev,
+ 	return strlen(buf) + 1;
+ }
+ 
+-static ssize_t led_delay_off_store(struct device *dev, 
++static ssize_t led_delay_off_store(struct device *dev,
+ 		struct device_attribute *attr, const char *buf, size_t size)
+ {
+ 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+@@ -133,7 +145,7 @@ static ssize_t led_delay_off_store(struct device *dev,
+ 			/* try to activate hardware acceleration, if any */
+ 			if (!led_cdev->blink_set ||
+ 			    led_cdev->blink_set(led_cdev,
+-				&timer_data->delay_on, &timer_data->delay_off)) {
++			      &timer_data->delay_on, &timer_data->delay_off)) {
+ 				/* no hardware acceleration, blink via timer */
+ 				mod_timer(&timer_data->timer, jiffies + 1);
+ 			}
+@@ -156,6 +168,9 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
+ 	if (!timer_data)
+ 		return;
+ 
++	timer_data->brightness_on = led_get_brightness(led_cdev);
++	if (timer_data->brightness_on == LED_OFF)
++		timer_data->brightness_on = LED_FULL;
+ 	led_cdev->trigger_data = timer_data;
+ 
+ 	init_timer(&timer_data->timer);
+diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
+index 2337e1a..005bd04 100644
+--- a/drivers/lguest/lg.h
++++ b/drivers/lguest/lg.h
+@@ -10,7 +10,6 @@
+ #include <linux/wait.h>
+ #include <linux/hrtimer.h>
+ #include <linux/err.h>
+-#include <asm/semaphore.h>
+ 
+ #include <asm/lguest.h>
+ 
+diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
+index 2895810..2097820 100644
+--- a/drivers/macintosh/adb.c
++++ b/drivers/macintosh/adb.c
+@@ -37,9 +37,9 @@
+ #include <linux/device.h>
+ #include <linux/kthread.h>
+ #include <linux/platform_device.h>
++#include <linux/semaphore.h>
+ 
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #ifdef CONFIG_PPC
+ #include <asm/prom.h>
+ #include <asm/machdep.h>
+diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
+index 8930230..cc9f275 100644
+--- a/drivers/macintosh/mac_hid.c
++++ b/drivers/macintosh/mac_hid.c
+@@ -103,6 +103,9 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
+ 	return 0;
+ }
+ 
++static struct lock_class_key emumousebtn_event_class;
++static struct lock_class_key emumousebtn_mutex_class;
++
+ static int emumousebtn_input_register(void)
+ {
+ 	int ret;
+@@ -111,6 +114,9 @@ static int emumousebtn_input_register(void)
+ 	if (!emumousebtn)
+ 		return -ENOMEM;
+ 
++	lockdep_set_class(&emumousebtn->event_lock, &emumousebtn_event_class);
++	lockdep_set_class(&emumousebtn->mutex, &emumousebtn_mutex_class);
++
+ 	emumousebtn->name = "Macintosh mouse button emulation";
+ 	emumousebtn->id.bustype = BUS_ADB;
+ 	emumousebtn->id.vendor = 0x0001;
+diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
+index bd8a1d1..82add26 100644
+--- a/drivers/macintosh/mediabay.c
++++ b/drivers/macintosh/mediabay.c
+@@ -79,6 +79,7 @@ struct media_bay_info {
+ 	int				sleeping;
+ 	struct semaphore		lock;
+ #ifdef CONFIG_BLK_DEV_IDE_PMAC
++	ide_hwif_t			*cd_port;
+ 	void __iomem			*cd_base;
+ 	int				cd_irq;
+ 	int				cd_retry;
+@@ -448,7 +449,7 @@ int check_media_bay_by_base(unsigned long base, int what)
+ }
+ 
+ int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
+-			    int irq, int index)
++			    int irq, ide_hwif_t *hwif)
+ {
+ 	int	i;
+ 
+@@ -456,10 +457,11 @@ int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
+ 		struct media_bay_info* bay = &media_bays[i];
+ 
+ 		if (bay->mdev && which_bay == bay->mdev->ofdev.node) {
+-			int timeout = 5000;
++			int timeout = 5000, index = hwif->index;
+ 			
+ 			down(&bay->lock);
+ 
++			bay->cd_port	= hwif;
+  			bay->cd_base	= (void __iomem *) base;
+ 			bay->cd_irq	= irq;
+ 
+@@ -551,15 +553,10 @@ static void media_bay_step(int i)
+ 			bay->timer = 0;
+ 			bay->state = mb_up;
+ 			if (bay->cd_index < 0) {
+-				hw_regs_t hw;
+-
+ 				printk("mediabay %d, registering IDE...\n", i);
+ 				pmu_suspend();
+-				ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL);
+-				hw.irq = bay->cd_irq;
+-				hw.chipset = ide_pmac;
+-				bay->cd_index =
+-					ide_register_hw(&hw, NULL, NULL);
++				ide_port_scan(bay->cd_port);
++				bay->cd_index = bay->cd_port->index;
+ 				pmu_resume();
+ 			}
+ 			if (bay->cd_index == -1) {
+@@ -589,7 +586,7 @@ static void media_bay_step(int i)
+     	        if (bay->cd_index >= 0) {
+ 			printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i,
+ 			       bay->cd_index);
+-			ide_unregister(bay->cd_index, 1, 1);
++			ide_port_unregister_devices(bay->cd_port);
+ 			bay->cd_index = -1;
+ 		}
+ 	    	if (bay->cd_retry) {
+diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c
+index b3fbb45..73d695d 100644
+--- a/drivers/macintosh/windfarm_pm112.c
++++ b/drivers/macintosh/windfarm_pm112.c
+@@ -668,7 +668,7 @@ static struct platform_driver wf_pm112_driver = {
+ 	.remove = __devexit_p(wf_pm112_remove),
+ 	.driver = {
+ 		.name = "windfarm",
+-		.bus = &platform_bus_type,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -711,3 +711,4 @@ module_exit(wf_pm112_exit);
+ MODULE_AUTHOR("Paul Mackerras <paulus at samba.org>");
+ MODULE_DESCRIPTION("Thermal control for PowerMac11,2");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:windfarm");
+diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
+index f24fa73..abbe206 100644
+--- a/drivers/macintosh/windfarm_pm81.c
++++ b/drivers/macintosh/windfarm_pm81.c
+@@ -770,7 +770,7 @@ static struct platform_driver wf_smu_driver = {
+         .remove = __devexit_p(wf_smu_remove),
+ 	.driver = {
+ 		.name = "windfarm",
+-		.bus = &platform_bus_type,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -810,4 +810,4 @@ module_exit(wf_smu_exit);
+ MODULE_AUTHOR("Benjamin Herrenschmidt <benh at kernel.crashing.org>");
+ MODULE_DESCRIPTION("Thermal control logic for iMac G5");
+ MODULE_LICENSE("GPL");
+-
++MODULE_ALIAS("platform:windfarm");
+diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
+index 26eee69..764c525 100644
+--- a/drivers/macintosh/windfarm_pm91.c
++++ b/drivers/macintosh/windfarm_pm91.c
+@@ -702,7 +702,7 @@ static struct platform_driver wf_smu_driver = {
+         .remove = __devexit_p(wf_smu_remove),
+ 	.driver = {
+ 		.name = "windfarm",
+-		.bus = &platform_bus_type,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -742,3 +742,4 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh at kernel.crashing.org>");
+ MODULE_DESCRIPTION("Thermal control logic for PowerMac9,1");
+ MODULE_LICENSE("GPL");
+ 
++MODULE_ALIAS("platform:windfarm");
+diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
+index f449d77..797918d 100644
+--- a/drivers/macintosh/windfarm_smu_sat.c
++++ b/drivers/macintosh/windfarm_smu_sat.c
+@@ -13,7 +13,7 @@
+ #include <linux/init.h>
+ #include <linux/wait.h>
+ #include <linux/i2c.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/prom.h>
+ #include <asm/smu.h>
+ #include <asm/pmac_low_i2c.h>
+diff --git a/drivers/md/Makefile b/drivers/md/Makefile
+index d9aa7ed..7be09ee 100644
+--- a/drivers/md/Makefile
++++ b/drivers/md/Makefile
+@@ -3,10 +3,10 @@
+ #
+ 
+ dm-mod-objs	:= dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
+-		   dm-ioctl.o dm-io.o kcopyd.o
++		   dm-ioctl.o dm-io.o dm-kcopyd.o
+ dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
+ dm-snapshot-objs := dm-snap.o dm-exception-store.o
+-dm-mirror-objs	:= dm-log.o dm-raid1.o
++dm-mirror-objs	:= dm-raid1.o
+ dm-rdac-objs	:= dm-mpath-rdac.o
+ dm-hp-sw-objs	:= dm-mpath-hp-sw.o
+ md-mod-objs     := md.o bitmap.o
+@@ -39,7 +39,7 @@ obj-$(CONFIG_DM_MULTIPATH_EMC)	+= dm-emc.o
+ obj-$(CONFIG_DM_MULTIPATH_HP)	+= dm-hp-sw.o
+ obj-$(CONFIG_DM_MULTIPATH_RDAC)	+= dm-rdac.o
+ obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
+-obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o
++obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o dm-log.o
+ obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
+ 
+ quiet_cmd_unroll = UNROLL  $@
+diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
+index 5bbce29..41f4080 100644
+--- a/drivers/md/dm-exception-store.c
++++ b/drivers/md/dm-exception-store.c
+@@ -9,13 +9,13 @@
+ 
+ #include "dm.h"
+ #include "dm-snap.h"
+-#include "dm-io.h"
+-#include "kcopyd.h"
+ 
+ #include <linux/mm.h>
+ #include <linux/pagemap.h>
+ #include <linux/vmalloc.h>
+ #include <linux/slab.h>
++#include <linux/dm-io.h>
++#include <linux/dm-kcopyd.h>
+ 
+ #define DM_MSG_PREFIX "snapshots"
+ #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32	/* 16KB */
+@@ -131,7 +131,7 @@ struct pstore {
+ 
+ static unsigned sectors_to_pages(unsigned sectors)
+ {
+-	return sectors / (PAGE_SIZE >> 9);
++	return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
+ }
+ 
+ static int alloc_area(struct pstore *ps)
+@@ -159,7 +159,7 @@ static void free_area(struct pstore *ps)
+ }
+ 
+ struct mdata_req {
+-	struct io_region *where;
++	struct dm_io_region *where;
+ 	struct dm_io_request *io_req;
+ 	struct work_struct work;
+ 	int result;
+@@ -177,7 +177,7 @@ static void do_metadata(struct work_struct *work)
+  */
+ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
+ {
+-	struct io_region where = {
++	struct dm_io_region where = {
+ 		.bdev = ps->snap->cow->bdev,
+ 		.sector = ps->snap->chunk_size * chunk,
+ 		.count = ps->snap->chunk_size,
+diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
+index 8f25f62..4789c42 100644
+--- a/drivers/md/dm-io.c
++++ b/drivers/md/dm-io.c
+@@ -5,13 +5,14 @@
+  * This file is released under the GPL.
+  */
+ 
+-#include "dm-io.h"
++#include "dm.h"
+ 
+ #include <linux/bio.h>
+ #include <linux/mempool.h>
+ #include <linux/module.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
++#include <linux/dm-io.h>
+ 
+ struct dm_io_client {
+ 	mempool_t *pool;
+@@ -20,7 +21,7 @@ struct dm_io_client {
+ 
+ /* FIXME: can we shrink this ? */
+ struct io {
+-	unsigned long error;
++	unsigned long error_bits;
+ 	atomic_t count;
+ 	struct task_struct *sleeper;
+ 	struct dm_io_client *client;
+@@ -107,14 +108,14 @@ static inline unsigned bio_get_region(struct bio *bio)
+ static void dec_count(struct io *io, unsigned int region, int error)
+ {
+ 	if (error)
+-		set_bit(region, &io->error);
++		set_bit(region, &io->error_bits);
+ 
+ 	if (atomic_dec_and_test(&io->count)) {
+ 		if (io->sleeper)
+ 			wake_up_process(io->sleeper);
+ 
+ 		else {
+-			unsigned long r = io->error;
++			unsigned long r = io->error_bits;
+ 			io_notify_fn fn = io->callback;
+ 			void *context = io->context;
+ 
+@@ -271,7 +272,7 @@ static void km_dp_init(struct dpages *dp, void *data)
+ /*-----------------------------------------------------------------
+  * IO routines that accept a list of pages.
+  *---------------------------------------------------------------*/
+-static void do_region(int rw, unsigned int region, struct io_region *where,
++static void do_region(int rw, unsigned region, struct dm_io_region *where,
+ 		      struct dpages *dp, struct io *io)
+ {
+ 	struct bio *bio;
+@@ -320,7 +321,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
+ }
+ 
+ static void dispatch_io(int rw, unsigned int num_regions,
+-			struct io_region *where, struct dpages *dp,
++			struct dm_io_region *where, struct dpages *dp,
+ 			struct io *io, int sync)
+ {
+ 	int i;
+@@ -347,17 +348,17 @@ static void dispatch_io(int rw, unsigned int num_regions,
+ }
+ 
+ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
+-		   struct io_region *where, int rw, struct dpages *dp,
++		   struct dm_io_region *where, int rw, struct dpages *dp,
+ 		   unsigned long *error_bits)
+ {
+ 	struct io io;
+ 
+-	if (num_regions > 1 && rw != WRITE) {
++	if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
+ 		WARN_ON(1);
+ 		return -EIO;
+ 	}
+ 
+-	io.error = 0;
++	io.error_bits = 0;
+ 	atomic_set(&io.count, 1); /* see dispatch_io() */
+ 	io.sleeper = current;
+ 	io.client = client;
+@@ -378,25 +379,25 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
+ 		return -EINTR;
+ 
+ 	if (error_bits)
+-		*error_bits = io.error;
++		*error_bits = io.error_bits;
+ 
+-	return io.error ? -EIO : 0;
++	return io.error_bits ? -EIO : 0;
+ }
+ 
+ static int async_io(struct dm_io_client *client, unsigned int num_regions,
+-		    struct io_region *where, int rw, struct dpages *dp,
++		    struct dm_io_region *where, int rw, struct dpages *dp,
+ 		    io_notify_fn fn, void *context)
+ {
+ 	struct io *io;
+ 
+-	if (num_regions > 1 && rw != WRITE) {
++	if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
+ 		WARN_ON(1);
+ 		fn(1, context);
+ 		return -EIO;
+ 	}
+ 
+ 	io = mempool_alloc(client->pool, GFP_NOIO);
+-	io->error = 0;
++	io->error_bits = 0;
+ 	atomic_set(&io->count, 1); /* see dispatch_io() */
+ 	io->sleeper = NULL;
+ 	io->client = client;
+@@ -435,10 +436,15 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp)
+ }
+ 
+ /*
+- * New collapsed (a)synchronous interface
++ * New collapsed (a)synchronous interface.
++ *
++ * If the IO is asynchronous (i.e. it has notify.fn), you must either unplug
++ * the queue with blk_unplug() some time later or set the BIO_RW_SYNC bit in
++ * io_req->bi_rw. If you fail to do one of these, the IO will be submitted to
++ * the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c.
+  */
+ int dm_io(struct dm_io_request *io_req, unsigned num_regions,
+-	  struct io_region *where, unsigned long *sync_error_bits)
++	  struct dm_io_region *where, unsigned long *sync_error_bits)
+ {
+ 	int r;
+ 	struct dpages dp;
+diff --git a/drivers/md/dm-io.h b/drivers/md/dm-io.h
+deleted file mode 100644
+index f647e2c..0000000
+--- a/drivers/md/dm-io.h
++++ /dev/null
+@@ -1,79 +0,0 @@
+-/*
+- * Copyright (C) 2003 Sistina Software
+- *
+- * This file is released under the GPL.
+- */
+-
+-#ifndef _DM_IO_H
+-#define _DM_IO_H
+-
+-#include "dm.h"
+-
+-struct io_region {
+-	struct block_device *bdev;
+-	sector_t sector;
+-	sector_t count;		/* If this is zero the region is ignored. */
+-};
+-
+-struct page_list {
+-	struct page_list *next;
+-	struct page *page;
+-};
+-
+-typedef void (*io_notify_fn)(unsigned long error, void *context);
+-
+-enum dm_io_mem_type {
+-	DM_IO_PAGE_LIST,/* Page list */
+-	DM_IO_BVEC,	/* Bio vector */
+-	DM_IO_VMA,	/* Virtual memory area */
+-	DM_IO_KMEM,	/* Kernel memory */
+-};
+-
+-struct dm_io_memory {
+-	enum dm_io_mem_type type;
+-
+-	union {
+-		struct page_list *pl;
+-		struct bio_vec *bvec;
+-		void *vma;
+-		void *addr;
+-	} ptr;
+-
+-	unsigned offset;
+-};
+-
+-struct dm_io_notify {
+-	io_notify_fn fn;	/* Callback for asynchronous requests */
+-	void *context;		/* Passed to callback */
+-};
+-
+-/*
+- * IO request structure
+- */
+-struct dm_io_client;
+-struct dm_io_request {
+-	int bi_rw;			/* READ|WRITE - not READA */
+-	struct dm_io_memory mem;	/* Memory to use for io */
+-	struct dm_io_notify notify;	/* Synchronous if notify.fn is NULL */
+-	struct dm_io_client *client;	/* Client memory handler */
+-};
+-
+-/*
+- * For async io calls, users can alternatively use the dm_io() function below
+- * and dm_io_client_create() to create private mempools for the client.
+- *
+- * Create/destroy may block.
+- */
+-struct dm_io_client *dm_io_client_create(unsigned num_pages);
+-int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client);
+-void dm_io_client_destroy(struct dm_io_client *client);
+-
+-/*
+- * IO interface using private per-client pools.
+- * Each bit in the optional 'sync_error_bits' bitset indicates whether an
+- * error occurred doing io to the corresponding region.
+- */
+-int dm_io(struct dm_io_request *io_req, unsigned num_regions,
+-	  struct io_region *region, unsigned long *sync_error_bits);
+-
+-#endif
+diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
+new file mode 100644
+index 0000000..996802b
+--- /dev/null
++++ b/drivers/md/dm-kcopyd.c
+@@ -0,0 +1,654 @@
++/*
++ * Copyright (C) 2002 Sistina Software (UK) Limited.
++ * Copyright (C) 2006 Red Hat GmbH
++ *
++ * This file is released under the GPL.
++ *
++ * Kcopyd provides a simple interface for copying an area of one
++ * block-device to one or more other block-devices, with an asynchronous
++ * completion notification.
++ */
++
++#include <linux/types.h>
++#include <asm/atomic.h>
++#include <linux/blkdev.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/mempool.h>
++#include <linux/module.h>
++#include <linux/pagemap.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/workqueue.h>
++#include <linux/mutex.h>
++#include <linux/dm-kcopyd.h>
++
++#include "dm.h"
++
++/*-----------------------------------------------------------------
++ * Each kcopyd client has its own little pool of preallocated
++ * pages for kcopyd io.
++ *---------------------------------------------------------------*/
++struct dm_kcopyd_client {
++	spinlock_t lock;
++	struct page_list *pages;
++	unsigned int nr_pages;
++	unsigned int nr_free_pages;
++
++	struct dm_io_client *io_client;
++
++	wait_queue_head_t destroyq;
++	atomic_t nr_jobs;
++
++	mempool_t *job_pool;
++
++	struct workqueue_struct *kcopyd_wq;
++	struct work_struct kcopyd_work;
++
++/*
++ * We maintain three lists of jobs:
++ *
++ * i)   jobs waiting for pages
++ * ii)  jobs that have pages, and are waiting for the io to be issued.
++ * iii) jobs that have completed.
++ *
++ * All three of these are protected by job_lock.
++ */
++	spinlock_t job_lock;
++	struct list_head complete_jobs;
++	struct list_head io_jobs;
++	struct list_head pages_jobs;
++};
++
++static void wake(struct dm_kcopyd_client *kc)
++{
++	queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
++}
++
++static struct page_list *alloc_pl(void)
++{
++	struct page_list *pl;
++
++	pl = kmalloc(sizeof(*pl), GFP_KERNEL);
++	if (!pl)
++		return NULL;
++
++	pl->page = alloc_page(GFP_KERNEL);
++	if (!pl->page) {
++		kfree(pl);
++		return NULL;
++	}
++
++	return pl;
++}
++
++static void free_pl(struct page_list *pl)
++{
++	__free_page(pl->page);
++	kfree(pl);
++}
++
++static int kcopyd_get_pages(struct dm_kcopyd_client *kc,
++			    unsigned int nr, struct page_list **pages)
++{
++	struct page_list *pl;
++
++	spin_lock(&kc->lock);
++	if (kc->nr_free_pages < nr) {
++		spin_unlock(&kc->lock);
++		return -ENOMEM;
++	}
++
++	kc->nr_free_pages -= nr;
++	for (*pages = pl = kc->pages; --nr; pl = pl->next)
++		;
++
++	kc->pages = pl->next;
++	pl->next = NULL;
++
++	spin_unlock(&kc->lock);
++
++	return 0;
++}
++
++static void kcopyd_put_pages(struct dm_kcopyd_client *kc, struct page_list *pl)
++{
++	struct page_list *cursor;
++
++	spin_lock(&kc->lock);
++	for (cursor = pl; cursor->next; cursor = cursor->next)
++		kc->nr_free_pages++;
++
++	kc->nr_free_pages++;
++	cursor->next = kc->pages;
++	kc->pages = pl;
++	spin_unlock(&kc->lock);
++}
++
++/*
++ * These three functions resize the page pool.
++ */
++static void drop_pages(struct page_list *pl)
++{
++	struct page_list *next;
++
++	while (pl) {
++		next = pl->next;
++		free_pl(pl);
++		pl = next;
++	}
++}
++
++static int client_alloc_pages(struct dm_kcopyd_client *kc, unsigned int nr)
++{
++	unsigned int i;
++	struct page_list *pl = NULL, *next;
++
++	for (i = 0; i < nr; i++) {
++		next = alloc_pl();
++		if (!next) {
++			if (pl)
++				drop_pages(pl);
++			return -ENOMEM;
++		}
++		next->next = pl;
++		pl = next;
++	}
++
++	kcopyd_put_pages(kc, pl);
++	kc->nr_pages += nr;
++	return 0;
++}
++
++static void client_free_pages(struct dm_kcopyd_client *kc)
++{
++	BUG_ON(kc->nr_free_pages != kc->nr_pages);
++	drop_pages(kc->pages);
++	kc->pages = NULL;
++	kc->nr_free_pages = kc->nr_pages = 0;
++}
++
++/*-----------------------------------------------------------------
++ * kcopyd_jobs need to be allocated by the *clients* of kcopyd,
++ * for this reason we use a mempool to prevent the client from
++ * ever having to do io (which could cause a deadlock).
++ *---------------------------------------------------------------*/
++struct kcopyd_job {
++	struct dm_kcopyd_client *kc;
++	struct list_head list;
++	unsigned long flags;
++
++	/*
++	 * Error state of the job.
++	 */
++	int read_err;
++	unsigned long write_err;
++
++	/*
++	 * Either READ or WRITE
++	 */
++	int rw;
++	struct dm_io_region source;
++
++	/*
++	 * The destinations for the transfer.
++	 */
++	unsigned int num_dests;
++	struct dm_io_region dests[DM_KCOPYD_MAX_REGIONS];
++
++	sector_t offset;
++	unsigned int nr_pages;
++	struct page_list *pages;
++
++	/*
++	 * Set this to ensure you are notified when the job has
++	 * completed.  'context' is for callback to use.
++	 */
++	dm_kcopyd_notify_fn fn;
++	void *context;
++
++	/*
++	 * These fields are only used if the job has been split
++	 * into more manageable parts.
++	 */
++	struct mutex lock;
++	atomic_t sub_jobs;
++	sector_t progress;
++};
++
++/* FIXME: this should scale with the number of pages */
++#define MIN_JOBS 512
++
++static struct kmem_cache *_job_cache;
++
++int __init dm_kcopyd_init(void)
++{
++	_job_cache = KMEM_CACHE(kcopyd_job, 0);
++	if (!_job_cache)
++		return -ENOMEM;
++
++	return 0;
++}
++
++void dm_kcopyd_exit(void)
++{
++	kmem_cache_destroy(_job_cache);
++	_job_cache = NULL;
++}
++
++/*
++ * Functions to push and pop a job onto the head of a given job
++ * list.
++ */
++static struct kcopyd_job *pop(struct list_head *jobs,
++			      struct dm_kcopyd_client *kc)
++{
++	struct kcopyd_job *job = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&kc->job_lock, flags);
++
++	if (!list_empty(jobs)) {
++		job = list_entry(jobs->next, struct kcopyd_job, list);
++		list_del(&job->list);
++	}
++	spin_unlock_irqrestore(&kc->job_lock, flags);
++
++	return job;
++}
++
++static void push(struct list_head *jobs, struct kcopyd_job *job)
++{
++	unsigned long flags;
++	struct dm_kcopyd_client *kc = job->kc;
++
++	spin_lock_irqsave(&kc->job_lock, flags);
++	list_add_tail(&job->list, jobs);
++	spin_unlock_irqrestore(&kc->job_lock, flags);
++}
++
++/*
++ * These three functions process 1 item from the corresponding
++ * job list.
++ *
++ * They return:
++ * < 0: error
++ *   0: success
++ * > 0: can't process yet.
++ */
++static int run_complete_job(struct kcopyd_job *job)
++{
++	void *context = job->context;
++	int read_err = job->read_err;
++	unsigned long write_err = job->write_err;
++	dm_kcopyd_notify_fn fn = job->fn;
++	struct dm_kcopyd_client *kc = job->kc;
++
++	kcopyd_put_pages(kc, job->pages);
++	mempool_free(job, kc->job_pool);
++	fn(read_err, write_err, context);
++
++	if (atomic_dec_and_test(&kc->nr_jobs))
++		wake_up(&kc->destroyq);
++
++	return 0;
++}
++
++static void complete_io(unsigned long error, void *context)
++{
++	struct kcopyd_job *job = (struct kcopyd_job *) context;
++	struct dm_kcopyd_client *kc = job->kc;
++
++	if (error) {
++		if (job->rw == WRITE)
++			job->write_err |= error;
++		else
++			job->read_err = 1;
++
++		if (!test_bit(DM_KCOPYD_IGNORE_ERROR, &job->flags)) {
++			push(&kc->complete_jobs, job);
++			wake(kc);
++			return;
++		}
++	}
++
++	if (job->rw == WRITE)
++		push(&kc->complete_jobs, job);
++
++	else {
++		job->rw = WRITE;
++		push(&kc->io_jobs, job);
++	}
++
++	wake(kc);
++}
++
++/*
++ * Request io on as many buffer heads as we can currently get for
++ * a particular job.
++ */
++static int run_io_job(struct kcopyd_job *job)
++{
++	int r;
++	struct dm_io_request io_req = {
++		.bi_rw = job->rw | (1 << BIO_RW_SYNC),
++		.mem.type = DM_IO_PAGE_LIST,
++		.mem.ptr.pl = job->pages,
++		.mem.offset = job->offset,
++		.notify.fn = complete_io,
++		.notify.context = job,
++		.client = job->kc->io_client,
++	};
++
++	if (job->rw == READ)
++		r = dm_io(&io_req, 1, &job->source, NULL);
++	else
++		r = dm_io(&io_req, job->num_dests, job->dests, NULL);
++
++	return r;
++}
++
++static int run_pages_job(struct kcopyd_job *job)
++{
++	int r;
++
++	job->nr_pages = dm_div_up(job->dests[0].count + job->offset,
++				  PAGE_SIZE >> 9);
++	r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages);
++	if (!r) {
++		/* this job is ready for io */
++		push(&job->kc->io_jobs, job);
++		return 0;
++	}
++
++	if (r == -ENOMEM)
++		/* can't complete now */
++		return 1;
++
++	return r;
++}
++
++/*
++ * Run through a list for as long as possible.  Returns the count
++ * of successful jobs.
++ */
++static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
++			int (*fn) (struct kcopyd_job *))
++{
++	struct kcopyd_job *job;
++	int r, count = 0;
++
++	while ((job = pop(jobs, kc))) {
++
++		r = fn(job);
++
++		if (r < 0) {
++			/* error this rogue job */
++			if (job->rw == WRITE)
++				job->write_err = (unsigned long) -1L;
++			else
++				job->read_err = 1;
++			push(&kc->complete_jobs, job);
++			break;
++		}
++
++		if (r > 0) {
++			/*
++			 * We couldn't service this job ATM, so
++			 * push this job back onto the list.
++			 */
++			push(jobs, job);
++			break;
++		}
++
++		count++;
++	}
++
++	return count;
++}
++
++/*
++ * kcopyd does this every time it's woken up.
++ */
++static void do_work(struct work_struct *work)
++{
++	struct dm_kcopyd_client *kc = container_of(work,
++					struct dm_kcopyd_client, kcopyd_work);
++
++	/*
++	 * The order that these are called is *very* important.
++	 * complete jobs can free some pages for pages jobs.
++	 * Pages jobs when successful will jump onto the io jobs
++	 * list.  io jobs call wake when they complete and it all
++	 * starts again.
++	 */
++	process_jobs(&kc->complete_jobs, kc, run_complete_job);
++	process_jobs(&kc->pages_jobs, kc, run_pages_job);
++	process_jobs(&kc->io_jobs, kc, run_io_job);
++}
++
++/*
++ * If we are copying a small region we just dispatch a single job
++ * to do the copy, otherwise the io has to be split up into many
++ * jobs.
++ */
++static void dispatch_job(struct kcopyd_job *job)
++{
++	struct dm_kcopyd_client *kc = job->kc;
++	atomic_inc(&kc->nr_jobs);
++	push(&kc->pages_jobs, job);
++	wake(kc);
++}
++
++#define SUB_JOB_SIZE 128
++static void segment_complete(int read_err, unsigned long write_err,
++			     void *context)
++{
++	/* FIXME: tidy this function */
++	sector_t progress = 0;
++	sector_t count = 0;
++	struct kcopyd_job *job = (struct kcopyd_job *) context;
++
++	mutex_lock(&job->lock);
++
++	/* update the error */
++	if (read_err)
++		job->read_err = 1;
++
++	if (write_err)
++		job->write_err |= write_err;
++
++	/*
++	 * Only dispatch more work if there hasn't been an error.
++	 */
++	if ((!job->read_err && !job->write_err) ||
++	    test_bit(DM_KCOPYD_IGNORE_ERROR, &job->flags)) {
++		/* get the next chunk of work */
++		progress = job->progress;
++		count = job->source.count - progress;
++		if (count) {
++			if (count > SUB_JOB_SIZE)
++				count = SUB_JOB_SIZE;
++
++			job->progress += count;
++		}
++	}
++	mutex_unlock(&job->lock);
++
++	if (count) {
++		int i;
++		struct kcopyd_job *sub_job = mempool_alloc(job->kc->job_pool,
++							   GFP_NOIO);
++
++		*sub_job = *job;
++		sub_job->source.sector += progress;
++		sub_job->source.count = count;
++
++		for (i = 0; i < job->num_dests; i++) {
++			sub_job->dests[i].sector += progress;
++			sub_job->dests[i].count = count;
++		}
++
++		sub_job->fn = segment_complete;
++		sub_job->context = job;
++		dispatch_job(sub_job);
++
++	} else if (atomic_dec_and_test(&job->sub_jobs)) {
++
++		/*
++		 * To avoid a race we must keep the job around
++		 * until after the notify function has completed.
++		 * Otherwise the client may try and stop the job
++		 * after we've completed.
++		 */
++		job->fn(read_err, write_err, job->context);
++		mempool_free(job, job->kc->job_pool);
++	}
++}
++
++/*
++ * Create some little jobs that will do the move between
++ * them.
++ */
++#define SPLIT_COUNT 8
++static void split_job(struct kcopyd_job *job)
++{
++	int i;
++
++	atomic_set(&job->sub_jobs, SPLIT_COUNT);
++	for (i = 0; i < SPLIT_COUNT; i++)
++		segment_complete(0, 0u, job);
++}
++
++int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
++		   unsigned int num_dests, struct dm_io_region *dests,
++		   unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
++{
++	struct kcopyd_job *job;
++
++	/*
++	 * Allocate a new job.
++	 */
++	job = mempool_alloc(kc->job_pool, GFP_NOIO);
++
++	/*
++	 * set up for the read.
++	 */
++	job->kc = kc;
++	job->flags = flags;
++	job->read_err = 0;
++	job->write_err = 0;
++	job->rw = READ;
++
++	job->source = *from;
++
++	job->num_dests = num_dests;
++	memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
++
++	job->offset = 0;
++	job->nr_pages = 0;
++	job->pages = NULL;
++
++	job->fn = fn;
++	job->context = context;
++
++	if (job->source.count < SUB_JOB_SIZE)
++		dispatch_job(job);
++
++	else {
++		mutex_init(&job->lock);
++		job->progress = 0;
++		split_job(job);
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL(dm_kcopyd_copy);
++
++/*
++ * Cancels a kcopyd job, eg. someone might be deactivating a
++ * mirror.
++ */
++#if 0
++int kcopyd_cancel(struct kcopyd_job *job, int block)
++{
++	/* FIXME: finish */
++	return -1;
++}
++#endif  /*  0  */
++
++/*-----------------------------------------------------------------
++ * Client setup
++ *---------------------------------------------------------------*/
++int dm_kcopyd_client_create(unsigned int nr_pages,
++			    struct dm_kcopyd_client **result)
++{
++	int r = -ENOMEM;
++	struct dm_kcopyd_client *kc;
++
++	kc = kmalloc(sizeof(*kc), GFP_KERNEL);
++	if (!kc)
++		return -ENOMEM;
++
++	spin_lock_init(&kc->lock);
++	spin_lock_init(&kc->job_lock);
++	INIT_LIST_HEAD(&kc->complete_jobs);
++	INIT_LIST_HEAD(&kc->io_jobs);
++	INIT_LIST_HEAD(&kc->pages_jobs);
++
++	kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
++	if (!kc->job_pool)
++		goto bad_slab;
++
++	INIT_WORK(&kc->kcopyd_work, do_work);
++	kc->kcopyd_wq = create_singlethread_workqueue("kcopyd");
++	if (!kc->kcopyd_wq)
++		goto bad_workqueue;
++
++	kc->pages = NULL;
++	kc->nr_pages = kc->nr_free_pages = 0;
++	r = client_alloc_pages(kc, nr_pages);
++	if (r)
++		goto bad_client_pages;
++
++	kc->io_client = dm_io_client_create(nr_pages);
++	if (IS_ERR(kc->io_client)) {
++		r = PTR_ERR(kc->io_client);
++		goto bad_io_client;
++	}
++
++	init_waitqueue_head(&kc->destroyq);
++	atomic_set(&kc->nr_jobs, 0);
++
++	*result = kc;
++	return 0;
++
++bad_io_client:
++	client_free_pages(kc);
++bad_client_pages:
++	destroy_workqueue(kc->kcopyd_wq);
++bad_workqueue:
++	mempool_destroy(kc->job_pool);
++bad_slab:
++	kfree(kc);
++
++	return r;
++}
++EXPORT_SYMBOL(dm_kcopyd_client_create);
++
++void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc)
++{
++	/* Wait for completion of all jobs submitted by this client. */
++	wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
++
++	BUG_ON(!list_empty(&kc->complete_jobs));
++	BUG_ON(!list_empty(&kc->io_jobs));
++	BUG_ON(!list_empty(&kc->pages_jobs));
++	destroy_workqueue(kc->kcopyd_wq);
++	dm_io_client_destroy(kc->io_client);
++	client_free_pages(kc);
++	mempool_destroy(kc->job_pool);
++	kfree(kc);
++}
++EXPORT_SYMBOL(dm_kcopyd_client_destroy);
+diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
+index 2a74b21..67a6f31 100644
+--- a/drivers/md/dm-log.c
++++ b/drivers/md/dm-log.c
+@@ -1,5 +1,6 @@
+ /*
+  * Copyright (C) 2003 Sistina Software
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+  *
+  * This file is released under the LGPL.
+  */
+@@ -8,64 +9,58 @@
+ #include <linux/slab.h>
+ #include <linux/module.h>
+ #include <linux/vmalloc.h>
++#include <linux/dm-io.h>
++#include <linux/dm-dirty-log.h>
+ 
+-#include "dm-log.h"
+-#include "dm-io.h"
++#include "dm.h"
+ 
+-#define DM_MSG_PREFIX "mirror log"
++#define DM_MSG_PREFIX "dirty region log"
+ 
+-static LIST_HEAD(_log_types);
+-static DEFINE_SPINLOCK(_lock);
++struct dm_dirty_log_internal {
++	struct dm_dirty_log_type *type;
+ 
+-int dm_register_dirty_log_type(struct dirty_log_type *type)
+-{
+-	spin_lock(&_lock);
+-	type->use_count = 0;
+-	list_add(&type->list, &_log_types);
+-	spin_unlock(&_lock);
++	struct list_head list;
++	long use;
++};
+ 
+-	return 0;
+-}
++static LIST_HEAD(_log_types);
++static DEFINE_SPINLOCK(_lock);
+ 
+-int dm_unregister_dirty_log_type(struct dirty_log_type *type)
++static struct dm_dirty_log_internal *__find_dirty_log_type(const char *name)
+ {
+-	spin_lock(&_lock);
+-
+-	if (type->use_count)
+-		DMWARN("Attempt to unregister a log type that is still in use");
+-	else
+-		list_del(&type->list);
++	struct dm_dirty_log_internal *log_type;
+ 
+-	spin_unlock(&_lock);
++	list_for_each_entry(log_type, &_log_types, list)
++		if (!strcmp(name, log_type->type->name))
++			return log_type;
+ 
+-	return 0;
++	return NULL;
+ }
+ 
+-static struct dirty_log_type *_get_type(const char *type_name)
++static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name)
+ {
+-	struct dirty_log_type *type;
++	struct dm_dirty_log_internal *log_type;
+ 
+ 	spin_lock(&_lock);
+-	list_for_each_entry (type, &_log_types, list)
+-		if (!strcmp(type_name, type->name)) {
+-			if (!type->use_count && !try_module_get(type->module)){
+-				spin_unlock(&_lock);
+-				return NULL;
+-			}
+-			type->use_count++;
+-			spin_unlock(&_lock);
+-			return type;
+-		}
++
++	log_type = __find_dirty_log_type(name);
++	if (log_type) {
++		if (!log_type->use && !try_module_get(log_type->type->module))
++			log_type = NULL;
++		else
++			log_type->use++;
++	}
+ 
+ 	spin_unlock(&_lock);
+-	return NULL;
++
++	return log_type;
+ }
+ 
+ /*
+  * get_type
+  * @type_name
+  *
+- * Attempt to retrieve the dirty_log_type by name.  If not already
++ * Attempt to retrieve the dm_dirty_log_type by name.  If not already
+  * available, attempt to load the appropriate module.
+  *
+  * Log modules are named "dm-log-" followed by the 'type_name'.
+@@ -78,14 +73,17 @@ static struct dirty_log_type *_get_type(const char *type_name)
+  *
+  * Returns: dirty_log_type* on success, NULL on failure
+  */
+-static struct dirty_log_type *get_type(const char *type_name)
++static struct dm_dirty_log_type *get_type(const char *type_name)
+ {
+ 	char *p, *type_name_dup;
+-	struct dirty_log_type *type;
++	struct dm_dirty_log_internal *log_type;
++
++	if (!type_name)
++		return NULL;
+ 
+-	type = _get_type(type_name);
+-	if (type)
+-		return type;
++	log_type = _get_dirty_log_type(type_name);
++	if (log_type)
++		return log_type->type;
+ 
+ 	type_name_dup = kstrdup(type_name, GFP_KERNEL);
+ 	if (!type_name_dup) {
+@@ -95,34 +93,106 @@ static struct dirty_log_type *get_type(const char *type_name)
+ 	}
+ 
+ 	while (request_module("dm-log-%s", type_name_dup) ||
+-	       !(type = _get_type(type_name))) {
++	       !(log_type = _get_dirty_log_type(type_name))) {
+ 		p = strrchr(type_name_dup, '-');
+ 		if (!p)
+ 			break;
+ 		p[0] = '\0';
+ 	}
+ 
+-	if (!type)
++	if (!log_type)
+ 		DMWARN("Module for logging type \"%s\" not found.", type_name);
+ 
+ 	kfree(type_name_dup);
+ 
+-	return type;
++	return log_type ? log_type->type : NULL;
+ }
+ 
+-static void put_type(struct dirty_log_type *type)
++static void put_type(struct dm_dirty_log_type *type)
+ {
++	struct dm_dirty_log_internal *log_type;
++
++	if (!type)
++		return;
++
+ 	spin_lock(&_lock);
+-	if (!--type->use_count)
++	log_type = __find_dirty_log_type(type->name);
++	if (!log_type)
++		goto out;
++
++	if (!--log_type->use)
+ 		module_put(type->module);
++
++	BUG_ON(log_type->use < 0);
++
++out:
+ 	spin_unlock(&_lock);
+ }
+ 
+-struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
+-				      unsigned int argc, char **argv)
++static struct dm_dirty_log_internal *_alloc_dirty_log_type(struct dm_dirty_log_type *type)
+ {
+-	struct dirty_log_type *type;
+-	struct dirty_log *log;
++	struct dm_dirty_log_internal *log_type = kzalloc(sizeof(*log_type),
++							 GFP_KERNEL);
++
++	if (log_type)
++		log_type->type = type;
++
++	return log_type;
++}
++
++int dm_dirty_log_type_register(struct dm_dirty_log_type *type)
++{
++	struct dm_dirty_log_internal *log_type = _alloc_dirty_log_type(type);
++	int r = 0;
++
++	if (!log_type)
++		return -ENOMEM;
++
++	spin_lock(&_lock);
++	if (!__find_dirty_log_type(type->name))
++		list_add(&log_type->list, &_log_types);
++	else {
++		kfree(log_type);
++		r = -EEXIST;
++	}
++	spin_unlock(&_lock);
++
++	return r;
++}
++EXPORT_SYMBOL(dm_dirty_log_type_register);
++
++int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type)
++{
++	struct dm_dirty_log_internal *log_type;
++
++	spin_lock(&_lock);
++
++	log_type = __find_dirty_log_type(type->name);
++	if (!log_type) {
++		spin_unlock(&_lock);
++		return -EINVAL;
++	}
++
++	if (log_type->use) {
++		spin_unlock(&_lock);
++		return -ETXTBSY;
++	}
++
++	list_del(&log_type->list);
++
++	spin_unlock(&_lock);
++	kfree(log_type);
++
++	return 0;
++}
++EXPORT_SYMBOL(dm_dirty_log_type_unregister);
++
++struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
++					 struct dm_target *ti,
++					 unsigned int argc, char **argv)
++{
++	struct dm_dirty_log_type *type;
++	struct dm_dirty_log *log;
+ 
+ 	log = kmalloc(sizeof(*log), GFP_KERNEL);
+ 	if (!log)
+@@ -143,13 +213,15 @@ struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *t
+ 
+ 	return log;
+ }
++EXPORT_SYMBOL(dm_dirty_log_create);
+ 
+-void dm_destroy_dirty_log(struct dirty_log *log)
++void dm_dirty_log_destroy(struct dm_dirty_log *log)
+ {
+ 	log->type->dtr(log);
+ 	put_type(log->type);
+ 	kfree(log);
+ }
++EXPORT_SYMBOL(dm_dirty_log_destroy);
+ 
+ /*-----------------------------------------------------------------
+  * Persistent and core logs share a lot of their implementation.
+@@ -207,7 +279,7 @@ struct log_c {
+ 	struct dm_dev *log_dev;
+ 	struct log_header header;
+ 
+-	struct io_region header_location;
++	struct dm_io_region header_location;
+ 	struct log_header *disk_header;
+ };
+ 
+@@ -215,7 +287,7 @@ struct log_c {
+  * The touched member needs to be updated every time we access
+  * one of the bitsets.
+  */
+-static  inline int log_test_bit(uint32_t *bs, unsigned bit)
++static inline int log_test_bit(uint32_t *bs, unsigned bit)
+ {
+ 	return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0;
+ }
+@@ -302,7 +374,7 @@ static inline int write_header(struct log_c *log)
+  * argv contains region_size followed optionally by [no]sync
+  *--------------------------------------------------------------*/
+ #define BYTE_SHIFT 3
+-static int create_log_context(struct dirty_log *log, struct dm_target *ti,
++static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
+ 			      unsigned int argc, char **argv,
+ 			      struct dm_dev *dev)
+ {
+@@ -315,7 +387,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+ 	int r;
+ 
+ 	if (argc < 1 || argc > 2) {
+-		DMWARN("wrong number of arguments to mirror log");
++		DMWARN("wrong number of arguments to dirty region log");
+ 		return -EINVAL;
+ 	}
+ 
+@@ -325,8 +397,8 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+ 		else if (!strcmp(argv[1], "nosync"))
+ 			sync = NOSYNC;
+ 		else {
+-			DMWARN("unrecognised sync argument to mirror log: %s",
+-			       argv[1]);
++			DMWARN("unrecognised sync argument to "
++			       "dirty region log: %s", argv[1]);
+ 			return -EINVAL;
+ 		}
+ 	}
+@@ -434,7 +506,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+ 	return 0;
+ }
+ 
+-static int core_ctr(struct dirty_log *log, struct dm_target *ti,
++static int core_ctr(struct dm_dirty_log *log, struct dm_target *ti,
+ 		    unsigned int argc, char **argv)
+ {
+ 	return create_log_context(log, ti, argc, argv, NULL);
+@@ -447,7 +519,7 @@ static void destroy_log_context(struct log_c *lc)
+ 	kfree(lc);
+ }
+ 
+-static void core_dtr(struct dirty_log *log)
++static void core_dtr(struct dm_dirty_log *log)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+ 
+@@ -460,14 +532,14 @@ static void core_dtr(struct dirty_log *log)
+  *
+  * argv contains log_device region_size followed optionally by [no]sync
+  *--------------------------------------------------------------*/
+-static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
++static int disk_ctr(struct dm_dirty_log *log, struct dm_target *ti,
+ 		    unsigned int argc, char **argv)
+ {
+ 	int r;
+ 	struct dm_dev *dev;
+ 
+ 	if (argc < 2 || argc > 3) {
+-		DMWARN("wrong number of arguments to disk mirror log");
++		DMWARN("wrong number of arguments to disk dirty region log");
+ 		return -EINVAL;
+ 	}
+ 
+@@ -485,7 +557,7 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
+ 	return 0;
+ }
+ 
+-static void disk_dtr(struct dirty_log *log)
++static void disk_dtr(struct dm_dirty_log *log)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+ 
+@@ -514,7 +586,7 @@ static void fail_log_device(struct log_c *lc)
+ 	dm_table_event(lc->ti->table);
+ }
+ 
+-static int disk_resume(struct dirty_log *log)
++static int disk_resume(struct dm_dirty_log *log)
+ {
+ 	int r;
+ 	unsigned i;
+@@ -524,7 +596,7 @@ static int disk_resume(struct dirty_log *log)
+ 	/* read the disk header */
+ 	r = read_header(lc);
+ 	if (r) {
+-		DMWARN("%s: Failed to read header on mirror log device",
++		DMWARN("%s: Failed to read header on dirty region log device",
+ 		       lc->log_dev->name);
+ 		fail_log_device(lc);
+ 		/*
+@@ -562,7 +634,7 @@ static int disk_resume(struct dirty_log *log)
+ 	/* write the new header */
+ 	r = write_header(lc);
+ 	if (r) {
+-		DMWARN("%s: Failed to write header on mirror log device",
++		DMWARN("%s: Failed to write header on dirty region log device",
+ 		       lc->log_dev->name);
+ 		fail_log_device(lc);
+ 	}
+@@ -570,38 +642,38 @@ static int disk_resume(struct dirty_log *log)
+ 	return r;
+ }
+ 
+-static uint32_t core_get_region_size(struct dirty_log *log)
++static uint32_t core_get_region_size(struct dm_dirty_log *log)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+ 	return lc->region_size;
+ }
+ 
+-static int core_resume(struct dirty_log *log)
++static int core_resume(struct dm_dirty_log *log)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+ 	lc->sync_search = 0;
+ 	return 0;
+ }
+ 
+-static int core_is_clean(struct dirty_log *log, region_t region)
++static int core_is_clean(struct dm_dirty_log *log, region_t region)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+ 	return log_test_bit(lc->clean_bits, region);
+ }
+ 
+-static int core_in_sync(struct dirty_log *log, region_t region, int block)
++static int core_in_sync(struct dm_dirty_log *log, region_t region, int block)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+ 	return log_test_bit(lc->sync_bits, region);
+ }
+ 
+-static int core_flush(struct dirty_log *log)
++static int core_flush(struct dm_dirty_log *log)
+ {
+ 	/* no op */
+ 	return 0;
+ }
+ 
+-static int disk_flush(struct dirty_log *log)
++static int disk_flush(struct dm_dirty_log *log)
+ {
+ 	int r;
+ 	struct log_c *lc = (struct log_c *) log->context;
+@@ -619,19 +691,19 @@ static int disk_flush(struct dirty_log *log)
+ 	return r;
+ }
+ 
+-static void core_mark_region(struct dirty_log *log, region_t region)
++static void core_mark_region(struct dm_dirty_log *log, region_t region)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+ 	log_clear_bit(lc, lc->clean_bits, region);
+ }
+ 
+-static void core_clear_region(struct dirty_log *log, region_t region)
++static void core_clear_region(struct dm_dirty_log *log, region_t region)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+ 	log_set_bit(lc, lc->clean_bits, region);
+ }
+ 
+-static int core_get_resync_work(struct dirty_log *log, region_t *region)
++static int core_get_resync_work(struct dm_dirty_log *log, region_t *region)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+ 
+@@ -654,7 +726,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
+ 	return 1;
+ }
+ 
+-static void core_set_region_sync(struct dirty_log *log, region_t region,
++static void core_set_region_sync(struct dm_dirty_log *log, region_t region,
+ 				 int in_sync)
+ {
+ 	struct log_c *lc = (struct log_c *) log->context;
+@@ -669,7 +741,7 @@ static void core_set_region_sync(struct dirty_log *log, region_t region,
+ 	}
+ }
+ 
+-static region_t core_get_sync_count(struct dirty_log *log)
++static region_t core_get_sync_count(struct dm_dirty_log *log)
+ {
+         struct log_c *lc = (struct log_c *) log->context;
+ 
+@@ -680,7 +752,7 @@ static region_t core_get_sync_count(struct dirty_log *log)
+ 	if (lc->sync != DEFAULTSYNC) \
+ 		DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "")
+ 
+-static int core_status(struct dirty_log *log, status_type_t status,
++static int core_status(struct dm_dirty_log *log, status_type_t status,
+ 		       char *result, unsigned int maxlen)
+ {
+ 	int sz = 0;
+@@ -700,7 +772,7 @@ static int core_status(struct dirty_log *log, status_type_t status,
+ 	return sz;
+ }
+ 
+-static int disk_status(struct dirty_log *log, status_type_t status,
++static int disk_status(struct dm_dirty_log *log, status_type_t status,
+ 		       char *result, unsigned int maxlen)
+ {
+ 	int sz = 0;
+@@ -722,7 +794,7 @@ static int disk_status(struct dirty_log *log, status_type_t status,
+ 	return sz;
+ }
+ 
+-static struct dirty_log_type _core_type = {
++static struct dm_dirty_log_type _core_type = {
+ 	.name = "core",
+ 	.module = THIS_MODULE,
+ 	.ctr = core_ctr,
+@@ -740,7 +812,7 @@ static struct dirty_log_type _core_type = {
+ 	.status = core_status,
+ };
+ 
+-static struct dirty_log_type _disk_type = {
++static struct dm_dirty_log_type _disk_type = {
+ 	.name = "disk",
+ 	.module = THIS_MODULE,
+ 	.ctr = disk_ctr,
+@@ -763,26 +835,28 @@ int __init dm_dirty_log_init(void)
+ {
+ 	int r;
+ 
+-	r = dm_register_dirty_log_type(&_core_type);
++	r = dm_dirty_log_type_register(&_core_type);
+ 	if (r)
+ 		DMWARN("couldn't register core log");
+ 
+-	r = dm_register_dirty_log_type(&_disk_type);
++	r = dm_dirty_log_type_register(&_disk_type);
+ 	if (r) {
+ 		DMWARN("couldn't register disk type");
+-		dm_unregister_dirty_log_type(&_core_type);
++		dm_dirty_log_type_unregister(&_core_type);
+ 	}
+ 
+ 	return r;
+ }
+ 
+-void dm_dirty_log_exit(void)
++void __exit dm_dirty_log_exit(void)
+ {
+-	dm_unregister_dirty_log_type(&_disk_type);
+-	dm_unregister_dirty_log_type(&_core_type);
++	dm_dirty_log_type_unregister(&_disk_type);
++	dm_dirty_log_type_unregister(&_core_type);
+ }
+ 
+-EXPORT_SYMBOL(dm_register_dirty_log_type);
+-EXPORT_SYMBOL(dm_unregister_dirty_log_type);
+-EXPORT_SYMBOL(dm_create_dirty_log);
+-EXPORT_SYMBOL(dm_destroy_dirty_log);
++module_init(dm_dirty_log_init);
++module_exit(dm_dirty_log_exit);
++
++MODULE_DESCRIPTION(DM_NAME " dirty region log");
++MODULE_AUTHOR("Joe Thornber, Heinz Mauelshagen <dm-devel at redhat.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h
+deleted file mode 100644
+index 3fae87e..0000000
+--- a/drivers/md/dm-log.h
++++ /dev/null
+@@ -1,131 +0,0 @@
+-/*
+- * Copyright (C) 2003 Sistina Software
+- *
+- * This file is released under the LGPL.
+- */
+-
+-#ifndef DM_DIRTY_LOG
+-#define DM_DIRTY_LOG
+-
+-#include "dm.h"
+-
+-typedef sector_t region_t;
+-
+-struct dirty_log_type;
+-
+-struct dirty_log {
+-	struct dirty_log_type *type;
+-	void *context;
+-};
+-
+-struct dirty_log_type {
+-	struct list_head list;
+-	const char *name;
+-	struct module *module;
+-	unsigned int use_count;
+-
+-	int (*ctr)(struct dirty_log *log, struct dm_target *ti,
+-		   unsigned int argc, char **argv);
+-	void (*dtr)(struct dirty_log *log);
+-
+-	/*
+-	 * There are times when we don't want the log to touch
+-	 * the disk.
+-	 */
+-	int (*presuspend)(struct dirty_log *log);
+-	int (*postsuspend)(struct dirty_log *log);
+-	int (*resume)(struct dirty_log *log);
+-
+-	/*
+-	 * Retrieves the smallest size of region that the log can
+-	 * deal with.
+-	 */
+-	uint32_t (*get_region_size)(struct dirty_log *log);
+-
+-        /*
+-	 * A predicate to say whether a region is clean or not.
+-	 * May block.
+-	 */
+-	int (*is_clean)(struct dirty_log *log, region_t region);
+-
+-	/*
+-	 *  Returns: 0, 1, -EWOULDBLOCK, < 0
+-	 *
+-	 * A predicate function to check the area given by
+-	 * [sector, sector + len) is in sync.
+-	 *
+-	 * If -EWOULDBLOCK is returned the state of the region is
+-	 * unknown, typically this will result in a read being
+-	 * passed to a daemon to deal with, since a daemon is
+-	 * allowed to block.
+-	 */
+-	int (*in_sync)(struct dirty_log *log, region_t region, int can_block);
+-
+-	/*
+-	 * Flush the current log state (eg, to disk).  This
+-	 * function may block.
+-	 */
+-	int (*flush)(struct dirty_log *log);
+-
+-	/*
+-	 * Mark an area as clean or dirty.  These functions may
+-	 * block, though for performance reasons blocking should
+-	 * be extremely rare (eg, allocating another chunk of
+-	 * memory for some reason).
+-	 */
+-	void (*mark_region)(struct dirty_log *log, region_t region);
+-	void (*clear_region)(struct dirty_log *log, region_t region);
+-
+-	/*
+-	 * Returns: <0 (error), 0 (no region), 1 (region)
+-	 *
+-	 * The mirrord will need perform recovery on regions of
+-	 * the mirror that are in the NOSYNC state.  This
+-	 * function asks the log to tell the caller about the
+-	 * next region that this machine should recover.
+-	 *
+-	 * Do not confuse this function with 'in_sync()', one
+-	 * tells you if an area is synchronised, the other
+-	 * assigns recovery work.
+-	*/
+-	int (*get_resync_work)(struct dirty_log *log, region_t *region);
+-
+-	/*
+-	 * This notifies the log that the resync status of a region
+-	 * has changed.  It also clears the region from the recovering
+-	 * list (if present).
+-	 */
+-	void (*set_region_sync)(struct dirty_log *log,
+-				region_t region, int in_sync);
+-
+-        /*
+-	 * Returns the number of regions that are in sync.
+-         */
+-        region_t (*get_sync_count)(struct dirty_log *log);
+-
+-	/*
+-	 * Support function for mirror status requests.
+-	 */
+-	int (*status)(struct dirty_log *log, status_type_t status_type,
+-		      char *result, unsigned int maxlen);
+-};
+-
+-int dm_register_dirty_log_type(struct dirty_log_type *type);
+-int dm_unregister_dirty_log_type(struct dirty_log_type *type);
+-
+-
+-/*
+- * Make sure you use these two functions, rather than calling
+- * type->constructor/destructor() directly.
+- */
+-struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
+-				      unsigned int argc, char **argv);
+-void dm_destroy_dirty_log(struct dirty_log *log);
+-
+-/*
+- * init/exit functions.
+- */
+-int dm_dirty_log_init(void);
+-void dm_dirty_log_exit(void);
+-
+-#endif
+diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
+index 762cb08..ff05fe8 100644
+--- a/drivers/md/dm-raid1.c
++++ b/drivers/md/dm-raid1.c
+@@ -7,9 +7,6 @@
+ #include "dm.h"
+ #include "dm-bio-list.h"
+ #include "dm-bio-record.h"
+-#include "dm-io.h"
+-#include "dm-log.h"
+-#include "kcopyd.h"
+ 
+ #include <linux/ctype.h>
+ #include <linux/init.h>
+@@ -22,6 +19,9 @@
+ #include <linux/workqueue.h>
+ #include <linux/log2.h>
+ #include <linux/hardirq.h>
++#include <linux/dm-io.h>
++#include <linux/dm-dirty-log.h>
++#include <linux/dm-kcopyd.h>
+ 
+ #define DM_MSG_PREFIX "raid1"
+ #define DM_IO_PAGES 64
+@@ -74,7 +74,7 @@ struct region_hash {
+ 	unsigned region_shift;
+ 
+ 	/* holds persistent region state */
+-	struct dirty_log *log;
++	struct dm_dirty_log *log;
+ 
+ 	/* hash table */
+ 	rwlock_t hash_lock;
+@@ -133,7 +133,7 @@ struct mirror_set {
+ 	struct dm_target *ti;
+ 	struct list_head list;
+ 	struct region_hash rh;
+-	struct kcopyd_client *kcopyd_client;
++	struct dm_kcopyd_client *kcopyd_client;
+ 	uint64_t features;
+ 
+ 	spinlock_t lock;	/* protects the lists */
+@@ -154,6 +154,9 @@ struct mirror_set {
+ 
+ 	struct workqueue_struct *kmirrord_wq;
+ 	struct work_struct kmirrord_work;
++	struct timer_list timer;
++	unsigned long timer_pending;
++
+ 	struct work_struct trigger_event;
+ 
+ 	unsigned int nr_mirrors;
+@@ -178,13 +181,32 @@ static void wake(struct mirror_set *ms)
+ 	queue_work(ms->kmirrord_wq, &ms->kmirrord_work);
+ }
+ 
++static void delayed_wake_fn(unsigned long data)
++{
++	struct mirror_set *ms = (struct mirror_set *) data;
++
++	clear_bit(0, &ms->timer_pending);
++	wake(ms);
++}
++
++static void delayed_wake(struct mirror_set *ms)
++{
++	if (test_and_set_bit(0, &ms->timer_pending))
++		return;
++
++	ms->timer.expires = jiffies + HZ / 5;
++	ms->timer.data = (unsigned long) ms;
++	ms->timer.function = delayed_wake_fn;
++	add_timer(&ms->timer);
++}
++
+ /* FIXME move this */
+ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
+ 
+ #define MIN_REGIONS 64
+ #define MAX_RECOVERY 1
+ static int rh_init(struct region_hash *rh, struct mirror_set *ms,
+-		   struct dirty_log *log, uint32_t region_size,
++		   struct dm_dirty_log *log, uint32_t region_size,
+ 		   region_t nr_regions)
+ {
+ 	unsigned int nr_buckets, max_buckets;
+@@ -249,7 +271,7 @@ static void rh_exit(struct region_hash *rh)
+ 	}
+ 
+ 	if (rh->log)
+-		dm_destroy_dirty_log(rh->log);
++		dm_dirty_log_destroy(rh->log);
+ 	if (rh->region_pool)
+ 		mempool_destroy(rh->region_pool);
+ 	vfree(rh->buckets);
+@@ -405,24 +427,22 @@ static void rh_update_states(struct region_hash *rh)
+ 	write_lock_irq(&rh->hash_lock);
+ 	spin_lock(&rh->region_lock);
+ 	if (!list_empty(&rh->clean_regions)) {
+-		list_splice(&rh->clean_regions, &clean);
+-		INIT_LIST_HEAD(&rh->clean_regions);
++		list_splice_init(&rh->clean_regions, &clean);
+ 
+ 		list_for_each_entry(reg, &clean, list)
+ 			list_del(&reg->hash_list);
+ 	}
+ 
+ 	if (!list_empty(&rh->recovered_regions)) {
+-		list_splice(&rh->recovered_regions, &recovered);
+-		INIT_LIST_HEAD(&rh->recovered_regions);
++		list_splice_init(&rh->recovered_regions, &recovered);
+ 
+ 		list_for_each_entry (reg, &recovered, list)
+ 			list_del(&reg->hash_list);
+ 	}
+ 
+ 	if (!list_empty(&rh->failed_recovered_regions)) {
+-		list_splice(&rh->failed_recovered_regions, &failed_recovered);
+-		INIT_LIST_HEAD(&rh->failed_recovered_regions);
++		list_splice_init(&rh->failed_recovered_regions,
++				 &failed_recovered);
+ 
+ 		list_for_each_entry(reg, &failed_recovered, list)
+ 			list_del(&reg->hash_list);
+@@ -790,7 +810,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
+ {
+ 	int r;
+ 	unsigned int i;
+-	struct io_region from, to[KCOPYD_MAX_REGIONS], *dest;
++	struct dm_io_region from, to[DM_KCOPYD_MAX_REGIONS], *dest;
+ 	struct mirror *m;
+ 	unsigned long flags = 0;
+ 
+@@ -822,9 +842,9 @@ static int recover(struct mirror_set *ms, struct region *reg)
+ 	}
+ 
+ 	/* hand to kcopyd */
+-	set_bit(KCOPYD_IGNORE_ERROR, &flags);
+-	r = kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to, flags,
+-			recovery_complete, reg);
++	set_bit(DM_KCOPYD_IGNORE_ERROR, &flags);
++	r = dm_kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to,
++			   flags, recovery_complete, reg);
+ 
+ 	return r;
+ }
+@@ -833,7 +853,7 @@ static void do_recovery(struct mirror_set *ms)
+ {
+ 	int r;
+ 	struct region *reg;
+-	struct dirty_log *log = ms->rh.log;
++	struct dm_dirty_log *log = ms->rh.log;
+ 
+ 	/*
+ 	 * Start quiescing some regions.
+@@ -909,7 +929,7 @@ static void map_bio(struct mirror *m, struct bio *bio)
+ 	bio->bi_sector = map_sector(m, bio);
+ }
+ 
+-static void map_region(struct io_region *io, struct mirror *m,
++static void map_region(struct dm_io_region *io, struct mirror *m,
+ 		       struct bio *bio)
+ {
+ 	io->bdev = m->dev->bdev;
+@@ -951,7 +971,7 @@ static void read_callback(unsigned long error, void *context)
+ /* Asynchronous read. */
+ static void read_async_bio(struct mirror *m, struct bio *bio)
+ {
+-	struct io_region io;
++	struct dm_io_region io;
+ 	struct dm_io_request io_req = {
+ 		.bi_rw = READ,
+ 		.mem.type = DM_IO_BVEC,
+@@ -1019,7 +1039,7 @@ static void __bio_mark_nosync(struct mirror_set *ms,
+ {
+ 	unsigned long flags;
+ 	struct region_hash *rh = &ms->rh;
+-	struct dirty_log *log = ms->rh.log;
++	struct dm_dirty_log *log = ms->rh.log;
+ 	struct region *reg;
+ 	region_t region = bio_to_region(rh, bio);
+ 	int recovering = 0;
+@@ -1107,7 +1127,7 @@ out:
+ static void do_write(struct mirror_set *ms, struct bio *bio)
+ {
+ 	unsigned int i;
+-	struct io_region io[ms->nr_mirrors], *dest = io;
++	struct dm_io_region io[ms->nr_mirrors], *dest = io;
+ 	struct mirror *m;
+ 	struct dm_io_request io_req = {
+ 		.bi_rw = WRITE,
+@@ -1182,6 +1202,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
+ 		spin_lock_irq(&ms->lock);
+ 		bio_list_merge(&ms->failures, &sync);
+ 		spin_unlock_irq(&ms->lock);
++		wake(ms);
+ 	} else
+ 		while ((bio = bio_list_pop(&sync)))
+ 			do_write(ms, bio);
+@@ -1241,7 +1262,7 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures)
+ 	bio_list_merge(&ms->failures, failures);
+ 	spin_unlock_irq(&ms->lock);
+ 
+-	wake(ms);
++	delayed_wake(ms);
+ }
+ 
+ static void trigger_event(struct work_struct *work)
+@@ -1255,7 +1276,7 @@ static void trigger_event(struct work_struct *work)
+ /*-----------------------------------------------------------------
+  * kmirrord
+  *---------------------------------------------------------------*/
+-static int _do_mirror(struct work_struct *work)
++static void do_mirror(struct work_struct *work)
+ {
+ 	struct mirror_set *ms =container_of(work, struct mirror_set,
+ 					    kmirrord_work);
+@@ -1277,23 +1298,7 @@ static int _do_mirror(struct work_struct *work)
+ 	do_writes(ms, &writes);
+ 	do_failures(ms, &failures);
+ 
+-	return (ms->failures.head) ? 1 : 0;
+-}
+-
+-static void do_mirror(struct work_struct *work)
+-{
+-	/*
+-	 * If _do_mirror returns 1, we give it
+-	 * another shot.  This helps for cases like
+-	 * 'suspend' where we call flush_workqueue
+-	 * and expect all work to be finished.  If
+-	 * a failure happens during a suspend, we
+-	 * couldn't issue a 'wake' because it would
+-	 * not be honored.  Therefore, we return '1'
+-	 * from _do_mirror, and retry here.
+-	 */
+-	while (_do_mirror(work))
+-		schedule();
++	dm_table_unplug_all(ms->ti->table);
+ }
+ 
+ 
+@@ -1303,7 +1308,7 @@ static void do_mirror(struct work_struct *work)
+ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
+ 					uint32_t region_size,
+ 					struct dm_target *ti,
+-					struct dirty_log *dl)
++					struct dm_dirty_log *dl)
+ {
+ 	size_t len;
+ 	struct mirror_set *ms = NULL;
+@@ -1403,12 +1408,12 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
+ /*
+  * Create dirty log: log_type #log_params <log_params>
+  */
+-static struct dirty_log *create_dirty_log(struct dm_target *ti,
++static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
+ 					  unsigned int argc, char **argv,
+ 					  unsigned int *args_used)
+ {
+ 	unsigned int param_count;
+-	struct dirty_log *dl;
++	struct dm_dirty_log *dl;
+ 
+ 	if (argc < 2) {
+ 		ti->error = "Insufficient mirror log arguments";
+@@ -1427,7 +1432,7 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti,
+ 		return NULL;
+ 	}
+ 
+-	dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2);
++	dl = dm_dirty_log_create(argv[0], ti, param_count, argv + 2);
+ 	if (!dl) {
+ 		ti->error = "Error creating mirror dirty log";
+ 		return NULL;
+@@ -1435,7 +1440,7 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti,
+ 
+ 	if (!_check_region_size(ti, dl->type->get_region_size(dl))) {
+ 		ti->error = "Invalid region size";
+-		dm_destroy_dirty_log(dl);
++		dm_dirty_log_destroy(dl);
+ 		return NULL;
+ 	}
+ 
+@@ -1496,7 +1501,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 	int r;
+ 	unsigned int nr_mirrors, m, args_used;
+ 	struct mirror_set *ms;
+-	struct dirty_log *dl;
++	struct dm_dirty_log *dl;
+ 
+ 	dl = create_dirty_log(ti, argc, argv, &args_used);
+ 	if (!dl)
+@@ -1506,9 +1511,9 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 	argc -= args_used;
+ 
+ 	if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 ||
+-	    nr_mirrors < 2 || nr_mirrors > KCOPYD_MAX_REGIONS + 1) {
++	    nr_mirrors < 2 || nr_mirrors > DM_KCOPYD_MAX_REGIONS + 1) {
+ 		ti->error = "Invalid number of mirrors";
+-		dm_destroy_dirty_log(dl);
++		dm_dirty_log_destroy(dl);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -1516,13 +1521,13 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 
+ 	if (argc < nr_mirrors * 2) {
+ 		ti->error = "Too few mirror arguments";
+-		dm_destroy_dirty_log(dl);
++		dm_dirty_log_destroy(dl);
+ 		return -EINVAL;
+ 	}
+ 
+ 	ms = alloc_context(nr_mirrors, dl->type->get_region_size(dl), ti, dl);
+ 	if (!ms) {
+-		dm_destroy_dirty_log(dl);
++		dm_dirty_log_destroy(dl);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -1547,6 +1552,8 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 		goto err_free_context;
+ 	}
+ 	INIT_WORK(&ms->kmirrord_work, do_mirror);
++	init_timer(&ms->timer);
++	ms->timer_pending = 0;
+ 	INIT_WORK(&ms->trigger_event, trigger_event);
+ 
+ 	r = parse_features(ms, argc, argv, &args_used);
+@@ -1571,7 +1578,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 		goto err_destroy_wq;
+ 	}
+ 
+-	r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
++	r = dm_kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
+ 	if (r)
+ 		goto err_destroy_wq;
+ 
+@@ -1589,8 +1596,9 @@ static void mirror_dtr(struct dm_target *ti)
+ {
+ 	struct mirror_set *ms = (struct mirror_set *) ti->private;
+ 
++	del_timer_sync(&ms->timer);
+ 	flush_workqueue(ms->kmirrord_wq);
+-	kcopyd_client_destroy(ms->kcopyd_client);
++	dm_kcopyd_client_destroy(ms->kcopyd_client);
+ 	destroy_workqueue(ms->kmirrord_wq);
+ 	free_context(ms, ti, ms->nr_mirrors);
+ }
+@@ -1734,7 +1742,7 @@ out:
+ static void mirror_presuspend(struct dm_target *ti)
+ {
+ 	struct mirror_set *ms = (struct mirror_set *) ti->private;
+-	struct dirty_log *log = ms->rh.log;
++	struct dm_dirty_log *log = ms->rh.log;
+ 
+ 	atomic_set(&ms->suspend, 1);
+ 
+@@ -1763,7 +1771,7 @@ static void mirror_presuspend(struct dm_target *ti)
+ static void mirror_postsuspend(struct dm_target *ti)
+ {
+ 	struct mirror_set *ms = ti->private;
+-	struct dirty_log *log = ms->rh.log;
++	struct dm_dirty_log *log = ms->rh.log;
+ 
+ 	if (log->type->postsuspend && log->type->postsuspend(log))
+ 		/* FIXME: need better error handling */
+@@ -1773,7 +1781,7 @@ static void mirror_postsuspend(struct dm_target *ti)
+ static void mirror_resume(struct dm_target *ti)
+ {
+ 	struct mirror_set *ms = ti->private;
+-	struct dirty_log *log = ms->rh.log;
++	struct dm_dirty_log *log = ms->rh.log;
+ 
+ 	atomic_set(&ms->suspend, 0);
+ 	if (log->type->resume && log->type->resume(log))
+@@ -1811,7 +1819,7 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
+ {
+ 	unsigned int m, sz = 0;
+ 	struct mirror_set *ms = (struct mirror_set *) ti->private;
+-	struct dirty_log *log = ms->rh.log;
++	struct dm_dirty_log *log = ms->rh.log;
+ 	char buffer[ms->nr_mirrors + 1];
+ 
+ 	switch (type) {
+@@ -1864,15 +1872,9 @@ static int __init dm_mirror_init(void)
+ {
+ 	int r;
+ 
+-	r = dm_dirty_log_init();
+-	if (r)
+-		return r;
+-
+ 	r = dm_register_target(&mirror_target);
+-	if (r < 0) {
++	if (r < 0)
+ 		DMERR("Failed to register mirror target");
+-		dm_dirty_log_exit();
+-	}
+ 
+ 	return r;
+ }
+@@ -1884,8 +1886,6 @@ static void __exit dm_mirror_exit(void)
+ 	r = dm_unregister_target(&mirror_target);
+ 	if (r < 0)
+ 		DMERR("unregister failed %d", r);
+-
+-	dm_dirty_log_exit();
+ }
+ 
+ /* Module hooks */
+diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
+index 4dc8a43..1ba8a47 100644
+--- a/drivers/md/dm-snap.c
++++ b/drivers/md/dm-snap.c
+@@ -18,10 +18,10 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/log2.h>
++#include <linux/dm-kcopyd.h>
+ 
+ #include "dm-snap.h"
+ #include "dm-bio-list.h"
+-#include "kcopyd.h"
+ 
+ #define DM_MSG_PREFIX "snapshots"
+ 
+@@ -36,9 +36,9 @@
+ #define SNAPSHOT_COPY_PRIORITY 2
+ 
+ /*
+- * Each snapshot reserves this many pages for io
++ * Reserve 1MB for each snapshot initially (with minimum of 1 page).
+  */
+-#define SNAPSHOT_PAGES 256
++#define SNAPSHOT_PAGES (((1UL << 20) >> PAGE_SHIFT) ? : 1)
+ 
+ static struct workqueue_struct *ksnapd;
+ static void flush_queued_bios(struct work_struct *work);
+@@ -536,7 +536,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 	s->last_percent = 0;
+ 	init_rwsem(&s->lock);
+ 	spin_lock_init(&s->pe_lock);
+-	s->table = ti->table;
++	s->ti = ti;
+ 
+ 	/* Allocate hash table for COW data */
+ 	if (init_hash_tables(s)) {
+@@ -558,7 +558,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 		goto bad4;
+ 	}
+ 
+-	r = kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
++	r = dm_kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
+ 	if (r) {
+ 		ti->error = "Could not create kcopyd client";
+ 		goto bad5;
+@@ -591,7 +591,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 	return 0;
+ 
+  bad6:
+-	kcopyd_client_destroy(s->kcopyd_client);
++	dm_kcopyd_client_destroy(s->kcopyd_client);
+ 
+  bad5:
+ 	s->store.destroy(&s->store);
+@@ -613,7 +613,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ 
+ static void __free_exceptions(struct dm_snapshot *s)
+ {
+-	kcopyd_client_destroy(s->kcopyd_client);
++	dm_kcopyd_client_destroy(s->kcopyd_client);
+ 	s->kcopyd_client = NULL;
+ 
+ 	exit_exception_table(&s->pending, pending_cache);
+@@ -699,7 +699,7 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
+ 
+ 	s->valid = 0;
+ 
+-	dm_table_event(s->table);
++	dm_table_event(s->ti->table);
+ }
+ 
+ static void get_pending_exception(struct dm_snap_pending_exception *pe)
+@@ -824,7 +824,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
+ static void start_copy(struct dm_snap_pending_exception *pe)
+ {
+ 	struct dm_snapshot *s = pe->snap;
+-	struct io_region src, dest;
++	struct dm_io_region src, dest;
+ 	struct block_device *bdev = s->origin->bdev;
+ 	sector_t dev_size;
+ 
+@@ -839,7 +839,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
+ 	dest.count = src.count;
+ 
+ 	/* Hand over to kcopyd */
+-	kcopyd_copy(s->kcopyd_client,
++	dm_kcopyd_copy(s->kcopyd_client,
+ 		    &src, 1, &dest, 0, copy_callback, pe);
+ }
+ 
+@@ -1060,7 +1060,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
+ 			goto next_snapshot;
+ 
+ 		/* Nothing to do if writing beyond end of snapshot */
+-		if (bio->bi_sector >= dm_table_get_size(snap->table))
++		if (bio->bi_sector >= dm_table_get_size(snap->ti->table))
+ 			goto next_snapshot;
+ 
+ 		/*
+diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
+index 93bce5d..24f9fb7 100644
+--- a/drivers/md/dm-snap.h
++++ b/drivers/md/dm-snap.h
+@@ -132,7 +132,7 @@ struct exception_store {
+ 
+ struct dm_snapshot {
+ 	struct rw_semaphore lock;
+-	struct dm_table *table;
++	struct dm_target *ti;
+ 
+ 	struct dm_dev *origin;
+ 	struct dm_dev *cow;
+@@ -169,7 +169,7 @@ struct dm_snapshot {
+ 	/* The on disk metadata handler */
+ 	struct exception_store store;
+ 
+-	struct kcopyd_client *kcopyd_client;
++	struct dm_kcopyd_client *kcopyd_client;
+ 
+ 	/* Queue of snapshot writes for ksnapd to flush */
+ 	struct bio_list queued_bios;
+diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
+index e75b143..51be533 100644
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -245,44 +245,6 @@ int dm_table_create(struct dm_table **result, int mode,
+ 	return 0;
+ }
+ 
+-int dm_create_error_table(struct dm_table **result, struct mapped_device *md)
+-{
+-	struct dm_table *t;
+-	sector_t dev_size = 1;
+-	int r;
+-
+-	/*
+-	 * Find current size of device.
+-	 * Default to 1 sector if inactive.
+-	 */
+-	t = dm_get_table(md);
+-	if (t) {
+-		dev_size = dm_table_get_size(t);
+-		dm_table_put(t);
+-	}
+-
+-	r = dm_table_create(&t, FMODE_READ, 1, md);
+-	if (r)
+-		return r;
+-
+-	r = dm_table_add_target(t, "error", 0, dev_size, NULL);
+-	if (r)
+-		goto out;
+-
+-	r = dm_table_complete(t);
+-	if (r)
+-		goto out;
+-
+-	*result = t;
+-
+-out:
+-	if (r)
+-		dm_table_put(t);
+-
+-	return r;
+-}
+-EXPORT_SYMBOL_GPL(dm_create_error_table);
+-
+ static void free_devices(struct list_head *devices)
+ {
+ 	struct list_head *tmp, *next;
+@@ -954,7 +916,7 @@ void dm_table_presuspend_targets(struct dm_table *t)
+ 	if (!t)
+ 		return;
+ 
+-	return suspend_targets(t, 0);
++	suspend_targets(t, 0);
+ }
+ 
+ void dm_table_postsuspend_targets(struct dm_table *t)
+@@ -962,7 +924,7 @@ void dm_table_postsuspend_targets(struct dm_table *t)
+ 	if (!t)
+ 		return;
+ 
+-	return suspend_targets(t, 1);
++	suspend_targets(t, 1);
+ }
+ 
+ int dm_table_resume_targets(struct dm_table *t)
+diff --git a/drivers/md/dm.c b/drivers/md/dm.c
+index 6617ce4..372369b 100644
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -204,6 +204,7 @@ static int (*_inits[])(void) __initdata = {
+ 	dm_target_init,
+ 	dm_linear_init,
+ 	dm_stripe_init,
++	dm_kcopyd_init,
+ 	dm_interface_init,
+ };
+ 
+@@ -212,6 +213,7 @@ static void (*_exits[])(void) = {
+ 	dm_target_exit,
+ 	dm_linear_exit,
+ 	dm_stripe_exit,
++	dm_kcopyd_exit,
+ 	dm_interface_exit,
+ };
+ 
+@@ -922,7 +924,7 @@ static void free_minor(int minor)
+ /*
+  * See if the device with a specific minor # is free.
+  */
+-static int specific_minor(struct mapped_device *md, int minor)
++static int specific_minor(int minor)
+ {
+ 	int r, m;
+ 
+@@ -955,7 +957,7 @@ out:
+ 	return r;
+ }
+ 
+-static int next_free_minor(struct mapped_device *md, int *minor)
++static int next_free_minor(int *minor)
+ {
+ 	int r, m;
+ 
+@@ -966,9 +968,8 @@ static int next_free_minor(struct mapped_device *md, int *minor)
+ 	spin_lock(&_minor_lock);
+ 
+ 	r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m);
+-	if (r) {
++	if (r)
+ 		goto out;
+-	}
+ 
+ 	if (m >= (1 << MINORBITS)) {
+ 		idr_remove(&_minor_idr, m);
+@@ -991,7 +992,7 @@ static struct block_device_operations dm_blk_dops;
+ static struct mapped_device *alloc_dev(int minor)
+ {
+ 	int r;
+-	struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL);
++	struct mapped_device *md = kzalloc(sizeof(*md), GFP_KERNEL);
+ 	void *old_md;
+ 
+ 	if (!md) {
+@@ -1004,13 +1005,12 @@ static struct mapped_device *alloc_dev(int minor)
+ 
+ 	/* get a minor number for the dev */
+ 	if (minor == DM_ANY_MINOR)
+-		r = next_free_minor(md, &minor);
++		r = next_free_minor(&minor);
+ 	else
+-		r = specific_minor(md, minor);
++		r = specific_minor(minor);
+ 	if (r < 0)
+ 		goto bad_minor;
+ 
+-	memset(md, 0, sizeof(*md));
+ 	init_rwsem(&md->io_lock);
+ 	mutex_init(&md->suspend_lock);
+ 	spin_lock_init(&md->pushback_lock);
+diff --git a/drivers/md/dm.h b/drivers/md/dm.h
+index b4584a3..8c03b63 100644
+--- a/drivers/md/dm.h
++++ b/drivers/md/dm.h
+@@ -16,67 +16,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ 
+-#define DM_NAME "device-mapper"
+-
+-#define DMERR(f, arg...) \
+-	printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+-#define DMERR_LIMIT(f, arg...) \
+-	do { \
+-		if (printk_ratelimit())	\
+-			printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
+-			       f "\n", ## arg); \
+-	} while (0)
+-
+-#define DMWARN(f, arg...) \
+-	printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+-#define DMWARN_LIMIT(f, arg...) \
+-	do { \
+-		if (printk_ratelimit())	\
+-			printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
+-			       f "\n", ## arg); \
+-	} while (0)
+-
+-#define DMINFO(f, arg...) \
+-	printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+-#define DMINFO_LIMIT(f, arg...) \
+-	do { \
+-		if (printk_ratelimit())	\
+-			printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
+-			       "\n", ## arg); \
+-	} while (0)
+-
+-#ifdef CONFIG_DM_DEBUG
+-#  define DMDEBUG(f, arg...) \
+-	printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
+-#  define DMDEBUG_LIMIT(f, arg...) \
+-	do { \
+-		if (printk_ratelimit())	\
+-			printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
+-			       "\n", ## arg); \
+-	} while (0)
+-#else
+-#  define DMDEBUG(f, arg...) do {} while (0)
+-#  define DMDEBUG_LIMIT(f, arg...) do {} while (0)
+-#endif
+-
+-#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
+-			  0 : scnprintf(result + sz, maxlen - sz, x))
+-
+-#define SECTOR_SHIFT 9
+-
+-/*
+- * Definitions of return values from target end_io function.
+- */
+-#define DM_ENDIO_INCOMPLETE	1
+-#define DM_ENDIO_REQUEUE	2
+-
+-/*
+- * Definitions of return values from target map function.
+- */
+-#define DM_MAPIO_SUBMITTED	0
+-#define DM_MAPIO_REMAPPED	1
+-#define DM_MAPIO_REQUEUE	DM_ENDIO_REQUEUE
+-
+ /*
+  * Suspend feature flags
+  */
+@@ -136,34 +75,6 @@ static inline int array_too_big(unsigned long fixed, unsigned long obj,
+ 	return (num > (ULONG_MAX - fixed) / obj);
+ }
+ 
+-/*
+- * Ceiling(n / sz)
+- */
+-#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
+-
+-#define dm_sector_div_up(n, sz) ( \
+-{ \
+-	sector_t _r = ((n) + (sz) - 1); \
+-	sector_div(_r, (sz)); \
+-	_r; \
+-} \
+-)
+-
+-/*
+- * ceiling(n / size) * size
+- */
+-#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
+-
+-static inline sector_t to_sector(unsigned long n)
+-{
+-	return (n >> 9);
+-}
+-
+-static inline unsigned long to_bytes(sector_t n)
+-{
+-	return (n << 9);
+-}
+-
+ int dm_split_args(int *argc, char ***argvp, char *input);
+ 
+ /*
+@@ -189,4 +100,13 @@ int dm_lock_for_deletion(struct mapped_device *md);
+ 
+ void dm_kobject_uevent(struct mapped_device *md);
+ 
++/*
++ * Dirty log
++ */
++int dm_dirty_log_init(void);
++void dm_dirty_log_exit(void);
++
++int dm_kcopyd_init(void);
++void dm_kcopyd_exit(void);
++
+ #endif
+diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
+deleted file mode 100644
+index e76b52a..0000000
+--- a/drivers/md/kcopyd.c
++++ /dev/null
+@@ -1,708 +0,0 @@
+-/*
+- * Copyright (C) 2002 Sistina Software (UK) Limited.
+- * Copyright (C) 2006 Red Hat GmbH
+- *
+- * This file is released under the GPL.
+- *
+- * Kcopyd provides a simple interface for copying an area of one
+- * block-device to one or more other block-devices, with an asynchronous
+- * completion notification.
+- */
+-
+-#include <asm/types.h>
+-#include <asm/atomic.h>
+-
+-#include <linux/blkdev.h>
+-#include <linux/fs.h>
+-#include <linux/init.h>
+-#include <linux/list.h>
+-#include <linux/mempool.h>
+-#include <linux/module.h>
+-#include <linux/pagemap.h>
+-#include <linux/slab.h>
+-#include <linux/vmalloc.h>
+-#include <linux/workqueue.h>
+-#include <linux/mutex.h>
+-
+-#include "kcopyd.h"
+-
+-static struct workqueue_struct *_kcopyd_wq;
+-static struct work_struct _kcopyd_work;
+-
+-static void wake(void)
+-{
+-	queue_work(_kcopyd_wq, &_kcopyd_work);
+-}
+-
+-/*-----------------------------------------------------------------
+- * Each kcopyd client has its own little pool of preallocated
+- * pages for kcopyd io.
+- *---------------------------------------------------------------*/
+-struct kcopyd_client {
+-	struct list_head list;
+-
+-	spinlock_t lock;
+-	struct page_list *pages;
+-	unsigned int nr_pages;
+-	unsigned int nr_free_pages;
+-
+-	struct dm_io_client *io_client;
+-
+-	wait_queue_head_t destroyq;
+-	atomic_t nr_jobs;
+-};
+-
+-static struct page_list *alloc_pl(void)
+-{
+-	struct page_list *pl;
+-
+-	pl = kmalloc(sizeof(*pl), GFP_KERNEL);
+-	if (!pl)
+-		return NULL;
+-
+-	pl->page = alloc_page(GFP_KERNEL);
+-	if (!pl->page) {
+-		kfree(pl);
+-		return NULL;
+-	}
+-
+-	return pl;
+-}
+-
+-static void free_pl(struct page_list *pl)
+-{
+-	__free_page(pl->page);
+-	kfree(pl);
+-}
+-
+-static int kcopyd_get_pages(struct kcopyd_client *kc,
+-			    unsigned int nr, struct page_list **pages)
+-{
+-	struct page_list *pl;
+-
+-	spin_lock(&kc->lock);
+-	if (kc->nr_free_pages < nr) {
+-		spin_unlock(&kc->lock);
+-		return -ENOMEM;
+-	}
+-
+-	kc->nr_free_pages -= nr;
+-	for (*pages = pl = kc->pages; --nr; pl = pl->next)
+-		;
+-
+-	kc->pages = pl->next;
+-	pl->next = NULL;
+-
+-	spin_unlock(&kc->lock);
+-
+-	return 0;
+-}
+-
+-static void kcopyd_put_pages(struct kcopyd_client *kc, struct page_list *pl)
+-{
+-	struct page_list *cursor;
+-
+-	spin_lock(&kc->lock);
+-	for (cursor = pl; cursor->next; cursor = cursor->next)
+-		kc->nr_free_pages++;
+-
+-	kc->nr_free_pages++;
+-	cursor->next = kc->pages;
+-	kc->pages = pl;
+-	spin_unlock(&kc->lock);
+-}
+-
+-/*
+- * These three functions resize the page pool.
+- */
+-static void drop_pages(struct page_list *pl)
+-{
+-	struct page_list *next;
+-
+-	while (pl) {
+-		next = pl->next;
+-		free_pl(pl);
+-		pl = next;
+-	}
+-}
+-
+-static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr)
+-{
+-	unsigned int i;
+-	struct page_list *pl = NULL, *next;
+-
+-	for (i = 0; i < nr; i++) {
+-		next = alloc_pl();
+-		if (!next) {
+-			if (pl)
+-				drop_pages(pl);
+-			return -ENOMEM;
+-		}
+-		next->next = pl;
+-		pl = next;
+-	}
+-
+-	kcopyd_put_pages(kc, pl);
+-	kc->nr_pages += nr;
+-	return 0;
+-}
+-
+-static void client_free_pages(struct kcopyd_client *kc)
+-{
+-	BUG_ON(kc->nr_free_pages != kc->nr_pages);
+-	drop_pages(kc->pages);
+-	kc->pages = NULL;
+-	kc->nr_free_pages = kc->nr_pages = 0;
+-}
+-
+-/*-----------------------------------------------------------------
+- * kcopyd_jobs need to be allocated by the *clients* of kcopyd,
+- * for this reason we use a mempool to prevent the client from
+- * ever having to do io (which could cause a deadlock).
+- *---------------------------------------------------------------*/
+-struct kcopyd_job {
+-	struct kcopyd_client *kc;
+-	struct list_head list;
+-	unsigned long flags;
+-
+-	/*
+-	 * Error state of the job.
+-	 */
+-	int read_err;
+-	unsigned long write_err;
+-
+-	/*
+-	 * Either READ or WRITE
+-	 */
+-	int rw;
+-	struct io_region source;
+-
+-	/*
+-	 * The destinations for the transfer.
+-	 */
+-	unsigned int num_dests;
+-	struct io_region dests[KCOPYD_MAX_REGIONS];
+-
+-	sector_t offset;
+-	unsigned int nr_pages;
+-	struct page_list *pages;
+-
+-	/*
+-	 * Set this to ensure you are notified when the job has
+-	 * completed.  'context' is for callback to use.
+-	 */
+-	kcopyd_notify_fn fn;
+-	void *context;
+-
+-	/*
+-	 * These fields are only used if the job has been split
+-	 * into more manageable parts.
+-	 */
+-	struct mutex lock;
+-	atomic_t sub_jobs;
+-	sector_t progress;
+-};
+-
+-/* FIXME: this should scale with the number of pages */
+-#define MIN_JOBS 512
+-
+-static struct kmem_cache *_job_cache;
+-static mempool_t *_job_pool;
+-
+-/*
+- * We maintain three lists of jobs:
+- *
+- * i)   jobs waiting for pages
+- * ii)  jobs that have pages, and are waiting for the io to be issued.
+- * iii) jobs that have completed.
+- *
+- * All three of these are protected by job_lock.
+- */
+-static DEFINE_SPINLOCK(_job_lock);
+-
+-static LIST_HEAD(_complete_jobs);
+-static LIST_HEAD(_io_jobs);
+-static LIST_HEAD(_pages_jobs);
+-
+-static int jobs_init(void)
+-{
+-	_job_cache = KMEM_CACHE(kcopyd_job, 0);
+-	if (!_job_cache)
+-		return -ENOMEM;
+-
+-	_job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
+-	if (!_job_pool) {
+-		kmem_cache_destroy(_job_cache);
+-		return -ENOMEM;
+-	}
+-
+-	return 0;
+-}
+-
+-static void jobs_exit(void)
+-{
+-	BUG_ON(!list_empty(&_complete_jobs));
+-	BUG_ON(!list_empty(&_io_jobs));
+-	BUG_ON(!list_empty(&_pages_jobs));
+-
+-	mempool_destroy(_job_pool);
+-	kmem_cache_destroy(_job_cache);
+-	_job_pool = NULL;
+-	_job_cache = NULL;
+-}
+-
+-/*
+- * Functions to push and pop a job onto the head of a given job
+- * list.
+- */
+-static struct kcopyd_job *pop(struct list_head *jobs)
+-{
+-	struct kcopyd_job *job = NULL;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&_job_lock, flags);
+-
+-	if (!list_empty(jobs)) {
+-		job = list_entry(jobs->next, struct kcopyd_job, list);
+-		list_del(&job->list);
+-	}
+-	spin_unlock_irqrestore(&_job_lock, flags);
+-
+-	return job;
+-}
+-
+-static void push(struct list_head *jobs, struct kcopyd_job *job)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&_job_lock, flags);
+-	list_add_tail(&job->list, jobs);
+-	spin_unlock_irqrestore(&_job_lock, flags);
+-}
+-
+-/*
+- * These three functions process 1 item from the corresponding
+- * job list.
+- *
+- * They return:
+- * < 0: error
+- *   0: success
+- * > 0: can't process yet.
+- */
+-static int run_complete_job(struct kcopyd_job *job)
+-{
+-	void *context = job->context;
+-	int read_err = job->read_err;
+-	unsigned long write_err = job->write_err;
+-	kcopyd_notify_fn fn = job->fn;
+-	struct kcopyd_client *kc = job->kc;
+-
+-	kcopyd_put_pages(kc, job->pages);
+-	mempool_free(job, _job_pool);
+-	fn(read_err, write_err, context);
+-
+-	if (atomic_dec_and_test(&kc->nr_jobs))
+-		wake_up(&kc->destroyq);
+-
+-	return 0;
+-}
+-
+-static void complete_io(unsigned long error, void *context)
+-{
+-	struct kcopyd_job *job = (struct kcopyd_job *) context;
+-
+-	if (error) {
+-		if (job->rw == WRITE)
+-			job->write_err |= error;
+-		else
+-			job->read_err = 1;
+-
+-		if (!test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
+-			push(&_complete_jobs, job);
+-			wake();
+-			return;
+-		}
+-	}
+-
+-	if (job->rw == WRITE)
+-		push(&_complete_jobs, job);
+-
+-	else {
+-		job->rw = WRITE;
+-		push(&_io_jobs, job);
+-	}
+-
+-	wake();
+-}
+-
+-/*
+- * Request io on as many buffer heads as we can currently get for
+- * a particular job.
+- */
+-static int run_io_job(struct kcopyd_job *job)
+-{
+-	int r;
+-	struct dm_io_request io_req = {
+-		.bi_rw = job->rw,
+-		.mem.type = DM_IO_PAGE_LIST,
+-		.mem.ptr.pl = job->pages,
+-		.mem.offset = job->offset,
+-		.notify.fn = complete_io,
+-		.notify.context = job,
+-		.client = job->kc->io_client,
+-	};
+-
+-	if (job->rw == READ)
+-		r = dm_io(&io_req, 1, &job->source, NULL);
+-	else
+-		r = dm_io(&io_req, job->num_dests, job->dests, NULL);
+-
+-	return r;
+-}
+-
+-static int run_pages_job(struct kcopyd_job *job)
+-{
+-	int r;
+-
+-	job->nr_pages = dm_div_up(job->dests[0].count + job->offset,
+-				  PAGE_SIZE >> 9);
+-	r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages);
+-	if (!r) {
+-		/* this job is ready for io */
+-		push(&_io_jobs, job);
+-		return 0;
+-	}
+-
+-	if (r == -ENOMEM)
+-		/* can't complete now */
+-		return 1;
+-
+-	return r;
+-}
+-
+-/*
+- * Run through a list for as long as possible.  Returns the count
+- * of successful jobs.
+- */
+-static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
+-{
+-	struct kcopyd_job *job;
+-	int r, count = 0;
+-
+-	while ((job = pop(jobs))) {
+-
+-		r = fn(job);
+-
+-		if (r < 0) {
+-			/* error this rogue job */
+-			if (job->rw == WRITE)
+-				job->write_err = (unsigned long) -1L;
+-			else
+-				job->read_err = 1;
+-			push(&_complete_jobs, job);
+-			break;
+-		}
+-
+-		if (r > 0) {
+-			/*
+-			 * We couldn't service this job ATM, so
+-			 * push this job back onto the list.
+-			 */
+-			push(jobs, job);
+-			break;
+-		}
+-
+-		count++;
+-	}
+-
+-	return count;
+-}
+-
+-/*
+- * kcopyd does this every time it's woken up.
+- */
+-static void do_work(struct work_struct *ignored)
+-{
+-	/*
+-	 * The order that these are called is *very* important.
+-	 * complete jobs can free some pages for pages jobs.
+-	 * Pages jobs when successful will jump onto the io jobs
+-	 * list.  io jobs call wake when they complete and it all
+-	 * starts again.
+-	 */
+-	process_jobs(&_complete_jobs, run_complete_job);
+-	process_jobs(&_pages_jobs, run_pages_job);
+-	process_jobs(&_io_jobs, run_io_job);
+-}
+-
+-/*
+- * If we are copying a small region we just dispatch a single job
+- * to do the copy, otherwise the io has to be split up into many
+- * jobs.
+- */
+-static void dispatch_job(struct kcopyd_job *job)
+-{
+-	atomic_inc(&job->kc->nr_jobs);
+-	push(&_pages_jobs, job);
+-	wake();
+-}
+-
+-#define SUB_JOB_SIZE 128
+-static void segment_complete(int read_err, unsigned long write_err,
+-			     void *context)
+-{
+-	/* FIXME: tidy this function */
+-	sector_t progress = 0;
+-	sector_t count = 0;
+-	struct kcopyd_job *job = (struct kcopyd_job *) context;
+-
+-	mutex_lock(&job->lock);
+-
+-	/* update the error */
+-	if (read_err)
+-		job->read_err = 1;
+-
+-	if (write_err)
+-		job->write_err |= write_err;
+-
+-	/*
+-	 * Only dispatch more work if there hasn't been an error.
+-	 */
+-	if ((!job->read_err && !job->write_err) ||
+-	    test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
+-		/* get the next chunk of work */
+-		progress = job->progress;
+-		count = job->source.count - progress;
+-		if (count) {
+-			if (count > SUB_JOB_SIZE)
+-				count = SUB_JOB_SIZE;
+-
+-			job->progress += count;
+-		}
+-	}
+-	mutex_unlock(&job->lock);
+-
+-	if (count) {
+-		int i;
+-		struct kcopyd_job *sub_job = mempool_alloc(_job_pool, GFP_NOIO);
+-
+-		*sub_job = *job;
+-		sub_job->source.sector += progress;
+-		sub_job->source.count = count;
+-
+-		for (i = 0; i < job->num_dests; i++) {
+-			sub_job->dests[i].sector += progress;
+-			sub_job->dests[i].count = count;
+-		}
+-
+-		sub_job->fn = segment_complete;
+-		sub_job->context = job;
+-		dispatch_job(sub_job);
+-
+-	} else if (atomic_dec_and_test(&job->sub_jobs)) {
+-
+-		/*
+-		 * To avoid a race we must keep the job around
+-		 * until after the notify function has completed.
+-		 * Otherwise the client may try and stop the job
+-		 * after we've completed.
+-		 */
+-		job->fn(read_err, write_err, job->context);
+-		mempool_free(job, _job_pool);
+-	}
+-}
+-
+-/*
+- * Create some little jobs that will do the move between
+- * them.
+- */
+-#define SPLIT_COUNT 8
+-static void split_job(struct kcopyd_job *job)
+-{
+-	int i;
+-
+-	atomic_set(&job->sub_jobs, SPLIT_COUNT);
+-	for (i = 0; i < SPLIT_COUNT; i++)
+-		segment_complete(0, 0u, job);
+-}
+-
+-int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+-		unsigned int num_dests, struct io_region *dests,
+-		unsigned int flags, kcopyd_notify_fn fn, void *context)
+-{
+-	struct kcopyd_job *job;
+-
+-	/*
+-	 * Allocate a new job.
+-	 */
+-	job = mempool_alloc(_job_pool, GFP_NOIO);
+-
+-	/*
+-	 * set up for the read.
+-	 */
+-	job->kc = kc;
+-	job->flags = flags;
+-	job->read_err = 0;
+-	job->write_err = 0;
+-	job->rw = READ;
+-
+-	job->source = *from;
+-
+-	job->num_dests = num_dests;
+-	memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
+-
+-	job->offset = 0;
+-	job->nr_pages = 0;
+-	job->pages = NULL;
+-
+-	job->fn = fn;
+-	job->context = context;
+-
+-	if (job->source.count < SUB_JOB_SIZE)
+-		dispatch_job(job);
+-
+-	else {
+-		mutex_init(&job->lock);
+-		job->progress = 0;
+-		split_job(job);
+-	}
+-
+-	return 0;
+-}
+-
+-/*
+- * Cancels a kcopyd job, eg. someone might be deactivating a
+- * mirror.
+- */
+-#if 0
+-int kcopyd_cancel(struct kcopyd_job *job, int block)
+-{
+-	/* FIXME: finish */
+-	return -1;
+-}
+-#endif  /*  0  */
+-
+-/*-----------------------------------------------------------------
+- * Unit setup
+- *---------------------------------------------------------------*/
+-static DEFINE_MUTEX(_client_lock);
+-static LIST_HEAD(_clients);
+-
+-static void client_add(struct kcopyd_client *kc)
+-{
+-	mutex_lock(&_client_lock);
+-	list_add(&kc->list, &_clients);
+-	mutex_unlock(&_client_lock);
+-}
+-
+-static void client_del(struct kcopyd_client *kc)
+-{
+-	mutex_lock(&_client_lock);
+-	list_del(&kc->list);
+-	mutex_unlock(&_client_lock);
+-}
+-
+-static DEFINE_MUTEX(kcopyd_init_lock);
+-static int kcopyd_clients = 0;
+-
+-static int kcopyd_init(void)
+-{
+-	int r;
+-
+-	mutex_lock(&kcopyd_init_lock);
+-
+-	if (kcopyd_clients) {
+-		/* Already initialized. */
+-		kcopyd_clients++;
+-		mutex_unlock(&kcopyd_init_lock);
+-		return 0;
+-	}
+-
+-	r = jobs_init();
+-	if (r) {
+-		mutex_unlock(&kcopyd_init_lock);
+-		return r;
+-	}
+-
+-	_kcopyd_wq = create_singlethread_workqueue("kcopyd");
+-	if (!_kcopyd_wq) {
+-		jobs_exit();
+-		mutex_unlock(&kcopyd_init_lock);
+-		return -ENOMEM;
+-	}
+-
+-	kcopyd_clients++;
+-	INIT_WORK(&_kcopyd_work, do_work);
+-	mutex_unlock(&kcopyd_init_lock);
+-	return 0;
+-}
+-
+-static void kcopyd_exit(void)
+-{
+-	mutex_lock(&kcopyd_init_lock);
+-	kcopyd_clients--;
+-	if (!kcopyd_clients) {
+-		jobs_exit();
+-		destroy_workqueue(_kcopyd_wq);
+-		_kcopyd_wq = NULL;
+-	}
+-	mutex_unlock(&kcopyd_init_lock);
+-}
+-
+-int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
+-{
+-	int r = 0;
+-	struct kcopyd_client *kc;
+-
+-	r = kcopyd_init();
+-	if (r)
+-		return r;
+-
+-	kc = kmalloc(sizeof(*kc), GFP_KERNEL);
+-	if (!kc) {
+-		kcopyd_exit();
+-		return -ENOMEM;
+-	}
+-
+-	spin_lock_init(&kc->lock);
+-	kc->pages = NULL;
+-	kc->nr_pages = kc->nr_free_pages = 0;
+-	r = client_alloc_pages(kc, nr_pages);
+-	if (r) {
+-		kfree(kc);
+-		kcopyd_exit();
+-		return r;
+-	}
+-
+-	kc->io_client = dm_io_client_create(nr_pages);
+-	if (IS_ERR(kc->io_client)) {
+-		r = PTR_ERR(kc->io_client);
+-		client_free_pages(kc);
+-		kfree(kc);
+-		kcopyd_exit();
+-		return r;
+-	}
+-
+-	init_waitqueue_head(&kc->destroyq);
+-	atomic_set(&kc->nr_jobs, 0);
+-
+-	client_add(kc);
+-	*result = kc;
+-	return 0;
+-}
+-
+-void kcopyd_client_destroy(struct kcopyd_client *kc)
+-{
+-	/* Wait for completion of all jobs submitted by this client. */
+-	wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
+-
+-	dm_io_client_destroy(kc->io_client);
+-	client_free_pages(kc);
+-	client_del(kc);
+-	kfree(kc);
+-	kcopyd_exit();
+-}
+-
+-EXPORT_SYMBOL(kcopyd_client_create);
+-EXPORT_SYMBOL(kcopyd_client_destroy);
+-EXPORT_SYMBOL(kcopyd_copy);
+diff --git a/drivers/md/kcopyd.h b/drivers/md/kcopyd.h
+deleted file mode 100644
+index 4845f2a..0000000
+--- a/drivers/md/kcopyd.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-/*
+- * Copyright (C) 2001 Sistina Software
+- *
+- * This file is released under the GPL.
+- *
+- * Kcopyd provides a simple interface for copying an area of one
+- * block-device to one or more other block-devices, with an asynchronous
+- * completion notification.
+- */
+-
+-#ifndef DM_KCOPYD_H
+-#define DM_KCOPYD_H
+-
+-#include "dm-io.h"
+-
+-/* FIXME: make this configurable */
+-#define KCOPYD_MAX_REGIONS 8
+-
+-#define KCOPYD_IGNORE_ERROR 1
+-
+-/*
+- * To use kcopyd you must first create a kcopyd client object.
+- */
+-struct kcopyd_client;
+-int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result);
+-void kcopyd_client_destroy(struct kcopyd_client *kc);
+-
+-/*
+- * Submit a copy job to kcopyd.  This is built on top of the
+- * previous three fns.
+- *
+- * read_err is a boolean,
+- * write_err is a bitset, with 1 bit for each destination region
+- */
+-typedef void (*kcopyd_notify_fn)(int read_err, unsigned long write_err,
+-				 void *context);
+-
+-int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+-		unsigned int num_dests, struct io_region *dests,
+-		unsigned int flags, kcopyd_notify_fn fn, void *context);
+-
+-#endif
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 61ccbd2..5ebfb4d 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -4152,7 +4152,7 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
+ 
+ 	return 0;
+ busy:
+-	printk(KERN_WARNING "md: cannot remove active disk %s from %s ... \n",
++	printk(KERN_WARNING "md: cannot remove active disk %s from %s ...\n",
+ 		bdevname(rdev->bdev,b), mdname(mddev));
+ 	return -EBUSY;
+ }
+diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
+index 1195069..128bb9c 100644
+--- a/drivers/media/Kconfig
++++ b/drivers/media/Kconfig
+@@ -30,7 +30,7 @@ config VIDEO_V4L2_COMMON
+ 	depends on (I2C || I2C=n) && VIDEO_DEV
+ 	default (I2C || I2C=n) && VIDEO_DEV
+ 
+-config VIDEO_V4L1
++config VIDEO_ALLOW_V4L1
+ 	bool "Enable Video For Linux API 1 (DEPRECATED)"
+ 	depends on VIDEO_DEV && VIDEO_V4L2_COMMON
+ 	default VIDEO_DEV && VIDEO_V4L2_COMMON
+@@ -59,10 +59,15 @@ config VIDEO_V4L1_COMPAT
+ 	  If you are unsure as to whether this is required, answer Y.
+ 
+ config VIDEO_V4L2
+-	bool
++	tristate
+ 	depends on VIDEO_DEV && VIDEO_V4L2_COMMON
+ 	default VIDEO_DEV && VIDEO_V4L2_COMMON
+ 
++config VIDEO_V4L1
++	tristate
++	depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
++	default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
++
+ source "drivers/media/video/Kconfig"
+ 
+ source "drivers/media/radio/Kconfig"
+@@ -155,7 +160,7 @@ config VIDEOBUF_GEN
+ 	tristate
+ 
+ config VIDEOBUF_DMA_SG
+-	depends on PCI
++	depends on HAS_DMA
+ 	select VIDEOBUF_GEN
+ 	tristate
+ 
+diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
+index bb2a027..2665052 100644
+--- a/drivers/media/common/ir-functions.c
++++ b/drivers/media/common/ir-functions.c
+@@ -34,7 +34,7 @@ static int repeat = 1;
+ module_param(repeat, int, 0444);
+ MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
+ 
+-static int debug = 0;    /* debug level (0,1,2) */
++static int debug;    /* debug level (0,1,2) */
+ module_param(debug, int, 0644);
+ 
+ #define dprintk(level, fmt, arg...)	if (debug >= level) \
+diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
+index 2ab5a12..a348581 100644
+--- a/drivers/media/common/ir-keymaps.c
++++ b/drivers/media/common/ir-keymaps.c
+@@ -212,6 +212,51 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
+ 
+ EXPORT_SYMBOL_GPL(ir_codes_pixelview);
+ 
++/*
++   Mauro Carvalho Chehab <mchehab at infradead.org>
++   present on PV MPEG 8000GT
++ */
++IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = {
++	[0x3c] = KEY_PAUSE,		/* Timeshift */
++	[0x12] = KEY_POWER,
++
++	[0x3d] = KEY_1,
++	[0x38] = KEY_2,
++	[0x18] = KEY_3,
++	[0x35] = KEY_4,
++	[0x39] = KEY_5,
++	[0x15] = KEY_6,
++	[0x36] = KEY_7,
++	[0x3a] = KEY_8,
++	[0x1e] = KEY_9,
++	[0x3e] = KEY_0,
++
++	[0x1c] = KEY_AGAIN,		/* LOOP	*/
++	[0x3f] = KEY_MEDIA,		/* Source */
++	[0x1f] = KEY_LAST,		/* +100 */
++	[0x1b] = KEY_MUTE,
++
++	[0x17] = KEY_CHANNELDOWN,
++	[0x16] = KEY_CHANNELUP,
++	[0x10] = KEY_VOLUMEUP,
++	[0x14] = KEY_VOLUMEDOWN,
++	[0x13] = KEY_ZOOM,
++
++	[0x19] = KEY_SHUFFLE,		/* SNAPSHOT */
++	[0x1a] = KEY_SEARCH,		/* scan */
++
++	[0x37] = KEY_REWIND,		/* << */
++	[0x32] = KEY_RECORD,		/* o (red) */
++	[0x33] = KEY_FORWARD,		/* >> */
++	[0x11] = KEY_STOP,		/* square */
++	[0x3b] = KEY_PLAY,		/* > */
++	[0x30] = KEY_PLAYPAUSE,		/* || */
++
++	[0x31] = KEY_TV,
++	[0x34] = KEY_RADIO,
++};
++EXPORT_SYMBOL_GPL(ir_codes_pixelview_new);
++
+ IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = {
+ 	[ 0x00 ] = KEY_0,
+ 	[ 0x01 ] = KEY_1,
+@@ -726,7 +771,11 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
+ 	[ 0x12 ] = KEY_CHANNELUP,    // Channel +
+ 	[ 0x13 ] = KEY_CHANNELDOWN,  // Channel -
+ 	[ 0x06 ] = KEY_AGAIN,        // Recall
+-	[ 0x10 ] = KEY_ENTER,      // Enter
++	[ 0x10 ] = KEY_ENTER,        // Enter
++
++	[ 0x19 ] = KEY_BACK,         // Rewind  ( <<< )
++	[ 0x1f ] = KEY_FORWARD,      // Forward ( >>> )
++	[ 0x0a ] = KEY_ANGLE,        // (no label, may be used as the PAUSE button)
+ };
+ 
+ EXPORT_SYMBOL_GPL(ir_codes_flyvideo);
+@@ -1157,7 +1206,8 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv);
+ 
+ /* Mapping for the 28 key remote control as seen at
+    http://www.sednacomputer.com/photo/cardbus-tv.jpg
+-   Pavel Mihaylov <bin at bash.info> */
++   Pavel Mihaylov <bin at bash.info>
++   Also for the remote bundled with Kozumi KTV-01C card */
+ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
+ 	[ 0x00 ] = KEY_0,
+ 	[ 0x01 ] = KEY_1,
+@@ -1188,6 +1238,11 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
+ 	[ 0x1c ] = KEY_RADIO,          /* FM Radio */
+ 	[ 0x1d ] = KEY_RECORD,
+ 	[ 0x1e ] = KEY_PAUSE,
++	/* additional codes for Kozumi's remote */
++	[0x14] = KEY_INFO,        /* OSD */
++	[0x16] = KEY_OK,          /* OK */
++	[0x17] = KEY_DIGITS,      /* Plus */
++	[0x1f] = KEY_PLAY,        /* Play */
+ };
+ 
+ EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna);
+@@ -1988,6 +2043,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
+ 
+ EXPORT_SYMBOL_GPL(ir_codes_behold);
+ 
++/* Beholder Intl. Ltd. 2008
++ * Dmitry Belimov d.belimov at google.com
++ * Keytable is used by BeholdTV Columbus
++ * The "ascii-art picture" below (in comments, first row
++ * is the keycode in hex, and subsequent row(s) shows
++ * the button labels (several variants when appropriate)
++ * helps to descide which keycodes to assign to the buttons.
++ */
++IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = {
++
++	/*  0x13   0x11   0x1C   0x12  *
++	 *  Mute  Source  TV/FM  Power *
++	 *                             */
++
++	[0x13] = KEY_MUTE,
++	[0x11] = KEY_PROPS,
++	[0x1C] = KEY_TUNER,	/* KEY_TV/KEY_RADIO */
++	[0x12] = KEY_POWER,
++
++	/*  0x01    0x02    0x03  0x0D    *
++	 *   1       2       3   Stereo   *
++	 *                        	  *
++	 *  0x04    0x05    0x06  0x19    *
++	 *   4       5       6   Snapshot *
++	 *                        	  *
++	 *  0x07    0x08    0x09  0x10    *
++	 *   7       8       9    Zoom 	  *
++	 *                                */
++	[0x01] = KEY_1,
++	[0x02] = KEY_2,
++	[0x03] = KEY_3,
++	[0x0D] = KEY_SETUP,	  /* Setup key */
++	[0x04] = KEY_4,
++	[0x05] = KEY_5,
++	[0x06] = KEY_6,
++	[0x19] = KEY_BOOKMARKS, /* Snapshot key */
++	[0x07] = KEY_7,
++	[0x08] = KEY_8,
++	[0x09] = KEY_9,
++	[0x10] = KEY_ZOOM,
++
++	/*  0x0A    0x00    0x0B       0x0C   *
++	 * RECALL    0    ChannelUp  VolumeUp *
++	 *                                    */
++	[0x0A] = KEY_AGAIN,
++	[0x00] = KEY_0,
++	[0x0B] = KEY_CHANNELUP,
++	[0x0C] = KEY_VOLUMEUP,
++
++	/*   0x1B      0x1D      0x15        0x18     *
++	 * Timeshift  Record  ChannelDown  VolumeDown *
++	 *                                            */
++
++	[0x1B] = KEY_REWIND,
++	[0x1D] = KEY_RECORD,
++	[0x15] = KEY_CHANNELDOWN,
++	[0x18] = KEY_VOLUMEDOWN,
++
++	/*   0x0E   0x1E     0x0F     0x1A  *
++	 *   Stop   Pause  Previouse  Next  *
++	 *                                  */
++
++	[0x0E] = KEY_STOP,
++	[0x1E] = KEY_PAUSE,
++	[0x0F] = KEY_PREVIOUS,
++	[0x1A] = KEY_NEXT,
++
++};
++EXPORT_SYMBOL_GPL(ir_codes_behold_columbus);
++
+ /*
+  * Remote control for the Genius TVGO A11MCE
+  * Adrian Pardini <pardo.bsso at gmail.com>
+@@ -2033,3 +2158,46 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = {
+ 	[0x50] = KEY_BLUE,
+ };
+ EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce);
++
++/*
++ * Remote control for Powercolor Real Angel 330
++ * Daniel Fraga <fragabr at gmail.com>
++ */
++IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = {
++	[0x38] = KEY_SWITCHVIDEOMODE,	/* switch inputs */
++	[0x0c] = KEY_MEDIA,		/* Turn ON/OFF App */
++	[0x00] = KEY_0,
++	[0x01] = KEY_1,
++	[0x02] = KEY_2,
++	[0x03] = KEY_3,
++	[0x04] = KEY_4,
++	[0x05] = KEY_5,
++	[0x06] = KEY_6,
++	[0x07] = KEY_7,
++	[0x08] = KEY_8,
++	[0x09] = KEY_9,
++	[0x0a] = KEY_DIGITS,		/* single, double, tripple digit */
++	[0x29] = KEY_PREVIOUS,		/* previous channel */
++	[0x12] = KEY_BRIGHTNESSUP,
++	[0x13] = KEY_BRIGHTNESSDOWN,
++	[0x2b] = KEY_MODE,		/* stereo/mono */
++	[0x2c] = KEY_TEXT,		/* teletext */
++	[0x20] = KEY_UP,		/* channel up */
++	[0x21] = KEY_DOWN,		/* channel down */
++	[0x10] = KEY_RIGHT,		/* volume up */
++	[0x11] = KEY_LEFT,		/* volume down */
++	[0x0d] = KEY_MUTE,
++	[0x1f] = KEY_RECORD,
++	[0x17] = KEY_PLAY,
++	[0x16] = KEY_PAUSE,
++	[0x0b] = KEY_STOP,
++	[0x27] = KEY_FASTFORWARD,
++	[0x26] = KEY_REWIND,
++	[0x1e] = KEY_SEARCH,		/* autoscan */
++	[0x0e] = KEY_SHUFFLE,		/* snapshot */
++	[0x2d] = KEY_SETUP,
++	[0x0f] = KEY_SCREEN,		/* full screen */
++	[0x14] = KEY_RADIO,		/* FM radio */
++	[0x25] = KEY_POWER,		/* power */
++};
++EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel);
+diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
+index 7707b8c..89c7660 100644
+--- a/drivers/media/common/saa7146_core.c
++++ b/drivers/media/common/saa7146_core.c
+@@ -74,7 +74,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
+ 		if (err) {
+ 			printk(KERN_ERR "%s: %s timed out while waiting for "
+ 					"registers getting programmed\n",
+-					dev->name, __FUNCTION__);
++					dev->name, __func__);
+ 			return -ETIMEDOUT;
+ 		}
+ 		msleep(1);
+@@ -89,7 +89,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
+ 		saa7146_read(dev, MC2);
+ 		if (err) {
+ 			DEB_S(("%s: %s timed out while waiting for transfer "
+-				"completion\n",	dev->name, __FUNCTION__));
++				"completion\n",	dev->name, __func__));
+ 			return -ETIMEDOUT;
+ 		}
+ 		msleep(1);
+@@ -111,7 +111,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
+ 		if (!loops--) {
+ 			printk(KERN_ERR "%s: %s timed out while waiting for "
+ 					"registers getting programmed\n",
+-					dev->name, __FUNCTION__);
++					dev->name, __func__);
+ 			return -ETIMEDOUT;
+ 		}
+ 		udelay(1);
+@@ -125,7 +125,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
+ 		saa7146_read(dev, MC2);
+ 		if (!loops--) {
+ 			DEB_S(("%s: %s timed out while waiting for transfer "
+-				"completion\n", dev->name, __FUNCTION__));
++				"completion\n", dev->name, __func__));
+ 			return -ETIMEDOUT;
+ 		}
+ 		udelay(5);
+diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
+index 7e7689a..35b01ec 100644
+--- a/drivers/media/common/saa7146_i2c.c
++++ b/drivers/media/common/saa7146_i2c.c
+@@ -203,7 +203,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
+ 				return -ERESTARTSYS;
+ 
+ 			printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+-				dev->name, __FUNCTION__);
++				dev->name, __func__);
+ 			return -EIO;
+ 		}
+ 		status = saa7146_read(dev, I2C_STATUS);
+@@ -221,7 +221,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
+ 			}
+ 			if (time_after(jiffies,timeout)) {
+ 				printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+-					dev->name, __FUNCTION__);
++					dev->name, __func__);
+ 				return -EIO;
+ 			}
+ 		}
+@@ -238,7 +238,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
+ 				 * (no answer from nonexisistant device...)
+ 				 */
+ 				printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+-					dev->name, __FUNCTION__);
++					dev->name, __func__);
+ 				return -EIO;
+ 			}
+ 			if (++trial < 50 && short_delay)
+diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
+index bfbd5a8..74e2b56 100644
+--- a/drivers/media/common/saa7146_vbi.c
++++ b/drivers/media/common/saa7146_vbi.c
+@@ -407,8 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
+ 	fh->vbi_fmt.start[1] = 312;
+ 	fh->vbi_fmt.count[1] = 16;
+ 
+-	videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VBI_CAPTURE,
+ 			    V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
+ 			    sizeof(struct saa7146_buf),
+diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
+index 66fdbd0..3cbc6eb 100644
+--- a/drivers/media/common/saa7146_video.c
++++ b/drivers/media/common/saa7146_video.c
+@@ -1410,8 +1410,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
+ 	sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+ 	fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
+ 
+-	videobuf_queue_pci_init(&fh->video_q, &video_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&fh->video_q, &video_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ 			    V4L2_FIELD_INTERLACED,
+ 			    sizeof(struct saa7146_buf),
+diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
+index 3197aeb..6ec5afb 100644
+--- a/drivers/media/dvb/b2c2/Kconfig
++++ b/drivers/media/dvb/b2c2/Kconfig
+@@ -9,6 +9,11 @@ config DVB_B2C2_FLEXCOP
+ 	select DVB_STV0297 if !DVB_FE_CUSTOMISE
+ 	select DVB_BCM3510 if !DVB_FE_CUSTOMISE
+ 	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
++	select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
++	select DVB_S5H1420 if !DVB_FE_CUSTOMISE
++	select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
++	select DVB_ISL6421 if !DVB_FE_CUSTOMISE
++	select DVB_CX24123 if !DVB_FE_CUSTOMISE
+ 	help
+ 	  Support for the digital TV receiver chip made by B2C2 Inc. included in
+ 	  Technisats PCI cards and USB boxes.
+diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
+index e97ff60..870e284 100644
+--- a/drivers/media/dvb/b2c2/Makefile
++++ b/drivers/media/dvb/b2c2/Makefile
+@@ -2,6 +2,7 @@ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
+ 	flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
+ obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
+ 
++
+ ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
+ b2c2-flexcop-objs += flexcop-dma.o
+ endif
+@@ -13,3 +14,4 @@ b2c2-flexcop-usb-objs = flexcop-usb.o
+ obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
+ 
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
++EXTRA_CFLAGS += -Idrivers/media/video/
+diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
+index 5a6c4fe..8ce0633 100644
+--- a/drivers/media/dvb/b2c2/flexcop-common.h
++++ b/drivers/media/dvb/b2c2/flexcop-common.h
+@@ -44,6 +44,14 @@ struct flexcop_dma {
+ 	u32 size; /* size of each address in bytes */
+ };
+ 
++struct flexcop_i2c_adapter {
++	struct flexcop_device *fc;
++	struct i2c_adapter i2c_adap;
++
++	u8 no_base_addr;
++	flexcop_i2c_port_t port;
++};
++
+ /* Control structure for data definitions that are common to
+  * the B2C2-based PCI and USB devices.
+  */
+@@ -72,7 +80,7 @@ struct flexcop_device {
+ 	struct dmx_frontend mem_frontend;
+ 	int (*fe_sleep) (struct dvb_frontend *);
+ 
+-	struct i2c_adapter i2c_adap;
++	struct flexcop_i2c_adapter fc_i2c_adap[3];
+ 	struct mutex i2c_mutex;
+ 	struct module *owner;
+ 
+@@ -87,7 +95,8 @@ struct flexcop_device {
+ 	int               (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value);
+ 
+ 
+-	int (*i2c_request) (struct flexcop_device*, flexcop_access_op_t, flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
++	int (*i2c_request) (struct flexcop_i2c_adapter*,
++		flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+ 	int (*stream_control) (struct flexcop_device*, int);
+ 
+ 	int (*get_mac_addr) (struct flexcop_device *fc, int extended);
+@@ -128,8 +137,8 @@ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
+  * one. We have it in flexcop-i2c.c, because it is going via the actual
+  * I2C-channel of the flexcop.
+  */
+-int flexcop_i2c_request(struct flexcop_device*, flexcop_access_op_t,
+-			flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
++int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t,
++	u8 chipaddr, u8 addr, u8 *buf, u16 len);
+ 
+ /* from flexcop-sram.c */
+ int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target);
+diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
+index 6f592bc..a91ed28 100644
+--- a/drivers/media/dvb/b2c2/flexcop-dma.c
++++ b/drivers/media/dvb/b2c2/flexcop-dma.c
+@@ -112,7 +112,7 @@ static int flexcop_dma_remap(struct flexcop_device *fc,
+ {
+ 	flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
+ 	flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+-	deb_info("%s\n",__FUNCTION__);
++	deb_info("%s\n",__func__);
+ 	v.dma_0xc.remap_enable = onoff;
+ 	fc->write_ibi_reg(fc,r,v);
+ 	return 0;
+@@ -162,7 +162,7 @@ int flexcop_dma_config_timer(struct flexcop_device *fc,
+ 
+ 	flexcop_dma_remap(fc,dma_idx,0);
+ 
+-	deb_info("%s\n",__FUNCTION__);
++	deb_info("%s\n",__func__);
+ 	v.dma_0x4_write.dmatimer = cycles;
+ 	fc->write_ibi_reg(fc,r,v);
+ 	return 0;
+diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c
+index bbcf070..8a8ae8a 100644
+--- a/drivers/media/dvb/b2c2/flexcop-eeprom.c
++++ b/drivers/media/dvb/b2c2/flexcop-eeprom.c
+@@ -114,15 +114,18 @@ static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t
+ {
+ 	int i,ret = 0;
+ 	u8 chipaddr =  0x50 | ((addr >> 8) & 3);
+-	for (i = 0; i < retries; i++)
+-		if ((ret = fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0)
++	for (i = 0; i < retries; i++) {
++		ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr,
++			addr & 0xff, buf, len);
++		if (ret == 0)
+ 			break;
++	}
+ 	return ret;
+ }
+ 
+ static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries)
+ {
+-	int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries);
++	int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries);
+ 	if (ret == 0)
+ 		if (calc_lrc(buf, len - 1) != buf[len - 1])
+ 			ret = -EINVAL;
+diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+index 0378fd6..7b0ea3b 100644
+--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
++++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+@@ -5,6 +5,8 @@
+  *
+  * see flexcop.c for copyright information.
+  */
++#include <media/tuner.h>
++
+ #include "flexcop.h"
+ 
+ #include "stv0299.h"
+@@ -15,6 +17,15 @@
+ #include "mt312.h"
+ #include "lgdt330x.h"
+ #include "dvb-pll.h"
++#include "tuner-simple.h"
++
++#include "s5h1420.h"
++#include "itd1000.h"
++
++#include "cx24123.h"
++#include "cx24113.h"
++
++#include "isl6421.h"
+ 
+ /* lnb control */
+ 
+@@ -180,13 +191,13 @@ static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dv
+ 	buf[2] = 0x84;  /* 0xC4 */
+ 	buf[3] = 0x08;
+ 
+-	if (params->frequency < 1500000) buf[3] |= 0x10;
++	if (params->frequency < 1500000)
++		buf[3] |= 0x10;
+ 
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+-	if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
++	if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
+ 		return -EIO;
+-	}
+ 	return 0;
+ }
+ 
+@@ -241,7 +252,7 @@ static struct stv0299_config samsung_tbmu24112_config = {
+ 	.mclk = 88000000UL,
+ 	.invert = 0,
+ 	.skip_reinit = 0,
+-	.lock_output = STV0229_LOCKOUTPUT_LK,
++	.lock_output = STV0299_LOCKOUTPUT_LK,
+ 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+ 	.min_delay_ms = 100,
+ 	.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
+@@ -337,7 +348,7 @@ static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe,
+ 
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+-	if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
++	if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
+ 		return -EIO;
+ 	return 0;
+ }
+@@ -386,10 +397,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 0);
+ 	deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
+-	ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3);
++	ret = fc->i2c_request(&fc->fc_i2c_adap[2],
++		FC_WRITE, 0x61, buf[0], &buf[1], 3);
+ 	deb_tuner("tuner write returned: %d\n",ret);
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ static u8 alps_tdee4_stv0297_inittab[] = {
+@@ -472,56 +484,159 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
+ //	.pll_set = alps_tdee4_stv0297_pll_set,
+ };
+ 
++
++/* SkyStar2 rev2.7 (a/u) */
++static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
++	.demod_address = 0x53,
++	.invert = 1,
++	.repeated_start_workaround = 1,
++};
++
++static struct itd1000_config skystar2_rev2_7_itd1000_config = {
++	.i2c_address = 0x61,
++};
++
++/* SkyStar2 rev2.8 */
++static struct cx24123_config skystar2_rev2_8_cx24123_config = {
++	.demod_address = 0x55,
++	.dont_use_pll = 1,
++	.agc_callback = cx24113_agc_callback,
++};
++
++static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
++	.i2c_addr = 0x54,
++	.xtal_khz = 10111,
++};
++
+ /* try to figure out the frontend, each card/box can have on of the following list */
+ int flexcop_frontend_init(struct flexcop_device *fc)
+ {
+ 	struct dvb_frontend_ops *ops;
++	struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap;
++	struct i2c_adapter *i2c_tuner;
++
++	/* enable no_base_addr - no repeated start when reading */
++	fc->fc_i2c_adap[0].no_base_addr = 1;
++	fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c);
++	if (fc->fe != NULL) {
++		flexcop_ibi_value r108;
++		i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
++		ops = &fc->fe->ops;
++
++		fc->fe_sleep = ops->sleep;
++		ops->sleep   = flexcop_sleep;
++
++		fc->dev_type = FC_SKY_REV27;
++
++		/* enable no_base_addr - no repeated start when reading */
++		fc->fc_i2c_adap[2].no_base_addr = 1;
++		if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
++			err("ISL6421 could NOT be attached");
++		else
++			info("ISL6421 successfully attached");
++
++		/* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */
++		r108.raw = 0x00000506;
++		fc->write_ibi_reg(fc, tw_sm_c_108, r108);
++		if (i2c_tuner) {
++			if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL)
++				err("ITD1000 could NOT be attached");
++			else
++				info("ITD1000 successfully attached");
++		}
++		goto fe_found;
++	}
++	fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */
++
++	/* try the sky v2.8 (cx24123, isl6421) */
++	fc->fe = dvb_attach(cx24123_attach,
++		&skystar2_rev2_8_cx24123_config, i2c);
++	if (fc->fe != NULL) {
++		i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
++		if (i2c_tuner != NULL) {
++			if (dvb_attach(cx24113_attach, fc->fe,
++					&skystar2_rev2_8_cx24113_config,
++					i2c_tuner) == NULL)
++				err("CX24113 could NOT be attached");
++			else
++				info("CX24113 successfully attached");
++		}
++
++		fc->dev_type = FC_SKY_REV28;
++
++		fc->fc_i2c_adap[2].no_base_addr = 1;
++		if (dvb_attach(isl6421_attach, fc->fe,
++		       &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL)
++			err("ISL6421 could NOT be attached");
++		else
++			info("ISL6421 successfully attached");
++
++		/* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
++		 * IR-receiver (PIC16F818) - but the card has no input for
++		 * that ??? */
++
++		goto fe_found;
++    }
+ 
+ 	/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
+-	if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
++	fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
++	if (fc->fe != NULL) {
+ 		ops = &fc->fe->ops;
+ 
+ 		ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
+ 
+ 		ops->set_voltage = flexcop_set_voltage;
+ 
+-		fc->fe_sleep             = ops->sleep;
+-		ops->sleep               = flexcop_sleep;
++		fc->fe_sleep = ops->sleep;
++		ops->sleep = flexcop_sleep;
++
++		fc->dev_type = FC_SKY;
++		goto fe_found;
++	}
+ 
+-		fc->dev_type          = FC_SKY;
+-		info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
+-	} else
+ 	/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
+-	if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
+-		fc->dev_type          = FC_AIR_DVB;
++	fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
++	if (fc->fe != NULL) {
++		fc->dev_type = FC_AIR_DVB;
+ 		fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
+-		info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
+-	} else
++		goto fe_found;
++	}
++
+ 	/* try the air atsc 2nd generation (nxt2002) */
+-	if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
+-		fc->dev_type          = FC_AIR_ATSC2;
++	fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
++	if (fc->fe != NULL) {
++		fc->dev_type = FC_AIR_ATSC2;
+ 		dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV);
+-		info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
+-	} else
+-	/* try the air atsc 3nd generation (lgdt3303) */
+-	if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
+-		fc->dev_type          = FC_AIR_ATSC3;
+-		dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
+-		info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
+-	} else
++		goto fe_found;
++	}
++
++	fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
++	if (fc->fe != NULL) {
++		fc->dev_type = FC_AIR_ATSC3;
++		dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
++				TUNER_LG_TDVS_H06XF);
++		goto fe_found;
++	}
++
+ 	/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
+-	if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
+-		fc->dev_type          = FC_AIR_ATSC1;
+-		info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
+-	} else
++	fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
++	if (fc->fe != NULL) {
++		fc->dev_type = FC_AIR_ATSC1;
++		goto fe_found;
++	}
++
+ 	/* try the cable dvb (stv0297) */
+-	if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
+-		fc->dev_type                        = FC_CABLE;
++	fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
++	if (fc->fe != NULL) {
++		fc->dev_type = FC_CABLE;
+ 		fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
+-		info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
+-	} else
++		goto fe_found;
++	}
++
+ 	/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
+-	if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
++	fc->fe = dvb_attach(vp310_mt312_attach,
++		&skystar23_samsung_tbdu18132_config, i2c);
++	if (fc->fe != NULL) {
+ 		ops = &fc->fe->ops;
+ 
+ 		ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
+@@ -535,19 +650,21 @@ int flexcop_frontend_init(struct flexcop_device *fc)
+ 		ops->sleep                  = flexcop_sleep;
+ 
+ 		fc->dev_type                = FC_SKY_OLD;
+-		info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
++		goto fe_found;
+ 	}
+ 
+-	if (fc->fe == NULL) {
+-		err("no frontend driver found for this B2C2/FlexCop adapter");
+-		return -ENODEV;
+-	} else {
+-		if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
+-			err("frontend registration failed!");
+-			dvb_frontend_detach(fc->fe);
+-			fc->fe = NULL;
+-			return -EINVAL;
+-		}
++	err("no frontend driver found for this B2C2/FlexCop adapter");
++	return -ENODEV;
++
++fe_found:
++	info("found '%s' .", fc->fe->ops.info.name);
++	if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
++		err("frontend registration failed!");
++		ops = &fc->fe->ops;
++		if (ops->release != NULL)
++			ops->release(fc->fe);
++		fc->fe = NULL;
++		return -EINVAL;
+ 	}
+ 	fc->init_state |= FC_STATE_FE_INIT;
+ 	return 0;
+diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
+index 6bf858a..55973ea 100644
+--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
++++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
+@@ -9,6 +9,8 @@
+ 
+ #define FC_MAX_I2C_RETRIES 100000
+ 
++/* #define DUMP_I2C_MESSAGES */
++
+ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
+ {
+ 	int i;
+@@ -38,30 +40,25 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
+ 	return -EREMOTEIO;
+ }
+ 
+-static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf)
++static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
++	flexcop_ibi_value r100, u8 *buf)
+ {
+ 	flexcop_ibi_value r104;
+ 	int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
+ 		ret;
+ 
+-	if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
+-		/* The Cablestar needs a different kind of i2c-transfer (does not
+-		 * support "Repeat Start"):
+-		 * wait for the ACK failure,
+-		 * and do a subsequent read with the Bit 30 enabled
+-		 */
+-		r100.tw_sm_c_100.no_base_addr_ack_error = 1;
+-		if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
+-			deb_i2c("no_base_addr read failed. %d\n",ret);
+-			return ret;
+-		}
++	r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
++	ret = flexcop_i2c_operation(i2c->fc, &r100);
++	if (ret != 0) {
++		deb_i2c("read failed. %d\n", ret);
++		return ret;
+ 	}
+ 
+ 	buf[0] = r100.tw_sm_c_100.data1_reg;
+ 
+ 	if (len > 0) {
+-		r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
+-		deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
++		r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
++		deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
+ 
+ 		/* there is at least one more byte, otherwise we wouldn't be here */
+ 		buf[1] = r104.tw_sm_c_104.data2_reg;
+@@ -85,17 +82,22 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100,
+ 	r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
+ 	r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
+ 
+-	deb_i2c("write: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
++	deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
+ 
+ 	/* write the additional i2c data before doing the actual i2c operation */
+-	fc->write_ibi_reg(fc,tw_sm_c_104,r104);
+-	return flexcop_i2c_operation(fc,&r100);
++	fc->write_ibi_reg(fc, tw_sm_c_104, r104);
++	return flexcop_i2c_operation(fc, &r100);
+ }
+ 
+-int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+-		flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
++int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
++	flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+ {
+ 	int ret;
++
++#ifdef DUMP_I2C_MESSAGES
++	int i;
++#endif
++
+ 	u16 bytes_to_transfer;
+ 	flexcop_ibi_value r100;
+ 
+@@ -103,7 +105,25 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+ 	r100.raw = 0;
+ 	r100.tw_sm_c_100.chipaddr = chipaddr;
+ 	r100.tw_sm_c_100.twoWS_rw = op;
+-	r100.tw_sm_c_100.twoWS_port_reg = port;
++	r100.tw_sm_c_100.twoWS_port_reg = i2c->port;
++
++#ifdef DUMP_I2C_MESSAGES
++	printk(KERN_DEBUG "%d ", i2c->port);
++	if (op == FC_READ)
++		printk("rd(");
++	else
++		printk("wr(");
++
++	printk("%02x): %02x ", chipaddr, addr);
++#endif
++
++	/* in that case addr is the only value ->
++	 * we write it twice as baseaddr and val0
++	 * BBTI is doing it like that for ISL6421 at least */
++	if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
++		buf = &addr;
++		len = 1;
++	}
+ 
+ 	while (len != 0) {
+ 		bytes_to_transfer = len > 4 ? 4 : len;
+@@ -112,9 +132,14 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+ 		r100.tw_sm_c_100.baseaddr = addr;
+ 
+ 		if (op == FC_READ)
+-			ret = flexcop_i2c_read4(fc, r100, buf);
++			ret = flexcop_i2c_read4(i2c, r100, buf);
+ 		else
+-			ret = flexcop_i2c_write4(fc,r100, buf);
++			ret = flexcop_i2c_write4(i2c->fc, r100, buf);
++
++#ifdef DUMP_I2C_MESSAGES
++		for (i = 0; i < bytes_to_transfer; i++)
++			printk("%02x ", buf[i]);
++#endif
+ 
+ 		if (ret < 0)
+ 			return ret;
+@@ -122,7 +147,11 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+ 		buf  += bytes_to_transfer;
+ 		addr += bytes_to_transfer;
+ 		len  -= bytes_to_transfer;
+-	};
++	}
++
++#ifdef DUMP_I2C_MESSAGES
++	printk("\n");
++#endif
+ 
+ 	return 0;
+ }
+@@ -132,7 +161,7 @@ EXPORT_SYMBOL(flexcop_i2c_request);
+ /* master xfer callback for demodulator */
+ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+ {
+-	struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
++	struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
+ 	int i, ret = 0;
+ 
+ 	/* Some drivers use 1 byte or 0 byte reads as probes, which this
+@@ -142,34 +171,29 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
+ 	if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
+ 		return 1;
+ 
+-	if (mutex_lock_interruptible(&fc->i2c_mutex))
++	if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
+ 		return -ERESTARTSYS;
+ 
+-	/* reading */
+-	if (num == 2 &&
+-		msgs[0].flags == 0 &&
+-		msgs[1].flags == I2C_M_RD &&
+-		msgs[0].buf != NULL &&
+-		msgs[1].buf != NULL) {
+-
+-		ret = fc->i2c_request(fc, FC_READ, FC_I2C_PORT_DEMOD, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
+-
+-	} else for (i = 0; i < num; i++) { /* writing command */
+-		if (msgs[i].flags != 0 || msgs[i].buf == NULL || msgs[i].len < 2) {
+-			ret = -EINVAL;
++	for (i = 0; i < num; i++) {
++		/* reading */
++		if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {
++			ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr,
++				msgs[i].buf[0], msgs[i+1].buf, msgs[i+1].len);
++			i++; /* skip the following message */
++		} else /* writing */
++			ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
++				msgs[i].buf[0], &msgs[i].buf[1],
++				msgs[i].len - 1);
++		if (ret < 0) {
++			err("i2c master_xfer failed");
+ 			break;
+ 		}
+-
+-		ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_DEMOD, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1);
+ 	}
+ 
+-	if (ret < 0)
+-		err("i2c master_xfer failed");
+-	else
+-		ret = num;
+-
+-	mutex_unlock(&fc->i2c_mutex);
++	mutex_unlock(&i2c->fc->i2c_mutex);
+ 
++	if (ret == 0)
++		ret = num;
+ 	return ret;
+ }
+ 
+@@ -189,28 +213,68 @@ int flexcop_i2c_init(struct flexcop_device *fc)
+ 
+ 	mutex_init(&fc->i2c_mutex);
+ 
+-	memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
+-	strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",
+-		sizeof(fc->i2c_adap.name));
+-
+-	i2c_set_adapdata(&fc->i2c_adap,fc);
++	fc->fc_i2c_adap[0].fc = fc;
++	fc->fc_i2c_adap[1].fc = fc;
++	fc->fc_i2c_adap[2].fc = fc;
++
++	fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;
++	fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
++	fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
++
++	strncpy(fc->fc_i2c_adap[0].i2c_adap.name,
++		"B2C2 FlexCop I2C to demod", I2C_NAME_SIZE);
++	strncpy(fc->fc_i2c_adap[1].i2c_adap.name,
++		"B2C2 FlexCop I2C to eeprom", I2C_NAME_SIZE);
++	strncpy(fc->fc_i2c_adap[2].i2c_adap.name,
++		"B2C2 FlexCop I2C to tuner", I2C_NAME_SIZE);
++
++	i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
++	i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
++	i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
++
++	fc->fc_i2c_adap[0].i2c_adap.class =
++		fc->fc_i2c_adap[1].i2c_adap.class =
++		fc->fc_i2c_adap[2].i2c_adap.class = I2C_CLASS_TV_DIGITAL;
++	fc->fc_i2c_adap[0].i2c_adap.algo =
++		fc->fc_i2c_adap[1].i2c_adap.algo =
++		fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
++	fc->fc_i2c_adap[0].i2c_adap.algo_data =
++		fc->fc_i2c_adap[1].i2c_adap.algo_data =
++		fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL;
++	fc->fc_i2c_adap[0].i2c_adap.dev.parent =
++		fc->fc_i2c_adap[1].i2c_adap.dev.parent =
++		fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev;
++
++	ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap);
++	if (ret < 0)
++		return ret;
+ 
+-	fc->i2c_adap.class	    = I2C_CLASS_TV_DIGITAL;
+-	fc->i2c_adap.algo       = &flexcop_algo;
+-	fc->i2c_adap.algo_data  = NULL;
+-	fc->i2c_adap.dev.parent	= fc->dev;
++	ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap);
++	if (ret < 0)
++		goto adap_1_failed;
+ 
+-	if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
+-		return ret;
++	ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap);
++	if (ret < 0)
++		goto adap_2_failed;
+ 
+ 	fc->init_state |= FC_STATE_I2C_INIT;
+ 	return 0;
++
++adap_2_failed:
++	i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
++adap_1_failed:
++	i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
++
++	return ret;
+ }
+ 
+ void flexcop_i2c_exit(struct flexcop_device *fc)
+ {
+-	if (fc->init_state & FC_STATE_I2C_INIT)
+-		i2c_del_adapter(&fc->i2c_adap);
++	if (fc->init_state & FC_STATE_I2C_INIT) {
++		i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap);
++		i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
++		i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
++	}
+ 
+ 	fc->init_state &= ~FC_STATE_I2C_INIT;
+ }
+diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
+index 167583b..93d20e5 100644
+--- a/drivers/media/dvb/b2c2/flexcop-misc.c
++++ b/drivers/media/dvb/b2c2/flexcop-misc.c
+@@ -52,6 +52,8 @@ static const char *flexcop_device_names[] = {
+ 	"Sky2PC/SkyStar 2 DVB-S (old version)",
+ 	"Cable2PC/CableStar 2 DVB-C",
+ 	"Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
++	"Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
++	"Sky2PC/SkyStar 2 DVB-S rev 2.8",
+ };
+ 
+ static const char *flexcop_bus_names[] = {
+diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
+index 01af4d2..5b30dfc 100644
+--- a/drivers/media/dvb/b2c2/flexcop-pci.c
++++ b/drivers/media/dvb/b2c2/flexcop-pci.c
+@@ -32,7 +32,7 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus
+ #define deb_irq(args...)   dprintk(0x08,args)
+ #define deb_chk(args...)   dprintk(0x10,args)
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS);
+ 
+diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
+index 491f9bd..7599fcc 100644
+--- a/drivers/media/dvb/b2c2/flexcop-reg.h
++++ b/drivers/media/dvb/b2c2/flexcop-reg.h
+@@ -25,6 +25,8 @@ typedef enum {
+ 	FC_SKY_OLD,
+ 	FC_CABLE,
+ 	FC_AIR_ATSC3,
++	FC_SKY_REV27,
++	FC_SKY_REV28,
+ } flexcop_device_type_t;
+ 
+ typedef enum {
+diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/dvb/b2c2/flexcop-sram.c
+index 01570ec..cda6952 100644
+--- a/drivers/media/dvb/b2c2/flexcop-sram.c
++++ b/drivers/media/dvb/b2c2/flexcop-sram.c
+@@ -90,7 +90,7 @@ static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *
+ 		};
+ 
+ 		if (retries == 0)
+-			printk("%s: SRAM timeout\n", __FUNCTION__);
++			printk("%s: SRAM timeout\n", __func__);
+ 
+ 		write_reg_dw(adapter, 0x700, command);
+ 
+@@ -115,7 +115,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
+ 		};
+ 
+ 		if (retries == 0)
+-			printk("%s: SRAM timeout\n", __FUNCTION__);
++			printk("%s: SRAM timeout\n", __func__);
+ 
+ 		write_reg_dw(adapter, 0x700, command);
+ 
+@@ -127,7 +127,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
+ 		};
+ 
+ 		if (retries == 0)
+-			printk("%s: SRAM timeout\n", __FUNCTION__);
++			printk("%s: SRAM timeout\n", __func__);
+ 
+ 		value = read_reg_dw(adapter, 0x700) >> 0x10;
+ 
+@@ -240,13 +240,13 @@ static void sram_init(struct adapter *adapter)
+ 
+ 		adapter->dw_sram_type = tmp & 0x30000;
+ 
+-		ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
++		ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
+ 
+ 	} else {
+ 
+ 		adapter->dw_sram_type = 0x10000;
+ 
+-		ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
++		ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
+ 	}
+ 
+ 	/* return value is never used? */
+@@ -257,7 +257,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+ {
+ 	u8 tmp1, tmp2;
+ 
+-	dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
++	dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
+ 
+ 	sram_set_size(adapter, mask);
+ 	sram_init(adapter);
+@@ -275,7 +275,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+ 	sram_read(adapter, addr, &tmp2, 1);
+ 	sram_read(adapter, addr, &tmp2, 1);
+ 
+-	dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2);
++	dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2);
+ 
+ 	if (tmp2 != 0xa5)
+ 		return 0;
+@@ -293,7 +293,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+ 	sram_read(adapter, addr, &tmp2, 1);
+ 	sram_read(adapter, addr, &tmp2, 1);
+ 
+-	dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2);
++	dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2);
+ 
+ 	if (tmp2 != 0x5a)
+ 		return 0;
+@@ -340,7 +340,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ 
+ 	tmp3 = read_reg_dw(adapter, 0x71c);
+ 
+-	dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
++	dprintk("%s: tmp3 = %x\n", __func__, tmp3);
+ 
+ 	write_reg_dw(adapter, 0x71c, tmp2);
+ 
+@@ -351,7 +351,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ 		sram_init(adapter);
+ 		write_reg_dw(adapter, 0x208, tmp);
+ 
+-		dprintk("%s: sram size = 32K\n", __FUNCTION__);
++		dprintk("%s: sram size = 32K\n", __func__);
+ 
+ 		return 32;
+ 	}
+@@ -361,7 +361,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ 		sram_init(adapter);
+ 		write_reg_dw(adapter, 0x208, tmp);
+ 
+-		dprintk("%s: sram size = 128K\n", __FUNCTION__);
++		dprintk("%s: sram size = 128K\n", __func__);
+ 
+ 		return 128;
+ 	}
+@@ -371,7 +371,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ 		sram_init(adapter);
+ 		write_reg_dw(adapter, 0x208, tmp);
+ 
+-		dprintk("%s: sram size = 64K\n", __FUNCTION__);
++		dprintk("%s: sram size = 64K\n", __func__);
+ 
+ 		return 64;
+ 	}
+@@ -381,7 +381,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ 		sram_init(adapter);
+ 		write_reg_dw(adapter, 0x208, tmp);
+ 
+-		dprintk("%s: sram size = 32K\n", __FUNCTION__);
++		dprintk("%s: sram size = 32K\n", __func__);
+ 
+ 		return 32;
+ 	}
+@@ -390,7 +390,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ 	sram_init(adapter);
+ 	write_reg_dw(adapter, 0x208, tmp);
+ 
+-	dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
++	dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
+index 87fb75f..449fb5c 100644
+--- a/drivers/media/dvb/b2c2/flexcop-usb.c
++++ b/drivers/media/dvb/b2c2/flexcop-usb.c
+@@ -211,10 +211,11 @@ static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
+ #endif
+ 
+ /* usb i2c stuff */
+-static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
++static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
+ 		flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
+-		flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
++		u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
+ {
++	struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
+ 	u16 wValue, wIndex;
+ 	int nWaitTime,pipe,len;
+ //	u8 dwRequestType;
+@@ -242,7 +243,7 @@ static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
+ 			deb_info("unsupported function for i2c_req %x\n",func);
+ 			return -EINVAL;
+ 	}
+-	wValue = (func << 8 ) | (port << 4);
++	wValue = (func << 8) | (i2c->port << 4);
+ 	wIndex = (chipaddr << 8 ) | addr;
+ 
+ 	deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req,
+@@ -274,13 +275,15 @@ static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi
+ 	return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0);
+ }
+ 
+-static int flexcop_usb_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+-		flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
++static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c,
++	flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+ {
+ 	if (op == FC_READ)
+-		return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_READ,port,chipaddr,addr,buf,len);
++		return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
++			USB_FUNC_I2C_READ, chipaddr, addr, buf, len);
+ 	else
+-		return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len);
++		return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
++			USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len);
+ }
+ 
+ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length)
+diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
+index 2ddafd0..5f79c8d 100644
+--- a/drivers/media/dvb/b2c2/flexcop.c
++++ b/drivers/media/dvb/b2c2/flexcop.c
+@@ -49,6 +49,8 @@ module_param_named(debug, b2c2_flexcop_debug,  int, 0644);
+ MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS);
+ #undef DEBSTATUS
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* global zero for ibi values */
+ flexcop_ibi_value ibi_zero;
+ 
+@@ -66,8 +68,10 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+ 
+ static int flexcop_dvb_init(struct flexcop_device *fc)
+ {
+-	int ret;
+-	if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
++	int ret = dvb_register_adapter(&fc->dvb_adapter,
++				       "FlexCop Digital TV device", fc->owner,
++				       fc->dev, adapter_nr);
++	if (ret < 0) {
+ 		err("error registering DVB adapter");
+ 		return ret;
+ 	}
+@@ -257,6 +261,12 @@ int flexcop_device_initialize(struct flexcop_device *fc)
+ 	if ((ret = flexcop_dvb_init(fc)))
+ 		goto error;
+ 
++	/* i2c has to be done before doing EEProm stuff -
++	 * because the EEProm is accessed via i2c */
++	ret = flexcop_i2c_init(fc);
++	if (ret)
++		goto error;
++
+ 	/* do the MAC address reading after initializing the dvb_adapter */
+ 	if (fc->get_mac_addr(fc, 0) == 0) {
+ 		u8 *b = fc->dvb_adapter.proposed_mac;
+@@ -266,10 +276,6 @@ int flexcop_device_initialize(struct flexcop_device *fc)
+ 	} else
+ 		warn("reading of MAC address failed.\n");
+ 
+-
+-	if ((ret = flexcop_i2c_init(fc)))
+-		goto error;
+-
+ 	if ((ret = flexcop_frontend_init(fc)))
+ 		goto error;
+ 
+diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
+index ea66617..902c762 100644
+--- a/drivers/media/dvb/bt8xx/Kconfig
++++ b/drivers/media/dvb/bt8xx/Kconfig
+@@ -7,8 +7,8 @@ config DVB_BT8XX
+ 	select DVB_CX24110 if !DVB_FE_CUSTOMISE
+ 	select DVB_OR51211 if !DVB_FE_CUSTOMISE
+ 	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+-	select DVB_PLL if !DVB_FE_CUSTOMISE
+ 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
++	select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ 	select FW_LOADER
+ 	help
+ 	  Support for PCI cards based on the Bt8xx PCI bridge. Examples are
+diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile
+index 84cf705..9d3e68b 100644
+--- a/drivers/media/dvb/bt8xx/Makefile
++++ b/drivers/media/dvb/bt8xx/Makefile
+@@ -1,3 +1,6 @@
+ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
+ 
+-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends
++EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
++EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
++EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
++EXTRA_CFLAGS += -Idrivers/media/video
+diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
+index 307ff35..75711bd 100644
+--- a/drivers/media/dvb/bt8xx/dst.c
++++ b/drivers/media/dvb/bt8xx/dst.c
+@@ -1290,7 +1290,7 @@ static int dst_get_signal(struct dst_state *state)
+ {
+ 	int retval;
+ 	u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
+-	//dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
++	//dprintk("%s: Getting Signal strength and other parameters\n", __func__);
+ 	if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
+ 		state->decode_lock = state->decode_strength = state->decode_snr = 0;
+ 		return 0;
+diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
+index 50bc32a..0258451 100644
+--- a/drivers/media/dvb/bt8xx/dst_ca.c
++++ b/drivers/media/dvb/bt8xx/dst_ca.c
+@@ -36,13 +36,13 @@
+ #define dprintk(x, y, z, format, arg...) do {						\
+ 	if (z) {									\
+ 		if	((x > DST_CA_ERROR) && (x > y))					\
+-			printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg);	\
++			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);	\
+ 		else if	((x > DST_CA_NOTICE) && (x > y))				\
+-			printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg);	\
++			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+ 		else if ((x > DST_CA_INFO) && (x > y))					\
+-			printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg);	\
++			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);	\
+ 		else if ((x > DST_CA_DEBUG) && (x > y))					\
+-			printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg);	\
++			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+ 	} else {									\
+ 		if (x > y)								\
+ 			printk(format, ## arg);						\
+@@ -162,7 +162,7 @@ static int ca_get_app_info(struct dst_state *state)
+ 	dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
+ 	dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
+ 		state->messages[7], (state->messages[8] << 8) | state->messages[9],
+-		(state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
++		(state->messages[10] << 8) | state->messages[11], __func__, (char *)(&state->messages[12]));
+ 	dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
+ 
+ 	// Transform dst message to correct application_info message
+diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+index dedd30a..6afbfbb 100644
+--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
++++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+@@ -40,10 +40,12 @@ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk( args... ) \
+-	do \
++	do { \
+ 		if (debug) printk(KERN_DEBUG args); \
+-	while (0)
++	} while (0)
+ 
+ #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
+ 
+@@ -609,8 +611,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
+ 		lgdt330x_reset(card);
+ 		card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
+ 		if (card->fe != NULL) {
+-			dvb_attach(dvb_pll_attach, card->fe, 0x61,
+-				   card->i2c_adapter, DVB_PLL_LG_TDVS_H06XF);
++			dvb_attach(simple_tuner_attach, card->fe,
++				   card->i2c_adapter, 0x61,
++				   TUNER_LG_TDVS_H06XF);
+ 			dprintk ("dvb_bt8xx: lgdt330x detected\n");
+ 		}
+ 		break;
+@@ -670,7 +673,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
+ 		state->dst_ca = NULL;
+ 		/*	DST is not a frontend, attaching the ASIC	*/
+ 		if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
+-			printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
++			printk("%s: Could not find a Twinhan DST.\n", __func__);
+ 			break;
+ 		}
+ 		/*	Attach other DST peripherals if any		*/
+@@ -692,8 +695,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
+ 	case BTTV_BOARD_PC_HDTV:
+ 		card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
+ 		if (card->fe != NULL)
+-			dvb_attach(dvb_pll_attach, card->fe, 0x61,
+-				   card->i2c_adapter, DVB_PLL_FCV1236D);
++			dvb_attach(simple_tuner_attach, card->fe,
++				   card->i2c_adapter, 0x61,
++				   TUNER_PHILIPS_FCV1236D);
+ 		break;
+ 	}
+ 
+@@ -715,7 +719,10 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
+ {
+ 	int result;
+ 
+-	if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
++	result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
++				      THIS_MODULE, &card->bt->dev->dev,
++				      adapter_nr);
++	if (result < 0) {
+ 		printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
+ 		return result;
+ 	}
+diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+index 436880e..4499ed2 100644
+--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
++++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+@@ -38,7 +38,7 @@
+ #include "or51211.h"
+ #include "lgdt330x.h"
+ #include "zl10353.h"
+-#include "dvb-pll.h"
++#include "tuner-simple.h"
+ 
+ struct dvb_bt8xx_card {
+ 	struct mutex lock;
+diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
+index db08b0a..f5010e8 100644
+--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
++++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
+@@ -58,11 +58,13 @@ static int debug;
+ module_param_named(debug, debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk(level, args...)						\
+ do {									\
+ 	if ((debug & level)) {						\
+ 		printk("%s: %s(): ", KBUILD_MODNAME,			\
+-		       __FUNCTION__);					\
++		       __func__);					\
+ 		printk(args); }						\
+ } while (0)
+ 
+@@ -938,7 +940,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
+ 		return -ENOMEM;
+ 	}
+ 
+-	if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
++	err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME,
++				   THIS_MODULE, &cinergyt2->udev->dev,
++				   adapter_nr);
++	if (err < 0) {
+ 		kfree(cinergyt2);
+ 		return err;
+ 	}
+diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
+index 0c1d87c..b0d347d 100644
+--- a/drivers/media/dvb/dvb-core/demux.h
++++ b/drivers/media/dvb/dvb-core/demux.h
+@@ -80,6 +80,8 @@ enum dmx_success {
+ #define	TS_PAYLOAD_ONLY 2   /* in case TS_PACKET is set, only send the TS
+ 			       payload (<=184 bytes per packet) to callback */
+ #define TS_DECODER      4   /* send stream to built-in decoder (if present) */
++#define TS_DEMUX        8   /* in case TS_PACKET is set, send the TS to
++			       the demux device, not to the dvr device */
+ 
+ /* PES type for filters which write to built-in decoder */
+ /* these should be kept identical to the types in dmx.h */
+diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
+index f94bc31..df5bef6 100644
+--- a/drivers/media/dvb/dvb-core/dmxdev.c
++++ b/drivers/media/dvb/dvb-core/dmxdev.c
+@@ -126,7 +126,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
+ 	struct dmxdev *dmxdev = dvbdev->priv;
+ 	struct dmx_frontend *front;
+ 
+-	dprintk("function : %s\n", __FUNCTION__);
++	dprintk("function : %s\n", __func__);
+ 
+ 	if (mutex_lock_interruptible(&dmxdev->mutex))
+ 		return -ERESTARTSYS;
+@@ -259,6 +259,39 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
+ 	return ret;
+ }
+ 
++static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
++				      unsigned long size)
++{
++	struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer;
++	void *newmem;
++	void *oldmem;
++
++	dprintk("function : %s\n", __func__);
++
++	if (buf->size == size)
++		return 0;
++	if (!size)
++		return -EINVAL;
++
++	newmem = vmalloc(size);
++	if (!newmem)
++		return -ENOMEM;
++
++	oldmem = buf->data;
++
++	spin_lock_irq(&dmxdev->lock);
++	buf->data = newmem;
++	buf->size = size;
++
++	/* reset and not flush in case the buffer shrinks */
++	dvb_ringbuffer_reset(buf);
++	spin_unlock_irq(&dmxdev->lock);
++
++	vfree(oldmem);
++
++	return 0;
++}
++
+ static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
+ 					       *dmxdevfilter, int state)
+ {
+@@ -271,28 +304,32 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
+ 				      unsigned long size)
+ {
+ 	struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
+-	void *mem;
++	void *newmem;
++	void *oldmem;
+ 
+ 	if (buf->size == size)
+ 		return 0;
++	if (!size)
++		return -EINVAL;
+ 	if (dmxdevfilter->state >= DMXDEV_STATE_GO)
+ 		return -EBUSY;
++
++	newmem = vmalloc(size);
++	if (!newmem)
++		return -ENOMEM;
++
++	oldmem = buf->data;
++
+ 	spin_lock_irq(&dmxdevfilter->dev->lock);
+-	mem = buf->data;
+-	buf->data = NULL;
++	buf->data = newmem;
+ 	buf->size = size;
+-	dvb_ringbuffer_flush(buf);
++
++	/* reset and not flush in case the buffer shrinks */
++	dvb_ringbuffer_reset(buf);
+ 	spin_unlock_irq(&dmxdevfilter->dev->lock);
+-	vfree(mem);
+ 
+-	if (buf->size) {
+-		mem = vmalloc(dmxdevfilter->buffer.size);
+-		if (!mem)
+-			return -ENOMEM;
+-		spin_lock_irq(&dmxdevfilter->dev->lock);
+-		buf->data = mem;
+-		spin_unlock_irq(&dmxdevfilter->dev->lock);
+-	}
++	vfree(oldmem);
++
+ 	return 0;
+ }
+ 
+@@ -374,7 +411,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
+ 		return 0;
+ 	}
+ 
+-	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP)
++	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
++	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
+ 		buffer = &dmxdevfilter->buffer;
+ 	else
+ 		buffer = &dmxdevfilter->dev->dvr_buffer;
+@@ -550,7 +588,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
+ 								   dvb_dmxdev_section_callback);
+ 			if (ret < 0) {
+ 				printk("DVB (%s): could not alloc feed\n",
+-				       __FUNCTION__);
++				       __func__);
+ 				return ret;
+ 			}
+ 
+@@ -558,7 +596,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
+ 					      (para->flags & DMX_CHECK_CRC) ? 1 : 0);
+ 			if (ret < 0) {
+ 				printk("DVB (%s): could not set feed\n",
+-				       __FUNCTION__);
++				       __func__);
+ 				dvb_dmxdev_feed_restart(filter);
+ 				return ret;
+ 			}
+@@ -620,9 +658,10 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
+ 
+ 		if (otype == DMX_OUT_TS_TAP)
+ 			ts_type |= TS_PACKET;
+-
+-		if (otype == DMX_OUT_TAP)
+-			ts_type |= TS_PAYLOAD_ONLY | TS_PACKET;
++		else if (otype == DMX_OUT_TSDEMUX_TAP)
++			ts_type |= TS_PACKET | TS_DEMUX;
++		else if (otype == DMX_OUT_TAP)
++			ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY;
+ 
+ 		ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux,
+ 						      tsfeed,
+@@ -732,7 +771,7 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
+ 				 struct dmxdev_filter *dmxdevfilter,
+ 				 struct dmx_sct_filter_params *params)
+ {
+-	dprintk("function : %s\n", __FUNCTION__);
++	dprintk("function : %s\n", __func__);
+ 
+ 	dvb_dmxdev_filter_stop(dmxdevfilter);
+ 
+@@ -1007,6 +1046,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
+ {
+ 	struct dvb_device *dvbdev = file->private_data;
+ 	struct dmxdev *dmxdev = dvbdev->priv;
++	unsigned long arg = (unsigned long)parg;
+ 	int ret;
+ 
+ 	if (mutex_lock_interruptible(&dmxdev->mutex))
+@@ -1014,8 +1054,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
+ 
+ 	switch (cmd) {
+ 	case DMX_SET_BUFFER_SIZE:
+-		// FIXME: implement
+-		ret = 0;
++		ret = dvb_dvr_set_buffer_size(dmxdev, arg);
+ 		break;
+ 
+ 	default:
+@@ -1038,7 +1077,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
+ 	struct dmxdev *dmxdev = dvbdev->priv;
+ 	unsigned int mask = 0;
+ 
+-	dprintk("function : %s\n", __FUNCTION__);
++	dprintk("function : %s\n", __func__);
+ 
+ 	poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
+ 
+diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+index 89437fd..8cbdb0e 100644
+--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
++++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+@@ -250,7 +250,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
+ 	unsigned long timeout;
+ 	unsigned long start;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* loop until timeout elapsed */
+ 	start = jiffies;
+@@ -263,7 +263,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
+ 
+ 		/* if we got the flags, it was successful! */
+ 		if (res & waitfor) {
+-			dprintk("%s succeeded timeout:%lu\n", __FUNCTION__, jiffies - start);
++			dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start);
+ 			return 0;
+ 		}
+ 
+@@ -276,7 +276,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
+ 		msleep(1);
+ 	}
+ 
+-	dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start);
++	dprintk("%s failed timeout:%lu\n", __func__, jiffies - start);
+ 
+ 	/* if we get here, we've timed out */
+ 	return -ETIMEDOUT;
+@@ -297,7 +297,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
+ 	int buf_size;
+ 	u8 buf[2];
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* we'll be determining these during this function */
+ 	ca->slot_info[slot].da_irq_supported = 0;
+@@ -549,7 +549,7 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
+ {
+ 	int configoption;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* set the config option */
+ 	ca->pub->write_attribute_mem(ca->pub, slot,
+@@ -587,7 +587,7 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb
+ 	u8 buf[HOST_LINK_BUF_SIZE];
+ 	int i;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* check if we have space for a link buf in the rx_buffer */
+ 	if (ebuf == NULL) {
+@@ -708,7 +708,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
+ 	int status;
+ 	int i;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 
+ 	// sanity check
+@@ -785,7 +785,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
+  */
+ static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot)
+ {
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	ca->pub->slot_shutdown(ca->pub, slot);
+ 	ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+@@ -892,7 +892,7 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
+ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
+ {
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	ca->wakeup = 1;
+ 	mb();
+@@ -964,7 +964,7 @@ static int dvb_ca_en50221_thread(void *data)
+ 	int pktcount;
+ 	void *rxbuf;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* choose the correct initial delay */
+ 	dvb_ca_en50221_thread_update_delay(ca);
+@@ -1172,7 +1172,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
+ 	int err = 0;
+ 	int slot;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	switch (cmd) {
+ 	case CA_RESET:
+@@ -1266,7 +1266,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
+ 	unsigned long timeout;
+ 	int written;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
+ 	if (count < 2)
+@@ -1401,7 +1401,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
+ 	int pktlen;
+ 	int dispose = 0;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
+ 	if (count < 2)
+@@ -1490,7 +1490,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
+ 	int err;
+ 	int i;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (!try_module_get(ca->pub->owner))
+ 		return -EIO;
+@@ -1534,7 +1534,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
+ 	struct dvb_ca_private *ca = dvbdev->priv;
+ 	int err;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* mark the CA device as closed */
+ 	ca->open = 0;
+@@ -1564,7 +1564,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
+ 	int slot;
+ 	int result = 0;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
+ 		mask |= POLLIN;
+@@ -1626,7 +1626,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
+ 	struct dvb_ca_private *ca = NULL;
+ 	int i;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (slot_count < 1)
+ 		return -EINVAL;
+@@ -1704,7 +1704,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
+ 	struct dvb_ca_private *ca = pubca->private;
+ 	int i;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* shutdown the thread if there was one */
+ 	kthread_stop(ca->thread);
+diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
+index 7959020..934e15f 100644
+--- a/drivers/media/dvb/dvb-core/dvb_demux.c
++++ b/drivers/media/dvb/dvb-core/dvb_demux.c
+@@ -368,7 +368,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
+ #define DVR_FEED(f)							\
+ 	(((f)->type == DMX_TYPE_TS) &&					\
+ 	((f)->feed.ts.is_filtering) &&					\
+-	(((f)->ts_type & (TS_PACKET|TS_PAYLOAD_ONLY)) == TS_PACKET))
++	(((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET))
+ 
+ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
+ {
+@@ -553,7 +553,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
+ 	spin_lock_irq(&feed->demux->lock);
+ 	if (dvb_demux_feed_find(feed)) {
+ 		printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
+-		       __FUNCTION__, feed->type, feed->state, feed->pid);
++		       __func__, feed->type, feed->state, feed->pid);
+ 		goto out;
+ 	}
+ 
+@@ -567,7 +567,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
+ 	spin_lock_irq(&feed->demux->lock);
+ 	if (!(dvb_demux_feed_find(feed))) {
+ 		printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
+-		       __FUNCTION__, feed->type, feed->state, feed->pid);
++		       __func__, feed->type, feed->state, feed->pid);
+ 		goto out;
+ 	}
+ 
+diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
+index 925cfa6..2dddd08 100644
+--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
++++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
+@@ -135,7 +135,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
+ 	struct dvb_frontend_event *e;
+ 	int wp;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (mutex_lock_interruptible (&events->mtx))
+ 		return;
+@@ -171,7 +171,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
+ 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ 	struct dvb_fe_events *events = &fepriv->events;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (events->overflow) {
+ 		events->overflow = 0;
+@@ -237,7 +237,7 @@ static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepr
+ {
+ 	int q2;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (locked)
+ 		(fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
+@@ -329,7 +329,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
+ 
+ 	dprintk("%s: drift:%i inversion:%i auto_step:%i "
+ 		"auto_sub_step:%i started_auto_step:%i\n",
+-		__FUNCTION__, fepriv->lnb_drift, fepriv->inversion,
++		__func__, fepriv->lnb_drift, fepriv->inversion,
+ 		fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
+ 
+ 	/* set the frontend itself */
+@@ -511,7 +511,7 @@ static int dvb_frontend_thread(void *data)
+ 	fe_status_t s;
+ 	struct dvb_frontend_parameters *params;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	fepriv->check_wrapped = 0;
+ 	fepriv->quality = 0;
+@@ -597,7 +597,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
+ {
+ 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	fepriv->exit = 1;
+ 	mb();
+@@ -665,7 +665,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
+ 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ 	struct task_struct *fe_thread;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (fepriv->thread) {
+ 		if (!fepriv->exit)
+@@ -763,7 +763,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
+ 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ 	int err = -EOPNOTSUPP;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (fepriv->exit)
+ 		return -ENODEV;
+@@ -895,7 +895,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
+ 			int i;
+ 			u8 last = 1;
+ 			if (dvb_frontend_debug)
+-				printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
++				printk("%s switch command: 0x%04lx\n", __func__, cmd);
+ 			do_gettimeofday(&nexttime);
+ 			if (dvb_frontend_debug)
+ 				memcpy(&tv[0], &nexttime, sizeof(struct timeval));
+@@ -919,7 +919,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
+ 			}
+ 			if (dvb_frontend_debug) {
+ 				printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
+-					__FUNCTION__, fe->dvb->num);
++					__func__, fe->dvb->num);
+ 				for (i = 1; i < 10; i++)
+ 					printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+ 			}
+@@ -1037,7 +1037,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc
+ 	struct dvb_frontend *fe = dvbdev->priv;
+ 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	poll_wait (file, &fepriv->events.wait_queue, wait);
+ 
+@@ -1054,7 +1054,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
+ 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ 	int ret;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
+ 		if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
+@@ -1095,7 +1095,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
+ 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ 	int ret;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+ 		fepriv->release_jiffies = jiffies;
+@@ -1135,7 +1135,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
+ 		.kernel_ioctl = dvb_frontend_ioctl
+ 	};
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (mutex_lock_interruptible(&frontend_mutex))
+ 		return -ERESTARTSYS;
+@@ -1169,7 +1169,7 @@ EXPORT_SYMBOL(dvb_register_frontend);
+ int dvb_unregister_frontend(struct dvb_frontend* fe)
+ {
+ 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	mutex_lock(&frontend_mutex);
+ 	dvb_frontend_stop (fe);
+diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
+index 4c8b62e..56d871c 100644
+--- a/drivers/media/dvb/dvb-core/dvb_net.c
++++ b/drivers/media/dvb/dvb-core/dvb_net.c
+@@ -354,7 +354,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
+ #ifdef ULE_DEBUG
+ 	/* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
+ 	static unsigned char ule_hist[100*TS_SZ];
+-	static unsigned char *ule_where = ule_hist, ule_dump = 0;
++	static unsigned char *ule_where = ule_hist, ule_dump;
+ #endif
+ 
+ 	/* For all TS cells in current buffer.
+@@ -965,17 +965,17 @@ static int dvb_net_feed_start(struct net_device *dev)
+ 	struct dmx_demux *demux = priv->demux;
+ 	unsigned char *mac = (unsigned char *) dev->dev_addr;
+ 
+-	dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
++	dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode);
+ 	mutex_lock(&priv->mutex);
+ 	if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
+-		printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
++		printk("%s: BUG %d\n", __func__, __LINE__);
+ 
+ 	priv->secfeed=NULL;
+ 	priv->secfilter=NULL;
+ 	priv->tsfeed = NULL;
+ 
+ 	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
+-		dprintk("%s: alloc secfeed\n", __FUNCTION__);
++		dprintk("%s: alloc secfeed\n", __func__);
+ 		ret=demux->allocate_section_feed(demux, &priv->secfeed,
+ 					 dvb_net_sec_callback);
+ 		if (ret<0) {
+@@ -993,38 +993,38 @@ static int dvb_net_feed_start(struct net_device *dev)
+ 		}
+ 
+ 		if (priv->rx_mode != RX_MODE_PROMISC) {
+-			dprintk("%s: set secfilter\n", __FUNCTION__);
++			dprintk("%s: set secfilter\n", __func__);
+ 			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
+ 		}
+ 
+ 		switch (priv->rx_mode) {
+ 		case RX_MODE_MULTI:
+ 			for (i = 0; i < priv->multi_num; i++) {
+-				dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);
++				dprintk("%s: set multi_secfilter[%d]\n", __func__, i);
+ 				dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
+ 						       priv->multi_macs[i], mask_normal);
+ 			}
+ 			break;
+ 		case RX_MODE_ALL_MULTI:
+ 			priv->multi_num=1;
+-			dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);
++			dprintk("%s: set multi_secfilter[0]\n", __func__);
+ 			dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
+ 					       mac_allmulti, mask_allmulti);
+ 			break;
+ 		case RX_MODE_PROMISC:
+ 			priv->multi_num=0;
+-			dprintk("%s: set secfilter\n", __FUNCTION__);
++			dprintk("%s: set secfilter\n", __func__);
+ 			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
+ 			break;
+ 		}
+ 
+-		dprintk("%s: start filtering\n", __FUNCTION__);
++		dprintk("%s: start filtering\n", __func__);
+ 		priv->secfeed->start_filtering(priv->secfeed);
+ 	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
+ 		struct timespec timeout = { 0, 10000000 }; // 10 msec
+ 
+ 		/* we have payloads encapsulated in TS */
+-		dprintk("%s: alloc tsfeed\n", __FUNCTION__);
++		dprintk("%s: alloc tsfeed\n", __func__);
+ 		ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
+ 		if (ret < 0) {
+ 			printk("%s: could not allocate ts feed\n", dev->name);
+@@ -1048,7 +1048,7 @@ static int dvb_net_feed_start(struct net_device *dev)
+ 			goto error;
+ 		}
+ 
+-		dprintk("%s: start filtering\n", __FUNCTION__);
++		dprintk("%s: start filtering\n", __func__);
+ 		priv->tsfeed->start_filtering(priv->tsfeed);
+ 	} else
+ 		ret = -EINVAL;
+@@ -1063,17 +1063,17 @@ static int dvb_net_feed_stop(struct net_device *dev)
+ 	struct dvb_net_priv *priv = dev->priv;
+ 	int i, ret = 0;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 	mutex_lock(&priv->mutex);
+ 	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
+ 		if (priv->secfeed) {
+ 			if (priv->secfeed->is_filtering) {
+-				dprintk("%s: stop secfeed\n", __FUNCTION__);
++				dprintk("%s: stop secfeed\n", __func__);
+ 				priv->secfeed->stop_filtering(priv->secfeed);
+ 			}
+ 
+ 			if (priv->secfilter) {
+-				dprintk("%s: release secfilter\n", __FUNCTION__);
++				dprintk("%s: release secfilter\n", __func__);
+ 				priv->secfeed->release_filter(priv->secfeed,
+ 							      priv->secfilter);
+ 				priv->secfilter=NULL;
+@@ -1082,7 +1082,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
+ 			for (i=0; i<priv->multi_num; i++) {
+ 				if (priv->multi_secfilter[i]) {
+ 					dprintk("%s: release multi_filter[%d]\n",
+-						__FUNCTION__, i);
++						__func__, i);
+ 					priv->secfeed->release_filter(priv->secfeed,
+ 								      priv->multi_secfilter[i]);
+ 					priv->multi_secfilter[i] = NULL;
+@@ -1096,7 +1096,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
+ 	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
+ 		if (priv->tsfeed) {
+ 			if (priv->tsfeed->is_filtering) {
+-				dprintk("%s: stop tsfeed\n", __FUNCTION__);
++				dprintk("%s: stop tsfeed\n", __func__);
+ 				priv->tsfeed->stop_filtering(priv->tsfeed);
+ 			}
+ 			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
+diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+index ac9d93c..872985b 100644
+--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
++++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+@@ -90,7 +90,11 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
+ 	rbuf->error = 0;
+ }
+ 
+-
++void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
++{
++	rbuf->pread = rbuf->pwrite = 0;
++	rbuf->error = 0;
++}
+ 
+ void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
+ {
+diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+index d97714e..8908262 100644
+--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
++++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+@@ -69,6 +69,7 @@ struct dvb_ringbuffer {
+ **     to lock read or write operations.
+ **     Two or more readers must be locked against each other.
+ **     Flushing the buffer counts as a read operation.
++**     Resetting the buffer counts as a read and write operation.
+ **     Two or more writers must be locked against each other.
+ */
+ 
+@@ -85,6 +86,13 @@ extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
+ extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
+ 
+ 
++/*
++** Reset the read and write pointers to zero and flush the buffer
++** This counts as a read and write operation
++*/
++extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
++
++
+ /* read routines & macros */
+ /* ---------------------- */
+ /* flush buffer */
+diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
+index 18738fa..8b56d92 100644
+--- a/drivers/media/dvb/dvb-core/dvbdev.c
++++ b/drivers/media/dvb/dvb-core/dvbdev.c
+@@ -49,7 +49,6 @@ static const char * const dnames[] = {
+ 	"net", "osd"
+ };
+ 
+-#define DVB_MAX_ADAPTERS	8
+ #define DVB_MAX_IDS		4
+ #define nums2minor(num,type,id)	((num << 6) | (id << 4) | type)
+ #define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64)
+@@ -97,7 +96,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
+ }
+ 
+ 
+-static struct file_operations dvb_device_fops =
++static const struct file_operations dvb_device_fops =
+ {
+ 	.owner =	THIS_MODULE,
+ 	.open =		dvb_device_open,
+@@ -196,7 +195,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ 	if ((id = dvbdev_get_free_id (adap, type)) < 0){
+ 		mutex_unlock(&dvbdev_register_lock);
+ 		*pdvbdev = NULL;
+-		printk(KERN_ERR "%s: couldn't find free device id\n", __FUNCTION__);
++		printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
+ 		return -ENFILE;
+ 	}
+ 
+@@ -235,7 +234,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ 			       "dvb%d.%s%d", adap->num, dnames[type], id);
+ 	if (IS_ERR(clsdev)) {
+ 		printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
+-		       __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
++		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+ 		return PTR_ERR(clsdev);
+ 	}
+ 
+@@ -262,18 +261,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
+ }
+ EXPORT_SYMBOL(dvb_unregister_device);
+ 
++static int dvbdev_check_free_adapter_num(int num)
++{
++	struct list_head *entry;
++	list_for_each(entry, &dvb_adapter_list) {
++		struct dvb_adapter *adap;
++		adap = list_entry(entry, struct dvb_adapter, list_head);
++		if (adap->num == num)
++			return 0;
++	}
++	return 1;
++}
+ 
+ static int dvbdev_get_free_adapter_num (void)
+ {
+ 	int num = 0;
+ 
+ 	while (num < DVB_MAX_ADAPTERS) {
+-		struct dvb_adapter *adap;
+-		list_for_each_entry(adap, &dvb_adapter_list, list_head)
+-			if (adap->num == num)
+-				goto skip;
+-		return num;
+-skip:
++		if (dvbdev_check_free_adapter_num(num))
++			return num;
+ 		num++;
+ 	}
+ 
+@@ -281,13 +287,28 @@ skip:
+ }
+ 
+ 
+-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
++int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
++			 struct module *module, struct device *device,
++			 short *adapter_nums)
+ {
+-	int num;
++	int i, num;
+ 
+ 	mutex_lock(&dvbdev_register_lock);
+ 
+-	if ((num = dvbdev_get_free_adapter_num ()) < 0) {
++	for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
++		num = adapter_nums[i];
++		if (num >= 0  &&  num < DVB_MAX_ADAPTERS) {
++		/* use the one the driver asked for */
++			if (dvbdev_check_free_adapter_num(num))
++				break;
++		} else {
++			num = dvbdev_get_free_adapter_num();
++			break;
++		}
++		num = -1;
++	}
++
++	if (num < 0) {
+ 		mutex_unlock(&dvbdev_register_lock);
+ 		return -ENFILE;
+ 	}
+diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
+index 6dff10e..5f9a737 100644
+--- a/drivers/media/dvb/dvb-core/dvbdev.h
++++ b/drivers/media/dvb/dvb-core/dvbdev.h
+@@ -31,6 +31,10 @@
+ 
+ #define DVB_MAJOR 212
+ 
++#define DVB_MAX_ADAPTERS 8
++
++#define DVB_UNSET (-1)
++
+ #define DVB_DEVICE_VIDEO      0
+ #define DVB_DEVICE_AUDIO      1
+ #define DVB_DEVICE_SEC        2
+@@ -41,6 +45,11 @@
+ #define DVB_DEVICE_NET        7
+ #define DVB_DEVICE_OSD        8
+ 
++#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
++	static short adapter_nr[] = \
++		{[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
++	module_param_array(adapter_nr, short, NULL, 0444); \
++	MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
+ 
+ struct dvb_adapter {
+ 	int num;
+@@ -78,7 +87,9 @@ struct dvb_device {
+ };
+ 
+ 
+-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
++extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
++				struct module *module, struct device *device,
++				short *adapter_nums);
+ extern int dvb_unregister_adapter (struct dvb_adapter *adap);
+ 
+ extern int dvb_register_device (struct dvb_adapter *adap,
+diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
+index d73934d..3c8493d 100644
+--- a/drivers/media/dvb/dvb-usb/Kconfig
++++ b/drivers/media/dvb/dvb-usb/Kconfig
+@@ -105,6 +105,7 @@ config DVB_USB_CXUSB
+ 	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ 	select DVB_MT352 if !DVB_FE_CUSTOMISE
+ 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
++	select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ 	help
+ 	  Say Y here to support the Conexant USB2.0 hybrid reference design.
+ 	  Currently, only DVB and ATSC modes are supported, analog mode
+diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
+index a6c5f19..dc8c878 100644
+--- a/drivers/media/dvb/dvb-usb/a800.c
++++ b/drivers/media/dvb/dvb-usb/a800.c
+@@ -18,6 +18,9 @@
+ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_rc(args...)   dprintk(debug,0x01,args)
+ 
+ static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
+@@ -94,7 +97,8 @@ static struct dvb_usb_device_properties a800_properties;
+ static int a800_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+-	return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL);
++	return dvb_usb_device_init(intf, &a800_properties,
++				   THIS_MODULE, NULL, adapter_nr);
+ }
+ 
+ /* do not change the order of the ID table */
+diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c
+index e7f76f5..cfe71fe 100644
+--- a/drivers/media/dvb/dvb-usb/af9005.c
++++ b/drivers/media/dvb/dvb-usb/af9005.c
+@@ -39,6 +39,8 @@ int dvb_usb_af9005_dump_eeprom = 0;
+ module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0);
+ MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom.");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* remote control decoder */
+ int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event,
+ 		  int *state);
+@@ -1020,7 +1022,8 @@ static struct dvb_usb_device_properties af9005_properties;
+ static int af9005_usb_probe(struct usb_interface *intf,
+ 			    const struct usb_device_id *id)
+ {
+-	return dvb_usb_device_init(intf, &af9005_properties, THIS_MODULE, NULL);
++	return dvb_usb_device_init(intf, &af9005_properties,
++				   THIS_MODULE, NULL, adapter_nr);
+ }
+ 
+ static struct usb_device_id af9005_usb_table[] = {
+diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c
+index f3ff813..2ccb90f 100644
+--- a/drivers/media/dvb/dvb-usb/au6610.c
++++ b/drivers/media/dvb/dvb-usb/au6610.c
+@@ -19,6 +19,8 @@ static int dvb_usb_au6610_debug;
+ module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
+ 			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+ {
+@@ -163,7 +165,9 @@ static int au6610_probe(struct usb_interface *intf,
+ 	if (intf->num_altsetting < AU6610_ALTSETTING_COUNT)
+ 		return -ENODEV;
+ 
+-	if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) {
++	ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d,
++				  adapter_nr);
++	if (ret == 0) {
+ 		alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
+ 
+ 		if (alt == NULL) {
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index c583650..720fcd1 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -23,6 +23,8 @@
+  *
+  * see Documentation/dvb/README.dvb-usb for more information
+  */
++#include <media/tuner.h>
++
+ #include "cxusb.h"
+ 
+ #include "cx22702.h"
+@@ -31,12 +33,15 @@
+ #include "mt352_priv.h"
+ #include "zl10353.h"
+ #include "tuner-xc2028.h"
+-#include "tuner-xc2028-types.h"
++#include "tuner-simple.h"
+ 
+ /* debug */
+ static int dvb_usb_cxusb_debug;
+ module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_info(args...)   dprintk(dvb_usb_cxusb_debug,0x01,args)
+ #define deb_i2c(args...)    if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
+ 				dprintk(dvb_usb_cxusb_debug,0x01,args)
+@@ -450,8 +455,9 @@ static struct mt352_config cxusb_mt352_xc3028_config = {
+ /* Callbacks for DVB USB */
+ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+-	dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+-		   DVB_PLL_FMD1216ME);
++	dvb_attach(simple_tuner_attach, adap->fe,
++		   &adap->dev->i2c_adap, 0x61,
++		   TUNER_PHILIPS_FMD1216ME_MK3);
+ 	return 0;
+ }
+ 
+@@ -477,8 +483,8 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
+ 
+ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+-	dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+-		   DVB_PLL_LG_TDVS_H06XF);
++	dvb_attach(simple_tuner_attach, adap->fe,
++		   &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
+ 	return 0;
+ }
+ 
+@@ -488,14 +494,14 @@ static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
+ 
+ 	switch (command) {
+ 	case XC2028_TUNER_RESET:
+-		deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
++		deb_info("%s: XC2028_TUNER_RESET %d\n", __func__, arg);
+ 		cxusb_bluebird_gpio_pulse(d, 0x01, 1);
+ 		break;
+ 	case XC2028_RESET_CLK:
+-		deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
++		deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg);
+ 		break;
+ 	default:
+-		deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__,
++		deb_info("%s: unknown command %d, arg %d\n", __func__,
+ 			 command, arg);
+ 		return -EINVAL;
+ 	}
+@@ -509,13 +515,12 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
+ 	struct xc2028_config	  cfg = {
+ 		.i2c_adap  = &adap->dev->i2c_adap,
+ 		.i2c_addr  = 0x61,
+-		.video_dev = adap->dev,
+ 		.callback  = dvico_bluebird_xc2028_callback,
+ 	};
+ 	static struct xc2028_ctrl ctl = {
+ 		.fname       = "xc3028-dvico-au-01.fw",
+ 		.max_len     = 64,
+-		.scode_table = ZARLINK456,
++		.scode_table = XC3028_FE_ZARLINK456,
+ 	};
+ 
+ 	fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
+@@ -720,16 +725,24 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
+ static int cxusb_probe(struct usb_interface *intf,
+ 		       const struct usb_device_id *id)
+ {
+-	if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) {
++	if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf,
++				&cxusb_bluebird_nano2_needsfirmware_properties,
++				     THIS_MODULE, NULL, adapter_nr))
+ 		return 0;
+-	}
+ 
+ 	return -EINVAL;
+ }
+diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
+index 4a903ea..66d4dc6 100644
+--- a/drivers/media/dvb/dvb-usb/dib0700.h
++++ b/drivers/media/dvb/dvb-usb/dib0700.h
+@@ -37,6 +37,7 @@ struct dib0700_state {
+ 	u8 channel_state;
+ 	u16 mt2060_if1[2];
+ 	u8 rc_toggle;
++	u8 rc_counter;
+ 	u8 is_dib7000pc;
+ };
+ 
+@@ -44,12 +45,15 @@ extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8
+ extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
+ extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
+ extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
++extern int dib0700_rc_setup(struct dvb_usb_device *d);
+ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
+ extern struct i2c_algorithm dib0700_i2c_algo;
+ extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
+ 			struct dvb_usb_device_description **desc, int *cold);
+ 
+ extern int dib0700_device_count;
++extern int dvb_usb_dib0700_ir_proto;
+ extern struct dvb_usb_device_properties dib0700_devices[];
+ extern struct usb_device_id dib0700_usb_id_table[];
++
+ #endif
+diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
+index c9857d5..595a046 100644
+--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
+@@ -13,10 +13,12 @@ int dvb_usb_dib0700_debug;
+ module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
+ 
+-static int dvb_usb_dib0700_ir_proto = 1;
++int dvb_usb_dib0700_ir_proto = 1;
+ module_param(dvb_usb_dib0700_ir_proto, int, 0644);
+ MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* expecting rx buffer: request data[0] data[1] ... data[2] */
+ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
+ {
+@@ -261,7 +263,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+ 	return dib0700_ctrl_wr(adap->dev, b, 4);
+ }
+ 
+-static int dib0700_rc_setup(struct dvb_usb_device *d)
++int dib0700_rc_setup(struct dvb_usb_device *d)
+ {
+ 	u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
+ 	int i = dib0700_ctrl_wr(d, rc_setup, 3);
+@@ -279,7 +281,8 @@ static int dib0700_probe(struct usb_interface *intf,
+ 	struct dvb_usb_device *dev;
+ 
+ 	for (i = 0; i < dib0700_device_count; i++)
+-		if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0)
++		if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE,
++					&dev, adapter_nr) == 0)
+ 		{
+ 			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 e709382..3462238 100644
+--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
++++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
+@@ -13,6 +13,7 @@
+ #include "dib7000p.h"
+ #include "mt2060.h"
+ #include "mt2266.h"
++#include "tuner-xc2028.h"
+ #include "dib0070.h"
+ 
+ static int force_lna_activation;
+@@ -297,10 +298,156 @@ static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
+ 		&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;;
+ }
+ 
++/* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */
++static struct dibx000_agc_config xc3028_agc_config = {
++	BAND_VHF | BAND_UHF,       /* band_caps */
++
++	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
++	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
++	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
++	(0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
++	(3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
++
++	712,	/* inv_gain */
++	21,	/* time_stabiliz */
++
++	0,	/* alpha_level */
++	118,	/* thlock */
++
++	0,	/* wbd_inv */
++	2867,	/* wbd_ref */
++	0,	/* wbd_sel */
++	2,	/* wbd_alpha */
++
++	0,	/* agc1_max */
++	0,	/* agc1_min */
++	39718,	/* agc2_max */
++	9930,	/* agc2_min */
++	0,	/* agc1_pt1 */
++	0,	/* agc1_pt2 */
++	0,	/* agc1_pt3 */
++	0,	/* agc1_slope1 */
++	0,	/* agc1_slope2 */
++	0,	/* agc2_pt1 */
++	128,	/* agc2_pt2 */
++	29,	/* agc2_slope1 */
++	29,	/* agc2_slope2 */
++
++	17,	/* alpha_mant */
++	27,	/* alpha_exp */
++	23,	/* beta_mant */
++	51,	/* beta_exp */
++
++	1,	/* perform_agc_softsplit */
++};
++
++/* PLL Configuration for COFDM BW_MHz = 8.00 with external clock = 30.00 */
++static struct dibx000_bandwidth_config xc3028_bw_config = {
++	60000, 30000, /* internal, sampling */
++	1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */
++	0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc,
++			  modulo */
++	(3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
++	(1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
++	20452225, /* timf */
++	30000000, /* xtal_hz */
++};
++
++static struct dib7000p_config stk7700ph_dib7700_xc3028_config = {
++	.output_mpeg2_in_188_bytes = 1,
++	.tuner_is_baseband = 1,
++
++	.agc_config_count = 1,
++	.agc = &xc3028_agc_config,
++	.bw  = &xc3028_bw_config,
++
++	.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
++	.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
++	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
++};
++
++static int stk7700ph_xc3028_callback(void *ptr, int command, int arg)
++{
++	struct dvb_usb_adapter *adap = ptr;
++
++	switch (command) {
++	case XC2028_TUNER_RESET:
++		/* Send the tuner in then out of reset */
++		dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10);
++		dib7000p_set_gpio(adap->fe, 8, 0, 1);
++		break;
++	case XC2028_RESET_CLK:
++		break;
++	default:
++		err("%s: unknown command %d, arg %d\n", __func__,
++			command, arg);
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static struct xc2028_ctrl stk7700ph_xc3028_ctrl = {
++	.fname = XC2028_DEFAULT_FIRMWARE,
++	.max_len = 64,
++	.demod = XC3028_FE_DIBCOM52,
++};
++
++static struct xc2028_config stk7700ph_xc3028_config = {
++	.i2c_addr = 0x61,
++	.callback = stk7700ph_xc3028_callback,
++	.ctrl = &stk7700ph_xc3028_ctrl,
++};
++
++static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
++{
++	struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
++
++	if (desc->idVendor  == USB_VID_PINNACLE &&
++	    desc->idProduct == USB_PID_PINNACLE_EXPRESSCARD_320CX)
++	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
++	else
++	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
++	msleep(20);
++	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);
++	msleep(10);
++	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
++	msleep(20);
++	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
++	msleep(10);
++
++	dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
++		&stk7700ph_dib7700_xc3028_config);
++
++	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
++		&stk7700ph_dib7700_xc3028_config);
++
++	return adap->fe == NULL ? -ENODEV : 0;
++}
++
++static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
++{
++	struct i2c_adapter *tun_i2c;
++
++	tun_i2c = dib7000p_get_i2c_master(adap->fe,
++		DIBX000_I2C_INTERFACE_TUNER, 1);
++
++	stk7700ph_xc3028_config.i2c_adap = tun_i2c;
++	stk7700ph_xc3028_config.video_dev = adap;
++
++	return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
++		== NULL ? -ENODEV : 0;
++}
++
+ #define DEFAULT_RC_INTERVAL 150
+ 
+ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
+ 
++/* Number of keypresses to ignore before start repeating */
++#define RC_REPEAT_DELAY 2
++
+ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+ {
+ 	u8 key[4];
+@@ -314,18 +461,67 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+ 		err("RC Query Failed");
+ 		return -1;
+ 	}
++
++	/* losing half of KEY_0 events from Philipps rc5 remotes.. */
+ 	if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
+-	if (key[3-1]!=st->rc_toggle) {
++
++	/* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]);  */
++
++	dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
++
++	switch (dvb_usb_dib0700_ir_proto) {
++	case 0: {
++		/* NEC protocol sends repeat code as 0 0 0 FF */
++		if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
++		    (key[3] == 0xFF)) {
++			st->rc_counter++;
++			if (st->rc_counter > RC_REPEAT_DELAY) {
++				*event = d->last_event;
++				*state = REMOTE_KEY_PRESSED;
++				st->rc_counter = RC_REPEAT_DELAY;
++			}
++			return 0;
++		}
+ 		for (i=0;i<d->props.rc_key_map_size; i++) {
+ 			if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
++				st->rc_counter = 0;
++				*event = keymap[i].event;
++				*state = REMOTE_KEY_PRESSED;
++				d->last_event = keymap[i].event;
++				return 0;
++			}
++		}
++		break;
++	}
++	default: {
++		/* RC-5 protocol changes toggle bit on new keypress */
++		for (i = 0; i < d->props.rc_key_map_size; i++) {
++			if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
++				if (d->last_event == keymap[i].event &&
++					key[3-1] == st->rc_toggle) {
++					st->rc_counter++;
++					/* prevents unwanted double hits */
++					if (st->rc_counter > RC_REPEAT_DELAY) {
++						*event = d->last_event;
++						*state = REMOTE_KEY_PRESSED;
++						st->rc_counter = RC_REPEAT_DELAY;
++					}
++
++					return 0;
++				}
++				st->rc_counter = 0;
+ 				*event = keymap[i].event;
+ 				*state = REMOTE_KEY_PRESSED;
+-				st->rc_toggle=key[3-1];
++				st->rc_toggle = key[3-1];
++				d->last_event = keymap[i].event;
+ 				return 0;
+ 			}
+ 		}
+-		err("Unknown remote controller key : %2X %2X",(int)key[3-2],(int)key[3-3]);
++		break;
+ 	}
++	}
++	err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]);
++	d->last_event = 0;
+ 	return 0;
+ }
+ 
+@@ -794,6 +990,10 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
+ /* STK7070P */
+ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
+ {
++	if (adap->dev->udev->descriptor.idVendor  == USB_VID_PINNACLE &&
++	adap->dev->udev->descriptor.idProduct == 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);
+@@ -808,9 +1008,11 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
+ 	msleep(10);
+ 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+ 
+-	dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config);
++	dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
++		&dib7070p_dib7000p_config);
+ 
+-	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &dib7070p_dib7000p_config);
++	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
++		&dib7070p_dib7000p_config);
+ 	return adap->fe == NULL ? -ENODEV : 0;
+ }
+ 
+@@ -878,34 +1080,43 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
+ /* DVB-USB and USB stuff follows */
+ struct usb_device_id dib0700_usb_id_table[] = {
+ /* 0 */	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P) },
+-		{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
+-
+-		{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
+-		{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
+-		{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
++	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
++	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
++	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
++	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
+ /* 5 */	{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
+-		{ USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
+-		{ USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
+-		{ USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
+-		{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
++	{ USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
++	{ USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
++	{ USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
++	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
+ /* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
+-		{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV2000E) },
+-		{ USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
+-		{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
+-		{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700D) },
++	{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV2000E) },
++	{ USB_DEVICE(USB_VID_TERRATEC,
++			USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
++	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
++	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700D) },
+ /* 15 */{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070P) },
+-		{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
+-		{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070PD) },
+-		{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
+-		{ USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500_PC) },
++	{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
++	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070PD) },
++	{ USB_DEVICE(USB_VID_PINNACLE,
++			USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
++	{ USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500_PC) },
+ /* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) },
+-		{ USB_DEVICE(USB_VID_GIGABYTE,  USB_PID_GIGABYTE_U7000) },
+-		{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
+-		{ USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3000) },
+-		{ USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3100) },
+-/* 25 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
+-		{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
+-		{ 0 }		/* Terminating entry */
++	{ USB_DEVICE(USB_VID_GIGABYTE,  USB_PID_GIGABYTE_U7000) },
++	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
++	{ USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3000) },
++	{ USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3100) },
++/* 25 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
++	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
++	{ USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_HT_USB_XE) },
++	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_EXPRESSCARD_320CX) },
++	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV72E) },
++/* 30 */{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV73E) },
++	{ USB_DEVICE(USB_VID_YUAN,	USB_PID_YUAN_EC372S) },
++	{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
++	{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_CINERGY_T_XXS) },
++	{ USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
++	{ 0 }		/* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
+ 
+@@ -969,7 +1180,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ 				{ NULL },
+ 			},
+ 			{   "Leadtek Winfast DTV Dongle (STK7700P based)",
+-				{ &dib0700_usb_id_table[8], NULL },
++				{ &dib0700_usb_id_table[8], &dib0700_usb_id_table[34] },
+ 				{ NULL },
+ 			},
+ 			{   "AVerMedia AVerTV DVB-T Express",
+@@ -1069,12 +1280,16 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ 			},
+ 		},
+ 
+-		.num_device_descs = 1,
++		.num_device_descs = 2,
+ 		.devices = {
+ 			{   "ASUS My Cinema U3000 Mini DVBT Tuner",
+ 				{ &dib0700_usb_id_table[23], NULL },
+ 				{ NULL },
+ 			},
++			{   "Yuan EC372S",
++				{ &dib0700_usb_id_table[31], NULL },
++				{ NULL },
++			}
+ 		}
+ 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+ 
+@@ -1090,7 +1305,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ 			},
+ 		},
+ 
+-		.num_device_descs = 6,
++		.num_device_descs = 9,
+ 		.devices = {
+ 			{   "DiBcom STK7070P reference design",
+ 				{ &dib0700_usb_id_table[15], NULL },
+@@ -1116,6 +1331,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ 				{ &dib0700_usb_id_table[26], NULL },
+ 				{ NULL },
+ 			},
++			{   "Pinnacle PCTV 72e",
++				{ &dib0700_usb_id_table[29], NULL },
++				{ NULL },
++			},
++			{   "Pinnacle PCTV 73e",
++				{ &dib0700_usb_id_table[30], NULL },
++				{ NULL },
++			},
++			{   "Terratec Cinergy T USB XXS",
++				{ &dib0700_usb_id_table[33], NULL },
++				{ NULL },
++			},
+ 		},
+ 
+ 		.rc_interval      = DEFAULT_RC_INTERVAL,
+@@ -1155,6 +1382,40 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ 				{ NULL },
+ 			}
+ 		}
++	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
++
++		.num_adapters = 1,
++		.adapter = {
++			{
++				.frontend_attach  = stk7700ph_frontend_attach,
++				.tuner_attach     = stk7700ph_tuner_attach,
++
++				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
++
++				.size_of_priv = sizeof(struct
++						dib0700_adapter_state),
++			},
++		},
++
++		.num_device_descs = 3,
++		.devices = {
++			{   "Terratec Cinergy HT USB XE",
++				{ &dib0700_usb_id_table[27], NULL },
++				{ NULL },
++			},
++			{   "Pinnacle Expresscard 320cx",
++				{ &dib0700_usb_id_table[28], NULL },
++				{ NULL },
++			},
++			{   "Terratec Cinergy HT Express",
++				{ &dib0700_usb_id_table[32], NULL },
++				{ NULL },
++			},
++		},
++		.rc_interval      = DEFAULT_RC_INTERVAL,
++		.rc_key_map       = dib0700_rc_keys,
++		.rc_key_map_size  = ARRAY_SIZE(dib0700_rc_keys),
++		.rc_query         = dib0700_rc_query
+ 	},
+ };
+ 
+diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
+index 043cada..eeef50b 100644
+--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
++++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
+@@ -14,6 +14,8 @@
+  */
+ #include "dibusb.h"
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ 	struct dvb_usb_adapter *adap = fe->dvb->priv;
+@@ -107,10 +109,14 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties;
+ static int dibusb_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+-	if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0)
++	if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &dibusb2_0b_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties,
++				     THIS_MODULE, NULL, adapter_nr))
+ 		return 0;
+ 
+ 	return -EINVAL;
+diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
+index e7ea3e7..059cec9 100644
+--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
++++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
+@@ -14,13 +14,16 @@
+  */
+ #include "dibusb.h"
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* USB Driver stuff */
+ static struct dvb_usb_device_properties dibusb_mc_properties;
+ 
+ static int dibusb_mc_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+-	return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL);
++	return dvb_usb_device_init(intf, &dibusb_mc_properties, THIS_MODULE,
++				   NULL, adapter_nr);
+ }
+ 
+ /* do not change the order of the ID table */
+diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
+index 3acbda4..b545cf3 100644
+--- a/drivers/media/dvb/dvb-usb/digitv.c
++++ b/drivers/media/dvb/dvb-usb/digitv.c
+@@ -20,6 +20,9 @@
+ static int dvb_usb_digitv_debug;
+ module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_rc(args...)   dprintk(dvb_usb_digitv_debug,0x01,args)
+ 
+ static int digitv_ctrl_msg(struct dvb_usb_device *d,
+@@ -256,8 +259,9 @@ static int digitv_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+ 	struct dvb_usb_device *d;
+-	int ret;
+-	if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
++	int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d,
++				      adapter_nr);
++	if (ret == 0) {
+ 		u8 b[4] = { 0 };
+ 
+ 		if (d != NULL) { /* do that only when the firmware is loaded */
+diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
+index d86cf9b..81a6cbf 100644
+--- a/drivers/media/dvb/dvb-usb/dtt200u.c
++++ b/drivers/media/dvb/dvb-usb/dtt200u.c
+@@ -18,6 +18,8 @@ int dvb_usb_dtt200u_debug;
+ module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
+ {
+ 	u8 b = SET_INIT;
+@@ -101,11 +103,16 @@ static struct dvb_usb_device_properties wt220u_miglia_properties;
+ static int dtt200u_usb_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+-	if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 ||
+-		dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0)
++	if (0 == dvb_usb_device_init(intf, &dtt200u_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &wt220u_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &wt220u_fc_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &wt220u_miglia_properties,
++				     THIS_MODULE, NULL, adapter_nr))
+ 		return 0;
+ 
+ 	return -ENODEV;
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+index 35ab68f..6b7b2a8 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+@@ -40,7 +40,8 @@ extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap);
+ extern int dvb_usb_i2c_init(struct dvb_usb_device *);
+ extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
+ 
+-extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap);
++extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap,
++				    short *adapter_nums);
+ extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap);
+ extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap);
+ extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap);
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+index 4561a67..ce8cd0c 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+@@ -77,12 +77,13 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+ 	return dvb_usb_ctrl_feed(dvbdmxfeed,0);
+ }
+ 
+-int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap)
++int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
+ {
+-	int ret;
++	int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
++				       adap->dev->owner, &adap->dev->udev->dev,
++				       adapter_nums);
+ 
+-	if ((ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
+-			adap->dev->owner, &adap->dev->udev->dev)) < 0) {
++	if (ret < 0) {
+ 		deb_info("dvb_register_adapter failed: error %d", ret);
+ 		goto err;
+ 	}
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+index aa4844e..34245d1 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+@@ -40,14 +40,15 @@
+ #define USB_VID_MSI				0x0db0
+ #define USB_VID_OPERA1				0x695c
+ #define USB_VID_PINNACLE			0x2304
++#define USB_VID_TECHNOTREND			0x0b48
+ #define USB_VID_TERRATEC			0x0ccd
+ #define USB_VID_VISIONPLUS			0x13d3
+ #define USB_VID_TWINHAN				0x1822
+ #define USB_VID_ULTIMA_ELECTRONIC		0x05d8
+ #define USB_VID_UNIWILL				0x1584
+ #define USB_VID_WIDEVIEW			0x14aa
+-/* dom : pour gigabyte u7000 */
+ #define USB_VID_GIGABYTE			0x1044
++#define USB_VID_YUAN				0x1164
+ 
+ 
+ /* Product IDs */
+@@ -134,10 +135,17 @@
+ #define USB_PID_AVERMEDIA_EXPRESS			0xb568
+ #define USB_PID_AVERMEDIA_VOLAR				0xa807
+ #define USB_PID_AVERMEDIA_VOLAR_2			0xb808
++#define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
+ #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a
++#define USB_PID_TERRATEC_CINERGY_HT_USB_XE		0x0058
++#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS		0x0060
++#define USB_PID_TERRATEC_CINERGY_T_XXS			0x0078
++#define USB_PID_PINNACLE_EXPRESSCARD_320CX		0x022e
+ #define USB_PID_PINNACLE_PCTV2000E			0x022c
+ #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH		0x0228
+ #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T	0x0229
++#define USB_PID_PINNACLE_PCTV72E			0x0236
++#define USB_PID_PINNACLE_PCTV73E			0x0237
+ #define USB_PID_PCTV_200E				0x020e
+ #define USB_PID_PCTV_400E				0x020f
+ #define USB_PID_PCTV_450E				0x0222
+@@ -172,6 +180,7 @@
+ #define USB_PID_WINFAST_DTV_DONGLE_COLD			0x6025
+ #define USB_PID_WINFAST_DTV_DONGLE_WARM			0x6026
+ #define USB_PID_WINFAST_DTV_DONGLE_STK7700P		0x6f00
++#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2		0x6f01
+ #define USB_PID_GENPIX_8PSK_REV_1_COLD			0x0200
+ #define USB_PID_GENPIX_8PSK_REV_1_WARM			0x0201
+ #define USB_PID_GENPIX_8PSK_REV_2			0x0202
+@@ -183,9 +192,9 @@
+ #define USB_PID_OPERA1_WARM				0x3829
+ #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD		0x0514
+ #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM		0x0513
+-/* dom pour gigabyte u7000 */
+ #define USB_PID_GIGABYTE_U7000				0x7001
+ #define USB_PID_ASUS_U3000				0x171f
+ #define USB_PID_ASUS_U3100				0x173f
++#define USB_PID_YUAN_EC372S				0x1edc
+ 
+ #endif
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+index cdd717c..e331db8 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+@@ -26,7 +26,7 @@ static int dvb_usb_force_pid_filter_usage;
+ module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
+ MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
+ 
+-static int dvb_usb_adapter_init(struct dvb_usb_device *d)
++static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
+ {
+ 	struct dvb_usb_adapter *adap;
+ 	int ret,n;
+@@ -72,7 +72,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d)
+ 		}
+ 
+ 		if ((ret = dvb_usb_adapter_stream_init(adap)) ||
+-			(ret = dvb_usb_adapter_dvb_init(adap)) ||
++			(ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) ||
+ 			(ret = dvb_usb_adapter_frontend_init(adap))) {
+ 			return ret;
+ 		}
+@@ -122,7 +122,7 @@ static int dvb_usb_exit(struct dvb_usb_device *d)
+ 	return 0;
+ }
+ 
+-static int dvb_usb_init(struct dvb_usb_device *d)
++static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
+ {
+ 	int ret = 0;
+ 
+@@ -143,7 +143,7 @@ static int dvb_usb_init(struct dvb_usb_device *d)
+ 	dvb_usb_device_power_ctrl(d, 1);
+ 
+ 	if ((ret = dvb_usb_i2c_init(d)) ||
+-		(ret = dvb_usb_adapter_init(d))) {
++		(ret = dvb_usb_adapter_init(d, adapter_nums))) {
+ 		dvb_usb_exit(d);
+ 		return ret;
+ 	}
+@@ -213,8 +213,10 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
+ /*
+  * USB
+  */
+-int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_properties
+-		*props, struct module *owner,struct dvb_usb_device **du)
++int dvb_usb_device_init(struct usb_interface *intf,
++			struct dvb_usb_device_properties *props,
++			struct module *owner, struct dvb_usb_device **du,
++			short *adapter_nums)
+ {
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	struct dvb_usb_device *d = NULL;
+@@ -254,7 +256,7 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_proper
+ 	if (du != NULL)
+ 		*du = d;
+ 
+-	ret = dvb_usb_init(d);
++	ret = dvb_usb_init(d, adapter_nums);
+ 
+ 	if (ret == 0)
+ 		info("%s successfully initialized and connected.",desc->name);
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
+index d1b3c7b..b1de0f7 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
+@@ -372,7 +372,10 @@ struct dvb_usb_device {
+ 	void *priv;
+ };
+ 
+-extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_device_properties *, struct module *, struct dvb_usb_device **);
++extern int dvb_usb_device_init(struct usb_interface *,
++			       struct dvb_usb_device_properties *,
++			       struct module *, struct dvb_usb_device **,
++			       short *adapter_nums);
+ extern void dvb_usb_device_exit(struct usb_interface *);
+ 
+ /* the generic read/write method for device control */
+diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
+index 6b99d9f..0a8ac64 100644
+--- a/drivers/media/dvb/dvb-usb/gl861.c
++++ b/drivers/media/dvb/dvb-usb/gl861.c
+@@ -16,6 +16,8 @@ static int dvb_usb_gl861_debug;
+ module_param_named(debug,dvb_usb_gl861_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
+ 			 u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+ {
+@@ -140,7 +142,9 @@ static int gl861_probe(struct usb_interface *intf,
+ 	if (intf->num_altsetting < 2)
+ 		return -ENODEV;
+ 
+-	if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) {
++	ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d,
++				  adapter_nr);
++	if (ret == 0) {
+ 		alt = usb_altnum_to_altsetting(intf, 0);
+ 
+ 		if (alt == NULL) {
+diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+index e37142d..262a858 100644
+--- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c
++++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+@@ -152,7 +152,7 @@ static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
+ {
+ 	struct gp8psk_fe_state *st = fe->demodulator_priv;
+ 
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 
+ 	if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
+ 			m->msg, m->msg_len)) {
+@@ -167,7 +167,7 @@ static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
+ 	struct gp8psk_fe_state *st = fe->demodulator_priv;
+ 	u8 cmd;
+ 
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 
+ 	/* These commands are certainly wrong */
+ 	cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
+diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
+index 83e8535..9a942af 100644
+--- a/drivers/media/dvb/dvb-usb/gp8psk.c
++++ b/drivers/media/dvb/dvb-usb/gp8psk.c
+@@ -22,6 +22,8 @@ int dvb_usb_gp8psk_debug;
+ module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+ {
+ 	int ret = 0,try = 0;
+@@ -190,7 +192,8 @@ static int gp8psk_usb_probe(struct usb_interface *intf,
+ {
+ 	int ret;
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+-	ret =  dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
++	ret = dvb_usb_device_init(intf, &gp8psk_properties,
++				  THIS_MODULE, NULL, adapter_nr);
+ 	if (ret == 0) {
+ 		info("found Genpix USB device pID = %x (hex)",
+ 			le16_to_cpu(udev->descriptor.idProduct));
+diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
+index a956bc5..a12e6f7 100644
+--- a/drivers/media/dvb/dvb-usb/m920x.c
++++ b/drivers/media/dvb/dvb-usb/m920x.c
+@@ -22,6 +22,8 @@ static int dvb_usb_m920x_debug;
+ module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
+ 
+ static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
+@@ -477,7 +479,7 @@ static struct qt1010_config m920x_qt1010_config = {
+ /* Callbacks for DVB USB */
+ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
+ {
+-	deb("%s\n",__FUNCTION__);
++	deb("%s\n",__func__);
+ 
+ 	if ((adap->fe = dvb_attach(mt352_attach,
+ 				   &m920x_mt352_config,
+@@ -489,7 +491,7 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
+ 
+ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
+ {
+-	deb("%s\n",__FUNCTION__);
++	deb("%s\n",__func__);
+ 
+ 	if ((adap->fe = dvb_attach(tda10046_attach,
+ 				   &m920x_tda10046_08_config,
+@@ -501,7 +503,7 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
+ 
+ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
+ {
+-	deb("%s\n",__FUNCTION__);
++	deb("%s\n",__func__);
+ 
+ 	if ((adap->fe = dvb_attach(tda10046_attach,
+ 				   &m920x_tda10046_0b_config,
+@@ -513,7 +515,7 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
+ 
+ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+-	deb("%s\n",__FUNCTION__);
++	deb("%s\n",__func__);
+ 
+ 	if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
+ 		return -ENODEV;
+@@ -523,7 +525,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
+ 
+ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+-	deb("%s\n",__FUNCTION__);
++	deb("%s\n",__func__);
+ 
+ 	if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
+ 		return -ENODEV;
+@@ -533,7 +535,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
+ 
+ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+-	deb("%s\n",__FUNCTION__);
++	deb("%s\n",__func__);
+ 
+ 	if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
+ 		return -ENODEV;
+@@ -618,27 +620,31 @@ static int m920x_probe(struct usb_interface *intf,
+ 		 * multi-tuner device
+ 		 */
+ 
+-		if ((ret = dvb_usb_device_init(intf, &megasky_properties,
+-					       THIS_MODULE, &d)) == 0) {
++		ret = dvb_usb_device_init(intf, &megasky_properties,
++					  THIS_MODULE, &d, adapter_nr);
++		if (ret == 0) {
+ 			rc_init_seq = megasky_rc_init;
+ 			goto found;
+ 		}
+ 
+-		if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
+-					       THIS_MODULE, &d)) == 0) {
++		ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
++					  THIS_MODULE, &d, adapter_nr);
++		if (ret == 0) {
+ 			/* No remote control, so no rc_init_seq */
+ 			goto found;
+ 		}
+ 
+ 		/* This configures both tuners on the TV Walker Twin */
+-		if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
+-					       THIS_MODULE, &d)) == 0) {
++		ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
++					  THIS_MODULE, &d, adapter_nr);
++		if (ret == 0) {
+ 			rc_init_seq = tvwalkertwin_rc_init;
+ 			goto found;
+ 		}
+ 
+-		if ((ret = dvb_usb_device_init(intf, &dposh_properties,
+-					       THIS_MODULE, &d)) == 0) {
++		ret = dvb_usb_device_init(intf, &dposh_properties,
++					  THIS_MODULE, &d, adapter_nr);
++		if (ret == 0) {
+ 			/* Remote controller not supported yet. */
+ 			goto found;
+ 		}
+diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+index badc468..07fb843 100644
+--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
++++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+@@ -15,6 +15,8 @@ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_rc(args...) dprintk(debug,0x01,args)
+ #define deb_ee(args...) dprintk(debug,0x02,args)
+ 
+@@ -142,7 +144,8 @@ static struct dvb_usb_device_properties nova_t_properties;
+ static int nova_t_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+-	return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL);
++	return dvb_usb_device_init(intf, &nova_t_properties,
++				   THIS_MODULE, NULL, adapter_nr);
+ }
+ 
+ /* do not change the order of the ID table */
+diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
+index 302cc67..7e32d11 100644
+--- a/drivers/media/dvb/dvb-usb/opera1.c
++++ b/drivers/media/dvb/dvb-usb/opera1.c
+@@ -46,6 +46,9 @@ MODULE_PARM_DESC(debug,
+ 		 "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
+ 		 DVB_USB_DEBUG_STATUS);
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
++
+ static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
+ 			    u8 * data, u16 len, int flags)
+ {
+@@ -243,7 +246,7 @@ static struct stv0299_config opera1_stv0299_config = {
+ 	.mclk = 88000000UL,
+ 	.invert = 1,
+ 	.skip_reinit = 0,
+-	.lock_output = STV0229_LOCKOUTPUT_0,
++	.lock_output = STV0299_LOCKOUTPUT_0,
+ 	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+ 	.inittab = opera1_inittab,
+ 	.set_symbol_rate = opera1_stv0299_set_symbol_rate,
+@@ -548,7 +551,8 @@ static int opera1_probe(struct usb_interface *intf,
+ 		return -EINVAL;
+ 	}
+ 
+-	if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, NULL) != 0)
++	if (0 != dvb_usb_device_init(intf, &opera1_properties,
++				     THIS_MODULE, NULL, adapter_nr))
+ 		return -EINVAL;
+ 	return 0;
+ }
+diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
+index 3b9da9c..20ca9d9 100644
+--- a/drivers/media/dvb/dvb-usb/ttusb2.c
++++ b/drivers/media/dvb/dvb-usb/ttusb2.c
+@@ -37,6 +37,8 @@ static int dvb_usb_ttusb2_debug;
+ module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ struct ttusb2_state {
+ 	u8 id;
+ };
+@@ -145,6 +147,7 @@ static struct tda10086_config tda10086_config = {
+ 	.demod_address = 0x0e,
+ 	.invert = 0,
+ 	.diseqc_tone = 1,
++	.xtal_freq = TDA10086_XTAL_16M,
+ };
+ 
+ static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
+@@ -176,17 +179,25 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
+ 
+ /* DVB USB Driver stuff */
+ static struct dvb_usb_device_properties ttusb2_properties;
++static struct dvb_usb_device_properties ttusb2_properties_s2400;
+ 
+ static int ttusb2_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+-	return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL);
++	if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
++				     THIS_MODULE, NULL, adapter_nr) ||
++	    0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
++				     THIS_MODULE, NULL, adapter_nr))
++		return 0;
++	return -ENODEV;
+ }
+ 
+ static struct usb_device_id ttusb2_table [] = {
+-		{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
+-		{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
+-		{}		/* Terminating entry */
++	{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
++	{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
++	{ USB_DEVICE(USB_VID_TECHNOTREND,
++		USB_PID_TECHNOTREND_CONNECT_S2400) },
++	{}		/* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE (usb, ttusb2_table);
+ 
+@@ -242,6 +253,54 @@ static struct dvb_usb_device_properties ttusb2_properties = {
+ 	}
+ };
+ 
++static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
++	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
++
++	.usb_ctrl = CYPRESS_FX2,
++	.firmware = "dvb-usb-tt-s2400-01.fw",
++
++	.size_of_priv = sizeof(struct ttusb2_state),
++
++	.num_adapters = 1,
++	.adapter = {
++		{
++			.streaming_ctrl   = NULL,
++
++			.frontend_attach  = ttusb2_frontend_attach,
++			.tuner_attach     = ttusb2_tuner_attach,
++
++			/* parameter for the MPEG2-data transfer */
++			.stream = {
++				.type = USB_ISOC,
++				.count = 5,
++				.endpoint = 0x02,
++				.u = {
++					.isoc = {
++						.framesperurb = 4,
++						.framesize = 940,
++						.interval = 1,
++					}
++				}
++			}
++		}
++	},
++
++	.power_ctrl       = ttusb2_power_ctrl,
++	.identify_state   = ttusb2_identify_state,
++
++	.i2c_algo         = &ttusb2_i2c_algo,
++
++	.generic_bulk_ctrl_endpoint = 0x01,
++
++	.num_device_descs = 1,
++	.devices = {
++		{   "Technotrend TT-connect S-2400",
++			{ &ttusb2_table[2], NULL },
++			{ NULL },
++		},
++	}
++};
++
+ static struct usb_driver ttusb2_driver = {
+ 	.name		= "dvb_usb_ttusb2",
+ 	.probe		= ttusb2_probe,
+diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
+index 0dcab3d..9e7653b 100644
+--- a/drivers/media/dvb/dvb-usb/umt-010.c
++++ b/drivers/media/dvb/dvb-usb/umt-010.c
+@@ -13,6 +13,8 @@
+ 
+ #include "mt352.h"
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int umt_mt352_demod_init(struct dvb_frontend *fe)
+ {
+ 	static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
+@@ -75,7 +77,8 @@ static struct dvb_usb_device_properties umt_properties;
+ static int umt_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+-	if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0)
++	if (0 == dvb_usb_device_init(intf, &umt_properties,
++				     THIS_MODULE, NULL, adapter_nr))
+ 		return 0;
+ 	return -EINVAL;
+ }
+diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
+index c3fdc7c..ccc7e44 100644
+--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
++++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
+@@ -67,7 +67,7 @@ static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+ {
+ 	struct vp702x_fe_state *st = fe->demodulator_priv;
+ 	vp702x_fe_refresh_state(st);
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 
+ 	if (st->lock == 0)
+ 		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+@@ -121,7 +121,7 @@ static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+ 
+ static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+ {
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 	tune->min_delay_ms = 2000;
+ 	return 0;
+ }
+@@ -183,21 +183,21 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
+ static int vp702x_fe_init(struct dvb_frontend *fe)
+ {
+ 	struct vp702x_fe_state *st = fe->demodulator_priv;
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 	vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
+ 	return 0;
+ }
+ 
+ static int vp702x_fe_sleep(struct dvb_frontend *fe)
+ {
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 	return 0;
+ }
+ 
+ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
+ 				  struct dvb_frontend_parameters *fep)
+ {
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 	return 0;
+ }
+ 
+@@ -208,7 +208,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
+ 	u8 cmd[8],ibuf[10];
+ 	memset(cmd,0,8);
+ 
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 
+ 	if (m->msg_len > 4)
+ 		return -EINVAL;
+@@ -230,7 +230,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
+ 
+ static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+ {
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 	return 0;
+ }
+ 
+@@ -238,7 +238,7 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+ {
+ 	struct vp702x_fe_state *st = fe->demodulator_priv;
+ 	u8 ibuf[10];
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 
+ 	st->tone_mode = tone;
+ 
+@@ -263,7 +263,7 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
+ {
+ 	struct vp702x_fe_state *st = fe->demodulator_priv;
+ 	u8 ibuf[10];
+-	deb_fe("%s\n",__FUNCTION__);
++	deb_fe("%s\n",__func__);
+ 
+ 	st->voltage = voltage;
+ 
+diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
+index e553c13..986fff9 100644
+--- a/drivers/media/dvb/dvb-usb/vp702x.c
++++ b/drivers/media/dvb/dvb-usb/vp702x.c
+@@ -21,6 +21,8 @@ int dvb_usb_vp702x_debug;
+ module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ struct vp702x_state {
+ 	int pid_filter_count;
+ 	int pid_filter_can_bypass;
+@@ -238,7 +240,8 @@ static struct dvb_usb_device_properties vp702x_properties;
+ static int vp702x_usb_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+-	return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
++	return dvb_usb_device_init(intf, &vp702x_properties,
++				   THIS_MODULE, NULL, adapter_nr);
+ }
+ 
+ static struct usb_device_id vp702x_usb_table [] = {
+diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
+index c172bab..acb3455 100644
+--- a/drivers/media/dvb/dvb-usb/vp7045.c
++++ b/drivers/media/dvb/dvb-usb/vp7045.c
+@@ -18,6 +18,9 @@
+ static int dvb_usb_vp7045_debug;
+ module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
+ #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
+ #define deb_rc(args...)   dprintk(dvb_usb_vp7045_debug,0x04,args)
+@@ -219,7 +222,8 @@ static struct dvb_usb_device_properties vp7045_properties;
+ static int vp7045_usb_probe(struct usb_interface *intf,
+ 		const struct usb_device_id *id)
+ {
+-	return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL);
++	return dvb_usb_device_init(intf, &vp7045_properties,
++				   THIS_MODULE, NULL, adapter_nr);
+ }
+ 
+ static struct usb_device_id vp7045_usb_table [] = {
+diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
+index 9ad86ce..f5fceb3 100644
+--- a/drivers/media/dvb/frontends/Kconfig
++++ b/drivers/media/dvb/frontends/Kconfig
+@@ -188,6 +188,14 @@ config DVB_DIB7000P
+ 	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+ 	  to support this frontend.
+ 
++config DVB_TDA10048
++	tristate "Philips TDA10048HN based"
++	depends on DVB_CORE && I2C
++	default m if DVB_FE_CUSTOMISE
++	select FW_LOADER
++	help
++	  A DVB-T tuner module. Say Y when you want to support this frontend.
++
+ comment "DVB-C (cable) frontends"
+ 	depends on DVB_CORE
+ 
+@@ -291,6 +299,22 @@ config DVB_S5H1409
+ 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+ 	  to support this frontend.
+ 
++config DVB_AU8522
++	tristate "Auvitek AU8522 based"
++	depends on DVB_CORE && I2C
++	default m if DVB_FE_CUSTOMISE
++	help
++	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
++	  to support this frontend.
++
++config DVB_S5H1411
++	tristate "Samsung S5H1411 based"
++	depends on DVB_CORE && I2C
++	default m if DVB_FE_CUSTOMISE
++	help
++	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
++	  to support this frontend.
++
+ comment "Tuners/PLL support"
+ 	depends on DVB_CORE
+ 
+@@ -369,6 +393,11 @@ config DVB_TUNER_XC5000
+ 	  This device is only used inside a SiP called togther with a
+ 	  demodulator for now.
+ 
++config DVB_TUNER_ITD1000
++	tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
++	depends on DVB_CORE && I2C
++	default m if DVB_FE_CUSTOMISE
++
+ comment "Miscellaneous devices"
+ 	depends on DVB_CORE
+ 
+@@ -379,6 +408,13 @@ config DVB_LNBP21
+ 	help
+ 	  An SEC control chip.
+ 
++config DVB_ISL6405
++	tristate "ISL6405 SEC controller"
++	depends on DVB_CORE && I2C
++	default m if DVB_FE_CUSTOMISE
++	help
++	  An SEC control chip.
++
+ config DVB_ISL6421
+ 	tristate "ISL6421 SEC controller"
+ 	depends on DVB_CORE && I2C
+diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
+index 16bd107..9747c73 100644
+--- a/drivers/media/dvb/frontends/Makefile
++++ b/drivers/media/dvb/frontends/Makefile
+@@ -38,6 +38,7 @@ obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
+ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
+ obj-$(CONFIG_DVB_CX24123) += cx24123.o
+ obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
++obj-$(CONFIG_DVB_ISL6405) += isl6405.o
+ obj-$(CONFIG_DVB_ISL6421) += isl6421.o
+ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
+ obj-$(CONFIG_DVB_TDA826X) += tda826x.o
+@@ -51,3 +52,7 @@ obj-$(CONFIG_DVB_TUA6100) += tua6100.o
+ obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
+ obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
+ obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
++obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
++obj-$(CONFIG_DVB_AU8522) += au8522.o
++obj-$(CONFIG_DVB_TDA10048) += tda10048.o
++obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
+diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
+new file mode 100644
+index 0000000..084a280
+--- /dev/null
++++ b/drivers/media/dvb/frontends/au8522.c
+@@ -0,0 +1,692 @@
++/*
++    Auvitek AU8522 QAM/8VSB demodulator driver
++
++    Copyright (C) 2008 Steven Toth <stoth at hauppauge.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/init.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include "dvb_frontend.h"
++#include "dvb-pll.h"
++#include "au8522.h"
++
++struct au8522_state {
++
++	struct i2c_adapter *i2c;
++
++	/* configuration settings */
++	const struct au8522_config *config;
++
++	struct dvb_frontend frontend;
++
++	u32 current_frequency;
++	fe_modulation_t current_modulation;
++
++};
++
++static int debug;
++
++#define dprintk(arg...) do {		\
++	if (debug) 			\
++		 printk(arg); 		\
++	} while (0)
++
++/* 16 bit registers, 8 bit values */
++static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
++{
++	int ret;
++	u8 buf [] = { reg >> 8, reg & 0xff, data };
++
++	struct i2c_msg msg = { .addr = state->config->demod_address,
++			       .flags = 0, .buf = buf, .len = 3 };
++
++	ret = i2c_transfer(state->i2c, &msg, 1);
++
++	if (ret != 1)
++		printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
++		       "ret == %i)\n", __func__, reg, data, ret);
++
++	return (ret != 1) ? -1 : 0;
++}
++
++static u8 au8522_readreg(struct au8522_state *state, u16 reg)
++{
++	int ret;
++	u8 b0 [] = { reg >> 8, reg & 0xff };
++	u8 b1 [] = { 0 };
++
++	struct i2c_msg msg [] = {
++		{ .addr = state->config->demod_address, .flags = 0,
++		  .buf = b0, .len = 2 },
++		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
++		  .buf = b1, .len = 1 } };
++
++	ret = i2c_transfer(state->i2c, msg, 2);
++
++	if (ret != 2)
++		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
++		       __func__, ret);
++	return b1[0];
++}
++
++static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
++{
++	struct au8522_state *state = fe->demodulator_priv;
++
++	dprintk("%s(%d)\n", __func__, enable);
++
++	if (enable)
++		return au8522_writereg(state, 0x106, 1);
++	else
++		return au8522_writereg(state, 0x106, 0);
++}
++
++struct mse2snr_tab {
++	u16 val;
++	u16 data;
++};
++
++/* VSB SNR lookup table */
++static struct mse2snr_tab vsb_mse2snr_tab[] = {
++	{   0, 270 },
++	{   2, 250 },
++	{   3, 240 },
++	{   5, 230 },
++	{   7, 220 },
++	{   9, 210 },
++	{  12, 200 },
++	{  13, 195 },
++	{  15, 190 },
++	{  17, 185 },
++	{  19, 180 },
++	{  21, 175 },
++	{  24, 170 },
++	{  27, 165 },
++	{  31, 160 },
++	{  32, 158 },
++	{  33, 156 },
++	{  36, 152 },
++	{  37, 150 },
++	{  39, 148 },
++	{  40, 146 },
++	{  41, 144 },
++	{  43, 142 },
++	{  44, 140 },
++	{  48, 135 },
++	{  50, 130 },
++	{  43, 142 },
++	{  53, 125 },
++	{  56, 120 },
++	{ 256, 115 },
++};
++
++/* QAM64 SNR lookup table */
++static struct mse2snr_tab qam64_mse2snr_tab[] = {
++	{  15,   0 },
++	{  16, 290 },
++	{  17, 288 },
++	{  18, 286 },
++	{  19, 284 },
++	{  20, 282 },
++	{  21, 281 },
++	{  22, 279 },
++	{  23, 277 },
++	{  24, 275 },
++	{  25, 273 },
++	{  26, 271 },
++	{  27, 269 },
++	{  28, 268 },
++	{  29, 266 },
++	{  30, 264 },
++	{  31, 262 },
++	{  32, 260 },
++	{  33, 259 },
++	{  34, 258 },
++	{  35, 256 },
++	{  36, 255 },
++	{  37, 254 },
++	{  38, 252 },
++	{  39, 251 },
++	{  40, 250 },
++	{  41, 249 },
++	{  42, 248 },
++	{  43, 246 },
++	{  44, 245 },
++	{  45, 244 },
++	{  46, 242 },
++	{  47, 241 },
++	{  48, 240 },
++	{  50, 239 },
++	{  51, 238 },
++	{  53, 237 },
++	{  54, 236 },
++	{  56, 235 },
++	{  57, 234 },
++	{  59, 233 },
++	{  60, 232 },
++	{  62, 231 },
++	{  63, 230 },
++	{  65, 229 },
++	{  67, 228 },
++	{  68, 227 },
++	{  70, 226 },
++	{  71, 225 },
++	{  73, 224 },
++	{  74, 223 },
++	{  76, 222 },
++	{  78, 221 },
++	{  80, 220 },
++	{  82, 219 },
++	{  85, 218 },
++	{  88, 217 },
++	{  90, 216 },
++	{  92, 215 },
++	{  93, 214 },
++	{  94, 212 },
++	{  95, 211 },
++	{  97, 210 },
++	{  99, 209 },
++	{ 101, 208 },
++	{ 102, 207 },
++	{ 104, 206 },
++	{ 107, 205 },
++	{ 111, 204 },
++	{ 114, 203 },
++	{ 118, 202 },
++	{ 122, 201 },
++	{ 125, 200 },
++	{ 128, 199 },
++	{ 130, 198 },
++	{ 132, 197 },
++	{ 256, 190 },
++};
++
++/* QAM256 SNR lookup table */
++static struct mse2snr_tab qam256_mse2snr_tab[] = {
++	{  16,   0 },
++	{  17, 400 },
++	{  18, 398 },
++	{  19, 396 },
++	{  20, 394 },
++	{  21, 392 },
++	{  22, 390 },
++	{  23, 388 },
++	{  24, 386 },
++	{  25, 384 },
++	{  26, 382 },
++	{  27, 380 },
++	{  28, 379 },
++	{  29, 378 },
++	{  30, 377 },
++	{  31, 376 },
++	{  32, 375 },
++	{  33, 374 },
++	{  34, 373 },
++	{  35, 372 },
++	{  36, 371 },
++	{  37, 370 },
++	{  38, 362 },
++	{  39, 354 },
++	{  40, 346 },
++	{  41, 338 },
++	{  42, 330 },
++	{  43, 328 },
++	{  44, 326 },
++	{  45, 324 },
++	{  46, 322 },
++	{  47, 320 },
++	{  48, 319 },
++	{  49, 318 },
++	{  50, 317 },
++	{  51, 316 },
++	{  52, 315 },
++	{  53, 314 },
++	{  54, 313 },
++	{  55, 312 },
++	{  56, 311 },
++	{  57, 310 },
++	{  58, 308 },
++	{  59, 306 },
++	{  60, 304 },
++	{  61, 302 },
++	{  62, 300 },
++	{  63, 298 },
++	{  65, 295 },
++	{  68, 294 },
++	{  70, 293 },
++	{  73, 292 },
++	{  76, 291 },
++	{  78, 290 },
++	{  79, 289 },
++	{  81, 288 },
++	{  82, 287 },
++	{  83, 286 },
++	{  84, 285 },
++	{  85, 284 },
++	{  86, 283 },
++	{  88, 282 },
++	{  89, 281 },
++	{ 256, 280 },
++};
++
++static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
++				 u16 *snr)
++{
++	int i, ret = -EINVAL;
++	dprintk("%s()\n", __func__);
++
++	for (i = 0; i < sz; i++) {
++		if (mse < tab[i].val) {
++			*snr = tab[i].data;
++			ret = 0;
++			break;
++		}
++	}
++	dprintk("%s() snr=%d\n", __func__, *snr);
++	return ret;
++}
++
++/* VSB Modulation table */
++static struct {
++	u16 reg;
++	u16 data;
++} VSB_mod_tab[] = {
++	{ 0x8090, 0x84 },
++	{ 0x4092, 0x11 },
++	{ 0x2005, 0x00 },
++	{ 0x8091, 0x80 },
++	{ 0x80a3, 0x0c },
++	{ 0x80a4, 0xe8 },
++	{ 0x8081, 0xc4 },
++	{ 0x80a5, 0x40 },
++	{ 0x80a7, 0x40 },
++	{ 0x80a6, 0x67 },
++	{ 0x8262, 0x20 },
++	{ 0x821c, 0x30 },
++	{ 0x80d8, 0x1a },
++	{ 0x8227, 0xa0 },
++	{ 0x8121, 0xff },
++	{ 0x80a8, 0xf0 },
++	{ 0x80a9, 0x05 },
++	{ 0x80aa, 0x77 },
++	{ 0x80ab, 0xf0 },
++	{ 0x80ac, 0x05 },
++	{ 0x80ad, 0x77 },
++	{ 0x80ae, 0x41 },
++	{ 0x80af, 0x66 },
++	{ 0x821b, 0xcc },
++	{ 0x821d, 0x80 },
++	{ 0x80b5, 0xfb },
++	{ 0x80b6, 0x8e },
++	{ 0x80b7, 0x39 },
++	{ 0x80a4, 0xe8 },
++	{ 0x8231, 0x13 },
++};
++
++/* QAM Modulation table */
++static struct {
++	u16 reg;
++	u16 data;
++} QAM_mod_tab[] = {
++	{ 0x80a3, 0x09 },
++	{ 0x80a4, 0x00 },
++	{ 0x8081, 0xc4 },
++	{ 0x80a5, 0x40 },
++	{ 0x80b5, 0xfb },
++	{ 0x80b6, 0x8e },
++	{ 0x80b7, 0x39 },
++	{ 0x80aa, 0x77 },
++	{ 0x80ad, 0x77 },
++	{ 0x80a6, 0x67 },
++	{ 0x8262, 0x20 },
++	{ 0x821c, 0x30 },
++	{ 0x80b8, 0x3e },
++	{ 0x80b9, 0xf0 },
++	{ 0x80ba, 0x01 },
++	{ 0x80bb, 0x18 },
++	{ 0x80bc, 0x50 },
++	{ 0x80bd, 0x00 },
++	{ 0x80be, 0xea },
++	{ 0x80bf, 0xef },
++	{ 0x80c0, 0xfc },
++	{ 0x80c1, 0xbd },
++	{ 0x80c2, 0x1f },
++	{ 0x80c3, 0xfc },
++	{ 0x80c4, 0xdd },
++	{ 0x80c5, 0xaf },
++	{ 0x80c6, 0x00 },
++	{ 0x80c7, 0x38 },
++	{ 0x80c8, 0x30 },
++	{ 0x80c9, 0x05 },
++	{ 0x80ca, 0x4a },
++	{ 0x80cb, 0xd0 },
++	{ 0x80cc, 0x01 },
++	{ 0x80cd, 0xd9 },
++	{ 0x80ce, 0x6f },
++	{ 0x80cf, 0xf9 },
++	{ 0x80d0, 0x70 },
++	{ 0x80d1, 0xdf },
++	{ 0x80d2, 0xf7 },
++	{ 0x80d3, 0xc2 },
++	{ 0x80d4, 0xdf },
++	{ 0x80d5, 0x02 },
++	{ 0x80d6, 0x9a },
++	{ 0x80d7, 0xd0 },
++	{ 0x8250, 0x0d },
++	{ 0x8251, 0xcd },
++	{ 0x8252, 0xe0 },
++	{ 0x8253, 0x05 },
++	{ 0x8254, 0xa7 },
++	{ 0x8255, 0xff },
++	{ 0x8256, 0xed },
++	{ 0x8257, 0x5b },
++	{ 0x8258, 0xae },
++	{ 0x8259, 0xe6 },
++	{ 0x825a, 0x3d },
++	{ 0x825b, 0x0f },
++	{ 0x825c, 0x0d },
++	{ 0x825d, 0xea },
++	{ 0x825e, 0xf2 },
++	{ 0x825f, 0x51 },
++	{ 0x8260, 0xf5 },
++	{ 0x8261, 0x06 },
++	{ 0x821a, 0x00 },
++	{ 0x8546, 0x40 },
++	{ 0x8210, 0x26 },
++	{ 0x8211, 0xf6 },
++	{ 0x8212, 0x84 },
++	{ 0x8213, 0x02 },
++	{ 0x8502, 0x01 },
++	{ 0x8121, 0x04 },
++	{ 0x8122, 0x04 },
++	{ 0x852e, 0x10 },
++	{ 0x80a4, 0xca },
++	{ 0x80a7, 0x40 },
++	{ 0x8526, 0x01 },
++};
++
++static int au8522_enable_modulation(struct dvb_frontend *fe,
++				    fe_modulation_t m)
++{
++	struct au8522_state *state = fe->demodulator_priv;
++	int i;
++
++	dprintk("%s(0x%08x)\n", __func__, m);
++
++	switch (m) {
++	case VSB_8:
++		dprintk("%s() VSB_8\n", __func__);
++		for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++)
++			au8522_writereg(state,
++				VSB_mod_tab[i].reg,
++				VSB_mod_tab[i].data);
++		break;
++	case QAM_64:
++	case QAM_256:
++		dprintk("%s() QAM 64/256\n", __func__);
++		for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++)
++			au8522_writereg(state,
++				QAM_mod_tab[i].reg,
++				QAM_mod_tab[i].data);
++		break;
++	default:
++		dprintk("%s() Invalid modulation\n", __func__);
++		return -EINVAL;
++	}
++
++	state->current_modulation = m;
++
++	return 0;
++}
++
++/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
++static int au8522_set_frontend(struct dvb_frontend *fe,
++			       struct dvb_frontend_parameters *p)
++{
++	struct au8522_state *state = fe->demodulator_priv;
++
++	dprintk("%s(frequency=%d)\n", __func__, p->frequency);
++
++	state->current_frequency = p->frequency;
++
++	au8522_enable_modulation(fe, p->u.vsb.modulation);
++
++	/* Allow the demod to settle */
++	msleep(100);
++
++	if (fe->ops.tuner_ops.set_params) {
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 1);
++		fe->ops.tuner_ops.set_params(fe, p);
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 0);
++	}
++
++	return 0;
++}
++
++/* Reset the demod hardware and reset all of the configuration registers
++   to a default state. */
++static int au8522_init(struct dvb_frontend *fe)
++{
++	struct au8522_state *state = fe->demodulator_priv;
++	dprintk("%s()\n", __func__);
++
++	au8522_writereg(state, 0xa4, 1 << 5);
++
++	au8522_i2c_gate_ctrl(fe, 1);
++
++	return 0;
++}
++
++static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
++{
++	struct au8522_state *state = fe->demodulator_priv;
++	u8 reg;
++	u32 tuner_status = 0;
++
++	*status = 0;
++
++	if (state->current_modulation == VSB_8) {
++		dprintk("%s() Checking VSB_8\n", __func__);
++		reg = au8522_readreg(state, 0x4088);
++		if (reg & 0x01)
++			*status |= FE_HAS_VITERBI;
++		if (reg & 0x02)
++			*status |= FE_HAS_LOCK | FE_HAS_SYNC;
++	} else {
++		dprintk("%s() Checking QAM\n", __func__);
++		reg = au8522_readreg(state, 0x4541);
++		if (reg & 0x80)
++			*status |= FE_HAS_VITERBI;
++		if (reg & 0x20)
++			*status |= FE_HAS_LOCK | FE_HAS_SYNC;
++	}
++
++	switch (state->config->status_mode) {
++	case AU8522_DEMODLOCKING:
++		dprintk("%s() DEMODLOCKING\n", __func__);
++		if (*status & FE_HAS_VITERBI)
++			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++		break;
++	case AU8522_TUNERLOCKING:
++		/* Get the tuner status */
++		dprintk("%s() TUNERLOCKING\n", __func__);
++		if (fe->ops.tuner_ops.get_status) {
++			if (fe->ops.i2c_gate_ctrl)
++				fe->ops.i2c_gate_ctrl(fe, 1);
++
++			fe->ops.tuner_ops.get_status(fe, &tuner_status);
++
++			if (fe->ops.i2c_gate_ctrl)
++				fe->ops.i2c_gate_ctrl(fe, 0);
++		}
++		if (tuner_status)
++			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++		break;
++	}
++
++	dprintk("%s() status 0x%08x\n", __func__, *status);
++
++	return 0;
++}
++
++static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++	struct au8522_state *state = fe->demodulator_priv;
++	int ret = -EINVAL;
++
++	dprintk("%s()\n", __func__);
++
++	if (state->current_modulation == QAM_256)
++		ret = au8522_mse2snr_lookup(qam256_mse2snr_tab,
++					    ARRAY_SIZE(qam256_mse2snr_tab),
++					    au8522_readreg(state, 0x4522),
++					    snr);
++	else if (state->current_modulation == QAM_64)
++		ret = au8522_mse2snr_lookup(qam64_mse2snr_tab,
++					    ARRAY_SIZE(qam64_mse2snr_tab),
++					    au8522_readreg(state, 0x4522),
++					    snr);
++	else /* VSB_8 */
++		ret = au8522_mse2snr_lookup(vsb_mse2snr_tab,
++					    ARRAY_SIZE(vsb_mse2snr_tab),
++					    au8522_readreg(state, 0x4311),
++					    snr);
++
++	return ret;
++}
++
++static int au8522_read_signal_strength(struct dvb_frontend *fe,
++				       u16 *signal_strength)
++{
++	return au8522_read_snr(fe, signal_strength);
++}
++
++static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
++{
++	struct au8522_state *state = fe->demodulator_priv;
++
++	if (state->current_modulation == VSB_8)
++		*ucblocks = au8522_readreg(state, 0x4087);
++	else
++		*ucblocks = au8522_readreg(state, 0x4543);
++
++	return 0;
++}
++
++static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
++{
++	return au8522_read_ucblocks(fe, ber);
++}
++
++static int au8522_get_frontend(struct dvb_frontend *fe,
++				struct dvb_frontend_parameters *p)
++{
++	struct au8522_state *state = fe->demodulator_priv;
++
++	p->frequency = state->current_frequency;
++	p->u.vsb.modulation = state->current_modulation;
++
++	return 0;
++}
++
++static int au8522_get_tune_settings(struct dvb_frontend *fe,
++				    struct dvb_frontend_tune_settings *tune)
++{
++	tune->min_delay_ms = 1000;
++	return 0;
++}
++
++static void au8522_release(struct dvb_frontend *fe)
++{
++	struct au8522_state *state = fe->demodulator_priv;
++	kfree(state);
++}
++
++static struct dvb_frontend_ops au8522_ops;
++
++struct dvb_frontend *au8522_attach(const struct au8522_config *config,
++				   struct i2c_adapter *i2c)
++{
++	struct au8522_state *state = NULL;
++
++	/* allocate memory for the internal state */
++	state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
++	if (state == NULL)
++		goto error;
++
++	/* setup the state */
++	state->config = config;
++	state->i2c = i2c;
++	/* create dvb_frontend */
++	memcpy(&state->frontend.ops, &au8522_ops,
++	       sizeof(struct dvb_frontend_ops));
++	state->frontend.demodulator_priv = state;
++
++	if (au8522_init(&state->frontend) != 0) {
++		printk(KERN_ERR "%s: Failed to initialize correctly\n",
++			__func__);
++		goto error;
++	}
++
++	/* Note: Leaving the I2C gate open here. */
++	au8522_i2c_gate_ctrl(&state->frontend, 1);
++
++	return &state->frontend;
++
++error:
++	kfree(state);
++	return NULL;
++}
++EXPORT_SYMBOL(au8522_attach);
++
++static struct dvb_frontend_ops au8522_ops = {
++
++	.info = {
++		.name			= "Auvitek AU8522 QAM/8VSB Frontend",
++		.type			= FE_ATSC,
++		.frequency_min		= 54000000,
++		.frequency_max		= 858000000,
++		.frequency_stepsize	= 62500,
++		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
++	},
++
++	.init                 = au8522_init,
++	.i2c_gate_ctrl        = au8522_i2c_gate_ctrl,
++	.set_frontend         = au8522_set_frontend,
++	.get_frontend         = au8522_get_frontend,
++	.get_tune_settings    = au8522_get_tune_settings,
++	.read_status          = au8522_read_status,
++	.read_ber             = au8522_read_ber,
++	.read_signal_strength = au8522_read_signal_strength,
++	.read_snr             = au8522_read_snr,
++	.read_ucblocks        = au8522_read_ucblocks,
++	.release              = au8522_release,
++};
++
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable verbose debug messages");
++
++MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
++MODULE_AUTHOR("Steven Toth");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h
+new file mode 100644
+index 0000000..d7affa3
+--- /dev/null
++++ b/drivers/media/dvb/frontends/au8522.h
+@@ -0,0 +1,56 @@
++/*
++    Auvitek AU8522 QAM/8VSB demodulator driver
++
++    Copyright (C) 2008 Steven Toth <stoth at hauppauge.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 __AU8522_H__
++#define __AU8522_H__
++
++#include <linux/dvb/frontend.h>
++
++struct au8522_config {
++	/* the demodulator's i2c address */
++	u8 demod_address;
++
++	/* Return lock status based on tuner lock, or demod lock */
++#define AU8522_TUNERLOCKING 0
++#define AU8522_DEMODLOCKING 1
++	u8 status_mode;
++};
++
++#if defined(CONFIG_DVB_AU8522) || 				\
++	    (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
++extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
++					  struct i2c_adapter *i2c);
++#else
++static inline
++struct dvb_frontend *au8522_attach(const struct au8522_config *config,
++				   struct i2c_adapter *i2c)
++{
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++	return NULL;
++}
++#endif /* CONFIG_DVB_AU8522 */
++
++#endif /* __AU8522_H__ */
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
+index a913f49..d268e65 100644
+--- a/drivers/media/dvb/frontends/bcm3510.c
++++ b/drivers/media/dvb/frontends/bcm3510.c
+@@ -91,7 +91,7 @@ static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8
+ 	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ 
+ 		deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
+-			__FUNCTION__, state->config->demod_address, reg,  err);
++			__func__, state->config->demod_address, reg,  err);
+ 		return -EREMOTEIO;
+ 	}
+ 
+@@ -110,7 +110,7 @@ static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 l
+ 
+ 	if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
+ 		deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
+-			__FUNCTION__, state->config->demod_address, reg,  err);
++			__func__, state->config->demod_address, reg,  err);
+ 		return -EREMOTEIO;
+ 	}
+ 	deb_i2c("i2c rd %02x: ",reg);
+diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h
+index 7e4f95e..f4575c0 100644
+--- a/drivers/media/dvb/frontends/bcm3510.h
++++ b/drivers/media/dvb/frontends/bcm3510.h
+@@ -41,7 +41,7 @@ extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+ static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+ 						  struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_BCM3510
+diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb/frontends/bsbe1.h
+index d8f6573..5e431eb 100644
+--- a/drivers/media/dvb/frontends/bsbe1.h
++++ b/drivers/media/dvb/frontends/bsbe1.h
+@@ -1,5 +1,5 @@
+ /*
+- * bsbe1.h - ALPS BSBE1 tuner support (moved from av7110.c)
++ * bsbe1.h - ALPS BSBE1 tuner support
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+@@ -26,44 +26,24 @@
+ #define BSBE1_H
+ 
+ static u8 alps_bsbe1_inittab[] = {
+-	0x01, 0x15,
+-	0x02, 0x30,
+-	0x03, 0x00,
++	0x01, 0x15,   /* XTAL = 4MHz, VCO = 352 MHz */
++	0x02, 0x30,   /* MCLK = 88 MHz */
++	0x03, 0x00,   /* ACR output 0 */
+ 	0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+-	0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
+-	0x06, 0x40,   /* DAC not used, set to high impendance mode */
+-	0x07, 0x00,   /* DAC LSB */
++	0x05, 0x05,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
++	0x06, 0x00,   /* DAC output 0 */
+ 	0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
+ 	0x09, 0x00,   /* FIFO */
+-	0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+-	0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
+-	0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
+-	0x10, 0x3f,   // AGC2  0x3d
+-	0x11, 0x84,
+-	0x12, 0xb9,
+-	0x15, 0xc9,   // lock detector threshold
+-	0x16, 0x00,
+-	0x17, 0x00,
+-	0x18, 0x00,
+-	0x19, 0x00,
+-	0x1a, 0x00,
+-	0x1f, 0x50,
+-	0x20, 0x00,
+-	0x21, 0x00,
+-	0x22, 0x00,
+-	0x23, 0x00,
+-	0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
+-	0x29, 0x1e,  // 1/2 threshold
+-	0x2a, 0x14,  // 2/3 threshold
+-	0x2b, 0x0f,  // 3/4 threshold
+-	0x2c, 0x09,  // 5/6 threshold
+-	0x2d, 0x05,  // 7/8 threshold
+-	0x2e, 0x01,
+-	0x31, 0x1f,  // test all FECs
+-	0x32, 0x19,  // viterbi and synchro search
+-	0x33, 0xfc,  // rs control
+-	0x34, 0x93,  // error control
+-	0x0f, 0x92,
++	0x0c, 0x51,   /* OP1/OP0 normal, val = 1 (LNB power on) */
++	0x0d, 0x82,   /* DC offset compensation = on, beta_agc1 = 2 */
++	0x0f, 0x92,   /* AGC1R */
++	0x10, 0x34,   /* AGC2O */
++	0x11, 0x84,   /* TLSR */
++	0x12, 0xb9,   /* CFD */
++	0x15, 0xc9,   /* lock detector threshold */
++	0x28, 0x00,   /* out imp: normal, type: parallel, FEC mode: QPSK */
++	0x33, 0xfc,   /* RS control */
++	0x34, 0x93,   /* count viterbi bit errors per 2E18 bytes */
+ 	0xff, 0xff
+ };
+ 
+@@ -100,11 +80,11 @@ static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_front
+ 	if ((params->frequency < 950000) || (params->frequency > 2150000))
+ 		return -EINVAL;
+ 
+-	div = (params->frequency + (125 - 1)) / 125; // round correctly
++	div = params->frequency / 1000;
+ 	data[0] = (div >> 8) & 0x7f;
+ 	data[1] = div & 0xff;
+-	data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
+-	data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
++	data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1;
++	data[3] = 0xe0;
+ 
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h
+index e231cd8..45a6dfd 100644
+--- a/drivers/media/dvb/frontends/bsru6.h
++++ b/drivers/media/dvb/frontends/bsru6.h
+@@ -133,7 +133,7 @@ static struct stv0299_config alps_bsru6_config = {
+ 	.mclk = 88000000UL,
+ 	.invert = 1,
+ 	.skip_reinit = 0,
+-	.lock_output = STV0229_LOCKOUTPUT_1,
++	.lock_output = STV0299_LOCKOUTPUT_1,
+ 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+ 	.min_delay_ms = 100,
+ 	.set_symbol_rate = alps_bsru6_set_symbol_rate,
+diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c
+index 11a4968..ace5cb1 100644
+--- a/drivers/media/dvb/frontends/cx22700.c
++++ b/drivers/media/dvb/frontends/cx22700.c
+@@ -73,13 +73,13 @@ static int cx22700_writereg (struct cx22700_state* state, u8 reg, u8 data)
+ 	u8 buf [] = { reg, data };
+ 	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	ret = i2c_transfer (state->i2c, &msg, 1);
+ 
+ 	if (ret != 1)
+ 		printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+-			__FUNCTION__, reg, data, ret);
++			__func__, reg, data, ret);
+ 
+ 	return (ret != 1) ? -1 : 0;
+ }
+@@ -92,7 +92,7 @@ static int cx22700_readreg (struct cx22700_state* state, u8 reg)
+ 	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+ 			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	ret = i2c_transfer (state->i2c, msg, 2);
+ 
+@@ -105,7 +105,7 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
+ {
+ 	u8 val;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	switch (inversion) {
+ 	case INVERSION_AUTO:
+@@ -127,7 +127,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
+ 	static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
+ 	u8 val;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (p->code_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8)
+ 		return -EINVAL;
+@@ -191,7 +191,7 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet
+ 						    FEC_5_6, FEC_7_8 };
+ 	u8 val;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (!(cx22700_readreg(state, 0x07) & 0x20))  /*  tps valid? */
+ 		return -EAGAIN;
+diff --git a/drivers/media/dvb/frontends/cx22700.h b/drivers/media/dvb/frontends/cx22700.h
+index 7ac3369..4757a93 100644
+--- a/drivers/media/dvb/frontends/cx22700.h
++++ b/drivers/media/dvb/frontends/cx22700.h
+@@ -38,7 +38,7 @@ extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+ static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_CX22700
+diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
+index 1dc164d..cc1db4e 100644
+--- a/drivers/media/dvb/frontends/cx22702.c
++++ b/drivers/media/dvb/frontends/cx22702.c
+@@ -48,7 +48,7 @@ struct cx22702_state {
+ 	u8 prevUCBlocks;
+ };
+ 
+-static int debug = 0;
++static int debug;
+ #define dprintk	if (debug) printk
+ 
+ /* Register values to initialise the demod */
+@@ -90,7 +90,7 @@ static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
+ 
+ 	if (ret != 1)
+ 		printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+-			__FUNCTION__, reg, data, ret);
++			__func__, reg, data, ret);
+ 
+ 	return (ret != 1) ? -1 : 0;
+ }
+@@ -108,7 +108,7 @@ static u8 cx22702_readreg (struct cx22702_state* state, u8 reg)
+ 	ret = i2c_transfer(state->i2c, msg, 2);
+ 
+ 	if (ret != 2)
+-		printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++		printk("%s: readreg error (ret == %i)\n", __func__, ret);
+ 
+ 	return b1[0];
+ }
+@@ -195,7 +195,7 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
+ static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ 	struct cx22702_state* state = fe->demodulator_priv;
+-	dprintk ("%s(%d)\n", __FUNCTION__, enable);
++	dprintk ("%s(%d)\n", __func__, enable);
+ 	if (enable)
+ 		return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
+ 	else
+@@ -228,7 +228,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ 		cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf );
+ 		break;
+ 	default:
+-		dprintk ("%s: invalid bandwidth\n",__FUNCTION__);
++		dprintk ("%s: invalid bandwidth\n",__func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -250,7 +250,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ 		cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
+ 		cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
+ 		cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
+-		dprintk("%s: Autodetecting\n",__FUNCTION__);
++		dprintk("%s: Autodetecting\n",__func__);
+ 		return 0;
+ 	}
+ 
+@@ -261,7 +261,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ 		case QAM_16: val = (val&0xe7)|0x08; break;
+ 		case QAM_64: val = (val&0xe7)|0x10; break;
+ 		default:
+-			dprintk ("%s: invalid constellation\n",__FUNCTION__);
++			dprintk ("%s: invalid constellation\n",__func__);
+ 			return -EINVAL;
+ 	}
+ 	switch(p->u.ofdm.hierarchy_information) {
+@@ -270,7 +270,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ 		case    HIERARCHY_2: val = (val&0xf8)|2; break;
+ 		case    HIERARCHY_4: val = (val&0xf8)|3; break;
+ 		default:
+-			dprintk ("%s: invalid hierarchy\n",__FUNCTION__);
++			dprintk ("%s: invalid hierarchy\n",__func__);
+ 			return -EINVAL;
+ 	}
+ 	cx22702_writereg (state, 0x06, val);
+@@ -284,7 +284,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ 		case FEC_5_6: val = (val&0xc7)|0x18; break;
+ 		case FEC_7_8: val = (val&0xc7)|0x20; break;
+ 		default:
+-			dprintk ("%s: invalid code_rate_HP\n",__FUNCTION__);
++			dprintk ("%s: invalid code_rate_HP\n",__func__);
+ 			return -EINVAL;
+ 	}
+ 	switch(p->u.ofdm.code_rate_LP) {
+@@ -295,7 +295,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ 		case FEC_5_6: val = (val&0xf8)|3; break;
+ 		case FEC_7_8: val = (val&0xf8)|4; break;
+ 		default:
+-			dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__);
++			dprintk ("%s: invalid code_rate_LP\n",__func__);
+ 			return -EINVAL;
+ 	}
+ 	cx22702_writereg (state, 0x07, val);
+@@ -307,14 +307,14 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ 		case  GUARD_INTERVAL_1_8: val = (val&0xf3)|0x08; break;
+ 		case  GUARD_INTERVAL_1_4: val = (val&0xf3)|0x0c; break;
+ 		default:
+-			dprintk ("%s: invalid guard_interval\n",__FUNCTION__);
++			dprintk ("%s: invalid guard_interval\n",__func__);
+ 			return -EINVAL;
+ 	}
+ 	switch(p->u.ofdm.transmission_mode) {
+ 		case TRANSMISSION_MODE_2K: val = (val&0xfc); break;
+ 		case TRANSMISSION_MODE_8K: val = (val&0xfc)|1; break;
+ 		default:
+-			dprintk ("%s: invalid transmission_mode\n",__FUNCTION__);
++			dprintk ("%s: invalid transmission_mode\n",__func__);
+ 			return -EINVAL;
+ 	}
+ 	cx22702_writereg(state, 0x08, val);
+@@ -360,7 +360,7 @@ static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 	reg23 = cx22702_readreg (state, 0x23);
+ 
+ 	dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
+-		,__FUNCTION__,reg0A,reg23);
++		,__func__,reg0A,reg23);
+ 
+ 	if(reg0A & 0x10) {
+ 		*status |= FE_HAS_LOCK;
+diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h
+index 9cd64da..8af766a 100644
+--- a/drivers/media/dvb/frontends/cx22702.h
++++ b/drivers/media/dvb/frontends/cx22702.h
+@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
+ static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_CX22702
+diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
+index b03d828..87ae29d 100644
+--- a/drivers/media/dvb/frontends/cx24110.c
++++ b/drivers/media/dvb/frontends/cx24110.c
+@@ -121,7 +121,7 @@ static int cx24110_writereg (struct cx24110_state* state, int reg, int data)
+ 
+ 	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ 		dprintk ("%s: writereg error (err == %i, reg == 0x%02x,"
+-			 " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
++			 " data == 0x%02x)\n", __func__, err, reg, data);
+ 		return -EREMOTEIO;
+ 	}
+ 
+@@ -247,7 +247,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
+ 	static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
+ 	int i;
+ 
+-	dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
++	dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate);
+ 	if (srate>90999000UL/2)
+ 		srate=90999000UL/2;
+ 	if (srate<500000)
+@@ -358,7 +358,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
+ /* fixme (low): error handling */
+ 	int i;
+ 
+-	dprintk("%s: init chip\n", __FUNCTION__);
++	dprintk("%s: init chip\n", __func__);
+ 
+ 	for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
+ 		cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
+diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h
+index 0ca3af4..1792adb 100644
+--- a/drivers/media/dvb/frontends/cx24110.h
++++ b/drivers/media/dvb/frontends/cx24110.h
+@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+ static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+ 						  struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_CX24110
+diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h
+new file mode 100644
+index 0000000..5ab3dd1
+--- /dev/null
++++ b/drivers/media/dvb/frontends/cx24113.h
+@@ -0,0 +1,48 @@
++/*
++ *  Driver for Conexant CX24113/CX24128 Tuner (Satelite)
++ *
++ *  Copyright (C) 2007-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef CX24113_H
++#define CX24113_H
++
++struct dvb_frontend;
++
++struct cx24113_config {
++	u8 i2c_addr; /* 0x14 or 0x54 */
++
++	u32 xtal_khz;
++};
++
++/* TODO: #if defined(CONFIG_DVB_TUNER_CX24113) || \
++ * (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) */
++
++static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
++	const struct cx24113_config *config, struct i2c_adapter *i2c)
++{
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++	return NULL;
++}
++
++static inline void cx24113_agc_callback(struct dvb_frontend *fe)
++{
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++}
++
++#endif /* CX24113_H */
+diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
+index d74fdbd..7f68d78 100644
+--- a/drivers/media/dvb/frontends/cx24123.c
++++ b/drivers/media/dvb/frontends/cx24123.c
+@@ -1,24 +1,26 @@
+ /*
+-    Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+-
+-    Copyright (C) 2005 Steven Toth <stoth at hauppauge.com>
+-
+-    Support for KWorld DVB-S 100 by Vadim Catana <skystar at moldova.cc>
+-
+-    This program is free software; you can redistribute it and/or modify
+-    it under the terms of the GNU General Public License as published by
+-    the Free Software Foundation; either version 2 of the License, or
+-    (at your option) any later version.
+-
+-    This program is distributed in the hope that it will be useful,
+-    but WITHOUT ANY WARRANTY; without even the implied warranty of
+-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-    GNU General Public License for more details.
+-
+-    You 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.
+-*/
++ *   Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
++ *
++ *   Copyright (C) 2005 Steven Toth <stoth at hauppauge.com>
++ *
++ *   Support for KWorld DVB-S 100 by Vadim Catana <skystar at moldova.cc>
++ *
++ *   Support for CX24123/CX24113-NIM by Patrick Boettcher <pb at linuxtv.org>
++ *
++ *   This program is free software; you can redistribute it and/or
++ *   modify it under the terms of the GNU General Public License as
++ *   published by the Free Software Foundation; either version 2 of
++ *   the License, or (at your option) any later version.
++ *
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ *   General Public License for more details.
++ *
++ *   You should have received a copy of the GNU General Public License
++ *   along with this program; if not, write to the Free Software
++ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+ 
+ #include <linux/slab.h>
+ #include <linux/kernel.h>
+@@ -32,9 +34,16 @@
+ 
+ static int force_band;
+ static int debug;
++
++#define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0)
++#define err(args...)  do { printk(KERN_ERR  "CX24123: " args); } while (0)
++
+ #define dprintk(args...) \
+ 	do { \
+-		if (debug) printk (KERN_DEBUG "cx24123: " args); \
++		if (debug) { \
++			printk(KERN_DEBUG "CX24123: %s: ", __func__); \
++			printk(args); \
++		} \
+ 	} while (0)
+ 
+ struct cx24123_state
+@@ -51,6 +60,10 @@ struct cx24123_state
+ 	u32 pllarg;
+ 	u32 FILTune;
+ 
++	struct i2c_adapter tuner_i2c_adapter;
++
++	u8 demod_rev;
++
+ 	/* The Demod/Tuner can't easily provide these, we cache them */
+ 	u32 currentfreq;
+ 	u32 currentsymbolrate;
+@@ -225,48 +238,52 @@ static struct {
+ 	{0x67, 0x83}, /* Non-DCII symbol clock */
+ };
+ 
+-static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
++static int cx24123_i2c_writereg(struct cx24123_state *state,
++	u8 i2c_addr, int reg, int data)
+ {
+ 	u8 buf[] = { reg, data };
+-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
++	struct i2c_msg msg = {
++		.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
++	};
+ 	int err;
+ 
+-	if (debug>1)
+-		printk("cx24123: %s:  write reg 0x%02x, value 0x%02x\n",
+-						__FUNCTION__,reg, data);
++	/* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */
+ 
+ 	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ 		printk("%s: writereg error(err == %i, reg == 0x%02x,"
+-			 " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+-		return -EREMOTEIO;
++			 " data == 0x%02x)\n", __func__, err, reg, data);
++		return err;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-static int cx24123_readreg(struct cx24123_state* state, u8 reg)
++static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg)
+ {
+ 	int ret;
+-	u8 b0[] = { reg };
+-	u8 b1[] = { 0 };
++	u8 b = 0;
+ 	struct i2c_msg msg[] = {
+-		{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+-		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
++		{ .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
++		{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &b, .len = 1 }
+ 	};
+ 
+ 	ret = i2c_transfer(state->i2c, msg, 2);
+ 
+ 	if (ret != 2) {
+-		printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret);
++		err("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
+ 		return ret;
+ 	}
+ 
+-	if (debug>1)
+-		printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret);
++	/* printk(KERN_DEBUG "rd(%02x): %02x %02x\n", i2c_addr, reg, b); */
+ 
+-	return b1[0];
++	return b;
+ }
+ 
++#define cx24123_readreg(state, reg) \
++	cx24123_i2c_readreg(state, state->config->demod_address, reg)
++#define cx24123_writereg(state, reg, val) \
++	cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
++
+ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
+ {
+ 	u8 nom_reg = cx24123_readreg(state, 0x0e);
+@@ -274,17 +291,17 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers
+ 
+ 	switch (inversion) {
+ 	case INVERSION_OFF:
+-		dprintk("%s:  inversion off\n",__FUNCTION__);
++		dprintk("inversion off\n");
+ 		cx24123_writereg(state, 0x0e, nom_reg & ~0x80);
+ 		cx24123_writereg(state, 0x10, auto_reg | 0x80);
+ 		break;
+ 	case INVERSION_ON:
+-		dprintk("%s:  inversion on\n",__FUNCTION__);
++		dprintk("inversion on\n");
+ 		cx24123_writereg(state, 0x0e, nom_reg | 0x80);
+ 		cx24123_writereg(state, 0x10, auto_reg | 0x80);
+ 		break;
+ 	case INVERSION_AUTO:
+-		dprintk("%s:  inversion auto\n",__FUNCTION__);
++		dprintk("inversion auto\n");
+ 		cx24123_writereg(state, 0x10, auto_reg & ~0x80);
+ 		break;
+ 	default:
+@@ -301,10 +318,10 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers
+ 	val = cx24123_readreg(state, 0x1b) >> 7;
+ 
+ 	if (val == 0) {
+-		dprintk("%s:  read inversion off\n",__FUNCTION__);
++		dprintk("read inversion off\n");
+ 		*inversion = INVERSION_OFF;
+ 	} else {
+-		dprintk("%s:  read inversion on\n",__FUNCTION__);
++		dprintk("read inversion on\n");
+ 		*inversion = INVERSION_ON;
+ 	}
+ 
+@@ -326,42 +343,42 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+ 
+ 	switch (fec) {
+ 	case FEC_1_2:
+-		dprintk("%s:  set FEC to 1/2\n",__FUNCTION__);
++		dprintk("set FEC to 1/2\n");
+ 		cx24123_writereg(state, 0x0e, nom_reg | 0x01);
+ 		cx24123_writereg(state, 0x0f, 0x02);
+ 		break;
+ 	case FEC_2_3:
+-		dprintk("%s:  set FEC to 2/3\n",__FUNCTION__);
++		dprintk("set FEC to 2/3\n");
+ 		cx24123_writereg(state, 0x0e, nom_reg | 0x02);
+ 		cx24123_writereg(state, 0x0f, 0x04);
+ 		break;
+ 	case FEC_3_4:
+-		dprintk("%s:  set FEC to 3/4\n",__FUNCTION__);
++		dprintk("set FEC to 3/4\n");
+ 		cx24123_writereg(state, 0x0e, nom_reg | 0x03);
+ 		cx24123_writereg(state, 0x0f, 0x08);
+ 		break;
+ 	case FEC_4_5:
+-		dprintk("%s:  set FEC to 4/5\n",__FUNCTION__);
++		dprintk("set FEC to 4/5\n");
+ 		cx24123_writereg(state, 0x0e, nom_reg | 0x04);
+ 		cx24123_writereg(state, 0x0f, 0x10);
+ 		break;
+ 	case FEC_5_6:
+-		dprintk("%s:  set FEC to 5/6\n",__FUNCTION__);
++		dprintk("set FEC to 5/6\n");
+ 		cx24123_writereg(state, 0x0e, nom_reg | 0x05);
+ 		cx24123_writereg(state, 0x0f, 0x20);
+ 		break;
+ 	case FEC_6_7:
+-		dprintk("%s:  set FEC to 6/7\n",__FUNCTION__);
++		dprintk("set FEC to 6/7\n");
+ 		cx24123_writereg(state, 0x0e, nom_reg | 0x06);
+ 		cx24123_writereg(state, 0x0f, 0x40);
+ 		break;
+ 	case FEC_7_8:
+-		dprintk("%s:  set FEC to 7/8\n",__FUNCTION__);
++		dprintk("set FEC to 7/8\n");
+ 		cx24123_writereg(state, 0x0e, nom_reg | 0x07);
+ 		cx24123_writereg(state, 0x0f, 0x80);
+ 		break;
+ 	case FEC_AUTO:
+-		dprintk("%s:  set FEC to auto\n",__FUNCTION__);
++		dprintk("set FEC to auto\n");
+ 		cx24123_writereg(state, 0x0f, 0xfe);
+ 		break;
+ 	default:
+@@ -490,7 +507,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
+ 	tmp = cx24123_readreg(state, 0x0c) & ~0xe0;
+ 	cx24123_writereg(state, 0x0c, tmp | sample_gain << 5);
+ 
+-	dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain);
++	dprintk("srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n",
++		srate, ratio, sample_rate, sample_gain);
+ 
+ 	return 0;
+ }
+@@ -570,7 +588,7 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
+ 	struct cx24123_state *state = fe->demodulator_priv;
+ 	unsigned long timeout;
+ 
+-	dprintk("%s:  pll writereg called, data=0x%08x\n",__FUNCTION__,data);
++	dprintk("pll writereg called, data=0x%08x\n", data);
+ 
+ 	/* align the 21 bytes into to bit23 boundary */
+ 	data = data << 3;
+@@ -583,7 +601,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
+ 	cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
+ 	while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ 		if (time_after(jiffies, timeout)) {
+-			printk("%s:  demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
++			err("%s:  demodulator is not responding, "\
++				"possibly hung, aborting.\n", __func__);
+ 			return -EREMOTEIO;
+ 		}
+ 		msleep(10);
+@@ -594,7 +613,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
+ 	cx24123_writereg(state, 0x22, (data>>8) & 0xff );
+ 	while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ 		if (time_after(jiffies, timeout)) {
+-			printk("%s:  demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
++			err("%s:  demodulator is not responding, "\
++				"possibly hung, aborting.\n", __func__);
+ 			return -EREMOTEIO;
+ 		}
+ 		msleep(10);
+@@ -605,7 +625,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
+ 	cx24123_writereg(state, 0x22, (data) & 0xff );
+ 	while ((cx24123_readreg(state, 0x20) & 0x80)) {
+ 		if (time_after(jiffies, timeout)) {
+-			printk("%s:  demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
++			err("%s:  demodulator is not responding," \
++				"possibly hung, aborting.\n", __func__);
+ 			return -EREMOTEIO;
+ 		}
+ 		msleep(10);
+@@ -626,7 +647,7 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
+ 	dprintk("frequency=%i\n", p->frequency);
+ 
+ 	if (cx24123_pll_calculate(fe, p) != 0) {
+-		printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
++		err("%s: cx24123_pll_calcutate failed\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -643,18 +664,38 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
+ 	cx24123_writereg(state, 0x27, state->FILTune >> 2);
+ 	cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3));
+ 
+-	dprintk("%s:  pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg,
+-			state->bandselectarg,state->pllarg);
++	dprintk("pll tune VCA=%d, band=%d, pll=%d\n", state->VCAarg,
++			state->bandselectarg, state->pllarg);
+ 
+ 	return 0;
+ }
+ 
++
++/*
++ * 0x23:
++ *    [7:7] = BTI enabled
++ *    [6:6] = I2C repeater enabled
++ *    [5:5] = I2C repeater start
++ *    [0:0] = BTI start
++ */
++
++/* mode == 1 -> i2c-repeater, 0 -> bti */
++static int cx24123_repeater_mode(struct cx24123_state *state, u8 mode, u8 start)
++{
++	u8 r = cx24123_readreg(state, 0x23) & 0x1e;
++	if (mode)
++		r |= (1 << 6) | (start << 5);
++	else
++		r |= (1 << 7) | (start);
++	return cx24123_writereg(state, 0x23, r);
++}
++
+ static int cx24123_initfe(struct dvb_frontend* fe)
+ {
+ 	struct cx24123_state *state = fe->demodulator_priv;
+ 	int i;
+ 
+-	dprintk("%s:  init frontend\n",__FUNCTION__);
++	dprintk("init frontend\n");
+ 
+ 	/* Configure the demod to a good set of defaults */
+ 	for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
+@@ -664,6 +705,9 @@ static int cx24123_initfe(struct dvb_frontend* fe)
+ 	if(state->config->lnb_polarity)
+ 		cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
+ 
++	if (state->config->dont_use_pll)
++	cx24123_repeater_mode(state, 1, 0);
++
+ 	return 0;
+ }
+ 
+@@ -676,10 +720,10 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
+ 
+ 	switch (voltage) {
+ 	case SEC_VOLTAGE_13:
+-		dprintk("%s: setting voltage 13V\n", __FUNCTION__);
++		dprintk("setting voltage 13V\n");
+ 		return cx24123_writereg(state, 0x29, val & 0x7f);
+ 	case SEC_VOLTAGE_18:
+-		dprintk("%s: setting voltage 18V\n", __FUNCTION__);
++		dprintk("setting voltage 18V\n");
+ 		return cx24123_writereg(state, 0x29, val | 0x80);
+ 	case SEC_VOLTAGE_OFF:
+ 		/* already handled in cx88-dvb */
+@@ -697,7 +741,8 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
+ 	unsigned long timeout = jiffies + msecs_to_jiffies(200);
+ 	while (!(cx24123_readreg(state, 0x29) & 0x40)) {
+ 		if(time_after(jiffies, timeout)) {
+-			printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
++			err("%s: diseqc queue not ready, " \
++				"command may be lost.\n", __func__);
+ 			break;
+ 		}
+ 		msleep(10);
+@@ -709,7 +754,7 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
+ 	struct cx24123_state *state = fe->demodulator_priv;
+ 	int i, val, tone;
+ 
+-	dprintk("%s:\n",__FUNCTION__);
++	dprintk("\n");
+ 
+ 	/* stop continuous tone if enabled */
+ 	tone = cx24123_readreg(state, 0x29);
+@@ -744,7 +789,7 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
+ 	struct cx24123_state *state = fe->demodulator_priv;
+ 	int val, tone;
+ 
+-	dprintk("%s:\n", __FUNCTION__);
++	dprintk("\n");
+ 
+ 	/* stop continuous tone if enabled */
+ 	tone = cx24123_readreg(state, 0x29);
+@@ -778,13 +823,21 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
+ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ {
+ 	struct cx24123_state *state = fe->demodulator_priv;
+-
+ 	int sync = cx24123_readreg(state, 0x14);
+-	int lock = cx24123_readreg(state, 0x20);
+ 
+ 	*status = 0;
+-	if (lock & 0x01)
+-		*status |= FE_HAS_SIGNAL;
++	if (state->config->dont_use_pll) {
++		u32 tun_status = 0;
++		if (fe->ops.tuner_ops.get_status)
++			fe->ops.tuner_ops.get_status(fe, &tun_status);
++		if (tun_status & TUNER_STATUS_LOCKED)
++			*status |= FE_HAS_SIGNAL;
++	} else {
++		int lock = cx24123_readreg(state, 0x20);
++		if (lock & 0x01)
++			*status |= FE_HAS_SIGNAL;
++	}
++
+ 	if (sync & 0x02)
+ 		*status |= FE_HAS_CARRIER;	/* Phase locked */
+ 	if (sync & 0x04)
+@@ -803,7 +856,7 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+  * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
+  * is available, so this value doubles up to satisfy both measurements
+  */
+-static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
++static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber)
+ {
+ 	struct cx24123_state *state = fe->demodulator_priv;
+ 
+@@ -813,23 +866,24 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
+ 		(cx24123_readreg(state, 0x1d) << 8 |
+ 		 cx24123_readreg(state, 0x1e));
+ 
+-	dprintk("%s:  BER = %d\n",__FUNCTION__,*ber);
++	dprintk("BER = %d\n", *ber);
+ 
+ 	return 0;
+ }
+ 
+-static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
++static int cx24123_read_signal_strength(struct dvb_frontend *fe,
++	u16 *signal_strength)
+ {
+ 	struct cx24123_state *state = fe->demodulator_priv;
+ 
+ 	*signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
+ 
+-	dprintk("%s:  Signal strength = %d\n",__FUNCTION__,*signal_strength);
++	dprintk("Signal strength = %d\n", *signal_strength);
+ 
+ 	return 0;
+ }
+ 
+-static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
++static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr)
+ {
+ 	struct cx24123_state *state = fe->demodulator_priv;
+ 
+@@ -838,16 +892,17 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
+ 	*snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
+ 			 (u16)cx24123_readreg(state, 0x19));
+ 
+-	dprintk("%s:  read S/N index = %d\n",__FUNCTION__,*snr);
++	dprintk("read S/N index = %d\n", *snr);
+ 
+ 	return 0;
+ }
+ 
+-static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
++static int cx24123_set_frontend(struct dvb_frontend *fe,
++	struct dvb_frontend_parameters *p)
+ {
+ 	struct cx24123_state *state = fe->demodulator_priv;
+ 
+-	dprintk("%s:  set_frontend\n",__FUNCTION__);
++	dprintk("\n");
+ 
+ 	if (state->config->set_ts_params)
+ 		state->config->set_ts_params(fe, 0);
+@@ -858,13 +913,22 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
+ 	cx24123_set_inversion(state, p->inversion);
+ 	cx24123_set_fec(state, p->u.qpsk.fec_inner);
+ 	cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
+-	cx24123_pll_tune(fe, p);
++
++	if (!state->config->dont_use_pll)
++		cx24123_pll_tune(fe, p);
++	else if (fe->ops.tuner_ops.set_params)
++		fe->ops.tuner_ops.set_params(fe, p);
++	else
++		err("it seems I don't have a tuner...");
+ 
+ 	/* Enable automatic aquisition and reset cycle */
+ 	cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
+ 	cx24123_writereg(state, 0x00, 0x10);
+ 	cx24123_writereg(state, 0x00, 0);
+ 
++	if (state->config->agc_callback)
++		state->config->agc_callback(fe);
++
+ 	return 0;
+ }
+ 
+@@ -872,14 +936,14 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
+ {
+ 	struct cx24123_state *state = fe->demodulator_priv;
+ 
+-	dprintk("%s:  get_frontend\n",__FUNCTION__);
++	dprintk("\n");
+ 
+ 	if (cx24123_get_inversion(state, &p->inversion) != 0) {
+-		printk("%s: Failed to get inversion status\n",__FUNCTION__);
++		err("%s: Failed to get inversion status\n", __func__);
+ 		return -EREMOTEIO;
+ 	}
+ 	if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
+-		printk("%s: Failed to get fec status\n",__FUNCTION__);
++		err("%s: Failed to get fec status\n", __func__);
+ 		return -EREMOTEIO;
+ 	}
+ 	p->frequency = state->currentfreq;
+@@ -900,13 +964,13 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+ 
+ 	switch (tone) {
+ 	case SEC_TONE_ON:
+-		dprintk("%s: setting tone on\n", __FUNCTION__);
++		dprintk("setting tone on\n");
+ 		return cx24123_writereg(state, 0x29, val | 0x10);
+ 	case SEC_TONE_OFF:
+-		dprintk("%s: setting tone off\n",__FUNCTION__);
++		dprintk("setting tone off\n");
+ 		return cx24123_writereg(state, 0x29, val & 0xef);
+ 	default:
+-		printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
++		err("CASE reached default with tone=%d\n", tone);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -939,47 +1003,86 @@ static int cx24123_get_algo(struct dvb_frontend *fe)
+ static void cx24123_release(struct dvb_frontend* fe)
+ {
+ 	struct cx24123_state* state = fe->demodulator_priv;
+-	dprintk("%s\n",__FUNCTION__);
++	dprintk("\n");
++	i2c_del_adapter(&state->tuner_i2c_adapter);
+ 	kfree(state);
+ }
+ 
++static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap,
++	struct i2c_msg msg[], int num)
++{
++	struct cx24123_state *state = i2c_get_adapdata(i2c_adap);
++	/* this repeater closes after the first stop */
++    cx24123_repeater_mode(state, 1, 1);
++	return i2c_transfer(state->i2c, msg, num);
++}
++
++static u32 cx24123_tuner_i2c_func(struct i2c_adapter *adapter)
++{
++	return I2C_FUNC_I2C;
++}
++
++static struct i2c_algorithm cx24123_tuner_i2c_algo = {
++	.master_xfer   = cx24123_tuner_i2c_tuner_xfer,
++	.functionality = cx24123_tuner_i2c_func,
++};
++
++struct i2c_adapter *
++	cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
++{
++	struct cx24123_state *state = fe->demodulator_priv;
++	return &state->tuner_i2c_adapter;
++}
++EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
++
+ static struct dvb_frontend_ops cx24123_ops;
+ 
+ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+ 				    struct i2c_adapter* i2c)
+ {
+-	struct cx24123_state* state = NULL;
+-	int ret;
+-
+-	dprintk("%s\n",__FUNCTION__);
++	struct cx24123_state *state =
++		kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
+ 
++	dprintk("\n");
+ 	/* allocate memory for the internal state */
+-	state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL);
+ 	if (state == NULL) {
+-		printk("Unable to kmalloc\n");
++		err("Unable to kmalloc\n");
+ 		goto error;
+ 	}
+ 
+ 	/* setup the state */
+ 	state->config = config;
+ 	state->i2c = i2c;
+-	state->VCAarg = 0;
+-	state->VGAarg = 0;
+-	state->bandselectarg = 0;
+-	state->pllarg = 0;
+-	state->currentfreq = 0;
+-	state->currentsymbolrate = 0;
+ 
+ 	/* check if the demod is there */
+-	ret = cx24123_readreg(state, 0x00);
+-	if ((ret != 0xd1) && (ret != 0xe1)) {
+-		printk("Version != d1 or e1\n");
++	state->demod_rev = cx24123_readreg(state, 0x00);
++	switch (state->demod_rev) {
++	case 0xe1: info("detected CX24123C\n"); break;
++	case 0xd1: info("detected CX24123\n"); break;
++	default:
++		err("wrong demod revision: %x\n", state->demod_rev);
+ 		goto error;
+ 	}
+ 
+ 	/* create dvb_frontend */
+ 	memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+ 	state->frontend.demodulator_priv = state;
++
++    /* create tuner i2c adapter */
++    if (config->dont_use_pll)
++	cx24123_repeater_mode(state, 1, 0);
++
++	strncpy(state->tuner_i2c_adapter.name,
++		"CX24123 tuner I2C bus", I2C_NAME_SIZE);
++	state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
++	state->tuner_i2c_adapter.algo      = &cx24123_tuner_i2c_algo;
++	state->tuner_i2c_adapter.algo_data = NULL;
++	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
++	if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
++	err("tuner i2c bus could not be initialized\n");
++		goto error;
++	}
++
+ 	return &state->frontend;
+ 
+ error:
+@@ -1029,7 +1132,8 @@ MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+ module_param(force_band, int, 0644);
+ MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
+ 
+-MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
++MODULE_DESCRIPTION("DVB Frontend module for Conexant " \
++	"CX24123/CX24109/CX24113 hardware");
+ MODULE_AUTHOR("Steven Toth");
+ MODULE_LICENSE("GPL");
+ 
+diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
+index 84f9e4f..81ebc3d 100644
+--- a/drivers/media/dvb/frontends/cx24123.h
++++ b/drivers/media/dvb/frontends/cx24123.h
+@@ -33,16 +33,27 @@ struct cx24123_config
+ 
+ 	/* 0 = LNB voltage normal, 1 = LNB voltage inverted */
+ 	int lnb_polarity;
++
++	/* this device has another tuner */
++	u8 dont_use_pll;
++	void (*agc_callback) (struct dvb_frontend *);
+ };
+ 
+ #if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE))
+-extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+-					   struct i2c_adapter* i2c);
++extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
++					   struct i2c_adapter *i2c);
++extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
+ #else
+-static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+-						  struct i2c_adapter* i2c)
++static inline struct dvb_frontend *cx24123_attach(
++	const struct cx24123_config *config, struct i2c_adapter *i2c)
++{
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++	return NULL;
++}
++static struct i2c_adapter *
++	cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_CX24123
+diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
+index a6d3854..ba91735 100644
+--- a/drivers/media/dvb/frontends/dib3000.h
++++ b/drivers/media/dvb/frontends/dib3000.h
+@@ -48,7 +48,7 @@ extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config
+ static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
+ 					     struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_DIB3000MB
+diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h
+index 72d4757..4142ed7 100644
+--- a/drivers/media/dvb/frontends/dib3000mc.h
++++ b/drivers/media/dvb/frontends/dib3000mc.h
+@@ -44,7 +44,7 @@ extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i
+ #else
+ static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_DIB3000MC
+diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
+index 47c23e2..1a0142e 100644
+--- a/drivers/media/dvb/frontends/dib7000p.c
++++ b/drivers/media/dvb/frontends/dib7000p.c
+@@ -1168,7 +1168,7 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
+ 	ret = dib7000p_tune(fe, fep);
+ 
+ 	/* make this a config parameter */
+-	dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
++	dib7000p_set_output_mode(state, state->cfg.output_mode);
+     return ret;
+ }
+ 
+@@ -1330,6 +1330,12 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
+ 	st->gpio_val = cfg->gpio_val;
+ 	st->gpio_dir = cfg->gpio_dir;
+ 
++	/* Ensure the output mode remains at the previous default if it's
++	 * not specifically set by the caller.
++	 */
++	if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL)
++		st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
++
+ 	demod                   = &st->demod;
+ 	demod->demodulator_priv = st;
+ 	memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
+diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
+index eefcac8..081bd81 100644
+--- a/drivers/media/dvb/frontends/dib7000p.h
++++ b/drivers/media/dvb/frontends/dib7000p.h
+@@ -31,6 +31,8 @@ struct dib7000p_config {
+ 	u8 spur_protect;
+ 
+ 	int (*agc_control) (struct dvb_frontend *, u8 before);
++
++	u8 output_mode;
+ };
+ 
+ #define DEFAULT_DIB7000P_I2C_ADDRESS 18
+diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
+index 8c8d734..a054894 100644
+--- a/drivers/media/dvb/frontends/dvb-pll.c
++++ b/drivers/media/dvb/frontends/dvb-pll.c
+@@ -44,14 +44,10 @@ struct dvb_pll_priv {
+ 
+ static unsigned int dvb_pll_devcount;
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+ 
+-static unsigned int input[DVB_PLL_MAX] = { [ 0 ... (DVB_PLL_MAX-1) ] = 0 };
+-module_param_array(input, int, NULL, 0644);
+-MODULE_PARM_DESC(input,"specify rf input choice, 0 for autoselect (default)");
+-
+ static unsigned int id[DVB_PLL_MAX] =
+ 	{ [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
+ module_param_array(id, int, NULL, 0644);
+@@ -80,23 +76,6 @@ struct dvb_pll_desc {
+ /* ----------------------------------------------------------- */
+ /* descriptions                                                */
+ 
+-/* Set AGC TOP value to 103 dBuV:
+-	0x80 = Control Byte
+-	0x40 = 250 uA charge pump (irrelevant)
+-	0x18 = Aux Byte to follow
+-	0x06 = 64.5 kHz divider (irrelevant)
+-	0x01 = Disable Vt (aka sleep)
+-
+-	0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
+-	0x50 = AGC Take over point = 103 dBuV */
+-static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
+-
+-/*	0x04 = 166.67 kHz divider
+-
+-	0x80 = AGC Time constant 50ms Iagc = 9 uA
+-	0x20 = AGC Take over point = 112 dBuV */
+-static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
+-
+ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
+ 	.name  = "Thomson dtt7579",
+ 	.min   = 177000000,
+@@ -112,19 +91,6 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
+ 	},
+ };
+ 
+-static struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
+-	.name  = "Thomson dtt7610",
+-	.min   =  44000000,
+-	.max   = 958000000,
+-	.iffreq= 44000000,
+-	.count = 3,
+-	.entries = {
+-		{ 157250000, 62500, 0x8e, 0x39 },
+-		{ 454000000, 62500, 0x8e, 0x3a },
+-		{ 999999999, 62500, 0x8e, 0x3c },
+-	},
+-};
+-
+ static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf,
+ 			       const struct dvb_frontend_parameters *params)
+ {
+@@ -165,34 +131,6 @@ static struct dvb_pll_desc dvb_pll_lg_z201 = {
+ 	},
+ };
+ 
+-static struct dvb_pll_desc dvb_pll_microtune_4042 = {
+-	.name  = "Microtune 4042 FI5",
+-	.min   =  57000000,
+-	.max   = 858000000,
+-	.iffreq= 44000000,
+-	.count = 3,
+-	.entries = {
+-		{ 162000000, 62500, 0x8e, 0xa1 },
+-		{ 457000000, 62500, 0x8e, 0x91 },
+-		{ 999999999, 62500, 0x8e, 0x31 },
+-	},
+-};
+-
+-static struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
+-	/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+-	.name  = "Thomson dtt761x",
+-	.min   =  57000000,
+-	.max   = 863000000,
+-	.iffreq= 44000000,
+-	.count = 3,
+-	.initdata = tua603x_agc103,
+-	.entries = {
+-		{ 147000000, 62500, 0x8e, 0x39 },
+-		{ 417000000, 62500, 0x8e, 0x3a },
+-		{ 999999999, 62500, 0x8e, 0x3c },
+-	},
+-};
+-
+ static struct dvb_pll_desc dvb_pll_unknown_1 = {
+ 	.name  = "unknown 1", /* used by dntv live dvb-t */
+ 	.min   = 174000000,
+@@ -301,54 +239,6 @@ static struct dvb_pll_desc dvb_pll_tua6034 = {
+ 	},
+ };
+ 
+-/* Infineon TUA6034
+- * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
+- */
+-static struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
+-	.name  = "LG TDVS-H06xF",
+-	.min   =  54000000,
+-	.max   = 863000000,
+-	.iffreq= 44000000,
+-	.initdata = tua603x_agc103,
+-	.count = 3,
+-	.entries = {
+-		{  165000000, 62500, 0xce, 0x01 },
+-		{  450000000, 62500, 0xce, 0x02 },
+-		{  999999999, 62500, 0xce, 0x04 },
+-	},
+-};
+-
+-/* Philips FMD1216ME
+- * used in Medion Hybrid PCMCIA card and USB Box
+- */
+-static void fmd1216me_bw(struct dvb_frontend *fe, u8 *buf,
+-			 const struct dvb_frontend_parameters *params)
+-{
+-	if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
+-	    params->frequency >= 158870000)
+-		buf[3] |= 0x08;
+-}
+-
+-static struct dvb_pll_desc dvb_pll_fmd1216me = {
+-	.name = "Philips FMD1216ME",
+-	.min = 50870000,
+-	.max = 858000000,
+-	.iffreq= 36125000,
+-	.set   = fmd1216me_bw,
+-	.initdata = tua603x_agc112,
+-	.sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
+-	.count = 7,
+-	.entries = {
+-		{ 143870000, 166667, 0xbc, 0x41 },
+-		{ 158870000, 166667, 0xf4, 0x41 },
+-		{ 329870000, 166667, 0xbc, 0x42 },
+-		{ 441870000, 166667, 0xf4, 0x42 },
+-		{ 625870000, 166667, 0xbc, 0x44 },
+-		{ 803870000, 166667, 0xf4, 0x44 },
+-		{ 999999999, 166667, 0xfc, 0x44 },
+-	}
+-};
+-
+ /* ALPS TDED4
+  * used in Nebula-Cards and USB boxes
+  */
+@@ -391,55 +281,6 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = {
+ 	}
+ };
+ 
+-/* Philips TUV1236D
+- * used in ATI HDTV Wonder
+- */
+-static void tuv1236d_rf(struct dvb_frontend *fe, u8 *buf,
+-			const struct dvb_frontend_parameters *params)
+-{
+-	struct dvb_pll_priv *priv = fe->tuner_priv;
+-	unsigned int new_rf = input[priv->nr];
+-
+-	if ((new_rf == 0) || (new_rf > 2)) {
+-		switch (params->u.vsb.modulation) {
+-			case QAM_64:
+-			case QAM_256:
+-				new_rf = 1;
+-				break;
+-			case VSB_8:
+-			default:
+-				new_rf = 2;
+-		}
+-	}
+-
+-	switch (new_rf) {
+-		case 1:
+-			buf[3] |= 0x08;
+-			break;
+-		case 2:
+-			buf[3] &= ~0x08;
+-			break;
+-		default:
+-			printk(KERN_WARNING
+-			       "%s: unhandled rf input selection: %d",
+-			       __FUNCTION__, new_rf);
+-	}
+-}
+-
+-static struct dvb_pll_desc dvb_pll_tuv1236d = {
+-	.name  = "Philips TUV1236D",
+-	.min   =  54000000,
+-	.max   = 864000000,
+-	.iffreq= 44000000,
+-	.set   = tuv1236d_rf,
+-	.count = 3,
+-	.entries = {
+-		{ 157250000, 62500, 0xc6, 0x41 },
+-		{ 454000000, 62500, 0xc6, 0x42 },
+-		{ 999999999, 62500, 0xc6, 0x44 },
+-	},
+-};
+-
+ /* Samsung TBMV30111IN / TBMV30712IN1
+  * used in Air2PC ATSC - 2nd generation (nxt2002)
+  */
+@@ -476,64 +317,6 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
+ 	},
+ };
+ 
+-/*
+- * Philips TD1316 Tuner.
+- */
+-static void td1316_bw(struct dvb_frontend *fe, u8 *buf,
+-		      const struct dvb_frontend_parameters *params)
+-{
+-	u8 band;
+-
+-	/* determine band */
+-	if (params->frequency < 161000000)
+-		band = 1;
+-	else if (params->frequency < 444000000)
+-		band = 2;
+-	else
+-		band = 4;
+-
+-	buf[3] |= band;
+-
+-	/* setup PLL filter */
+-	if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+-		buf[3] |= 1 << 3;
+-}
+-
+-static struct dvb_pll_desc dvb_pll_philips_td1316 = {
+-	.name  = "Philips TD1316",
+-	.min   =  87000000,
+-	.max   = 895000000,
+-	.iffreq= 36166667,
+-	.set   = td1316_bw,
+-	.count = 9,
+-	.entries = {
+-		{  93834000, 166667, 0xca, 0x60},
+-		{ 123834000, 166667, 0xca, 0xa0},
+-		{ 163834000, 166667, 0xca, 0xc0},
+-		{ 253834000, 166667, 0xca, 0x60},
+-		{ 383834000, 166667, 0xca, 0xa0},
+-		{ 443834000, 166667, 0xca, 0xc0},
+-		{ 583834000, 166667, 0xca, 0x60},
+-		{ 793834000, 166667, 0xca, 0xa0},
+-		{ 858834000, 166667, 0xca, 0xe0},
+-	},
+-};
+-
+-/* FE6600 used on DViCO Hybrid */
+-static struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
+-	.name = "Thomson FE6600",
+-	.min =  44250000,
+-	.max = 858000000,
+-	.iffreq= 36125000,
+-	.count = 4,
+-	.entries = {
+-		{ 250000000, 166667, 0xb4, 0x12 },
+-		{ 455000000, 166667, 0xfe, 0x11 },
+-		{ 775500000, 166667, 0xbc, 0x18 },
+-		{ 999999999, 166667, 0xf4, 0x18 },
+-	}
+-};
+-
+ static void opera1_bw(struct dvb_frontend *fe, u8 *buf,
+ 		      const struct dvb_frontend_parameters *params)
+ {
+@@ -560,50 +343,23 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
+ 	}
+ };
+ 
+-/* Philips FCV1236D
+- */
+-static struct dvb_pll_desc dvb_pll_fcv1236d = {
+-/* Bit_0: RF Input select
+- * Bit_1: 0=digital, 1=analog
+- */
+-	.name  = "Philips FCV1236D",
+-	.min   =  53000000,
+-	.max   = 803000000,
+-	.iffreq= 44000000,
+-	.count = 3,
+-	.entries = {
+-		{ 159000000, 62500, 0x8e, 0xa0 },
+-		{ 453000000, 62500, 0x8e, 0x90 },
+-		{ 999999999, 62500, 0x8e, 0x30 },
+-	},
+-};
+-
+ /* ----------------------------------------------------------- */
+ 
+ static struct dvb_pll_desc *pll_list[] = {
+ 	[DVB_PLL_UNDEFINED]              = NULL,
+ 	[DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
+ 	[DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
+-	[DVB_PLL_THOMSON_DTT7610]        = &dvb_pll_thomson_dtt7610,
+ 	[DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
+-	[DVB_PLL_MICROTUNE_4042]         = &dvb_pll_microtune_4042,
+-	[DVB_PLL_THOMSON_DTT761X]        = &dvb_pll_thomson_dtt761x,
+ 	[DVB_PLL_UNKNOWN_1]              = &dvb_pll_unknown_1,
+ 	[DVB_PLL_TUA6010XS]              = &dvb_pll_tua6010xs,
+ 	[DVB_PLL_ENV57H1XD5]             = &dvb_pll_env57h1xd5,
+ 	[DVB_PLL_TUA6034]                = &dvb_pll_tua6034,
+-	[DVB_PLL_LG_TDVS_H06XF]          = &dvb_pll_lg_tdvs_h06xf,
+ 	[DVB_PLL_TDA665X]                = &dvb_pll_tda665x,
+-	[DVB_PLL_FMD1216ME]              = &dvb_pll_fmd1216me,
+ 	[DVB_PLL_TDED4]                  = &dvb_pll_tded4,
+-	[DVB_PLL_TUV1236D]               = &dvb_pll_tuv1236d,
+ 	[DVB_PLL_TDHU2]                  = &dvb_pll_tdhu2,
+ 	[DVB_PLL_SAMSUNG_TBMV]           = &dvb_pll_samsung_tbmv,
+ 	[DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
+-	[DVB_PLL_PHILIPS_TD1316]         = &dvb_pll_philips_td1316,
+-	[DVB_PLL_THOMSON_FE6600]         = &dvb_pll_thomson_fe6600,
+ 	[DVB_PLL_OPERA1]                 = &dvb_pll_opera1,
+-	[DVB_PLL_FCV1236D]               = &dvb_pll_fcv1236d,
+ };
+ 
+ /* ----------------------------------------------------------- */
+@@ -849,20 +605,6 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
+ 		       id[priv->nr] == pll_desc_id ?
+ 				"insmod option" : "autodetected");
+ 	}
+-	if ((debug) || (input[priv->nr] > 0)) {
+-		printk("dvb-pll[%d]", priv->nr);
+-		if (i2c != NULL)
+-			printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
+-		printk(": tuner rf input will be ");
+-		switch (input[priv->nr]) {
+-		case 0:
+-			printk("autoselected\n");
+-			break;
+-		default:
+-			printk("set to input %d (insmod option)\n",
+-			       input[priv->nr]);
+-		}
+-	}
+ 
+ 	return fe;
+ }
+diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
+index e93a810..872ca29 100644
+--- a/drivers/media/dvb/frontends/dvb-pll.h
++++ b/drivers/media/dvb/frontends/dvb-pll.h
+@@ -11,26 +11,17 @@
+ #define DVB_PLL_UNDEFINED               0
+ #define DVB_PLL_THOMSON_DTT7579         1
+ #define DVB_PLL_THOMSON_DTT759X         2
+-#define DVB_PLL_THOMSON_DTT7610         3
+-#define DVB_PLL_LG_Z201                 4
+-#define DVB_PLL_MICROTUNE_4042          5
+-#define DVB_PLL_THOMSON_DTT761X         6
+-#define DVB_PLL_UNKNOWN_1               7
+-#define DVB_PLL_TUA6010XS               8
+-#define DVB_PLL_ENV57H1XD5              9
+-#define DVB_PLL_TUA6034                10
+-#define DVB_PLL_LG_TDVS_H06XF          11
+-#define DVB_PLL_TDA665X                12
+-#define DVB_PLL_FMD1216ME              13
+-#define DVB_PLL_TDED4                  14
+-#define DVB_PLL_TUV1236D               15
+-#define DVB_PLL_TDHU2                  16
+-#define DVB_PLL_SAMSUNG_TBMV           17
+-#define DVB_PLL_PHILIPS_SD1878_TDA8261 18
+-#define DVB_PLL_PHILIPS_TD1316         19
+-#define DVB_PLL_THOMSON_FE6600         20
+-#define DVB_PLL_OPERA1                 21
+-#define DVB_PLL_FCV1236D               22
++#define DVB_PLL_LG_Z201                 3
++#define DVB_PLL_UNKNOWN_1               4
++#define DVB_PLL_TUA6010XS               5
++#define DVB_PLL_ENV57H1XD5              6
++#define DVB_PLL_TUA6034                 7
++#define DVB_PLL_TDA665X                 8
++#define DVB_PLL_TDED4                   9
++#define DVB_PLL_TDHU2                  10
++#define DVB_PLL_SAMSUNG_TBMV           11
++#define DVB_PLL_PHILIPS_SD1878_TDA8261 12
++#define DVB_PLL_OPERA1                 13
+ 
+ /**
+  * Attach a dvb-pll to the supplied frontend structure.
+@@ -52,7 +43,7 @@ static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
+ 					   struct i2c_adapter *i2c,
+ 					   unsigned int pll_desc_id)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif
+diff --git a/drivers/media/dvb/frontends/isl6405.c b/drivers/media/dvb/frontends/isl6405.c
+new file mode 100644
+index 0000000..33d33f4
+--- /dev/null
++++ b/drivers/media/dvb/frontends/isl6405.c
+@@ -0,0 +1,164 @@
++/*
++ * isl6405.c - driver for dual lnb supply and control ic ISL6405
++ *
++ * Copyright (C) 2008 Hartmut Hackmann
++ * Copyright (C) 2006 Oliver Endriss
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
++ *
++ *
++ * the project's page is at http://www.linuxtv.org
++ */
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++
++#include "dvb_frontend.h"
++#include "isl6405.h"
++
++struct isl6405 {
++	u8			config;
++	u8			override_or;
++	u8			override_and;
++	struct i2c_adapter	*i2c;
++	u8			i2c_addr;
++};
++
++static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
++{
++	struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
++	struct i2c_msg msg = {	.addr = isl6405->i2c_addr, .flags = 0,
++				.buf = &isl6405->config,
++				.len = sizeof(isl6405->config) };
++
++	if (isl6405->override_or & 0x80) {
++		isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2);
++		switch (voltage) {
++		case SEC_VOLTAGE_OFF:
++			break;
++		case SEC_VOLTAGE_13:
++			isl6405->config |= ISL6405_EN2;
++			break;
++		case SEC_VOLTAGE_18:
++			isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2);
++			break;
++		default:
++			return -EINVAL;
++		}
++	} else {
++		isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1);
++		switch (voltage) {
++		case SEC_VOLTAGE_OFF:
++			break;
++		case SEC_VOLTAGE_13:
++			isl6405->config |= ISL6405_EN1;
++			break;
++		case SEC_VOLTAGE_18:
++			isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1);
++			break;
++		default:
++			return -EINVAL;
++		};
++	}
++	isl6405->config |= isl6405->override_or;
++	isl6405->config &= isl6405->override_and;
++
++	return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
++}
++
++static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
++{
++	struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
++	struct i2c_msg msg = {	.addr = isl6405->i2c_addr, .flags = 0,
++				.buf = &isl6405->config,
++				.len = sizeof(isl6405->config) };
++
++	if (isl6405->override_or & 0x80) {
++		if (arg)
++			isl6405->config |= ISL6405_LLC2;
++		else
++			isl6405->config &= ~ISL6405_LLC2;
++	} else {
++		if (arg)
++			isl6405->config |= ISL6405_LLC1;
++		else
++			isl6405->config &= ~ISL6405_LLC1;
++	}
++	isl6405->config |= isl6405->override_or;
++	isl6405->config &= isl6405->override_and;
++
++	return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
++}
++
++static void isl6405_release(struct dvb_frontend *fe)
++{
++	/* power off */
++	isl6405_set_voltage(fe, SEC_VOLTAGE_OFF);
++
++	/* free */
++	kfree(fe->sec_priv);
++	fe->sec_priv = NULL;
++}
++
++struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
++				    u8 i2c_addr, u8 override_set, u8 override_clear)
++{
++	struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL);
++	if (!isl6405)
++		return NULL;
++
++	/* default configuration */
++	if (override_set & 0x80)
++		isl6405->config = ISL6405_ISEL2;
++	else
++		isl6405->config = ISL6405_ISEL1;
++	isl6405->i2c = i2c;
++	isl6405->i2c_addr = i2c_addr;
++	fe->sec_priv = isl6405;
++
++	/* bits which should be forced to '1' */
++	isl6405->override_or = override_set;
++
++	/* bits which should be forced to '0' */
++	isl6405->override_and = ~override_clear;
++
++	/* detect if it is present or not */
++	if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) {
++		kfree(isl6405);
++		fe->sec_priv = NULL;
++		return NULL;
++	}
++
++	/* install release callback */
++	fe->ops.release_sec = isl6405_release;
++
++	/* override frontend ops */
++	fe->ops.set_voltage = isl6405_set_voltage;
++	fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage;
++
++	return fe;
++}
++EXPORT_SYMBOL(isl6405_attach);
++
++MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405");
++MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb/frontends/isl6405.h
+new file mode 100644
+index 0000000..1c793d3
+--- /dev/null
++++ b/drivers/media/dvb/frontends/isl6405.h
+@@ -0,0 +1,74 @@
++/*
++ * isl6405.h - driver for dual lnb supply and control ic ISL6405
++ *
++ * Copyright (C) 2008 Hartmut Hackmann
++ * Copyright (C) 2006 Oliver Endriss
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
++ *
++ *
++ * the project's page is at http://www.linuxtv.org
++ */
++
++#ifndef _ISL6405_H
++#define _ISL6405_H
++
++#include <linux/dvb/frontend.h>
++
++/* system register bits */
++
++/* this bit selects register (control) 1 or 2
++   note that the bit maps are different */
++
++#define ISL6405_SR	0x80
++
++/* SR = 0 */
++#define ISL6405_OLF1	0x01
++#define ISL6405_EN1	0x02
++#define ISL6405_VSEL1	0x04
++#define ISL6405_LLC1	0x08
++#define ISL6405_ENT1	0x10
++#define ISL6405_ISEL1	0x20
++#define ISL6405_DCL	0x40
++
++/* SR = 1 */
++#define ISL6405_OLF2	0x01
++#define ISL6405_OTF	0x02
++#define ISL6405_EN2	0x04
++#define ISL6405_VSEL2	0x08
++#define ISL6405_LLC2	0x10
++#define ISL6405_ENT2	0x20
++#define ISL6405_ISEL2	0x40
++
++#if defined(CONFIG_DVB_ISL6405) || (defined(CONFIG_DVB_ISL6405_MODULE) && defined(MODULE))
++/* override_set and override_clear control which system register bits (above)
++ * to always set & clear
++ */
++extern struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
++					   u8 i2c_addr, u8 override_set, u8 override_clear);
++#else
++static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe,
++						  struct i2c_adapter *i2c, u8 i2c_addr,
++						  u8 override_set, u8 override_clear)
++{
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++	return NULL;
++}
++#endif /* CONFIG_DVB_ISL6405 */
++
++#endif
+diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h
+index ea7f78a..47e4518 100644
+--- a/drivers/media/dvb/frontends/isl6421.h
++++ b/drivers/media/dvb/frontends/isl6421.h
+@@ -47,7 +47,7 @@ extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_a
+ static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+ 						  u8 override_set, u8 override_clear)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_ISL6421
+diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c
+new file mode 100644
+index 0000000..04c562c
+--- /dev/null
++++ b/drivers/media/dvb/frontends/itd1000.c
+@@ -0,0 +1,400 @@
++/*
++ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ *
++ *  Copyright (c) 2007-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/delay.h>
++#include <linux/dvb/frontend.h>
++#include <linux/i2c.h>
++
++#include "dvb_frontend.h"
++
++#include "itd1000.h"
++#include "itd1000_priv.h"
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
++
++#define deb(args...)  do { \
++	if (debug) { \
++		printk(KERN_DEBUG   "ITD1000: " args);\
++		printk("\n"); \
++	} \
++} while (0)
++
++#define warn(args...) do { \
++	printk(KERN_WARNING "ITD1000: " args); \
++	printk("\n"); \
++} while (0)
++
++#define info(args...) do { \
++	printk(KERN_INFO    "ITD1000: " args); \
++	printk("\n"); \
++} while (0)
++
++/* don't write more than one byte with flexcop behind */
++static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 len)
++{
++	u8 buf[1+len];
++	struct i2c_msg msg = {
++		.addr = state->cfg->i2c_address, .flags = 0, .buf = buf, .len = len+1
++	};
++	buf[0] = reg;
++	memcpy(&buf[1], v, len);
++
++	/* deb("wr %02x: %02x", reg, v[0]); */
++
++	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
++		printk(KERN_WARNING "itd1000 I2C write failed\n");
++		return -EREMOTEIO;
++	}
++	return 0;
++}
++
++static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
++{
++	u8 val;
++	struct i2c_msg msg[2] = {
++		{ .addr = state->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
++		{ .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = &val, .len = 1 },
++	};
++
++	/* ugly flexcop workaround */
++	itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
++
++	if (i2c_transfer(state->i2c, msg, 2) != 2) {
++		warn("itd1000 I2C read failed");
++		return -EREMOTEIO;
++	}
++	return val;
++}
++
++static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
++{
++	int ret = itd1000_write_regs(state, r, &v, 1);
++	state->shadow[r] = v;
++	return ret;
++}
++
++
++static struct {
++	u32 symbol_rate;
++	u8  pgaext  : 4; /* PLLFH */
++	u8  bbgvmin : 4; /* BBGVMIN */
++} itd1000_lpf_pga[] = {
++	{        0, 0x8, 0x3 },
++	{  5200000, 0x8, 0x3 },
++	{ 12200000, 0x4, 0x3 },
++	{ 15400000, 0x2, 0x3 },
++	{ 19800000, 0x2, 0x3 },
++	{ 21500000, 0x2, 0x3 },
++	{ 24500000, 0x2, 0x3 },
++	{ 28400000, 0x2, 0x3 },
++	{ 33400000, 0x2, 0x3 },
++	{ 34400000, 0x1, 0x4 },
++	{ 34400000, 0x1, 0x4 },
++	{ 38400000, 0x1, 0x4 },
++	{ 38400000, 0x1, 0x4 },
++	{ 40400000, 0x1, 0x4 },
++	{ 45400000, 0x1, 0x4 },
++};
++
++static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
++{
++	u8 i;
++	u8 con1    = itd1000_read_reg(state, CON1)    & 0xfd;
++	u8 pllfh   = itd1000_read_reg(state, PLLFH)   & 0x0f;
++	u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0;
++	u8 bw      = itd1000_read_reg(state, BW)      & 0xf0;
++
++	deb("symbol_rate = %d", symbol_rate);
++
++	/* not sure what is that ? - starting to download the table */
++	itd1000_write_reg(state, CON1, con1 | (1 << 1));
++
++	for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++)
++		if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) {
++			deb("symrate: index: %d pgaext: %x, bbgvmin: %x", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
++			itd1000_write_reg(state, PLLFH,   pllfh | (itd1000_lpf_pga[i].pgaext << 4));
++			itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin));
++			itd1000_write_reg(state, BW,      bw | (i & 0x0f));
++			break;
++		}
++
++	itd1000_write_reg(state, CON1, con1 | (0 << 1));
++}
++
++static struct {
++	u8 vcorg;
++	u32 fmax_rg;
++} itd1000_vcorg[] = {
++	{  1,  920000 },
++	{  2,  971000 },
++	{  3, 1031000 },
++	{  4, 1091000 },
++	{  5, 1171000 },
++	{  6, 1281000 },
++	{  7, 1381000 },
++	{  8,  500000 },	/* this is intentional. */
++	{  9, 1451000 },
++	{ 10, 1531000 },
++	{ 11, 1631000 },
++	{ 12, 1741000 },
++	{ 13, 1891000 },
++	{ 14, 2071000 },
++	{ 15, 2250000 },
++};
++
++static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
++{
++	u8 i;
++	u8 gvbb_i2c     = itd1000_read_reg(state, GVBB_I2C) & 0xbf;
++	u8 vco_chp1_i2c = itd1000_read_reg(state, VCO_CHP1_I2C) & 0x0f;
++	u8 adcout;
++
++	/* reserved bit again (reset ?) */
++	itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6));
++
++	for (i = 0; i < ARRAY_SIZE(itd1000_vcorg); i++) {
++		if (freq_khz < itd1000_vcorg[i].fmax_rg) {
++			itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | (itd1000_vcorg[i].vcorg << 4));
++			msleep(1);
++
++			adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
++
++			deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
++
++			if (adcout > 13) {
++				if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15))
++					itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg + 1) << 4));
++			} else if (adcout < 2) {
++				if (!(itd1000_vcorg[i].vcorg == 1 || itd1000_vcorg[i].vcorg == 9))
++					itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg - 1) << 4));
++			}
++			break;
++		}
++	}
++}
++
++struct {
++	u32 freq;
++	u8 values[10]; /* RFTR, RFST1 - RFST9 */
++} itd1000_fre_values[] = {
++	{ 1075000, { 0x59, 0x1d, 0x1c, 0x17, 0x16, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++	{ 1250000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++	{ 1450000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++	{ 1650000, { 0x69, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++	{ 1750000, { 0x69, 0x1e, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++	{ 1850000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
++	{ 1900000, { 0x69, 0x1d, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
++	{ 1950000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0d, 0x0b, 0x0a } },
++	{ 2050000, { 0x69, 0x1e, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0b, 0x0a } },
++	{ 2150000, { 0x69, 0x1d, 0x1c, 0x17, 0x15, 0x14, 0x13, 0x0f, 0x0e, 0x0b } }
++};
++
++
++#define FREF 16
++
++static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
++{
++	int i, j;
++	u32 plln, pllf;
++	u64 tmp;
++
++	plln = (freq_khz * 1000) / 2 / FREF;
++
++	/* Compute the factional part times 1000 */
++	tmp  = plln % 1000000;
++	plln /= 1000000;
++
++	tmp *= 1048576;
++	do_div(tmp, 1000000);
++	pllf = (u32) tmp;
++
++	state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
++	deb("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d", freq_khz, state->frequency, pllf, plln);
++
++	itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
++	itd1000_write_reg(state, PLLNL, plln & 0xff);
++	itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
++	itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
++	itd1000_write_reg(state, PLLFL, (pllf >> 0) & 0xff);
++
++	for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) {
++		if (freq_khz <= itd1000_fre_values[i].freq) {
++			deb("fre_values: %d", i);
++			itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]);
++			for (j = 0; j < 9; j++)
++				itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]);
++			break;
++		}
++	}
++
++	itd1000_set_vco(state, freq_khz);
++}
++
++static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
++{
++	struct itd1000_state *state = fe->tuner_priv;
++	u8 pllcon1;
++
++	itd1000_set_lo(state, p->frequency);
++	itd1000_set_lpf_bw(state, p->u.qpsk.symbol_rate);
++
++	pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
++	itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
++	itd1000_write_reg(state, PLLCON1, pllcon1);
++
++	return 0;
++}
++
++static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++	struct itd1000_state *state = fe->tuner_priv;
++	*frequency = state->frequency;
++	return 0;
++}
++
++static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++	return 0;
++}
++
++static u8 itd1000_init_tab[][2] = {
++	{ PLLCON1,       0x65 }, /* Register does not change */
++	{ PLLNH,         0x80 }, /* Bits [7:6] do not change */
++	{ RESERVED_0X6D, 0x3b },
++	{ VCO_CHP2_I2C,  0x12 },
++	{ 0x72,          0xf9 }, /* No such regsister defined */
++	{ RESERVED_0X73, 0xff },
++	{ RESERVED_0X74, 0xb2 },
++	{ RESERVED_0X75, 0xc7 },
++	{ EXTGVBBRF,     0xf0 },
++	{ DIVAGCCK,      0x80 },
++	{ BBTR,          0xa0 },
++	{ RESERVED_0X7E, 0x4f },
++	{ 0x82,          0x88 }, /* No such regsister defined */
++	{ 0x83,          0x80 }, /* No such regsister defined */
++	{ 0x84,          0x80 }, /* No such regsister defined */
++	{ RESERVED_0X85, 0x74 },
++	{ RESERVED_0X86, 0xff },
++	{ RESERVED_0X88, 0x02 },
++	{ RESERVED_0X89, 0x16 },
++	{ RFST0,         0x1f },
++	{ RESERVED_0X94, 0x66 },
++	{ RESERVED_0X95, 0x66 },
++	{ RESERVED_0X96, 0x77 },
++	{ RESERVED_0X97, 0x99 },
++	{ RESERVED_0X98, 0xff },
++	{ RESERVED_0X99, 0xfc },
++	{ RESERVED_0X9A, 0xba },
++	{ RESERVED_0X9B, 0xaa },
++};
++
++static u8 itd1000_reinit_tab[][2] = {
++	{ VCO_CHP1_I2C, 0x8a },
++	{ BW,           0x87 },
++	{ GVBB_I2C,     0x03 },
++	{ BBGVMIN,      0x03 },
++	{ CON1,         0x2e },
++};
++
++
++static int itd1000_init(struct dvb_frontend *fe)
++{
++	struct itd1000_state *state = fe->tuner_priv;
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(itd1000_init_tab); i++)
++		itd1000_write_reg(state, itd1000_init_tab[i][0], itd1000_init_tab[i][1]);
++
++	for (i = 0; i < ARRAY_SIZE(itd1000_reinit_tab); i++)
++		itd1000_write_reg(state, itd1000_reinit_tab[i][0], itd1000_reinit_tab[i][1]);
++
++	return 0;
++}
++
++static int itd1000_sleep(struct dvb_frontend *fe)
++{
++	return 0;
++}
++
++static int itd1000_release(struct dvb_frontend *fe)
++{
++	kfree(fe->tuner_priv);
++	fe->tuner_priv = NULL;
++	return 0;
++}
++
++static const struct dvb_tuner_ops itd1000_tuner_ops = {
++	.info = {
++		.name           = "Integrant ITD1000",
++		.frequency_min  = 950000,
++		.frequency_max  = 2150000,
++		.frequency_step = 125,     /* kHz for QPSK frontends */
++	},
++
++	.release       = itd1000_release,
++
++	.init          = itd1000_init,
++	.sleep         = itd1000_sleep,
++
++	.set_params    = itd1000_set_parameters,
++	.get_frequency = itd1000_get_frequency,
++	.get_bandwidth = itd1000_get_bandwidth
++};
++
++
++struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
++{
++	struct itd1000_state *state = NULL;
++	u8 i = 0;
++
++	state = kzalloc(sizeof(struct itd1000_state), GFP_KERNEL);
++	if (state == NULL)
++		return NULL;
++
++	state->cfg = cfg;
++	state->i2c = i2c;
++
++	i = itd1000_read_reg(state, 0);
++	if (i != 0) {
++		kfree(state);
++		return NULL;
++	}
++	info("successfully identified (ID: %d)", i);
++
++	memset(state->shadow, 0xff, sizeof(state->shadow));
++	for (i = 0x65; i < 0x9c; i++)
++		state->shadow[i] = itd1000_read_reg(state, i);
++
++	memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops));
++
++	fe->tuner_priv = state;
++
++	return fe;
++}
++EXPORT_SYMBOL(itd1000_attach);
++
++MODULE_AUTHOR("Patrick Boettcher <pb at linuxtv.org>");
++MODULE_DESCRIPTION("Integrant ITD1000 driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/itd1000.h b/drivers/media/dvb/frontends/itd1000.h
+new file mode 100644
+index 0000000..5e18df0
+--- /dev/null
++++ b/drivers/media/dvb/frontends/itd1000.h
+@@ -0,0 +1,42 @@
++/*
++ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ *
++ *  Copyright (c) 2007 Patrick Boettcher <pb at linuxtv.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef ITD1000_H
++#define ITD1000_H
++
++struct dvb_frontend;
++struct i2c_adapter;
++
++struct itd1000_config {
++	u8 i2c_address;
++};
++
++#if defined(CONFIG_DVB_TUNER_ITD1000) || (defined(CONFIG_DVB_TUNER_ITD1000_MODULE) && defined(MODULE))
++extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg);
++#else
++static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
++{
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++	return NULL;
++}
++#endif
++
++#endif
+diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb/frontends/itd1000_priv.h
+new file mode 100644
+index 0000000..8cdc54e
+--- /dev/null
++++ b/drivers/media/dvb/frontends/itd1000_priv.h
+@@ -0,0 +1,88 @@
++/*
++ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ *
++ *  Copyright (c) 2007 Patrick Boettcher <pb at linuxtv.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef ITD1000_PRIV_H
++#define ITD1000_PRIV_H
++
++struct itd1000_state {
++	struct itd1000_config *cfg;
++	struct i2c_adapter    *i2c;
++
++	u32 frequency; /* contains the value resulting from the LO-setting */
++
++	/* ugly workaround for flexcop's incapable i2c-controller
++	 * FIXME, if possible
++	 */
++	u8 shadow[255];
++};
++
++enum itd1000_register {
++	VCO_CHP1 = 0x65,
++	VCO_CHP2,
++	PLLCON1,
++	PLLNH,
++	PLLNL,
++	PLLFH,
++	PLLFM,
++	PLLFL,
++	RESERVED_0X6D,
++	PLLLOCK,
++	VCO_CHP2_I2C,
++	VCO_CHP1_I2C,
++	BW,
++	RESERVED_0X73 = 0x73,
++	RESERVED_0X74,
++	RESERVED_0X75,
++	GVBB,
++	GVRF,
++	GVBB_I2C,
++	EXTGVBBRF,
++	DIVAGCCK,
++	BBTR,
++	RFTR,
++	BBGVMIN,
++	RESERVED_0X7E,
++	RESERVED_0X85 = 0x85,
++	RESERVED_0X86,
++	CON1,
++	RESERVED_0X88,
++	RESERVED_0X89,
++	RFST0,
++	RFST1,
++	RFST2,
++	RFST3,
++	RFST4,
++	RFST5,
++	RFST6,
++	RFST7,
++	RFST8,
++	RFST9,
++	RESERVED_0X94,
++	RESERVED_0X95,
++	RESERVED_0X96,
++	RESERVED_0X97,
++	RESERVED_0X98,
++	RESERVED_0X99,
++	RESERVED_0X9A,
++	RESERVED_0X9B,
++};
++
++#endif
+diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
+index 443d904..e1e70e9 100644
+--- a/drivers/media/dvb/frontends/l64781.c
++++ b/drivers/media/dvb/frontends/l64781.c
+@@ -57,7 +57,7 @@ static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
+ 
+ 	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
+ 		dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
+-			 __FUNCTION__, reg, ret);
++			 __func__, reg, ret);
+ 
+ 	return (ret != 1) ? -1 : 0;
+ }
+diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h
+index cd15f76..1305a9e 100644
+--- a/drivers/media/dvb/frontends/l64781.h
++++ b/drivers/media/dvb/frontends/l64781.h
+@@ -38,7 +38,7 @@ extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+ static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+ 					  struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_L64781
+diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
+index bdc9fa8..f0195c8 100644
+--- a/drivers/media/dvb/frontends/lgdt330x.c
++++ b/drivers/media/dvb/frontends/lgdt330x.c
+@@ -49,7 +49,7 @@
+ /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
+ /* #define USE_EQMSE */
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
+ #define dprintk(args...) \
+@@ -88,7 +88,7 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state,
+ 
+ 	for (i=0; i<len-1; i+=2){
+ 		if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+-			printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
++			printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
+ 			if (err < 0)
+ 				return err;
+ 			else
+@@ -117,7 +117,7 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
+ 	int ret;
+ 	ret = i2c_transfer(state->i2c, msg, 2);
+ 	if (ret != 2) {
+-		printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
++		printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
+ 	} else {
+ 		ret = 0;
+ 	}
+@@ -256,7 +256,7 @@ static int lgdt330x_init(struct dvb_frontend* fe)
+ 		printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
+ 		err = -ENODEV;
+ 	}
+-	dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
++	dprintk("%s entered as %s\n", __func__, chip_name);
+ 	if (err < 0)
+ 		return err;
+ 	return lgdt330x_SwReset(state);
+@@ -334,7 +334,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ 	if (state->current_modulation != param->u.vsb.modulation) {
+ 		switch(param->u.vsb.modulation) {
+ 		case VSB_8:
+-			dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
++			dprintk("%s: VSB_8 MODE\n", __func__);
+ 
+ 			/* Select VSB mode */
+ 			top_ctrl_cfg[1] = 0x03;
+@@ -350,7 +350,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ 			break;
+ 
+ 		case QAM_64:
+-			dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
++			dprintk("%s: QAM_64 MODE\n", __func__);
+ 
+ 			/* Select QAM_64 mode */
+ 			top_ctrl_cfg[1] = 0x00;
+@@ -366,7 +366,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ 			break;
+ 
+ 		case QAM_256:
+-			dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
++			dprintk("%s: QAM_256 MODE\n", __func__);
+ 
+ 			/* Select QAM_256 mode */
+ 			top_ctrl_cfg[1] = 0x01;
+@@ -381,7 +381,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ 			}
+ 			break;
+ 		default:
+-			printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
++			printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation);
+ 			return -1;
+ 		}
+ 		/*
+@@ -431,7 +431,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 
+ 	/* AGC status register */
+ 	i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
+-	dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
++	dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
+ 	if ((buf[0] & 0x0c) == 0x8){
+ 		/* Test signal does not exist flag */
+ 		/* as well as the AGC lock flag.   */
+@@ -445,7 +445,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 	 */
+ 	/* signal status */
+ 	i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
+-	dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
++	dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]);
+ 
+ 
+ 	/* sync status */
+@@ -461,7 +461,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 
+ 	/* Carrier Recovery Lock Status Register */
+ 	i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+-	dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
++	dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
+ 	switch (state->current_modulation) {
+ 	case QAM_256:
+ 	case QAM_64:
+@@ -474,7 +474,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 			*status |= FE_HAS_CARRIER;
+ 		break;
+ 	default:
+-		printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
++		printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
+ 	}
+ 
+ 	return 0;
+@@ -493,7 +493,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 	if (err < 0)
+ 		return err;
+ 
+-	dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
++	dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
+ 	if ((buf[0] & 0x21) == 0x01){
+ 		/* Test input signal does not exist flag */
+ 		/* as well as the AGC lock flag.   */
+@@ -502,7 +502,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 
+ 	/* Carrier Recovery Lock Status Register */
+ 	i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+-	dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
++	dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
+ 	switch (state->current_modulation) {
+ 	case QAM_256:
+ 	case QAM_64:
+@@ -533,7 +533,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 		}
+ 		break;
+ 	default:
+-		printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
++		printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
+ 	}
+ 	return 0;
+ }
+@@ -607,14 +607,14 @@ static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
+ 		break;
+ 	default:
+ 		printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
+ 	}
+ 
+ 	state->snr = calculate_snr(noise, c);
+ 	*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
+ 
+-	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
++	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
+ 		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
+ 
+ 	return 0;
+@@ -651,14 +651,14 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
+ 		break;
+ 	default:
+ 		printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
+ 	}
+ 
+ 	state->snr = calculate_snr(noise, c);
+ 	*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
+ 
+-	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
++	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
+ 		state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
+ 
+ 	return 0;
+@@ -743,7 +743,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+ 
+ error:
+ 	kfree(state);
+-	dprintk("%s: ERROR\n",__FUNCTION__);
++	dprintk("%s: ERROR\n",__func__);
+ 	return NULL;
+ }
+ 
+diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h
+index 9950590..9012504 100644
+--- a/drivers/media/dvb/frontends/lgdt330x.h
++++ b/drivers/media/dvb/frontends/lgdt330x.h
+@@ -59,7 +59,7 @@ extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config
+ static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+ 					    struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_LGDT330X
+diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h
+index 68906ac..8fe094b 100644
+--- a/drivers/media/dvb/frontends/lnbp21.h
++++ b/drivers/media/dvb/frontends/lnbp21.h
+@@ -45,7 +45,7 @@ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_ad
+ #else
+ static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_LNBP21
+diff --git a/drivers/media/dvb/frontends/mt2060.h b/drivers/media/dvb/frontends/mt2060.h
+index 0a86eab..acba005 100644
+--- a/drivers/media/dvb/frontends/mt2060.h
++++ b/drivers/media/dvb/frontends/mt2060.h
+@@ -35,7 +35,7 @@ extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_a
+ #else
+ static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TUNER_MT2060
+diff --git a/drivers/media/dvb/frontends/mt2131.c b/drivers/media/dvb/frontends/mt2131.c
+index 13cf166..e254bcf 100644
+--- a/drivers/media/dvb/frontends/mt2131.c
++++ b/drivers/media/dvb/frontends/mt2131.c
+@@ -110,7 +110,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
+ 		priv->bandwidth = 0;
+ 
+ 	freq = params->frequency / 1000;  // Hz -> kHz
+-	dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq);
++	dprintk(1, "%s() freq=%d\n", __func__, freq);
+ 
+ 	f_lo1 = freq + MT2131_IF1 * 1000;
+ 	f_lo1 = (f_lo1 / 250) * 250;
+@@ -187,7 +187,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
+ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+ {
+ 	struct mt2131_priv *priv = fe->tuner_priv;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	*frequency = priv->frequency;
+ 	return 0;
+ }
+@@ -195,7 +195,7 @@ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+ static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+ {
+ 	struct mt2131_priv *priv = fe->tuner_priv;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	*bandwidth = priv->bandwidth;
+ 	return 0;
+ }
+@@ -214,7 +214,7 @@ static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
+ 
+ 	mt2131_readreg(priv, 0x09, &afc_status);
+ 	dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
+-		__FUNCTION__, lock_status, afc_status);
++		__func__, lock_status, afc_status);
+ 
+ 	return 0;
+ }
+@@ -223,7 +223,7 @@ static int mt2131_init(struct dvb_frontend *fe)
+ {
+ 	struct mt2131_priv *priv = fe->tuner_priv;
+ 	int ret;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	if ((ret = mt2131_writeregs(priv, mt2131_config1,
+ 				    sizeof(mt2131_config1))) < 0)
+@@ -243,7 +243,7 @@ static int mt2131_init(struct dvb_frontend *fe)
+ 
+ static int mt2131_release(struct dvb_frontend *fe)
+ {
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	kfree(fe->tuner_priv);
+ 	fe->tuner_priv = NULL;
+ 	return 0;
+@@ -273,7 +273,7 @@ struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
+ 	struct mt2131_priv *priv = NULL;
+ 	u8 id = 0;
+ 
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
+ 	if (priv == NULL)
+diff --git a/drivers/media/dvb/frontends/mt2131.h b/drivers/media/dvb/frontends/mt2131.h
+index 1e4ffe7..606d857 100644
+--- a/drivers/media/dvb/frontends/mt2131.h
++++ b/drivers/media/dvb/frontends/mt2131.h
+@@ -41,7 +41,7 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
+ 						 struct mt2131_config *cfg,
+ 						 u16 if1)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif /* CONFIG_DVB_TUNER_MT2131 */
+diff --git a/drivers/media/dvb/frontends/mt2266.h b/drivers/media/dvb/frontends/mt2266.h
+index f31dd61..c5113ef 100644
+--- a/drivers/media/dvb/frontends/mt2266.h
++++ b/drivers/media/dvb/frontends/mt2266.h
+@@ -29,7 +29,7 @@ extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_a
+ #else
+ static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TUNER_MT2266
+diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
+index 1638301..081ca33 100644
+--- a/drivers/media/dvb/frontends/mt312.c
++++ b/drivers/media/dvb/frontends/mt312.c
+@@ -1,7 +1,8 @@
+ /*
+-    Driver for Zarlink VP310/MT312 Satellite Channel Decoder
++    Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
+ 
+     Copyright (C) 2003 Andreas Oberritter <obi at linuxtv.org>
++    Copyright (C) 2008 Matthias Schwarzott <zzam at gentoo.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
+@@ -43,7 +44,8 @@ struct mt312_state {
+ 	struct dvb_frontend frontend;
+ 
+ 	u8 id;
+-	u8 frequency;
++	unsigned long xtal;
++	u8 freq_mult;
+ };
+ 
+ static int debug;
+@@ -53,12 +55,11 @@ static int debug;
+ 			printk(KERN_DEBUG "mt312: " args); \
+ 	} while (0)
+ 
+-#define MT312_SYS_CLK		90000000UL	/* 90 MHz */
+-#define MT312_LPOWER_SYS_CLK	60000000UL	/* 60 MHz */
+ #define MT312_PLL_CLK		10000000UL	/* 10 MHz */
++#define MT312_PLL_CLK_10_111	10111000UL	/* 10.111 MHz */
+ 
+ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+-		      void *buf, const size_t count)
++		      u8 *buf, const size_t count)
+ {
+ 	int ret;
+ 	struct i2c_msg msg[2];
+@@ -76,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+ 	ret = i2c_transfer(state->i2c, msg, 2);
+ 
+ 	if (ret != 2) {
+-		printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret);
++		printk(KERN_ERR "%s: ret == %d\n", __func__, ret);
+ 		return -EREMOTEIO;
+ 	}
+ 
+@@ -84,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+ 		int i;
+ 		dprintk("R(%d):", reg & 0x7f);
+ 		for (i = 0; i < count; i++)
+-			printk(" %02x", ((const u8 *) buf)[i]);
++			printk(" %02x", buf[i]);
+ 		printk("\n");
+ 	}
+ 
+@@ -92,7 +93,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+ }
+ 
+ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+-		       const void *src, const size_t count)
++		       const u8 *src, const size_t count)
+ {
+ 	int ret;
+ 	u8 buf[count + 1];
+@@ -102,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+ 		int i;
+ 		dprintk("W(%d):", reg & 0x7f);
+ 		for (i = 0; i < count; i++)
+-			printk(" %02x", ((const u8 *) src)[i]);
++			printk(" %02x", src[i]);
+ 		printk("\n");
+ 	}
+ 
+@@ -117,7 +118,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+ 	ret = i2c_transfer(state->i2c, &msg, 1);
+ 
+ 	if (ret != 1) {
+-		dprintk("%s: ret == %d\n", __FUNCTION__, ret);
++		dprintk("%s: ret == %d\n", __func__, ret);
+ 		return -EREMOTEIO;
+ 	}
+ 
+@@ -209,7 +210,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
+ 		dprintk("sym_rat_op=%d dec_ratio=%d\n",
+ 		       sym_rat_op, dec_ratio);
+ 		dprintk("*sr(manual) = %lu\n",
+-		       (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
++		       (((state->xtal * 8192) / (sym_rat_op + 8192)) *
+ 			2) - dec_ratio);
+ 	}
+ 
+@@ -242,7 +243,7 @@ static int mt312_initfe(struct dvb_frontend *fe)
+ 
+ 	/* wake up */
+ 	ret = mt312_writereg(state, CONFIG,
+-			(state->frequency == 60 ? 0x88 : 0x8c));
++			(state->freq_mult == 6 ? 0x88 : 0x8c));
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -265,12 +266,37 @@ static int mt312_initfe(struct dvb_frontend *fe)
+ 			return ret;
+ 	}
+ 
++	switch (state->id) {
++	case ID_ZL10313:
++		/* enable ADC */
++		ret = mt312_writereg(state, GPP_CTRL, 0x80);
++		if (ret < 0)
++			return ret;
++
++		/* configure ZL10313 for optimal ADC performance */
++		buf[0] = 0x80;
++		buf[1] = 0xB0;
++		ret = mt312_write(state, HW_CTRL, buf, 2);
++		if (ret < 0)
++			return ret;
++
++		/* enable MPEG output and ADCs */
++		ret = mt312_writereg(state, HW_CTRL, 0x00);
++		if (ret < 0)
++			return ret;
++
++		ret = mt312_writereg(state, MPEG_CTRL, 0x00);
++		if (ret < 0)
++			return ret;
++
++		break;
++	}
++
+ 	/* SYS_CLK */
+-	buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK :
+-				MT312_SYS_CLK) * 2, 1000000);
++	buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
+ 
+ 	/* DISEQC_RATIO */
+-	buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
++	buf[1] = mt312_div(state->xtal, 22000 * 4);
+ 
+ 	ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
+ 	if (ret < 0)
+@@ -280,7 +306,17 @@ static int mt312_initfe(struct dvb_frontend *fe)
+ 	if (ret < 0)
+ 		return ret;
+ 
+-	ret = mt312_writereg(state, OP_CTRL, 0x53);
++	/* different MOCLK polarity */
++	switch (state->id) {
++	case ID_ZL10313:
++		buf[0] = 0x33;
++		break;
++	default:
++		buf[0] = 0x53;
++		break;
++	}
++
++	ret = mt312_writereg(state, OP_CTRL, buf[0]);
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -323,6 +359,9 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe,
+ 	if (ret < 0)
+ 		return ret;
+ 
++	/* is there a better way to wait for message to be transmitted */
++	msleep(100);
++
+ 	/* set DISEQC_MODE[2:0] to zero if a return message is expected */
+ 	if (c->msg[0] & 0x02) {
+ 		ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
+@@ -383,11 +422,16 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
+ {
+ 	struct mt312_state *state = fe->demodulator_priv;
+ 	const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
++	u8 val;
+ 
+ 	if (v > SEC_VOLTAGE_OFF)
+ 		return -EINVAL;
+ 
+-	return mt312_writereg(state, DISEQC_MODE, volt_tab[v]);
++	val = volt_tab[v];
++	if (state->config->voltage_inverted)
++		val ^= 0x40;
++
++	return mt312_writereg(state, DISEQC_MODE, val);
+ }
+ 
+ static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
+@@ -463,7 +507,7 @@ static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
+ 	int ret;
+ 	u8 buf[2];
+ 
+-	ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf));
++	ret = mt312_read(state, M_SNR_H, buf, sizeof(buf));
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -478,7 +522,7 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
+ 	int ret;
+ 	u8 buf[2];
+ 
+-	ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf));
++	ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf));
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -499,7 +543,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
+ 	    { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f };
+ 	const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };
+ 
+-	dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
++	dprintk("%s: Freq %d\n", __func__, p->frequency);
+ 
+ 	if ((p->frequency < fe->ops.info.frequency_min)
+ 	    || (p->frequency > fe->ops.info.frequency_max))
+@@ -532,17 +576,17 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
+ 			return ret;
+ 		if (p->u.qpsk.symbol_rate >= 30000000) {
+ 			/* Note that 30MS/s should use 90MHz */
+-			if ((config_val & 0x0c) == 0x08) {
++			if (state->freq_mult == 6) {
+ 				/* We are running 60MHz */
+-				state->frequency = 90;
++				state->freq_mult = 9;
+ 				ret = mt312_initfe(fe);
+ 				if (ret < 0)
+ 					return ret;
+ 			}
+ 		} else {
+-			if ((config_val & 0x0c) == 0x0C) {
++			if (state->freq_mult == 9) {
+ 				/* We are running 90MHz */
+-				state->frequency = 60;
++				state->freq_mult = 6;
+ 				ret = mt312_initfe(fe);
+ 				if (ret < 0)
+ 					return ret;
+@@ -551,6 +595,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
+ 		break;
+ 
+ 	case ID_MT312:
++	case ID_ZL10313:
+ 		break;
+ 
+ 	default:
+@@ -616,11 +661,29 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+ {
+ 	struct mt312_state *state = fe->demodulator_priv;
+ 
+-	if (enable) {
+-		return mt312_writereg(state, GPP_CTRL, 0x40);
+-	} else {
+-		return mt312_writereg(state, GPP_CTRL, 0x00);
++	u8 val = 0x00;
++	int ret;
++
++	switch (state->id) {
++	case ID_ZL10313:
++		ret = mt312_readreg(state, GPP_CTRL, &val);
++		if (ret < 0)
++			goto error;
++
++		/* preserve this bit to not accidently shutdown ADC */
++		val &= 0x80;
++		break;
+ 	}
++
++	if (enable)
++		val |= 0x40;
++	else
++		val &= ~0x40;
++
++	ret = mt312_writereg(state, GPP_CTRL, val);
++
++error:
++	return ret;
+ }
+ 
+ static int mt312_sleep(struct dvb_frontend *fe)
+@@ -634,6 +697,18 @@ static int mt312_sleep(struct dvb_frontend *fe)
+ 	if (ret < 0)
+ 		return ret;
+ 
++	if (state->id == ID_ZL10313) {
++		/* reset ADC */
++		ret = mt312_writereg(state, GPP_CTRL, 0x00);
++		if (ret < 0)
++			return ret;
++
++		/* full shutdown of ADCs, mpeg bus tristated */
++		ret = mt312_writereg(state, HW_CTRL, 0x0d);
++		if (ret < 0)
++			return ret;
++	}
++
+ 	ret = mt312_readreg(state, CONFIG, &config);
+ 	if (ret < 0)
+ 		return ret;
+@@ -661,6 +736,7 @@ static void mt312_release(struct dvb_frontend *fe)
+ 	kfree(state);
+ }
+ 
++#define MT312_SYS_CLK		90000000UL	/* 90 MHz */
+ static struct dvb_frontend_ops vp310_mt312_ops = {
+ 
+ 	.info = {
+@@ -668,8 +744,8 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
+ 		.type = FE_QPSK,
+ 		.frequency_min = 950000,
+ 		.frequency_max = 2150000,
+-		.frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
+-		.symbol_rate_min = MT312_SYS_CLK / 128,
++		.frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */
++		.symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */
+ 		.symbol_rate_max = MT312_SYS_CLK / 2,
+ 		.caps =
+ 		    FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+@@ -726,14 +802,21 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
+ 	switch (state->id) {
+ 	case ID_VP310:
+ 		strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
+-		state->frequency = 90;
++		state->xtal = MT312_PLL_CLK;
++		state->freq_mult = 9;
+ 		break;
+ 	case ID_MT312:
+ 		strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
+-		state->frequency = 60;
++		state->xtal = MT312_PLL_CLK;
++		state->freq_mult = 6;
++		break;
++	case ID_ZL10313:
++		strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
++		state->xtal = MT312_PLL_CLK_10_111;
++		state->freq_mult = 9;
+ 		break;
+ 	default:
+-		printk(KERN_WARNING "Only Zarlink VP310/MT312"
++		printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
+ 			" are supported chips.\n");
+ 		goto error;
+ 	}
+@@ -749,7 +832,7 @@ EXPORT_SYMBOL(vp310_mt312_attach);
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+ 
+-MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
++MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
+ MODULE_AUTHOR("Andreas Oberritter <obi at linuxtv.org>");
+ MODULE_LICENSE("GPL");
+ 
+diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
+index f17cb93..de796ea 100644
+--- a/drivers/media/dvb/frontends/mt312.h
++++ b/drivers/media/dvb/frontends/mt312.h
+@@ -31,6 +31,9 @@
+ struct mt312_config {
+ 	/* the demodulator's i2c address */
+ 	u8 demod_address;
++
++	/* inverted voltage setting */
++	unsigned int voltage_inverted:1;
+ };
+ 
+ #if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
+@@ -40,7 +43,7 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
+ static inline struct dvb_frontend *vp310_mt312_attach(
+ 	const struct mt312_config *config, struct i2c_adapter *i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif /* CONFIG_DVB_MT312 */
+diff --git a/drivers/media/dvb/frontends/mt312_priv.h b/drivers/media/dvb/frontends/mt312_priv.h
+index 5e0b95b..a3959f9 100644
+--- a/drivers/media/dvb/frontends/mt312_priv.h
++++ b/drivers/media/dvb/frontends/mt312_priv.h
+@@ -110,6 +110,8 @@ enum mt312_reg_addr {
+ 	VIT_ERRPER_H = 83,
+ 	VIT_ERRPER_M = 84,
+ 	VIT_ERRPER_L = 85,
++	HW_CTRL = 84,	/* ZL10313 only */
++	MPEG_CTRL = 85,	/* ZL10313 only */
+ 	VIT_SETUP = 86,
+ 	VIT_REF0 = 87,
+ 	VIT_REF1 = 88,
+@@ -156,7 +158,8 @@ enum mt312_reg_addr {
+ 
+ enum mt312_model_id {
+ 	ID_VP310 = 1,
+-	ID_MT312 = 3
++	ID_MT312 = 3,
++	ID_ZL10313 = 5,
+ };
+ 
+ #endif				/* DVB_FRONTENDS_MT312_PRIV */
+diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
+index 7cd190b..beba5aa 100644
+--- a/drivers/media/dvb/frontends/mt352.c
++++ b/drivers/media/dvb/frontends/mt352.c
+@@ -95,7 +95,7 @@ static int mt352_read_register(struct mt352_state* state, u8 reg)
+ 
+ 	if (ret != 2) {
+ 		printk("%s: readreg error (reg=%d, ret==%i)\n",
+-		       __FUNCTION__, reg, ret);
++		       __func__, reg, ret);
+ 		return ret;
+ 	}
+ 
+@@ -135,7 +135,7 @@ static void mt352_calc_nominal_rate(struct mt352_state* state,
+ 	value = 64 * bw * (1<<16) / (7 * 8);
+ 	value = value * 1000 / adc_clock;
+ 	dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+-		__FUNCTION__, bw, adc_clock, value);
++		__func__, bw, adc_clock, value);
+ 	buf[0] = msb(value);
+ 	buf[1] = lsb(value);
+ }
+@@ -161,7 +161,7 @@ static void mt352_calc_input_freq(struct mt352_state* state,
+ 	}
+ 	value = -16374 * ife / adc_clock;
+ 	dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
+-		__FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff);
++		__func__, if2, ife, adc_clock, value, value & 0x3fff);
+ 	buf[0] = msb(value);
+ 	buf[1] = lsb(value);
+ }
+@@ -521,7 +521,7 @@ static int mt352_init(struct dvb_frontend* fe)
+ 
+ 	static u8 mt352_reset_attach [] = { RESET, 0xC0 };
+ 
+-	dprintk("%s: hello\n",__FUNCTION__);
++	dprintk("%s: hello\n",__func__);
+ 
+ 	if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 ||
+ 	    (mt352_read_register(state, CONFIG) & 0x20) == 0) {
+diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h
+index e996408..595092f 100644
+--- a/drivers/media/dvb/frontends/mt352.h
++++ b/drivers/media/dvb/frontends/mt352.h
+@@ -58,7 +58,7 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
+ static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
+ 					 struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_MT352
+diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
+index fcf964f..23d0228 100644
+--- a/drivers/media/dvb/frontends/nxt200x.c
++++ b/drivers/media/dvb/frontends/nxt200x.c
+@@ -74,7 +74,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len
+ 
+ 	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ 		printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
+-			__FUNCTION__, addr, err);
++			__func__, addr, err);
+ 		return -EREMOTEIO;
+ 	}
+ 	return 0;
+@@ -87,7 +87,7 @@ static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
+ 
+ 	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ 		printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
+-			__FUNCTION__, addr, err);
++			__func__, addr, err);
+ 		return -EREMOTEIO;
+ 	}
+ 	return 0;
+@@ -104,7 +104,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8
+ 
+ 	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ 		printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
+-			__FUNCTION__, state->config->demod_address, err);
++			__func__, state->config->demod_address, err);
+ 		return -EREMOTEIO;
+ 	}
+ 	return 0;
+@@ -121,7 +121,7 @@ static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 le
+ 
+ 	if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
+ 		printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
+-			__FUNCTION__, state->config->demod_address, err);
++			__func__, state->config->demod_address, err);
+ 		return -EREMOTEIO;
+ 	}
+ 	return 0;
+@@ -146,7 +146,7 @@ static u16 nxt200x_crc(u16 crc, u8 c)
+ static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
+ {
+ 	u8 attr, len2, buf;
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* set mutli register register */
+ 	nxt200x_writebytes(state, 0x35, &reg, 1);
+@@ -207,7 +207,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
+ {
+ 	int i;
+ 	u8 buf, len2, attr;
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* set mutli register register */
+ 	nxt200x_writebytes(state, 0x35, &reg, 1);
+@@ -254,7 +254,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
+ static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
+ {
+ 	u8 buf, stopval, counter = 0;
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* set correct stop value */
+ 	switch (state->demod_chip) {
+@@ -287,7 +287,7 @@ static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
+ static void nxt200x_microcontroller_start (struct nxt200x_state* state)
+ {
+ 	u8 buf;
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	buf = 0x00;
+ 	nxt200x_writebytes(state, 0x22, &buf, 1);
+@@ -297,7 +297,7 @@ static void nxt2004_microcontroller_init (struct nxt200x_state* state)
+ {
+ 	u8 buf[9];
+ 	u8 counter = 0;
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	buf[0] = 0x00;
+ 	nxt200x_writebytes(state, 0x2b, buf, 1);
+@@ -328,7 +328,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
+ {
+ 	u8 buf, count = 0;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
+ 
+@@ -387,7 +387,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
+ static void nxt200x_agc_reset(struct nxt200x_state* state)
+ {
+ 	u8 buf;
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	switch (state->demod_chip) {
+ 		case NXT2002:
+@@ -416,7 +416,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
+ 	u8 buf[3], written = 0, chunkpos = 0;
+ 	u16 rambase, position, crc = 0;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 	dprintk("Firmware is %zu bytes\n", fw->size);
+ 
+ 	/* Get the RAM base for this nxt2002 */
+@@ -483,7 +483,7 @@ static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware
+ 	u8 buf[3];
+ 	u16 rambase, position, crc=0;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 	dprintk("Firmware is %zu bytes\n", fw->size);
+ 
+ 	/* set rambase */
+diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h
+index bb0ef58..f3c8458 100644
+--- a/drivers/media/dvb/frontends/nxt200x.h
++++ b/drivers/media/dvb/frontends/nxt200x.h
+@@ -49,7 +49,7 @@ extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+ static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_NXT200X
+diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
+index d313d7d..0eef22d 100644
+--- a/drivers/media/dvb/frontends/nxt6000.c
++++ b/drivers/media/dvb/frontends/nxt6000.c
+@@ -38,7 +38,7 @@ struct nxt6000_state {
+ 	struct dvb_frontend frontend;
+ };
+ 
+-static int debug = 0;
++static int debug;
+ #define dprintk if (debug) printk
+ 
+ static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
+diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb/frontends/nxt6000.h
+index 13d2251..878eb38 100644
+--- a/drivers/media/dvb/frontends/nxt6000.h
++++ b/drivers/media/dvb/frontends/nxt6000.h
+@@ -40,7 +40,7 @@ extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
+ static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_NXT6000
+diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
+index 1d2d28c..c7b5785 100644
+--- a/drivers/media/dvb/frontends/or51132.c
++++ b/drivers/media/dvb/frontends/or51132.c
+@@ -91,7 +91,7 @@ static int or51132_writebuf(struct or51132_state *state, const u8 *buf, int len)
+    Less code and more efficient that loading a buffer on the stack with
+    the bytes to send and then calling or51132_writebuf() on that. */
+ #define or51132_writebytes(state, data...)  \
+-	({ const static u8 _data[] = {data}; \
++	({ static const u8 _data[] = {data}; \
+ 	or51132_writebuf(state, _data, sizeof(_data)); })
+ 
+ /* Read data from demod into buffer.  Returns 0 on success. */
+@@ -132,7 +132,7 @@ static int or51132_readreg(struct or51132_state *state, u8 reg)
+ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+ {
+ 	struct or51132_state* state = fe->demodulator_priv;
+-	const static u8 run_buf[] = {0x7F,0x01};
++	static const u8 run_buf[] = {0x7F,0x01};
+ 	u8 rec_buf[8];
+ 	u32 firmwareAsize, firmwareBsize;
+ 	int i,ret;
+@@ -419,7 +419,7 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 		*status = 0;
+ 		return -EREMOTEIO;
+ 	}
+-	dprintk("%s: read_status %04x\n", __FUNCTION__, reg);
++	dprintk("%s: read_status %04x\n", __func__, reg);
+ 
+ 	if (reg & 0x0100) /* Receiver Lock */
+ 		*status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|
+@@ -504,14 +504,14 @@ start:
+ 		if (retry--) goto start;
+ 		return -EREMOTEIO;
+ 	}
+-	dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__,
++	dprintk("%s: modulation %02x, NTSC rej O%s\n", __func__,
+ 		reg&0xff, reg&0x1000?"n":"ff");
+ 
+ 	/* Calculate SNR using noise, c, and NTSC rejection correction */
+ 	state->snr = calculate_snr(noise, c) - usK;
+ 	*snr = (state->snr) >> 16;
+ 
+-	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
++	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
+ 		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
+ 
+ 	return 0;
+diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb/frontends/or51132.h
+index add24f0..1b8e04d 100644
+--- a/drivers/media/dvb/frontends/or51132.h
++++ b/drivers/media/dvb/frontends/or51132.h
+@@ -41,7 +41,7 @@ extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+ static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_OR51132
+diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
+index 6a6b0d7..7eaa476 100644
+--- a/drivers/media/dvb/frontends/or51211.c
++++ b/drivers/media/dvb/frontends/or51211.c
+@@ -307,19 +307,19 @@ static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
+ 
+ 	if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
+ 		printk(KERN_WARNING "%s: error writing snr reg\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return -1;
+ 	}
+ 	if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+ 		printk(KERN_WARNING "%s: read_status read error\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return -1;
+ 	}
+ 
+ 	state->snr = calculate_snr(rec_buf[0], 89599047);
+ 	*snr = (state->snr) >> 16;
+ 
+-	dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0],
++	dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0],
+ 		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
+ 
+ 	return 0;
+diff --git a/drivers/media/dvb/frontends/or51211.h b/drivers/media/dvb/frontends/or51211.h
+index 8aad840..3ce0508 100644
+--- a/drivers/media/dvb/frontends/or51211.h
++++ b/drivers/media/dvb/frontends/or51211.h
+@@ -44,7 +44,7 @@ extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+ static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_OR51211
+diff --git a/drivers/media/dvb/frontends/qt1010.h b/drivers/media/dvb/frontends/qt1010.h
+index 3ab4aa0..cff6a7c 100644
+--- a/drivers/media/dvb/frontends/qt1010.h
++++ b/drivers/media/dvb/frontends/qt1010.h
+@@ -45,7 +45,7 @@ static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
+ 						 struct i2c_adapter *i2c,
+ 						 struct qt1010_config *cfg)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TUNER_QT1010
+diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
+index 1a4d831..b999ec4 100644
+--- a/drivers/media/dvb/frontends/s5h1409.c
++++ b/drivers/media/dvb/frontends/s5h1409.c
+@@ -48,7 +48,7 @@ struct s5h1409_state {
+ 	u32 qam_state;
+ };
+ 
+-static int debug = 0;
++static int debug;
+ #define dprintk	if (debug) printk
+ 
+ /* Register values to initialise the demod, this will set VSB by default */
+@@ -312,7 +312,7 @@ static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
+ 
+ 	if (ret != 1)
+ 		printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+-		       "ret == %i)\n", __FUNCTION__, reg, data, ret);
++		       "ret == %i)\n", __func__, reg, data, ret);
+ 
+ 	return (ret != 1) ? -1 : 0;
+ }
+@@ -332,7 +332,7 @@ static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
+ 	ret = i2c_transfer(state->i2c, msg, 2);
+ 
+ 	if (ret != 2)
+-		printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++		printk("%s: readreg error (ret == %i)\n", __func__, ret);
+ 	return (b1[0] << 8) | b1[1];
+ }
+ 
+@@ -340,7 +340,7 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s()\n", __FUNCTION__);
++	dprintk("%s()\n", __func__);
+ 
+ 	s5h1409_writereg(state, 0xf5, 0);
+ 	s5h1409_writereg(state, 0xf5, 1);
+@@ -356,7 +356,7 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
++	dprintk("%s(%d KHz)\n", __func__, KHz);
+ 
+ 	switch (KHz) {
+ 	case 4000:
+@@ -381,7 +381,7 @@ static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s(%d)\n", __FUNCTION__, inverted);
++	dprintk("%s(%d)\n", __func__, inverted);
+ 
+ 	if(inverted == 1)
+ 		return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
+@@ -394,25 +394,25 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s(0x%08x)\n", __FUNCTION__, m);
++	dprintk("%s(0x%08x)\n", __func__, m);
+ 
+ 	switch(m) {
+ 	case VSB_8:
+-		dprintk("%s() VSB_8\n", __FUNCTION__);
++		dprintk("%s() VSB_8\n", __func__);
+ 		if (state->if_freq != S5H1409_VSB_IF_FREQ)
+ 			s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
+ 		s5h1409_writereg(state, 0xf4, 0);
+ 		break;
+ 	case QAM_64:
+ 	case QAM_256:
+-		dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
++		dprintk("%s() QAM_AUTO (64/256)\n", __func__);
+ 		if (state->if_freq != S5H1409_QAM_IF_FREQ)
+ 			s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
+ 		s5h1409_writereg(state, 0xf4, 1);
+ 		s5h1409_writereg(state, 0x85, 0x110);
+ 		break;
+ 	default:
+-		dprintk("%s() Invalid modulation\n", __FUNCTION__);
++		dprintk("%s() Invalid modulation\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -426,7 +426,7 @@ static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s(%d)\n", __FUNCTION__, enable);
++	dprintk("%s(%d)\n", __func__, enable);
+ 
+ 	if (enable)
+ 		return s5h1409_writereg(state, 0xf3, 1);
+@@ -438,7 +438,7 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s(%d)\n", __FUNCTION__, enable);
++	dprintk("%s(%d)\n", __func__, enable);
+ 
+ 	if (enable)
+ 		return s5h1409_writereg(state, 0xe3,
+@@ -452,7 +452,7 @@ static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s(%d)\n", __FUNCTION__, enable);
++	dprintk("%s(%d)\n", __func__, enable);
+ 
+ 	return s5h1409_writereg(state, 0xf2, enable);
+ }
+@@ -461,7 +461,7 @@ static int s5h1409_register_reset(struct dvb_frontend* fe)
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s()\n", __FUNCTION__);
++	dprintk("%s()\n", __func__);
+ 
+ 	return s5h1409_writereg(state, 0xfa, 0);
+ }
+@@ -534,7 +534,7 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency);
++	dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+ 
+ 	s5h1409_softreset(fe);
+ 
+@@ -565,7 +565,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+ 	struct s5h1409_state *state = fe->demodulator_priv;
+ 	u16 val;
+ 
+-	dprintk("%s(%d)\n", __FUNCTION__, mode);
++	dprintk("%s(%d)\n", __func__, mode);
+ 
+ 	val = s5h1409_readreg(state, 0xac) & 0xcfff;
+ 	switch (mode) {
+@@ -573,7 +573,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+ 		val |= 0x0000;
+ 		break;
+ 	case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
+-		dprintk("%s(%d) Mode1 or Defaulting\n", __FUNCTION__, mode);
++		dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
+ 		val |= 0x1000;
+ 		break;
+ 	case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
+@@ -597,7 +597,7 @@ static int s5h1409_init (struct dvb_frontend* fe)
+ 	int i;
+ 
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+-	dprintk("%s()\n", __FUNCTION__);
++	dprintk("%s()\n", __func__);
+ 
+ 	s5h1409_sleep(fe, 0);
+ 	s5h1409_register_reset(fe);
+@@ -663,7 +663,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 		break;
+ 	}
+ 
+-	dprintk("%s() status 0x%08x\n", __FUNCTION__, *status);
++	dprintk("%s() status 0x%08x\n", __func__, *status);
+ 
+ 	return 0;
+ }
+@@ -671,7 +671,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ {
+ 	int i, ret = -EINVAL;
+-	dprintk("%s()\n", __FUNCTION__);
++	dprintk("%s()\n", __func__);
+ 
+ 	for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+ 		if (v < qam256_snr_tab[i].val) {
+@@ -686,7 +686,7 @@ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ {
+ 	int i, ret = -EINVAL;
+-	dprintk("%s()\n", __FUNCTION__);
++	dprintk("%s()\n", __func__);
+ 
+ 	for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+ 		if (v < qam64_snr_tab[i].val) {
+@@ -701,7 +701,7 @@ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ {
+ 	int i, ret = -EINVAL;
+-	dprintk("%s()\n", __FUNCTION__);
++	dprintk("%s()\n", __func__);
+ 
+ 	for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+ 		if (v > vsb_snr_tab[i].val) {
+@@ -710,7 +710,7 @@ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ 			break;
+ 		}
+ 	}
+-	dprintk("%s() snr=%d\n", __FUNCTION__, *snr);
++	dprintk("%s() snr=%d\n", __func__, *snr);
+ 	return ret;
+ }
+ 
+@@ -718,7 +718,7 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
+ {
+ 	struct s5h1409_state* state = fe->demodulator_priv;
+ 	u16 reg;
+-	dprintk("%s()\n", __FUNCTION__);
++	dprintk("%s()\n", __func__);
+ 
+ 	switch(state->current_modulation) {
+ 	case QAM_64:
+@@ -812,7 +812,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+ 
+ 	if (s5h1409_init(&state->frontend) != 0) {
+ 		printk(KERN_ERR "%s: Failed to initialize correctly\n",
+-			__FUNCTION__);
++			__func__);
+ 		goto error;
+ 	}
+ 
+diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h
+index f0bb13f..59f4335 100644
+--- a/drivers/media/dvb/frontends/s5h1409.h
++++ b/drivers/media/dvb/frontends/s5h1409.h
+@@ -67,7 +67,7 @@ extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+ static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+ 						  struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif /* CONFIG_DVB_S5H1409 */
+diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
+new file mode 100644
+index 0000000..eb5bfc9
+--- /dev/null
++++ b/drivers/media/dvb/frontends/s5h1411.c
+@@ -0,0 +1,888 @@
++/*
++    Samsung S5H1411 VSB/QAM demodulator driver
++
++    Copyright (C) 2008 Steven Toth <stoth at hauppauge.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/init.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include "dvb_frontend.h"
++#include "dvb-pll.h"
++#include "s5h1411.h"
++
++struct s5h1411_state {
++
++	struct i2c_adapter *i2c;
++
++	/* configuration settings */
++	const struct s5h1411_config *config;
++
++	struct dvb_frontend frontend;
++
++	fe_modulation_t current_modulation;
++
++	u32 current_frequency;
++	int if_freq;
++
++	u8 inversion;
++};
++
++static int debug;
++
++#define dprintk(arg...) do {	\
++	if (debug)		\
++		printk(arg);	\
++	} while (0)
++
++/* Register values to initialise the demod, defaults to VSB */
++static struct init_tab {
++	u8	addr;
++	u8	reg;
++	u16	data;
++} init_tab[] = {
++	{ S5H1411_I2C_TOP_ADDR, 0x00, 0x0071, },
++	{ S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
++	{ S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
++	{ S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
++	{ S5H1411_I2C_TOP_ADDR, 0x1f, 0x342a, },
++	{ S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
++	{ S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
++	{ S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
++	{ S5H1411_I2C_TOP_ADDR, 0x27, 0x0f04, },
++	{ S5H1411_I2C_TOP_ADDR, 0x28, 0x070f, },
++	{ S5H1411_I2C_TOP_ADDR, 0x29, 0x2820, },
++	{ S5H1411_I2C_TOP_ADDR, 0x2a, 0x102e, },
++	{ S5H1411_I2C_TOP_ADDR, 0x2b, 0x0220, },
++	{ S5H1411_I2C_TOP_ADDR, 0x2e, 0x0d0e, },
++	{ S5H1411_I2C_TOP_ADDR, 0x2f, 0x1013, },
++	{ S5H1411_I2C_TOP_ADDR, 0x31, 0x171b, },
++	{ S5H1411_I2C_TOP_ADDR, 0x32, 0x0e0f, },
++	{ S5H1411_I2C_TOP_ADDR, 0x33, 0x0f10, },
++	{ S5H1411_I2C_TOP_ADDR, 0x34, 0x170e, },
++	{ S5H1411_I2C_TOP_ADDR, 0x35, 0x4b10, },
++	{ S5H1411_I2C_TOP_ADDR, 0x36, 0x0f17, },
++	{ S5H1411_I2C_TOP_ADDR, 0x3c, 0x1577, },
++	{ S5H1411_I2C_TOP_ADDR, 0x3d, 0x081a, },
++	{ S5H1411_I2C_TOP_ADDR, 0x3e, 0x77ee, },
++	{ S5H1411_I2C_TOP_ADDR, 0x40, 0x1e09, },
++	{ S5H1411_I2C_TOP_ADDR, 0x41, 0x0f0c, },
++	{ S5H1411_I2C_TOP_ADDR, 0x42, 0x1f10, },
++	{ S5H1411_I2C_TOP_ADDR, 0x4d, 0x0509, },
++	{ S5H1411_I2C_TOP_ADDR, 0x4e, 0x0a00, },
++	{ S5H1411_I2C_TOP_ADDR, 0x50, 0x0000, },
++	{ S5H1411_I2C_TOP_ADDR, 0x5b, 0x0000, },
++	{ S5H1411_I2C_TOP_ADDR, 0x5c, 0x0008, },
++	{ S5H1411_I2C_TOP_ADDR, 0x57, 0x1101, },
++	{ S5H1411_I2C_TOP_ADDR, 0x65, 0x007c, },
++	{ S5H1411_I2C_TOP_ADDR, 0x68, 0x0512, },
++	{ S5H1411_I2C_TOP_ADDR, 0x69, 0x0258, },
++	{ S5H1411_I2C_TOP_ADDR, 0x70, 0x0004, },
++	{ S5H1411_I2C_TOP_ADDR, 0x71, 0x0007, },
++	{ S5H1411_I2C_TOP_ADDR, 0x76, 0x00a9, },
++	{ S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
++	{ S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
++	{ S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
++	{ S5H1411_I2C_TOP_ADDR, 0xb5, 0xafbb, },
++	{ S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
++	{ S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
++	{ S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
++	{ S5H1411_I2C_TOP_ADDR, 0xb8, 0x003f, },
++	{ S5H1411_I2C_TOP_ADDR, 0xb9, 0x2700, },
++	{ S5H1411_I2C_TOP_ADDR, 0xba, 0xfac8, },
++	{ S5H1411_I2C_TOP_ADDR, 0xbe, 0x1003, },
++	{ S5H1411_I2C_TOP_ADDR, 0xbf, 0x103f, },
++	{ S5H1411_I2C_TOP_ADDR, 0xce, 0x2000, },
++	{ S5H1411_I2C_TOP_ADDR, 0xcf, 0x0800, },
++	{ S5H1411_I2C_TOP_ADDR, 0xd0, 0x0800, },
++	{ S5H1411_I2C_TOP_ADDR, 0xd1, 0x0400, },
++	{ S5H1411_I2C_TOP_ADDR, 0xd2, 0x0800, },
++	{ S5H1411_I2C_TOP_ADDR, 0xd3, 0x2000, },
++	{ S5H1411_I2C_TOP_ADDR, 0xd4, 0x3000, },
++	{ S5H1411_I2C_TOP_ADDR, 0xdb, 0x4a9b, },
++	{ S5H1411_I2C_TOP_ADDR, 0xdc, 0x1000, },
++	{ S5H1411_I2C_TOP_ADDR, 0xde, 0x0001, },
++	{ S5H1411_I2C_TOP_ADDR, 0xdf, 0x0000, },
++	{ S5H1411_I2C_TOP_ADDR, 0xe3, 0x0301, },
++	{ S5H1411_I2C_QAM_ADDR, 0xf3, 0x0000, },
++	{ S5H1411_I2C_QAM_ADDR, 0xf3, 0x0001, },
++	{ S5H1411_I2C_QAM_ADDR, 0x08, 0x0600, },
++	{ S5H1411_I2C_QAM_ADDR, 0x18, 0x4201, },
++	{ S5H1411_I2C_QAM_ADDR, 0x1e, 0x6476, },
++	{ S5H1411_I2C_QAM_ADDR, 0x21, 0x0830, },
++	{ S5H1411_I2C_QAM_ADDR, 0x0c, 0x5679, },
++	{ S5H1411_I2C_QAM_ADDR, 0x0d, 0x579b, },
++	{ S5H1411_I2C_QAM_ADDR, 0x24, 0x0102, },
++	{ S5H1411_I2C_QAM_ADDR, 0x31, 0x7488, },
++	{ S5H1411_I2C_QAM_ADDR, 0x32, 0x0a08, },
++	{ S5H1411_I2C_QAM_ADDR, 0x3d, 0x8689, },
++	{ S5H1411_I2C_QAM_ADDR, 0x49, 0x0048, },
++	{ S5H1411_I2C_QAM_ADDR, 0x57, 0x2012, },
++	{ S5H1411_I2C_QAM_ADDR, 0x5d, 0x7676, },
++	{ S5H1411_I2C_QAM_ADDR, 0x04, 0x0400, },
++	{ S5H1411_I2C_QAM_ADDR, 0x58, 0x00c0, },
++	{ S5H1411_I2C_QAM_ADDR, 0x5b, 0x0100, },
++};
++
++/* VSB SNR lookup table */
++static struct vsb_snr_tab {
++	u16	val;
++	u16	data;
++} vsb_snr_tab[] = {
++	{  0x39f, 300, },
++	{  0x39b, 295, },
++	{  0x397, 290, },
++	{  0x394, 285, },
++	{  0x38f, 280, },
++	{  0x38b, 275, },
++	{  0x387, 270, },
++	{  0x382, 265, },
++	{  0x37d, 260, },
++	{  0x377, 255, },
++	{  0x370, 250, },
++	{  0x36a, 245, },
++	{  0x364, 240, },
++	{  0x35b, 235, },
++	{  0x353, 230, },
++	{  0x349, 225, },
++	{  0x340, 320, },
++	{  0x337, 215, },
++	{  0x327, 210, },
++	{  0x31b, 205, },
++	{  0x310, 200, },
++	{  0x302, 195, },
++	{  0x2f3, 190, },
++	{  0x2e4, 185, },
++	{  0x2d7, 180, },
++	{  0x2cd, 175, },
++	{  0x2bb, 170, },
++	{  0x2a9, 165, },
++	{  0x29e, 160, },
++	{  0x284, 155, },
++	{  0x27a, 150, },
++	{  0x260, 145, },
++	{  0x23a, 140, },
++	{  0x224, 135, },
++	{  0x213, 130, },
++	{  0x204, 125, },
++	{  0x1fe, 120, },
++	{      0,   0, },
++};
++
++/* QAM64 SNR lookup table */
++static struct qam64_snr_tab {
++	u16	val;
++	u16	data;
++} qam64_snr_tab[] = {
++	{  0x0001,   0, },
++	{  0x0af0, 300, },
++	{  0x0d80, 290, },
++	{  0x10a0, 280, },
++	{  0x14b5, 270, },
++	{  0x1590, 268, },
++	{  0x1680, 266, },
++	{  0x17b0, 264, },
++	{  0x18c0, 262, },
++	{  0x19b0, 260, },
++	{  0x1ad0, 258, },
++	{  0x1d00, 256, },
++	{  0x1da0, 254, },
++	{  0x1ef0, 252, },
++	{  0x2050, 250, },
++	{  0x20f0, 249, },
++	{  0x21d0, 248, },
++	{  0x22b0, 247, },
++	{  0x23a0, 246, },
++	{  0x2470, 245, },
++	{  0x24f0, 244, },
++	{  0x25a0, 243, },
++	{  0x26c0, 242, },
++	{  0x27b0, 241, },
++	{  0x28d0, 240, },
++	{  0x29b0, 239, },
++	{  0x2ad0, 238, },
++	{  0x2ba0, 237, },
++	{  0x2c80, 236, },
++	{  0x2d20, 235, },
++	{  0x2e00, 234, },
++	{  0x2f10, 233, },
++	{  0x3050, 232, },
++	{  0x3190, 231, },
++	{  0x3300, 230, },
++	{  0x3340, 229, },
++	{  0x3200, 228, },
++	{  0x3550, 227, },
++	{  0x3610, 226, },
++	{  0x3600, 225, },
++	{  0x3700, 224, },
++	{  0x3800, 223, },
++	{  0x3920, 222, },
++	{  0x3a20, 221, },
++	{  0x3b30, 220, },
++	{  0x3d00, 219, },
++	{  0x3e00, 218, },
++	{  0x4000, 217, },
++	{  0x4100, 216, },
++	{  0x4300, 215, },
++	{  0x4400, 214, },
++	{  0x4600, 213, },
++	{  0x4700, 212, },
++	{  0x4800, 211, },
++	{  0x4a00, 210, },
++	{  0x4b00, 209, },
++	{  0x4d00, 208, },
++	{  0x4f00, 207, },
++	{  0x5050, 206, },
++	{  0x5200, 205, },
++	{  0x53c0, 204, },
++	{  0x5450, 203, },
++	{  0x5650, 202, },
++	{  0x5820, 201, },
++	{  0x6000, 200, },
++	{  0xffff,   0, },
++};
++
++/* QAM256 SNR lookup table */
++static struct qam256_snr_tab {
++	u16	val;
++	u16	data;
++} qam256_snr_tab[] = {
++	{  0x0001,   0, },
++	{  0x0970, 400, },
++	{  0x0a90, 390, },
++	{  0x0b90, 380, },
++	{  0x0d90, 370, },
++	{  0x0ff0, 360, },
++	{  0x1240, 350, },
++	{  0x1345, 348, },
++	{  0x13c0, 346, },
++	{  0x14c0, 344, },
++	{  0x1500, 342, },
++	{  0x1610, 340, },
++	{  0x1700, 338, },
++	{  0x1800, 336, },
++	{  0x18b0, 334, },
++	{  0x1900, 332, },
++	{  0x1ab0, 330, },
++	{  0x1bc0, 328, },
++	{  0x1cb0, 326, },
++	{  0x1db0, 324, },
++	{  0x1eb0, 322, },
++	{  0x2030, 320, },
++	{  0x2200, 318, },
++	{  0x2280, 316, },
++	{  0x2410, 314, },
++	{  0x25b0, 312, },
++	{  0x27a0, 310, },
++	{  0x2840, 308, },
++	{  0x29d0, 306, },
++	{  0x2b10, 304, },
++	{  0x2d30, 302, },
++	{  0x2f20, 300, },
++	{  0x30c0, 298, },
++	{  0x3260, 297, },
++	{  0x32c0, 296, },
++	{  0x3300, 295, },
++	{  0x33b0, 294, },
++	{  0x34b0, 293, },
++	{  0x35a0, 292, },
++	{  0x3650, 291, },
++	{  0x3800, 290, },
++	{  0x3900, 289, },
++	{  0x3a50, 288, },
++	{  0x3b30, 287, },
++	{  0x3cb0, 286, },
++	{  0x3e20, 285, },
++	{  0x3fa0, 284, },
++	{  0x40a0, 283, },
++	{  0x41c0, 282, },
++	{  0x42f0, 281, },
++	{  0x44a0, 280, },
++	{  0x4600, 279, },
++	{  0x47b0, 278, },
++	{  0x4900, 277, },
++	{  0x4a00, 276, },
++	{  0x4ba0, 275, },
++	{  0x4d00, 274, },
++	{  0x4f00, 273, },
++	{  0x5000, 272, },
++	{  0x51f0, 272, },
++	{  0x53a0, 270, },
++	{  0x5520, 269, },
++	{  0x5700, 268, },
++	{  0x5800, 267, },
++	{  0x5a00, 266, },
++	{  0x5c00, 265, },
++	{  0x5d00, 264, },
++	{  0x5f00, 263, },
++	{  0x6000, 262, },
++	{  0x6200, 261, },
++	{  0x6400, 260, },
++	{  0xffff,   0, },
++};
++
++/* 8 bit registers, 16 bit values */
++static int s5h1411_writereg(struct s5h1411_state *state,
++	u8 addr, u8 reg, u16 data)
++{
++	int ret;
++	u8 buf [] = { reg, data >> 8,  data & 0xff };
++
++	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
++
++	ret = i2c_transfer(state->i2c, &msg, 1);
++
++	if (ret != 1)
++		printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
++		       "ret == %i)\n", __func__, addr, reg, data, ret);
++
++	return (ret != 1) ? -1 : 0;
++}
++
++static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
++{
++	int ret;
++	u8 b0 [] = { reg };
++	u8 b1 [] = { 0, 0 };
++
++	struct i2c_msg msg [] = {
++		{ .addr = addr, .flags = 0, .buf = b0, .len = 1 },
++		{ .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
++
++	ret = i2c_transfer(state->i2c, msg, 2);
++
++	if (ret != 2)
++		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
++			__func__, ret);
++	return (b1[0] << 8) | b1[1];
++}
++
++static int s5h1411_softreset(struct dvb_frontend *fe)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++
++	dprintk("%s()\n", __func__);
++
++	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
++	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
++	return 0;
++}
++
++static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++
++	dprintk("%s(%d KHz)\n", __func__, KHz);
++
++	switch (KHz) {
++	case 3250:
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d9);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
++		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
++		break;
++	case 3500:
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1225);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x1e96);
++		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1225);
++		break;
++	case 4000:
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x14bc);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0xb53e);
++		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x14bd);
++		break;
++	default:
++		dprintk("%s(%d KHz) Invalid, defaulting to 5380\n",
++			__func__, KHz);
++		/* no break, need to continue */
++	case 5380:
++	case 44000:
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x3655);
++		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1be4);
++		break;
++	}
++
++	state->if_freq = KHz;
++
++	return 0;
++}
++
++static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++	u16 val;
++
++	dprintk("%s(%d)\n", __func__, mode);
++
++	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbe) & 0xcfff;
++	switch (mode) {
++	case S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
++		val |= 0x0000;
++		break;
++	case S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
++		dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
++		val |= 0x1000;
++		break;
++	case S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
++		val |= 0x2000;
++		break;
++	case S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
++		val |= 0x3000;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	/* Configure MPEG Signal Timing charactistics */
++	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
++}
++
++static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++	u16 val;
++
++	dprintk("%s(%d)\n", __func__, inversion);
++	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
++
++	if (inversion == 1)
++		val |= 0x1000; /* Inverted */
++	else
++		val |= 0x0000;
++
++	state->inversion = inversion;
++	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
++}
++
++static int s5h1411_enable_modulation(struct dvb_frontend *fe,
++				     fe_modulation_t m)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++
++	dprintk("%s(0x%08x)\n", __func__, m);
++
++	switch (m) {
++	case VSB_8:
++		dprintk("%s() VSB_8\n", __func__);
++		s5h1411_set_if_freq(fe, state->config->vsb_if);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x71);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x00);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0xf1);
++		break;
++	case QAM_64:
++	case QAM_256:
++		dprintk("%s() QAM_AUTO (64/256)\n", __func__);
++		s5h1411_set_if_freq(fe, state->config->qam_if);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x0001);
++		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x16, 0x1101);
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0x00f0);
++		break;
++	default:
++		dprintk("%s() Invalid modulation\n", __func__);
++		return -EINVAL;
++	}
++
++	state->current_modulation = m;
++	s5h1411_softreset(fe);
++
++	return 0;
++}
++
++static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++
++	dprintk("%s(%d)\n", __func__, enable);
++
++	if (enable)
++		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
++	else
++		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
++}
++
++static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++	u16 val;
++
++	dprintk("%s(%d)\n", __func__, enable);
++
++	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
++
++	if (enable)
++		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
++				val | 0x02);
++	else
++		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
++}
++
++static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++
++	dprintk("%s(%d)\n", __func__, enable);
++
++	if (enable)
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
++	else {
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
++		s5h1411_softreset(fe);
++	}
++
++	return 0;
++}
++
++static int s5h1411_register_reset(struct dvb_frontend *fe)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++
++	dprintk("%s()\n", __func__);
++
++	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
++}
++
++/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
++static int s5h1411_set_frontend(struct dvb_frontend *fe,
++	struct dvb_frontend_parameters *p)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++
++	dprintk("%s(frequency=%d)\n", __func__, p->frequency);
++
++	s5h1411_softreset(fe);
++
++	state->current_frequency = p->frequency;
++
++	s5h1411_enable_modulation(fe, p->u.vsb.modulation);
++
++	/* Allow the demod to settle */
++	msleep(100);
++
++	if (fe->ops.tuner_ops.set_params) {
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 1);
++
++		fe->ops.tuner_ops.set_params(fe, p);
++
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 0);
++	}
++
++	return 0;
++}
++
++/* Reset the demod hardware and reset all of the configuration registers
++   to a default state. */
++static int s5h1411_init(struct dvb_frontend *fe)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++	int i;
++
++	dprintk("%s()\n", __func__);
++
++	s5h1411_sleep(fe, 0);
++	s5h1411_register_reset(fe);
++
++	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
++		s5h1411_writereg(state, init_tab[i].addr,
++			init_tab[i].reg,
++			init_tab[i].data);
++
++	/* The datasheet says that after initialisation, VSB is default */
++	state->current_modulation = VSB_8;
++
++	if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
++		/* Serial */
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101);
++	else
++		/* Parallel */
++		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001);
++
++	s5h1411_set_spectralinversion(fe, state->config->inversion);
++	s5h1411_set_if_freq(fe, state->config->vsb_if);
++	s5h1411_set_gpio(fe, state->config->gpio);
++	s5h1411_set_mpeg_timing(fe, state->config->mpeg_timing);
++	s5h1411_softreset(fe);
++
++	/* Note: Leaving the I2C gate closed. */
++	s5h1411_i2c_gate_ctrl(fe, 0);
++
++	return 0;
++}
++
++static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++	u16 reg;
++	u32 tuner_status = 0;
++
++	*status = 0;
++
++	/* Get the demodulator status */
++	reg = (s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2) >> 15)
++		& 0x0001;
++	if (reg)
++		*status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_SIGNAL;
++
++	switch (state->current_modulation) {
++	case QAM_64:
++	case QAM_256:
++		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
++		if (reg & 0x100)
++			*status |= FE_HAS_VITERBI;
++		if (reg & 0x10)
++			*status |= FE_HAS_SYNC;
++		break;
++	case VSB_8:
++		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x5e);
++		if (reg & 0x0001)
++			*status |= FE_HAS_SYNC;
++		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
++		if (reg & 0x1000)
++			*status |= FE_HAS_VITERBI;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	switch (state->config->status_mode) {
++	case S5H1411_DEMODLOCKING:
++		if (*status & FE_HAS_VITERBI)
++			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++		break;
++	case S5H1411_TUNERLOCKING:
++		/* Get the tuner status */
++		if (fe->ops.tuner_ops.get_status) {
++			if (fe->ops.i2c_gate_ctrl)
++				fe->ops.i2c_gate_ctrl(fe, 1);
++
++			fe->ops.tuner_ops.get_status(fe, &tuner_status);
++
++			if (fe->ops.i2c_gate_ctrl)
++				fe->ops.i2c_gate_ctrl(fe, 0);
++		}
++		if (tuner_status)
++			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++		break;
++	}
++
++	dprintk("%s() status 0x%08x\n", __func__, *status);
++
++	return 0;
++}
++
++static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
++{
++	int i, ret = -EINVAL;
++	dprintk("%s()\n", __func__);
++
++	for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
++		if (v < qam256_snr_tab[i].val) {
++			*snr = qam256_snr_tab[i].data;
++			ret = 0;
++			break;
++		}
++	}
++	return ret;
++}
++
++static int s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
++{
++	int i, ret = -EINVAL;
++	dprintk("%s()\n", __func__);
++
++	for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
++		if (v < qam64_snr_tab[i].val) {
++			*snr = qam64_snr_tab[i].data;
++			ret = 0;
++			break;
++		}
++	}
++	return ret;
++}
++
++static int s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
++{
++	int i, ret = -EINVAL;
++	dprintk("%s()\n", __func__);
++
++	for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
++		if (v > vsb_snr_tab[i].val) {
++			*snr = vsb_snr_tab[i].data;
++			ret = 0;
++			break;
++		}
++	}
++	dprintk("%s() snr=%d\n", __func__, *snr);
++	return ret;
++}
++
++static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++	u16 reg;
++	dprintk("%s()\n", __func__);
++
++	switch (state->current_modulation) {
++	case QAM_64:
++		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
++		return s5h1411_qam64_lookup_snr(fe, snr, reg);
++	case QAM_256:
++		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
++		return s5h1411_qam256_lookup_snr(fe, snr, reg);
++	case VSB_8:
++		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR,
++			0xf2) & 0x3ff;
++		return s5h1411_vsb_lookup_snr(fe, snr, reg);
++	default:
++		break;
++	}
++
++	return -EINVAL;
++}
++
++static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
++	u16 *signal_strength)
++{
++	return s5h1411_read_snr(fe, signal_strength);
++}
++
++static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++
++	*ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
++
++	return 0;
++}
++
++static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
++{
++	return s5h1411_read_ucblocks(fe, ber);
++}
++
++static int s5h1411_get_frontend(struct dvb_frontend *fe,
++				struct dvb_frontend_parameters *p)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++
++	p->frequency = state->current_frequency;
++	p->u.vsb.modulation = state->current_modulation;
++
++	return 0;
++}
++
++static int s5h1411_get_tune_settings(struct dvb_frontend *fe,
++				     struct dvb_frontend_tune_settings *tune)
++{
++	tune->min_delay_ms = 1000;
++	return 0;
++}
++
++static void s5h1411_release(struct dvb_frontend *fe)
++{
++	struct s5h1411_state *state = fe->demodulator_priv;
++	kfree(state);
++}
++
++static struct dvb_frontend_ops s5h1411_ops;
++
++struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
++				    struct i2c_adapter *i2c)
++{
++	struct s5h1411_state *state = NULL;
++	u16 reg;
++
++	/* allocate memory for the internal state */
++	state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
++	if (state == NULL)
++		goto error;
++
++	/* setup the state */
++	state->config = config;
++	state->i2c = i2c;
++	state->current_modulation = VSB_8;
++	state->inversion = state->config->inversion;
++
++	/* check if the demod exists */
++	reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
++	if (reg != 0x0066)
++		goto error;
++
++	/* create dvb_frontend */
++	memcpy(&state->frontend.ops, &s5h1411_ops,
++	       sizeof(struct dvb_frontend_ops));
++
++	state->frontend.demodulator_priv = state;
++
++	if (s5h1411_init(&state->frontend) != 0) {
++		printk(KERN_ERR "%s: Failed to initialize correctly\n",
++			__func__);
++		goto error;
++	}
++
++	/* Note: Leaving the I2C gate open here. */
++	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
++
++	return &state->frontend;
++
++error:
++	kfree(state);
++	return NULL;
++}
++EXPORT_SYMBOL(s5h1411_attach);
++
++static struct dvb_frontend_ops s5h1411_ops = {
++
++	.info = {
++		.name			= "Samsung S5H1411 QAM/8VSB Frontend",
++		.type			= FE_ATSC,
++		.frequency_min		= 54000000,
++		.frequency_max		= 858000000,
++		.frequency_stepsize	= 62500,
++		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
++	},
++
++	.init                 = s5h1411_init,
++	.i2c_gate_ctrl        = s5h1411_i2c_gate_ctrl,
++	.set_frontend         = s5h1411_set_frontend,
++	.get_frontend         = s5h1411_get_frontend,
++	.get_tune_settings    = s5h1411_get_tune_settings,
++	.read_status          = s5h1411_read_status,
++	.read_ber             = s5h1411_read_ber,
++	.read_signal_strength = s5h1411_read_signal_strength,
++	.read_snr             = s5h1411_read_snr,
++	.read_ucblocks        = s5h1411_read_ucblocks,
++	.release              = s5h1411_release,
++};
++
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable verbose debug messages");
++
++MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
++MODULE_AUTHOR("Steven Toth");
++MODULE_LICENSE("GPL");
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb/frontends/s5h1411.h
+new file mode 100644
+index 0000000..1855f64
+--- /dev/null
++++ b/drivers/media/dvb/frontends/s5h1411.h
+@@ -0,0 +1,90 @@
++/*
++    Samsung S5H1411 VSB/QAM demodulator driver
++
++    Copyright (C) 2008 Steven Toth <stoth at hauppauge.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 __S5H1411_H__
++#define __S5H1411_H__
++
++#include <linux/dvb/frontend.h>
++
++#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
++#define S5H1411_I2C_QAM_ADDR (0x34 >> 1)
++
++struct s5h1411_config {
++
++	/* serial/parallel output */
++#define S5H1411_PARALLEL_OUTPUT 0
++#define S5H1411_SERIAL_OUTPUT   1
++	u8 output_mode;
++
++	/* GPIO Setting */
++#define S5H1411_GPIO_OFF 0
++#define S5H1411_GPIO_ON  1
++	u8 gpio;
++
++	/* MPEG signal timing */
++#define S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK       0
++#define S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK    1
++#define S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK    2
++#define S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
++	u16 mpeg_timing;
++
++	/* IF Freq for QAM and VSB in KHz */
++#define S5H1411_IF_2500  2500
++#define S5H1411_IF_3500  3500
++#define S5H1411_IF_4000  4000
++#define S5H1411_IF_5380  5380
++#define S5H1411_IF_44000 44000
++#define S5H1411_VSB_IF_DEFAULT S5H1411_IF_44000
++#define S5H1411_QAM_IF_DEFAULT S5H1411_IF_44000
++	u16 qam_if;
++	u16 vsb_if;
++
++	/* Spectral Inversion */
++#define S5H1411_INVERSION_OFF 0
++#define S5H1411_INVERSION_ON  1
++	u8 inversion;
++
++	/* Return lock status based on tuner lock, or demod lock */
++#define S5H1411_TUNERLOCKING 0
++#define S5H1411_DEMODLOCKING 1
++	u8 status_mode;
++};
++
++#if defined(CONFIG_DVB_S5H1411) || \
++	(defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
++extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
++					   struct i2c_adapter *i2c);
++#else
++static inline struct dvb_frontend *s5h1411_attach(
++	const struct s5h1411_config *config,
++	struct i2c_adapter *i2c)
++{
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++	return NULL;
++}
++#endif /* CONFIG_DVB_S5H1411 */
++
++#endif /* __S5H1411_H__ */
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
+index 2c2c344..281e1cb 100644
+--- a/drivers/media/dvb/frontends/s5h1420.c
++++ b/drivers/media/dvb/frontends/s5h1420.c
+@@ -1,24 +1,26 @@
+ /*
+-Driver for Samsung S5H1420 QPSK Demodulator
+-
+-Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU General Public License as published by
+-the Free Software Foundation; either version 2 of the License, or
+-(at your option) any later version.
+-
+-This program is distributed in the hope that it will be useful,
+-but WITHOUT ANY WARRANTY; without even the implied warranty of
+-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-
+-GNU General Public License for more details.
+-
+-You should have received a copy of the GNU General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-*/
++ * Driver for
++ *    Samsung S5H1420 and
++ *    PnpNetwork PN1010 QPSK Demodulator
++ *
++ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
++ * Copyright (C) 2005-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+ 
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -29,23 +31,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ #include <linux/jiffies.h>
+ #include <asm/div64.h>
+ 
+-#include "dvb_frontend.h"
+-#include "s5h1420.h"
++#include <linux/i2c.h>
+ 
+ 
++#include "dvb_frontend.h"
++#include "s5h1420.h"
++#include "s5h1420_priv.h"
+ 
+ #define TONE_FREQ 22000
+ 
+ struct s5h1420_state {
+ 	struct i2c_adapter* i2c;
+ 	const struct s5h1420_config* config;
++
+ 	struct dvb_frontend frontend;
++	struct i2c_adapter tuner_i2c_adapter;
++
++	u8 CON_1_val;
+ 
+ 	u8 postlocked:1;
+ 	u32 fclk;
+ 	u32 tunedfreq;
+ 	fe_code_rate_t fec_inner;
+ 	u32 symbol_rate;
++
++	/* FIXME: ugly workaround for flexcop's incapable i2c-controller
++	 * it does not support repeated-start, workaround: write addr-1
++	 * and then read
++	 */
++	u8 shadow[255];
+ };
+ 
+ static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
+@@ -53,44 +67,66 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+ 				     struct dvb_frontend_tune_settings* fesettings);
+ 
+ 
+-static int debug = 0;
+-#define dprintk if (debug) printk
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable debugging");
++
++#define dprintk(x...) do { \
++	if (debug) \
++		printk(KERN_DEBUG "S5H1420: " x); \
++} while (0)
++
++static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
++{
++	int ret;
++	u8 b[2];
++	struct i2c_msg msg[] = {
++		{ .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
++		{ .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
++		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
++	};
++
++	b[0] = (reg - 1) & 0xff;
++	b[1] = state->shadow[(reg - 1) & 0xff];
++
++	if (state->config->repeated_start_workaround) {
++		ret = i2c_transfer(state->i2c, msg, 3);
++		if (ret != 3)
++			return ret;
++	} else {
++		ret = i2c_transfer(state->i2c, &msg[1], 2);
++		if (ret != 2)
++			return ret;
++	}
++
++	/* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
++
++	return b[0];
++}
+ 
+ static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
+ {
+-	u8 buf [] = { reg, data };
++	u8 buf[] = { reg, data };
+ 	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+ 	int err;
+ 
+-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+-		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
++	/* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
++	err = i2c_transfer(state->i2c, &msg, 1);
++	if (err != 1) {
++		dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+ 		return -EREMOTEIO;
+ 	}
++	state->shadow[reg] = data;
+ 
+ 	return 0;
+ }
+ 
+-static u8 s5h1420_readreg (struct s5h1420_state* state, u8 reg)
+-{
+-	int ret;
+-	u8 b0 [] = { reg };
+-	u8 b1 [] = { 0 };
+-	struct i2c_msg msg1 = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 };
+-	struct i2c_msg msg2 = { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 };
+-
+-	if ((ret = i2c_transfer (state->i2c, &msg1, 1)) != 1)
+-		return ret;
+-
+-	if ((ret = i2c_transfer (state->i2c, &msg2, 1)) != 1)
+-		return ret;
+-
+-	return b1[0];
+-}
+-
+ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+ {
+ 	struct s5h1420_state* state = fe->demodulator_priv;
+ 
++	dprintk("enter %s\n", __func__);
++
+ 	switch(voltage) {
+ 	case SEC_VOLTAGE_13:
+ 		s5h1420_writereg(state, 0x3c,
+@@ -106,6 +142,7 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
+ 		break;
+ 	}
+ 
++	dprintk("leave %s\n", __func__);
+ 	return 0;
+ }
+ 
+@@ -113,6 +150,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+ {
+ 	struct s5h1420_state* state = fe->demodulator_priv;
+ 
++	dprintk("enter %s\n", __func__);
+ 	switch(tone) {
+ 	case SEC_TONE_ON:
+ 		s5h1420_writereg(state, 0x3b,
+@@ -124,6 +162,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+ 				 (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
+ 		break;
+ 	}
++	dprintk("leave %s\n", __func__);
+ 
+ 	return 0;
+ }
+@@ -137,6 +176,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
+ 	unsigned long timeout;
+ 	int result = 0;
+ 
++	dprintk("enter %s\n", __func__);
+ 	if (cmd->msg_len > 8)
+ 		return -EINVAL;
+ 
+@@ -168,6 +208,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
+ 	/* restore original settings */
+ 	s5h1420_writereg(state, 0x3b, val);
+ 	msleep(15);
++	dprintk("leave %s\n", __func__);
+ 	return result;
+ }
+ 
+@@ -289,6 +330,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 	struct s5h1420_state* state = fe->demodulator_priv;
+ 	u8 val;
+ 
++	dprintk("enter %s\n", __func__);
++
+ 	if (status == NULL)
+ 		return -EINVAL;
+ 
+@@ -297,13 +340,13 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 
+ 	/* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
+ 	the inversion, wait a bit and check again */
+-	if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) {
+-		val = s5h1420_readreg(state, 0x32);
++	if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) {
++		val = s5h1420_readreg(state, Vit10);
+ 		if ((val & 0x07) == 0x03) {
+ 			if (val & 0x08)
+-				s5h1420_writereg(state, 0x31, 0x13);
++				s5h1420_writereg(state, Vit09, 0x13);
+ 			else
+-				s5h1420_writereg(state, 0x31, 0x1b);
++				s5h1420_writereg(state, Vit09, 0x1b);
+ 
+ 			/* wait a bit then update lock status */
+ 			mdelay(200);
+@@ -312,68 +355,73 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 	}
+ 
+ 	/* perform post lock setup */
+-	if ((*status & FE_HAS_LOCK) && (!state->postlocked)) {
++	if ((*status & FE_HAS_LOCK) && !state->postlocked) {
+ 
+ 		/* calculate the data rate */
+ 		u32 tmp = s5h1420_getsymbolrate(state);
+-		switch(s5h1420_readreg(state, 0x32) & 0x07) {
+-		case 0:
+-			tmp = (tmp * 2 * 1) / 2;
+-			break;
+-
+-		case 1:
+-			tmp = (tmp * 2 * 2) / 3;
+-			break;
+-
+-		case 2:
+-			tmp = (tmp * 2 * 3) / 4;
+-			break;
+-
+-		case 3:
+-			tmp = (tmp * 2 * 5) / 6;
+-			break;
+-
+-		case 4:
+-			tmp = (tmp * 2 * 6) / 7;
+-			break;
+-
+-		case 5:
+-			tmp = (tmp * 2 * 7) / 8;
+-			break;
++		switch (s5h1420_readreg(state, Vit10) & 0x07) {
++		case 0: tmp = (tmp * 2 * 1) / 2; break;
++		case 1: tmp = (tmp * 2 * 2) / 3; break;
++		case 2: tmp = (tmp * 2 * 3) / 4; break;
++		case 3: tmp = (tmp * 2 * 5) / 6; break;
++		case 4: tmp = (tmp * 2 * 6) / 7; break;
++		case 5: tmp = (tmp * 2 * 7) / 8; break;
+ 		}
++
+ 		if (tmp == 0) {
+-			printk("s5h1420: avoided division by 0\n");
++			printk(KERN_ERR "s5h1420: avoided division by 0\n");
+ 			tmp = 1;
+ 		}
+ 		tmp = state->fclk / tmp;
+ 
++
+ 		/* set the MPEG_CLK_INTL for the calculated data rate */
+-		if (tmp < 4)
++		if (tmp < 2)
+ 			val = 0x00;
+-		else if (tmp < 8)
++		else if (tmp < 5)
+ 			val = 0x01;
+-		else if (tmp < 12)
++		else if (tmp < 9)
+ 			val = 0x02;
+-		else if (tmp < 16)
++		else if (tmp < 13)
+ 			val = 0x03;
+-		else if (tmp < 24)
++		else if (tmp < 17)
+ 			val = 0x04;
+-		else if (tmp < 32)
++		else if (tmp < 25)
+ 			val = 0x05;
+-		else
++		else if (tmp < 33)
+ 			val = 0x06;
+-		s5h1420_writereg(state, 0x22, val);
++		else
++			val = 0x07;
++		dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val);
++
++		s5h1420_writereg(state, FEC01, 0x18);
++		s5h1420_writereg(state, FEC01, 0x10);
++		s5h1420_writereg(state, FEC01, val);
++
++		/* Enable "MPEG_Out" */
++		val = s5h1420_readreg(state, Mpeg02);
++		s5h1420_writereg(state, Mpeg02, val | (1 << 6));
+ 
+-		/* DC freeze */
+-		s5h1420_writereg(state, 0x1f, s5h1420_readreg(state, 0x1f) | 0x01);
++		/* kicker disable */
++		val = s5h1420_readreg(state, QPSK01) & 0x7f;
++		s5h1420_writereg(state, QPSK01, val);
+ 
+-		/* kicker disable + remove DC offset */
+-		s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) & 0x6f);
++		/* DC freeze TODO it was never activated by default or it can stay activated */
++
++		if (s5h1420_getsymbolrate(state) >= 20000000) {
++			s5h1420_writereg(state, Loop04, 0x8a);
++			s5h1420_writereg(state, Loop05, 0x6a);
++		} else {
++			s5h1420_writereg(state, Loop04, 0x58);
++			s5h1420_writereg(state, Loop05, 0x27);
++		}
+ 
+ 		/* post-lock processing has been done! */
+ 		state->postlocked = 1;
+ 	}
+ 
++	dprintk("leave %s\n", __func__);
++
+ 	return 0;
+ }
+ 
+@@ -414,6 +462,7 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+ 
+ static void s5h1420_reset(struct s5h1420_state* state)
+ {
++	dprintk("%s\n", __func__);
+ 	s5h1420_writereg (state, 0x01, 0x08);
+ 	s5h1420_writereg (state, 0x01, 0x00);
+ 	udelay(10);
+@@ -422,54 +471,52 @@ static void s5h1420_reset(struct s5h1420_state* state)
+ static void s5h1420_setsymbolrate(struct s5h1420_state* state,
+ 				  struct dvb_frontend_parameters *p)
+ {
++	u8 v;
+ 	u64 val;
+ 
++	dprintk("enter %s\n", __func__);
++
+ 	val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
+-	if (p->u.qpsk.symbol_rate <= 21000000) {
++	if (p->u.qpsk.symbol_rate < 29000000)
+ 		val *= 2;
+-	}
+ 	do_div(val, (state->fclk / 1000));
+ 
+-	s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0x7f);
+-	s5h1420_writereg(state, 0x11, val >> 16);
+-	s5h1420_writereg(state, 0x12, val >> 8);
+-	s5h1420_writereg(state, 0x13, val & 0xff);
+-	s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x80);
++	dprintk("symbol rate register: %06llx\n", val);
++
++	v = s5h1420_readreg(state, Loop01);
++	s5h1420_writereg(state, Loop01, v & 0x7f);
++	s5h1420_writereg(state, Tnco01, val >> 16);
++	s5h1420_writereg(state, Tnco02, val >> 8);
++	s5h1420_writereg(state, Tnco03, val & 0xff);
++	s5h1420_writereg(state, Loop01,  v | 0x80);
++	dprintk("leave %s\n", __func__);
+ }
+ 
+ static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
+ {
+-	u64 val = 0;
+-	int sampling = 2;
+-
+-	if (s5h1420_readreg(state, 0x05) & 0x2)
+-		sampling = 1;
+-
+-	s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
+-	val  = s5h1420_readreg(state, 0x11) << 16;
+-	val |= s5h1420_readreg(state, 0x12) << 8;
+-	val |= s5h1420_readreg(state, 0x13);
+-	s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
+-
+-	val *= (state->fclk / 1000ULL);
+-	do_div(val, ((1<<24) * sampling));
+-
+-	return (u32) (val * 1000ULL);
++	return state->symbol_rate;
+ }
+ 
+ static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
+ {
+ 	int val;
++	u8 v;
++
++	dprintk("enter %s\n", __func__);
+ 
+ 	/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
+ 	 * divide fclk by 1000000 to get the correct value. */
+ 	val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
+ 
+-	s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0xbf);
+-	s5h1420_writereg(state, 0x0e, val >> 16);
+-	s5h1420_writereg(state, 0x0f, val >> 8);
+-	s5h1420_writereg(state, 0x10, val & 0xff);
+-	s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x40);
++	dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val);
++
++	v = s5h1420_readreg(state, Loop01);
++	s5h1420_writereg(state, Loop01, v & 0xbf);
++	s5h1420_writereg(state, Pnco01, val >> 16);
++	s5h1420_writereg(state, Pnco02, val >> 8);
++	s5h1420_writereg(state, Pnco03, val & 0xff);
++	s5h1420_writereg(state, Loop01, v | 0x40);
++	dprintk("leave %s\n", __func__);
+ }
+ 
+ static int s5h1420_getfreqoffset(struct s5h1420_state* state)
+@@ -496,52 +543,53 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
+ 				     struct dvb_frontend_parameters *p)
+ {
+ 	u8 inversion = 0;
++	u8 vit08, vit09;
++
++	dprintk("enter %s\n", __func__);
+ 
+-	if (p->inversion == INVERSION_OFF) {
++	if (p->inversion == INVERSION_OFF)
+ 		inversion = state->config->invert ? 0x08 : 0;
+-	} else if (p->inversion == INVERSION_ON) {
++	else if (p->inversion == INVERSION_ON)
+ 		inversion = state->config->invert ? 0 : 0x08;
+-	}
+ 
+ 	if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
+-		s5h1420_writereg(state, 0x30, 0x3f);
+-		s5h1420_writereg(state, 0x31, 0x00 | inversion);
++		vit08 = 0x3f;
++		vit09 = 0;
+ 	} else {
+ 		switch(p->u.qpsk.fec_inner) {
+ 		case FEC_1_2:
+-			s5h1420_writereg(state, 0x30, 0x01);
+-			s5h1420_writereg(state, 0x31, 0x10 | inversion);
++			vit08 = 0x01; vit09 = 0x10;
+ 			break;
+ 
+ 		case FEC_2_3:
+-			s5h1420_writereg(state, 0x30, 0x02);
+-			s5h1420_writereg(state, 0x31, 0x11 | inversion);
++			vit08 = 0x02; vit09 = 0x11;
+ 			break;
+ 
+ 		case FEC_3_4:
+-			s5h1420_writereg(state, 0x30, 0x04);
+-			s5h1420_writereg(state, 0x31, 0x12 | inversion);
++			vit08 = 0x04; vit09 = 0x12;
+ 			break;
+ 
+ 		case FEC_5_6:
+-			s5h1420_writereg(state, 0x30, 0x08);
+-			s5h1420_writereg(state, 0x31, 0x13 | inversion);
++			vit08 = 0x08; vit09 = 0x13;
+ 			break;
+ 
+ 		case FEC_6_7:
+-			s5h1420_writereg(state, 0x30, 0x10);
+-			s5h1420_writereg(state, 0x31, 0x14 | inversion);
++			vit08 = 0x10; vit09 = 0x14;
+ 			break;
+ 
+ 		case FEC_7_8:
+-			s5h1420_writereg(state, 0x30, 0x20);
+-			s5h1420_writereg(state, 0x31, 0x15 | inversion);
++			vit08 = 0x20; vit09 = 0x15;
+ 			break;
+ 
+ 		default:
+ 			return;
+ 		}
+ 	}
++	vit09 |= inversion;
++	dprintk("fec: %02x %02x\n", vit08, vit09);
++	s5h1420_writereg(state, Vit08, vit08);
++	s5h1420_writereg(state, Vit09, vit09);
++	dprintk("leave %s\n", __func__);
+ }
+ 
+ static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
+@@ -583,16 +631,19 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
+ 	struct s5h1420_state* state = fe->demodulator_priv;
+ 	int frequency_delta;
+ 	struct dvb_frontend_tune_settings fesettings;
++	uint8_t clock_settting;
++
++	dprintk("enter %s\n", __func__);
+ 
+ 	/* check if we should do a fast-tune */
+ 	memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
+ 	s5h1420_get_tune_settings(fe, &fesettings);
+ 	frequency_delta = p->frequency - state->tunedfreq;
+ 	if ((frequency_delta > -fesettings.max_drift) &&
+-	    (frequency_delta < fesettings.max_drift) &&
+-	    (frequency_delta != 0) &&
+-	    (state->fec_inner == p->u.qpsk.fec_inner) &&
+-	    (state->symbol_rate == p->u.qpsk.symbol_rate)) {
++			(frequency_delta < fesettings.max_drift) &&
++			(frequency_delta != 0) &&
++			(state->fec_inner == p->u.qpsk.fec_inner) &&
++			(state->symbol_rate == p->u.qpsk.symbol_rate)) {
+ 
+ 		if (fe->ops.tuner_ops.set_params) {
+ 			fe->ops.tuner_ops.set_params(fe, p);
+@@ -606,54 +657,93 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
+ 		} else {
+ 			s5h1420_setfreqoffset(state, 0);
+ 		}
++		dprintk("simple tune\n");
+ 		return 0;
+ 	}
++	dprintk("tuning demod\n");
+ 
+ 	/* first of all, software reset */
+ 	s5h1420_reset(state);
+ 
+ 	/* set s5h1420 fclk PLL according to desired symbol rate */
+-	if (p->u.qpsk.symbol_rate > 28000000) {
+-		state->fclk = 88000000;
+-		s5h1420_writereg(state, 0x03, 0x50);
+-		s5h1420_writereg(state, 0x04, 0x40);
+-		s5h1420_writereg(state, 0x05, 0xae);
+-	} else if (p->u.qpsk.symbol_rate > 21000000) {
++	if (p->u.qpsk.symbol_rate > 33000000)
++		state->fclk = 80000000;
++	else if (p->u.qpsk.symbol_rate > 28500000)
+ 		state->fclk = 59000000;
+-		s5h1420_writereg(state, 0x03, 0x33);
+-		s5h1420_writereg(state, 0x04, 0x40);
+-		s5h1420_writereg(state, 0x05, 0xae);
+-	} else {
++	else if (p->u.qpsk.symbol_rate > 25000000)
++		state->fclk = 86000000;
++	else if (p->u.qpsk.symbol_rate > 1900000)
+ 		state->fclk = 88000000;
+-		s5h1420_writereg(state, 0x03, 0x50);
+-		s5h1420_writereg(state, 0x04, 0x40);
+-		s5h1420_writereg(state, 0x05, 0xac);
++	else
++		state->fclk = 44000000;
++
++	/* Clock */
++	switch (state->fclk) {
++	default:
++	case 88000000:
++		clock_settting = 80;
++		break;
++	case 86000000:
++		clock_settting = 78;
++		break;
++	case 80000000:
++		clock_settting = 72;
++		break;
++	case 59000000:
++		clock_settting = 51;
++		break;
++	case 44000000:
++		clock_settting = 36;
++		break;
+ 	}
++	dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
++	s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
++	s5h1420_writereg(state, PLL02, 0x40);
++	s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+ 
+-	/* set misc registers */
+-	s5h1420_writereg(state, 0x02, 0x00);
+-	s5h1420_writereg(state, 0x06, 0x00);
+-	s5h1420_writereg(state, 0x07, 0xb0);
+-	s5h1420_writereg(state, 0x0a, 0xe7);
+-	s5h1420_writereg(state, 0x0b, 0x78);
+-	s5h1420_writereg(state, 0x0c, 0x48);
+-	s5h1420_writereg(state, 0x0d, 0x6b);
+-	s5h1420_writereg(state, 0x2e, 0x8e);
+-	s5h1420_writereg(state, 0x35, 0x33);
+-	s5h1420_writereg(state, 0x38, 0x01);
+-	s5h1420_writereg(state, 0x39, 0x7d);
+-	s5h1420_writereg(state, 0x3a, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+-	s5h1420_writereg(state, 0x3c, 0x00);
+-	s5h1420_writereg(state, 0x45, 0x61);
+-	s5h1420_writereg(state, 0x46, 0x1d);
++	/* TODO DC offset removal, config parameter ? */
++	if (p->u.qpsk.symbol_rate > 29000000)
++		s5h1420_writereg(state, QPSK01, 0xae | 0x10);
++	else
++		s5h1420_writereg(state, QPSK01, 0xac | 0x10);
+ 
+-	/* start QPSK */
+-	s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
++	/* set misc registers */
++	s5h1420_writereg(state, CON_1, 0x00);
++	s5h1420_writereg(state, QPSK02, 0x00);
++	s5h1420_writereg(state, Pre01, 0xb0);
++
++	s5h1420_writereg(state, Loop01, 0xF0);
++	s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
++	s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
++	if (p->u.qpsk.symbol_rate > 20000000)
++		s5h1420_writereg(state, Loop04, 0x79);
++	else
++		s5h1420_writereg(state, Loop04, 0x58);
++	s5h1420_writereg(state, Loop05, 0x6b);
++
++	if (p->u.qpsk.symbol_rate >= 8000000)
++		s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
++	else if (p->u.qpsk.symbol_rate >= 4000000)
++		s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
++	else
++		s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
++
++	s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
++
++	s5h1420_writereg(state, Sync01, 0x33);
++	s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity);
++	s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */
++	s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */
++
++	s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */
++	s5h1420_writereg(state, DiS03, 0x00);
++	s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */
+ 
+ 	/* set tuner PLL */
+ 	if (fe->ops.tuner_ops.set_params) {
+ 		fe->ops.tuner_ops.set_params(fe, p);
+-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 0);
+ 		s5h1420_setfreqoffset(state, 0);
+ 	}
+ 
+@@ -661,10 +751,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
+ 	s5h1420_setsymbolrate(state, p);
+ 	s5h1420_setfec_inversion(state, p);
+ 
++	/* start QPSK */
++	s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
++
+ 	state->fec_inner = p->u.qpsk.fec_inner;
+ 	state->symbol_rate = p->u.qpsk.symbol_rate;
+ 	state->postlocked = 0;
+ 	state->tunedfreq = p->frequency;
++
++	dprintk("leave %s\n", __func__);
+ 	return 0;
+ }
+ 
+@@ -717,11 +812,10 @@ static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ 	struct s5h1420_state* state = fe->demodulator_priv;
+ 
+-	if (enable) {
+-		return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+-	} else {
+-		return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
+-	}
++	if (enable)
++		return s5h1420_writereg(state, 0x02, state->CON_1_val | 1);
++	else
++		return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe);
+ }
+ 
+ static int s5h1420_init (struct dvb_frontend* fe)
+@@ -729,7 +823,8 @@ static int s5h1420_init (struct dvb_frontend* fe)
+ 	struct s5h1420_state* state = fe->demodulator_priv;
+ 
+ 	/* disable power down and do reset */
+-	s5h1420_writereg(state, 0x02, 0x10);
++	state->CON_1_val = 0x10;
++	s5h1420_writereg(state, 0x02, state->CON_1_val);
+ 	msleep(10);
+ 	s5h1420_reset(state);
+ 
+@@ -739,26 +834,60 @@ static int s5h1420_init (struct dvb_frontend* fe)
+ static int s5h1420_sleep(struct dvb_frontend* fe)
+ {
+ 	struct s5h1420_state* state = fe->demodulator_priv;
+-
+-	return s5h1420_writereg(state, 0x02, 0x12);
++	state->CON_1_val = 0x12;
++	return s5h1420_writereg(state, 0x02, state->CON_1_val);
+ }
+ 
+ static void s5h1420_release(struct dvb_frontend* fe)
+ {
+ 	struct s5h1420_state* state = fe->demodulator_priv;
++	i2c_del_adapter(&state->tuner_i2c_adapter);
+ 	kfree(state);
+ }
+ 
+-static struct dvb_frontend_ops s5h1420_ops;
++static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
++{
++	return I2C_FUNC_I2C;
++}
++
++static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
++{
++	struct s5h1420_state *state = i2c_get_adapdata(i2c_adap);
++	struct i2c_msg m[1 + num];
++	u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */
++
++	memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
++
++	m[0].addr = state->config->demod_address;
++	m[0].buf  = tx_open;
++	m[0].len  = 2;
+ 
+-struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+-				    struct i2c_adapter* i2c)
++	memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
++
++	return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
++}
++
++static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
++	.master_xfer   = s5h1420_tuner_i2c_tuner_xfer,
++	.functionality = s5h1420_tuner_i2c_func,
++};
++
++struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+ {
+-	struct s5h1420_state* state = NULL;
+-	u8 identity;
++	struct s5h1420_state *state = fe->demodulator_priv;
++	return &state->tuner_i2c_adapter;
++}
++EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
++
++static struct dvb_frontend_ops s5h1420_ops;
+ 
++struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
++				    struct i2c_adapter *i2c)
++{
+ 	/* allocate memory for the internal state */
+-	state = kmalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
++	struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
++	u8 i;
++
+ 	if (state == NULL)
+ 		goto error;
+ 
+@@ -772,24 +901,42 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+ 	state->symbol_rate = 0;
+ 
+ 	/* check if the demod is there + identify it */
+-	identity = s5h1420_readreg(state, 0x00);
+-	if (identity != 0x03)
++	i = s5h1420_readreg(state, ID01);
++	if (i != 0x03)
+ 		goto error;
+ 
++	memset(state->shadow, 0xff, sizeof(state->shadow));
++
++	for (i = 0; i < 0x50; i++)
++		state->shadow[i] = s5h1420_readreg(state, i);
++
+ 	/* create dvb_frontend */
+ 	memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
+ 	state->frontend.demodulator_priv = state;
++
++	/* create tuner i2c adapter */
++	strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE);
++	state->tuner_i2c_adapter.class     = I2C_CLASS_TV_DIGITAL,
++	state->tuner_i2c_adapter.algo      = &s5h1420_tuner_i2c_algo;
++	state->tuner_i2c_adapter.algo_data = NULL;
++	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
++	if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
++		printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n");
++		goto error;
++	}
++
+ 	return &state->frontend;
+ 
+ error:
+ 	kfree(state);
+ 	return NULL;
+ }
++EXPORT_SYMBOL(s5h1420_attach);
+ 
+ static struct dvb_frontend_ops s5h1420_ops = {
+ 
+ 	.info = {
+-		.name     = "Samsung S5H1420 DVB-S",
++		.name     = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
+ 		.type     = FE_QPSK,
+ 		.frequency_min    = 950000,
+ 		.frequency_max    = 2150000,
+@@ -826,10 +973,6 @@ static struct dvb_frontend_ops s5h1420_ops = {
+ 	.set_voltage = s5h1420_set_voltage,
+ };
+ 
+-module_param(debug, int, 0644);
+-
+-MODULE_DESCRIPTION("Samsung S5H1420 DVB-S Demodulator driver");
+-MODULE_AUTHOR("Andrew de Quincey");
++MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
++MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
+ MODULE_LICENSE("GPL");
+-
+-EXPORT_SYMBOL(s5h1420_attach);
+diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
+index 1555870..4c913f1 100644
+--- a/drivers/media/dvb/frontends/s5h1420.h
++++ b/drivers/media/dvb/frontends/s5h1420.h
+@@ -1,25 +1,26 @@
+ /*
+-    Driver for S5H1420 QPSK Demodulators
+-
+-    Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
+-
+-    This program is free software; you can redistribute it and/or modify
+-    it under the terms of the GNU General Public License as published by
+-    the Free Software Foundation; either version 2 of the License, or
+-    (at your option) any later version.
+-
+-    This program is distributed in the hope that it will be useful,
+-    but WITHOUT ANY WARRANTY; without even the implied warranty of
+-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-
+-    GNU General Public License for more details.
+-
+-    You should have received a copy of the GNU General Public License
+-    along with this program; if not, write to the Free Software
+-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-*/
+-
++ * Driver for
++ *    Samsung S5H1420 and
++ *    PnpNetwork PN1010 QPSK Demodulator
++ *
++ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
++ * Copyright (C) 2005-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+ #ifndef S5H1420_H
+ #define S5H1420_H
+ 
+@@ -31,17 +32,26 @@ struct s5h1420_config
+ 	u8 demod_address;
+ 
+ 	/* does the inversion require inversion? */
+-	u8 invert:1;
++	u8 invert : 1;
++
++	u8 repeated_start_workaround : 1;
++	u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */
+ };
+ 
+ #if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
+-extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+-	     struct i2c_adapter* i2c);
++extern struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
++	     struct i2c_adapter *i2c);
++extern struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe);
+ #else
+-static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+-					   struct i2c_adapter* i2c)
++static inline struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
++					   struct i2c_adapter *i2c)
++{
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++	return NULL;
++}
++
++static inline struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_S5H1420
+diff --git a/drivers/media/dvb/frontends/s5h1420_priv.h b/drivers/media/dvb/frontends/s5h1420_priv.h
+new file mode 100644
+index 0000000..d9c58d2
+--- /dev/null
++++ b/drivers/media/dvb/frontends/s5h1420_priv.h
+@@ -0,0 +1,102 @@
++/*
++ * Driver for
++ *    Samsung S5H1420 and
++ *    PnpNetwork PN1010 QPSK Demodulator
++ *
++ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
++ * Copyright (C) 2005 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
++ * Ave, Cambridge, MA 02139, USA.
++ */
++#ifndef S5H1420_PRIV
++#define S5H1420_PRIV
++
++#include <asm/types.h>
++
++enum s5h1420_register {
++	ID01      = 0x00,
++	CON_0     = 0x01,
++	CON_1     = 0x02,
++	PLL01     = 0x03,
++	PLL02     = 0x04,
++	QPSK01    = 0x05,
++	QPSK02    = 0x06,
++	Pre01     = 0x07,
++	Post01    = 0x08,
++	Loop01    = 0x09,
++	Loop02    = 0x0a,
++	Loop03    = 0x0b,
++	Loop04    = 0x0c,
++	Loop05    = 0x0d,
++	Pnco01    = 0x0e,
++	Pnco02    = 0x0f,
++	Pnco03    = 0x10,
++	Tnco01    = 0x11,
++	Tnco02    = 0x12,
++	Tnco03    = 0x13,
++	Monitor01 = 0x14,
++	Monitor02 = 0x15,
++	Monitor03 = 0x16,
++	Monitor04 = 0x17,
++	Monitor05 = 0x18,
++	Monitor06 = 0x19,
++	Monitor07 = 0x1a,
++	Monitor12 = 0x1f,
++
++	FEC01     = 0x22,
++	Soft01    = 0x23,
++	Soft02    = 0x24,
++	Soft03    = 0x25,
++	Soft04    = 0x26,
++	Soft05    = 0x27,
++	Soft06    = 0x28,
++	Vit01     = 0x29,
++	Vit02     = 0x2a,
++	Vit03     = 0x2b,
++	Vit04     = 0x2c,
++	Vit05     = 0x2d,
++	Vit06     = 0x2e,
++	Vit07     = 0x2f,
++	Vit08     = 0x30,
++	Vit09     = 0x31,
++	Vit10     = 0x32,
++	Vit11     = 0x33,
++	Vit12     = 0x34,
++	Sync01    = 0x35,
++	Sync02    = 0x36,
++	Rs01      = 0x37,
++	Mpeg01    = 0x38,
++	Mpeg02    = 0x39,
++	DiS01     = 0x3a,
++	DiS02     = 0x3b,
++	DiS03     = 0x3c,
++	DiS04     = 0x3d,
++	DiS05     = 0x3e,
++	DiS06     = 0x3f,
++	DiS07     = 0x40,
++	DiS08     = 0x41,
++	DiS09     = 0x42,
++	DiS10     = 0x43,
++	DiS11     = 0x44,
++	Rf01      = 0x45,
++	Err01     = 0x46,
++	Err02     = 0x47,
++	Err03     = 0x48,
++	Err04     = 0x49,
++};
++
++
++#endif
+diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
+index da876f7..aa78aa1 100644
+--- a/drivers/media/dvb/frontends/sp8870.c
++++ b/drivers/media/dvb/frontends/sp8870.c
+@@ -70,7 +70,7 @@ static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
+ 	int err;
+ 
+ 	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+-		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
++		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+ 		return -EREMOTEIO;
+ 	}
+ 
+@@ -88,7 +88,7 @@ static int sp8870_readreg (struct sp8870_state* state, u16 reg)
+ 	ret = i2c_transfer (state->i2c, msg, 2);
+ 
+ 	if (ret != 2) {
+-		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+ 		return -1;
+ 	}
+ 
+@@ -104,7 +104,7 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
+ 	int tx_len;
+ 	int err = 0;
+ 
+-	dprintk ("%s: ...\n", __FUNCTION__);
++	dprintk ("%s: ...\n", __func__);
+ 
+ 	if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
+ 		return -EINVAL;
+@@ -131,14 +131,14 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
+ 		msg.buf = tx_buf;
+ 		msg.len = tx_len + 2;
+ 		if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+-			printk("%s: firmware upload failed!\n", __FUNCTION__);
+-			printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
++			printk("%s: firmware upload failed!\n", __func__);
++			printk ("%s: i2c error (err == %i)\n", __func__, err);
+ 			return err;
+ 		}
+ 		fw_pos += tx_len;
+ 	}
+ 
+-	dprintk ("%s: done!\n", __FUNCTION__);
++	dprintk ("%s: done!\n", __func__);
+ 	return 0;
+ };
+ 
+@@ -310,7 +310,7 @@ static int sp8870_init (struct dvb_frontend* fe)
+ 	if (state->initialised) return 0;
+ 	state->initialised = 1;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 
+ 	/* request the firmware, this will block until someone uploads it */
+@@ -449,15 +449,15 @@ static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks
+ 	return 0;
+ }
+ 
+-// number of trials to recover from lockup
++/* number of trials to recover from lockup */
+ #define MAXTRIALS 5
+-// maximum checks for data valid signal
++/* maximum checks for data valid signal */
+ #define MAXCHECKS 100
+ 
+-// only for debugging: counter for detected lockups
+-static int lockups = 0;
+-// only for debugging: counter for channel switches
+-static int switches = 0;
++/* only for debugging: counter for detected lockups */
++static int lockups;
++/* only for debugging: counter for channel switches */
++static int switches;
+ 
+ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+ {
+@@ -475,7 +475,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
+ 	int trials = 0;
+ 	int check_count = 0;
+ 
+-	dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
++	dprintk("%s: frequency = %i\n", __func__, p->frequency);
+ 
+ 	for (trials = 1; trials <= MAXTRIALS; trials++) {
+ 
+@@ -487,7 +487,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
+ 			valid = sp8870_read_data_valid_signal(state);
+ 			if (valid) {
+ 				dprintk("%s: delay = %i usec\n",
+-					__FUNCTION__, check_count * 10);
++					__func__, check_count * 10);
+ 				break;
+ 			}
+ 			udelay(10);
+@@ -497,20 +497,20 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
+ 	}
+ 
+ 	if (!valid) {
+-		printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
++		printk("%s: firmware crash!!!!!!\n", __func__);
+ 		return -EIO;
+ 	}
+ 
+ 	if (debug) {
+ 		if (valid) {
+ 			if (trials > 1) {
+-				printk("%s: firmware lockup!!!\n", __FUNCTION__);
+-				printk("%s: recovered after %i trial(s))\n",  __FUNCTION__, trials - 1);
++				printk("%s: firmware lockup!!!\n", __func__);
++				printk("%s: recovered after %i trial(s))\n",  __func__, trials - 1);
+ 				lockups++;
+ 			}
+ 		}
+ 		switches++;
+-		printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
++		printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
+ 	}
+ 
+ 	return 0;
+diff --git a/drivers/media/dvb/frontends/sp8870.h b/drivers/media/dvb/frontends/sp8870.h
+index 909cefe..a764a79 100644
+--- a/drivers/media/dvb/frontends/sp8870.h
++++ b/drivers/media/dvb/frontends/sp8870.h
+@@ -42,7 +42,7 @@ extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+ static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+ 					  struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_SP8870
+diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
+index 1aa2539..49f5587 100644
+--- a/drivers/media/dvb/frontends/sp887x.c
++++ b/drivers/media/dvb/frontends/sp887x.c
+@@ -43,7 +43,7 @@ static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len)
+ 
+ 	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ 		printk ("%s: i2c write error (addr %02x, err == %i)\n",
+-			__FUNCTION__, state->config->demod_address, err);
++			__func__, state->config->demod_address, err);
+ 		return -EREMOTEIO;
+ 	}
+ 
+@@ -65,7 +65,7 @@ static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data)
+ 		{
+ 			printk("%s: writereg error "
+ 			       "(reg %03x, data %03x, ret == %i)\n",
+-			       __FUNCTION__, reg & 0xffff, data & 0xffff, ret);
++			       __func__, reg & 0xffff, data & 0xffff, ret);
+ 			return ret;
+ 		}
+ 	}
+@@ -82,7 +82,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
+ 			 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
+ 
+ 	if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+-		printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++		printk("%s: readreg error (ret == %i)\n", __func__, ret);
+ 		return -1;
+ 	}
+ 
+@@ -91,7 +91,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
+ 
+ static void sp887x_microcontroller_stop (struct sp887x_state* state)
+ {
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 	sp887x_writereg(state, 0xf08, 0x000);
+ 	sp887x_writereg(state, 0xf09, 0x000);
+ 
+@@ -101,7 +101,7 @@ static void sp887x_microcontroller_stop (struct sp887x_state* state)
+ 
+ static void sp887x_microcontroller_start (struct sp887x_state* state)
+ {
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 	sp887x_writereg(state, 0xf08, 0x000);
+ 	sp887x_writereg(state, 0xf09, 0x000);
+ 
+@@ -112,7 +112,7 @@ static void sp887x_microcontroller_start (struct sp887x_state* state)
+ static void sp887x_setup_agc (struct sp887x_state* state)
+ {
+ 	/* setup AGC parameters */
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 	sp887x_writereg(state, 0x33c, 0x054);
+ 	sp887x_writereg(state, 0x33b, 0x04c);
+ 	sp887x_writereg(state, 0x328, 0x000);
+@@ -142,7 +142,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
+ 	int fw_size = fw->size;
+ 	unsigned char *mem = fw->data;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	/* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */
+ 	if (fw_size < FW_SIZE+10)
+@@ -155,7 +155,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
+ 
+ 	sp887x_microcontroller_stop (state);
+ 
+-	printk ("%s: firmware upload... ", __FUNCTION__);
++	printk ("%s: firmware upload... ", __func__);
+ 
+ 	/* setup write pointer to -1 (end of memory) */
+ 	/* bit 0x8000 in address is set to enable 13bit mode */
+@@ -181,7 +181,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
+ 
+ 		if ((err = i2c_writebytes (state, buf, c+2)) < 0) {
+ 			printk ("failed.\n");
+-			printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
++			printk ("%s: i2c error (err == %i)\n", __func__, err);
+ 			return err;
+ 		}
+ 	}
+diff --git a/drivers/media/dvb/frontends/sp887x.h b/drivers/media/dvb/frontends/sp887x.h
+index 7ee78d7..04eff6e 100644
+--- a/drivers/media/dvb/frontends/sp887x.h
++++ b/drivers/media/dvb/frontends/sp887x.h
+@@ -24,7 +24,7 @@ extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
+ static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
+ 					  struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_SP887X
+diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
+index 7c23775..62caf80 100644
+--- a/drivers/media/dvb/frontends/stv0297.c
++++ b/drivers/media/dvb/frontends/stv0297.c
+@@ -58,7 +58,7 @@ static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
+ 
+ 	if (ret != 1)
+ 		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+-			"ret == %i)\n", __FUNCTION__, reg, data, ret);
++			"ret == %i)\n", __func__, reg, data, ret);
+ 
+ 	return (ret != 1) ? -1 : 0;
+ }
+@@ -75,16 +75,16 @@ static int stv0297_readreg(struct stv0297_state *state, u8 reg)
+ 	// this device needs a STOP between the register and data
+ 	if (state->config->stop_during_read) {
+ 		if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
++			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
+ 			return -1;
+ 		}
+ 		if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
++			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
+ 			return -1;
+ 		}
+ 	} else {
+ 		if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
++			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
+ 			return -1;
+ 		}
+ 	}
+@@ -115,16 +115,16 @@ static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len
+ 	// this device needs a STOP between the register and data
+ 	if (state->config->stop_during_read) {
+ 		if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
++			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
+ 			return -1;
+ 		}
+ 		if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
++			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
+ 			return -1;
+ 		}
+ 	} else {
+ 		if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
++			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
+ 			return -1;
+ 		}
+ 	}
+diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h
+index 69f4515..3f8f946 100644
+--- a/drivers/media/dvb/frontends/stv0297.h
++++ b/drivers/media/dvb/frontends/stv0297.h
+@@ -49,7 +49,7 @@ extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
+ static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_STV0297
+diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
+index 035dd7b..1755618 100644
+--- a/drivers/media/dvb/frontends/stv0299.c
++++ b/drivers/media/dvb/frontends/stv0299.c
+@@ -86,7 +86,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
+ 
+ 	if (ret != 1)
+ 		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+-			"ret == %i)\n", __FUNCTION__, reg, data, ret);
++			"ret == %i)\n", __func__, reg, data, ret);
+ 
+ 	return (ret != 1) ? -EREMOTEIO : 0;
+ }
+@@ -113,7 +113,7 @@ static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
+ 
+ 	if (ret != 2)
+ 		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+-				__FUNCTION__, reg, ret);
++				__func__, reg, ret);
+ 
+ 	return b1[0];
+ }
+@@ -127,14 +127,14 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
+ 	ret = i2c_transfer (state->i2c, msg, 2);
+ 
+ 	if (ret != 2)
+-		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+ 
+ 	return ret == 2 ? 0 : ret;
+ }
+ 
+ static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
+ {
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	switch (fec) {
+ 	case FEC_AUTO:
+@@ -174,7 +174,7 @@ static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
+ 					     FEC_7_8, FEC_1_2 };
+ 	u8 index;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	index = stv0299_readreg (state, 0x1b);
+ 	index &= 0x7;
+@@ -189,11 +189,11 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
+ {
+ 	unsigned long start = jiffies;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	while (stv0299_readreg(state, 0x0a) & 1) {
+ 		if (jiffies - start > timeout) {
+-			dprintk ("%s: timeout!!\n", __FUNCTION__);
++			dprintk ("%s: timeout!!\n", __func__);
+ 			return -ETIMEDOUT;
+ 		}
+ 		msleep(10);
+@@ -206,11 +206,11 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
+ {
+ 	unsigned long start = jiffies;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) {
+ 		if (jiffies - start > timeout) {
+-			dprintk ("%s: timeout!!\n", __FUNCTION__);
++			dprintk ("%s: timeout!!\n", __func__);
+ 			return -ETIMEDOUT;
+ 		}
+ 		msleep(10);
+@@ -245,7 +245,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
+ 	u8 sfr[3];
+ 	s8 rtf;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	stv0299_readregs (state, 0x1f, sfr, 3);
+ 	stv0299_readregs (state, 0x1a, (u8 *)&rtf, 1);
+@@ -257,8 +257,8 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
+ 	offset = (s32) rtf * (srate / 4096L);
+ 	offset /= 128;
+ 
+-	dprintk ("%s : srate = %i\n", __FUNCTION__, srate);
+-	dprintk ("%s : ofset = %i\n", __FUNCTION__, offset);
++	dprintk ("%s : srate = %i\n", __func__, srate);
++	dprintk ("%s : ofset = %i\n", __func__, offset);
+ 
+ 	srate += offset;
+ 
+@@ -276,7 +276,7 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
+ 	u8 val;
+ 	int i;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (stv0299_wait_diseqc_idle (state, 100) < 0)
+ 		return -ETIMEDOUT;
+@@ -305,7 +305,7 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t
+ 	struct stv0299_state* state = fe->demodulator_priv;
+ 	u8 val;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (stv0299_wait_diseqc_idle (state, 100) < 0)
+ 		return -ETIMEDOUT;
+@@ -355,7 +355,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
+ 	u8 reg0x08;
+ 	u8 reg0x0c;
+ 
+-	dprintk("%s: %s\n", __FUNCTION__,
++	dprintk("%s: %s\n", __func__,
+ 		voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+ 		voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+ 
+@@ -366,26 +366,32 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
+ 	 *  H/V switching over OP0, OP1 and OP2 are LNB power enable bits
+ 	 */
+ 	reg0x0c &= 0x0f;
+-
+-	if (voltage == SEC_VOLTAGE_OFF) {
+-		stv0299_writeregI (state, 0x0c, 0x00); /*	LNB power off! */
+-		return stv0299_writeregI (state, 0x08, 0x00); /*	LNB power off! */
+-	}
+-
+-	stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6));
++	reg0x08 = (reg0x08 & 0x3f) | (state->config->lock_output << 6);
+ 
+ 	switch (voltage) {
+ 	case SEC_VOLTAGE_13:
+-		if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) reg0x0c |= 0x10;
+-		else reg0x0c |= 0x40;
+-
+-		return stv0299_writeregI(state, 0x0c, reg0x0c);
+-
++		if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
++			reg0x0c |= 0x10; /* OP1 off, OP0 on */
++		else
++			reg0x0c |= 0x40; /* OP1 on, OP0 off */
++		break;
+ 	case SEC_VOLTAGE_18:
+-		return stv0299_writeregI(state, 0x0c, reg0x0c | 0x50);
++		reg0x0c |= 0x50; /* OP1 on, OP0 on */
++		break;
++	case SEC_VOLTAGE_OFF:
++		/* LNB power off! */
++		reg0x08 = 0x00;
++		reg0x0c = 0x00;
++		break;
+ 	default:
+ 		return -EINVAL;
+ 	};
++
++	if (state->config->op0_off)
++		reg0x0c &= ~0x10;
++
++	stv0299_writeregI(state, 0x08, reg0x08);
++	return stv0299_writeregI(state, 0x0c, reg0x0c);
+ }
+ 
+ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
+@@ -408,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
+ 
+ 	cmd = cmd << 1;
+ 	if (debug_legacy_dish_switch)
+-		printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
++		printk ("%s switch command: 0x%04lx\n",__func__, cmd);
+ 
+ 	do_gettimeofday (&nexttime);
+ 	if (debug_legacy_dish_switch)
+@@ -433,7 +439,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
+ 	}
+ 	if (debug_legacy_dish_switch) {
+ 		printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
+-			__FUNCTION__, fe->dvb->num);
++			__func__, fe->dvb->num);
+ 		for (i = 1; i < 10; i++)
+ 			printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+ 	}
+@@ -445,11 +451,20 @@ static int stv0299_init (struct dvb_frontend* fe)
+ {
+ 	struct stv0299_state* state = fe->demodulator_priv;
+ 	int i;
++	u8 reg;
++	u8 val;
+ 
+ 	dprintk("stv0299: init chip\n");
+ 
+-	for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
+-		stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]);
++	for (i = 0; ; i += 2)  {
++		reg = state->config->inittab[i];
++		val = state->config->inittab[i+1];
++		if (reg == 0xff && val == 0xff)
++			break;
++		if (reg == 0x0c && state->config->op0_off)
++			val &= ~0x10;
++		stv0299_writeregI(state, reg, val);
++	}
+ 
+ 	return 0;
+ }
+@@ -461,7 +476,7 @@ static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 	u8 signal = 0xff - stv0299_readreg (state, 0x18);
+ 	u8 sync = stv0299_readreg (state, 0x1b);
+ 
+-	dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
++	dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
+ 	*status = 0;
+ 
+ 	if (signal > 10)
+@@ -499,7 +514,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+ 	s32 signal =  0xffff - ((stv0299_readreg (state, 0x18) << 8)
+ 			       | stv0299_readreg (state, 0x19));
+ 
+-	dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
++	dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__,
+ 		 stv0299_readreg (state, 0x18),
+ 		 stv0299_readreg (state, 0x19), (int) signal);
+ 
+@@ -536,7 +551,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
+ 	struct stv0299_state* state = fe->demodulator_priv;
+ 	int invval = 0;
+ 
+-	dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
++	dprintk ("%s : FE_SET_FRONTEND\n", __func__);
+ 
+ 	// set the inversion
+ 	if (p->inversion == INVERSION_OFF) invval = 0;
+diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
+index 33df949..3282f43 100644
+--- a/drivers/media/dvb/frontends/stv0299.h
++++ b/drivers/media/dvb/frontends/stv0299.h
+@@ -48,10 +48,10 @@
+ #include <linux/dvb/frontend.h>
+ #include "dvb_frontend.h"
+ 
+-#define STV0229_LOCKOUTPUT_0  0
+-#define STV0229_LOCKOUTPUT_1  1
+-#define STV0229_LOCKOUTPUT_CF 2
+-#define STV0229_LOCKOUTPUT_LK 3
++#define STV0299_LOCKOUTPUT_0  0
++#define STV0299_LOCKOUTPUT_1  1
++#define STV0299_LOCKOUTPUT_CF 2
++#define STV0299_LOCKOUTPUT_LK 3
+ 
+ #define STV0299_VOLT13_OP0 0
+ #define STV0299_VOLT13_OP1 1
+@@ -82,6 +82,9 @@ struct stv0299_config
+ 	/* Is 13v controlled by OP0 or OP1? */
+ 	u8 volt13_op0_op1:1;
+ 
++	/* Turn-off OP0? */
++	u8 op0_off:1;
++
+ 	/* minimum delay before retuning */
+ 	int min_delay_ms;
+ 
+@@ -96,7 +99,7 @@ extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
+ static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_STV0299
+diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
+index 45137d2..f648fdb 100644
+--- a/drivers/media/dvb/frontends/tda10021.c
++++ b/drivers/media/dvb/frontends/tda10021.c
+@@ -79,7 +79,7 @@ static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
+ 	if (ret != 1)
+ 		printk("DVB: TDA10021(%d): %s, writereg error "
+ 			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+-			state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
++			state->frontend.dvb->num, __func__, reg, data, ret);
+ 
+ 	msleep(10);
+ 	return (ret != 1) ? -EREMOTEIO : 0;
+@@ -97,7 +97,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
+ 	// Don't print an error message if the id is read.
+ 	if (ret != 2 && reg != 0x1a)
+ 		printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
+-				__FUNCTION__, ret);
++				__func__, ret);
+ 	return b1[0];
+ }
+ 
+diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c
+index 364bc01..0727b80 100644
+--- a/drivers/media/dvb/frontends/tda10023.c
++++ b/drivers/media/dvb/frontends/tda10023.c
+@@ -118,7 +118,7 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
+ 	ret = i2c_transfer (state->i2c, msg, 2);
+ 	if (ret != 2)
+ 		printk("DVB: TDA10023: %s: readreg error (ret == %i)\n",
+-				 __FUNCTION__, ret);
++				 __func__, ret);
+ 	return b1[0];
+ }
+ 
+@@ -132,7 +132,7 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
+ 	if (ret != 1)
+ 		printk("DVB: TDA10023(%d): %s, writereg error "
+ 			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+-			state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
++			state->frontend.dvb->num, __func__, reg, data, ret);
+ 
+ 	return (ret != 1) ? -EREMOTEIO : 0;
+ }
+diff --git a/drivers/media/dvb/frontends/tda1002x.h b/drivers/media/dvb/frontends/tda1002x.h
+index e9094d8..1bcc0d4 100644
+--- a/drivers/media/dvb/frontends/tda1002x.h
++++ b/drivers/media/dvb/frontends/tda1002x.h
+@@ -40,7 +40,7 @@ extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config
+ static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
+ 					    struct i2c_adapter* i2c, u8 pwm)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TDA10021
+@@ -52,7 +52,7 @@ extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config
+ static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
+ 					    struct i2c_adapter* i2c, u8 pwm)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TDA10023
+diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
+new file mode 100644
+index 0000000..090fb7d
+--- /dev/null
++++ b/drivers/media/dvb/frontends/tda10048.c
+@@ -0,0 +1,841 @@
++/*
++    NXP TDA10048HN DVB OFDM demodulator driver
++
++    Copyright (C) 2008 Steven Toth <stoth at hauppauge.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/init.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include "dvb_frontend.h"
++#include "dvb_math.h"
++#include "tda10048.h"
++
++#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
++#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878
++
++/* Register name definitions */
++#define TDA10048_IDENTITY          0x00
++#define TDA10048_VERSION           0x01
++#define TDA10048_DSP_CODE_CPT      0x0C
++#define TDA10048_DSP_CODE_IN       0x0E
++#define TDA10048_IN_CONF1          0x10
++#define TDA10048_IN_CONF2          0x11
++#define TDA10048_IN_CONF3          0x12
++#define TDA10048_OUT_CONF1         0x14
++#define TDA10048_OUT_CONF2         0x15
++#define TDA10048_OUT_CONF3         0x16
++#define TDA10048_AUTO              0x18
++#define TDA10048_SYNC_STATUS       0x1A
++#define TDA10048_CONF_C4_1         0x1E
++#define TDA10048_CONF_C4_2         0x1F
++#define TDA10048_CODE_IN_RAM       0x20
++#define TDA10048_CHANNEL_INFO_1_R  0x22
++#define TDA10048_CHANNEL_INFO_2_R  0x23
++#define TDA10048_CHANNEL_INFO1     0x24
++#define TDA10048_CHANNEL_INFO2     0x25
++#define TDA10048_TIME_ERROR_R      0x26
++#define TDA10048_TIME_ERROR        0x27
++#define TDA10048_FREQ_ERROR_LSB_R  0x28
++#define TDA10048_FREQ_ERROR_MSB_R  0x29
++#define TDA10048_FREQ_ERROR_LSB    0x2A
++#define TDA10048_FREQ_ERROR_MSB    0x2B
++#define TDA10048_IT_SEL            0x30
++#define TDA10048_IT_STAT           0x32
++#define TDA10048_DSP_AD_LSB        0x3C
++#define TDA10048_DSP_AD_MSB        0x3D
++#define TDA10048_DSP_REF_LSB       0x3E
++#define TDA10048_DSP_REF_MSB       0x3F
++#define TDA10048_CONF_TRISTATE1    0x44
++#define TDA10048_CONF_TRISTATE2    0x45
++#define TDA10048_CONF_POLARITY     0x46
++#define TDA10048_GPIO_SP_DS0       0x48
++#define TDA10048_GPIO_SP_DS1       0x49
++#define TDA10048_GPIO_SP_DS2       0x4A
++#define TDA10048_GPIO_SP_DS3       0x4B
++#define TDA10048_GPIO_OUT_SEL      0x4C
++#define TDA10048_GPIO_SELECT       0x4D
++#define TDA10048_IC_MODE           0x4E
++#define TDA10048_CONF_XO           0x50
++#define TDA10048_CONF_PLL1         0x51
++#define TDA10048_CONF_PLL2         0x52
++#define TDA10048_CONF_PLL3         0x53
++#define TDA10048_CONF_ADC          0x54
++#define TDA10048_CONF_ADC_2        0x55
++#define TDA10048_CONF_C1_1         0x60
++#define TDA10048_CONF_C1_3         0x62
++#define TDA10048_AGC_CONF          0x70
++#define TDA10048_AGC_THRESHOLD_LSB 0x72
++#define TDA10048_AGC_THRESHOLD_MSB 0x73
++#define TDA10048_AGC_RENORM        0x74
++#define TDA10048_AGC_GAINS         0x76
++#define TDA10048_AGC_TUN_MIN       0x78
++#define TDA10048_AGC_TUN_MAX       0x79
++#define TDA10048_AGC_IF_MIN        0x7A
++#define TDA10048_AGC_IF_MAX        0x7B
++#define TDA10048_AGC_TUN_LEVEL     0x7E
++#define TDA10048_AGC_IF_LEVEL      0x7F
++#define TDA10048_DIG_AGC_LEVEL     0x81
++#define TDA10048_FREQ_PHY2_LSB     0x86
++#define TDA10048_FREQ_PHY2_MSB     0x87
++#define TDA10048_TIME_INVWREF_LSB  0x88
++#define TDA10048_TIME_INVWREF_MSB  0x89
++#define TDA10048_TIME_WREF_LSB     0x8A
++#define TDA10048_TIME_WREF_MID1    0x8B
++#define TDA10048_TIME_WREF_MID2    0x8C
++#define TDA10048_TIME_WREF_MSB     0x8D
++#define TDA10048_NP_OUT            0xA2
++#define TDA10048_CELL_ID_LSB       0xA4
++#define TDA10048_CELL_ID_MSB       0xA5
++#define TDA10048_EXTTPS_ODD        0xAA
++#define TDA10048_EXTTPS_EVEN       0xAB
++#define TDA10048_TPS_LENGTH        0xAC
++#define TDA10048_FREE_REG_1        0xB2
++#define TDA10048_FREE_REG_2        0xB3
++#define TDA10048_CONF_C3_1         0xC0
++#define TDA10048_CYBER_CTRL        0xC2
++#define TDA10048_CBER_NMAX_LSB     0xC4
++#define TDA10048_CBER_NMAX_MSB     0xC5
++#define TDA10048_CBER_LSB          0xC6
++#define TDA10048_CBER_MSB          0xC7
++#define TDA10048_VBER_LSB          0xC8
++#define TDA10048_VBER_MID          0xC9
++#define TDA10048_VBER_MSB          0xCA
++#define TDA10048_CYBER_LUT         0xCC
++#define TDA10048_UNCOR_CTRL        0xCD
++#define TDA10048_UNCOR_CPT_LSB     0xCE
++#define TDA10048_UNCOR_CPT_MSB     0xCF
++#define TDA10048_SOFT_IT_C3        0xD6
++#define TDA10048_CONF_TS2          0xE0
++#define TDA10048_CONF_TS1          0xE1
++
++static unsigned int debug;
++
++#define dprintk(level, fmt, arg...)\
++	do { if (debug >= level)\
++		printk(KERN_DEBUG "tda10048: " fmt, ## arg);\
++	} while (0)
++
++struct tda10048_state {
++
++	struct i2c_adapter *i2c;
++
++	/* configuration settings */
++	const struct tda10048_config *config;
++	struct dvb_frontend frontend;
++
++	int fwloaded;
++};
++
++static struct init_tab {
++	u8	reg;
++	u16	data;
++} init_tab[] = {
++	{ TDA10048_CONF_PLL1, 0x08 },
++	{ TDA10048_CONF_ADC_2, 0x00 },
++	{ TDA10048_CONF_C4_1, 0x00 },
++	{ TDA10048_CONF_PLL1, 0x0f },
++	{ TDA10048_CONF_PLL2, 0x0a },
++	{ TDA10048_CONF_PLL3, 0x43 },
++	{ TDA10048_FREQ_PHY2_LSB, 0x02 },
++	{ TDA10048_FREQ_PHY2_MSB, 0x0a },
++	{ TDA10048_TIME_WREF_LSB, 0xbd },
++	{ TDA10048_TIME_WREF_MID1, 0xe4 },
++	{ TDA10048_TIME_WREF_MID2, 0xa8 },
++	{ TDA10048_TIME_WREF_MSB, 0x02 },
++	{ TDA10048_TIME_INVWREF_LSB, 0x04 },
++	{ TDA10048_TIME_INVWREF_MSB, 0x06 },
++	{ TDA10048_CONF_C4_1, 0x00 },
++	{ TDA10048_CONF_C1_1, 0xa8 },
++	{ TDA10048_AGC_CONF, 0x16 },
++	{ TDA10048_CONF_C1_3, 0x0b },
++	{ TDA10048_AGC_TUN_MIN, 0x00 },
++	{ TDA10048_AGC_TUN_MAX, 0xff },
++	{ TDA10048_AGC_IF_MIN, 0x00 },
++	{ TDA10048_AGC_IF_MAX, 0xff },
++	{ TDA10048_AGC_THRESHOLD_MSB, 0x00 },
++	{ TDA10048_AGC_THRESHOLD_LSB, 0x70 },
++	{ TDA10048_CYBER_CTRL, 0x38 },
++	{ TDA10048_AGC_GAINS, 0x12 },
++	{ TDA10048_CONF_XO, 0x00 },
++	{ TDA10048_CONF_TS1, 0x07 },
++	{ TDA10048_IC_MODE, 0x00 },
++	{ TDA10048_CONF_TS2, 0xc0 },
++	{ TDA10048_CONF_TRISTATE1, 0x21 },
++	{ TDA10048_CONF_TRISTATE2, 0x00 },
++	{ TDA10048_CONF_POLARITY, 0x00 },
++	{ TDA10048_CONF_C4_2, 0x04 },
++	{ TDA10048_CONF_ADC, 0x60 },
++	{ TDA10048_CONF_ADC_2, 0x10 },
++	{ TDA10048_CONF_ADC, 0x60 },
++	{ TDA10048_CONF_ADC_2, 0x00 },
++	{ TDA10048_CONF_C1_1, 0xa8 },
++	{ TDA10048_UNCOR_CTRL, 0x00 },
++	{ TDA10048_CONF_C4_2, 0x04 },
++};
++
++static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
++{
++	int ret;
++	u8 buf [] = { reg, data };
++	struct i2c_msg msg = {
++		.addr = state->config->demod_address,
++		.flags = 0, .buf = buf, .len = 2 };
++
++	dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
++
++	ret = i2c_transfer(state->i2c, &msg, 1);
++
++	if (ret != 1)
++		printk("%s: writereg error (ret == %i)\n", __func__, ret);
++
++	return (ret != 1) ? -1 : 0;
++}
++
++static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
++{
++	int ret;
++	u8 b0 [] = { reg };
++	u8 b1 [] = { 0 };
++	struct i2c_msg msg [] = {
++		{ .addr = state->config->demod_address,
++			.flags = 0, .buf = b0, .len = 1 },
++		{ .addr = state->config->demod_address,
++			.flags = I2C_M_RD, .buf = b1, .len = 1 } };
++
++	dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
++
++	ret = i2c_transfer(state->i2c, msg, 2);
++
++	if (ret != 2)
++		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
++			__func__, ret);
++
++	return b1[0];
++}
++
++static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
++	u8 *data, u16 len)
++{
++	int ret = -EREMOTEIO;
++	struct i2c_msg msg;
++	u8 *buf;
++
++	dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len);
++
++	buf = kmalloc(len + 1, GFP_KERNEL);
++	if (buf == NULL) {
++		ret = -ENOMEM;
++		goto error;
++	}
++
++	*buf = reg;
++	memcpy(buf + 1, data, len);
++
++	msg.addr = state->config->demod_address;
++	msg.flags = 0;
++	msg.buf = buf;
++	msg.len = len + 1;
++
++	dprintk(2, "%s():  write len = %d\n",
++		__func__, msg.len);
++
++	ret = i2c_transfer(state->i2c, &msg, 1);
++	if (ret != 1) {
++		printk(KERN_ERR "%s(): writereg error err %i\n",
++			 __func__, ret);
++		ret = -EREMOTEIO;
++	}
++
++error:
++	kfree(buf);
++
++	return ret;
++}
++
++static int tda10048_firmware_upload(struct dvb_frontend *fe)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++	const struct firmware *fw;
++	int ret;
++	int pos = 0;
++	int cnt;
++	u8 wlen = state->config->fwbulkwritelen;
++
++	if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
++		wlen = TDA10048_BULKWRITE_200;
++
++	/* request the firmware, this will block and timeout */
++	printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n",
++		__func__,
++		TDA10048_DEFAULT_FIRMWARE);
++
++	ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE,
++		&state->i2c->dev);
++	if (ret) {
++		printk(KERN_ERR "%s: Upload failed. (file not found?)\n",
++			__func__);
++		return -EIO;
++	} else {
++		printk(KERN_INFO "%s: firmware read %Zu bytes.\n",
++			__func__,
++			fw->size);
++		ret = 0;
++	}
++
++	if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) {
++		printk(KERN_ERR "%s: firmware incorrect size\n", __func__);
++		return -EIO;
++	} else {
++		printk(KERN_INFO "%s: firmware uploading\n", __func__);
++
++		/* Soft reset */
++		tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
++			tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
++				& 0xfe);
++		tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
++			tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
++				| 0x01);
++
++		/* Put the demod into host download mode */
++		tda10048_writereg(state, TDA10048_CONF_C4_1,
++			tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9);
++
++		/* Boot the DSP */
++		tda10048_writereg(state, TDA10048_CONF_C4_1,
++			tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08);
++
++		/* Prepare for download */
++		tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0);
++
++		/* Download the firmware payload */
++		while (pos < fw->size) {
++
++			if ((fw->size - pos) > wlen)
++				cnt = wlen;
++			else
++				cnt = fw->size - pos;
++
++			tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN,
++				&fw->data[pos], cnt);
++
++			pos += cnt;
++		}
++
++		ret = -EIO;
++		/* Wait up to 250ms for the DSP to boot */
++		for (cnt = 0; cnt < 250 ; cnt += 10) {
++
++			msleep(10);
++
++			if (tda10048_readreg(state, TDA10048_SYNC_STATUS)
++				& 0x40) {
++				ret = 0;
++				break;
++			}
++		}
++	}
++
++	release_firmware(fw);
++
++	if (ret == 0) {
++		printk(KERN_INFO "%s: firmware uploaded\n", __func__);
++		state->fwloaded = 1;
++	} else
++		printk(KERN_ERR "%s: firmware upload failed\n", __func__);
++
++	return ret;
++}
++
++static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++
++	dprintk(1, "%s(%d)\n", __func__, inversion);
++
++	if (inversion == TDA10048_INVERSION_ON)
++		tda10048_writereg(state, TDA10048_CONF_C1_1,
++			tda10048_readreg(state, TDA10048_CONF_C1_1) | 0x20);
++	else
++		tda10048_writereg(state, TDA10048_CONF_C1_1,
++			tda10048_readreg(state, TDA10048_CONF_C1_1) & 0xdf);
++
++	return 0;
++}
++
++/* Retrieve the demod settings */
++static int tda10048_get_tps(struct tda10048_state *state,
++	struct dvb_ofdm_parameters *p)
++{
++	u8 val;
++
++	/* Make sure the TPS regs are valid */
++	if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01))
++		return -EAGAIN;
++
++	val = tda10048_readreg(state, TDA10048_OUT_CONF2);
++	switch ((val & 0x60) >> 5) {
++	case 0: p->constellation =   QPSK; break;
++	case 1: p->constellation = QAM_16; break;
++	case 2: p->constellation = QAM_64; break;
++	}
++	switch ((val & 0x18) >> 3) {
++	case 0: p->hierarchy_information = HIERARCHY_NONE; break;
++	case 1: p->hierarchy_information =    HIERARCHY_1; break;
++	case 2: p->hierarchy_information =    HIERARCHY_2; break;
++	case 3: p->hierarchy_information =    HIERARCHY_4; break;
++	}
++	switch (val & 0x07) {
++	case 0: p->code_rate_HP = FEC_1_2; break;
++	case 1: p->code_rate_HP = FEC_2_3; break;
++	case 2: p->code_rate_HP = FEC_3_4; break;
++	case 3: p->code_rate_HP = FEC_5_6; break;
++	case 4: p->code_rate_HP = FEC_7_8; break;
++	}
++
++	val = tda10048_readreg(state, TDA10048_OUT_CONF3);
++	switch (val & 0x07) {
++	case 0: p->code_rate_LP = FEC_1_2; break;
++	case 1: p->code_rate_LP = FEC_2_3; break;
++	case 2: p->code_rate_LP = FEC_3_4; break;
++	case 3: p->code_rate_LP = FEC_5_6; break;
++	case 4: p->code_rate_LP = FEC_7_8; break;
++	}
++
++	val = tda10048_readreg(state, TDA10048_OUT_CONF1);
++	switch ((val & 0x0c) >> 2) {
++	case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
++	case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
++	case 2: p->guard_interval =  GUARD_INTERVAL_1_8; break;
++	case 3: p->guard_interval =  GUARD_INTERVAL_1_4; break;
++	}
++	switch (val & 0x02) {
++	case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
++	case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
++	}
++
++	return 0;
++}
++
++static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++	dprintk(1, "%s(%d)\n", __func__, enable);
++
++	if (enable)
++		return tda10048_writereg(state, TDA10048_CONF_C4_1,
++			tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02);
++	else
++		return tda10048_writereg(state, TDA10048_CONF_C4_1,
++			tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd);
++}
++
++static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++	dprintk(1, "%s(%d)\n", __func__, serial);
++
++	/* Ensure pins are out of tri-state */
++	tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21);
++	tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00);
++
++	if (serial) {
++		tda10048_writereg(state, TDA10048_IC_MODE, 0x80 | 0x20);
++		tda10048_writereg(state, TDA10048_CONF_TS2, 0xc0);
++	} else {
++		tda10048_writereg(state, TDA10048_IC_MODE, 0x00);
++		tda10048_writereg(state, TDA10048_CONF_TS2, 0x01);
++	}
++
++	return 0;
++}
++
++/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
++/* TODO: Support manual tuning with specific params */
++static int tda10048_set_frontend(struct dvb_frontend *fe,
++	struct dvb_frontend_parameters *p)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++
++	dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
++
++	if (fe->ops.tuner_ops.set_params) {
++
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 1);
++
++		fe->ops.tuner_ops.set_params(fe, p);
++
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 0);
++	}
++
++	/* Enable demod TPS auto detection and begin acquisition */
++	tda10048_writereg(state, TDA10048_AUTO, 0x57);
++
++	return 0;
++}
++
++/* Establish sane defaults and load firmware. */
++static int tda10048_init(struct dvb_frontend *fe)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++	int ret = 0, i;
++
++	dprintk(1, "%s()\n", __func__);
++
++	/* Apply register defaults */
++	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
++		tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
++
++	if (state->fwloaded == 0)
++		ret = tda10048_firmware_upload(fe);
++
++	/* Set either serial or parallel */
++	tda10048_output_mode(fe, state->config->output_mode);
++
++	/* set inversion */
++	tda10048_set_inversion(fe, state->config->inversion);
++
++	/* Ensure we leave the gate closed */
++	tda10048_i2c_gate_ctrl(fe, 0);
++
++	return ret;
++}
++
++static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++	u8 reg;
++
++	*status = 0;
++
++	reg = tda10048_readreg(state, TDA10048_SYNC_STATUS);
++
++	dprintk(1, "%s() status =0x%02x\n", __func__, reg);
++
++	if (reg & 0x02)
++		*status |= FE_HAS_CARRIER;
++
++	if (reg & 0x04)
++		*status |= FE_HAS_SIGNAL;
++
++	if (reg & 0x08) {
++		*status |= FE_HAS_LOCK;
++		*status |= FE_HAS_VITERBI;
++		*status |= FE_HAS_SYNC;
++	}
++
++	return 0;
++}
++
++static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++
++	dprintk(1, "%s()\n", __func__);
++
++	/* TODO: A reset may be required here */
++	*ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
++		tda10048_readreg(state, TDA10048_CBER_LSB);
++
++	return 0;
++}
++
++static int tda10048_read_signal_strength(struct dvb_frontend *fe,
++	u16 *signal_strength)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++	u8 v;
++
++	dprintk(1, "%s()\n", __func__);
++
++	*signal_strength = 65535;
++
++	v = tda10048_readreg(state, TDA10048_NP_OUT);
++	if (v > 0)
++		*signal_strength -= (v << 8) | v;
++
++	return 0;
++}
++
++/* SNR lookup table */
++static struct snr_tab {
++	u8 val;
++	u8 data;
++} snr_tab[] = {
++	{   0,   0 },
++	{   1, 246 },
++	{   2, 215 },
++	{   3, 198 },
++	{   4, 185 },
++	{   5, 176 },
++	{   6, 168 },
++	{   7, 161 },
++	{   8, 155 },
++	{   9, 150 },
++	{  10, 146 },
++	{  11, 141 },
++	{  12, 138 },
++	{  13, 134 },
++	{  14, 131 },
++	{  15, 128 },
++	{  16, 125 },
++	{  17, 122 },
++	{  18, 120 },
++	{  19, 118 },
++	{  20, 115 },
++	{  21, 113 },
++	{  22, 111 },
++	{  23, 109 },
++	{  24, 107 },
++	{  25, 106 },
++	{  26, 104 },
++	{  27, 102 },
++	{  28, 101 },
++	{  29,  99 },
++	{  30,  98 },
++	{  31,  96 },
++	{  32,  95 },
++	{  33,  94 },
++	{  34,  92 },
++	{  35,  91 },
++	{  36,  90 },
++	{  37,  89 },
++	{  38,  88 },
++	{  39,  86 },
++	{  40,  85 },
++	{  41,  84 },
++	{  42,  83 },
++	{  43,  82 },
++	{  44,  81 },
++	{  45,  80 },
++	{  46,  79 },
++	{  47,  78 },
++	{  48,  77 },
++	{  49,  76 },
++	{  50,  76 },
++	{  51,  75 },
++	{  52,  74 },
++	{  53,  73 },
++	{  54,  72 },
++	{  56,  71 },
++	{  57,  70 },
++	{  58,  69 },
++	{  60,  68 },
++	{  61,  67 },
++	{  63,  66 },
++	{  64,  65 },
++	{  66,  64 },
++	{  67,  63 },
++	{  68,  62 },
++	{  69,  62 },
++	{  70,  61 },
++	{  72,  60 },
++	{  74,  59 },
++	{  75,  58 },
++	{  77,  57 },
++	{  79,  56 },
++	{  81,  55 },
++	{  83,  54 },
++	{  85,  53 },
++	{  87,  52 },
++	{  89,  51 },
++	{  91,  50 },
++	{  93,  49 },
++	{  95,  48 },
++	{  97,  47 },
++	{ 100,  46 },
++	{ 102,  45 },
++	{ 104,  44 },
++	{ 107,  43 },
++	{ 109,  42 },
++	{ 112,  41 },
++	{ 114,  40 },
++	{ 117,  39 },
++	{ 120,  38 },
++	{ 123,  37 },
++	{ 125,  36 },
++	{ 128,  35 },
++	{ 131,  34 },
++	{ 134,  33 },
++	{ 138,  32 },
++	{ 141,  31 },
++	{ 144,  30 },
++	{ 147,  29 },
++	{ 151,  28 },
++	{ 154,  27 },
++	{ 158,  26 },
++	{ 162,  25 },
++	{ 165,  24 },
++	{ 169,  23 },
++	{ 173,  22 },
++	{ 177,  21 },
++	{ 181,  20 },
++	{ 186,  19 },
++	{ 190,  18 },
++	{ 194,  17 },
++	{ 199,  16 },
++	{ 204,  15 },
++	{ 208,  14 },
++	{ 213,  13 },
++	{ 218,  12 },
++	{ 223,  11 },
++	{ 229,  10 },
++	{ 234,   9 },
++	{ 239,   8 },
++	{ 245,   7 },
++	{ 251,   6 },
++	{ 255,   5 },
++};
++
++static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++	u8 v;
++	int i, ret = -EINVAL;
++
++	dprintk(1, "%s()\n", __func__);
++
++	v = tda10048_readreg(state, TDA10048_NP_OUT);
++	for (i = 0; i < ARRAY_SIZE(snr_tab); i++) {
++		if (v <= snr_tab[i].val) {
++			*snr = snr_tab[i].data;
++			ret = 0;
++			break;
++		}
++	}
++
++	return ret;
++}
++
++static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++
++	dprintk(1, "%s()\n", __func__);
++
++	*ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
++		tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
++
++	return 0;
++}
++
++static int tda10048_get_frontend(struct dvb_frontend *fe,
++	struct dvb_frontend_parameters *p)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++
++	dprintk(1, "%s()\n", __func__);
++
++	p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
++		& 0x20 ? INVERSION_ON : INVERSION_OFF;
++
++	return tda10048_get_tps(state, &p->u.ofdm);
++}
++
++static int tda10048_get_tune_settings(struct dvb_frontend *fe,
++	struct dvb_frontend_tune_settings *tune)
++{
++	tune->min_delay_ms = 1000;
++	return 0;
++}
++
++static void tda10048_release(struct dvb_frontend *fe)
++{
++	struct tda10048_state *state = fe->demodulator_priv;
++	dprintk(1, "%s()\n", __func__);
++	kfree(state);
++}
++
++static struct dvb_frontend_ops tda10048_ops;
++
++struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
++	struct i2c_adapter *i2c)
++{
++	struct tda10048_state *state = NULL;
++
++	dprintk(1, "%s()\n", __func__);
++
++	/* allocate memory for the internal state */
++	state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL);
++	if (state == NULL)
++		goto error;
++
++	/* setup the state */
++	state->config = config;
++	state->i2c = i2c;
++	state->fwloaded = 0;
++
++	/* check if the demod is present */
++	if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
++		goto error;
++
++	/* create dvb_frontend */
++	memcpy(&state->frontend.ops, &tda10048_ops,
++		sizeof(struct dvb_frontend_ops));
++	state->frontend.demodulator_priv = state;
++
++	/* Leave the gate closed */
++	tda10048_i2c_gate_ctrl(&state->frontend, 0);
++
++	return &state->frontend;
++
++error:
++	kfree(state);
++	return NULL;
++}
++EXPORT_SYMBOL(tda10048_attach);
++
++static struct dvb_frontend_ops tda10048_ops = {
++
++	.info = {
++		.name			= "NXP TDA10048HN DVB-T",
++		.type			= FE_OFDM,
++		.frequency_min		= 177000000,
++		.frequency_max		= 858000000,
++		.frequency_stepsize	= 166666,
++		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
++		FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
++		FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
++		FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
++		FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
++	},
++
++	.release = tda10048_release,
++	.init = tda10048_init,
++	.i2c_gate_ctrl = tda10048_i2c_gate_ctrl,
++	.set_frontend = tda10048_set_frontend,
++	.get_frontend = tda10048_get_frontend,
++	.get_tune_settings = tda10048_get_tune_settings,
++	.read_status = tda10048_read_status,
++	.read_ber = tda10048_read_ber,
++	.read_signal_strength = tda10048_read_signal_strength,
++	.read_snr = tda10048_read_snr,
++	.read_ucblocks = tda10048_read_ucblocks,
++};
++
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable verbose debug messages");
++
++MODULE_DESCRIPTION("NXP TDA10048HN DVB-T Demodulator driver");
++MODULE_AUTHOR("Steven Toth");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
+new file mode 100644
+index 0000000..2b5c78e
+--- /dev/null
++++ b/drivers/media/dvb/frontends/tda10048.h
+@@ -0,0 +1,63 @@
++/*
++    NXP TDA10048HN DVB OFDM demodulator driver
++
++    Copyright (C) 2008 Steven Toth <stoth at hauppauge.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 TDA10048_H
++#define TDA10048_H
++
++#include <linux/dvb/frontend.h>
++#include <linux/firmware.h>
++
++struct tda10048_config {
++
++	/* the demodulator's i2c address */
++	u8 demod_address;
++
++	/* serial/parallel output */
++#define TDA10048_PARALLEL_OUTPUT 0
++#define TDA10048_SERIAL_OUTPUT   1
++	u8 output_mode;
++
++#define TDA10048_BULKWRITE_200	200
++#define TDA10048_BULKWRITE_50	50
++	u8 fwbulkwritelen;
++
++	/* Spectral Inversion */
++#define TDA10048_INVERSION_OFF 0
++#define TDA10048_INVERSION_ON  1
++	u8 inversion;
++};
++
++#if defined(CONFIG_DVB_TDA10048) || \
++	(defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE))
++extern struct dvb_frontend *tda10048_attach(
++	const struct tda10048_config *config,
++	struct i2c_adapter *i2c);
++#else
++static inline struct dvb_frontend *tda10048_attach(
++	const struct tda10048_config *config,
++	struct i2c_adapter *i2c)
++{
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++	return NULL;
++}
++#endif /* CONFIG_DVB_TDA10048 */
++
++#endif /* TDA10048_H */
+diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
+index 8415a8a..4997384 100644
+--- a/drivers/media/dvb/frontends/tda1004x.c
++++ b/drivers/media/dvb/frontends/tda1004x.c
+@@ -131,16 +131,16 @@ static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
+ 	u8 buf[] = { reg, data };
+ 	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
+ 
+-	dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
++	dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data);
+ 
+ 	msg.addr = state->config->demod_address;
+ 	ret = i2c_transfer(state->i2c, &msg, 1);
+ 
+ 	if (ret != 1)
+ 		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+-			__FUNCTION__, reg, data, ret);
++			__func__, reg, data, ret);
+ 
+-	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
++	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
+ 		reg, data, ret);
+ 	return (ret != 1) ? -1 : 0;
+ }
+@@ -153,19 +153,19 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
+ 	struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
+ 				{ .flags = I2C_M_RD, .buf = b1, .len = 1 }};
+ 
+-	dprintk("%s: reg=0x%x\n", __FUNCTION__, reg);
++	dprintk("%s: reg=0x%x\n", __func__, reg);
+ 
+ 	msg[0].addr = state->config->demod_address;
+ 	msg[1].addr = state->config->demod_address;
+ 	ret = i2c_transfer(state->i2c, msg, 2);
+ 
+ 	if (ret != 2) {
+-		dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
++		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
+ 			ret);
+ 		return -1;
+ 	}
+ 
+-	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
++	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
+ 		reg, b1[0], ret);
+ 	return b1[0];
+ }
+@@ -173,7 +173,7 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
+ static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data)
+ {
+ 	int val;
+-	dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg,
++	dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg,
+ 		mask, data);
+ 
+ 	// read a byte and check
+@@ -194,7 +194,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
+ 	int i;
+ 	int result;
+ 
+-	dprintk("%s: reg=0x%x, len=0x%x\n", __FUNCTION__, reg, len);
++	dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len);
+ 
+ 	result = 0;
+ 	for (i = 0; i < len; i++) {
+@@ -209,7 +209,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
+ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
+ {
+ 	int result;
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2);
+ 	msleep(20);
+@@ -218,7 +218,7 @@ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
+ 
+ static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
+ {
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0);
+ }
+@@ -345,7 +345,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
+ 		}
+ 		pos += tx_size;
+ 
+-		dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos);
++		dprintk("%s: fw_pos=0x%x\n", __func__, pos);
+ 	}
+ 	// give the DSP a chance to settle 03/10/05 Hac
+ 	msleep(100);
+@@ -444,10 +444,10 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
+ 		tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
+ 	}
+ 	if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
+-		dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
++		dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__);
+ 		tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
+ 	} else {
+-		dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
++		dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__);
+ 		tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
+ 	}
+ 	if(tda10046_clk53m)
+@@ -488,7 +488,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
+ 	if (state->config->xtal_freq == TDA10046_XTAL_4M) {
+ 		tda1004x_write_byteI(state, TDA1004X_CONFC4, 0);
+ 	} else {
+-		dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __FUNCTION__);
++		dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__);
+ 		tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80);
+ 	}
+ 	tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
+@@ -594,7 +594,7 @@ static int tda10045_init(struct dvb_frontend* fe)
+ {
+ 	struct tda1004x_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (tda10045_fwupload(fe)) {
+ 		printk("tda1004x: firmware upload failed\n");
+@@ -624,7 +624,7 @@ static int tda10045_init(struct dvb_frontend* fe)
+ static int tda10046_init(struct dvb_frontend* fe)
+ {
+ 	struct tda1004x_state* state = fe->demodulator_priv;
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (tda10046_fwupload(fe)) {
+ 		printk("tda1004x: firmware upload failed\n");
+@@ -686,7 +686,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
+ 	int tmp;
+ 	int inversion;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
+ 		// setup auto offset
+@@ -881,7 +881,7 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
+ {
+ 	struct tda1004x_state* state = fe->demodulator_priv;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	// inversion status
+ 	fe_params->inversion = INVERSION_OFF;
+@@ -989,7 +989,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
+ 	int cber;
+ 	int vber;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	// read status
+ 	status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
+@@ -1048,7 +1048,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
+ 	}
+ 
+ 	// success
+-	dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status);
++	dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
+ 	return 0;
+ }
+ 
+@@ -1058,7 +1058,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+ 	int tmp;
+ 	int reg = 0;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	// determine the register to use
+ 	switch (state->demod_type) {
+@@ -1077,7 +1077,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+ 		return -EIO;
+ 
+ 	*signal = (tmp << 8) | tmp;
+-	dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal);
++	dprintk("%s: signal=0x%x\n", __func__, *signal);
+ 	return 0;
+ }
+ 
+@@ -1086,7 +1086,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
+ 	struct tda1004x_state* state = fe->demodulator_priv;
+ 	int tmp;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	// read it
+ 	tmp = tda1004x_read_byte(state, TDA1004X_SNR);
+@@ -1095,7 +1095,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
+ 	tmp = 255 - tmp;
+ 
+ 	*snr = ((tmp << 8) | tmp);
+-	dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
++	dprintk("%s: snr=0x%x\n", __func__, *snr);
+ 	return 0;
+ }
+ 
+@@ -1106,7 +1106,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+ 	int tmp2;
+ 	int counter;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	// read the UCBLOCKS and reset
+ 	counter = 0;
+@@ -1132,7 +1132,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+ 	else
+ 		*ucblocks = 0xffffffff;
+ 
+-	dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);
++	dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
+ 	return 0;
+ }
+ 
+@@ -1141,7 +1141,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
+ 	struct tda1004x_state* state = fe->demodulator_priv;
+ 	int tmp;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	// read it in
+ 	tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
+@@ -1155,7 +1155,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
+ 	// The address 0x20 should be read to cope with a TDA10046 bug
+ 	tda1004x_read_byte(state, TDA1004X_CBER_RESET);
+ 
+-	dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber);
++	dprintk("%s: ber=0x%x\n", __func__, *ber);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h
+index abae843..4e27ffb 100644
+--- a/drivers/media/dvb/frontends/tda1004x.h
++++ b/drivers/media/dvb/frontends/tda1004x.h
+@@ -94,7 +94,6 @@ struct tda1004x_config
+ 
+ 	/* slave address and configuration of the tuner */
+ 	u8 tuner_address;
+-	u8 tuner_config;
+ 	u8 antenna_switch;
+ 
+ 	/* if the board uses another I2c Bridge (tda8290), its address */
+@@ -128,13 +127,13 @@ extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config
+ static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
+ 					    struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+ 					    struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TDA1004X
+diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
+index 0d2b69a..a17ce3c 100644
+--- a/drivers/media/dvb/frontends/tda10086.c
++++ b/drivers/media/dvb/frontends/tda10086.c
+@@ -43,7 +43,7 @@ struct tda10086_state {
+ 	bool has_lock;
+ };
+ 
+-static int debug = 0;
++static int debug;
+ #define dprintk(args...) \
+ 	do { \
+ 		if (debug) printk(KERN_DEBUG "tda10086: " args); \
+@@ -60,7 +60,7 @@ static int tda10086_write_byte(struct tda10086_state *state, int reg, int data)
+ 
+ 	if (ret != 1)
+ 		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+-			__FUNCTION__, reg, data, ret);
++			__func__, reg, data, ret);
+ 
+ 	return (ret != 1) ? ret : 0;
+ }
+@@ -78,7 +78,7 @@ static int tda10086_read_byte(struct tda10086_state *state, int reg)
+ 	ret = i2c_transfer(state->i2c, msg, 2);
+ 
+ 	if (ret != 2) {
+-		dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
++		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
+ 			ret);
+ 		return ret;
+ 	}
+@@ -90,16 +90,16 @@ static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask,
+ {
+ 	int val;
+ 
+-	// read a byte and check
++	/* read a byte and check */
+ 	val = tda10086_read_byte(state, reg);
+ 	if (val < 0)
+ 		return val;
+ 
+-	// mask if off
++	/* mask if off */
+ 	val = val & ~mask;
+ 	val |= data & 0xff;
+ 
+-	// write it out again
++	/* write it out again */
+ 	return tda10086_write_byte(state, reg, val);
+ }
+ 
+@@ -108,62 +108,67 @@ static int tda10086_init(struct dvb_frontend* fe)
+ 	struct tda10086_state* state = fe->demodulator_priv;
+ 	u8 t22k_off = 0x80;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (state->config->diseqc_tone)
+ 		t22k_off = 0;
+-	// reset
++	/* reset */
+ 	tda10086_write_byte(state, 0x00, 0x00);
+ 	msleep(10);
+ 
+-	// misc setup
++	/* misc setup */
+ 	tda10086_write_byte(state, 0x01, 0x94);
+-	tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
++	tda10086_write_byte(state, 0x02, 0x35); /* NOTE: TT drivers appear to disable CSWP */
+ 	tda10086_write_byte(state, 0x03, 0xe4);
+ 	tda10086_write_byte(state, 0x04, 0x43);
+ 	tda10086_write_byte(state, 0x0c, 0x0c);
+-	tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
+-	tda10086_write_byte(state, 0x20, 0x89); // misc
+-	tda10086_write_byte(state, 0x30, 0x04); // acquisition period length
+-	tda10086_write_byte(state, 0x32, 0x00); // irq off
+-	tda10086_write_byte(state, 0x31, 0x56); // setup AFC
+-
+-	// setup PLL (assumes 16Mhz XIN)
+-	tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup
+-	tda10086_write_byte(state, 0x3a, 0x0b); // M=12
+-	tda10086_write_byte(state, 0x3b, 0x01); // P=2
+-	tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL
+-
+-	// setup TS interface
++	tda10086_write_byte(state, 0x1b, 0xb0); /* noise threshold */
++	tda10086_write_byte(state, 0x20, 0x89); /* misc */
++	tda10086_write_byte(state, 0x30, 0x04); /* acquisition period length */
++	tda10086_write_byte(state, 0x32, 0x00); /* irq off */
++	tda10086_write_byte(state, 0x31, 0x56); /* setup AFC */
++
++	/* setup PLL (this assumes SACLK = 96MHz) */
++	tda10086_write_byte(state, 0x55, 0x2c); /* misc PLL setup */
++	if (state->config->xtal_freq == TDA10086_XTAL_16M) {
++		tda10086_write_byte(state, 0x3a, 0x0b); /* M=12 */
++		tda10086_write_byte(state, 0x3b, 0x01); /* P=2 */
++	} else {
++		tda10086_write_byte(state, 0x3a, 0x17); /* M=24 */
++		tda10086_write_byte(state, 0x3b, 0x00); /* P=1 */
++	}
++	tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */
++
++	/* setup TS interface */
+ 	tda10086_write_byte(state, 0x11, 0x81);
+ 	tda10086_write_byte(state, 0x12, 0x81);
+-	tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST
+-	tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use
+-	tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use
++	tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */
++	tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */
++	tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */
+ 	tda10086_write_byte(state, 0x10, 0x2a);
+ 
+-	// setup ADC
+-	tda10086_write_byte(state, 0x58, 0x61); // ADC setup
+-	tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC
++	/* setup ADC */
++	tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */
++	tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */
+ 
+-	// setup AGC
++	/* setup AGC */
+ 	tda10086_write_byte(state, 0x05, 0x0B);
+ 	tda10086_write_byte(state, 0x37, 0x63);
+-	tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
++	tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */
+ 	tda10086_write_byte(state, 0x40, 0x64);
+ 	tda10086_write_byte(state, 0x41, 0x4f);
+ 	tda10086_write_byte(state, 0x42, 0x43);
+ 
+-	// setup viterbi
+-	tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK
++	/* setup viterbi */
++	tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */
+ 
+-	// setup carrier recovery
++	/* setup carrier recovery */
+ 	tda10086_write_byte(state, 0x3d, 0x80);
+ 
+-	// setup SEC
+-	tda10086_write_byte(state, 0x36, t22k_off); // all SEC off, 22k tone
+-	tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));      // } tone frequency
+-	tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // }
++	/* setup SEC */
++	tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */
++	tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));
++	tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8);
+ 
+ 	return 0;
+ }
+@@ -173,7 +178,7 @@ static void tda10086_diseqc_wait(struct tda10086_state *state)
+ 	unsigned long timeout = jiffies + msecs_to_jiffies(200);
+ 	while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
+ 		if(time_after(jiffies, timeout)) {
+-			printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
++			printk("%s: diseqc queue not ready, command may be lost.\n", __func__);
+ 			break;
+ 		}
+ 		msleep(10);
+@@ -185,7 +190,7 @@ static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+ 	struct tda10086_state* state = fe->demodulator_priv;
+ 	u8 t22k_off = 0x80;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (state->config->diseqc_tone)
+ 		t22k_off = 0;
+@@ -211,7 +216,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
+ 	u8 oldval;
+ 	u8 t22k_off = 0x80;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (state->config->diseqc_tone)
+ 		t22k_off = 0;
+@@ -239,7 +244,7 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic
+ 	u8 oldval = tda10086_read_byte(state, 0x36);
+ 	u8 t22k_off = 0x80;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (state->config->diseqc_tone)
+ 		t22k_off = 0;
+@@ -266,7 +271,7 @@ static int tda10086_set_inversion(struct tda10086_state *state,
+ {
+ 	u8 invval = 0x80;
+ 
+-	dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert);
++	dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);
+ 
+ 	switch(fe_params->inversion) {
+ 	case INVERSION_OFF:
+@@ -300,9 +305,9 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
+ 	u32 bdri;
+ 	u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
+ 
+-	dprintk ("%s %i\n", __FUNCTION__, symbol_rate);
++	dprintk ("%s %i\n", __func__, symbol_rate);
+ 
+-	// setup the decimation and anti-aliasing filters..
++	/* setup the decimation and anti-aliasing filters.. */
+ 	if (symbol_rate < (u32) (SACLK * 0.0137)) {
+ 		dfn=4;
+ 		afs=1;
+@@ -339,13 +344,13 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
+ 		byp=1;
+ 	}
+ 
+-	// calculate BDR
++	/* calculate BDR */
+ 	big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
+ 	big += ((SACLK/1000ULL)-1ULL);
+ 	do_div(big, (SACLK/1000ULL));
+ 	bdr = big & 0xfffff;
+ 
+-	// calculate BDRI
++	/* calculate BDRI */
+ 	tmp = (1<<dfn)*(symbol_rate/1000);
+ 	bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
+ 
+@@ -366,7 +371,7 @@ static int tda10086_set_fec(struct tda10086_state *state,
+ {
+ 	u8 fecval;
+ 
+-	dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner);
++	dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);
+ 
+ 	switch(fe_params->u.qpsk.fec_inner) {
+ 	case FEC_1_2:
+@@ -412,13 +417,13 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
+ 	u32 freq = 0;
+ 	int freqoff;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+-	// modify parameters for tuning
++	/* modify parameters for tuning */
+ 	tda10086_write_byte(state, 0x02, 0x35);
+ 	state->has_lock = false;
+ 
+-	// set params
++	/* set params */
+ 	if (fe->ops.tuner_ops.set_params) {
+ 		fe->ops.tuner_ops.set_params(fe, fe_params);
+ 		if (fe->ops.i2c_gate_ctrl)
+@@ -430,7 +435,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
+ 			fe->ops.i2c_gate_ctrl(fe, 0);
+ 	}
+ 
+-	// calcluate the frequency offset (in *Hz* not kHz)
++	/* calcluate the frequency offset (in *Hz* not kHz) */
+ 	freqoff = fe_params->frequency - freq;
+ 	freqoff = ((1<<16) * freqoff) / (SACLK/1000);
+ 	tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
+@@ -443,7 +448,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
+ 	if ((ret = tda10086_set_fec(state, fe_params)) < 0)
+ 		return ret;
+ 
+-	// soft reset + disable TS output until lock
++	/* soft reset + disable TS output until lock */
+ 	tda10086_write_mask(state, 0x10, 0x40, 0x40);
+ 	tda10086_write_mask(state, 0x00, 0x01, 0x00);
+ 
+@@ -459,13 +464,13 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
+ 	int tmp;
+ 	u64 tmp64;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+-	// check for invalid symbol rate
++	/* check for invalid symbol rate */
+ 	if (fe_params->u.qpsk.symbol_rate < 500000)
+ 		return -EINVAL;
+ 
+-	// calculate the updated frequency (note: we convert from Hz->kHz)
++	/* calculate the updated frequency (note: we convert from Hz->kHz) */
+ 	tmp64 = tda10086_read_byte(state, 0x52);
+ 	tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
+ 	if (tmp64 & 0x8000)
+@@ -474,7 +479,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
+ 	do_div(tmp64, (1ULL<<15) * (1ULL<<1));
+ 	fe_params->frequency = (int) state->frequency + (int) tmp64;
+ 
+-	// the inversion
++	/* the inversion */
+ 	val = tda10086_read_byte(state, 0x0c);
+ 	if (val & 0x80) {
+ 		switch(val & 0x40) {
+@@ -505,7 +510,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
+ 		}
+ 	}
+ 
+-	// calculate the updated symbol rate
++	/* calculate the updated symbol rate */
+ 	tmp = tda10086_read_byte(state, 0x1d);
+ 	if (tmp & 0x80)
+ 		tmp |= 0xffffff00;
+@@ -513,7 +518,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
+ 	tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
+ 	fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
+ 
+-	// the FEC
++	/* the FEC */
+ 	val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
+ 	switch(val) {
+ 	case 0x00:
+@@ -550,7 +555,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
+ 	struct tda10086_state* state = fe->demodulator_priv;
+ 	u8 val;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	val = tda10086_read_byte(state, 0x0e);
+ 	*fe_status = 0;
+@@ -566,7 +571,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
+ 		*fe_status |= FE_HAS_LOCK;
+ 		if (!state->has_lock) {
+ 			state->has_lock = true;
+-			// modify parameters for stable reception
++			/* modify parameters for stable reception */
+ 			tda10086_write_byte(state, 0x02, 0x00);
+ 		}
+ 	}
+@@ -579,7 +584,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+ 	struct tda10086_state* state = fe->demodulator_priv;
+ 	u8 _str;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	_str = 0xff - tda10086_read_byte(state, 0x43);
+ 	*signal = (_str << 8) | _str;
+@@ -592,7 +597,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
+ 	struct tda10086_state* state = fe->demodulator_priv;
+ 	u8 _snr;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	_snr = 0xff - tda10086_read_byte(state, 0x1c);
+ 	*snr = (_snr << 8) | _snr;
+@@ -604,12 +609,12 @@ static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+ {
+ 	struct tda10086_state* state = fe->demodulator_priv;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+-	// read it
++	/* read it */
+ 	*ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
+ 
+-	// reset counter
++	/* reset counter */
+ 	tda10086_write_byte(state, 0x18, 0x00);
+ 	tda10086_write_byte(state, 0x18, 0x80);
+ 
+@@ -620,9 +625,9 @@ static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
+ {
+ 	struct tda10086_state* state = fe->demodulator_priv;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+-	// read it
++	/* read it */
+ 	*ber = 0;
+ 	*ber |= tda10086_read_byte(state, 0x15);
+ 	*ber |= tda10086_read_byte(state, 0x16) << 8;
+@@ -635,7 +640,7 @@ static int tda10086_sleep(struct dvb_frontend* fe)
+ {
+ 	struct tda10086_state* state = fe->demodulator_priv;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	tda10086_write_mask(state, 0x00, 0x08, 0x08);
+ 
+@@ -646,7 +651,7 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ 	struct tda10086_state* state = fe->demodulator_priv;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	if (enable) {
+ 		tda10086_write_mask(state, 0x00, 0x10, 0x10);
+@@ -737,7 +742,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+ {
+ 	struct tda10086_state *state;
+ 
+-	dprintk ("%s\n", __FUNCTION__);
++	dprintk ("%s\n", __func__);
+ 
+ 	/* allocate memory for the internal state */
+ 	state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
+diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h
+index eeceaee..61148c5 100644
+--- a/drivers/media/dvb/frontends/tda10086.h
++++ b/drivers/media/dvb/frontends/tda10086.h
+@@ -26,6 +26,11 @@
+ #include <linux/dvb/frontend.h>
+ #include <linux/firmware.h>
+ 
++enum tda10086_xtal {
++	TDA10086_XTAL_16M,
++	TDA10086_XTAL_4M
++};
++
+ struct tda10086_config
+ {
+ 	/* the demodulator's i2c address */
+@@ -36,6 +41,9 @@ struct tda10086_config
+ 
+ 	/* do we need the diseqc signal with carrier? */
+ 	u8 diseqc_tone;
++
++	/* frequency of the reference xtal */
++	enum tda10086_xtal xtal_freq;
+ };
+ 
+ #if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE))
+@@ -45,9 +53,9 @@ extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config
+ static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+ 						   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+-#endif // CONFIG_DVB_TDA10086
++#endif /* CONFIG_DVB_TDA10086 */
+ 
+-#endif // TDA10086_H
++#endif /* TDA10086_H */
+diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c
+index bca5709..e27a762 100644
+--- a/drivers/media/dvb/frontends/tda18271-common.c
++++ b/drivers/media/dvb/frontends/tda18271-common.c
+@@ -125,16 +125,16 @@ int tda18271_read_regs(struct dvb_frontend *fe)
+ 	unsigned char buf = 0x00;
+ 	int ret;
+ 	struct i2c_msg msg[] = {
+-		{ .addr = priv->i2c_addr, .flags = 0,
++		{ .addr = priv->i2c_props.addr, .flags = 0,
+ 		  .buf = &buf, .len = 1 },
+-		{ .addr = priv->i2c_addr, .flags = I2C_M_RD,
++		{ .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
+ 		  .buf = regs, .len = 16 }
+ 	};
+ 
+ 	tda18271_i2c_gate_ctrl(fe, 1);
+ 
+ 	/* read all registers */
+-	ret = i2c_transfer(priv->i2c_adap, msg, 2);
++	ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
+ 
+ 	tda18271_i2c_gate_ctrl(fe, 0);
+ 
+@@ -155,16 +155,16 @@ int tda18271_read_extended(struct dvb_frontend *fe)
+ 	unsigned char buf = 0x00;
+ 	int ret, i;
+ 	struct i2c_msg msg[] = {
+-		{ .addr = priv->i2c_addr, .flags = 0,
++		{ .addr = priv->i2c_props.addr, .flags = 0,
+ 		  .buf = &buf, .len = 1 },
+-		{ .addr = priv->i2c_addr, .flags = I2C_M_RD,
++		{ .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
+ 		  .buf = regdump, .len = TDA18271_NUM_REGS }
+ 	};
+ 
+ 	tda18271_i2c_gate_ctrl(fe, 1);
+ 
+ 	/* read all registers */
+-	ret = i2c_transfer(priv->i2c_adap, msg, 2);
++	ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
+ 
+ 	tda18271_i2c_gate_ctrl(fe, 0);
+ 
+@@ -192,7 +192,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+ 	unsigned char *regs = priv->tda18271_regs;
+ 	unsigned char buf[TDA18271_NUM_REGS + 1];
+-	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
++	struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
+ 			       .buf = buf, .len = len + 1 };
+ 	int i, ret;
+ 
+@@ -205,7 +205,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+ 	tda18271_i2c_gate_ctrl(fe, 1);
+ 
+ 	/* write registers */
+-	ret = i2c_transfer(priv->i2c_adap, &msg, 1);
++	ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+ 
+ 	tda18271_i2c_gate_ctrl(fe, 0);
+ 
+@@ -217,13 +217,29 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+ 
+ /*---------------------------------------------------------------------*/
+ 
++int tda18271_charge_pump_source(struct dvb_frontend *fe,
++				enum tda18271_pll pll, int force)
++{
++	struct tda18271_priv *priv = fe->tuner_priv;
++	unsigned char *regs = priv->tda18271_regs;
++
++	int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4;
++
++	regs[r_cp] &= ~0x20;
++	regs[r_cp] |= ((force & 1) << 5);
++	tda18271_write_regs(fe, r_cp, 1);
++
++	return 0;
++}
++
+ int tda18271_init_regs(struct dvb_frontend *fe)
+ {
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+ 	unsigned char *regs = priv->tda18271_regs;
+ 
+ 	tda_dbg("initializing registers for device @ %d-%04x\n",
+-		i2c_adapter_id(priv->i2c_adap), priv->i2c_addr);
++		i2c_adapter_id(priv->i2c_props.adap),
++		priv->i2c_props.addr);
+ 
+ 	/* initialize registers */
+ 	switch (priv->id) {
+@@ -310,7 +326,12 @@ int tda18271_init_regs(struct dvb_frontend *fe)
+ 	regs[R_EB22] = 0x48;
+ 	regs[R_EB23] = 0xb0;
+ 
+-	tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
++	if (priv->small_i2c) {
++		tda18271_write_regs(fe, 0x00, 0x10);
++		tda18271_write_regs(fe, 0x10, 0x10);
++		tda18271_write_regs(fe, 0x20, 0x07);
++	} else
++		tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
+ 
+ 	/* setup agc1 gain */
+ 	regs[R_EB17] = 0x00;
+@@ -349,24 +370,15 @@ int tda18271_init_regs(struct dvb_frontend *fe)
+ 	regs[R_MD2] = 0x08;
+ 	regs[R_MD3] = 0x00;
+ 
+-	switch (priv->id) {
+-	case TDA18271HDC1:
+-		tda18271_write_regs(fe, R_EP3, 11);
+-		break;
+-	case TDA18271HDC2:
+-		tda18271_write_regs(fe, R_EP3, 12);
+-		break;
+-	};
++	tda18271_write_regs(fe, R_EP3, 11);
+ 
+ 	if ((priv->id) == TDA18271HDC2) {
+ 		/* main pll cp source on */
+-		regs[R_EB4] = 0x61;
+-		tda18271_write_regs(fe, R_EB4, 1);
++		tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
+ 		msleep(1);
+ 
+ 		/* main pll cp source off */
+-		regs[R_EB4] = 0x41;
+-		tda18271_write_regs(fe, R_EB4, 1);
++		tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
+ 	}
+ 
+ 	msleep(5); /* pll locking */
+@@ -398,6 +410,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
+ 	tda18271_write_regs(fe, R_EP3, 11);
+ 	msleep(5); /* pll locking */
+ 
++	/* launch detector */
+ 	tda18271_write_regs(fe, R_EP1, 1);
+ 	msleep(5); /* wanted mid measurement */
+ 
+diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c
+index dfe72aa..b262100 100644
+--- a/drivers/media/dvb/frontends/tda18271-fe.c
++++ b/drivers/media/dvb/frontends/tda18271-fe.c
+@@ -31,30 +31,23 @@ static int tda18271_cal_on_startup;
+ module_param_named(cal, tda18271_cal_on_startup, int, 0644);
+ MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup");
+ 
+-static LIST_HEAD(tda18271_list);
+ static DEFINE_MUTEX(tda18271_list_mutex);
++static LIST_HEAD(hybrid_tuner_instance_list);
+ 
+ /*---------------------------------------------------------------------*/
+ 
+-static int tda18271_ir_cal_init(struct dvb_frontend *fe)
++static inline int charge_pump_source(struct dvb_frontend *fe, int force)
+ {
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+-	unsigned char *regs = priv->tda18271_regs;
+-
+-	tda18271_read_regs(fe);
+-
+-	/* test IR_CAL_OK to see if we need init */
+-	if ((regs[R_EP1] & 0x08) == 0)
+-		tda18271_init_regs(fe);
+-
+-	return 0;
++	return tda18271_charge_pump_source(fe,
++					   (priv->role == TDA18271_SLAVE) ?
++					   TDA18271_CAL_PLL :
++					   TDA18271_MAIN_PLL, force);
+ }
+ 
+-/* ------------------------------------------------------------------ */
+-
+ static int tda18271_channel_configuration(struct dvb_frontend *fe,
+-					  u32 ifc, u32 freq, u32 bw, u8 std,
+-					  int radio)
++					  struct tda18271_std_map_item *map,
++					  u32 freq, u32 bw)
+ {
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+ 	unsigned char *regs = priv->tda18271_regs;
+@@ -64,38 +57,34 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
+ 
+ 	/* set standard */
+ 	regs[R_EP3]  &= ~0x1f; /* clear std bits */
+-	regs[R_EP3]  |= std;
++	regs[R_EP3]  |= (map->agc_mode << 3) | map->std;
++
++	/* set rfagc to high speed mode */
++	regs[R_EP3] &= ~0x04;
+ 
+ 	/* set cal mode to normal */
+ 	regs[R_EP4]  &= ~0x03;
+ 
+ 	/* update IF output level & IF notch frequency */
+ 	regs[R_EP4]  &= ~0x1c; /* clear if level bits */
++	regs[R_EP4]  |= (map->if_lvl << 2);
+ 
+ 	switch (priv->mode) {
+ 	case TDA18271_ANALOG:
+ 		regs[R_MPD]  &= ~0x80; /* IF notch = 0 */
+ 		break;
+ 	case TDA18271_DIGITAL:
+-		regs[R_EP4]  |= 0x04; /* IF level = 1 */
+ 		regs[R_MPD]  |= 0x80; /* IF notch = 1 */
+ 		break;
+ 	}
+ 
+-	if (radio)
+-		regs[R_EP4]  |=  0x80;
+-	else
+-		regs[R_EP4]  &= ~0x80;
++	/* update FM_RFn */
++	regs[R_EP4]  &= ~0x80;
++	regs[R_EP4]  |= map->fm_rfn << 7;
+ 
+-	/* update RF_TOP / IF_TOP */
+-	switch (priv->mode) {
+-	case TDA18271_ANALOG:
+-		regs[R_EB22]  = 0x2c;
+-		break;
+-	case TDA18271_DIGITAL:
+-		regs[R_EB22]  = 0x37;
+-		break;
+-	}
++	/* update rf top / if top */
++	regs[R_EB22]  = 0x00;
++	regs[R_EB22] |= map->rfagc_top;
+ 	tda18271_write_regs(fe, R_EB22, 1);
+ 
+ 	/* --------------------------------------------------------------- */
+@@ -117,8 +106,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
+ 
+ 	/* dual tuner and agc1 extra configuration */
+ 
+-	/* main vco when Master, cal vco when slave */
+-	regs[R_EB1]  |= 0x04; /* FIXME: assumes master */
++	switch (priv->role) {
++	case TDA18271_MASTER:
++		regs[R_EB1]  |= 0x04; /* main vco */
++		break;
++	case TDA18271_SLAVE:
++		regs[R_EB1]  &= ~0x04; /* cal vco */
++		break;
++	}
+ 
+ 	/* agc1 always active */
+ 	regs[R_EB1]  &= ~0x02;
+@@ -130,25 +125,40 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
+ 
+ 	/* --------------------------------------------------------------- */
+ 
+-	N = freq + ifc;
++	N = map->if_freq * 1000 + freq;
+ 
+-	/* FIXME: assumes master */
+-	tda18271_calc_main_pll(fe, N);
+-	tda18271_write_regs(fe, R_MPD, 4);
++	switch (priv->role) {
++	case TDA18271_MASTER:
++		tda18271_calc_main_pll(fe, N);
++		tda18271_write_regs(fe, R_MPD, 4);
++		break;
++	case TDA18271_SLAVE:
++		tda18271_calc_cal_pll(fe, N);
++		tda18271_write_regs(fe, R_CPD, 4);
++
++		regs[R_MPD] = regs[R_CPD] & 0x7f;
++		tda18271_write_regs(fe, R_MPD, 1);
++		break;
++	}
+ 
+ 	tda18271_write_regs(fe, R_TM, 7);
+ 
+-	/* main pll charge pump source */
+-	regs[R_EB4] |= 0x20;
+-	tda18271_write_regs(fe, R_EB4, 1);
++	/* force charge pump source */
++	charge_pump_source(fe, 1);
+ 
+ 	msleep(1);
+ 
+-	/* normal operation for the main pll */
+-	regs[R_EB4] &= ~0x20;
+-	tda18271_write_regs(fe, R_EB4, 1);
++	/* return pll to normal operation */
++	charge_pump_source(fe, 0);
+ 
+-	msleep(5);
++	msleep(20);
++
++	/* set rfagc to normal speed mode */
++	if (map->fm_rfn)
++		regs[R_EP3] &= ~0x04;
++	else
++		regs[R_EP3] |= 0x04;
++	tda18271_write_regs(fe, R_EP3, 1);
+ 
+ 	return 0;
+ }
+@@ -195,8 +205,10 @@ static int tda18271_read_thermometer(struct dvb_frontend *fe)
+ 	return tm;
+ }
+ 
+-static int tda18271_rf_tracking_filters_correction(struct dvb_frontend *fe,
+-						   u32 freq)
++/* ------------------------------------------------------------------ */
++
++static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe,
++						     u32 freq)
+ {
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+ 	struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
+@@ -296,12 +308,10 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
+ 	tda18271_write_regs(fe, R_EB13, 1);
+ 
+ 	/* main pll charge pump source */
+-	regs[R_EB4]  |= 0x20;
+-	tda18271_write_regs(fe, R_EB4, 1);
++	tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
+ 
+ 	/* cal pll charge pump source */
+-	regs[R_EB7]  |= 0x20;
+-	tda18271_write_regs(fe, R_EB7, 1);
++	tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 1);
+ 
+ 	/* force dcdc converter to 0 V */
+ 	regs[R_EB14] = 0x00;
+@@ -320,8 +330,8 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
+ 	/* set the internal calibration signal */
+ 	N = freq;
+ 
+-	tda18271_calc_main_pll(fe, N);
+-	tda18271_write_regs(fe, R_MPD, 4);
++	tda18271_calc_cal_pll(fe, N);
++	tda18271_write_regs(fe, R_CPD, 4);
+ 
+ 	/* downconvert internal calibration */
+ 	N += 1000000;
+@@ -339,14 +349,12 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
+ 	/* --------------------------------------------------------------- */
+ 
+ 	/* normal operation for the main pll */
+-	regs[R_EB4] &= ~0x20;
+-	tda18271_write_regs(fe, R_EB4, 1);
++	tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
+ 
+ 	/* normal operation for the cal pll  */
+-	regs[R_EB7] &= ~0x20;
+-	tda18271_write_regs(fe, R_EB7, 1);
++	tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 0);
+ 
+-	msleep(5); /* plls locking */
++	msleep(10); /* plls locking */
+ 
+ 	/* launch the rf tracking filters calibration */
+ 	regs[R_EB20]  |= 0x20;
+@@ -443,7 +451,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe,
+ 
+ 		count += 200;
+ 
+-		if (count < count_limit)
++		if (count <= count_limit)
+ 			continue;
+ 
+ 		if (sgn <= 0)
+@@ -587,7 +595,7 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe)
+ 
+ /* ------------------------------------------------------------------ */
+ 
+-static int tda18271_rf_cal_init(struct dvb_frontend *fe)
++static int tda18271c2_rf_cal_init(struct dvb_frontend *fe)
+ {
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+ 	unsigned char *regs = priv->tda18271_regs;
+@@ -610,63 +618,13 @@ static int tda18271_rf_cal_init(struct dvb_frontend *fe)
+ 	return 0;
+ }
+ 
+-static int tda18271_init(struct dvb_frontend *fe)
+-{
+-	struct tda18271_priv *priv = fe->tuner_priv;
+-
+-	mutex_lock(&priv->lock);
+-
+-	/* power up */
+-	tda18271_set_standby_mode(fe, 0, 0, 0);
+-
+-	/* initialization */
+-	tda18271_ir_cal_init(fe);
+-
+-	if (priv->id == TDA18271HDC2)
+-		tda18271_rf_cal_init(fe);
+-
+-	mutex_unlock(&priv->lock);
+-
+-	return 0;
+-}
+-
+-static int tda18271c2_tune(struct dvb_frontend *fe,
+-			   u32 ifc, u32 freq, u32 bw, u8 std, int radio)
+-{
+-	struct tda18271_priv *priv = fe->tuner_priv;
+-
+-	tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
+-
+-	tda18271_init(fe);
+-
+-	mutex_lock(&priv->lock);
+-
+-	tda18271_rf_tracking_filters_correction(fe, freq);
+-
+-	tda18271_channel_configuration(fe, ifc, freq, bw, std, radio);
+-
+-	mutex_unlock(&priv->lock);
+-
+-	return 0;
+-}
+-
+-/* ------------------------------------------------------------------ */
+-
+-static int tda18271c1_tune(struct dvb_frontend *fe,
+-			   u32 ifc, u32 freq, u32 bw, u8 std, int radio)
++static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe,
++						     u32 freq, u32 bw)
+ {
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+ 	unsigned char *regs = priv->tda18271_regs;
+ 	u32 N = 0;
+ 
+-	tda18271_init(fe);
+-
+-	mutex_lock(&priv->lock);
+-
+-	tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
+-
+-	/* RF tracking filter calibration */
+-
+ 	/* calculate bp filter */
+ 	tda18271_calc_bp_filter(fe, &freq);
+ 	tda18271_write_regs(fe, R_EP1, 1);
+@@ -737,7 +695,7 @@ static int tda18271c1_tune(struct dvb_frontend *fe,
+ 
+ 	regs[R_EB7]   = 0x40;
+ 	tda18271_write_regs(fe, R_EB7, 1);
+-	msleep(10);
++	msleep(10); /* pll locking */
+ 
+ 	regs[R_EB20]  = 0xec;
+ 	tda18271_write_regs(fe, R_EB20, 1);
+@@ -752,74 +710,70 @@ static int tda18271c1_tune(struct dvb_frontend *fe,
+ 	if (0 == tda18271_calc_rf_cal(fe, &freq))
+ 		tda18271_write_regs(fe, R_EB14, 1);
+ 
+-	/* Channel Configuration */
++	return 0;
++}
+ 
+-	switch (priv->mode) {
+-	case TDA18271_ANALOG:
+-		regs[R_EB22]  = 0x2c;
+-		break;
+-	case TDA18271_DIGITAL:
+-		regs[R_EB22]  = 0x37;
+-		break;
+-	}
+-	tda18271_write_regs(fe, R_EB22, 1);
++/* ------------------------------------------------------------------ */
+ 
+-	regs[R_EP1]  |= 0x40; /* set dis power level on */
++static int tda18271_ir_cal_init(struct dvb_frontend *fe)
++{
++	struct tda18271_priv *priv = fe->tuner_priv;
++	unsigned char *regs = priv->tda18271_regs;
+ 
+-	/* set standard */
+-	regs[R_EP3]  &= ~0x1f; /* clear std bits */
++	tda18271_read_regs(fe);
+ 
+-	/* see table 22 */
+-	regs[R_EP3]  |= std;
++	/* test IR_CAL_OK to see if we need init */
++	if ((regs[R_EP1] & 0x08) == 0)
++		tda18271_init_regs(fe);
+ 
+-	regs[R_EP4]  &= ~0x03; /* set cal mode to normal */
++	return 0;
++}
+ 
+-	regs[R_EP4]  &= ~0x1c; /* clear if level bits */
+-	switch (priv->mode) {
+-	case TDA18271_ANALOG:
+-		regs[R_MPD]  &= ~0x80; /* IF notch = 0 */
+-		break;
+-	case TDA18271_DIGITAL:
+-		regs[R_EP4]  |= 0x04;
+-		regs[R_MPD]  |= 0x80;
+-		break;
+-	}
++static int tda18271_init(struct dvb_frontend *fe)
++{
++	struct tda18271_priv *priv = fe->tuner_priv;
+ 
+-	if (radio)
+-		regs[R_EP4]  |=  0x80;
+-	else
+-		regs[R_EP4]  &= ~0x80;
++	mutex_lock(&priv->lock);
+ 
+-	/* image rejection validity */
+-	tda18271_calc_ir_measure(fe, &freq);
++	/* power up */
++	tda18271_set_standby_mode(fe, 0, 0, 0);
+ 
+-	/* calculate MAIN PLL */
+-	N = freq + ifc;
++	/* initialization */
++	tda18271_ir_cal_init(fe);
+ 
+-	tda18271_calc_main_pll(fe, N);
++	if (priv->id == TDA18271HDC2)
++		tda18271c2_rf_cal_init(fe);
+ 
+-	tda18271_write_regs(fe, R_TM, 15);
+-	msleep(5);
+ 	mutex_unlock(&priv->lock);
+ 
+ 	return 0;
+ }
+ 
+-static inline int tda18271_tune(struct dvb_frontend *fe,
+-				u32 ifc, u32 freq, u32 bw, u8 std, int radio)
++static int tda18271_tune(struct dvb_frontend *fe,
++			 struct tda18271_std_map_item *map, u32 freq, u32 bw)
+ {
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+-	int ret = -EINVAL;
++
++	tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n",
++		freq, map->if_freq, bw, map->agc_mode, map->std);
++
++	tda18271_init(fe);
++
++	mutex_lock(&priv->lock);
+ 
+ 	switch (priv->id) {
+ 	case TDA18271HDC1:
+-		ret = tda18271c1_tune(fe, ifc, freq, bw, std, radio);
++		tda18271c1_rf_tracking_filter_calibration(fe, freq, bw);
+ 		break;
+ 	case TDA18271HDC2:
+-		ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio);
++		tda18271c2_rf_tracking_filters_correction(fe, freq);
+ 		break;
+ 	}
+-	return ret;
++	tda18271_channel_configuration(fe, map, freq, bw);
++
++	mutex_unlock(&priv->lock);
++
++	return 0;
+ }
+ 
+ /* ------------------------------------------------------------------ */
+@@ -829,9 +783,8 @@ static int tda18271_set_params(struct dvb_frontend *fe,
+ {
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+ 	struct tda18271_std_map *std_map = &priv->std;
++	struct tda18271_std_map_item *map;
+ 	int ret;
+-	u8 std;
+-	u16 sgIF;
+ 	u32 bw, freq = params->frequency;
+ 
+ 	priv->mode = TDA18271_DIGITAL;
+@@ -840,13 +793,11 @@ static int tda18271_set_params(struct dvb_frontend *fe,
+ 		switch (params->u.vsb.modulation) {
+ 		case VSB_8:
+ 		case VSB_16:
+-			std  = std_map->atsc_6.std_bits;
+-			sgIF = std_map->atsc_6.if_freq;
++			map = &std_map->atsc_6;
+ 			break;
+ 		case QAM_64:
+ 		case QAM_256:
+-			std  = std_map->qam_6.std_bits;
+-			sgIF = std_map->qam_6.if_freq;
++			map = &std_map->qam_6;
+ 			break;
+ 		default:
+ 			tda_warn("modulation not set!\n");
+@@ -861,18 +812,15 @@ static int tda18271_set_params(struct dvb_frontend *fe,
+ 		switch (params->u.ofdm.bandwidth) {
+ 		case BANDWIDTH_6_MHZ:
+ 			bw = 6000000;
+-			std  = std_map->dvbt_6.std_bits;
+-			sgIF = std_map->dvbt_6.if_freq;
++			map = &std_map->dvbt_6;
+ 			break;
+ 		case BANDWIDTH_7_MHZ:
+ 			bw = 7000000;
+-			std  = std_map->dvbt_7.std_bits;
+-			sgIF = std_map->dvbt_7.if_freq;
++			map = &std_map->dvbt_7;
+ 			break;
+ 		case BANDWIDTH_8_MHZ:
+ 			bw = 8000000;
+-			std  = std_map->dvbt_8.std_bits;
+-			sgIF = std_map->dvbt_8.if_freq;
++			map = &std_map->dvbt_8;
+ 			break;
+ 		default:
+ 			tda_warn("bandwidth not set!\n");
+@@ -887,7 +835,7 @@ static int tda18271_set_params(struct dvb_frontend *fe,
+ 	if (fe->ops.analog_ops.standby)
+ 		fe->ops.analog_ops.standby(fe);
+ 
+-	ret = tda18271_tune(fe, sgIF * 1000, freq, bw, std, 0);
++	ret = tda18271_tune(fe, map, freq, bw);
+ 
+ 	if (ret < 0)
+ 		goto fail;
+@@ -904,57 +852,46 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe,
+ {
+ 	struct tda18271_priv *priv = fe->tuner_priv;
+ 	struct tda18271_std_map *std_map = &priv->std;
++	struct tda18271_std_map_item *map;
+ 	char *mode;
+-	int ret, radio = 0;
+-	u8 std;
+-	u16 sgIF;
++	int ret;
+ 	u32 freq = params->frequency * 62500;
+ 
+ 	priv->mode = TDA18271_ANALOG;
+ 
+ 	if (params->mode == V4L2_TUNER_RADIO) {
+-		radio = 1;
+ 		freq = freq / 1000;
+-		std  = std_map->fm_radio.std_bits;
+-		sgIF = std_map->fm_radio.if_freq;
++		map = &std_map->fm_radio;
+ 		mode = "fm";
+ 	} else if (params->std & V4L2_STD_MN) {
+-		std  = std_map->atv_mn.std_bits;
+-		sgIF = std_map->atv_mn.if_freq;
++		map = &std_map->atv_mn;
+ 		mode = "MN";
+ 	} else if (params->std & V4L2_STD_B) {
+-		std  = std_map->atv_b.std_bits;
+-		sgIF = std_map->atv_b.if_freq;
++		map = &std_map->atv_b;
+ 		mode = "B";
+ 	} else if (params->std & V4L2_STD_GH) {
+-		std  = std_map->atv_gh.std_bits;
+-		sgIF = std_map->atv_gh.if_freq;
++		map = &std_map->atv_gh;
+ 		mode = "GH";
+ 	} else if (params->std & V4L2_STD_PAL_I) {
+-		std  = std_map->atv_i.std_bits;
+-		sgIF = std_map->atv_i.if_freq;
++		map = &std_map->atv_i;
+ 		mode = "I";
+ 	} else if (params->std & V4L2_STD_DK) {
+-		std  = std_map->atv_dk.std_bits;
+-		sgIF = std_map->atv_dk.if_freq;
++		map = &std_map->atv_dk;
+ 		mode = "DK";
+ 	} else if (params->std & V4L2_STD_SECAM_L) {
+-		std  = std_map->atv_l.std_bits;
+-		sgIF = std_map->atv_l.if_freq;
++		map = &std_map->atv_l;
+ 		mode = "L";
+ 	} else if (params->std & V4L2_STD_SECAM_LC) {
+-		std  = std_map->atv_lc.std_bits;
+-		sgIF = std_map->atv_lc.if_freq;
++		map = &std_map->atv_lc;
+ 		mode = "L'";
+ 	} else {
+-		std  = std_map->atv_i.std_bits;
+-		sgIF = std_map->atv_i.if_freq;
++		map = &std_map->atv_i;
+ 		mode = "xx";
+ 	}
+ 
+ 	tda_dbg("setting tda18271 to system %s\n", mode);
+ 
+-	ret = tda18271_tune(fe, sgIF * 1000, freq, 0, std, radio);
++	ret = tda18271_tune(fe, map, freq, 0);
+ 
+ 	if (ret < 0)
+ 		goto fail;
+@@ -986,16 +923,9 @@ static int tda18271_release(struct dvb_frontend *fe)
+ 
+ 	mutex_lock(&tda18271_list_mutex);
+ 
+-	priv->count--;
++	if (priv)
++		hybrid_tuner_release_state(priv);
+ 
+-	if (!priv->count) {
+-		tda_dbg("destroying instance @ %d-%04x\n",
+-			i2c_adapter_id(priv->i2c_adap),
+-			priv->i2c_addr);
+-		list_del(&priv->tda18271_list);
+-
+-		kfree(priv);
+-	}
+ 	mutex_unlock(&tda18271_list_mutex);
+ 
+ 	fe->tuner_priv = NULL;
+@@ -1020,15 +950,20 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+ /* ------------------------------------------------------------------ */
+ 
+ #define tda18271_update_std(std_cfg, name) do {				\
+-	if (map->std_cfg.if_freq + map->std_cfg.std_bits > 0) {		\
++	if (map->std_cfg.if_freq +					\
++		map->std_cfg.agc_mode + map->std_cfg.std +		\
++		map->std_cfg.if_lvl + map->std_cfg.rfagc_top > 0) {	\
+ 		tda_dbg("Using custom std config for %s\n", name);	\
+ 		memcpy(&std->std_cfg, &map->std_cfg,			\
+ 			sizeof(struct tda18271_std_map_item));		\
+ 	} } while (0)
+ 
+ #define tda18271_dump_std_item(std_cfg, name) do {			\
+-	tda_dbg("(%s) if freq = %d, std bits = 0x%02x\n",		\
+-		name, std->std_cfg.if_freq, std->std_cfg.std_bits);	\
++	tda_dbg("(%s) if_freq = %d, agc_mode = %d, std = %d, "		\
++		"if_lvl = %d, rfagc_top = 0x%02x\n",			\
++		name, std->std_cfg.if_freq,				\
++		std->std_cfg.agc_mode, std->std_cfg.std,		\
++		std->std_cfg.if_lvl, std->std_cfg.rfagc_top);		\
+ 	} while (0)
+ 
+ static int tda18271_dump_std_map(struct dvb_frontend *fe)
+@@ -1037,20 +972,20 @@ static int tda18271_dump_std_map(struct dvb_frontend *fe)
+ 	struct tda18271_std_map *std = &priv->std;
+ 
+ 	tda_dbg("========== STANDARD MAP SETTINGS ==========\n");
+-	tda18271_dump_std_item(fm_radio, "fm");
+-	tda18271_dump_std_item(atv_b,  "pal b");
+-	tda18271_dump_std_item(atv_dk, "pal dk");
+-	tda18271_dump_std_item(atv_gh, "pal gh");
+-	tda18271_dump_std_item(atv_i,  "pal i");
+-	tda18271_dump_std_item(atv_l,  "pal l");
+-	tda18271_dump_std_item(atv_lc, "pal l'");
++	tda18271_dump_std_item(fm_radio, "  fm  ");
++	tda18271_dump_std_item(atv_b,  "atv b ");
++	tda18271_dump_std_item(atv_dk, "atv dk");
++	tda18271_dump_std_item(atv_gh, "atv gh");
++	tda18271_dump_std_item(atv_i,  "atv i ");
++	tda18271_dump_std_item(atv_l,  "atv l ");
++	tda18271_dump_std_item(atv_lc, "atv l'");
+ 	tda18271_dump_std_item(atv_mn, "atv mn");
+ 	tda18271_dump_std_item(atsc_6, "atsc 6");
+ 	tda18271_dump_std_item(dvbt_6, "dvbt 6");
+ 	tda18271_dump_std_item(dvbt_7, "dvbt 7");
+ 	tda18271_dump_std_item(dvbt_8, "dvbt 8");
+-	tda18271_dump_std_item(qam_6,  "qam 6");
+-	tda18271_dump_std_item(qam_8,  "qam 8");
++	tda18271_dump_std_item(qam_6,  "qam 6 ");
++	tda18271_dump_std_item(qam_8,  "qam 8 ");
+ 
+ 	return 0;
+ }
+@@ -1109,7 +1044,8 @@ static int tda18271_get_id(struct dvb_frontend *fe)
+ 	}
+ 
+ 	tda_info("%s detected @ %d-%04x%s\n", name,
+-		 i2c_adapter_id(priv->i2c_adap), priv->i2c_addr,
++		 i2c_adapter_id(priv->i2c_props.adap),
++		 priv->i2c_props.addr,
+ 		 (0 == ret) ? "" : ", device not supported.");
+ 
+ 	return ret;
+@@ -1136,45 +1072,28 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
+ 				     struct tda18271_config *cfg)
+ {
+ 	struct tda18271_priv *priv = NULL;
+-	int state_found = 0;
++	int instance;
+ 
+ 	mutex_lock(&tda18271_list_mutex);
+ 
+-	list_for_each_entry(priv, &tda18271_list, tda18271_list) {
+-		if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) &&
+-		    (priv->i2c_addr == addr)) {
+-			tda_dbg("attaching existing tuner @ %d-%04x\n",
+-				i2c_adapter_id(priv->i2c_adap),
+-				priv->i2c_addr);
+-			priv->count++;
+-			fe->tuner_priv = priv;
+-			state_found = 1;
+-			/* allow dvb driver to override i2c gate setting */
+-			if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
+-				priv->gate = cfg->gate;
+-			break;
+-		}
+-	}
+-	if (state_found == 0) {
+-		tda_dbg("creating new tuner instance @ %d-%04x\n",
+-			i2c_adapter_id(i2c), addr);
+-
+-		priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
+-		if (priv == NULL) {
+-			mutex_unlock(&tda18271_list_mutex);
+-			return NULL;
+-		}
+-
+-		priv->i2c_addr = addr;
+-		priv->i2c_adap = i2c;
++	instance = hybrid_tuner_request_state(struct tda18271_priv, priv,
++					      hybrid_tuner_instance_list,
++					      i2c, addr, "tda18271");
++	switch (instance) {
++	case 0:
++		goto fail;
++		break;
++	case 1:
++		/* new tuner instance */
+ 		priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
++		priv->role = (cfg) ? cfg->role : TDA18271_MASTER;
+ 		priv->cal_initialized = false;
+ 		mutex_init(&priv->lock);
+-		priv->count++;
+ 
+ 		fe->tuner_priv = priv;
+ 
+-		list_add_tail(&priv->tda18271_list, &tda18271_list);
++		if (cfg)
++			priv->small_i2c = cfg->small_i2c;
+ 
+ 		if (tda18271_get_id(fe) < 0)
+ 			goto fail;
+@@ -1186,9 +1105,18 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
+ 		tda18271_init_regs(fe);
+ 
+ 		if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2))
+-			tda18271_rf_cal_init(fe);
++			tda18271c2_rf_cal_init(fe);
+ 
+ 		mutex_unlock(&priv->lock);
++		break;
++	default:
++		/* existing tuner instance */
++		fe->tuner_priv = priv;
++
++		/* allow dvb driver to override i2c gate setting */
++		if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
++			priv->gate = cfg->gate;
++		break;
+ 	}
+ 
+ 	/* override default std map with values in config struct */
+@@ -1200,7 +1128,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
+ 	memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
+ 	       sizeof(struct dvb_tuner_ops));
+ 
+-	if (tda18271_debug & DBG_MAP)
++	if (tda18271_debug & (DBG_MAP | DBG_ADV))
+ 		tda18271_dump_std_map(fe);
+ 
+ 	return fe;
+@@ -1214,7 +1142,7 @@ EXPORT_SYMBOL_GPL(tda18271_attach);
+ MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
+ MODULE_AUTHOR("Michael Krufky <mkrufky at linuxtv.org>");
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION("0.2");
++MODULE_VERSION("0.3");
+ 
+ /*
+  * Overrides for Emacs so that we follow Linus's tabbing style.
+diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h
+index 7b939a5..2bc5eb3 100644
+--- a/drivers/media/dvb/frontends/tda18271-priv.h
++++ b/drivers/media/dvb/frontends/tda18271-priv.h
+@@ -24,6 +24,7 @@
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/mutex.h>
++#include "tuner-i2c.h"
+ #include "tda18271.h"
+ 
+ #define R_ID     0x00	/* ID byte                */
+@@ -85,6 +86,11 @@ struct tda18271_rf_tracking_filter_cal {
+ 	int rf_b2;
+ };
+ 
++enum tda18271_pll {
++	TDA18271_MAIN_PLL,
++	TDA18271_CAL_PLL,
++};
++
+ enum tda18271_mode {
+ 	TDA18271_ANALOG,
+ 	TDA18271_DIGITAL,
+@@ -98,19 +104,19 @@ enum tda18271_ver {
+ };
+ 
+ struct tda18271_priv {
+-	u8 i2c_addr;
+-	struct i2c_adapter *i2c_adap;
+ 	unsigned char tda18271_regs[TDA18271_NUM_REGS];
+ 
+-	struct list_head tda18271_list;
++	struct list_head	hybrid_tuner_instance_list;
++	struct tuner_i2c_props	i2c_props;
+ 
+ 	enum tda18271_mode mode;
++	enum tda18271_role role;
+ 	enum tda18271_i2c_gate gate;
+ 	enum tda18271_ver id;
+ 
+-	unsigned int count;
+ 	unsigned int tm_rfcal;
+ 	unsigned int cal_initialized:1;
++	unsigned int small_i2c:1;
+ 
+ 	struct tda18271_map_layout *maps;
+ 	struct tda18271_std_map std;
+@@ -133,7 +139,7 @@ extern int tda18271_debug;
+ #define DBG_CAL  16
+ 
+ #define tda_printk(kern, fmt, arg...) \
+-	printk(kern "%s: " fmt, __FUNCTION__, ##arg)
++	printk(kern "%s: " fmt, __func__, ##arg)
+ 
+ #define dprintk(kern, lvl, fmt, arg...) do {\
+ 	if (tda18271_debug & lvl) \
+@@ -188,6 +194,8 @@ extern int tda18271_read_extended(struct dvb_frontend *fe);
+ extern int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len);
+ extern int tda18271_init_regs(struct dvb_frontend *fe);
+ 
++extern int tda18271_charge_pump_source(struct dvb_frontend *fe,
++				       enum tda18271_pll pll, int force);
+ extern int tda18271_set_standby_mode(struct dvb_frontend *fe,
+ 				     int sm, int sm_lt, int sm_xt);
+ 
+diff --git a/drivers/media/dvb/frontends/tda18271-tables.c b/drivers/media/dvb/frontends/tda18271-tables.c
+index e94afcf..83e7561 100644
+--- a/drivers/media/dvb/frontends/tda18271-tables.c
++++ b/drivers/media/dvb/frontends/tda18271-tables.c
+@@ -1187,37 +1187,65 @@ fail:
+ /*---------------------------------------------------------------------*/
+ 
+ static struct tda18271_std_map tda18271c1_std_map = {
+-	.fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
+-	.atv_b    = { .if_freq = 6750, .std_bits = 0x0e },
+-	.atv_dk   = { .if_freq = 7750, .std_bits = 0x0f },
+-	.atv_gh   = { .if_freq = 7750, .std_bits = 0x0f },
+-	.atv_i    = { .if_freq = 7750, .std_bits = 0x0f },
+-	.atv_l    = { .if_freq = 7750, .std_bits = 0x0f },
+-	.atv_lc   = { .if_freq = 1250, .std_bits = 0x0f },
+-	.atv_mn   = { .if_freq = 5750, .std_bits = 0x0d },
+-	.atsc_6   = { .if_freq = 3250, .std_bits = 0x1c },
+-	.dvbt_6   = { .if_freq = 3300, .std_bits = 0x1c },
+-	.dvbt_7   = { .if_freq = 3800, .std_bits = 0x1d },
+-	.dvbt_8   = { .if_freq = 4300, .std_bits = 0x1e },
+-	.qam_6    = { .if_freq = 4000, .std_bits = 0x1d },
+-	.qam_8    = { .if_freq = 5000, .std_bits = 0x1f },
++	.fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
++	.atv_b    = { .if_freq = 6750, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++	.atv_dk   = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++	.atv_gh   = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++	.atv_i    = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++	.atv_l    = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++	.atv_lc   = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++	.atv_mn   = { .if_freq = 5750, .fm_rfn = 0, .agc_mode = 1, .std = 5,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
++	.atsc_6   = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++	.dvbt_6   = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++	.dvbt_7   = { .if_freq = 3800, .fm_rfn = 0, .agc_mode = 3, .std = 5,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
++	.dvbt_8   = { .if_freq = 4300, .fm_rfn = 0, .agc_mode = 3, .std = 6,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
++	.qam_6    = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
++	.qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
+ };
+ 
+ static struct tda18271_std_map tda18271c2_std_map = {
+-	.fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
+-	.atv_b    = { .if_freq = 6000, .std_bits = 0x0d },
+-	.atv_dk   = { .if_freq = 6900, .std_bits = 0x0e },
+-	.atv_gh   = { .if_freq = 7100, .std_bits = 0x0e },
+-	.atv_i    = { .if_freq = 7250, .std_bits = 0x0e },
+-	.atv_l    = { .if_freq = 6900, .std_bits = 0x0e },
+-	.atv_lc   = { .if_freq = 1250, .std_bits = 0x0e },
+-	.atv_mn   = { .if_freq = 5400, .std_bits = 0x0c },
+-	.atsc_6   = { .if_freq = 3250, .std_bits = 0x1c },
+-	.dvbt_6   = { .if_freq = 3300, .std_bits = 0x1c },
+-	.dvbt_7   = { .if_freq = 3500, .std_bits = 0x1c },
+-	.dvbt_8   = { .if_freq = 4000, .std_bits = 0x1d },
+-	.qam_6    = { .if_freq = 4000, .std_bits = 0x1d },
+-	.qam_8    = { .if_freq = 5000, .std_bits = 0x1f },
++	.fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
++	.atv_b    = { .if_freq = 6000, .fm_rfn = 0, .agc_mode = 1, .std = 5,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
++	.atv_dk   = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++	.atv_gh   = { .if_freq = 7100, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++	.atv_i    = { .if_freq = 7250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++	.atv_l    = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++	.atv_lc   = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++	.atv_mn   = { .if_freq = 5400, .fm_rfn = 0, .agc_mode = 1, .std = 4,
++		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0c */
++	.atsc_6   = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++	.dvbt_6   = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++	.dvbt_7   = { .if_freq = 3500, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++	.dvbt_8   = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
++	.qam_6    = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
++	.qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
++		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
+ };
+ 
+ /*---------------------------------------------------------------------*/
+diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h
+index 24b0e35..0e7af8d 100644
+--- a/drivers/media/dvb/frontends/tda18271.h
++++ b/drivers/media/dvb/frontends/tda18271.h
+@@ -26,7 +26,17 @@
+ 
+ struct tda18271_std_map_item {
+ 	u16 if_freq;
+-	u8 std_bits;
++
++	/* EP3[4:3] */
++	unsigned int agc_mode:2;
++	/* EP3[2:0] */
++	unsigned int std:3;
++	/* EP4[7] */
++	unsigned int fm_rfn:1;
++	/* EP4[4:2] */
++	unsigned int if_lvl:3;
++	/* EB22[6:0] */
++	unsigned int rfagc_top:7;
+ };
+ 
+ struct tda18271_std_map {
+@@ -46,6 +56,11 @@ struct tda18271_std_map {
+ 	struct tda18271_std_map_item qam_8;
+ };
+ 
++enum tda18271_role {
++	TDA18271_MASTER = 0,
++	TDA18271_SLAVE,
++};
++
+ enum tda18271_i2c_gate {
+ 	TDA18271_GATE_AUTO = 0,
+ 	TDA18271_GATE_ANALOG,
+@@ -56,8 +71,14 @@ struct tda18271_config {
+ 	/* override default if freq / std settings (optional) */
+ 	struct tda18271_std_map *std_map;
+ 
++	/* master / slave tuner: master uses main pll, slave uses cal pll */
++	enum tda18271_role role;
++
+ 	/* use i2c gate provided by analog or digital demod */
+ 	enum tda18271_i2c_gate gate;
++
++	/* some i2c providers cant write all 39 registers at once */
++	unsigned int small_i2c:1;
+ };
+ 
+ #if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
+@@ -70,7 +91,7 @@ static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
+ 						   struct i2c_adapter *i2c,
+ 						   struct tda18271_config *cfg)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif
+diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
+index 011b74f..5b843b2 100644
+--- a/drivers/media/dvb/frontends/tda8083.c
++++ b/drivers/media/dvb/frontends/tda8083.c
+@@ -68,7 +68,7 @@ static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
+ 
+ 	if (ret != 1)
+ 		dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
+-			__FUNCTION__, reg, ret);
++			__func__, reg, ret);
+ 
+ 	return (ret != 1) ? -1 : 0;
+ }
+@@ -83,7 +83,7 @@ static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len
+ 
+ 	if (ret != 2)
+ 		dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
+-			__FUNCTION__, reg1, ret);
++			__func__, reg1, ret);
+ 
+ 	return ret == 2 ? 0 : -1;
+ }
+diff --git a/drivers/media/dvb/frontends/tda8083.h b/drivers/media/dvb/frontends/tda8083.h
+index 2d33079..5a03c14 100644
+--- a/drivers/media/dvb/frontends/tda8083.h
++++ b/drivers/media/dvb/frontends/tda8083.h
+@@ -42,7 +42,7 @@ extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
+ static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TDA8083
+diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c
+index bd3ebc2..a051554 100644
+--- a/drivers/media/dvb/frontends/tda826x.c
++++ b/drivers/media/dvb/frontends/tda826x.c
+@@ -26,7 +26,7 @@
+ 
+ #include "tda826x.h"
+ 
+-static int debug = 0;
++static int debug;
+ #define dprintk(args...) \
+ 	do { \
+ 		if (debug) printk(KERN_DEBUG "tda826x: " args); \
+@@ -54,7 +54,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
+ 	u8 buf [] = { 0x00, 0x8d };
+ 	struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 };
+ 
+-	dprintk("%s:\n", __FUNCTION__);
++	dprintk("%s:\n", __func__);
+ 
+ 	if (!priv->has_loopthrough)
+ 		buf[1] = 0xad;
+@@ -62,7 +62,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+ 	if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+-		dprintk("%s: i2c error\n", __FUNCTION__);
++		dprintk("%s: i2c error\n", __func__);
+ 	}
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 0);
+@@ -75,13 +75,24 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
+ 	struct tda826x_priv *priv = fe->tuner_priv;
+ 	int ret;
+ 	u32 div;
++	u32 ksyms;
++	u32 bandwidth;
+ 	u8 buf [11];
+ 	struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 };
+ 
+-	dprintk("%s:\n", __FUNCTION__);
++	dprintk("%s:\n", __func__);
+ 
+ 	div = (params->frequency + (1000-1)) / 1000;
+ 
++	/* BW = ((1 + RO) * SR/2 + 5) * 1.3      [SR in MSPS, BW in MHz] */
++	/* with R0 = 0.35 and some transformations: */
++	ksyms = params->u.qpsk.symbol_rate / 1000;
++	bandwidth = (878 * ksyms + 6500000) / 1000000 + 1;
++	if (bandwidth < 5)
++		bandwidth = 5;
++	else if (bandwidth > 36)
++		bandwidth = 36;
++
+ 	buf[0] = 0x00; // subaddress
+ 	buf[1] = 0x09; // powerdown RSSI + the magic value 1
+ 	if (!priv->has_loopthrough)
+@@ -89,7 +100,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
+ 	buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
+ 	buf[3] = div >> 7;
+ 	buf[4] = div << 1;
+-	buf[5] = 0x77; // baseband cut-off 19 MHz
++	buf[5] = ((bandwidth - 5) << 3) | 7; /* baseband cut-off */
+ 	buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
+ 	buf[7] = 0x83; // charge pumps at high, tests off
+ 	buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
+@@ -99,7 +110,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+ 	if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+-		dprintk("%s: i2c error\n", __FUNCTION__);
++		dprintk("%s: i2c error\n", __func__);
+ 	}
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 0);
+@@ -138,7 +149,7 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2
+ 	};
+ 	int ret;
+ 
+-	dprintk("%s:\n", __FUNCTION__);
++	dprintk("%s:\n", __func__);
+ 
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+diff --git a/drivers/media/dvb/frontends/tda826x.h b/drivers/media/dvb/frontends/tda826x.h
+index ad99811..89e9792 100644
+--- a/drivers/media/dvb/frontends/tda826x.h
++++ b/drivers/media/dvb/frontends/tda826x.h
+@@ -45,7 +45,7 @@ static inline struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe,
+ 						  struct i2c_adapter *i2c,
+ 						  int has_loopthrough)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TDA826X
+diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c
+index 229b119..d30d2c9 100644
+--- a/drivers/media/dvb/frontends/tda827x.c
++++ b/drivers/media/dvb/frontends/tda827x.c
+@@ -25,7 +25,7 @@
+ 
+ #include "tda827x.h"
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+ 
+@@ -142,7 +142,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
+ 	int i, tuner_freq, if_freq;
+ 	u32 N;
+ 
+-	dprintk("%s:\n", __FUNCTION__);
++	dprintk("%s:\n", __func__);
+ 	switch (params->u.ofdm.bandwidth) {
+ 	case BANDWIDTH_6_MHZ:
+ 		if_freq = 4000000;
+@@ -186,7 +186,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+ 	if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
+ 		printk("%s: could not write to tuner at addr: 0x%02x\n",
+-		       __FUNCTION__, priv->i2c_addr << 1);
++		       __func__, priv->i2c_addr << 1);
+ 		return -EIO;
+ 	}
+ 	msleep(500);
+@@ -212,7 +212,7 @@ static int tda827xo_sleep(struct dvb_frontend *fe)
+ 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+ 			       .buf = buf, .len = sizeof(buf) };
+ 
+-	dprintk("%s:\n", __FUNCTION__);
++	dprintk("%s:\n", __func__);
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+ 	i2c_transfer(priv->i2c_adap, &msg, 1);
+@@ -389,6 +389,79 @@ static struct tda827xa_data tda827xa_analog[] = {
+ 	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
+ };
+ 
++static int tda827xa_sleep(struct dvb_frontend *fe)
++{
++	struct tda827x_priv *priv = fe->tuner_priv;
++	static u8 buf[] = { 0x30, 0x90 };
++	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
++			       .buf = buf, .len = sizeof(buf) };
++
++	dprintk("%s:\n", __func__);
++	if (fe->ops.i2c_gate_ctrl)
++		fe->ops.i2c_gate_ctrl(fe, 1);
++
++	i2c_transfer(priv->i2c_adap, &msg, 1);
++
++	if (fe->ops.i2c_gate_ctrl)
++		fe->ops.i2c_gate_ctrl(fe, 0);
++
++	if (priv->cfg && priv->cfg->sleep)
++		priv->cfg->sleep(fe);
++
++	return 0;
++}
++
++static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
++			      struct analog_parameters *params)
++{
++	struct tda827x_priv *priv = fe->tuner_priv;
++	unsigned char buf[] = {0x22, 0x01};
++	int arg;
++	int gp_func;
++	struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0,
++			       .buf = buf, .len = sizeof(buf) };
++
++	if (NULL == priv->cfg) {
++		dprintk("tda827x_config not defined, cannot set LNA gain!\n");
++		return;
++	}
++	if (priv->cfg->config) {
++		if (high)
++			dprintk("setting LNA to high gain\n");
++		else
++			dprintk("setting LNA to low gain\n");
++	}
++	switch (priv->cfg->config) {
++	case 0: /* no LNA */
++		break;
++	case 1: /* switch is GPIO 0 of tda8290 */
++	case 2:
++		if (params == NULL) {
++			gp_func = 0;
++			arg  = 0;
++		} else {
++			/* turn Vsync on */
++			gp_func = 1;
++			if (params->std & V4L2_STD_MN)
++				arg = 1;
++			else
++				arg = 0;
++		}
++		if (priv->cfg->tuner_callback)
++			priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
++								gp_func, arg);
++		buf[1] = high ? 0 : 1;
++		if (priv->cfg->config == 2)
++			buf[1] = high ? 1 : 0;
++		i2c_transfer(priv->i2c_adap, &msg, 1);
++		break;
++	case 3: /* switch with GPIO of saa713x */
++		if (priv->cfg->tuner_callback)
++			priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high);
++		break;
++	}
++}
++
+ static int tda827xa_set_params(struct dvb_frontend *fe,
+ 			       struct dvb_frontend_parameters *params)
+ {
+@@ -401,9 +474,9 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
+ 	int i, tuner_freq, if_freq;
+ 	u32 N;
+ 
+-	dprintk("%s:\n", __FUNCTION__);
+-	if (priv->cfg && priv->cfg->lna_gain)
+-		priv->cfg->lna_gain(fe, 1);
++	dprintk("%s:\n", __func__);
++
++	tda827xa_lna_gain(fe, 1, NULL);
+ 	msleep(20);
+ 
+ 	switch (params->u.ofdm.bandwidth) {
+@@ -444,7 +517,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+ 	if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
+ 		printk("%s: could not write to tuner at addr: 0x%02x\n",
+-		       __FUNCTION__, priv->i2c_addr << 1);
++		       __func__, priv->i2c_addr << 1);
+ 		return -EIO;
+ 	}
+ 	buf[0] = 0x90;
+@@ -474,8 +547,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
+ 	buf[1] >>= 4;
+ 	dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
+ 	if ((buf[1]) < 2) {
+-		if (priv->cfg && priv->cfg->lna_gain)
+-			priv->cfg->lna_gain(fe, 0);
++		tda827xa_lna_gain(fe, 0, NULL);
+ 		buf[0] = 0x60;
+ 		buf[1] = 0x0c;
+ 		if (fe->ops.i2c_gate_ctrl)
+@@ -523,75 +595,6 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
+ 	return 0;
+ }
+ 
+-static int tda827xa_sleep(struct dvb_frontend *fe)
+-{
+-	struct tda827x_priv *priv = fe->tuner_priv;
+-	static u8 buf[] = { 0x30, 0x90 };
+-	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+-			       .buf = buf, .len = sizeof(buf) };
+-
+-	dprintk("%s:\n", __FUNCTION__);
+-	if (fe->ops.i2c_gate_ctrl)
+-		fe->ops.i2c_gate_ctrl(fe, 1);
+-
+-	i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+-	if (fe->ops.i2c_gate_ctrl)
+-		fe->ops.i2c_gate_ctrl(fe, 0);
+-
+-	if (priv->cfg && priv->cfg->sleep)
+-		priv->cfg->sleep(fe);
+-
+-	return 0;
+-}
+-
+-/* ------------------------------------------------------------------ */
+-
+-static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
+-			      struct analog_parameters *params)
+-{
+-	struct tda827x_priv *priv = fe->tuner_priv;
+-	unsigned char buf[] = {0x22, 0x01};
+-	int arg;
+-	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+-			       .buf = buf, .len = sizeof(buf) };
+-
+-	if (NULL == priv->cfg) {
+-		dprintk("tda827x_config not defined, cannot set LNA gain!\n");
+-		return;
+-	}
+-
+-	if (priv->cfg->config) {
+-		if (high)
+-			dprintk("setting LNA to high gain\n");
+-		else
+-			dprintk("setting LNA to low gain\n");
+-	}
+-	switch (*priv->cfg->config) {
+-	case 0: /* no LNA */
+-		break;
+-	case 1: /* switch is GPIO 0 of tda8290 */
+-	case 2:
+-		/* turn Vsync on */
+-		if (params->std & V4L2_STD_MN)
+-			arg = 1;
+-		else
+-			arg = 0;
+-		if (priv->cfg->tuner_callback)
+-			priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
+-						  1, arg);
+-		buf[1] = high ? 0 : 1;
+-		if (*priv->cfg->config == 2)
+-			buf[1] = high ? 1 : 0;
+-		i2c_transfer(priv->i2c_adap, &msg, 1);
+-		break;
+-	case 3: /* switch with GPIO of saa713x */
+-		if (priv->cfg->tuner_callback)
+-			priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
+-						  0, high);
+-		break;
+-	}
+-}
+ 
+ static int tda827xa_set_analog_params(struct dvb_frontend *fe,
+ 				      struct analog_parameters *params)
+@@ -726,7 +729,7 @@ static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+ static int tda827x_init(struct dvb_frontend *fe)
+ {
+ 	struct tda827x_priv *priv = fe->tuner_priv;
+-	dprintk("%s:\n", __FUNCTION__);
++	dprintk("%s:\n", __func__);
+ 	if (priv->cfg && priv->cfg->init)
+ 		priv->cfg->init(fe);
+ 
+@@ -794,7 +797,7 @@ static int tda827x_probe_version(struct dvb_frontend *fe)
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+ 	if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
+ 		printk("%s: could not read from tuner at addr: 0x%02x\n",
+-		       __FUNCTION__, msg.addr << 1);
++		       __func__, msg.addr << 1);
+ 		return -EIO;
+ 	}
+ 	if ((data & 0x3c) == 0) {
+@@ -818,7 +821,7 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
+ {
+ 	struct tda827x_priv *priv = NULL;
+ 
+-	dprintk("%s:\n", __FUNCTION__);
++	dprintk("%s:\n", __func__);
+ 	priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
+ 	if (priv == NULL)
+ 		return NULL;
+diff --git a/drivers/media/dvb/frontends/tda827x.h b/drivers/media/dvb/frontends/tda827x.h
+index 92eb65b..b73c235 100644
+--- a/drivers/media/dvb/frontends/tda827x.h
++++ b/drivers/media/dvb/frontends/tda827x.h
+@@ -30,12 +30,12 @@
+ struct tda827x_config
+ {
+ 	/* saa7134 - provided callbacks */
+-	void (*lna_gain) (struct dvb_frontend *fe, int high);
+ 	int (*init) (struct dvb_frontend *fe);
+ 	int (*sleep) (struct dvb_frontend *fe);
+ 
+ 	/* interface to tda829x driver */
+-	unsigned int *config;
++	unsigned int config;
++	int 	     switch_addr;
+ 	int (*tuner_callback) (void *dev, int command, int arg);
+ 
+ 	void (*agcf)(struct dvb_frontend *fe);
+@@ -61,7 +61,7 @@ static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe,
+ 						  struct i2c_adapter *i2c,
+ 						  struct tda827x_config *cfg)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TDA827X
+diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c
+index 6ba0029..1790bae 100644
+--- a/drivers/media/dvb/frontends/tua6100.c
++++ b/drivers/media/dvb/frontends/tua6100.c
+@@ -58,7 +58,7 @@ static int tua6100_sleep(struct dvb_frontend *fe)
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 1);
+ 	if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+-		printk("%s: i2c error\n", __FUNCTION__);
++		printk("%s: i2c error\n", __func__);
+ 	}
+ 	if (fe->ops.i2c_gate_ctrl)
+ 		fe->ops.i2c_gate_ctrl(fe, 0);
+diff --git a/drivers/media/dvb/frontends/tua6100.h b/drivers/media/dvb/frontends/tua6100.h
+index 03a665e..f83dbd5 100644
+--- a/drivers/media/dvb/frontends/tua6100.h
++++ b/drivers/media/dvb/frontends/tua6100.h
+@@ -39,7 +39,7 @@ extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, st
+ #else
+ static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TUA6100
+diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
+index 8791701..a184597 100644
+--- a/drivers/media/dvb/frontends/ves1820.c
++++ b/drivers/media/dvb/frontends/ves1820.c
+@@ -66,7 +66,7 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
+ 
+ 	if (ret != 1)
+ 		printk("ves1820: %s(): writereg error (reg == 0x%02x, "
+-			"val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret);
++			"val == 0x%02x, ret == %i)\n", __func__, reg, data, ret);
+ 
+ 	return (ret != 1) ? -EREMOTEIO : 0;
+ }
+@@ -85,7 +85,7 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
+ 
+ 	if (ret != 2)
+ 		printk("ves1820: %s(): readreg error (reg == 0x%02x, "
+-		"ret == %i)\n", __FUNCTION__, reg, ret);
++		"ret == %i)\n", __func__, reg, ret);
+ 
+ 	return b1[0];
+ }
+diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb/frontends/ves1820.h
+index e4a2a32..e902ed6 100644
+--- a/drivers/media/dvb/frontends/ves1820.h
++++ b/drivers/media/dvb/frontends/ves1820.h
+@@ -48,7 +48,7 @@ extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
+ static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
+ 					   struct i2c_adapter* i2c, u8 pwm)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_VES1820
+diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c
+index 23fd030..bd55896 100644
+--- a/drivers/media/dvb/frontends/ves1x93.c
++++ b/drivers/media/dvb/frontends/ves1x93.c
+@@ -48,7 +48,7 @@ struct ves1x93_state {
+ 	u8 demod_type;
+ };
+ 
+-static int debug = 0;
++static int debug;
+ #define dprintk	if (debug) printk
+ 
+ #define DEMOD_VES1893		0
+@@ -98,7 +98,7 @@ static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
+ 	int err;
+ 
+ 	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+-		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
++		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+ 		return -EREMOTEIO;
+ 	}
+ 
+@@ -179,7 +179,7 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
+ 	u32 tmp;
+ 	u32 FIN;
+ 
+-	dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate);
++	dprintk("%s: srate == %d\n", __func__, (unsigned int) srate);
+ 
+ 	if (srate > state->config->xin/2)
+ 		srate = state->config->xin/2;
+@@ -266,7 +266,7 @@ static int ves1x93_init (struct dvb_frontend* fe)
+ 	int i;
+ 	int val;
+ 
+-	dprintk("%s: init chip\n", __FUNCTION__);
++	dprintk("%s: init chip\n", __func__);
+ 
+ 	for (i = 0; i < state->tab_size; i++) {
+ 		if (state->init_1x93_wtab[i]) {
+diff --git a/drivers/media/dvb/frontends/ves1x93.h b/drivers/media/dvb/frontends/ves1x93.h
+index d507f89..8a5a49e 100644
+--- a/drivers/media/dvb/frontends/ves1x93.h
++++ b/drivers/media/dvb/frontends/ves1x93.h
+@@ -47,7 +47,7 @@ extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
+ static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
+ 					   struct i2c_adapter* i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_VES1X93
+diff --git a/drivers/media/dvb/frontends/xc5000.c b/drivers/media/dvb/frontends/xc5000.c
+index f642ca2..43d35bd 100644
+--- a/drivers/media/dvb/frontends/xc5000.c
++++ b/drivers/media/dvb/frontends/xc5000.c
+@@ -151,7 +151,7 @@ typedef struct {
+ #define FM_Radio_INPUT2 	21
+ #define FM_Radio_INPUT1 	22
+ 
+-XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
++static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
+ 	{"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
+ 	{"M/N-NTSC/PAL-A2",   0x0600, 0x8020},
+ 	{"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
+@@ -209,7 +209,7 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
+ 	struct xc5000_priv *priv = fe->tuner_priv;
+ 	int ret;
+ 
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	if (priv->cfg->tuner_callback) {
+ 		ret = priv->cfg->tuner_callback(priv->cfg->priv,
+@@ -330,7 +330,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
+ 
+ static int xc_initialize(struct xc5000_priv *priv)
+ {
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	return xc_write_reg(priv, XREG_INIT, 0);
+ }
+ 
+@@ -338,9 +338,9 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
+ 	u16 VideoMode, u16 AudioMode)
+ {
+ 	int ret;
+-	dprintk(1, "%s(0x%04x,0x%04x)\n", __FUNCTION__, VideoMode, AudioMode);
++	dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
+ 	dprintk(1, "%s() Standard = %s\n",
+-		__FUNCTION__,
++		__func__,
+ 		XC5000_Standard[priv->video_standard].Name);
+ 
+ 	ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
+@@ -361,7 +361,7 @@ static int xc_shutdown(struct xc5000_priv *priv)
+ 
+ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
+ {
+-	dprintk(1, "%s(%d) Source = %s\n", __FUNCTION__, rf_mode,
++	dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
+ 		rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
+ 
+ 	if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
+@@ -369,7 +369,7 @@ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
+ 		rf_mode = XC_RF_MODE_CABLE;
+ 		printk(KERN_ERR
+ 			"%s(), Invalid mode, defaulting to CABLE",
+-			__FUNCTION__);
++			__func__);
+ 	}
+ 	return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
+ }
+@@ -380,7 +380,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
+ {
+ 	u16 freq_code;
+ 
+-	dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
++	dprintk(1, "%s(%u)\n", __func__, freq_hz);
+ 
+ 	if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
+ 		(freq_hz < xc5000_tuner_ops.info.frequency_min))
+@@ -396,7 +396,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
+ {
+ 	u32 freq_code = (freq_khz * 1024)/1000;
+ 	dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
+-		__FUNCTION__, freq_khz, freq_code);
++		__func__, freq_khz, freq_code);
+ 
+ 	return xc_write_reg(priv, XREG_IF_OUT, freq_code);
+ }
+@@ -488,7 +488,7 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
+ {
+ 	int found = 0;
+ 
+-	dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
++	dprintk(1, "%s(%u)\n", __func__, freq_hz);
+ 
+ 	if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
+ 		return 0;
+@@ -627,12 +627,12 @@ static int xc5000_set_params(struct dvb_frontend *fe,
+ 	struct xc5000_priv *priv = fe->tuner_priv;
+ 	int ret;
+ 
+-	dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency);
++	dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
+ 
+ 	switch(params->u.vsb.modulation) {
+ 	case VSB_8:
+ 	case VSB_16:
+-		dprintk(1, "%s() VSB modulation\n", __FUNCTION__);
++		dprintk(1, "%s() VSB modulation\n", __func__);
+ 		priv->rf_mode = XC_RF_MODE_AIR;
+ 		priv->freq_hz = params->frequency - 1750000;
+ 		priv->bandwidth = BANDWIDTH_6_MHZ;
+@@ -641,7 +641,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
+ 	case QAM_64:
+ 	case QAM_256:
+ 	case QAM_AUTO:
+-		dprintk(1, "%s() QAM modulation\n", __FUNCTION__);
++		dprintk(1, "%s() QAM modulation\n", __func__);
+ 		priv->rf_mode = XC_RF_MODE_CABLE;
+ 		priv->freq_hz = params->frequency - 1750000;
+ 		priv->bandwidth = BANDWIDTH_6_MHZ;
+@@ -652,7 +652,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
+ 	}
+ 
+ 	dprintk(1, "%s() frequency=%d (compensated)\n",
+-		__FUNCTION__, priv->freq_hz);
++		__func__, priv->freq_hz);
+ 
+ 	ret = xc_SetSignalSource(priv, priv->rf_mode);
+ 	if (ret != XC_RESULT_SUCCESS) {
+@@ -697,7 +697,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
+ 		xc_load_fw_and_init_tuner(fe);
+ 
+ 	dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
+-		__FUNCTION__, params->frequency);
++		__func__, params->frequency);
+ 
+ 	priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
+ 
+@@ -775,7 +775,7 @@ tune_channel:
+ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
+ {
+ 	struct xc5000_priv *priv = fe->tuner_priv;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	*freq = priv->freq_hz;
+ 	return 0;
+ }
+@@ -783,7 +783,7 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
+ static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
+ {
+ 	struct xc5000_priv *priv = fe->tuner_priv;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	*bw = priv->bandwidth;
+ 	return 0;
+@@ -796,7 +796,7 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
+ 
+ 	xc_get_lock_status(priv, &lock_status);
+ 
+-	dprintk(1, "%s() lock_status = 0x%08x\n", __FUNCTION__, lock_status);
++	dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
+ 
+ 	*status = lock_status;
+ 
+@@ -836,7 +836,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
+ 	struct xc5000_priv *priv = fe->tuner_priv;
+ 	int ret;
+ 
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	/* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
+ 	 * once shutdown without reloading the driver. Maybe I am not
+@@ -848,7 +848,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
+ 	if(ret != XC_RESULT_SUCCESS) {
+ 		printk(KERN_ERR
+ 			"xc5000: %s() unable to shutdown tuner\n",
+-			__FUNCTION__);
++			__func__);
+ 		return -EREMOTEIO;
+ 	}
+ 	else {
+@@ -860,7 +860,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
+ static int xc5000_init(struct dvb_frontend *fe)
+ {
+ 	struct xc5000_priv *priv = fe->tuner_priv;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
+ 		printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
+@@ -875,7 +875,7 @@ static int xc5000_init(struct dvb_frontend *fe)
+ 
+ static int xc5000_release(struct dvb_frontend *fe)
+ {
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	kfree(fe->tuner_priv);
+ 	fe->tuner_priv = NULL;
+ 	return 0;
+@@ -907,7 +907,7 @@ struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
+ 	struct xc5000_priv *priv = NULL;
+ 	u16 id = 0;
+ 
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
+ 	if (priv == NULL)
+diff --git a/drivers/media/dvb/frontends/xc5000.h b/drivers/media/dvb/frontends/xc5000.h
+index 32a5f1c..b890883 100644
+--- a/drivers/media/dvb/frontends/xc5000.h
++++ b/drivers/media/dvb/frontends/xc5000.h
+@@ -55,7 +55,7 @@ static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
+ 						 struct i2c_adapter *i2c,
+ 						 struct xc5000_config *cfg)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif // CONFIG_DVB_TUNER_XC5000
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index 276e3b6..36a5a1c 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -46,7 +46,7 @@ static int debug;
+ 		if (debug) printk(KERN_DEBUG "zl10353: " args); \
+ 	} while (0)
+ 
+-static int debug_regs = 0;
++static int debug_regs;
+ 
+ static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
+ {
+@@ -88,7 +88,7 @@ static int zl10353_read_register(struct zl10353_state *state, u8 reg)
+ 
+ 	if (ret != 2) {
+ 		printk("%s: readreg error (reg=%d, ret==%i)\n",
+-		       __FUNCTION__, reg, ret);
++		       __func__, reg, ret);
+ 		return ret;
+ 	}
+ 
+@@ -152,7 +152,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+ 	*nominal_rate = value;
+ 
+ 	dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+-		__FUNCTION__, bw, adc_clock, *nominal_rate);
++		__func__, bw, adc_clock, *nominal_rate);
+ }
+ 
+ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
+@@ -181,7 +181,7 @@ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
+ 	*input_freq = -value;
+ 
+ 	dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
+-		__FUNCTION__, if2, ife, adc_clock, -(int)value, *input_freq);
++		__func__, if2, ife, adc_clock, -(int)value, *input_freq);
+ }
+ 
+ static int zl10353_sleep(struct dvb_frontend *fe)
+diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
+index fc734c2..fdbb88f 100644
+--- a/drivers/media/dvb/frontends/zl10353.h
++++ b/drivers/media/dvb/frontends/zl10353.h
+@@ -47,7 +47,7 @@ extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
+ static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
+ 					   struct i2c_adapter *i2c)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif /* CONFIG_DVB_ZL10353 */
+diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
+index 08a2599..960ed57 100644
+--- a/drivers/media/dvb/pluto2/pluto2.c
++++ b/drivers/media/dvb/pluto2/pluto2.c
+@@ -39,6 +39,8 @@
+ #include "dvbdev.h"
+ #include "tda1004x.h"
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define DRIVER_NAME		"pluto2"
+ 
+ #define REG_PIDn(n)		((n) << 2)	/* PID n pattern registers */
+@@ -662,7 +664,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
+ 		goto err_pluto_hw_exit;
+ 
+ 	/* dvb */
+-	ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
++	ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME,
++				   THIS_MODULE, &pdev->dev, adapter_nr);
+ 	if (ret < 0)
+ 		goto err_i2c_del_adapter;
+ 
+diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
+index 0e5701b..747e7f1 100644
+--- a/drivers/media/dvb/ttpci/av7110.c
++++ b/drivers/media/dvb/ttpci/av7110.c
+@@ -112,6 +112,8 @@ MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14:
+ module_param(tv_standard, int, 0444);
+ MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static void restart_feeds(struct av7110 *av7110);
+ 
+ static int av7110_num;
+@@ -359,7 +361,7 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir,
+ {
+ 	dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
+ 	if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
+-		printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
++		printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -497,7 +499,7 @@ static void gpioirq(unsigned long data)
+ 		       saa7146_read(av7110->dev, SSR));
+ 
+ 	if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
+-		printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
++		printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
+ 		BUG(); /* maybe we should try resetting the debi? */
+ 	}
+ 
+@@ -827,7 +829,7 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
+ 	if (ret != 0 || handle >= 32) {
+ 		printk("dvb-ttpci: %s error  buf %04x %04x %04x %04x  "
+ 				"ret %d  handle %04x\n",
+-				__FUNCTION__, buf[0], buf[1], buf[2], buf[3],
++				__func__, buf[0], buf[1], buf[2], buf[3],
+ 				ret, handle);
+ 		dvbdmxfilter->hw_handle = 0xffff;
+ 		if (!ret)
+@@ -854,7 +856,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
+ 	handle = dvbdmxfilter->hw_handle;
+ 	if (handle >= 32) {
+ 		printk("%s tried to stop invalid filter %04x, filter type = %x\n",
+-				__FUNCTION__, handle, dvbdmxfilter->type);
++				__func__, handle, dvbdmxfilter->type);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -867,7 +869,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
+ 	if (ret != 0 || answ[1] != handle) {
+ 		printk("dvb-ttpci: %s error  cmd %04x %04x %04x  ret %x  "
+ 				"resp %04x %04x  pid %d\n",
+-				__FUNCTION__, buf[0], buf[1], buf[2], ret,
++				__func__, buf[0], buf[1], buf[2], ret,
+ 				answ[0], answ[1], dvbdmxfilter->feed->pid);
+ 		if (!ret)
+ 			ret = -1;
+@@ -1122,7 +1124,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
+ 
+ 	ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
+ 	if (ret) {
+-		printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
++		printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
+ 		return ret;
+ 	}
+ 	dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
+@@ -2461,7 +2463,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
+ 		goto err_kfree_0;
+ 
+ 	ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
+-				   THIS_MODULE, &dev->pci->dev);
++				   THIS_MODULE, &dev->pci->dev, adapter_nr);
+ 	if (ret < 0)
+ 		goto err_put_firmware_1;
+ 
+diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
+index 39fbf7d..e494e04 100644
+--- a/drivers/media/dvb/ttpci/av7110.h
++++ b/drivers/media/dvb/ttpci/av7110.h
+@@ -40,7 +40,7 @@
+ extern int av7110_debug;
+ 
+ #define dprintk(level,args...) \
+-	    do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __FUNCTION__); printk(args); } } while (0)
++	    do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __func__); printk(args); } } while (0)
+ 
+ #define MAXFILT 32
+ 
+diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
+index a468aa2..9d81074 100644
+--- a/drivers/media/dvb/ttpci/av7110_hw.c
++++ b/drivers/media/dvb/ttpci/av7110_hw.c
+@@ -53,11 +53,11 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config,
+ 	struct saa7146_dev *dev = av7110->dev;
+ 
+ 	if (count <= 0 || count > 32764) {
+-		printk("%s: invalid count %d\n", __FUNCTION__, count);
++		printk("%s: invalid count %d\n", __func__, count);
+ 		return -1;
+ 	}
+ 	if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
+-		printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
++		printk("%s: wait_for_debi_done failed\n", __func__);
+ 		return -1;
+ 	}
+ 	saa7146_write(dev, DEBI_CONFIG, config);
+@@ -76,11 +76,11 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
+ 	u32 result = 0;
+ 
+ 	if (count > 32764 || count <= 0) {
+-		printk("%s: invalid count %d\n", __FUNCTION__, count);
++		printk("%s: invalid count %d\n", __func__, count);
+ 		return 0;
+ 	}
+ 	if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
+-		printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
++		printk("%s: wait_for_debi_done #1 failed\n", __func__);
+ 		return 0;
+ 	}
+ 	saa7146_write(dev, DEBI_AD, av7110->debi_bus);
+@@ -91,7 +91,7 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
+ 	if (count > 4)
+ 		return count;
+ 	if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
+-		printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
++		printk("%s: wait_for_debi_done #2 failed\n", __func__);
+ 		return 0;
+ 	}
+ 
+@@ -332,7 +332,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
+ 			break;
+ 		if (err) {
+ 			printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
+-				__FUNCTION__, stat & flags);
++				__func__, stat & flags);
+ 			return -ETIMEDOUT;
+ 		}
+ 		msleep(1);
+@@ -362,7 +362,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ 		if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+ 			break;
+ 		if (err) {
+-			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
++			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__);
+ 			av7110->arm_errors++;
+ 			return -ETIMEDOUT;
+ 		}
+@@ -379,7 +379,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ 		if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+ 			break;
+ 		if (err) {
+-			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
++			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__);
+ 			return -ETIMEDOUT;
+ 		}
+ 		msleep(1);
+@@ -419,14 +419,14 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ 			stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ 			if (stat & flags[0]) {
+ 				printk(KERN_ERR "%s: %s QUEUE overflow\n",
+-					__FUNCTION__, type);
++					__func__, type);
+ 				return -1;
+ 			}
+ 			if ((stat & flags[1]) == 0)
+ 				break;
+ 			if (err) {
+ 				printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
+-					__FUNCTION__, type);
++					__func__, type);
+ 				return -ETIMEDOUT;
+ 			}
+ 			msleep(1);
+@@ -454,7 +454,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ 			break;
+ 		if (err) {
+ 			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
+-			       __FUNCTION__, (buf[0] >> 8) & 0xff);
++			       __func__, (buf[0] >> 8) & 0xff);
+ 			return -ETIMEDOUT;
+ 		}
+ 		msleep(1);
+@@ -462,11 +462,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ 
+ 	stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ 	if (stat & GPMQOver) {
+-		printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
++		printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __func__);
+ 		return -ENOSPC;
+ 	}
+ 	else if (stat & OSDQOver) {
+-		printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
++		printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__);
+ 		return -ENOSPC;
+ 	}
+ #endif
+@@ -491,7 +491,7 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ 	mutex_unlock(&av7110->dcomlock);
+ 	if (ret && ret!=-ERESTARTSYS)
+ 		printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
+-		       __FUNCTION__, ret);
++		       __func__, ret);
+ 	return ret;
+ }
+ 
+@@ -575,7 +575,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
+ 		if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+ 			break;
+ 		if (err) {
+-			printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
++			printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __func__);
+ 			mutex_unlock(&av7110->dcomlock);
+ 			return -ETIMEDOUT;
+ 		}
+@@ -591,7 +591,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
+ 		if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+ 			break;
+ 		if (err) {
+-			printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
++			printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __func__);
+ 			mutex_unlock(&av7110->dcomlock);
+ 			return -ETIMEDOUT;
+ 		}
+@@ -602,12 +602,12 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
+ #ifdef COM_DEBUG
+ 	stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ 	if (stat & GPMQOver) {
+-		printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
++		printk(KERN_ERR "%s: GPMQOver\n", __func__);
+ 		mutex_unlock(&av7110->dcomlock);
+ 		return -1;
+ 	}
+ 	else if (stat & OSDQOver) {
+-		printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
++		printk(KERN_ERR "%s: OSDQOver\n", __func__);
+ 		mutex_unlock(&av7110->dcomlock);
+ 		return -1;
+ 	}
+@@ -741,7 +741,7 @@ static int FlushText(struct av7110 *av7110)
+ 			break;
+ 		if (err) {
+ 			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			mutex_unlock(&av7110->dcomlock);
+ 			return -ETIMEDOUT;
+ 		}
+@@ -768,7 +768,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
+ 			break;
+ 		if (ret) {
+ 			printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			mutex_unlock(&av7110->dcomlock);
+ 			return -ETIMEDOUT;
+ 		}
+@@ -782,7 +782,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
+ 			break;
+ 		if (ret) {
+ 			printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			mutex_unlock(&av7110->dcomlock);
+ 			return -ETIMEDOUT;
+ 		}
+diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
+index a283e1d..23a1c63 100644
+--- a/drivers/media/dvb/ttpci/av7110_ir.c
++++ b/drivers/media/dvb/ttpci/av7110_ir.c
+@@ -133,7 +133,7 @@ static void av7110_emit_key(unsigned long parm)
+ 		break;
+ 
+ 	default:
+-		printk("%s invalid protocol %x\n", __FUNCTION__, ir->protocol);
++		printk("%s invalid protocol %x\n", __func__, ir->protocol);
+ 		return;
+ 	}
+ 
+@@ -143,7 +143,7 @@ static void av7110_emit_key(unsigned long parm)
+ 	keycode = ir->key_map[data];
+ 
+ 	dprintk(16, "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n",
+-		__FUNCTION__, ircom, addr, data, keycode);
++		__func__, ircom, addr, data, keycode);
+ 
+ 	/* check device address */
+ 	if (!(ir->device_mask & (1 << addr)))
+@@ -151,7 +151,7 @@ static void av7110_emit_key(unsigned long parm)
+ 
+ 	if (!keycode) {
+ 		printk ("%s: code %08x -> addr %i data 0x%02x -> unknown key!\n",
+-			__FUNCTION__, ircom, addr, data);
++			__func__, ircom, addr, data);
+ 		return;
+ 	}
+ 
+diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
+index e2f066f..b4a0cc5 100644
+--- a/drivers/media/dvb/ttpci/av7110_v4l.c
++++ b/drivers/media/dvb/ttpci/av7110_v4l.c
+@@ -573,7 +573,7 @@ static int av7110_vbi_reset(struct inode *inode, struct file *file)
+ 	struct saa7146_dev *dev = fh->dev;
+ 	struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+ 
+-	dprintk(2, "%s\n", __FUNCTION__);
++	dprintk(2, "%s\n", __func__);
+ 	av7110->wssMode = 0;
+ 	av7110->wssData = 0;
+ 	if (FW_VERSION(av7110->arm_app) < 0x2623)
+@@ -590,7 +590,7 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size
+ 	struct v4l2_sliced_vbi_data d;
+ 	int rc;
+ 
+-	dprintk(2, "%s\n", __FUNCTION__);
++	dprintk(2, "%s\n", __func__);
+ 	if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
+ 		return -EINVAL;
+ 	if (copy_from_user(&d, data, count))
+diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
+index 2d64d55..b30a528 100644
+--- a/drivers/media/dvb/ttpci/budget-av.c
++++ b/drivers/media/dvb/ttpci/budget-av.c
+@@ -178,7 +178,7 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
+ 	udelay(1);
+ 
+ 	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
+-	if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
++	if (result == -ETIMEDOUT) {
+ 		ciintf_slot_shutdown(ca, slot);
+ 		printk(KERN_INFO "budget-av: cam ejected 3\n");
+ 		return -ETIMEDOUT;
+@@ -577,7 +577,7 @@ static struct stv0299_config typhoon_config = {
+ 	.mclk = 88000000UL,
+ 	.invert = 0,
+ 	.skip_reinit = 0,
+-	.lock_output = STV0229_LOCKOUTPUT_1,
++	.lock_output = STV0299_LOCKOUTPUT_1,
+ 	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+ 	.min_delay_ms = 100,
+ 	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+@@ -590,7 +590,7 @@ static struct stv0299_config cinergy_1200s_config = {
+ 	.mclk = 88000000UL,
+ 	.invert = 0,
+ 	.skip_reinit = 0,
+-	.lock_output = STV0229_LOCKOUTPUT_0,
++	.lock_output = STV0299_LOCKOUTPUT_0,
+ 	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+ 	.min_delay_ms = 100,
+ 	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+@@ -602,7 +602,7 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = {
+ 	.mclk = 88000000UL,
+ 	.invert = 1,
+ 	.skip_reinit = 0,
+-	.lock_output = STV0229_LOCKOUTPUT_1,
++	.lock_output = STV0299_LOCKOUTPUT_1,
+ 	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+ 	.min_delay_ms = 100,
+ 	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+@@ -869,7 +869,7 @@ static struct stv0299_config philips_sd1878_config = {
+ 	.mclk = 88000000UL,
+ 	.invert = 0,
+ 	.skip_reinit = 0,
+-	.lock_output = STV0229_LOCKOUTPUT_1,
++	.lock_output = STV0299_LOCKOUTPUT_1,
+ 	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+ 	.min_delay_ms = 100,
+ 	.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
+@@ -941,6 +941,12 @@ static void frontend_init(struct budget_av *budget_av)
+ 	switch (saa->pci->subsystem_device) {
+ 
+ 	case SUBID_DVBS_KNC1:
++		/*
++		 * maybe that setting is needed for other dvb-s cards as well,
++		 * but so far it has been only confirmed for this type
++		 */
++		budget_av->reinitialise_demod = 1;
++		/* fall through */
+ 	case SUBID_DVBS_KNC1_PLUS:
+ 	case SUBID_DVBS_EASYWATCH_1:
+ 		if (saa->pci->subsystem_vendor == 0x1894) {
+diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
+index 5093492..6530323 100644
+--- a/drivers/media/dvb/ttpci/budget-ci.c
++++ b/drivers/media/dvb/ttpci/budget-ci.c
+@@ -86,7 +86,7 @@ static int rc5_device = -1;
+ module_param(rc5_device, int, 0644);
+ MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
+ 
+-static int ir_debug = 0;
++static int ir_debug;
+ module_param(ir_debug, int, 0644);
+ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
+ 
+@@ -728,7 +728,7 @@ static struct stv0299_config philips_su1278_tt_config = {
+ 	.mclk = 64000000UL,
+ 	.invert = 0,
+ 	.skip_reinit = 1,
+-	.lock_output = STV0229_LOCKOUTPUT_1,
++	.lock_output = STV0299_LOCKOUTPUT_1,
+ 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+ 	.min_delay_ms = 50,
+ 	.set_symbol_rate = philips_su1278_tt_set_symbol_rate,
+@@ -1121,7 +1121,7 @@ static void frontend_init(struct budget_ci *budget_ci)
+ 
+ 			budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+ 			if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
+-				printk("%s: No LNBP21 found!\n", __FUNCTION__);
++				printk("%s: No LNBP21 found!\n", __func__);
+ 				dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+ 				budget_ci->budget.dvb_frontend = NULL;
+ 			}
+diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
+index 0252081..18cac4b 100644
+--- a/drivers/media/dvb/ttpci/budget-core.c
++++ b/drivers/media/dvb/ttpci/budget-core.c
+@@ -57,6 +57,8 @@ module_param_named(bufsize, dma_buffer_size, int, 0444);
+ MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
+ MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /****************************************************************************
+  * TT budget / WinTV Nova
+  ****************************************************************************/
+@@ -223,7 +225,7 @@ static void vpeirq(unsigned long data)
+ 
+ 	if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
+ 		printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
+-			budget->dev->name, __FUNCTION__, budget->buffer_warnings, count);
++			budget->dev->name, __func__, budget->buffer_warnings, count);
+ 		budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
+ 		budget->buffer_warnings = 0;
+ 	}
+@@ -471,9 +473,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
+ 		budget->buffer_width, budget->buffer_height);
+ 	printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
+ 
+-	if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) {
++	ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
++				   owner, &budget->dev->pci->dev, adapter_nr);
++	if (ret < 0)
+ 		return ret;
+-	}
+ 
+ 	/* set dd1 stream a & b */
+ 	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
+index 14b00f5..2293d80 100644
+--- a/drivers/media/dvb/ttpci/budget.c
++++ b/drivers/media/dvb/ttpci/budget.c
+@@ -45,6 +45,7 @@
+ #include "tda826x.h"
+ #include "lnbp21.h"
+ #include "bsru6.h"
++#include "bsbe1.h"
+ 
+ static int diseqc_method;
+ module_param(diseqc_method, int, 0444);
+@@ -257,11 +258,17 @@ static struct ves1820_config alps_tdbe2_config = {
+ 
+ static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+ {
+-	struct budget* budget = (struct budget*) fe->dvb->priv;
++	struct budget *budget = fe->dvb->priv;
++	u8 *tuner_addr = fe->tuner_priv;
+ 	u32 div;
+ 	u8 cfg, cpump, band_select;
+ 	u8 data[4];
+-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
++	struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) };
++
++	if (tuner_addr)
++		msg.addr = *tuner_addr;
++	else
++		msg.addr = 0x61;
+ 
+ 	div = (36125000 + params->frequency) / 166666;
+ 
+@@ -292,6 +299,12 @@ static struct l64781_config grundig_29504_401_config = {
+ 	.demod_address = 0x55,
+ };
+ 
++static struct l64781_config grundig_29504_401_config_activy = {
++	.demod_address = 0x54,
++};
++
++static u8 tuner_address_grundig_29504_401_activy = 0x60;
++
+ static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+ {
+ 	struct budget* budget = (struct budget*) fe->dvb->priv;
+@@ -346,14 +359,48 @@ static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
+ static struct s5h1420_config s5h1420_config = {
+ 	.demod_address = 0x53,
+ 	.invert = 1,
++	.cdclk_polarity = 1,
+ };
+ 
+ static struct tda10086_config tda10086_config = {
+ 	.demod_address = 0x0e,
+ 	.invert = 0,
+ 	.diseqc_tone = 1,
++	.xtal_freq = TDA10086_XTAL_16M,
+ };
+ 
++static struct stv0299_config alps_bsru6_config_activy = {
++	.demod_address = 0x68,
++	.inittab = alps_bsru6_inittab,
++	.mclk = 88000000UL,
++	.invert = 1,
++	.op0_off = 1,
++	.min_delay_ms = 100,
++	.set_symbol_rate = alps_bsru6_set_symbol_rate,
++};
++
++static struct stv0299_config alps_bsbe1_config_activy = {
++	.demod_address = 0x68,
++	.inittab = alps_bsbe1_inittab,
++	.mclk = 88000000UL,
++	.invert = 1,
++	.op0_off = 1,
++	.min_delay_ms = 100,
++	.set_symbol_rate = alps_bsbe1_set_symbol_rate,
++};
++
++
++static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
++{
++	u8 val;
++	struct i2c_msg msg[] = {
++		{ .addr = adr, .flags = 0, .buf = &reg, .len = 1 },
++		{ .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
++	};
++
++	return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
++}
++
+ static u8 read_pwm(struct budget* budget)
+ {
+ 	u8 b = 0xff;
+@@ -369,6 +416,8 @@ static u8 read_pwm(struct budget* budget)
+ 
+ static void frontend_init(struct budget *budget)
+ {
++	(void)alps_bsbe1_config; /* avoid warning */
++
+ 	switch(budget->dev->pci->subsystem_device) {
+ 	case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
+ 	case 0x1013:
+@@ -414,15 +463,43 @@ static void frontend_init(struct budget *budget)
+ 		}
+ 		break;
+ 
+-	case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
+-		budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
+-		if (budget->dvb_frontend) {
+-			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+-			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+-			budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+-			budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
++	case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */
++	{
++		int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67);
++
++		if (subtype < 0)
++			break;
++		/* fixme: find a better way to identify the card */
++		if (subtype < 0x36) {
++			/* assume ALPS BSRU6 */
++			budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap);
++			if (budget->dvb_frontend) {
++				printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n");
++				budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
++				budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
++				budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
++				budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
++				break;
++			}
++		} else {
++			/* assume ALPS BSBE1 */
++			/* reset tuner */
++			saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO);
++			msleep(50);
++			saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI);
++			msleep(250);
++			budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap);
++			if (budget->dvb_frontend) {
++				printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n");
++				budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
++				budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
++				budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
++				budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
++				break;
++			}
+ 		}
+ 		break;
++	}
+ 
+ 	case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
+ 		budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
+@@ -433,12 +510,20 @@ static void frontend_init(struct budget *budget)
+ 		}
+ 		break;
+ 
++	case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
++		budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
++		if (budget->dvb_frontend) {
++			budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy;
++			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
++		}
++		break;
++
+ 	case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
+ 		budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
+ 		if (budget->dvb_frontend) {
+ 			budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
+ 			if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
+-				printk("%s: No LNBP21 found!\n", __FUNCTION__);
++				printk("%s: No LNBP21 found!\n", __func__);
+ 				goto error_out;
+ 			}
+ 			break;
+@@ -454,9 +539,9 @@ static void frontend_init(struct budget *budget)
+ 		budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
+ 		if (budget->dvb_frontend) {
+ 			if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL)
+-				printk("%s: No tda826x found!\n", __FUNCTION__);
++				printk("%s: No tda826x found!\n", __func__);
+ 			if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
+-				printk("%s: No LNBP21 found!\n", __FUNCTION__);
++				printk("%s: No LNBP21 found!\n", __func__);
+ 				goto error_out;
+ 			}
+ 			break;
+@@ -537,6 +622,7 @@ MAKE_BUDGET_INFO(satel,	"SATELCO Multimedia PCI",	BUDGET_TT_HW_DISEQC);
+ MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
+ MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
+ MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
++MAKE_BUDGET_INFO(fsact,	 "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
+ 
+ static struct pci_device_id pci_tbl[] = {
+ 	MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
+@@ -547,6 +633,7 @@ static struct pci_device_id pci_tbl[] = {
+ 	MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
+ 	MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
+ 	MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
++	MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
+ 	{
+ 		.vendor    = 0,
+ 	}
+diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
+index d764ffa..dd450b7 100644
+--- a/drivers/media/dvb/ttpci/budget.h
++++ b/drivers/media/dvb/ttpci/budget.h
+@@ -1,3 +1,4 @@
++
+ #ifndef __BUDGET_DVB__
+ #define __BUDGET_DVB__
+ 
+@@ -21,7 +22,7 @@ extern int budget_debug;
+ #endif
+ 
+ #define dprintk(level,args...) \
+-	    do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0)
++	    do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __func__); printk(args); } } while (0)
+ 
+ struct budget_info {
+ 	char *name;
+diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
+index 1f31e91..7dd54b3 100644
+--- a/drivers/media/dvb/ttpci/ttpci-eeprom.c
++++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c
+@@ -95,7 +95,7 @@ static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encode
+ 		{ .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 }
+ 	};
+ 
+-	/* dprintk("%s\n", __FUNCTION__); */
++	/* dprintk("%s\n", __func__); */
+ 
+ 	ret = i2c_transfer(adapter, msg, 2);
+ 
+diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+index 7902ae1..732ce4d 100644
+--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
++++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+@@ -56,10 +56,11 @@
+ */
+ 
+ static int debug;
+-
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0)
+ 
+ #define ISO_BUF_COUNT      4
+@@ -153,12 +154,12 @@ static int ttusb_cmd(struct ttusb *ttusb,
+ 			   (u8 *) data, len, &actual_len, 1000);
+ 	if (err != 0) {
+ 		dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
+-			__FUNCTION__, err);
++			__func__, err);
+ 		mutex_unlock(&ttusb->semusb);
+ 		return err;
+ 	}
+ 	if (actual_len != len) {
+-		dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__,
++		dprintk("%s: only wrote %d of %d bytes\n", __func__,
+ 			actual_len, len);
+ 		mutex_unlock(&ttusb->semusb);
+ 		return -1;
+@@ -168,7 +169,7 @@ static int ttusb_cmd(struct ttusb *ttusb,
+ 			   ttusb->last_result, 32, &actual_len, 1000);
+ 
+ 	if (err != 0) {
+-		printk("%s: failed, receive error %d\n", __FUNCTION__,
++		printk("%s: failed, receive error %d\n", __func__,
+ 		       err);
+ 		mutex_unlock(&ttusb->semusb);
+ 		return err;
+@@ -229,7 +230,7 @@ static int ttusb_i2c_msg(struct ttusb *ttusb,
+ 		if (err || b[0] != 0x55 || b[1] != id) {
+ 			dprintk
+ 			    ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ",
+-			     __FUNCTION__, err, id);
++			     __func__, err, id);
+ 			return -EREMOTEIO;
+ 		}
+ 
+@@ -273,7 +274,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num
+ 				    snd_buf, snd_len, rcv_buf, rcv_len);
+ 
+ 		if (err < rcv_len) {
+-			dprintk("%s: i == %i\n", __FUNCTION__, i);
++			dprintk("%s: i == %i\n", __func__, i);
+ 			break;
+ 		}
+ 
+@@ -327,7 +328,7 @@ static int ttusb_boot_dsp(struct ttusb *ttusb)
+       done:
+ 	if (err) {
+ 		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+-			__FUNCTION__, err);
++			__func__, err);
+ 	}
+ 
+ 	return err;
+@@ -427,7 +428,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
+ 	if ((err = ttusb_result(ttusb, get_version, sizeof(get_version))))
+ 		return err;
+ 
+-	dprintk("%s: stc-version: %c%c%c%c%c\n", __FUNCTION__,
++	dprintk("%s: stc-version: %c%c%c%c%c\n", __func__,
+ 		get_version[4], get_version[5], get_version[6],
+ 		get_version[7], get_version[8]);
+ 
+@@ -437,7 +438,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
+ 	    memcmp(get_version + 4, "V 2.2", 5)) {
+ 		printk
+ 		    ("%s: unknown STC version %c%c%c%c%c, please report!\n",
+-		     __FUNCTION__, get_version[4], get_version[5],
++		     __func__, get_version[4], get_version[5],
+ 		     get_version[6], get_version[7], get_version[8]);
+ 	}
+ 
+@@ -453,7 +454,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
+ 	    ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version));
+ 	if (err)
+ 		return err;
+-	printk("%s: dsp-version: %c%c%c\n", __FUNCTION__,
++	printk("%s: dsp-version: %c%c%c\n", __func__,
+ 	       get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]);
+ 	return 0;
+ }
+@@ -476,7 +477,7 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe,
+ 	/* Diseqc */
+ 	if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) {
+ 		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+-			__FUNCTION__, err);
++			__func__, err);
+ 	}
+ 
+ 	return err;
+@@ -494,7 +495,7 @@ static int ttusb_update_lnb(struct ttusb *ttusb)
+ 	/* SetLNB */
+ 	if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) {
+ 		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+-			__FUNCTION__, err);
++			__func__, err);
+ 	}
+ 
+ 	return err;
+@@ -528,7 +529,7 @@ static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq)
+ 	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
+ 	if (err) {
+ 		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+-			__FUNCTION__, err);
++			__func__, err);
+ 	}
+ }
+ #endif
+@@ -542,7 +543,7 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel,
+ 				  const u8 * data, int len);
+ #endif
+ 
+-static int numpkt = 0, numts, numstuff, numsec, numinvalid;
++static int numpkt, numts, numstuff, numsec, numinvalid;
+ static unsigned long lastj;
+ 
+ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
+@@ -554,7 +555,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
+ 		csum ^= le16_to_cpup((u16 *) (muxpack + i));
+ 	if (csum) {
+ 		printk("%s: muxpack with incorrect checksum, ignoring\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		numinvalid++;
+ 		return;
+ 	}
+@@ -563,7 +564,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
+ 	cc &= 0x7FFF;
+ 	if ((cc != ttusb->cc) && (ttusb->cc != -1))
+ 		printk("%s: cc discontinuity (%d frames missing)\n",
+-		       __FUNCTION__, (cc - ttusb->cc) & 0x7FFF);
++		       __func__, (cc - ttusb->cc) & 0x7FFF);
+ 	ttusb->cc = (cc + 1) & 0x7FFF;
+ 	if (muxpack[0] & 0x80) {
+ #ifdef TTUSB_HWSECTIONS
+@@ -613,7 +614,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
+ 	int maxwork = 1024;
+ 	while (len) {
+ 		if (!(maxwork--)) {
+-			printk("%s: too much work\n", __FUNCTION__);
++			printk("%s: too much work\n", __func__);
+ 			break;
+ 		}
+ 
+@@ -632,7 +633,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
+ #else
+ 				if (ttusb->insync) {
+ 					printk("%s: lost sync.\n",
+-					       __FUNCTION__);
++					       __func__);
+ 					ttusb->insync = 0;
+ 				}
+ #endif
+@@ -691,7 +692,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
+ 					else {
+ 						dprintk
+ 						    ("%s: invalid state: first byte is %x\n",
+-						     __FUNCTION__,
++						     __func__,
+ 						     ttusb->muxpack[0]);
+ 						ttusb->mux_state = 0;
+ 					}
+@@ -740,7 +741,7 @@ static void ttusb_iso_irq(struct urb *urb)
+ 
+ #if 0
+ 	printk("%s: status %d, errcount == %d, length == %i\n",
+-	       __FUNCTION__,
++	       __func__,
+ 	       urb->status, urb->error_count, urb->actual_length);
+ #endif
+ 
+@@ -833,7 +834,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
+ 	int i, j, err, buffer_offset = 0;
+ 
+ 	if (ttusb->iso_streaming) {
+-		printk("%s: iso xfer already running!\n", __FUNCTION__);
++		printk("%s: iso xfer already running!\n", __func__);
+ 		return 0;
+ 	}
+ 
+@@ -869,7 +870,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
+ 			ttusb_stop_iso_xfer(ttusb);
+ 			printk
+ 			    ("%s: failed urb submission (%i: err = %i)!\n",
+-			     __FUNCTION__, i, err);
++			     __func__, i, err);
+ 			return err;
+ 		}
+ 	}
+@@ -1005,7 +1006,7 @@ static int stc_release(struct inode *inode, struct file *file)
+ 	return 0;
+ }
+ 
+-static struct file_operations stc_fops = {
++static const struct file_operations stc_fops = {
+ 	.owner = THIS_MODULE,
+ 	.read = stc_read,
+ 	.open = stc_open,
+@@ -1313,7 +1314,7 @@ static struct stv0299_config alps_stv0299_config = {
+ 	.mclk = 88000000UL,
+ 	.invert = 1,
+ 	.skip_reinit = 0,
+-	.lock_output = STV0229_LOCKOUTPUT_1,
++	.lock_output = STV0299_LOCKOUTPUT_1,
+ 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+ 	.min_delay_ms = 100,
+ 	.set_symbol_rate = alps_stv0299_set_symbol_rate,
+@@ -1643,7 +1644,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
+ 	struct ttusb *ttusb;
+ 	int result;
+ 
+-	dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
++	dprintk("%s: TTUSB DVB connected\n", __func__);
+ 
+ 	udev = interface_to_usbdev(intf);
+ 
+@@ -1669,7 +1670,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
+ 
+ 	mutex_unlock(&ttusb->semi2c);
+ 
+-	if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) {
++	result = dvb_register_adapter(&ttusb->adapter,
++				      "Technotrend/Hauppauge Nova-USB",
++				      THIS_MODULE, &udev->dev, adapter_nr);
++	if (result < 0) {
+ 		ttusb_free_iso_urbs(ttusb);
+ 		kfree(ttusb);
+ 		return result;
+@@ -1773,7 +1777,7 @@ static void ttusb_disconnect(struct usb_interface *intf)
+ 
+ 	kfree(ttusb);
+ 
+-	dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__);
++	dprintk("%s: TTUSB DVB disconnected\n", __func__);
+ }
+ 
+ static struct usb_device_id ttusb_table[] = {
+diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+index 1ec981d..42eee04 100644
+--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
++++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+@@ -52,6 +52,8 @@ MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
+ module_param(enable_rc, int, 0644);
+ MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk	if (debug) printk
+ 
+ #define DRIVER_NAME		"TechnoTrend/Hauppauge DEC USB"
+@@ -217,11 +219,11 @@ static void ttusb_dec_handle_irq( struct urb *urb)
+ 		case -ETIME:
+ 			/* this urb is dead, cleanup */
+ 			dprintk("%s:urb shutting down with status: %d\n",
+-					__FUNCTION__, urb->status);
++					__func__, urb->status);
+ 			return;
+ 		default:
+ 			dprintk("%s:nonzero status received: %d\n",
+-					__FUNCTION__,urb->status);
++					__func__,urb->status);
+ 			goto exit;
+ 	}
+ 
+@@ -235,7 +237,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
+ 		 * keyrepeat signal is recieved for lets say 200ms.
+ 		 * this should/could be added later ...
+ 		 * for now lets report each signal as a key down and up*/
+-		dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
++		dprintk("%s:rc signal:%d\n", __func__, buffer[4]);
+ 		input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
+ 		input_sync(dec->rc_input_dev);
+ 		input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
+@@ -245,7 +247,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
+ exit:	retval = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if(retval)
+ 		printk("%s - usb_commit_urb failed with result: %d\n",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ }
+ 
+ static u16 crc16(u16 crc, const u8 *buf, size_t len)
+@@ -268,7 +270,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+ 	int result, actual_len, i;
+ 	u8 *b;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
+ 	if (!b)
+@@ -276,7 +278,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+ 
+ 	if ((result = mutex_lock_interruptible(&dec->usb_mutex))) {
+ 		kfree(b);
+-		printk("%s: Failed to lock usb mutex.\n", __FUNCTION__);
++		printk("%s: Failed to lock usb mutex.\n", __func__);
+ 		return result;
+ 	}
+ 
+@@ -289,7 +291,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+ 		memcpy(&b[4], params, param_length);
+ 
+ 	if (debug) {
+-		printk("%s: command: ", __FUNCTION__);
++		printk("%s: command: ", __func__);
+ 		for (i = 0; i < param_length + 4; i++)
+ 			printk("0x%02X ", b[i]);
+ 		printk("\n");
+@@ -300,7 +302,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+ 
+ 	if (result) {
+ 		printk("%s: command bulk message failed: error %d\n",
+-		       __FUNCTION__, result);
++		       __func__, result);
+ 		mutex_unlock(&dec->usb_mutex);
+ 		kfree(b);
+ 		return result;
+@@ -311,13 +313,13 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+ 
+ 	if (result) {
+ 		printk("%s: result bulk message failed: error %d\n",
+-		       __FUNCTION__, result);
++		       __func__, result);
+ 		mutex_unlock(&dec->usb_mutex);
+ 		kfree(b);
+ 		return result;
+ 	} else {
+ 		if (debug) {
+-			printk("%s: result: ", __FUNCTION__);
++			printk("%s: result: ", __func__);
+ 			for (i = 0; i < actual_len; i++)
+ 				printk("0x%02X ", b[i]);
+ 			printk("\n");
+@@ -343,7 +345,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
+ 	int result;
+ 	unsigned int tmp;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
+ 	if (result)
+@@ -400,7 +402,7 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
+ 	u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
+ 	u16 video = htons(dec->pid[DMX_PES_VIDEO]);
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	memcpy(&b[0], &pcr, 2);
+ 	memcpy(&b[2], &audio, 2);
+@@ -419,12 +421,12 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
+ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
+ {
+ 	if (length < 8) {
+-		printk("%s: packet too short - discarding\n", __FUNCTION__);
++		printk("%s: packet too short - discarding\n", __func__);
+ 		return;
+ 	}
+ 
+ 	if (length > 8 + MAX_PVA_LENGTH) {
+-		printk("%s: packet too long - discarding\n", __FUNCTION__);
++		printk("%s: packet too long - discarding\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -507,7 +509,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
+ 		break;
+ 
+ 	default:
+-		printk("%s: unknown PVA type: %02x.\n", __FUNCTION__,
++		printk("%s: unknown PVA type: %02x.\n", __func__,
+ 		       pva[2]);
+ 		break;
+ 	}
+@@ -546,7 +548,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
+ 	u16 packet_id;
+ 
+ 	if (dec->packet_length % 2) {
+-		printk("%s: odd sized packet - discarding\n", __FUNCTION__);
++		printk("%s: odd sized packet - discarding\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -554,7 +556,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
+ 		csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
+ 
+ 	if (csum) {
+-		printk("%s: checksum failed - discarding\n", __FUNCTION__);
++		printk("%s: checksum failed - discarding\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -563,7 +565,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
+ 
+ 	if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
+ 		printk("%s: warning: lost packets between %u and %u\n",
+-		       __FUNCTION__, dec->next_packet_id - 1, packet_id);
++		       __func__, dec->next_packet_id - 1, packet_id);
+ 	}
+ 
+ 	if (packet_id == 0xffff)
+@@ -652,7 +654,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
+ 					dec->packet_state = 7;
+ 				} else {
+ 					printk("%s: unknown packet type: "
+-					       "%02x%02x\n", __FUNCTION__,
++					       "%02x%02x\n", __func__,
+ 					       dec->packet[0], dec->packet[1]);
+ 					dec->packet_state = 0;
+ 				}
+@@ -724,7 +726,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
+ 
+ 		default:
+ 			printk("%s: illegal packet state encountered.\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			dec->packet_state = 0;
+ 		}
+ 	}
+@@ -792,7 +794,7 @@ static void ttusb_dec_process_urb(struct urb *urb)
+ 	} else {
+ 		 /* -ENOENT is expected when unlinking urbs */
+ 		if (urb->status != -ENOENT)
+-			dprintk("%s: urb error: %d\n", __FUNCTION__,
++			dprintk("%s: urb error: %d\n", __func__,
+ 				urb->status);
+ 	}
+ 
+@@ -804,7 +806,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
+ {
+ 	int i, j, buffer_offset = 0;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	for (i = 0; i < ISO_BUF_COUNT; i++) {
+ 		int frame_offset = 0;
+@@ -834,7 +836,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
+ {
+ 	int i;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (mutex_lock_interruptible(&dec->iso_mutex))
+ 		return;
+@@ -889,7 +891,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
+ {
+ 	int i, result;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (mutex_lock_interruptible(&dec->iso_mutex))
+ 		return -EAGAIN;
+@@ -905,7 +907,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
+ 			if ((result = usb_submit_urb(dec->iso_urb[i],
+ 						     GFP_ATOMIC))) {
+ 				printk("%s: failed urb submission %d: "
+-				       "error %d\n", __FUNCTION__, i, result);
++				       "error %d\n", __func__, i, result);
+ 
+ 				while (i) {
+ 					usb_kill_urb(dec->iso_urb[i - 1]);
+@@ -932,7 +934,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
+ 	u8 b0[] = { 0x05 };
+ 	int result = 0;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	dprintk("  ts_type:");
+ 
+@@ -1012,7 +1014,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
+ 	unsigned long flags;
+ 	u8 x = 1;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	pid = htons(dvbdmxfeed->pid);
+ 	memcpy(&b0[0], &pid, 2);
+@@ -1052,7 +1054,7 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+ {
+ 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (!dvbdmx->dmx.frontend)
+ 		return -EINVAL;
+@@ -1113,7 +1115,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
+ 
+ static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+ {
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	switch (dvbdmxfeed->type) {
+ 	case DMX_TYPE_TS:
+@@ -1132,7 +1134,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
+ {
+ 	int i;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	for (i = 0; i < ISO_BUF_COUNT; i++)
+ 		usb_free_urb(dec->iso_urb[i]);
+@@ -1147,7 +1149,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
+ {
+ 	int i;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	dec->iso_buffer = pci_alloc_consistent(NULL,
+ 					       ISO_FRAME_SIZE *
+@@ -1214,7 +1216,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
+ 
+ 	dec->rc_input_dev = input_dev;
+ 	if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
+-		printk("%s: usb_submit_urb failed\n",__FUNCTION__);
++		printk("%s: usb_submit_urb failed\n",__func__);
+ 	/* enable irq pipe */
+ 	ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
+ 
+@@ -1223,7 +1225,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
+ 
+ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
+ {
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	dec->v_pes[0] = 0x00;
+ 	dec->v_pes[1] = 0x00;
+@@ -1233,7 +1235,7 @@ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
+ 
+ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
+ {
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	mutex_init(&dec->usb_mutex);
+ 	mutex_init(&dec->iso_mutex);
+@@ -1281,11 +1283,11 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
+ 	u32 crc32_csum, crc32_check, tmp;
+ 	const struct firmware *fw_entry = NULL;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
+ 		printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
+-		       __FUNCTION__, dec->firmware_name);
++		       __func__, dec->firmware_name);
+ 		return 1;
+ 	}
+ 
+@@ -1294,7 +1296,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
+ 
+ 	if (firmware_size < 60) {
+ 		printk("%s: firmware size too small for DSP code (%zu < 60).\n",
+-			__FUNCTION__, firmware_size);
++			__func__, firmware_size);
+ 		release_firmware(fw_entry);
+ 		return -1;
+ 	}
+@@ -1308,7 +1310,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
+ 	if (crc32_csum != crc32_check) {
+ 		printk("%s: crc32 check of DSP code failed (calculated "
+ 		       "0x%08x != 0x%08x in file), file invalid.\n",
+-			__FUNCTION__, crc32_csum, crc32_check);
++			__func__, crc32_csum, crc32_check);
+ 		release_firmware(fw_entry);
+ 		return -1;
+ 	}
+@@ -1376,7 +1378,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
+ 	int result;
+ 	unsigned int mode, model, version;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
+ 
+@@ -1415,7 +1417,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
+ 			default:
+ 				printk(KERN_ERR "%s: unknown model returned "
+ 				       "by firmware (%08x) - please report\n",
+-				       __FUNCTION__, model);
++				       __func__, model);
+ 				return -1;
+ 				break;
+ 			}
+@@ -1434,12 +1436,14 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+ {
+ 	int result;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if ((result = dvb_register_adapter(&dec->adapter,
+-					   dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
++					   dec->model_name, THIS_MODULE,
++					   &dec->udev->dev,
++					   adapter_nr)) < 0) {
+ 		printk("%s: dvb_register_adapter failed: error %d\n",
+-		       __FUNCTION__, result);
++		       __func__, result);
+ 
+ 		return result;
+ 	}
+@@ -1454,7 +1458,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+ 	dec->demux.write_to_decoder = NULL;
+ 
+ 	if ((result = dvb_dmx_init(&dec->demux)) < 0) {
+-		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
++		printk("%s: dvb_dmx_init failed: error %d\n", __func__,
+ 		       result);
+ 
+ 		dvb_unregister_adapter(&dec->adapter);
+@@ -1468,7 +1472,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+ 
+ 	if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
+ 		printk("%s: dvb_dmxdev_init failed: error %d\n",
+-		       __FUNCTION__, result);
++		       __func__, result);
+ 
+ 		dvb_dmx_release(&dec->demux);
+ 		dvb_unregister_adapter(&dec->adapter);
+@@ -1480,7 +1484,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+ 
+ 	if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,
+ 						  &dec->frontend)) < 0) {
+-		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
++		printk("%s: dvb_dmx_init failed: error %d\n", __func__,
+ 		       result);
+ 
+ 		dvb_dmxdev_release(&dec->dmxdev);
+@@ -1492,7 +1496,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+ 
+ 	if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,
+ 						      &dec->frontend)) < 0) {
+-		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
++		printk("%s: dvb_dmx_init failed: error %d\n", __func__,
+ 		       result);
+ 
+ 		dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
+@@ -1510,7 +1514,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+ 
+ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
+ {
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	dvb_net_release(&dec->dvb_net);
+ 	dec->demux.dmx.close(&dec->demux.dmx);
+@@ -1528,7 +1532,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
+ static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
+ {
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 	/* we have to check whether the irq URB is already submitted.
+ 	  * As the irq is submitted after the interface is changed,
+ 	  * this is the best method i figured out.
+@@ -1552,7 +1556,7 @@ static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
+ {
+ 	int i;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	dec->iso_stream_count = 0;
+ 
+@@ -1612,12 +1616,12 @@ static int ttusb_dec_probe(struct usb_interface *intf,
+ 	struct usb_device *udev;
+ 	struct ttusb_dec *dec;
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	udev = interface_to_usbdev(intf);
+ 
+ 	if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
+-		printk("%s: couldn't allocate memory.\n", __FUNCTION__);
++		printk("%s: couldn't allocate memory.\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -1692,7 +1696,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
+ 
+ 	usb_set_intfdata(intf, NULL);
+ 
+-	dprintk("%s\n", __FUNCTION__);
++	dprintk("%s\n", __func__);
+ 
+ 	if (dec->active) {
+ 		ttusb_dec_exit_tasklet(dec);
+@@ -1749,7 +1753,7 @@ static int __init ttusb_dec_init(void)
+ 	int result;
+ 
+ 	if ((result = usb_register(&ttusb_dec_driver)) < 0) {
+-		printk("%s: initialisation failed: error %d.\n", __FUNCTION__,
++		printk("%s: initialisation failed: error %d.\n", __func__,
+ 		       result);
+ 		return result;
+ 	}
+diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+index a6fb1d6..eb5eaec 100644
+--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
++++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+@@ -53,7 +53,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 		return ret;
+ 
+ 	if(len != 4) {
+-		printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
++		printk(KERN_ERR "%s: unexpected reply\n", __func__);
+ 		return -EIO;
+ 	}
+ 
+@@ -70,7 +70,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ 			break;
+ 		default:
+ 			pr_info("%s: returned unknown value: %d\n",
+-				__FUNCTION__, result[3]);
++				__func__, result[3]);
+ 			return -EIO;
+ 	}
+ 
+diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
+index 36c0e36..4e3f83e 100644
+--- a/drivers/media/radio/dsbr100.c
++++ b/drivers/media/radio/dsbr100.c
+@@ -438,7 +438,9 @@ static const struct file_operations usb_dsbr100_fops = {
+ 	.open		= usb_dsbr100_open,
+ 	.release	= usb_dsbr100_close,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek		= no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
+index 3ae56fe..09fe6f1 100644
+--- a/drivers/media/radio/miropcm20-radio.c
++++ b/drivers/media/radio/miropcm20-radio.c
+@@ -221,7 +221,9 @@ static const struct file_operations pcm20_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= pcm20_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
+index aed1147..06dfed9 100644
+--- a/drivers/media/radio/miropcm20-rds.c
++++ b/drivers/media/radio/miropcm20-rds.c
+@@ -19,7 +19,7 @@
+ #include "miropcm20-rds-core.h"
+ 
+ static char * text_buffer;
+-static int rds_users = 0;
++static int rds_users;
+ 
+ 
+ static int rds_f_open(struct inode *in, struct file *fi)
+diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
+index f0a67e9..1ec18ed 100644
+--- a/drivers/media/radio/radio-aimslab.c
++++ b/drivers/media/radio/radio-aimslab.c
+@@ -36,7 +36,6 @@
+ #include <asm/uaccess.h>	/* copy to/from user		*/
+ #include <linux/videodev2.h>	/* kernel radio structs		*/
+ #include <media/v4l2-common.h>
+-#include <asm/semaphore.h>	/* Lock for the I/O 		*/
+ 
+ #include <linux/version.h>	/* for KERNEL_VERSION MACRO	*/
+ #define RADIO_VERSION KERNEL_VERSION(0,0,2)
+@@ -383,7 +382,9 @@ static const struct file_operations rtrack_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
+index 9b1f7a9..46cdb54 100644
+--- a/drivers/media/radio/radio-aztech.c
++++ b/drivers/media/radio/radio-aztech.c
+@@ -346,7 +346,9 @@ static const struct file_operations aztech_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
+index 57b9e3a..b14db53 100644
+--- a/drivers/media/radio/radio-cadet.c
++++ b/drivers/media/radio/radio-cadet.c
+@@ -69,13 +69,13 @@ static struct v4l2_queryctrl radio_qctrl[] = {
+ 
+ static int io=-1;		/* default to isapnp activation */
+ static int radio_nr = -1;
+-static int users=0;
+-static int curtuner=0;
+-static int tunestat=0;
+-static int sigstrength=0;
++static int users;
++static int curtuner;
++static int tunestat;
++static int sigstrength;
+ static wait_queue_head_t read_queue;
+ static struct timer_list readtimer;
+-static __u8 rdsin=0,rdsout=0,rdsstat=0;
++static __u8 rdsin, rdsout, rdsstat;
+ static unsigned char rdsbuf[RDS_BUFFER];
+ static spinlock_t cadet_io_lock;
+ 
+@@ -563,7 +563,9 @@ static const struct file_operations cadet_fops = {
+ 	.read		= cadet_read,
+ 	.ioctl		= video_ioctl2,
+ 	.poll		= cadet_poll,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
+index 99a3231..de49be9 100644
+--- a/drivers/media/radio/radio-gemtek-pci.c
++++ b/drivers/media/radio/radio-gemtek-pci.c
+@@ -368,7 +368,9 @@ static const struct file_operations gemtek_pci_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
+index 246422b..81f6aeb 100644
+--- a/drivers/media/radio/radio-gemtek.c
++++ b/drivers/media/radio/radio-gemtek.c
+@@ -397,7 +397,9 @@ static const struct file_operations gemtek_fops = {
+ 	.open		= video_exclusive_open,
+ 	.release	= video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek		= no_llseek
+ };
+ 
+diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
+index bc51f4d..bddd3c4 100644
+--- a/drivers/media/radio/radio-maestro.c
++++ b/drivers/media/radio/radio-maestro.c
+@@ -100,7 +100,9 @@ static const struct file_operations maestro_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
+index 8e184cf..0133ecf 100644
+--- a/drivers/media/radio/radio-maxiradio.c
++++ b/drivers/media/radio/radio-maxiradio.c
+@@ -103,7 +103,9 @@ static const struct file_operations maxiradio_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl          = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
+index 82aedfc..0708021 100644
+--- a/drivers/media/radio/radio-rtrack2.c
++++ b/drivers/media/radio/radio-rtrack2.c
+@@ -288,7 +288,9 @@ static const struct file_operations rtrack2_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
+index 53e1148..66e052f 100644
+--- a/drivers/media/radio/radio-sf16fmi.c
++++ b/drivers/media/radio/radio-sf16fmi.c
+@@ -288,7 +288,9 @@ static const struct file_operations fmi_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
+index ebc5fbb..b0ccf7c 100644
+--- a/drivers/media/radio/radio-sf16fmr2.c
++++ b/drivers/media/radio/radio-sf16fmr2.c
+@@ -29,6 +29,8 @@ static struct mutex lock;
+ #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+ #define RADIO_VERSION KERNEL_VERSION(0,0,2)
+ 
++#define AUD_VOL_INDEX 1
++
+ static struct v4l2_queryctrl radio_qctrl[] = {
+ 	{
+ 		.id            = V4L2_CID_AUDIO_MUTE,
+@@ -37,13 +39,14 @@ static struct v4l2_queryctrl radio_qctrl[] = {
+ 		.maximum       = 1,
+ 		.default_value = 1,
+ 		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+-	},{
++	},
++	[AUD_VOL_INDEX] = {
+ 		.id            = V4L2_CID_AUDIO_VOLUME,
+ 		.name          = "Volume",
+ 		.minimum       = 0,
+-		.maximum       = 65535,
+-		.step          = 1<<12,
+-		.default_value = 0xff,
++		.maximum       = 15,
++		.step          = 1,
++		.default_value = 0,
+ 		.type          = V4L2_CTRL_TYPE_INTEGER,
+ 	}
+ };
+@@ -61,7 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
+ struct fmr2_device
+ {
+ 	int port;
+-	int curvol; /* 0-65535, if not volume 0 or 65535 */
++	int curvol; /* 0-15 */
+ 	int mute;
+ 	int stereo; /* card is producing stereo audio */
+ 	unsigned long curfreq; /* freq in kHz */
+@@ -176,51 +179,35 @@ static int fmr2_setfreq(struct fmr2_device *dev)
+ /* !!! not tested, in my card this does't work !!! */
+ static int fmr2_setvolume(struct fmr2_device *dev)
+ {
+-	int i,a,n, port = dev->port;
++	int vol[16] = { 0x021, 0x084, 0x090, 0x104,
++			0x110, 0x204, 0x210, 0x402,
++			0x404, 0x408, 0x410, 0x801,
++			0x802, 0x804, 0x808, 0x810 };
++	int i, a, port = dev->port;
++	int n = vol[dev->curvol & 0x0f];
+ 
+-	if (dev->card_type != 11) return 1;
++	if (dev->card_type != 11)
++		return 1;
+ 
+-	switch( (dev->curvol+(1<<11)) >> 12 )
+-	{
+-	case 0: case 1: n = 0x21; break;
+-	case 2: n = 0x84; break;
+-	case 3: n = 0x90; break;
+-	case 4: n = 0x104; break;
+-	case 5: n = 0x110; break;
+-	case 6: n = 0x204; break;
+-	case 7: n = 0x210; break;
+-	case 8: n = 0x402; break;
+-	case 9: n = 0x404; break;
+-	default:
+-	case 10: n = 0x408; break;
+-	case 11: n = 0x410; break;
+-	case 12: n = 0x801; break;
+-	case 13: n = 0x802; break;
+-	case 14: n = 0x804; break;
+-	case 15: n = 0x808; break;
+-	case 16: n = 0x810; break;
+-	}
+-	for(i=12;--i>=0;)
+-	{
++	for (i = 12; --i >= 0; ) {
+ 		a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */
+-		outb(a|4, port);
+-		wait(4,port);
+-		outb(a|0x24, port);
+-		wait(4,port);
+-		outb(a|4, port);
+-		wait(4,port);
++		outb(a | 4, port);
++		wait(4, port);
++		outb(a | 0x24, port);
++		wait(4, port);
++		outb(a | 4, port);
++		wait(4, port);
+ 	}
+-	for(i=6;--i>=0;)
+-	{
++	for (i = 6; --i >= 0; ) {
+ 		a = ((0x18 >> i) & 1) << 6;
+-		outb(a|4, port);
++		outb(a | 4, port);
+ 		wait(4,port);
+-		outb(a|0x24, port);
++		outb(a | 0x24, port);
+ 		wait(4,port);
+ 		outb(a|4, port);
+ 		wait(4,port);
+ 	}
+-	wait(4,port);
++	wait(4, port);
+ 	outb(0x14, port);
+ 
+ 	return 0;
+@@ -312,16 +299,10 @@ static int vidioc_queryctrl(struct file *file, void *priv,
+ 					struct v4l2_queryctrl *qc)
+ {
+ 	int i;
+-	struct video_device *dev = video_devdata(file);
+-	struct fmr2_device *fmr2 = dev->priv;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+-		if ((fmr2->card_type != 11)
+-				&& V4L2_CID_AUDIO_VOLUME)
+-			radio_qctrl[i].step = 65535;
+ 		if (qc->id && qc->id == radio_qctrl[i].id) {
+-			memcpy(qc, &(radio_qctrl[i]),
+-						sizeof(*qc));
++			memcpy(qc, &radio_qctrl[i], sizeof(*qc));
+ 			return 0;
+ 		}
+ 	}
+@@ -354,24 +335,13 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_AUDIO_MUTE:
+ 		fmr2->mute = ctrl->value;
+-		if (fmr2->card_type != 11) {
+-			if (!fmr2->mute)
+-				fmr2->curvol = 65535;
+-			else
+-				fmr2->curvol = 0;
+-		}
+ 		break;
+ 	case V4L2_CID_AUDIO_VOLUME:
+-		fmr2->curvol = ctrl->value;
+-		if (fmr2->card_type != 11) {
+-			if (fmr2->curvol) {
+-				fmr2->curvol = 65535;
+-				fmr2->mute = 0;
+-			} else {
+-				fmr2->curvol = 0;
+-				fmr2->mute = 1;
+-			}
+-		}
++		if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum)
++			fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum;
++		else
++			fmr2->curvol = ctrl->value;
++
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -387,6 +357,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
+ 	mutex_lock(&lock);
+ 	if (fmr2->curvol && !fmr2->mute) {
+ 		fmr2_setvolume(fmr2);
++		/* Set frequency and unmute card */
+ 		fmr2_setfreq(fmr2);
+ 	} else
+ 		fmr2_mute(fmr2->port);
+@@ -433,7 +404,9 @@ static const struct file_operations fmr2_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl          = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+@@ -487,6 +460,11 @@ static int __init fmr2_init(void)
+ 	fmr2_product_info(&fmr2_unit);
+ 	mutex_unlock(&lock);
+ 	debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type));
++
++	/* Only card_type == 11 implements volume */
++	if (fmr2_unit.card_type != 11)
++		radio_qctrl[AUD_VOL_INDEX].maximum = 1;
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
+index 649f14d..77354ca 100644
+--- a/drivers/media/radio/radio-si470x.c
++++ b/drivers/media/radio/radio-si470x.c
+@@ -85,6 +85,7 @@
+  *		Oliver Neukum <oliver at neukum.org>
+  *		Version 1.0.7
+  *		- usb autosuspend support
++ *             - unplugging fixed
+  *
+  * ToDo:
+  * - add seeking support
+@@ -97,10 +98,10 @@
+ /* driver definitions */
+ #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz at gmx.net>"
+ #define DRIVER_NAME "radio-si470x"
+-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6)
++#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7)
+ #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
+ #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
+-#define DRIVER_VERSION "1.0.6"
++#define DRIVER_VERSION "1.0.7"
+ 
+ 
+ /* kernel includes */
+@@ -424,6 +425,7 @@ struct si470x_device {
+ 
+ 	/* driver management */
+ 	unsigned int users;
++       unsigned char disconnected;
+ 
+ 	/* Silabs internal registers (0..15) */
+ 	unsigned short registers[RADIO_REGISTER_NUM];
+@@ -440,6 +442,12 @@ struct si470x_device {
+ 
+ 
+ /*
++ * Lock to prevent kfree of data before all users have releases the device.
++ */
++static DEFINE_MUTEX(open_close_lock);
++
++
++/*
+  * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
+  * 62.5 kHz otherwise.
+  * The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
+@@ -577,7 +585,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
+ 		usb_rcvintpipe(radio->usbdev, 1),
+ 		(void *) &buf, sizeof(buf), &size, usb_timeout);
+ 	if (size != sizeof(buf))
+-		printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: "
++	       printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
+ 			"return size differs: %d != %zu\n", size, sizeof(buf));
+ 	if (retval < 0)
+ 		printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
+@@ -875,6 +883,8 @@ static void si470x_work(struct work_struct *work)
+ 	struct si470x_device *radio = container_of(work, struct si470x_device,
+ 		work.work);
+ 
++       if (radio->disconnected)
++	       return;
+ 	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
+ 		return;
+ 
+@@ -1001,13 +1011,21 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
+ static int si470x_fops_release(struct inode *inode, struct file *file)
+ {
+ 	struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+-	int retval;
++       int retval = 0;
+ 
+ 	if (!radio)
+ 		return -ENODEV;
+ 
++       mutex_lock(&open_close_lock);
+ 	radio->users--;
+ 	if (radio->users == 0) {
++	       if (radio->disconnected) {
++		       video_unregister_device(radio->videodev);
++		       kfree(radio->buffer);
++		       kfree(radio);
++		       goto done;
++	       }
++
+ 		/* stop rds reception */
+ 		cancel_delayed_work_sync(&radio->work);
+ 
+@@ -1016,10 +1034,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
+ 
+ 		retval = si470x_stop(radio);
+ 		usb_autopm_put_interface(radio->intf);
+-		return retval;
+ 	}
+ 
+-	return 0;
++done:
++       mutex_unlock(&open_close_lock);
++       return retval;
+ }
+ 
+ 
+@@ -1032,7 +1051,9 @@ static const struct file_operations si470x_fops = {
+ 	.read		= si470x_fops_read,
+ 	.poll		= si470x_fops_poll,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.open		= si470x_fops_open,
+ 	.release	= si470x_fops_release,
+ };
+@@ -1157,6 +1178,9 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
+ {
+ 	struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ 
++       if (radio->disconnected)
++	       return -EIO;
++
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_AUDIO_VOLUME:
+ 		ctrl->value = radio->registers[SYSCONFIG2] &
+@@ -1181,6 +1205,9 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
+ 	struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ 	int retval;
+ 
++       if (radio->disconnected)
++	       return -EIO;
++
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_AUDIO_VOLUME:
+ 		radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
+@@ -1243,6 +1270,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
+ 	struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ 	int retval;
+ 
++       if (radio->disconnected)
++	       return -EIO;
+ 	if (tuner->index > 0)
+ 		return -EINVAL;
+ 
+@@ -1299,6 +1328,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
+ 	struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ 	int retval;
+ 
++       if (radio->disconnected)
++	       return -EIO;
+ 	if (tuner->index > 0)
+ 		return -EINVAL;
+ 
+@@ -1324,6 +1355,9 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
+ {
+ 	struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ 
++       if (radio->disconnected)
++	       return -EIO;
++
+ 	freq->type = V4L2_TUNER_RADIO;
+ 	freq->frequency = si470x_get_freq(radio);
+ 
+@@ -1340,6 +1374,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
+ 	struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ 	int retval;
+ 
++       if (radio->disconnected)
++	       return -EIO;
+ 	if (freq->type != V4L2_TUNER_RADIO)
+ 		return -EINVAL;
+ 
+@@ -1510,11 +1546,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
+ {
+ 	struct si470x_device *radio = usb_get_intfdata(intf);
+ 
++       mutex_lock(&open_close_lock);
++       radio->disconnected = 1;
+ 	cancel_delayed_work_sync(&radio->work);
+ 	usb_set_intfdata(intf, NULL);
+-	video_unregister_device(radio->videodev);
+-	kfree(radio->buffer);
+-	kfree(radio);
++       if (radio->users == 0) {
++	       video_unregister_device(radio->videodev);
++	       kfree(radio->buffer);
++	       kfree(radio);
++       }
++       mutex_unlock(&open_close_lock);
+ }
+ 
+ 
+diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
+index 535ffe8..acc3208 100644
+--- a/drivers/media/radio/radio-terratec.c
++++ b/drivers/media/radio/radio-terratec.c
+@@ -360,7 +360,9 @@ static const struct file_operations terratec_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
+index c11981f..4ebdfba 100644
+--- a/drivers/media/radio/radio-trust.c
++++ b/drivers/media/radio/radio-trust.c
+@@ -340,7 +340,9 @@ static const struct file_operations trust_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
+index 1366326..18f2abd 100644
+--- a/drivers/media/radio/radio-typhoon.c
++++ b/drivers/media/radio/radio-typhoon.c
+@@ -35,6 +35,7 @@
+ #include <linux/init.h>		/* Initdata                       */
+ #include <linux/ioport.h>	/* request_region		  */
+ #include <linux/proc_fs.h>	/* radio card status report	  */
++#include <linux/seq_file.h>
+ #include <asm/io.h>		/* outb, outb_p                   */
+ #include <asm/uaccess.h>	/* copy to/from user              */
+ #include <linux/videodev2.h>	/* kernel radio structs           */
+@@ -93,9 +94,6 @@ static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
+ static void typhoon_mute(struct typhoon_device *dev);
+ static void typhoon_unmute(struct typhoon_device *dev);
+ static int typhoon_setvol(struct typhoon_device *dev, int vol);
+-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+-static int typhoon_get_info(char *buf, char **start, off_t offset, int len);
+-#endif
+ 
+ static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
+ {
+@@ -340,7 +338,9 @@ static const struct file_operations typhoon_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+@@ -366,30 +366,39 @@ static struct video_device typhoon_radio =
+ 
+ #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+ 
+-static int typhoon_get_info(char *buf, char **start, off_t offset, int len)
++static int typhoon_proc_show(struct seq_file *m, void *v)
+ {
+-	char *out = buf;
+-
+ 	#ifdef MODULE
+ 	    #define MODULEPROCSTRING "Driver loaded as a module"
+ 	#else
+ 	    #define MODULEPROCSTRING "Driver compiled into kernel"
+ 	#endif
+ 
+-	/* output must be kept under PAGE_SIZE */
+-	out += sprintf(out, BANNER);
+-	out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n");
+-	out += sprintf(out, "frequency = %lu kHz\n",
++	seq_puts(m, BANNER);
++	seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n");
++	seq_printf(m, "frequency = %lu kHz\n",
+ 		typhoon_unit.curfreq >> 4);
+-	out += sprintf(out, "volume = %d\n", typhoon_unit.curvol);
+-	out += sprintf(out, "mute = %s\n", typhoon_unit.muted ?
++	seq_printf(m, "volume = %d\n", typhoon_unit.curvol);
++	seq_printf(m, "mute = %s\n", typhoon_unit.muted ?
+ 		"on" : "off");
+-	out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase);
+-	out += sprintf(out, "mute frequency = %lu kHz\n",
++	seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase);
++	seq_printf(m, "mute frequency = %lu kHz\n",
+ 		typhoon_unit.mutefreq >> 4);
+-	return out - buf;
++	return 0;
+ }
+ 
++static int typhoon_proc_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, typhoon_proc_show, NULL);
++}
++
++static const struct file_operations typhoon_proc_fops = {
++	.owner		= THIS_MODULE,
++	.open		= typhoon_proc_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
+ #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
+ 
+ MODULE_AUTHOR("Dr. Henrik Seidel");
+@@ -404,7 +413,7 @@ MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
+ module_param(radio_nr, int, 0);
+ 
+ #ifdef MODULE
+-static unsigned long mutefreq = 0;
++static unsigned long mutefreq;
+ module_param(mutefreq, ulong, 0);
+ MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
+ #endif
+@@ -450,8 +459,7 @@ static int __init typhoon_init(void)
+ 	typhoon_mute(&typhoon_unit);
+ 
+ #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+-	if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL,
+-				    typhoon_get_info))
++	if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops))
+ 		printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
+ #endif
+ 
+diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
+index 203f437..43773c5 100644
+--- a/drivers/media/radio/radio-zoltrix.c
++++ b/drivers/media/radio/radio-zoltrix.c
+@@ -401,7 +401,9 @@ static const struct file_operations zoltrix_fops =
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 1832966..fe9a4cc 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -270,6 +270,15 @@ config VIDEO_SAA711X
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called saa7115.
+ 
++config VIDEO_SAA717X
++	tristate "Philips SAA7171/3/4 audio/video decoders"
++	depends on VIDEO_V4L2 && I2C
++	---help---
++	  Support for the Philips SAA7171/3/4 audio/video decoders.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called saa717x.
++
+ config VIDEO_SAA7191
+ 	tristate "Philips SAA7191 video decoder"
+ 	depends on VIDEO_V4L1 && I2C
+@@ -689,6 +698,8 @@ source "drivers/media/video/cx88/Kconfig"
+ 
+ source "drivers/media/video/cx23885/Kconfig"
+ 
++source "drivers/media/video/au0828/Kconfig"
++
+ source "drivers/media/video/ivtv/Kconfig"
+ 
+ config VIDEO_M32R_AR
+@@ -836,4 +847,49 @@ config USB_STKWEBCAM
+ 
+ endif # V4L_USB_DRIVERS
+ 
++config SOC_CAMERA
++	tristate "SoC camera support"
++	depends on VIDEO_V4L2
++	select VIDEOBUF_DMA_SG
++	help
++	  SoC Camera is a common API to several cameras, not connecting
++	  over a bus like PCI or USB. For example some i2c camera connected
++	  directly to the data bus of an SoC.
++
++config SOC_CAMERA_MT9M001
++	tristate "mt9m001 support"
++	depends on SOC_CAMERA
++	select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
++	help
++	  This driver supports MT9M001 cameras from Micron, monochrome
++	  and colour models.
++
++config MT9M001_PCA9536_SWITCH
++	bool "pca9536 datawidth switch for mt9m001"
++	depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
++	help
++	  Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
++	  extender to switch between 8 and 10 bit datawidth modes
++
++config SOC_CAMERA_MT9V022
++	tristate "mt9v022 support"
++	depends on SOC_CAMERA
++	select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
++	help
++	  This driver supports MT9V022 cameras from Micron
++
++config MT9V022_PCA9536_SWITCH
++	bool "pca9536 datawidth switch for mt9v022"
++	depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
++	help
++	  Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
++	  extender to switch between 8 and 10 bit datawidth modes
++
++config VIDEO_PXA27x
++	tristate "PXA27x Quick Capture Interface driver"
++	depends on VIDEO_DEV && PXA27x
++	select SOC_CAMERA
++	---help---
++	  This is a v4l2 driver for the PXA27x Quick Capture Interface
++
+ endif # VIDEO_CAPTURE_DRIVERS
+diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
+index 3f209b3..be14227 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -4,7 +4,7 @@
+ 
+ zr36067-objs	:=	zoran_procfs.o zoran_device.o \
+ 			zoran_driver.o zoran_card.o
+-tuner-objs	:=	tuner-core.o tuner-types.o
++tuner-objs	:=	tuner-core.o
+ 
+ msp3400-objs	:=	msp3400-driver.o msp3400-kthreads.o
+ 
+@@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
+ obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o
+ obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o
+ obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
++obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
+ obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
+ obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
+ obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
+@@ -87,6 +88,8 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o
+ 
+ obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
+ obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
++# tuner-types will be merged into tuner-simple, in the future
++obj-$(CONFIG_TUNER_SIMPLE) += tuner-types.o
+ obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
+ obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
+ obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
+@@ -135,5 +138,12 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
+ obj-$(CONFIG_VIDEO_CX23885) += cx23885/
+ 
++obj-$(CONFIG_VIDEO_PXA27x)	+= pxa_camera.o
++obj-$(CONFIG_SOC_CAMERA)	+= soc_camera.o
++obj-$(CONFIG_SOC_CAMERA_MT9M001)	+= mt9m001.o
++obj-$(CONFIG_SOC_CAMERA_MT9V022)	+= mt9v022.o
++
++obj-$(CONFIG_VIDEO_AU0828) += au0828/
++
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
+index fea2e72..f794f2d 100644
+--- a/drivers/media/video/adv7170.c
++++ b/drivers/media/video/adv7170.c
+@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(x) (x)->name
+ 
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
+index 10d4d89..8ee07a6 100644
+--- a/drivers/media/video/adv7175.c
++++ b/drivers/media/video/adv7175.c
+@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+ 
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
+index c94a4d0..8c7d195 100644
+--- a/drivers/media/video/arv.c
++++ b/drivers/media/video/arv.c
+@@ -125,8 +125,8 @@ static unsigned char	yuv[MAX_AR_FRAME_BYTES];
+ /* default frequency */
+ #define DEFAULT_FREQ	50	/* 50 or 75 (MHz) is available as BCLK */
+ static int freq = DEFAULT_FREQ;	/* BCLK: available 50 or 70 (MHz) */
+-static int vga = 0;		/* default mode(0:QVGA mode, other:VGA mode) */
+-static int vga_interlace = 0;	/* 0 is normal mode for, else interlace mode */
++static int vga;			/* default mode(0:QVGA mode, other:VGA mode) */
++static int vga_interlace;	/* 0 is normal mode for, else interlace mode */
+ module_param(freq, int, 0);
+ module_param(vga, int, 0);
+ module_param(vga_interlace, int, 0);
+@@ -747,7 +747,9 @@ static const struct file_operations ar_fops = {
+ 	.release	= video_exclusive_release,
+ 	.read		= ar_read,
+ 	.ioctl		= ar_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek		= no_llseek,
+ };
+ 
+diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
+new file mode 100644
+index 0000000..4170826
+--- /dev/null
++++ b/drivers/media/video/au0828/Kconfig
+@@ -0,0 +1,12 @@
++
++config VIDEO_AU0828
++	tristate "Auvitek AU0828 support"
++       depends on VIDEO_DEV && I2C && INPUT && DVB_CORE
++	select I2C_ALGOBIT
++	select DVB_AU8522 if !DVB_FE_CUSTOMIZE
++	select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
++	---help---
++	  This is a video4linux driver for Auvitek's USB device.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called au0828
+diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile
+new file mode 100644
+index 0000000..9f4f572
+--- /dev/null
++++ b/drivers/media/video/au0828/Makefile
+@@ -0,0 +1,9 @@
++au0828-objs	:= au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
++
++obj-$(CONFIG_VIDEO_AU0828) += au0828.o
++
++EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
++EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
++
++EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
+new file mode 100644
+index 0000000..a2a6983
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-cards.c
+@@ -0,0 +1,181 @@
++/*
++ *  Driver for the Auvitek USB bridge
++ *
++ *  Copyright (c) 2008 Steven Toth <stoth at hauppauge.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 "au0828.h"
++#include "au0828-cards.h"
++
++struct au0828_board au0828_boards[] = {
++	[AU0828_BOARD_UNKNOWN] = {
++		.name	= "Unknown board",
++	},
++	[AU0828_BOARD_HAUPPAUGE_HVR850] = {
++		.name	= "Hauppauge HVR850",
++	},
++	[AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
++		.name	= "Hauppauge HVR950Q",
++	},
++	[AU0828_BOARD_DVICO_FUSIONHDTV7] = {
++		.name	= "DViCO FusionHDTV USB",
++	},
++};
++
++/* Tuner callback function for au0828 boards. Currently only needed
++ * for HVR1500Q, which has an xc5000 tuner.
++ */
++int au0828_tuner_callback(void *priv, int command, int arg)
++{
++	struct au0828_dev *dev = priv;
++
++	dprintk(1, "%s()\n", __func__);
++
++	switch (dev->board) {
++	case AU0828_BOARD_HAUPPAUGE_HVR850:
++	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++	case AU0828_BOARD_DVICO_FUSIONHDTV7:
++		if (command == 0) {
++			/* Tuner Reset Command from xc5000 */
++			/* Drive the tuner into reset and out */
++			au0828_clear(dev, REG_001, 2);
++			mdelay(200);
++			au0828_set(dev, REG_001, 2);
++			mdelay(50);
++			return 0;
++		} else {
++			printk(KERN_ERR
++				"%s(): Unknown command.\n", __func__);
++			return -EINVAL;
++		}
++		break;
++	}
++
++	return 0; /* Should never be here */
++}
++
++static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
++{
++	struct tveeprom tv;
++
++	tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
++
++	/* Make sure we support the board model */
++	switch (tv.model) {
++	case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
++	case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
++		break;
++	default:
++		printk(KERN_WARNING "%s: warning: "
++		       "unknown hauppauge model #%d\n", __func__, tv.model);
++		break;
++	}
++
++	printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
++	       __func__, tv.model);
++}
++
++void au0828_card_setup(struct au0828_dev *dev)
++{
++	static u8 eeprom[256];
++
++	dprintk(1, "%s()\n", __func__);
++
++	if (dev->i2c_rc == 0) {
++		dev->i2c_client.addr = 0xa0 >> 1;
++		tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
++	}
++
++	switch (dev->board) {
++	case AU0828_BOARD_HAUPPAUGE_HVR850:
++	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++		if (dev->i2c_rc == 0)
++			hauppauge_eeprom(dev, eeprom+0xa0);
++		break;
++	}
++}
++
++/*
++ * The bridge has between 8 and 12 gpios.
++ * Regs 1 and 0 deal with output enables.
++ * Regs 3 and 2 deal with direction.
++ */
++void au0828_gpio_setup(struct au0828_dev *dev)
++{
++	dprintk(1, "%s()\n", __func__);
++
++	switch (dev->board) {
++	case AU0828_BOARD_HAUPPAUGE_HVR850:
++	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++		/* GPIO's
++		 * 4 - CS5340
++		 * 5 - AU8522 Demodulator
++		 * 6 - eeprom W/P
++		 * 9 - XC5000 Tuner
++		 */
++
++		/* Into reset */
++		au0828_write(dev, REG_003, 0x02);
++		au0828_write(dev, REG_002, 0x88 | 0x20);
++		au0828_write(dev, REG_001, 0x0);
++		au0828_write(dev, REG_000, 0x0);
++		msleep(100);
++
++		/* Out of reset */
++		au0828_write(dev, REG_003, 0x02);
++		au0828_write(dev, REG_001, 0x02);
++		au0828_write(dev, REG_002, 0x88 | 0x20);
++		au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40);
++		msleep(250);
++		break;
++	case AU0828_BOARD_DVICO_FUSIONHDTV7:
++		/* GPIO's
++		 * 6 - ?
++		 * 8 - AU8522 Demodulator
++		 * 9 - XC5000 Tuner
++		 */
++
++		/* Into reset */
++		au0828_write(dev, REG_003, 0x02);
++		au0828_write(dev, REG_002, 0xa0);
++		au0828_write(dev, REG_001, 0x0);
++		au0828_write(dev, REG_000, 0x0);
++		msleep(100);
++
++		/* Out of reset */
++		au0828_write(dev, REG_003, 0x02);
++		au0828_write(dev, REG_002, 0xa0);
++		au0828_write(dev, REG_001, 0x02);
++		au0828_write(dev, REG_000, 0xa0);
++		msleep(250);
++		break;
++	}
++}
++
++/* table of devices that work with this driver */
++struct usb_device_id au0828_usb_id_table [] = {
++	{ USB_DEVICE(0x2040, 0x7200),
++		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
++	{ USB_DEVICE(0x2040, 0x7240),
++		.driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
++	{ USB_DEVICE(0x0fe9, 0xd620),
++		.driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
++	{ },
++};
++
++MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);
+diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h
+new file mode 100644
+index 0000000..e26f54a
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-cards.h
+@@ -0,0 +1,25 @@
++/*
++ *  Driver for the Auvitek USB bridge
++ *
++ *  Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#define AU0828_BOARD_UNKNOWN		0
++#define AU0828_BOARD_HAUPPAUGE_HVR950Q	1
++#define AU0828_BOARD_HAUPPAUGE_HVR850 	2
++#define AU0828_BOARD_DVICO_FUSIONHDTV7	3
+diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
+new file mode 100644
+index 0000000..54bfc0f
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-core.c
+@@ -0,0 +1,256 @@
++/*
++ *  Driver for the Auvitek USB bridge
++ *
++ *  Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/videodev2.h>
++#include <media/v4l2-common.h>
++#include <linux/mutex.h>
++
++#include "au0828.h"
++
++/*
++ * 1 = General debug messages
++ * 2 = USB handling
++ * 4 = I2C related
++ * 8 = Bridge related
++ */
++int au0828_debug;
++module_param_named(debug, au0828_debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable debug messages");
++
++#define _AU0828_BULKPIPE 0x03
++#define _BULKPIPESIZE 0xffff
++
++static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
++	u16 index, unsigned char *cp, u16 size);
++static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
++	u16 index, unsigned char *cp, u16 size);
++
++/* USB Direction */
++#define CMD_REQUEST_IN		0x00
++#define CMD_REQUEST_OUT		0x01
++
++u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
++{
++	recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1);
++	dprintk(8, "%s(0x%x) = 0x%x\n", __func__, reg, dev->ctrlmsg[0]);
++	return dev->ctrlmsg[0];
++}
++
++u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
++{
++	dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val);
++	return send_control_msg(dev, CMD_REQUEST_OUT, val, reg,
++				dev->ctrlmsg, 0);
++}
++
++static void cmd_msg_dump(struct au0828_dev *dev)
++{
++	int i;
++
++	for (i = 0; i < sizeof(dev->ctrlmsg); i += 16)
++		dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x "
++				"%02x %02x %02x %02x %02x %02x %02x %02x\n",
++			__func__,
++			dev->ctrlmsg[i+0], dev->ctrlmsg[i+1],
++			dev->ctrlmsg[i+2], dev->ctrlmsg[i+3],
++			dev->ctrlmsg[i+4], dev->ctrlmsg[i+5],
++			dev->ctrlmsg[i+6], dev->ctrlmsg[i+7],
++			dev->ctrlmsg[i+8], dev->ctrlmsg[i+9],
++			dev->ctrlmsg[i+10], dev->ctrlmsg[i+11],
++			dev->ctrlmsg[i+12], dev->ctrlmsg[i+13],
++			dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]);
++}
++
++static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
++	u16 index, unsigned char *cp, u16 size)
++{
++	int status = -ENODEV;
++	mutex_lock(&dev->mutex);
++	if (dev->usbdev) {
++
++		/* cp must be memory that has been allocated by kmalloc */
++		status = usb_control_msg(dev->usbdev,
++				usb_sndctrlpipe(dev->usbdev, 0),
++				request,
++				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++				value, index,
++				cp, size, 1000);
++
++		status = min(status, 0);
++
++		if (status < 0) {
++			printk(KERN_ERR "%s() Failed sending control message, error %d.\n",
++				__func__, status);
++		}
++
++	}
++	mutex_unlock(&dev->mutex);
++	return status;
++}
++
++static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
++	u16 index, unsigned char *cp, u16 size)
++{
++	int status = -ENODEV;
++	mutex_lock(&dev->mutex);
++	if (dev->usbdev) {
++
++		memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg));
++
++		/* cp must be memory that has been allocated by kmalloc */
++		status = usb_control_msg(dev->usbdev,
++				usb_rcvctrlpipe(dev->usbdev, 0),
++				request,
++				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++				value, index,
++				cp, size, 1000);
++
++		status = min(status, 0);
++
++		if (status < 0) {
++			printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
++				__func__, status);
++		} else
++			cmd_msg_dump(dev);
++	}
++	mutex_unlock(&dev->mutex);
++	return status;
++}
++
++static void au0828_usb_disconnect(struct usb_interface *interface)
++{
++	struct au0828_dev *dev = usb_get_intfdata(interface);
++
++	dprintk(1, "%s()\n", __func__);
++
++	/* Digital TV */
++	au0828_dvb_unregister(dev);
++
++	/* I2C */
++	au0828_i2c_unregister(dev);
++
++	usb_set_intfdata(interface, NULL);
++
++	mutex_lock(&dev->mutex);
++	dev->usbdev = NULL;
++	mutex_unlock(&dev->mutex);
++
++	kfree(dev);
++
++}
++
++static int au0828_usb_probe(struct usb_interface *interface,
++	const struct usb_device_id *id)
++{
++	int ifnum;
++	struct au0828_dev *dev;
++	struct usb_device *usbdev = interface_to_usbdev(interface);
++
++	ifnum = interface->altsetting->desc.bInterfaceNumber;
++
++	if (ifnum != 0)
++		return -ENODEV;
++
++	dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
++		le16_to_cpu(usbdev->descriptor.idVendor),
++		le16_to_cpu(usbdev->descriptor.idProduct),
++		ifnum);
++
++	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++	if (dev == NULL) {
++		printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
++		return -ENOMEM;
++	}
++
++	mutex_init(&dev->mutex);
++	mutex_init(&dev->dvb.lock);
++	dev->usbdev = usbdev;
++	dev->board = id->driver_info;
++
++	usb_set_intfdata(interface, dev);
++
++	/* Power Up the bridge */
++	au0828_write(dev, REG_600, 1 << 4);
++
++	/* Bring up the GPIO's and supporting devices */
++	au0828_gpio_setup(dev);
++
++	/* I2C */
++	au0828_i2c_register(dev);
++
++	/* Setup */
++	au0828_card_setup(dev);
++
++	/* Digital TV */
++	au0828_dvb_register(dev);
++
++	printk(KERN_INFO "Registered device AU0828 [%s]\n",
++		au0828_boards[dev->board].name == NULL ? "Unset" :
++		au0828_boards[dev->board].name);
++
++	return 0;
++}
++
++static struct usb_driver au0828_usb_driver = {
++	.name		= DRIVER_NAME,
++	.probe		= au0828_usb_probe,
++	.disconnect	= au0828_usb_disconnect,
++	.id_table	= au0828_usb_id_table,
++};
++
++static int __init au0828_init(void)
++{
++	int ret;
++
++	if (au0828_debug & 1)
++		printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
++
++	if (au0828_debug & 2)
++		printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
++
++	if (au0828_debug & 4)
++		printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
++
++	if (au0828_debug & 8)
++		printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
++		       __func__);
++
++	printk(KERN_INFO "au0828 driver loaded\n");
++
++	ret = usb_register(&au0828_usb_driver);
++	if (ret)
++		printk(KERN_ERR "usb_register failed, error = %d\n", ret);
++
++	return ret;
++}
++
++static void __exit au0828_exit(void)
++{
++	usb_deregister(&au0828_usb_driver);
++}
++
++module_init(au0828_init);
++module_exit(au0828_exit);
++
++MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
++MODULE_AUTHOR("Steven Toth <stoth at hauppauge.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
+new file mode 100644
+index 0000000..5040d7f
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-dvb.c
+@@ -0,0 +1,373 @@
++/*
++ *  Driver for the Auvitek USB bridge
++ *
++ *  Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/suspend.h>
++#include <media/v4l2-common.h>
++
++#include "au0828.h"
++#include "au8522.h"
++#include "xc5000.h"
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
++#define _AU0828_BULKPIPE 0x83
++#define _BULKPIPESIZE 0xe522
++
++static struct au8522_config hauppauge_hvr950q_config = {
++	.demod_address = 0x8e >> 1,
++	.status_mode   = AU8522_DEMODLOCKING,
++};
++
++static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
++	.i2c_address      = 0x61,
++	.if_khz           = 6000,
++	.tuner_callback   = au0828_tuner_callback
++};
++
++/*-------------------------------------------------------------------*/
++static void urb_completion(struct urb *purb)
++{
++	u8 *ptr;
++	struct au0828_dev *dev = purb->context;
++	int ptype = usb_pipetype(purb->pipe);
++
++	dprintk(2, "%s()\n", __func__);
++
++	if (!dev)
++		return;
++
++	if (dev->urb_streaming == 0)
++		return;
++
++	if (ptype != PIPE_BULK) {
++		printk(KERN_ERR "%s() Unsupported URB type %d\n",
++		       __func__, ptype);
++		return;
++	}
++
++	ptr = (u8 *)purb->transfer_buffer;
++
++	/* Feed the transport payload into the kernel demux */
++	dvb_dmx_swfilter_packets(&dev->dvb.demux,
++		purb->transfer_buffer, purb->actual_length / 188);
++
++	/* Clean the buffer before we requeue */
++	memset(purb->transfer_buffer, 0, URB_BUFSIZE);
++
++	/* Requeue URB */
++	usb_submit_urb(purb, GFP_ATOMIC);
++}
++
++static int stop_urb_transfer(struct au0828_dev *dev)
++{
++	int i;
++
++	dprintk(2, "%s()\n", __func__);
++
++	for (i = 0; i < URB_COUNT; i++) {
++		usb_kill_urb(dev->urbs[i]);
++		kfree(dev->urbs[i]->transfer_buffer);
++		usb_free_urb(dev->urbs[i]);
++	}
++
++	dev->urb_streaming = 0;
++
++	return 0;
++}
++
++static int start_urb_transfer(struct au0828_dev *dev)
++{
++	struct urb *purb;
++	int i, ret = -ENOMEM;
++
++	dprintk(2, "%s()\n", __func__);
++
++	if (dev->urb_streaming) {
++		dprintk(2, "%s: iso xfer already running!\n", __func__);
++		return 0;
++	}
++
++	for (i = 0; i < URB_COUNT; i++) {
++
++		dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
++		if (!dev->urbs[i])
++			goto err;
++
++		purb = dev->urbs[i];
++
++		purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL);
++		if (!purb->transfer_buffer) {
++			usb_free_urb(purb);
++			dev->urbs[i] = 0;
++			goto err;
++		}
++
++		purb->status = -EINPROGRESS;
++		usb_fill_bulk_urb(purb,
++				  dev->usbdev,
++				  usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE),
++				  purb->transfer_buffer,
++				  URB_BUFSIZE,
++				  urb_completion,
++				  dev);
++
++	}
++
++	for (i = 0; i < URB_COUNT; i++) {
++		ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC);
++		if (ret != 0) {
++			stop_urb_transfer(dev);
++			printk(KERN_ERR "%s: failed urb submission, "
++			       "err = %d\n", __func__, ret);
++			return ret;
++		}
++	}
++
++	dev->urb_streaming = 1;
++	ret = 0;
++
++err:
++	return ret;
++}
++
++static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
++{
++	struct dvb_demux *demux = feed->demux;
++	struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
++	struct au0828_dvb *dvb = &dev->dvb;
++	int ret = 0;
++
++	dprintk(1, "%s()\n", __func__);
++
++	if (!demux->dmx.frontend)
++		return -EINVAL;
++
++	if (dvb) {
++		mutex_lock(&dvb->lock);
++		if (dvb->feeding++ == 0) {
++			/* Start transport */
++			au0828_write(dev, 0x608, 0x90);
++			au0828_write(dev, 0x609, 0x72);
++			au0828_write(dev, 0x60a, 0x71);
++			au0828_write(dev, 0x60b, 0x01);
++			ret = start_urb_transfer(dev);
++		}
++		mutex_unlock(&dvb->lock);
++	}
++
++	return ret;
++}
++
++static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
++{
++	struct dvb_demux *demux = feed->demux;
++	struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
++	struct au0828_dvb *dvb = &dev->dvb;
++	int ret = 0;
++
++	dprintk(1, "%s()\n", __func__);
++
++	if (dvb) {
++		mutex_lock(&dvb->lock);
++		if (--dvb->feeding == 0) {
++			/* Stop transport */
++			au0828_write(dev, 0x608, 0x00);
++			au0828_write(dev, 0x609, 0x00);
++			au0828_write(dev, 0x60a, 0x00);
++			au0828_write(dev, 0x60b, 0x00);
++			ret = stop_urb_transfer(dev);
++		}
++		mutex_unlock(&dvb->lock);
++	}
++
++	return ret;
++}
++
++static int dvb_register(struct au0828_dev *dev)
++{
++	struct au0828_dvb *dvb = &dev->dvb;
++	int result;
++
++	dprintk(1, "%s()\n", __func__);
++
++	/* register adapter */
++	result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
++				      &dev->usbdev->dev, adapter_nr);
++	if (result < 0) {
++		printk(KERN_ERR "%s: dvb_register_adapter failed "
++		       "(errno = %d)\n", DRIVER_NAME, result);
++		goto fail_adapter;
++	}
++	dvb->adapter.priv = dev;
++
++	/* register frontend */
++	result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
++	if (result < 0) {
++		printk(KERN_ERR "%s: dvb_register_frontend failed "
++		       "(errno = %d)\n", DRIVER_NAME, result);
++		goto fail_frontend;
++	}
++
++	/* register demux stuff */
++	dvb->demux.dmx.capabilities =
++		DMX_TS_FILTERING | DMX_SECTION_FILTERING |
++		DMX_MEMORY_BASED_FILTERING;
++	dvb->demux.priv       = dev;
++	dvb->demux.filternum  = 256;
++	dvb->demux.feednum    = 256;
++	dvb->demux.start_feed = au0828_dvb_start_feed;
++	dvb->demux.stop_feed  = au0828_dvb_stop_feed;
++	result = dvb_dmx_init(&dvb->demux);
++	if (result < 0) {
++		printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
++		       DRIVER_NAME, result);
++		goto fail_dmx;
++	}
++
++	dvb->dmxdev.filternum    = 256;
++	dvb->dmxdev.demux        = &dvb->demux.dmx;
++	dvb->dmxdev.capabilities = 0;
++	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
++	if (result < 0) {
++		printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
++		       DRIVER_NAME, result);
++		goto fail_dmxdev;
++	}
++
++	dvb->fe_hw.source = DMX_FRONTEND_0;
++	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++	if (result < 0) {
++		printk(KERN_ERR "%s: add_frontend failed "
++		       "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result);
++		goto fail_fe_hw;
++	}
++
++	dvb->fe_mem.source = DMX_MEMORY_FE;
++	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++	if (result < 0) {
++		printk(KERN_ERR "%s: add_frontend failed "
++		       "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result);
++		goto fail_fe_mem;
++	}
++
++	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++	if (result < 0) {
++		printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
++		       DRIVER_NAME, result);
++		goto fail_fe_conn;
++	}
++
++	/* register network adapter */
++	dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
++	return 0;
++
++fail_fe_conn:
++	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++fail_fe_mem:
++	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++fail_fe_hw:
++	dvb_dmxdev_release(&dvb->dmxdev);
++fail_dmxdev:
++	dvb_dmx_release(&dvb->demux);
++fail_dmx:
++	dvb_unregister_frontend(dvb->frontend);
++fail_frontend:
++	dvb_frontend_detach(dvb->frontend);
++	dvb_unregister_adapter(&dvb->adapter);
++fail_adapter:
++	return result;
++}
++
++void au0828_dvb_unregister(struct au0828_dev *dev)
++{
++	struct au0828_dvb *dvb = &dev->dvb;
++
++	dprintk(1, "%s()\n", __func__);
++
++	if (dvb->frontend == NULL)
++		return;
++
++	dvb_net_release(&dvb->net);
++	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++	dvb_dmxdev_release(&dvb->dmxdev);
++	dvb_dmx_release(&dvb->demux);
++	dvb_unregister_frontend(dvb->frontend);
++	dvb_frontend_detach(dvb->frontend);
++	dvb_unregister_adapter(&dvb->adapter);
++}
++
++/* All the DVB attach calls go here, this function get's modified
++ * for each new card. No other function in this file needs
++ * to change.
++ */
++int au0828_dvb_register(struct au0828_dev *dev)
++{
++	struct au0828_dvb *dvb = &dev->dvb;
++	int ret;
++
++	dprintk(1, "%s()\n", __func__);
++
++	/* init frontend */
++	switch (dev->board) {
++	case AU0828_BOARD_HAUPPAUGE_HVR850:
++	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++	case AU0828_BOARD_DVICO_FUSIONHDTV7:
++		dvb->frontend = dvb_attach(au8522_attach,
++				&hauppauge_hvr950q_config,
++				&dev->i2c_adap);
++		if (dvb->frontend != NULL) {
++			hauppauge_hvr950q_tunerconfig.priv = dev;
++			dvb_attach(xc5000_attach, dvb->frontend,
++				&dev->i2c_adap,
++				&hauppauge_hvr950q_tunerconfig);
++		}
++		break;
++	default:
++		printk(KERN_WARNING "The frontend of your DVB/ATSC card "
++		       "isn't supported yet\n");
++		break;
++	}
++	if (NULL == dvb->frontend) {
++		printk(KERN_ERR "%s() Frontend initialization failed\n",
++		       __func__);
++		return -1;
++	}
++
++	/* Put the analog decoder in standby to keep it quiet */
++	au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL);
++
++	if (dvb->frontend->ops.analog_ops.standby)
++		dvb->frontend->ops.analog_ops.standby(dvb->frontend);
++
++	/* register everything */
++	ret = dvb_register(dev);
++	if (ret < 0) {
++		if (dvb->frontend->ops.release)
++			dvb->frontend->ops.release(dvb->frontend);
++		return ret;
++	}
++
++	return 0;
++}
+diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
+new file mode 100644
+index 0000000..741a493
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-i2c.c
+@@ -0,0 +1,381 @@
++/*
++ *  Driver for the Auvitek AU0828 USB bridge
++ *
++ *  Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++
++#include "au0828.h"
++
++#include <media/v4l2-common.h>
++
++static int i2c_scan;
++module_param(i2c_scan, int, 0444);
++MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
++
++#define I2C_WAIT_DELAY 512
++#define I2C_WAIT_RETRY 64
++
++static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
++{
++	struct au0828_dev *dev = i2c_adap->algo_data;
++	return au0828_read(dev, REG_201) & 0x08 ? 0 : 1;
++}
++
++static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
++{
++	struct au0828_dev *dev = i2c_adap->algo_data;
++	return au0828_read(dev, REG_201) & 0x02 ? 0 : 1;
++}
++
++static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
++{
++	int count;
++
++	for (count = 0; count < I2C_WAIT_RETRY; count++) {
++		if (!i2c_slave_did_read_ack(i2c_adap))
++			break;
++		udelay(I2C_WAIT_DELAY);
++	}
++
++	if (I2C_WAIT_RETRY == count)
++		return 0;
++
++	return 1;
++}
++
++static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
++{
++	struct au0828_dev *dev = i2c_adap->algo_data;
++	return au0828_read(dev, REG_201) & 0x01 ? 0 : 1;
++}
++
++static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
++{
++	int count;
++
++	for (count = 0; count < I2C_WAIT_RETRY; count++) {
++		if (!i2c_is_read_busy(i2c_adap))
++			break;
++		udelay(I2C_WAIT_DELAY);
++	}
++
++	if (I2C_WAIT_RETRY == count)
++		return 0;
++
++	return 1;
++}
++
++static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
++{
++	struct au0828_dev *dev = i2c_adap->algo_data;
++	return au0828_read(dev, REG_201) & 0x04 ? 1 : 0;
++}
++
++static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
++{
++	int count;
++
++	for (count = 0; count < I2C_WAIT_RETRY; count++) {
++		if (i2c_is_write_done(i2c_adap))
++			break;
++		udelay(I2C_WAIT_DELAY);
++	}
++
++	if (I2C_WAIT_RETRY == count)
++		return 0;
++
++	return 1;
++}
++
++static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
++{
++	struct au0828_dev *dev = i2c_adap->algo_data;
++	return au0828_read(dev, REG_201) & 0x10 ? 1 : 0;
++}
++
++static int i2c_wait_done(struct i2c_adapter *i2c_adap)
++{
++	int count;
++
++	for (count = 0; count < I2C_WAIT_RETRY; count++) {
++		if (!i2c_is_busy(i2c_adap))
++			break;
++		udelay(I2C_WAIT_DELAY);
++	}
++
++	if (I2C_WAIT_RETRY == count)
++		return 0;
++
++	return 1;
++}
++
++/* FIXME: Implement join handling correctly */
++static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
++	const struct i2c_msg *msg, int joined_rlen)
++{
++	int i, strobe = 0;
++	struct au0828_dev *dev = i2c_adap->algo_data;
++
++	dprintk(4, "%s()\n", __func__);
++
++	au0828_write(dev, REG_2FF, 0x01);
++	au0828_write(dev, REG_202, 0x07);
++
++	/* Hardware needs 8 bit addresses */
++	au0828_write(dev, REG_203, msg->addr << 1);
++
++	dprintk(4, "SEND: %02x\n", msg->addr);
++
++	for (i = 0; i < msg->len;) {
++
++		dprintk(4, " %02x\n", msg->buf[i]);
++
++		au0828_write(dev, REG_205, msg->buf[i]);
++
++		strobe++;
++		i++;
++
++		if ((strobe >= 4) || (i >= msg->len)) {
++
++			/* Strobe the byte into the bus */
++			if (i < msg->len)
++				au0828_write(dev, REG_200, 0x41);
++			else
++				au0828_write(dev, REG_200, 0x01);
++
++			/* Reset strobe trigger */
++			strobe = 0;
++
++			if (!i2c_wait_write_done(i2c_adap))
++				return -EIO;
++
++		}
++
++	}
++	if (!i2c_wait_done(i2c_adap))
++		return -EIO;
++
++	dprintk(4, "\n");
++
++	return msg->len;
++}
++
++/* FIXME: Implement join handling correctly */
++static int i2c_readbytes(struct i2c_adapter *i2c_adap,
++	const struct i2c_msg *msg, int joined)
++{
++	struct au0828_dev *dev = i2c_adap->algo_data;
++	int i;
++
++	dprintk(4, "%s()\n", __func__);
++
++	au0828_write(dev, REG_2FF, 0x01);
++	au0828_write(dev, REG_202, 0x07);
++
++	/* Hardware needs 8 bit addresses */
++	au0828_write(dev, REG_203, msg->addr << 1);
++
++	dprintk(4, " RECV:\n");
++
++	/* Deal with i2c_scan */
++	if (msg->len == 0) {
++		au0828_write(dev, REG_200, 0x20);
++		if (i2c_wait_read_ack(i2c_adap))
++			return -EIO;
++		return 0;
++	}
++
++	for (i = 0; i < msg->len;) {
++
++		i++;
++
++		if (i < msg->len)
++			au0828_write(dev, REG_200, 0x60);
++		else
++			au0828_write(dev, REG_200, 0x20);
++
++		if (!i2c_wait_read_done(i2c_adap))
++			return -EIO;
++
++		msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff;
++
++		dprintk(4, " %02x\n", msg->buf[i-1]);
++	}
++	if (!i2c_wait_done(i2c_adap))
++		return -EIO;
++
++	dprintk(4, "\n");
++
++	return msg->len;
++}
++
++static int i2c_xfer(struct i2c_adapter *i2c_adap,
++		    struct i2c_msg *msgs, int num)
++{
++	int i, retval = 0;
++
++	dprintk(4, "%s(num = %d)\n", __func__, num);
++
++	for (i = 0; i < num; i++) {
++		dprintk(4, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
++			__func__, num, msgs[i].addr, msgs[i].len);
++		if (msgs[i].flags & I2C_M_RD) {
++			/* read */
++			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
++		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
++			   msgs[i].addr == msgs[i + 1].addr) {
++			/* write then read from same address */
++			retval = i2c_sendbytes(i2c_adap, &msgs[i],
++					       msgs[i + 1].len);
++			if (retval < 0)
++				goto err;
++			i++;
++			retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
++		} else {
++			/* write */
++			retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
++		}
++		if (retval < 0)
++			goto err;
++	}
++	return num;
++
++err:
++	return retval;
++}
++
++static int attach_inform(struct i2c_client *client)
++{
++	dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
++		client->driver->driver.name, client->addr, client->name);
++
++	if (!client->driver->command)
++		return 0;
++
++	return 0;
++}
++
++static int detach_inform(struct i2c_client *client)
++{
++	dprintk(1, "i2c detach [client=%s]\n", client->name);
++
++	return 0;
++}
++
++void au0828_call_i2c_clients(struct au0828_dev *dev,
++			      unsigned int cmd, void *arg)
++{
++	if (dev->i2c_rc != 0)
++		return;
++
++	i2c_clients_command(&dev->i2c_adap, cmd, arg);
++}
++
++static u32 au0828_functionality(struct i2c_adapter *adap)
++{
++	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
++}
++
++static struct i2c_algorithm au0828_i2c_algo_template = {
++	.master_xfer	= i2c_xfer,
++	.functionality	= au0828_functionality,
++};
++
++/* ----------------------------------------------------------------------- */
++
++static struct i2c_adapter au0828_i2c_adap_template = {
++	.name              = DRIVER_NAME,
++	.owner             = THIS_MODULE,
++	.id                = I2C_HW_B_AU0828,
++	.algo              = &au0828_i2c_algo_template,
++	.class             = I2C_CLASS_TV_ANALOG,
++	.client_register   = attach_inform,
++	.client_unregister = detach_inform,
++};
++
++static struct i2c_client au0828_i2c_client_template = {
++	.name	= "au0828 internal",
++};
++
++static char *i2c_devs[128] = {
++	[0x8e >> 1] = "au8522",
++	[0xa0 >> 1] = "eeprom",
++	[0xc2 >> 1] = "tuner/xc5000",
++};
++
++static void do_i2c_scan(char *name, struct i2c_client *c)
++{
++	unsigned char buf;
++	int i, rc;
++
++	for (i = 0; i < 128; i++) {
++		c->addr = i;
++		rc = i2c_master_recv(c, &buf, 0);
++		if (rc < 0)
++			continue;
++		printk(KERN_INFO "%s: i2c scan: found device @ 0x%x  [%s]\n",
++		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
++	}
++}
++
++/* init + register i2c algo-bit adapter */
++int au0828_i2c_register(struct au0828_dev *dev)
++{
++	dprintk(1, "%s()\n", __func__);
++
++	memcpy(&dev->i2c_adap, &au0828_i2c_adap_template,
++	       sizeof(dev->i2c_adap));
++	memcpy(&dev->i2c_algo, &au0828_i2c_algo_template,
++	       sizeof(dev->i2c_algo));
++	memcpy(&dev->i2c_client, &au0828_i2c_client_template,
++	       sizeof(dev->i2c_client));
++
++	dev->i2c_adap.dev.parent = &dev->usbdev->dev;
++
++	strlcpy(dev->i2c_adap.name, DRIVER_NAME,
++		sizeof(dev->i2c_adap.name));
++
++	dev->i2c_algo.data = dev;
++	dev->i2c_adap.algo_data = dev;
++	i2c_set_adapdata(&dev->i2c_adap, dev);
++	i2c_add_adapter(&dev->i2c_adap);
++
++	dev->i2c_client.adapter = &dev->i2c_adap;
++
++	if (0 == dev->i2c_rc) {
++		printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME);
++		if (i2c_scan)
++			do_i2c_scan(DRIVER_NAME, &dev->i2c_client);
++	} else
++		printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME);
++
++	return dev->i2c_rc;
++}
++
++int au0828_i2c_unregister(struct au0828_dev *dev)
++{
++	i2c_del_adapter(&dev->i2c_adap);
++	return 0;
++}
++
+diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h
+new file mode 100644
+index 0000000..3982755
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-reg.h
+@@ -0,0 +1,38 @@
++/*
++ *  Driver for the Auvitek USB bridge
++ *
++ *  Copyright (c) 2008 Steven Toth <stoth at hauppauge.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.
++ */
++
++/* We'll start to rename these registers once we have a better
++ * understanding of their meaning.
++ */
++#define REG_000 0x000
++#define REG_001 0x001
++#define REG_002 0x002
++#define REG_003 0x003
++
++#define REG_200 0x200
++#define REG_201 0x201
++#define REG_202 0x202
++#define REG_203 0x203
++#define REG_205 0x205
++#define REG_209 0x209
++#define REG_2FF 0x2ff
++
++#define REG_600 0x600
+diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
+new file mode 100644
+index 0000000..7beb571
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828.h
+@@ -0,0 +1,124 @@
++/*
++ *  Driver for the Auvitek AU0828 USB bridge
++ *
++ *  Copyright (c) 2008 Steven Toth <stoth at hauppauge.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/usb.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
++#include <media/tveeprom.h>
++
++/* DVB */
++#include "demux.h"
++#include "dmxdev.h"
++#include "dvb_demux.h"
++#include "dvb_frontend.h"
++#include "dvb_net.h"
++#include "dvbdev.h"
++
++#include "au0828-reg.h"
++#include "au0828-cards.h"
++
++#define DRIVER_NAME "au0828"
++#define URB_COUNT   16
++#define URB_BUFSIZE (0xe522)
++
++struct au0828_board {
++	char *name;
++};
++
++struct au0828_dvb {
++	struct mutex lock;
++	struct dvb_adapter adapter;
++	struct dvb_frontend *frontend;
++	struct dvb_demux demux;
++	struct dmxdev dmxdev;
++	struct dmx_frontend fe_hw;
++	struct dmx_frontend fe_mem;
++	struct dvb_net net;
++	int feeding;
++};
++
++struct au0828_dev {
++	struct mutex mutex;
++	struct usb_device	*usbdev;
++	int			board;
++	u8			ctrlmsg[64];
++
++	/* I2C */
++	struct i2c_adapter		i2c_adap;
++	struct i2c_algo_bit_data	i2c_algo;
++	struct i2c_client		i2c_client;
++	u32 				i2c_rc;
++
++	/* Digital */
++	struct au0828_dvb		dvb;
++
++	/* USB / URB Related */
++	int		urb_streaming;
++	struct urb	*urbs[URB_COUNT];
++
++};
++
++struct au0828_buff {
++	struct au0828_dev	*dev;
++	struct urb		*purb;
++	struct list_head	buff_list;
++};
++
++/* ----------------------------------------------------------- */
++#define au0828_read(dev, reg) au0828_readreg(dev, reg)
++#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
++#define au0828_andor(dev, reg, mask, value) 				\
++	 au0828_writereg(dev, reg, 					\
++	(au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask)))
++
++#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit))
++#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0)
++
++/* ----------------------------------------------------------- */
++/* au0828-core.c */
++extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
++extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
++extern int au0828_debug;
++
++/* ----------------------------------------------------------- */
++/* au0828-cards.c */
++extern struct au0828_board au0828_boards[];
++extern struct usb_device_id au0828_usb_id_table[];
++extern void au0828_gpio_setup(struct au0828_dev *dev);
++extern int au0828_tuner_callback(void *priv, int command, int arg);
++extern void au0828_card_setup(struct au0828_dev *dev);
++
++/* ----------------------------------------------------------- */
++/* au0828-i2c.c */
++extern int au0828_i2c_register(struct au0828_dev *dev);
++extern int au0828_i2c_unregister(struct au0828_dev *dev);
++extern void au0828_call_i2c_clients(struct au0828_dev *dev,
++	unsigned int cmd, void *arg);
++
++/* ----------------------------------------------------------- */
++/* au0828-dvb.c */
++extern int au0828_dvb_register(struct au0828_dev *dev);
++extern void au0828_dvb_unregister(struct au0828_dev *dev);
++
++#define dprintk(level, fmt, arg...)\
++	do { if (au0828_debug & level)\
++		printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
++	} while (0)
+diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
+index e663cc0..8bfd5c7 100644
+--- a/drivers/media/video/bt819.c
++++ b/drivers/media/video/bt819.c
+@@ -57,7 +57,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+ 
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
+index 7dee2e3..98ee2d8 100644
+--- a/drivers/media/video/bt856.c
++++ b/drivers/media/video/bt856.c
+@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+ 
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
+index 7374c02..f20a01c 100644
+--- a/drivers/media/video/bt8xx/bttv-cards.c
++++ b/drivers/media/video/bt8xx/bttv-cards.c
+@@ -71,6 +71,8 @@ static void kodicom4400r_init(struct bttv *btv);
+ static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
+ static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
+ 
++static void geovision_muxsel(struct bttv *btv, unsigned int input);
++
+ static int terratec_active_radio_upgrade(struct bttv *btv);
+ static int tea5757_read(struct bttv *btv);
+ static int tea5757_write(struct bttv *btv, int value);
+@@ -301,6 +303,7 @@ static struct CARD {
+ 	{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
+ 	{ 0x00261822, BTTV_BOARD_TWINHAN_DST,	"DNTV Live! Mini "},
+ 	{ 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2,	"DViCO FusionHDTV 2" },
++	{ 0x763c008a, BTTV_BOARD_GEOVISION_GV600,	"GeoVision GV-600" },
+ 
+ 	{ 0, -1, NULL }
+ };
+@@ -576,6 +579,8 @@ struct tvcard bttv_tvcards[] = {
+ 		.needs_tvaudio	= 1,
+ 		.pll		= PLL_28,
+ 		.tuner_type	= UNSET,
++		.tuner_addr     = ADDR_UNSET,
++		.radio_addr     = ADDR_UNSET,
+ 	},
+ 	[BTTV_BOARD_WINVIEW_601] = {
+ 		.name		= "Leadtek WinView 601",
+@@ -2322,7 +2327,7 @@ struct tvcard bttv_tvcards[] = {
+ 		.tuner          = 0,
+ 		.svhs           = 2,
+ 		.muxsel         = { 2, 3, 1, 0 },
+-		.tuner_type     = TUNER_PHILIPS_ATSC,
++		.tuner_type     = TUNER_PHILIPS_FCV1236D,
+ 		.tuner_addr	= ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 		.has_dvb        = 1,
+@@ -2961,7 +2966,7 @@ struct tvcard bttv_tvcards[] = {
+ 	[BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
+ 		.name           = "DViCO FusionHDTV 2",
+ 		.tuner          = 0,
+-		.tuner_type     = TUNER_PHILIPS_ATSC, /* FCV1236D */
++		.tuner_type     = TUNER_PHILIPS_FCV1236D,
+ 		.tuner_addr	= ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 		.video_inputs   = 3,
+@@ -2992,6 +2997,45 @@ struct tvcard bttv_tvcards[] = {
+ 		.tuner_addr     = ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 	},
++	[BTTV_BOARD_GEOVISION_GV600] = {
++		/* emhn at usb.ve */
++		.name             = "Geovision GV-600",
++		.video_inputs     = 16,
++		.audio_inputs     = 0,
++		.tuner            = UNSET,
++		.svhs             = UNSET,
++		.gpiomask         = 0x0,
++		.muxsel           = { 2, 2, 2, 2, 2, 2, 2, 2,
++				      2, 2, 2, 2, 2, 2, 2, 2 },
++		.muxsel_hook      = geovision_muxsel,
++		.gpiomux          = { 0 },
++		.no_msp34xx       = 1,
++		.pll              = PLL_28,
++		.tuner_type       = UNSET,
++		.tuner_addr	  = ADDR_UNSET,
++		.radio_addr       = ADDR_UNSET,
++	},
++	[BTTV_BOARD_KOZUMI_KTV_01C] = {
++		/* Mauro Lacy <mauro at lacy.com.ar>
++		 * Based on MagicTV and Conceptronic CONTVFMi */
++
++		.name           = "Kozumi KTV-01C",
++		.video_inputs   = 3,
++		.audio_inputs   = 1,
++		.tuner          = 0,
++		.svhs           = 2,
++		.gpiomask       = 0x008007,
++		.muxsel         = { 2, 3, 1, 1 },
++		.gpiomux        = { 0, 1, 2, 2 }, /* CONTVFMi */
++		.gpiomute 	= 3, /* CONTVFMi */
++		.needs_tvaudio  = 0,
++		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */
++		.tuner_addr     = ADDR_UNSET,
++		.radio_addr     = ADDR_UNSET,
++		.pll            = PLL_28,
++		.has_radio      = 1,
++		.has_remote     = 1,
++	},
+ };
+ 
+ static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
+@@ -3331,6 +3375,13 @@ static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
+ 	gpio_bits( 3<<9, inmux<<9 );
+ }
+ 
++static void geovision_muxsel(struct bttv *btv, unsigned int input)
++{
++	unsigned int inmux = input % 16;
++	gpio_inout(0xf, 0xf);
++	gpio_bits(0xf, inmux);
++}
++
+ /* ----------------------------------------------------------------------- */
+ 
+ static void bttv_reset_audio(struct bttv *btv)
+diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
+index fcf8f2d..2ca3e9c 100644
+--- a/drivers/media/video/bt8xx/bttv-driver.c
++++ b/drivers/media/video/bt8xx/bttv-driver.c
+@@ -2372,7 +2372,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
+ 	if (check_btres(fh, RESOURCE_OVERLAY)) {
+ 		struct bttv_buffer *new;
+ 
+-		new = videobuf_pci_alloc(sizeof(*new));
++		new = videobuf_sg_alloc(sizeof(*new));
+ 		new->crop = btv->crop[!!fh->do_crop].rect;
+ 		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+ 		retval = bttv_switch_overlay(btv,fh,new);
+@@ -2760,7 +2760,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
+ 	mutex_lock(&fh->cap.vb_lock);
+ 	if (on) {
+ 		fh->ov.tvnorm = btv->tvnorm;
+-		new = videobuf_pci_alloc(sizeof(*new));
++		new = videobuf_sg_alloc(sizeof(*new));
+ 		new->crop = btv->crop[!!fh->do_crop].rect;
+ 		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+ 	} else {
+@@ -2834,7 +2834,7 @@ static int bttv_s_fbuf(struct file *file, void *f,
+ 		if (check_btres(fh, RESOURCE_OVERLAY)) {
+ 			struct bttv_buffer *new;
+ 
+-			new = videobuf_pci_alloc(sizeof(*new));
++			new = videobuf_sg_alloc(sizeof(*new));
+ 			new->crop = btv->crop[!!fh->do_crop].rect;
+ 			bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+ 			retval = bttv_switch_overlay(btv, fh, new);
+@@ -3117,12 +3117,18 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
+ 
+ static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+ {
++	if (unlikely(a->index))
++		return -EINVAL;
++
+ 	strcpy(a->name, "audio");
+ 	return 0;
+ }
+ 
+ static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+ {
++	if (unlikely(a->index))
++		return -EINVAL;
++
+ 	return 0;
+ }
+ 
+@@ -3184,7 +3190,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
+ 			/* need to capture a new frame */
+ 			if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
+ 				goto err;
+-			fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize);
++			fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
+ 			if (NULL == fh->cap.read_buf)
+ 				goto err;
+ 			fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
+@@ -3251,14 +3257,14 @@ static int bttv_open(struct inode *inode, struct file *file)
+ 	fh->ov.setup_ok = 0;
+ 	v4l2_prio_open(&btv->prio,&fh->prio);
+ 
+-	videobuf_queue_pci_init(&fh->cap, &bttv_video_qops,
+-			    btv->c.pci, &btv->s_lock,
++	videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
++			    &btv->c.pci->dev, &btv->s_lock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ 			    V4L2_FIELD_INTERLACED,
+ 			    sizeof(struct bttv_buffer),
+ 			    fh);
+-	videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops,
+-			    btv->c.pci, &btv->s_lock,
++	videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
++			    &btv->c.pci->dev, &btv->s_lock,
+ 			    V4L2_BUF_TYPE_VBI_CAPTURE,
+ 			    V4L2_FIELD_SEQ_TB,
+ 			    sizeof(struct bttv_buffer),
+@@ -3457,6 +3463,9 @@ static int radio_release(struct inode *inode, struct file *file)
+ 	struct bttv *btv = fh->btv;
+ 	struct rds_command cmd;
+ 
++	file->private_data = NULL;
++	kfree(fh);
++
+ 	btv->radio_user--;
+ 
+ 	bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
+@@ -3510,7 +3519,7 @@ static int radio_enum_input(struct file *file, void *priv,
+ 		return -EINVAL;
+ 
+ 	strcpy(i->name, "Radio");
+-	 i->type = V4L2_INPUT_TYPE_TUNER;
++	i->type = V4L2_INPUT_TYPE_TUNER;
+ 
+ 	return 0;
+ }
+@@ -3518,10 +3527,9 @@ static int radio_enum_input(struct file *file, void *priv,
+ static int radio_g_audio(struct file *file, void *priv,
+ 					struct v4l2_audio *a)
+ {
+-	if (a->index != 0)
++	if (unlikely(a->index))
+ 		return -EINVAL;
+ 
+-	memset(a, 0, sizeof(*a));
+ 	strcpy(a->name, "Radio");
+ 
+ 	return 0;
+@@ -3543,11 +3551,17 @@ static int radio_s_tuner(struct file *file, void *priv,
+ static int radio_s_audio(struct file *file, void *priv,
+ 					struct v4l2_audio *a)
+ {
++	if (unlikely(a->index))
++		return -EINVAL;
++
+ 	return 0;
+ }
+ 
+ static int radio_s_input(struct file *filp, void *priv, unsigned int i)
+ {
++	if (unlikely(i))
++		return -EINVAL;
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
+index fc9ecb2..a38af98 100644
+--- a/drivers/media/video/bt8xx/bttv-input.c
++++ b/drivers/media/video/bt8xx/bttv-input.c
+@@ -278,6 +278,12 @@ int bttv_input_init(struct bttv *btv)
+ 		ir->mask_keyup   = 0x004000;
+ 		ir->polling      = 50; /* ms */
+ 		break;
++	case BTTV_BOARD_KOZUMI_KTV_01C:
++		ir_codes         = ir_codes_pctv_sedna;
++		ir->mask_keycode = 0x001f00;
++		ir->mask_keyup   = 0x006000;
++		ir->polling      = 50; /* ms */
++		break;
+ 	}
+ 	if (NULL == ir_codes) {
+ 		dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
+diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
+index 75fa82c..bfdbc46 100644
+--- a/drivers/media/video/bt8xx/bttv-vbi.c
++++ b/drivers/media/video/bt8xx/bttv-vbi.c
+@@ -54,7 +54,7 @@
+ #define VBI_DEFLINES 16
+ 
+ static unsigned int vbibufs = 4;
+-static unsigned int vbi_debug = 0;
++static unsigned int vbi_debug;
+ 
+ module_param(vbibufs,   int, 0444);
+ module_param(vbi_debug, int, 0644);
+diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
+index bf4c339..f239320 100644
+--- a/drivers/media/video/bt8xx/bttv.h
++++ b/drivers/media/video/bt8xx/bttv.h
+@@ -19,6 +19,7 @@
+ #include <media/ir-common.h>
+ #include <media/ir-kbd-i2c.h>
+ #include <media/i2c-addr.h>
++#include <media/tuner.h>
+ 
+ /* ---------------------------------------------------------- */
+ /* exported by bttv-cards.c                                   */
+@@ -173,6 +174,8 @@
+ #define BTTV_BOARD_VOODOOTV_200		   0x93
+ #define BTTV_BOARD_DVICO_FUSIONHDTV_2	   0x94
+ #define BTTV_BOARD_TYPHOON_TVTUNERPCI	   0x95
++#define BTTV_BOARD_GEOVISION_GV600	   0x96
++#define BTTV_BOARD_KOZUMI_KTV_01C          0x97
+ 
+ 
+ /* more card-specific defines */
+diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
+index 1305d31..03816b7 100644
+--- a/drivers/media/video/bt8xx/bttvp.h
++++ b/drivers/media/video/bt8xx/bttvp.h
+@@ -42,7 +42,6 @@
+ 
+ #include <linux/device.h>
+ #include <media/videobuf-dma-sg.h>
+-#include <media/tuner.h>
+ #include <media/tveeprom.h>
+ #include <media/ir-common.h>
+ 
+diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
+index 0322653..b364ada 100644
+--- a/drivers/media/video/bw-qcam.c
++++ b/drivers/media/video/bw-qcam.c
+@@ -523,7 +523,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
+ 	int ret=1;
+ 	unsigned int hi, lo;
+ 	unsigned int hi2, lo2;
+-	static int state = 0;
++	static int state;
+ 
+ 	if (buffer == NULL)
+ 	{
+@@ -898,7 +898,9 @@ static const struct file_operations qcam_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl          = qcam_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.read		= qcam_read,
+ 	.llseek         = no_llseek,
+ };
+@@ -912,7 +914,7 @@ static struct video_device qcam_template=
+ 
+ #define MAX_CAMS 4
+ static struct qcam_device *qcams[MAX_CAMS];
+-static unsigned int num_cams = 0;
++static unsigned int num_cams;
+ 
+ static int init_bwqcam(struct parport *port)
+ {
+diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
+index cf1546b..fe1e67b 100644
+--- a/drivers/media/video/c-qcam.c
++++ b/drivers/media/video/c-qcam.c
+@@ -36,6 +36,7 @@
+ #include <linux/videodev.h>
+ #include <media/v4l2-common.h>
+ #include <linux/mutex.h>
++#include <linux/jiffies.h>
+ 
+ #include <asm/uaccess.h>
+ 
+@@ -69,7 +70,7 @@ struct qcam_device {
+ 
+ static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
+ static int probe = 2;
+-static int force_rgb = 0;
++static int force_rgb;
+ static int video_nr = -1;
+ 
+ static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
+@@ -95,7 +96,8 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
+ 	unsigned long oldjiffies = jiffies;
+ 	unsigned int i;
+ 
+-	for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
++	for (oldjiffies = jiffies;
++	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
+ 		if (qcam_ready1(qcam) == value)
+ 			return 0;
+ 
+@@ -120,7 +122,8 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
+ 	unsigned long oldjiffies = jiffies;
+ 	unsigned int i;
+ 
+-	for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
++	for (oldjiffies = jiffies;
++	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
+ 		if (qcam_ready2(qcam) == value)
+ 			return 0;
+ 
+@@ -689,7 +692,9 @@ static const struct file_operations qcam_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl          = qcam_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.read		= qcam_read,
+ 	.llseek         = no_llseek,
+ };
+@@ -741,7 +746,7 @@ static struct qcam_device *qcam_init(struct parport *port)
+ }
+ 
+ static struct qcam_device *qcams[MAX_CAMS];
+-static unsigned int num_cams = 0;
++static unsigned int num_cams;
+ 
+ static int init_cqcam(struct parport *port)
+ {
+diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
+index 7ae499c..5195b1f 100644
+--- a/drivers/media/video/cafe_ccic.c
++++ b/drivers/media/video/cafe_ccic.c
+@@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("Video");
+  */
+ 
+ #define MAX_DMA_BUFS 3
+-static int alloc_bufs_at_read = 0;
++static int alloc_bufs_at_read;
+ module_param(alloc_bufs_at_read, bool, 0444);
+ MODULE_PARM_DESC(alloc_bufs_at_read,
+ 		"Non-zero value causes DMA buffers to be allocated when the "
+@@ -99,7 +99,7 @@ MODULE_PARM_DESC(max_buffers,
+ 		"will be allowed to allocate.  These buffers are big and live "
+ 		"in vmalloc space.");
+ 
+-static int flip = 0;
++static int flip;
+ module_param(flip, bool, 0444);
+ MODULE_PARM_DESC(flip,
+ 		"If set, the sensor will be instructed to flip the image "
+diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
+index 7c630f5..2a81376 100644
+--- a/drivers/media/video/cpia.c
++++ b/drivers/media/video/cpia.c
+@@ -3792,7 +3792,9 @@ static const struct file_operations cpia_fops = {
+ 	.read		= cpia_read,
+ 	.mmap		= cpia_mmap,
+ 	.ioctl          = cpia_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h
+index 78392fb..5096058 100644
+--- a/drivers/media/video/cpia.h
++++ b/drivers/media/video/cpia.h
+@@ -412,11 +412,11 @@ void cpia_unregister_camera(struct cam_data *cam);
+ /* ErrorCode */
+ #define ERROR_FLICKER_BELOW_MIN_EXP     0x01 /*flicker exposure got below minimum exposure */
+ #define ALOG(fmt,args...) printk(fmt, ##args)
+-#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __FUNCTION__ , __LINE__ , ##args)
++#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args)
+ 
+ #ifdef _CPIA_DEBUG_
+ #define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
+-#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __FUNCTION__, __LINE__ , ##args)
++#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
+ #else
+ #define DBG(fmn,args...) do {} while(0)
+ #endif
+diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c
+index a76bd78..c8b9fdb 100644
+--- a/drivers/media/video/cpia2/cpia2_core.c
++++ b/drivers/media/video/cpia2/cpia2_core.c
+@@ -34,7 +34,7 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ 
+-//#define _CPIA2_DEBUG_
++/* #define _CPIA2_DEBUG_ */
+ 
+ #include "cpia2patch.h"
+ 
+@@ -48,7 +48,7 @@ static const char *block_name[] = {
+ };
+ #endif
+ 
+-static unsigned int debugs_on = 0;//DEBUG_REG;
++static unsigned int debugs_on;	/* default 0 - DEBUG_REG */
+ 
+ 
+ /******************************************************************************
+@@ -570,7 +570,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
+ 			    block_name[block_index]);
+ 		break;
+ 	default:
+-		LOG("%s: invalid request mode\n",__FUNCTION__);
++		LOG("%s: invalid request mode\n",__func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -952,7 +952,7 @@ static int set_default_user_mode(struct camera_data *cam)
+ 			frame_rate = CPIA2_VP_FRAMERATE_30;
+ 		break;
+ 	default:
+-		LOG("%s: Invalid sensor flag value 0x%0X\n",__FUNCTION__,
++		LOG("%s: Invalid sensor flag value 0x%0X\n",__func__,
+ 		    cam->params.version.sensor_flags);
+ 		return -EINVAL;
+ 	}
+@@ -2356,12 +2356,12 @@ long cpia2_read(struct camera_data *cam,
+ 	}
+ 
+ 	if (!buf) {
+-		ERR("%s: buffer NULL\n",__FUNCTION__);
++		ERR("%s: buffer NULL\n",__func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (!cam) {
+-		ERR("%s: Internal error, camera_data NULL!\n",__FUNCTION__);
++		ERR("%s: Internal error, camera_data NULL!\n",__func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -2370,7 +2370,7 @@ long cpia2_read(struct camera_data *cam,
+ 		return -ERESTARTSYS;
+ 
+ 	if (!cam->present) {
+-		LOG("%s: camera removed\n",__FUNCTION__);
++		LOG("%s: camera removed\n",__func__);
+ 		mutex_unlock(&cam->busy_lock);
+ 		return 0;	/* EOF */
+ 	}
+@@ -2434,7 +2434,7 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
+ 	unsigned int status=0;
+ 
+ 	if(!cam) {
+-		ERR("%s: Internal error, camera_data not found!\n",__FUNCTION__);
++		ERR("%s: Internal error, camera_data not found!\n",__func__);
+ 		return POLLERR;
+ 	}
+ 
+diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
+index d8e9298..a457474 100644
+--- a/drivers/media/video/cpia2/cpia2_usb.c
++++ b/drivers/media/video/cpia2/cpia2_usb.c
+@@ -84,7 +84,7 @@ static struct usb_driver cpia2_driver = {
+  *****************************************************************************/
+ static void process_frame(struct camera_data *cam)
+ {
+-	static int frame_count = 0;
++	static int frame_count;
+ 
+ 	unsigned char *inbuff = cam->workbuff->data;
+ 
+diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
+index e378abe..7ce2789 100644
+--- a/drivers/media/video/cpia2/cpia2_v4l.c
++++ b/drivers/media/video/cpia2/cpia2_v4l.c
+@@ -1927,7 +1927,9 @@ static const struct file_operations fops_template = {
+ 	.poll		= cpia2_v4l_poll,
+ 	.ioctl		= cpia2_ioctl,
+ 	.llseek		= no_llseek,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.mmap		= cpia2_mmap,
+ };
+ 
+diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
+index 9da4726..ef1f893 100644
+--- a/drivers/media/video/cpia_usb.c
++++ b/drivers/media/video/cpia_usb.c
+@@ -170,7 +170,7 @@ static void cpia_usb_complete(struct urb *urb)
+ 	/* resubmit */
+ 	urb->dev = ucpia->dev;
+ 	if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
+-		printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __FUNCTION__,  i);
++		printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__,  i);
+ }
+ 
+ static int cpia_usb_open(void *privdata)
+diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
+index 1fd326f..ca5fbce 100644
+--- a/drivers/media/video/cx23885/Kconfig
++++ b/drivers/media/video/cx23885/Kconfig
+@@ -8,6 +8,7 @@ config VIDEO_CX23885
+ 	select VIDEO_TVEEPROM
+ 	select VIDEO_IR
+ 	select VIDEOBUF_DVB
++	select VIDEO_CX25840
+ 	select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE
+ 	select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+ 	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+@@ -16,6 +17,7 @@ config VIDEO_CX23885
+ 	select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+ 	select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
+ 	select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
++	select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
+ 	---help---
+ 	  This is a video4linux driver for Conexant 23885 based
+ 	  TV cards.
+diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
+index 32c90be..d7b0721 100644
+--- a/drivers/media/video/cx23885/Makefile
++++ b/drivers/media/video/cx23885/Makefile
+@@ -1,4 +1,4 @@
+-cx23885-objs	:= cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o
++cx23885-objs	:= cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o
+ 
+ obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
+ 
+diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
+new file mode 100644
+index 0000000..acdd3b6
+--- /dev/null
++++ b/drivers/media/video/cx23885/cx23885-417.c
+@@ -0,0 +1,1764 @@
++/*
++ *
++ *  Support for a cx23417 mpeg encoder via cx23885 host port.
++ *
++ *    (c) 2004 Jelle Foks <jelle at foks.8m.com>
++ *    (c) 2004 Gerd Knorr <kraxel at bytesex.org>
++ *    (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *      - CX23885/7/8 support
++ *
++ *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/firmware.h>
++#include <media/v4l2-common.h>
++#include <media/cx2341x.h>
++
++#include "cx23885.h"
++#include "media/cx2341x.h"
++
++#define CX23885_FIRM_IMAGE_SIZE 376836
++#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
++
++static unsigned int mpegbufs = 32;
++module_param(mpegbufs, int, 0644);
++MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
++static unsigned int mpeglines = 32;
++module_param(mpeglines, int, 0644);
++MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
++static unsigned int mpeglinesize = 512;
++module_param(mpeglinesize, int, 0644);
++MODULE_PARM_DESC(mpeglinesize,
++	"number of bytes in each line of an MPEG buffer, range 512-1024");
++
++static unsigned int v4l_debug;
++module_param(v4l_debug, int, 0644);
++MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
++
++#define dprintk(level, fmt, arg...)\
++	do { if (v4l_debug >= level) \
++		printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\
++	} while (0)
++
++static struct cx23885_tvnorm cx23885_tvnorms[] = {
++	{
++		.name      = "NTSC-M",
++		.id        = V4L2_STD_NTSC_M,
++	}, {
++		.name      = "NTSC-JP",
++		.id        = V4L2_STD_NTSC_M_JP,
++	}, {
++		.name      = "PAL-BG",
++		.id        = V4L2_STD_PAL_BG,
++	}, {
++		.name      = "PAL-DK",
++		.id        = V4L2_STD_PAL_DK,
++	}, {
++		.name      = "PAL-I",
++		.id        = V4L2_STD_PAL_I,
++	}, {
++		.name      = "PAL-M",
++		.id        = V4L2_STD_PAL_M,
++	}, {
++		.name      = "PAL-N",
++		.id        = V4L2_STD_PAL_N,
++	}, {
++		.name      = "PAL-Nc",
++		.id        = V4L2_STD_PAL_Nc,
++	}, {
++		.name      = "PAL-60",
++		.id        = V4L2_STD_PAL_60,
++	}, {
++		.name      = "SECAM-L",
++		.id        = V4L2_STD_SECAM_L,
++	}, {
++		.name      = "SECAM-DK",
++		.id        = V4L2_STD_SECAM_DK,
++	}
++};
++
++/* ------------------------------------------------------------------ */
++enum cx23885_capture_type {
++	CX23885_MPEG_CAPTURE,
++	CX23885_RAW_CAPTURE,
++	CX23885_RAW_PASSTHRU_CAPTURE
++};
++enum cx23885_capture_bits {
++	CX23885_RAW_BITS_NONE             = 0x00,
++	CX23885_RAW_BITS_YUV_CAPTURE      = 0x01,
++	CX23885_RAW_BITS_PCM_CAPTURE      = 0x02,
++	CX23885_RAW_BITS_VBI_CAPTURE      = 0x04,
++	CX23885_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
++	CX23885_RAW_BITS_TO_HOST_CAPTURE  = 0x10
++};
++enum cx23885_capture_end {
++	CX23885_END_AT_GOP, /* stop at the end of gop, generate irq */
++	CX23885_END_NOW, /* stop immediately, no irq */
++};
++enum cx23885_framerate {
++	CX23885_FRAMERATE_NTSC_30, /* NTSC: 30fps */
++	CX23885_FRAMERATE_PAL_25   /* PAL: 25fps */
++};
++enum cx23885_stream_port {
++	CX23885_OUTPUT_PORT_MEMORY,
++	CX23885_OUTPUT_PORT_STREAMING,
++	CX23885_OUTPUT_PORT_SERIAL
++};
++enum cx23885_data_xfer_status {
++	CX23885_MORE_BUFFERS_FOLLOW,
++	CX23885_LAST_BUFFER,
++};
++enum cx23885_picture_mask {
++	CX23885_PICTURE_MASK_NONE,
++	CX23885_PICTURE_MASK_I_FRAMES,
++	CX23885_PICTURE_MASK_I_P_FRAMES = 0x3,
++	CX23885_PICTURE_MASK_ALL_FRAMES = 0x7,
++};
++enum cx23885_vbi_mode_bits {
++	CX23885_VBI_BITS_SLICED,
++	CX23885_VBI_BITS_RAW,
++};
++enum cx23885_vbi_insertion_bits {
++	CX23885_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
++	CX23885_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
++	CX23885_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
++	CX23885_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
++	CX23885_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
++};
++enum cx23885_dma_unit {
++	CX23885_DMA_BYTES,
++	CX23885_DMA_FRAMES,
++};
++enum cx23885_dma_transfer_status_bits {
++	CX23885_DMA_TRANSFER_BITS_DONE = 0x01,
++	CX23885_DMA_TRANSFER_BITS_ERROR = 0x04,
++	CX23885_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
++};
++enum cx23885_pause {
++	CX23885_PAUSE_ENCODING,
++	CX23885_RESUME_ENCODING,
++};
++enum cx23885_copyright {
++	CX23885_COPYRIGHT_OFF,
++	CX23885_COPYRIGHT_ON,
++};
++enum cx23885_notification_type {
++	CX23885_NOTIFICATION_REFRESH,
++};
++enum cx23885_notification_status {
++	CX23885_NOTIFICATION_OFF,
++	CX23885_NOTIFICATION_ON,
++};
++enum cx23885_notification_mailbox {
++	CX23885_NOTIFICATION_NO_MAILBOX = -1,
++};
++enum cx23885_field1_lines {
++	CX23885_FIELD1_SAA7114 = 0x00EF, /* 239 */
++	CX23885_FIELD1_SAA7115 = 0x00F0, /* 240 */
++	CX23885_FIELD1_MICRONAS = 0x0105, /* 261 */
++};
++enum cx23885_field2_lines {
++	CX23885_FIELD2_SAA7114 = 0x00EF, /* 239 */
++	CX23885_FIELD2_SAA7115 = 0x00F0, /* 240 */
++	CX23885_FIELD2_MICRONAS = 0x0106, /* 262 */
++};
++enum cx23885_custom_data_type {
++	CX23885_CUSTOM_EXTENSION_USR_DATA,
++	CX23885_CUSTOM_PRIVATE_PACKET,
++};
++enum cx23885_mute {
++	CX23885_UNMUTE,
++	CX23885_MUTE,
++};
++enum cx23885_mute_video_mask {
++	CX23885_MUTE_VIDEO_V_MASK = 0x0000FF00,
++	CX23885_MUTE_VIDEO_U_MASK = 0x00FF0000,
++	CX23885_MUTE_VIDEO_Y_MASK = 0xFF000000,
++};
++enum cx23885_mute_video_shift {
++	CX23885_MUTE_VIDEO_V_SHIFT = 8,
++	CX23885_MUTE_VIDEO_U_SHIFT = 16,
++	CX23885_MUTE_VIDEO_Y_SHIFT = 24,
++};
++
++/* defines below are from ivtv-driver.h */
++#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
++
++/* Firmware API commands */
++#define IVTV_API_STD_TIMEOUT 500
++
++/* Registers */
++/* IVTV_REG_OFFSET */
++#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
++#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
++#define IVTV_REG_SPU (0x9050)
++#define IVTV_REG_HW_BLOCKS (0x9054)
++#define IVTV_REG_VPU (0x9058)
++#define IVTV_REG_APU (0xA064)
++
++/**** Bit definitions for MC417_RWD and MC417_OEN registers  ***
++  bits 31-16
+++-----------+
++| Reserved  |
+++-----------+
++  bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 8
+++-------+-------+-------+-------+-------+-------+-------+-------+
++| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
+++-------+-------+-------+-------+-------+-------+-------+-------+
++ bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
+++-------+-------+-------+-------+-------+-------+-------+-------+
++|MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
+++-------+-------+-------+-------+-------+-------+-------+-------+
++***/
++#define MC417_MIWR	0x8000
++#define MC417_MIRD	0x4000
++#define MC417_MICS	0x2000
++#define MC417_MIRDY	0x1000
++#define MC417_MIADDR	0x0F00
++#define MC417_MIDATA	0x00FF
++
++/* MIADDR* nibble definitions */
++#define  MCI_MEMORY_DATA_BYTE0          0x000
++#define  MCI_MEMORY_DATA_BYTE1          0x100
++#define  MCI_MEMORY_DATA_BYTE2          0x200
++#define  MCI_MEMORY_DATA_BYTE3          0x300
++#define  MCI_MEMORY_ADDRESS_BYTE2       0x400
++#define  MCI_MEMORY_ADDRESS_BYTE1       0x500
++#define  MCI_MEMORY_ADDRESS_BYTE0       0x600
++#define  MCI_REGISTER_DATA_BYTE0        0x800
++#define  MCI_REGISTER_DATA_BYTE1        0x900
++#define  MCI_REGISTER_DATA_BYTE2        0xA00
++#define  MCI_REGISTER_DATA_BYTE3        0xB00
++#define  MCI_REGISTER_ADDRESS_BYTE0     0xC00
++#define  MCI_REGISTER_ADDRESS_BYTE1     0xD00
++#define  MCI_REGISTER_MODE              0xE00
++
++/* Read and write modes */
++#define  MCI_MODE_REGISTER_READ         0
++#define  MCI_MODE_REGISTER_WRITE        1
++#define  MCI_MODE_MEMORY_READ           0
++#define  MCI_MODE_MEMORY_WRITE          0x40
++
++/*** Bit definitions for MC417_CTL register ****
++ bits 31-6   bits 5-4   bit 3    bits 2-1       Bit 0
+++--------+-------------+--------+--------------+------------+
++|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
+++--------+-------------+--------+--------------+------------+
++***/
++#define MC417_SPD_CTL(x)	(((x) << 4) & 0x00000030)
++#define MC417_GPIO_SEL(x)	(((x) << 1) & 0x00000006)
++#define MC417_UART_GPIO_EN	0x00000001
++
++/* Values for speed control */
++#define MC417_SPD_CTL_SLOW	0x1
++#define MC417_SPD_CTL_MEDIUM	0x0
++#define MC417_SPD_CTL_FAST	0x3     /* b'1x, but we use b'11 */
++
++/* Values for GPIO select */
++#define MC417_GPIO_SEL_GPIO3	0x3
++#define MC417_GPIO_SEL_GPIO2	0x2
++#define MC417_GPIO_SEL_GPIO1	0x1
++#define MC417_GPIO_SEL_GPIO0	0x0
++
++void cx23885_mc417_init(struct cx23885_dev *dev)
++{
++	u32 regval;
++
++	dprintk(2, "%s()\n", __func__);
++
++	/* Configure MC417_CTL register to defaults. */
++	regval = MC417_SPD_CTL(MC417_SPD_CTL_FAST)	|
++		 MC417_GPIO_SEL(MC417_GPIO_SEL_GPIO3)	|
++		 MC417_UART_GPIO_EN;
++	cx_write(MC417_CTL, regval);
++
++	/* Configure MC417_OEN to defaults. */
++	regval = MC417_MIRDY;
++	cx_write(MC417_OEN, regval);
++
++	/* Configure MC417_RWD to defaults. */
++	regval = MC417_MIWR | MC417_MIRD | MC417_MICS;
++	cx_write(MC417_RWD, regval);
++}
++
++static int mc417_wait_ready(struct cx23885_dev *dev)
++{
++	u32 mi_ready;
++	unsigned long timeout = jiffies + msecs_to_jiffies(1);
++
++	for (;;) {
++		mi_ready = cx_read(MC417_RWD) & MC417_MIRDY;
++		if (mi_ready != 0)
++			return 0;
++		if (time_after(jiffies, timeout))
++			return -1;
++		udelay(1);
++	}
++}
++
++static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
++{
++	u32 regval;
++
++	/* Enable MC417 GPIO outputs except for MC417_MIRDY,
++	 * which is an input.
++	 */
++	cx_write(MC417_OEN, MC417_MIRDY);
++
++	/* Write data byte 0 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0 |
++		(value & 0x000000FF);
++	cx_write(MC417_RWD, regval);
++
++	/* Transition CS/WR to effect write transaction across bus. */
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write data byte 1 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1 |
++		((value >> 8) & 0x000000FF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write data byte 2 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2 |
++		((value >> 16) & 0x000000FF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write data byte 3 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3 |
++		((value >> 24) & 0x000000FF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write address byte 0 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
++		(address & 0xFF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write address byte 1 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
++		((address >> 8) & 0xFF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Indicate that this is a write. */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
++		MCI_MODE_REGISTER_WRITE;
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Wait for the trans to complete (MC417_MIRDY asserted). */
++	return mc417_wait_ready(dev);
++}
++
++static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
++{
++	int retval;
++	u32 regval;
++	u32 tempval;
++	u32 dataval;
++
++	/* Enable MC417 GPIO outputs except for MC417_MIRDY,
++	 * which is an input.
++	 */
++	cx_write(MC417_OEN, MC417_MIRDY);
++
++	/* Write address byte 0 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
++		((address & 0x00FF));
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write address byte 1 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
++		((address >> 8) & 0xFF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Indicate that this is a register read. */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
++		MCI_MODE_REGISTER_READ;
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Wait for the trans to complete (MC417_MIRDY asserted). */
++	retval = mc417_wait_ready(dev);
++
++	/* switch the DAT0-7 GPIO[10:3] to input mode */
++	cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
++
++	/* Read data byte 0 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
++	cx_write(MC417_RWD, regval);
++
++	/* Transition RD to effect read transaction across bus.
++	 * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
++	 * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
++	 * input only...)
++	 */
++	regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
++	cx_write(MC417_RWD, regval);
++
++	/* Collect byte */
++	tempval = cx_read(MC417_RWD);
++	dataval = tempval & 0x000000FF;
++
++	/* Bring CS and RD high. */
++	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++	cx_write(MC417_RWD, regval);
++
++	/* Read data byte 1 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
++	cx_write(MC417_RWD, regval);
++	regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
++	cx_write(MC417_RWD, regval);
++	tempval = cx_read(MC417_RWD);
++	dataval |= ((tempval & 0x000000FF) << 8);
++	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++	cx_write(MC417_RWD, regval);
++
++	/* Read data byte 2 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
++	cx_write(MC417_RWD, regval);
++	regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
++	cx_write(MC417_RWD, regval);
++	tempval = cx_read(MC417_RWD);
++	dataval |= ((tempval & 0x000000FF) << 16);
++	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++	cx_write(MC417_RWD, regval);
++
++	/* Read data byte 3 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
++	cx_write(MC417_RWD, regval);
++	regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
++	cx_write(MC417_RWD, regval);
++	tempval = cx_read(MC417_RWD);
++	dataval |= ((tempval & 0x000000FF) << 24);
++	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++	cx_write(MC417_RWD, regval);
++
++	*value  = dataval;
++
++	return retval;
++}
++
++int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value)
++{
++	u32 regval;
++
++	/* Enable MC417 GPIO outputs except for MC417_MIRDY,
++	 * which is an input.
++	 */
++	cx_write(MC417_OEN, MC417_MIRDY);
++
++	/* Write data byte 0 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 |
++		(value & 0x000000FF);
++	cx_write(MC417_RWD, regval);
++
++	/* Transition CS/WR to effect write transaction across bus. */
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write data byte 1 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 |
++		((value >> 8) & 0x000000FF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write data byte 2 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 |
++		((value >> 16) & 0x000000FF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write data byte 3 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 |
++		((value >> 24) & 0x000000FF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write address byte 2 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
++		MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write address byte 1 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
++		((address >> 8) & 0xFF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write address byte 0 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
++		(address & 0xFF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Wait for the trans to complete (MC417_MIRDY asserted). */
++	return mc417_wait_ready(dev);
++}
++
++int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)
++{
++	int retval;
++	u32 regval;
++	u32 tempval;
++	u32 dataval;
++
++	/* Enable MC417 GPIO outputs except for MC417_MIRDY,
++	 * which is an input.
++	 */
++	cx_write(MC417_OEN, MC417_MIRDY);
++
++	/* Write address byte 2 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
++		MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write address byte 1 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
++		((address >> 8) & 0xFF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Write address byte 0 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
++		(address & 0xFF);
++	cx_write(MC417_RWD, regval);
++	regval |= MC417_MICS | MC417_MIWR;
++	cx_write(MC417_RWD, regval);
++
++	/* Wait for the trans to complete (MC417_MIRDY asserted). */
++	retval = mc417_wait_ready(dev);
++
++	/* switch the DAT0-7 GPIO[10:3] to input mode */
++	cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
++
++	/* Read data byte 3 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
++	cx_write(MC417_RWD, regval);
++
++	/* Transition RD to effect read transaction across bus. */
++	regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
++	cx_write(MC417_RWD, regval);
++
++	/* Collect byte */
++	tempval = cx_read(MC417_RWD);
++	dataval = ((tempval & 0x000000FF) << 24);
++
++	/* Bring CS and RD high. */
++	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++	cx_write(MC417_RWD, regval);
++
++	/* Read data byte 2 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
++	cx_write(MC417_RWD, regval);
++	regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
++	cx_write(MC417_RWD, regval);
++	tempval = cx_read(MC417_RWD);
++	dataval |= ((tempval & 0x000000FF) << 16);
++	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++	cx_write(MC417_RWD, regval);
++
++	/* Read data byte 1 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
++	cx_write(MC417_RWD, regval);
++	regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
++	cx_write(MC417_RWD, regval);
++	tempval = cx_read(MC417_RWD);
++	dataval |= ((tempval & 0x000000FF) << 8);
++	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++	cx_write(MC417_RWD, regval);
++
++	/* Read data byte 0 */
++	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
++	cx_write(MC417_RWD, regval);
++	regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
++	cx_write(MC417_RWD, regval);
++	tempval = cx_read(MC417_RWD);
++	dataval |= (tempval & 0x000000FF);
++	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++	cx_write(MC417_RWD, regval);
++
++	*value  = dataval;
++
++	return retval;
++}
++
++/* ------------------------------------------------------------------ */
++
++/* MPEG encoder API */
++char *cmd_to_str(int cmd)
++{
++	switch (cmd) {
++	case CX2341X_ENC_PING_FW:
++		return  "PING_FW";
++	case CX2341X_ENC_START_CAPTURE:
++		return  "START_CAPTURE";
++	case CX2341X_ENC_STOP_CAPTURE:
++		return  "STOP_CAPTURE";
++	case CX2341X_ENC_SET_AUDIO_ID:
++		return  "SET_AUDIO_ID";
++	case CX2341X_ENC_SET_VIDEO_ID:
++		return  "SET_VIDEO_ID";
++	case CX2341X_ENC_SET_PCR_ID:
++		return  "SET_PCR_PID";
++	case CX2341X_ENC_SET_FRAME_RATE:
++		return  "SET_FRAME_RATE";
++	case CX2341X_ENC_SET_FRAME_SIZE:
++		return  "SET_FRAME_SIZE";
++	case CX2341X_ENC_SET_BIT_RATE:
++		return  "SET_BIT_RATE";
++	case CX2341X_ENC_SET_GOP_PROPERTIES:
++		return  "SET_GOP_PROPERTIES";
++	case CX2341X_ENC_SET_ASPECT_RATIO:
++		return  "SET_ASPECT_RATIO";
++	case CX2341X_ENC_SET_DNR_FILTER_MODE:
++		return  "SET_DNR_FILTER_PROPS";
++	case CX2341X_ENC_SET_DNR_FILTER_PROPS:
++		return  "SET_DNR_FILTER_PROPS";
++	case CX2341X_ENC_SET_CORING_LEVELS:
++		return  "SET_CORING_LEVELS";
++	case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
++		return  "SET_SPATIAL_FILTER_TYPE";
++	case CX2341X_ENC_SET_VBI_LINE:
++		return  "SET_VBI_LINE";
++	case CX2341X_ENC_SET_STREAM_TYPE:
++		return  "SET_STREAM_TYPE";
++	case CX2341X_ENC_SET_OUTPUT_PORT:
++		return  "SET_OUTPUT_PORT";
++	case CX2341X_ENC_SET_AUDIO_PROPERTIES:
++		return  "SET_AUDIO_PROPERTIES";
++	case CX2341X_ENC_HALT_FW:
++		return  "HALT_FW";
++	case CX2341X_ENC_GET_VERSION:
++		return  "GET_VERSION";
++	case CX2341X_ENC_SET_GOP_CLOSURE:
++		return  "SET_GOP_CLOSURE";
++	case CX2341X_ENC_GET_SEQ_END:
++		return  "GET_SEQ_END";
++	case CX2341X_ENC_SET_PGM_INDEX_INFO:
++		return  "SET_PGM_INDEX_INFO";
++	case CX2341X_ENC_SET_VBI_CONFIG:
++		return  "SET_VBI_CONFIG";
++	case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
++		return  "SET_DMA_BLOCK_SIZE";
++	case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
++		return  "GET_PREV_DMA_INFO_MB_10";
++	case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
++		return  "GET_PREV_DMA_INFO_MB_9";
++	case CX2341X_ENC_SCHED_DMA_TO_HOST:
++		return  "SCHED_DMA_TO_HOST";
++	case CX2341X_ENC_INITIALIZE_INPUT:
++		return  "INITIALIZE_INPUT";
++	case CX2341X_ENC_SET_FRAME_DROP_RATE:
++		return  "SET_FRAME_DROP_RATE";
++	case CX2341X_ENC_PAUSE_ENCODER:
++		return  "PAUSE_ENCODER";
++	case CX2341X_ENC_REFRESH_INPUT:
++		return  "REFRESH_INPUT";
++	case CX2341X_ENC_SET_COPYRIGHT:
++		return  "SET_COPYRIGHT";
++	case CX2341X_ENC_SET_EVENT_NOTIFICATION:
++		return  "SET_EVENT_NOTIFICATION";
++	case CX2341X_ENC_SET_NUM_VSYNC_LINES:
++		return  "SET_NUM_VSYNC_LINES";
++	case CX2341X_ENC_SET_PLACEHOLDER:
++		return  "SET_PLACEHOLDER";
++	case CX2341X_ENC_MUTE_VIDEO:
++		return  "MUTE_VIDEO";
++	case CX2341X_ENC_MUTE_AUDIO:
++		return  "MUTE_AUDIO";
++	case CX2341X_ENC_MISC:
++		return  "MISC";
++	default:
++		return "UNKNOWN";
++	}
++}
++
++static int cx23885_mbox_func(void *priv,
++			     u32 command,
++			     int in,
++			     int out,
++			     u32 data[CX2341X_MBOX_MAX_DATA])
++{
++	struct cx23885_dev *dev = priv;
++	unsigned long timeout;
++	u32 value, flag, retval = 0;
++	int i;
++
++	dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
++		cmd_to_str(command));
++
++	/* this may not be 100% safe if we can't read any memory location
++	   without side effects */
++	mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
++	if (value != 0x12345678) {
++		printk(KERN_ERR
++			"Firmware and/or mailbox pointer not initialized "
++			"or corrupted, signature = 0x%x, cmd = %s\n", value,
++			cmd_to_str(command));
++		return -1;
++	}
++
++	/* This read looks at 32 bits, but flag is only 8 bits.
++	 * Seems we also bail if CMD or TIMEOUT bytes are set???
++	 */
++	mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
++	if (flag) {
++		printk(KERN_ERR "ERROR: Mailbox appears to be in use "
++			"(%x), cmd = %s\n", flag, cmd_to_str(command));
++		return -1;
++	}
++
++	flag |= 1; /* tell 'em we're working on it */
++	mc417_memory_write(dev, dev->cx23417_mailbox, flag);
++
++	/* write command + args + fill remaining with zeros */
++	/* command code */
++	mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
++	mc417_memory_write(dev, dev->cx23417_mailbox + 3,
++		IVTV_API_STD_TIMEOUT); /* timeout */
++	for (i = 0; i < in; i++) {
++		mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
++		dprintk(3, "API Input %d = %d\n", i, data[i]);
++	}
++	for (; i < CX2341X_MBOX_MAX_DATA; i++)
++		mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
++
++	flag |= 3; /* tell 'em we're done writing */
++	mc417_memory_write(dev, dev->cx23417_mailbox, flag);
++
++	/* wait for firmware to handle the API command */
++	timeout = jiffies + msecs_to_jiffies(10);
++	for (;;) {
++		mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
++		if (0 != (flag & 4))
++			break;
++		if (time_after(jiffies, timeout)) {
++			printk(KERN_ERR "ERROR: API Mailbox timeout\n");
++			return -1;
++		}
++		udelay(10);
++	}
++
++	/* read output values */
++	for (i = 0; i < out; i++) {
++		mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
++		dprintk(3, "API Output %d = %d\n", i, data[i]);
++	}
++
++	mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
++	dprintk(3, "API result = %d\n", retval);
++
++	flag = 0;
++	mc417_memory_write(dev, dev->cx23417_mailbox, flag);
++
++	return retval;
++}
++
++/* We don't need to call the API often, so using just one
++ * mailbox will probably suffice
++ */
++static int cx23885_api_cmd(struct cx23885_dev *dev,
++			   u32 command,
++			   u32 inputcnt,
++			   u32 outputcnt,
++			   ...)
++{
++	u32 data[CX2341X_MBOX_MAX_DATA];
++	va_list vargs;
++	int i, err;
++
++	dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
++
++	va_start(vargs, outputcnt);
++	for (i = 0; i < inputcnt; i++)
++		data[i] = va_arg(vargs, int);
++
++	err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data);
++	for (i = 0; i < outputcnt; i++) {
++		int *vptr = va_arg(vargs, int *);
++		*vptr = data[i];
++	}
++	va_end(vargs);
++
++	return err;
++}
++
++static int cx23885_find_mailbox(struct cx23885_dev *dev)
++{
++	u32 signature[4] = {
++		0x12345678, 0x34567812, 0x56781234, 0x78123456
++	};
++	int signaturecnt = 0;
++	u32 value;
++	int i;
++
++	dprintk(2, "%s()\n", __func__);
++
++	for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) {
++		mc417_memory_read(dev, i, &value);
++		if (value == signature[signaturecnt])
++			signaturecnt++;
++		else
++			signaturecnt = 0;
++		if (4 == signaturecnt) {
++			dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
++			return i+1;
++		}
++	}
++	printk(KERN_ERR "Mailbox signature values not found!\n");
++	return -1;
++}
++
++static int cx23885_load_firmware(struct cx23885_dev *dev)
++{
++	static const unsigned char magic[8] = {
++		0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
++	};
++	const struct firmware *firmware;
++	int i, retval = 0;
++	u32 value = 0;
++	u32 gpio_output = 0;
++	u32 checksum = 0;
++	u32 *dataptr;
++
++	dprintk(2, "%s()\n", __func__);
++
++	/* Save GPIO settings before reset of APU */
++	retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
++	retval |= mc417_memory_read(dev, 0x900C, &value);
++
++	retval  = mc417_register_write(dev,
++		IVTV_REG_VPU, 0xFFFFFFED);
++	retval |= mc417_register_write(dev,
++		IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
++	retval |= mc417_register_write(dev,
++		IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
++	retval |= mc417_register_write(dev,
++		IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
++	retval |= mc417_register_write(dev,
++		IVTV_REG_APU, 0);
++
++	if (retval != 0) {
++		printk(KERN_ERR "%s: Error with mc417_register_write\n",
++			__func__);
++		return -1;
++	}
++
++	retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,
++				  &dev->pci->dev);
++
++	if (retval != 0) {
++		printk(KERN_ERR
++			"ERROR: Hotplug firmware request failed (%s).\n",
++			CX2341X_FIRM_ENC_FILENAME);
++		printk(KERN_ERR "Please fix your hotplug setup, the board will "
++			"not work without firmware loaded!\n");
++		return -1;
++	}
++
++	if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
++		printk(KERN_ERR "ERROR: Firmware size mismatch "
++			"(have %zd, expected %d)\n",
++			firmware->size, CX23885_FIRM_IMAGE_SIZE);
++		release_firmware(firmware);
++		return -1;
++	}
++
++	if (0 != memcmp(firmware->data, magic, 8)) {
++		printk(KERN_ERR
++			"ERROR: Firmware magic mismatch, wrong file?\n");
++		release_firmware(firmware);
++		return -1;
++	}
++
++	/* transfer to the chip */
++	dprintk(2, "Loading firmware ...\n");
++	dataptr = (u32 *)firmware->data;
++	for (i = 0; i < (firmware->size >> 2); i++) {
++		value = *dataptr;
++		checksum += ~value;
++		if (mc417_memory_write(dev, i, value) != 0) {
++			printk(KERN_ERR "ERROR: Loading firmware failed!\n");
++			release_firmware(firmware);
++			return -1;
++		}
++		dataptr++;
++	}
++
++	/* read back to verify with the checksum */
++	dprintk(1, "Verifying firmware ...\n");
++	for (i--; i >= 0; i--) {
++		if (mc417_memory_read(dev, i, &value) != 0) {
++			printk(KERN_ERR "ERROR: Reading firmware failed!\n");
++			release_firmware(firmware);
++			return -1;
++		}
++		checksum -= ~value;
++	}
++	if (checksum) {
++		printk(KERN_ERR
++			"ERROR: Firmware load failed (checksum mismatch).\n");
++		release_firmware(firmware);
++		return -1;
++	}
++	release_firmware(firmware);
++	dprintk(1, "Firmware upload successful.\n");
++
++	retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
++		IVTV_CMD_HW_BLOCKS_RST);
++
++	/* Restore GPIO settings, make sure EIO14 is enabled as an output. */
++	dprintk(2, "%s: GPIO output EIO 0-15 was = 0x%x\n",
++		__func__, gpio_output);
++	/* Power-up seems to have GPIOs AFU. This was causing digital side
++	 * to fail at power-up. Seems GPIOs should be set to 0x10ff0411 at
++	 * power-up.
++	 * gpio_output |= (1<<14);
++	 */
++	/* Note: GPIO14 is specific to the HVR1800 here */
++	gpio_output = 0x10ff0411 | (1<<14);
++	retval |= mc417_register_write(dev, 0x9020, gpio_output | (1<<14));
++	dprintk(2, "%s: GPIO output EIO 0-15 now = 0x%x\n",
++		__func__, gpio_output);
++
++	dprintk(1, "%s: GPIO value  EIO 0-15 was = 0x%x\n",
++		__func__, value);
++	value |= (1<<14);
++	dprintk(1, "%s: GPIO value  EIO 0-15 now = 0x%x\n",
++		__func__, value);
++	retval |= mc417_register_write(dev, 0x900C, value);
++
++	retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
++	retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
++
++	if (retval < 0)
++		printk(KERN_ERR "%s: Error with mc417_register_write\n",
++			__func__);
++	return 0;
++}
++
++void cx23885_417_check_encoder(struct cx23885_dev *dev)
++{
++	u32 status, seq;
++
++	status = seq = 0;
++	cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
++	dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
++}
++
++static void cx23885_codec_settings(struct cx23885_dev *dev)
++{
++	dprintk(1, "%s()\n", __func__);
++
++	/* assign frame size */
++	cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
++				dev->ts1.height, dev->ts1.width);
++
++	dev->mpeg_params.width = dev->ts1.width;
++	dev->mpeg_params.height = dev->ts1.height;
++	dev->mpeg_params.is_50hz =
++		(dev->encodernorm.id & V4L2_STD_625_50) != 0;
++
++	cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params);
++
++	cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
++	cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
++}
++
++static int cx23885_initialize_codec(struct cx23885_dev *dev)
++{
++	int version;
++	int retval;
++	u32 i, data[7];
++
++	dprintk(1, "%s()\n", __func__);
++
++	retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
++	if (retval < 0) {
++		dprintk(2, "%s() PING OK\n", __func__);
++		retval = cx23885_load_firmware(dev);
++		if (retval < 0) {
++			printk(KERN_ERR "%s() f/w load failed\n", __func__);
++			return retval;
++		}
++		dev->cx23417_mailbox = cx23885_find_mailbox(dev);
++		if (dev->cx23417_mailbox < 0) {
++			printk(KERN_ERR "%s() mailbox < 0, error\n",
++				__func__);
++			return -1;
++		}
++		retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
++		if (retval < 0) {
++			printk(KERN_ERR
++				"ERROR: cx23417 firmware ping failed!\n");
++			return -1;
++		}
++		retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
++			&version);
++		if (retval < 0) {
++			printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
++				"version failed!\n");
++			return -1;
++		}
++		dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
++		msleep(200);
++	}
++
++	cx23885_codec_settings(dev);
++	msleep(60);
++
++	cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
++		CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115);
++	cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
++		CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++		0, 0);
++
++	/* Setup to capture VBI */
++	data[0] = 0x0001BD00;
++	data[1] = 1;          /* frames per interrupt */
++	data[2] = 4;          /* total bufs */
++	data[3] = 0x91559155; /* start codes */
++	data[4] = 0x206080C0; /* stop codes */
++	data[5] = 6;          /* lines */
++	data[6] = 64;         /* BPL */
++
++	cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
++		data[2], data[3], data[4], data[5], data[6]);
++
++	for (i = 2; i <= 24; i++) {
++		int valid;
++
++		valid = ((i >= 19) && (i <= 21));
++		cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
++				valid, 0 , 0, 0);
++		cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
++				i | 0x80000000, valid, 0, 0, 0);
++	}
++
++	cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE);
++	msleep(60);
++
++	/* initialize the video input */
++	cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
++	msleep(60);
++
++	/* Enable VIP style pixel invalidation so we work with scaled mode */
++	mc417_memory_write(dev, 2120, 0x00000080);
++
++	/* start capturing to the host interface */
++	cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
++		CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
++	msleep(10);
++
++	return 0;
++}
++
++/* ------------------------------------------------------------------ */
++
++static int bb_buf_setup(struct videobuf_queue *q,
++	unsigned int *count, unsigned int *size)
++{
++	struct cx23885_fh *fh = q->priv_data;
++
++	fh->dev->ts1.ts_packet_size  = mpeglinesize;
++	fh->dev->ts1.ts_packet_count = mpeglines;
++
++	*size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
++	*count = mpegbufs;
++
++	return 0;
++}
++
++static int bb_buf_prepare(struct videobuf_queue *q,
++	struct videobuf_buffer *vb, enum v4l2_field field)
++{
++	struct cx23885_fh *fh = q->priv_data;
++	return cx23885_buf_prepare(q, &fh->dev->ts1,
++		(struct cx23885_buffer *)vb,
++		field);
++}
++
++static void bb_buf_queue(struct videobuf_queue *q,
++	struct videobuf_buffer *vb)
++{
++	struct cx23885_fh *fh = q->priv_data;
++	cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb);
++}
++
++static void bb_buf_release(struct videobuf_queue *q,
++	struct videobuf_buffer *vb)
++{
++	cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
++}
++
++static struct videobuf_queue_ops cx23885_qops = {
++	.buf_setup    = bb_buf_setup,
++	.buf_prepare  = bb_buf_prepare,
++	.buf_queue    = bb_buf_queue,
++	.buf_release  = bb_buf_release,
++};
++
++/* ------------------------------------------------------------------ */
++
++static const u32 *ctrl_classes[] = {
++	cx2341x_mpeg_ctrls,
++	NULL
++};
++
++static int cx23885_queryctrl(struct cx23885_dev *dev,
++	struct v4l2_queryctrl *qctrl)
++{
++	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
++	if (qctrl->id == 0)
++		return -EINVAL;
++
++	/* MPEG V4L2 controls */
++	if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
++		qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
++
++	return 0;
++}
++
++static int cx23885_querymenu(struct cx23885_dev *dev,
++	struct v4l2_querymenu *qmenu)
++{
++	struct v4l2_queryctrl qctrl;
++
++	qctrl.id = qmenu->id;
++	cx23885_queryctrl(dev, &qctrl);
++	return v4l2_ctrl_query_menu(qmenu, &qctrl,
++		cx2341x_ctrl_get_menu(qmenu->id));
++}
++
++int cx23885_do_ioctl(struct inode *inode, struct file *file, int radio,
++	struct cx23885_dev *dev, unsigned int cmd, void *arg,
++	v4l2_kioctl driver_ioctl)
++{
++	int err;
++
++	switch (cmd) {
++	/* ---------- tv norms ---------- */
++	case VIDIOC_ENUMSTD:
++	{
++		struct v4l2_standard *e = arg;
++		unsigned int i;
++
++		i = e->index;
++		if (i >= ARRAY_SIZE(cx23885_tvnorms))
++			return -EINVAL;
++		err = v4l2_video_std_construct(e,
++			cx23885_tvnorms[e->index].id,
++			cx23885_tvnorms[e->index].name);
++		e->index = i;
++		if (err < 0)
++			return err;
++		return 0;
++	}
++	case VIDIOC_G_STD:
++	{
++		v4l2_std_id *id = arg;
++
++		*id = dev->encodernorm.id;
++		return 0;
++	}
++	case VIDIOC_S_STD:
++	{
++		v4l2_std_id *id = arg;
++		unsigned int i;
++
++		for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
++			if (*id & cx23885_tvnorms[i].id)
++				break;
++		if (i == ARRAY_SIZE(cx23885_tvnorms))
++			return -EINVAL;
++		dev->encodernorm = cx23885_tvnorms[i];
++
++		return 0;
++	}
++
++	/* ------ input switching ---------- */
++	case VIDIOC_ENUMINPUT:
++	{
++		struct cx23885_input *input;
++		struct v4l2_input *i = arg;
++		unsigned int n;
++
++		n = i->index;
++		if (n >= 4)
++			return -EINVAL;
++		input = &cx23885_boards[dev->board].input[n];
++		if (input->type == 0)
++			return -EINVAL;
++		memset(i, 0, sizeof(*i));
++		i->index = n;
++		/* FIXME
++		 * strcpy(i->name, input->name); */
++		strcpy(i->name, "unset");
++		if (input->type == CX23885_VMUX_TELEVISION ||
++		    input->type == CX23885_VMUX_CABLE)
++			i->type = V4L2_INPUT_TYPE_TUNER;
++		else
++			i->type  = V4L2_INPUT_TYPE_CAMERA;
++
++		for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++)
++			i->std |= cx23885_tvnorms[n].id;
++		return 0;
++	}
++	case VIDIOC_G_INPUT:
++	{
++		unsigned int *i = arg;
++
++		*i = dev->input;
++		return 0;
++	}
++	case VIDIOC_S_INPUT:
++	{
++		unsigned int *i = arg;
++
++		if (*i >= 4)
++			return -EINVAL;
++
++		return 0;
++	}
++
++	/* --- tuner ioctls ------------------------------------------ */
++	case VIDIOC_G_TUNER:
++	{
++		struct v4l2_tuner *t = arg;
++
++		if (UNSET == dev->tuner_type)
++			return -EINVAL;
++		if (0 != t->index)
++			return -EINVAL;
++		memset(t, 0, sizeof(*t));
++		strcpy(t->name, "Television");
++		cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
++		cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
++
++		dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
++
++		return 0;
++	}
++	case VIDIOC_S_TUNER:
++	{
++		struct v4l2_tuner *t = arg;
++
++		if (UNSET == dev->tuner_type)
++			return -EINVAL;
++
++		/* Update the A/V core */
++		cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t);
++
++		return 0;
++	}
++	case VIDIOC_G_FREQUENCY:
++	{
++		struct v4l2_frequency *f = arg;
++
++		memset(f, 0, sizeof(*f));
++		if (UNSET == dev->tuner_type)
++			return -EINVAL;
++		f->type = V4L2_TUNER_ANALOG_TV;
++		f->frequency = dev->freq;
++
++		/* Assumption that tuner is always on bus 1 */
++		cx23885_call_i2c_clients(&dev->i2c_bus[1],
++			VIDIOC_G_FREQUENCY, f);
++
++		return 0;
++	}
++	case VIDIOC_S_FREQUENCY:
++	{
++		struct v4l2_frequency *f = arg;
++
++		dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n",
++			dev->tuner_type);
++		dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n",
++			f->tuner, f->type);
++		if (UNSET == dev->tuner_type)
++			return -EINVAL;
++		if (f->tuner != 0)
++			return -EINVAL;
++		if (f->type != V4L2_TUNER_ANALOG_TV)
++			return -EINVAL;
++		dev->freq = f->frequency;
++
++		/* Assumption that tuner is always on bus 1 */
++		cx23885_call_i2c_clients(&dev->i2c_bus[1],
++			VIDIOC_S_FREQUENCY, f);
++		return 0;
++	}
++	case VIDIOC_S_CTRL:
++	{
++		/* Update the A/V core */
++		cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, arg);
++		return 0;
++	}
++	default:
++		/* Convert V4L ioctl to V4L2 and call mpeg_do_ioctl
++		 * (driver_ioctl) */
++		return v4l_compat_translate_ioctl(inode, file, cmd, arg,
++						  driver_ioctl);
++	}
++
++	return 0;
++}
++
++static int mpeg_do_ioctl(struct inode *inode, struct file *file,
++			 unsigned int cmd, void *arg)
++{
++	struct cx23885_fh  *fh  = file->private_data;
++	struct cx23885_dev *dev = fh->dev;
++	struct cx23885_tsport  *tsport = &dev->ts1;
++
++	if (v4l_debug > 1)
++		v4l_print_ioctl(dev->name, cmd);
++
++	switch (cmd) {
++
++	/* --- capabilities ------------------------------------------ */
++	case VIDIOC_QUERYCAP:
++	{
++		struct v4l2_capability *cap = arg;
++
++		memset(cap, 0, sizeof(*cap));
++		strcpy(cap->driver, dev->name);
++		strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
++			sizeof(cap->card));
++		sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
++		cap->version = CX23885_VERSION_CODE;
++		cap->capabilities =
++			V4L2_CAP_VIDEO_CAPTURE |
++			V4L2_CAP_READWRITE     |
++			V4L2_CAP_STREAMING     |
++			0;
++		if (UNSET != dev->tuner_type)
++			cap->capabilities |= V4L2_CAP_TUNER;
++
++		return 0;
++	}
++
++	/* --- capture ioctls ---------------------------------------- */
++	case VIDIOC_ENUM_FMT:
++	{
++		struct v4l2_fmtdesc *f = arg;
++		int index;
++
++		index = f->index;
++		if (index != 0)
++			return -EINVAL;
++
++		memset(f, 0, sizeof(*f));
++		f->index = index;
++		strlcpy(f->description, "MPEG", sizeof(f->description));
++		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++		f->pixelformat = V4L2_PIX_FMT_MPEG;
++		return 0;
++	}
++	case VIDIOC_G_FMT:
++	{
++		struct v4l2_format *f = arg;
++
++		memset(f, 0, sizeof(*f));
++		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
++		f->fmt.pix.bytesperline = 0;
++		f->fmt.pix.sizeimage    =
++			dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
++		f->fmt.pix.colorspace   = 0;
++		f->fmt.pix.width        = dev->ts1.width;
++		f->fmt.pix.height       = dev->ts1.height;
++		f->fmt.pix.field        = fh->mpegq.field;
++		dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
++			dev->ts1.width, dev->ts1.height, fh->mpegq.field);
++		return 0;
++	}
++	case VIDIOC_TRY_FMT:
++	{
++		struct v4l2_format *f = arg;
++
++		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
++		f->fmt.pix.bytesperline = 0;
++		f->fmt.pix.sizeimage    =
++			dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
++		f->fmt.pix.sizeimage    =
++		f->fmt.pix.colorspace   = 0;
++		dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
++			dev->ts1.width, dev->ts1.height, fh->mpegq.field);
++		return 0;
++	}
++	case VIDIOC_S_FMT:
++	{
++		struct v4l2_format *f = arg;
++
++		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
++		f->fmt.pix.bytesperline = 0;
++		f->fmt.pix.sizeimage    =
++			dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
++		f->fmt.pix.colorspace   = 0;
++		dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
++			f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
++		return 0;
++	}
++
++	/* --- streaming capture ------------------------------------- */
++	case VIDIOC_REQBUFS:
++		return videobuf_reqbufs(&fh->mpegq, arg);
++
++	case VIDIOC_QUERYBUF:
++		return videobuf_querybuf(&fh->mpegq, arg);
++
++	case VIDIOC_QBUF:
++		return videobuf_qbuf(&fh->mpegq, arg);
++
++	case VIDIOC_DQBUF:
++		return videobuf_dqbuf(&fh->mpegq, arg,
++				      file->f_flags & O_NONBLOCK);
++
++	case VIDIOC_STREAMON:
++		return videobuf_streamon(&fh->mpegq);
++
++	case VIDIOC_STREAMOFF:
++		return videobuf_streamoff(&fh->mpegq);
++
++	case VIDIOC_G_EXT_CTRLS:
++	{
++		struct v4l2_ext_controls *f = arg;
++
++		if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
++			return -EINVAL;
++		return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, cmd);
++	}
++	case VIDIOC_S_EXT_CTRLS:
++	case VIDIOC_TRY_EXT_CTRLS:
++	{
++		struct v4l2_ext_controls *f = arg;
++		struct cx2341x_mpeg_params p;
++		int err;
++
++		if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
++			return -EINVAL;
++		p = dev->mpeg_params;
++		err = cx2341x_ext_ctrls(&p, 0, f, cmd);
++		if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
++			err = cx2341x_update(dev, cx23885_mbox_func,
++				&dev->mpeg_params, &p);
++			dev->mpeg_params = p;
++		}
++		return err;
++	}
++	case VIDIOC_S_FREQUENCY:
++	{
++		cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
++			CX23885_END_NOW, CX23885_MPEG_CAPTURE,
++			CX23885_RAW_BITS_NONE);
++		cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
++			mpeg_do_ioctl);
++		cx23885_initialize_codec(dev);
++
++		return 0;
++	}
++	case VIDIOC_LOG_STATUS:
++	{
++		char name[32 + 2];
++
++		snprintf(name, sizeof(name), "%s/2", dev->name);
++		printk(KERN_INFO
++			"%s/2: ============  START LOG STATUS  ============\n",
++		       dev->name);
++		cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
++			NULL);
++		cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
++			NULL);
++		cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
++			NULL);
++		cx2341x_log_status(&dev->mpeg_params, name);
++		printk(KERN_INFO
++			"%s/2: =============  END LOG STATUS  =============\n",
++		       dev->name);
++		return 0;
++	}
++	case VIDIOC_QUERYMENU:
++		return cx23885_querymenu(dev, arg);
++	case VIDIOC_QUERYCTRL:
++	{
++		struct v4l2_queryctrl *c = arg;
++
++		return cx23885_queryctrl(dev, c);
++	}
++
++	default:
++		return cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
++				mpeg_do_ioctl);
++	}
++	return 0;
++}
++
++static int mpeg_ioctl(struct inode *inode, struct file *file,
++			unsigned int cmd, unsigned long arg)
++{
++	return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
++}
++
++static int mpeg_open(struct inode *inode, struct file *file)
++{
++	int minor = iminor(inode);
++	struct cx23885_dev *h, *dev = NULL;
++	struct list_head *list;
++	struct cx23885_fh *fh;
++
++	dprintk(2, "%s()\n", __func__);
++
++	list_for_each(list, &cx23885_devlist) {
++		h = list_entry(list, struct cx23885_dev, devlist);
++		if (h->v4l_device->minor == minor) {
++			dev = h;
++			break;
++		}
++	}
++
++	if (dev == NULL)
++		return -ENODEV;
++
++	/* allocate + initialize per filehandle data */
++	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
++	if (NULL == fh)
++		return -ENOMEM;
++
++	file->private_data = fh;
++	fh->dev      = dev;
++
++	videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops,
++			    &dev->pci->dev, &dev->ts1.slock,
++			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
++			    V4L2_FIELD_INTERLACED,
++			    sizeof(struct cx23885_buffer),
++			    fh);
++
++	return 0;
++}
++
++static int mpeg_release(struct inode *inode, struct file *file)
++{
++	struct cx23885_fh  *fh  = file->private_data;
++	struct cx23885_dev *dev = fh->dev;
++
++	dprintk(2, "%s()\n", __func__);
++
++	/* FIXME: Review this crap */
++	/* Shut device down on last close */
++	if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
++		if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
++			/* stop mpeg capture */
++			cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
++				CX23885_END_NOW, CX23885_MPEG_CAPTURE,
++				CX23885_RAW_BITS_NONE);
++
++			msleep(500);
++			cx23885_417_check_encoder(dev);
++
++			cx23885_cancel_buffers(&fh->dev->ts1);
++		}
++	}
++
++	if (fh->mpegq.streaming)
++		videobuf_streamoff(&fh->mpegq);
++	if (fh->mpegq.reading)
++		videobuf_read_stop(&fh->mpegq);
++
++	videobuf_mmap_free(&fh->mpegq);
++	file->private_data = NULL;
++	kfree(fh);
++
++	return 0;
++}
++
++static ssize_t mpeg_read(struct file *file, char __user *data,
++	size_t count, loff_t *ppos)
++{
++	struct cx23885_fh *fh = file->private_data;
++	struct cx23885_dev *dev = fh->dev;
++
++	dprintk(2, "%s()\n", __func__);
++
++	/* Deal w/ A/V decoder * and mpeg encoder sync issues. */
++	/* Start mpeg encoder on first read. */
++	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
++		if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
++			if (cx23885_initialize_codec(dev) < 0)
++				return -EINVAL;
++		}
++	}
++
++	return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
++				    file->f_flags & O_NONBLOCK);
++}
++
++static unsigned int mpeg_poll(struct file *file,
++	struct poll_table_struct *wait)
++{
++	struct cx23885_fh *fh = file->private_data;
++	struct cx23885_dev *dev = fh->dev;
++
++	dprintk(2, "%s\n", __func__);
++
++	return videobuf_poll_stream(file, &fh->mpegq, wait);
++}
++
++static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
++{
++	struct cx23885_fh *fh = file->private_data;
++	struct cx23885_dev *dev = fh->dev;
++
++	dprintk(2, "%s()\n", __func__);
++
++	return videobuf_mmap_mapper(&fh->mpegq, vma);
++}
++
++static struct file_operations mpeg_fops = {
++	.owner	       = THIS_MODULE,
++	.open	       = mpeg_open,
++	.release       = mpeg_release,
++	.read	       = mpeg_read,
++	.poll          = mpeg_poll,
++	.mmap	       = mpeg_mmap,
++	.ioctl	       = mpeg_ioctl,
++	.llseek        = no_llseek,
++};
++
++static struct video_device cx23885_mpeg_template = {
++	.name          = "cx23885",
++	.type          = VID_TYPE_CAPTURE |
++				VID_TYPE_TUNER |
++				VID_TYPE_SCALES |
++				VID_TYPE_MPEG_ENCODER,
++	.fops          = &mpeg_fops,
++	.minor         = -1,
++};
++
++void cx23885_417_unregister(struct cx23885_dev *dev)
++{
++	dprintk(1, "%s()\n", __func__);
++
++	if (dev->v4l_device) {
++		if (-1 != dev->v4l_device->minor)
++			video_unregister_device(dev->v4l_device);
++		else
++			video_device_release(dev->v4l_device);
++		dev->v4l_device = NULL;
++	}
++}
++
++static struct video_device *cx23885_video_dev_alloc(
++	struct cx23885_tsport *tsport,
++	struct pci_dev *pci,
++	struct video_device *template,
++	char *type)
++{
++	struct video_device *vfd;
++	struct cx23885_dev *dev = tsport->dev;
++
++	dprintk(1, "%s()\n", __func__);
++
++	vfd = video_device_alloc();
++	if (NULL == vfd)
++		return NULL;
++	*vfd = *template;
++	vfd->minor   = -1;
++	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
++		type, cx23885_boards[tsport->dev->board].name);
++	vfd->dev     = &pci->dev;
++	vfd->release = video_device_release;
++	return vfd;
++}
++
++int cx23885_417_register(struct cx23885_dev *dev)
++{
++	/* FIXME: Port1 hardcoded here */
++	int err = -ENODEV;
++	struct cx23885_tsport *tsport = &dev->ts1;
++
++	dprintk(1, "%s()\n", __func__);
++
++	if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER)
++		return err;
++
++	/* Set default TV standard */
++	dev->encodernorm = cx23885_tvnorms[0];
++
++	if (dev->encodernorm.id & V4L2_STD_525_60)
++		tsport->height = 480;
++	else
++		tsport->height = 576;
++
++	tsport->width = 720;
++	cx2341x_fill_defaults(&dev->mpeg_params);
++
++	dev->mpeg_params.port = CX2341X_PORT_SERIAL;
++
++	/* Allocate and initialize V4L video device */
++	dev->v4l_device = cx23885_video_dev_alloc(tsport,
++		dev->pci, &cx23885_mpeg_template, "mpeg");
++	err = video_register_device(dev->v4l_device,
++		VFL_TYPE_GRABBER, -1);
++	if (err < 0) {
++		printk(KERN_INFO "%s: can't register mpeg device\n", dev->name);
++		return err;
++	}
++
++	/* Initialize MC417 registers */
++	cx23885_mc417_init(dev);
++
++	printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
++	       dev->name, dev->v4l_device->minor & 0x1f);
++
++	return 0;
++}
+diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
+index dfa2698..6ebf587 100644
+--- a/drivers/media/video/cx23885/cx23885-cards.c
++++ b/drivers/media/video/cx23885/cx23885-cards.c
+@@ -73,6 +73,7 @@ struct cx23885_board cx23885_boards[] = {
+ 	[CX23885_BOARD_HAUPPAUGE_HVR1800] = {
+ 		.name		= "Hauppauge WinTV-HVR1800",
+ 		.porta		= CX23885_ANALOG_VIDEO,
++		.portb		= CX23885_MPEG_ENCODER,
+ 		.portc		= CX23885_MPEG_DVB,
+ 		.tuner_type	= TUNER_PHILIPS_TDA8290,
+ 		.tuner_addr	= 0x42, /* 0x84 >> 1 */
+@@ -130,6 +131,18 @@ struct cx23885_board cx23885_boards[] = {
+ 		.name		= "Hauppauge WinTV-HVR1500",
+ 		.portc		= CX23885_MPEG_DVB,
+ 	},
++	[CX23885_BOARD_HAUPPAUGE_HVR1200] = {
++		.name		= "Hauppauge WinTV-HVR1200",
++		.portc		= CX23885_MPEG_DVB,
++	},
++	[CX23885_BOARD_HAUPPAUGE_HVR1700] = {
++		.name		= "Hauppauge WinTV-HVR1700",
++		.portc		= CX23885_MPEG_DVB,
++	},
++	[CX23885_BOARD_HAUPPAUGE_HVR1400] = {
++		.name		= "Hauppauge WinTV-HVR1400",
++		.portc		= CX23885_MPEG_DVB,
++	},
+ };
+ const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
+ 
+@@ -181,6 +194,18 @@ struct cx23885_subid cx23885_subids[] = {
+ 		.subvendor = 0x0070,
+ 		.subdevice = 0x7717,
+ 		.card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
++	}, {
++		.subvendor = 0x0070,
++		.subdevice = 0x71d1,
++		.card      = CX23885_BOARD_HAUPPAUGE_HVR1200,
++	}, {
++		.subvendor = 0x0070,
++		.subdevice = 0x8101,
++		.card      = CX23885_BOARD_HAUPPAUGE_HVR1700,
++	}, {
++		.subvendor = 0x0070,
++		.subdevice = 0x8010,
++		.card      = CX23885_BOARD_HAUPPAUGE_HVR1400,
+ 	},
+ };
+ const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
+@@ -235,6 +260,12 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
+ 	case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
+ 	case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */
+ 	case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
++	case 80019:
++		/* WinTV-HVR1400 (Express Card, Retail, IR,
++		 * DVB-T and Basic analog */
++	case 81519:
++		/* WinTV-HVR1700 (PCIe, Retail, No IR, half height,
++		 * DVB-T and MPEG2 HW Encoder */
+ 		break;
+ 	default:
+ 		printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model);
+@@ -264,7 +295,7 @@ int cx23885_tuner_callback(void *priv, int command, int arg)
+ 		}
+ 		else {
+ 			printk(KERN_ERR
+-				"%s(): Unknow command.\n", __FUNCTION__);
++				"%s(): Unknow command.\n", __func__);
+ 			return -EINVAL;
+ 		}
+ 		break;
+@@ -306,6 +337,10 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
+ 		/* GPIO-15-18 cx23417 READY, CS, RD, WR */
+ 		/* GPIO-19 IR_RX */
+ 
++		/* CX23417 GPIO's */
++		/* EIO15 Zilog Reset */
++		/* EIO14 S5H1409/CX24227 Reset */
++
+ 		/* Force the TDA8295A into reset and back */
+ 		cx_set(GP0_IO, 0x00040004);
+ 		mdelay(20);
+@@ -314,6 +349,50 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
+ 		cx_set(GP0_IO, 0x00040004);
+ 		mdelay(20);
+ 		break;
++	case CX23885_BOARD_HAUPPAUGE_HVR1200:
++		/* GPIO-0 tda10048 demodulator reset */
++		/* GPIO-2 tda18271 tuner reset */
++
++		/* Put the parts into reset and back */
++		cx_set(GP0_IO, 0x00050000);
++		mdelay(20);
++		cx_clear(GP0_IO, 0x00000005);
++		mdelay(20);
++		cx_set(GP0_IO, 0x00050005);
++		break;
++	case CX23885_BOARD_HAUPPAUGE_HVR1700:
++		/* GPIO-0 TDA10048 demodulator reset */
++		/* GPIO-2 TDA8295A Reset */
++		/* GPIO-3-10 cx23417 data0-7 */
++		/* GPIO-11-14 cx23417 addr0-3 */
++		/* GPIO-15-18 cx23417 READY, CS, RD, WR */
++
++		/* The following GPIO's are on the interna AVCore (cx25840) */
++		/* GPIO-19 IR_RX */
++		/* GPIO-20 IR_TX 416/DVBT Select */
++		/* GPIO-21 IIS DAT */
++		/* GPIO-22 IIS WCLK */
++		/* GPIO-23 IIS BCLK */
++
++		/* Put the parts into reset and back */
++		cx_set(GP0_IO, 0x00050000);
++		mdelay(20);
++		cx_clear(GP0_IO, 0x00000005);
++		mdelay(20);
++		cx_set(GP0_IO, 0x00050005);
++		break;
++	case CX23885_BOARD_HAUPPAUGE_HVR1400:
++		/* GPIO-0  Dibcom7000p demodulator reset */
++		/* GPIO-2  xc3028L tuner reset */
++		/* GPIO-13 LED */
++
++		/* Put the parts into reset and back */
++		cx_set(GP0_IO, 0x00050000);
++		mdelay(20);
++		cx_clear(GP0_IO, 0x00000005);
++		mdelay(20);
++		cx_set(GP0_IO, 0x00050005);
++		break;
+ 	}
+ }
+ 
+@@ -324,6 +403,8 @@ int cx23885_ir_init(struct cx23885_dev *dev)
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1800:
++	case CX23885_BOARD_HAUPPAUGE_HVR1200:
++	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ 		/* FIXME: Implement me */
+ 		break;
+ 	}
+@@ -348,11 +429,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
++	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ 		if (dev->i2c_bus[0].i2c_rc == 0)
+ 			hauppauge_eeprom(dev, eeprom+0x80);
+ 		break;
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
++	case CX23885_BOARD_HAUPPAUGE_HVR1200:
++	case CX23885_BOARD_HAUPPAUGE_HVR1700:
+ 		if (dev->i2c_bus[0].i2c_rc == 0)
+ 			hauppauge_eeprom(dev, eeprom+0xc0);
+ 		break;
+@@ -364,17 +448,45 @@ void cx23885_card_setup(struct cx23885_dev *dev)
+ 		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ 		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ 		break;
++	case CX23885_BOARD_HAUPPAUGE_HVR1800:
++		/* Defaults for VID B - Analog encoder */
++		/* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
++		ts1->gen_ctrl_val    = 0x10e;
++		ts1->ts_clk_en_val   = 0x1; /* Enable TS_CLK */
++		ts1->src_sel_val     = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
++
++		/* APB_TSVALERR_POL (active low)*/
++		ts1->vld_misc_val    = 0x2000;
++		ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc);
++
++		/* Defaults for VID C */
++		ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
++		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
++		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
++		break;
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+-	case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
++	case CX23885_BOARD_HAUPPAUGE_HVR1200:
++	case CX23885_BOARD_HAUPPAUGE_HVR1700:
++	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ 	default:
+ 		ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+ 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ 	}
+ 
++	/* Certain boards support analog, or require the avcore to be
++	 * loaded, ensure this happens.
++	 */
++	switch (dev->board) {
++	case CX23885_BOARD_HAUPPAUGE_HVR1800:
++	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
++	case CX23885_BOARD_HAUPPAUGE_HVR1700:
++		request_module("cx25840");
++		break;
++	}
+ }
+ 
+ /* ------------------------------------------------------------------ */
+diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
+index 7f10b27..f24abcd 100644
+--- a/drivers/media/video/cx23885/cx23885-core.c
++++ b/drivers/media/video/cx23885/cx23885-core.c
+@@ -190,25 +190,25 @@ static struct sram_channel cx23887_sram_channels[] = {
+ static int cx23885_risc_decode(u32 risc)
+ {
+ 	static char *instr[16] = {
+-		[ RISC_SYNC    >> 28 ] = "sync",
+-		[ RISC_WRITE   >> 28 ] = "write",
+-		[ RISC_WRITEC  >> 28 ] = "writec",
+-		[ RISC_READ    >> 28 ] = "read",
+-		[ RISC_READC   >> 28 ] = "readc",
+-		[ RISC_JUMP    >> 28 ] = "jump",
+-		[ RISC_SKIP    >> 28 ] = "skip",
+-		[ RISC_WRITERM >> 28 ] = "writerm",
+-		[ RISC_WRITECM >> 28 ] = "writecm",
+-		[ RISC_WRITECR >> 28 ] = "writecr",
++		[RISC_SYNC    >> 28] = "sync",
++		[RISC_WRITE   >> 28] = "write",
++		[RISC_WRITEC  >> 28] = "writec",
++		[RISC_READ    >> 28] = "read",
++		[RISC_READC   >> 28] = "readc",
++		[RISC_JUMP    >> 28] = "jump",
++		[RISC_SKIP    >> 28] = "skip",
++		[RISC_WRITERM >> 28] = "writerm",
++		[RISC_WRITECM >> 28] = "writecm",
++		[RISC_WRITECR >> 28] = "writecr",
+ 	};
+ 	static int incr[16] = {
+-		[ RISC_WRITE   >> 28 ] = 3,
+-		[ RISC_JUMP    >> 28 ] = 3,
+-		[ RISC_SKIP    >> 28 ] = 1,
+-		[ RISC_SYNC    >> 28 ] = 1,
+-		[ RISC_WRITERM >> 28 ] = 3,
+-		[ RISC_WRITECM >> 28 ] = 3,
+-		[ RISC_WRITECR >> 28 ] = 4,
++		[RISC_WRITE   >> 28] = 3,
++		[RISC_JUMP    >> 28] = 3,
++		[RISC_SKIP    >> 28] = 1,
++		[RISC_SYNC    >> 28] = 1,
++		[RISC_WRITERM >> 28] = 3,
++		[RISC_WRITECM >> 28] = 3,
++		[RISC_WRITECR >> 28] = 4,
+ 	};
+ 	static char *bits[] = {
+ 		"12",   "13",   "14",   "resync",
+@@ -260,7 +260,7 @@ void cx23885_wakeup(struct cx23885_tsport *port,
+ 	}
+ 	if (bc != 1)
+ 		printk("%s: %d buffers handled (should be 1)\n",
+-		       __FUNCTION__, bc);
++		       __func__, bc);
+ }
+ 
+ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+@@ -272,7 +272,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+ 
+ 	if (ch->cmds_start == 0)
+ 	{
+-		dprintk(1, "%s() Erasing channel [%s]\n", __FUNCTION__,
++		dprintk(1, "%s() Erasing channel [%s]\n", __func__,
+ 			ch->name);
+ 		cx_write(ch->ptr1_reg, 0);
+ 		cx_write(ch->ptr2_reg, 0);
+@@ -280,7 +280,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+ 		cx_write(ch->cnt1_reg, 0);
+ 		return 0;
+ 	} else {
+-		dprintk(1, "%s() Configuring channel [%s]\n", __FUNCTION__,
++		dprintk(1, "%s() Configuring channel [%s]\n", __func__,
+ 			ch->name);
+ 	}
+ 
+@@ -297,7 +297,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+ 
+ 	/* write CDT */
+ 	for (i = 0; i < lines; i++) {
+-		dprintk(2, "%s() 0x%08x <- 0x%08x\n", __FUNCTION__, cdt + 16*i,
++		dprintk(2, "%s() 0x%08x <- 0x%08x\n", __func__, cdt + 16*i,
+ 			ch->fifo_start + bpl*i);
+ 		cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
+ 		cx_write(cdt + 16*i +  4, 0);
+@@ -449,7 +449,7 @@ static void cx23885_shutdown(struct cx23885_dev *dev)
+ 
+ static void cx23885_reset(struct cx23885_dev *dev)
+ {
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	cx23885_shutdown(dev);
+ 
+@@ -482,7 +482,7 @@ static void cx23885_reset(struct cx23885_dev *dev)
+ 
+ static int cx23885_pci_quirks(struct cx23885_dev *dev)
+ {
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	/* The cx23885 bridge has a weird bug which causes NMI to be asserted
+ 	 * when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
+@@ -513,11 +513,13 @@ int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+ 
+ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno)
+ {
+-	dprintk(1, "%s(portno=%d)\n", __FUNCTION__, portno);
++	dprintk(1, "%s(portno=%d)\n", __func__, portno);
+ 
+ 	/* Transport bus init dma queue  - Common settings */
+ 	port->dma_ctl_val        = 0x11; /* Enable RISC controller and Fifo */
+ 	port->ts_int_msk_val     = 0x1111; /* TS port bits for RISC */
++	port->vld_misc_val       = 0x0;
++	port->hw_sop_ctrl_val    = (0x47 << 16 | 188 << 4);
+ 
+ 	spin_lock_init(&port->slock);
+ 	port->dev = dev;
+@@ -544,7 +546,7 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
+ 		port->reg_ts_clk_en      = VID_B_TS_CLK_EN;
+ 		port->reg_src_sel        = VID_B_SRC_SEL;
+ 		port->reg_ts_int_msk     = VID_B_INT_MSK;
+-		port->reg_ts_int_stat   = VID_B_INT_STAT;
++		port->reg_ts_int_stat    = VID_B_INT_STAT;
+ 		port->sram_chno          = SRAM_CH03; /* VID_B */
+ 		port->pci_irqmask        = 0x02; /* VID_B bit1 */
+ 		break;
+@@ -604,14 +606,14 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
+ 		break;
+ 	default:
+ 		printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
+-			__FUNCTION__, dev->hwrevision);
++			__func__, dev->hwrevision);
+ 	}
+ 	if (dev->hwrevision)
+ 		printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
+-			__FUNCTION__, dev->hwrevision);
++			__func__, dev->hwrevision);
+ 	else
+ 		printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
+-			__FUNCTION__, dev->hwrevision);
++			__func__, dev->hwrevision);
+ }
+ 
+ static int cx23885_dev_setup(struct cx23885_dev *dev)
+@@ -644,7 +646,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
+ 		BUG();
+ 
+ 	dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
+-		__FUNCTION__, dev->bridge);
++		__func__, dev->bridge);
+ 
+ 	/* board config */
+ 	dev->board = UNSET;
+@@ -697,10 +699,12 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
+ 	dev->i2c_bus[2].reg_wdata = I2C3_WDATA;
+ 	dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */
+ 
+-	if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
++	if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) ||
++		(cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
+ 		cx23885_init_tsport(dev, &dev->ts1, 1);
+ 
+-	if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
++	if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) ||
++		(cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
+ 		cx23885_init_tsport(dev, &dev->ts2, 2);
+ 
+ 	if (get_resources(dev) < 0) {
+@@ -734,9 +738,9 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
+ 	dev->radio_addr = cx23885_boards[dev->board].radio_addr;
+ 
+ 	dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n",
+-		__FUNCTION__, dev->tuner_type, dev->tuner_addr);
++		__func__, dev->tuner_type, dev->tuner_addr);
+ 	dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
+-		__FUNCTION__, dev->radio_type, dev->radio_addr);
++		__func__, dev->radio_type, dev->radio_addr);
+ 
+ 	/* init hardware */
+ 	cx23885_reset(dev);
+@@ -744,28 +748,43 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
+ 	cx23885_i2c_register(&dev->i2c_bus[0]);
+ 	cx23885_i2c_register(&dev->i2c_bus[1]);
+ 	cx23885_i2c_register(&dev->i2c_bus[2]);
+-	cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+ 	cx23885_card_setup(dev);
++	cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+ 	cx23885_ir_init(dev);
+ 
+ 	if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
+ 		if (cx23885_video_register(dev) < 0) {
+ 			printk(KERN_ERR "%s() Failed to register analog "
+-				"video adapters on VID_A\n", __FUNCTION__);
++				"video adapters on VID_A\n", __func__);
+ 		}
+ 	}
+ 
+ 	if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+ 		if (cx23885_dvb_register(&dev->ts1) < 0) {
+ 			printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
+-			       __FUNCTION__);
++			       __func__);
++		}
++	} else
++	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
++		if (cx23885_417_register(dev) < 0) {
++			printk(KERN_ERR
++				"%s() Failed to register 417 on VID_B\n",
++			       __func__);
+ 		}
+ 	}
+ 
+ 	if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+ 		if (cx23885_dvb_register(&dev->ts2) < 0) {
+-			printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n",
+-			       __FUNCTION__);
++			printk(KERN_ERR
++				"%s() Failed to register dvb on VID_C\n",
++			       __func__);
++		}
++	} else
++	if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) {
++		if (cx23885_417_register(dev) < 0) {
++			printk(KERN_ERR
++				"%s() Failed to register 417 on VID_C\n",
++			       __func__);
+ 		}
+ 	}
+ 
+@@ -785,12 +804,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
+ 	if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
+ 		cx23885_video_unregister(dev);
+ 
+-	if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
++	if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+ 		cx23885_dvb_unregister(&dev->ts1);
+ 
+-	if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
++	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++		cx23885_417_unregister(dev);
++
++	if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+ 		cx23885_dvb_unregister(&dev->ts2);
+ 
++	if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
++		cx23885_417_unregister(dev);
++
+ 	cx23885_i2c_unregister(&dev->i2c_bus[2]);
+ 	cx23885_i2c_unregister(&dev->i2c_bus[1]);
+ 	cx23885_i2c_unregister(&dev->i2c_bus[0]);
+@@ -952,7 +977,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
+ 	videobuf_waiton(&buf->vb, 0, 0);
+ 	videobuf_dma_unmap(q, dma);
+ 	videobuf_dma_free(dma);
+-	btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
++	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+ 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ }
+ 
+@@ -960,50 +985,50 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
+ {
+ 	struct cx23885_dev *dev = port->dev;
+ 
+-	dprintk(1, "%s() Register Dump\n", __FUNCTION__);
+-	dprintk(1, "%s() DEV_CNTRL2               0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() Register Dump\n", __func__);
++	dprintk(1, "%s() DEV_CNTRL2               0x%08X\n", __func__,
+ 		cx_read(DEV_CNTRL2));
+-	dprintk(1, "%s() PCI_INT_MSK              0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() PCI_INT_MSK              0x%08X\n", __func__,
+ 		cx_read(PCI_INT_MSK));
+-	dprintk(1, "%s() AUD_INT_INT_MSK          0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() AUD_INT_INT_MSK          0x%08X\n", __func__,
+ 		cx_read(AUDIO_INT_INT_MSK));
+-	dprintk(1, "%s() AUD_INT_DMA_CTL          0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() AUD_INT_DMA_CTL          0x%08X\n", __func__,
+ 		cx_read(AUD_INT_DMA_CTL));
+-	dprintk(1, "%s() AUD_EXT_INT_MSK          0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() AUD_EXT_INT_MSK          0x%08X\n", __func__,
+ 		cx_read(AUDIO_EXT_INT_MSK));
+-	dprintk(1, "%s() AUD_EXT_DMA_CTL          0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() AUD_EXT_DMA_CTL          0x%08X\n", __func__,
+ 		cx_read(AUD_EXT_DMA_CTL));
+-	dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __func__,
+ 		cx_read(PAD_CTRL));
+-	dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __func__,
+ 		cx_read(ALT_PIN_OUT_SEL));
+-	dprintk(1, "%s() GPIO2                    0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() GPIO2                    0x%08X\n", __func__,
+ 		cx_read(GPIO2));
+-	dprintk(1, "%s() gpcnt(0x%08X)          0x%08X\n", __FUNCTION__,
++	dprintk(1, "%s() gpcnt(0x%08X)          0x%08X\n", __func__,
+ 		port->reg_gpcnt, cx_read(port->reg_gpcnt));
+-	dprintk(1, "%s() gpcnt_ctl(0x%08X)      0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() gpcnt_ctl(0x%08X)      0x%08x\n", __func__,
+ 		port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
+-	dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __func__,
+ 		port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
+-	dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __func__,
+ 		port->reg_src_sel, cx_read(port->reg_src_sel));
+-	dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __func__,
+ 		port->reg_lngth, cx_read(port->reg_lngth));
+-	dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __func__,
+ 		port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl));
+-	dprintk(1, "%s() gen_ctrl(0x%08X)       0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() gen_ctrl(0x%08X)       0x%08x\n", __func__,
+ 		port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
+-	dprintk(1, "%s() bd_pkt_status(0x%08X)  0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() bd_pkt_status(0x%08X)  0x%08x\n", __func__,
+ 		port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status));
+-	dprintk(1, "%s() sop_status(0x%08X)     0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() sop_status(0x%08X)     0x%08x\n", __func__,
+ 		port->reg_sop_status, cx_read(port->reg_sop_status));
+-	dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __func__,
+ 		port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat));
+-	dprintk(1, "%s() vld_misc(0x%08X)       0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() vld_misc(0x%08X)       0x%08x\n", __func__,
+ 		port->reg_vld_misc, cx_read(port->reg_vld_misc));
+-	dprintk(1, "%s() ts_clk_en(0x%08X)      0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() ts_clk_en(0x%08X)      0x%08x\n", __func__,
+ 		port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en));
+-	dprintk(1, "%s() ts_int_msk(0x%08X)     0x%08x\n", __FUNCTION__,
++	dprintk(1, "%s() ts_int_msk(0x%08X)     0x%08x\n", __func__,
+ 		port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
+ }
+ 
+@@ -1012,8 +1037,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+ 			     struct cx23885_buffer   *buf)
+ {
+ 	struct cx23885_dev *dev = port->dev;
++	u32 reg;
+ 
+-	dprintk(1, "%s() w: %d, h: %d, f: %d\n", __FUNCTION__,
++	dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
+ 		buf->vb.width, buf->vb.height, buf->vb.field);
+ 
+ 	/* setup fifo + format */
+@@ -1031,21 +1057,24 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+ 	if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
+ 		(!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) {
+ 		printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",
+-			__FUNCTION__,
++			__func__,
+ 			cx23885_boards[dev->board].portb,
+ 			cx23885_boards[dev->board].portc );
+ 		return -EINVAL;
+ 	}
+ 
++	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++		cx23885_av_clk(dev, 0);
++
+ 	udelay(100);
+ 
+ 	/* If the port supports SRC SELECT, configure it */
+ 	if(port->reg_src_sel)
+ 		cx_write(port->reg_src_sel, port->src_sel_val);
+ 
+-	cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4);
++	cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
+ 	cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
+-	cx_write(port->reg_vld_misc, 0x00);
++	cx_write(port->reg_vld_misc, port->vld_misc_val);
+ 	cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
+ 	udelay(100);
+ 
+@@ -1054,11 +1083,26 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+ 	cx_write(port->reg_gpcnt_ctl, 3);
+ 	q->count = 1;
+ 
++	if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
++
++		reg = cx_read(PAD_CTRL);
++		reg = reg & ~0x1;    /* Clear TS1_OE */
++
++		/* FIXME, bit 2 writing here is questionable */
++		/* set TS1_SOP_OE and TS1_OE_HI */
++		reg = reg | 0xa;
++		cx_write(PAD_CTRL, reg);
++
++		/* FIXME and these two registers should be documented. */
++		cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011);
++		cx_write(ALT_PIN_OUT_SEL, 0x10100045);
++	}
++
+ 	switch(dev->bridge) {
+ 	case CX23885_BRIDGE_885:
+ 	case CX23885_BRIDGE_887:
+ 		/* enable irqs */
+-		dprintk(1, "%s() enabling TS int's and DMA\n", __FUNCTION__ );
++		dprintk(1, "%s() enabling TS int's and DMA\n", __func__ );
+ 		cx_set(port->reg_ts_int_msk,  port->ts_int_msk_val);
+ 		cx_set(port->reg_dma_ctl, port->dma_ctl_val);
+ 		cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
+@@ -1069,6 +1113,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+ 
+ 	cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
+ 
++	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++		cx23885_av_clk(dev, 1);
++
+ 	if (debug > 4)
+ 		cx23885_tsport_reg_dump(port);
+ 
+@@ -1078,12 +1125,32 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+ static int cx23885_stop_dma(struct cx23885_tsport *port)
+ {
+ 	struct cx23885_dev *dev = port->dev;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	u32 reg;
++
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	/* Stop interrupts and DMA */
+ 	cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
+ 	cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+ 
++	if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
++
++		reg = cx_read(PAD_CTRL);
++
++		/* Set TS1_OE */
++		reg = reg | 0x1;
++
++		/* clear TS1_SOP_OE and TS1_OE_HI */
++		reg = reg & ~0xa;
++		cx_write(PAD_CTRL, reg);
++		cx_write(port->reg_src_sel, 0);
++		cx_write(port->reg_gen_ctrl, 8);
++
++	}
++
++	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++		cx23885_av_clk(dev, 0);
++
+ 	return 0;
+ }
+ 
+@@ -1093,13 +1160,13 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
+ 	struct cx23885_dev *dev = port->dev;
+ 	struct cx23885_buffer *buf;
+ 
+-	dprintk(5, "%s()\n", __FUNCTION__);
++	dprintk(5, "%s()\n", __func__);
+ 	if (list_empty(&q->active))
+ 	{
+ 		struct cx23885_buffer *prev;
+ 		prev = NULL;
+ 
+-		dprintk(5, "%s() queue is empty\n", __FUNCTION__);
++		dprintk(5, "%s() queue is empty\n", __func__);
+ 
+ 		for (;;) {
+ 			if (list_empty(&q->queued))
+@@ -1154,7 +1221,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
+ 	int size = port->ts_packet_size * port->ts_packet_count;
+ 	int rc;
+ 
+-	dprintk(1, "%s: %p\n", __FUNCTION__, buf);
++	dprintk(1, "%s: %p\n", __func__, buf);
+ 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+ 		return -EINVAL;
+ 
+@@ -1197,7 +1264,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
+ 		buf->count    = cx88q->count++;
+ 		mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
+ 		dprintk(1, "[%p/%d] %s - first active\n",
+-			buf, buf->vb.i, __FUNCTION__);
++			buf, buf->vb.i, __func__);
+ 	} else {
+ 		dprintk( 1, "queue is not empty - append to active\n" );
+ 		prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
+@@ -1208,7 +1275,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
+ 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ 		prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
+ 		dprintk( 1, "[%p/%d] %s - append to active\n",
+-			 buf, buf->vb.i, __FUNCTION__);
++			 buf, buf->vb.i, __func__);
+ 	}
+ }
+ 
+@@ -1239,13 +1306,23 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
+ 	spin_unlock_irqrestore(&port->slock, flags);
+ }
+ 
++void cx23885_cancel_buffers(struct cx23885_tsport *port)
++{
++	struct cx23885_dev *dev = port->dev;
++	struct cx23885_dmaqueue *q = &port->mpegq;
++
++	dprintk(1, "%s()\n", __FUNCTION__);
++	del_timer_sync(&q->timeout);
++	cx23885_stop_dma(port);
++	do_cancel_buffers(port, "cancel", 0);
++}
+ 
+ static void cx23885_timeout(unsigned long data)
+ {
+ 	struct cx23885_tsport *port = (struct cx23885_tsport *)data;
+ 	struct cx23885_dev *dev = port->dev;
+ 
+-	dprintk(1, "%s()\n",__FUNCTION__);
++	dprintk(1, "%s()\n",__func__);
+ 
+ 	if (debug > 5)
+ 		cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
+@@ -1254,16 +1331,77 @@ static void cx23885_timeout(unsigned long data)
+ 	do_cancel_buffers(port, "timeout", 1);
+ }
+ 
++int cx23885_irq_417(struct cx23885_dev *dev, u32 status)
++{
++	/* FIXME: port1 assumption here. */
++	struct cx23885_tsport *port = &dev->ts1;
++	int count = 0;
++	int handled = 0;
++
++	if (status == 0)
++		return handled;
++
++	count = cx_read(port->reg_gpcnt);
++	dprintk(7, "status: 0x%08x  mask: 0x%08x count: 0x%x\n",
++		status, cx_read(port->reg_ts_int_msk), count);
++
++	if ((status & VID_B_MSK_BAD_PKT)         ||
++		(status & VID_B_MSK_OPC_ERR)     ||
++		(status & VID_B_MSK_VBI_OPC_ERR) ||
++		(status & VID_B_MSK_SYNC)        ||
++		(status & VID_B_MSK_VBI_SYNC)    ||
++		(status & VID_B_MSK_OF)          ||
++		(status & VID_B_MSK_VBI_OF)) {
++		printk(KERN_ERR "%s: V4L mpeg risc op code error, status "
++			"= 0x%x\n", dev->name, status);
++		if (status & VID_B_MSK_BAD_PKT)
++			dprintk(1, "        VID_B_MSK_BAD_PKT\n");
++		if (status & VID_B_MSK_OPC_ERR)
++			dprintk(1, "        VID_B_MSK_OPC_ERR\n");
++		if (status & VID_B_MSK_VBI_OPC_ERR)
++			dprintk(1, "        VID_B_MSK_VBI_OPC_ERR\n");
++		if (status & VID_B_MSK_SYNC)
++			dprintk(1, "        VID_B_MSK_SYNC\n");
++		if (status & VID_B_MSK_VBI_SYNC)
++			dprintk(1, "        VID_B_MSK_VBI_SYNC\n");
++		if (status & VID_B_MSK_OF)
++			dprintk(1, "        VID_B_MSK_OF\n");
++		if (status & VID_B_MSK_VBI_OF)
++			dprintk(1, "        VID_B_MSK_VBI_OF\n");
++
++		cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
++		cx23885_sram_channel_dump(dev,
++			&dev->sram_channels[port->sram_chno]);
++		cx23885_417_check_encoder(dev);
++	} else if (status & VID_B_MSK_RISCI1) {
++		dprintk(7, "        VID_B_MSK_RISCI1\n");
++		spin_lock(&port->slock);
++		cx23885_wakeup(port, &port->mpegq, count);
++		spin_unlock(&port->slock);
++	} else if (status & VID_B_MSK_RISCI2) {
++		dprintk(7, "        VID_B_MSK_RISCI2\n");
++		spin_lock(&port->slock);
++		cx23885_restart_queue(port, &port->mpegq);
++		spin_unlock(&port->slock);
++	}
++	if (status) {
++		cx_write(port->reg_ts_int_stat, status);
++		handled = 1;
++	}
++
++	return handled;
++}
++
+ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
+ {
+ 	struct cx23885_dev *dev = port->dev;
+ 	int handled = 0;
+ 	u32 count;
+ 
+-	if ( (status & VID_BC_MSK_OPC_ERR) ||
+-	     (status & VID_BC_MSK_BAD_PKT) ||
+-	     (status & VID_BC_MSK_SYNC) ||
+-	     (status & VID_BC_MSK_OF))
++	if ((status & VID_BC_MSK_OPC_ERR) ||
++		(status & VID_BC_MSK_BAD_PKT) ||
++		(status & VID_BC_MSK_SYNC) ||
++		(status & VID_BC_MSK_OF))
+ 	{
+ 		if (status & VID_BC_MSK_OPC_ERR)
+ 			dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);
+@@ -1277,7 +1415,8 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
+ 		printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
+ 
+ 		cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+-		cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
++		cx23885_sram_channel_dump(dev,
++			&dev->sram_channels[port->sram_chno]);
+ 
+ 	} else if (status & VID_BC_MSK_RISCI1) {
+ 
+@@ -1378,11 +1517,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
+ 	if (ts1_status) {
+ 		if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+ 			handled += cx23885_irq_ts(ts1, ts1_status);
++		else
++		if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++			handled += cx23885_irq_417(dev, ts1_status);
+ 	}
+ 
+ 	if (ts2_status) {
+ 		if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+ 			handled += cx23885_irq_ts(ts2, ts2_status);
++		else
++		if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
++			handled += cx23885_irq_417(dev, ts2_status);
+ 	}
+ 
+ 	if (vida_status)
+@@ -1422,7 +1567,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
+ 	printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
+ 	       "latency: %d, mmio: 0x%llx\n", dev->name,
+ 	       pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+-	       dev->pci_lat, (unsigned long long)pci_resource_start(pci_dev,0));
++	       dev->pci_lat,
++		(unsigned long long)pci_resource_start(pci_dev, 0));
+ 
+ 	pci_set_master(pci_dev);
+ 	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
+index ed465c0..f056497 100644
+--- a/drivers/media/video/cx23885/cx23885-dvb.c
++++ b/drivers/media/video/cx23885/cx23885-dvb.c
+@@ -36,9 +36,12 @@
+ #include "tda18271.h"
+ #include "lgdt330x.h"
+ #include "xc5000.h"
++#include "tda10048.h"
+ #include "dvb-pll.h"
+ #include "tuner-xc2028.h"
+-#include "tuner-xc2028-types.h"
++#include "tuner-simple.h"
++#include "dib7000p.h"
++#include "dibx000_common.h"
+ 
+ static unsigned int debug;
+ 
+@@ -53,6 +56,8 @@ static unsigned int alt_tuner;
+ module_param(alt_tuner, int, 0644);
+ MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* ------------------------------------------------------------------ */
+ 
+ static int dvb_buf_setup(struct videobuf_queue *q,
+@@ -104,6 +109,13 @@ static struct s5h1409_config hauppauge_generic_config = {
+ 	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+ };
+ 
++static struct tda10048_config hauppauge_hvr1200_config = {
++	.demod_address    = 0x10 >> 1,
++	.output_mode      = TDA10048_SERIAL_OUTPUT,
++	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
++	.inversion        = TDA10048_INVERSION_ON
++};
++
+ static struct s5h1409_config hauppauge_ezqam_config = {
+ 	.demod_address = 0x32 >> 1,
+ 	.output_mode   = S5H1409_SERIAL_OUTPUT,
+@@ -164,8 +176,10 @@ static struct tda829x_config tda829x_no_probe = {
+ };
+ 
+ static struct tda18271_std_map hauppauge_tda18271_std_map = {
+-	.atsc_6   = { .if_freq = 5380, .std_bits = 0x1b },
+-	.qam_6    = { .if_freq = 4000, .std_bits = 0x18 },
++	.atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
++		      .if_lvl = 6, .rfagc_top = 0x37 },
++	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
++		      .if_lvl = 6, .rfagc_top = 0x37 },
+ };
+ 
+ static struct tda18271_config hauppauge_tda18271_config = {
+@@ -173,6 +187,96 @@ static struct tda18271_config hauppauge_tda18271_config = {
+ 	.gate    = TDA18271_GATE_ANALOG,
+ };
+ 
++static struct tda18271_config hauppauge_hvr1200_tuner_config = {
++	.gate    = TDA18271_GATE_ANALOG,
++};
++
++static struct dibx000_agc_config xc3028_agc_config = {
++	BAND_VHF | BAND_UHF,	/* band_caps */
++
++	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
++	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
++	 * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0,
++	 * P_agc_nb_est=2, P_agc_write=0
++	 */
++	(0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
++		(3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
++
++	712,	/* inv_gain */
++	21,	/* time_stabiliz */
++
++	0,	/* alpha_level */
++	118,	/* thlock */
++
++	0,	/* wbd_inv */
++	2867,	/* wbd_ref */
++	0,	/* wbd_sel */
++	2,	/* wbd_alpha */
++
++	0,	/* agc1_max */
++	0,	/* agc1_min */
++	39718,	/* agc2_max */
++	9930,	/* agc2_min */
++	0,	/* agc1_pt1 */
++	0,	/* agc1_pt2 */
++	0,	/* agc1_pt3 */
++	0,	/* agc1_slope1 */
++	0,	/* agc1_slope2 */
++	0,	/* agc2_pt1 */
++	128,	/* agc2_pt2 */
++	29,	/* agc2_slope1 */
++	29,	/* agc2_slope2 */
++
++	17,	/* alpha_mant */
++	27,	/* alpha_exp */
++	23,	/* beta_mant */
++	51,	/* beta_exp */
++
++	1,	/* perform_agc_softsplit */
++};
++
++/* PLL Configuration for COFDM BW_MHz = 8.000000
++ * With external clock = 30.000000 */
++static struct dibx000_bandwidth_config xc3028_bw_config = {
++	60000,	/* internal */
++	30000,	/* sampling */
++	1,	/* pll_cfg: prediv */
++	8,	/* pll_cfg: ratio */
++	3,	/* pll_cfg: range */
++	1,	/* pll_cfg: reset */
++	0,	/* pll_cfg: bypass */
++	0,	/* misc: refdiv */
++	0,	/* misc: bypclk_div */
++	1,	/* misc: IO_CLK_en_core */
++	1,	/* misc: ADClkSrc */
++	0,	/* misc: modulo */
++	(3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
++	(1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
++	20452225, /* timf */
++	30000000  /* xtal_hz */
++};
++
++static struct dib7000p_config hauppauge_hvr1400_dib7000_config = {
++	.output_mpeg2_in_188_bytes = 1,
++	.hostbus_diversity = 1,
++	.tuner_is_baseband = 0,
++	.update_lna  = NULL,
++
++	.agc_config_count = 1,
++	.agc = &xc3028_agc_config,
++	.bw  = &xc3028_bw_config,
++
++	.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
++	.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
++	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
++
++	.pwm_freq_div = 0,
++	.agc_control  = NULL,
++	.spur_protect = 0,
++
++	.output_mode = OUTMODE_MPEG2_SERIAL,
++};
++
+ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
+ {
+ 	struct cx23885_tsport *port = ptr;
+@@ -182,7 +286,7 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
+ 	case XC2028_TUNER_RESET:
+ 		/* Send the tuner in then out of reset */
+ 		/* GPIO-2 xc3028 tuner */
+-		dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
++		dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
+ 
+ 		cx_set(GP0_IO, 0x00040000);
+ 		cx_clear(GP0_IO, 0x00000004);
+@@ -192,10 +296,10 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
+ 		msleep(5);
+ 		break;
+ 	case XC2028_RESET_CLK:
+-		dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
++		dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
+ 		break;
+ 	default:
+-		dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__,
++		dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
+ 			command, arg);
+ 		return -EINVAL;
+ 	}
+@@ -271,8 +375,9 @@ static int dvb_register(struct cx23885_tsport *port)
+ 						&fusionhdtv_5_express,
+ 						&i2c_bus->i2c_adap);
+ 		if (port->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, port->dvb.frontend, 0x61,
+-				   &i2c_bus->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
++			dvb_attach(simple_tuner_attach, port->dvb.frontend,
++				   &i2c_bus->i2c_adap, 0x61,
++				   TUNER_LG_TDVS_H06XF);
+ 		}
+ 		break;
+ 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+@@ -297,13 +402,52 @@ static int dvb_register(struct cx23885_tsport *port)
+ 			struct xc2028_config cfg = {
+ 				.i2c_adap  = &i2c_bus->i2c_adap,
+ 				.i2c_addr  = 0x61,
+-				.video_dev = port,
+ 				.callback  = cx23885_hvr1500_xc3028_callback,
+ 			};
+ 			static struct xc2028_ctrl ctl = {
+ 				.fname       = "xc3028-v27.fw",
+ 				.max_len     = 64,
+-				.scode_table = OREN538,
++				.scode_table = XC3028_FE_OREN538,
++			};
++
++			fe = dvb_attach(xc2028_attach,
++					port->dvb.frontend, &cfg);
++			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
++				fe->ops.tuner_ops.set_config(fe, &ctl);
++		}
++		break;
++	case CX23885_BOARD_HAUPPAUGE_HVR1200:
++	case CX23885_BOARD_HAUPPAUGE_HVR1700:
++		i2c_bus = &dev->i2c_bus[0];
++		port->dvb.frontend = dvb_attach(tda10048_attach,
++			&hauppauge_hvr1200_config,
++			&i2c_bus->i2c_adap);
++		if (port->dvb.frontend != NULL) {
++			dvb_attach(tda829x_attach, port->dvb.frontend,
++				&dev->i2c_bus[1].i2c_adap, 0x42,
++				&tda829x_no_probe);
++			dvb_attach(tda18271_attach, port->dvb.frontend,
++				0x60, &dev->i2c_bus[1].i2c_adap,
++				&hauppauge_hvr1200_tuner_config);
++		}
++		break;
++	case CX23885_BOARD_HAUPPAUGE_HVR1400:
++		i2c_bus = &dev->i2c_bus[0];
++		port->dvb.frontend = dvb_attach(dib7000p_attach,
++			&i2c_bus->i2c_adap,
++			0x12, &hauppauge_hvr1400_dib7000_config);
++		if (port->dvb.frontend != NULL) {
++			struct dvb_frontend *fe;
++			struct xc2028_config cfg = {
++				.i2c_adap  = &dev->i2c_bus[1].i2c_adap,
++				.i2c_addr  = 0x64,
++				.callback  = cx23885_hvr1500_xc3028_callback,
++			};
++			static struct xc2028_ctrl ctl = {
++				.fname   = "xc3028L-v36.fw",
++				.max_len = 64,
++				.demod   = 5000,
++				.d2633   = 1
+ 			};
+ 
+ 			fe = dvb_attach(xc2028_attach,
+@@ -330,7 +474,7 @@ static int dvb_register(struct cx23885_tsport *port)
+ 
+ 	/* register everything */
+ 	return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
+-				     &dev->pci->dev);
++				     &dev->pci->dev, adapter_nr);
+ }
+ 
+ int cx23885_dvb_register(struct cx23885_tsport *port)
+@@ -338,7 +482,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
+ 	struct cx23885_dev *dev = port->dev;
+ 	int err;
+ 
+-	dprintk(1, "%s\n", __FUNCTION__);
++	dprintk(1, "%s\n", __func__);
+ 	dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ 		dev->board,
+ 		dev->name,
+@@ -349,12 +493,12 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
+ 
+ 	/* dvb stuff */
+ 	printk("%s: cx23885 based dvb card\n", dev->name);
+-	videobuf_queue_pci_init(&port->dvb.dvbq, &dvb_qops, dev->pci, &port->slock,
++	videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
+ 			    sizeof(struct cx23885_buffer), port);
+ 	err = dvb_register(port);
+ 	if (err != 0)
+-		printk("%s() dvb_register failed err = %d\n", __FUNCTION__, err);
++		printk("%s() dvb_register failed err = %d\n", __func__, err);
+ 
+ 	return err;
+ }
+diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
+index 92fe0bd..c6bb0a0 100644
+--- a/drivers/media/video/cx23885/cx23885-i2c.c
++++ b/drivers/media/video/cx23885/cx23885-i2c.c
+@@ -33,7 +33,7 @@ static unsigned int i2c_debug;
+ module_param(i2c_debug, int, 0644);
+ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+ 
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, 0444);
+ MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+ 
+@@ -87,10 +87,10 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+ 	int retval, cnt;
+ 
+ 	if (joined_rlen)
+-		dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__,
++		dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
+ 			msg->len, joined_rlen);
+ 	else
+-		dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
++		dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+ 
+ 	/* Deal with i2c probe functions with zero payload */
+ 	if (msg->len == 0) {
+@@ -101,7 +101,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+ 		if (!i2c_slave_did_ack(i2c_adap))
+ 			return -EIO;
+ 
+-		dprintk(1, "%s() returns 0\n", __FUNCTION__);
++		dprintk(1, "%s() returns 0\n", __func__);
+ 		return 0;
+ 	}
+ 
+@@ -176,7 +176,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+ 
+ 
+ 	if (i2c_debug && !joined)
+-		dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
++		dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+ 
+ 	/* Deal with i2c probe functions with zero payload */
+ 	if (msg->len == 0) {
+@@ -188,7 +188,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+ 			return -EIO;
+ 
+ 
+-		dprintk(1, "%s() returns 0\n", __FUNCTION__);
++		dprintk(1, "%s() returns 0\n", __func__);
+ 		return 0;
+ 	}
+ 
+@@ -238,11 +238,11 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
+ 	struct cx23885_dev *dev = bus->dev;
+ 	int i, retval = 0;
+ 
+-	dprintk(1, "%s(num = %d)\n", __FUNCTION__, num);
++	dprintk(1, "%s(num = %d)\n", __func__, num);
+ 
+ 	for (i = 0 ; i < num; i++) {
+ 		dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
+-			__FUNCTION__, num, msgs[i].addr, msgs[i].len);
++			__func__, num, msgs[i].addr, msgs[i].len);
+ 		if (msgs[i].flags & I2C_M_RD) {
+ 			/* read */
+ 			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+@@ -353,6 +353,8 @@ static struct i2c_client cx23885_i2c_client_template = {
+ };
+ 
+ static char *i2c_devs[128] = {
++	[0x10 >> 1]   = "tda10048",
++	[0x12 >> 1]   = "dib7000pc",
+ 	[ 0x1c >> 1 ] = "lgdt3303",
+ 	[ 0x86 >> 1 ] = "tda9887",
+ 	[ 0x32 >> 1 ] = "cx24227",
+@@ -360,7 +362,8 @@ static char *i2c_devs[128] = {
+ 	[ 0x84 >> 1 ] = "tda8295",
+ 	[ 0xa0 >> 1 ] = "eeprom",
+ 	[ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
+-	[ 0xc2 >> 1 ] = "tuner/mt2131/tda8275/xc5000",
++	[0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
++	[0xc8 >> 1]   = "tuner/xc3028L",
+ };
+ 
+ static void do_i2c_scan(char *name, struct i2c_client *c)
+@@ -383,7 +386,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
+ {
+ 	struct cx23885_dev *dev = bus->dev;
+ 
+-	dprintk(1, "%s(bus = %d)\n", __FUNCTION__, bus->nr);
++	dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+ 
+ 	memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template,
+ 	       sizeof(bus->i2c_adap));
+@@ -420,6 +423,29 @@ int cx23885_i2c_unregister(struct cx23885_i2c *bus)
+ 	return 0;
+ }
+ 
++void cx23885_av_clk(struct cx23885_dev *dev, int enable)
++{
++	/* write 0 to bus 2 addr 0x144 via i2x_xfer() */
++	char buffer[3];
++	struct i2c_msg msg;
++	dprintk(1, "%s(enabled = %d)\n", __func__, enable);
++
++	/* Register 0x144 */
++	buffer[0] = 0x01;
++	buffer[1] = 0x44;
++	if (enable == 1)
++		buffer[2] = 0x05;
++	else
++		buffer[2] = 0x00;
++
++	msg.addr = 0x44;
++	msg.flags = I2C_M_TEN;
++	msg.len = 3;
++	msg.buf = buffer;
++
++	i2c_xfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
++}
++
+ /* ----------------------------------------------------------------------- */
+ 
+ /*
+diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
+index d3c4d2c..8465221 100644
+--- a/drivers/media/video/cx23885/cx23885-video.c
++++ b/drivers/media/video/cx23885/cx23885-video.c
+@@ -141,7 +141,7 @@ static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
+ 		if (formats[i].fourcc == fourcc)
+ 			return formats+i;
+ 
+-	printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __FUNCTION__, fourcc);
++	printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+ 	return NULL;
+ }
+ 
+@@ -292,13 +292,13 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
+ 	}
+ 	if (bc != 1)
+ 		printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
+-			__FUNCTION__, bc);
++			__func__, bc);
+ }
+ 
+ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
+ {
+ 	dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
+-		__FUNCTION__,
++		__func__,
+ 		(unsigned int)norm,
+ 		v4l2_norm_to_name(norm));
+ 
+@@ -319,7 +319,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
+ 				    char *type)
+ {
+ 	struct video_device *vfd;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	vfd = video_device_alloc();
+ 	if (NULL == vfd)
+@@ -358,7 +358,7 @@ EXPORT_SYMBOL(cx23885_ctrl_query);
+ static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
+ 	unsigned int bit)
+ {
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	if (fh->resources & bit)
+ 		/* have it already allocated */
+ 		return 1;
+@@ -392,7 +392,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
+ 	unsigned int bits)
+ {
+ 	BUG_ON((fh->resources & bits) != bits);
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	mutex_lock(&dev->lock);
+ 	fh->resources  &= ~bits;
+@@ -407,7 +407,7 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
+ 	memset(&route, 0, sizeof(route));
+ 
+ 	dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+-		__FUNCTION__,
++		__func__,
+ 		input, INPUT(input)->vmux,
+ 		INPUT(input)->gpio0, INPUT(input)->gpio1,
+ 		INPUT(input)->gpio2, INPUT(input)->gpio3);
+@@ -427,7 +427,7 @@ EXPORT_SYMBOL(cx23885_video_mux);
+ int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
+ 	unsigned int height, enum v4l2_field field)
+ {
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	return 0;
+ }
+ 
+@@ -435,7 +435,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
+ 			   struct cx23885_dmaqueue *q,
+ 			   struct cx23885_buffer *buf)
+ {
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	/* setup fifo + format */
+ 	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
+@@ -463,7 +463,7 @@ static int cx23885_restart_video_queue(struct cx23885_dev *dev,
+ {
+ 	struct cx23885_buffer *buf, *prev;
+ 	struct list_head *item;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	if (!list_empty(&q->active)) {
+ 		buf = list_entry(q->active.next, struct cx23885_buffer,
+@@ -579,13 +579,13 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ 			if (dev->tvnorm & V4L2_STD_NTSC) {
+ 				/* cx25840 transmits NTSC bottom field first */
+ 				dprintk(1, "%s() Creating NTSC risc\n",
+-					__FUNCTION__);
++					__func__);
+ 				line0_offset = buf->bpl;
+ 				line1_offset = 0;
+ 			} else {
+ 				/* All other formats are top field first */
+ 				dprintk(1, "%s() Creating PAL/SECAM risc\n",
+-					__FUNCTION__);
++					__func__);
+ 				line0_offset = 0;
+ 				line1_offset = buf->bpl;
+ 			}
+@@ -765,8 +765,8 @@ static int video_open(struct inode *inode, struct file *file)
+ 	fh->height   = 240;
+ 	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+ 
+-	videobuf_queue_pci_init(&fh->vidq, &cx23885_video_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ 			    V4L2_FIELD_INTERLACED,
+ 			    sizeof(struct cx23885_buffer),
+@@ -885,7 +885,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
+ 
+ int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+ {
+-	dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __FUNCTION__);
++	dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
+ 	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
+ 	return 0;
+ }
+@@ -894,7 +894,7 @@ EXPORT_SYMBOL(cx23885_get_control);
+ int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+ {
+ 	dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
+-		" (disabled - no action)\n", __FUNCTION__);
++		" (disabled - no action)\n", __func__);
+ 	return 0;
+ }
+ EXPORT_SYMBOL(cx23885_set_control);
+@@ -990,7 +990,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ 	struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
+ 	int err;
+ 
+-	dprintk(2, "%s()\n", __FUNCTION__);
++	dprintk(2, "%s()\n", __func__);
+ 	err = vidioc_try_fmt_cap(file, priv, f);
+ 
+ 	if (0 != err)
+@@ -999,7 +999,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ 	fh->width      = f->fmt.pix.width;
+ 	fh->height     = f->fmt.pix.height;
+ 	fh->vidq.field = f->fmt.pix.field;
+-	dprintk(2, "%s() width=%d height=%d field=%d\n", __FUNCTION__,
++	dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
+ 		fh->width, fh->height, fh->vidq.field);
+ 	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f);
+ 	return 0;
+@@ -1101,7 +1101,7 @@ static int vidioc_streamon(struct file *file, void *priv,
+ {
+ 	struct cx23885_fh *fh = priv;
+ 	struct cx23885_dev *dev = fh->dev;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+ 		return -EINVAL;
+@@ -1118,7 +1118,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+ 	struct cx23885_fh *fh = priv;
+ 	struct cx23885_dev *dev = fh->dev;
+ 	int err, res;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ 		return -EINVAL;
+@@ -1136,7 +1136,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
+ {
+ 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	mutex_lock(&dev->lock);
+ 	cx23885_set_tvnorm(dev, *tvnorms);
+@@ -1159,7 +1159,7 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
+ 		[CX23885_VMUX_DEBUG]      = "for debug only",
+ 	};
+ 	unsigned int n;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 
+ 	n = i->index;
+ 	if (n >= 4)
+@@ -1184,7 +1184,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
+ 				struct v4l2_input *i)
+ {
+ 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	return cx23885_enum_input(dev, i);
+ }
+ 
+@@ -1193,7 +1193,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+ 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ 
+ 	*i = dev->input;
+-	dprintk(1, "%s() returns %d\n", __FUNCTION__, *i);
++	dprintk(1, "%s() returns %d\n", __func__, *i);
+ 	return 0;
+ }
+ 
+@@ -1201,10 +1201,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+ {
+ 	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ 
+-	dprintk(1, "%s(%d)\n", __FUNCTION__, i);
++	dprintk(1, "%s(%d)\n", __func__, i);
+ 
+ 	if (i >= 4) {
+-		dprintk(1, "%s() -EINVAL\n", __FUNCTION__);
++		dprintk(1, "%s() -EINVAL\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -1389,7 +1389,7 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
+ 		return handled;
+ 	cx_write(VID_A_INT_STAT, status);
+ 
+-	dprintk(2, "%s() status = 0x%08x\n", __FUNCTION__, status);
++	dprintk(2, "%s() status = 0x%08x\n", __func__, status);
+ 	/* risc op code error */
+ 	if (status & (1 << 16)) {
+ 		printk(KERN_WARNING "%s/0: video risc op code error\n",
+@@ -1487,7 +1487,7 @@ static const struct file_operations radio_fops = {
+ 
+ void cx23885_video_unregister(struct cx23885_dev *dev)
+ {
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	cx_clear(PCI_INT_MSK, 1);
+ 
+ 	if (dev->video_dev) {
+@@ -1505,7 +1505,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
+ {
+ 	int err;
+ 
+-	dprintk(1, "%s()\n", __FUNCTION__);
++	dprintk(1, "%s()\n", __func__);
+ 	spin_lock_init(&dev->slock);
+ 
+ 	/* Initialize VBI template */
+diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
+index 7cb2179..32af87f 100644
+--- a/drivers/media/video/cx23885/cx23885.h
++++ b/drivers/media/video/cx23885/cx23885.h
+@@ -32,6 +32,7 @@
+ 
+ #include "btcx-risc.h"
+ #include "cx23885-reg.h"
++#include "media/cx2341x.h"
+ 
+ #include <linux/version.h>
+ #include <linux/mutex.h>
+@@ -59,6 +60,9 @@
+ #define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP   4
+ #define CX23885_BOARD_HAUPPAUGE_HVR1500Q       5
+ #define CX23885_BOARD_HAUPPAUGE_HVR1500        6
++#define CX23885_BOARD_HAUPPAUGE_HVR1200        7
++#define CX23885_BOARD_HAUPPAUGE_HVR1700        8
++#define CX23885_BOARD_HAUPPAUGE_HVR1400        9
+ 
+ /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
+ #define CX23885_NORMS (\
+@@ -154,6 +158,7 @@ typedef enum {
+ 	CX23885_MPEG_UNDEFINED = 0,
+ 	CX23885_MPEG_DVB,
+ 	CX23885_ANALOG_VIDEO,
++	CX23885_MPEG_ENCODER,
+ } port_t;
+ 
+ struct cx23885_board {
+@@ -252,6 +257,8 @@ struct cx23885_tsport {
+ 	u32                        gen_ctrl_val;
+ 	u32                        ts_clk_en_val;
+ 	u32                        src_sel_val;
++	u32                        vld_misc_val;
++	u32                        hw_sop_ctrl_val;
+ };
+ 
+ struct cx23885_dev {
+@@ -312,6 +319,14 @@ struct cx23885_dev {
+ 	struct cx23885_dmaqueue    vidq;
+ 	struct cx23885_dmaqueue    vbiq;
+ 	spinlock_t                 slock;
++
++	/* MPEG Encoder ONLY settings */
++	u32                        cx23417_mailbox;
++	struct cx2341x_mpeg_params mpeg_params;
++	struct video_device        *v4l_device;
++	atomic_t                   v4l_reader_count;
++	struct cx23885_tvnorm      encodernorm;
++
+ };
+ 
+ extern struct list_head cx23885_devlist;
+@@ -431,6 +446,18 @@ extern int cx23885_i2c_register(struct cx23885_i2c *bus);
+ extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
+ extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
+ 				     void *arg);
++extern void cx23885_av_clk(struct cx23885_dev *dev, int enable);
++
++/* ----------------------------------------------------------- */
++/* cx23885-417.c                                               */
++extern int cx23885_417_register(struct cx23885_dev *dev);
++extern void cx23885_417_unregister(struct cx23885_dev *dev);
++extern int cx23885_irq_417(struct cx23885_dev *dev, u32 status);
++extern void cx23885_417_check_encoder(struct cx23885_dev *dev);
++extern void cx23885_mc417_init(struct cx23885_dev *dev);
++extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value);
++extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value);
++
+ 
+ /* ----------------------------------------------------------- */
+ /* tv norms                                                    */
+diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
+index 756a1ee..7fde678 100644
+--- a/drivers/media/video/cx25840/cx25840-core.c
++++ b/drivers/media/video/cx25840/cx25840-core.c
+@@ -352,7 +352,7 @@ static void cx23885_initialize(struct i2c_client *client)
+ static void input_change(struct i2c_client *client)
+ {
+ 	struct cx25840_state *state = i2c_get_clientdata(client);
+-	v4l2_std_id std = cx25840_get_v4lstd(client);
++	v4l2_std_id std = state->std;
+ 
+ 	/* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
+ 	if (std & V4L2_STD_SECAM) {
+@@ -523,32 +523,34 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
+ 
+ /* ----------------------------------------------------------------------- */
+ 
+-static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
++static int set_v4lstd(struct i2c_client *client)
+ {
+-	u8 fmt=0; 	/* zero is autodetect */
++	struct cx25840_state *state = i2c_get_clientdata(client);
++	u8 fmt = 0; 	/* zero is autodetect */
++	u8 pal_m = 0;
+ 
+ 	/* First tests should be against specific std */
+-	if (std == V4L2_STD_NTSC_M_JP) {
+-		fmt=0x2;
+-	} else if (std == V4L2_STD_NTSC_443) {
+-		fmt=0x3;
+-	} else if (std == V4L2_STD_PAL_M) {
+-		fmt=0x5;
+-	} else if (std == V4L2_STD_PAL_N) {
+-		fmt=0x6;
+-	} else if (std == V4L2_STD_PAL_Nc) {
+-		fmt=0x7;
+-	} else if (std == V4L2_STD_PAL_60) {
+-		fmt=0x8;
++	if (state->std == V4L2_STD_NTSC_M_JP) {
++		fmt = 0x2;
++	} else if (state->std == V4L2_STD_NTSC_443) {
++		fmt = 0x3;
++	} else if (state->std == V4L2_STD_PAL_M) {
++		pal_m = 1;
++		fmt = 0x5;
++	} else if (state->std == V4L2_STD_PAL_N) {
++		fmt = 0x6;
++	} else if (state->std == V4L2_STD_PAL_Nc) {
++		fmt = 0x7;
++	} else if (state->std == V4L2_STD_PAL_60) {
++		fmt = 0x8;
+ 	} else {
+ 		/* Then, test against generic ones */
+-		if (std & V4L2_STD_NTSC) {
+-			fmt=0x1;
+-		} else if (std & V4L2_STD_PAL) {
+-			fmt=0x4;
+-		} else if (std & V4L2_STD_SECAM) {
+-			fmt=0xc;
+-		}
++		if (state->std & V4L2_STD_NTSC)
++			fmt = 0x1;
++		else if (state->std & V4L2_STD_PAL)
++			fmt = 0x4;
++		else if (state->std & V4L2_STD_SECAM)
++			fmt = 0xc;
+ 	}
+ 
+ 	v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
+@@ -563,42 +565,13 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
+ 		cx25840_and_or(client, 0x47b, ~6, 0);
+ 	}
+ 	cx25840_and_or(client, 0x400, ~0xf, fmt);
++	cx25840_and_or(client, 0x403, ~0x3, pal_m);
+ 	cx25840_vbi_setup(client);
++	if (!state->is_cx25836)
++		input_change(client);
+ 	return 0;
+ }
+ 
+-v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
+-{
+-	struct cx25840_state *state = i2c_get_clientdata(client);
+-	/* check VID_FMT_SEL first */
+-	u8 fmt = cx25840_read(client, 0x400) & 0xf;
+-
+-	if (!fmt) {
+-		/* check AFD_FMT_STAT if set to autodetect */
+-		fmt = cx25840_read(client, 0x40d) & 0xf;
+-	}
+-
+-	switch (fmt) {
+-	case 0x1:
+-	{
+-		/* if the audio std is A2-M, then this is the South Korean
+-		   NTSC standard */
+-		if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)
+-			return V4L2_STD_NTSC_M_KR;
+-		return V4L2_STD_NTSC_M;
+-	}
+-	case 0x2: return V4L2_STD_NTSC_M_JP;
+-	case 0x3: return V4L2_STD_NTSC_443;
+-	case 0x4: return V4L2_STD_PAL;
+-	case 0x5: return V4L2_STD_PAL_M;
+-	case 0x6: return V4L2_STD_PAL_N;
+-	case 0x7: return V4L2_STD_PAL_Nc;
+-	case 0x8: return V4L2_STD_PAL_60;
+-	case 0xc: return V4L2_STD_SECAM;
+-	default: return V4L2_STD_UNKNOWN;
+-	}
+-}
+-
+ /* ----------------------------------------------------------------------- */
+ 
+ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+@@ -718,9 +691,10 @@ static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
+ 
+ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
+ {
++	struct cx25840_state *state = i2c_get_clientdata(client);
+ 	struct v4l2_pix_format *pix;
+ 	int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
+-	int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
++	int is_50Hz = !(state->std & V4L2_STD_525_60);
+ 
+ 	switch (fmt->type) {
+ 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+@@ -1096,12 +1070,15 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
+ 	}
+ 
+ 	case VIDIOC_G_STD:
+-		*(v4l2_std_id *)arg = cx25840_get_v4lstd(client);
++		*(v4l2_std_id *)arg = state->std;
+ 		break;
+ 
+ 	case VIDIOC_S_STD:
++		if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
++			return 0;
+ 		state->radio = 0;
+-		return set_v4lstd(client, *(v4l2_std_id *)arg);
++		state->std = *(v4l2_std_id *)arg;
++		return set_v4lstd(client);
+ 
+ 	case AUDC_SET_RADIO:
+ 		state->radio = 1;
+@@ -1291,6 +1268,12 @@ static int cx25840_probe(struct i2c_client *client)
+ 	state->id = id;
+ 	state->rev = device_id;
+ 
++	if (state->is_cx23885) {
++		/* Drive GPIO2 direction and values */
++		cx25840_write(client, 0x160, 0x1d);
++		cx25840_write(client, 0x164, 0x00);
++	}
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h
+index 95093ed..8bf797f 100644
+--- a/drivers/media/video/cx25840/cx25840-core.h
++++ b/drivers/media/video/cx25840/cx25840-core.h
+@@ -38,6 +38,7 @@ struct cx25840_state {
+ 	struct i2c_client *c;
+ 	int pvr150_workaround;
+ 	int radio;
++	v4l2_std_id std;
+ 	enum cx25840_video_input vid_input;
+ 	enum cx25840_audio_input aud_input;
+ 	u32 audclk_freq;
+@@ -60,7 +61,6 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
+ u8 cx25840_read(struct i2c_client *client, u16 addr);
+ u32 cx25840_read4(struct i2c_client *client, u16 addr);
+ int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
+-v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client);
+ 
+ /* ----------------------------------------------------------------------- */
+ /* cx25850-firmware.c                                                      */
+diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c
+index 1ddf724..620d295 100644
+--- a/drivers/media/video/cx25840/cx25840-firmware.c
++++ b/drivers/media/video/cx25840/cx25840-firmware.c
+@@ -79,11 +79,9 @@ static int check_fw_load(struct i2c_client *client, int size)
+ 	return 0;
+ }
+ 
+-static int fw_write(struct i2c_client *client, u8 * data, int size)
++static int fw_write(struct i2c_client *client, u8 *data, int size)
+ {
+-	int sent;
+-
+-	if ((sent = i2c_master_send(client, data, size)) < size) {
++	if (i2c_master_send(client, data, size) < size) {
+ 		v4l_err(client, "firmware load i2c failure\n");
+ 		return -ENOSYS;
+ 	}
+@@ -96,7 +94,7 @@ int cx25840_loadfw(struct i2c_client *client)
+ 	struct cx25840_state *state = i2c_get_clientdata(client);
+ 	const struct firmware *fw = NULL;
+ 	u8 buffer[4], *ptr;
+-	int size, send, retval;
++	int size, retval;
+ 
+ 	if (state->is_cx23885)
+ 		firmware = FWFILE_CX23885;
+@@ -124,8 +122,7 @@ int cx25840_loadfw(struct i2c_client *client)
+ 	while (size > 0) {
+ 		ptr[0] = 0x08;
+ 		ptr[1] = 0x02;
+-		send = size > (FWSEND - 2) ? FWSEND : size + 2;
+-		retval = fw_write(client, ptr, send);
++		retval = fw_write(client, ptr, min(FWSEND, size + 2));
+ 
+ 		if (retval < 0) {
+ 			release_firmware(fw);
+diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
+index 6828f59..c754b9d 100644
+--- a/drivers/media/video/cx25840/cx25840-vbi.c
++++ b/drivers/media/video/cx25840/cx25840-vbi.c
+@@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p)
+ void cx25840_vbi_setup(struct i2c_client *client)
+ {
+ 	struct cx25840_state *state = i2c_get_clientdata(client);
+-	v4l2_std_id std = cx25840_get_v4lstd(client);
++	v4l2_std_id std = state->std;
+ 	int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
+ 	int luma_lpf,uv_lpf, comb;
+ 	u32 pll_int,pll_frac,pll_post;
+@@ -242,7 +242,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
+ 			0, 0, V4L2_SLICED_VPS, 0, 0,	/* 9 */
+ 			0, 0, 0, 0
+ 		};
+-		int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
++		int is_pal = !(state->std & V4L2_STD_525_60);
+ 		int i;
+ 
+ 		fmt = arg;
+@@ -279,7 +279,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
+ 
+ 	case VIDIOC_S_FMT:
+ 	{
+-		int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
++		int is_pal = !(state->std & V4L2_STD_525_60);
+ 		int vbi_offset = is_pal ? 1 : 0;
+ 		int i, x;
+ 		u8 lcr[24];
+diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
+index 49d3813..27635cd 100644
+--- a/drivers/media/video/cx88/Kconfig
++++ b/drivers/media/video/cx88/Kconfig
+@@ -57,6 +57,8 @@ config VIDEO_CX88_DVB
+ 	select DVB_NXT200X if !DVB_FE_CUSTOMISE
+ 	select DVB_CX24123 if !DVB_FE_CUSTOMISE
+ 	select DVB_ISL6421 if !DVB_FE_CUSTOMISE
++	select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
++	select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+ 	---help---
+ 	  This adds support for DVB/ATSC cards based on the
+ 	  Conexant 2388x chip.
+diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
+index 316b106..e976fc6 100644
+--- a/drivers/media/video/cx88/cx88-alsa.c
++++ b/drivers/media/video/cx88/cx88-alsa.c
+@@ -283,7 +283,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
+ 	BUG_ON(!chip->dma_size);
+ 
+ 	dprintk(2,"Freeing buffer\n");
+-	videobuf_pci_dma_unmap(chip->pci, chip->dma_risc);
++	videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc);
+ 	videobuf_dma_free(chip->dma_risc);
+ 	btcx_riscmem_free(chip->pci,&chip->buf->risc);
+ 	kfree(chip->buf);
+@@ -385,7 +385,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
+ 	BUG_ON(!chip->dma_size);
+ 	BUG_ON(chip->num_periods & (chip->num_periods-1));
+ 
+-	buf = videobuf_pci_alloc(sizeof(*buf));
++	buf = videobuf_sg_alloc(sizeof(*buf));
+ 	if (NULL == buf)
+ 		return -ENOMEM;
+ 
+@@ -396,14 +396,14 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
+ 	buf->vb.height = chip->num_periods;
+ 	buf->vb.size   = chip->dma_size;
+ 
+-	dma=videobuf_to_dma(&buf->vb);
++	dma = videobuf_to_dma(&buf->vb);
+ 	videobuf_dma_init(dma);
+ 	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+ 			(PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
+ 	if (ret < 0)
+ 		goto error;
+ 
+-	ret = videobuf_pci_dma_map(chip->pci,dma);
++	ret = videobuf_sg_dma_map(&chip->pci->dev, dma);
+ 	if (ret < 0)
+ 		goto error;
+ 
+@@ -494,7 +494,7 @@ static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
+ 
+ 	count = atomic_read(&chip->count);
+ 
+-//	dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__,
++//	dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__,
+ //		count, new, count & (runtime->periods-1),
+ //		runtime->period_size * (count & (runtime->periods-1)));
+ 	return runtime->period_size * (count & (runtime->periods-1));
+@@ -690,10 +690,8 @@ MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
+ static int snd_cx88_free(snd_cx88_card_t *chip)
+ {
+ 
+-	if (chip->irq >= 0){
+-		synchronize_irq(chip->irq);
++	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+-	}
+ 
+ 	cx88_core_put(chip->core,chip->pci);
+ 
+diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
+index a99e9d5..6c0c94c 100644
+--- a/drivers/media/video/cx88/cx88-blackbird.c
++++ b/drivers/media/video/cx88/cx88-blackbird.c
+@@ -45,7 +45,7 @@ static unsigned int mpegbufs = 32;
+ module_param(mpegbufs,int,0644);
+ MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
+ 
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug,int,0644);
+ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
+ 
+@@ -314,7 +314,7 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat
+ 	u32 value, flag, retval;
+ 	int i;
+ 
+-	dprintk(1,"%s: 0x%X\n", __FUNCTION__, command);
++	dprintk(1,"%s: 0x%X\n", __func__, command);
+ 
+ 	/* this may not be 100% safe if we can't read any memory location
+ 	   without side effects */
+@@ -546,10 +546,12 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
+ 		if (retval < 0)
+ 			return retval;
+ 
+-		dev->mailbox = blackbird_find_mailbox(dev);
+-		if (dev->mailbox < 0)
++		retval = blackbird_find_mailbox(dev);
++		if (retval < 0)
+ 			return -1;
+ 
++		dev->mailbox = retval;
++
+ 		retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+ 		if (retval < 0) {
+ 			dprintk(0, "ERROR: Firmware ping failed!\n");
+@@ -693,7 +695,7 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc
+ 		return -EINVAL;
+ 
+ 	/* Standard V4L2 controls */
+-	if (cx8800_ctrl_query(qctrl) == 0)
++	if (cx8800_ctrl_query(dev->core, qctrl) == 0)
+ 		return 0;
+ 
+ 	/* MPEG V4L2 controls */
+@@ -933,7 +935,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
+ 	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+ 	if (unlikely(qctrl->id == 0))
+ 		return -EINVAL;
+-	return cx8800_ctrl_query(qctrl);
++	return cx8800_ctrl_query(dev->core, qctrl);
+ }
+ 
+ static int vidioc_enum_input (struct file *file, void *priv,
+@@ -1055,7 +1057,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
+ 
+ 	dev = cx8802_get_device(inode);
+ 
+-	dprintk( 1, "%s\n", __FUNCTION__);
++	dprintk( 1, "%s\n", __func__);
+ 
+ 	if (dev == NULL)
+ 		return -ENODEV;
+@@ -1065,7 +1067,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
+ 	if (drv) {
+ 		err = drv->request_acquire(drv);
+ 		if(err != 0) {
+-			dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
++			dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
+ 			return err;
+ 		}
+ 	}
+@@ -1087,8 +1089,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
+ 	file->private_data = fh;
+ 	fh->dev      = dev;
+ 
+-	videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ 			    V4L2_FIELD_INTERLACED,
+ 			    sizeof(struct cx88_buffer),
+@@ -1284,7 +1286,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
+ 	struct cx8802_dev *dev = core->dvbdev;
+ 	int err;
+ 
+-	dprintk( 1, "%s\n", __FUNCTION__);
++	dprintk( 1, "%s\n", __func__);
+ 	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ 		core->boardnr,
+ 		core->name,
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index 8c9a8ad..2b6b283 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -44,6 +44,16 @@ static unsigned int latency = UNSET;
+ module_param(latency,int,0444);
+ MODULE_PARM_DESC(latency,"pci latency timer");
+ 
++#define info_printk(core, fmt, arg...) \
++	printk(KERN_INFO "%s: " fmt, core->name , ## arg)
++
++#define warn_printk(core, fmt, arg...) \
++	printk(KERN_WARNING "%s: " fmt, core->name , ## arg)
++
++#define err_printk(core, fmt, arg...) \
++	printk(KERN_ERR "%s: " fmt, core->name , ## arg)
++
++
+ /* ------------------------------------------------------------------ */
+ /* board config info                                                  */
+ 
+@@ -1354,6 +1364,10 @@ static const struct cx88_board cx88_boards[] = {
+ 		}},
+ 		/* fixme: Add radio support */
+ 		.mpeg           = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
++		.radio = {
++			.type   = CX88_RADIO,
++			.gpio0	= 0xe780,
++		},
+ 	},
+ 	[CX88_BOARD_ADSTECH_PTV_390] = {
+ 		.name           = "ADS Tech Instant Video PCI",
+@@ -1401,6 +1415,246 @@ static const struct cx88_board cx88_boards[] = {
+ 		}},
+ 		.mpeg           = CX88_MPEG_DVB,
+ 	},
++	[CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
++		.name           = "DViCO FusionHDTV 5 PCI nano",
++		/* xc3008 tuner, digital only for now */
++		.tuner_type     = TUNER_ABSENT,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.input          = {{
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++			.gpio0  = 0x000027df, /* Unconfirmed */
++		}, {
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0  = 0x000027df, /* Unconfirmed */
++			.audioroute = 1,
++		}, {
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio0  = 0x000027df, /* Unconfirmed */
++			.audioroute = 1,
++		} },
++		.mpeg           = CX88_MPEG_DVB,
++	},
++	[CX88_BOARD_PINNACLE_HYBRID_PCTV] = {
++		.name           = "Pinnacle Hybrid PCTV",
++		.tuner_type     = TUNER_XC2028,
++		.tuner_addr     = 0x61,
++		.input          = { {
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++		}, {
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++		}, {
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++		} },
++		.radio = {
++			.type   = CX88_RADIO,
++			.gpio0  = 0x004ff,
++			.gpio1  = 0x010ff,
++			.gpio2  = 0x0ff,
++		},
++	},
++	[CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
++		.name           = "Winfast TV2000 XP Global",
++		.tuner_type     = TUNER_XC2028,
++		.tuner_addr     = 0x61,
++		.input          = { {
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++			.gpio0  = 0x0400, /* pin 2:mute = 0 (off?) */
++			.gpio1  = 0x0000,
++			.gpio2  = 0x0800, /* pin 19:audio = 0 (tv) */
++
++		}, {
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0  = 0x0400, /* probably?  or 0x0404 to turn mute on */
++			.gpio1  = 0x0000,
++			.gpio2  = 0x0808, /* pin 19:audio = 1 (line) */
++
++		}, {
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++		} },
++		.radio = {
++			.type   = CX88_RADIO,
++			.gpio0  = 0x004ff,
++			.gpio1  = 0x010ff,
++			.gpio2  = 0x0ff,
++		},
++	},
++	[CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
++		.name           = "PowerColor Real Angel 330",
++		.tuner_type     = TUNER_XC2028,
++		.tuner_addr     = 0x61,
++		.input          = { {
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++			.gpio0 = 0x00ff,
++			.gpio1 = 0xf35d,
++			.gpio3 = 0x0000,
++		}, {
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0 = 0x00ff,
++			.gpio1 = 0xf37d,
++			.gpio3 = 0x0000,
++		}, {
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio0  = 0x000ff,
++			.gpio1  = 0x0f37d,
++			.gpio3  = 0x00000,
++		} },
++		.radio = {
++			.type   = CX88_RADIO,
++			.gpio0  = 0x000ff,
++			.gpio1  = 0x0f35d,
++			.gpio3  = 0x00000,
++		},
++	},
++	[CX88_BOARD_GENIATECH_X8000_MT] = {
++		/* Also PowerColor Real Angel 330 and Geniatech X800 OEM */
++		.name           = "Geniatech X8000-MT DVBT",
++		.tuner_type     = TUNER_XC2028,
++		.tuner_addr     = 0x61,
++		.input          = { {
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++			.gpio0  = 0x00000000,
++			.gpio1  = 0x00e3e341,
++			.gpio2  = 0x00000000,
++			.gpio3  = 0x00000000,
++		}, {
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0  = 0x00000000,
++			.gpio1  = 0x00e3e361,
++			.gpio2  = 0x00000000,
++			.gpio3  = 0x00000000,
++		}, {
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio0  = 0x00000000,
++			.gpio1  = 0x00e3e361,
++			.gpio2  = 0x00000000,
++			.gpio3  = 0x00000000,
++		} },
++		.radio = {
++			.type   = CX88_RADIO,
++			.gpio0  = 0x00000000,
++			.gpio1  = 0x00e3e341,
++			.gpio2  = 0x00000000,
++			.gpio3  = 0x00000000,
++		},
++		.mpeg           = CX88_MPEG_DVB,
++	},
++	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
++		.name           = "DViCO FusionHDTV DVB-T PRO",
++		.tuner_type     = TUNER_ABSENT, /* XXX: Has XC3028 */
++		.radio_type     = UNSET,
++		.tuner_addr     = ADDR_UNSET,
++		.radio_addr     = ADDR_UNSET,
++		.input          = { {
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0  = 0x000067df,
++		}, {
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio0  = 0x000067df,
++		} },
++		.mpeg           = CX88_MPEG_DVB,
++	},
++	[CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = {
++		.name           = "DViCO FusionHDTV 7 Gold",
++		.tuner_type     = TUNER_XC5000,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.input          = {{
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++			.gpio0  = 0x10df,
++		},{
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0  = 0x16d9,
++		},{
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio0  = 0x16d9,
++		}},
++		.mpeg           = CX88_MPEG_DVB,
++	},
++	[CX88_BOARD_PROLINK_PV_8000GT] = {
++		.name           = "Prolink Pixelview MPEG 8000GT",
++		.tuner_type     = TUNER_XC2028,
++		.tuner_addr     = 0x61,
++		.input          = { {
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++			.gpio0 = 0x0ff,
++			.gpio2 = 0x0cfb,
++		}, {
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio2 = 0x0cfb,
++		}, {
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio2 = 0x0cfb,
++		} },
++		.radio = {
++			.type   = CX88_RADIO,
++			.gpio2 = 0x0cfb,
++		},
++	},
++	/* Both radio, analog and ATSC work with this board.
++	   However, for analog to work, s5h1409 gate should be open,
++	   otherwise, tuner-xc3028 won't be detected.
++	   A proper fix require using the newer i2c methods to add
++	   tuner-xc3028 without doing an i2c probe.
++	 */
++	[CX88_BOARD_KWORLD_ATSC_120] = {
++		.name           = "Kworld PlusTV HD PCI 120 (ATSC 120)",
++		.tuner_type     = TUNER_XC2028,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.input          = { {
++			.type   = CX88_VMUX_TELEVISION,
++			.vmux   = 0,
++			.gpio0  = 0x000000ff,
++			.gpio1  = 0x0000f35d,
++			.gpio2  = 0x00000000,
++		}, {
++			.type   = CX88_VMUX_COMPOSITE1,
++			.vmux   = 1,
++			.gpio0  = 0x000000ff,
++			.gpio1  = 0x0000f37e,
++			.gpio2  = 0x00000000,
++		}, {
++			.type   = CX88_VMUX_SVIDEO,
++			.vmux   = 2,
++			.gpio0  = 0x000000ff,
++			.gpio1  = 0x0000f37e,
++			.gpio2  = 0x00000000,
++		} },
++		.radio = {
++			.type   = CX88_RADIO,
++			.gpio0  = 0x000000ff,
++			.gpio1  = 0x0000f35d,
++			.gpio2  = 0x00000000,
++		},
++		.mpeg           = CX88_MPEG_DVB,
++	},
+ };
+ 
+ /* ------------------------------------------------------------------ */
+@@ -1605,7 +1859,11 @@ static const struct cx88_subid cx88_subids[] = {
+ 		.subdevice = 0xdb11,
+ 		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+ 		/* Re-branded DViCO: UltraView DVB-T Plus */
+-	},{
++	}, {
++		.subvendor = 0x18ac,
++		.subdevice = 0xdb30,
++		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO,
++	}, {
+ 		.subvendor = 0x17de,
+ 		.subdevice = 0x0840,
+ 		.card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
+@@ -1714,6 +1972,38 @@ static const struct cx88_subid cx88_subids[] = {
+ 		.subvendor = 0x11bd,
+ 		.subdevice = 0x0051,
+ 		.card      = CX88_BOARD_PINNACLE_PCTV_HD_800i,
++	}, {
++		.subvendor = 0x18ac,
++		.subdevice = 0xd530,
++		.card      = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO,
++	}, {
++		.subvendor = 0x12ab,
++		.subdevice = 0x1788,
++		.card      = CX88_BOARD_PINNACLE_HYBRID_PCTV,
++	}, {
++		.subvendor = 0x14f1,
++		.subdevice = 0xea3d,
++		.card      = CX88_BOARD_POWERCOLOR_REAL_ANGEL,
++	}, {
++		.subvendor = 0x107d,
++		.subdevice = 0x6f18,
++		.card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
++	}, {
++		.subvendor = 0x14f1,
++		.subdevice = 0x8852,
++		.card      = CX88_BOARD_GENIATECH_X8000_MT,
++	}, {
++		.subvendor = 0x18ac,
++		.subdevice = 0xd610,
++		.card      = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD,
++	}, {
++		.subvendor = 0x1554,
++		.subdevice = 0x4935,
++		.card      = CX88_BOARD_PROLINK_PV_8000GT,
++	}, {
++		.subvendor = 0x17de,
++		.subdevice = 0x08c1,
++		.card      = CX88_BOARD_KWORLD_ATSC_120,
+ 	},
+ };
+ 
+@@ -1731,17 +2021,16 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ 	if (eeprom_data[4] != 0x7d ||
+ 	    eeprom_data[5] != 0x10 ||
+ 	    eeprom_data[7] != 0x66) {
+-		printk(KERN_WARNING "%s: Leadtek eeprom invalid.\n",
+-		       core->name);
++		warn_printk(core, "Leadtek eeprom invalid.\n");
+ 		return;
+ 	}
+ 
+ 	core->board.tuner_type = (eeprom_data[6] == 0x13) ?
+ 		TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3;
+ 
+-	printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
+-	       "tuner=%d, eeprom[0]=0x%02x\n",
+-	       core->name, core->board.tuner_type, eeprom_data[0]);
++	info_printk(core, "Leadtek Winfast 2000XP Expert config: "
++		    "tuner=%d, eeprom[0]=0x%02x\n",
++		    core->board.tuner_type, eeprom_data[0]);
+ }
+ 
+ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
+@@ -1785,13 +2074,12 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ 		/* known */
+ 		break;
+ 	default:
+-		printk("%s: warning: unknown hauppauge model #%d\n",
+-		       core->name, tv.model);
++		warn_printk(core, "warning: unknown hauppauge model #%d\n",
++			    tv.model);
+ 		break;
+ 	}
+ 
+-	printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+-			core->name, tv.model);
++	info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
+ }
+ 
+ /* ----------------------------------------------------------------------- */
+@@ -1837,8 +2125,7 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ 	char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
+ 		? gdi_tuner[eeprom_data[0x0d]].name : NULL;
+ 
+-	printk(KERN_INFO "%s: GDI: tuner=%s\n", core->name,
+-	       name ? name : "unknown");
++	info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
+ 	if (NULL == name)
+ 		return;
+ 	core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
+@@ -1846,6 +2133,75 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ 		CX88_RADIO : 0;
+ }
+ 
++/* ------------------------------------------------------------------- */
++/* some Divco specific stuff                                           */
++static int cx88_dvico_xc2028_callback(struct cx88_core *core,
++				      int command, int arg)
++{
++	switch (command) {
++	case XC2028_TUNER_RESET:
++		cx_write(MO_GP0_IO, 0x101000);
++		mdelay(5);
++		cx_set(MO_GP0_IO, 0x101010);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++
++/* ----------------------------------------------------------------------- */
++/* some Geniatech specific stuff                                           */
++
++static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core,
++						int command, int mode)
++{
++	switch (command) {
++	case XC2028_TUNER_RESET:
++		switch (INPUT(core->input).type) {
++		case CX88_RADIO:
++			break;
++		case CX88_VMUX_DVB:
++			cx_write(MO_GP1_IO, 0x030302);
++			mdelay(50);
++			break;
++		default:
++			cx_write(MO_GP1_IO, 0x030301);
++			mdelay(50);
++		}
++		cx_write(MO_GP1_IO, 0x101010);
++		mdelay(50);
++		cx_write(MO_GP1_IO, 0x101000);
++		mdelay(50);
++		cx_write(MO_GP1_IO, 0x101010);
++		mdelay(50);
++		return 0;
++	}
++	return -EINVAL;
++}
++
++/* ------------------------------------------------------------------- */
++/* some Divco specific stuff                                           */
++static int cx88_pv_8000gt_callback(struct cx88_core *core,
++				   int command, int arg)
++{
++	switch (command) {
++	case XC2028_TUNER_RESET:
++		cx_write(MO_GP2_IO, 0xcf7);
++		mdelay(50);
++		cx_write(MO_GP2_IO, 0xef5);
++		mdelay(50);
++		cx_write(MO_GP2_IO, 0xcf7);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
+ /* ----------------------------------------------------------------------- */
+ /* some DViCO specific stuff                                               */
+ 
+@@ -1874,32 +2230,85 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
+ 		msg.len = (i != 12 ? 5 : 2);
+ 		err = i2c_transfer(&core->i2c_adap, &msg, 1);
+ 		if (err != 1) {
+-			printk("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n", i, err);
++			warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d "
++					  "failed (err = %d)!\n", i, err);
+ 			return;
+ 		}
+ 	}
+ }
+ 
++static int cx88_xc2028_tuner_callback(struct cx88_core *core,
++				      int command, int arg)
++{
++	/* Board-specific callbacks */
++	switch (core->boardnr) {
++	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
++	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
++	case CX88_BOARD_GENIATECH_X8000_MT:
++	case CX88_BOARD_KWORLD_ATSC_120:
++		return cx88_xc3028_geniatech_tuner_callback(core,
++							command, arg);
++	case CX88_BOARD_PROLINK_PV_8000GT:
++		return cx88_pv_8000gt_callback(core, command, arg);
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++		return cx88_dvico_xc2028_callback(core, command, arg);
++	}
++
++	switch (command) {
++	case XC2028_TUNER_RESET:
++		switch (INPUT(core->input).type) {
++		case CX88_RADIO:
++			info_printk(core, "setting GPIO to radio!\n");
++			cx_write(MO_GP0_IO, 0x4ff);
++			mdelay(250);
++			cx_write(MO_GP2_IO, 0xff);
++			mdelay(250);
++			break;
++		case CX88_VMUX_DVB:	/* Digital TV*/
++		default:		/* Analog TV */
++			info_printk(core, "setting GPIO to TV!\n");
++			break;
++		}
++		cx_write(MO_GP1_IO, 0x101010);
++		mdelay(250);
++		cx_write(MO_GP1_IO, 0x101000);
++		mdelay(250);
++		cx_write(MO_GP1_IO, 0x101010);
++		mdelay(250);
++		return 0;
++	}
++	return -EINVAL;
++}
++
+ /* ----------------------------------------------------------------------- */
+ /* Tuner callback function. Currently only needed for the Pinnacle 	   *
+  * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both	   *
+  * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c)    */
+ 
+-int cx88_tuner_callback(void *priv, int command, int arg)
++static int cx88_xc5000_tuner_callback(struct cx88_core *core,
++				      int command, int arg)
+ {
+-	struct i2c_algo_bit_data *i2c_algo = priv;
+-	struct cx88_core *core = i2c_algo->data;
+-
+-	switch(core->boardnr) {
++	switch (core->boardnr) {
+ 	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+-		if(command == 0) { /* This is the reset command from xc5000 */
++		if (command == 0) { /* This is the reset command from xc5000 */
+ 			/* Reset XC5000 tuner via SYS_RSTO_pin */
+ 			cx_write(MO_SRST_IO, 0);
+ 			msleep(10);
+ 			cx_write(MO_SRST_IO, 1);
+ 			return 0;
++		} else {
++			err_printk(core, "xc5000: unknown tuner "
++				   "callback command.\n");
++			return -EINVAL;
+ 		}
+-		else {
++		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
++		if (command == 0) { /* This is the reset command from xc5000 */
++			cx_clear(MO_GP0_IO, 0x00000010);
++			msleep(10);
++			cx_set(MO_GP0_IO, 0x00000010);
++			return 0;
++		} else {
+ 			printk(KERN_ERR
+ 				"xc5000: unknown tuner callback command.\n");
+ 			return -EINVAL;
+@@ -1908,6 +2317,36 @@ int cx88_tuner_callback(void *priv, int command, int arg)
+ 	}
+ 	return 0; /* Should never be here */
+ }
++
++int cx88_tuner_callback(void *priv, int command, int arg)
++{
++	struct i2c_algo_bit_data *i2c_algo = priv;
++	struct cx88_core *core;
++
++	if (!i2c_algo) {
++		printk(KERN_ERR "cx88: Error - i2c private data undefined.\n");
++		return -EINVAL;
++	}
++
++	core = i2c_algo->data;
++
++	if (!core) {
++		printk(KERN_ERR "cx88: Error - device struct undefined.\n");
++		return -EINVAL;
++	}
++
++	switch (core->board.tuner_type) {
++		case TUNER_XC2028:
++			info_printk(core, "Calling XC2028/3028 callback\n");
++			return cx88_xc2028_tuner_callback(core, command, arg);
++		case TUNER_XC5000:
++			info_printk(core, "Calling XC5000 callback\n");
++			return cx88_xc5000_tuner_callback(core, command, arg);
++	}
++	err_printk(core, "Error: Calling callback for tuner %d\n",
++		   core->board.tuner_type);
++	return -EINVAL;
++}
+ EXPORT_SYMBOL(cx88_tuner_callback);
+ 
+ /* ----------------------------------------------------------------------- */
+@@ -1918,23 +2357,25 @@ static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
+ 
+ 	if (0 == pci->subsystem_vendor &&
+ 	    0 == pci->subsystem_device) {
+-		printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n"
++		printk(KERN_ERR
++		       "%s: Your board has no valid PCI Subsystem ID and thus can't\n"
+ 		       "%s: be autodetected.  Please pass card=<n> insmod option to\n"
+ 		       "%s: workaround that.  Redirect complaints to the vendor of\n"
+ 		       "%s: the TV card.  Best regards,\n"
+ 		       "%s:         -- tux\n",
+ 		       core->name,core->name,core->name,core->name,core->name);
+ 	} else {
+-		printk("%s: Your board isn't known (yet) to the driver.  You can\n"
++		printk(KERN_ERR
++		       "%s: Your board isn't known (yet) to the driver.  You can\n"
+ 		       "%s: try to pick one of the existing card configs via\n"
+ 		       "%s: card=<n> insmod option.  Updating to the latest\n"
+ 		       "%s: version might help as well.\n",
+ 		       core->name,core->name,core->name,core->name);
+ 	}
+-	printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+-	       core->name);
++	err_printk(core, "Here is a list of valid choices for the card=<n> "
++		   "insmod option:\n");
+ 	for (i = 0; i < ARRAY_SIZE(cx88_boards); i++)
+-		printk("%s:    card=%d -> %s\n",
++		printk(KERN_ERR "%s:    card=%d -> %s\n",
+ 		       core->name, i, cx88_boards[i].name);
+ }
+ 
+@@ -1951,9 +2392,57 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
+ 		cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
+ 		udelay(1000);
+ 		break;
++
++	case CX88_BOARD_PROLINK_PV_8000GT:
++		cx_write(MO_GP2_IO, 0xcf7);
++		mdelay(50);
++		cx_write(MO_GP2_IO, 0xef5);
++		mdelay(50);
++		cx_write(MO_GP2_IO, 0xcf7);
++		msleep(10);
++		break;
++
++	 case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
++		/* Enable the xc5000 tuner */
++		cx_set(MO_GP0_IO, 0x00001010);
++		break;
+ 	}
+ }
+ 
++/*
++ * Sets board-dependent xc3028 configuration
++ */
++void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
++{
++	memset(ctl, 0, sizeof(*ctl));
++
++	ctl->fname   = XC2028_DEFAULT_FIRMWARE;
++	ctl->max_len = 64;
++
++	switch (core->boardnr) {
++	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
++		/* Doesn't work with firmware version 2.7 */
++		ctl->fname = "xc3028-v25.fw";
++		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++		ctl->scode_table = XC3028_FE_ZARLINK456;
++		break;
++	case CX88_BOARD_KWORLD_ATSC_120:
++	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
++		ctl->demod = XC3028_FE_OREN538;
++		break;
++	case CX88_BOARD_PROLINK_PV_8000GT:
++		/*
++		 * This board uses non-MTS firmware
++		 */
++		break;
++	default:
++		ctl->demod = XC3028_FE_OREN538;
++		ctl->mts = 1;
++	}
++}
++EXPORT_SYMBOL_GPL(cx88_setup_xc3028);
++
+ static void cx88_card_setup(struct cx88_core *core)
+ {
+ 	static u8 eeprom[256];
+@@ -1991,6 +2480,13 @@ static void cx88_card_setup(struct cx88_core *core)
+ 		cx_write(MO_GP0_IO, 0x000007f8);
+ 		cx_write(MO_GP1_IO, 0x00000001);
+ 		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++		/* GPIO0:0 is hooked to demod reset */
++		/* GPIO0:4 is hooked to xc3028 reset */
++		cx_write(MO_GP0_IO, 0x00111100);
++		msleep(1);
++		cx_write(MO_GP0_IO, 0x00111111);
++		break;
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+ 		/* GPIO0:6 is hooked to FX2 reset pin */
+ 		cx_set(MO_GP0_IO, 0x00004040);
+@@ -2038,10 +2534,8 @@ static void cx88_card_setup(struct cx88_core *core)
+ 			for (i = 0; i < ARRAY_SIZE(buffer); i++)
+ 				if (2 != i2c_master_send(&core->i2c_client,
+ 							buffer[i],2))
+-					printk(KERN_WARNING
+-						"%s: Unable to enable "
+-						"tuner(%i).\n",
+-						core->name, i);
++					warn_printk(core, "Unable to enable "
++						    "tuner(%i).\n", i);
+ 		}
+ 		break;
+ 	case CX88_BOARD_MSI_TVANYWHERE_MASTER:
+@@ -2062,6 +2556,22 @@ static void cx88_card_setup(struct cx88_core *core)
+ 		cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
+ 	}
+ 	}
++
++	if (core->board.tuner_type == TUNER_XC2028) {
++		struct v4l2_priv_tun_config  xc2028_cfg;
++		struct xc2028_ctrl           ctl;
++
++		/* Fills device-dependent initialization parameters */
++		cx88_setup_xc3028(core, &ctl);
++
++		/* Sends parameters to xc2028/3028 tuner */
++		memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
++		xc2028_cfg.tuner = TUNER_XC2028;
++		xc2028_cfg.priv  = &ctl;
++		info_printk(core, "Asking xc2028/3028 to load firmware %s\n",
++			    ctl.fname);
++		cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
++	}
+ }
+ 
+ /* ------------------------------------------------------------------ */
+@@ -2178,9 +2688,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+ 
+ 	memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
+ 
+-	printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+-		core->name,pci->subsystem_vendor,
+-		pci->subsystem_device, core->board.name,
++	info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
++		pci->subsystem_vendor, pci->subsystem_device, core->board.name,
+ 		core->boardnr, card[core->nr] == core->boardnr ?
+ 		"insmod option" : "autodetected");
+ 
+@@ -2189,8 +2698,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+ 	if (radio[core->nr] != UNSET)
+ 		core->board.radio_type = radio[core->nr];
+ 
+-	printk(KERN_INFO "%s: TV tuner type %d, Radio tuner type %d\n",
+-	       core->name, core->board.tuner_type, core->board.radio_type);
++	info_printk(core, "TV tuner type %d, Radio tuner type %d\n",
++		    core->board.tuner_type, core->board.radio_type);
+ 
+ 	/* init hardware */
+ 	cx88_reset(core);
+@@ -2207,12 +2716,3 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+ 
+ 	return core;
+ }
+-
+-/* ------------------------------------------------------------------ */
+-
+-/*
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
+- */
+diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
+index 01e2ac9..c4d1aff 100644
+--- a/drivers/media/video/cx88/cx88-core.c
++++ b/drivers/media/video/cx88/cx88-core.c
+@@ -47,15 +47,15 @@ MODULE_LICENSE("GPL");
+ 
+ /* ------------------------------------------------------------------ */
+ 
+-static unsigned int core_debug = 0;
++static unsigned int core_debug;
+ module_param(core_debug,int,0644);
+ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+ 
+-static unsigned int nicam = 0;
++static unsigned int nicam;
+ module_param(nicam,int,0644);
+ MODULE_PARM_DESC(nicam,"tv audio is nicam");
+ 
+-static unsigned int nocomb = 0;
++static unsigned int nocomb;
+ module_param(nocomb,int,0644);
+ MODULE_PARM_DESC(nocomb,"disable comb filter");
+ 
+@@ -219,7 +219,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
+ 	videobuf_waiton(&buf->vb,0,0);
+ 	videobuf_dma_unmap(q, dma);
+ 	videobuf_dma_free(dma);
+-	btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
++	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+ 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ }
+ 
+@@ -548,7 +548,7 @@ void cx88_wakeup(struct cx88_core *core,
+ 		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ 	}
+ 	if (bc != 1)
+-		printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
++		printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
+ }
+ 
+ void cx88_shutdown(struct cx88_core *core)
+@@ -577,7 +577,7 @@ void cx88_shutdown(struct cx88_core *core)
+ 
+ int cx88_reset(struct cx88_core *core)
+ {
+-	dprintk(1,"%s\n",__FUNCTION__);
++	dprintk(1,"%s\n",__func__);
+ 	cx88_shutdown(core);
+ 
+ 	/* clear irq status */
+@@ -929,7 +929,10 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
+ 
+ 	dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
+ 		cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
+-	cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat);
++	/* Chroma AGC must be disabled if SECAM is used, we enable it
++	   by default on PAL and NTSC */
++	cx_andor(MO_INPUT_FORMAT, 0x40f,
++		 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
+ 
+ 	// FIXME: as-is from DScaler
+ 	dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index f7b41eb..1c7fe68 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -45,16 +45,21 @@
+ #include "nxt200x.h"
+ #include "cx24123.h"
+ #include "isl6421.h"
++#include "tuner-simple.h"
++#include "tda9887.h"
++#include "s5h1411.h"
+ 
+ MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
+ MODULE_AUTHOR("Chris Pascoe <c.pascoe at itee.uq.edu.au>");
+ MODULE_AUTHOR("Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]");
+ MODULE_LICENSE("GPL");
+ 
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk(level,fmt, arg...)	if (debug >= level) \
+ 	printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
+ 
+@@ -235,6 +240,19 @@ static struct zl10353_config dvico_fusionhdtv_hybrid = {
+ 	.no_tuner      = 1,
+ };
+ 
++static struct zl10353_config dvico_fusionhdtv_xc3028 = {
++	.demod_address = 0x0f,
++	.if2           = 45600,
++	.no_tuner      = 1,
++};
++
++static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
++	.demod_address = 0x0f,
++	.if2 = 4560,
++	.no_tuner = 1,
++	.demod_init = dvico_fusionhdtv_demod_init,
++};
++
+ static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
+ 	.demod_address = 0x0f,
+ };
+@@ -266,7 +284,7 @@ static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
+ 	struct cx8802_dev *dev= fe->dvb->priv;
+ 	struct cx88_core *core = dev->core;
+ 
+-	dprintk(1, "%s: index = %d\n", __FUNCTION__, index);
++	dprintk(1, "%s: index = %d\n", __func__, index);
+ 	if (index == 0)
+ 		cx_clear(MO_GP0_IO, 8);
+ 	else
+@@ -357,6 +375,40 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
+ 	return 0;
+ }
+ 
++static int cx88_pci_nano_callback(void *ptr, int command, int arg)
++{
++	struct cx88_core *core = ptr;
++
++	switch (command) {
++	case XC2028_TUNER_RESET:
++		/* Send the tuner in then out of reset */
++		dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
++
++		switch (core->boardnr) {
++		case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
++			/* GPIO-4 xc3028 tuner */
++
++			cx_set(MO_GP0_IO, 0x00001000);
++			cx_clear(MO_GP0_IO, 0x00000010);
++			msleep(100);
++			cx_set(MO_GP0_IO, 0x00000010);
++			msleep(100);
++			break;
++		}
++
++		break;
++	case XC2028_RESET_CLK:
++		dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
++		break;
++	default:
++		dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
++			command, arg);
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
+ static struct cx24123_config geniatech_dvbs_config = {
+ 	.demod_address = 0x55,
+ 	.set_ts_params = cx24123_set_ts_param,
+@@ -383,12 +435,92 @@ static struct s5h1409_config pinnacle_pctv_hd_800i_config = {
+ 	.mpeg_timing   = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
+ };
+ 
++static struct s5h1409_config dvico_hdtv5_pci_nano_config = {
++	.demod_address = 0x32 >> 1,
++	.output_mode   = S5H1409_SERIAL_OUTPUT,
++	.gpio          = S5H1409_GPIO_OFF,
++	.inversion     = S5H1409_INVERSION_OFF,
++	.status_mode   = S5H1409_DEMODLOCKING,
++	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
++};
++
++static struct s5h1409_config kworld_atsc_120_config = {
++	.demod_address = 0x32 >> 1,
++	.output_mode   = S5H1409_SERIAL_OUTPUT,
++	.gpio	       = S5H1409_GPIO_OFF,
++	.inversion     = S5H1409_INVERSION_OFF,
++	.status_mode   = S5H1409_DEMODLOCKING,
++	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
++};
++
+ static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
+ 	.i2c_address	= 0x64,
+ 	.if_khz		= 5380,
+ 	.tuner_callback	= cx88_tuner_callback,
+ };
+ 
++static struct zl10353_config cx88_geniatech_x8000_mt = {
++       .demod_address = (0x1e >> 1),
++       .no_tuner = 1,
++};
++
++static struct s5h1411_config dvico_fusionhdtv7_config = {
++	.output_mode   = S5H1411_SERIAL_OUTPUT,
++	.gpio          = S5H1411_GPIO_ON,
++	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
++	.qam_if        = S5H1411_IF_44000,
++	.vsb_if        = S5H1411_IF_44000,
++	.inversion     = S5H1411_INVERSION_OFF,
++	.status_mode   = S5H1411_DEMODLOCKING
++};
++
++static struct xc5000_config dvico_fusionhdtv7_tuner_config = {
++	.i2c_address    = 0xc2 >> 1,
++	.if_khz         = 5380,
++	.tuner_callback = cx88_tuner_callback,
++};
++
++static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
++{
++	struct dvb_frontend *fe;
++	struct xc2028_ctrl ctl;
++	struct xc2028_config cfg = {
++		.i2c_adap  = &dev->core->i2c_adap,
++		.i2c_addr  = addr,
++		.ctrl      = &ctl,
++		.callback  = cx88_tuner_callback,
++	};
++
++	if (!dev->dvb.frontend) {
++		printk(KERN_ERR "%s/2: dvb frontend not attached. "
++				"Can't attach xc3028\n",
++		       dev->core->name);
++		return -EINVAL;
++	}
++
++	/*
++	 * Some xc3028 devices may be hidden by an I2C gate. This is known
++	 * to happen with some s5h1409-based devices.
++	 * Now that I2C gate is open, sets up xc3028 configuration
++	 */
++	cx88_setup_xc3028(dev->core, &ctl);
++
++	fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
++	if (!fe) {
++		printk(KERN_ERR "%s/2: xc3028 attach failed\n",
++		       dev->core->name);
++		dvb_frontend_detach(dev->dvb.frontend);
++		dvb_unregister_frontend(dev->dvb.frontend);
++		dev->dvb.frontend = NULL;
++		return -EINVAL;
++	}
++
++	printk(KERN_INFO "%s/2: xc3028 attached\n",
++	       dev->core->name);
++
++	return 0;
++}
++
+ static int dvb_register(struct cx8802_dev *dev)
+ {
+ 	/* init struct videobuf_dvb */
+@@ -429,8 +561,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ 					       &hauppauge_hvr_config,
+ 					       &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x61,
++				   TUNER_PHILIPS_FMD1216ME_MK3);
+ 		}
+ 		break;
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+@@ -497,8 +630,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ 		dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
+ 					       &dev->vp3054->adap);
+ 		if (dev->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x61,
++				   TUNER_PHILIPS_FMD1216ME_MK3);
+ 		}
+ #else
+ 		printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name);
+@@ -509,18 +643,36 @@ static int dvb_register(struct cx8802_dev *dev)
+ 					       &dvico_fusionhdtv_hybrid,
+ 					       &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   &dev->core->i2c_adap,
+-				   DVB_PLL_THOMSON_FE6600);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x61,
++				   TUNER_THOMSON_FE6600);
+ 		}
+ 		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++		dev->dvb.frontend = dvb_attach(zl10353_attach,
++					       &dvico_fusionhdtv_xc3028,
++					       &dev->core->i2c_adap);
++		if (dev->dvb.frontend == NULL)
++			dev->dvb.frontend = dvb_attach(mt352_attach,
++						&dvico_fusionhdtv_mt352_xc3028,
++						&dev->core->i2c_adap);
++		/*
++		 * On this board, the demod provides the I2C bus pullup.
++		 * We must not permit gate_ctrl to be performed, or
++		 * the xc3028 cannot communicate on the bus.
++		 */
++		if (dev->dvb.frontend)
++			dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
++		if (attach_xc3028(0x61, dev) < 0)
++			return -EINVAL;
++		break;
+ 	case CX88_BOARD_PCHDTV_HD3000:
+ 		dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
+ 					       &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   &dev->core->i2c_adap,
+-				   DVB_PLL_THOMSON_DTT761X);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x61,
++				   TUNER_THOMSON_DTT761X);
+ 		}
+ 		break;
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+@@ -540,9 +692,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ 					       &fusionhdtv_3_gold,
+ 					       &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   &dev->core->i2c_adap,
+-				   DVB_PLL_MICROTUNE_4042);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x61,
++				   TUNER_MICROTUNE_4042FI5);
+ 		}
+ 		}
+ 		break;
+@@ -560,9 +712,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ 					       &fusionhdtv_3_gold,
+ 					       &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   &dev->core->i2c_adap,
+-				   DVB_PLL_THOMSON_DTT761X);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x61,
++				   TUNER_THOMSON_DTT761X);
+ 		}
+ 		}
+ 		break;
+@@ -580,9 +732,11 @@ static int dvb_register(struct cx8802_dev *dev)
+ 					       &fusionhdtv_5_gold,
+ 					       &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   &dev->core->i2c_adap,
+-				   DVB_PLL_LG_TDVS_H06XF);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x61,
++				   TUNER_LG_TDVS_H06XF);
++			dvb_attach(tda9887_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x43);
+ 		}
+ 		}
+ 		break;
+@@ -600,9 +754,11 @@ static int dvb_register(struct cx8802_dev *dev)
+ 					       &pchdtv_hd5500,
+ 					       &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   &dev->core->i2c_adap,
+-				   DVB_PLL_LG_TDVS_H06XF);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x61,
++				   TUNER_LG_TDVS_H06XF);
++			dvb_attach(tda9887_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x43);
+ 		}
+ 		}
+ 		break;
+@@ -611,8 +767,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ 					       &ati_hdtvwonder,
+ 					       &dev->core->i2c_adap);
+ 		if (dev->dvb.frontend != NULL) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   NULL, DVB_PLL_TUV1236D);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap, 0x61,
++				   TUNER_PHILIPS_TUV1236D);
+ 		}
+ 		break;
+ 	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+@@ -658,14 +815,77 @@ static int dvb_register(struct cx8802_dev *dev)
+ 				   &pinnacle_pctv_hd_800i_tuner_config);
+ 		}
+ 		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
++		dev->dvb.frontend = dvb_attach(s5h1409_attach,
++						&dvico_hdtv5_pci_nano_config,
++						&dev->core->i2c_adap);
++		if (dev->dvb.frontend != NULL) {
++			struct dvb_frontend *fe;
++			struct xc2028_config cfg = {
++				.i2c_adap  = &dev->core->i2c_adap,
++				.i2c_addr  = 0x61,
++				.callback  = cx88_pci_nano_callback,
++			};
++			static struct xc2028_ctrl ctl = {
++				.fname       = "xc3028-v27.fw",
++				.max_len     = 64,
++				.scode_table = XC3028_FE_OREN538,
++			};
++
++			fe = dvb_attach(xc2028_attach,
++					dev->dvb.frontend, &cfg);
++			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
++				fe->ops.tuner_ops.set_config(fe, &ctl);
++		}
++		break;
++	 case CX88_BOARD_PINNACLE_HYBRID_PCTV:
++		dev->dvb.frontend = dvb_attach(zl10353_attach,
++					       &cx88_geniatech_x8000_mt,
++					       &dev->core->i2c_adap);
++		if (attach_xc3028(0x61, dev) < 0)
++			return -EINVAL;
++		break;
++	 case CX88_BOARD_GENIATECH_X8000_MT:
++		dev->ts_gen_cntrl = 0x00;
++
++		dev->dvb.frontend = dvb_attach(zl10353_attach,
++					       &cx88_geniatech_x8000_mt,
++					       &dev->core->i2c_adap);
++		if (attach_xc3028(0x61, dev) < 0)
++			return -EINVAL;
++		break;
++	 case CX88_BOARD_KWORLD_ATSC_120:
++		dev->dvb.frontend = dvb_attach(s5h1409_attach,
++					       &kworld_atsc_120_config,
++					       &dev->core->i2c_adap);
++		if (attach_xc3028(0x61, dev) < 0)
++			return -EINVAL;
++		break;
++	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
++		dev->dvb.frontend = dvb_attach(s5h1411_attach,
++					       &dvico_fusionhdtv7_config,
++					       &dev->core->i2c_adap);
++		if (dev->dvb.frontend != NULL) {
++			/* tuner_config.video_dev must point to
++			 * i2c_adap.algo_data
++			 */
++			dvico_fusionhdtv7_tuner_config.priv =
++						dev->core->i2c_adap.algo_data;
++			dvb_attach(xc5000_attach, dev->dvb.frontend,
++				   &dev->core->i2c_adap,
++				   &dvico_fusionhdtv7_tuner_config);
++		}
++		break;
+ 	default:
+ 		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
+ 		       dev->core->name);
+ 		break;
+ 	}
+ 	if (NULL == dev->dvb.frontend) {
+-		printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name);
+-		return -1;
++		printk(KERN_ERR
++		       "%s/2: frontend initialization failed\n",
++		       dev->core->name);
++		return -EINVAL;
+ 	}
+ 
+ 	/* Ensure all frontends negotiate bus access */
+@@ -675,7 +895,8 @@ static int dvb_register(struct cx8802_dev *dev)
+ 	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+ 
+ 	/* register everything */
+-	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
++	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
++				     &dev->pci->dev, adapter_nr);
+ }
+ 
+ /* ----------------------------------------------------------- */
+@@ -685,7 +906,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
+ {
+ 	struct cx88_core *core = drv->core;
+ 	int err = 0;
+-	dprintk( 1, "%s\n", __FUNCTION__);
++	dprintk( 1, "%s\n", __func__);
+ 
+ 	switch (core->boardnr) {
+ 	case CX88_BOARD_HAUPPAUGE_HVR1300:
+@@ -708,7 +929,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
+ {
+ 	struct cx88_core *core = drv->core;
+ 	int err = 0;
+-	dprintk( 1, "%s\n", __FUNCTION__);
++	dprintk( 1, "%s\n", __func__);
+ 
+ 	switch (core->boardnr) {
+ 	case CX88_BOARD_HAUPPAUGE_HVR1300:
+@@ -726,7 +947,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
+ 	struct cx8802_dev *dev = drv->core->dvbdev;
+ 	int err;
+ 
+-	dprintk( 1, "%s\n", __FUNCTION__);
++	dprintk( 1, "%s\n", __func__);
+ 	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ 		core->boardnr,
+ 		core->name,
+@@ -744,8 +965,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
+ 
+ 	/* dvb stuff */
+ 	printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
+-	videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ 			    V4L2_FIELD_TOP,
+ 			    sizeof(struct cx88_buffer),
+@@ -764,7 +985,8 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
+ 	struct cx8802_dev *dev = drv->core->dvbdev;
+ 
+ 	/* dvb */
+-	videobuf_dvb_unregister(&dev->dvb);
++	if (dev->dvb.frontend)
++		videobuf_dvb_unregister(&dev->dvb);
+ 
+ 	vp3054_i2c_remove(dev);
+ 
+diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
+index 566b26a..c6b4473 100644
+--- a/drivers/media/video/cx88/cx88-i2c.c
++++ b/drivers/media/video/cx88/cx88-i2c.c
+@@ -35,11 +35,11 @@
+ #include "cx88.h"
+ #include <media/v4l2-common.h>
+ 
+-static unsigned int i2c_debug = 0;
++static unsigned int i2c_debug;
+ module_param(i2c_debug, int, 0644);
+ MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
+ 
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, 0444);
+ MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+ 
+diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
+index bb0911b..53526d9 100644
+--- a/drivers/media/video/cx88/cx88-input.c
++++ b/drivers/media/video/cx88/cx88-input.c
+@@ -57,7 +57,7 @@ struct cx88_IR {
+ 	u32 mask_keyup;
+ };
+ 
+-static int ir_debug = 0;
++static int ir_debug;
+ module_param(ir_debug, int, 0644);	/* debug level [IR] */
+ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+ 
+@@ -258,6 +258,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+ 		ir->mask_keyup = 0x80;
+ 		ir->polling = 1; /* ms */
+ 		break;
++	case CX88_BOARD_PROLINK_PV_8000GT:
++		ir_codes = ir_codes_pixelview_new;
++		ir->gpio_addr = MO_GP1_IO;
++		ir->mask_keycode = 0x3f;
++		ir->mask_keyup = 0x80;
++		ir->polling = 1; /* ms */
++		break;
+ 	case CX88_BOARD_KWORLD_LTV883:
+ 		ir_codes = ir_codes_pixelview;
+ 		ir->gpio_addr = MO_GP1_IO;
+@@ -310,6 +317,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+ 		ir_type = IR_TYPE_RC5;
+ 		ir->sampling = 1;
+ 		break;
++	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
++		ir_codes = ir_codes_powercolor_real_angel;
++		ir->gpio_addr = MO_GP2_IO;
++		ir->mask_keycode = 0x7e;
++		ir->polling = 100; /* ms */
++		break;
+ 	}
+ 
+ 	if (NULL == ir_codes) {
+diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
+index e357f41..a6b061c 100644
+--- a/drivers/media/video/cx88/cx88-mpeg.c
++++ b/drivers/media/video/cx88/cx88-mpeg.c
+@@ -39,7 +39,7 @@ MODULE_AUTHOR("Chris Pascoe <c.pascoe at itee.uq.edu.au>");
+ MODULE_AUTHOR("Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]");
+ MODULE_LICENSE("GPL");
+ 
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug,int,0644);
+ MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
+ 
+@@ -146,7 +146,7 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
+ 		cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
+ 		udelay(100);
+ 	} else {
+-		printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
++		printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
+ 			core->board.mpeg );
+ 		return -EINVAL;
+ 	}
+@@ -247,7 +247,7 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
+ 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ 	int rc;
+ 
+-	dprintk(1, "%s: %p\n", __FUNCTION__, buf);
++	dprintk(1, "%s: %p\n", __func__, buf);
+ 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+ 		return -EINVAL;
+ 
+@@ -289,7 +289,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
+ 		buf->count    = cx88q->count++;
+ 		mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
+ 		dprintk(1,"[%p/%d] %s - first active\n",
+-			buf, buf->vb.i, __FUNCTION__);
++			buf, buf->vb.i, __func__);
+ 
+ 	} else {
+ 		dprintk( 1, "queue is not empty - append to active\n" );
+@@ -299,7 +299,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
+ 		buf->count    = cx88q->count++;
+ 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ 		dprintk( 1, "[%p/%d] %s - append to active\n",
+-			buf, buf->vb.i, __FUNCTION__);
++			buf, buf->vb.i, __func__);
+ 	}
+ }
+ 
+@@ -342,7 +342,7 @@ static void cx8802_timeout(unsigned long data)
+ {
+ 	struct cx8802_dev *dev = (struct cx8802_dev*)data;
+ 
+-	dprintk(1, "%s\n",__FUNCTION__);
++	dprintk(1, "%s\n",__func__);
+ 
+ 	if (debug)
+ 		cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
+@@ -613,6 +613,8 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
+ 	    core->active_type_id != drv->type_id)
+ 		return -EBUSY;
+ 
++	core->input = CX88_VMUX_DVB;
++
+ 	if (drv->advise_acquire)
+ 	{
+ 		mutex_lock(&drv->core->lock);
+@@ -623,7 +625,7 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
+ 		}
+ 		mutex_unlock(&drv->core->lock);
+ 
+-		mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
++		mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+ 	}
+ 
+ 	return 0;
+@@ -639,7 +641,7 @@ static int cx8802_request_release(struct cx8802_driver *drv)
+ 	{
+ 		drv->advise_release(drv);
+ 		core->active_type_id = CX88_BOARD_NONE;
+-		mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
++		mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+ 	}
+ 	mutex_unlock(&drv->core->lock);
+ 
+@@ -813,7 +815,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+ 
+ 	dev = pci_get_drvdata(pci_dev);
+ 
+-	dprintk( 1, "%s\n", __FUNCTION__);
++	dprintk( 1, "%s\n", __func__);
+ 
+ 	if (!list_empty(&dev->drvlist)) {
+ 		struct cx8802_driver *drv, *tmp;
+diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
+index 76e5c78..3a1977f 100644
+--- a/drivers/media/video/cx88/cx88-tvaudio.c
++++ b/drivers/media/video/cx88/cx88-tvaudio.c
+@@ -53,15 +53,15 @@
+ 
+ #include "cx88.h"
+ 
+-static unsigned int audio_debug = 0;
++static unsigned int audio_debug;
+ module_param(audio_debug, int, 0644);
+ MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
+ 
+-static unsigned int always_analog = 0;
++static unsigned int always_analog;
+ module_param(always_analog,int,0644);
+ MODULE_PARM_DESC(always_analog,"force analog audio out");
+ 
+-static unsigned int radio_deemphasis = 0;
++static unsigned int radio_deemphasis;
+ module_param(radio_deemphasis,int,0644);
+ MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, "
+ 		 "0=None, 1=50us (elsewhere), 2=75us (USA)");
+@@ -265,12 +265,12 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
+ 	mode |= EN_FMRADIO_EN_RDS;
+ 
+ 	if (sap) {
+-		dprintk("%s SAP (status: unknown)\n", __FUNCTION__);
++		dprintk("%s SAP (status: unknown)\n", __func__);
+ 		set_audio_start(core, SEL_SAP);
+ 		set_audio_registers(core, btsc_sap);
+ 		set_audio_finish(core, mode);
+ 	} else {
+-		dprintk("%s (status: known-good)\n", __FUNCTION__);
++		dprintk("%s (status: known-good)\n", __func__);
+ 		set_audio_start(core, SEL_BTSC);
+ 		set_audio_registers(core, btsc);
+ 		set_audio_finish(core, mode);
+@@ -351,16 +351,16 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
+ 	set_audio_start(core,SEL_NICAM);
+ 	switch (core->tvaudio) {
+ 	case WW_L:
+-		dprintk("%s SECAM-L NICAM (status: devel)\n", __FUNCTION__);
++		dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
+ 		set_audio_registers(core, nicam_l);
+ 		break;
+ 	case WW_I:
+-		dprintk("%s PAL-I NICAM (status: known-good)\n", __FUNCTION__);
++		dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
+ 		set_audio_registers(core, nicam_bgdki_common);
+ 		set_audio_registers(core, nicam_i);
+ 		break;
+ 	default:
+-		dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __FUNCTION__);
++		dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
+ 		set_audio_registers(core, nicam_bgdki_common);
+ 		set_audio_registers(core, nicam_default);
+ 		break;
+@@ -600,28 +600,28 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
+ 	set_audio_start(core, SEL_A2);
+ 	switch (core->tvaudio) {
+ 	case WW_BG:
+-		dprintk("%s PAL-BG A1/2 (status: known-good)\n", __FUNCTION__);
++		dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
+ 		set_audio_registers(core, a2_bgdk_common);
+ 		set_audio_registers(core, a2_bg);
+ 		set_audio_registers(core, a2_deemph50);
+ 		break;
+ 	case WW_DK:
+-		dprintk("%s PAL-DK A1/2 (status: known-good)\n", __FUNCTION__);
++		dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
+ 		set_audio_registers(core, a2_bgdk_common);
+ 		set_audio_registers(core, a2_dk);
+ 		set_audio_registers(core, a2_deemph50);
+ 		break;
+ 	case WW_I:
+-		dprintk("%s PAL-I A1 (status: known-good)\n", __FUNCTION__);
++		dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
+ 		set_audio_registers(core, a1_i);
+ 		set_audio_registers(core, a2_deemph50);
+ 		break;
+ 	case WW_L:
+-		dprintk("%s AM-L (status: devel)\n", __FUNCTION__);
++		dprintk("%s AM-L (status: devel)\n", __func__);
+ 		set_audio_registers(core, am_l);
+ 		break;
+ 	default:
+-		dprintk("%s Warning: wrong value\n", __FUNCTION__);
++		dprintk("%s Warning: wrong value\n", __func__);
+ 		return;
+ 		break;
+ 	};
+@@ -637,7 +637,7 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
+ 
+ 		{ /* end of list */ },
+ 	};
+-	dprintk("%s (status: unknown)\n", __FUNCTION__);
++	dprintk("%s (status: unknown)\n", __func__);
+ 
+ 	set_audio_start(core, SEL_EIAJ);
+ 	set_audio_registers(core, eiaj);
+@@ -691,7 +691,7 @@ static void set_audio_standard_FM(struct cx88_core *core,
+ 		{ /* end of list */ },
+ 	};
+ 
+-	dprintk("%s (status: unknown)\n", __FUNCTION__);
++	dprintk("%s (status: unknown)\n", __func__);
+ 	set_audio_start(core, SEL_FMRADIO);
+ 
+ 	switch (deemph) {
+diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
+index d96ecfc..0943060 100644
+--- a/drivers/media/video/cx88/cx88-vbi.c
++++ b/drivers/media/video/cx88/cx88-vbi.c
+@@ -11,7 +11,7 @@ static unsigned int vbibufs = 4;
+ module_param(vbibufs,int,0644);
+ MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
+ 
+-static unsigned int vbi_debug = 0;
++static unsigned int vbi_debug;
+ module_param(vbi_debug,int,0644);
+ MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
+ 
+diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
+index 2271796..eea23f9 100644
+--- a/drivers/media/video/cx88/cx88-video.c
++++ b/drivers/media/video/cx88/cx88-video.c
+@@ -63,11 +63,11 @@ MODULE_PARM_DESC(video_nr,"video device numbers");
+ MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
+ MODULE_PARM_DESC(radio_nr,"radio device numbers");
+ 
+-static unsigned int video_debug = 0;
++static unsigned int video_debug;
+ module_param(video_debug,int,0644);
+ MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+ 
+-static unsigned int irq_debug = 0;
++static unsigned int irq_debug;
+ module_param(irq_debug,int,0644);
+ MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
+ 
+@@ -228,6 +228,30 @@ static struct cx88_ctrl cx8800_ctls[] = {
+ 		.mask                  = 0x00ff,
+ 		.shift                 = 0,
+ 	},{
++		.v = {
++			.id            = V4L2_CID_CHROMA_AGC,
++			.name          = "Chroma AGC",
++			.minimum       = 0,
++			.maximum       = 1,
++			.default_value = 0x1,
++			.type          = V4L2_CTRL_TYPE_BOOLEAN,
++		},
++		.reg                   = MO_INPUT_FORMAT,
++		.mask                  = 1 << 10,
++		.shift                 = 10,
++	}, {
++		.v = {
++			.id            = V4L2_CID_COLOR_KILLER,
++			.name          = "Color killer",
++			.minimum       = 0,
++			.maximum       = 1,
++			.default_value = 0x1,
++			.type          = V4L2_CTRL_TYPE_BOOLEAN,
++		},
++		.reg                   = MO_INPUT_FORMAT,
++		.mask                  = 1 << 9,
++		.shift                 = 9,
++	}, {
+ 	/* --- audio --- */
+ 		.v = {
+ 			.id            = V4L2_CID_AUDIO_MUTE,
+@@ -282,6 +306,8 @@ const u32 cx88_user_ctrls[] = {
+ 	V4L2_CID_AUDIO_VOLUME,
+ 	V4L2_CID_AUDIO_BALANCE,
+ 	V4L2_CID_AUDIO_MUTE,
++	V4L2_CID_CHROMA_AGC,
++	V4L2_CID_COLOR_KILLER,
+ 	0
+ };
+ EXPORT_SYMBOL(cx88_user_ctrls);
+@@ -291,7 +317,7 @@ static const u32 *ctrl_classes[] = {
+ 	NULL
+ };
+ 
+-int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
++int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl)
+ {
+ 	int i;
+ 
+@@ -306,6 +332,11 @@ int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
+ 		return 0;
+ 	}
+ 	*qctrl = cx8800_ctls[i].v;
++	/* Report chroma AGC as inactive when SECAM is selected */
++	if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC &&
++	    core->tvnorm & V4L2_STD_SECAM)
++		qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
++
+ 	return 0;
+ }
+ EXPORT_SYMBOL(cx8800_ctrl_query);
+@@ -776,14 +807,14 @@ static int video_open(struct inode *inode, struct file *file)
+ 	fh->height   = 240;
+ 	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+ 
+-	videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ 			    V4L2_FIELD_INTERLACED,
+ 			    sizeof(struct cx88_buffer),
+ 			    fh);
+-	videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VBI_CAPTURE,
+ 			    V4L2_FIELD_SEQ_TB,
+ 			    sizeof(struct cx88_buffer),
+@@ -976,6 +1007,12 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
+ 		}
+ 		mask=0xffff;
+ 		break;
++	case V4L2_CID_CHROMA_AGC:
++		/* Do not allow chroma AGC to be enabled for SECAM */
++		value = ((ctl->value - c->off) << c->shift) & c->mask;
++		if (core->tvnorm & V4L2_STD_SECAM && value)
++			return -EINVAL;
++		break;
+ 	default:
+ 		value = ((ctl->value - c->off) << c->shift) & c->mask;
+ 		break;
+@@ -1268,10 +1305,12 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+ static int vidioc_queryctrl (struct file *file, void *priv,
+ 				struct v4l2_queryctrl *qctrl)
+ {
++	struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
++
+ 	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+ 	if (unlikely(qctrl->id == 0))
+ 		return -EINVAL;
+-	return cx8800_ctrl_query(qctrl);
++	return cx8800_ctrl_query(core, qctrl);
+ }
+ 
+ static int vidioc_g_ctrl (struct file *file, void *priv,
+@@ -1832,8 +1871,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
+ 
+ 	switch (core->boardnr) {
+ 	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+-		request_module("ir-kbd-i2c");
++	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+ 		request_module("rtc-isl1208");
++		/* break intentionally omitted */
++	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
++		request_module("ir-kbd-i2c");
+ 	}
+ 
+ 	/* register v4l devices */
+@@ -1917,6 +1959,9 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
+ 		core->kthread = NULL;
+ 	}
+ 
++	if (core->ir)
++		cx88_ir_stop(core, core->ir);
++
+ 	cx88_shutdown(core); /* FIXME */
+ 	pci_disable_device(pci_dev);
+ 
+diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
+index 37e6d2e..14ac173 100644
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -37,6 +37,7 @@
+ 
+ #include "btcx-risc.h"
+ #include "cx88-reg.h"
++#include "tuner-xc2028.h"
+ 
+ #include <linux/version.h>
+ #include <linux/mutex.h>
+@@ -211,6 +212,15 @@ extern struct sram_channel cx88_sram_channels[];
+ #define CX88_BOARD_HAUPPAUGE_HVR1300       56
+ #define CX88_BOARD_ADSTECH_PTV_390         57
+ #define CX88_BOARD_PINNACLE_PCTV_HD_800i   58
++#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59
++#define CX88_BOARD_PINNACLE_HYBRID_PCTV    60
++#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61
++#define CX88_BOARD_POWERCOLOR_REAL_ANGEL   62
++#define CX88_BOARD_GENIATECH_X8000_MT      63
++#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64
++#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65
++#define CX88_BOARD_PROLINK_PV_8000GT       66
++#define CX88_BOARD_KWORLD_ATSC_120         67
+ 
+ enum cx88_itype {
+ 	CX88_VMUX_COMPOSITE1 = 1,
+@@ -595,6 +605,7 @@ extern int cx88_tuner_callback(void *dev, int command, int arg);
+ extern int cx88_get_resources(const struct cx88_core *core,
+ 			      struct pci_dev *pci);
+ extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
++extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
+ 
+ /* ----------------------------------------------------------- */
+ /* cx88-tvaudio.c                                              */
+@@ -640,7 +651,8 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev);
+ /* ----------------------------------------------------------- */
+ /* cx88-video.c*/
+ extern const u32 cx88_user_ctrls[];
+-extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
++extern int cx8800_ctrl_query(struct cx88_core *core,
++			     struct v4l2_queryctrl *qctrl);
+ int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i);
+ int cx88_set_freq (struct cx88_core  *core,struct v4l2_frequency *f);
+ int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
+diff --git a/drivers/media/video/dabfirmware.h b/drivers/media/video/dabfirmware.h
+index d14d803..cbd9263 100644
+--- a/drivers/media/video/dabfirmware.h
++++ b/drivers/media/video/dabfirmware.h
+@@ -1,5 +1,12 @@
+ /*
+  * dabdata.h - dab usb firmware and bitstream data
++ *
++ * Copyright (C) 1999 BayCom GmbH
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that redistributions of source
++ * code retain the above copyright notice and this comment without
++ * modification.
+  */
+ 
+ static INTEL_HEX_RECORD firmware[] = {
+diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
+index a5731f9..8d1f8ee 100644
+--- a/drivers/media/video/dabusb.c
++++ b/drivers/media/video/dabusb.c
+@@ -205,7 +205,7 @@ static void dabusb_iso_complete (struct urb *purb)
+ /*-------------------------------------------------------------------*/
+ static int dabusb_alloc_buffers (pdabusb_t s)
+ {
+-	int buffers = 0;
++	int transfer_len = 0;
+ 	pbuff_t b;
+ 	unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
+ 	int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
+@@ -216,7 +216,7 @@ static int dabusb_alloc_buffers (pdabusb_t s)
+ 	dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
+ 		 pipesize, packets, transfer_buffer_length);
+ 
+-	while (buffers < (s->total_buffer_size << 10)) {
++	while (transfer_len < (s->total_buffer_size << 10)) {
+ 		b = kzalloc(sizeof (buff_t), GFP_KERNEL);
+ 		if (!b) {
+ 			err("kzalloc(sizeof(buff_t))==NULL");
+@@ -251,10 +251,10 @@ static int dabusb_alloc_buffers (pdabusb_t s)
+ 			b->purb->iso_frame_desc[i].length = pipesize;
+ 		}
+ 
+-		buffers += transfer_buffer_length;
++		transfer_len += transfer_buffer_length;
+ 		list_add_tail (&b->buff_list, &s->free_buff_list);
+ 	}
+-	s->got_mem = buffers;
++	s->got_mem = transfer_len;
+ 
+ 	return 0;
+ 
+diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
+index 9ceb6b2..88d6df7 100644
+--- a/drivers/media/video/dpc7146.c
++++ b/drivers/media/video/dpc7146.c
+@@ -54,11 +54,11 @@
+ 
+ #define DPC_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "debug verbosity");
+ 
+-static int dpc_num = 0;
++static int dpc_num;
+ 
+ #define DPC_INPUTS	2
+ static struct v4l2_input dpc_inputs[DPC_INPUTS] = {
+diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
+index 0f7a0bd..9caffed 100644
+--- a/drivers/media/video/em28xx/Kconfig
++++ b/drivers/media/video/em28xx/Kconfig
+@@ -1,11 +1,13 @@
+ config VIDEO_EM28XX
+-	tristate "Empia EM2800/2820/2840 USB video capture support"
++	tristate "Empia EM28xx USB video capture support"
+ 	depends on VIDEO_DEV && I2C && INPUT
+ 	select VIDEO_TUNER
+ 	select VIDEO_TVEEPROM
+ 	select VIDEO_IR
++	select VIDEOBUF_VMALLOC
+ 	select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+ 	select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
++	select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
+ 	---help---
+ 	  This is a video4linux driver for Empia 28xx based TV cards.
+ 
+@@ -27,3 +29,13 @@ config VIDEO_EM28XX_ALSA
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called em28xx-alsa
+ 
++config VIDEO_EM28XX_DVB
++	tristate "DVB/ATSC Support for em28xx based TV cards"
++	depends on VIDEO_EM28XX && DVB_CORE
++	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
++	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
++	select VIDEOBUF_DVB
++	select FW_LOADER
++	---help---
++	  This adds support for DVB cards based on the
++	  Empiatech em28xx chips.
+diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile
+index 0924550..3d1c3cc 100644
+--- a/drivers/media/video/em28xx/Makefile
++++ b/drivers/media/video/em28xx/Makefile
+@@ -5,6 +5,7 @@ em28xx-alsa-objs := em28xx-audio.o
+ 
+ obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
+ obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
++obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
+ 
+ EXTRA_CFLAGS += -Idrivers/media/video
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
+index 8c67f67..92b2a6d 100644
+--- a/drivers/media/video/em28xx/em28xx-audio.c
++++ b/drivers/media/video/em28xx/em28xx-audio.c
+@@ -51,7 +51,7 @@ MODULE_PARM_DESC(debug, "activates debug info");
+ #define dprintk(fmt, arg...) do {					\
+ 	    if (debug)							\
+ 		printk(KERN_INFO "em28xx-audio %s: " fmt,		\
+-				  __FUNCTION__, ##arg); 		\
++				  __func__, ##arg); 		\
+ 	} while (0)
+ 
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
+index aae7753..50ccf37 100644
+--- a/drivers/media/video/em28xx/em28xx-cards.c
++++ b/drivers/media/video/em28xx/em28xx-cards.c
+@@ -36,7 +36,6 @@
+ #include <media/v4l2-common.h>
+ 
+ #include "em28xx.h"
+-#include "tuner-xc2028.h"
+ 
+ static int tuner = -1;
+ module_param(tuner, int, 0444);
+@@ -52,26 +51,6 @@ struct em28xx_hash_table {
+ 	unsigned int  tuner;
+ };
+ 
+-/* Boards supported by driver */
+-
+-#define EM2800_BOARD_UNKNOWN			0
+-#define EM2820_BOARD_UNKNOWN			1
+-#define EM2820_BOARD_TERRATEC_CINERGY_250	2
+-#define EM2820_BOARD_PINNACLE_USB_2		3
+-#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
+-#define EM2820_BOARD_MSI_VOX_USB_2              5
+-#define EM2800_BOARD_TERRATEC_CINERGY_200       6
+-#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
+-#define EM2800_BOARD_KWORLD_USB2800             8
+-#define EM2820_BOARD_PINNACLE_DVC_90		9
+-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900	10
+-#define EM2880_BOARD_TERRATEC_HYBRID_XS		11
+-#define EM2820_BOARD_KWORLD_PVRTV2800RF		12
+-#define EM2880_BOARD_TERRATEC_PRODIGY_XS	13
+-#define EM2820_BOARD_PROLINK_PLAYTV_USB2	14
+-#define EM2800_BOARD_VGEAR_POCKETTV             15
+-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950	16
+-
+ struct em28xx_board em28xx_boards[] = {
+ 	[EM2800_BOARD_UNKNOWN] = {
+ 		.name         = "Unknown EM2800 video grabber",
+@@ -200,6 +179,7 @@ struct em28xx_board em28xx_boards[] = {
+ 		.tuner_type     = TUNER_XC2028,
+ 		.mts_firmware   = 1,
+ 		.has_12mhz_i2s  = 1,
++		.has_dvb        = 1,
+ 		.decoder        = EM28XX_TVP5150,
+ 		.input          = { {
+ 			.type     = EM28XX_VMUX_TELEVISION,
+@@ -214,9 +194,6 @@ struct em28xx_board em28xx_boards[] = {
+ 			.vmux     = TVP5150_SVIDEO,
+ 			.amux     = 1,
+ 		} },
+-
+-		/* gpio's 4, 1, 0 */
+-		.analog_gpio = 0x003d2d,
+ 	},
+ 	[EM2880_BOARD_TERRATEC_HYBRID_XS] = {
+ 		.name         = "Terratec Hybrid XS",
+@@ -331,7 +308,7 @@ struct em28xx_board em28xx_boards[] = {
+ 		.name         = "Kworld USB2800",
+ 		.is_em2800    = 1,
+ 		.vchannels    = 3,
+-		.tuner_type   = TUNER_PHILIPS_ATSC,
++		.tuner_type   = TUNER_PHILIPS_FCV1236D,
+ 		.tda9887_conf = TDA9887_PRESENT,
+ 		.decoder      = EM28XX_SAA7113,
+ 		.input          = { {
+@@ -453,7 +430,36 @@ struct usb_device_id em28xx_id_table [] = {
+ };
+ MODULE_DEVICE_TABLE(usb, em28xx_id_table);
+ 
+-/* EEPROM hash table for devices with generic USB IDs */
++/*
++ *  Reset sequences for analog/digital modes
++ */
++
++/* Board Hauppauge WinTV HVR 900 analog */
++static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
++	{EM28XX_R08_GPIO,	0x2d,	~EM_GPIO_4,	10},
++	{0x05,			0xff,	0x10,		10},
++	{  -1,			-1,	-1,		-1},
++};
++
++/* Board Hauppauge WinTV HVR 900 digital */
++static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
++	{EM28XX_R08_GPIO,	0x2e,	~EM_GPIO_4,	10},
++	{EM2880_R04_GPO,	0x04,	0x0f,		10},
++	{EM2880_R04_GPO,	0x0c,	0x0f,		10},
++	{ -1,			-1,	-1,		-1},
++};
++
++/* Board Hauppauge WinTV HVR 900 tuner_callback */
++static struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = {
++	{EM28XX_R08_GPIO,	EM_GPIO_4,	EM_GPIO_4,	10},
++	{EM28XX_R08_GPIO,	0,		EM_GPIO_4,	10},
++	{EM28XX_R08_GPIO,	EM_GPIO_4,	EM_GPIO_4,	10},
++	{  -1,			-1,		-1,		-1},
++};
++
++/*
++ * EEPROM hash table for devices with generic USB IDs
++ */
+ static struct em28xx_hash_table em28xx_eeprom_hash [] = {
+ 	/* P/N: SA 60002070465 Tuner: TVF7533-MF */
+ 	{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
+@@ -465,79 +471,113 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
+ 	{0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
+ };
+ 
++int em28xx_tuner_callback(void *ptr, int command, int arg)
++{
++	int rc = 0;
++	struct em28xx *dev = ptr;
++
++	if (dev->tuner_type != TUNER_XC2028)
++		return 0;
++
++	if (command != XC2028_TUNER_RESET)
++		return 0;
++
++	if (dev->mode == EM28XX_ANALOG_MODE)
++		rc = em28xx_gpio_set(dev, dev->tun_analog_gpio);
++	else
++		rc = em28xx_gpio_set(dev, dev->tun_digital_gpio);
++
++	return rc;
++}
++EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
++
++static void em28xx_set_model(struct em28xx *dev)
++{
++	dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
++	dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
++	dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
++	dev->decoder = em28xx_boards[dev->model].decoder;
++	dev->video_inputs = em28xx_boards[dev->model].vchannels;
++	dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
++	dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
++	dev->has_dvb = em28xx_boards[dev->model].has_dvb;
++}
++
+ /* Since em28xx_pre_card_setup() requires a proper dev->model,
+  * this won't work for boards with generic PCI IDs
+  */
+ void em28xx_pre_card_setup(struct em28xx *dev)
+ {
++	int rc;
++
++	rc = em28xx_read_reg(dev, EM2880_R04_GPO);
++	if (rc >= 0)
++		dev->reg_gpo = rc;
++
++	dev->wait_after_write = 5;
++	rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
++	if (rc > 0) {
++		switch (rc) {
++		case CHIP_ID_EM2883:
++			em28xx_info("chip ID is em2882/em2883\n");
++			dev->wait_after_write = 0;
++			break;
++		default:
++			em28xx_info("em28xx chip ID = %d\n", rc);
++		}
++	}
++	em28xx_set_model(dev);
++
+ 	/* request some modules */
+ 	switch (dev->model) {
+ 	case EM2880_BOARD_TERRATEC_PRODIGY_XS:
+ 	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+-	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+ 	case EM2880_BOARD_TERRATEC_HYBRID_XS:
+-		em28xx_write_regs(dev, XCLK_REG, "\x27", 1);
+-		em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1);
+-		em28xx_write_regs(dev, 0x08, "\xff", 1);
+-		em28xx_write_regs(dev, 0x04, "\x00", 1);
+-		msleep(100);
+-		em28xx_write_regs(dev, 0x04, "\x08", 1);
+-		msleep(100);
+-		em28xx_write_regs(dev, 0x08, "\xff", 1);
+-		msleep(50);
+-		em28xx_write_regs(dev, 0x08, "\x2d", 1);
++	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
++		em28xx_write_regs(dev, EM28XX_R0F_XCLK,    "\x27", 1);
++		em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+ 		msleep(50);
+-		em28xx_write_regs(dev, 0x08, "\x3d", 1);
++
++		/* Sets GPO/GPIO sequences for this device */
++		dev->analog_gpio      = hauppauge_wintv_hvr_900_analog;
++		dev->digital_gpio     = hauppauge_wintv_hvr_900_digital;
++		dev->tun_analog_gpio  = hauppauge_wintv_hvr_900_tuner_callback;
++		dev->tun_digital_gpio = hauppauge_wintv_hvr_900_tuner_callback;
++
+ 		break;
+ 	}
++
++	em28xx_gpio_set(dev, dev->tun_analog_gpio);
++	em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
++
++	/* Unlock device */
++	em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+ }
+ 
+-static int em28xx_tuner_callback(void *ptr, int command, int arg)
++static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
+ {
+-	int rc = 0;
+-	struct em28xx *dev = ptr;
++	memset(ctl, 0, sizeof(*ctl));
+ 
+-	if (dev->tuner_type != TUNER_XC2028)
+-		return 0;
+-
+-	switch (command) {
+-	case XC2028_TUNER_RESET:
+-	{
+-		/* GPIO and initialization codes for analog TV and radio
+-		   This code should be complemented for DTV, since reset
+-		   codes are different.
+-		 */
+-
+-		dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
+-		dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
+-
+-		if (dev->analog_gpio) {
+-			char gpio0 = dev->analog_gpio & 0xff;
+-			char gpio1 = (dev->analog_gpio >> 8) & 0xff;
+-			char gpio4 = dev->analog_gpio >> 24;
+-
+-			if (gpio4) {
+-				dev->em28xx_write_regs(dev, 0x04, &gpio4, 1);
+-				msleep(140);
+-			}
+-
+-			msleep(6);
+-			dev->em28xx_write_regs(dev, 0x08, &gpio0, 1);
+-			msleep(10);
+-			dev->em28xx_write_regs(dev, 0x08, &gpio1, 1);
+-			msleep(5);
+-		}
++	ctl->fname   = XC2028_DEFAULT_FIRMWARE;
++	ctl->max_len = 64;
++	ctl->mts = em28xx_boards[dev->model].mts_firmware;
+ 
++	switch (dev->model) {
++	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
++		ctl->demod = XC3028_FE_ZARLINK456;
+ 		break;
++	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
++		/* FIXME: Better to specify the needed IF */
++		ctl->demod = XC3028_FE_DEFAULT;
++		break;
++	default:
++		ctl->demod = XC3028_FE_OREN538;
+ 	}
+-	}
+-	return rc;
+ }
+ 
+ static void em28xx_config_tuner(struct em28xx *dev)
+ {
+ 	struct v4l2_priv_tun_config  xc2028_cfg;
+-	struct xc2028_ctrl           ctl;
+ 	struct tuner_setup           tun_setup;
+ 	struct v4l2_frequency        f;
+ 
+@@ -552,11 +592,9 @@ static void em28xx_config_tuner(struct em28xx *dev)
+ 	em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+ 
+ 	if (dev->tuner_type == TUNER_XC2028) {
+-		memset(&ctl, 0, sizeof(ctl));
++		struct xc2028_ctrl           ctl;
+ 
+-		ctl.fname   = XC2028_DEFAULT_FIRMWARE;
+-		ctl.max_len = 64;
+-		ctl.mts = em28xx_boards[dev->model].mts_firmware;
++		em28xx_setup_xc3028(dev, &ctl);
+ 
+ 		xc2028_cfg.tuner = TUNER_XC2028;
+ 		xc2028_cfg.priv  = &ctl;
+@@ -654,19 +692,6 @@ static int em28xx_hint_board(struct em28xx *dev)
+ 	return -1;
+ }
+ 
+-
+-static void em28xx_set_model(struct em28xx *dev)
+-{
+-	dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
+-	dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
+-	dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
+-	dev->decoder = em28xx_boards[dev->model].decoder;
+-	dev->video_inputs = em28xx_boards[dev->model].vchannels;
+-	dev->analog_gpio = em28xx_boards[dev->model].analog_gpio;
+-	dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
+-	dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
+-}
+-
+ /* ----------------------------------------------------------------------- */
+ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
+ {
+diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
+index c1caaa8..5d837c1 100644
+--- a/drivers/media/video/em28xx/em28xx-core.c
++++ b/drivers/media/video/em28xx/em28xx-core.c
+@@ -31,104 +31,33 @@
+ 
+ /* #define ENABLE_DEBUG_ISOC_FRAMES */
+ 
+-static unsigned int core_debug = 0;
++static unsigned int core_debug;
+ module_param(core_debug,int,0644);
+ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+ 
+ #define em28xx_coredbg(fmt, arg...) do {\
+ 	if (core_debug) \
+ 		printk(KERN_INFO "%s %s :"fmt, \
+-			 dev->name, __FUNCTION__ , ##arg); } while (0)
++			 dev->name, __func__ , ##arg); } while (0)
+ 
+-static unsigned int reg_debug = 0;
++static unsigned int reg_debug;
+ module_param(reg_debug,int,0644);
+ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
+ 
+ #define em28xx_regdbg(fmt, arg...) do {\
+ 	if (reg_debug) \
+ 		printk(KERN_INFO "%s %s :"fmt, \
+-			 dev->name, __FUNCTION__ , ##arg); } while (0)
+-
+-static unsigned int isoc_debug = 0;
+-module_param(isoc_debug,int,0644);
+-MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]");
+-
+-#define em28xx_isocdbg(fmt, arg...) do {\
+-	if (isoc_debug) \
+-		printk(KERN_INFO "%s %s :"fmt, \
+-			 dev->name, __FUNCTION__ , ##arg); } while (0)
++			 dev->name, __func__ , ##arg); } while (0)
+ 
+ static int alt = EM28XX_PINOUT;
+ module_param(alt, int, 0644);
+ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
+ 
+-
+-/*
+- * em28xx_request_buffers()
+- * allocate a number of buffers
+- */
+-u32 em28xx_request_buffers(struct em28xx *dev, u32 count)
+-{
+-	const size_t imagesize = PAGE_ALIGN(dev->frame_size);	/*needs to be page aligned cause the buffers can be mapped individually! */
+-	void *buff = NULL;
+-	u32 i;
+-	em28xx_coredbg("requested %i buffers with size %zi\n",
+-			count, imagesize);
+-	if (count > EM28XX_NUM_FRAMES)
+-		count = EM28XX_NUM_FRAMES;
+-
+-	dev->num_frames = count;
+-	while (dev->num_frames > 0) {
+-		if ((buff = vmalloc_32(dev->num_frames * imagesize))) {
+-			memset(buff, 0, dev->num_frames * imagesize);
+-			break;
+-		}
+-		dev->num_frames--;
+-	}
+-
+-	for (i = 0; i < dev->num_frames; i++) {
+-		dev->frame[i].bufmem = buff + i * imagesize;
+-		dev->frame[i].buf.index = i;
+-		dev->frame[i].buf.m.offset = i * imagesize;
+-		dev->frame[i].buf.length = dev->frame_size;
+-		dev->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		dev->frame[i].buf.sequence = 0;
+-		dev->frame[i].buf.field = V4L2_FIELD_NONE;
+-		dev->frame[i].buf.memory = V4L2_MEMORY_MMAP;
+-		dev->frame[i].buf.flags = 0;
+-	}
+-	return dev->num_frames;
+-}
+-
+-/*
+- * em28xx_queue_unusedframes()
+- * add all frames that are not currently in use to the inbuffer queue
+- */
+-void em28xx_queue_unusedframes(struct em28xx *dev)
+-{
+-	unsigned long lock_flags;
+-	u32 i;
+-
+-	for (i = 0; i < dev->num_frames; i++)
+-		if (dev->frame[i].state == F_UNUSED) {
+-			dev->frame[i].state = F_QUEUED;
+-			spin_lock_irqsave(&dev->queue_lock, lock_flags);
+-			list_add_tail(&dev->frame[i].frame, &dev->inqueue);
+-			spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+-		}
+-}
+-
+-/*
+- * em28xx_release_buffers()
+- * free frame buffers
+- */
+-void em28xx_release_buffers(struct em28xx *dev)
+-{
+-	if (dev->num_frames) {
+-		vfree(dev->frame[0].bufmem);
+-		dev->num_frames = 0;
+-	}
+-}
++/* FIXME */
++#define em28xx_isocdbg(fmt, arg...) do {\
++	if (core_debug) \
++		printk(KERN_INFO "%s %s :"fmt, \
++			 dev->name, __func__ , ##arg); } while (0)
+ 
+ /*
+  * em28xx_read_reg_req()
+@@ -148,11 +77,11 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
+ 			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 			      0x0000, reg, buf, len, HZ);
+ 
+-	if (reg_debug){
++	if (reg_debug) {
+ 		printk(ret < 0 ? " failed!\n" : "%02x values: ", ret);
+-		for (byte = 0; byte < len; byte++) {
++		for (byte = 0; byte < len; byte++)
+ 			printk(" %02x", (unsigned char)buf[byte]);
+-		}
++
+ 		printk("\n");
+ 	}
+ 
+@@ -205,7 +134,10 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
+ 	unsigned char *bufs;
+ 
+ 	if (dev->state & DEV_DISCONNECTED)
+-		return(-ENODEV);
++		return -ENODEV;
++
++	if (len < 1)
++		return -EINVAL;
+ 
+ 	bufs = kmalloc(len, GFP_KERNEL);
+ 
+@@ -214,8 +146,8 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
+ 	if (reg_debug) {
+ 		int i;
+ 		for (i = 0; i < len; ++i)
+-			printk (" %02x", (unsigned char)buf[i]);
+-		printk ("\n");
++			printk(" %02x", (unsigned char)buf[i]);
++		printk("\n");
+ 	}
+ 
+ 	if (!bufs)
+@@ -224,14 +156,32 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
+ 	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
+ 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 			      0x0000, reg, bufs, len, HZ);
+-	msleep(5);		/* FIXME: magic number */
++	if (dev->wait_after_write)
++		msleep(dev->wait_after_write);
++
+ 	kfree(bufs);
+ 	return ret;
+ }
+ 
+ int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
+ {
+-	return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
++	int rc;
++
++	rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
++
++	/* Stores GPO/GPIO values at the cache, if changed
++	   Only write values should be stored, since input on a GPIO
++	   register will return the input bits.
++	   Not sure what happens on reading GPO register.
++	 */
++	if (rc >= 0) {
++		if (reg == EM2880_R04_GPO)
++			dev->reg_gpo = buf[0];
++		else if (reg == EM28XX_R08_GPIO)
++			dev->reg_gpio = buf[0];
++	}
++
++	return rc;
+ }
+ 
+ /*
+@@ -244,9 +194,20 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
+ {
+ 	int oldval;
+ 	u8 newval;
+-	if ((oldval = em28xx_read_reg(dev, reg)) < 0)
++
++	/* Uses cache for gpo/gpio registers */
++	if (reg == EM2880_R04_GPO)
++		oldval = dev->reg_gpo;
++	else if (reg == EM28XX_R08_GPIO)
++		oldval = dev->reg_gpio;
++	else
++		oldval = em28xx_read_reg(dev, reg);
++
++	if (oldval < 0)
+ 		return oldval;
++
+ 	newval = (((u8) oldval) & ~bitmask) | (val & bitmask);
++
+ 	return em28xx_write_regs(dev, reg, &newval, 1);
+ }
+ 
+@@ -258,20 +219,26 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
+ {
+ 	int ret, i;
+ 	u8 addr = reg & 0x7f;
+-	if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0)
++
++	ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, val, 2);
++	if (ret < 0)
+ 		return ret;
+-	if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0)
++
++	ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1);
++	if (ret < 0)
+ 		return ret;
+ 
+ 	/* Wait up to 50 ms for AC97 command to complete */
+ 	for (i = 0; i < 10; i++) {
+-		if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
++		ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY);
++		if (ret < 0)
+ 			return ret;
++
+ 		if (!(ret & 0x01))
+ 			return 0;
+ 		msleep(5);
+ 	}
+-	em28xx_warn ("AC97 command still being executed: not handled properly!\n");
++	em28xx_warn("AC97 command still being executed: not handled properly!\n");
+ 	return 0;
+ }
+ 
+@@ -289,7 +256,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
+ 		else
+ 			input = EM2800_AUDIO_SRC_TUNER;
+ 
+-		ret = em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &input, 1);
++		ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1);
+ 		if (ret < 0)
+ 			return ret;
+ 	}
+@@ -315,7 +282,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
+ 		}
+ 	}
+ 
+-	ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
++	ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0);
+ 	if (ret < 0)
+ 		return ret;
+ 	msleep(5);
+@@ -323,11 +290,11 @@ static int em28xx_set_audio_source(struct em28xx *dev)
+ 	/* Sets AC97 mixer registers
+ 	   This is seems to be needed, even for non-ac97 configs
+ 	 */
+-	ret = em28xx_write_ac97(dev, VIDEO_AC97, video);
++	ret = em28xx_write_ac97(dev, EM28XX_R14_VIDEO_AC97, video);
+ 	if (ret < 0)
+ 		return ret;
+ 
+-	ret = em28xx_write_ac97(dev, LINE_IN_AC97, line);
++	ret = em28xx_write_ac97(dev, EM28XX_R10_LINE_IN_AC97, line);
+ 
+ 	return ret;
+ }
+@@ -343,7 +310,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
+ 
+ 	/* Mute */
+ 	s[1] |= 0x80;
+-	ret = em28xx_write_ac97(dev, MASTER_AC97, s);
++	ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
+ 
+ 	if (ret < 0)
+ 		return ret;
+@@ -354,7 +321,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
+ 	if (!dev->mute)
+ 		xclk |= 0x80;
+ 
+-	ret = em28xx_write_reg_bits(dev, XCLK_REG, xclk, 0xa7);
++	ret = em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, xclk, 0xa7);
+ 	if (ret < 0)
+ 		return ret;
+ 	msleep(10);
+@@ -365,7 +332,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
+ 	/* Unmute device */
+ 	if (!dev->mute)
+ 		s[1] &= ~0x80;
+-	ret = em28xx_write_ac97(dev, MASTER_AC97, s);
++	ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
+ 
+ 	return ret;
+ }
+@@ -373,50 +340,68 @@ EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
+ 
+ int em28xx_colorlevels_set_default(struct em28xx *dev)
+ {
+-	em28xx_write_regs(dev, YGAIN_REG, "\x10", 1);	/* contrast */
+-	em28xx_write_regs(dev, YOFFSET_REG, "\x00", 1);	/* brightness */
+-	em28xx_write_regs(dev, UVGAIN_REG, "\x10", 1);	/* saturation */
+-	em28xx_write_regs(dev, UOFFSET_REG, "\x00", 1);
+-	em28xx_write_regs(dev, VOFFSET_REG, "\x00", 1);
+-	em28xx_write_regs(dev, SHARPNESS_REG, "\x00", 1);
+-
+-	em28xx_write_regs(dev, GAMMA_REG, "\x20", 1);
+-	em28xx_write_regs(dev, RGAIN_REG, "\x20", 1);
+-	em28xx_write_regs(dev, GGAIN_REG, "\x20", 1);
+-	em28xx_write_regs(dev, BGAIN_REG, "\x20", 1);
+-	em28xx_write_regs(dev, ROFFSET_REG, "\x00", 1);
+-	em28xx_write_regs(dev, GOFFSET_REG, "\x00", 1);
+-	return em28xx_write_regs(dev, BOFFSET_REG, "\x00", 1);
++	em28xx_write_regs(dev, EM28XX_R20_YGAIN, "\x10", 1);	/* contrast */
++	em28xx_write_regs(dev, EM28XX_R21_YOFFSET, "\x00", 1);	/* brightness */
++	em28xx_write_regs(dev, EM28XX_R22_UVGAIN, "\x10", 1);	/* saturation */
++	em28xx_write_regs(dev, EM28XX_R23_UOFFSET, "\x00", 1);
++	em28xx_write_regs(dev, EM28XX_R24_VOFFSET, "\x00", 1);
++	em28xx_write_regs(dev, EM28XX_R25_SHARPNESS, "\x00", 1);
++
++	em28xx_write_regs(dev, EM28XX_R14_GAMMA, "\x20", 1);
++	em28xx_write_regs(dev, EM28XX_R15_RGAIN, "\x20", 1);
++	em28xx_write_regs(dev, EM28XX_R16_GGAIN, "\x20", 1);
++	em28xx_write_regs(dev, EM28XX_R17_BGAIN, "\x20", 1);
++	em28xx_write_regs(dev, EM28XX_R18_ROFFSET, "\x00", 1);
++	em28xx_write_regs(dev, EM28XX_R19_GOFFSET, "\x00", 1);
++	return em28xx_write_regs(dev, EM28XX_R1A_BOFFSET, "\x00", 1);
+ }
+ 
+ int em28xx_capture_start(struct em28xx *dev, int start)
+ {
+-	int ret;
++	int rc;
+ 	/* FIXME: which is the best order? */
+ 	/* video registers are sampled by VREF */
+-	if ((ret = em28xx_write_reg_bits(dev, USBSUSP_REG, start ? 0x10 : 0x00,
+-					  0x10)) < 0)
+-		return ret;
++	rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
++				   start ? 0x10 : 0x00, 0x10);
++	if (rc < 0)
++		return rc;
++
++	if (!start) {
++		/* disable video capture */
++		rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x27", 1);
++		return rc;
++	}
++
+ 	/* enable video capture */
+-	return em28xx_write_regs(dev, VINENABLE_REG, start ? "\x67" : "\x27", 1);
++	rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
++
++	if (dev->mode == EM28XX_ANALOG_MODE)
++		rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x67", 1);
++	else
++		rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x37", 1);
++
++	msleep(6);
++
++	return rc;
+ }
+ 
+ int em28xx_outfmt_set_yuv422(struct em28xx *dev)
+ {
+-	em28xx_write_regs(dev, OUTFMT_REG, "\x34", 1);
+-	em28xx_write_regs(dev, VINMODE_REG, "\x10", 1);
+-	return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1);
++	em28xx_write_regs(dev, EM28XX_R27_OUTFMT, "\x34", 1);
++	em28xx_write_regs(dev, EM28XX_R10_VINMODE, "\x10", 1);
++	return em28xx_write_regs(dev, EM28XX_R11_VINCTRL, "\x11", 1);
+ }
+ 
+ static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
+ 				  u8 ymin, u8 ymax)
+ {
+-	em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax);
++	em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
++			xmin, ymin, xmax, ymax);
+ 
+-	em28xx_write_regs(dev, XMIN_REG, &xmin, 1);
+-	em28xx_write_regs(dev, XMAX_REG, &xmax, 1);
+-	em28xx_write_regs(dev, YMIN_REG, &ymin, 1);
+-	return em28xx_write_regs(dev, YMAX_REG, &ymax, 1);
++	em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
++	em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
++	em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
++	return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
+ }
+ 
+ static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
+@@ -426,34 +411,36 @@ static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
+ 	u8 cheight = height;
+ 	u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01);
+ 
+-	em28xx_coredbg("em28xx Area Set: (%d,%d)\n", (width | (overflow & 2) << 7),
++	em28xx_coredbg("em28xx Area Set: (%d,%d)\n",
++			(width | (overflow & 2) << 7),
+ 			(height | (overflow & 1) << 8));
+ 
+-	em28xx_write_regs(dev, HSTART_REG, &hstart, 1);
+-	em28xx_write_regs(dev, VSTART_REG, &vstart, 1);
+-	em28xx_write_regs(dev, CWIDTH_REG, &cwidth, 1);
+-	em28xx_write_regs(dev, CHEIGHT_REG, &cheight, 1);
+-	return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1);
++	em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
++	em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
++	em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
++	em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
++	return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
+ }
+ 
+ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
+ {
+ 	u8 mode;
+ 	/* the em2800 scaler only supports scaling down to 50% */
+-	if(dev->is_em2800)
++	if (dev->is_em2800)
+ 		mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
+ 	else {
+ 		u8 buf[2];
+ 		buf[0] = h;
+ 		buf[1] = h >> 8;
+-		em28xx_write_regs(dev, HSCALELOW_REG, (char *)buf, 2);
++		em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
+ 		buf[0] = v;
+ 		buf[1] = v >> 8;
+-		em28xx_write_regs(dev, VSCALELOW_REG, (char *)buf, 2);
+-		/* it seems that both H and V scalers must be active to work correctly */
++		em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
++		/* it seems that both H and V scalers must be active
++		   to work correctly */
+ 		mode = (h || v)? 0x30: 0x00;
+ 	}
+-	return em28xx_write_reg_bits(dev, COMPR_REG, mode, 0x30);
++	return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
+ }
+ 
+ /* FIXME: this only function read values from dev */
+@@ -469,376 +456,271 @@ int em28xx_resolution_set(struct em28xx *dev)
+ 	return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
+ }
+ 
+-
+-/******************* isoc transfer handling ****************************/
+-
+-#ifdef ENABLE_DEBUG_ISOC_FRAMES
+-static void em28xx_isoc_dump(struct urb *urb)
++int em28xx_set_alternate(struct em28xx *dev)
+ {
+-	int len = 0;
+-	int ntrans = 0;
++	int errCode, prev_alt = dev->alt;
+ 	int i;
++	unsigned int min_pkt_size = dev->width * 2 + 4;
+ 
+-	printk(KERN_DEBUG "isocIrq: sf=%d np=%d ec=%x\n",
+-	       urb->start_frame, urb->number_of_packets,
+-	       urb->error_count);
+-	for (i = 0; i < urb->number_of_packets; i++) {
+-		unsigned char *buf =
+-				urb->transfer_buffer +
+-				urb->iso_frame_desc[i].offset;
+-		int alen = urb->iso_frame_desc[i].actual_length;
+-		if (alen > 0) {
+-			if (buf[0] == 0x88) {
+-				ntrans++;
+-				len += alen;
+-			} else if (buf[0] == 0x22) {
+-				printk(KERN_DEBUG
+-						"= l=%d nt=%d bpp=%d\n",
+-				len - 4 * ntrans, ntrans,
+-				ntrans == 0 ? 0 : len / ntrans);
+-				ntrans = 1;
+-				len = alen;
+-			} else
+-				printk(KERN_DEBUG "!\n");
++	/* When image size is bigger than a certain value,
++	   the frame size should be increased, otherwise, only
++	   green screen will be received.
++	 */
++	if (dev->width * 2 * dev->height > 720 * 240 * 2)
++		min_pkt_size *= 2;
++
++	for (i = 0; i < dev->num_alt; i++) {
++		/* stop when the selected alt setting offers enough bandwidth */
++		if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
++			dev->alt = i;
++			break;
++		/* otherwise make sure that we end up with the maximum bandwidth
++		   because the min_pkt_size equation might be wrong...
++		*/
++		} else if (dev->alt_max_pkt_size[i] >
++			   dev->alt_max_pkt_size[dev->alt])
++			dev->alt = i;
++	}
++
++	if (dev->alt != prev_alt) {
++		em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
++				min_pkt_size, dev->alt);
++		dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
++		em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
++			       dev->alt, dev->max_pkt_size);
++		errCode = usb_set_interface(dev->udev, 0, dev->alt);
++		if (errCode < 0) {
++			em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
++					dev->alt, errCode);
++			return errCode;
+ 		}
+-		printk(KERN_DEBUG "   n=%d s=%d al=%d %x\n", i,
+-		       urb->iso_frame_desc[i].status,
+-		       urb->iso_frame_desc[i].actual_length,
+-		       (unsigned int)
+-				       *((unsigned char *)(urb->transfer_buffer +
+-				       urb->iso_frame_desc[i].
+-				       offset)));
+ 	}
++	return 0;
+ }
+-#endif
+ 
+-static inline int em28xx_isoc_video(struct em28xx *dev,struct em28xx_frame_t **f,
+-				    unsigned long *lock_flags, unsigned char buf)
++int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
+ {
+-	if (!(buf & 0x01)) {
+-		if ((*f)->state == F_GRABBING) {
+-			/*previous frame is incomplete */
+-			if ((*f)->fieldbytesused < dev->field_size) {
+-				(*f)->state = F_ERROR;
+-				em28xx_isocdbg ("dropping incomplete bottom field (%i missing bytes)",
+-					 dev->field_size-(*f)->fieldbytesused);
+-			} else {
+-				(*f)->state = F_DONE;
+-				(*f)->buf.bytesused = dev->frame_size;
+-			}
+-		}
+-		if ((*f)->state == F_DONE || (*f)->state == F_ERROR) {
+-			/* move current frame to outqueue and get next free buffer from inqueue */
+-			spin_lock_irqsave(&dev-> queue_lock, *lock_flags);
+-			list_move_tail(&(*f)->frame, &dev->outqueue);
+-			if (!list_empty(&dev->inqueue))
+-				(*f) = list_entry(dev-> inqueue.next,
+-			struct em28xx_frame_t,frame);
+-			else
+-				(*f) = NULL;
+-			spin_unlock_irqrestore(&dev->queue_lock,*lock_flags);
+-		}
+-		if (!(*f)) {
+-			em28xx_isocdbg ("new frame but no buffer is free");
+-			return -1;
+-		}
+-		do_gettimeofday(&(*f)->buf.timestamp);
+-		(*f)->buf.sequence = ++dev->frame_count;
+-		(*f)->buf.field = V4L2_FIELD_INTERLACED;
+-		(*f)->state = F_GRABBING;
+-		(*f)->buf.bytesused = 0;
+-		(*f)->top_field = 1;
+-		(*f)->fieldbytesused = 0;
+-	} else {
+-					/* acquiring bottom field */
+-		if ((*f)->state == F_GRABBING) {
+-			if (!(*f)->top_field) {
+-				(*f)->state = F_ERROR;
+-				em28xx_isocdbg ("unexpected begin of bottom field; discarding it");
+-			} else if ((*f)-> fieldbytesused < dev->field_size - 172) {
+-				(*f)->state = F_ERROR;
+-				em28xx_isocdbg ("dropping incomplete top field (%i missing bytes)",
+-					 dev->field_size-(*f)->fieldbytesused);
+-			} else {
+-				(*f)->top_field = 0;
+-				(*f)->fieldbytesused = 0;
+-			}
++	int rc = 0;
++
++	if (!gpio)
++		return rc;
++
++	dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
++	if (dev->mode == EM28XX_ANALOG_MODE)
++		dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
++	else
++		dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1);
++	msleep(6);
++
++	/* Send GPIO reset sequences specified at board entry */
++	while (gpio->sleep >= 0) {
++		if (gpio->reg >= 0) {
++			rc = em28xx_write_reg_bits(dev,
++						   gpio->reg,
++						   gpio->val,
++						   gpio->mask);
++			if (rc < 0)
++				return rc;
+ 		}
++		if (gpio->sleep > 0)
++			msleep(gpio->sleep);
++
++		gpio++;
+ 	}
+-	return (0);
++	return rc;
+ }
+ 
+-static inline void em28xx_isoc_video_copy(struct em28xx *dev,
+-					  struct em28xx_frame_t **f, unsigned char *buf, int len)
++int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
+ {
+-	void *fieldstart, *startwrite, *startread;
+-	int linesdone, currlinedone, offset, lencopy,remain;
++	if (dev->mode == set_mode)
++		return 0;
+ 
+-	if(dev->frame_size != (*f)->buf.length){
+-		em28xx_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length);
+-		return;
++	if (set_mode == EM28XX_MODE_UNDEFINED) {
++		dev->mode = set_mode;
++		return 0;
+ 	}
+ 
+-	if ((*f)->fieldbytesused + len > dev->field_size)
+-		len =dev->field_size - (*f)->fieldbytesused;
+-
+-	if (buf[0] != 0x88 && buf[0] != 0x22) {
+-		em28xx_isocdbg("frame is not complete\n");
+-		startread = buf;
+-		len+=4;
+-	} else
+-		startread = buf + 4;
+-
+-	remain = len;
++	dev->mode = set_mode;
+ 
+-	if ((*f)->top_field)
+-		fieldstart = (*f)->bufmem;
++	if (dev->mode == EM28XX_DIGITAL_MODE)
++		return em28xx_gpio_set(dev, dev->digital_gpio);
+ 	else
+-		fieldstart = (*f)->bufmem + dev->bytesperline;
+-
+-	linesdone = (*f)->fieldbytesused / dev->bytesperline;
+-	currlinedone = (*f)->fieldbytesused % dev->bytesperline;
+-	offset = linesdone * dev->bytesperline * 2 + currlinedone;
+-	startwrite = fieldstart + offset;
+-	lencopy = dev->bytesperline - currlinedone;
+-	lencopy = lencopy > remain ? remain : lencopy;
+-
+-	memcpy(startwrite, startread, lencopy);
+-	remain -= lencopy;
+-
+-	while (remain > 0) {
+-		startwrite += lencopy + dev->bytesperline;
+-		startread += lencopy;
+-		if (dev->bytesperline > remain)
+-			lencopy = remain;
+-		else
+-			lencopy = dev->bytesperline;
+-
+-		memcpy(startwrite, startread, lencopy);
+-		remain -= lencopy;
+-	}
+-
+-	(*f)->fieldbytesused += len;
++		return em28xx_gpio_set(dev, dev->analog_gpio);
+ }
++EXPORT_SYMBOL_GPL(em28xx_set_mode);
++
++/* ------------------------------------------------------------------
++	URB control
++   ------------------------------------------------------------------*/
+ 
+ /*
+- * em28xx_isoIrq()
+- * handles the incoming isoc urbs and fills the frames from our inqueue
++ * IRQ callback, called by URB callback
+  */
+-static void em28xx_isocIrq(struct urb *urb)
++static void em28xx_irq_callback(struct urb *urb)
+ {
+-	struct em28xx *dev = urb->context;
+-	int i, status;
+-	struct em28xx_frame_t **f;
+-	unsigned long lock_flags;
+-
+-	if (!dev)
+-		return;
+-#ifdef ENABLE_DEBUG_ISOC_FRAMES
+-	if (isoc_debug>1)
+-		em28xx_isoc_dump(urb);
+-#endif
+-
+-	if (urb->status == -ENOENT)
+-		return;
+-
+-	f = &dev->frame_current;
+-
+-	if (dev->stream == STREAM_INTERRUPT) {
+-		dev->stream = STREAM_OFF;
+-		if ((*f))
+-			(*f)->state = F_QUEUED;
+-		em28xx_isocdbg("stream interrupted");
+-		wake_up_interruptible(&dev->wait_stream);
+-	}
+-
+-	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+-		return;
+-
+-	if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) {
+-		if (!(*f))
+-			(*f) = list_entry(dev->inqueue.next,
+-		struct em28xx_frame_t, frame);
+-
+-		for (i = 0; i < urb->number_of_packets; i++) {
+-			unsigned char *buf = urb->transfer_buffer +
+-					urb->iso_frame_desc[i].offset;
+-			int len = urb->iso_frame_desc[i].actual_length - 4;
+-
+-			if (urb->iso_frame_desc[i].status) {
+-				em28xx_isocdbg("data error: [%d] len=%d, status=%d", i,
+-					urb->iso_frame_desc[i].actual_length,
+-					urb->iso_frame_desc[i].status);
+-				if (urb->iso_frame_desc[i].status != -EPROTO)
+-					continue;
+-			}
+-			if (urb->iso_frame_desc[i].actual_length <= 0) {
+-				em28xx_isocdbg("packet %d is empty",i);
+-				continue;
+-			}
+-			if (urb->iso_frame_desc[i].actual_length >
+-			    urb->iso_frame_desc[i].length) {
+-				em28xx_isocdbg("packet bigger than packet size");
+-				continue;
+-			}
+-			/*new frame */
+-			if (buf[0] == 0x22 && buf[1] == 0x5a) {
+-				em28xx_isocdbg("Video frame, length=%i!",len);
+-
+-				if (em28xx_isoc_video(dev,f,&lock_flags,buf[2]))
+-				break;
+-			} else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) {
+-				em28xx_isocdbg("VBI HEADER!!!");
+-			}
++	struct em28xx_dmaqueue  *dma_q = urb->context;
++	struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
++	int rc, i;
+ 
+-			/* actual copying */
+-			if ((*f)->state == F_GRABBING) {
+-				em28xx_isoc_video_copy(dev,f,buf, len);
+-			}
+-		}
+-	}
++	/* Copy data from URB */
++	spin_lock(&dev->slock);
++	rc = dev->isoc_ctl.isoc_copy(dev, urb);
++	spin_unlock(&dev->slock);
+ 
++	/* Reset urb buffers */
+ 	for (i = 0; i < urb->number_of_packets; i++) {
+ 		urb->iso_frame_desc[i].status = 0;
+ 		urb->iso_frame_desc[i].actual_length = 0;
+ 	}
+-
+ 	urb->status = 0;
+-	if ((status = usb_submit_urb(urb, GFP_ATOMIC))) {
+-		em28xx_errdev("resubmit of urb failed (error=%i)\n", status);
+-		dev->state |= DEV_MISCONFIGURED;
++
++	urb->status = usb_submit_urb(urb, GFP_ATOMIC);
++	if (urb->status) {
++		em28xx_isocdbg("urb resubmit failed (error=%i)\n",
++			       urb->status);
+ 	}
+-	wake_up_interruptible(&dev->wait_frame);
+-	return;
+ }
+ 
+ /*
+- * em28xx_uninit_isoc()
+- * deallocates the buffers and urbs allocated during em28xx_init_iosc()
++ * Stop and Deallocate URBs
+  */
+ void em28xx_uninit_isoc(struct em28xx *dev)
+ {
++	struct urb *urb;
+ 	int i;
+ 
+-	for (i = 0; i < EM28XX_NUM_BUFS; i++) {
+-		if (dev->urb[i]) {
+-			usb_kill_urb(dev->urb[i]);
+-			if (dev->transfer_buffer[i]) {
++	em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n");
++
++	dev->isoc_ctl.nfields = -1;
++	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
++		urb = dev->isoc_ctl.urb[i];
++		if (urb) {
++			usb_kill_urb(urb);
++			usb_unlink_urb(urb);
++			if (dev->isoc_ctl.transfer_buffer[i]) {
+ 				usb_buffer_free(dev->udev,
+-						dev->urb[i]->transfer_buffer_length,
+-						dev->transfer_buffer[i],
+-						dev->urb[i]->transfer_dma);
++					urb->transfer_buffer_length,
++					dev->isoc_ctl.transfer_buffer[i],
++					urb->transfer_dma);
+ 			}
+-			usb_free_urb(dev->urb[i]);
++			usb_free_urb(urb);
++			dev->isoc_ctl.urb[i] = NULL;
+ 		}
+-		dev->urb[i] = NULL;
+-		dev->transfer_buffer[i] = NULL;
++		dev->isoc_ctl.transfer_buffer[i] = NULL;
+ 	}
++
++	kfree(dev->isoc_ctl.urb);
++	kfree(dev->isoc_ctl.transfer_buffer);
++
++	dev->isoc_ctl.urb = NULL;
++	dev->isoc_ctl.transfer_buffer = NULL;
++	dev->isoc_ctl.num_bufs = 0;
++
+ 	em28xx_capture_start(dev, 0);
+ }
++EXPORT_SYMBOL_GPL(em28xx_uninit_isoc);
+ 
+ /*
+- * em28xx_init_isoc()
+- * allocates transfer buffers and submits the urbs for isoc transfer
++ * Allocate URBs and start IRQ
+  */
+-int em28xx_init_isoc(struct em28xx *dev)
++int em28xx_init_isoc(struct em28xx *dev, int max_packets,
++		     int num_bufs, int max_pkt_size,
++		     int (*isoc_copy) (struct em28xx *dev, struct urb *urb))
+ {
+-	/* change interface to 3 which allows the biggest packet sizes */
+-	int i, errCode;
+-	int sb_size;
+-
+-	em28xx_set_alternate(dev);
+-	sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
+-
+-	/* reset streaming vars */
+-	dev->frame_current = NULL;
+-	dev->frame_count = 0;
+-
+-	/* allocate urbs */
+-	for (i = 0; i < EM28XX_NUM_BUFS; i++) {
+-		struct urb *urb;
+-		int j;
+-		/* allocate transfer buffer */
+-		urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);
+-		if (!urb){
+-			em28xx_errdev("cannot alloc urb %i\n", i);
++	struct em28xx_dmaqueue *dma_q = &dev->vidq;
++	int i;
++	int sb_size, pipe;
++	struct urb *urb;
++	int j, k;
++	int rc;
++
++	em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n");
++
++	/* De-allocates all pending stuff */
++	em28xx_uninit_isoc(dev);
++
++	dev->isoc_ctl.isoc_copy = isoc_copy;
++	dev->isoc_ctl.num_bufs = num_bufs;
++
++	dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
++	if (!dev->isoc_ctl.urb) {
++		em28xx_errdev("cannot alloc memory for usb buffers\n");
++		return -ENOMEM;
++	}
++
++	dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
++					      GFP_KERNEL);
++	if (!dev->isoc_ctl.transfer_buffer) {
++		em28xx_errdev("cannot allocate memory for usbtransfer\n");
++		kfree(dev->isoc_ctl.urb);
++		return -ENOMEM;
++	}
++
++	dev->isoc_ctl.max_pkt_size = max_pkt_size;
++	dev->isoc_ctl.buf = NULL;
++
++	sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
++
++	/* allocate urbs and transfer buffers */
++	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
++		urb = usb_alloc_urb(max_packets, GFP_KERNEL);
++		if (!urb) {
++			em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
+ 			em28xx_uninit_isoc(dev);
+ 			return -ENOMEM;
+ 		}
+-		dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size,
+-							   GFP_KERNEL,
+-							   &urb->transfer_dma);
+-		if (!dev->transfer_buffer[i]) {
+-			em28xx_errdev
+-					("unable to allocate %i bytes for transfer buffer %i\n",
+-					 sb_size, i);
++		dev->isoc_ctl.urb[i] = urb;
++
++		dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
++			sb_size, GFP_KERNEL, &urb->transfer_dma);
++		if (!dev->isoc_ctl.transfer_buffer[i]) {
++			em28xx_err("unable to allocate %i bytes for transfer"
++					" buffer %i%s\n",
++					sb_size, i,
++					in_interrupt()?" while in int":"");
+ 			em28xx_uninit_isoc(dev);
+-			usb_free_urb(urb);
+ 			return -ENOMEM;
+ 		}
+-		memset(dev->transfer_buffer[i], 0, sb_size);
+-		urb->dev = dev->udev;
+-		urb->context = dev;
+-		urb->pipe = usb_rcvisocpipe(dev->udev, 0x82);
+-		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+-		urb->interval = 1;
+-		urb->transfer_buffer = dev->transfer_buffer[i];
+-		urb->complete = em28xx_isocIrq;
+-		urb->number_of_packets = EM28XX_NUM_PACKETS;
+-		urb->transfer_buffer_length = sb_size;
+-		for (j = 0; j < EM28XX_NUM_PACKETS; j++) {
+-			urb->iso_frame_desc[j].offset = j * dev->max_pkt_size;
+-			urb->iso_frame_desc[j].length = dev->max_pkt_size;
++		memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
++
++		/* FIXME: this is a hack - should be
++			'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
++			should also be using 'desc.bInterval'
++		 */
++		pipe = usb_rcvisocpipe(dev->udev,
++			dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84);
++
++		usb_fill_int_urb(urb, dev->udev, pipe,
++				 dev->isoc_ctl.transfer_buffer[i], sb_size,
++				 em28xx_irq_callback, dma_q, 1);
++
++		urb->number_of_packets = max_packets;
++		urb->transfer_flags = URB_ISO_ASAP;
++
++		k = 0;
++		for (j = 0; j < max_packets; j++) {
++			urb->iso_frame_desc[j].offset = k;
++			urb->iso_frame_desc[j].length =
++						dev->isoc_ctl.max_pkt_size;
++			k += dev->isoc_ctl.max_pkt_size;
+ 		}
+-		dev->urb[i] = urb;
+ 	}
+ 
+-	/* submit urbs */
+-	em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n",
+-		       EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size);
+-	for (i = 0; i < EM28XX_NUM_BUFS; i++) {
+-		errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL);
+-		if (errCode) {
+-			em28xx_errdev("submit of urb %i failed (error=%i)\n", i,
+-				      errCode);
+-			em28xx_uninit_isoc(dev);
+-			return errCode;
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-int em28xx_set_alternate(struct em28xx *dev)
+-{
+-	int errCode, prev_alt = dev->alt;
+-	int i;
+-	unsigned int min_pkt_size = dev->bytesperline+4;
+-
+-	/* When image size is bigger than a ceirtain value,
+-	   the frame size should be increased, otherwise, only
+-	   green screen will be received.
+-	 */
+-	if (dev->frame_size > 720*240*2)
+-		min_pkt_size *= 2;
++	init_waitqueue_head(&dma_q->wq);
+ 
+-	for (i = 0; i < dev->num_alt; i++)
+-		if (dev->alt_max_pkt_size[i] >= min_pkt_size)
+-			break;
+-	dev->alt = i;
++	em28xx_capture_start(dev, 1);
+ 
+-	if (dev->alt != prev_alt) {
+-		em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+-				min_pkt_size, dev->alt);
+-		dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+-		em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
+-			       dev->alt, dev->max_pkt_size);
+-		errCode = usb_set_interface(dev->udev, 0, dev->alt);
+-		if (errCode < 0) {
+-			em28xx_errdev ("cannot change alternate number to %d (error=%i)\n",
+-					dev->alt, errCode);
+-			return errCode;
++	/* submit urbs and enables IRQ */
++	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
++		rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
++		if (rc) {
++			em28xx_err("submit of urb %i failed (error=%i)\n", i,
++				   rc);
++			em28xx_uninit_isoc(dev);
++			return rc;
+ 		}
+ 	}
++
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(em28xx_init_isoc);
+diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
+new file mode 100644
+index 0000000..7df8157
+--- /dev/null
++++ b/drivers/media/video/em28xx/em28xx-dvb.c
+@@ -0,0 +1,474 @@
++/*
++ DVB device driver for em28xx
++
++ (c) 2008 Mauro Carvalho Chehab <mchehab at infradead.org>
++
++ (c) 2008 Devin Heitmueller <devin.heitmueller at gmail.com>
++	- Fixes for the driver to properly work with HVR-950
++
++ (c) 2008 Aidan Thornton <makosoft at googlemail.com>
++
++ Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
++	(c) 2004, 2005 Chris Pascoe <c.pascoe at itee.uq.edu.au>
++	(c) 2004 Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License.
++ */
++
++#include <linux/kernel.h>
++#include <linux/usb.h>
++
++#include "em28xx.h"
++#include <media/v4l2-common.h>
++#include <media/videobuf-vmalloc.h>
++
++#include "lgdt330x.h"
++#include "zl10353.h"
++
++MODULE_DESCRIPTION("driver for em28xx based DVB cards");
++MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
++MODULE_LICENSE("GPL");
++
++static unsigned int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
++#define dprintk(level, fmt, arg...) do {			\
++if (debug >= level) 						\
++	printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg);	\
++} while (0)
++
++#define EM28XX_DVB_NUM_BUFS 5
++#define EM28XX_DVB_MAX_PACKETSIZE 564
++#define EM28XX_DVB_MAX_PACKETS 64
++
++struct em28xx_dvb {
++	struct dvb_frontend        *frontend;
++
++	/* feed count management */
++	struct mutex               lock;
++	int                        nfeeds;
++
++	/* general boilerplate stuff */
++	struct dvb_adapter         adapter;
++	struct dvb_demux           demux;
++	struct dmxdev              dmxdev;
++	struct dmx_frontend        fe_hw;
++	struct dmx_frontend        fe_mem;
++	struct dvb_net             net;
++};
++
++
++static inline void print_err_status(struct em28xx *dev,
++				     int packet, int status)
++{
++	char *errmsg = "Unknown";
++
++	switch (status) {
++	case -ENOENT:
++		errmsg = "unlinked synchronuously";
++		break;
++	case -ECONNRESET:
++		errmsg = "unlinked asynchronuously";
++		break;
++	case -ENOSR:
++		errmsg = "Buffer error (overrun)";
++		break;
++	case -EPIPE:
++		errmsg = "Stalled (device not responding)";
++		break;
++	case -EOVERFLOW:
++		errmsg = "Babble (bad cable?)";
++		break;
++	case -EPROTO:
++		errmsg = "Bit-stuff error (bad cable?)";
++		break;
++	case -EILSEQ:
++		errmsg = "CRC/Timeout (could be anything)";
++		break;
++	case -ETIME:
++		errmsg = "Device does not respond";
++		break;
++	}
++	if (packet < 0) {
++		dprintk(1, "URB status %d [%s].\n", status, errmsg);
++	} else {
++		dprintk(1, "URB packet %d, status %d [%s].\n",
++			packet, status, errmsg);
++	}
++}
++
++static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
++{
++	int i;
++
++	if (!dev)
++		return 0;
++
++	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
++		return 0;
++
++	if (urb->status < 0) {
++		print_err_status(dev, -1, urb->status);
++		if (urb->status == -ENOENT)
++			return 0;
++	}
++
++	for (i = 0; i < urb->number_of_packets; i++) {
++		int status = urb->iso_frame_desc[i].status;
++
++		if (status < 0) {
++			print_err_status(dev, i, status);
++			if (urb->iso_frame_desc[i].status != -EPROTO)
++				continue;
++		}
++
++		dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
++				 urb->iso_frame_desc[i].offset,
++				 urb->iso_frame_desc[i].actual_length);
++	}
++
++	return 0;
++}
++
++static int start_streaming(struct em28xx_dvb *dvb)
++{
++	int rc;
++	struct em28xx *dev = dvb->adapter.priv;
++
++	usb_set_interface(dev->udev, 0, 1);
++	rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
++	if (rc < 0)
++		return rc;
++
++	return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
++				EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE,
++				dvb_isoc_copy);
++}
++
++static int stop_streaming(struct em28xx_dvb *dvb)
++{
++	struct em28xx *dev = dvb->adapter.priv;
++
++	em28xx_uninit_isoc(dev);
++
++	em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++
++	return 0;
++}
++
++static int start_feed(struct dvb_demux_feed *feed)
++{
++	struct dvb_demux *demux  = feed->demux;
++	struct em28xx_dvb *dvb = demux->priv;
++	int rc, ret;
++
++	if (!demux->dmx.frontend)
++		return -EINVAL;
++
++	mutex_lock(&dvb->lock);
++	dvb->nfeeds++;
++	rc = dvb->nfeeds;
++
++	if (dvb->nfeeds == 1) {
++		ret = start_streaming(dvb);
++		if (ret < 0)
++			rc = ret;
++	}
++
++	mutex_unlock(&dvb->lock);
++	return rc;
++}
++
++static int stop_feed(struct dvb_demux_feed *feed)
++{
++	struct dvb_demux *demux  = feed->demux;
++	struct em28xx_dvb *dvb = demux->priv;
++	int err = 0;
++
++	mutex_lock(&dvb->lock);
++	dvb->nfeeds--;
++
++	if (0 == dvb->nfeeds)
++		err = stop_streaming(dvb);
++
++	mutex_unlock(&dvb->lock);
++	return err;
++}
++
++
++
++/* ------------------------------------------------------------------ */
++static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
++{
++	struct em28xx *dev = fe->dvb->priv;
++
++	if (acquire)
++		return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
++	else
++		return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++}
++
++/* ------------------------------------------------------------------ */
++
++static struct lgdt330x_config em2880_lgdt3303_dev = {
++	.demod_address = 0x0e,
++	.demod_chip = LGDT3303,
++};
++
++static struct zl10353_config em28xx_zl10353_with_xc3028 = {
++	.demod_address = (0x1e >> 1),
++	.no_tuner = 1,
++	.parallel_ts = 1,
++	.if2 = 45600,
++};
++
++/* ------------------------------------------------------------------ */
++
++static int attach_xc3028(u8 addr, struct em28xx *dev)
++{
++	struct dvb_frontend *fe;
++	struct xc2028_config cfg;
++
++	memset(&cfg, 0, sizeof(cfg));
++	cfg.i2c_adap  = &dev->i2c_adap;
++	cfg.i2c_addr  = addr;
++	cfg.callback  = em28xx_tuner_callback;
++
++	if (!dev->dvb->frontend) {
++		printk(KERN_ERR "%s/2: dvb frontend not attached. "
++				"Can't attach xc3028\n",
++		       dev->name);
++		return -EINVAL;
++	}
++
++	fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg);
++	if (!fe) {
++		printk(KERN_ERR "%s/2: xc3028 attach failed\n",
++		       dev->name);
++		dvb_frontend_detach(dev->dvb->frontend);
++		dvb_unregister_frontend(dev->dvb->frontend);
++		dev->dvb->frontend = NULL;
++		return -EINVAL;
++	}
++
++	printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name);
++
++	return 0;
++}
++
++/* ------------------------------------------------------------------ */
++
++int register_dvb(struct em28xx_dvb *dvb,
++		 struct module *module,
++		 struct em28xx *dev,
++		 struct device *device)
++{
++	int result;
++
++	mutex_init(&dvb->lock);
++
++	/* register adapter */
++	result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
++				      adapter_nr);
++	if (result < 0) {
++		printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
++		       dev->name, result);
++		goto fail_adapter;
++	}
++
++	/* Ensure all frontends negotiate bus access */
++	dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
++
++	dvb->adapter.priv = dev;
++
++	/* register frontend */
++	result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
++	if (result < 0) {
++		printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
++		       dev->name, result);
++		goto fail_frontend;
++	}
++
++	/* register demux stuff */
++	dvb->demux.dmx.capabilities =
++		DMX_TS_FILTERING | DMX_SECTION_FILTERING |
++		DMX_MEMORY_BASED_FILTERING;
++	dvb->demux.priv       = dvb;
++	dvb->demux.filternum  = 256;
++	dvb->demux.feednum    = 256;
++	dvb->demux.start_feed = start_feed;
++	dvb->demux.stop_feed  = stop_feed;
++
++	result = dvb_dmx_init(&dvb->demux);
++	if (result < 0) {
++		printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
++		       dev->name, result);
++		goto fail_dmx;
++	}
++
++	dvb->dmxdev.filternum    = 256;
++	dvb->dmxdev.demux        = &dvb->demux.dmx;
++	dvb->dmxdev.capabilities = 0;
++	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
++	if (result < 0) {
++		printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
++		       dev->name, result);
++		goto fail_dmxdev;
++	}
++
++	dvb->fe_hw.source = DMX_FRONTEND_0;
++	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++	if (result < 0) {
++		printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
++		       dev->name, result);
++		goto fail_fe_hw;
++	}
++
++	dvb->fe_mem.source = DMX_MEMORY_FE;
++	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++	if (result < 0) {
++		printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
++		       dev->name, result);
++		goto fail_fe_mem;
++	}
++
++	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++	if (result < 0) {
++		printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
++		       dev->name, result);
++		goto fail_fe_conn;
++	}
++
++	/* register network adapter */
++	dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
++	return 0;
++
++fail_fe_conn:
++	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++fail_fe_mem:
++	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++fail_fe_hw:
++	dvb_dmxdev_release(&dvb->dmxdev);
++fail_dmxdev:
++	dvb_dmx_release(&dvb->demux);
++fail_dmx:
++	dvb_unregister_frontend(dvb->frontend);
++fail_frontend:
++	dvb_frontend_detach(dvb->frontend);
++	dvb_unregister_adapter(&dvb->adapter);
++fail_adapter:
++	return result;
++}
++
++static void unregister_dvb(struct em28xx_dvb *dvb)
++{
++	dvb_net_release(&dvb->net);
++	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++	dvb_dmxdev_release(&dvb->dmxdev);
++	dvb_dmx_release(&dvb->demux);
++	dvb_unregister_frontend(dvb->frontend);
++	dvb_frontend_detach(dvb->frontend);
++	dvb_unregister_adapter(&dvb->adapter);
++}
++
++
++static int dvb_init(struct em28xx *dev)
++{
++	int result = 0;
++	struct em28xx_dvb *dvb;
++
++	dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
++
++	if (dvb == NULL) {
++		printk(KERN_INFO "em28xx_dvb: memory allocation failed\n");
++		return -ENOMEM;
++	}
++	dev->dvb = dvb;
++
++	em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
++	/* init frontend */
++	switch (dev->model) {
++	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
++		dvb->frontend = dvb_attach(lgdt330x_attach,
++					   &em2880_lgdt3303_dev,
++					   &dev->i2c_adap);
++		if (attach_xc3028(0x61, dev) < 0) {
++			result = -EINVAL;
++			goto out_free;
++		}
++		break;
++	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
++		dvb->frontend = dvb_attach(zl10353_attach,
++					   &em28xx_zl10353_with_xc3028,
++					   &dev->i2c_adap);
++		if (attach_xc3028(0x61, dev) < 0) {
++			result = -EINVAL;
++			goto out_free;
++		}
++		break;
++	default:
++		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
++				" isn't supported yet\n",
++		       dev->name);
++		break;
++	}
++	if (NULL == dvb->frontend) {
++		printk(KERN_ERR
++		       "%s/2: frontend initialization failed\n",
++		       dev->name);
++		result = -EINVAL;
++		goto out_free;
++	}
++
++	/* register everything */
++	result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
++
++	if (result < 0)
++		goto out_free;
++
++	em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++	printk(KERN_INFO "Successfully loaded em28xx-dvb\n");
++	return 0;
++
++out_free:
++	em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++	kfree(dvb);
++	dev->dvb = NULL;
++	return result;
++}
++
++static int dvb_fini(struct em28xx *dev)
++{
++	if (dev->dvb) {
++		unregister_dvb(dev->dvb);
++		dev->dvb = NULL;
++	}
++
++	return 0;
++}
++
++static struct em28xx_ops dvb_ops = {
++	.id   = EM28XX_DVB,
++	.name = "Em28xx dvb Extension",
++	.init = dvb_init,
++	.fini = dvb_fini,
++};
++
++static int __init em28xx_dvb_register(void)
++{
++	return em28xx_register_extension(&dvb_ops);
++}
++
++static void __exit em28xx_dvb_unregister(void)
++{
++	em28xx_unregister_extension(&dvb_ops);
++}
++
++module_init(em28xx_dvb_register);
++module_exit(em28xx_dvb_unregister);
+diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
+index cacd04d..6a78fd2 100644
+--- a/drivers/media/video/em28xx/em28xx-i2c.c
++++ b/drivers/media/video/em28xx/em28xx-i2c.c
+@@ -33,19 +33,29 @@
+ 
+ /* ----------------------------------------------------------- */
+ 
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, 0444);
+ MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+ 
+-static unsigned int i2c_debug = 0;
++static unsigned int i2c_debug;
+ module_param(i2c_debug, int, 0644);
+ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+ 
+-#define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\
+-			printk(fmt, ##args); } while (0)
+-#define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \
+-			printk(KERN_DEBUG "%s at %s: " fmt, \
+-			dev->name, __FUNCTION__ , ##args); } while (0)
++
++#define dprintk1(lvl, fmt, args...)			\
++do {							\
++	if (i2c_debug >= lvl) {				\
++	printk(fmt, ##args);				\
++      }							\
++} while (0)
++
++#define dprintk2(lvl, fmt, args...)			\
++do {							\
++	if (i2c_debug >= lvl) {				\
++		printk(KERN_DEBUG "%s at %s: " fmt,	\
++		       dev->name, __func__ , ##args);	\
++      } 						\
++} while (0)
+ 
+ /*
+  * em2800_i2c_send_max4()
+@@ -235,16 +245,16 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
+ 		return 0;
+ 	for (i = 0; i < num; i++) {
+ 		addr = msgs[i].addr << 1;
+-		dprintk2(2,"%s %s addr=%x len=%d:",
++		dprintk2(2, "%s %s addr=%x len=%d:",
+ 			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+ 			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+-		if (!msgs[i].len) {	/* no len: check only for device presence */
++		if (!msgs[i].len) { /* no len: check only for device presence */
+ 			if (dev->is_em2800)
+ 				rc = em2800_i2c_check_for_device(dev, addr);
+ 			else
+ 				rc = em28xx_i2c_check_for_device(dev, addr);
+ 			if (rc < 0) {
+-				dprintk2(2," no device\n");
++				dprintk2(2, " no device\n");
+ 				return rc;
+ 			}
+ 
+@@ -258,14 +268,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
+ 				rc = em28xx_i2c_recv_bytes(dev, addr,
+ 							   msgs[i].buf,
+ 							   msgs[i].len);
+-			if (i2c_debug>=2) {
+-				for (byte = 0; byte < msgs[i].len; byte++) {
++			if (i2c_debug >= 2) {
++				for (byte = 0; byte < msgs[i].len; byte++)
+ 					printk(" %02x", msgs[i].buf[byte]);
+-				}
+ 			}
+ 		} else {
+ 			/* write bytes */
+-			if (i2c_debug>=2) {
++			if (i2c_debug >= 2) {
+ 				for (byte = 0; byte < msgs[i].len; byte++)
+ 					printk(" %02x", msgs[i].buf[byte]);
+ 			}
+@@ -281,13 +290,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
+ 		}
+ 		if (rc < 0)
+ 			goto err;
+-		if (i2c_debug>=2)
++		if (i2c_debug >= 2)
+ 			printk("\n");
+ 	}
+ 
+ 	return num;
+-      err:
+-	dprintk2(2," ERROR: %i\n", rc);
++err:
++	dprintk2(2, " ERROR: %i\n", rc);
+ 	return rc;
+ }
+ 
+@@ -330,7 +339,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
+ 		return -1;
+ 
+ 	buf = 0;
+-	if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) {
++
++	err = i2c_master_send(&dev->i2c_client, &buf, 1);
++	if (err != 1) {
+ 		printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
+ 		       dev->name, err);
+ 		return -1;
+@@ -403,8 +414,10 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
+ 		break;
+ 	}
+ 	printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
+-				em_eeprom->string_idx_table,em_eeprom->string1,
+-				em_eeprom->string2,em_eeprom->string3);
++				em_eeprom->string_idx_table,
++				em_eeprom->string1,
++				em_eeprom->string2,
++				em_eeprom->string3);
+ 
+ 	return 0;
+ }
+@@ -430,58 +443,61 @@ static int attach_inform(struct i2c_client *client)
+ 	struct em28xx *dev = client->adapter->algo_data;
+ 
+ 	switch (client->addr << 1) {
+-		case 0x86:
+-		case 0x84:
+-		case 0x96:
+-		case 0x94:
+-		{
+-			struct v4l2_priv_tun_config tda9887_cfg;
+-
+-			struct tuner_setup tun_setup;
+-
+-			tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+-			tun_setup.type = TUNER_TDA9887;
+-			tun_setup.addr = client->addr;
+-
+-			em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+-
+-			tda9887_cfg.tuner = TUNER_TDA9887;
+-			tda9887_cfg.priv = &dev->tda9887_conf;
+-			em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
+-						&tda9887_cfg);
+-			break;
+-		}
+-		case 0x42:
+-			dprintk1(1,"attach_inform: saa7114 detected.\n");
+-			break;
+-		case 0x4a:
+-			dprintk1(1,"attach_inform: saa7113 detected.\n");
+-			break;
+-		case 0xa0:
+-			dprintk1(1,"attach_inform: eeprom detected.\n");
+-			break;
+-		case 0x60:
+-		case 0x8e:
+-		{
+-			struct IR_i2c *ir = i2c_get_clientdata(client);
+-			dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys);
+-			em28xx_set_ir(dev,ir);
+-			break;
+-		}
+-		case 0x80:
+-		case 0x88:
+-			dprintk1(1,"attach_inform: msp34xx detected.\n");
+-			break;
+-		case 0xb8:
+-		case 0xba:
+-			dprintk1(1,"attach_inform: tvp5150 detected.\n");
+-			break;
+-
+-		default:
+-			if (!dev->tuner_addr)
+-				dev->tuner_addr = client->addr;
+-
+-			dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1);
++	case 0x86:
++	case 0x84:
++	case 0x96:
++	case 0x94:
++	{
++		struct v4l2_priv_tun_config tda9887_cfg;
++
++		struct tuner_setup tun_setup;
++
++		tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
++		tun_setup.type = TUNER_TDA9887;
++		tun_setup.addr = client->addr;
++
++		em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR,
++			&tun_setup);
++
++		tda9887_cfg.tuner = TUNER_TDA9887;
++		tda9887_cfg.priv = &dev->tda9887_conf;
++		em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
++					&tda9887_cfg);
++		break;
++	}
++	case 0x42:
++		dprintk1(1, "attach_inform: saa7114 detected.\n");
++		break;
++	case 0x4a:
++		dprintk1(1, "attach_inform: saa7113 detected.\n");
++		break;
++	case 0xa0:
++		dprintk1(1, "attach_inform: eeprom detected.\n");
++		break;
++	case 0x60:
++	case 0x8e:
++	{
++		struct IR_i2c *ir = i2c_get_clientdata(client);
++		dprintk1(1, "attach_inform: IR detected (%s).\n",
++			ir->phys);
++		em28xx_set_ir(dev, ir);
++		break;
++	}
++	case 0x80:
++	case 0x88:
++		dprintk1(1, "attach_inform: msp34xx detected.\n");
++		break;
++	case 0xb8:
++	case 0xba:
++		dprintk1(1, "attach_inform: tvp5150 detected.\n");
++		break;
++
++	default:
++		if (!dev->tuner_addr)
++			dev->tuner_addr = client->addr;
++
++		dprintk1(1, "attach inform: detected I2C address %x\n",
++				client->addr << 1);
+ 
+ 	}
+ 
+diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
+index 10da2fd..bb58071 100644
+--- a/drivers/media/video/em28xx/em28xx-input.c
++++ b/drivers/media/video/em28xx/em28xx-input.c
+@@ -32,10 +32,12 @@
+ 
+ static unsigned int ir_debug;
+ module_param(ir_debug, int, 0644);
+-MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
++MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+ 
+-#define dprintk(fmt, arg...)	if (ir_debug) \
+-	printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
++#define dprintk(fmt, arg...) \
++	if (ir_debug) { \
++		printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
++	}
+ 
+ /* ----------------------------------------------------------------------- */
+ 
+@@ -44,7 +46,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+ 	unsigned char b;
+ 
+ 	/* poll IR chip */
+-	if (1 != i2c_master_recv(&ir->c,&b,1)) {
++	if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+ 		dprintk("read error\n");
+ 		return -EIO;
+ 	}
+@@ -74,24 +76,25 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+ 	unsigned char code;
+ 
+ 	/* poll IR chip */
+-	if (2 != i2c_master_recv(&ir->c,buf,2))
++	if (2 != i2c_master_recv(&ir->c, buf, 2))
+ 		return -EIO;
+ 
+ 	/* Does eliminate repeated parity code */
+-	if (buf[1]==0xff)
++	if (buf[1] == 0xff)
+ 		return 0;
+ 
+-	ir->old=buf[1];
++	ir->old = buf[1];
+ 
+ 	/* Rearranges bits to the right order */
+-	code=    ((buf[0]&0x01)<<5) | /* 0010 0000 */
++	code =   ((buf[0]&0x01)<<5) | /* 0010 0000 */
+ 		 ((buf[0]&0x02)<<3) | /* 0001 0000 */
+ 		 ((buf[0]&0x04)<<1) | /* 0000 1000 */
+ 		 ((buf[0]&0x08)>>1) | /* 0000 0100 */
+ 		 ((buf[0]&0x10)>>3) | /* 0000 0010 */
+ 		 ((buf[0]&0x20)>>5);  /* 0000 0001 */
+ 
+-	dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",code,buf[0]);
++	dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",
++			code, buf[0]);
+ 
+ 	/* return key */
+ 	*ir_key = code;
+@@ -106,15 +109,14 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
+ 
+ 	/* poll IR chip */
+ 
+-	if (3 != i2c_master_recv(&ir->c,buf,3)) {
++	if (3 != i2c_master_recv(&ir->c, buf, 3)) {
+ 		dprintk("read error\n");
+ 		return -EIO;
+ 	}
+ 
+ 	dprintk("key %02x\n", buf[2]&0x3f);
+-	if (buf[0]!=0x00){
++	if (buf[0] != 0x00)
+ 		return 0;
+-	}
+ 
+ 	*ir_key = buf[2]&0x3f;
+ 	*ir_raw = buf[2]&0x3f;
+diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
+new file mode 100644
+index 0000000..9058bed
+--- /dev/null
++++ b/drivers/media/video/em28xx/em28xx-reg.h
+@@ -0,0 +1,88 @@
++#define EM_GPIO_0  (1 << 0)
++#define EM_GPIO_1  (1 << 1)
++#define EM_GPIO_2  (1 << 2)
++#define EM_GPIO_3  (1 << 3)
++#define EM_GPIO_4  (1 << 4)
++#define EM_GPIO_5  (1 << 5)
++#define EM_GPIO_6  (1 << 6)
++#define EM_GPIO_7  (1 << 7)
++
++#define EM_GPO_0   (1 << 0)
++#define EM_GPO_1   (1 << 1)
++#define EM_GPO_2   (1 << 2)
++#define EM_GPO_3   (1 << 3)
++
++/* em2800 registers */
++#define EM2800_R08_AUDIOSRC 0x08
++
++/* em28xx registers */
++
++	/* GPIO/GPO registers */
++#define EM2880_R04_GPO	0x04    /* em2880-em2883 only */
++#define EM28XX_R08_GPIO	0x08	/* em2820 or upper */
++
++#define EM28XX_R06_I2C_CLK	0x06
++#define EM28XX_R0A_CHIPID	0x0a
++#define EM28XX_R0C_USBSUSP	0x0c	/* */
++
++#define EM28XX_R0E_AUDIOSRC	0x0e
++#define EM28XX_R0F_XCLK	0x0f
++
++#define EM28XX_R10_VINMODE	0x10
++#define EM28XX_R11_VINCTRL	0x11
++#define EM28XX_R12_VINENABLE	0x12	/* */
++
++#define EM28XX_R14_GAMMA	0x14
++#define EM28XX_R15_RGAIN	0x15
++#define EM28XX_R16_GGAIN	0x16
++#define EM28XX_R17_BGAIN	0x17
++#define EM28XX_R18_ROFFSET	0x18
++#define EM28XX_R19_GOFFSET	0x19
++#define EM28XX_R1A_BOFFSET	0x1a
++
++#define EM28XX_R1B_OFLOW	0x1b
++#define EM28XX_R1C_HSTART	0x1c
++#define EM28XX_R1D_VSTART	0x1d
++#define EM28XX_R1E_CWIDTH	0x1e
++#define EM28XX_R1F_CHEIGHT	0x1f
++
++#define EM28XX_R20_YGAIN	0x20
++#define EM28XX_R21_YOFFSET	0x21
++#define EM28XX_R22_UVGAIN	0x22
++#define EM28XX_R23_UOFFSET	0x23
++#define EM28XX_R24_VOFFSET	0x24
++#define EM28XX_R25_SHARPNESS	0x25
++
++#define EM28XX_R26_COMPR	0x26
++#define EM28XX_R27_OUTFMT	0x27
++
++#define EM28XX_R28_XMIN	0x28
++#define EM28XX_R29_XMAX	0x29
++#define EM28XX_R2A_YMIN	0x2a
++#define EM28XX_R2B_YMAX	0x2b
++
++#define EM28XX_R30_HSCALELOW	0x30
++#define EM28XX_R31_HSCALEHIGH	0x31
++#define EM28XX_R32_VSCALELOW	0x32
++#define EM28XX_R33_VSCALEHIGH	0x33
++
++#define EM28XX_R40_AC97LSB	0x40
++#define EM28XX_R41_AC97MSB	0x41
++#define EM28XX_R42_AC97ADDR	0x42
++#define EM28XX_R43_AC97BUSY	0x43
++
++/* em202 registers */
++#define EM28XX_R02_MASTER_AC97	0x02
++#define EM28XX_R10_LINE_IN_AC97    0x10
++#define EM28XX_R14_VIDEO_AC97	0x14
++
++/* register settings */
++#define EM2800_AUDIO_SRC_TUNER  0x0d
++#define EM2800_AUDIO_SRC_LINE   0x0c
++#define EM28XX_AUDIO_SRC_TUNER	0xc0
++#define EM28XX_AUDIO_SRC_LINE	0x80
++
++/* FIXME: Need to be populated with the other chip ID's */
++enum em28xx_chip_id {
++	CHIP_ID_EM2883 = 36,
++};
+diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
+index 4abe670..8996175 100644
+--- a/drivers/media/video/em28xx/em28xx-video.c
++++ b/drivers/media/video/em28xx/em28xx-video.c
+@@ -1,5 +1,6 @@
+ /*
+-   em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
++   em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
++		    video capture devices
+ 
+    Copyright (C) 2005 Ludovico Cavedon <cavedon at sssup.it>
+ 		      Markus Rechberger <mrechberger at gmail.com>
+@@ -52,7 +53,19 @@
+ #define em28xx_videodbg(fmt, arg...) do {\
+ 	if (video_debug) \
+ 		printk(KERN_INFO "%s %s :"fmt, \
+-			 dev->name, __FUNCTION__ , ##arg); } while (0)
++			 dev->name, __func__ , ##arg); } while (0)
++
++static unsigned int isoc_debug;
++module_param(isoc_debug, int, 0644);
++MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
++
++#define em28xx_isocdbg(fmt, arg...) \
++do {\
++	if (isoc_debug) { \
++		printk(KERN_INFO "%s %s :"fmt, \
++			 dev->name, __func__ , ##arg); \
++	} \
++  } while (0)
+ 
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(DRIVER_DESC);
+@@ -74,9 +87,9 @@ MODULE_PARM_DESC(video_nr, "video device numbers");
+ MODULE_PARM_DESC(vbi_nr,   "vbi device numbers");
+ MODULE_PARM_DESC(radio_nr, "radio device numbers");
+ 
+-static unsigned int video_debug = 0;
+-module_param(video_debug,int,0644);
+-MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
++static unsigned int video_debug;
++module_param(video_debug, int, 0644);
++MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+ 
+ /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
+ static unsigned long em28xx_devused;
+@@ -93,7 +106,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
+ 		.step = 0x1,
+ 		.default_value = 0x1f,
+ 		.flags = 0,
+-	},{
++	}, {
+ 		.id = V4L2_CID_AUDIO_MUTE,
+ 		.type = V4L2_CTRL_TYPE_BOOLEAN,
+ 		.name = "Mute",
+@@ -107,8 +120,391 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
+ 
+ static struct usb_driver em28xx_usb_driver;
+ 
++/* ------------------------------------------------------------------
++	DMA and thread functions
++   ------------------------------------------------------------------*/
++
++/*
++ * Announces that a buffer were filled and request the next
++ */
++static inline void buffer_filled(struct em28xx *dev,
++				  struct em28xx_dmaqueue *dma_q,
++				  struct em28xx_buffer *buf)
++{
++	/* Advice that buffer was filled */
++	em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
++	buf->vb.state = VIDEOBUF_DONE;
++	buf->vb.field_count++;
++	do_gettimeofday(&buf->vb.ts);
+ 
+-/*********************  v4l2 interface  ******************************************/
++	dev->isoc_ctl.buf = NULL;
++
++	list_del(&buf->vb.queue);
++	wake_up(&buf->vb.done);
++}
++
++/*
++ * Identify the buffer header type and properly handles
++ */
++static void em28xx_copy_video(struct em28xx *dev,
++			      struct em28xx_dmaqueue  *dma_q,
++			      struct em28xx_buffer *buf,
++			      unsigned char *p,
++			      unsigned char *outp, unsigned long len)
++{
++	void *fieldstart, *startwrite, *startread;
++	int  linesdone, currlinedone, offset, lencopy, remain;
++	int bytesperline = dev->width << 1;
++
++	if (dma_q->pos + len > buf->vb.size)
++		len = buf->vb.size - dma_q->pos;
++
++	if (p[0] != 0x88 && p[0] != 0x22) {
++		em28xx_isocdbg("frame is not complete\n");
++		len += 4;
++	} else
++		p += 4;
++
++	startread = p;
++	remain = len;
++
++	/* Interlaces frame */
++	if (buf->top_field)
++		fieldstart = outp;
++	else
++		fieldstart = outp + bytesperline;
++
++	linesdone = dma_q->pos / bytesperline;
++	currlinedone = dma_q->pos % bytesperline;
++	offset = linesdone * bytesperline * 2 + currlinedone;
++	startwrite = fieldstart + offset;
++	lencopy = bytesperline - currlinedone;
++	lencopy = lencopy > remain ? remain : lencopy;
++
++	if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
++		em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
++			       ((char *)startwrite + lencopy) -
++			       ((char *)outp + buf->vb.size));
++		lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite;
++	}
++	if (lencopy <= 0)
++		return;
++	memcpy(startwrite, startread, lencopy);
++
++	remain -= lencopy;
++
++	while (remain > 0) {
++		startwrite += lencopy + bytesperline;
++		startread += lencopy;
++		if (bytesperline > remain)
++			lencopy = remain;
++		else
++			lencopy = bytesperline;
++
++		if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
++			em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n",
++				       ((char *)startwrite + lencopy) -
++				       ((char *)outp + buf->vb.size));
++			lencopy = remain = (char *)outp + buf->vb.size -
++					   (char *)startwrite;
++		}
++		if (lencopy <= 0)
++			break;
++
++		memcpy(startwrite, startread, lencopy);
++
++		remain -= lencopy;
++	}
++
++	dma_q->pos += len;
++}
++
++static inline void print_err_status(struct em28xx *dev,
++				     int packet, int status)
++{
++	char *errmsg = "Unknown";
++
++	switch (status) {
++	case -ENOENT:
++		errmsg = "unlinked synchronuously";
++		break;
++	case -ECONNRESET:
++		errmsg = "unlinked asynchronuously";
++		break;
++	case -ENOSR:
++		errmsg = "Buffer error (overrun)";
++		break;
++	case -EPIPE:
++		errmsg = "Stalled (device not responding)";
++		break;
++	case -EOVERFLOW:
++		errmsg = "Babble (bad cable?)";
++		break;
++	case -EPROTO:
++		errmsg = "Bit-stuff error (bad cable?)";
++		break;
++	case -EILSEQ:
++		errmsg = "CRC/Timeout (could be anything)";
++		break;
++	case -ETIME:
++		errmsg = "Device does not respond";
++		break;
++	}
++	if (packet < 0) {
++		em28xx_isocdbg("URB status %d [%s].\n",	status, errmsg);
++	} else {
++		em28xx_isocdbg("URB packet %d, status %d [%s].\n",
++			       packet, status, errmsg);
++	}
++}
++
++/*
++ * video-buf generic routine to get the next available buffer
++ */
++static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
++					  struct em28xx_buffer **buf)
++{
++	struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
++	char *outp;
++
++	if (list_empty(&dma_q->active)) {
++		em28xx_isocdbg("No active queue to serve\n");
++		dev->isoc_ctl.buf = NULL;
++		*buf = NULL;
++		return;
++	}
++
++	/* Get the next buffer */
++	*buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
++
++	/* Cleans up buffer - Usefull for testing for frame/URB loss */
++	outp = videobuf_to_vmalloc(&(*buf)->vb);
++	memset(outp, 0, (*buf)->vb.size);
++
++	dev->isoc_ctl.buf = *buf;
++
++	return;
++}
++
++/*
++ * Controls the isoc copy of each urb packet
++ */
++static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
++{
++	struct em28xx_buffer    *buf;
++	struct em28xx_dmaqueue  *dma_q = urb->context;
++	unsigned char *outp = NULL;
++	int i, len = 0, rc = 1;
++	unsigned char *p;
++
++	if (!dev)
++		return 0;
++
++	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
++		return 0;
++
++	if (urb->status < 0) {
++		print_err_status(dev, -1, urb->status);
++		if (urb->status == -ENOENT)
++			return 0;
++	}
++
++	buf = dev->isoc_ctl.buf;
++	if (buf != NULL)
++		outp = videobuf_to_vmalloc(&buf->vb);
++
++	for (i = 0; i < urb->number_of_packets; i++) {
++		int status = urb->iso_frame_desc[i].status;
++
++		if (status < 0) {
++			print_err_status(dev, i, status);
++			if (urb->iso_frame_desc[i].status != -EPROTO)
++				continue;
++		}
++
++		len = urb->iso_frame_desc[i].actual_length - 4;
++
++		if (urb->iso_frame_desc[i].actual_length <= 0) {
++			/* em28xx_isocdbg("packet %d is empty",i); - spammy */
++			continue;
++		}
++		if (urb->iso_frame_desc[i].actual_length >
++						dev->max_pkt_size) {
++			em28xx_isocdbg("packet bigger than packet size");
++			continue;
++		}
++
++		p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
++
++		/* FIXME: incomplete buffer checks where removed to make
++		   logic simpler. Impacts of those changes should be evaluated
++		 */
++		if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) {
++			em28xx_isocdbg("VBI HEADER!!!\n");
++			/* FIXME: Should add vbi copy */
++			continue;
++		}
++		if (p[0] == 0x22 && p[1] == 0x5a) {
++			em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
++				       len, (p[2] & 1)? "odd" : "even");
++
++			if (!(p[2] & 1)) {
++				if (buf != NULL)
++					buffer_filled(dev, dma_q, buf);
++				get_next_buf(dma_q, &buf);
++				if (buf == NULL)
++					outp = NULL;
++				else
++					outp = videobuf_to_vmalloc(&buf->vb);
++			}
++
++			if (buf != NULL) {
++				if (p[2] & 1)
++					buf->top_field = 0;
++				else
++					buf->top_field = 1;
++			}
++
++			dma_q->pos = 0;
++		}
++		if (buf != NULL)
++			em28xx_copy_video(dev, dma_q, buf, p, outp, len);
++	}
++	return rc;
++}
++
++/* ------------------------------------------------------------------
++	Videobuf operations
++   ------------------------------------------------------------------*/
++
++static int
++buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
++{
++	struct em28xx_fh *fh = vq->priv_data;
++	struct em28xx        *dev = fh->dev;
++	struct v4l2_frequency f;
++
++	*size = 16 * fh->dev->width * fh->dev->height >> 3;
++	if (0 == *count)
++		*count = EM28XX_DEF_BUF;
++
++	if (*count < EM28XX_MIN_BUF)
++		*count = EM28XX_MIN_BUF;
++
++	/* Ask tuner to go to analog mode */
++	memset(&f, 0, sizeof(f));
++	f.frequency = dev->ctl_freq;
++
++	em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
++
++	return 0;
++}
++
++/* This is called *without* dev->slock held; please keep it that way */
++static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
++{
++	struct em28xx_fh     *fh  = vq->priv_data;
++	struct em28xx        *dev = fh->dev;
++	unsigned long flags = 0;
++	if (in_interrupt())
++		BUG();
++
++	/* We used to wait for the buffer to finish here, but this didn't work
++	   because, as we were keeping the state as VIDEOBUF_QUEUED,
++	   videobuf_queue_cancel marked it as finished for us.
++	   (Also, it could wedge forever if the hardware was misconfigured.)
++
++	   This should be safe; by the time we get here, the buffer isn't
++	   queued anymore. If we ever start marking the buffers as
++	   VIDEOBUF_ACTIVE, it won't be, though.
++	*/
++	spin_lock_irqsave(&dev->slock, flags);
++	if (dev->isoc_ctl.buf == buf)
++		dev->isoc_ctl.buf = NULL;
++	spin_unlock_irqrestore(&dev->slock, flags);
++
++	videobuf_vmalloc_free(&buf->vb);
++	buf->vb.state = VIDEOBUF_NEEDS_INIT;
++}
++
++static int
++buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
++						enum v4l2_field field)
++{
++	struct em28xx_fh     *fh  = vq->priv_data;
++	struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
++	struct em28xx        *dev = fh->dev;
++	int                  rc = 0, urb_init = 0;
++
++	/* FIXME: It assumes depth = 16 */
++	/* The only currently supported format is 16 bits/pixel */
++	buf->vb.size = 16 * dev->width * dev->height >> 3;
++
++	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
++		return -EINVAL;
++
++	buf->vb.width  = dev->width;
++	buf->vb.height = dev->height;
++	buf->vb.field  = field;
++
++	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
++		rc = videobuf_iolock(vq, &buf->vb, NULL);
++		if (rc < 0)
++			goto fail;
++	}
++
++	if (!dev->isoc_ctl.num_bufs)
++		urb_init = 1;
++
++	if (urb_init) {
++		rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
++				      EM28XX_NUM_BUFS, dev->max_pkt_size,
++				      em28xx_isoc_copy);
++		if (rc < 0)
++			goto fail;
++	}
++
++	buf->vb.state = VIDEOBUF_PREPARED;
++	return 0;
++
++fail:
++	free_buffer(vq, buf);
++	return rc;
++}
++
++static void
++buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
++{
++	struct em28xx_buffer    *buf     = container_of(vb, struct em28xx_buffer, vb);
++	struct em28xx_fh        *fh      = vq->priv_data;
++	struct em28xx           *dev     = fh->dev;
++	struct em28xx_dmaqueue  *vidq    = &dev->vidq;
++
++	buf->vb.state = VIDEOBUF_QUEUED;
++	list_add_tail(&buf->vb.queue, &vidq->active);
++
++}
++
++static void buffer_release(struct videobuf_queue *vq,
++				struct videobuf_buffer *vb)
++{
++	struct em28xx_buffer   *buf  = container_of(vb, struct em28xx_buffer, vb);
++	struct em28xx_fh       *fh   = vq->priv_data;
++	struct em28xx          *dev  = (struct em28xx *)fh->dev;
++
++	em28xx_isocdbg("em28xx: called buffer_release\n");
++
++	free_buffer(vq, buf);
++}
++
++static struct videobuf_queue_ops em28xx_video_qops = {
++	.buf_setup      = buffer_setup,
++	.buf_prepare    = buffer_prepare,
++	.buf_queue      = buffer_queue,
++	.buf_release    = buffer_release,
++};
++
++/*********************  v4l2 interface  **************************************/
+ 
+ /*
+  * em28xx_config()
+@@ -123,9 +519,9 @@ static int em28xx_config(struct em28xx *dev)
+ 
+ 	/* enable vbi capturing */
+ 
+-/*	em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); audio register */
+-/*	em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
+-	em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
++/*	em28xx_write_regs_req(dev, 0x00, 0x0e, "\xC0", 1); audio register */
++/*	em28xx_write_regs_req(dev, 0x00, 0x0f, "\x80", 1); clk register */
++	em28xx_write_regs_req(dev, 0x00, 0x11, "\x51", 1);
+ 
+ 	dev->mute = 1;		/* maybe not the right place... */
+ 	dev->volume = 0x1f;
+@@ -152,23 +548,6 @@ static void em28xx_config_i2c(struct em28xx *dev)
+ 	em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
+ }
+ 
+-/*
+- * em28xx_empty_framequeues()
+- * prepare queues for incoming and outgoing frames
+- */
+-static void em28xx_empty_framequeues(struct em28xx *dev)
+-{
+-	u32 i;
+-
+-	INIT_LIST_HEAD(&dev->inqueue);
+-	INIT_LIST_HEAD(&dev->outqueue);
+-
+-	for (i = 0; i < EM28XX_NUM_FRAMES; i++) {
+-		dev->frame[i].state = F_UNUSED;
+-		dev->frame[i].buf.bytesused = 0;
+-	}
+-}
+-
+ static void video_mux(struct em28xx *dev, int index)
+ {
+ 	struct v4l2_routing route;
+@@ -181,12 +560,15 @@ static void video_mux(struct em28xx *dev, int index)
+ 	em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
+ 
+ 	if (dev->has_msp34xx) {
+-		if (dev->i2s_speed)
+-			em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
++		if (dev->i2s_speed) {
++			em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ,
++				&dev->i2s_speed);
++		}
+ 		route.input = dev->ctl_ainput;
+ 		route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
+ 		/* Note: this is msp3400 specific */
+-		em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
++		em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
++			&route);
+ 	}
+ 
+ 	em28xx_audio_analog_set(dev);
+@@ -202,15 +584,12 @@ static int res_get(struct em28xx_fh *fh)
+ 	if (fh->stream_on)
+ 		return rc;
+ 
+-	mutex_lock(&dev->lock);
+-
+ 	if (dev->stream_on)
+-		rc = -EINVAL;
+-	else {
+-		dev->stream_on = 1;
+-		fh->stream_on  = 1;
+-	}
++		return -EINVAL;
+ 
++	mutex_lock(&dev->lock);
++	dev->stream_on = 1;
++	fh->stream_on  = 1;
+ 	mutex_unlock(&dev->lock);
+ 	return rc;
+ }
+@@ -231,33 +610,6 @@ static void res_free(struct em28xx_fh *fh)
+ }
+ 
+ /*
+- * em28xx_vm_open()
+- */
+-static void em28xx_vm_open(struct vm_area_struct *vma)
+-{
+-	struct em28xx_frame_t *f = vma->vm_private_data;
+-	f->vma_use_count++;
+-}
+-
+-/*
+- * em28xx_vm_close()
+- */
+-static void em28xx_vm_close(struct vm_area_struct *vma)
+-{
+-	/* NOTE: buffers are not freed here */
+-	struct em28xx_frame_t *f = vma->vm_private_data;
+-
+-	if (f->vma_use_count)
+-		f->vma_use_count--;
+-}
+-
+-static struct vm_operations_struct em28xx_vm_ops = {
+-	.open = em28xx_vm_open,
+-	.close = em28xx_vm_close,
+-};
+-
+-
+-/*
+  * em28xx_get_ctrl()
+  * return the current saturation, brightness or contrast, mute state
+  */
+@@ -296,34 +648,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
+ 	}
+ }
+ 
+-/*
+- * em28xx_stream_interrupt()
+- * stops streaming
+- */
+-static int em28xx_stream_interrupt(struct em28xx *dev)
+-{
+-	int rc = 0;
+-
+-	/* stop reading from the device */
+-
+-	dev->stream = STREAM_INTERRUPT;
+-	rc = wait_event_timeout(dev->wait_stream,
+-				(dev->stream == STREAM_OFF) ||
+-				(dev->state & DEV_DISCONNECTED),
+-				EM28XX_URB_TIMEOUT);
+-
+-	if (rc) {
+-		dev->state |= DEV_MISCONFIGURED;
+-		em28xx_videodbg("device is misconfigured; close and "
+-			"open /dev/video%d again\n",
+-				dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
+-		return rc;
+-	}
+-
+-	return 0;
+-}
+-
+-
+ static int check_dev(struct em28xx *dev)
+ {
+ 	if (dev->state & DEV_DISCONNECTED) {
+@@ -370,8 +694,8 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
+ 	f->fmt.pix.width = dev->width;
+ 	f->fmt.pix.height = dev->height;
+ 	f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+-	f->fmt.pix.bytesperline = dev->bytesperline;
+-	f->fmt.pix.sizeimage = dev->frame_size;
++	f->fmt.pix.bytesperline = dev->width * 2;
++	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline  * dev->height;
+ 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ 
+ 	/* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
+@@ -447,7 +771,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ {
+ 	struct em28xx_fh      *fh  = priv;
+ 	struct em28xx         *dev = fh->dev;
+-	int                   rc, i;
++	int                   rc;
+ 
+ 	rc = check_dev(dev);
+ 	if (rc < 0)
+@@ -457,49 +781,34 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ 
+ 	mutex_lock(&dev->lock);
+ 
+-	for (i = 0; i < dev->num_frames; i++)
+-		if (dev->frame[i].vma_use_count) {
+-			em28xx_videodbg("VIDIOC_S_FMT failed. "
+-					"Unmap the buffers first.\n");
+-			rc = -EINVAL;
+-			goto err;
+-		}
+-
+-	/* stop io in case it is already in progress */
+-	if (dev->stream == STREAM_ON) {
+-		em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n");
+-		rc = em28xx_stream_interrupt(dev);
+-		if (rc < 0)
+-			goto err;
++	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
++		em28xx_errdev("%s queue busy\n", __func__);
++		rc = -EBUSY;
++		goto out;
+ 	}
+ 
+-	em28xx_release_buffers(dev);
+-	dev->io = IO_NONE;
++	if (dev->stream_on && !fh->stream_on) {
++		em28xx_errdev("%s device in use by another fh\n", __func__);
++		rc = -EBUSY;
++		goto out;
++	}
+ 
+ 	/* set new image size */
+ 	dev->width = f->fmt.pix.width;
+ 	dev->height = f->fmt.pix.height;
+-	dev->frame_size = dev->width * dev->height * 2;
+-	dev->field_size = dev->frame_size >> 1;
+-	dev->bytesperline = dev->width * 2;
+ 	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+ 
+-	/* FIXME: This is really weird! Why capture is starting with
+-	   this ioctl ???
+-	 */
+-	em28xx_uninit_isoc(dev);
+ 	em28xx_set_alternate(dev);
+-	em28xx_capture_start(dev, 1);
+ 	em28xx_resolution_set(dev);
+-	em28xx_init_isoc(dev);
++
+ 	rc = 0;
+ 
+-err:
++out:
+ 	mutex_unlock(&dev->lock);
+ 	return rc;
+ }
+ 
+-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
++static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
+ {
+ 	struct em28xx_fh   *fh  = priv;
+ 	struct em28xx      *dev = fh->dev;
+@@ -524,9 +833,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+ 	/* set new image size */
+ 	dev->width = f.fmt.pix.width;
+ 	dev->height = f.fmt.pix.height;
+-	dev->frame_size = dev->width * dev->height * 2;
+-	dev->field_size = dev->frame_size >> 1;
+-	dev->bytesperline = dev->width * 2;
+ 	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+ 
+ 	em28xx_resolution_set(dev);
+@@ -619,11 +925,11 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+ 
+ 	index = dev->ctl_ainput;
+ 
+-	if (index == 0) {
++	if (index == 0)
+ 		strcpy(a->name, "Television");
+-	} else {
++	else
+ 		strcpy(a->name, "Line In");
+-	}
++
+ 	a->capability = V4L2_AUDCAP_STEREO;
+ 	a->index = index;
+ 
+@@ -834,9 +1140,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
+ static int em28xx_reg_len(int reg)
+ {
+ 	switch (reg) {
+-	case AC97LSB_REG:
+-	case HSCALELOW_REG:
+-	case VSCALELOW_REG:
++	case EM28XX_R40_AC97LSB:
++	case EM28XX_R30_HSCALELOW:
++	case EM28XX_R32_VSCALELOW:
+ 		return 2;
+ 	default:
+ 		return 1;
+@@ -918,23 +1224,11 @@ static int vidioc_streamon(struct file *file, void *priv,
+ 	if (rc < 0)
+ 		return rc;
+ 
+-	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
+-		return -EINVAL;
+-
+-	if (list_empty(&dev->inqueue))
+-		return -EINVAL;
+-
+-	mutex_lock(&dev->lock);
+ 
+-	if (unlikely(res_get(fh) < 0)) {
+-		mutex_unlock(&dev->lock);
++	if (unlikely(res_get(fh) < 0))
+ 		return -EBUSY;
+-	}
+ 
+-	dev->stream = STREAM_ON;	/* FIXME: Start video capture here? */
+-
+-	mutex_unlock(&dev->lock);
+-	return 0;
++	return (videobuf_streamon(&fh->vb_vidq));
+ }
+ 
+ static int vidioc_streamoff(struct file *file, void *priv,
+@@ -948,23 +1242,14 @@ static int vidioc_streamoff(struct file *file, void *priv,
+ 	if (rc < 0)
+ 		return rc;
+ 
+-	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
++	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++	if (type != fh->type)
+ 		return -EINVAL;
+ 
+-	mutex_lock(&dev->lock);
+-
+-	if (dev->stream == STREAM_ON) {
+-		em28xx_videodbg("VIDIOC_STREAMOFF: interrupting stream\n");
+-		rc = em28xx_stream_interrupt(dev);
+-		if (rc < 0) {
+-			mutex_unlock(&dev->lock);
+-			return rc;
+-		}
+-	}
+-
+-	em28xx_empty_framequeues(dev);
++	videobuf_streamoff(&fh->vb_vidq);
++	res_free(fh);
+ 
+-	mutex_unlock(&dev->lock);
+ 	return 0;
+ }
+ 
+@@ -1058,53 +1343,13 @@ static int vidioc_reqbufs(struct file *file, void *priv,
+ {
+ 	struct em28xx_fh      *fh  = priv;
+ 	struct em28xx         *dev = fh->dev;
+-	u32                   i;
+ 	int                   rc;
+ 
+ 	rc = check_dev(dev);
+ 	if (rc < 0)
+ 		return rc;
+ 
+-	if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+-		rb->memory != V4L2_MEMORY_MMAP)
+-		return -EINVAL;
+-
+-	if (dev->io == IO_READ) {
+-		em28xx_videodbg("method is set to read;"
+-				" close and open the device again to"
+-				" choose the mmap I/O method\n");
+-		return -EINVAL;
+-	}
+-
+-	for (i = 0; i < dev->num_frames; i++)
+-		if (dev->frame[i].vma_use_count) {
+-			em28xx_videodbg("VIDIOC_REQBUFS failed; "
+-					"previous buffers are still mapped\n");
+-			return -EINVAL;
+-		}
+-
+-	mutex_lock(&dev->lock);
+-
+-	if (dev->stream == STREAM_ON) {
+-		em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n");
+-		rc = em28xx_stream_interrupt(dev);
+-		if (rc < 0) {
+-			mutex_unlock(&dev->lock);
+-			return rc;
+-		}
+-	}
+-
+-	em28xx_empty_framequeues(dev);
+-
+-	em28xx_release_buffers(dev);
+-	if (rb->count)
+-		rb->count = em28xx_request_buffers(dev, rb->count);
+-
+-	dev->frame_current = NULL;
+-	dev->io = rb->count ? IO_MMAP : IO_NONE;
+-
+-	mutex_unlock(&dev->lock);
+-	return 0;
++	return (videobuf_reqbufs(&fh->vb_vidq, rb));
+ }
+ 
+ static int vidioc_querybuf(struct file *file, void *priv,
+@@ -1118,52 +1363,20 @@ static int vidioc_querybuf(struct file *file, void *priv,
+ 	if (rc < 0)
+ 		return rc;
+ 
+-	if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+-		b->index >= dev->num_frames || dev->io != IO_MMAP)
+-		return -EINVAL;
+-
+-	mutex_lock(&dev->lock);
+-
+-	memcpy(b, &dev->frame[b->index].buf, sizeof(*b));
+-
+-	if (dev->frame[b->index].vma_use_count)
+-		b->flags |= V4L2_BUF_FLAG_MAPPED;
+-
+-	if (dev->frame[b->index].state == F_DONE)
+-		b->flags |= V4L2_BUF_FLAG_DONE;
+-	else if (dev->frame[b->index].state != F_UNUSED)
+-		b->flags |= V4L2_BUF_FLAG_QUEUED;
+-
+-	mutex_unlock(&dev->lock);
+-	return 0;
++	return (videobuf_querybuf(&fh->vb_vidq, b));
+ }
+ 
+ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+ {
+ 	struct em28xx_fh      *fh  = priv;
+ 	struct em28xx         *dev = fh->dev;
+-	unsigned long         lock_flags;
+ 	int                   rc;
+ 
+ 	rc = check_dev(dev);
+ 	if (rc < 0)
+ 		return rc;
+ 
+-	if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE  || dev->io != IO_MMAP ||
+-						b->index >= dev->num_frames)
+-		return -EINVAL;
+-
+-	if (dev->frame[b->index].state != F_UNUSED)
+-		return -EAGAIN;
+-
+-	dev->frame[b->index].state = F_QUEUED;
+-
+-	/* add frame to fifo */
+-	spin_lock_irqsave(&dev->queue_lock, lock_flags);
+-	list_add_tail(&dev->frame[b->index].frame, &dev->inqueue);
+-	spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+-
+-	return 0;
++	return (videobuf_qbuf(&fh->vb_vidq, b));
+ }
+ 
+ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+@@ -1171,46 +1384,24 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+ 	struct em28xx_fh      *fh  = priv;
+ 	struct em28xx         *dev = fh->dev;
+ 	int                   rc;
+-	struct em28xx_frame_t *f;
+-	unsigned long         lock_flags;
+ 
+ 	rc = check_dev(dev);
+ 	if (rc < 0)
+ 		return rc;
+ 
+-	if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
+-		return -EINVAL;
+-
+-	if (list_empty(&dev->outqueue)) {
+-		if (dev->stream == STREAM_OFF)
+-			return -EINVAL;
+-
+-		if (file->f_flags & O_NONBLOCK)
+-			return -EAGAIN;
+-
+-		rc = wait_event_interruptible(dev->wait_frame,
+-					(!list_empty(&dev->outqueue)) ||
+-					(dev->state & DEV_DISCONNECTED));
+-		if (rc)
+-			return rc;
+-
+-		if (dev->state & DEV_DISCONNECTED)
+-			return -ENODEV;
+-	}
+-
+-	spin_lock_irqsave(&dev->queue_lock, lock_flags);
+-	f = list_entry(dev->outqueue.next, struct em28xx_frame_t, frame);
+-	list_del(dev->outqueue.next);
+-	spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+-
+-	f->state = F_UNUSED;
+-	memcpy(b, &f->buf, sizeof(*b));
++	return (videobuf_dqbuf(&fh->vb_vidq, b,
++				file->f_flags & O_NONBLOCK));
++}
+ 
+-	if (f->vma_use_count)
+-		b->flags |= V4L2_BUF_FLAG_MAPPED;
++#ifdef CONFIG_VIDEO_V4L1_COMPAT
++static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
++{
++	struct em28xx_fh  *fh = priv;
+ 
+-	return 0;
++	return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
+ }
++#endif
++
+ 
+ /* ----------------------------------------------------------- */
+ /* RADIO ESPECIFIC IOCTLS                                      */
+@@ -1316,17 +1507,18 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+ {
+ 	int minor = iminor(inode);
+ 	int errCode = 0, radio = 0;
+-	struct em28xx *h,*dev = NULL;
++	struct em28xx *h, *dev = NULL;
+ 	struct em28xx_fh *fh;
++	enum v4l2_buf_type fh_type = 0;
+ 
+ 	list_for_each_entry(h, &em28xx_devlist, devlist) {
+ 		if (h->vdev->minor == minor) {
+ 			dev  = h;
+-			dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++			fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ 		}
+ 		if (h->vbi_dev->minor == minor) {
+ 			dev  = h;
+-			dev->type = V4L2_BUF_TYPE_VBI_CAPTURE;
++			fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ 		}
+ 		if (h->radio_dev &&
+ 		    h->radio_dev->minor == minor) {
+@@ -1338,10 +1530,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+ 		return -ENODEV;
+ 
+ 	em28xx_videodbg("open minor=%d type=%s users=%d\n",
+-				minor,v4l2_type_names[dev->type],dev->users);
++				minor, v4l2_type_names[fh_type], dev->users);
+ 
+-	fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
+ 
++	fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
+ 	if (!fh) {
+ 		em28xx_errdev("em28xx-video.c: Out of memory?!\n");
+ 		return -ENOMEM;
+@@ -1349,28 +1541,24 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+ 	mutex_lock(&dev->lock);
+ 	fh->dev = dev;
+ 	fh->radio = radio;
++	fh->type = fh_type;
+ 	filp->private_data = fh;
+ 
+-	if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
++	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+ 		dev->width = norm_maxw(dev);
+ 		dev->height = norm_maxh(dev);
+-		dev->frame_size = dev->width * dev->height * 2;
+-		dev->field_size = dev->frame_size >> 1;	/*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
+-		dev->bytesperline = dev->width * 2;
+ 		dev->hscale = 0;
+ 		dev->vscale = 0;
+ 
++		em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+ 		em28xx_set_alternate(dev);
+-		em28xx_capture_start(dev, 1);
+ 		em28xx_resolution_set(dev);
+ 
++		/* Needed, since GPIO might have disabled power of
++		   some i2c device
++		 */
++		em28xx_config_i2c(dev);
+ 
+-		/* start the transfer */
+-		errCode = em28xx_init_isoc(dev);
+-		if (errCode)
+-			goto err;
+-
+-		em28xx_empty_framequeues(dev);
+ 	}
+ 	if (fh->radio) {
+ 		em28xx_videodbg("video_open: setting radio device\n");
+@@ -1379,8 +1567,12 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+ 
+ 	dev->users++;
+ 
+-err:
++	videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
++			NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
++			sizeof(struct em28xx_buffer), fh);
++
+ 	mutex_unlock(&dev->lock);
++
+ 	return errCode;
+ }
+ 
+@@ -1423,12 +1615,13 @@ static void em28xx_release_resources(struct em28xx *dev)
+ 	usb_put_dev(dev->udev);
+ 
+ 	/* Mark device as unused */
+-	em28xx_devused&=~(1<<dev->devno);
++	em28xx_devused &= ~(1<<dev->devno);
+ }
+ 
+ /*
+  * em28xx_v4l2_close()
+- * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls
++ * stops streaming and deallocates all resources allocated by the v4l2
++ * calls and ioctls
+  */
+ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+ {
+@@ -1445,9 +1638,8 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+ 	mutex_lock(&dev->lock);
+ 
+ 	if (dev->users == 1) {
+-		em28xx_uninit_isoc(dev);
+-		em28xx_release_buffers(dev);
+-		dev->io = IO_NONE;
++		videobuf_stop(&fh->vb_vidq);
++		videobuf_mmap_free(&fh->vb_vidq);
+ 
+ 		/* the device is already disconnect,
+ 		   free the remaining resources */
+@@ -1458,6 +1650,10 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+ 			return 0;
+ 		}
+ 
++		/* do this before setting alternate! */
++		em28xx_uninit_isoc(dev);
++		em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++
+ 		/* set alternate 0 */
+ 		dev->alt = 0;
+ 		em28xx_videodbg("setting alternate 0\n");
+@@ -1479,135 +1675,29 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+  * will allocate buffers when called for the first time
+  */
+ static ssize_t
+-em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
+-		 loff_t * f_pos)
++em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
++		 loff_t *pos)
+ {
+-	struct em28xx_frame_t *f, *i;
+-	unsigned long lock_flags;
+-	int ret = 0;
+ 	struct em28xx_fh *fh = filp->private_data;
+ 	struct em28xx *dev = fh->dev;
++	int rc;
++
++	rc = check_dev(dev);
++	if (rc < 0)
++		return rc;
+ 
+ 	/* FIXME: read() is not prepared to allow changing the video
+ 	   resolution while streaming. Seems a bug at em28xx_set_fmt
+ 	 */
+ 
+-	if (unlikely(res_get(fh) < 0))
+-		return -EBUSY;
+-
+-	mutex_lock(&dev->lock);
+-
+-	if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-		em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
++	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
++		if (unlikely(res_get(fh)))
++			return -EBUSY;
+ 
+-	if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+-		em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
+-		em28xx_videodbg("not supported yet! ...\n");
+-		if (copy_to_user(buf, "", 1)) {
+-			mutex_unlock(&dev->lock);
+-			return -EFAULT;
+-		}
+-		mutex_unlock(&dev->lock);
+-		return (1);
+-	}
+-	if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
+-		em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n");
+-		em28xx_videodbg("not supported yet! ...\n");
+-		if (copy_to_user(buf, "", 1)) {
+-			mutex_unlock(&dev->lock);
+-			return -EFAULT;
+-		}
+-		mutex_unlock(&dev->lock);
+-		return (1);
++		return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
++					filp->f_flags & O_NONBLOCK);
+ 	}
+-
+-	if (dev->state & DEV_DISCONNECTED) {
+-		em28xx_videodbg("device not present\n");
+-		mutex_unlock(&dev->lock);
+-		return -ENODEV;
+-	}
+-
+-	if (dev->state & DEV_MISCONFIGURED) {
+-		em28xx_videodbg("device misconfigured; close and open it again\n");
+-		mutex_unlock(&dev->lock);
+-		return -EIO;
+-	}
+-
+-	if (dev->io == IO_MMAP) {
+-		em28xx_videodbg ("IO method is set to mmap; close and open"
+-				" the device again to choose the read method\n");
+-		mutex_unlock(&dev->lock);
+-		return -EINVAL;
+-	}
+-
+-	if (dev->io == IO_NONE) {
+-		if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) {
+-			em28xx_errdev("read failed, not enough memory\n");
+-			mutex_unlock(&dev->lock);
+-			return -ENOMEM;
+-		}
+-		dev->io = IO_READ;
+-		dev->stream = STREAM_ON;
+-		em28xx_queue_unusedframes(dev);
+-	}
+-
+-	if (!count) {
+-		mutex_unlock(&dev->lock);
+-		return 0;
+-	}
+-
+-	if (list_empty(&dev->outqueue)) {
+-		if (filp->f_flags & O_NONBLOCK) {
+-			mutex_unlock(&dev->lock);
+-			return -EAGAIN;
+-		}
+-		ret = wait_event_interruptible
+-		    (dev->wait_frame,
+-		     (!list_empty(&dev->outqueue)) ||
+-		     (dev->state & DEV_DISCONNECTED));
+-		if (ret) {
+-			mutex_unlock(&dev->lock);
+-			return ret;
+-		}
+-		if (dev->state & DEV_DISCONNECTED) {
+-			mutex_unlock(&dev->lock);
+-			return -ENODEV;
+-		}
+-		dev->video_bytesread = 0;
+-	}
+-
+-	f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame);
+-
+-	em28xx_queue_unusedframes(dev);
+-
+-	if (count > f->buf.length)
+-		count = f->buf.length;
+-
+-	if ((dev->video_bytesread + count) > dev->frame_size)
+-		count = dev->frame_size - dev->video_bytesread;
+-
+-	if (copy_to_user(buf, f->bufmem+dev->video_bytesread, count)) {
+-		em28xx_err("Error while copying to user\n");
+-		return -EFAULT;
+-	}
+-	dev->video_bytesread += count;
+-
+-	if (dev->video_bytesread == dev->frame_size) {
+-		spin_lock_irqsave(&dev->queue_lock, lock_flags);
+-		list_for_each_entry(i, &dev->outqueue, frame)
+-				    i->state = F_UNUSED;
+-		INIT_LIST_HEAD(&dev->outqueue);
+-		spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+-
+-		em28xx_queue_unusedframes(dev);
+-		dev->video_bytesread = 0;
+-	}
+-
+-	*f_pos += count;
+-
+-	mutex_unlock(&dev->lock);
+-
+-	return count;
++	return 0;
+ }
+ 
+ /*
+@@ -1616,46 +1706,21 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
+  */
+ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
+ {
+-	unsigned int mask = 0;
+ 	struct em28xx_fh *fh = filp->private_data;
+ 	struct em28xx *dev = fh->dev;
++	int rc;
++
++	rc = check_dev(dev);
++	if (rc < 0)
++		return rc;
+ 
+ 	if (unlikely(res_get(fh) < 0))
+ 		return POLLERR;
+ 
+-	mutex_lock(&dev->lock);
+-
+-	if (dev->state & DEV_DISCONNECTED) {
+-		em28xx_videodbg("device not present\n");
+-	} else if (dev->state & DEV_MISCONFIGURED) {
+-		em28xx_videodbg("device is misconfigured; close and open it again\n");
+-	} else {
+-		if (dev->io == IO_NONE) {
+-			if (!em28xx_request_buffers
+-			    (dev, EM28XX_NUM_READ_FRAMES)) {
+-				em28xx_warn
+-				    ("poll() failed, not enough memory\n");
+-			} else {
+-				dev->io = IO_READ;
+-				dev->stream = STREAM_ON;
+-			}
+-		}
+-
+-		if (dev->io == IO_READ) {
+-			em28xx_queue_unusedframes(dev);
+-			poll_wait(filp, &dev->wait_frame, wait);
+-
+-			if (!list_empty(&dev->outqueue))
+-				mask |= POLLIN | POLLRDNORM;
+-
+-			mutex_unlock(&dev->lock);
+-
+-			return mask;
+-		}
+-	}
++	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
++		return POLLERR;
+ 
+-	mutex_unlock(&dev->lock);
+-	return POLLERR;
++	return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+ }
+ 
+ /*
+@@ -1665,69 +1730,23 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+ 	struct em28xx_fh *fh    = filp->private_data;
+ 	struct em28xx	 *dev   = fh->dev;
+-	unsigned long	 size   = vma->vm_end - vma->vm_start;
+-	unsigned long	 start  = vma->vm_start;
+-	void 		 *pos;
+-	u32		 i;
++	int		 rc;
+ 
+ 	if (unlikely(res_get(fh) < 0))
+ 		return -EBUSY;
+ 
+-	mutex_lock(&dev->lock);
+-
+-	if (dev->state & DEV_DISCONNECTED) {
+-		em28xx_videodbg("mmap: device not present\n");
+-		mutex_unlock(&dev->lock);
+-		return -ENODEV;
+-	}
+-
+-	if (dev->state & DEV_MISCONFIGURED) {
+-		em28xx_videodbg ("mmap: Device is misconfigured; close and "
+-						"open it again\n");
+-		mutex_unlock(&dev->lock);
+-		return -EIO;
+-	}
+-
+-	if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE)) {
+-		mutex_unlock(&dev->lock);
+-		return -EINVAL;
+-	}
+-
+-	if (size > PAGE_ALIGN(dev->frame[0].buf.length))
+-		size = PAGE_ALIGN(dev->frame[0].buf.length);
+-
+-	for (i = 0; i < dev->num_frames; i++) {
+-		if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
+-			break;
+-	}
+-	if (i == dev->num_frames) {
+-		em28xx_videodbg("mmap: user supplied mapping address is out of range\n");
+-		mutex_unlock(&dev->lock);
+-		return -EINVAL;
+-	}
+-
+-	/* VM_IO is eventually going to replace PageReserved altogether */
+-	vma->vm_flags |= VM_IO;
+-	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
++	rc = check_dev(dev);
++	if (rc < 0)
++		return rc;
+ 
+-	pos = dev->frame[i].bufmem;
+-	while (size > 0) {	/* size is page-aligned */
+-		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+-			em28xx_videodbg("mmap: vm_insert_page failed\n");
+-			mutex_unlock(&dev->lock);
+-			return -EAGAIN;
+-		}
+-		start += PAGE_SIZE;
+-		pos += PAGE_SIZE;
+-		size -= PAGE_SIZE;
+-	}
++	rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+ 
+-	vma->vm_ops = &em28xx_vm_ops;
+-	vma->vm_private_data = &dev->frame[i];
++	em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
++		(unsigned long)vma->vm_start,
++		(unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
++		rc);
+ 
+-	em28xx_vm_open(vma);
+-	mutex_unlock(&dev->lock);
+-	return 0;
++	return rc;
+ }
+ 
+ static const struct file_operations em28xx_v4l_fops = {
+@@ -1790,6 +1809,9 @@ static const struct video_device em28xx_video_template = {
+ 	.vidioc_g_register          = vidioc_g_register,
+ 	.vidioc_s_register          = vidioc_s_register,
+ #endif
++#ifdef CONFIG_VIDEO_V4L1_COMPAT
++	.vidiocgmbuf                = vidiocgmbuf,
++#endif
+ 
+ 	.tvnorms                    = V4L2_STD_ALL,
+ 	.current_norm               = V4L2_STD_PAL,
+@@ -1818,7 +1840,7 @@ static struct video_device em28xx_radio_template = {
+ #endif
+ };
+ 
+-/******************************** usb interface *****************************************/
++/******************************** usb interface ******************************/
+ 
+ 
+ static LIST_HEAD(em28xx_extension_devlist);
+@@ -1875,6 +1897,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
+ 	vfd->dev = &dev->udev->dev;
+ 	vfd->release = video_device_release;
+ 	vfd->type = type;
++	vfd->debug = video_debug;
+ 
+ 	snprintf(vfd->name, sizeof(vfd->name), "%s %s",
+ 		 dev->name, type_name);
+@@ -1898,7 +1921,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+ 
+ 	dev->udev = udev;
+ 	mutex_init(&dev->lock);
+-	spin_lock_init(&dev->queue_lock);
++	spin_lock_init(&dev->slock);
+ 	init_waitqueue_head(&dev->open);
+ 	init_waitqueue_head(&dev->wait_frame);
+ 	init_waitqueue_head(&dev->wait_stream);
+@@ -1910,10 +1933,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+ 	dev->em28xx_read_reg_req = em28xx_read_reg_req;
+ 	dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
+ 
+-	errCode = em28xx_read_reg(dev, CHIPID_REG);
+-	if (errCode >= 0)
+-		em28xx_info("em28xx chip ID = %d\n", errCode);
+-
+ 	em28xx_pre_card_setup(dev);
+ 
+ 	errCode = em28xx_config(dev);
+@@ -1946,10 +1965,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+ 	dev->width = maxw;
+ 	dev->height = maxh;
+ 	dev->interlaced = EM28XX_INTERLACED_DEFAULT;
+-	dev->field_size = dev->width * dev->height;
+-	dev->frame_size =
+-	    dev->interlaced ? dev->field_size << 1 : dev->field_size;
+-	dev->bytesperline = dev->width * 2;
+ 	dev->hscale = 0;
+ 	dev->vscale = 0;
+ 	dev->ctl_input = 2;
+@@ -2005,6 +2020,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+ 			    dev->radio_dev->minor & 0x1f);
+ 	}
+ 
++	/* init video dma queues */
++	INIT_LIST_HEAD(&dev->vidq.active);
++	INIT_LIST_HEAD(&dev->vidq.queued);
++
+ 
+ 	if (dev->has_msp34xx) {
+ 		/* Send a reset to other chips via gpio */
+@@ -2048,6 +2067,9 @@ static void request_module_async(struct work_struct *work)
+ 		request_module("snd-usb-audio");
+ 	else
+ 		request_module("em28xx-alsa");
++
++	if (dev->has_dvb)
++		request_module("em28xx-dvb");
+ }
+ 
+ static void request_modules(struct em28xx *dev)
+@@ -2077,22 +2099,24 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ 	ifnum = interface->altsetting[0].desc.bInterfaceNumber;
+ 
+ 	/* Check to see next free device and mark as used */
+-	nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS);
+-	em28xx_devused|=1<<nr;
++	nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
++	em28xx_devused |= 1<<nr;
+ 
+ 	/* Don't register audio interfaces */
+ 	if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
+ 		em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n",
+-				udev->descriptor.idVendor,udev->descriptor.idProduct,
++				udev->descriptor.idVendor,
++				udev->descriptor.idProduct,
+ 				ifnum,
+ 				interface->altsetting[0].desc.bInterfaceClass);
+ 
+-		em28xx_devused&=~(1<<nr);
++		em28xx_devused &= ~(1<<nr);
+ 		return -ENODEV;
+ 	}
+ 
+ 	em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n",
+-			udev->descriptor.idVendor,udev->descriptor.idProduct,
++			udev->descriptor.idVendor,
++			udev->descriptor.idProduct,
+ 			ifnum,
+ 			interface->altsetting[0].desc.bInterfaceClass);
+ 
+@@ -2102,18 +2126,19 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ 	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+ 	    USB_ENDPOINT_XFER_ISOC) {
+ 		em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
+-		em28xx_devused&=~(1<<nr);
++		em28xx_devused &= ~(1<<nr);
+ 		return -ENODEV;
+ 	}
+ 	if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+ 		em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
+-		em28xx_devused&=~(1<<nr);
++		em28xx_devused &= ~(1<<nr);
+ 		return -ENODEV;
+ 	}
+ 
+ 	if (nr >= EM28XX_MAXBOARDS) {
+-		printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS);
+-		em28xx_devused&=~(1<<nr);
++		printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
++				EM28XX_MAXBOARDS);
++		em28xx_devused &= ~(1<<nr);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -2121,7 +2146,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ 	if (dev == NULL) {
+ 		em28xx_err(DRIVER_NAME ": out of memory!\n");
+-		em28xx_devused&=~(1<<nr);
++		em28xx_devused &= ~(1<<nr);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -2145,14 +2170,14 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ 	/* compute alternate max packet sizes */
+ 	uif = udev->actconfig->interface[0];
+ 
+-	dev->num_alt=uif->num_altsetting;
+-	em28xx_info("Alternate settings: %i\n",dev->num_alt);
+-//	dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)*
+-	dev->alt_max_pkt_size = kmalloc(32*
+-						dev->num_alt,GFP_KERNEL);
++	dev->num_alt = uif->num_altsetting;
++	em28xx_info("Alternate settings: %i\n", dev->num_alt);
++/*	dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */
++	dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);
++
+ 	if (dev->alt_max_pkt_size == NULL) {
+ 		em28xx_errdev("out of memory!\n");
+-		em28xx_devused&=~(1<<nr);
++		em28xx_devused &= ~(1<<nr);
+ 		kfree(dev);
+ 		return -ENOMEM;
+ 	}
+@@ -2162,11 +2187,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ 							wMaxPacketSize);
+ 		dev->alt_max_pkt_size[i] =
+ 		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+-		em28xx_info("Alternate setting %i, max size= %i\n",i,
+-							dev->alt_max_pkt_size[i]);
++		em28xx_info("Alternate setting %i, max size= %i\n", i,
++						dev->alt_max_pkt_size[i]);
+ 	}
+ 
+-	if ((card[nr]>=0)&&(card[nr]<em28xx_bcount))
++	if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
+ 		dev->model = card[nr];
+ 
+ 	/* allocate device struct */
+@@ -2202,7 +2227,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
+ 
+ 	em28xx_info("disconnecting %s\n", dev->vdev->name);
+ 
+-	/* wait until all current v4l2 io is finished then deallocate resources */
++	/* wait until all current v4l2 io is finished then deallocate
++	   resources */
+ 	mutex_lock(&dev->lock);
+ 
+ 	wake_up_interruptible_all(&dev->open);
+diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
+index 04e0e48..002f170 100644
+--- a/drivers/media/video/em28xx/em28xx.h
++++ b/drivers/media/video/em28xx/em28xx.h
+@@ -26,11 +26,39 @@
+ #define _EM28XX_H
+ 
+ #include <linux/videodev2.h>
++#include <media/videobuf-vmalloc.h>
++
+ #include <linux/i2c.h>
+ #include <linux/mutex.h>
+ #include <media/ir-kbd-i2c.h>
+-
+-#define UNSET -1
++#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE)
++#include <media/videobuf-dvb.h>
++#endif
++#include "tuner-xc2028.h"
++#include "em28xx-reg.h"
++
++/* Boards supported by driver */
++#define EM2800_BOARD_UNKNOWN			0
++#define EM2820_BOARD_UNKNOWN			1
++#define EM2820_BOARD_TERRATEC_CINERGY_250	2
++#define EM2820_BOARD_PINNACLE_USB_2		3
++#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
++#define EM2820_BOARD_MSI_VOX_USB_2              5
++#define EM2800_BOARD_TERRATEC_CINERGY_200       6
++#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
++#define EM2800_BOARD_KWORLD_USB2800             8
++#define EM2820_BOARD_PINNACLE_DVC_90		9
++#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900	10
++#define EM2880_BOARD_TERRATEC_HYBRID_XS		11
++#define EM2820_BOARD_KWORLD_PVRTV2800RF		12
++#define EM2880_BOARD_TERRATEC_PRODIGY_XS	13
++#define EM2820_BOARD_PROLINK_PLAYTV_USB2	14
++#define EM2800_BOARD_VGEAR_POCKETTV             15
++#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950	16
++
++/* Limits minimum and default number of buffers */
++#define EM28XX_MIN_BUF 4
++#define EM28XX_DEF_BUF 8
+ 
+ /* maximum number of em28xx boards */
+ #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
+@@ -81,31 +109,78 @@
+ /* time in msecs to wait for i2c writes to finish */
+ #define EM2800_I2C_WRITE_TIMEOUT 20
+ 
+-/* the various frame states */
+-enum em28xx_frame_state {
+-	F_UNUSED = 0,
+-	F_QUEUED,
+-	F_GRABBING,
+-	F_DONE,
+-	F_ERROR,
++enum em28xx_mode {
++	EM28XX_MODE_UNDEFINED,
++	EM28XX_ANALOG_MODE,
++	EM28XX_DIGITAL_MODE,
+ };
+ 
+-/* stream states */
+ enum em28xx_stream_state {
+ 	STREAM_OFF,
+ 	STREAM_INTERRUPT,
+ 	STREAM_ON,
+ };
+ 
+-/* frames */
+-struct em28xx_frame_t {
+-	void *bufmem;
+-	struct v4l2_buffer buf;
+-	enum em28xx_frame_state state;
++struct em28xx;
++
++struct em28xx_usb_isoc_ctl {
++		/* max packet size of isoc transaction */
++	int				max_pkt_size;
++
++		/* number of allocated urbs */
++	int				num_bufs;
++
++		/* urb for isoc transfers */
++	struct urb			**urb;
++
++		/* transfer buffers for isoc transfer */
++	char				**transfer_buffer;
++
++		/* Last buffer command and region */
++	u8				cmd;
++	int				pos, size, pktsize;
++
++		/* Last field: ODD or EVEN? */
++	int				field;
++
++		/* Stores incomplete commands */
++	u32				tmp_buf;
++	int				tmp_buf_len;
++
++		/* Stores already requested buffers */
++	struct em28xx_buffer    	*buf;
++
++		/* Stores the number of received fields */
++	int				nfields;
++
++		/* isoc urb callback */
++	int (*isoc_copy) (struct em28xx *dev, struct urb *urb);
++
++};
++
++struct em28xx_fmt {
++	char  *name;
++	u32   fourcc;          /* v4l2 format id */
++};
++
++/* buffer for one video frame */
++struct em28xx_buffer {
++	/* common v4l buffer stuff -- must be first */
++	struct videobuf_buffer vb;
++
+ 	struct list_head frame;
+-	unsigned long vma_use_count;
+ 	int top_field;
+-	int fieldbytesused;
++	int receiving;
++};
++
++struct em28xx_dmaqueue {
++	struct list_head       active;
++	struct list_head       queued;
++
++	wait_queue_head_t          wq;
++
++	/* Counters to control buffer fill */
++	int                        pos;
+ };
+ 
+ /* io methods */
+@@ -152,6 +227,12 @@ enum em28xx_decoder {
+ 	EM28XX_SAA7114
+ };
+ 
++struct em28xx_reg_seq {
++	int reg;
++	unsigned char val, mask;
++	int sleep;
++};
++
+ struct em28xx_board {
+ 	char *name;
+ 	int vchannels;
+@@ -165,8 +246,7 @@ struct em28xx_board {
+ 	unsigned int mts_firmware:1;
+ 	unsigned int has_12mhz_i2s:1;
+ 	unsigned int max_range_640_480:1;
+-
+-	unsigned int analog_gpio;
++	unsigned int has_dvb:1;
+ 
+ 	enum em28xx_decoder decoder;
+ 
+@@ -199,7 +279,10 @@ enum em28xx_dev_state {
+ #define EM28XX_NUM_AUDIO_PACKETS 64
+ #define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */
+ #define EM28XX_CAPTURE_STREAM_EN 1
++
++/* em28xx extensions */
+ #define EM28XX_AUDIO   0x10
++#define EM28XX_DVB     0x20
+ 
+ struct em28xx_audio {
+ 	char name[50];
+@@ -217,13 +300,24 @@ struct em28xx_audio {
+ 	spinlock_t slock;
+ };
+ 
++struct em28xx;
++
++struct em28xx_fh {
++	struct em28xx *dev;
++	unsigned int  stream_on:1;	/* Locks streams */
++	int           radio;
++
++	struct videobuf_queue        vb_vidq;
++
++	enum v4l2_buf_type           type;
++};
++
+ /* main device struct */
+ struct em28xx {
+ 	/* generic device properties */
+ 	char name[30];		/* name (including minor) of the device */
+ 	int model;		/* index in the device_data struct */
+ 	int devno;		/* marks the number of this device */
+-	unsigned int analog_gpio;
+ 	unsigned int is_em2800:1;
+ 	unsigned int has_msp34xx:1;
+ 	unsigned int has_tda9887:1;
+@@ -231,6 +325,16 @@ struct em28xx {
+ 	unsigned int has_audio_class:1;
+ 	unsigned int has_12mhz_i2s:1;
+ 	unsigned int max_range_640_480:1;
++	unsigned int has_dvb:1;
++
++	/* Some older em28xx chips needs a waiting time after writing */
++	unsigned int wait_after_write;
++
++	/* GPIO sequences for analog and digital mode */
++	struct em28xx_reg_seq *analog_gpio, *digital_gpio;
++
++	/* GPIO sequences for tuner callbacks */
++	struct em28xx_reg_seq *tun_analog_gpio, *tun_digital_gpio;
+ 
+ 	int video_inputs;	/* number of video inputs */
+ 	struct list_head	devlist;
+@@ -255,36 +359,28 @@ struct em28xx {
+ 	int mute;
+ 	int volume;
+ 	/* frame properties */
+-	struct em28xx_frame_t frame[EM28XX_NUM_FRAMES];	/* list of frames */
+-	int num_frames;		/* number of frames currently in use */
+-	unsigned int frame_count;	/* total number of transfered frames */
+-	struct em28xx_frame_t *frame_current;	/* the frame that is being filled */
+ 	int width;		/* current frame width */
+ 	int height;		/* current frame height */
+-	int frame_size;		/* current frame size */
+-	int field_size;		/* current field size */
+-	int bytesperline;
+ 	int hscale;		/* horizontal scale factor (see datasheet) */
+ 	int vscale;		/* vertical scale factor (see datasheet) */
+ 	int interlaced;		/* 1=interlace fileds, 0=just top fileds */
+-	int type;
+ 	unsigned int video_bytesread;	/* Number of bytes read */
+ 
+ 	unsigned long hash;	/* eeprom hash - for boards with generic ID */
+-	unsigned long i2c_hash;	/* i2c devicelist hash - for boards with generic ID */
++	unsigned long i2c_hash;	/* i2c devicelist hash -
++				   for boards with generic ID */
+ 
+ 	struct em28xx_audio *adev;
+ 
+ 	/* states */
+ 	enum em28xx_dev_state state;
+-	enum em28xx_stream_state stream;
+ 	enum em28xx_io_method io;
+ 
+ 	struct work_struct         request_module_wk;
+ 
+ 	/* locks */
+ 	struct mutex lock;
+-	spinlock_t queue_lock;
++	/* spinlock_t queue_lock; */
+ 	struct list_head inqueue, outqueue;
+ 	wait_queue_head_t open, wait_frame, wait_stream;
+ 	struct video_device *vbi_dev;
+@@ -292,6 +388,11 @@ struct em28xx {
+ 
+ 	unsigned char eedata[256];
+ 
++	/* Isoc control struct */
++	struct em28xx_dmaqueue vidq;
++	struct em28xx_usb_isoc_ctl isoc_ctl;
++	spinlock_t slock;
++
+ 	/* usb transfer */
+ 	struct usb_device *udev;	/* the usb device */
+ 	int alt;		/* alternate */
+@@ -301,20 +402,21 @@ struct em28xx {
+ 	struct urb *urb[EM28XX_NUM_BUFS];	/* urb for isoc transfers */
+ 	char *transfer_buffer[EM28XX_NUM_BUFS];	/* transfer buffers for isoc transfer */
+ 	/* helper funcs that call usb_control_msg */
+-	int (*em28xx_write_regs) (struct em28xx * dev, u16 reg, char *buf,
+-				  int len);
+-	int (*em28xx_read_reg) (struct em28xx * dev, u16 reg);
+-	int (*em28xx_read_reg_req_len) (struct em28xx * dev, u8 req, u16 reg,
++	int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
+ 					char *buf, int len);
+-	int (*em28xx_write_regs_req) (struct em28xx * dev, u8 req, u16 reg,
++	int (*em28xx_read_reg) (struct em28xx *dev, u16 reg);
++	int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg,
++					char *buf, int len);
++	int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg,
+ 				      char *buf, int len);
+-	int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg);
+-};
++	int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg);
+ 
+-struct em28xx_fh {
+-	struct em28xx *dev;
+-	unsigned int  stream_on:1;	/* Locks streams */
+-	int           radio;
++	enum em28xx_mode mode;
++
++	/* Caches GPO and GPIO registers */
++	unsigned char	reg_gpo, reg_gpio;
++
++	struct em28xx_dvb *dvb;
+ };
+ 
+ struct em28xx_ops {
+@@ -351,22 +453,27 @@ int em28xx_colorlevels_set_default(struct em28xx *dev);
+ int em28xx_capture_start(struct em28xx *dev, int start);
+ int em28xx_outfmt_set_yuv422(struct em28xx *dev);
+ int em28xx_resolution_set(struct em28xx *dev);
+-int em28xx_init_isoc(struct em28xx *dev);
+-void em28xx_uninit_isoc(struct em28xx *dev);
+ int em28xx_set_alternate(struct em28xx *dev);
++int em28xx_init_isoc(struct em28xx *dev, int max_packets,
++		     int num_bufs, int max_pkt_size,
++		     int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
++void em28xx_uninit_isoc(struct em28xx *dev);
++int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
++int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
+ 
+ /* Provided by em28xx-video.c */
+ int em28xx_register_extension(struct em28xx_ops *dev);
+ void em28xx_unregister_extension(struct em28xx_ops *dev);
+ 
+ /* Provided by em28xx-cards.c */
+-extern int em2800_variant_detect(struct usb_device* udev,int model);
++extern int em2800_variant_detect(struct usb_device *udev, int model);
+ extern void em28xx_pre_card_setup(struct em28xx *dev);
+ extern void em28xx_card_setup(struct em28xx *dev);
+ extern struct em28xx_board em28xx_boards[];
+ extern struct usb_device_id em28xx_id_table[];
+ extern const unsigned int em28xx_bcount;
+ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
++int em28xx_tuner_callback(void *ptr, int command, int arg);
+ 
+ /* Provided by em28xx-input.c */
+ /* TODO: Check if the standard get_key handlers on ir-common can be used */
+@@ -375,71 +482,6 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
+ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
+ 				     u32 *ir_raw);
+ 
+-/* em2800 registers */
+-#define EM2800_AUDIOSRC_REG 0x08
+-
+-/* em28xx registers */
+-#define I2C_CLK_REG	0x06
+-#define CHIPID_REG	0x0a
+-#define USBSUSP_REG	0x0c	/* */
+-
+-#define AUDIOSRC_REG	0x0e
+-#define XCLK_REG	0x0f
+-
+-#define VINMODE_REG	0x10
+-#define VINCTRL_REG	0x11
+-#define VINENABLE_REG	0x12	/* */
+-
+-#define GAMMA_REG	0x14
+-#define RGAIN_REG	0x15
+-#define GGAIN_REG	0x16
+-#define BGAIN_REG	0x17
+-#define ROFFSET_REG	0x18
+-#define GOFFSET_REG	0x19
+-#define BOFFSET_REG	0x1a
+-
+-#define OFLOW_REG	0x1b
+-#define HSTART_REG	0x1c
+-#define VSTART_REG	0x1d
+-#define CWIDTH_REG	0x1e
+-#define CHEIGHT_REG	0x1f
+-
+-#define YGAIN_REG	0x20
+-#define YOFFSET_REG	0x21
+-#define UVGAIN_REG	0x22
+-#define UOFFSET_REG	0x23
+-#define VOFFSET_REG	0x24
+-#define SHARPNESS_REG	0x25
+-
+-#define COMPR_REG	0x26
+-#define OUTFMT_REG	0x27
+-
+-#define XMIN_REG	0x28
+-#define XMAX_REG	0x29
+-#define YMIN_REG	0x2a
+-#define YMAX_REG	0x2b
+-
+-#define HSCALELOW_REG	0x30
+-#define HSCALEHIGH_REG	0x31
+-#define VSCALELOW_REG	0x32
+-#define VSCALEHIGH_REG	0x33
+-
+-#define AC97LSB_REG	0x40
+-#define AC97MSB_REG	0x41
+-#define AC97ADDR_REG	0x42
+-#define AC97BUSY_REG	0x43
+-
+-/* em202 registers */
+-#define MASTER_AC97	0x02
+-#define LINE_IN_AC97    0x10
+-#define VIDEO_AC97	0x14
+-
+-/* register settings */
+-#define EM2800_AUDIO_SRC_TUNER  0x0d
+-#define EM2800_AUDIO_SRC_LINE   0x0c
+-#define EM28XX_AUDIO_SRC_TUNER	0xc0
+-#define EM28XX_AUDIO_SRC_LINE	0x80
+-
+ /* printk macros */
+ 
+ #define em28xx_err(fmt, arg...) do {\
+@@ -456,80 +498,80 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
+ 	printk(KERN_WARNING "%s: "fmt,\
+ 			dev->name , ##arg); } while (0)
+ 
+-inline static int em28xx_compression_disable(struct em28xx *dev)
++static inline int em28xx_compression_disable(struct em28xx *dev)
+ {
+ 	/* side effect of disabling scaler and mixer */
+-	return em28xx_write_regs(dev, COMPR_REG, "\x00", 1);
++	return em28xx_write_regs(dev, EM28XX_R26_COMPR, "\x00", 1);
+ }
+ 
+-inline static int em28xx_contrast_get(struct em28xx *dev)
++static inline int em28xx_contrast_get(struct em28xx *dev)
+ {
+-	return em28xx_read_reg(dev, YGAIN_REG) & 0x1f;
++	return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f;
+ }
+ 
+-inline static int em28xx_brightness_get(struct em28xx *dev)
++static inline int em28xx_brightness_get(struct em28xx *dev)
+ {
+-	return em28xx_read_reg(dev, YOFFSET_REG);
++	return em28xx_read_reg(dev, EM28XX_R21_YOFFSET);
+ }
+ 
+-inline static int em28xx_saturation_get(struct em28xx *dev)
++static inline int em28xx_saturation_get(struct em28xx *dev)
+ {
+-	return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f;
++	return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f;
+ }
+ 
+-inline static int em28xx_u_balance_get(struct em28xx *dev)
++static inline int em28xx_u_balance_get(struct em28xx *dev)
+ {
+-	return em28xx_read_reg(dev, UOFFSET_REG);
++	return em28xx_read_reg(dev, EM28XX_R23_UOFFSET);
+ }
+ 
+-inline static int em28xx_v_balance_get(struct em28xx *dev)
++static inline int em28xx_v_balance_get(struct em28xx *dev)
+ {
+-	return em28xx_read_reg(dev, VOFFSET_REG);
++	return em28xx_read_reg(dev, EM28XX_R24_VOFFSET);
+ }
+ 
+-inline static int em28xx_gamma_get(struct em28xx *dev)
++static inline int em28xx_gamma_get(struct em28xx *dev)
+ {
+-	return em28xx_read_reg(dev, GAMMA_REG) & 0x3f;
++	return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f;
+ }
+ 
+-inline static int em28xx_contrast_set(struct em28xx *dev, s32 val)
++static inline int em28xx_contrast_set(struct em28xx *dev, s32 val)
+ {
+ 	u8 tmp = (u8) val;
+-	return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1);
++	return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1);
+ }
+ 
+-inline static int em28xx_brightness_set(struct em28xx *dev, s32 val)
++static inline int em28xx_brightness_set(struct em28xx *dev, s32 val)
+ {
+ 	u8 tmp = (u8) val;
+-	return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1);
++	return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1);
+ }
+ 
+-inline static int em28xx_saturation_set(struct em28xx *dev, s32 val)
++static inline int em28xx_saturation_set(struct em28xx *dev, s32 val)
+ {
+ 	u8 tmp = (u8) val;
+-	return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1);
++	return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1);
+ }
+ 
+-inline static int em28xx_u_balance_set(struct em28xx *dev, s32 val)
++static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val)
+ {
+ 	u8 tmp = (u8) val;
+-	return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1);
++	return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1);
+ }
+ 
+-inline static int em28xx_v_balance_set(struct em28xx *dev, s32 val)
++static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val)
+ {
+ 	u8 tmp = (u8) val;
+-	return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1);
++	return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1);
+ }
+ 
+-inline static int em28xx_gamma_set(struct em28xx *dev, s32 val)
++static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
+ {
+ 	u8 tmp = (u8) val;
+-	return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1);
++	return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1);
+ }
+ 
+ /*FIXME: maxw should be dependent of alt mode */
+-inline static unsigned int norm_maxw(struct em28xx *dev)
++static inline unsigned int norm_maxw(struct em28xx *dev)
+ {
+ 	if (dev->max_range_640_480)
+ 		return 640;
+@@ -537,7 +579,7 @@ inline static unsigned int norm_maxw(struct em28xx *dev)
+ 		return 720;
+ }
+ 
+-inline static unsigned int norm_maxh(struct em28xx *dev)
++static inline unsigned int norm_maxh(struct em28xx *dev)
+ {
+ 	if (dev->max_range_640_480)
+ 		return 480;
+diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h
+index 02c741d..cc77d14 100644
+--- a/drivers/media/video/et61x251/et61x251.h
++++ b/drivers/media/video/et61x251/et61x251.h
+@@ -199,7 +199,7 @@ do {                                                                          \
+ 			dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
+ 		else if ((level) >= 3)                                        \
+ 			dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",   \
+-				 __FILE__, __FUNCTION__, __LINE__ , ## args); \
++				 __FILE__, __func__, __LINE__ , ## args); \
+ 	}                                                                     \
+ } while (0)
+ #	define KDBG(level, fmt, args...)                                      \
+@@ -209,7 +209,7 @@ do {                                                                          \
+ 			pr_info("et61x251: " fmt "\n", ## args);              \
+ 		else if ((level) == 3)                                        \
+ 			pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__,   \
+-				 __FUNCTION__, __LINE__ , ## args);           \
++				 __func__, __LINE__ , ## args);           \
+ 	}                                                                     \
+ } while (0)
+ #	define V4LDBG(level, name, cmd)                                       \
+@@ -225,7 +225,7 @@ do {                                                                          \
+ 
+ #undef PDBG
+ #define PDBG(fmt, args...)                                                    \
+-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
++dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
+ 	 __LINE__ , ## args)
+ 
+ #undef PDBGG
+diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
+index 06b6a3a..5e749c5 100644
+--- a/drivers/media/video/et61x251/et61x251_core.c
++++ b/drivers/media/video/et61x251/et61x251_core.c
+@@ -2523,7 +2523,9 @@ static const struct file_operations et61x251_fops = {
+ 	.open =    et61x251_open,
+ 	.release = et61x251_release,
+ 	.ioctl =   et61x251_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.read =    et61x251_read,
+ 	.poll =    et61x251_poll,
+ 	.mmap =    et61x251_mmap,
+@@ -2538,7 +2540,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+ {
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	struct et61x251_device* cam;
+-	static unsigned int dev_nr = 0;
++	static unsigned int dev_nr;
+ 	unsigned int i;
+ 	int err = 0;
+ 
+diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
+index c7fed34..352f84d 100644
+--- a/drivers/media/video/hexium_gemini.c
++++ b/drivers/media/video/hexium_gemini.c
+@@ -25,12 +25,12 @@
+ 
+ #include <media/saa7146_vv.h>
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "debug verbosity");
+ 
+ /* global variables */
+-static int hexium_num = 0;
++static int hexium_num;
+ 
+ #define HEXIUM_GEMINI			4
+ #define HEXIUM_GEMINI_DUAL		5
+diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
+index 137c473..8d3c148 100644
+--- a/drivers/media/video/hexium_orion.c
++++ b/drivers/media/video/hexium_orion.c
+@@ -25,12 +25,12 @@
+ 
+ #include <media/saa7146_vv.h>
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "debug verbosity");
+ 
+ /* global variables */
+-static int hexium_num = 0;
++static int hexium_num;
+ 
+ #define HEXIUM_HV_PCI6_ORION		1
+ #define HEXIUM_ORION_1SVHS_3BNC		2
+diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
+index 9851987..7b65f5e 100644
+--- a/drivers/media/video/ir-kbd-i2c.c
++++ b/drivers/media/video/ir-kbd-i2c.c
+@@ -40,7 +40,6 @@
+ #include <linux/i2c.h>
+ #include <linux/i2c-id.h>
+ #include <linux/workqueue.h>
+-#include <asm/semaphore.h>
+ 
+ #include <media/ir-common.h>
+ #include <media/ir-kbd-i2c.h>
+@@ -51,7 +50,7 @@
+ static int debug;
+ module_param(debug, int, 0644);    /* debug level (0,1,2) */
+ 
+-static int hauppauge = 0;
++static int hauppauge;
+ module_param(hauppauge, int, 0644);    /* Choose Hauppauge remote */
+ MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)");
+ 
+@@ -154,7 +153,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+ 	}
+ 
+ 	if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0)
+-		dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__,
++		dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__,
+ 			buf[0], buf[1], buf[2], buf[3]);
+ 
+ 	/* no key pressed or signal from other ir remote */
+@@ -509,10 +508,13 @@ static int ir_probe(struct i2c_adapter *adap)
+ 	static const int probe_em28XX[] = { 0x30, 0x47, -1 };
+ 	static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
+ 	static const int probe_cx23885[] = { 0x6b, -1 };
+-	const int *probe = NULL;
+-	struct i2c_client c;
+-	unsigned char buf;
+-	int i,rc;
++	const int *probe;
++	struct i2c_msg msg = {
++		.flags = I2C_M_RD,
++		.len = 0,
++		.buf = NULL,
++	};
++	int i, rc;
+ 
+ 	switch (adap->id) {
+ 	case I2C_HW_B_BT848:
+@@ -533,20 +535,18 @@ static int ir_probe(struct i2c_adapter *adap)
+ 	case I2C_HW_B_CX23885:
+ 		probe = probe_cx23885;
+ 		break;
+-	}
+-	if (NULL == probe)
++	default:
+ 		return 0;
++	}
+ 
+-	memset(&c,0,sizeof(c));
+-	c.adapter = adap;
+ 	for (i = 0; -1 != probe[i]; i++) {
+-		c.addr = probe[i];
+-		rc = i2c_master_recv(&c,&buf,0);
++		msg.addr = probe[i];
++		rc = i2c_transfer(adap, &msg, 1);
+ 		dprintk(1,"probe 0x%02x @ %s: %s\n",
+ 			probe[i], adap->name,
+-			(0 == rc) ? "yes" : "no");
+-		if (0 == rc) {
+-			ir_attach(adap,probe[i],0,0);
++			(1 == rc) ? "yes" : "no");
++		if (1 == rc) {
++			ir_attach(adap, probe[i], 0, 0);
+ 			break;
+ 		}
+ 	}
+diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig
+index 270906f..b617170 100644
+--- a/drivers/media/video/ivtv/Kconfig
++++ b/drivers/media/video/ivtv/Kconfig
+@@ -10,6 +10,7 @@ config VIDEO_IVTV
+ 	select VIDEO_CX25840
+ 	select VIDEO_MSP3400
+ 	select VIDEO_SAA711X
++	select VIDEO_SAA717X
+ 	select VIDEO_SAA7127
+ 	select VIDEO_TVAUDIO
+ 	select VIDEO_CS53L32A
+diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c
+index f23c6b8..e908649 100644
+--- a/drivers/media/video/ivtv/ivtv-cards.c
++++ b/drivers/media/video/ivtv/ivtv-cards.c
+@@ -416,11 +416,10 @@ static const struct ivtv_card ivtv_card_avc2410 = {
+ 	   on the country/region setting of the user to decide which tuner
+ 	   is available. */
+ 	.tuners = {
+-		/* This tuner has been verified for the AVC2410 */
+ 		{ .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+-		/* This is a good guess, but I'm not totally sure this is
+-		   the correct tuner for NTSC. */
+-		{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
++		{ .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP,
++			.tuner = TUNER_PHILIPS_FM1236_MK3 },
++		{ .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 },
+ 	},
+ 	.pci_list = ivtv_pci_avc2410,
+ 	.i2c = &ivtv_i2c_std,
+diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
+index 191aafd..9186fa2 100644
+--- a/drivers/media/video/ivtv/ivtv-cards.h
++++ b/drivers/media/video/ivtv/ivtv-cards.h
+@@ -119,7 +119,7 @@
+ 
+ #define IVTV_CARD_MAX_VIDEO_INPUTS 6
+ #define IVTV_CARD_MAX_AUDIO_INPUTS 3
+-#define IVTV_CARD_MAX_TUNERS  	   2
++#define IVTV_CARD_MAX_TUNERS  	   3
+ 
+ /* SAA71XX HW inputs */
+ #define IVTV_SAA71XX_COMPOSITE0 0
+diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
+index 948ca35..065df53 100644
+--- a/drivers/media/video/ivtv/ivtv-driver.c
++++ b/drivers/media/video/ivtv/ivtv-driver.c
+@@ -101,7 +101,7 @@ static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+ static unsigned int cardtype_c = 1;
+ static unsigned int tuner_c = 1;
+ static unsigned int radio_c = 1;
+-static char pal[] = "--";
++static char pal[] = "---";
+ static char secam[] = "--";
+ static char ntsc[] = "-";
+ 
+@@ -126,12 +126,13 @@ static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS;
+ static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS;
+ static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS;
+ 
+-static int ivtv_yuv_mode = 0;
+-static int ivtv_yuv_threshold=-1;
++static int ivtv_yuv_mode;
++static int ivtv_yuv_threshold = -1;
+ static int ivtv_pci_latency = 1;
+ 
+-int ivtv_debug = 0;
++int ivtv_debug;
+ 
++static int tunertype = -1;
+ static int newi2c = -1;
+ 
+ module_param_array(tuner, int, &tuner_c, 0644);
+@@ -154,6 +155,7 @@ module_param(dec_mpg_buffers, int, 0644);
+ module_param(dec_yuv_buffers, int, 0644);
+ module_param(dec_vbi_buffers, int, 0644);
+ 
++module_param(tunertype, int, 0644);
+ module_param(newi2c, int, 0644);
+ 
+ MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
+@@ -190,9 +192,14 @@ MODULE_PARM_DESC(cardtype,
+ 		 "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
+ 		 "\t\t\t 0 = Autodetect (default)\n"
+ 		 "\t\t\t-1 = Ignore this card\n\t\t");
+-MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
+-MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC");
+-MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K");
++MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60");
++MODULE_PARM_DESC(secam, "Set SECAM standard: BGH, DK, L, LC");
++MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J (Japan), K (South Korea)");
++MODULE_PARM_DESC(tunertype,
++		"Specify tuner type:\n"
++		"\t\t\t 0 = tuner for PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc\n"
++		"\t\t\t 1 = tuner for NTSC-M/J/K, PAL-M/N/Nc\n"
++		"\t\t\t-1 = Autodetect (default)\n");
+ MODULE_PARM_DESC(debug,
+ 		 "Debug level (bitmask). Default: 0\n"
+ 		 "\t\t\t   1/0x0001: warning\n"
+@@ -490,30 +497,35 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
+ {
+ 	switch (pal[0]) {
+ 		case '6':
++			tunertype = 0;
+ 			return V4L2_STD_PAL_60;
+ 		case 'b':
+ 		case 'B':
+ 		case 'g':
+ 		case 'G':
+-			return V4L2_STD_PAL_BG;
+ 		case 'h':
+ 		case 'H':
+-			return V4L2_STD_PAL_H;
++			tunertype = 0;
++			return V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+ 		case 'n':
+ 		case 'N':
++			tunertype = 1;
+ 			if (pal[1] == 'c' || pal[1] == 'C')
+ 				return V4L2_STD_PAL_Nc;
+ 			return V4L2_STD_PAL_N;
+ 		case 'i':
+ 		case 'I':
++			tunertype = 0;
+ 			return V4L2_STD_PAL_I;
+ 		case 'd':
+ 		case 'D':
+ 		case 'k':
+ 		case 'K':
++			tunertype = 0;
+ 			return V4L2_STD_PAL_DK;
+ 		case 'M':
+ 		case 'm':
++			tunertype = 1;
+ 			return V4L2_STD_PAL_M;
+ 		case '-':
+ 			break;
+@@ -529,14 +541,17 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
+ 		case 'G':
+ 		case 'h':
+ 		case 'H':
++			tunertype = 0;
+ 			return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+ 		case 'd':
+ 		case 'D':
+ 		case 'k':
+ 		case 'K':
++			tunertype = 0;
+ 			return V4L2_STD_SECAM_DK;
+ 		case 'l':
+ 		case 'L':
++			tunertype = 0;
+ 			if (secam[1] == 'C' || secam[1] == 'c')
+ 				return V4L2_STD_SECAM_LC;
+ 			return V4L2_STD_SECAM_L;
+@@ -550,12 +565,15 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
+ 	switch (ntsc[0]) {
+ 		case 'm':
+ 		case 'M':
++			tunertype = 1;
+ 			return V4L2_STD_NTSC_M;
+ 		case 'j':
+ 		case 'J':
++			tunertype = 1;
+ 			return V4L2_STD_NTSC_M_JP;
+ 		case 'k':
+ 		case 'K':
++			tunertype = 1;
+ 			return V4L2_STD_NTSC_M_KR;
+ 		case '-':
+ 			break;
+@@ -584,8 +602,13 @@ static void ivtv_process_options(struct ivtv *itv)
+ 	itv->options.tuner = tuner[itv->num];
+ 	itv->options.radio = radio[itv->num];
+ 	itv->options.newi2c = newi2c;
+-
++	if (tunertype < -1 || tunertype > 1) {
++		IVTV_WARN("Invalid tunertype argument, will autodetect instead\n");
++		tunertype = -1;
++	}
+ 	itv->std = ivtv_parse_std(itv);
++	if (itv->std == 0 && tunertype >= 0)
++		itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN);
+ 	itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15);
+ 	chipname = itv->has_cx23415 ? "cx23415" : "cx23416";
+ 	if (itv->options.cardtype == -1) {
+@@ -711,6 +734,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
+ 	itv->yuv_info.lace_mode = ivtv_yuv_mode;
+ 	itv->yuv_info.lace_threshold = ivtv_yuv_threshold;
+ 	itv->yuv_info.max_frames_buffered = 3;
++	itv->yuv_info.track_osd = 1;
+ 	return 0;
+ }
+ 
+@@ -859,7 +883,9 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
+ #ifndef CONFIG_VIDEO_SAA7127
+ 	hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127);
+ #endif
++#ifndef CONFIG_VIDEO_SAA717X
+ 	hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X);
++#endif
+ #ifndef CONFIG_VIDEO_UPD64031A
+ 	hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A);
+ #endif
+diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
+index 536140f..ba06e81 100644
+--- a/drivers/media/video/ivtv/ivtv-driver.h
++++ b/drivers/media/video/ivtv/ivtv-driver.h
+@@ -456,6 +456,8 @@ struct yuv_playback_info
+ 	int v_filter_2;
+ 	int h_filter;
+ 
++	u8 track_osd; /* Should yuv output track the OSD size & position */
++
+ 	u32 osd_x_offset;
+ 	u32 osd_y_offset;
+ 
+diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
+index 6fb96f1..a7640c4 100644
+--- a/drivers/media/video/ivtv/ivtv-fileops.c
++++ b/drivers/media/video/ivtv/ivtv-fileops.c
+@@ -219,7 +219,9 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
+ 			/* Process pending program info updates and pending VBI data */
+ 			ivtv_update_pgm_info(itv);
+ 
+-			if (jiffies - itv->dualwatch_jiffies > msecs_to_jiffies(1000)) {
++			if (time_after(jiffies,
++				       itv->dualwatch_jiffies +
++				       msecs_to_jiffies(1000))) {
+ 				itv->dualwatch_jiffies = jiffies;
+ 				ivtv_dualwatch(itv);
+ 			}
+@@ -753,7 +755,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
+ 	IVTV_DEBUG_HI_FILE("Encoder poll\n");
+ 	poll_wait(filp, &s->waitq, wait);
+ 
+-	if (eof || s->q_full.length)
++	if (eof || s->q_full.length || s->q_io.length)
+ 		return POLLIN | POLLRDNORM;
+ 	return 0;
+ }
+diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
+index fa5ab1e..9824eaf 100644
+--- a/drivers/media/video/ivtv/ivtv-i2c.c
++++ b/drivers/media/video/ivtv/ivtv-i2c.c
+@@ -177,10 +177,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
+ 	}
+ 
+ 	if (id != I2C_DRIVERID_TUNER) {
+-		c = i2c_new_device(&itv->i2c_adap, &info);
+-		if (c->driver == NULL)
++		if (id == I2C_DRIVERID_UPD64031A ||
++		    id == I2C_DRIVERID_UPD64083) {
++			unsigned short addrs[2] = { info.addr, I2C_CLIENT_END };
++
++			c = i2c_new_probed_device(&itv->i2c_adap, &info, addrs);
++		} else
++			c = i2c_new_device(&itv->i2c_adap, &info);
++		if (c && c->driver == NULL)
+ 			i2c_unregister_device(c);
+-		else
++		else if (c)
+ 			itv->i2c_clients[i] = c;
+ 		return itv->i2c_clients[i] ? 0 : -ENODEV;
+ 	}
+diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
+index edef2a5..15cac18 100644
+--- a/drivers/media/video/ivtv/ivtv-ioctl.c
++++ b/drivers/media/video/ivtv/ivtv-ioctl.c
+@@ -712,6 +712,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
+ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
+ {
+ 	struct ivtv_open_id *id = NULL;
++	struct yuv_playback_info *yi = &itv->yuv_info;
+ 	u32 data[CX2341X_MBOX_MAX_DATA];
+ 	int streamtype = 0;
+ 
+@@ -741,7 +742,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ 
+ 		memset(vcap, 0, sizeof(*vcap));
+ 		strcpy(vcap->driver, IVTV_DRIVER_NAME);     /* driver name */
+-		strcpy(vcap->card, itv->card_name); 	    /* card type */
++		strncpy(vcap->card, itv->card_name,
++				sizeof(vcap->card)-1); 	    /* card type */
+ 		strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
+ 		vcap->version = IVTV_DRIVER_VERSION; 	    /* version */
+ 		vcap->capabilities = itv->v4l2_cap; 	    /* capabilities */
+@@ -827,8 +829,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ 	case VIDIOC_CROPCAP: {
+ 		struct v4l2_cropcap *cropcap = arg;
+ 
+-		if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+-		    cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++		if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ 			return -EINVAL;
+ 		cropcap->bounds.top = cropcap->bounds.left = 0;
+ 		cropcap->bounds.width = 720;
+@@ -837,8 +838,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ 			cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
+ 			cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
+ 		} else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+-			cropcap->bounds.width = itv->yuv_info.osd_full_w;
+-			cropcap->bounds.height = itv->yuv_info.osd_full_h;
++			if (yi->track_osd) {
++				cropcap->bounds.width = yi->osd_full_w;
++				cropcap->bounds.height = yi->osd_full_h;
++			} else {
++				cropcap->bounds.width = 720;
++				cropcap->bounds.height =
++						itv->is_out_50hz ? 576 : 480;
++			}
+ 			cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
+ 			cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
+ 		} else {
+@@ -856,7 +863,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ 		if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ 		    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+ 			if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+-				itv->yuv_info.main_rect = crop->c;
++				yi->main_rect = crop->c;
+ 				return 0;
+ 			} else {
+ 				if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+@@ -867,9 +874,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ 			}
+ 			return -EINVAL;
+ 		}
+-		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-			return -EINVAL;
+-		return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
++		return -EINVAL;
+ 	}
+ 
+ 	case VIDIOC_G_CROP: {
+@@ -878,14 +883,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ 		if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ 		    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+ 			if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
+-				crop->c = itv->yuv_info.main_rect;
++				crop->c = yi->main_rect;
+ 			else
+ 				crop->c = itv->main_rect;
+ 			return 0;
+ 		}
+-		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-			return -EINVAL;
+-		return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
++		return -EINVAL;
+ 	}
+ 
+ 	case VIDIOC_ENUM_FMT: {
+@@ -1070,11 +1073,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ 			itv->main_rect.height = itv->params.height;
+ 			ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+ 				720, itv->main_rect.height, 0, 0);
+-			itv->yuv_info.main_rect = itv->main_rect;
++			yi->main_rect = itv->main_rect;
+ 			if (!itv->osd_info) {
+-				itv->yuv_info.osd_full_w = 720;
+-				itv->yuv_info.osd_full_h =
+-						itv->is_out_50hz ? 576 : 480;
++				yi->osd_full_w = 720;
++				yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
+ 			}
+ 		}
+ 		break;
+@@ -1272,6 +1274,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ 			else
+ 				fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+ 		}
++		if (yi->track_osd)
++			fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
+ 		break;
+ 	}
+ 
+@@ -1285,6 +1289,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ 			(fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
+ 		itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
+ 		ivtv_set_osd_alpha(itv);
++		yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
+ 		break;
+ 	}
+ 
+@@ -1628,6 +1633,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+ 		if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
+ 			printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
+ 			v4l_printk_ioctl(cmd);
++			printk("\n");
+ 		}
+ 		return ivtv_debug_ioctls(filp, cmd, arg);
+ 
+@@ -1671,6 +1677,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+ 		if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
+ 			printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
+ 			v4l_printk_ioctl(cmd);
++			printk("\n");
+ 		}
+ 		return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
+ 
+@@ -1684,6 +1691,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+ 		if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
+ 			printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
+ 			v4l_printk_ioctl(cmd);
++			printk("\n");
+ 		}
+ 		return ivtv_control_ioctls(itv, cmd, arg);
+ 
+diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
+index 65604dd..a329c46 100644
+--- a/drivers/media/video/ivtv/ivtv-irq.c
++++ b/drivers/media/video/ivtv/ivtv-irq.c
+@@ -384,6 +384,8 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
+ 	ivtv_stream_sync_for_device(s);
+ 	write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR);
+ 	write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
++	itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
++	add_timer(&itv->dma_timer);
+ }
+ 
+ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
+@@ -398,6 +400,8 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
+ 	ivtv_stream_sync_for_device(s);
+ 	write_reg(s->sg_handle, IVTV_REG_DECDMAADDR);
+ 	write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
++	itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
++	add_timer(&itv->dma_timer);
+ }
+ 
+ /* start the encoder DMA */
+@@ -459,8 +463,6 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
+ 		ivtv_dma_enc_start_xfer(s);
+ 		set_bit(IVTV_F_I_DMA, &itv->i_flags);
+ 		itv->cur_dma_stream = s->type;
+-		itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+-		add_timer(&itv->dma_timer);
+ 	}
+ }
+ 
+@@ -481,8 +483,6 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s)
+ 	ivtv_dma_dec_start_xfer(s);
+ 	set_bit(IVTV_F_I_DMA, &itv->i_flags);
+ 	itv->cur_dma_stream = s->type;
+-	itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+-	add_timer(&itv->dma_timer);
+ }
+ 
+ static void ivtv_irq_dma_read(struct ivtv *itv)
+@@ -492,10 +492,11 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
+ 	int hw_stream_type = 0;
+ 
+ 	IVTV_DEBUG_HI_IRQ("DEC DMA READ\n");
+-	if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) {
+-		del_timer(&itv->dma_timer);
++
++	del_timer(&itv->dma_timer);
++
++	if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0)
+ 		return;
+-	}
+ 
+ 	if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
+ 		s = &itv->streams[itv->cur_dma_stream];
+@@ -543,7 +544,6 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
+ 		}
+ 		wake_up(&s->waitq);
+ 	}
+-	del_timer(&itv->dma_timer);
+ 	clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
+ 	clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+ 	itv->cur_dma_stream = -1;
+@@ -557,10 +557,12 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
+ 
+ 	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data);
+ 	IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
+-	if (itv->cur_dma_stream < 0) {
+-		del_timer(&itv->dma_timer);
++
++	del_timer(&itv->dma_timer);
++
++	if (itv->cur_dma_stream < 0)
+ 		return;
+-	}
++
+ 	s = &itv->streams[itv->cur_dma_stream];
+ 	ivtv_stream_sync_for_cpu(s);
+ 
+@@ -585,7 +587,6 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
+ 		ivtv_dma_enc_start_xfer(s);
+ 		return;
+ 	}
+-	del_timer(&itv->dma_timer);
+ 	clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+ 	itv->cur_dma_stream = -1;
+ 	dma_post(s);
+diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c
+index 13a6c37..1b5c0ac 100644
+--- a/drivers/media/video/ivtv/ivtv-mailbox.c
++++ b/drivers/media/video/ivtv/ivtv-mailbox.c
+@@ -177,7 +177,8 @@ static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int f
+ 
+ 		/* Sleep before a retry, if not atomic */
+ 		if (!(flags & API_NO_WAIT_MB)) {
+-			if (jiffies - then > msecs_to_jiffies(10*retries))
++			if (time_after(jiffies,
++				       then + msecs_to_jiffies(10*retries)))
+ 			       break;
+ 			ivtv_msleep_timeout(10, 0);
+ 		}
+@@ -244,7 +245,9 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
+ 	   data, then just return 0 as there is no need to issue this command again.
+ 	   Just an optimization to prevent unnecessary use of mailboxes. */
+ 	if (itv->api_cache[cmd].last_jiffies &&
+-	    jiffies - itv->api_cache[cmd].last_jiffies < msecs_to_jiffies(1800000) &&
++	    time_before(jiffies,
++			itv->api_cache[cmd].last_jiffies +
++			msecs_to_jiffies(1800000)) &&
+ 	    !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) {
+ 		itv->api_cache[cmd].last_jiffies = jiffies;
+ 		return 0;
+@@ -299,7 +302,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
+ 		}
+ 	}
+ 	while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
+-		if (jiffies - then > api_timeout) {
++		if (time_after(jiffies, then + api_timeout)) {
+ 			IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name);
+ 			/* reset the mailbox, but it is likely too late already */
+ 			write_sync(0, &mbox->flags);
+@@ -311,7 +314,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
+ 		else
+ 			ivtv_msleep_timeout(1, 0);
+ 	}
+-	if (jiffies - then > msecs_to_jiffies(100))
++	if (time_after(jiffies, then + msecs_to_jiffies(100)))
+ 		IVTV_DEBUG_WARN("%s took %u jiffies\n",
+ 				api_info[cmd].name,
+ 				jiffies_to_msecs(jiffies - then));
+diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c
+index 39a2167..3e1deec 100644
+--- a/drivers/media/video/ivtv/ivtv-queue.c
++++ b/drivers/media/video/ivtv/ivtv-queue.c
+@@ -51,7 +51,7 @@ void ivtv_queue_init(struct ivtv_queue *q)
+ 
+ void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q)
+ {
+-	unsigned long flags = 0;
++	unsigned long flags;
+ 
+ 	/* clear the buffer if it is going to be enqueued to the free queue */
+ 	if (q == &s->q_free) {
+@@ -71,7 +71,7 @@ void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_qu
+ struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q)
+ {
+ 	struct ivtv_buffer *buf = NULL;
+-	unsigned long flags = 0;
++	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&s->qlock, flags);
+ 	if (!list_empty(&q->list)) {
+diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
+index 24d98ec..4ab8d36 100644
+--- a/drivers/media/video/ivtv/ivtv-streams.c
++++ b/drivers/media/video/ivtv/ivtv-streams.c
+@@ -768,7 +768,8 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
+ 
+ 			/* wait 2s for EOS interrupt */
+ 			while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
+-				jiffies < then + msecs_to_jiffies (2000)) {
++				time_before(jiffies,
++					    then + msecs_to_jiffies(2000))) {
+ 				schedule_timeout(msecs_to_jiffies(10));
+ 			}
+ 
+diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
+index 8518348..393d917 100644
+--- a/drivers/media/video/ivtv/ivtv-yuv.c
++++ b/drivers/media/video/ivtv/ivtv-yuv.c
+@@ -718,9 +718,11 @@ static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
+ 		f->src_w -= (osd_scale * osd_crop) >> 16;
+ 	}
+ 
+-	/* The OSD can be moved. Track to it */
+-	f->dst_x += itv->yuv_info.osd_x_offset;
+-	f->dst_y += itv->yuv_info.osd_y_offset;
++	if (itv->yuv_info.track_osd) {
++		/* The OSD can be moved. Track to it */
++		f->dst_x += itv->yuv_info.osd_x_offset;
++		f->dst_y += itv->yuv_info.osd_y_offset;
++	}
+ 
+ 	/* Width & height for both src & dst must be even.
+ 	   Same for coordinates. */
+@@ -792,11 +794,19 @@ void ivtv_yuv_work_handler(struct ivtv *itv)
+ 	IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
+ 	f = yi->new_frame_info[frame];
+ 
+-	/* Update the osd pan info */
+-	f.pan_x = yi->osd_x_pan;
+-	f.pan_y = yi->osd_y_pan;
+-	f.vis_w = yi->osd_vis_w;
+-	f.vis_h = yi->osd_vis_h;
++	if (yi->track_osd) {
++		/* Snapshot the osd pan info */
++		f.pan_x = yi->osd_x_pan;
++		f.pan_y = yi->osd_y_pan;
++		f.vis_w = yi->osd_vis_w;
++		f.vis_h = yi->osd_vis_h;
++	} else {
++		/* Not tracking the osd, so assume full screen */
++		f.pan_x = 0;
++		f.pan_y = 0;
++		f.vis_w = 720;
++		f.vis_h = yi->decode_height;
++	}
+ 
+ 	/* Calculate the display window coordinates. Exit if nothing left */
+ 	if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
+@@ -914,7 +924,7 @@ static void ivtv_yuv_init(struct ivtv *itv)
+ }
+ 
+ /* Get next available yuv buffer on PVR350 */
+-void ivtv_yuv_next_free(struct ivtv *itv)
++static void ivtv_yuv_next_free(struct ivtv *itv)
+ {
+ 	int draw, display;
+ 	struct yuv_playback_info *yi = &itv->yuv_info;
+@@ -937,7 +947,7 @@ void ivtv_yuv_next_free(struct ivtv *itv)
+ }
+ 
+ /* Set up frame according to ivtv_dma_frame parameters */
+-void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
++static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+ {
+ 	struct yuv_playback_info *yi = &itv->yuv_info;
+ 	u8 frame = yi->draw_frame;
+@@ -965,12 +975,6 @@ void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+ 	/* Are we going to offset the Y plane */
+ 	nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
+ 
+-	/* Snapshot the osd pan info */
+-	nf->pan_x = yi->osd_x_pan;
+-	nf->pan_y = yi->osd_y_pan;
+-	nf->vis_w = yi->osd_vis_w;
+-	nf->vis_h = yi->osd_vis_h;
+-
+ 	nf->update = 0;
+ 	nf->interlaced_y = 0;
+ 	nf->interlaced_uv = 0;
+@@ -1042,7 +1046,7 @@ void ivtv_yuv_frame_complete(struct ivtv *itv)
+ 			(itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
+ }
+ 
+-int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
++static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+ {
+ 	DEFINE_WAIT(wait);
+ 	int rc = 0;
+diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
+index 3d51fa0..e7ccbc8 100644
+--- a/drivers/media/video/meye.c
++++ b/drivers/media/video/meye.c
+@@ -42,15 +42,10 @@
+ #include <linux/meye.h>
+ 
+ MODULE_AUTHOR("Stelian Pop <stelian at popies.net>");
+-MODULE_DESCRIPTION("v4l/v4l2 driver for the MotionEye camera");
++MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(MEYE_DRIVER_VERSION);
+ 
+-/* force usage of V4L1 API */
+-static int forcev4l1; /* = 0 */
+-module_param(forcev4l1, int, 0644);
+-MODULE_PARM_DESC(forcev4l1, "force use of V4L1 instead of V4L2");
+-
+ /* number of grab buffers */
+ static unsigned int gbuffers = 2;
+ module_param(gbuffers, int, 0444);
+@@ -789,7 +784,7 @@ static irqreturn_t meye_irq(int irq, void *dev_id)
+ {
+ 	u32 v;
+ 	int reqnr;
+-	static int sequence = 0;
++	static int sequence;
+ 
+ 	v = mchip_read(MCHIP_MM_INTA);
+ 
+@@ -876,795 +871,735 @@ static int meye_release(struct inode *inode, struct file *file)
+ 	return 0;
+ }
+ 
+-static int meye_do_ioctl(struct inode *inode, struct file *file,
+-			 unsigned int cmd, void *arg)
++static int meyeioc_g_params(struct meye_params *p)
+ {
+-	switch (cmd) {
++	*p = meye.params;
++	return 0;
++}
+ 
+-	case VIDIOCGCAP: {
+-		struct video_capability *b = arg;
+-		strcpy(b->name,meye.video_dev->name);
+-		b->type = VID_TYPE_CAPTURE;
+-		b->channels = 1;
+-		b->audios = 0;
+-		b->maxwidth = 640;
+-		b->maxheight = 480;
+-		b->minwidth = 320;
+-		b->minheight = 240;
+-		break;
+-	}
++static int meyeioc_s_params(struct meye_params *jp)
++{
++	if (jp->subsample > 1)
++		return -EINVAL;
+ 
+-	case VIDIOCGCHAN: {
+-		struct video_channel *v = arg;
+-		v->flags = 0;
+-		v->tuners = 0;
+-		v->type = VIDEO_TYPE_CAMERA;
+-		if (v->channel != 0)
+-			return -EINVAL;
+-		strcpy(v->name,"Camera");
+-		break;
+-	}
++	if (jp->quality > 10)
++		return -EINVAL;
+ 
+-	case VIDIOCSCHAN: {
+-		struct video_channel *v = arg;
+-		if (v->channel != 0)
+-			return -EINVAL;
+-		break;
+-	}
++	if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
++		return -EINVAL;
+ 
+-	case VIDIOCGPICT: {
+-		struct video_picture *p = arg;
+-		*p = meye.picture;
+-		break;
+-	}
++	if (jp->framerate > 31)
++		return -EINVAL;
+ 
+-	case VIDIOCSPICT: {
+-		struct video_picture *p = arg;
+-		if (p->depth != 16)
+-			return -EINVAL;
+-		if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV)
+-			return -EINVAL;
+-		mutex_lock(&meye.lock);
+-		sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS,
+-				      p->brightness >> 10);
+-		sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE,
+-				      p->hue >> 10);
+-		sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR,
+-				      p->colour >> 10);
+-		sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST,
+-				      p->contrast >> 10);
+-		meye.picture = *p;
+-		mutex_unlock(&meye.lock);
+-		break;
+-	}
++	mutex_lock(&meye.lock);
+ 
+-	case VIDIOCSYNC: {
+-		int *i = arg;
+-		int unused;
++	if (meye.params.subsample != jp->subsample ||
++	    meye.params.quality != jp->quality)
++		mchip_hic_stop();	/* need restart */
++
++	meye.params = *jp;
++	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
++			      meye.params.sharpness);
++	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
++			      meye.params.agc);
++	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
++			      meye.params.picture);
++	mutex_unlock(&meye.lock);
+ 
+-		if (*i < 0 || *i >= gbuffers)
+-			return -EINVAL;
++	return 0;
++}
+ 
+-		mutex_lock(&meye.lock);
++static int meyeioc_qbuf_capt(int *nb)
++{
++	if (!meye.grab_fbuffer)
++		return -EINVAL;
+ 
+-		switch (meye.grab_buffer[*i].state) {
++	if (*nb >= gbuffers)
++		return -EINVAL;
+ 
+-		case MEYE_BUF_UNUSED:
+-			mutex_unlock(&meye.lock);
+-			return -EINVAL;
+-		case MEYE_BUF_USING:
+-			if (file->f_flags & O_NONBLOCK) {
+-				mutex_unlock(&meye.lock);
+-				return -EAGAIN;
+-			}
+-			if (wait_event_interruptible(meye.proc_list,
+-						     (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
+-				mutex_unlock(&meye.lock);
+-				return -EINTR;
+-			}
+-			/* fall through */
+-		case MEYE_BUF_DONE:
+-			meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
+-			kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
+-		}
+-		mutex_unlock(&meye.lock);
+-		break;
++	if (*nb < 0) {
++		/* stop capture */
++		mchip_hic_stop();
++		return 0;
+ 	}
+ 
+-	case VIDIOCMCAPTURE: {
+-		struct video_mmap *vm = arg;
+-		int restart = 0;
+-
+-		if (vm->frame >= gbuffers || vm->frame < 0)
+-			return -EINVAL;
+-		if (vm->format != VIDEO_PALETTE_YUV422 && vm->format != VIDEO_PALETTE_YUYV)
+-			return -EINVAL;
+-		if (vm->height * vm->width * 2 > gbufsize)
+-			return -EINVAL;
+-		if (!meye.grab_fbuffer)
+-			return -EINVAL;
+-		if (meye.grab_buffer[vm->frame].state != MEYE_BUF_UNUSED)
+-			return -EBUSY;
+-
+-		mutex_lock(&meye.lock);
+-		if (vm->width == 640 && vm->height == 480) {
+-			if (meye.params.subsample) {
+-				meye.params.subsample = 0;
+-				restart = 1;
+-			}
+-		} else if (vm->width == 320 && vm->height == 240) {
+-			if (!meye.params.subsample) {
+-				meye.params.subsample = 1;
+-				restart = 1;
+-			}
+-		} else {
+-			mutex_unlock(&meye.lock);
+-			return -EINVAL;
+-		}
++	if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
++		return -EBUSY;
+ 
+-		if (restart || meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT)
+-			mchip_continuous_start();
+-		meye.grab_buffer[vm->frame].state = MEYE_BUF_USING;
+-		kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int));
+-		mutex_unlock(&meye.lock);
+-		break;
+-	}
++	mutex_lock(&meye.lock);
+ 
+-	case VIDIOCGMBUF: {
+-		struct video_mbuf *vm = arg;
+-		int i;
++	if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
++		mchip_cont_compression_start();
+ 
+-		memset(vm, 0 , sizeof(*vm));
+-		vm->size = gbufsize * gbuffers;
+-		vm->frames = gbuffers;
+-		for (i = 0; i < gbuffers; i++)
+-			vm->offsets[i] = i * gbufsize;
+-		break;
+-	}
++	meye.grab_buffer[*nb].state = MEYE_BUF_USING;
++	kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
++	mutex_unlock(&meye.lock);
+ 
+-	case MEYEIOC_G_PARAMS: {
+-		struct meye_params *p = arg;
+-		*p = meye.params;
+-		break;
+-	}
++	return 0;
++}
+ 
+-	case MEYEIOC_S_PARAMS: {
+-		struct meye_params *jp = arg;
+-		if (jp->subsample > 1)
+-			return -EINVAL;
+-		if (jp->quality > 10)
+-			return -EINVAL;
+-		if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
+-			return -EINVAL;
+-		if (jp->framerate > 31)
+-			return -EINVAL;
+-		mutex_lock(&meye.lock);
+-		if (meye.params.subsample != jp->subsample ||
+-		    meye.params.quality != jp->quality)
+-			mchip_hic_stop();	/* need restart */
+-		meye.params = *jp;
+-		sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
+-				      meye.params.sharpness);
+-		sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
+-				      meye.params.agc);
+-		sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
+-				      meye.params.picture);
+-		mutex_unlock(&meye.lock);
+-		break;
+-	}
++static int meyeioc_sync(struct file *file, void *fh, int *i)
++{
++	int unused;
+ 
+-	case MEYEIOC_QBUF_CAPT: {
+-		int *nb = arg;
+-
+-		if (!meye.grab_fbuffer)
+-			return -EINVAL;
+-		if (*nb >= gbuffers)
+-			return -EINVAL;
+-		if (*nb < 0) {
+-			/* stop capture */
+-			mchip_hic_stop();
+-			return 0;
+-		}
+-		if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
+-			return -EBUSY;
+-		mutex_lock(&meye.lock);
+-		if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
+-			mchip_cont_compression_start();
+-		meye.grab_buffer[*nb].state = MEYE_BUF_USING;
+-		kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
++	if (*i < 0 || *i >= gbuffers)
++		return -EINVAL;
++
++	mutex_lock(&meye.lock);
++	switch (meye.grab_buffer[*i].state) {
++
++	case MEYE_BUF_UNUSED:
+ 		mutex_unlock(&meye.lock);
+-		break;
++		return -EINVAL;
++	case MEYE_BUF_USING:
++		if (file->f_flags & O_NONBLOCK) {
++			mutex_unlock(&meye.lock);
++			return -EAGAIN;
++		}
++		if (wait_event_interruptible(meye.proc_list,
++			(meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
++			mutex_unlock(&meye.lock);
++			return -EINTR;
++		}
++		/* fall through */
++	case MEYE_BUF_DONE:
++		meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
++		kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
+ 	}
++	*i = meye.grab_buffer[*i].size;
++	mutex_unlock(&meye.lock);
++	return 0;
++}
+ 
+-	case MEYEIOC_SYNC: {
+-		int *i = arg;
+-		int unused;
++static int meyeioc_stillcapt(void)
++{
++	if (!meye.grab_fbuffer)
++		return -EINVAL;
+ 
+-		if (*i < 0 || *i >= gbuffers)
+-			return -EINVAL;
++	if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
++		return -EBUSY;
+ 
+-		mutex_lock(&meye.lock);
+-		switch (meye.grab_buffer[*i].state) {
++	mutex_lock(&meye.lock);
++	meye.grab_buffer[0].state = MEYE_BUF_USING;
++	mchip_take_picture();
+ 
+-		case MEYE_BUF_UNUSED:
+-			mutex_unlock(&meye.lock);
+-			return -EINVAL;
+-		case MEYE_BUF_USING:
+-			if (file->f_flags & O_NONBLOCK) {
+-				mutex_unlock(&meye.lock);
+-				return -EAGAIN;
+-			}
+-			if (wait_event_interruptible(meye.proc_list,
+-						     (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
+-				mutex_unlock(&meye.lock);
+-				return -EINTR;
+-			}
+-			/* fall through */
+-		case MEYE_BUF_DONE:
+-			meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
+-			kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
+-		}
+-		*i = meye.grab_buffer[*i].size;
+-		mutex_unlock(&meye.lock);
+-		break;
+-	}
++	mchip_get_picture(meye.grab_fbuffer,
++			mchip_hsize() * mchip_vsize() * 2);
+ 
+-	case MEYEIOC_STILLCAPT: {
++	meye.grab_buffer[0].state = MEYE_BUF_DONE;
++	mutex_unlock(&meye.lock);
+ 
+-		if (!meye.grab_fbuffer)
+-			return -EINVAL;
+-		if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+-			return -EBUSY;
+-		mutex_lock(&meye.lock);
+-		meye.grab_buffer[0].state = MEYE_BUF_USING;
++	return 0;
++}
++
++static int meyeioc_stilljcapt(int *len)
++{
++	if (!meye.grab_fbuffer)
++		return -EINVAL;
++
++	if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
++		return -EBUSY;
++
++	mutex_lock(&meye.lock);
++	meye.grab_buffer[0].state = MEYE_BUF_USING;
++	*len = -1;
++
++	while (*len == -1) {
+ 		mchip_take_picture();
+-		mchip_get_picture(
+-			meye.grab_fbuffer,
+-			mchip_hsize() * mchip_vsize() * 2);
+-		meye.grab_buffer[0].state = MEYE_BUF_DONE;
+-		mutex_unlock(&meye.lock);
+-		break;
++		*len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
+ 	}
+ 
+-	case MEYEIOC_STILLJCAPT: {
+-		int *len = arg;
+-
+-		if (!meye.grab_fbuffer)
+-			return -EINVAL;
+-		if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+-			return -EBUSY;
+-		mutex_lock(&meye.lock);
+-		meye.grab_buffer[0].state = MEYE_BUF_USING;
+-		*len = -1;
+-		while (*len == -1) {
+-			mchip_take_picture();
+-			*len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
+-		}
+-		meye.grab_buffer[0].state = MEYE_BUF_DONE;
+-		mutex_unlock(&meye.lock);
+-		break;
+-	}
++	meye.grab_buffer[0].state = MEYE_BUF_DONE;
++	mutex_unlock(&meye.lock);
++	return 0;
++}
+ 
+-	case VIDIOC_QUERYCAP: {
+-		struct v4l2_capability *cap = arg;
++static int vidioc_querycap(struct file *file, void *fh,
++				struct v4l2_capability *cap)
++{
++	memset(cap, 0, sizeof(*cap));
++	strcpy(cap->driver, "meye");
++	strcpy(cap->card, "meye");
++	sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
+ 
+-		if (forcev4l1)
+-			return -EINVAL;
++	cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
++		       MEYE_DRIVER_MINORVERSION;
+ 
+-		memset(cap, 0, sizeof(*cap));
+-		strcpy(cap->driver, "meye");
+-		strcpy(cap->card, "meye");
+-		sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
+-		cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
+-			       MEYE_DRIVER_MINORVERSION;
+-		cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+-				    V4L2_CAP_STREAMING;
+-		break;
+-	}
++	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
++			    V4L2_CAP_STREAMING;
++
++	return 0;
++}
++
++static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
++{
++	if (i->index != 0)
++		return -EINVAL;
+ 
+-	case VIDIOC_ENUMINPUT: {
+-		struct v4l2_input *i = arg;
++	memset(i, 0, sizeof(*i));
++	i->index = 0;
++	strcpy(i->name, "Camera");
++	i->type = V4L2_INPUT_TYPE_CAMERA;
+ 
+-		if (i->index != 0)
+-			return -EINVAL;
+-		memset(i, 0, sizeof(*i));
+-		i->index = 0;
+-		strcpy(i->name, "Camera");
+-		i->type = V4L2_INPUT_TYPE_CAMERA;
++	return 0;
++}
++
++static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
++{
++	*i = 0;
++	return 0;
++}
++
++static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
++{
++	if (i != 0)
++		return -EINVAL;
++
++	return 0;
++}
++
++static int vidioc_queryctrl(struct file *file, void *fh,
++				struct v4l2_queryctrl *c)
++{
++	switch (c->id) {
++
++	case V4L2_CID_BRIGHTNESS:
++		c->type = V4L2_CTRL_TYPE_INTEGER;
++		strcpy(c->name, "Brightness");
++		c->minimum = 0;
++		c->maximum = 63;
++		c->step = 1;
++		c->default_value = 32;
++		c->flags = 0;
++		break;
++	case V4L2_CID_HUE:
++		c->type = V4L2_CTRL_TYPE_INTEGER;
++		strcpy(c->name, "Hue");
++		c->minimum = 0;
++		c->maximum = 63;
++		c->step = 1;
++		c->default_value = 32;
++		c->flags = 0;
++		break;
++	case V4L2_CID_CONTRAST:
++		c->type = V4L2_CTRL_TYPE_INTEGER;
++		strcpy(c->name, "Contrast");
++		c->minimum = 0;
++		c->maximum = 63;
++		c->step = 1;
++		c->default_value = 32;
++		c->flags = 0;
++		break;
++	case V4L2_CID_SATURATION:
++		c->type = V4L2_CTRL_TYPE_INTEGER;
++		strcpy(c->name, "Saturation");
++		c->minimum = 0;
++		c->maximum = 63;
++		c->step = 1;
++		c->default_value = 32;
++		c->flags = 0;
++		break;
++	case V4L2_CID_AGC:
++		c->type = V4L2_CTRL_TYPE_INTEGER;
++		strcpy(c->name, "Agc");
++		c->minimum = 0;
++		c->maximum = 63;
++		c->step = 1;
++		c->default_value = 48;
++		c->flags = 0;
+ 		break;
++	case V4L2_CID_MEYE_SHARPNESS:
++	case V4L2_CID_SHARPNESS:
++		c->type = V4L2_CTRL_TYPE_INTEGER;
++		strcpy(c->name, "Sharpness");
++		c->minimum = 0;
++		c->maximum = 63;
++		c->step = 1;
++		c->default_value = 32;
++
++		/* Continue to report legacy private SHARPNESS ctrl but
++		 * say it is disabled in preference to ctrl in the spec
++		 */
++		c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 :
++						V4L2_CTRL_FLAG_DISABLED;
++		break;
++	case V4L2_CID_PICTURE:
++		c->type = V4L2_CTRL_TYPE_INTEGER;
++		strcpy(c->name, "Picture");
++		c->minimum = 0;
++		c->maximum = 63;
++		c->step = 1;
++		c->default_value = 0;
++		c->flags = 0;
++		break;
++	case V4L2_CID_JPEGQUAL:
++		c->type = V4L2_CTRL_TYPE_INTEGER;
++		strcpy(c->name, "JPEG quality");
++		c->minimum = 0;
++		c->maximum = 10;
++		c->step = 1;
++		c->default_value = 8;
++		c->flags = 0;
++		break;
++	case V4L2_CID_FRAMERATE:
++		c->type = V4L2_CTRL_TYPE_INTEGER;
++		strcpy(c->name, "Framerate");
++		c->minimum = 0;
++		c->maximum = 31;
++		c->step = 1;
++		c->default_value = 0;
++		c->flags = 0;
++		break;
++	default:
++		return -EINVAL;
+ 	}
+ 
+-	case VIDIOC_G_INPUT: {
+-		int *i = arg;
++	return 0;
++}
+ 
+-		*i = 0;
++static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
++{
++	mutex_lock(&meye.lock);
++	switch (c->id) {
++	case V4L2_CID_BRIGHTNESS:
++		sony_pic_camera_command(
++			SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
++		meye.picture.brightness = c->value << 10;
++		break;
++	case V4L2_CID_HUE:
++		sony_pic_camera_command(
++			SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
++		meye.picture.hue = c->value << 10;
++		break;
++	case V4L2_CID_CONTRAST:
++		sony_pic_camera_command(
++			SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
++		meye.picture.contrast = c->value << 10;
++		break;
++	case V4L2_CID_SATURATION:
++		sony_pic_camera_command(
++			SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
++		meye.picture.colour = c->value << 10;
++		break;
++	case V4L2_CID_AGC:
++		sony_pic_camera_command(
++			SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
++		meye.params.agc = c->value;
++		break;
++	case V4L2_CID_SHARPNESS:
++	case V4L2_CID_MEYE_SHARPNESS:
++		sony_pic_camera_command(
++			SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
++		meye.params.sharpness = c->value;
++		break;
++	case V4L2_CID_PICTURE:
++		sony_pic_camera_command(
++			SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
++		meye.params.picture = c->value;
++		break;
++	case V4L2_CID_JPEGQUAL:
++		meye.params.quality = c->value;
++		break;
++	case V4L2_CID_FRAMERATE:
++		meye.params.framerate = c->value;
+ 		break;
++	default:
++		mutex_unlock(&meye.lock);
++		return -EINVAL;
+ 	}
++	mutex_unlock(&meye.lock);
+ 
+-	case VIDIOC_S_INPUT: {
+-		int *i = arg;
++	return 0;
++}
+ 
+-		if (*i != 0)
+-			return -EINVAL;
++static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
++{
++	mutex_lock(&meye.lock);
++	switch (c->id) {
++	case V4L2_CID_BRIGHTNESS:
++		c->value = meye.picture.brightness >> 10;
++		break;
++	case V4L2_CID_HUE:
++		c->value = meye.picture.hue >> 10;
++		break;
++	case V4L2_CID_CONTRAST:
++		c->value = meye.picture.contrast >> 10;
++		break;
++	case V4L2_CID_SATURATION:
++		c->value = meye.picture.colour >> 10;
++		break;
++	case V4L2_CID_AGC:
++		c->value = meye.params.agc;
++		break;
++	case V4L2_CID_SHARPNESS:
++	case V4L2_CID_MEYE_SHARPNESS:
++		c->value = meye.params.sharpness;
+ 		break;
++	case V4L2_CID_PICTURE:
++		c->value = meye.params.picture;
++		break;
++	case V4L2_CID_JPEGQUAL:
++		c->value = meye.params.quality;
++		break;
++	case V4L2_CID_FRAMERATE:
++		c->value = meye.params.framerate;
++		break;
++	default:
++		mutex_unlock(&meye.lock);
++		return -EINVAL;
+ 	}
++	mutex_unlock(&meye.lock);
+ 
+-	case VIDIOC_QUERYCTRL: {
+-		struct v4l2_queryctrl *c = arg;
++	return 0;
++}
+ 
+-		switch (c->id) {
++static int vidioc_enum_fmt_cap(struct file *file, void *fh,
++				struct v4l2_fmtdesc *f)
++{
++	if (f->index > 1)
++		return -EINVAL;
+ 
+-		case V4L2_CID_BRIGHTNESS:
+-			c->type = V4L2_CTRL_TYPE_INTEGER;
+-			strcpy(c->name, "Brightness");
+-			c->minimum = 0;
+-			c->maximum = 63;
+-			c->step = 1;
+-			c->default_value = 32;
+-			c->flags = 0;
+-			break;
+-		case V4L2_CID_HUE:
+-			c->type = V4L2_CTRL_TYPE_INTEGER;
+-			strcpy(c->name, "Hue");
+-			c->minimum = 0;
+-			c->maximum = 63;
+-			c->step = 1;
+-			c->default_value = 32;
+-			c->flags = 0;
+-			break;
+-		case V4L2_CID_CONTRAST:
+-			c->type = V4L2_CTRL_TYPE_INTEGER;
+-			strcpy(c->name, "Contrast");
+-			c->minimum = 0;
+-			c->maximum = 63;
+-			c->step = 1;
+-			c->default_value = 32;
+-			c->flags = 0;
+-			break;
+-		case V4L2_CID_SATURATION:
+-			c->type = V4L2_CTRL_TYPE_INTEGER;
+-			strcpy(c->name, "Saturation");
+-			c->minimum = 0;
+-			c->maximum = 63;
+-			c->step = 1;
+-			c->default_value = 32;
+-			c->flags = 0;
+-			break;
+-		case V4L2_CID_AGC:
+-			c->type = V4L2_CTRL_TYPE_INTEGER;
+-			strcpy(c->name, "Agc");
+-			c->minimum = 0;
+-			c->maximum = 63;
+-			c->step = 1;
+-			c->default_value = 48;
+-			c->flags = 0;
+-			break;
+-		case V4L2_CID_SHARPNESS:
+-			c->type = V4L2_CTRL_TYPE_INTEGER;
+-			strcpy(c->name, "Sharpness");
+-			c->minimum = 0;
+-			c->maximum = 63;
+-			c->step = 1;
+-			c->default_value = 32;
+-			c->flags = 0;
+-			break;
+-		case V4L2_CID_PICTURE:
+-			c->type = V4L2_CTRL_TYPE_INTEGER;
+-			strcpy(c->name, "Picture");
+-			c->minimum = 0;
+-			c->maximum = 63;
+-			c->step = 1;
+-			c->default_value = 0;
+-			c->flags = 0;
+-			break;
+-		case V4L2_CID_JPEGQUAL:
+-			c->type = V4L2_CTRL_TYPE_INTEGER;
+-			strcpy(c->name, "JPEG quality");
+-			c->minimum = 0;
+-			c->maximum = 10;
+-			c->step = 1;
+-			c->default_value = 8;
+-			c->flags = 0;
+-			break;
+-		case V4L2_CID_FRAMERATE:
+-			c->type = V4L2_CTRL_TYPE_INTEGER;
+-			strcpy(c->name, "Framerate");
+-			c->minimum = 0;
+-			c->maximum = 31;
+-			c->step = 1;
+-			c->default_value = 0;
+-			c->flags = 0;
+-			break;
+-		default:
+-			return -EINVAL;
+-		}
+-		break;
++	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++
++	if (f->index == 0) {
++		/* standard YUV 422 capture */
++		memset(f, 0, sizeof(*f));
++		f->index = 0;
++		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++		f->flags = 0;
++		strcpy(f->description, "YUV422");
++		f->pixelformat = V4L2_PIX_FMT_YUYV;
++	} else {
++		/* compressed MJPEG capture */
++		memset(f, 0, sizeof(*f));
++		f->index = 1;
++		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++		f->flags = V4L2_FMT_FLAG_COMPRESSED;
++		strcpy(f->description, "MJPEG");
++		f->pixelformat = V4L2_PIX_FMT_MJPEG;
+ 	}
+ 
+-	case VIDIOC_S_CTRL: {
+-		struct v4l2_control *c = arg;
++	return 0;
++}
+ 
+-		mutex_lock(&meye.lock);
+-		switch (c->id) {
+-		case V4L2_CID_BRIGHTNESS:
+-			sony_pic_camera_command(
+-				SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
+-			meye.picture.brightness = c->value << 10;
+-			break;
+-		case V4L2_CID_HUE:
+-			sony_pic_camera_command(
+-				SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
+-			meye.picture.hue = c->value << 10;
+-			break;
+-		case V4L2_CID_CONTRAST:
+-			sony_pic_camera_command(
+-				SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
+-			meye.picture.contrast = c->value << 10;
+-			break;
+-		case V4L2_CID_SATURATION:
+-			sony_pic_camera_command(
+-				SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
+-			meye.picture.colour = c->value << 10;
+-			break;
+-		case V4L2_CID_AGC:
+-			sony_pic_camera_command(
+-				SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
+-			meye.params.agc = c->value;
+-			break;
+-		case V4L2_CID_SHARPNESS:
+-			sony_pic_camera_command(
+-				SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
+-			meye.params.sharpness = c->value;
+-			break;
+-		case V4L2_CID_PICTURE:
+-			sony_pic_camera_command(
+-				SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
+-			meye.params.picture = c->value;
+-			break;
+-		case V4L2_CID_JPEGQUAL:
+-			meye.params.quality = c->value;
+-			break;
+-		case V4L2_CID_FRAMERATE:
+-			meye.params.framerate = c->value;
+-			break;
+-		default:
+-			mutex_unlock(&meye.lock);
+-			return -EINVAL;
+-		}
+-		mutex_unlock(&meye.lock);
+-		break;
++static int vidioc_try_fmt_cap(struct file *file, void *fh,
++				struct v4l2_format *f)
++{
++	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++
++	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
++	    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
++		return -EINVAL;
++
++	if (f->fmt.pix.field != V4L2_FIELD_ANY &&
++	    f->fmt.pix.field != V4L2_FIELD_NONE)
++		return -EINVAL;
++
++	f->fmt.pix.field = V4L2_FIELD_NONE;
++
++	if (f->fmt.pix.width <= 320) {
++		f->fmt.pix.width = 320;
++		f->fmt.pix.height = 240;
++	} else {
++		f->fmt.pix.width = 640;
++		f->fmt.pix.height = 480;
+ 	}
+ 
+-	case VIDIOC_G_CTRL: {
+-		struct v4l2_control *c = arg;
++	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
++	f->fmt.pix.sizeimage = f->fmt.pix.height *
++			       f->fmt.pix.bytesperline;
++	f->fmt.pix.colorspace = 0;
++	f->fmt.pix.priv = 0;
+ 
+-		mutex_lock(&meye.lock);
+-		switch (c->id) {
+-		case V4L2_CID_BRIGHTNESS:
+-			c->value = meye.picture.brightness >> 10;
+-			break;
+-		case V4L2_CID_HUE:
+-			c->value = meye.picture.hue >> 10;
+-			break;
+-		case V4L2_CID_CONTRAST:
+-			c->value = meye.picture.contrast >> 10;
+-			break;
+-		case V4L2_CID_SATURATION:
+-			c->value = meye.picture.colour >> 10;
+-			break;
+-		case V4L2_CID_AGC:
+-			c->value = meye.params.agc;
+-			break;
+-		case V4L2_CID_SHARPNESS:
+-			c->value = meye.params.sharpness;
+-			break;
+-		case V4L2_CID_PICTURE:
+-			c->value = meye.params.picture;
+-			break;
+-		case V4L2_CID_JPEGQUAL:
+-			c->value = meye.params.quality;
+-			break;
+-		case V4L2_CID_FRAMERATE:
+-			c->value = meye.params.framerate;
+-			break;
+-		default:
+-			mutex_unlock(&meye.lock);
+-			return -EINVAL;
+-		}
+-		mutex_unlock(&meye.lock);
++	return 0;
++}
++
++static int vidioc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
++{
++	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++
++	memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
++	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++
++	switch (meye.mchip_mode) {
++	case MCHIP_HIC_MODE_CONT_OUT:
++	default:
++		f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
++		break;
++	case MCHIP_HIC_MODE_CONT_COMP:
++		f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
+ 		break;
+ 	}
+ 
+-	case VIDIOC_ENUM_FMT: {
+-		struct v4l2_fmtdesc *f = arg;
+-
+-		if (f->index > 1)
+-			return -EINVAL;
+-		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-			return -EINVAL;
+-		if (f->index == 0) {
+-			/* standard YUV 422 capture */
+-			memset(f, 0, sizeof(*f));
+-			f->index = 0;
+-			f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-			f->flags = 0;
+-			strcpy(f->description, "YUV422");
+-			f->pixelformat = V4L2_PIX_FMT_YUYV;
+-		} else {
+-			/* compressed MJPEG capture */
+-			memset(f, 0, sizeof(*f));
+-			f->index = 1;
+-			f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-			f->flags = V4L2_FMT_FLAG_COMPRESSED;
+-			strcpy(f->description, "MJPEG");
+-			f->pixelformat = V4L2_PIX_FMT_MJPEG;
+-		}
+-		break;
++	f->fmt.pix.field = V4L2_FIELD_NONE;
++	f->fmt.pix.width = mchip_hsize();
++	f->fmt.pix.height = mchip_vsize();
++	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
++	f->fmt.pix.sizeimage = f->fmt.pix.height *
++			       f->fmt.pix.bytesperline;
++	f->fmt.pix.colorspace = 0;
++	f->fmt.pix.priv = 0;
++
++	return 0;
++}
++
++static int vidioc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
++{
++	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++
++	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
++	    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
++		return -EINVAL;
++
++	if (f->fmt.pix.field != V4L2_FIELD_ANY &&
++	    f->fmt.pix.field != V4L2_FIELD_NONE)
++		return -EINVAL;
++
++	f->fmt.pix.field = V4L2_FIELD_NONE;
++	mutex_lock(&meye.lock);
++
++	if (f->fmt.pix.width <= 320) {
++		f->fmt.pix.width = 320;
++		f->fmt.pix.height = 240;
++		meye.params.subsample = 1;
++	} else {
++		f->fmt.pix.width = 640;
++		f->fmt.pix.height = 480;
++		meye.params.subsample = 0;
+ 	}
+ 
+-	case VIDIOC_TRY_FMT: {
+-		struct v4l2_format *f = arg;
+-
+-		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-			return -EINVAL;
+-		if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+-		    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+-			return -EINVAL;
+-		if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+-		    f->fmt.pix.field != V4L2_FIELD_NONE)
+-			return -EINVAL;
+-		f->fmt.pix.field = V4L2_FIELD_NONE;
+-		if (f->fmt.pix.width <= 320) {
+-			f->fmt.pix.width = 320;
+-			f->fmt.pix.height = 240;
+-		} else {
+-			f->fmt.pix.width = 640;
+-			f->fmt.pix.height = 480;
+-		}
+-		f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+-		f->fmt.pix.sizeimage = f->fmt.pix.height *
+-				       f->fmt.pix.bytesperline;
+-		f->fmt.pix.colorspace = 0;
+-		f->fmt.pix.priv = 0;
++	switch (f->fmt.pix.pixelformat) {
++	case V4L2_PIX_FMT_YUYV:
++		meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
++		break;
++	case V4L2_PIX_FMT_MJPEG:
++		meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
+ 		break;
+ 	}
+ 
+-	case VIDIOC_G_FMT: {
+-		struct v4l2_format *f = arg;
++	mutex_unlock(&meye.lock);
++	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
++	f->fmt.pix.sizeimage = f->fmt.pix.height *
++			       f->fmt.pix.bytesperline;
++	f->fmt.pix.colorspace = 0;
++	f->fmt.pix.priv = 0;
+ 
+-		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-			return -EINVAL;
+-		memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+-		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		switch (meye.mchip_mode) {
+-		case MCHIP_HIC_MODE_CONT_OUT:
+-		default:
+-			f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+-			break;
+-		case MCHIP_HIC_MODE_CONT_COMP:
+-			f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
+-			break;
+-		}
+-		f->fmt.pix.field = V4L2_FIELD_NONE;
+-		f->fmt.pix.width = mchip_hsize();
+-		f->fmt.pix.height = mchip_vsize();
+-		f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+-		f->fmt.pix.sizeimage = f->fmt.pix.height *
+-				       f->fmt.pix.bytesperline;
+-		f->fmt.pix.colorspace = 0;
+-		f->fmt.pix.priv = 0;
+-		break;
+-	}
++	return 0;
++}
+ 
+-	case VIDIOC_S_FMT: {
+-		struct v4l2_format *f = arg;
+-
+-		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-			return -EINVAL;
+-		if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+-		    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+-			return -EINVAL;
+-		if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+-		    f->fmt.pix.field != V4L2_FIELD_NONE)
+-			return -EINVAL;
+-		f->fmt.pix.field = V4L2_FIELD_NONE;
+-		mutex_lock(&meye.lock);
+-		if (f->fmt.pix.width <= 320) {
+-			f->fmt.pix.width = 320;
+-			f->fmt.pix.height = 240;
+-			meye.params.subsample = 1;
+-		} else {
+-			f->fmt.pix.width = 640;
+-			f->fmt.pix.height = 480;
+-			meye.params.subsample = 0;
+-		}
+-		switch (f->fmt.pix.pixelformat) {
+-		case V4L2_PIX_FMT_YUYV:
+-			meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
+-			break;
+-		case V4L2_PIX_FMT_MJPEG:
+-			meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
+-			break;
+-		}
+-		mutex_unlock(&meye.lock);
+-		f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+-		f->fmt.pix.sizeimage = f->fmt.pix.height *
+-				       f->fmt.pix.bytesperline;
+-		f->fmt.pix.colorspace = 0;
+-		f->fmt.pix.priv = 0;
++static int vidioc_reqbufs(struct file *file, void *fh,
++				struct v4l2_requestbuffers *req)
++{
++	int i;
+ 
+-		break;
+-	}
++	if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
+ 
+-	case VIDIOC_REQBUFS: {
+-		struct v4l2_requestbuffers *req = arg;
+-		int i;
++	if (req->memory != V4L2_MEMORY_MMAP)
++		return -EINVAL;
+ 
+-		if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-			return -EINVAL;
+-		if (req->memory != V4L2_MEMORY_MMAP)
+-			return -EINVAL;
+-		if (meye.grab_fbuffer && req->count == gbuffers) {
+-			/* already allocated, no modifications */
+-			break;
+-		}
+-		mutex_lock(&meye.lock);
+-		if (meye.grab_fbuffer) {
+-			for (i = 0; i < gbuffers; i++)
+-				if (meye.vma_use_count[i]) {
+-					mutex_unlock(&meye.lock);
+-					return -EINVAL;
+-				}
+-			rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
+-			meye.grab_fbuffer = NULL;
+-		}
+-		gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
+-		req->count = gbuffers;
+-		meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
+-		if (!meye.grab_fbuffer) {
+-			printk(KERN_ERR "meye: v4l framebuffer allocation"
+-					" failed\n");
+-			mutex_unlock(&meye.lock);
+-			return -ENOMEM;
+-		}
+-		for (i = 0; i < gbuffers; i++)
+-			meye.vma_use_count[i] = 0;
+-		mutex_unlock(&meye.lock);
+-		break;
++	if (meye.grab_fbuffer && req->count == gbuffers) {
++		/* already allocated, no modifications */
++		return 0;
+ 	}
+ 
+-	case VIDIOC_QUERYBUF: {
+-		struct v4l2_buffer *buf = arg;
+-		int index = buf->index;
+-
+-		if (index < 0 || index >= gbuffers)
+-			return -EINVAL;
+-		memset(buf, 0, sizeof(*buf));
+-		buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		buf->index = index;
+-		buf->bytesused = meye.grab_buffer[index].size;
+-		buf->flags = V4L2_BUF_FLAG_MAPPED;
+-		if (meye.grab_buffer[index].state == MEYE_BUF_USING)
+-			buf->flags |= V4L2_BUF_FLAG_QUEUED;
+-		if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
+-			buf->flags |= V4L2_BUF_FLAG_DONE;
+-		buf->field = V4L2_FIELD_NONE;
+-		buf->timestamp = meye.grab_buffer[index].timestamp;
+-		buf->sequence = meye.grab_buffer[index].sequence;
+-		buf->memory = V4L2_MEMORY_MMAP;
+-		buf->m.offset = index * gbufsize;
+-		buf->length = gbufsize;
+-		break;
++	mutex_lock(&meye.lock);
++	if (meye.grab_fbuffer) {
++		for (i = 0; i < gbuffers; i++)
++			if (meye.vma_use_count[i]) {
++				mutex_unlock(&meye.lock);
++				return -EINVAL;
++			}
++		rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
++		meye.grab_fbuffer = NULL;
+ 	}
+ 
+-	case VIDIOC_QBUF: {
+-		struct v4l2_buffer *buf = arg;
+-
+-		if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-			return -EINVAL;
+-		if (buf->memory != V4L2_MEMORY_MMAP)
+-			return -EINVAL;
+-		if (buf->index < 0 || buf->index >= gbuffers)
+-			return -EINVAL;
+-		if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
+-			return -EINVAL;
+-		mutex_lock(&meye.lock);
+-		buf->flags |= V4L2_BUF_FLAG_QUEUED;
+-		buf->flags &= ~V4L2_BUF_FLAG_DONE;
+-		meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
+-		kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
++	gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
++	req->count = gbuffers;
++	meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
++
++	if (!meye.grab_fbuffer) {
++		printk(KERN_ERR "meye: v4l framebuffer allocation"
++				" failed\n");
+ 		mutex_unlock(&meye.lock);
+-		break;
++		return -ENOMEM;
+ 	}
+ 
+-	case VIDIOC_DQBUF: {
+-		struct v4l2_buffer *buf = arg;
+-		int reqnr;
++	for (i = 0; i < gbuffers; i++)
++		meye.vma_use_count[i] = 0;
+ 
+-		if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+-			return -EINVAL;
+-		if (buf->memory != V4L2_MEMORY_MMAP)
+-			return -EINVAL;
++	mutex_unlock(&meye.lock);
+ 
+-		mutex_lock(&meye.lock);
+-		if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
+-			mutex_unlock(&meye.lock);
+-			return -EAGAIN;
+-		}
+-		if (wait_event_interruptible(meye.proc_list,
+-					     kfifo_len(meye.doneq) != 0) < 0) {
+-			mutex_unlock(&meye.lock);
+-			return -EINTR;
+-		}
+-		if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
+-			       sizeof(int))) {
+-			mutex_unlock(&meye.lock);
+-			return -EBUSY;
+-		}
+-		if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
+-			mutex_unlock(&meye.lock);
+-			return -EINVAL;
+-		}
+-		buf->index = reqnr;
+-		buf->bytesused = meye.grab_buffer[reqnr].size;
+-		buf->flags = V4L2_BUF_FLAG_MAPPED;
+-		buf->field = V4L2_FIELD_NONE;
+-		buf->timestamp = meye.grab_buffer[reqnr].timestamp;
+-		buf->sequence = meye.grab_buffer[reqnr].sequence;
+-		buf->memory = V4L2_MEMORY_MMAP;
+-		buf->m.offset = reqnr * gbufsize;
+-		buf->length = gbufsize;
+-		meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
++	return 0;
++}
++
++static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
++{
++	int index = buf->index;
++
++	if (index < 0 || index >= gbuffers)
++		return -EINVAL;
++
++	memset(buf, 0, sizeof(*buf));
++
++	buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	buf->index = index;
++	buf->bytesused = meye.grab_buffer[index].size;
++	buf->flags = V4L2_BUF_FLAG_MAPPED;
++
++	if (meye.grab_buffer[index].state == MEYE_BUF_USING)
++		buf->flags |= V4L2_BUF_FLAG_QUEUED;
++
++	if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
++		buf->flags |= V4L2_BUF_FLAG_DONE;
++
++	buf->field = V4L2_FIELD_NONE;
++	buf->timestamp = meye.grab_buffer[index].timestamp;
++	buf->sequence = meye.grab_buffer[index].sequence;
++	buf->memory = V4L2_MEMORY_MMAP;
++	buf->m.offset = index * gbufsize;
++	buf->length = gbufsize;
++
++	return 0;
++}
++
++static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
++{
++	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++
++	if (buf->memory != V4L2_MEMORY_MMAP)
++		return -EINVAL;
++
++	if (buf->index < 0 || buf->index >= gbuffers)
++		return -EINVAL;
++
++	if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
++		return -EINVAL;
++
++	mutex_lock(&meye.lock);
++	buf->flags |= V4L2_BUF_FLAG_QUEUED;
++	buf->flags &= ~V4L2_BUF_FLAG_DONE;
++	meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
++	kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
++	mutex_unlock(&meye.lock);
++
++	return 0;
++}
++
++static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
++{
++	int reqnr;
++
++	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++
++	if (buf->memory != V4L2_MEMORY_MMAP)
++		return -EINVAL;
++
++	mutex_lock(&meye.lock);
++
++	if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
+ 		mutex_unlock(&meye.lock);
+-		break;
++		return -EAGAIN;
+ 	}
+ 
+-	case VIDIOC_STREAMON: {
+-		mutex_lock(&meye.lock);
+-		switch (meye.mchip_mode) {
+-		case MCHIP_HIC_MODE_CONT_OUT:
+-			mchip_continuous_start();
+-			break;
+-		case MCHIP_HIC_MODE_CONT_COMP:
+-			mchip_cont_compression_start();
+-			break;
+-		default:
+-			mutex_unlock(&meye.lock);
+-			return -EINVAL;
+-		}
++	if (wait_event_interruptible(meye.proc_list,
++				     kfifo_len(meye.doneq) != 0) < 0) {
+ 		mutex_unlock(&meye.lock);
+-		break;
++		return -EINTR;
+ 	}
+ 
+-	case VIDIOC_STREAMOFF: {
+-		int i;
++	if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
++		       sizeof(int))) {
++		mutex_unlock(&meye.lock);
++		return -EBUSY;
++	}
+ 
+-		mutex_lock(&meye.lock);
+-		mchip_hic_stop();
+-		kfifo_reset(meye.grabq);
+-		kfifo_reset(meye.doneq);
+-		for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
+-			meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
++	if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
+ 		mutex_unlock(&meye.lock);
+-		break;
++		return -EINVAL;
+ 	}
+ 
+-	/*
+-	 * XXX what about private snapshot ioctls ?
+-	 * Do they need to be converted to V4L2 ?
+-	*/
++	buf->index = reqnr;
++	buf->bytesused = meye.grab_buffer[reqnr].size;
++	buf->flags = V4L2_BUF_FLAG_MAPPED;
++	buf->field = V4L2_FIELD_NONE;
++	buf->timestamp = meye.grab_buffer[reqnr].timestamp;
++	buf->sequence = meye.grab_buffer[reqnr].sequence;
++	buf->memory = V4L2_MEMORY_MMAP;
++	buf->m.offset = reqnr * gbufsize;
++	buf->length = gbufsize;
++	meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
++	mutex_unlock(&meye.lock);
++
++	return 0;
++}
+ 
++static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
++{
++	mutex_lock(&meye.lock);
++
++	switch (meye.mchip_mode) {
++	case MCHIP_HIC_MODE_CONT_OUT:
++		mchip_continuous_start();
++		break;
++	case MCHIP_HIC_MODE_CONT_COMP:
++		mchip_cont_compression_start();
++		break;
+ 	default:
+-		return -ENOIOCTLCMD;
++		mutex_unlock(&meye.lock);
++		return -EINVAL;
+ 	}
+ 
++	mutex_unlock(&meye.lock);
++
+ 	return 0;
+ }
+ 
+-static int meye_ioctl(struct inode *inode, struct file *file,
+-		     unsigned int cmd, unsigned long arg)
++static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
+ {
+-	return video_usercopy(inode, file, cmd, arg, meye_do_ioctl);
++	mutex_lock(&meye.lock);
++	mchip_hic_stop();
++	kfifo_reset(meye.grabq);
++	kfifo_reset(meye.doneq);
++
++	for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
++		meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
++
++	mutex_unlock(&meye.lock);
++	return 0;
++}
++
++static int vidioc_default(struct file *file, void *fh, int cmd, void *arg)
++{
++	switch (cmd) {
++	case MEYEIOC_G_PARAMS:
++		return meyeioc_g_params((struct meye_params *) arg);
++
++	case MEYEIOC_S_PARAMS:
++		return meyeioc_s_params((struct meye_params *) arg);
++
++	case MEYEIOC_QBUF_CAPT:
++		return meyeioc_qbuf_capt((int *) arg);
++
++	case MEYEIOC_SYNC:
++		return meyeioc_sync(file, fh, (int *) arg);
++
++	case MEYEIOC_STILLCAPT:
++		return meyeioc_stillcapt();
++
++	case MEYEIOC_STILLJCAPT:
++		return meyeioc_stilljcapt((int *) arg);
++
++	default:
++		return -EINVAL;
++	}
++
+ }
+ 
+ static unsigned int meye_poll(struct file *file, poll_table *wait)
+@@ -1752,8 +1687,10 @@ static const struct file_operations meye_fops = {
+ 	.open		= meye_open,
+ 	.release	= meye_release,
+ 	.mmap		= meye_mmap,
+-	.ioctl		= meye_ioctl,
++	.ioctl		= video_ioctl2,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.poll		= meye_poll,
+ 	.llseek		= no_llseek,
+ };
+@@ -1765,6 +1702,24 @@ static struct video_device meye_template = {
+ 	.fops		= &meye_fops,
+ 	.release	= video_device_release,
+ 	.minor		= -1,
++	.vidioc_querycap	= vidioc_querycap,
++	.vidioc_enum_input	= vidioc_enum_input,
++	.vidioc_g_input		= vidioc_g_input,
++	.vidioc_s_input		= vidioc_s_input,
++	.vidioc_queryctrl	= vidioc_queryctrl,
++	.vidioc_s_ctrl		= vidioc_s_ctrl,
++	.vidioc_g_ctrl		= vidioc_g_ctrl,
++	.vidioc_enum_fmt_cap	= vidioc_enum_fmt_cap,
++	.vidioc_try_fmt_cap	= vidioc_try_fmt_cap,
++	.vidioc_g_fmt_cap	= vidioc_g_fmt_cap,
++	.vidioc_s_fmt_cap	= vidioc_s_fmt_cap,
++	.vidioc_reqbufs		= vidioc_reqbufs,
++	.vidioc_querybuf	= vidioc_querybuf,
++	.vidioc_qbuf		= vidioc_qbuf,
++	.vidioc_dqbuf		= vidioc_dqbuf,
++	.vidioc_streamon	= vidioc_streamon,
++	.vidioc_streamoff	= vidioc_streamoff,
++	.vidioc_default		= vidioc_default,
+ };
+ 
+ #ifdef CONFIG_PM
+diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
+index 7a11f31..b73c740 100644
+--- a/drivers/media/video/msp3400-driver.c
++++ b/drivers/media/video/msp3400-driver.c
+@@ -366,7 +366,7 @@ int msp_sleep(struct msp_state *state, int timeout)
+ }
+ 
+ /* ------------------------------------------------------------------------ */
+-#ifdef CONFIG_VIDEO_V4L1
++#ifdef CONFIG_VIDEO_ALLOW_V4L1
+ static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
+ {
+ 	if (rxsubchans == V4L2_TUNER_SUB_MONO)
+@@ -514,7 +514,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
+ 	/* --- v4l ioctls --- */
+ 	/* take care: bttv does userspace copying, we'll get a
+ 	   kernel pointer here... */
+-#ifdef CONFIG_VIDEO_V4L1
++#ifdef CONFIG_VIDEO_ALLOW_V4L1
+ 	case VIDIOCGAUDIO:
+ 	{
+ 		struct video_audio *va = arg;
+diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
+index 61ec794..7f55685 100644
+--- a/drivers/media/video/msp3400-kthreads.c
++++ b/drivers/media/video/msp3400-kthreads.c
+@@ -833,11 +833,6 @@ static int msp34xxg_modus(struct i2c_client *client)
+ 		v4l_dbg(1, msp_debug, client, "selected radio modus\n");
+ 		return 0x0001;
+ 	}
+-
+-	if (state->v4l2_std & V4L2_STD_PAL) {
+-		v4l_dbg(1, msp_debug, client, "selected PAL modus\n");
+-		return 0x7001;
+-	}
+ 	if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
+ 		v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");
+ 		return 0x4001;
+@@ -846,15 +841,15 @@ static int msp34xxg_modus(struct i2c_client *client)
+ 		v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");
+ 		return 0x0001;
+ 	}
++	if (state->v4l2_std == V4L2_STD_SECAM_L) {
++		v4l_dbg(1, msp_debug, client, "selected SECAM-L modus\n");
++		return 0x6001;
++	}
+ 	if (state->v4l2_std & V4L2_STD_MN) {
+ 		v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");
+ 		return 0x2001;
+ 	}
+-	if (state->v4l2_std & V4L2_STD_SECAM) {
+-		v4l_dbg(1, msp_debug, client, "selected SECAM modus\n");
+-		return 0x6001;
+-	}
+-	return 0x0001;
++	return 0x7001;
+ }
+ 
+ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
+diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
+index 74fd6a0..fbcb282 100644
+--- a/drivers/media/video/mt20xx.c
++++ b/drivers/media/video/mt20xx.c
+@@ -10,12 +10,10 @@
+ #include "tuner-i2c.h"
+ #include "mt20xx.h"
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+ 
+-#define PREFIX "mt20xx"
+-
+ /* ---------------------------------------------------------------------- */
+ 
+ static unsigned int optimize_vco  = 1;
+@@ -24,7 +22,7 @@ module_param(optimize_vco,      int, 0644);
+ static unsigned int tv_antenna    = 1;
+ module_param(tv_antenna,        int, 0644);
+ 
+-static unsigned int radio_antenna = 0;
++static unsigned int radio_antenna;
+ module_param(radio_antenna,     int, 0644);
+ 
+ /* ---------------------------------------------------------------------- */
+@@ -611,6 +609,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
+ 
+ 	priv->i2c_props.addr = i2c_addr;
+ 	priv->i2c_props.adap = i2c_adap;
++	priv->i2c_props.name = "mt20xx";
+ 
+ 	//priv->radio_if2 = 10700 * 1000;	/* 10.7MHz - FM radio */
+ 
+diff --git a/drivers/media/video/mt20xx.h b/drivers/media/video/mt20xx.h
+index 5e9c825..aa848e1 100644
+--- a/drivers/media/video/mt20xx.h
++++ b/drivers/media/video/mt20xx.h
+@@ -29,7 +29,7 @@ static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
+ 					     struct i2c_adapter* i2c_adap,
+ 					     u8 i2c_addr)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
+new file mode 100644
+index 0000000..3fb5f63
+--- /dev/null
++++ b/drivers/media/video/mt9m001.c
+@@ -0,0 +1,722 @@
++/*
++ * Driver for MT9M001 CMOS Image Sensor from Micron
++ *
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at 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/videodev2.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/log2.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-chip-ident.h>
++#include <media/soc_camera.h>
++
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++#include <asm/gpio.h>
++#endif
++
++/* mt9m001 i2c address 0x5d
++ * The platform has to define i2c_board_info
++ * and call i2c_register_board_info() */
++
++/* mt9m001 selected register addresses */
++#define MT9M001_CHIP_VERSION		0x00
++#define MT9M001_ROW_START		0x01
++#define MT9M001_COLUMN_START		0x02
++#define MT9M001_WINDOW_HEIGHT		0x03
++#define MT9M001_WINDOW_WIDTH		0x04
++#define MT9M001_HORIZONTAL_BLANKING	0x05
++#define MT9M001_VERTICAL_BLANKING	0x06
++#define MT9M001_OUTPUT_CONTROL		0x07
++#define MT9M001_SHUTTER_WIDTH		0x09
++#define MT9M001_FRAME_RESTART		0x0b
++#define MT9M001_SHUTTER_DELAY		0x0c
++#define MT9M001_RESET			0x0d
++#define MT9M001_READ_OPTIONS1		0x1e
++#define MT9M001_READ_OPTIONS2		0x20
++#define MT9M001_GLOBAL_GAIN		0x35
++#define MT9M001_CHIP_ENABLE		0xF1
++
++static const struct soc_camera_data_format mt9m001_colour_formats[] = {
++	/* Order important: first natively supported,
++	 * second supported with a GPIO extender */
++	{
++		.name		= "Bayer (sRGB) 10 bit",
++		.depth		= 10,
++		.fourcc		= V4L2_PIX_FMT_SBGGR16,
++		.colorspace	= V4L2_COLORSPACE_SRGB,
++	}, {
++		.name		= "Bayer (sRGB) 8 bit",
++		.depth		= 8,
++		.fourcc		= V4L2_PIX_FMT_SBGGR8,
++		.colorspace	= V4L2_COLORSPACE_SRGB,
++	}
++};
++
++static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
++	/* Order important - see above */
++	{
++		.name		= "Monochrome 10 bit",
++		.depth		= 10,
++		.fourcc		= V4L2_PIX_FMT_Y16,
++	}, {
++		.name		= "Monochrome 8 bit",
++		.depth		= 8,
++		.fourcc		= V4L2_PIX_FMT_GREY,
++	},
++};
++
++struct mt9m001 {
++	struct i2c_client *client;
++	struct soc_camera_device icd;
++	int model;	/* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
++	int switch_gpio;
++	unsigned char autoexposure;
++	unsigned char datawidth;
++};
++
++static int reg_read(struct soc_camera_device *icd, const u8 reg)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++	struct i2c_client *client = mt9m001->client;
++	s32 data = i2c_smbus_read_word_data(client, reg);
++	return data < 0 ? data : swab16(data);
++}
++
++static int reg_write(struct soc_camera_device *icd, const u8 reg,
++		     const u16 data)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++	return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data));
++}
++
++static int reg_set(struct soc_camera_device *icd, const u8 reg,
++		   const u16 data)
++{
++	int ret;
++
++	ret = reg_read(icd, reg);
++	if (ret < 0)
++		return ret;
++	return reg_write(icd, reg, ret | data);
++}
++
++static int reg_clear(struct soc_camera_device *icd, const u8 reg,
++		     const u16 data)
++{
++	int ret;
++
++	ret = reg_read(icd, reg);
++	if (ret < 0)
++		return ret;
++	return reg_write(icd, reg, ret & ~data);
++}
++
++static int mt9m001_init(struct soc_camera_device *icd)
++{
++	int ret;
++
++	/* Disable chip, synchronous option update */
++	dev_dbg(icd->vdev->dev, "%s\n", __func__);
++
++	ret = reg_write(icd, MT9M001_RESET, 1);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9M001_RESET, 0);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
++
++	return ret >= 0 ? 0 : -EIO;
++}
++
++static int mt9m001_release(struct soc_camera_device *icd)
++{
++	/* Disable the chip */
++	reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
++	return 0;
++}
++
++static int mt9m001_start_capture(struct soc_camera_device *icd)
++{
++	/* Switch to master "normal" mode */
++	if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0)
++		return -EIO;
++	return 0;
++}
++
++static int mt9m001_stop_capture(struct soc_camera_device *icd)
++{
++	/* Stop sensor readout */
++	if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0)
++		return -EIO;
++	return 0;
++}
++
++static int bus_switch_request(struct mt9m001 *mt9m001,
++			      struct soc_camera_link *icl)
++{
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++	int ret;
++	unsigned int gpio = icl->gpio;
++
++	if (gpio_is_valid(gpio)) {
++		/* We have a data bus switch. */
++		ret = gpio_request(gpio, "mt9m001");
++		if (ret < 0) {
++			dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n",
++				gpio);
++			return ret;
++		}
++
++		ret = gpio_direction_output(gpio, 0);
++		if (ret < 0) {
++			dev_err(&mt9m001->client->dev,
++				"Cannot set GPIO %u to output\n", gpio);
++			gpio_free(gpio);
++			return ret;
++		}
++	}
++
++	mt9m001->switch_gpio = gpio;
++#else
++	mt9m001->switch_gpio = -EINVAL;
++#endif
++	return 0;
++}
++
++static void bus_switch_release(struct mt9m001 *mt9m001)
++{
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++	if (gpio_is_valid(mt9m001->switch_gpio))
++		gpio_free(mt9m001->switch_gpio);
++#endif
++}
++
++static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit)
++{
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++	if (!gpio_is_valid(mt9m001->switch_gpio))
++		return -ENODEV;
++
++	gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit);
++	return 0;
++#else
++	return -ENODEV;
++#endif
++}
++
++static int bus_switch_possible(struct mt9m001 *mt9m001)
++{
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++	return gpio_is_valid(mt9m001->switch_gpio);
++#else
++	return 0;
++#endif
++}
++
++static int mt9m001_set_bus_param(struct soc_camera_device *icd,
++				 unsigned long flags)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++	unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
++	int ret;
++
++	/* Flags validity verified in test_bus_param */
++
++	if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
++	    (mt9m001->datawidth != 9  && (width_flag == SOCAM_DATAWIDTH_9)) ||
++	    (mt9m001->datawidth != 8  && (width_flag == SOCAM_DATAWIDTH_8))) {
++		/* Well, we actually only can do 10 or 8 bits... */
++		if (width_flag == SOCAM_DATAWIDTH_9)
++			return -EINVAL;
++		ret = bus_switch_act(mt9m001,
++				     width_flag == SOCAM_DATAWIDTH_8);
++		if (ret < 0)
++			return ret;
++
++		mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
++	}
++
++	return 0;
++}
++
++static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++	unsigned int width_flag = SOCAM_DATAWIDTH_10;
++
++	if (bus_switch_possible(mt9m001))
++		width_flag |= SOCAM_DATAWIDTH_8;
++
++	/* MT9M001 has all capture_format parameters fixed */
++	return SOCAM_PCLK_SAMPLE_RISING |
++		SOCAM_HSYNC_ACTIVE_HIGH |
++		SOCAM_VSYNC_ACTIVE_HIGH |
++		SOCAM_MASTER |
++		width_flag;
++}
++
++static int mt9m001_set_fmt_cap(struct soc_camera_device *icd,
++		__u32 pixfmt, struct v4l2_rect *rect)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++	int ret;
++	const u16 hblank = 9, vblank = 25;
++
++	/* Blanking and start values - default... */
++	ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
++
++	/* The caller provides a supported format, as verified per
++	 * call to icd->try_fmt_cap() */
++	if (ret >= 0)
++		ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9M001_ROW_START, rect->top);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
++				rect->height + icd->y_skip_top - 1);
++	if (ret >= 0 && mt9m001->autoexposure) {
++		ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
++				rect->height + icd->y_skip_top + vblank);
++		if (ret >= 0) {
++			const struct v4l2_queryctrl *qctrl =
++				soc_camera_find_qctrl(icd->ops,
++						      V4L2_CID_EXPOSURE);
++			icd->exposure = (524 + (rect->height + icd->y_skip_top +
++						vblank - 1) *
++					 (qctrl->maximum - qctrl->minimum)) /
++				1048 + qctrl->minimum;
++		}
++	}
++
++	return ret < 0 ? ret : 0;
++}
++
++static int mt9m001_try_fmt_cap(struct soc_camera_device *icd,
++			       struct v4l2_format *f)
++{
++	if (f->fmt.pix.height < 32 + icd->y_skip_top)
++		f->fmt.pix.height = 32 + icd->y_skip_top;
++	if (f->fmt.pix.height > 1024 + icd->y_skip_top)
++		f->fmt.pix.height = 1024 + icd->y_skip_top;
++	if (f->fmt.pix.width < 48)
++		f->fmt.pix.width = 48;
++	if (f->fmt.pix.width > 1280)
++		f->fmt.pix.width = 1280;
++	f->fmt.pix.width &= ~0x01; /* has to be even, unsure why was ~3 */
++
++	return 0;
++}
++
++static int mt9m001_get_chip_id(struct soc_camera_device *icd,
++			       struct v4l2_chip_ident *id)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++
++	if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
++		return -EINVAL;
++
++	if (id->match_chip != mt9m001->client->addr)
++		return -ENODEV;
++
++	id->ident	= mt9m001->model;
++	id->revision	= 0;
++
++	return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int mt9m001_get_register(struct soc_camera_device *icd,
++				struct v4l2_register *reg)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++
++	if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
++		return -EINVAL;
++
++	if (reg->match_chip != mt9m001->client->addr)
++		return -ENODEV;
++
++	reg->val = reg_read(icd, reg->reg);
++
++	if (reg->val > 0xffff)
++		return -EIO;
++
++	return 0;
++}
++
++static int mt9m001_set_register(struct soc_camera_device *icd,
++				struct v4l2_register *reg)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++
++	if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
++		return -EINVAL;
++
++	if (reg->match_chip != mt9m001->client->addr)
++		return -ENODEV;
++
++	if (reg_write(icd, reg->reg, reg->val) < 0)
++		return -EIO;
++
++	return 0;
++}
++#endif
++
++const struct v4l2_queryctrl mt9m001_controls[] = {
++	{
++		.id		= V4L2_CID_VFLIP,
++		.type		= V4L2_CTRL_TYPE_BOOLEAN,
++		.name		= "Flip Vertically",
++		.minimum	= 0,
++		.maximum	= 1,
++		.step		= 1,
++		.default_value	= 0,
++	}, {
++		.id		= V4L2_CID_GAIN,
++		.type		= V4L2_CTRL_TYPE_INTEGER,
++		.name		= "Gain",
++		.minimum	= 0,
++		.maximum	= 127,
++		.step		= 1,
++		.default_value	= 64,
++		.flags		= V4L2_CTRL_FLAG_SLIDER,
++	}, {
++		.id		= V4L2_CID_EXPOSURE,
++		.type		= V4L2_CTRL_TYPE_INTEGER,
++		.name		= "Exposure",
++		.minimum	= 1,
++		.maximum	= 255,
++		.step		= 1,
++		.default_value	= 255,
++		.flags		= V4L2_CTRL_FLAG_SLIDER,
++	}, {
++		.id		= V4L2_CID_EXPOSURE_AUTO,
++		.type		= V4L2_CTRL_TYPE_BOOLEAN,
++		.name		= "Automatic Exposure",
++		.minimum	= 0,
++		.maximum	= 1,
++		.step		= 1,
++		.default_value	= 1,
++	}
++};
++
++static int mt9m001_video_probe(struct soc_camera_device *);
++static void mt9m001_video_remove(struct soc_camera_device *);
++static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
++static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
++
++static struct soc_camera_ops mt9m001_ops = {
++	.owner			= THIS_MODULE,
++	.probe			= mt9m001_video_probe,
++	.remove			= mt9m001_video_remove,
++	.init			= mt9m001_init,
++	.release		= mt9m001_release,
++	.start_capture		= mt9m001_start_capture,
++	.stop_capture		= mt9m001_stop_capture,
++	.set_fmt_cap		= mt9m001_set_fmt_cap,
++	.try_fmt_cap		= mt9m001_try_fmt_cap,
++	.set_bus_param		= mt9m001_set_bus_param,
++	.query_bus_param	= mt9m001_query_bus_param,
++	.controls		= mt9m001_controls,
++	.num_controls		= ARRAY_SIZE(mt9m001_controls),
++	.get_control		= mt9m001_get_control,
++	.set_control		= mt9m001_set_control,
++	.get_chip_id		= mt9m001_get_chip_id,
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++	.get_register		= mt9m001_get_register,
++	.set_register		= mt9m001_set_register,
++#endif
++};
++
++static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++	int data;
++
++	switch (ctrl->id) {
++	case V4L2_CID_VFLIP:
++		data = reg_read(icd, MT9M001_READ_OPTIONS2);
++		if (data < 0)
++			return -EIO;
++		ctrl->value = !!(data & 0x8000);
++		break;
++	case V4L2_CID_EXPOSURE_AUTO:
++		ctrl->value = mt9m001->autoexposure;
++		break;
++	}
++	return 0;
++}
++
++static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++	const struct v4l2_queryctrl *qctrl;
++	int data;
++
++	qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id);
++
++	if (!qctrl)
++		return -EINVAL;
++
++	switch (ctrl->id) {
++	case V4L2_CID_VFLIP:
++		if (ctrl->value)
++			data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000);
++		else
++			data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000);
++		if (data < 0)
++			return -EIO;
++		break;
++	case V4L2_CID_GAIN:
++		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
++			return -EINVAL;
++		/* See Datasheet Table 7, Gain settings. */
++		if (ctrl->value <= qctrl->default_value) {
++			/* Pack it into 0..1 step 0.125, register values 0..8 */
++			unsigned long range = qctrl->default_value - qctrl->minimum;
++			data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
++
++			dev_dbg(&icd->dev, "Setting gain %d\n", data);
++			data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
++			if (data < 0)
++				return -EIO;
++		} else {
++			/* Pack it into 1.125..15 variable step, register values 9..67 */
++			/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
++			unsigned long range = qctrl->maximum - qctrl->default_value - 1;
++			unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
++					       111 + range / 2) / range + 9;
++
++			if (gain <= 32)
++				data = gain;
++			else if (gain <= 64)
++				data = ((gain - 32) * 16 + 16) / 32 + 80;
++			else
++				data = ((gain - 64) * 7 + 28) / 56 + 96;
++
++			dev_dbg(&icd->dev, "Setting gain from %d to %d\n",
++				 reg_read(icd, MT9M001_GLOBAL_GAIN), data);
++			data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
++			if (data < 0)
++				return -EIO;
++		}
++
++		/* Success */
++		icd->gain = ctrl->value;
++		break;
++	case V4L2_CID_EXPOSURE:
++		/* mt9m001 has maximum == default */
++		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
++			return -EINVAL;
++		else {
++			unsigned long range = qctrl->maximum - qctrl->minimum;
++			unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 +
++						 range / 2) / range + 1;
++
++			dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n",
++				 reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter);
++			if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0)
++				return -EIO;
++			icd->exposure = ctrl->value;
++			mt9m001->autoexposure = 0;
++		}
++		break;
++	case V4L2_CID_EXPOSURE_AUTO:
++		if (ctrl->value) {
++			const u16 vblank = 25;
++			if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height +
++				      icd->y_skip_top + vblank) < 0)
++				return -EIO;
++			qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
++			icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) *
++					 (qctrl->maximum - qctrl->minimum)) /
++				1048 + qctrl->minimum;
++			mt9m001->autoexposure = 1;
++		} else
++			mt9m001->autoexposure = 0;
++		break;
++	}
++	return 0;
++}
++
++/* Interface active, can use i2c. If it fails, it can indeed mean, that
++ * this wasn't our capture interface, so, we wait for the right one */
++static int mt9m001_video_probe(struct soc_camera_device *icd)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++	s32 data;
++	int ret;
++
++	/* We must have a parent by now. And it cannot be a wrong one.
++	 * So this entire test is completely redundant. */
++	if (!icd->dev.parent ||
++	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
++		return -ENODEV;
++
++	/* Enable the chip */
++	data = reg_write(&mt9m001->icd, MT9M001_CHIP_ENABLE, 1);
++	dev_dbg(&icd->dev, "write: %d\n", data);
++
++	/* Read out the chip version register */
++	data = reg_read(icd, MT9M001_CHIP_VERSION);
++
++	/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
++	switch (data) {
++	case 0x8411:
++	case 0x8421:
++		mt9m001->model = V4L2_IDENT_MT9M001C12ST;
++		icd->formats = mt9m001_colour_formats;
++		if (mt9m001->client->dev.platform_data)
++			icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats);
++		else
++			icd->num_formats = 1;
++		break;
++	case 0x8431:
++		mt9m001->model = V4L2_IDENT_MT9M001C12STM;
++		icd->formats = mt9m001_monochrome_formats;
++		if (mt9m001->client->dev.platform_data)
++			icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats);
++		else
++			icd->num_formats = 1;
++		break;
++	default:
++		ret = -ENODEV;
++		dev_err(&icd->dev,
++			"No MT9M001 chip detected, register read %x\n", data);
++		goto ei2c;
++	}
++
++	dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
++		 data == 0x8431 ? "C12STM" : "C12ST");
++
++	/* Now that we know the model, we can start video */
++	ret = soc_camera_video_start(icd);
++	if (ret)
++		goto eisis;
++
++	return 0;
++
++eisis:
++ei2c:
++	return ret;
++}
++
++static void mt9m001_video_remove(struct soc_camera_device *icd)
++{
++	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++
++	dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
++		mt9m001->icd.dev.parent, mt9m001->icd.vdev);
++	soc_camera_video_stop(&mt9m001->icd);
++}
++
++static int mt9m001_probe(struct i2c_client *client)
++{
++	struct mt9m001 *mt9m001;
++	struct soc_camera_device *icd;
++	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
++	struct soc_camera_link *icl = client->dev.platform_data;
++	int ret;
++
++	if (!icl) {
++		dev_err(&client->dev, "MT9M001 driver needs platform data\n");
++		return -EINVAL;
++	}
++
++	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
++		dev_warn(&adapter->dev,
++			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
++		return -EIO;
++	}
++
++	mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL);
++	if (!mt9m001)
++		return -ENOMEM;
++
++	mt9m001->client = client;
++	i2c_set_clientdata(client, mt9m001);
++
++	/* Second stage probe - when a capture adapter is there */
++	icd = &mt9m001->icd;
++	icd->ops	= &mt9m001_ops;
++	icd->control	= &client->dev;
++	icd->x_min	= 20;
++	icd->y_min	= 12;
++	icd->x_current	= 20;
++	icd->y_current	= 12;
++	icd->width_min	= 48;
++	icd->width_max	= 1280;
++	icd->height_min	= 32;
++	icd->height_max	= 1024;
++	icd->y_skip_top	= 1;
++	icd->iface	= icl->bus_id;
++	/* Default datawidth - this is the only width this camera (normally)
++	 * supports. It is only with extra logic that it can support
++	 * other widths. Therefore it seems to be a sensible default. */
++	mt9m001->datawidth = 10;
++	/* Simulated autoexposure. If enabled, we calculate shutter width
++	 * ourselves in the driver based on vertical blanking and frame width */
++	mt9m001->autoexposure = 1;
++
++	ret = bus_switch_request(mt9m001, icl);
++	if (ret)
++		goto eswinit;
++
++	ret = soc_camera_device_register(icd);
++	if (ret)
++		goto eisdr;
++
++	return 0;
++
++eisdr:
++	bus_switch_release(mt9m001);
++eswinit:
++	kfree(mt9m001);
++	return ret;
++}
++
++static int mt9m001_remove(struct i2c_client *client)
++{
++	struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
++
++	soc_camera_device_unregister(&mt9m001->icd);
++	bus_switch_release(mt9m001);
++	kfree(mt9m001);
++
++	return 0;
++}
++
++static struct i2c_driver mt9m001_i2c_driver = {
++	.driver = {
++		.name = "mt9m001",
++	},
++	.probe		= mt9m001_probe,
++	.remove		= mt9m001_remove,
++};
++
++static int __init mt9m001_mod_init(void)
++{
++	return i2c_add_driver(&mt9m001_i2c_driver);
++}
++
++static void __exit mt9m001_mod_exit(void)
++{
++	i2c_del_driver(&mt9m001_i2c_driver);
++}
++
++module_init(mt9m001_mod_init);
++module_exit(mt9m001_mod_exit);
++
++MODULE_DESCRIPTION("Micron MT9M001 Camera driver");
++MODULE_AUTHOR("Guennadi Liakhovetski <kernel at pengutronix.de>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
+new file mode 100644
+index 0000000..d4b9e27
+--- /dev/null
++++ b/drivers/media/video/mt9v022.c
+@@ -0,0 +1,844 @@
++/*
++ * Driver for MT9V022 CMOS Image Sensor from Micron
++ *
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at 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/videodev2.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/log2.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-chip-ident.h>
++#include <media/soc_camera.h>
++
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++#include <asm/gpio.h>
++#endif
++
++/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
++ * The platform has to define i2c_board_info
++ * and call i2c_register_board_info() */
++
++static char *sensor_type;
++module_param(sensor_type, charp, S_IRUGO);
++MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"\n");
++
++/* mt9v022 selected register addresses */
++#define MT9V022_CHIP_VERSION		0x00
++#define MT9V022_COLUMN_START		0x01
++#define MT9V022_ROW_START		0x02
++#define MT9V022_WINDOW_HEIGHT		0x03
++#define MT9V022_WINDOW_WIDTH		0x04
++#define MT9V022_HORIZONTAL_BLANKING	0x05
++#define MT9V022_VERTICAL_BLANKING	0x06
++#define MT9V022_CHIP_CONTROL		0x07
++#define MT9V022_SHUTTER_WIDTH1		0x08
++#define MT9V022_SHUTTER_WIDTH2		0x09
++#define MT9V022_SHUTTER_WIDTH_CTRL	0x0a
++#define MT9V022_TOTAL_SHUTTER_WIDTH	0x0b
++#define MT9V022_RESET			0x0c
++#define MT9V022_READ_MODE		0x0d
++#define MT9V022_MONITOR_MODE		0x0e
++#define MT9V022_PIXEL_OPERATION_MODE	0x0f
++#define MT9V022_LED_OUT_CONTROL		0x1b
++#define MT9V022_ADC_MODE_CONTROL	0x1c
++#define MT9V022_ANALOG_GAIN		0x34
++#define MT9V022_BLACK_LEVEL_CALIB_CTRL	0x47
++#define MT9V022_PIXCLK_FV_LV		0x74
++#define MT9V022_DIGITAL_TEST_PATTERN	0x7f
++#define MT9V022_AEC_AGC_ENABLE		0xAF
++#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH	0xBD
++
++/* Progressive scan, master, defaults */
++#define MT9V022_CHIP_CONTROL_DEFAULT	0x188
++
++static const struct soc_camera_data_format mt9v022_colour_formats[] = {
++	/* Order important: first natively supported,
++	 * second supported with a GPIO extender */
++	{
++		.name		= "Bayer (sRGB) 10 bit",
++		.depth		= 10,
++		.fourcc		= V4L2_PIX_FMT_SBGGR16,
++		.colorspace	= V4L2_COLORSPACE_SRGB,
++	}, {
++		.name		= "Bayer (sRGB) 8 bit",
++		.depth		= 8,
++		.fourcc		= V4L2_PIX_FMT_SBGGR8,
++		.colorspace	= V4L2_COLORSPACE_SRGB,
++	}
++};
++
++static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
++	/* Order important - see above */
++	{
++		.name		= "Monochrome 10 bit",
++		.depth		= 10,
++		.fourcc		= V4L2_PIX_FMT_Y16,
++	}, {
++		.name		= "Monochrome 8 bit",
++		.depth		= 8,
++		.fourcc		= V4L2_PIX_FMT_GREY,
++	},
++};
++
++struct mt9v022 {
++	struct i2c_client *client;
++	struct soc_camera_device icd;
++	int model;	/* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
++	int switch_gpio;
++	u16 chip_control;
++	unsigned char datawidth;
++};
++
++static int reg_read(struct soc_camera_device *icd, const u8 reg)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++	struct i2c_client *client = mt9v022->client;
++	s32 data = i2c_smbus_read_word_data(client, reg);
++	return data < 0 ? data : swab16(data);
++}
++
++static int reg_write(struct soc_camera_device *icd, const u8 reg,
++		     const u16 data)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++	return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data));
++}
++
++static int reg_set(struct soc_camera_device *icd, const u8 reg,
++		   const u16 data)
++{
++	int ret;
++
++	ret = reg_read(icd, reg);
++	if (ret < 0)
++		return ret;
++	return reg_write(icd, reg, ret | data);
++}
++
++static int reg_clear(struct soc_camera_device *icd, const u8 reg,
++		     const u16 data)
++{
++	int ret;
++
++	ret = reg_read(icd, reg);
++	if (ret < 0)
++		return ret;
++	return reg_write(icd, reg, ret & ~data);
++}
++
++static int mt9v022_init(struct soc_camera_device *icd)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++	int ret;
++
++	/* Almost the default mode: master, parallel, simultaneous, and an
++	 * undocumented bit 0x200, which is present in table 7, but not in 8,
++	 * plus snapshot mode to disable scan for now */
++	mt9v022->chip_control |= 0x10;
++	ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
++	if (ret >= 0)
++		reg_write(icd, MT9V022_READ_MODE, 0x300);
++
++	/* All defaults */
++	if (ret >= 0)
++		/* AEC, AGC on */
++		ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
++	if (ret >= 0)
++		/* default - auto */
++		ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0);
++
++	return ret >= 0 ? 0 : -EIO;
++}
++
++static int mt9v022_release(struct soc_camera_device *icd)
++{
++	/* Nothing? */
++	return 0;
++}
++
++static int mt9v022_start_capture(struct soc_camera_device *icd)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++	/* Switch to master "normal" mode */
++	mt9v022->chip_control &= ~0x10;
++	if (reg_write(icd, MT9V022_CHIP_CONTROL,
++		      mt9v022->chip_control) < 0)
++		return -EIO;
++	return 0;
++}
++
++static int mt9v022_stop_capture(struct soc_camera_device *icd)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++	/* Switch to snapshot mode */
++	mt9v022->chip_control |= 0x10;
++	if (reg_write(icd, MT9V022_CHIP_CONTROL,
++		      mt9v022->chip_control) < 0)
++		return -EIO;
++	return 0;
++}
++
++static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl)
++{
++#ifdef CONFIG_MT9V022_PCA9536_SWITCH
++	int ret;
++	unsigned int gpio = icl->gpio;
++
++	if (gpio_is_valid(gpio)) {
++		/* We have a data bus switch. */
++		ret = gpio_request(gpio, "mt9v022");
++		if (ret < 0) {
++			dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio);
++			return ret;
++		}
++
++		ret = gpio_direction_output(gpio, 0);
++		if (ret < 0) {
++			dev_err(&mt9v022->client->dev,
++				"Cannot set GPIO %u to output\n", gpio);
++			gpio_free(gpio);
++			return ret;
++		}
++	}
++
++	mt9v022->switch_gpio = gpio;
++#else
++	mt9v022->switch_gpio = -EINVAL;
++#endif
++	return 0;
++}
++
++static void bus_switch_release(struct mt9v022 *mt9v022)
++{
++#ifdef CONFIG_MT9V022_PCA9536_SWITCH
++	if (gpio_is_valid(mt9v022->switch_gpio))
++		gpio_free(mt9v022->switch_gpio);
++#endif
++}
++
++static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit)
++{
++#ifdef CONFIG_MT9V022_PCA9536_SWITCH
++	if (!gpio_is_valid(mt9v022->switch_gpio))
++		return -ENODEV;
++
++	gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit);
++	return 0;
++#else
++	return -ENODEV;
++#endif
++}
++
++static int bus_switch_possible(struct mt9v022 *mt9v022)
++{
++#ifdef CONFIG_MT9V022_PCA9536_SWITCH
++	return gpio_is_valid(mt9v022->switch_gpio);
++#else
++	return 0;
++#endif
++}
++
++static int mt9v022_set_bus_param(struct soc_camera_device *icd,
++				 unsigned long flags)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++	unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
++	int ret;
++	u16 pixclk = 0;
++
++	/* Only one width bit may be set */
++	if (!is_power_of_2(width_flag))
++		return -EINVAL;
++
++	if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
++	    (mt9v022->datawidth != 9  && (width_flag == SOCAM_DATAWIDTH_9)) ||
++	    (mt9v022->datawidth != 8  && (width_flag == SOCAM_DATAWIDTH_8))) {
++		/* Well, we actually only can do 10 or 8 bits... */
++		if (width_flag == SOCAM_DATAWIDTH_9)
++			return -EINVAL;
++
++		ret = bus_switch_act(mt9v022,
++				     width_flag == SOCAM_DATAWIDTH_8);
++		if (ret < 0)
++			return ret;
++
++		mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
++	}
++
++	if (flags & SOCAM_PCLK_SAMPLE_RISING)
++		pixclk |= 0x10;
++
++	if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH))
++		pixclk |= 0x1;
++
++	if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
++		pixclk |= 0x2;
++
++	ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk);
++	if (ret < 0)
++		return ret;
++
++	if (!(flags & SOCAM_MASTER))
++		mt9v022->chip_control &= ~0x8;
++
++	ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
++	if (ret < 0)
++		return ret;
++
++	dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
++		pixclk, mt9v022->chip_control);
++
++	return 0;
++}
++
++static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++	unsigned int width_flag = SOCAM_DATAWIDTH_10;
++
++	if (bus_switch_possible(mt9v022))
++		width_flag |= SOCAM_DATAWIDTH_8;
++
++	return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
++		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
++		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
++		SOCAM_MASTER | SOCAM_SLAVE |
++		width_flag;
++}
++
++static int mt9v022_set_fmt_cap(struct soc_camera_device *icd,
++		__u32 pixfmt, struct v4l2_rect *rect)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++	int ret;
++
++	/* The caller provides a supported format, as verified per call to
++	 * icd->try_fmt_cap(), datawidth is from our supported format list */
++	switch (pixfmt) {
++	case V4L2_PIX_FMT_GREY:
++	case V4L2_PIX_FMT_Y16:
++		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
++			return -EINVAL;
++		break;
++	case V4L2_PIX_FMT_SBGGR8:
++	case V4L2_PIX_FMT_SBGGR16:
++		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
++			return -EINVAL;
++		break;
++	case 0:
++		/* No format change, only geometry */
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	/* Like in example app. Contradicts the datasheet though */
++	ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
++	if (ret >= 0) {
++		if (ret & 1) /* Autoexposure */
++			ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
++					rect->height + icd->y_skip_top + 43);
++		else
++			ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
++					rect->height + icd->y_skip_top + 43);
++	}
++	/* Setup frame format: defaults apart from width and height */
++	if (ret >= 0)
++		ret = reg_write(icd, MT9V022_COLUMN_START, rect->left);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9V022_ROW_START, rect->top);
++	if (ret >= 0)
++		/* Default 94, Phytec driver says:
++		 * "width + horizontal blank >= 660" */
++		ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING,
++				rect->width > 660 - 43 ? 43 :
++				660 - rect->width);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width);
++	if (ret >= 0)
++		ret = reg_write(icd, MT9V022_WINDOW_HEIGHT,
++				rect->height + icd->y_skip_top);
++
++	if (ret < 0)
++		return ret;
++
++	dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height);
++
++	return 0;
++}
++
++static int mt9v022_try_fmt_cap(struct soc_camera_device *icd,
++			       struct v4l2_format *f)
++{
++	if (f->fmt.pix.height < 32 + icd->y_skip_top)
++		f->fmt.pix.height = 32 + icd->y_skip_top;
++	if (f->fmt.pix.height > 480 + icd->y_skip_top)
++		f->fmt.pix.height = 480 + icd->y_skip_top;
++	if (f->fmt.pix.width < 48)
++		f->fmt.pix.width = 48;
++	if (f->fmt.pix.width > 752)
++		f->fmt.pix.width = 752;
++	f->fmt.pix.width &= ~0x03; /* ? */
++
++	return 0;
++}
++
++static int mt9v022_get_chip_id(struct soc_camera_device *icd,
++			       struct v4l2_chip_ident *id)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++
++	if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
++		return -EINVAL;
++
++	if (id->match_chip != mt9v022->client->addr)
++		return -ENODEV;
++
++	id->ident	= mt9v022->model;
++	id->revision	= 0;
++
++	return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int mt9v022_get_register(struct soc_camera_device *icd,
++				struct v4l2_register *reg)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++
++	if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
++		return -EINVAL;
++
++	if (reg->match_chip != mt9v022->client->addr)
++		return -ENODEV;
++
++	reg->val = reg_read(icd, reg->reg);
++
++	if (reg->val > 0xffff)
++		return -EIO;
++
++	return 0;
++}
++
++static int mt9v022_set_register(struct soc_camera_device *icd,
++				struct v4l2_register *reg)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++
++	if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
++		return -EINVAL;
++
++	if (reg->match_chip != mt9v022->client->addr)
++		return -ENODEV;
++
++	if (reg_write(icd, reg->reg, reg->val) < 0)
++		return -EIO;
++
++	return 0;
++}
++#endif
++
++const struct v4l2_queryctrl mt9v022_controls[] = {
++	{
++		.id		= V4L2_CID_VFLIP,
++		.type		= V4L2_CTRL_TYPE_BOOLEAN,
++		.name		= "Flip Vertically",
++		.minimum	= 0,
++		.maximum	= 1,
++		.step		= 1,
++		.default_value	= 0,
++	}, {
++		.id		= V4L2_CID_HFLIP,
++		.type		= V4L2_CTRL_TYPE_BOOLEAN,
++		.name		= "Flip Horizontally",
++		.minimum	= 0,
++		.maximum	= 1,
++		.step		= 1,
++		.default_value	= 0,
++	}, {
++		.id		= V4L2_CID_GAIN,
++		.type		= V4L2_CTRL_TYPE_INTEGER,
++		.name		= "Analog Gain",
++		.minimum	= 64,
++		.maximum	= 127,
++		.step		= 1,
++		.default_value	= 64,
++		.flags		= V4L2_CTRL_FLAG_SLIDER,
++	}, {
++		.id		= V4L2_CID_EXPOSURE,
++		.type		= V4L2_CTRL_TYPE_INTEGER,
++		.name		= "Exposure",
++		.minimum	= 1,
++		.maximum	= 255,
++		.step		= 1,
++		.default_value	= 255,
++		.flags		= V4L2_CTRL_FLAG_SLIDER,
++	}, {
++		.id		= V4L2_CID_AUTOGAIN,
++		.type		= V4L2_CTRL_TYPE_BOOLEAN,
++		.name		= "Automatic Gain",
++		.minimum	= 0,
++		.maximum	= 1,
++		.step		= 1,
++		.default_value	= 1,
++	}, {
++		.id		= V4L2_CID_EXPOSURE_AUTO,
++		.type		= V4L2_CTRL_TYPE_BOOLEAN,
++		.name		= "Automatic Exposure",
++		.minimum	= 0,
++		.maximum	= 1,
++		.step		= 1,
++		.default_value	= 1,
++	}
++};
++
++static int mt9v022_video_probe(struct soc_camera_device *);
++static void mt9v022_video_remove(struct soc_camera_device *);
++static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
++static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
++
++static struct soc_camera_ops mt9v022_ops = {
++	.owner			= THIS_MODULE,
++	.probe			= mt9v022_video_probe,
++	.remove			= mt9v022_video_remove,
++	.init			= mt9v022_init,
++	.release		= mt9v022_release,
++	.start_capture		= mt9v022_start_capture,
++	.stop_capture		= mt9v022_stop_capture,
++	.set_fmt_cap		= mt9v022_set_fmt_cap,
++	.try_fmt_cap		= mt9v022_try_fmt_cap,
++	.set_bus_param		= mt9v022_set_bus_param,
++	.query_bus_param	= mt9v022_query_bus_param,
++	.controls		= mt9v022_controls,
++	.num_controls		= ARRAY_SIZE(mt9v022_controls),
++	.get_control		= mt9v022_get_control,
++	.set_control		= mt9v022_set_control,
++	.get_chip_id		= mt9v022_get_chip_id,
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++	.get_register		= mt9v022_get_register,
++	.set_register		= mt9v022_set_register,
++#endif
++};
++
++static int mt9v022_get_control(struct soc_camera_device *icd,
++			       struct v4l2_control *ctrl)
++{
++	int data;
++
++	switch (ctrl->id) {
++	case V4L2_CID_VFLIP:
++		data = reg_read(icd, MT9V022_READ_MODE);
++		if (data < 0)
++			return -EIO;
++		ctrl->value = !!(data & 0x10);
++		break;
++	case V4L2_CID_HFLIP:
++		data = reg_read(icd, MT9V022_READ_MODE);
++		if (data < 0)
++			return -EIO;
++		ctrl->value = !!(data & 0x20);
++		break;
++	case V4L2_CID_EXPOSURE_AUTO:
++		data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
++		if (data < 0)
++			return -EIO;
++		ctrl->value = !!(data & 0x1);
++		break;
++	case V4L2_CID_AUTOGAIN:
++		data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
++		if (data < 0)
++			return -EIO;
++		ctrl->value = !!(data & 0x2);
++		break;
++	}
++	return 0;
++}
++
++static int mt9v022_set_control(struct soc_camera_device *icd,
++			       struct v4l2_control *ctrl)
++{
++	int data;
++	const struct v4l2_queryctrl *qctrl;
++
++	qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
++
++	if (!qctrl)
++		return -EINVAL;
++
++	switch (ctrl->id) {
++	case V4L2_CID_VFLIP:
++		if (ctrl->value)
++			data = reg_set(icd, MT9V022_READ_MODE, 0x10);
++		else
++			data = reg_clear(icd, MT9V022_READ_MODE, 0x10);
++		if (data < 0)
++			return -EIO;
++		break;
++	case V4L2_CID_HFLIP:
++		if (ctrl->value)
++			data = reg_set(icd, MT9V022_READ_MODE, 0x20);
++		else
++			data = reg_clear(icd, MT9V022_READ_MODE, 0x20);
++		if (data < 0)
++			return -EIO;
++		break;
++	case V4L2_CID_GAIN:
++		/* mt9v022 has minimum == default */
++		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
++			return -EINVAL;
++		else {
++			unsigned long range = qctrl->maximum - qctrl->minimum;
++			/* Datasheet says 16 to 64. autogain only works properly
++			 * after setting gain to maximum 14. Larger values
++			 * produce "white fly" noise effect. On the whole,
++			 * manually setting analog gain does no good. */
++			unsigned long gain = ((ctrl->value - qctrl->minimum) *
++					      10 + range / 2) / range + 4;
++			if (gain >= 32)
++				gain &= ~1;
++			/* The user wants to set gain manually, hope, she
++			 * knows, what she's doing... Switch AGC off. */
++
++			if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
++				return -EIO;
++
++			dev_info(&icd->dev, "Setting gain from %d to %lu\n",
++				 reg_read(icd, MT9V022_ANALOG_GAIN), gain);
++			if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0)
++				return -EIO;
++			icd->gain = ctrl->value;
++		}
++		break;
++	case V4L2_CID_EXPOSURE:
++		/* mt9v022 has maximum == default */
++		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
++			return -EINVAL;
++		else {
++			unsigned long range = qctrl->maximum - qctrl->minimum;
++			unsigned long shutter = ((ctrl->value - qctrl->minimum) *
++						 479 + range / 2) / range + 1;
++			/* The user wants to set shutter width manually, hope,
++			 * she knows, what she's doing... Switch AEC off. */
++
++			if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
++				return -EIO;
++
++			dev_dbg(&icd->dev, "Shutter width from %d to %lu\n",
++				reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH),
++				shutter);
++			if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
++				      shutter) < 0)
++				return -EIO;
++			icd->exposure = ctrl->value;
++		}
++		break;
++	case V4L2_CID_AUTOGAIN:
++		if (ctrl->value)
++			data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
++		else
++			data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
++		if (data < 0)
++			return -EIO;
++		break;
++	case V4L2_CID_EXPOSURE_AUTO:
++		if (ctrl->value)
++			data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
++		else
++			data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
++		if (data < 0)
++			return -EIO;
++		break;
++	}
++	return 0;
++}
++
++/* Interface active, can use i2c. If it fails, it can indeed mean, that
++ * this wasn't our capture interface, so, we wait for the right one */
++static int mt9v022_video_probe(struct soc_camera_device *icd)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++	s32 data;
++	int ret;
++
++	if (!icd->dev.parent ||
++	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
++		return -ENODEV;
++
++	/* Read out the chip version register */
++	data = reg_read(icd, MT9V022_CHIP_VERSION);
++
++	/* must be 0x1311 or 0x1313 */
++	if (data != 0x1311 && data != 0x1313) {
++		ret = -ENODEV;
++		dev_info(&icd->dev, "No MT9V022 detected, ID register 0x%x\n",
++			 data);
++		goto ei2c;
++	}
++
++	/* Soft reset */
++	ret = reg_write(icd, MT9V022_RESET, 1);
++	if (ret < 0)
++		goto ei2c;
++	/* 15 clock cycles */
++	udelay(200);
++	if (reg_read(icd, MT9V022_RESET)) {
++		dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
++		goto ei2c;
++	}
++
++	/* Set monochrome or colour sensor type */
++	if (sensor_type && (!strcmp("colour", sensor_type) ||
++			    !strcmp("color", sensor_type))) {
++		ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
++		mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
++		icd->formats = mt9v022_colour_formats;
++		if (mt9v022->client->dev.platform_data)
++			icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats);
++		else
++			icd->num_formats = 1;
++	} else {
++		ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
++		mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
++		icd->formats = mt9v022_monochrome_formats;
++		if (mt9v022->client->dev.platform_data)
++			icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats);
++		else
++			icd->num_formats = 1;
++	}
++
++	if (ret >= 0)
++		ret = soc_camera_video_start(icd);
++	if (ret < 0)
++		goto eisis;
++
++	dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
++		 data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
++		 "monochrome" : "colour");
++
++	return 0;
++
++eisis:
++ei2c:
++	return ret;
++}
++
++static void mt9v022_video_remove(struct soc_camera_device *icd)
++{
++	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++
++	dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
++		mt9v022->icd.dev.parent, mt9v022->icd.vdev);
++	soc_camera_video_stop(&mt9v022->icd);
++}
++
++static int mt9v022_probe(struct i2c_client *client)
++{
++	struct mt9v022 *mt9v022;
++	struct soc_camera_device *icd;
++	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
++	struct soc_camera_link *icl = client->dev.platform_data;
++	int ret;
++
++	if (!icl) {
++		dev_err(&client->dev, "MT9V022 driver needs platform data\n");
++		return -EINVAL;
++	}
++
++	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
++		dev_warn(&adapter->dev,
++			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
++		return -EIO;
++	}
++
++	mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL);
++	if (!mt9v022)
++		return -ENOMEM;
++
++	mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
++	mt9v022->client = client;
++	i2c_set_clientdata(client, mt9v022);
++
++	icd = &mt9v022->icd;
++	icd->ops	= &mt9v022_ops;
++	icd->control	= &client->dev;
++	icd->x_min	= 1;
++	icd->y_min	= 4;
++	icd->x_current	= 1;
++	icd->y_current	= 4;
++	icd->width_min	= 48;
++	icd->width_max	= 752;
++	icd->height_min	= 32;
++	icd->height_max	= 480;
++	icd->y_skip_top	= 1;
++	icd->iface	= icl->bus_id;
++	/* Default datawidth - this is the only width this camera (normally)
++	 * supports. It is only with extra logic that it can support
++	 * other widths. Therefore it seems to be a sensible default. */
++	mt9v022->datawidth = 10;
++
++	ret = bus_switch_request(mt9v022, icl);
++	if (ret)
++		goto eswinit;
++
++	ret = soc_camera_device_register(icd);
++	if (ret)
++		goto eisdr;
++
++	return 0;
++
++eisdr:
++	bus_switch_release(mt9v022);
++eswinit:
++	kfree(mt9v022);
++	return ret;
++}
++
++static int mt9v022_remove(struct i2c_client *client)
++{
++	struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
++
++	soc_camera_device_unregister(&mt9v022->icd);
++	bus_switch_release(mt9v022);
++	kfree(mt9v022);
++
++	return 0;
++}
++
++static struct i2c_driver mt9v022_i2c_driver = {
++	.driver = {
++		.name = "mt9v022",
++	},
++	.probe		= mt9v022_probe,
++	.remove		= mt9v022_remove,
++};
++
++static int __init mt9v022_mod_init(void)
++{
++	return i2c_add_driver(&mt9v022_i2c_driver);
++}
++
++static void __exit mt9v022_mod_exit(void)
++{
++	i2c_del_driver(&mt9v022_i2c_driver);
++}
++
++module_init(mt9v022_mod_init);
++module_exit(mt9v022_mod_exit);
++
++MODULE_DESCRIPTION("Micron MT9V022 Camera driver");
++MODULE_AUTHOR("Guennadi Liakhovetski <kernel at pengutronix.de>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
+index cb5a510..f68e91f 100644
+--- a/drivers/media/video/mxb.c
++++ b/drivers/media/video/mxb.c
+@@ -38,7 +38,7 @@
+ #define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
+ 
+ /* global variable */
+-static int mxb_num = 0;
++static int mxb_num;
+ 
+ /* initial frequence the tuner will be tuned to.
+    in verden (lower saxony, germany) 4148 is a
+@@ -47,7 +47,7 @@ static int freq = 4148;
+ module_param(freq, int, 0644);
+ MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+ 
+diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
+index d55d580..eafb0c7 100644
+--- a/drivers/media/video/ov511.c
++++ b/drivers/media/video/ov511.c
+@@ -41,7 +41,6 @@
+ #include <linux/slab.h>
+ #include <linux/ctype.h>
+ #include <linux/pagemap.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <linux/mm.h>
+ #include <linux/device.h>
+@@ -4660,7 +4659,9 @@ static const struct file_operations ov511_fops = {
+ 	.read =		ov51x_v4l1_read,
+ 	.mmap =		ov51x_v4l1_mmap,
+ 	.ioctl =	ov51x_v4l1_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.llseek =	no_llseek,
+ };
+ 
+@@ -5832,7 +5833,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ 		goto error;
+ 
+ 	memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev));
+-	ov->vdev->dev = &dev->dev;
++	ov->vdev->dev = &intf->dev;
+ 	video_set_drvdata(ov->vdev, ov);
+ 
+ 	for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
+diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h
+index 18c6422..1010e51 100644
+--- a/drivers/media/video/ov511.h
++++ b/drivers/media/video/ov511.h
+@@ -12,7 +12,7 @@
+ #ifdef OV511_DEBUG
+ 	#define PDEBUG(level, fmt, args...) \
+ 		if (debug >= (level)) info("[%s:%d] " fmt, \
+-		__FUNCTION__, __LINE__ , ## args)
++		__func__, __LINE__ , ## args)
+ #else
+ 	#define PDEBUG(level, fmt, args...) do {} while(0)
+ #endif
+diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h
+index 50c7763..9afa4fe 100644
+--- a/drivers/media/video/ovcamchip/ovcamchip_priv.h
++++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h
+@@ -24,11 +24,11 @@ extern int ovcamchip_debug;
+ 
+ #define PDEBUG(level, fmt, args...) \
+ 	if (ovcamchip_debug >= (level))	pr_debug("[%s:%d] " fmt "\n", \
+-		__FUNCTION__, __LINE__ , ## args)
++		__func__, __LINE__ , ## args)
+ 
+ #define DDEBUG(level, dev, fmt, args...) \
+ 	if (ovcamchip_debug >= (level))	dev_dbg(dev, "[%s:%d] " fmt "\n", \
+-		__FUNCTION__, __LINE__ , ## args)
++		__func__, __LINE__ , ## args)
+ 
+ /* Number of times to retry chip detection. Increase this if you are getting
+  * "Failed to init camera chip" */
+diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
+index 6820c2a..51b1461 100644
+--- a/drivers/media/video/pms.c
++++ b/drivers/media/video/pms.c
+@@ -57,11 +57,11 @@ struct i2c_info
+ 	u8 hits;
+ };
+ 
+-static int i2c_count 		= 0;
++static int i2c_count;
+ static struct i2c_info i2cinfo[64];
+ 
+ static int decoder 		= PHILIPS2;
+-static int standard 		= 0;	/* 0 - auto 1 - ntsc 2 - pal 3 - secam */
++static int standard;	/* 0 - auto 1 - ntsc 2 - pal 3 - secam */
+ 
+ /*
+  *	I/O ports and Shared Memory
+@@ -885,7 +885,9 @@ static const struct file_operations pms_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl          = pms_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.read           = pms_read,
+ 	.llseek         = no_llseek,
+ };
+diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
+index 6fc1b8b..158b3d0 100644
+--- a/drivers/media/video/pvrusb2/Kconfig
++++ b/drivers/media/video/pvrusb2/Kconfig
+@@ -58,6 +58,31 @@ config VIDEO_PVRUSB2_SYSFS
+ 
+ 	  Note: This feature is experimental and subject to change.
+ 
++config VIDEO_PVRUSB2_DVB
++	bool "pvrusb2 DVB support (EXPERIMENTAL)"
++	default n
++	depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
++	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
++	select DVB_S5H1409 if !DVB_FE_CUSTOMISE
++	select DVB_S5H1411 if !DVB_FE_CUSTOMISE
++	select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
++	select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
++	select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
++	select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
++	---help---
++
++	  This option enables compilation of a DVB interface for the
++	  pvrusb2 driver.  Currently this is very very experimental.
++	  It is also limiting - the DVB interface can only access the
++	  digital side of hybrid devices, and there are going to be
++	  issues if you attempt to mess with the V4L side at the same
++	  time.  Don't turn this on unless you know what you are
++	  doing.
++
++	  If you are in doubt, say N.
++
++	  Note: This feature is very experimental and might break
++
+ config VIDEO_PVRUSB2_DEBUGIFC
+ 	bool "pvrusb2 debug interface"
+ 	depends on VIDEO_PVRUSB2_SYSFS
+diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile
+index 47284e5..5b3083c 100644
+--- a/drivers/media/video/pvrusb2/Makefile
++++ b/drivers/media/video/pvrusb2/Makefile
+@@ -1,5 +1,6 @@
+ obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
+ obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
++obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
+ 
+ pvrusb2-objs	:= pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
+ 		   pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
+@@ -9,6 +10,11 @@ pvrusb2-objs	:= pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
+ 		   pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
+ 		   pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
+ 		   pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
++		   $(obj-pvrusb2-dvb-y) \
+ 		   $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
+ 
+ obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
++
++EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
++EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
+index 9d94aed..b5db6a5 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-context.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-context.c
+@@ -23,40 +23,193 @@
+ #include "pvrusb2-ioread.h"
+ #include "pvrusb2-hdw.h"
+ #include "pvrusb2-debug.h"
++#include <linux/wait.h>
++#include <linux/kthread.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/slab.h>
+-#include <asm/semaphore.h>
++
++static struct pvr2_context *pvr2_context_exist_first;
++static struct pvr2_context *pvr2_context_exist_last;
++static struct pvr2_context *pvr2_context_notify_first;
++static struct pvr2_context *pvr2_context_notify_last;
++static DEFINE_MUTEX(pvr2_context_mutex);
++static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data);
++static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data);
++static int pvr2_context_cleanup_flag;
++static int pvr2_context_cleaned_flag;
++static struct task_struct *pvr2_context_thread_ptr;
++
++
++static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
++{
++	int signal_flag = 0;
++	mutex_lock(&pvr2_context_mutex);
++	if (fl) {
++		if (!mp->notify_flag) {
++			signal_flag = (pvr2_context_notify_first == NULL);
++			mp->notify_prev = pvr2_context_notify_last;
++			mp->notify_next = NULL;
++			pvr2_context_notify_last = mp;
++			if (mp->notify_prev) {
++				mp->notify_prev->notify_next = mp;
++			} else {
++				pvr2_context_notify_first = mp;
++			}
++			mp->notify_flag = !0;
++		}
++	} else {
++		if (mp->notify_flag) {
++			mp->notify_flag = 0;
++			if (mp->notify_next) {
++				mp->notify_next->notify_prev = mp->notify_prev;
++			} else {
++				pvr2_context_notify_last = mp->notify_prev;
++			}
++			if (mp->notify_prev) {
++				mp->notify_prev->notify_next = mp->notify_next;
++			} else {
++				pvr2_context_notify_first = mp->notify_next;
++			}
++		}
++	}
++	mutex_unlock(&pvr2_context_mutex);
++	if (signal_flag) wake_up(&pvr2_context_sync_data);
++}
+ 
+ 
+ static void pvr2_context_destroy(struct pvr2_context *mp)
+ {
+-	pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
++	pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
+ 	if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
++	pvr2_context_set_notify(mp, 0);
++	mutex_lock(&pvr2_context_mutex);
++	if (mp->exist_next) {
++		mp->exist_next->exist_prev = mp->exist_prev;
++	} else {
++		pvr2_context_exist_last = mp->exist_prev;
++	}
++	if (mp->exist_prev) {
++		mp->exist_prev->exist_next = mp->exist_next;
++	} else {
++		pvr2_context_exist_first = mp->exist_next;
++	}
++	if (!pvr2_context_exist_first) {
++		/* Trigger wakeup on control thread in case it is waiting
++		   for an exit condition. */
++		wake_up(&pvr2_context_sync_data);
++	}
++	mutex_unlock(&pvr2_context_mutex);
+ 	kfree(mp);
+ }
+ 
+ 
+-static void pvr2_context_state_check(struct pvr2_context *mp)
++static void pvr2_context_notify(struct pvr2_context *mp)
+ {
+-	if (mp->init_flag) return;
++	pvr2_context_set_notify(mp,!0);
++}
++
+ 
+-	switch (pvr2_hdw_get_state(mp->hdw)) {
+-	case PVR2_STATE_WARM: break;
+-	case PVR2_STATE_ERROR: break;
+-	case PVR2_STATE_READY: break;
+-	case PVR2_STATE_RUN: break;
+-	default: return;
++static void pvr2_context_check(struct pvr2_context *mp)
++{
++	struct pvr2_channel *ch1, *ch2;
++	pvr2_trace(PVR2_TRACE_CTXT,
++		   "pvr2_context %p (notify)", mp);
++	if (!mp->initialized_flag && !mp->disconnect_flag) {
++		mp->initialized_flag = !0;
++		pvr2_trace(PVR2_TRACE_CTXT,
++			   "pvr2_context %p (initialize)", mp);
++		/* Finish hardware initialization */
++		if (pvr2_hdw_initialize(mp->hdw,
++					(void (*)(void *))pvr2_context_notify,
++					mp)) {
++			mp->video_stream.stream =
++				pvr2_hdw_get_video_stream(mp->hdw);
++			/* Trigger interface initialization.  By doing this
++			   here initialization runs in our own safe and
++			   cozy thread context. */
++			if (mp->setup_func) mp->setup_func(mp);
++		} else {
++			pvr2_trace(PVR2_TRACE_CTXT,
++				   "pvr2_context %p (thread skipping setup)",
++				   mp);
++			/* Even though initialization did not succeed,
++			   we're still going to continue anyway.  We need
++			   to do this in order to await the expected
++			   disconnect (which we will detect in the normal
++			   course of operation). */
++		}
+ 	}
+ 
+-	pvr2_context_enter(mp); do {
+-		mp->init_flag = !0;
+-		mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
+-		if (mp->setup_func) {
+-			mp->setup_func(mp);
++	for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
++		ch2 = ch1->mc_next;
++		if (ch1->check_func) ch1->check_func(ch1);
++	}
++
++	if (mp->disconnect_flag && !mp->mc_first) {
++		/* Go away... */
++		pvr2_context_destroy(mp);
++		return;
++	}
++}
++
++
++static int pvr2_context_shutok(void)
++{
++	return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
++}
++
++
++static int pvr2_context_thread_func(void *foo)
++{
++	struct pvr2_context *mp;
++
++	pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
++
++	do {
++		while ((mp = pvr2_context_notify_first) != NULL) {
++			pvr2_context_set_notify(mp, 0);
++			pvr2_context_check(mp);
+ 		}
+-	} while (0); pvr2_context_exit(mp);
+- }
++		wait_event_interruptible(
++			pvr2_context_sync_data,
++			((pvr2_context_notify_first != NULL) ||
++			 pvr2_context_shutok()));
++	} while (!pvr2_context_shutok());
++
++	pvr2_context_cleaned_flag = !0;
++	wake_up(&pvr2_context_cleanup_data);
++
++	pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
++
++	wait_event_interruptible(
++		pvr2_context_sync_data,
++		kthread_should_stop());
++
++	pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
++
++	return 0;
++}
++
++
++int pvr2_context_global_init(void)
++{
++	pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
++					      0,
++					      "pvrusb2-context");
++	return (pvr2_context_thread_ptr ? 0 : -ENOMEM);
++}
++
++
++void pvr2_context_global_done(void)
++{
++	pvr2_context_cleanup_flag = !0;
++	wake_up(&pvr2_context_sync_data);
++	wait_event_interruptible(
++		pvr2_context_cleanup_data,
++		pvr2_context_cleaned_flag);
++	kthread_stop(pvr2_context_thread_ptr);
++}
+ 
+ 
+ struct pvr2_context *pvr2_context_create(
+@@ -67,67 +220,75 @@ struct pvr2_context *pvr2_context_create(
+ 	struct pvr2_context *mp = NULL;
+ 	mp = kzalloc(sizeof(*mp),GFP_KERNEL);
+ 	if (!mp) goto done;
+-	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
++	pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
+ 	mp->setup_func = setup_func;
+ 	mutex_init(&mp->mutex);
++	mutex_lock(&pvr2_context_mutex);
++	mp->exist_prev = pvr2_context_exist_last;
++	mp->exist_next = NULL;
++	pvr2_context_exist_last = mp;
++	if (mp->exist_prev) {
++		mp->exist_prev->exist_next = mp;
++	} else {
++		pvr2_context_exist_first = mp;
++	}
++	mutex_unlock(&pvr2_context_mutex);
+ 	mp->hdw = pvr2_hdw_create(intf,devid);
+ 	if (!mp->hdw) {
+ 		pvr2_context_destroy(mp);
+ 		mp = NULL;
+ 		goto done;
+ 	}
+-	pvr2_hdw_set_state_callback(mp->hdw,
+-				    (void (*)(void *))pvr2_context_state_check,
+-				    mp);
+-	pvr2_context_state_check(mp);
++	pvr2_context_set_notify(mp, !0);
+  done:
+ 	return mp;
+ }
+ 
+ 
+-void pvr2_context_enter(struct pvr2_context *mp)
++static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
++{
++	unsigned int tmsk,mmsk;
++	struct pvr2_channel *cp;
++	struct pvr2_hdw *hdw = mp->hdw;
++	mmsk = pvr2_hdw_get_input_available(hdw);
++	tmsk = mmsk;
++	for (cp = mp->mc_first; cp; cp = cp->mc_next) {
++		if (!cp->input_mask) continue;
++		tmsk &= cp->input_mask;
++	}
++	pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
++	pvr2_hdw_commit_ctl(hdw);
++}
++
++
++static void pvr2_context_enter(struct pvr2_context *mp)
+ {
+ 	mutex_lock(&mp->mutex);
+-	pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
+ }
+ 
+ 
+-void pvr2_context_exit(struct pvr2_context *mp)
++static void pvr2_context_exit(struct pvr2_context *mp)
+ {
+ 	int destroy_flag = 0;
+ 	if (!(mp->mc_first || !mp->disconnect_flag)) {
+ 		destroy_flag = !0;
+ 	}
+-	pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
+ 	mutex_unlock(&mp->mutex);
+-	if (destroy_flag) pvr2_context_destroy(mp);
+-}
+-
+-
+-static void pvr2_context_run_checks(struct pvr2_context *mp)
+-{
+-	struct pvr2_channel *ch1,*ch2;
+-	for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
+-		ch2 = ch1->mc_next;
+-		if (ch1->check_func) {
+-			ch1->check_func(ch1);
+-		}
+-	}
++	if (destroy_flag) pvr2_context_notify(mp);
+ }
+ 
+ 
+ void pvr2_context_disconnect(struct pvr2_context *mp)
+ {
+-	pvr2_context_enter(mp); do {
+-		pvr2_hdw_disconnect(mp->hdw);
+-		mp->disconnect_flag = !0;
+-		pvr2_context_run_checks(mp);
+-	} while (0); pvr2_context_exit(mp);
++	pvr2_hdw_disconnect(mp->hdw);
++	mp->disconnect_flag = !0;
++	pvr2_context_notify(mp);
+ }
+ 
+ 
+ void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
+ {
++	pvr2_context_enter(mp);
+ 	cp->hdw = mp->hdw;
+ 	cp->mc_head = mp;
+ 	cp->mc_next = NULL;
+@@ -138,6 +299,7 @@ void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
+ 		mp->mc_first = cp;
+ 	}
+ 	mp->mc_last = cp;
++	pvr2_context_exit(mp);
+ }
+ 
+ 
+@@ -153,7 +315,10 @@ static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
+ void pvr2_channel_done(struct pvr2_channel *cp)
+ {
+ 	struct pvr2_context *mp = cp->mc_head;
++	pvr2_context_enter(mp);
++	cp->input_mask = 0;
+ 	pvr2_channel_disclaim_stream(cp);
++	pvr2_context_reset_input_limits(mp);
+ 	if (cp->mc_next) {
+ 		cp->mc_next->mc_prev = cp->mc_prev;
+ 	} else {
+@@ -165,6 +330,58 @@ void pvr2_channel_done(struct pvr2_channel *cp)
+ 		mp->mc_first = cp->mc_next;
+ 	}
+ 	cp->hdw = NULL;
++	pvr2_context_exit(mp);
++}
++
++
++int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
++{
++	unsigned int tmsk,mmsk;
++	int ret = 0;
++	struct pvr2_channel *p2;
++	struct pvr2_hdw *hdw = cp->hdw;
++
++	mmsk = pvr2_hdw_get_input_available(hdw);
++	cmsk &= mmsk;
++	if (cmsk == cp->input_mask) {
++		/* No change; nothing to do */
++		return 0;
++	}
++
++	pvr2_context_enter(cp->mc_head);
++	do {
++		if (!cmsk) {
++			cp->input_mask = 0;
++			pvr2_context_reset_input_limits(cp->mc_head);
++			break;
++		}
++		tmsk = mmsk;
++		for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
++			if (p2 == cp) continue;
++			if (!p2->input_mask) continue;
++			tmsk &= p2->input_mask;
++		}
++		if (!(tmsk & cmsk)) {
++			ret = -EPERM;
++			break;
++		}
++		tmsk &= cmsk;
++		if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
++			/* Internal failure changing allowed list; probably
++			   should not happen, but react if it does. */
++			break;
++		}
++		cp->input_mask = cmsk;
++		pvr2_hdw_commit_ctl(hdw);
++	} while (0);
++	pvr2_context_exit(cp->mc_head);
++	return ret;
++}
++
++
++unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
++{
++	return cp->input_mask;
+ }
+ 
+ 
+@@ -174,7 +391,7 @@ int pvr2_channel_claim_stream(struct pvr2_channel *cp,
+ 	int code = 0;
+ 	pvr2_context_enter(cp->mc_head); do {
+ 		if (sp == cp->stream) break;
+-		if (sp->user) {
++		if (sp && sp->user) {
+ 			code = -EBUSY;
+ 			break;
+ 		}
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h
+index a04187a..745e270 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-context.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-context.h
+@@ -30,7 +30,6 @@ struct pvr2_stream;  /* stream interface - defined elsewhere */
+ struct pvr2_context;        /* All central state */
+ struct pvr2_channel;        /* One I/O pathway to a user */
+ struct pvr2_context_stream; /* Wrapper for a stream */
+-struct pvr2_crit_reg;       /* Critical region pointer */
+ struct pvr2_ioread;         /* Low level stream structure */
+ 
+ struct pvr2_context_stream {
+@@ -41,11 +40,16 @@ struct pvr2_context_stream {
+ struct pvr2_context {
+ 	struct pvr2_channel *mc_first;
+ 	struct pvr2_channel *mc_last;
++	struct pvr2_context *exist_next;
++	struct pvr2_context *exist_prev;
++	struct pvr2_context *notify_next;
++	struct pvr2_context *notify_prev;
+ 	struct pvr2_hdw *hdw;
+ 	struct pvr2_context_stream video_stream;
+ 	struct mutex mutex;
++	int notify_flag;
++	int initialized_flag;
+ 	int disconnect_flag;
+-	int init_flag;
+ 
+ 	/* Called after pvr2_context initialization is complete */
+ 	void (*setup_func)(struct pvr2_context *);
+@@ -58,12 +62,10 @@ struct pvr2_channel {
+ 	struct pvr2_channel *mc_prev;
+ 	struct pvr2_context_stream *stream;
+ 	struct pvr2_hdw *hdw;
++	unsigned int input_mask;
+ 	void (*check_func)(struct pvr2_channel *);
+ };
+ 
+-void pvr2_context_enter(struct pvr2_context *);
+-void pvr2_context_exit(struct pvr2_context *);
+-
+ struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
+ 					 const struct usb_device_id *devid,
+ 					 void (*setup_func)(struct pvr2_context *));
+@@ -71,11 +73,15 @@ void pvr2_context_disconnect(struct pvr2_context *);
+ 
+ void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
+ void pvr2_channel_done(struct pvr2_channel *);
++int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int);
++unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *);
+ int pvr2_channel_claim_stream(struct pvr2_channel *,
+ 			      struct pvr2_context_stream *);
+ struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
+ 	struct pvr2_context_stream *);
+ 
++int pvr2_context_global_init(void);
++void pvr2_context_global_done(void);
+ 
+ #endif /* __PVRUSB2_CONTEXT_H */
+ /*
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+index 5a3e8d2..91a42f2 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+@@ -30,6 +30,9 @@ static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
+ {
+ 	if (cptr->info->check_value) {
+ 		if (!cptr->info->check_value(cptr,val)) return -ERANGE;
++	} else if (cptr->info->type == pvr2_ctl_enum) {
++		if (val < 0) return -ERANGE;
++		if (val >= cptr->info->def.type_enum.count) return -ERANGE;
+ 	} else {
+ 		int lim;
+ 		lim = cptr->info->def.type_int.min_value;
+@@ -63,13 +66,10 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
+ 		if (cptr->info->set_value) {
+ 			if (cptr->info->type == pvr2_ctl_bitmask) {
+ 				mask &= cptr->info->def.type_bitmask.valid_bits;
+-			} else if (cptr->info->type == pvr2_ctl_int) {
++			} else if ((cptr->info->type == pvr2_ctl_int)||
++				   (cptr->info->type == pvr2_ctl_enum)) {
+ 				ret = pvr2_ctrl_range_check(cptr,val);
+ 				if (ret < 0) break;
+-			} else if (cptr->info->type == pvr2_ctl_enum) {
+-				if (val >= cptr->info->def.type_enum.count) {
+-					break;
+-				}
+ 			} else if (cptr->info->type != pvr2_ctl_bool) {
+ 				break;
+ 			}
+@@ -204,8 +204,7 @@ int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
+ 		if (cptr->info->type == pvr2_ctl_enum) {
+ 			const char **names;
+ 			names = cptr->info->def.type_enum.value_names;
+-			if ((val >= 0) &&
+-			    (val < cptr->info->def.type_enum.count)) {
++			if (pvr2_ctrl_range_check(cptr,val) == 0) {
+ 				if (names[val]) {
+ 					*blen = scnprintf(
+ 						bptr,bmax,"%s",
+@@ -528,10 +527,8 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
+ 				ptr,len,valptr,
+ 				cptr->info->def.type_enum.value_names,
+ 				cptr->info->def.type_enum.count);
+-			if ((ret >= 0) &&
+-			    ((*valptr < 0) ||
+-			     (*valptr >= cptr->info->def.type_enum.count))) {
+-				ret = -ERANGE;
++			if (ret >= 0) {
++				ret = pvr2_ctrl_range_check(cptr,*valptr);
+ 			}
+ 			if (maskptr) *maskptr = ~0;
+ 		} else if (cptr->info->type == pvr2_ctl_bitmask) {
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+index ffdc45c..97350b0 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+@@ -84,7 +84,9 @@ static const struct routing_scheme_item routing_schemegv[] = {
+ 		.vid = CX25840_COMPOSITE2,
+ 		.aud = CX25840_AUDIO5,
+ 	},
+-	[PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
++	[PVR2_CVAL_INPUT_RADIO] = {
++		/* line-in is used for radio and composite.  A GPIO is
++		   used to switch between the two choices. */
+ 		.vid = CX25840_COMPOSITE1,
+ 		.aud = CX25840_AUDIO_SERIAL,
+ 	},
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h
+index fca49d8..11537dd 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-debug.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-debug.h
+@@ -39,7 +39,7 @@ extern int pvrusb2_debug;
+ #define PVR2_TRACE_EEPROM     (1 << 10) /* eeprom parsing / report */
+ #define PVR2_TRACE_STRUCT     (1 << 11) /* internal struct creation */
+ #define PVR2_TRACE_OPEN_CLOSE (1 << 12) /* application open / close */
+-#define PVR2_TRACE_CREG       (1 << 13) /* Main critical region entry / exit */
++#define PVR2_TRACE_CTXT       (1 << 13) /* Main context tracking */
+ #define PVR2_TRACE_SYSFS      (1 << 14) /* Sysfs driven I/O */
+ #define PVR2_TRACE_FIRMWARE   (1 << 15) /* firmware upload actions */
+ #define PVR2_TRACE_CHIPS      (1 << 16) /* chip broadcast operation */
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+index b068743..b53121c 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+@@ -164,6 +164,8 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
+ 	int ccnt;
+ 	int ret;
+ 	u32 gpio_dir,gpio_in,gpio_out;
++	struct pvr2_stream_stats stats;
++	struct pvr2_stream *sp;
+ 
+ 	ret = pvr2_hdw_is_hsm(hdw);
+ 	ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
+@@ -182,6 +184,24 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
+ 			 pvr2_hdw_get_streaming(hdw) ? "on" : "off");
+ 	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+ 
++
++	sp = pvr2_hdw_get_video_stream(hdw);
++	if (sp) {
++		pvr2_stream_get_stats(sp, &stats, 0);
++		ccnt = scnprintf(
++			buf,acnt,
++			"Bytes streamed=%u"
++			" URBs: queued=%u idle=%u ready=%u"
++			" processed=%u failed=%u\n",
++			stats.bytes_processed,
++			stats.buffers_in_queue,
++			stats.buffers_in_idle,
++			stats.buffers_in_ready,
++			stats.buffers_processed,
++			stats.buffers_failed);
++		bcnt += ccnt; acnt -= ccnt; buf += ccnt;
++	}
++
+ 	return bcnt;
+ }
+ 
+@@ -220,6 +240,10 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
+ 			return pvr2_hdw_cmd_decoder_reset(hdw);
+ 		} else if (debugifc_match_keyword(wptr,wlen,"worker")) {
+ 			return pvr2_hdw_untrip(hdw);
++		} else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
++			pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
++					      NULL, !0);
++			return 0;
+ 		}
+ 		return -EINVAL;
+ 	} else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+index fe9991c..3a141d9 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+@@ -32,7 +32,16 @@ pvr2_device_desc structures.
+ /* This is needed in order to pull in tuner type ids... */
+ #include <linux/i2c.h>
+ #include <media/tuner.h>
+-
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++#include "pvrusb2-hdw-internal.h"
++#include "lgdt330x.h"
++#include "s5h1409.h"
++#include "s5h1411.h"
++#include "tda10048.h"
++#include "tda18271.h"
++#include "tda8290.h"
++#include "tuner-simple.h"
++#endif
+ 
+ 
+ /*------------------------------------------------------------------------*/
+@@ -49,14 +58,19 @@ static const char *pvr2_fw1_names_29xxx[] = {
+ };
+ 
+ static const struct pvr2_device_desc pvr2_device_29xxx = {
+-		.description = "WinTV PVR USB2 Model Category 29xxxx",
++		.description = "WinTV PVR USB2 Model Category 29xxx",
+ 		.shortname = "29xxx",
+ 		.client_modules.lst = pvr2_client_29xxx,
+ 		.client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx),
+ 		.fx2_firmware.lst = pvr2_fw1_names_29xxx,
+ 		.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
+ 		.flag_has_hauppauge_rom = !0,
++		.flag_has_analogtuner = !0,
++		.flag_has_fmradio = !0,
++		.flag_has_composite = !0,
++		.flag_has_svideo = !0,
+ 		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++		.led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+ };
+ 
+ 
+@@ -75,7 +89,7 @@ static const char *pvr2_fw1_names_24xxx[] = {
+ };
+ 
+ static const struct pvr2_device_desc pvr2_device_24xxx = {
+-		.description = "WinTV PVR USB2 Model Category 24xxxx",
++		.description = "WinTV PVR USB2 Model Category 24xxx",
+ 		.shortname = "24xxx",
+ 		.client_modules.lst = pvr2_client_24xxx,
+ 		.client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx),
+@@ -85,7 +99,12 @@ static const struct pvr2_device_desc pvr2_device_24xxx = {
+ 		.flag_has_wm8775 = !0,
+ 		.flag_has_hauppauge_rom = !0,
+ 		.flag_has_hauppauge_custom_ir = !0,
++		.flag_has_analogtuner = !0,
++		.flag_has_fmradio = !0,
++		.flag_has_composite = !0,
++		.flag_has_svideo = !0,
+ 		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++		.led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+ };
+ 
+ 
+@@ -105,6 +124,30 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
+ 		.client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
+ 		.flag_has_cx25840 = !0,
+ 		.default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
++		.flag_has_analogtuner = !0,
++		.flag_has_fmradio = !0,
++		.flag_has_composite = !0,
++		.flag_has_svideo = !0,
++		.signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
++};
++
++
++
++/*------------------------------------------------------------------------*/
++/* GOTVIEW USB2.0 DVD Deluxe */
++
++/* (same module list as gotview_2) */
++
++static const struct pvr2_device_desc pvr2_device_gotview_2d = {
++		.description = "Gotview USB 2.0 DVD Deluxe",
++		.shortname = "gv2d",
++		.client_modules.lst = pvr2_client_gotview_2,
++		.client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
++		.flag_has_cx25840 = !0,
++		.default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
++		.flag_has_analogtuner = !0,
++		.flag_has_composite = !0,
++		.flag_has_svideo = !0,
+ 		.signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
+ };
+ 
+@@ -114,6 +157,38 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
+ /*------------------------------------------------------------------------*/
+ /* OnAir Creator */
+ 
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++static struct lgdt330x_config pvr2_lgdt3303_config = {
++	.demod_address       = 0x0e,
++	.demod_chip          = LGDT3303,
++	.clock_polarity_flip = 1,
++};
++
++static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
++{
++	adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
++			      &adap->channel.hdw->i2c_adap);
++	if (adap->fe)
++		return 0;
++
++	return -EIO;
++}
++
++static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
++{
++	dvb_attach(simple_tuner_attach, adap->fe,
++		   &adap->channel.hdw->i2c_adap, 0x61,
++		   TUNER_LG_TDVS_H06XF);
++
++	return 0;
++}
++
++struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
++	.frontend_attach = pvr2_lgdt3303_attach,
++	.tuner_attach    = pvr2_lgh06xf_attach,
++};
++#endif
++
+ static const char *pvr2_client_onair_creator[] = {
+ 	"saa7115",
+ 	"tuner",
+@@ -126,7 +201,16 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
+ 		.client_modules.lst = pvr2_client_onair_creator,
+ 		.client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator),
+ 		.default_tuner_type = TUNER_LG_TDVS_H06XF,
++		.flag_has_analogtuner = !0,
++		.flag_has_composite = !0,
++		.flag_has_svideo = !0,
++		.flag_digital_requires_cx23416 = !0,
+ 		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++		.digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
++		.default_std_mask = V4L2_STD_NTSC_M,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++		.dvb_props = &pvr2_onair_creator_fe_props,
++#endif
+ };
+ #endif
+ 
+@@ -136,6 +220,37 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
+ /*------------------------------------------------------------------------*/
+ /* OnAir USB 2.0 */
+ 
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++static struct lgdt330x_config pvr2_lgdt3302_config = {
++	.demod_address       = 0x0e,
++	.demod_chip          = LGDT3302,
++};
++
++static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
++{
++	adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
++			      &adap->channel.hdw->i2c_adap);
++	if (adap->fe)
++		return 0;
++
++	return -EIO;
++}
++
++static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
++{
++	dvb_attach(simple_tuner_attach, adap->fe,
++		   &adap->channel.hdw->i2c_adap, 0x61,
++		   TUNER_PHILIPS_FCV1236D);
++
++	return 0;
++}
++
++struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
++	.frontend_attach = pvr2_lgdt3302_attach,
++	.tuner_attach    = pvr2_fcv1236d_attach,
++};
++#endif
++
+ static const char *pvr2_client_onair_usb2[] = {
+ 	"saa7115",
+ 	"tuner",
+@@ -147,8 +262,17 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
+ 		.shortname = "oa2",
+ 		.client_modules.lst = pvr2_client_onair_usb2,
+ 		.client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2),
+-		.default_tuner_type = TUNER_PHILIPS_ATSC,
++		.default_tuner_type = TUNER_PHILIPS_FCV1236D,
++		.flag_has_analogtuner = !0,
++		.flag_has_composite = !0,
++		.flag_has_svideo = !0,
++		.flag_digital_requires_cx23416 = !0,
+ 		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++		.digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
++		.default_std_mask = V4L2_STD_NTSC_M,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++		.dvb_props = &pvr2_onair_usb2_fe_props,
++#endif
+ };
+ #endif
+ 
+@@ -157,6 +281,50 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
+ /*------------------------------------------------------------------------*/
+ /* Hauppauge PVR-USB2 Model 73xxx */
+ 
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++static struct tda10048_config hauppauge_tda10048_config = {
++	.demod_address  = 0x10 >> 1,
++	.output_mode    = TDA10048_PARALLEL_OUTPUT,
++	.fwbulkwritelen = TDA10048_BULKWRITE_50,
++	.inversion      = TDA10048_INVERSION_ON,
++};
++
++static struct tda829x_config tda829x_no_probe = {
++	.probe_tuner = TDA829X_DONT_PROBE,
++};
++
++static struct tda18271_config hauppauge_tda18271_dvb_config = {
++	.gate    = TDA18271_GATE_ANALOG,
++};
++
++static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
++{
++	adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
++			      &adap->channel.hdw->i2c_adap);
++	if (adap->fe)
++		return 0;
++
++	return -EIO;
++}
++
++static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
++{
++	dvb_attach(tda829x_attach, adap->fe,
++		   &adap->channel.hdw->i2c_adap, 0x42,
++		   &tda829x_no_probe);
++	dvb_attach(tda18271_attach, adap->fe, 0x60,
++		   &adap->channel.hdw->i2c_adap,
++		   &hauppauge_tda18271_dvb_config);
++
++	return 0;
++}
++
++struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
++	.frontend_attach = pvr2_tda10048_attach,
++	.tuner_attach    = pvr2_73xxx_tda18271_8295_attach,
++};
++#endif
++
+ static const char *pvr2_client_73xxx[] = {
+ 	"cx25840",
+ 	"tuner",
+@@ -167,7 +335,7 @@ static const char *pvr2_fw1_names_73xxx[] = {
+ };
+ 
+ static const struct pvr2_device_desc pvr2_device_73xxx = {
+-		.description = "WinTV PVR USB2 Model Category 73xxxx",
++		.description = "WinTV PVR USB2 Model Category 73xxx",
+ 		.shortname = "73xxx",
+ 		.client_modules.lst = pvr2_client_73xxx,
+ 		.client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx),
+@@ -175,15 +343,14 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
+ 		.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx),
+ 		.flag_has_cx25840 = !0,
+ 		.flag_has_hauppauge_rom = !0,
+-#if 0
+ 		.flag_has_analogtuner = !0,
+ 		.flag_has_composite = !0,
+ 		.flag_has_svideo = !0,
+ 		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+ 		.digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+ 		.led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+-#else
+-		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++		.dvb_props = &pvr2_73xxx_dvb_props,
+ #endif
+ };
+ 
+@@ -192,6 +359,80 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
+ /*------------------------------------------------------------------------*/
+ /* Hauppauge PVR-USB2 Model 75xxx */
+ 
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++static struct s5h1409_config pvr2_s5h1409_config = {
++	.demod_address = 0x32 >> 1,
++	.output_mode   = S5H1409_PARALLEL_OUTPUT,
++	.gpio          = S5H1409_GPIO_OFF,
++	.qam_if        = 4000,
++	.inversion     = S5H1409_INVERSION_ON,
++	.status_mode   = S5H1409_DEMODLOCKING,
++};
++
++static struct s5h1411_config pvr2_s5h1411_config = {
++	.output_mode   = S5H1411_PARALLEL_OUTPUT,
++	.gpio          = S5H1411_GPIO_OFF,
++	.vsb_if        = S5H1411_IF_44000,
++	.qam_if        = S5H1411_IF_4000,
++	.inversion     = S5H1411_INVERSION_ON,
++	.status_mode   = S5H1411_DEMODLOCKING,
++};
++
++static struct tda18271_std_map hauppauge_tda18271_std_map = {
++	.atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
++		      .if_lvl = 6, .rfagc_top = 0x37, },
++	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
++		      .if_lvl = 6, .rfagc_top = 0x37, },
++};
++
++static struct tda18271_config hauppauge_tda18271_config = {
++	.std_map = &hauppauge_tda18271_std_map,
++	.gate    = TDA18271_GATE_ANALOG,
++};
++
++static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
++{
++	adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
++			      &adap->channel.hdw->i2c_adap);
++	if (adap->fe)
++		return 0;
++
++	return -EIO;
++}
++
++static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
++{
++	adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
++			      &adap->channel.hdw->i2c_adap);
++	if (adap->fe)
++		return 0;
++
++	return -EIO;
++}
++
++static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
++{
++	dvb_attach(tda829x_attach, adap->fe,
++		   &adap->channel.hdw->i2c_adap, 0x42,
++		   &tda829x_no_probe);
++	dvb_attach(tda18271_attach, adap->fe, 0x60,
++		   &adap->channel.hdw->i2c_adap,
++		   &hauppauge_tda18271_config);
++
++	return 0;
++}
++
++struct pvr2_dvb_props pvr2_750xx_dvb_props = {
++	.frontend_attach = pvr2_s5h1409_attach,
++	.tuner_attach    = pvr2_tda18271_8295_attach,
++};
++
++struct pvr2_dvb_props pvr2_751xx_dvb_props = {
++	.frontend_attach = pvr2_s5h1411_attach,
++	.tuner_attach    = pvr2_tda18271_8295_attach,
++};
++#endif
++
+ static const char *pvr2_client_75xxx[] = {
+ 	"cx25840",
+ 	"tuner",
+@@ -201,17 +442,46 @@ static const char *pvr2_fw1_names_75xxx[] = {
+ 		"v4l-pvrusb2-73xxx-01.fw",
+ };
+ 
+-static const struct pvr2_device_desc pvr2_device_75xxx = {
+-		.description = "WinTV PVR USB2 Model Category 75xxxx",
+-		.shortname = "75xxx",
++static const struct pvr2_device_desc pvr2_device_750xx = {
++		.description = "WinTV PVR USB2 Model Category 750xx",
++		.shortname = "750xx",
+ 		.client_modules.lst = pvr2_client_75xxx,
+ 		.client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
+ 		.fx2_firmware.lst = pvr2_fw1_names_75xxx,
+ 		.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
+ 		.flag_has_cx25840 = !0,
+ 		.flag_has_hauppauge_rom = !0,
++		.flag_has_analogtuner = !0,
++		.flag_has_composite = !0,
++		.flag_has_svideo = !0,
+ 		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++		.digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+ 		.default_std_mask = V4L2_STD_NTSC_M,
++		.led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++		.dvb_props = &pvr2_750xx_dvb_props,
++#endif
++};
++
++static const struct pvr2_device_desc pvr2_device_751xx = {
++		.description = "WinTV PVR USB2 Model Category 751xx",
++		.shortname = "751xx",
++		.client_modules.lst = pvr2_client_75xxx,
++		.client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
++		.fx2_firmware.lst = pvr2_fw1_names_75xxx,
++		.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
++		.flag_has_cx25840 = !0,
++		.flag_has_hauppauge_rom = !0,
++		.flag_has_analogtuner = !0,
++		.flag_has_composite = !0,
++		.flag_has_svideo = !0,
++		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++		.digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
++		.default_std_mask = V4L2_STD_NTSC_M,
++		.led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++		.dvb_props = &pvr2_751xx_dvb_props,
++#endif
+ };
+ 
+ 
+@@ -225,6 +495,8 @@ struct usb_device_id pvr2_device_table[] = {
+ 	  .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
+ 	{ USB_DEVICE(0x1164, 0x0622),
+ 	  .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2},
++	{ USB_DEVICE(0x1164, 0x0602),
++	  .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d},
+ #ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
+ 	{ USB_DEVICE(0x11ba, 0x1003),
+ 	  .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator},
+@@ -236,9 +508,9 @@ struct usb_device_id pvr2_device_table[] = {
+ 	{ USB_DEVICE(0x2040, 0x7300),
+ 	  .driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
+ 	{ USB_DEVICE(0x2040, 0x7500),
+-	  .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
++	  .driver_info = (kernel_ulong_t)&pvr2_device_750xx},
+ 	{ USB_DEVICE(0x2040, 0x7501),
+-	  .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
++	  .driver_info = (kernel_ulong_t)&pvr2_device_751xx},
+ 	{ }
+ };
+ 
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+index 64b467f..d016f8b 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+@@ -23,6 +23,9 @@
+ 
+ #include <linux/mod_devicetable.h>
+ #include <linux/videodev2.h>
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++#include "pvrusb2-dvb.h"
++#endif
+ 
+ /*
+ 
+@@ -39,6 +42,13 @@ struct pvr2_string_table {
+ #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
+ #define PVR2_ROUTING_SCHEME_GOTVIEW 1
+ 
++#define PVR2_DIGITAL_SCHEME_NONE 0
++#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
++#define PVR2_DIGITAL_SCHEME_ONAIR 2
++
++#define PVR2_LED_SCHEME_NONE 0
++#define PVR2_LED_SCHEME_HAUPPAUGE 1
++
+ /* This describes a particular hardware type (except for the USB device ID
+    which must live in a separate structure due to environmental
+    constraints).  See the top of pvrusb2-hdw.c for where this is
+@@ -58,40 +68,64 @@ struct pvr2_device_desc {
+ 	   was initialized from internal ROM. */
+ 	struct pvr2_string_table fx2_firmware;
+ 
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++	/* callback functions to handle attachment of digital tuner & demod */
++	struct pvr2_dvb_props *dvb_props;
++
++#endif
++	/* Initial standard bits to use for this device, if not zero.
++	   Anything set here is also implied as an available standard.
++	   Note: This is ignored if overridden on the module load line via
++	   the video_std module option. */
++	v4l2_std_id default_std_mask;
++
++	/* V4L tuner type ID to use with this device (only used if the
++	   driver could not discover the type any other way). */
++	int default_tuner_type;
++
+ 	/* Signal routing scheme used by device, contains one of
+ 	   PVR2_ROUTING_SCHEME_XXX.  Schemes have to be defined as we
+ 	   encounter them.  This is an arbitrary integer scheme id; its
+ 	   meaning is contained entirely within the driver and is
+ 	   interpreted by logic which must send commands to the chip-level
+ 	   drivers (search for things which touch this field). */
+-	unsigned int signal_routing_scheme;
++	unsigned char signal_routing_scheme;
+ 
+-	/* V4L tuner type ID to use with this device (only used if the
+-	   driver could not discover the type any other way). */
+-	int default_tuner_type;
++	/* Indicates scheme for controlling device's LED (if any).  The
++	   driver will turn on the LED when streaming is underway.  This
++	   contains one of PVR2_LED_SCHEME_XXX. */
++	unsigned char led_scheme;
+ 
+-	/* Initial standard bits to use for this device, if not zero.
+-	   Anything set here is also implied as an available standard.
+-	   Note: This is ignored if overridden on the module load line via
+-	   the video_std module option. */
+-	v4l2_std_id default_std_mask;
++	/* Control scheme to use if there is a digital tuner.  This
++	   contains one of PVR2_DIGITAL_SCHEME_XXX.  This is an arbitrary
++	   integer scheme id; its meaning is contained entirely within the
++	   driver and is interpreted by logic which must control the
++	   streaming pathway (search for things which touch this field). */
++	unsigned char digital_control_scheme;
+ 
+ 	/* If set, we don't bother trying to load cx23416 firmware. */
+-	char flag_skip_cx23416_firmware;
++	unsigned int flag_skip_cx23416_firmware:1;
++
++	/* If set, the encoder must be healthy in order for digital mode to
++	   work (otherwise we assume that digital streaming will work even
++	   if we fail to locate firmware for the encoder).  If the device
++	   doesn't support digital streaming then this flag has no
++	   effect. */
++	unsigned int flag_digital_requires_cx23416:1;
+ 
+ 	/* Device has a hauppauge eeprom which we can interrogate. */
+-	char flag_has_hauppauge_rom;
++	unsigned int flag_has_hauppauge_rom:1;
+ 
+ 	/* Device does not require a powerup command to be issued. */
+-	char flag_no_powerup;
++	unsigned int flag_no_powerup:1;
+ 
+ 	/* Device has a cx25840 - this enables special additional logic to
+ 	   handle it. */
+-	char flag_has_cx25840;
++	unsigned int flag_has_cx25840:1;
+ 
+ 	/* Device has a wm8775 - this enables special additional logic to
+ 	   ensure that it is found. */
+-	char flag_has_wm8775;
++	unsigned int flag_has_wm8775:1;
+ 
+ 	/* Device has IR hardware that can be faked into looking like a
+ 	   normal Hauppauge i2c IR receiver.  This is currently very
+@@ -101,7 +135,15 @@ struct pvr2_device_desc {
+ 	   to virtualize the presence of the non-existant IR receiver chip and
+ 	   implement the virtual receiver in terms of appropriate FX2
+ 	   commands. */
+-	char flag_has_hauppauge_custom_ir;
++	unsigned int flag_has_hauppauge_custom_ir:1;
++
++	/* These bits define which kinds of sources the device can handle.
++	   Note: Digital tuner presence is inferred by the
++	   digital_control_scheme enumeration. */
++	unsigned int flag_has_fmradio:1;       /* Has FM radio receiver */
++	unsigned int flag_has_analogtuner:1;   /* Has analog tuner */
++	unsigned int flag_has_composite:1;     /* Has composite input */
++	unsigned int flag_has_svideo:1;        /* Has s-video input */
+ };
+ 
+ extern struct usb_device_id pvr2_device_table[];
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
+new file mode 100644
+index 0000000..2e64f98
+--- /dev/null
++++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
+@@ -0,0 +1,425 @@
++/*
++ *  pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver.
++ *
++ *  Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.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
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public 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/kthread.h>
++#include <linux/freezer.h>
++#include "dvbdev.h"
++#include "pvrusb2-hdw-internal.h"
++#include "pvrusb2-hdw.h"
++#include "pvrusb2-io.h"
++#include "pvrusb2-dvb.h"
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
++static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
++{
++	int ret;
++	unsigned int count;
++	struct pvr2_buffer *bp;
++	struct pvr2_stream *stream;
++
++	printk(KERN_DEBUG "dvb thread started\n");
++	set_freezable();
++
++	stream = adap->channel.stream->stream;
++
++	for (;;) {
++		if (kthread_should_stop()) break;
++
++		/* Not sure about this... */
++		try_to_freeze();
++
++		bp = pvr2_stream_get_ready_buffer(stream);
++		if (bp != NULL) {
++			count = pvr2_buffer_get_count(bp);
++			if (count) {
++				dvb_dmx_swfilter(
++					&adap->demux,
++					adap->buffer_storage[
++					    pvr2_buffer_get_id(bp)],
++					count);
++			} else {
++				ret = pvr2_buffer_get_status(bp);
++				if (ret < 0) break;
++			}
++			ret = pvr2_buffer_queue(bp);
++			if (ret < 0) break;
++
++			/* Since we know we did something to a buffer,
++			   just go back and try again.  No point in
++			   blocking unless we really ran out of
++			   buffers to process. */
++			continue;
++		}
++
++
++		/* Wait until more buffers become available or we're
++		   told not to wait any longer. */
++		ret = wait_event_interruptible(
++		    adap->buffer_wait_data,
++		    (pvr2_stream_get_ready_count(stream) > 0) ||
++		    kthread_should_stop());
++		if (ret < 0) break;
++	}
++
++	/* If we get here and ret is < 0, then an error has occurred.
++	   Probably would be a good idea to communicate that to DVB core... */
++
++	printk(KERN_DEBUG "dvb thread stopped\n");
++
++	return 0;
++}
++
++static int pvr2_dvb_feed_thread(void *data)
++{
++	int stat = pvr2_dvb_feed_func(data);
++	/* from videobuf-dvb.c: */
++	while (!kthread_should_stop()) {
++		set_current_state(TASK_INTERRUPTIBLE);
++		schedule();
++	}
++	return stat;
++}
++
++static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap)
++{
++	wake_up(&adap->buffer_wait_data);
++}
++
++static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap)
++{
++	unsigned int idx;
++	struct pvr2_stream *stream;
++
++	if (adap->thread) {
++		kthread_stop(adap->thread);
++		adap->thread = NULL;
++	}
++
++	if (adap->channel.stream) {
++		stream = adap->channel.stream->stream;
++	} else {
++		stream = NULL;
++	}
++	if (stream) {
++		pvr2_hdw_set_streaming(adap->channel.hdw, 0);
++		pvr2_stream_set_callback(stream, NULL, NULL);
++		pvr2_stream_kill(stream);
++		pvr2_stream_set_buffer_count(stream, 0);
++		pvr2_channel_claim_stream(&adap->channel, NULL);
++	}
++
++	if (adap->stream_run) {
++		for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
++			if (!(adap->buffer_storage[idx])) continue;
++			kfree(adap->buffer_storage[idx]);
++			adap->buffer_storage[idx] = 0;
++		}
++		adap->stream_run = 0;
++	}
++}
++
++static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap)
++{
++	struct pvr2_context *pvr = adap->channel.mc_head;
++	unsigned int idx;
++	int ret;
++	struct pvr2_buffer *bp;
++	struct pvr2_stream *stream = 0;
++
++	if (adap->stream_run) return -EIO;
++
++	ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream);
++	/* somebody else already has the stream */
++	if (ret < 0) return ret;
++
++	stream = adap->channel.stream->stream;
++
++	for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
++		adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE,
++						    GFP_KERNEL);
++		if (!(adap->buffer_storage[idx])) return -ENOMEM;
++	}
++
++	pvr2_stream_set_callback(pvr->video_stream.stream,
++				 (pvr2_stream_callback) pvr2_dvb_notify, adap);
++
++	ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT);
++	if (ret < 0) return ret;
++
++	for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
++		bp = pvr2_stream_get_buffer(stream, idx);
++		pvr2_buffer_set_buffer(bp,
++				       adap->buffer_storage[idx],
++				       PVR2_DVB_BUFFER_SIZE);
++	}
++
++	ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1);
++	if (ret < 0) return ret;
++
++	while ((bp = pvr2_stream_get_idle_buffer(stream)) != 0) {
++		ret = pvr2_buffer_queue(bp);
++		if (ret < 0) return ret;
++	}
++
++	adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb");
++
++	if (IS_ERR(adap->thread)) {
++		ret = PTR_ERR(adap->thread);
++		adap->thread = NULL;
++		return ret;
++	}
++
++	adap->stream_run = !0;
++
++	return 0;
++}
++
++static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap)
++{
++	int ret = pvr2_dvb_stream_do_start(adap);
++	if (ret < 0) pvr2_dvb_stream_end(adap);
++	return ret;
++}
++
++static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
++{
++	struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv;
++	int ret = 0;
++
++	if (adap == NULL) return -ENODEV;
++
++	mutex_lock(&adap->lock);
++	do {
++		if (onoff) {
++			if (!adap->feedcount) {
++				printk(KERN_DEBUG "start feeding\n");
++				ret = pvr2_dvb_stream_start(adap);
++				if (ret < 0) break;
++			}
++			(adap->feedcount)++;
++		} else if (adap->feedcount > 0) {
++			(adap->feedcount)--;
++			if (!adap->feedcount) {
++				printk(KERN_DEBUG "stop feeding\n");
++				pvr2_dvb_stream_end(adap);
++			}
++		}
++	} while (0);
++	mutex_unlock(&adap->lock);
++
++	return ret;
++}
++
++static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
++{
++	printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n",
++	       dvbdmxfeed->pid, dvbdmxfeed->type);
++	return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
++}
++
++static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
++{
++	printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n",
++	       dvbdmxfeed->pid, dvbdmxfeed->type);
++	return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
++}
++
++static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
++{
++	struct pvr2_dvb_adapter *adap = fe->dvb->priv;
++	return pvr2_channel_limit_inputs(
++	    &adap->channel,
++	    (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0));
++}
++
++static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
++{
++	int ret;
++
++	ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
++				   THIS_MODULE/*&hdw->usb_dev->owner*/,
++				   &adap->channel.hdw->usb_dev->dev,
++				   adapter_nr);
++	if (ret < 0) {
++		err("dvb_register_adapter failed: error %d", ret);
++		goto err;
++	}
++	adap->dvb_adap.priv = adap;
++
++	adap->demux.dmx.capabilities = DMX_TS_FILTERING |
++				       DMX_SECTION_FILTERING |
++				       DMX_MEMORY_BASED_FILTERING;
++	adap->demux.priv             = adap;
++	adap->demux.filternum        = 256;
++	adap->demux.feednum          = 256;
++	adap->demux.start_feed       = pvr2_dvb_start_feed;
++	adap->demux.stop_feed        = pvr2_dvb_stop_feed;
++	adap->demux.write_to_decoder = NULL;
++
++	ret = dvb_dmx_init(&adap->demux);
++	if (ret < 0) {
++		err("dvb_dmx_init failed: error %d", ret);
++		goto err_dmx;
++	}
++
++	adap->dmxdev.filternum       = adap->demux.filternum;
++	adap->dmxdev.demux           = &adap->demux.dmx;
++	adap->dmxdev.capabilities    = 0;
++
++	ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
++	if (ret < 0) {
++		err("dvb_dmxdev_init failed: error %d", ret);
++		goto err_dmx_dev;
++	}
++
++	dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
++
++	return 0;
++
++err_dmx_dev:
++	dvb_dmx_release(&adap->demux);
++err_dmx:
++	dvb_unregister_adapter(&adap->dvb_adap);
++err:
++	return ret;
++}
++
++static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
++{
++	printk(KERN_DEBUG "unregistering DVB devices\n");
++	dvb_net_release(&adap->dvb_net);
++	adap->demux.dmx.close(&adap->demux.dmx);
++	dvb_dmxdev_release(&adap->dmxdev);
++	dvb_dmx_release(&adap->demux);
++	dvb_unregister_adapter(&adap->dvb_adap);
++	return 0;
++}
++
++static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
++{
++	struct pvr2_hdw *hdw = adap->channel.hdw;
++	struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
++	int ret = 0;
++
++	if (dvb_props == NULL) {
++		err("fe_props not defined!");
++		return -EINVAL;
++	}
++
++	ret = pvr2_channel_limit_inputs(
++	    &adap->channel,
++	    (1 << PVR2_CVAL_INPUT_DTV));
++	if (ret) {
++		err("failed to grab control of dtv input (code=%d)",
++		    ret);
++		return ret;
++	}
++
++	if (dvb_props->frontend_attach == NULL) {
++		err("frontend_attach not defined!");
++		ret = -EINVAL;
++		goto done;
++	}
++
++	if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
++
++		if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
++			err("frontend registration failed!");
++			dvb_frontend_detach(adap->fe);
++			adap->fe = NULL;
++			ret = -ENODEV;
++			goto done;
++		}
++
++		if (dvb_props->tuner_attach)
++			dvb_props->tuner_attach(adap);
++
++		if (adap->fe->ops.analog_ops.standby)
++			adap->fe->ops.analog_ops.standby(adap->fe);
++
++		/* Ensure all frontends negotiate bus access */
++		adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
++
++	} else {
++		err("no frontend was attached!");
++		ret = -ENODEV;
++		return ret;
++	}
++
++ done:
++	pvr2_channel_limit_inputs(&adap->channel, 0);
++	return ret;
++}
++
++static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
++{
++	if (adap->fe != NULL) {
++		dvb_unregister_frontend(adap->fe);
++		dvb_frontend_detach(adap->fe);
++	}
++	return 0;
++}
++
++static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap)
++{
++	pvr2_dvb_stream_end(adap);
++	pvr2_dvb_frontend_exit(adap);
++	pvr2_dvb_adapter_exit(adap);
++	pvr2_channel_done(&adap->channel);
++	kfree(adap);
++}
++
++static void pvr2_dvb_internal_check(struct pvr2_channel *chp)
++{
++	struct pvr2_dvb_adapter *adap;
++	adap = container_of(chp, struct pvr2_dvb_adapter, channel);
++	if (!adap->channel.mc_head->disconnect_flag) return;
++	pvr2_dvb_destroy(adap);
++}
++
++struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr)
++{
++	int ret = 0;
++	struct pvr2_dvb_adapter *adap;
++	if (!pvr->hdw->hdw_desc->dvb_props) {
++		/* Device lacks a digital interface so don't set up
++		   the DVB side of the driver either.  For now. */
++		return NULL;
++	}
++	adap = kzalloc(sizeof(*adap), GFP_KERNEL);
++	if (!adap) return adap;
++	pvr2_channel_init(&adap->channel, pvr);
++	adap->channel.check_func = pvr2_dvb_internal_check;
++	init_waitqueue_head(&adap->buffer_wait_data);
++	mutex_init(&adap->lock);
++	ret = pvr2_dvb_adapter_init(adap);
++	if (ret < 0) goto fail1;
++	ret = pvr2_dvb_frontend_init(adap);
++	if (ret < 0) goto fail2;
++	return adap;
++
++fail2:
++	pvr2_dvb_adapter_exit(adap);
++fail1:
++	pvr2_channel_done(&adap->channel);
++	return NULL;
++}
++
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h
+new file mode 100644
+index 0000000..884ff91
+--- /dev/null
++++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h
+@@ -0,0 +1,41 @@
++#ifndef __PVRUSB2_DVB_H__
++#define __PVRUSB2_DVB_H__
++
++#include "dvb_frontend.h"
++#include "dvb_demux.h"
++#include "dvb_net.h"
++#include "dmxdev.h"
++#include "pvrusb2-context.h"
++
++#define PVR2_DVB_BUFFER_COUNT 32
++#define PVR2_DVB_BUFFER_SIZE PAGE_ALIGN(0x4000)
++
++struct pvr2_dvb_adapter {
++	struct pvr2_channel	channel;
++
++	struct dvb_adapter	dvb_adap;
++	struct dmxdev		dmxdev;
++	struct dvb_demux	demux;
++	struct dvb_net		dvb_net;
++	struct dvb_frontend	*fe;
++
++	int			feedcount;
++	int			max_feed_count;
++
++	struct task_struct	*thread;
++	struct mutex		lock;
++
++	unsigned int		stream_run:1;
++
++	wait_queue_head_t	buffer_wait_data;
++	char			*buffer_storage[PVR2_DVB_BUFFER_COUNT];
++};
++
++struct pvr2_dvb_props {
++	int (*frontend_attach) (struct pvr2_dvb_adapter *);
++	int (*tuner_attach) (struct pvr2_dvb_adapter *);
++};
++
++struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr);
++
++#endif /* __PVRUSB2_DVB_H__ */
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+index 6406287..c46d367 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+@@ -278,11 +278,20 @@ static int pvr2_encoder_cmd(void *ctxt,
+ 			ret = -EBUSY;
+ 		}
+ 		if (ret) {
++			del_timer_sync(&hdw->encoder_run_timer);
+ 			hdw->state_encoder_ok = 0;
+ 			pvr2_trace(PVR2_TRACE_STBITS,
+ 				   "State bit %s <-- %s",
+ 				   "state_encoder_ok",
+ 				   (hdw->state_encoder_ok ? "true" : "false"));
++			if (hdw->state_encoder_runok) {
++				hdw->state_encoder_runok = 0;
++				pvr2_trace(PVR2_TRACE_STBITS,
++				   "State bit %s <-- %s",
++					   "state_encoder_runok",
++					   (hdw->state_encoder_runok ?
++					    "true" : "false"));
++			}
+ 			pvr2_trace(
+ 				PVR2_TRACE_ERROR_LEGS,
+ 				"Giving up on command."
+@@ -480,10 +489,6 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw)
+ 	/* unmask some interrupts */
+ 	pvr2_write_register(hdw, 0x0048, 0xbfffffff);
+ 
+-	/* change some GPIO data */
+-	pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
+-	pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
+-
+ 	pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
+ 			  hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
+ 
+@@ -526,12 +531,6 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
+ 		break;
+ 	}
+ 
+-	/* change some GPIO data */
+-	/* Note: Bit d7 of dir appears to control the LED.  So we shut it
+-	   off here. */
+-	pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
+-	pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
+-
+ 	return status;
+ }
+ 
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
+index ffbc6d0..abaada3 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
+@@ -22,32 +22,41 @@
+ #ifndef _PVRUSB2_FX2_CMD_H_
+ #define _PVRUSB2_FX2_CMD_H_
+ 
+-#define FX2CMD_MEM_WRITE_DWORD  0x01
+-#define FX2CMD_MEM_READ_DWORD   0x02
++#define FX2CMD_MEM_WRITE_DWORD  0x01u
++#define FX2CMD_MEM_READ_DWORD   0x02u
+ 
+-#define FX2CMD_MEM_READ_64BYTES 0x28
++#define FX2CMD_MEM_READ_64BYTES 0x28u
+ 
+-#define FX2CMD_REG_WRITE        0x04
+-#define FX2CMD_REG_READ         0x05
+-#define FX2CMD_MEMSEL           0x06
++#define FX2CMD_REG_WRITE        0x04u
++#define FX2CMD_REG_READ         0x05u
++#define FX2CMD_MEMSEL           0x06u
+ 
+-#define FX2CMD_I2C_WRITE        0x08
+-#define FX2CMD_I2C_READ         0x09
++#define FX2CMD_I2C_WRITE        0x08u
++#define FX2CMD_I2C_READ         0x09u
+ 
+-#define FX2CMD_GET_USB_SPEED    0x0b
++#define FX2CMD_GET_USB_SPEED    0x0bu
+ 
+-#define FX2CMD_STREAMING_ON     0x36
+-#define FX2CMD_STREAMING_OFF    0x37
++#define FX2CMD_STREAMING_ON     0x36u
++#define FX2CMD_STREAMING_OFF    0x37u
+ 
+-#define FX2CMD_FWPOST1          0x52
++#define FX2CMD_FWPOST1          0x52u
+ 
+-#define FX2CMD_POWER_OFF        0xdc
+-#define FX2CMD_POWER_ON         0xde
++#define FX2CMD_POWER_OFF        0xdcu
++#define FX2CMD_POWER_ON         0xdeu
+ 
+-#define FX2CMD_DEEP_RESET       0xdd
++#define FX2CMD_DEEP_RESET       0xddu
+ 
+-#define FX2CMD_GET_EEPROM_ADDR  0xeb
+-#define FX2CMD_GET_IR_CODE      0xec
++#define FX2CMD_GET_EEPROM_ADDR  0xebu
++#define FX2CMD_GET_IR_CODE      0xecu
++
++#define FX2CMD_HCW_DEMOD_RESETIN       0xf0u
++#define FX2CMD_HCW_DTV_STREAMING_ON    0xf1u
++#define FX2CMD_HCW_DTV_STREAMING_OFF   0xf2u
++
++#define FX2CMD_ONAIR_DTV_STREAMING_ON  0xa0u
++#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1u
++#define FX2CMD_ONAIR_DTV_POWER_ON      0xa2u
++#define FX2CMD_ONAIR_DTV_POWER_OFF     0xa3u
+ 
+ #endif /* _PVRUSB2_FX2_CMD_H_ */
+ 
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+index d7a216b..a3fe251 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+@@ -163,6 +163,11 @@ struct pvr2_decoder_ctrl {
+ #define FW1_STATE_RELOAD 3
+ #define FW1_STATE_OK 4
+ 
++/* What state the device is in if it is a hybrid */
++#define PVR2_PATHWAY_UNKNOWN 0
++#define PVR2_PATHWAY_ANALOG 1
++#define PVR2_PATHWAY_DIGITAL 2
++
+ typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
+ #define PVR2_I2C_FUNC_CNT 128
+ 
+@@ -182,7 +187,6 @@ struct pvr2_hdw {
+ 	struct workqueue_struct *workqueue;
+ 	struct work_struct workpoll;     /* Update driver state */
+ 	struct work_struct worki2csync;  /* Update i2c clients */
+-	struct work_struct workinit;     /* Driver initialization sequence */
+ 
+ 	/* Video spigot */
+ 	struct pvr2_stream *vid_stream;
+@@ -229,17 +233,19 @@ struct pvr2_hdw {
+ 
+ 	/* Bits of state that describe what is going on with various parts
+ 	   of the driver. */
++	int state_pathway_ok;         /* Pathway config is ok */
+ 	int state_encoder_ok;         /* Encoder is operational */
+ 	int state_encoder_run;        /* Encoder is running */
+ 	int state_encoder_config;     /* Encoder is configured */
+ 	int state_encoder_waitok;     /* Encoder pre-wait done */
++	int state_encoder_runok;      /* Encoder has run for >= .25 sec */
+ 	int state_decoder_run;        /* Decoder is running */
+ 	int state_usbstream_run;      /* FX2 is streaming */
+ 	int state_decoder_quiescent;  /* Decoder idle for > 50msec */
+ 	int state_pipeline_config;    /* Pipeline is configured */
+-	int state_pipeline_req;                /* Somebody wants to stream */
+-	int state_pipeline_pause;              /* Pipeline must be paused */
+-	int state_pipeline_idle;               /* Pipeline not running */
++	int state_pipeline_req;       /* Somebody wants to stream */
++	int state_pipeline_pause;     /* Pipeline must be paused */
++	int state_pipeline_idle;      /* Pipeline not running */
+ 
+ 	/* This is the master state of the driver.  It is the combined
+ 	   result of other bits of state.  Examining this will indicate the
+@@ -247,6 +253,9 @@ struct pvr2_hdw {
+ 	   PVR2_STATE_xxxx */
+ 	unsigned int master_state;
+ 
++	/* True if device led is currently on */
++	int led_on;
++
+ 	/* True if states must be re-evaluated */
+ 	int state_stale;
+ 
+@@ -259,6 +268,9 @@ struct pvr2_hdw {
+ 	/* Timer for measuring encoder pre-wait time */
+ 	struct timer_list encoder_wait_timer;
+ 
++	/* Timer for measuring encoder minimum run time */
++	struct timer_list encoder_run_timer;
++
+ 	/* Place to block while waiting for state changes */
+ 	wait_queue_head_t state_wait_data;
+ 
+@@ -267,6 +279,7 @@ struct pvr2_hdw {
+ 	int flag_disconnected;  /* flag_ok == 0 due to disconnect */
+ 	int flag_init_ok;       /* true if structure is fully initialized */
+ 	int fw1_state;          /* current situation with fw1 */
++	int pathway_state;      /* one of PVR2_PATHWAY_xxx */
+ 	int flag_decoder_missed;/* We've noticed missing decoder */
+ 	int flag_tripped;       /* Indicates overall failure to start */
+ 
+@@ -323,6 +336,11 @@ struct pvr2_hdw {
+ 	int v4l_minor_number_vbi;
+ 	int v4l_minor_number_radio;
+ 
++	/* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */
++	unsigned int input_avail_mask;
++	/* Bit mask of PVR2_CVAL_INPUT choices which are currenly allowed */
++	unsigned int input_allowed_mask;
++
+ 	/* Location of eeprom or a negative number if none */
+ 	int eeprom_addr;
+ 
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+index d6955fa..0a86888 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+@@ -25,7 +25,6 @@
+ #include <linux/firmware.h>
+ #include <linux/videodev2.h>
+ #include <media/v4l2-common.h>
+-#include <asm/semaphore.h>
+ #include "pvrusb2.h"
+ #include "pvrusb2-std.h"
+ #include "pvrusb2-util.h"
+@@ -44,13 +43,13 @@
+ static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
+ static DEFINE_MUTEX(pvr2_unit_mtx);
+ 
+-static int ctlchg = 0;
++static int ctlchg;
+ static int initusbreset = 1;
+-static int procreload = 0;
++static int procreload;
+ static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
+ static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+ static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+-static int init_pause_msec = 0;
++static int init_pause_msec;
+ 
+ module_param(ctlchg, int, S_IRUGO|S_IWUSR);
+ MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
+@@ -183,6 +182,7 @@ static const char *control_values_srate[] = {
+ 
+ static const char *control_values_input[] = {
+ 	[PVR2_CVAL_INPUT_TV]        = "television",  /*xawtv needs this name*/
++	[PVR2_CVAL_INPUT_DTV]       = "dtv",
+ 	[PVR2_CVAL_INPUT_RADIO]     = "radio",
+ 	[PVR2_CVAL_INPUT_SVIDEO]    = "s-video",
+ 	[PVR2_CVAL_INPUT_COMPOSITE] = "composite",
+@@ -216,12 +216,45 @@ static const char *pvr2_state_names[] = {
+ };
+ 
+ 
++struct pvr2_fx2cmd_descdef {
++	unsigned char id;
++	unsigned char *desc;
++};
++
++static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = {
++	{FX2CMD_MEM_WRITE_DWORD, "write encoder dword"},
++	{FX2CMD_MEM_READ_DWORD, "read encoder dword"},
++	{FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"},
++	{FX2CMD_REG_WRITE, "write encoder register"},
++	{FX2CMD_REG_READ, "read encoder register"},
++	{FX2CMD_MEMSEL, "encoder memsel"},
++	{FX2CMD_I2C_WRITE, "i2c write"},
++	{FX2CMD_I2C_READ, "i2c read"},
++	{FX2CMD_GET_USB_SPEED, "get USB speed"},
++	{FX2CMD_STREAMING_ON, "stream on"},
++	{FX2CMD_STREAMING_OFF, "stream off"},
++	{FX2CMD_FWPOST1, "fwpost1"},
++	{FX2CMD_POWER_OFF, "power off"},
++	{FX2CMD_POWER_ON, "power on"},
++	{FX2CMD_DEEP_RESET, "deep reset"},
++	{FX2CMD_GET_EEPROM_ADDR, "get rom addr"},
++	{FX2CMD_GET_IR_CODE, "get IR code"},
++	{FX2CMD_HCW_DEMOD_RESETIN, "hcw demod resetin"},
++	{FX2CMD_HCW_DTV_STREAMING_ON, "hcw dtv stream on"},
++	{FX2CMD_HCW_DTV_STREAMING_OFF, "hcw dtv stream off"},
++	{FX2CMD_ONAIR_DTV_STREAMING_ON, "onair dtv stream on"},
++	{FX2CMD_ONAIR_DTV_STREAMING_OFF, "onair dtv stream off"},
++	{FX2CMD_ONAIR_DTV_POWER_ON, "onair dtv power on"},
++	{FX2CMD_ONAIR_DTV_POWER_OFF, "onair dtv power off"},
++};
++
++
++static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v);
+ static void pvr2_hdw_state_sched(struct pvr2_hdw *);
+ static int pvr2_hdw_state_eval(struct pvr2_hdw *);
+ static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
+ static void pvr2_hdw_worker_i2c(struct work_struct *work);
+ static void pvr2_hdw_worker_poll(struct work_struct *work);
+-static void pvr2_hdw_worker_init(struct work_struct *work);
+ static int pvr2_hdw_wait(struct pvr2_hdw *,int state);
+ static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *);
+ static void pvr2_hdw_state_log_state(struct pvr2_hdw *);
+@@ -232,6 +265,8 @@ static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
+ static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
+ static void pvr2_hdw_quiescent_timeout(unsigned long);
+ static void pvr2_hdw_encoder_wait_timeout(unsigned long);
++static void pvr2_hdw_encoder_run_timeout(unsigned long);
++static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32);
+ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
+ 				unsigned int timeout,int probe_fl,
+ 				void *write_data,unsigned int write_len,
+@@ -368,26 +403,14 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp)
+ 	return 0;
+ }
+ 
+-static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
++static int ctrl_check_input(struct pvr2_ctrl *cptr,int v)
+ {
+-	struct pvr2_hdw *hdw = cptr->hdw;
+-
+-	if (hdw->input_val != v) {
+-		hdw->input_val = v;
+-		hdw->input_dirty = !0;
+-	}
++	return ((1 << v) & cptr->hdw->input_allowed_mask) != 0;
++}
+ 
+-	/* Handle side effects - if we switch to a mode that needs the RF
+-	   tuner, then select the right frequency choice as well and mark
+-	   it dirty. */
+-	if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+-		hdw->freqSelector = 0;
+-		hdw->freqDirty = !0;
+-	} else if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
+-		hdw->freqSelector = 1;
+-		hdw->freqDirty = !0;
+-	}
+-	return 0;
++static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
++{
++	return pvr2_hdw_set_input(cptr->hdw,v);
+ }
+ 
+ static int ctrl_isdirty_input(struct pvr2_ctrl *cptr)
+@@ -804,6 +827,7 @@ static const struct pvr2_ctl_info control_defs[] = {
+ 		.name = "input",
+ 		.internal_id = PVR2_CID_INPUT,
+ 		.default_value = PVR2_CVAL_INPUT_TV,
++		.check_value = ctrl_check_input,
+ 		DEFREF(input),
+ 		DEFENUM(control_values_input),
+ 	},{
+@@ -983,7 +1007,7 @@ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
+ 
+ /* Set the currently tuned frequency and account for all possible
+    driver-core side effects of this action. */
+-void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
++static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
+ {
+ 	if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+ 		if (hdw->freqSelector) {
+@@ -1196,6 +1220,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ 	   time we configure the encoder, then we'll fully configure it. */
+ 	hdw->enc_cur_valid = 0;
+ 
++	/* Encoder is about to be reset so note that as far as we're
++	   concerned now, the encoder has never been run. */
++	del_timer_sync(&hdw->encoder_run_timer);
++	if (hdw->state_encoder_runok) {
++		hdw->state_encoder_runok = 0;
++		trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
++	}
++
+ 	/* First prepare firmware loading */
+ 	ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
+ 	ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
+@@ -1213,19 +1245,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ 	ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
+ 	ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
+ 	ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
+-	LOCK_TAKE(hdw->ctl_lock); do {
+-		hdw->cmd_buffer[0] = FX2CMD_FWPOST1;
+-		ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+-		hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
+-		hdw->cmd_buffer[1] = 0;
+-		ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
+-	} while (0); LOCK_GIVE(hdw->ctl_lock);
++	ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1);
++	ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
+ 
+ 	if (ret) {
+ 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ 			   "firmware2 upload prep failed, ret=%d",ret);
+ 		release_firmware(fw_entry);
+-		return ret;
++		goto done;
+ 	}
+ 
+ 	/* Now send firmware */
+@@ -1238,7 +1265,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ 			   " must be a multiple of %zu bytes",
+ 			   fw_files[fwidx],sizeof(u32));
+ 		release_firmware(fw_entry);
+-		return -1;
++		ret = -EINVAL;
++		goto done;
+ 	}
+ 
+ 	fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
+@@ -1246,7 +1274,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ 		release_firmware(fw_entry);
+ 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ 			   "failed to allocate memory for firmware2 upload");
+-		return -ENOMEM;
++		ret = -ENOMEM;
++		goto done;
+ 	}
+ 
+ 	pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
+@@ -1277,23 +1306,27 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ 	if (ret) {
+ 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ 			   "firmware2 upload transfer failure");
+-		return ret;
++		goto done;
+ 	}
+ 
+ 	/* Finish upload */
+ 
+ 	ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
+ 	ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
+-	LOCK_TAKE(hdw->ctl_lock); do {
+-		hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
+-		hdw->cmd_buffer[1] = 0;
+-		ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
+-	} while (0); LOCK_GIVE(hdw->ctl_lock);
++	ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
+ 
+ 	if (ret) {
+ 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ 			   "firmware2 upload post-proc failure");
+ 	}
++
++ done:
++	if (hdw->hdw_desc->signal_routing_scheme ==
++	    PVR2_ROUTING_SCHEME_GOTVIEW) {
++		/* Ensure that GPIO 11 is set to output for GOTVIEW
++		   hardware. */
++		pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
++	}
+ 	return ret;
+ }
+ 
+@@ -1365,11 +1398,6 @@ int pvr2_hdw_untrip(struct pvr2_hdw *hdw)
+ }
+ 
+ 
+-const char *pvr2_hdw_get_state_name(unsigned int id)
+-{
+-	if (id >= ARRAY_SIZE(pvr2_state_names)) return NULL;
+-	return pvr2_state_names[id];
+-}
+ 
+ 
+ int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
+@@ -1496,7 +1524,7 @@ struct pvr2_std_hack {
+    default - which can always be overridden explicitly - and if the user
+    has otherwise named a default then that default will always be used in
+    place of this table. */
+-const static struct pvr2_std_hack std_eeprom_maps[] = {
++static const struct pvr2_std_hack std_eeprom_maps[] = {
+ 	{	/* PAL(B/G) */
+ 		.pat = V4L2_STD_B|V4L2_STD_GH,
+ 		.std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G,
+@@ -1713,6 +1741,13 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
+ 
+ 	if (!pvr2_hdw_dev_ok(hdw)) return;
+ 
++	if (hdw->hdw_desc->signal_routing_scheme ==
++	    PVR2_ROUTING_SCHEME_GOTVIEW) {
++		/* Ensure that GPIO 11 is set to output for GOTVIEW
++		   hardware. */
++		pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
++	}
++
+ 	pvr2_hdw_commit_setup(hdw);
+ 
+ 	hdw->vid_stream = pvr2_stream_create();
+@@ -1806,12 +1841,37 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw)
+ }
+ 
+ 
+-/* Create and return a structure for interacting with the underlying
+-   hardware */
++/* Perform second stage initialization.  Set callback pointer first so that
++   we can avoid a possible initialization race (if the kernel thread runs
++   before the callback has been set). */
++int pvr2_hdw_initialize(struct pvr2_hdw *hdw,
++			void (*callback_func)(void *),
++			void *callback_data)
++{
++	LOCK_TAKE(hdw->big_lock); do {
++		if (hdw->flag_disconnected) {
++			/* Handle a race here: If we're already
++			   disconnected by this point, then give up.  If we
++			   get past this then we'll remain connected for
++			   the duration of initialization since the entire
++			   initialization sequence is now protected by the
++			   big_lock. */
++			break;
++		}
++		hdw->state_data = callback_data;
++		hdw->state_func = callback_func;
++		pvr2_hdw_setup(hdw);
++	} while (0); LOCK_GIVE(hdw->big_lock);
++	return hdw->flag_init_ok;
++}
++
++
++/* Create, set up, and return a structure for interacting with the
++   underlying hardware.  */
+ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ 				 const struct usb_device_id *devid)
+ {
+-	unsigned int idx,cnt1,cnt2;
++	unsigned int idx,cnt1,cnt2,m;
+ 	struct pvr2_hdw *hdw;
+ 	int valid_std_mask;
+ 	struct pvr2_ctrl *cptr;
+@@ -1835,6 +1895,10 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ 	hdw->encoder_wait_timer.data = (unsigned long)hdw;
+ 	hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
+ 
++	init_timer(&hdw->encoder_run_timer);
++	hdw->encoder_run_timer.data = (unsigned long)hdw;
++	hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout;
++
+ 	hdw->master_state = PVR2_STATE_DEAD;
+ 
+ 	init_waitqueue_head(&hdw->state_wait_data);
+@@ -1842,6 +1906,26 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ 	hdw->tuner_signal_stale = !0;
+ 	cx2341x_fill_defaults(&hdw->enc_ctl_state);
+ 
++	/* Calculate which inputs are OK */
++	m = 0;
++	if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV;
++	if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) {
++		m |= 1 << PVR2_CVAL_INPUT_DTV;
++	}
++	if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO;
++	if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE;
++	if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO;
++	hdw->input_avail_mask = m;
++	hdw->input_allowed_mask = hdw->input_avail_mask;
++
++	/* If not a hybrid device, pathway_state never changes.  So
++	   initialize it here to what it should forever be. */
++	if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) {
++		hdw->pathway_state = PVR2_PATHWAY_ANALOG;
++	} else if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) {
++		hdw->pathway_state = PVR2_PATHWAY_DIGITAL;
++	}
++
+ 	hdw->control_cnt = CTRLDEF_COUNT;
+ 	hdw->control_cnt += MPEGDEF_COUNT;
+ 	hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
+@@ -1859,6 +1943,15 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ 		cptr = hdw->controls + idx;
+ 		cptr->info = control_defs+idx;
+ 	}
++
++	/* Ensure that default input choice is a valid one. */
++	m = hdw->input_avail_mask;
++	if (m) for (idx = 0; idx < (sizeof(m) << 3); idx++) {
++		if (!((1 << idx) & m)) continue;
++		hdw->input_val = idx;
++		break;
++	}
++
+ 	/* Define and configure additional controls from cx2341x module. */
+ 	hdw->mpeg_ctrl_info = kzalloc(
+ 		sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
+@@ -1982,7 +2075,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ 	hdw->workqueue = create_singlethread_workqueue(hdw->name);
+ 	INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
+ 	INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c);
+-	INIT_WORK(&hdw->workinit,pvr2_hdw_worker_init);
+ 
+ 	pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
+ 		   hdw->unit_number,hdw->name);
+@@ -2004,11 +2096,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ 	mutex_init(&hdw->ctl_lock_mutex);
+ 	mutex_init(&hdw->big_lock_mutex);
+ 
+-	queue_work(hdw->workqueue,&hdw->workinit);
+ 	return hdw;
+  fail:
+ 	if (hdw) {
+ 		del_timer_sync(&hdw->quiescent_timer);
++		del_timer_sync(&hdw->encoder_run_timer);
+ 		del_timer_sync(&hdw->encoder_wait_timer);
+ 		if (hdw->workqueue) {
+ 			flush_workqueue(hdw->workqueue);
+@@ -2065,13 +2157,14 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
+ {
+ 	if (!hdw) return;
+ 	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
+-	del_timer_sync(&hdw->quiescent_timer);
+-	del_timer_sync(&hdw->encoder_wait_timer);
+ 	if (hdw->workqueue) {
+ 		flush_workqueue(hdw->workqueue);
+ 		destroy_workqueue(hdw->workqueue);
+ 		hdw->workqueue = NULL;
+ 	}
++	del_timer_sync(&hdw->quiescent_timer);
++	del_timer_sync(&hdw->encoder_run_timer);
++	del_timer_sync(&hdw->encoder_wait_timer);
+ 	if (hdw->fw_buffer) {
+ 		kfree(hdw->fw_buffer);
+ 		hdw->fw_buffer = NULL;
+@@ -2353,6 +2446,18 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
+ 		}
+ 	}
+ 
++	if (hdw->input_dirty && hdw->state_pathway_ok &&
++	    (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
++	      PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
++	     hdw->pathway_state)) {
++		/* Change of mode being asked for... */
++		hdw->state_pathway_ok = 0;
++		trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
++	}
++	if (!hdw->state_pathway_ok) {
++		/* Can't commit anything until pathway is ok. */
++		return 0;
++	}
+ 	/* If any of the below has changed, then we can't do the update
+ 	   while the pipeline is running.  Pipeline must be paused first
+ 	   and decoder -> encoder connection be made quiescent before we
+@@ -2406,12 +2511,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
+ 		hdw->active_stream_type = hdw->desired_stream_type;
+ 	}
+ 
++	if (hdw->hdw_desc->signal_routing_scheme ==
++	    PVR2_ROUTING_SCHEME_GOTVIEW) {
++		u32 b;
++		/* Handle GOTVIEW audio switching */
++		pvr2_hdw_gpio_get_out(hdw,&b);
++		if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
++			/* Set GPIO 11 */
++			pvr2_hdw_gpio_chg_out(hdw,(1 << 11),~0);
++		} else {
++			/* Clear GPIO 11 */
++			pvr2_hdw_gpio_chg_out(hdw,(1 << 11),0);
++		}
++	}
++
+ 	/* Now execute i2c core update */
+ 	pvr2_i2c_core_sync(hdw);
+ 
+-	if (hdw->state_encoder_run) {
+-		/* If encoder isn't running, then this will get worked out
+-		   later when we start the encoder. */
++	if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) &&
++	    hdw->state_encoder_run) {
++		/* If encoder isn't running or it can't be touched, then
++		   this will get worked out later when we start the
++		   encoder. */
+ 		if (pvr2_encoder_adjust(hdw) < 0) return !0;
+ 	}
+ 
+@@ -2454,15 +2575,6 @@ static void pvr2_hdw_worker_poll(struct work_struct *work)
+ }
+ 
+ 
+-static void pvr2_hdw_worker_init(struct work_struct *work)
+-{
+-	struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workinit);
+-	LOCK_TAKE(hdw->big_lock); do {
+-		pvr2_hdw_setup(hdw);
+-	} while (0); LOCK_GIVE(hdw->big_lock);
+-}
+-
+-
+ static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
+ {
+ 	return wait_event_interruptible(
+@@ -2472,17 +2584,6 @@ static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
+ }
+ 
+ 
+-void pvr2_hdw_set_state_callback(struct pvr2_hdw *hdw,
+-				 void (*callback_func)(void *),
+-				 void *callback_data)
+-{
+-	LOCK_TAKE(hdw->big_lock); do {
+-		hdw->state_data = callback_data;
+-		hdw->state_func = callback_func;
+-	} while (0); LOCK_GIVE(hdw->big_lock);
+-}
+-
+-
+ /* Return name for this driver instance */
+ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
+ {
+@@ -3051,6 +3152,67 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
+ 				    read_data,read_len);
+ }
+ 
++
++static int pvr2_issue_simple_cmd(struct pvr2_hdw *hdw,u32 cmdcode)
++{
++	int ret;
++	unsigned int cnt = 1;
++	unsigned int args = 0;
++	LOCK_TAKE(hdw->ctl_lock);
++	hdw->cmd_buffer[0] = cmdcode & 0xffu;
++	args = (cmdcode >> 8) & 0xffu;
++	args = (args > 2) ? 2 : args;
++	if (args) {
++		cnt += args;
++		hdw->cmd_buffer[1] = (cmdcode >> 16) & 0xffu;
++		if (args > 1) {
++			hdw->cmd_buffer[2] = (cmdcode >> 24) & 0xffu;
++		}
++	}
++	if (pvrusb2_debug & PVR2_TRACE_INIT) {
++		unsigned int idx;
++		unsigned int ccnt,bcnt;
++		char tbuf[50];
++		cmdcode &= 0xffu;
++		bcnt = 0;
++		ccnt = scnprintf(tbuf+bcnt,
++				 sizeof(tbuf)-bcnt,
++				 "Sending FX2 command 0x%x",cmdcode);
++		bcnt += ccnt;
++		for (idx = 0; idx < ARRAY_SIZE(pvr2_fx2cmd_desc); idx++) {
++			if (pvr2_fx2cmd_desc[idx].id == cmdcode) {
++				ccnt = scnprintf(tbuf+bcnt,
++						 sizeof(tbuf)-bcnt,
++						 " \"%s\"",
++						 pvr2_fx2cmd_desc[idx].desc);
++				bcnt += ccnt;
++				break;
++			}
++		}
++		if (args) {
++			ccnt = scnprintf(tbuf+bcnt,
++					 sizeof(tbuf)-bcnt,
++					 " (%u",hdw->cmd_buffer[1]);
++			bcnt += ccnt;
++			if (args > 1) {
++				ccnt = scnprintf(tbuf+bcnt,
++						 sizeof(tbuf)-bcnt,
++						 ",%u",hdw->cmd_buffer[2]);
++				bcnt += ccnt;
++			}
++			ccnt = scnprintf(tbuf+bcnt,
++					 sizeof(tbuf)-bcnt,
++					 ")");
++			bcnt += ccnt;
++		}
++		pvr2_trace(PVR2_TRACE_INIT,"%.*s",bcnt,tbuf);
++	}
++	ret = pvr2_send_request(hdw,hdw->cmd_buffer,cnt,NULL,0);
++	LOCK_GIVE(hdw->ctl_lock);
++	return ret;
++}
++
++
+ int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
+ {
+ 	int ret;
+@@ -3158,25 +3320,19 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
+ 
+ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
+ {
+-	int status;
+-	LOCK_TAKE(hdw->ctl_lock); do {
+-		pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
+-		hdw->cmd_buffer[0] = FX2CMD_DEEP_RESET;
+-		status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+-	} while (0); LOCK_GIVE(hdw->ctl_lock);
+-	return status;
++	return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET);
+ }
+ 
+ 
+ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
+ {
+-	int status;
+-	LOCK_TAKE(hdw->ctl_lock); do {
+-		pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
+-		hdw->cmd_buffer[0] = FX2CMD_POWER_ON;
+-		status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+-	} while (0); LOCK_GIVE(hdw->ctl_lock);
+-	return status;
++	return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON);
++}
++
++
++int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw)
++{
++	return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_OFF);
+ }
+ 
+ 
+@@ -3201,16 +3357,173 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
+ }
+ 
+ 
++static int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff)
++{
++	hdw->flag_ok = !0;
++	return pvr2_issue_simple_cmd(hdw,
++				     FX2CMD_HCW_DEMOD_RESETIN |
++				     (1 << 8) |
++				     ((onoff ? 1 : 0) << 16));
++}
++
++
++static int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff)
++{
++	hdw->flag_ok = !0;
++	return pvr2_issue_simple_cmd(hdw,(onoff ?
++					  FX2CMD_ONAIR_DTV_POWER_ON :
++					  FX2CMD_ONAIR_DTV_POWER_OFF));
++}
++
++
++static int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw,
++						int onoff)
++{
++	return pvr2_issue_simple_cmd(hdw,(onoff ?
++					  FX2CMD_ONAIR_DTV_STREAMING_ON :
++					  FX2CMD_ONAIR_DTV_STREAMING_OFF));
++}
++
++
++static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
++{
++	int cmode;
++	/* Compare digital/analog desired setting with current setting.  If
++	   they don't match, fix it... */
++	cmode = (digitalFl ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG);
++	if (cmode == hdw->pathway_state) {
++		/* They match; nothing to do */
++		return;
++	}
++
++	switch (hdw->hdw_desc->digital_control_scheme) {
++	case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
++		pvr2_hdw_cmd_hcw_demod_reset(hdw,digitalFl);
++		if (cmode == PVR2_PATHWAY_ANALOG) {
++			/* If moving to analog mode, also force the decoder
++			   to reset.  If no decoder is attached, then it's
++			   ok to ignore this because if/when the decoder
++			   attaches, it will reset itself at that time. */
++			pvr2_hdw_cmd_decoder_reset(hdw);
++		}
++		break;
++	case PVR2_DIGITAL_SCHEME_ONAIR:
++		/* Supposedly we should always have the power on whether in
++		   digital or analog mode.  But for now do what appears to
++		   work... */
++		pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl);
++		break;
++	default: break;
++	}
++
++	pvr2_hdw_untrip_unlocked(hdw);
++	hdw->pathway_state = cmode;
++}
++
++
++void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff)
++{
++	/* change some GPIO data
++	 *
++	 * note: bit d7 of dir appears to control the LED,
++	 * so we shut it off here.
++	 *
++	 */
++	if (onoff) {
++		pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000481);
++	} else {
++		pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000401);
++	}
++	pvr2_hdw_gpio_chg_out(hdw, 0xffffffff, 0x00000000);
++}
++
++
++typedef void (*led_method_func)(struct pvr2_hdw *,int);
++
++static led_method_func led_methods[] = {
++	[PVR2_LED_SCHEME_HAUPPAUGE] = pvr2_led_ctrl_hauppauge,
++};
++
++
++/* Toggle LED */
++static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff)
++{
++	unsigned int scheme_id;
++	led_method_func fp;
++
++	if ((!onoff) == (!hdw->led_on)) return;
++
++	hdw->led_on = onoff != 0;
++
++	scheme_id = hdw->hdw_desc->led_scheme;
++	if (scheme_id < ARRAY_SIZE(led_methods)) {
++		fp = led_methods[scheme_id];
++	} else {
++		fp = NULL;
++	}
++
++	if (fp) (*fp)(hdw,onoff);
++}
++
++
+ /* Stop / start video stream transport */
+ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
+ {
+-	int status;
+-	LOCK_TAKE(hdw->ctl_lock); do {
+-		hdw->cmd_buffer[0] =
+-			(runFl ? FX2CMD_STREAMING_ON : FX2CMD_STREAMING_OFF);
+-		status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+-	} while (0); LOCK_GIVE(hdw->ctl_lock);
+-	return status;
++	int ret;
++
++	/* If we're in analog mode, then just issue the usual analog
++	   command. */
++	if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
++		return pvr2_issue_simple_cmd(hdw,
++					     (runFl ?
++					      FX2CMD_STREAMING_ON :
++					      FX2CMD_STREAMING_OFF));
++		/*Note: Not reached */
++	}
++
++	if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) {
++		/* Whoops, we don't know what mode we're in... */
++		return -EINVAL;
++	}
++
++	/* To get here we have to be in digital mode.  The mechanism here
++	   is unfortunately different for different vendors.  So we switch
++	   on the device's digital scheme attribute in order to figure out
++	   what to do. */
++	switch (hdw->hdw_desc->digital_control_scheme) {
++	case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
++		return pvr2_issue_simple_cmd(hdw,
++					     (runFl ?
++					      FX2CMD_HCW_DTV_STREAMING_ON :
++					      FX2CMD_HCW_DTV_STREAMING_OFF));
++	case PVR2_DIGITAL_SCHEME_ONAIR:
++		ret = pvr2_issue_simple_cmd(hdw,
++					    (runFl ?
++					     FX2CMD_STREAMING_ON :
++					     FX2CMD_STREAMING_OFF));
++		if (ret) return ret;
++		return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl);
++	default:
++		return -EINVAL;
++	}
++}
++
++
++/* Evaluate whether or not state_pathway_ok can change */
++static int state_eval_pathway_ok(struct pvr2_hdw *hdw)
++{
++	if (hdw->state_pathway_ok) {
++		/* Nothing to do if pathway is already ok */
++		return 0;
++	}
++	if (!hdw->state_pipeline_idle) {
++		/* Not allowed to change anything if pipeline is not idle */
++		return 0;
++	}
++	pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV);
++	hdw->state_pathway_ok = !0;
++	trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
++	return !0;
+ }
+ 
+ 
+@@ -3223,6 +3536,12 @@ static int state_eval_encoder_ok(struct pvr2_hdw *hdw)
+ 	if (hdw->state_encoder_config) return 0;
+ 	if (hdw->state_decoder_run) return 0;
+ 	if (hdw->state_usbstream_run) return 0;
++	if (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) {
++		if (!hdw->hdw_desc->flag_digital_requires_cx23416) return 0;
++	} else if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) {
++		return 0;
++	}
++
+ 	if (pvr2_upload_firmware2(hdw) < 0) {
+ 		hdw->flag_tripped = !0;
+ 		trace_stbit("flag_tripped",hdw->flag_tripped);
+@@ -3248,7 +3567,9 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
+ 		/* paranoia - solve race if timer just completed */
+ 		del_timer_sync(&hdw->encoder_wait_timer);
+ 	} else {
+-		if (!hdw->state_encoder_ok ||
++		if (!hdw->state_pathway_ok ||
++		    (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
++		    !hdw->state_encoder_ok ||
+ 		    !hdw->state_pipeline_idle ||
+ 		    hdw->state_pipeline_pause ||
+ 		    !hdw->state_pipeline_req ||
+@@ -3297,20 +3618,116 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
+ }
+ 
+ 
++/* Return true if the encoder should not be running. */
++static int state_check_disable_encoder_run(struct pvr2_hdw *hdw)
++{
++	if (!hdw->state_encoder_ok) {
++		/* Encoder isn't healthy at the moment, so stop it. */
++		return !0;
++	}
++	if (!hdw->state_pathway_ok) {
++		/* Mode is not understood at the moment (i.e. it wants to
++		   change), so encoder must be stopped. */
++		return !0;
++	}
++
++	switch (hdw->pathway_state) {
++	case PVR2_PATHWAY_ANALOG:
++		if (!hdw->state_decoder_run) {
++			/* We're in analog mode and the decoder is not
++			   running; thus the encoder should be stopped as
++			   well. */
++			return !0;
++		}
++		break;
++	case PVR2_PATHWAY_DIGITAL:
++		if (hdw->state_encoder_runok) {
++			/* This is a funny case.  We're in digital mode so
++			   really the encoder should be stopped.  However
++			   if it really is running, only kill it after
++			   runok has been set.  This gives a chance for the
++			   onair quirk to function (encoder must run
++			   briefly first, at least once, before onair
++			   digital streaming can work). */
++			return !0;
++		}
++		break;
++	default:
++		/* Unknown mode; so encoder should be stopped. */
++		return !0;
++	}
++
++	/* If we get here, we haven't found a reason to stop the
++	   encoder. */
++	return 0;
++}
++
++
++/* Return true if the encoder should be running. */
++static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
++{
++	if (!hdw->state_encoder_ok) {
++		/* Don't run the encoder if it isn't healthy... */
++		return 0;
++	}
++	if (!hdw->state_pathway_ok) {
++		/* Don't run the encoder if we don't (yet) know what mode
++		   we need to be in... */
++		return 0;
++	}
++
++	switch (hdw->pathway_state) {
++	case PVR2_PATHWAY_ANALOG:
++		if (hdw->state_decoder_run) {
++			/* In analog mode, if the decoder is running, then
++			   run the encoder. */
++			return !0;
++		}
++		break;
++	case PVR2_PATHWAY_DIGITAL:
++		if ((hdw->hdw_desc->digital_control_scheme ==
++		     PVR2_DIGITAL_SCHEME_ONAIR) &&
++		    !hdw->state_encoder_runok) {
++			/* This is a quirk.  OnAir hardware won't stream
++			   digital until the encoder has been run at least
++			   once, for a minimal period of time (empiricially
++			   measured to be 1/4 second).  So if we're on
++			   OnAir hardware and the encoder has never been
++			   run at all, then start the encoder.  Normal
++			   state machine logic in the driver will
++			   automatically handle the remaining bits. */
++			return !0;
++		}
++		break;
++	default:
++		/* For completeness (unknown mode; encoder won't run ever) */
++		break;
++	}
++	/* If we get here, then we haven't found any reason to run the
++	   encoder, so don't run it. */
++	return 0;
++}
++
++
+ /* Evaluate whether or not state_encoder_run can change */
+ static int state_eval_encoder_run(struct pvr2_hdw *hdw)
+ {
+ 	if (hdw->state_encoder_run) {
++		if (!state_check_disable_encoder_run(hdw)) return 0;
+ 		if (hdw->state_encoder_ok) {
+-			if (hdw->state_decoder_run) return 0;
++			del_timer_sync(&hdw->encoder_run_timer);
+ 			if (pvr2_encoder_stop(hdw) < 0) return !0;
+ 		}
+ 		hdw->state_encoder_run = 0;
+ 	} else {
+-		if (!hdw->state_encoder_ok) return 0;
+-		if (!hdw->state_decoder_run) return 0;
++		if (!state_check_enable_encoder_run(hdw)) return 0;
+ 		if (pvr2_encoder_start(hdw) < 0) return !0;
+ 		hdw->state_encoder_run = !0;
++		if (!hdw->state_encoder_runok) {
++			hdw->encoder_run_timer.expires =
++				jiffies + (HZ*250/1000);
++			add_timer(&hdw->encoder_run_timer);
++		}
+ 	}
+ 	trace_stbit("state_encoder_run",hdw->state_encoder_run);
+ 	return !0;
+@@ -3339,13 +3756,27 @@ static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
+ }
+ 
+ 
++/* Timeout function for encoder run timer. */
++static void pvr2_hdw_encoder_run_timeout(unsigned long data)
++{
++	struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
++	if (!hdw->state_encoder_runok) {
++		hdw->state_encoder_runok = !0;
++		trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
++		hdw->state_stale = !0;
++		queue_work(hdw->workqueue,&hdw->workpoll);
++	}
++}
++
++
+ /* Evaluate whether or not state_decoder_run can change */
+ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
+ {
+ 	if (hdw->state_decoder_run) {
+ 		if (hdw->state_encoder_ok) {
+ 			if (hdw->state_pipeline_req &&
+-			    !hdw->state_pipeline_pause) return 0;
++			    !hdw->state_pipeline_pause &&
++			    hdw->state_pathway_ok) return 0;
+ 		}
+ 		if (!hdw->flag_decoder_missed) {
+ 			pvr2_decoder_enable(hdw,0);
+@@ -3378,7 +3809,9 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
+ 			   hopefully further stabilize the encoder. */
+ 			return 0;
+ 		}
+-		if (!hdw->state_pipeline_req ||
++		if (!hdw->state_pathway_ok ||
++		    (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
++		    !hdw->state_pipeline_req ||
+ 		    hdw->state_pipeline_pause ||
+ 		    !hdw->state_pipeline_config ||
+ 		    !hdw->state_encoder_config ||
+@@ -3399,16 +3832,43 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
+ static int state_eval_usbstream_run(struct pvr2_hdw *hdw)
+ {
+ 	if (hdw->state_usbstream_run) {
+-		if (hdw->state_encoder_ok) {
+-			if (hdw->state_encoder_run) return 0;
++		int fl = !0;
++		if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
++			fl = (hdw->state_encoder_ok &&
++			      hdw->state_encoder_run);
++		} else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
++			   (hdw->hdw_desc->flag_digital_requires_cx23416)) {
++			fl = hdw->state_encoder_ok;
++		}
++		if (fl &&
++		    hdw->state_pipeline_req &&
++		    !hdw->state_pipeline_pause &&
++		    hdw->state_pathway_ok) {
++			return 0;
+ 		}
+ 		pvr2_hdw_cmd_usbstream(hdw,0);
+ 		hdw->state_usbstream_run = 0;
+ 	} else {
+-		if (!hdw->state_encoder_ok ||
+-		    !hdw->state_encoder_run ||
+-		    !hdw->state_pipeline_req ||
+-		    hdw->state_pipeline_pause) return 0;
++		if (!hdw->state_pipeline_req ||
++		    hdw->state_pipeline_pause ||
++		    !hdw->state_pathway_ok) return 0;
++		if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
++			if (!hdw->state_encoder_ok ||
++			    !hdw->state_encoder_run) return 0;
++		} else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
++			   (hdw->hdw_desc->flag_digital_requires_cx23416)) {
++			if (!hdw->state_encoder_ok) return 0;
++			if (hdw->state_encoder_run) return 0;
++			if (hdw->hdw_desc->digital_control_scheme ==
++			    PVR2_DIGITAL_SCHEME_ONAIR) {
++				/* OnAir digital receivers won't stream
++				   unless the analog encoder has run first.
++				   Why?  I have no idea.  But don't even
++				   try until we know the analog side is
++				   known to have run. */
++				if (!hdw->state_encoder_runok) return 0;
++			}
++		}
+ 		if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0;
+ 		hdw->state_usbstream_run = !0;
+ 	}
+@@ -3454,7 +3914,8 @@ static int state_update_pipeline_state(struct pvr2_hdw *hdw)
+ typedef int (*state_eval_func)(struct pvr2_hdw *);
+ 
+ /* Set of functions to be run to evaluate various states in the driver. */
+-const static state_eval_func eval_funcs[] = {
++static const state_eval_func eval_funcs[] = {
++	state_eval_pathway_ok,
+ 	state_eval_pipeline_config,
+ 	state_eval_encoder_ok,
+ 	state_eval_encoder_config,
+@@ -3502,6 +3963,34 @@ static int pvr2_hdw_state_update(struct pvr2_hdw *hdw)
+ }
+ 
+ 
++static unsigned int print_input_mask(unsigned int msk,
++				     char *buf,unsigned int acnt)
++{
++	unsigned int idx,ccnt;
++	unsigned int tcnt = 0;
++	for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) {
++		if (!((1 << idx) & msk)) continue;
++		ccnt = scnprintf(buf+tcnt,
++				 acnt-tcnt,
++				 "%s%s",
++				 (tcnt ? ", " : ""),
++				 control_values_input[idx]);
++		tcnt += ccnt;
++	}
++	return tcnt;
++}
++
++
++static const char *pvr2_pathway_state_name(int id)
++{
++	switch (id) {
++	case PVR2_PATHWAY_ANALOG: return "analog";
++	case PVR2_PATHWAY_DIGITAL: return "digital";
++	default: return "unknown";
++	}
++}
++
++
+ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
+ 					     char *buf,unsigned int acnt)
+ {
+@@ -3509,13 +3998,15 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
+ 	case 0:
+ 		return scnprintf(
+ 			buf,acnt,
+-			"driver:%s%s%s%s%s",
++			"driver:%s%s%s%s%s <mode=%s>",
+ 			(hdw->flag_ok ? " <ok>" : " <fail>"),
+ 			(hdw->flag_init_ok ? " <init>" : " <uninitialized>"),
+ 			(hdw->flag_disconnected ? " <disconnected>" :
+ 			 " <connected>"),
+ 			(hdw->flag_tripped ? " <tripped>" : ""),
+-			(hdw->flag_decoder_missed ? " <no decoder>" : ""));
++			(hdw->flag_decoder_missed ? " <no decoder>" : ""),
++			pvr2_pathway_state_name(hdw->pathway_state));
++
+ 	case 1:
+ 		return scnprintf(
+ 			buf,acnt,
+@@ -3528,7 +4019,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
+ 	case 2:
+ 		return scnprintf(
+ 			buf,acnt,
+-			"worker:%s%s%s%s%s%s",
++			"worker:%s%s%s%s%s%s%s",
+ 			(hdw->state_decoder_run ?
+ 			 " <decode:run>" :
+ 			 (hdw->state_decoder_quiescent ?
+@@ -3538,20 +4029,65 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
+ 			(hdw->state_encoder_ok ?
+ 			 "" : " <encode:init>"),
+ 			(hdw->state_encoder_run ?
+-			 " <encode:run>" : " <encode:stop>"),
++			 (hdw->state_encoder_runok ?
++			  " <encode:run>" :
++			  " <encode:firstrun>") :
++			 (hdw->state_encoder_runok ?
++			  " <encode:stop>" :
++			  " <encode:virgin>")),
+ 			(hdw->state_encoder_config ?
+ 			 " <encode:configok>" :
+ 			 (hdw->state_encoder_waitok ?
+-			  "" : " <encode:wait>")),
++			  "" : " <encode:waitok>")),
+ 			(hdw->state_usbstream_run ?
+-			 " <usb:run>" : " <usb:stop>"));
+-		break;
++			 " <usb:run>" : " <usb:stop>"),
++			(hdw->state_pathway_ok ?
++			 " <pathway:ok>" : ""));
+ 	case 3:
+ 		return scnprintf(
+ 			buf,acnt,
+ 			"state: %s",
+ 			pvr2_get_state_name(hdw->master_state));
+-		break;
++	case 4: {
++		unsigned int tcnt = 0;
++		unsigned int ccnt;
++
++		ccnt = scnprintf(buf,
++				 acnt,
++				 "Hardware supported inputs: ");
++		tcnt += ccnt;
++		tcnt += print_input_mask(hdw->input_avail_mask,
++					 buf+tcnt,
++					 acnt-tcnt);
++		if (hdw->input_avail_mask != hdw->input_allowed_mask) {
++			ccnt = scnprintf(buf+tcnt,
++					 acnt-tcnt,
++					 "; allowed inputs: ");
++			tcnt += ccnt;
++			tcnt += print_input_mask(hdw->input_allowed_mask,
++						 buf+tcnt,
++						 acnt-tcnt);
++		}
++		return tcnt;
++	}
++	case 5: {
++		struct pvr2_stream_stats stats;
++		if (!hdw->vid_stream) break;
++		pvr2_stream_get_stats(hdw->vid_stream,
++				      &stats,
++				      0);
++		return scnprintf(
++			buf,acnt,
++			"Bytes streamed=%u"
++			" URBs: queued=%u idle=%u ready=%u"
++			" processed=%u failed=%u",
++			stats.bytes_processed,
++			stats.buffers_in_queue,
++			stats.buffers_in_idle,
++			stats.buffers_in_ready,
++			stats.buffers_processed,
++			stats.buffers_failed);
++	}
+ 	default: break;
+ 	}
+ 	return 0;
+@@ -3597,6 +4133,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
+ 	unsigned int st;
+ 	int state_updated = 0;
+ 	int callback_flag = 0;
++	int analog_mode;
+ 
+ 	pvr2_trace(PVR2_TRACE_STBITS,
+ 		   "Drive state check START");
+@@ -3607,18 +4144,23 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
+ 	/* Process all state and get back over disposition */
+ 	state_updated = pvr2_hdw_state_update(hdw);
+ 
++	analog_mode = (hdw->pathway_state != PVR2_PATHWAY_DIGITAL);
++
+ 	/* Update master state based upon all other states. */
+ 	if (!hdw->flag_ok) {
+ 		st = PVR2_STATE_DEAD;
+ 	} else if (hdw->fw1_state != FW1_STATE_OK) {
+ 		st = PVR2_STATE_COLD;
+-	} else if (!hdw->state_encoder_ok) {
++	} else if ((analog_mode ||
++		    hdw->hdw_desc->flag_digital_requires_cx23416) &&
++		   !hdw->state_encoder_ok) {
+ 		st = PVR2_STATE_WARM;
+-	} else if (hdw->flag_tripped || hdw->flag_decoder_missed) {
++	} else if (hdw->flag_tripped ||
++		   (analog_mode && hdw->flag_decoder_missed)) {
+ 		st = PVR2_STATE_ERROR;
+-	} else if (hdw->state_encoder_run &&
+-		   hdw->state_decoder_run &&
+-		   hdw->state_usbstream_run) {
++	} else if (hdw->state_usbstream_run &&
++		   (!analog_mode ||
++		    (hdw->state_encoder_run && hdw->state_decoder_run))) {
+ 		st = PVR2_STATE_RUN;
+ 	} else {
+ 		st = PVR2_STATE_READY;
+@@ -3628,6 +4170,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
+ 			   "Device state change from %s to %s",
+ 			   pvr2_get_state_name(hdw->master_state),
+ 			   pvr2_get_state_name(st));
++		pvr2_led_ctrl(hdw,st == PVR2_STATE_RUN);
+ 		hdw->master_state = st;
+ 		state_updated = !0;
+ 		callback_flag = !0;
+@@ -3657,47 +4200,6 @@ static void pvr2_hdw_state_sched(struct pvr2_hdw *hdw)
+ }
+ 
+ 
+-void pvr2_hdw_get_debug_info_unlocked(const struct pvr2_hdw *hdw,
+-				      struct pvr2_hdw_debug_info *ptr)
+-{
+-	ptr->big_lock_held = hdw->big_lock_held;
+-	ptr->ctl_lock_held = hdw->ctl_lock_held;
+-	ptr->flag_disconnected = hdw->flag_disconnected;
+-	ptr->flag_init_ok = hdw->flag_init_ok;
+-	ptr->flag_ok = hdw->flag_ok;
+-	ptr->fw1_state = hdw->fw1_state;
+-	ptr->flag_decoder_missed = hdw->flag_decoder_missed;
+-	ptr->flag_tripped = hdw->flag_tripped;
+-	ptr->state_encoder_ok = hdw->state_encoder_ok;
+-	ptr->state_encoder_run = hdw->state_encoder_run;
+-	ptr->state_decoder_run = hdw->state_decoder_run;
+-	ptr->state_usbstream_run = hdw->state_usbstream_run;
+-	ptr->state_decoder_quiescent = hdw->state_decoder_quiescent;
+-	ptr->state_pipeline_config = hdw->state_pipeline_config;
+-	ptr->state_pipeline_req = hdw->state_pipeline_req;
+-	ptr->state_pipeline_pause = hdw->state_pipeline_pause;
+-	ptr->state_pipeline_idle = hdw->state_pipeline_idle;
+-	ptr->cmd_debug_state = hdw->cmd_debug_state;
+-	ptr->cmd_code = hdw->cmd_debug_code;
+-	ptr->cmd_debug_write_len = hdw->cmd_debug_write_len;
+-	ptr->cmd_debug_read_len = hdw->cmd_debug_read_len;
+-	ptr->cmd_debug_timeout = hdw->ctl_timeout_flag;
+-	ptr->cmd_debug_write_pend = hdw->ctl_write_pend_flag;
+-	ptr->cmd_debug_read_pend = hdw->ctl_read_pend_flag;
+-	ptr->cmd_debug_rstatus = hdw->ctl_read_urb->status;
+-	ptr->cmd_debug_wstatus = hdw->ctl_read_urb->status;
+-}
+-
+-
+-void pvr2_hdw_get_debug_info_locked(struct pvr2_hdw *hdw,
+-				    struct pvr2_hdw_debug_info *ptr)
+-{
+-	LOCK_TAKE(hdw->ctl_lock); do {
+-		pvr2_hdw_get_debug_info_unlocked(hdw,ptr);
+-	} while(0); LOCK_GIVE(hdw->ctl_lock);
+-}
+-
+-
+ int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
+ {
+ 	return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp);
+@@ -3757,6 +4259,80 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
+ }
+ 
+ 
++unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw)
++{
++	return hdw->input_avail_mask;
++}
++
++
++unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw)
++{
++	return hdw->input_allowed_mask;
++}
++
++
++static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v)
++{
++	if (hdw->input_val != v) {
++		hdw->input_val = v;
++		hdw->input_dirty = !0;
++	}
++
++	/* Handle side effects - if we switch to a mode that needs the RF
++	   tuner, then select the right frequency choice as well and mark
++	   it dirty. */
++	if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
++		hdw->freqSelector = 0;
++		hdw->freqDirty = !0;
++	} else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) ||
++		   (hdw->input_val == PVR2_CVAL_INPUT_DTV)) {
++		hdw->freqSelector = 1;
++		hdw->freqDirty = !0;
++	}
++	return 0;
++}
++
++
++int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw,
++			       unsigned int change_mask,
++			       unsigned int change_val)
++{
++	int ret = 0;
++	unsigned int nv,m,idx;
++	LOCK_TAKE(hdw->big_lock);
++	do {
++		nv = hdw->input_allowed_mask & ~change_mask;
++		nv |= (change_val & change_mask);
++		nv &= hdw->input_avail_mask;
++		if (!nv) {
++			/* No legal modes left; return error instead. */
++			ret = -EPERM;
++			break;
++		}
++		hdw->input_allowed_mask = nv;
++		if ((1 << hdw->input_val) & hdw->input_allowed_mask) {
++			/* Current mode is still in the allowed mask, so
++			   we're done. */
++			break;
++		}
++		/* Select and switch to a mode that is still in the allowed
++		   mask */
++		if (!hdw->input_allowed_mask) {
++			/* Nothing legal; give up */
++			break;
++		}
++		m = hdw->input_allowed_mask;
++		for (idx = 0; idx < (sizeof(m) << 3); idx++) {
++			if (!((1 << idx) & m)) continue;
++			pvr2_hdw_set_input(hdw,idx);
++			break;
++		}
++	} while (0);
++	LOCK_GIVE(hdw->big_lock);
++	return ret;
++}
++
++
+ /* Find I2C address of eeprom */
+ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
+ {
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+index 3ad7a13..20295e0 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+@@ -40,9 +40,10 @@
+ 
+ /* Legal values for the INPUT state variable */
+ #define PVR2_CVAL_INPUT_TV 0
+-#define PVR2_CVAL_INPUT_SVIDEO 1
++#define PVR2_CVAL_INPUT_DTV 1
+ #define PVR2_CVAL_INPUT_COMPOSITE 2
+-#define PVR2_CVAL_INPUT_RADIO 3
++#define PVR2_CVAL_INPUT_SVIDEO 3
++#define PVR2_CVAL_INPUT_RADIO 4
+ 
+ enum pvr2_config {
+ 	pvr2_config_empty,    /* No configuration */
+@@ -90,9 +91,6 @@ enum pvr2_v4l_type {
+ /* Translate configuration enum to a string label */
+ const char *pvr2_config_get_name(enum pvr2_config);
+ 
+-/* Translate a master state enum to a string label */
+-const char *pvr2_hdw_get_state_name(unsigned int);
+-
+ struct pvr2_hdw;
+ 
+ /* Create and return a structure for interacting with the underlying
+@@ -100,14 +98,15 @@ struct pvr2_hdw;
+ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ 				 const struct usb_device_id *devid);
+ 
++/* Perform second stage initialization, passing in a notification callback
++   for when the master state changes. */
++int pvr2_hdw_initialize(struct pvr2_hdw *,
++			void (*callback_func)(void *),
++			void *callback_data);
++
+ /* Destroy hardware interaction structure */
+ void pvr2_hdw_destroy(struct pvr2_hdw *);
+ 
+-/* Register a function to be called whenever the master state changes. */
+-void pvr2_hdw_set_state_callback(struct pvr2_hdw *,
+-				 void (*callback_func)(void *),
+-				 void *callback_data);
+-
+ /* Return true if in the ready (normal) state */
+ int pvr2_hdw_dev_ok(struct pvr2_hdw *);
+ 
+@@ -146,6 +145,23 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *,
+ /* Commit all control changes made up to this point */
+ int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
+ 
++/* Return a bit mask of valid input selections for this device.  Mask bits
++ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
++unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *);
++
++/* Return a bit mask of allowed input selections for this device.  Mask bits
++ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
++unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *);
++
++/* Change the set of allowed input selections for this device.  Both
++   change_mask and change_valu are mask bits according to
++   PVR_CVAL_INPUT_xxxx definitions.  The change_mask parameter indicate
++   which settings are being changed and the change_val parameter indicates
++   whether corresponding settings are being set or cleared. */
++int pvr2_hdw_set_input_allowed(struct pvr2_hdw *,
++			       unsigned int change_mask,
++			       unsigned int change_val);
++
+ /* Return name for this driver instance */
+ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
+ 
+@@ -250,6 +266,9 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *);
+ /* Execute simple reset command */
+ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *);
+ 
++/* suspend */
++int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *);
++
+ /* Order decoder to reset */
+ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *);
+ 
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+index 62867fa..793c89a 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+@@ -35,7 +35,7 @@
+ 
+ */
+ 
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
+ MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+ 
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
+index a9889ff..7aff8b7 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
+@@ -80,6 +80,10 @@ struct pvr2_stream {
+ 	/* Tracking state for tolerating errors */
+ 	unsigned int fail_count;
+ 	unsigned int fail_tolerance;
++
++	unsigned int buffers_processed;
++	unsigned int buffers_failed;
++	unsigned int bytes_processed;
+ };
+ 
+ struct pvr2_buffer {
+@@ -446,6 +450,8 @@ static void buffer_complete(struct urb *urb)
+ 	    (urb->status == -ENOENT) ||
+ 	    (urb->status == -ECONNRESET) ||
+ 	    (urb->status == -ESHUTDOWN)) {
++		(sp->buffers_processed)++;
++		sp->bytes_processed += urb->actual_length;
+ 		bp->used_count = urb->actual_length;
+ 		if (sp->fail_count) {
+ 			pvr2_trace(PVR2_TRACE_TOLERANCE,
+@@ -457,11 +463,13 @@ static void buffer_complete(struct urb *urb)
+ 		// We can tolerate this error, because we're below the
+ 		// threshold...
+ 		(sp->fail_count)++;
++		(sp->buffers_failed)++;
+ 		pvr2_trace(PVR2_TRACE_TOLERANCE,
+ 			   "stream %p ignoring error %d"
+ 			   " - fail count increased to %u",
+ 			   sp,urb->status,sp->fail_count);
+ 	} else {
++		(sp->buffers_failed)++;
+ 		bp->status = urb->status;
+ 	}
+ 	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+@@ -515,6 +523,28 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp,
+ 	} while(0); mutex_unlock(&sp->mutex);
+ }
+ 
++void pvr2_stream_get_stats(struct pvr2_stream *sp,
++			   struct pvr2_stream_stats *stats,
++			   int zero_counts)
++{
++	unsigned long irq_flags;
++	spin_lock_irqsave(&sp->list_lock,irq_flags);
++	if (stats) {
++		stats->buffers_in_queue = sp->q_count;
++		stats->buffers_in_idle = sp->i_count;
++		stats->buffers_in_ready = sp->r_count;
++		stats->buffers_processed = sp->buffers_processed;
++		stats->buffers_failed = sp->buffers_failed;
++		stats->bytes_processed = sp->bytes_processed;
++	}
++	if (zero_counts) {
++		sp->buffers_processed = 0;
++		sp->buffers_failed = 0;
++		sp->bytes_processed = 0;
++	}
++	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
++}
++
+ /* Query / set the nominal buffer count */
+ int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
+ {
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h
+index 93279cc..42fcf82 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-io.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-io.h
+@@ -36,6 +36,15 @@ enum pvr2_buffer_state {
+ struct pvr2_stream;
+ struct pvr2_buffer;
+ 
++struct pvr2_stream_stats {
++	unsigned int buffers_in_queue;
++	unsigned int buffers_in_idle;
++	unsigned int buffers_in_ready;
++	unsigned int buffers_processed;
++	unsigned int buffers_failed;
++	unsigned int bytes_processed;
++};
++
+ /* Initialize / tear down stream structure */
+ struct pvr2_stream *pvr2_stream_create(void);
+ void pvr2_stream_destroy(struct pvr2_stream *);
+@@ -45,6 +54,9 @@ void pvr2_stream_setup(struct pvr2_stream *,
+ void pvr2_stream_set_callback(struct pvr2_stream *,
+ 			      pvr2_stream_callback func,
+ 			      void *data);
++void pvr2_stream_get_stats(struct pvr2_stream *,
++			   struct pvr2_stream_stats *,
++			   int zero_counts);
+ 
+ /* Query / set the nominal buffer count */
+ int pvr2_stream_get_buffer_count(struct pvr2_stream *);
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
+index b63b226..332aced 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
+@@ -60,6 +60,10 @@ static void pvr_setup_attach(struct pvr2_context *pvr)
+ {
+ 	/* Create association with v4l layer */
+ 	pvr2_v4l2_create(pvr);
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++	/* Create association with dvb layer */
++	pvr2_dvb_create(pvr);
++#endif
+ #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+ 	pvr2_sysfs_create(pvr,class_ptr);
+ #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+@@ -121,6 +125,12 @@ static int __init pvr_init(void)
+ 
+ 	pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
+ 
++	ret = pvr2_context_global_init();
++	if (ret != 0) {
++		pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret);
++		return ret;
++	}
++
+ #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+ 	class_ptr = pvr2_sysfs_class_create();
+ #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+@@ -132,6 +142,8 @@ static int __init pvr_init(void)
+ 	if (pvrusb2_debug) info("Debug mask is %d (0x%x)",
+ 				pvrusb2_debug,pvrusb2_debug);
+ 
++	pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
++
+ 	return ret;
+ }
+ 
+@@ -144,6 +156,10 @@ static void __exit pvr_exit(void)
+ #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+ 	pvr2_sysfs_class_destroy(class_ptr);
+ #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
++
++	pvr2_context_global_done();
++
++	pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
+ }
+ 
+ module_init(pvr_init);
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c
+index da30928..fdc5a2b 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-std.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-std.c
+@@ -79,7 +79,7 @@ struct std_name {
+ #define TSTD_Nc  (V4L2_STD_PAL_Nc)
+ #define TSTD_60  (V4L2_STD_PAL_60)
+ 
+-#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM)
++#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM)
+ 
+ /* Mapping of standard bits to color system */
+ static const struct std_name std_groups[] = {
+@@ -328,7 +328,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+ 	struct v4l2_standard *stddefs;
+ 
+ 	if (pvrusb2_debug & PVR2_TRACE_STD) {
+-		char buf[50];
++		char buf[100];
+ 		bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
+ 		pvr2_trace(
+ 			PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)",
+@@ -352,8 +352,11 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+ 		if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
+ 	}
+ 
++	/* Don't complain about ATSC standard values */
++	fmsk &= ~CSTD_ATSC;
++
+ 	if (fmsk) {
+-		char buf[50];
++		char buf[100];
+ 		bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
+ 		pvr2_trace(
+ 			PVR2_TRACE_ERROR_LEGS,
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+index 7a1cd87..0ff7a83 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+@@ -21,7 +21,6 @@
+ 
+ #include <linux/string.h>
+ #include <linux/slab.h>
+-#include <asm/semaphore.h>
+ #include "pvrusb2-sysfs.h"
+ #include "pvrusb2-hdw.h"
+ #include "pvrusb2-debug.h"
+@@ -288,6 +287,8 @@ static ssize_t store_val_norm(int id,struct device *class_dev,
+ 	struct pvr2_sysfs *sfp;
+ 	int ret;
+ 	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
++	pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
++			 sfp,id,(int)count,buf);
+ 	ret = store_val_any(id,0,sfp,buf,count);
+ 	if (!ret) ret = count;
+ 	return ret;
+@@ -299,6 +300,8 @@ static ssize_t store_val_custom(int id,struct device *class_dev,
+ 	struct pvr2_sysfs *sfp;
+ 	int ret;
+ 	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
++	pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
++			 sfp,id,(int)count,buf);
+ 	ret = store_val_any(id,1,sfp,buf,count);
+ 	if (!ret) ret = count;
+ 	return ret;
+@@ -605,8 +608,9 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
+ 
+ 	ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+ 	if (ret) {
+-		printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
+-		       __FUNCTION__, ret);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "sysfs_create_group error: %d",
++			   ret);
+ 		return;
+ 	}
+ 	cip->created_ok = !0;
+@@ -637,15 +641,17 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
+ 	sfp->debugifc = dip;
+ 	ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+ 	if (ret < 0) {
+-		printk(KERN_WARNING "%s: device_create_file error: %d\n",
+-		       __FUNCTION__, ret);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "device_create_file error: %d",
++			   ret);
+ 	} else {
+ 		dip->debugcmd_created_ok = !0;
+ 	}
+ 	ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+ 	if (ret < 0) {
+-		printk(KERN_WARNING "%s: device_create_file error: %d\n",
+-		       __FUNCTION__, ret);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "device_create_file error: %d",
++			   ret);
+ 	} else {
+ 		dip->debuginfo_created_ok = !0;
+ 	}
+@@ -848,8 +854,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ 	class_dev->driver_data = sfp;
+ 	ret = device_register(class_dev);
+ 	if (ret) {
+-		printk(KERN_ERR "%s: device_register failed\n",
+-		       __FUNCTION__);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "device_register failed");
+ 		kfree(class_dev);
+ 		return;
+ 	}
+@@ -861,8 +867,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ 	ret = device_create_file(sfp->class_dev,
+ 				       &sfp->attr_v4l_minor_number);
+ 	if (ret < 0) {
+-		printk(KERN_WARNING "%s: device_create_file error: %d\n",
+-		       __FUNCTION__, ret);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "device_create_file error: %d",
++			   ret);
+ 	} else {
+ 		sfp->v4l_minor_number_created_ok = !0;
+ 	}
+@@ -874,8 +881,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ 	ret = device_create_file(sfp->class_dev,
+ 				       &sfp->attr_v4l_radio_minor_number);
+ 	if (ret < 0) {
+-		printk(KERN_WARNING "%s: device_create_file error: %d\n",
+-		       __FUNCTION__, ret);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "device_create_file error: %d",
++			   ret);
+ 	} else {
+ 		sfp->v4l_radio_minor_number_created_ok = !0;
+ 	}
+@@ -886,8 +894,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ 	sfp->attr_unit_number.store = NULL;
+ 	ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+ 	if (ret < 0) {
+-		printk(KERN_WARNING "%s: device_create_file error: %d\n",
+-		       __FUNCTION__, ret);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "device_create_file error: %d",
++			   ret);
+ 	} else {
+ 		sfp->unit_number_created_ok = !0;
+ 	}
+@@ -899,8 +908,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ 	ret = device_create_file(sfp->class_dev,
+ 				       &sfp->attr_bus_info);
+ 	if (ret < 0) {
+-		printk(KERN_WARNING "%s: device_create_file error: %d\n",
+-		       __FUNCTION__, ret);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "device_create_file error: %d",
++			   ret);
+ 	} else {
+ 		sfp->bus_info_created_ok = !0;
+ 	}
+@@ -912,8 +922,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ 	ret = device_create_file(sfp->class_dev,
+ 				 &sfp->attr_hdw_name);
+ 	if (ret < 0) {
+-		printk(KERN_WARNING "%s: device_create_file error: %d\n",
+-		       __FUNCTION__, ret);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "device_create_file error: %d",
++			   ret);
+ 	} else {
+ 		sfp->hdw_name_created_ok = !0;
+ 	}
+@@ -925,8 +936,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ 	ret = device_create_file(sfp->class_dev,
+ 				 &sfp->attr_hdw_desc);
+ 	if (ret < 0) {
+-		printk(KERN_WARNING "%s: device_create_file error: %d\n",
+-		       __FUNCTION__, ret);
++		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++			   "device_create_file error: %d",
++			   ret);
+ 	} else {
+ 		sfp->hdw_desc_created_ok = !0;
+ 	}
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+index 8f0587e..087a182 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+@@ -57,7 +57,9 @@ struct pvr2_v4l2_fh {
+ 	struct pvr2_v4l2_fh *vprev;
+ 	wait_queue_head_t wait_data;
+ 	int fw_mode_flag;
+-	int prev_input_val;
++	/* Map contiguous ordinal value to input id */
++	unsigned char *input_map;
++	unsigned int input_cnt;
+ };
+ 
+ struct pvr2_v4l2 {
+@@ -259,14 +261,21 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+ 		struct v4l2_input *vi = (struct v4l2_input *)arg;
+ 		struct v4l2_input tmp;
+ 		unsigned int cnt;
++		int val;
+ 
+ 		cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+ 
+ 		memset(&tmp,0,sizeof(tmp));
+ 		tmp.index = vi->index;
+ 		ret = 0;
+-		switch (vi->index) {
++		if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
++			ret = -EINVAL;
++			break;
++		}
++		val = fh->input_map[vi->index];
++		switch (val) {
+ 		case PVR2_CVAL_INPUT_TV:
++		case PVR2_CVAL_INPUT_DTV:
+ 		case PVR2_CVAL_INPUT_RADIO:
+ 			tmp.type = V4L2_INPUT_TYPE_TUNER;
+ 			break;
+@@ -281,7 +290,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+ 		if (ret < 0) break;
+ 
+ 		cnt = 0;
+-		pvr2_ctrl_get_valname(cptr,vi->index,
++		pvr2_ctrl_get_valname(cptr,val,
+ 				      tmp.name,sizeof(tmp.name)-1,&cnt);
+ 		tmp.name[cnt] = 0;
+ 
+@@ -303,22 +312,33 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+ 
+ 	case VIDIOC_G_INPUT:
+ 	{
++		unsigned int idx;
+ 		struct pvr2_ctrl *cptr;
+ 		struct v4l2_input *vi = (struct v4l2_input *)arg;
+ 		int val;
+ 		cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+ 		val = 0;
+ 		ret = pvr2_ctrl_get_value(cptr,&val);
+-		vi->index = val;
++		vi->index = 0;
++		for (idx = 0; idx < fh->input_cnt; idx++) {
++			if (fh->input_map[idx] == val) {
++				vi->index = idx;
++				break;
++			}
++		}
+ 		break;
+ 	}
+ 
+ 	case VIDIOC_S_INPUT:
+ 	{
+ 		struct v4l2_input *vi = (struct v4l2_input *)arg;
++		if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
++			ret = -ERANGE;
++			break;
++		}
+ 		ret = pvr2_ctrl_set_value(
+ 			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
+-			vi->index);
++			fh->input_map[vi->index]);
+ 		break;
+ 	}
+ 
+@@ -858,7 +878,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
+ {
+ 	struct pvr2_v4l2_fh *fhp = file->private_data;
+ 	struct pvr2_v4l2 *vp = fhp->vhead;
+-	struct pvr2_context *mp = fhp->vhead->channel.mc_head;
+ 	struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
+ 
+ 	pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
+@@ -875,42 +894,30 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
+ 	v4l2_prio_close(&vp->prio, &fhp->prio);
+ 	file->private_data = NULL;
+ 
+-	pvr2_context_enter(mp); do {
+-		/* Restore the previous input selection, if it makes sense
+-		   to do so. */
+-		if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
+-			struct pvr2_ctrl *cp;
+-			int pval;
+-			cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+-			pvr2_ctrl_get_value(cp,&pval);
+-			/* Only restore if we're still selecting the radio */
+-			if (pval == PVR2_CVAL_INPUT_RADIO) {
+-				pvr2_ctrl_set_value(cp,fhp->prev_input_val);
+-				pvr2_hdw_commit_ctl(hdw);
+-			}
+-		}
+-
+-		if (fhp->vnext) {
+-			fhp->vnext->vprev = fhp->vprev;
+-		} else {
+-			vp->vlast = fhp->vprev;
+-		}
+-		if (fhp->vprev) {
+-			fhp->vprev->vnext = fhp->vnext;
+-		} else {
+-			vp->vfirst = fhp->vnext;
+-		}
+-		fhp->vnext = NULL;
+-		fhp->vprev = NULL;
+-		fhp->vhead = NULL;
+-		pvr2_channel_done(&fhp->channel);
+-		pvr2_trace(PVR2_TRACE_STRUCT,
+-			   "Destroying pvr_v4l2_fh id=%p",fhp);
+-		kfree(fhp);
+-		if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
+-			pvr2_v4l2_destroy_no_lock(vp);
+-		}
+-	} while (0); pvr2_context_exit(mp);
++	if (fhp->vnext) {
++		fhp->vnext->vprev = fhp->vprev;
++	} else {
++		vp->vlast = fhp->vprev;
++	}
++	if (fhp->vprev) {
++		fhp->vprev->vnext = fhp->vnext;
++	} else {
++		vp->vfirst = fhp->vnext;
++	}
++	fhp->vnext = NULL;
++	fhp->vprev = NULL;
++	fhp->vhead = NULL;
++	pvr2_channel_done(&fhp->channel);
++	pvr2_trace(PVR2_TRACE_STRUCT,
++		   "Destroying pvr_v4l2_fh id=%p",fhp);
++	if (fhp->input_map) {
++		kfree(fhp->input_map);
++		fhp->input_map = NULL;
++	}
++	kfree(fhp);
++	if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
++		pvr2_v4l2_destroy_no_lock(vp);
++	}
+ 	return 0;
+ }
+ 
+@@ -921,6 +928,9 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
+ 	struct pvr2_v4l2_fh *fhp;
+ 	struct pvr2_v4l2 *vp;
+ 	struct pvr2_hdw *hdw;
++	unsigned int input_mask = 0;
++	unsigned int input_cnt,idx;
++	int ret = 0;
+ 
+ 	dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
+ 
+@@ -943,32 +953,62 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
+ 	init_waitqueue_head(&fhp->wait_data);
+ 	fhp->dev_info = dip;
+ 
+-	pvr2_context_enter(vp->channel.mc_head); do {
+-		pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
+-		pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
++	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
++	pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+ 
+-		fhp->vnext = NULL;
+-		fhp->vprev = vp->vlast;
+-		if (vp->vlast) {
+-			vp->vlast->vnext = fhp;
+-		} else {
+-			vp->vfirst = fhp;
+-		}
+-		vp->vlast = fhp;
+-		fhp->vhead = vp;
+-
+-		/* Opening the /dev/radioX device implies a mode switch.
+-		   So execute that here.  Note that you can get the
+-		   IDENTICAL effect merely by opening the normal video
+-		   device and setting the input appropriately. */
+-		if (dip->v4l_type == VFL_TYPE_RADIO) {
+-			struct pvr2_ctrl *cp;
+-			cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+-			pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
+-			pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
+-			pvr2_hdw_commit_ctl(hdw);
+-		}
+-	} while (0); pvr2_context_exit(vp->channel.mc_head);
++	if (dip->v4l_type == VFL_TYPE_RADIO) {
++		/* Opening device as a radio, legal input selection subset
++		   is just the radio. */
++		input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
++	} else {
++		/* Opening the main V4L device, legal input selection
++		   subset includes all analog inputs. */
++		input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
++			      (1 << PVR2_CVAL_INPUT_TV) |
++			      (1 << PVR2_CVAL_INPUT_COMPOSITE) |
++			      (1 << PVR2_CVAL_INPUT_SVIDEO));
++	}
++	ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
++	if (ret) {
++		pvr2_channel_done(&fhp->channel);
++		pvr2_trace(PVR2_TRACE_STRUCT,
++			   "Destroying pvr_v4l2_fh id=%p (input mask error)",
++			   fhp);
++
++		kfree(fhp);
++		return ret;
++	}
++
++	input_mask &= pvr2_hdw_get_input_available(hdw);
++	input_cnt = 0;
++	for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
++		if (input_mask & (1 << idx)) input_cnt++;
++	}
++	fhp->input_cnt = input_cnt;
++	fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
++	if (!fhp->input_map) {
++		pvr2_channel_done(&fhp->channel);
++		pvr2_trace(PVR2_TRACE_STRUCT,
++			   "Destroying pvr_v4l2_fh id=%p (input map failure)",
++			   fhp);
++		kfree(fhp);
++		return -ENOMEM;
++	}
++	input_cnt = 0;
++	for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
++		if (!(input_mask & (1 << idx))) continue;
++		fhp->input_map[input_cnt++] = idx;
++	}
++
++	fhp->vnext = NULL;
++	fhp->vprev = vp->vlast;
++	if (vp->vlast) {
++		vp->vlast->vnext = fhp;
++	} else {
++		vp->vfirst = fhp;
++	}
++	vp->vlast = fhp;
++	fhp->vhead = vp;
+ 
+ 	fhp->file = file;
+ 	file->private_data = fhp;
+@@ -1201,24 +1241,27 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
+ 
+ 	vp = kzalloc(sizeof(*vp),GFP_KERNEL);
+ 	if (!vp) return vp;
+-	vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
+-	vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
+-	if (!(vp->dev_video && vp->dev_radio)) {
+-		kfree(vp->dev_video);
+-		kfree(vp->dev_radio);
+-		kfree(vp);
+-		return NULL;
+-	}
+ 	pvr2_channel_init(&vp->channel,mnp);
+ 	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
+ 
+ 	vp->channel.check_func = pvr2_v4l2_internal_check;
+ 
+ 	/* register streams */
++	vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
++	if (!vp->dev_video) goto fail;
+ 	pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
+-	pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
++	if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
++	    (1 << PVR2_CVAL_INPUT_RADIO)) {
++		vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
++		if (!vp->dev_radio) goto fail;
++		pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
++	}
+ 
+ 	return vp;
++ fail:
++	pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
++	pvr2_v4l2_destroy_no_lock(vp);
++	return 0;
+ }
+ 
+ /*
+diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
+index e0a453a..423fa7c 100644
+--- a/drivers/media/video/pwc/pwc-if.c
++++ b/drivers/media/video/pwc/pwc-if.c
+@@ -130,8 +130,8 @@ static int default_fbufs = 3;   /* Default number of frame buffers */
+ #ifdef CONFIG_USB_PWC_DEBUG
+ 	int pwc_trace = PWC_DEBUG_LEVEL;
+ #endif
+-static int power_save = 0;
+-static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
++static int power_save;
++static int led_on = 100, led_off; /* defaults to LED that is on while in use */
+ static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
+ static struct {
+ 	int type;
+@@ -159,7 +159,9 @@ static const struct file_operations pwc_fops = {
+ 	.poll =		pwc_video_poll,
+ 	.mmap =		pwc_video_mmap,
+ 	.ioctl =        pwc_video_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.llseek =       no_llseek,
+ };
+ static struct video_device pwc_template = {
+@@ -487,7 +489,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
+ 	int i;
+ 	unsigned long flags;
+ 
+-	PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__);
++	PWC_DEBUG_MEMORY(">> %s __enter__\n", __func__);
+ 
+ 	spin_lock_irqsave(&pdev->ptrlock, flags);
+ 	pdev->full_frames = NULL;
+@@ -509,7 +511,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
+ 	pdev->fill_image = 0;
+ 	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+ 
+-	PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__);
++	PWC_DEBUG_MEMORY("<< %s __leaving__\n", __func__);
+ }
+ 
+ 
+@@ -786,8 +788,8 @@ static void pwc_isoc_handler(struct urb *urb)
+ 		} /* ..status == 0 */
+ 		else {
+ 			/* This is normally not interesting to the user, unless
+-			 * you are really debugging something */
+-			static int iso_error = 0;
++			 * you are really debugging something, default = 0 */
++			static int iso_error;
+ 			iso_error++;
+ 			if (iso_error < 20)
+ 				PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
+@@ -1426,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
+ 	unsigned long page, pos = 0;
+ 	int index;
+ 
+-	PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__);
++	PWC_DEBUG_MEMORY(">> %s\n", __func__);
+ 	pdev = vdev->priv;
+ 	size = vma->vm_end - vma->vm_start;
+ 	start = vma->vm_start;
+diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
+index 32fbe1a..1742889 100644
+--- a/drivers/media/video/pwc/pwc-v4l.c
++++ b/drivers/media/video/pwc/pwc-v4l.c
+@@ -351,8 +351,10 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+ 		return -EFAULT;
+ 
+ #ifdef CONFIG_USB_PWC_DEBUG
+-	if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
++	if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) {
+ 		v4l_printk_ioctl(cmd);
++		printk("\n");
++	}
+ #endif
+ 
+ 
+diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
+new file mode 100644
+index 0000000..7cc8e9b
+--- /dev/null
++++ b/drivers/media/video/pxa_camera.c
+@@ -0,0 +1,1206 @@
++/*
++ * V4L2 Driver for PXA camera host
++ *
++ * Copyright (C) 2006, Sascha Hauer, Pengutronix
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at 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.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/moduleparam.h>
++#include <linux/time.h>
++#include <linux/version.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/mutex.h>
++#include <linux/clk.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-dev.h>
++#include <media/soc_camera.h>
++
++#include <linux/videodev2.h>
++
++#include <asm/dma.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/camera.h>
++
++#define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
++#define PXA_CAM_DRV_NAME "pxa27x-camera"
++
++#define CICR0_SIM_MP	(0 << 24)
++#define CICR0_SIM_SP	(1 << 24)
++#define CICR0_SIM_MS	(2 << 24)
++#define CICR0_SIM_EP	(3 << 24)
++#define CICR0_SIM_ES	(4 << 24)
++
++#define CICR1_DW_VAL(x)   ((x) & CICR1_DW)	    /* Data bus width */
++#define CICR1_PPL_VAL(x)  (((x) << 15) & CICR1_PPL) /* Pixels per line */
++#define CICR1_COLOR_SP_VAL(x)	(((x) << 3) & CICR1_COLOR_SP)	/* color space */
++#define CICR1_RGB_BPP_VAL(x)	(((x) << 7) & CICR1_RGB_BPP)	/* bpp for rgb */
++#define CICR1_RGBT_CONV_VAL(x)	(((x) << 29) & CICR1_RGBT_CONV)	/* rgbt conv */
++
++#define CICR2_BLW_VAL(x)  (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */
++#define CICR2_ELW_VAL(x)  (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */
++#define CICR2_HSW_VAL(x)  (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */
++#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */
++#define CICR2_FSW_VAL(x)  (((x) << 0) & CICR2_FSW)  /* Frame stabilization wait count */
++
++#define CICR3_BFW_VAL(x)  (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count  */
++#define CICR3_EFW_VAL(x)  (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */
++#define CICR3_VSW_VAL(x)  (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */
++#define CICR3_LPF_VAL(x)  (((x) << 0) & CICR3_LPF)  /* Lines per frame */
++
++#define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \
++			CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \
++			CICR0_EOFM | CICR0_FOM)
++
++static DEFINE_MUTEX(camera_lock);
++
++/*
++ * Structures
++ */
++enum pxa_camera_active_dma {
++	DMA_Y = 0x1,
++	DMA_U = 0x2,
++	DMA_V = 0x4,
++};
++
++/* descriptor needed for the PXA DMA engine */
++struct pxa_cam_dma {
++	dma_addr_t		sg_dma;
++	struct pxa_dma_desc	*sg_cpu;
++	size_t			sg_size;
++	int			sglen;
++};
++
++/* buffer for one video frame */
++struct pxa_buffer {
++	/* common v4l buffer stuff -- must be first */
++	struct videobuf_buffer vb;
++
++	const struct soc_camera_data_format        *fmt;
++
++	/* our descriptor lists for Y, U and V channels */
++	struct pxa_cam_dma dmas[3];
++
++	int			inwork;
++
++	enum pxa_camera_active_dma active_dma;
++};
++
++struct pxa_camera_dev {
++	struct device		*dev;
++	/* PXA27x is only supposed to handle one camera on its Quick Capture
++	 * interface. If anyone ever builds hardware to enable more than
++	 * one camera, they will have to modify this driver too */
++	struct soc_camera_device *icd;
++	struct clk		*clk;
++
++	unsigned int		irq;
++	void __iomem		*base;
++
++	int			channels;
++	unsigned int		dma_chans[3];
++
++	struct pxacamera_platform_data *pdata;
++	struct resource		*res;
++	unsigned long		platform_flags;
++	unsigned long		platform_mclk_10khz;
++
++	struct list_head	capture;
++
++	spinlock_t		lock;
++
++	struct pxa_buffer	*active;
++	struct pxa_dma_desc	*sg_tail[3];
++};
++
++static const char *pxa_cam_driver_description = "PXA_Camera";
++
++static unsigned int vid_limit = 16;	/* Video memory limit, in Mb */
++
++/*
++ *  Videobuf operations
++ */
++static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
++			      unsigned int *size)
++{
++	struct soc_camera_device *icd = vq->priv_data;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	struct pxa_camera_dev *pcdev = ici->priv;
++
++	dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
++
++	/* planar capture requires Y, U and V buffers to be page aligned */
++	if (pcdev->channels == 3) {
++		*size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */
++		*size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */
++		*size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */
++	} else {
++		*size = icd->width * icd->height *
++			((icd->current_fmt->depth + 7) >> 3);
++	}
++
++	if (0 == *count)
++		*count = 32;
++	while (*size * *count > vid_limit * 1024 * 1024)
++		(*count)--;
++
++	return 0;
++}
++
++static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
++{
++	struct soc_camera_device *icd = vq->priv_data;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	struct pxa_camera_dev *pcdev = ici->priv;
++	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
++	int i;
++
++	BUG_ON(in_interrupt());
++
++	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++		&buf->vb, buf->vb.baddr, buf->vb.bsize);
++
++	/* This waits until this buffer is out of danger, i.e., until it is no
++	 * longer in STATE_QUEUED or STATE_ACTIVE */
++	videobuf_waiton(&buf->vb, 0, 0);
++	videobuf_dma_unmap(vq, dma);
++	videobuf_dma_free(dma);
++
++	for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
++		if (buf->dmas[i].sg_cpu)
++			dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size,
++					  buf->dmas[i].sg_cpu,
++					  buf->dmas[i].sg_dma);
++		buf->dmas[i].sg_cpu = NULL;
++	}
++
++	buf->vb.state = VIDEOBUF_NEEDS_INIT;
++}
++
++static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
++				struct pxa_buffer *buf,
++				struct videobuf_dmabuf *dma, int channel,
++				int sglen, int sg_start, int cibr,
++				unsigned int size)
++{
++	struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
++	int i;
++
++	if (pxa_dma->sg_cpu)
++		dma_free_coherent(pcdev->dev, pxa_dma->sg_size,
++				  pxa_dma->sg_cpu, pxa_dma->sg_dma);
++
++	pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
++	pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size,
++					     &pxa_dma->sg_dma, GFP_KERNEL);
++	if (!pxa_dma->sg_cpu)
++		return -ENOMEM;
++
++	pxa_dma->sglen = sglen;
++
++	for (i = 0; i < sglen; i++) {
++		int sg_i = sg_start + i;
++		struct scatterlist *sg = dma->sglist;
++		unsigned int dma_len = sg_dma_len(&sg[sg_i]), xfer_len;
++
++		pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
++		pxa_dma->sg_cpu[i].dtadr = sg_dma_address(&sg[sg_i]);
++
++		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
++		xfer_len = (min(dma_len, size) + 7) & ~7;
++
++		pxa_dma->sg_cpu[i].dcmd =
++			DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
++		size -= dma_len;
++		pxa_dma->sg_cpu[i].ddadr =
++			pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
++	}
++
++	pxa_dma->sg_cpu[sglen - 1].ddadr = DDADR_STOP;
++	pxa_dma->sg_cpu[sglen - 1].dcmd |= DCMD_ENDIRQEN;
++
++	return 0;
++}
++
++static int pxa_videobuf_prepare(struct videobuf_queue *vq,
++		struct videobuf_buffer *vb, enum v4l2_field field)
++{
++	struct soc_camera_device *icd = vq->priv_data;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	struct pxa_camera_dev *pcdev = ici->priv;
++	struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
++	int ret;
++	int sglen_y,  sglen_yu = 0, sglen_u = 0, sglen_v = 0;
++	int size_y, size_u = 0, size_v = 0;
++
++	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++		vb, vb->baddr, vb->bsize);
++
++	/* Added list head initialization on alloc */
++	WARN_ON(!list_empty(&vb->queue));
++
++#ifdef DEBUG
++	/* This can be useful if you want to see if we actually fill
++	 * the buffer with something */
++	memset((void *)vb->baddr, 0xaa, vb->bsize);
++#endif
++
++	BUG_ON(NULL == icd->current_fmt);
++
++	/* I think, in buf_prepare you only have to protect global data,
++	 * the actual buffer is yours */
++	buf->inwork = 1;
++
++	if (buf->fmt	!= icd->current_fmt ||
++	    vb->width	!= icd->width ||
++	    vb->height	!= icd->height ||
++	    vb->field	!= field) {
++		buf->fmt	= icd->current_fmt;
++		vb->width	= icd->width;
++		vb->height	= icd->height;
++		vb->field	= field;
++		vb->state	= VIDEOBUF_NEEDS_INIT;
++	}
++
++	vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
++	if (0 != vb->baddr && vb->bsize < vb->size) {
++		ret = -EINVAL;
++		goto out;
++	}
++
++	if (vb->state == VIDEOBUF_NEEDS_INIT) {
++		unsigned int size = vb->size;
++		struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
++
++		ret = videobuf_iolock(vq, vb, NULL);
++		if (ret)
++			goto fail;
++
++		if (pcdev->channels == 3) {
++			/* FIXME the calculations should be more precise */
++			sglen_y = dma->sglen / 2;
++			sglen_u = sglen_v = dma->sglen / 4 + 1;
++			sglen_yu = sglen_y + sglen_u;
++			size_y = size / 2;
++			size_u = size_v = size / 4;
++		} else {
++			sglen_y = dma->sglen;
++			size_y = size;
++		}
++
++		/* init DMA for Y channel */
++		ret = pxa_init_dma_channel(pcdev, buf, dma, 0, sglen_y,
++					   0, 0x28, size_y);
++
++		if (ret) {
++			dev_err(pcdev->dev,
++				"DMA initialization for Y/RGB failed\n");
++			goto fail;
++		}
++
++		if (pcdev->channels == 3) {
++			/* init DMA for U channel */
++			ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u,
++						   sglen_y, 0x30, size_u);
++			if (ret) {
++				dev_err(pcdev->dev,
++					"DMA initialization for U failed\n");
++				goto fail_u;
++			}
++
++			/* init DMA for V channel */
++			ret = pxa_init_dma_channel(pcdev, buf, dma, 2, sglen_v,
++						   sglen_yu, 0x38, size_v);
++			if (ret) {
++				dev_err(pcdev->dev,
++					"DMA initialization for V failed\n");
++				goto fail_v;
++			}
++		}
++
++		vb->state = VIDEOBUF_PREPARED;
++	}
++
++	buf->inwork = 0;
++	buf->active_dma = DMA_Y;
++	if (pcdev->channels == 3)
++		buf->active_dma |= DMA_U | DMA_V;
++
++	return 0;
++
++fail_v:
++	dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size,
++			  buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
++fail_u:
++	dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size,
++			  buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
++fail:
++	free_buffer(vq, buf);
++out:
++	buf->inwork = 0;
++	return ret;
++}
++
++static void pxa_videobuf_queue(struct videobuf_queue *vq,
++			       struct videobuf_buffer *vb)
++{
++	struct soc_camera_device *icd = vq->priv_data;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	struct pxa_camera_dev *pcdev = ici->priv;
++	struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
++	struct pxa_buffer *active;
++	unsigned long flags;
++	int i;
++
++	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++		vb, vb->baddr, vb->bsize);
++	spin_lock_irqsave(&pcdev->lock, flags);
++
++	list_add_tail(&vb->queue, &pcdev->capture);
++
++	vb->state = VIDEOBUF_ACTIVE;
++	active = pcdev->active;
++
++	if (!active) {
++		CIFR |= CIFR_RESET_F;
++
++		for (i = 0; i < pcdev->channels; i++) {
++			DDADR(pcdev->dma_chans[i]) = buf->dmas[i].sg_dma;
++			DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
++			pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen - 1;
++		}
++
++		pcdev->active = buf;
++		CICR0 |= CICR0_ENB;
++	} else {
++		struct pxa_cam_dma *buf_dma;
++		struct pxa_cam_dma *act_dma;
++		int nents;
++
++		for (i = 0; i < pcdev->channels; i++) {
++			buf_dma = &buf->dmas[i];
++			act_dma = &active->dmas[i];
++			nents = buf_dma->sglen;
++
++			/* Stop DMA engine */
++			DCSR(pcdev->dma_chans[i]) = 0;
++
++			/* Add the descriptors we just initialized to
++			   the currently running chain */
++			pcdev->sg_tail[i]->ddadr = buf_dma->sg_dma;
++			pcdev->sg_tail[i] = buf_dma->sg_cpu + buf_dma->sglen - 1;
++
++			/* Setup a dummy descriptor with the DMA engines current
++			 * state
++			 */
++			buf_dma->sg_cpu[nents].dsadr =
++				pcdev->res->start + 0x28 + i*8; /* CIBRx */
++			buf_dma->sg_cpu[nents].dtadr =
++				DTADR(pcdev->dma_chans[i]);
++			buf_dma->sg_cpu[nents].dcmd =
++				DCMD(pcdev->dma_chans[i]);
++
++			if (DDADR(pcdev->dma_chans[i]) == DDADR_STOP) {
++				/* The DMA engine is on the last
++				   descriptor, set the next descriptors
++				   address to the descriptors we just
++				   initialized */
++				buf_dma->sg_cpu[nents].ddadr = buf_dma->sg_dma;
++			} else {
++				buf_dma->sg_cpu[nents].ddadr =
++					DDADR(pcdev->dma_chans[i]);
++			}
++
++			/* The next descriptor is the dummy descriptor */
++			DDADR(pcdev->dma_chans[i]) = buf_dma->sg_dma + nents *
++				sizeof(struct pxa_dma_desc);
++
++			DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
++		}
++	}
++
++	spin_unlock_irqrestore(&pcdev->lock, flags);
++}
++
++static void pxa_videobuf_release(struct videobuf_queue *vq,
++				 struct videobuf_buffer *vb)
++{
++	struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
++#ifdef DEBUG
++	struct soc_camera_device *icd = vq->priv_data;
++
++	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++		vb, vb->baddr, vb->bsize);
++
++	switch (vb->state) {
++	case VIDEOBUF_ACTIVE:
++		dev_dbg(&icd->dev, "%s (active)\n", __func__);
++		break;
++	case VIDEOBUF_QUEUED:
++		dev_dbg(&icd->dev, "%s (queued)\n", __func__);
++		break;
++	case VIDEOBUF_PREPARED:
++		dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
++		break;
++	default:
++		dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
++		break;
++	}
++#endif
++
++	free_buffer(vq, buf);
++}
++
++static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
++			      struct videobuf_buffer *vb,
++			      struct pxa_buffer *buf)
++{
++	/* _init is used to debug races, see comment in pxa_camera_reqbufs() */
++	list_del_init(&vb->queue);
++	vb->state = VIDEOBUF_DONE;
++	do_gettimeofday(&vb->ts);
++	vb->field_count++;
++	wake_up(&vb->done);
++
++	if (list_empty(&pcdev->capture)) {
++		pcdev->active = NULL;
++		DCSR(pcdev->dma_chans[0]) = 0;
++		DCSR(pcdev->dma_chans[1]) = 0;
++		DCSR(pcdev->dma_chans[2]) = 0;
++		CICR0 &= ~CICR0_ENB;
++		return;
++	}
++
++	pcdev->active = list_entry(pcdev->capture.next,
++				   struct pxa_buffer, vb.queue);
++}
++
++static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
++			       enum pxa_camera_active_dma act_dma)
++{
++	struct pxa_buffer *buf;
++	unsigned long flags;
++	u32 status, camera_status, overrun;
++	struct videobuf_buffer *vb;
++
++	spin_lock_irqsave(&pcdev->lock, flags);
++
++	status = DCSR(channel);
++	DCSR(channel) = status | DCSR_ENDINTR;
++
++	if (status & DCSR_BUSERR) {
++		dev_err(pcdev->dev, "DMA Bus Error IRQ!\n");
++		goto out;
++	}
++
++	if (!(status & DCSR_ENDINTR)) {
++		dev_err(pcdev->dev, "Unknown DMA IRQ source, "
++			"status: 0x%08x\n", status);
++		goto out;
++	}
++
++	if (!pcdev->active) {
++		dev_err(pcdev->dev, "DMA End IRQ with no active buffer!\n");
++		goto out;
++	}
++
++	camera_status = CISR;
++	overrun = CISR_IFO_0;
++	if (pcdev->channels == 3)
++		overrun |= CISR_IFO_1 | CISR_IFO_2;
++	if (camera_status & overrun) {
++		dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", camera_status);
++		/* Stop the Capture Interface */
++		CICR0 &= ~CICR0_ENB;
++		/* Stop DMA */
++		DCSR(channel) = 0;
++		/* Reset the FIFOs */
++		CIFR |= CIFR_RESET_F;
++		/* Enable End-Of-Frame Interrupt */
++		CICR0 &= ~CICR0_EOFM;
++		/* Restart the Capture Interface */
++		CICR0 |= CICR0_ENB;
++		goto out;
++	}
++
++	vb = &pcdev->active->vb;
++	buf = container_of(vb, struct pxa_buffer, vb);
++	WARN_ON(buf->inwork || list_empty(&vb->queue));
++	dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++		vb, vb->baddr, vb->bsize);
++
++	buf->active_dma &= ~act_dma;
++	if (!buf->active_dma)
++		pxa_camera_wakeup(pcdev, vb, buf);
++
++out:
++	spin_unlock_irqrestore(&pcdev->lock, flags);
++}
++
++static void pxa_camera_dma_irq_y(int channel, void *data)
++{
++	struct pxa_camera_dev *pcdev = data;
++	pxa_camera_dma_irq(channel, pcdev, DMA_Y);
++}
++
++static void pxa_camera_dma_irq_u(int channel, void *data)
++{
++	struct pxa_camera_dev *pcdev = data;
++	pxa_camera_dma_irq(channel, pcdev, DMA_U);
++}
++
++static void pxa_camera_dma_irq_v(int channel, void *data)
++{
++	struct pxa_camera_dev *pcdev = data;
++	pxa_camera_dma_irq(channel, pcdev, DMA_V);
++}
++
++static struct videobuf_queue_ops pxa_videobuf_ops = {
++	.buf_setup      = pxa_videobuf_setup,
++	.buf_prepare    = pxa_videobuf_prepare,
++	.buf_queue      = pxa_videobuf_queue,
++	.buf_release    = pxa_videobuf_release,
++};
++
++static int mclk_get_divisor(struct pxa_camera_dev *pcdev)
++{
++	unsigned int mclk_10khz = pcdev->platform_mclk_10khz;
++	unsigned long div;
++	unsigned long lcdclk;
++
++	lcdclk = clk_get_rate(pcdev->clk) / 10000;
++
++	/* We verify platform_mclk_10khz != 0, so if anyone breaks it, here
++	 * they get a nice Oops */
++	div = (lcdclk + 2 * mclk_10khz - 1) / (2 * mclk_10khz) - 1;
++
++	dev_dbg(pcdev->dev, "LCD clock %lukHz, target freq %dkHz, "
++		"divisor %lu\n", lcdclk * 10, mclk_10khz * 10, div);
++
++	return div;
++}
++
++static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
++{
++	struct pxacamera_platform_data *pdata = pcdev->pdata;
++	u32 cicr4 = 0;
++
++	dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n",
++		pcdev, pdata);
++
++	if (pdata && pdata->init) {
++		dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__);
++		pdata->init(pcdev->dev);
++	}
++
++	if (pdata && pdata->power) {
++		dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__);
++		pdata->power(pcdev->dev, 1);
++	}
++
++	if (pdata && pdata->reset) {
++		dev_dbg(pcdev->dev, "%s: Releasing camera reset\n",
++			__func__);
++		pdata->reset(pcdev->dev, 1);
++	}
++
++	CICR0 = 0x3FF;   /* disable all interrupts */
++
++	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
++		cicr4 |= CICR4_PCLK_EN;
++	if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
++		cicr4 |= CICR4_MCLK_EN;
++	if (pcdev->platform_flags & PXA_CAMERA_PCP)
++		cicr4 |= CICR4_PCP;
++	if (pcdev->platform_flags & PXA_CAMERA_HSP)
++		cicr4 |= CICR4_HSP;
++	if (pcdev->platform_flags & PXA_CAMERA_VSP)
++		cicr4 |= CICR4_VSP;
++
++	CICR4 = mclk_get_divisor(pcdev) | cicr4;
++
++	clk_enable(pcdev->clk);
++}
++
++static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
++{
++	struct pxacamera_platform_data *board = pcdev->pdata;
++
++	clk_disable(pcdev->clk);
++
++	if (board && board->reset) {
++		dev_dbg(pcdev->dev, "%s: Asserting camera reset\n",
++			__func__);
++		board->reset(pcdev->dev, 0);
++	}
++
++	if (board && board->power) {
++		dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__);
++		board->power(pcdev->dev, 0);
++	}
++}
++
++static irqreturn_t pxa_camera_irq(int irq, void *data)
++{
++	struct pxa_camera_dev *pcdev = data;
++	unsigned int status = CISR;
++
++	dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status);
++
++	if (!status)
++		return IRQ_NONE;
++
++	CISR = status;
++
++	if (status & CISR_EOF) {
++		int i;
++		for (i = 0; i < pcdev->channels; i++) {
++			DDADR(pcdev->dma_chans[i]) =
++				pcdev->active->dmas[i].sg_dma;
++			DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
++		}
++		CICR0 |= CICR0_EOFM;
++	}
++
++	return IRQ_HANDLED;
++}
++
++/* The following two functions absolutely depend on the fact, that
++ * there can be only one camera on PXA quick capture interface */
++static int pxa_camera_add_device(struct soc_camera_device *icd)
++{
++	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
++	struct pxa_camera_dev *pcdev = ici->priv;
++	int ret;
++
++	mutex_lock(&camera_lock);
++
++	if (pcdev->icd) {
++		ret = -EBUSY;
++		goto ebusy;
++	}
++
++	dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
++		 icd->devnum);
++
++	pxa_camera_activate(pcdev);
++	ret = icd->ops->init(icd);
++
++	if (!ret)
++		pcdev->icd = icd;
++
++ebusy:
++	mutex_unlock(&camera_lock);
++
++	return ret;
++}
++
++static void pxa_camera_remove_device(struct soc_camera_device *icd)
++{
++	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
++	struct pxa_camera_dev *pcdev = ici->priv;
++
++	BUG_ON(icd != pcdev->icd);
++
++	dev_info(&icd->dev, "PXA Camera driver detached from camera %d\n",
++		 icd->devnum);
++
++	/* disable capture, disable interrupts */
++	CICR0 = 0x3ff;
++
++	/* Stop DMA engine */
++	DCSR(pcdev->dma_chans[0]) = 0;
++	DCSR(pcdev->dma_chans[1]) = 0;
++	DCSR(pcdev->dma_chans[2]) = 0;
++
++	icd->ops->release(icd);
++
++	pxa_camera_deactivate(pcdev);
++
++	pcdev->icd = NULL;
++}
++
++static int test_platform_param(struct pxa_camera_dev *pcdev,
++			       unsigned char buswidth, unsigned long *flags)
++{
++	/*
++	 * Platform specified synchronization and pixel clock polarities are
++	 * only a recommendation and are only used during probing. The PXA270
++	 * quick capture interface supports both.
++	 */
++	*flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
++		  SOCAM_MASTER : SOCAM_SLAVE) |
++		SOCAM_HSYNC_ACTIVE_HIGH |
++		SOCAM_HSYNC_ACTIVE_LOW |
++		SOCAM_VSYNC_ACTIVE_HIGH |
++		SOCAM_VSYNC_ACTIVE_LOW |
++		SOCAM_PCLK_SAMPLE_RISING |
++		SOCAM_PCLK_SAMPLE_FALLING;
++
++	/* If requested data width is supported by the platform, use it */
++	switch (buswidth) {
++	case 10:
++		if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10))
++			return -EINVAL;
++		*flags |= SOCAM_DATAWIDTH_10;
++		break;
++	case 9:
++		if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9))
++			return -EINVAL;
++		*flags |= SOCAM_DATAWIDTH_9;
++		break;
++	case 8:
++		if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8))
++			return -EINVAL;
++		*flags |= SOCAM_DATAWIDTH_8;
++	}
++
++	return 0;
++}
++
++static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
++{
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	struct pxa_camera_dev *pcdev = ici->priv;
++	unsigned long dw, bpp, bus_flags, camera_flags, common_flags;
++	u32 cicr0, cicr1, cicr4 = 0;
++	int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
++
++	if (ret < 0)
++		return ret;
++
++	camera_flags = icd->ops->query_bus_param(icd);
++
++	common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
++	if (!common_flags)
++		return -EINVAL;
++
++	pcdev->channels = 1;
++
++	/* Make choises, based on platform preferences */
++	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
++	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
++		if (pcdev->platform_flags & PXA_CAMERA_HSP)
++			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
++		else
++			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
++	}
++
++	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
++	    (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
++		if (pcdev->platform_flags & PXA_CAMERA_VSP)
++			common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
++		else
++			common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
++	}
++
++	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
++	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
++		if (pcdev->platform_flags & PXA_CAMERA_PCP)
++			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
++		else
++			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
++	}
++
++	ret = icd->ops->set_bus_param(icd, common_flags);
++	if (ret < 0)
++		return ret;
++
++	/* Datawidth is now guaranteed to be equal to one of the three values.
++	 * We fix bit-per-pixel equal to data-width... */
++	switch (common_flags & SOCAM_DATAWIDTH_MASK) {
++	case SOCAM_DATAWIDTH_10:
++		icd->buswidth = 10;
++		dw = 4;
++		bpp = 0x40;
++		break;
++	case SOCAM_DATAWIDTH_9:
++		icd->buswidth = 9;
++		dw = 3;
++		bpp = 0x20;
++		break;
++	default:
++		/* Actually it can only be 8 now,
++		 * default is just to silence compiler warnings */
++	case SOCAM_DATAWIDTH_8:
++		icd->buswidth = 8;
++		dw = 2;
++		bpp = 0;
++	}
++
++	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
++		cicr4 |= CICR4_PCLK_EN;
++	if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
++		cicr4 |= CICR4_MCLK_EN;
++	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
++		cicr4 |= CICR4_PCP;
++	if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
++		cicr4 |= CICR4_HSP;
++	if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
++		cicr4 |= CICR4_VSP;
++
++	cicr0 = CICR0;
++	if (cicr0 & CICR0_ENB)
++		CICR0 = cicr0 & ~CICR0_ENB;
++
++	cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw;
++
++	switch (pixfmt) {
++	case V4L2_PIX_FMT_YUV422P:
++		pcdev->channels = 3;
++		cicr1 |= CICR1_YCBCR_F;
++	case V4L2_PIX_FMT_YUYV:
++		cicr1 |= CICR1_COLOR_SP_VAL(2);
++		break;
++	case V4L2_PIX_FMT_RGB555:
++		cicr1 |= CICR1_RGB_BPP_VAL(1) | CICR1_RGBT_CONV_VAL(2) |
++			CICR1_TBIT | CICR1_COLOR_SP_VAL(1);
++		break;
++	case V4L2_PIX_FMT_RGB565:
++		cicr1 |= CICR1_COLOR_SP_VAL(1) | CICR1_RGB_BPP_VAL(2);
++		break;
++	}
++
++	CICR1 = cicr1;
++	CICR2 = 0;
++	CICR3 = CICR3_LPF_VAL(icd->height - 1) |
++		CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
++	CICR4 = mclk_get_divisor(pcdev) | cicr4;
++
++	/* CIF interrupts are not used, only DMA */
++	CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
++		 CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) |
++		CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB);
++
++	return 0;
++}
++
++static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
++{
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	struct pxa_camera_dev *pcdev = ici->priv;
++	unsigned long bus_flags, camera_flags;
++	int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
++
++	if (ret < 0)
++		return ret;
++
++	camera_flags = icd->ops->query_bus_param(icd);
++
++	return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
++}
++
++static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd,
++				  __u32 pixfmt, struct v4l2_rect *rect)
++{
++	return icd->ops->set_fmt_cap(icd, pixfmt, rect);
++}
++
++static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd,
++				  struct v4l2_format *f)
++{
++	/* limit to pxa hardware capabilities */
++	if (f->fmt.pix.height < 32)
++		f->fmt.pix.height = 32;
++	if (f->fmt.pix.height > 2048)
++		f->fmt.pix.height = 2048;
++	if (f->fmt.pix.width < 48)
++		f->fmt.pix.width = 48;
++	if (f->fmt.pix.width > 2048)
++		f->fmt.pix.width = 2048;
++	f->fmt.pix.width &= ~0x01;
++
++	/* limit to sensor capabilities */
++	return icd->ops->try_fmt_cap(icd, f);
++}
++
++static int pxa_camera_reqbufs(struct soc_camera_file *icf,
++			      struct v4l2_requestbuffers *p)
++{
++	int i;
++
++	/* This is for locking debugging only. I removed spinlocks and now I
++	 * check whether .prepare is ever called on a linked buffer, or whether
++	 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
++	 * it hadn't triggered */
++	for (i = 0; i < p->count; i++) {
++		struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i],
++						      struct pxa_buffer, vb);
++		buf->inwork = 0;
++		INIT_LIST_HEAD(&buf->vb.queue);
++	}
++
++	return 0;
++}
++
++static unsigned int pxa_camera_poll(struct file *file, poll_table *pt)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct pxa_buffer *buf;
++
++	buf = list_entry(icf->vb_vidq.stream.next, struct pxa_buffer,
++			 vb.stream);
++
++	poll_wait(file, &buf->vb.done, pt);
++
++	if (buf->vb.state == VIDEOBUF_DONE ||
++	    buf->vb.state == VIDEOBUF_ERROR)
++		return POLLIN|POLLRDNORM;
++
++	return 0;
++}
++
++static int pxa_camera_querycap(struct soc_camera_host *ici,
++			       struct v4l2_capability *cap)
++{
++	/* cap->name is set by the firendly caller:-> */
++	strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
++	cap->version = PXA_CAM_VERSION_CODE;
++	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
++
++	return 0;
++}
++
++static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf)
++{
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icf->icd->dev.parent);
++	struct pxa_camera_dev *pcdev = ici->priv;
++
++	return &pcdev->lock;
++}
++
++static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
++	.owner		= THIS_MODULE,
++	.add		= pxa_camera_add_device,
++	.remove		= pxa_camera_remove_device,
++	.set_fmt_cap	= pxa_camera_set_fmt_cap,
++	.try_fmt_cap	= pxa_camera_try_fmt_cap,
++	.reqbufs	= pxa_camera_reqbufs,
++	.poll		= pxa_camera_poll,
++	.querycap	= pxa_camera_querycap,
++	.try_bus_param	= pxa_camera_try_bus_param,
++	.set_bus_param	= pxa_camera_set_bus_param,
++	.spinlock_alloc	= pxa_camera_spinlock_alloc,
++};
++
++/* Should be allocated dynamically too, but we have only one. */
++static struct soc_camera_host pxa_soc_camera_host = {
++	.drv_name		= PXA_CAM_DRV_NAME,
++	.vbq_ops		= &pxa_videobuf_ops,
++	.msize			= sizeof(struct pxa_buffer),
++	.ops			= &pxa_soc_camera_host_ops,
++};
++
++static int pxa_camera_probe(struct platform_device *pdev)
++{
++	struct pxa_camera_dev *pcdev;
++	struct resource *res;
++	void __iomem *base;
++	unsigned int irq;
++	int err = 0;
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	irq = platform_get_irq(pdev, 0);
++	if (!res || !irq) {
++		err = -ENODEV;
++		goto exit;
++	}
++
++	pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
++	if (!pcdev) {
++		dev_err(&pdev->dev, "Could not allocate pcdev\n");
++		err = -ENOMEM;
++		goto exit;
++	}
++
++	pcdev->clk = clk_get(&pdev->dev, "CAMCLK");
++	if (IS_ERR(pcdev->clk)) {
++		err = PTR_ERR(pcdev->clk);
++		goto exit_kfree;
++	}
++
++	dev_set_drvdata(&pdev->dev, pcdev);
++	pcdev->res = res;
++
++	pcdev->pdata = pdev->dev.platform_data;
++	pcdev->platform_flags = pcdev->pdata->flags;
++	if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
++			PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
++		/* Platform hasn't set available data widths. This is bad.
++		 * Warn and use a default. */
++		dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
++			 "data widths, using default 10 bit\n");
++		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
++	}
++	pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz;
++	if (!pcdev->platform_mclk_10khz) {
++		dev_warn(&pdev->dev,
++			 "mclk_10khz == 0! Please, fix your platform data. "
++			 "Using default 20MHz\n");
++		pcdev->platform_mclk_10khz = 2000;
++	}
++
++	INIT_LIST_HEAD(&pcdev->capture);
++	spin_lock_init(&pcdev->lock);
++
++	/*
++	 * Request the regions.
++	 */
++	if (!request_mem_region(res->start, res->end - res->start + 1,
++				PXA_CAM_DRV_NAME)) {
++		err = -EBUSY;
++		goto exit_clk;
++	}
++
++	base = ioremap(res->start, res->end - res->start + 1);
++	if (!base) {
++		err = -ENOMEM;
++		goto exit_release;
++	}
++	pcdev->irq = irq;
++	pcdev->base = base;
++	pcdev->dev = &pdev->dev;
++
++	/* request dma */
++	pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
++					      pxa_camera_dma_irq_y, pcdev);
++	if (pcdev->dma_chans[0] < 0) {
++		dev_err(pcdev->dev, "Can't request DMA for Y\n");
++		err = -ENOMEM;
++		goto exit_iounmap;
++	}
++	dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
++
++	pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
++					      pxa_camera_dma_irq_u, pcdev);
++	if (pcdev->dma_chans[1] < 0) {
++		dev_err(pcdev->dev, "Can't request DMA for U\n");
++		err = -ENOMEM;
++		goto exit_free_dma_y;
++	}
++	dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
++
++	pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
++					      pxa_camera_dma_irq_v, pcdev);
++	if (pcdev->dma_chans[0] < 0) {
++		dev_err(pcdev->dev, "Can't request DMA for V\n");
++		err = -ENOMEM;
++		goto exit_free_dma_u;
++	}
++	dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
++
++	DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD;
++	DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD;
++	DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD;
++
++	/* request irq */
++	err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
++			  pcdev);
++	if (err) {
++		dev_err(pcdev->dev, "Camera interrupt register failed \n");
++		goto exit_free_dma;
++	}
++
++	pxa_soc_camera_host.priv	= pcdev;
++	pxa_soc_camera_host.dev.parent	= &pdev->dev;
++	pxa_soc_camera_host.nr		= pdev->id;
++	err = soc_camera_host_register(&pxa_soc_camera_host);
++	if (err)
++		goto exit_free_irq;
++
++	return 0;
++
++exit_free_irq:
++	free_irq(pcdev->irq, pcdev);
++exit_free_dma:
++	pxa_free_dma(pcdev->dma_chans[2]);
++exit_free_dma_u:
++	pxa_free_dma(pcdev->dma_chans[1]);
++exit_free_dma_y:
++	pxa_free_dma(pcdev->dma_chans[0]);
++exit_iounmap:
++	iounmap(base);
++exit_release:
++	release_mem_region(res->start, res->end - res->start + 1);
++exit_clk:
++	clk_put(pcdev->clk);
++exit_kfree:
++	kfree(pcdev);
++exit:
++	return err;
++}
++
++static int __devexit pxa_camera_remove(struct platform_device *pdev)
++{
++	struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
++	struct resource *res;
++
++	clk_put(pcdev->clk);
++
++	pxa_free_dma(pcdev->dma_chans[0]);
++	pxa_free_dma(pcdev->dma_chans[1]);
++	pxa_free_dma(pcdev->dma_chans[2]);
++	free_irq(pcdev->irq, pcdev);
++
++	soc_camera_host_unregister(&pxa_soc_camera_host);
++
++	iounmap(pcdev->base);
++
++	res = pcdev->res;
++	release_mem_region(res->start, res->end - res->start + 1);
++
++	kfree(pcdev);
++
++	dev_info(&pdev->dev, "PXA Camera driver unloaded\n");
++
++	return 0;
++}
++
++static struct platform_driver pxa_camera_driver = {
++	.driver 	= {
++		.name	= PXA_CAM_DRV_NAME,
++	},
++	.probe		= pxa_camera_probe,
++	.remove		= __exit_p(pxa_camera_remove),
++};
++
++
++static int __devinit pxa_camera_init(void)
++{
++	return platform_driver_register(&pxa_camera_driver);
++}
++
++static void __exit pxa_camera_exit(void)
++{
++	return platform_driver_unregister(&pxa_camera_driver);
++}
++
++module_init(pxa_camera_init);
++module_exit(pxa_camera_exit);
++
++MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
++MODULE_AUTHOR("Guennadi Liakhovetski <kernel at pengutronix.de>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
+index f55d6e8..ec8c65d 100644
+--- a/drivers/media/video/saa5249.c
++++ b/drivers/media/video/saa5249.c
+@@ -701,7 +701,9 @@ static const struct file_operations saa_fops = {
+ 	.open		= saa5249_open,
+ 	.release       	= saa5249_release,
+ 	.ioctl          = saa5249_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek         = no_llseek,
+ };
+ 
+diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
+index 72e344a..716ee7f 100644
+--- a/drivers/media/video/saa6588.c
++++ b/drivers/media/video/saa6588.c
+@@ -44,10 +44,10 @@ static unsigned short normal_i2c[] = {
+ I2C_CLIENT_INSMOD;
+ 
+ /* insmod options */
+-static unsigned int debug = 0;
+-static unsigned int xtal = 0;
+-static unsigned int rbds = 0;
+-static unsigned int plvl = 0;
++static unsigned int debug;
++static unsigned int xtal;
++static unsigned int rbds;
++static unsigned int plvl;
+ static unsigned int bufblocks = 100;
+ 
+ module_param(debug, int, 0644);
+diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
+index 1df2602..4aa82b3 100644
+--- a/drivers/media/video/saa7110.c
++++ b/drivers/media/video/saa7110.c
+@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
+ #include <media/v4l2-common.h>
+ #include <linux/video_decoder.h>
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
+index a0772c5..96c3d43 100644
+--- a/drivers/media/video/saa7111.c
++++ b/drivers/media/video/saa7111.c
+@@ -55,7 +55,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+ 
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
+index bf91a4f..e790755 100644
+--- a/drivers/media/video/saa7114.c
++++ b/drivers/media/video/saa7114.c
+@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(x) (x)->name
+ 
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
+index 41e5e51..416d05d 100644
+--- a/drivers/media/video/saa7115.c
++++ b/drivers/media/video/saa7115.c
+@@ -57,7 +57,7 @@ MODULE_AUTHOR(  "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
+ 		"Hans Verkuil, Mauro Carvalho Chehab");
+ MODULE_LICENSE("GPL");
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, bool, 0644);
+ 
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+@@ -957,7 +957,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
+ 
+ 		if (std == V4L2_STD_PAL_M) {
+ 			reg |= 0x30;
+-		} else if (std == V4L2_STD_PAL_N) {
++		} else if (std == V4L2_STD_PAL_Nc) {
+ 			reg |= 0x20;
+ 		} else if (std == V4L2_STD_PAL_60) {
+ 			reg |= 0x10;
+diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
+index 80bf911..cedb988 100644
+--- a/drivers/media/video/saa711x.c
++++ b/drivers/media/video/saa711x.c
+@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL");
+ 
+ #include <linux/video_decoder.h>
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, " Set the default Debug level.  Default: 0 (Off) - (0-1)");
+ 
+diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
+index 96bc3b1..e086f14 100644
+--- a/drivers/media/video/saa7134/Kconfig
++++ b/drivers/media/video/saa7134/Kconfig
+@@ -37,6 +37,7 @@ config VIDEO_SAA7134_DVB
+ 	select DVB_TDA826X if !DVB_FE_CUSTOMISE
+ 	select DVB_TDA827X if !DVB_FE_CUSTOMISE
+ 	select DVB_ISL6421 if !DVB_FE_CUSTOMISE
++	select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ 	---help---
+ 	  This adds support for DVB cards based on the
+ 	  Philips saa7134 chip.
+diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
+index 047add8..ba30824 100644
+--- a/drivers/media/video/saa7134/saa7134-alsa.c
++++ b/drivers/media/video/saa7134/saa7134-alsa.c
+@@ -31,7 +31,7 @@
+ #include "saa7134.h"
+ #include "saa7134-reg.h"
+ 
+-static unsigned int debug  = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
+ 
+@@ -503,7 +503,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
+ 	/* release the old buffer */
+ 	if (substream->runtime->dma_area) {
+ 		saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+-		videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
++		videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ 		dsp_buffer_free(dev);
+ 		substream->runtime->dma_area = NULL;
+ 	}
+@@ -519,12 +519,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
+ 		return err;
+ 	}
+ 
+-	if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) {
++	if (0 != (err = videobuf_sg_dma_map(&dev->pci->dev, &dev->dmasound.dma))) {
+ 		dsp_buffer_free(dev);
+ 		return err;
+ 	}
+ 	if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
+-		videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
++		videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ 		dsp_buffer_free(dev);
+ 		return err;
+ 	}
+@@ -533,7 +533,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
+ 						dev->dmasound.dma.sglen,
+ 						0))) {
+ 		saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+-		videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
++		videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ 		dsp_buffer_free(dev);
+ 		return err;
+ 	}
+@@ -569,7 +569,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
+ 
+ 	if (substream->runtime->dma_area) {
+ 		saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+-		videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
++		videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ 		dsp_buffer_free(dev);
+ 		substream->runtime->dma_area = NULL;
+ 	}
+@@ -954,10 +954,8 @@ static void snd_saa7134_free(struct snd_card * card)
+ 	if (chip->dev->dmasound.priv_data == NULL)
+ 		return;
+ 
+-	if (chip->irq >= 0) {
+-		synchronize_irq(chip->irq);
++	if (chip->irq >= 0)
+ 		free_irq(chip->irq, &chip->dev->dmasound);
+-	}
+ 
+ 	chip->dev->dmasound.priv_data = NULL;
+ 
+diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
+index 6f57442..9837595 100644
+--- a/drivers/media/video/saa7134/saa7134-cards.c
++++ b/drivers/media/video/saa7134/saa7134-cards.c
+@@ -22,11 +22,15 @@
+ 
+ #include <linux/init.h>
+ #include <linux/module.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
+ 
+ #include "saa7134-reg.h"
+ #include "saa7134.h"
++#include "tuner-xc2028.h"
+ #include <media/v4l2-common.h>
+ #include <media/tveeprom.h>
++#include "tea5767.h"
+ 
+ /* commly used strings */
+ static char name_mute[]    = "mute";
+@@ -1046,7 +1050,7 @@ struct saa7134_board saa7134_boards[] = {
+ 	},
+ 	[SAA7134_BOARD_MANLI_MTV002] = {
+ 		/* Ognjen Nastic <ognjen at logosoft.ba> */
+-		.name           = "Manli MuchTV M-TV002/Behold TV 403 FM",
++		.name           = "Manli MuchTV M-TV002",
+ 		.audio_clock    = 0x00200000,
+ 		.tuner_type     = TUNER_PHILIPS_PAL,
+ 		.radio_type     = UNSET,
+@@ -1073,7 +1077,7 @@ struct saa7134_board saa7134_boards[] = {
+ 	},
+ 	[SAA7134_BOARD_MANLI_MTV001] = {
+ 		/* Ognjen Nastic <ognjen at logosoft.ba> UNTESTED */
+-		.name           = "Manli MuchTV M-TV001/Behold TV 401",
++		.name           = "Manli MuchTV M-TV001",
+ 		.audio_clock    = 0x00200000,
+ 		.tuner_type     = TUNER_PHILIPS_PAL,
+ 		.radio_type     = UNSET,
+@@ -2195,6 +2199,8 @@ struct saa7134_board saa7134_boards[] = {
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_409FM] = {
+ 		/* <http://tuner.beholder.ru>, Sergey <skiv at orel.ru> */
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV 409 FM",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -2202,6 +2208,7 @@ struct saa7134_board saa7134_boards[] = {
+ 		.tuner_addr     = ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 		.tda9887_conf   = TDA9887_PRESENT,
++		.gpiomask       = 0x00008000,
+ 		.inputs         = {{
+ 			  .name = name_tv,
+ 			  .vmux = 3,
+@@ -2908,15 +2915,13 @@ struct saa7134_board saa7134_boards[] = {
+ 		}},
+ 	},
+ 	[SAA7134_BOARD_MD7134_BRIDGE_2] = {
+-		/* This card has two saa7134 chips on it,
+-		   but only one of them is currently working.
+-		   The programming for the primary decoder is
+-		   in SAA7134_BOARD_MD7134 */
++		/* The second saa7134 on this card only serves as DVB-S host bridge */
+ 		.name           = "Medion 7134 Bridge #2",
+ 		.audio_clock    = 0x00187de7,
+ 		.radio_type     = UNSET,
+ 		.tuner_addr	= ADDR_UNSET,
+ 		.radio_addr	= ADDR_UNSET,
++		.mpeg           = SAA7134_MPEG_DVB,
+ 	},
+ 	[SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = {
+ 		.name		= "LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB",
+@@ -3330,7 +3335,7 @@ struct saa7134_board saa7134_boards[] = {
+   /*	Juan Pablo Sormani <sorman at gmail.com> */
+ 		.name           = "Encore ENLTV-FM",
+ 		.audio_clock    = 0x00200000,
+-		.tuner_type     = TUNER_PHILIPS_ATSC,
++		.tuner_type     = TUNER_PHILIPS_FCV1236D,
+ 		.radio_type     = UNSET,
+ 		.tuner_addr	= ADDR_UNSET,
+ 		.radio_addr	= ADDR_UNSET,
+@@ -3575,12 +3580,15 @@ struct saa7134_board saa7134_boards[] = {
+ 		}},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_401] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV 401",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+ 		.radio_type     = UNSET,
+ 		.tuner_addr	= ADDR_UNSET,
+ 		.radio_addr	= ADDR_UNSET,
++		.gpiomask       = 0x00008000,
+ 		.inputs         = {{
+ 			.name = name_svideo,
+ 			.vmux = 8,
+@@ -3601,12 +3609,15 @@ struct saa7134_board saa7134_boards[] = {
+ 		},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_403] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV 403",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+ 		.radio_type     = UNSET,
+ 		.tuner_addr	= ADDR_UNSET,
+ 		.radio_addr	= ADDR_UNSET,
++		.gpiomask       = 0x00008000,
+ 		.inputs         = {{
+ 			.name = name_svideo,
+ 			.vmux = 8,
+@@ -3623,12 +3634,15 @@ struct saa7134_board saa7134_boards[] = {
+ 		}},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_403FM] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV 403 FM",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+ 		.radio_type     = UNSET,
+ 		.tuner_addr	= ADDR_UNSET,
+ 		.radio_addr	= ADDR_UNSET,
++		.gpiomask       = 0x00008000,
+ 		.inputs         = {{
+ 			.name = name_svideo,
+ 			.vmux = 8,
+@@ -3649,6 +3663,8 @@ struct saa7134_board saa7134_boards[] = {
+ 		},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_405] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV 405",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3656,6 +3672,7 @@ struct saa7134_board saa7134_boards[] = {
+ 		.tuner_addr     = ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 		.tda9887_conf   = TDA9887_PRESENT,
++		.gpiomask       = 0x00008000,
+ 		.inputs         = {{
+ 			.name = name_svideo,
+ 			.vmux = 8,
+@@ -3673,6 +3690,8 @@ struct saa7134_board saa7134_boards[] = {
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_405FM] = {
+ 		/* Sergey <skiv at orel.ru> */
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV 405 FM",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3680,6 +3699,7 @@ struct saa7134_board saa7134_boards[] = {
+ 		.tuner_addr     = ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 		.tda9887_conf   = TDA9887_PRESENT,
++		.gpiomask       = 0x00008000,
+ 		.inputs         = {{
+ 			.name = name_svideo,
+ 			.vmux = 8,
+@@ -3700,6 +3720,8 @@ struct saa7134_board saa7134_boards[] = {
+ 		},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_407] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name 		= "Beholder BeholdTV 407",
+ 		.audio_clock 	= 0x00187de7,
+ 		.tuner_type 	= TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3707,7 +3729,7 @@ struct saa7134_board saa7134_boards[] = {
+ 		.tuner_addr 	= ADDR_UNSET,
+ 		.radio_addr 	= ADDR_UNSET,
+ 		.tda9887_conf 	= TDA9887_PRESENT,
+-		.gpiomask = 0xc0c000,
++		.gpiomask       = 0x00008000,
+ 		.inputs = {{
+ 			.name = name_svideo,
+ 			.vmux = 8,
+@@ -3727,6 +3749,8 @@ struct saa7134_board saa7134_boards[] = {
+ 		}},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_407FM] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name 		= "Beholder BeholdTV 407 FM",
+ 		.audio_clock 	= 0x00187de7,
+ 		.tuner_type 	= TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3734,7 +3758,7 @@ struct saa7134_board saa7134_boards[] = {
+ 		.tuner_addr 	= ADDR_UNSET,
+ 		.radio_addr 	= ADDR_UNSET,
+ 		.tda9887_conf 	= TDA9887_PRESENT,
+-		.gpiomask = 0xc0c000,
++		.gpiomask       = 0x00008000,
+ 		.inputs = {{
+ 			.name = name_svideo,
+ 			.vmux = 8,
+@@ -3759,6 +3783,8 @@ struct saa7134_board saa7134_boards[] = {
+ 		},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_409] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV 409",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3766,6 +3792,7 @@ struct saa7134_board saa7134_boards[] = {
+ 		.tuner_addr     = ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 		.tda9887_conf   = TDA9887_PRESENT,
++		.gpiomask       = 0x00008000,
+ 		.inputs         = {{
+ 			.name = name_tv,
+ 			.vmux = 3,
+@@ -3782,6 +3809,8 @@ struct saa7134_board saa7134_boards[] = {
+ 		}},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_505FM] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV 505 FM/RDS",
+ 		.audio_clock    = 0x00200000,
+ 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3789,6 +3818,7 @@ struct saa7134_board saa7134_boards[] = {
+ 		.tuner_addr     = ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 		.tda9887_conf   = TDA9887_PRESENT,
++		.gpiomask       = 0x00008000,
+ 		.inputs         = {{
+ 			.name = name_tv,
+ 			.vmux = 3,
+@@ -3813,6 +3843,8 @@ struct saa7134_board saa7134_boards[] = {
+ 		},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_507_9FM] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3820,6 +3852,7 @@ struct saa7134_board saa7134_boards[] = {
+ 		.tuner_addr     = ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 		.tda9887_conf   = TDA9887_PRESENT,
++		.gpiomask       = 0x00008000,
+ 		.inputs         = {{
+ 			.name = name_tv,
+ 			.vmux = 3,
+@@ -3840,6 +3873,8 @@ struct saa7134_board saa7134_boards[] = {
+ 		},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
++		/*       Beholder Intl. Ltd. 2008      */
++		/*Dmitry Belimov <d.belimov at gmail.com> */
+ 		.name           = "Beholder BeholdTV Columbus TVFM",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_ALPS_TSBE5_PAL,
+@@ -3847,23 +3882,28 @@ struct saa7134_board saa7134_boards[] = {
+ 		.tuner_addr     = ADDR_UNSET,
+ 		.radio_addr     = ADDR_UNSET,
+ 		.tda9887_conf   = TDA9887_PRESENT,
++		.gpiomask       = 0x000A8004,
+ 		.inputs         = {{
+ 			.name = name_tv,
+ 			.vmux = 3,
+ 			.amux = TV,
+ 			.tv   = 1,
+-		},{
++			.gpio = 0x000A8004,
++		}, {
+ 			.name = name_comp1,
+ 			.vmux = 1,
+ 			.amux = LINE1,
+-		},{
++			.gpio = 0x000A8000,
++		}, {
+ 			.name = name_svideo,
+ 			.vmux = 8,
+ 			.amux = LINE1,
+-		}},
++			.gpio = 0x000A8000,
++		} },
+ 		.radio = {
+ 			.name = name_radio,
+ 			.amux = LINE2,
++			.gpio = 0x000A8000,
+ 		},
+ 	},
+ 	[SAA7134_BOARD_BEHOLD_607_9FM] = {
+@@ -3992,6 +4032,221 @@ struct saa7134_board saa7134_boards[] = {
+ 			.gpio = 0x6000,
+ 		},
+ 	},
++	[SAA7134_BOARD_PHILIPS_SNAKE] = {
++		.name           = "NXP Snake DVB-S reference design",
++		.audio_clock    = 0x00200000,
++		.tuner_type     = TUNER_ABSENT,
++		.radio_type     = UNSET,
++		.tuner_addr     = ADDR_UNSET,
++		.radio_addr     = ADDR_UNSET,
++		.mpeg           = SAA7134_MPEG_DVB,
++		.inputs = {{
++			.name   = name_comp1,
++			.vmux   = 3,
++			.amux   = LINE1,
++		}, {
++			.name   = name_svideo,
++			.vmux   = 8,
++			.amux   = LINE1,
++		} },
++	},
++	[SAA7134_BOARD_CREATIX_CTX953] = {
++		.name         = "Medion/Creatix CTX953 Hybrid",
++		.audio_clock  = 0x00187de7,
++		.tuner_type   = TUNER_PHILIPS_TDA8290,
++		.radio_type   = UNSET,
++		.tuner_addr   = ADDR_UNSET,
++		.radio_addr   = ADDR_UNSET,
++		.tuner_config = 0,
++		.mpeg         = SAA7134_MPEG_DVB,
++		.inputs       = {{
++			.name = name_tv,
++			.vmux = 1,
++			.amux = TV,
++			.tv   = 1,
++		}, {
++			.name = name_comp1,
++			.vmux = 0,
++			.amux = LINE1,
++		}, {
++			.name = name_svideo,
++			.vmux = 8,
++			.amux = LINE1,
++		} },
++	},
++	[SAA7134_BOARD_MSI_TVANYWHERE_AD11] = {
++		.name           = "MSI TV at nywhere A/D v1.1",
++		.audio_clock    = 0x00187de7,
++		.tuner_type     = TUNER_PHILIPS_TDA8290,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.tuner_config   = 2,
++		.mpeg           = SAA7134_MPEG_DVB,
++		.gpiomask       = 0x0200000,
++		.inputs = { {
++			.name   = name_tv,
++			.vmux   = 1,
++			.amux   = TV,
++			.tv     = 1,
++		}, {
++			.name   = name_comp1,
++			.vmux   = 3,
++			.amux   = LINE1,
++		}, {
++			.name   = name_svideo,
++			.vmux   = 8,
++			.amux   = LINE1,
++		} },
++		.radio = {
++			.name   = name_radio,
++			.amux   = TV,
++			.gpio   = 0x0200000,
++		},
++	},
++	[SAA7134_BOARD_AVERMEDIA_CARDBUS_506] = {
++		.name           = "AVerMedia Cardbus TV/Radio (E506R)",
++		.audio_clock    = 0x187de7,
++		.tuner_type     = TUNER_XC2028,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		 /*
++		    TODO:
++		 .mpeg           = SAA7134_MPEG_DVB,
++		 */
++
++		 .inputs         = {{
++			 .name = name_tv,
++			 .vmux = 1,
++			 .amux = TV,
++			 .tv   = 1,
++		 }, {
++			 .name = name_comp1,
++			 .vmux = 3,
++			 .amux = LINE2,
++		 }, {
++			 .name = name_svideo,
++			 .vmux = 8,
++			 .amux = LINE1,
++		 } },
++		 .radio = {
++			 .name = name_radio,
++			 .amux = TV,
++		 },
++	},
++	[SAA7134_BOARD_AVERMEDIA_A16D] = {
++		.name           = "AVerMedia Hybrid TV/Radio (A16D)",
++		.audio_clock    = 0x187de7,
++		.tuner_type     = TUNER_XC2028,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.inputs         = {{
++			.name = name_tv,
++			.vmux = 1,
++			.amux = TV,
++			.tv   = 1,
++		}, {
++			.name = name_svideo,
++			.vmux = 8,
++			.amux = LINE1,
++		} },
++		.radio = {
++			.name = name_radio,
++			.amux = LINE1,
++		},
++	},
++	[SAA7134_BOARD_AVERMEDIA_M115] = {
++		.name           = "Avermedia M115",
++		.audio_clock    = 0x187de7,
++		.tuner_type     = TUNER_XC2028,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.inputs         = {{
++			.name = name_tv,
++			.vmux = 1,
++			.amux = TV,
++			.tv   = 1,
++		}, {
++			.name = name_comp1,
++			.vmux = 3,
++			.amux = LINE1,
++		}, {
++			.name = name_svideo,
++			.vmux = 8,
++			.amux = LINE2,
++		} },
++	},
++	[SAA7134_BOARD_VIDEOMATE_T750] = {
++		/* John Newbigin <jn at it.swin.edu.au> */
++		.name           = "Compro VideoMate T750",
++		.audio_clock    = 0x00187de7,
++		.tuner_type     = TUNER_XC2028,
++		.radio_type     = UNSET,
++		.tuner_addr	= ADDR_UNSET,
++		.radio_addr	= ADDR_UNSET,
++		.mpeg           = SAA7134_MPEG_DVB,
++		.inputs = {{
++			.name   = name_tv,
++			.vmux   = 3,
++			.amux   = TV,
++			.tv     = 1,
++		}, {
++			.name   = name_comp1,
++			.vmux   = 1,
++			.amux   = LINE2,
++		}, {
++			.name   = name_svideo,
++			.vmux   = 8,
++			.amux   = LINE2,
++		} },
++		.radio = {
++			.name = name_radio,
++			.amux = TV,
++		}
++	},
++	[SAA7134_BOARD_AVERMEDIA_A700_PRO] = {
++		/* Matthias Schwarzott <zzam at gentoo.org> */
++		.name           = "Avermedia DVB-S Pro A700",
++		.audio_clock    = 0x00187de7,
++		.tuner_type     = TUNER_ABSENT,
++		.radio_type     = UNSET,
++		.tuner_addr     = ADDR_UNSET,
++		.radio_addr     = ADDR_UNSET,
++		/* no DVB support for now */
++		/* .mpeg           = SAA7134_MPEG_DVB, */
++		.inputs         = { {
++			.name = name_comp,
++			.vmux = 1,
++			.amux = LINE1,
++		}, {
++			.name = name_svideo,
++			.vmux = 6,
++			.amux = LINE1,
++		} },
++	},
++	[SAA7134_BOARD_AVERMEDIA_A700_HYBRID] = {
++		/* Matthias Schwarzott <zzam at gentoo.org> */
++		.name           = "Avermedia DVB-S Hybrid+FM A700",
++		.audio_clock    = 0x00187de7,
++		.tuner_type     = TUNER_ABSENT, /* TUNER_XC2028 */
++		.radio_type     = UNSET,
++		.tuner_addr     = ADDR_UNSET,
++		.radio_addr     = ADDR_UNSET,
++		/* no DVB support for now */
++		/* .mpeg           = SAA7134_MPEG_DVB, */
++		.inputs         = { {
++			.name = name_comp,
++			.vmux = 1,
++			.amux = LINE1,
++		}, {
++			.name = name_svideo,
++			.vmux = 6,
++			.amux = LINE1,
++		} },
++	},
+ };
+ 
+ const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
+@@ -4224,6 +4479,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
+ 		.driver_data  = SAA7134_BOARD_MD2819,
+ 	},{
+ 		.vendor       = PCI_VENDOR_ID_PHILIPS,
++		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
++		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
++		.subdevice    = 0xa7a1,
++		.driver_data  = SAA7134_BOARD_AVERMEDIA_A700_PRO,
++	}, {
++		.vendor       = PCI_VENDOR_ID_PHILIPS,
++		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
++		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
++		.subdevice    = 0xa7a2,
++		.driver_data  = SAA7134_BOARD_AVERMEDIA_A700_HYBRID,
++	}, {
++		.vendor       = PCI_VENDOR_ID_PHILIPS,
+ 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ 		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+ 		.subdevice    = 0x2115,
+@@ -4942,7 +5209,43 @@ struct pci_device_id saa7134_pci_tbl[] = {
+ 		.subvendor    = 0x1822, /*Twinhan Technology Co. Ltd*/
+ 		.subdevice    = 0x0022,
+ 		.driver_data  = SAA7134_BOARD_TWINHAN_DTV_DVB_3056,
++	}, {
++		.vendor       = PCI_VENDOR_ID_PHILIPS,
++		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
++		.subvendor    = 0x16be,
++		.subdevice    = 0x0010, /* Medion version CTX953_V.1.4.3 */
++		.driver_data  = SAA7134_BOARD_CREATIX_CTX953,
++	}, {
++		.vendor       = PCI_VENDOR_ID_PHILIPS,
++		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
++		.subvendor    = 0x1462, /* MSI */
++		.subdevice    = 0x8625, /* TV at nywhere A/D v1.1 */
++		.driver_data  = SAA7134_BOARD_MSI_TVANYWHERE_AD11,
+ 	},{
++		.vendor       = PCI_VENDOR_ID_PHILIPS,
++		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
++		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
++		.subdevice    = 0xf436,
++		.driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS_506,
++	}, {
++		.vendor       = PCI_VENDOR_ID_PHILIPS,
++		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
++		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
++		.subdevice    = 0xf936,
++		.driver_data  = SAA7134_BOARD_AVERMEDIA_A16D,
++	}, {
++		.vendor       = PCI_VENDOR_ID_PHILIPS,
++		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
++		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
++		.subdevice    = 0xa836,
++		.driver_data  = SAA7134_BOARD_AVERMEDIA_M115,
++	}, {
++		.vendor       = PCI_VENDOR_ID_PHILIPS,
++		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
++		.subvendor    = 0x185b,
++		.subdevice    = 0xc900,
++		.driver_data  = SAA7134_BOARD_VIDEOMATE_T750,
++	}, {
+ 		/* --- boards without eeprom + subsystem ID --- */
+ 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+ 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+@@ -4998,6 +5301,77 @@ static void board_flyvideo(struct saa7134_dev *dev)
+ 	       dev->name, dev->name, dev->name);
+ }
+ 
++static int saa7134_xc2028_callback(struct saa7134_dev *dev,
++				   int command, int arg)
++{
++	switch (command) {
++	case XC2028_TUNER_RESET:
++		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
++		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
++		mdelay(250);
++		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0);
++		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0);
++		mdelay(250);
++		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
++		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
++		mdelay(250);
++		saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02);
++		saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81);
++		saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7);
++		saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03);
++		saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2,
++			   0x0001e000, 0x0001e000);
++		return 0;
++	}
++	return -EINVAL;
++}
++
++
++static int saa7134_tda8290_callback(struct saa7134_dev *dev,
++				    int command, int arg)
++{
++	u8 sync_control;
++
++	switch (command) {
++	case 0: /* switch LNA gain through GPIO 22*/
++		saa7134_set_gpio(dev, 22, arg) ;
++		break;
++	case 1: /* vsync output at GPIO22. 50 / 60Hz */
++		saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80);
++		saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03);
++		if (arg == 1)
++			sync_control = 11;
++		else
++			sync_control = 17;
++		saa_writeb(SAA7134_VGATE_START, sync_control);
++		saa_writeb(SAA7134_VGATE_STOP, sync_control + 1);
++		saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++int saa7134_tuner_callback(void *priv, int command, int arg)
++{
++	struct saa7134_dev *dev = priv;
++	if (dev != NULL) {
++		switch (dev->tuner_type) {
++		case TUNER_PHILIPS_TDA8290:
++			return saa7134_tda8290_callback(dev, command, arg);
++		case TUNER_XC2028:
++			return saa7134_xc2028_callback(dev, command, arg);
++		}
++	} else {
++		printk(KERN_ERR "saa7134: Error - device struct undefined.\n");
++		return -EINVAL;
++	}
++	return -EINVAL;
++}
++EXPORT_SYMBOL(saa7134_tuner_callback);
++
+ /* ----------------------------------------------------------- */
+ 
+ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data)
+@@ -5067,6 +5441,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+ 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+ 	case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+ 	case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
++	case SAA7134_BOARD_VIDEOMATE_T750:
+ 	case SAA7134_BOARD_MANLI_MTV001:
+ 	case SAA7134_BOARD_MANLI_MTV002:
+ 	case SAA7134_BOARD_BEHOLD_409FM:
+@@ -5133,11 +5508,29 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+ 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000);
+ 		break;
+ 	case SAA7134_BOARD_AVERMEDIA_CARDBUS:
+-	case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
++	case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
++	case SAA7134_BOARD_AVERMEDIA_M115:
++	case SAA7134_BOARD_AVERMEDIA_A16D:
++		/* power-down tuner chip */
++		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0);
++		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0);
++		msleep(10);
+ 		/* power-up tuner chip */
+ 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0xffffffff);
+ 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
+-		msleep(1);
++		msleep(10);
++		break;
++	case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
++		/* power-down tuner chip */
++		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x000A8004, 0x000A8004);
++		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0);
++		msleep(10);
++		/* power-up tuner chip */
++		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x000A8004, 0x000A8004);
++		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0x000A8004);
++		msleep(10);
++		/* remote via GPIO */
++		dev->has_remote = SAA7134_REMOTE_GPIO;
+ 		break;
+ 	case SAA7134_BOARD_RTD_VFG7350:
+ 
+@@ -5160,7 +5553,6 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+ 		dev->has_remote = SAA7134_REMOTE_I2C;
+ 		break;
+ 	case SAA7134_BOARD_AVERMEDIA_A169_B:
+-	case SAA7134_BOARD_MD7134_BRIDGE_2:
+ 		printk("%s: %s: dual saa713x broadcast decoders\n"
+ 		       "%s: Sorry, none of the inputs to this chip are supported yet.\n"
+ 		       "%s: Dual decoder functionality is disabled for now, use the other chip.\n",
+@@ -5172,6 +5564,15 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+ 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x8c040007, 0x8c040007);
+ 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd);
+ 		break;
++	case SAA7134_BOARD_AVERMEDIA_A700_PRO:
++	case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
++		/* write windows gpio values */
++		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x80040100, 0x80040100);
++		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
++		printk("%s: %s: hybrid analog/dvb card\n"
++		       "%s: Sorry, only the analog inputs are supported for now.\n",
++			dev->name, card(dev).name, dev->name);
++		break;
+ 	}
+ 	return 0;
+ }
+@@ -5200,11 +5601,16 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+ 		dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+ 
+ 		if (TUNER_ABSENT != dev->tuner_type) {
+-				tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
+-				tun_setup.type = dev->tuner_type;
+-				tun_setup.addr = ADDR_UNSET;
++			tun_setup.mode_mask = T_RADIO     |
++					      T_ANALOG_TV |
++					      T_DIGITAL_TV;
++			tun_setup.type = dev->tuner_type;
++			tun_setup.addr = ADDR_UNSET;
++			tun_setup.tuner_callback = saa7134_tuner_callback;
+ 
+-				saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR, &tun_setup);
++			saa7134_i2c_call_clients(dev,
++						 TUNER_SET_TYPE_ADDR,
++						 &tun_setup);
+ 		}
+ 		break;
+ 	case SAA7134_BOARD_MD7134:
+@@ -5275,14 +5681,25 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+ 						 &tda9887_cfg);
+ 		}
+ 
+-		tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
++		tun_setup.mode_mask = T_RADIO     |
++				      T_ANALOG_TV |
++				      T_DIGITAL_TV;
+ 		tun_setup.type = dev->tuner_type;
+ 		tun_setup.addr = ADDR_UNSET;
+ 
+-		saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
++		saa7134_i2c_call_clients(dev,
++					 TUNER_SET_TYPE_ADDR, &tun_setup);
+ 		}
+ 		break;
+ 	case SAA7134_BOARD_PHILIPS_EUROPA:
++		if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) {
++			/* Reconfigure board as Snake reference design */
++			dev->board = SAA7134_BOARD_PHILIPS_SNAKE;
++			dev->tuner_type = saa7134_boards[dev->board].tuner_type;
++			printk(KERN_INFO "%s: Reconfigured board as %s\n",
++				dev->name, saa7134_boards[dev->board].name);
++			break;
++		}
+ 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+ 	case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
+ 		/* The Philips EUROPA based hybrid boards have the tuner connected through
+@@ -5333,6 +5750,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+ 	case SAA7134_BOARD_MEDION_MD8800_QUADRO:
+ 	case SAA7134_BOARD_AVERMEDIA_SUPER_007:
+ 	case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
++	case SAA7134_BOARD_CREATIX_CTX953:
+ 		/* this is a hybrid board, initialize to analog mode
+ 		 * and configure firmware eeprom address
+ 		 */
+@@ -5402,13 +5820,46 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+ 			break;
+ 		}
+ 		break;
++	case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
++		{
++		struct v4l2_priv_tun_config tea5767_cfg;
++		struct tea5767_ctrl ctl;
++
++		dev->i2c_client.addr = 0xC0;
++		/* set TEA5767(analog FM) defines */
++		memset(&ctl, 0, sizeof(ctl));
++		ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
++		tea5767_cfg.tuner = TUNER_TEA5767;
++		tea5767_cfg.priv  = &ctl;
++		saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg);
++		}
++		break;
+ 	}
++
++	if (dev->tuner_type == TUNER_XC2028) {
++		struct v4l2_priv_tun_config  xc2028_cfg;
++		struct xc2028_ctrl           ctl;
++
++		memset(&xc2028_cfg, 0, sizeof(ctl));
++		memset(&ctl, 0, sizeof(ctl));
++
++		ctl.fname   = XC2028_DEFAULT_FIRMWARE;
++		ctl.max_len = 64;
++
++		switch (dev->board) {
++		case SAA7134_BOARD_AVERMEDIA_A16D:
++			ctl.demod = XC3028_FE_ZARLINK456;
++			break;
++		default:
++			ctl.demod = XC3028_FE_OREN538;
++			ctl.mts = 1;
++		}
++
++		xc2028_cfg.tuner = TUNER_XC2028;
++		xc2028_cfg.priv  = &ctl;
++
++		saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
++	}
++
+ 	return 0;
+ }
+-
+-/* ----------------------------------------------------------- */
+-/*
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
+diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
+index 58ab163..eec1278 100644
+--- a/drivers/media/video/saa7134/saa7134-core.c
++++ b/drivers/media/video/saa7134/saa7134-core.c
+@@ -42,23 +42,23 @@ MODULE_LICENSE("GPL");
+ 
+ /* ------------------------------------------------------------------ */
+ 
+-static unsigned int irq_debug = 0;
++static unsigned int irq_debug;
+ module_param(irq_debug, int, 0644);
+ MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
+ 
+-static unsigned int core_debug = 0;
++static unsigned int core_debug;
+ module_param(core_debug, int, 0644);
+ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+ 
+-static unsigned int gpio_tracking = 0;
++static unsigned int gpio_tracking;
+ module_param(gpio_tracking, int, 0644);
+ MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
+ 
+-static unsigned int alsa = 0;
++static unsigned int alsa;
+ module_param(alsa, int, 0644);
+ MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]");
+ 
+-static unsigned int oss = 0;
++static unsigned int oss;
+ module_param(oss, int, 0644);
+ MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]");
+ 
+@@ -142,39 +142,6 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
+ 	}
+ }
+ 
+-int saa7134_tuner_callback(void *ptr, int command, int arg)
+-{
+-	u8 sync_control;
+-	struct saa7134_dev *dev = ptr;
+-
+-	switch (dev->tuner_type) {
+-	case TUNER_PHILIPS_TDA8290:
+-		switch (command) {
+-		case 0: /* switch LNA gain through GPIO 22*/
+-			saa7134_set_gpio(dev, 22, arg) ;
+-			break;
+-		case 1: /* vsync output at GPIO22. 50 / 60Hz */
+-			dprintk("setting GPIO22 to vsync %d\n", arg);
+-			saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80);
+-			saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03);
+-			if (arg == 1)
+-				sync_control = 11;
+-			else
+-				sync_control = 17;
+-			saa_writeb(SAA7134_VGATE_START, sync_control);
+-			saa_writeb(SAA7134_VGATE_STOP, sync_control + 1);
+-			saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00);
+-			break;
+-		default:
+-			return -EINVAL;
+-		}
+-		break;
+-	default:
+-		return -ENODEV;
+-	}
+-	return 0;
+-}
+-
+ /* ------------------------------------------------------------------ */
+ 
+ 
+@@ -897,6 +864,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
+ 	struct saa7134_dev *dev;
+ 	struct saa7134_mpeg_ops *mops;
+ 	int err;
++	int mask;
++
++	if (saa7134_devcount == SAA7134_MAXBOARDS)
++		return -ENOMEM;
+ 
+ 	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+ 	if (NULL == dev)
+@@ -1094,6 +1065,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
+ 	if (TUNER_ABSENT != dev->tuner_type)
+ 		saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
+ 
++	if (card(dev).gpiomask != 0) {
++		mask = card(dev).gpiomask;
++		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   mask, mask);
++		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, 0);
++	}
+ 	return 0;
+ 
+  fail4:
+diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
+index ea2be9e..2d16be2 100644
+--- a/drivers/media/video/saa7134/saa7134-dvb.c
++++ b/drivers/media/video/saa7134/saa7134-dvb.c
+@@ -33,33 +33,40 @@
+ #include "saa7134.h"
+ #include <media/v4l2-common.h>
+ #include "dvb-pll.h"
++#include <dvb_frontend.h>
+ 
+ #include "mt352.h"
+ #include "mt352_priv.h" /* FIXME */
+ #include "tda1004x.h"
+ #include "nxt200x.h"
++#include "tuner-xc2028.h"
+ 
+ #include "tda10086.h"
+ #include "tda826x.h"
+ #include "tda827x.h"
+ #include "isl6421.h"
++#include "isl6405.h"
++#include "lnbp21.h"
++#include "tuner-simple.h"
+ 
+ MODULE_AUTHOR("Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]");
+ MODULE_LICENSE("GPL");
+ 
+-static unsigned int antenna_pwr = 0;
++static unsigned int antenna_pwr;
+ 
+ module_param(antenna_pwr, int, 0444);
+ MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
+ 
+-static int use_frontend = 0;
++static int use_frontend;
+ module_param(use_frontend, int, 0644);
+ MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off).");
+ 
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk(fmt, arg...)	do { if (debug) \
+ 	printk(KERN_DEBUG "%s/dvb: " fmt, dev->name , ## arg); } while(0)
+ 
+@@ -91,7 +98,7 @@ static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
+ 	saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 28));
+ 	udelay(10);
+ 	ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27);
+-	dprintk("%s %s\n", __FUNCTION__, ok ? "on" : "off");
++	dprintk("%s %s\n", __func__, ok ? "on" : "off");
+ 
+ 	if (!ok)
+ 		saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 26));
+@@ -111,7 +118,7 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe)
+ 	static u8 irq_cfg []       = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 };
+ 	struct saa7134_dev *dev= fe->dvb->priv;
+ 
+-	dprintk("%s called\n", __FUNCTION__);
++	dprintk("%s called\n", __func__);
+ 
+ 	mt352_write(fe, clock_config,   sizeof(clock_config));
+ 	udelay(200);
+@@ -146,6 +153,26 @@ static int mt352_aver777_init(struct dvb_frontend* fe)
+ 	return 0;
+ }
+ 
++static int mt352_aver_a16d_init(struct dvb_frontend *fe)
++{
++	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x2d };
++	static u8 reset []         = { RESET,      0x80 };
++	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
++	static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0xa0 };
++	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 };
++
++	mt352_write(fe, clock_config,   sizeof(clock_config));
++	udelay(200);
++	mt352_write(fe, reset,          sizeof(reset));
++	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
++	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
++	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
++
++	return 0;
++}
++
++
++
+ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
+ 					   struct dvb_frontend_parameters* params)
+ {
+@@ -188,6 +215,16 @@ static struct mt352_config avermedia_777 = {
+ 	.demod_init    = mt352_aver777_init,
+ };
+ 
++static struct mt352_config avermedia_16d = {
++	.demod_address = 0xf,
++	.demod_init    = mt352_aver_a16d_init,
++};
++
++static struct mt352_config avermedia_e506r_mt352_dev = {
++	.demod_address   = (0x1e >> 1),
++	.no_tuner        = 1,
++};
++
+ /* ==================================================================
+  * tda1004x based DVB-T cards, helper functions
+  */
+@@ -430,8 +467,6 @@ static struct tda1004x_config philips_europa_config = {
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+ 
+-/* ------------------------------------------------------------------ */
+-
+ static struct tda1004x_config medion_cardbus = {
+ 	.demod_address = 0x08,
+ 	.invert        = 1,
+@@ -447,47 +482,6 @@ static struct tda1004x_config medion_cardbus = {
+  * tda 1004x based cards with philips silicon tuner
+  */
+ 
+-static void philips_tda827x_lna_gain(struct dvb_frontend *fe, int high)
+-{
+-	struct saa7134_dev *dev = fe->dvb->priv;
+-	struct tda1004x_state *state = fe->demodulator_priv;
+-	u8 addr = state->config->i2c_gate;
+-	u8 config = state->config->tuner_config;
+-	u8 GP00_CF[] = {0x20, 0x01};
+-	u8 GP00_LEV[] = {0x22, 0x00};
+-
+-	struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = GP00_CF, .len = 2};
+-	if (config) {
+-		if (high) {
+-			dprintk("setting LNA to high gain\n");
+-		} else {
+-			dprintk("setting LNA to low gain\n");
+-		}
+-	}
+-	switch (config) {
+-	case 0: /* no LNA */
+-		break;
+-	case 1: /* switch is GPIO 0 of tda8290 */
+-	case 2:
+-		/* turn Vsync off */
+-		saa7134_set_gpio(dev, 22, 0);
+-		GP00_LEV[1] = high ? 0 : 1;
+-		if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
+-			wprintk("could not access tda8290 at addr: 0x%02x\n",
+-				addr << 1);
+-			return;
+-		}
+-		msg.buf = GP00_LEV;
+-		if (config == 2)
+-			GP00_LEV[1] = high ? 1 : 0;
+-		i2c_transfer(&dev->i2c_adap, &msg, 1);
+-		break;
+-	case 3: /* switch with GPIO of saa713x */
+-		saa7134_set_gpio(dev, 22, high);
+-		break;
+-	}
+-}
+-
+ static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
+ {
+ 	struct tda1004x_state *state = fe->demodulator_priv;
+@@ -510,8 +504,6 @@ static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
+ 	return 0;
+ }
+ 
+-/* ------------------------------------------------------------------ */
+-
+ static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
+ {
+ 	struct saa7134_dev *dev = fe->dvb->priv;
+@@ -546,28 +538,57 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
+ 	return 0;
+ }
+ 
+-static struct tda827x_config tda827x_cfg = {
+-	.lna_gain = philips_tda827x_lna_gain,
+-	.init = philips_tda827x_tuner_init,
+-	.sleep = philips_tda827x_tuner_sleep
+-};
+-
+-static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *tda_conf)
++static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf,
++							  struct tda827x_config *tuner_conf)
+ {
+-	dev->dvb.frontend = dvb_attach(tda10046_attach, tda_conf, &dev->i2c_adap);
++	dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
+ 	if (dev->dvb.frontend) {
+-		if (tda_conf->i2c_gate)
++		if (cdec_conf->i2c_gate)
+ 			dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+-		if (dvb_attach(tda827x_attach, dev->dvb.frontend, tda_conf->tuner_address,
+-						&dev->i2c_adap,&tda827x_cfg) == NULL) {
++		if (dvb_attach(tda827x_attach, dev->dvb.frontend, cdec_conf->tuner_address,
++							&dev->i2c_adap, tuner_conf) == NULL) {
+ 			wprintk("no tda827x tuner found at addr: %02x\n",
+-				tda_conf->tuner_address);
++				cdec_conf->tuner_address);
+ 		}
+ 	}
+ }
+ 
+ /* ------------------------------------------------------------------ */
+ 
++static struct tda827x_config tda827x_cfg_0 = {
++	.tuner_callback = saa7134_tuner_callback,
++	.init = philips_tda827x_tuner_init,
++	.sleep = philips_tda827x_tuner_sleep,
++	.config = 0,
++	.switch_addr = 0
++};
++
++static struct tda827x_config tda827x_cfg_1 = {
++	.tuner_callback = saa7134_tuner_callback,
++	.init = philips_tda827x_tuner_init,
++	.sleep = philips_tda827x_tuner_sleep,
++	.config = 1,
++	.switch_addr = 0x4b
++};
++
++static struct tda827x_config tda827x_cfg_2 = {
++	.tuner_callback = saa7134_tuner_callback,
++	.init = philips_tda827x_tuner_init,
++	.sleep = philips_tda827x_tuner_sleep,
++	.config = 2,
++	.switch_addr = 0x4b
++};
++
++static struct tda827x_config tda827x_cfg_2_sw42 = {
++	.tuner_callback = saa7134_tuner_callback,
++	.init = philips_tda827x_tuner_init,
++	.sleep = philips_tda827x_tuner_sleep,
++	.config = 2,
++	.switch_addr = 0x42
++};
++
++/* ------------------------------------------------------------------ */
++
+ static struct tda1004x_config tda827x_lifeview_config = {
+ 	.demod_address = 0x08,
+ 	.invert        = 1,
+@@ -590,7 +611,6 @@ static struct tda1004x_config philips_tiger_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 0,
+ 	.antenna_switch= 1,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -605,7 +625,6 @@ static struct tda1004x_config cinergy_ht_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 0,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+ 
+@@ -619,7 +638,6 @@ static struct tda1004x_config cinergy_ht_pci_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x60,
+-	.tuner_config  = 0,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+ 
+@@ -633,7 +651,6 @@ static struct tda1004x_config philips_tiger_s_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 2,
+ 	.antenna_switch= 1,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -648,7 +665,6 @@ static struct tda1004x_config pinnacle_pctv_310i_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 1,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+ 
+@@ -662,7 +678,6 @@ static struct tda1004x_config hauppauge_hvr_1110_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 1,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+ 
+@@ -676,7 +691,6 @@ static struct tda1004x_config asus_p7131_dual_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 0,
+ 	.antenna_switch= 2,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -715,7 +729,6 @@ static struct tda1004x_config md8800_dvbt_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x60,
+-	.tuner_config  = 0,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+ 
+@@ -729,7 +742,6 @@ static struct tda1004x_config asus_p7131_4871_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 2,
+ 	.antenna_switch= 2,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -744,7 +756,6 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 2,
+ 	.antenna_switch= 2,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -759,7 +770,6 @@ static struct tda1004x_config kworld_dvb_t_210_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 2,
+ 	.antenna_switch= 1,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -774,7 +784,6 @@ static struct tda1004x_config avermedia_super_007_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x4b,
+ 	.tuner_address = 0x60,
+-	.tuner_config  = 0,
+ 	.antenna_switch= 1,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -789,7 +798,6 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
+ 	.if_freq       = TDA10046_FREQ_045,
+ 	.i2c_gate      = 0x42,
+ 	.tuner_address = 0x61,
+-	.tuner_config  = 2,
+ 	.antenna_switch = 1,
+ 	.request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -817,9 +825,10 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
+ }
+ 
+ static struct tda827x_config ads_duo_cfg = {
+-	.lna_gain = philips_tda827x_lna_gain,
++	.tuner_callback = saa7134_tuner_callback,
+ 	.init = ads_duo_tuner_init,
+-	.sleep = ads_duo_tuner_sleep
++	.sleep = ads_duo_tuner_sleep,
++	.config = 0
+ };
+ 
+ static struct tda1004x_config ads_tech_duo_config = {
+@@ -842,8 +851,73 @@ static struct tda10086_config flydvbs = {
+ 	.demod_address = 0x0e,
+ 	.invert = 0,
+ 	.diseqc_tone = 0,
++	.xtal_freq = TDA10086_XTAL_16M,
+ };
+ 
++static struct tda10086_config sd1878_4m = {
++	.demod_address = 0x0e,
++	.invert = 0,
++	.diseqc_tone = 0,
++	.xtal_freq = TDA10086_XTAL_4M,
++};
++
++/* ------------------------------------------------------------------
++ * special case: lnb supply is connected to the gated i2c
++ */
++
++static int md8800_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
++{
++	int res = -EIO;
++	struct saa7134_dev *dev = fe->dvb->priv;
++	if (fe->ops.i2c_gate_ctrl) {
++		fe->ops.i2c_gate_ctrl(fe, 1);
++		if (dev->original_set_voltage)
++			res = dev->original_set_voltage(fe, voltage);
++		fe->ops.i2c_gate_ctrl(fe, 0);
++	}
++	return res;
++};
++
++static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg)
++{
++	int res = -EIO;
++	struct saa7134_dev *dev = fe->dvb->priv;
++	if (fe->ops.i2c_gate_ctrl) {
++		fe->ops.i2c_gate_ctrl(fe, 1);
++		if (dev->original_set_high_voltage)
++			res = dev->original_set_high_voltage(fe, arg);
++		fe->ops.i2c_gate_ctrl(fe, 0);
++	}
++	return res;
++};
++
++static int md8800_set_voltage2(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
++{
++	struct saa7134_dev *dev = fe->dvb->priv;
++	u8 wbuf[2] = { 0x1f, 00 };
++	u8 rbuf;
++	struct i2c_msg msg[] = { { .addr = 0x08, .flags = 0, .buf = wbuf, .len = 1 },
++				 { .addr = 0x08, .flags = I2C_M_RD, .buf = &rbuf, .len = 1 } };
++
++	if (i2c_transfer(&dev->i2c_adap, msg, 2) != 2)
++		return -EIO;
++	/* NOTE: this assumes that gpo1 is used, it might be bit 5 (gpo2) */
++	if (voltage == SEC_VOLTAGE_18)
++		wbuf[1] = rbuf | 0x10;
++	else
++		wbuf[1] = rbuf & 0xef;
++	msg[0].len = 2;
++	i2c_transfer(&dev->i2c_adap, msg, 1);
++	return 0;
++}
++
++static int md8800_set_high_voltage2(struct dvb_frontend *fe, long arg)
++{
++	struct saa7134_dev *dev = fe->dvb->priv;
++	wprintk("%s: sorry can't set high LNB supply voltage from here\n", __func__);
++	return -EIO;
++}
++
+ /* ==================================================================
+  * nxt200x based ATSC cards, helper functions
+  */
+@@ -863,12 +937,14 @@ static struct nxt200x_config kworldatsc110 = {
+ static int dvb_init(struct saa7134_dev *dev)
+ {
+ 	int ret;
++	int attach_xc3028 = 0;
++
+ 	/* init struct videobuf_dvb */
+ 	dev->ts.nr_bufs    = 32;
+ 	dev->ts.nr_packets = 32*4;
+ 	dev->dvb.name = dev->name;
+-	videobuf_queue_pci_init(&dev->dvb.dvbq, &saa7134_ts_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ 			    V4L2_FIELD_ALTERNATE,
+ 			    sizeof(struct saa7134_buf),
+@@ -889,17 +965,25 @@ static int dvb_init(struct saa7134_dev *dev)
+ 		dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
+ 					       &dev->i2c_adap);
+ 		if (dev->dvb.frontend) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   NULL, DVB_PLL_PHILIPS_TD1316);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->i2c_adap, 0x61,
++				   TUNER_PHILIPS_TD1316);
+ 		}
+ 		break;
++	case SAA7134_BOARD_AVERMEDIA_A16D:
++		dprintk("avertv A16D dvb setup\n");
++		dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_16d,
++					       &dev->i2c_adap);
++		attach_xc3028 = 1;
++		break;
+ 	case SAA7134_BOARD_MD7134:
+ 		dev->dvb.frontend = dvb_attach(tda10046_attach,
+ 					       &medion_cardbus,
+ 					       &dev->i2c_adap);
+ 		if (dev->dvb.frontend) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
+-				   &dev->i2c_adap, DVB_PLL_FMD1216ME);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->i2c_adap, medion_cardbus.tuner_address,
++				   TUNER_PHILIPS_FMD1216ME_MK3);
+ 		}
+ 		break;
+ 	case SAA7134_BOARD_PHILIPS_TOUGH:
+@@ -913,7 +997,7 @@ static int dvb_init(struct saa7134_dev *dev)
+ 		break;
+ 	case SAA7134_BOARD_FLYDVBTDUO:
+ 	case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
+-		configure_tda827x_fe(dev, &tda827x_lifeview_config);
++		configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
+ 		break;
+ 	case SAA7134_BOARD_PHILIPS_EUROPA:
+ 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+@@ -938,36 +1022,36 @@ static int dvb_init(struct saa7134_dev *dev)
+ 		}
+ 		break;
+ 	case SAA7134_BOARD_KWORLD_DVBT_210:
+-		configure_tda827x_fe(dev, &kworld_dvb_t_210_config);
++		configure_tda827x_fe(dev, &kworld_dvb_t_210_config, &tda827x_cfg_2);
+ 		break;
+ 	case SAA7134_BOARD_PHILIPS_TIGER:
+-		configure_tda827x_fe(dev, &philips_tiger_config);
++		configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0);
+ 		break;
+ 	case SAA7134_BOARD_PINNACLE_PCTV_310i:
+-		configure_tda827x_fe(dev, &pinnacle_pctv_310i_config);
++		configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, &tda827x_cfg_1);
+ 		break;
+ 	case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+-		configure_tda827x_fe(dev, &hauppauge_hvr_1110_config);
++		configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, &tda827x_cfg_1);
+ 		break;
+ 	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+-		configure_tda827x_fe(dev, &asus_p7131_dual_config);
++		configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0);
+ 		break;
+ 	case SAA7134_BOARD_FLYDVBT_LR301:
+-		configure_tda827x_fe(dev, &tda827x_lifeview_config);
++		configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
+ 		break;
+ 	case SAA7134_BOARD_FLYDVB_TRIO:
+ 		if(! use_frontend) {	/* terrestrial */
+-			configure_tda827x_fe(dev, &lifeview_trio_config);
+-		} else {  	        /* satellite */
++			configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0);
++		} else {  		/* satellite */
+ 			dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
+ 			if (dev->dvb.frontend) {
+ 				if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
+ 									&dev->i2c_adap, 0) == NULL) {
+-					wprintk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__);
++					wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
+ 				}
+ 				if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
+ 										0x08, 0, 0) == NULL) {
+-					wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__);
++					wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
+ 				}
+ 			}
+ 		}
+@@ -979,18 +1063,56 @@ static int dvb_init(struct saa7134_dev *dev)
+ 					       &dev->i2c_adap);
+ 		if (dev->dvb.frontend) {
+ 			if (dvb_attach(tda827x_attach,dev->dvb.frontend,
+-				   ads_tech_duo_config.tuner_address,
+-				   &dev->i2c_adap,&ads_duo_cfg) == NULL) {
++				   ads_tech_duo_config.tuner_address, &dev->i2c_adap,
++								&ads_duo_cfg) == NULL) {
+ 				wprintk("no tda827x tuner found at addr: %02x\n",
+ 					ads_tech_duo_config.tuner_address);
+ 			}
+ 		}
+ 		break;
+ 	case SAA7134_BOARD_TEVION_DVBT_220RF:
+-		configure_tda827x_fe(dev, &tevion_dvbt220rf_config);
++		configure_tda827x_fe(dev, &tevion_dvbt220rf_config, &tda827x_cfg_0);
+ 		break;
+ 	case SAA7134_BOARD_MEDION_MD8800_QUADRO:
+-		configure_tda827x_fe(dev, &md8800_dvbt_config);
++		if (!use_frontend) {     /* terrestrial */
++			configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
++		} else {        /* satellite */
++			dev->dvb.frontend = dvb_attach(tda10086_attach,
++							&flydvbs, &dev->i2c_adap);
++			if (dev->dvb.frontend) {
++				struct dvb_frontend *fe = dev->dvb.frontend;
++				u8 dev_id = dev->eedata[2];
++				u8 data = 0xc4;
++				struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1};
++
++				if (dvb_attach(tda826x_attach, dev->dvb.frontend,
++						0x60, &dev->i2c_adap, 0) == NULL)
++					wprintk("%s: Medion Quadro, no tda826x "
++						"found !\n", __func__);
++				if (dev_id != 0x08) {
++					/* we need to open the i2c gate (we know it exists) */
++					fe->ops.i2c_gate_ctrl(fe, 1);
++					if (dvb_attach(isl6405_attach, fe,
++							&dev->i2c_adap, 0x08, 0, 0) == NULL)
++						wprintk("%s: Medion Quadro, no ISL6405 "
++							"found !\n", __func__);
++					if (dev_id == 0x07) {
++						/* fire up the 2nd section of the LNB supply since
++						   we can't do this from the other section */
++						msg.buf = &data;
++						i2c_transfer(&dev->i2c_adap, &msg, 1);
++					}
++					fe->ops.i2c_gate_ctrl(fe, 0);
++					dev->original_set_voltage = fe->ops.set_voltage;
++					fe->ops.set_voltage = md8800_set_voltage;
++					dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
++					fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
++				} else {
++					fe->ops.set_voltage = md8800_set_voltage2;
++					fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage2;
++				}
++			}
++		}
+ 		break;
+ 	case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
+ 		dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
+@@ -1004,8 +1126,9 @@ static int dvb_init(struct saa7134_dev *dev)
+ 		dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
+ 					       &dev->i2c_adap);
+ 		if (dev->dvb.frontend) {
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+-				   NULL, DVB_PLL_TUV1236D);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->i2c_adap, 0x61,
++				   TUNER_PHILIPS_TUV1236D);
+ 		}
+ 		break;
+ 	case SAA7134_BOARD_FLYDVBS_LR300:
+@@ -1014,11 +1137,11 @@ static int dvb_init(struct saa7134_dev *dev)
+ 		if (dev->dvb.frontend) {
+ 			if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+ 				       &dev->i2c_adap, 0) == NULL) {
+-				wprintk("%s: No tda826x found!\n", __FUNCTION__);
++				wprintk("%s: No tda826x found!\n", __func__);
+ 			}
+ 			if (dvb_attach(isl6421_attach, dev->dvb.frontend,
+ 				       &dev->i2c_adap, 0x08, 0, 0) == NULL) {
+-				wprintk("%s: No ISL6421 found!\n", __FUNCTION__);
++				wprintk("%s: No ISL6421 found!\n", __func__);
+ 			}
+ 		}
+ 		break;
+@@ -1030,8 +1153,9 @@ static int dvb_init(struct saa7134_dev *dev)
+ 			dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
+ 			dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+ 
+-			dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
+-				   &dev->i2c_adap, DVB_PLL_FMD1216ME);
++			dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++				   &dev->i2c_adap, medion_cardbus.tuner_address,
++				   TUNER_PHILIPS_FMD1216ME_MK3);
+ 		}
+ 		break;
+ 	case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+@@ -1044,38 +1168,107 @@ static int dvb_init(struct saa7134_dev *dev)
+ 		}
+ 		break;
+ 	case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+-		configure_tda827x_fe(dev, &cinergy_ht_config);
++		configure_tda827x_fe(dev, &cinergy_ht_config, &tda827x_cfg_0);
+ 		break;
+ 	case SAA7134_BOARD_CINERGY_HT_PCI:
+-		configure_tda827x_fe(dev, &cinergy_ht_pci_config);
++		configure_tda827x_fe(dev, &cinergy_ht_pci_config, &tda827x_cfg_0);
+ 		break;
+ 	case SAA7134_BOARD_PHILIPS_TIGER_S:
+-		configure_tda827x_fe(dev, &philips_tiger_s_config);
++		configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
+ 		break;
+ 	case SAA7134_BOARD_ASUS_P7131_4871:
+-		configure_tda827x_fe(dev, &asus_p7131_4871_config);
++		configure_tda827x_fe(dev, &asus_p7131_4871_config, &tda827x_cfg_2);
+ 		break;
+ 	case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
+-		configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config);
++		configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, &tda827x_cfg_2);
+ 		break;
+ 	case SAA7134_BOARD_AVERMEDIA_SUPER_007:
+-		configure_tda827x_fe(dev, &avermedia_super_007_config);
++		configure_tda827x_fe(dev, &avermedia_super_007_config, &tda827x_cfg_0);
+ 		break;
+ 	case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
+-		configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config);
++		configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, &tda827x_cfg_2_sw42);
++		break;
++	case SAA7134_BOARD_PHILIPS_SNAKE:
++		dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
++						&dev->i2c_adap);
++		if (dev->dvb.frontend) {
++			if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
++					&dev->i2c_adap, 0) == NULL)
++				wprintk("%s: No tda826x found!\n", __func__);
++			if (dvb_attach(lnbp21_attach, dev->dvb.frontend,
++					&dev->i2c_adap, 0, 0) == NULL)
++				wprintk("%s: No lnbp21 found!\n", __func__);
++		}
++		break;
++	case SAA7134_BOARD_CREATIX_CTX953:
++		configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
++		break;
++	case SAA7134_BOARD_MSI_TVANYWHERE_AD11:
++		configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
++		break;
++	case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
++		dev->dvb.frontend = dvb_attach(mt352_attach,
++					       &avermedia_e506r_mt352_dev,
++					       &dev->i2c_adap);
++		attach_xc3028 = 1;
++		break;
++	case SAA7134_BOARD_MD7134_BRIDGE_2:
++		dev->dvb.frontend = dvb_attach(tda10086_attach,
++						&sd1878_4m, &dev->i2c_adap);
++		if (dev->dvb.frontend) {
++			struct dvb_frontend *fe;
++			if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
++				  &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL)
++				wprintk("%s: MD7134 DVB-S, no SD1878 "
++					"found !\n", __func__);
++			/* we need to open the i2c gate (we know it exists) */
++			fe = dev->dvb.frontend;
++			fe->ops.i2c_gate_ctrl(fe, 1);
++			if (dvb_attach(isl6405_attach, fe,
++					&dev->i2c_adap, 0x08, 0, 0) == NULL)
++				wprintk("%s: MD7134 DVB-S, no ISL6405 "
++					"found !\n", __func__);
++			fe->ops.i2c_gate_ctrl(fe, 0);
++			dev->original_set_voltage = fe->ops.set_voltage;
++			fe->ops.set_voltage = md8800_set_voltage;
++			dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
++			fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
++		}
+ 		break;
+ 	default:
+ 		wprintk("Huh? unknown DVB card?\n");
+ 		break;
+ 	}
+ 
++	if (attach_xc3028) {
++		struct dvb_frontend *fe;
++		struct xc2028_config cfg = {
++			.i2c_adap  = &dev->i2c_adap,
++			.i2c_addr  = 0x61,
++		};
++
++		if (!dev->dvb.frontend)
++			return -1;
++
++		fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
++		if (!fe) {
++			printk(KERN_ERR "%s/2: xc3028 attach failed\n",
++			       dev->name);
++			dvb_frontend_detach(dev->dvb.frontend);
++			dvb_unregister_frontend(dev->dvb.frontend);
++			dev->dvb.frontend = NULL;
++			return -1;
++		}
++	}
++
+ 	if (NULL == dev->dvb.frontend) {
+ 		printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
+ 		return -1;
+ 	}
+ 
+ 	/* register everything else */
+-	ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
++	ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev,
++				    adapter_nr);
+ 
+ 	/* this sequence is necessary to make the tda1004x load its firmware
+ 	 * and to enter analog mode of hybrid boards
+@@ -1106,9 +1299,22 @@ static int dvb_fini(struct saa7134_dev *dev)
+ 
+ 		/* otherwise we don't detect the tuner on next insmod */
+ 		saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tda9887_cfg);
++	} else if (dev->board == SAA7134_BOARD_MEDION_MD8800_QUADRO) {
++		if ((dev->eedata[2] == 0x07) && use_frontend) {
++			/* turn off the 2nd lnb supply */
++			u8 data = 0x80;
++			struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1};
++			struct dvb_frontend *fe;
++			fe = dev->dvb.frontend;
++			if (fe->ops.i2c_gate_ctrl) {
++				fe->ops.i2c_gate_ctrl(fe, 1);
++				i2c_transfer(&dev->i2c_adap, &msg, 1);
++				fe->ops.i2c_gate_ctrl(fe, 0);
++			}
++		}
+ 	}
+-
+-	videobuf_dvb_unregister(&dev->dvb);
++	if (dev->dvb.frontend)
++		videobuf_dvb_unregister(&dev->dvb);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
+index 3d2ec30..1314522 100644
+--- a/drivers/media/video/saa7134/saa7134-empress.c
++++ b/drivers/media/video/saa7134/saa7134-empress.c
+@@ -40,7 +40,7 @@ static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+ module_param_array(empress_nr, int, NULL, 0444);
+ MODULE_PARM_DESC(empress_nr,"ts device number");
+ 
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"enable debug messages");
+ 
+@@ -402,7 +402,7 @@ static int empress_init(struct saa7134_dev *dev)
+ {
+ 	int err;
+ 
+-	dprintk("%s: %s\n",dev->name,__FUNCTION__);
++	dprintk("%s: %s\n",dev->name,__func__);
+ 	dev->empress_dev = video_device_alloc();
+ 	if (NULL == dev->empress_dev)
+ 		return -ENOMEM;
+@@ -427,8 +427,8 @@ static int empress_init(struct saa7134_dev *dev)
+ 	printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
+ 	       dev->name,dev->empress_dev->minor & 0x1f);
+ 
+-	videobuf_queue_pci_init(&dev->empress_tsq, &saa7134_ts_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ 			    V4L2_FIELD_ALTERNATE,
+ 			    sizeof(struct saa7134_buf),
+@@ -440,7 +440,7 @@ static int empress_init(struct saa7134_dev *dev)
+ 
+ static int empress_fini(struct saa7134_dev *dev)
+ {
+-	dprintk("%s: %s\n",dev->name,__FUNCTION__);
++	dprintk("%s: %s\n",dev->name,__func__);
+ 
+ 	if (NULL == dev->empress_dev)
+ 		return 0;
+diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
+index d3322c3..2ccfaba 100644
+--- a/drivers/media/video/saa7134/saa7134-i2c.c
++++ b/drivers/media/video/saa7134/saa7134-i2c.c
+@@ -33,11 +33,11 @@
+ 
+ /* ----------------------------------------------------------- */
+ 
+-static unsigned int i2c_debug = 0;
++static unsigned int i2c_debug;
+ module_param(i2c_debug, int, 0644);
+ MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
+ 
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, 0444);
+ MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+ 
+@@ -140,6 +140,8 @@ static inline int i2c_is_busy(enum i2c_status status)
+ {
+ 	switch (status) {
+ 	case BUSY:
++	case TO_SCL:
++	case TO_ARB:
+ 		return true;
+ 	default:
+ 		return false;
+diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
+index b418881..767ff30 100644
+--- a/drivers/media/video/saa7134/saa7134-input.c
++++ b/drivers/media/video/saa7134/saa7134-input.c
+@@ -27,15 +27,15 @@
+ #include "saa7134-reg.h"
+ #include "saa7134.h"
+ 
+-static unsigned int disable_ir = 0;
++static unsigned int disable_ir;
+ module_param(disable_ir, int, 0444);
+ MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
+ 
+-static unsigned int ir_debug = 0;
++static unsigned int ir_debug;
+ module_param(ir_debug, int, 0644);
+ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
+ 
+-static int pinnacle_remote = 0;
++static int pinnacle_remote;
+ module_param(pinnacle_remote, int, 0644);    /* Choose Pinnacle PCTV remote */
+ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
+ 
+@@ -331,6 +331,11 @@ int saa7134_input_init1(struct saa7134_dev *dev)
+ 		break;
+ 	case SAA7134_BOARD_MANLI_MTV001:
+ 	case SAA7134_BOARD_MANLI_MTV002:
++		ir_codes     = ir_codes_manli;
++		mask_keycode = 0x001f00;
++		mask_keyup   = 0x004000;
++		polling      = 50; /* ms */
++		break;
+ 	case SAA7134_BOARD_BEHOLD_409FM:
+ 	case SAA7134_BOARD_BEHOLD_401:
+ 	case SAA7134_BOARD_BEHOLD_403:
+@@ -343,7 +348,13 @@ int saa7134_input_init1(struct saa7134_dev *dev)
+ 	case SAA7134_BOARD_BEHOLD_505FM:
+ 	case SAA7134_BOARD_BEHOLD_507_9FM:
+ 		ir_codes     = ir_codes_manli;
+-		mask_keycode = 0x001f00;
++		mask_keycode = 0x003f00;
++		mask_keyup   = 0x004000;
++		polling      = 50; /* ms */
++		break;
++	case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
++		ir_codes     = ir_codes_behold_columbus;
++		mask_keycode = 0x003f00;
+ 		mask_keyup   = 0x004000;
+ 		polling      = 50; // ms
+ 		break;
+diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h
+index ac6431b..86f5eef 100644
+--- a/drivers/media/video/saa7134/saa7134-reg.h
++++ b/drivers/media/video/saa7134/saa7134-reg.h
+@@ -365,6 +365,9 @@
+ #define SAA7135_DSP_RWSTATE_RDB                 (1 << 1)
+ #define SAA7135_DSP_RWSTATE_WRR                 (1 << 0)
+ 
++#define SAA7135_DSP_RWCLEAR			0x586
++#define SAA7135_DSP_RWCLEAR_RERR		    1
++
+ /* ------------------------------------------------------------------ */
+ /*
+  * Local variables:
+diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
+index f1b8fca..eae72fd 100644
+--- a/drivers/media/video/saa7134/saa7134-ts.c
++++ b/drivers/media/video/saa7134/saa7134-ts.c
+@@ -32,7 +32,7 @@
+ 
+ /* ------------------------------------------------------------------ */
+ 
+-static unsigned int ts_debug  = 0;
++static unsigned int ts_debug;
+ module_param(ts_debug, int, 0644);
+ MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
+ 
+diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
+index 4e98104..232af59 100644
+--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
++++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
+@@ -35,18 +35,18 @@
+ 
+ /* ------------------------------------------------------------------ */
+ 
+-static unsigned int audio_debug = 0;
++static unsigned int audio_debug;
+ module_param(audio_debug, int, 0644);
+ MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]");
+ 
+-static unsigned int audio_ddep = 0;
++static unsigned int audio_ddep;
+ module_param(audio_ddep, int, 0644);
+ MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite");
+ 
+ static int audio_clock_override = UNSET;
+ module_param(audio_clock_override, int, 0644);
+ 
+-static int audio_clock_tweak = 0;
++static int audio_clock_tweak;
+ module_param(audio_clock_tweak, int, 0644);
+ MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])");
+ 
+@@ -653,6 +653,17 @@ static char *stdres[0x20] = {
+ 
+ #define DSP_RETRY 32
+ #define DSP_DELAY 16
++#define SAA7135_DSP_RWCLEAR_RERR 1
++
++static inline int saa_dsp_reset_error_bit(struct saa7134_dev *dev)
++{
++	int state = saa_readb(SAA7135_DSP_RWSTATE);
++	if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
++		d2printk("%s: resetting error bit\n", dev->name);
++		saa_writeb(SAA7135_DSP_RWCLEAR, SAA7135_DSP_RWCLEAR_RERR);
++	}
++	return 0;
++}
+ 
+ static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
+ {
+@@ -660,8 +671,8 @@ static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
+ 
+ 	state = saa_readb(SAA7135_DSP_RWSTATE);
+ 	if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
+-		printk("%s: dsp access error\n",dev->name);
+-		/* FIXME: send ack ... */
++		printk(KERN_WARNING "%s: dsp access error\n", dev->name);
++		saa_dsp_reset_error_bit(dev);
+ 		return -EIO;
+ 	}
+ 	while (0 == (state & bit)) {
+diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
+index f0d5ed9..cb03042 100644
+--- a/drivers/media/video/saa7134/saa7134-vbi.c
++++ b/drivers/media/video/saa7134/saa7134-vbi.c
+@@ -31,7 +31,7 @@
+ 
+ /* ------------------------------------------------------------------ */
+ 
+-static unsigned int vbi_debug  = 0;
++static unsigned int vbi_debug;
+ module_param(vbi_debug, int, 0644);
+ MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
+ 
+diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
+index 39c41ad..a0baf2d 100644
+--- a/drivers/media/video/saa7134/saa7134-video.c
++++ b/drivers/media/video/saa7134/saa7134-video.c
+@@ -40,7 +40,7 @@
+ 
+ unsigned int video_debug;
+ static unsigned int gbuffers      = 8;
+-static unsigned int noninterlaced = 0;
++static unsigned int noninterlaced; /* 0 */
+ static unsigned int gbufsize      = 720*576*4;
+ static unsigned int gbufsize_max  = 720*576*4;
+ static char secam[] = "--";
+@@ -626,13 +626,8 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
+ {
+ 	saa7134_set_decoder(dev);
+ 
+-	if (card_in(dev, dev->ctl_input).tv) {
+-		if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
+-				&& ((card(dev).tuner_config == 1)
+-				||  (card(dev).tuner_config == 2)))
+-			saa7134_set_gpio(dev, 22, 5);
++	if (card_in(dev, dev->ctl_input).tv)
+ 		saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+-	}
+ }
+ 
+ static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
+@@ -1350,14 +1345,14 @@ static int video_open(struct inode *inode, struct file *file)
+ 	fh->height   = 576;
+ 	v4l2_prio_open(&dev->prio,&fh->prio);
+ 
+-	videobuf_queue_pci_init(&fh->cap, &video_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&fh->cap, &video_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ 			    V4L2_FIELD_INTERLACED,
+ 			    sizeof(struct saa7134_buf),
+ 			    fh);
+-	videobuf_queue_pci_init(&fh->vbi, &saa7134_vbi_qops,
+-			    dev->pci, &dev->slock,
++	videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops,
++			    &dev->pci->dev, &dev->slock,
+ 			    V4L2_BUF_TYPE_VBI_CAPTURE,
+ 			    V4L2_FIELD_SEQ_TB,
+ 			    sizeof(struct saa7134_buf),
+diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
+index f940d02..924ffd1 100644
+--- a/drivers/media/video/saa7134/saa7134.h
++++ b/drivers/media/video/saa7134/saa7134.h
+@@ -253,7 +253,17 @@ struct saa7134_format {
+ #define SAA7134_BOARD_BEHOLD_607_9FM	129
+ #define SAA7134_BOARD_BEHOLD_M6		130
+ #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131
+-#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132
++#define SAA7134_BOARD_GENIUS_TVGO_A11MCE   132
++#define SAA7134_BOARD_PHILIPS_SNAKE        133
++#define SAA7134_BOARD_CREATIX_CTX953       134
++#define SAA7134_BOARD_MSI_TVANYWHERE_AD11  135
++#define SAA7134_BOARD_AVERMEDIA_CARDBUS_506 136
++#define SAA7134_BOARD_AVERMEDIA_A16D       137
++#define SAA7134_BOARD_AVERMEDIA_M115       138
++#define SAA7134_BOARD_VIDEOMATE_T750       139
++#define SAA7134_BOARD_AVERMEDIA_A700_PRO    140
++#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141
++
+ 
+ #define SAA7134_MAXBOARDS 8
+ #define SAA7134_INPUT_MAX 8
+@@ -380,9 +390,7 @@ struct saa7134_fh {
+ 	unsigned int               radio;
+ 	enum v4l2_buf_type         type;
+ 	unsigned int               resources;
+-#ifdef VIDIOC_G_PRIORITY
+ 	enum v4l2_priority	   prio;
+-#endif
+ 
+ 	/* video overlay */
+ 	struct v4l2_window         win;
+@@ -454,9 +462,7 @@ struct saa7134_dev {
+ 	struct list_head           devlist;
+ 	struct mutex               lock;
+ 	spinlock_t                 slock;
+-#ifdef VIDIOC_G_PRIORITY
+ 	struct v4l2_prio_state     prio;
+-#endif
+ 	/* workstruct for loading modules */
+ 	struct work_struct request_module_wk;
+ 
+@@ -556,7 +562,9 @@ struct saa7134_dev {
+ #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
+ 	/* SAA7134_MPEG_DVB only */
+ 	struct videobuf_dvb        dvb;
+-	int (*original_demod_sleep)(struct dvb_frontend* fe);
++	int (*original_demod_sleep)(struct dvb_frontend *fe);
++	int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
++	int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
+ #endif
+ };
+ 
+@@ -594,7 +602,6 @@ extern int saa7134_no_overlay;
+ 
+ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
+ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
+-int saa7134_tuner_callback(void *ptr, int command, int arg);
+ 
+ #define SAA7134_PGTABLE_SIZE 4096
+ 
+@@ -631,6 +638,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
+ 
+ extern int saa7134_board_init1(struct saa7134_dev *dev);
+ extern int saa7134_board_init2(struct saa7134_dev *dev);
++int saa7134_tuner_callback(void *priv, int command, int arg);
+ 
+ 
+ /* ----------------------------------------------------------- */
+diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
+new file mode 100644
+index 0000000..53c5edb
+--- /dev/null
++++ b/drivers/media/video/saa717x.c
+@@ -0,0 +1,1516 @@
++/*
++ * saa717x - Philips SAA717xHL video decoder driver
++ *
++ * Based on the saa7115 driver
++ *
++ * Changes by Ohta Kyuma <alpha292 at bremen.or.jp>
++ *    - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
++ *
++ * Changes by T.Adachi (tadachi at tadachi-net.com)
++ *    - support audio, video scaler etc, and checked the initialize sequence.
++ *
++ * Cleaned up by Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * Note: this is a reversed engineered driver based on captures from
++ * the I2C bus under Windows. This chip is very similar to the saa7134,
++ * though. Unfortunately, this driver is currently only working for NTSC.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You 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/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++
++#include <linux/videodev.h>
++#include <linux/videodev2.h>
++#include <linux/i2c.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-i2c-drv.h>
++
++MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
++MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
++MODULE_LICENSE("GPL");
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Debug level (0-1)");
++
++/*
++ * Generic i2c probe
++ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
++ */
++
++struct saa717x_state {
++	v4l2_std_id std;
++	int input;
++	int enable;
++	int radio;
++	int bright;
++	int contrast;
++	int hue;
++	int sat;
++	int playback;
++	int audio;
++	int tuner_audio_mode;
++	int audio_main_mute;
++	int audio_main_vol_r;
++	int audio_main_vol_l;
++	u16 audio_main_bass;
++	u16 audio_main_treble;
++	u16 audio_main_volume;
++	u16 audio_main_balance;
++	int audio_input;
++};
++
++/* ----------------------------------------------------------------------- */
++
++/* for audio mode */
++#define TUNER_AUDIO_MONO   	0  /* LL */
++#define TUNER_AUDIO_STEREO 	1  /* LR */
++#define TUNER_AUDIO_LANG1  	2  /* LL */
++#define TUNER_AUDIO_LANG2  	3  /* RR */
++
++#define SAA717X_NTSC_WIDTH   	(704)
++#define SAA717X_NTSC_HEIGHT  	(480)
++
++/* ----------------------------------------------------------------------- */
++
++static int saa717x_write(struct i2c_client *client, u32 reg, u32 value)
++{
++	struct i2c_adapter *adap = client->adapter;
++	int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
++	unsigned char mm1[6];
++	struct i2c_msg msg;
++
++	msg.flags = 0;
++	msg.addr = client->addr;
++	mm1[0] = (reg >> 8) & 0xff;
++	mm1[1] = reg & 0xff;
++
++	if (fw_addr) {
++		mm1[4] = (value >> 16) & 0xff;
++		mm1[3] = (value >> 8) & 0xff;
++		mm1[2] = value & 0xff;
++	} else {
++		mm1[2] = value & 0xff;
++	}
++	msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
++	msg.buf = mm1;
++	v4l_dbg(2, debug, client, "wrote:  reg 0x%03x=%08x\n", reg, value);
++	return i2c_transfer(adap, &msg, 1) == 1;
++}
++
++static void saa717x_write_regs(struct i2c_client *client, u32 *data)
++{
++	while (data[0] || data[1]) {
++		saa717x_write(client, data[0], data[1]);
++		data += 2;
++	}
++}
++
++static u32 saa717x_read(struct i2c_client *client, u32 reg)
++{
++	struct i2c_adapter *adap = client->adapter;
++	int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
++	unsigned char mm1[2];
++	unsigned char mm2[4] = { 0, 0, 0, 0 };
++	struct i2c_msg msgs[2];
++	u32 value;
++
++	msgs[0].flags = 0;
++	msgs[1].flags = I2C_M_RD;
++	msgs[0].addr = msgs[1].addr = client->addr;
++	mm1[0] = (reg >> 8) & 0xff;
++	mm1[1] = reg & 0xff;
++	msgs[0].len = 2;
++	msgs[0].buf = mm1;
++	msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
++	msgs[1].buf = mm2;
++	i2c_transfer(adap, msgs, 2);
++
++	if (fw_addr)
++		value = (mm2[2] & 0xff)  | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
++	else
++		value = mm2[0] & 0xff;
++
++	v4l_dbg(2, debug, client, "read:  reg 0x%03x=0x%08x\n", reg, value);
++	return value;
++}
++
++/* ----------------------------------------------------------------------- */
++
++static u32 reg_init_initialize[] =
++{
++	/* from linux driver */
++	0x101, 0x008, /* Increment delay */
++
++	0x103, 0x000, /* Analog input control 2 */
++	0x104, 0x090, /* Analog input control 3 */
++	0x105, 0x090, /* Analog input control 4 */
++	0x106, 0x0eb, /* Horizontal sync start */
++	0x107, 0x0e0, /* Horizontal sync stop */
++	0x109, 0x055, /* Luminance control */
++
++	0x10f, 0x02a, /* Chroma gain control */
++	0x110, 0x000, /* Chroma control 2 */
++
++	0x114, 0x045, /* analog/ADC */
++
++	0x118, 0x040, /* RAW data gain */
++	0x119, 0x080, /* RAW data offset */
++
++	0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
++	0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
++	0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
++	0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
++
++	0x049, 0x000, /* VBI vertical input window start (H) TASK A */
++
++	0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
++	0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
++
++	0x064, 0x080, /* Lumina brightness TASK A */
++	0x065, 0x040, /* Luminance contrast TASK A */
++	0x066, 0x040, /* Chroma saturation TASK A */
++	/* 067H: Reserved */
++	0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
++	0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
++	0x06a, 0x000, /* VBI phase offset TASK A */
++
++	0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
++	0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
++
++	0x072, 0x000, /* Vertical filter mode TASK A */
++
++	0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
++	0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
++	0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
++	0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
++
++	0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
++
++	0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
++	0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
++
++	0x0a4, 0x080, /* Lumina brightness TASK B */
++	0x0a5, 0x040, /* Luminance contrast TASK B */
++	0x0a6, 0x040, /* Chroma saturation TASK B */
++	/* 0A7H reserved */
++	0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
++	0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
++	0x0aa, 0x000, /* VBI phase offset TASK B */
++
++	0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
++	0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
++
++	0x0b2, 0x000, /* Vertical filter mode TASK B */
++
++	0x00c, 0x000, /* Start point GREEN path */
++	0x00d, 0x000, /* Start point BLUE path */
++	0x00e, 0x000, /* Start point RED path */
++
++	0x010, 0x010, /* GREEN path gamma curve --- */
++	0x011, 0x020,
++	0x012, 0x030,
++	0x013, 0x040,
++	0x014, 0x050,
++	0x015, 0x060,
++	0x016, 0x070,
++	0x017, 0x080,
++	0x018, 0x090,
++	0x019, 0x0a0,
++	0x01a, 0x0b0,
++	0x01b, 0x0c0,
++	0x01c, 0x0d0,
++	0x01d, 0x0e0,
++	0x01e, 0x0f0,
++	0x01f, 0x0ff, /* --- GREEN path gamma curve */
++
++	0x020, 0x010, /* BLUE path gamma curve --- */
++	0x021, 0x020,
++	0x022, 0x030,
++	0x023, 0x040,
++	0x024, 0x050,
++	0x025, 0x060,
++	0x026, 0x070,
++	0x027, 0x080,
++	0x028, 0x090,
++	0x029, 0x0a0,
++	0x02a, 0x0b0,
++	0x02b, 0x0c0,
++	0x02c, 0x0d0,
++	0x02d, 0x0e0,
++	0x02e, 0x0f0,
++	0x02f, 0x0ff, /* --- BLUE path gamma curve */
++
++	0x030, 0x010, /* RED path gamma curve --- */
++	0x031, 0x020,
++	0x032, 0x030,
++	0x033, 0x040,
++	0x034, 0x050,
++	0x035, 0x060,
++	0x036, 0x070,
++	0x037, 0x080,
++	0x038, 0x090,
++	0x039, 0x0a0,
++	0x03a, 0x0b0,
++	0x03b, 0x0c0,
++	0x03c, 0x0d0,
++	0x03d, 0x0e0,
++	0x03e, 0x0f0,
++	0x03f, 0x0ff, /* --- RED path gamma curve */
++
++	0x109, 0x085, /* Luminance control  */
++
++	/**** from app start ****/
++	0x584, 0x000, /* AGC gain control */
++	0x585, 0x000, /* Program count */
++	0x586, 0x003, /* Status reset */
++	0x588, 0x0ff, /* Number of audio samples (L) */
++	0x589, 0x00f, /* Number of audio samples (M) */
++	0x58a, 0x000, /* Number of audio samples (H) */
++	0x58b, 0x000, /* Audio select */
++	0x58c, 0x010, /* Audio channel assign1 */
++	0x58d, 0x032, /* Audio channel assign2 */
++	0x58e, 0x054, /* Audio channel assign3 */
++	0x58f, 0x023, /* Audio format */
++	0x590, 0x000, /* SIF control */
++
++	0x595, 0x000, /* ?? */
++	0x596, 0x000, /* ?? */
++	0x597, 0x000, /* ?? */
++
++	0x464, 0x00, /* Digital input crossbar1 */
++
++	0x46c, 0xbbbb10, /* Digital output selection1-3 */
++	0x470, 0x101010, /* Digital output selection4-6 */
++
++	0x478, 0x00, /* Sound feature control */
++
++	0x474, 0x18, /* Softmute control */
++
++	0x454, 0x0425b9, /* Sound Easy programming(reset) */
++	0x454, 0x042539, /* Sound Easy programming(reset) */
++
++
++	/**** common setting( of DVD play, including scaler commands) ****/
++	0x042, 0x003, /* Data path configuration for VBI (TASK A) */
++
++	0x082, 0x003, /* Data path configuration for VBI (TASK B) */
++
++	0x108, 0x0f8, /* Sync control */
++	0x2a9, 0x0fd, /* ??? */
++	0x102, 0x089, /* select video input "mode 9" */
++	0x111, 0x000, /* Mode/delay control */
++
++	0x10e, 0x00a, /* Chroma control 1 */
++
++	0x594, 0x002, /* SIF, analog I/O select */
++
++	0x454, 0x0425b9, /* Sound  */
++	0x454, 0x042539,
++
++	0x111, 0x000,
++	0x10e, 0x00a,
++	0x464, 0x000,
++	0x300, 0x000,
++	0x301, 0x006,
++	0x302, 0x000,
++	0x303, 0x006,
++	0x308, 0x040,
++	0x309, 0x000,
++	0x30a, 0x000,
++	0x30b, 0x000,
++	0x000, 0x002,
++	0x001, 0x000,
++	0x002, 0x000,
++	0x003, 0x000,
++	0x004, 0x033,
++	0x040, 0x01d,
++	0x041, 0x001,
++	0x042, 0x004,
++	0x043, 0x000,
++	0x080, 0x01e,
++	0x081, 0x001,
++	0x082, 0x004,
++	0x083, 0x000,
++	0x190, 0x018,
++	0x115, 0x000,
++	0x116, 0x012,
++	0x117, 0x018,
++	0x04a, 0x011,
++	0x08a, 0x011,
++	0x04b, 0x000,
++	0x08b, 0x000,
++	0x048, 0x000,
++	0x088, 0x000,
++	0x04e, 0x012,
++	0x08e, 0x012,
++	0x058, 0x012,
++	0x098, 0x012,
++	0x059, 0x000,
++	0x099, 0x000,
++	0x05a, 0x003,
++	0x09a, 0x003,
++	0x05b, 0x001,
++	0x09b, 0x001,
++	0x054, 0x008,
++	0x094, 0x008,
++	0x055, 0x000,
++	0x095, 0x000,
++	0x056, 0x0c7,
++	0x096, 0x0c7,
++	0x057, 0x002,
++	0x097, 0x002,
++	0x0ff, 0x0ff,
++	0x060, 0x001,
++	0x0a0, 0x001,
++	0x061, 0x000,
++	0x0a1, 0x000,
++	0x062, 0x000,
++	0x0a2, 0x000,
++	0x063, 0x000,
++	0x0a3, 0x000,
++	0x070, 0x000,
++	0x0b0, 0x000,
++	0x071, 0x004,
++	0x0b1, 0x004,
++	0x06c, 0x0e9,
++	0x0ac, 0x0e9,
++	0x06d, 0x003,
++	0x0ad, 0x003,
++	0x05c, 0x0d0,
++	0x09c, 0x0d0,
++	0x05d, 0x002,
++	0x09d, 0x002,
++	0x05e, 0x0f2,
++	0x09e, 0x0f2,
++	0x05f, 0x000,
++	0x09f, 0x000,
++	0x074, 0x000,
++	0x0b4, 0x000,
++	0x075, 0x000,
++	0x0b5, 0x000,
++	0x076, 0x000,
++	0x0b6, 0x000,
++	0x077, 0x000,
++	0x0b7, 0x000,
++	0x195, 0x008,
++	0x0ff, 0x0ff,
++	0x108, 0x0f8,
++	0x111, 0x000,
++	0x10e, 0x00a,
++	0x2a9, 0x0fd,
++	0x464, 0x001,
++	0x454, 0x042135,
++	0x598, 0x0e7,
++	0x599, 0x07d,
++	0x59a, 0x018,
++	0x59c, 0x066,
++	0x59d, 0x090,
++	0x59e, 0x001,
++	0x584, 0x000,
++	0x585, 0x000,
++	0x586, 0x003,
++	0x588, 0x0ff,
++	0x589, 0x00f,
++	0x58a, 0x000,
++	0x58b, 0x000,
++	0x58c, 0x010,
++	0x58d, 0x032,
++	0x58e, 0x054,
++	0x58f, 0x023,
++	0x590, 0x000,
++	0x595, 0x000,
++	0x596, 0x000,
++	0x597, 0x000,
++	0x464, 0x000,
++	0x46c, 0xbbbb10,
++	0x470, 0x101010,
++
++
++	0x478, 0x000,
++	0x474, 0x018,
++	0x454, 0x042135,
++	0x598, 0x0e7,
++	0x599, 0x07d,
++	0x59a, 0x018,
++	0x59c, 0x066,
++	0x59d, 0x090,
++	0x59e, 0x001,
++	0x584, 0x000,
++	0x585, 0x000,
++	0x586, 0x003,
++	0x588, 0x0ff,
++	0x589, 0x00f,
++	0x58a, 0x000,
++	0x58b, 0x000,
++	0x58c, 0x010,
++	0x58d, 0x032,
++	0x58e, 0x054,
++	0x58f, 0x023,
++	0x590, 0x000,
++	0x595, 0x000,
++	0x596, 0x000,
++	0x597, 0x000,
++	0x464, 0x000,
++	0x46c, 0xbbbb10,
++	0x470, 0x101010,
++
++	0x478, 0x000,
++	0x474, 0x018,
++	0x454, 0x042135,
++	0x598, 0x0e7,
++	0x599, 0x07d,
++	0x59a, 0x018,
++	0x59c, 0x066,
++	0x59d, 0x090,
++	0x59e, 0x001,
++	0x584, 0x000,
++	0x585, 0x000,
++	0x586, 0x003,
++	0x588, 0x0ff,
++	0x589, 0x00f,
++	0x58a, 0x000,
++	0x58b, 0x000,
++	0x58c, 0x010,
++	0x58d, 0x032,
++	0x58e, 0x054,
++	0x58f, 0x023,
++	0x590, 0x000,
++	0x595, 0x000,
++	0x596, 0x000,
++	0x597, 0x000,
++	0x464, 0x000,
++	0x46c, 0xbbbb10,
++	0x470, 0x101010,
++	0x478, 0x000,
++	0x474, 0x018,
++	0x454, 0x042135,
++	0x193, 0x000,
++	0x300, 0x000,
++	0x301, 0x006,
++	0x302, 0x000,
++	0x303, 0x006,
++	0x308, 0x040,
++	0x309, 0x000,
++	0x30a, 0x000,
++	0x30b, 0x000,
++	0x000, 0x002,
++	0x001, 0x000,
++	0x002, 0x000,
++	0x003, 0x000,
++	0x004, 0x033,
++	0x040, 0x01d,
++	0x041, 0x001,
++	0x042, 0x004,
++	0x043, 0x000,
++	0x080, 0x01e,
++	0x081, 0x001,
++	0x082, 0x004,
++	0x083, 0x000,
++	0x190, 0x018,
++	0x115, 0x000,
++	0x116, 0x012,
++	0x117, 0x018,
++	0x04a, 0x011,
++	0x08a, 0x011,
++	0x04b, 0x000,
++	0x08b, 0x000,
++	0x048, 0x000,
++	0x088, 0x000,
++	0x04e, 0x012,
++	0x08e, 0x012,
++	0x058, 0x012,
++	0x098, 0x012,
++	0x059, 0x000,
++	0x099, 0x000,
++	0x05a, 0x003,
++	0x09a, 0x003,
++	0x05b, 0x001,
++	0x09b, 0x001,
++	0x054, 0x008,
++	0x094, 0x008,
++	0x055, 0x000,
++	0x095, 0x000,
++	0x056, 0x0c7,
++	0x096, 0x0c7,
++	0x057, 0x002,
++	0x097, 0x002,
++	0x060, 0x001,
++	0x0a0, 0x001,
++	0x061, 0x000,
++	0x0a1, 0x000,
++	0x062, 0x000,
++	0x0a2, 0x000,
++	0x063, 0x000,
++	0x0a3, 0x000,
++	0x070, 0x000,
++	0x0b0, 0x000,
++	0x071, 0x004,
++	0x0b1, 0x004,
++	0x06c, 0x0e9,
++	0x0ac, 0x0e9,
++	0x06d, 0x003,
++	0x0ad, 0x003,
++	0x05c, 0x0d0,
++	0x09c, 0x0d0,
++	0x05d, 0x002,
++	0x09d, 0x002,
++	0x05e, 0x0f2,
++	0x09e, 0x0f2,
++	0x05f, 0x000,
++	0x09f, 0x000,
++	0x074, 0x000,
++	0x0b4, 0x000,
++	0x075, 0x000,
++	0x0b5, 0x000,
++	0x076, 0x000,
++	0x0b6, 0x000,
++	0x077, 0x000,
++	0x0b7, 0x000,
++	0x195, 0x008,
++	0x598, 0x0e7,
++	0x599, 0x07d,
++	0x59a, 0x018,
++	0x59c, 0x066,
++	0x59d, 0x090,
++	0x59e, 0x001,
++	0x584, 0x000,
++	0x585, 0x000,
++	0x586, 0x003,
++	0x588, 0x0ff,
++	0x589, 0x00f,
++	0x58a, 0x000,
++	0x58b, 0x000,
++	0x58c, 0x010,
++	0x58d, 0x032,
++	0x58e, 0x054,
++	0x58f, 0x023,
++	0x590, 0x000,
++	0x595, 0x000,
++	0x596, 0x000,
++	0x597, 0x000,
++	0x464, 0x000,
++	0x46c, 0xbbbb10,
++	0x470, 0x101010,
++	0x478, 0x000,
++	0x474, 0x018,
++	0x454, 0x042135,
++	0x193, 0x0a6,
++	0x108, 0x0f8,
++	0x042, 0x003,
++	0x082, 0x003,
++	0x454, 0x0425b9,
++	0x454, 0x042539,
++	0x193, 0x000,
++	0x193, 0x0a6,
++	0x464, 0x000,
++
++	0, 0
++};
++
++/* Tuner */
++static u32 reg_init_tuner_input[] = {
++	0x108, 0x0f8, /* Sync control */
++	0x111, 0x000, /* Mode/delay control */
++	0x10e, 0x00a, /* Chroma control 1 */
++	0, 0
++};
++
++/* Composite */
++static u32 reg_init_composite_input[] = {
++	0x108, 0x0e8, /* Sync control */
++	0x111, 0x000, /* Mode/delay control */
++	0x10e, 0x04a, /* Chroma control 1 */
++	0, 0
++};
++
++/* S-Video */
++static u32 reg_init_svideo_input[] = {
++	0x108, 0x0e8, /* Sync control */
++	0x111, 0x000, /* Mode/delay control */
++	0x10e, 0x04a, /* Chroma control 1 */
++	0, 0
++};
++
++static u32 reg_set_audio_template[4][2] =
++{
++	{ /* for MONO
++		tadachi 6/29 DMA audio output select?
++		Register 0x46c
++		7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
++		0: MAIN left,  1: MAIN right
++		2: AUX1 left,  3: AUX1 right
++		4: AUX2 left,  5: AUX2 right
++		6: DPL left,   7: DPL  right
++		8: DPL center, 9: DPL surround
++		A: monitor output, B: digital sense */
++		0xbbbb00,
++
++		/* tadachi 6/29 DAC and I2S output select?
++		   Register 0x470
++		   7-4:DAC right ch. 3-0:DAC left ch.
++		   I2S1 right,left  I2S2 right,left */
++		0x00,
++	},
++	{ /* for STEREO */
++		0xbbbb10, 0x101010,
++	},
++	{ /* for LANG1 */
++		0xbbbb00, 0x00,
++	},
++	{ /* for LANG2/SAP */
++		0xbbbb11, 0x111111,
++	}
++};
++
++
++/* Get detected audio flags (from saa7134 driver) */
++static void get_inf_dev_status(struct i2c_client *client,
++		int *dual_flag, int *stereo_flag)
++{
++	u32 reg_data3;
++
++	static char *stdres[0x20] = {
++		[0x00] = "no standard detected",
++		[0x01] = "B/G (in progress)",
++		[0x02] = "D/K (in progress)",
++		[0x03] = "M (in progress)",
++
++		[0x04] = "B/G A2",
++		[0x05] = "B/G NICAM",
++		[0x06] = "D/K A2 (1)",
++		[0x07] = "D/K A2 (2)",
++		[0x08] = "D/K A2 (3)",
++		[0x09] = "D/K NICAM",
++		[0x0a] = "L NICAM",
++		[0x0b] = "I NICAM",
++
++		[0x0c] = "M Korea",
++		[0x0d] = "M BTSC ",
++		[0x0e] = "M EIAJ",
++
++		[0x0f] = "FM radio / IF 10.7 / 50 deemp",
++		[0x10] = "FM radio / IF 10.7 / 75 deemp",
++		[0x11] = "FM radio / IF sel / 50 deemp",
++		[0x12] = "FM radio / IF sel / 75 deemp",
++
++		[0x13 ... 0x1e] = "unknown",
++		[0x1f] = "??? [in progress]",
++	};
++
++
++	*dual_flag = *stereo_flag = 0;
++
++	/* (demdec status: 0x528) */
++
++	/* read current status */
++	reg_data3 = saa717x_read(client, 0x0528);
++
++	v4l_dbg(1, debug, client, "tvaudio thread status: 0x%x [%s%s%s]\n",
++		reg_data3, stdres[reg_data3 & 0x1f],
++		(reg_data3 & 0x000020) ? ",stereo" : "",
++		(reg_data3 & 0x000040) ? ",dual"   : "");
++	v4l_dbg(1, debug, client, "detailed status: "
++		"%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
++		(reg_data3 & 0x000080) ? " A2/EIAJ pilot tone "     : "",
++		(reg_data3 & 0x000100) ? " A2/EIAJ dual "           : "",
++		(reg_data3 & 0x000200) ? " A2/EIAJ stereo "         : "",
++		(reg_data3 & 0x000400) ? " A2/EIAJ noise mute "     : "",
++
++		(reg_data3 & 0x000800) ? " BTSC/FM radio pilot "    : "",
++		(reg_data3 & 0x001000) ? " SAP carrier "            : "",
++		(reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
++		(reg_data3 & 0x004000) ? " SAP noise mute "         : "",
++		(reg_data3 & 0x008000) ? " VDSP "                   : "",
++
++		(reg_data3 & 0x010000) ? " NICST "                  : "",
++		(reg_data3 & 0x020000) ? " NICDU "                  : "",
++		(reg_data3 & 0x040000) ? " NICAM muted "            : "",
++		(reg_data3 & 0x080000) ? " NICAM reserve sound "    : "",
++
++		(reg_data3 & 0x100000) ? " init done "              : "");
++
++	if (reg_data3 & 0x000220) {
++		v4l_dbg(1, debug, client, "ST!!!\n");
++		*stereo_flag = 1;
++	}
++
++	if (reg_data3 & 0x000140) {
++		v4l_dbg(1, debug, client, "DUAL!!!\n");
++		*dual_flag = 1;
++	}
++}
++
++/* regs write to set audio mode */
++static void set_audio_mode(struct i2c_client *client, int audio_mode)
++{
++	v4l_dbg(1, debug, client, "writing registers to set audio mode by set %d\n",
++			audio_mode);
++
++	saa717x_write(client, 0x46c, reg_set_audio_template[audio_mode][0]);
++	saa717x_write(client, 0x470, reg_set_audio_template[audio_mode][1]);
++}
++
++/* write regs to video output level (bright,contrast,hue,sat) */
++static void set_video_output_level_regs(struct i2c_client *client,
++		struct saa717x_state *decoder)
++{
++	/* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */
++	saa717x_write(client, 0x10a, decoder->bright);
++
++	/* contrast 7fh (max: 1.984) - 44h (ITU) - 40h (1.0) -
++	   0h (luminance off) 40: i2c dump
++	   c0h (-1.0 inverse chrominance)
++	   80h (-2.0 inverse chrominance) */
++	saa717x_write(client, 0x10b, decoder->contrast);
++
++	/* saturation? 7fh(max)-40h(ITU)-0h(color off)
++	   c0h (-1.0 inverse chrominance)
++	   80h (-2.0 inverse chrominance) */
++	saa717x_write(client, 0x10c, decoder->sat);
++
++	/* color hue (phase) control
++	   7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */
++	saa717x_write(client, 0x10d, decoder->hue);
++}
++
++/* write regs to set audio volume, bass and treble */
++static int set_audio_regs(struct i2c_client *client,
++		struct saa717x_state *decoder)
++{
++	u8 mute = 0xac; /* -84 dB */
++	u32 val;
++	unsigned int work_l, work_r;
++
++	/* set SIF analog I/O select */
++	saa717x_write(client, 0x0594, decoder->audio_input);
++	v4l_dbg(1, debug, client, "set audio input %d\n",
++			decoder->audio_input);
++
++	/* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
++	work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
++	work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
++	decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
++	decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
++
++	/* set main volume */
++	/* main volume L[7-0],R[7-0],0x00  24=24dB,-83dB, -84(mute) */
++	/*    def:0dB->6dB(MPG600GR) */
++	/* if mute is on, set mute */
++	if (decoder->audio_main_mute) {
++		val = mute | (mute << 8);
++	} else {
++		val = (u8)decoder->audio_main_vol_l |
++			((u8)decoder->audio_main_vol_r << 8);
++	}
++
++	saa717x_write(client, 0x480, val);
++
++	/* bass and treble; go to another function */
++	/* set bass and treble */
++	val = decoder->audio_main_bass | (decoder->audio_main_treble << 8);
++	saa717x_write(client, 0x488, val);
++	return 0;
++}
++
++/********** scaling staff ***********/
++static void set_h_prescale(struct i2c_client *client,
++		int task, int prescale)
++{
++	static const struct {
++		int xpsc;
++		int xacl;
++		int xc2_1;
++		int xdcg;
++		int vpfy;
++	} vals[] = {
++		/* XPSC XACL XC2_1 XDCG VPFY */
++		{    1,   0,    0,    0,   0 },
++		{    2,   2,    1,    2,   2 },
++		{    3,   4,    1,    3,   2 },
++		{    4,   8,    1,    4,   2 },
++		{    5,   8,    1,    4,   2 },
++		{    6,   8,    1,    4,   3 },
++		{    7,   8,    1,    4,   3 },
++		{    8,  15,    0,    4,   3 },
++		{    9,  15,    0,    4,   3 },
++		{   10,  16,    1,    5,   3 },
++	};
++	static const int count = ARRAY_SIZE(vals);
++	int i, task_shift;
++
++	task_shift = task * 0x40;
++	for (i = 0; i < count; i++)
++		if (vals[i].xpsc == prescale)
++			break;
++	if (i == count)
++		return;
++
++	/* horizonal prescaling */
++	saa717x_write(client, 0x60 + task_shift, vals[i].xpsc);
++	/* accumulation length */
++	saa717x_write(client, 0x61 + task_shift, vals[i].xacl);
++	/* level control */
++	saa717x_write(client, 0x62 + task_shift,
++			(vals[i].xc2_1 << 3) | vals[i].xdcg);
++	/*FIR prefilter control */
++	saa717x_write(client, 0x63 + task_shift,
++			(vals[i].vpfy << 2) | vals[i].vpfy);
++}
++
++/********** scaling staff ***********/
++static void set_v_scale(struct i2c_client *client, int task, int yscale)
++{
++	int task_shift;
++
++	task_shift = task * 0x40;
++	/* Vertical scaling ratio (LOW) */
++	saa717x_write(client, 0x70 + task_shift, yscale & 0xff);
++	/* Vertical scaling ratio (HI) */
++	saa717x_write(client, 0x71 + task_shift, yscale >> 8);
++}
++
++static int saa717x_set_audio_clock_freq(struct i2c_client *client, u32 freq)
++{
++	/* not yet implament, so saa717x_cfg_??hz_??_audio is not defined. */
++	return 0;
++}
++
++static int saa717x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
++{
++	struct saa717x_state *state = i2c_get_clientdata(client);
++
++	switch (ctrl->id) {
++	case V4L2_CID_BRIGHTNESS:
++		if (ctrl->value < 0 || ctrl->value > 255) {
++			v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
++			return -ERANGE;
++		}
++
++		state->bright = ctrl->value;
++		v4l_dbg(1, debug, client, "bright:%d\n", state->bright);
++		saa717x_write(client, 0x10a, state->bright);
++		break;
++
++	case V4L2_CID_CONTRAST:
++		if (ctrl->value < 0 || ctrl->value > 127) {
++			v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
++			return -ERANGE;
++		}
++
++		state->contrast = ctrl->value;
++		v4l_dbg(1, debug, client, "contrast:%d\n", state->contrast);
++		saa717x_write(client, 0x10b, state->contrast);
++		break;
++
++	case V4L2_CID_SATURATION:
++		if (ctrl->value < 0 || ctrl->value > 127) {
++			v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
++			return -ERANGE;
++		}
++
++		state->sat = ctrl->value;
++		v4l_dbg(1, debug, client, "sat:%d\n", state->sat);
++		saa717x_write(client, 0x10c, state->sat);
++		break;
++
++	case V4L2_CID_HUE:
++		if (ctrl->value < -127 || ctrl->value > 127) {
++			v4l_err(client, "invalid hue setting %d\n", ctrl->value);
++			return -ERANGE;
++		}
++
++		state->hue = ctrl->value;
++		v4l_dbg(1, debug, client, "hue:%d\n", state->hue);
++		saa717x_write(client, 0x10d, state->hue);
++		break;
++
++	case V4L2_CID_AUDIO_MUTE:
++		state->audio_main_mute = ctrl->value;
++		set_audio_regs(client, state);
++		break;
++
++	case V4L2_CID_AUDIO_VOLUME:
++		state->audio_main_volume = ctrl->value;
++		set_audio_regs(client, state);
++		break;
++
++	case V4L2_CID_AUDIO_BALANCE:
++		state->audio_main_balance = ctrl->value;
++		set_audio_regs(client, state);
++		break;
++
++	case V4L2_CID_AUDIO_TREBLE:
++		state->audio_main_treble = ctrl->value;
++		set_audio_regs(client, state);
++		break;
++
++	case V4L2_CID_AUDIO_BASS:
++		state->audio_main_bass = ctrl->value;
++		set_audio_regs(client, state);
++		break;
++
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static int saa717x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
++{
++	struct saa717x_state *state = i2c_get_clientdata(client);
++
++	switch (ctrl->id) {
++	case V4L2_CID_BRIGHTNESS:
++		ctrl->value = state->bright;
++		break;
++
++	case V4L2_CID_CONTRAST:
++		ctrl->value = state->contrast;
++		break;
++
++	case V4L2_CID_SATURATION:
++		ctrl->value = state->sat;
++		break;
++
++	case V4L2_CID_HUE:
++		ctrl->value = state->hue;
++		break;
++
++	case V4L2_CID_AUDIO_MUTE:
++		ctrl->value = state->audio_main_mute;
++		break;
++
++	case V4L2_CID_AUDIO_VOLUME:
++		ctrl->value = state->audio_main_volume;
++		break;
++
++	case V4L2_CID_AUDIO_BALANCE:
++		ctrl->value = state->audio_main_balance;
++		break;
++
++	case V4L2_CID_AUDIO_TREBLE:
++		ctrl->value = state->audio_main_treble;
++		break;
++
++	case V4L2_CID_AUDIO_BASS:
++		ctrl->value = state->audio_main_bass;
++		break;
++
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static struct v4l2_queryctrl saa717x_qctrl[] = {
++	{
++		.id            = V4L2_CID_BRIGHTNESS,
++		.type          = V4L2_CTRL_TYPE_INTEGER,
++		.name          = "Brightness",
++		.minimum       = 0,
++		.maximum       = 255,
++		.step          = 1,
++		.default_value = 128,
++		.flags         = 0,
++	}, {
++		.id            = V4L2_CID_CONTRAST,
++		.type          = V4L2_CTRL_TYPE_INTEGER,
++		.name          = "Contrast",
++		.minimum       = 0,
++		.maximum       = 255,
++		.step          = 1,
++		.default_value = 64,
++		.flags         = 0,
++	}, {
++		.id            = V4L2_CID_SATURATION,
++		.type          = V4L2_CTRL_TYPE_INTEGER,
++		.name          = "Saturation",
++		.minimum       = 0,
++		.maximum       = 255,
++		.step          = 1,
++		.default_value = 64,
++		.flags         = 0,
++	}, {
++		.id            = V4L2_CID_HUE,
++		.type          = V4L2_CTRL_TYPE_INTEGER,
++		.name          = "Hue",
++		.minimum       = -128,
++		.maximum       = 127,
++		.step          = 1,
++		.default_value = 0,
++		.flags 	       = 0,
++	}, {
++		.id            = V4L2_CID_AUDIO_VOLUME,
++		.type          = V4L2_CTRL_TYPE_INTEGER,
++		.name          = "Volume",
++		.minimum       = 0,
++		.maximum       = 65535,
++		.step          = 65535 / 100,
++		.default_value = 58880,
++		.flags         = 0,
++	}, {
++		.id            = V4L2_CID_AUDIO_BALANCE,
++		.type          = V4L2_CTRL_TYPE_INTEGER,
++		.name          = "Balance",
++		.minimum       = 0,
++		.maximum       = 65535,
++		.step          = 65535 / 100,
++		.default_value = 32768,
++		.flags         = 0,
++	}, {
++		.id            = V4L2_CID_AUDIO_MUTE,
++		.type          = V4L2_CTRL_TYPE_BOOLEAN,
++		.name          = "Mute",
++		.minimum       = 0,
++		.maximum       = 1,
++		.step          = 1,
++		.default_value = 1,
++		.flags         = 0,
++	}, {
++		.id            = V4L2_CID_AUDIO_BASS,
++		.type          = V4L2_CTRL_TYPE_INTEGER,
++		.name          = "Bass",
++		.minimum       = 0,
++		.maximum       = 65535,
++		.step          = 65535 / 100,
++		.default_value = 32768,
++	}, {
++		.id            = V4L2_CID_AUDIO_TREBLE,
++		.type          = V4L2_CTRL_TYPE_INTEGER,
++		.name          = "Treble",
++		.minimum       = 0,
++		.maximum       = 65535,
++		.step          = 65535 / 100,
++		.default_value = 32768,
++	},
++};
++
++static int saa717x_set_video_input(struct i2c_client *client, struct saa717x_state *decoder, int inp)
++{
++	int is_tuner = inp & 0x80;  /* tuner input flag */
++
++	inp &= 0x7f;
++
++	v4l_dbg(1, debug, client, "decoder set input (%d)\n", inp);
++	/* inputs from 0-9 are available*/
++	/* saa717x have mode0-mode9 but mode5 is reserved. */
++	if (inp < 0 || inp > 9 || inp == 5)
++		return -EINVAL;
++
++	if (decoder->input != inp) {
++		int input_line = inp;
++
++		decoder->input = input_line;
++		v4l_dbg(1, debug, client,  "now setting %s input %d\n",
++				input_line >= 6 ? "S-Video" : "Composite",
++				input_line);
++
++		/* select mode */
++		saa717x_write(client, 0x102,
++				(saa717x_read(client, 0x102) & 0xf0) |
++				input_line);
++
++		/* bypass chrominance trap for modes 6..9 */
++		saa717x_write(client, 0x109,
++				(saa717x_read(client, 0x109) & 0x7f) |
++				(input_line < 6 ? 0x0 : 0x80));
++
++		/* change audio_mode */
++		if (is_tuner) {
++			/* tuner */
++			set_audio_mode(client, decoder->tuner_audio_mode);
++		} else {
++			/* Force to STEREO mode if Composite or
++			 * S-Video were chosen */
++			set_audio_mode(client, TUNER_AUDIO_STEREO);
++		}
++		/* change initialize procedure (Composite/S-Video) */
++		if (is_tuner)
++			saa717x_write_regs(client, reg_init_tuner_input);
++		else if (input_line >= 6)
++			saa717x_write_regs(client, reg_init_svideo_input);
++		else
++			saa717x_write_regs(client, reg_init_composite_input);
++	}
++
++	return 0;
++}
++
++static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg)
++{
++	struct saa717x_state *decoder = i2c_get_clientdata(client);
++
++	v4l_dbg(1, debug, client, "IOCTL: %08x\n", cmd);
++
++	switch (cmd) {
++	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
++		return saa717x_set_audio_clock_freq(client, *(u32 *)arg);
++
++	case VIDIOC_G_CTRL:
++		return saa717x_get_v4lctrl(client, (struct v4l2_control *)arg);
++
++	case VIDIOC_S_CTRL:
++		return saa717x_set_v4lctrl(client, (struct v4l2_control *)arg);
++
++	case VIDIOC_QUERYCTRL: {
++		struct v4l2_queryctrl *qc = arg;
++		int i;
++
++		for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++)
++			if (qc->id && qc->id == saa717x_qctrl[i].id) {
++				memcpy(qc, &saa717x_qctrl[i], sizeof(*qc));
++				return 0;
++			}
++		return -EINVAL;
++	}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++	case VIDIOC_DBG_G_REGISTER: {
++		struct v4l2_register *reg = arg;
++
++		if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
++			return -EINVAL;
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++		reg->val = saa717x_read(client, reg->reg);
++		break;
++	}
++
++	case VIDIOC_DBG_S_REGISTER: {
++		struct v4l2_register *reg = arg;
++		u16 addr = reg->reg & 0xffff;
++		u8 val = reg->val & 0xff;
++
++		if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
++			return -EINVAL;
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++		saa717x_write(client, addr, val);
++		break;
++	}
++#endif
++
++	case VIDIOC_S_FMT: {
++		struct v4l2_format *fmt = (struct v4l2_format *)arg;
++		struct v4l2_pix_format *pix;
++		int prescale, h_scale, v_scale;
++
++		pix = &fmt->fmt.pix;
++		v4l_dbg(1, debug, client, "decoder set size\n");
++
++		/* FIXME need better bounds checking here */
++		if (pix->width < 1 || pix->width > 1440)
++			return -EINVAL;
++		if (pix->height < 1 || pix->height > 960)
++			return -EINVAL;
++
++		/* scaling setting */
++		/* NTSC and interlace only */
++		prescale = SAA717X_NTSC_WIDTH / pix->width;
++		if (prescale == 0)
++			prescale = 1;
++		h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width;
++		/* interlace */
++		v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height;
++
++		/* Horizontal prescaling etc */
++		set_h_prescale(client, 0, prescale);
++		set_h_prescale(client, 1, prescale);
++
++		/* Horizontal scaling increment */
++		/* TASK A */
++		saa717x_write(client, 0x6C, (u8)(h_scale & 0xFF));
++		saa717x_write(client, 0x6D, (u8)((h_scale >> 8) & 0xFF));
++		/* TASK B */
++		saa717x_write(client, 0xAC, (u8)(h_scale & 0xFF));
++		saa717x_write(client, 0xAD, (u8)((h_scale >> 8) & 0xFF));
++
++		/* Vertical prescaling etc */
++		set_v_scale(client, 0, v_scale);
++		set_v_scale(client, 1, v_scale);
++
++		/* set video output size */
++		/* video number of pixels at output */
++		/* TASK A */
++		saa717x_write(client, 0x5C, (u8)(pix->width & 0xFF));
++		saa717x_write(client, 0x5D, (u8)((pix->width >> 8) & 0xFF));
++		/* TASK B */
++		saa717x_write(client, 0x9C, (u8)(pix->width & 0xFF));
++		saa717x_write(client, 0x9D, (u8)((pix->width >> 8) & 0xFF));
++
++		/* video number of lines at output */
++		/* TASK A */
++		saa717x_write(client, 0x5E, (u8)(pix->height & 0xFF));
++		saa717x_write(client, 0x5F, (u8)((pix->height >> 8) & 0xFF));
++		/* TASK B */
++		saa717x_write(client, 0x9E, (u8)(pix->height & 0xFF));
++		saa717x_write(client, 0x9F, (u8)((pix->height >> 8) & 0xFF));
++		break;
++	}
++
++	case AUDC_SET_RADIO:
++		decoder->radio = 1;
++		break;
++
++	case VIDIOC_S_STD: {
++		v4l2_std_id std = *(v4l2_std_id *) arg;
++
++		v4l_dbg(1, debug, client, "decoder set norm ");
++		v4l_dbg(1, debug, client, "(not yet implementd)\n");
++
++		decoder->radio = 0;
++		decoder->std = std;
++		break;
++	}
++
++	case VIDIOC_INT_G_AUDIO_ROUTING: {
++		struct v4l2_routing *route = arg;
++
++		route->input = decoder->audio_input;
++		route->output = 0;
++		break;
++	}
++
++	case VIDIOC_INT_S_AUDIO_ROUTING: {
++		struct v4l2_routing *route = arg;
++
++		if (route->input < 3) { /* FIXME! --tadachi */
++			decoder->audio_input = route->input;
++			v4l_dbg(1, debug, client,
++				"set decoder audio input to %d\n",
++				decoder->audio_input);
++			set_audio_regs(client, decoder);
++			break;
++		}
++		return -ERANGE;
++	}
++
++	case VIDIOC_INT_S_VIDEO_ROUTING: {
++		struct v4l2_routing *route = arg;
++		int inp = route->input;
++
++		return saa717x_set_video_input(client, decoder, inp);
++	}
++
++	case VIDIOC_STREAMON: {
++		v4l_dbg(1, debug, client, "decoder enable output\n");
++		decoder->enable = 1;
++		saa717x_write(client, 0x193, 0xa6);
++		break;
++	}
++
++	case VIDIOC_STREAMOFF: {
++		v4l_dbg(1, debug, client, "decoder disable output\n");
++		decoder->enable = 0;
++		saa717x_write(client, 0x193, 0x26); /* right? FIXME!--tadachi */
++		break;
++	}
++
++		/* change audio mode */
++	case VIDIOC_S_TUNER: {
++		struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
++		int audio_mode;
++		char *mes[4] = {
++			"MONO", "STEREO", "LANG1", "LANG2/SAP"
++		};
++
++		audio_mode = V4L2_TUNER_MODE_STEREO;
++
++		switch (vt->audmode) {
++		case V4L2_TUNER_MODE_MONO:
++			audio_mode = TUNER_AUDIO_MONO;
++			break;
++		case V4L2_TUNER_MODE_STEREO:
++			audio_mode = TUNER_AUDIO_STEREO;
++			break;
++		case V4L2_TUNER_MODE_LANG2:
++			audio_mode = TUNER_AUDIO_LANG2;
++			break;
++		case V4L2_TUNER_MODE_LANG1:
++			audio_mode = TUNER_AUDIO_LANG1;
++			break;
++		}
++
++		v4l_dbg(1, debug, client, "change audio mode to %s\n",
++				mes[audio_mode]);
++		decoder->tuner_audio_mode = audio_mode;
++		/* The registers are not changed here. */
++		/* See DECODER_ENABLE_OUTPUT section. */
++		set_audio_mode(client, decoder->tuner_audio_mode);
++		break;
++	}
++
++	case VIDIOC_G_TUNER: {
++		struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
++		int dual_f, stereo_f;
++
++		if (decoder->radio)
++			break;
++		get_inf_dev_status(client, &dual_f, &stereo_f);
++
++		v4l_dbg(1, debug, client, "DETECT==st:%d dual:%d\n",
++				stereo_f, dual_f);
++
++		/* mono */
++		if ((dual_f == 0) && (stereo_f == 0)) {
++			vt->rxsubchans = V4L2_TUNER_SUB_MONO;
++			v4l_dbg(1, debug, client, "DETECT==MONO\n");
++		}
++
++		/* stereo */
++		if (stereo_f == 1) {
++			if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
++			    vt->audmode == V4L2_TUNER_MODE_LANG1) {
++				vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
++				v4l_dbg(1, debug, client, "DETECT==ST(ST)\n");
++			} else {
++				vt->rxsubchans = V4L2_TUNER_SUB_MONO;
++				v4l_dbg(1, debug, client, "DETECT==ST(MONO)\n");
++			}
++		}
++
++		/* dual */
++		if (dual_f == 1) {
++			if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
++				vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
++				v4l_dbg(1, debug, client, "DETECT==DUAL1\n");
++			} else {
++				vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
++				v4l_dbg(1, debug, client, "DETECT==DUAL2\n");
++			}
++		}
++		break;
++	}
++
++	case VIDIOC_LOG_STATUS:
++		/* not yet implemented */
++		break;
++
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++/* ----------------------------------------------------------------------- */
++
++
++/* i2c implementation */
++
++/* ----------------------------------------------------------------------- */
++static int saa717x_probe(struct i2c_client *client)
++{
++	struct saa717x_state *decoder;
++	u8 id = 0;
++	char *p = "";
++
++	/* Check if the adapter supports the needed features */
++	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
++		return -EIO;
++
++	snprintf(client->name, sizeof(client->name) - 1, "saa717x");
++
++	if (saa717x_write(client, 0x5a4, 0xfe) &&
++			saa717x_write(client, 0x5a5, 0x0f) &&
++			saa717x_write(client, 0x5a6, 0x00) &&
++			saa717x_write(client, 0x5a7, 0x01))
++		id = saa717x_read(client, 0x5a0);
++	if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
++		v4l_dbg(1, debug, client, "saa717x not found (id=%02x)\n", id);
++		return -ENODEV;
++	}
++	if (id == 0xc2)
++		p = "saa7173";
++	else if (id == 0x32)
++		p = "saa7174A";
++	else if (id == 0x6c)
++		p = "saa7174HL";
++	else
++		p = "saa7171";
++	v4l_info(client, "%s found @ 0x%x (%s)\n", p,
++			client->addr << 1, client->adapter->name);
++
++	decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
++	i2c_set_clientdata(client, decoder);
++
++	if (decoder == NULL)
++		return -ENOMEM;
++	decoder->std = V4L2_STD_NTSC;
++	decoder->input = -1;
++	decoder->enable = 1;
++
++	/* tune these parameters */
++	decoder->bright = 0x80;
++	decoder->contrast = 0x44;
++	decoder->sat = 0x40;
++	decoder->hue = 0x00;
++
++	/* FIXME!! */
++	decoder->playback = 0;	/* initially capture mode used */
++	decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
++
++	decoder->audio_input = 2; /* FIXME!! */
++
++	decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
++	/* set volume, bass and treble */
++	decoder->audio_main_vol_l = 6;
++	decoder->audio_main_vol_r = 6;
++	decoder->audio_main_bass = 0;
++	decoder->audio_main_treble = 0;
++	decoder->audio_main_mute = 0;
++	decoder->audio_main_balance = 32768;
++	/* normalize (24 to -40 (not -84) -> 65535 to 0) */
++	decoder->audio_main_volume =
++		(decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40));
++
++	v4l_dbg(1, debug, client, "writing init values\n");
++
++	/* FIXME!! */
++	saa717x_write_regs(client, reg_init_initialize);
++	set_video_output_level_regs(client, decoder);
++	/* set bass,treble to 0db 20041101 K.Ohta */
++	decoder->audio_main_bass = 0;
++	decoder->audio_main_treble = 0;
++	set_audio_regs(client, decoder);
++
++	set_current_state(TASK_INTERRUPTIBLE);
++	schedule_timeout(2*HZ);
++	return 0;
++}
++
++static int saa717x_remove(struct i2c_client *client)
++{
++	kfree(i2c_get_clientdata(client));
++	return 0;
++}
++
++/* ----------------------------------------------------------------------- */
++
++static struct v4l2_i2c_driver_data v4l2_i2c_data = {
++	.name = "saa717x",
++	.driverid = I2C_DRIVERID_SAA717X,
++	.command = saa717x_command,
++	.probe = saa717x_probe,
++	.remove = saa717x_remove,
++	.legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
++};
+diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
+index 41f7044..02fda4e 100644
+--- a/drivers/media/video/saa7185.c
++++ b/drivers/media/video/saa7185.c
+@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+ 
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
+index d5d7d6c..1cd6293 100644
+--- a/drivers/media/video/se401.c
++++ b/drivers/media/video/se401.c
+@@ -35,7 +35,7 @@ static const char version[] = "0.24";
+ #include <linux/usb.h>
+ #include "se401.h"
+ 
+-static int flickerless=0;
++static int flickerless;
+ static int video_nr = -1;
+ 
+ static struct usb_device_id device_table [] = {
+@@ -300,10 +300,10 @@ static void se401_button_irq(struct urb *urb)
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
++		dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ 		return;
+ 	default:
+-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
++		dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ 		goto exit;
+ 	}
+ 
+@@ -315,7 +315,7 @@ exit:
+ 	status = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (status)
+ 		err ("%s - usb_submit_urb failed with result %d",
+-		     __FUNCTION__, status);
++		     __func__, status);
+ }
+ 
+ static void se401_video_irq(struct urb *urb)
+@@ -1224,7 +1224,9 @@ static const struct file_operations se401_fops = {
+ 	.read =         se401_read,
+ 	.mmap =         se401_mmap,
+ 	.ioctl =        se401_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.llseek =       no_llseek,
+ };
+ static struct video_device se401_template = {
+@@ -1279,7 +1281,7 @@ static int se401_init(struct usb_se401 *se401, int button)
+ 	rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
+ 	se401->cheight=cp[0]+cp[1]*256;
+ 
+-	if (!cp[2] && SE401_FORMAT_BAYER) {
++	if (!(cp[2] & SE401_FORMAT_BAYER)) {
+ 		err("Bayer format not supported!");
+ 		return 1;
+ 	}
+diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
+index 2e3c3de..0c8d87d 100644
+--- a/drivers/media/video/sn9c102/sn9c102.h
++++ b/drivers/media/video/sn9c102/sn9c102.h
+@@ -176,7 +176,7 @@ do {                                                                          \
+ 			dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
+ 		else if ((level) >= 3)                                        \
+ 			dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",      \
+-				 __FUNCTION__, __LINE__ , ## args);           \
++				 __func__, __LINE__ , ## args);           \
+ 	}                                                                     \
+ } while (0)
+ #	define V4LDBG(level, name, cmd)                                       \
+@@ -191,7 +191,7 @@ do {                                                                          \
+ 			pr_info("sn9c102: " fmt "\n", ## args);               \
+ 		else if ((level) == 3)                                        \
+ 			pr_debug("sn9c102: [%s:%d] " fmt "\n",                \
+-				 __FUNCTION__, __LINE__ , ## args);           \
++				 __func__, __LINE__ , ## args);           \
+ 	}                                                                     \
+ } while (0)
+ #else
+@@ -202,7 +202,7 @@ do {                                                                          \
+ 
+ #undef PDBG
+ #define PDBG(fmt, args...)                                                    \
+-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
++dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
+ 	 __LINE__ , ## args)
+ 
+ #undef PDBGG
+diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
+index c40ba3a..5748b1e 100644
+--- a/drivers/media/video/sn9c102/sn9c102_core.c
++++ b/drivers/media/video/sn9c102/sn9c102_core.c
+@@ -464,9 +464,9 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
+ }
+ 
+ 
+-int
+-sn9c102_i2c_try_write(struct sn9c102_device* cam,
+-		      const struct sn9c102_sensor* sensor, u8 address, u8 value)
++static int sn9c102_i2c_try_write(struct sn9c102_device* cam,
++				 const struct sn9c102_sensor* sensor,
++				 u8 address, u8 value)
+ {
+ 	return sn9c102_i2c_try_raw_write(cam, sensor, 3,
+ 					 sensor->i2c_slave_id, address,
+@@ -528,7 +528,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
+ 
+ 		/* Search for the SOF marker (fixed part) in the header */
+ 		for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
+-			if (unlikely(i+j) == len)
++			if (unlikely(i+j == len))
+ 				return NULL;
+ 			if (*(m+i+j) == marker[cam->sof.bytesread]) {
+ 				cam->sof.header[cam->sof.bytesread] = *(m+i+j);
+@@ -3224,7 +3224,9 @@ static const struct file_operations sn9c102_fops = {
+ 	.open = sn9c102_open,
+ 	.release = sn9c102_release,
+ 	.ioctl = sn9c102_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.read = sn9c102_read,
+ 	.poll = sn9c102_poll,
+ 	.mmap = sn9c102_mmap,
+@@ -3239,7 +3241,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+ {
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	struct sn9c102_device* cam;
+-	static unsigned int dev_nr = 0;
++	static unsigned int dev_nr;
+ 	unsigned int i;
+ 	int err = 0, r;
+ 
+diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
+index 2d7d786..4af7382 100644
+--- a/drivers/media/video/sn9c102/sn9c102_sensor.h
++++ b/drivers/media/video/sn9c102/sn9c102_sensor.h
+@@ -85,9 +85,6 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
+ */
+ 
+ /* The "try" I2C I/O versions are used when probing the sensor */
+-extern int sn9c102_i2c_try_write(struct sn9c102_device*,
+-				 const struct sn9c102_sensor*, u8 address,
+-				 u8 value);
+ extern int sn9c102_i2c_try_read(struct sn9c102_device*,
+ 				const struct sn9c102_sensor*, u8 address);
+ 
+@@ -126,7 +123,7 @@ extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
+    Register adresses must be < 256.
+ */
+ #define sn9c102_write_const_regs(sn9c102_device, data...)                     \
+-	({ const static u8 _valreg[][2] = {data};                             \
++	({ static const u8 _valreg[][2] = {data};                             \
+ 	sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
+ 
+ /*****************************************************************************/
+diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
+new file mode 100644
+index 0000000..a1b9244
+--- /dev/null
++++ b/drivers/media/video/soc_camera.c
+@@ -0,0 +1,1031 @@
++/*
++ * camera image capture (abstract) bus driver
++ *
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at pengutronix.de>
++ *
++ * This driver provides an interface between platform-specific camera
++ * busses and camera devices. It should be used if the camera is
++ * connected not over a "proper" bus like PCI or USB, but over a
++ * special bus, like, for example, the Quick Capture interface on PXA270
++ * SoCs. Later it should also be used for i.MX31 SoCs from Freescale.
++ * It can handle multiple cameras and / or multiple busses, which can
++ * be used, e.g., in stereo-vision applications.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/list.h>
++#include <linux/err.h>
++#include <linux/mutex.h>
++#include <linux/vmalloc.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-dev.h>
++#include <media/soc_camera.h>
++
++static LIST_HEAD(hosts);
++static LIST_HEAD(devices);
++static DEFINE_MUTEX(list_lock);
++static DEFINE_MUTEX(video_lock);
++
++const static struct soc_camera_data_format*
++format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc)
++{
++	unsigned int i;
++
++	for (i = 0; i < icd->num_formats; i++)
++		if (icd->formats[i].fourcc == fourcc)
++			return icd->formats + i;
++	return NULL;
++}
++
++static int soc_camera_try_fmt_cap(struct file *file, void *priv,
++				  struct v4l2_format *f)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	enum v4l2_field field;
++	const struct soc_camera_data_format *fmt;
++	int ret;
++
++	WARN_ON(priv != file->private_data);
++
++	fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat);
++	if (!fmt) {
++		dev_dbg(&icd->dev, "invalid format 0x%08x\n",
++			f->fmt.pix.pixelformat);
++		return -EINVAL;
++	}
++
++	dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc);
++
++	field = f->fmt.pix.field;
++
++	if (field == V4L2_FIELD_ANY) {
++		field = V4L2_FIELD_NONE;
++	} else if (V4L2_FIELD_NONE != field) {
++		dev_err(&icd->dev, "Field type invalid.\n");
++		return -EINVAL;
++	}
++
++	/* test physical bus parameters */
++	ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat);
++	if (ret)
++		return ret;
++
++	/* limit format to hardware capabilities */
++	ret = ici->ops->try_fmt_cap(icd, f);
++
++	/* calculate missing fields */
++	f->fmt.pix.field = field;
++	f->fmt.pix.bytesperline =
++		(f->fmt.pix.width * fmt->depth) >> 3;
++	f->fmt.pix.sizeimage =
++		f->fmt.pix.height * f->fmt.pix.bytesperline;
++
++	return ret;
++}
++
++static int soc_camera_enum_input(struct file *file, void *priv,
++				 struct v4l2_input *inp)
++{
++	if (inp->index != 0)
++		return -EINVAL;
++
++	inp->type = V4L2_INPUT_TYPE_CAMERA;
++	inp->std = V4L2_STD_UNKNOWN;
++	strcpy(inp->name, "Camera");
++
++	return 0;
++}
++
++static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i)
++{
++	*i = 0;
++
++	return 0;
++}
++
++static int soc_camera_s_input(struct file *file, void *priv, unsigned int i)
++{
++	if (i > 0)
++		return -EINVAL;
++
++	return 0;
++}
++
++static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a)
++{
++	return 0;
++}
++
++static int soc_camera_reqbufs(struct file *file, void *priv,
++			      struct v4l2_requestbuffers *p)
++{
++	int ret;
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++
++	WARN_ON(priv != file->private_data);
++
++	dev_dbg(&icd->dev, "%s: %d\n", __func__, p->memory);
++
++	ret = videobuf_reqbufs(&icf->vb_vidq, p);
++	if (ret < 0)
++		return ret;
++
++	return ici->ops->reqbufs(icf, p);
++}
++
++static int soc_camera_querybuf(struct file *file, void *priv,
++			       struct v4l2_buffer *p)
++{
++	struct soc_camera_file *icf = file->private_data;
++
++	WARN_ON(priv != file->private_data);
++
++	return videobuf_querybuf(&icf->vb_vidq, p);
++}
++
++static int soc_camera_qbuf(struct file *file, void *priv,
++			   struct v4l2_buffer *p)
++{
++	struct soc_camera_file *icf = file->private_data;
++
++	WARN_ON(priv != file->private_data);
++
++	return videobuf_qbuf(&icf->vb_vidq, p);
++}
++
++static int soc_camera_dqbuf(struct file *file, void *priv,
++			    struct v4l2_buffer *p)
++{
++	struct soc_camera_file *icf = file->private_data;
++
++	WARN_ON(priv != file->private_data);
++
++	return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
++}
++
++static int soc_camera_open(struct inode *inode, struct file *file)
++{
++	struct video_device *vdev;
++	struct soc_camera_device *icd;
++	struct soc_camera_host *ici;
++	struct soc_camera_file *icf;
++	spinlock_t *lock;
++	int ret;
++
++	icf = vmalloc(sizeof(*icf));
++	if (!icf)
++		return -ENOMEM;
++
++	/* Protect against icd->remove() until we module_get() both drivers. */
++	mutex_lock(&video_lock);
++
++	vdev = video_devdata(file);
++	icd = container_of(vdev->dev, struct soc_camera_device, dev);
++	ici = to_soc_camera_host(icd->dev.parent);
++
++	if (!try_module_get(icd->ops->owner)) {
++		dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
++		ret = -EINVAL;
++		goto emgd;
++	}
++
++	if (!try_module_get(ici->ops->owner)) {
++		dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
++		ret = -EINVAL;
++		goto emgi;
++	}
++
++	icf->icd = icd;
++
++	icf->lock = ici->ops->spinlock_alloc(icf);
++	if (!icf->lock) {
++		ret = -ENOMEM;
++		goto esla;
++	}
++
++	icd->use_count++;
++
++	/* Now we really have to activate the camera */
++	if (icd->use_count == 1) {
++		ret = ici->ops->add(icd);
++		if (ret < 0) {
++			dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
++			icd->use_count--;
++			goto eiciadd;
++		}
++	}
++
++	mutex_unlock(&video_lock);
++
++	file->private_data = icf;
++	dev_dbg(&icd->dev, "camera device open\n");
++
++	/* We must pass NULL as dev pointer, then all pci_* dma operations
++	 * transform to normal dma_* ones. */
++	videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock,
++				V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
++				ici->msize, icd);
++
++	return 0;
++
++	/* All errors are entered with the video_lock held */
++eiciadd:
++	lock = icf->lock;
++	icf->lock = NULL;
++	if (ici->ops->spinlock_free)
++		ici->ops->spinlock_free(lock);
++esla:
++	module_put(ici->ops->owner);
++emgi:
++	module_put(icd->ops->owner);
++emgd:
++	mutex_unlock(&video_lock);
++	vfree(icf);
++	return ret;
++}
++
++static int soc_camera_close(struct inode *inode, struct file *file)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
++	struct video_device *vdev = icd->vdev;
++	spinlock_t *lock = icf->lock;
++
++	mutex_lock(&video_lock);
++	icd->use_count--;
++	if (!icd->use_count)
++		ici->ops->remove(icd);
++	icf->lock = NULL;
++	if (ici->ops->spinlock_free)
++		ici->ops->spinlock_free(lock);
++	module_put(icd->ops->owner);
++	module_put(ici->ops->owner);
++	mutex_unlock(&video_lock);
++
++	vfree(icf);
++
++	dev_dbg(vdev->dev, "camera device close\n");
++
++	return 0;
++}
++
++static ssize_t soc_camera_read(struct file *file, char __user *buf,
++			   size_t count, loff_t *ppos)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	struct video_device *vdev = icd->vdev;
++	int err = -EINVAL;
++
++	dev_err(vdev->dev, "camera device read not implemented\n");
++
++	return err;
++}
++
++static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	int err;
++
++	dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
++
++	err = videobuf_mmap_mapper(&icf->vb_vidq, vma);
++
++	dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
++		(unsigned long)vma->vm_start,
++		(unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
++		err);
++
++	return err;
++}
++
++static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++
++	if (list_empty(&icf->vb_vidq.stream)) {
++		dev_err(&icd->dev, "Trying to poll with no queued buffers!\n");
++		return POLLERR;
++	}
++
++	return ici->ops->poll(file, pt);
++}
++
++
++static struct file_operations soc_camera_fops = {
++	.owner		= THIS_MODULE,
++	.open		= soc_camera_open,
++	.release	= soc_camera_close,
++	.ioctl		= video_ioctl2,
++	.read		= soc_camera_read,
++	.mmap		= soc_camera_mmap,
++	.poll		= soc_camera_poll,
++	.llseek		= no_llseek,
++};
++
++
++static int soc_camera_s_fmt_cap(struct file *file, void *priv,
++				struct v4l2_format *f)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	int ret;
++	struct v4l2_rect rect;
++	const static struct soc_camera_data_format *data_fmt;
++
++	WARN_ON(priv != file->private_data);
++
++	data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat);
++	if (!data_fmt)
++		return -EINVAL;
++
++	/* buswidth may be further adjusted by the ici */
++	icd->buswidth = data_fmt->depth;
++
++	ret = soc_camera_try_fmt_cap(file, icf, f);
++	if (ret < 0)
++		return ret;
++
++	rect.left	= icd->x_current;
++	rect.top	= icd->y_current;
++	rect.width	= f->fmt.pix.width;
++	rect.height	= f->fmt.pix.height;
++	ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect);
++	if (ret < 0)
++		return ret;
++
++	icd->current_fmt	= data_fmt;
++	icd->width		= rect.width;
++	icd->height		= rect.height;
++	icf->vb_vidq.field	= f->fmt.pix.field;
++	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
++		dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
++			 f->type);
++
++	dev_dbg(&icd->dev, "set width: %d height: %d\n",
++		icd->width, icd->height);
++
++	/* set physical bus parameters */
++	return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat);
++}
++
++static int soc_camera_enum_fmt_cap(struct file *file, void  *priv,
++				   struct v4l2_fmtdesc *f)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	const struct soc_camera_data_format *format;
++
++	WARN_ON(priv != file->private_data);
++
++	if (f->index >= icd->num_formats)
++		return -EINVAL;
++
++	format = &icd->formats[f->index];
++
++	strlcpy(f->description, format->name, sizeof(f->description));
++	f->pixelformat = format->fourcc;
++	return 0;
++}
++
++static int soc_camera_g_fmt_cap(struct file *file, void *priv,
++				struct v4l2_format *f)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	WARN_ON(priv != file->private_data);
++
++	f->fmt.pix.width	= icd->width;
++	f->fmt.pix.height	= icd->height;
++	f->fmt.pix.field	= icf->vb_vidq.field;
++	f->fmt.pix.pixelformat	= icd->current_fmt->fourcc;
++	f->fmt.pix.bytesperline	=
++		(f->fmt.pix.width * icd->current_fmt->depth) >> 3;
++	f->fmt.pix.sizeimage	=
++		f->fmt.pix.height * f->fmt.pix.bytesperline;
++	dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n",
++		icd->current_fmt->fourcc);
++	return 0;
++}
++
++static int soc_camera_querycap(struct file *file, void  *priv,
++			       struct v4l2_capability *cap)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++
++	WARN_ON(priv != file->private_data);
++
++	strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver));
++	return ici->ops->querycap(ici, cap);
++}
++
++static int soc_camera_streamon(struct file *file, void *priv,
++			       enum v4l2_buf_type i)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	WARN_ON(priv != file->private_data);
++
++	dev_dbg(&icd->dev, "%s\n", __func__);
++
++	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++
++	icd->ops->start_capture(icd);
++
++	/* This calls buf_queue from host driver's videobuf_queue_ops */
++	return videobuf_streamon(&icf->vb_vidq);
++}
++
++static int soc_camera_streamoff(struct file *file, void *priv,
++				enum v4l2_buf_type i)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	WARN_ON(priv != file->private_data);
++
++	dev_dbg(&icd->dev, "%s\n", __func__);
++
++	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++
++	/* This calls buf_release from host driver's videobuf_queue_ops for all
++	 * remaining buffers. When the last buffer is freed, stop capture */
++	videobuf_streamoff(&icf->vb_vidq);
++
++	icd->ops->stop_capture(icd);
++
++	return 0;
++}
++
++static int soc_camera_queryctrl(struct file *file, void *priv,
++				struct v4l2_queryctrl *qc)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	int i;
++
++	WARN_ON(priv != file->private_data);
++
++	if (!qc->id)
++		return -EINVAL;
++
++	for (i = 0; i < icd->ops->num_controls; i++)
++		if (qc->id == icd->ops->controls[i].id) {
++			memcpy(qc, &(icd->ops->controls[i]),
++				sizeof(*qc));
++			return 0;
++		}
++
++	return -EINVAL;
++}
++
++static int soc_camera_g_ctrl(struct file *file, void *priv,
++			     struct v4l2_control *ctrl)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	WARN_ON(priv != file->private_data);
++
++	switch (ctrl->id) {
++	case V4L2_CID_GAIN:
++		if (icd->gain == (unsigned short)~0)
++			return -EINVAL;
++		ctrl->value = icd->gain;
++		return 0;
++	case V4L2_CID_EXPOSURE:
++		if (icd->exposure == (unsigned short)~0)
++			return -EINVAL;
++		ctrl->value = icd->exposure;
++		return 0;
++	}
++
++	if (icd->ops->get_control)
++		return icd->ops->get_control(icd, ctrl);
++	return -EINVAL;
++}
++
++static int soc_camera_s_ctrl(struct file *file, void *priv,
++			     struct v4l2_control *ctrl)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	WARN_ON(priv != file->private_data);
++
++	if (icd->ops->set_control)
++		return icd->ops->set_control(icd, ctrl);
++	return -EINVAL;
++}
++
++static int soc_camera_cropcap(struct file *file, void *fh,
++			      struct v4l2_cropcap *a)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	a->bounds.left			= icd->x_min;
++	a->bounds.top			= icd->y_min;
++	a->bounds.width			= icd->width_max;
++	a->bounds.height		= icd->height_max;
++	a->defrect.left			= icd->x_min;
++	a->defrect.top			= icd->y_min;
++	a->defrect.width		= 640;
++	a->defrect.height		= 480;
++	a->pixelaspect.numerator	= 1;
++	a->pixelaspect.denominator	= 1;
++
++	return 0;
++}
++
++static int soc_camera_g_crop(struct file *file, void *fh,
++			     struct v4l2_crop *a)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	a->c.left	= icd->x_current;
++	a->c.top	= icd->y_current;
++	a->c.width	= icd->width;
++	a->c.height	= icd->height;
++
++	return 0;
++}
++
++static int soc_camera_s_crop(struct file *file, void *fh,
++			     struct v4l2_crop *a)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	int ret;
++
++	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++		return -EINVAL;
++
++	ret = ici->ops->set_fmt_cap(icd, 0, &a->c);
++	if (!ret) {
++		icd->width	= a->c.width;
++		icd->height	= a->c.height;
++		icd->x_current	= a->c.left;
++		icd->y_current	= a->c.top;
++	}
++
++	return ret;
++}
++
++static int soc_camera_g_chip_ident(struct file *file, void *fh,
++				   struct v4l2_chip_ident *id)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	if (!icd->ops->get_chip_id)
++		return -EINVAL;
++
++	return icd->ops->get_chip_id(icd, id);
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int soc_camera_g_register(struct file *file, void *fh,
++				 struct v4l2_register *reg)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	if (!icd->ops->get_register)
++		return -EINVAL;
++
++	return icd->ops->get_register(icd, reg);
++}
++
++static int soc_camera_s_register(struct file *file, void *fh,
++				 struct v4l2_register *reg)
++{
++	struct soc_camera_file *icf = file->private_data;
++	struct soc_camera_device *icd = icf->icd;
++
++	if (!icd->ops->set_register)
++		return -EINVAL;
++
++	return icd->ops->set_register(icd, reg);
++}
++#endif
++
++static int device_register_link(struct soc_camera_device *icd)
++{
++	int ret = device_register(&icd->dev);
++
++	if (ret < 0) {
++		/* Prevent calling device_unregister() */
++		icd->dev.parent = NULL;
++		dev_err(&icd->dev, "Cannot register device: %d\n", ret);
++	/* Even if probe() was unsuccessful for all registered drivers,
++	 * device_register() returns 0, and we add the link, just to
++	 * document this camera's control device */
++	} else if (icd->control)
++		/* Have to sysfs_remove_link() before device_unregister()? */
++		if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
++				      "control"))
++			dev_warn(&icd->dev,
++				 "Failed creating the control symlink\n");
++	return ret;
++}
++
++/* So far this function cannot fail */
++static void scan_add_host(struct soc_camera_host *ici)
++{
++	struct soc_camera_device *icd;
++
++	mutex_lock(&list_lock);
++
++	list_for_each_entry(icd, &devices, list) {
++		if (icd->iface == ici->nr) {
++			icd->dev.parent = &ici->dev;
++			device_register_link(icd);
++		}
++	}
++
++	mutex_unlock(&list_lock);
++}
++
++/* return: 0 if no match found or a match found and
++ * device_register() successful, error code otherwise */
++static int scan_add_device(struct soc_camera_device *icd)
++{
++	struct soc_camera_host *ici;
++	int ret = 0;
++
++	mutex_lock(&list_lock);
++
++	list_add_tail(&icd->list, &devices);
++
++	/* Watch out for class_for_each_device / class_find_device API by
++	 * Dave Young <hidave.darkstar at gmail.com> */
++	list_for_each_entry(ici, &hosts, list) {
++		if (icd->iface == ici->nr) {
++			ret = 1;
++			icd->dev.parent = &ici->dev;
++			break;
++		}
++	}
++
++	mutex_unlock(&list_lock);
++
++	if (ret)
++		ret = device_register_link(icd);
++
++	return ret;
++}
++
++static int soc_camera_probe(struct device *dev)
++{
++	struct soc_camera_device *icd = to_soc_camera_dev(dev);
++	struct soc_camera_host *ici =
++		to_soc_camera_host(icd->dev.parent);
++	int ret;
++
++	if (!icd->ops->probe)
++		return -ENODEV;
++
++	/* We only call ->add() here to activate and probe the camera.
++	 * We shall ->remove() and deactivate it immediately afterwards. */
++	ret = ici->ops->add(icd);
++	if (ret < 0)
++		return ret;
++
++	ret = icd->ops->probe(icd);
++	if (ret >= 0) {
++		const struct v4l2_queryctrl *qctrl;
++
++		qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
++		icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
++		qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
++		icd->exposure = qctrl ? qctrl->default_value :
++			(unsigned short)~0;
++	}
++	ici->ops->remove(icd);
++
++	return ret;
++}
++
++/* This is called on device_unregister, which only means we have to disconnect
++ * from the host, but not remove ourselves from the device list */
++static int soc_camera_remove(struct device *dev)
++{
++	struct soc_camera_device *icd = to_soc_camera_dev(dev);
++
++	if (icd->ops->remove)
++		icd->ops->remove(icd);
++
++	return 0;
++}
++
++static struct bus_type soc_camera_bus_type = {
++	.name		= "soc-camera",
++	.probe		= soc_camera_probe,
++	.remove		= soc_camera_remove,
++};
++
++static struct device_driver ic_drv = {
++	.name	= "camera",
++	.bus	= &soc_camera_bus_type,
++	.owner	= THIS_MODULE,
++};
++
++/*
++ * Image capture host - this is a host device, not a bus device, so,
++ * no bus reference, no probing.
++ */
++static struct class soc_camera_host_class = {
++	.owner		= THIS_MODULE,
++	.name		= "camera_host",
++};
++
++static void dummy_release(struct device *dev)
++{
++}
++
++static spinlock_t *spinlock_alloc(struct soc_camera_file *icf)
++{
++	spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
++
++	if (lock)
++		spin_lock_init(lock);
++
++	return lock;
++}
++
++static void spinlock_free(spinlock_t *lock)
++{
++	kfree(lock);
++}
++
++int soc_camera_host_register(struct soc_camera_host *ici)
++{
++	int ret;
++	struct soc_camera_host *ix;
++
++	if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove)
++		return -EINVAL;
++
++	/* Number might be equal to the platform device ID */
++	sprintf(ici->dev.bus_id, "camera_host%d", ici->nr);
++	ici->dev.class = &soc_camera_host_class;
++
++	mutex_lock(&list_lock);
++	list_for_each_entry(ix, &hosts, list) {
++		if (ix->nr == ici->nr) {
++			mutex_unlock(&list_lock);
++			return -EBUSY;
++		}
++	}
++
++	list_add_tail(&ici->list, &hosts);
++	mutex_unlock(&list_lock);
++
++	ici->dev.release = dummy_release;
++
++	ret = device_register(&ici->dev);
++
++	if (ret)
++		goto edevr;
++
++	if (!ici->ops->spinlock_alloc) {
++		ici->ops->spinlock_alloc = spinlock_alloc;
++		ici->ops->spinlock_free = spinlock_free;
++	}
++
++	scan_add_host(ici);
++
++	return 0;
++
++edevr:
++	mutex_lock(&list_lock);
++	list_del(&ici->list);
++	mutex_unlock(&list_lock);
++
++	return ret;
++}
++EXPORT_SYMBOL(soc_camera_host_register);
++
++/* Unregister all clients! */
++void soc_camera_host_unregister(struct soc_camera_host *ici)
++{
++	struct soc_camera_device *icd;
++
++	mutex_lock(&list_lock);
++
++	list_del(&ici->list);
++
++	list_for_each_entry(icd, &devices, list) {
++		if (icd->dev.parent == &ici->dev) {
++			device_unregister(&icd->dev);
++			/* Not before device_unregister(), .remove
++			 * needs parent to call ici->ops->remove() */
++			icd->dev.parent = NULL;
++			memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
++		}
++	}
++
++	mutex_unlock(&list_lock);
++
++	device_unregister(&ici->dev);
++}
++EXPORT_SYMBOL(soc_camera_host_unregister);
++
++/* Image capture device */
++int soc_camera_device_register(struct soc_camera_device *icd)
++{
++	struct soc_camera_device *ix;
++	int num = -1, i;
++
++	if (!icd)
++		return -EINVAL;
++
++	for (i = 0; i < 256 && num < 0; i++) {
++		num = i;
++		list_for_each_entry(ix, &devices, list) {
++			if (ix->iface == icd->iface && ix->devnum == i) {
++				num = -1;
++				break;
++			}
++		}
++	}
++
++	if (num < 0)
++		/* ok, we have 256 cameras on this host...
++		 * man, stay reasonable... */
++		return -ENOMEM;
++
++	icd->devnum = num;
++	icd->dev.bus = &soc_camera_bus_type;
++	snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id),
++		 "%u-%u", icd->iface, icd->devnum);
++
++	icd->dev.release = dummy_release;
++
++	return scan_add_device(icd);
++}
++EXPORT_SYMBOL(soc_camera_device_register);
++
++void soc_camera_device_unregister(struct soc_camera_device *icd)
++{
++	mutex_lock(&list_lock);
++	list_del(&icd->list);
++
++	/* The bus->remove will be eventually called */
++	if (icd->dev.parent)
++		device_unregister(&icd->dev);
++	mutex_unlock(&list_lock);
++}
++EXPORT_SYMBOL(soc_camera_device_unregister);
++
++int soc_camera_video_start(struct soc_camera_device *icd)
++{
++	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
++	int err = -ENOMEM;
++	struct video_device *vdev;
++
++	if (!icd->dev.parent)
++		return -ENODEV;
++
++	vdev = video_device_alloc();
++	if (!vdev)
++		goto evidallocd;
++	dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev);
++
++	strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
++	/* Maybe better &ici->dev */
++	vdev->dev		= &icd->dev;
++	vdev->type		= VID_TYPE_CAPTURE;
++	vdev->current_norm	= V4L2_STD_UNKNOWN;
++	vdev->fops		= &soc_camera_fops;
++	vdev->release		= video_device_release;
++	vdev->minor		= -1;
++	vdev->tvnorms		= V4L2_STD_UNKNOWN,
++	vdev->vidioc_querycap	= soc_camera_querycap;
++	vdev->vidioc_g_fmt_cap	= soc_camera_g_fmt_cap;
++	vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap;
++	vdev->vidioc_s_fmt_cap	= soc_camera_s_fmt_cap;
++	vdev->vidioc_enum_input	= soc_camera_enum_input;
++	vdev->vidioc_g_input	= soc_camera_g_input;
++	vdev->vidioc_s_input	= soc_camera_s_input;
++	vdev->vidioc_s_std	= soc_camera_s_std;
++	vdev->vidioc_reqbufs	= soc_camera_reqbufs;
++	vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap;
++	vdev->vidioc_querybuf	= soc_camera_querybuf;
++	vdev->vidioc_qbuf	= soc_camera_qbuf;
++	vdev->vidioc_dqbuf	= soc_camera_dqbuf;
++	vdev->vidioc_streamon	= soc_camera_streamon;
++	vdev->vidioc_streamoff	= soc_camera_streamoff;
++	vdev->vidioc_queryctrl	= soc_camera_queryctrl;
++	vdev->vidioc_g_ctrl	= soc_camera_g_ctrl;
++	vdev->vidioc_s_ctrl	= soc_camera_s_ctrl;
++	vdev->vidioc_cropcap	= soc_camera_cropcap;
++	vdev->vidioc_g_crop	= soc_camera_g_crop;
++	vdev->vidioc_s_crop	= soc_camera_s_crop;
++	vdev->vidioc_g_chip_ident = soc_camera_g_chip_ident;
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++	vdev->vidioc_g_register	= soc_camera_g_register;
++	vdev->vidioc_s_register	= soc_camera_s_register;
++#endif
++
++	icd->current_fmt = &icd->formats[0];
++
++	err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
++	if (err < 0) {
++		dev_err(vdev->dev, "video_register_device failed\n");
++		goto evidregd;
++	}
++	icd->vdev = vdev;
++
++	return 0;
++
++evidregd:
++	video_device_release(vdev);
++evidallocd:
++	return err;
++}
++EXPORT_SYMBOL(soc_camera_video_start);
++
++void soc_camera_video_stop(struct soc_camera_device *icd)
++{
++	struct video_device *vdev = icd->vdev;
++
++	dev_dbg(&icd->dev, "%s\n", __func__);
++
++	if (!icd->dev.parent || !vdev)
++		return;
++
++	mutex_lock(&video_lock);
++	video_unregister_device(vdev);
++	icd->vdev = NULL;
++	mutex_unlock(&video_lock);
++}
++EXPORT_SYMBOL(soc_camera_video_stop);
++
++static int __init soc_camera_init(void)
++{
++	int ret = bus_register(&soc_camera_bus_type);
++	if (ret)
++		return ret;
++	ret = driver_register(&ic_drv);
++	if (ret)
++		goto edrvr;
++	ret = class_register(&soc_camera_host_class);
++	if (ret)
++		goto eclr;
++
++	return 0;
++
++eclr:
++	driver_unregister(&ic_drv);
++edrvr:
++	bus_unregister(&soc_camera_bus_type);
++	return ret;
++}
++
++static void __exit soc_camera_exit(void)
++{
++	class_unregister(&soc_camera_host_class);
++	driver_unregister(&ic_drv);
++	bus_unregister(&soc_camera_bus_type);
++}
++
++module_init(soc_camera_init);
++module_exit(soc_camera_exit);
++
++MODULE_DESCRIPTION("Image capture bus driver");
++MODULE_AUTHOR("Guennadi Liakhovetski <kernel at pengutronix.de>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
+index ceba45a..9276ed9 100644
+--- a/drivers/media/video/stk-webcam.c
++++ b/drivers/media/video/stk-webcam.c
+@@ -1100,7 +1100,7 @@ static int stk_setup_format(struct stk_camera *dev)
+ 			&& i < ARRAY_SIZE(stk_sizes))
+ 		i++;
+ 	if (i == ARRAY_SIZE(stk_sizes)) {
+-		STK_ERROR("Something is broken in %s\n", __FUNCTION__);
++		STK_ERROR("Something is broken in %s\n", __func__);
+ 		return -EFAULT;
+ 	}
+ 	/* This registers controls some timings, not sure of what. */
+@@ -1465,7 +1465,7 @@ static void stk_camera_disconnect(struct usb_interface *interface)
+ }
+ 
+ #ifdef CONFIG_PM
+-int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
++static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
+ {
+ 	struct stk_camera *dev = usb_get_intfdata(intf);
+ 	if (is_streaming(dev)) {
+@@ -1476,7 +1476,7 @@ int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
+ 	return 0;
+ }
+ 
+-int stk_camera_resume(struct usb_interface *intf)
++static int stk_camera_resume(struct usb_interface *intf)
+ {
+ 	struct stk_camera *dev = usb_get_intfdata(intf);
+ 	if (!is_initialised(dev))
+diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
+index 3fb85af..c109511 100644
+--- a/drivers/media/video/stradis.c
++++ b/drivers/media/video/stradis.c
+@@ -58,7 +58,7 @@
+ 
+ static struct saa7146 saa7146s[SAA7146_MAX];
+ 
+-static int saa_num = 0;		/* number of SAA7146s in use */
++static int saa_num;		/* number of SAA7146s in use */
+ 
+ static int video_nr = -1;
+ module_param(video_nr, int, 0);
+@@ -248,7 +248,7 @@ static void I2CBusScan(struct saa7146 *saa)
+ 			attach_inform(saa, i);
+ }
+ 
+-static int debiwait_maxwait = 0;
++static int debiwait_maxwait;
+ 
+ static int wait_for_debi_done(struct saa7146 *saa)
+ {
+@@ -1906,7 +1906,9 @@ static const struct file_operations saa_fops = {
+ 	.open = saa_open,
+ 	.release = saa_release,
+ 	.ioctl = saa_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.read = saa_read,
+ 	.llseek = no_llseek,
+ 	.write = saa_write,
+diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
+index afc32aa..d7f130b 100644
+--- a/drivers/media/video/stv680.c
++++ b/drivers/media/video/stv680.c
+@@ -72,15 +72,18 @@
+ #include "stv680.h"
+ 
+ static int video_nr = -1;
+-static int swapRGB = 0;   /* default for auto sleect */
+-static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */
+ 
+-static unsigned int debug = 0;
++static int swapRGB;	/* 0 = default for auto select */
++
++/* 0 = default to allow auto select; -1 = swap never, +1 = swap always */
++static int swapRGB_on;
++
++static unsigned int debug;
+ 
+ #define PDEBUG(level, fmt, args...) \
+ 	do { \
+ 	if (debug >= level)	\
+-		info("[%s:%d] " fmt, __FUNCTION__, __LINE__ , ## args);	\
++		info("[%s:%d] " fmt, __func__, __LINE__ , ## args);	\
+ 	} while (0)
+ 
+ 
+@@ -1391,7 +1394,9 @@ static const struct file_operations stv680_fops = {
+ 	.read =		stv680_read,
+ 	.mmap =		stv680_mmap,
+ 	.ioctl =        stv680_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.llseek =       no_llseek,
+ };
+ static struct video_device stv680_template = {
+diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c
+index fb895f6..6943b44 100644
+--- a/drivers/media/video/tcm825x.c
++++ b/drivers/media/video/tcm825x.c
+@@ -906,7 +906,7 @@ static int __init tcm825x_init(void)
+ 	rval = i2c_add_driver(&tcm825x_i2c_driver);
+ 	if (rval)
+ 		printk(KERN_INFO "%s: failed registering " TCM825X_NAME "\n",
+-		       __FUNCTION__);
++		       __func__);
+ 
+ 	return rval;
+ }
+diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
+index 55bc89a..0ebb5b5 100644
+--- a/drivers/media/video/tda8290.c
++++ b/drivers/media/video/tda8290.c
+@@ -32,8 +32,6 @@ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+ 
+-#define PREFIX "tda8290"
+-
+ /* ---------------------------------------------------------------------- */
+ 
+ struct tda8290_priv {
+@@ -174,7 +172,7 @@ static void tda8290_set_params(struct dvb_frontend *fe,
+ 	set_audio(fe, params);
+ 
+ 	if (priv->cfg.config)
+-		tuner_dbg("tda827xa config is 0x%02x\n", *priv->cfg.config);
++		tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);
+ 	tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
+ 	tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
+ 	tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
+@@ -365,7 +363,7 @@ static void tda8295_set_params(struct dvb_frontend *fe,
+ 
+ 	set_audio(fe, params);
+ 
+-	tuner_dbg("%s: freq = %d\n", __FUNCTION__, params->frequency);
++	tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
+ 
+ 	tda8295_power(fe, 1);
+ 	tda8295_agc1_out(fe, 1);
+@@ -444,8 +442,7 @@ static void tda8290_init_if(struct dvb_frontend *fe)
+ 	unsigned char set_GP00_CF[] = { 0x20, 0x01 };
+ 	unsigned char set_GP01_CF[] = { 0x20, 0x0B };
+ 
+-	if ((priv->cfg.config) &&
+-	    ((*priv->cfg.config == 1) || (*priv->cfg.config == 2)))
++	if ((priv->cfg.config == 1) || (priv->cfg.config == 2))
+ 		tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
+ 	else
+ 		tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
+@@ -590,8 +587,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
+ 		else
+ 			priv->ver |= TDA8275A;
+ 
+-		tda827x_attach(fe, priv->tda827x_addr,
+-			       priv->i2c_props.adap, &priv->cfg);
++		tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg);
++		priv->cfg.switch_addr = priv->i2c_props.addr;
+ 	}
+ 	if (fe->ops.tuner_ops.init)
+ 		fe->ops.tuner_ops.init(fe);
+@@ -616,7 +613,7 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props)
+ 	if (tda8290_id[1] == TDA8290_ID) {
+ 		if (debug)
+ 			printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
+-			       __FUNCTION__, i2c_adapter_id(i2c_props->adap),
++			       __func__, i2c_adapter_id(i2c_props->adap),
+ 			       i2c_props->addr);
+ 		return 0;
+ 	}
+@@ -636,7 +633,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props)
+ 	if (tda8295_id[1] == TDA8295_ID) {
+ 		if (debug)
+ 			printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n",
+-			       __FUNCTION__, i2c_adapter_id(i2c_props->adap),
++			       __func__, i2c_adapter_id(i2c_props->adap),
+ 			       i2c_props->addr);
+ 		return 0;
+ 	}
+@@ -674,6 +671,7 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
+ 
+ 	priv->i2c_props.addr     = i2c_addr;
+ 	priv->i2c_props.adap     = i2c_adap;
++	priv->i2c_props.name     = "tda829x";
+ 	if (cfg) {
+ 		priv->cfg.config         = cfg->lna_cfg;
+ 		priv->cfg.tuner_callback = cfg->tuner_callback;
+diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h
+index dc8ef31..d3bbf27 100644
+--- a/drivers/media/video/tda8290.h
++++ b/drivers/media/video/tda8290.h
+@@ -21,7 +21,7 @@
+ #include "dvb_frontend.h"
+ 
+ struct tda829x_config {
+-	unsigned int *lna_cfg;
++	unsigned int lna_cfg;
+ 	int (*tuner_callback) (void *dev, int command, int arg);
+ 
+ 	unsigned int probe_tuner:1;
+@@ -39,7 +39,7 @@ extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
+ #else
+ static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return -EINVAL;
+ }
+ 
+@@ -49,7 +49,7 @@ static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
+ 						  struct tda829x_config *cfg)
+ {
+ 	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+-	       __FUNCTION__);
++	       __func__);
+ 	return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
+index bdca5d2..0cee002 100644
+--- a/drivers/media/video/tda9840.c
++++ b/drivers/media/video/tda9840.c
+@@ -31,11 +31,11 @@
+ 
+ #include "tda9840.h"
+ 
+-static int debug = 0;		/* insmod parameter */
++static int debug;		/* insmod parameter */
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+ #define dprintk(args...) \
+-	    do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
++	    do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+ 
+ #define	SWITCH		0x00
+ #define	LEVEL_ADJUST	0x02
+diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
+index 106c93b..a0545ba 100644
+--- a/drivers/media/video/tda9887.c
++++ b/drivers/media/video/tda9887.c
+@@ -25,10 +25,12 @@ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+ 
+-#define PREFIX "tda9887"
++static DEFINE_MUTEX(tda9887_list_mutex);
++static LIST_HEAD(hybrid_tuner_instance_list);
+ 
+ struct tda9887_priv {
+ 	struct tuner_i2c_props i2c_props;
++	struct list_head hybrid_tuner_instance_list;
+ 
+ 	unsigned char 	   data[4];
+ 	unsigned int       config;
+@@ -644,7 +646,15 @@ static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
+ 
+ static void tda9887_release(struct dvb_frontend *fe)
+ {
+-	kfree(fe->analog_demod_priv);
++	struct tda9887_priv *priv = fe->analog_demod_priv;
++
++	mutex_lock(&tda9887_list_mutex);
++
++	if (priv)
++		hybrid_tuner_release_state(priv);
++
++	mutex_unlock(&tda9887_list_mutex);
++
+ 	fe->analog_demod_priv = NULL;
+ }
+ 
+@@ -665,17 +675,29 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
+ 				    u8 i2c_addr)
+ {
+ 	struct tda9887_priv *priv = NULL;
++	int instance;
+ 
+-	priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL);
+-	if (priv == NULL)
+-		return NULL;
+-	fe->analog_demod_priv = priv;
++	mutex_lock(&tda9887_list_mutex);
+ 
+-	priv->i2c_props.addr = i2c_addr;
+-	priv->i2c_props.adap = i2c_adap;
+-	priv->mode = T_STANDBY;
++	instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
++					      hybrid_tuner_instance_list,
++					      i2c_adap, i2c_addr, "tda9887");
++	switch (instance) {
++	case 0:
++		mutex_unlock(&tda9887_list_mutex);
++		return NULL;
++		break;
++	case 1:
++		fe->analog_demod_priv = priv;
++		priv->mode = T_STANDBY;
++		tuner_info("tda988[5/6/7] found\n");
++		break;
++	default:
++		fe->analog_demod_priv = priv;
++		break;
++	}
+ 
+-	tuner_info("tda988[5/6/7] found\n");
++	mutex_unlock(&tda9887_list_mutex);
+ 
+ 	memcpy(&fe->ops.analog_ops, &tda9887_ops,
+ 	       sizeof(struct analog_demod_ops));
+diff --git a/drivers/media/video/tda9887.h b/drivers/media/video/tda9887.h
+index 8f873a8..be49dcb 100644
+--- a/drivers/media/video/tda9887.h
++++ b/drivers/media/video/tda9887.h
+@@ -30,7 +30,7 @@ static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
+ 						  struct i2c_adapter *i2c_adap,
+ 						  u8 i2c_addr)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c
+index 5326eec..b93cdef 100644
+--- a/drivers/media/video/tea5761.c
++++ b/drivers/media/video/tea5761.c
+@@ -14,12 +14,10 @@
+ #include "tuner-i2c.h"
+ #include "tea5761.h"
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+ 
+-#define PREFIX "tea5761"
+-
+ struct tea5761_priv {
+ 	struct tuner_i2c_props i2c_props;
+ 
+@@ -131,7 +129,7 @@ static void tea5761_status_dump(unsigned char *buffer)
+ 
+ 	frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4;	/* Freq in KHz */
+ 
+-	printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
++	printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n",
+ 	       frq / 1000, frq % 1000, div);
+ }
+ 
+@@ -249,14 +247,19 @@ int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
+ 
+ 	if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) {
+ 		printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc);
+-		return EINVAL;
++		return -EINVAL;
+ 	}
+ 
+-	if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) {
+-		printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]);
+-		return EINVAL;
++	if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) {
++		printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x."
++				    " It is not a TEA5761\n",
++				    buffer[13], buffer[14], buffer[15]);
++		return -EINVAL;
+ 	}
+-	printk(KERN_WARNING "TEA5761 detected.\n");
++	printk(KERN_WARNING "tea5761: TEA%02x%02x detected. "
++			    "Manufacturer ID= 0x%02x\n",
++			    buffer[14], buffer[15], buffer[13]);
++
+ 	return 0;
+ }
+ 
+@@ -302,6 +305,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
+ 
+ 	priv->i2c_props.addr = i2c_addr;
+ 	priv->i2c_props.adap = i2c_adap;
++	priv->i2c_props.name = "tea5761";
+ 
+ 	memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops,
+ 	       sizeof(struct dvb_tuner_ops));
+diff --git a/drivers/media/video/tea5761.h b/drivers/media/video/tea5761.h
+index 73a03b4..8eb6272 100644
+--- a/drivers/media/video/tea5761.h
++++ b/drivers/media/video/tea5761.h
+@@ -31,7 +31,7 @@ static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap,
+ 					u8 i2c_addr)
+ {
+ 	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+-	       __FUNCTION__);
++	       __func__);
+ 	return -EINVAL;
+ }
+ 
+@@ -39,7 +39,7 @@ static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
+ 						   struct i2c_adapter* i2c_adap,
+ 						   u8 i2c_addr)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
+index e1b48d8..f6e7d7a 100644
+--- a/drivers/media/video/tea5767.c
++++ b/drivers/media/video/tea5767.c
+@@ -16,12 +16,10 @@
+ #include "tuner-i2c.h"
+ #include "tea5767.h"
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+ 
+-#define PREFIX "tea5767"
+-
+ /*****************************************************************************/
+ 
+ struct tea5767_priv {
+@@ -137,14 +135,14 @@ static void tea5767_status_dump(struct tea5767_priv *priv,
+ 	unsigned int div, frq;
+ 
+ 	if (TEA5767_READY_FLAG_MASK & buffer[0])
+-		printk(PREFIX "Ready Flag ON\n");
++		tuner_info("Ready Flag ON\n");
+ 	else
+-		printk(PREFIX "Ready Flag OFF\n");
++		tuner_info("Ready Flag OFF\n");
+ 
+ 	if (TEA5767_BAND_LIMIT_MASK & buffer[0])
+-		printk(PREFIX "Tuner at band limit\n");
++		tuner_info("Tuner at band limit\n");
+ 	else
+-		printk(PREFIX "Tuner not at band limit\n");
++		tuner_info("Tuner not at band limit\n");
+ 
+ 	div = ((buffer[0] & 0x3f) << 8) | buffer[1];
+ 
+@@ -166,23 +164,23 @@ static void tea5767_status_dump(struct tea5767_priv *priv,
+ 	buffer[0] = (div >> 8) & 0x3f;
+ 	buffer[1] = div & 0xff;
+ 
+-	printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
+-	       frq / 1000, frq % 1000, div);
++	tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n",
++		   frq / 1000, frq % 1000, div);
+ 
+ 	if (TEA5767_STEREO_MASK & buffer[2])
+-		printk(PREFIX "Stereo\n");
++		tuner_info("Stereo\n");
+ 	else
+-		printk(PREFIX "Mono\n");
++		tuner_info("Mono\n");
+ 
+-	printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
++	tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
+ 
+-	printk(PREFIX "ADC Level = %d\n",
+-	       (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
++	tuner_info("ADC Level = %d\n",
++		   (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
+ 
+-	printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
++	tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
+ 
+-	printk(PREFIX "Reserved = 0x%02x\n",
+-	       (buffer[4] & TEA5767_RESERVED_MASK));
++	tuner_info("Reserved = 0x%02x\n",
++		   (buffer[4] & TEA5767_RESERVED_MASK));
+ }
+ 
+ /* Freq should be specifyed at 62.5 Hz */
+@@ -395,11 +393,6 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
+ 		return EINVAL;
+ 	}
+ 
+-	/* It seems that tea5767 returns 0xff after the 5th byte */
+-	if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
+-		printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n");
+-		return EINVAL;
+-	}
+ 
+ 	return 0;
+ }
+@@ -456,6 +449,8 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
+ 
+ 	priv->i2c_props.addr  = i2c_addr;
+ 	priv->i2c_props.adap  = i2c_adap;
++	priv->i2c_props.name  = "tea5767";
++
+ 	priv->ctrl.xtal_freq  = TEA5767_HIGH_LO_32768;
+ 	priv->ctrl.port1      = 1;
+ 	priv->ctrl.port2      = 1;
+diff --git a/drivers/media/video/tea5767.h b/drivers/media/video/tea5767.h
+index a44451f..7b547c0 100644
+--- a/drivers/media/video/tea5767.h
++++ b/drivers/media/video/tea5767.h
+@@ -50,7 +50,7 @@ static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap,
+ 					u8 i2c_addr)
+ {
+ 	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+-	       __FUNCTION__);
++	       __func__);
+ 	return -EINVAL;
+ }
+ 
+@@ -58,7 +58,7 @@ static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
+ 						   struct i2c_adapter* i2c_adap,
+ 						   u8 i2c_addr)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
+index df2fad9..9513d86 100644
+--- a/drivers/media/video/tea6415c.c
++++ b/drivers/media/video/tea6415c.c
+@@ -33,11 +33,11 @@
+ 
+ #include "tea6415c.h"
+ 
+-static int debug = 0;		/* insmod parameter */
++static int debug;		/* insmod parameter */
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+ #define dprintk(args...) \
+-	    do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
++	    do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+ 
+ #define TEA6415C_NUM_INPUTS	8
+ #define TEA6415C_NUM_OUTPUTS	6
+diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
+index 4ff6c63..7fd5336 100644
+--- a/drivers/media/video/tea6420.c
++++ b/drivers/media/video/tea6420.c
+@@ -33,11 +33,11 @@
+ 
+ #include "tea6420.h"
+ 
+-static int debug = 0;		/* insmod parameter */
++static int debug;		/* insmod parameter */
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+ #define dprintk(args...) \
+-	    do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
++	    do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+ 
+ /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
+ static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END };
+diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
+index 78a09a2..2b72e10 100644
+--- a/drivers/media/video/tuner-core.c
++++ b/drivers/media/video/tuner-core.c
+@@ -68,9 +68,9 @@ static unsigned short normal_i2c[] = {
+ I2C_CLIENT_INSMOD;
+ 
+ /* insmod options used at init time => read/only */
+-static unsigned int addr = 0;
+-static unsigned int no_autodetect = 0;
+-static unsigned int show_i2c = 0;
++static unsigned int addr;
++static unsigned int no_autodetect;
++static unsigned int show_i2c;
+ 
+ /* insmod options used at runtime => read/write */
+ static int tuner_debug;
+@@ -313,24 +313,14 @@ static void tuner_i2c_address_check(struct tuner *t)
+ 	tuner_warn("output to v4l-dvb-maintainer at linuxtv.org\n");
+ 	tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
+ 	tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
+-		   t->i2c->adapter->name, t->i2c->addr, t->type,
+-		   tuners[t->type].name);
++		   t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name);
+ 	tuner_warn("====================== WARNING! ======================\n");
+ }
+ 
+-static void attach_simple_tuner(struct tuner *t)
+-{
+-	struct simple_tuner_config cfg = {
+-		.type = t->type,
+-		.tun  = &tuners[t->type]
+-	};
+-	simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
+-}
+-
+ static void attach_tda829x(struct tuner *t)
+ {
+ 	struct tda829x_config cfg = {
+-		.lna_cfg        = &t->config,
++		.lna_cfg        = t->config,
+ 		.tuner_callback = t->tuner_callback,
+ 	};
+ 	tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
+@@ -352,11 +342,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ 		return;
+ 	}
+ 
+-	if (type >= tuner_count) {
+-		tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count);
+-		return;
+-	}
+-
+ 	t->type = type;
+ 	t->config = new_config;
+ 	if (tuner_callback != NULL) {
+@@ -384,19 +369,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ 		break;
+ 	}
+ 	case TUNER_TEA5767:
+-		if (tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) {
+-			t->type = TUNER_ABSENT;
+-			t->mode_mask = T_UNINITIALIZED;
+-			return;
+-		}
++		if (!tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
++			goto attach_failed;
+ 		t->mode_mask = T_RADIO;
+ 		break;
+ 	case TUNER_TEA5761:
+-		if (tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) {
+-			t->type = TUNER_ABSENT;
+-			t->mode_mask = T_UNINITIALIZED;
+-			return;
+-		}
++		if (!tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
++			goto attach_failed;
+ 		t->mode_mask = T_RADIO;
+ 		break;
+ 	case TUNER_PHILIPS_FMD1216ME_MK3:
+@@ -409,7 +388,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ 		buffer[2] = 0x86;
+ 		buffer[3] = 0x54;
+ 		i2c_master_send(c, buffer, 4);
+-		attach_simple_tuner(t);
++		if (!simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
++					t->type))
++			goto attach_failed;
+ 		break;
+ 	case TUNER_PHILIPS_TD1316:
+ 		buffer[0] = 0x0b;
+@@ -417,45 +398,45 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ 		buffer[2] = 0x86;
+ 		buffer[3] = 0xa4;
+ 		i2c_master_send(c,buffer,4);
+-		attach_simple_tuner(t);
++		if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
++					t->i2c->addr, t->type))
++			goto attach_failed;
+ 		break;
+ 	case TUNER_XC2028:
+ 	{
+ 		struct xc2028_config cfg = {
+ 			.i2c_adap  = t->i2c->adapter,
+ 			.i2c_addr  = t->i2c->addr,
+-			.video_dev = c->adapter->algo_data,
+ 			.callback  = t->tuner_callback,
+ 		};
+-		if (!xc2028_attach(&t->fe, &cfg)) {
+-			t->type = TUNER_ABSENT;
+-			t->mode_mask = T_UNINITIALIZED;
+-			return;
+-		}
++		if (!xc2028_attach(&t->fe, &cfg))
++			goto attach_failed;
+ 		break;
+ 	}
+ 	case TUNER_TDA9887:
+ 		tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
+ 		break;
+ 	case TUNER_XC5000:
++	{
++		struct dvb_tuner_ops *xc_tuner_ops;
++
+ 		xc5000_cfg.i2c_address	  = t->i2c->addr;
+ 		xc5000_cfg.if_khz	  = 5380;
+ 		xc5000_cfg.priv           = c->adapter->algo_data;
+ 		xc5000_cfg.tuner_callback = t->tuner_callback;
+-		if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg)) {
+-			t->type = TUNER_ABSENT;
+-			t->mode_mask = T_UNINITIALIZED;
+-			return;
+-		}
+-		{
+-		struct dvb_tuner_ops *xc_tuner_ops;
++		if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg))
++			goto attach_failed;
++
+ 		xc_tuner_ops = &t->fe.ops.tuner_ops;
+-		if(xc_tuner_ops->init != NULL)
++		if (xc_tuner_ops->init)
+ 			xc_tuner_ops->init(&t->fe);
+-		}
+ 		break;
++	}
+ 	default:
+-		attach_simple_tuner(t);
++		if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
++					t->i2c->addr, t->type))
++			goto attach_failed;
++
+ 		break;
+ 	}
+ 
+@@ -477,11 +458,27 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ 	if (t->mode_mask == T_UNINITIALIZED)
+ 		t->mode_mask = new_mode_mask;
+ 
+-	set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
++	/* xc2028/3028 and xc5000 requires a firmware to be set-up later
++	   trying to set a frequency here will just fail
++	   FIXME: better to move set_freq to the tuner code. This is needed
++	   on analog tuners for PLL to properly work
++	 */
++	if (t->type != TUNER_XC2028 && t->type != TUNER_XC5000)
++		set_freq(c, (V4L2_TUNER_RADIO == t->mode) ?
++			    t->radio_freq : t->tv_freq);
++
+ 	tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
+ 		  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
+ 		  t->mode_mask);
+ 	tuner_i2c_address_check(t);
++	return;
++
++attach_failed:
++	tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
++	t->type = TUNER_ABSENT;
++	t->mode_mask = T_UNINITIALIZED;
++
++	return;
+ }
+ 
+ /*
+@@ -496,14 +493,16 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
+ {
+ 	struct tuner *t = i2c_get_clientdata(c);
+ 
+-	tuner_dbg("set addr for type %i\n", t->type);
+-
+ 	if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
+ 		(t->mode_mask & tun_setup->mode_mask))) ||
+ 		(tun_setup->addr == c->addr)) {
+ 			set_type(c, tun_setup->type, tun_setup->mode_mask,
+ 				 tun_setup->config, tun_setup->tuner_callback);
+-	}
++	} else
++		tuner_dbg("set addr discarded for type %i, mask %x. "
++			  "Asked to change tuner at addr 0x%02x, with mask %x\n",
++			  t->type, t->mode_mask,
++			  tun_setup->addr, tun_setup->mode_mask);
+ }
+ 
+ static inline int check_mode(struct tuner *t, char *cmd)
+@@ -759,7 +758,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
+ 		if (analog_ops->standby)
+ 			analog_ops->standby(&t->fe);
+ 		break;
+-#ifdef CONFIG_VIDEO_V4L1
++#ifdef CONFIG_VIDEO_ALLOW_V4L1
+ 	case VIDIOCSAUDIO:
+ 		if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
+ 			return 0;
+@@ -1112,8 +1111,8 @@ static int tuner_probe(struct i2c_client *client)
+ 	if (!no_autodetect) {
+ 		switch (client->addr) {
+ 		case 0x10:
+-			if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr)
+-					!= EINVAL) {
++			if (tea5761_autodetection(t->i2c->adapter,
++						  t->i2c->addr) >= 0) {
+ 				t->type = TUNER_TEA5761;
+ 				t->mode_mask = T_RADIO;
+ 				t->mode = T_STANDBY;
+@@ -1125,7 +1124,7 @@ static int tuner_probe(struct i2c_client *client)
+ 
+ 				goto register_client;
+ 			}
+-			break;
++			return -ENODEV;
+ 		case 0x42:
+ 		case 0x43:
+ 		case 0x4a:
+diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h
+index de52e8f..3ad6c8e 100644
+--- a/drivers/media/video/tuner-i2c.h
++++ b/drivers/media/video/tuner-i2c.h
+@@ -26,6 +26,10 @@
+ struct tuner_i2c_props {
+ 	u8 addr;
+ 	struct i2c_adapter *adap;
++
++	/* used for tuner instance management */
++	int count;
++	char *name;
+ };
+ 
+ static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len)
+@@ -59,29 +63,111 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
+ 	return (ret == 2) ? ilen : ret;
+ }
+ 
+-#define tuner_warn(fmt, arg...) do {					\
+-	printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX,			\
+-			i2c_adapter_id(priv->i2c_props.adap),		\
+-			priv->i2c_props.addr, ##arg);			\
++/* Callers must declare as a global for the module:
++ *
++ * static LIST_HEAD(hybrid_tuner_instance_list);
++ *
++ * hybrid_tuner_instance_list should be the third argument
++ * passed into hybrid_tuner_request_state().
++ *
++ * state structure must contain the following:
++ *
++ * 	struct list_head	hybrid_tuner_instance_list;
++ *	struct tuner_i2c_props	i2c_props;
++ *
++ * hybrid_tuner_instance_list (both within state structure and globally)
++ * is only required if the driver is using hybrid_tuner_request_state
++ * and hybrid_tuner_release_state to manage state sharing between
++ * multiple instances of hybrid tuners.
++ */
++
++#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do {		\
++	printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name,		\
++			i2cprops.adap ?					\
++				i2c_adapter_id(i2cprops.adap) : -1,	\
++			i2cprops.addr, ##arg);				\
+ 	 } while (0)
+ 
+-#define tuner_info(fmt, arg...) do {					\
+-	printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX,			\
+-			i2c_adapter_id(priv->i2c_props.adap),		\
+-			priv->i2c_props.addr , ##arg);			\
++/* TO DO: convert all callers of these macros to pass in
++ * struct tuner_i2c_props, then remove the macro wrappers */
++
++#define __tuner_warn(i2cprops, fmt, arg...) do {			\
++	tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg);		\
+ 	} while (0)
+ 
+-#define tuner_err(fmt, arg...) do {					\
+-	printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, 			\
+-			i2c_adapter_id(priv->i2c_props.adap),		\
+-			priv->i2c_props.addr , ##arg);			\
++#define __tuner_info(i2cprops, fmt, arg...) do {			\
++	tuner_printk(KERN_INFO, i2cprops, fmt, ##arg);			\
+ 	} while (0)
+ 
+-#define tuner_dbg(fmt, arg...) do {					\
++#define __tuner_err(i2cprops, fmt, arg...) do {				\
++	tuner_printk(KERN_ERR, i2cprops, fmt, ##arg);			\
++	} while (0)
++
++#define __tuner_dbg(i2cprops, fmt, arg...) do {				\
+ 	if ((debug))							\
+-		printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX,		\
+-			i2c_adapter_id(priv->i2c_props.adap),		\
+-			priv->i2c_props.addr , ##arg);			\
++		tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg);		\
+ 	} while (0)
+ 
++#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg)
++#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg)
++#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg)
++#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg)
++
++/****************************************************************************/
++
++/* The return value of hybrid_tuner_request_state indicates the number of
++ * instances using this tuner object.
++ *
++ * 0 - no instances, indicates an error - kzalloc must have failed
++ *
++ * 1 - one instance, indicates that the tuner object was created successfully
++ *
++ * 2 (or more) instances, indicates that an existing tuner object was found
++ */
++
++#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\
++({									\
++	int __ret = 0;							\
++	list_for_each_entry(state, &list, hybrid_tuner_instance_list) {	\
++		if (((i2cadap) && (state->i2c_props.adap)) &&		\
++		    ((i2c_adapter_id(state->i2c_props.adap) ==		\
++		      i2c_adapter_id(i2cadap)) &&			\
++		     (i2caddr == state->i2c_props.addr))) {		\
++			__tuner_info(state->i2c_props,			\
++				     "attaching existing instance\n");	\
++			state->i2c_props.count++;			\
++			__ret = state->i2c_props.count;			\
++			break;						\
++		}							\
++	}								\
++	if (0 == __ret) {						\
++		state = kzalloc(sizeof(type), GFP_KERNEL);		\
++		if (NULL == state)					\
++			goto __fail;					\
++		state->i2c_props.addr = i2caddr;			\
++		state->i2c_props.adap = i2cadap;			\
++		state->i2c_props.name = devname;			\
++		__tuner_info(state->i2c_props,				\
++			     "creating new instance\n");		\
++		list_add_tail(&state->hybrid_tuner_instance_list, &list);\
++		state->i2c_props.count++;				\
++		__ret = state->i2c_props.count;				\
++	}								\
++__fail:									\
++	__ret;								\
++})
++
++#define hybrid_tuner_release_state(state)				\
++({									\
++	int __ret;							\
++	state->i2c_props.count--;					\
++	__ret = state->i2c_props.count;					\
++	if (!state->i2c_props.count) {					\
++		__tuner_info(state->i2c_props, "destroying instance\n");\
++		list_del(&state->hybrid_tuner_instance_list);		\
++		kfree(state);						\
++	}								\
++	__ret;								\
++})
++
+ #endif /* __TUNER_I2C_H__ */
+diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
+index c1db576..be8d903 100644
+--- a/drivers/media/video/tuner-simple.c
++++ b/drivers/media/video/tuner-simple.c
+@@ -13,15 +13,25 @@
+ #include "tuner-i2c.h"
+ #include "tuner-simple.h"
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+ 
+-#define PREFIX "tuner-simple"
++#define TUNER_SIMPLE_MAX 64
++static unsigned int simple_devcount;
+ 
+-static int offset = 0;
++static int offset;
+ module_param(offset, int, 0664);
+-MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
++MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
++
++static unsigned int atv_input[TUNER_SIMPLE_MAX] = \
++			{ [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
++static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \
++			{ [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
++module_param_array(atv_input, int, NULL, 0644);
++module_param_array(dtv_input, int, NULL, 0644);
++MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect");
++MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect");
+ 
+ /* ---------------------------------------------------------------------- */
+ 
+@@ -36,8 +46,8 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
+  */
+ #define TEMIC_SET_PAL_I         0x05
+ #define TEMIC_SET_PAL_DK        0x09
+-#define TEMIC_SET_PAL_L         0x0a // SECAM ?
+-#define TEMIC_SET_PAL_L2        0x0b // change IF !
++#define TEMIC_SET_PAL_L         0x0a /* SECAM ? */
++#define TEMIC_SET_PAL_L2        0x0b /* change IF ! */
+ #define TEMIC_SET_PAL_BG        0x0c
+ 
+ /* tv tuner system standard selection for Philips FQ1216ME
+@@ -90,14 +100,21 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
+ #define TUNER_PLL_LOCKED   0x40
+ #define TUNER_STEREO_MK3   0x04
+ 
++static DEFINE_MUTEX(tuner_simple_list_mutex);
++static LIST_HEAD(hybrid_tuner_instance_list);
++
+ struct tuner_simple_priv {
++	unsigned int nr;
+ 	u16 last_div;
++
+ 	struct tuner_i2c_props i2c_props;
++	struct list_head hybrid_tuner_instance_list;
+ 
+ 	unsigned int type;
+ 	struct tunertype *tun;
+ 
+ 	u32 frequency;
++	u32 bandwidth;
+ };
+ 
+ /* ---------------------------------------------------------------------- */
+@@ -107,7 +124,7 @@ static int tuner_read_status(struct dvb_frontend *fe)
+ 	struct tuner_simple_priv *priv = fe->tuner_priv;
+ 	unsigned char byte;
+ 
+-	if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1))
++	if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1))
+ 		return 0;
+ 
+ 	return byte;
+@@ -121,13 +138,13 @@ static inline int tuner_signal(const int status)
+ static inline int tuner_stereo(const int type, const int status)
+ {
+ 	switch (type) {
+-		case TUNER_PHILIPS_FM1216ME_MK3:
+-		case TUNER_PHILIPS_FM1236_MK3:
+-		case TUNER_PHILIPS_FM1256_IH3:
+-		case TUNER_LG_NTSC_TAPE:
+-			return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
+-		default:
+-			return status & TUNER_STEREO;
++	case TUNER_PHILIPS_FM1216ME_MK3:
++	case TUNER_PHILIPS_FM1236_MK3:
++	case TUNER_PHILIPS_FM1256_IH3:
++	case TUNER_LG_NTSC_TAPE:
++		return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
++	default:
++		return status & TUNER_STEREO;
+ 	}
+ }
+ 
+@@ -145,7 +162,12 @@ static inline int tuner_afcstatus(const int status)
+ static int simple_get_status(struct dvb_frontend *fe, u32 *status)
+ {
+ 	struct tuner_simple_priv *priv = fe->tuner_priv;
+-	int tuner_status = tuner_read_status(fe);
++	int tuner_status;
++
++	if (priv->i2c_props.adap == NULL)
++		return -EINVAL;
++
++	tuner_status = tuner_read_status(fe);
+ 
+ 	*status = 0;
+ 
+@@ -162,7 +184,12 @@ static int simple_get_status(struct dvb_frontend *fe, u32 *status)
+ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+ {
+ 	struct tuner_simple_priv *priv = fe->tuner_priv;
+-	int signal = tuner_signal(tuner_read_status(fe));
++	int signal;
++
++	if (priv->i2c_props.adap == NULL)
++		return -EINVAL;
++
++	signal = tuner_signal(tuner_read_status(fe));
+ 
+ 	*strength = signal;
+ 
+@@ -173,174 +200,378 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+ 
+ /* ---------------------------------------------------------------------- */
+ 
+-static int simple_set_tv_freq(struct dvb_frontend *fe,
+-			      struct analog_parameters *params)
++static inline char *tuner_param_name(enum param_type type)
+ {
+-	struct tuner_simple_priv *priv = fe->tuner_priv;
+-	u8 config, cb, tuneraddr;
+-	u16 div;
+-	struct tunertype *tun;
+-	u8 buffer[4];
+-	int rc, IFPCoff, i, j;
+-	enum param_type desired_type;
+-	struct tuner_params *t_params;
++	char *name;
+ 
+-	tun = priv->tun;
++	switch (type) {
++	case TUNER_PARAM_TYPE_RADIO:
++		name = "radio";
++		break;
++	case TUNER_PARAM_TYPE_PAL:
++		name = "pal";
++		break;
++	case TUNER_PARAM_TYPE_SECAM:
++		name = "secam";
++		break;
++	case TUNER_PARAM_TYPE_NTSC:
++		name = "ntsc";
++		break;
++	case TUNER_PARAM_TYPE_DIGITAL:
++		name = "digital";
++		break;
++	default:
++		name = "unknown";
++		break;
++	}
++	return name;
++}
+ 
+-	/* IFPCoff = Video Intermediate Frequency - Vif:
+-		940  =16*58.75  NTSC/J (Japan)
+-		732  =16*45.75  M/N STD
+-		704  =16*44     ATSC (at DVB code)
+-		632  =16*39.50  I U.K.
+-		622.4=16*38.90  B/G D/K I, L STD
+-		592  =16*37.00  D China
+-		590  =16.36.875 B Australia
+-		543.2=16*33.95  L' STD
+-		171.2=16*10.70  FM Radio (at set_radio_freq)
+-	*/
++static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
++						enum param_type desired_type)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++	struct tunertype *tun = priv->tun;
++	int i;
+ 
+-	if (params->std == V4L2_STD_NTSC_M_JP) {
+-		IFPCoff      = 940;
+-		desired_type = TUNER_PARAM_TYPE_NTSC;
+-	} else if ((params->std & V4L2_STD_MN) &&
+-		  !(params->std & ~V4L2_STD_MN)) {
+-		IFPCoff      = 732;
+-		desired_type = TUNER_PARAM_TYPE_NTSC;
+-	} else if (params->std == V4L2_STD_SECAM_LC) {
+-		IFPCoff      = 543;
+-		desired_type = TUNER_PARAM_TYPE_SECAM;
+-	} else {
+-		IFPCoff      = 623;
+-		desired_type = TUNER_PARAM_TYPE_PAL;
+-	}
++	for (i = 0; i < tun->count; i++)
++		if (desired_type == tun->params[i].type)
++			break;
+ 
+-	for (j = 0; j < tun->count-1; j++) {
+-		if (desired_type != tun->params[j].type)
+-			continue;
+-		break;
+-	}
+-	/* use default tuner_t_params if desired_type not available */
+-	if (desired_type != tun->params[j].type) {
+-		tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n",
+-			  IFPCoff, priv->type);
+-		j = 0;
++	/* use default tuner params if desired_type not available */
++	if (i == tun->count) {
++		tuner_dbg("desired params (%s) undefined for tuner %d\n",
++			  tuner_param_name(desired_type), priv->type);
++		i = 0;
+ 	}
+-	t_params = &tun->params[j];
++
++	tuner_dbg("using tuner params #%d (%s)\n", i,
++		  tuner_param_name(tun->params[i].type));
++
++	return &tun->params[i];
++}
++
++static int simple_config_lookup(struct dvb_frontend *fe,
++				struct tuner_params *t_params,
++				int *frequency, u8 *config, u8 *cb)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++	int i;
+ 
+ 	for (i = 0; i < t_params->count; i++) {
+-		if (params->frequency > t_params->ranges[i].limit)
++		if (*frequency > t_params->ranges[i].limit)
+ 			continue;
+ 		break;
+ 	}
+ 	if (i == t_params->count) {
+-		tuner_dbg("TV frequency out of range (%d > %d)",
+-				params->frequency, t_params->ranges[i - 1].limit);
+-		params->frequency = t_params->ranges[--i].limit;
++		tuner_dbg("frequency out of range (%d > %d)\n",
++			  *frequency, t_params->ranges[i - 1].limit);
++		*frequency = t_params->ranges[--i].limit;
+ 	}
+-	config = t_params->ranges[i].config;
+-	cb     = t_params->ranges[i].cb;
+-	/*  i == 0 -> VHF_LO
+-	 *  i == 1 -> VHF_HI
+-	 *  i == 2 -> UHF     */
+-	tuner_dbg("tv: param %d, range %d\n",j,i);
++	*config = t_params->ranges[i].config;
++	*cb     = t_params->ranges[i].cb;
++
++	tuner_dbg("freq = %d.%02d (%d), range = %d, "
++		  "config = 0x%02x, cb = 0x%02x\n",
++		  *frequency / 16, *frequency % 16 * 100 / 16, *frequency,
++		  i, *config, *cb);
++
++	return i;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void simple_set_rf_input(struct dvb_frontend *fe,
++				u8 *config, u8 *cb, unsigned int rf)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
+ 
+-	div=params->frequency + IFPCoff + offset;
++	switch (priv->type) {
++	case TUNER_PHILIPS_TUV1236D:
++		switch (rf) {
++		case 1:
++			*cb |= 0x08;
++			break;
++		default:
++			*cb &= ~0x08;
++			break;
++		}
++		break;
++	case TUNER_PHILIPS_FCV1236D:
++		switch (rf) {
++		case 1:
++			*cb |= 0x01;
++			break;
++		default:
++			*cb &= ~0x01;
++			break;
++		}
++		break;
++	default:
++		break;
++	}
++}
+ 
+-	tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n",
+-					params->frequency / 16, params->frequency % 16 * 100 / 16,
+-					IFPCoff / 16, IFPCoff % 16 * 100 / 16,
+-					offset / 16, offset % 16 * 100 / 16,
+-					div);
++static int simple_std_setup(struct dvb_frontend *fe,
++			    struct analog_parameters *params,
++			    u8 *config, u8 *cb)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++	u8 tuneraddr;
++	int rc;
+ 
+ 	/* tv norm specific stuff for multi-norm tuners */
+ 	switch (priv->type) {
+-	case TUNER_PHILIPS_SECAM: // FI1216MF
++	case TUNER_PHILIPS_SECAM: /* FI1216MF */
+ 		/* 0x01 -> ??? no change ??? */
+ 		/* 0x02 -> PAL BDGHI / SECAM L */
+ 		/* 0x04 -> ??? PAL others / SECAM others ??? */
+-		cb &= ~0x03;
+-		if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM
+-			cb |= PHILIPS_MF_SET_STD_L;
++		*cb &= ~0x03;
++		if (params->std & V4L2_STD_SECAM_L)
++			/* also valid for V4L2_STD_SECAM */
++			*cb |= PHILIPS_MF_SET_STD_L;
+ 		else if (params->std & V4L2_STD_SECAM_LC)
+-			cb |= PHILIPS_MF_SET_STD_LC;
++			*cb |= PHILIPS_MF_SET_STD_LC;
+ 		else /* V4L2_STD_B|V4L2_STD_GH */
+-			cb |= PHILIPS_MF_SET_STD_BG;
++			*cb |= PHILIPS_MF_SET_STD_BG;
+ 		break;
+ 
+ 	case TUNER_TEMIC_4046FM5:
+-		cb &= ~0x0f;
++		*cb &= ~0x0f;
+ 
+ 		if (params->std & V4L2_STD_PAL_BG) {
+-			cb |= TEMIC_SET_PAL_BG;
++			*cb |= TEMIC_SET_PAL_BG;
+ 
+ 		} else if (params->std & V4L2_STD_PAL_I) {
+-			cb |= TEMIC_SET_PAL_I;
++			*cb |= TEMIC_SET_PAL_I;
+ 
+ 		} else if (params->std & V4L2_STD_PAL_DK) {
+-			cb |= TEMIC_SET_PAL_DK;
++			*cb |= TEMIC_SET_PAL_DK;
+ 
+ 		} else if (params->std & V4L2_STD_SECAM_L) {
+-			cb |= TEMIC_SET_PAL_L;
++			*cb |= TEMIC_SET_PAL_L;
+ 
+ 		}
+ 		break;
+ 
+ 	case TUNER_PHILIPS_FQ1216ME:
+-		cb &= ~0x0f;
++		*cb &= ~0x0f;
+ 
+ 		if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
+-			cb |= PHILIPS_SET_PAL_BGDK;
++			*cb |= PHILIPS_SET_PAL_BGDK;
+ 
+ 		} else if (params->std & V4L2_STD_PAL_I) {
+-			cb |= PHILIPS_SET_PAL_I;
++			*cb |= PHILIPS_SET_PAL_I;
+ 
+ 		} else if (params->std & V4L2_STD_SECAM_L) {
+-			cb |= PHILIPS_SET_PAL_L;
++			*cb |= PHILIPS_SET_PAL_L;
+ 
+ 		}
+ 		break;
+ 
+-	case TUNER_PHILIPS_ATSC:
++	case TUNER_PHILIPS_FCV1236D:
+ 		/* 0x00 -> ATSC antenna input 1 */
+ 		/* 0x01 -> ATSC antenna input 2 */
+ 		/* 0x02 -> NTSC antenna input 1 */
+ 		/* 0x03 -> NTSC antenna input 2 */
+-		cb &= ~0x03;
++		*cb &= ~0x03;
+ 		if (!(params->std & V4L2_STD_ATSC))
+-			cb |= 2;
+-		/* FIXME: input */
++			*cb |= 2;
+ 		break;
+ 
+ 	case TUNER_MICROTUNE_4042FI5:
+ 		/* Set the charge pump for fast tuning */
+-		config |= TUNER_CHARGE_PUMP;
++		*config |= TUNER_CHARGE_PUMP;
+ 		break;
+ 
+ 	case TUNER_PHILIPS_TUV1236D:
++	{
+ 		/* 0x40 -> ATSC antenna input 1 */
+ 		/* 0x48 -> ATSC antenna input 2 */
+ 		/* 0x00 -> NTSC antenna input 1 */
+ 		/* 0x08 -> NTSC antenna input 2 */
+-		buffer[0] = 0x14;
+-		buffer[1] = 0x00;
+-		buffer[2] = 0x17;
+-		buffer[3] = 0x00;
+-		cb &= ~0x40;
++		u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00};
++		*cb &= ~0x40;
+ 		if (params->std & V4L2_STD_ATSC) {
+-			cb |= 0x40;
++			*cb |= 0x40;
+ 			buffer[1] = 0x04;
+ 		}
+ 		/* set to the correct mode (analog or digital) */
+ 		tuneraddr = priv->i2c_props.addr;
+ 		priv->i2c_props.addr = 0x0a;
+-		if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2)))
+-			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
+-		if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2)))
+-			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
++		rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2);
++		if (2 != rc)
++			tuner_warn("i2c i/o error: rc == %d "
++				   "(should be 2)\n", rc);
++		rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2);
++		if (2 != rc)
++			tuner_warn("i2c i/o error: rc == %d "
++				   "(should be 2)\n", rc);
+ 		priv->i2c_props.addr = tuneraddr;
+-		/* FIXME: input */
+ 		break;
+ 	}
++	}
++	if (atv_input[priv->nr])
++		simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);
++
++	return 0;
++}
++
++static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
++			    u16 div, u8 config, u8 cb)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++	int rc;
++
++	switch (priv->type) {
++	case TUNER_LG_TDVS_H06XF:
++		/* Set the Auxiliary Byte. */
++		buffer[0] = buffer[2];
++		buffer[0] &= ~0x20;
++		buffer[0] |= 0x18;
++		buffer[1] = 0x20;
++		tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]);
++
++		rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
++		if (2 != rc)
++			tuner_warn("i2c i/o error: rc == %d "
++				   "(should be 2)\n", rc);
++		break;
++	case TUNER_MICROTUNE_4042FI5:
++	{
++		/* FIXME - this may also work for other tuners */
++		unsigned long timeout = jiffies + msecs_to_jiffies(1);
++		u8 status_byte = 0;
++
++		/* Wait until the PLL locks */
++		for (;;) {
++			if (time_after(jiffies, timeout))
++				return 0;
++			rc = tuner_i2c_xfer_recv(&priv->i2c_props,
++						 &status_byte, 1);
++			if (1 != rc) {
++				tuner_warn("i2c i/o read error: rc == %d "
++					   "(should be 1)\n", rc);
++				break;
++			}
++			if (status_byte & TUNER_PLL_LOCKED)
++				break;
++			udelay(10);
++		}
++
++		/* Set the charge pump for optimized phase noise figure */
++		config &= ~TUNER_CHARGE_PUMP;
++		buffer[0] = (div>>8) & 0x7f;
++		buffer[1] = div      & 0xff;
++		buffer[2] = config;
++		buffer[3] = cb;
++		tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
++			  buffer[0], buffer[1], buffer[2], buffer[3]);
++
++		rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
++		if (4 != rc)
++			tuner_warn("i2c i/o error: rc == %d "
++				   "(should be 4)\n", rc);
++		break;
++	}
++	}
++
++	return 0;
++}
++
++static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++
++	switch (priv->type) {
++	case TUNER_TENA_9533_DI:
++	case TUNER_YMEC_TVF_5533MF:
++		tuner_dbg("This tuner doesn't have FM. "
++			  "Most cards have a TEA5767 for FM\n");
++		return 0;
++	case TUNER_PHILIPS_FM1216ME_MK3:
++	case TUNER_PHILIPS_FM1236_MK3:
++	case TUNER_PHILIPS_FMD1216ME_MK3:
++	case TUNER_LG_NTSC_TAPE:
++	case TUNER_PHILIPS_FM1256_IH3:
++		buffer[3] = 0x19;
++		break;
++	case TUNER_TNF_5335MF:
++		buffer[3] = 0x11;
++		break;
++	case TUNER_LG_PAL_FM:
++		buffer[3] = 0xa5;
++		break;
++	case TUNER_THOMSON_DTT761X:
++		buffer[3] = 0x39;
++		break;
++	case TUNER_MICROTUNE_4049FM5:
++	default:
++		buffer[3] = 0xa4;
++		break;
++	}
++
++	return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int simple_set_tv_freq(struct dvb_frontend *fe,
++			      struct analog_parameters *params)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++	u8 config, cb;
++	u16 div;
++	struct tunertype *tun;
++	u8 buffer[4];
++	int rc, IFPCoff, i;
++	enum param_type desired_type;
++	struct tuner_params *t_params;
++
++	tun = priv->tun;
++
++	/* IFPCoff = Video Intermediate Frequency - Vif:
++		940  =16*58.75  NTSC/J (Japan)
++		732  =16*45.75  M/N STD
++		704  =16*44     ATSC (at DVB code)
++		632  =16*39.50  I U.K.
++		622.4=16*38.90  B/G D/K I, L STD
++		592  =16*37.00  D China
++		590  =16.36.875 B Australia
++		543.2=16*33.95  L' STD
++		171.2=16*10.70  FM Radio (at set_radio_freq)
++	*/
++
++	if (params->std == V4L2_STD_NTSC_M_JP) {
++		IFPCoff      = 940;
++		desired_type = TUNER_PARAM_TYPE_NTSC;
++	} else if ((params->std & V4L2_STD_MN) &&
++		  !(params->std & ~V4L2_STD_MN)) {
++		IFPCoff      = 732;
++		desired_type = TUNER_PARAM_TYPE_NTSC;
++	} else if (params->std == V4L2_STD_SECAM_LC) {
++		IFPCoff      = 543;
++		desired_type = TUNER_PARAM_TYPE_SECAM;
++	} else {
++		IFPCoff      = 623;
++		desired_type = TUNER_PARAM_TYPE_PAL;
++	}
++
++	t_params = simple_tuner_params(fe, desired_type);
++
++	i = simple_config_lookup(fe, t_params, &params->frequency,
++				 &config, &cb);
++
++	div = params->frequency + IFPCoff + offset;
++
++	tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, "
++		  "Offset=%d.%02d MHz, div=%0d\n",
++		  params->frequency / 16, params->frequency % 16 * 100 / 16,
++		  IFPCoff / 16, IFPCoff % 16 * 100 / 16,
++		  offset / 16, offset % 16 * 100 / 16, div);
++
++	/* tv norm specific stuff for multi-norm tuners */
++	simple_std_setup(fe, params, &config, &cb);
+ 
+ 	if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
+ 		buffer[0] = config;
+@@ -357,8 +588,10 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
+ 	if (t_params->has_tda9887) {
+ 		struct v4l2_priv_tun_config tda9887_cfg;
+ 		int config = 0;
+-		int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) &&
+-			!(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC));
++		int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
++						 V4L2_STD_SECAM_LC)) &&
++			!(params->std & ~(V4L2_STD_SECAM_L |
++					  V4L2_STD_SECAM_LC));
+ 
+ 		tda9887_cfg.tuner = TUNER_TDA9887;
+ 		tda9887_cfg.priv  = &config;
+@@ -368,8 +601,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
+ 				config |= TDA9887_PORT1_ACTIVE;
+ 			if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
+ 				config |= TDA9887_PORT2_ACTIVE;
+-		}
+-		else {
++		} else {
+ 			if (t_params->port1_active)
+ 				config |= TDA9887_PORT1_ACTIVE;
+ 			if (t_params->port2_active)
+@@ -384,8 +616,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
+ 				config |= TDA9887_TOP(t_params->default_top_secam_mid);
+ 			else if (t_params->default_top_secam_high)
+ 				config |= TDA9887_TOP(t_params->default_top_secam_high);
+-		}
+-		else {
++		} else {
+ 			if (i == 0 && t_params->default_top_low)
+ 				config |= TDA9887_TOP(t_params->default_top_low);
+ 			else if (i == 1 && t_params->default_top_mid)
+@@ -399,56 +630,14 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
+ 				    &tda9887_cfg);
+ 	}
+ 	tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+-		  buffer[0],buffer[1],buffer[2],buffer[3]);
+-
+-	if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
+-		tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+-
+-	switch (priv->type) {
+-	case TUNER_LG_TDVS_H06XF:
+-		/* Set the Auxiliary Byte. */
+-		buffer[0] = buffer[2];
+-		buffer[0] &= ~0x20;
+-		buffer[0] |= 0x18;
+-		buffer[1] = 0x20;
+-		tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]);
+-
+-		if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2)))
+-			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
+-		break;
+-	case TUNER_MICROTUNE_4042FI5:
+-	{
+-		// FIXME - this may also work for other tuners
+-		unsigned long timeout = jiffies + msecs_to_jiffies(1);
+-		u8 status_byte = 0;
++		  buffer[0], buffer[1], buffer[2], buffer[3]);
+ 
+-		/* Wait until the PLL locks */
+-		for (;;) {
+-			if (time_after(jiffies,timeout))
+-				return 0;
+-			if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) {
+-				tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc);
+-				break;
+-			}
+-			if (status_byte & TUNER_PLL_LOCKED)
+-				break;
+-			udelay(10);
+-		}
++	rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
++	if (4 != rc)
++		tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
+ 
+-		/* Set the charge pump for optimized phase noise figure */
+-		config &= ~TUNER_CHARGE_PUMP;
+-		buffer[0] = (div>>8) & 0x7f;
+-		buffer[1] = div      & 0xff;
+-		buffer[2] = config;
+-		buffer[3] = cb;
+-		tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+-			  buffer[0],buffer[1],buffer[2],buffer[3]);
++	simple_post_tune(fe, &buffer[0], div, config, cb);
+ 
+-		if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
+-			tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+-		break;
+-	}
+-	}
+ 	return 0;
+ }
+ 
+@@ -483,37 +672,13 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
+ 		freq += (unsigned int)(41.3*16000);
+ 		break;
+ 	default:
+-		tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if);
++		tuner_warn("Unsupported radio_if value %d\n",
++			   t_params->radio_if);
+ 		return 0;
+ 	}
+ 
+ 	/* Bandswitch byte */
+-	switch (priv->type) {
+-	case TUNER_TENA_9533_DI:
+-	case TUNER_YMEC_TVF_5533MF:
+-		tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");
+-		return 0;
+-	case TUNER_PHILIPS_FM1216ME_MK3:
+-	case TUNER_PHILIPS_FM1236_MK3:
+-	case TUNER_PHILIPS_FMD1216ME_MK3:
+-	case TUNER_LG_NTSC_TAPE:
+-	case TUNER_PHILIPS_FM1256_IH3:
+-		buffer[3] = 0x19;
+-		break;
+-	case TUNER_TNF_5335MF:
+-		buffer[3] = 0x11;
+-		break;
+-	case TUNER_LG_PAL_FM:
+-		buffer[3] = 0xa5;
+-		break;
+-	case TUNER_THOMSON_DTT761X:
+-		buffer[3] = 0x39;
+-		break;
+-	case TUNER_MICROTUNE_4049FM5:
+-	default:
+-		buffer[3] = 0xa4;
+-		break;
+-	}
++	simple_radio_bandswitch(fe, &buffer[0]);
+ 
+ 	buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
+ 		    TUNER_RATIO_SELECT_50; /* 50 kHz step */
+@@ -534,7 +699,7 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
+ 	}
+ 
+ 	tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
+-	       buffer[0],buffer[1],buffer[2],buffer[3]);
++	       buffer[0], buffer[1], buffer[2], buffer[3]);
+ 	priv->last_div = div;
+ 
+ 	if (t_params->has_tda9887) {
+@@ -544,9 +709,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
+ 		tda9887_cfg.tuner = TUNER_TDA9887;
+ 		tda9887_cfg.priv = &config;
+ 
+-		if (t_params->port1_active && !t_params->port1_fm_high_sensitivity)
++		if (t_params->port1_active &&
++		    !t_params->port1_fm_high_sensitivity)
+ 			config |= TDA9887_PORT1_ACTIVE;
+-		if (t_params->port2_active && !t_params->port2_fm_high_sensitivity)
++		if (t_params->port2_active &&
++		    !t_params->port2_fm_high_sensitivity)
+ 			config |= TDA9887_PORT2_ACTIVE;
+ 		if (t_params->intercarrier_mode)
+ 			config |= TDA9887_INTERCARRIER;
+@@ -557,10 +724,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
+ 		if (t_params->radio_if == 2)
+ 			config |= TDA9887_RIF_41_3;
+ 		i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
+-					&tda9887_cfg);
++				    &tda9887_cfg);
+ 	}
+-	if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
+-		tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
++	rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
++	if (4 != rc)
++		tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
+ 
+ 	return 0;
+ }
+@@ -571,6 +739,9 @@ static int simple_set_params(struct dvb_frontend *fe,
+ 	struct tuner_simple_priv *priv = fe->tuner_priv;
+ 	int ret = -EINVAL;
+ 
++	if (priv->i2c_props.adap == NULL)
++		return -EINVAL;
++
+ 	switch (params->mode) {
+ 	case V4L2_TUNER_RADIO:
+ 		ret = simple_set_radio_freq(fe, params);
+@@ -582,14 +753,210 @@ static int simple_set_params(struct dvb_frontend *fe,
+ 		priv->frequency = params->frequency * 62500;
+ 		break;
+ 	}
++	priv->bandwidth = 0;
+ 
+ 	return ret;
+ }
+ 
++static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
++			   const struct dvb_frontend_parameters *params)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++
++	switch (priv->type) {
++	case TUNER_PHILIPS_FMD1216ME_MK3:
++		if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
++		    params->frequency >= 158870000)
++			buf[3] |= 0x08;
++		break;
++	case TUNER_PHILIPS_TD1316:
++		/* determine band */
++		buf[3] |= (params->frequency < 161000000) ? 1 :
++			  (params->frequency < 444000000) ? 2 : 4;
++
++		/* setup PLL filter */
++		if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
++			buf[3] |= 1 << 3;
++		break;
++	case TUNER_PHILIPS_TUV1236D:
++	case TUNER_PHILIPS_FCV1236D:
++	{
++		unsigned int new_rf;
++
++		if (dtv_input[priv->nr])
++			new_rf = dtv_input[priv->nr];
++		else
++			switch (params->u.vsb.modulation) {
++			case QAM_64:
++			case QAM_256:
++				new_rf = 1;
++				break;
++			case VSB_8:
++			default:
++				new_rf = 0;
++				break;
++			}
++		simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);
++		break;
++	}
++	default:
++		break;
++	}
++}
++
++static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
++				const struct dvb_frontend_parameters *params)
++{
++	/* This function returns the tuned frequency on success, 0 on error */
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++	struct tunertype *tun = priv->tun;
++	static struct tuner_params *t_params;
++	u8 config, cb;
++	u32 div;
++	int ret, frequency = params->frequency / 62500;
++
++	t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
++	ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
++	if (ret < 0)
++		return 0; /* failure */
++
++	div = ((frequency + t_params->iffreq) * 62500 + offset +
++	       tun->stepsize/2) / tun->stepsize;
++
++	buf[0] = div >> 8;
++	buf[1] = div & 0xff;
++	buf[2] = config;
++	buf[3] = cb;
++
++	simple_set_dvb(fe, buf, params);
++
++	tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
++		  tun->name, div, buf[0], buf[1], buf[2], buf[3]);
++
++	/* calculate the frequency we set it to */
++	return (div * tun->stepsize) - t_params->iffreq;
++}
++
++static int simple_dvb_calc_regs(struct dvb_frontend *fe,
++				struct dvb_frontend_parameters *params,
++				u8 *buf, int buf_len)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++	u32 frequency;
++
++	if (buf_len < 5)
++		return -EINVAL;
++
++	frequency = simple_dvb_configure(fe, buf+1, params);
++	if (frequency == 0)
++		return -EINVAL;
++
++	buf[0] = priv->i2c_props.addr;
++
++	priv->frequency = frequency;
++	priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
++		params->u.ofdm.bandwidth : 0;
++
++	return 5;
++}
++
++static int simple_dvb_set_params(struct dvb_frontend *fe,
++				 struct dvb_frontend_parameters *params)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++	u32 prev_freq, prev_bw;
++	int ret;
++	u8 buf[5];
++
++	if (priv->i2c_props.adap == NULL)
++		return -EINVAL;
++
++	prev_freq = priv->frequency;
++	prev_bw   = priv->bandwidth;
++
++	ret = simple_dvb_calc_regs(fe, params, buf, 5);
++	if (ret != 5)
++		goto fail;
++
++	/* put analog demod in standby when tuning digital */
++	if (fe->ops.analog_ops.standby)
++		fe->ops.analog_ops.standby(fe);
++
++	if (fe->ops.i2c_gate_ctrl)
++		fe->ops.i2c_gate_ctrl(fe, 1);
++
++	/* buf[0] contains the i2c address, but *
++	 * we already have it in i2c_props.addr */
++	ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4);
++	if (ret != 4)
++		goto fail;
++
++	return 0;
++fail:
++	/* calc_regs sets frequency and bandwidth. if we failed, unset them */
++	priv->frequency = prev_freq;
++	priv->bandwidth = prev_bw;
++
++	return ret;
++}
++
++static int simple_init(struct dvb_frontend *fe)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++
++	if (priv->i2c_props.adap == NULL)
++		return -EINVAL;
++
++	if (priv->tun->initdata) {
++		int ret;
++
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 1);
++
++		ret = tuner_i2c_xfer_send(&priv->i2c_props,
++					  priv->tun->initdata + 1,
++					  priv->tun->initdata[0]);
++		if (ret != priv->tun->initdata[0])
++			return ret;
++	}
++
++	return 0;
++}
++
++static int simple_sleep(struct dvb_frontend *fe)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++
++	if (priv->i2c_props.adap == NULL)
++		return -EINVAL;
++
++	if (priv->tun->sleepdata) {
++		int ret;
++
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 1);
++
++		ret = tuner_i2c_xfer_send(&priv->i2c_props,
++					  priv->tun->sleepdata + 1,
++					  priv->tun->sleepdata[0]);
++		if (ret != priv->tun->sleepdata[0])
++			return ret;
++	}
++
++	return 0;
++}
+ 
+ static int simple_release(struct dvb_frontend *fe)
+ {
+-	kfree(fe->tuner_priv);
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++
++	mutex_lock(&tuner_simple_list_mutex);
++
++	if (priv)
++		hybrid_tuner_release_state(priv);
++
++	mutex_unlock(&tuner_simple_list_mutex);
++
+ 	fe->tuner_priv = NULL;
+ 
+ 	return 0;
+@@ -602,10 +969,22 @@ static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+ 	return 0;
+ }
+ 
++static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++	struct tuner_simple_priv *priv = fe->tuner_priv;
++	*bandwidth = priv->bandwidth;
++	return 0;
++}
++
+ static struct dvb_tuner_ops simple_tuner_ops = {
++	.init              = simple_init,
++	.sleep             = simple_sleep,
+ 	.set_analog_params = simple_set_params,
++	.set_params        = simple_dvb_set_params,
++	.calc_regs         = simple_dvb_calc_regs,
+ 	.release           = simple_release,
+ 	.get_frequency     = simple_get_frequency,
++	.get_bandwidth     = simple_get_bandwidth,
+ 	.get_status        = simple_get_status,
+ 	.get_rf_strength   = simple_get_rf_strength,
+ };
+@@ -613,30 +992,92 @@ static struct dvb_tuner_ops simple_tuner_ops = {
+ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
+ 					 struct i2c_adapter *i2c_adap,
+ 					 u8 i2c_addr,
+-					 struct simple_tuner_config *cfg)
++					 unsigned int type)
+ {
+ 	struct tuner_simple_priv *priv = NULL;
++	int instance;
+ 
+-	priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL);
+-	if (priv == NULL)
++	if (type >= tuner_count) {
++		printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
++		       __func__, type, tuner_count-1);
+ 		return NULL;
+-	fe->tuner_priv = priv;
++	}
+ 
+-	priv->i2c_props.addr = i2c_addr;
+-	priv->i2c_props.adap = i2c_adap;
+-	priv->type = cfg->type;
+-	priv->tun  = cfg->tun;
++	/* If i2c_adap is set, check that the tuner is at the correct address.
++	 * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly
++	 * by the digital demod via calc_regs.
++	 */
++	if (i2c_adap != NULL) {
++		u8 b[1];
++		struct i2c_msg msg = {
++			.addr = i2c_addr, .flags = I2C_M_RD,
++			.buf = b, .len = 1,
++		};
++
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 1);
++
++		if (1 != i2c_transfer(i2c_adap, &msg, 1))
++			tuner_warn("unable to probe %s, proceeding anyway.",
++				   tuners[type].name);
++
++		if (fe->ops.i2c_gate_ctrl)
++			fe->ops.i2c_gate_ctrl(fe, 0);
++	}
+ 
+-	memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops));
++	mutex_lock(&tuner_simple_list_mutex);
+ 
+-	tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name);
++	instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv,
++					      hybrid_tuner_instance_list,
++					      i2c_adap, i2c_addr,
++					      "tuner-simple");
++	switch (instance) {
++	case 0:
++		mutex_unlock(&tuner_simple_list_mutex);
++		return NULL;
++		break;
++	case 1:
++		fe->tuner_priv = priv;
+ 
+-	strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name));
++		priv->type = type;
++		priv->tun  = &tuners[type];
++		priv->nr   = simple_devcount++;
++		break;
++	default:
++		fe->tuner_priv = priv;
++		break;
++	}
+ 
+-	return fe;
+-}
++	mutex_unlock(&tuner_simple_list_mutex);
++
++	memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
++	       sizeof(struct dvb_tuner_ops));
++
++	tuner_info("type set to %d (%s)\n", type, priv->tun->name);
++
++	if ((debug) || ((atv_input[priv->nr] > 0) ||
++			(dtv_input[priv->nr] > 0))) {
++		if (0 == atv_input[priv->nr])
++			tuner_info("tuner %d atv rf input will be "
++				   "autoselected\n", priv->nr);
++		else
++			tuner_info("tuner %d atv rf input will be "
++				   "set to input %d (insmod option)\n",
++				   priv->nr, atv_input[priv->nr]);
++		if (0 == dtv_input[priv->nr])
++			tuner_info("tuner %d dtv rf input will be "
++				   "autoselected\n", priv->nr);
++		else
++			tuner_info("tuner %d dtv rf input will be "
++				   "set to input %d (insmod option)\n",
++				   priv->nr, dtv_input[priv->nr]);
++	}
+ 
++	strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name,
++		sizeof(fe->ops.tuner_ops.info.name));
+ 
++	return fe;
++}
+ EXPORT_SYMBOL_GPL(simple_tuner_attach);
+ 
+ MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
+diff --git a/drivers/media/video/tuner-simple.h b/drivers/media/video/tuner-simple.h
+index 9089939..e46cf01 100644
+--- a/drivers/media/video/tuner-simple.h
++++ b/drivers/media/video/tuner-simple.h
+@@ -20,25 +20,18 @@
+ #include <linux/i2c.h>
+ #include "dvb_frontend.h"
+ 
+-struct simple_tuner_config
+-{
+-	/* chip type */
+-	unsigned int type;
+-	struct tunertype *tun;
+-};
+-
+ #if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE))
+ extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
+ 						struct i2c_adapter *i2c_adap,
+ 						u8 i2c_addr,
+-						struct simple_tuner_config *cfg);
++						unsigned int type);
+ #else
+ static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
+ 						       struct i2c_adapter *i2c_adap,
+ 						       u8 i2c_addr,
+-						       struct simple_tuner_config *cfg)
++						       unsigned int type)
+ {
+-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ 	return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
+index 883047f..10dddca 100644
+--- a/drivers/media/video/tuner-types.c
++++ b/drivers/media/video/tuner-types.c
+@@ -35,6 +35,27 @@
+  *	based on the video standard in use.
+  */
+ 
++/* The following was taken from dvb-pll.c: */
++
++/* Set AGC TOP value to 103 dBuV:
++ *	0x80 = Control Byte
++ *	0x40 = 250 uA charge pump (irrelevant)
++ *	0x18 = Aux Byte to follow
++ *	0x06 = 64.5 kHz divider (irrelevant)
++ *	0x01 = Disable Vt (aka sleep)
++ *
++ *	0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
++ *	0x50 = AGC Take over point = 103 dBuV
++ */
++static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
++
++/*	0x04 = 166.67 kHz divider
++ *
++ *	0x80 = AGC Time constant 50ms Iagc = 9 uA
++ *	0x20 = AGC Take over point = 112 dBuV
++ */
++static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
++
+ /* 0-9 */
+ /* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
+ 
+@@ -594,19 +615,31 @@ static struct tuner_params tuner_philips_pal_mk_params[] = {
+ 	},
+ };
+ 
+-/* ---- TUNER_PHILIPS_ATSC - Philips FCV1236D (ATSC/NTSC) ---- */
++/* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */
+ 
+-static struct tuner_range tuner_philips_fcv1236d_ranges[] = {
+-	{ 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
+-	{ 16 * 451.25 /*MHz*/, 0x8e, 0x90, },
++static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = {
++	{ 16 * 157.25 /*MHz*/, 0x8e, 0xa2, },
++	{ 16 * 451.25 /*MHz*/, 0x8e, 0x92, },
++	{ 16 * 999.99        , 0x8e, 0x32, },
++};
++
++static struct tuner_range tuner_philips_fcv1236d_atsc_ranges[] = {
++	{ 16 * 159.00 /*MHz*/, 0x8e, 0xa0, },
++	{ 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
+ 	{ 16 * 999.99        , 0x8e, 0x30, },
+ };
+ 
+ static struct tuner_params tuner_philips_fcv1236d_params[] = {
+ 	{
+ 		.type   = TUNER_PARAM_TYPE_NTSC,
+-		.ranges = tuner_philips_fcv1236d_ranges,
+-		.count  = ARRAY_SIZE(tuner_philips_fcv1236d_ranges),
++		.ranges = tuner_philips_fcv1236d_ntsc_ranges,
++		.count  = ARRAY_SIZE(tuner_philips_fcv1236d_ntsc_ranges),
++	},
++	{
++		.type   = TUNER_PARAM_TYPE_DIGITAL,
++		.ranges = tuner_philips_fcv1236d_atsc_ranges,
++		.count  = ARRAY_SIZE(tuner_philips_fcv1236d_atsc_ranges),
++		.iffreq = 16 * 44.00,
+ 	},
+ };
+ 
+@@ -701,12 +734,24 @@ static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
+ 	{ 16 * 999.99        , 0x8e, 0x31, },
+ };
+ 
++static struct tuner_range tuner_microtune_4042fi5_atsc_ranges[] = {
++	{ 16 * 162.00 /*MHz*/, 0x8e, 0xa1, },
++	{ 16 * 457.00 /*MHz*/, 0x8e, 0x91, },
++	{ 16 * 999.99        , 0x8e, 0x31, },
++};
++
+ static struct tuner_params tuner_microtune_4042fi5_params[] = {
+ 	{
+ 		.type   = TUNER_PARAM_TYPE_NTSC,
+ 		.ranges = tuner_microtune_4042fi5_ntsc_ranges,
+ 		.count  = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges),
+ 	},
++	{
++		.type   = TUNER_PARAM_TYPE_DIGITAL,
++		.ranges = tuner_microtune_4042fi5_atsc_ranges,
++		.count  = ARRAY_SIZE(tuner_microtune_4042fi5_atsc_ranges),
++		.iffreq = 16 * 44.00 /*MHz*/,
++	},
+ };
+ 
+ /* 50-59 */
+@@ -740,6 +785,7 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
+ 
+ /* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
+ 
++/* single range used for both ntsc and atsc */
+ static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
+ 	{ 16 * 157.25 /*MHz*/, 0x8e, 0x39, },
+ 	{ 16 * 454.00 /*MHz*/, 0x8e, 0x3a, },
+@@ -752,6 +798,12 @@ static struct tuner_params tuner_thomson_dtt7610_params[] = {
+ 		.ranges = tuner_thomson_dtt7610_ntsc_ranges,
+ 		.count  = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
+ 	},
++	{
++		.type   = TUNER_PARAM_TYPE_DIGITAL,
++		.ranges = tuner_thomson_dtt7610_ntsc_ranges,
++		.count  = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
++		.iffreq = 16 * 44.00 /*MHz*/,
++	},
+ };
+ 
+ /* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
+@@ -855,6 +907,11 @@ static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
+ 	{ 16 * 999.99        , 0x8e, 0x3c, },
+ };
+ 
++static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = {
++	{ 16 * 147.00 /*MHz*/, 0x8e, 0x39, },
++	{ 16 * 417.00 /*MHz*/, 0x8e, 0x3a, },
++	{ 16 * 999.99        , 0x8e, 0x3c, },
++};
+ 
+ static struct tuner_params tuner_thomson_dtt761x_params[] = {
+ 	{
+@@ -865,6 +922,12 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = {
+ 		.fm_gain_normal = 1,
+ 		.radio_if = 2, /* 41.3 MHz */
+ 	},
++	{
++		.type   = TUNER_PARAM_TYPE_DIGITAL,
++		.ranges = tuner_thomson_dtt761x_atsc_ranges,
++		.count  = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges),
++		.iffreq = 16 * 44.00, /*MHz*/
++	},
+ };
+ 
+ /* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
+@@ -891,6 +954,15 @@ static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
+ 	{ 16 * 999.99        , 0x86, 0x54, },
+ };
+ 
++static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = {
++	{ 16 * 143.87 /*MHz*/, 0xbc, 0x41 },
++	{ 16 * 158.87 /*MHz*/, 0xf4, 0x41 },
++	{ 16 * 329.87 /*MHz*/, 0xbc, 0x42 },
++	{ 16 * 441.87 /*MHz*/, 0xf4, 0x42 },
++	{ 16 * 625.87 /*MHz*/, 0xbc, 0x44 },
++	{ 16 * 803.87 /*MHz*/, 0xf4, 0x44 },
++	{ 16 * 999.99        , 0xfc, 0x44 },
++};
+ 
+ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
+ 	{
+@@ -904,6 +976,12 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
+ 		.port2_invert_for_secam_lc = 1,
+ 		.port1_set_for_fm_mono = 1,
+ 	},
++	{
++		.type   = TUNER_PARAM_TYPE_DIGITAL,
++		.ranges = tuner_philips_fmd1216me_mk3_dvb_ranges,
++		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges),
++		.iffreq = 16 * 36.125, /*MHz*/
++	},
+ };
+ 
+ 
+@@ -915,6 +993,11 @@ static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
+ 	{ 16 * 999.99        , 0x8e, 0x04 },
+ };
+ 
++static struct tuner_range tuner_tua6034_atsc_ranges[] = {
++	{ 16 * 165.00 /*MHz*/, 0xce, 0x01 },
++	{ 16 * 450.00 /*MHz*/, 0xce, 0x02 },
++	{ 16 * 999.99        , 0xce, 0x04 },
++};
+ 
+ static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
+ 	{
+@@ -922,6 +1005,12 @@ static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
+ 		.ranges = tuner_tua6034_ntsc_ranges,
+ 		.count  = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
+ 	},
++	{
++		.type   = TUNER_PARAM_TYPE_DIGITAL,
++		.ranges = tuner_tua6034_atsc_ranges,
++		.count  = ARRAY_SIZE(tuner_tua6034_atsc_ranges),
++		.iffreq = 16 * 44.00,
++	},
+ };
+ 
+ /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
+@@ -974,12 +1063,30 @@ static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
+ 	{ 16 * 999.99        , 0xc8, 0xa4, },
+ };
+ 
++static struct tuner_range tuner_philips_td1316_dvb_ranges[] = {
++	{ 16 *  93.834 /*MHz*/, 0xca, 0x60, },
++	{ 16 * 123.834 /*MHz*/, 0xca, 0xa0, },
++	{ 16 * 163.834 /*MHz*/, 0xca, 0xc0, },
++	{ 16 * 253.834 /*MHz*/, 0xca, 0x60, },
++	{ 16 * 383.834 /*MHz*/, 0xca, 0xa0, },
++	{ 16 * 443.834 /*MHz*/, 0xca, 0xc0, },
++	{ 16 * 583.834 /*MHz*/, 0xca, 0x60, },
++	{ 16 * 793.834 /*MHz*/, 0xca, 0xa0, },
++	{ 16 * 999.999        , 0xca, 0xe0, },
++};
++
+ static struct tuner_params tuner_philips_td1316_params[] = {
+ 	{
+ 		.type   = TUNER_PARAM_TYPE_PAL,
+ 		.ranges = tuner_philips_td1316_pal_ranges,
+ 		.count  = ARRAY_SIZE(tuner_philips_td1316_pal_ranges),
+ 	},
++	{
++		.type   = TUNER_PARAM_TYPE_DIGITAL,
++		.ranges = tuner_philips_td1316_dvb_ranges,
++		.count  = ARRAY_SIZE(tuner_philips_td1316_dvb_ranges),
++		.iffreq = 16 * 36.166667 /*MHz*/,
++	},
+ };
+ 
+ /* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
+@@ -990,6 +1097,11 @@ static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
+ 	{ 16 * 999.99        , 0xce, 0x04, },
+ };
+ 
++static struct tuner_range tuner_tuv1236d_atsc_ranges[] = {
++	{ 16 * 157.25 /*MHz*/, 0xc6, 0x41, },
++	{ 16 * 454.00 /*MHz*/, 0xc6, 0x42, },
++	{ 16 * 999.99        , 0xc6, 0x44, },
++};
+ 
+ static struct tuner_params tuner_tuv1236d_params[] = {
+ 	{
+@@ -997,6 +1109,12 @@ static struct tuner_params tuner_tuv1236d_params[] = {
+ 		.ranges = tuner_tuv1236d_ntsc_ranges,
+ 		.count  = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
+ 	},
++	{
++		.type   = TUNER_PARAM_TYPE_DIGITAL,
++		.ranges = tuner_tuv1236d_atsc_ranges,
++		.count  = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges),
++		.iffreq = 16 * 44.00,
++	},
+ };
+ 
+ /* ------------ TUNER_TNF_xxx5  - Texas Instruments--------- */
+@@ -1050,17 +1168,30 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
+ 
+ /* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */
+ 
+-static struct tuner_range tuner_thomson_fe6600_ranges[] = {
++static struct tuner_range tuner_thomson_fe6600_pal_ranges[] = {
+ 	{ 16 * 160.00 /*MHz*/, 0xfe, 0x11, },
+ 	{ 16 * 442.00 /*MHz*/, 0xf6, 0x12, },
+ 	{ 16 * 999.99        , 0xf6, 0x18, },
+ };
+ 
++static struct tuner_range tuner_thomson_fe6600_dvb_ranges[] = {
++	{ 16 * 250.00 /*MHz*/, 0xb4, 0x12, },
++	{ 16 * 455.00 /*MHz*/, 0xfe, 0x11, },
++	{ 16 * 775.50 /*MHz*/, 0xbc, 0x18, },
++	{ 16 * 999.99        , 0xf4, 0x18, },
++};
++
+ static struct tuner_params tuner_thomson_fe6600_params[] = {
+ 	{
+ 		.type   = TUNER_PARAM_TYPE_PAL,
+-		.ranges = tuner_thomson_fe6600_ranges,
+-		.count  = ARRAY_SIZE(tuner_thomson_fe6600_ranges),
++		.ranges = tuner_thomson_fe6600_pal_ranges,
++		.count  = ARRAY_SIZE(tuner_thomson_fe6600_pal_ranges),
++	},
++	{
++		.type   = TUNER_PARAM_TYPE_DIGITAL,
++		.ranges = tuner_thomson_fe6600_dvb_ranges,
++		.count  = ARRAY_SIZE(tuner_thomson_fe6600_dvb_ranges),
++		.iffreq = 16 * 36.125 /*MHz*/,
+ 	},
+ };
+ 
+@@ -1303,10 +1434,13 @@ struct tunertype tuners[] = {
+ 		.params = tuner_philips_pal_mk_params,
+ 		.count  = ARRAY_SIZE(tuner_philips_pal_mk_params),
+ 	},
+-	[TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
++	[TUNER_PHILIPS_FCV1236D] = { /* Philips ATSC */
+ 		.name   = "Philips FCV1236D ATSC/NTSC dual in",
+ 		.params = tuner_philips_fcv1236d_params,
+ 		.count  = ARRAY_SIZE(tuner_philips_fcv1236d_params),
++		.min = 16 *  53.00,
++		.max = 16 * 803.00,
++		.stepsize = 62500,
+ 	},
+ 	[TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
+ 		.name   = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
+@@ -1342,6 +1476,9 @@ struct tunertype tuners[] = {
+ 		.name   = "Microtune 4042 FI5 ATSC/NTSC dual in",
+ 		.params = tuner_microtune_4042fi5_params,
+ 		.count  = ARRAY_SIZE(tuner_microtune_4042fi5_params),
++		.min    = 16 *  57.00,
++		.max    = 16 * 858.00,
++		.stepsize = 62500,
+ 	},
+ 
+ 	/* 50-59 */
+@@ -1359,6 +1496,9 @@ struct tunertype tuners[] = {
+ 		.name   = "Thomson DTT 7610 (ATSC/NTSC)",
+ 		.params = tuner_thomson_dtt7610_params,
+ 		.count  = ARRAY_SIZE(tuner_thomson_dtt7610_params),
++		.min    = 16 *  44.00,
++		.max    = 16 * 958.00,
++		.stepsize = 62500,
+ 	},
+ 	[TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
+ 		.name   = "Philips FQ1286",
+@@ -1400,6 +1540,10 @@ struct tunertype tuners[] = {
+ 		.name   = "Thomson DTT 761X (ATSC/NTSC)",
+ 		.params = tuner_thomson_dtt761x_params,
+ 		.count  = ARRAY_SIZE(tuner_thomson_dtt761x_params),
++		.min    = 16 *  57.00,
++		.max    = 16 * 863.00,
++		.stepsize = 62500,
++		.initdata = tua603x_agc103,
+ 	},
+ 	[TUNER_TENA_9533_DI] = { /* Philips PAL */
+ 		.name   = "Tena TNF9533-D/IF/TNF9533-B/DF",
+@@ -1414,11 +1558,20 @@ struct tunertype tuners[] = {
+ 		.name   = "Philips FMD1216ME MK3 Hybrid Tuner",
+ 		.params = tuner_philips_fmd1216me_mk3_params,
+ 		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params),
++		.min = 16 *  50.87,
++		.max = 16 * 858.00,
++		.stepsize = 166667,
++		.initdata = tua603x_agc112,
++		.sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
+ 	},
+ 	[TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */
+ 		.name   = "LG TDVS-H06xF", /* H061F, H062F & H064F */
+ 		.params = tuner_lg_tdvs_h06xf_params,
+ 		.count  = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params),
++		.min    = 16 *  54.00,
++		.max    = 16 * 863.00,
++		.stepsize = 62500,
++		.initdata = tua603x_agc103,
+ 	},
+ 	[TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
+ 		.name   = "Ymec TVF66T5-B/DFF",
+@@ -1434,11 +1587,17 @@ struct tunertype tuners[] = {
+ 		.name   = "Philips TD1316 Hybrid Tuner",
+ 		.params = tuner_philips_td1316_params,
+ 		.count  = ARRAY_SIZE(tuner_philips_td1316_params),
++		.min    = 16 *  87.00,
++		.max    = 16 * 895.00,
++		.stepsize = 166667,
+ 	},
+ 	[TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
+ 		.name   = "Philips TUV1236D ATSC/NTSC dual in",
+ 		.params = tuner_tuv1236d_params,
+ 		.count  = ARRAY_SIZE(tuner_tuv1236d_params),
++		.min    = 16 *  54.00,
++		.max    = 16 * 864.00,
++		.stepsize = 62500,
+ 	},
+ 	[TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */
+ 		.name   = "Tena TNF 5335 and similar models",
+@@ -1460,6 +1619,9 @@ struct tunertype tuners[] = {
+ 		.name   = "Thomson FE6600",
+ 		.params = tuner_thomson_fe6600_params,
+ 		.count  = ARRAY_SIZE(tuner_thomson_fe6600_params),
++		.min    = 16 *  44.25,
++		.max    = 16 * 858.00,
++		.stepsize = 166667,
+ 	},
+ 	[TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */
+ 		.name   = "Samsung TCPG 6121P30A",
+@@ -1480,5 +1642,11 @@ struct tunertype tuners[] = {
+ 		/* see xc5000.c for details */
+ 	},
+ };
++EXPORT_SYMBOL(tuners);
+ 
+ unsigned const int tuner_count = ARRAY_SIZE(tuners);
++EXPORT_SYMBOL(tuner_count);
++
++MODULE_DESCRIPTION("Simple tuner device type database");
++MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/tuner-xc2028-types.h b/drivers/media/video/tuner-xc2028-types.h
+index d0057fb..74dc46a 100644
+--- a/drivers/media/video/tuner-xc2028-types.h
++++ b/drivers/media/video/tuner-xc2028-types.h
+@@ -1,6 +1,9 @@
+ /* tuner-xc2028_types
+  *
+- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * This file includes internal tipes to be used inside tuner-xc2028.
++ * Shouldn't be included outside tuner-xc2028
++ *
++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
+  * This code is placed under the terms of the GNU General Public License v2
+  */
+ 
+@@ -54,11 +57,13 @@
+ /* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
+ 	and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
+ 	There are variants both with and without NOGD
++	Those firmwares produce better result with LCD displays
+  */
+ #define LCD		(1<<12)
+ 
+ /* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
+ 	and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
++	The NOGD firmwares don't have group delay compensation filter
+  */
+ #define NOGD		(1<<13)
+ 
+@@ -85,11 +90,19 @@
+ /* This flag identifies that the scode table has a new format */
+ #define HAS_IF         (1 << 30)
+ 
+-#define SCODE_TYPES	(MTS|DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \
+-			 LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794|     \
+-			 DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE)
++/* There are different scode tables for MTS and non-MTS.
++   The MTS firmwares support mono only
++  */
++#define SCODE_TYPES (SCODE | MTS)
++
+ 
+-/* Newer types to be moved to videodev2.h */
++/* Newer types not defined on videodev2.h.
++   The original idea were to move all those types to videodev2.h, but
++   it seemed overkill, since, with the exception of SECAM/K3, the other
++   types seem to be autodetected.
++   It is not clear where secam/k3 is used, nor we have a feedback of this
++   working or being autodetected by the standard secam firmware.
++ */
+ 
+ #define V4L2_STD_SECAM_K3	(0x04000000)
+ 
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 50cf876..9e9003c 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -1,6 +1,6 @@
+ /* tuner-xc2028
+  *
+- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
+  *
+  * Copyright (c) 2007 Michel Ludwig (michel.ludwig at gmail.com)
+  *       - frontend interface
+@@ -23,8 +23,6 @@
+ #include "dvb_frontend.h"
+ 
+ 
+-#define PREFIX "xc2028"
+-
+ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+@@ -43,6 +41,11 @@ MODULE_PARM_DESC(audio_std,
+ 	"NICAM/A\n"
+ 	"NICAM/B\n");
+ 
++static char firmware_name[FIRMWARE_NAME_MAX];
++module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
++MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
++				"default firmware name\n");
++
+ static LIST_HEAD(xc2028_list);
+ static DEFINE_MUTEX(xc2028_list_mutex);
+ 
+@@ -127,12 +130,12 @@ struct xc2028_data {
+ 	_rc;								\
+ })
+ 
+-static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
++static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
+ {
+ 	unsigned char buf[2];
+ 	unsigned char ibuf[2];
+ 
+-	tuner_dbg("%s %04x called\n", __FUNCTION__, reg);
++	tuner_dbg("%s %04x called\n", __func__, reg);
+ 
+ 	buf[0] = reg >> 8;
+ 	buf[1] = (unsigned char) reg;
+@@ -145,7 +148,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
+ }
+ 
+ #define dump_firm_type(t) 	dump_firm_type_and_int_freq(t, 0)
+-void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
++static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
+ {
+ 	 if (type & BASE)
+ 		printk("BASE ");
+@@ -232,6 +235,7 @@ static  v4l2_std_id parse_audio_std_option(void)
+ static void free_firmware(struct xc2028_data *priv)
+ {
+ 	int i;
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	if (!priv->firm)
+ 		return;
+@@ -255,19 +259,24 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 	int                   rc = 0;
+ 	int		      n, n_array;
+ 	char		      name[33];
++	char		      *fname;
++
++	tuner_dbg("%s called\n", __func__);
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	if (!firmware_name[0])
++		fname = priv->ctrl.fname;
++	else
++		fname = firmware_name;
+ 
+-	tuner_dbg("Reading firmware %s\n", priv->ctrl.fname);
+-	rc = request_firmware(&fw, priv->ctrl.fname,
+-			      &priv->i2c_props.adap->dev);
++	tuner_dbg("Reading firmware %s\n", fname);
++	rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev);
+ 	if (rc < 0) {
+ 		if (rc == -ENOENT)
+ 			tuner_err("Error: firmware %s not found.\n",
+-				   priv->ctrl.fname);
++				   fname);
+ 		else
+ 			tuner_err("Error %d while requesting firmware %s \n",
+-				   rc, priv->ctrl.fname);
++				   rc, fname);
+ 
+ 		return rc;
+ 	}
+@@ -276,7 +285,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 
+ 	if (fw->size < sizeof(name) - 1 + 2 + 2) {
+ 		tuner_err("Error: firmware file %s has invalid size!\n",
+-			  priv->ctrl.fname);
++			  fname);
+ 		goto corrupt;
+ 	}
+ 
+@@ -291,7 +300,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ 	p += 2;
+ 
+ 	tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
+-		   n_array, priv->ctrl.fname, name,
++		   n_array, fname, name,
+ 		   priv->firm_version >> 8, priv->firm_version & 0xff);
+ 
+ 	priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+@@ -395,9 +404,9 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+ 	int                 i, best_i = -1, best_nr_matches = 0;
+-	unsigned int        ign_firm_type_mask = 0;
++	unsigned int        type_mask = 0;
+ 
+-	tuner_dbg("%s called, want type=", __FUNCTION__);
++	tuner_dbg("%s called, want type=", __func__);
+ 	if (debug) {
+ 		dump_firm_type(type);
+ 		printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+@@ -412,18 +421,23 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ 		*id = V4L2_STD_PAL;
+ 
+ 	if (type & BASE)
+-		type &= BASE_TYPES;
++		type_mask = BASE_TYPES;
+ 	else if (type & SCODE) {
+ 		type &= SCODE_TYPES;
+-		ign_firm_type_mask = HAS_IF;
++		type_mask = SCODE_TYPES & ~HAS_IF;
+ 	} else if (type & DTV_TYPES)
+-		type &= DTV_TYPES;
++		type_mask = DTV_TYPES;
+ 	else if (type & STD_SPECIFIC_TYPES)
+-		type &= STD_SPECIFIC_TYPES;
++		type_mask = STD_SPECIFIC_TYPES;
++
++	type &= type_mask;
++
++	if (!(type & SCODE))
++		type_mask = ~0;
+ 
+ 	/* Seek for exact match */
+ 	for (i = 0; i < priv->firm_size; i++) {
+-		if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) &&
++		if ((type == (priv->firm[i].type & type_mask)) &&
+ 		    (*id == priv->firm[i].id))
+ 			goto found;
+ 	}
+@@ -433,7 +447,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ 		v4l2_std_id match_mask;
+ 		int nr_matches;
+ 
+-		if (type != (priv->firm[i].type & ~ign_firm_type_mask))
++		if (type != (priv->firm[i].type & type_mask))
+ 			continue;
+ 
+ 		match_mask = *id & priv->firm[i].id;
+@@ -483,7 +497,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+ 	int                pos, rc;
+ 	unsigned char      *p, *endp, buf[priv->ctrl.max_len];
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	pos = seek_firmware(fe, type, id);
+ 	if (pos < 0)
+@@ -586,7 +600,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
+ 	int                pos, rc;
+ 	unsigned char	   *p;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	if (!int_freq) {
+ 		pos = seek_firmware(fe, type, id);
+@@ -650,7 +664,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
+ 	u16			   version, hwmodel;
+ 	v4l2_std_id		   std0;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	if (!priv->firm) {
+ 		if (!priv->ctrl.fname) {
+@@ -770,10 +784,10 @@ check_device:
+ 		goto fail;
+ 	}
+ 
+-	tuner_info("Device is Xceive %d version %d.%d, "
+-		   "firmware version %d.%d\n",
+-		   hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
+-		   (version & 0xf0) >> 4, version & 0xf);
++	tuner_dbg("Device is Xceive %d version %d.%d, "
++		  "firmware version %d.%d\n",
++		  hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
++		  (version & 0xf0) >> 4, version & 0xf);
+ 
+ 	/* Check firmware version against what we downloaded. */
+ 	if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
+@@ -824,27 +838,34 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
+ 	u16                 frq_lock, signal = 0;
+ 	int                 rc;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	mutex_lock(&priv->lock);
+ 
+ 	/* Sync Lock Indicator */
+ 	rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
+-	if (rc < 0 || frq_lock == 0)
++	if (rc < 0)
+ 		goto ret;
+ 
+-	/* Frequency is locked. Return signal quality */
++	/* Frequency is locked */
++	if (frq_lock == 1)
++		signal = 32768;
+ 
+ 	/* Get SNR of the video signal */
+ 	rc = xc2028_get_reg(priv, 0x0040, &signal);
+ 	if (rc < 0)
+-		signal = -frq_lock;
++		goto ret;
++
++	/* Use both frq_lock and signal to generate the result */
++	signal = signal || ((signal & 0x07) << 12);
+ 
+ ret:
+ 	mutex_unlock(&priv->lock);
+ 
+ 	*strength = signal;
+ 
++	tuner_dbg("signal strength is %d\n", signal);
++
+ 	return rc;
+ }
+ 
+@@ -861,7 +882,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
+ 	unsigned char	   buf[4];
+ 	u32		   div, offset = 0;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	mutex_lock(&priv->lock);
+ 
+@@ -906,9 +927,11 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
+ 	if (rc < 0)
+ 		goto ret;
+ 
+-	rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
+-	if (rc < 0)
+-		goto ret;
++	/* Return code shouldn't be checked.
++	   The reset CLK is needed only with tm6000.
++	   Driver should work fine even if this fails.
++	 */
++	priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
+ 
+ 	msleep(10);
+ 
+@@ -942,7 +965,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
+ 	struct xc2028_data *priv = fe->tuner_priv;
+ 	unsigned int       type=0;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	if (p->mode == V4L2_TUNER_RADIO) {
+ 		type |= FM;
+@@ -975,7 +998,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
+ 	fe_bandwidth_t     bw = BANDWIDTH_8_MHZ;
+ 	u16                demod = 0;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	if (priv->ctrl.d2633)
+ 		type |= D2633;
+@@ -1040,33 +1063,12 @@ static int xc2028_set_params(struct dvb_frontend *fe,
+ 				T_DIGITAL_TV, type, 0, demod);
+ }
+ 
+-static int xc2028_sleep(struct dvb_frontend *fe)
+-{
+-	struct xc2028_data *priv = fe->tuner_priv;
+-	int rc = 0;
+-
+-	tuner_dbg("%s called\n", __FUNCTION__);
+-
+-	mutex_lock(&priv->lock);
+-
+-	if (priv->firm_version < 0x0202)
+-		rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
+-	else
+-		rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
+-
+-	priv->cur_fw.type = 0;	/* need firmware reload */
+-
+-	mutex_unlock(&priv->lock);
+-
+-	return rc;
+-}
+-
+ 
+ static int xc2028_dvb_release(struct dvb_frontend *fe)
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	mutex_lock(&xc2028_list_mutex);
+ 
+@@ -1091,7 +1093,7 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+ {
+ 	struct xc2028_data *priv = fe->tuner_priv;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	*frequency = priv->frequency;
+ 
+@@ -1104,25 +1106,25 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
+ 	struct xc2028_ctrl *p    = priv_cfg;
+ 	int                 rc   = 0;
+ 
+-	tuner_dbg("%s called\n", __FUNCTION__);
++	tuner_dbg("%s called\n", __func__);
+ 
+ 	mutex_lock(&priv->lock);
+ 
+-	kfree(priv->ctrl.fname);
+-	free_firmware(priv);
+-
+ 	memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
+-	priv->ctrl.fname = NULL;
++	if (priv->ctrl.max_len < 9)
++		priv->ctrl.max_len = 13;
+ 
+ 	if (p->fname) {
++		if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
++			kfree(priv->ctrl.fname);
++			free_firmware(priv);
++		}
++
+ 		priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
+ 		if (priv->ctrl.fname == NULL)
+ 			rc = -ENOMEM;
+ 	}
+ 
+-	if (priv->ctrl.max_len < 9)
+-		priv->ctrl.max_len = 13;
+-
+ 	mutex_unlock(&priv->lock);
+ 
+ 	return rc;
+@@ -1142,8 +1144,6 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
+ 	.get_frequency     = xc2028_get_frequency,
+ 	.get_rf_strength   = xc2028_signal,
+ 	.set_params        = xc2028_set_params,
+-	.sleep             = xc2028_sleep,
+-
+ };
+ 
+ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+@@ -1153,23 +1153,29 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+ 	void               *video_dev;
+ 
+ 	if (debug)
+-		printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n");
++		printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
+ 
+-	if (NULL == cfg || NULL == cfg->video_dev)
++	if (NULL == cfg)
+ 		return NULL;
+ 
+ 	if (!fe) {
+-		printk(KERN_ERR PREFIX ": No frontend!\n");
++		printk(KERN_ERR "xc2028: No frontend!\n");
+ 		return NULL;
+ 	}
+ 
+-	video_dev = cfg->video_dev;
++	video_dev = cfg->i2c_adap->algo_data;
++
++	if (debug)
++		printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
+ 
+ 	mutex_lock(&xc2028_list_mutex);
+ 
+ 	list_for_each_entry(priv, &xc2028_list, xc2028_list) {
+-		if (priv->video_dev == cfg->video_dev) {
++		if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
+ 			video_dev = NULL;
++			if (debug)
++				printk(KERN_DEBUG "xc2028: reusing device\n");
++
+ 			break;
+ 		}
+ 	}
+@@ -1183,6 +1189,8 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+ 
+ 		priv->i2c_props.addr = cfg->i2c_addr;
+ 		priv->i2c_props.adap = cfg->i2c_adap;
++		priv->i2c_props.name = "xc2028";
++
+ 		priv->video_dev = video_dev;
+ 		priv->tuner_callback = cfg->callback;
+ 		priv->ctrl.max_len = 13;
+@@ -1195,6 +1203,9 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+ 	fe->tuner_priv = priv;
+ 	priv->count++;
+ 
++	if (debug)
++		printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
++
+ 	memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
+ 	       sizeof(xc2028_dvb_tuner_ops));
+ 
+diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h
+index 3eb8420..fc2f132 100644
+--- a/drivers/media/video/tuner-xc2028.h
++++ b/drivers/media/video/tuner-xc2028.h
+@@ -1,6 +1,6 @@
+ /* tuner-xc2028
+  *
+- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
+  * This code is placed under the terms of the GNU General Public License v2
+  */
+ 
+@@ -12,7 +12,7 @@
+ #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
+ 
+ /*      Dmoduler		IF (kHz) */
+-#define	XC3028_FE_DEFAULT	0
++#define	XC3028_FE_DEFAULT	0		/* Don't load SCODE */
+ #define XC3028_FE_LG60		6000
+ #define	XC3028_FE_ATI638	6380
+ #define	XC3028_FE_OREN538	5380
+@@ -55,7 +55,7 @@ static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+ 						 struct xc2028_config *cfg)
+ {
+ 	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+-	       __FUNCTION__);
++	       __func__);
+ 	return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
+index 01ebcec..f29a2cd 100644
+--- a/drivers/media/video/tvaudio.c
++++ b/drivers/media/video/tvaudio.c
+@@ -38,7 +38,7 @@
+ /* ---------------------------------------------------------------------- */
+ /* insmod args                                                            */
+ 
+-static int debug = 0;	/* insmod parameter */
++static int debug;	/* insmod parameter */
+ module_param(debug, int, 0644);
+ 
+ MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
+@@ -1235,11 +1235,11 @@ static int tda9850  = 1;
+ static int tda9855  = 1;
+ static int tda9873  = 1;
+ static int tda9874a = 1;
+-static int tea6300  = 0;  /* address clash with msp34xx */
+-static int tea6320  = 0;  /* address clash with msp34xx */
++static int tea6300;	/* default 0 - address clash with msp34xx */
++static int tea6320;	/* default 0 - address clash with msp34xx */
+ static int tea6420  = 1;
+ static int pic16c54 = 1;
+-static int ta8874z  = 0;  /* address clash with tda9840 */
++static int ta8874z;	/* default 0 - address clash with tda9840 */
+ 
+ module_param(tda8425, int, 0444);
+ module_param(tda9840, int, 0444);
+diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
+index dc0da44..3cf8a8e 100644
+--- a/drivers/media/video/tveeprom.c
++++ b/drivers/media/video/tveeprom.c
+@@ -745,109 +745,6 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
+ }
+ EXPORT_SYMBOL(tveeprom_read);
+ 
+-/* ----------------------------------------------------------------------- */
+-/* needed for ivtv.sf.net at the moment.  Should go away in the long       */
+-/* run, just call the exported tveeprom_* directly, there is no point in   */
+-/* using the indirect way via i2c_driver->command()                        */
+-
+-static unsigned short normal_i2c[] = {
+-	0xa0 >> 1,
+-	I2C_CLIENT_END,
+-};
+-
+-I2C_CLIENT_INSMOD;
+-
+-static struct i2c_driver i2c_driver_tveeprom;
+-
+-static int
+-tveeprom_command(struct i2c_client *client,
+-		 unsigned int       cmd,
+-		 void              *arg)
+-{
+-	struct tveeprom eeprom;
+-	u32 *eeprom_props = arg;
+-	u8 *buf;
+-
+-	switch (cmd) {
+-	case 0:
+-		buf = kzalloc(256, GFP_KERNEL);
+-		tveeprom_read(client, buf, 256);
+-		tveeprom_hauppauge_analog(client, &eeprom, buf);
+-		kfree(buf);
+-		eeprom_props[0] = eeprom.tuner_type;
+-		eeprom_props[1] = eeprom.tuner_formats;
+-		eeprom_props[2] = eeprom.model;
+-		eeprom_props[3] = eeprom.revision;
+-		eeprom_props[4] = eeprom.has_radio;
+-		break;
+-	default:
+-		return -EINVAL;
+-	}
+-	return 0;
+-}
+-
+-static int
+-tveeprom_detect_client(struct i2c_adapter *adapter,
+-		       int                 address,
+-		       int                 kind)
+-{
+-	struct i2c_client *client;
+-
+-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+-	if (NULL == client)
+-		return -ENOMEM;
+-	client->addr = address;
+-	client->adapter = adapter;
+-	client->driver = &i2c_driver_tveeprom;
+-	snprintf(client->name, sizeof(client->name), "tveeprom");
+-	i2c_attach_client(client);
+-
+-	return 0;
+-}
+-
+-static int
+-tveeprom_attach_adapter(struct i2c_adapter *adapter)
+-{
+-	if (adapter->class & I2C_CLASS_TV_ANALOG)
+-		return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
+-	return 0;
+-}
+-
+-static int
+-tveeprom_detach_client(struct i2c_client *client)
+-{
+-	int err;
+-
+-	err = i2c_detach_client(client);
+-	if (err < 0)
+-		return err;
+-	kfree(client);
+-	return 0;
+-}
+-
+-static struct i2c_driver i2c_driver_tveeprom = {
+-	.driver = {
+-		.name   = "tveeprom",
+-	},
+-	.id             = I2C_DRIVERID_TVEEPROM,
+-	.attach_adapter = tveeprom_attach_adapter,
+-	.detach_client  = tveeprom_detach_client,
+-	.command        = tveeprom_command,
+-};
+-
+-static int __init tveeprom_init(void)
+-{
+-	return i2c_add_driver(&i2c_driver_tveeprom);
+-}
+-
+-static void __exit tveeprom_exit(void)
+-{
+-	i2c_del_driver(&i2c_driver_tveeprom);
+-}
+-
+-module_init(tveeprom_init);
+-module_exit(tveeprom_exit);
+-
+ /*
+  * Local variables:
+  * c-basic-offset: 8
+diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
+index b6e24e7..6a3af10 100644
+--- a/drivers/media/video/tvp5150.c
++++ b/drivers/media/video/tvp5150.c
+@@ -27,7 +27,7 @@ static unsigned short normal_i2c[] = {
+ 
+ I2C_CLIENT_INSMOD;
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c
+index 14db95e..59166b7 100644
+--- a/drivers/media/video/usbvideo/ibmcam.c
++++ b/drivers/media/video/usbvideo/ibmcam.c
+@@ -121,7 +121,7 @@ static int init_model2_yb = -1;
+ 
+ /* 01.01.08 - Added for RCA video in support -LO */
+ /* Settings for camera model 3 */
+-static int init_model3_input = 0;
++static int init_model3_input;
+ 
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
+@@ -802,6 +802,21 @@ static enum ParseState ibmcam_model2_320x240_parse_lines(
+ 		return scan_Continue;
+ }
+ 
++/*
++ * ibmcam_model3_parse_lines()
++ *
++ * | Even lines |     Odd Lines       |
++ * -----------------------------------|
++ * |YYY........Y|UYVYUYVY.........UYVY|
++ * |YYY........Y|UYVYUYVY.........UYVY|
++ * |............|.....................|
++ * |YYY........Y|UYVYUYVY.........UYVY|
++ * |------------+---------------------|
++ *
++ * There is one (U, V) chroma pair for every four luma (Y) values.  This
++ * function reads a pair of lines at a time and obtains missing chroma values
++ * from adjacent pixels.
++ */
+ static enum ParseState ibmcam_model3_parse_lines(
+ 	struct uvd *uvd,
+ 	struct usbvideo_frame *frame,
+@@ -816,6 +831,7 @@ static enum ParseState ibmcam_model3_parse_lines(
+ 	const int ccm = 128; /* Color correction median - see below */
+ 	int i, u, v, rw, data_w=0, data_h=0, color_corr;
+ 	static unsigned char lineBuffer[640*3];
++	int line;
+ 
+ 	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
+ 	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
+@@ -869,15 +885,15 @@ static enum ParseState ibmcam_model3_parse_lines(
+ 		return scan_NextFrame;
+ 	}
+ 
+-	/* Make sure there's enough data for the entire line */
+-	len = 3 * data_w; /* <y-data> <uv-data> */
++	/* Make sure that lineBuffer can store two lines of data */
++	len = 3 * data_w; /* <y-data> <uyvy-data> */
+ 	assert(len <= sizeof(lineBuffer));
+ 
+-	/* Make sure there's enough data for the entire line */
++	/* Make sure there's enough data for two lines */
+ 	if (RingQueue_GetLength(&uvd->dp) < len)
+ 		return scan_Out;
+ 
+-	/* Suck one line out of the ring queue */
++	/* Suck two lines of data out of the ring queue */
+ 	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
+ 
+ 	data = lineBuffer;
+@@ -887,15 +903,23 @@ static enum ParseState ibmcam_model3_parse_lines(
+ 	rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
+ 	RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
+ 
+-	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
+-		int y, rv, gv, bv;	/* RGB components */
++	/* Iterate over two lines. */
++	for (line = 0; line < 2; line++) {
++		for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
++			int y;
++			int rv, gv, bv;	/* RGB components */
+ 
+-		if (i < data_w) {
+-			y = data[i];	/* Luminosity is the first line */
++			if (i >= data_w) {
++				RGB24_PUTPIXEL(frame, i, rw, 0, 0, 0);
++				continue;
++			}
++
++			/* first line is YYY...Y; second is UYVY...UYVY */
++			y = data[(line == 0) ? i : (i*2 + 1)];
+ 
+ 			/* Apply static color correction */
+-			u = color[i*2] + hue_corr;
+-			v = color[i*2 + 1] + hue2_corr;
++			u = color[(i/2)*4] + hue_corr;
++			v = color[(i/2)*4 + 2] + hue2_corr;
+ 
+ 			/* Apply color correction */
+ 			if (color_corr != 0) {
+@@ -903,13 +927,21 @@ static enum ParseState ibmcam_model3_parse_lines(
+ 				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
+ 				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
+ 			}
+-		} else
+-			y = 0, u = v = 128;
+ 
+-		YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
+-		RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */
++
++			YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
++			RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv);  /* No deinterlacing */
++		}
++
++		/* Check for the end of requested data */
++		if (rw == 0)
++			break;
++
++		/* Prepare for the second line */
++		rw--;
++		data = lineBuffer + data_w;
+ 	}
+-	frame->deinterlace = Deinterlace_FillEvenLines;
++	frame->deinterlace = Deinterlace_None;
+ 
+ 	/*
+ 	 * Account for number of bytes that we wrote into output V4L frame.
+diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
+index 719b17c..1c18028 100644
+--- a/drivers/media/video/usbvideo/konicawc.c
++++ b/drivers/media/video/usbvideo/konicawc.c
+@@ -57,11 +57,11 @@ static struct usbvideo *cams;
+ static int debug;
+ #define DEBUG(n, format, arg...) \
+ 	if (n <= debug) {	 \
+-		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
++		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
+ 	}
+ #else
+ #define DEBUG(n, arg...)
+-static const int debug = 0;
++static const int debug;
+ #endif
+ 
+ 
+diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
+index a2acba0..32e536e 100644
+--- a/drivers/media/video/usbvideo/quickcam_messenger.c
++++ b/drivers/media/video/usbvideo/quickcam_messenger.c
+@@ -46,11 +46,11 @@
+ static int debug;
+ #define DEBUG(n, format, arg...) \
+ 	if (n <= debug) {	 \
+-		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
++		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
+ 	}
+ #else
+ #define DEBUG(n, arg...)
+-static const int debug = 0;
++static const int debug;
+ #endif
+ 
+ #define DRIVER_VERSION "v0.01"
+diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c
+index 95453c1..9544e64 100644
+--- a/drivers/media/video/usbvideo/ultracam.c
++++ b/drivers/media/video/usbvideo/ultracam.c
+@@ -28,9 +28,9 @@ typedef struct {
+ 
+ static struct usbvideo *cams = NULL;
+ 
+-static int debug = 0;
++static int debug;
+ 
+-static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
++static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
+ 
+ static const int min_canvasWidth  = 8;
+ static const int min_canvasHeight = 4;
+diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
+index 5d363be..4128ee2 100644
+--- a/drivers/media/video/usbvideo/usbvideo.c
++++ b/drivers/media/video/usbvideo/usbvideo.c
+@@ -522,14 +522,14 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
+ 	struct usbvideo_frame *frame;
+ 	int num_cell = 0;
+ 	int scan_length = 0;
+-	static int num_pass = 0;
++	static int num_pass;
+ 
+ 	if (uvd == NULL) {
+-		err("%s: uvd == NULL", __FUNCTION__);
++		err("%s: uvd == NULL", __func__);
+ 		return;
+ 	}
+ 	if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
+-		err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe);
++		err("%s: uvd->curframe=%d.", __func__, uvd->curframe);
+ 		return;
+ 	}
+ 
+@@ -630,15 +630,15 @@ EXPORT_SYMBOL(usbvideo_HexDump);
+ static int usbvideo_ClientIncModCount(struct uvd *uvd)
+ {
+ 	if (uvd == NULL) {
+-		err("%s: uvd == NULL", __FUNCTION__);
++		err("%s: uvd == NULL", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (uvd->handle == NULL) {
+-		err("%s: uvd->handle == NULL", __FUNCTION__);
++		err("%s: uvd->handle == NULL", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (!try_module_get(uvd->handle->md_module)) {
+-		err("%s: try_module_get() == 0", __FUNCTION__);
++		err("%s: try_module_get() == 0", __func__);
+ 		return -ENODEV;
+ 	}
+ 	return 0;
+@@ -647,15 +647,15 @@ static int usbvideo_ClientIncModCount(struct uvd *uvd)
+ static void usbvideo_ClientDecModCount(struct uvd *uvd)
+ {
+ 	if (uvd == NULL) {
+-		err("%s: uvd == NULL", __FUNCTION__);
++		err("%s: uvd == NULL", __func__);
+ 		return;
+ 	}
+ 	if (uvd->handle == NULL) {
+-		err("%s: uvd->handle == NULL", __FUNCTION__);
++		err("%s: uvd->handle == NULL", __func__);
+ 		return;
+ 	}
+ 	if (uvd->handle->md_module == NULL) {
+-		err("%s: uvd->handle->md_module == NULL", __FUNCTION__);
++		err("%s: uvd->handle->md_module == NULL", __func__);
+ 		return;
+ 	}
+ 	module_put(uvd->handle->md_module);
+@@ -675,13 +675,13 @@ int usbvideo_register(
+ 
+ 	/* Check parameters for sanity */
+ 	if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
+-		err("%s: Illegal call", __FUNCTION__);
++		err("%s: Illegal call", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	/* Check registration callback - must be set! */
+ 	if (cbTbl->probe == NULL) {
+-		err("%s: probe() is required!", __FUNCTION__);
++		err("%s: probe() is required!", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -692,7 +692,7 @@ int usbvideo_register(
+ 		return -ENOMEM;
+ 	}
+ 	dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
+-	    __FUNCTION__, cams, base_size, num_cams);
++	    __func__, cams, base_size, num_cams);
+ 
+ 	/* Copy callbacks, apply defaults for those that are not set */
+ 	memmove(&cams->cb, cbTbl, sizeof(cams->cb));
+@@ -721,7 +721,7 @@ int usbvideo_register(
+ 			up->user_data = kmalloc(up->user_size, GFP_KERNEL);
+ 			if (up->user_data == NULL) {
+ 				err("%s: Failed to allocate user_data (%d. bytes)",
+-				    __FUNCTION__, up->user_size);
++				    __func__, up->user_size);
+ 				while (i) {
+ 					up = &cams->cam[--i];
+ 					kfree(up->user_data);
+@@ -730,7 +730,7 @@ int usbvideo_register(
+ 				return -ENOMEM;
+ 			}
+ 			dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
+-			     __FUNCTION__, i, up->user_data, up->user_size);
++			     __func__, i, up->user_data, up->user_size);
+ 		}
+ 	}
+ 
+@@ -776,19 +776,19 @@ void usbvideo_Deregister(struct usbvideo **pCams)
+ 	int i;
+ 
+ 	if (pCams == NULL) {
+-		err("%s: pCams == NULL", __FUNCTION__);
++		err("%s: pCams == NULL", __func__);
+ 		return;
+ 	}
+ 	cams = *pCams;
+ 	if (cams == NULL) {
+-		err("%s: cams == NULL", __FUNCTION__);
++		err("%s: cams == NULL", __func__);
+ 		return;
+ 	}
+ 
+-	dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName);
++	dbg("%s: Deregistering %s driver.", __func__, cams->drvName);
+ 	usb_deregister(&cams->usbdrv);
+ 
+-	dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras);
++	dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras);
+ 	for (i=0; i < cams->num_cameras; i++) {
+ 		struct uvd *up = &cams->cam[i];
+ 		int warning = 0;
+@@ -802,16 +802,16 @@ void usbvideo_Deregister(struct usbvideo **pCams)
+ 		}
+ 		if (warning) {
+ 			err("%s: Warning: user_data=$%p user_size=%d.",
+-			    __FUNCTION__, up->user_data, up->user_size);
++			    __func__, up->user_data, up->user_size);
+ 		} else {
+ 			dbg("%s: Freeing %d. $%p->user_data=$%p",
+-			    __FUNCTION__, i, up, up->user_data);
++			    __func__, i, up, up->user_data);
+ 			kfree(up->user_data);
+ 		}
+ 	}
+ 	/* Whole array was allocated in one chunk */
+ 	dbg("%s: Freed %d uvd structures",
+-	    __FUNCTION__, cams->num_cameras);
++	    __func__, cams->num_cameras);
+ 	kfree(cams);
+ 	*pCams = NULL;
+ }
+@@ -846,7 +846,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
+ 	int i;
+ 
+ 	if (uvd == NULL) {
+-		err("%s($%p): Illegal call.", __FUNCTION__, intf);
++		err("%s($%p): Illegal call.", __func__, intf);
+ 		return;
+ 	}
+ 
+@@ -854,7 +854,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
+ 
+ 	usbvideo_ClientIncModCount(uvd);
+ 	if (uvd->debug > 0)
+-		info("%s(%p.)", __FUNCTION__, intf);
++		info("%s(%p.)", __func__, intf);
+ 
+ 	mutex_lock(&uvd->lock);
+ 	uvd->remove_pending = 1; /* Now all ISO data will be ignored */
+@@ -870,10 +870,10 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
+ 
+ 	video_unregister_device(&uvd->vdev);
+ 	if (uvd->debug > 0)
+-		info("%s: Video unregistered.", __FUNCTION__);
++		info("%s: Video unregistered.", __func__);
+ 
+ 	if (uvd->user)
+-		info("%s: In use, disconnect pending.", __FUNCTION__);
++		info("%s: In use, disconnect pending.", __func__);
+ 	else
+ 		usbvideo_CameraRelease(uvd);
+ 	mutex_unlock(&uvd->lock);
+@@ -895,7 +895,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
+ static void usbvideo_CameraRelease(struct uvd *uvd)
+ {
+ 	if (uvd == NULL) {
+-		err("%s: Illegal call", __FUNCTION__);
++		err("%s: Illegal call", __func__);
+ 		return;
+ 	}
+ 
+@@ -946,7 +946,9 @@ static const struct file_operations usbvideo_fops = {
+ 	.read =   usbvideo_v4l_read,
+ 	.mmap =   usbvideo_v4l_mmap,
+ 	.ioctl =  usbvideo_v4l_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.llseek = no_llseek,
+ };
+ static const struct video_device usbvideo_template = {
+@@ -1011,18 +1013,18 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
+ 	char tmp1[20], tmp2[20];	/* Buffers for printing */
+ 
+ 	if (uvd == NULL) {
+-		err("%s: Illegal call.", __FUNCTION__);
++		err("%s: Illegal call.", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (uvd->video_endp == 0) {
+-		info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__);
++		info("%s: No video endpoint specified; data pump disabled.", __func__);
+ 	}
+ 	if (uvd->paletteBits == 0) {
+-		err("%s: No palettes specified!", __FUNCTION__);
++		err("%s: No palettes specified!", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (uvd->defaultPalette == 0) {
+-		info("%s: No default palette!", __FUNCTION__);
++		info("%s: No default palette!", __func__);
+ 	}
+ 
+ 	uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
+@@ -1032,19 +1034,19 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
+ 
+ 	if (uvd->debug > 0) {
+ 		info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
+-		     __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits);
++		     __func__, uvd->iface, uvd->video_endp, uvd->paletteBits);
+ 	}
+ 	if (uvd->dev == NULL) {
+-		err("%s: uvd->dev == NULL", __FUNCTION__);
++		err("%s: uvd->dev == NULL", __func__);
+ 		return -EINVAL;
+ 	}
+-	uvd->vdev.dev=&(uvd->dev->dev);
++	uvd->vdev.dev = &uvd->dev->dev;
+ 	if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+-		err("%s: video_register_device failed", __FUNCTION__);
++		err("%s: video_register_device failed", __func__);
+ 		return -EPIPE;
+ 	}
+ 	if (uvd->debug > 1) {
+-		info("%s: video_register_device() successful", __FUNCTION__);
++		info("%s: video_register_device() successful", __func__);
+ 	}
+ 
+ 	info("%s on /dev/video%d: canvas=%s videosize=%s",
+@@ -1111,14 +1113,14 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+ 	int i, errCode = 0;
+ 
+ 	if (uvd->debug > 1)
+-		info("%s($%p)", __FUNCTION__, dev);
++		info("%s($%p)", __func__, dev);
+ 
+ 	if (0 < usbvideo_ClientIncModCount(uvd))
+ 		return -ENODEV;
+ 	mutex_lock(&uvd->lock);
+ 
+ 	if (uvd->user) {
+-		err("%s: Someone tried to open an already opened device!", __FUNCTION__);
++		err("%s: Someone tried to open an already opened device!", __func__);
+ 		errCode = -EBUSY;
+ 	} else {
+ 		/* Clear statistics */
+@@ -1134,7 +1136,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+ 		RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
+ 		if ((uvd->fbuf == NULL) ||
+ 		    (!RingQueue_IsAllocated(&uvd->dp))) {
+-			err("%s: Failed to allocate fbuf or dp", __FUNCTION__);
++			err("%s: Failed to allocate fbuf or dp", __func__);
+ 			errCode = -ENOMEM;
+ 		} else {
+ 			/* Allocate all buffers */
+@@ -1178,19 +1180,19 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+ 		if (errCode == 0) {
+ 			if (VALID_CALLBACK(uvd, setupOnOpen)) {
+ 				if (uvd->debug > 1)
+-					info("%s: setupOnOpen callback", __FUNCTION__);
++					info("%s: setupOnOpen callback", __func__);
+ 				errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
+ 				if (errCode < 0) {
+ 					err("%s: setupOnOpen callback failed (%d.).",
+-					    __FUNCTION__, errCode);
++					    __func__, errCode);
+ 				} else if (uvd->debug > 1) {
+-					info("%s: setupOnOpen callback successful", __FUNCTION__);
++					info("%s: setupOnOpen callback successful", __func__);
+ 				}
+ 			}
+ 			if (errCode == 0) {
+ 				uvd->settingsAdjusted = 0;
+ 				if (uvd->debug > 1)
+-					info("%s: Open succeeded.", __FUNCTION__);
++					info("%s: Open succeeded.", __func__);
+ 				uvd->user++;
+ 				file->private_data = uvd;
+ 			}
+@@ -1200,7 +1202,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+ 	if (errCode != 0)
+ 		usbvideo_ClientDecModCount(uvd);
+ 	if (uvd->debug > 0)
+-		info("%s: Returning %d.", __FUNCTION__, errCode);
++		info("%s: Returning %d.", __func__, errCode);
+ 	return errCode;
+ }
+ 
+@@ -1223,7 +1225,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
+ 	int i;
+ 
+ 	if (uvd->debug > 1)
+-		info("%s($%p)", __FUNCTION__, dev);
++		info("%s($%p)", __func__, dev);
+ 
+ 	mutex_lock(&uvd->lock);
+ 	GET_CALLBACK(uvd, stopDataPump)(uvd);
+@@ -1250,7 +1252,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
+ 	usbvideo_ClientDecModCount(uvd);
+ 
+ 	if (uvd->debug > 1)
+-		info("%s: Completed.", __FUNCTION__);
++		info("%s: Completed.", __func__);
+ 	file->private_data = NULL;
+ 	return 0;
+ }
+@@ -1504,7 +1506,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
+ 		return -EFAULT;
+ 
+ 	if (uvd->debug >= 1)
+-		info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock);
++		info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock);
+ 
+ 	mutex_lock(&uvd->lock);
+ 
+@@ -1551,7 +1553,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
+ 	 */
+ 	if (frmx == -1) {
+ 		if (uvd->defaultPalette == 0) {
+-			err("%s: No default palette; don't know what to do!", __FUNCTION__);
++			err("%s: No default palette; don't know what to do!", __func__);
+ 			count = -EFAULT;
+ 			goto read_done;
+ 		}
+@@ -1623,7 +1625,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
+ 	frame->seqRead_Index += count;
+ 	if (uvd->debug >= 1) {
+ 		err("%s: {copy} count used=%Zd, new seqRead_Index=%ld",
+-			__FUNCTION__, count, frame->seqRead_Index);
++			__func__, count, frame->seqRead_Index);
+ 	}
+ 
+ 	/* Finally check if the frame is done with and "release" it */
+@@ -1634,7 +1636,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
+ 		/* Mark it as available to be used again. */
+ 		uvd->frame[frmx].frameState = FrameState_Unused;
+ 		if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
+-			err("%s: usbvideo_NewFrame failed.", __FUNCTION__);
++			err("%s: usbvideo_NewFrame failed.", __func__);
+ 		}
+ 	}
+ read_done:
+@@ -1741,10 +1743,10 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
+ 	int i, errFlag;
+ 
+ 	if (uvd->debug > 1)
+-		info("%s($%p)", __FUNCTION__, uvd);
++		info("%s($%p)", __func__, uvd);
+ 
+ 	if (!CAMERA_IS_OPERATIONAL(uvd)) {
+-		err("%s: Camera is not operational", __FUNCTION__);
++		err("%s: Camera is not operational", __func__);
+ 		return -EFAULT;
+ 	}
+ 	uvd->curframe = -1;
+@@ -1752,14 +1754,14 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
+ 	/* Alternate interface 1 is is the biggest frame size */
+ 	i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
+ 	if (i < 0) {
+-		err("%s: usb_set_interface error", __FUNCTION__);
++		err("%s: usb_set_interface error", __func__);
+ 		uvd->last_error = i;
+ 		return -EBUSY;
+ 	}
+ 	if (VALID_CALLBACK(uvd, videoStart))
+ 		GET_CALLBACK(uvd, videoStart)(uvd);
+ 	else
+-		err("%s: videoStart not set", __FUNCTION__);
++		err("%s: videoStart not set", __func__);
+ 
+ 	/* We double buffer the Iso lists */
+ 	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+@@ -1784,12 +1786,12 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
+ 	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+ 		errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
+ 		if (errFlag)
+-			err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag);
++			err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag);
+ 	}
+ 
+ 	uvd->streaming = 1;
+ 	if (uvd->debug > 1)
+-		info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp);
++		info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp);
+ 	return 0;
+ }
+ 
+@@ -1811,14 +1813,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
+ 		return;
+ 
+ 	if (uvd->debug > 1)
+-		info("%s($%p)", __FUNCTION__, uvd);
++		info("%s($%p)", __func__, uvd);
+ 
+ 	/* Unschedule all of the iso td's */
+ 	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+ 		usb_kill_urb(uvd->sbuf[i].urb);
+ 	}
+ 	if (uvd->debug > 1)
+-		info("%s: streaming=0", __FUNCTION__);
++		info("%s: streaming=0", __func__);
+ 	uvd->streaming = 0;
+ 
+ 	if (!uvd->remove_pending) {
+@@ -1826,12 +1828,12 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
+ 		if (VALID_CALLBACK(uvd, videoStop))
+ 			GET_CALLBACK(uvd, videoStop)(uvd);
+ 		else
+-			err("%s: videoStop not set", __FUNCTION__);
++			err("%s: videoStop not set", __func__);
+ 
+ 		/* Set packet size to 0 */
+ 		j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
+ 		if (j < 0) {
+-			err("%s: usb_set_interface() error %d.", __FUNCTION__, j);
++			err("%s: usb_set_interface() error %d.", __func__, j);
+ 			uvd->last_error = j;
+ 		}
+ 	}
+@@ -1955,12 +1957,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ 	struct usbvideo_frame *frame = &uvd->frame[frameNum];
+ 
+ 	if (uvd->debug >= 2)
+-		info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum);
++		info("%s($%p,%d.)", __func__, uvd, frameNum);
+ 
+ 	switch (frame->frameState) {
+ 	case FrameState_Unused:
+ 		if (uvd->debug >= 2)
+-			info("%s: FrameState_Unused", __FUNCTION__);
++			info("%s: FrameState_Unused", __func__);
+ 		return -EINVAL;
+ 	case FrameState_Ready:
+ 	case FrameState_Grabbing:
+@@ -1970,7 +1972,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ 	redo:
+ 		if (!CAMERA_IS_OPERATIONAL(uvd)) {
+ 			if (uvd->debug >= 2)
+-				info("%s: Camera is not operational (1)", __FUNCTION__);
++				info("%s: Camera is not operational (1)", __func__);
+ 			return -EIO;
+ 		}
+ 		ntries = 0;
+@@ -1979,24 +1981,24 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ 			signalPending = signal_pending(current);
+ 			if (!CAMERA_IS_OPERATIONAL(uvd)) {
+ 				if (uvd->debug >= 2)
+-					info("%s: Camera is not operational (2)", __FUNCTION__);
++					info("%s: Camera is not operational (2)", __func__);
+ 				return -EIO;
+ 			}
+ 			assert(uvd->fbuf != NULL);
+ 			if (signalPending) {
+ 				if (uvd->debug >= 2)
+-					info("%s: Signal=$%08x", __FUNCTION__, signalPending);
++					info("%s: Signal=$%08x", __func__, signalPending);
+ 				if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
+ 					usbvideo_TestPattern(uvd, 1, 0);
+ 					uvd->curframe = -1;
+ 					uvd->stats.frame_num++;
+ 					if (uvd->debug >= 2)
+-						info("%s: Forced test pattern screen", __FUNCTION__);
++						info("%s: Forced test pattern screen", __func__);
+ 					return 0;
+ 				} else {
+ 					/* Standard answer: Interrupted! */
+ 					if (uvd->debug >= 2)
+-						info("%s: Interrupted!", __FUNCTION__);
++						info("%s: Interrupted!", __func__);
+ 					return -EINTR;
+ 				}
+ 			} else {
+@@ -2006,17 +2008,17 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ 				else if (VALID_CALLBACK(uvd, processData))
+ 					GET_CALLBACK(uvd, processData)(uvd, frame);
+ 				else
+-					err("%s: processData not set", __FUNCTION__);
++					err("%s: processData not set", __func__);
+ 			}
+ 		} while (frame->frameState == FrameState_Grabbing);
+ 		if (uvd->debug >= 2) {
+ 			info("%s: Grabbing done; state=%d. (%lu. bytes)",
+-			     __FUNCTION__, frame->frameState, frame->seqRead_Length);
++			     __func__, frame->frameState, frame->seqRead_Length);
+ 		}
+ 		if (frame->frameState == FrameState_Error) {
+ 			int ret = usbvideo_NewFrame(uvd, frameNum);
+ 			if (ret < 0) {
+-				err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret);
++				err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret);
+ 				return ret;
+ 			}
+ 			goto redo;
+@@ -2048,7 +2050,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ 		}
+ 		frame->frameState = FrameState_Done_Hold;
+ 		if (uvd->debug >= 2)
+-			info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__);
++			info("%s: Entered FrameState_Done_Hold state.", __func__);
+ 		return 0;
+ 
+ 	case FrameState_Done_Hold:
+@@ -2059,12 +2061,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ 		 * it will be released back into the wild to roam freely.
+ 		 */
+ 		if (uvd->debug >= 2)
+-			info("%s: FrameState_Done_Hold state.", __FUNCTION__);
++			info("%s: FrameState_Done_Hold state.", __func__);
+ 		return 0;
+ 	}
+ 
+ 	/* Catch-all for other cases. We shall not be here. */
+-	err("%s: Invalid state %d.", __FUNCTION__, frame->frameState);
++	err("%s: Invalid state %d.", __func__, frame->frameState);
+ 	frame->frameState = FrameState_Unused;
+ 	return 0;
+ }
+@@ -2160,7 +2162,7 @@ static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
+ 	const int ccm = 128; /* Color correction median - see below */
+ 
+ 	if ((uvd == NULL) || (frame == NULL)) {
+-		err("%s: Illegal call.", __FUNCTION__);
++		err("%s: Illegal call.", __func__);
+ 		return;
+ 	}
+ 	adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
+diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
+index da1ba02..6481935 100644
+--- a/drivers/media/video/usbvideo/vicam.c
++++ b/drivers/media/video/usbvideo/vicam.c
+@@ -48,7 +48,7 @@
+ // #define VICAM_DEBUG
+ 
+ #ifdef VICAM_DEBUG
+-#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
++#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args)
+ #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
+ #else
+ #define DBG(fmn,args...) do {} while(0)
+@@ -1066,7 +1066,9 @@ static const struct file_operations vicam_fops = {
+ 	.read		= vicam_read,
+ 	.mmap		= vicam_mmap,
+ 	.ioctl		= vicam_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek		= no_llseek,
+ };
+ 
+diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
+index 56775ab..a9c5e5a 100644
+--- a/drivers/media/video/usbvision/usbvision-core.c
++++ b/drivers/media/video/usbvision/usbvision-core.c
+@@ -53,19 +53,21 @@
+ 
+ #include "usbvision.h"
+ 
+-static unsigned int core_debug = 0;
++static unsigned int core_debug;
+ module_param(core_debug,int,0644);
+ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+ 
+-static unsigned int force_testpattern = 0;
++static unsigned int force_testpattern;
+ module_param(force_testpattern,int,0644);
+ MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]");
+ 
+-static int adjustCompression = 1;			// Set the compression to be adaptive
++static int adjustCompression = 1;	/* Set the compression to be adaptive */
+ module_param(adjustCompression, int, 0444);
+ MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device.  Default: 1 (On)");
+ 
+-static int SwitchSVideoInput = 0;			// To help people with Black and White output with using s-video input.  Some cables and input device are wired differently.
++/* To help people with Black and White output with using s-video input.
++ * Some cables and input device are wired differently. */
++static int SwitchSVideoInput;
+ module_param(SwitchSVideoInput, int, 0444);
+ MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input.  Some cables and input device are wired differently. Default: 0 (Off)");
+ 
+@@ -82,8 +84,10 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]");
+ 
+ 
+ #ifdef USBVISION_DEBUG
+-	#define PDEBUG(level, fmt, args...) \
+-		if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
++	#define PDEBUG(level, fmt, args...) { \
++		if (core_debug & (level)) \
++			info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
++	}
+ #else
+ 	#define PDEBUG(level, fmt, args...) do {} while(0)
+ #endif
+@@ -384,7 +388,7 @@ int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
+ 	scratch_reset(usbvision);
+ 	if(usbvision->scratch == NULL) {
+ 		err("%s: unable to allocate %d bytes for scratch",
+-		    __FUNCTION__, scratch_buf_size);
++		    __func__, scratch_buf_size);
+ 		return -ENOMEM;
+ 	}
+ 	return 0;
+@@ -418,7 +422,7 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision,
+ 	unsigned char *f;
+ 	int num_cell = 0;
+ 	int scan_length = 0;
+-	static int num_pass = 0;
++	static int num_pass;
+ 
+ 	if (usbvision == NULL) {
+ 		printk(KERN_ERR "%s: usbvision == NULL\n", proc);
+@@ -493,7 +497,8 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
+ 	int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
+ 	usbvision->IntraFrameBuffer = vmalloc_32(IFB_size);
+ 	if (usbvision->IntraFrameBuffer == NULL) {
+-		err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size);
++		err("%s: unable to allocate %d for compr. frame buffer",
++		    __func__, IFB_size);
+ 		return -ENOMEM;
+ 	}
+ 	return 0;
+@@ -1430,7 +1435,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision,
+ 	}
+ #if ENABLE_HEXDUMP
+ 	if (totlen > 0) {
+-		static int foo = 0;
++		static int foo;
+ 		if (foo < 1) {
+ 			printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);
+ 			usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);
+@@ -1516,7 +1521,7 @@ static void usbvision_isocIrq(struct urb *urb)
+ 
+ 	if(errCode) {
+ 		err("%s: usb_submit_urb failed: error %d",
+-		    __FUNCTION__, errCode);
++		    __func__, errCode);
+ 	}
+ 
+ 	return;
+@@ -1547,7 +1552,7 @@ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg)
+ 				0, (__u16) reg, buffer, 1, HZ);
+ 
+ 	if (errCode < 0) {
+-		err("%s: failed: error %d", __FUNCTION__, errCode);
++		err("%s: failed: error %d", __func__, errCode);
+ 		return errCode;
+ 	}
+ 	return buffer[0];
+@@ -1575,7 +1580,7 @@ int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
+ 				USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
+ 
+ 	if (errCode < 0) {
+-		err("%s: failed: error %d", __FUNCTION__, errCode);
++		err("%s: failed: error %d", __func__, errCode);
+ 	}
+ 	return errCode;
+ }
+@@ -1851,7 +1856,7 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width,
+ 				 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
+ 
+ 		if (errCode < 0) {
+-			err("%s failed: error %d", __FUNCTION__, errCode);
++			err("%s failed: error %d", __func__, errCode);
+ 			return errCode;
+ 		}
+ 		usbvision->curwidth = usbvision->stretch_width * UsbWidth;
+@@ -2237,7 +2242,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision)
+ 			     (__u16) USBVISION_DRM_PRM1, value, 8, HZ);
+ 
+ 	if (rc < 0) {
+-		err("%sERROR=%d", __FUNCTION__, rc);
++		err("%sERROR=%d", __func__, rc);
+ 		return rc;
+ 	}
+ 
+@@ -2486,7 +2491,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
+ 
+ 		urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
+ 		if (urb == NULL) {
+-			err("%s: usb_alloc_urb() failed", __FUNCTION__);
++			err("%s: usb_alloc_urb() failed", __func__);
+ 			return -ENOMEM;
+ 		}
+ 		usbvision->sbuf[bufIdx].urb = urb;
+@@ -2520,13 +2525,13 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
+ 						 GFP_KERNEL);
+ 		if (errCode) {
+ 			err("%s: usb_submit_urb(%d) failed: error %d",
+-			    __FUNCTION__, bufIdx, errCode);
++			    __func__, bufIdx, errCode);
+ 		}
+ 	}
+ 
+ 	usbvision->streaming = Stream_Idle;
+ 	PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
+-	       __FUNCTION__,
++	       __func__,
+ 	       usbvision->video_endp);
+ 	return 0;
+ }
+@@ -2560,7 +2565,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
+ 	}
+ 
+ 
+-	PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__);
++	PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__);
+ 	usbvision->streaming = Stream_Off;
+ 
+ 	if (!usbvision->remove_pending) {
+@@ -2571,7 +2576,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
+ 					    usbvision->ifaceAlt);
+ 		if (errCode < 0) {
+ 			err("%s: usb_set_interface() failed: error %d",
+-			    __FUNCTION__, errCode);
++			    __func__, errCode);
+ 			usbvision->last_error = errCode;
+ 		}
+ 		regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
+index aabc42c..e2274d7 100644
+--- a/drivers/media/video/usbvision/usbvision-i2c.c
++++ b/drivers/media/video/usbvision/usbvision-i2c.c
+@@ -40,13 +40,15 @@
+ 
+ #define DBG_I2C		1<<0
+ 
+-static int i2c_debug = 0;
++static int i2c_debug;
+ 
+ module_param (i2c_debug, int, 0644);			// debug_i2c_usb mode of the device driver
+ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+ 
+-#define PDEBUG(level, fmt, args...) \
+-		if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
++#define PDEBUG(level, fmt, args...) { \
++		if (i2c_debug & (level)) \
++			info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
++	}
+ 
+ static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
+ 			    short len);
+diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
+index df52f8a..d97261a 100644
+--- a/drivers/media/video/usbvision/usbvision-video.c
++++ b/drivers/media/video/usbvision/usbvision-video.c
+@@ -97,10 +97,10 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
+ 
+ 
+ #ifdef USBVISION_DEBUG
+-	#define PDEBUG(level, fmt, args...) \
++	#define PDEBUG(level, fmt, args...) { \
+ 		if (video_debug & (level)) \
+-			info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ ,\
+-				## args)
++			info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
++	}
+ #else
+ 	#define PDEBUG(level, fmt, args...) do {} while(0)
+ #endif
+@@ -115,7 +115,7 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
+ 
+ 
+ /* sequential number of usbvision device */
+-static int usbvision_nr = 0;
++static int usbvision_nr;
+ 
+ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
+ 	{ 1, 1,  8, V4L2_PIX_FMT_GREY    , "GREY" },
+@@ -135,7 +135,7 @@ static void usbvision_release(struct usb_usbvision *usbvision);
+ /* Set the default format for ISOC endpoint */
+ static int isocMode = ISOC_MODE_COMPRESS;
+ /* Set the default Debug Mode of the device driver */
+-static int video_debug = 0;
++static int video_debug;
+ /* Set the default device to power on at startup */
+ static int PowerOnAtOpen = 1;
+ /* Sequential Number of Video Device */
+@@ -343,7 +343,7 @@ static void usbvision_create_sysfs(struct video_device *vdev)
+ 			return;
+ 	} while (0);
+ 
+-	err("%s error: %d\n", __FUNCTION__, res);
++	err("%s error: %d\n", __func__, res);
+ }
+ 
+ static void usbvision_remove_sysfs(struct video_device *vdev)
+@@ -490,7 +490,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
+ 	mutex_unlock(&usbvision->lock);
+ 
+ 	if (usbvision->remove_pending) {
+-		printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
++		printk(KERN_INFO "%s: Final disconnect\n", __func__);
+ 		usbvision_release(usbvision);
+ 	}
+ 
+@@ -522,7 +522,7 @@ static int vidioc_g_register (struct file *file, void *priv,
+ 	errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
+ 	if (errCode < 0) {
+ 		err("%s: VIDIOC_DBG_G_REGISTER failed: error %d",
+-		    __FUNCTION__, errCode);
++		    __func__, errCode);
+ 		return errCode;
+ 	}
+ 	reg->val = errCode;
+@@ -543,7 +543,7 @@ static int vidioc_s_register (struct file *file, void *priv,
+ 	errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
+ 	if (errCode < 0) {
+ 		err("%s: VIDIOC_DBG_S_REGISTER failed: error %d",
+-		    __FUNCTION__, errCode);
++		    __func__, errCode);
+ 		return errCode;
+ 	}
+ 	return 0;
+@@ -1102,7 +1102,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
+ 	int ret,i;
+ 	struct usbvision_frame *frame;
+ 
+-	PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__,
++	PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__,
+ 	       (unsigned long)count, noblock);
+ 
+ 	if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
+@@ -1171,7 +1171,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
+ 	}
+ 
+ 	PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld",
+-	       __FUNCTION__,
++	       __func__,
+ 	       frame->index, frame->bytes_read, frame->scanlength);
+ 
+ 	/* copy bytes to user space; we allow for partials reads */
+@@ -1184,7 +1184,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
+ 
+ 	frame->bytes_read += count;
+ 	PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld",
+-	       __FUNCTION__,
++	       __func__,
+ 	       (unsigned long)count, frame->bytes_read);
+ 
+ 	/* For now, forget the frame if it has not been read in one shot. */
+@@ -1269,12 +1269,12 @@ static int usbvision_radio_open(struct inode *inode, struct file *file)
+ 		(struct usb_usbvision *) video_get_drvdata(dev);
+ 	int errCode = 0;
+ 
+-	PDEBUG(DBG_IO, "%s:", __FUNCTION__);
++	PDEBUG(DBG_IO, "%s:", __func__);
+ 
+ 	mutex_lock(&usbvision->lock);
+ 
+ 	if (usbvision->user) {
+-		err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__);
++		err("%s: Someone tried to open an already opened USBVision Radio!", __func__);
+ 		errCode = -EBUSY;
+ 	}
+ 	else {
+@@ -1342,7 +1342,7 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
+ 	mutex_unlock(&usbvision->lock);
+ 
+ 	if (usbvision->remove_pending) {
+-		printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
++		printk(KERN_INFO "%s: Final disconnect\n", __func__);
+ 		usbvision_release(usbvision);
+ 	}
+ 
+@@ -1507,7 +1507,7 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
+ 	struct video_device *vdev;
+ 
+ 	if (usb_dev == NULL) {
+-		err("%s: usbvision->dev is not set", __FUNCTION__);
++		err("%s: usbvision->dev is not set", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -1759,7 +1759,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
+ 		PDEBUG(DBG_PROBE, "model out of bounds %d",model);
+ 		return -ENODEV;
+ 	}
+-	printk(KERN_INFO "%s: %s found\n", __FUNCTION__,
++	printk(KERN_INFO "%s: %s found\n", __func__,
+ 				usbvision_device_data[model].ModelString);
+ 
+ 	if (usbvision_device_data[model].Interface >= 0) {
+@@ -1771,20 +1771,20 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
+ 	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+ 	    USB_ENDPOINT_XFER_ISOC) {
+ 		err("%s: interface %d. has non-ISO endpoint!",
+-		    __FUNCTION__, ifnum);
++		    __func__, ifnum);
+ 		err("%s: Endpoint attributes %d",
+-		    __FUNCTION__, endpoint->bmAttributes);
++		    __func__, endpoint->bmAttributes);
+ 		return -ENODEV;
+ 	}
+ 	if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
+ 	    USB_DIR_OUT) {
+ 		err("%s: interface %d. has ISO OUT endpoint!",
+-		    __FUNCTION__, ifnum);
++		    __func__, ifnum);
+ 		return -ENODEV;
+ 	}
+ 
+ 	if ((usbvision = usbvision_alloc(dev)) == NULL) {
+-		err("%s: couldn't allocate USBVision struct", __FUNCTION__);
++		err("%s: couldn't allocate USBVision struct", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -1868,7 +1868,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
+ 	PDEBUG(DBG_PROBE, "");
+ 
+ 	if (usbvision == NULL) {
+-		err("%s: usb_get_intfdata() failed", __FUNCTION__);
++		err("%s: usb_get_intfdata() failed", __func__);
+ 		return;
+ 	}
+ 	usb_set_intfdata (intf, NULL);
+@@ -1891,7 +1891,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
+ 
+ 	if (usbvision->user) {
+ 		printk(KERN_INFO "%s: In use, disconnect pending\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		wake_up_interruptible(&usbvision->wait_frame);
+ 		wake_up_interruptible(&usbvision->wait_stream);
+ 	} else {
+diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
+index 50e1ff9..a0f6c60 100644
+--- a/drivers/media/video/v4l1-compat.c
++++ b/drivers/media/video/v4l1-compat.c
+@@ -39,15 +39,18 @@
+ #include <linux/kmod.h>
+ #endif
+ 
+-static unsigned int debug  = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug,"enable debug messages");
++MODULE_PARM_DESC(debug, "enable debug messages");
+ MODULE_AUTHOR("Bill Dirks");
+ MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
+ MODULE_LICENSE("GPL");
+ 
+-#define dprintk(fmt, arg...)	if (debug) \
+-	printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg)
++#define dprintk(fmt, arg...) \
++	do { \
++		if (debug) \
++			printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg);\
++	} while (0)
+ 
+ /*
+  *	I O C T L   T R A N S L A T I O N
+@@ -69,14 +72,12 @@ get_v4l_control(struct inode            *inode,
+ 	qctrl2.id = cid;
+ 	err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
+ 	if (err < 0)
+-		dprintk("VIDIOC_QUERYCTRL: %d\n",err);
+-	if (err == 0 &&
+-	    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
+-	{
++		dprintk("VIDIOC_QUERYCTRL: %d\n", err);
++	if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) {
+ 		ctrl2.id = qctrl2.id;
+ 		err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
+ 		if (err < 0) {
+-			dprintk("VIDIOC_G_CTRL: %d\n",err);
++			dprintk("VIDIOC_G_CTRL: %d\n", err);
+ 			return 0;
+ 		}
+ 		return ((ctrl2.value - qctrl2.minimum) * 65535
+@@ -100,11 +101,10 @@ set_v4l_control(struct inode            *inode,
+ 	qctrl2.id = cid;
+ 	err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
+ 	if (err < 0)
+-		dprintk("VIDIOC_QUERYCTRL: %d\n",err);
++		dprintk("VIDIOC_QUERYCTRL: %d\n", err);
+ 	if (err == 0 &&
+ 	    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
+-	    !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED))
+-	{
++	    !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) {
+ 		if (value < 0)
+ 			value = 0;
+ 		if (value > 65535)
+@@ -119,14 +119,14 @@ set_v4l_control(struct inode            *inode,
+ 		ctrl2.value += qctrl2.minimum;
+ 		err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
+ 		if (err < 0)
+-			dprintk("VIDIOC_S_CTRL: %d\n",err);
++			dprintk("VIDIOC_S_CTRL: %d\n", err);
+ 	}
+ 	return 0;
+ }
+ 
+ /* ----------------------------------------------------------------- */
+ 
+-const static unsigned int palette2pixelformat[] = {
++static const unsigned int palette2pixelformat[] = {
+ 	[VIDEO_PALETTE_GREY]    = V4L2_PIX_FMT_GREY,
+ 	[VIDEO_PALETTE_RGB555]  = V4L2_PIX_FMT_RGB555,
+ 	[VIDEO_PALETTE_RGB565]  = V4L2_PIX_FMT_RGB565,
+@@ -157,8 +157,7 @@ static unsigned int __attribute_const__
+ pixelformat_to_palette(unsigned int pixelformat)
+ {
+ 	int	palette = 0;
+-	switch (pixelformat)
+-	{
++	switch (pixelformat) {
+ 	case V4L2_PIX_FMT_GREY:
+ 		palette = VIDEO_PALETTE_GREY;
+ 		break;
+@@ -200,14 +199,13 @@ pixelformat_to_palette(unsigned int pixelformat)
+ 
+ /* ----------------------------------------------------------------- */
+ 
+-static int poll_one(struct file *file)
++static int poll_one(struct file *file, struct poll_wqueues *pwq)
+ {
+ 	int retval = 1;
+ 	poll_table *table;
+-	struct poll_wqueues pwq;
+ 
+-	poll_initwait(&pwq);
+-	table = &pwq.pt;
++	poll_initwait(pwq);
++	table = &pwq->pt;
+ 	for (;;) {
+ 		int mask;
+ 		set_current_state(TASK_INTERRUPTIBLE);
+@@ -222,878 +220,1073 @@ static int poll_one(struct file *file)
+ 		schedule();
+ 	}
+ 	set_current_state(TASK_RUNNING);
+-	poll_freewait(&pwq);
++	poll_freewait(pwq);
+ 	return retval;
+ }
+ 
+-static int count_inputs(struct inode         *inode,
+-			struct file          *file,
+-			v4l2_kioctl          drv)
++static int count_inputs(
++			struct inode *inode,
++			struct file *file,
++			v4l2_kioctl drv)
+ {
+ 	struct v4l2_input input2;
+ 	int i;
+ 
+ 	for (i = 0;; i++) {
+-		memset(&input2,0,sizeof(input2));
++		memset(&input2, 0, sizeof(input2));
+ 		input2.index = i;
+-		if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2))
++		if (0 != drv(inode, file, VIDIOC_ENUMINPUT, &input2))
+ 			break;
+ 	}
+ 	return i;
+ }
+ 
+-static int check_size(struct inode         *inode,
+-		      struct file          *file,
+-		      v4l2_kioctl          drv,
+-		      int *maxw, int *maxh)
++static int check_size(
++		struct inode *inode,
++		struct file *file,
++		v4l2_kioctl drv,
++		int *maxw,
++		int *maxh)
+ {
+ 	struct v4l2_fmtdesc desc2;
+ 	struct v4l2_format  fmt2;
+ 
+-	memset(&desc2,0,sizeof(desc2));
+-	memset(&fmt2,0,sizeof(fmt2));
++	memset(&desc2, 0, sizeof(desc2));
++	memset(&fmt2, 0, sizeof(fmt2));
+ 
+ 	desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-	if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))
++	if (0 != drv(inode, file, VIDIOC_ENUM_FMT, &desc2))
+ 		goto done;
+ 
+ 	fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ 	fmt2.fmt.pix.width       = 10000;
+ 	fmt2.fmt.pix.height      = 10000;
+ 	fmt2.fmt.pix.pixelformat = desc2.pixelformat;
+-	if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2))
++	if (0 != drv(inode, file, VIDIOC_TRY_FMT, &fmt2))
+ 		goto done;
+ 
+ 	*maxw = fmt2.fmt.pix.width;
+ 	*maxh = fmt2.fmt.pix.height;
+ 
+- done:
++done:
+ 	return 0;
+ }
+ 
+ /* ----------------------------------------------------------------- */
+ 
+-/*
+- *	This function is exported.
+- */
+-int
+-v4l_compat_translate_ioctl(struct inode         *inode,
+-			   struct file		*file,
+-			   int			cmd,
+-			   void			*arg,
+-			   v4l2_kioctl          drv)
++static noinline int v4l1_compat_get_capabilities(
++					struct video_capability *cap,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
+ {
+-	struct v4l2_capability  *cap2 = NULL;
+-	struct v4l2_format	*fmt2 = NULL;
+-	enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-
+-	struct v4l2_framebuffer fbuf2;
+-	struct v4l2_input	input2;
+-	struct v4l2_tuner	tun2;
+-	struct v4l2_standard	std2;
+-	struct v4l2_frequency   freq2;
+-	struct v4l2_audio	aud2;
+-	struct v4l2_queryctrl	qctrl2;
+-	struct v4l2_buffer	buf2;
+-	v4l2_std_id    		sid;
+-	int i, err = 0;
+-
+-	switch (cmd) {
+-	case VIDIOCGCAP:	/* capability */
+-	{
+-		struct video_capability *cap = arg;
+-
+-		cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
+-		if (!cap2) {
+-			err = -ENOMEM;
+-			break;
+-		}
+-		memset(cap, 0, sizeof(*cap));
+-		memset(&fbuf2, 0, sizeof(fbuf2));
++	int err;
++	struct v4l2_framebuffer fbuf;
++	struct v4l2_capability *cap2;
++
++	cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
++	if (!cap2) {
++		err = -ENOMEM;
++		return err;
++	}
++	memset(cap, 0, sizeof(*cap));
++	memset(&fbuf, 0, sizeof(fbuf));
+ 
+-		err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
++	err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
++	if (err < 0) {
++		dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err);
++		goto done;
++	}
++	if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
++		err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+ 		if (err < 0) {
+-			dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
+-			break;
++			dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err);
++			memset(&fbuf, 0, sizeof(fbuf));
+ 		}
+-		if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
+-			err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
+-			if (err < 0) {
+-				dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
+-				memset(&fbuf2, 0, sizeof(fbuf2));
+-			}
+-			err = 0;
+-		}
+-
+-		memcpy(cap->name, cap2->card,
+-		       min(sizeof(cap->name), sizeof(cap2->card)));
+-		cap->name[sizeof(cap->name) - 1] = 0;
+-		if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
+-			cap->type |= VID_TYPE_CAPTURE;
+-		if (cap2->capabilities & V4L2_CAP_TUNER)
+-			cap->type |= VID_TYPE_TUNER;
+-		if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
+-			cap->type |= VID_TYPE_TELETEXT;
+-		if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
+-			cap->type |= VID_TYPE_OVERLAY;
+-		if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
+-			cap->type |= VID_TYPE_CLIPPING;
+-
+-		cap->channels  = count_inputs(inode,file,drv);
+-		check_size(inode,file,drv,
+-			   &cap->maxwidth,&cap->maxheight);
+-		cap->audios    =  0; /* FIXME */
+-		cap->minwidth  = 48; /* FIXME */
+-		cap->minheight = 32; /* FIXME */
+-		break;
++		err = 0;
+ 	}
+-	case VIDIOCGFBUF: /*  get frame buffer  */
+-	{
+-		struct video_buffer	*buffer = arg;
+ 
+-		memset(buffer, 0, sizeof(*buffer));
+-		memset(&fbuf2, 0, sizeof(fbuf2));
++	memcpy(cap->name, cap2->card,
++	       min(sizeof(cap->name), sizeof(cap2->card)));
++	cap->name[sizeof(cap->name) - 1] = 0;
++	if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
++		cap->type |= VID_TYPE_CAPTURE;
++	if (cap2->capabilities & V4L2_CAP_TUNER)
++		cap->type |= VID_TYPE_TUNER;
++	if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
++		cap->type |= VID_TYPE_TELETEXT;
++	if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
++		cap->type |= VID_TYPE_OVERLAY;
++	if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
++		cap->type |= VID_TYPE_CLIPPING;
++
++	cap->channels  = count_inputs(inode, file, drv);
++	check_size(inode, file, drv,
++		   &cap->maxwidth, &cap->maxheight);
++	cap->audios    =  0; /* FIXME */
++	cap->minwidth  = 48; /* FIXME */
++	cap->minheight = 32; /* FIXME */
++
++done:
++	kfree(cap2);
++	return err;
++}
+ 
+-		err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
+-		if (err < 0) {
+-			dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
+-			break;
+-		}
+-		buffer->base   = fbuf2.base;
+-		buffer->height = fbuf2.fmt.height;
+-		buffer->width  = fbuf2.fmt.width;
++static noinline int v4l1_compat_get_frame_buffer(
++					struct video_buffer *buffer,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_framebuffer fbuf;
+ 
+-		switch (fbuf2.fmt.pixelformat) {
+-		case V4L2_PIX_FMT_RGB332:
+-			buffer->depth = 8;
+-			break;
+-		case V4L2_PIX_FMT_RGB555:
+-			buffer->depth = 15;
+-			break;
+-		case V4L2_PIX_FMT_RGB565:
+-			buffer->depth = 16;
+-			break;
+-		case V4L2_PIX_FMT_BGR24:
+-			buffer->depth = 24;
+-			break;
+-		case V4L2_PIX_FMT_BGR32:
+-			buffer->depth = 32;
+-			break;
+-		default:
+-			buffer->depth = 0;
+-		}
+-		if (fbuf2.fmt.bytesperline) {
+-			buffer->bytesperline = fbuf2.fmt.bytesperline;
+-			if (!buffer->depth && buffer->width)
+-				buffer->depth   = ((fbuf2.fmt.bytesperline<<3)
+-						  + (buffer->width-1) )
+-						  /buffer->width;
+-		} else {
+-			buffer->bytesperline =
+-				(buffer->width * buffer->depth + 7) & 7;
+-			buffer->bytesperline >>= 3;
+-		}
++	memset(buffer, 0, sizeof(*buffer));
++	memset(&fbuf, 0, sizeof(fbuf));
++
++	err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
++	if (err < 0) {
++		dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err);
++		goto done;
++	}
++	buffer->base   = fbuf.base;
++	buffer->height = fbuf.fmt.height;
++	buffer->width  = fbuf.fmt.width;
++
++	switch (fbuf.fmt.pixelformat) {
++	case V4L2_PIX_FMT_RGB332:
++		buffer->depth = 8;
++		break;
++	case V4L2_PIX_FMT_RGB555:
++		buffer->depth = 15;
++		break;
++	case V4L2_PIX_FMT_RGB565:
++		buffer->depth = 16;
++		break;
++	case V4L2_PIX_FMT_BGR24:
++		buffer->depth = 24;
++		break;
++	case V4L2_PIX_FMT_BGR32:
++		buffer->depth = 32;
+ 		break;
++	default:
++		buffer->depth = 0;
+ 	}
+-	case VIDIOCSFBUF: /*  set frame buffer  */
+-	{
+-		struct video_buffer	*buffer = arg;
+-
+-		memset(&fbuf2, 0, sizeof(fbuf2));
+-		fbuf2.base       = buffer->base;
+-		fbuf2.fmt.height = buffer->height;
+-		fbuf2.fmt.width  = buffer->width;
+-		switch (buffer->depth) {
+-		case 8:
+-			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
+-			break;
+-		case 15:
+-			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
+-			break;
+-		case 16:
+-			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
+-			break;
+-		case 24:
+-			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
+-			break;
+-		case 32:
+-			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
+-			break;
+-		}
+-		fbuf2.fmt.bytesperline = buffer->bytesperline;
+-		err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
+-		if (err < 0)
+-			dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);
++	if (fbuf.fmt.bytesperline) {
++		buffer->bytesperline = fbuf.fmt.bytesperline;
++		if (!buffer->depth && buffer->width)
++			buffer->depth   = ((fbuf.fmt.bytesperline<<3)
++					  + (buffer->width-1))
++					  / buffer->width;
++	} else {
++		buffer->bytesperline =
++			(buffer->width * buffer->depth + 7) & 7;
++		buffer->bytesperline >>= 3;
++	}
++done:
++	return err;
++}
++
++static noinline int v4l1_compat_set_frame_buffer(
++					struct video_buffer *buffer,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_framebuffer fbuf;
++
++	memset(&fbuf, 0, sizeof(fbuf));
++	fbuf.base       = buffer->base;
++	fbuf.fmt.height = buffer->height;
++	fbuf.fmt.width  = buffer->width;
++	switch (buffer->depth) {
++	case 8:
++		fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
++		break;
++	case 15:
++		fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
++		break;
++	case 16:
++		fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
++		break;
++	case 24:
++		fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
++		break;
++	case 32:
++		fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
+ 		break;
+ 	}
+-	case VIDIOCGWIN: /*  get window or capture dimensions  */
+-	{
+-		struct video_window	*win = arg;
++	fbuf.fmt.bytesperline = buffer->bytesperline;
++	err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
++	if (err < 0)
++		dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err);
++	return err;
++}
+ 
+-		fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+-		if (!fmt2) {
+-			err = -ENOMEM;
+-			break;
+-		}
+-		memset(win,0,sizeof(*win));
++static noinline int v4l1_compat_get_win_cap_dimensions(
++					struct video_window *win,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_format *fmt;
+ 
+-		fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+-		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+-		if (err < 0)
+-			dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
+-		if (err == 0) {
+-			win->x         = fmt2->fmt.win.w.left;
+-			win->y         = fmt2->fmt.win.w.top;
+-			win->width     = fmt2->fmt.win.w.width;
+-			win->height    = fmt2->fmt.win.w.height;
+-			win->chromakey = fmt2->fmt.win.chromakey;
+-			win->clips     = NULL;
+-			win->clipcount = 0;
+-			break;
+-		}
++	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++	if (!fmt) {
++		err = -ENOMEM;
++		return err;
++	}
++	memset(win, 0, sizeof(*win));
+ 
+-		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+-		if (err < 0) {
+-			dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
+-			break;
+-		}
+-		win->x         = 0;
+-		win->y         = 0;
+-		win->width     = fmt2->fmt.pix.width;
+-		win->height    = fmt2->fmt.pix.height;
+-		win->chromakey = 0;
++	fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
++	err = drv(inode, file, VIDIOC_G_FMT, fmt);
++	if (err < 0)
++		dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err);
++	if (err == 0) {
++		win->x         = fmt->fmt.win.w.left;
++		win->y         = fmt->fmt.win.w.top;
++		win->width     = fmt->fmt.win.w.width;
++		win->height    = fmt->fmt.win.w.height;
++		win->chromakey = fmt->fmt.win.chromakey;
+ 		win->clips     = NULL;
+ 		win->clipcount = 0;
+-		break;
++		goto done;
+ 	}
+-	case VIDIOCSWIN: /*  set window and/or capture dimensions  */
+-	{
+-		struct video_window	*win = arg;
+-		int err1,err2;
+ 
+-		fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+-		if (!fmt2) {
+-			err = -ENOMEM;
+-			break;
+-		}
+-		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
+-		err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
+-		if (err1 < 0)
+-			dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
+-		if (err1 == 0) {
+-			fmt2->fmt.pix.width  = win->width;
+-			fmt2->fmt.pix.height = win->height;
+-			fmt2->fmt.pix.field  = V4L2_FIELD_ANY;
+-			fmt2->fmt.pix.bytesperline = 0;
+-			err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+-			if (err < 0)
+-				dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
+-					err);
+-			win->width  = fmt2->fmt.pix.width;
+-			win->height = fmt2->fmt.pix.height;
+-		}
++	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	err = drv(inode, file, VIDIOC_G_FMT, fmt);
++	if (err < 0) {
++		dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err);
++		goto done;
++	}
++	win->x         = 0;
++	win->y         = 0;
++	win->width     = fmt->fmt.pix.width;
++	win->height    = fmt->fmt.pix.height;
++	win->chromakey = 0;
++	win->clips     = NULL;
++	win->clipcount = 0;
++done:
++	kfree(fmt);
++	return err;
++}
+ 
+-		memset(fmt2,0,sizeof(*fmt2));
+-		fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+-		fmt2->fmt.win.w.left    = win->x;
+-		fmt2->fmt.win.w.top     = win->y;
+-		fmt2->fmt.win.w.width   = win->width;
+-		fmt2->fmt.win.w.height  = win->height;
+-		fmt2->fmt.win.chromakey = win->chromakey;
+-		fmt2->fmt.win.clips     = (void __user *)win->clips;
+-		fmt2->fmt.win.clipcount = win->clipcount;
+-		err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
+-		if (err2 < 0)
+-			dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);
+-
+-		if (err1 != 0 && err2 != 0)
+-			err = err1;
+-		break;
++static noinline int v4l1_compat_set_win_cap_dimensions(
++					struct video_window *win,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err, err1, err2;
++	struct v4l2_format *fmt;
++
++	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++	if (!fmt) {
++		err = -ENOMEM;
++		return err;
+ 	}
+-	case VIDIOCCAPTURE: /*  turn on/off preview  */
+-	{
+-		int *on = arg;
+-
+-		if (0 == *on) {
+-			/* dirty hack time.  But v4l1 has no STREAMOFF
+-			 * equivalent in the API, and this one at
+-			 * least comes close ... */
+-			drv(inode, file, VIDIOC_STREAMOFF, &captype);
+-		}
+-		err = drv(inode, file, VIDIOC_OVERLAY, arg);
++	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	drv(inode, file, VIDIOC_STREAMOFF, &fmt->type);
++	err1 = drv(inode, file, VIDIOC_G_FMT, fmt);
++	if (err1 < 0)
++		dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1);
++	if (err1 == 0) {
++		fmt->fmt.pix.width  = win->width;
++		fmt->fmt.pix.height = win->height;
++		fmt->fmt.pix.field  = V4L2_FIELD_ANY;
++		fmt->fmt.pix.bytesperline = 0;
++		err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ 		if (err < 0)
+-			dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err);
+-		break;
++			dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
++				err);
++		win->width  = fmt->fmt.pix.width;
++		win->height = fmt->fmt.pix.height;
+ 	}
+-	case VIDIOCGCHAN: /*  get input information  */
+-	{
+-		struct video_channel	*chan = arg;
+ 
+-		memset(&input2,0,sizeof(input2));
+-		input2.index = chan->channel;
+-		err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
+-		if (err < 0) {
+-			dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
+-				"channel=%d err=%d\n",chan->channel,err);
+-			break;
+-		}
+-		chan->channel = input2.index;
+-		memcpy(chan->name, input2.name,
+-		       min(sizeof(chan->name), sizeof(input2.name)));
+-		chan->name[sizeof(chan->name) - 1] = 0;
+-		chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
+-		chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
+-		switch (input2.type) {
+-		case V4L2_INPUT_TYPE_TUNER:
+-			chan->type = VIDEO_TYPE_TV;
+-			break;
+-		default:
+-		case V4L2_INPUT_TYPE_CAMERA:
+-			chan->type = VIDEO_TYPE_CAMERA;
+-			break;
+-		}
+-		chan->norm = 0;
+-		err = drv(inode, file, VIDIOC_G_STD, &sid);
+-		if (err < 0)
+-			dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err);
+-		if (err == 0) {
+-			if (sid & V4L2_STD_PAL)
+-				chan->norm = VIDEO_MODE_PAL;
+-			if (sid & V4L2_STD_NTSC)
+-				chan->norm = VIDEO_MODE_NTSC;
+-			if (sid & V4L2_STD_SECAM)
+-				chan->norm = VIDEO_MODE_SECAM;
+-		}
+-		break;
+-	}
+-	case VIDIOCSCHAN: /*  set input  */
+-	{
+-		struct video_channel *chan = arg;
++	memset(fmt, 0, sizeof(*fmt));
++	fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
++	fmt->fmt.win.w.left    = win->x;
++	fmt->fmt.win.w.top     = win->y;
++	fmt->fmt.win.w.width   = win->width;
++	fmt->fmt.win.w.height  = win->height;
++	fmt->fmt.win.chromakey = win->chromakey;
++	fmt->fmt.win.clips     = (void __user *)win->clips;
++	fmt->fmt.win.clipcount = win->clipcount;
++	err2 = drv(inode, file, VIDIOC_S_FMT, fmt);
++	if (err2 < 0)
++		dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2);
++
++	if (err1 != 0 && err2 != 0)
++		err = err1;
++	else
++		err = 0;
++	kfree(fmt);
++	return err;
++}
+ 
+-		sid = 0;
+-		err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
+-		if (err < 0)
+-			dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
+-		switch (chan->norm) {
+-		case VIDEO_MODE_PAL:
+-			sid = V4L2_STD_PAL;
+-			break;
+-		case VIDEO_MODE_NTSC:
+-			sid = V4L2_STD_NTSC;
+-			break;
+-		case VIDEO_MODE_SECAM:
+-			sid = V4L2_STD_SECAM;
+-			break;
+-		}
+-		if (0 != sid) {
+-			err = drv(inode, file, VIDIOC_S_STD, &sid);
+-			if (err < 0)
+-				dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
+-		}
+-		break;
++static noinline int v4l1_compat_turn_preview_on_off(
++					int *on,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++
++	if (0 == *on) {
++		/* dirty hack time.  But v4l1 has no STREAMOFF
++		 * equivalent in the API, and this one at
++		 * least comes close ... */
++		drv(inode, file, VIDIOC_STREAMOFF, &captype);
+ 	}
+-	case VIDIOCGPICT: /*  get tone controls & partial capture format  */
+-	{
+-		struct video_picture	*pict = arg;
+-
+-		fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+-		if (!fmt2) {
+-			err = -ENOMEM;
+-			break;
+-		}
++	err = drv(inode, file, VIDIOC_OVERLAY, on);
++	if (err < 0)
++		dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err);
++	return err;
++}
+ 
+-		pict->brightness = get_v4l_control(inode, file,
+-						   V4L2_CID_BRIGHTNESS,drv);
+-		pict->hue = get_v4l_control(inode, file,
+-					    V4L2_CID_HUE, drv);
+-		pict->contrast = get_v4l_control(inode, file,
+-						 V4L2_CID_CONTRAST, drv);
+-		pict->colour = get_v4l_control(inode, file,
+-					       V4L2_CID_SATURATION, drv);
+-		pict->whiteness = get_v4l_control(inode, file,
+-						  V4L2_CID_WHITENESS, drv);
+-
+-		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+-		if (err < 0) {
+-			dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
+-			break;
+-		}
++static noinline int v4l1_compat_get_input_info(
++					struct video_channel *chan,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_input	input2;
++	v4l2_std_id    		sid;
+ 
+-		pict->depth   = ((fmt2->fmt.pix.bytesperline<<3)
+-				 + (fmt2->fmt.pix.width-1) )
+-				 /fmt2->fmt.pix.width;
+-		pict->palette = pixelformat_to_palette(
+-			fmt2->fmt.pix.pixelformat);
++	memset(&input2, 0, sizeof(input2));
++	input2.index = chan->channel;
++	err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
++	if (err < 0) {
++		dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
++			"channel=%d err=%d\n", chan->channel, err);
++		goto done;
++	}
++	chan->channel = input2.index;
++	memcpy(chan->name, input2.name,
++	       min(sizeof(chan->name), sizeof(input2.name)));
++	chan->name[sizeof(chan->name) - 1] = 0;
++	chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
++	chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
++	switch (input2.type) {
++	case V4L2_INPUT_TYPE_TUNER:
++		chan->type = VIDEO_TYPE_TV;
++		break;
++	default:
++	case V4L2_INPUT_TYPE_CAMERA:
++		chan->type = VIDEO_TYPE_CAMERA;
+ 		break;
+ 	}
+-	case VIDIOCSPICT: /*  set tone controls & partial capture format  */
+-	{
+-		struct video_picture	*pict = arg;
+-		int mem_err = 0, ovl_err = 0;
++	chan->norm = 0;
++	err = drv(inode, file, VIDIOC_G_STD, &sid);
++	if (err < 0)
++		dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err);
++	if (err == 0) {
++		if (sid & V4L2_STD_PAL)
++			chan->norm = VIDEO_MODE_PAL;
++		if (sid & V4L2_STD_NTSC)
++			chan->norm = VIDEO_MODE_NTSC;
++		if (sid & V4L2_STD_SECAM)
++			chan->norm = VIDEO_MODE_SECAM;
++	}
++done:
++	return err;
++}
+ 
+-		fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+-		if (!fmt2) {
+-			err = -ENOMEM;
+-			break;
+-		}
+-		memset(&fbuf2, 0, sizeof(fbuf2));
+-
+-		set_v4l_control(inode, file,
+-				V4L2_CID_BRIGHTNESS, pict->brightness, drv);
+-		set_v4l_control(inode, file,
+-				V4L2_CID_HUE, pict->hue, drv);
+-		set_v4l_control(inode, file,
+-				V4L2_CID_CONTRAST, pict->contrast, drv);
+-		set_v4l_control(inode, file,
+-				V4L2_CID_SATURATION, pict->colour, drv);
+-		set_v4l_control(inode, file,
+-				V4L2_CID_WHITENESS, pict->whiteness, drv);
+-		/*
+-		 * V4L1 uses this ioctl to set both memory capture and overlay
+-		 * pixel format, while V4L2 has two different ioctls for this.
+-		 * Some cards may not support one or the other, and may support
+-		 * different pixel formats for memory vs overlay.
+-		 */
+-
+-		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+-		/* If VIDIOC_G_FMT failed, then the driver likely doesn't
+-		   support memory capture.  Trying to set the memory capture
+-		   parameters would be pointless.  */
+-		if (err < 0) {
+-			dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
+-			mem_err = -1000;  /* didn't even try */
+-		} else if (fmt2->fmt.pix.pixelformat !=
+-			 palette_to_pixelformat(pict->palette)) {
+-			fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
+-				pict->palette);
+-			mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+-			if (mem_err < 0)
+-				dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
+-					mem_err);
+-		}
++static noinline int v4l1_compat_set_input(
++					struct video_channel *chan,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	v4l2_std_id sid = 0;
+ 
+-		err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
+-		/* If VIDIOC_G_FBUF failed, then the driver likely doesn't
+-		   support overlay.  Trying to set the overlay parameters
+-		   would be quite pointless.  */
+-		if (err < 0) {
+-			dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
+-			ovl_err = -1000;  /* didn't even try */
+-		} else if (fbuf2.fmt.pixelformat !=
+-			 palette_to_pixelformat(pict->palette)) {
+-			fbuf2.fmt.pixelformat = palette_to_pixelformat(
+-				pict->palette);
+-			ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
+-			if (ovl_err < 0)
+-				dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
+-					ovl_err);
+-		}
+-		if (ovl_err < 0 && mem_err < 0)
+-			/* ioctl failed, couldn't set either parameter */
+-			if (mem_err != -1000) {
+-			    err = mem_err;
+-			} else if (ovl_err == -EPERM) {
+-			    err = 0;
+-			} else {
+-			    err = ovl_err;
+-			}
+-		else
+-			err = 0;
++	err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
++	if (err < 0)
++		dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err);
++	switch (chan->norm) {
++	case VIDEO_MODE_PAL:
++		sid = V4L2_STD_PAL;
++		break;
++	case VIDEO_MODE_NTSC:
++		sid = V4L2_STD_NTSC;
++		break;
++	case VIDEO_MODE_SECAM:
++		sid = V4L2_STD_SECAM;
+ 		break;
+ 	}
+-	case VIDIOCGTUNER: /*  get tuner information  */
+-	{
+-		struct video_tuner	*tun = arg;
+-
+-		memset(&tun2,0,sizeof(tun2));
+-		err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+-		if (err < 0) {
+-			dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err);
+-			break;
+-		}
+-		memcpy(tun->name, tun2.name,
+-		       min(sizeof(tun->name), sizeof(tun2.name)));
+-		tun->name[sizeof(tun->name) - 1] = 0;
+-		tun->rangelow = tun2.rangelow;
+-		tun->rangehigh = tun2.rangehigh;
+-		tun->flags = 0;
+-		tun->mode = VIDEO_MODE_AUTO;
+-
+-		for (i = 0; i < 64; i++) {
+-			memset(&std2,0,sizeof(std2));
+-			std2.index = i;
+-			if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
+-				break;
+-			if (std2.id & V4L2_STD_PAL)
+-				tun->flags |= VIDEO_TUNER_PAL;
+-			if (std2.id & V4L2_STD_NTSC)
+-				tun->flags |= VIDEO_TUNER_NTSC;
+-			if (std2.id & V4L2_STD_SECAM)
+-				tun->flags |= VIDEO_TUNER_SECAM;
+-		}
+-
+-		err = drv(inode, file, VIDIOC_G_STD, &sid);
++	if (0 != sid) {
++		err = drv(inode, file, VIDIOC_S_STD, &sid);
+ 		if (err < 0)
+-			dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
+-		if (err == 0) {
+-			if (sid & V4L2_STD_PAL)
+-				tun->mode = VIDEO_MODE_PAL;
+-			if (sid & V4L2_STD_NTSC)
+-				tun->mode = VIDEO_MODE_NTSC;
+-			if (sid & V4L2_STD_SECAM)
+-				tun->mode = VIDEO_MODE_SECAM;
+-		}
+-
+-		if (tun2.capability & V4L2_TUNER_CAP_LOW)
+-			tun->flags |= VIDEO_TUNER_LOW;
+-		if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
+-			tun->flags |= VIDEO_TUNER_STEREO_ON;
+-		tun->signal = tun2.signal;
+-		break;
++			dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err);
+ 	}
+-	case VIDIOCSTUNER: /*  select a tuner input  */
+-	{
+-		struct video_tuner	*tun = arg;
+-		struct v4l2_tuner	t;
+-		memset(&t,0,sizeof(t));
+-
+-		t.index=tun->tuner;
++	return err;
++}
+ 
+-		err = drv(inode, file, VIDIOC_S_INPUT, &t);
+-		if (err < 0)
+-			dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
++static noinline int v4l1_compat_get_picture(
++					struct video_picture *pict,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_format *fmt;
+ 
+-		break;
++	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++	if (!fmt) {
++		err = -ENOMEM;
++		return err;
+ 	}
+-	case VIDIOCGFREQ: /*  get frequency  */
+-	{
+-		unsigned long *freq = arg;
+-		memset(&freq2,0,sizeof(freq2));
+ 
+-		freq2.tuner = 0;
+-		err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+-		if (err < 0)
+-			dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err);
+-		if (0 == err)
+-			*freq = freq2.frequency;
+-		break;
++	pict->brightness = get_v4l_control(inode, file,
++					   V4L2_CID_BRIGHTNESS, drv);
++	pict->hue = get_v4l_control(inode, file,
++				    V4L2_CID_HUE, drv);
++	pict->contrast = get_v4l_control(inode, file,
++					 V4L2_CID_CONTRAST, drv);
++	pict->colour = get_v4l_control(inode, file,
++				       V4L2_CID_SATURATION, drv);
++	pict->whiteness = get_v4l_control(inode, file,
++					  V4L2_CID_WHITENESS, drv);
++
++	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	err = drv(inode, file, VIDIOC_G_FMT, fmt);
++	if (err < 0) {
++		dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err);
++		goto done;
+ 	}
+-	case VIDIOCSFREQ: /*  set frequency  */
+-	{
+-		unsigned long *freq = arg;
+-		memset(&freq2,0,sizeof(freq2));
+ 
+-		drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+-		freq2.frequency = *freq;
+-		err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
+-		if (err < 0)
+-			dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err);
+-		break;
++	pict->depth   = ((fmt->fmt.pix.bytesperline << 3)
++			 + (fmt->fmt.pix.width - 1))
++			 / fmt->fmt.pix.width;
++	pict->palette = pixelformat_to_palette(
++		fmt->fmt.pix.pixelformat);
++done:
++	kfree(fmt);
++	return err;
++}
++
++static noinline int v4l1_compat_set_picture(
++					struct video_picture *pict,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_framebuffer fbuf;
++	int mem_err = 0, ovl_err = 0;
++	struct v4l2_format *fmt;
++
++	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++	if (!fmt) {
++		err = -ENOMEM;
++		return err;
++	}
++	memset(&fbuf, 0, sizeof(fbuf));
++
++	set_v4l_control(inode, file,
++			V4L2_CID_BRIGHTNESS, pict->brightness, drv);
++	set_v4l_control(inode, file,
++			V4L2_CID_HUE, pict->hue, drv);
++	set_v4l_control(inode, file,
++			V4L2_CID_CONTRAST, pict->contrast, drv);
++	set_v4l_control(inode, file,
++			V4L2_CID_SATURATION, pict->colour, drv);
++	set_v4l_control(inode, file,
++			V4L2_CID_WHITENESS, pict->whiteness, drv);
++	/*
++	 * V4L1 uses this ioctl to set both memory capture and overlay
++	 * pixel format, while V4L2 has two different ioctls for this.
++	 * Some cards may not support one or the other, and may support
++	 * different pixel formats for memory vs overlay.
++	 */
++
++	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	err = drv(inode, file, VIDIOC_G_FMT, fmt);
++	/* If VIDIOC_G_FMT failed, then the driver likely doesn't
++	   support memory capture.  Trying to set the memory capture
++	   parameters would be pointless.  */
++	if (err < 0) {
++		dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err);
++		mem_err = -1000;  /* didn't even try */
++	} else if (fmt->fmt.pix.pixelformat !=
++		 palette_to_pixelformat(pict->palette)) {
++		fmt->fmt.pix.pixelformat = palette_to_pixelformat(
++			pict->palette);
++		mem_err = drv(inode, file, VIDIOC_S_FMT, fmt);
++		if (mem_err < 0)
++			dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
++				mem_err);
+ 	}
+-	case VIDIOCGAUDIO: /*  get audio properties/controls  */
+-	{
+-		struct video_audio	*aud = arg;
+-		memset(&aud2,0,sizeof(aud2));
+ 
+-		err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
+-		if (err < 0) {
+-			dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err);
+-			break;
+-		}
+-		memcpy(aud->name, aud2.name,
+-		       min(sizeof(aud->name), sizeof(aud2.name)));
+-		aud->name[sizeof(aud->name) - 1] = 0;
+-		aud->audio = aud2.index;
+-		aud->flags = 0;
+-		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
+-		if (i >= 0) {
+-			aud->volume = i;
+-			aud->flags |= VIDEO_AUDIO_VOLUME;
+-		}
+-		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
+-		if (i >= 0) {
+-			aud->bass = i;
+-			aud->flags |= VIDEO_AUDIO_BASS;
+-		}
+-		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
+-		if (i >= 0) {
+-			aud->treble = i;
+-			aud->flags |= VIDEO_AUDIO_TREBLE;
+-		}
+-		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
+-		if (i >= 0) {
+-			aud->balance = i;
+-			aud->flags |= VIDEO_AUDIO_BALANCE;
+-		}
+-		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
+-		if (i >= 0) {
+-			if (i)
+-				aud->flags |= VIDEO_AUDIO_MUTE;
+-			aud->flags |= VIDEO_AUDIO_MUTABLE;
+-		}
+-		aud->step = 1;
+-		qctrl2.id = V4L2_CID_AUDIO_VOLUME;
+-		if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
+-		    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
+-			aud->step = qctrl2.step;
+-		aud->mode = 0;
+-
+-		memset(&tun2,0,sizeof(tun2));
+-		err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+-		if (err < 0) {
+-			dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
++	err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
++	/* If VIDIOC_G_FBUF failed, then the driver likely doesn't
++	   support overlay.  Trying to set the overlay parameters
++	   would be quite pointless.  */
++	if (err < 0) {
++		dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err);
++		ovl_err = -1000;  /* didn't even try */
++	} else if (fbuf.fmt.pixelformat !=
++		 palette_to_pixelformat(pict->palette)) {
++		fbuf.fmt.pixelformat = palette_to_pixelformat(
++			pict->palette);
++		ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
++		if (ovl_err < 0)
++			dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
++				ovl_err);
++	}
++	if (ovl_err < 0 && mem_err < 0) {
++		/* ioctl failed, couldn't set either parameter */
++		if (mem_err != -1000)
++			err = mem_err;
++		else if (ovl_err == -EPERM)
+ 			err = 0;
++		else
++			err = ovl_err;
++	} else
++		err = 0;
++	kfree(fmt);
++	return err;
++}
++
++static noinline int v4l1_compat_get_tuner(
++					struct video_tuner *tun,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err, i;
++	struct v4l2_tuner	tun2;
++	struct v4l2_standard	std2;
++	v4l2_std_id    		sid;
++
++	memset(&tun2, 0, sizeof(tun2));
++	err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
++	if (err < 0) {
++		dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err);
++		goto done;
++	}
++	memcpy(tun->name, tun2.name,
++	       min(sizeof(tun->name), sizeof(tun2.name)));
++	tun->name[sizeof(tun->name) - 1] = 0;
++	tun->rangelow = tun2.rangelow;
++	tun->rangehigh = tun2.rangehigh;
++	tun->flags = 0;
++	tun->mode = VIDEO_MODE_AUTO;
++
++	for (i = 0; i < 64; i++) {
++		memset(&std2, 0, sizeof(std2));
++		std2.index = i;
++		if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
+ 			break;
+-		}
++		if (std2.id & V4L2_STD_PAL)
++			tun->flags |= VIDEO_TUNER_PAL;
++		if (std2.id & V4L2_STD_NTSC)
++			tun->flags |= VIDEO_TUNER_NTSC;
++		if (std2.id & V4L2_STD_SECAM)
++			tun->flags |= VIDEO_TUNER_SECAM;
++	}
+ 
+-		if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
+-			aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+-		else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
+-			aud->mode = VIDEO_SOUND_STEREO;
+-		else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
+-			aud->mode = VIDEO_SOUND_MONO;
+-		break;
++	err = drv(inode, file, VIDIOC_G_STD, &sid);
++	if (err < 0)
++		dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err);
++	if (err == 0) {
++		if (sid & V4L2_STD_PAL)
++			tun->mode = VIDEO_MODE_PAL;
++		if (sid & V4L2_STD_NTSC)
++			tun->mode = VIDEO_MODE_NTSC;
++		if (sid & V4L2_STD_SECAM)
++			tun->mode = VIDEO_MODE_SECAM;
+ 	}
+-	case VIDIOCSAUDIO: /*  set audio controls  */
+-	{
+-		struct video_audio	*aud = arg;
+ 
+-		memset(&aud2,0,sizeof(aud2));
+-		memset(&tun2,0,sizeof(tun2));
++	if (tun2.capability & V4L2_TUNER_CAP_LOW)
++		tun->flags |= VIDEO_TUNER_LOW;
++	if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
++		tun->flags |= VIDEO_TUNER_STEREO_ON;
++	tun->signal = tun2.signal;
++done:
++	return err;
++}
+ 
+-		aud2.index = aud->audio;
+-		err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
+-		if (err < 0) {
+-			dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err);
+-			break;
+-		}
++static noinline int v4l1_compat_select_tuner(
++					struct video_tuner *tun,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_tuner	t;/*84 bytes on x86_64*/
++	memset(&t, 0, sizeof(t));
+ 
+-		set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
+-				aud->volume, drv);
+-		set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
+-				aud->bass, drv);
+-		set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
+-				aud->treble, drv);
+-		set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
+-				aud->balance, drv);
+-		set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
+-				!!(aud->flags & VIDEO_AUDIO_MUTE), drv);
+-
+-		err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+-		if (err < 0)
+-			dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err);
+-		if (err == 0) {
+-			switch (aud->mode) {
+-			default:
+-			case VIDEO_SOUND_MONO:
+-			case VIDEO_SOUND_LANG1:
+-				tun2.audmode = V4L2_TUNER_MODE_MONO;
+-				break;
+-			case VIDEO_SOUND_STEREO:
+-				tun2.audmode = V4L2_TUNER_MODE_STEREO;
+-				break;
+-			case VIDEO_SOUND_LANG2:
+-				tun2.audmode = V4L2_TUNER_MODE_LANG2;
+-				break;
+-			}
+-			err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
+-			if (err < 0)
+-				dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err);
+-		}
++	t.index = tun->tuner;
++
++	err = drv(inode, file, VIDIOC_S_INPUT, &t);
++	if (err < 0)
++		dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err);
++	return err;
++}
++
++static noinline int v4l1_compat_get_frequency(
++					unsigned long *freq,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_frequency   freq2;
++	memset(&freq2, 0, sizeof(freq2));
++
++	freq2.tuner = 0;
++	err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
++	if (err < 0)
++		dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err);
++	if (0 == err)
++		*freq = freq2.frequency;
++	return err;
++}
++
++static noinline int v4l1_compat_set_frequency(
++					unsigned long *freq,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_frequency   freq2;
++	memset(&freq2, 0, sizeof(freq2));
++
++	drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
++	freq2.frequency = *freq;
++	err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
++	if (err < 0)
++		dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err);
++	return err;
++}
++
++static noinline int v4l1_compat_get_audio(
++					struct video_audio *aud,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err, i;
++	struct v4l2_queryctrl	qctrl2;
++	struct v4l2_audio	aud2;
++	struct v4l2_tuner	tun2;
++	memset(&aud2, 0, sizeof(aud2));
++
++	err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
++	if (err < 0) {
++		dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err);
++		goto done;
++	}
++	memcpy(aud->name, aud2.name,
++	       min(sizeof(aud->name), sizeof(aud2.name)));
++	aud->name[sizeof(aud->name) - 1] = 0;
++	aud->audio = aud2.index;
++	aud->flags = 0;
++	i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
++	if (i >= 0) {
++		aud->volume = i;
++		aud->flags |= VIDEO_AUDIO_VOLUME;
++	}
++	i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
++	if (i >= 0) {
++		aud->bass = i;
++		aud->flags |= VIDEO_AUDIO_BASS;
++	}
++	i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
++	if (i >= 0) {
++		aud->treble = i;
++		aud->flags |= VIDEO_AUDIO_TREBLE;
++	}
++	i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
++	if (i >= 0) {
++		aud->balance = i;
++		aud->flags |= VIDEO_AUDIO_BALANCE;
++	}
++	i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
++	if (i >= 0) {
++		if (i)
++			aud->flags |= VIDEO_AUDIO_MUTE;
++		aud->flags |= VIDEO_AUDIO_MUTABLE;
++	}
++	aud->step = 1;
++	qctrl2.id = V4L2_CID_AUDIO_VOLUME;
++	if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
++	    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
++		aud->step = qctrl2.step;
++	aud->mode = 0;
++
++	memset(&tun2, 0, sizeof(tun2));
++	err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
++	if (err < 0) {
++		dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err);
+ 		err = 0;
+-		break;
++		goto done;
+ 	}
+-	case VIDIOCMCAPTURE: /*  capture a frame  */
+-	{
+-		struct video_mmap	*mm = arg;
+ 
+-		fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+-		if (!fmt2) {
+-			err = -ENOMEM;
+-			break;
+-		}
+-		memset(&buf2,0,sizeof(buf2));
++	if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
++		aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
++	else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
++		aud->mode = VIDEO_SOUND_STEREO;
++	else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
++		aud->mode = VIDEO_SOUND_MONO;
++done:
++	return err;
++}
+ 
+-		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+-		if (err < 0) {
+-			dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
++static noinline int v4l1_compat_set_audio(
++					struct video_audio *aud,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_audio	aud2;
++	struct v4l2_tuner	tun2;
++
++	memset(&aud2, 0, sizeof(aud2));
++	memset(&tun2, 0, sizeof(tun2));
++
++	aud2.index = aud->audio;
++	err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
++	if (err < 0) {
++		dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err);
++		goto done;
++	}
++
++	set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
++			aud->volume, drv);
++	set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
++			aud->bass, drv);
++	set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
++			aud->treble, drv);
++	set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
++			aud->balance, drv);
++	set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
++			!!(aud->flags & VIDEO_AUDIO_MUTE), drv);
++
++	err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
++	if (err < 0)
++		dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err);
++	if (err == 0) {
++		switch (aud->mode) {
++		default:
++		case VIDEO_SOUND_MONO:
++		case VIDEO_SOUND_LANG1:
++			tun2.audmode = V4L2_TUNER_MODE_MONO;
+ 			break;
+-		}
+-		if (mm->width   != fmt2->fmt.pix.width  ||
+-		    mm->height  != fmt2->fmt.pix.height ||
+-		    palette_to_pixelformat(mm->format) !=
+-		    fmt2->fmt.pix.pixelformat)
+-		{/* New capture format...  */
+-			fmt2->fmt.pix.width = mm->width;
+-			fmt2->fmt.pix.height = mm->height;
+-			fmt2->fmt.pix.pixelformat =
+-				palette_to_pixelformat(mm->format);
+-			fmt2->fmt.pix.field = V4L2_FIELD_ANY;
+-			fmt2->fmt.pix.bytesperline = 0;
+-			err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+-			if (err < 0) {
+-				dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
+-				break;
+-			}
+-		}
+-		buf2.index = mm->frame;
+-		buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
+-		if (err < 0) {
+-			dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err);
++		case VIDEO_SOUND_STEREO:
++			tun2.audmode = V4L2_TUNER_MODE_STEREO;
+ 			break;
+-		}
+-		err = drv(inode, file, VIDIOC_QBUF, &buf2);
+-		if (err < 0) {
+-			dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err);
++		case VIDEO_SOUND_LANG2:
++			tun2.audmode = V4L2_TUNER_MODE_LANG2;
+ 			break;
+ 		}
+-		err = drv(inode, file, VIDIOC_STREAMON, &captype);
++		err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
+ 		if (err < 0)
+-			dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err);
+-		break;
++			dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err);
+ 	}
+-	case VIDIOCSYNC: /*  wait for a frame  */
+-	{
+-		int			*i = arg;
++	err = 0;
++done:
++	return err;
++}
+ 
+-		memset(&buf2,0,sizeof(buf2));
+-		buf2.index = *i;
+-		buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-		err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
+-		if (err < 0) {
+-			/*  No such buffer */
+-			dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
+-			break;
+-		}
+-		if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) {
+-			/* Buffer is not mapped  */
+-			err = -EINVAL;
+-			break;
+-		}
++static noinline int v4l1_compat_capture_frame(
++					struct video_mmap *mm,
++					struct inode *inode,
++					struct file *file,
++					v4l2_kioctl drv)
++{
++	int err;
++	enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	struct v4l2_buffer	buf;
++	struct v4l2_format	*fmt;
++
++	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++	if (!fmt) {
++		err = -ENOMEM;
++		return err;
++	}
++	memset(&buf, 0, sizeof(buf));
+ 
+-		/* make sure capture actually runs so we don't block forever */
+-		err = drv(inode, file, VIDIOC_STREAMON, &captype);
++	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	err = drv(inode, file, VIDIOC_G_FMT, fmt);
++	if (err < 0) {
++		dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err);
++		goto done;
++	}
++	if (mm->width   != fmt->fmt.pix.width  ||
++	    mm->height  != fmt->fmt.pix.height ||
++	    palette_to_pixelformat(mm->format) !=
++	    fmt->fmt.pix.pixelformat) {
++		/* New capture format...  */
++		fmt->fmt.pix.width = mm->width;
++		fmt->fmt.pix.height = mm->height;
++		fmt->fmt.pix.pixelformat =
++			palette_to_pixelformat(mm->format);
++		fmt->fmt.pix.field = V4L2_FIELD_ANY;
++		fmt->fmt.pix.bytesperline = 0;
++		err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ 		if (err < 0) {
+-			dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err);
+-			break;
++			dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err);
++			goto done;
+ 		}
++	}
++	buf.index = mm->frame;
++	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
++	if (err < 0) {
++		dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err);
++		goto done;
++	}
++	err = drv(inode, file, VIDIOC_QBUF, &buf);
++	if (err < 0) {
++		dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err);
++		goto done;
++	}
++	err = drv(inode, file, VIDIOC_STREAMON, &captype);
++	if (err < 0)
++		dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err);
++done:
++	kfree(fmt);
++	return err;
++}
+ 
+-		/*  Loop as long as the buffer is queued, but not done  */
+-		while ((buf2.flags &
+-			(V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
+-		       == V4L2_BUF_FLAG_QUEUED)
+-		{
+-			err = poll_one(file);
+-			if (err < 0 ||	/* error or sleep was interrupted  */
+-			    err == 0)	/* timeout? Shouldn't occur.  */
+-				break;
+-			err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
+-			if (err < 0)
+-				dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
+-		}
+-		if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */
+-			break;
+-		do {
+-			err = drv(inode, file, VIDIOC_DQBUF, &buf2);
+-			if (err < 0)
+-				dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err);
+-		} while (err == 0 && buf2.index != *i);
+-		break;
++static noinline int v4l1_compat_sync(
++				int *i,
++				struct inode *inode,
++				struct file *file,
++				v4l2_kioctl drv)
++{
++	int err;
++	enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	struct v4l2_buffer buf;
++	struct poll_wqueues *pwq;
++
++	memset(&buf, 0, sizeof(buf));
++	buf.index = *i;
++	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++	err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
++	if (err < 0) {
++		/*  No such buffer */
++		dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
++		goto done;
++	}
++	if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) {
++		/* Buffer is not mapped  */
++		err = -EINVAL;
++		goto done;
+ 	}
+ 
+-	case VIDIOCGVBIFMT: /* query VBI data capture format */
+-	{
+-		struct vbi_format      *fmt = arg;
++	/* make sure capture actually runs so we don't block forever */
++	err = drv(inode, file, VIDIOC_STREAMON, &captype);
++	if (err < 0) {
++		dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err);
++		goto done;
++	}
+ 
+-		fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+-		if (!fmt2) {
+-			err = -ENOMEM;
++	pwq = kmalloc(sizeof(*pwq), GFP_KERNEL);
++	/*  Loop as long as the buffer is queued, but not done  */
++	while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
++						== V4L2_BUF_FLAG_QUEUED) {
++		err = poll_one(file, pwq);
++		if (err < 0 ||	/* error or sleep was interrupted  */
++		    err == 0)	/* timeout? Shouldn't occur.  */
+ 			break;
+-		}
+-		fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
++		err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
++		if (err < 0)
++			dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
++	}
++	kfree(pwq);
++	if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
++		goto done;
++	do {
++		err = drv(inode, file, VIDIOC_DQBUF, &buf);
++		if (err < 0)
++			dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err);
++	} while (err == 0 && buf.index != *i);
++done:
++	return err;
++}
+ 
+-		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+-		if (err < 0) {
+-			dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
+-			break;
+-		}
+-		if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
+-			err = -EINVAL;
+-			break;
+-		}
+-		memset(fmt, 0, sizeof(*fmt));
+-		fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
+-		fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
+-		fmt->sample_format    = VIDEO_PALETTE_RAW;
+-		fmt->start[0]         = fmt2->fmt.vbi.start[0];
+-		fmt->count[0]         = fmt2->fmt.vbi.count[0];
+-		fmt->start[1]         = fmt2->fmt.vbi.start[1];
+-		fmt->count[1]         = fmt2->fmt.vbi.count[1];
+-		fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
+-		break;
++static noinline int v4l1_compat_get_vbi_format(
++				struct vbi_format *fmt,
++				struct inode *inode,
++				struct file *file,
++				v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_format *fmt2;
++
++	fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
++	if (!fmt2) {
++		err = -ENOMEM;
++		return err;
+ 	}
+-	case VIDIOCSVBIFMT:
+-	{
+-		struct vbi_format      *fmt = arg;
++	fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ 
+-		if (VIDEO_PALETTE_RAW != fmt->sample_format) {
+-			err = -EINVAL;
+-			break;
+-		}
++	err = drv(inode, file, VIDIOC_G_FMT, fmt2);
++	if (err < 0) {
++		dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
++		goto done;
++	}
++	if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
++		err = -EINVAL;
++		goto done;
++	}
++	memset(fmt, 0, sizeof(*fmt));
++	fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
++	fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
++	fmt->sample_format    = VIDEO_PALETTE_RAW;
++	fmt->start[0]         = fmt2->fmt.vbi.start[0];
++	fmt->count[0]         = fmt2->fmt.vbi.count[0];
++	fmt->start[1]         = fmt2->fmt.vbi.start[1];
++	fmt->count[1]         = fmt2->fmt.vbi.count[1];
++	fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
++done:
++	kfree(fmt2);
++	return err;
++}
+ 
+-		fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+-		if (!fmt2) {
+-			err = -ENOMEM;
+-			break;
+-		}
+-		fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+-		fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
+-		fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
+-		fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
+-		fmt2->fmt.vbi.start[0]         = fmt->start[0];
+-		fmt2->fmt.vbi.count[0]         = fmt->count[0];
+-		fmt2->fmt.vbi.start[1]         = fmt->start[1];
+-		fmt2->fmt.vbi.count[1]         = fmt->count[1];
+-		fmt2->fmt.vbi.flags            = fmt->flags;
+-		err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
+-		if (err < 0) {
+-			dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
+-			break;
+-		}
++static noinline int v4l1_compat_set_vbi_format(
++				struct vbi_format *fmt,
++				struct inode *inode,
++				struct file *file,
++				v4l2_kioctl drv)
++{
++	int err;
++	struct v4l2_format	*fmt2 = NULL;
+ 
+-		if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
+-		    fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
+-		    fmt2->fmt.vbi.sample_format    != V4L2_PIX_FMT_GREY     ||
+-		    fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
+-		    fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
+-		    fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
+-		    fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
+-		    fmt2->fmt.vbi.flags            != fmt->flags) {
+-			err = -EINVAL;
+-			break;
+-		}
+-		err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+-		if (err < 0)
+-			dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
+-		break;
++	if (VIDEO_PALETTE_RAW != fmt->sample_format) {
++		err = -EINVAL;
++		return err;
+ 	}
+ 
++	fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
++	if (!fmt2) {
++		err = -ENOMEM;
++		return err;
++	}
++	fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
++	fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
++	fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
++	fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
++	fmt2->fmt.vbi.start[0]         = fmt->start[0];
++	fmt2->fmt.vbi.count[0]         = fmt->count[0];
++	fmt2->fmt.vbi.start[1]         = fmt->start[1];
++	fmt2->fmt.vbi.count[1]         = fmt->count[1];
++	fmt2->fmt.vbi.flags            = fmt->flags;
++	err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
++	if (err < 0) {
++		dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
++		goto done;
++	}
++
++	if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
++	    fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
++	    fmt2->fmt.vbi.sample_format    != V4L2_PIX_FMT_GREY     ||
++	    fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
++	    fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
++	    fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
++	    fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
++	    fmt2->fmt.vbi.flags            != fmt->flags) {
++		err = -EINVAL;
++		goto done;
++	}
++	err = drv(inode, file, VIDIOC_S_FMT, fmt2);
++	if (err < 0)
++		dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
++done:
++	kfree(fmt2);
++	return err;
++}
++
++/*
++ *	This function is exported.
++ */
++int
++v4l_compat_translate_ioctl(struct inode         *inode,
++			   struct file		*file,
++			   int			cmd,
++			   void			*arg,
++			   v4l2_kioctl          drv)
++{
++	int err;
++
++	switch (cmd) {
++	case VIDIOCGCAP:	/* capability */
++		err = v4l1_compat_get_capabilities(arg, inode, file, drv);
++		break;
++	case VIDIOCGFBUF: /*  get frame buffer  */
++		err = v4l1_compat_get_frame_buffer(arg, inode, file, drv);
++		break;
++	case VIDIOCSFBUF: /*  set frame buffer  */
++		err = v4l1_compat_set_frame_buffer(arg, inode, file, drv);
++		break;
++	case VIDIOCGWIN: /*  get window or capture dimensions  */
++		err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv);
++		break;
++	case VIDIOCSWIN: /*  set window and/or capture dimensions  */
++		err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv);
++		break;
++	case VIDIOCCAPTURE: /*  turn on/off preview  */
++		err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv);
++		break;
++	case VIDIOCGCHAN: /*  get input information  */
++		err = v4l1_compat_get_input_info(arg, inode, file, drv);
++		break;
++	case VIDIOCSCHAN: /*  set input  */
++		err = v4l1_compat_set_input(arg, inode, file, drv);
++		break;
++	case VIDIOCGPICT: /*  get tone controls & partial capture format  */
++		err = v4l1_compat_get_picture(arg, inode, file, drv);
++		break;
++	case VIDIOCSPICT: /*  set tone controls & partial capture format  */
++		err = v4l1_compat_set_picture(arg, inode, file, drv);
++		break;
++	case VIDIOCGTUNER: /*  get tuner information  */
++		err = v4l1_compat_get_tuner(arg, inode, file, drv);
++		break;
++	case VIDIOCSTUNER: /*  select a tuner input  */
++		err = v4l1_compat_select_tuner(arg, inode, file, drv);
++		break;
++	case VIDIOCGFREQ: /*  get frequency  */
++		err = v4l1_compat_get_frequency(arg, inode, file, drv);
++		break;
++	case VIDIOCSFREQ: /*  set frequency  */
++		err = v4l1_compat_set_frequency(arg, inode, file, drv);
++		break;
++	case VIDIOCGAUDIO: /*  get audio properties/controls  */
++		err = v4l1_compat_get_audio(arg, inode, file, drv);
++		break;
++	case VIDIOCSAUDIO: /*  set audio controls  */
++		err = v4l1_compat_set_audio(arg, inode, file, drv);
++		break;
++	case VIDIOCMCAPTURE: /*  capture a frame  */
++		err = v4l1_compat_capture_frame(arg, inode, file, drv);
++		break;
++	case VIDIOCSYNC: /*  wait for a frame  */
++		err = v4l1_compat_sync(arg, inode, file, drv);
++		break;
++	case VIDIOCGVBIFMT: /* query VBI data capture format */
++		err = v4l1_compat_get_vbi_format(arg, inode, file, drv);
++		break;
++	case VIDIOCSVBIFMT:
++		err = v4l1_compat_set_vbi_format(arg, inode, file, drv);
++		break;
+ 	default:
+ 		err = -ENOIOCTLCMD;
+ 		break;
+ 	}
+ 
+-	kfree(cap2);
+-	kfree(fmt2);
+ 	return err;
+ }
+-
+ EXPORT_SYMBOL(v4l_compat_translate_ioctl);
+ 
+ /*
+diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
+index eab79ff..fc51e49 100644
+--- a/drivers/media/video/videobuf-core.c
++++ b/drivers/media/video/videobuf-core.c
+@@ -64,32 +64,25 @@ void *videobuf_alloc(struct videobuf_queue *q)
+ 	return vb;
+ }
+ 
++#define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\
++				vb->state != VIDEOBUF_QUEUED)
+ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
+ {
+-	int retval = 0;
+-	DECLARE_WAITQUEUE(wait, current);
+-
+ 	MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
+-	add_wait_queue(&vb->done, &wait);
+-	while (vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) {
+-		if (non_blocking) {
+-			retval = -EAGAIN;
+-			break;
+-		}
+-		set_current_state(intr  ? TASK_INTERRUPTIBLE
+-					: TASK_UNINTERRUPTIBLE);
+-		if (vb->state == VIDEOBUF_ACTIVE ||
+-		    vb->state == VIDEOBUF_QUEUED)
+-			schedule();
+-		set_current_state(TASK_RUNNING);
+-		if (intr && signal_pending(current)) {
+-			dprintk(1, "buffer waiton: -EINTR\n");
+-			retval = -EINTR;
+-			break;
+-		}
++
++	if (non_blocking) {
++		if (WAITON_CONDITION)
++			return 0;
++		else
++			return -EAGAIN;
+ 	}
+-	remove_wait_queue(&vb->done, &wait);
+-	return retval;
++
++	if (intr)
++		return wait_event_interruptible(vb->done, WAITON_CONDITION);
++	else
++		wait_event(vb->done, WAITON_CONDITION);
++
++	return 0;
+ }
+ 
+ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
+@@ -98,29 +91,22 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ 	MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
+ 	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+ 
+-	/* This is required to avoid OOPS on some cases,
+-	   since mmap_mapper() method should be called before _iolock.
+-	   On some cases, the mmap_mapper() is called only after scheduling.
+-	 */
+-	if (vb->memory == V4L2_MEMORY_MMAP) {
+-		wait_event_timeout(vb->done, q->is_mmapped,
+-				   msecs_to_jiffies(100));
+-		if (!q->is_mmapped) {
+-			printk(KERN_ERR
+-			       "Error: mmap_mapper() never called!\n");
+-			return -EINVAL;
+-		}
+-	}
+-
+ 	return CALL(q, iolock, q, vb, fbuf);
+ }
+ 
++void *videobuf_queue_to_vmalloc (struct videobuf_queue *q,
++			   struct videobuf_buffer *buf)
++{
++	return CALL(q, vmalloc, buf);
++}
++EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc);
++
+ /* --------------------------------------------------------------------- */
+ 
+ 
+ void videobuf_queue_core_init(struct videobuf_queue *q,
+ 			 struct videobuf_queue_ops *ops,
+-			 void *dev,
++			 struct device *dev,
+ 			 spinlock_t *irqlock,
+ 			 enum v4l2_buf_type type,
+ 			 enum v4l2_field field,
+@@ -144,10 +130,14 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
+ 	BUG_ON(!q->ops->buf_queue);
+ 	BUG_ON(!q->ops->buf_release);
+ 
++	/* Lock is mandatory for queue_cancel to work */
++	BUG_ON(!irqlock);
++
+ 	/* Having implementations for abstract methods are mandatory */
+ 	BUG_ON(!q->int_ops);
+ 
+ 	mutex_init(&q->vb_lock);
++	init_waitqueue_head(&q->wait);
+ 	INIT_LIST_HEAD(&q->stream);
+ }
+ 
+@@ -195,19 +185,22 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
+ 	unsigned long flags = 0;
+ 	int i;
+ 
++	q->streaming = 0;
++	q->reading  = 0;
++	wake_up_interruptible_sync(&q->wait);
++
+ 	/* remove queued buffers from list */
+-	if (q->irqlock)
+-		spin_lock_irqsave(q->irqlock, flags);
++	spin_lock_irqsave(q->irqlock, flags);
+ 	for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ 		if (NULL == q->bufs[i])
+ 			continue;
+ 		if (q->bufs[i]->state == VIDEOBUF_QUEUED) {
+ 			list_del(&q->bufs[i]->queue);
+ 			q->bufs[i]->state = VIDEOBUF_ERROR;
++			wake_up_all(&q->bufs[i]->done);
+ 		}
+ 	}
+-	if (q->irqlock)
+-		spin_unlock_irqrestore(q->irqlock, flags);
++	spin_unlock_irqrestore(q->irqlock, flags);
+ 
+ 	/* free all buffers + clear queue */
+ 	for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+@@ -563,14 +556,13 @@ int videobuf_qbuf(struct videobuf_queue *q,
+ 
+ 	list_add_tail(&buf->stream, &q->stream);
+ 	if (q->streaming) {
+-		if (q->irqlock)
+-			spin_lock_irqsave(q->irqlock, flags);
++		spin_lock_irqsave(q->irqlock, flags);
+ 		q->ops->buf_queue(q, buf);
+-		if (q->irqlock)
+-			spin_unlock_irqrestore(q->irqlock, flags);
++		spin_unlock_irqrestore(q->irqlock, flags);
+ 	}
+ 	dprintk(1, "qbuf: succeded\n");
+ 	retval = 0;
++	wake_up_interruptible_sync(&q->wait);
+ 
+  done:
+ 	mutex_unlock(&q->vb_lock);
+@@ -581,35 +573,88 @@ int videobuf_qbuf(struct videobuf_queue *q,
+ 	return retval;
+ }
+ 
+-int videobuf_dqbuf(struct videobuf_queue *q,
+-	       struct v4l2_buffer *b, int nonblocking)
++
++/* Locking: Caller holds q->vb_lock */
++static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock)
+ {
+-	struct videobuf_buffer *buf;
+ 	int retval;
+ 
+-	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+-
+-	mutex_lock(&q->vb_lock);
+-	retval = -EBUSY;
+-	if (q->reading) {
+-		dprintk(1, "dqbuf: Reading running...\n");
+-		goto done;
+-	}
+-	retval = -EINVAL;
+-	if (b->type != q->type) {
+-		dprintk(1, "dqbuf: Wrong type.\n");
++checks:
++	if (!q->streaming) {
++		dprintk(1, "next_buffer: Not streaming\n");
++		retval = -EINVAL;
+ 		goto done;
+ 	}
++
+ 	if (list_empty(&q->stream)) {
+-		dprintk(1, "dqbuf: stream running\n");
+-		goto done;
++		if (noblock) {
++			retval = -EAGAIN;
++			dprintk(2, "next_buffer: no buffers to dequeue\n");
++			goto done;
++		} else {
++			dprintk(2, "next_buffer: waiting on buffer\n");
++
++			/* Drop lock to avoid deadlock with qbuf */
++			mutex_unlock(&q->vb_lock);
++
++			/* Checking list_empty and streaming is safe without
++			 * locks because we goto checks to validate while
++			 * holding locks before proceeding */
++			retval = wait_event_interruptible(q->wait,
++				!list_empty(&q->stream) || !q->streaming);
++			mutex_lock(&q->vb_lock);
++
++			if (retval)
++				goto done;
++
++			goto checks;
++		}
+ 	}
++
++	retval = 0;
++
++done:
++	return retval;
++}
++
++
++/* Locking: Caller holds q->vb_lock */
++static int stream_next_buffer(struct videobuf_queue *q,
++			struct videobuf_buffer **vb, int nonblocking)
++{
++	int retval;
++	struct videobuf_buffer *buf = NULL;
++
++	retval = stream_next_buffer_check_queue(q, nonblocking);
++	if (retval)
++		goto done;
++
+ 	buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
+ 	retval = videobuf_waiton(buf, nonblocking, 1);
++	if (retval < 0)
++		goto done;
++
++	*vb = buf;
++done:
++	return retval;
++}
++
++int videobuf_dqbuf(struct videobuf_queue *q,
++	       struct v4l2_buffer *b, int nonblocking)
++{
++	struct videobuf_buffer *buf = NULL;
++	int retval;
++
++	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
++
++	mutex_lock(&q->vb_lock);
++
++	retval = stream_next_buffer(q, &buf, nonblocking);
+ 	if (retval < 0) {
+-		dprintk(1, "dqbuf: waiton returned %d\n", retval);
++		dprintk(1, "dqbuf: next_buffer error: %i\n", retval);
+ 		goto done;
+ 	}
++
+ 	switch (buf->state) {
+ 	case VIDEOBUF_ERROR:
+ 		dprintk(1, "dqbuf: state is error\n");
+@@ -650,14 +695,13 @@ int videobuf_streamon(struct videobuf_queue *q)
+ 	if (q->streaming)
+ 		goto done;
+ 	q->streaming = 1;
+-	if (q->irqlock)
+-		spin_lock_irqsave(q->irqlock, flags);
++	spin_lock_irqsave(q->irqlock, flags);
+ 	list_for_each_entry(buf, &q->stream, stream)
+ 		if (buf->state == VIDEOBUF_PREPARED)
+ 			q->ops->buf_queue(q, buf);
+-	if (q->irqlock)
+-		spin_unlock_irqrestore(q->irqlock, flags);
++	spin_unlock_irqrestore(q->irqlock, flags);
+ 
++	wake_up_interruptible_sync(&q->wait);
+  done:
+ 	mutex_unlock(&q->vb_lock);
+ 	return retval;
+@@ -670,7 +714,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q)
+ 		return -EINVAL;
+ 
+ 	videobuf_queue_cancel(q);
+-	q->streaming = 0;
+ 
+ 	return 0;
+ }
+@@ -712,11 +755,9 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
+ 		goto done;
+ 
+ 	/* start capture & wait */
+-	if (q->irqlock)
+-		spin_lock_irqsave(q->irqlock, flags);
++	spin_lock_irqsave(q->irqlock, flags);
+ 	q->ops->buf_queue(q, q->read_buf);
+-	if (q->irqlock)
+-		spin_unlock_irqrestore(q->irqlock, flags);
++	spin_unlock_irqrestore(q->irqlock, flags);
+ 	retval = videobuf_waiton(q->read_buf, 0, 0);
+ 	if (0 == retval) {
+ 		CALL(q, sync, q, q->read_buf);
+@@ -740,14 +781,13 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
+ {
+ 	enum v4l2_field field;
+ 	unsigned long flags = 0;
+-	unsigned size, nbufs;
++	unsigned size = 0, nbufs = 1;
+ 	int retval;
+ 
+ 	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+ 
+ 	mutex_lock(&q->vb_lock);
+ 
+-	nbufs = 1; size = 0;
+ 	q->ops->buf_setup(q, &nbufs, &size);
+ 
+ 	if (NULL == q->read_buf  &&
+@@ -778,12 +818,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
+ 			q->read_buf = NULL;
+ 			goto done;
+ 		}
+-		if (q->irqlock)
+-			spin_lock_irqsave(q->irqlock, flags);
+ 
++		spin_lock_irqsave(q->irqlock, flags);
+ 		q->ops->buf_queue(q, q->read_buf);
+-		if (q->irqlock)
+-			spin_unlock_irqrestore(q->irqlock, flags);
++		spin_unlock_irqrestore(q->irqlock, flags);
++
+ 		q->read_off = 0;
+ 	}
+ 
+@@ -849,12 +888,10 @@ static int __videobuf_read_start(struct videobuf_queue *q)
+ 			return err;
+ 		list_add_tail(&q->bufs[i]->stream, &q->stream);
+ 	}
+-	if (q->irqlock)
+-		spin_lock_irqsave(q->irqlock, flags);
++	spin_lock_irqsave(q->irqlock, flags);
+ 	for (i = 0; i < count; i++)
+ 		q->ops->buf_queue(q, q->bufs[i]);
+-	if (q->irqlock)
+-		spin_unlock_irqrestore(q->irqlock, flags);
++	spin_unlock_irqrestore(q->irqlock, flags);
+ 	q->reading = 1;
+ 	return 0;
+ }
+@@ -863,7 +900,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
+ {
+ 	int i;
+ 
+-
+ 	videobuf_queue_cancel(q);
+ 	__videobuf_mmap_free(q);
+ 	INIT_LIST_HEAD(&q->stream);
+@@ -874,7 +910,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
+ 		q->bufs[i] = NULL;
+ 	}
+ 	q->read_buf = NULL;
+-	q->reading  = 0;
+ 
+ }
+ 
+@@ -919,7 +954,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
+ 
+ 	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+ 
+-	dprintk(2, "%s\n", __FUNCTION__);
++	dprintk(2, "%s\n", __func__);
+ 	mutex_lock(&q->vb_lock);
+ 	retval = -EBUSY;
+ 	if (q->streaming)
+@@ -968,11 +1003,9 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
+ 		if (q->read_off == q->read_buf->size) {
+ 			list_add_tail(&q->read_buf->stream,
+ 				      &q->stream);
+-			if (q->irqlock)
+-				spin_lock_irqsave(q->irqlock, flags);
++			spin_lock_irqsave(q->irqlock, flags);
+ 			q->ops->buf_queue(q, q->read_buf);
+-			if (q->irqlock)
+-				spin_unlock_irqrestore(q->irqlock, flags);
++			spin_unlock_irqrestore(q->irqlock, flags);
+ 			q->read_buf = NULL;
+ 		}
+ 		if (retval < 0)
+diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
+index 53fed4b..03a7b94 100644
+--- a/drivers/media/video/videobuf-dma-sg.c
++++ b/drivers/media/video/videobuf-dma-sg.c
+@@ -1,5 +1,5 @@
+ /*
+- * helper functions for PCI DMA video4linux capture buffers
++ * helper functions for SG DMA video4linux capture buffers
+  *
+  * The functions expect the hardware being able to scatter gatter
+  * (i.e. the buffers are not linear in physical memory, but fragmented
+@@ -24,7 +24,7 @@
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
+ 
+-#include <linux/pci.h>
++#include <linux/dma-mapping.h>
+ #include <linux/vmalloc.h>
+ #include <linux/pagemap.h>
+ #include <linux/scatterlist.h>
+@@ -39,10 +39,10 @@
+ #define MAGIC_CHECK(is,should)	if (unlikely((is) != (should))) \
+ 	{ printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ 
+-MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers");
++MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers");
+ MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
+ MODULE_LICENSE("GPL");
+ 
+@@ -119,10 +119,10 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
+ 
+ struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf)
+ {
+-	struct videbuf_pci_sg_memory *mem=buf->priv;
+-	BUG_ON (!mem);
++	struct videobuf_dma_sg_memory *mem = buf->priv;
++	BUG_ON(!mem);
+ 
+-	MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
++	MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+ 
+ 	return &mem->dma;
+ }
+@@ -141,9 +141,14 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
+ 
+ 	dma->direction = direction;
+ 	switch (dma->direction) {
+-	case PCI_DMA_FROMDEVICE: rw = READ;  break;
+-	case PCI_DMA_TODEVICE:   rw = WRITE; break;
+-	default:                 BUG();
++	case DMA_FROM_DEVICE:
++		rw = READ;
++		break;
++	case DMA_TO_DEVICE:
++		rw = WRITE;
++		break;
++	default:
++		BUG();
+ 	}
+ 
+ 	first = (data          & PAGE_MASK) >> PAGE_SHIFT;
+@@ -157,9 +162,6 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
+ 	dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
+ 		data,size,dma->nr_pages);
+ 
+-	dma->varea = (void *) data;
+-
+-
+ 	err = get_user_pages(current,current->mm,
+ 			     data & PAGE_MASK, dma->nr_pages,
+ 			     rw == READ, 1, /* force */
+@@ -216,10 +218,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
+ 	return 0;
+ }
+ 
+-int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
++int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma)
+ {
+-	void                   *dev=q->dev;
+-
+ 	MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+ 	BUG_ON(0 == dma->nr_pages);
+ 
+@@ -245,11 +245,11 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+ 		return -ENOMEM;
+ 	}
+ 	if (!dma->bus_addr) {
+-		dma->sglen = pci_map_sg(dev,dma->sglist,
++		dma->sglen = dma_map_sg(q->dev, dma->sglist,
+ 					dma->nr_pages, dma->direction);
+ 		if (0 == dma->sglen) {
+ 			printk(KERN_WARNING
+-			       "%s: videobuf_map_sg failed\n",__FUNCTION__);
++			       "%s: videobuf_map_sg failed\n",__func__);
+ 			kfree(dma->sglist);
+ 			dma->sglist = NULL;
+ 			dma->sglen = 0;
+@@ -259,26 +259,22 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+ 	return 0;
+ }
+ 
+-int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma)
++int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma)
+ {
+-	void                   *dev=q->dev;
+-
+-	MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
++	MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
+ 	BUG_ON(!dma->sglen);
+ 
+-	pci_dma_sync_sg_for_cpu (dev,dma->sglist,dma->nr_pages,dma->direction);
++	dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction);
+ 	return 0;
+ }
+ 
+ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+ {
+-	void                   *dev=q->dev;
+-
+-	MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
++	MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
+ 	if (!dma->sglen)
+ 		return 0;
+ 
+-	pci_unmap_sg (dev,dma->sglist,dma->nr_pages,dma->direction);
++	dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction);
+ 
+ 	kfree(dma->sglist);
+ 	dma->sglist = NULL;
+@@ -301,33 +297,32 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
+ 
+ 	vfree(dma->vmalloc);
+ 	dma->vmalloc = NULL;
+-	dma->varea = NULL;
+ 
+ 	if (dma->bus_addr) {
+ 		dma->bus_addr = 0;
+ 	}
+-	dma->direction = PCI_DMA_NONE;
++	dma->direction = DMA_NONE;
+ 	return 0;
+ }
+ 
+ /* --------------------------------------------------------------------- */
+ 
+-int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
++int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma)
+ {
+ 	struct videobuf_queue q;
+ 
+-	q.dev=pci;
++	q.dev = dev;
+ 
+-	return (videobuf_dma_map(&q,dma));
++	return videobuf_dma_map(&q, dma);
+ }
+ 
+-int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
++int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma)
+ {
+ 	struct videobuf_queue q;
+ 
+-	q.dev=pci;
++	q.dev = dev;
+ 
+-	return (videobuf_dma_unmap(&q,dma));
++	return videobuf_dma_unmap(&q, dma);
+ }
+ 
+ /* --------------------------------------------------------------------- */
+@@ -347,7 +342,7 @@ videobuf_vm_close(struct vm_area_struct *vma)
+ {
+ 	struct videobuf_mapping *map = vma->vm_private_data;
+ 	struct videobuf_queue *q = map->q;
+-	struct videbuf_pci_sg_memory *mem;
++	struct videobuf_dma_sg_memory *mem;
+ 	int i;
+ 
+ 	dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map,
+@@ -409,18 +404,18 @@ static struct vm_operations_struct videobuf_vm_ops =
+ };
+ 
+ /* ---------------------------------------------------------------------
+- * PCI handlers for the generic methods
++ * SG handlers for the generic methods
+  */
+ 
+ /* Allocated area consists on 3 parts:
+ 	struct video_buffer
+ 	struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
+-	struct videobuf_pci_sg_memory
++	struct videobuf_dma_sg_memory
+  */
+ 
+ static void *__videobuf_alloc(size_t size)
+ {
+-	struct videbuf_pci_sg_memory *mem;
++	struct videobuf_dma_sg_memory *mem;
+ 	struct videobuf_buffer *vb;
+ 
+ 	vb = kzalloc(size+sizeof(*mem),GFP_KERNEL);
+@@ -431,22 +426,32 @@ static void *__videobuf_alloc(size_t size)
+ 	videobuf_dma_init(&mem->dma);
+ 
+ 	dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
+-		__FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
++		__func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+ 		mem,(long)sizeof(*mem));
+ 
+ 	return vb;
+ }
+ 
++static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf)
++{
++	struct videobuf_dma_sg_memory *mem = buf->priv;
++	BUG_ON(!mem);
++
++	MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
++
++	return mem->dma.vmalloc;
++}
++
+ static int __videobuf_iolock (struct videobuf_queue* q,
+ 			      struct videobuf_buffer *vb,
+ 			      struct v4l2_framebuffer *fbuf)
+ {
+ 	int err,pages;
+ 	dma_addr_t bus;
+-	struct videbuf_pci_sg_memory *mem=vb->priv;
++	struct videobuf_dma_sg_memory *mem = vb->priv;
+ 	BUG_ON(!mem);
+ 
+-	MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
++	MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+ 
+ 	switch (vb->memory) {
+ 	case V4L2_MEMORY_MMAP:
+@@ -455,14 +460,14 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ 			/* no userspace addr -- kernel bounce buffer */
+ 			pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+ 			err = videobuf_dma_init_kernel( &mem->dma,
+-							PCI_DMA_FROMDEVICE,
++							DMA_FROM_DEVICE,
+ 							pages );
+ 			if (0 != err)
+ 				return err;
+ 		} else if (vb->memory == V4L2_MEMORY_USERPTR) {
+ 			/* dma directly to userspace */
+ 			err = videobuf_dma_init_user( &mem->dma,
+-						      PCI_DMA_FROMDEVICE,
++						      DMA_FROM_DEVICE,
+ 						      vb->baddr,vb->bsize );
+ 			if (0 != err)
+ 				return err;
+@@ -473,7 +478,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ 			locking inversion, so don't take it here */
+ 
+ 			err = videobuf_dma_init_user_locked(&mem->dma,
+-						      PCI_DMA_FROMDEVICE,
++						      DMA_FROM_DEVICE,
+ 						      vb->baddr, vb->bsize);
+ 			if (0 != err)
+ 				return err;
+@@ -490,7 +495,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ 		 */
+ 		bus   = (dma_addr_t)(unsigned long)fbuf->base + vb->boff;
+ 		pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+-		err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE,
++		err = videobuf_dma_init_overlay(&mem->dma, DMA_FROM_DEVICE,
+ 						bus, pages);
+ 		if (0 != err)
+ 			return err;
+@@ -498,7 +503,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ 	default:
+ 		BUG();
+ 	}
+-	err = videobuf_dma_map(q,&mem->dma);
++	err = videobuf_dma_map(q, &mem->dma);
+ 	if (0 != err)
+ 		return err;
+ 
+@@ -508,8 +513,8 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ static int __videobuf_sync(struct videobuf_queue *q,
+ 			   struct videobuf_buffer *buf)
+ {
+-	struct videbuf_pci_sg_memory *mem=buf->priv;
+-	BUG_ON (!mem);
++	struct videobuf_dma_sg_memory *mem = buf->priv;
++	BUG_ON(!mem);
+ 	MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+ 
+ 	return	videobuf_dma_sync(q,&mem->dma);
+@@ -532,7 +537,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
+ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ 			 struct vm_area_struct *vma)
+ {
+-	struct videbuf_pci_sg_memory *mem;
++	struct videobuf_dma_sg_memory *mem;
+ 	struct videobuf_mapping *map;
+ 	unsigned int first,last,size,i;
+ 	int retval;
+@@ -547,12 +552,20 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ 		goto done;
+ 	}
+ 
++	/* This function maintains backwards compatibility with V4L1 and will
++	 * map more than one buffer if the vma length is equal to the combined
++	 * size of multiple buffers than it will map them together.  See
++	 * VIDIOCGMBUF in the v4l spec
++	 *
++	 * TODO: Allow drivers to specify if they support this mode
++	 */
++
+ 	/* look for first buffer to map */
+ 	for (first = 0; first < VIDEO_MAX_FRAME; first++) {
+ 		if (NULL == q->bufs[first])
+ 			continue;
+ 		mem=q->bufs[first]->priv;
+-		BUG_ON (!mem);
++		BUG_ON(!mem);
+ 		MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+ 
+ 		if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
+@@ -591,10 +604,16 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ 	map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
+ 	if (NULL == map)
+ 		goto done;
+-	for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) {
++
++	size = 0;
++	for (i = first; i <= last; i++) {
++		if (NULL == q->bufs[i])
++			continue;
+ 		q->bufs[i]->map   = map;
+ 		q->bufs[i]->baddr = vma->vm_start + size;
++		size += q->bufs[i]->bsize;
+ 	}
++
+ 	map->count    = 1;
+ 	map->start    = vma->vm_start;
+ 	map->end      = vma->vm_end;
+@@ -615,8 +634,8 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q,
+ 				char __user *data, size_t count,
+ 				int nonblocking )
+ {
+-	struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
+-	BUG_ON (!mem);
++	struct videobuf_dma_sg_memory *mem = q->read_buf->priv;
++	BUG_ON(!mem);
+ 	MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+ 
+ 	/* copy to userspace */
+@@ -634,8 +653,8 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q,
+ 				int vbihack, int nonblocking )
+ {
+ 	unsigned int  *fc;
+-	struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
+-	BUG_ON (!mem);
++	struct videobuf_dma_sg_memory *mem = q->read_buf->priv;
++	BUG_ON(!mem);
+ 	MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+ 
+ 	if (vbihack) {
+@@ -658,7 +677,7 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q,
+ 	return count;
+ }
+ 
+-static struct videobuf_qtype_ops pci_ops = {
++static struct videobuf_qtype_ops sg_ops = {
+ 	.magic        = MAGIC_QTYPE_OPS,
+ 
+ 	.alloc        = __videobuf_alloc,
+@@ -668,23 +687,24 @@ static struct videobuf_qtype_ops pci_ops = {
+ 	.mmap_mapper  = __videobuf_mmap_mapper,
+ 	.video_copy_to_user = __videobuf_copy_to_user,
+ 	.copy_stream  = __videobuf_copy_stream,
++	.vmalloc      = __videobuf_to_vmalloc,
+ };
+ 
+-void *videobuf_pci_alloc (size_t size)
++void *videobuf_sg_alloc(size_t size)
+ {
+ 	struct videobuf_queue q;
+ 
+ 	/* Required to make generic handler to call __videobuf_alloc */
+-	q.int_ops=&pci_ops;
++	q.int_ops = &sg_ops;
+ 
+-	q.msize=size;
++	q.msize = size;
+ 
+-	return videobuf_alloc (&q);
++	return videobuf_alloc(&q);
+ }
+ 
+-void videobuf_queue_pci_init(struct videobuf_queue* q,
++void videobuf_queue_sg_init(struct videobuf_queue* q,
+ 			 struct videobuf_queue_ops *ops,
+-			 void *dev,
++			 struct device *dev,
+ 			 spinlock_t *irqlock,
+ 			 enum v4l2_buf_type type,
+ 			 enum v4l2_field field,
+@@ -692,7 +712,7 @@ void videobuf_queue_pci_init(struct videobuf_queue* q,
+ 			 void *priv)
+ {
+ 	videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
+-				 priv, &pci_ops);
++				 priv, &sg_ops);
+ }
+ 
+ /* --------------------------------------------------------------------- */
+@@ -709,11 +729,11 @@ EXPORT_SYMBOL_GPL(videobuf_dma_sync);
+ EXPORT_SYMBOL_GPL(videobuf_dma_unmap);
+ EXPORT_SYMBOL_GPL(videobuf_dma_free);
+ 
+-EXPORT_SYMBOL_GPL(videobuf_pci_dma_map);
+-EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap);
+-EXPORT_SYMBOL_GPL(videobuf_pci_alloc);
++EXPORT_SYMBOL_GPL(videobuf_sg_dma_map);
++EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap);
++EXPORT_SYMBOL_GPL(videobuf_sg_alloc);
+ 
+-EXPORT_SYMBOL_GPL(videobuf_queue_pci_init);
++EXPORT_SYMBOL_GPL(videobuf_queue_sg_init);
+ 
+ /*
+  * Local variables:
+diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c
+index b73aba6..6e4d73e 100644
+--- a/drivers/media/video/videobuf-dvb.c
++++ b/drivers/media/video/videobuf-dvb.c
+@@ -20,9 +20,10 @@
+ #include <linux/fs.h>
+ #include <linux/kthread.h>
+ #include <linux/file.h>
++
+ #include <linux/freezer.h>
+ 
+-#include <media/videobuf-dma-sg.h>
++#include <media/videobuf-core.h>
+ #include <media/videobuf-dvb.h>
+ 
+ /* ------------------------------------------------------------------ */
+@@ -30,7 +31,7 @@
+ MODULE_AUTHOR("Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]");
+ MODULE_LICENSE("GPL");
+ 
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"enable debug messages");
+ 
+@@ -45,7 +46,7 @@ static int videobuf_dvb_thread(void *data)
+ 	struct videobuf_buffer *buf;
+ 	unsigned long flags;
+ 	int err;
+-	struct videobuf_dmabuf *dma;
++	void *outp;
+ 
+ 	dprintk("dvb thread started\n");
+ 	set_freezable();
+@@ -66,9 +67,10 @@ static int videobuf_dvb_thread(void *data)
+ 		try_to_freeze();
+ 
+ 		/* feed buffer data to demux */
+-		dma=videobuf_to_dma(buf);
++		outp = videobuf_queue_to_vmalloc (&dvb->dvbq, buf);
++
+ 		if (buf->state == VIDEOBUF_DONE)
+-			dvb_dmx_swfilter(&dvb->demux, dma->vmalloc,
++			dvb_dmx_swfilter(&dvb->demux, outp,
+ 					 buf->size);
+ 
+ 		/* requeue buffer */
+@@ -138,14 +140,16 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
+ int videobuf_dvb_register(struct videobuf_dvb *dvb,
+ 			  struct module *module,
+ 			  void *adapter_priv,
+-			  struct device *device)
++			  struct device *device,
++			  short *adapter_nr)
+ {
+ 	int result;
+ 
+ 	mutex_init(&dvb->lock);
+ 
+ 	/* register adapter */
+-	result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device);
++	result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device,
++				      adapter_nr);
+ 	if (result < 0) {
+ 		printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
+ 		       dvb->name, result);
+diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c
+index 5266ecc..c91e1d8 100644
+--- a/drivers/media/video/videobuf-vmalloc.c
++++ b/drivers/media/video/videobuf-vmalloc.c
+@@ -33,7 +33,7 @@
+ #define MAGIC_CHECK(is,should)	if (unlikely((is) != (should))) \
+ 	{ printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ 
+ MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
+@@ -57,20 +57,26 @@ videobuf_vm_open(struct vm_area_struct *vma)
+ 	map->count++;
+ }
+ 
+-static void
+-videobuf_vm_close(struct vm_area_struct *vma)
++static void videobuf_vm_close(struct vm_area_struct *vma)
+ {
+ 	struct videobuf_mapping *map = vma->vm_private_data;
+ 	struct videobuf_queue *q = map->q;
+ 	int i;
+ 
+-	dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n",map,
+-		map->count,vma->vm_start,vma->vm_end);
++	dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
++		map->count, vma->vm_start, vma->vm_end);
+ 
+ 	map->count--;
+ 	if (0 == map->count) {
+-		dprintk(1,"munmap %p q=%p\n",map,q);
++		struct videobuf_vmalloc_memory *mem;
++
++		dprintk(1, "munmap %p q=%p\n", map, q);
+ 		mutex_lock(&q->vb_lock);
++
++		/* We need first to cancel streams, before unmapping */
++		if (q->streaming)
++			videobuf_queue_cancel(q);
++
+ 		for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ 			if (NULL == q->bufs[i])
+ 				continue;
+@@ -78,14 +84,35 @@ videobuf_vm_close(struct vm_area_struct *vma)
+ 			if (q->bufs[i]->map != map)
+ 				continue;
+ 
+-			q->ops->buf_release(q,q->bufs[i]);
++			mem = q->bufs[i]->priv;
++			if (mem) {
++				/* This callback is called only if kernel has
++				   allocated memory and this memory is mmapped.
++				   In this case, memory should be freed,
++				   in order to do memory unmap.
++				 */
++
++				MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
++
++				/* vfree is not atomic - can't be
++				   called with IRQ's disabled
++				 */
++				dprintk(1, "%s: buf[%d] freeing (%p)\n",
++					__func__, i, mem->vmalloc);
++
++				vfree(mem->vmalloc);
++				mem->vmalloc = NULL;
++			}
+ 
+ 			q->bufs[i]->map   = NULL;
+ 			q->bufs[i]->baddr = 0;
+ 		}
+-		mutex_unlock(&q->vb_lock);
++
+ 		kfree(map);
++
++		mutex_unlock(&q->vb_lock);
+ 	}
++
+ 	return;
+ }
+ 
+@@ -102,7 +129,7 @@ static struct vm_operations_struct videobuf_vm_ops =
+ /* Allocated area consists on 3 parts:
+ 	struct video_buffer
+ 	struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
+-	struct videobuf_pci_sg_memory
++	struct videobuf_dma_sg_memory
+  */
+ 
+ static void *__videobuf_alloc(size_t size)
+@@ -116,7 +143,7 @@ static void *__videobuf_alloc(size_t size)
+ 	mem->magic=MAGIC_VMAL_MEM;
+ 
+ 	dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
+-		__FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
++		__func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+ 		mem,(long)sizeof(*mem));
+ 
+ 	return vb;
+@@ -126,45 +153,74 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ 			      struct videobuf_buffer *vb,
+ 			      struct v4l2_framebuffer *fbuf)
+ {
++	struct videobuf_vmalloc_memory *mem = vb->priv;
+ 	int pages;
+-	struct videobuf_vmalloc_memory *mem=vb->priv;
+ 
+ 	BUG_ON(!mem);
+ 
+-	MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
++	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+ 
+-	pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
++	switch (vb->memory) {
++	case V4L2_MEMORY_MMAP:
++		dprintk(1, "%s memory method MMAP\n", __func__);
+ 
+-	/* Currently, doesn't support V4L2_MEMORY_OVERLAY */
+-	if ((vb->memory != V4L2_MEMORY_MMAP) &&
+-				(vb->memory != V4L2_MEMORY_USERPTR) ) {
+-		printk(KERN_ERR "Method currently unsupported.\n");
+-		return -EINVAL;
+-	}
++		/* All handling should be done by __videobuf_mmap_mapper() */
++		if (!mem->vmalloc) {
++			printk(KERN_ERR "memory is not alloced/mmapped.\n");
++			return -EINVAL;
++		}
++		break;
++	case V4L2_MEMORY_USERPTR:
++		pages = PAGE_ALIGN(vb->size);
+ 
+-	/* FIXME: should be tested with kernel mmap mem */
+-	mem->vmalloc=vmalloc_user (PAGE_ALIGN(vb->size));
+-	if (NULL == mem->vmalloc) {
+-		printk(KERN_ERR "vmalloc (%d pages) failed\n",pages);
+-		return -ENOMEM;
+-	}
++		dprintk(1, "%s memory method USERPTR\n", __func__);
+ 
+-	dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
+-				(unsigned long)mem->vmalloc,
+-				pages << PAGE_SHIFT);
++#if 1
++		if (vb->baddr) {
++			printk(KERN_ERR "USERPTR is currently not supported\n");
++			return -EINVAL;
++		}
++#endif
+ 
+-	/* It seems that some kernel versions need to do remap *after*
+-	   the mmap() call
+-	 */
+-	if (mem->vma) {
+-		int retval=remap_vmalloc_range(mem->vma, mem->vmalloc,0);
+-		kfree(mem->vma);
+-		mem->vma=NULL;
+-		if (retval<0) {
+-			dprintk(1,"mmap app bug: remap_vmalloc_range area %p error %d\n",
+-				mem->vmalloc,retval);
+-			return retval;
++		/* The only USERPTR currently supported is the one needed for
++		   read() method.
++		 */
++
++		mem->vmalloc = vmalloc_user(pages);
++		if (!mem->vmalloc) {
++			printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
++			return -ENOMEM;
++		}
++		dprintk(1, "vmalloc is at addr %p (%d pages)\n",
++			mem->vmalloc, pages);
++
++#if 0
++		int rc;
++		/* Kernel userptr is used also by read() method. In this case,
++		   there's no need to remap, since data will be copied to user
++		 */
++		if (!vb->baddr)
++			return 0;
++
++		/* FIXME: to properly support USERPTR, remap should occur.
++		   The code bellow won't work, since mem->vma = NULL
++		 */
++		/* Try to remap memory */
++		rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
++		if (rc < 0) {
++			printk(KERN_ERR "mmap: remap failed with error %d. ", rc);
++			return -ENOMEM;
+ 		}
++#endif
++
++		break;
++	case V4L2_MEMORY_OVERLAY:
++	default:
++		dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
++
++		/* Currently, doesn't support V4L2_MEMORY_OVERLAY */
++		printk(KERN_ERR "Memory method currently unsupported.\n");
++		return -EINVAL;
+ 	}
+ 
+ 	return 0;
+@@ -180,6 +236,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
+ {
+ 	unsigned int i;
+ 
++	dprintk(1, "%s\n", __func__);
+ 	for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ 		if (q->bufs[i]) {
+ 			if (q->bufs[i]->map)
+@@ -196,10 +253,11 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ 	struct videobuf_vmalloc_memory *mem;
+ 	struct videobuf_mapping *map;
+ 	unsigned int first;
+-	int retval;
++	int retval, pages;
+ 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ 
+-	if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED))
++	dprintk(1, "%s\n", __func__);
++	if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
+ 		return -EINVAL;
+ 
+ 	/* look for first buffer to map */
+@@ -219,46 +277,55 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ 	}
+ 
+ 	/* create mapping + update buffer list */
+-	map = q->bufs[first]->map = kzalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
++	map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
+ 	if (NULL == map)
+ 		return -ENOMEM;
+ 
++	q->bufs[first]->map = map;
+ 	map->start = vma->vm_start;
+ 	map->end   = vma->vm_end;
+ 	map->q     = q;
+ 
+ 	q->bufs[first]->baddr = vma->vm_start;
+ 
+-	vma->vm_ops          = &videobuf_vm_ops;
+-	vma->vm_flags       |= VM_DONTEXPAND | VM_RESERVED;
+-	vma->vm_private_data = map;
++	mem = q->bufs[first]->priv;
++	BUG_ON(!mem);
++	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+ 
+-	mem=q->bufs[first]->priv;
+-	BUG_ON (!mem);
+-	MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
++	pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
++	mem->vmalloc = vmalloc_user(pages);
++	if (!mem->vmalloc) {
++		printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
++		goto error;
++	}
++	dprintk(1, "vmalloc is at addr %p (%d pages)\n",
++		mem->vmalloc, pages);
+ 
+ 	/* Try to remap memory */
+-	retval=remap_vmalloc_range(vma, mem->vmalloc,0);
+-	if (retval<0) {
+-		dprintk(1,"mmap: postponing remap_vmalloc_range\n");
+-
+-		mem->vma=kmalloc(sizeof(*vma),GFP_KERNEL);
+-		if (!mem->vma) {
+-			kfree(map);
+-			q->bufs[first]->map=NULL;
+-			return -ENOMEM;
+-		}
+-		memcpy(mem->vma,vma,sizeof(*vma));
++	retval = remap_vmalloc_range(vma, mem->vmalloc, 0);
++	if (retval < 0) {
++		printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
++		vfree(mem->vmalloc);
++		goto error;
+ 	}
+ 
++	vma->vm_ops          = &videobuf_vm_ops;
++	vma->vm_flags       |= VM_DONTEXPAND | VM_RESERVED;
++	vma->vm_private_data = map;
++
+ 	dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
+-		map,q,vma->vm_start,vma->vm_end,
++		map, q, vma->vm_start, vma->vm_end,
+ 		(long int) q->bufs[first]->bsize,
+-		vma->vm_pgoff,first);
++		vma->vm_pgoff, first);
+ 
+ 	videobuf_vm_open(vma);
+ 
+-	return (0);
++	return 0;
++
++error:
++	mem = NULL;
++	kfree(map);
++	return -ENOMEM;
+ }
+ 
+ static int __videobuf_copy_to_user ( struct videobuf_queue *q,
+@@ -320,6 +387,7 @@ static struct videobuf_qtype_ops qops = {
+ 	.mmap_mapper  = __videobuf_mmap_mapper,
+ 	.video_copy_to_user = __videobuf_copy_to_user,
+ 	.copy_stream  = __videobuf_copy_stream,
++	.vmalloc      = videobuf_to_vmalloc,
+ };
+ 
+ void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
+@@ -349,13 +417,24 @@ EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
+ 
+ void videobuf_vmalloc_free (struct videobuf_buffer *buf)
+ {
+-	struct videobuf_vmalloc_memory *mem=buf->priv;
+-	BUG_ON (!mem);
++	struct videobuf_vmalloc_memory *mem = buf->priv;
+ 
+-	MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
++	/* mmapped memory can't be freed here, otherwise mmapped region
++	   would be released, while still needed. In this case, the memory
++	   release should happen inside videobuf_vm_close().
++	   So, it should free memory only if the memory were allocated for
++	   read() operation.
++	 */
++	if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0))
++		return;
++
++	if (!mem)
++		return;
++
++	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+ 
+ 	vfree(mem->vmalloc);
+-	mem->vmalloc=NULL;
++	mem->vmalloc = NULL;
+ 
+ 	return;
+ }
+diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c
+index 87951ec..cf24956 100644
+--- a/drivers/media/video/videocodec.c
++++ b/drivers/media/video/videocodec.c
+@@ -39,12 +39,13 @@
+ 
+ #ifdef CONFIG_PROC_FS
+ #include <linux/proc_fs.h>
++#include <linux/seq_file.h>
+ #include <asm/uaccess.h>
+ #endif
+ 
+ #include "videocodec.h"
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-4)");
+ 
+@@ -320,56 +321,22 @@ videocodec_unregister (const struct videocodec *codec)
+ }
+ 
+ #ifdef CONFIG_PROC_FS
+-/* ============ */
+-/* procfs stuff */
+-/* ============ */
+-
+-static char *videocodec_buf = NULL;
+-static int videocodec_bufsize = 0;
+-
+-static int
+-videocodec_build_table (void)
++static int proc_videocodecs_show(struct seq_file *m, void *v)
+ {
+ 	struct codec_list *h = codeclist_top;
+ 	struct attached_list *a;
+-	int i = 0, size;
+-
+-	// sum up amount of slaves plus their attached masters
+-	while (h) {
+-		i += h->attached + 1;
+-		h = h->next;
+-	}
+-#define LINESIZE 100
+-	size = LINESIZE * (i + 1);
+ 
+-	dprintk(3, "videocodec_build table: %d entries, %d bytes\n", i,
+-		size);
+-
+-	kfree(videocodec_buf);
+-	videocodec_buf = kmalloc(size, GFP_KERNEL);
+-
+-	if (!videocodec_buf)
+-		return 0;
+-
+-	i = 0;
+-	i += scnprintf(videocodec_buf + i, size - 1,
+-		      "<S>lave or attached <M>aster name  type flags    magic    ");
+-	i += scnprintf(videocodec_buf + i, size -i - 1, "(connected as)\n");
++	seq_printf(m, "<S>lave or attached <M>aster name  type flags    magic    ");
++	seq_printf(m, "(connected as)\n");
+ 
+ 	h = codeclist_top;
+ 	while (h) {
+-		if (i > (size - LINESIZE))
+-			break;	// security check
+-		i += scnprintf(videocodec_buf + i, size -i -1,
+-			      "S %32s %04x %08lx %08lx (TEMPLATE)\n",
++		seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
+ 			      h->codec->name, h->codec->type,
+ 			      h->codec->flags, h->codec->magic);
+ 		a = h->list;
+ 		while (a) {
+-			if (i > (size - LINESIZE))
+-				break;	// security check
+-			i += scnprintf(videocodec_buf + i, size -i -1,
+-				      "M %32s %04x %08lx %08lx (%s)\n",
++			seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
+ 				      a->codec->master_data->name,
+ 				      a->codec->master_data->type,
+ 				      a->codec->master_data->flags,
+@@ -380,54 +347,21 @@ videocodec_build_table (void)
+ 		h = h->next;
+ 	}
+ 
+-	return i;
++	return 0;
+ }
+ 
+-//The definition:
+-//typedef int (read_proc_t)(char *page, char **start, off_t off,
+-//                          int count, int *eof, void *data);
+-
+-static int
+-videocodec_info (char  *buffer,
+-		 char **buffer_location,
+-		 off_t  offset,
+-		 int    buffer_length,
+-		 int   *eof,
+-		 void  *data)
++static int proc_videocodecs_open(struct inode *inode, struct file *file)
+ {
+-	int size;
+-
+-	dprintk(3, "videocodec_info: offset: %ld, len %d / size %d\n",
+-		offset, buffer_length, videocodec_bufsize);
+-
+-	if (offset == 0) {
+-		videocodec_bufsize = videocodec_build_table();
+-	}
+-	if ((offset < 0) || (offset >= videocodec_bufsize)) {
+-		dprintk(4,
+-			"videocodec_info: call delivers no result, return 0\n");
+-		*eof = 1;
+-		return 0;
+-	}
+-
+-	if (buffer_length < (videocodec_bufsize - offset)) {
+-		dprintk(4, "videocodec_info: %ld needed, %d got\n",
+-			videocodec_bufsize - offset, buffer_length);
+-		size = buffer_length;
+-	} else {
+-		dprintk(4, "videocodec_info: last reading of %ld bytes\n",
+-			videocodec_bufsize - offset);
+-		size = videocodec_bufsize - offset;
+-		*eof = 1;
+-	}
+-
+-	memcpy(buffer, videocodec_buf + offset, size);
+-	/* doesn't work...                           */
+-	/* copy_to_user(buffer, videocodec_buf+offset, size); */
+-	/* *buffer_location = videocodec_buf+offset; */
+-
+-	return size;
++	return single_open(file, proc_videocodecs_show, NULL);
+ }
++
++static const struct file_operations videocodecs_proc_fops = {
++	.owner		= THIS_MODULE,
++	.open		= proc_videocodecs_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
+ #endif
+ 
+ /* ===================== */
+@@ -444,16 +378,8 @@ videocodec_init (void)
+ 	       VIDEOCODEC_VERSION);
+ 
+ #ifdef CONFIG_PROC_FS
+-	videocodec_buf = NULL;
+-	videocodec_bufsize = 0;
+-
+-	videocodec_proc_entry = create_proc_entry("videocodecs", 0, NULL);
+-	if (videocodec_proc_entry) {
+-		videocodec_proc_entry->read_proc = videocodec_info;
+-		videocodec_proc_entry->write_proc = NULL;
+-		videocodec_proc_entry->data = NULL;
+-		videocodec_proc_entry->owner = THIS_MODULE;
+-	} else {
++	videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops);
++	if (!videocodec_proc_entry) {
+ 		dprintk(1, KERN_ERR "videocodec: can't init procfs.\n");
+ 	}
+ #endif
+@@ -465,7 +391,6 @@ videocodec_exit (void)
+ {
+ #ifdef CONFIG_PROC_FS
+ 	remove_proc_entry("videocodecs", NULL);
+-	kfree(videocodec_buf);
+ #endif
+ }
+ 
+diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
+index 0d9b637..31e8af0 100644
+--- a/drivers/media/video/videodev.c
++++ b/drivers/media/video/videodev.c
+@@ -18,14 +18,14 @@
+ 
+ #define dbgarg(cmd, fmt, arg...) \
+ 		if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {		\
+-			printk (KERN_DEBUG "%s: ",  vfd->name);		\
++			printk(KERN_DEBUG "%s: ",  vfd->name);		\
+ 			v4l_printk_ioctl(cmd);				\
+-			printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); \
++			printk(" " fmt,  ## arg);			\
+ 		}
+ 
+ #define dbgarg2(fmt, arg...) \
+ 		if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)			\
+-			printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
++			printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+ 
+ #include <linux/module.h>
+ #include <linux/types.h>
+@@ -378,38 +378,45 @@ static const char *v4l2_int_ioctls[] = {
+    external ioctl messages as well as internal V4L ioctl */
+ void v4l_printk_ioctl(unsigned int cmd)
+ {
+-	char *dir;
++	char *dir, *type;
+ 
+-	switch (_IOC_DIR(cmd)) {
+-	case _IOC_NONE:              dir = "--"; break;
+-	case _IOC_READ:              dir = "r-"; break;
+-	case _IOC_WRITE:             dir = "-w"; break;
+-	case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+-	default:                     dir = "*ERR*"; break;
+-	}
+ 	switch (_IOC_TYPE(cmd)) {
+ 	case 'd':
+-		printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n",
+-		       (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
+-		       v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+-		break;
++		if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) {
++			type = "v4l2_int";
++			break;
++		}
++		printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]);
++		return;
+ #ifdef CONFIG_VIDEO_V4L1_COMPAT
+ 	case 'v':
+-		printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
+-		       (_IOC_NR(cmd) < V4L1_IOCTLS) ?
+-		       v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+-		break;
++		if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
++			type = "v4l1";
++			break;
++		}
++		printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
++		return;
+ #endif
+ 	case 'V':
+-		printk("v4l2 ioctl %s, dir=%s (0x%08x)\n",
+-		       (_IOC_NR(cmd) < V4L2_IOCTLS) ?
+-		       v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+-		break;
+-
++		if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
++			type = "v4l2";
++			break;
++		}
++		printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
++		return;
+ 	default:
+-		printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n",
+-		       _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
++		type = "unknown";
++	}
++
++	switch (_IOC_DIR(cmd)) {
++	case _IOC_NONE:              dir = "--"; break;
++	case _IOC_READ:              dir = "r-"; break;
++	case _IOC_WRITE:             dir = "-w"; break;
++	case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
++	default:                     dir = "*ERR*"; break;
+ 	}
++	printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
++		type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
+ }
+ EXPORT_SYMBOL(v4l_printk_ioctl);
+ 
+@@ -774,6 +781,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
+ 	if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
+ 				!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
+ 		v4l_print_ioctl(vfd->name, cmd);
++		printk("\n");
+ 	}
+ 
+ #ifdef CONFIG_VIDEO_V4L1_COMPAT
+@@ -1853,12 +1861,20 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
+ 			dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
+ 		break;
+ 	}
++	default:
++	{
++		if (!vfd->vidioc_default)
++			break;
++		ret = vfd->vidioc_default(file, fh, cmd, arg);
++		break;
++	}
+ 	} /* switch */
+ 
+ 	if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
+ 		if (ret<0) {
+-			printk ("%s: err:\n", vfd->name);
++			printk("%s: err: on ", vfd->name);
+ 			v4l_print_ioctl(vfd->name, cmd);
++			printk("\n");
+ 		}
+ 	}
+ 
+@@ -2019,7 +2035,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
+ 			break;
+ 		default:
+ 			printk(KERN_ERR "%s called with unknown type: %d\n",
+-			       __FUNCTION__, type);
++			       __func__, type);
+ 			return -1;
+ 	}
+ 
+@@ -2057,7 +2073,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
+ 	ret = device_register(&vfd->class_dev);
+ 	if (ret < 0) {
+ 		printk(KERN_ERR "%s: device_register failed\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		goto fail_minor;
+ 	}
+ 
+diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
+index 5bb7529..d545c98 100644
+--- a/drivers/media/video/vino.c
++++ b/drivers/media/video/vino.c
+@@ -333,7 +333,7 @@ struct vino_settings {
+  *
+  * Use non-zero value to enable conversion.
+  */
+-static int vino_pixel_conversion = 0;
++static int vino_pixel_conversion;
+ 
+ module_param_named(pixelconv, vino_pixel_conversion, int, 0);
+ 
+@@ -4370,8 +4370,8 @@ static int vino_ioctl(struct inode *inode, struct file *file,
+ 
+ /* Initialization and cleanup */
+ 
+-// __initdata
+-static int vino_init_stage = 0;
++/* __initdata */
++static int vino_init_stage;
+ 
+ static const struct file_operations vino_fops = {
+ 	.owner		= THIS_MODULE,
+@@ -4385,8 +4385,8 @@ static const struct file_operations vino_fops = {
+ 
+ static struct video_device v4l_device_template = {
+ 	.name		= "NOT SET",
+-	//.type		= VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE |
+-	//	VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY
++	/*.type		= VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | */
++	/*	VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY */
+ 	.fops		= &vino_fops,
+ 	.minor		= -1,
+ };
+diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
+index 1db067c..845be18 100644
+--- a/drivers/media/video/vivi.c
++++ b/drivers/media/video/vivi.c
+@@ -146,8 +146,6 @@ struct vivi_buffer {
+ 
+ struct vivi_dmaqueue {
+ 	struct list_head       active;
+-	struct list_head       queued;
+-	struct timer_list      timeout;
+ 
+ 	/* thread for generating video stream*/
+ 	struct task_struct         *kthread;
+@@ -162,8 +160,8 @@ static LIST_HEAD(vivi_devlist);
+ struct vivi_dev {
+ 	struct list_head           vivi_devlist;
+ 
+-	struct mutex               lock;
+ 	spinlock_t                 slock;
++	struct mutex		   mutex;
+ 
+ 	int                        users;
+ 
+@@ -322,24 +320,26 @@ static void gen_line(char *basep, int inipos, int wmax,
+ end:
+ 	return;
+ }
++
+ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
+ {
+ 	int h , pos = 0;
+ 	int hmax  = buf->vb.height;
+ 	int wmax  = buf->vb.width;
+ 	struct timeval ts;
+-	char *tmpbuf = kmalloc(wmax * 2, GFP_KERNEL);
++	char *tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
+ 	void *vbuf = videobuf_to_vmalloc(&buf->vb);
+ 
+ 	if (!tmpbuf)
+ 		return;
+ 
++	if (!vbuf)
++		return;
++
+ 	for (h = 0; h < hmax; h++) {
+ 		gen_line(tmpbuf, 0, wmax, hmax, h, dev->mv_count,
+ 			 dev->timestr);
+-		/* FIXME: replacing to __copy_to_user */
+-		if (copy_to_user(vbuf + pos, tmpbuf, wmax * 2) != 0)
+-			dprintk(dev, 2, "vivifill copy_to_user failed.\n");
++		memcpy(vbuf + pos, tmpbuf, wmax * 2);
+ 		pos += wmax*2;
+ 	}
+ 
+@@ -372,107 +372,71 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
+ 			dev->timestr, (unsigned long)tmpbuf, pos);
+ 
+ 	/* Advice that buffer was filled */
+-	buf->vb.state = VIDEOBUF_DONE;
+ 	buf->vb.field_count++;
+ 	do_gettimeofday(&ts);
+ 	buf->vb.ts = ts;
+-
+-	list_del(&buf->vb.queue);
+-	wake_up(&buf->vb.done);
++	buf->vb.state = VIDEOBUF_DONE;
+ }
+ 
+-static int restart_video_queue(struct vivi_dmaqueue *dma_q);
+-
+-static void vivi_thread_tick(struct vivi_dmaqueue  *dma_q)
++static void vivi_thread_tick(struct vivi_fh *fh)
+ {
+-	struct vivi_buffer    *buf;
+-	struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
++	struct vivi_buffer *buf;
++	struct vivi_dev *dev = fh->dev;
++	struct vivi_dmaqueue *dma_q = &dev->vidq;
+ 
+-	int bc;
++	unsigned long flags = 0;
+ 
+-	spin_lock(&dev->slock);
+-	/* Announces videobuf that all went ok */
+-	for (bc = 0;; bc++) {
+-		if (list_empty(&dma_q->active)) {
+-			dprintk(dev, 1, "No active queue to serve\n");
+-			break;
+-		}
++	dprintk(dev, 1, "Thread tick\n");
+ 
+-		buf = list_entry(dma_q->active.next,
+-				 struct vivi_buffer, vb.queue);
++	spin_lock_irqsave(&dev->slock, flags);
++	if (list_empty(&dma_q->active)) {
++		dprintk(dev, 1, "No active queue to serve\n");
++		goto unlock;
++	}
+ 
+-		/* Nobody is waiting something to be done, just return */
+-		if (!waitqueue_active(&buf->vb.done)) {
+-			mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+-			spin_unlock(&dev->slock);
+-			return;
+-		}
++	buf = list_entry(dma_q->active.next,
++			 struct vivi_buffer, vb.queue);
++
++	/* Nobody is waiting on this buffer, return */
++	if (!waitqueue_active(&buf->vb.done))
++		goto unlock;
+ 
+-		do_gettimeofday(&buf->vb.ts);
+-		dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
++	list_del(&buf->vb.queue);
+ 
+-		/* Fill buffer */
+-		vivi_fillbuff(dev, buf);
++	do_gettimeofday(&buf->vb.ts);
+ 
+-		if (list_empty(&dma_q->active)) {
+-			del_timer(&dma_q->timeout);
+-		} else {
+-			mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT);
+-		}
+-	}
+-	if (bc != 1)
+-		dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n",
+-			__FUNCTION__, bc);
+-	spin_unlock(&dev->slock);
++	/* Fill buffer */
++	vivi_fillbuff(dev, buf);
++	dprintk(dev, 1, "filled buffer %p\n", buf);
++
++	wake_up(&buf->vb.done);
++	dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
++unlock:
++	spin_unlock_irqrestore(&dev->slock, flags);
++	return;
+ }
+ 
+ #define frames_to_ms(frames)					\
+ 	((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
+ 
+-static void vivi_sleep(struct vivi_dmaqueue  *dma_q)
++static void vivi_sleep(struct vivi_fh *fh)
+ {
+-	struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+-	int timeout, running_time;
++	struct vivi_dev *dev = fh->dev;
++	struct vivi_dmaqueue *dma_q = &dev->vidq;
++	int timeout;
+ 	DECLARE_WAITQUEUE(wait, current);
+ 
+-	dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
++	dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
+ 		(unsigned long)dma_q);
+ 
+ 	add_wait_queue(&dma_q->wq, &wait);
+ 	if (kthread_should_stop())
+ 		goto stop_task;
+ 
+-	running_time = jiffies - dma_q->ini_jiffies;
+-	dma_q->frame++;
+-
+ 	/* Calculate time to wake up */
+-	timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) - running_time;
+-
+-	if (timeout > msecs_to_jiffies(frames_to_ms(2)) || timeout <= 0) {
+-		int old = dma_q->frame;
+-		int nframes;
+-
+-		dma_q->frame = (jiffies_to_msecs(running_time) /
+-			       frames_to_ms(1)) + 1;
+-
+-		timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame))
+-			  - running_time;
+-
+-		if (unlikely (timeout <= 0))
+-			timeout = 1;
+-
+-		nframes = (dma_q->frame > old)?
+-				  dma_q->frame - old : old - dma_q->frame;
+-
+-		dprintk(dev, 1, "%ld: %s %d frames. "
+-			"Current frame is %d. Will sleep for %d jiffies\n",
+-			jiffies,
+-			(dma_q->frame > old)? "Underrun, losed" : "Overrun of",
+-			nframes, dma_q->frame, timeout);
+-	} else
+-		dprintk(dev, 1, "will sleep for %d jiffies\n", timeout);
++	timeout = msecs_to_jiffies(frames_to_ms(1));
+ 
+-	vivi_thread_tick(dma_q);
++	vivi_thread_tick(fh);
+ 
+ 	schedule_timeout_interruptible(timeout);
+ 
+@@ -483,16 +447,15 @@ stop_task:
+ 
+ static int vivi_thread(void *data)
+ {
+-	struct vivi_dmaqueue  *dma_q = data;
+-	struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
++	struct vivi_fh  *fh = data;
++	struct vivi_dev *dev = fh->dev;
+ 
+ 	dprintk(dev, 1, "thread started\n");
+ 
+-	mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+ 	set_freezable();
+ 
+ 	for (;;) {
+-		vivi_sleep(dma_q);
++		vivi_sleep(fh);
+ 
+ 		if (kthread_should_stop())
+ 			break;
+@@ -501,16 +464,17 @@ static int vivi_thread(void *data)
+ 	return 0;
+ }
+ 
+-static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
++static int vivi_start_thread(struct vivi_fh *fh)
+ {
+-	struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
++	struct vivi_dev *dev = fh->dev;
++	struct vivi_dmaqueue *dma_q = &dev->vidq;
+ 
+ 	dma_q->frame = 0;
+ 	dma_q->ini_jiffies = jiffies;
+ 
+-	dprintk(dev, 1, "%s\n", __FUNCTION__);
++	dprintk(dev, 1, "%s\n", __func__);
+ 
+-	dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi");
++	dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
+ 
+ 	if (IS_ERR(dma_q->kthread)) {
+ 		printk(KERN_ERR "vivi: kernel_thread() failed\n");
+@@ -519,7 +483,7 @@ static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
+ 	/* Wakes thread */
+ 	wake_up_interruptible(&dma_q->wq);
+ 
+-	dprintk(dev, 1, "returning from %s\n", __FUNCTION__);
++	dprintk(dev, 1, "returning from %s\n", __func__);
+ 	return 0;
+ }
+ 
+@@ -527,7 +491,7 @@ static void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
+ {
+ 	struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+ 
+-	dprintk(dev, 1, "%s\n", __FUNCTION__);
++	dprintk(dev, 1, "%s\n", __func__);
+ 	/* shutdown control thread */
+ 	if (dma_q->kthread) {
+ 		kthread_stop(dma_q->kthread);
+@@ -535,91 +499,6 @@ static void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
+ 	}
+ }
+ 
+-static int restart_video_queue(struct vivi_dmaqueue *dma_q)
+-{
+-	struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+-	struct vivi_buffer *buf, *prev;
+-
+-	dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
+-		(unsigned long)dma_q);
+-
+-	if (!list_empty(&dma_q->active)) {
+-		buf = list_entry(dma_q->active.next,
+-				 struct vivi_buffer, vb.queue);
+-		dprintk(dev, 2, "restart_queue [%p/%d]: restart dma\n",
+-			buf, buf->vb.i);
+-
+-		dprintk(dev, 1, "Restarting video dma\n");
+-		vivi_stop_thread(dma_q);
+-
+-		/* cancel all outstanding capture / vbi requests */
+-		list_for_each_entry_safe(buf, prev, &dma_q->active, vb.queue) {
+-			list_del(&buf->vb.queue);
+-			buf->vb.state = VIDEOBUF_ERROR;
+-			wake_up(&buf->vb.done);
+-		}
+-		mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+-
+-		return 0;
+-	}
+-
+-	prev = NULL;
+-	for (;;) {
+-		if (list_empty(&dma_q->queued))
+-			return 0;
+-		buf = list_entry(dma_q->queued.next,
+-				 struct vivi_buffer, vb.queue);
+-		if (NULL == prev) {
+-			list_del(&buf->vb.queue);
+-			list_add_tail(&buf->vb.queue, &dma_q->active);
+-
+-			dprintk(dev, 1, "Restarting video dma\n");
+-			vivi_stop_thread(dma_q);
+-			vivi_start_thread(dma_q);
+-
+-			buf->vb.state = VIDEOBUF_ACTIVE;
+-			mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+-			dprintk(dev, 2,
+-				"[%p/%d] restart_queue - first active\n",
+-				buf, buf->vb.i);
+-
+-		} else if (prev->vb.width  == buf->vb.width  &&
+-			   prev->vb.height == buf->vb.height &&
+-			   prev->fmt       == buf->fmt) {
+-			list_del(&buf->vb.queue);
+-			list_add_tail(&buf->vb.queue, &dma_q->active);
+-			buf->vb.state = VIDEOBUF_ACTIVE;
+-			dprintk(dev, 2,
+-				"[%p/%d] restart_queue - move to active\n",
+-				buf, buf->vb.i);
+-		} else {
+-			return 0;
+-		}
+-		prev = buf;
+-	}
+-}
+-
+-static void vivi_vid_timeout(unsigned long data)
+-{
+-	struct vivi_dev      *dev  = (struct vivi_dev *)data;
+-	struct vivi_dmaqueue *vidq = &dev->vidq;
+-	struct vivi_buffer   *buf;
+-
+-	spin_lock(&dev->slock);
+-
+-	while (!list_empty(&vidq->active)) {
+-		buf = list_entry(vidq->active.next,
+-				 struct vivi_buffer, vb.queue);
+-		list_del(&buf->vb.queue);
+-		buf->vb.state = VIDEOBUF_ERROR;
+-		wake_up(&buf->vb.done);
+-		printk(KERN_INFO "vivi/0: [%p/%d] timeout\n", buf, buf->vb.i);
+-	}
+-	restart_video_queue(vidq);
+-
+-	spin_unlock(&dev->slock);
+-}
+-
+ /* ------------------------------------------------------------------
+ 	Videobuf operations
+    ------------------------------------------------------------------*/
+@@ -637,7 +516,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+ 	while (*size * *count > vid_limit * 1024 * 1024)
+ 		(*count)--;
+ 
+-	dprintk(dev, 1, "%s, count=%d, size=%d\n", __FUNCTION__,
++	dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
+ 		*count, *size);
+ 
+ 	return 0;
+@@ -648,13 +527,13 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
+ 	struct vivi_fh  *fh = vq->priv_data;
+ 	struct vivi_dev *dev  = fh->dev;
+ 
+-	dprintk(dev, 1, "%s\n", __FUNCTION__);
++	dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
+ 
+ 	if (in_interrupt())
+ 		BUG();
+ 
+-	videobuf_waiton(&buf->vb, 0, 0);
+ 	videobuf_vmalloc_free(&buf->vb);
++	dprintk(dev, 1, "free_buffer: freed\n");
+ 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ }
+ 
+@@ -667,28 +546,25 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+ 	struct vivi_fh     *fh  = vq->priv_data;
+ 	struct vivi_dev    *dev = fh->dev;
+ 	struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
+-	int rc, init_buffer = 0;
++	int rc;
+ 
+-	dprintk(dev, 1, "%s, field=%d\n", __FUNCTION__, field);
++	dprintk(dev, 1, "%s, field=%d\n", __func__, field);
+ 
+ 	BUG_ON(NULL == fh->fmt);
++
+ 	if (fh->width  < 48 || fh->width  > norm_maxw() ||
+ 	    fh->height < 32 || fh->height > norm_maxh())
+ 		return -EINVAL;
++
+ 	buf->vb.size = fh->width*fh->height*2;
+ 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+ 		return -EINVAL;
+ 
+-	if (buf->fmt       != fh->fmt    ||
+-	    buf->vb.width  != fh->width  ||
+-	    buf->vb.height != fh->height ||
+-	buf->vb.field  != field) {
+-		buf->fmt       = fh->fmt;
+-		buf->vb.width  = fh->width;
+-		buf->vb.height = fh->height;
+-		buf->vb.field  = field;
+-		init_buffer = 1;
+-	}
++	/* These properties only change when queue is idle, see s_fmt */
++	buf->fmt       = fh->fmt;
++	buf->vb.width  = fh->width;
++	buf->vb.height = fh->height;
++	buf->vb.field  = field;
+ 
+ 	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ 		rc = videobuf_iolock(vq, &buf->vb, NULL);
+@@ -711,45 +587,12 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+ 	struct vivi_buffer    *buf  = container_of(vb, struct vivi_buffer, vb);
+ 	struct vivi_fh        *fh   = vq->priv_data;
+ 	struct vivi_dev       *dev  = fh->dev;
+-	struct vivi_dmaqueue  *vidq = &dev->vidq;
+-	struct vivi_buffer    *prev;
+-
+-	if (!list_empty(&vidq->queued)) {
+-		dprintk(dev, 1, "adding vb queue=0x%08lx\n",
+-			(unsigned long)&buf->vb.queue);
+-		list_add_tail(&buf->vb.queue, &vidq->queued);
+-		buf->vb.state = VIDEOBUF_QUEUED;
+-		dprintk(dev, 2, "[%p/%d] buffer_queue - append to queued\n",
+-			buf, buf->vb.i);
+-	} else if (list_empty(&vidq->active)) {
+-		list_add_tail(&buf->vb.queue, &vidq->active);
+-
+-		buf->vb.state = VIDEOBUF_ACTIVE;
+-		mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
+-		dprintk(dev, 2, "[%p/%d] buffer_queue - first active\n",
+-			buf, buf->vb.i);
+-
+-		vivi_start_thread(vidq);
+-	} else {
+-		prev = list_entry(vidq->active.prev,
+-				  struct vivi_buffer, vb.queue);
+-		if (prev->vb.width  == buf->vb.width  &&
+-		    prev->vb.height == buf->vb.height &&
+-		    prev->fmt       == buf->fmt) {
+-			list_add_tail(&buf->vb.queue, &vidq->active);
+-			buf->vb.state = VIDEOBUF_ACTIVE;
+-			dprintk(dev, 2,
+-				"[%p/%d] buffer_queue - append to active\n",
+-				buf, buf->vb.i);
+-
+-		} else {
+-			list_add_tail(&buf->vb.queue, &vidq->queued);
+-			buf->vb.state = VIDEOBUF_QUEUED;
+-			dprintk(dev, 2,
+-				"[%p/%d] buffer_queue - first queued\n",
+-				buf, buf->vb.i);
+-		}
+-	}
++	struct vivi_dmaqueue *vidq = &dev->vidq;
++
++	dprintk(dev, 1, "%s\n", __func__);
++
++	buf->vb.state = VIDEOBUF_QUEUED;
++	list_add_tail(&buf->vb.queue, &vidq->active);
+ }
+ 
+ static void buffer_release(struct videobuf_queue *vq,
+@@ -758,11 +601,8 @@ static void buffer_release(struct videobuf_queue *vq,
+ 	struct vivi_buffer   *buf  = container_of(vb, struct vivi_buffer, vb);
+ 	struct vivi_fh       *fh   = vq->priv_data;
+ 	struct vivi_dev      *dev  = (struct vivi_dev *)fh->dev;
+-	struct vivi_dmaqueue *vidq = &dev->vidq;
+-
+-	dprintk(dev, 1, "%s\n", __FUNCTION__);
+ 
+-	vivi_stop_thread(vidq);
++	dprintk(dev, 1, "%s\n", __func__);
+ 
+ 	free_buffer(vq, buf);
+ }
+@@ -869,17 +709,31 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ 					struct v4l2_format *f)
+ {
+ 	struct vivi_fh  *fh = priv;
++	struct videobuf_queue *q = &fh->vb_vidq;
++
+ 	int ret = vidioc_try_fmt_cap(file, fh, f);
+ 	if (ret < 0)
+ 		return (ret);
+ 
++	mutex_lock(&q->vb_lock);
++
++	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
++		dprintk(fh->dev, 1, "%s queue busy\n", __func__);
++		ret = -EBUSY;
++		goto out;
++	}
++
+ 	fh->fmt           = &format;
+ 	fh->width         = f->fmt.pix.width;
+ 	fh->height        = f->fmt.pix.height;
+ 	fh->vb_vidq.field = f->fmt.pix.field;
+ 	fh->type          = f->type;
+ 
+-	return (0);
++	ret = 0;
++out:
++	mutex_unlock(&q->vb_lock);
++
++	return (ret);
+ }
+ 
+ static int vidioc_reqbufs(struct file *file, void *priv,
+@@ -1034,8 +888,9 @@ static int vivi_open(struct inode *inode, struct file *file)
+ {
+ 	int minor = iminor(inode);
+ 	struct vivi_dev *dev;
+-	struct vivi_fh *fh;
++	struct vivi_fh *fh = NULL;
+ 	int i;
++	int retval = 0;
+ 
+ 	printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
+ 
+@@ -1045,9 +900,15 @@ static int vivi_open(struct inode *inode, struct file *file)
+ 	return -ENODEV;
+ 
+ found:
+-	/* If more than one user, mutex should be added */
++	mutex_lock(&dev->mutex);
+ 	dev->users++;
+ 
++	if (dev->users > 1) {
++		dev->users--;
++		retval = -EBUSY;
++		goto unlock;
++	}
++
+ 	dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
+ 		v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
+ 
+@@ -1055,8 +916,13 @@ found:
+ 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ 	if (NULL == fh) {
+ 		dev->users--;
+-		return -ENOMEM;
++		retval = -ENOMEM;
++		goto unlock;
+ 	}
++unlock:
++	mutex_unlock(&dev->mutex);
++	if (retval)
++		return retval;
+ 
+ 	file->private_data = fh;
+ 	fh->dev      = dev;
+@@ -1084,6 +950,8 @@ found:
+ 			NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
+ 			sizeof(struct vivi_buffer), fh);
+ 
++	vivi_start_thread(fh);
++
+ 	return 0;
+ }
+ 
+@@ -1106,7 +974,7 @@ vivi_poll(struct file *file, struct poll_table_struct *wait)
+ 	struct vivi_dev       *dev = fh->dev;
+ 	struct videobuf_queue *q = &fh->vb_vidq;
+ 
+-	dprintk(dev, 1, "%s\n", __FUNCTION__);
++	dprintk(dev, 1, "%s\n", __func__);
+ 
+ 	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+ 		return POLLERR;
+@@ -1128,7 +996,9 @@ static int vivi_close(struct inode *inode, struct file *file)
+ 
+ 	kfree(fh);
+ 
++	mutex_lock(&dev->mutex);
+ 	dev->users--;
++	mutex_unlock(&dev->mutex);
+ 
+ 	dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
+ 		minor, dev->users);
+@@ -1182,6 +1052,7 @@ static const struct file_operations vivi_fops = {
+ 	.read           = vivi_read,
+ 	.poll		= vivi_poll,
+ 	.ioctl          = video_ioctl2, /* V4L2 ioctl handler */
++	.compat_ioctl   = v4l_compat_ioctl32,
+ 	.mmap           = vivi_mmap,
+ 	.llseek         = no_llseek,
+ };
+@@ -1236,16 +1107,11 @@ static int __init vivi_init(void)
+ 
+ 		/* init video dma queues */
+ 		INIT_LIST_HEAD(&dev->vidq.active);
+-		INIT_LIST_HEAD(&dev->vidq.queued);
+ 		init_waitqueue_head(&dev->vidq.wq);
+ 
+ 		/* initialize locks */
+-		mutex_init(&dev->lock);
+ 		spin_lock_init(&dev->slock);
+-
+-		dev->vidq.timeout.function = vivi_vid_timeout;
+-		dev->vidq.timeout.data     = (unsigned long)dev;
+-		init_timer(&dev->vidq.timeout);
++		mutex_init(&dev->mutex);
+ 
+ 		vfd = video_device_alloc();
+ 		if (NULL == vfd)
+diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
+index a913385..3529302 100644
+--- a/drivers/media/video/vpx3220.c
++++ b/drivers/media/video/vpx3220.c
+@@ -40,7 +40,7 @@
+ #define I2C_VPX3220        0x86
+ #define VPX3220_DEBUG	KERN_DEBUG "vpx3220: "
+ 
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+ 
+diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
+index 08aaae0..33f7026 100644
+--- a/drivers/media/video/w9966.c
++++ b/drivers/media/video/w9966.c
+@@ -61,10 +61,10 @@
+ #include <media/v4l2-common.h>
+ #include <linux/parport.h>
+ 
+-//#define DEBUG				// Undef me for production
++/*#define DEBUG*/				/* Undef me for production */
+ 
+ #ifdef DEBUG
+-#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __FUNCTION__ , ##a)
++#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
+ #else
+ #define DPRINTF(x...)
+ #endif
+@@ -134,7 +134,7 @@ MODULE_PARM_DESC(pardev, "pardev: where to search for\n\
+ \tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n\
+ \tcam 1 to parport3 and search every parport for cam 2 etc...");
+ 
+-static int parmode = 0;
++static int parmode;
+ module_param(parmode, int, 0);
+ MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
+ 
+@@ -188,7 +188,9 @@ static const struct file_operations w9966_fops = {
+ 	.open           = video_exclusive_open,
+ 	.release        = video_exclusive_release,
+ 	.ioctl          = w9966_v4l_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.read           = w9966_v4l_read,
+ 	.llseek         = no_llseek,
+ };
+diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
+index 2ae1430..8405224 100644
+--- a/drivers/media/video/w9968cf.c
++++ b/drivers/media/video/w9968cf.c
+@@ -3461,7 +3461,9 @@ static const struct file_operations w9968cf_fops = {
+ 	.release = w9968cf_release,
+ 	.read =    w9968cf_read,
+ 	.ioctl =   w9968cf_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.mmap =    w9968cf_mmap,
+ 	.llseek =  no_llseek,
+ };
+@@ -3481,7 +3483,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+ 	enum w9968cf_model_id mod_id;
+ 	struct list_head* ptr;
+ 	u8 sc = 0; /* number of simultaneous cameras */
+-	static unsigned short dev_nr = 0; /* we are handling device number n */
++	static unsigned short dev_nr; /* 0 - we are handling device number n */
+ 
+ 	if (le16_to_cpu(udev->descriptor.idVendor)  == winbond_id_table[0].idVendor &&
+ 	    le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct)
+diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h
+index ec7696e..3c95316 100644
+--- a/drivers/media/video/w9968cf.h
++++ b/drivers/media/video/w9968cf.h
+@@ -298,7 +298,7 @@ struct w9968cf_device {
+ 			dev_warn(&cam->dev, fmt "\n", ## args);               \
+ 		else if ((level) >= 5)                                        \
+ 			dev_info(&cam->dev, "[%s:%d] " fmt "\n",              \
+-				 __FUNCTION__, __LINE__ , ## args);           \
++				 __func__, __LINE__ , ## args);           \
+ 	}                                                                     \
+ }
+ /* For generic kernel (not device specific) messages */
+@@ -309,7 +309,7 @@ struct w9968cf_device {
+ 		if ((level) >= 1 && (level) <= 4)                             \
+ 			pr_info("w9968cf: " fmt "\n", ## args);               \
+ 		else if ((level) >= 5)                                        \
+-			pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__,  \
++			pr_debug("w9968cf: [%s:%d] " fmt "\n", __func__,  \
+ 				 __LINE__ , ## args);                         \
+ 	}                                                                     \
+ }
+@@ -321,7 +321,7 @@ struct w9968cf_device {
+ 
+ #undef PDBG
+ #define PDBG(fmt, args...)                                                    \
+-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args);
++dev_info(&cam->dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args);
+ 
+ #undef PDBGG
+ #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */
+diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h
+index a2de50e..7bbab54 100644
+--- a/drivers/media/video/zc0301/zc0301.h
++++ b/drivers/media/video/zc0301/zc0301.h
+@@ -160,7 +160,7 @@ do {                                                                          \
+ 			dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
+ 		else if ((level) >= 3)                                        \
+ 			dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n",   \
+-				 __FILE__, __FUNCTION__, __LINE__ , ## args); \
++				 __FILE__, __func__, __LINE__ , ## args); \
+ 	}                                                                     \
+ } while (0)
+ #	define KDBG(level, fmt, args...)                                      \
+@@ -170,7 +170,7 @@ do {                                                                          \
+ 			pr_info("zc0301: " fmt "\n", ## args);                \
+ 		else if ((level) == 3)                                        \
+ 			pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__,   \
+-				 __FUNCTION__, __LINE__ , ## args);           \
++				 __func__, __LINE__ , ## args);           \
+ 	}                                                                     \
+ } while (0)
+ #	define V4LDBG(level, name, cmd)                                       \
+@@ -186,7 +186,7 @@ do {                                                                          \
+ 
+ #undef PDBG
+ #define PDBG(fmt, args...)                                                    \
+-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__,   \
++dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
+ 	 __LINE__ , ## args)
+ 
+ #undef PDBGG
+diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
+index 2c5665c..363dd2b 100644
+--- a/drivers/media/video/zc0301/zc0301_core.c
++++ b/drivers/media/video/zc0301/zc0301_core.c
+@@ -1925,7 +1925,9 @@ static const struct file_operations zc0301_fops = {
+ 	.open =    zc0301_open,
+ 	.release = zc0301_release,
+ 	.ioctl =   zc0301_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl = v4l_compat_ioctl32,
++#endif
+ 	.read =    zc0301_read,
+ 	.poll =    zc0301_poll,
+ 	.mmap =    zc0301_mmap,
+@@ -1939,7 +1941,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+ {
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+ 	struct zc0301_device* cam;
+-	static unsigned int dev_nr = 0;
++	static unsigned int dev_nr;
+ 	unsigned int i;
+ 	int err = 0;
+ 
+diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
+index 498a43c..81cc3b0 100644
+--- a/drivers/media/video/zoran.h
++++ b/drivers/media/video/zoran.h
+@@ -243,10 +243,8 @@ struct zoran_format {
+ #ifdef CONFIG_VIDEO_V4L1_COMPAT
+ 	int palette;
+ #endif
+-#ifdef CONFIG_VIDEO_V4L2
+ 	__u32 fourcc;
+ 	int colorspace;
+-#endif
+ 	int depth;
+ 	__u32 flags;
+ 	__u32 vfespfr;
+@@ -271,20 +269,6 @@ struct zoran_v4l_settings {
+ 	const struct zoran_format *format;	/* capture format */
+ };
+ 
+-/* whoops, this one is undeclared if !v4l2 */
+-#ifndef CONFIG_VIDEO_V4L2
+-struct v4l2_jpegcompression {
+-	int quality;
+-	int APPn;
+-	int APP_len;
+-	char APP_data[60];
+-	int COM_len;
+-	char COM_data[60];
+-	__u32 jpeg_markers;
+-	__u8 reserved[116];
+-};
+-#endif
+-
+ /* jpg-capture/-playback settings */
+ struct zoran_jpg_settings {
+ 	int decimation;		/* this bit is used to set everything to default */
+diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
+index 690281b..006d488 100644
+--- a/drivers/media/video/zoran_card.c
++++ b/drivers/media/video/zoran_card.c
+@@ -83,7 +83,7 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder");
+    or set in in a VIDIOCSFBUF ioctl
+  */
+ 
+-static unsigned long vidmem = 0;	/* Video memory base address */
++static unsigned long vidmem;	/* default = 0 - Video memory base address */
+ module_param(vidmem, ulong, 0444);
+ MODULE_PARM_DESC(vidmem, "Default video memory base address");
+ 
+@@ -91,7 +91,7 @@ MODULE_PARM_DESC(vidmem, "Default video memory base address");
+    Default input and video norm at startup of the driver.
+ */
+ 
+-static unsigned int default_input = 0;	/* 0=Composite, 1=S-Video */
++static unsigned int default_input;	/* default 0 = Composite, 1 = S-Video */
+ module_param(default_input, uint, 0444);
+ MODULE_PARM_DESC(default_input,
+ 		 "Default input (0=Composite, 1=S-Video, 2=Internal)");
+@@ -101,7 +101,7 @@ module_param(default_mux, int, 0644);
+ MODULE_PARM_DESC(default_mux,
+ 		 "Default 6 Eyes mux setting (Input selection)");
+ 
+-static int default_norm = 0;	/* 0=PAL, 1=NTSC 2=SECAM */
++static int default_norm;	/* default 0 = PAL, 1 = NTSC 2 = SECAM */
+ module_param(default_norm, int, 0444);
+ MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
+ 
+diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran_card.h
+index 8444ca0..1b5c417 100644
+--- a/drivers/media/video/zoran_card.h
++++ b/drivers/media/video/zoran_card.h
+@@ -50,4 +50,6 @@ extern int zoran_check_jpg_settings(struct zoran *zr,
+ extern void zoran_open_init_params(struct zoran *zr);
+ extern void zoran_vdev_release(struct video_device *vdev);
+ 
++void zr36016_write(struct videocodec *codec, u16 reg, u32 val);
++
+ #endif				/* __ZORAN_CARD_H__ */
+diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
+index f97c206..7b60533 100644
+--- a/drivers/media/video/zoran_device.c
++++ b/drivers/media/video/zoran_device.c
+@@ -60,7 +60,8 @@
+ 
+ extern const struct zoran_format zoran_formats[];
+ 
+-static int lml33dpath = 0;	/* 1 will use digital path in capture
++static int lml33dpath;		/* default = 0
++				 * 1 will use digital path in capture
+ 				 * mode instead of analog. It can be
+ 				 * used for picture adjustments using
+ 				 * tool like xawtv while watching image
+@@ -927,11 +928,6 @@ count_reset_interrupt (struct zoran *zr)
+ 	return isr;
+ }
+ 
+-/* hack */
+-extern void zr36016_write (struct videocodec *codec,
+-			   u16                reg,
+-			   u32                val);
+-
+ void
+ jpeg_start (struct zoran *zr)
+ {
+@@ -987,7 +983,7 @@ void
+ zr36057_enable_jpg (struct zoran          *zr,
+ 		    enum zoran_codec_mode  mode)
+ {
+-	static int zero = 0;
++	static int zero;
+ 	static int one = 1;
+ 	struct vfe_settings cap;
+ 	int field_size =
+@@ -1726,7 +1722,7 @@ decoder_command (struct zoran *zr,
+ 		return -EIO;
+ 
+ 	if (zr->card.type == LML33 &&
+-	    (cmd == DECODER_SET_NORM || DECODER_SET_INPUT)) {
++	    (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) {
+ 		int res;
+ 
+ 		// Bt819 needs to reset its FIFO buffer using #FRST pin and
+diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
+index fea4946..0134bec 100644
+--- a/drivers/media/video/zoran_driver.c
++++ b/drivers/media/video/zoran_driver.c
+@@ -85,7 +85,6 @@
+ #include "zoran_device.h"
+ #include "zoran_card.h"
+ 
+-#ifdef CONFIG_VIDEO_V4L2
+ 	/* we declare some card type definitions here, they mean
+ 	 * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */
+ #define ZORAN_V4L2_VID_FLAGS ( \
+@@ -94,19 +93,15 @@
+ 				V4L2_CAP_VIDEO_OUTPUT |\
+ 				V4L2_CAP_VIDEO_OVERLAY \
+ 			      )
+-#endif
+ 
+ #include <asm/byteorder.h>
+ 
+-#if defined(CONFIG_VIDEO_V4L2) && defined(CONFIG_VIDEO_V4L1_COMPAT)
++#if defined(CONFIG_VIDEO_V4L1_COMPAT)
+ #define ZFMT(pal, fcc, cs) \
+ 	.palette = (pal), .fourcc = (fcc), .colorspace = (cs)
+-#elif defined(CONFIG_VIDEO_V4L2)
+-#define ZFMT(pal, fcc, cs) \
+-	.fourcc = (fcc), .colorspace = (cs)
+ #else
+ #define ZFMT(pal, fcc, cs) \
+-	.palette = (pal)
++	.fourcc = (fcc), .colorspace = (cs)
+ #endif
+ 
+ const struct zoran_format zoran_formats[] = {
+@@ -205,11 +200,10 @@ extern int jpg_nbufs;
+ extern int jpg_bufsize;
+ extern int pass_through;
+ 
+-static int lock_norm = 0;	/* 1=Don't change TV standard (norm) */
++static int lock_norm;	/* 0 = default 1 = Don't change TV standard (norm) */
+ module_param(lock_norm, int, 0644);
+ MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
+ 
+-#ifdef CONFIG_VIDEO_V4L2
+ 	/* small helper function for calculating buffersizes for v4l2
+ 	 * we calculate the nearest higher power-of-two, which
+ 	 * will be the recommended buffersize */
+@@ -232,7 +226,6 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
+ 		return 8192;
+ 	return result;
+ }
+-#endif
+ 
+ /* forward references */
+ static void v4l_fbuffer_free(struct file *file);
+@@ -1709,7 +1702,6 @@ setup_overlay (struct file *file,
+ 	return wait_grab_pending(zr);
+ }
+ 
+-#ifdef CONFIG_VIDEO_V4L2
+ 	/* get the status of a buffer in the clients buffer queue */
+ static int
+ zoran_v4l2_buffer_status (struct file        *file,
+@@ -1815,7 +1807,6 @@ zoran_v4l2_buffer_status (struct file        *file,
+ 
+ 	return 0;
+ }
+-#endif
+ 
+ static int
+ zoran_set_norm (struct zoran *zr,
+@@ -2624,8 +2615,6 @@ zoran_do_ioctl (struct inode *inode,
+ 	}
+ 		break;
+ 
+-#ifdef CONFIG_VIDEO_V4L2
+-
+ 		/* The new video4linux2 capture interface - much nicer than video4linux1, since
+ 		 * it allows for integrating the JPEG capturing calls inside standard v4l2
+ 		 */
+@@ -4197,7 +4186,6 @@ zoran_do_ioctl (struct inode *inode,
+ 		return 0;
+ 	}
+ 		break;
+-#endif
+ 
+ 	default:
+ 		dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n",
+@@ -4247,7 +4235,7 @@ zoran_poll (struct file *file,
+ 		dprintk(3,
+ 			KERN_DEBUG
+ 			"%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
+-			ZR_DEVNAME(zr), __FUNCTION__,
++			ZR_DEVNAME(zr), __func__,
+ 			"FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
+ 			"UPMD"[zr->v4l_buffers.buffer[frame].state],
+ 			zr->v4l_pend_tail, zr->v4l_pend_head);
+@@ -4269,7 +4257,7 @@ zoran_poll (struct file *file,
+ 		dprintk(3,
+ 			KERN_DEBUG
+ 			"%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
+-			ZR_DEVNAME(zr), __FUNCTION__,
++			ZR_DEVNAME(zr), __func__,
+ 			"FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
+ 			"UPMD"[zr->jpg_buffers.buffer[frame].state],
+ 			zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
+@@ -4644,7 +4632,9 @@ static const struct file_operations zoran_fops = {
+ 	.open = zoran_open,
+ 	.release = zoran_close,
+ 	.ioctl = zoran_ioctl,
++#ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= v4l_compat_ioctl32,
++#endif
+ 	.llseek = no_llseek,
+ 	.read = zoran_read,
+ 	.write = zoran_write,
+@@ -4655,9 +4645,7 @@ static const struct file_operations zoran_fops = {
+ struct video_device zoran_template __devinitdata = {
+ 	.name = ZORAN_NAME,
+ 	.type = ZORAN_VID_TYPE,
+-#ifdef CONFIG_VIDEO_V4L2
+ 	.type2 = ZORAN_V4L2_VID_FLAGS,
+-#endif
+ 	.fops = &zoran_fops,
+ 	.release = &zoran_vdev_release,
+ 	.minor = -1
+diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c
+index dd08455..00d132b 100644
+--- a/drivers/media/video/zr36016.c
++++ b/drivers/media/video/zr36016.c
+@@ -55,11 +55,10 @@
+ #define MAX_CODECS 20
+ 
+ /* amount of chips attached via this driver */
+-static int zr36016_codecs = 0;
++static int zr36016_codecs;
+ 
+ /* debugging is available via module parameter */
+-
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-4)");
+ 
+diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
+index faae4ec..cf8b271 100644
+--- a/drivers/media/video/zr36050.c
++++ b/drivers/media/video/zr36050.c
+@@ -52,11 +52,10 @@
+ #define MAX_CODECS 20
+ 
+ /* amount of chips attached via this driver */
+-static int zr36050_codecs = 0;
++static int zr36050_codecs;
+ 
+ /* debugging is available via module parameter */
+-
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-4)");
+ 
+diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c
+index 7849b65..8e74054 100644
+--- a/drivers/media/video/zr36060.c
++++ b/drivers/media/video/zr36060.c
+@@ -52,14 +52,14 @@
+ #define MAX_CODECS 20
+ 
+ /* amount of chips attached via this driver */
+-static int zr36060_codecs = 0;
++static int zr36060_codecs;
+ 
+-static int low_bitrate = 0;
++static int low_bitrate;
+ module_param(low_bitrate, bool, 0);
+ MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
+ 
+ /* debugging is available via module parameter */
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-4)");
+ 
+diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
+index 04949c8..a0e49dc 100644
+--- a/drivers/media/video/zr364xx.c
++++ b/drivers/media/video/zr364xx.c
+@@ -62,8 +62,8 @@
+ 
+ 
+ /* Module parameters */
+-static int debug = 0;
+-static int mode = 0;
++static int debug;
++static int mode;
+ 
+ 
+ /* Module parameters interface */
+diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
+index 946e3d3..61b98c3 100644
+--- a/drivers/memstick/core/memstick.c
++++ b/drivers/memstick/core/memstick.c
+@@ -177,16 +177,16 @@ static struct bus_type memstick_bus_type = {
+ 	.resume         = memstick_device_resume
+ };
+ 
+-static void memstick_free(struct class_device *cdev)
++static void memstick_free(struct device *dev)
+ {
+-	struct memstick_host *host = container_of(cdev, struct memstick_host,
+-						  cdev);
++	struct memstick_host *host = container_of(dev, struct memstick_host,
++						  dev);
+ 	kfree(host);
+ }
+ 
+ static struct class memstick_host_class = {
+ 	.name       = "memstick_host",
+-	.release    = memstick_free
++	.dev_release = memstick_free
+ };
+ 
+ static void memstick_free_card(struct device *dev)
+@@ -383,8 +383,8 @@ static struct memstick_dev *memstick_alloc_card(struct memstick_host *host)
+ 	if (card) {
+ 		card->host = host;
+ 		snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+-			 "%s", host->cdev.class_id);
+-		card->dev.parent = host->cdev.dev;
++			 "%s", host->dev.bus_id);
++		card->dev.parent = &host->dev;
+ 		card->dev.bus = &memstick_bus_type;
+ 		card->dev.release = memstick_free_card;
+ 		card->check = memstick_dummy_check;
+@@ -427,7 +427,7 @@ static void memstick_check(struct work_struct *work)
+ 						  media_checker);
+ 	struct memstick_dev *card;
+ 
+-	dev_dbg(host->cdev.dev, "memstick_check started\n");
++	dev_dbg(&host->dev, "memstick_check started\n");
+ 	mutex_lock(&host->lock);
+ 	if (!host->card)
+ 		memstick_power_on(host);
+@@ -440,7 +440,7 @@ static void memstick_check(struct work_struct *work)
+ 			host->card = NULL;
+ 		}
+ 	} else {
+-		dev_dbg(host->cdev.dev, "new card %02x, %02x, %02x\n",
++		dev_dbg(&host->dev, "new card %02x, %02x, %02x\n",
+ 			card->id.type, card->id.category, card->id.class);
+ 		if (host->card) {
+ 			if (memstick_set_rw_addr(host->card)
+@@ -465,7 +465,7 @@ static void memstick_check(struct work_struct *work)
+ 		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
+ 
+ 	mutex_unlock(&host->lock);
+-	dev_dbg(host->cdev.dev, "memstick_check finished\n");
++	dev_dbg(&host->dev, "memstick_check finished\n");
+ }
+ 
+ /**
+@@ -482,9 +482,9 @@ struct memstick_host *memstick_alloc_host(unsigned int extra,
+ 	if (host) {
+ 		mutex_init(&host->lock);
+ 		INIT_WORK(&host->media_checker, memstick_check);
+-		host->cdev.class = &memstick_host_class;
+-		host->cdev.dev = dev;
+-		class_device_initialize(&host->cdev);
++		host->dev.class = &memstick_host_class;
++		host->dev.parent = dev;
++		device_initialize(&host->dev);
+ 	}
+ 	return host;
+ }
+@@ -507,10 +507,9 @@ int memstick_add_host(struct memstick_host *host)
+ 	if (rc)
+ 		return rc;
+ 
+-	snprintf(host->cdev.class_id, BUS_ID_SIZE,
+-		 "memstick%u", host->id);
++	snprintf(host->dev.bus_id, BUS_ID_SIZE, "memstick%u", host->id);
+ 
+-	rc = class_device_add(&host->cdev);
++	rc = device_add(&host->dev);
+ 	if (rc) {
+ 		spin_lock(&memstick_host_lock);
+ 		idr_remove(&memstick_host_idr, host->id);
+@@ -541,7 +540,7 @@ void memstick_remove_host(struct memstick_host *host)
+ 	spin_lock(&memstick_host_lock);
+ 	idr_remove(&memstick_host_idr, host->id);
+ 	spin_unlock(&memstick_host_lock);
+-	class_device_del(&host->cdev);
++	device_del(&host->dev);
+ }
+ EXPORT_SYMBOL(memstick_remove_host);
+ 
+@@ -552,7 +551,7 @@ EXPORT_SYMBOL(memstick_remove_host);
+ void memstick_free_host(struct memstick_host *host)
+ {
+ 	mutex_destroy(&host->lock);
+-	class_device_put(&host->cdev);
++	put_device(&host->dev);
+ }
+ EXPORT_SYMBOL(memstick_free_host);
+ 
+diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
+index 557dbbb..477d0fb 100644
+--- a/drivers/memstick/core/mspro_block.c
++++ b/drivers/memstick/core/mspro_block.c
+@@ -1127,8 +1127,8 @@ static int mspro_block_init_disk(struct memstick_dev *card)
+ 	u64 limit = BLK_BOUNCE_HIGH;
+ 	unsigned long capacity;
+ 
+-	if (host->cdev.dev->dma_mask && *(host->cdev.dev->dma_mask))
+-		limit = *(host->cdev.dev->dma_mask);
++	if (host->dev.dma_mask && *(host->dev.dma_mask))
++		limit = *(host->dev.dma_mask);
+ 
+ 	for (rc = 0; msb->attr_group.attrs[rc]; ++rc) {
+ 		s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]);
+diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
+index 8770a5f..a054668 100644
+--- a/drivers/memstick/host/jmb38x_ms.c
++++ b/drivers/memstick/host/jmb38x_ms.c
+@@ -361,15 +361,15 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
+ 	unsigned int data_len, cmd, t_val;
+ 
+ 	if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {
+-		dev_dbg(msh->cdev.dev, "no media status\n");
++		dev_dbg(&msh->dev, "no media status\n");
+ 		host->req->error = -ETIME;
+ 		return host->req->error;
+ 	}
+ 
+-	dev_dbg(msh->cdev.dev, "control %08x\n",
++	dev_dbg(&msh->dev, "control %08x\n",
+ 		readl(host->addr + HOST_CONTROL));
+-	dev_dbg(msh->cdev.dev, "status %08x\n", readl(host->addr + INT_STATUS));
+-	dev_dbg(msh->cdev.dev, "hstatus %08x\n", readl(host->addr + STATUS));
++	dev_dbg(&msh->dev, "status %08x\n", readl(host->addr + INT_STATUS));
++	dev_dbg(&msh->dev, "hstatus %08x\n", readl(host->addr + STATUS));
+ 
+ 	host->cmd_flags = 0;
+ 	host->block_pos = 0;
+@@ -448,7 +448,7 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
+ 	host->req->error = 0;
+ 
+ 	writel(cmd, host->addr + TPC);
+-	dev_dbg(msh->cdev.dev, "executing TPC %08x, len %x\n", cmd, data_len);
++	dev_dbg(&msh->dev, "executing TPC %08x, len %x\n", cmd, data_len);
+ 
+ 	return 0;
+ }
+@@ -461,11 +461,11 @@ static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)
+ 
+ 	del_timer(&host->timer);
+ 
+-	dev_dbg(msh->cdev.dev, "c control %08x\n",
++	dev_dbg(&msh->dev, "c control %08x\n",
+ 		readl(host->addr + HOST_CONTROL));
+-	dev_dbg(msh->cdev.dev, "c status %08x\n",
++	dev_dbg(&msh->dev, "c status %08x\n",
+ 		readl(host->addr + INT_STATUS));
+-	dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS));
++	dev_dbg(&msh->dev, "c hstatus %08x\n", readl(host->addr + STATUS));
+ 
+ 	host->req->int_reg = readl(host->addr + STATUS) & 0xff;
+ 
+diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
+index c6be6eb..db3c892 100644
+--- a/drivers/message/fusion/mptbase.c
++++ b/drivers/message/fusion/mptbase.c
+@@ -79,7 +79,7 @@ MODULE_VERSION(my_VERSION);
+ /*
+  *  cmd line parameters
+  */
+-static int mpt_msi_enable;
++static int mpt_msi_enable = -1;
+ module_param(mpt_msi_enable, int, 0);
+ MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+ 
+@@ -1686,6 +1686,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		ioc->bus_type = SAS;
+ 	}
+ 
++	if (ioc->bus_type == SAS && mpt_msi_enable == -1)
++		ioc->msi_enable = 1;
++	else
++		ioc->msi_enable = mpt_msi_enable;
++
+ 	if (ioc->errata_flag_1064)
+ 		pci_disable_io_access(pdev);
+ 
+@@ -1831,7 +1836,7 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state)
+ 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+ 
+ 	free_irq(ioc->pci_irq, ioc);
+-	if (mpt_msi_enable)
++	if (ioc->msi_enable)
+ 		pci_disable_msi(ioc->pcidev);
+ 	ioc->pci_irq = -1;
+ 	pci_save_state(pdev);
+@@ -2057,15 +2062,17 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
+ 	if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
+ 		ioc->pci_irq = -1;
+ 		if (ioc->pcidev->irq) {
+-			if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
++			if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
+ 				printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
+ 				    ioc->name);
++			else
++				ioc->msi_enable = 0;
+ 			rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
+ 			    IRQF_SHARED, ioc->name, ioc);
+ 			if (rc < 0) {
+ 				printk(MYIOC_s_ERR_FMT "Unable to allocate "
+ 				    "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
+-				if (mpt_msi_enable)
++				if (ioc->msi_enable)
+ 					pci_disable_msi(ioc->pcidev);
+ 				return -EBUSY;
+ 			}
+@@ -2173,7 +2180,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
+ 		/*
+ 		 * Initalize link list for inactive raid volumes.
+ 		 */
+-		init_MUTEX(&ioc->raid_data.inactive_list_mutex);
++		mutex_init(&ioc->raid_data.inactive_list_mutex);
+ 		INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
+ 
+ 		if (ioc->bus_type == SAS) {
+@@ -2261,7 +2268,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
+  out:
+ 	if ((ret != 0) && irq_allocated) {
+ 		free_irq(ioc->pci_irq, ioc);
+-		if (mpt_msi_enable)
++		if (ioc->msi_enable)
+ 			pci_disable_msi(ioc->pcidev);
+ 	}
+ 	return ret;
+@@ -2443,7 +2450,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
+ 
+ 	if (ioc->pci_irq != -1) {
+ 		free_irq(ioc->pci_irq, ioc);
+-		if (mpt_msi_enable)
++		if (ioc->msi_enable)
+ 			pci_disable_msi(ioc->pcidev);
+ 		ioc->pci_irq = -1;
+ 	}
+@@ -5159,13 +5166,13 @@ mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
+ 	if (list_empty(&ioc->raid_data.inactive_list))
+ 		return;
+ 
+-	down(&ioc->raid_data.inactive_list_mutex);
++	mutex_lock(&ioc->raid_data.inactive_list_mutex);
+ 	list_for_each_entry_safe(component_info, pNext,
+ 	    &ioc->raid_data.inactive_list, list) {
+ 		list_del(&component_info->list);
+ 		kfree(component_info);
+ 	}
+-	up(&ioc->raid_data.inactive_list_mutex);
++	mutex_unlock(&ioc->raid_data.inactive_list_mutex);
+ }
+ 
+ /**
+@@ -5224,7 +5231,7 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
+ 	if (!handle_inactive_volumes)
+ 		goto out;
+ 
+-	down(&ioc->raid_data.inactive_list_mutex);
++	mutex_lock(&ioc->raid_data.inactive_list_mutex);
+ 	for (i = 0; i < buffer->NumPhysDisks; i++) {
+ 		if(mpt_raid_phys_disk_pg0(ioc,
+ 		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+@@ -5244,7 +5251,7 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
+ 		list_add_tail(&component_info->list,
+ 		    &ioc->raid_data.inactive_list);
+ 	}
+-	up(&ioc->raid_data.inactive_list_mutex);
++	mutex_unlock(&ioc->raid_data.inactive_list_mutex);
+ 
+  out:
+ 	if (buffer)
+diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
+index caadc68..a8f6174 100644
+--- a/drivers/message/fusion/mptbase.h
++++ b/drivers/message/fusion/mptbase.h
+@@ -51,6 +51,7 @@
+ 
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
++#include <linux/mutex.h>
+ 
+ #include "lsi/mpi_type.h"
+ #include "lsi/mpi.h"		/* Fusion MPI(nterface) basic defs */
+@@ -531,7 +532,7 @@ struct inactive_raid_component_info {
+ typedef	struct _RaidCfgData {
+ 	IOCPage2_t	*pIocPg2;		/* table of Raid Volumes */
+ 	IOCPage3_t	*pIocPg3;		/* table of physical disks */
+-	struct semaphore	inactive_list_mutex;
++	struct mutex	inactive_list_mutex;
+ 	struct list_head	inactive_list; /* link list for physical
+ 						disk that belong in
+ 						inactive volumes */
+@@ -630,6 +631,7 @@ typedef struct _MPT_ADAPTER
+ 	int			 mtrr_reg;
+ 	struct pci_dev		*pcidev;	/* struct pci_dev pointer */
+ 	int			bars;		/* bitmask of BAR's that must be configured */
++	int			msi_enable;
+ 	u8			__iomem *memmap;	/* mmap address */
+ 	struct Scsi_Host	*sh;		/* Scsi Host pointer */
+ 	SpiCfgData		spi_data;	/* Scsi config. data */
+@@ -693,7 +695,6 @@ typedef struct _MPT_ADAPTER
+ 	struct mutex		 sas_discovery_mutex;
+ 	u8			 sas_discovery_runtime;
+ 	u8			 sas_discovery_ignore_events;
+-	u16			 handle;
+ 	int			 sas_index; /* index refrencing */
+ 	MPT_SAS_MGMT		 sas_mgmt;
+ 	struct work_struct	 sas_persist_task;
+diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
+index 78734e2..4684807 100644
+--- a/drivers/message/fusion/mptsas.c
++++ b/drivers/message/fusion/mptsas.c
+@@ -230,6 +230,20 @@ static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
+ 	return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
+ }
+ 
++static struct mptsas_portinfo *
++mptsas_get_hba_portinfo(MPT_ADAPTER *ioc)
++{
++	struct list_head	*head = &ioc->sas_topology;
++	struct mptsas_portinfo	*pi = NULL;
++
++	/* always the first entry on sas_topology list */
++
++	if (!list_empty(head))
++		pi = list_entry(head->next, struct mptsas_portinfo, list);
++
++	return pi;
++}
++
+ /*
+  * mptsas_find_portinfo_by_handle
+  *
+@@ -1290,7 +1304,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
+ 		struct mptsas_portinfo *port_info;
+ 
+ 		mutex_lock(&ioc->sas_topology_mutex);
+-		port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
++		port_info = mptsas_get_hba_portinfo(ioc);
+ 		if (port_info && port_info->phy_info)
+ 			sas_address =
+ 				port_info->phy_info[0].phy->identify.sas_address;
+@@ -2028,8 +2042,7 @@ static int mptsas_probe_one_phy(struct device *dev,
+ 			int i;
+ 
+ 			mutex_lock(&ioc->sas_topology_mutex);
+-			port_info = mptsas_find_portinfo_by_handle(ioc,
+-								   ioc->handle);
++			port_info = mptsas_get_hba_portinfo(ioc);
+ 			mutex_unlock(&ioc->sas_topology_mutex);
+ 
+ 			for (i = 0; i < port_info->num_phys; i++)
+@@ -2099,8 +2112,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
+ 
+ 	mptsas_sas_io_unit_pg1(ioc);
+ 	mutex_lock(&ioc->sas_topology_mutex);
+-	ioc->handle = hba->phy_info[0].handle;
+-	port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
++	port_info = mptsas_get_hba_portinfo(ioc);
+ 	if (!port_info) {
+ 		port_info = hba;
+ 		list_add_tail(&port_info->list, &ioc->sas_topology);
+diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
+index c207bda..b109bd8 100644
+--- a/drivers/message/fusion/mptscsih.c
++++ b/drivers/message/fusion/mptscsih.c
+@@ -2304,14 +2304,14 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
+ 	if (list_empty(&ioc->raid_data.inactive_list))
+ 		goto out;
+ 
+-	down(&ioc->raid_data.inactive_list_mutex);
++	mutex_lock(&ioc->raid_data.inactive_list_mutex);
+ 	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+ 	    list) {
+ 		if ((component_info->d.PhysDiskID == id) &&
+ 		    (component_info->d.PhysDiskBus == channel))
+ 			rc = 1;
+ 	}
+-	up(&ioc->raid_data.inactive_list_mutex);
++	mutex_unlock(&ioc->raid_data.inactive_list_mutex);
+ 
+  out:
+ 	return rc;
+@@ -2341,14 +2341,14 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
+ 	if (list_empty(&ioc->raid_data.inactive_list))
+ 		goto out;
+ 
+-	down(&ioc->raid_data.inactive_list_mutex);
++	mutex_lock(&ioc->raid_data.inactive_list_mutex);
+ 	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+ 	    list) {
+ 		if ((component_info->d.PhysDiskID == id) &&
+ 		    (component_info->d.PhysDiskBus == channel))
+ 			rc = component_info->d.PhysDiskNum;
+ 	}
+-	up(&ioc->raid_data.inactive_list_mutex);
++	mutex_unlock(&ioc->raid_data.inactive_list_mutex);
+ 
+  out:
+ 	return rc;
+@@ -3300,9 +3300,10 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
+ }
+ 
+ static ssize_t
+-mptscsih_version_fw_show(struct class_device *cdev, char *buf)
++mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr,
++			 char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+@@ -3312,12 +3313,13 @@ mptscsih_version_fw_show(struct class_device *cdev, char *buf)
+ 	    (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
+ 	    ioc->facts.FWVersion.Word & 0x000000FF);
+ }
+-static CLASS_DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
++static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
+ 
+ static ssize_t
+-mptscsih_version_bios_show(struct class_device *cdev, char *buf)
++mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr,
++			   char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+@@ -3327,129 +3329,141 @@ mptscsih_version_bios_show(struct class_device *cdev, char *buf)
+ 	    (ioc->biosVersion & 0x0000FF00) >> 8,
+ 	    ioc->biosVersion & 0x000000FF);
+ }
+-static CLASS_DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
++static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
+ 
+ static ssize_t
+-mptscsih_version_mpi_show(struct class_device *cdev, char *buf)
++mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
+ }
+-static CLASS_DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
++static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
+ 
+ static ssize_t
+-mptscsih_version_product_show(struct class_device *cdev, char *buf)
++mptscsih_version_product_show(struct device *dev,
++			      struct device_attribute *attr,
++char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
+ }
+-static CLASS_DEVICE_ATTR(version_product, S_IRUGO,
++static DEVICE_ATTR(version_product, S_IRUGO,
+     mptscsih_version_product_show, NULL);
+ 
+ static ssize_t
+-mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf)
++mptscsih_version_nvdata_persistent_show(struct device *dev,
++					struct device_attribute *attr,
++					char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%02xh\n",
+ 	    ioc->nvdata_version_persistent);
+ }
+-static CLASS_DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
++static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
+     mptscsih_version_nvdata_persistent_show, NULL);
+ 
+ static ssize_t
+-mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf)
++mptscsih_version_nvdata_default_show(struct device *dev,
++				     struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
+ }
+-static CLASS_DEVICE_ATTR(version_nvdata_default, S_IRUGO,
++static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
+     mptscsih_version_nvdata_default_show, NULL);
+ 
+ static ssize_t
+-mptscsih_board_name_show(struct class_device *cdev, char *buf)
++mptscsih_board_name_show(struct device *dev, struct device_attribute *attr,
++			 char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
+ }
+-static CLASS_DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
++static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
+ 
+ static ssize_t
+-mptscsih_board_assembly_show(struct class_device *cdev, char *buf)
++mptscsih_board_assembly_show(struct device *dev,
++			     struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
+ }
+-static CLASS_DEVICE_ATTR(board_assembly, S_IRUGO,
++static DEVICE_ATTR(board_assembly, S_IRUGO,
+     mptscsih_board_assembly_show, NULL);
+ 
+ static ssize_t
+-mptscsih_board_tracer_show(struct class_device *cdev, char *buf)
++mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr,
++			   char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
+ }
+-static CLASS_DEVICE_ATTR(board_tracer, S_IRUGO,
++static DEVICE_ATTR(board_tracer, S_IRUGO,
+     mptscsih_board_tracer_show, NULL);
+ 
+ static ssize_t
+-mptscsih_io_delay_show(struct class_device *cdev, char *buf)
++mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr,
++		       char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
+ }
+-static CLASS_DEVICE_ATTR(io_delay, S_IRUGO,
++static DEVICE_ATTR(io_delay, S_IRUGO,
+     mptscsih_io_delay_show, NULL);
+ 
+ static ssize_t
+-mptscsih_device_delay_show(struct class_device *cdev, char *buf)
++mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr,
++			   char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
+ }
+-static CLASS_DEVICE_ATTR(device_delay, S_IRUGO,
++static DEVICE_ATTR(device_delay, S_IRUGO,
+     mptscsih_device_delay_show, NULL);
+ 
+ static ssize_t
+-mptscsih_debug_level_show(struct class_device *cdev, char *buf)
++mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
+ }
+ static ssize_t
+-mptscsih_debug_level_store(struct class_device *cdev, const char *buf,
+-								size_t count)
++mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr,
++			   const char *buf, size_t count)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	MPT_SCSI_HOST	*hd = shost_priv(host);
+ 	MPT_ADAPTER *ioc = hd->ioc;
+ 	int val = 0;
+@@ -3462,22 +3476,22 @@ mptscsih_debug_level_store(struct class_device *cdev, const char *buf,
+ 				ioc->name, ioc->debug_level);
+ 	return strlen(buf);
+ }
+-static CLASS_DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
+-    mptscsih_debug_level_show, mptscsih_debug_level_store);
+-
+-struct class_device_attribute *mptscsih_host_attrs[] = {
+-	&class_device_attr_version_fw,
+-	&class_device_attr_version_bios,
+-	&class_device_attr_version_mpi,
+-	&class_device_attr_version_product,
+-	&class_device_attr_version_nvdata_persistent,
+-	&class_device_attr_version_nvdata_default,
+-	&class_device_attr_board_name,
+-	&class_device_attr_board_assembly,
+-	&class_device_attr_board_tracer,
+-	&class_device_attr_io_delay,
+-	&class_device_attr_device_delay,
+-	&class_device_attr_debug_level,
++static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
++	mptscsih_debug_level_show, mptscsih_debug_level_store);
++
++struct device_attribute *mptscsih_host_attrs[] = {
++	&dev_attr_version_fw,
++	&dev_attr_version_bios,
++	&dev_attr_version_mpi,
++	&dev_attr_version_product,
++	&dev_attr_version_nvdata_persistent,
++	&dev_attr_version_nvdata_default,
++	&dev_attr_board_name,
++	&dev_attr_board_assembly,
++	&dev_attr_board_tracer,
++	&dev_attr_io_delay,
++	&dev_attr_device_delay,
++	&dev_attr_debug_level,
+ 	NULL,
+ };
+ EXPORT_SYMBOL(mptscsih_host_attrs);
+diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
+index d289e97..7ea7da0 100644
+--- a/drivers/message/fusion/mptscsih.h
++++ b/drivers/message/fusion/mptscsih.h
+@@ -129,4 +129,4 @@ extern void mptscsih_timer_expired(unsigned long data);
+ extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
+ extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
+ extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
+-extern struct class_device_attribute *mptscsih_host_attrs[];
++extern struct device_attribute *mptscsih_host_attrs[];
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index 0c886c8..2566479 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -22,6 +22,22 @@ config MFD_ASIC3
+ 	  This driver supports the ASIC3 multifunction chip found on many
+ 	  PDAs (mainly iPAQ and HTC based ones)
+ 
++config HTC_EGPIO
++	bool "HTC EGPIO support"
++	depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB
++	help
++	    This driver supports the CPLD egpio chip present on
++	    several HTC phones.  It provides basic support for input
++	    pins, output pins, and irqs.
++
++config HTC_PASIC3
++	tristate "HTC PASIC3 LED/DS1WM chip support"
++	help
++	  This core driver provides register access for the LED/DS1WM
++	  chips labeled "AIC2" and "AIC3", found on HTC Blueangel and
++	  HTC Magician devices, respectively. Actual functionality is
++	  handled by the leds-pasic3 and ds1wm drivers.
++
+ endmenu
+ 
+ menu "Multimedia Capabilities Port drivers"
+diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
+index 521cd5c..eef4e26 100644
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -5,6 +5,9 @@
+ obj-$(CONFIG_MFD_SM501)		+= sm501.o
+ obj-$(CONFIG_MFD_ASIC3)		+= asic3.o
+ 
++obj-$(CONFIG_HTC_EGPIO)		+= htc-egpio.o
++obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
++
+ obj-$(CONFIG_MCP)		+= mcp-core.o
+ obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
+ obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
+diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
+new file mode 100644
+index 0000000..8872cc0
+--- /dev/null
++++ b/drivers/mfd/htc-egpio.c
+@@ -0,0 +1,440 @@
++/*
++ * Support for the GPIO/IRQ expander chips present on several HTC phones.
++ * These are implemented in CPLD chips present on the board.
++ *
++ * Copyright (c) 2007 Kevin O'Connor <kevin at koconnor.net>
++ * Copyright (c) 2007 Philipp Zabel <philipp.zabel at gmail.com>
++ *
++ * This file may be distributed under the terms of the GNU GPL license.
++ */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <linux/spinlock.h>
++#include <linux/platform_device.h>
++#include <linux/module.h>
++#include <linux/mfd/htc-egpio.h>
++
++struct egpio_chip {
++	int              reg_start;
++	int              cached_values;
++	unsigned long    is_out;
++	struct device    *dev;
++	struct gpio_chip chip;
++};
++
++struct egpio_info {
++	spinlock_t        lock;
++
++	/* iomem info */
++	void __iomem      *base_addr;
++	int               bus_shift;	/* byte shift */
++	int               reg_shift;	/* bit shift */
++	int               reg_mask;
++
++	/* irq info */
++	int               ack_register;
++	int               ack_write;
++	u16               irqs_enabled;
++	uint              irq_start;
++	int               nirqs;
++	uint              chained_irq;
++
++	/* egpio info */
++	struct egpio_chip *chip;
++	int               nchips;
++};
++
++static inline void egpio_writew(u16 value, struct egpio_info *ei, int reg)
++{
++	writew(value, ei->base_addr + (reg << ei->bus_shift));
++}
++
++static inline u16 egpio_readw(struct egpio_info *ei, int reg)
++{
++	return readw(ei->base_addr + (reg << ei->bus_shift));
++}
++
++/*
++ * IRQs
++ */
++
++static inline void ack_irqs(struct egpio_info *ei)
++{
++	egpio_writew(ei->ack_write, ei, ei->ack_register);
++	pr_debug("EGPIO ack - write %x to base+%x\n",
++			ei->ack_write, ei->ack_register << ei->bus_shift);
++}
++
++static void egpio_ack(unsigned int irq)
++{
++}
++
++/* There does not appear to be a way to proactively mask interrupts
++ * on the egpio chip itself.  So, we simply ignore interrupts that
++ * aren't desired. */
++static void egpio_mask(unsigned int irq)
++{
++	struct egpio_info *ei = get_irq_chip_data(irq);
++	ei->irqs_enabled &= ~(1 << (irq - ei->irq_start));
++	pr_debug("EGPIO mask %d %04x\n", irq, ei->irqs_enabled);
++}
++static void egpio_unmask(unsigned int irq)
++{
++	struct egpio_info *ei = get_irq_chip_data(irq);
++	ei->irqs_enabled |= 1 << (irq - ei->irq_start);
++	pr_debug("EGPIO unmask %d %04x\n", irq, ei->irqs_enabled);
++}
++
++static struct irq_chip egpio_muxed_chip = {
++	.name   = "htc-egpio",
++	.ack	= egpio_ack,
++	.mask   = egpio_mask,
++	.unmask = egpio_unmask,
++};
++
++static void egpio_handler(unsigned int irq, struct irq_desc *desc)
++{
++	struct egpio_info *ei = get_irq_data(irq);
++	int irqpin;
++
++	/* Read current pins. */
++	unsigned long readval = egpio_readw(ei, ei->ack_register);
++	pr_debug("IRQ reg: %x\n", (unsigned int)readval);
++	/* Ack/unmask interrupts. */
++	ack_irqs(ei);
++	/* Process all set pins. */
++	readval &= ei->irqs_enabled;
++	for_each_bit(irqpin, &readval, ei->nirqs) {
++		/* Run irq handler */
++		pr_debug("got IRQ %d\n", irqpin);
++		irq = ei->irq_start + irqpin;
++		desc = &irq_desc[irq];
++		desc->handle_irq(irq, desc);
++	}
++}
++
++int htc_egpio_get_wakeup_irq(struct device *dev)
++{
++	struct egpio_info *ei = dev_get_drvdata(dev);
++
++	/* Read current pins. */
++	u16 readval = egpio_readw(ei, ei->ack_register);
++	/* Ack/unmask interrupts. */
++	ack_irqs(ei);
++	/* Return first set pin. */
++	readval &= ei->irqs_enabled;
++	return ei->irq_start + ffs(readval) - 1;
++}
++EXPORT_SYMBOL(htc_egpio_get_wakeup_irq);
++
++static inline int egpio_pos(struct egpio_info *ei, int bit)
++{
++	return bit >> ei->reg_shift;
++}
++
++static inline int egpio_bit(struct egpio_info *ei, int bit)
++{
++	return 1 << (bit & ((1 << ei->reg_shift)-1));
++}
++
++/*
++ * Input pins
++ */
++
++static int egpio_get(struct gpio_chip *chip, unsigned offset)
++{
++	struct egpio_chip *egpio;
++	struct egpio_info *ei;
++	unsigned           bit;
++	int                reg;
++	int                value;
++
++	pr_debug("egpio_get_value(%d)\n", chip->base + offset);
++
++	egpio = container_of(chip, struct egpio_chip, chip);
++	ei    = dev_get_drvdata(egpio->dev);
++	bit   = egpio_bit(ei, offset);
++	reg   = egpio->reg_start + egpio_pos(ei, offset);
++
++	value = egpio_readw(ei, reg);
++	pr_debug("readw(%p + %x) = %x\n",
++			ei->base_addr, reg << ei->bus_shift, value);
++	return value & bit;
++}
++
++static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++	struct egpio_chip *egpio;
++
++	egpio = container_of(chip, struct egpio_chip, chip);
++	return test_bit(offset, &egpio->is_out) ? -EINVAL : 0;
++}
++
++
++/*
++ * Output pins
++ */
++
++static void egpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++	unsigned long     flag;
++	struct egpio_chip *egpio;
++	struct egpio_info *ei;
++	unsigned          bit;
++	int               pos;
++	int               reg;
++	int               shift;
++
++	pr_debug("egpio_set(%s, %d(%d), %d)\n",
++			chip->label, offset, offset+chip->base, value);
++
++	egpio = container_of(chip, struct egpio_chip, chip);
++	ei    = dev_get_drvdata(egpio->dev);
++	bit   = egpio_bit(ei, offset);
++	pos   = egpio_pos(ei, offset);
++	reg   = egpio->reg_start + pos;
++	shift = pos << ei->reg_shift;
++
++	pr_debug("egpio %s: reg %d = 0x%04x\n", value ? "set" : "clear",
++			reg, (egpio->cached_values >> shift) & ei->reg_mask);
++
++	spin_lock_irqsave(&ei->lock, flag);
++	if (value)
++		egpio->cached_values |= (1 << offset);
++	else
++		egpio->cached_values &= ~(1 << offset);
++	egpio_writew((egpio->cached_values >> shift) & ei->reg_mask, ei, reg);
++	spin_unlock_irqrestore(&ei->lock, flag);
++}
++
++static int egpio_direction_output(struct gpio_chip *chip,
++					unsigned offset, int value)
++{
++	struct egpio_chip *egpio;
++
++	egpio = container_of(chip, struct egpio_chip, chip);
++	if (test_bit(offset, &egpio->is_out)) {
++		egpio_set(chip, offset, value);
++		return 0;
++	} else {
++		return -EINVAL;
++	}
++}
++
++static void egpio_write_cache(struct egpio_info *ei)
++{
++	int               i;
++	struct egpio_chip *egpio;
++	int               shift;
++
++	for (i = 0; i < ei->nchips; i++) {
++		egpio = &(ei->chip[i]);
++		if (!egpio->is_out)
++			continue;
++
++		for (shift = 0; shift < egpio->chip.ngpio;
++				shift += (1<<ei->reg_shift)) {
++
++			int reg = egpio->reg_start + egpio_pos(ei, shift);
++
++			if (!((egpio->is_out >> shift) & ei->reg_mask))
++				continue;
++
++			pr_debug("EGPIO: setting %x to %x, was %x\n", reg,
++				(egpio->cached_values >> shift) & ei->reg_mask,
++				egpio_readw(ei, reg));
++
++			egpio_writew((egpio->cached_values >> shift)
++					& ei->reg_mask, ei, reg);
++		}
++	}
++}
++
++
++/*
++ * Setup
++ */
++
++static int __init egpio_probe(struct platform_device *pdev)
++{
++	struct htc_egpio_platform_data *pdata = pdev->dev.platform_data;
++	struct resource   *res;
++	struct egpio_info *ei;
++	struct gpio_chip  *chip;
++	unsigned int      irq, irq_end;
++	int               i;
++	int               ret;
++
++	/* Initialize ei data structure. */
++	ei = kzalloc(sizeof(*ei), GFP_KERNEL);
++	if (!ei)
++		return -ENOMEM;
++
++	spin_lock_init(&ei->lock);
++
++	/* Find chained irq */
++	ret = -EINVAL;
++	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++	if (res)
++		ei->chained_irq = res->start;
++
++	/* Map egpio chip into virtual address space. */
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!res)
++		goto fail;
++	ei->base_addr = ioremap_nocache(res->start, res->end - res->start);
++	if (!ei->base_addr)
++		goto fail;
++	pr_debug("EGPIO phys=%08x virt=%p\n", res->start, ei->base_addr);
++
++	if ((pdata->bus_width != 16) && (pdata->bus_width != 32))
++		goto fail;
++	ei->bus_shift = fls(pdata->bus_width - 1) - 3;
++	pr_debug("bus_shift = %d\n", ei->bus_shift);
++
++	if ((pdata->reg_width != 8) && (pdata->reg_width != 16))
++		goto fail;
++	ei->reg_shift = fls(pdata->reg_width - 1);
++	pr_debug("reg_shift = %d\n", ei->reg_shift);
++
++	ei->reg_mask = (1 << pdata->reg_width) - 1;
++
++	platform_set_drvdata(pdev, ei);
++
++	ei->nchips = pdata->num_chips;
++	ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL);
++	if (!ei) {
++		ret = -ENOMEM;
++		goto fail;
++	}
++	for (i = 0; i < ei->nchips; i++) {
++		ei->chip[i].reg_start = pdata->chip[i].reg_start;
++		ei->chip[i].cached_values = pdata->chip[i].initial_values;
++		ei->chip[i].is_out = pdata->chip[i].direction;
++		ei->chip[i].dev = &(pdev->dev);
++		chip = &(ei->chip[i].chip);
++		chip->label           = "htc-egpio";
++		chip->get             = egpio_get;
++		chip->set             = egpio_set;
++		chip->direction_input = egpio_direction_input;
++		chip->direction_output = egpio_direction_output;
++		chip->base            = pdata->chip[i].gpio_base;
++		chip->ngpio           = pdata->chip[i].num_gpios;
++
++		gpiochip_add(chip);
++	}
++
++	/* Set initial pin values */
++	egpio_write_cache(ei);
++
++	ei->irq_start = pdata->irq_base;
++	ei->nirqs = pdata->num_irqs;
++	ei->ack_register = pdata->ack_register;
++
++	if (ei->chained_irq) {
++		/* Setup irq handlers */
++		ei->ack_write = 0xFFFF;
++		if (pdata->invert_acks)
++			ei->ack_write = 0;
++		irq_end = ei->irq_start + ei->nirqs;
++		for (irq = ei->irq_start; irq < irq_end; irq++) {
++			set_irq_chip(irq, &egpio_muxed_chip);
++			set_irq_chip_data(irq, ei);
++			set_irq_handler(irq, handle_simple_irq);
++			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++		}
++		set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING);
++		set_irq_data(ei->chained_irq, ei);
++		set_irq_chained_handler(ei->chained_irq, egpio_handler);
++		ack_irqs(ei);
++
++		device_init_wakeup(&pdev->dev, 1);
++	}
++
++	return 0;
++
++fail:
++	printk(KERN_ERR "EGPIO failed to setup\n");
++	kfree(ei);
++	return ret;
++}
++
++static int __exit egpio_remove(struct platform_device *pdev)
++{
++	struct egpio_info *ei = platform_get_drvdata(pdev);
++	unsigned int      irq, irq_end;
++
++	if (ei->chained_irq) {
++		irq_end = ei->irq_start + ei->nirqs;
++		for (irq = ei->irq_start; irq < irq_end; irq++) {
++			set_irq_chip(irq, NULL);
++			set_irq_handler(irq, NULL);
++			set_irq_flags(irq, 0);
++		}
++		set_irq_chained_handler(ei->chained_irq, NULL);
++		device_init_wakeup(&pdev->dev, 0);
++	}
++	iounmap(ei->base_addr);
++	kfree(ei->chip);
++	kfree(ei);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int egpio_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	struct egpio_info *ei = platform_get_drvdata(pdev);
++
++	if (ei->chained_irq && device_may_wakeup(&pdev->dev))
++		enable_irq_wake(ei->chained_irq);
++	return 0;
++}
++
++static int egpio_resume(struct platform_device *pdev)
++{
++	struct egpio_info *ei = platform_get_drvdata(pdev);
++
++	if (ei->chained_irq && device_may_wakeup(&pdev->dev))
++		disable_irq_wake(ei->chained_irq);
++
++	/* Update registers from the cache, in case
++	   the CPLD was powered off during suspend */
++	egpio_write_cache(ei);
++	return 0;
++}
++#else
++#define egpio_suspend NULL
++#define egpio_resume NULL
++#endif
++
++
++static struct platform_driver egpio_driver = {
++	.driver = {
++		.name = "htc-egpio",
++	},
++	.remove       = __exit_p(egpio_remove),
++	.suspend      = egpio_suspend,
++	.resume       = egpio_resume,
++};
++
++static int __init egpio_init(void)
++{
++	return platform_driver_probe(&egpio_driver, egpio_probe);
++}
++
++static void __exit egpio_exit(void)
++{
++	platform_driver_unregister(&egpio_driver);
++}
++
++/* start early for dependencies */
++subsys_initcall(egpio_init);
++module_exit(egpio_exit)
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Kevin O'Connor <kevin at koconnor.net>");
+diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
+new file mode 100644
+index 0000000..4edc120
+--- /dev/null
++++ b/drivers/mfd/htc-pasic3.c
+@@ -0,0 +1,262 @@
++/*
++ * Core driver for HTC PASIC3 LED/DS1WM chip.
++ *
++ * Copyright (C) 2006 Philipp Zabel <philipp.zabel at gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <linux/ds1wm.h>
++#include <linux/gpio.h>
++#include <linux/io.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/mfd/htc-pasic3.h>
++
++struct pasic3_data {
++	void __iomem *mapping;
++	unsigned int bus_shift;
++	struct platform_device *ds1wm_pdev;
++	struct platform_device *led_pdev;
++};
++
++#define REG_ADDR  5
++#define REG_DATA  6
++
++#define READ_MODE 0x80
++
++/*
++ * write to a secondary register on the PASIC3
++ */
++void pasic3_write_register(struct device *dev, u32 reg, u8 val)
++{
++	struct pasic3_data *asic = dev->driver_data;
++	int bus_shift = asic->bus_shift;
++	void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
++	void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
++
++	__raw_writeb(~READ_MODE & reg, addr);
++	__raw_writeb(val, data);
++}
++EXPORT_SYMBOL(pasic3_write_register); /* for leds-pasic3 */
++
++/*
++ * read from a secondary register on the PASIC3
++ */
++u8 pasic3_read_register(struct device *dev, u32 reg)
++{
++	struct pasic3_data *asic = dev->driver_data;
++	int bus_shift = asic->bus_shift;
++	void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
++	void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
++
++	__raw_writeb(READ_MODE | reg, addr);
++	return __raw_readb(data);
++}
++EXPORT_SYMBOL(pasic3_read_register); /* for leds-pasic3 */
++
++/*
++ * LEDs
++ */
++
++static int led_device_add(struct device *pasic3_dev,
++				const struct pasic3_leds_machinfo *pdata)
++{
++	struct pasic3_data *asic = pasic3_dev->driver_data;
++	struct platform_device *pdev;
++	int ret;
++
++	pdev = platform_device_alloc("pasic3-led", -1);
++	if (!pdev) {
++		dev_dbg(pasic3_dev, "failed to allocate LED platform device\n");
++		return -ENOMEM;
++	}
++
++	ret = platform_device_add_data(pdev, pdata,
++					sizeof(struct pasic3_leds_machinfo));
++	if (ret < 0) {
++		dev_dbg(pasic3_dev, "failed to add LED platform data\n");
++		goto exit_pdev_put;
++	}
++
++	pdev->dev.parent = pasic3_dev;
++	ret = platform_device_add(pdev);
++	if (ret < 0) {
++		dev_dbg(pasic3_dev, "failed to add LED platform device\n");
++		goto exit_pdev_put;
++	}
++
++	asic->led_pdev = pdev;
++	return 0;
++
++exit_pdev_put:
++	platform_device_put(pdev);
++	return ret;
++}
++
++/*
++ * DS1WM
++ */
++
++static void ds1wm_enable(struct platform_device *pdev)
++{
++	struct device *dev = pdev->dev.parent;
++	int c;
++
++	c = pasic3_read_register(dev, 0x28);
++	pasic3_write_register(dev, 0x28, c & 0x7f);
++
++	dev_dbg(dev, "DS1WM OWM_EN low (active) %02x\n", c & 0x7f);
++}
++
++static void ds1wm_disable(struct platform_device *pdev)
++{
++	struct device *dev = pdev->dev.parent;
++	int c;
++
++	c = pasic3_read_register(dev, 0x28);
++	pasic3_write_register(dev, 0x28, c | 0x80);
++
++	dev_dbg(dev, "DS1WM OWM_EN high (inactive) %02x\n", c | 0x80);
++}
++
++static struct ds1wm_platform_data ds1wm_pdata = {
++	.bus_shift = 2,
++	.enable    = ds1wm_enable,
++	.disable   = ds1wm_disable,
++};
++
++static int ds1wm_device_add(struct device *pasic3_dev, int bus_shift)
++{
++	struct pasic3_data *asic = pasic3_dev->driver_data;
++	struct platform_device *pdev;
++	int ret;
++
++	pdev = platform_device_alloc("ds1wm", -1);
++	if (!pdev) {
++		dev_dbg(pasic3_dev, "failed to allocate DS1WM platform device\n");
++		return -ENOMEM;
++	}
++
++	ret = platform_device_add_resources(pdev, pdev->resource,
++						pdev->num_resources);
++	if (ret < 0) {
++		dev_dbg(pasic3_dev, "failed to add DS1WM resources\n");
++		goto exit_pdev_put;
++	}
++
++	ds1wm_pdata.bus_shift = asic->bus_shift;
++	ret = platform_device_add_data(pdev, &ds1wm_pdata,
++					sizeof(struct ds1wm_platform_data));
++	if (ret < 0) {
++		dev_dbg(pasic3_dev, "failed to add DS1WM platform data\n");
++		goto exit_pdev_put;
++	}
++
++	pdev->dev.parent = pasic3_dev;
++	ret = platform_device_add(pdev);
++	if (ret < 0) {
++		dev_dbg(pasic3_dev, "failed to add DS1WM platform device\n");
++		goto exit_pdev_put;
++	}
++
++	asic->ds1wm_pdev = pdev;
++	return 0;
++
++exit_pdev_put:
++	platform_device_put(pdev);
++	return ret;
++}
++
++static int __init pasic3_probe(struct platform_device *pdev)
++{
++	struct pasic3_platform_data *pdata = pdev->dev.platform_data;
++	struct device *dev = &pdev->dev;
++	struct pasic3_data *asic;
++	struct resource *r;
++	int ret;
++
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!r)
++		return -ENXIO;
++
++	if (!request_mem_region(r->start, r->end - r->start + 1, "pasic3"))
++		return -EBUSY;
++
++	asic = kzalloc(sizeof(struct pasic3_data), GFP_KERNEL);
++	if (!asic)
++		return -ENOMEM;
++
++	platform_set_drvdata(pdev, asic);
++
++	if (pdata && pdata->bus_shift)
++		asic->bus_shift = pdata->bus_shift;
++	else
++		asic->bus_shift = 2;
++
++	asic->mapping = ioremap(r->start, r->end - r->start + 1);
++	if (!asic->mapping) {
++		dev_err(dev, "couldn't ioremap PASIC3\n");
++		kfree(asic);
++		return -ENOMEM;
++	}
++
++	ret = ds1wm_device_add(dev, asic->bus_shift);
++	if (ret < 0)
++		dev_warn(dev, "failed to register DS1WM\n");
++
++	if (pdata->led_pdata) {
++		ret = led_device_add(dev, pdata->led_pdata);
++		if (ret < 0)
++			dev_warn(dev, "failed to register LED device\n");
++	}
++
++	return 0;
++}
++
++static int pasic3_remove(struct platform_device *pdev)
++{
++	struct pasic3_data *asic = platform_get_drvdata(pdev);
++	struct resource *r;
++
++	if (asic->led_pdev)
++		platform_device_unregister(asic->led_pdev);
++	if (asic->ds1wm_pdev)
++		platform_device_unregister(asic->ds1wm_pdev);
++
++	iounmap(asic->mapping);
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	release_mem_region(r->start, r->end - r->start + 1);
++	kfree(asic);
++	return 0;
++}
++
++static struct platform_driver pasic3_driver = {
++	.driver		= {
++		.name	= "pasic3",
++	},
++	.remove		= pasic3_remove,
++};
++
++static int __init pasic3_base_init(void)
++{
++	return platform_driver_probe(&pasic3_driver, pasic3_probe);
++}
++
++static void __exit pasic3_base_exit(void)
++{
++	platform_driver_unregister(&pasic3_driver);
++}
++
++module_init(pasic3_base_init);
++module_exit(pasic3_base_exit);
++
++MODULE_AUTHOR("Philipp Zabel <philipp.zabel at gmail.com>");
++MODULE_DESCRIPTION("Core driver for HTC PASIC3");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
+index fdbaa77..5e85948 100644
+--- a/drivers/mfd/ucb1x00-ts.c
++++ b/drivers/mfd/ucb1x00-ts.c
+@@ -32,7 +32,6 @@
+ #include <linux/kthread.h>
+ 
+ #include <asm/dma.h>
+-#include <asm/semaphore.h>
+ #include <asm/arch/collie.h>
+ #include <asm/mach-types.h>
+ 
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 962817e..297a48f 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -22,6 +22,39 @@ config ATMEL_PWM
+ 	  purposes including software controlled power-efficent backlights
+ 	  on LCD displays, motor control, and waveform generation.
+ 
++config ATMEL_TCLIB
++	bool "Atmel AT32/AT91 Timer/Counter Library"
++	depends on (AVR32 || ARCH_AT91)
++	help
++	  Select this if you want a library to allocate the Timer/Counter
++	  blocks found on many Atmel processors.  This facilitates using
++	  these blocks by different drivers despite processor differences.
++
++config ATMEL_TCB_CLKSRC
++	bool "TC Block Clocksource"
++	depends on ATMEL_TCLIB && GENERIC_TIME
++	default y
++	help
++	  Select this to get a high precision clocksource based on a
++	  TC block with a 5+ MHz base clock rate.  Two timer channels
++	  are combined to make a single 32-bit timer.
++
++	  When GENERIC_CLOCKEVENTS is defined, the third timer channel
++	  may be used as a clock event device supporting oneshot mode
++	  (delays of up to two seconds) based on the 32 KiHz clock.
++
++config ATMEL_TCB_CLKSRC_BLOCK
++	int
++	depends on ATMEL_TCB_CLKSRC
++	prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X
++	default 0
++	range 0 1
++	help
++	  Some chips provide more than one TC block, so you have the
++	  choice of which one to use for the clock framework.  The other
++	  TC can be used for other purposes, such as PWM generation and
++	  interval timing.
++
+ config IBM_ASM
+ 	tristate "Device driver for IBM RSA service processor"
+ 	depends on X86 && PCI && INPUT && EXPERIMENTAL
+@@ -327,4 +360,16 @@ config ENCLOSURE_SERVICES
+ 	  driver (SCSI/ATA) which supports enclosures
+ 	  or a SCSI enclosure device (SES) to use these services.
+ 
++config SGI_XP
++	tristate "Support communication between SGI SSIs"
++	depends on IA64_GENERIC || IA64_SGI_SN2
++	select IA64_UNCACHED_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2
++	select GENERIC_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2
++	---help---
++	  An SGI machine can be divided into multiple Single System
++	  Images which act independently of each other and have
++	  hardware based memory protection from the others.  Enabling
++	  this feature will allow for direct communication between SSIs
++	  based on a network adapter and DMA messaging.
++
+ endif # MISC_DEVICES
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 3b12f5d..5914da4 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_ACER_WMI)     += acer-wmi.o
+ obj-$(CONFIG_ASUS_LAPTOP)     += asus-laptop.o
+ obj-$(CONFIG_ATMEL_PWM)		+= atmel_pwm.o
+ obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
++obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
+ obj-$(CONFIG_TC1100_WMI)	+= tc1100-wmi.o
+ obj-$(CONFIG_LKDTM)		+= lkdtm.o
+ obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
+@@ -22,3 +23,5 @@ obj-$(CONFIG_FUJITSU_LAPTOP)	+= fujitsu-laptop.o
+ obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
+ obj-$(CONFIG_INTEL_MENLOW)	+= intel_menlow.o
+ obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
++obj-$(CONFIG_KGDB_TESTS)	+= kgdbts.o
++obj-$(CONFIG_SGI_XP)		+= sgi-xp/
+diff --git a/drivers/misc/atmel_tclib.c b/drivers/misc/atmel_tclib.c
+new file mode 100644
+index 0000000..05dc8a3
+--- /dev/null
++++ b/drivers/misc/atmel_tclib.c
+@@ -0,0 +1,161 @@
++#include <linux/atmel_tc.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++/* Number of bytes to reserve for the iomem resource */
++#define ATMEL_TC_IOMEM_SIZE	256
++
++
++/*
++ * This is a thin library to solve the problem of how to portably allocate
++ * one of the TC blocks.  For simplicity, it doesn't currently expect to
++ * share individual timers between different drivers.
++ */
++
++#if defined(CONFIG_AVR32)
++/* AVR32 has these divide PBB */
++const u8 atmel_tc_divisors[5] = { 0, 4, 8, 16, 32, };
++EXPORT_SYMBOL(atmel_tc_divisors);
++
++#elif defined(CONFIG_ARCH_AT91)
++/* AT91 has these divide MCK */
++const u8 atmel_tc_divisors[5] = { 2, 8, 32, 128, 0, };
++EXPORT_SYMBOL(atmel_tc_divisors);
++
++#endif
++
++static DEFINE_SPINLOCK(tc_list_lock);
++static LIST_HEAD(tc_list);
++
++/**
++ * atmel_tc_alloc - allocate a specified TC block
++ * @block: which block to allocate
++ * @name: name to be associated with the iomem resource
++ *
++ * Caller allocates a block.  If it is available, a pointer to a
++ * pre-initialized struct atmel_tc is returned. The caller can access
++ * the registers directly through the "regs" field.
++ */
++struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name)
++{
++	struct atmel_tc		*tc;
++	struct platform_device	*pdev = NULL;
++	struct resource		*r;
++
++	spin_lock(&tc_list_lock);
++	list_for_each_entry(tc, &tc_list, node) {
++		if (tc->pdev->id == block) {
++			pdev = tc->pdev;
++			break;
++		}
++	}
++
++	if (!pdev || tc->iomem)
++		goto fail;
++
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	r = request_mem_region(r->start, ATMEL_TC_IOMEM_SIZE, name);
++	if (!r)
++		goto fail;
++
++	tc->regs = ioremap(r->start, ATMEL_TC_IOMEM_SIZE);
++	if (!tc->regs)
++		goto fail_ioremap;
++
++	tc->iomem = r;
++
++out:
++	spin_unlock(&tc_list_lock);
++	return tc;
++
++fail_ioremap:
++	release_resource(r);
++fail:
++	tc = NULL;
++	goto out;
++}
++EXPORT_SYMBOL_GPL(atmel_tc_alloc);
++
++/**
++ * atmel_tc_free - release a specified TC block
++ * @tc: Timer/counter block that was returned by atmel_tc_alloc()
++ *
++ * This reverses the effect of atmel_tc_alloc(), unmapping the I/O
++ * registers, invalidating the resource returned by that routine and
++ * making the TC available to other drivers.
++ */
++void atmel_tc_free(struct atmel_tc *tc)
++{
++	spin_lock(&tc_list_lock);
++	if (tc->regs) {
++		iounmap(tc->regs);
++		release_resource(tc->iomem);
++		tc->regs = NULL;
++		tc->iomem = NULL;
++	}
++	spin_unlock(&tc_list_lock);
++}
++EXPORT_SYMBOL_GPL(atmel_tc_free);
++
++static int __init tc_probe(struct platform_device *pdev)
++{
++	struct atmel_tc *tc;
++	struct clk	*clk;
++	int		irq;
++
++	if (!platform_get_resource(pdev, IORESOURCE_MEM, 0))
++		return -EINVAL;
++
++	irq = platform_get_irq(pdev, 0);
++	if (irq < 0)
++		return -EINVAL;
++
++	tc = kzalloc(sizeof(struct atmel_tc), GFP_KERNEL);
++	if (!tc)
++		return -ENOMEM;
++
++	tc->pdev = pdev;
++
++	clk = clk_get(&pdev->dev, "t0_clk");
++	if (IS_ERR(clk)) {
++		kfree(tc);
++		return -EINVAL;
++	}
++
++	tc->clk[0] = clk;
++	tc->clk[1] = clk_get(&pdev->dev, "t1_clk");
++	if (IS_ERR(tc->clk[1]))
++		tc->clk[1] = clk;
++	tc->clk[2] = clk_get(&pdev->dev, "t2_clk");
++	if (IS_ERR(tc->clk[2]))
++		tc->clk[2] = clk;
++
++	tc->irq[0] = irq;
++	tc->irq[1] = platform_get_irq(pdev, 1);
++	if (tc->irq[1] < 0)
++		tc->irq[1] = irq;
++	tc->irq[2] = platform_get_irq(pdev, 2);
++	if (tc->irq[2] < 0)
++		tc->irq[2] = irq;
++
++	spin_lock(&tc_list_lock);
++	list_add_tail(&tc->node, &tc_list);
++	spin_unlock(&tc_list_lock);
++
++	return 0;
++}
++
++static struct platform_driver tc_driver = {
++	.driver.name	= "atmel_tcb",
++};
++
++static int __init tc_init(void)
++{
++	return platform_driver_probe(&tc_driver, tc_probe);
++}
++arch_initcall(tc_init);
+diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
+index 6fcb0e9..fafb57f 100644
+--- a/drivers/misc/enclosure.c
++++ b/drivers/misc/enclosure.c
+@@ -40,16 +40,16 @@ static struct class enclosure_component_class;
+  * Looks through the list of registered enclosures to see
+  * if it can find a match for a device.  Returns NULL if no
+  * enclosure is found. Obtains a reference to the enclosure class
+- * device which must be released with class_device_put().
++ * device which must be released with device_put().
+  */
+ struct enclosure_device *enclosure_find(struct device *dev)
+ {
+-	struct enclosure_device *edev = NULL;
++	struct enclosure_device *edev;
+ 
+ 	mutex_lock(&container_list_lock);
+ 	list_for_each_entry(edev, &container_list, node) {
+-		if (edev->cdev.dev == dev) {
+-			class_device_get(&edev->cdev);
++		if (edev->edev.parent == dev) {
++			get_device(&edev->edev);
+ 			mutex_unlock(&container_list_lock);
+ 			return edev;
+ 		}
+@@ -117,11 +117,11 @@ enclosure_register(struct device *dev, const char *name, int components,
+ 
+ 	edev->components = components;
+ 
+-	edev->cdev.class = &enclosure_class;
+-	edev->cdev.dev = get_device(dev);
++	edev->edev.class = &enclosure_class;
++	edev->edev.parent = get_device(dev);
+ 	edev->cb = cb;
+-	snprintf(edev->cdev.class_id, BUS_ID_SIZE, "%s", name);
+-	err = class_device_register(&edev->cdev);
++	snprintf(edev->edev.bus_id, BUS_ID_SIZE, "%s", name);
++	err = device_register(&edev->edev);
+ 	if (err)
+ 		goto err;
+ 
+@@ -135,7 +135,7 @@ enclosure_register(struct device *dev, const char *name, int components,
+ 	return edev;
+ 
+  err:
+-	put_device(edev->cdev.dev);
++	put_device(edev->edev.parent);
+ 	kfree(edev);
+ 	return ERR_PTR(err);
+ }
+@@ -158,27 +158,28 @@ void enclosure_unregister(struct enclosure_device *edev)
+ 
+ 	for (i = 0; i < edev->components; i++)
+ 		if (edev->component[i].number != -1)
+-			class_device_unregister(&edev->component[i].cdev);
++			device_unregister(&edev->component[i].cdev);
+ 
+ 	/* prevent any callbacks into service user */
+ 	edev->cb = &enclosure_null_callbacks;
+-	class_device_unregister(&edev->cdev);
++	device_unregister(&edev->edev);
+ }
+ EXPORT_SYMBOL_GPL(enclosure_unregister);
+ 
+-static void enclosure_release(struct class_device *cdev)
++static void enclosure_release(struct device *cdev)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev);
+ 
+-	put_device(cdev->dev);
++	put_device(cdev->parent);
+ 	kfree(edev);
+ }
+ 
+-static void enclosure_component_release(struct class_device *cdev)
++static void enclosure_component_release(struct device *dev)
+ {
+-	if (cdev->dev)
+-		put_device(cdev->dev);
+-	class_device_put(cdev->parent);
++	struct enclosure_component *cdev = to_enclosure_component(dev);
++
++	put_device(cdev->dev);
++	put_device(dev->parent);
+ }
+ 
+ /**
+@@ -201,7 +202,7 @@ enclosure_component_register(struct enclosure_device *edev,
+ 			     const char *name)
+ {
+ 	struct enclosure_component *ecomp;
+-	struct class_device *cdev;
++	struct device *cdev;
+ 	int err;
+ 
+ 	if (number >= edev->components)
+@@ -215,14 +216,14 @@ enclosure_component_register(struct enclosure_device *edev,
+ 	ecomp->type = type;
+ 	ecomp->number = number;
+ 	cdev = &ecomp->cdev;
+-	cdev->parent = class_device_get(&edev->cdev);
++	cdev->parent = get_device(&edev->edev);
+ 	cdev->class = &enclosure_component_class;
+ 	if (name)
+-		snprintf(cdev->class_id, BUS_ID_SIZE, "%s", name);
++		snprintf(cdev->bus_id, BUS_ID_SIZE, "%s", name);
+ 	else
+-		snprintf(cdev->class_id, BUS_ID_SIZE, "%u", number);
++		snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number);
+ 
+-	err = class_device_register(cdev);
++	err = device_register(cdev);
+ 	if (err)
+ 		ERR_PTR(err);
+ 
+@@ -247,18 +248,17 @@ EXPORT_SYMBOL_GPL(enclosure_component_register);
+ int enclosure_add_device(struct enclosure_device *edev, int component,
+ 			 struct device *dev)
+ {
+-	struct class_device *cdev;
++	struct enclosure_component *cdev;
+ 
+ 	if (!edev || component >= edev->components)
+ 		return -EINVAL;
+ 
+-	cdev = &edev->component[component].cdev;
++	cdev = &edev->component[component];
+ 
+-	class_device_del(cdev);
+-	if (cdev->dev)
+-		put_device(cdev->dev);
++	device_del(&cdev->cdev);
++	put_device(cdev->dev);
+ 	cdev->dev = get_device(dev);
+-	return class_device_add(cdev);
++	return device_add(&cdev->cdev);
+ }
+ EXPORT_SYMBOL_GPL(enclosure_add_device);
+ 
+@@ -272,18 +272,17 @@ EXPORT_SYMBOL_GPL(enclosure_add_device);
+  */
+ int enclosure_remove_device(struct enclosure_device *edev, int component)
+ {
+-	struct class_device *cdev;
++	struct enclosure_component *cdev;
+ 
+ 	if (!edev || component >= edev->components)
+ 		return -EINVAL;
+ 
+-	cdev = &edev->component[component].cdev;
++	cdev = &edev->component[component];
+ 
+-	class_device_del(cdev);
+-	if (cdev->dev)
+-		put_device(cdev->dev);
++	device_del(&cdev->cdev);
++	put_device(cdev->dev);
+ 	cdev->dev = NULL;
+-	return class_device_add(cdev);
++	return device_add(&cdev->cdev);
+ }
+ EXPORT_SYMBOL_GPL(enclosure_remove_device);
+ 
+@@ -291,14 +290,16 @@ EXPORT_SYMBOL_GPL(enclosure_remove_device);
+  * sysfs pieces below
+  */
+ 
+-static ssize_t enclosure_show_components(struct class_device *cdev, char *buf)
++static ssize_t enclosure_show_components(struct device *cdev,
++					 struct device_attribute *attr,
++					 char *buf)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev);
+ 
+ 	return snprintf(buf, 40, "%d\n", edev->components);
+ }
+ 
+-static struct class_device_attribute enclosure_attrs[] = {
++static struct device_attribute enclosure_attrs[] = {
+ 	__ATTR(components, S_IRUGO, enclosure_show_components, NULL),
+ 	__ATTR_NULL
+ };
+@@ -306,8 +307,8 @@ static struct class_device_attribute enclosure_attrs[] = {
+ static struct class enclosure_class = {
+ 	.name			= "enclosure",
+ 	.owner			= THIS_MODULE,
+-	.release		= enclosure_release,
+-	.class_dev_attrs	= enclosure_attrs,
++	.dev_release		= enclosure_release,
++	.dev_attrs		= enclosure_attrs,
+ };
+ 
+ static const char *const enclosure_status [] = {
+@@ -326,7 +327,8 @@ static const char *const enclosure_type [] = {
+ 	[ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
+ };
+ 
+-static ssize_t get_component_fault(struct class_device *cdev, char *buf)
++static ssize_t get_component_fault(struct device *cdev,
++				   struct device_attribute *attr, char *buf)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ 	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -336,8 +338,9 @@ static ssize_t get_component_fault(struct class_device *cdev, char *buf)
+ 	return snprintf(buf, 40, "%d\n", ecomp->fault);
+ }
+ 
+-static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
+-				   size_t count)
++static ssize_t set_component_fault(struct device *cdev,
++				   struct device_attribute *attr,
++				   const char *buf, size_t count)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ 	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -348,7 +351,8 @@ static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
+ 	return count;
+ }
+ 
+-static ssize_t get_component_status(struct class_device *cdev, char *buf)
++static ssize_t get_component_status(struct device *cdev,
++				    struct device_attribute *attr,char *buf)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ 	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -358,8 +362,9 @@ static ssize_t get_component_status(struct class_device *cdev, char *buf)
+ 	return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]);
+ }
+ 
+-static ssize_t set_component_status(struct class_device *cdev, const char *buf,
+-				   size_t count)
++static ssize_t set_component_status(struct device *cdev,
++				    struct device_attribute *attr,
++				    const char *buf, size_t count)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ 	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -380,7 +385,8 @@ static ssize_t set_component_status(struct class_device *cdev, const char *buf,
+ 		return -EINVAL;
+ }
+ 
+-static ssize_t get_component_active(struct class_device *cdev, char *buf)
++static ssize_t get_component_active(struct device *cdev,
++				    struct device_attribute *attr, char *buf)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ 	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -390,8 +396,9 @@ static ssize_t get_component_active(struct class_device *cdev, char *buf)
+ 	return snprintf(buf, 40, "%d\n", ecomp->active);
+ }
+ 
+-static ssize_t set_component_active(struct class_device *cdev, const char *buf,
+-				   size_t count)
++static ssize_t set_component_active(struct device *cdev,
++				    struct device_attribute *attr,
++				    const char *buf, size_t count)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ 	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -402,7 +409,8 @@ static ssize_t set_component_active(struct class_device *cdev, const char *buf,
+ 	return count;
+ }
+ 
+-static ssize_t get_component_locate(struct class_device *cdev, char *buf)
++static ssize_t get_component_locate(struct device *cdev,
++				    struct device_attribute *attr, char *buf)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ 	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -412,8 +420,9 @@ static ssize_t get_component_locate(struct class_device *cdev, char *buf)
+ 	return snprintf(buf, 40, "%d\n", ecomp->locate);
+ }
+ 
+-static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
+-				   size_t count)
++static ssize_t set_component_locate(struct device *cdev,
++				    struct device_attribute *attr,
++				    const char *buf, size_t count)
+ {
+ 	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ 	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -424,7 +433,8 @@ static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
+ 	return count;
+ }
+ 
+-static ssize_t get_component_type(struct class_device *cdev, char *buf)
++static ssize_t get_component_type(struct device *cdev,
++				  struct device_attribute *attr, char *buf)
+ {
+ 	struct enclosure_component *ecomp = to_enclosure_component(cdev);
+ 
+@@ -432,7 +442,7 @@ static ssize_t get_component_type(struct class_device *cdev, char *buf)
+ }
+ 
+ 
+-static struct class_device_attribute enclosure_component_attrs[] = {
++static struct device_attribute enclosure_component_attrs[] = {
+ 	__ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
+ 	       set_component_fault),
+ 	__ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
+@@ -448,8 +458,8 @@ static struct class_device_attribute enclosure_component_attrs[] = {
+ static struct class enclosure_component_class =  {
+ 	.name			= "enclosure_component",
+ 	.owner			= THIS_MODULE,
+-	.class_dev_attrs	= enclosure_component_attrs,
+-	.release		= enclosure_component_release,
++	.dev_attrs	= enclosure_component_attrs,
++	.dev_release		= enclosure_component_release,
+ };
+ 
+ static int __init enclosure_init(void)
+diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c
+index de16e88..0c0bb30 100644
+--- a/drivers/misc/intel_menlow.c
++++ b/drivers/misc/intel_menlow.c
+@@ -213,7 +213,7 @@ static int intel_menlow_memory_remove(struct acpi_device *device, int type)
+ 	return 0;
+ }
+ 
+-const static struct acpi_device_id intel_menlow_memory_ids[] = {
++static const struct acpi_device_id intel_menlow_memory_ids[] = {
+ 	{"INT0002", 0},
+ 	{"", 0},
+ };
+diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
+new file mode 100644
+index 0000000..6d6286c
+--- /dev/null
++++ b/drivers/misc/kgdbts.c
+@@ -0,0 +1,1090 @@
++/*
++ * kgdbts is a test suite for kgdb for the sole purpose of validating
++ * that key pieces of the kgdb internals are working properly such as
++ * HW/SW breakpoints, single stepping, and NMI.
++ *
++ * Created by: Jason Wessel <jason.wessel at windriver.com>
++ *
++ * Copyright (c) 2008 Wind River Systems, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ * See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* Information about the kgdb test suite.
++ * -------------------------------------
++ *
++ * The kgdb test suite is designed as a KGDB I/O module which
++ * simulates the communications that a debugger would have with kgdb.
++ * The tests are broken up in to a line by line and referenced here as
++ * a "get" which is kgdb requesting input and "put" which is kgdb
++ * sending a response.
++ *
++ * The kgdb suite can be invoked from the kernel command line
++ * arguments system or executed dynamically at run time.  The test
++ * suite uses the variable "kgdbts" to obtain the information about
++ * which tests to run and to configure the verbosity level.  The
++ * following are the various characters you can use with the kgdbts=
++ * line:
++ *
++ * When using the "kgdbts=" you only choose one of the following core
++ * test types:
++ * A = Run all the core tests silently
++ * V1 = Run all the core tests with minimal output
++ * V2 = Run all the core tests in debug mode
++ *
++ * You can also specify optional tests:
++ * N## = Go to sleep with interrupts of for ## seconds
++ *       to test the HW NMI watchdog
++ * F## = Break at do_fork for ## iterations
++ * S## = Break at sys_open for ## iterations
++ *
++ * NOTE: that the do_fork and sys_open tests are mutually exclusive.
++ *
++ * To invoke the kgdb test suite from boot you use a kernel start
++ * argument as follows:
++ * 	kgdbts=V1 kgdbwait
++ * Or if you wanted to perform the NMI test for 6 seconds and do_fork
++ * test for 100 forks, you could use:
++ * 	kgdbts=V1N6F100 kgdbwait
++ *
++ * The test suite can also be invoked at run time with:
++ *	echo kgdbts=V1N6F100 > /sys/module/kgdbts/parameters/kgdbts
++ * Or as another example:
++ *	echo kgdbts=V2 > /sys/module/kgdbts/parameters/kgdbts
++ *
++ * When developing a new kgdb arch specific implementation or
++ * using these tests for the purpose of regression testing,
++ * several invocations are required.
++ *
++ * 1) Boot with the test suite enabled by using the kernel arguments
++ *       "kgdbts=V1F100 kgdbwait"
++ *    ## If kgdb arch specific implementation has NMI use
++ *       "kgdbts=V1N6F100
++ *
++ * 2) After the system boot run the basic test.
++ * echo kgdbts=V1 > /sys/module/kgdbts/parameters/kgdbts
++ *
++ * 3) Run the concurrency tests.  It is best to use n+1
++ *    while loops where n is the number of cpus you have
++ *    in your system.  The example below uses only two
++ *    loops.
++ *
++ * ## This tests break points on sys_open
++ * while [ 1 ] ; do find / > /dev/null 2>&1 ; done &
++ * while [ 1 ] ; do find / > /dev/null 2>&1 ; done &
++ * echo kgdbts=V1S10000 > /sys/module/kgdbts/parameters/kgdbts
++ * fg # and hit control-c
++ * fg # and hit control-c
++ * ## This tests break points on do_fork
++ * while [ 1 ] ; do date > /dev/null ; done &
++ * while [ 1 ] ; do date > /dev/null ; done &
++ * echo kgdbts=V1F1000 > /sys/module/kgdbts/parameters/kgdbts
++ * fg # and hit control-c
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/kgdb.h>
++#include <linux/ctype.h>
++#include <linux/uaccess.h>
++#include <linux/syscalls.h>
++#include <linux/nmi.h>
++#include <linux/delay.h>
++#include <linux/kthread.h>
++#include <linux/delay.h>
++
++#define v1printk(a...) do { \
++	if (verbose) \
++		printk(KERN_INFO a); \
++	} while (0)
++#define v2printk(a...) do { \
++	if (verbose > 1) \
++		printk(KERN_INFO a); \
++		touch_nmi_watchdog();	\
++	} while (0)
++#define eprintk(a...) do { \
++		printk(KERN_ERR a); \
++		WARN_ON(1); \
++	} while (0)
++#define MAX_CONFIG_LEN		40
++
++static const char hexchars[] = "0123456789abcdef";
++static struct kgdb_io kgdbts_io_ops;
++static char get_buf[BUFMAX];
++static int get_buf_cnt;
++static char put_buf[BUFMAX];
++static int put_buf_cnt;
++static char scratch_buf[BUFMAX];
++static int verbose;
++static int repeat_test;
++static int test_complete;
++static int send_ack;
++static int final_ack;
++static int hw_break_val;
++static int hw_break_val2;
++#if defined(CONFIG_ARM) || defined(CONFIG_MIPS)
++static int arch_needs_sstep_emulation = 1;
++#else
++static int arch_needs_sstep_emulation;
++#endif
++static unsigned long sstep_addr;
++static int sstep_state;
++
++/* Storage for the registers, in GDB format. */
++static unsigned long kgdbts_gdb_regs[(NUMREGBYTES +
++					sizeof(unsigned long) - 1) /
++					sizeof(unsigned long)];
++static struct pt_regs kgdbts_regs;
++
++/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
++static int configured		= -1;
++
++#ifdef CONFIG_KGDB_TESTS_BOOT_STRING
++static char config[MAX_CONFIG_LEN] = CONFIG_KGDB_TESTS_BOOT_STRING;
++#else
++static char config[MAX_CONFIG_LEN];
++#endif
++static struct kparam_string kps = {
++	.string			= config,
++	.maxlen			= MAX_CONFIG_LEN,
++};
++
++static void fill_get_buf(char *buf);
++
++struct test_struct {
++	char *get;
++	char *put;
++	void (*get_handler)(char *);
++	int (*put_handler)(char *, char *);
++};
++
++struct test_state {
++	char *name;
++	struct test_struct *tst;
++	int idx;
++	int (*run_test) (int, int);
++	int (*validate_put) (char *);
++};
++
++static struct test_state ts;
++
++static int kgdbts_unreg_thread(void *ptr)
++{
++	/* Wait until the tests are complete and then ungresiter the I/O
++	 * driver.
++	 */
++	while (!final_ack)
++		msleep_interruptible(1500);
++
++	if (configured)
++		kgdb_unregister_io_module(&kgdbts_io_ops);
++	configured = 0;
++
++	return 0;
++}
++
++/* This is noinline such that it can be used for a single location to
++ * place a breakpoint
++ */
++static noinline void kgdbts_break_test(void)
++{
++	v2printk("kgdbts: breakpoint complete\n");
++}
++
++/* Lookup symbol info in the kernel */
++static unsigned long lookup_addr(char *arg)
++{
++	unsigned long addr = 0;
++
++	if (!strcmp(arg, "kgdbts_break_test"))
++		addr = (unsigned long)kgdbts_break_test;
++	else if (!strcmp(arg, "sys_open"))
++		addr = (unsigned long)sys_open;
++	else if (!strcmp(arg, "do_fork"))
++		addr = (unsigned long)do_fork;
++	else if (!strcmp(arg, "hw_break_val"))
++		addr = (unsigned long)&hw_break_val;
++	return addr;
++}
++
++static void break_helper(char *bp_type, char *arg, unsigned long vaddr)
++{
++	unsigned long addr;
++
++	if (arg)
++		addr = lookup_addr(arg);
++	else
++		addr = vaddr;
++
++	sprintf(scratch_buf, "%s,%lx,%i", bp_type, addr,
++		BREAK_INSTR_SIZE);
++	fill_get_buf(scratch_buf);
++}
++
++static void sw_break(char *arg)
++{
++	break_helper("Z0", arg, 0);
++}
++
++static void sw_rem_break(char *arg)
++{
++	break_helper("z0", arg, 0);
++}
++
++static void hw_break(char *arg)
++{
++	break_helper("Z1", arg, 0);
++}
++
++static void hw_rem_break(char *arg)
++{
++	break_helper("z1", arg, 0);
++}
++
++static void hw_write_break(char *arg)
++{
++	break_helper("Z2", arg, 0);
++}
++
++static void hw_rem_write_break(char *arg)
++{
++	break_helper("z2", arg, 0);
++}
++
++static void hw_access_break(char *arg)
++{
++	break_helper("Z4", arg, 0);
++}
++
++static void hw_rem_access_break(char *arg)
++{
++	break_helper("z4", arg, 0);
++}
++
++static void hw_break_val_access(void)
++{
++	hw_break_val2 = hw_break_val;
++}
++
++static void hw_break_val_write(void)
++{
++	hw_break_val++;
++}
++
++static int check_and_rewind_pc(char *put_str, char *arg)
++{
++	unsigned long addr = lookup_addr(arg);
++	int offset = 0;
++
++	kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
++		 NUMREGBYTES);
++	gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
++	v2printk("Stopped at IP: %lx\n", instruction_pointer(&kgdbts_regs));
++#ifdef CONFIG_X86
++	/* On x86 a breakpoint stop requires it to be decremented */
++	if (addr + 1 == kgdbts_regs.ip)
++		offset = -1;
++#endif
++	if (strcmp(arg, "silent") &&
++		instruction_pointer(&kgdbts_regs) + offset != addr) {
++		eprintk("kgdbts: BP mismatch %lx expected %lx\n",
++			   instruction_pointer(&kgdbts_regs) + offset, addr);
++		return 1;
++	}
++#ifdef CONFIG_X86
++	/* On x86 adjust the instruction pointer if needed */
++	kgdbts_regs.ip += offset;
++#endif
++	return 0;
++}
++
++static int check_single_step(char *put_str, char *arg)
++{
++	unsigned long addr = lookup_addr(arg);
++	/*
++	 * From an arch indepent point of view the instruction pointer
++	 * should be on a different instruction
++	 */
++	kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
++		 NUMREGBYTES);
++	gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
++	v2printk("Singlestep stopped at IP: %lx\n",
++		   instruction_pointer(&kgdbts_regs));
++	if (instruction_pointer(&kgdbts_regs) == addr) {
++		eprintk("kgdbts: SingleStep failed at %lx\n",
++			   instruction_pointer(&kgdbts_regs));
++		return 1;
++	}
++
++	return 0;
++}
++
++static void write_regs(char *arg)
++{
++	memset(scratch_buf, 0, sizeof(scratch_buf));
++	scratch_buf[0] = 'G';
++	pt_regs_to_gdb_regs(kgdbts_gdb_regs, &kgdbts_regs);
++	kgdb_mem2hex((char *)kgdbts_gdb_regs, &scratch_buf[1], NUMREGBYTES);
++	fill_get_buf(scratch_buf);
++}
++
++static void skip_back_repeat_test(char *arg)
++{
++	int go_back = simple_strtol(arg, NULL, 10);
++
++	repeat_test--;
++	if (repeat_test <= 0)
++		ts.idx++;
++	else
++		ts.idx -= go_back;
++	fill_get_buf(ts.tst[ts.idx].get);
++}
++
++static int got_break(char *put_str, char *arg)
++{
++	test_complete = 1;
++	if (!strncmp(put_str+1, arg, 2)) {
++		if (!strncmp(arg, "T0", 2))
++			test_complete = 2;
++		return 0;
++	}
++	return 1;
++}
++
++static void emul_sstep_get(char *arg)
++{
++	if (!arch_needs_sstep_emulation) {
++		fill_get_buf(arg);
++		return;
++	}
++	switch (sstep_state) {
++	case 0:
++		v2printk("Emulate single step\n");
++		/* Start by looking at the current PC */
++		fill_get_buf("g");
++		break;
++	case 1:
++		/* set breakpoint */
++		break_helper("Z0", 0, sstep_addr);
++		break;
++	case 2:
++		/* Continue */
++		fill_get_buf("c");
++		break;
++	case 3:
++		/* Clear breakpoint */
++		break_helper("z0", 0, sstep_addr);
++		break;
++	default:
++		eprintk("kgdbts: ERROR failed sstep get emulation\n");
++	}
++	sstep_state++;
++}
++
++static int emul_sstep_put(char *put_str, char *arg)
++{
++	if (!arch_needs_sstep_emulation) {
++		if (!strncmp(put_str+1, arg, 2))
++			return 0;
++		return 1;
++	}
++	switch (sstep_state) {
++	case 1:
++		/* validate the "g" packet to get the IP */
++		kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
++			 NUMREGBYTES);
++		gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
++		v2printk("Stopped at IP: %lx\n",
++			 instruction_pointer(&kgdbts_regs));
++		/* Want to stop at IP + break instruction size by default */
++		sstep_addr = instruction_pointer(&kgdbts_regs) +
++			BREAK_INSTR_SIZE;
++		break;
++	case 2:
++		if (strncmp(put_str, "$OK", 3)) {
++			eprintk("kgdbts: failed sstep break set\n");
++			return 1;
++		}
++		break;
++	case 3:
++		if (strncmp(put_str, "$T0", 3)) {
++			eprintk("kgdbts: failed continue sstep\n");
++			return 1;
++		}
++		break;
++	case 4:
++		if (strncmp(put_str, "$OK", 3)) {
++			eprintk("kgdbts: failed sstep break unset\n");
++			return 1;
++		}
++		/* Single step is complete so continue on! */
++		sstep_state = 0;
++		return 0;
++	default:
++		eprintk("kgdbts: ERROR failed sstep put emulation\n");
++	}
++
++	/* Continue on the same test line until emulation is complete */
++	ts.idx--;
++	return 0;
++}
++
++static int final_ack_set(char *put_str, char *arg)
++{
++	if (strncmp(put_str+1, arg, 2))
++		return 1;
++	final_ack = 1;
++	return 0;
++}
++/*
++ * Test to plant a breakpoint and detach, which should clear out the
++ * breakpoint and restore the original instruction.
++ */
++static struct test_struct plant_and_detach_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
++	{ "D", "OK" }, /* Detach */
++	{ "", "" },
++};
++
++/*
++ * Simple test to write in a software breakpoint, check for the
++ * correct stop location and detach.
++ */
++static struct test_struct sw_breakpoint_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
++	{ "c", "T0*", }, /* Continue */
++	{ "g", "kgdbts_break_test", 0, check_and_rewind_pc },
++	{ "write", "OK", write_regs },
++	{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
++	{ "D", "OK" }, /* Detach */
++	{ "D", "OK", 0,  got_break }, /* If the test worked we made it here */
++	{ "", "" },
++};
++
++/*
++ * Test a known bad memory read location to test the fault handler and
++ * read bytes 1-8 at the bad address
++ */
++static struct test_struct bad_read_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "m0,1", "E*" }, /* read 1 byte at address 1 */
++	{ "m0,2", "E*" }, /* read 1 byte at address 2 */
++	{ "m0,3", "E*" }, /* read 1 byte at address 3 */
++	{ "m0,4", "E*" }, /* read 1 byte at address 4 */
++	{ "m0,5", "E*" }, /* read 1 byte at address 5 */
++	{ "m0,6", "E*" }, /* read 1 byte at address 6 */
++	{ "m0,7", "E*" }, /* read 1 byte at address 7 */
++	{ "m0,8", "E*" }, /* read 1 byte at address 8 */
++	{ "D", "OK" }, /* Detach which removes all breakpoints and continues */
++	{ "", "" },
++};
++
++/*
++ * Test for hitting a breakpoint, remove it, single step, plant it
++ * again and detach.
++ */
++static struct test_struct singlestep_break_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
++	{ "c", "T0*", }, /* Continue */
++	{ "g", "kgdbts_break_test", 0, check_and_rewind_pc },
++	{ "write", "OK", write_regs }, /* Write registers */
++	{ "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
++	{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
++	{ "g", "kgdbts_break_test", 0, check_single_step },
++	{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
++	{ "c", "T0*", }, /* Continue */
++	{ "g", "kgdbts_break_test", 0, check_and_rewind_pc },
++	{ "write", "OK", write_regs }, /* Write registers */
++	{ "D", "OK" }, /* Remove all breakpoints and continues */
++	{ "", "" },
++};
++
++/*
++ * Test for hitting a breakpoint at do_fork for what ever the number
++ * of iterations required by the variable repeat_test.
++ */
++static struct test_struct do_fork_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
++	{ "c", "T0*", }, /* Continue */
++	{ "g", "do_fork", 0, check_and_rewind_pc }, /* check location */
++	{ "write", "OK", write_regs }, /* Write registers */
++	{ "do_fork", "OK", sw_rem_break }, /*remove breakpoint */
++	{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
++	{ "g", "do_fork", 0, check_single_step },
++	{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
++	{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
++	{ "D", "OK", 0, final_ack_set }, /* detach and unregister I/O */
++	{ "", "" },
++};
++
++/* Test for hitting a breakpoint at sys_open for what ever the number
++ * of iterations required by the variable repeat_test.
++ */
++static struct test_struct sys_open_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
++	{ "c", "T0*", }, /* Continue */
++	{ "g", "sys_open", 0, check_and_rewind_pc }, /* check location */
++	{ "write", "OK", write_regs }, /* Write registers */
++	{ "sys_open", "OK", sw_rem_break }, /*remove breakpoint */
++	{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
++	{ "g", "sys_open", 0, check_single_step },
++	{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
++	{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
++	{ "D", "OK", 0, final_ack_set }, /* detach and unregister I/O */
++	{ "", "" },
++};
++
++/*
++ * Test for hitting a simple hw breakpoint
++ */
++static struct test_struct hw_breakpoint_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "kgdbts_break_test", "OK", hw_break, }, /* set hw breakpoint */
++	{ "c", "T0*", }, /* Continue */
++	{ "g", "kgdbts_break_test", 0, check_and_rewind_pc },
++	{ "write", "OK", write_regs },
++	{ "kgdbts_break_test", "OK", hw_rem_break }, /*remove breakpoint */
++	{ "D", "OK" }, /* Detach */
++	{ "D", "OK", 0,  got_break }, /* If the test worked we made it here */
++	{ "", "" },
++};
++
++/*
++ * Test for hitting a hw write breakpoint
++ */
++static struct test_struct hw_write_break_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "hw_break_val", "OK", hw_write_break, }, /* set hw breakpoint */
++	{ "c", "T0*", 0, got_break }, /* Continue */
++	{ "g", "silent", 0, check_and_rewind_pc },
++	{ "write", "OK", write_regs },
++	{ "hw_break_val", "OK", hw_rem_write_break }, /*remove breakpoint */
++	{ "D", "OK" }, /* Detach */
++	{ "D", "OK", 0,  got_break }, /* If the test worked we made it here */
++	{ "", "" },
++};
++
++/*
++ * Test for hitting a hw access breakpoint
++ */
++static struct test_struct hw_access_break_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "hw_break_val", "OK", hw_access_break, }, /* set hw breakpoint */
++	{ "c", "T0*", 0, got_break }, /* Continue */
++	{ "g", "silent", 0, check_and_rewind_pc },
++	{ "write", "OK", write_regs },
++	{ "hw_break_val", "OK", hw_rem_access_break }, /*remove breakpoint */
++	{ "D", "OK" }, /* Detach */
++	{ "D", "OK", 0,  got_break }, /* If the test worked we made it here */
++	{ "", "" },
++};
++
++/*
++ * Test for hitting a hw access breakpoint
++ */
++static struct test_struct nmi_sleep_test[] = {
++	{ "?", "S0*" }, /* Clear break points */
++	{ "c", "T0*", 0, got_break }, /* Continue */
++	{ "D", "OK" }, /* Detach */
++	{ "D", "OK", 0,  got_break }, /* If the test worked we made it here */
++	{ "", "" },
++};
++
++static void fill_get_buf(char *buf)
++{
++	unsigned char checksum = 0;
++	int count = 0;
++	char ch;
++
++	strcpy(get_buf, "$");
++	strcat(get_buf, buf);
++	while ((ch = buf[count])) {
++		checksum += ch;
++		count++;
++	}
++	strcat(get_buf, "#");
++	get_buf[count + 2] = hexchars[checksum >> 4];
++	get_buf[count + 3] = hexchars[checksum & 0xf];
++	get_buf[count + 4] = '\0';
++	v2printk("get%i: %s\n", ts.idx, get_buf);
++}
++
++static int validate_simple_test(char *put_str)
++{
++	char *chk_str;
++
++	if (ts.tst[ts.idx].put_handler)
++		return ts.tst[ts.idx].put_handler(put_str,
++			ts.tst[ts.idx].put);
++
++	chk_str = ts.tst[ts.idx].put;
++	if (*put_str == '$')
++		put_str++;
++
++	while (*chk_str != '\0' && *put_str != '\0') {
++		/* If someone does a * to match the rest of the string, allow
++		 * it, or stop if the recieved string is complete.
++		 */
++		if (*put_str == '#' || *chk_str == '*')
++			return 0;
++		if (*put_str != *chk_str)
++			return 1;
++
++		chk_str++;
++		put_str++;
++	}
++	if (*chk_str == '\0' && (*put_str == '\0' || *put_str == '#'))
++		return 0;
++
++	return 1;
++}
++
++static int run_simple_test(int is_get_char, int chr)
++{
++	int ret = 0;
++	if (is_get_char) {
++		/* Send an ACK on the get if a prior put completed and set the
++		 * send ack variable
++		 */
++		if (send_ack) {
++			send_ack = 0;
++			return '+';
++		}
++		/* On the first get char, fill the transmit buffer and then
++		 * take from the get_string.
++		 */
++		if (get_buf_cnt == 0) {
++			if (ts.tst[ts.idx].get_handler)
++				ts.tst[ts.idx].get_handler(ts.tst[ts.idx].get);
++			else
++				fill_get_buf(ts.tst[ts.idx].get);
++		}
++
++		if (get_buf[get_buf_cnt] == '\0') {
++			eprintk("kgdbts: ERROR GET: EOB on '%s' at %i\n",
++			   ts.name, ts.idx);
++			get_buf_cnt = 0;
++			fill_get_buf("D");
++		}
++		ret = get_buf[get_buf_cnt];
++		get_buf_cnt++;
++		return ret;
++	}
++
++	/* This callback is a put char which is when kgdb sends data to
++	 * this I/O module.
++	 */
++	if (ts.tst[ts.idx].get[0] == '\0' &&
++		ts.tst[ts.idx].put[0] == '\0') {
++		eprintk("kgdbts: ERROR: beyond end of test on"
++			   " '%s' line %i\n", ts.name, ts.idx);
++		return 0;
++	}
++
++	if (put_buf_cnt >= BUFMAX) {
++		eprintk("kgdbts: ERROR: put buffer overflow on"
++			   " '%s' line %i\n", ts.name, ts.idx);
++		put_buf_cnt = 0;
++		return 0;
++	}
++	/* Ignore everything until the first valid packet start '$' */
++	if (put_buf_cnt == 0 && chr != '$')
++		return 0;
++
++	put_buf[put_buf_cnt] = chr;
++	put_buf_cnt++;
++
++	/* End of packet == #XX so look for the '#' */
++	if (put_buf_cnt > 3 && put_buf[put_buf_cnt - 3] == '#') {
++		put_buf[put_buf_cnt] = '\0';
++		v2printk("put%i: %s\n", ts.idx, put_buf);
++		/* Trigger check here */
++		if (ts.validate_put && ts.validate_put(put_buf)) {
++			eprintk("kgdbts: ERROR PUT: end of test "
++			   "buffer on '%s' line %i expected %s got %s\n",
++			   ts.name, ts.idx, ts.tst[ts.idx].put, put_buf);
++		}
++		ts.idx++;
++		put_buf_cnt = 0;
++		get_buf_cnt = 0;
++		send_ack = 1;
++	}
++	return 0;
++}
++
++static void init_simple_test(void)
++{
++	memset(&ts, 0, sizeof(ts));
++	ts.run_test = run_simple_test;
++	ts.validate_put = validate_simple_test;
++}
++
++static void run_plant_and_detach_test(int is_early)
++{
++	char before[BREAK_INSTR_SIZE];
++	char after[BREAK_INSTR_SIZE];
++
++	probe_kernel_read(before, (char *)kgdbts_break_test,
++	  BREAK_INSTR_SIZE);
++	init_simple_test();
++	ts.tst = plant_and_detach_test;
++	ts.name = "plant_and_detach_test";
++	/* Activate test with initial breakpoint */
++	if (!is_early)
++		kgdb_breakpoint();
++	probe_kernel_read(after, (char *)kgdbts_break_test,
++	  BREAK_INSTR_SIZE);
++	if (memcmp(before, after, BREAK_INSTR_SIZE)) {
++		printk(KERN_CRIT "kgdbts: ERROR kgdb corrupted memory\n");
++		panic("kgdb memory corruption");
++	}
++
++	/* complete the detach test */
++	if (!is_early)
++		kgdbts_break_test();
++}
++
++static void run_breakpoint_test(int is_hw_breakpoint)
++{
++	test_complete = 0;
++	init_simple_test();
++	if (is_hw_breakpoint) {
++		ts.tst = hw_breakpoint_test;
++		ts.name = "hw_breakpoint_test";
++	} else {
++		ts.tst = sw_breakpoint_test;
++		ts.name = "sw_breakpoint_test";
++	}
++	/* Activate test with initial breakpoint */
++	kgdb_breakpoint();
++	/* run code with the break point in it */
++	kgdbts_break_test();
++	kgdb_breakpoint();
++
++	if (test_complete)
++		return;
++
++	eprintk("kgdbts: ERROR %s test failed\n", ts.name);
++}
++
++static void run_hw_break_test(int is_write_test)
++{
++	test_complete = 0;
++	init_simple_test();
++	if (is_write_test) {
++		ts.tst = hw_write_break_test;
++		ts.name = "hw_write_break_test";
++	} else {
++		ts.tst = hw_access_break_test;
++		ts.name = "hw_access_break_test";
++	}
++	/* Activate test with initial breakpoint */
++	kgdb_breakpoint();
++	hw_break_val_access();
++	if (is_write_test) {
++		if (test_complete == 2)
++			eprintk("kgdbts: ERROR %s broke on access\n",
++				ts.name);
++		hw_break_val_write();
++	}
++	kgdb_breakpoint();
++
++	if (test_complete == 1)
++		return;
++
++	eprintk("kgdbts: ERROR %s test failed\n", ts.name);
++}
++
++static void run_nmi_sleep_test(int nmi_sleep)
++{
++	unsigned long flags;
++
++	init_simple_test();
++	ts.tst = nmi_sleep_test;
++	ts.name = "nmi_sleep_test";
++	/* Activate test with initial breakpoint */
++	kgdb_breakpoint();
++	local_irq_save(flags);
++	mdelay(nmi_sleep*1000);
++	touch_nmi_watchdog();
++	local_irq_restore(flags);
++	if (test_complete != 2)
++		eprintk("kgdbts: ERROR nmi_test did not hit nmi\n");
++	kgdb_breakpoint();
++	if (test_complete == 1)
++		return;
++
++	eprintk("kgdbts: ERROR %s test failed\n", ts.name);
++}
++
++static void run_bad_read_test(void)
++{
++	init_simple_test();
++	ts.tst = bad_read_test;
++	ts.name = "bad_read_test";
++	/* Activate test with initial breakpoint */
++	kgdb_breakpoint();
++}
++
++static void run_do_fork_test(void)
++{
++	init_simple_test();
++	ts.tst = do_fork_test;
++	ts.name = "do_fork_test";
++	/* Activate test with initial breakpoint */
++	kgdb_breakpoint();
++}
++
++static void run_sys_open_test(void)
++{
++	init_simple_test();
++	ts.tst = sys_open_test;
++	ts.name = "sys_open_test";
++	/* Activate test with initial breakpoint */
++	kgdb_breakpoint();
++}
++
++static void run_singlestep_break_test(void)
++{
++	init_simple_test();
++	ts.tst = singlestep_break_test;
++	ts.name = "singlestep_breakpoint_test";
++	/* Activate test with initial breakpoint */
++	kgdb_breakpoint();
++	kgdbts_break_test();
++	kgdbts_break_test();
++}
++
++static void kgdbts_run_tests(void)
++{
++	char *ptr;
++	int fork_test = 0;
++	int sys_open_test = 0;
++	int nmi_sleep = 0;
++
++	ptr = strstr(config, "F");
++	if (ptr)
++		fork_test = simple_strtol(ptr+1, NULL, 10);
++	ptr = strstr(config, "S");
++	if (ptr)
++		sys_open_test = simple_strtol(ptr+1, NULL, 10);
++	ptr = strstr(config, "N");
++	if (ptr)
++		nmi_sleep = simple_strtol(ptr+1, NULL, 10);
++
++	/* required internal KGDB tests */
++	v1printk("kgdbts:RUN plant and detach test\n");
++	run_plant_and_detach_test(0);
++	v1printk("kgdbts:RUN sw breakpoint test\n");
++	run_breakpoint_test(0);
++	v1printk("kgdbts:RUN bad memory access test\n");
++	run_bad_read_test();
++	v1printk("kgdbts:RUN singlestep breakpoint test\n");
++	run_singlestep_break_test();
++
++	/* ===Optional tests=== */
++
++	/* All HW break point tests */
++	if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
++		v1printk("kgdbts:RUN hw breakpoint test\n");
++		run_breakpoint_test(1);
++		v1printk("kgdbts:RUN hw write breakpoint test\n");
++		run_hw_break_test(1);
++		v1printk("kgdbts:RUN access write breakpoint test\n");
++		run_hw_break_test(0);
++	}
++
++	if (nmi_sleep) {
++		v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep);
++		run_nmi_sleep_test(nmi_sleep);
++	}
++
++	/* If the do_fork test is run it will be the last test that is
++	 * executed because a kernel thread will be spawned at the very
++	 * end to unregister the debug hooks.
++	 */
++	if (fork_test) {
++		repeat_test = fork_test;
++		printk(KERN_INFO "kgdbts:RUN do_fork for %i breakpoints\n",
++			repeat_test);
++		kthread_run(kgdbts_unreg_thread, 0, "kgdbts_unreg");
++		run_do_fork_test();
++		return;
++	}
++
++	/* If the sys_open test is run it will be the last test that is
++	 * executed because a kernel thread will be spawned at the very
++	 * end to unregister the debug hooks.
++	 */
++	if (sys_open_test) {
++		repeat_test = sys_open_test;
++		printk(KERN_INFO "kgdbts:RUN sys_open for %i breakpoints\n",
++			repeat_test);
++		kthread_run(kgdbts_unreg_thread, 0, "kgdbts_unreg");
++		run_sys_open_test();
++		return;
++	}
++	/* Shutdown and unregister */
++	kgdb_unregister_io_module(&kgdbts_io_ops);
++	configured = 0;
++}
++
++static int kgdbts_option_setup(char *opt)
++{
++	if (strlen(opt) > MAX_CONFIG_LEN) {
++		printk(KERN_ERR "kgdbts: config string too long\n");
++		return -ENOSPC;
++	}
++	strcpy(config, opt);
++
++	verbose = 0;
++	if (strstr(config, "V1"))
++		verbose = 1;
++	if (strstr(config, "V2"))
++		verbose = 2;
++
++	return 0;
++}
++
++__setup("kgdbts=", kgdbts_option_setup);
++
++static int configure_kgdbts(void)
++{
++	int err = 0;
++
++	if (!strlen(config) || isspace(config[0]))
++		goto noconfig;
++	err = kgdbts_option_setup(config);
++	if (err)
++		goto noconfig;
++
++	final_ack = 0;
++	run_plant_and_detach_test(1);
++
++	err = kgdb_register_io_module(&kgdbts_io_ops);
++	if (err) {
++		configured = 0;
++		return err;
++	}
++	configured = 1;
++	kgdbts_run_tests();
++
++	return err;
++
++noconfig:
++	config[0] = 0;
++	configured = 0;
++
++	return err;
++}
++
++static int __init init_kgdbts(void)
++{
++	/* Already configured? */
++	if (configured == 1)
++		return 0;
++
++	return configure_kgdbts();
++}
++
++static void cleanup_kgdbts(void)
++{
++	if (configured == 1)
++		kgdb_unregister_io_module(&kgdbts_io_ops);
++}
++
++static int kgdbts_get_char(void)
++{
++	int val = 0;
++
++	if (ts.run_test)
++		val = ts.run_test(1, 0);
++
++	return val;
++}
++
++static void kgdbts_put_char(u8 chr)
++{
++	if (ts.run_test)
++		ts.run_test(0, chr);
++}
++
++static int param_set_kgdbts_var(const char *kmessage, struct kernel_param *kp)
++{
++	int len = strlen(kmessage);
++
++	if (len >= MAX_CONFIG_LEN) {
++		printk(KERN_ERR "kgdbts: config string too long\n");
++		return -ENOSPC;
++	}
++
++	/* Only copy in the string if the init function has not run yet */
++	if (configured < 0) {
++		strcpy(config, kmessage);
++		return 0;
++	}
++
++	if (kgdb_connected) {
++		printk(KERN_ERR
++	       "kgdbts: Cannot reconfigure while KGDB is connected.\n");
++
++		return -EBUSY;
++	}
++
++	strcpy(config, kmessage);
++	/* Chop out \n char as a result of echo */
++	if (config[len - 1] == '\n')
++		config[len - 1] = '\0';
++
++	if (configured == 1)
++		cleanup_kgdbts();
++
++	/* Go and configure with the new params. */
++	return configure_kgdbts();
++}
++
++static void kgdbts_pre_exp_handler(void)
++{
++	/* Increment the module count when the debugger is active */
++	if (!kgdb_connected)
++		try_module_get(THIS_MODULE);
++}
++
++static void kgdbts_post_exp_handler(void)
++{
++	/* decrement the module count when the debugger detaches */
++	if (!kgdb_connected)
++		module_put(THIS_MODULE);
++}
++
++static struct kgdb_io kgdbts_io_ops = {
++	.name			= "kgdbts",
++	.read_char		= kgdbts_get_char,
++	.write_char		= kgdbts_put_char,
++	.pre_exception		= kgdbts_pre_exp_handler,
++	.post_exception		= kgdbts_post_exp_handler,
++};
++
++module_init(init_kgdbts);
++module_exit(cleanup_kgdbts);
++module_param_call(kgdbts, param_set_kgdbts_var, param_get_string, &kps, 0644);
++MODULE_PARM_DESC(kgdbts, "<A|V1|V2>[F#|S#][N#]");
++MODULE_DESCRIPTION("KGDB Test Suite");
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Wind River Systems, Inc.");
++
+diff --git a/drivers/misc/sgi-xp/Makefile b/drivers/misc/sgi-xp/Makefile
+new file mode 100644
+index 0000000..b6e40a7
+--- /dev/null
++++ b/drivers/misc/sgi-xp/Makefile
+@@ -0,0 +1,11 @@
++#
++# Makefile for SGI's XP devices.
++#
++
++obj-$(CONFIG_SGI_XP)		+= xp.o
++xp-y				:= xp_main.o xp_nofault.o
++
++obj-$(CONFIG_SGI_XP)		+= xpc.o
++xpc-y				:= xpc_main.o xpc_channel.o xpc_partition.o
++
++obj-$(CONFIG_SGI_XP)		+= xpnet.o
+diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h
+new file mode 100644
+index 0000000..5515234
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xp.h
+@@ -0,0 +1,463 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2004-2008 Silicon Graphics, Inc. All rights reserved.
++ */
++
++/*
++ * External Cross Partition (XP) structures and defines.
++ */
++
++#ifndef _DRIVERS_MISC_SGIXP_XP_H
++#define _DRIVERS_MISC_SGIXP_XP_H
++
++#include <linux/cache.h>
++#include <linux/hardirq.h>
++#include <linux/mutex.h>
++#include <asm/sn/types.h>
++#include <asm/sn/bte.h>
++
++#ifdef USE_DBUG_ON
++#define DBUG_ON(condition)	BUG_ON(condition)
++#else
++#define DBUG_ON(condition)
++#endif
++
++/*
++ * Define the maximum number of logically defined partitions the system
++ * can support. It is constrained by the maximum number of hardware
++ * partitionable regions. The term 'region' in this context refers to the
++ * minimum number of nodes that can comprise an access protection grouping.
++ * The access protection is in regards to memory, IPI and IOI.
++ *
++ * The maximum number of hardware partitionable regions is equal to the
++ * maximum number of nodes in the entire system divided by the minimum number
++ * of nodes that comprise an access protection grouping.
++ */
++#define XP_MAX_PARTITIONS	64
++
++/*
++ * Define the number of u64s required to represent all the C-brick nasids
++ * as a bitmap.  The cross-partition kernel modules deal only with
++ * C-brick nasids, thus the need for bitmaps which don't account for
++ * odd-numbered (non C-brick) nasids.
++ */
++#define XP_MAX_PHYSNODE_ID	(MAX_NUMALINK_NODES / 2)
++#define XP_NASID_MASK_BYTES	((XP_MAX_PHYSNODE_ID + 7) / 8)
++#define XP_NASID_MASK_WORDS	((XP_MAX_PHYSNODE_ID + 63) / 64)
++
++/*
++ * Wrapper for bte_copy() that should it return a failure status will retry
++ * the bte_copy() once in the hope that the failure was due to a temporary
++ * aberration (i.e., the link going down temporarily).
++ *
++ * 	src - physical address of the source of the transfer.
++ *	vdst - virtual address of the destination of the transfer.
++ *	len - number of bytes to transfer from source to destination.
++ *	mode - see bte_copy() for definition.
++ *	notification - see bte_copy() for definition.
++ *
++ * Note: xp_bte_copy() should never be called while holding a spinlock.
++ */
++static inline bte_result_t
++xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification)
++{
++	bte_result_t ret;
++	u64 pdst = ia64_tpa(vdst);
++
++	/*
++	 * Ensure that the physically mapped memory is contiguous.
++	 *
++	 * We do this by ensuring that the memory is from region 7 only.
++	 * If the need should arise to use memory from one of the other
++	 * regions, then modify the BUG_ON() statement to ensure that the
++	 * memory from that region is always physically contiguous.
++	 */
++	BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL);
++
++	ret = bte_copy(src, pdst, len, mode, notification);
++	if ((ret != BTE_SUCCESS) && BTE_ERROR_RETRY(ret)) {
++		if (!in_interrupt())
++			cond_resched();
++
++		ret = bte_copy(src, pdst, len, mode, notification);
++	}
++
++	return ret;
++}
++
++/*
++ * XPC establishes channel connections between the local partition and any
++ * other partition that is currently up. Over these channels, kernel-level
++ * `users' can communicate with their counterparts on the other partitions.
++ *
++ * The maxinum number of channels is limited to eight. For performance reasons,
++ * the internal cross partition structures require sixteen bytes per channel,
++ * and eight allows all of this interface-shared info to fit in one cache line.
++ *
++ * XPC_NCHANNELS reflects the total number of channels currently defined.
++ * If the need for additional channels arises, one can simply increase
++ * XPC_NCHANNELS accordingly. If the day should come where that number
++ * exceeds the MAXIMUM number of channels allowed (eight), then one will need
++ * to make changes to the XPC code to allow for this.
++ */
++#define XPC_MEM_CHANNEL		0	/* memory channel number */
++#define	XPC_NET_CHANNEL		1	/* network channel number */
++
++#define	XPC_NCHANNELS		2	/* #of defined channels */
++#define XPC_MAX_NCHANNELS	8	/* max #of channels allowed */
++
++#if XPC_NCHANNELS > XPC_MAX_NCHANNELS
++#error	XPC_NCHANNELS exceeds MAXIMUM allowed.
++#endif
++
++/*
++ * The format of an XPC message is as follows:
++ *
++ *      +-------+--------------------------------+
++ *      | flags |////////////////////////////////|
++ *      +-------+--------------------------------+
++ *      |             message #                  |
++ *      +----------------------------------------+
++ *      |     payload (user-defined message)     |
++ *      |                                        |
++ *         		:
++ *      |                                        |
++ *      +----------------------------------------+
++ *
++ * The size of the payload is defined by the user via xpc_connect(). A user-
++ * defined message resides in the payload area.
++ *
++ * The user should have no dealings with the message header, but only the
++ * message's payload. When a message entry is allocated (via xpc_allocate())
++ * a pointer to the payload area is returned and not the actual beginning of
++ * the XPC message. The user then constructs a message in the payload area
++ * and passes that pointer as an argument on xpc_send() or xpc_send_notify().
++ *
++ * The size of a message entry (within a message queue) must be a cacheline
++ * sized multiple in order to facilitate the BTE transfer of messages from one
++ * message queue to another. A macro, XPC_MSG_SIZE(), is provided for the user
++ * that wants to fit as many msg entries as possible in a given memory size
++ * (e.g. a memory page).
++ */
++struct xpc_msg {
++	u8 flags;		/* FOR XPC INTERNAL USE ONLY */
++	u8 reserved[7];		/* FOR XPC INTERNAL USE ONLY */
++	s64 number;		/* FOR XPC INTERNAL USE ONLY */
++
++	u64 payload;		/* user defined portion of message */
++};
++
++#define XPC_MSG_PAYLOAD_OFFSET	(u64) (&((struct xpc_msg *)0)->payload)
++#define XPC_MSG_SIZE(_payload_size) \
++		L1_CACHE_ALIGN(XPC_MSG_PAYLOAD_OFFSET + (_payload_size))
++
++/*
++ * Define the return values and values passed to user's callout functions.
++ * (It is important to add new value codes at the end just preceding
++ * xpcUnknownReason, which must have the highest numerical value.)
++ */
++enum xpc_retval {
++	xpcSuccess = 0,
++
++	xpcNotConnected,	/*  1: channel is not connected */
++	xpcConnected,		/*  2: channel connected (opened) */
++	xpcRETIRED1,		/*  3: (formerly xpcDisconnected) */
++
++	xpcMsgReceived,		/*  4: message received */
++	xpcMsgDelivered,	/*  5: message delivered and acknowledged */
++
++	xpcRETIRED2,		/*  6: (formerly xpcTransferFailed) */
++
++	xpcNoWait,		/*  7: operation would require wait */
++	xpcRetry,		/*  8: retry operation */
++	xpcTimeout,		/*  9: timeout in xpc_allocate_msg_wait() */
++	xpcInterrupted,		/* 10: interrupted wait */
++
++	xpcUnequalMsgSizes,	/* 11: message size disparity between sides */
++	xpcInvalidAddress,	/* 12: invalid address */
++
++	xpcNoMemory,		/* 13: no memory available for XPC structures */
++	xpcLackOfResources,	/* 14: insufficient resources for operation */
++	xpcUnregistered,	/* 15: channel is not registered */
++	xpcAlreadyRegistered,	/* 16: channel is already registered */
++
++	xpcPartitionDown,	/* 17: remote partition is down */
++	xpcNotLoaded,		/* 18: XPC module is not loaded */
++	xpcUnloading,		/* 19: this side is unloading XPC module */
++
++	xpcBadMagic,		/* 20: XPC MAGIC string not found */
++
++	xpcReactivating,	/* 21: remote partition was reactivated */
++
++	xpcUnregistering,	/* 22: this side is unregistering channel */
++	xpcOtherUnregistering,	/* 23: other side is unregistering channel */
++
++	xpcCloneKThread,	/* 24: cloning kernel thread */
++	xpcCloneKThreadFailed,	/* 25: cloning kernel thread failed */
++
++	xpcNoHeartbeat,		/* 26: remote partition has no heartbeat */
++
++	xpcPioReadError,	/* 27: PIO read error */
++	xpcPhysAddrRegFailed,	/* 28: registration of phys addr range failed */
++
++	xpcBteDirectoryError,	/* 29: maps to BTEFAIL_DIR */
++	xpcBtePoisonError,	/* 30: maps to BTEFAIL_POISON */
++	xpcBteWriteError,	/* 31: maps to BTEFAIL_WERR */
++	xpcBteAccessError,	/* 32: maps to BTEFAIL_ACCESS */
++	xpcBtePWriteError,	/* 33: maps to BTEFAIL_PWERR */
++	xpcBtePReadError,	/* 34: maps to BTEFAIL_PRERR */
++	xpcBteTimeOutError,	/* 35: maps to BTEFAIL_TOUT */
++	xpcBteXtalkError,	/* 36: maps to BTEFAIL_XTERR */
++	xpcBteNotAvailable,	/* 37: maps to BTEFAIL_NOTAVAIL */
++	xpcBteUnmappedError,	/* 38: unmapped BTEFAIL_ error */
++
++	xpcBadVersion,		/* 39: bad version number */
++	xpcVarsNotSet,		/* 40: the XPC variables are not set up */
++	xpcNoRsvdPageAddr,	/* 41: unable to get rsvd page's phys addr */
++	xpcInvalidPartid,	/* 42: invalid partition ID */
++	xpcLocalPartid,		/* 43: local partition ID */
++
++	xpcOtherGoingDown,	/* 44: other side going down, reason unknown */
++	xpcSystemGoingDown,	/* 45: system is going down, reason unknown */
++	xpcSystemHalt,		/* 46: system is being halted */
++	xpcSystemReboot,	/* 47: system is being rebooted */
++	xpcSystemPoweroff,	/* 48: system is being powered off */
++
++	xpcDisconnecting,	/* 49: channel disconnecting (closing) */
++
++	xpcOpenCloseError,	/* 50: channel open/close protocol error */
++
++	xpcDisconnected,	/* 51: channel disconnected (closed) */
++
++	xpcBteSh2Start,		/* 52: BTE CRB timeout */
++
++				/* 53: 0x1 BTE Error Response Short */
++	xpcBteSh2RspShort = xpcBteSh2Start + BTEFAIL_SH2_RESP_SHORT,
++
++				/* 54: 0x2 BTE Error Response Long */
++	xpcBteSh2RspLong = xpcBteSh2Start + BTEFAIL_SH2_RESP_LONG,
++
++				/* 56: 0x4 BTE Error Response DSB */
++	xpcBteSh2RspDSB = xpcBteSh2Start + BTEFAIL_SH2_RESP_DSP,
++
++				/* 60: 0x8 BTE Error Response Access */
++	xpcBteSh2RspAccess = xpcBteSh2Start + BTEFAIL_SH2_RESP_ACCESS,
++
++				/* 68: 0x10 BTE Error CRB timeout */
++	xpcBteSh2CRBTO = xpcBteSh2Start + BTEFAIL_SH2_CRB_TO,
++
++				/* 84: 0x20 BTE Error NACK limit */
++	xpcBteSh2NACKLimit = xpcBteSh2Start + BTEFAIL_SH2_NACK_LIMIT,
++
++				/* 115: BTE end */
++	xpcBteSh2End = xpcBteSh2Start + BTEFAIL_SH2_ALL,
++
++	xpcUnknownReason	/* 116: unknown reason - must be last in enum */
++};
++
++/*
++ * Define the callout function types used by XPC to update the user on
++ * connection activity and state changes (via the user function registered by
++ * xpc_connect()) and to notify them of messages received and delivered (via
++ * the user function registered by xpc_send_notify()).
++ *
++ * The two function types are xpc_channel_func and xpc_notify_func and
++ * both share the following arguments, with the exception of "data", which
++ * only xpc_channel_func has.
++ *
++ * Arguments:
++ *
++ *	reason - reason code. (See following table.)
++ *	partid - partition ID associated with condition.
++ *	ch_number - channel # associated with condition.
++ *	data - pointer to optional data. (See following table.)
++ *	key - pointer to optional user-defined value provided as the "key"
++ *	      argument to xpc_connect() or xpc_send_notify().
++ *
++ * In the following table the "Optional Data" column applies to callouts made
++ * to functions registered by xpc_connect(). A "NA" in that column indicates
++ * that this reason code can be passed to functions registered by
++ * xpc_send_notify() (i.e. they don't have data arguments).
++ *
++ * Also, the first three reason codes in the following table indicate
++ * success, whereas the others indicate failure. When a failure reason code
++ * is received, one can assume that the channel is not connected.
++ *
++ *
++ * Reason Code          | Cause                          | Optional Data
++ * =====================+================================+=====================
++ * xpcConnected         | connection has been established| max #of entries
++ *                      | to the specified partition on  | allowed in message
++ *                      | the specified channel          | queue
++ * ---------------------+--------------------------------+---------------------
++ * xpcMsgReceived       | an XPC message arrived from    | address of payload
++ *                      | the specified partition on the |
++ *                      | specified channel              | [the user must call
++ *                      |                                | xpc_received() when
++ *                      |                                | finished with the
++ *                      |                                | payload]
++ * ---------------------+--------------------------------+---------------------
++ * xpcMsgDelivered      | notification that the message  | NA
++ *                      | was delivered to the intended  |
++ *                      | recipient and that they have   |
++ *                      | acknowledged its receipt by    |
++ *                      | calling xpc_received()         |
++ * =====================+================================+=====================
++ * xpcUnequalMsgSizes   | can't connect to the specified | NULL
++ *                      | partition on the specified     |
++ *                      | channel because of mismatched  |
++ *                      | message sizes                  |
++ * ---------------------+--------------------------------+---------------------
++ * xpcNoMemory          | insufficient memory avaiable   | NULL
++ *                      | to allocate message queue      |
++ * ---------------------+--------------------------------+---------------------
++ * xpcLackOfResources   | lack of resources to create    | NULL
++ *                      | the necessary kthreads to      |
++ *                      | support the channel            |
++ * ---------------------+--------------------------------+---------------------
++ * xpcUnregistering     | this side's user has           | NULL or NA
++ *                      | unregistered by calling        |
++ *                      | xpc_disconnect()               |
++ * ---------------------+--------------------------------+---------------------
++ * xpcOtherUnregistering| the other side's user has      | NULL or NA
++ *                      | unregistered by calling        |
++ *                      | xpc_disconnect()               |
++ * ---------------------+--------------------------------+---------------------
++ * xpcNoHeartbeat       | the other side's XPC is no     | NULL or NA
++ *                      | longer heartbeating            |
++ *                      |                                |
++ * ---------------------+--------------------------------+---------------------
++ * xpcUnloading         | this side's XPC module is      | NULL or NA
++ *                      | being unloaded                 |
++ *                      |                                |
++ * ---------------------+--------------------------------+---------------------
++ * xpcOtherUnloading    | the other side's XPC module is | NULL or NA
++ *                      | is being unloaded              |
++ *                      |                                |
++ * ---------------------+--------------------------------+---------------------
++ * xpcPioReadError      | xp_nofault_PIOR() returned an  | NULL or NA
++ *                      | error while sending an IPI     |
++ *                      |                                |
++ * ---------------------+--------------------------------+---------------------
++ * xpcInvalidAddress    | the address either received or | NULL or NA
++ *                      | sent by the specified partition|
++ *                      | is invalid                     |
++ * ---------------------+--------------------------------+---------------------
++ * xpcBteNotAvailable   | attempt to pull data from the  | NULL or NA
++ * xpcBtePoisonError    | specified partition over the   |
++ * xpcBteWriteError     | specified channel via a        |
++ * xpcBteAccessError    | bte_copy() failed              |
++ * xpcBteTimeOutError   |                                |
++ * xpcBteXtalkError     |                                |
++ * xpcBteDirectoryError |                                |
++ * xpcBteGenericError   |                                |
++ * xpcBteUnmappedError  |                                |
++ * ---------------------+--------------------------------+---------------------
++ * xpcUnknownReason     | the specified channel to the   | NULL or NA
++ *                      | specified partition was        |
++ *                      | unavailable for unknown reasons|
++ * =====================+================================+=====================
++ */
++
++typedef void (*xpc_channel_func) (enum xpc_retval reason, partid_t partid,
++				  int ch_number, void *data, void *key);
++
++typedef void (*xpc_notify_func) (enum xpc_retval reason, partid_t partid,
++				 int ch_number, void *key);
++
++/*
++ * The following is a registration entry. There is a global array of these,
++ * one per channel. It is used to record the connection registration made
++ * by the users of XPC. As long as a registration entry exists, for any
++ * partition that comes up, XPC will attempt to establish a connection on
++ * that channel. Notification that a connection has been made will occur via
++ * the xpc_channel_func function.
++ *
++ * The 'func' field points to the function to call when aynchronous
++ * notification is required for such events as: a connection established/lost,
++ * or an incoming message received, or an error condition encountered. A
++ * non-NULL 'func' field indicates that there is an active registration for
++ * the channel.
++ */
++struct xpc_registration {
++	struct mutex mutex;
++	xpc_channel_func func;	/* function to call */
++	void *key;		/* pointer to user's key */
++	u16 nentries;		/* #of msg entries in local msg queue */
++	u16 msg_size;		/* message queue's message size */
++	u32 assigned_limit;	/* limit on #of assigned kthreads */
++	u32 idle_limit;		/* limit on #of idle kthreads */
++} ____cacheline_aligned;
++
++#define XPC_CHANNEL_REGISTERED(_c)	(xpc_registrations[_c].func != NULL)
++
++/* the following are valid xpc_allocate() flags */
++#define XPC_WAIT	0	/* wait flag */
++#define XPC_NOWAIT	1	/* no wait flag */
++
++struct xpc_interface {
++	void (*connect) (int);
++	void (*disconnect) (int);
++	enum xpc_retval (*allocate) (partid_t, int, u32, void **);
++	enum xpc_retval (*send) (partid_t, int, void *);
++	enum xpc_retval (*send_notify) (partid_t, int, void *,
++					xpc_notify_func, void *);
++	void (*received) (partid_t, int, void *);
++	enum xpc_retval (*partid_to_nasids) (partid_t, void *);
++};
++
++extern struct xpc_interface xpc_interface;
++
++extern void xpc_set_interface(void (*)(int),
++			      void (*)(int),
++			      enum xpc_retval (*)(partid_t, int, u32, void **),
++			      enum xpc_retval (*)(partid_t, int, void *),
++			      enum xpc_retval (*)(partid_t, int, void *,
++						  xpc_notify_func, void *),
++			      void (*)(partid_t, int, void *),
++			      enum xpc_retval (*)(partid_t, void *));
++extern void xpc_clear_interface(void);
++
++extern enum xpc_retval xpc_connect(int, xpc_channel_func, void *, u16,
++				   u16, u32, u32);
++extern void xpc_disconnect(int);
++
++static inline enum xpc_retval
++xpc_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
++{
++	return xpc_interface.allocate(partid, ch_number, flags, payload);
++}
++
++static inline enum xpc_retval
++xpc_send(partid_t partid, int ch_number, void *payload)
++{
++	return xpc_interface.send(partid, ch_number, payload);
++}
++
++static inline enum xpc_retval
++xpc_send_notify(partid_t partid, int ch_number, void *payload,
++		xpc_notify_func func, void *key)
++{
++	return xpc_interface.send_notify(partid, ch_number, payload, func, key);
++}
++
++static inline void
++xpc_received(partid_t partid, int ch_number, void *payload)
++{
++	return xpc_interface.received(partid, ch_number, payload);
++}
++
++static inline enum xpc_retval
++xpc_partid_to_nasids(partid_t partid, void *nasids)
++{
++	return xpc_interface.partid_to_nasids(partid, nasids);
++}
++
++extern u64 xp_nofault_PIOR_target;
++extern int xp_nofault_PIOR(void *);
++extern int xp_error_PIOR(void);
++
++#endif /* _DRIVERS_MISC_SGIXP_XP_H */
+diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
+new file mode 100644
+index 0000000..1fbf99b
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xp_main.c
+@@ -0,0 +1,279 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
++ */
++
++/*
++ * Cross Partition (XP) base.
++ *
++ *	XP provides a base from which its users can interact
++ *	with XPC, yet not be dependent on XPC.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <asm/sn/intr.h>
++#include <asm/sn/sn_sal.h>
++#include "xp.h"
++
++/*
++ * The export of xp_nofault_PIOR needs to happen here since it is defined
++ * in drivers/misc/sgi-xp/xp_nofault.S. The target of the nofault read is
++ * defined here.
++ */
++EXPORT_SYMBOL_GPL(xp_nofault_PIOR);
++
++u64 xp_nofault_PIOR_target;
++EXPORT_SYMBOL_GPL(xp_nofault_PIOR_target);
++
++/*
++ * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
++ * users of XPC.
++ */
++struct xpc_registration xpc_registrations[XPC_NCHANNELS];
++EXPORT_SYMBOL_GPL(xpc_registrations);
++
++/*
++ * Initialize the XPC interface to indicate that XPC isn't loaded.
++ */
++static enum xpc_retval
++xpc_notloaded(void)
++{
++	return xpcNotLoaded;
++}
++
++struct xpc_interface xpc_interface = {
++	(void (*)(int))xpc_notloaded,
++	(void (*)(int))xpc_notloaded,
++	(enum xpc_retval(*)(partid_t, int, u32, void **))xpc_notloaded,
++	(enum xpc_retval(*)(partid_t, int, void *))xpc_notloaded,
++	(enum xpc_retval(*)(partid_t, int, void *, xpc_notify_func, void *))
++	    xpc_notloaded,
++	(void (*)(partid_t, int, void *))xpc_notloaded,
++	(enum xpc_retval(*)(partid_t, void *))xpc_notloaded
++};
++EXPORT_SYMBOL_GPL(xpc_interface);
++
++/*
++ * XPC calls this when it (the XPC module) has been loaded.
++ */
++void
++xpc_set_interface(void (*connect) (int),
++		  void (*disconnect) (int),
++		  enum xpc_retval (*allocate) (partid_t, int, u32, void **),
++		  enum xpc_retval (*send) (partid_t, int, void *),
++		  enum xpc_retval (*send_notify) (partid_t, int, void *,
++						  xpc_notify_func, void *),
++		  void (*received) (partid_t, int, void *),
++		  enum xpc_retval (*partid_to_nasids) (partid_t, void *))
++{
++	xpc_interface.connect = connect;
++	xpc_interface.disconnect = disconnect;
++	xpc_interface.allocate = allocate;
++	xpc_interface.send = send;
++	xpc_interface.send_notify = send_notify;
++	xpc_interface.received = received;
++	xpc_interface.partid_to_nasids = partid_to_nasids;
++}
++EXPORT_SYMBOL_GPL(xpc_set_interface);
++
++/*
++ * XPC calls this when it (the XPC module) is being unloaded.
++ */
++void
++xpc_clear_interface(void)
++{
++	xpc_interface.connect = (void (*)(int))xpc_notloaded;
++	xpc_interface.disconnect = (void (*)(int))xpc_notloaded;
++	xpc_interface.allocate = (enum xpc_retval(*)(partid_t, int, u32,
++						     void **))xpc_notloaded;
++	xpc_interface.send = (enum xpc_retval(*)(partid_t, int, void *))
++	    xpc_notloaded;
++	xpc_interface.send_notify = (enum xpc_retval(*)(partid_t, int, void *,
++							xpc_notify_func,
++							void *))xpc_notloaded;
++	xpc_interface.received = (void (*)(partid_t, int, void *))
++	    xpc_notloaded;
++	xpc_interface.partid_to_nasids = (enum xpc_retval(*)(partid_t, void *))
++	    xpc_notloaded;
++}
++EXPORT_SYMBOL_GPL(xpc_clear_interface);
++
++/*
++ * Register for automatic establishment of a channel connection whenever
++ * a partition comes up.
++ *
++ * Arguments:
++ *
++ *	ch_number - channel # to register for connection.
++ *	func - function to call for asynchronous notification of channel
++ *	       state changes (i.e., connection, disconnection, error) and
++ *	       the arrival of incoming messages.
++ *      key - pointer to optional user-defined value that gets passed back
++ *	      to the user on any callouts made to func.
++ *	payload_size - size in bytes of the XPC message's payload area which
++ *		       contains a user-defined message. The user should make
++ *		       this large enough to hold their largest message.
++ *	nentries - max #of XPC message entries a message queue can contain.
++ *		   The actual number, which is determined when a connection
++ * 		   is established and may be less then requested, will be
++ *		   passed to the user via the xpcConnected callout.
++ *	assigned_limit - max number of kthreads allowed to be processing
++ * 			 messages (per connection) at any given instant.
++ *	idle_limit - max number of kthreads allowed to be idle at any given
++ * 		     instant.
++ */
++enum xpc_retval
++xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
++	    u16 nentries, u32 assigned_limit, u32 idle_limit)
++{
++	struct xpc_registration *registration;
++
++	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
++	DBUG_ON(payload_size == 0 || nentries == 0);
++	DBUG_ON(func == NULL);
++	DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
++
++	registration = &xpc_registrations[ch_number];
++
++	if (mutex_lock_interruptible(&registration->mutex) != 0)
++		return xpcInterrupted;
++
++	/* if XPC_CHANNEL_REGISTERED(ch_number) */
++	if (registration->func != NULL) {
++		mutex_unlock(&registration->mutex);
++		return xpcAlreadyRegistered;
++	}
++
++	/* register the channel for connection */
++	registration->msg_size = XPC_MSG_SIZE(payload_size);
++	registration->nentries = nentries;
++	registration->assigned_limit = assigned_limit;
++	registration->idle_limit = idle_limit;
++	registration->key = key;
++	registration->func = func;
++
++	mutex_unlock(&registration->mutex);
++
++	xpc_interface.connect(ch_number);
++
++	return xpcSuccess;
++}
++EXPORT_SYMBOL_GPL(xpc_connect);
++
++/*
++ * Remove the registration for automatic connection of the specified channel
++ * when a partition comes up.
++ *
++ * Before returning this xpc_disconnect() will wait for all connections on the
++ * specified channel have been closed/torndown. So the caller can be assured
++ * that they will not be receiving any more callouts from XPC to their
++ * function registered via xpc_connect().
++ *
++ * Arguments:
++ *
++ *	ch_number - channel # to unregister.
++ */
++void
++xpc_disconnect(int ch_number)
++{
++	struct xpc_registration *registration;
++
++	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
++
++	registration = &xpc_registrations[ch_number];
++
++	/*
++	 * We've decided not to make this a down_interruptible(), since we
++	 * figured XPC's users will just turn around and call xpc_disconnect()
++	 * again anyways, so we might as well wait, if need be.
++	 */
++	mutex_lock(&registration->mutex);
++
++	/* if !XPC_CHANNEL_REGISTERED(ch_number) */
++	if (registration->func == NULL) {
++		mutex_unlock(&registration->mutex);
++		return;
++	}
++
++	/* remove the connection registration for the specified channel */
++	registration->func = NULL;
++	registration->key = NULL;
++	registration->nentries = 0;
++	registration->msg_size = 0;
++	registration->assigned_limit = 0;
++	registration->idle_limit = 0;
++
++	xpc_interface.disconnect(ch_number);
++
++	mutex_unlock(&registration->mutex);
++
++	return;
++}
++EXPORT_SYMBOL_GPL(xpc_disconnect);
++
++int __init
++xp_init(void)
++{
++	int ret, ch_number;
++	u64 func_addr = *(u64 *)xp_nofault_PIOR;
++	u64 err_func_addr = *(u64 *)xp_error_PIOR;
++
++	if (!ia64_platform_is("sn2"))
++		return -ENODEV;
++
++	/*
++	 * Register a nofault code region which performs a cross-partition
++	 * PIO read. If the PIO read times out, the MCA handler will consume
++	 * the error and return to a kernel-provided instruction to indicate
++	 * an error. This PIO read exists because it is guaranteed to timeout
++	 * if the destination is down (AMO operations do not timeout on at
++	 * least some CPUs on Shubs <= v1.2, which unfortunately we have to
++	 * work around).
++	 */
++	ret = sn_register_nofault_code(func_addr, err_func_addr, err_func_addr,
++				       1, 1);
++	if (ret != 0) {
++		printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
++		       ret);
++	}
++	/*
++	 * Setup the nofault PIO read target. (There is no special reason why
++	 * SH_IPI_ACCESS was selected.)
++	 */
++	if (is_shub2())
++		xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
++	else
++		xp_nofault_PIOR_target = SH1_IPI_ACCESS;
++
++	/* initialize the connection registration mutex */
++	for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++)
++		mutex_init(&xpc_registrations[ch_number].mutex);
++
++	return 0;
++}
++
++module_init(xp_init);
++
++void __exit
++xp_exit(void)
++{
++	u64 func_addr = *(u64 *)xp_nofault_PIOR;
++	u64 err_func_addr = *(u64 *)xp_error_PIOR;
++
++	/* unregister the PIO read nofault code region */
++	(void)sn_register_nofault_code(func_addr, err_func_addr,
++				       err_func_addr, 1, 0);
++}
++
++module_exit(xp_exit);
++
++MODULE_AUTHOR("Silicon Graphics, Inc.");
++MODULE_DESCRIPTION("Cross Partition (XP) base");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/misc/sgi-xp/xp_nofault.S b/drivers/misc/sgi-xp/xp_nofault.S
+new file mode 100644
+index 0000000..e38d433
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xp_nofault.S
+@@ -0,0 +1,35 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
++ */
++
++/*
++ * The xp_nofault_PIOR function takes a pointer to a remote PIO register
++ * and attempts to load and consume a value from it.  This function
++ * will be registered as a nofault code block.  In the event that the
++ * PIO read fails, the MCA handler will force the error to look
++ * corrected and vector to the xp_error_PIOR which will return an error.
++ *
++ * The definition of "consumption" and the time it takes for an MCA
++ * to surface is processor implementation specific.  This code
++ * is sufficient on Itanium through the Montvale processor family.
++ * It may need to be adjusted for future processor implementations.
++ *
++ *	extern int xp_nofault_PIOR(void *remote_register);
++ */
++
++	.global xp_nofault_PIOR
++xp_nofault_PIOR:
++	mov	r8=r0			// Stage a success return value
++	ld8.acq	r9=[r32];;		// PIO Read the specified register
++	adds	r9=1,r9;;		// Add to force consumption
++	srlz.i;;			// Allow time for MCA to surface
++	br.ret.sptk.many b0;;		// Return success
++
++	.global xp_error_PIOR
++xp_error_PIOR:
++	mov	r8=1			// Return value of 1
++	br.ret.sptk.many b0;;		// Return failure
+diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h
+new file mode 100644
+index 0000000..9eb6d4a
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpc.h
+@@ -0,0 +1,1187 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
++ */
++
++/*
++ * Cross Partition Communication (XPC) structures and macros.
++ */
++
++#ifndef _DRIVERS_MISC_SGIXP_XPC_H
++#define _DRIVERS_MISC_SGIXP_XPC_H
++
++#include <linux/interrupt.h>
++#include <linux/sysctl.h>
++#include <linux/device.h>
++#include <linux/mutex.h>
++#include <linux/completion.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/sn/bte.h>
++#include <asm/sn/clksupport.h>
++#include <asm/sn/addrs.h>
++#include <asm/sn/mspec.h>
++#include <asm/sn/shub_mmr.h>
++#include "xp.h"
++
++/*
++ * XPC Version numbers consist of a major and minor number. XPC can always
++ * talk to versions with same major #, and never talk to versions with a
++ * different major #.
++ */
++#define _XPC_VERSION(_maj, _min)	(((_maj) << 4) | ((_min) & 0xf))
++#define XPC_VERSION_MAJOR(_v)		((_v) >> 4)
++#define XPC_VERSION_MINOR(_v)		((_v) & 0xf)
++
++/*
++ * The next macros define word or bit representations for given
++ * C-brick nasid in either the SAL provided bit array representing
++ * nasids in the partition/machine or the AMO_t array used for
++ * inter-partition initiation communications.
++ *
++ * For SN2 machines, C-Bricks are alway even numbered NASIDs.  As
++ * such, some space will be saved by insisting that nasid information
++ * passed from SAL always be packed for C-Bricks and the
++ * cross-partition interrupts use the same packing scheme.
++ */
++#define XPC_NASID_W_INDEX(_n)	(((_n) / 64) / 2)
++#define XPC_NASID_B_INDEX(_n)	(((_n) / 2) & (64 - 1))
++#define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \
++				    (1UL << XPC_NASID_B_INDEX(_n)))
++#define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
++
++#define XPC_HB_DEFAULT_INTERVAL		5	/* incr HB every x secs */
++#define XPC_HB_CHECK_DEFAULT_INTERVAL	20	/* check HB every x secs */
++
++/* define the process name of HB checker and the CPU it is pinned to */
++#define XPC_HB_CHECK_THREAD_NAME	"xpc_hb"
++#define XPC_HB_CHECK_CPU		0
++
++/* define the process name of the discovery thread */
++#define XPC_DISCOVERY_THREAD_NAME	"xpc_discovery"
++
++/*
++ * the reserved page
++ *
++ *   SAL reserves one page of memory per partition for XPC. Though a full page
++ *   in length (16384 bytes), its starting address is not page aligned, but it
++ *   is cacheline aligned. The reserved page consists of the following:
++ *
++ *   reserved page header
++ *
++ *     The first cacheline of the reserved page contains the header
++ *     (struct xpc_rsvd_page). Before SAL initialization has completed,
++ *     SAL has set up the following fields of the reserved page header:
++ *     SAL_signature, SAL_version, partid, and nasids_size. The other
++ *     fields are set up by XPC. (xpc_rsvd_page points to the local
++ *     partition's reserved page.)
++ *
++ *   part_nasids mask
++ *   mach_nasids mask
++ *
++ *     SAL also sets up two bitmaps (or masks), one that reflects the actual
++ *     nasids in this partition (part_nasids), and the other that reflects
++ *     the actual nasids in the entire machine (mach_nasids). We're only
++ *     interested in the even numbered nasids (which contain the processors
++ *     and/or memory), so we only need half as many bits to represent the
++ *     nasids. The part_nasids mask is located starting at the first cacheline
++ *     following the reserved page header. The mach_nasids mask follows right
++ *     after the part_nasids mask. The size in bytes of each mask is reflected
++ *     by the reserved page header field 'nasids_size'. (Local partition's
++ *     mask pointers are xpc_part_nasids and xpc_mach_nasids.)
++ *
++ *   vars
++ *   vars part
++ *
++ *     Immediately following the mach_nasids mask are the XPC variables
++ *     required by other partitions. First are those that are generic to all
++ *     partitions (vars), followed on the next available cacheline by those
++ *     which are partition specific (vars part). These are setup by XPC.
++ *     (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
++ *
++ * Note: Until vars_pa is set, the partition XPC code has not been initialized.
++ */
++struct xpc_rsvd_page {
++	u64 SAL_signature;	/* SAL: unique signature */
++	u64 SAL_version;	/* SAL: version */
++	u8 partid;		/* SAL: partition ID */
++	u8 version;
++	u8 pad1[6];		/* align to next u64 in cacheline */
++	u64 vars_pa;		/* physical address of struct xpc_vars */
++	struct timespec stamp;	/* time when reserved page was setup by XPC */
++	u64 pad2[9];		/* align to last u64 in cacheline */
++	u64 nasids_size;	/* SAL: size of each nasid mask in bytes */
++};
++
++#define XPC_RP_VERSION _XPC_VERSION(1, 1) /* version 1.1 of the reserved page */
++
++#define XPC_SUPPORTS_RP_STAMP(_version) \
++			(_version >= _XPC_VERSION(1, 1))
++
++/*
++ * compare stamps - the return value is:
++ *
++ *	< 0,	if stamp1 < stamp2
++ *	= 0,	if stamp1 == stamp2
++ *	> 0,	if stamp1 > stamp2
++ */
++static inline int
++xpc_compare_stamps(struct timespec *stamp1, struct timespec *stamp2)
++{
++	int ret;
++
++	ret = stamp1->tv_sec - stamp2->tv_sec;
++	if (ret == 0)
++		ret = stamp1->tv_nsec - stamp2->tv_nsec;
++
++	return ret;
++}
++
++/*
++ * Define the structures by which XPC variables can be exported to other
++ * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
++ */
++
++/*
++ * The following structure describes the partition generic variables
++ * needed by other partitions in order to properly initialize.
++ *
++ * struct xpc_vars version number also applies to struct xpc_vars_part.
++ * Changes to either structure and/or related functionality should be
++ * reflected by incrementing either the major or minor version numbers
++ * of struct xpc_vars.
++ */
++struct xpc_vars {
++	u8 version;
++	u64 heartbeat;
++	u64 heartbeating_to_mask;
++	u64 heartbeat_offline;	/* if 0, heartbeat should be changing */
++	int act_nasid;
++	int act_phys_cpuid;
++	u64 vars_part_pa;
++	u64 amos_page_pa;	/* paddr of page of AMOs from MSPEC driver */
++	AMO_t *amos_page;	/* vaddr of page of AMOs from MSPEC driver */
++};
++
++#define XPC_V_VERSION _XPC_VERSION(3, 1)    /* version 3.1 of the cross vars */
++
++#define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \
++			(_version >= _XPC_VERSION(3, 1))
++
++static inline int
++xpc_hb_allowed(partid_t partid, struct xpc_vars *vars)
++{
++	return ((vars->heartbeating_to_mask & (1UL << partid)) != 0);
++}
++
++static inline void
++xpc_allow_hb(partid_t partid, struct xpc_vars *vars)
++{
++	u64 old_mask, new_mask;
++
++	do {
++		old_mask = vars->heartbeating_to_mask;
++		new_mask = (old_mask | (1UL << partid));
++	} while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
++		 old_mask);
++}
++
++static inline void
++xpc_disallow_hb(partid_t partid, struct xpc_vars *vars)
++{
++	u64 old_mask, new_mask;
++
++	do {
++		old_mask = vars->heartbeating_to_mask;
++		new_mask = (old_mask & ~(1UL << partid));
++	} while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
++		 old_mask);
++}
++
++/*
++ * The AMOs page consists of a number of AMO variables which are divided into
++ * four groups, The first two groups are used to identify an IRQ's sender.
++ * These two groups consist of 64 and 128 AMO variables respectively. The last
++ * two groups, consisting of just one AMO variable each, are used to identify
++ * the remote partitions that are currently engaged (from the viewpoint of
++ * the XPC running on the remote partition).
++ */
++#define XPC_NOTIFY_IRQ_AMOS	   0
++#define XPC_ACTIVATE_IRQ_AMOS	   (XPC_NOTIFY_IRQ_AMOS + XP_MAX_PARTITIONS)
++#define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS)
++#define XPC_DISENGAGE_REQUEST_AMO  (XPC_ENGAGED_PARTITIONS_AMO + 1)
++
++/*
++ * The following structure describes the per partition specific variables.
++ *
++ * An array of these structures, one per partition, will be defined. As a
++ * partition becomes active XPC will copy the array entry corresponding to
++ * itself from that partition. It is desirable that the size of this
++ * structure evenly divide into a cacheline, such that none of the entries
++ * in this array crosses a cacheline boundary. As it is now, each entry
++ * occupies half a cacheline.
++ */
++struct xpc_vars_part {
++	u64 magic;
++
++	u64 openclose_args_pa;	/* physical address of open and close args */
++	u64 GPs_pa;		/* physical address of Get/Put values */
++
++	u64 IPI_amo_pa;		/* physical address of IPI AMO_t structure */
++	int IPI_nasid;		/* nasid of where to send IPIs */
++	int IPI_phys_cpuid;	/* physical CPU ID of where to send IPIs */
++
++	u8 nchannels;		/* #of defined channels supported */
++
++	u8 reserved[23];	/* pad to a full 64 bytes */
++};
++
++/*
++ * The vars_part MAGIC numbers play a part in the first contact protocol.
++ *
++ * MAGIC1 indicates that the per partition specific variables for a remote
++ * partition have been initialized by this partition.
++ *
++ * MAGIC2 indicates that this partition has pulled the remote partititions
++ * per partition variables that pertain to this partition.
++ */
++#define XPC_VP_MAGIC1	0x0053524156435058L   /* 'XPCVARS\0'L (little endian) */
++#define XPC_VP_MAGIC2	0x0073726176435058L   /* 'XPCvars\0'L (little endian) */
++
++/* the reserved page sizes and offsets */
++
++#define XPC_RP_HEADER_SIZE	L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
++#define XPC_RP_VARS_SIZE	L1_CACHE_ALIGN(sizeof(struct xpc_vars))
++
++#define XPC_RP_PART_NASIDS(_rp) ((u64 *)((u8 *)(_rp) + XPC_RP_HEADER_SIZE))
++#define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words)
++#define XPC_RP_VARS(_rp)	((struct xpc_vars *)(XPC_RP_MACH_NASIDS(_rp) + \
++				    xp_nasid_mask_words))
++#define XPC_RP_VARS_PART(_rp)	((struct xpc_vars_part *) \
++				    ((u8 *)XPC_RP_VARS(_rp) + XPC_RP_VARS_SIZE))
++
++/*
++ * Functions registered by add_timer() or called by kernel_thread() only
++ * allow for a single 64-bit argument. The following macros can be used to
++ * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
++ * the passed argument.
++ */
++#define XPC_PACK_ARGS(_arg1, _arg2) \
++			((((u64) _arg1) & 0xffffffff) | \
++			((((u64) _arg2) & 0xffffffff) << 32))
++
++#define XPC_UNPACK_ARG1(_args)	(((u64) _args) & 0xffffffff)
++#define XPC_UNPACK_ARG2(_args)	((((u64) _args) >> 32) & 0xffffffff)
++
++/*
++ * Define a Get/Put value pair (pointers) used with a message queue.
++ */
++struct xpc_gp {
++	s64 get;		/* Get value */
++	s64 put;		/* Put value */
++};
++
++#define XPC_GP_SIZE \
++		L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_NCHANNELS)
++
++/*
++ * Define a structure that contains arguments associated with opening and
++ * closing a channel.
++ */
++struct xpc_openclose_args {
++	u16 reason;		/* reason why channel is closing */
++	u16 msg_size;		/* sizeof each message entry */
++	u16 remote_nentries;	/* #of message entries in remote msg queue */
++	u16 local_nentries;	/* #of message entries in local msg queue */
++	u64 local_msgqueue_pa;	/* physical address of local message queue */
++};
++
++#define XPC_OPENCLOSE_ARGS_SIZE \
++	      L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * XPC_NCHANNELS)
++
++/* struct xpc_msg flags */
++
++#define	XPC_M_DONE		0x01	/* msg has been received/consumed */
++#define	XPC_M_READY		0x02	/* msg is ready to be sent */
++#define	XPC_M_INTERRUPT		0x04	/* send interrupt when msg consumed */
++
++#define XPC_MSG_ADDRESS(_payload) \
++		((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))
++
++/*
++ * Defines notify entry.
++ *
++ * This is used to notify a message's sender that their message was received
++ * and consumed by the intended recipient.
++ */
++struct xpc_notify {
++	u8 type;		/* type of notification */
++
++	/* the following two fields are only used if type == XPC_N_CALL */
++	xpc_notify_func func;	/* user's notify function */
++	void *key;		/* pointer to user's key */
++};
++
++/* struct xpc_notify type of notification */
++
++#define	XPC_N_CALL		0x01	/* notify function provided by user */
++
++/*
++ * Define the structure that manages all the stuff required by a channel. In
++ * particular, they are used to manage the messages sent across the channel.
++ *
++ * This structure is private to a partition, and is NOT shared across the
++ * partition boundary.
++ *
++ * There is an array of these structures for each remote partition. It is
++ * allocated at the time a partition becomes active. The array contains one
++ * of these structures for each potential channel connection to that partition.
++ *
++ * Each of these structures manages two message queues (circular buffers).
++ * They are allocated at the time a channel connection is made. One of
++ * these message queues (local_msgqueue) holds the locally created messages
++ * that are destined for the remote partition. The other of these message
++ * queues (remote_msgqueue) is a locally cached copy of the remote partition's
++ * own local_msgqueue.
++ *
++ * The following is a description of the Get/Put pointers used to manage these
++ * two message queues. Consider the local_msgqueue to be on one partition
++ * and the remote_msgqueue to be its cached copy on another partition. A
++ * description of what each of the lettered areas contains is included.
++ *
++ *
++ *                     local_msgqueue      remote_msgqueue
++ *
++ *                        |/////////|      |/////////|
++ *    w_remote_GP.get --> +---------+      |/////////|
++ *                        |    F    |      |/////////|
++ *     remote_GP.get  --> +---------+      +---------+ <-- local_GP->get
++ *                        |         |      |         |
++ *                        |         |      |    E    |
++ *                        |         |      |         |
++ *                        |         |      +---------+ <-- w_local_GP.get
++ *                        |    B    |      |/////////|
++ *                        |         |      |////D////|
++ *                        |         |      |/////////|
++ *                        |         |      +---------+ <-- w_remote_GP.put
++ *                        |         |      |////C////|
++ *      local_GP->put --> +---------+      +---------+ <-- remote_GP.put
++ *                        |         |      |/////////|
++ *                        |    A    |      |/////////|
++ *                        |         |      |/////////|
++ *     w_local_GP.put --> +---------+      |/////////|
++ *                        |/////////|      |/////////|
++ *
++ *
++ *	    ( remote_GP.[get|put] are cached copies of the remote
++ *	      partition's local_GP->[get|put], and thus their values can
++ *	      lag behind their counterparts on the remote partition. )
++ *
++ *
++ *  A - Messages that have been allocated, but have not yet been sent to the
++ *	remote partition.
++ *
++ *  B - Messages that have been sent, but have not yet been acknowledged by the
++ *      remote partition as having been received.
++ *
++ *  C - Area that needs to be prepared for the copying of sent messages, by
++ *	the clearing of the message flags of any previously received messages.
++ *
++ *  D - Area into which sent messages are to be copied from the remote
++ *	partition's local_msgqueue and then delivered to their intended
++ *	recipients. [ To allow for a multi-message copy, another pointer
++ *	(next_msg_to_pull) has been added to keep track of the next message
++ *	number needing to be copied (pulled). It chases after w_remote_GP.put.
++ *	Any messages lying between w_local_GP.get and next_msg_to_pull have
++ *	been copied and are ready to be delivered. ]
++ *
++ *  E - Messages that have been copied and delivered, but have not yet been
++ *	acknowledged by the recipient as having been received.
++ *
++ *  F - Messages that have been acknowledged, but XPC has not yet notified the
++ *	sender that the message was received by its intended recipient.
++ *	This is also an area that needs to be prepared for the allocating of
++ *	new messages, by the clearing of the message flags of the acknowledged
++ *	messages.
++ */
++struct xpc_channel {
++	partid_t partid;	/* ID of remote partition connected */
++	spinlock_t lock;	/* lock for updating this structure */
++	u32 flags;		/* general flags */
++
++	enum xpc_retval reason;	/* reason why channel is disconnect'g */
++	int reason_line;	/* line# disconnect initiated from */
++
++	u16 number;		/* channel # */
++
++	u16 msg_size;		/* sizeof each msg entry */
++	u16 local_nentries;	/* #of msg entries in local msg queue */
++	u16 remote_nentries;	/* #of msg entries in remote msg queue */
++
++	void *local_msgqueue_base;	/* base address of kmalloc'd space */
++	struct xpc_msg *local_msgqueue;	/* local message queue */
++	void *remote_msgqueue_base;	/* base address of kmalloc'd space */
++	struct xpc_msg *remote_msgqueue; /* cached copy of remote partition's */
++					 /* local message queue */
++	u64 remote_msgqueue_pa;	/* phys addr of remote partition's */
++				/* local message queue */
++
++	atomic_t references;	/* #of external references to queues */
++
++	atomic_t n_on_msg_allocate_wq;	/* #on msg allocation wait queue */
++	wait_queue_head_t msg_allocate_wq;	/* msg allocation wait queue */
++
++	u8 delayed_IPI_flags;	/* IPI flags received, but delayed */
++				/* action until channel disconnected */
++
++	/* queue of msg senders who want to be notified when msg received */
++
++	atomic_t n_to_notify;	/* #of msg senders to notify */
++	struct xpc_notify *notify_queue;    /* notify queue for messages sent */
++
++	xpc_channel_func func;	/* user's channel function */
++	void *key;		/* pointer to user's key */
++
++	struct mutex msg_to_pull_mutex;	/* next msg to pull serialization */
++	struct completion wdisconnect_wait;    /* wait for channel disconnect */
++
++	struct xpc_openclose_args *local_openclose_args; /* args passed on */
++					     /* opening or closing of channel */
++
++	/* various flavors of local and remote Get/Put values */
++
++	struct xpc_gp *local_GP;	/* local Get/Put values */
++	struct xpc_gp remote_GP;	/* remote Get/Put values */
++	struct xpc_gp w_local_GP;	/* working local Get/Put values */
++	struct xpc_gp w_remote_GP;	/* working remote Get/Put values */
++	s64 next_msg_to_pull;	/* Put value of next msg to pull */
++
++	/* kthread management related fields */
++
++	atomic_t kthreads_assigned;	/* #of kthreads assigned to channel */
++	u32 kthreads_assigned_limit;	/* limit on #of kthreads assigned */
++	atomic_t kthreads_idle;	/* #of kthreads idle waiting for work */
++	u32 kthreads_idle_limit;	/* limit on #of kthreads idle */
++	atomic_t kthreads_active;	/* #of kthreads actively working */
++
++	wait_queue_head_t idle_wq;	/* idle kthread wait queue */
++
++} ____cacheline_aligned;
++
++/* struct xpc_channel flags */
++
++#define	XPC_C_WASCONNECTED	0x00000001	/* channel was connected */
++
++#define	XPC_C_ROPENREPLY	0x00000002	/* remote open channel reply */
++#define	XPC_C_OPENREPLY		0x00000004	/* local open channel reply */
++#define	XPC_C_ROPENREQUEST	0x00000008     /* remote open channel request */
++#define	XPC_C_OPENREQUEST	0x00000010	/* local open channel request */
++
++#define	XPC_C_SETUP		0x00000020 /* channel's msgqueues are alloc'd */
++#define	XPC_C_CONNECTEDCALLOUT	0x00000040     /* connected callout initiated */
++#define	XPC_C_CONNECTEDCALLOUT_MADE \
++				0x00000080     /* connected callout completed */
++#define	XPC_C_CONNECTED		0x00000100	/* local channel is connected */
++#define	XPC_C_CONNECTING	0x00000200	/* channel is being connected */
++
++#define	XPC_C_RCLOSEREPLY	0x00000400	/* remote close channel reply */
++#define	XPC_C_CLOSEREPLY	0x00000800	/* local close channel reply */
++#define	XPC_C_RCLOSEREQUEST	0x00001000    /* remote close channel request */
++#define	XPC_C_CLOSEREQUEST	0x00002000     /* local close channel request */
++
++#define	XPC_C_DISCONNECTED	0x00004000	/* channel is disconnected */
++#define	XPC_C_DISCONNECTING	0x00008000   /* channel is being disconnected */
++#define	XPC_C_DISCONNECTINGCALLOUT \
++				0x00010000 /* disconnecting callout initiated */
++#define	XPC_C_DISCONNECTINGCALLOUT_MADE \
++				0x00020000 /* disconnecting callout completed */
++#define	XPC_C_WDISCONNECT	0x00040000  /* waiting for channel disconnect */
++
++/*
++ * Manages channels on a partition basis. There is one of these structures
++ * for each partition (a partition will never utilize the structure that
++ * represents itself).
++ */
++struct xpc_partition {
++
++	/* XPC HB infrastructure */
++
++	u8 remote_rp_version;	/* version# of partition's rsvd pg */
++	struct timespec remote_rp_stamp; /* time when rsvd pg was initialized */
++	u64 remote_rp_pa;	/* phys addr of partition's rsvd pg */
++	u64 remote_vars_pa;	/* phys addr of partition's vars */
++	u64 remote_vars_part_pa;	/* phys addr of partition's vars part */
++	u64 last_heartbeat;	/* HB at last read */
++	u64 remote_amos_page_pa;	/* phys addr of partition's amos page */
++	int remote_act_nasid;	/* active part's act/deact nasid */
++	int remote_act_phys_cpuid;	/* active part's act/deact phys cpuid */
++	u32 act_IRQ_rcvd;	/* IRQs since activation */
++	spinlock_t act_lock;	/* protect updating of act_state */
++	u8 act_state;		/* from XPC HB viewpoint */
++	u8 remote_vars_version;	/* version# of partition's vars */
++	enum xpc_retval reason;	/* reason partition is deactivating */
++	int reason_line;	/* line# deactivation initiated from */
++	int reactivate_nasid;	/* nasid in partition to reactivate */
++
++	unsigned long disengage_request_timeout;	/* timeout in jiffies */
++	struct timer_list disengage_request_timer;
++
++	/* XPC infrastructure referencing and teardown control */
++
++	u8 setup_state;		/* infrastructure setup state */
++	wait_queue_head_t teardown_wq;	/* kthread waiting to teardown infra */
++	atomic_t references;	/* #of references to infrastructure */
++
++	/*
++	 * NONE OF THE PRECEDING FIELDS OF THIS STRUCTURE WILL BE CLEARED WHEN
++	 * XPC SETS UP THE NECESSARY INFRASTRUCTURE TO SUPPORT CROSS PARTITION
++	 * COMMUNICATION. ALL OF THE FOLLOWING FIELDS WILL BE CLEARED. (THE
++	 * 'nchannels' FIELD MUST BE THE FIRST OF THE FIELDS TO BE CLEARED.)
++	 */
++
++	u8 nchannels;		/* #of defined channels supported */
++	atomic_t nchannels_active;  /* #of channels that are not DISCONNECTED */
++	atomic_t nchannels_engaged;  /* #of channels engaged with remote part */
++	struct xpc_channel *channels;	/* array of channel structures */
++
++	void *local_GPs_base;	/* base address of kmalloc'd space */
++	struct xpc_gp *local_GPs;	/* local Get/Put values */
++	void *remote_GPs_base;	/* base address of kmalloc'd space */
++	struct xpc_gp *remote_GPs;	/* copy of remote partition's local */
++					/* Get/Put values */
++	u64 remote_GPs_pa;	/* phys address of remote partition's local */
++				/* Get/Put values */
++
++	/* fields used to pass args when opening or closing a channel */
++
++	void *local_openclose_args_base;   /* base address of kmalloc'd space */
++	struct xpc_openclose_args *local_openclose_args;      /* local's args */
++	void *remote_openclose_args_base;  /* base address of kmalloc'd space */
++	struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
++							  /* args */
++	u64 remote_openclose_args_pa;	/* phys addr of remote's args */
++
++	/* IPI sending, receiving and handling related fields */
++
++	int remote_IPI_nasid;	/* nasid of where to send IPIs */
++	int remote_IPI_phys_cpuid;	/* phys CPU ID of where to send IPIs */
++	AMO_t *remote_IPI_amo_va;    /* address of remote IPI AMO_t structure */
++
++	AMO_t *local_IPI_amo_va;	/* address of IPI AMO_t structure */
++	u64 local_IPI_amo;	/* IPI amo flags yet to be handled */
++	char IPI_owner[8];	/* IPI owner's name */
++	struct timer_list dropped_IPI_timer;	/* dropped IPI timer */
++
++	spinlock_t IPI_lock;	/* IPI handler lock */
++
++	/* channel manager related fields */
++
++	atomic_t channel_mgr_requests;	/* #of requests to activate chan mgr */
++	wait_queue_head_t channel_mgr_wq;	/* channel mgr's wait queue */
++
++} ____cacheline_aligned;
++
++/* struct xpc_partition act_state values (for XPC HB) */
++
++#define	XPC_P_INACTIVE		0x00	/* partition is not active */
++#define XPC_P_ACTIVATION_REQ	0x01	/* created thread to activate */
++#define XPC_P_ACTIVATING	0x02	/* activation thread started */
++#define XPC_P_ACTIVE		0x03	/* xpc_partition_up() was called */
++#define XPC_P_DEACTIVATING	0x04	/* partition deactivation initiated */
++
++#define XPC_DEACTIVATE_PARTITION(_p, _reason) \
++			xpc_deactivate_partition(__LINE__, (_p), (_reason))
++
++/* struct xpc_partition setup_state values */
++
++#define XPC_P_UNSET		0x00	/* infrastructure was never setup */
++#define XPC_P_SETUP		0x01	/* infrastructure is setup */
++#define XPC_P_WTEARDOWN		0x02	/* waiting to teardown infrastructure */
++#define XPC_P_TORNDOWN		0x03	/* infrastructure is torndown */
++
++/*
++ * struct xpc_partition IPI_timer #of seconds to wait before checking for
++ * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
++ * after the IPI was received.
++ */
++#define XPC_P_DROPPED_IPI_WAIT	(0.25 * HZ)
++
++/* number of seconds to wait for other partitions to disengage */
++#define XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT	90
++
++/* interval in seconds to print 'waiting disengagement' messages */
++#define XPC_DISENGAGE_PRINTMSG_INTERVAL		10
++
++#define XPC_PARTID(_p)	((partid_t) ((_p) - &xpc_partitions[0]))
++
++/* found in xp_main.c */
++extern struct xpc_registration xpc_registrations[];
++
++/* found in xpc_main.c */
++extern struct device *xpc_part;
++extern struct device *xpc_chan;
++extern int xpc_disengage_request_timelimit;
++extern int xpc_disengage_request_timedout;
++extern irqreturn_t xpc_notify_IRQ_handler(int, void *);
++extern void xpc_dropped_IPI_check(struct xpc_partition *);
++extern void xpc_activate_partition(struct xpc_partition *);
++extern void xpc_activate_kthreads(struct xpc_channel *, int);
++extern void xpc_create_kthreads(struct xpc_channel *, int, int);
++extern void xpc_disconnect_wait(int);
++
++/* found in xpc_partition.c */
++extern int xpc_exiting;
++extern struct xpc_vars *xpc_vars;
++extern struct xpc_rsvd_page *xpc_rsvd_page;
++extern struct xpc_vars_part *xpc_vars_part;
++extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
++extern char *xpc_remote_copy_buffer;
++extern void *xpc_remote_copy_buffer_base;
++extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
++extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
++extern void xpc_allow_IPI_ops(void);
++extern void xpc_restrict_IPI_ops(void);
++extern int xpc_identify_act_IRQ_sender(void);
++extern int xpc_partition_disengaged(struct xpc_partition *);
++extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);
++extern void xpc_mark_partition_inactive(struct xpc_partition *);
++extern void xpc_discovery(void);
++extern void xpc_check_remote_hb(void);
++extern void xpc_deactivate_partition(const int, struct xpc_partition *,
++				     enum xpc_retval);
++extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *);
++
++/* found in xpc_channel.c */
++extern void xpc_initiate_connect(int);
++extern void xpc_initiate_disconnect(int);
++extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **);
++extern enum xpc_retval xpc_initiate_send(partid_t, int, void *);
++extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *,
++						xpc_notify_func, void *);
++extern void xpc_initiate_received(partid_t, int, void *);
++extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *);
++extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *);
++extern void xpc_process_channel_activity(struct xpc_partition *);
++extern void xpc_connected_callout(struct xpc_channel *);
++extern void xpc_deliver_msg(struct xpc_channel *);
++extern void xpc_disconnect_channel(const int, struct xpc_channel *,
++				   enum xpc_retval, unsigned long *);
++extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval);
++extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval);
++extern void xpc_teardown_infrastructure(struct xpc_partition *);
++
++static inline void
++xpc_wakeup_channel_mgr(struct xpc_partition *part)
++{
++	if (atomic_inc_return(&part->channel_mgr_requests) == 1)
++		wake_up(&part->channel_mgr_wq);
++}
++
++/*
++ * These next two inlines are used to keep us from tearing down a channel's
++ * msg queues while a thread may be referencing them.
++ */
++static inline void
++xpc_msgqueue_ref(struct xpc_channel *ch)
++{
++	atomic_inc(&ch->references);
++}
++
++static inline void
++xpc_msgqueue_deref(struct xpc_channel *ch)
++{
++	s32 refs = atomic_dec_return(&ch->references);
++
++	DBUG_ON(refs < 0);
++	if (refs == 0)
++		xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
++}
++
++#define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
++		xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
++
++/*
++ * These two inlines are used to keep us from tearing down a partition's
++ * setup infrastructure while a thread may be referencing it.
++ */
++static inline void
++xpc_part_deref(struct xpc_partition *part)
++{
++	s32 refs = atomic_dec_return(&part->references);
++
++	DBUG_ON(refs < 0);
++	if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN)
++		wake_up(&part->teardown_wq);
++}
++
++static inline int
++xpc_part_ref(struct xpc_partition *part)
++{
++	int setup;
++
++	atomic_inc(&part->references);
++	setup = (part->setup_state == XPC_P_SETUP);
++	if (!setup)
++		xpc_part_deref(part);
++
++	return setup;
++}
++
++/*
++ * The following macro is to be used for the setting of the reason and
++ * reason_line fields in both the struct xpc_channel and struct xpc_partition
++ * structures.
++ */
++#define XPC_SET_REASON(_p, _reason, _line) \
++	{ \
++		(_p)->reason = _reason; \
++		(_p)->reason_line = _line; \
++	}
++
++/*
++ * This next set of inlines are used to keep track of when a partition is
++ * potentially engaged in accessing memory belonging to another partition.
++ */
++
++static inline void
++xpc_mark_partition_engaged(struct xpc_partition *part)
++{
++	unsigned long irq_flags;
++	AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
++				   (XPC_ENGAGED_PARTITIONS_AMO *
++				    sizeof(AMO_t)));
++
++	local_irq_save(irq_flags);
++
++	/* set bit corresponding to our partid in remote partition's AMO */
++	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
++			 (1UL << sn_partition_id));
++	/*
++	 * We must always use the nofault function regardless of whether we
++	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++	 * didn't, we'd never know that the other partition is down and would
++	 * keep sending IPIs and AMOs to it until the heartbeat times out.
++	 */
++	(void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
++							       variable),
++						     xp_nofault_PIOR_target));
++
++	local_irq_restore(irq_flags);
++}
++
++static inline void
++xpc_mark_partition_disengaged(struct xpc_partition *part)
++{
++	unsigned long irq_flags;
++	AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
++				   (XPC_ENGAGED_PARTITIONS_AMO *
++				    sizeof(AMO_t)));
++
++	local_irq_save(irq_flags);
++
++	/* clear bit corresponding to our partid in remote partition's AMO */
++	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
++			 ~(1UL << sn_partition_id));
++	/*
++	 * We must always use the nofault function regardless of whether we
++	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++	 * didn't, we'd never know that the other partition is down and would
++	 * keep sending IPIs and AMOs to it until the heartbeat times out.
++	 */
++	(void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
++							       variable),
++						     xp_nofault_PIOR_target));
++
++	local_irq_restore(irq_flags);
++}
++
++static inline void
++xpc_request_partition_disengage(struct xpc_partition *part)
++{
++	unsigned long irq_flags;
++	AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
++				   (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
++
++	local_irq_save(irq_flags);
++
++	/* set bit corresponding to our partid in remote partition's AMO */
++	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
++			 (1UL << sn_partition_id));
++	/*
++	 * We must always use the nofault function regardless of whether we
++	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++	 * didn't, we'd never know that the other partition is down and would
++	 * keep sending IPIs and AMOs to it until the heartbeat times out.
++	 */
++	(void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
++							       variable),
++						     xp_nofault_PIOR_target));
++
++	local_irq_restore(irq_flags);
++}
++
++static inline void
++xpc_cancel_partition_disengage_request(struct xpc_partition *part)
++{
++	unsigned long irq_flags;
++	AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
++				   (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
++
++	local_irq_save(irq_flags);
++
++	/* clear bit corresponding to our partid in remote partition's AMO */
++	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
++			 ~(1UL << sn_partition_id));
++	/*
++	 * We must always use the nofault function regardless of whether we
++	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++	 * didn't, we'd never know that the other partition is down and would
++	 * keep sending IPIs and AMOs to it until the heartbeat times out.
++	 */
++	(void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
++							       variable),
++						     xp_nofault_PIOR_target));
++
++	local_irq_restore(irq_flags);
++}
++
++static inline u64
++xpc_partition_engaged(u64 partid_mask)
++{
++	AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
++
++	/* return our partition's AMO variable ANDed with partid_mask */
++	return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
++		partid_mask);
++}
++
++static inline u64
++xpc_partition_disengage_requested(u64 partid_mask)
++{
++	AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
++
++	/* return our partition's AMO variable ANDed with partid_mask */
++	return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
++		partid_mask);
++}
++
++static inline void
++xpc_clear_partition_engaged(u64 partid_mask)
++{
++	AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
++
++	/* clear bit(s) based on partid_mask in our partition's AMO */
++	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
++			 ~partid_mask);
++}
++
++static inline void
++xpc_clear_partition_disengage_request(u64 partid_mask)
++{
++	AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
++
++	/* clear bit(s) based on partid_mask in our partition's AMO */
++	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
++			 ~partid_mask);
++}
++
++/*
++ * The following set of macros and inlines are used for the sending and
++ * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
++ * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
++ * the other that is associated with channel activity (SGI_XPC_NOTIFY).
++ */
++
++static inline u64
++xpc_IPI_receive(AMO_t *amo)
++{
++	return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_CLEAR);
++}
++
++static inline enum xpc_retval
++xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
++{
++	int ret = 0;
++	unsigned long irq_flags;
++
++	local_irq_save(irq_flags);
++
++	FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR, flag);
++	sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
++
++	/*
++	 * We must always use the nofault function regardless of whether we
++	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++	 * didn't, we'd never know that the other partition is down and would
++	 * keep sending IPIs and AMOs to it until the heartbeat times out.
++	 */
++	ret = xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
++						     xp_nofault_PIOR_target));
++
++	local_irq_restore(irq_flags);
++
++	return ((ret == 0) ? xpcSuccess : xpcPioReadError);
++}
++
++/*
++ * IPIs associated with SGI_XPC_ACTIVATE IRQ.
++ */
++
++/*
++ * Flag the appropriate AMO variable and send an IPI to the specified node.
++ */
++static inline void
++xpc_activate_IRQ_send(u64 amos_page_pa, int from_nasid, int to_nasid,
++		      int to_phys_cpuid)
++{
++	int w_index = XPC_NASID_W_INDEX(from_nasid);
++	int b_index = XPC_NASID_B_INDEX(from_nasid);
++	AMO_t *amos = (AMO_t *)__va(amos_page_pa +
++				    (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
++
++	(void)xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,
++			   to_phys_cpuid, SGI_XPC_ACTIVATE);
++}
++
++static inline void
++xpc_IPI_send_activate(struct xpc_vars *vars)
++{
++	xpc_activate_IRQ_send(vars->amos_page_pa, cnodeid_to_nasid(0),
++			      vars->act_nasid, vars->act_phys_cpuid);
++}
++
++static inline void
++xpc_IPI_send_activated(struct xpc_partition *part)
++{
++	xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
++			      part->remote_act_nasid,
++			      part->remote_act_phys_cpuid);
++}
++
++static inline void
++xpc_IPI_send_reactivate(struct xpc_partition *part)
++{
++	xpc_activate_IRQ_send(xpc_vars->amos_page_pa, part->reactivate_nasid,
++			      xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);
++}
++
++static inline void
++xpc_IPI_send_disengage(struct xpc_partition *part)
++{
++	xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
++			      part->remote_act_nasid,
++			      part->remote_act_phys_cpuid);
++}
++
++/*
++ * IPIs associated with SGI_XPC_NOTIFY IRQ.
++ */
++
++/*
++ * Send an IPI to the remote partition that is associated with the
++ * specified channel.
++ */
++#define XPC_NOTIFY_IRQ_SEND(_ch, _ipi_f, _irq_f) \
++		xpc_notify_IRQ_send(_ch, _ipi_f, #_ipi_f, _irq_f)
++
++static inline void
++xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string,
++		    unsigned long *irq_flags)
++{
++	struct xpc_partition *part = &xpc_partitions[ch->partid];
++	enum xpc_retval ret;
++
++	if (likely(part->act_state != XPC_P_DEACTIVATING)) {
++		ret = xpc_IPI_send(part->remote_IPI_amo_va,
++				   (u64)ipi_flag << (ch->number * 8),
++				   part->remote_IPI_nasid,
++				   part->remote_IPI_phys_cpuid, SGI_XPC_NOTIFY);
++		dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
++			ipi_flag_string, ch->partid, ch->number, ret);
++		if (unlikely(ret != xpcSuccess)) {
++			if (irq_flags != NULL)
++				spin_unlock_irqrestore(&ch->lock, *irq_flags);
++			XPC_DEACTIVATE_PARTITION(part, ret);
++			if (irq_flags != NULL)
++				spin_lock_irqsave(&ch->lock, *irq_flags);
++		}
++	}
++}
++
++/*
++ * Make it look like the remote partition, which is associated with the
++ * specified channel, sent us an IPI. This faked IPI will be handled
++ * by xpc_dropped_IPI_check().
++ */
++#define XPC_NOTIFY_IRQ_SEND_LOCAL(_ch, _ipi_f) \
++		xpc_notify_IRQ_send_local(_ch, _ipi_f, #_ipi_f)
++
++static inline void
++xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag,
++			  char *ipi_flag_string)
++{
++	struct xpc_partition *part = &xpc_partitions[ch->partid];
++
++	FETCHOP_STORE_OP(TO_AMO((u64)&part->local_IPI_amo_va->variable),
++			 FETCHOP_OR, ((u64)ipi_flag << (ch->number * 8)));
++	dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
++		ipi_flag_string, ch->partid, ch->number);
++}
++
++/*
++ * The sending and receiving of IPIs includes the setting of an AMO variable
++ * to indicate the reason the IPI was sent. The 64-bit variable is divided
++ * up into eight bytes, ordered from right to left. Byte zero pertains to
++ * channel 0, byte one to channel 1, and so on. Each byte is described by
++ * the following IPI flags.
++ */
++
++#define	XPC_IPI_CLOSEREQUEST	0x01
++#define	XPC_IPI_CLOSEREPLY	0x02
++#define	XPC_IPI_OPENREQUEST	0x04
++#define	XPC_IPI_OPENREPLY	0x08
++#define	XPC_IPI_MSGREQUEST	0x10
++
++/* given an AMO variable and a channel#, get its associated IPI flags */
++#define XPC_GET_IPI_FLAGS(_amo, _c)	((u8) (((_amo) >> ((_c) * 8)) & 0xff))
++#define XPC_SET_IPI_FLAGS(_amo, _c, _f)	(_amo) |= ((u64) (_f) << ((_c) * 8))
++
++#define	XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0fUL)
++#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010UL)
++
++static inline void
++xpc_IPI_send_closerequest(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++	struct xpc_openclose_args *args = ch->local_openclose_args;
++
++	args->reason = ch->reason;
++
++	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREQUEST, irq_flags);
++}
++
++static inline void
++xpc_IPI_send_closereply(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREPLY, irq_flags);
++}
++
++static inline void
++xpc_IPI_send_openrequest(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++	struct xpc_openclose_args *args = ch->local_openclose_args;
++
++	args->msg_size = ch->msg_size;
++	args->local_nentries = ch->local_nentries;
++
++	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREQUEST, irq_flags);
++}
++
++static inline void
++xpc_IPI_send_openreply(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++	struct xpc_openclose_args *args = ch->local_openclose_args;
++
++	args->remote_nentries = ch->remote_nentries;
++	args->local_nentries = ch->local_nentries;
++	args->local_msgqueue_pa = __pa(ch->local_msgqueue);
++
++	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREPLY, irq_flags);
++}
++
++static inline void
++xpc_IPI_send_msgrequest(struct xpc_channel *ch)
++{
++	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_MSGREQUEST, NULL);
++}
++
++static inline void
++xpc_IPI_send_local_msgrequest(struct xpc_channel *ch)
++{
++	XPC_NOTIFY_IRQ_SEND_LOCAL(ch, XPC_IPI_MSGREQUEST);
++}
++
++/*
++ * Memory for XPC's AMO variables is allocated by the MSPEC driver. These
++ * pages are located in the lowest granule. The lowest granule uses 4k pages
++ * for cached references and an alternate TLB handler to never provide a
++ * cacheable mapping for the entire region. This will prevent speculative
++ * reading of cached copies of our lines from being issued which will cause
++ * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
++ * AMO variables (based on XP_MAX_PARTITIONS) for message notification and an
++ * additional 128 AMO variables (based on XP_NASID_MASK_WORDS) for partition
++ * activation and 2 AMO variables for partition deactivation.
++ */
++static inline AMO_t *
++xpc_IPI_init(int index)
++{
++	AMO_t *amo = xpc_vars->amos_page + index;
++
++	(void)xpc_IPI_receive(amo);	/* clear AMO variable */
++	return amo;
++}
++
++static inline enum xpc_retval
++xpc_map_bte_errors(bte_result_t error)
++{
++	if (error == BTE_SUCCESS)
++		return xpcSuccess;
++
++	if (is_shub2()) {
++		if (BTE_VALID_SH2_ERROR(error))
++			return xpcBteSh2Start + error;
++		return xpcBteUnmappedError;
++	}
++	switch (error) {
++	case BTE_SUCCESS:
++		return xpcSuccess;
++	case BTEFAIL_DIR:
++		return xpcBteDirectoryError;
++	case BTEFAIL_POISON:
++		return xpcBtePoisonError;
++	case BTEFAIL_WERR:
++		return xpcBteWriteError;
++	case BTEFAIL_ACCESS:
++		return xpcBteAccessError;
++	case BTEFAIL_PWERR:
++		return xpcBtePWriteError;
++	case BTEFAIL_PRERR:
++		return xpcBtePReadError;
++	case BTEFAIL_TOUT:
++		return xpcBteTimeOutError;
++	case BTEFAIL_XTERR:
++		return xpcBteXtalkError;
++	case BTEFAIL_NOTAVAIL:
++		return xpcBteNotAvailable;
++	default:
++		return xpcBteUnmappedError;
++	}
++}
++
++/*
++ * Check to see if there is any channel activity to/from the specified
++ * partition.
++ */
++static inline void
++xpc_check_for_channel_activity(struct xpc_partition *part)
++{
++	u64 IPI_amo;
++	unsigned long irq_flags;
++
++	IPI_amo = xpc_IPI_receive(part->local_IPI_amo_va);
++	if (IPI_amo == 0)
++		return;
++
++	spin_lock_irqsave(&part->IPI_lock, irq_flags);
++	part->local_IPI_amo |= IPI_amo;
++	spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
++
++	dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n",
++		XPC_PARTID(part), IPI_amo);
++
++	xpc_wakeup_channel_mgr(part);
++}
++
++#endif /* _DRIVERS_MISC_SGIXP_XPC_H */
+diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c
+new file mode 100644
+index 0000000..bfcb9ea
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpc_channel.c
+@@ -0,0 +1,2243 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
++ */
++
++/*
++ * Cross Partition Communication (XPC) channel support.
++ *
++ *	This is the part of XPC that manages the channels and
++ *	sends/receives messages across them to/from other partitions.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/mutex.h>
++#include <linux/completion.h>
++#include <asm/sn/bte.h>
++#include <asm/sn/sn_sal.h>
++#include "xpc.h"
++
++/*
++ * Guarantee that the kzalloc'd memory is cacheline aligned.
++ */
++static void *
++xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
++{
++	/* see if kzalloc will give us cachline aligned memory by default */
++	*base = kzalloc(size, flags);
++	if (*base == NULL)
++		return NULL;
++
++	if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
++		return *base;
++
++	kfree(*base);
++
++	/* nope, we'll have to do it ourselves */
++	*base = kzalloc(size + L1_CACHE_BYTES, flags);
++	if (*base == NULL)
++		return NULL;
++
++	return (void *)L1_CACHE_ALIGN((u64)*base);
++}
++
++/*
++ * Set up the initial values for the XPartition Communication channels.
++ */
++static void
++xpc_initialize_channels(struct xpc_partition *part, partid_t partid)
++{
++	int ch_number;
++	struct xpc_channel *ch;
++
++	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
++		ch = &part->channels[ch_number];
++
++		ch->partid = partid;
++		ch->number = ch_number;
++		ch->flags = XPC_C_DISCONNECTED;
++
++		ch->local_GP = &part->local_GPs[ch_number];
++		ch->local_openclose_args =
++		    &part->local_openclose_args[ch_number];
++
++		atomic_set(&ch->kthreads_assigned, 0);
++		atomic_set(&ch->kthreads_idle, 0);
++		atomic_set(&ch->kthreads_active, 0);
++
++		atomic_set(&ch->references, 0);
++		atomic_set(&ch->n_to_notify, 0);
++
++		spin_lock_init(&ch->lock);
++		mutex_init(&ch->msg_to_pull_mutex);
++		init_completion(&ch->wdisconnect_wait);
++
++		atomic_set(&ch->n_on_msg_allocate_wq, 0);
++		init_waitqueue_head(&ch->msg_allocate_wq);
++		init_waitqueue_head(&ch->idle_wq);
++	}
++}
++
++/*
++ * Setup the infrastructure necessary to support XPartition Communication
++ * between the specified remote partition and the local one.
++ */
++enum xpc_retval
++xpc_setup_infrastructure(struct xpc_partition *part)
++{
++	int ret, cpuid;
++	struct timer_list *timer;
++	partid_t partid = XPC_PARTID(part);
++
++	/*
++	 * Zero out MOST of the entry for this partition. Only the fields
++	 * starting with `nchannels' will be zeroed. The preceding fields must
++	 * remain `viable' across partition ups and downs, since they may be
++	 * referenced during this memset() operation.
++	 */
++	memset(&part->nchannels, 0, sizeof(struct xpc_partition) -
++	       offsetof(struct xpc_partition, nchannels));
++
++	/*
++	 * Allocate all of the channel structures as a contiguous chunk of
++	 * memory.
++	 */
++	part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
++				 GFP_KERNEL);
++	if (part->channels == NULL) {
++		dev_err(xpc_chan, "can't get memory for channels\n");
++		return xpcNoMemory;
++	}
++
++	part->nchannels = XPC_NCHANNELS;
++
++	/* allocate all the required GET/PUT values */
++
++	part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
++							GFP_KERNEL,
++							&part->local_GPs_base);
++	if (part->local_GPs == NULL) {
++		kfree(part->channels);
++		part->channels = NULL;
++		dev_err(xpc_chan, "can't get memory for local get/put "
++			"values\n");
++		return xpcNoMemory;
++	}
++
++	part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
++							 GFP_KERNEL,
++							 &part->
++							 remote_GPs_base);
++	if (part->remote_GPs == NULL) {
++		dev_err(xpc_chan, "can't get memory for remote get/put "
++			"values\n");
++		kfree(part->local_GPs_base);
++		part->local_GPs = NULL;
++		kfree(part->channels);
++		part->channels = NULL;
++		return xpcNoMemory;
++	}
++
++	/* allocate all the required open and close args */
++
++	part->local_openclose_args =
++	    xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
++					  &part->local_openclose_args_base);
++	if (part->local_openclose_args == NULL) {
++		dev_err(xpc_chan, "can't get memory for local connect args\n");
++		kfree(part->remote_GPs_base);
++		part->remote_GPs = NULL;
++		kfree(part->local_GPs_base);
++		part->local_GPs = NULL;
++		kfree(part->channels);
++		part->channels = NULL;
++		return xpcNoMemory;
++	}
++
++	part->remote_openclose_args =
++	    xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
++					  &part->remote_openclose_args_base);
++	if (part->remote_openclose_args == NULL) {
++		dev_err(xpc_chan, "can't get memory for remote connect args\n");
++		kfree(part->local_openclose_args_base);
++		part->local_openclose_args = NULL;
++		kfree(part->remote_GPs_base);
++		part->remote_GPs = NULL;
++		kfree(part->local_GPs_base);
++		part->local_GPs = NULL;
++		kfree(part->channels);
++		part->channels = NULL;
++		return xpcNoMemory;
++	}
++
++	xpc_initialize_channels(part, partid);
++
++	atomic_set(&part->nchannels_active, 0);
++	atomic_set(&part->nchannels_engaged, 0);
++
++	/* local_IPI_amo were set to 0 by an earlier memset() */
++
++	/* Initialize this partitions AMO_t structure */
++	part->local_IPI_amo_va = xpc_IPI_init(partid);
++
++	spin_lock_init(&part->IPI_lock);
++
++	atomic_set(&part->channel_mgr_requests, 1);
++	init_waitqueue_head(&part->channel_mgr_wq);
++
++	sprintf(part->IPI_owner, "xpc%02d", partid);
++	ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, IRQF_SHARED,
++			  part->IPI_owner, (void *)(u64)partid);
++	if (ret != 0) {
++		dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
++			"errno=%d\n", -ret);
++		kfree(part->remote_openclose_args_base);
++		part->remote_openclose_args = NULL;
++		kfree(part->local_openclose_args_base);
++		part->local_openclose_args = NULL;
++		kfree(part->remote_GPs_base);
++		part->remote_GPs = NULL;
++		kfree(part->local_GPs_base);
++		part->local_GPs = NULL;
++		kfree(part->channels);
++		part->channels = NULL;
++		return xpcLackOfResources;
++	}
++
++	/* Setup a timer to check for dropped IPIs */
++	timer = &part->dropped_IPI_timer;
++	init_timer(timer);
++	timer->function = (void (*)(unsigned long))xpc_dropped_IPI_check;
++	timer->data = (unsigned long)part;
++	timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT;
++	add_timer(timer);
++
++	/*
++	 * With the setting of the partition setup_state to XPC_P_SETUP, we're
++	 * declaring that this partition is ready to go.
++	 */
++	part->setup_state = XPC_P_SETUP;
++
++	/*
++	 * Setup the per partition specific variables required by the
++	 * remote partition to establish channel connections with us.
++	 *
++	 * The setting of the magic # indicates that these per partition
++	 * specific variables are ready to be used.
++	 */
++	xpc_vars_part[partid].GPs_pa = __pa(part->local_GPs);
++	xpc_vars_part[partid].openclose_args_pa =
++	    __pa(part->local_openclose_args);
++	xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va);
++	cpuid = raw_smp_processor_id();	/* any CPU in this partition will do */
++	xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(cpuid);
++	xpc_vars_part[partid].IPI_phys_cpuid = cpu_physical_id(cpuid);
++	xpc_vars_part[partid].nchannels = part->nchannels;
++	xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
++
++	return xpcSuccess;
++}
++
++/*
++ * Create a wrapper that hides the underlying mechanism for pulling a cacheline
++ * (or multiple cachelines) from a remote partition.
++ *
++ * src must be a cacheline aligned physical address on the remote partition.
++ * dst must be a cacheline aligned virtual address on this partition.
++ * cnt must be an cacheline sized
++ */
++static enum xpc_retval
++xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst,
++			   const void *src, size_t cnt)
++{
++	bte_result_t bte_ret;
++
++	DBUG_ON((u64)src != L1_CACHE_ALIGN((u64)src));
++	DBUG_ON((u64)dst != L1_CACHE_ALIGN((u64)dst));
++	DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
++
++	if (part->act_state == XPC_P_DEACTIVATING)
++		return part->reason;
++
++	bte_ret = xp_bte_copy((u64)src, (u64)dst, (u64)cnt,
++			      (BTE_NORMAL | BTE_WACQUIRE), NULL);
++	if (bte_ret == BTE_SUCCESS)
++		return xpcSuccess;
++
++	dev_dbg(xpc_chan, "xp_bte_copy() from partition %d failed, ret=%d\n",
++		XPC_PARTID(part), bte_ret);
++
++	return xpc_map_bte_errors(bte_ret);
++}
++
++/*
++ * Pull the remote per partition specific variables from the specified
++ * partition.
++ */
++enum xpc_retval
++xpc_pull_remote_vars_part(struct xpc_partition *part)
++{
++	u8 buffer[L1_CACHE_BYTES * 2];
++	struct xpc_vars_part *pulled_entry_cacheline =
++	    (struct xpc_vars_part *)L1_CACHE_ALIGN((u64)buffer);
++	struct xpc_vars_part *pulled_entry;
++	u64 remote_entry_cacheline_pa, remote_entry_pa;
++	partid_t partid = XPC_PARTID(part);
++	enum xpc_retval ret;
++
++	/* pull the cacheline that contains the variables we're interested in */
++
++	DBUG_ON(part->remote_vars_part_pa !=
++		L1_CACHE_ALIGN(part->remote_vars_part_pa));
++	DBUG_ON(sizeof(struct xpc_vars_part) != L1_CACHE_BYTES / 2);
++
++	remote_entry_pa = part->remote_vars_part_pa +
++	    sn_partition_id * sizeof(struct xpc_vars_part);
++
++	remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
++
++	pulled_entry = (struct xpc_vars_part *)((u64)pulled_entry_cacheline +
++						(remote_entry_pa &
++						 (L1_CACHE_BYTES - 1)));
++
++	ret = xpc_pull_remote_cachelines(part, pulled_entry_cacheline,
++					 (void *)remote_entry_cacheline_pa,
++					 L1_CACHE_BYTES);
++	if (ret != xpcSuccess) {
++		dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
++			"partition %d, ret=%d\n", partid, ret);
++		return ret;
++	}
++
++	/* see if they've been set up yet */
++
++	if (pulled_entry->magic != XPC_VP_MAGIC1 &&
++	    pulled_entry->magic != XPC_VP_MAGIC2) {
++
++		if (pulled_entry->magic != 0) {
++			dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
++				"partition %d has bad magic value (=0x%lx)\n",
++				partid, sn_partition_id, pulled_entry->magic);
++			return xpcBadMagic;
++		}
++
++		/* they've not been initialized yet */
++		return xpcRetry;
++	}
++
++	if (xpc_vars_part[partid].magic == XPC_VP_MAGIC1) {
++
++		/* validate the variables */
++
++		if (pulled_entry->GPs_pa == 0 ||
++		    pulled_entry->openclose_args_pa == 0 ||
++		    pulled_entry->IPI_amo_pa == 0) {
++
++			dev_err(xpc_chan, "partition %d's XPC vars_part for "
++				"partition %d are not valid\n", partid,
++				sn_partition_id);
++			return xpcInvalidAddress;
++		}
++
++		/* the variables we imported look to be valid */
++
++		part->remote_GPs_pa = pulled_entry->GPs_pa;
++		part->remote_openclose_args_pa =
++		    pulled_entry->openclose_args_pa;
++		part->remote_IPI_amo_va =
++		    (AMO_t *)__va(pulled_entry->IPI_amo_pa);
++		part->remote_IPI_nasid = pulled_entry->IPI_nasid;
++		part->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid;
++
++		if (part->nchannels > pulled_entry->nchannels)
++			part->nchannels = pulled_entry->nchannels;
++
++		/* let the other side know that we've pulled their variables */
++
++		xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
++	}
++
++	if (pulled_entry->magic == XPC_VP_MAGIC1)
++		return xpcRetry;
++
++	return xpcSuccess;
++}
++
++/*
++ * Get the IPI flags and pull the openclose args and/or remote GPs as needed.
++ */
++static u64
++xpc_get_IPI_flags(struct xpc_partition *part)
++{
++	unsigned long irq_flags;
++	u64 IPI_amo;
++	enum xpc_retval ret;
++
++	/*
++	 * See if there are any IPI flags to be handled.
++	 */
++
++	spin_lock_irqsave(&part->IPI_lock, irq_flags);
++	IPI_amo = part->local_IPI_amo;
++	if (IPI_amo != 0)
++		part->local_IPI_amo = 0;
++
++	spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
++
++	if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) {
++		ret = xpc_pull_remote_cachelines(part,
++						 part->remote_openclose_args,
++						 (void *)part->
++						 remote_openclose_args_pa,
++						 XPC_OPENCLOSE_ARGS_SIZE);
++		if (ret != xpcSuccess) {
++			XPC_DEACTIVATE_PARTITION(part, ret);
++
++			dev_dbg(xpc_chan, "failed to pull openclose args from "
++				"partition %d, ret=%d\n", XPC_PARTID(part),
++				ret);
++
++			/* don't bother processing IPIs anymore */
++			IPI_amo = 0;
++		}
++	}
++
++	if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) {
++		ret = xpc_pull_remote_cachelines(part, part->remote_GPs,
++						 (void *)part->remote_GPs_pa,
++						 XPC_GP_SIZE);
++		if (ret != xpcSuccess) {
++			XPC_DEACTIVATE_PARTITION(part, ret);
++
++			dev_dbg(xpc_chan, "failed to pull GPs from partition "
++				"%d, ret=%d\n", XPC_PARTID(part), ret);
++
++			/* don't bother processing IPIs anymore */
++			IPI_amo = 0;
++		}
++	}
++
++	return IPI_amo;
++}
++
++/*
++ * Allocate the local message queue and the notify queue.
++ */
++static enum xpc_retval
++xpc_allocate_local_msgqueue(struct xpc_channel *ch)
++{
++	unsigned long irq_flags;
++	int nentries;
++	size_t nbytes;
++
++	for (nentries = ch->local_nentries; nentries > 0; nentries--) {
++
++		nbytes = nentries * ch->msg_size;
++		ch->local_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
++								   GFP_KERNEL,
++						      &ch->local_msgqueue_base);
++		if (ch->local_msgqueue == NULL)
++			continue;
++
++		nbytes = nentries * sizeof(struct xpc_notify);
++		ch->notify_queue = kzalloc(nbytes, GFP_KERNEL);
++		if (ch->notify_queue == NULL) {
++			kfree(ch->local_msgqueue_base);
++			ch->local_msgqueue = NULL;
++			continue;
++		}
++
++		spin_lock_irqsave(&ch->lock, irq_flags);
++		if (nentries < ch->local_nentries) {
++			dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
++				"partid=%d, channel=%d\n", nentries,
++				ch->local_nentries, ch->partid, ch->number);
++
++			ch->local_nentries = nentries;
++		}
++		spin_unlock_irqrestore(&ch->lock, irq_flags);
++		return xpcSuccess;
++	}
++
++	dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
++		"queue, partid=%d, channel=%d\n", ch->partid, ch->number);
++	return xpcNoMemory;
++}
++
++/*
++ * Allocate the cached remote message queue.
++ */
++static enum xpc_retval
++xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
++{
++	unsigned long irq_flags;
++	int nentries;
++	size_t nbytes;
++
++	DBUG_ON(ch->remote_nentries <= 0);
++
++	for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
++
++		nbytes = nentries * ch->msg_size;
++		ch->remote_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
++								    GFP_KERNEL,
++						     &ch->remote_msgqueue_base);
++		if (ch->remote_msgqueue == NULL)
++			continue;
++
++		spin_lock_irqsave(&ch->lock, irq_flags);
++		if (nentries < ch->remote_nentries) {
++			dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
++				"partid=%d, channel=%d\n", nentries,
++				ch->remote_nentries, ch->partid, ch->number);
++
++			ch->remote_nentries = nentries;
++		}
++		spin_unlock_irqrestore(&ch->lock, irq_flags);
++		return xpcSuccess;
++	}
++
++	dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
++		"partid=%d, channel=%d\n", ch->partid, ch->number);
++	return xpcNoMemory;
++}
++
++/*
++ * Allocate message queues and other stuff associated with a channel.
++ *
++ * Note: Assumes all of the channel sizes are filled in.
++ */
++static enum xpc_retval
++xpc_allocate_msgqueues(struct xpc_channel *ch)
++{
++	unsigned long irq_flags;
++	enum xpc_retval ret;
++
++	DBUG_ON(ch->flags & XPC_C_SETUP);
++
++	ret = xpc_allocate_local_msgqueue(ch);
++	if (ret != xpcSuccess)
++		return ret;
++
++	ret = xpc_allocate_remote_msgqueue(ch);
++	if (ret != xpcSuccess) {
++		kfree(ch->local_msgqueue_base);
++		ch->local_msgqueue = NULL;
++		kfree(ch->notify_queue);
++		ch->notify_queue = NULL;
++		return ret;
++	}
++
++	spin_lock_irqsave(&ch->lock, irq_flags);
++	ch->flags |= XPC_C_SETUP;
++	spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++	return xpcSuccess;
++}
++
++/*
++ * Process a connect message from a remote partition.
++ *
++ * Note: xpc_process_connect() is expecting to be called with the
++ * spin_lock_irqsave held and will leave it locked upon return.
++ */
++static void
++xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++	enum xpc_retval ret;
++
++	DBUG_ON(!spin_is_locked(&ch->lock));
++
++	if (!(ch->flags & XPC_C_OPENREQUEST) ||
++	    !(ch->flags & XPC_C_ROPENREQUEST)) {
++		/* nothing more to do for now */
++		return;
++	}
++	DBUG_ON(!(ch->flags & XPC_C_CONNECTING));
++
++	if (!(ch->flags & XPC_C_SETUP)) {
++		spin_unlock_irqrestore(&ch->lock, *irq_flags);
++		ret = xpc_allocate_msgqueues(ch);
++		spin_lock_irqsave(&ch->lock, *irq_flags);
++
++		if (ret != xpcSuccess)
++			XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);
++
++		if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING))
++			return;
++
++		DBUG_ON(!(ch->flags & XPC_C_SETUP));
++		DBUG_ON(ch->local_msgqueue == NULL);
++		DBUG_ON(ch->remote_msgqueue == NULL);
++	}
++
++	if (!(ch->flags & XPC_C_OPENREPLY)) {
++		ch->flags |= XPC_C_OPENREPLY;
++		xpc_IPI_send_openreply(ch, irq_flags);
++	}
++
++	if (!(ch->flags & XPC_C_ROPENREPLY))
++		return;
++
++	DBUG_ON(ch->remote_msgqueue_pa == 0);
++
++	ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP);	/* clear all else */
++
++	dev_info(xpc_chan, "channel %d to partition %d connected\n",
++		 ch->number, ch->partid);
++
++	spin_unlock_irqrestore(&ch->lock, *irq_flags);
++	xpc_create_kthreads(ch, 1, 0);
++	spin_lock_irqsave(&ch->lock, *irq_flags);
++}
++
++/*
++ * Notify those who wanted to be notified upon delivery of their message.
++ */
++static void
++xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
++{
++	struct xpc_notify *notify;
++	u8 notify_type;
++	s64 get = ch->w_remote_GP.get - 1;
++
++	while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
++
++		notify = &ch->notify_queue[get % ch->local_nentries];
++
++		/*
++		 * See if the notify entry indicates it was associated with
++		 * a message who's sender wants to be notified. It is possible
++		 * that it is, but someone else is doing or has done the
++		 * notification.
++		 */
++		notify_type = notify->type;
++		if (notify_type == 0 ||
++		    cmpxchg(&notify->type, notify_type, 0) != notify_type) {
++			continue;
++		}
++
++		DBUG_ON(notify_type != XPC_N_CALL);
++
++		atomic_dec(&ch->n_to_notify);
++
++		if (notify->func != NULL) {
++			dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
++				"msg_number=%ld, partid=%d, channel=%d\n",
++				(void *)notify, get, ch->partid, ch->number);
++
++			notify->func(reason, ch->partid, ch->number,
++				     notify->key);
++
++			dev_dbg(xpc_chan, "notify->func() returned, "
++				"notify=0x%p, msg_number=%ld, partid=%d, "
++				"channel=%d\n", (void *)notify, get,
++				ch->partid, ch->number);
++		}
++	}
++}
++
++/*
++ * Free up message queues and other stuff that were allocated for the specified
++ * channel.
++ *
++ * Note: ch->reason and ch->reason_line are left set for debugging purposes,
++ * they're cleared when XPC_C_DISCONNECTED is cleared.
++ */
++static void
++xpc_free_msgqueues(struct xpc_channel *ch)
++{
++	DBUG_ON(!spin_is_locked(&ch->lock));
++	DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
++
++	ch->remote_msgqueue_pa = 0;
++	ch->func = NULL;
++	ch->key = NULL;
++	ch->msg_size = 0;
++	ch->local_nentries = 0;
++	ch->remote_nentries = 0;
++	ch->kthreads_assigned_limit = 0;
++	ch->kthreads_idle_limit = 0;
++
++	ch->local_GP->get = 0;
++	ch->local_GP->put = 0;
++	ch->remote_GP.get = 0;
++	ch->remote_GP.put = 0;
++	ch->w_local_GP.get = 0;
++	ch->w_local_GP.put = 0;
++	ch->w_remote_GP.get = 0;
++	ch->w_remote_GP.put = 0;
++	ch->next_msg_to_pull = 0;
++
++	if (ch->flags & XPC_C_SETUP) {
++		ch->flags &= ~XPC_C_SETUP;
++
++		dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
++			ch->flags, ch->partid, ch->number);
++
++		kfree(ch->local_msgqueue_base);
++		ch->local_msgqueue = NULL;
++		kfree(ch->remote_msgqueue_base);
++		ch->remote_msgqueue = NULL;
++		kfree(ch->notify_queue);
++		ch->notify_queue = NULL;
++	}
++}
++
++/*
++ * spin_lock_irqsave() is expected to be held on entry.
++ */
++static void
++xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++	struct xpc_partition *part = &xpc_partitions[ch->partid];
++	u32 channel_was_connected = (ch->flags & XPC_C_WASCONNECTED);
++
++	DBUG_ON(!spin_is_locked(&ch->lock));
++
++	if (!(ch->flags & XPC_C_DISCONNECTING))
++		return;
++
++	DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
++
++	/* make sure all activity has settled down first */
++
++	if (atomic_read(&ch->kthreads_assigned) > 0 ||
++	    atomic_read(&ch->references) > 0) {
++		return;
++	}
++	DBUG_ON((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
++		!(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE));
++
++	if (part->act_state == XPC_P_DEACTIVATING) {
++		/* can't proceed until the other side disengages from us */
++		if (xpc_partition_engaged(1UL << ch->partid))
++			return;
++
++	} else {
++
++		/* as long as the other side is up do the full protocol */
++
++		if (!(ch->flags & XPC_C_RCLOSEREQUEST))
++			return;
++
++		if (!(ch->flags & XPC_C_CLOSEREPLY)) {
++			ch->flags |= XPC_C_CLOSEREPLY;
++			xpc_IPI_send_closereply(ch, irq_flags);
++		}
++
++		if (!(ch->flags & XPC_C_RCLOSEREPLY))
++			return;
++	}
++
++	/* wake those waiting for notify completion */
++	if (atomic_read(&ch->n_to_notify) > 0) {
++		/* >>> we do callout while holding ch->lock */
++		xpc_notify_senders(ch, ch->reason, ch->w_local_GP.put);
++	}
++
++	/* both sides are disconnected now */
++
++	if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) {
++		spin_unlock_irqrestore(&ch->lock, *irq_flags);
++		xpc_disconnect_callout(ch, xpcDisconnected);
++		spin_lock_irqsave(&ch->lock, *irq_flags);
++	}
++
++	/* it's now safe to free the channel's message queues */
++	xpc_free_msgqueues(ch);
++
++	/* mark disconnected, clear all other flags except XPC_C_WDISCONNECT */
++	ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT));
++
++	atomic_dec(&part->nchannels_active);
++
++	if (channel_was_connected) {
++		dev_info(xpc_chan, "channel %d to partition %d disconnected, "
++			 "reason=%d\n", ch->number, ch->partid, ch->reason);
++	}
++
++	if (ch->flags & XPC_C_WDISCONNECT) {
++		/* we won't lose the CPU since we're holding ch->lock */
++		complete(&ch->wdisconnect_wait);
++	} else if (ch->delayed_IPI_flags) {
++		if (part->act_state != XPC_P_DEACTIVATING) {
++			/* time to take action on any delayed IPI flags */
++			spin_lock(&part->IPI_lock);
++			XPC_SET_IPI_FLAGS(part->local_IPI_amo, ch->number,
++					  ch->delayed_IPI_flags);
++			spin_unlock(&part->IPI_lock);
++		}
++		ch->delayed_IPI_flags = 0;
++	}
++}
++
++/*
++ * Process a change in the channel's remote connection state.
++ */
++static void
++xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
++			  u8 IPI_flags)
++{
++	unsigned long irq_flags;
++	struct xpc_openclose_args *args =
++	    &part->remote_openclose_args[ch_number];
++	struct xpc_channel *ch = &part->channels[ch_number];
++	enum xpc_retval reason;
++
++	spin_lock_irqsave(&ch->lock, irq_flags);
++
++again:
++
++	if ((ch->flags & XPC_C_DISCONNECTED) &&
++	    (ch->flags & XPC_C_WDISCONNECT)) {
++		/*
++		 * Delay processing IPI flags until thread waiting disconnect
++		 * has had a chance to see that the channel is disconnected.
++		 */
++		ch->delayed_IPI_flags |= IPI_flags;
++		spin_unlock_irqrestore(&ch->lock, irq_flags);
++		return;
++	}
++
++	if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
++
++		dev_dbg(xpc_chan, "XPC_IPI_CLOSEREQUEST (reason=%d) received "
++			"from partid=%d, channel=%d\n", args->reason,
++			ch->partid, ch->number);
++
++		/*
++		 * If RCLOSEREQUEST is set, we're probably waiting for
++		 * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
++		 * with this RCLOSEREQUEST in the IPI_flags.
++		 */
++
++		if (ch->flags & XPC_C_RCLOSEREQUEST) {
++			DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
++			DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
++			DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));
++			DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);
++
++			DBUG_ON(!(IPI_flags & XPC_IPI_CLOSEREPLY));
++			IPI_flags &= ~XPC_IPI_CLOSEREPLY;
++			ch->flags |= XPC_C_RCLOSEREPLY;
++
++			/* both sides have finished disconnecting */
++			xpc_process_disconnect(ch, &irq_flags);
++			DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
++			goto again;
++		}
++
++		if (ch->flags & XPC_C_DISCONNECTED) {
++			if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
++				if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo,
++						       ch_number) &
++				     XPC_IPI_OPENREQUEST)) {
++
++					DBUG_ON(ch->delayed_IPI_flags != 0);
++					spin_lock(&part->IPI_lock);
++					XPC_SET_IPI_FLAGS(part->local_IPI_amo,
++							  ch_number,
++							  XPC_IPI_CLOSEREQUEST);
++					spin_unlock(&part->IPI_lock);
++				}
++				spin_unlock_irqrestore(&ch->lock, irq_flags);
++				return;
++			}
++
++			XPC_SET_REASON(ch, 0, 0);
++			ch->flags &= ~XPC_C_DISCONNECTED;
++
++			atomic_inc(&part->nchannels_active);
++			ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
++		}
++
++		IPI_flags &= ~(XPC_IPI_OPENREQUEST | XPC_IPI_OPENREPLY);
++
++		/*
++		 * The meaningful CLOSEREQUEST connection state fields are:
++		 *      reason = reason connection is to be closed
++		 */
++
++		ch->flags |= XPC_C_RCLOSEREQUEST;
++
++		if (!(ch->flags & XPC_C_DISCONNECTING)) {
++			reason = args->reason;
++			if (reason <= xpcSuccess || reason > xpcUnknownReason)
++				reason = xpcUnknownReason;
++			else if (reason == xpcUnregistering)
++				reason = xpcOtherUnregistering;
++
++			XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
++
++			DBUG_ON(IPI_flags & XPC_IPI_CLOSEREPLY);
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			return;
++		}
++
++		xpc_process_disconnect(ch, &irq_flags);
++	}
++
++	if (IPI_flags & XPC_IPI_CLOSEREPLY) {
++
++		dev_dbg(xpc_chan, "XPC_IPI_CLOSEREPLY received from partid=%d,"
++			" channel=%d\n", ch->partid, ch->number);
++
++		if (ch->flags & XPC_C_DISCONNECTED) {
++			DBUG_ON(part->act_state != XPC_P_DEACTIVATING);
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			return;
++		}
++
++		DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
++
++		if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
++			if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo, ch_number)
++			     & XPC_IPI_CLOSEREQUEST)) {
++
++				DBUG_ON(ch->delayed_IPI_flags != 0);
++				spin_lock(&part->IPI_lock);
++				XPC_SET_IPI_FLAGS(part->local_IPI_amo,
++						  ch_number,
++						  XPC_IPI_CLOSEREPLY);
++				spin_unlock(&part->IPI_lock);
++			}
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			return;
++		}
++
++		ch->flags |= XPC_C_RCLOSEREPLY;
++
++		if (ch->flags & XPC_C_CLOSEREPLY) {
++			/* both sides have finished disconnecting */
++			xpc_process_disconnect(ch, &irq_flags);
++		}
++	}
++
++	if (IPI_flags & XPC_IPI_OPENREQUEST) {
++
++		dev_dbg(xpc_chan, "XPC_IPI_OPENREQUEST (msg_size=%d, "
++			"local_nentries=%d) received from partid=%d, "
++			"channel=%d\n", args->msg_size, args->local_nentries,
++			ch->partid, ch->number);
++
++		if (part->act_state == XPC_P_DEACTIVATING ||
++		    (ch->flags & XPC_C_ROPENREQUEST)) {
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			return;
++		}
++
++		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
++			ch->delayed_IPI_flags |= XPC_IPI_OPENREQUEST;
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			return;
++		}
++		DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |
++				       XPC_C_OPENREQUEST)));
++		DBUG_ON(ch->flags & (XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
++				     XPC_C_OPENREPLY | XPC_C_CONNECTED));
++
++		/*
++		 * The meaningful OPENREQUEST connection state fields are:
++		 *      msg_size = size of channel's messages in bytes
++		 *      local_nentries = remote partition's local_nentries
++		 */
++		if (args->msg_size == 0 || args->local_nentries == 0) {
++			/* assume OPENREQUEST was delayed by mistake */
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			return;
++		}
++
++		ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
++		ch->remote_nentries = args->local_nentries;
++
++		if (ch->flags & XPC_C_OPENREQUEST) {
++			if (args->msg_size != ch->msg_size) {
++				XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
++						       &irq_flags);
++				spin_unlock_irqrestore(&ch->lock, irq_flags);
++				return;
++			}
++		} else {
++			ch->msg_size = args->msg_size;
++
++			XPC_SET_REASON(ch, 0, 0);
++			ch->flags &= ~XPC_C_DISCONNECTED;
++
++			atomic_inc(&part->nchannels_active);
++		}
++
++		xpc_process_connect(ch, &irq_flags);
++	}
++
++	if (IPI_flags & XPC_IPI_OPENREPLY) {
++
++		dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY (local_msgqueue_pa=0x%lx, "
++			"local_nentries=%d, remote_nentries=%d) received from "
++			"partid=%d, channel=%d\n", args->local_msgqueue_pa,
++			args->local_nentries, args->remote_nentries,
++			ch->partid, ch->number);
++
++		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			return;
++		}
++		if (!(ch->flags & XPC_C_OPENREQUEST)) {
++			XPC_DISCONNECT_CHANNEL(ch, xpcOpenCloseError,
++					       &irq_flags);
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			return;
++		}
++
++		DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
++		DBUG_ON(ch->flags & XPC_C_CONNECTED);
++
++		/*
++		 * The meaningful OPENREPLY connection state fields are:
++		 *      local_msgqueue_pa = physical address of remote
++		 *                          partition's local_msgqueue
++		 *      local_nentries = remote partition's local_nentries
++		 *      remote_nentries = remote partition's remote_nentries
++		 */
++		DBUG_ON(args->local_msgqueue_pa == 0);
++		DBUG_ON(args->local_nentries == 0);
++		DBUG_ON(args->remote_nentries == 0);
++
++		ch->flags |= XPC_C_ROPENREPLY;
++		ch->remote_msgqueue_pa = args->local_msgqueue_pa;
++
++		if (args->local_nentries < ch->remote_nentries) {
++			dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
++				"remote_nentries=%d, old remote_nentries=%d, "
++				"partid=%d, channel=%d\n",
++				args->local_nentries, ch->remote_nentries,
++				ch->partid, ch->number);
++
++			ch->remote_nentries = args->local_nentries;
++		}
++		if (args->remote_nentries < ch->local_nentries) {
++			dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
++				"local_nentries=%d, old local_nentries=%d, "
++				"partid=%d, channel=%d\n",
++				args->remote_nentries, ch->local_nentries,
++				ch->partid, ch->number);
++
++			ch->local_nentries = args->remote_nentries;
++		}
++
++		xpc_process_connect(ch, &irq_flags);
++	}
++
++	spin_unlock_irqrestore(&ch->lock, irq_flags);
++}
++
++/*
++ * Attempt to establish a channel connection to a remote partition.
++ */
++static enum xpc_retval
++xpc_connect_channel(struct xpc_channel *ch)
++{
++	unsigned long irq_flags;
++	struct xpc_registration *registration = &xpc_registrations[ch->number];
++
++	if (mutex_trylock(&registration->mutex) == 0)
++		return xpcRetry;
++
++	if (!XPC_CHANNEL_REGISTERED(ch->number)) {
++		mutex_unlock(&registration->mutex);
++		return xpcUnregistered;
++	}
++
++	spin_lock_irqsave(&ch->lock, irq_flags);
++
++	DBUG_ON(ch->flags & XPC_C_CONNECTED);
++	DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
++
++	if (ch->flags & XPC_C_DISCONNECTING) {
++		spin_unlock_irqrestore(&ch->lock, irq_flags);
++		mutex_unlock(&registration->mutex);
++		return ch->reason;
++	}
++
++	/* add info from the channel connect registration to the channel */
++
++	ch->kthreads_assigned_limit = registration->assigned_limit;
++	ch->kthreads_idle_limit = registration->idle_limit;
++	DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
++	DBUG_ON(atomic_read(&ch->kthreads_idle) != 0);
++	DBUG_ON(atomic_read(&ch->kthreads_active) != 0);
++
++	ch->func = registration->func;
++	DBUG_ON(registration->func == NULL);
++	ch->key = registration->key;
++
++	ch->local_nentries = registration->nentries;
++
++	if (ch->flags & XPC_C_ROPENREQUEST) {
++		if (registration->msg_size != ch->msg_size) {
++			/* the local and remote sides aren't the same */
++
++			/*
++			 * Because XPC_DISCONNECT_CHANNEL() can block we're
++			 * forced to up the registration sema before we unlock
++			 * the channel lock. But that's okay here because we're
++			 * done with the part that required the registration
++			 * sema. XPC_DISCONNECT_CHANNEL() requires that the
++			 * channel lock be locked and will unlock and relock
++			 * the channel lock as needed.
++			 */
++			mutex_unlock(&registration->mutex);
++			XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
++					       &irq_flags);
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			return xpcUnequalMsgSizes;
++		}
++	} else {
++		ch->msg_size = registration->msg_size;
++
++		XPC_SET_REASON(ch, 0, 0);
++		ch->flags &= ~XPC_C_DISCONNECTED;
++
++		atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
++	}
++
++	mutex_unlock(&registration->mutex);
++
++	/* initiate the connection */
++
++	ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
++	xpc_IPI_send_openrequest(ch, &irq_flags);
++
++	xpc_process_connect(ch, &irq_flags);
++
++	spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++	return xpcSuccess;
++}
++
++/*
++ * Clear some of the msg flags in the local message queue.
++ */
++static inline void
++xpc_clear_local_msgqueue_flags(struct xpc_channel *ch)
++{
++	struct xpc_msg *msg;
++	s64 get;
++
++	get = ch->w_remote_GP.get;
++	do {
++		msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
++					 (get % ch->local_nentries) *
++					 ch->msg_size);
++		msg->flags = 0;
++	} while (++get < ch->remote_GP.get);
++}
++
++/*
++ * Clear some of the msg flags in the remote message queue.
++ */
++static inline void
++xpc_clear_remote_msgqueue_flags(struct xpc_channel *ch)
++{
++	struct xpc_msg *msg;
++	s64 put;
++
++	put = ch->w_remote_GP.put;
++	do {
++		msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
++					 (put % ch->remote_nentries) *
++					 ch->msg_size);
++		msg->flags = 0;
++	} while (++put < ch->remote_GP.put);
++}
++
++static void
++xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
++{
++	struct xpc_channel *ch = &part->channels[ch_number];
++	int nmsgs_sent;
++
++	ch->remote_GP = part->remote_GPs[ch_number];
++
++	/* See what, if anything, has changed for each connected channel */
++
++	xpc_msgqueue_ref(ch);
++
++	if (ch->w_remote_GP.get == ch->remote_GP.get &&
++	    ch->w_remote_GP.put == ch->remote_GP.put) {
++		/* nothing changed since GPs were last pulled */
++		xpc_msgqueue_deref(ch);
++		return;
++	}
++
++	if (!(ch->flags & XPC_C_CONNECTED)) {
++		xpc_msgqueue_deref(ch);
++		return;
++	}
++
++	/*
++	 * First check to see if messages recently sent by us have been
++	 * received by the other side. (The remote GET value will have
++	 * changed since we last looked at it.)
++	 */
++
++	if (ch->w_remote_GP.get != ch->remote_GP.get) {
++
++		/*
++		 * We need to notify any senders that want to be notified
++		 * that their sent messages have been received by their
++		 * intended recipients. We need to do this before updating
++		 * w_remote_GP.get so that we don't allocate the same message
++		 * queue entries prematurely (see xpc_allocate_msg()).
++		 */
++		if (atomic_read(&ch->n_to_notify) > 0) {
++			/*
++			 * Notify senders that messages sent have been
++			 * received and delivered by the other side.
++			 */
++			xpc_notify_senders(ch, xpcMsgDelivered,
++					   ch->remote_GP.get);
++		}
++
++		/*
++		 * Clear msg->flags in previously sent messages, so that
++		 * they're ready for xpc_allocate_msg().
++		 */
++		xpc_clear_local_msgqueue_flags(ch);
++
++		ch->w_remote_GP.get = ch->remote_GP.get;
++
++		dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
++			"channel=%d\n", ch->w_remote_GP.get, ch->partid,
++			ch->number);
++
++		/*
++		 * If anyone was waiting for message queue entries to become
++		 * available, wake them up.
++		 */
++		if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
++			wake_up(&ch->msg_allocate_wq);
++	}
++
++	/*
++	 * Now check for newly sent messages by the other side. (The remote
++	 * PUT value will have changed since we last looked at it.)
++	 */
++
++	if (ch->w_remote_GP.put != ch->remote_GP.put) {
++		/*
++		 * Clear msg->flags in previously received messages, so that
++		 * they're ready for xpc_get_deliverable_msg().
++		 */
++		xpc_clear_remote_msgqueue_flags(ch);
++
++		ch->w_remote_GP.put = ch->remote_GP.put;
++
++		dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
++			"channel=%d\n", ch->w_remote_GP.put, ch->partid,
++			ch->number);
++
++		nmsgs_sent = ch->w_remote_GP.put - ch->w_local_GP.get;
++		if (nmsgs_sent > 0) {
++			dev_dbg(xpc_chan, "msgs waiting to be copied and "
++				"delivered=%d, partid=%d, channel=%d\n",
++				nmsgs_sent, ch->partid, ch->number);
++
++			if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)
++				xpc_activate_kthreads(ch, nmsgs_sent);
++		}
++	}
++
++	xpc_msgqueue_deref(ch);
++}
++
++void
++xpc_process_channel_activity(struct xpc_partition *part)
++{
++	unsigned long irq_flags;
++	u64 IPI_amo, IPI_flags;
++	struct xpc_channel *ch;
++	int ch_number;
++	u32 ch_flags;
++
++	IPI_amo = xpc_get_IPI_flags(part);
++
++	/*
++	 * Initiate channel connections for registered channels.
++	 *
++	 * For each connected channel that has pending messages activate idle
++	 * kthreads and/or create new kthreads as needed.
++	 */
++
++	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
++		ch = &part->channels[ch_number];
++
++		/*
++		 * Process any open or close related IPI flags, and then deal
++		 * with connecting or disconnecting the channel as required.
++		 */
++
++		IPI_flags = XPC_GET_IPI_FLAGS(IPI_amo, ch_number);
++
++		if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_flags))
++			xpc_process_openclose_IPI(part, ch_number, IPI_flags);
++
++		ch_flags = ch->flags;	/* need an atomic snapshot of flags */
++
++		if (ch_flags & XPC_C_DISCONNECTING) {
++			spin_lock_irqsave(&ch->lock, irq_flags);
++			xpc_process_disconnect(ch, &irq_flags);
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++			continue;
++		}
++
++		if (part->act_state == XPC_P_DEACTIVATING)
++			continue;
++
++		if (!(ch_flags & XPC_C_CONNECTED)) {
++			if (!(ch_flags & XPC_C_OPENREQUEST)) {
++				DBUG_ON(ch_flags & XPC_C_SETUP);
++				(void)xpc_connect_channel(ch);
++			} else {
++				spin_lock_irqsave(&ch->lock, irq_flags);
++				xpc_process_connect(ch, &irq_flags);
++				spin_unlock_irqrestore(&ch->lock, irq_flags);
++			}
++			continue;
++		}
++
++		/*
++		 * Process any message related IPI flags, this may involve the
++		 * activation of kthreads to deliver any pending messages sent
++		 * from the other partition.
++		 */
++
++		if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_flags))
++			xpc_process_msg_IPI(part, ch_number);
++	}
++}
++
++/*
++ * XPC's heartbeat code calls this function to inform XPC that a partition is
++ * going down.  XPC responds by tearing down the XPartition Communication
++ * infrastructure used for the just downed partition.
++ *
++ * XPC's heartbeat code will never call this function and xpc_partition_up()
++ * at the same time. Nor will it ever make multiple calls to either function
++ * at the same time.
++ */
++void
++xpc_partition_going_down(struct xpc_partition *part, enum xpc_retval reason)
++{
++	unsigned long irq_flags;
++	int ch_number;
++	struct xpc_channel *ch;
++
++	dev_dbg(xpc_chan, "deactivating partition %d, reason=%d\n",
++		XPC_PARTID(part), reason);
++
++	if (!xpc_part_ref(part)) {
++		/* infrastructure for this partition isn't currently set up */
++		return;
++	}
++
++	/* disconnect channels associated with the partition going down */
++
++	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
++		ch = &part->channels[ch_number];
++
++		xpc_msgqueue_ref(ch);
++		spin_lock_irqsave(&ch->lock, irq_flags);
++
++		XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
++
++		spin_unlock_irqrestore(&ch->lock, irq_flags);
++		xpc_msgqueue_deref(ch);
++	}
++
++	xpc_wakeup_channel_mgr(part);
++
++	xpc_part_deref(part);
++}
++
++/*
++ * Teardown the infrastructure necessary to support XPartition Communication
++ * between the specified remote partition and the local one.
++ */
++void
++xpc_teardown_infrastructure(struct xpc_partition *part)
++{
++	partid_t partid = XPC_PARTID(part);
++
++	/*
++	 * We start off by making this partition inaccessible to local
++	 * processes by marking it as no longer setup. Then we make it
++	 * inaccessible to remote processes by clearing the XPC per partition
++	 * specific variable's magic # (which indicates that these variables
++	 * are no longer valid) and by ignoring all XPC notify IPIs sent to
++	 * this partition.
++	 */
++
++	DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
++	DBUG_ON(atomic_read(&part->nchannels_active) != 0);
++	DBUG_ON(part->setup_state != XPC_P_SETUP);
++	part->setup_state = XPC_P_WTEARDOWN;
++
++	xpc_vars_part[partid].magic = 0;
++
++	free_irq(SGI_XPC_NOTIFY, (void *)(u64)partid);
++
++	/*
++	 * Before proceeding with the teardown we have to wait until all
++	 * existing references cease.
++	 */
++	wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
++
++	/* now we can begin tearing down the infrastructure */
++
++	part->setup_state = XPC_P_TORNDOWN;
++
++	/* in case we've still got outstanding timers registered... */
++	del_timer_sync(&part->dropped_IPI_timer);
++
++	kfree(part->remote_openclose_args_base);
++	part->remote_openclose_args = NULL;
++	kfree(part->local_openclose_args_base);
++	part->local_openclose_args = NULL;
++	kfree(part->remote_GPs_base);
++	part->remote_GPs = NULL;
++	kfree(part->local_GPs_base);
++	part->local_GPs = NULL;
++	kfree(part->channels);
++	part->channels = NULL;
++	part->local_IPI_amo_va = NULL;
++}
++
++/*
++ * Called by XP at the time of channel connection registration to cause
++ * XPC to establish connections to all currently active partitions.
++ */
++void
++xpc_initiate_connect(int ch_number)
++{
++	partid_t partid;
++	struct xpc_partition *part;
++	struct xpc_channel *ch;
++
++	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
++
++	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++		part = &xpc_partitions[partid];
++
++		if (xpc_part_ref(part)) {
++			ch = &part->channels[ch_number];
++
++			/*
++			 * Initiate the establishment of a connection on the
++			 * newly registered channel to the remote partition.
++			 */
++			xpc_wakeup_channel_mgr(part);
++			xpc_part_deref(part);
++		}
++	}
++}
++
++void
++xpc_connected_callout(struct xpc_channel *ch)
++{
++	/* let the registerer know that a connection has been established */
++
++	if (ch->func != NULL) {
++		dev_dbg(xpc_chan, "ch->func() called, reason=xpcConnected, "
++			"partid=%d, channel=%d\n", ch->partid, ch->number);
++
++		ch->func(xpcConnected, ch->partid, ch->number,
++			 (void *)(u64)ch->local_nentries, ch->key);
++
++		dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "
++			"partid=%d, channel=%d\n", ch->partid, ch->number);
++	}
++}
++
++/*
++ * Called by XP at the time of channel connection unregistration to cause
++ * XPC to teardown all current connections for the specified channel.
++ *
++ * Before returning xpc_initiate_disconnect() will wait until all connections
++ * on the specified channel have been closed/torndown. So the caller can be
++ * assured that they will not be receiving any more callouts from XPC to the
++ * function they registered via xpc_connect().
++ *
++ * Arguments:
++ *
++ *	ch_number - channel # to unregister.
++ */
++void
++xpc_initiate_disconnect(int ch_number)
++{
++	unsigned long irq_flags;
++	partid_t partid;
++	struct xpc_partition *part;
++	struct xpc_channel *ch;
++
++	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
++
++	/* initiate the channel disconnect for every active partition */
++	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++		part = &xpc_partitions[partid];
++
++		if (xpc_part_ref(part)) {
++			ch = &part->channels[ch_number];
++			xpc_msgqueue_ref(ch);
++
++			spin_lock_irqsave(&ch->lock, irq_flags);
++
++			if (!(ch->flags & XPC_C_DISCONNECTED)) {
++				ch->flags |= XPC_C_WDISCONNECT;
++
++				XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
++						       &irq_flags);
++			}
++
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++			xpc_msgqueue_deref(ch);
++			xpc_part_deref(part);
++		}
++	}
++
++	xpc_disconnect_wait(ch_number);
++}
++
++/*
++ * To disconnect a channel, and reflect it back to all who may be waiting.
++ *
++ * An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
++ * xpc_process_disconnect(), and if set, XPC_C_WDISCONNECT is cleared by
++ * xpc_disconnect_wait().
++ *
++ * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON RETURN.
++ */
++void
++xpc_disconnect_channel(const int line, struct xpc_channel *ch,
++		       enum xpc_retval reason, unsigned long *irq_flags)
++{
++	u32 channel_was_connected = (ch->flags & XPC_C_CONNECTED);
++
++	DBUG_ON(!spin_is_locked(&ch->lock));
++
++	if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED))
++		return;
++
++	DBUG_ON(!(ch->flags & (XPC_C_CONNECTING | XPC_C_CONNECTED)));
++
++	dev_dbg(xpc_chan, "reason=%d, line=%d, partid=%d, channel=%d\n",
++		reason, line, ch->partid, ch->number);
++
++	XPC_SET_REASON(ch, reason, line);
++
++	ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
++	/* some of these may not have been set */
++	ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |
++		       XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
++		       XPC_C_CONNECTING | XPC_C_CONNECTED);
++
++	xpc_IPI_send_closerequest(ch, irq_flags);
++
++	if (channel_was_connected)
++		ch->flags |= XPC_C_WASCONNECTED;
++
++	spin_unlock_irqrestore(&ch->lock, *irq_flags);
++
++	/* wake all idle kthreads so they can exit */
++	if (atomic_read(&ch->kthreads_idle) > 0) {
++		wake_up_all(&ch->idle_wq);
++
++	} else if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
++		   !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
++		/* start a kthread that will do the xpcDisconnecting callout */
++		xpc_create_kthreads(ch, 1, 1);
++	}
++
++	/* wake those waiting to allocate an entry from the local msg queue */
++	if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
++		wake_up(&ch->msg_allocate_wq);
++
++	spin_lock_irqsave(&ch->lock, *irq_flags);
++}
++
++void
++xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason)
++{
++	/*
++	 * Let the channel's registerer know that the channel is being
++	 * disconnected. We don't want to do this if the registerer was never
++	 * informed of a connection being made.
++	 */
++
++	if (ch->func != NULL) {
++		dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
++			"channel=%d\n", reason, ch->partid, ch->number);
++
++		ch->func(reason, ch->partid, ch->number, NULL, ch->key);
++
++		dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
++			"channel=%d\n", reason, ch->partid, ch->number);
++	}
++}
++
++/*
++ * Wait for a message entry to become available for the specified channel,
++ * but don't wait any longer than 1 jiffy.
++ */
++static enum xpc_retval
++xpc_allocate_msg_wait(struct xpc_channel *ch)
++{
++	enum xpc_retval ret;
++
++	if (ch->flags & XPC_C_DISCONNECTING) {
++		DBUG_ON(ch->reason == xpcInterrupted);
++		return ch->reason;
++	}
++
++	atomic_inc(&ch->n_on_msg_allocate_wq);
++	ret = interruptible_sleep_on_timeout(&ch->msg_allocate_wq, 1);
++	atomic_dec(&ch->n_on_msg_allocate_wq);
++
++	if (ch->flags & XPC_C_DISCONNECTING) {
++		ret = ch->reason;
++		DBUG_ON(ch->reason == xpcInterrupted);
++	} else if (ret == 0) {
++		ret = xpcTimeout;
++	} else {
++		ret = xpcInterrupted;
++	}
++
++	return ret;
++}
++
++/*
++ * Allocate an entry for a message from the message queue associated with the
++ * specified channel.
++ */
++static enum xpc_retval
++xpc_allocate_msg(struct xpc_channel *ch, u32 flags,
++		 struct xpc_msg **address_of_msg)
++{
++	struct xpc_msg *msg;
++	enum xpc_retval ret;
++	s64 put;
++
++	/* this reference will be dropped in xpc_send_msg() */
++	xpc_msgqueue_ref(ch);
++
++	if (ch->flags & XPC_C_DISCONNECTING) {
++		xpc_msgqueue_deref(ch);
++		return ch->reason;
++	}
++	if (!(ch->flags & XPC_C_CONNECTED)) {
++		xpc_msgqueue_deref(ch);
++		return xpcNotConnected;
++	}
++
++	/*
++	 * Get the next available message entry from the local message queue.
++	 * If none are available, we'll make sure that we grab the latest
++	 * GP values.
++	 */
++	ret = xpcTimeout;
++
++	while (1) {
++
++		put = ch->w_local_GP.put;
++		rmb();	/* guarantee that .put loads before .get */
++		if (put - ch->w_remote_GP.get < ch->local_nentries) {
++
++			/* There are available message entries. We need to try
++			 * to secure one for ourselves. We'll do this by trying
++			 * to increment w_local_GP.put as long as someone else
++			 * doesn't beat us to it. If they do, we'll have to
++			 * try again.
++			 */
++			if (cmpxchg(&ch->w_local_GP.put, put, put + 1) == put) {
++				/* we got the entry referenced by put */
++				break;
++			}
++			continue;	/* try again */
++		}
++
++		/*
++		 * There aren't any available msg entries at this time.
++		 *
++		 * In waiting for a message entry to become available,
++		 * we set a timeout in case the other side is not
++		 * sending completion IPIs. This lets us fake an IPI
++		 * that will cause the IPI handler to fetch the latest
++		 * GP values as if an IPI was sent by the other side.
++		 */
++		if (ret == xpcTimeout)
++			xpc_IPI_send_local_msgrequest(ch);
++
++		if (flags & XPC_NOWAIT) {
++			xpc_msgqueue_deref(ch);
++			return xpcNoWait;
++		}
++
++		ret = xpc_allocate_msg_wait(ch);
++		if (ret != xpcInterrupted && ret != xpcTimeout) {
++			xpc_msgqueue_deref(ch);
++			return ret;
++		}
++	}
++
++	/* get the message's address and initialize it */
++	msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
++				 (put % ch->local_nentries) * ch->msg_size);
++
++	DBUG_ON(msg->flags != 0);
++	msg->number = put;
++
++	dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "
++		"msg_number=%ld, partid=%d, channel=%d\n", put + 1,
++		(void *)msg, msg->number, ch->partid, ch->number);
++
++	*address_of_msg = msg;
++
++	return xpcSuccess;
++}
++
++/*
++ * Allocate an entry for a message from the message queue associated with the
++ * specified channel. NOTE that this routine can sleep waiting for a message
++ * entry to become available. To not sleep, pass in the XPC_NOWAIT flag.
++ *
++ * Arguments:
++ *
++ *	partid - ID of partition to which the channel is connected.
++ *	ch_number - channel #.
++ *	flags - see xpc.h for valid flags.
++ *	payload - address of the allocated payload area pointer (filled in on
++ * 	          return) in which the user-defined message is constructed.
++ */
++enum xpc_retval
++xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
++{
++	struct xpc_partition *part = &xpc_partitions[partid];
++	enum xpc_retval ret = xpcUnknownReason;
++	struct xpc_msg *msg = NULL;
++
++	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
++
++	*payload = NULL;
++
++	if (xpc_part_ref(part)) {
++		ret = xpc_allocate_msg(&part->channels[ch_number], flags, &msg);
++		xpc_part_deref(part);
++
++		if (msg != NULL)
++			*payload = &msg->payload;
++	}
++
++	return ret;
++}
++
++/*
++ * Now we actually send the messages that are ready to be sent by advancing
++ * the local message queue's Put value and then send an IPI to the recipient
++ * partition.
++ */
++static void
++xpc_send_msgs(struct xpc_channel *ch, s64 initial_put)
++{
++	struct xpc_msg *msg;
++	s64 put = initial_put + 1;
++	int send_IPI = 0;
++
++	while (1) {
++
++		while (1) {
++			if (put == ch->w_local_GP.put)
++				break;
++
++			msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
++						 (put % ch->local_nentries) *
++						 ch->msg_size);
++
++			if (!(msg->flags & XPC_M_READY))
++				break;
++
++			put++;
++		}
++
++		if (put == initial_put) {
++			/* nothing's changed */
++			break;
++		}
++
++		if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) !=
++		    initial_put) {
++			/* someone else beat us to it */
++			DBUG_ON(ch->local_GP->put < initial_put);
++			break;
++		}
++
++		/* we just set the new value of local_GP->put */
++
++		dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "
++			"channel=%d\n", put, ch->partid, ch->number);
++
++		send_IPI = 1;
++
++		/*
++		 * We need to ensure that the message referenced by
++		 * local_GP->put is not XPC_M_READY or that local_GP->put
++		 * equals w_local_GP.put, so we'll go have a look.
++		 */
++		initial_put = put;
++	}
++
++	if (send_IPI)
++		xpc_IPI_send_msgrequest(ch);
++}
++
++/*
++ * Common code that does the actual sending of the message by advancing the
++ * local message queue's Put value and sends an IPI to the partition the
++ * message is being sent to.
++ */
++static enum xpc_retval
++xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,
++	     xpc_notify_func func, void *key)
++{
++	enum xpc_retval ret = xpcSuccess;
++	struct xpc_notify *notify = notify;
++	s64 put, msg_number = msg->number;
++
++	DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
++	DBUG_ON((((u64)msg - (u64)ch->local_msgqueue) / ch->msg_size) !=
++		msg_number % ch->local_nentries);
++	DBUG_ON(msg->flags & XPC_M_READY);
++
++	if (ch->flags & XPC_C_DISCONNECTING) {
++		/* drop the reference grabbed in xpc_allocate_msg() */
++		xpc_msgqueue_deref(ch);
++		return ch->reason;
++	}
++
++	if (notify_type != 0) {
++		/*
++		 * Tell the remote side to send an ACK interrupt when the
++		 * message has been delivered.
++		 */
++		msg->flags |= XPC_M_INTERRUPT;
++
++		atomic_inc(&ch->n_to_notify);
++
++		notify = &ch->notify_queue[msg_number % ch->local_nentries];
++		notify->func = func;
++		notify->key = key;
++		notify->type = notify_type;
++
++		/* >>> is a mb() needed here? */
++
++		if (ch->flags & XPC_C_DISCONNECTING) {
++			/*
++			 * An error occurred between our last error check and
++			 * this one. We will try to clear the type field from
++			 * the notify entry. If we succeed then
++			 * xpc_disconnect_channel() didn't already process
++			 * the notify entry.
++			 */
++			if (cmpxchg(&notify->type, notify_type, 0) ==
++			    notify_type) {
++				atomic_dec(&ch->n_to_notify);
++				ret = ch->reason;
++			}
++
++			/* drop the reference grabbed in xpc_allocate_msg() */
++			xpc_msgqueue_deref(ch);
++			return ret;
++		}
++	}
++
++	msg->flags |= XPC_M_READY;
++
++	/*
++	 * The preceding store of msg->flags must occur before the following
++	 * load of ch->local_GP->put.
++	 */
++	mb();
++
++	/* see if the message is next in line to be sent, if so send it */
++
++	put = ch->local_GP->put;
++	if (put == msg_number)
++		xpc_send_msgs(ch, put);
++
++	/* drop the reference grabbed in xpc_allocate_msg() */
++	xpc_msgqueue_deref(ch);
++	return ret;
++}
++
++/*
++ * Send a message previously allocated using xpc_initiate_allocate() on the
++ * specified channel connected to the specified partition.
++ *
++ * This routine will not wait for the message to be received, nor will
++ * notification be given when it does happen. Once this routine has returned
++ * the message entry allocated via xpc_initiate_allocate() is no longer
++ * accessable to the caller.
++ *
++ * This routine, although called by users, does not call xpc_part_ref() to
++ * ensure that the partition infrastructure is in place. It relies on the
++ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
++ *
++ * Arguments:
++ *
++ *	partid - ID of partition to which the channel is connected.
++ *	ch_number - channel # to send message on.
++ *	payload - pointer to the payload area allocated via
++ *			xpc_initiate_allocate().
++ */
++enum xpc_retval
++xpc_initiate_send(partid_t partid, int ch_number, void *payload)
++{
++	struct xpc_partition *part = &xpc_partitions[partid];
++	struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
++	enum xpc_retval ret;
++
++	dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *)msg,
++		partid, ch_number);
++
++	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
++	DBUG_ON(msg == NULL);
++
++	ret = xpc_send_msg(&part->channels[ch_number], msg, 0, NULL, NULL);
++
++	return ret;
++}
++
++/*
++ * Send a message previously allocated using xpc_initiate_allocate on the
++ * specified channel connected to the specified partition.
++ *
++ * This routine will not wait for the message to be sent. Once this routine
++ * has returned the message entry allocated via xpc_initiate_allocate() is no
++ * longer accessable to the caller.
++ *
++ * Once the remote end of the channel has received the message, the function
++ * passed as an argument to xpc_initiate_send_notify() will be called. This
++ * allows the sender to free up or re-use any buffers referenced by the
++ * message, but does NOT mean the message has been processed at the remote
++ * end by a receiver.
++ *
++ * If this routine returns an error, the caller's function will NOT be called.
++ *
++ * This routine, although called by users, does not call xpc_part_ref() to
++ * ensure that the partition infrastructure is in place. It relies on the
++ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
++ *
++ * Arguments:
++ *
++ *	partid - ID of partition to which the channel is connected.
++ *	ch_number - channel # to send message on.
++ *	payload - pointer to the payload area allocated via
++ *			xpc_initiate_allocate().
++ *	func - function to call with asynchronous notification of message
++ *		  receipt. THIS FUNCTION MUST BE NON-BLOCKING.
++ *	key - user-defined key to be passed to the function when it's called.
++ */
++enum xpc_retval
++xpc_initiate_send_notify(partid_t partid, int ch_number, void *payload,
++			 xpc_notify_func func, void *key)
++{
++	struct xpc_partition *part = &xpc_partitions[partid];
++	struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
++	enum xpc_retval ret;
++
++	dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *)msg,
++		partid, ch_number);
++
++	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
++	DBUG_ON(msg == NULL);
++	DBUG_ON(func == NULL);
++
++	ret = xpc_send_msg(&part->channels[ch_number], msg, XPC_N_CALL,
++			   func, key);
++	return ret;
++}
++
++static struct xpc_msg *
++xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
++{
++	struct xpc_partition *part = &xpc_partitions[ch->partid];
++	struct xpc_msg *remote_msg, *msg;
++	u32 msg_index, nmsgs;
++	u64 msg_offset;
++	enum xpc_retval ret;
++
++	if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) {
++		/* we were interrupted by a signal */
++		return NULL;
++	}
++
++	while (get >= ch->next_msg_to_pull) {
++
++		/* pull as many messages as are ready and able to be pulled */
++
++		msg_index = ch->next_msg_to_pull % ch->remote_nentries;
++
++		DBUG_ON(ch->next_msg_to_pull >= ch->w_remote_GP.put);
++		nmsgs = ch->w_remote_GP.put - ch->next_msg_to_pull;
++		if (msg_index + nmsgs > ch->remote_nentries) {
++			/* ignore the ones that wrap the msg queue for now */
++			nmsgs = ch->remote_nentries - msg_index;
++		}
++
++		msg_offset = msg_index * ch->msg_size;
++		msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + msg_offset);
++		remote_msg = (struct xpc_msg *)(ch->remote_msgqueue_pa +
++						msg_offset);
++
++		ret = xpc_pull_remote_cachelines(part, msg, remote_msg,
++						 nmsgs * ch->msg_size);
++		if (ret != xpcSuccess) {
++
++			dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
++				" msg %ld from partition %d, channel=%d, "
++				"ret=%d\n", nmsgs, ch->next_msg_to_pull,
++				ch->partid, ch->number, ret);
++
++			XPC_DEACTIVATE_PARTITION(part, ret);
++
++			mutex_unlock(&ch->msg_to_pull_mutex);
++			return NULL;
++		}
++
++		ch->next_msg_to_pull += nmsgs;
++	}
++
++	mutex_unlock(&ch->msg_to_pull_mutex);
++
++	/* return the message we were looking for */
++	msg_offset = (get % ch->remote_nentries) * ch->msg_size;
++	msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + msg_offset);
++
++	return msg;
++}
++
++/*
++ * Get a message to be delivered.
++ */
++static struct xpc_msg *
++xpc_get_deliverable_msg(struct xpc_channel *ch)
++{
++	struct xpc_msg *msg = NULL;
++	s64 get;
++
++	do {
++		if (ch->flags & XPC_C_DISCONNECTING)
++			break;
++
++		get = ch->w_local_GP.get;
++		rmb();	/* guarantee that .get loads before .put */
++		if (get == ch->w_remote_GP.put)
++			break;
++
++		/* There are messages waiting to be pulled and delivered.
++		 * We need to try to secure one for ourselves. We'll do this
++		 * by trying to increment w_local_GP.get and hope that no one
++		 * else beats us to it. If they do, we'll we'll simply have
++		 * to try again for the next one.
++		 */
++
++		if (cmpxchg(&ch->w_local_GP.get, get, get + 1) == get) {
++			/* we got the entry referenced by get */
++
++			dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "
++				"partid=%d, channel=%d\n", get + 1,
++				ch->partid, ch->number);
++
++			/* pull the message from the remote partition */
++
++			msg = xpc_pull_remote_msg(ch, get);
++
++			DBUG_ON(msg != NULL && msg->number != get);
++			DBUG_ON(msg != NULL && (msg->flags & XPC_M_DONE));
++			DBUG_ON(msg != NULL && !(msg->flags & XPC_M_READY));
++
++			break;
++		}
++
++	} while (1);
++
++	return msg;
++}
++
++/*
++ * Deliver a message to its intended recipient.
++ */
++void
++xpc_deliver_msg(struct xpc_channel *ch)
++{
++	struct xpc_msg *msg;
++
++	msg = xpc_get_deliverable_msg(ch);
++	if (msg != NULL) {
++
++		/*
++		 * This ref is taken to protect the payload itself from being
++		 * freed before the user is finished with it, which the user
++		 * indicates by calling xpc_initiate_received().
++		 */
++		xpc_msgqueue_ref(ch);
++
++		atomic_inc(&ch->kthreads_active);
++
++		if (ch->func != NULL) {
++			dev_dbg(xpc_chan, "ch->func() called, msg=0x%p, "
++				"msg_number=%ld, partid=%d, channel=%d\n",
++				(void *)msg, msg->number, ch->partid,
++				ch->number);
++
++			/* deliver the message to its intended recipient */
++			ch->func(xpcMsgReceived, ch->partid, ch->number,
++				 &msg->payload, ch->key);
++
++			dev_dbg(xpc_chan, "ch->func() returned, msg=0x%p, "
++				"msg_number=%ld, partid=%d, channel=%d\n",
++				(void *)msg, msg->number, ch->partid,
++				ch->number);
++		}
++
++		atomic_dec(&ch->kthreads_active);
++	}
++}
++
++/*
++ * Now we actually acknowledge the messages that have been delivered and ack'd
++ * by advancing the cached remote message queue's Get value and if requested
++ * send an IPI to the message sender's partition.
++ */
++static void
++xpc_acknowledge_msgs(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
++{
++	struct xpc_msg *msg;
++	s64 get = initial_get + 1;
++	int send_IPI = 0;
++
++	while (1) {
++
++		while (1) {
++			if (get == ch->w_local_GP.get)
++				break;
++
++			msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
++						 (get % ch->remote_nentries) *
++						 ch->msg_size);
++
++			if (!(msg->flags & XPC_M_DONE))
++				break;
++
++			msg_flags |= msg->flags;
++			get++;
++		}
++
++		if (get == initial_get) {
++			/* nothing's changed */
++			break;
++		}
++
++		if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) !=
++		    initial_get) {
++			/* someone else beat us to it */
++			DBUG_ON(ch->local_GP->get <= initial_get);
++			break;
++		}
++
++		/* we just set the new value of local_GP->get */
++
++		dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
++			"channel=%d\n", get, ch->partid, ch->number);
++
++		send_IPI = (msg_flags & XPC_M_INTERRUPT);
++
++		/*
++		 * We need to ensure that the message referenced by
++		 * local_GP->get is not XPC_M_DONE or that local_GP->get
++		 * equals w_local_GP.get, so we'll go have a look.
++		 */
++		initial_get = get;
++	}
++
++	if (send_IPI)
++		xpc_IPI_send_msgrequest(ch);
++}
++
++/*
++ * Acknowledge receipt of a delivered message.
++ *
++ * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition
++ * that sent the message.
++ *
++ * This function, although called by users, does not call xpc_part_ref() to
++ * ensure that the partition infrastructure is in place. It relies on the
++ * fact that we called xpc_msgqueue_ref() in xpc_deliver_msg().
++ *
++ * Arguments:
++ *
++ *	partid - ID of partition to which the channel is connected.
++ *	ch_number - channel # message received on.
++ *	payload - pointer to the payload area allocated via
++ *			xpc_initiate_allocate().
++ */
++void
++xpc_initiate_received(partid_t partid, int ch_number, void *payload)
++{
++	struct xpc_partition *part = &xpc_partitions[partid];
++	struct xpc_channel *ch;
++	struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
++	s64 get, msg_number = msg->number;
++
++	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
++
++	ch = &part->channels[ch_number];
++
++	dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
++		(void *)msg, msg_number, ch->partid, ch->number);
++
++	DBUG_ON((((u64)msg - (u64)ch->remote_msgqueue) / ch->msg_size) !=
++		msg_number % ch->remote_nentries);
++	DBUG_ON(msg->flags & XPC_M_DONE);
++
++	msg->flags |= XPC_M_DONE;
++
++	/*
++	 * The preceding store of msg->flags must occur before the following
++	 * load of ch->local_GP->get.
++	 */
++	mb();
++
++	/*
++	 * See if this message is next in line to be acknowledged as having
++	 * been delivered.
++	 */
++	get = ch->local_GP->get;
++	if (get == msg_number)
++		xpc_acknowledge_msgs(ch, get, msg->flags);
++
++	/* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg()  */
++	xpc_msgqueue_deref(ch);
++}
+diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
+new file mode 100644
+index 0000000..f673ba9
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpc_main.c
+@@ -0,0 +1,1323 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
++ */
++
++/*
++ * Cross Partition Communication (XPC) support - standard version.
++ *
++ *	XPC provides a message passing capability that crosses partition
++ *	boundaries. This module is made up of two parts:
++ *
++ *	    partition	This part detects the presence/absence of other
++ *			partitions. It provides a heartbeat and monitors
++ *			the heartbeats of other partitions.
++ *
++ *	    channel	This part manages the channels and sends/receives
++ *			messages across them to/from other partitions.
++ *
++ *	There are a couple of additional functions residing in XP, which
++ *	provide an interface to XPC for its users.
++ *
++ *
++ *	Caveats:
++ *
++ *	  . We currently have no way to determine which nasid an IPI came
++ *	    from. Thus, xpc_IPI_send() does a remote AMO write followed by
++ *	    an IPI. The AMO indicates where data is to be pulled from, so
++ *	    after the IPI arrives, the remote partition checks the AMO word.
++ *	    The IPI can actually arrive before the AMO however, so other code
++ *	    must periodically check for this case. Also, remote AMO operations
++ *	    do not reliably time out. Thus we do a remote PIO read solely to
++ *	    know whether the remote partition is down and whether we should
++ *	    stop sending IPIs to it. This remote PIO read operation is set up
++ *	    in a special nofault region so SAL knows to ignore (and cleanup)
++ *	    any errors due to the remote AMO write, PIO read, and/or PIO
++ *	    write operations.
++ *
++ *	    If/when new hardware solves this IPI problem, we should abandon
++ *	    the current approach.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/reboot.h>
++#include <linux/completion.h>
++#include <linux/kdebug.h>
++#include <linux/kthread.h>
++#include <linux/uaccess.h>
++#include <asm/sn/intr.h>
++#include <asm/sn/sn_sal.h>
++#include "xpc.h"
++
++/* define two XPC debug device structures to be used with dev_dbg() et al */
++
++struct device_driver xpc_dbg_name = {
++	.name = "xpc"
++};
++
++struct device xpc_part_dbg_subname = {
++	.bus_id = {0},		/* set to "part" at xpc_init() time */
++	.driver = &xpc_dbg_name
++};
++
++struct device xpc_chan_dbg_subname = {
++	.bus_id = {0},		/* set to "chan" at xpc_init() time */
++	.driver = &xpc_dbg_name
++};
++
++struct device *xpc_part = &xpc_part_dbg_subname;
++struct device *xpc_chan = &xpc_chan_dbg_subname;
++
++static int xpc_kdebug_ignore;
++
++/* systune related variables for /proc/sys directories */
++
++static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
++static int xpc_hb_min_interval = 1;
++static int xpc_hb_max_interval = 10;
++
++static int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_INTERVAL;
++static int xpc_hb_check_min_interval = 10;
++static int xpc_hb_check_max_interval = 120;
++
++int xpc_disengage_request_timelimit = XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT;
++static int xpc_disengage_request_min_timelimit;	/* = 0 */
++static int xpc_disengage_request_max_timelimit = 120;
++
++static ctl_table xpc_sys_xpc_hb_dir[] = {
++	{
++	 .ctl_name = CTL_UNNUMBERED,
++	 .procname = "hb_interval",
++	 .data = &xpc_hb_interval,
++	 .maxlen = sizeof(int),
++	 .mode = 0644,
++	 .proc_handler = &proc_dointvec_minmax,
++	 .strategy = &sysctl_intvec,
++	 .extra1 = &xpc_hb_min_interval,
++	 .extra2 = &xpc_hb_max_interval},
++	{
++	 .ctl_name = CTL_UNNUMBERED,
++	 .procname = "hb_check_interval",
++	 .data = &xpc_hb_check_interval,
++	 .maxlen = sizeof(int),
++	 .mode = 0644,
++	 .proc_handler = &proc_dointvec_minmax,
++	 .strategy = &sysctl_intvec,
++	 .extra1 = &xpc_hb_check_min_interval,
++	 .extra2 = &xpc_hb_check_max_interval},
++	{}
++};
++static ctl_table xpc_sys_xpc_dir[] = {
++	{
++	 .ctl_name = CTL_UNNUMBERED,
++	 .procname = "hb",
++	 .mode = 0555,
++	 .child = xpc_sys_xpc_hb_dir},
++	{
++	 .ctl_name = CTL_UNNUMBERED,
++	 .procname = "disengage_request_timelimit",
++	 .data = &xpc_disengage_request_timelimit,
++	 .maxlen = sizeof(int),
++	 .mode = 0644,
++	 .proc_handler = &proc_dointvec_minmax,
++	 .strategy = &sysctl_intvec,
++	 .extra1 = &xpc_disengage_request_min_timelimit,
++	 .extra2 = &xpc_disengage_request_max_timelimit},
++	{}
++};
++static ctl_table xpc_sys_dir[] = {
++	{
++	 .ctl_name = CTL_UNNUMBERED,
++	 .procname = "xpc",
++	 .mode = 0555,
++	 .child = xpc_sys_xpc_dir},
++	{}
++};
++static struct ctl_table_header *xpc_sysctl;
++
++/* non-zero if any remote partition disengage request was timed out */
++int xpc_disengage_request_timedout;
++
++/* #of IRQs received */
++static atomic_t xpc_act_IRQ_rcvd;
++
++/* IRQ handler notifies this wait queue on receipt of an IRQ */
++static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);
++
++static unsigned long xpc_hb_check_timeout;
++
++/* notification that the xpc_hb_checker thread has exited */
++static DECLARE_COMPLETION(xpc_hb_checker_exited);
++
++/* notification that the xpc_discovery thread has exited */
++static DECLARE_COMPLETION(xpc_discovery_exited);
++
++static struct timer_list xpc_hb_timer;
++
++static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);
++
++static int xpc_system_reboot(struct notifier_block *, unsigned long, void *);
++static struct notifier_block xpc_reboot_notifier = {
++	.notifier_call = xpc_system_reboot,
++};
++
++static int xpc_system_die(struct notifier_block *, unsigned long, void *);
++static struct notifier_block xpc_die_notifier = {
++	.notifier_call = xpc_system_die,
++};
++
++/*
++ * Timer function to enforce the timelimit on the partition disengage request.
++ */
++static void
++xpc_timeout_partition_disengage_request(unsigned long data)
++{
++	struct xpc_partition *part = (struct xpc_partition *)data;
++
++	DBUG_ON(time_before(jiffies, part->disengage_request_timeout));
++
++	(void)xpc_partition_disengaged(part);
++
++	DBUG_ON(part->disengage_request_timeout != 0);
++	DBUG_ON(xpc_partition_engaged(1UL << XPC_PARTID(part)) != 0);
++}
++
++/*
++ * Notify the heartbeat check thread that an IRQ has been received.
++ */
++static irqreturn_t
++xpc_act_IRQ_handler(int irq, void *dev_id)
++{
++	atomic_inc(&xpc_act_IRQ_rcvd);
++	wake_up_interruptible(&xpc_act_IRQ_wq);
++	return IRQ_HANDLED;
++}
++
++/*
++ * Timer to produce the heartbeat.  The timer structures function is
++ * already set when this is initially called.  A tunable is used to
++ * specify when the next timeout should occur.
++ */
++static void
++xpc_hb_beater(unsigned long dummy)
++{
++	xpc_vars->heartbeat++;
++
++	if (time_after_eq(jiffies, xpc_hb_check_timeout))
++		wake_up_interruptible(&xpc_act_IRQ_wq);
++
++	xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ);
++	add_timer(&xpc_hb_timer);
++}
++
++/*
++ * This thread is responsible for nearly all of the partition
++ * activation/deactivation.
++ */
++static int
++xpc_hb_checker(void *ignore)
++{
++	int last_IRQ_count = 0;
++	int new_IRQ_count;
++	int force_IRQ = 0;
++
++	/* this thread was marked active by xpc_hb_init() */
++
++	set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));
++
++	/* set our heartbeating to other partitions into motion */
++	xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
++	xpc_hb_beater(0);
++
++	while (!xpc_exiting) {
++
++		dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
++			"been received\n",
++			(int)(xpc_hb_check_timeout - jiffies),
++			atomic_read(&xpc_act_IRQ_rcvd) - last_IRQ_count);
++
++		/* checking of remote heartbeats is skewed by IRQ handling */
++		if (time_after_eq(jiffies, xpc_hb_check_timeout)) {
++			dev_dbg(xpc_part, "checking remote heartbeats\n");
++			xpc_check_remote_hb();
++
++			/*
++			 * We need to periodically recheck to ensure no
++			 * IPI/AMO pairs have been missed.  That check
++			 * must always reset xpc_hb_check_timeout.
++			 */
++			force_IRQ = 1;
++		}
++
++		/* check for outstanding IRQs */
++		new_IRQ_count = atomic_read(&xpc_act_IRQ_rcvd);
++		if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {
++			force_IRQ = 0;
++
++			dev_dbg(xpc_part, "found an IRQ to process; will be "
++				"resetting xpc_hb_check_timeout\n");
++
++			last_IRQ_count += xpc_identify_act_IRQ_sender();
++			if (last_IRQ_count < new_IRQ_count) {
++				/* retry once to help avoid missing AMO */
++				(void)xpc_identify_act_IRQ_sender();
++			}
++			last_IRQ_count = new_IRQ_count;
++
++			xpc_hb_check_timeout = jiffies +
++			    (xpc_hb_check_interval * HZ);
++		}
++
++		/* wait for IRQ or timeout */
++		(void)wait_event_interruptible(xpc_act_IRQ_wq,
++					       (last_IRQ_count <
++						atomic_read(&xpc_act_IRQ_rcvd)
++						|| time_after_eq(jiffies,
++							xpc_hb_check_timeout) ||
++						xpc_exiting));
++	}
++
++	dev_dbg(xpc_part, "heartbeat checker is exiting\n");
++
++	/* mark this thread as having exited */
++	complete(&xpc_hb_checker_exited);
++	return 0;
++}
++
++/*
++ * This thread will attempt to discover other partitions to activate
++ * based on info provided by SAL. This new thread is short lived and
++ * will exit once discovery is complete.
++ */
++static int
++xpc_initiate_discovery(void *ignore)
++{
++	xpc_discovery();
++
++	dev_dbg(xpc_part, "discovery thread is exiting\n");
++
++	/* mark this thread as having exited */
++	complete(&xpc_discovery_exited);
++	return 0;
++}
++
++/*
++ * Establish first contact with the remote partititon. This involves pulling
++ * the XPC per partition variables from the remote partition and waiting for
++ * the remote partition to pull ours.
++ */
++static enum xpc_retval
++xpc_make_first_contact(struct xpc_partition *part)
++{
++	enum xpc_retval ret;
++
++	while ((ret = xpc_pull_remote_vars_part(part)) != xpcSuccess) {
++		if (ret != xpcRetry) {
++			XPC_DEACTIVATE_PARTITION(part, ret);
++			return ret;
++		}
++
++		dev_dbg(xpc_chan, "waiting to make first contact with "
++			"partition %d\n", XPC_PARTID(part));
++
++		/* wait a 1/4 of a second or so */
++		(void)msleep_interruptible(250);
++
++		if (part->act_state == XPC_P_DEACTIVATING)
++			return part->reason;
++	}
++
++	return xpc_mark_partition_active(part);
++}
++
++/*
++ * The first kthread assigned to a newly activated partition is the one
++ * created by XPC HB with which it calls xpc_partition_up(). XPC hangs on to
++ * that kthread until the partition is brought down, at which time that kthread
++ * returns back to XPC HB. (The return of that kthread will signify to XPC HB
++ * that XPC has dismantled all communication infrastructure for the associated
++ * partition.) This kthread becomes the channel manager for that partition.
++ *
++ * Each active partition has a channel manager, who, besides connecting and
++ * disconnecting channels, will ensure that each of the partition's connected
++ * channels has the required number of assigned kthreads to get the work done.
++ */
++static void
++xpc_channel_mgr(struct xpc_partition *part)
++{
++	while (part->act_state != XPC_P_DEACTIVATING ||
++	       atomic_read(&part->nchannels_active) > 0 ||
++	       !xpc_partition_disengaged(part)) {
++
++		xpc_process_channel_activity(part);
++
++		/*
++		 * Wait until we've been requested to activate kthreads or
++		 * all of the channel's message queues have been torn down or
++		 * a signal is pending.
++		 *
++		 * The channel_mgr_requests is set to 1 after being awakened,
++		 * This is done to prevent the channel mgr from making one pass
++		 * through the loop for each request, since he will
++		 * be servicing all the requests in one pass. The reason it's
++		 * set to 1 instead of 0 is so that other kthreads will know
++		 * that the channel mgr is running and won't bother trying to
++		 * wake him up.
++		 */
++		atomic_dec(&part->channel_mgr_requests);
++		(void)wait_event_interruptible(part->channel_mgr_wq,
++				(atomic_read(&part->channel_mgr_requests) > 0 ||
++				 part->local_IPI_amo != 0 ||
++				 (part->act_state == XPC_P_DEACTIVATING &&
++				 atomic_read(&part->nchannels_active) == 0 &&
++				 xpc_partition_disengaged(part))));
++		atomic_set(&part->channel_mgr_requests, 1);
++	}
++}
++
++/*
++ * When XPC HB determines that a partition has come up, it will create a new
++ * kthread and that kthread will call this function to attempt to set up the
++ * basic infrastructure used for Cross Partition Communication with the newly
++ * upped partition.
++ *
++ * The kthread that was created by XPC HB and which setup the XPC
++ * infrastructure will remain assigned to the partition until the partition
++ * goes down. At which time the kthread will teardown the XPC infrastructure
++ * and then exit.
++ *
++ * XPC HB will put the remote partition's XPC per partition specific variables
++ * physical address into xpc_partitions[partid].remote_vars_part_pa prior to
++ * calling xpc_partition_up().
++ */
++static void
++xpc_partition_up(struct xpc_partition *part)
++{
++	DBUG_ON(part->channels != NULL);
++
++	dev_dbg(xpc_chan, "activating partition %d\n", XPC_PARTID(part));
++
++	if (xpc_setup_infrastructure(part) != xpcSuccess)
++		return;
++
++	/*
++	 * The kthread that XPC HB called us with will become the
++	 * channel manager for this partition. It will not return
++	 * back to XPC HB until the partition's XPC infrastructure
++	 * has been dismantled.
++	 */
++
++	(void)xpc_part_ref(part);	/* this will always succeed */
++
++	if (xpc_make_first_contact(part) == xpcSuccess)
++		xpc_channel_mgr(part);
++
++	xpc_part_deref(part);
++
++	xpc_teardown_infrastructure(part);
++}
++
++static int
++xpc_activating(void *__partid)
++{
++	partid_t partid = (u64)__partid;
++	struct xpc_partition *part = &xpc_partitions[partid];
++	unsigned long irq_flags;
++
++	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++
++	spin_lock_irqsave(&part->act_lock, irq_flags);
++
++	if (part->act_state == XPC_P_DEACTIVATING) {
++		part->act_state = XPC_P_INACTIVE;
++		spin_unlock_irqrestore(&part->act_lock, irq_flags);
++		part->remote_rp_pa = 0;
++		return 0;
++	}
++
++	/* indicate the thread is activating */
++	DBUG_ON(part->act_state != XPC_P_ACTIVATION_REQ);
++	part->act_state = XPC_P_ACTIVATING;
++
++	XPC_SET_REASON(part, 0, 0);
++	spin_unlock_irqrestore(&part->act_lock, irq_flags);
++
++	dev_dbg(xpc_part, "bringing partition %d up\n", partid);
++
++	/*
++	 * Register the remote partition's AMOs with SAL so it can handle
++	 * and cleanup errors within that address range should the remote
++	 * partition go down. We don't unregister this range because it is
++	 * difficult to tell when outstanding writes to the remote partition
++	 * are finished and thus when it is safe to unregister. This should
++	 * not result in wasted space in the SAL xp_addr_region table because
++	 * we should get the same page for remote_amos_page_pa after module
++	 * reloads and system reboots.
++	 */
++	if (sn_register_xp_addr_region(part->remote_amos_page_pa,
++				       PAGE_SIZE, 1) < 0) {
++		dev_warn(xpc_part, "xpc_partition_up(%d) failed to register "
++			 "xp_addr region\n", partid);
++
++		spin_lock_irqsave(&part->act_lock, irq_flags);
++		part->act_state = XPC_P_INACTIVE;
++		XPC_SET_REASON(part, xpcPhysAddrRegFailed, __LINE__);
++		spin_unlock_irqrestore(&part->act_lock, irq_flags);
++		part->remote_rp_pa = 0;
++		return 0;
++	}
++
++	xpc_allow_hb(partid, xpc_vars);
++	xpc_IPI_send_activated(part);
++
++	/*
++	 * xpc_partition_up() holds this thread and marks this partition as
++	 * XPC_P_ACTIVE by calling xpc_hb_mark_active().
++	 */
++	(void)xpc_partition_up(part);
++
++	xpc_disallow_hb(partid, xpc_vars);
++	xpc_mark_partition_inactive(part);
++
++	if (part->reason == xpcReactivating) {
++		/* interrupting ourselves results in activating partition */
++		xpc_IPI_send_reactivate(part);
++	}
++
++	return 0;
++}
++
++void
++xpc_activate_partition(struct xpc_partition *part)
++{
++	partid_t partid = XPC_PARTID(part);
++	unsigned long irq_flags;
++	struct task_struct *kthread;
++
++	spin_lock_irqsave(&part->act_lock, irq_flags);
++
++	DBUG_ON(part->act_state != XPC_P_INACTIVE);
++
++	part->act_state = XPC_P_ACTIVATION_REQ;
++	XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
++
++	spin_unlock_irqrestore(&part->act_lock, irq_flags);
++
++	kthread = kthread_run(xpc_activating, (void *)((u64)partid), "xpc%02d",
++			      partid);
++	if (IS_ERR(kthread)) {
++		spin_lock_irqsave(&part->act_lock, irq_flags);
++		part->act_state = XPC_P_INACTIVE;
++		XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
++		spin_unlock_irqrestore(&part->act_lock, irq_flags);
++	}
++}
++
++/*
++ * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
++ * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
++ * than one partition, we use an AMO_t structure per partition to indicate
++ * whether a partition has sent an IPI or not.  If it has, then wake up the
++ * associated kthread to handle it.
++ *
++ * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IPIs sent by XPC
++ * running on other partitions.
++ *
++ * Noteworthy Arguments:
++ *
++ *	irq - Interrupt ReQuest number. NOT USED.
++ *
++ *	dev_id - partid of IPI's potential sender.
++ */
++irqreturn_t
++xpc_notify_IRQ_handler(int irq, void *dev_id)
++{
++	partid_t partid = (partid_t) (u64)dev_id;
++	struct xpc_partition *part = &xpc_partitions[partid];
++
++	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++
++	if (xpc_part_ref(part)) {
++		xpc_check_for_channel_activity(part);
++
++		xpc_part_deref(part);
++	}
++	return IRQ_HANDLED;
++}
++
++/*
++ * Check to see if xpc_notify_IRQ_handler() dropped any IPIs on the floor
++ * because the write to their associated IPI amo completed after the IRQ/IPI
++ * was received.
++ */
++void
++xpc_dropped_IPI_check(struct xpc_partition *part)
++{
++	if (xpc_part_ref(part)) {
++		xpc_check_for_channel_activity(part);
++
++		part->dropped_IPI_timer.expires = jiffies +
++		    XPC_P_DROPPED_IPI_WAIT;
++		add_timer(&part->dropped_IPI_timer);
++		xpc_part_deref(part);
++	}
++}
++
++void
++xpc_activate_kthreads(struct xpc_channel *ch, int needed)
++{
++	int idle = atomic_read(&ch->kthreads_idle);
++	int assigned = atomic_read(&ch->kthreads_assigned);
++	int wakeup;
++
++	DBUG_ON(needed <= 0);
++
++	if (idle > 0) {
++		wakeup = (needed > idle) ? idle : needed;
++		needed -= wakeup;
++
++		dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, "
++			"channel=%d\n", wakeup, ch->partid, ch->number);
++
++		/* only wakeup the requested number of kthreads */
++		wake_up_nr(&ch->idle_wq, wakeup);
++	}
++
++	if (needed <= 0)
++		return;
++
++	if (needed + assigned > ch->kthreads_assigned_limit) {
++		needed = ch->kthreads_assigned_limit - assigned;
++		if (needed <= 0)
++			return;
++	}
++
++	dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",
++		needed, ch->partid, ch->number);
++
++	xpc_create_kthreads(ch, needed, 0);
++}
++
++/*
++ * This function is where XPC's kthreads wait for messages to deliver.
++ */
++static void
++xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
++{
++	do {
++		/* deliver messages to their intended recipients */
++
++		while (ch->w_local_GP.get < ch->w_remote_GP.put &&
++		       !(ch->flags & XPC_C_DISCONNECTING)) {
++			xpc_deliver_msg(ch);
++		}
++
++		if (atomic_inc_return(&ch->kthreads_idle) >
++		    ch->kthreads_idle_limit) {
++			/* too many idle kthreads on this channel */
++			atomic_dec(&ch->kthreads_idle);
++			break;
++		}
++
++		dev_dbg(xpc_chan, "idle kthread calling "
++			"wait_event_interruptible_exclusive()\n");
++
++		(void)wait_event_interruptible_exclusive(ch->idle_wq,
++				(ch->w_local_GP.get < ch->w_remote_GP.put ||
++				 (ch->flags & XPC_C_DISCONNECTING)));
++
++		atomic_dec(&ch->kthreads_idle);
++
++	} while (!(ch->flags & XPC_C_DISCONNECTING));
++}
++
++static int
++xpc_kthread_start(void *args)
++{
++	partid_t partid = XPC_UNPACK_ARG1(args);
++	u16 ch_number = XPC_UNPACK_ARG2(args);
++	struct xpc_partition *part = &xpc_partitions[partid];
++	struct xpc_channel *ch;
++	int n_needed;
++	unsigned long irq_flags;
++
++	dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n",
++		partid, ch_number);
++
++	ch = &part->channels[ch_number];
++
++	if (!(ch->flags & XPC_C_DISCONNECTING)) {
++
++		/* let registerer know that connection has been established */
++
++		spin_lock_irqsave(&ch->lock, irq_flags);
++		if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) {
++			ch->flags |= XPC_C_CONNECTEDCALLOUT;
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++			xpc_connected_callout(ch);
++
++			spin_lock_irqsave(&ch->lock, irq_flags);
++			ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE;
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++			/*
++			 * It is possible that while the callout was being
++			 * made that the remote partition sent some messages.
++			 * If that is the case, we may need to activate
++			 * additional kthreads to help deliver them. We only
++			 * need one less than total #of messages to deliver.
++			 */
++			n_needed = ch->w_remote_GP.put - ch->w_local_GP.get - 1;
++			if (n_needed > 0 && !(ch->flags & XPC_C_DISCONNECTING))
++				xpc_activate_kthreads(ch, n_needed);
++
++		} else {
++			spin_unlock_irqrestore(&ch->lock, irq_flags);
++		}
++
++		xpc_kthread_waitmsgs(part, ch);
++	}
++
++	/* let registerer know that connection is disconnecting */
++
++	spin_lock_irqsave(&ch->lock, irq_flags);
++	if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
++	    !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
++		ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
++		spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++		xpc_disconnect_callout(ch, xpcDisconnecting);
++
++		spin_lock_irqsave(&ch->lock, irq_flags);
++		ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
++	}
++	spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++	if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
++		if (atomic_dec_return(&part->nchannels_engaged) == 0) {
++			xpc_mark_partition_disengaged(part);
++			xpc_IPI_send_disengage(part);
++		}
++	}
++
++	xpc_msgqueue_deref(ch);
++
++	dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",
++		partid, ch_number);
++
++	xpc_part_deref(part);
++	return 0;
++}
++
++/*
++ * For each partition that XPC has established communications with, there is
++ * a minimum of one kernel thread assigned to perform any operation that
++ * may potentially sleep or block (basically the callouts to the asynchronous
++ * functions registered via xpc_connect()).
++ *
++ * Additional kthreads are created and destroyed by XPC as the workload
++ * demands.
++ *
++ * A kthread is assigned to one of the active channels that exists for a given
++ * partition.
++ */
++void
++xpc_create_kthreads(struct xpc_channel *ch, int needed,
++		    int ignore_disconnecting)
++{
++	unsigned long irq_flags;
++	u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
++	struct xpc_partition *part = &xpc_partitions[ch->partid];
++	struct task_struct *kthread;
++
++	while (needed-- > 0) {
++
++		/*
++		 * The following is done on behalf of the newly created
++		 * kthread. That kthread is responsible for doing the
++		 * counterpart to the following before it exits.
++		 */
++		if (ignore_disconnecting) {
++			if (!atomic_inc_not_zero(&ch->kthreads_assigned)) {
++				/* kthreads assigned had gone to zero */
++				BUG_ON(!(ch->flags &
++					 XPC_C_DISCONNECTINGCALLOUT_MADE));
++				break;
++			}
++
++		} else if (ch->flags & XPC_C_DISCONNECTING) {
++			break;
++
++		} else if (atomic_inc_return(&ch->kthreads_assigned) == 1) {
++			if (atomic_inc_return(&part->nchannels_engaged) == 1)
++				xpc_mark_partition_engaged(part);
++		}
++		(void)xpc_part_ref(part);
++		xpc_msgqueue_ref(ch);
++
++		kthread = kthread_run(xpc_kthread_start, (void *)args,
++				      "xpc%02dc%d", ch->partid, ch->number);
++		if (IS_ERR(kthread)) {
++			/* the fork failed */
++
++			/*
++			 * NOTE: if (ignore_disconnecting &&
++			 * !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true,
++			 * then we'll deadlock if all other kthreads assigned
++			 * to this channel are blocked in the channel's
++			 * registerer, because the only thing that will unblock
++			 * them is the xpcDisconnecting callout that this
++			 * failed kthread_run() would have made.
++			 */
++
++			if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
++			    atomic_dec_return(&part->nchannels_engaged) == 0) {
++				xpc_mark_partition_disengaged(part);
++				xpc_IPI_send_disengage(part);
++			}
++			xpc_msgqueue_deref(ch);
++			xpc_part_deref(part);
++
++			if (atomic_read(&ch->kthreads_assigned) <
++			    ch->kthreads_idle_limit) {
++				/*
++				 * Flag this as an error only if we have an
++				 * insufficient #of kthreads for the channel
++				 * to function.
++				 */
++				spin_lock_irqsave(&ch->lock, irq_flags);
++				XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources,
++						       &irq_flags);
++				spin_unlock_irqrestore(&ch->lock, irq_flags);
++			}
++			break;
++		}
++	}
++}
++
++void
++xpc_disconnect_wait(int ch_number)
++{
++	unsigned long irq_flags;
++	partid_t partid;
++	struct xpc_partition *part;
++	struct xpc_channel *ch;
++	int wakeup_channel_mgr;
++
++	/* now wait for all callouts to the caller's function to cease */
++	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++		part = &xpc_partitions[partid];
++
++		if (!xpc_part_ref(part))
++			continue;
++
++		ch = &part->channels[ch_number];
++
++		if (!(ch->flags & XPC_C_WDISCONNECT)) {
++			xpc_part_deref(part);
++			continue;
++		}
++
++		wait_for_completion(&ch->wdisconnect_wait);
++
++		spin_lock_irqsave(&ch->lock, irq_flags);
++		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
++		wakeup_channel_mgr = 0;
++
++		if (ch->delayed_IPI_flags) {
++			if (part->act_state != XPC_P_DEACTIVATING) {
++				spin_lock(&part->IPI_lock);
++				XPC_SET_IPI_FLAGS(part->local_IPI_amo,
++						  ch->number,
++						  ch->delayed_IPI_flags);
++				spin_unlock(&part->IPI_lock);
++				wakeup_channel_mgr = 1;
++			}
++			ch->delayed_IPI_flags = 0;
++		}
++
++		ch->flags &= ~XPC_C_WDISCONNECT;
++		spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++		if (wakeup_channel_mgr)
++			xpc_wakeup_channel_mgr(part);
++
++		xpc_part_deref(part);
++	}
++}
++
++static void
++xpc_do_exit(enum xpc_retval reason)
++{
++	partid_t partid;
++	int active_part_count, printed_waiting_msg = 0;
++	struct xpc_partition *part;
++	unsigned long printmsg_time, disengage_request_timeout = 0;
++
++	/* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
++	DBUG_ON(xpc_exiting == 1);
++
++	/*
++	 * Let the heartbeat checker thread and the discovery thread
++	 * (if one is running) know that they should exit. Also wake up
++	 * the heartbeat checker thread in case it's sleeping.
++	 */
++	xpc_exiting = 1;
++	wake_up_interruptible(&xpc_act_IRQ_wq);
++
++	/* ignore all incoming interrupts */
++	free_irq(SGI_XPC_ACTIVATE, NULL);
++
++	/* wait for the discovery thread to exit */
++	wait_for_completion(&xpc_discovery_exited);
++
++	/* wait for the heartbeat checker thread to exit */
++	wait_for_completion(&xpc_hb_checker_exited);
++
++	/* sleep for a 1/3 of a second or so */
++	(void)msleep_interruptible(300);
++
++	/* wait for all partitions to become inactive */
++
++	printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
++	xpc_disengage_request_timedout = 0;
++
++	do {
++		active_part_count = 0;
++
++		for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++			part = &xpc_partitions[partid];
++
++			if (xpc_partition_disengaged(part) &&
++			    part->act_state == XPC_P_INACTIVE) {
++				continue;
++			}
++
++			active_part_count++;
++
++			XPC_DEACTIVATE_PARTITION(part, reason);
++
++			if (part->disengage_request_timeout >
++			    disengage_request_timeout) {
++				disengage_request_timeout =
++				    part->disengage_request_timeout;
++			}
++		}
++
++		if (xpc_partition_engaged(-1UL)) {
++			if (time_after(jiffies, printmsg_time)) {
++				dev_info(xpc_part, "waiting for remote "
++					 "partitions to disengage, timeout in "
++					 "%ld seconds\n",
++					 (disengage_request_timeout - jiffies)
++					 / HZ);
++				printmsg_time = jiffies +
++				    (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
++				printed_waiting_msg = 1;
++			}
++
++		} else if (active_part_count > 0) {
++			if (printed_waiting_msg) {
++				dev_info(xpc_part, "waiting for local partition"
++					 " to disengage\n");
++				printed_waiting_msg = 0;
++			}
++
++		} else {
++			if (!xpc_disengage_request_timedout) {
++				dev_info(xpc_part, "all partitions have "
++					 "disengaged\n");
++			}
++			break;
++		}
++
++		/* sleep for a 1/3 of a second or so */
++		(void)msleep_interruptible(300);
++
++	} while (1);
++
++	DBUG_ON(xpc_partition_engaged(-1UL));
++
++	/* indicate to others that our reserved page is uninitialized */
++	xpc_rsvd_page->vars_pa = 0;
++
++	/* now it's time to eliminate our heartbeat */
++	del_timer_sync(&xpc_hb_timer);
++	DBUG_ON(xpc_vars->heartbeating_to_mask != 0);
++
++	if (reason == xpcUnloading) {
++		/* take ourselves off of the reboot_notifier_list */
++		(void)unregister_reboot_notifier(&xpc_reboot_notifier);
++
++		/* take ourselves off of the die_notifier list */
++		(void)unregister_die_notifier(&xpc_die_notifier);
++	}
++
++	/* close down protections for IPI operations */
++	xpc_restrict_IPI_ops();
++
++	/* clear the interface to XPC's functions */
++	xpc_clear_interface();
++
++	if (xpc_sysctl)
++		unregister_sysctl_table(xpc_sysctl);
++
++	kfree(xpc_remote_copy_buffer_base);
++}
++
++/*
++ * This function is called when the system is being rebooted.
++ */
++static int
++xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
++{
++	enum xpc_retval reason;
++
++	switch (event) {
++	case SYS_RESTART:
++		reason = xpcSystemReboot;
++		break;
++	case SYS_HALT:
++		reason = xpcSystemHalt;
++		break;
++	case SYS_POWER_OFF:
++		reason = xpcSystemPoweroff;
++		break;
++	default:
++		reason = xpcSystemGoingDown;
++	}
++
++	xpc_do_exit(reason);
++	return NOTIFY_DONE;
++}
++
++/*
++ * Notify other partitions to disengage from all references to our memory.
++ */
++static void
++xpc_die_disengage(void)
++{
++	struct xpc_partition *part;
++	partid_t partid;
++	unsigned long engaged;
++	long time, printmsg_time, disengage_request_timeout;
++
++	/* keep xpc_hb_checker thread from doing anything (just in case) */
++	xpc_exiting = 1;
++
++	xpc_vars->heartbeating_to_mask = 0;	/* indicate we're deactivated */
++
++	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++		part = &xpc_partitions[partid];
++
++		if (!XPC_SUPPORTS_DISENGAGE_REQUEST(part->
++		    remote_vars_version)) {
++
++			/* just in case it was left set by an earlier XPC */
++			xpc_clear_partition_engaged(1UL << partid);
++			continue;
++		}
++
++		if (xpc_partition_engaged(1UL << partid) ||
++		    part->act_state != XPC_P_INACTIVE) {
++			xpc_request_partition_disengage(part);
++			xpc_mark_partition_disengaged(part);
++			xpc_IPI_send_disengage(part);
++		}
++	}
++
++	time = rtc_time();
++	printmsg_time = time +
++	    (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second);
++	disengage_request_timeout = time +
++	    (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);
++
++	/* wait for all other partitions to disengage from us */
++
++	while (1) {
++		engaged = xpc_partition_engaged(-1UL);
++		if (!engaged) {
++			dev_info(xpc_part, "all partitions have disengaged\n");
++			break;
++		}
++
++		time = rtc_time();
++		if (time >= disengage_request_timeout) {
++			for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++				if (engaged & (1UL << partid)) {
++					dev_info(xpc_part, "disengage from "
++						 "remote partition %d timed "
++						 "out\n", partid);
++				}
++			}
++			break;
++		}
++
++		if (time >= printmsg_time) {
++			dev_info(xpc_part, "waiting for remote partitions to "
++				 "disengage, timeout in %ld seconds\n",
++				 (disengage_request_timeout - time) /
++				 sn_rtc_cycles_per_second);
++			printmsg_time = time +
++			    (XPC_DISENGAGE_PRINTMSG_INTERVAL *
++			     sn_rtc_cycles_per_second);
++		}
++	}
++}
++
++/*
++ * This function is called when the system is being restarted or halted due
++ * to some sort of system failure. If this is the case we need to notify the
++ * other partitions to disengage from all references to our memory.
++ * This function can also be called when our heartbeater could be offlined
++ * for a time. In this case we need to notify other partitions to not worry
++ * about the lack of a heartbeat.
++ */
++static int
++xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
++{
++	switch (event) {
++	case DIE_MACHINE_RESTART:
++	case DIE_MACHINE_HALT:
++		xpc_die_disengage();
++		break;
++
++	case DIE_KDEBUG_ENTER:
++		/* Should lack of heartbeat be ignored by other partitions? */
++		if (!xpc_kdebug_ignore)
++			break;
++
++		/* fall through */
++	case DIE_MCA_MONARCH_ENTER:
++	case DIE_INIT_MONARCH_ENTER:
++		xpc_vars->heartbeat++;
++		xpc_vars->heartbeat_offline = 1;
++		break;
++
++	case DIE_KDEBUG_LEAVE:
++		/* Is lack of heartbeat being ignored by other partitions? */
++		if (!xpc_kdebug_ignore)
++			break;
++
++		/* fall through */
++	case DIE_MCA_MONARCH_LEAVE:
++	case DIE_INIT_MONARCH_LEAVE:
++		xpc_vars->heartbeat++;
++		xpc_vars->heartbeat_offline = 0;
++		break;
++	}
++
++	return NOTIFY_DONE;
++}
++
++int __init
++xpc_init(void)
++{
++	int ret;
++	partid_t partid;
++	struct xpc_partition *part;
++	struct task_struct *kthread;
++	size_t buf_size;
++
++	if (!ia64_platform_is("sn2"))
++		return -ENODEV;
++
++	buf_size = max(XPC_RP_VARS_SIZE,
++		       XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES);
++	xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size,
++							       GFP_KERNEL,
++						  &xpc_remote_copy_buffer_base);
++	if (xpc_remote_copy_buffer == NULL)
++		return -ENOMEM;
++
++	snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
++	snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
++
++	xpc_sysctl = register_sysctl_table(xpc_sys_dir);
++
++	/*
++	 * The first few fields of each entry of xpc_partitions[] need to
++	 * be initialized now so that calls to xpc_connect() and
++	 * xpc_disconnect() can be made prior to the activation of any remote
++	 * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
++	 * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
++	 * PARTITION HAS BEEN ACTIVATED.
++	 */
++	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++		part = &xpc_partitions[partid];
++
++		DBUG_ON((u64)part != L1_CACHE_ALIGN((u64)part));
++
++		part->act_IRQ_rcvd = 0;
++		spin_lock_init(&part->act_lock);
++		part->act_state = XPC_P_INACTIVE;
++		XPC_SET_REASON(part, 0, 0);
++
++		init_timer(&part->disengage_request_timer);
++		part->disengage_request_timer.function =
++		    xpc_timeout_partition_disengage_request;
++		part->disengage_request_timer.data = (unsigned long)part;
++
++		part->setup_state = XPC_P_UNSET;
++		init_waitqueue_head(&part->teardown_wq);
++		atomic_set(&part->references, 0);
++	}
++
++	/*
++	 * Open up protections for IPI operations (and AMO operations on
++	 * Shub 1.1 systems).
++	 */
++	xpc_allow_IPI_ops();
++
++	/*
++	 * Interrupts being processed will increment this atomic variable and
++	 * awaken the heartbeat thread which will process the interrupts.
++	 */
++	atomic_set(&xpc_act_IRQ_rcvd, 0);
++
++	/*
++	 * This is safe to do before the xpc_hb_checker thread has started
++	 * because the handler releases a wait queue.  If an interrupt is
++	 * received before the thread is waiting, it will not go to sleep,
++	 * but rather immediately process the interrupt.
++	 */
++	ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0,
++			  "xpc hb", NULL);
++	if (ret != 0) {
++		dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
++			"errno=%d\n", -ret);
++
++		xpc_restrict_IPI_ops();
++
++		if (xpc_sysctl)
++			unregister_sysctl_table(xpc_sysctl);
++
++		kfree(xpc_remote_copy_buffer_base);
++		return -EBUSY;
++	}
++
++	/*
++	 * Fill the partition reserved page with the information needed by
++	 * other partitions to discover we are alive and establish initial
++	 * communications.
++	 */
++	xpc_rsvd_page = xpc_rsvd_page_init();
++	if (xpc_rsvd_page == NULL) {
++		dev_err(xpc_part, "could not setup our reserved page\n");
++
++		free_irq(SGI_XPC_ACTIVATE, NULL);
++		xpc_restrict_IPI_ops();
++
++		if (xpc_sysctl)
++			unregister_sysctl_table(xpc_sysctl);
++
++		kfree(xpc_remote_copy_buffer_base);
++		return -EBUSY;
++	}
++
++	/* add ourselves to the reboot_notifier_list */
++	ret = register_reboot_notifier(&xpc_reboot_notifier);
++	if (ret != 0)
++		dev_warn(xpc_part, "can't register reboot notifier\n");
++
++	/* add ourselves to the die_notifier list */
++	ret = register_die_notifier(&xpc_die_notifier);
++	if (ret != 0)
++		dev_warn(xpc_part, "can't register die notifier\n");
++
++	init_timer(&xpc_hb_timer);
++	xpc_hb_timer.function = xpc_hb_beater;
++
++	/*
++	 * The real work-horse behind xpc.  This processes incoming
++	 * interrupts and monitors remote heartbeats.
++	 */
++	kthread = kthread_run(xpc_hb_checker, NULL, XPC_HB_CHECK_THREAD_NAME);
++	if (IS_ERR(kthread)) {
++		dev_err(xpc_part, "failed while forking hb check thread\n");
++
++		/* indicate to others that our reserved page is uninitialized */
++		xpc_rsvd_page->vars_pa = 0;
++
++		/* take ourselves off of the reboot_notifier_list */
++		(void)unregister_reboot_notifier(&xpc_reboot_notifier);
++
++		/* take ourselves off of the die_notifier list */
++		(void)unregister_die_notifier(&xpc_die_notifier);
++
++		del_timer_sync(&xpc_hb_timer);
++		free_irq(SGI_XPC_ACTIVATE, NULL);
++		xpc_restrict_IPI_ops();
++
++		if (xpc_sysctl)
++			unregister_sysctl_table(xpc_sysctl);
++
++		kfree(xpc_remote_copy_buffer_base);
++		return -EBUSY;
++	}
++
++	/*
++	 * Startup a thread that will attempt to discover other partitions to
++	 * activate based on info provided by SAL. This new thread is short
++	 * lived and will exit once discovery is complete.
++	 */
++	kthread = kthread_run(xpc_initiate_discovery, NULL,
++			      XPC_DISCOVERY_THREAD_NAME);
++	if (IS_ERR(kthread)) {
++		dev_err(xpc_part, "failed while forking discovery thread\n");
++
++		/* mark this new thread as a non-starter */
++		complete(&xpc_discovery_exited);
++
++		xpc_do_exit(xpcUnloading);
++		return -EBUSY;
++	}
++
++	/* set the interface to point at XPC's functions */
++	xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,
++			  xpc_initiate_allocate, xpc_initiate_send,
++			  xpc_initiate_send_notify, xpc_initiate_received,
++			  xpc_initiate_partid_to_nasids);
++
++	return 0;
++}
++
++module_init(xpc_init);
++
++void __exit
++xpc_exit(void)
++{
++	xpc_do_exit(xpcUnloading);
++}
++
++module_exit(xpc_exit);
++
++MODULE_AUTHOR("Silicon Graphics, Inc.");
++MODULE_DESCRIPTION("Cross Partition Communication (XPC) support");
++MODULE_LICENSE("GPL");
++
++module_param(xpc_hb_interval, int, 0);
++MODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between "
++		 "heartbeat increments.");
++
++module_param(xpc_hb_check_interval, int, 0);
++MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "
++		 "heartbeat checks.");
++
++module_param(xpc_disengage_request_timelimit, int, 0);
++MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "
++		 "for disengage request to complete.");
++
++module_param(xpc_kdebug_ignore, int, 0);
++MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by "
++		 "other partitions when dropping into kdebug.");
+diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c
+new file mode 100644
+index 0000000..27e200e
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpc_partition.c
+@@ -0,0 +1,1174 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
++ */
++
++/*
++ * Cross Partition Communication (XPC) partition support.
++ *
++ *	This is the part of XPC that detects the presence/absence of
++ *	other partitions. It provides a heartbeat and monitors the
++ *	heartbeats of other partitions.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/sysctl.h>
++#include <linux/cache.h>
++#include <linux/mmzone.h>
++#include <linux/nodemask.h>
++#include <asm/uncached.h>
++#include <asm/sn/bte.h>
++#include <asm/sn/intr.h>
++#include <asm/sn/sn_sal.h>
++#include <asm/sn/nodepda.h>
++#include <asm/sn/addrs.h>
++#include "xpc.h"
++
++/* XPC is exiting flag */
++int xpc_exiting;
++
++/* SH_IPI_ACCESS shub register value on startup */
++static u64 xpc_sh1_IPI_access;
++static u64 xpc_sh2_IPI_access0;
++static u64 xpc_sh2_IPI_access1;
++static u64 xpc_sh2_IPI_access2;
++static u64 xpc_sh2_IPI_access3;
++
++/* original protection values for each node */
++u64 xpc_prot_vec[MAX_NUMNODES];
++
++/* this partition's reserved page pointers */
++struct xpc_rsvd_page *xpc_rsvd_page;
++static u64 *xpc_part_nasids;
++static u64 *xpc_mach_nasids;
++struct xpc_vars *xpc_vars;
++struct xpc_vars_part *xpc_vars_part;
++
++static int xp_nasid_mask_bytes;	/* actual size in bytes of nasid mask */
++static int xp_nasid_mask_words;	/* actual size in words of nasid mask */
++
++/*
++ * For performance reasons, each entry of xpc_partitions[] is cacheline
++ * aligned. And xpc_partitions[] is padded with an additional entry at the
++ * end so that the last legitimate entry doesn't share its cacheline with
++ * another variable.
++ */
++struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
++
++/*
++ * Generic buffer used to store a local copy of portions of a remote
++ * partition's reserved page (either its header and part_nasids mask,
++ * or its vars).
++ */
++char *xpc_remote_copy_buffer;
++void *xpc_remote_copy_buffer_base;
++
++/*
++ * Guarantee that the kmalloc'd memory is cacheline aligned.
++ */
++void *
++xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
++{
++	/* see if kmalloc will give us cachline aligned memory by default */
++	*base = kmalloc(size, flags);
++	if (*base == NULL)
++		return NULL;
++
++	if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
++		return *base;
++
++	kfree(*base);
++
++	/* nope, we'll have to do it ourselves */
++	*base = kmalloc(size + L1_CACHE_BYTES, flags);
++	if (*base == NULL)
++		return NULL;
++
++	return (void *)L1_CACHE_ALIGN((u64)*base);
++}
++
++/*
++ * Given a nasid, get the physical address of the  partition's reserved page
++ * for that nasid. This function returns 0 on any error.
++ */
++static u64
++xpc_get_rsvd_page_pa(int nasid)
++{
++	bte_result_t bte_res;
++	s64 status;
++	u64 cookie = 0;
++	u64 rp_pa = nasid;	/* seed with nasid */
++	u64 len = 0;
++	u64 buf = buf;
++	u64 buf_len = 0;
++	void *buf_base = NULL;
++
++	while (1) {
++
++		status = sn_partition_reserved_page_pa(buf, &cookie, &rp_pa,
++						       &len);
++
++		dev_dbg(xpc_part, "SAL returned with status=%li, cookie="
++			"0x%016lx, address=0x%016lx, len=0x%016lx\n",
++			status, cookie, rp_pa, len);
++
++		if (status != SALRET_MORE_PASSES)
++			break;
++
++		if (L1_CACHE_ALIGN(len) > buf_len) {
++			kfree(buf_base);
++			buf_len = L1_CACHE_ALIGN(len);
++			buf = (u64)xpc_kmalloc_cacheline_aligned(buf_len,
++								 GFP_KERNEL,
++								 &buf_base);
++			if (buf_base == NULL) {
++				dev_err(xpc_part, "unable to kmalloc "
++					"len=0x%016lx\n", buf_len);
++				status = SALRET_ERROR;
++				break;
++			}
++		}
++
++		bte_res = xp_bte_copy(rp_pa, buf, buf_len,
++				      (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++		if (bte_res != BTE_SUCCESS) {
++			dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
++			status = SALRET_ERROR;
++			break;
++		}
++	}
++
++	kfree(buf_base);
++
++	if (status != SALRET_OK)
++		rp_pa = 0;
++
++	dev_dbg(xpc_part, "reserved page at phys address 0x%016lx\n", rp_pa);
++	return rp_pa;
++}
++
++/*
++ * Fill the partition reserved page with the information needed by
++ * other partitions to discover we are alive and establish initial
++ * communications.
++ */
++struct xpc_rsvd_page *
++xpc_rsvd_page_init(void)
++{
++	struct xpc_rsvd_page *rp;
++	AMO_t *amos_page;
++	u64 rp_pa, nasid_array = 0;
++	int i, ret;
++
++	/* get the local reserved page's address */
++
++	preempt_disable();
++	rp_pa = xpc_get_rsvd_page_pa(cpuid_to_nasid(smp_processor_id()));
++	preempt_enable();
++	if (rp_pa == 0) {
++		dev_err(xpc_part, "SAL failed to locate the reserved page\n");
++		return NULL;
++	}
++	rp = (struct xpc_rsvd_page *)__va(rp_pa);
++
++	if (rp->partid != sn_partition_id) {
++		dev_err(xpc_part, "the reserved page's partid of %d should be "
++			"%d\n", rp->partid, sn_partition_id);
++		return NULL;
++	}
++
++	rp->version = XPC_RP_VERSION;
++
++	/* establish the actual sizes of the nasid masks */
++	if (rp->SAL_version == 1) {
++		/* SAL_version 1 didn't set the nasids_size field */
++		rp->nasids_size = 128;
++	}
++	xp_nasid_mask_bytes = rp->nasids_size;
++	xp_nasid_mask_words = xp_nasid_mask_bytes / 8;
++
++	/* setup the pointers to the various items in the reserved page */
++	xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
++	xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
++	xpc_vars = XPC_RP_VARS(rp);
++	xpc_vars_part = XPC_RP_VARS_PART(rp);
++
++	/*
++	 * Before clearing xpc_vars, see if a page of AMOs had been previously
++	 * allocated. If not we'll need to allocate one and set permissions
++	 * so that cross-partition AMOs are allowed.
++	 *
++	 * The allocated AMO page needs MCA reporting to remain disabled after
++	 * XPC has unloaded.  To make this work, we keep a copy of the pointer
++	 * to this page (i.e., amos_page) in the struct xpc_vars structure,
++	 * which is pointed to by the reserved page, and re-use that saved copy
++	 * on subsequent loads of XPC. This AMO page is never freed, and its
++	 * memory protections are never restricted.
++	 */
++	amos_page = xpc_vars->amos_page;
++	if (amos_page == NULL) {
++		amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0));
++		if (amos_page == NULL) {
++			dev_err(xpc_part, "can't allocate page of AMOs\n");
++			return NULL;
++		}
++
++		/*
++		 * Open up AMO-R/W to cpu.  This is done for Shub 1.1 systems
++		 * when xpc_allow_IPI_ops() is called via xpc_hb_init().
++		 */
++		if (!enable_shub_wars_1_1()) {
++			ret = sn_change_memprotect(ia64_tpa((u64)amos_page),
++						   PAGE_SIZE,
++						   SN_MEMPROT_ACCESS_CLASS_1,
++						   &nasid_array);
++			if (ret != 0) {
++				dev_err(xpc_part, "can't change memory "
++					"protections\n");
++				uncached_free_page(__IA64_UNCACHED_OFFSET |
++						   TO_PHYS((u64)amos_page));
++				return NULL;
++			}
++		}
++	} else if (!IS_AMO_ADDRESS((u64)amos_page)) {
++		/*
++		 * EFI's XPBOOT can also set amos_page in the reserved page,
++		 * but it happens to leave it as an uncached physical address
++		 * and we need it to be an uncached virtual, so we'll have to
++		 * convert it.
++		 */
++		if (!IS_AMO_PHYS_ADDRESS((u64)amos_page)) {
++			dev_err(xpc_part, "previously used amos_page address "
++				"is bad = 0x%p\n", (void *)amos_page);
++			return NULL;
++		}
++		amos_page = (AMO_t *)TO_AMO((u64)amos_page);
++	}
++
++	/* clear xpc_vars */
++	memset(xpc_vars, 0, sizeof(struct xpc_vars));
++
++	xpc_vars->version = XPC_V_VERSION;
++	xpc_vars->act_nasid = cpuid_to_nasid(0);
++	xpc_vars->act_phys_cpuid = cpu_physical_id(0);
++	xpc_vars->vars_part_pa = __pa(xpc_vars_part);
++	xpc_vars->amos_page_pa = ia64_tpa((u64)amos_page);
++	xpc_vars->amos_page = amos_page;	/* save for next load of XPC */
++
++	/* clear xpc_vars_part */
++	memset((u64 *)xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
++	       XP_MAX_PARTITIONS);
++
++	/* initialize the activate IRQ related AMO variables */
++	for (i = 0; i < xp_nasid_mask_words; i++)
++		(void)xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
++
++	/* initialize the engaged remote partitions related AMO variables */
++	(void)xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
++	(void)xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
++
++	/* timestamp of when reserved page was setup by XPC */
++	rp->stamp = CURRENT_TIME;
++
++	/*
++	 * This signifies to the remote partition that our reserved
++	 * page is initialized.
++	 */
++	rp->vars_pa = __pa(xpc_vars);
++
++	return rp;
++}
++
++/*
++ * Change protections to allow IPI operations (and AMO operations on
++ * Shub 1.1 systems).
++ */
++void
++xpc_allow_IPI_ops(void)
++{
++	int node;
++	int nasid;
++
++	/* >>> Change SH_IPI_ACCESS code to use SAL call once it is available */
++
++	if (is_shub2()) {
++		xpc_sh2_IPI_access0 =
++		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
++		xpc_sh2_IPI_access1 =
++		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
++		xpc_sh2_IPI_access2 =
++		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
++		xpc_sh2_IPI_access3 =
++		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
++
++		for_each_online_node(node) {
++			nasid = cnodeid_to_nasid(node);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
++			      -1UL);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
++			      -1UL);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
++			      -1UL);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
++			      -1UL);
++		}
++
++	} else {
++		xpc_sh1_IPI_access =
++		    (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
++
++		for_each_online_node(node) {
++			nasid = cnodeid_to_nasid(node);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
++			      -1UL);
++
++			/*
++			 * Since the BIST collides with memory operations on
++			 * SHUB 1.1 sn_change_memprotect() cannot be used.
++			 */
++			if (enable_shub_wars_1_1()) {
++				/* open up everything */
++				xpc_prot_vec[node] = (u64)HUB_L((u64 *)
++								GLOBAL_MMR_ADDR
++								(nasid,
++						  SH1_MD_DQLP_MMR_DIR_PRIVEC0));
++				HUB_S((u64 *)
++				      GLOBAL_MMR_ADDR(nasid,
++						   SH1_MD_DQLP_MMR_DIR_PRIVEC0),
++				      -1UL);
++				HUB_S((u64 *)
++				      GLOBAL_MMR_ADDR(nasid,
++						   SH1_MD_DQRP_MMR_DIR_PRIVEC0),
++				      -1UL);
++			}
++		}
++	}
++}
++
++/*
++ * Restrict protections to disallow IPI operations (and AMO operations on
++ * Shub 1.1 systems).
++ */
++void
++xpc_restrict_IPI_ops(void)
++{
++	int node;
++	int nasid;
++
++	/* >>> Change SH_IPI_ACCESS code to use SAL call once it is available */
++
++	if (is_shub2()) {
++
++		for_each_online_node(node) {
++			nasid = cnodeid_to_nasid(node);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
++			      xpc_sh2_IPI_access0);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
++			      xpc_sh2_IPI_access1);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
++			      xpc_sh2_IPI_access2);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
++			      xpc_sh2_IPI_access3);
++		}
++
++	} else {
++
++		for_each_online_node(node) {
++			nasid = cnodeid_to_nasid(node);
++			HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
++			      xpc_sh1_IPI_access);
++
++			if (enable_shub_wars_1_1()) {
++				HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
++						   SH1_MD_DQLP_MMR_DIR_PRIVEC0),
++				      xpc_prot_vec[node]);
++				HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
++						   SH1_MD_DQRP_MMR_DIR_PRIVEC0),
++				      xpc_prot_vec[node]);
++			}
++		}
++	}
++}
++
++/*
++ * At periodic intervals, scan through all active partitions and ensure
++ * their heartbeat is still active.  If not, the partition is deactivated.
++ */
++void
++xpc_check_remote_hb(void)
++{
++	struct xpc_vars *remote_vars;
++	struct xpc_partition *part;
++	partid_t partid;
++	bte_result_t bres;
++
++	remote_vars = (struct xpc_vars *)xpc_remote_copy_buffer;
++
++	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++
++		if (xpc_exiting)
++			break;
++
++		if (partid == sn_partition_id)
++			continue;
++
++		part = &xpc_partitions[partid];
++
++		if (part->act_state == XPC_P_INACTIVE ||
++		    part->act_state == XPC_P_DEACTIVATING) {
++			continue;
++		}
++
++		/* pull the remote_hb cache line */
++		bres = xp_bte_copy(part->remote_vars_pa,
++				   (u64)remote_vars,
++				   XPC_RP_VARS_SIZE,
++				   (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++		if (bres != BTE_SUCCESS) {
++			XPC_DEACTIVATE_PARTITION(part,
++						 xpc_map_bte_errors(bres));
++			continue;
++		}
++
++		dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
++			" = %ld, heartbeat_offline = %ld, HB_mask = 0x%lx\n",
++			partid, remote_vars->heartbeat, part->last_heartbeat,
++			remote_vars->heartbeat_offline,
++			remote_vars->heartbeating_to_mask);
++
++		if (((remote_vars->heartbeat == part->last_heartbeat) &&
++		     (remote_vars->heartbeat_offline == 0)) ||
++		    !xpc_hb_allowed(sn_partition_id, remote_vars)) {
++
++			XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);
++			continue;
++		}
++
++		part->last_heartbeat = remote_vars->heartbeat;
++	}
++}
++
++/*
++ * Get a copy of a portion of the remote partition's rsvd page.
++ *
++ * remote_rp points to a buffer that is cacheline aligned for BTE copies and
++ * is large enough to contain a copy of their reserved page header and
++ * part_nasids mask.
++ */
++static enum xpc_retval
++xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
++		  struct xpc_rsvd_page *remote_rp, u64 *remote_rp_pa)
++{
++	int bres, i;
++
++	/* get the reserved page's physical address */
++
++	*remote_rp_pa = xpc_get_rsvd_page_pa(nasid);
++	if (*remote_rp_pa == 0)
++		return xpcNoRsvdPageAddr;
++
++	/* pull over the reserved page header and part_nasids mask */
++	bres = xp_bte_copy(*remote_rp_pa, (u64)remote_rp,
++			   XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
++			   (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++	if (bres != BTE_SUCCESS)
++		return xpc_map_bte_errors(bres);
++
++	if (discovered_nasids != NULL) {
++		u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp);
++
++		for (i = 0; i < xp_nasid_mask_words; i++)
++			discovered_nasids[i] |= remote_part_nasids[i];
++	}
++
++	/* check that the partid is for another partition */
++
++	if (remote_rp->partid < 1 ||
++	    remote_rp->partid > (XP_MAX_PARTITIONS - 1)) {
++		return xpcInvalidPartid;
++	}
++
++	if (remote_rp->partid == sn_partition_id)
++		return xpcLocalPartid;
++
++	if (XPC_VERSION_MAJOR(remote_rp->version) !=
++	    XPC_VERSION_MAJOR(XPC_RP_VERSION)) {
++		return xpcBadVersion;
++	}
++
++	return xpcSuccess;
++}
++
++/*
++ * Get a copy of the remote partition's XPC variables from the reserved page.
++ *
++ * remote_vars points to a buffer that is cacheline aligned for BTE copies and
++ * assumed to be of size XPC_RP_VARS_SIZE.
++ */
++static enum xpc_retval
++xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
++{
++	int bres;
++
++	if (remote_vars_pa == 0)
++		return xpcVarsNotSet;
++
++	/* pull over the cross partition variables */
++	bres = xp_bte_copy(remote_vars_pa, (u64)remote_vars, XPC_RP_VARS_SIZE,
++			   (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++	if (bres != BTE_SUCCESS)
++		return xpc_map_bte_errors(bres);
++
++	if (XPC_VERSION_MAJOR(remote_vars->version) !=
++	    XPC_VERSION_MAJOR(XPC_V_VERSION)) {
++		return xpcBadVersion;
++	}
++
++	return xpcSuccess;
++}
++
++/*
++ * Update the remote partition's info.
++ */
++static void
++xpc_update_partition_info(struct xpc_partition *part, u8 remote_rp_version,
++			  struct timespec *remote_rp_stamp, u64 remote_rp_pa,
++			  u64 remote_vars_pa, struct xpc_vars *remote_vars)
++{
++	part->remote_rp_version = remote_rp_version;
++	dev_dbg(xpc_part, "  remote_rp_version = 0x%016x\n",
++		part->remote_rp_version);
++
++	part->remote_rp_stamp = *remote_rp_stamp;
++	dev_dbg(xpc_part, "  remote_rp_stamp (tv_sec = 0x%lx tv_nsec = 0x%lx\n",
++		part->remote_rp_stamp.tv_sec, part->remote_rp_stamp.tv_nsec);
++
++	part->remote_rp_pa = remote_rp_pa;
++	dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
++
++	part->remote_vars_pa = remote_vars_pa;
++	dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
++		part->remote_vars_pa);
++
++	part->last_heartbeat = remote_vars->heartbeat;
++	dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
++		part->last_heartbeat);
++
++	part->remote_vars_part_pa = remote_vars->vars_part_pa;
++	dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
++		part->remote_vars_part_pa);
++
++	part->remote_act_nasid = remote_vars->act_nasid;
++	dev_dbg(xpc_part, "  remote_act_nasid = 0x%x\n",
++		part->remote_act_nasid);
++
++	part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
++	dev_dbg(xpc_part, "  remote_act_phys_cpuid = 0x%x\n",
++		part->remote_act_phys_cpuid);
++
++	part->remote_amos_page_pa = remote_vars->amos_page_pa;
++	dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
++		part->remote_amos_page_pa);
++
++	part->remote_vars_version = remote_vars->version;
++	dev_dbg(xpc_part, "  remote_vars_version = 0x%x\n",
++		part->remote_vars_version);
++}
++
++/*
++ * Prior code has determined the nasid which generated an IPI.  Inspect
++ * that nasid to determine if its partition needs to be activated or
++ * deactivated.
++ *
++ * A partition is consider "awaiting activation" if our partition
++ * flags indicate it is not active and it has a heartbeat.  A
++ * partition is considered "awaiting deactivation" if our partition
++ * flags indicate it is active but it has no heartbeat or it is not
++ * sending its heartbeat to us.
++ *
++ * To determine the heartbeat, the remote nasid must have a properly
++ * initialized reserved page.
++ */
++static void
++xpc_identify_act_IRQ_req(int nasid)
++{
++	struct xpc_rsvd_page *remote_rp;
++	struct xpc_vars *remote_vars;
++	u64 remote_rp_pa;
++	u64 remote_vars_pa;
++	int remote_rp_version;
++	int reactivate = 0;
++	int stamp_diff;
++	struct timespec remote_rp_stamp = { 0, 0 };
++	partid_t partid;
++	struct xpc_partition *part;
++	enum xpc_retval ret;
++
++	/* pull over the reserved page structure */
++
++	remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer;
++
++	ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
++	if (ret != xpcSuccess) {
++		dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
++			 "which sent interrupt, reason=%d\n", nasid, ret);
++		return;
++	}
++
++	remote_vars_pa = remote_rp->vars_pa;
++	remote_rp_version = remote_rp->version;
++	if (XPC_SUPPORTS_RP_STAMP(remote_rp_version))
++		remote_rp_stamp = remote_rp->stamp;
++
++	partid = remote_rp->partid;
++	part = &xpc_partitions[partid];
++
++	/* pull over the cross partition variables */
++
++	remote_vars = (struct xpc_vars *)xpc_remote_copy_buffer;
++
++	ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
++	if (ret != xpcSuccess) {
++
++		dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
++			 "which sent interrupt, reason=%d\n", nasid, ret);
++
++		XPC_DEACTIVATE_PARTITION(part, ret);
++		return;
++	}
++
++	part->act_IRQ_rcvd++;
++
++	dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
++		"%ld:0x%lx\n", (int)nasid, (int)partid, part->act_IRQ_rcvd,
++		remote_vars->heartbeat, remote_vars->heartbeating_to_mask);
++
++	if (xpc_partition_disengaged(part) &&
++	    part->act_state == XPC_P_INACTIVE) {
++
++		xpc_update_partition_info(part, remote_rp_version,
++					  &remote_rp_stamp, remote_rp_pa,
++					  remote_vars_pa, remote_vars);
++
++		if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
++			if (xpc_partition_disengage_requested(1UL << partid)) {
++				/*
++				 * Other side is waiting on us to disengage,
++				 * even though we already have.
++				 */
++				return;
++			}
++		} else {
++			/* other side doesn't support disengage requests */
++			xpc_clear_partition_disengage_request(1UL << partid);
++		}
++
++		xpc_activate_partition(part);
++		return;
++	}
++
++	DBUG_ON(part->remote_rp_version == 0);
++	DBUG_ON(part->remote_vars_version == 0);
++
++	if (!XPC_SUPPORTS_RP_STAMP(part->remote_rp_version)) {
++		DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(part->
++						       remote_vars_version));
++
++		if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
++			DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
++							       version));
++			/* see if the other side rebooted */
++			if (part->remote_amos_page_pa ==
++			    remote_vars->amos_page_pa &&
++			    xpc_hb_allowed(sn_partition_id, remote_vars)) {
++				/* doesn't look that way, so ignore the IPI */
++				return;
++			}
++		}
++
++		/*
++		 * Other side rebooted and previous XPC didn't support the
++		 * disengage request, so we don't need to do anything special.
++		 */
++
++		xpc_update_partition_info(part, remote_rp_version,
++					  &remote_rp_stamp, remote_rp_pa,
++					  remote_vars_pa, remote_vars);
++		part->reactivate_nasid = nasid;
++		XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
++		return;
++	}
++
++	DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version));
++
++	if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
++		DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
++
++		/*
++		 * Other side rebooted and previous XPC did support the
++		 * disengage request, but the new one doesn't.
++		 */
++
++		xpc_clear_partition_engaged(1UL << partid);
++		xpc_clear_partition_disengage_request(1UL << partid);
++
++		xpc_update_partition_info(part, remote_rp_version,
++					  &remote_rp_stamp, remote_rp_pa,
++					  remote_vars_pa, remote_vars);
++		reactivate = 1;
++
++	} else {
++		DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
++
++		stamp_diff = xpc_compare_stamps(&part->remote_rp_stamp,
++						&remote_rp_stamp);
++		if (stamp_diff != 0) {
++			DBUG_ON(stamp_diff >= 0);
++
++			/*
++			 * Other side rebooted and the previous XPC did support
++			 * the disengage request, as does the new one.
++			 */
++
++			DBUG_ON(xpc_partition_engaged(1UL << partid));
++			DBUG_ON(xpc_partition_disengage_requested(1UL <<
++								  partid));
++
++			xpc_update_partition_info(part, remote_rp_version,
++						  &remote_rp_stamp,
++						  remote_rp_pa, remote_vars_pa,
++						  remote_vars);
++			reactivate = 1;
++		}
++	}
++
++	if (part->disengage_request_timeout > 0 &&
++	    !xpc_partition_disengaged(part)) {
++		/* still waiting on other side to disengage from us */
++		return;
++	}
++
++	if (reactivate) {
++		part->reactivate_nasid = nasid;
++		XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
++
++	} else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) &&
++		   xpc_partition_disengage_requested(1UL << partid)) {
++		XPC_DEACTIVATE_PARTITION(part, xpcOtherGoingDown);
++	}
++}
++
++/*
++ * Loop through the activation AMO variables and process any bits
++ * which are set.  Each bit indicates a nasid sending a partition
++ * activation or deactivation request.
++ *
++ * Return #of IRQs detected.
++ */
++int
++xpc_identify_act_IRQ_sender(void)
++{
++	int word, bit;
++	u64 nasid_mask;
++	u64 nasid;		/* remote nasid */
++	int n_IRQs_detected = 0;
++	AMO_t *act_amos;
++
++	act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
++
++	/* scan through act AMO variable looking for non-zero entries */
++	for (word = 0; word < xp_nasid_mask_words; word++) {
++
++		if (xpc_exiting)
++			break;
++
++		nasid_mask = xpc_IPI_receive(&act_amos[word]);
++		if (nasid_mask == 0) {
++			/* no IRQs from nasids in this variable */
++			continue;
++		}
++
++		dev_dbg(xpc_part, "AMO[%d] gave back 0x%lx\n", word,
++			nasid_mask);
++
++		/*
++		 * If this nasid has been added to the machine since
++		 * our partition was reset, this will retain the
++		 * remote nasid in our reserved pages machine mask.
++		 * This is used in the event of module reload.
++		 */
++		xpc_mach_nasids[word] |= nasid_mask;
++
++		/* locate the nasid(s) which sent interrupts */
++
++		for (bit = 0; bit < (8 * sizeof(u64)); bit++) {
++			if (nasid_mask & (1UL << bit)) {
++				n_IRQs_detected++;
++				nasid = XPC_NASID_FROM_W_B(word, bit);
++				dev_dbg(xpc_part, "interrupt from nasid %ld\n",
++					nasid);
++				xpc_identify_act_IRQ_req(nasid);
++			}
++		}
++	}
++	return n_IRQs_detected;
++}
++
++/*
++ * See if the other side has responded to a partition disengage request
++ * from us.
++ */
++int
++xpc_partition_disengaged(struct xpc_partition *part)
++{
++	partid_t partid = XPC_PARTID(part);
++	int disengaged;
++
++	disengaged = (xpc_partition_engaged(1UL << partid) == 0);
++	if (part->disengage_request_timeout) {
++		if (!disengaged) {
++			if (time_before(jiffies,
++			    part->disengage_request_timeout)) {
++				/* timelimit hasn't been reached yet */
++				return 0;
++			}
++
++			/*
++			 * Other side hasn't responded to our disengage
++			 * request in a timely fashion, so assume it's dead.
++			 */
++
++			dev_info(xpc_part, "disengage from remote partition %d "
++				 "timed out\n", partid);
++			xpc_disengage_request_timedout = 1;
++			xpc_clear_partition_engaged(1UL << partid);
++			disengaged = 1;
++		}
++		part->disengage_request_timeout = 0;
++
++		/* cancel the timer function, provided it's not us */
++		if (!in_interrupt()) {
++			del_singleshot_timer_sync(&part->
++						  disengage_request_timer);
++		}
++
++		DBUG_ON(part->act_state != XPC_P_DEACTIVATING &&
++			part->act_state != XPC_P_INACTIVE);
++		if (part->act_state != XPC_P_INACTIVE)
++			xpc_wakeup_channel_mgr(part);
++
++		if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version))
++			xpc_cancel_partition_disengage_request(part);
++	}
++	return disengaged;
++}
++
++/*
++ * Mark specified partition as active.
++ */
++enum xpc_retval
++xpc_mark_partition_active(struct xpc_partition *part)
++{
++	unsigned long irq_flags;
++	enum xpc_retval ret;
++
++	dev_dbg(xpc_part, "setting partition %d to ACTIVE\n", XPC_PARTID(part));
++
++	spin_lock_irqsave(&part->act_lock, irq_flags);
++	if (part->act_state == XPC_P_ACTIVATING) {
++		part->act_state = XPC_P_ACTIVE;
++		ret = xpcSuccess;
++	} else {
++		DBUG_ON(part->reason == xpcSuccess);
++		ret = part->reason;
++	}
++	spin_unlock_irqrestore(&part->act_lock, irq_flags);
++
++	return ret;
++}
++
++/*
++ * Notify XPC that the partition is down.
++ */
++void
++xpc_deactivate_partition(const int line, struct xpc_partition *part,
++			 enum xpc_retval reason)
++{
++	unsigned long irq_flags;
++
++	spin_lock_irqsave(&part->act_lock, irq_flags);
++
++	if (part->act_state == XPC_P_INACTIVE) {
++		XPC_SET_REASON(part, reason, line);
++		spin_unlock_irqrestore(&part->act_lock, irq_flags);
++		if (reason == xpcReactivating) {
++			/* we interrupt ourselves to reactivate partition */
++			xpc_IPI_send_reactivate(part);
++		}
++		return;
++	}
++	if (part->act_state == XPC_P_DEACTIVATING) {
++		if ((part->reason == xpcUnloading && reason != xpcUnloading) ||
++		    reason == xpcReactivating) {
++			XPC_SET_REASON(part, reason, line);
++		}
++		spin_unlock_irqrestore(&part->act_lock, irq_flags);
++		return;
++	}
++
++	part->act_state = XPC_P_DEACTIVATING;
++	XPC_SET_REASON(part, reason, line);
++
++	spin_unlock_irqrestore(&part->act_lock, irq_flags);
++
++	if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
++		xpc_request_partition_disengage(part);
++		xpc_IPI_send_disengage(part);
++
++		/* set a timelimit on the disengage request */
++		part->disengage_request_timeout = jiffies +
++		    (xpc_disengage_request_timelimit * HZ);
++		part->disengage_request_timer.expires =
++		    part->disengage_request_timeout;
++		add_timer(&part->disengage_request_timer);
++	}
++
++	dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
++		XPC_PARTID(part), reason);
++
++	xpc_partition_going_down(part, reason);
++}
++
++/*
++ * Mark specified partition as inactive.
++ */
++void
++xpc_mark_partition_inactive(struct xpc_partition *part)
++{
++	unsigned long irq_flags;
++
++	dev_dbg(xpc_part, "setting partition %d to INACTIVE\n",
++		XPC_PARTID(part));
++
++	spin_lock_irqsave(&part->act_lock, irq_flags);
++	part->act_state = XPC_P_INACTIVE;
++	spin_unlock_irqrestore(&part->act_lock, irq_flags);
++	part->remote_rp_pa = 0;
++}
++
++/*
++ * SAL has provided a partition and machine mask.  The partition mask
++ * contains a bit for each even nasid in our partition.  The machine
++ * mask contains a bit for each even nasid in the entire machine.
++ *
++ * Using those two bit arrays, we can determine which nasids are
++ * known in the machine.  Each should also have a reserved page
++ * initialized if they are available for partitioning.
++ */
++void
++xpc_discovery(void)
++{
++	void *remote_rp_base;
++	struct xpc_rsvd_page *remote_rp;
++	struct xpc_vars *remote_vars;
++	u64 remote_rp_pa;
++	u64 remote_vars_pa;
++	int region;
++	int region_size;
++	int max_regions;
++	int nasid;
++	struct xpc_rsvd_page *rp;
++	partid_t partid;
++	struct xpc_partition *part;
++	u64 *discovered_nasids;
++	enum xpc_retval ret;
++
++	remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
++						  xp_nasid_mask_bytes,
++						  GFP_KERNEL, &remote_rp_base);
++	if (remote_rp == NULL)
++		return;
++
++	remote_vars = (struct xpc_vars *)remote_rp;
++
++	discovered_nasids = kzalloc(sizeof(u64) * xp_nasid_mask_words,
++				    GFP_KERNEL);
++	if (discovered_nasids == NULL) {
++		kfree(remote_rp_base);
++		return;
++	}
++
++	rp = (struct xpc_rsvd_page *)xpc_rsvd_page;
++
++	/*
++	 * The term 'region' in this context refers to the minimum number of
++	 * nodes that can comprise an access protection grouping. The access
++	 * protection is in regards to memory, IOI and IPI.
++	 */
++	max_regions = 64;
++	region_size = sn_region_size;
++
++	switch (region_size) {
++	case 128:
++		max_regions *= 2;
++	case 64:
++		max_regions *= 2;
++	case 32:
++		max_regions *= 2;
++		region_size = 16;
++		DBUG_ON(!is_shub2());
++	}
++
++	for (region = 0; region < max_regions; region++) {
++
++		if (xpc_exiting)
++			break;
++
++		dev_dbg(xpc_part, "searching region %d\n", region);
++
++		for (nasid = (region * region_size * 2);
++		     nasid < ((region + 1) * region_size * 2); nasid += 2) {
++
++			if (xpc_exiting)
++				break;
++
++			dev_dbg(xpc_part, "checking nasid %d\n", nasid);
++
++			if (XPC_NASID_IN_ARRAY(nasid, xpc_part_nasids)) {
++				dev_dbg(xpc_part, "PROM indicates Nasid %d is "
++					"part of the local partition; skipping "
++					"region\n", nasid);
++				break;
++			}
++
++			if (!(XPC_NASID_IN_ARRAY(nasid, xpc_mach_nasids))) {
++				dev_dbg(xpc_part, "PROM indicates Nasid %d was "
++					"not on Numa-Link network at reset\n",
++					nasid);
++				continue;
++			}
++
++			if (XPC_NASID_IN_ARRAY(nasid, discovered_nasids)) {
++				dev_dbg(xpc_part, "Nasid %d is part of a "
++					"partition which was previously "
++					"discovered\n", nasid);
++				continue;
++			}
++
++			/* pull over the reserved page structure */
++
++			ret = xpc_get_remote_rp(nasid, discovered_nasids,
++						remote_rp, &remote_rp_pa);
++			if (ret != xpcSuccess) {
++				dev_dbg(xpc_part, "unable to get reserved page "
++					"from nasid %d, reason=%d\n", nasid,
++					ret);
++
++				if (ret == xpcLocalPartid)
++					break;
++
++				continue;
++			}
++
++			remote_vars_pa = remote_rp->vars_pa;
++
++			partid = remote_rp->partid;
++			part = &xpc_partitions[partid];
++
++			/* pull over the cross partition variables */
++
++			ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
++			if (ret != xpcSuccess) {
++				dev_dbg(xpc_part, "unable to get XPC variables "
++					"from nasid %d, reason=%d\n", nasid,
++					ret);
++
++				XPC_DEACTIVATE_PARTITION(part, ret);
++				continue;
++			}
++
++			if (part->act_state != XPC_P_INACTIVE) {
++				dev_dbg(xpc_part, "partition %d on nasid %d is "
++					"already activating\n", partid, nasid);
++				break;
++			}
++
++			/*
++			 * Register the remote partition's AMOs with SAL so it
++			 * can handle and cleanup errors within that address
++			 * range should the remote partition go down. We don't
++			 * unregister this range because it is difficult to
++			 * tell when outstanding writes to the remote partition
++			 * are finished and thus when it is thus safe to
++			 * unregister. This should not result in wasted space
++			 * in the SAL xp_addr_region table because we should
++			 * get the same page for remote_act_amos_pa after
++			 * module reloads and system reboots.
++			 */
++			if (sn_register_xp_addr_region
++			    (remote_vars->amos_page_pa, PAGE_SIZE, 1) < 0) {
++				dev_dbg(xpc_part,
++					"partition %d failed to "
++					"register xp_addr region 0x%016lx\n",
++					partid, remote_vars->amos_page_pa);
++
++				XPC_SET_REASON(part, xpcPhysAddrRegFailed,
++					       __LINE__);
++				break;
++			}
++
++			/*
++			 * The remote nasid is valid and available.
++			 * Send an interrupt to that nasid to notify
++			 * it that we are ready to begin activation.
++			 */
++			dev_dbg(xpc_part, "sending an interrupt to AMO 0x%lx, "
++				"nasid %d, phys_cpuid 0x%x\n",
++				remote_vars->amos_page_pa,
++				remote_vars->act_nasid,
++				remote_vars->act_phys_cpuid);
++
++			if (XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
++							   version)) {
++				part->remote_amos_page_pa =
++				    remote_vars->amos_page_pa;
++				xpc_mark_partition_disengaged(part);
++				xpc_cancel_partition_disengage_request(part);
++			}
++			xpc_IPI_send_activate(remote_vars);
++		}
++	}
++
++	kfree(discovered_nasids);
++	kfree(remote_rp_base);
++}
++
++/*
++ * Given a partid, get the nasids owned by that partition from the
++ * remote partition's reserved page.
++ */
++enum xpc_retval
++xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
++{
++	struct xpc_partition *part;
++	u64 part_nasid_pa;
++	int bte_res;
++
++	part = &xpc_partitions[partid];
++	if (part->remote_rp_pa == 0)
++		return xpcPartitionDown;
++
++	memset(nasid_mask, 0, XP_NASID_MASK_BYTES);
++
++	part_nasid_pa = (u64)XPC_RP_PART_NASIDS(part->remote_rp_pa);
++
++	bte_res = xp_bte_copy(part_nasid_pa, (u64)nasid_mask,
++			      xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE),
++			      NULL);
++
++	return xpc_map_bte_errors(bte_res);
++}
+diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
+new file mode 100644
+index 0000000..a9543c6
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpnet.c
+@@ -0,0 +1,677 @@
++/*
++ * 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) 1999-2008 Silicon Graphics, Inc. All rights reserved.
++ */
++
++/*
++ * Cross Partition Network Interface (XPNET) support
++ *
++ *	XPNET provides a virtual network layered on top of the Cross
++ *	Partition communication layer.
++ *
++ *	XPNET provides direct point-to-point and broadcast-like support
++ *	for an ethernet-like device.  The ethernet broadcast medium is
++ *	replaced with a point-to-point message structure which passes
++ *	pointers to a DMA-capable block that a remote partition should
++ *	retrieve and pass to the upper level networking layer.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/smp.h>
++#include <linux/string.h>
++#include <asm/sn/bte.h>
++#include <asm/sn/io.h>
++#include <asm/sn/sn_sal.h>
++#include <asm/atomic.h>
++#include "xp.h"
++
++/*
++ * The message payload transferred by XPC.
++ *
++ * buf_pa is the physical address where the DMA should pull from.
++ *
++ * NOTE: for performance reasons, buf_pa should _ALWAYS_ begin on a
++ * cacheline boundary.  To accomplish this, we record the number of
++ * bytes from the beginning of the first cacheline to the first useful
++ * byte of the skb (leadin_ignore) and the number of bytes from the
++ * last useful byte of the skb to the end of the last cacheline
++ * (tailout_ignore).
++ *
++ * size is the number of bytes to transfer which includes the skb->len
++ * (useful bytes of the senders skb) plus the leadin and tailout
++ */
++struct xpnet_message {
++	u16 version;		/* Version for this message */
++	u16 embedded_bytes;	/* #of bytes embedded in XPC message */
++	u32 magic;		/* Special number indicating this is xpnet */
++	u64 buf_pa;		/* phys address of buffer to retrieve */
++	u32 size;		/* #of bytes in buffer */
++	u8 leadin_ignore;	/* #of bytes to ignore at the beginning */
++	u8 tailout_ignore;	/* #of bytes to ignore at the end */
++	unsigned char data;	/* body of small packets */
++};
++
++/*
++ * Determine the size of our message, the cacheline aligned size,
++ * and then the number of message will request from XPC.
++ *
++ * XPC expects each message to exist in an individual cacheline.
++ */
++#define XPNET_MSG_SIZE		(L1_CACHE_BYTES - XPC_MSG_PAYLOAD_OFFSET)
++#define XPNET_MSG_DATA_MAX	\
++		(XPNET_MSG_SIZE - (u64)(&((struct xpnet_message *)0)->data))
++#define XPNET_MSG_ALIGNED_SIZE	(L1_CACHE_ALIGN(XPNET_MSG_SIZE))
++#define XPNET_MSG_NENTRIES	(PAGE_SIZE / XPNET_MSG_ALIGNED_SIZE)
++
++#define XPNET_MAX_KTHREADS	(XPNET_MSG_NENTRIES + 1)
++#define XPNET_MAX_IDLE_KTHREADS	(XPNET_MSG_NENTRIES + 1)
++
++/*
++ * Version number of XPNET implementation. XPNET can always talk to versions
++ * with same major #, and never talk to versions with a different version.
++ */
++#define _XPNET_VERSION(_major, _minor)	(((_major) << 4) | (_minor))
++#define XPNET_VERSION_MAJOR(_v)		((_v) >> 4)
++#define XPNET_VERSION_MINOR(_v)		((_v) & 0xf)
++
++#define	XPNET_VERSION _XPNET_VERSION(1, 0)	/* version 1.0 */
++#define	XPNET_VERSION_EMBED _XPNET_VERSION(1, 1)	/* version 1.1 */
++#define XPNET_MAGIC	0x88786984	/* "XNET" */
++
++#define XPNET_VALID_MSG(_m)						     \
++   ((XPNET_VERSION_MAJOR(_m->version) == XPNET_VERSION_MAJOR(XPNET_VERSION)) \
++    && (msg->magic == XPNET_MAGIC))
++
++#define XPNET_DEVICE_NAME		"xp0"
++
++/*
++ * When messages are queued with xpc_send_notify, a kmalloc'd buffer
++ * of the following type is passed as a notification cookie.  When the
++ * notification function is called, we use the cookie to decide
++ * whether all outstanding message sends have completed.  The skb can
++ * then be released.
++ */
++struct xpnet_pending_msg {
++	struct list_head free_list;
++	struct sk_buff *skb;
++	atomic_t use_count;
++};
++
++/* driver specific structure pointed to by the device structure */
++struct xpnet_dev_private {
++	struct net_device_stats stats;
++};
++
++struct net_device *xpnet_device;
++
++/*
++ * When we are notified of other partitions activating, we add them to
++ * our bitmask of partitions to which we broadcast.
++ */
++static u64 xpnet_broadcast_partitions;
++/* protect above */
++static DEFINE_SPINLOCK(xpnet_broadcast_lock);
++
++/*
++ * Since the Block Transfer Engine (BTE) is being used for the transfer
++ * and it relies upon cache-line size transfers, we need to reserve at
++ * least one cache-line for head and tail alignment.  The BTE is
++ * limited to 8MB transfers.
++ *
++ * Testing has shown that changing MTU to greater than 64KB has no effect
++ * on TCP as the two sides negotiate a Max Segment Size that is limited
++ * to 64K.  Other protocols May use packets greater than this, but for
++ * now, the default is 64KB.
++ */
++#define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
++/* 32KB has been determined to be the ideal */
++#define XPNET_DEF_MTU (0x8000UL)
++
++/*
++ * The partition id is encapsulated in the MAC address.  The following
++ * define locates the octet the partid is in.
++ */
++#define XPNET_PARTID_OCTET	1
++#define XPNET_LICENSE_OCTET	2
++
++/*
++ * Define the XPNET debug device structure that is to be used with dev_dbg(),
++ * dev_err(), dev_warn(), and dev_info().
++ */
++struct device_driver xpnet_dbg_name = {
++	.name = "xpnet"
++};
++
++struct device xpnet_dbg_subname = {
++	.bus_id = {0},		/* set to "" */
++	.driver = &xpnet_dbg_name
++};
++
++struct device *xpnet = &xpnet_dbg_subname;
++
++/*
++ * Packet was recevied by XPC and forwarded to us.
++ */
++static void
++xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg)
++{
++	struct sk_buff *skb;
++	bte_result_t bret;
++	struct xpnet_dev_private *priv =
++	    (struct xpnet_dev_private *)xpnet_device->priv;
++
++	if (!XPNET_VALID_MSG(msg)) {
++		/*
++		 * Packet with a different XPC version.  Ignore.
++		 */
++		xpc_received(partid, channel, (void *)msg);
++
++		priv->stats.rx_errors++;
++
++		return;
++	}
++	dev_dbg(xpnet, "received 0x%lx, %d, %d, %d\n", msg->buf_pa, msg->size,
++		msg->leadin_ignore, msg->tailout_ignore);
++
++	/* reserve an extra cache line */
++	skb = dev_alloc_skb(msg->size + L1_CACHE_BYTES);
++	if (!skb) {
++		dev_err(xpnet, "failed on dev_alloc_skb(%d)\n",
++			msg->size + L1_CACHE_BYTES);
++
++		xpc_received(partid, channel, (void *)msg);
++
++		priv->stats.rx_errors++;
++
++		return;
++	}
++
++	/*
++	 * The allocated skb has some reserved space.
++	 * In order to use bte_copy, we need to get the
++	 * skb->data pointer moved forward.
++	 */
++	skb_reserve(skb, (L1_CACHE_BYTES - ((u64)skb->data &
++					    (L1_CACHE_BYTES - 1)) +
++			  msg->leadin_ignore));
++
++	/*
++	 * Update the tail pointer to indicate data actually
++	 * transferred.
++	 */
++	skb_put(skb, (msg->size - msg->leadin_ignore - msg->tailout_ignore));
++
++	/*
++	 * Move the data over from the other side.
++	 */
++	if ((XPNET_VERSION_MINOR(msg->version) == 1) &&
++	    (msg->embedded_bytes != 0)) {
++		dev_dbg(xpnet, "copying embedded message. memcpy(0x%p, 0x%p, "
++			"%lu)\n", skb->data, &msg->data,
++			(size_t)msg->embedded_bytes);
++
++		skb_copy_to_linear_data(skb, &msg->data,
++					(size_t)msg->embedded_bytes);
++	} else {
++		dev_dbg(xpnet, "transferring buffer to the skb->data area;\n\t"
++			"bte_copy(0x%p, 0x%p, %hu)\n", (void *)msg->buf_pa,
++			(void *)__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
++			msg->size);
++
++		bret = bte_copy(msg->buf_pa,
++				__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
++				msg->size, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++
++		if (bret != BTE_SUCCESS) {
++			/*
++			 * >>> Need better way of cleaning skb.  Currently skb
++			 * >>> appears in_use and we can't just call
++			 * >>> dev_kfree_skb.
++			 */
++			dev_err(xpnet, "bte_copy(0x%p, 0x%p, 0x%hx) returned "
++				"error=0x%x\n", (void *)msg->buf_pa,
++				(void *)__pa((u64)skb->data &
++					     ~(L1_CACHE_BYTES - 1)),
++				msg->size, bret);
++
++			xpc_received(partid, channel, (void *)msg);
++
++			priv->stats.rx_errors++;
++
++			return;
++		}
++	}
++
++	dev_dbg(xpnet, "<skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
++		"skb->end=0x%p skb->len=%d\n", (void *)skb->head,
++		(void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
++		skb->len);
++
++	skb->protocol = eth_type_trans(skb, xpnet_device);
++	skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++	dev_dbg(xpnet, "passing skb to network layer\n"
++		KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
++		"skb->end=0x%p skb->len=%d\n",
++		(void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
++		skb_end_pointer(skb), skb->len);
++
++	xpnet_device->last_rx = jiffies;
++	priv->stats.rx_packets++;
++	priv->stats.rx_bytes += skb->len + ETH_HLEN;
++
++	netif_rx_ni(skb);
++	xpc_received(partid, channel, (void *)msg);
++}
++
++/*
++ * This is the handler which XPC calls during any sort of change in
++ * state or message reception on a connection.
++ */
++static void
++xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel,
++			  void *data, void *key)
++{
++	long bp;
++
++	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++	DBUG_ON(channel != XPC_NET_CHANNEL);
++
++	switch (reason) {
++	case xpcMsgReceived:	/* message received */
++		DBUG_ON(data == NULL);
++
++		xpnet_receive(partid, channel, (struct xpnet_message *)data);
++		break;
++
++	case xpcConnected:	/* connection completed to a partition */
++		spin_lock_bh(&xpnet_broadcast_lock);
++		xpnet_broadcast_partitions |= 1UL << (partid - 1);
++		bp = xpnet_broadcast_partitions;
++		spin_unlock_bh(&xpnet_broadcast_lock);
++
++		netif_carrier_on(xpnet_device);
++
++		dev_dbg(xpnet, "%s connection created to partition %d; "
++			"xpnet_broadcast_partitions=0x%lx\n",
++			xpnet_device->name, partid, bp);
++		break;
++
++	default:
++		spin_lock_bh(&xpnet_broadcast_lock);
++		xpnet_broadcast_partitions &= ~(1UL << (partid - 1));
++		bp = xpnet_broadcast_partitions;
++		spin_unlock_bh(&xpnet_broadcast_lock);
++
++		if (bp == 0)
++			netif_carrier_off(xpnet_device);
++
++		dev_dbg(xpnet, "%s disconnected from partition %d; "
++			"xpnet_broadcast_partitions=0x%lx\n",
++			xpnet_device->name, partid, bp);
++		break;
++
++	}
++}
++
++static int
++xpnet_dev_open(struct net_device *dev)
++{
++	enum xpc_retval ret;
++
++	dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %ld, "
++		"%ld)\n", XPC_NET_CHANNEL, xpnet_connection_activity,
++		XPNET_MSG_SIZE, XPNET_MSG_NENTRIES, XPNET_MAX_KTHREADS,
++		XPNET_MAX_IDLE_KTHREADS);
++
++	ret = xpc_connect(XPC_NET_CHANNEL, xpnet_connection_activity, NULL,
++			  XPNET_MSG_SIZE, XPNET_MSG_NENTRIES,
++			  XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS);
++	if (ret != xpcSuccess) {
++		dev_err(xpnet, "ifconfig up of %s failed on XPC connect, "
++			"ret=%d\n", dev->name, ret);
++
++		return -ENOMEM;
++	}
++
++	dev_dbg(xpnet, "ifconfig up of %s; XPC connected\n", dev->name);
++
++	return 0;
++}
++
++static int
++xpnet_dev_stop(struct net_device *dev)
++{
++	xpc_disconnect(XPC_NET_CHANNEL);
++
++	dev_dbg(xpnet, "ifconfig down of %s; XPC disconnected\n", dev->name);
++
++	return 0;
++}
++
++static int
++xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
++{
++	/* 68 comes from min TCP+IP+MAC header */
++	if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {
++		dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "
++			"between 68 and %ld\n", dev->name, new_mtu,
++			XPNET_MAX_MTU);
++		return -EINVAL;
++	}
++
++	dev->mtu = new_mtu;
++	dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);
++	return 0;
++}
++
++/*
++ * Required for the net_device structure.
++ */
++static int
++xpnet_dev_set_config(struct net_device *dev, struct ifmap *new_map)
++{
++	return 0;
++}
++
++/*
++ * Return statistics to the caller.
++ */
++static struct net_device_stats *
++xpnet_dev_get_stats(struct net_device *dev)
++{
++	struct xpnet_dev_private *priv;
++
++	priv = (struct xpnet_dev_private *)dev->priv;
++
++	return &priv->stats;
++}
++
++/*
++ * Notification that the other end has received the message and
++ * DMA'd the skb information.  At this point, they are done with
++ * our side.  When all recipients are done processing, we
++ * release the skb and then release our pending message structure.
++ */
++static void
++xpnet_send_completed(enum xpc_retval reason, partid_t partid, int channel,
++		     void *__qm)
++{
++	struct xpnet_pending_msg *queued_msg = (struct xpnet_pending_msg *)__qm;
++
++	DBUG_ON(queued_msg == NULL);
++
++	dev_dbg(xpnet, "message to %d notified with reason %d\n",
++		partid, reason);
++
++	if (atomic_dec_return(&queued_msg->use_count) == 0) {
++		dev_dbg(xpnet, "all acks for skb->head=-x%p\n",
++			(void *)queued_msg->skb->head);
++
++		dev_kfree_skb_any(queued_msg->skb);
++		kfree(queued_msg);
++	}
++}
++
++/*
++ * Network layer has formatted a packet (skb) and is ready to place it
++ * "on the wire".  Prepare and send an xpnet_message to all partitions
++ * which have connected with us and are targets of this packet.
++ *
++ * MAC-NOTE:  For the XPNET driver, the MAC address contains the
++ * destination partition_id.  If the destination partition id word
++ * is 0xff, this packet is to broadcast to all partitions.
++ */
++static int
++xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	struct xpnet_pending_msg *queued_msg;
++	enum xpc_retval ret;
++	struct xpnet_message *msg;
++	u64 start_addr, end_addr;
++	long dp;
++	u8 second_mac_octet;
++	partid_t dest_partid;
++	struct xpnet_dev_private *priv;
++	u16 embedded_bytes;
++
++	priv = (struct xpnet_dev_private *)dev->priv;
++
++	dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
++		"skb->end=0x%p skb->len=%d\n", (void *)skb->head,
++		(void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
++		skb->len);
++
++	/*
++	 * The xpnet_pending_msg tracks how many outstanding
++	 * xpc_send_notifies are relying on this skb.  When none
++	 * remain, release the skb.
++	 */
++	queued_msg = kmalloc(sizeof(struct xpnet_pending_msg), GFP_ATOMIC);
++	if (queued_msg == NULL) {
++		dev_warn(xpnet, "failed to kmalloc %ld bytes; dropping "
++			 "packet\n", sizeof(struct xpnet_pending_msg));
++
++		priv->stats.tx_errors++;
++
++		return -ENOMEM;
++	}
++
++	/* get the beginning of the first cacheline and end of last */
++	start_addr = ((u64)skb->data & ~(L1_CACHE_BYTES - 1));
++	end_addr = L1_CACHE_ALIGN((u64)skb_tail_pointer(skb));
++
++	/* calculate how many bytes to embed in the XPC message */
++	embedded_bytes = 0;
++	if (unlikely(skb->len <= XPNET_MSG_DATA_MAX)) {
++		/* skb->data does fit so embed */
++		embedded_bytes = skb->len;
++	}
++
++	/*
++	 * Since the send occurs asynchronously, we set the count to one
++	 * and begin sending.  Any sends that happen to complete before
++	 * we are done sending will not free the skb.  We will be left
++	 * with that task during exit.  This also handles the case of
++	 * a packet destined for a partition which is no longer up.
++	 */
++	atomic_set(&queued_msg->use_count, 1);
++	queued_msg->skb = skb;
++
++	second_mac_octet = skb->data[XPNET_PARTID_OCTET];
++	if (second_mac_octet == 0xff) {
++		/* we are being asked to broadcast to all partitions */
++		dp = xpnet_broadcast_partitions;
++	} else if (second_mac_octet != 0) {
++		dp = xpnet_broadcast_partitions &
++		    (1UL << (second_mac_octet - 1));
++	} else {
++		/* 0 is an invalid partid.  Ignore */
++		dp = 0;
++	}
++	dev_dbg(xpnet, "destination Partitions mask (dp) = 0x%lx\n", dp);
++
++	/*
++	 * If we wanted to allow promiscuous mode to work like an
++	 * unswitched network, this would be a good point to OR in a
++	 * mask of partitions which should be receiving all packets.
++	 */
++
++	/*
++	 * Main send loop.
++	 */
++	for (dest_partid = 1; dp && dest_partid < XP_MAX_PARTITIONS;
++	     dest_partid++) {
++
++		if (!(dp & (1UL << (dest_partid - 1)))) {
++			/* not destined for this partition */
++			continue;
++		}
++
++		/* remove this partition from the destinations mask */
++		dp &= ~(1UL << (dest_partid - 1));
++
++		/* found a partition to send to */
++
++		ret = xpc_allocate(dest_partid, XPC_NET_CHANNEL,
++				   XPC_NOWAIT, (void **)&msg);
++		if (unlikely(ret != xpcSuccess))
++			continue;
++
++		msg->embedded_bytes = embedded_bytes;
++		if (unlikely(embedded_bytes != 0)) {
++			msg->version = XPNET_VERSION_EMBED;
++			dev_dbg(xpnet, "calling memcpy(0x%p, 0x%p, 0x%lx)\n",
++				&msg->data, skb->data, (size_t)embedded_bytes);
++			skb_copy_from_linear_data(skb, &msg->data,
++						  (size_t)embedded_bytes);
++		} else {
++			msg->version = XPNET_VERSION;
++		}
++		msg->magic = XPNET_MAGIC;
++		msg->size = end_addr - start_addr;
++		msg->leadin_ignore = (u64)skb->data - start_addr;
++		msg->tailout_ignore = end_addr - (u64)skb_tail_pointer(skb);
++		msg->buf_pa = __pa(start_addr);
++
++		dev_dbg(xpnet, "sending XPC message to %d:%d\n"
++			KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, "
++			"msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
++			dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
++			msg->leadin_ignore, msg->tailout_ignore);
++
++		atomic_inc(&queued_msg->use_count);
++
++		ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, msg,
++				      xpnet_send_completed, queued_msg);
++		if (unlikely(ret != xpcSuccess)) {
++			atomic_dec(&queued_msg->use_count);
++			continue;
++		}
++	}
++
++	if (atomic_dec_return(&queued_msg->use_count) == 0) {
++		dev_dbg(xpnet, "no partitions to receive packet destined for "
++			"%d\n", dest_partid);
++
++		dev_kfree_skb(skb);
++		kfree(queued_msg);
++	}
++
++	priv->stats.tx_packets++;
++	priv->stats.tx_bytes += skb->len;
++
++	return 0;
++}
++
++/*
++ * Deal with transmit timeouts coming from the network layer.
++ */
++static void
++xpnet_dev_tx_timeout(struct net_device *dev)
++{
++	struct xpnet_dev_private *priv;
++
++	priv = (struct xpnet_dev_private *)dev->priv;
++
++	priv->stats.tx_errors++;
++	return;
++}
++
++static int __init
++xpnet_init(void)
++{
++	int i;
++	u32 license_num;
++	int result = -ENOMEM;
++
++	if (!ia64_platform_is("sn2"))
++		return -ENODEV;
++
++	dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
++
++	/*
++	 * use ether_setup() to init the majority of our device
++	 * structure and then override the necessary pieces.
++	 */
++	xpnet_device = alloc_netdev(sizeof(struct xpnet_dev_private),
++				    XPNET_DEVICE_NAME, ether_setup);
++	if (xpnet_device == NULL)
++		return -ENOMEM;
++
++	netif_carrier_off(xpnet_device);
++
++	xpnet_device->mtu = XPNET_DEF_MTU;
++	xpnet_device->change_mtu = xpnet_dev_change_mtu;
++	xpnet_device->open = xpnet_dev_open;
++	xpnet_device->get_stats = xpnet_dev_get_stats;
++	xpnet_device->stop = xpnet_dev_stop;
++	xpnet_device->hard_start_xmit = xpnet_dev_hard_start_xmit;
++	xpnet_device->tx_timeout = xpnet_dev_tx_timeout;
++	xpnet_device->set_config = xpnet_dev_set_config;
++
++	/*
++	 * Multicast assumes the LSB of the first octet is set for multicast
++	 * MAC addresses.  We chose the first octet of the MAC to be unlikely
++	 * to collide with any vendor's officially issued MAC.
++	 */
++	xpnet_device->dev_addr[0] = 0xfe;
++	xpnet_device->dev_addr[XPNET_PARTID_OCTET] = sn_partition_id;
++	license_num = sn_partition_serial_number_val();
++	for (i = 3; i >= 0; i--) {
++		xpnet_device->dev_addr[XPNET_LICENSE_OCTET + i] =
++		    license_num & 0xff;
++		license_num = license_num >> 8;
++	}
++
++	/*
++	 * ether_setup() sets this to a multicast device.  We are
++	 * really not supporting multicast at this time.
++	 */
++	xpnet_device->flags &= ~IFF_MULTICAST;
++
++	/*
++	 * No need to checksum as it is a DMA transfer.  The BTE will
++	 * report an error if the data is not retrievable and the
++	 * packet will be dropped.
++	 */
++	xpnet_device->features = NETIF_F_NO_CSUM;
++
++	result = register_netdev(xpnet_device);
++	if (result != 0)
++		free_netdev(xpnet_device);
++
++	return result;
++}
++
++module_init(xpnet_init);
++
++static void __exit
++xpnet_exit(void)
++{
++	dev_info(xpnet, "unregistering network device %s\n",
++		 xpnet_device[0].name);
++
++	unregister_netdev(xpnet_device);
++
++	free_netdev(xpnet_device);
++}
++
++module_exit(xpnet_exit);
++
++MODULE_AUTHOR("Silicon Graphics, Inc.");
++MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
+index b966674..01ced4c 100644
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -35,10 +35,6 @@
+ #include "sd_ops.h"
+ #include "sdio_ops.h"
+ 
+-extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
+-extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
+-extern int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
+-
+ static struct workqueue_struct *workqueue;
+ 
+ /*
+@@ -516,7 +512,7 @@ static void mmc_power_off(struct mmc_host *host)
+ /*
+  * Cleanup when the last reference to the bus operator is dropped.
+  */
+-void __mmc_release_bus(struct mmc_host *host)
++static void __mmc_release_bus(struct mmc_host *host)
+ {
+ 	BUG_ON(!host);
+ 	BUG_ON(host->bus_refs);
+diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
+index cfa8e15..cdb332b 100644
+--- a/drivers/mmc/core/core.h
++++ b/drivers/mmc/core/core.h
+@@ -46,6 +46,10 @@ void mmc_rescan(struct work_struct *work);
+ void mmc_start_host(struct mmc_host *host);
+ void mmc_stop_host(struct mmc_host *host);
+ 
++int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
++int mmc_attach_sd(struct mmc_host *host, u32 ocr);
++int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
++
+ extern int use_spi_crc;
+ 
+ #endif
+diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
+index c65d203..1d795c5 100644
+--- a/drivers/mmc/core/host.c
++++ b/drivers/mmc/core/host.c
+@@ -2,7 +2,7 @@
+  *  linux/drivers/mmc/core/host.c
+  *
+  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+- *  Copyright (C) 2007 Pierre Ossman
++ *  Copyright (C) 2007-2008 Pierre Ossman
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+@@ -57,12 +57,25 @@ static DEFINE_SPINLOCK(mmc_host_lock);
+  */
+ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+ {
++	int err;
+ 	struct mmc_host *host;
+ 
++	if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
++		return NULL;
++
+ 	host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+ 	if (!host)
+ 		return NULL;
+ 
++	spin_lock(&mmc_host_lock);
++	err = idr_get_new(&mmc_host_idr, host, &host->index);
++	spin_unlock(&mmc_host_lock);
++	if (err)
++		goto free;
++
++	snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
++		 "mmc%d", host->index);
++
+ 	host->parent = dev;
+ 	host->class_dev.parent = dev;
+ 	host->class_dev.class = &mmc_host_class;
+@@ -85,6 +98,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+ 	host->max_blk_count = PAGE_CACHE_SIZE / 512;
+ 
+ 	return host;
++
++free:
++	kfree(host);
++	return NULL;
+ }
+ 
+ EXPORT_SYMBOL(mmc_alloc_host);
+@@ -104,18 +121,6 @@ int mmc_add_host(struct mmc_host *host)
+ 	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
+ 		!host->ops->enable_sdio_irq);
+ 
+-	if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+-		return -ENOMEM;
+-
+-	spin_lock(&mmc_host_lock);
+-	err = idr_get_new(&mmc_host_idr, host, &host->index);
+-	spin_unlock(&mmc_host_lock);
+-	if (err)
+-		return err;
+-
+-	snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
+-		 "mmc%d", host->index);
+-
+ 	led_trigger_register_simple(host->class_dev.bus_id, &host->led);
+ 
+ 	err = device_add(&host->class_dev);
+@@ -144,10 +149,6 @@ void mmc_remove_host(struct mmc_host *host)
+ 	device_del(&host->class_dev);
+ 
+ 	led_trigger_unregister_simple(host->led);
+-
+-	spin_lock(&mmc_host_lock);
+-	idr_remove(&mmc_host_idr, host->index);
+-	spin_unlock(&mmc_host_lock);
+ }
+ 
+ EXPORT_SYMBOL(mmc_remove_host);
+@@ -160,6 +161,10 @@ EXPORT_SYMBOL(mmc_remove_host);
+  */
+ void mmc_free_host(struct mmc_host *host)
+ {
++	spin_lock(&mmc_host_lock);
++	idr_remove(&mmc_host_idr, host->index);
++	spin_unlock(&mmc_host_lock);
++
+ 	put_device(&host->class_dev);
+ }
+ 
+diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
+index 3bd3021..c292e12 100644
+--- a/drivers/mmc/core/sdio_irq.c
++++ b/drivers/mmc/core/sdio_irq.c
+@@ -128,12 +128,12 @@ static int sdio_irq_thread(void *_host)
+ 			}
+ 		}
+ 
+-		set_task_state(current, TASK_INTERRUPTIBLE);
++		set_current_state(TASK_INTERRUPTIBLE);
+ 		if (host->caps & MMC_CAP_SDIO_IRQ)
+ 			host->ops->enable_sdio_irq(host, 1);
+ 		if (!kthread_should_stop())
+ 			schedule_timeout(period);
+-		set_task_state(current, TASK_RUNNING);
++		set_current_state(TASK_RUNNING);
+ 	} while (!kthread_should_stop());
+ 
+ 	if (host->caps & MMC_CAP_SDIO_IRQ)
+diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
+index e1fca58..c8fa095 100644
+--- a/drivers/mmc/core/sdio_ops.c
++++ b/drivers/mmc/core/sdio_ops.c
+@@ -17,6 +17,7 @@
+ #include <linux/mmc/sdio.h>
+ 
+ #include "core.h"
++#include "sdio_ops.h"
+ 
+ int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+ {
+diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
+index 90c358b..14759e9 100644
+--- a/drivers/mmc/host/omap.c
++++ b/drivers/mmc/host/omap.c
+@@ -32,6 +32,7 @@
+ #include <asm/mach-types.h>
+ 
+ #include <asm/arch/board.h>
++#include <asm/arch/mmc.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/dma.h>
+ #include <asm/arch/mux.h>
+@@ -93,9 +94,27 @@
+ 
+ /* Specifies how often in millisecs to poll for card status changes
+  * when the cover switch is open */
+-#define OMAP_MMC_SWITCH_POLL_DELAY	500
+-
+-static int mmc_omap_enable_poll = 1;
++#define OMAP_MMC_COVER_POLL_DELAY	500
++
++struct mmc_omap_host;
++
++struct mmc_omap_slot {
++	int			id;
++	unsigned int		vdd;
++	u16			saved_con;
++	u16			bus_mode;
++	unsigned int		fclk_freq;
++	unsigned		powered:1;
++
++	struct tasklet_struct	cover_tasklet;
++	struct timer_list       cover_timer;
++	unsigned		cover_open;
++
++	struct mmc_request      *mrq;
++	struct mmc_omap_host    *host;
++	struct mmc_host		*mmc;
++	struct omap_mmc_slot_data *pdata;
++};
+ 
+ struct mmc_omap_host {
+ 	int			initialized;
+@@ -115,6 +134,15 @@ struct mmc_omap_host {
+ 	unsigned char		bus_mode;
+ 	unsigned char		hw_bus_mode;
+ 
++	struct work_struct	cmd_abort_work;
++	unsigned		abort:1;
++	struct timer_list	cmd_abort_timer;
++
++	struct work_struct      slot_release_work;
++	struct mmc_omap_slot    *next_slot;
++	struct work_struct      send_stop_work;
++	struct mmc_data		*stop_data;
++
+ 	unsigned int		sg_len;
+ 	int			sg_idx;
+ 	u16 *			buffer;
+@@ -131,63 +159,178 @@ struct mmc_omap_host {
+ 	unsigned		dma_len;
+ 
+ 	short			power_pin;
+-	short			wp_pin;
+ 
+-	int			switch_pin;
+-	struct work_struct	switch_work;
+-	struct timer_list	switch_timer;
+-	int			switch_last_state;
++	struct mmc_omap_slot    *slots[OMAP_MMC_MAX_SLOTS];
++	struct mmc_omap_slot    *current_slot;
++	spinlock_t              slot_lock;
++	wait_queue_head_t       slot_wq;
++	int                     nr_slots;
++
++	struct timer_list       clk_timer;
++	spinlock_t		clk_lock;     /* for changing enabled state */
++	unsigned int            fclk_enabled:1;
++
++	struct omap_mmc_platform_data *pdata;
+ };
+ 
+-static inline int
+-mmc_omap_cover_is_open(struct mmc_omap_host *host)
++void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
+ {
+-	if (host->switch_pin < 0)
+-		return 0;
+-	return omap_get_gpio_datain(host->switch_pin);
++	unsigned long tick_ns;
++
++	if (slot != NULL && slot->host->fclk_enabled && slot->fclk_freq > 0) {
++		tick_ns = (1000000000 + slot->fclk_freq - 1) / slot->fclk_freq;
++		ndelay(8 * tick_ns);
++	}
+ }
+ 
+-static ssize_t
+-mmc_omap_show_cover_switch(struct device *dev,
+-	struct device_attribute *attr, char *buf)
++void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable)
+ {
+-	struct mmc_omap_host *host = dev_get_drvdata(dev);
++	unsigned long flags;
+ 
+-	return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" :
+-			"closed");
++	spin_lock_irqsave(&host->clk_lock, flags);
++	if (host->fclk_enabled != enable) {
++		host->fclk_enabled = enable;
++		if (enable)
++			clk_enable(host->fclk);
++		else
++			clk_disable(host->fclk);
++	}
++	spin_unlock_irqrestore(&host->clk_lock, flags);
+ }
+ 
+-static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
++static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed)
++{
++	struct mmc_omap_host *host = slot->host;
++	unsigned long flags;
+ 
+-static ssize_t
+-mmc_omap_show_enable_poll(struct device *dev,
+-	struct device_attribute *attr, char *buf)
++	if (claimed)
++		goto no_claim;
++	spin_lock_irqsave(&host->slot_lock, flags);
++	while (host->mmc != NULL) {
++		spin_unlock_irqrestore(&host->slot_lock, flags);
++		wait_event(host->slot_wq, host->mmc == NULL);
++		spin_lock_irqsave(&host->slot_lock, flags);
++	}
++	host->mmc = slot->mmc;
++	spin_unlock_irqrestore(&host->slot_lock, flags);
++no_claim:
++	del_timer(&host->clk_timer);
++	if (host->current_slot != slot || !claimed)
++		mmc_omap_fclk_offdelay(host->current_slot);
++
++	if (host->current_slot != slot) {
++		OMAP_MMC_WRITE(host, CON, slot->saved_con & 0xFC00);
++		if (host->pdata->switch_slot != NULL)
++			host->pdata->switch_slot(mmc_dev(slot->mmc), slot->id);
++		host->current_slot = slot;
++	}
++
++	if (claimed) {
++		mmc_omap_fclk_enable(host, 1);
++
++		/* Doing the dummy read here seems to work around some bug
++		 * at least in OMAP24xx silicon where the command would not
++		 * start after writing the CMD register. Sigh. */
++		OMAP_MMC_READ(host, CON);
++
++		OMAP_MMC_WRITE(host, CON, slot->saved_con);
++	} else
++		mmc_omap_fclk_enable(host, 0);
++}
++
++static void mmc_omap_start_request(struct mmc_omap_host *host,
++				   struct mmc_request *req);
++
++static void mmc_omap_slot_release_work(struct work_struct *work)
+ {
+-	return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll);
++	struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
++						  slot_release_work);
++	struct mmc_omap_slot *next_slot = host->next_slot;
++	struct mmc_request *rq;
++
++	host->next_slot = NULL;
++	mmc_omap_select_slot(next_slot, 1);
++
++	rq = next_slot->mrq;
++	next_slot->mrq = NULL;
++	mmc_omap_start_request(host, rq);
+ }
+ 
+-static ssize_t
+-mmc_omap_store_enable_poll(struct device *dev,
+-	struct device_attribute *attr, const char *buf,
+-	size_t size)
++static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled)
+ {
+-	int enable_poll;
++	struct mmc_omap_host *host = slot->host;
++	unsigned long flags;
++	int i;
++
++	BUG_ON(slot == NULL || host->mmc == NULL);
++
++	if (clk_enabled)
++		/* Keeps clock running for at least 8 cycles on valid freq */
++		mod_timer(&host->clk_timer, jiffies  + HZ/10);
++	else {
++		del_timer(&host->clk_timer);
++		mmc_omap_fclk_offdelay(slot);
++		mmc_omap_fclk_enable(host, 0);
++	}
+ 
+-	if (sscanf(buf, "%10d", &enable_poll) != 1)
+-		return -EINVAL;
++	spin_lock_irqsave(&host->slot_lock, flags);
++	/* Check for any pending requests */
++	for (i = 0; i < host->nr_slots; i++) {
++		struct mmc_omap_slot *new_slot;
+ 
+-	if (enable_poll != mmc_omap_enable_poll) {
+-		struct mmc_omap_host *host = dev_get_drvdata(dev);
++		if (host->slots[i] == NULL || host->slots[i]->mrq == NULL)
++			continue;
+ 
+-		mmc_omap_enable_poll = enable_poll;
+-		if (enable_poll && host->switch_pin >= 0)
+-			schedule_work(&host->switch_work);
++		BUG_ON(host->next_slot != NULL);
++		new_slot = host->slots[i];
++		/* The current slot should not have a request in queue */
++		BUG_ON(new_slot == host->current_slot);
++
++		host->next_slot = new_slot;
++		host->mmc = new_slot->mmc;
++		spin_unlock_irqrestore(&host->slot_lock, flags);
++		schedule_work(&host->slot_release_work);
++		return;
+ 	}
+-	return size;
++
++	host->mmc = NULL;
++	wake_up(&host->slot_wq);
++	spin_unlock_irqrestore(&host->slot_lock, flags);
++}
++
++static inline
++int mmc_omap_cover_is_open(struct mmc_omap_slot *slot)
++{
++	if (slot->pdata->get_cover_state)
++		return slot->pdata->get_cover_state(mmc_dev(slot->mmc),
++						    slot->id);
++	return 0;
++}
++
++static ssize_t
++mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr,
++			   char *buf)
++{
++	struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
++	struct mmc_omap_slot *slot = mmc_priv(mmc);
++
++	return sprintf(buf, "%s\n", mmc_omap_cover_is_open(slot) ? "open" :
++		       "closed");
+ }
+ 
+-static DEVICE_ATTR(enable_poll, 0664,
+-		   mmc_omap_show_enable_poll, mmc_omap_store_enable_poll);
++static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
++
++static ssize_t
++mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr,
++			char *buf)
++{
++	struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
++	struct mmc_omap_slot *slot = mmc_priv(mmc);
++
++	return sprintf(buf, "%s\n", slot->pdata->name);
++}
++
++static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL);
+ 
+ static void
+ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+@@ -233,7 +376,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+ 
+ 	cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12);
+ 
+-	if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
++	if (host->current_slot->bus_mode == MMC_BUSMODE_OPENDRAIN)
+ 		cmdreg |= 1 << 6;
+ 
+ 	if (cmd->flags & MMC_RSP_BUSY)
+@@ -242,7 +385,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+ 	if (host->data && !(host->data->flags & MMC_DATA_WRITE))
+ 		cmdreg |= 1 << 15;
+ 
+-	clk_enable(host->fclk);
++	mod_timer(&host->cmd_abort_timer, jiffies + HZ/2);
+ 
+ 	OMAP_MMC_WRITE(host, CTO, 200);
+ 	OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
+@@ -257,26 +400,46 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+ }
+ 
+ static void
++mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data,
++		     int abort)
++{
++	enum dma_data_direction dma_data_dir;
++
++	BUG_ON(host->dma_ch < 0);
++	if (data->error)
++		omap_stop_dma(host->dma_ch);
++	/* Release DMA channel lazily */
++	mod_timer(&host->dma_timer, jiffies + HZ);
++	if (data->flags & MMC_DATA_WRITE)
++		dma_data_dir = DMA_TO_DEVICE;
++	else
++		dma_data_dir = DMA_FROM_DEVICE;
++	dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
++		     dma_data_dir);
++}
++
++static void mmc_omap_send_stop_work(struct work_struct *work)
++{
++	struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
++						  send_stop_work);
++	struct mmc_omap_slot *slot = host->current_slot;
++	struct mmc_data *data = host->stop_data;
++	unsigned long tick_ns;
++
++	tick_ns = (1000000000 + slot->fclk_freq - 1)/slot->fclk_freq;
++	ndelay(8*tick_ns);
++
++	mmc_omap_start_command(host, data->stop);
++}
++
++static void
+ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+ {
+-	if (host->dma_in_use) {
+-		enum dma_data_direction dma_data_dir;
+-
+-		BUG_ON(host->dma_ch < 0);
+-		if (data->error)
+-			omap_stop_dma(host->dma_ch);
+-		/* Release DMA channel lazily */
+-		mod_timer(&host->dma_timer, jiffies + HZ);
+-		if (data->flags & MMC_DATA_WRITE)
+-			dma_data_dir = DMA_TO_DEVICE;
+-		else
+-			dma_data_dir = DMA_FROM_DEVICE;
+-		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
+-			     dma_data_dir);
+-	}
++	if (host->dma_in_use)
++		mmc_omap_release_dma(host, data, data->error);
++
+ 	host->data = NULL;
+ 	host->sg_len = 0;
+-	clk_disable(host->fclk);
+ 
+ 	/* NOTE:  MMC layer will sometimes poll-wait CMD13 next, issuing
+ 	 * dozens of requests until the card finishes writing data.
+@@ -284,12 +447,58 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+ 	 */
+ 
+ 	if (!data->stop) {
++		struct mmc_host *mmc;
++
+ 		host->mrq = NULL;
+-		mmc_request_done(host->mmc, data->mrq);
++		mmc = host->mmc;
++		mmc_omap_release_slot(host->current_slot, 1);
++		mmc_request_done(mmc, data->mrq);
+ 		return;
+ 	}
+ 
+-	mmc_omap_start_command(host, data->stop);
++	host->stop_data = data;
++	schedule_work(&host->send_stop_work);
++}
++
++static void
++mmc_omap_send_abort(struct mmc_omap_host *host, int maxloops)
++{
++	struct mmc_omap_slot *slot = host->current_slot;
++	unsigned int restarts, passes, timeout;
++	u16 stat = 0;
++
++	/* Sending abort takes 80 clocks. Have some extra and round up */
++	timeout = (120*1000000 + slot->fclk_freq - 1)/slot->fclk_freq;
++	restarts = 0;
++	while (restarts < maxloops) {
++		OMAP_MMC_WRITE(host, STAT, 0xFFFF);
++		OMAP_MMC_WRITE(host, CMD, (3 << 12) | (1 << 7));
++
++		passes = 0;
++		while (passes < timeout) {
++			stat = OMAP_MMC_READ(host, STAT);
++			if (stat & OMAP_MMC_STAT_END_OF_CMD)
++				goto out;
++			udelay(1);
++			passes++;
++		}
++
++		restarts++;
++	}
++out:
++	OMAP_MMC_WRITE(host, STAT, stat);
++}
++
++static void
++mmc_omap_abort_xfer(struct mmc_omap_host *host, struct mmc_data *data)
++{
++	if (host->dma_in_use)
++		mmc_omap_release_dma(host, data, 1);
++
++	host->data = NULL;
++	host->sg_len = 0;
++
++	mmc_omap_send_abort(host, 10000);
+ }
+ 
+ static void
+@@ -345,6 +554,8 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+ {
+ 	host->cmd = NULL;
+ 
++	del_timer(&host->cmd_abort_timer);
++
+ 	if (cmd->flags & MMC_RSP_PRESENT) {
+ 		if (cmd->flags & MMC_RSP_136) {
+ 			/* response type 2 */
+@@ -369,10 +580,66 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+ 	}
+ 
+ 	if (host->data == NULL || cmd->error) {
++		struct mmc_host *mmc;
++
++		if (host->data != NULL)
++			mmc_omap_abort_xfer(host, host->data);
+ 		host->mrq = NULL;
+-		clk_disable(host->fclk);
+-		mmc_request_done(host->mmc, cmd->mrq);
++		mmc = host->mmc;
++		mmc_omap_release_slot(host->current_slot, 1);
++		mmc_request_done(mmc, cmd->mrq);
++	}
++}
++
++/*
++ * Abort stuck command. Can occur when card is removed while it is being
++ * read.
++ */
++static void mmc_omap_abort_command(struct work_struct *work)
++{
++	struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
++						  cmd_abort_work);
++	BUG_ON(!host->cmd);
++
++	dev_dbg(mmc_dev(host->mmc), "Aborting stuck command CMD%d\n",
++		host->cmd->opcode);
++
++	if (host->cmd->error == 0)
++		host->cmd->error = -ETIMEDOUT;
++
++	if (host->data == NULL) {
++		struct mmc_command *cmd;
++		struct mmc_host    *mmc;
++
++		cmd = host->cmd;
++		host->cmd = NULL;
++		mmc_omap_send_abort(host, 10000);
++
++		host->mrq = NULL;
++		mmc = host->mmc;
++		mmc_omap_release_slot(host->current_slot, 1);
++		mmc_request_done(mmc, cmd->mrq);
++	} else
++		mmc_omap_cmd_done(host, host->cmd);
++
++	host->abort = 0;
++	enable_irq(host->irq);
++}
++
++static void
++mmc_omap_cmd_timer(unsigned long data)
++{
++	struct mmc_omap_host *host = (struct mmc_omap_host *) data;
++	unsigned long flags;
++
++	spin_lock_irqsave(&host->slot_lock, flags);
++	if (host->cmd != NULL && !host->abort) {
++		OMAP_MMC_WRITE(host, IE, 0);
++		disable_irq(host->irq);
++		host->abort = 1;
++		schedule_work(&host->cmd_abort_work);
+ 	}
++	spin_unlock_irqrestore(&host->slot_lock, flags);
+ }
+ 
+ /* PIO only */
+@@ -388,6 +655,14 @@ mmc_omap_sg_to_buf(struct mmc_omap_host *host)
+ 		host->buffer_bytes_left = host->total_bytes_left;
+ }
+ 
++static void
++mmc_omap_clk_timer(unsigned long data)
++{
++	struct mmc_omap_host *host = (struct mmc_omap_host *) data;
++
++	mmc_omap_fclk_enable(host, 0);
++}
++
+ /* PIO only */
+ static void
+ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
+@@ -436,11 +711,12 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ 	u16 status;
+ 	int end_command;
+ 	int end_transfer;
+-	int transfer_error;
++	int transfer_error, cmd_error;
+ 
+ 	if (host->cmd == NULL && host->data == NULL) {
+ 		status = OMAP_MMC_READ(host, STAT);
+-		dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
++		dev_info(mmc_dev(host->slots[0]->mmc),
++			 "Spurious IRQ 0x%04x\n", status);
+ 		if (status != 0) {
+ 			OMAP_MMC_WRITE(host, STAT, status);
+ 			OMAP_MMC_WRITE(host, IE, 0);
+@@ -451,12 +727,19 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ 	end_command = 0;
+ 	end_transfer = 0;
+ 	transfer_error = 0;
++	cmd_error = 0;
+ 
+ 	while ((status = OMAP_MMC_READ(host, STAT)) != 0) {
++		int cmd;
++
+ 		OMAP_MMC_WRITE(host, STAT, status);
++		if (host->cmd != NULL)
++			cmd = host->cmd->opcode;
++		else
++			cmd = -1;
+ #ifdef CONFIG_MMC_DEBUG
+ 		dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
+-			status, host->cmd != NULL ? host->cmd->opcode : -1);
++			status, cmd);
+ 		mmc_omap_report_irq(status);
+ 		printk("\n");
+ #endif
+@@ -468,12 +751,12 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ 				mmc_omap_xfer_data(host, 1);
+ 		}
+ 
+-		if (status & OMAP_MMC_STAT_END_OF_DATA) {
++		if (status & OMAP_MMC_STAT_END_OF_DATA)
+ 			end_transfer = 1;
+-		}
+ 
+ 		if (status & OMAP_MMC_STAT_DATA_TOUT) {
+-			dev_dbg(mmc_dev(host->mmc), "data timeout\n");
++			dev_dbg(mmc_dev(host->mmc), "data timeout (CMD%d)\n",
++				cmd);
+ 			if (host->data) {
+ 				host->data->error = -ETIMEDOUT;
+ 				transfer_error = 1;
+@@ -495,17 +778,16 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ 		if (status & OMAP_MMC_STAT_CMD_TOUT) {
+ 			/* Timeouts are routine with some commands */
+ 			if (host->cmd) {
+-				if (host->cmd->opcode != MMC_ALL_SEND_CID &&
+-						host->cmd->opcode !=
+-						MMC_SEND_OP_COND &&
+-						host->cmd->opcode !=
+-						MMC_APP_CMD &&
+-						!mmc_omap_cover_is_open(host))
++				struct mmc_omap_slot *slot =
++					host->current_slot;
++				if (slot == NULL ||
++				    !mmc_omap_cover_is_open(slot))
+ 					dev_err(mmc_dev(host->mmc),
+-						"command timeout, CMD %d\n",
+-						host->cmd->opcode);
++						"command timeout (CMD%d)\n",
++						cmd);
+ 				host->cmd->error = -ETIMEDOUT;
+ 				end_command = 1;
++				cmd_error = 1;
+ 			}
+ 		}
+ 
+@@ -513,9 +795,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ 			if (host->cmd) {
+ 				dev_err(mmc_dev(host->mmc),
+ 					"command CRC error (CMD%d, arg 0x%08x)\n",
+-					host->cmd->opcode, host->cmd->arg);
++					cmd, host->cmd->arg);
+ 				host->cmd->error = -EILSEQ;
+ 				end_command = 1;
++				cmd_error = 1;
+ 			} else
+ 				dev_err(mmc_dev(host->mmc),
+ 					"command CRC error without cmd?\n");
+@@ -524,13 +807,13 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ 		if (status & OMAP_MMC_STAT_CARD_ERR) {
+ 			dev_dbg(mmc_dev(host->mmc),
+ 				"ignoring card status error (CMD%d)\n",
+-				host->cmd->opcode);
++				cmd);
+ 			end_command = 1;
+ 		}
+ 
+ 		/*
+ 		 * NOTE: On 1610 the END_OF_CMD may come too early when
+-		 * starting a write 
++		 * starting a write
+ 		 */
+ 		if ((status & OMAP_MMC_STAT_END_OF_CMD) &&
+ 		    (!(status & OMAP_MMC_STAT_A_EMPTY))) {
+@@ -538,63 +821,72 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ 		}
+ 	}
+ 
+-	if (end_command) {
++	if (cmd_error && host->data) {
++		del_timer(&host->cmd_abort_timer);
++		host->abort = 1;
++		OMAP_MMC_WRITE(host, IE, 0);
++		disable_irq(host->irq);
++		schedule_work(&host->cmd_abort_work);
++		return IRQ_HANDLED;
++	}
++
++	if (end_command)
+ 		mmc_omap_cmd_done(host, host->cmd);
++	if (host->data != NULL) {
++		if (transfer_error)
++			mmc_omap_xfer_done(host, host->data);
++		else if (end_transfer)
++			mmc_omap_end_of_data(host, host->data);
+ 	}
+-	if (transfer_error)
+-		mmc_omap_xfer_done(host, host->data);
+-	else if (end_transfer)
+-		mmc_omap_end_of_data(host, host->data);
+ 
+ 	return IRQ_HANDLED;
+ }
+ 
+-static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id)
++void omap_mmc_notify_cover_event(struct device *dev, int num, int is_closed)
+ {
+-	struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id;
++	int cover_open;
++	struct mmc_omap_host *host = dev_get_drvdata(dev);
++	struct mmc_omap_slot *slot = host->slots[num];
+ 
+-	schedule_work(&host->switch_work);
++	BUG_ON(num >= host->nr_slots);
+ 
+-	return IRQ_HANDLED;
++	/* Other subsystems can call in here before we're initialised. */
++	if (host->nr_slots == 0 || !host->slots[num])
++		return;
++
++	cover_open = mmc_omap_cover_is_open(slot);
++	if (cover_open != slot->cover_open) {
++		slot->cover_open = cover_open;
++		sysfs_notify(&slot->mmc->class_dev.kobj, NULL, "cover_switch");
++	}
++
++	tasklet_hi_schedule(&slot->cover_tasklet);
+ }
+ 
+-static void mmc_omap_switch_timer(unsigned long arg)
++static void mmc_omap_cover_timer(unsigned long arg)
+ {
+-	struct mmc_omap_host *host = (struct mmc_omap_host *) arg;
+-
+-	schedule_work(&host->switch_work);
++	struct mmc_omap_slot *slot = (struct mmc_omap_slot *) arg;
++	tasklet_schedule(&slot->cover_tasklet);
+ }
+ 
+-static void mmc_omap_switch_handler(struct work_struct *work)
++static void mmc_omap_cover_handler(unsigned long param)
+ {
+-	struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, switch_work);
+-	struct mmc_card *card;
+-	static int complained = 0;
+-	int cards = 0, cover_open;
++	struct mmc_omap_slot *slot = (struct mmc_omap_slot *)param;
++	int cover_open = mmc_omap_cover_is_open(slot);
+ 
+-	if (host->switch_pin == -1)
++	mmc_detect_change(slot->mmc, 0);
++	if (!cover_open)
+ 		return;
+-	cover_open = mmc_omap_cover_is_open(host);
+-	if (cover_open != host->switch_last_state) {
+-		kobject_uevent(&host->dev->kobj, KOBJ_CHANGE);
+-		host->switch_last_state = cover_open;
+-	}
+-	mmc_detect_change(host->mmc, 0);
+-	list_for_each_entry(card, &host->mmc->cards, node) {
+-		if (mmc_card_present(card))
+-			cards++;
+-	}
+-	if (mmc_omap_cover_is_open(host)) {
+-		if (!complained) {
+-			dev_info(mmc_dev(host->mmc), "cover is open\n");
+-			complained = 1;
+-		}
+-		if (mmc_omap_enable_poll)
+-			mod_timer(&host->switch_timer, jiffies +
+-				msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY));
+-	} else {
+-		complained = 0;
+-	}
++
++	/*
++	 * If no card is inserted, we postpone polling until
++	 * the cover has been closed.
++	 */
++	if (slot->mmc->card == NULL || !mmc_card_present(slot->mmc->card))
++		return;
++
++	mod_timer(&slot->cover_timer,
++		  jiffies + msecs_to_jiffies(OMAP_MMC_COVER_POLL_DELAY));
+ }
+ 
+ /* Prepare to transfer the next segment of a scatterlist */
+@@ -765,13 +1057,12 @@ static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_reques
+ 
+ static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+ {
+-	int timeout;
++	unsigned int timeout, cycle_ns;
+ 	u16 reg;
+ 
+-	/* Convert ns to clock cycles by assuming 20MHz frequency
+-	 * 1 cycle at 20MHz = 500 ns
+-	 */
+-	timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
++	cycle_ns = 1000000000 / host->current_slot->fclk_freq;
++	timeout = req->data->timeout_ns / cycle_ns;
++	timeout += req->data->timeout_clks;
+ 
+ 	/* Check if we need to use timeout multiplier register */
+ 	reg = OMAP_MMC_READ(host, SDIO);
+@@ -854,11 +1145,10 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
+ 	}
+ }
+ 
+-static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
++static void mmc_omap_start_request(struct mmc_omap_host *host,
++				   struct mmc_request *req)
+ {
+-	struct mmc_omap_host *host = mmc_priv(mmc);
+-
+-	WARN_ON(host->mrq != NULL);
++	BUG_ON(host->mrq != NULL);
+ 
+ 	host->mrq = req;
+ 
+@@ -867,60 +1157,56 @@ static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
+ 	mmc_omap_start_command(host, req->cmd);
+ 	if (host->dma_in_use)
+ 		omap_start_dma(host->dma_ch);
++	BUG_ON(irqs_disabled());
+ }
+ 
+-static void innovator_fpga_socket_power(int on)
++static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
+ {
+-#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
+-	if (on) {
+-		fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
+-		     OMAP1510_FPGA_POWER);
+-	} else {
+-		fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
+-		     OMAP1510_FPGA_POWER);
+-	}
+-#endif
++	struct mmc_omap_slot *slot = mmc_priv(mmc);
++	struct mmc_omap_host *host = slot->host;
++	unsigned long flags;
++
++	spin_lock_irqsave(&host->slot_lock, flags);
++	if (host->mmc != NULL) {
++		BUG_ON(slot->mrq != NULL);
++		slot->mrq = req;
++		spin_unlock_irqrestore(&host->slot_lock, flags);
++		return;
++	} else
++		host->mmc = mmc;
++	spin_unlock_irqrestore(&host->slot_lock, flags);
++	mmc_omap_select_slot(slot, 1);
++	mmc_omap_start_request(host, req);
+ }
+ 
+-/*
+- * Turn the socket power on/off. Innovator uses FPGA, most boards
+- * probably use GPIO.
+- */
+-static void mmc_omap_power(struct mmc_omap_host *host, int on)
++static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
++				int vdd)
+ {
+-	if (on) {
+-		if (machine_is_omap_innovator())
+-			innovator_fpga_socket_power(1);
+-		else if (machine_is_omap_h2())
+-			tps65010_set_gpio_out_value(GPIO3, HIGH);
+-		else if (machine_is_omap_h3())
+-			/* GPIO 4 of TPS65010 sends SD_EN signal */
+-			tps65010_set_gpio_out_value(GPIO4, HIGH);
+-		else if (cpu_is_omap24xx()) {
+-			u16 reg = OMAP_MMC_READ(host, CON);
+-			OMAP_MMC_WRITE(host, CON, reg | (1 << 11));
+-		} else
+-			if (host->power_pin >= 0)
+-				omap_set_gpio_dataout(host->power_pin, 1);
+-	} else {
+-		if (machine_is_omap_innovator())
+-			innovator_fpga_socket_power(0);
+-		else if (machine_is_omap_h2())
+-			tps65010_set_gpio_out_value(GPIO3, LOW);
+-		else if (machine_is_omap_h3())
+-			tps65010_set_gpio_out_value(GPIO4, LOW);
+-		else if (cpu_is_omap24xx()) {
+-			u16 reg = OMAP_MMC_READ(host, CON);
+-			OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11));
+-		} else
+-			if (host->power_pin >= 0)
+-				omap_set_gpio_dataout(host->power_pin, 0);
++	struct mmc_omap_host *host;
++
++	host = slot->host;
++
++	if (slot->pdata->set_power != NULL)
++		slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
++					vdd);
++
++	if (cpu_is_omap24xx()) {
++		u16 w;
++
++		if (power_on) {
++			w = OMAP_MMC_READ(host, CON);
++			OMAP_MMC_WRITE(host, CON, w | (1 << 11));
++		} else {
++			w = OMAP_MMC_READ(host, CON);
++			OMAP_MMC_WRITE(host, CON, w & ~(1 << 11));
++		}
+ 	}
+ }
+ 
+ static int mmc_omap_calc_divisor(struct mmc_host *mmc, struct mmc_ios *ios)
+ {
+-	struct mmc_omap_host *host = mmc_priv(mmc);
++	struct mmc_omap_slot *slot = mmc_priv(mmc);
++	struct mmc_omap_host *host = slot->host;
+ 	int func_clk_rate = clk_get_rate(host->fclk);
+ 	int dsor;
+ 
+@@ -936,7 +1222,8 @@ static int mmc_omap_calc_divisor(struct mmc_host *mmc, struct mmc_ios *ios)
+ 
+ 	if (dsor > 250)
+ 		dsor = 250;
+-	dsor++;
++
++	slot->fclk_freq = func_clk_rate / dsor;
+ 
+ 	if (ios->bus_width == MMC_BUS_WIDTH_4)
+ 		dsor |= 1 << 15;
+@@ -946,28 +1233,40 @@ static int mmc_omap_calc_divisor(struct mmc_host *mmc, struct mmc_ios *ios)
+ 
+ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ {
+-	struct mmc_omap_host *host = mmc_priv(mmc);
+-	int dsor;
+-	int i;
++	struct mmc_omap_slot *slot = mmc_priv(mmc);
++	struct mmc_omap_host *host = slot->host;
++	int i, dsor;
++	int clk_enabled;
++
++	mmc_omap_select_slot(slot, 0);
+ 
+ 	dsor = mmc_omap_calc_divisor(mmc, ios);
+-	host->bus_mode = ios->bus_mode;
+-	host->hw_bus_mode = host->bus_mode;
+ 
++	if (ios->vdd != slot->vdd)
++		slot->vdd = ios->vdd;
++
++	clk_enabled = 0;
+ 	switch (ios->power_mode) {
+ 	case MMC_POWER_OFF:
+-		mmc_omap_power(host, 0);
++		mmc_omap_set_power(slot, 0, ios->vdd);
+ 		break;
+ 	case MMC_POWER_UP:
+ 		/* Cannot touch dsor yet, just power up MMC */
+-		mmc_omap_power(host, 1);
+-		return;
++		mmc_omap_set_power(slot, 1, ios->vdd);
++		goto exit;
+ 	case MMC_POWER_ON:
++		mmc_omap_fclk_enable(host, 1);
++		clk_enabled = 1;
+ 		dsor |= 1 << 11;
+ 		break;
+ 	}
+ 
+-	clk_enable(host->fclk);
++	if (slot->bus_mode != ios->bus_mode) {
++		if (slot->pdata->set_bus_mode != NULL)
++			slot->pdata->set_bus_mode(mmc_dev(mmc), slot->id,
++						  ios->bus_mode);
++		slot->bus_mode = ios->bus_mode;
++	}
+ 
+ 	/* On insanely high arm_per frequencies something sometimes
+ 	 * goes somehow out of sync, and the POW bit is not being set,
+@@ -975,43 +1274,143 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ 	 * Writing to the CON register twice seems to do the trick. */
+ 	for (i = 0; i < 2; i++)
+ 		OMAP_MMC_WRITE(host, CON, dsor);
++	slot->saved_con = dsor;
+ 	if (ios->power_mode == MMC_POWER_ON) {
++		/* worst case at 400kHz, 80 cycles makes 200 microsecs */
++		int usecs = 250;
++
+ 		/* Send clock cycles, poll completion */
+ 		OMAP_MMC_WRITE(host, IE, 0);
+ 		OMAP_MMC_WRITE(host, STAT, 0xffff);
+ 		OMAP_MMC_WRITE(host, CMD, 1 << 7);
+-		while ((OMAP_MMC_READ(host, STAT) & 1) == 0);
++		while (usecs > 0 && (OMAP_MMC_READ(host, STAT) & 1) == 0) {
++			udelay(1);
++			usecs--;
++		}
+ 		OMAP_MMC_WRITE(host, STAT, 1);
+ 	}
+-	clk_disable(host->fclk);
+-}
+-
+-static int mmc_omap_get_ro(struct mmc_host *mmc)
+-{
+-	struct mmc_omap_host *host = mmc_priv(mmc);
+ 
+-	return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
++exit:
++	mmc_omap_release_slot(slot, clk_enabled);
+ }
+ 
+ static const struct mmc_host_ops mmc_omap_ops = {
+ 	.request	= mmc_omap_request,
+ 	.set_ios	= mmc_omap_set_ios,
+-	.get_ro		= mmc_omap_get_ro,
+ };
+ 
+-static int __init mmc_omap_probe(struct platform_device *pdev)
++static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id)
+ {
+-	struct omap_mmc_conf *minfo = pdev->dev.platform_data;
++	struct mmc_omap_slot *slot = NULL;
+ 	struct mmc_host *mmc;
++	int r;
++
++	mmc = mmc_alloc_host(sizeof(struct mmc_omap_slot), host->dev);
++	if (mmc == NULL)
++		return -ENOMEM;
++
++	slot = mmc_priv(mmc);
++	slot->host = host;
++	slot->mmc = mmc;
++	slot->id = id;
++	slot->pdata = &host->pdata->slots[id];
++
++	host->slots[id] = slot;
++
++	mmc->caps = MMC_CAP_MULTIWRITE;
++	if (host->pdata->conf.wire4)
++		mmc->caps |= MMC_CAP_4_BIT_DATA;
++
++	mmc->ops = &mmc_omap_ops;
++	mmc->f_min = 400000;
++
++	if (cpu_class_is_omap2())
++		mmc->f_max = 48000000;
++	else
++		mmc->f_max = 24000000;
++	if (host->pdata->max_freq)
++		mmc->f_max = min(host->pdata->max_freq, mmc->f_max);
++	mmc->ocr_avail = slot->pdata->ocr_mask;
++
++	/* Use scatterlist DMA to reduce per-transfer costs.
++	 * NOTE max_seg_size assumption that small blocks aren't
++	 * normally used (except e.g. for reading SD registers).
++	 */
++	mmc->max_phys_segs = 32;
++	mmc->max_hw_segs = 32;
++	mmc->max_blk_size = 2048;	/* BLEN is 11 bits (+1) */
++	mmc->max_blk_count = 2048;	/* NBLK is 11 bits (+1) */
++	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
++	mmc->max_seg_size = mmc->max_req_size;
++
++	r = mmc_add_host(mmc);
++	if (r < 0)
++		goto err_remove_host;
++
++	if (slot->pdata->name != NULL) {
++		r = device_create_file(&mmc->class_dev,
++					&dev_attr_slot_name);
++		if (r < 0)
++			goto err_remove_host;
++	}
++
++	if (slot->pdata->get_cover_state != NULL) {
++		r = device_create_file(&mmc->class_dev,
++					&dev_attr_cover_switch);
++		if (r < 0)
++			goto err_remove_slot_name;
++
++		setup_timer(&slot->cover_timer, mmc_omap_cover_timer,
++			    (unsigned long)slot);
++		tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler,
++			     (unsigned long)slot);
++		tasklet_schedule(&slot->cover_tasklet);
++	}
++
++	return 0;
++
++err_remove_slot_name:
++	if (slot->pdata->name != NULL)
++		device_remove_file(&mmc->class_dev, &dev_attr_slot_name);
++err_remove_host:
++	mmc_remove_host(mmc);
++	mmc_free_host(mmc);
++	return r;
++}
++
++static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
++{
++	struct mmc_host *mmc = slot->mmc;
++
++	if (slot->pdata->name != NULL)
++		device_remove_file(&mmc->class_dev, &dev_attr_slot_name);
++	if (slot->pdata->get_cover_state != NULL)
++		device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
++
++	tasklet_kill(&slot->cover_tasklet);
++	del_timer_sync(&slot->cover_timer);
++	flush_scheduled_work();
++
++	mmc_remove_host(mmc);
++	mmc_free_host(mmc);
++}
++
++static int __init mmc_omap_probe(struct platform_device *pdev)
++{
++	struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
+ 	struct mmc_omap_host *host = NULL;
+ 	struct resource *res;
+-	int ret = 0;
++	int i, ret = 0;
+ 	int irq;
+ 
+-	if (minfo == NULL) {
++	if (pdata == NULL) {
+ 		dev_err(&pdev->dev, "platform data missing\n");
+ 		return -ENXIO;
+ 	}
++	if (pdata->nr_slots == 0) {
++		dev_err(&pdev->dev, "no slots\n");
++		return -ENXIO;
++	}
+ 
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	irq = platform_get_irq(pdev, 0);
+@@ -1019,28 +1418,46 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
+ 		return -ENXIO;
+ 
+ 	res = request_mem_region(res->start, res->end - res->start + 1,
+-			         pdev->name);
++				 pdev->name);
+ 	if (res == NULL)
+ 		return -EBUSY;
+ 
+-	mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
+-	if (mmc == NULL) {
++	host = kzalloc(sizeof(struct mmc_omap_host), GFP_KERNEL);
++	if (host == NULL) {
+ 		ret = -ENOMEM;
+ 		goto err_free_mem_region;
+ 	}
+ 
+-	host = mmc_priv(mmc);
+-	host->mmc = mmc;
++	INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work);
++	INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
++
++	INIT_WORK(&host->cmd_abort_work, mmc_omap_abort_command);
++	setup_timer(&host->cmd_abort_timer, mmc_omap_cmd_timer,
++		    (unsigned long) host);
++
++	spin_lock_init(&host->clk_lock);
++	setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host);
+ 
+ 	spin_lock_init(&host->dma_lock);
+-	init_timer(&host->dma_timer);
+-	host->dma_timer.function = mmc_omap_dma_timer;
+-	host->dma_timer.data = (unsigned long) host;
++	setup_timer(&host->dma_timer, mmc_omap_dma_timer, (unsigned long) host);
++	spin_lock_init(&host->slot_lock);
++	init_waitqueue_head(&host->slot_wq);
++
++	host->pdata = pdata;
++	host->dev = &pdev->dev;
++	platform_set_drvdata(pdev, host);
+ 
+ 	host->id = pdev->id;
+ 	host->mem_res = res;
+ 	host->irq = irq;
+ 
++	host->use_dma = 1;
++	host->dma_ch = -1;
++
++	host->irq = irq;
++	host->phys_base = host->mem_res->start;
++	host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
++
+ 	if (cpu_is_omap24xx()) {
+ 		host->iclk = clk_get(&pdev->dev, "mmc_ick");
+ 		if (IS_ERR(host->iclk))
+@@ -1058,109 +1475,34 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
+ 		goto err_free_iclk;
+ 	}
+ 
+-	/* REVISIT:
+-	 * Also, use minfo->cover to decide how to manage
+-	 * the card detect sensing.
+-	 */
+-	host->power_pin = minfo->power_pin;
+-	host->switch_pin = minfo->switch_pin;
+-	host->wp_pin = minfo->wp_pin;
+-	host->use_dma = 1;
+-	host->dma_ch = -1;
+-
+-	host->irq = irq;
+-	host->phys_base = host->mem_res->start;
+-	host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
+-
+-	mmc->ops = &mmc_omap_ops;
+-	mmc->f_min = 400000;
+-	mmc->f_max = 24000000;
+-	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+-	mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
+-
+-	if (minfo->wire4)
+-		 mmc->caps |= MMC_CAP_4_BIT_DATA;
+-
+-	/* Use scatterlist DMA to reduce per-transfer costs.
+-	 * NOTE max_seg_size assumption that small blocks aren't
+-	 * normally used (except e.g. for reading SD registers).
+-	 */
+-	mmc->max_phys_segs = 32;
+-	mmc->max_hw_segs = 32;
+-	mmc->max_blk_size = 2048;	/* BLEN is 11 bits (+1) */
+-	mmc->max_blk_count = 2048;	/* NBLK is 11 bits (+1) */
+-	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+-	mmc->max_seg_size = mmc->max_req_size;
+-
+-	if (host->power_pin >= 0) {
+-		if ((ret = omap_request_gpio(host->power_pin)) != 0) {
+-			dev_err(mmc_dev(host->mmc),
+-				"Unable to get GPIO pin for MMC power\n");
+-			goto err_free_fclk;
+-		}
+-		omap_set_gpio_direction(host->power_pin, 0);
+-	}
+-
+ 	ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
+ 	if (ret)
+-		goto err_free_power_gpio;
++		goto err_free_fclk;
+ 
+-	host->dev = &pdev->dev;
+-	platform_set_drvdata(pdev, host);
++	if (pdata->init != NULL) {
++		ret = pdata->init(&pdev->dev);
++		if (ret < 0)
++			goto err_free_irq;
++	}
+ 
+-	if (host->switch_pin >= 0) {
+-		INIT_WORK(&host->switch_work, mmc_omap_switch_handler);
+-		init_timer(&host->switch_timer);
+-		host->switch_timer.function = mmc_omap_switch_timer;
+-		host->switch_timer.data = (unsigned long) host;
+-		if (omap_request_gpio(host->switch_pin) != 0) {
+-			dev_warn(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC cover switch\n");
+-			host->switch_pin = -1;
+-			goto no_switch;
+-		}
++	host->nr_slots = pdata->nr_slots;
++	for (i = 0; i < pdata->nr_slots; i++) {
++		ret = mmc_omap_new_slot(host, i);
++		if (ret < 0) {
++			while (--i >= 0)
++				mmc_omap_remove_slot(host->slots[i]);
+ 
+-		omap_set_gpio_direction(host->switch_pin, 1);
+-		ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin),
+-				  mmc_omap_switch_irq, IRQF_TRIGGER_RISING, DRIVER_NAME, host);
+-		if (ret) {
+-			dev_warn(mmc_dev(host->mmc), "Unable to get IRQ for MMC cover switch\n");
+-			omap_free_gpio(host->switch_pin);
+-			host->switch_pin = -1;
+-			goto no_switch;
+-		}
+-		ret = device_create_file(&pdev->dev, &dev_attr_cover_switch);
+-		if (ret == 0) {
+-			ret = device_create_file(&pdev->dev, &dev_attr_enable_poll);
+-			if (ret != 0)
+-				device_remove_file(&pdev->dev, &dev_attr_cover_switch);
++			goto err_plat_cleanup;
+ 		}
+-		if (ret) {
+-			dev_warn(mmc_dev(host->mmc), "Unable to create sysfs attributes\n");
+-			free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+-			omap_free_gpio(host->switch_pin);
+-			host->switch_pin = -1;
+-			goto no_switch;
+-		}
+-		if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host))
+-			schedule_work(&host->switch_work);
+ 	}
+ 
+-	mmc_add_host(mmc);
+-
+ 	return 0;
+ 
+-no_switch:
+-	/* FIXME: Free other resources too. */
+-	if (host) {
+-		if (host->iclk && !IS_ERR(host->iclk))
+-			clk_put(host->iclk);
+-		if (host->fclk && !IS_ERR(host->fclk))
+-			clk_put(host->fclk);
+-		mmc_free_host(host->mmc);
+-	}
+-err_free_power_gpio:
+-	if (host->power_pin >= 0)
+-		omap_free_gpio(host->power_pin);
++err_plat_cleanup:
++	if (pdata->cleanup)
++		pdata->cleanup(&pdev->dev);
++err_free_irq:
++	free_irq(host->irq, host);
+ err_free_fclk:
+ 	clk_put(host->fclk);
+ err_free_iclk:
+@@ -1169,7 +1511,7 @@ err_free_iclk:
+ 		clk_put(host->iclk);
+ 	}
+ err_free_mmc_host:
+-	mmc_free_host(host->mmc);
++	kfree(host);
+ err_free_mem_region:
+ 	release_mem_region(res->start, res->end - res->start + 1);
+ 	return ret;
+@@ -1178,25 +1520,18 @@ err_free_mem_region:
+ static int mmc_omap_remove(struct platform_device *pdev)
+ {
+ 	struct mmc_omap_host *host = platform_get_drvdata(pdev);
++	int i;
+ 
+ 	platform_set_drvdata(pdev, NULL);
+ 
+ 	BUG_ON(host == NULL);
+ 
+-	mmc_remove_host(host->mmc);
+-	free_irq(host->irq, host);
++	for (i = 0; i < host->nr_slots; i++)
++		mmc_omap_remove_slot(host->slots[i]);
++
++	if (host->pdata->cleanup)
++		host->pdata->cleanup(&pdev->dev);
+ 
+-	if (host->power_pin >= 0)
+-		omap_free_gpio(host->power_pin);
+-	if (host->switch_pin >= 0) {
+-		device_remove_file(&pdev->dev, &dev_attr_enable_poll);
+-		device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+-		free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+-		omap_free_gpio(host->switch_pin);
+-		host->switch_pin = -1;
+-		del_timer_sync(&host->switch_timer);
+-		flush_scheduled_work();
+-	}
+ 	if (host->iclk && !IS_ERR(host->iclk))
+ 		clk_put(host->iclk);
+ 	if (host->fclk && !IS_ERR(host->fclk))
+@@ -1205,7 +1540,7 @@ static int mmc_omap_remove(struct platform_device *pdev)
+ 	release_mem_region(pdev->resource[0].start,
+ 			   pdev->resource[0].end - pdev->resource[0].start + 1);
+ 
+-	mmc_free_host(host->mmc);
++	kfree(host);
+ 
+ 	return 0;
+ }
+@@ -1213,35 +1548,47 @@ static int mmc_omap_remove(struct platform_device *pdev)
+ #ifdef CONFIG_PM
+ static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg)
+ {
+-	int ret = 0;
++	int i, ret = 0;
+ 	struct mmc_omap_host *host = platform_get_drvdata(pdev);
+ 
+-	if (host && host->suspended)
++	if (host == NULL || host->suspended)
+ 		return 0;
+ 
+-	if (host) {
+-		ret = mmc_suspend_host(host->mmc, mesg);
+-		if (ret == 0)
+-			host->suspended = 1;
++	for (i = 0; i < host->nr_slots; i++) {
++		struct mmc_omap_slot *slot;
++
++		slot = host->slots[i];
++		ret = mmc_suspend_host(slot->mmc, mesg);
++		if (ret < 0) {
++			while (--i >= 0) {
++				slot = host->slots[i];
++				mmc_resume_host(slot->mmc);
++			}
++			return ret;
++		}
+ 	}
+-	return ret;
++	host->suspended = 1;
++	return 0;
+ }
+ 
+ static int mmc_omap_resume(struct platform_device *pdev)
+ {
+-	int ret = 0;
++	int i, ret = 0;
+ 	struct mmc_omap_host *host = platform_get_drvdata(pdev);
+ 
+-	if (host && !host->suspended)
++	if (host == NULL || !host->suspended)
+ 		return 0;
+ 
+-	if (host) {
+-		ret = mmc_resume_host(host->mmc);
+-		if (ret == 0)
+-			host->suspended = 0;
+-	}
++	for (i = 0; i < host->nr_slots; i++) {
++		struct mmc_omap_slot *slot;
++		slot = host->slots[i];
++		ret = mmc_resume_host(slot->mmc);
++		if (ret < 0)
++			return ret;
+ 
+-	return ret;
++		host->suspended = 0;
++	}
++	return 0;
+ }
+ #else
+ #define mmc_omap_suspend	NULL
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+index 4b673aa..07c2048 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -1,7 +1,7 @@
+ /*
+  *  linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
+  *
+- *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
++ *  Copyright (C) 2005-2008 Pierre Ossman, 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
+@@ -19,6 +19,8 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/scatterlist.h>
+ 
++#include <linux/leds.h>
++
+ #include <linux/mmc/host.h>
+ 
+ #include "sdhci.h"
+@@ -30,10 +32,6 @@
+ 
+ static unsigned int debug_quirks = 0;
+ 
+-/* For multi controllers in one platform case */
+-static u16 chip_index = 0;
+-static spinlock_t index_lock;
+-
+ /*
+  * Different quirks to handle when the hardware deviates from a strict
+  * interpretation of the SDHCI specification.
+@@ -43,7 +41,7 @@ static spinlock_t index_lock;
+ #define SDHCI_QUIRK_CLOCK_BEFORE_RESET			(1<<0)
+ /* Controller has bad caps bits, but really supports DMA */
+ #define SDHCI_QUIRK_FORCE_DMA				(1<<1)
+-/* Controller doesn't like some resets when there is no card inserted. */
++/* Controller doesn't like to be reset when there is no card inserted. */
+ #define SDHCI_QUIRK_NO_CARD_NO_RESET			(1<<2)
+ /* Controller doesn't like clearing the power reg before a change */
+ #define SDHCI_QUIRK_SINGLE_POWER_WRITE			(1<<3)
+@@ -71,13 +69,21 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
+ 	{
+ 		.vendor		= PCI_VENDOR_ID_RICOH,
+ 		.device		= PCI_DEVICE_ID_RICOH_R5C822,
+-		.subvendor	= PCI_ANY_ID,
++		.subvendor	= PCI_VENDOR_ID_SAMSUNG,
+ 		.subdevice	= PCI_ANY_ID,
+ 		.driver_data	= SDHCI_QUIRK_FORCE_DMA |
+ 				  SDHCI_QUIRK_NO_CARD_NO_RESET,
+ 	},
+ 
+ 	{
++		.vendor		= PCI_VENDOR_ID_RICOH,
++		.device		= PCI_DEVICE_ID_RICOH_R5C822,
++		.subvendor	= PCI_ANY_ID,
++		.subdevice	= PCI_ANY_ID,
++		.driver_data	= SDHCI_QUIRK_FORCE_DMA,
++	},
++
++	{
+ 		.vendor		= PCI_VENDOR_ID_TI,
+ 		.device		= PCI_DEVICE_ID_TI_XX21_XX11_SD,
+ 		.subvendor	= PCI_ANY_ID,
+@@ -256,6 +262,24 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
+ 	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+ }
+ 
++#ifdef CONFIG_LEDS_CLASS
++static void sdhci_led_control(struct led_classdev *led,
++	enum led_brightness brightness)
++{
++	struct sdhci_host *host = container_of(led, struct sdhci_host, led);
++	unsigned long flags;
++
++	spin_lock_irqsave(&host->lock, flags);
++
++	if (brightness == LED_OFF)
++		sdhci_deactivate_led(host);
++	else
++		sdhci_activate_led(host);
++
++	spin_unlock_irqrestore(&host->lock, flags);
++}
++#endif
++
+ /*****************************************************************************\
+  *                                                                           *
+  * Core functions                                                            *
+@@ -773,7 +797,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ 
+ 	WARN_ON(host->mrq != NULL);
+ 
++#ifndef CONFIG_LEDS_CLASS
+ 	sdhci_activate_led(host);
++#endif
+ 
+ 	host->mrq = mrq;
+ 
+@@ -965,7 +991,9 @@ static void sdhci_tasklet_finish(unsigned long param)
+ 	host->cmd = NULL;
+ 	host->data = NULL;
+ 
++#ifndef CONFIG_LEDS_CLASS
+ 	sdhci_deactivate_led(host);
++#endif
+ 
+ 	mmiowb();
+ 	spin_unlock_irqrestore(&host->lock, flags);
+@@ -1105,7 +1133,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
+ 		goto out;
+ 	}
+ 
+-	DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask);
++	DBG("*** %s got interrupt: 0x%08x\n",
++		mmc_hostname(host->mmc), intmask);
+ 
+ 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+ 		writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
+@@ -1235,7 +1264,7 @@ static int sdhci_resume (struct pci_dev *pdev)
+ 		if (chip->hosts[i]->flags & SDHCI_USE_DMA)
+ 			pci_set_master(pdev);
+ 		ret = request_irq(chip->hosts[i]->irq, sdhci_irq,
+-			IRQF_SHARED, chip->hosts[i]->slot_descr,
++			IRQF_SHARED, mmc_hostname(chip->hosts[i]->mmc),
+ 			chip->hosts[i]);
+ 		if (ret)
+ 			return ret;
+@@ -1324,9 +1353,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ 
+ 	DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
+ 
+-	snprintf(host->slot_descr, 20, "sdhc%d:slot%d", chip->index, slot);
+-
+-	ret = pci_request_region(pdev, host->bar, host->slot_descr);
++	ret = pci_request_region(pdev, host->bar, mmc_hostname(mmc));
+ 	if (ret)
+ 		goto free;
+ 
+@@ -1343,7 +1370,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ 	version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
+ 	if (version > 1) {
+ 		printk(KERN_ERR "%s: Unknown controller version (%d). "
+-			"You may experience problems.\n", host->slot_descr,
++			"You may experience problems.\n", mmc_hostname(mmc),
+ 			version);
+ 	}
+ 
+@@ -1366,13 +1393,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ 		(host->flags & SDHCI_USE_DMA)) {
+ 		printk(KERN_WARNING "%s: Will use DMA "
+ 			"mode even though HW doesn't fully "
+-			"claim to support it.\n", host->slot_descr);
++			"claim to support it.\n", mmc_hostname(mmc));
+ 	}
+ 
+ 	if (host->flags & SDHCI_USE_DMA) {
+ 		if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ 			printk(KERN_WARNING "%s: No suitable DMA available. "
+-				"Falling back to PIO.\n", host->slot_descr);
++				"Falling back to PIO.\n", mmc_hostname(mmc));
+ 			host->flags &= ~SDHCI_USE_DMA;
+ 		}
+ 	}
+@@ -1386,7 +1413,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ 		(caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
+ 	if (host->max_clk == 0) {
+ 		printk(KERN_ERR "%s: Hardware doesn't specify base clock "
+-			"frequency.\n", host->slot_descr);
++			"frequency.\n", mmc_hostname(mmc));
+ 		ret = -ENODEV;
+ 		goto unmap;
+ 	}
+@@ -1396,7 +1423,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ 		(caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
+ 	if (host->timeout_clk == 0) {
+ 		printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
+-			"frequency.\n", host->slot_descr);
++			"frequency.\n", mmc_hostname(mmc));
+ 		ret = -ENODEV;
+ 		goto unmap;
+ 	}
+@@ -1424,7 +1451,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ 
+ 	if (mmc->ocr_avail == 0) {
+ 		printk(KERN_ERR "%s: Hardware doesn't report any "
+-			"support voltages.\n", host->slot_descr);
++			"support voltages.\n", mmc_hostname(mmc));
+ 		ret = -ENODEV;
+ 		goto unmap;
+ 	}
+@@ -1458,8 +1485,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ 	 */
+ 	mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
+ 	if (mmc->max_blk_size >= 3) {
+-		printk(KERN_WARNING "%s: Invalid maximum block size, assuming 512\n",
+-			host->slot_descr);
++		printk(KERN_WARNING "%s: Invalid maximum block size, "
++			"assuming 512 bytes\n", mmc_hostname(mmc));
+ 		mmc->max_blk_size = 512;
+ 	} else
+ 		mmc->max_blk_size = 512 << mmc->max_blk_size;
+@@ -1480,7 +1507,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ 	setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
+ 
+ 	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
+-		host->slot_descr, host);
++		mmc_hostname(mmc), host);
+ 	if (ret)
+ 		goto untasklet;
+ 
+@@ -1490,16 +1517,32 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ 	sdhci_dumpregs(host);
+ #endif
+ 
++#ifdef CONFIG_LEDS_CLASS
++	host->led.name = mmc_hostname(mmc);
++	host->led.brightness = LED_OFF;
++	host->led.default_trigger = mmc_hostname(mmc);
++	host->led.brightness_set = sdhci_led_control;
++
++	ret = led_classdev_register(&pdev->dev, &host->led);
++	if (ret)
++		goto reset;
++#endif
++
+ 	mmiowb();
+ 
+ 	mmc_add_host(mmc);
+ 
+-	printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc),
+-		host->addr, host->irq,
++	printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n",
++		mmc_hostname(mmc), host->addr, host->irq,
+ 		(host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
+ 
+ 	return 0;
+ 
++#ifdef CONFIG_LEDS_CLASS
++reset:
++	sdhci_reset(host, SDHCI_RESET_ALL);
++	free_irq(host->irq, host);
++#endif
+ untasklet:
+ 	tasklet_kill(&host->card_tasklet);
+ 	tasklet_kill(&host->finish_tasklet);
+@@ -1527,6 +1570,10 @@ static void sdhci_remove_slot(struct pci_dev *pdev, int slot)
+ 
+ 	mmc_remove_host(mmc);
+ 
++#ifdef CONFIG_LEDS_CLASS
++	led_classdev_unregister(&host->led);
++#endif
++
+ 	sdhci_reset(host, SDHCI_RESET_ALL);
+ 
+ 	free_irq(host->irq, host);
+@@ -1589,11 +1636,6 @@ static int __devinit sdhci_probe(struct pci_dev *pdev,
+ 	chip->num_slots = slots;
+ 	pci_set_drvdata(pdev, chip);
+ 
+-	/* Add for multi controller case */
+-	spin_lock(&index_lock);
+-	chip->index = chip_index++;
+-	spin_unlock(&index_lock);
+-
+ 	for (i = 0;i < slots;i++) {
+ 		ret = sdhci_probe_slot(pdev, i);
+ 		if (ret) {
+@@ -1654,8 +1696,6 @@ static int __init sdhci_drv_init(void)
+ 		": Secure Digital Host Controller Interface driver\n");
+ 	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
+ 
+-	spin_lock_init(&index_lock);
+-
+ 	return pci_register_driver(&sdhci_driver);
+ }
+ 
+diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
+index d5a38f1..7fb02e1 100644
+--- a/drivers/mmc/host/sdhci.h
++++ b/drivers/mmc/host/sdhci.h
+@@ -1,7 +1,7 @@
+ /*
+  *  linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver
+  *
+- *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
++ *  Copyright (C) 2005-2008 Pierre Ossman, 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
+@@ -168,6 +168,10 @@ struct sdhci_host {
+ 	struct sdhci_chip	*chip;
+ 	struct mmc_host		*mmc;		/* MMC structure */
+ 
++#ifdef CONFIG_LEDS_CLASS
++	struct led_classdev	led;		/* LED control */
++#endif
++
+ 	spinlock_t		lock;		/* Mutex */
+ 
+ 	int			flags;		/* Host attributes */
+@@ -190,8 +194,6 @@ struct sdhci_host {
+ 	int			offset;		/* Offset into current sg */
+ 	int			remain;		/* Bytes left in current */
+ 
+-	char			slot_descr[20];	/* Name for reservations */
+-
+ 	int			irq;		/* Device IRQ */
+ 	int			bar;		/* PCI BAR index */
+ 	unsigned long		addr;		/* Bus address */
+@@ -208,7 +210,6 @@ struct sdhci_chip {
+ 
+ 	unsigned long		quirks;
+ 
+-	int			index;		/* Index for chip0, chip1 ...*/
+ 	int			num_slots;	/* Slots on controller */
+ 	struct sdhci_host	*hosts[0];	/* Pointers to hosts */
+ };
+diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
+index e850334..eed06d0 100644
+--- a/drivers/mtd/Kconfig
++++ b/drivers/mtd/Kconfig
+@@ -158,6 +158,12 @@ config MTD_OF_PARTS
+ 	  the partition map from the children of the flash node,
+ 	  as described in Documentation/powerpc/booting-without-of.txt.
+ 
++config MTD_AR7_PARTS
++	tristate "TI AR7 partitioning support"
++	depends on MTD_PARTITIONS
++	---help---
++	  TI AR7 partitioning support
++
+ comment "User Modules And Translation Layers"
+ 
+ config MTD_CHAR
+diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
+index 538e33d..4b77335 100644
+--- a/drivers/mtd/Makefile
++++ b/drivers/mtd/Makefile
+@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT)	+= mtdconcat.o
+ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
+ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
+ obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
++obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
+ obj-$(CONFIG_MTD_OF_PARTS)      += ofpart.o
+ 
+ # 'Users' - code which presents functionality to userspace.
+diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
+new file mode 100644
+index 0000000..ecf170b
+--- /dev/null
++++ b/drivers/mtd/ar7part.c
+@@ -0,0 +1,151 @@
++/*
++ * Copyright © 2007 Eugene Konev <ejka at openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ *
++ * TI AR7 flash partition table.
++ * Based on ar7 map by Felix Fietkau <nbd at openwrt.org>
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/bootmem.h>
++#include <linux/magic.h>
++
++#define AR7_PARTS	4
++#define ROOT_OFFSET	0xe0000
++
++#define LOADER_MAGIC1	le32_to_cpu(0xfeedfa42)
++#define LOADER_MAGIC2	le32_to_cpu(0xfeed1281)
++
++#ifndef SQUASHFS_MAGIC
++#define SQUASHFS_MAGIC	0x73717368
++#endif
++
++struct ar7_bin_rec {
++	unsigned int checksum;
++	unsigned int length;
++	unsigned int address;
++};
++
++static struct mtd_partition ar7_parts[AR7_PARTS];
++
++static int create_mtd_partitions(struct mtd_info *master,
++				 struct mtd_partition **pparts,
++				 unsigned long origin)
++{
++	struct ar7_bin_rec header;
++	unsigned int offset;
++	size_t len;
++	unsigned int pre_size = master->erasesize, post_size = 0;
++	unsigned int root_offset = ROOT_OFFSET;
++
++	int retries = 10;
++
++	ar7_parts[0].name = "loader";
++	ar7_parts[0].offset = 0;
++	ar7_parts[0].size = master->erasesize;
++	ar7_parts[0].mask_flags = MTD_WRITEABLE;
++
++	ar7_parts[1].name = "config";
++	ar7_parts[1].offset = 0;
++	ar7_parts[1].size = master->erasesize;
++	ar7_parts[1].mask_flags = 0;
++
++	do { /* Try 10 blocks starting from master->erasesize */
++		offset = pre_size;
++		master->read(master, offset,
++			     sizeof(header), &len, (uint8_t *)&header);
++		if (!strncmp((char *)&header, "TIENV0.8", 8))
++			ar7_parts[1].offset = pre_size;
++		if (header.checksum == LOADER_MAGIC1)
++			break;
++		if (header.checksum == LOADER_MAGIC2)
++			break;
++		pre_size += master->erasesize;
++	} while (retries--);
++
++	pre_size = offset;
++
++	if (!ar7_parts[1].offset) {
++		ar7_parts[1].offset = master->size - master->erasesize;
++		post_size = master->erasesize;
++	}
++
++	switch (header.checksum) {
++	case LOADER_MAGIC1:
++		while (header.length) {
++			offset += sizeof(header) + header.length;
++			master->read(master, offset, sizeof(header),
++				     &len, (uint8_t *)&header);
++		}
++		root_offset = offset + sizeof(header) + 4;
++		break;
++	case LOADER_MAGIC2:
++		while (header.length) {
++			offset += sizeof(header) + header.length;
++			master->read(master, offset, sizeof(header),
++				     &len, (uint8_t *)&header);
++		}
++		root_offset = offset + sizeof(header) + 4 + 0xff;
++		root_offset &= ~(uint32_t)0xff;
++		break;
++	default:
++		printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum);
++		break;
++	}
++
++	master->read(master, root_offset,
++		sizeof(header), &len, (u8 *)&header);
++	if (header.checksum != SQUASHFS_MAGIC) {
++		root_offset += master->erasesize - 1;
++		root_offset &= ~(master->erasesize - 1);
++	}
++
++	ar7_parts[2].name = "linux";
++	ar7_parts[2].offset = pre_size;
++	ar7_parts[2].size = master->size - pre_size - post_size;
++	ar7_parts[2].mask_flags = 0;
++
++	ar7_parts[3].name = "rootfs";
++	ar7_parts[3].offset = root_offset;
++	ar7_parts[3].size = master->size - root_offset - post_size;
++	ar7_parts[3].mask_flags = 0;
++
++	*pparts = ar7_parts;
++	return AR7_PARTS;
++}
++
++static struct mtd_part_parser ar7_parser = {
++	.owner = THIS_MODULE,
++	.parse_fn = create_mtd_partitions,
++	.name = "ar7part",
++};
++
++static int __init ar7_parser_init(void)
++{
++	return register_mtd_parser(&ar7_parser);
++}
++
++module_init(ar7_parser_init);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR(	"Felix Fietkau <nbd at openwrt.org>, "
++		"Eugene Konev <ejka at openwrt.org>");
++MODULE_DESCRIPTION("MTD partitioning for TI AR7");
+diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
+index 0080452..e812df6 100644
+--- a/drivers/mtd/chips/cfi_cmdset_0001.c
++++ b/drivers/mtd/chips/cfi_cmdset_0001.c
+@@ -384,7 +384,7 @@ read_pri_intelext(struct map_info *map, __u16 adr)
+ 			if (extp_size > 4096) {
+ 				printk(KERN_ERR
+ 					"%s: cfi_pri_intelext is too fat\n",
+-					__FUNCTION__);
++					__func__);
+ 				return NULL;
+ 			}
+ 			goto again;
+@@ -619,6 +619,9 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
+ 				  sizeof(struct cfi_intelext_blockinfo);
+ 		}
+ 
++		if (!numparts)
++			numparts = 1;
++
+ 		/* Programming Region info */
+ 		if (extp->MinorVersion >= '4') {
+ 			struct cfi_intelext_programming_regioninfo *prinfo;
+@@ -641,7 +644,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
+ 		if ((1 << partshift) < mtd->erasesize) {
+ 			printk( KERN_ERR
+ 				"%s: bad number of hw partitions (%d)\n",
+-				__FUNCTION__, numparts);
++				__func__, numparts);
+ 			return -EINVAL;
+ 		}
+ 
+@@ -1071,10 +1074,10 @@ static int __xipram xip_wait_for_operation(
+ 			chip->state = newstate;
+ 			map_write(map, CMD(0xff), adr);
+ 			(void) map_read(map, adr);
+-			asm volatile (".rep 8; nop; .endr");
++			xip_iprefetch();
+ 			local_irq_enable();
+ 			spin_unlock(chip->mutex);
+-			asm volatile (".rep 8; nop; .endr");
++			xip_iprefetch();
+ 			cond_resched();
+ 
+ 			/*
+@@ -2013,7 +2016,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+ 
+ #ifdef DEBUG_LOCK_BITS
+ 	printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
+-	       __FUNCTION__, ofs, len);
++	       __func__, ofs, len);
+ 	cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+ 		ofs, len, NULL);
+ #endif
+@@ -2023,7 +2026,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+ 
+ #ifdef DEBUG_LOCK_BITS
+ 	printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
+-	       __FUNCTION__, ret);
++	       __func__, ret);
+ 	cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+ 		ofs, len, NULL);
+ #endif
+@@ -2037,7 +2040,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+ 
+ #ifdef DEBUG_LOCK_BITS
+ 	printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
+-	       __FUNCTION__, ofs, len);
++	       __func__, ofs, len);
+ 	cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+ 		ofs, len, NULL);
+ #endif
+@@ -2047,7 +2050,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+ 
+ #ifdef DEBUG_LOCK_BITS
+ 	printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
+-	       __FUNCTION__, ret);
++	       __func__, ret);
+ 	cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+ 		ofs, len, NULL);
+ #endif
+diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
+index 458d477..f7fcc63 100644
+--- a/drivers/mtd/chips/cfi_cmdset_0002.c
++++ b/drivers/mtd/chips/cfi_cmdset_0002.c
+@@ -220,6 +220,28 @@ static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
+ 	mtd->flags |= MTD_POWERUP_LOCK;
+ }
+ 
++static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
++{
++	struct map_info *map = mtd->priv;
++	struct cfi_private *cfi = map->fldrv_priv;
++
++	if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) {
++		cfi->cfiq->EraseRegionInfo[0] |= 0x0040;
++		pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name);
++	}
++}
++
++static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
++{
++	struct map_info *map = mtd->priv;
++	struct cfi_private *cfi = map->fldrv_priv;
++
++	if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) {
++		cfi->cfiq->EraseRegionInfo[1] &= ~0x0040;
++		pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name);
++	}
++}
++
+ static struct cfi_fixup cfi_fixup_table[] = {
+ 	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
+ #ifdef AMD_BOOTLOC_BUG
+@@ -231,6 +253,10 @@ static struct cfi_fixup cfi_fixup_table[] = {
+ 	{ CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, },
+ 	{ CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, },
+ 	{ CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, },
++	{ CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors, NULL, },
++	{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
++	{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
++	{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
+ #if !FORCE_WORD_WRITE
+ 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
+ #endif
+@@ -723,10 +749,10 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
+ 			chip->erase_suspended = 1;
+ 			map_write(map, CMD(0xf0), adr);
+ 			(void) map_read(map, adr);
+-			asm volatile (".rep 8; nop; .endr");
++			xip_iprefetch();
+ 			local_irq_enable();
+ 			spin_unlock(chip->mutex);
+-			asm volatile (".rep 8; nop; .endr");
++			xip_iprefetch();
+ 			cond_resched();
+ 
+ 			/*
+diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
+index 492e2ab..1b720cc 100644
+--- a/drivers/mtd/chips/cfi_cmdset_0020.c
++++ b/drivers/mtd/chips/cfi_cmdset_0020.c
+@@ -445,7 +445,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
+  retry:
+ 
+ #ifdef DEBUG_CFI_FEATURES
+-       printk("%s: chip->state[%d]\n", __FUNCTION__, chip->state);
++       printk("%s: chip->state[%d]\n", __func__, chip->state);
+ #endif
+ 	spin_lock_bh(chip->mutex);
+ 
+@@ -463,7 +463,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
+ 		map_write(map, CMD(0x70), cmd_adr);
+                 chip->state = FL_STATUS;
+ #ifdef DEBUG_CFI_FEATURES
+-        printk("%s: 1 status[%x]\n", __FUNCTION__, map_read(map, cmd_adr));
++	printk("%s: 1 status[%x]\n", __func__, map_read(map, cmd_adr));
+ #endif
+ 
+ 	case FL_STATUS:
+@@ -591,7 +591,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
+         /* check for errors: 'lock bit', 'VPP', 'dead cell'/'unerased cell' or 'incorrect cmd' -- saw */
+         if (map_word_bitsset(map, status, CMD(0x3a))) {
+ #ifdef DEBUG_CFI_FEATURES
+-		printk("%s: 2 status[%lx]\n", __FUNCTION__, status.x[0]);
++		printk("%s: 2 status[%lx]\n", __func__, status.x[0]);
+ #endif
+ 		/* clear status */
+ 		map_write(map, CMD(0x50), cmd_adr);
+@@ -625,9 +625,9 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
+ 	ofs = to  - (chipnum << cfi->chipshift);
+ 
+ #ifdef DEBUG_CFI_FEATURES
+-        printk("%s: map_bankwidth(map)[%x]\n", __FUNCTION__, map_bankwidth(map));
+-        printk("%s: chipnum[%x] wbufsize[%x]\n", __FUNCTION__, chipnum, wbufsize);
+-        printk("%s: ofs[%x] len[%x]\n", __FUNCTION__, ofs, len);
++	printk("%s: map_bankwidth(map)[%x]\n", __func__, map_bankwidth(map));
++	printk("%s: chipnum[%x] wbufsize[%x]\n", __func__, chipnum, wbufsize);
++	printk("%s: ofs[%x] len[%x]\n", __func__, ofs, len);
+ #endif
+ 
+         /* Write buffer is worth it only if more than one word to write... */
+@@ -893,7 +893,8 @@ retry:
+ 	return ret;
+ }
+ 
+-int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
++static int cfi_staa_erase_varsize(struct mtd_info *mtd,
++				  struct erase_info *instr)
+ {	struct map_info *map = mtd->priv;
+ 	struct cfi_private *cfi = map->fldrv_priv;
+ 	unsigned long adr, len;
+diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
+index f651b6e..a4463a9 100644
+--- a/drivers/mtd/chips/cfi_probe.c
++++ b/drivers/mtd/chips/cfi_probe.c
+@@ -39,7 +39,7 @@ struct mtd_info *cfi_probe(struct map_info *map);
+ #define xip_allowed(base, map) \
+ do { \
+ 	(void) map_read(map, base); \
+-	asm volatile (".rep 8; nop; .endr"); \
++	xip_iprefetch(); \
+ 	local_irq_enable(); \
+ } while (0)
+ 
+@@ -232,6 +232,11 @@ static int __xipram cfi_chip_setup(struct map_info *map,
+ 	cfi->mfr = cfi_read_query16(map, base);
+ 	cfi->id = cfi_read_query16(map, base + ofs_factor);
+ 
++	/* Get AMD/Spansion extended JEDEC ID */
++	if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
++		cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
++			  cfi_read_query(map, base + 0xf * ofs_factor);
++
+ 	/* Put it back into Read Mode */
+ 	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+ 	/* ... even if it's an Intel chip */
+diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
+index 2e51496..72e0022 100644
+--- a/drivers/mtd/chips/cfi_util.c
++++ b/drivers/mtd/chips/cfi_util.c
+@@ -65,7 +65,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
+ 
+ #ifdef CONFIG_MTD_XIP
+ 	(void) map_read(map, base);
+-	asm volatile (".rep 8; nop; .endr");
++	xip_iprefetch();
+ 	local_irq_enable();
+ #endif
+ 
+diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
+index 4be51a8..aa07575 100644
+--- a/drivers/mtd/chips/jedec_probe.c
++++ b/drivers/mtd/chips/jedec_probe.c
+@@ -132,6 +132,8 @@
+ #define M29F800AB	0x0058
+ #define M29W800DT	0x00D7
+ #define M29W800DB	0x005B
++#define M29W400DT	0x00EE
++#define M29W400DB	0x00EF
+ #define M29W160DT	0x22C4
+ #define M29W160DB	0x2249
+ #define M29W040B	0x00E3
+@@ -160,6 +162,7 @@
+ #define SST49LF030A	0x001C
+ #define SST49LF040A	0x0051
+ #define SST49LF080A	0x005B
++#define SST36VF3203	0x7354
+ 
+ /* Toshiba */
+ #define TC58FVT160	0x00C2
+@@ -1113,7 +1116,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x10000,8),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_MACRONIX,
+ 		.dev_id		= MX29F016,
+ 		.name		= "Macronix MX29F016",
+@@ -1125,7 +1128,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x10000,32),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_MACRONIX,
+ 		.dev_id		= MX29F004T,
+ 		.name		= "Macronix MX29F004T",
+@@ -1140,7 +1143,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 			ERASEINFO(0x02000,2),
+ 			ERASEINFO(0x04000,1),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_MACRONIX,
+ 		.dev_id		= MX29F004B,
+ 		.name		= "Macronix MX29F004B",
+@@ -1218,7 +1221,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x40000,16),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_SST,
+ 		.dev_id		= SST39LF512,
+ 		.name		= "SST 39LF512",
+@@ -1230,7 +1233,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x01000,16),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_SST,
+ 		.dev_id		= SST39LF010,
+ 		.name		= "SST 39LF010",
+@@ -1242,7 +1245,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x01000,32),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_SST,
+  		.dev_id 	= SST29EE020,
+ 		.name		= "SST 29EE020",
+@@ -1276,7 +1279,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x01000,64),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_SST,
+ 		.dev_id		= SST39LF040,
+ 		.name		= "SST 39LF040",
+@@ -1288,7 +1291,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x01000,128),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_SST,
+ 		.dev_id		= SST39SF010A,
+ 		.name		= "SST 39SF010A",
+@@ -1300,7 +1303,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x01000,32),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_SST,
+ 		.dev_id		= SST39SF020A,
+ 		.name		= "SST 39SF020A",
+@@ -1412,6 +1415,18 @@ static const struct amd_flash_info jedec_table[] = {
+ 			ERASEINFO(0x1000,256)
+ 		}
+ 	}, {
++		.mfr_id		= MANUFACTURER_SST,
++		.dev_id		= SST36VF3203,
++		.name		= "SST 36VF3203",
++		.devtypes	= CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
++		.uaddr		= MTD_UADDR_0x0AAA_0x0555,
++		.dev_size	= SIZE_4MiB,
++		.cmd_set	= P_ID_AMD_STD,
++		.nr_regions	= 1,
++		.regions	= {
++			ERASEINFO(0x10000,64),
++		}
++	}, {
+ 		.mfr_id		= MANUFACTURER_ST,
+ 		.dev_id		= M29F800AB,
+ 		.name		= "ST M29F800AB",
+@@ -1426,7 +1441,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 			ERASEINFO(0x08000,1),
+ 			ERASEINFO(0x10000,15),
+ 		}
+-       }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_ST,	/* FIXME - CFI device? */
+ 		.dev_id		= M29W800DT,
+ 		.name		= "ST M29W800DT",
+@@ -1456,6 +1471,36 @@ static const struct amd_flash_info jedec_table[] = {
+ 			ERASEINFO(0x08000,1),
+ 			ERASEINFO(0x10000,15)
+ 		}
++	},  {
++		.mfr_id         = MANUFACTURER_ST,
++		.dev_id         = M29W400DT,
++		.name           = "ST M29W400DT",
++		.devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
++		.uaddr          = MTD_UADDR_0x0AAA_0x0555,
++		.dev_size       = SIZE_512KiB,
++		.cmd_set        = P_ID_AMD_STD,
++		.nr_regions     = 4,
++		.regions        = {
++			ERASEINFO(0x04000,7),
++			ERASEINFO(0x02000,1),
++			ERASEINFO(0x08000,2),
++			ERASEINFO(0x10000,1)
++		}
++	}, {
++		.mfr_id         = MANUFACTURER_ST,
++		.dev_id         = M29W400DB,
++		.name           = "ST M29W400DB",
++		.devtypes       = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
++		.uaddr          = MTD_UADDR_0x0AAA_0x0555,
++		.dev_size       = SIZE_512KiB,
++		.cmd_set        = P_ID_AMD_STD,
++		.nr_regions     = 4,
++		.regions        = {
++			ERASEINFO(0x04000,1),
++			ERASEINFO(0x02000,2),
++			ERASEINFO(0x08000,1),
++			ERASEINFO(0x10000,7)
++		}
+ 	}, {
+ 		.mfr_id		= MANUFACTURER_ST,	/* FIXME - CFI device? */
+ 		.dev_id		= M29W160DT,
+@@ -1486,7 +1531,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 			ERASEINFO(0x08000,1),
+ 			ERASEINFO(0x10000,31)
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_ST,
+ 		.dev_id		= M29W040B,
+ 		.name		= "ST M29W040B",
+@@ -1498,7 +1543,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x10000,8),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_ST,
+ 		.dev_id		= M50FW040,
+ 		.name		= "ST M50FW040",
+@@ -1510,7 +1555,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x10000,8),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_ST,
+ 		.dev_id		= M50FW080,
+ 		.name		= "ST M50FW080",
+@@ -1522,7 +1567,7 @@ static const struct amd_flash_info jedec_table[] = {
+ 		.regions	= {
+ 			ERASEINFO(0x10000,16),
+ 		}
+-        }, {
++	}, {
+ 		.mfr_id		= MANUFACTURER_ST,
+ 		.dev_id		= M50FW016,
+ 		.name		= "ST M50FW016",
+diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
+index b44292a..e472a0e 100644
+--- a/drivers/mtd/cmdlinepart.c
++++ b/drivers/mtd/cmdlinepart.c
+@@ -119,7 +119,8 @@ static struct mtd_partition * newpart(char *s,
+ 		char *p;
+ 
+ 	    	name = ++s;
+-		if ((p = strchr(name, delim)) == 0)
++		p = strchr(name, delim);
++		if (!p)
+ 		{
+ 			printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
+ 			return NULL;
+@@ -159,9 +160,10 @@ static struct mtd_partition * newpart(char *s,
+ 			return NULL;
+ 		}
+ 		/* more partitions follow, parse them */
+-		if ((parts = newpart(s + 1, &s, num_parts,
+-		                     this_part + 1, &extra_mem, extra_mem_size)) == 0)
+-		  return NULL;
++		parts = newpart(s + 1, &s, num_parts, this_part + 1,
++				&extra_mem, extra_mem_size);
++		if (!parts)
++			return NULL;
+ 	}
+ 	else
+ 	{	/* this is the last partition: allocate space for all */
+@@ -308,9 +310,6 @@ static int parse_cmdline_partitions(struct mtd_info *master,
+ 	struct cmdline_mtd_partition *part;
+ 	char *mtd_id = master->name;
+ 
+-	if(!cmdline)
+-		return -EINVAL;
+-
+ 	/* parse command line */
+ 	if (!cmdline_parsed)
+ 		mtdpart_setup_real(cmdline);
+@@ -341,7 +340,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
+ 			return part->num_parts;
+ 		}
+ 	}
+-	return -EINVAL;
++	return 0;
+ }
+ 
+ 
+diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
+index 811d56f..35ed110 100644
+--- a/drivers/mtd/devices/Kconfig
++++ b/drivers/mtd/devices/Kconfig
+@@ -77,6 +77,13 @@ config MTD_M25P80
+ 	  if you want to specify device partitioning or to use a device which
+ 	  doesn't support the JEDEC ID instruction.
+ 
++config M25PXX_USE_FAST_READ
++	bool "Use FAST_READ OPCode allowing SPI CLK <= 50MHz"
++	depends on MTD_M25P80
++	default y
++	help
++	  This option enables FAST_READ access supported by ST M25Pxx.
++
+ config MTD_SLRAM
+ 	tristate "Uncached system RAM"
+ 	help
+diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
+index ad1880c..519d942 100644
+--- a/drivers/mtd/devices/block2mtd.c
++++ b/drivers/mtd/devices/block2mtd.c
+@@ -305,7 +305,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
+ 	}
+ 	list_add(&dev->list, &blkmtd_device_list);
+ 	INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
+-			dev->mtd.name + strlen("blkmtd: "),
++			dev->mtd.name + strlen("block2mtd: "),
+ 			dev->mtd.erasesize >> 10, dev->mtd.erasesize);
+ 	return dev;
+ 
+@@ -366,9 +366,9 @@ static inline void kill_final_newline(char *str)
+ }
+ 
+ 
+-#define parse_err(fmt, args...) do {		\
+-	ERROR("block2mtd: " fmt "\n", ## args);	\
+-	return 0;				\
++#define parse_err(fmt, args...) do {	\
++	ERROR(fmt, ## args);		\
++	return 0;			\
+ } while (0)
+ 
+ #ifndef MODULE
+@@ -473,7 +473,7 @@ static void __devexit block2mtd_exit(void)
+ 		block2mtd_sync(&dev->mtd);
+ 		del_mtd_device(&dev->mtd);
+ 		INFO("mtd%d: [%s] removed", dev->mtd.index,
+-				dev->mtd.name + strlen("blkmtd: "));
++				dev->mtd.name + strlen("block2mtd: "));
+ 		list_del(&dev->list);
+ 		block2mtd_free_device(dev);
+ 	}
+diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
+index 99fd210..1d324e5 100644
+--- a/drivers/mtd/devices/lart.c
++++ b/drivers/mtd/devices/lart.c
+@@ -275,7 +275,7 @@ static __u8 read8 (__u32 offset)
+ {
+    volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset);
+ #ifdef LART_DEBUG
+-   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n",__FUNCTION__,offset,*data);
++   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n", __func__, offset, *data);
+ #endif
+    return (*data);
+ }
+@@ -284,7 +284,7 @@ static __u32 read32 (__u32 offset)
+ {
+    volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
+ #ifdef LART_DEBUG
+-   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n",__FUNCTION__,offset,*data);
++   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n", __func__, offset, *data);
+ #endif
+    return (*data);
+ }
+@@ -294,7 +294,7 @@ static void write32 (__u32 x,__u32 offset)
+    volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
+    *data = x;
+ #ifdef LART_DEBUG
+-   printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,*data);
++   printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, *data);
+ #endif
+ }
+ 
+@@ -337,7 +337,7 @@ static inline int erase_block (__u32 offset)
+    __u32 status;
+ 
+ #ifdef LART_DEBUG
+-   printk (KERN_DEBUG "%s(): 0x%.8x\n",__FUNCTION__,offset);
++   printk (KERN_DEBUG "%s(): 0x%.8x\n", __func__, offset);
+ #endif
+ 
+    /* erase and confirm */
+@@ -371,7 +371,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
+    int i,first;
+ 
+ #ifdef LART_DEBUG
+-   printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len);
++   printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n", __func__, instr->addr, instr->len);
+ #endif
+ 
+    /* sanity checks */
+@@ -442,7 +442,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
+ static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf)
+ {
+ #ifdef LART_DEBUG
+-   printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) from,len);
++   printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n", __func__, (__u32)from, len);
+ #endif
+ 
+    /* sanity checks */
+@@ -488,7 +488,7 @@ static inline int write_dword (__u32 offset,__u32 x)
+    __u32 status;
+ 
+ #ifdef LART_DEBUG
+-   printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,x);
++   printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, x);
+ #endif
+ 
+    /* setup writing */
+@@ -524,7 +524,7 @@ static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen
+    int i,n;
+ 
+ #ifdef LART_DEBUG
+-   printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len);
++   printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n", __func__, (__u32)to, len);
+ #endif
+ 
+    *retlen = 0;
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 98df5bc..25efd33 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -33,7 +33,7 @@
+ /* Flash opcodes. */
+ #define	OPCODE_WREN		0x06	/* Write enable */
+ #define	OPCODE_RDSR		0x05	/* Read status register */
+-#define	OPCODE_READ		0x03	/* Read data bytes (low frequency) */
++#define	OPCODE_NORM_READ	0x03	/* Read data bytes (low frequency) */
+ #define	OPCODE_FAST_READ	0x0b	/* Read data bytes (high frequency) */
+ #define	OPCODE_PP		0x02	/* Page program (up to 256 bytes) */
+ #define	OPCODE_BE_4K 		0x20	/* Erase 4KiB block */
+@@ -52,7 +52,15 @@
+ 
+ /* Define max times to check status register before we give up. */
+ #define	MAX_READY_WAIT_COUNT	100000
++#define	CMD_SIZE		4
+ 
++#ifdef CONFIG_M25PXX_USE_FAST_READ
++#define OPCODE_READ 	OPCODE_FAST_READ
++#define FAST_READ_DUMMY_BYTE 1
++#else
++#define OPCODE_READ 	OPCODE_NORM_READ
++#define FAST_READ_DUMMY_BYTE 0
++#endif
+ 
+ #ifdef CONFIG_MTD_PARTITIONS
+ #define	mtd_has_partitions()	(1)
+@@ -68,7 +76,7 @@ struct m25p {
+ 	struct mtd_info		mtd;
+ 	unsigned		partitioned:1;
+ 	u8			erase_opcode;
+-	u8			command[4];
++	u8			command[CMD_SIZE + FAST_READ_DUMMY_BYTE];
+ };
+ 
+ static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
+@@ -151,7 +159,7 @@ static int wait_till_ready(struct m25p *flash)
+ static int erase_sector(struct m25p *flash, u32 offset)
+ {
+ 	DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
+-			flash->spi->dev.bus_id, __FUNCTION__,
++			flash->spi->dev.bus_id, __func__,
+ 			flash->mtd.erasesize / 1024, offset);
+ 
+ 	/* Wait until finished previous write command. */
+@@ -167,7 +175,7 @@ static int erase_sector(struct m25p *flash, u32 offset)
+ 	flash->command[2] = offset >> 8;
+ 	flash->command[3] = offset;
+ 
+-	spi_write(flash->spi, flash->command, sizeof(flash->command));
++	spi_write(flash->spi, flash->command, CMD_SIZE);
+ 
+ 	return 0;
+ }
+@@ -188,7 +196,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
+ 	u32 addr,len;
+ 
+ 	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
+-			flash->spi->dev.bus_id, __FUNCTION__, "at",
++			flash->spi->dev.bus_id, __func__, "at",
+ 			(u32)instr->addr, instr->len);
+ 
+ 	/* sanity checks */
+@@ -240,7 +248,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+ 	struct spi_message m;
+ 
+ 	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+-			flash->spi->dev.bus_id, __FUNCTION__, "from",
++			flash->spi->dev.bus_id, __func__, "from",
+ 			(u32)from, len);
+ 
+ 	/* sanity checks */
+@@ -253,8 +261,12 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+ 	spi_message_init(&m);
+ 	memset(t, 0, (sizeof t));
+ 
++	/* NOTE:
++	 * OPCODE_FAST_READ (if available) is faster.
++	 * Should add 1 byte DUMMY_BYTE.
++	 */
+ 	t[0].tx_buf = flash->command;
+-	t[0].len = sizeof(flash->command);
++	t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE;
+ 	spi_message_add_tail(&t[0], &m);
+ 
+ 	t[1].rx_buf = buf;
+@@ -287,7 +299,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+ 
+ 	spi_sync(flash->spi, &m);
+ 
+-	*retlen = m.actual_length - sizeof(flash->command);
++	*retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE;
+ 
+ 	mutex_unlock(&flash->lock);
+ 
+@@ -308,7 +320,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ 	struct spi_message m;
+ 
+ 	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+-			flash->spi->dev.bus_id, __FUNCTION__, "to",
++			flash->spi->dev.bus_id, __func__, "to",
+ 			(u32)to, len);
+ 
+ 	if (retlen)
+@@ -325,7 +337,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ 	memset(t, 0, (sizeof t));
+ 
+ 	t[0].tx_buf = flash->command;
+-	t[0].len = sizeof(flash->command);
++	t[0].len = CMD_SIZE;
+ 	spi_message_add_tail(&t[0], &m);
+ 
+ 	t[1].tx_buf = buf;
+@@ -354,7 +366,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ 
+ 		spi_sync(flash->spi, &m);
+ 
+-		*retlen = m.actual_length - sizeof(flash->command);
++		*retlen = m.actual_length - CMD_SIZE;
+ 	} else {
+ 		u32 i;
+ 
+@@ -364,7 +376,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ 		t[1].len = page_size;
+ 		spi_sync(flash->spi, &m);
+ 
+-		*retlen = m.actual_length - sizeof(flash->command);
++		*retlen = m.actual_length - CMD_SIZE;
+ 
+ 		/* write everything in PAGESIZE chunks */
+ 		for (i = page_size; i < len; i += page_size) {
+@@ -387,8 +399,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ 			spi_sync(flash->spi, &m);
+ 
+ 			if (retlen)
+-				*retlen += m.actual_length
+-					- sizeof(flash->command);
++				*retlen += m.actual_length - CMD_SIZE;
+ 		}
+ 	}
+ 
+@@ -435,6 +446,7 @@ static struct flash_info __devinitdata m25p_data [] = {
+ 	{ "at25fs040",  0x1f6604, 64 * 1024, 8, SECT_4K, },
+ 
+ 	{ "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
++	{ "at25df641",  0x1f4800, 64 * 1024, 128, SECT_4K, },
+ 
+ 	{ "at26f004",   0x1f0400, 64 * 1024, 8, SECT_4K, },
+ 	{ "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
+diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
+index e427c82..bf485ff 100644
+--- a/drivers/mtd/devices/mtdram.c
++++ b/drivers/mtd/devices/mtdram.c
+@@ -17,6 +17,7 @@
+ #include <linux/init.h>
+ #include <linux/mtd/compatmac.h>
+ #include <linux/mtd/mtd.h>
++#include <linux/mtd/mtdram.h>
+ 
+ static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
+ static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
+diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
+index 180298b..5f96018 100644
+--- a/drivers/mtd/devices/phram.c
++++ b/drivers/mtd/devices/phram.c
+@@ -282,7 +282,7 @@ static int phram_setup(const char *val, struct kernel_param *kp)
+ }
+ 
+ module_param_call(phram, phram_setup, NULL, NULL, 000);
+-MODULE_PARM_DESC(phram,"Memory region to map. \"map=<name>,<start>,<length>\"");
++MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\"");
+ 
+ 
+ static int __init init_phram(void)
+diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
+index c815d0f..4a79b18 100644
+--- a/drivers/mtd/ftl.c
++++ b/drivers/mtd/ftl.c
+@@ -136,8 +136,6 @@ typedef struct partition_t {
+ #endif
+ } partition_t;
+ 
+-void ftl_freepart(partition_t *part);
+-
+ /* Partition state flags */
+ #define FTL_FORMATTED	0x01
+ 
+@@ -1014,7 +1012,7 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev,
+ 
+ /*====================================================================*/
+ 
+-void ftl_freepart(partition_t *part)
++static void ftl_freepart(partition_t *part)
+ {
+ 	vfree(part->VirtualBlockMap);
+ 	part->VirtualBlockMap = NULL;
+@@ -1069,7 +1067,7 @@ static void ftl_remove_dev(struct mtd_blktrans_dev *dev)
+ 	kfree(dev);
+ }
+ 
+-struct mtd_blktrans_ops ftl_tr = {
++static struct mtd_blktrans_ops ftl_tr = {
+ 	.name		= "ftl",
+ 	.major		= FTL_MAJOR,
+ 	.part_bits	= PART_BITS,
+diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
+index b8917be..c551d2f 100644
+--- a/drivers/mtd/inftlmount.c
++++ b/drivers/mtd/inftlmount.c
+@@ -41,11 +41,6 @@
+ 
+ char inftlmountrev[]="$Revision: 1.18 $";
+ 
+-extern int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+-			  size_t *retlen, uint8_t *buf);
+-extern int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+-			   size_t *retlen, uint8_t *buf);
+-
+ /*
+  * find_boot_record: Find the INFTL Media Header and its Spare copy which
+  *	contains the various device information of the INFTL partition and
+diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
+index 12c2536..1bd69aa 100644
+--- a/drivers/mtd/maps/Kconfig
++++ b/drivers/mtd/maps/Kconfig
+@@ -21,6 +21,9 @@ config MTD_PHYSMAP
+ 	  particular board as well as the bus width, either statically
+ 	  with config options or at run-time.
+ 
++	  To compile this driver as a module, choose M here: the
++	  module will be called physmap.
++
+ config MTD_PHYSMAP_START
+ 	hex "Physical start address of flash mapping"
+ 	depends on MTD_PHYSMAP
+diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
+index fc3b267..1f49206 100644
+--- a/drivers/mtd/maps/bast-flash.c
++++ b/drivers/mtd/maps/bast-flash.c
+@@ -137,7 +137,7 @@ static int bast_flash_probe(struct platform_device *pdev)
+ 	if (info->map.size > AREA_MAXSIZE)
+ 		info->map.size = AREA_MAXSIZE;
+ 
+-	pr_debug("%s: area %08lx, size %ld\n", __FUNCTION__,
++	pr_debug("%s: area %08lx, size %ld\n", __func__,
+ 		 info->map.phys, info->map.size);
+ 
+ 	info->area = request_mem_region(res->start, info->map.size,
+@@ -149,7 +149,7 @@ static int bast_flash_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	info->map.virt = ioremap(res->start, info->map.size);
+-	pr_debug("%s: virt at %08x\n", __FUNCTION__, (int)info->map.virt);
++	pr_debug("%s: virt at %08x\n", __func__, (int)info->map.virt);
+ 
+ 	if (info->map.virt == 0) {
+ 		printk(KERN_ERR PFX "failed to ioremap() region\n");
+@@ -223,3 +223,4 @@ module_exit(bast_flash_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Ben Dooks <ben at simtec.co.uk>");
+ MODULE_DESCRIPTION("BAST MTD Map driver");
++MODULE_ALIAS("platform:bast-nor");
+diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
+index 688ef49..59d8fb4 100644
+--- a/drivers/mtd/maps/ck804xrom.c
++++ b/drivers/mtd/maps/ck804xrom.c
+@@ -28,6 +28,9 @@
+ 
+ #define ROM_PROBE_STEP_SIZE (64*1024)
+ 
++#define DEV_CK804 1
++#define DEV_MCP55 2
++
+ struct ck804xrom_window {
+ 	void __iomem *virt;
+ 	unsigned long phys;
+@@ -45,8 +48,9 @@ struct ck804xrom_map_info {
+ 	char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
+ };
+ 
+-
+-/* The 2 bits controlling the window size are often set to allow reading
++/*
++ * The following applies to ck804 only:
++ * The 2 bits controlling the window size are often set to allow reading
+  * the BIOS, but too small to allow writing, since the lock registers are
+  * 4MiB lower in the address space than the data.
+  *
+@@ -58,10 +62,17 @@ struct ck804xrom_map_info {
+  * If only the 7 Bit is set, it is a 4MiB window.  Otherwise, a
+  * 64KiB window.
+  *
++ * The following applies to mcp55 only:
++ * The 15 bits controlling the window size are distributed as follows: 
++ * byte @0x88: bit 0..7
++ * byte @0x8c: bit 8..15
++ * word @0x90: bit 16..30
++ * If all bits are enabled, we have a 16? MiB window
++ * Please set win_size_bits to 0x7fffffff if you actually want to do something
+  */
+ static uint win_size_bits = 0;
+ module_param(win_size_bits, uint, 0);
+-MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS.");
++MODULE_PARM_DESC(win_size_bits, "ROM window size bits override, normally set by BIOS.");
+ 
+ static struct ck804xrom_window ck804xrom_window = {
+ 	.maps = LIST_HEAD_INIT(ck804xrom_window.maps),
+@@ -102,10 +113,11 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window)
+ 
+ 
+ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
+-	const struct pci_device_id *ent)
++					 const struct pci_device_id *ent)
+ {
+ 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+ 	u8 byte;
++	u16 word;
+ 	struct ck804xrom_window *window = &ck804xrom_window;
+ 	struct ck804xrom_map_info *map = NULL;
+ 	unsigned long map_top;
+@@ -113,26 +125,42 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
+ 	/* Remember the pci dev I find the window in */
+ 	window->pdev = pci_dev_get(pdev);
+ 
+-	/* Enable the selected rom window.  This is often incorrectly
+-	 * set up by the BIOS, and the 4MiB offset for the lock registers
+-	 * requires the full 5MiB of window space.
+-	 *
+-	 * This 'write, then read' approach leaves the bits for
+-	 * other uses of the hardware info.
+-	 */
+-        pci_read_config_byte(pdev, 0x88, &byte);
+-        pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
+-
+-
+-	/* Assume the rom window is properly setup, and find it's size */
+-	pci_read_config_byte(pdev, 0x88, &byte);
+-
+-	if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
+-		window->phys = 0xffb00000; /* 5MiB */
+-	else if ((byte & (1<<7)) == (1<<7))
+-		window->phys = 0xffc00000; /* 4MiB */
+-	else
+-		window->phys = 0xffff0000; /* 64KiB */
++	switch (ent->driver_data) {
++	case DEV_CK804:
++		/* Enable the selected rom window.  This is often incorrectly
++		 * set up by the BIOS, and the 4MiB offset for the lock registers
++		 * requires the full 5MiB of window space.
++		 *
++		 * This 'write, then read' approach leaves the bits for
++		 * other uses of the hardware info.
++		 */
++		pci_read_config_byte(pdev, 0x88, &byte);
++		pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
++
++		/* Assume the rom window is properly setup, and find it's size */
++		pci_read_config_byte(pdev, 0x88, &byte);
++
++		if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
++			window->phys = 0xffb00000; /* 5MiB */
++		else if ((byte & (1<<7)) == (1<<7))
++			window->phys = 0xffc00000; /* 4MiB */
++		else
++			window->phys = 0xffff0000; /* 64KiB */
++		break;
++
++	case DEV_MCP55:
++		pci_read_config_byte(pdev, 0x88, &byte);
++		pci_write_config_byte(pdev, 0x88, byte | (win_size_bits & 0xff));
++
++		pci_read_config_byte(pdev, 0x8c, &byte);
++		pci_write_config_byte(pdev, 0x8c, byte | ((win_size_bits & 0xff00) >> 8));
++
++		pci_read_config_word(pdev, 0x90, &word);
++		pci_write_config_word(pdev, 0x90, word | ((win_size_bits & 0x7fff0000) >> 16));
++
++		window->phys = 0xff000000; /* 16MiB, hardcoded for now */
++		break;
++	}
+ 
+ 	window->size = 0xffffffffUL - window->phys + 1UL;
+ 
+@@ -303,8 +331,15 @@ static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
+ }
+ 
+ static struct pci_device_id ck804xrom_pci_tbl[] = {
+-	{ PCI_VENDOR_ID_NVIDIA, 0x0051,
+-        PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */
++	{ PCI_VENDOR_ID_NVIDIA, 0x0051, PCI_ANY_ID, PCI_ANY_ID, DEV_CK804 },
++	{ PCI_VENDOR_ID_NVIDIA, 0x0360, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++	{ PCI_VENDOR_ID_NVIDIA, 0x0361, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++	{ PCI_VENDOR_ID_NVIDIA, 0x0362, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++	{ PCI_VENDOR_ID_NVIDIA, 0x0363, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++	{ PCI_VENDOR_ID_NVIDIA, 0x0364, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++	{ PCI_VENDOR_ID_NVIDIA, 0x0365, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++	{ PCI_VENDOR_ID_NVIDIA, 0x0366, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++	{ PCI_VENDOR_ID_NVIDIA, 0x0367, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+ 	{ 0, }
+ };
+ 
+@@ -332,7 +367,7 @@ static int __init init_ck804xrom(void)
+ 			break;
+ 	}
+ 	if (pdev) {
+-		retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]);
++		retVal = ck804xrom_init_one(pdev, id);
+ 		pci_dev_put(pdev);
+ 		return retVal;
+ 	}
+diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
+index 6946d80..325c888 100644
+--- a/drivers/mtd/maps/integrator-flash.c
++++ b/drivers/mtd/maps/integrator-flash.c
+@@ -190,6 +190,7 @@ static struct platform_driver armflash_driver = {
+ 	.remove		= armflash_remove,
+ 	.driver		= {
+ 		.name	= "armflash",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -209,3 +210,4 @@ module_exit(armflash_exit);
+ MODULE_AUTHOR("ARM Ltd");
+ MODULE_DESCRIPTION("ARM Integrator CFI map driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:armflash");
+diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
+index c26488a..c8396b8 100644
+--- a/drivers/mtd/maps/ixp2000.c
++++ b/drivers/mtd/maps/ixp2000.c
+@@ -253,6 +253,7 @@ static struct platform_driver ixp2000_flash_driver = {
+ 	.remove		= ixp2000_flash_remove,
+ 	.driver		= {
+ 		.name	= "IXP2000-Flash",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -270,4 +271,4 @@ module_init(ixp2000_flash_init);
+ module_exit(ixp2000_flash_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Deepak Saxena <dsaxena at plexity.net>");
+-
++MODULE_ALIAS("platform:IXP2000-Flash");
+diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
+index 7a828e3..01f19a4 100644
+--- a/drivers/mtd/maps/ixp4xx.c
++++ b/drivers/mtd/maps/ixp4xx.c
+@@ -275,6 +275,7 @@ static struct platform_driver ixp4xx_flash_driver = {
+ 	.remove		= ixp4xx_flash_remove,
+ 	.driver		= {
+ 		.name	= "IXP4XX-Flash",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -295,3 +296,4 @@ module_exit(ixp4xx_flash_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems");
+ MODULE_AUTHOR("Deepak Saxena");
++MODULE_ALIAS("platform:IXP4XX-Flash");
+diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
+index e8d9ae5..240b0e2 100644
+--- a/drivers/mtd/maps/omap_nor.c
++++ b/drivers/mtd/maps/omap_nor.c
+@@ -70,7 +70,7 @@ static void omap_set_vpp(struct map_info *map, int enable)
+ 	}
+ }
+ 
+-static int __devinit omapflash_probe(struct platform_device *pdev)
++static int __init omapflash_probe(struct platform_device *pdev)
+ {
+ 	int err;
+ 	struct omapflash_info *info;
+@@ -130,7 +130,7 @@ out_free_info:
+ 	return err;
+ }
+ 
+-static int __devexit omapflash_remove(struct platform_device *pdev)
++static int __exit omapflash_remove(struct platform_device *pdev)
+ {
+ 	struct omapflash_info *info = platform_get_drvdata(pdev);
+ 
+@@ -152,16 +152,16 @@ static int __devexit omapflash_remove(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver omapflash_driver = {
+-	.probe	= omapflash_probe,
+-	.remove	= __devexit_p(omapflash_remove),
++	.remove	= __exit_p(omapflash_remove),
+ 	.driver = {
+ 		.name	= "omapflash",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+ static int __init omapflash_init(void)
+ {
+-	return platform_driver_register(&omapflash_driver);
++	return platform_driver_probe(&omapflash_driver, omapflash_probe);
+ }
+ 
+ static void __exit omapflash_exit(void)
+@@ -174,4 +174,4 @@ module_exit(omapflash_exit);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("MTD NOR map driver for TI OMAP boards");
+-
++MODULE_ALIAS("platform:omapflash");
+diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
+index eaeb56a..1912d96 100644
+--- a/drivers/mtd/maps/pcmciamtd.c
++++ b/drivers/mtd/maps/pcmciamtd.c
+@@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
+ #undef DEBUG
+ #define DEBUG(n, format, arg...) \
+ 	if (n <= debug) {	 \
+-		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
++		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
+ 	}
+ 
+ #else
+diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
+index bc4649a..183255f 100644
+--- a/drivers/mtd/maps/physmap.c
++++ b/drivers/mtd/maps/physmap.c
+@@ -242,6 +242,7 @@ static struct platform_driver physmap_flash_driver = {
+ 	.shutdown	= physmap_flash_shutdown,
+ 	.driver		= {
+ 		.name	= "physmap-flash",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -319,3 +320,10 @@ module_exit(physmap_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("David Woodhouse <dwmw2 at infradead.org>");
+ MODULE_DESCRIPTION("Generic configurable MTD map driver");
++
++/* legacy platform drivers can't hotplug or coldplg */
++#ifndef PHYSMAP_COMPAT
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:physmap-flash");
++#endif
++
+diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
+index 894c0b2..f0b10ca 100644
+--- a/drivers/mtd/maps/plat-ram.c
++++ b/drivers/mtd/maps/plat-ram.c
+@@ -47,6 +47,7 @@ struct platram_info {
+ 	struct mtd_info		*mtd;
+ 	struct map_info		 map;
+ 	struct mtd_partition	*partitions;
++	bool			free_partitions;
+ 	struct resource		*area;
+ 	struct platdata_mtd_ram	*pdata;
+ };
+@@ -98,7 +99,8 @@ static int platram_remove(struct platform_device *pdev)
+ #ifdef CONFIG_MTD_PARTITIONS
+ 		if (info->partitions) {
+ 			del_mtd_partitions(info->mtd);
+-			kfree(info->partitions);
++			if (info->free_partitions)
++				kfree(info->partitions);
+ 		}
+ #endif
+ 		del_mtd_device(info->mtd);
+@@ -176,7 +178,8 @@ static int platram_probe(struct platform_device *pdev)
+ 
+ 	info->map.phys = res->start;
+ 	info->map.size = (res->end - res->start) + 1;
+-	info->map.name = pdata->mapname != NULL ? pdata->mapname : (char *)pdev->name;
++	info->map.name = pdata->mapname != NULL ?
++			(char *)pdata->mapname : (char *)pdev->name;
+ 	info->map.bankwidth = pdata->bankwidth;
+ 
+ 	/* register our usage of the memory area */
+@@ -203,9 +206,19 @@ static int platram_probe(struct platform_device *pdev)
+ 
+ 	dev_dbg(&pdev->dev, "initialised map, probing for mtd\n");
+ 
+-	/* probe for the right mtd map driver */
++	/* probe for the right mtd map driver
++	 * supplied by the platform_data struct */
++
++	if (pdata->map_probes != 0) {
++		const char **map_probes = pdata->map_probes;
++
++		for ( ; !info->mtd && *map_probes; map_probes++)
++			info->mtd = do_map_probe(*map_probes , &info->map);
++	}
++	/* fallback to map_ram */
++	else
++		info->mtd = do_map_probe("map_ram", &info->map);
+ 
+-	info->mtd = do_map_probe("map_ram" , &info->map);
+ 	if (info->mtd == NULL) {
+ 		dev_err(&pdev->dev, "failed to probe for map_ram\n");
+ 		err = -ENOMEM;
+@@ -220,19 +233,21 @@ static int platram_probe(struct platform_device *pdev)
+ 	 * to add this device whole */
+ 
+ #ifdef CONFIG_MTD_PARTITIONS
+-	if (pdata->nr_partitions > 0) {
+-		const char **probes = { NULL };
+-
+-		if (pdata->probes)
+-			probes = (const char **)pdata->probes;
+-
+-		err = parse_mtd_partitions(info->mtd, probes,
++	if (!pdata->nr_partitions) {
++		/* try to probe using the supplied probe type */
++		if (pdata->probes) {
++			err = parse_mtd_partitions(info->mtd, pdata->probes,
+ 					   &info->partitions, 0);
+-		if (err > 0) {
+-			err = add_mtd_partitions(info->mtd, info->partitions,
+-						 err);
++			info->free_partitions = 1;
++			if (err > 0)
++				err = add_mtd_partitions(info->mtd,
++					info->partitions, err);
+ 		}
+ 	}
++	/* use the static mapping */
++	else
++		err = add_mtd_partitions(info->mtd, pdata->partitions,
++				pdata->nr_partitions);
+ #endif /* CONFIG_MTD_PARTITIONS */
+ 
+ 	if (add_mtd_device(info->mtd)) {
+@@ -240,7 +255,9 @@ static int platram_probe(struct platform_device *pdev)
+ 		err = -ENOMEM;
+ 	}
+ 
+-	dev_info(&pdev->dev, "registered mtd device\n");
++	if (!err)
++		dev_info(&pdev->dev, "registered mtd device\n");
++
+ 	return err;
+ 
+  exit_free:
+@@ -251,6 +268,9 @@ static int platram_probe(struct platform_device *pdev)
+ 
+ /* device driver info */
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:mtd-ram");
++
+ static struct platform_driver platram_driver = {
+ 	.probe		= platram_probe,
+ 	.remove		= platram_remove,
+diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c
+index 02bde8c..f43ba28 100644
+--- a/drivers/mtd/maps/pmcmsp-flash.c
++++ b/drivers/mtd/maps/pmcmsp-flash.c
+@@ -46,7 +46,7 @@ static struct mtd_partition **msp_parts;
+ static struct map_info *msp_maps;
+ static int fcnt;
+ 
+-#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n",__FUNCTION__,__LINE__)
++#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n", __func__, __LINE__)
+ 
+ int __init init_msp_flash(void)
+ {
+diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
+index f904e6b..c7d5a52 100644
+--- a/drivers/mtd/maps/sa1100-flash.c
++++ b/drivers/mtd/maps/sa1100-flash.c
+@@ -456,6 +456,7 @@ static struct platform_driver sa1100_mtd_driver = {
+ 	.shutdown	= sa1100_mtd_shutdown,
+ 	.driver		= {
+ 		.name	= "flash",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -475,3 +476,4 @@ module_exit(sa1100_mtd_exit);
+ MODULE_AUTHOR("Nicolas Pitre");
+ MODULE_DESCRIPTION("SA1100 CFI map driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:flash");
+diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c
+index 12fe53c..917dc77 100644
+--- a/drivers/mtd/maps/sharpsl-flash.c
++++ b/drivers/mtd/maps/sharpsl-flash.c
+@@ -92,7 +92,7 @@ int __init init_sharpsl(void)
+ 	parts = sharpsl_partitions;
+ 	nb_parts = ARRAY_SIZE(sharpsl_partitions);
+ 
+-	printk(KERN_NOTICE "Using %s partision definition\n", part_type);
++	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+ 	add_mtd_partitions(mymtd, parts, nb_parts);
+ 
+ 	return 0;
+diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
+index 37e4ded..5217340 100644
+--- a/drivers/mtd/maps/tqm8xxl.c
++++ b/drivers/mtd/maps/tqm8xxl.c
+@@ -124,7 +124,7 @@ int __init init_tqm_mtd(void)
+ 	//request maximum flash size address space
+ 	start_scan_addr = ioremap(flash_addr, flash_size);
+ 	if (!start_scan_addr) {
+-		printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr);
++		printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __func__, flash_addr);
+ 		return -EIO;
+ 	}
+ 
+@@ -132,7 +132,7 @@ int __init init_tqm_mtd(void)
+ 		if(mtd_size >= flash_size)
+ 			break;
+ 
+-		printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx);
++		printk(KERN_INFO "%s: chip probing count %d\n", __func__, idx);
+ 
+ 		map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
+ 		if(map_banks[idx] == NULL) {
+@@ -178,7 +178,7 @@ int __init init_tqm_mtd(void)
+ 			mtd_size += mtd_banks[idx]->size;
+ 			num_banks++;
+ 
+-			printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks,
++			printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __func__, num_banks,
+ 			mtd_banks[idx]->name, mtd_banks[idx]->size);
+ 		}
+ 	}
+diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
+index d3cf050..5a680e1 100644
+--- a/drivers/mtd/mtdoops.c
++++ b/drivers/mtd/mtdoops.c
+@@ -35,7 +35,7 @@
+ 
+ #define OOPS_PAGE_SIZE 4096
+ 
+-struct mtdoops_context {
++static struct mtdoops_context {
+ 	int mtd_index;
+ 	struct work_struct work_erase;
+ 	struct work_struct work_write;
+diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
+index 4a3c675..5076faf 100644
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -278,6 +278,54 @@ config MTD_NAND_AT91
+ 	help
+ 	  Enables support for NAND Flash / Smart Media Card interface
+ 	  on Atmel AT91 processors.
++choice
++	prompt "ECC management for NAND Flash / SmartMedia on AT91"
++	depends on MTD_NAND_AT91
++
++config MTD_NAND_AT91_ECC_HW
++	bool "Hardware ECC"
++	depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260
++	help
++	  Uses hardware ECC provided by the at91sam9260/at91sam9263 chip
++	  instead of software ECC.
++	  The hardware ECC controller is capable of single bit error
++	  correction and 2-bit random detection per page.
++
++	  NB : hardware and software ECC schemes are incompatible.
++	  If you switch from one to another, you'll have to erase your
++	  mtd partition.
++
++	  If unsure, say Y
++
++config MTD_NAND_AT91_ECC_SOFT
++	bool "Software ECC"
++	help
++	  Uses software ECC.
++
++	  NB : hardware and software ECC schemes are incompatible.
++	  If you switch from one to another, you'll have to erase your
++	  mtd partition.
++
++config MTD_NAND_AT91_ECC_NONE
++	bool "No ECC (testing only, DANGEROUS)"
++	depends on DEBUG_KERNEL
++	help
++	  No ECC will be used.
++	  It's not a good idea and it should be reserved for testing
++	  purpose only.
++
++	  If unsure, say N
++
++	  endchoice
++
++endchoice
++
++config MTD_NAND_PXA3xx
++	bool "Support for NAND flash devices on PXA3xx"
++	depends on MTD_NAND && PXA3xx
++	help
++	  This enables the driver for the NAND flash device found on
++	  PXA3xx processors
+ 
+ config MTD_NAND_CM_X270
+ 	tristate "Support for NAND Flash on CM-X270 modules"
+@@ -314,7 +362,7 @@ config MTD_ALAUDA
+ 
+ config MTD_NAND_ORION
+ 	tristate "NAND Flash support for Marvell Orion SoC"
+-	depends on ARCH_ORION && MTD_NAND
++	depends on PLAT_ORION && MTD_NAND
+ 	help
+ 	  This enables the NAND flash controller on Orion machines.
+ 
+@@ -330,4 +378,12 @@ config MTD_NAND_FSL_ELBC
+ 	  Enabling this option will enable you to use this to control
+ 	  external NAND devices.
+ 
++config MTD_NAND_FSL_UPM
++	tristate "Support for NAND on Freescale UPM"
++	depends on MTD_NAND && OF_GPIO && (PPC_83xx || PPC_85xx)
++	select FSL_LBC
++	help
++	  Enables support for NAND Flash chips wired onto Freescale PowerPC
++	  processor localbus with User-Programmable Machine support.
++
+ endif # MTD_NAND
+diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
+index 80d575e..a6e74a4 100644
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -27,10 +27,12 @@ obj-$(CONFIG_MTD_NAND_NDFC)		+= ndfc.o
+ obj-$(CONFIG_MTD_NAND_AT91)		+= at91_nand.o
+ obj-$(CONFIG_MTD_NAND_CM_X270)		+= cmx270_nand.o
+ obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)	+= excite_nandflash.o
++obj-$(CONFIG_MTD_NAND_PXA3xx)		+= pxa3xx_nand.o
+ obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
+ obj-$(CONFIG_MTD_ALAUDA)		+= alauda.o
+ obj-$(CONFIG_MTD_NAND_PASEMI)		+= pasemi_nand.o
+ obj-$(CONFIG_MTD_NAND_ORION)		+= orion_nand.o
+ obj-$(CONFIG_MTD_NAND_FSL_ELBC)		+= fsl_elbc_nand.o
++obj-$(CONFIG_MTD_NAND_FSL_UPM)		+= fsl_upm.o
+ 
+ nand-objs := nand_base.o nand_bbt.o
+diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c
+index c9fb2ac..414ceae 100644
+--- a/drivers/mtd/nand/at91_nand.c
++++ b/drivers/mtd/nand/at91_nand.c
+@@ -9,6 +9,15 @@
+  *  Derived from drivers/mtd/spia.c
+  *	 Copyright (C) 2000 Steven J. Hill (sjhill at cotw.com)
+  *
++ *
++ *  Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
++ *     Richard Genoud (richard.genoud at gmail.com), Adeneo Copyright (C) 2007
++ *
++ *     Derived from Das U-Boot source code
++ *     		(u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
++ *     (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
++ *
++ *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+@@ -29,11 +38,59 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+ 
++#ifdef CONFIG_MTD_NAND_AT91_ECC_HW
++#define hard_ecc	1
++#else
++#define hard_ecc	0
++#endif
++
++#ifdef CONFIG_MTD_NAND_AT91_ECC_NONE
++#define no_ecc		1
++#else
++#define no_ecc		0
++#endif
++
++/* Register access macros */
++#define ecc_readl(add, reg)				\
++	__raw_readl(add + AT91_ECC_##reg)
++#define ecc_writel(add, reg, value)			\
++	__raw_writel((value), add + AT91_ECC_##reg)
++
++#include <asm/arch/at91_ecc.h> /* AT91SAM9260/3 ECC registers */
++
++/* oob layout for large page size
++ * bad block info is on bytes 0 and 1
++ * the bytes have to be consecutives to avoid
++ * several NAND_CMD_RNDOUT during read
++ */
++static struct nand_ecclayout at91_oobinfo_large = {
++	.eccbytes = 4,
++	.eccpos = {60, 61, 62, 63},
++	.oobfree = {
++		{2, 58}
++	},
++};
++
++/* oob layout for small page size
++ * bad block info is on bytes 4 and 5
++ * the bytes have to be consecutives to avoid
++ * several NAND_CMD_RNDOUT during read
++ */
++static struct nand_ecclayout at91_oobinfo_small = {
++	.eccbytes = 4,
++	.eccpos = {0, 1, 2, 3},
++	.oobfree = {
++		{6, 10}
++	},
++};
++
+ struct at91_nand_host {
+ 	struct nand_chip	nand_chip;
+ 	struct mtd_info		mtd;
+ 	void __iomem		*io_base;
+ 	struct at91_nand_data	*board;
++	struct device		*dev;
++	void __iomem		*ecc;
+ };
+ 
+ /*
+@@ -44,6 +101,12 @@ static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+ 	struct nand_chip *nand_chip = mtd->priv;
+ 	struct at91_nand_host *host = nand_chip->priv;
+ 
++	if (host->board->enable_pin && (ctrl & NAND_CTRL_CHANGE)) {
++		if (ctrl & NAND_NCE)
++			at91_set_gpio_value(host->board->enable_pin, 0);
++		else
++			at91_set_gpio_value(host->board->enable_pin, 1);
++	}
+ 	if (cmd == NAND_CMD_NONE)
+ 		return;
+ 
+@@ -82,8 +145,217 @@ static void at91_nand_disable(struct at91_nand_host *host)
+ 		at91_set_gpio_value(host->board->enable_pin, 1);
+ }
+ 
++/*
++ * write oob for small pages
++ */
++static int at91_nand_write_oob_512(struct mtd_info *mtd,
++		struct nand_chip *chip, int page)
++{
++	int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
++	int eccsize = chip->ecc.size, length = mtd->oobsize;
++	int len, pos, status = 0;
++	const uint8_t *bufpoi = chip->oob_poi;
++
++	pos = eccsize + chunk;
++
++	chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
++	len = min_t(int, length, chunk);
++	chip->write_buf(mtd, bufpoi, len);
++	bufpoi += len;
++	length -= len;
++	if (length > 0)
++		chip->write_buf(mtd, bufpoi, length);
++
++	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
++	status = chip->waitfunc(mtd, chip);
++
++	return status & NAND_STATUS_FAIL ? -EIO : 0;
++
++}
++
++/*
++ * read oob for small pages
++ */
++static int at91_nand_read_oob_512(struct mtd_info *mtd,
++		struct nand_chip *chip,	int page, int sndcmd)
++{
++	if (sndcmd) {
++		chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
++		sndcmd = 0;
++	}
++	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
++	return sndcmd;
++}
++
++/*
++ * Calculate HW ECC
++ *
++ * function called after a write
++ *
++ * mtd:        MTD block structure
++ * dat:        raw data (unused)
++ * ecc_code:   buffer for ECC
++ */
++static int at91_nand_calculate(struct mtd_info *mtd,
++		const u_char *dat, unsigned char *ecc_code)
++{
++	struct nand_chip *nand_chip = mtd->priv;
++	struct at91_nand_host *host = nand_chip->priv;
++	uint32_t *eccpos = nand_chip->ecc.layout->eccpos;
++	unsigned int ecc_value;
++
++	/* get the first 2 ECC bytes */
++	ecc_value = ecc_readl(host->ecc, PR);
++
++	ecc_code[eccpos[0]] = ecc_value & 0xFF;
++	ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;
++
++	/* get the last 2 ECC bytes */
++	ecc_value = ecc_readl(host->ecc, NPR) & AT91_ECC_NPARITY;
++
++	ecc_code[eccpos[2]] = ecc_value & 0xFF;
++	ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;
++
++	return 0;
++}
++
++/*
++ * HW ECC read page function
++ *
++ * mtd:        mtd info structure
++ * chip:       nand chip info structure
++ * buf:        buffer to store read data
++ */
++static int at91_nand_read_page(struct mtd_info *mtd,
++		struct nand_chip *chip, uint8_t *buf)
++{
++	int eccsize = chip->ecc.size;
++	int eccbytes = chip->ecc.bytes;
++	uint32_t *eccpos = chip->ecc.layout->eccpos;
++	uint8_t *p = buf;
++	uint8_t *oob = chip->oob_poi;
++	uint8_t *ecc_pos;
++	int stat;
++
++	/* read the page */
++	chip->read_buf(mtd, p, eccsize);
++
++	/* move to ECC position if needed */
++	if (eccpos[0] != 0) {
++		/* This only works on large pages
++		 * because the ECC controller waits for
++		 * NAND_CMD_RNDOUTSTART after the
++		 * NAND_CMD_RNDOUT.
++		 * anyway, for small pages, the eccpos[0] == 0
++		 */
++		chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
++				mtd->writesize + eccpos[0], -1);
++	}
++
++	/* the ECC controller needs to read the ECC just after the data */
++	ecc_pos = oob + eccpos[0];
++	chip->read_buf(mtd, ecc_pos, eccbytes);
++
++	/* check if there's an error */
++	stat = chip->ecc.correct(mtd, p, oob, NULL);
++
++	if (stat < 0)
++		mtd->ecc_stats.failed++;
++	else
++		mtd->ecc_stats.corrected += stat;
++
++	/* get back to oob start (end of page) */
++	chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
++
++	/* read the oob */
++	chip->read_buf(mtd, oob, mtd->oobsize);
++
++	return 0;
++}
++
++/*
++ * HW ECC Correction
++ *
++ * function called after a read
++ *
++ * mtd:        MTD block structure
++ * dat:        raw data read from the chip
++ * read_ecc:   ECC from the chip (unused)
++ * isnull:     unused
++ *
++ * Detect and correct a 1 bit error for a page
++ */
++static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
++		u_char *read_ecc, u_char *isnull)
++{
++	struct nand_chip *nand_chip = mtd->priv;
++	struct at91_nand_host *host = nand_chip->priv;
++	unsigned int ecc_status;
++	unsigned int ecc_word, ecc_bit;
++
++	/* get the status from the Status Register */
++	ecc_status = ecc_readl(host->ecc, SR);
++
++	/* if there's no error */
++	if (likely(!(ecc_status & AT91_ECC_RECERR)))
++		return 0;
++
++	/* get error bit offset (4 bits) */
++	ecc_bit = ecc_readl(host->ecc, PR) & AT91_ECC_BITADDR;
++	/* get word address (12 bits) */
++	ecc_word = ecc_readl(host->ecc, PR) & AT91_ECC_WORDADDR;
++	ecc_word >>= 4;
++
++	/* if there are multiple errors */
++	if (ecc_status & AT91_ECC_MULERR) {
++		/* check if it is a freshly erased block
++		 * (filled with 0xff) */
++		if ((ecc_bit == AT91_ECC_BITADDR)
++				&& (ecc_word == (AT91_ECC_WORDADDR >> 4))) {
++			/* the block has just been erased, return OK */
++			return 0;
++		}
++		/* it doesn't seems to be a freshly
++		 * erased block.
++		 * We can't correct so many errors */
++		dev_dbg(host->dev, "at91_nand : multiple errors detected."
++				" Unable to correct.\n");
++		return -EIO;
++	}
++
++	/* if there's a single bit error : we can correct it */
++	if (ecc_status & AT91_ECC_ECCERR) {
++		/* there's nothing much to do here.
++		 * the bit error is on the ECC itself.
++		 */
++		dev_dbg(host->dev, "at91_nand : one bit error on ECC code."
++				" Nothing to correct\n");
++		return 0;
++	}
++
++	dev_dbg(host->dev, "at91_nand : one bit error on data."
++			" (word offset in the page :"
++			" 0x%x bit offset : 0x%x)\n",
++			ecc_word, ecc_bit);
++	/* correct the error */
++	if (nand_chip->options & NAND_BUSWIDTH_16) {
++		/* 16 bits words */
++		((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit);
++	} else {
++		/* 8 bits words */
++		dat[ecc_word] ^= (1 << ecc_bit);
++	}
++	dev_dbg(host->dev, "at91_nand : error corrected\n");
++	return 1;
++}
++
++/*
++ * Enable HW ECC : unsused
++ */
++static void at91_nand_hwctl(struct mtd_info *mtd, int mode) { ; }
++
+ #ifdef CONFIG_MTD_PARTITIONS
+-const char *part_probes[] = { "cmdlinepart", NULL };
++static const char *part_probes[] = { "cmdlinepart", NULL };
+ #endif
+ 
+ /*
+@@ -94,6 +366,8 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ 	struct at91_nand_host *host;
+ 	struct mtd_info *mtd;
+ 	struct nand_chip *nand_chip;
++	struct resource *regs;
++	struct resource *mem;
+ 	int res;
+ 
+ #ifdef CONFIG_MTD_PARTITIONS
+@@ -108,8 +382,13 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ 		return -ENOMEM;
+ 	}
+ 
+-	host->io_base = ioremap(pdev->resource[0].start,
+-				pdev->resource[0].end - pdev->resource[0].start + 1);
++	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!mem) {
++		printk(KERN_ERR "at91_nand: can't get I/O resource mem\n");
++		return -ENXIO;
++	}
++
++	host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
+ 	if (host->io_base == NULL) {
+ 		printk(KERN_ERR "at91_nand: ioremap failed\n");
+ 		kfree(host);
+@@ -119,6 +398,7 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ 	mtd = &host->mtd;
+ 	nand_chip = &host->nand_chip;
+ 	host->board = pdev->dev.platform_data;
++	host->dev = &pdev->dev;
+ 
+ 	nand_chip->priv = host;		/* link the private data structures */
+ 	mtd->priv = nand_chip;
+@@ -132,7 +412,32 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ 	if (host->board->rdy_pin)
+ 		nand_chip->dev_ready = at91_nand_device_ready;
+ 
++	regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++	if (!regs && hard_ecc) {
++		printk(KERN_ERR "at91_nand: can't get I/O resource "
++				"regs\nFalling back on software ECC\n");
++	}
++
+ 	nand_chip->ecc.mode = NAND_ECC_SOFT;	/* enable ECC */
++	if (no_ecc)
++		nand_chip->ecc.mode = NAND_ECC_NONE;
++	if (hard_ecc && regs) {
++		host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
++		if (host->ecc == NULL) {
++			printk(KERN_ERR "at91_nand: ioremap failed\n");
++			res = -EIO;
++			goto err_ecc_ioremap;
++		}
++		nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME;
++		nand_chip->ecc.calculate = at91_nand_calculate;
++		nand_chip->ecc.correct = at91_nand_correct;
++		nand_chip->ecc.hwctl = at91_nand_hwctl;
++		nand_chip->ecc.read_page = at91_nand_read_page;
++		nand_chip->ecc.bytes = 4;
++		nand_chip->ecc.prepad = 0;
++		nand_chip->ecc.postpad = 0;
++	}
++
+ 	nand_chip->chip_delay = 20;		/* 20us command delay time */
+ 
+ 	if (host->board->bus_width_16)		/* 16-bit bus width */
+@@ -149,8 +454,53 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ 		}
+ 	}
+ 
+-	/* Scan to find existance of the device */
+-	if (nand_scan(mtd, 1)) {
++	/* first scan to find the device and get the page size */
++	if (nand_scan_ident(mtd, 1)) {
++		res = -ENXIO;
++		goto out;
++	}
++
++	if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
++		/* ECC is calculated for the whole page (1 step) */
++		nand_chip->ecc.size = mtd->writesize;
++
++		/* set ECC page size and oob layout */
++		switch (mtd->writesize) {
++		case 512:
++			nand_chip->ecc.layout = &at91_oobinfo_small;
++			nand_chip->ecc.read_oob = at91_nand_read_oob_512;
++			nand_chip->ecc.write_oob = at91_nand_write_oob_512;
++			ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_528);
++			break;
++		case 1024:
++			nand_chip->ecc.layout = &at91_oobinfo_large;
++			ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_1056);
++			break;
++		case 2048:
++			nand_chip->ecc.layout = &at91_oobinfo_large;
++			ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_2112);
++			break;
++		case 4096:
++			nand_chip->ecc.layout = &at91_oobinfo_large;
++			ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_4224);
++			break;
++		default:
++			/* page size not handled by HW ECC */
++			/* switching back to soft ECC */
++			nand_chip->ecc.mode = NAND_ECC_SOFT;
++			nand_chip->ecc.calculate = NULL;
++			nand_chip->ecc.correct = NULL;
++			nand_chip->ecc.hwctl = NULL;
++			nand_chip->ecc.read_page = NULL;
++			nand_chip->ecc.postpad = 0;
++			nand_chip->ecc.prepad = 0;
++			nand_chip->ecc.bytes = 0;
++			break;
++		}
++	}
++
++	/* second phase scan */
++	if (nand_scan_tail(mtd)) {
+ 		res = -ENXIO;
+ 		goto out;
+ 	}
+@@ -179,9 +529,15 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ 	if (!res)
+ 		return res;
+ 
++#ifdef CONFIG_MTD_PARTITIONS
+ release:
++#endif
+ 	nand_release(mtd);
++
+ out:
++	iounmap(host->ecc);
++
++err_ecc_ioremap:
+ 	at91_nand_disable(host);
+ 	platform_set_drvdata(pdev, NULL);
+ 	iounmap(host->io_base);
+@@ -202,6 +558,7 @@ static int __devexit at91_nand_remove(struct platform_device *pdev)
+ 	at91_nand_disable(host);
+ 
+ 	iounmap(host->io_base);
++	iounmap(host->ecc);
+ 	kfree(host);
+ 
+ 	return 0;
+@@ -233,4 +590,5 @@ module_exit(at91_nand_exit);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Rick Bronson");
+-MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200");
++MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200 / AT91SAM9");
++MODULE_ALIAS("platform:at91_nand");
+diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
+index 747042a..e87a572 100644
+--- a/drivers/mtd/nand/bf5xx_nand.c
++++ b/drivers/mtd/nand/bf5xx_nand.c
+@@ -1,6 +1,6 @@
+ /* linux/drivers/mtd/nand/bf5xx_nand.c
+  *
+- * Copyright 2006-2007 Analog Devices Inc.
++ * Copyright 2006-2008 Analog Devices Inc.
+  *	http://blackfin.uclinux.org/
+  *	Bryan Wu <bryan.wu at analog.com>
+  *
+@@ -74,7 +74,7 @@ static int hardware_ecc = 1;
+ static int hardware_ecc;
+ #endif
+ 
+-static unsigned short bfin_nfc_pin_req[] =
++static const unsigned short bfin_nfc_pin_req[] =
+ 	{P_NAND_CE,
+ 	 P_NAND_RB,
+ 	 P_NAND_D0,
+@@ -581,12 +581,6 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
+ 	bfin_write_NFC_IRQSTAT(val);
+ 	SSYNC();
+ 
+-	if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
+-		printk(KERN_ERR DRV_NAME
+-		": Requesting Peripherals failed\n");
+-		return -EFAULT;
+-	}
+-
+ 	/* DMA initialization  */
+ 	if (bf5xx_nand_dma_init(info))
+ 		err = -ENXIO;
+@@ -654,6 +648,12 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
+ 
+ 	dev_dbg(&pdev->dev, "(%p)\n", pdev);
+ 
++	if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
++		printk(KERN_ERR DRV_NAME
++		": Requesting Peripherals failed\n");
++		return -EFAULT;
++	}
++
+ 	if (!plat) {
+ 		dev_err(&pdev->dev, "no platform specific information\n");
+ 		goto exit_error;
+@@ -803,3 +803,4 @@ module_exit(bf5xx_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR(DRV_AUTHOR);
+ MODULE_DESCRIPTION(DRV_DESC);
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
+index 8dab696..3370a80 100644
+--- a/drivers/mtd/nand/cs553x_nand.c
++++ b/drivers/mtd/nand/cs553x_nand.c
+@@ -279,7 +279,7 @@ static int is_geode(void)
+ 
+ 
+ #ifdef CONFIG_MTD_PARTITIONS
+-const char *part_probes[] = { "cmdlinepart", NULL };
++static const char *part_probes[] = { "cmdlinepart", NULL };
+ #endif
+ 
+ 
+diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
+index b025dfe..4b69aac 100644
+--- a/drivers/mtd/nand/fsl_elbc_nand.c
++++ b/drivers/mtd/nand/fsl_elbc_nand.c
+@@ -36,207 +36,12 @@
+ #include <linux/mtd/partitions.h>
+ 
+ #include <asm/io.h>
+-
++#include <asm/fsl_lbc.h>
+ 
+ #define MAX_BANKS 8
+ #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
+ #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
+ 
+-struct elbc_bank {
+-	__be32 br;             /**< Base Register  */
+-#define BR_BA           0xFFFF8000
+-#define BR_BA_SHIFT             15
+-#define BR_PS           0x00001800
+-#define BR_PS_SHIFT             11
+-#define BR_PS_8         0x00000800  /* Port Size 8 bit */
+-#define BR_PS_16        0x00001000  /* Port Size 16 bit */
+-#define BR_PS_32        0x00001800  /* Port Size 32 bit */
+-#define BR_DECC         0x00000600
+-#define BR_DECC_SHIFT            9
+-#define BR_DECC_OFF     0x00000000  /* HW ECC checking and generation off */
+-#define BR_DECC_CHK     0x00000200  /* HW ECC checking on, generation off */
+-#define BR_DECC_CHK_GEN 0x00000400  /* HW ECC checking and generation on */
+-#define BR_WP           0x00000100
+-#define BR_WP_SHIFT              8
+-#define BR_MSEL         0x000000E0
+-#define BR_MSEL_SHIFT            5
+-#define BR_MS_GPCM      0x00000000  /* GPCM */
+-#define BR_MS_FCM       0x00000020  /* FCM */
+-#define BR_MS_SDRAM     0x00000060  /* SDRAM */
+-#define BR_MS_UPMA      0x00000080  /* UPMA */
+-#define BR_MS_UPMB      0x000000A0  /* UPMB */
+-#define BR_MS_UPMC      0x000000C0  /* UPMC */
+-#define BR_V            0x00000001
+-#define BR_V_SHIFT               0
+-#define BR_RES          ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
+-
+-	__be32 or;             /**< Base Register  */
+-#define OR0 0x5004
+-#define OR1 0x500C
+-#define OR2 0x5014
+-#define OR3 0x501C
+-#define OR4 0x5024
+-#define OR5 0x502C
+-#define OR6 0x5034
+-#define OR7 0x503C
+-
+-#define OR_FCM_AM               0xFFFF8000
+-#define OR_FCM_AM_SHIFT                 15
+-#define OR_FCM_BCTLD            0x00001000
+-#define OR_FCM_BCTLD_SHIFT              12
+-#define OR_FCM_PGS              0x00000400
+-#define OR_FCM_PGS_SHIFT                10
+-#define OR_FCM_CSCT             0x00000200
+-#define OR_FCM_CSCT_SHIFT                9
+-#define OR_FCM_CST              0x00000100
+-#define OR_FCM_CST_SHIFT                 8
+-#define OR_FCM_CHT              0x00000080
+-#define OR_FCM_CHT_SHIFT                 7
+-#define OR_FCM_SCY              0x00000070
+-#define OR_FCM_SCY_SHIFT                 4
+-#define OR_FCM_SCY_1            0x00000010
+-#define OR_FCM_SCY_2            0x00000020
+-#define OR_FCM_SCY_3            0x00000030
+-#define OR_FCM_SCY_4            0x00000040
+-#define OR_FCM_SCY_5            0x00000050
+-#define OR_FCM_SCY_6            0x00000060
+-#define OR_FCM_SCY_7            0x00000070
+-#define OR_FCM_RST              0x00000008
+-#define OR_FCM_RST_SHIFT                 3
+-#define OR_FCM_TRLX             0x00000004
+-#define OR_FCM_TRLX_SHIFT                2
+-#define OR_FCM_EHTR             0x00000002
+-#define OR_FCM_EHTR_SHIFT                1
+-};
+-
+-struct elbc_regs {
+-	struct elbc_bank bank[8];
+-	u8 res0[0x28];
+-	__be32 mar;             /**< UPM Address Register */
+-	u8 res1[0x4];
+-	__be32 mamr;            /**< UPMA Mode Register */
+-	__be32 mbmr;            /**< UPMB Mode Register */
+-	__be32 mcmr;            /**< UPMC Mode Register */
+-	u8 res2[0x8];
+-	__be32 mrtpr;           /**< Memory Refresh Timer Prescaler Register */
+-	__be32 mdr;             /**< UPM Data Register */
+-	u8 res3[0x4];
+-	__be32 lsor;            /**< Special Operation Initiation Register */
+-	__be32 lsdmr;           /**< SDRAM Mode Register */
+-	u8 res4[0x8];
+-	__be32 lurt;            /**< UPM Refresh Timer */
+-	__be32 lsrt;            /**< SDRAM Refresh Timer */
+-	u8 res5[0x8];
+-	__be32 ltesr;           /**< Transfer Error Status Register */
+-#define LTESR_BM   0x80000000
+-#define LTESR_FCT  0x40000000
+-#define LTESR_PAR  0x20000000
+-#define LTESR_WP   0x04000000
+-#define LTESR_ATMW 0x00800000
+-#define LTESR_ATMR 0x00400000
+-#define LTESR_CS   0x00080000
+-#define LTESR_CC   0x00000001
+-#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+-	__be32 ltedr;           /**< Transfer Error Disable Register */
+-	__be32 lteir;           /**< Transfer Error Interrupt Register */
+-	__be32 lteatr;          /**< Transfer Error Attributes Register */
+-	__be32 ltear;           /**< Transfer Error Address Register */
+-	u8 res6[0xC];
+-	__be32 lbcr;            /**< Configuration Register */
+-#define LBCR_LDIS  0x80000000
+-#define LBCR_LDIS_SHIFT    31
+-#define LBCR_BCTLC 0x00C00000
+-#define LBCR_BCTLC_SHIFT   22
+-#define LBCR_AHD   0x00200000
+-#define LBCR_LPBSE 0x00020000
+-#define LBCR_LPBSE_SHIFT   17
+-#define LBCR_EPAR  0x00010000
+-#define LBCR_EPAR_SHIFT    16
+-#define LBCR_BMT   0x0000FF00
+-#define LBCR_BMT_SHIFT      8
+-#define LBCR_INIT  0x00040000
+-	__be32 lcrr;            /**< Clock Ratio Register */
+-#define LCRR_DBYP    0x80000000
+-#define LCRR_DBYP_SHIFT      31
+-#define LCRR_BUFCMDC 0x30000000
+-#define LCRR_BUFCMDC_SHIFT   28
+-#define LCRR_ECL     0x03000000
+-#define LCRR_ECL_SHIFT       24
+-#define LCRR_EADC    0x00030000
+-#define LCRR_EADC_SHIFT      16
+-#define LCRR_CLKDIV  0x0000000F
+-#define LCRR_CLKDIV_SHIFT     0
+-	u8 res7[0x8];
+-	__be32 fmr;             /**< Flash Mode Register */
+-#define FMR_CWTO     0x0000F000
+-#define FMR_CWTO_SHIFT       12
+-#define FMR_BOOT     0x00000800
+-#define FMR_ECCM     0x00000100
+-#define FMR_AL       0x00000030
+-#define FMR_AL_SHIFT          4
+-#define FMR_OP       0x00000003
+-#define FMR_OP_SHIFT          0
+-	__be32 fir;             /**< Flash Instruction Register */
+-#define FIR_OP0      0xF0000000
+-#define FIR_OP0_SHIFT        28
+-#define FIR_OP1      0x0F000000
+-#define FIR_OP1_SHIFT        24
+-#define FIR_OP2      0x00F00000
+-#define FIR_OP2_SHIFT        20
+-#define FIR_OP3      0x000F0000
+-#define FIR_OP3_SHIFT        16
+-#define FIR_OP4      0x0000F000
+-#define FIR_OP4_SHIFT        12
+-#define FIR_OP5      0x00000F00
+-#define FIR_OP5_SHIFT         8
+-#define FIR_OP6      0x000000F0
+-#define FIR_OP6_SHIFT         4
+-#define FIR_OP7      0x0000000F
+-#define FIR_OP7_SHIFT         0
+-#define FIR_OP_NOP   0x0	/* No operation and end of sequence */
+-#define FIR_OP_CA    0x1        /* Issue current column address */
+-#define FIR_OP_PA    0x2        /* Issue current block+page address */
+-#define FIR_OP_UA    0x3        /* Issue user defined address */
+-#define FIR_OP_CM0   0x4        /* Issue command from FCR[CMD0] */
+-#define FIR_OP_CM1   0x5        /* Issue command from FCR[CMD1] */
+-#define FIR_OP_CM2   0x6        /* Issue command from FCR[CMD2] */
+-#define FIR_OP_CM3   0x7        /* Issue command from FCR[CMD3] */
+-#define FIR_OP_WB    0x8        /* Write FBCR bytes from FCM buffer */
+-#define FIR_OP_WS    0x9        /* Write 1 or 2 bytes from MDR[AS] */
+-#define FIR_OP_RB    0xA        /* Read FBCR bytes to FCM buffer */
+-#define FIR_OP_RS    0xB        /* Read 1 or 2 bytes to MDR[AS] */
+-#define FIR_OP_CW0   0xC        /* Wait then issue FCR[CMD0] */
+-#define FIR_OP_CW1   0xD        /* Wait then issue FCR[CMD1] */
+-#define FIR_OP_RBW   0xE        /* Wait then read FBCR bytes */
+-#define FIR_OP_RSW   0xE        /* Wait then read 1 or 2 bytes */
+-	__be32 fcr;             /**< Flash Command Register */
+-#define FCR_CMD0     0xFF000000
+-#define FCR_CMD0_SHIFT       24
+-#define FCR_CMD1     0x00FF0000
+-#define FCR_CMD1_SHIFT       16
+-#define FCR_CMD2     0x0000FF00
+-#define FCR_CMD2_SHIFT        8
+-#define FCR_CMD3     0x000000FF
+-#define FCR_CMD3_SHIFT        0
+-	__be32 fbar;            /**< Flash Block Address Register */
+-#define FBAR_BLK     0x00FFFFFF
+-	__be32 fpar;            /**< Flash Page Address Register */
+-#define FPAR_SP_PI   0x00007C00
+-#define FPAR_SP_PI_SHIFT     10
+-#define FPAR_SP_MS   0x00000200
+-#define FPAR_SP_CI   0x000001FF
+-#define FPAR_SP_CI_SHIFT      0
+-#define FPAR_LP_PI   0x0003F000
+-#define FPAR_LP_PI_SHIFT     12
+-#define FPAR_LP_MS   0x00000800
+-#define FPAR_LP_CI   0x000007FF
+-#define FPAR_LP_CI_SHIFT      0
+-	__be32 fbcr;            /**< Flash Byte Count Register */
+-#define FBCR_BC      0x00000FFF
+-	u8 res11[0x8];
+-	u8 res8[0xF00];
+-};
+-
+ struct fsl_elbc_ctrl;
+ 
+ /* mtd information per set */
+@@ -261,7 +66,7 @@ struct fsl_elbc_ctrl {
+ 
+ 	/* device info */
+ 	struct device *dev;
+-	struct elbc_regs __iomem *regs;
++	struct fsl_lbc_regs __iomem *regs;
+ 	int irq;
+ 	wait_queue_head_t irq_wait;
+ 	unsigned int irq_status; /* status read from LTESR by irq handler */
+@@ -322,7 +127,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
+ 	struct nand_chip *chip = mtd->priv;
+ 	struct fsl_elbc_mtd *priv = chip->priv;
+ 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 	int buf_num;
+ 
+ 	ctrl->page = page_addr;
+@@ -363,7 +168,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
+ 	struct nand_chip *chip = mtd->priv;
+ 	struct fsl_elbc_mtd *priv = chip->priv;
+ 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 
+ 	/* Setup the FMR[OP] to execute without write protection */
+ 	out_be32(&lbc->fmr, priv->fmr | 3);
+@@ -379,11 +184,11 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
+ 	         in_be32(&lbc->fbar), in_be32(&lbc->fpar),
+ 	         in_be32(&lbc->fbcr), priv->bank);
+ 
++	ctrl->irq_status = 0;
+ 	/* execute special operation */
+ 	out_be32(&lbc->lsor, priv->bank);
+ 
+ 	/* wait for FCM complete flag or timeout */
+-	ctrl->irq_status = 0;
+ 	wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
+ 	                   FCM_TIMEOUT_MSECS * HZ/1000);
+ 	ctrl->status = ctrl->irq_status;
+@@ -406,7 +211,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
+ {
+ 	struct fsl_elbc_mtd *priv = chip->priv;
+ 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 
+ 	if (priv->page_size) {
+ 		out_be32(&lbc->fir,
+@@ -439,7 +244,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
+ 	struct nand_chip *chip = mtd->priv;
+ 	struct fsl_elbc_mtd *priv = chip->priv;
+ 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 
+ 	ctrl->use_mdr = 0;
+ 
+@@ -541,19 +346,20 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
+ 		ctrl->column = column;
+ 		ctrl->oob = 0;
+ 
+-		fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
+-		      (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
+-
+ 		if (priv->page_size) {
++			fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) |
++			      (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
++
+ 			out_be32(&lbc->fir,
+ 			         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ 			         (FIR_OP_CA  << FIR_OP1_SHIFT) |
+ 			         (FIR_OP_PA  << FIR_OP2_SHIFT) |
+ 			         (FIR_OP_WB  << FIR_OP3_SHIFT) |
+ 			         (FIR_OP_CW1 << FIR_OP4_SHIFT));
+-
+-			fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
+ 		} else {
++			fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
++			      (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
++
+ 			out_be32(&lbc->fir,
+ 			         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ 			         (FIR_OP_CM2 << FIR_OP1_SHIFT) |
+@@ -675,7 +481,7 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+ 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
+ 
+-	if (len < 0) {
++	if (len <= 0) {
+ 		dev_err(ctrl->dev, "write_buf of %d bytes", len);
+ 		ctrl->status = 0;
+ 		return;
+@@ -690,6 +496,15 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+ 	}
+ 
+ 	memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
++	/*
++	 * This is workaround for the weird elbc hangs during nand write,
++	 * Scott Wood says: "...perhaps difference in how long it takes a
++	 * write to make it through the localbus compared to a write to IMMR
++	 * is causing problems, and sync isn't helping for some reason."
++	 * Reading back the last byte helps though.
++	 */
++	in_8(&ctrl->addr[ctrl->index] + len - 1);
++
+ 	ctrl->index += len;
+ }
+ 
+@@ -775,7 +590,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
+ {
+ 	struct fsl_elbc_mtd *priv = chip->priv;
+ 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 
+ 	if (ctrl->status != LTESR_CC)
+ 		return NAND_STATUS_FAIL;
+@@ -807,7 +622,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
+ 	struct nand_chip *chip = mtd->priv;
+ 	struct fsl_elbc_mtd *priv = chip->priv;
+ 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 	unsigned int al;
+ 
+ 	/* calculate FMR Address Length field */
+@@ -861,7 +676,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
+ 	/* adjust Option Register and ECC to match Flash page size */
+ 	if (mtd->writesize == 512) {
+ 		priv->page_size = 0;
+-		clrbits32(&lbc->bank[priv->bank].or, ~OR_FCM_PGS);
++		clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
+ 	} else if (mtd->writesize == 2048) {
+ 		priv->page_size = 1;
+ 		setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
+@@ -882,11 +697,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
+ 		return -1;
+ 	}
+ 
+-	/* The default u-boot configuration on MPC8313ERDB causes errors;
+-	 * more delay is needed.  This should be safe for other boards
+-	 * as well.
+-	 */
+-	setbits32(&lbc->bank[priv->bank].or, 0x70);
+ 	return 0;
+ }
+ 
+@@ -922,7 +732,7 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
+ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
+ {
+ 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 	struct nand_chip *chip = &priv->chip;
+ 
+ 	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
+@@ -974,6 +784,8 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
+ 
+ 	nand_release(&priv->mtd);
+ 
++	kfree(priv->mtd.name);
++
+ 	if (priv->vbase)
+ 		iounmap(priv->vbase);
+ 
+@@ -986,7 +798,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
+ static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
+                                struct device_node *node)
+ {
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 	struct fsl_elbc_mtd *priv;
+ 	struct resource res;
+ #ifdef CONFIG_MTD_PARTITIONS
+@@ -1034,6 +846,12 @@ static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
+ 		goto err;
+ 	}
+ 
++	priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", res.start);
++	if (!priv->mtd.name) {
++		ret = -ENOMEM;
++		goto err;
++	}
++
+ 	ret = fsl_elbc_chip_init(priv);
+ 	if (ret)
+ 		goto err;
+@@ -1083,7 +901,7 @@ err:
+ 
+ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+ {
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 
+ 	/* clear event registers */
+ 	setbits32(&lbc->ltesr, LTESR_NAND_MASK);
+@@ -1128,7 +946,7 @@ static int __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev)
+ static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
+ {
+ 	struct fsl_elbc_ctrl *ctrl = data;
+-	struct elbc_regs __iomem *lbc = ctrl->regs;
++	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ 	__be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
+ 
+ 	if (status) {
+diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
+new file mode 100644
+index 0000000..1ebfd87
+--- /dev/null
++++ b/drivers/mtd/nand/fsl_upm.c
+@@ -0,0 +1,291 @@
++/*
++ * Freescale UPM NAND driver.
++ *
++ * Copyright © 2007-2008  MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at 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/kernel.h>
++#include <linux/module.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/nand_ecc.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mtd/mtd.h>
++#include <linux/of_platform.h>
++#include <linux/of_gpio.h>
++#include <linux/io.h>
++#include <asm/fsl_lbc.h>
++
++struct fsl_upm_nand {
++	struct device *dev;
++	struct mtd_info mtd;
++	struct nand_chip chip;
++	int last_ctrl;
++#ifdef CONFIG_MTD_PARTITIONS
++	struct mtd_partition *parts;
++#endif
++
++	struct fsl_upm upm;
++	uint8_t upm_addr_offset;
++	uint8_t upm_cmd_offset;
++	void __iomem *io_base;
++	int rnb_gpio;
++	const uint32_t *wait_pattern;
++	const uint32_t *wait_write;
++	int chip_delay;
++};
++
++#define to_fsl_upm_nand(mtd) container_of(mtd, struct fsl_upm_nand, mtd)
++
++static int fun_chip_ready(struct mtd_info *mtd)
++{
++	struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++
++	if (gpio_get_value(fun->rnb_gpio))
++		return 1;
++
++	dev_vdbg(fun->dev, "busy\n");
++	return 0;
++}
++
++static void fun_wait_rnb(struct fsl_upm_nand *fun)
++{
++	int cnt = 1000000;
++
++	if (fun->rnb_gpio >= 0) {
++		while (--cnt && !fun_chip_ready(&fun->mtd))
++			cpu_relax();
++	}
++
++	if (!cnt)
++		dev_err(fun->dev, "tired waiting for RNB\n");
++}
++
++static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
++{
++	struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++
++	if (!(ctrl & fun->last_ctrl)) {
++		fsl_upm_end_pattern(&fun->upm);
++
++		if (cmd == NAND_CMD_NONE)
++			return;
++
++		fun->last_ctrl = ctrl & (NAND_ALE | NAND_CLE);
++	}
++
++	if (ctrl & NAND_CTRL_CHANGE) {
++		if (ctrl & NAND_ALE)
++			fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset);
++		else if (ctrl & NAND_CLE)
++			fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
++	}
++
++	fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd);
++
++	if (fun->wait_pattern)
++		fun_wait_rnb(fun);
++}
++
++static uint8_t fun_read_byte(struct mtd_info *mtd)
++{
++	struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++
++	return in_8(fun->chip.IO_ADDR_R);
++}
++
++static void fun_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
++{
++	struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++	int i;
++
++	for (i = 0; i < len; i++)
++		buf[i] = in_8(fun->chip.IO_ADDR_R);
++}
++
++static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
++{
++	struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++	int i;
++
++	for (i = 0; i < len; i++) {
++		out_8(fun->chip.IO_ADDR_W, buf[i]);
++		if (fun->wait_write)
++			fun_wait_rnb(fun);
++	}
++}
++
++static int __devinit fun_chip_init(struct fsl_upm_nand *fun)
++{
++	int ret;
++#ifdef CONFIG_MTD_PARTITIONS
++	static const char *part_types[] = { "cmdlinepart", NULL, };
++#endif
++
++	fun->chip.IO_ADDR_R = fun->io_base;
++	fun->chip.IO_ADDR_W = fun->io_base;
++	fun->chip.cmd_ctrl = fun_cmd_ctrl;
++	fun->chip.chip_delay = fun->chip_delay;
++	fun->chip.read_byte = fun_read_byte;
++	fun->chip.read_buf = fun_read_buf;
++	fun->chip.write_buf = fun_write_buf;
++	fun->chip.ecc.mode = NAND_ECC_SOFT;
++
++	if (fun->rnb_gpio >= 0)
++		fun->chip.dev_ready = fun_chip_ready;
++
++	fun->mtd.priv = &fun->chip;
++	fun->mtd.owner = THIS_MODULE;
++
++	ret = nand_scan(&fun->mtd, 1);
++	if (ret)
++		return ret;
++
++	fun->mtd.name = fun->dev->bus_id;
++
++#ifdef CONFIG_MTD_PARTITIONS
++	ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
++	if (ret > 0)
++		return add_mtd_partitions(&fun->mtd, fun->parts, ret);
++#endif
++	return add_mtd_device(&fun->mtd);
++}
++
++static int __devinit fun_probe(struct of_device *ofdev,
++			       const struct of_device_id *ofid)
++{
++	struct fsl_upm_nand *fun;
++	struct resource io_res;
++	const uint32_t *prop;
++	int ret;
++	int size;
++
++	fun = kzalloc(sizeof(*fun), GFP_KERNEL);
++	if (!fun)
++		return -ENOMEM;
++
++	ret = of_address_to_resource(ofdev->node, 0, &io_res);
++	if (ret) {
++		dev_err(&ofdev->dev, "can't get IO base\n");
++		goto err1;
++	}
++
++	ret = fsl_upm_find(io_res.start, &fun->upm);
++	if (ret) {
++		dev_err(&ofdev->dev, "can't find UPM\n");
++		goto err1;
++	}
++
++	prop = of_get_property(ofdev->node, "fsl,upm-addr-offset", &size);
++	if (!prop || size != sizeof(uint32_t)) {
++		dev_err(&ofdev->dev, "can't get UPM address offset\n");
++		ret = -EINVAL;
++		goto err2;
++	}
++	fun->upm_addr_offset = *prop;
++
++	prop = of_get_property(ofdev->node, "fsl,upm-cmd-offset", &size);
++	if (!prop || size != sizeof(uint32_t)) {
++		dev_err(&ofdev->dev, "can't get UPM command offset\n");
++		ret = -EINVAL;
++		goto err2;
++	}
++	fun->upm_cmd_offset = *prop;
++
++	fun->rnb_gpio = of_get_gpio(ofdev->node, 0);
++	if (fun->rnb_gpio >= 0) {
++		ret = gpio_request(fun->rnb_gpio, ofdev->dev.bus_id);
++		if (ret) {
++			dev_err(&ofdev->dev, "can't request RNB gpio\n");
++			goto err2;
++		}
++		gpio_direction_input(fun->rnb_gpio);
++	} else if (fun->rnb_gpio == -EINVAL) {
++		dev_err(&ofdev->dev, "specified RNB gpio is invalid\n");
++		goto err2;
++	}
++
++	fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start,
++					  io_res.end - io_res.start + 1);
++	if (!fun->io_base) {
++		ret = -ENOMEM;
++		goto err2;
++	}
++
++	fun->dev = &ofdev->dev;
++	fun->last_ctrl = NAND_CLE;
++	fun->wait_pattern = of_get_property(ofdev->node, "fsl,wait-pattern",
++					    NULL);
++	fun->wait_write = of_get_property(ofdev->node, "fsl,wait-write", NULL);
++
++	prop = of_get_property(ofdev->node, "chip-delay", NULL);
++	if (prop)
++		fun->chip_delay = *prop;
++	else
++		fun->chip_delay = 50;
++
++	ret = fun_chip_init(fun);
++	if (ret)
++		goto err2;
++
++	dev_set_drvdata(&ofdev->dev, fun);
++
++	return 0;
++err2:
++	if (fun->rnb_gpio >= 0)
++		gpio_free(fun->rnb_gpio);
++err1:
++	kfree(fun);
++
++	return ret;
++}
++
++static int __devexit fun_remove(struct of_device *ofdev)
++{
++	struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
++
++	nand_release(&fun->mtd);
++
++	if (fun->rnb_gpio >= 0)
++		gpio_free(fun->rnb_gpio);
++
++	kfree(fun);
++
++	return 0;
++}
++
++static struct of_device_id of_fun_match[] = {
++	{ .compatible = "fsl,upm-nand" },
++	{},
++};
++MODULE_DEVICE_TABLE(of, of_fun_match);
++
++static struct of_platform_driver of_fun_driver = {
++	.name		= "fsl,upm-nand",
++	.match_table	= of_fun_match,
++	.probe		= fun_probe,
++	.remove		= __devexit_p(fun_remove),
++};
++
++static int __init fun_module_init(void)
++{
++	return of_register_platform_driver(&of_fun_driver);
++}
++module_init(fun_module_init);
++
++static void __exit fun_module_exit(void)
++{
++	of_unregister_platform_driver(&of_fun_driver);
++}
++module_exit(fun_module_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Anton Vorontsov <avorontsov at ru.mvista.com>");
++MODULE_DESCRIPTION("Driver for NAND chips working through Freescale "
++		   "LocalBus User-Programmable Machine");
+diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
+index 7acb1a0..ba1bdf7 100644
+--- a/drivers/mtd/nand/nand_base.c
++++ b/drivers/mtd/nand/nand_base.c
+@@ -2229,6 +2229,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
+ {
+ 	struct nand_flash_dev *type = NULL;
+ 	int i, dev_id, maf_idx;
++	int tmp_id, tmp_manf;
+ 
+ 	/* Select the device */
+ 	chip->select_chip(mtd, 0);
+@@ -2240,6 +2241,26 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
+ 	*maf_id = chip->read_byte(mtd);
+ 	dev_id = chip->read_byte(mtd);
+ 
++	/* Try again to make sure, as some systems the bus-hold or other
++	 * interface concerns can cause random data which looks like a
++	 * possibly credible NAND flash to appear. If the two results do
++	 * not match, ignore the device completely.
++	 */
++
++	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
++
++	/* Read manufacturer and device IDs */
++
++	tmp_manf = chip->read_byte(mtd);
++	tmp_id = chip->read_byte(mtd);
++
++	if (tmp_manf != *maf_id || tmp_id != dev_id) {
++		printk(KERN_INFO "%s: second ID read did not match "
++		       "%02x,%02x against %02x,%02x\n", __func__,
++		       *maf_id, dev_id, tmp_manf, tmp_id);
++		return ERR_PTR(-ENODEV);
++	}
++
+ 	/* Lookup the flash id */
+ 	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+ 		if (dev_id == nand_flash_ids[i].id) {
+diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
+index 1c0e89f..955959e 100644
+--- a/drivers/mtd/nand/ndfc.c
++++ b/drivers/mtd/nand/ndfc.c
+@@ -317,3 +317,5 @@ module_exit(ndfc_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Thomas Gleixner <tglx at linutronix.de>");
+ MODULE_DESCRIPTION("Platform driver for NDFC");
++MODULE_ALIAS("platform:ndfc-chip");
++MODULE_ALIAS("platform:ndfc-nand");
+diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
+index 9162cca..59e05a1 100644
+--- a/drivers/mtd/nand/orion_nand.c
++++ b/drivers/mtd/nand/orion_nand.c
+@@ -18,8 +18,8 @@
+ #include <linux/mtd/partitions.h>
+ #include <asm/io.h>
+ #include <asm/sizes.h>
+-#include <asm/arch/platform.h>
+ #include <asm/arch/hardware.h>
++#include <asm/plat-orion/orion_nand.h>
+ 
+ #ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_probes[] = { "cmdlinepart", NULL };
+@@ -169,3 +169,4 @@ module_exit(orion_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Tzachi Perelstein");
+ MODULE_DESCRIPTION("NAND glue for Orion platforms");
++MODULE_ALIAS("platform:orion_nand");
+diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
+index f6d5c2a..f674c54 100644
+--- a/drivers/mtd/nand/plat_nand.c
++++ b/drivers/mtd/nand/plat_nand.c
+@@ -54,6 +54,7 @@ static int __init plat_nand_probe(struct platform_device *pdev)
+ 	data->chip.priv = &data;
+ 	data->mtd.priv = &data->chip;
+ 	data->mtd.owner = THIS_MODULE;
++	data->mtd.name = pdev->dev.bus_id;
+ 
+ 	data->chip.IO_ADDR_R = data->io_base;
+ 	data->chip.IO_ADDR_W = data->io_base;
+@@ -150,3 +151,4 @@ module_exit(plat_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Vitaly Wool");
+ MODULE_DESCRIPTION("Simple generic NAND driver");
++MODULE_ALIAS("platform:gen_nand");
+diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
+new file mode 100644
+index 0000000..fceb468
+--- /dev/null
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -0,0 +1,1249 @@
++/*
++ * drivers/mtd/nand/pxa3xx_nand.c
++ *
++ * Copyright © 2005 Intel Corporation
++ * Copyright © 2006 Marvell International Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++#include <linux/io.h>
++#include <linux/irq.h>
++#include <asm/dma.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa3xx_nand.h>
++
++#define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
++
++/* registers and bit definitions */
++#define NDCR		(0x00) /* Control register */
++#define NDTR0CS0	(0x04) /* Timing Parameter 0 for CS0 */
++#define NDTR1CS0	(0x0C) /* Timing Parameter 1 for CS0 */
++#define NDSR		(0x14) /* Status Register */
++#define NDPCR		(0x18) /* Page Count Register */
++#define NDBDR0		(0x1C) /* Bad Block Register 0 */
++#define NDBDR1		(0x20) /* Bad Block Register 1 */
++#define NDDB		(0x40) /* Data Buffer */
++#define NDCB0		(0x48) /* Command Buffer0 */
++#define NDCB1		(0x4C) /* Command Buffer1 */
++#define NDCB2		(0x50) /* Command Buffer2 */
++
++#define NDCR_SPARE_EN		(0x1 << 31)
++#define NDCR_ECC_EN		(0x1 << 30)
++#define NDCR_DMA_EN		(0x1 << 29)
++#define NDCR_ND_RUN		(0x1 << 28)
++#define NDCR_DWIDTH_C		(0x1 << 27)
++#define NDCR_DWIDTH_M		(0x1 << 26)
++#define NDCR_PAGE_SZ		(0x1 << 24)
++#define NDCR_NCSX		(0x1 << 23)
++#define NDCR_ND_MODE		(0x3 << 21)
++#define NDCR_NAND_MODE   	(0x0)
++#define NDCR_CLR_PG_CNT		(0x1 << 20)
++#define NDCR_CLR_ECC		(0x1 << 19)
++#define NDCR_RD_ID_CNT_MASK	(0x7 << 16)
++#define NDCR_RD_ID_CNT(x)	(((x) << 16) & NDCR_RD_ID_CNT_MASK)
++
++#define NDCR_RA_START		(0x1 << 15)
++#define NDCR_PG_PER_BLK		(0x1 << 14)
++#define NDCR_ND_ARB_EN		(0x1 << 12)
++
++#define NDSR_MASK		(0xfff)
++#define NDSR_RDY		(0x1 << 11)
++#define NDSR_CS0_PAGED		(0x1 << 10)
++#define NDSR_CS1_PAGED		(0x1 << 9)
++#define NDSR_CS0_CMDD		(0x1 << 8)
++#define NDSR_CS1_CMDD		(0x1 << 7)
++#define NDSR_CS0_BBD		(0x1 << 6)
++#define NDSR_CS1_BBD		(0x1 << 5)
++#define NDSR_DBERR		(0x1 << 4)
++#define NDSR_SBERR		(0x1 << 3)
++#define NDSR_WRDREQ		(0x1 << 2)
++#define NDSR_RDDREQ		(0x1 << 1)
++#define NDSR_WRCMDREQ		(0x1)
++
++#define NDCB0_AUTO_RS		(0x1 << 25)
++#define NDCB0_CSEL		(0x1 << 24)
++#define NDCB0_CMD_TYPE_MASK	(0x7 << 21)
++#define NDCB0_CMD_TYPE(x)	(((x) << 21) & NDCB0_CMD_TYPE_MASK)
++#define NDCB0_NC		(0x1 << 20)
++#define NDCB0_DBC		(0x1 << 19)
++#define NDCB0_ADDR_CYC_MASK	(0x7 << 16)
++#define NDCB0_ADDR_CYC(x)	(((x) << 16) & NDCB0_ADDR_CYC_MASK)
++#define NDCB0_CMD2_MASK		(0xff << 8)
++#define NDCB0_CMD1_MASK		(0xff)
++#define NDCB0_ADDR_CYC_SHIFT	(16)
++
++/* dma-able I/O address for the NAND data and commands */
++#define NDCB0_DMA_ADDR		(0x43100048)
++#define NDDB_DMA_ADDR		(0x43100040)
++
++/* macros for registers read/write */
++#define nand_writel(info, off, val)	\
++	__raw_writel((val), (info)->mmio_base + (off))
++
++#define nand_readl(info, off)		\
++	__raw_readl((info)->mmio_base + (off))
++
++/* error code and state */
++enum {
++	ERR_NONE	= 0,
++	ERR_DMABUSERR	= -1,
++	ERR_SENDCMD	= -2,
++	ERR_DBERR	= -3,
++	ERR_BBERR	= -4,
++};
++
++enum {
++	STATE_READY	= 0,
++	STATE_CMD_HANDLE,
++	STATE_DMA_READING,
++	STATE_DMA_WRITING,
++	STATE_DMA_DONE,
++	STATE_PIO_READING,
++	STATE_PIO_WRITING,
++};
++
++struct pxa3xx_nand_timing {
++	unsigned int	tCH;  /* Enable signal hold time */
++	unsigned int	tCS;  /* Enable signal setup time */
++	unsigned int	tWH;  /* ND_nWE high duration */
++	unsigned int	tWP;  /* ND_nWE pulse time */
++	unsigned int	tRH;  /* ND_nRE high duration */
++	unsigned int	tRP;  /* ND_nRE pulse width */
++	unsigned int	tR;   /* ND_nWE high to ND_nRE low for read */
++	unsigned int	tWHR; /* ND_nWE high to ND_nRE low for status read */
++	unsigned int	tAR;  /* ND_ALE low to ND_nRE low delay */
++};
++
++struct pxa3xx_nand_cmdset {
++	uint16_t	read1;
++	uint16_t	read2;
++	uint16_t	program;
++	uint16_t	read_status;
++	uint16_t	read_id;
++	uint16_t	erase;
++	uint16_t	reset;
++	uint16_t	lock;
++	uint16_t	unlock;
++	uint16_t	lock_status;
++};
++
++struct pxa3xx_nand_flash {
++	struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
++	struct pxa3xx_nand_cmdset *cmdset;
++
++	uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
++	uint32_t page_size;	/* Page size in bytes (PAGE_SZ) */
++	uint32_t flash_width;	/* Width of Flash memory (DWIDTH_M) */
++	uint32_t dfc_width;	/* Width of flash controller(DWIDTH_C) */
++	uint32_t num_blocks;	/* Number of physical blocks in Flash */
++	uint32_t chip_id;
++
++	/* NOTE: these are automatically calculated, do not define */
++	size_t		oob_size;
++	size_t		read_id_bytes;
++
++	unsigned int	col_addr_cycles;
++	unsigned int	row_addr_cycles;
++};
++
++struct pxa3xx_nand_info {
++	struct nand_chip	nand_chip;
++
++	struct platform_device	 *pdev;
++	struct pxa3xx_nand_flash *flash_info;
++
++	struct clk		*clk;
++	void __iomem		*mmio_base;
++
++	unsigned int 		buf_start;
++	unsigned int		buf_count;
++
++	/* DMA information */
++	int			drcmr_dat;
++	int			drcmr_cmd;
++
++	unsigned char		*data_buff;
++	dma_addr_t 		data_buff_phys;
++	size_t			data_buff_size;
++	int 			data_dma_ch;
++	struct pxa_dma_desc	*data_desc;
++	dma_addr_t 		data_desc_addr;
++
++	uint32_t		reg_ndcr;
++
++	/* saved column/page_addr during CMD_SEQIN */
++	int			seqin_column;
++	int			seqin_page_addr;
++
++	/* relate to the command */
++	unsigned int		state;
++
++	int			use_ecc;	/* use HW ECC ? */
++	int			use_dma;	/* use DMA ? */
++
++	size_t			data_size;	/* data size in FIFO */
++	int 			retcode;
++	struct completion 	cmd_complete;
++
++	/* generated NDCBx register values */
++	uint32_t		ndcb0;
++	uint32_t		ndcb1;
++	uint32_t		ndcb2;
++};
++
++static int use_dma = 1;
++module_param(use_dma, bool, 0444);
++MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");
++
++static struct pxa3xx_nand_cmdset smallpage_cmdset = {
++	.read1		= 0x0000,
++	.read2		= 0x0050,
++	.program	= 0x1080,
++	.read_status	= 0x0070,
++	.read_id	= 0x0090,
++	.erase		= 0xD060,
++	.reset		= 0x00FF,
++	.lock		= 0x002A,
++	.unlock		= 0x2423,
++	.lock_status	= 0x007A,
++};
++
++static struct pxa3xx_nand_cmdset largepage_cmdset = {
++	.read1		= 0x3000,
++	.read2		= 0x0050,
++	.program	= 0x1080,
++	.read_status	= 0x0070,
++	.read_id	= 0x0090,
++	.erase		= 0xD060,
++	.reset		= 0x00FF,
++	.lock		= 0x002A,
++	.unlock		= 0x2423,
++	.lock_status	= 0x007A,
++};
++
++static struct pxa3xx_nand_timing samsung512MbX16_timing = {
++	.tCH	= 10,
++	.tCS	= 0,
++	.tWH	= 20,
++	.tWP	= 40,
++	.tRH	= 30,
++	.tRP	= 40,
++	.tR	= 11123,
++	.tWHR	= 110,
++	.tAR	= 10,
++};
++
++static struct pxa3xx_nand_flash samsung512MbX16 = {
++	.timing		= &samsung512MbX16_timing,
++	.cmdset		= &smallpage_cmdset,
++	.page_per_block	= 32,
++	.page_size	= 512,
++	.flash_width	= 16,
++	.dfc_width	= 16,
++	.num_blocks	= 4096,
++	.chip_id	= 0x46ec,
++};
++
++static struct pxa3xx_nand_timing micron_timing = {
++	.tCH	= 10,
++	.tCS	= 25,
++	.tWH	= 15,
++	.tWP	= 25,
++	.tRH	= 15,
++	.tRP	= 25,
++	.tR	= 25000,
++	.tWHR	= 60,
++	.tAR	= 10,
++};
++
++static struct pxa3xx_nand_flash micron1GbX8 = {
++	.timing		= &micron_timing,
++	.cmdset		= &largepage_cmdset,
++	.page_per_block	= 64,
++	.page_size	= 2048,
++	.flash_width	= 8,
++	.dfc_width	= 8,
++	.num_blocks	= 1024,
++	.chip_id	= 0xa12c,
++};
++
++static struct pxa3xx_nand_flash micron1GbX16 = {
++	.timing		= &micron_timing,
++	.cmdset		= &largepage_cmdset,
++	.page_per_block	= 64,
++	.page_size	= 2048,
++	.flash_width	= 16,
++	.dfc_width	= 16,
++	.num_blocks	= 1024,
++	.chip_id	= 0xb12c,
++};
++
++static struct pxa3xx_nand_flash *builtin_flash_types[] = {
++	&samsung512MbX16,
++	&micron1GbX8,
++	&micron1GbX16,
++};
++
++#define NDTR0_tCH(c)	(min((c), 7) << 19)
++#define NDTR0_tCS(c)	(min((c), 7) << 16)
++#define NDTR0_tWH(c)	(min((c), 7) << 11)
++#define NDTR0_tWP(c)	(min((c), 7) << 8)
++#define NDTR0_tRH(c)	(min((c), 7) << 3)
++#define NDTR0_tRP(c)	(min((c), 7) << 0)
++
++#define NDTR1_tR(c)	(min((c), 65535) << 16)
++#define NDTR1_tWHR(c)	(min((c), 15) << 4)
++#define NDTR1_tAR(c)	(min((c), 15) << 0)
++
++/* convert nano-seconds to nand flash controller clock cycles */
++#define ns2cycle(ns, clk)	(int)(((ns) * (clk / 1000000) / 1000) + 1)
++
++static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
++				   struct pxa3xx_nand_timing *t)
++{
++	unsigned long nand_clk = clk_get_rate(info->clk);
++	uint32_t ndtr0, ndtr1;
++
++	ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) |
++		NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) |
++		NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) |
++		NDTR0_tWP(ns2cycle(t->tWP, nand_clk)) |
++		NDTR0_tRH(ns2cycle(t->tRH, nand_clk)) |
++		NDTR0_tRP(ns2cycle(t->tRP, nand_clk));
++
++	ndtr1 = NDTR1_tR(ns2cycle(t->tR, nand_clk)) |
++		NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
++		NDTR1_tAR(ns2cycle(t->tAR, nand_clk));
++
++	nand_writel(info, NDTR0CS0, ndtr0);
++	nand_writel(info, NDTR1CS0, ndtr1);
++}
++
++#define WAIT_EVENT_TIMEOUT	10
++
++static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
++{
++	int timeout = WAIT_EVENT_TIMEOUT;
++	uint32_t ndsr;
++
++	while (timeout--) {
++		ndsr = nand_readl(info, NDSR) & NDSR_MASK;
++		if (ndsr & event) {
++			nand_writel(info, NDSR, ndsr);
++			return 0;
++		}
++		udelay(10);
++	}
++
++	return -ETIMEDOUT;
++}
++
++static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
++			uint16_t cmd, int column, int page_addr)
++{
++	struct pxa3xx_nand_flash *f = info->flash_info;
++	struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
++
++	/* calculate data size */
++	switch (f->page_size) {
++	case 2048:
++		info->data_size = (info->use_ecc) ? 2088 : 2112;
++		break;
++	case 512:
++		info->data_size = (info->use_ecc) ? 520 : 528;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	/* generate values for NDCBx registers */
++	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
++	info->ndcb1 = 0;
++	info->ndcb2 = 0;
++	info->ndcb0 |= NDCB0_ADDR_CYC(f->row_addr_cycles + f->col_addr_cycles);
++
++	if (f->col_addr_cycles == 2) {
++		/* large block, 2 cycles for column address
++		 * row address starts from 3rd cycle
++		 */
++		info->ndcb1 |= (page_addr << 16) | (column & 0xffff);
++		if (f->row_addr_cycles == 3)
++			info->ndcb2 = (page_addr >> 16) & 0xff;
++	} else
++		/* small block, 1 cycles for column address
++		 * row address starts from 2nd cycle
++		 */
++		info->ndcb1 = (page_addr << 8) | (column & 0xff);
++
++	if (cmd == cmdset->program)
++		info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
++
++	return 0;
++}
++
++static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
++			uint16_t cmd, int page_addr)
++{
++	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
++	info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
++	info->ndcb1 = page_addr;
++	info->ndcb2 = 0;
++	return 0;
++}
++
++static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
++{
++	struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset;
++
++	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
++	info->ndcb1 = 0;
++	info->ndcb2 = 0;
++
++	if (cmd == cmdset->read_id) {
++		info->ndcb0 |= NDCB0_CMD_TYPE(3);
++		info->data_size = 8;
++	} else if (cmd == cmdset->read_status) {
++		info->ndcb0 |= NDCB0_CMD_TYPE(4);
++		info->data_size = 8;
++	} else if (cmd == cmdset->reset || cmd == cmdset->lock ||
++		   cmd == cmdset->unlock) {
++		info->ndcb0 |= NDCB0_CMD_TYPE(5);
++	} else
++		return -EINVAL;
++
++	return 0;
++}
++
++static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
++{
++	uint32_t ndcr;
++
++	ndcr = nand_readl(info, NDCR);
++	nand_writel(info, NDCR, ndcr & ~int_mask);
++}
++
++static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
++{
++	uint32_t ndcr;
++
++	ndcr = nand_readl(info, NDCR);
++	nand_writel(info, NDCR, ndcr | int_mask);
++}
++
++/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
++ * otherwise, it does not work
++ */
++static int write_cmd(struct pxa3xx_nand_info *info)
++{
++	uint32_t ndcr;
++
++	/* clear status bits and run */
++	nand_writel(info, NDSR, NDSR_MASK);
++
++	ndcr = info->reg_ndcr;
++
++	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
++	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
++	ndcr |= NDCR_ND_RUN;
++
++	nand_writel(info, NDCR, ndcr);
++
++	if (wait_for_event(info, NDSR_WRCMDREQ)) {
++		printk(KERN_ERR "timed out writing command\n");
++		return -ETIMEDOUT;
++	}
++
++	nand_writel(info, NDCB0, info->ndcb0);
++	nand_writel(info, NDCB0, info->ndcb1);
++	nand_writel(info, NDCB0, info->ndcb2);
++	return 0;
++}
++
++static int handle_data_pio(struct pxa3xx_nand_info *info)
++{
++	int ret, timeout = CHIP_DELAY_TIMEOUT;
++
++	switch (info->state) {
++	case STATE_PIO_WRITING:
++		__raw_writesl(info->mmio_base + NDDB, info->data_buff,
++				info->data_size << 2);
++
++		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
++
++		ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
++		if (!ret) {
++			printk(KERN_ERR "program command time out\n");
++			return -1;
++		}
++		break;
++	case STATE_PIO_READING:
++		__raw_readsl(info->mmio_base + NDDB, info->data_buff,
++				info->data_size << 2);
++		break;
++	default:
++		printk(KERN_ERR "%s: invalid state %d\n", __func__,
++				info->state);
++		return -EINVAL;
++	}
++
++	info->state = STATE_READY;
++	return 0;
++}
++
++static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
++{
++	struct pxa_dma_desc *desc = info->data_desc;
++	int dma_len = ALIGN(info->data_size, 32);
++
++	desc->ddadr = DDADR_STOP;
++	desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
++
++	if (dir_out) {
++		desc->dsadr = info->data_buff_phys;
++		desc->dtadr = NDDB_DMA_ADDR;
++		desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
++	} else {
++		desc->dtadr = info->data_buff_phys;
++		desc->dsadr = NDDB_DMA_ADDR;
++		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
++	}
++
++	DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
++	DDADR(info->data_dma_ch) = info->data_desc_addr;
++	DCSR(info->data_dma_ch) |= DCSR_RUN;
++}
++
++static void pxa3xx_nand_data_dma_irq(int channel, void *data)
++{
++	struct pxa3xx_nand_info *info = data;
++	uint32_t dcsr;
++
++	dcsr = DCSR(channel);
++	DCSR(channel) = dcsr;
++
++	if (dcsr & DCSR_BUSERR) {
++		info->retcode = ERR_DMABUSERR;
++		complete(&info->cmd_complete);
++	}
++
++	if (info->state == STATE_DMA_WRITING) {
++		info->state = STATE_DMA_DONE;
++		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
++	} else {
++		info->state = STATE_READY;
++		complete(&info->cmd_complete);
++	}
++}
++
++static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
++{
++	struct pxa3xx_nand_info *info = devid;
++	unsigned int status;
++
++	status = nand_readl(info, NDSR);
++
++	if (status & (NDSR_RDDREQ | NDSR_DBERR)) {
++		if (status & NDSR_DBERR)
++			info->retcode = ERR_DBERR;
++
++		disable_int(info, NDSR_RDDREQ | NDSR_DBERR);
++
++		if (info->use_dma) {
++			info->state = STATE_DMA_READING;
++			start_data_dma(info, 0);
++		} else {
++			info->state = STATE_PIO_READING;
++			complete(&info->cmd_complete);
++		}
++	} else if (status & NDSR_WRDREQ) {
++		disable_int(info, NDSR_WRDREQ);
++		if (info->use_dma) {
++			info->state = STATE_DMA_WRITING;
++			start_data_dma(info, 1);
++		} else {
++			info->state = STATE_PIO_WRITING;
++			complete(&info->cmd_complete);
++		}
++	} else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) {
++		if (status & NDSR_CS0_BBD)
++			info->retcode = ERR_BBERR;
++
++		disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
++		info->state = STATE_READY;
++		complete(&info->cmd_complete);
++	}
++	nand_writel(info, NDSR, status);
++	return IRQ_HANDLED;
++}
++
++static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event)
++{
++	uint32_t ndcr;
++	int ret, timeout = CHIP_DELAY_TIMEOUT;
++
++	if (write_cmd(info)) {
++		info->retcode = ERR_SENDCMD;
++		goto fail_stop;
++	}
++
++	info->state = STATE_CMD_HANDLE;
++
++	enable_int(info, event);
++
++	ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
++	if (!ret) {
++		printk(KERN_ERR "command execution timed out\n");
++		info->retcode = ERR_SENDCMD;
++		goto fail_stop;
++	}
++
++	if (info->use_dma == 0 && info->data_size > 0)
++		if (handle_data_pio(info))
++			goto fail_stop;
++
++	return 0;
++
++fail_stop:
++	ndcr = nand_readl(info, NDCR);
++	nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
++	udelay(10);
++	return -ETIMEDOUT;
++}
++
++static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
++{
++	struct pxa3xx_nand_info *info = mtd->priv;
++	return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0;
++}
++
++static inline int is_buf_blank(uint8_t *buf, size_t len)
++{
++	for (; len > 0; len--)
++		if (*buf++ != 0xff)
++			return 0;
++	return 1;
++}
++
++static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
++				int column, int page_addr)
++{
++	struct pxa3xx_nand_info *info = mtd->priv;
++	struct pxa3xx_nand_flash *flash_info = info->flash_info;
++	struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset;
++	int ret;
++
++	info->use_dma = (use_dma) ? 1 : 0;
++	info->use_ecc = 0;
++	info->data_size = 0;
++	info->state = STATE_READY;
++
++	init_completion(&info->cmd_complete);
++
++	switch (command) {
++	case NAND_CMD_READOOB:
++		/* disable HW ECC to get all the OOB data */
++		info->buf_count = mtd->writesize + mtd->oobsize;
++		info->buf_start = mtd->writesize + column;
++
++		if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
++			break;
++
++		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR);
++
++		/* We only are OOB, so if the data has error, does not matter */
++		if (info->retcode == ERR_DBERR)
++			info->retcode = ERR_NONE;
++		break;
++
++	case NAND_CMD_READ0:
++		info->use_ecc = 1;
++		info->retcode = ERR_NONE;
++		info->buf_start = column;
++		info->buf_count = mtd->writesize + mtd->oobsize;
++		memset(info->data_buff, 0xFF, info->buf_count);
++
++		if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
++			break;
++
++		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR);
++
++		if (info->retcode == ERR_DBERR) {
++			/* for blank page (all 0xff), HW will calculate its ECC as
++			 * 0, which is different from the ECC information within
++			 * OOB, ignore such double bit errors
++			 */
++			if (is_buf_blank(info->data_buff, mtd->writesize))
++				info->retcode = ERR_NONE;
++		}
++		break;
++	case NAND_CMD_SEQIN:
++		info->buf_start = column;
++		info->buf_count = mtd->writesize + mtd->oobsize;
++		memset(info->data_buff, 0xff, info->buf_count);
++
++		/* save column/page_addr for next CMD_PAGEPROG */
++		info->seqin_column = column;
++		info->seqin_page_addr = page_addr;
++		break;
++	case NAND_CMD_PAGEPROG:
++		info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
++
++		if (prepare_read_prog_cmd(info, cmdset->program,
++				info->seqin_column, info->seqin_page_addr))
++			break;
++
++		pxa3xx_nand_do_cmd(info, NDSR_WRDREQ);
++		break;
++	case NAND_CMD_ERASE1:
++		if (prepare_erase_cmd(info, cmdset->erase, page_addr))
++			break;
++
++		pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
++		break;
++	case NAND_CMD_ERASE2:
++		break;
++	case NAND_CMD_READID:
++	case NAND_CMD_STATUS:
++		info->use_dma = 0;	/* force PIO read */
++		info->buf_start = 0;
++		info->buf_count = (command == NAND_CMD_READID) ?
++				flash_info->read_id_bytes : 1;
++
++		if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
++				cmdset->read_id : cmdset->read_status))
++			break;
++
++		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ);
++		break;
++	case NAND_CMD_RESET:
++		if (prepare_other_cmd(info, cmdset->reset))
++			break;
++
++		ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD);
++		if (ret == 0) {
++			int timeout = 2;
++			uint32_t ndcr;
++
++			while (timeout--) {
++				if (nand_readl(info, NDSR) & NDSR_RDY)
++					break;
++				msleep(10);
++			}
++
++			ndcr = nand_readl(info, NDCR);
++			nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
++		}
++		break;
++	default:
++		printk(KERN_ERR "non-supported command.\n");
++		break;
++	}
++
++	if (info->retcode == ERR_DBERR) {
++		printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
++		info->retcode = ERR_NONE;
++	}
++}
++
++static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
++{
++	struct pxa3xx_nand_info *info = mtd->priv;
++	char retval = 0xFF;
++
++	if (info->buf_start < info->buf_count)
++		/* Has just send a new command? */
++		retval = info->data_buff[info->buf_start++];
++
++	return retval;
++}
++
++static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
++{
++	struct pxa3xx_nand_info *info = mtd->priv;
++	u16 retval = 0xFFFF;
++
++	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
++		retval = *((u16 *)(info->data_buff+info->buf_start));
++		info->buf_start += 2;
++	}
++	return retval;
++}
++
++static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
++{
++	struct pxa3xx_nand_info *info = mtd->priv;
++	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
++
++	memcpy(buf, info->data_buff + info->buf_start, real_len);
++	info->buf_start += real_len;
++}
++
++static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
++		const uint8_t *buf, int len)
++{
++	struct pxa3xx_nand_info *info = mtd->priv;
++	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
++
++	memcpy(info->data_buff + info->buf_start, buf, real_len);
++	info->buf_start += real_len;
++}
++
++static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
++		const uint8_t *buf, int len)
++{
++	return 0;
++}
++
++static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
++{
++	return;
++}
++
++static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
++{
++	struct pxa3xx_nand_info *info = mtd->priv;
++
++	/* pxa3xx_nand_send_command has waited for command complete */
++	if (this->state == FL_WRITING || this->state == FL_ERASING) {
++		if (info->retcode == ERR_NONE)
++			return 0;
++		else {
++			/*
++			 * any error make it return 0x01 which will tell
++			 * the caller the erase and write fail
++			 */
++			return 0x01;
++		}
++	}
++
++	return 0;
++}
++
++static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
++{
++	return;
++}
++
++static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd,
++		const uint8_t *dat, uint8_t *ecc_code)
++{
++	return 0;
++}
++
++static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
++		uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
++{
++	struct pxa3xx_nand_info *info = mtd->priv;
++	/*
++	 * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we
++	 * consider it as a ecc error which will tell the caller the
++	 * read fail We have distinguish all the errors, but the
++	 * nand_read_ecc only check this function return value
++	 */
++	if (info->retcode != ERR_NONE)
++		return -1;
++
++	return 0;
++}
++
++static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
++{
++	struct pxa3xx_nand_flash *f = info->flash_info;
++	struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
++	uint32_t ndcr;
++	uint8_t  id_buff[8];
++
++	if (prepare_other_cmd(info, cmdset->read_id)) {
++		printk(KERN_ERR "failed to prepare command\n");
++		return -EINVAL;
++	}
++
++	/* Send command */
++	if (write_cmd(info))
++		goto fail_timeout;
++
++	/* Wait for CMDDM(command done successfully) */
++	if (wait_for_event(info, NDSR_RDDREQ))
++		goto fail_timeout;
++
++	__raw_readsl(info->mmio_base + NDDB, id_buff, 2);
++	*id = id_buff[0] | (id_buff[1] << 8);
++	return 0;
++
++fail_timeout:
++	ndcr = nand_readl(info, NDCR);
++	nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
++	udelay(10);
++	return -ETIMEDOUT;
++}
++
++static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
++				    struct pxa3xx_nand_flash *f)
++{
++	struct platform_device *pdev = info->pdev;
++	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
++	uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
++
++	if (f->page_size != 2048 && f->page_size != 512)
++		return -EINVAL;
++
++	if (f->flash_width != 16 && f->flash_width != 8)
++		return -EINVAL;
++
++	/* calculate flash information */
++	f->oob_size = (f->page_size == 2048) ? 64 : 16;
++	f->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
++
++	/* calculate addressing information */
++	f->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
++
++	if (f->num_blocks * f->page_per_block > 65536)
++		f->row_addr_cycles = 3;
++	else
++		f->row_addr_cycles = 2;
++
++	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
++	ndcr |= (f->col_addr_cycles == 2) ? NDCR_RA_START : 0;
++	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
++	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
++	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
++	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
++
++	ndcr |= NDCR_RD_ID_CNT(f->read_id_bytes);
++	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
++
++	info->reg_ndcr = ndcr;
++
++	pxa3xx_nand_set_timing(info, f->timing);
++	info->flash_info = f;
++	return 0;
++}
++
++static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info)
++{
++	struct pxa3xx_nand_flash *f;
++	uint32_t id;
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
++
++		f = builtin_flash_types[i];
++
++		if (pxa3xx_nand_config_flash(info, f))
++			continue;
++
++		if (__readid(info, &id))
++			continue;
++
++		if (id == f->chip_id)
++			return 0;
++	}
++
++	return -ENODEV;
++}
++
++/* the maximum possible buffer size for large page with OOB data
++ * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
++ * data buffer and the DMA descriptor
++ */
++#define MAX_BUFF_SIZE	PAGE_SIZE
++
++static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
++{
++	struct platform_device *pdev = info->pdev;
++	int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
++
++	if (use_dma == 0) {
++		info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
++		if (info->data_buff == NULL)
++			return -ENOMEM;
++		return 0;
++	}
++
++	info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
++				&info->data_buff_phys, GFP_KERNEL);
++	if (info->data_buff == NULL) {
++		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
++		return -ENOMEM;
++	}
++
++	info->data_buff_size = MAX_BUFF_SIZE;
++	info->data_desc = (void *)info->data_buff + data_desc_offset;
++	info->data_desc_addr = info->data_buff_phys + data_desc_offset;
++
++	info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
++				pxa3xx_nand_data_dma_irq, info);
++	if (info->data_dma_ch < 0) {
++		dev_err(&pdev->dev, "failed to request data dma\n");
++		dma_free_coherent(&pdev->dev, info->data_buff_size,
++				info->data_buff, info->data_buff_phys);
++		return info->data_dma_ch;
++	}
++
++	return 0;
++}
++
++static struct nand_ecclayout hw_smallpage_ecclayout = {
++	.eccbytes = 6,
++	.eccpos = {8, 9, 10, 11, 12, 13 },
++	.oobfree = { {2, 6} }
++};
++
++static struct nand_ecclayout hw_largepage_ecclayout = {
++	.eccbytes = 24,
++	.eccpos = {
++		40, 41, 42, 43, 44, 45, 46, 47,
++		48, 49, 50, 51, 52, 53, 54, 55,
++		56, 57, 58, 59, 60, 61, 62, 63},
++	.oobfree = { {2, 38} }
++};
++
++static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
++				 struct pxa3xx_nand_info *info)
++{
++	struct pxa3xx_nand_flash *f = info->flash_info;
++	struct nand_chip *this = &info->nand_chip;
++
++	this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
++
++	this->waitfunc		= pxa3xx_nand_waitfunc;
++	this->select_chip	= pxa3xx_nand_select_chip;
++	this->dev_ready		= pxa3xx_nand_dev_ready;
++	this->cmdfunc		= pxa3xx_nand_cmdfunc;
++	this->read_word		= pxa3xx_nand_read_word;
++	this->read_byte		= pxa3xx_nand_read_byte;
++	this->read_buf		= pxa3xx_nand_read_buf;
++	this->write_buf		= pxa3xx_nand_write_buf;
++	this->verify_buf	= pxa3xx_nand_verify_buf;
++
++	this->ecc.mode		= NAND_ECC_HW;
++	this->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
++	this->ecc.calculate	= pxa3xx_nand_ecc_calculate;
++	this->ecc.correct	= pxa3xx_nand_ecc_correct;
++	this->ecc.size		= f->page_size;
++
++	if (f->page_size == 2048)
++		this->ecc.layout = &hw_largepage_ecclayout;
++	else
++		this->ecc.layout = &hw_smallpage_ecclayout;
++
++	this->chip_delay = 25;
++}
++
++static int pxa3xx_nand_probe(struct platform_device *pdev)
++{
++	struct pxa3xx_nand_platform_data *pdata;
++	struct pxa3xx_nand_info *info;
++	struct nand_chip *this;
++	struct mtd_info *mtd;
++	struct resource *r;
++	int ret = 0, irq;
++
++	pdata = pdev->dev.platform_data;
++
++	if (!pdata) {
++		dev_err(&pdev->dev, "no platform data defined\n");
++		return -ENODEV;
++	}
++
++	mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
++			GFP_KERNEL);
++	if (!mtd) {
++		dev_err(&pdev->dev, "failed to allocate memory\n");
++		return -ENOMEM;
++	}
++
++	info = (struct pxa3xx_nand_info *)(&mtd[1]);
++	info->pdev = pdev;
++
++	this = &info->nand_chip;
++	mtd->priv = info;
++
++	info->clk = clk_get(&pdev->dev, "NANDCLK");
++	if (IS_ERR(info->clk)) {
++		dev_err(&pdev->dev, "failed to get nand clock\n");
++		ret = PTR_ERR(info->clk);
++		goto fail_free_mtd;
++	}
++	clk_enable(info->clk);
++
++	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
++	if (r == NULL) {
++		dev_err(&pdev->dev, "no resource defined for data DMA\n");
++		ret = -ENXIO;
++		goto fail_put_clk;
++	}
++	info->drcmr_dat = r->start;
++
++	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
++	if (r == NULL) {
++		dev_err(&pdev->dev, "no resource defined for command DMA\n");
++		ret = -ENXIO;
++		goto fail_put_clk;
++	}
++	info->drcmr_cmd = r->start;
++
++	irq = platform_get_irq(pdev, 0);
++	if (irq < 0) {
++		dev_err(&pdev->dev, "no IRQ resource defined\n");
++		ret = -ENXIO;
++		goto fail_put_clk;
++	}
++
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (r == NULL) {
++		dev_err(&pdev->dev, "no IO memory resource defined\n");
++		ret = -ENODEV;
++		goto fail_put_clk;
++	}
++
++	r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
++	if (r == NULL) {
++		dev_err(&pdev->dev, "failed to request memory resource\n");
++		ret = -EBUSY;
++		goto fail_put_clk;
++	}
++
++	info->mmio_base = ioremap(r->start, r->end - r->start + 1);
++	if (info->mmio_base == NULL) {
++		dev_err(&pdev->dev, "ioremap() failed\n");
++		ret = -ENODEV;
++		goto fail_free_res;
++	}
++
++	ret = pxa3xx_nand_init_buff(info);
++	if (ret)
++		goto fail_free_io;
++
++	ret = request_irq(IRQ_NAND, pxa3xx_nand_irq, IRQF_DISABLED,
++				pdev->name, info);
++	if (ret < 0) {
++		dev_err(&pdev->dev, "failed to request IRQ\n");
++		goto fail_free_buf;
++	}
++
++	ret = pxa3xx_nand_detect_flash(info);
++	if (ret) {
++		dev_err(&pdev->dev, "failed to detect flash\n");
++		ret = -ENODEV;
++		goto fail_free_irq;
++	}
++
++	pxa3xx_nand_init_mtd(mtd, info);
++
++	platform_set_drvdata(pdev, mtd);
++
++	if (nand_scan(mtd, 1)) {
++		dev_err(&pdev->dev, "failed to scan nand\n");
++		ret = -ENXIO;
++		goto fail_free_irq;
++	}
++
++	return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
++
++fail_free_irq:
++	free_irq(IRQ_NAND, info);
++fail_free_buf:
++	if (use_dma) {
++		pxa_free_dma(info->data_dma_ch);
++		dma_free_coherent(&pdev->dev, info->data_buff_size,
++			info->data_buff, info->data_buff_phys);
++	} else
++		kfree(info->data_buff);
++fail_free_io:
++	iounmap(info->mmio_base);
++fail_free_res:
++	release_mem_region(r->start, r->end - r->start + 1);
++fail_put_clk:
++	clk_disable(info->clk);
++	clk_put(info->clk);
++fail_free_mtd:
++	kfree(mtd);
++	return ret;
++}
++
++static int pxa3xx_nand_remove(struct platform_device *pdev)
++{
++	struct mtd_info *mtd = platform_get_drvdata(pdev);
++	struct pxa3xx_nand_info *info = mtd->priv;
++
++	platform_set_drvdata(pdev, NULL);
++
++	del_mtd_device(mtd);
++	del_mtd_partitions(mtd);
++	free_irq(IRQ_NAND, info);
++	if (use_dma) {
++		pxa_free_dma(info->data_dma_ch);
++		dma_free_writecombine(&pdev->dev, info->data_buff_size,
++				info->data_buff, info->data_buff_phys);
++	} else
++		kfree(info->data_buff);
++	kfree(mtd);
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
++	struct pxa3xx_nand_info *info = mtd->priv;
++
++	if (info->state != STATE_READY) {
++		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
++		return -EAGAIN;
++	}
++
++	return 0;
++}
++
++static int pxa3xx_nand_resume(struct platform_device *pdev)
++{
++	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
++	struct pxa3xx_nand_info *info = mtd->priv;
++
++	clk_enable(info->clk);
++
++	return pxa3xx_nand_config_flash(info);
++}
++#else
++#define pxa3xx_nand_suspend	NULL
++#define pxa3xx_nand_resume	NULL
++#endif
++
++static struct platform_driver pxa3xx_nand_driver = {
++	.driver = {
++		.name	= "pxa3xx-nand",
++	},
++	.probe		= pxa3xx_nand_probe,
++	.remove		= pxa3xx_nand_remove,
++	.suspend	= pxa3xx_nand_suspend,
++	.resume		= pxa3xx_nand_resume,
++};
++
++static int __init pxa3xx_nand_init(void)
++{
++	return platform_driver_register(&pxa3xx_nand_driver);
++}
++module_init(pxa3xx_nand_init);
++
++static void __exit pxa3xx_nand_exit(void)
++{
++	platform_driver_unregister(&pxa3xx_nand_driver);
++}
++module_exit(pxa3xx_nand_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("PXA3xx NAND controller driver");
+diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
+index 0f6ac25..26f8821 100644
+--- a/drivers/mtd/nand/rtc_from4.c
++++ b/drivers/mtd/nand/rtc_from4.c
+@@ -478,6 +478,7 @@ static int __init rtc_from4_init(void)
+ 	struct nand_chip *this;
+ 	unsigned short bcr1, bcr2, wcr2;
+ 	int i;
++	int ret;
+ 
+ 	/* Allocate memory for MTD device structure and private data */
+ 	rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
+@@ -537,6 +538,22 @@ static int __init rtc_from4_init(void)
+ 	this->ecc.hwctl = rtc_from4_enable_hwecc;
+ 	this->ecc.calculate = rtc_from4_calculate_ecc;
+ 	this->ecc.correct = rtc_from4_correct_data;
++
++	/* We could create the decoder on demand, if memory is a concern.
++	 * This way we have it handy, if an error happens
++	 *
++	 * Symbolsize is 10 (bits)
++	 * Primitve polynomial is x^10+x^3+1
++	 * first consecutive root is 0
++	 * primitve element to generate roots = 1
++	 * generator polinomial degree = 6
++	 */
++	rs_decoder = init_rs(10, 0x409, 0, 1, 6);
++	if (!rs_decoder) {
++		printk(KERN_ERR "Could not create a RS decoder\n");
++		ret = -ENOMEM;
++		goto err_1;
++	}
+ #else
+ 	printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
+ 
+@@ -549,8 +566,8 @@ static int __init rtc_from4_init(void)
+ 
+ 	/* Scan to find existence of the device */
+ 	if (nand_scan(rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) {
+-		kfree(rtc_from4_mtd);
+-		return -ENXIO;
++		ret = -ENXIO;
++		goto err_2;
+ 	}
+ 
+ 	/* Perform 'device recovery' for each chip in case there was a power loss. */
+@@ -566,28 +583,19 @@ static int __init rtc_from4_init(void)
+ #endif
+ 
+ 	/* Register the partitions */
+-	add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
++	ret = add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
++	if (ret)
++		goto err_3;
+ 
+-#ifdef RTC_FROM4_HWECC
+-	/* We could create the decoder on demand, if memory is a concern.
+-	 * This way we have it handy, if an error happens
+-	 *
+-	 * Symbolsize is 10 (bits)
+-	 * Primitve polynomial is x^10+x^3+1
+-	 * first consecutive root is 0
+-	 * primitve element to generate roots = 1
+-	 * generator polinomial degree = 6
+-	 */
+-	rs_decoder = init_rs(10, 0x409, 0, 1, 6);
+-	if (!rs_decoder) {
+-		printk(KERN_ERR "Could not create a RS decoder\n");
+-		nand_release(rtc_from4_mtd);
+-		kfree(rtc_from4_mtd);
+-		return -ENOMEM;
+-	}
+-#endif
+ 	/* Return happy */
+ 	return 0;
++err_3:
++	nand_release(rtc_from4_mtd);
++err_2:
++	free_rs(rs_decoder);
++err_1:
++	kfree(rtc_from4_mtd);
++	return ret;
+ }
+ 
+ module_init(rtc_from4_init);
+diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
+index 9260ad9..b34a460 100644
+--- a/drivers/mtd/nand/s3c2410.c
++++ b/drivers/mtd/nand/s3c2410.c
+@@ -119,8 +119,7 @@ struct s3c2410_nand_info {
+ 	void __iomem			*sel_reg;
+ 	int				sel_bit;
+ 	int				mtd_count;
+-
+-	unsigned long			save_nfconf;
++	unsigned long			save_sel;
+ 
+ 	enum s3c_cpu_type		cpu_type;
+ };
+@@ -358,6 +357,14 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+ 	if (diff0 == 0 && diff1 == 0 && diff2 == 0)
+ 		return 0;		/* ECC is ok */
+ 
++	/* sometimes people do not think about using the ECC, so check
++	 * to see if we have an 0xff,0xff,0xff read ECC and then ignore
++	 * the error, on the assumption that this is an un-eccd page.
++	 */
++	if (read_ecc[0] == 0xff && read_ecc[1] == 0xff && read_ecc[2] == 0xff
++	    && info->platform->ignore_unset_ecc)
++		return 0;
++
+ 	/* Can we correct this ECC (ie, one row and column change).
+ 	 * Note, this is similar to the 256 error code on smartmedia */
+ 
+@@ -473,7 +480,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
+ 	ecc_code[1] = ecc >> 8;
+ 	ecc_code[2] = ecc >> 16;
+ 
+-	pr_debug("%s: returning ecc %06lx\n", __func__, ecc);
++	pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff);
+ 
+ 	return 0;
+ }
+@@ -644,9 +651,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
+ 		chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+ 		chip->ecc.correct   = s3c2410_nand_correct_data;
+ 		chip->ecc.mode	    = NAND_ECC_HW;
+-		chip->ecc.size	    = 512;
+-		chip->ecc.bytes	    = 3;
+-		chip->ecc.layout    = &nand_hw_eccoob;
+ 
+ 		switch (info->cpu_type) {
+ 		case TYPE_S3C2410:
+@@ -668,6 +672,40 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
+ 	} else {
+ 		chip->ecc.mode	    = NAND_ECC_SOFT;
+ 	}
++
++	if (set->ecc_layout != NULL)
++		chip->ecc.layout = set->ecc_layout;
++
++	if (set->disable_ecc)
++		chip->ecc.mode	= NAND_ECC_NONE;
++}
++
++/* s3c2410_nand_update_chip
++ *
++ * post-probe chip update, to change any items, such as the
++ * layout for large page nand
++ */
++
++static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
++				     struct s3c2410_nand_mtd *nmtd)
++{
++	struct nand_chip *chip = &nmtd->chip;
++
++	printk("%s: chip %p: %d\n", __func__, chip, chip->page_shift);
++
++	if (hardware_ecc) {
++		/* change the behaviour depending on wether we are using
++		 * the large or small page nand device */
++
++		if (chip->page_shift > 10) {
++			chip->ecc.size	    = 256;
++			chip->ecc.bytes	    = 3;
++		} else {
++			chip->ecc.size	    = 512;
++			chip->ecc.bytes	    = 3;
++			chip->ecc.layout    = &nand_hw_eccoob;
++		}
++	}
+ }
+ 
+ /* s3c2410_nand_probe
+@@ -776,9 +814,12 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
+ 
+ 		s3c2410_nand_init_chip(info, nmtd, sets);
+ 
+-		nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
++		nmtd->scan_res = nand_scan_ident(&nmtd->mtd,
++						 (sets) ? sets->nr_chips : 1);
+ 
+ 		if (nmtd->scan_res == 0) {
++			s3c2410_nand_update_chip(info, nmtd);
++			nand_scan_tail(&nmtd->mtd);
+ 			s3c2410_nand_add_partition(info, nmtd, sets);
+ 		}
+ 
+@@ -810,15 +851,14 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
+ 	struct s3c2410_nand_info *info = platform_get_drvdata(dev);
+ 
+ 	if (info) {
+-		info->save_nfconf = readl(info->regs + S3C2410_NFCONF);
++		info->save_sel = readl(info->sel_reg);
+ 
+ 		/* For the moment, we must ensure nFCE is high during
+ 		 * the time we are suspended. This really should be
+ 		 * handled by suspending the MTDs we are using, but
+ 		 * that is currently not the case. */
+ 
+-		writel(info->save_nfconf | info->sel_bit,
+-		       info->regs + S3C2410_NFCONF);
++		writel(info->save_sel | info->sel_bit, info->sel_reg);
+ 
+ 		if (!allow_clk_stop(info))
+ 			clk_disable(info->clk);
+@@ -830,7 +870,7 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
+ static int s3c24xx_nand_resume(struct platform_device *dev)
+ {
+ 	struct s3c2410_nand_info *info = platform_get_drvdata(dev);
+-	unsigned long nfconf;
++	unsigned long sel;
+ 
+ 	if (info) {
+ 		clk_enable(info->clk);
+@@ -838,10 +878,10 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
+ 
+ 		/* Restore the state of the nFCE line. */
+ 
+-		nfconf = readl(info->regs + S3C2410_NFCONF);
+-		nfconf &= ~info->sel_bit;
+-		nfconf |= info->save_nfconf & info->sel_bit;
+-		writel(nfconf, info->regs + S3C2410_NFCONF);
++		sel = readl(info->sel_reg);
++		sel &= ~info->sel_bit;
++		sel |= info->save_sel & info->sel_bit;
++		writel(sel, info->sel_reg);
+ 
+ 		if (allow_clk_stop(info))
+ 			clk_disable(info->clk);
+@@ -927,3 +967,6 @@ module_exit(s3c2410_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Ben Dooks <ben at simtec.co.uk>");
+ MODULE_DESCRIPTION("S3C24XX MTD NAND driver");
++MODULE_ALIAS("platform:s3c2410-nand");
++MODULE_ALIAS("platform:s3c2412-nand");
++MODULE_ALIAS("platform:s3c2440-nand");
+diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
+index 0513cbc..345e6ef 100644
+--- a/drivers/mtd/nftlmount.c
++++ b/drivers/mtd/nftlmount.c
+@@ -33,11 +33,6 @@
+ 
+ char nftlmountrev[]="$Revision: 1.41 $";
+ 
+-extern int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+-			 size_t *retlen, uint8_t *buf);
+-extern int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+-			  size_t *retlen, uint8_t *buf);
+-
+ /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
+  *	various device information of the NFTL partition and Bad Unit Table. Update
+  *	the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
+diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
+index f86e069..4f80c2f 100644
+--- a/drivers/mtd/ofpart.c
++++ b/drivers/mtd/ofpart.c
+@@ -72,3 +72,5 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
+ 	return nr_parts;
+ }
+ EXPORT_SYMBOL(of_mtd_parse_partitions);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
+index 8d7d21b..5d7965f 100644
+--- a/drivers/mtd/onenand/onenand_base.c
++++ b/drivers/mtd/onenand/onenand_base.c
+@@ -329,6 +329,21 @@ static int onenand_wait(struct mtd_info *mtd, int state)
+ 		printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl);
+ 		if (ctrl & ONENAND_CTRL_LOCK)
+ 			printk(KERN_ERR "onenand_wait: it's locked error.\n");
++		if (state == FL_READING) {
++			/*
++			 * A power loss while writing can result in a page
++			 * becoming unreadable.  When the device is mounted
++			 * again, reading that page gives controller errors.
++			 * Upper level software like JFFS2 treat -EIO as fatal,
++			 * refusing to mount at all.  That means it is necessary
++			 * to treat the error as an ECC error to allow recovery.
++			 * Note that typically in this case, the eraseblock can
++			 * still be erased and rewritten i.e. it has not become
++			 * a bad block.
++			 */
++			mtd->ecc_stats.failed++;
++			return -EBADMSG;
++		}
+ 		return -EIO;
+ 	}
+ 
+@@ -1336,7 +1351,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
+ 	}
+ 
+ 	/* Reject writes, which are not page aligned */
+-        if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
++        if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
+                 printk(KERN_ERR "onenand_panic_write: Attempt to write not page aligned data\n");
+                 return -EINVAL;
+         }
+@@ -1466,7 +1481,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
+ 	}
+ 
+ 	/* Reject writes, which are not page aligned */
+-        if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
++        if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
+                 printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
+                 return -EINVAL;
+         }
+@@ -2052,7 +2067,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+  *
+  * Check lock status
+  */
+-static void onenand_check_lock_status(struct onenand_chip *this)
++static int onenand_check_lock_status(struct onenand_chip *this)
+ {
+ 	unsigned int value, block, status;
+ 	unsigned int end;
+@@ -2070,9 +2085,13 @@ static void onenand_check_lock_status(struct onenand_chip *this)
+ 
+ 		/* Check lock status */
+ 		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
+-		if (!(status & ONENAND_WP_US))
++		if (!(status & ONENAND_WP_US)) {
+ 			printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
++			return 0;
++		}
+ 	}
++
++	return 1;
+ }
+ 
+ /**
+@@ -2081,9 +2100,11 @@ static void onenand_check_lock_status(struct onenand_chip *this)
+  *
+  * Unlock all blocks
+  */
+-static int onenand_unlock_all(struct mtd_info *mtd)
++static void onenand_unlock_all(struct mtd_info *mtd)
+ {
+ 	struct onenand_chip *this = mtd->priv;
++	loff_t ofs = 0;
++	size_t len = this->chipsize;
+ 
+ 	if (this->options & ONENAND_HAS_UNLOCK_ALL) {
+ 		/* Set start block address */
+@@ -2099,23 +2120,19 @@ static int onenand_unlock_all(struct mtd_info *mtd)
+ 		    & ONENAND_CTRL_ONGO)
+ 			continue;
+ 
++		/* Check lock status */
++		if (onenand_check_lock_status(this))
++			return;
++
+ 		/* Workaround for all block unlock in DDP */
+ 		if (ONENAND_IS_DDP(this)) {
+-			/* 1st block on another chip */
+-			loff_t ofs = this->chipsize >> 1;
+-			size_t len = mtd->erasesize;
+-
+-			onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
++			/* All blocks on another chip */
++			ofs = this->chipsize >> 1;
++			len = this->chipsize >> 1;
+ 		}
+-
+-		onenand_check_lock_status(this);
+-
+-		return 0;
+ 	}
+ 
+-	onenand_do_lock_cmd(mtd, 0x0, this->chipsize, ONENAND_CMD_UNLOCK);
+-
+-	return 0;
++	onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
+ }
+ 
+ #ifdef CONFIG_MTD_ONENAND_OTP
+diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
+index aecdd50..2f53b51 100644
+--- a/drivers/mtd/onenand/onenand_bbt.c
++++ b/drivers/mtd/onenand/onenand_bbt.c
+@@ -17,9 +17,6 @@
+ #include <linux/mtd/onenand.h>
+ #include <linux/mtd/compatmac.h>
+ 
+-extern int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
+-				struct mtd_oob_ops *ops);
+-
+ /**
+  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
+  * @param buf		the buffer to search
+diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
+index 823fba4..c84e454 100644
+--- a/drivers/mtd/rfd_ftl.c
++++ b/drivers/mtd/rfd_ftl.c
+@@ -823,7 +823,7 @@ static void rfd_ftl_remove_dev(struct mtd_blktrans_dev *dev)
+ 	kfree(part);
+ }
+ 
+-struct mtd_blktrans_ops rfd_ftl_tr = {
++static struct mtd_blktrans_ops rfd_ftl_tr = {
+ 	.name		= "rfd",
+ 	.major		= RFD_FTL_MAJOR,
+ 	.part_bits	= PART_BITS,
+diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
+index b9daf15..3f06310 100644
+--- a/drivers/mtd/ubi/Kconfig
++++ b/drivers/mtd/ubi/Kconfig
+@@ -24,8 +24,13 @@ config MTD_UBI_WL_THRESHOLD
+ 	  erase counter value and the lowest erase counter value of eraseblocks
+ 	  of UBI devices. When this threshold is exceeded, UBI starts performing
+ 	  wear leveling by means of moving data from eraseblock with low erase
+-	  counter to eraseblocks with high erase counter. Leave the default
+-	  value if unsure.
++	  counter to eraseblocks with high erase counter.
++
++	  The default value should be OK for SLC NAND flashes, NOR flashes and
++	  other flashes which have eraseblock life-cycle 100000 or more.
++	  However, in case of MLC NAND flashes which typically have eraseblock
++	  life-cycle less then 10000, the threshold should be lessened (e.g.,
++	  to 128 or 256, although it does not have to be power of 2).
+ 
+ config MTD_UBI_BEB_RESERVE
+ 	int "Percentage of reserved eraseblocks for bad eraseblocks handling"
+diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
+index 2759604..961416a 100644
+--- a/drivers/mtd/ubi/build.c
++++ b/drivers/mtd/ubi/build.c
+@@ -606,8 +606,16 @@ static int io_init(struct ubi_device *ubi)
+ 		ubi->ro_mode = 1;
+ 	}
+ 
+-	dbg_msg("leb_size         %d", ubi->leb_size);
+-	dbg_msg("ro_mode          %d", ubi->ro_mode);
++	ubi_msg("physical eraseblock size:   %d bytes (%d KiB)",
++		ubi->peb_size, ubi->peb_size >> 10);
++	ubi_msg("logical eraseblock size:    %d bytes", ubi->leb_size);
++	ubi_msg("smallest flash I/O unit:    %d", ubi->min_io_size);
++	if (ubi->hdrs_min_io_size != ubi->min_io_size)
++		ubi_msg("sub-page size:              %d",
++			ubi->hdrs_min_io_size);
++	ubi_msg("VID header offset:          %d (aligned %d)",
++		ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
++	ubi_msg("data offset:                %d", ubi->leb_start);
+ 
+ 	/*
+ 	 * Note, ideally, we have to initialize ubi->bad_peb_count here. But
+@@ -755,8 +763,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
+ 	mutex_init(&ubi->volumes_mutex);
+ 	spin_lock_init(&ubi->volumes_lock);
+ 
+-	dbg_msg("attaching mtd%d to ubi%d: VID header offset %d",
+-		mtd->index, ubi_num, vid_hdr_offset);
++	ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
+ 
+ 	err = io_init(ubi);
+ 	if (err)
+@@ -804,15 +811,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
+ 	ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
+ 	ubi_msg("MTD device name:            \"%s\"", mtd->name);
+ 	ubi_msg("MTD device size:            %llu MiB", ubi->flash_size >> 20);
+-	ubi_msg("physical eraseblock size:   %d bytes (%d KiB)",
+-		ubi->peb_size, ubi->peb_size >> 10);
+-	ubi_msg("logical eraseblock size:    %d bytes", ubi->leb_size);
+ 	ubi_msg("number of good PEBs:        %d", ubi->good_peb_count);
+ 	ubi_msg("number of bad PEBs:         %d", ubi->bad_peb_count);
+-	ubi_msg("smallest flash I/O unit:    %d", ubi->min_io_size);
+-	ubi_msg("VID header offset:          %d (aligned %d)",
+-		ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
+-	ubi_msg("data offset:                %d", ubi->leb_start);
+ 	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);
+@@ -950,8 +950,7 @@ static int __init ubi_init(void)
+ 	BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
+ 
+ 	if (mtd_devs > UBI_MAX_DEVICES) {
+-		printk(KERN_ERR "UBI error: too many MTD devices, "
+-		       "maximum is %d\n", UBI_MAX_DEVICES);
++		ubi_err("too many MTD devices, maximum is %d", UBI_MAX_DEVICES);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -959,25 +958,25 @@ static int __init ubi_init(void)
+ 	ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);
+ 	if (IS_ERR(ubi_class)) {
+ 		err = PTR_ERR(ubi_class);
+-		printk(KERN_ERR "UBI error: cannot create UBI class\n");
++		ubi_err("cannot create UBI class");
+ 		goto out;
+ 	}
+ 
+ 	err = class_create_file(ubi_class, &ubi_version);
+ 	if (err) {
+-		printk(KERN_ERR "UBI error: cannot create sysfs file\n");
++		ubi_err("cannot create sysfs file");
+ 		goto out_class;
+ 	}
+ 
+ 	err = misc_register(&ubi_ctrl_cdev);
+ 	if (err) {
+-		printk(KERN_ERR "UBI error: cannot register device\n");
++		ubi_err("cannot register device");
+ 		goto out_version;
+ 	}
+ 
+ 	ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
+-						sizeof(struct ubi_wl_entry),
+-						0, 0, NULL);
++					      sizeof(struct ubi_wl_entry),
++					      0, 0, NULL);
+ 	if (!ubi_wl_entry_slab)
+ 		goto out_dev_unreg;
+ 
+@@ -1000,8 +999,7 @@ static int __init ubi_init(void)
+ 		mutex_unlock(&ubi_devices_mutex);
+ 		if (err < 0) {
+ 			put_mtd_device(mtd);
+-			printk(KERN_ERR "UBI error: cannot attach mtd%d\n",
+-			       mtd->index);
++			ubi_err("cannot attach mtd%d", mtd->index);
+ 			goto out_detach;
+ 		}
+ 	}
+@@ -1023,7 +1021,7 @@ out_version:
+ out_class:
+ 	class_destroy(ubi_class);
+ out:
+-	printk(KERN_ERR "UBI error: cannot initialize UBI, error %d\n", err);
++	ubi_err("UBI error: cannot initialize UBI, error %d", err);
+ 	return err;
+ }
+ module_init(ubi_init);
+diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
+index 51c40b1..8ea99d8 100644
+--- a/drivers/mtd/ubi/debug.h
++++ b/drivers/mtd/ubi/debug.h
+@@ -41,7 +41,7 @@
+ /* Generic debugging message */
+ #define dbg_msg(fmt, ...)                                    \
+ 	printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
+-	       current->pid, __FUNCTION__, ##__VA_ARGS__)
++	       current->pid, __func__, ##__VA_ARGS__)
+ 
+ #define ubi_dbg_dump_stack() dump_stack()
+ 
+@@ -99,8 +99,10 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
+ #ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD
+ /* Initialization and build messages */
+ #define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
++#define UBI_IO_DEBUG 1
+ #else
+ #define dbg_bld(fmt, ...) ({})
++#define UBI_IO_DEBUG 0
+ #endif
+ 
+ #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS
+diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
+index d397219..e909b39 100644
+--- a/drivers/mtd/ubi/gluebi.c
++++ b/drivers/mtd/ubi/gluebi.c
+@@ -291,11 +291,12 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
+ 	/*
+ 	 * In case of dynamic volume, MTD device size is just volume size. In
+ 	 * case of a static volume the size is equivalent to the amount of data
+-	 * bytes, which is zero at this moment and will be changed after volume
+-	 * update.
++	 * bytes.
+ 	 */
+ 	if (vol->vol_type == UBI_DYNAMIC_VOLUME)
+ 		mtd->size = vol->usable_leb_size * vol->reserved_pebs;
++	else
++		mtd->size = vol->used_bytes;
+ 
+ 	if (add_mtd_device(mtd)) {
+ 		ubi_err("cannot not add MTD device\n");
+diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
+index db3efde..4ac11df 100644
+--- a/drivers/mtd/ubi/io.c
++++ b/drivers/mtd/ubi/io.c
+@@ -631,6 +631,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
+ 
+ 	dbg_io("read EC header from PEB %d", pnum);
+ 	ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
++	if (UBI_IO_DEBUG)
++		verbose = 1;
+ 
+ 	err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
+ 	if (err) {
+@@ -904,6 +906,8 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
+ 
+ 	dbg_io("read VID header from PEB %d", pnum);
+ 	ubi_assert(pnum >= 0 &&  pnum < ubi->peb_count);
++	if (UBI_IO_DEBUG)
++		verbose = 1;
+ 
+ 	p = (char *)vid_hdr - ubi->vid_hdr_shift;
+ 	err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
+diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
+index 05aa3e7..96d410e 100644
+--- a/drivers/mtd/ubi/scan.c
++++ b/drivers/mtd/ubi/scan.c
+@@ -42,6 +42,7 @@
+ 
+ #include <linux/err.h>
+ #include <linux/crc32.h>
++#include <asm/div64.h>
+ #include "ubi.h"
+ 
+ #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+@@ -92,27 +93,6 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
+ }
+ 
+ /**
+- * commit_to_mean_value - commit intermediate results to the final mean erase
+- * counter value.
+- * @si: scanning information
+- *
+- * This is a helper function which calculates partial mean erase counter mean
+- * value and adds it to the resulting mean value. As we can work only in
+- * integer arithmetic and we want to calculate the mean value of erase counter
+- * accurately, we first sum erase counter values in @si->ec_sum variable and
+- * count these components in @si->ec_count. If this temporary @si->ec_sum is
+- * going to overflow, we calculate the partial mean value
+- * (@si->ec_sum/@si->ec_count) and add it to @si->mean_ec.
+- */
+-static void commit_to_mean_value(struct ubi_scan_info *si)
+-{
+-	si->ec_sum /= si->ec_count;
+-	if (si->ec_sum % si->ec_count >= si->ec_count / 2)
+-		si->mean_ec += 1;
+-	si->mean_ec += si->ec_sum;
+-}
+-
+-/**
+  * validate_vid_hdr - check that volume identifier header is correct and
+  * consistent.
+  * @vid_hdr: the volume identifier header to check
+@@ -901,15 +881,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
+ 
+ adjust_mean_ec:
+ 	if (!ec_corr) {
+-		if (si->ec_sum + ec < ec) {
+-			commit_to_mean_value(si);
+-			si->ec_sum = 0;
+-			si->ec_count = 0;
+-		} else {
+-			si->ec_sum += ec;
+-			si->ec_count += 1;
+-		}
+-
++		si->ec_sum += ec;
++		si->ec_count += 1;
+ 		if (ec > si->max_ec)
+ 			si->max_ec = ec;
+ 		if (ec < si->min_ec)
+@@ -965,9 +938,11 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
+ 
+ 	dbg_msg("scanning is finished");
+ 
+-	/* Finish mean erase counter calculations */
+-	if (si->ec_count)
+-		commit_to_mean_value(si);
++	/* Calculate mean erase counter */
++	if (si->ec_count) {
++		do_div(si->ec_sum, si->ec_count);
++		si->mean_ec = si->ec_sum;
++	}
+ 
+ 	if (si->is_empty)
+ 		ubi_msg("empty MTD device detected");
+diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
+index 46d444a..966b9b6 100644
+--- a/drivers/mtd/ubi/scan.h
++++ b/drivers/mtd/ubi/scan.h
+@@ -124,7 +124,7 @@ struct ubi_scan_info {
+ 	int max_ec;
+ 	unsigned long long max_sqnum;
+ 	int mean_ec;
+-	int ec_sum;
++	uint64_t ec_sum;
+ 	int ec_count;
+ };
+ 
+diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
+new file mode 100644
+index 0000000..c3185d9
+--- /dev/null
++++ b/drivers/mtd/ubi/ubi-media.h
+@@ -0,0 +1,372 @@
++/*
++ * Copyright (c) International Business Machines Corp., 2006
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ * the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public 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: Artem Bityutskiy (Битюцкий Артём)
++ *          Thomas Gleixner
++ *          Frank Haverkamp
++ *          Oliver Lohmann
++ *          Andreas Arnez
++ */
++
++/*
++ * This file defines the layout of UBI headers and all the other UBI on-flash
++ * data structures.
++ */
++
++#ifndef __UBI_MEDIA_H__
++#define __UBI_MEDIA_H__
++
++#include <asm/byteorder.h>
++
++/* The version of UBI images supported by this implementation */
++#define UBI_VERSION 1
++
++/* The highest erase counter value supported by this implementation */
++#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
++
++/* The initial CRC32 value used when calculating CRC checksums */
++#define UBI_CRC32_INIT 0xFFFFFFFFU
++
++/* Erase counter header magic number (ASCII "UBI#") */
++#define UBI_EC_HDR_MAGIC  0x55424923
++/* Volume identifier header magic number (ASCII "UBI!") */
++#define UBI_VID_HDR_MAGIC 0x55424921
++
++/*
++ * Volume type constants used in the volume identifier header.
++ *
++ * @UBI_VID_DYNAMIC: dynamic volume
++ * @UBI_VID_STATIC: static volume
++ */
++enum {
++	UBI_VID_DYNAMIC = 1,
++	UBI_VID_STATIC  = 2
++};
++
++/*
++ * Volume flags used in the volume table record.
++ *
++ * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
++ *
++ * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
++ * table. UBI automatically re-sizes the volume which has this flag and makes
++ * the volume to be of largest possible size. This means that if after the
++ * initialization UBI finds out that there are available physical eraseblocks
++ * present on the device, it automatically appends all of them to the volume
++ * (the physical eraseblocks reserved for bad eraseblocks handling and other
++ * reserved physical eraseblocks are not taken). So, if there is a volume with
++ * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical
++ * eraseblocks will be zero after UBI is loaded, because all of them will be
++ * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared
++ * after the volume had been initialized.
++ *
++ * The auto-resize feature is useful for device production purposes. For
++ * example, different NAND flash chips may have different amount of initial bad
++ * eraseblocks, depending of particular chip instance. Manufacturers of NAND
++ * chips usually guarantee that the amount of initial bad eraseblocks does not
++ * exceed certain percent, e.g. 2%. When one creates an UBI image which will be
++ * flashed to the end devices in production, he does not know the exact amount
++ * of good physical eraseblocks the NAND chip on the device will have, but this
++ * number is required to calculate the volume sized and put them to the volume
++ * table of the UBI image. In this case, one of the volumes (e.g., the one
++ * which will store the root file system) is marked as "auto-resizable", and
++ * UBI will adjust its size on the first boot if needed.
++ *
++ * Note, first UBI reserves some amount of physical eraseblocks for bad
++ * eraseblock handling, and then re-sizes the volume, not vice-versa. This
++ * means that the pool of reserved physical eraseblocks will always be present.
++ */
++enum {
++	UBI_VTBL_AUTORESIZE_FLG = 0x01,
++};
++
++/*
++ * Compatibility constants used by internal volumes.
++ *
++ * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
++ * to the flash
++ * @UBI_COMPAT_RO: attach this device in read-only mode
++ * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
++ * physical eraseblocks, don't allow the wear-leveling unit to move them
++ * @UBI_COMPAT_REJECT: reject this UBI image
++ */
++enum {
++	UBI_COMPAT_DELETE   = 1,
++	UBI_COMPAT_RO       = 2,
++	UBI_COMPAT_PRESERVE = 4,
++	UBI_COMPAT_REJECT   = 5
++};
++
++/* Sizes of UBI headers */
++#define UBI_EC_HDR_SIZE  sizeof(struct ubi_ec_hdr)
++#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
++
++/* Sizes of UBI headers without the ending CRC */
++#define UBI_EC_HDR_SIZE_CRC  (UBI_EC_HDR_SIZE  - sizeof(__be32))
++#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32))
++
++/**
++ * struct ubi_ec_hdr - UBI erase counter header.
++ * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
++ * @version: version of UBI implementation which is supposed to accept this
++ * UBI image
++ * @padding1: reserved for future, zeroes
++ * @ec: the erase counter
++ * @vid_hdr_offset: where the VID header starts
++ * @data_offset: where the user data start
++ * @padding2: reserved for future, zeroes
++ * @hdr_crc: erase counter header CRC checksum
++ *
++ * The erase counter header takes 64 bytes and has a plenty of unused space for
++ * future usage. The unused fields are zeroed. The @version field is used to
++ * indicate the version of UBI implementation which is supposed to be able to
++ * work with this UBI image. If @version is greater then the current UBI
++ * version, the image is rejected. This may be useful in future if something
++ * is changed radically. This field is duplicated in the volume identifier
++ * header.
++ *
++ * The @vid_hdr_offset and @data_offset fields contain the offset of the the
++ * volume identifier header and user data, relative to the beginning of the
++ * physical eraseblock. These values have to be the same for all physical
++ * eraseblocks.
++ */
++struct ubi_ec_hdr {
++	__be32  magic;
++	__u8    version;
++	__u8    padding1[3];
++	__be64  ec; /* Warning: the current limit is 31-bit anyway! */
++	__be32  vid_hdr_offset;
++	__be32  data_offset;
++	__u8    padding2[36];
++	__be32  hdr_crc;
++} __attribute__ ((packed));
++
++/**
++ * struct ubi_vid_hdr - on-flash UBI volume identifier header.
++ * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
++ * @version: UBI implementation version which is supposed to accept this UBI
++ * image (%UBI_VERSION)
++ * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
++ * @copy_flag: if this logical eraseblock was copied from another physical
++ * eraseblock (for wear-leveling reasons)
++ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
++ * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
++ * @vol_id: ID of this volume
++ * @lnum: logical eraseblock number
++ * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
++ * removed, kept only for not breaking older UBI users)
++ * @data_size: how many bytes of data this logical eraseblock contains
++ * @used_ebs: total number of used logical eraseblocks in this volume
++ * @data_pad: how many bytes at the end of this physical eraseblock are not
++ * used
++ * @data_crc: CRC checksum of the data stored in this logical eraseblock
++ * @padding1: reserved for future, zeroes
++ * @sqnum: sequence number
++ * @padding2: reserved for future, zeroes
++ * @hdr_crc: volume identifier header CRC checksum
++ *
++ * The @sqnum is the value of the global sequence counter at the time when this
++ * VID header was created. The global sequence counter is incremented each time
++ * UBI writes a new VID header to the flash, i.e. when it maps a logical
++ * eraseblock to a new physical eraseblock. The global sequence counter is an
++ * unsigned 64-bit integer and we assume it never overflows. The @sqnum
++ * (sequence number) is used to distinguish between older and newer versions of
++ * logical eraseblocks.
++ *
++ * There are 2 situations when there may be more then one physical eraseblock
++ * corresponding to the same logical eraseblock, i.e., having the same @vol_id
++ * and @lnum values in the volume identifier header. Suppose we have a logical
++ * eraseblock L and it is mapped to the physical eraseblock P.
++ *
++ * 1. Because UBI may erase physical eraseblocks asynchronously, the following
++ * situation is possible: L is asynchronously erased, so P is scheduled for
++ * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
++ * so P1 is written to, then an unclean reboot happens. Result - there are 2
++ * physical eraseblocks P and P1 corresponding to the same logical eraseblock
++ * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
++ * flash.
++ *
++ * 2. From time to time UBI moves logical eraseblocks to other physical
++ * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
++ * to P1, and an unclean reboot happens before P is physically erased, there
++ * are two physical eraseblocks P and P1 corresponding to L and UBI has to
++ * select one of them when the flash is attached. The @sqnum field says which
++ * PEB is the original (obviously P will have lower @sqnum) and the copy. But
++ * it is not enough to select the physical eraseblock with the higher sequence
++ * number, because the unclean reboot could have happen in the middle of the
++ * copying process, so the data in P is corrupted. It is also not enough to
++ * just select the physical eraseblock with lower sequence number, because the
++ * data there may be old (consider a case if more data was added to P1 after
++ * the copying). Moreover, the unclean reboot may happen when the erasure of P
++ * was just started, so it result in unstable P, which is "mostly" OK, but
++ * still has unstable bits.
++ *
++ * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
++ * copy. UBI also calculates data CRC when the data is moved and stores it at
++ * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
++ * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
++ * examined. If it is cleared, the situation* is simple and the newer one is
++ * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
++ * checksum is correct, this physical eraseblock is selected (P1). Otherwise
++ * the older one (P) is selected.
++ *
++ * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
++ * in the past. But it is not used anymore and we keep it in order to be able
++ * to deal with old UBI images. It will be removed at some point.
++ *
++ * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
++ * Internal volumes are not seen from outside and are used for various internal
++ * UBI purposes. In this implementation there is only one internal volume - the
++ * layout volume. Internal volumes are the main mechanism of UBI extensions.
++ * For example, in future one may introduce a journal internal volume. Internal
++ * volumes have their own reserved range of IDs.
++ *
++ * The @compat field is only used for internal volumes and contains the "degree
++ * of their compatibility". It is always zero for user volumes. This field
++ * provides a mechanism to introduce UBI extensions and to be still compatible
++ * with older UBI binaries. For example, if someone introduced a journal in
++ * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
++ * journal volume.  And in this case, older UBI binaries, which know nothing
++ * about the journal volume, would just delete this volume and work perfectly
++ * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
++ * - it just ignores the Ext3fs journal.
++ *
++ * The @data_crc field contains the CRC checksum of the contents of the logical
++ * eraseblock if this is a static volume. In case of dynamic volumes, it does
++ * not contain the CRC checksum as a rule. The only exception is when the
++ * data of the physical eraseblock was moved by the wear-leveling unit, then
++ * the wear-leveling unit calculates the data CRC and stores it in the
++ * @data_crc field. And of course, the @copy_flag is %in this case.
++ *
++ * The @data_size field is used only for static volumes because UBI has to know
++ * how many bytes of data are stored in this eraseblock. For dynamic volumes,
++ * this field usually contains zero. The only exception is when the data of the
++ * physical eraseblock was moved to another physical eraseblock for
++ * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
++ * contents and uses both @data_crc and @data_size fields. In this case, the
++ * @data_size field contains data size.
++ *
++ * The @used_ebs field is used only for static volumes and indicates how many
++ * eraseblocks the data of the volume takes. For dynamic volumes this field is
++ * not used and always contains zero.
++ *
++ * The @data_pad is calculated when volumes are created using the alignment
++ * parameter. So, effectively, the @data_pad field reduces the size of logical
++ * eraseblocks of this volume. This is very handy when one uses block-oriented
++ * software (say, cramfs) on top of the UBI volume.
++ */
++struct ubi_vid_hdr {
++	__be32  magic;
++	__u8    version;
++	__u8    vol_type;
++	__u8    copy_flag;
++	__u8    compat;
++	__be32  vol_id;
++	__be32  lnum;
++	__be32  leb_ver; /* obsolete, to be removed, don't use */
++	__be32  data_size;
++	__be32  used_ebs;
++	__be32  data_pad;
++	__be32  data_crc;
++	__u8    padding1[4];
++	__be64  sqnum;
++	__u8    padding2[12];
++	__be32  hdr_crc;
++} __attribute__ ((packed));
++
++/* Internal UBI volumes count */
++#define UBI_INT_VOL_COUNT 1
++
++/*
++ * Starting ID of internal volumes. There is reserved room for 4096 internal
++ * volumes.
++ */
++#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
++
++/* The layout volume contains the volume table */
++
++#define UBI_LAYOUT_VOLUME_ID     UBI_INTERNAL_VOL_START
++#define UBI_LAYOUT_VOLUME_TYPE   UBI_VID_DYNAMIC
++#define UBI_LAYOUT_VOLUME_ALIGN  1
++#define UBI_LAYOUT_VOLUME_EBS    2
++#define UBI_LAYOUT_VOLUME_NAME   "layout volume"
++#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
++
++/* The maximum number of volumes per one UBI device */
++#define UBI_MAX_VOLUMES 128
++
++/* The maximum volume name length */
++#define UBI_VOL_NAME_MAX 127
++
++/* Size of the volume table record */
++#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
++
++/* Size of the volume table record without the ending CRC */
++#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32))
++
++/**
++ * struct ubi_vtbl_record - a record in the volume table.
++ * @reserved_pebs: how many physical eraseblocks are reserved for this volume
++ * @alignment: volume alignment
++ * @data_pad: how many bytes are unused at the end of the each physical
++ * eraseblock to satisfy the requested alignment
++ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
++ * @upd_marker: if volume update was started but not finished
++ * @name_len: volume name length
++ * @name: the volume name
++ * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
++ * @padding: reserved, zeroes
++ * @crc: a CRC32 checksum of the record
++ *
++ * The volume table records are stored in the volume table, which is stored in
++ * the layout volume. The layout volume consists of 2 logical eraseblock, each
++ * of which contains a copy of the volume table (i.e., the volume table is
++ * duplicated). The volume table is an array of &struct ubi_vtbl_record
++ * objects indexed by the volume ID.
++ *
++ * If the size of the logical eraseblock is large enough to fit
++ * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
++ * records. Otherwise, it contains as many records as it can fit (i.e., size of
++ * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
++ *
++ * The @upd_marker flag is used to implement volume update. It is set to %1
++ * before update and set to %0 after the update. So if the update operation was
++ * interrupted, UBI knows that the volume is corrupted.
++ *
++ * The @alignment field is specified when the volume is created and cannot be
++ * later changed. It may be useful, for example, when a block-oriented file
++ * system works on top of UBI. The @data_pad field is calculated using the
++ * logical eraseblock size and @alignment. The alignment must be multiple to the
++ * minimal flash I/O unit. If @alignment is 1, all the available space of
++ * the physical eraseblocks is used.
++ *
++ * Empty records contain all zeroes and the CRC checksum of those zeroes.
++ */
++struct ubi_vtbl_record {
++	__be32  reserved_pebs;
++	__be32  alignment;
++	__be32  data_pad;
++	__u8    vol_type;
++	__u8    upd_marker;
++	__be16  name_len;
++	__u8    name[UBI_VOL_NAME_MAX+1];
++	__u8    flags;
++	__u8    padding[23];
++	__be32  crc;
++} __attribute__ ((packed));
++
++#endif /* !__UBI_MEDIA_H__ */
+diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
+index a548c1d..67dcbd1 100644
+--- a/drivers/mtd/ubi/ubi.h
++++ b/drivers/mtd/ubi/ubi.h
+@@ -37,10 +37,9 @@
+ #include <linux/string.h>
+ #include <linux/vmalloc.h>
+ #include <linux/mtd/mtd.h>
+-
+-#include <mtd/ubi-header.h>
+ #include <linux/mtd/ubi.h>
+ 
++#include "ubi-media.h"
+ #include "scan.h"
+ #include "debug.h"
+ 
+@@ -54,10 +53,10 @@
+ #define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__)
+ /* UBI warning messages */
+ #define ubi_warn(fmt, ...) printk(KERN_WARNING "UBI warning: %s: " fmt "\n", \
+-				  __FUNCTION__, ##__VA_ARGS__)
++				  __func__, ##__VA_ARGS__)
+ /* UBI error messages */
+ #define ubi_err(fmt, ...) printk(KERN_ERR "UBI error: %s: " fmt "\n", \
+-				 __FUNCTION__, ##__VA_ARGS__)
++				 __func__, ##__VA_ARGS__)
+ 
+ /* Lowest number PEBs reserved for bad PEB handling */
+ #define MIN_RESEVED_PEBS 2
+diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
+index 8fafac9..54dac06 100644
+--- a/drivers/net/3c509.c
++++ b/drivers/net/3c509.c
+@@ -54,25 +54,24 @@
+ 		v1.19a 28Oct2002 Davud Ruggiero <jdr at farfalle.com>
+ 			- Increase *read_eeprom udelay to workaround oops with 2 cards.
+ 		v1.19b 08Nov2002 Marc Zyngier <maz at wild-wind.fr.eu.org>
+-		    - Introduce driver model for EISA cards.
++			- Introduce driver model for EISA cards.
++		v1.20  04Feb2008 Ondrej Zary <linux at rainbow-software.org>
++			- convert to isa_driver and pnp_driver and some cleanups
+ */
+ 
+ #define DRV_NAME	"3c509"
+-#define DRV_VERSION	"1.19b"
+-#define DRV_RELDATE	"08Nov2002"
++#define DRV_VERSION	"1.20"
++#define DRV_RELDATE	"04Feb2008"
+ 
+ /* A few values that may be tweaked. */
+ 
+ /* Time in jiffies before concluding the transmitter is hung. */
+ #define TX_TIMEOUT  (400*HZ/1000)
+-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+-static int max_interrupt_work = 10;
+ 
+ #include <linux/module.h>
+-#ifdef CONFIG_MCA
+ #include <linux/mca.h>
+-#endif
+-#include <linux/isapnp.h>
++#include <linux/isa.h>
++#include <linux/pnp.h>
+ #include <linux/string.h>
+ #include <linux/interrupt.h>
+ #include <linux/errno.h>
+@@ -97,10 +96,6 @@ static int max_interrupt_work = 10;
+ 
+ static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker at scyld.com\n";
+ 
+-#if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA))
+-#define EL3_SUSPEND
+-#endif
+-
+ #ifdef EL3_DEBUG
+ static int el3_debug = EL3_DEBUG;
+ #else
+@@ -111,6 +106,7 @@ static int el3_debug = 2;
+  * a global variable so that the mca/eisa probe routines can increment
+  * it */
+ static int el3_cards = 0;
++#define EL3_MAX_CARDS 8
+ 
+ /* To minimize the size of the driver source I only define operating
+    constants if they are used several times.  You'll need the manual
+@@ -119,7 +115,7 @@ static int el3_cards = 0;
+ #define EL3_DATA 0x00
+ #define EL3_CMD 0x0e
+ #define EL3_STATUS 0x0e
+-#define	 EEPROM_READ 0x80
++#define	EEPROM_READ 0x80
+ 
+ #define EL3_IO_EXTENT	16
+ 
+@@ -168,23 +164,31 @@ enum RxFilter {
+  */
+ #define SKB_QUEUE_SIZE	64
+ 
++enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA };
++
+ struct el3_private {
+ 	struct net_device_stats stats;
+-	struct net_device *next_dev;
+ 	spinlock_t lock;
+ 	/* skb send-queue */
+ 	int head, size;
+ 	struct sk_buff *queue[SKB_QUEUE_SIZE];
+-	enum {
+-		EL3_MCA,
+-		EL3_PNP,
+-		EL3_EISA,
+-	} type;						/* type of device */
+-	struct device *dev;
++	enum el3_cardtype type;
+ };
+-static int id_port __initdata = 0x110;	/* Start with 0x110 to avoid new sound cards.*/
+-static struct net_device *el3_root_dev;
++static int id_port;
++static int current_tag;
++static struct net_device *el3_devs[EL3_MAX_CARDS];
++
++/* Parameters that may be passed into the module. */
++static int debug = -1;
++static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
++/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
++static int max_interrupt_work = 10;
++#ifdef CONFIG_PNP
++static int nopnp;
++#endif
+ 
++static int __init el3_common_init(struct net_device *dev);
++static void el3_common_remove(struct net_device *dev);
+ static ushort id_read_eeprom(int index);
+ static ushort read_eeprom(int ioaddr, int index);
+ static int el3_open(struct net_device *dev);
+@@ -199,7 +203,7 @@ static void el3_tx_timeout (struct net_device *dev);
+ static void el3_down(struct net_device *dev);
+ static void el3_up(struct net_device *dev);
+ static const struct ethtool_ops ethtool_ops;
+-#ifdef EL3_SUSPEND
++#ifdef CONFIG_PM
+ static int el3_suspend(struct device *, pm_message_t);
+ static int el3_resume(struct device *);
+ #else
+@@ -209,13 +213,272 @@ static int el3_resume(struct device *);
+ 
+ 
+ /* generic device remove for all device types */
+-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ static int el3_device_remove (struct device *device);
+-#endif
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void el3_poll_controller(struct net_device *dev);
+ #endif
+ 
++/* Return 0 on success, 1 on error, 2 when found already detected PnP card */
++static int el3_isa_id_sequence(__be16 *phys_addr)
++{
++	short lrs_state = 0xff;
++	int i;
++
++	/* ISA boards are detected by sending the ID sequence to the
++	   ID_PORT.  We find cards past the first by setting the 'current_tag'
++	   on cards as they are found.  Cards with their tag set will not
++	   respond to subsequent ID sequences. */
++
++	outb(0x00, id_port);
++	outb(0x00, id_port);
++	for (i = 0; i < 255; i++) {
++		outb(lrs_state, id_port);
++		lrs_state <<= 1;
++		lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
++	}
++	/* For the first probe, clear all board's tag registers. */
++	if (current_tag == 0)
++		outb(0xd0, id_port);
++	else			/* Otherwise kill off already-found boards. */
++		outb(0xd8, id_port);
++	if (id_read_eeprom(7) != 0x6d50)
++		return 1;
++	/* Read in EEPROM data, which does contention-select.
++	   Only the lowest address board will stay "on-line".
++	   3Com got the byte order backwards. */
++	for (i = 0; i < 3; i++)
++		phys_addr[i] = htons(id_read_eeprom(i));
++#ifdef CONFIG_PNP
++	if (!nopnp) {
++		/* The ISA PnP 3c509 cards respond to the ID sequence too.
++		   This check is needed in order not to register them twice. */
++		for (i = 0; i < el3_cards; i++) {
++			struct el3_private *lp = netdev_priv(el3_devs[i]);
++			if (lp->type == EL3_PNP
++			    && !memcmp(phys_addr, el3_devs[i]->dev_addr,
++				       ETH_ALEN)) {
++				if (el3_debug > 3)
++					printk(KERN_DEBUG "3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
++						phys_addr[0] & 0xff, phys_addr[0] >> 8,
++						phys_addr[1] & 0xff, phys_addr[1] >> 8,
++						phys_addr[2] & 0xff, phys_addr[2] >> 8);
++				/* Set the adaptor tag so that the next card can be found. */
++				outb(0xd0 + ++current_tag, id_port);
++				return 2;
++			}
++		}
++	}
++#endif /* CONFIG_PNP */
++	return 0;
++
++}
++
++static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
++				   int ioaddr, int irq, int if_port,
++				   enum el3_cardtype type)
++{
++	struct el3_private *lp = netdev_priv(dev);
++
++	memcpy(dev->dev_addr, phys_addr, ETH_ALEN);
++	dev->base_addr = ioaddr;
++	dev->irq = irq;
++	dev->if_port = if_port;
++	lp->type = type;
++}
++
++static int __devinit el3_isa_match(struct device *pdev,
++				   unsigned int ndev)
++{
++	struct net_device *dev;
++	int ioaddr, isa_irq, if_port, err;
++	unsigned int iobase;
++	__be16 phys_addr[3];
++
++	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
++		;	/* Skip to next card when PnP card found */
++	if (err == 1)
++		return 0;
++
++	iobase = id_read_eeprom(8);
++	if_port = iobase >> 14;
++	ioaddr = 0x200 + ((iobase & 0x1f) << 4);
++	if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
++		isa_irq = irq[el3_cards];
++	else
++		isa_irq = id_read_eeprom(9) >> 12;
++
++	dev = alloc_etherdev(sizeof(struct el3_private));
++	if (!dev)
++		return -ENOMEM;
++
++	netdev_boot_setup_check(dev);
++
++	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
++		free_netdev(dev);
++		return 0;
++	}
++
++	/* Set the adaptor tag so that the next card can be found. */
++	outb(0xd0 + ++current_tag, id_port);
++
++	/* Activate the adaptor at the EEPROM location. */
++	outb((ioaddr >> 4) | 0xe0, id_port);
++
++	EL3WINDOW(0);
++	if (inw(ioaddr) != 0x6d50) {
++		free_netdev(dev);
++		return 0;
++	}
++
++	/* Free the interrupt so that some other card can use it. */
++	outw(0x0f00, ioaddr + WN0_IRQ);
++
++	el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
++	dev_set_drvdata(pdev, dev);
++	if (el3_common_init(dev)) {
++		free_netdev(dev);
++		return 0;
++	}
++
++	el3_devs[el3_cards++] = dev;
++	return 1;
++}
++
++static int __devexit el3_isa_remove(struct device *pdev,
++				    unsigned int ndev)
++{
++	el3_device_remove(pdev);
++	dev_set_drvdata(pdev, NULL);
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int el3_isa_suspend(struct device *dev, unsigned int n,
++			   pm_message_t state)
++{
++	current_tag = 0;
++	return el3_suspend(dev, state);
++}
++
++static int el3_isa_resume(struct device *dev, unsigned int n)
++{
++	struct net_device *ndev = dev_get_drvdata(dev);
++	int ioaddr = ndev->base_addr, err;
++	__be16 phys_addr[3];
++
++	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
++		;	/* Skip to next card when PnP card found */
++	if (err == 1)
++		return 0;
++	/* Set the adaptor tag so that the next card can be found. */
++	outb(0xd0 + ++current_tag, id_port);
++	/* Enable the card */
++	outb((ioaddr >> 4) | 0xe0, id_port);
++	EL3WINDOW(0);
++	if (inw(ioaddr) != 0x6d50)
++		return 1;
++	/* Free the interrupt so that some other card can use it. */
++	outw(0x0f00, ioaddr + WN0_IRQ);
++	return el3_resume(dev);
++}
++#endif
++
++static struct isa_driver el3_isa_driver = {
++	.match		= el3_isa_match,
++	.remove		= __devexit_p(el3_isa_remove),
++#ifdef CONFIG_PM
++	.suspend	= el3_isa_suspend,
++	.resume		= el3_isa_resume,
++#endif
++	.driver		= {
++		.name	= "3c509"
++	},
++};
++static int isa_registered;
++
++#ifdef CONFIG_PNP
++static struct pnp_device_id el3_pnp_ids[] = {
++	{ .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
++	{ .id = "TCM5091" }, /* 3Com Etherlink III */
++	{ .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
++	{ .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
++	{ .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
++	{ .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
++	{ .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
++	{ .id = "" }
++};
++MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
++
++static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
++				    const struct pnp_device_id *id)
++{
++	short i;
++	int ioaddr, irq, if_port;
++	u16 phys_addr[3];
++	struct net_device *dev = NULL;
++	int err;
++
++	ioaddr = pnp_port_start(pdev, 0);
++	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
++		return -EBUSY;
++	irq = pnp_irq(pdev, 0);
++	EL3WINDOW(0);
++	for (i = 0; i < 3; i++)
++		phys_addr[i] = htons(read_eeprom(ioaddr, i));
++	if_port = read_eeprom(ioaddr, 8) >> 14;
++	dev = alloc_etherdev(sizeof(struct el3_private));
++	if (!dev) {
++		release_region(ioaddr, EL3_IO_EXTENT);
++		return -ENOMEM;
++	}
++	SET_NETDEV_DEV(dev, &pdev->dev);
++	netdev_boot_setup_check(dev);
++
++	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
++	pnp_set_drvdata(pdev, dev);
++	err = el3_common_init(dev);
++
++	if (err) {
++		pnp_set_drvdata(pdev, NULL);
++		free_netdev(dev);
++		return err;
++	}
++
++	el3_devs[el3_cards++] = dev;
++	return 0;
++}
++
++static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
++{
++	el3_common_remove(pnp_get_drvdata(pdev));
++	pnp_set_drvdata(pdev, NULL);
++}
++
++#ifdef CONFIG_PM
++static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
++{
++	return el3_suspend(&pdev->dev, state);
++}
++
++static int el3_pnp_resume(struct pnp_dev *pdev)
++{
++	return el3_resume(&pdev->dev);
++}
++#endif
++
++static struct pnp_driver el3_pnp_driver = {
++	.name		= "3c509",
++	.id_table	= el3_pnp_ids,
++	.probe		= el3_pnp_probe,
++	.remove		= __devexit_p(el3_pnp_remove),
++#ifdef CONFIG_PM
++	.suspend	= el3_pnp_suspend,
++	.resume		= el3_pnp_resume,
++#endif
++};
++static int pnp_registered;
++#endif /* CONFIG_PNP */
++
+ #ifdef CONFIG_EISA
+ static struct eisa_device_id el3_eisa_ids[] = {
+ 		{ "TCM5092" },
+@@ -230,13 +493,14 @@ static int el3_eisa_probe (struct device *device);
+ static struct eisa_driver el3_eisa_driver = {
+ 		.id_table = el3_eisa_ids,
+ 		.driver   = {
+-				.name    = "3c509",
++				.name    = "3c579",
+ 				.probe   = el3_eisa_probe,
+ 				.remove  = __devexit_p (el3_device_remove),
+ 				.suspend = el3_suspend,
+ 				.resume  = el3_resume,
+ 		}
+ };
++static int eisa_registered;
+ #endif
+ 
+ #ifdef CONFIG_MCA
+@@ -271,45 +535,9 @@ static struct mca_driver el3_mca_driver = {
+ 				.resume  = el3_resume,
+ 		},
+ };
++static int mca_registered;
+ #endif /* CONFIG_MCA */
+ 
+-#if defined(__ISAPNP__)
+-static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
+-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
+-		(long) "3Com Etherlink III (TP)" },
+-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5091),
+-		(long) "3Com Etherlink III" },
+-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5094),
+-		(long) "3Com Etherlink III (combo)" },
+-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5095),
+-		(long) "3Com Etherlink III (TPO)" },
+-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5098),
+-		(long) "3Com Etherlink III (TPC)" },
+-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+-		ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f7),
+-		(long) "3Com Etherlink III compatible" },
+-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+-		ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f8),
+-		(long) "3Com Etherlink III compatible" },
+-	{ }	/* terminate list */
+-};
+-
+-static __be16 el3_isapnp_phys_addr[8][3];
+-static int nopnp;
+-#endif /* __ISAPNP__ */
+-
+-/* With the driver model introduction for EISA devices, both init
+- * and cleanup have been split :
+- * - EISA devices probe/remove starts in el3_eisa_probe/el3_device_remove
+- * - MCA/ISA still use el3_probe
+- *
+- * Both call el3_common_init/el3_common_remove. */
+-
+ static int __init el3_common_init(struct net_device *dev)
+ {
+ 	struct el3_private *lp = netdev_priv(dev);
+@@ -360,231 +588,11 @@ static int __init el3_common_init(struct net_device *dev)
+ 
+ static void el3_common_remove (struct net_device *dev)
+ {
+-	struct el3_private *lp = netdev_priv(dev);
+-
+-	(void) lp;				/* Keep gcc quiet... */
+-#if defined(__ISAPNP__)
+-	if (lp->type == EL3_PNP)
+-		pnp_device_detach(to_pnp_dev(lp->dev));
+-#endif
+-
+ 	unregister_netdev (dev);
+ 	release_region(dev->base_addr, EL3_IO_EXTENT);
+ 	free_netdev (dev);
+ }
+ 
+-static int __init el3_probe(int card_idx)
+-{
+-	struct net_device *dev;
+-	struct el3_private *lp;
+-	short lrs_state = 0xff, i;
+-	int ioaddr, irq, if_port;
+-	__be16 phys_addr[3];
+-	static int current_tag;
+-	int err = -ENODEV;
+-#if defined(__ISAPNP__)
+-	static int pnp_cards;
+-	struct pnp_dev *idev = NULL;
+-	int pnp_found = 0;
+-
+-	if (nopnp == 1)
+-		goto no_pnp;
+-
+-	for (i=0; el3_isapnp_adapters[i].vendor != 0; i++) {
+-		int j;
+-		while ((idev = pnp_find_dev(NULL,
+-					    el3_isapnp_adapters[i].vendor,
+-					    el3_isapnp_adapters[i].function,
+-					    idev))) {
+-			if (pnp_device_attach(idev) < 0)
+-				continue;
+-			if (pnp_activate_dev(idev) < 0) {
+-__again:
+-				pnp_device_detach(idev);
+-				continue;
+-			}
+-			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
+-				goto __again;
+-			ioaddr = pnp_port_start(idev, 0);
+-			if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509 PnP")) {
+-				pnp_device_detach(idev);
+-				return -EBUSY;
+-			}
+-			irq = pnp_irq(idev, 0);
+-			if (el3_debug > 3)
+-				printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n",
+-					(char*) el3_isapnp_adapters[i].driver_data, ioaddr, irq);
+-			EL3WINDOW(0);
+-			for (j = 0; j < 3; j++)
+-				el3_isapnp_phys_addr[pnp_cards][j] =
+-					phys_addr[j] =
+-						htons(read_eeprom(ioaddr, j));
+-			if_port = read_eeprom(ioaddr, 8) >> 14;
+-			dev = alloc_etherdev(sizeof (struct el3_private));
+-			if (!dev) {
+-					release_region(ioaddr, EL3_IO_EXTENT);
+-					pnp_device_detach(idev);
+-					return -ENOMEM;
+-			}
+-
+-			SET_NETDEV_DEV(dev, &idev->dev);
+-			pnp_cards++;
+-
+-			netdev_boot_setup_check(dev);
+-			pnp_found = 1;
+-			goto found;
+-		}
+-	}
+-no_pnp:
+-#endif /* __ISAPNP__ */
+-
+-	/* Select an open I/O location at 0x1*0 to do contention select. */
+-	for ( ; id_port < 0x200; id_port += 0x10) {
+-		if (!request_region(id_port, 1, "3c509"))
+-			continue;
+-		outb(0x00, id_port);
+-		outb(0xff, id_port);
+-		if (inb(id_port) & 0x01){
+-			release_region(id_port, 1);
+-			break;
+-		} else
+-			release_region(id_port, 1);
+-	}
+-	if (id_port >= 0x200) {
+-		/* Rare -- do we really need a warning? */
+-		printk(" WARNING: No I/O port available for 3c509 activation.\n");
+-		return -ENODEV;
+-	}
+-
+-	/* Next check for all ISA bus boards by sending the ID sequence to the
+-	   ID_PORT.  We find cards past the first by setting the 'current_tag'
+-	   on cards as they are found.  Cards with their tag set will not
+-	   respond to subsequent ID sequences. */
+-
+-	outb(0x00, id_port);
+-	outb(0x00, id_port);
+-	for(i = 0; i < 255; i++) {
+-		outb(lrs_state, id_port);
+-		lrs_state <<= 1;
+-		lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
+-	}
+-
+-	/* For the first probe, clear all board's tag registers. */
+-	if (current_tag == 0)
+-		outb(0xd0, id_port);
+-	else				/* Otherwise kill off already-found boards. */
+-		outb(0xd8, id_port);
+-
+-	if (id_read_eeprom(7) != 0x6d50) {
+-		return -ENODEV;
+-	}
+-
+-	/* Read in EEPROM data, which does contention-select.
+-	   Only the lowest address board will stay "on-line".
+-	   3Com got the byte order backwards. */
+-	for (i = 0; i < 3; i++) {
+-		phys_addr[i] = htons(id_read_eeprom(i));
+-	}
+-
+-#if defined(__ISAPNP__)
+-	if (nopnp == 0) {
+-		/* The ISA PnP 3c509 cards respond to the ID sequence.
+-		   This check is needed in order not to register them twice. */
+-		for (i = 0; i < pnp_cards; i++) {
+-			if (phys_addr[0] == el3_isapnp_phys_addr[i][0] &&
+-			    phys_addr[1] == el3_isapnp_phys_addr[i][1] &&
+-			    phys_addr[2] == el3_isapnp_phys_addr[i][2])
+-			{
+-				if (el3_debug > 3)
+-					printk("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
+-						phys_addr[0] & 0xff, phys_addr[0] >> 8,
+-						phys_addr[1] & 0xff, phys_addr[1] >> 8,
+-						phys_addr[2] & 0xff, phys_addr[2] >> 8);
+-				/* Set the adaptor tag so that the next card can be found. */
+-				outb(0xd0 + ++current_tag, id_port);
+-				goto no_pnp;
+-			}
+-		}
+-	}
+-#endif /* __ISAPNP__ */
+-
+-	{
+-		unsigned int iobase = id_read_eeprom(8);
+-		if_port = iobase >> 14;
+-		ioaddr = 0x200 + ((iobase & 0x1f) << 4);
+-	}
+-	irq = id_read_eeprom(9) >> 12;
+-
+-	dev = alloc_etherdev(sizeof (struct el3_private));
+-	if (!dev)
+-		return -ENOMEM;
+-
+-	netdev_boot_setup_check(dev);
+-
+-	/* Set passed-in IRQ or I/O Addr. */
+-	if (dev->irq > 1  &&  dev->irq < 16)
+-			irq = dev->irq;
+-
+-	if (dev->base_addr) {
+-		if (dev->mem_end == 0x3c509 	/* Magic key */
+-		    && dev->base_addr >= 0x200  &&  dev->base_addr <= 0x3e0)
+-			ioaddr = dev->base_addr & 0x3f0;
+-		else if (dev->base_addr != ioaddr)
+-			goto out;
+-	}
+-
+-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509")) {
+-		err = -EBUSY;
+-		goto out;
+-	}
+-
+-	/* Set the adaptor tag so that the next card can be found. */
+-	outb(0xd0 + ++current_tag, id_port);
+-
+-	/* Activate the adaptor at the EEPROM location. */
+-	outb((ioaddr >> 4) | 0xe0, id_port);
+-
+-	EL3WINDOW(0);
+-	if (inw(ioaddr) != 0x6d50)
+-		goto out1;
+-
+-	/* Free the interrupt so that some other card can use it. */
+-	outw(0x0f00, ioaddr + WN0_IRQ);
+-
+-#if defined(__ISAPNP__)
+- found:							/* PNP jumps here... */
+-#endif /* __ISAPNP__ */
+-
+-	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
+-	dev->base_addr = ioaddr;
+-	dev->irq = irq;
+-	dev->if_port = if_port;
+-	lp = netdev_priv(dev);
+-#if defined(__ISAPNP__)
+-	lp->dev = &idev->dev;
+-	if (pnp_found)
+-		lp->type = EL3_PNP;
+-#endif
+-	err = el3_common_init(dev);
+-
+-	if (err)
+-		goto out1;
+-
+-	el3_cards++;
+-	lp->next_dev = el3_root_dev;
+-	el3_root_dev = dev;
+-	return 0;
+-
+-out1:
+-#if defined(__ISAPNP__)
+-	if (idev)
+-		pnp_device_detach(idev);
+-#endif
+-out:
+-	free_netdev(dev);
+-	return err;
+-}
+-
+ #ifdef CONFIG_MCA
+ static int __init el3_mca_probe(struct device *device)
+ {
+@@ -596,7 +604,6 @@ static int __init el3_mca_probe(struct device *device)
+ 	 * redone for multi-card detection by ZP Gu (zpg at castle.net)
+ 	 * now works as a module */
+ 
+-	struct el3_private *lp;
+ 	short i;
+ 	int ioaddr, irq, if_port;
+ 	u16 phys_addr[3];
+@@ -613,7 +620,7 @@ static int __init el3_mca_probe(struct device *device)
+ 	irq = pos5 & 0x0f;
+ 
+ 
+-	printk("3c529: found %s at slot %d\n",
++	printk(KERN_INFO "3c529: found %s at slot %d\n",
+ 		   el3_mca_adapter_names[mdev->index], slot + 1);
+ 
+ 	/* claim the slot */
+@@ -626,7 +633,7 @@ static int __init el3_mca_probe(struct device *device)
+ 	irq = mca_device_transform_irq(mdev, irq);
+ 	ioaddr = mca_device_transform_ioport(mdev, ioaddr);
+ 	if (el3_debug > 2) {
+-			printk("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
++			printk(KERN_DEBUG "3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
+ 	}
+ 	EL3WINDOW(0);
+ 	for (i = 0; i < 3; i++) {
+@@ -641,13 +648,7 @@ static int __init el3_mca_probe(struct device *device)
+ 
+ 	netdev_boot_setup_check(dev);
+ 
+-	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
+-	dev->base_addr = ioaddr;
+-	dev->irq = irq;
+-	dev->if_port = if_port;
+-	lp = netdev_priv(dev);
+-	lp->dev = device;
+-	lp->type = EL3_MCA;
++	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA);
+ 	device->driver_data = dev;
+ 	err = el3_common_init(dev);
+ 
+@@ -657,7 +658,7 @@ static int __init el3_mca_probe(struct device *device)
+ 		return -ENOMEM;
+ 	}
+ 
+-	el3_cards++;
++	el3_devs[el3_cards++] = dev;
+ 	return 0;
+ }
+ 
+@@ -666,7 +667,6 @@ static int __init el3_mca_probe(struct device *device)
+ #ifdef CONFIG_EISA
+ static int __init el3_eisa_probe (struct device *device)
+ {
+-	struct el3_private *lp;
+ 	short i;
+ 	int ioaddr, irq, if_port;
+ 	u16 phys_addr[3];
+@@ -678,7 +678,7 @@ static int __init el3_eisa_probe (struct device *device)
+ 	edev = to_eisa_device (device);
+ 	ioaddr = edev->base_addr;
+ 
+-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
++	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
+ 		return -EBUSY;
+ 
+ 	/* Change the register set to the configuration window 0. */
+@@ -700,13 +700,7 @@ static int __init el3_eisa_probe (struct device *device)
+ 
+ 	netdev_boot_setup_check(dev);
+ 
+-	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
+-	dev->base_addr = ioaddr;
+-	dev->irq = irq;
+-	dev->if_port = if_port;
+-	lp = netdev_priv(dev);
+-	lp->dev = device;
+-	lp->type = EL3_EISA;
++	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
+ 	eisa_set_drvdata (edev, dev);
+ 	err = el3_common_init(dev);
+ 
+@@ -716,12 +710,11 @@ static int __init el3_eisa_probe (struct device *device)
+ 		return err;
+ 	}
+ 
+-	el3_cards++;
++	el3_devs[el3_cards++] = dev;
+ 	return 0;
+ }
+ #endif
+ 
+-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ /* This remove works for all device types.
+  *
+  * The net dev must be stored in the driver_data field */
+@@ -734,7 +727,6 @@ static int __devexit el3_device_remove (struct device *device)
+ 	el3_common_remove (dev);
+ 	return 0;
+ }
+-#endif
+ 
+ /* Read a word from the EEPROM using the regular EEPROM access register.
+    Assume that we are in register window zero.
+@@ -749,7 +741,7 @@ static ushort read_eeprom(int ioaddr, int index)
+ }
+ 
+ /* Read a word from the EEPROM when in the ISA ID probe state. */
+-static ushort __init id_read_eeprom(int index)
++static ushort id_read_eeprom(int index)
+ {
+ 	int bit, word = 0;
+ 
+@@ -765,7 +757,7 @@ static ushort __init id_read_eeprom(int index)
+ 		word = (word << 1) + (inb(id_port) & 0x01);
+ 
+ 	if (el3_debug > 3)
+-		printk("  3c509 EEPROM word %d %#4.4x.\n", index, word);
++		printk(KERN_DEBUG "  3c509 EEPROM word %d %#4.4x.\n", index, word);
+ 
+ 	return word;
+ }
+@@ -787,13 +779,13 @@ el3_open(struct net_device *dev)
+ 
+ 	EL3WINDOW(0);
+ 	if (el3_debug > 3)
+-		printk("%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
++		printk(KERN_DEBUG "%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
+ 			   dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
+ 
+ 	el3_up(dev);
+ 
+ 	if (el3_debug > 3)
+-		printk("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
++		printk(KERN_DEBUG "%s: Opened 3c509  IRQ %d  status %4.4x.\n",
+ 			   dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
+ 
+ 	return 0;
+@@ -806,7 +798,7 @@ el3_tx_timeout (struct net_device *dev)
+ 	int ioaddr = dev->base_addr;
+ 
+ 	/* Transmitter timeout, serious problems. */
+-	printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
++	printk(KERN_WARNING "%s: transmit timed out, Tx_status %2.2x status %4.4x "
+ 		   "Tx FIFO room %d.\n",
+ 		   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
+ 		   inw(ioaddr + TX_FREE));
+@@ -831,7 +823,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	lp->stats.tx_bytes += skb->len;
+ 
+ 	if (el3_debug > 4) {
+-		printk("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
++		printk(KERN_DEBUG "%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
+ 			   dev->name, skb->len, inw(ioaddr + EL3_STATUS));
+ 	}
+ #if 0
+@@ -840,7 +832,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		ushort status = inw(ioaddr + EL3_STATUS);
+ 		if (status & 0x0001 		/* IRQ line active, missed one. */
+ 			&& inw(ioaddr + EL3_STATUS) & 1) { 			/* Make sure. */
+-			printk("%s: Missed interrupt, status then %04x now %04x"
++			printk(KERN_DEBUG "%s: Missed interrupt, status then %04x now %04x"
+ 				   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
+ 				   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
+ 				   inw(ioaddr + RX_STATUS));
+@@ -914,7 +906,7 @@ el3_interrupt(int irq, void *dev_id)
+ 
+ 	if (el3_debug > 4) {
+ 		status = inw(ioaddr + EL3_STATUS);
+-		printk("%s: interrupt, status %4.4x.\n", dev->name, status);
++		printk(KERN_DEBUG "%s: interrupt, status %4.4x.\n", dev->name, status);
+ 	}
+ 
+ 	while ((status = inw(ioaddr + EL3_STATUS)) &
+@@ -925,7 +917,7 @@ el3_interrupt(int irq, void *dev_id)
+ 
+ 		if (status & TxAvailable) {
+ 			if (el3_debug > 5)
+-				printk("	TX room bit was handled.\n");
++				printk(KERN_DEBUG "	TX room bit was handled.\n");
+ 			/* There's room in the FIFO for a full-sized packet. */
+ 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+ 			netif_wake_queue (dev);
+@@ -964,7 +956,7 @@ el3_interrupt(int irq, void *dev_id)
+ 		}
+ 
+ 		if (--i < 0) {
+-			printk("%s: Infinite loop in interrupt, status %4.4x.\n",
++			printk(KERN_ERR "%s: Infinite loop in interrupt, status %4.4x.\n",
+ 				   dev->name, status);
+ 			/* Clear all interrupts. */
+ 			outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
+@@ -975,7 +967,7 @@ el3_interrupt(int irq, void *dev_id)
+ 	}
+ 
+ 	if (el3_debug > 4) {
+-		printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
++		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", dev->name,
+ 			   inw(ioaddr + EL3_STATUS));
+ 	}
+ 	spin_unlock(&lp->lock);
+@@ -1450,7 +1442,7 @@ el3_up(struct net_device *dev)
+ }
+ 
+ /* Power Management support functions */
+-#ifdef EL3_SUSPEND
++#ifdef CONFIG_PM
+ 
+ static int
+ el3_suspend(struct device *pdev, pm_message_t state)
+@@ -1500,79 +1492,102 @@ el3_resume(struct device *pdev)
+ 	return 0;
+ }
+ 
+-#endif /* EL3_SUSPEND */
+-
+-/* Parameters that may be passed into the module. */
+-static int debug = -1;
+-static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+-static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
++#endif /* CONFIG_PM */
+ 
+ module_param(debug,int, 0);
+ module_param_array(irq, int, NULL, 0);
+-module_param_array(xcvr, int, NULL, 0);
+ module_param(max_interrupt_work, int, 0);
+ MODULE_PARM_DESC(debug, "debug level (0-6)");
+ MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+-MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
+ MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
+-#if defined(__ISAPNP__)
++#ifdef CONFIG_PNP
+ module_param(nopnp, int, 0);
+ MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
+-MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
+-#endif	/* __ISAPNP__ */
+-MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B) ISA/PnP ethernet driver");
++#endif	/* CONFIG_PNP */
++MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
+ MODULE_LICENSE("GPL");
+ 
+ static int __init el3_init_module(void)
+ {
+ 	int ret = 0;
+-	el3_cards = 0;
+ 
+ 	if (debug >= 0)
+ 		el3_debug = debug;
+ 
+-	el3_root_dev = NULL;
+-	while (el3_probe(el3_cards) == 0) {
+-		if (irq[el3_cards] > 1)
+-			el3_root_dev->irq = irq[el3_cards];
+-		if (xcvr[el3_cards] >= 0)
+-			el3_root_dev->if_port = xcvr[el3_cards];
+-		el3_cards++;
++#ifdef CONFIG_PNP
++	if (!nopnp) {
++		ret = pnp_register_driver(&el3_pnp_driver);
++		if (!ret)
++			pnp_registered = 1;
++	}
++#endif
++	/* Select an open I/O location at 0x1*0 to do ISA contention select. */
++	/* Start with 0x110 to avoid some sound cards.*/
++	for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10) {
++		if (!request_region(id_port, 1, "3c509-control"))
++			continue;
++		outb(0x00, id_port);
++		outb(0xff, id_port);
++		if (inb(id_port) & 0x01)
++			break;
++		else
++			release_region(id_port, 1);
++	}
++	if (id_port >= 0x200) {
++		id_port = 0;
++		printk(KERN_ERR "No I/O port available for 3c509 activation.\n");
++	} else {
++		ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
++		if (!ret)
++			isa_registered = 1;
+ 	}
+-
+ #ifdef CONFIG_EISA
+ 	ret = eisa_driver_register(&el3_eisa_driver);
++	if (!ret)
++		eisa_registered = 1;
+ #endif
+ #ifdef CONFIG_MCA
+-	{
+-		int err = mca_register_driver(&el3_mca_driver);
+-		if (ret == 0)
+-			ret = err;
+-	}
++	ret = mca_register_driver(&el3_mca_driver);
++	if (!ret)
++		mca_registered = 1;
++#endif
++
++#ifdef CONFIG_PNP
++	if (pnp_registered)
++		ret = 0;
++#endif
++	if (isa_registered)
++		ret = 0;
++#ifdef CONFIG_EISA
++	if (eisa_registered)
++		ret = 0;
++#endif
++#ifdef CONFIG_MCA
++	if (mca_registered)
++		ret = 0;
+ #endif
+ 	return ret;
+ }
+ 
+ static void __exit el3_cleanup_module(void)
+ {
+-	struct net_device *next_dev;
+-
+-	while (el3_root_dev) {
+-		struct el3_private *lp = netdev_priv(el3_root_dev);
+-
+-		next_dev = lp->next_dev;
+-		el3_common_remove (el3_root_dev);
+-		el3_root_dev = next_dev;
+-	}
+-
++#ifdef CONFIG_PNP
++	if (pnp_registered)
++		pnp_unregister_driver(&el3_pnp_driver);
++#endif
++	if (isa_registered)
++		isa_unregister_driver(&el3_isa_driver);
++	if (id_port)
++		release_region(id_port, 1);
+ #ifdef CONFIG_EISA
+-	eisa_driver_unregister (&el3_eisa_driver);
++	if (eisa_registered)
++		eisa_driver_unregister(&el3_eisa_driver);
+ #endif
+ #ifdef CONFIG_MCA
+-	mca_unregister_driver(&el3_mca_driver);
++	if (mca_registered)
++		mca_unregister_driver(&el3_mca_driver);
+ #endif
+ }
+ 
+ module_init (el3_init_module);
+ module_exit (el3_cleanup_module);
+-
+diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
+index b72b89d..fae295b 100644
+--- a/drivers/net/3c527.c
++++ b/drivers/net/3c527.c
+@@ -103,8 +103,8 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter <rnp at paradise.net.
+ #include <linux/ethtool.h>
+ #include <linux/completion.h>
+ #include <linux/bitops.h>
++#include <linux/semaphore.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
+index be6e918..53bd903 100644
+--- a/drivers/net/8139too.c
++++ b/drivers/net/8139too.c
+@@ -966,8 +966,8 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
+ 
+ 	addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
+ 	for (i = 0; i < 3; i++)
+-		((u16 *) (dev->dev_addr))[i] =
+-		    le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
++		((__le16 *) (dev->dev_addr))[i] =
++		    cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len));
+ 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+ 
+ 	/* The Rtl8139-specific entries in the device structure. */
+@@ -1373,8 +1373,8 @@ static void rtl8139_hw_start (struct net_device *dev)
+ 	/* unlock Config[01234] and BMCR register writes */
+ 	RTL_W8_F (Cfg9346, Cfg9346_Unlock);
+ 	/* Restore our idea of the MAC address. */
+-	RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
+-	RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));
++	RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
++	RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4)));
+ 
+ 	/* Must enable Tx/Rx before setting transfer thresholds! */
+ 	RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+@@ -1945,7 +1945,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
+ 		rmb();
+ 
+ 		/* read size+status of next frame from DMA ring buffer */
+-		rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
++		rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset));
+ 		rx_size = rx_status >> 16;
+ 		pkt_size = rx_size - 4;
+ 
+diff --git a/drivers/net/8390.c b/drivers/net/8390.c
+index a828076..a499e86 100644
+--- a/drivers/net/8390.c
++++ b/drivers/net/8390.c
+@@ -48,14 +48,16 @@ EXPORT_SYMBOL(__alloc_ei_netdev);
+ 
+ #if defined(MODULE)
+ 
+-int init_module(void)
++static int __init ns8390_module_init(void)
+ {
+ 	return 0;
+ }
+ 
+-void cleanup_module(void)
++static void __exit ns8390_module_exit(void)
+ {
+ }
+ 
++module_init(ns8390_module_init);
++module_exit(ns8390_module_exit);
+ #endif /* MODULE */
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 3a0b20a..0697aa8 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -467,6 +467,13 @@ config SNI_82596
+ 	  Say Y here to support the on-board Intel 82596 ethernet controller
+ 	  built into SNI RM machines.
+ 
++config KORINA
++	tristate "Korina (IDT RC32434) Ethernet support"
++	depends on NET_ETHERNET && MIKROTIK_RB500
++	help
++	  If you have a Mikrotik RouterBoard 500 or IDT RC32434
++	  based system say Y. Otherwise say N.
++
+ config MIPS_JAZZ_SONIC
+ 	tristate "MIPS JAZZ onboard SONIC Ethernet support"
+ 	depends on MACH_JAZZ
+@@ -820,7 +827,7 @@ config ULTRA32
+ 
+ config BFIN_MAC
+ 	tristate "Blackfin 527/536/537 on-chip mac support"
+-	depends on NET_ETHERNET && (BF527 || BF537 || BF536) && (!BF537_PORT_H)
++	depends on NET_ETHERNET && (BF527 || BF537 || BF536)
+ 	select CRC32
+ 	select MII
+ 	select PHYLIB
+@@ -1431,7 +1438,7 @@ config CS89x0
+ config TC35815
+ 	tristate "TOSHIBA TC35815 Ethernet support"
+ 	depends on NET_PCI && PCI && MIPS
+-	select MII
++	select PHYLIB
+ 
+ config EEPRO100
+ 	tristate "EtherExpressPro/100 support (eepro100, original Becker driver)"
+@@ -2220,93 +2227,6 @@ config SKY2_DEBUG
+ 
+ 	 If unsure, say N.
+ 
+-config SK98LIN
+-	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
+-	depends on PCI
+-	---help---
+-	  Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
+-	  compliant Gigabit Ethernet Adapter.
+-
+-	  This driver supports the original Yukon chipset. This driver is
+-	  deprecated and will be removed from the kernel in the near future,
+-	  it has been replaced by the skge driver. skge is cleaner and
+-	  seems to work better.
+-
+-	  This driver does not support the newer Yukon2 chipset. A separate
+-	  driver, sky2, is provided to support Yukon2-based adapters.
+-
+-	  The following adapters are supported by this driver:
+-	    - 3Com 3C940 Gigabit LOM Ethernet Adapter
+-	    - 3Com 3C941 Gigabit LOM Ethernet Adapter
+-	    - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
+-	    - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter
+-	    - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter
+-	    - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter
+-	    - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter
+-	    - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter
+-	    - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
+-	    - Allied Telesyn AT-2971T Gigabit Ethernet Adapter
+-	    - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
+-	    - EG1032 v2 Instant Gigabit Network Adapter
+-	    - EG1064 v2 Instant Gigabit Network Adapter
+-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
+-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron)
+-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus)
+-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS)
+-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox)
+-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
+-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
+-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
+-	    - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
+-	    - Marvell RDK-8001 Adapter
+-	    - Marvell RDK-8002 Adapter
+-	    - Marvell RDK-8003 Adapter
+-	    - Marvell RDK-8004 Adapter
+-	    - Marvell RDK-8006 Adapter
+-	    - Marvell RDK-8007 Adapter
+-	    - Marvell RDK-8008 Adapter
+-	    - Marvell RDK-8009 Adapter
+-	    - Marvell RDK-8010 Adapter
+-	    - Marvell RDK-8011 Adapter
+-	    - Marvell RDK-8012 Adapter
+-	    - Marvell RDK-8052 Adapter
+-	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
+-	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
+-	    - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
+-	    - SK-9521 10/100/1000Base-T Adapter
+-	    - SK-9521 V2.0 10/100/1000Base-T Adapter
+-	    - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
+-	    - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
+-	    - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
+-	    - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
+-	    - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
+-	    - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
+-	    - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
+-	    - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
+-	    - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
+-	    - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
+-	    - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
+-	    - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
+-	    - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
+-	    - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
+-	    - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
+-	    - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
+-	    - SMC EZ Card 1000 (SMC9452TXV.2)
+-	  
+-	  The adapters support Jumbo Frames.
+-	  The dual link adapters support link-failover and dual port features.
+-	  Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support 
+-	  the scatter-gather functionality with sendfile(). Please refer to 
+-	  <file:Documentation/networking/sk98lin.txt> for more information about
+-	  optional driver parameters.
+-	  Questions concerning this driver may be addressed to:
+-	      <linux at syskonnect.de>
+-	  
+-	  If you want to compile this driver as a module ( = code which can be
+-	  inserted in and removed from the running kernel whenever you want),
+-	  say M here and read <file:Documentation/kbuild/modules.txt>. The module will
+-	  be called sk98lin. This is recommended.
+-
+ config VIA_VELOCITY
+ 	tristate "VIA Velocity support"
+ 	depends on PCI
+@@ -2358,6 +2278,7 @@ config TSI108_ETH
+ config GELIC_NET
+ 	tristate "PS3 Gigabit Ethernet driver"
+ 	depends on PPC_PS3
++	select PS3_SYS_MANAGER
+ 	help
+ 	  This driver supports the network device on the PS3 game
+ 	  console.  This driver has built-in support for Ethernet.
+@@ -2415,7 +2336,7 @@ config UGETH_TX_ON_DEMAND
+ 
+ config MV643XX_ETH
+ 	tristate "Marvell Discovery (643XX) and Orion ethernet support"
+-	depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || ARCH_ORION
++	depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION
+ 	select MII
+ 	help
+ 	  This driver supports the gigabit ethernet MACs in the
+diff --git a/drivers/net/Makefile b/drivers/net/Makefile
+index 3b1ea32..2f1f3f2 100644
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -15,7 +15,7 @@ obj-$(CONFIG_CHELSIO_T3) += cxgb3/
+ obj-$(CONFIG_EHEA) += ehea/
+ obj-$(CONFIG_CAN) += can/
+ obj-$(CONFIG_BONDING) += bonding/
+-obj-$(CONFIG_ATL1) += atl1/
++obj-$(CONFIG_ATL1) += atlx/
+ obj-$(CONFIG_GIANFAR) += gianfar_driver.o
+ obj-$(CONFIG_TEHUTI) += tehuti.o
+ 
+@@ -75,7 +75,6 @@ ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y)
+ obj-$(CONFIG_TC35815) += tc35815.o
+ obj-$(CONFIG_SKGE) += skge.o
+ obj-$(CONFIG_SKY2) += sky2.o
+-obj-$(CONFIG_SK98LIN) += sk98lin/
+ obj-$(CONFIG_SKFP) += skfp/
+ obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+ obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
+@@ -191,6 +190,7 @@ obj-$(CONFIG_ZORRO8390) += zorro8390.o
+ obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
+ obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
+ obj-$(CONFIG_EQUALIZER) += eql.o
++obj-$(CONFIG_KORINA) += korina.o
+ obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
+ obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+ obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
+@@ -218,7 +218,8 @@ obj-$(CONFIG_SMC911X) += smc911x.o
+ obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
+ obj-$(CONFIG_DM9000) += dm9000.o
+ obj-$(CONFIG_FEC_8XX) += fec_8xx/
+-obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o
++obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
++pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
+ obj-$(CONFIG_MLX4_CORE) += mlx4/
+ obj-$(CONFIG_ENC28J60) += enc28j60.o
+ 
+diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
+index c59c806..bdc4c0b 100644
+--- a/drivers/net/arcnet/arcnet.c
++++ b/drivers/net/arcnet/arcnet.c
+@@ -940,7 +940,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
+ 
+ 			/* is the RECON info empty or old? */
+ 			if (!lp->first_recon || !lp->last_recon ||
+-			    jiffies - lp->last_recon > HZ * 10) {
++			    time_after(jiffies, lp->last_recon + HZ * 10)) {
+ 				if (lp->network_down)
+ 					BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n");
+ 				lp->first_recon = lp->last_recon = jiffies;
+@@ -974,7 +974,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
+ 					lp->num_recons = 1;
+ 				}
+ 			}
+-		} else if (lp->network_down && jiffies - lp->last_recon > HZ * 10) {
++		} else if (lp->network_down &&
++				time_after(jiffies, lp->last_recon + HZ * 10)) {
+ 			if (lp->network_down)
+ 				BUGMSG(D_NORMAL, "cabling restored?\n");
+ 			lp->first_recon = lp->last_recon = 0;
+diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
+index 7cf0a25..8b51313 100644
+--- a/drivers/net/arcnet/com20020.c
++++ b/drivers/net/arcnet/com20020.c
+@@ -348,14 +348,15 @@ MODULE_LICENSE("GPL");
+ 
+ #ifdef MODULE
+ 
+-int init_module(void)
++static int __init com20020_module_init(void)
+ {
+ 	BUGLVL(D_NORMAL) printk(VERSION);
+ 	return 0;
+ }
+ 
+-void cleanup_module(void)
++static void __exit com20020_module_exit(void)
+ {
+ }
+-
++module_init(com20020_module_init);
++module_exit(com20020_module_exit);
+ #endif				/* MODULE */
+diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
+index 0ae0d83..1e39e78 100644
+--- a/drivers/net/arm/at91_ether.c
++++ b/drivers/net/arm/at91_ether.c
+@@ -1043,7 +1043,9 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
+ 	} else if (machine_is_csb337()) {
+ 		/* mix link activity status into LED2 link state */
+ 		write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
+-	}
++	} else if (machine_is_ecbat91())
++		write_phy(phy_address, MII_LEDCTRL_REG, 0x156A);
++
+ 	disable_mdi();
+ 	spin_unlock_irq(&lp->lock);
+ 
+@@ -1246,3 +1248,4 @@ module_exit(at91ether_exit)
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
+ MODULE_AUTHOR("Andrew Victor");
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
+index 91a6590..ecd8fc6 100644
+--- a/drivers/net/arm/ep93xx_eth.c
++++ b/drivers/net/arm/ep93xx_eth.c
+@@ -897,6 +897,7 @@ static struct platform_driver ep93xx_eth_driver = {
+ 	.remove		= ep93xx_eth_remove,
+ 	.driver		= {
+ 		.name	= "ep93xx-eth",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -914,3 +915,4 @@ static void __exit ep93xx_eth_cleanup_module(void)
+ module_init(ep93xx_eth_init_module);
+ module_exit(ep93xx_eth_cleanup_module);
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:ep93xx-eth");
+diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
+index 24d81f9..7e874d4 100644
+--- a/drivers/net/at1700.c
++++ b/drivers/net/at1700.c
+@@ -881,7 +881,7 @@ MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address");
+ MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
+ MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
+ 
+-int __init init_module(void)
++static int __init at1700_module_init(void)
+ {
+ 	if (io == 0)
+ 		printk("at1700: You should not use auto-probing with insmod!\n");
+@@ -891,13 +891,14 @@ int __init init_module(void)
+ 	return 0;
+ }
+ 
+-void __exit
+-cleanup_module(void)
++static void __exit at1700_module_exit(void)
+ {
+ 	unregister_netdev(dev_at1700);
+ 	cleanup_card(dev_at1700);
+ 	free_netdev(dev_at1700);
+ }
++module_init(at1700_module_init);
++module_exit(at1700_module_exit);
+ #endif /* MODULE */
+ MODULE_LICENSE("GPL");
+ 
+diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
+index 13c293b..4cceaac 100644
+--- a/drivers/net/atarilance.c
++++ b/drivers/net/atarilance.c
+@@ -1155,7 +1155,7 @@ static int lance_set_mac_address( struct net_device *dev, void *addr )
+ #ifdef MODULE
+ static struct net_device *atarilance_dev;
+ 
+-int __init init_module(void)
++static int __init atarilance_module_init(void)
+ {
+ 	atarilance_dev = atarilance_probe(-1);
+ 	if (IS_ERR(atarilance_dev))
+@@ -1163,13 +1163,14 @@ int __init init_module(void)
+ 	return 0;
+ }
+ 
+-void __exit cleanup_module(void)
++static void __exit atarilance_module_exit(void)
+ {
+ 	unregister_netdev(atarilance_dev);
+ 	free_irq(atarilance_dev->irq, atarilance_dev);
+ 	free_netdev(atarilance_dev);
+ }
+-
++module_init(atarilance_module_init);
++module_exit(atarilance_module_exit);
+ #endif /* MODULE */
+ 
+ 
+diff --git a/drivers/net/atl1/Makefile b/drivers/net/atl1/Makefile
+deleted file mode 100644
+index a6b707e..0000000
+--- a/drivers/net/atl1/Makefile
++++ /dev/null
+@@ -1,2 +0,0 @@
+-obj-$(CONFIG_ATL1)	+= atl1.o
+-atl1-y			+= atl1_main.o atl1_hw.o atl1_ethtool.o atl1_param.o
+diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h
+deleted file mode 100644
+index ff4765f..0000000
+--- a/drivers/net/atl1/atl1.h
++++ /dev/null
+@@ -1,286 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * Derived from Intel e1000 driver
+- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc., 59
+- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+- */
+-
+-#ifndef _ATL1_H_
+-#define _ATL1_H_
+-
+-#include <linux/types.h>
+-#include <linux/if_vlan.h>
+-
+-#include "atl1_hw.h"
+-
+-/* function prototypes needed by multiple files */
+-s32 atl1_up(struct atl1_adapter *adapter);
+-void atl1_down(struct atl1_adapter *adapter);
+-int atl1_reset(struct atl1_adapter *adapter);
+-s32 atl1_setup_ring_resources(struct atl1_adapter *adapter);
+-void atl1_free_ring_resources(struct atl1_adapter *adapter);
+-
+-extern char atl1_driver_name[];
+-extern char atl1_driver_version[];
+-extern const struct ethtool_ops atl1_ethtool_ops;
+-
+-struct atl1_adapter;
+-
+-#define ATL1_MAX_INTR		3
+-#define ATL1_MAX_TX_BUF_LEN	0x3000	/* 12288 bytes */
+-
+-#define ATL1_DEFAULT_TPD	256
+-#define ATL1_MAX_TPD		1024
+-#define ATL1_MIN_TPD		64
+-#define ATL1_DEFAULT_RFD	512
+-#define ATL1_MIN_RFD		128
+-#define ATL1_MAX_RFD		2048
+-
+-#define ATL1_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
+-#define ATL1_RFD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_free_desc)
+-#define ATL1_TPD_DESC(R, i)	ATL1_GET_DESC(R, i, struct tx_packet_desc)
+-#define ATL1_RRD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_return_desc)
+-
+-/*
+- * This detached comment is preserved for documentation purposes only.
+- * It was originally attached to some code that got deleted, but seems
+- * important enough to keep around...
+- *
+- * <begin detached comment>
+- * Some workarounds require millisecond delays and are run during interrupt
+- * context.  Most notably, when establishing link, the phy may need tweaking
+- * but cannot process phy register reads/writes faster than millisecond
+- * intervals...and we establish link due to a "link status change" interrupt.
+- * <end detached comment>
+- */
+-
+-/*
+- * atl1_ring_header represents a single, contiguous block of DMA space
+- * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
+- * message blocks (cmb, smb) described below
+- */
+-struct atl1_ring_header {
+-	void *desc;		/* virtual address */
+-	dma_addr_t dma;		/* physical address*/
+-	unsigned int size;	/* length in bytes */
+-};
+-
+-/*
+- * atl1_buffer is wrapper around a pointer to a socket buffer
+- * so a DMA handle can be stored along with the skb
+- */
+-struct atl1_buffer {
+-	struct sk_buff *skb;	/* socket buffer */
+-	u16 length;		/* rx buffer length */
+-	u16 alloced;		/* 1 if skb allocated */
+-	dma_addr_t dma;
+-};
+-
+-/* transmit packet descriptor (tpd) ring */
+-struct atl1_tpd_ring {
+-	void *desc;		/* descriptor ring virtual address */
+-	dma_addr_t dma;		/* descriptor ring physical address */
+-	u16 size;		/* descriptor ring length in bytes */
+-	u16 count;		/* number of descriptors in the ring */
+-	u16 hw_idx;		/* hardware index */
+-	atomic_t next_to_clean;
+-	atomic_t next_to_use;
+-	struct atl1_buffer *buffer_info;
+-};
+-
+-/* receive free descriptor (rfd) ring */
+-struct atl1_rfd_ring {
+-	void *desc;		/* descriptor ring virtual address */
+-	dma_addr_t dma;		/* descriptor ring physical address */
+-	u16 size;		/* descriptor ring length in bytes */
+-	u16 count;		/* number of descriptors in the ring */
+-	atomic_t next_to_use;
+-	u16 next_to_clean;
+-	struct atl1_buffer *buffer_info;
+-};
+-
+-/* receive return descriptor (rrd) ring */
+-struct atl1_rrd_ring {
+-	void *desc;		/* descriptor ring virtual address */
+-	dma_addr_t dma;		/* descriptor ring physical address */
+-	unsigned int size;	/* descriptor ring length in bytes */
+-	u16 count;		/* number of descriptors in the ring */
+-	u16 next_to_use;
+-	atomic_t next_to_clean;
+-};
+-
+-/* coalescing message block (cmb) */
+-struct atl1_cmb {
+-	struct coals_msg_block *cmb;
+-	dma_addr_t dma;
+-};
+-
+-/* statistics message block (smb) */
+-struct atl1_smb {
+-	struct stats_msg_block *smb;
+-	dma_addr_t dma;
+-};
+-
+-/* Statistics counters */
+-struct atl1_sft_stats {
+-	u64 rx_packets;
+-	u64 tx_packets;
+-	u64 rx_bytes;
+-	u64 tx_bytes;
+-	u64 multicast;
+-	u64 collisions;
+-	u64 rx_errors;
+-	u64 rx_length_errors;
+-	u64 rx_crc_errors;
+-	u64 rx_frame_errors;
+-	u64 rx_fifo_errors;
+-	u64 rx_missed_errors;
+-	u64 tx_errors;
+-	u64 tx_fifo_errors;
+-	u64 tx_aborted_errors;
+-	u64 tx_window_errors;
+-	u64 tx_carrier_errors;
+-	u64 tx_pause;		/* num pause packets transmitted. */
+-	u64 excecol;		/* num tx packets w/ excessive collisions. */
+-	u64 deffer;		/* num tx packets deferred */
+-	u64 scc;		/* num packets subsequently transmitted
+-				 * successfully w/ single prior collision. */
+-	u64 mcc;		/* num packets subsequently transmitted
+-				 * successfully w/ multiple prior collisions. */
+-	u64 latecol;		/* num tx packets  w/ late collisions. */
+-	u64 tx_underun;		/* num tx packets aborted due to transmit
+-				 * FIFO underrun, or TRD FIFO underrun */
+-	u64 tx_trunc;		/* num tx packets truncated due to size
+-				 * exceeding MTU, regardless whether truncated
+-				 * by the chip or not. (The name doesn't really
+-				 * reflect the meaning in this case.) */
+-	u64 rx_pause;		/* num Pause packets received. */
+-	u64 rx_rrd_ov;
+-	u64 rx_trunc;
+-};
+-
+-/* hardware structure */
+-struct atl1_hw {
+-	u8 __iomem *hw_addr;
+-	struct atl1_adapter *back;
+-	enum atl1_dma_order dma_ord;
+-	enum atl1_dma_rcb rcb_value;
+-	enum atl1_dma_req_block dmar_block;
+-	enum atl1_dma_req_block dmaw_block;
+-	u8 preamble_len;
+-	u8 max_retry;		/* Retransmission maximum, after which the
+-				 * packet will be discarded */
+-	u8 jam_ipg;		/* IPG to start JAM for collision based flow
+-				 * control in half-duplex mode. In units of
+-				 * 8-bit time */
+-	u8 ipgt;		/* Desired back to back inter-packet gap.
+-				 * The default is 96-bit time */
+-	u8 min_ifg;		/* Minimum number of IFG to enforce in between
+-				 * receive frames. Frame gap below such IFP
+-				 * is dropped */
+-	u8 ipgr1;		/* 64bit Carrier-Sense window */
+-	u8 ipgr2;		/* 96-bit IPG window */
+-	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned
+-				 * burst. Each TPD is 16 bytes long */
+-	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned
+-				 * burst. Each RFD is 12 bytes long */
+-	u8 rfd_fetch_gap;
+-	u8 rrd_burst;		/* Threshold number of RRDs that can be retired
+-				 * in a burst. Each RRD is 16 bytes long */
+-	u8 tpd_fetch_th;
+-	u8 tpd_fetch_gap;
+-	u16 tx_jumbo_task_th;
+-	u16 txf_burst;		/* Number of data bytes to read in a cache-
+-				 * aligned burst. Each SRAM entry is 8 bytes */
+-	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN
+-				 * packets should add 4 bytes */
+-	u16 rx_jumbo_lkah;
+-	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after
+-				 * every 512ns passes. */
+-	u16 lcol;		/* Collision Window */
+-
+-	u16 cmb_tpd;
+-	u16 cmb_rrd;
+-	u16 cmb_rx_timer;
+-	u16 cmb_tx_timer;
+-	u32 smb_timer;
+-	u16 media_type;
+-	u16 autoneg_advertised;
+-
+-	u16 mii_autoneg_adv_reg;
+-	u16 mii_1000t_ctrl_reg;
+-
+-	u32 max_frame_size;
+-	u32 min_frame_size;
+-
+-	u16 dev_rev;
+-
+-	/* spi flash */
+-	u8 flash_vendor;
+-
+-	u8 mac_addr[ETH_ALEN];
+-	u8 perm_mac_addr[ETH_ALEN];
+-
+-	bool phy_configured;
+-};
+-
+-struct atl1_adapter {
+-	struct net_device *netdev;
+-	struct pci_dev *pdev;
+-	struct net_device_stats net_stats;
+-	struct atl1_sft_stats soft_stats;
+-	struct vlan_group *vlgrp;
+-	u32 rx_buffer_len;
+-	u32 wol;
+-	u16 link_speed;
+-	u16 link_duplex;
+-	spinlock_t lock;
+-	struct work_struct tx_timeout_task;
+-	struct work_struct link_chg_task;
+-	struct work_struct pcie_dma_to_rst_task;
+-	struct timer_list watchdog_timer;
+-	struct timer_list phy_config_timer;
+-	bool phy_timer_pending;
+-
+-	/* all descriptor rings' memory */
+-	struct atl1_ring_header ring_header;
+-
+-	/* TX */
+-	struct atl1_tpd_ring tpd_ring;
+-	spinlock_t mb_lock;
+-
+-	/* RX */
+-	struct atl1_rfd_ring rfd_ring;
+-	struct atl1_rrd_ring rrd_ring;
+-	u64 hw_csum_err;
+-	u64 hw_csum_good;
+-
+-	u16 imt;	/* interrupt moderator timer (2us resolution */
+-	u16 ict;	/* interrupt clear timer (2us resolution */
+-	struct mii_if_info mii;		/* MII interface info */
+-
+-	/* structs defined in atl1_hw.h */
+-	u32 bd_number;			/* board number */
+-	bool pci_using_64;
+-	struct atl1_hw hw;
+-	struct atl1_smb smb;
+-	struct atl1_cmb cmb;
+-};
+-
+-#endif	/* _ATL1_H_ */
+diff --git a/drivers/net/atl1/atl1_ethtool.c b/drivers/net/atl1/atl1_ethtool.c
+deleted file mode 100644
+index 68a83be..0000000
+--- a/drivers/net/atl1/atl1_ethtool.c
++++ /dev/null
+@@ -1,505 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * Derived from Intel e1000 driver
+- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc., 59
+- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/pci.h>
+-#include <linux/ethtool.h>
+-#include <linux/netdevice.h>
+-#include <linux/mii.h>
+-#include <asm/uaccess.h>
+-
+-#include "atl1.h"
+-
+-struct atl1_stats {
+-	char stat_string[ETH_GSTRING_LEN];
+-	int sizeof_stat;
+-	int stat_offset;
+-};
+-
+-#define ATL1_STAT(m) sizeof(((struct atl1_adapter *)0)->m), \
+-	offsetof(struct atl1_adapter, m)
+-
+-static struct atl1_stats atl1_gstrings_stats[] = {
+-	{"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
+-	{"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
+-	{"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
+-	{"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
+-	{"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
+-	{"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
+-	{"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
+-	{"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
+-	{"multicast", ATL1_STAT(soft_stats.multicast)},
+-	{"collisions", ATL1_STAT(soft_stats.collisions)},
+-	{"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
+-	{"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+-	{"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
+-	{"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
+-	{"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
+-	{"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+-	{"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
+-	{"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
+-	{"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
+-	{"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
+-	{"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
+-	{"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
+-	{"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
+-	{"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
+-	{"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
+-	{"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
+-	{"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
+-	{"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
+-	{"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
+-	{"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
+-	{"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
+-};
+-
+-static void atl1_get_ethtool_stats(struct net_device *netdev,
+-				struct ethtool_stats *stats, u64 *data)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	int i;
+-	char *p;
+-
+-	for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+-		p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
+-		data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
+-			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+-	}
+-
+-}
+-
+-static int atl1_get_sset_count(struct net_device *netdev, int sset)
+-{
+-	switch (sset) {
+-	case ETH_SS_STATS:
+-		return ARRAY_SIZE(atl1_gstrings_stats);
+-	default:
+-		return -EOPNOTSUPP;
+-	}
+-}
+-
+-static int atl1_get_settings(struct net_device *netdev,
+-				struct ethtool_cmd *ecmd)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct atl1_hw *hw = &adapter->hw;
+-
+-	ecmd->supported = (SUPPORTED_10baseT_Half |
+-			   SUPPORTED_10baseT_Full |
+-			   SUPPORTED_100baseT_Half |
+-			   SUPPORTED_100baseT_Full |
+-			   SUPPORTED_1000baseT_Full |
+-			   SUPPORTED_Autoneg | SUPPORTED_TP);
+-	ecmd->advertising = ADVERTISED_TP;
+-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+-	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
+-		ecmd->advertising |= ADVERTISED_Autoneg;
+-		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
+-			ecmd->advertising |= ADVERTISED_Autoneg;
+-			ecmd->advertising |=
+-			    (ADVERTISED_10baseT_Half |
+-			     ADVERTISED_10baseT_Full |
+-			     ADVERTISED_100baseT_Half |
+-			     ADVERTISED_100baseT_Full |
+-			     ADVERTISED_1000baseT_Full);
+-		}
+-		else
+-			ecmd->advertising |= (ADVERTISED_1000baseT_Full);
+-	}
+-	ecmd->port = PORT_TP;
+-	ecmd->phy_address = 0;
+-	ecmd->transceiver = XCVR_INTERNAL;
+-
+-	if (netif_carrier_ok(adapter->netdev)) {
+-		u16 link_speed, link_duplex;
+-		atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
+-		ecmd->speed = link_speed;
+-		if (link_duplex == FULL_DUPLEX)
+-			ecmd->duplex = DUPLEX_FULL;
+-		else
+-			ecmd->duplex = DUPLEX_HALF;
+-	} else {
+-		ecmd->speed = -1;
+-		ecmd->duplex = -1;
+-	}
+-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+-	    hw->media_type == MEDIA_TYPE_1000M_FULL)
+-		ecmd->autoneg = AUTONEG_ENABLE;
+-	else
+-		ecmd->autoneg = AUTONEG_DISABLE;
+-
+-	return 0;
+-}
+-
+-static int atl1_set_settings(struct net_device *netdev,
+-				struct ethtool_cmd *ecmd)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct atl1_hw *hw = &adapter->hw;
+-	u16 phy_data;
+-	int ret_val = 0;
+-	u16 old_media_type = hw->media_type;
+-
+-	if (netif_running(adapter->netdev)) {
+-		dev_dbg(&adapter->pdev->dev, "ethtool shutting down adapter\n");
+-		atl1_down(adapter);
+-	}
+-
+-	if (ecmd->autoneg == AUTONEG_ENABLE)
+-		hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
+-	else {
+-		if (ecmd->speed == SPEED_1000) {
+-			if (ecmd->duplex != DUPLEX_FULL) {
+-				dev_warn(&adapter->pdev->dev,
+-					"can't force to 1000M half duplex\n");
+-				ret_val = -EINVAL;
+-				goto exit_sset;
+-			}
+-			hw->media_type = MEDIA_TYPE_1000M_FULL;
+-		} else if (ecmd->speed == SPEED_100) {
+-			if (ecmd->duplex == DUPLEX_FULL) {
+-				hw->media_type = MEDIA_TYPE_100M_FULL;
+-			} else
+-				hw->media_type = MEDIA_TYPE_100M_HALF;
+-		} else {
+-			if (ecmd->duplex == DUPLEX_FULL)
+-				hw->media_type = MEDIA_TYPE_10M_FULL;
+-			else
+-				hw->media_type = MEDIA_TYPE_10M_HALF;
+-		}
+-	}
+-	switch (hw->media_type) {
+-	case MEDIA_TYPE_AUTO_SENSOR:
+-		ecmd->advertising =
+-		    ADVERTISED_10baseT_Half |
+-		    ADVERTISED_10baseT_Full |
+-		    ADVERTISED_100baseT_Half |
+-		    ADVERTISED_100baseT_Full |
+-		    ADVERTISED_1000baseT_Full |
+-		    ADVERTISED_Autoneg | ADVERTISED_TP;
+-		break;
+-	case MEDIA_TYPE_1000M_FULL:
+-		ecmd->advertising =
+-		    ADVERTISED_1000baseT_Full |
+-		    ADVERTISED_Autoneg | ADVERTISED_TP;
+-		break;
+-	default:
+-		ecmd->advertising = 0;
+-		break;
+-	}
+-	if (atl1_phy_setup_autoneg_adv(hw)) {
+-		ret_val = -EINVAL;
+-		dev_warn(&adapter->pdev->dev,
+-			"invalid ethtool speed/duplex setting\n");
+-		goto exit_sset;
+-	}
+-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+-	    hw->media_type == MEDIA_TYPE_1000M_FULL)
+-		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+-	else {
+-		switch (hw->media_type) {
+-		case MEDIA_TYPE_100M_FULL:
+-			phy_data =
+-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+-			    MII_CR_RESET;
+-			break;
+-		case MEDIA_TYPE_100M_HALF:
+-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+-			break;
+-		case MEDIA_TYPE_10M_FULL:
+-			phy_data =
+-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+-			break;
+-		default:	/* MEDIA_TYPE_10M_HALF: */
+-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+-			break;
+-		}
+-	}
+-	atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+-exit_sset:
+-	if (ret_val)
+-		hw->media_type = old_media_type;
+-
+-	if (netif_running(adapter->netdev)) {
+-		dev_dbg(&adapter->pdev->dev, "ethtool starting adapter\n");
+-		atl1_up(adapter);
+-	} else if (!ret_val) {
+-		dev_dbg(&adapter->pdev->dev, "ethtool resetting adapter\n");
+-		atl1_reset(adapter);
+-	}
+-	return ret_val;
+-}
+-
+-static void atl1_get_drvinfo(struct net_device *netdev,
+-				struct ethtool_drvinfo *drvinfo)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-
+-	strncpy(drvinfo->driver, atl1_driver_name, sizeof(drvinfo->driver));
+-	strncpy(drvinfo->version, atl1_driver_version,
+-		sizeof(drvinfo->version));
+-	strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+-		sizeof(drvinfo->bus_info));
+-	drvinfo->eedump_len = ATL1_EEDUMP_LEN;
+-}
+-
+-static void atl1_get_wol(struct net_device *netdev,
+-			    struct ethtool_wolinfo *wol)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-
+-	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+-	wol->wolopts = 0;
+-	if (adapter->wol & ATL1_WUFC_EX)
+-		wol->wolopts |= WAKE_UCAST;
+-	if (adapter->wol & ATL1_WUFC_MC)
+-		wol->wolopts |= WAKE_MCAST;
+-	if (adapter->wol & ATL1_WUFC_BC)
+-		wol->wolopts |= WAKE_BCAST;
+-	if (adapter->wol & ATL1_WUFC_MAG)
+-		wol->wolopts |= WAKE_MAGIC;
+-	return;
+-}
+-
+-static int atl1_set_wol(struct net_device *netdev,
+-			struct ethtool_wolinfo *wol)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-
+-	if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+-		return -EOPNOTSUPP;
+-	adapter->wol = 0;
+-	if (wol->wolopts & WAKE_UCAST)
+-		adapter->wol |= ATL1_WUFC_EX;
+-	if (wol->wolopts & WAKE_MCAST)
+-		adapter->wol |= ATL1_WUFC_MC;
+-	if (wol->wolopts & WAKE_BCAST)
+-		adapter->wol |= ATL1_WUFC_BC;
+-	if (wol->wolopts & WAKE_MAGIC)
+-		adapter->wol |= ATL1_WUFC_MAG;
+-	return 0;
+-}
+-
+-static void atl1_get_ringparam(struct net_device *netdev,
+-			    struct ethtool_ringparam *ring)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
+-	struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
+-
+-	ring->rx_max_pending = ATL1_MAX_RFD;
+-	ring->tx_max_pending = ATL1_MAX_TPD;
+-	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;
+-}
+-
+-static int atl1_set_ringparam(struct net_device *netdev,
+-				struct ethtool_ringparam *ring)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
+-	struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
+-	struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
+-
+-	struct atl1_tpd_ring tpd_old, tpd_new;
+-	struct atl1_rfd_ring rfd_old, rfd_new;
+-	struct atl1_rrd_ring rrd_old, rrd_new;
+-	struct atl1_ring_header rhdr_old, rhdr_new;
+-	int err;
+-
+-	tpd_old = adapter->tpd_ring;
+-	rfd_old = adapter->rfd_ring;
+-	rrd_old = adapter->rrd_ring;
+-	rhdr_old = adapter->ring_header;
+-
+-	if (netif_running(adapter->netdev))
+-		atl1_down(adapter);
+-
+-	rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
+-	rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
+-			rfdr->count;
+-	rfdr->count = (rfdr->count + 3) & ~3;
+-	rrdr->count = rfdr->count;
+-
+-	tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
+-	tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
+-			tpdr->count;
+-	tpdr->count = (tpdr->count + 3) & ~3;
+-
+-	if (netif_running(adapter->netdev)) {
+-		/* try to get new resources before deleting old */
+-		err = atl1_setup_ring_resources(adapter);
+-		if (err)
+-			goto err_setup_ring;
+-
+-		/*
+-		 * save the new, restore the old in order to free it,
+-		 * then restore the new back again
+-		 */
+-
+-		rfd_new = adapter->rfd_ring;
+-		rrd_new = adapter->rrd_ring;
+-		tpd_new = adapter->tpd_ring;
+-		rhdr_new = adapter->ring_header;
+-		adapter->rfd_ring = rfd_old;
+-		adapter->rrd_ring = rrd_old;
+-		adapter->tpd_ring = tpd_old;
+-		adapter->ring_header = rhdr_old;
+-		atl1_free_ring_resources(adapter);
+-		adapter->rfd_ring = rfd_new;
+-		adapter->rrd_ring = rrd_new;
+-		adapter->tpd_ring = tpd_new;
+-		adapter->ring_header = rhdr_new;
+-
+-		err = atl1_up(adapter);
+-		if (err)
+-			return err;
+-	}
+-	return 0;
+-
+-err_setup_ring:
+-	adapter->rfd_ring = rfd_old;
+-	adapter->rrd_ring = rrd_old;
+-	adapter->tpd_ring = tpd_old;
+-	adapter->ring_header = rhdr_old;
+-	atl1_up(adapter);
+-	return err;
+-}
+-
+-static void atl1_get_pauseparam(struct net_device *netdev,
+-			     struct ethtool_pauseparam *epause)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct atl1_hw *hw = &adapter->hw;
+-
+-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+-	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
+-		epause->autoneg = AUTONEG_ENABLE;
+-	} else {
+-		epause->autoneg = AUTONEG_DISABLE;
+-	}
+-	epause->rx_pause = 1;
+-	epause->tx_pause = 1;
+-}
+-
+-static int atl1_set_pauseparam(struct net_device *netdev,
+-			     struct ethtool_pauseparam *epause)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct atl1_hw *hw = &adapter->hw;
+-
+-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+-	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
+-		epause->autoneg = AUTONEG_ENABLE;
+-	} else {
+-		epause->autoneg = AUTONEG_DISABLE;
+-	}
+-
+-	epause->rx_pause = 1;
+-	epause->tx_pause = 1;
+-
+-	return 0;
+-}
+-
+-static u32 atl1_get_rx_csum(struct net_device *netdev)
+-{
+-	return 1;
+-}
+-
+-static void atl1_get_strings(struct net_device *netdev, u32 stringset,
+-				u8 *data)
+-{
+-	u8 *p = data;
+-	int i;
+-
+-	switch (stringset) {
+-	case ETH_SS_STATS:
+-		for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+-			memcpy(p, atl1_gstrings_stats[i].stat_string,
+-				ETH_GSTRING_LEN);
+-			p += ETH_GSTRING_LEN;
+-		}
+-		break;
+-	}
+-}
+-
+-static int atl1_nway_reset(struct net_device *netdev)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct atl1_hw *hw = &adapter->hw;
+-
+-	if (netif_running(netdev)) {
+-		u16 phy_data;
+-		atl1_down(adapter);
+-
+-		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+-			hw->media_type == MEDIA_TYPE_1000M_FULL) {
+-			phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+-		} else {
+-			switch (hw->media_type) {
+-			case MEDIA_TYPE_100M_FULL:
+-				phy_data = MII_CR_FULL_DUPLEX |
+-					MII_CR_SPEED_100 | MII_CR_RESET;
+-				break;
+-			case MEDIA_TYPE_100M_HALF:
+-				phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+-				break;
+-			case MEDIA_TYPE_10M_FULL:
+-				phy_data = MII_CR_FULL_DUPLEX |
+-					MII_CR_SPEED_10 | MII_CR_RESET;
+-				break;
+-			default:  /* MEDIA_TYPE_10M_HALF */
+-				phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+-			}
+-		}
+-		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+-		atl1_up(adapter);
+-	}
+-	return 0;
+-}
+-
+-const struct ethtool_ops atl1_ethtool_ops = {
+-	.get_settings		= atl1_get_settings,
+-	.set_settings		= atl1_set_settings,
+-	.get_drvinfo		= atl1_get_drvinfo,
+-	.get_wol		= atl1_get_wol,
+-	.set_wol		= atl1_set_wol,
+-	.get_ringparam		= atl1_get_ringparam,
+-	.set_ringparam		= atl1_set_ringparam,
+-	.get_pauseparam		= atl1_get_pauseparam,
+-	.set_pauseparam 	= atl1_set_pauseparam,
+-	.get_rx_csum		= atl1_get_rx_csum,
+-	.set_tx_csum		= ethtool_op_set_tx_hw_csum,
+-	.get_link		= ethtool_op_get_link,
+-	.set_sg			= ethtool_op_set_sg,
+-	.get_strings		= atl1_get_strings,
+-	.nway_reset		= atl1_nway_reset,
+-	.get_ethtool_stats	= atl1_get_ethtool_stats,
+-	.get_sset_count		= atl1_get_sset_count,
+-	.set_tso		= ethtool_op_set_tso,
+-};
+diff --git a/drivers/net/atl1/atl1_hw.c b/drivers/net/atl1/atl1_hw.c
+deleted file mode 100644
+index 9d3bd22..0000000
+--- a/drivers/net/atl1/atl1_hw.c
++++ /dev/null
+@@ -1,720 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * Derived from Intel e1000 driver
+- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc., 59
+- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/pci.h>
+-#include <linux/delay.h>
+-#include <linux/if_vlan.h>
+-#include <linux/etherdevice.h>
+-#include <linux/crc32.h>
+-#include <asm/byteorder.h>
+-
+-#include "atl1.h"
+-
+-/*
+- * Reset the transmit and receive units; mask and clear all interrupts.
+- * hw - Struct containing variables accessed by shared code
+- * return : ATL1_SUCCESS  or  idle status (if error)
+- */
+-s32 atl1_reset_hw(struct atl1_hw *hw)
+-{
+-	struct pci_dev *pdev = hw->back->pdev;
+-	u32 icr;
+-	int i;
+-
+-	/*
+-	 * Clear Interrupt mask to stop board from generating
+-	 * interrupts & Clear any pending interrupt events
+-	 */
+-	/*
+-	 * iowrite32(0, hw->hw_addr + REG_IMR);
+-	 * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
+-	 */
+-
+-	/*
+-	 * Issue Soft Reset to the MAC.  This will reset the chip's
+-	 * transmit, receive, DMA.  It will not effect
+-	 * the current PCI configuration.  The global reset bit is self-
+-	 * clearing, and should clear within a microsecond.
+-	 */
+-	iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
+-	ioread32(hw->hw_addr + REG_MASTER_CTRL);
+-
+-	iowrite16(1, hw->hw_addr + REG_GPHY_ENABLE);
+-	ioread16(hw->hw_addr + REG_GPHY_ENABLE);
+-
+-	msleep(1);		/* delay about 1ms */
+-
+-	/* Wait at least 10ms for All module to be Idle */
+-	for (i = 0; i < 10; i++) {
+-		icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
+-		if (!icr)
+-			break;
+-		msleep(1);	/* delay 1 ms */
+-		cpu_relax();	/* FIXME: is this still the right way to do this? */
+-	}
+-
+-	if (icr) {
+-		dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
+-		return icr;
+-	}
+-
+-	return ATL1_SUCCESS;
+-}
+-
+-/* function about EEPROM
+- *
+- * check_eeprom_exist
+- * return 0 if eeprom exist
+- */
+-static int atl1_check_eeprom_exist(struct atl1_hw *hw)
+-{
+-	u32 value;
+-	value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+-	if (value & SPI_FLASH_CTRL_EN_VPD) {
+-		value &= ~SPI_FLASH_CTRL_EN_VPD;
+-		iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+-	}
+-
+-	value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
+-	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+-}
+-
+-static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
+-{
+-	int i;
+-	u32 control;
+-
+-	if (offset & 3)
+-		return false;	/* address do not align */
+-
+-	iowrite32(0, hw->hw_addr + REG_VPD_DATA);
+-	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+-	iowrite32(control, hw->hw_addr + REG_VPD_CAP);
+-	ioread32(hw->hw_addr + REG_VPD_CAP);
+-
+-	for (i = 0; i < 10; i++) {
+-		msleep(2);
+-		control = ioread32(hw->hw_addr + REG_VPD_CAP);
+-		if (control & VPD_CAP_VPD_FLAG)
+-			break;
+-	}
+-	if (control & VPD_CAP_VPD_FLAG) {
+-		*p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
+-		return true;
+-	}
+-	return false;		/* timeout */
+-}
+-
+-/*
+- * Reads the value from a PHY register
+- * hw - Struct containing variables accessed by shared code
+- * reg_addr - address of the PHY register to read
+- */
+-s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
+-{
+-	u32 val;
+-	int i;
+-
+-	val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+-		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
+-		MDIO_CLK_SEL_SHIFT;
+-	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+-	ioread32(hw->hw_addr + REG_MDIO_CTRL);
+-
+-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+-		udelay(2);
+-		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+-		if (!(val & (MDIO_START | MDIO_BUSY)))
+-			break;
+-	}
+-	if (!(val & (MDIO_START | MDIO_BUSY))) {
+-		*phy_data = (u16) val;
+-		return ATL1_SUCCESS;
+-	}
+-	return ATL1_ERR_PHY;
+-}
+-
+-#define CUSTOM_SPI_CS_SETUP	2
+-#define CUSTOM_SPI_CLK_HI	2
+-#define CUSTOM_SPI_CLK_LO	2
+-#define CUSTOM_SPI_CS_HOLD	2
+-#define CUSTOM_SPI_CS_HI	3
+-
+-static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
+-{
+-	int i;
+-	u32 value;
+-
+-	iowrite32(0, hw->hw_addr + REG_SPI_DATA);
+-	iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
+-
+-	value = SPI_FLASH_CTRL_WAIT_READY |
+-	    (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
+-	    SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
+-					     SPI_FLASH_CTRL_CLK_HI_MASK) <<
+-	    SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
+-					   SPI_FLASH_CTRL_CLK_LO_MASK) <<
+-	    SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
+-					   SPI_FLASH_CTRL_CS_HOLD_MASK) <<
+-	    SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
+-					    SPI_FLASH_CTRL_CS_HI_MASK) <<
+-	    SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
+-	    SPI_FLASH_CTRL_INS_SHIFT;
+-
+-	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+-
+-	value |= SPI_FLASH_CTRL_START;
+-	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+-	ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+-
+-	for (i = 0; i < 10; i++) {
+-		msleep(1);	/* 1ms */
+-		value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+-		if (!(value & SPI_FLASH_CTRL_START))
+-			break;
+-	}
+-
+-	if (value & SPI_FLASH_CTRL_START)
+-		return false;
+-
+-	*buf = ioread32(hw->hw_addr + REG_SPI_DATA);
+-
+-	return true;
+-}
+-
+-/*
+- * get_permanent_address
+- * return 0 if get valid mac address,
+- */
+-static int atl1_get_permanent_address(struct atl1_hw *hw)
+-{
+-	u32 addr[2];
+-	u32 i, control;
+-	u16 reg;
+-	u8 eth_addr[ETH_ALEN];
+-	bool key_valid;
+-
+-	if (is_valid_ether_addr(hw->perm_mac_addr))
+-		return 0;
+-
+-	/* init */
+-	addr[0] = addr[1] = 0;
+-
+-	if (!atl1_check_eeprom_exist(hw)) {	/* eeprom exist */
+-		reg = 0;
+-		key_valid = false;
+-		/* Read out all EEPROM content */
+-		i = 0;
+-		while (1) {
+-			if (atl1_read_eeprom(hw, i + 0x100, &control)) {
+-				if (key_valid) {
+-					if (reg == REG_MAC_STA_ADDR)
+-						addr[0] = control;
+-					else if (reg == (REG_MAC_STA_ADDR + 4))
+-						addr[1] = control;
+-					key_valid = false;
+-				} else if ((control & 0xff) == 0x5A) {
+-					key_valid = true;
+-					reg = (u16) (control >> 16);
+-				} else
+-					break;	/* assume data end while encount an invalid KEYWORD */
+-			} else
+-				break;	/* read error */
+-			i += 4;
+-		}
+-
+-		*(u32 *) &eth_addr[2] = swab32(addr[0]);
+-		*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+-		if (is_valid_ether_addr(eth_addr)) {
+-			memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+-			return 0;
+-		}
+-		return 1;
+-	}
+-
+-	/* see if SPI FLAGS exist ? */
+-	addr[0] = addr[1] = 0;
+-	reg = 0;
+-	key_valid = false;
+-	i = 0;
+-	while (1) {
+-		if (atl1_spi_read(hw, i + 0x1f000, &control)) {
+-			if (key_valid) {
+-				if (reg == REG_MAC_STA_ADDR)
+-					addr[0] = control;
+-				else if (reg == (REG_MAC_STA_ADDR + 4))
+-					addr[1] = control;
+-				key_valid = false;
+-			} else if ((control & 0xff) == 0x5A) {
+-				key_valid = true;
+-				reg = (u16) (control >> 16);
+-			} else
+-				break;	/* data end */
+-		} else
+-			break;	/* read error */
+-		i += 4;
+-	}
+-
+-	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+-	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+-	if (is_valid_ether_addr(eth_addr)) {
+-		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+-		return 0;
+-	}
+-
+-	/*
+-	 * On some motherboards, the MAC address is written by the
+-	 * BIOS directly to the MAC register during POST, and is
+-	 * not stored in eeprom.  If all else thus far has failed
+-	 * to fetch the permanent MAC address, try reading it directly.
+-	 */
+-	addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
+-	addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+-	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+-	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+-	if (is_valid_ether_addr(eth_addr)) {
+-		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+-		return 0;
+-	}
+-
+-	return 1;
+-}
+-
+-/*
+- * Reads the adapter's MAC address from the EEPROM
+- * hw - Struct containing variables accessed by shared code
+- */
+-s32 atl1_read_mac_addr(struct atl1_hw *hw)
+-{
+-	u16 i;
+-
+-	if (atl1_get_permanent_address(hw))
+-		random_ether_addr(hw->perm_mac_addr);
+-
+-	for (i = 0; i < ETH_ALEN; i++)
+-		hw->mac_addr[i] = hw->perm_mac_addr[i];
+-	return ATL1_SUCCESS;
+-}
+-
+-/*
+- * Hashes an address to determine its location in the multicast table
+- * hw - Struct containing variables accessed by shared code
+- * mc_addr - the multicast address to hash
+- *
+- * atl1_hash_mc_addr
+- *  purpose
+- *      set hash value for a multicast address
+- *      hash calcu processing :
+- *          1. calcu 32bit CRC for multicast address
+- *          2. reverse crc with MSB to LSB
+- */
+-u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
+-{
+-	u32 crc32, value = 0;
+-	int i;
+-
+-	crc32 = ether_crc_le(6, mc_addr);
+-	for (i = 0; i < 32; i++)
+-		value |= (((crc32 >> i) & 1) << (31 - i));
+-
+-	return value;
+-}
+-
+-/*
+- * Sets the bit in the multicast table corresponding to the hash value.
+- * hw - Struct containing variables accessed by shared code
+- * hash_value - Multicast address hash value
+- */
+-void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
+-{
+-	u32 hash_bit, hash_reg;
+-	u32 mta;
+-
+-	/*
+-	 * The HASH Table  is a register array of 2 32-bit registers.
+-	 * It is treated like an array of 64 bits.  We want to set
+-	 * bit BitArray[hash_value]. So we figure out what register
+-	 * the bit is in, read it, OR in the new bit, then write
+-	 * back the new value.  The register is determined by the
+-	 * upper 7 bits of the hash value and the bit within that
+-	 * register are determined by the lower 5 bits of the value.
+-	 */
+-	hash_reg = (hash_value >> 31) & 0x1;
+-	hash_bit = (hash_value >> 26) & 0x1F;
+-	mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+-	mta |= (1 << hash_bit);
+-	iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+-}
+-
+-/*
+- * Writes a value to a PHY register
+- * hw - Struct containing variables accessed by shared code
+- * reg_addr - address of the PHY register to write
+- * data - data to write to the PHY
+- */
+-s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
+-{
+-	int i;
+-	u32 val;
+-
+-	val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+-	    (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+-	    MDIO_SUP_PREAMBLE |
+-	    MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+-	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+-	ioread32(hw->hw_addr + REG_MDIO_CTRL);
+-
+-	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+-		udelay(2);
+-		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+-		if (!(val & (MDIO_START | MDIO_BUSY)))
+-			break;
+-	}
+-
+-	if (!(val & (MDIO_START | MDIO_BUSY)))
+-		return ATL1_SUCCESS;
+-
+-	return ATL1_ERR_PHY;
+-}
+-
+-/*
+- * Make L001's PHY out of Power Saving State (bug)
+- * hw - Struct containing variables accessed by shared code
+- * when power on, L001's PHY always on Power saving State
+- * (Gigabit Link forbidden)
+- */
+-static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
+-{
+-	s32 ret;
+-	ret = atl1_write_phy_reg(hw, 29, 0x0029);
+-	if (ret)
+-		return ret;
+-	return atl1_write_phy_reg(hw, 30, 0);
+-}
+-
+-/*
+- *TODO: do something or get rid of this
+- */
+-s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
+-{
+-/*    s32 ret_val;
+- *    u16 phy_data;
+- */
+-
+-/*
+-    ret_val = atl1_write_phy_reg(hw, ...);
+-    ret_val = atl1_write_phy_reg(hw, ...);
+-    ....
+-*/
+-	return ATL1_SUCCESS;
+-}
+-
+-/*
+- * Resets the PHY and make all config validate
+- * hw - Struct containing variables accessed by shared code
+- *
+- * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
+- */
+-static s32 atl1_phy_reset(struct atl1_hw *hw)
+-{
+-	struct pci_dev *pdev = hw->back->pdev;
+-	s32 ret_val;
+-	u16 phy_data;
+-
+-	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+-	    hw->media_type == MEDIA_TYPE_1000M_FULL)
+-		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+-	else {
+-		switch (hw->media_type) {
+-		case MEDIA_TYPE_100M_FULL:
+-			phy_data =
+-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+-			    MII_CR_RESET;
+-			break;
+-		case MEDIA_TYPE_100M_HALF:
+-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+-			break;
+-		case MEDIA_TYPE_10M_FULL:
+-			phy_data =
+-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+-			break;
+-		default:	/* MEDIA_TYPE_10M_HALF: */
+-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+-			break;
+-		}
+-	}
+-
+-	ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+-	if (ret_val) {
+-		u32 val;
+-		int i;
+-		/* pcie serdes link may be down! */
+-		dev_dbg(&pdev->dev, "pcie phy link down\n");
+-
+-		for (i = 0; i < 25; i++) {
+-			msleep(1);
+-			val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+-			if (!(val & (MDIO_START | MDIO_BUSY)))
+-				break;
+-		}
+-
+-		if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
+-			dev_warn(&pdev->dev, "pcie link down at least 25ms\n");
+-			return ret_val;
+-		}
+-	}
+-	return ATL1_SUCCESS;
+-}
+-
+-/*
+- * Configures PHY autoneg and flow control advertisement settings
+- * hw - Struct containing variables accessed by shared code
+- */
+-s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
+-{
+-	s32 ret_val;
+-	s16 mii_autoneg_adv_reg;
+-	s16 mii_1000t_ctrl_reg;
+-
+-	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
+-	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+-
+-	/* Read the MII 1000Base-T Control Register (Address 9). */
+-	mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+-
+-	/*
+-	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
+-	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
+-	 * the  1000Base-T Control Register (Address 9).
+-	 */
+-	mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+-	mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
+-
+-	/*
+-	 * Need to parse media_type  and set up
+-	 * the appropriate PHY registers.
+-	 */
+-	switch (hw->media_type) {
+-	case MEDIA_TYPE_AUTO_SENSOR:
+-		mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+-					MII_AR_10T_FD_CAPS |
+-					MII_AR_100TX_HD_CAPS |
+-					MII_AR_100TX_FD_CAPS);
+-		mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+-		break;
+-
+-	case MEDIA_TYPE_1000M_FULL:
+-		mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+-		break;
+-
+-	case MEDIA_TYPE_100M_FULL:
+-		mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
+-		break;
+-
+-	case MEDIA_TYPE_100M_HALF:
+-		mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
+-		break;
+-
+-	case MEDIA_TYPE_10M_FULL:
+-		mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
+-		break;
+-
+-	default:
+-		mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
+-		break;
+-	}
+-
+-	/* flow control fixed to enable all */
+-	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+-
+-	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+-	hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+-
+-	ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+-	if (ret_val)
+-		return ret_val;
+-
+-	ret_val = atl1_write_phy_reg(hw, MII_AT001_CR, mii_1000t_ctrl_reg);
+-	if (ret_val)
+-		return ret_val;
+-
+-	return ATL1_SUCCESS;
+-}
+-
+-/*
+- * Configures link settings.
+- * hw - Struct containing variables accessed by shared code
+- * Assumes the hardware has previously been reset and the
+- * transmitter and receiver are not enabled.
+- */
+-static s32 atl1_setup_link(struct atl1_hw *hw)
+-{
+-	struct pci_dev *pdev = hw->back->pdev;
+-	s32 ret_val;
+-
+-	/*
+-	 * Options:
+-	 *  PHY will advertise value(s) parsed from
+-	 *  autoneg_advertised and fc
+-	 *  no matter what autoneg is , We will not wait link result.
+-	 */
+-	ret_val = atl1_phy_setup_autoneg_adv(hw);
+-	if (ret_val) {
+-		dev_dbg(&pdev->dev, "error setting up autonegotiation\n");
+-		return ret_val;
+-	}
+-	/* SW.Reset , En-Auto-Neg if needed */
+-	ret_val = atl1_phy_reset(hw);
+-	if (ret_val) {
+-		dev_dbg(&pdev->dev, "error resetting phy\n");
+-		return ret_val;
+-	}
+-	hw->phy_configured = true;
+-	return ret_val;
+-}
+-
+-static struct atl1_spi_flash_dev flash_table[] = {
+-/*	MFR_NAME  WRSR  READ  PRGM  WREN  WRDI  RDSR  RDID  SECTOR_ERASE CHIP_ERASE */
+-	{"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52,        0x62},
+-	{"SST",   0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20,        0x60},
+-	{"ST",    0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8,        0xC7},
+-};
+-
+-static void atl1_init_flash_opcode(struct atl1_hw *hw)
+-{
+-	if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
+-		hw->flash_vendor = 0;	/* ATMEL */
+-
+-	/* Init OP table */
+-	iowrite8(flash_table[hw->flash_vendor].cmd_program,
+-		hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
+-	iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
+-		hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
+-	iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
+-		hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
+-	iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
+-		hw->hw_addr + REG_SPI_FLASH_OP_RDID);
+-	iowrite8(flash_table[hw->flash_vendor].cmd_wren,
+-		hw->hw_addr + REG_SPI_FLASH_OP_WREN);
+-	iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
+-		hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
+-	iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
+-		hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
+-	iowrite8(flash_table[hw->flash_vendor].cmd_read,
+-		hw->hw_addr + REG_SPI_FLASH_OP_READ);
+-}
+-
+-/*
+- * Performs basic configuration of the adapter.
+- * hw - Struct containing variables accessed by shared code
+- * Assumes that the controller has previously been reset and is in a
+- * post-reset uninitialized state. Initializes multicast table,
+- * and  Calls routines to setup link
+- * Leaves the transmit and receive units disabled and uninitialized.
+- */
+-s32 atl1_init_hw(struct atl1_hw *hw)
+-{
+-	u32 ret_val = 0;
+-
+-	/* Zero out the Multicast HASH table */
+-	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+-	/* clear the old settings from the multicast hash table */
+-	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+-
+-	atl1_init_flash_opcode(hw);
+-
+-	if (!hw->phy_configured) {
+-		/* enable GPHY LinkChange Interrrupt */
+-		ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
+-		if (ret_val)
+-			return ret_val;
+-		/* make PHY out of power-saving state */
+-		ret_val = atl1_phy_leave_power_saving(hw);
+-		if (ret_val)
+-			return ret_val;
+-		/* Call a subroutine to configure the link */
+-		ret_val = atl1_setup_link(hw);
+-	}
+-	return ret_val;
+-}
+-
+-/*
+- * Detects the current speed and duplex settings of the hardware.
+- * hw - Struct containing variables accessed by shared code
+- * speed - Speed of the connection
+- * duplex - Duplex setting of the connection
+- */
+-s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
+-{
+-	struct pci_dev *pdev = hw->back->pdev;
+-	s32 ret_val;
+-	u16 phy_data;
+-
+-	/* ; --- Read   PHY Specific Status Register (17) */
+-	ret_val = atl1_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+-	if (ret_val)
+-		return ret_val;
+-
+-	if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+-		return ATL1_ERR_PHY_RES;
+-
+-	switch (phy_data & MII_AT001_PSSR_SPEED) {
+-	case MII_AT001_PSSR_1000MBS:
+-		*speed = SPEED_1000;
+-		break;
+-	case MII_AT001_PSSR_100MBS:
+-		*speed = SPEED_100;
+-		break;
+-	case MII_AT001_PSSR_10MBS:
+-		*speed = SPEED_10;
+-		break;
+-	default:
+-		dev_dbg(&pdev->dev, "error getting speed\n");
+-		return ATL1_ERR_PHY_SPEED;
+-		break;
+-	}
+-	if (phy_data & MII_AT001_PSSR_DPLX)
+-		*duplex = FULL_DUPLEX;
+-	else
+-		*duplex = HALF_DUPLEX;
+-
+-	return ATL1_SUCCESS;
+-}
+-
+-void atl1_set_mac_addr(struct atl1_hw *hw)
+-{
+-	u32 value;
+-	/*
+-	 * 00-0B-6A-F6-00-DC
+-	 * 0:  6AF600DC   1: 000B
+-	 * low dword
+-	 */
+-	value = (((u32) hw->mac_addr[2]) << 24) |
+-	    (((u32) hw->mac_addr[3]) << 16) |
+-	    (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
+-	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+-	/* high dword */
+-	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+-	iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
+-}
+diff --git a/drivers/net/atl1/atl1_hw.h b/drivers/net/atl1/atl1_hw.h
+deleted file mode 100644
+index 939aa0f..0000000
+--- a/drivers/net/atl1/atl1_hw.h
++++ /dev/null
+@@ -1,946 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * Derived from Intel e1000 driver
+- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc., 59
+- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+- *
+- * There are a lot of defines in here that are unused and/or have cryptic
+- * names.  Please leave them alone, as they're the closest thing we have
+- * to a spec from Attansic at present. *ahem* -- CHS
+- */
+-
+-#ifndef _ATL1_HW_H_
+-#define _ATL1_HW_H_
+-
+-#include <linux/types.h>
+-#include <linux/mii.h>
+-
+-struct atl1_adapter;
+-struct atl1_hw;
+-
+-/* function prototypes needed by multiple files */
+-s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw);
+-s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data);
+-s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
+-s32 atl1_read_mac_addr(struct atl1_hw *hw);
+-s32 atl1_init_hw(struct atl1_hw *hw);
+-s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
+-s32 atl1_set_speed_and_duplex(struct atl1_hw *hw, u16 speed, u16 duplex);
+-u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
+-void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
+-s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
+-void atl1_set_mac_addr(struct atl1_hw *hw);
+-s32 atl1_phy_enter_power_saving(struct atl1_hw *hw);
+-s32 atl1_reset_hw(struct atl1_hw *hw);
+-void atl1_check_options(struct atl1_adapter *adapter);
+-
+-/* register definitions */
+-#define REG_PCIE_CAP_LIST			0x58
+-
+-#define REG_VPD_CAP				0x6C
+-#define VPD_CAP_ID_MASK				0xff
+-#define VPD_CAP_ID_SHIFT			0
+-#define VPD_CAP_NEXT_PTR_MASK			0xFF
+-#define VPD_CAP_NEXT_PTR_SHIFT			8
+-#define VPD_CAP_VPD_ADDR_MASK			0x7FFF
+-#define VPD_CAP_VPD_ADDR_SHIFT			16
+-#define VPD_CAP_VPD_FLAG			0x80000000
+-
+-#define REG_VPD_DATA				0x70
+-
+-#define REG_SPI_FLASH_CTRL			0x200
+-#define SPI_FLASH_CTRL_STS_NON_RDY		0x1
+-#define SPI_FLASH_CTRL_STS_WEN			0x2
+-#define SPI_FLASH_CTRL_STS_WPEN			0x80
+-#define SPI_FLASH_CTRL_DEV_STS_MASK		0xFF
+-#define SPI_FLASH_CTRL_DEV_STS_SHIFT		0
+-#define SPI_FLASH_CTRL_INS_MASK			0x7
+-#define SPI_FLASH_CTRL_INS_SHIFT		8
+-#define SPI_FLASH_CTRL_START			0x800
+-#define SPI_FLASH_CTRL_EN_VPD			0x2000
+-#define SPI_FLASH_CTRL_LDSTART			0x8000
+-#define SPI_FLASH_CTRL_CS_HI_MASK		0x3
+-#define SPI_FLASH_CTRL_CS_HI_SHIFT		16
+-#define SPI_FLASH_CTRL_CS_HOLD_MASK		0x3
+-#define SPI_FLASH_CTRL_CS_HOLD_SHIFT		18
+-#define SPI_FLASH_CTRL_CLK_LO_MASK		0x3
+-#define SPI_FLASH_CTRL_CLK_LO_SHIFT		20
+-#define SPI_FLASH_CTRL_CLK_HI_MASK		0x3
+-#define SPI_FLASH_CTRL_CLK_HI_SHIFT		22
+-#define SPI_FLASH_CTRL_CS_SETUP_MASK		0x3
+-#define SPI_FLASH_CTRL_CS_SETUP_SHIFT		24
+-#define SPI_FLASH_CTRL_EROM_PGSZ_MASK		0x3
+-#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT		26
+-#define SPI_FLASH_CTRL_WAIT_READY		0x10000000
+-
+-#define REG_SPI_ADDR				0x204
+-
+-#define REG_SPI_DATA				0x208
+-
+-#define REG_SPI_FLASH_CONFIG			0x20C
+-#define SPI_FLASH_CONFIG_LD_ADDR_MASK		0xFFFFFF
+-#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT		0
+-#define SPI_FLASH_CONFIG_VPD_ADDR_MASK		0x3
+-#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT		24
+-#define SPI_FLASH_CONFIG_LD_EXIST		0x4000000
+-
+-#define REG_SPI_FLASH_OP_PROGRAM		0x210
+-#define REG_SPI_FLASH_OP_SC_ERASE		0x211
+-#define REG_SPI_FLASH_OP_CHIP_ERASE		0x212
+-#define REG_SPI_FLASH_OP_RDID			0x213
+-#define REG_SPI_FLASH_OP_WREN			0x214
+-#define REG_SPI_FLASH_OP_RDSR			0x215
+-#define REG_SPI_FLASH_OP_WRSR			0x216
+-#define REG_SPI_FLASH_OP_READ			0x217
+-
+-#define REG_TWSI_CTRL				0x218
+-#define TWSI_CTRL_LD_OFFSET_MASK		0xFF
+-#define TWSI_CTRL_LD_OFFSET_SHIFT		0
+-#define TWSI_CTRL_LD_SLV_ADDR_MASK		0x7
+-#define TWSI_CTRL_LD_SLV_ADDR_SHIFT		8
+-#define TWSI_CTRL_SW_LDSTART			0x800
+-#define TWSI_CTRL_HW_LDSTART			0x1000
+-#define TWSI_CTRL_SMB_SLV_ADDR_MASK		0x7F
+-#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT		15
+-#define TWSI_CTRL_LD_EXIST			0x400000
+-#define TWSI_CTRL_READ_FREQ_SEL_MASK		0x3
+-#define TWSI_CTRL_READ_FREQ_SEL_SHIFT		23
+-#define TWSI_CTRL_FREQ_SEL_100K			0
+-#define TWSI_CTRL_FREQ_SEL_200K			1
+-#define TWSI_CTRL_FREQ_SEL_300K			2
+-#define TWSI_CTRL_FREQ_SEL_400K			3
+-#define TWSI_CTRL_SMB_SLV_ADDR
+-#define TWSI_CTRL_WRITE_FREQ_SEL_MASK		0x3
+-#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT		24
+-
+-#define REG_PCIE_DEV_MISC_CTRL			0x21C
+-#define PCIE_DEV_MISC_CTRL_EXT_PIPE		0x2
+-#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS		0x1
+-#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST		0x4
+-#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN	0x8
+-#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN	0x10
+-
+-/* Selene Master Control Register */
+-#define REG_MASTER_CTRL				0x1400
+-#define MASTER_CTRL_SOFT_RST			0x1
+-#define MASTER_CTRL_MTIMER_EN			0x2
+-#define MASTER_CTRL_ITIMER_EN			0x4
+-#define MASTER_CTRL_MANUAL_INT			0x8
+-#define MASTER_CTRL_REV_NUM_SHIFT		16
+-#define MASTER_CTRL_REV_NUM_MASK		0xff
+-#define MASTER_CTRL_DEV_ID_SHIFT		24
+-#define MASTER_CTRL_DEV_ID_MASK			0xff
+-
+-/* Timer Initial Value Register */
+-#define REG_MANUAL_TIMER_INIT			0x1404
+-
+-/* IRQ ModeratorTimer Initial Value Register */
+-#define REG_IRQ_MODU_TIMER_INIT			0x1408
+-
+-#define REG_GPHY_ENABLE				0x140C
+-
+-/* IRQ Anti-Lost Timer Initial Value Register */
+-#define REG_CMBDISDMA_TIMER			0x140E
+-
+-/* Block IDLE Status Register */
+-#define REG_IDLE_STATUS				0x1410
+-#define IDLE_STATUS_RXMAC			1
+-#define IDLE_STATUS_TXMAC			2
+-#define IDLE_STATUS_RXQ				4
+-#define IDLE_STATUS_TXQ				8
+-#define IDLE_STATUS_DMAR			0x10
+-#define IDLE_STATUS_DMAW			0x20
+-#define IDLE_STATUS_SMB				0x40
+-#define IDLE_STATUS_CMB				0x80
+-
+-/* MDIO Control Register */
+-#define REG_MDIO_CTRL				0x1414
+-#define MDIO_DATA_MASK				0xffff
+-#define MDIO_DATA_SHIFT				0
+-#define MDIO_REG_ADDR_MASK			0x1f
+-#define MDIO_REG_ADDR_SHIFT			16
+-#define MDIO_RW					0x200000
+-#define MDIO_SUP_PREAMBLE			0x400000
+-#define MDIO_START				0x800000
+-#define MDIO_CLK_SEL_SHIFT			24
+-#define MDIO_CLK_25_4				0
+-#define MDIO_CLK_25_6				2
+-#define MDIO_CLK_25_8				3
+-#define MDIO_CLK_25_10				4
+-#define MDIO_CLK_25_14				5
+-#define MDIO_CLK_25_20				6
+-#define MDIO_CLK_25_28				7
+-#define MDIO_BUSY				0x8000000
+-#define MDIO_WAIT_TIMES				30
+-
+-/* MII PHY Status Register */
+-#define REG_PHY_STATUS				0x1418
+-
+-/* BIST Control and Status Register0 (for the Packet Memory) */
+-#define REG_BIST0_CTRL				0x141c
+-#define BIST0_NOW				0x1
+-#define BIST0_SRAM_FAIL				0x2
+-#define BIST0_FUSE_FLAG				0x4
+-#define REG_BIST1_CTRL				0x1420
+-#define BIST1_NOW				0x1
+-#define BIST1_SRAM_FAIL				0x2
+-#define BIST1_FUSE_FLAG				0x4
+-
+-/* MAC Control Register */
+-#define REG_MAC_CTRL				0x1480
+-#define MAC_CTRL_TX_EN				1
+-#define MAC_CTRL_RX_EN				2
+-#define MAC_CTRL_TX_FLOW			4
+-#define MAC_CTRL_RX_FLOW			8
+-#define MAC_CTRL_LOOPBACK			0x10
+-#define MAC_CTRL_DUPLX				0x20
+-#define MAC_CTRL_ADD_CRC			0x40
+-#define MAC_CTRL_PAD				0x80
+-#define MAC_CTRL_LENCHK				0x100
+-#define MAC_CTRL_HUGE_EN			0x200
+-#define MAC_CTRL_PRMLEN_SHIFT			10
+-#define MAC_CTRL_PRMLEN_MASK			0xf
+-#define MAC_CTRL_RMV_VLAN			0x4000
+-#define MAC_CTRL_PROMIS_EN			0x8000
+-#define MAC_CTRL_TX_PAUSE			0x10000
+-#define MAC_CTRL_SCNT				0x20000
+-#define MAC_CTRL_SRST_TX			0x40000
+-#define MAC_CTRL_TX_SIMURST			0x80000
+-#define MAC_CTRL_SPEED_SHIFT			20
+-#define MAC_CTRL_SPEED_MASK			0x300000
+-#define MAC_CTRL_SPEED_1000			2
+-#define MAC_CTRL_SPEED_10_100			1
+-#define MAC_CTRL_DBG_TX_BKPRESURE		0x400000
+-#define MAC_CTRL_TX_HUGE			0x800000
+-#define MAC_CTRL_RX_CHKSUM_EN			0x1000000
+-#define MAC_CTRL_MC_ALL_EN			0x2000000
+-#define MAC_CTRL_BC_EN				0x4000000
+-#define MAC_CTRL_DBG				0x8000000
+-
+-/* MAC IPG/IFG Control Register */
+-#define REG_MAC_IPG_IFG				0x1484
+-#define MAC_IPG_IFG_IPGT_SHIFT			0
+-#define MAC_IPG_IFG_IPGT_MASK			0x7f
+-#define MAC_IPG_IFG_MIFG_SHIFT			8
+-#define MAC_IPG_IFG_MIFG_MASK			0xff
+-#define MAC_IPG_IFG_IPGR1_SHIFT			16
+-#define MAC_IPG_IFG_IPGR1_MASK			0x7f
+-#define MAC_IPG_IFG_IPGR2_SHIFT			24
+-#define MAC_IPG_IFG_IPGR2_MASK			0x7f
+-
+-/* MAC STATION ADDRESS */
+-#define REG_MAC_STA_ADDR			0x1488
+-
+-/* Hash table for multicast address */
+-#define REG_RX_HASH_TABLE			0x1490
+-
+-/* MAC Half-Duplex Control Register */
+-#define REG_MAC_HALF_DUPLX_CTRL			0x1498
+-#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT		0
+-#define MAC_HALF_DUPLX_CTRL_LCOL_MASK		0x3ff
+-#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT		12
+-#define MAC_HALF_DUPLX_CTRL_RETRY_MASK		0xf
+-#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN		0x10000
+-#define MAC_HALF_DUPLX_CTRL_NO_BACK_C		0x20000
+-#define MAC_HALF_DUPLX_CTRL_NO_BACK_P		0x40000
+-#define MAC_HALF_DUPLX_CTRL_ABEBE		0x80000
+-#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT		20
+-#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK		0xf
+-#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT	24
+-#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK		0xf
+-
+-/* Maximum Frame Length Control Register */
+-#define REG_MTU					0x149c
+-
+-/* Wake-On-Lan control register */
+-#define REG_WOL_CTRL				0x14a0
+-#define WOL_PATTERN_EN				0x00000001
+-#define WOL_PATTERN_PME_EN			0x00000002
+-#define WOL_MAGIC_EN				0x00000004
+-#define WOL_MAGIC_PME_EN			0x00000008
+-#define WOL_LINK_CHG_EN				0x00000010
+-#define WOL_LINK_CHG_PME_EN			0x00000020
+-#define WOL_PATTERN_ST				0x00000100
+-#define WOL_MAGIC_ST				0x00000200
+-#define WOL_LINKCHG_ST				0x00000400
+-#define WOL_CLK_SWITCH_EN			0x00008000
+-#define WOL_PT0_EN				0x00010000
+-#define WOL_PT1_EN				0x00020000
+-#define WOL_PT2_EN				0x00040000
+-#define WOL_PT3_EN				0x00080000
+-#define WOL_PT4_EN				0x00100000
+-#define WOL_PT5_EN				0x00200000
+-#define WOL_PT6_EN				0x00400000
+-
+-/* WOL Length ( 2 DWORD ) */
+-#define REG_WOL_PATTERN_LEN			0x14a4
+-#define WOL_PT_LEN_MASK				0x7f
+-#define WOL_PT0_LEN_SHIFT			0
+-#define WOL_PT1_LEN_SHIFT			8
+-#define WOL_PT2_LEN_SHIFT			16
+-#define WOL_PT3_LEN_SHIFT			24
+-#define WOL_PT4_LEN_SHIFT			0
+-#define WOL_PT5_LEN_SHIFT			8
+-#define WOL_PT6_LEN_SHIFT			16
+-
+-/* Internal SRAM Partition Register */
+-#define REG_SRAM_RFD_ADDR			0x1500
+-#define REG_SRAM_RFD_LEN			(REG_SRAM_RFD_ADDR+ 4)
+-#define REG_SRAM_RRD_ADDR			(REG_SRAM_RFD_ADDR+ 8)
+-#define REG_SRAM_RRD_LEN			(REG_SRAM_RFD_ADDR+12)
+-#define REG_SRAM_TPD_ADDR			(REG_SRAM_RFD_ADDR+16)
+-#define REG_SRAM_TPD_LEN			(REG_SRAM_RFD_ADDR+20)
+-#define REG_SRAM_TRD_ADDR			(REG_SRAM_RFD_ADDR+24)
+-#define REG_SRAM_TRD_LEN			(REG_SRAM_RFD_ADDR+28)
+-#define REG_SRAM_RXF_ADDR			(REG_SRAM_RFD_ADDR+32)
+-#define REG_SRAM_RXF_LEN			(REG_SRAM_RFD_ADDR+36)
+-#define REG_SRAM_TXF_ADDR			(REG_SRAM_RFD_ADDR+40)
+-#define REG_SRAM_TXF_LEN			(REG_SRAM_RFD_ADDR+44)
+-#define REG_SRAM_TCPH_PATH_ADDR			(REG_SRAM_RFD_ADDR+48)
+-#define SRAM_TCPH_ADDR_MASK			0x0fff
+-#define SRAM_TCPH_ADDR_SHIFT			0
+-#define SRAM_PATH_ADDR_MASK			0x0fff
+-#define SRAM_PATH_ADDR_SHIFT			16
+-
+-/* Load Ptr Register */
+-#define REG_LOAD_PTR				(REG_SRAM_RFD_ADDR+52)
+-
+-/* Descriptor Control register */
+-#define REG_DESC_BASE_ADDR_HI			0x1540
+-#define REG_DESC_RFD_ADDR_LO			(REG_DESC_BASE_ADDR_HI+4)
+-#define REG_DESC_RRD_ADDR_LO			(REG_DESC_BASE_ADDR_HI+8)
+-#define REG_DESC_TPD_ADDR_LO			(REG_DESC_BASE_ADDR_HI+12)
+-#define REG_DESC_CMB_ADDR_LO			(REG_DESC_BASE_ADDR_HI+16)
+-#define REG_DESC_SMB_ADDR_LO			(REG_DESC_BASE_ADDR_HI+20)
+-#define REG_DESC_RFD_RRD_RING_SIZE		(REG_DESC_BASE_ADDR_HI+24)
+-#define DESC_RFD_RING_SIZE_MASK			0x7ff
+-#define DESC_RFD_RING_SIZE_SHIFT		0
+-#define DESC_RRD_RING_SIZE_MASK			0x7ff
+-#define DESC_RRD_RING_SIZE_SHIFT		16
+-#define REG_DESC_TPD_RING_SIZE			(REG_DESC_BASE_ADDR_HI+28)
+-#define DESC_TPD_RING_SIZE_MASK			0x3ff
+-#define DESC_TPD_RING_SIZE_SHIFT		0
+-
+-/* TXQ Control Register */
+-#define REG_TXQ_CTRL				0x1580
+-#define TXQ_CTRL_TPD_BURST_NUM_SHIFT		0
+-#define TXQ_CTRL_TPD_BURST_NUM_MASK		0x1f
+-#define TXQ_CTRL_EN				0x20
+-#define TXQ_CTRL_ENH_MODE			0x40
+-#define TXQ_CTRL_TPD_FETCH_TH_SHIFT		8
+-#define TXQ_CTRL_TPD_FETCH_TH_MASK		0x3f
+-#define TXQ_CTRL_TXF_BURST_NUM_SHIFT		16
+-#define TXQ_CTRL_TXF_BURST_NUM_MASK		0xffff
+-
+-/* Jumbo packet Threshold for task offload */
+-#define REG_TX_JUMBO_TASK_TH_TPD_IPG		0x1584
+-#define TX_JUMBO_TASK_TH_MASK			0x7ff
+-#define TX_JUMBO_TASK_TH_SHIFT			0
+-#define TX_TPD_MIN_IPG_MASK			0x1f
+-#define TX_TPD_MIN_IPG_SHIFT			16
+-
+-/* RXQ Control Register */
+-#define REG_RXQ_CTRL				0x15a0
+-#define RXQ_CTRL_RFD_BURST_NUM_SHIFT		0
+-#define RXQ_CTRL_RFD_BURST_NUM_MASK		0xff
+-#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT		8
+-#define RXQ_CTRL_RRD_BURST_THRESH_MASK		0xff
+-#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT		16
+-#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK		0x1f
+-#define RXQ_CTRL_CUT_THRU_EN			0x40000000
+-#define RXQ_CTRL_EN				0x80000000
+-
+-/* Rx jumbo packet threshold and rrd  retirement timer */
+-#define REG_RXQ_JMBOSZ_RRDTIM			(REG_RXQ_CTRL+ 4)
+-#define RXQ_JMBOSZ_TH_MASK			0x7ff
+-#define RXQ_JMBOSZ_TH_SHIFT			0
+-#define RXQ_JMBO_LKAH_MASK			0xf
+-#define RXQ_JMBO_LKAH_SHIFT			11
+-#define RXQ_RRD_TIMER_MASK			0xffff
+-#define RXQ_RRD_TIMER_SHIFT			16
+-
+-/* RFD flow control register */
+-#define REG_RXQ_RXF_PAUSE_THRESH		(REG_RXQ_CTRL+ 8)
+-#define RXQ_RXF_PAUSE_TH_HI_SHIFT		16
+-#define RXQ_RXF_PAUSE_TH_HI_MASK		0xfff
+-#define RXQ_RXF_PAUSE_TH_LO_SHIFT		0
+-#define RXQ_RXF_PAUSE_TH_LO_MASK		0xfff
+-
+-/* RRD flow control register */
+-#define REG_RXQ_RRD_PAUSE_THRESH		(REG_RXQ_CTRL+12)
+-#define RXQ_RRD_PAUSE_TH_HI_SHIFT		0
+-#define RXQ_RRD_PAUSE_TH_HI_MASK		0xfff
+-#define RXQ_RRD_PAUSE_TH_LO_SHIFT		16
+-#define RXQ_RRD_PAUSE_TH_LO_MASK		0xfff
+-
+-/* DMA Engine Control Register */
+-#define REG_DMA_CTRL				0x15c0
+-#define DMA_CTRL_DMAR_IN_ORDER			0x1
+-#define DMA_CTRL_DMAR_ENH_ORDER			0x2
+-#define DMA_CTRL_DMAR_OUT_ORDER			0x4
+-#define DMA_CTRL_RCB_VALUE			0x8
+-#define DMA_CTRL_DMAR_BURST_LEN_SHIFT		4
+-#define DMA_CTRL_DMAR_BURST_LEN_MASK		7
+-#define DMA_CTRL_DMAW_BURST_LEN_SHIFT		7
+-#define DMA_CTRL_DMAW_BURST_LEN_MASK		7
+-#define DMA_CTRL_DMAR_EN				0x400
+-#define DMA_CTRL_DMAW_EN				0x800
+-
+-/* CMB/SMB Control Register */
+-#define REG_CSMB_CTRL				0x15d0
+-#define CSMB_CTRL_CMB_NOW			1
+-#define CSMB_CTRL_SMB_NOW			2
+-#define CSMB_CTRL_CMB_EN			4
+-#define CSMB_CTRL_SMB_EN			8
+-
+-/* CMB DMA Write Threshold Register */
+-#define REG_CMB_WRITE_TH			(REG_CSMB_CTRL+ 4)
+-#define CMB_RRD_TH_SHIFT			0
+-#define CMB_RRD_TH_MASK				0x7ff
+-#define CMB_TPD_TH_SHIFT			16
+-#define CMB_TPD_TH_MASK				0x7ff
+-
+-/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
+-#define REG_CMB_WRITE_TIMER			(REG_CSMB_CTRL+ 8)
+-#define CMB_RX_TM_SHIFT				0
+-#define CMB_RX_TM_MASK				0xffff
+-#define CMB_TX_TM_SHIFT				16
+-#define CMB_TX_TM_MASK				0xffff
+-
+-/* Number of packet received since last CMB write */
+-#define REG_CMB_RX_PKT_CNT			(REG_CSMB_CTRL+12)
+-
+-/* Number of packet transmitted since last CMB write */
+-#define REG_CMB_TX_PKT_CNT			(REG_CSMB_CTRL+16)
+-
+-/* SMB auto DMA timer register */
+-#define REG_SMB_TIMER				(REG_CSMB_CTRL+20)
+-
+-/* Mailbox Register */
+-#define REG_MAILBOX				0x15f0
+-#define MB_RFD_PROD_INDX_SHIFT			0
+-#define MB_RFD_PROD_INDX_MASK			0x7ff
+-#define MB_RRD_CONS_INDX_SHIFT			11
+-#define MB_RRD_CONS_INDX_MASK			0x7ff
+-#define MB_TPD_PROD_INDX_SHIFT			22
+-#define MB_TPD_PROD_INDX_MASK			0x3ff
+-
+-/* Interrupt Status Register */
+-#define REG_ISR					0x1600
+-#define ISR_SMB					1
+-#define ISR_TIMER				2
+-#define ISR_MANUAL				4
+-#define ISR_RXF_OV				8
+-#define ISR_RFD_UNRUN				0x10
+-#define ISR_RRD_OV				0x20
+-#define ISR_TXF_UNRUN				0x40
+-#define ISR_LINK				0x80
+-#define ISR_HOST_RFD_UNRUN			0x100
+-#define ISR_HOST_RRD_OV				0x200
+-#define ISR_DMAR_TO_RST				0x400
+-#define ISR_DMAW_TO_RST				0x800
+-#define ISR_GPHY				0x1000
+-#define ISR_RX_PKT				0x10000
+-#define ISR_TX_PKT				0x20000
+-#define ISR_TX_DMA				0x40000
+-#define ISR_RX_DMA				0x80000
+-#define ISR_CMB_RX				0x100000
+-#define ISR_CMB_TX				0x200000
+-#define ISR_MAC_RX				0x400000
+-#define ISR_MAC_TX				0x800000
+-#define ISR_UR_DETECTED				0x1000000
+-#define ISR_FERR_DETECTED			0x2000000
+-#define ISR_NFERR_DETECTED			0x4000000
+-#define ISR_CERR_DETECTED			0x8000000
+-#define ISR_PHY_LINKDOWN			0x10000000
+-#define ISR_DIS_SMB				0x20000000
+-#define ISR_DIS_DMA				0x40000000
+-#define ISR_DIS_INT				0x80000000
+-
+-/* Interrupt Mask Register */
+-#define REG_IMR					0x1604
+-
+-/* Normal Interrupt mask  */
+-#define IMR_NORMAL_MASK	(\
+-	ISR_SMB		|\
+-	ISR_GPHY	|\
+-	ISR_PHY_LINKDOWN|\
+-	ISR_DMAR_TO_RST	|\
+-	ISR_DMAW_TO_RST	|\
+-	ISR_CMB_TX	|\
+-	ISR_CMB_RX	)
+-
+-/* Debug Interrupt Mask  (enable all interrupt) */
+-#define IMR_DEBUG_MASK	(\
+-	ISR_SMB		|\
+-	ISR_TIMER	|\
+-	ISR_MANUAL	|\
+-	ISR_RXF_OV	|\
+-	ISR_RFD_UNRUN	|\
+-	ISR_RRD_OV	|\
+-	ISR_TXF_UNRUN	|\
+-	ISR_LINK	|\
+-	ISR_CMB_TX	|\
+-	ISR_CMB_RX	|\
+-	ISR_RX_PKT	|\
+-	ISR_TX_PKT	|\
+-	ISR_MAC_RX	|\
+-	ISR_MAC_TX	)
+-
+-/* Interrupt Status Register */
+-#define REG_RFD_RRD_IDX				0x1800
+-#define REG_TPD_IDX				0x1804
+-
+-/*  MII definition */
+-/* PHY Common Register */
+-#define MII_AT001_CR					0x09
+-#define MII_AT001_SR					0x0A
+-#define MII_AT001_ESR					0x0F
+-#define MII_AT001_PSCR					0x10
+-#define MII_AT001_PSSR					0x11
+-
+-/* PHY Control Register */
+-#define MII_CR_SPEED_SELECT_MSB				0x0040	/* bits 6,13: 10=1000, 01=100, 00=10 */
+-#define MII_CR_COLL_TEST_ENABLE				0x0080	/* Collision test enable */
+-#define MII_CR_FULL_DUPLEX				0x0100	/* FDX =1, half duplex =0 */
+-#define MII_CR_RESTART_AUTO_NEG				0x0200	/* Restart auto negotiation */
+-#define MII_CR_ISOLATE					0x0400	/* Isolate PHY from MII */
+-#define MII_CR_POWER_DOWN				0x0800	/* Power down */
+-#define MII_CR_AUTO_NEG_EN				0x1000	/* Auto Neg Enable */
+-#define MII_CR_SPEED_SELECT_LSB				0x2000	/* bits 6,13: 10=1000, 01=100, 00=10 */
+-#define MII_CR_LOOPBACK					0x4000	/* 0 = normal, 1 = loopback */
+-#define MII_CR_RESET					0x8000	/* 0 = normal, 1 = PHY reset */
+-#define MII_CR_SPEED_MASK				0x2040
+-#define MII_CR_SPEED_1000				0x0040
+-#define MII_CR_SPEED_100				0x2000
+-#define MII_CR_SPEED_10					0x0000
+-
+-/* PHY Status Register */
+-#define MII_SR_EXTENDED_CAPS				0x0001	/* Extended register capabilities */
+-#define MII_SR_JABBER_DETECT				0x0002	/* Jabber Detected */
+-#define MII_SR_LINK_STATUS				0x0004	/* Link Status 1 = link */
+-#define MII_SR_AUTONEG_CAPS				0x0008	/* Auto Neg Capable */
+-#define MII_SR_REMOTE_FAULT				0x0010	/* Remote Fault Detect */
+-#define MII_SR_AUTONEG_COMPLETE				0x0020	/* Auto Neg Complete */
+-#define MII_SR_PREAMBLE_SUPPRESS			0x0040	/* Preamble may be suppressed */
+-#define MII_SR_EXTENDED_STATUS				0x0100	/* Ext. status info in Reg 0x0F */
+-#define MII_SR_100T2_HD_CAPS				0x0200	/* 100T2 Half Duplex Capable */
+-#define MII_SR_100T2_FD_CAPS				0x0400	/* 100T2 Full Duplex Capable */
+-#define MII_SR_10T_HD_CAPS				0x0800	/* 10T   Half Duplex Capable */
+-#define MII_SR_10T_FD_CAPS				0x1000	/* 10T   Full Duplex Capable */
+-#define MII_SR_100X_HD_CAPS				0x2000	/* 100X  Half Duplex Capable */
+-#define MII_SR_100X_FD_CAPS				0x4000	/* 100X  Full Duplex Capable */
+-#define MII_SR_100T4_CAPS				0x8000	/* 100T4 Capable */
+-
+-/* Link partner ability register. */
+-#define MII_LPA_SLCT					0x001f	/* Same as advertise selector  */
+-#define MII_LPA_10HALF					0x0020	/* Can do 10mbps half-duplex   */
+-#define MII_LPA_10FULL					0x0040	/* Can do 10mbps full-duplex   */
+-#define MII_LPA_100HALF					0x0080	/* Can do 100mbps half-duplex  */
+-#define MII_LPA_100FULL					0x0100	/* Can do 100mbps full-duplex  */
+-#define MII_LPA_100BASE4				0x0200	/* 100BASE-T4  */
+-#define MII_LPA_PAUSE					0x0400	/* PAUSE */
+-#define MII_LPA_ASYPAUSE				0x0800	/* Asymmetrical PAUSE */
+-#define MII_LPA_RFAULT					0x2000	/* Link partner faulted        */
+-#define MII_LPA_LPACK					0x4000	/* Link partner acked us       */
+-#define MII_LPA_NPAGE					0x8000	/* Next page bit               */
+-
+-/* Autoneg Advertisement Register */
+-#define MII_AR_SELECTOR_FIELD				0x0001	/* indicates IEEE 802.3 CSMA/CD */
+-#define MII_AR_10T_HD_CAPS				0x0020	/* 10T   Half Duplex Capable */
+-#define MII_AR_10T_FD_CAPS				0x0040	/* 10T   Full Duplex Capable */
+-#define MII_AR_100TX_HD_CAPS				0x0080	/* 100TX Half Duplex Capable */
+-#define MII_AR_100TX_FD_CAPS				0x0100	/* 100TX Full Duplex Capable */
+-#define MII_AR_100T4_CAPS				0x0200	/* 100T4 Capable */
+-#define MII_AR_PAUSE					0x0400	/* Pause operation desired */
+-#define MII_AR_ASM_DIR					0x0800	/* Asymmetric Pause Direction bit */
+-#define MII_AR_REMOTE_FAULT				0x2000	/* Remote Fault detected */
+-#define MII_AR_NEXT_PAGE				0x8000	/* Next Page ability supported */
+-#define MII_AR_SPEED_MASK				0x01E0
+-#define MII_AR_DEFAULT_CAP_MASK				0x0DE0
+-
+-/* 1000BASE-T Control Register */
+-#define MII_AT001_CR_1000T_HD_CAPS			0x0100	/* Advertise 1000T HD capability */
+-#define MII_AT001_CR_1000T_FD_CAPS			0x0200	/* Advertise 1000T FD capability  */
+-#define MII_AT001_CR_1000T_REPEATER_DTE			0x0400	/* 1=Repeater/switch device port, 0=DTE device */
+-#define MII_AT001_CR_1000T_MS_VALUE			0x0800	/* 1=Configure PHY as Master, 0=Configure PHY as Slave */
+-#define MII_AT001_CR_1000T_MS_ENABLE			0x1000	/* 1=Master/Slave manual config value, 0=Automatic Master/Slave config */
+-#define MII_AT001_CR_1000T_TEST_MODE_NORMAL		0x0000	/* Normal Operation */
+-#define MII_AT001_CR_1000T_TEST_MODE_1			0x2000	/* Transmit Waveform test */
+-#define MII_AT001_CR_1000T_TEST_MODE_2			0x4000	/* Master Transmit Jitter test */
+-#define MII_AT001_CR_1000T_TEST_MODE_3			0x6000	/* Slave Transmit Jitter test */
+-#define MII_AT001_CR_1000T_TEST_MODE_4			0x8000	/* Transmitter Distortion test */
+-#define MII_AT001_CR_1000T_SPEED_MASK			0x0300
+-#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK		0x0300
+-
+-/* 1000BASE-T Status Register */
+-#define MII_AT001_SR_1000T_LP_HD_CAPS			0x0400	/* LP is 1000T HD capable */
+-#define MII_AT001_SR_1000T_LP_FD_CAPS			0x0800	/* LP is 1000T FD capable */
+-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS		0x1000	/* Remote receiver OK */
+-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS		0x2000	/* Local receiver OK */
+-#define MII_AT001_SR_1000T_MS_CONFIG_RES		0x4000	/* 1=Local TX is Master, 0=Slave */
+-#define MII_AT001_SR_1000T_MS_CONFIG_FAULT		0x8000	/* Master/Slave config fault */
+-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT	12
+-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT	13
+-
+-/* Extended Status Register */
+-#define MII_AT001_ESR_1000T_HD_CAPS			0x1000	/* 1000T HD capable */
+-#define MII_AT001_ESR_1000T_FD_CAPS			0x2000	/* 1000T FD capable */
+-#define MII_AT001_ESR_1000X_HD_CAPS			0x4000	/* 1000X HD capable */
+-#define MII_AT001_ESR_1000X_FD_CAPS			0x8000	/* 1000X FD capable */
+-
+-/* AT001 PHY Specific Control Register */
+-#define MII_AT001_PSCR_JABBER_DISABLE			0x0001	/* 1=Jabber Function disabled */
+-#define MII_AT001_PSCR_POLARITY_REVERSAL		0x0002	/* 1=Polarity Reversal enabled */
+-#define MII_AT001_PSCR_SQE_TEST				0x0004	/* 1=SQE Test enabled */
+-#define MII_AT001_PSCR_MAC_POWERDOWN			0x0008
+-#define MII_AT001_PSCR_CLK125_DISABLE			0x0010	/* 1=CLK125 low, 0=CLK125 toggling */
+-#define MII_AT001_PSCR_MDI_MANUAL_MODE			0x0000	/* MDI Crossover Mode bits 6:5, Manual MDI configuration */
+-#define MII_AT001_PSCR_MDIX_MANUAL_MODE			0x0020	/* Manual MDIX configuration */
+-#define MII_AT001_PSCR_AUTO_X_1000T			0x0040	/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
+-#define MII_AT001_PSCR_AUTO_X_MODE			0x0060	/* Auto crossover enabled all speeds. */
+-#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE		0x0080	/* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T RX Threshold), 0=Normal 10BASE-T RX Threshold */
+-#define MII_AT001_PSCR_MII_5BIT_ENABLE			0x0100	/* 1=5-Bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
+-#define MII_AT001_PSCR_SCRAMBLER_DISABLE		0x0200	/* 1=Scrambler disable */
+-#define MII_AT001_PSCR_FORCE_LINK_GOOD			0x0400	/* 1=Force link good */
+-#define MII_AT001_PSCR_ASSERT_CRS_ON_TX			0x0800	/* 1=Assert CRS on Transmit */
+-#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT		1
+-#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT		5
+-#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT	7
+-
+-/* AT001 PHY Specific Status Register */
+-#define MII_AT001_PSSR_SPD_DPLX_RESOLVED		0x0800	/* 1=Speed & Duplex resolved */
+-#define MII_AT001_PSSR_DPLX				0x2000	/* 1=Duplex 0=Half Duplex */
+-#define MII_AT001_PSSR_SPEED				0xC000	/* Speed, bits 14:15 */
+-#define MII_AT001_PSSR_10MBS				0x0000	/* 00=10Mbs */
+-#define MII_AT001_PSSR_100MBS				0x4000	/* 01=100Mbs */
+-#define MII_AT001_PSSR_1000MBS				0x8000	/* 10=1000Mbs */
+-
+-/* PCI Command Register Bit Definitions */
+-#define PCI_REG_COMMAND					0x04	/* PCI Command Register */
+-#define CMD_IO_SPACE					0x0001
+-#define CMD_MEMORY_SPACE				0x0002
+-#define CMD_BUS_MASTER					0x0004
+-
+-/* Wake Up Filter Control */
+-#define ATL1_WUFC_LNKC	0x00000001	/* Link Status Change Wakeup Enable */
+-#define ATL1_WUFC_MAG	0x00000002	/* Magic Packet Wakeup Enable */
+-#define ATL1_WUFC_EX	0x00000004	/* Directed Exact Wakeup Enable */
+-#define ATL1_WUFC_MC	0x00000008	/* Multicast Wakeup Enable */
+-#define ATL1_WUFC_BC	0x00000010	/* Broadcast Wakeup Enable */
+-
+-/* Error Codes */
+-#define ATL1_SUCCESS			0
+-#define ATL1_ERR_EEPROM			1
+-#define ATL1_ERR_PHY			2
+-#define ATL1_ERR_CONFIG			3
+-#define ATL1_ERR_PARAM			4
+-#define ATL1_ERR_MAC_TYPE		5
+-#define ATL1_ERR_PHY_TYPE		6
+-#define ATL1_ERR_PHY_SPEED		7
+-#define ATL1_ERR_PHY_RES		8
+-
+-#define SPEED_0		0xffff
+-#define SPEED_10	10
+-#define SPEED_100	100
+-#define SPEED_1000	1000
+-#define HALF_DUPLEX	1
+-#define FULL_DUPLEX	2
+-
+-#define MEDIA_TYPE_AUTO_SENSOR	0
+-#define MEDIA_TYPE_1000M_FULL	1
+-#define MEDIA_TYPE_100M_FULL	2
+-#define MEDIA_TYPE_100M_HALF	3
+-#define MEDIA_TYPE_10M_FULL	4
+-#define MEDIA_TYPE_10M_HALF	5
+-
+-#define ADVERTISE_10_HALF		0x0001
+-#define ADVERTISE_10_FULL		0x0002
+-#define ADVERTISE_100_HALF		0x0004
+-#define ADVERTISE_100_FULL		0x0008
+-#define ADVERTISE_1000_HALF		0x0010
+-#define ADVERTISE_1000_FULL		0x0020
+-#define AUTONEG_ADVERTISE_SPEED_DEFAULT	0x002F	/* Everything but 1000-Half */
+-#define AUTONEG_ADVERTISE_10_100_ALL	0x000F	/* All 10/100 speeds */
+-#define AUTONEG_ADVERTISE_10_ALL	0x0003	/* 10Mbps Full & Half speeds */
+-
+-#define MAX_JUMBO_FRAME_SIZE		0x2800
+-
+-#define PHY_AUTO_NEG_TIME	45	/* 4.5 Seconds */
+-#define PHY_FORCE_TIME		20	/* 2.0 Seconds */
+-
+-/* For checksumming , the sum of all words in the EEPROM should equal 0xBABA */
+-#define EEPROM_SUM		0xBABA
+-
+-#define ATL1_EEDUMP_LEN		48
+-
+-/* Statistics counters collected by the MAC */
+-struct stats_msg_block {
+-	/* rx */
+-	u32 rx_ok;		/* The number of good packet received. */
+-	u32 rx_bcast;		/* The number of good broadcast packet received. */
+-	u32 rx_mcast;		/* The number of good multicast packet received. */
+-	u32 rx_pause;		/* The number of Pause packet received. */
+-	u32 rx_ctrl;		/* The number of Control packet received other than Pause frame. */
+-	u32 rx_fcs_err;		/* The number of packets with bad FCS. */
+-	u32 rx_len_err;		/* The number of packets with mismatch of length field and actual size. */
+-	u32 rx_byte_cnt;	/* The number of bytes of good packet received. FCS is NOT included. */
+-	u32 rx_runt;		/* The number of packets received that are less than 64 byte long and with good FCS. */
+-	u32 rx_frag;		/* The number of packets received that are less than 64 byte long and with bad FCS. */
+-	u32 rx_sz_64;		/* The number of good and bad packets received that are 64 byte long. */
+-	u32 rx_sz_65_127;	/* The number of good and bad packets received that are between 65 and 127-byte long. */
+-	u32 rx_sz_128_255;	/* The number of good and bad packets received that are between 128 and 255-byte long. */
+-	u32 rx_sz_256_511;	/* The number of good and bad packets received that are between 256 and 511-byte long. */
+-	u32 rx_sz_512_1023;	/* The number of good and bad packets received that are between 512 and 1023-byte long. */
+-	u32 rx_sz_1024_1518;	/* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+-	u32 rx_sz_1519_max;	/* The number of good and bad packets received that are between 1519-byte and MTU. */
+-	u32 rx_sz_ov;		/* The number of good and bad packets received that are more than MTU size Å¡C truncated by Selene. */
+-	u32 rx_rxf_ov;		/* The number of frame dropped due to occurrence of RX FIFO overflow. */
+-	u32 rx_rrd_ov;		/* The number of frame dropped due to occurrence of RRD overflow. */
+-	u32 rx_align_err;	/* Alignment Error */
+-	u32 rx_bcast_byte_cnt;	/* The byte count of broadcast packet received, excluding FCS. */
+-	u32 rx_mcast_byte_cnt;	/* The byte count of multicast packet received, excluding FCS. */
+-	u32 rx_err_addr;	/* The number of packets dropped due to address filtering. */
+-
+-	/* tx */
+-	u32 tx_ok;		/* The number of good packet transmitted. */
+-	u32 tx_bcast;		/* The number of good broadcast packet transmitted. */
+-	u32 tx_mcast;		/* The number of good multicast packet transmitted. */
+-	u32 tx_pause;		/* The number of Pause packet transmitted. */
+-	u32 tx_exc_defer;	/* The number of packets transmitted with excessive deferral. */
+-	u32 tx_ctrl;		/* The number of packets transmitted is a control frame, excluding Pause frame. */
+-	u32 tx_defer;		/* The number of packets transmitted that is deferred. */
+-	u32 tx_byte_cnt;	/* The number of bytes of data transmitted. FCS is NOT included. */
+-	u32 tx_sz_64;		/* The number of good and bad packets transmitted that are 64 byte long. */
+-	u32 tx_sz_65_127;	/* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+-	u32 tx_sz_128_255;	/* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+-	u32 tx_sz_256_511;	/* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+-	u32 tx_sz_512_1023;	/* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+-	u32 tx_sz_1024_1518;	/* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+-	u32 tx_sz_1519_max;	/* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+-	u32 tx_1_col;		/* The number of packets subsequently transmitted successfully with a single prior collision. */
+-	u32 tx_2_col;		/* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+-	u32 tx_late_col;	/* The number of packets transmitted with late collisions. */
+-	u32 tx_abort_col;	/* The number of transmit packets aborted due to excessive collisions. */
+-	u32 tx_underrun;	/* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+-	u32 tx_rd_eop;		/* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+-	u32 tx_len_err;		/* The number of transmit packets with length field does NOT match the actual frame size. */
+-	u32 tx_trunc;		/* The number of transmit packets truncated due to size exceeding MTU. */
+-	u32 tx_bcast_byte;	/* The byte count of broadcast packet transmitted, excluding FCS. */
+-	u32 tx_mcast_byte;	/* The byte count of multicast packet transmitted, excluding FCS. */
+-	u32 smb_updated;	/* 1: SMB Updated. This is used by software as the indication of the statistics update.
+-				 * Software should clear this bit as soon as retrieving the statistics information. */
+-};
+-
+-/* Coalescing Message Block */
+-struct coals_msg_block {
+-	u32 int_stats;		/* interrupt status */
+-	u16 rrd_prod_idx;	/* TRD Producer Index. */
+-	u16 rfd_cons_idx;	/* RFD Consumer Index. */
+-	u16 update;		/* Selene sets this bit every time it DMA the CMB to host memory.
+-				 * Software supposes to clear this bit when CMB information is processed. */
+-	u16 tpd_cons_idx;	/* TPD Consumer Index. */
+-};
+-
+-/* RRD descriptor */
+-struct rx_return_desc {
+-	u8 num_buf;		/* Number of RFD buffers used by the received packet */
+-	u8 resved;
+-	u16 buf_indx;		/* RFD Index of the first buffer */
+-	union {
+-		u32 valid;
+-		struct {
+-			u16 rx_chksum;
+-			u16 pkt_size;
+-		} xsum_sz;
+-	} xsz;
+-
+-	u16 pkt_flg;		/* Packet flags */
+-	u16 err_flg;		/* Error flags */
+-	u16 resved2;
+-	u16 vlan_tag;		/* VLAN TAG */
+-};
+-
+-#define PACKET_FLAG_ETH_TYPE	0x0080
+-#define PACKET_FLAG_VLAN_INS	0x0100
+-#define PACKET_FLAG_ERR		0x0200
+-#define PACKET_FLAG_IPV4	0x0400
+-#define PACKET_FLAG_UDP		0x0800
+-#define PACKET_FLAG_TCP		0x1000
+-#define PACKET_FLAG_BCAST	0x2000
+-#define PACKET_FLAG_MCAST	0x4000
+-#define PACKET_FLAG_PAUSE	0x8000
+-
+-#define ERR_FLAG_CRC		0x0001
+-#define ERR_FLAG_CODE		0x0002
+-#define ERR_FLAG_DRIBBLE	0x0004
+-#define ERR_FLAG_RUNT		0x0008
+-#define ERR_FLAG_OV		0x0010
+-#define ERR_FLAG_TRUNC		0x0020
+-#define ERR_FLAG_IP_CHKSUM	0x0040
+-#define ERR_FLAG_L4_CHKSUM	0x0080
+-#define ERR_FLAG_LEN		0x0100
+-#define ERR_FLAG_DES_ADDR	0x0200
+-
+-/* RFD descriptor */
+-struct rx_free_desc {
+-	__le64 buffer_addr;	/* Address of the descriptor's data buffer */
+-	__le16 buf_len;		/* Size of the receive buffer in host memory, in byte */
+-	u16 coalese;		/* Update consumer index to host after the reception of this frame */
+-	/* __attribute__ ((packed)) is required */
+-} __attribute__ ((packed));
+-
+-/* tsopu defines */
+-#define TSO_PARAM_BUFLEN_MASK           0x3FFF
+-#define TSO_PARAM_BUFLEN_SHIFT          0
+-#define TSO_PARAM_DMAINT_MASK           0x0001
+-#define TSO_PARAM_DMAINT_SHIFT          14
+-#define TSO_PARAM_PKTNT_MASK            0x0001
+-#define TSO_PARAM_PKTINT_SHIFT          15
+-#define TSO_PARAM_VLANTAG_MASK          0xFFFF
+-#define TSO_PARAM_VLAN_SHIFT            16
+-
+-/* tsopl defines */
+-#define TSO_PARAM_EOP_MASK              0x0001
+-#define TSO_PARAM_EOP_SHIFT             0
+-#define TSO_PARAM_COALESCE_MASK         0x0001
+-#define TSO_PARAM_COALESCE_SHIFT        1
+-#define TSO_PARAM_INSVLAG_MASK          0x0001
+-#define TSO_PARAM_INSVLAG_SHIFT         2
+-#define TSO_PARAM_CUSTOMCKSUM_MASK      0x0001
+-#define TSO_PARAM_CUSTOMCKSUM_SHIFT     3
+-#define TSO_PARAM_SEGMENT_MASK          0x0001
+-#define TSO_PARAM_SEGMENT_SHIFT         4
+-#define TSO_PARAM_IPCKSUM_MASK          0x0001
+-#define TSO_PARAM_IPCKSUM_SHIFT         5
+-#define TSO_PARAM_TCPCKSUM_MASK         0x0001
+-#define TSO_PARAM_TCPCKSUM_SHIFT        6
+-#define TSO_PARAM_UDPCKSUM_MASK         0x0001
+-#define TSO_PARAM_UDPCKSUM_SHIFT        7
+-#define TSO_PARAM_VLANTAGGED_MASK       0x0001
+-#define TSO_PARAM_VLANTAGGED_SHIFT      8
+-#define TSO_PARAM_ETHTYPE_MASK          0x0001
+-#define TSO_PARAM_ETHTYPE_SHIFT         9
+-#define TSO_PARAM_IPHL_MASK             0x000F
+-#define TSO_PARAM_IPHL_SHIFT            10
+-#define TSO_PARAM_TCPHDRLEN_MASK        0x000F
+-#define TSO_PARAM_TCPHDRLEN_SHIFT       14
+-#define TSO_PARAM_HDRFLAG_MASK          0x0001
+-#define TSO_PARAM_HDRFLAG_SHIFT         18
+-#define TSO_PARAM_MSS_MASK              0x1FFF
+-#define TSO_PARAM_MSS_SHIFT             19
+-
+-/* csumpu defines */
+-#define CSUM_PARAM_BUFLEN_MASK          0x3FFF
+-#define CSUM_PARAM_BUFLEN_SHIFT         0
+-#define CSUM_PARAM_DMAINT_MASK          0x0001
+-#define CSUM_PARAM_DMAINT_SHIFT         14
+-#define CSUM_PARAM_PKTINT_MASK          0x0001
+-#define CSUM_PARAM_PKTINT_SHIFT         15
+-#define CSUM_PARAM_VALANTAG_MASK        0xFFFF
+-#define CSUM_PARAM_VALAN_SHIFT          16
+-
+-/* csumpl defines*/
+-#define CSUM_PARAM_EOP_MASK             0x0001
+-#define CSUM_PARAM_EOP_SHIFT            0
+-#define CSUM_PARAM_COALESCE_MASK        0x0001
+-#define CSUM_PARAM_COALESCE_SHIFT       1
+-#define CSUM_PARAM_INSVLAG_MASK         0x0001
+-#define CSUM_PARAM_INSVLAG_SHIFT        2
+-#define CSUM_PARAM_CUSTOMCKSUM_MASK     0x0001
+-#define CSUM_PARAM_CUSTOMCKSUM_SHIFT    3
+-#define CSUM_PARAM_SEGMENT_MASK         0x0001
+-#define CSUM_PARAM_SEGMENT_SHIFT        4
+-#define CSUM_PARAM_IPCKSUM_MASK         0x0001
+-#define CSUM_PARAM_IPCKSUM_SHIFT        5
+-#define CSUM_PARAM_TCPCKSUM_MASK        0x0001
+-#define CSUM_PARAM_TCPCKSUM_SHIFT       6
+-#define CSUM_PARAM_UDPCKSUM_MASK        0x0001
+-#define CSUM_PARAM_UDPCKSUM_SHIFT       7
+-#define CSUM_PARAM_VLANTAGGED_MASK      0x0001
+-#define CSUM_PARAM_VLANTAGGED_SHIFT     8
+-#define CSUM_PARAM_ETHTYPE_MASK         0x0001
+-#define CSUM_PARAM_ETHTYPE_SHIFT        9
+-#define CSUM_PARAM_IPHL_MASK            0x000F
+-#define CSUM_PARAM_IPHL_SHIFT           10
+-#define CSUM_PARAM_PLOADOFFSET_MASK     0x00FF
+-#define CSUM_PARAM_PLOADOFFSET_SHIFT    16
+-#define CSUM_PARAM_XSUMOFFSET_MASK      0x00FF
+-#define CSUM_PARAM_XSUMOFFSET_SHIFT     24
+-
+-/* TPD descriptor */
+-struct tso_param {
+-        /* The order of these declarations is important -- don't change it */
+-        u32 tsopu;      /* tso_param upper word */
+-        u32 tsopl;      /* tso_param lower word */
+-};
+-
+-struct csum_param {
+-        /* The order of these declarations is important -- don't change it */
+-        u32 csumpu;     /* csum_param upper word */
+-        u32 csumpl;     /* csum_param lower word */
+-};
+-
+-union tpd_descr {
+-	u64 data;
+-	struct csum_param csum;
+-	struct tso_param tso;
+-};
+-
+-struct tx_packet_desc {
+-	__le64 buffer_addr;
+-	union tpd_descr desc;
+-};
+-
+-/* DMA Order Settings */
+-enum atl1_dma_order {
+-	atl1_dma_ord_in = 1,
+-	atl1_dma_ord_enh = 2,
+-	atl1_dma_ord_out = 4
+-};
+-
+-enum atl1_dma_rcb {
+-	atl1_rcb_64 = 0,
+-	atl1_rcb_128 = 1
+-};
+-
+-enum atl1_dma_req_block {
+-	atl1_dma_req_128 = 0,
+-	atl1_dma_req_256 = 1,
+-	atl1_dma_req_512 = 2,
+-	atl1_dma_req_1024 = 3,
+-	atl1_dma_req_2048 = 4,
+-	atl1_dma_req_4096 = 5
+-};
+-
+-struct atl1_spi_flash_dev {
+-	const char *manu_name;	/* manufacturer id */
+-	/* op-code */
+-	u8 cmd_wrsr;
+-	u8 cmd_read;
+-	u8 cmd_program;
+-	u8 cmd_wren;
+-	u8 cmd_wrdi;
+-	u8 cmd_rdsr;
+-	u8 cmd_rdid;
+-	u8 cmd_sector_erase;
+-	u8 cmd_chip_erase;
+-};
+-
+-#endif	/* _ATL1_HW_H_ */
+diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
+deleted file mode 100644
+index 129b8b3..0000000
+--- a/drivers/net/atl1/atl1_main.c
++++ /dev/null
+@@ -1,2450 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * Derived from Intel e1000 driver
+- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc., 59
+- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- *
+- * Contact Information:
+- * Xiong Huang <xiong_huang at attansic.com>
+- * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei,
+- * Xinzhu  302, TAIWAN, REPUBLIC OF CHINA
+- *
+- * Chris Snook <csnook at redhat.com>
+- * Jay Cliburn <jcliburn at gmail.com>
+- *
+- * This version is adapted from the Attansic reference driver for
+- * inclusion in the Linux kernel.  It is currently under heavy development.
+- * A very incomplete list of things that need to be dealt with:
+- *
+- * TODO:
+- * Fix TSO; tx performance is horrible with TSO enabled.
+- * Wake on LAN.
+- * Add more ethtool functions.
+- * Fix abstruse irq enable/disable condition described here:
+- *	http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
+- *
+- * NEEDS TESTING:
+- * VLAN
+- * multicast
+- * promiscuous mode
+- * interrupt coalescing
+- * SMP torture testing
+- */
+-
+-#include <linux/types.h>
+-#include <linux/netdevice.h>
+-#include <linux/pci.h>
+-#include <linux/spinlock.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/skbuff.h>
+-#include <linux/etherdevice.h>
+-#include <linux/if_vlan.h>
+-#include <linux/if_ether.h>
+-#include <linux/irqreturn.h>
+-#include <linux/workqueue.h>
+-#include <linux/timer.h>
+-#include <linux/jiffies.h>
+-#include <linux/hardirq.h>
+-#include <linux/interrupt.h>
+-#include <linux/irqflags.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/net.h>
+-#include <linux/pm.h>
+-#include <linux/in.h>
+-#include <linux/ip.h>
+-#include <linux/tcp.h>
+-#include <linux/compiler.h>
+-#include <linux/delay.h>
+-#include <linux/mii.h>
+-#include <net/checksum.h>
+-
+-#include <asm/atomic.h>
+-#include <asm/byteorder.h>
+-
+-#include "atl1.h"
+-
+-#define DRIVER_VERSION "2.0.7"
+-
+-char atl1_driver_name[] = "atl1";
+-static const char atl1_driver_string[] = "Attansic L1 Ethernet Network Driver";
+-static const char atl1_copyright[] = "Copyright(c) 2005-2006 Attansic Corporation.";
+-char atl1_driver_version[] = DRIVER_VERSION;
+-
+-MODULE_AUTHOR
+-    ("Attansic Corporation <xiong_huang at attansic.com>, Chris Snook <csnook at redhat.com>, Jay Cliburn <jcliburn at gmail.com>");
+-MODULE_DESCRIPTION("Attansic 1000M Ethernet Network Driver");
+-MODULE_LICENSE("GPL");
+-MODULE_VERSION(DRIVER_VERSION);
+-
+-/*
+- * atl1_pci_tbl - PCI Device ID Table
+- */
+-static const struct pci_device_id atl1_pci_tbl[] = {
+-	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
+-	/* required last entry */
+-	{0,}
+-};
+-
+-MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
+-
+-/*
+- * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
+- * @adapter: board private structure to initialize
+- *
+- * atl1_sw_init initializes the Adapter private data structure.
+- * Fields are initialized based on PCI device information and
+- * OS network device settings (MTU size).
+- */
+-static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
+-{
+-	struct atl1_hw *hw = &adapter->hw;
+-	struct net_device *netdev = adapter->netdev;
+-
+-	hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+-	hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+-
+-	adapter->wol = 0;
+-	adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
+-	adapter->ict = 50000;	/* 100ms */
+-	adapter->link_speed = SPEED_0;	/* hardware init */
+-	adapter->link_duplex = FULL_DUPLEX;
+-
+-	hw->phy_configured = false;
+-	hw->preamble_len = 7;
+-	hw->ipgt = 0x60;
+-	hw->min_ifg = 0x50;
+-	hw->ipgr1 = 0x40;
+-	hw->ipgr2 = 0x60;
+-	hw->max_retry = 0xf;
+-	hw->lcol = 0x37;
+-	hw->jam_ipg = 7;
+-	hw->rfd_burst = 8;
+-	hw->rrd_burst = 8;
+-	hw->rfd_fetch_gap = 1;
+-	hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
+-	hw->rx_jumbo_lkah = 1;
+-	hw->rrd_ret_timer = 16;
+-	hw->tpd_burst = 4;
+-	hw->tpd_fetch_th = 16;
+-	hw->txf_burst = 0x100;
+-	hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
+-	hw->tpd_fetch_gap = 1;
+-	hw->rcb_value = atl1_rcb_64;
+-	hw->dma_ord = atl1_dma_ord_enh;
+-	hw->dmar_block = atl1_dma_req_256;
+-	hw->dmaw_block = atl1_dma_req_256;
+-	hw->cmb_rrd = 4;
+-	hw->cmb_tpd = 4;
+-	hw->cmb_rx_timer = 1;	/* about 2us */
+-	hw->cmb_tx_timer = 1;	/* about 2us */
+-	hw->smb_timer = 100000;	/* about 200ms */
+-
+-	spin_lock_init(&adapter->lock);
+-	spin_lock_init(&adapter->mb_lock);
+-
+-	return 0;
+-}
+-
+-static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	u16 result;
+-
+-	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
+-
+-	return result;
+-}
+-
+-static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
+-	int val)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-
+-	atl1_write_phy_reg(&adapter->hw, reg_num, val);
+-}
+-
+-/*
+- * atl1_mii_ioctl -
+- * @netdev:
+- * @ifreq:
+- * @cmd:
+- */
+-static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	unsigned long flags;
+-	int retval;
+-
+-	if (!netif_running(netdev))
+-		return -EINVAL;
+-
+-	spin_lock_irqsave(&adapter->lock, flags);
+-	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+-	spin_unlock_irqrestore(&adapter->lock, flags);
+-
+-	return retval;
+-}
+-
+-/*
+- * atl1_ioctl -
+- * @netdev:
+- * @ifreq:
+- * @cmd:
+- */
+-static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+-{
+-	switch (cmd) {
+-	case SIOCGMIIPHY:
+-	case SIOCGMIIREG:
+-	case SIOCSMIIREG:
+-		return atl1_mii_ioctl(netdev, ifr, cmd);
+-	default:
+-		return -EOPNOTSUPP;
+-	}
+-}
+-
+-/*
+- * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
+- * @adapter: board private structure
+- *
+- * Return 0 on success, negative on failure
+- */
+-s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
+-{
+-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+-	struct atl1_ring_header *ring_header = &adapter->ring_header;
+-	struct pci_dev *pdev = adapter->pdev;
+-	int size;
+-	u8 offset = 0;
+-
+-	size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
+-	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
+-	if (unlikely(!tpd_ring->buffer_info)) {
+-		dev_err(&pdev->dev, "kzalloc failed , size = D%d\n", size);
+-		goto err_nomem;
+-	}
+-	rfd_ring->buffer_info =
+-		(struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
+-
+-	/* real ring DMA buffer
+-	 * each ring/block may need up to 8 bytes for alignment, hence the
+-	 * additional 40 bytes tacked onto the end.
+-	 */
+-	ring_header->size = size =
+-		sizeof(struct tx_packet_desc) * tpd_ring->count
+-		+ sizeof(struct rx_free_desc) * rfd_ring->count
+-		+ sizeof(struct rx_return_desc) * rrd_ring->count
+-		+ sizeof(struct coals_msg_block)
+-		+ sizeof(struct stats_msg_block)
+-		+ 40;
+-
+-	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
+-		&ring_header->dma);
+-	if (unlikely(!ring_header->desc)) {
+-		dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
+-		goto err_nomem;
+-	}
+-
+-	memset(ring_header->desc, 0, ring_header->size);
+-
+-	/* init TPD ring */
+-	tpd_ring->dma = ring_header->dma;
+-	offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
+-	tpd_ring->dma += offset;
+-	tpd_ring->desc = (u8 *) ring_header->desc + offset;
+-	tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
+-
+-	/* init RFD ring */
+-	rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
+-	offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
+-	rfd_ring->dma += offset;
+-	rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
+-	rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
+-
+-
+-	/* init RRD ring */
+-	rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
+-	offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
+-	rrd_ring->dma += offset;
+-	rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
+-	rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
+-
+-
+-	/* init CMB */
+-	adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
+-	offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
+-	adapter->cmb.dma += offset;
+-	adapter->cmb.cmb = (struct coals_msg_block *)
+-		((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
+-
+-	/* init SMB */
+-	adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
+-	offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
+-	adapter->smb.dma += offset;
+-	adapter->smb.smb = (struct stats_msg_block *)
+-		((u8 *) adapter->cmb.cmb +
+-		(sizeof(struct coals_msg_block) + offset));
+-
+-	return ATL1_SUCCESS;
+-
+-err_nomem:
+-	kfree(tpd_ring->buffer_info);
+-	return -ENOMEM;
+-}
+-
+-static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
+-{
+-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+-
+-	atomic_set(&tpd_ring->next_to_use, 0);
+-	atomic_set(&tpd_ring->next_to_clean, 0);
+-
+-	rfd_ring->next_to_clean = 0;
+-	atomic_set(&rfd_ring->next_to_use, 0);
+-
+-	rrd_ring->next_to_use = 0;
+-	atomic_set(&rrd_ring->next_to_clean, 0);
+-}
+-
+-/*
+- * atl1_clean_rx_ring - Free RFD Buffers
+- * @adapter: board private structure
+- */
+-static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+-{
+-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+-	struct atl1_buffer *buffer_info;
+-	struct pci_dev *pdev = adapter->pdev;
+-	unsigned long size;
+-	unsigned int i;
+-
+-	/* Free all the Rx ring sk_buffs */
+-	for (i = 0; i < rfd_ring->count; i++) {
+-		buffer_info = &rfd_ring->buffer_info[i];
+-		if (buffer_info->dma) {
+-			pci_unmap_page(pdev, buffer_info->dma,
+-				buffer_info->length, PCI_DMA_FROMDEVICE);
+-			buffer_info->dma = 0;
+-		}
+-		if (buffer_info->skb) {
+-			dev_kfree_skb(buffer_info->skb);
+-			buffer_info->skb = NULL;
+-		}
+-	}
+-
+-	size = sizeof(struct atl1_buffer) * rfd_ring->count;
+-	memset(rfd_ring->buffer_info, 0, size);
+-
+-	/* Zero out the descriptor ring */
+-	memset(rfd_ring->desc, 0, rfd_ring->size);
+-
+-	rfd_ring->next_to_clean = 0;
+-	atomic_set(&rfd_ring->next_to_use, 0);
+-
+-	rrd_ring->next_to_use = 0;
+-	atomic_set(&rrd_ring->next_to_clean, 0);
+-}
+-
+-/*
+- * atl1_clean_tx_ring - Free Tx Buffers
+- * @adapter: board private structure
+- */
+-static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+-{
+-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+-	struct atl1_buffer *buffer_info;
+-	struct pci_dev *pdev = adapter->pdev;
+-	unsigned long size;
+-	unsigned int i;
+-
+-	/* Free all the Tx ring sk_buffs */
+-	for (i = 0; i < tpd_ring->count; i++) {
+-		buffer_info = &tpd_ring->buffer_info[i];
+-		if (buffer_info->dma) {
+-			pci_unmap_page(pdev, buffer_info->dma,
+-				buffer_info->length, PCI_DMA_TODEVICE);
+-			buffer_info->dma = 0;
+-		}
+-	}
+-
+-	for (i = 0; i < tpd_ring->count; i++) {
+-		buffer_info = &tpd_ring->buffer_info[i];
+-		if (buffer_info->skb) {
+-			dev_kfree_skb_any(buffer_info->skb);
+-			buffer_info->skb = NULL;
+-		}
+-	}
+-
+-	size = sizeof(struct atl1_buffer) * tpd_ring->count;
+-	memset(tpd_ring->buffer_info, 0, size);
+-
+-	/* Zero out the descriptor ring */
+-	memset(tpd_ring->desc, 0, tpd_ring->size);
+-
+-	atomic_set(&tpd_ring->next_to_use, 0);
+-	atomic_set(&tpd_ring->next_to_clean, 0);
+-}
+-
+-/*
+- * atl1_free_ring_resources - Free Tx / RX descriptor Resources
+- * @adapter: board private structure
+- *
+- * Free all transmit software resources
+- */
+-void atl1_free_ring_resources(struct atl1_adapter *adapter)
+-{
+-	struct pci_dev *pdev = adapter->pdev;
+-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+-	struct atl1_ring_header *ring_header = &adapter->ring_header;
+-
+-	atl1_clean_tx_ring(adapter);
+-	atl1_clean_rx_ring(adapter);
+-
+-	kfree(tpd_ring->buffer_info);
+-	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
+-		ring_header->dma);
+-
+-	tpd_ring->buffer_info = NULL;
+-	tpd_ring->desc = NULL;
+-	tpd_ring->dma = 0;
+-
+-	rfd_ring->buffer_info = NULL;
+-	rfd_ring->desc = NULL;
+-	rfd_ring->dma = 0;
+-
+-	rrd_ring->desc = NULL;
+-	rrd_ring->dma = 0;
+-}
+-
+-static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
+-{
+-	u32 value;
+-	struct atl1_hw *hw = &adapter->hw;
+-	struct net_device *netdev = adapter->netdev;
+-	/* Config MAC CTRL Register */
+-	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+-	/* duplex */
+-	if (FULL_DUPLEX == adapter->link_duplex)
+-		value |= MAC_CTRL_DUPLX;
+-	/* speed */
+-	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
+-			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+-		  MAC_CTRL_SPEED_SHIFT);
+-	/* flow control */
+-	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+-	/* PAD & CRC */
+-	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+-	/* preamble length */
+-	value |= (((u32) adapter->hw.preamble_len
+-		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+-	/* vlan */
+-	if (adapter->vlgrp)
+-		value |= MAC_CTRL_RMV_VLAN;
+-	/* rx checksum
+-	   if (adapter->rx_csum)
+-	   value |= MAC_CTRL_RX_CHKSUM_EN;
+-	 */
+-	/* filter mode */
+-	value |= MAC_CTRL_BC_EN;
+-	if (netdev->flags & IFF_PROMISC)
+-		value |= MAC_CTRL_PROMIS_EN;
+-	else if (netdev->flags & IFF_ALLMULTI)
+-		value |= MAC_CTRL_MC_ALL_EN;
+-	/* value |= MAC_CTRL_LOOPBACK; */
+-	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
+-}
+-
+-/*
+- * atl1_set_mac - Change the Ethernet Address of the NIC
+- * @netdev: network interface device structure
+- * @p: pointer to an address structure
+- *
+- * Returns 0 on success, negative on failure
+- */
+-static int atl1_set_mac(struct net_device *netdev, void *p)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct sockaddr *addr = p;
+-
+-	if (netif_running(netdev))
+-		return -EBUSY;
+-
+-	if (!is_valid_ether_addr(addr->sa_data))
+-		return -EADDRNOTAVAIL;
+-
+-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+-	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+-
+-	atl1_set_mac_addr(&adapter->hw);
+-	return 0;
+-}
+-
+-static u32 atl1_check_link(struct atl1_adapter *adapter)
+-{
+-	struct atl1_hw *hw = &adapter->hw;
+-	struct net_device *netdev = adapter->netdev;
+-	u32 ret_val;
+-	u16 speed, duplex, phy_data;
+-	int reconfig = 0;
+-
+-	/* MII_BMSR must read twice */
+-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+-	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+-	if (!(phy_data & BMSR_LSTATUS)) {	/* link down */
+-		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
+-			dev_info(&adapter->pdev->dev, "link is down\n");
+-			adapter->link_speed = SPEED_0;
+-			netif_carrier_off(netdev);
+-			netif_stop_queue(netdev);
+-		}
+-		return ATL1_SUCCESS;
+-	}
+-
+-	/* Link Up */
+-	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
+-	if (ret_val)
+-		return ret_val;
+-
+-	switch (hw->media_type) {
+-	case MEDIA_TYPE_1000M_FULL:
+-		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
+-			reconfig = 1;
+-		break;
+-	case MEDIA_TYPE_100M_FULL:
+-		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
+-			reconfig = 1;
+-		break;
+-	case MEDIA_TYPE_100M_HALF:
+-		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
+-			reconfig = 1;
+-		break;
+-	case MEDIA_TYPE_10M_FULL:
+-		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
+-			reconfig = 1;
+-		break;
+-	case MEDIA_TYPE_10M_HALF:
+-		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
+-			reconfig = 1;
+-		break;
+-	}
+-
+-	/* link result is our setting */
+-	if (!reconfig) {
+-		if (adapter->link_speed != speed
+-		    || adapter->link_duplex != duplex) {
+-			adapter->link_speed = speed;
+-			adapter->link_duplex = duplex;
+-			atl1_setup_mac_ctrl(adapter);
+-			dev_info(&adapter->pdev->dev,
+-				"%s link is up %d Mbps %s\n",
+-				netdev->name, adapter->link_speed,
+-				adapter->link_duplex == FULL_DUPLEX ?
+-				"full duplex" : "half duplex");
+-		}
+-		if (!netif_carrier_ok(netdev)) {	/* Link down -> Up */
+-			netif_carrier_on(netdev);
+-			netif_wake_queue(netdev);
+-		}
+-		return ATL1_SUCCESS;
+-	}
+-
+-	/* change orignal link status */
+-	if (netif_carrier_ok(netdev)) {
+-		adapter->link_speed = SPEED_0;
+-		netif_carrier_off(netdev);
+-		netif_stop_queue(netdev);
+-	}
+-
+-	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
+-	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
+-		switch (hw->media_type) {
+-		case MEDIA_TYPE_100M_FULL:
+-			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+-			           MII_CR_RESET;
+-			break;
+-		case MEDIA_TYPE_100M_HALF:
+-			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+-			break;
+-		case MEDIA_TYPE_10M_FULL:
+-			phy_data =
+-			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+-			break;
+-		default:	/* MEDIA_TYPE_10M_HALF: */
+-			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+-			break;
+-		}
+-		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+-		return ATL1_SUCCESS;
+-	}
+-
+-	/* auto-neg, insert timer to re-config phy */
+-	if (!adapter->phy_timer_pending) {
+-		adapter->phy_timer_pending = true;
+-		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
+-	}
+-
+-	return ATL1_SUCCESS;
+-}
+-
+-static void atl1_check_for_link(struct atl1_adapter *adapter)
+-{
+-	struct net_device *netdev = adapter->netdev;
+-	u16 phy_data = 0;
+-
+-	spin_lock(&adapter->lock);
+-	adapter->phy_timer_pending = false;
+-	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+-	atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+-	spin_unlock(&adapter->lock);
+-
+-	/* notify upper layer link down ASAP */
+-	if (!(phy_data & BMSR_LSTATUS)) {	/* Link Down */
+-		if (netif_carrier_ok(netdev)) {	/* old link state: Up */
+-			dev_info(&adapter->pdev->dev, "%s link is down\n",
+-				netdev->name);
+-			adapter->link_speed = SPEED_0;
+-			netif_carrier_off(netdev);
+-			netif_stop_queue(netdev);
+-		}
+-	}
+-	schedule_work(&adapter->link_chg_task);
+-}
+-
+-/*
+- * atl1_set_multi - Multicast and Promiscuous mode set
+- * @netdev: network interface device structure
+- *
+- * The set_multi entry point is called whenever the multicast address
+- * list or the network interface flags are updated.  This routine is
+- * responsible for configuring the hardware for proper multicast,
+- * promiscuous mode, and all-multi behavior.
+- */
+-static void atl1_set_multi(struct net_device *netdev)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct atl1_hw *hw = &adapter->hw;
+-	struct dev_mc_list *mc_ptr;
+-	u32 rctl;
+-	u32 hash_value;
+-
+-	/* Check for Promiscuous and All Multicast modes */
+-	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+-	if (netdev->flags & IFF_PROMISC)
+-		rctl |= MAC_CTRL_PROMIS_EN;
+-	else if (netdev->flags & IFF_ALLMULTI) {
+-		rctl |= MAC_CTRL_MC_ALL_EN;
+-		rctl &= ~MAC_CTRL_PROMIS_EN;
+-	} else
+-		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+-
+-	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
+-
+-	/* clear the old settings from the multicast hash table */
+-	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+-	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+-
+-	/* compute mc addresses' hash value ,and put it into hash table */
+-	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+-		hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
+-		atl1_hash_set(hw, hash_value);
+-	}
+-}
+-
+-/*
+- * atl1_change_mtu - Change the Maximum Transfer Unit
+- * @netdev: network interface device structure
+- * @new_mtu: new value for maximum frame size
+- *
+- * Returns 0 on success, negative on failure
+- */
+-static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	int old_mtu = netdev->mtu;
+-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+-
+-	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+-	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+-		dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+-		return -EINVAL;
+-	}
+-
+-	adapter->hw.max_frame_size = max_frame;
+-	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
+-	adapter->rx_buffer_len = (max_frame + 7) & ~7;
+-	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
+-
+-	netdev->mtu = new_mtu;
+-	if ((old_mtu != new_mtu) && netif_running(netdev)) {
+-		atl1_down(adapter);
+-		atl1_up(adapter);
+-	}
+-
+-	return 0;
+-}
+-
+-static void set_flow_ctrl_old(struct atl1_adapter *adapter)
+-{
+-	u32 hi, lo, value;
+-
+-	/* RFD Flow Control */
+-	value = adapter->rfd_ring.count;
+-	hi = value / 16;
+-	if (hi < 2)
+-		hi = 2;
+-	lo = value * 7 / 8;
+-
+-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+-		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+-
+-	/* RRD Flow Control */
+-	value = adapter->rrd_ring.count;
+-	lo = value / 16;
+-	hi = value * 7 / 8;
+-	if (lo < 2)
+-		lo = 2;
+-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+-		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+-	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+-}
+-
+-static void set_flow_ctrl_new(struct atl1_hw *hw)
+-{
+-	u32 hi, lo, value;
+-
+-	/* RXF Flow Control */
+-	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
+-	lo = value / 16;
+-	if (lo < 192)
+-		lo = 192;
+-	hi = value * 7 / 8;
+-	if (hi < lo)
+-		hi = lo + 16;
+-	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+-		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+-	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+-
+-	/* RRD Flow Control */
+-	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
+-	lo = value / 8;
+-	hi = value * 7 / 8;
+-	if (lo < 2)
+-		lo = 2;
+-	if (hi < lo)
+-		hi = lo + 3;
+-	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+-		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+-	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+-}
+-
+-/*
+- * atl1_configure - Configure Transmit&Receive Unit after Reset
+- * @adapter: board private structure
+- *
+- * Configure the Tx /Rx unit of the MAC after a reset.
+- */
+-static u32 atl1_configure(struct atl1_adapter *adapter)
+-{
+-	struct atl1_hw *hw = &adapter->hw;
+-	u32 value;
+-
+-	/* clear interrupt status */
+-	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
+-
+-	/* set MAC Address */
+-	value = (((u32) hw->mac_addr[2]) << 24) |
+-		(((u32) hw->mac_addr[3]) << 16) |
+-		(((u32) hw->mac_addr[4]) << 8) |
+-		(((u32) hw->mac_addr[5]));
+-	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+-	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+-	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+-
+-	/* tx / rx ring */
+-
+-	/* HI base address */
+-	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
+-		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
+-	/* LO base address */
+-	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
+-		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
+-	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
+-		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
+-	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
+-		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
+-	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
+-		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
+-	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
+-		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
+-
+-	/* element count */
+-	value = adapter->rrd_ring.count;
+-	value <<= 16;
+-	value += adapter->rfd_ring.count;
+-	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
+-	iowrite32(adapter->tpd_ring.count, hw->hw_addr +
+-		REG_DESC_TPD_RING_SIZE);
+-
+-	/* Load Ptr */
+-	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
+-
+-	/* config Mailbox */
+-	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
+-		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
+-		((atomic_read(&adapter->rrd_ring.next_to_clean)
+-		& MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
+-		((atomic_read(&adapter->rfd_ring.next_to_use)
+-		& MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
+-	iowrite32(value, hw->hw_addr + REG_MAILBOX);
+-
+-	/* config IPG/IFG */
+-	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
+-		 << MAC_IPG_IFG_IPGT_SHIFT) |
+-		(((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
+-		<< MAC_IPG_IFG_MIFG_SHIFT) |
+-		(((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
+-		<< MAC_IPG_IFG_IPGR1_SHIFT) |
+-		(((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
+-		<< MAC_IPG_IFG_IPGR2_SHIFT);
+-	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
+-
+-	/* config  Half-Duplex Control */
+-	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
+-		(((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
+-		<< MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+-		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+-		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+-		(((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
+-		<< MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+-	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
+-
+-	/* set Interrupt Moderator Timer */
+-	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
+-	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
+-
+-	/* set Interrupt Clear Timer */
+-	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
+-
+-	/* set max frame size hw will accept */
+-	iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
+-
+-	/* jumbo size & rrd retirement timer */
+-	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
+-		 << RXQ_JMBOSZ_TH_SHIFT) |
+-		(((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
+-		<< RXQ_JMBO_LKAH_SHIFT) |
+-		(((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
+-		<< RXQ_RRD_TIMER_SHIFT);
+-	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
+-
+-	/* Flow Control */
+-	switch (hw->dev_rev) {
+-	case 0x8001:
+-	case 0x9001:
+-	case 0x9002:
+-	case 0x9003:
+-		set_flow_ctrl_old(adapter);
+-		break;
+-	default:
+-		set_flow_ctrl_new(hw);
+-		break;
+-	}
+-
+-	/* config TXQ */
+-	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
+-		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
+-		(((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
+-		<< TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
+-		(((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
+-		<< TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
+-		TXQ_CTRL_EN;
+-	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
+-
+-	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
+-	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
+-		<< TX_JUMBO_TASK_TH_SHIFT) |
+-		(((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
+-		<< TX_TPD_MIN_IPG_SHIFT);
+-	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
+-
+-	/* config RXQ */
+-	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
+-		<< RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
+-		(((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
+-		<< RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
+-		(((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
+-		<< RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
+-		RXQ_CTRL_EN;
+-	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
+-
+-	/* config DMA Engine */
+-	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+-		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+-		((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+-		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
+-		DMA_CTRL_DMAW_EN;
+-	value |= (u32) hw->dma_ord;
+-	if (atl1_rcb_128 == hw->rcb_value)
+-		value |= DMA_CTRL_RCB_VALUE;
+-	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
+-
+-	/* config CMB / SMB */
+-	value = (hw->cmb_tpd > adapter->tpd_ring.count) ?
+-		hw->cmb_tpd : adapter->tpd_ring.count;
+-	value <<= 16;
+-	value |= hw->cmb_rrd;
+-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
+-	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
+-	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
+-	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
+-
+-	/* --- enable CMB / SMB */
+-	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
+-	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
+-
+-	value = ioread32(adapter->hw.hw_addr + REG_ISR);
+-	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
+-		value = 1;	/* config failed */
+-	else
+-		value = 0;
+-
+-	/* clear all interrupt status */
+-	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
+-	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
+-	return value;
+-}
+-
+-/*
+- * atl1_pcie_patch - Patch for PCIE module
+- */
+-static void atl1_pcie_patch(struct atl1_adapter *adapter)
+-{
+-	u32 value;
+-
+-	/* much vendor magic here */
+-	value = 0x6500;
+-	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
+-	/* pcie flow control mode change */
+-	value = ioread32(adapter->hw.hw_addr + 0x1008);
+-	value |= 0x8000;
+-	iowrite32(value, adapter->hw.hw_addr + 0x1008);
+-}
+-
+-/*
+- * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
+- * on PCI Command register is disable.
+- * The function enable this bit.
+- * Brackett, 2006/03/15
+- */
+-static void atl1_via_workaround(struct atl1_adapter *adapter)
+-{
+-	unsigned long value;
+-
+-	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
+-	if (value & PCI_COMMAND_INTX_DISABLE)
+-		value &= ~PCI_COMMAND_INTX_DISABLE;
+-	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+-}
+-
+-/*
+- * atl1_irq_enable - Enable default interrupt generation settings
+- * @adapter: board private structure
+- */
+-static void atl1_irq_enable(struct atl1_adapter *adapter)
+-{
+-	iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+-	ioread32(adapter->hw.hw_addr + REG_IMR);
+-}
+-
+-/*
+- * atl1_irq_disable - Mask off interrupt generation on the NIC
+- * @adapter: board private structure
+- */
+-static void atl1_irq_disable(struct atl1_adapter *adapter)
+-{
+-	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+-	ioread32(adapter->hw.hw_addr + REG_IMR);
+-	synchronize_irq(adapter->pdev->irq);
+-}
+-
+-static void atl1_clear_phy_int(struct atl1_adapter *adapter)
+-{
+-	u16 phy_data;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&adapter->lock, flags);
+-	atl1_read_phy_reg(&adapter->hw, 19, &phy_data);
+-	spin_unlock_irqrestore(&adapter->lock, flags);
+-}
+-
+-static void atl1_inc_smb(struct atl1_adapter *adapter)
+-{
+-	struct stats_msg_block *smb = adapter->smb.smb;
+-
+-	/* Fill out the OS statistics structure */
+-	adapter->soft_stats.rx_packets += smb->rx_ok;
+-	adapter->soft_stats.tx_packets += smb->tx_ok;
+-	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
+-	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
+-	adapter->soft_stats.multicast += smb->rx_mcast;
+-	adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
+-		smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
+-
+-	/* Rx Errors */
+-	adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
+-		smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
+-		smb->rx_rrd_ov + smb->rx_align_err);
+-	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
+-	adapter->soft_stats.rx_length_errors += smb->rx_len_err;
+-	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
+-	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
+-	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
+-		smb->rx_rxf_ov);
+-
+-	adapter->soft_stats.rx_pause += smb->rx_pause;
+-	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
+-	adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
+-
+-	/* Tx Errors */
+-	adapter->soft_stats.tx_errors += (smb->tx_late_col +
+-		smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
+-	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
+-	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
+-	adapter->soft_stats.tx_window_errors += smb->tx_late_col;
+-
+-	adapter->soft_stats.excecol += smb->tx_abort_col;
+-	adapter->soft_stats.deffer += smb->tx_defer;
+-	adapter->soft_stats.scc += smb->tx_1_col;
+-	adapter->soft_stats.mcc += smb->tx_2_col;
+-	adapter->soft_stats.latecol += smb->tx_late_col;
+-	adapter->soft_stats.tx_underun += smb->tx_underrun;
+-	adapter->soft_stats.tx_trunc += smb->tx_trunc;
+-	adapter->soft_stats.tx_pause += smb->tx_pause;
+-
+-	adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
+-	adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
+-	adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
+-	adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
+-	adapter->net_stats.multicast = adapter->soft_stats.multicast;
+-	adapter->net_stats.collisions = adapter->soft_stats.collisions;
+-	adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
+-	adapter->net_stats.rx_over_errors =
+-		adapter->soft_stats.rx_missed_errors;
+-	adapter->net_stats.rx_length_errors =
+-		adapter->soft_stats.rx_length_errors;
+-	adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
+-	adapter->net_stats.rx_frame_errors =
+-		adapter->soft_stats.rx_frame_errors;
+-	adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
+-	adapter->net_stats.rx_missed_errors =
+-		adapter->soft_stats.rx_missed_errors;
+-	adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
+-	adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
+-	adapter->net_stats.tx_aborted_errors =
+-		adapter->soft_stats.tx_aborted_errors;
+-	adapter->net_stats.tx_window_errors =
+-		adapter->soft_stats.tx_window_errors;
+-	adapter->net_stats.tx_carrier_errors =
+-		adapter->soft_stats.tx_carrier_errors;
+-}
+-
+-/*
+- * atl1_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 *atl1_get_stats(struct net_device *netdev)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	return &adapter->net_stats;
+-}
+-
+-static void atl1_update_mailbox(struct atl1_adapter *adapter)
+-{
+-	unsigned long flags;
+-	u32 tpd_next_to_use;
+-	u32 rfd_next_to_use;
+-	u32 rrd_next_to_clean;
+-	u32 value;
+-
+-	spin_lock_irqsave(&adapter->mb_lock, flags);
+-
+-	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+-	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
+-	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
+-
+-	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+-		MB_RFD_PROD_INDX_SHIFT) |
+-		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+-		MB_RRD_CONS_INDX_SHIFT) |
+-		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+-		MB_TPD_PROD_INDX_SHIFT);
+-	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+-
+-	spin_unlock_irqrestore(&adapter->mb_lock, flags);
+-}
+-
+-static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
+-	struct rx_return_desc *rrd, u16 offset)
+-{
+-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+-
+-	while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
+-		rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
+-		if (++rfd_ring->next_to_clean == rfd_ring->count) {
+-			rfd_ring->next_to_clean = 0;
+-		}
+-	}
+-}
+-
+-static void atl1_update_rfd_index(struct atl1_adapter *adapter,
+-	struct rx_return_desc *rrd)
+-{
+-	u16 num_buf;
+-
+-	num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
+-		adapter->rx_buffer_len;
+-	if (rrd->num_buf == num_buf)
+-		/* clean alloc flag for bad rrd */
+-		atl1_clean_alloc_flag(adapter, rrd, num_buf);
+-}
+-
+-static void atl1_rx_checksum(struct atl1_adapter *adapter,
+-	struct rx_return_desc *rrd, struct sk_buff *skb)
+-{
+-	struct pci_dev *pdev = adapter->pdev;
+-
+-	skb->ip_summed = CHECKSUM_NONE;
+-
+-	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+-		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
+-					ERR_FLAG_CODE | ERR_FLAG_OV)) {
+-			adapter->hw_csum_err++;
+-			dev_printk(KERN_DEBUG, &pdev->dev,
+-				"rx checksum error\n");
+-			return;
+-		}
+-	}
+-
+-	/* not IPv4 */
+-	if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
+-		/* checksum is invalid, but it's not an IPv4 pkt, so ok */
+-		return;
+-
+-	/* IPv4 packet */
+-	if (likely(!(rrd->err_flg &
+-		(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
+-		skb->ip_summed = CHECKSUM_UNNECESSARY;
+-		adapter->hw_csum_good++;
+-		return;
+-	}
+-
+-	/* IPv4, but hardware thinks its checksum is wrong */
+-	dev_printk(KERN_DEBUG, &pdev->dev,
+-		"hw csum wrong, pkt_flag:%x, err_flag:%x\n",
+-		rrd->pkt_flg, rrd->err_flg);
+-	skb->ip_summed = CHECKSUM_COMPLETE;
+-	skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
+-	adapter->hw_csum_err++;
+-	return;
+-}
+-
+-/*
+- * atl1_alloc_rx_buffers - Replace used receive buffers
+- * @adapter: address of board private structure
+- */
+-static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
+-{
+-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+-	struct pci_dev *pdev = adapter->pdev;
+-	struct page *page;
+-	unsigned long offset;
+-	struct atl1_buffer *buffer_info, *next_info;
+-	struct sk_buff *skb;
+-	u16 num_alloc = 0;
+-	u16 rfd_next_to_use, next_next;
+-	struct rx_free_desc *rfd_desc;
+-
+-	next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
+-	if (++next_next == rfd_ring->count)
+-		next_next = 0;
+-	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+-	next_info = &rfd_ring->buffer_info[next_next];
+-
+-	while (!buffer_info->alloced && !next_info->alloced) {
+-		if (buffer_info->skb) {
+-			buffer_info->alloced = 1;
+-			goto next;
+-		}
+-
+-		rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
+-
+-		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+-		if (unlikely(!skb)) {	/* Better luck next round */
+-			adapter->net_stats.rx_dropped++;
+-			break;
+-		}
+-
+-		/*
+-		 * Make buffer alignment 2 beyond a 16 byte boundary
+-		 * this will result in a 16 byte aligned IP header after
+-		 * the 14 byte MAC header is removed
+-		 */
+-		skb_reserve(skb, NET_IP_ALIGN);
+-
+-		buffer_info->alloced = 1;
+-		buffer_info->skb = skb;
+-		buffer_info->length = (u16) adapter->rx_buffer_len;
+-		page = virt_to_page(skb->data);
+-		offset = (unsigned long)skb->data & ~PAGE_MASK;
+-		buffer_info->dma = pci_map_page(pdev, page, offset,
+-						adapter->rx_buffer_len,
+-						PCI_DMA_FROMDEVICE);
+-		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+-		rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
+-		rfd_desc->coalese = 0;
+-
+-next:
+-		rfd_next_to_use = next_next;
+-		if (unlikely(++next_next == rfd_ring->count))
+-			next_next = 0;
+-
+-		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+-		next_info = &rfd_ring->buffer_info[next_next];
+-		num_alloc++;
+-	}
+-
+-	if (num_alloc) {
+-		/*
+-		 * Force memory writes to complete before letting h/w
+-		 * know there are new descriptors to fetch.  (Only
+-		 * applicable for weak-ordered memory model archs,
+-		 * such as IA-64).
+-		 */
+-		wmb();
+-		atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
+-	}
+-	return num_alloc;
+-}
+-
+-static void atl1_intr_rx(struct atl1_adapter *adapter)
+-{
+-	int i, count;
+-	u16 length;
+-	u16 rrd_next_to_clean;
+-	u32 value;
+-	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+-	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+-	struct atl1_buffer *buffer_info;
+-	struct rx_return_desc *rrd;
+-	struct sk_buff *skb;
+-
+-	count = 0;
+-
+-	rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
+-
+-	while (1) {
+-		rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
+-		i = 1;
+-		if (likely(rrd->xsz.valid)) {	/* packet valid */
+-chk_rrd:
+-			/* check rrd status */
+-			if (likely(rrd->num_buf == 1))
+-				goto rrd_ok;
+-
+-			/* rrd seems to be bad */
+-			if (unlikely(i-- > 0)) {
+-				/* rrd may not be DMAed completely */
+-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+-					"incomplete RRD DMA transfer\n");
+-				udelay(1);
+-				goto chk_rrd;
+-			}
+-			/* bad rrd */
+-			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+-				"bad RRD\n");
+-			/* see if update RFD index */
+-			if (rrd->num_buf > 1)
+-				atl1_update_rfd_index(adapter, rrd);
+-
+-			/* update rrd */
+-			rrd->xsz.valid = 0;
+-			if (++rrd_next_to_clean == rrd_ring->count)
+-				rrd_next_to_clean = 0;
+-			count++;
+-			continue;
+-		} else {	/* current rrd still not be updated */
+-
+-			break;
+-		}
+-rrd_ok:
+-		/* clean alloc flag for bad rrd */
+-		atl1_clean_alloc_flag(adapter, rrd, 0);
+-
+-		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
+-		if (++rfd_ring->next_to_clean == rfd_ring->count)
+-			rfd_ring->next_to_clean = 0;
+-
+-		/* update rrd next to clean */
+-		if (++rrd_next_to_clean == rrd_ring->count)
+-			rrd_next_to_clean = 0;
+-		count++;
+-
+-		if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+-			if (!(rrd->err_flg &
+-				(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
+-				| ERR_FLAG_LEN))) {
+-				/* packet error, don't need upstream */
+-				buffer_info->alloced = 0;
+-				rrd->xsz.valid = 0;
+-				continue;
+-			}
+-		}
+-
+-		/* Good Receive */
+-		pci_unmap_page(adapter->pdev, buffer_info->dma,
+-			       buffer_info->length, PCI_DMA_FROMDEVICE);
+-		skb = buffer_info->skb;
+-		length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
+-
+-		skb_put(skb, length - ETH_FCS_LEN);
+-
+-		/* Receive Checksum Offload */
+-		atl1_rx_checksum(adapter, rrd, skb);
+-		skb->protocol = eth_type_trans(skb, adapter->netdev);
+-
+-		if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
+-			u16 vlan_tag = (rrd->vlan_tag >> 4) |
+-					((rrd->vlan_tag & 7) << 13) |
+-					((rrd->vlan_tag & 8) << 9);
+-			vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
+-		} else
+-			netif_rx(skb);
+-
+-		/* let protocol layer free skb */
+-		buffer_info->skb = NULL;
+-		buffer_info->alloced = 0;
+-		rrd->xsz.valid = 0;
+-
+-		adapter->netdev->last_rx = jiffies;
+-	}
+-
+-	atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
+-
+-	atl1_alloc_rx_buffers(adapter);
+-
+-	/* update mailbox ? */
+-	if (count) {
+-		u32 tpd_next_to_use;
+-		u32 rfd_next_to_use;
+-
+-		spin_lock(&adapter->mb_lock);
+-
+-		tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+-		rfd_next_to_use =
+-		    atomic_read(&adapter->rfd_ring.next_to_use);
+-		rrd_next_to_clean =
+-		    atomic_read(&adapter->rrd_ring.next_to_clean);
+-		value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+-			MB_RFD_PROD_INDX_SHIFT) |
+-                        ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+-			MB_RRD_CONS_INDX_SHIFT) |
+-                        ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+-			MB_TPD_PROD_INDX_SHIFT);
+-		iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+-		spin_unlock(&adapter->mb_lock);
+-	}
+-}
+-
+-static void atl1_intr_tx(struct atl1_adapter *adapter)
+-{
+-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+-	struct atl1_buffer *buffer_info;
+-	u16 sw_tpd_next_to_clean;
+-	u16 cmb_tpd_next_to_clean;
+-
+-	sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+-	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
+-
+-	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
+-		struct tx_packet_desc *tpd;
+-
+-		tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
+-		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
+-		if (buffer_info->dma) {
+-			pci_unmap_page(adapter->pdev, buffer_info->dma,
+-				       buffer_info->length, PCI_DMA_TODEVICE);
+-			buffer_info->dma = 0;
+-		}
+-
+-		if (buffer_info->skb) {
+-			dev_kfree_skb_irq(buffer_info->skb);
+-			buffer_info->skb = NULL;
+-		}
+-		tpd->buffer_addr = 0;
+-		tpd->desc.data = 0;
+-
+-		if (++sw_tpd_next_to_clean == tpd_ring->count)
+-			sw_tpd_next_to_clean = 0;
+-	}
+-	atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
+-
+-	if (netif_queue_stopped(adapter->netdev)
+-	    && netif_carrier_ok(adapter->netdev))
+-		netif_wake_queue(adapter->netdev);
+-}
+-
+-static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
+-{
+-	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) ?
+-		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,
+-			 struct tso_param *tso)
+-{
+-	/* We enter this function holding a spinlock. */
+-	u8 ipofst;
+-	int err;
+-
+-	if (skb_shinfo(skb)->gso_size) {
+-		if (skb_header_cloned(skb)) {
+-			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+-			if (unlikely(err))
+-				return err;
+-		}
+-
+-		if (skb->protocol == ntohs(ETH_P_IP)) {
+-			struct iphdr *iph = ip_hdr(skb);
+-
+-			iph->tot_len = 0;
+-			iph->check = 0;
+-			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+-				iph->daddr, 0, IPPROTO_TCP, 0);
+-			ipofst = skb_network_offset(skb);
+-			if (ipofst != ETH_HLEN) /* 802.3 frame */
+-				tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT;
+-
+-			tso->tsopl |= (iph->ihl &
+-				CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT;
+-			tso->tsopl |= (tcp_hdrlen(skb) &
+-				TSO_PARAM_TCPHDRLEN_MASK) <<
+-				TSO_PARAM_TCPHDRLEN_SHIFT;
+-			tso->tsopl |= (skb_shinfo(skb)->gso_size &
+-				TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT;
+-			tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT;
+-			tso->tsopl |= 1 << TSO_PARAM_TCPCKSUM_SHIFT;
+-			tso->tsopl |= 1 << TSO_PARAM_SEGMENT_SHIFT;
+-			return true;
+-		}
+-	}
+-	return false;
+-}
+-
+-static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
+-	struct csum_param *csum)
+-{
+-	u8 css, cso;
+-
+-	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+-		cso = skb_transport_offset(skb);
+-		css = cso + skb->csum_offset;
+-		if (unlikely(cso & 0x1)) {
+-			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+-				"payload offset not an even number\n");
+-			return -1;
+-		}
+-		csum->csumpl |= (cso & CSUM_PARAM_PLOADOFFSET_MASK) <<
+-			CSUM_PARAM_PLOADOFFSET_SHIFT;
+-		csum->csumpl |= (css & CSUM_PARAM_XSUMOFFSET_MASK) <<
+-			CSUM_PARAM_XSUMOFFSET_SHIFT;
+-		csum->csumpl |= 1 << CSUM_PARAM_CUSTOMCKSUM_SHIFT;
+-		return true;
+-	}
+-
+-	return true;
+-}
+-
+-static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+-	bool tcp_seg)
+-{
+-	/* We enter this function holding a spinlock. */
+-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+-	struct atl1_buffer *buffer_info;
+-	struct page *page;
+-	int first_buf_len = skb->len;
+-	unsigned long offset;
+-	unsigned int nr_frags;
+-	unsigned int f;
+-	u16 tpd_next_to_use;
+-	u16 proto_hdr_len;
+-	u16 len12;
+-
+-	first_buf_len -= skb->data_len;
+-	nr_frags = skb_shinfo(skb)->nr_frags;
+-	tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
+-	buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+-	if (unlikely(buffer_info->skb))
+-		BUG();
+-	buffer_info->skb = NULL;	/* put skb in last TPD */
+-
+-	if (tcp_seg) {
+-		/* TSO/GSO */
+-		proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+-		buffer_info->length = proto_hdr_len;
+-		page = virt_to_page(skb->data);
+-		offset = (unsigned long)skb->data & ~PAGE_MASK;
+-		buffer_info->dma = pci_map_page(adapter->pdev, page,
+-						offset, proto_hdr_len,
+-						PCI_DMA_TODEVICE);
+-
+-		if (++tpd_next_to_use == tpd_ring->count)
+-			tpd_next_to_use = 0;
+-
+-		if (first_buf_len > proto_hdr_len) {
+-			int i, m;
+-
+-			len12 = first_buf_len - proto_hdr_len;
+-			m = (len12 + ATL1_MAX_TX_BUF_LEN - 1) /
+-				ATL1_MAX_TX_BUF_LEN;
+-			for (i = 0; i < m; i++) {
+-				buffer_info =
+-				    &tpd_ring->buffer_info[tpd_next_to_use];
+-				buffer_info->skb = NULL;
+-				buffer_info->length =
+-				    (ATL1_MAX_TX_BUF_LEN >=
+-				     len12) ? ATL1_MAX_TX_BUF_LEN : len12;
+-				len12 -= buffer_info->length;
+-				page = virt_to_page(skb->data +
+-					(proto_hdr_len +
+-					i * ATL1_MAX_TX_BUF_LEN));
+-				offset = (unsigned long)(skb->data +
+-					(proto_hdr_len +
+-					i * ATL1_MAX_TX_BUF_LEN)) & ~PAGE_MASK;
+-				buffer_info->dma = pci_map_page(adapter->pdev,
+-					page, offset, buffer_info->length,
+-					PCI_DMA_TODEVICE);
+-				if (++tpd_next_to_use == tpd_ring->count)
+-					tpd_next_to_use = 0;
+-			}
+-		}
+-	} else {
+-		/* not TSO/GSO */
+-		buffer_info->length = first_buf_len;
+-		page = virt_to_page(skb->data);
+-		offset = (unsigned long)skb->data & ~PAGE_MASK;
+-		buffer_info->dma = pci_map_page(adapter->pdev, page,
+-			offset, first_buf_len, PCI_DMA_TODEVICE);
+-		if (++tpd_next_to_use == tpd_ring->count)
+-			tpd_next_to_use = 0;
+-	}
+-
+-	for (f = 0; f < nr_frags; f++) {
+-		struct skb_frag_struct *frag;
+-		u16 lenf, i, m;
+-
+-		frag = &skb_shinfo(skb)->frags[f];
+-		lenf = frag->size;
+-
+-		m = (lenf + ATL1_MAX_TX_BUF_LEN - 1) / ATL1_MAX_TX_BUF_LEN;
+-		for (i = 0; i < m; i++) {
+-			buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+-			if (unlikely(buffer_info->skb))
+-				BUG();
+-			buffer_info->skb = NULL;
+-			buffer_info->length = (lenf > ATL1_MAX_TX_BUF_LEN) ?
+-				ATL1_MAX_TX_BUF_LEN : lenf;
+-			lenf -= buffer_info->length;
+-			buffer_info->dma = pci_map_page(adapter->pdev,
+-				frag->page,
+-				frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
+-				buffer_info->length, PCI_DMA_TODEVICE);
+-
+-			if (++tpd_next_to_use == tpd_ring->count)
+-				tpd_next_to_use = 0;
+-		}
+-	}
+-
+-	/* last tpd's buffer-info */
+-	buffer_info->skb = skb;
+-}
+-
+-static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
+-       union tpd_descr *descr)
+-{
+-	/* We enter this function holding a spinlock. */
+-	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+-	int j;
+-	u32 val;
+-	struct atl1_buffer *buffer_info;
+-	struct tx_packet_desc *tpd;
+-	u16 tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
+-
+-	for (j = 0; j < count; j++) {
+-		buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+-		tpd = ATL1_TPD_DESC(&adapter->tpd_ring, tpd_next_to_use);
+-		tpd->desc.csum.csumpu = descr->csum.csumpu;
+-		tpd->desc.csum.csumpl = descr->csum.csumpl;
+-		tpd->desc.tso.tsopu = descr->tso.tsopu;
+-		tpd->desc.tso.tsopl = descr->tso.tsopl;
+-		tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+-		tpd->desc.data = descr->data;
+-		tpd->desc.csum.csumpu |= (cpu_to_le16(buffer_info->length) &
+-			CSUM_PARAM_BUFLEN_MASK) << CSUM_PARAM_BUFLEN_SHIFT;
+-
+-		val = (descr->tso.tsopl >> TSO_PARAM_SEGMENT_SHIFT) &
+-			TSO_PARAM_SEGMENT_MASK;
+-		if (val && !j)
+-			tpd->desc.tso.tsopl |= 1 << TSO_PARAM_HDRFLAG_SHIFT;
+-
+-		if (j == (count - 1))
+-			tpd->desc.csum.csumpl |= 1 << CSUM_PARAM_EOP_SHIFT;
+-
+-		if (++tpd_next_to_use == tpd_ring->count)
+-			tpd_next_to_use = 0;
+-	}
+-	/*
+-	 * Force memory writes to complete before letting h/w
+-	 * know there are new descriptors to fetch.  (Only
+-	 * applicable for weak-ordered memory model archs,
+-	 * such as IA-64).
+-	 */
+-	wmb();
+-
+-	atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use);
+-}
+-
+-static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	int len = skb->len;
+-	int tso;
+-	int count = 1;
+-	int ret_val;
+-	u32 val;
+-	union tpd_descr param;
+-	u16 frag_size;
+-	u16 vlan_tag;
+-	unsigned long flags;
+-	unsigned int nr_frags = 0;
+-	unsigned int mss = 0;
+-	unsigned int f;
+-	unsigned int proto_hdr_len;
+-
+-	len -= skb->data_len;
+-
+-	if (unlikely(skb->len == 0)) {
+-		dev_kfree_skb_any(skb);
+-		return NETDEV_TX_OK;
+-	}
+-
+-	param.data = 0;
+-	param.tso.tsopu = 0;
+-	param.tso.tsopl = 0;
+-	param.csum.csumpu = 0;
+-	param.csum.csumpl = 0;
+-
+-	/* nr_frags will be nonzero if we're doing scatter/gather (SG) */
+-	nr_frags = skb_shinfo(skb)->nr_frags;
+-	for (f = 0; f < nr_frags; f++) {
+-		frag_size = skb_shinfo(skb)->frags[f].size;
+-		if (frag_size)
+-			count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
+-				ATL1_MAX_TX_BUF_LEN;
+-	}
+-
+-	/* mss will be nonzero if we're doing segment offload (TSO/GSO) */
+-	mss = skb_shinfo(skb)->gso_size;
+-	if (mss) {
+-		if (skb->protocol == htons(ETH_P_IP)) {
+-			proto_hdr_len = (skb_transport_offset(skb) +
+-					 tcp_hdrlen(skb));
+-			if (unlikely(proto_hdr_len > len)) {
+-				dev_kfree_skb_any(skb);
+-				return NETDEV_TX_OK;
+-			}
+-			/* need additional TPD ? */
+-			if (proto_hdr_len != len)
+-				count += (len - proto_hdr_len +
+-					ATL1_MAX_TX_BUF_LEN - 1) /
+-					ATL1_MAX_TX_BUF_LEN;
+-		}
+-	}
+-
+-	if (!spin_trylock_irqsave(&adapter->lock, flags)) {
+-		/* Can't get lock - tell upper layer to requeue */
+-		dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx locked\n");
+-		return NETDEV_TX_LOCKED;
+-	}
+-
+-	if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
+-		/* not enough descriptors */
+-		netif_stop_queue(netdev);
+-		spin_unlock_irqrestore(&adapter->lock, flags);
+-		dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx busy\n");
+-		return NETDEV_TX_BUSY;
+-	}
+-
+-	param.data = 0;
+-
+-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+-		vlan_tag = vlan_tx_tag_get(skb);
+-		vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
+-			((vlan_tag >> 9) & 0x8);
+-		param.csum.csumpl |= 1 << CSUM_PARAM_INSVLAG_SHIFT;
+-		param.csum.csumpu |= (vlan_tag & CSUM_PARAM_VALANTAG_MASK) <<
+-			CSUM_PARAM_VALAN_SHIFT;
+-	}
+-
+-	tso = atl1_tso(adapter, skb, &param.tso);
+-	if (tso < 0) {
+-		spin_unlock_irqrestore(&adapter->lock, flags);
+-		dev_kfree_skb_any(skb);
+-		return NETDEV_TX_OK;
+-	}
+-
+-	if (!tso) {
+-		ret_val = atl1_tx_csum(adapter, skb, &param.csum);
+-		if (ret_val < 0) {
+-			spin_unlock_irqrestore(&adapter->lock, flags);
+-			dev_kfree_skb_any(skb);
+-			return NETDEV_TX_OK;
+-		}
+-	}
+-
+-	val = (param.csum.csumpl >> CSUM_PARAM_SEGMENT_SHIFT) &
+-		CSUM_PARAM_SEGMENT_MASK;
+-	atl1_tx_map(adapter, skb, 1 == val);
+-	atl1_tx_queue(adapter, count, &param);
+-	netdev->trans_start = jiffies;
+-	spin_unlock_irqrestore(&adapter->lock, flags);
+-	atl1_update_mailbox(adapter);
+-	return NETDEV_TX_OK;
+-}
+-
+-/*
+- * atl1_intr - Interrupt Handler
+- * @irq: interrupt number
+- * @data: pointer to a network interface device structure
+- * @pt_regs: CPU registers structure
+- */
+-static irqreturn_t atl1_intr(int irq, void *data)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(data);
+-	u32 status;
+-	int max_ints = 10;
+-
+-	status = adapter->cmb.cmb->int_stats;
+-	if (!status)
+-		return IRQ_NONE;
+-
+-	do {
+-		/* clear CMB interrupt status at once */
+-		adapter->cmb.cmb->int_stats = 0;
+-
+-		if (status & ISR_GPHY)	/* clear phy status */
+-			atl1_clear_phy_int(adapter);
+-
+-		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+-		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+-
+-		/* check if SMB intr */
+-		if (status & ISR_SMB)
+-			atl1_inc_smb(adapter);
+-
+-		/* check if PCIE PHY Link down */
+-		if (status & ISR_PHY_LINKDOWN) {
+-			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+-				"pcie phy link down %x\n", status);
+-			if (netif_running(adapter->netdev)) {	/* reset MAC */
+-				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+-				schedule_work(&adapter->pcie_dma_to_rst_task);
+-				return IRQ_HANDLED;
+-			}
+-		}
+-
+-		/* check if DMA read/write error ? */
+-		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+-			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+-				"pcie DMA r/w error (status = 0x%x)\n",
+-				status);
+-			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+-			schedule_work(&adapter->pcie_dma_to_rst_task);
+-			return IRQ_HANDLED;
+-		}
+-
+-		/* link event */
+-		if (status & ISR_GPHY) {
+-			adapter->soft_stats.tx_carrier_errors++;
+-			atl1_check_for_link(adapter);
+-		}
+-
+-		/* transmit event */
+-		if (status & ISR_CMB_TX)
+-			atl1_intr_tx(adapter);
+-
+-		/* rx exception */
+-		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+-			ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+-			ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+-			if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+-				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+-				ISR_HOST_RRD_OV))
+-				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+-					"rx exception, ISR = 0x%x\n", status);
+-			atl1_intr_rx(adapter);
+-		}
+-
+-		if (--max_ints < 0)
+-			break;
+-
+-	} while ((status = adapter->cmb.cmb->int_stats));
+-
+-	/* re-enable Interrupt */
+-	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
+-	return IRQ_HANDLED;
+-}
+-
+-/*
+- * atl1_watchdog - Timer Call-back
+- * @data: pointer to netdev cast into an unsigned long
+- */
+-static void atl1_watchdog(unsigned long data)
+-{
+-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+-
+-	/* Reset the timer */
+-	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+-}
+-
+-/*
+- * atl1_phy_config - Timer Call-back
+- * @data: pointer to netdev cast into an unsigned long
+- */
+-static void atl1_phy_config(unsigned long data)
+-{
+-	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+-	struct atl1_hw *hw = &adapter->hw;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&adapter->lock, flags);
+-	adapter->phy_timer_pending = false;
+-	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+-	atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
+-	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+-	spin_unlock_irqrestore(&adapter->lock, flags);
+-}
+-
+-/*
+- * atl1_tx_timeout - Respond to a Tx Hang
+- * @netdev: network interface device structure
+- */
+-static void atl1_tx_timeout(struct net_device *netdev)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	/* Do the reset outside of interrupt context */
+-	schedule_work(&adapter->tx_timeout_task);
+-}
+-
+-/*
+- * Orphaned vendor comment left intact here:
+- * <vendor comment>
+- * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
+- * will assert. We do soft reset <0x1400=1> according
+- * with the SPEC. BUT, it seemes that PCIE or DMA
+- * state-machine will not be reset. DMAR_TO_INT will
+- * assert again and again.
+- * </vendor comment>
+- */
+-static void atl1_tx_timeout_task(struct work_struct *work)
+-{
+-	struct atl1_adapter *adapter =
+-		container_of(work, struct atl1_adapter, tx_timeout_task);
+-	struct net_device *netdev = adapter->netdev;
+-
+-	netif_device_detach(netdev);
+-	atl1_down(adapter);
+-	atl1_up(adapter);
+-	netif_device_attach(netdev);
+-}
+-
+-/*
+- * atl1_link_chg_task - deal with link change event Out of interrupt context
+- */
+-static void atl1_link_chg_task(struct work_struct *work)
+-{
+-	struct atl1_adapter *adapter =
+-               container_of(work, struct atl1_adapter, link_chg_task);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&adapter->lock, flags);
+-	atl1_check_link(adapter);
+-	spin_unlock_irqrestore(&adapter->lock, flags);
+-}
+-
+-static void atl1_vlan_rx_register(struct net_device *netdev,
+-	struct vlan_group *grp)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	unsigned long flags;
+-	u32 ctrl;
+-
+-	spin_lock_irqsave(&adapter->lock, flags);
+-	/* atl1_irq_disable(adapter); */
+-	adapter->vlgrp = grp;
+-
+-	if (grp) {
+-		/* enable VLAN tag insert/strip */
+-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+-		ctrl |= MAC_CTRL_RMV_VLAN;
+-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+-	} else {
+-		/* disable VLAN tag insert/strip */
+-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+-		ctrl &= ~MAC_CTRL_RMV_VLAN;
+-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+-	}
+-
+-	/* atl1_irq_enable(adapter); */
+-	spin_unlock_irqrestore(&adapter->lock, flags);
+-}
+-
+-static void atl1_restore_vlan(struct atl1_adapter *adapter)
+-{
+-	atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+-}
+-
+-int atl1_reset(struct atl1_adapter *adapter)
+-{
+-	int ret;
+-
+-	ret = atl1_reset_hw(&adapter->hw);
+-	if (ret != ATL1_SUCCESS)
+-		return ret;
+-	return atl1_init_hw(&adapter->hw);
+-}
+-
+-s32 atl1_up(struct atl1_adapter *adapter)
+-{
+-	struct net_device *netdev = adapter->netdev;
+-	int err;
+-	int irq_flags = IRQF_SAMPLE_RANDOM;
+-
+-	/* hardware has been reset, we need to reload some things */
+-	atl1_set_multi(netdev);
+-	atl1_init_ring_ptrs(adapter);
+-	atl1_restore_vlan(adapter);
+-	err = atl1_alloc_rx_buffers(adapter);
+-	if (unlikely(!err))		/* no RX BUFFER allocated */
+-		return -ENOMEM;
+-
+-	if (unlikely(atl1_configure(adapter))) {
+-		err = -EIO;
+-		goto err_up;
+-	}
+-
+-	err = pci_enable_msi(adapter->pdev);
+-	if (err) {
+-		dev_info(&adapter->pdev->dev,
+-			"Unable to enable MSI: %d\n", err);
+-		irq_flags |= IRQF_SHARED;
+-	}
+-
+-	err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,
+-			netdev->name, netdev);
+-	if (unlikely(err))
+-		goto err_up;
+-
+-	mod_timer(&adapter->watchdog_timer, jiffies);
+-	atl1_irq_enable(adapter);
+-	atl1_check_link(adapter);
+-	return 0;
+-
+-err_up:
+-	pci_disable_msi(adapter->pdev);
+-	/* free rx_buffers */
+-	atl1_clean_rx_ring(adapter);
+-	return err;
+-}
+-
+-void atl1_down(struct atl1_adapter *adapter)
+-{
+-	struct net_device *netdev = adapter->netdev;
+-
+-	del_timer_sync(&adapter->watchdog_timer);
+-	del_timer_sync(&adapter->phy_config_timer);
+-	adapter->phy_timer_pending = false;
+-
+-	atl1_irq_disable(adapter);
+-	free_irq(adapter->pdev->irq, netdev);
+-	pci_disable_msi(adapter->pdev);
+-	atl1_reset_hw(&adapter->hw);
+-	adapter->cmb.cmb->int_stats = 0;
+-
+-	adapter->link_speed = SPEED_0;
+-	adapter->link_duplex = -1;
+-	netif_carrier_off(netdev);
+-	netif_stop_queue(netdev);
+-
+-	atl1_clean_tx_ring(adapter);
+-	atl1_clean_rx_ring(adapter);
+-}
+-
+-/*
+- * atl1_open - Called when a network interface is made active
+- * @netdev: network interface device structure
+- *
+- * Returns 0 on success, negative value on failure
+- *
+- * The open entry point is called when a network interface is made
+- * active by the system (IFF_UP).  At this point all resources needed
+- * for transmit and receive operations are allocated, the interrupt
+- * handler is registered with the OS, the watchdog timer is started,
+- * and the stack is notified that the interface is ready.
+- */
+-static int atl1_open(struct net_device *netdev)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	int err;
+-
+-	/* allocate transmit descriptors */
+-	err = atl1_setup_ring_resources(adapter);
+-	if (err)
+-		return err;
+-
+-	err = atl1_up(adapter);
+-	if (err)
+-		goto err_up;
+-
+-	return 0;
+-
+-err_up:
+-	atl1_reset(adapter);
+-	return err;
+-}
+-
+-/*
+- * atl1_close - Disables a network interface
+- * @netdev: network interface device structure
+- *
+- * Returns 0, this is not allowed to fail
+- *
+- * The close entry point is called when an interface is de-activated
+- * by the OS.  The hardware is still under the drivers control, but
+- * needs to be disabled.  A global MAC reset is issued to stop the
+- * hardware, and all transmit and receive resources are freed.
+- */
+-static int atl1_close(struct net_device *netdev)
+-{
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	atl1_down(adapter);
+-	atl1_free_ring_resources(adapter);
+-	return 0;
+-}
+-
+-#ifdef CONFIG_PM
+-static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+-	struct net_device *netdev = pci_get_drvdata(pdev);
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	struct atl1_hw *hw = &adapter->hw;
+-	u32 ctrl = 0;
+-	u32 wufc = adapter->wol;
+-
+-	netif_device_detach(netdev);
+-	if (netif_running(netdev))
+-		atl1_down(adapter);
+-
+-	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+-	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+-	if (ctrl & BMSR_LSTATUS)
+-		wufc &= ~ATL1_WUFC_LNKC;
+-
+-	/* reduce speed to 10/100M */
+-	if (wufc) {
+-		atl1_phy_enter_power_saving(hw);
+-		/* if resume, let driver to re- setup link */
+-		hw->phy_configured = false;
+-		atl1_set_mac_addr(hw);
+-		atl1_set_multi(netdev);
+-
+-		ctrl = 0;
+-		/* turn on magic packet wol */
+-		if (wufc & ATL1_WUFC_MAG)
+-			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+-
+-		/* turn on Link change WOL */
+-		if (wufc & ATL1_WUFC_LNKC)
+-			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+-		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+-
+-		/* turn on all-multi mode if wake on multicast is enabled */
+-		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+-		ctrl &= ~MAC_CTRL_DBG;
+-		ctrl &= ~MAC_CTRL_PROMIS_EN;
+-		if (wufc & ATL1_WUFC_MC)
+-			ctrl |= MAC_CTRL_MC_ALL_EN;
+-		else
+-			ctrl &= ~MAC_CTRL_MC_ALL_EN;
+-
+-		/* turn on broadcast mode if wake on-BC is enabled */
+-		if (wufc & ATL1_WUFC_BC)
+-			ctrl |= MAC_CTRL_BC_EN;
+-		else
+-			ctrl &= ~MAC_CTRL_BC_EN;
+-
+-		/* enable RX */
+-		ctrl |= MAC_CTRL_RX_EN;
+-		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
+-		pci_enable_wake(pdev, PCI_D3hot, 1);
+-		pci_enable_wake(pdev, PCI_D3cold, 1);
+-	} else {
+-		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
+-		pci_enable_wake(pdev, PCI_D3hot, 0);
+-		pci_enable_wake(pdev, PCI_D3cold, 0);
+-	}
+-
+-	pci_save_state(pdev);
+-	pci_disable_device(pdev);
+-
+-	pci_set_power_state(pdev, PCI_D3hot);
+-
+-	return 0;
+-}
+-
+-static int atl1_resume(struct pci_dev *pdev)
+-{
+-	struct net_device *netdev = pci_get_drvdata(pdev);
+-	struct atl1_adapter *adapter = netdev_priv(netdev);
+-	u32 ret_val;
+-
+-	pci_set_power_state(pdev, 0);
+-	pci_restore_state(pdev);
+-
+-	ret_val = pci_enable_device(pdev);
+-	pci_enable_wake(pdev, PCI_D3hot, 0);
+-	pci_enable_wake(pdev, PCI_D3cold, 0);
+-
+-	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
+-	atl1_reset(adapter);
+-
+-	if (netif_running(netdev))
+-		atl1_up(adapter);
+-	netif_device_attach(netdev);
+-
+-	atl1_via_workaround(adapter);
+-
+-	return 0;
+-}
+-#else
+-#define atl1_suspend NULL
+-#define atl1_resume NULL
+-#endif
+-
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-static void atl1_poll_controller(struct net_device *netdev)
+-{
+-	disable_irq(netdev->irq);
+-	atl1_intr(netdev->irq, netdev);
+-	enable_irq(netdev->irq);
+-}
+-#endif
+-
+-/*
+- * atl1_probe - Device Initialization Routine
+- * @pdev: PCI device information struct
+- * @ent: entry in atl1_pci_tbl
+- *
+- * Returns 0 on success, negative on failure
+- *
+- * atl1_probe initializes an adapter identified by a pci_dev structure.
+- * The OS initialization, configuring of the adapter private structure,
+- * and a hardware reset occur.
+- */
+-static int __devinit atl1_probe(struct pci_dev *pdev,
+-	const struct pci_device_id *ent)
+-{
+-	struct net_device *netdev;
+-	struct atl1_adapter *adapter;
+-	static int cards_found = 0;
+-	int err;
+-
+-	err = pci_enable_device(pdev);
+-	if (err)
+-		return err;
+-
+-	/*
+-	 * The atl1 chip can DMA to 64-bit addresses, but it uses a single
+-	 * shared register for the high 32 bits, so only a single, aligned,
+-	 * 4 GB physical address range can be used at a time.
+-	 *
+-	 * Supporting 64-bit DMA on this hardware is more trouble than it's
+-	 * worth.  It is far easier to limit to 32-bit DMA than update
+-	 * various kernel subsystems to support the mechanics required by a
+-	 * fixed-high-32-bit system.
+-	 */
+-	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+-	if (err) {
+-		dev_err(&pdev->dev, "no usable DMA configuration\n");
+-		goto err_dma;
+-	}
+-	/* Mark all PCI regions associated with PCI device
+-	 * pdev as being reserved by owner atl1_driver_name
+-	 */
+-	err = pci_request_regions(pdev, atl1_driver_name);
+-	if (err)
+-		goto err_request_regions;
+-
+-	/* Enables bus-mastering on the device and calls
+-	 * pcibios_set_master to do the needed arch specific settings
+-	 */
+-	pci_set_master(pdev);
+-
+-	netdev = alloc_etherdev(sizeof(struct atl1_adapter));
+-	if (!netdev) {
+-		err = -ENOMEM;
+-		goto err_alloc_etherdev;
+-	}
+-	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.hw_addr = pci_iomap(pdev, 0, 0);
+-	if (!adapter->hw.hw_addr) {
+-		err = -EIO;
+-		goto err_pci_iomap;
+-	}
+-	/* get device revision number */
+-	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
+-		(REG_MASTER_CTRL + 2));
+-	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
+-
+-	/* set default ring resource counts */
+-	adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
+-	adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
+-
+-	adapter->mii.dev = netdev;
+-	adapter->mii.mdio_read = mdio_read;
+-	adapter->mii.mdio_write = mdio_write;
+-	adapter->mii.phy_id_mask = 0x1f;
+-	adapter->mii.reg_num_mask = 0x1f;
+-
+-	netdev->open = &atl1_open;
+-	netdev->stop = &atl1_close;
+-	netdev->hard_start_xmit = &atl1_xmit_frame;
+-	netdev->get_stats = &atl1_get_stats;
+-	netdev->set_multicast_list = &atl1_set_multi;
+-	netdev->set_mac_address = &atl1_set_mac;
+-	netdev->change_mtu = &atl1_change_mtu;
+-	netdev->do_ioctl = &atl1_ioctl;
+-	netdev->tx_timeout = &atl1_tx_timeout;
+-	netdev->watchdog_timeo = 5 * HZ;
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-	netdev->poll_controller = atl1_poll_controller;
+-#endif
+-	netdev->vlan_rx_register = atl1_vlan_rx_register;
+-
+-	netdev->ethtool_ops = &atl1_ethtool_ops;
+-	adapter->bd_number = cards_found;
+-
+-	/* setup the private structure */
+-	err = atl1_sw_init(adapter);
+-	if (err)
+-		goto err_common;
+-
+-	netdev->features = NETIF_F_HW_CSUM;
+-	netdev->features |= NETIF_F_SG;
+-	netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+-
+-	/*
+-	 * FIXME - Until tso performance gets fixed, disable the feature.
+-	 * Enable it with ethtool -K if desired.
+-	 */
+-	/* netdev->features |= NETIF_F_TSO; */
+-
+-	netdev->features |= NETIF_F_LLTX;
+-
+-	/*
+-	 * patch for some L1 of old version,
+-	 * the final version of L1 may not need these
+-	 * patches
+-	 */
+-	/* atl1_pcie_patch(adapter); */
+-
+-	/* really reset GPHY core */
+-	iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
+-
+-	/*
+-	 * reset the controller to
+-	 * put the device in a known good starting state
+-	 */
+-	if (atl1_reset_hw(&adapter->hw)) {
+-		err = -EIO;
+-		goto err_common;
+-	}
+-
+-	/* copy the MAC address out of the EEPROM */
+-	atl1_read_mac_addr(&adapter->hw);
+-	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+-
+-	if (!is_valid_ether_addr(netdev->dev_addr)) {
+-		err = -EIO;
+-		goto err_common;
+-	}
+-
+-	atl1_check_options(adapter);
+-
+-	/* pre-init the MAC, and setup link */
+-	err = atl1_init_hw(&adapter->hw);
+-	if (err) {
+-		err = -EIO;
+-		goto err_common;
+-	}
+-
+-	atl1_pcie_patch(adapter);
+-	/* assume we have no link for now */
+-	netif_carrier_off(netdev);
+-	netif_stop_queue(netdev);
+-
+-	init_timer(&adapter->watchdog_timer);
+-	adapter->watchdog_timer.function = &atl1_watchdog;
+-	adapter->watchdog_timer.data = (unsigned long)adapter;
+-
+-	init_timer(&adapter->phy_config_timer);
+-	adapter->phy_config_timer.function = &atl1_phy_config;
+-	adapter->phy_config_timer.data = (unsigned long)adapter;
+-	adapter->phy_timer_pending = false;
+-
+-	INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
+-
+-	INIT_WORK(&adapter->link_chg_task, atl1_link_chg_task);
+-
+-	INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
+-
+-	err = register_netdev(netdev);
+-	if (err)
+-		goto err_common;
+-
+-	cards_found++;
+-	atl1_via_workaround(adapter);
+-	return 0;
+-
+-err_common:
+-	pci_iounmap(pdev, adapter->hw.hw_addr);
+-err_pci_iomap:
+-	free_netdev(netdev);
+-err_alloc_etherdev:
+-	pci_release_regions(pdev);
+-err_dma:
+-err_request_regions:
+-	pci_disable_device(pdev);
+-	return err;
+-}
+-
+-/*
+- * atl1_remove - Device Removal Routine
+- * @pdev: PCI device information struct
+- *
+- * atl1_remove is called by the PCI subsystem to alert the driver
+- * that it should release a PCI device.  The could be caused by a
+- * Hot-Plug event, or because the driver is going to be removed from
+- * memory.
+- */
+-static void __devexit atl1_remove(struct pci_dev *pdev)
+-{
+-	struct net_device *netdev = pci_get_drvdata(pdev);
+-	struct atl1_adapter *adapter;
+-	/* Device not available. Return. */
+-	if (!netdev)
+-		return;
+-
+-	adapter = netdev_priv(netdev);
+-
+-	/* Some atl1 boards lack persistent storage for their MAC, and get it
+-	 * from the BIOS during POST.  If we've been messing with the MAC
+-	 * address, we need to save the permanent one.
+-	 */
+-	if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
+-		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
+-			ETH_ALEN);
+-		atl1_set_mac_addr(&adapter->hw);
+-	}
+-
+-	iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
+-	unregister_netdev(netdev);
+-	pci_iounmap(pdev, adapter->hw.hw_addr);
+-	pci_release_regions(pdev);
+-	free_netdev(netdev);
+-	pci_disable_device(pdev);
+-}
+-
+-static struct pci_driver atl1_driver = {
+-	.name = atl1_driver_name,
+-	.id_table = atl1_pci_tbl,
+-	.probe = atl1_probe,
+-	.remove = __devexit_p(atl1_remove),
+-	.suspend = atl1_suspend,
+-	.resume = atl1_resume
+-};
+-
+-/*
+- * atl1_exit_module - Driver Exit Cleanup Routine
+- *
+- * atl1_exit_module is called just before the driver is removed
+- * from memory.
+- */
+-static void __exit atl1_exit_module(void)
+-{
+-	pci_unregister_driver(&atl1_driver);
+-}
+-
+-/*
+- * atl1_init_module - Driver Registration Routine
+- *
+- * atl1_init_module is the first routine called when the driver is
+- * loaded. All it does is register with the PCI subsystem.
+- */
+-static int __init atl1_init_module(void)
+-{
+-	return pci_register_driver(&atl1_driver);
+-}
+-
+-module_init(atl1_init_module);
+-module_exit(atl1_exit_module);
+diff --git a/drivers/net/atl1/atl1_param.c b/drivers/net/atl1/atl1_param.c
+deleted file mode 100644
+index 4246bb9..0000000
+--- a/drivers/net/atl1/atl1_param.c
++++ /dev/null
+@@ -1,203 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * Derived from Intel e1000 driver
+- * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the Free
+- * Software Foundation; either version 2 of the License, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc., 59
+- * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/moduleparam.h>
+-#include <linux/pci.h>
+-#include "atl1.h"
+-
+-/*
+- * This is the only thing that needs to be changed to adjust the
+- * maximum number of ports that the driver can manage.
+- */
+-#define ATL1_MAX_NIC 4
+-
+-#define OPTION_UNSET    -1
+-#define OPTION_DISABLED 0
+-#define OPTION_ENABLED  1
+-
+-#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
+-
+-/*
+- * Interrupt Moderate Timer in units of 2 us
+- *
+- * Valid Range: 10-65535
+- *
+- * Default Value: 100 (200us)
+- */
+-static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+-static int num_int_mod_timer = 0;
+-module_param_array_named(int_mod_timer, int_mod_timer, int, &num_int_mod_timer, 0);
+-MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
+-
+-/*
+- * flash_vendor
+- *
+- * Valid Range: 0-2
+- *
+- * 0 - Atmel
+- * 1 - SST
+- * 2 - ST
+- *
+- * Default Value: 0
+- */
+-static int __devinitdata flash_vendor[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+-static int num_flash_vendor = 0;
+-module_param_array_named(flash_vendor, flash_vendor, int, &num_flash_vendor, 0);
+-MODULE_PARM_DESC(flash_vendor, "SPI flash vendor");
+-
+-#define DEFAULT_INT_MOD_CNT	100	/* 200us */
+-#define MAX_INT_MOD_CNT		65000
+-#define MIN_INT_MOD_CNT		50
+-
+-#define FLASH_VENDOR_DEFAULT	0
+-#define FLASH_VENDOR_MIN	0
+-#define FLASH_VENDOR_MAX	2
+-
+-struct atl1_option {
+-	enum { enable_option, range_option, list_option } type;
+-	char *name;
+-	char *err;
+-	int def;
+-	union {
+-		struct {	/* range_option info */
+-			int min;
+-			int max;
+-		} r;
+-		struct {	/* list_option info */
+-			int nr;
+-			struct atl1_opt_list {
+-				int i;
+-				char *str;
+-			} *p;
+-		} l;
+-	} arg;
+-};
+-
+-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, struct pci_dev *pdev)
+-{
+-	if (*value == OPTION_UNSET) {
+-		*value = opt->def;
+-		return 0;
+-	}
+-
+-	switch (opt->type) {
+-	case enable_option:
+-		switch (*value) {
+-		case OPTION_ENABLED:
+-			dev_info(&pdev->dev, "%s enabled\n", opt->name);
+-			return 0;
+-		case OPTION_DISABLED:
+-			dev_info(&pdev->dev, "%s disabled\n", opt->name);
+-			return 0;
+-		}
+-		break;
+-	case range_option:
+-		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+-			dev_info(&pdev->dev, "%s set to %i\n", opt->name,
+-				*value);
+-			return 0;
+-		}
+-		break;
+-	case list_option:{
+-			int i;
+-			struct atl1_opt_list *ent;
+-
+-			for (i = 0; i < opt->arg.l.nr; i++) {
+-				ent = &opt->arg.l.p[i];
+-				if (*value == ent->i) {
+-					if (ent->str[0] != '\0')
+-						dev_info(&pdev->dev, "%s\n",
+-							ent->str);
+-					return 0;
+-				}
+-			}
+-		}
+-		break;
+-
+-	default:
+-		break;
+-	}
+-
+-	dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
+-		opt->name, *value, opt->err);
+-	*value = opt->def;
+-	return -1;
+-}
+-
+-/*
+- * atl1_check_options - Range Checking for Command Line Parameters
+- * @adapter: board private structure
+- *
+- * This routine checks all command line parameters for valid user
+- * input.  If an invalid value is given, or if no user specified
+- * value exists, a default value is used.  The final value is stored
+- * in a variable in the adapter structure.
+- */
+-void __devinit atl1_check_options(struct atl1_adapter *adapter)
+-{
+-	struct pci_dev *pdev = adapter->pdev;
+-	int bd = adapter->bd_number;
+-	if (bd >= ATL1_MAX_NIC) {
+-		dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
+-		dev_notice(&pdev->dev, "using defaults for all values\n");
+-	}
+-	{			/* Interrupt Moderate Timer */
+-		struct atl1_option opt = {
+-			.type = range_option,
+-			.name = "Interrupt Moderator Timer",
+-			.err = "using default of "
+-				__MODULE_STRING(DEFAULT_INT_MOD_CNT),
+-			.def = DEFAULT_INT_MOD_CNT,
+-			.arg = {.r =
+-				{.min = MIN_INT_MOD_CNT,.max = MAX_INT_MOD_CNT}}
+-		};
+-		int val;
+-		if (num_int_mod_timer > bd) {
+-			val = int_mod_timer[bd];
+-			atl1_validate_option(&val, &opt, pdev);
+-			adapter->imt = (u16) val;
+-		} else
+-			adapter->imt = (u16) (opt.def);
+-	}
+-
+-	{			/* Flash Vendor */
+-		struct atl1_option opt = {
+-			.type = range_option,
+-			.name = "SPI Flash Vendor",
+-			.err = "using default of "
+-				__MODULE_STRING(FLASH_VENDOR_DEFAULT),
+-			.def = DEFAULT_INT_MOD_CNT,
+-			.arg = {.r =
+-				{.min = FLASH_VENDOR_MIN,.max =
+-				 FLASH_VENDOR_MAX}}
+-		};
+-		int val;
+-		if (num_flash_vendor > bd) {
+-			val = flash_vendor[bd];
+-			atl1_validate_option(&val, &opt, pdev);
+-			adapter->hw.flash_vendor = (u8) val;
+-		} else
+-			adapter->hw.flash_vendor = (u8) (opt.def);
+-	}
+-}
+diff --git a/drivers/net/atlx/Makefile b/drivers/net/atlx/Makefile
+new file mode 100644
+index 0000000..ca45553
+--- /dev/null
++++ b/drivers/net/atlx/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_ATL1)	+= atl1.o
+diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
+new file mode 100644
+index 0000000..0afe522
+--- /dev/null
++++ b/drivers/net/atlx/atl1.c
+@@ -0,0 +1,3702 @@
++/*
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ *
++ * Derived from Intel e1000 driver
++ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59
++ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called COPYING.
++ *
++ * Contact Information:
++ * Xiong Huang <xiong_huang at attansic.com>
++ * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei,
++ * Xinzhu  302, TAIWAN, REPUBLIC OF CHINA
++ *
++ * Chris Snook <csnook at redhat.com>
++ * Jay Cliburn <jcliburn at gmail.com>
++ *
++ * This version is adapted from the Attansic reference driver for
++ * inclusion in the Linux kernel.  It is currently under heavy development.
++ * A very incomplete list of things that need to be dealt with:
++ *
++ * TODO:
++ * Wake on LAN.
++ * Add more ethtool functions.
++ * Fix abstruse irq enable/disable condition described here:
++ *	http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
++ *
++ * NEEDS TESTING:
++ * VLAN
++ * multicast
++ * promiscuous mode
++ * interrupt coalescing
++ * SMP torture testing
++ */
++
++#include <asm/atomic.h>
++#include <asm/byteorder.h>
++
++#include <linux/compiler.h>
++#include <linux/crc32.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/etherdevice.h>
++#include <linux/hardirq.h>
++#include <linux/if_ether.h>
++#include <linux/if_vlan.h>
++#include <linux/in.h>
++#include <linux/interrupt.h>
++#include <linux/ip.h>
++#include <linux/irqflags.h>
++#include <linux/irqreturn.h>
++#include <linux/jiffies.h>
++#include <linux/mii.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/net.h>
++#include <linux/netdevice.h>
++#include <linux/pci.h>
++#include <linux/pci_ids.h>
++#include <linux/pm.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/tcp.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
++
++#include <net/checksum.h>
++
++#include "atl1.h"
++
++/* Temporary hack for merging atl1 and atl2 */
++#include "atlx.c"
++
++/*
++ * This is the only thing that needs to be changed to adjust the
++ * maximum number of ports that the driver can manage.
++ */
++#define ATL1_MAX_NIC 4
++
++#define OPTION_UNSET    -1
++#define OPTION_DISABLED 0
++#define OPTION_ENABLED  1
++
++#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
++
++/*
++ * Interrupt Moderate Timer in units of 2 us
++ *
++ * Valid Range: 10-65535
++ *
++ * Default Value: 100 (200us)
++ */
++static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
++static int num_int_mod_timer;
++module_param_array_named(int_mod_timer, int_mod_timer, int,
++	&num_int_mod_timer, 0);
++MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
++
++#define DEFAULT_INT_MOD_CNT	100	/* 200us */
++#define MAX_INT_MOD_CNT		65000
++#define MIN_INT_MOD_CNT		50
++
++struct atl1_option {
++	enum { enable_option, range_option, list_option } type;
++	char *name;
++	char *err;
++	int def;
++	union {
++		struct {	/* range_option info */
++			int min;
++			int max;
++		} r;
++		struct {	/* list_option info */
++			int nr;
++			struct atl1_opt_list {
++				int i;
++				char *str;
++			} *p;
++		} l;
++	} arg;
++};
++
++static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
++	struct pci_dev *pdev)
++{
++	if (*value == OPTION_UNSET) {
++		*value = opt->def;
++		return 0;
++	}
++
++	switch (opt->type) {
++	case enable_option:
++		switch (*value) {
++		case OPTION_ENABLED:
++			dev_info(&pdev->dev, "%s enabled\n", opt->name);
++			return 0;
++		case OPTION_DISABLED:
++			dev_info(&pdev->dev, "%s disabled\n", opt->name);
++			return 0;
++		}
++		break;
++	case range_option:
++		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
++			dev_info(&pdev->dev, "%s set to %i\n", opt->name,
++				*value);
++			return 0;
++		}
++		break;
++	case list_option:{
++			int i;
++			struct atl1_opt_list *ent;
++
++			for (i = 0; i < opt->arg.l.nr; i++) {
++				ent = &opt->arg.l.p[i];
++				if (*value == ent->i) {
++					if (ent->str[0] != '\0')
++						dev_info(&pdev->dev, "%s\n",
++							ent->str);
++					return 0;
++				}
++			}
++		}
++		break;
++
++	default:
++		break;
++	}
++
++	dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
++		opt->name, *value, opt->err);
++	*value = opt->def;
++	return -1;
++}
++
++/*
++ * atl1_check_options - Range Checking for Command Line Parameters
++ * @adapter: board private structure
++ *
++ * This routine checks all command line parameters for valid user
++ * input.  If an invalid value is given, or if no user specified
++ * value exists, a default value is used.  The final value is stored
++ * in a variable in the adapter structure.
++ */
++void __devinit atl1_check_options(struct atl1_adapter *adapter)
++{
++	struct pci_dev *pdev = adapter->pdev;
++	int bd = adapter->bd_number;
++	if (bd >= ATL1_MAX_NIC) {
++		dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
++		dev_notice(&pdev->dev, "using defaults for all values\n");
++	}
++	{			/* Interrupt Moderate Timer */
++		struct atl1_option opt = {
++			.type = range_option,
++			.name = "Interrupt Moderator Timer",
++			.err = "using default of "
++				__MODULE_STRING(DEFAULT_INT_MOD_CNT),
++			.def = DEFAULT_INT_MOD_CNT,
++			.arg = {.r = {.min = MIN_INT_MOD_CNT,
++					.max = MAX_INT_MOD_CNT} }
++		};
++		int val;
++		if (num_int_mod_timer > bd) {
++			val = int_mod_timer[bd];
++			atl1_validate_option(&val, &opt, pdev);
++			adapter->imt = (u16) val;
++		} else
++			adapter->imt = (u16) (opt.def);
++	}
++}
++
++/*
++ * atl1_pci_tbl - PCI Device ID Table
++ */
++static const struct pci_device_id atl1_pci_tbl[] = {
++	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
++	/* required last entry */
++	{0,}
++};
++MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
++
++static const u32 atl1_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
++	NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
++
++static int debug = -1;
++module_param(debug, int, 0);
++MODULE_PARM_DESC(debug, "Message level (0=none,...,16=all)");
++
++/*
++ * Reset the transmit and receive units; mask and clear all interrupts.
++ * hw - Struct containing variables accessed by shared code
++ * return : 0  or  idle status (if error)
++ */
++static s32 atl1_reset_hw(struct atl1_hw *hw)
++{
++	struct pci_dev *pdev = hw->back->pdev;
++	struct atl1_adapter *adapter = hw->back;
++	u32 icr;
++	int i;
++
++	/*
++	 * Clear Interrupt mask to stop board from generating
++	 * interrupts & Clear any pending interrupt events
++	 */
++	/*
++	 * iowrite32(0, hw->hw_addr + REG_IMR);
++	 * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
++	 */
++
++	/*
++	 * Issue Soft Reset to the MAC.  This will reset the chip's
++	 * transmit, receive, DMA.  It will not effect
++	 * the current PCI configuration.  The global reset bit is self-
++	 * clearing, and should clear within a microsecond.
++	 */
++	iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
++	ioread32(hw->hw_addr + REG_MASTER_CTRL);
++
++	iowrite16(1, hw->hw_addr + REG_PHY_ENABLE);
++	ioread16(hw->hw_addr + REG_PHY_ENABLE);
++
++	/* delay about 1ms */
++	msleep(1);
++
++	/* Wait at least 10ms for All module to be Idle */
++	for (i = 0; i < 10; i++) {
++		icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
++		if (!icr)
++			break;
++		/* delay 1 ms */
++		msleep(1);
++		/* FIXME: still the right way to do this? */
++		cpu_relax();
++	}
++
++	if (icr) {
++		if (netif_msg_hw(adapter))
++			dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
++		return icr;
++	}
++
++	return 0;
++}
++
++/* function about EEPROM
++ *
++ * check_eeprom_exist
++ * return 0 if eeprom exist
++ */
++static int atl1_check_eeprom_exist(struct atl1_hw *hw)
++{
++	u32 value;
++	value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++	if (value & SPI_FLASH_CTRL_EN_VPD) {
++		value &= ~SPI_FLASH_CTRL_EN_VPD;
++		iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++	}
++
++	value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
++	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
++}
++
++static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
++{
++	int i;
++	u32 control;
++
++	if (offset & 3)
++		/* address do not align */
++		return false;
++
++	iowrite32(0, hw->hw_addr + REG_VPD_DATA);
++	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
++	iowrite32(control, hw->hw_addr + REG_VPD_CAP);
++	ioread32(hw->hw_addr + REG_VPD_CAP);
++
++	for (i = 0; i < 10; i++) {
++		msleep(2);
++		control = ioread32(hw->hw_addr + REG_VPD_CAP);
++		if (control & VPD_CAP_VPD_FLAG)
++			break;
++	}
++	if (control & VPD_CAP_VPD_FLAG) {
++		*p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
++		return true;
++	}
++	/* timeout */
++	return false;
++}
++
++/*
++ * Reads the value from a PHY register
++ * hw - Struct containing variables accessed by shared code
++ * reg_addr - address of the PHY register to read
++ */
++s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
++{
++	u32 val;
++	int i;
++
++	val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
++		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
++		MDIO_CLK_SEL_SHIFT;
++	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
++	ioread32(hw->hw_addr + REG_MDIO_CTRL);
++
++	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
++		udelay(2);
++		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
++		if (!(val & (MDIO_START | MDIO_BUSY)))
++			break;
++	}
++	if (!(val & (MDIO_START | MDIO_BUSY))) {
++		*phy_data = (u16) val;
++		return 0;
++	}
++	return ATLX_ERR_PHY;
++}
++
++#define CUSTOM_SPI_CS_SETUP	2
++#define CUSTOM_SPI_CLK_HI	2
++#define CUSTOM_SPI_CLK_LO	2
++#define CUSTOM_SPI_CS_HOLD	2
++#define CUSTOM_SPI_CS_HI	3
++
++static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
++{
++	int i;
++	u32 value;
++
++	iowrite32(0, hw->hw_addr + REG_SPI_DATA);
++	iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
++
++	value = SPI_FLASH_CTRL_WAIT_READY |
++	    (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
++	    SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
++					     SPI_FLASH_CTRL_CLK_HI_MASK) <<
++	    SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
++					   SPI_FLASH_CTRL_CLK_LO_MASK) <<
++	    SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
++					   SPI_FLASH_CTRL_CS_HOLD_MASK) <<
++	    SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
++					    SPI_FLASH_CTRL_CS_HI_MASK) <<
++	    SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
++	    SPI_FLASH_CTRL_INS_SHIFT;
++
++	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++
++	value |= SPI_FLASH_CTRL_START;
++	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++	ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++
++	for (i = 0; i < 10; i++) {
++		msleep(1);
++		value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++		if (!(value & SPI_FLASH_CTRL_START))
++			break;
++	}
++
++	if (value & SPI_FLASH_CTRL_START)
++		return false;
++
++	*buf = ioread32(hw->hw_addr + REG_SPI_DATA);
++
++	return true;
++}
++
++/*
++ * get_permanent_address
++ * return 0 if get valid mac address,
++ */
++static int atl1_get_permanent_address(struct atl1_hw *hw)
++{
++	u32 addr[2];
++	u32 i, control;
++	u16 reg;
++	u8 eth_addr[ETH_ALEN];
++	bool key_valid;
++
++	if (is_valid_ether_addr(hw->perm_mac_addr))
++		return 0;
++
++	/* init */
++	addr[0] = addr[1] = 0;
++
++	if (!atl1_check_eeprom_exist(hw)) {
++		reg = 0;
++		key_valid = false;
++		/* Read out all EEPROM content */
++		i = 0;
++		while (1) {
++			if (atl1_read_eeprom(hw, i + 0x100, &control)) {
++				if (key_valid) {
++					if (reg == REG_MAC_STA_ADDR)
++						addr[0] = control;
++					else if (reg == (REG_MAC_STA_ADDR + 4))
++						addr[1] = control;
++					key_valid = false;
++				} else if ((control & 0xff) == 0x5A) {
++					key_valid = true;
++					reg = (u16) (control >> 16);
++				} else
++					break;
++			} else
++				/* read error */
++				break;
++			i += 4;
++		}
++
++		*(u32 *) &eth_addr[2] = swab32(addr[0]);
++		*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
++		if (is_valid_ether_addr(eth_addr)) {
++			memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
++			return 0;
++		}
++		return 1;
++	}
++
++	/* see if SPI FLAGS exist ? */
++	addr[0] = addr[1] = 0;
++	reg = 0;
++	key_valid = false;
++	i = 0;
++	while (1) {
++		if (atl1_spi_read(hw, i + 0x1f000, &control)) {
++			if (key_valid) {
++				if (reg == REG_MAC_STA_ADDR)
++					addr[0] = control;
++				else if (reg == (REG_MAC_STA_ADDR + 4))
++					addr[1] = control;
++				key_valid = false;
++			} else if ((control & 0xff) == 0x5A) {
++				key_valid = true;
++				reg = (u16) (control >> 16);
++			} else
++				/* data end */
++				break;
++		} else
++			/* read error */
++			break;
++		i += 4;
++	}
++
++	*(u32 *) &eth_addr[2] = swab32(addr[0]);
++	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
++	if (is_valid_ether_addr(eth_addr)) {
++		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
++		return 0;
++	}
++
++	/*
++	 * On some motherboards, the MAC address is written by the
++	 * BIOS directly to the MAC register during POST, and is
++	 * not stored in eeprom.  If all else thus far has failed
++	 * to fetch the permanent MAC address, try reading it directly.
++	 */
++	addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
++	addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
++	*(u32 *) &eth_addr[2] = swab32(addr[0]);
++	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
++	if (is_valid_ether_addr(eth_addr)) {
++		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
++		return 0;
++	}
++
++	return 1;
++}
++
++/*
++ * Reads the adapter's MAC address from the EEPROM
++ * hw - Struct containing variables accessed by shared code
++ */
++s32 atl1_read_mac_addr(struct atl1_hw *hw)
++{
++	u16 i;
++
++	if (atl1_get_permanent_address(hw))
++		random_ether_addr(hw->perm_mac_addr);
++
++	for (i = 0; i < ETH_ALEN; i++)
++		hw->mac_addr[i] = hw->perm_mac_addr[i];
++	return 0;
++}
++
++/*
++ * Hashes an address to determine its location in the multicast table
++ * hw - Struct containing variables accessed by shared code
++ * mc_addr - the multicast address to hash
++ *
++ * atl1_hash_mc_addr
++ *  purpose
++ *      set hash value for a multicast address
++ *      hash calcu processing :
++ *          1. calcu 32bit CRC for multicast address
++ *          2. reverse crc with MSB to LSB
++ */
++u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
++{
++	u32 crc32, value = 0;
++	int i;
++
++	crc32 = ether_crc_le(6, mc_addr);
++	for (i = 0; i < 32; i++)
++		value |= (((crc32 >> i) & 1) << (31 - i));
++
++	return value;
++}
++
++/*
++ * Sets the bit in the multicast table corresponding to the hash value.
++ * hw - Struct containing variables accessed by shared code
++ * hash_value - Multicast address hash value
++ */
++void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
++{
++	u32 hash_bit, hash_reg;
++	u32 mta;
++
++	/*
++	 * The HASH Table  is a register array of 2 32-bit registers.
++	 * It is treated like an array of 64 bits.  We want to set
++	 * bit BitArray[hash_value]. So we figure out what register
++	 * the bit is in, read it, OR in the new bit, then write
++	 * back the new value.  The register is determined by the
++	 * upper 7 bits of the hash value and the bit within that
++	 * register are determined by the lower 5 bits of the value.
++	 */
++	hash_reg = (hash_value >> 31) & 0x1;
++	hash_bit = (hash_value >> 26) & 0x1F;
++	mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
++	mta |= (1 << hash_bit);
++	iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
++}
++
++/*
++ * Writes a value to a PHY register
++ * hw - Struct containing variables accessed by shared code
++ * reg_addr - address of the PHY register to write
++ * data - data to write to the PHY
++ */
++static s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
++{
++	int i;
++	u32 val;
++
++	val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
++	    (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
++	    MDIO_SUP_PREAMBLE |
++	    MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
++	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
++	ioread32(hw->hw_addr + REG_MDIO_CTRL);
++
++	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
++		udelay(2);
++		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
++		if (!(val & (MDIO_START | MDIO_BUSY)))
++			break;
++	}
++
++	if (!(val & (MDIO_START | MDIO_BUSY)))
++		return 0;
++
++	return ATLX_ERR_PHY;
++}
++
++/*
++ * Make L001's PHY out of Power Saving State (bug)
++ * hw - Struct containing variables accessed by shared code
++ * when power on, L001's PHY always on Power saving State
++ * (Gigabit Link forbidden)
++ */
++static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
++{
++	s32 ret;
++	ret = atl1_write_phy_reg(hw, 29, 0x0029);
++	if (ret)
++		return ret;
++	return atl1_write_phy_reg(hw, 30, 0);
++}
++
++/*
++ *TODO: do something or get rid of this
++ */
++#ifdef CONFIG_PM
++static s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
++{
++/*    s32 ret_val;
++ *    u16 phy_data;
++ */
++
++/*
++    ret_val = atl1_write_phy_reg(hw, ...);
++    ret_val = atl1_write_phy_reg(hw, ...);
++    ....
++*/
++	return 0;
++}
++#endif
++
++/*
++ * Resets the PHY and make all config validate
++ * hw - Struct containing variables accessed by shared code
++ *
++ * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
++ */
++static s32 atl1_phy_reset(struct atl1_hw *hw)
++{
++	struct pci_dev *pdev = hw->back->pdev;
++	struct atl1_adapter *adapter = hw->back;
++	s32 ret_val;
++	u16 phy_data;
++
++	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++	    hw->media_type == MEDIA_TYPE_1000M_FULL)
++		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
++	else {
++		switch (hw->media_type) {
++		case MEDIA_TYPE_100M_FULL:
++			phy_data =
++			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
++			    MII_CR_RESET;
++			break;
++		case MEDIA_TYPE_100M_HALF:
++			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++			break;
++		case MEDIA_TYPE_10M_FULL:
++			phy_data =
++			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
++			break;
++		default:
++			/* MEDIA_TYPE_10M_HALF: */
++			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++			break;
++		}
++	}
++
++	ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++	if (ret_val) {
++		u32 val;
++		int i;
++		/* pcie serdes link may be down! */
++		if (netif_msg_hw(adapter))
++			dev_dbg(&pdev->dev, "pcie phy link down\n");
++
++		for (i = 0; i < 25; i++) {
++			msleep(1);
++			val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
++			if (!(val & (MDIO_START | MDIO_BUSY)))
++				break;
++		}
++
++		if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
++			if (netif_msg_hw(adapter))
++				dev_warn(&pdev->dev,
++					"pcie link down at least 25ms\n");
++			return ret_val;
++		}
++	}
++	return 0;
++}
++
++/*
++ * Configures PHY autoneg and flow control advertisement settings
++ * hw - Struct containing variables accessed by shared code
++ */
++static s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
++{
++	s32 ret_val;
++	s16 mii_autoneg_adv_reg;
++	s16 mii_1000t_ctrl_reg;
++
++	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
++	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
++
++	/* Read the MII 1000Base-T Control Register (Address 9). */
++	mii_1000t_ctrl_reg = MII_ATLX_CR_1000T_DEFAULT_CAP_MASK;
++
++	/*
++	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
++	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
++	 * the  1000Base-T Control Register (Address 9).
++	 */
++	mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
++	mii_1000t_ctrl_reg &= ~MII_ATLX_CR_1000T_SPEED_MASK;
++
++	/*
++	 * Need to parse media_type  and set up
++	 * the appropriate PHY registers.
++	 */
++	switch (hw->media_type) {
++	case MEDIA_TYPE_AUTO_SENSOR:
++		mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
++					MII_AR_10T_FD_CAPS |
++					MII_AR_100TX_HD_CAPS |
++					MII_AR_100TX_FD_CAPS);
++		mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
++		break;
++
++	case MEDIA_TYPE_1000M_FULL:
++		mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
++		break;
++
++	case MEDIA_TYPE_100M_FULL:
++		mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
++		break;
++
++	case MEDIA_TYPE_100M_HALF:
++		mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
++		break;
++
++	case MEDIA_TYPE_10M_FULL:
++		mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
++		break;
++
++	default:
++		mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
++		break;
++	}
++
++	/* flow control fixed to enable all */
++	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
++
++	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
++	hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
++
++	ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
++	if (ret_val)
++		return ret_val;
++
++	ret_val = atl1_write_phy_reg(hw, MII_ATLX_CR, mii_1000t_ctrl_reg);
++	if (ret_val)
++		return ret_val;
++
++	return 0;
++}
++
++/*
++ * Configures link settings.
++ * hw - Struct containing variables accessed by shared code
++ * Assumes the hardware has previously been reset and the
++ * transmitter and receiver are not enabled.
++ */
++static s32 atl1_setup_link(struct atl1_hw *hw)
++{
++	struct pci_dev *pdev = hw->back->pdev;
++	struct atl1_adapter *adapter = hw->back;
++	s32 ret_val;
++
++	/*
++	 * Options:
++	 *  PHY will advertise value(s) parsed from
++	 *  autoneg_advertised and fc
++	 *  no matter what autoneg is , We will not wait link result.
++	 */
++	ret_val = atl1_phy_setup_autoneg_adv(hw);
++	if (ret_val) {
++		if (netif_msg_link(adapter))
++			dev_dbg(&pdev->dev,
++				"error setting up autonegotiation\n");
++		return ret_val;
++	}
++	/* SW.Reset , En-Auto-Neg if needed */
++	ret_val = atl1_phy_reset(hw);
++	if (ret_val) {
++		if (netif_msg_link(adapter))
++			dev_dbg(&pdev->dev, "error resetting phy\n");
++		return ret_val;
++	}
++	hw->phy_configured = true;
++	return ret_val;
++}
++
++static void atl1_init_flash_opcode(struct atl1_hw *hw)
++{
++	if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
++		/* Atmel */
++		hw->flash_vendor = 0;
++
++	/* Init OP table */
++	iowrite8(flash_table[hw->flash_vendor].cmd_program,
++		hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
++	iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
++		hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
++	iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
++		hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
++	iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
++		hw->hw_addr + REG_SPI_FLASH_OP_RDID);
++	iowrite8(flash_table[hw->flash_vendor].cmd_wren,
++		hw->hw_addr + REG_SPI_FLASH_OP_WREN);
++	iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
++		hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
++	iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
++		hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
++	iowrite8(flash_table[hw->flash_vendor].cmd_read,
++		hw->hw_addr + REG_SPI_FLASH_OP_READ);
++}
++
++/*
++ * Performs basic configuration of the adapter.
++ * hw - Struct containing variables accessed by shared code
++ * Assumes that the controller has previously been reset and is in a
++ * post-reset uninitialized state. Initializes multicast table,
++ * and  Calls routines to setup link
++ * Leaves the transmit and receive units disabled and uninitialized.
++ */
++static s32 atl1_init_hw(struct atl1_hw *hw)
++{
++	u32 ret_val = 0;
++
++	/* Zero out the Multicast HASH table */
++	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
++	/* clear the old settings from the multicast hash table */
++	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
++
++	atl1_init_flash_opcode(hw);
++
++	if (!hw->phy_configured) {
++		/* enable GPHY LinkChange Interrrupt */
++		ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
++		if (ret_val)
++			return ret_val;
++		/* make PHY out of power-saving state */
++		ret_val = atl1_phy_leave_power_saving(hw);
++		if (ret_val)
++			return ret_val;
++		/* Call a subroutine to configure the link */
++		ret_val = atl1_setup_link(hw);
++	}
++	return ret_val;
++}
++
++/*
++ * Detects the current speed and duplex settings of the hardware.
++ * hw - Struct containing variables accessed by shared code
++ * speed - Speed of the connection
++ * duplex - Duplex setting of the connection
++ */
++static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
++{
++	struct pci_dev *pdev = hw->back->pdev;
++	struct atl1_adapter *adapter = hw->back;
++	s32 ret_val;
++	u16 phy_data;
++
++	/* ; --- Read   PHY Specific Status Register (17) */
++	ret_val = atl1_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);
++	if (ret_val)
++		return ret_val;
++
++	if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
++		return ATLX_ERR_PHY_RES;
++
++	switch (phy_data & MII_ATLX_PSSR_SPEED) {
++	case MII_ATLX_PSSR_1000MBS:
++		*speed = SPEED_1000;
++		break;
++	case MII_ATLX_PSSR_100MBS:
++		*speed = SPEED_100;
++		break;
++	case MII_ATLX_PSSR_10MBS:
++		*speed = SPEED_10;
++		break;
++	default:
++		if (netif_msg_hw(adapter))
++			dev_dbg(&pdev->dev, "error getting speed\n");
++		return ATLX_ERR_PHY_SPEED;
++		break;
++	}
++	if (phy_data & MII_ATLX_PSSR_DPLX)
++		*duplex = FULL_DUPLEX;
++	else
++		*duplex = HALF_DUPLEX;
++
++	return 0;
++}
++
++void atl1_set_mac_addr(struct atl1_hw *hw)
++{
++	u32 value;
++	/*
++	 * 00-0B-6A-F6-00-DC
++	 * 0:  6AF600DC   1: 000B
++	 * low dword
++	 */
++	value = (((u32) hw->mac_addr[2]) << 24) |
++	    (((u32) hw->mac_addr[3]) << 16) |
++	    (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
++	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
++	/* high dword */
++	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
++	iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
++}
++
++/*
++ * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
++ * @adapter: board private structure to initialize
++ *
++ * atl1_sw_init initializes the Adapter private data structure.
++ * Fields are initialized based on PCI device information and
++ * OS network device settings (MTU size).
++ */
++static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
++{
++	struct atl1_hw *hw = &adapter->hw;
++	struct net_device *netdev = adapter->netdev;
++
++	hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
++	hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
++
++	adapter->wol = 0;
++	adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
++	adapter->ict = 50000;		/* 100ms */
++	adapter->link_speed = SPEED_0;	/* hardware init */
++	adapter->link_duplex = FULL_DUPLEX;
++
++	hw->phy_configured = false;
++	hw->preamble_len = 7;
++	hw->ipgt = 0x60;
++	hw->min_ifg = 0x50;
++	hw->ipgr1 = 0x40;
++	hw->ipgr2 = 0x60;
++	hw->max_retry = 0xf;
++	hw->lcol = 0x37;
++	hw->jam_ipg = 7;
++	hw->rfd_burst = 8;
++	hw->rrd_burst = 8;
++	hw->rfd_fetch_gap = 1;
++	hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
++	hw->rx_jumbo_lkah = 1;
++	hw->rrd_ret_timer = 16;
++	hw->tpd_burst = 4;
++	hw->tpd_fetch_th = 16;
++	hw->txf_burst = 0x100;
++	hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
++	hw->tpd_fetch_gap = 1;
++	hw->rcb_value = atl1_rcb_64;
++	hw->dma_ord = atl1_dma_ord_enh;
++	hw->dmar_block = atl1_dma_req_256;
++	hw->dmaw_block = atl1_dma_req_256;
++	hw->cmb_rrd = 4;
++	hw->cmb_tpd = 4;
++	hw->cmb_rx_timer = 1;	/* about 2us */
++	hw->cmb_tx_timer = 1;	/* about 2us */
++	hw->smb_timer = 100000;	/* about 200ms */
++
++	spin_lock_init(&adapter->lock);
++	spin_lock_init(&adapter->mb_lock);
++
++	return 0;
++}
++
++static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	u16 result;
++
++	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
++
++	return result;
++}
++
++static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
++	int val)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++
++	atl1_write_phy_reg(&adapter->hw, reg_num, val);
++}
++
++/*
++ * atl1_mii_ioctl -
++ * @netdev:
++ * @ifreq:
++ * @cmd:
++ */
++static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	unsigned long flags;
++	int retval;
++
++	if (!netif_running(netdev))
++		return -EINVAL;
++
++	spin_lock_irqsave(&adapter->lock, flags);
++	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
++	spin_unlock_irqrestore(&adapter->lock, flags);
++
++	return retval;
++}
++
++/*
++ * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
++ * @adapter: board private structure
++ *
++ * Return 0 on success, negative on failure
++ */
++static s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
++{
++	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++	struct atl1_ring_header *ring_header = &adapter->ring_header;
++	struct pci_dev *pdev = adapter->pdev;
++	int size;
++	u8 offset = 0;
++
++	size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
++	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
++	if (unlikely(!tpd_ring->buffer_info)) {
++		if (netif_msg_drv(adapter))
++			dev_err(&pdev->dev, "kzalloc failed , size = D%d\n",
++				size);
++		goto err_nomem;
++	}
++	rfd_ring->buffer_info =
++		(struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
++
++	/*
++	 * real ring DMA buffer
++	 * each ring/block may need up to 8 bytes for alignment, hence the
++	 * additional 40 bytes tacked onto the end.
++	 */
++	ring_header->size = size =
++		sizeof(struct tx_packet_desc) * tpd_ring->count
++		+ sizeof(struct rx_free_desc) * rfd_ring->count
++		+ sizeof(struct rx_return_desc) * rrd_ring->count
++		+ sizeof(struct coals_msg_block)
++		+ sizeof(struct stats_msg_block)
++		+ 40;
++
++	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
++		&ring_header->dma);
++	if (unlikely(!ring_header->desc)) {
++		if (netif_msg_drv(adapter))
++			dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
++		goto err_nomem;
++	}
++
++	memset(ring_header->desc, 0, ring_header->size);
++
++	/* init TPD ring */
++	tpd_ring->dma = ring_header->dma;
++	offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
++	tpd_ring->dma += offset;
++	tpd_ring->desc = (u8 *) ring_header->desc + offset;
++	tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
++
++	/* init RFD ring */
++	rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
++	offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
++	rfd_ring->dma += offset;
++	rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
++	rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
++
++
++	/* init RRD ring */
++	rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
++	offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
++	rrd_ring->dma += offset;
++	rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
++	rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
++
++
++	/* init CMB */
++	adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
++	offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
++	adapter->cmb.dma += offset;
++	adapter->cmb.cmb = (struct coals_msg_block *)
++		((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
++
++	/* init SMB */
++	adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
++	offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
++	adapter->smb.dma += offset;
++	adapter->smb.smb = (struct stats_msg_block *)
++		((u8 *) adapter->cmb.cmb +
++		(sizeof(struct coals_msg_block) + offset));
++
++	return 0;
++
++err_nomem:
++	kfree(tpd_ring->buffer_info);
++	return -ENOMEM;
++}
++
++static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
++{
++	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++
++	atomic_set(&tpd_ring->next_to_use, 0);
++	atomic_set(&tpd_ring->next_to_clean, 0);
++
++	rfd_ring->next_to_clean = 0;
++	atomic_set(&rfd_ring->next_to_use, 0);
++
++	rrd_ring->next_to_use = 0;
++	atomic_set(&rrd_ring->next_to_clean, 0);
++}
++
++/*
++ * atl1_clean_rx_ring - Free RFD Buffers
++ * @adapter: board private structure
++ */
++static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
++{
++	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++	struct atl1_buffer *buffer_info;
++	struct pci_dev *pdev = adapter->pdev;
++	unsigned long size;
++	unsigned int i;
++
++	/* Free all the Rx ring sk_buffs */
++	for (i = 0; i < rfd_ring->count; i++) {
++		buffer_info = &rfd_ring->buffer_info[i];
++		if (buffer_info->dma) {
++			pci_unmap_page(pdev, buffer_info->dma,
++				buffer_info->length, PCI_DMA_FROMDEVICE);
++			buffer_info->dma = 0;
++		}
++		if (buffer_info->skb) {
++			dev_kfree_skb(buffer_info->skb);
++			buffer_info->skb = NULL;
++		}
++	}
++
++	size = sizeof(struct atl1_buffer) * rfd_ring->count;
++	memset(rfd_ring->buffer_info, 0, size);
++
++	/* Zero out the descriptor ring */
++	memset(rfd_ring->desc, 0, rfd_ring->size);
++
++	rfd_ring->next_to_clean = 0;
++	atomic_set(&rfd_ring->next_to_use, 0);
++
++	rrd_ring->next_to_use = 0;
++	atomic_set(&rrd_ring->next_to_clean, 0);
++}
++
++/*
++ * atl1_clean_tx_ring - Free Tx Buffers
++ * @adapter: board private structure
++ */
++static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
++{
++	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++	struct atl1_buffer *buffer_info;
++	struct pci_dev *pdev = adapter->pdev;
++	unsigned long size;
++	unsigned int i;
++
++	/* Free all the Tx ring sk_buffs */
++	for (i = 0; i < tpd_ring->count; i++) {
++		buffer_info = &tpd_ring->buffer_info[i];
++		if (buffer_info->dma) {
++			pci_unmap_page(pdev, buffer_info->dma,
++				buffer_info->length, PCI_DMA_TODEVICE);
++			buffer_info->dma = 0;
++		}
++	}
++
++	for (i = 0; i < tpd_ring->count; i++) {
++		buffer_info = &tpd_ring->buffer_info[i];
++		if (buffer_info->skb) {
++			dev_kfree_skb_any(buffer_info->skb);
++			buffer_info->skb = NULL;
++		}
++	}
++
++	size = sizeof(struct atl1_buffer) * tpd_ring->count;
++	memset(tpd_ring->buffer_info, 0, size);
++
++	/* Zero out the descriptor ring */
++	memset(tpd_ring->desc, 0, tpd_ring->size);
++
++	atomic_set(&tpd_ring->next_to_use, 0);
++	atomic_set(&tpd_ring->next_to_clean, 0);
++}
++
++/*
++ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
++ * @adapter: board private structure
++ *
++ * Free all transmit software resources
++ */
++static void atl1_free_ring_resources(struct atl1_adapter *adapter)
++{
++	struct pci_dev *pdev = adapter->pdev;
++	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++	struct atl1_ring_header *ring_header = &adapter->ring_header;
++
++	atl1_clean_tx_ring(adapter);
++	atl1_clean_rx_ring(adapter);
++
++	kfree(tpd_ring->buffer_info);
++	pci_free_consistent(pdev, ring_header->size, ring_header->desc,
++		ring_header->dma);
++
++	tpd_ring->buffer_info = NULL;
++	tpd_ring->desc = NULL;
++	tpd_ring->dma = 0;
++
++	rfd_ring->buffer_info = NULL;
++	rfd_ring->desc = NULL;
++	rfd_ring->dma = 0;
++
++	rrd_ring->desc = NULL;
++	rrd_ring->dma = 0;
++}
++
++static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
++{
++	u32 value;
++	struct atl1_hw *hw = &adapter->hw;
++	struct net_device *netdev = adapter->netdev;
++	/* Config MAC CTRL Register */
++	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
++	/* duplex */
++	if (FULL_DUPLEX == adapter->link_duplex)
++		value |= MAC_CTRL_DUPLX;
++	/* speed */
++	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
++			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
++		  MAC_CTRL_SPEED_SHIFT);
++	/* flow control */
++	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
++	/* PAD & CRC */
++	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
++	/* preamble length */
++	value |= (((u32) adapter->hw.preamble_len
++		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
++	/* vlan */
++	if (adapter->vlgrp)
++		value |= MAC_CTRL_RMV_VLAN;
++	/* rx checksum
++	   if (adapter->rx_csum)
++	   value |= MAC_CTRL_RX_CHKSUM_EN;
++	 */
++	/* filter mode */
++	value |= MAC_CTRL_BC_EN;
++	if (netdev->flags & IFF_PROMISC)
++		value |= MAC_CTRL_PROMIS_EN;
++	else if (netdev->flags & IFF_ALLMULTI)
++		value |= MAC_CTRL_MC_ALL_EN;
++	/* value |= MAC_CTRL_LOOPBACK; */
++	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
++}
++
++static u32 atl1_check_link(struct atl1_adapter *adapter)
++{
++	struct atl1_hw *hw = &adapter->hw;
++	struct net_device *netdev = adapter->netdev;
++	u32 ret_val;
++	u16 speed, duplex, phy_data;
++	int reconfig = 0;
++
++	/* MII_BMSR must read twice */
++	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
++	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
++	if (!(phy_data & BMSR_LSTATUS)) {
++		/* link down */
++		if (netif_carrier_ok(netdev)) {
++			/* old link state: Up */
++			if (netif_msg_link(adapter))
++				dev_info(&adapter->pdev->dev, "link is down\n");
++			adapter->link_speed = SPEED_0;
++			netif_carrier_off(netdev);
++			netif_stop_queue(netdev);
++		}
++		return 0;
++	}
++
++	/* Link Up */
++	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
++	if (ret_val)
++		return ret_val;
++
++	switch (hw->media_type) {
++	case MEDIA_TYPE_1000M_FULL:
++		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
++			reconfig = 1;
++		break;
++	case MEDIA_TYPE_100M_FULL:
++		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
++			reconfig = 1;
++		break;
++	case MEDIA_TYPE_100M_HALF:
++		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
++			reconfig = 1;
++		break;
++	case MEDIA_TYPE_10M_FULL:
++		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
++			reconfig = 1;
++		break;
++	case MEDIA_TYPE_10M_HALF:
++		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
++			reconfig = 1;
++		break;
++	}
++
++	/* link result is our setting */
++	if (!reconfig) {
++		if (adapter->link_speed != speed
++		    || adapter->link_duplex != duplex) {
++			adapter->link_speed = speed;
++			adapter->link_duplex = duplex;
++			atl1_setup_mac_ctrl(adapter);
++			if (netif_msg_link(adapter))
++				dev_info(&adapter->pdev->dev,
++					"%s link is up %d Mbps %s\n",
++					netdev->name, adapter->link_speed,
++					adapter->link_duplex == FULL_DUPLEX ?
++					"full duplex" : "half duplex");
++		}
++		if (!netif_carrier_ok(netdev)) {
++			/* Link down -> Up */
++			netif_carrier_on(netdev);
++			netif_wake_queue(netdev);
++		}
++		return 0;
++	}
++
++	/* change original link status */
++	if (netif_carrier_ok(netdev)) {
++		adapter->link_speed = SPEED_0;
++		netif_carrier_off(netdev);
++		netif_stop_queue(netdev);
++	}
++
++	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
++	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
++		switch (hw->media_type) {
++		case MEDIA_TYPE_100M_FULL:
++			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
++			           MII_CR_RESET;
++			break;
++		case MEDIA_TYPE_100M_HALF:
++			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++			break;
++		case MEDIA_TYPE_10M_FULL:
++			phy_data =
++			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
++			break;
++		default:
++			/* MEDIA_TYPE_10M_HALF: */
++			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++			break;
++		}
++		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++		return 0;
++	}
++
++	/* auto-neg, insert timer to re-config phy */
++	if (!adapter->phy_timer_pending) {
++		adapter->phy_timer_pending = true;
++		mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
++	}
++
++	return 0;
++}
++
++static void set_flow_ctrl_old(struct atl1_adapter *adapter)
++{
++	u32 hi, lo, value;
++
++	/* RFD Flow Control */
++	value = adapter->rfd_ring.count;
++	hi = value / 16;
++	if (hi < 2)
++		hi = 2;
++	lo = value * 7 / 8;
++
++	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
++		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
++	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
++
++	/* RRD Flow Control */
++	value = adapter->rrd_ring.count;
++	lo = value / 16;
++	hi = value * 7 / 8;
++	if (lo < 2)
++		lo = 2;
++	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
++		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
++	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
++}
++
++static void set_flow_ctrl_new(struct atl1_hw *hw)
++{
++	u32 hi, lo, value;
++
++	/* RXF Flow Control */
++	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
++	lo = value / 16;
++	if (lo < 192)
++		lo = 192;
++	hi = value * 7 / 8;
++	if (hi < lo)
++		hi = lo + 16;
++	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
++		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
++	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
++
++	/* RRD Flow Control */
++	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
++	lo = value / 8;
++	hi = value * 7 / 8;
++	if (lo < 2)
++		lo = 2;
++	if (hi < lo)
++		hi = lo + 3;
++	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
++		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
++	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
++}
++
++/*
++ * atl1_configure - Configure Transmit&Receive Unit after Reset
++ * @adapter: board private structure
++ *
++ * Configure the Tx /Rx unit of the MAC after a reset.
++ */
++static u32 atl1_configure(struct atl1_adapter *adapter)
++{
++	struct atl1_hw *hw = &adapter->hw;
++	u32 value;
++
++	/* clear interrupt status */
++	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
++
++	/* set MAC Address */
++	value = (((u32) hw->mac_addr[2]) << 24) |
++		(((u32) hw->mac_addr[3]) << 16) |
++		(((u32) hw->mac_addr[4]) << 8) |
++		(((u32) hw->mac_addr[5]));
++	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
++	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
++	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
++
++	/* tx / rx ring */
++
++	/* HI base address */
++	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
++		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
++	/* LO base address */
++	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
++		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
++	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
++		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
++	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
++		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
++	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
++		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
++	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
++		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
++
++	/* element count */
++	value = adapter->rrd_ring.count;
++	value <<= 16;
++	value += adapter->rfd_ring.count;
++	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
++	iowrite32(adapter->tpd_ring.count, hw->hw_addr +
++		REG_DESC_TPD_RING_SIZE);
++
++	/* Load Ptr */
++	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
++
++	/* config Mailbox */
++	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
++		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
++		((atomic_read(&adapter->rrd_ring.next_to_clean)
++		& MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
++		((atomic_read(&adapter->rfd_ring.next_to_use)
++		& MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
++	iowrite32(value, hw->hw_addr + REG_MAILBOX);
++
++	/* config IPG/IFG */
++	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
++		 << MAC_IPG_IFG_IPGT_SHIFT) |
++		(((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
++		<< MAC_IPG_IFG_MIFG_SHIFT) |
++		(((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
++		<< MAC_IPG_IFG_IPGR1_SHIFT) |
++		(((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
++		<< MAC_IPG_IFG_IPGR2_SHIFT);
++	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
++
++	/* config  Half-Duplex Control */
++	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
++		(((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
++		<< MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
++		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
++		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
++		(((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
++		<< MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
++	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
++
++	/* set Interrupt Moderator Timer */
++	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
++	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
++
++	/* set Interrupt Clear Timer */
++	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
++
++	/* set max frame size hw will accept */
++	iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
++
++	/* jumbo size & rrd retirement timer */
++	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
++		 << RXQ_JMBOSZ_TH_SHIFT) |
++		(((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
++		<< RXQ_JMBO_LKAH_SHIFT) |
++		(((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
++		<< RXQ_RRD_TIMER_SHIFT);
++	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
++
++	/* Flow Control */
++	switch (hw->dev_rev) {
++	case 0x8001:
++	case 0x9001:
++	case 0x9002:
++	case 0x9003:
++		set_flow_ctrl_old(adapter);
++		break;
++	default:
++		set_flow_ctrl_new(hw);
++		break;
++	}
++
++	/* config TXQ */
++	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
++		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
++		(((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
++		<< TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
++		(((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
++		<< TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
++		TXQ_CTRL_EN;
++	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
++
++	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
++	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
++		<< TX_JUMBO_TASK_TH_SHIFT) |
++		(((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
++		<< TX_TPD_MIN_IPG_SHIFT);
++	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
++
++	/* config RXQ */
++	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
++		<< RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
++		(((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
++		<< RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
++		(((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
++		<< RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
++		RXQ_CTRL_EN;
++	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
++
++	/* config DMA Engine */
++	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
++		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
++		((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
++		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
++		DMA_CTRL_DMAW_EN;
++	value |= (u32) hw->dma_ord;
++	if (atl1_rcb_128 == hw->rcb_value)
++		value |= DMA_CTRL_RCB_VALUE;
++	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
++
++	/* config CMB / SMB */
++	value = (hw->cmb_tpd > adapter->tpd_ring.count) ?
++		hw->cmb_tpd : adapter->tpd_ring.count;
++	value <<= 16;
++	value |= hw->cmb_rrd;
++	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
++	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
++	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
++	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
++
++	/* --- enable CMB / SMB */
++	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
++	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
++
++	value = ioread32(adapter->hw.hw_addr + REG_ISR);
++	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
++		value = 1;	/* config failed */
++	else
++		value = 0;
++
++	/* clear all interrupt status */
++	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
++	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
++	return value;
++}
++
++/*
++ * atl1_pcie_patch - Patch for PCIE module
++ */
++static void atl1_pcie_patch(struct atl1_adapter *adapter)
++{
++	u32 value;
++
++	/* much vendor magic here */
++	value = 0x6500;
++	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
++	/* pcie flow control mode change */
++	value = ioread32(adapter->hw.hw_addr + 0x1008);
++	value |= 0x8000;
++	iowrite32(value, adapter->hw.hw_addr + 0x1008);
++}
++
++/*
++ * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
++ * on PCI Command register is disable.
++ * The function enable this bit.
++ * Brackett, 2006/03/15
++ */
++static void atl1_via_workaround(struct atl1_adapter *adapter)
++{
++	unsigned long value;
++
++	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
++	if (value & PCI_COMMAND_INTX_DISABLE)
++		value &= ~PCI_COMMAND_INTX_DISABLE;
++	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
++}
++
++static void atl1_inc_smb(struct atl1_adapter *adapter)
++{
++	struct stats_msg_block *smb = adapter->smb.smb;
++
++	/* Fill out the OS statistics structure */
++	adapter->soft_stats.rx_packets += smb->rx_ok;
++	adapter->soft_stats.tx_packets += smb->tx_ok;
++	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
++	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
++	adapter->soft_stats.multicast += smb->rx_mcast;
++	adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
++		smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
++
++	/* Rx Errors */
++	adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
++		smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
++		smb->rx_rrd_ov + smb->rx_align_err);
++	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
++	adapter->soft_stats.rx_length_errors += smb->rx_len_err;
++	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
++	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
++	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
++		smb->rx_rxf_ov);
++
++	adapter->soft_stats.rx_pause += smb->rx_pause;
++	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
++	adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
++
++	/* Tx Errors */
++	adapter->soft_stats.tx_errors += (smb->tx_late_col +
++		smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
++	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
++	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
++	adapter->soft_stats.tx_window_errors += smb->tx_late_col;
++
++	adapter->soft_stats.excecol += smb->tx_abort_col;
++	adapter->soft_stats.deffer += smb->tx_defer;
++	adapter->soft_stats.scc += smb->tx_1_col;
++	adapter->soft_stats.mcc += smb->tx_2_col;
++	adapter->soft_stats.latecol += smb->tx_late_col;
++	adapter->soft_stats.tx_underun += smb->tx_underrun;
++	adapter->soft_stats.tx_trunc += smb->tx_trunc;
++	adapter->soft_stats.tx_pause += smb->tx_pause;
++
++	adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
++	adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
++	adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
++	adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
++	adapter->net_stats.multicast = adapter->soft_stats.multicast;
++	adapter->net_stats.collisions = adapter->soft_stats.collisions;
++	adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
++	adapter->net_stats.rx_over_errors =
++		adapter->soft_stats.rx_missed_errors;
++	adapter->net_stats.rx_length_errors =
++		adapter->soft_stats.rx_length_errors;
++	adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
++	adapter->net_stats.rx_frame_errors =
++		adapter->soft_stats.rx_frame_errors;
++	adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
++	adapter->net_stats.rx_missed_errors =
++		adapter->soft_stats.rx_missed_errors;
++	adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
++	adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
++	adapter->net_stats.tx_aborted_errors =
++		adapter->soft_stats.tx_aborted_errors;
++	adapter->net_stats.tx_window_errors =
++		adapter->soft_stats.tx_window_errors;
++	adapter->net_stats.tx_carrier_errors =
++		adapter->soft_stats.tx_carrier_errors;
++}
++
++static void atl1_update_mailbox(struct atl1_adapter *adapter)
++{
++	unsigned long flags;
++	u32 tpd_next_to_use;
++	u32 rfd_next_to_use;
++	u32 rrd_next_to_clean;
++	u32 value;
++
++	spin_lock_irqsave(&adapter->mb_lock, flags);
++
++	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
++	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
++	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
++
++	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
++		MB_RFD_PROD_INDX_SHIFT) |
++		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
++		MB_RRD_CONS_INDX_SHIFT) |
++		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
++		MB_TPD_PROD_INDX_SHIFT);
++	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
++
++	spin_unlock_irqrestore(&adapter->mb_lock, flags);
++}
++
++static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
++	struct rx_return_desc *rrd, u16 offset)
++{
++	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++
++	while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
++		rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
++		if (++rfd_ring->next_to_clean == rfd_ring->count) {
++			rfd_ring->next_to_clean = 0;
++		}
++	}
++}
++
++static void atl1_update_rfd_index(struct atl1_adapter *adapter,
++	struct rx_return_desc *rrd)
++{
++	u16 num_buf;
++
++	num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
++		adapter->rx_buffer_len;
++	if (rrd->num_buf == num_buf)
++		/* clean alloc flag for bad rrd */
++		atl1_clean_alloc_flag(adapter, rrd, num_buf);
++}
++
++static void atl1_rx_checksum(struct atl1_adapter *adapter,
++	struct rx_return_desc *rrd, struct sk_buff *skb)
++{
++	struct pci_dev *pdev = adapter->pdev;
++
++	skb->ip_summed = CHECKSUM_NONE;
++
++	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
++		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
++					ERR_FLAG_CODE | ERR_FLAG_OV)) {
++			adapter->hw_csum_err++;
++			if (netif_msg_rx_err(adapter))
++				dev_printk(KERN_DEBUG, &pdev->dev,
++					"rx checksum error\n");
++			return;
++		}
++	}
++
++	/* not IPv4 */
++	if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
++		/* checksum is invalid, but it's not an IPv4 pkt, so ok */
++		return;
++
++	/* IPv4 packet */
++	if (likely(!(rrd->err_flg &
++		(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
++		skb->ip_summed = CHECKSUM_UNNECESSARY;
++		adapter->hw_csum_good++;
++		return;
++	}
++
++	/* IPv4, but hardware thinks its checksum is wrong */
++	if (netif_msg_rx_err(adapter))
++		dev_printk(KERN_DEBUG, &pdev->dev,
++			"hw csum wrong, pkt_flag:%x, err_flag:%x\n",
++			rrd->pkt_flg, rrd->err_flg);
++	skb->ip_summed = CHECKSUM_COMPLETE;
++	skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
++	adapter->hw_csum_err++;
++	return;
++}
++
++/*
++ * atl1_alloc_rx_buffers - Replace used receive buffers
++ * @adapter: address of board private structure
++ */
++static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
++{
++	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++	struct pci_dev *pdev = adapter->pdev;
++	struct page *page;
++	unsigned long offset;
++	struct atl1_buffer *buffer_info, *next_info;
++	struct sk_buff *skb;
++	u16 num_alloc = 0;
++	u16 rfd_next_to_use, next_next;
++	struct rx_free_desc *rfd_desc;
++
++	next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
++	if (++next_next == rfd_ring->count)
++		next_next = 0;
++	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
++	next_info = &rfd_ring->buffer_info[next_next];
++
++	while (!buffer_info->alloced && !next_info->alloced) {
++		if (buffer_info->skb) {
++			buffer_info->alloced = 1;
++			goto next;
++		}
++
++		rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
++
++		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
++		if (unlikely(!skb)) {
++			/* Better luck next round */
++			adapter->net_stats.rx_dropped++;
++			break;
++		}
++
++		/*
++		 * Make buffer alignment 2 beyond a 16 byte boundary
++		 * this will result in a 16 byte aligned IP header after
++		 * the 14 byte MAC header is removed
++		 */
++		skb_reserve(skb, NET_IP_ALIGN);
++
++		buffer_info->alloced = 1;
++		buffer_info->skb = skb;
++		buffer_info->length = (u16) adapter->rx_buffer_len;
++		page = virt_to_page(skb->data);
++		offset = (unsigned long)skb->data & ~PAGE_MASK;
++		buffer_info->dma = pci_map_page(pdev, page, offset,
++						adapter->rx_buffer_len,
++						PCI_DMA_FROMDEVICE);
++		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
++		rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
++		rfd_desc->coalese = 0;
++
++next:
++		rfd_next_to_use = next_next;
++		if (unlikely(++next_next == rfd_ring->count))
++			next_next = 0;
++
++		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
++		next_info = &rfd_ring->buffer_info[next_next];
++		num_alloc++;
++	}
++
++	if (num_alloc) {
++		/*
++		 * Force memory writes to complete before letting h/w
++		 * know there are new descriptors to fetch.  (Only
++		 * applicable for weak-ordered memory model archs,
++		 * such as IA-64).
++		 */
++		wmb();
++		atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
++	}
++	return num_alloc;
++}
++
++static void atl1_intr_rx(struct atl1_adapter *adapter)
++{
++	int i, count;
++	u16 length;
++	u16 rrd_next_to_clean;
++	u32 value;
++	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++	struct atl1_buffer *buffer_info;
++	struct rx_return_desc *rrd;
++	struct sk_buff *skb;
++
++	count = 0;
++
++	rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
++
++	while (1) {
++		rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
++		i = 1;
++		if (likely(rrd->xsz.valid)) {	/* packet valid */
++chk_rrd:
++			/* check rrd status */
++			if (likely(rrd->num_buf == 1))
++				goto rrd_ok;
++			else if (netif_msg_rx_err(adapter)) {
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"unexpected RRD buffer count\n");
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"rx_buf_len = %d\n",
++					adapter->rx_buffer_len);
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"RRD num_buf = %d\n",
++					rrd->num_buf);
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"RRD pkt_len = %d\n",
++					rrd->xsz.xsum_sz.pkt_size);
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"RRD pkt_flg = 0x%08X\n",
++					rrd->pkt_flg);
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"RRD err_flg = 0x%08X\n",
++					rrd->err_flg);
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"RRD vlan_tag = 0x%08X\n",
++					rrd->vlan_tag);
++			}
++
++			/* rrd seems to be bad */
++			if (unlikely(i-- > 0)) {
++				/* rrd may not be DMAed completely */
++				udelay(1);
++				goto chk_rrd;
++			}
++			/* bad rrd */
++			if (netif_msg_rx_err(adapter))
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"bad RRD\n");
++			/* see if update RFD index */
++			if (rrd->num_buf > 1)
++				atl1_update_rfd_index(adapter, rrd);
++
++			/* update rrd */
++			rrd->xsz.valid = 0;
++			if (++rrd_next_to_clean == rrd_ring->count)
++				rrd_next_to_clean = 0;
++			count++;
++			continue;
++		} else {	/* current rrd still not be updated */
++
++			break;
++		}
++rrd_ok:
++		/* clean alloc flag for bad rrd */
++		atl1_clean_alloc_flag(adapter, rrd, 0);
++
++		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
++		if (++rfd_ring->next_to_clean == rfd_ring->count)
++			rfd_ring->next_to_clean = 0;
++
++		/* update rrd next to clean */
++		if (++rrd_next_to_clean == rrd_ring->count)
++			rrd_next_to_clean = 0;
++		count++;
++
++		if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
++			if (!(rrd->err_flg &
++				(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
++				| ERR_FLAG_LEN))) {
++				/* packet error, don't need upstream */
++				buffer_info->alloced = 0;
++				rrd->xsz.valid = 0;
++				continue;
++			}
++		}
++
++		/* Good Receive */
++		pci_unmap_page(adapter->pdev, buffer_info->dma,
++			       buffer_info->length, PCI_DMA_FROMDEVICE);
++		skb = buffer_info->skb;
++		length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
++
++		skb_put(skb, length - ETH_FCS_LEN);
++
++		/* Receive Checksum Offload */
++		atl1_rx_checksum(adapter, rrd, skb);
++		skb->protocol = eth_type_trans(skb, adapter->netdev);
++
++		if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
++			u16 vlan_tag = (rrd->vlan_tag >> 4) |
++					((rrd->vlan_tag & 7) << 13) |
++					((rrd->vlan_tag & 8) << 9);
++			vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
++		} else
++			netif_rx(skb);
++
++		/* let protocol layer free skb */
++		buffer_info->skb = NULL;
++		buffer_info->alloced = 0;
++		rrd->xsz.valid = 0;
++
++		adapter->netdev->last_rx = jiffies;
++	}
++
++	atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
++
++	atl1_alloc_rx_buffers(adapter);
++
++	/* update mailbox ? */
++	if (count) {
++		u32 tpd_next_to_use;
++		u32 rfd_next_to_use;
++
++		spin_lock(&adapter->mb_lock);
++
++		tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
++		rfd_next_to_use =
++		    atomic_read(&adapter->rfd_ring.next_to_use);
++		rrd_next_to_clean =
++		    atomic_read(&adapter->rrd_ring.next_to_clean);
++		value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
++			MB_RFD_PROD_INDX_SHIFT) |
++                        ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
++			MB_RRD_CONS_INDX_SHIFT) |
++                        ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
++			MB_TPD_PROD_INDX_SHIFT);
++		iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
++		spin_unlock(&adapter->mb_lock);
++	}
++}
++
++static void atl1_intr_tx(struct atl1_adapter *adapter)
++{
++	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++	struct atl1_buffer *buffer_info;
++	u16 sw_tpd_next_to_clean;
++	u16 cmb_tpd_next_to_clean;
++
++	sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
++	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
++
++	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
++		struct tx_packet_desc *tpd;
++
++		tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
++		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
++		if (buffer_info->dma) {
++			pci_unmap_page(adapter->pdev, buffer_info->dma,
++				       buffer_info->length, PCI_DMA_TODEVICE);
++			buffer_info->dma = 0;
++		}
++
++		if (buffer_info->skb) {
++			dev_kfree_skb_irq(buffer_info->skb);
++			buffer_info->skb = NULL;
++		}
++
++		if (++sw_tpd_next_to_clean == tpd_ring->count)
++			sw_tpd_next_to_clean = 0;
++	}
++	atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
++
++	if (netif_queue_stopped(adapter->netdev)
++	    && netif_carrier_ok(adapter->netdev))
++		netif_wake_queue(adapter->netdev);
++}
++
++static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
++{
++	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) ?
++		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,
++	struct tx_packet_desc *ptpd)
++{
++	/* spinlock held */
++	u8 hdr_len, ip_off;
++	u32 real_len;
++	int err;
++
++	if (skb_shinfo(skb)->gso_size) {
++		if (skb_header_cloned(skb)) {
++			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
++			if (unlikely(err))
++				return -1;
++		}
++
++		if (skb->protocol == ntohs(ETH_P_IP)) {
++			struct iphdr *iph = ip_hdr(skb);
++
++			real_len = (((unsigned char *)iph - skb->data) +
++				ntohs(iph->tot_len));
++			if (real_len < skb->len)
++				pskb_trim(skb, real_len);
++			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
++			if (skb->len == hdr_len) {
++				iph->check = 0;
++				tcp_hdr(skb)->check =
++					~csum_tcpudp_magic(iph->saddr,
++					iph->daddr, tcp_hdrlen(skb),
++					IPPROTO_TCP, 0);
++				ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
++					TPD_IPHL_SHIFT;
++				ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
++					TPD_TCPHDRLEN_MASK) <<
++					TPD_TCPHDRLEN_SHIFT;
++				ptpd->word3 |= 1 << TPD_IP_CSUM_SHIFT;
++				ptpd->word3 |= 1 << TPD_TCP_CSUM_SHIFT;
++				return 1;
++			}
++
++			iph->check = 0;
++			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
++					iph->daddr, 0, IPPROTO_TCP, 0);
++			ip_off = (unsigned char *)iph -
++				(unsigned char *) skb_network_header(skb);
++			if (ip_off == 8) /* 802.3-SNAP frame */
++				ptpd->word3 |= 1 << TPD_ETHTYPE_SHIFT;
++			else if (ip_off != 0)
++				return -2;
++
++			ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
++				TPD_IPHL_SHIFT;
++			ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
++				TPD_TCPHDRLEN_MASK) << TPD_TCPHDRLEN_SHIFT;
++			ptpd->word3 |= (skb_shinfo(skb)->gso_size &
++				TPD_MSS_MASK) << TPD_MSS_SHIFT;
++			ptpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
++			return 3;
++		}
++	}
++	return false;
++}
++
++static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
++	struct tx_packet_desc *ptpd)
++{
++	u8 css, cso;
++
++	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
++		css = (u8) (skb->csum_start - skb_headroom(skb));
++		cso = css + (u8) skb->csum_offset;
++		if (unlikely(css & 0x1)) {
++			/* L1 hardware requires an even number here */
++			if (netif_msg_tx_err(adapter))
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"payload offset not an even number\n");
++			return -1;
++		}
++		ptpd->word3 |= (css & TPD_PLOADOFFSET_MASK) <<
++			TPD_PLOADOFFSET_SHIFT;
++		ptpd->word3 |= (cso & TPD_CCSUMOFFSET_MASK) <<
++			TPD_CCSUMOFFSET_SHIFT;
++		ptpd->word3 |= 1 << TPD_CUST_CSUM_EN_SHIFT;
++		return true;
++	}
++	return 0;
++}
++
++static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
++	struct tx_packet_desc *ptpd)
++{
++	/* spinlock held */
++	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++	struct atl1_buffer *buffer_info;
++	u16 buf_len = skb->len;
++	struct page *page;
++	unsigned long offset;
++	unsigned int nr_frags;
++	unsigned int f;
++	int retval;
++	u16 next_to_use;
++	u16 data_len;
++	u8 hdr_len;
++
++	buf_len -= skb->data_len;
++	nr_frags = skb_shinfo(skb)->nr_frags;
++	next_to_use = atomic_read(&tpd_ring->next_to_use);
++	buffer_info = &tpd_ring->buffer_info[next_to_use];
++	if (unlikely(buffer_info->skb))
++		BUG();
++	/* put skb in last TPD */
++	buffer_info->skb = NULL;
++
++	retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
++	if (retval) {
++		/* TSO */
++		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
++		buffer_info->length = hdr_len;
++		page = virt_to_page(skb->data);
++		offset = (unsigned long)skb->data & ~PAGE_MASK;
++		buffer_info->dma = pci_map_page(adapter->pdev, page,
++						offset, hdr_len,
++						PCI_DMA_TODEVICE);
++
++		if (++next_to_use == tpd_ring->count)
++			next_to_use = 0;
++
++		if (buf_len > hdr_len) {
++			int i, nseg;
++
++			data_len = buf_len - hdr_len;
++			nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) /
++				ATL1_MAX_TX_BUF_LEN;
++			for (i = 0; i < nseg; i++) {
++				buffer_info =
++				    &tpd_ring->buffer_info[next_to_use];
++				buffer_info->skb = NULL;
++				buffer_info->length =
++				    (ATL1_MAX_TX_BUF_LEN >=
++				     data_len) ? ATL1_MAX_TX_BUF_LEN : data_len;
++				data_len -= buffer_info->length;
++				page = virt_to_page(skb->data +
++					(hdr_len + i * ATL1_MAX_TX_BUF_LEN));
++				offset = (unsigned long)(skb->data +
++					(hdr_len + i * ATL1_MAX_TX_BUF_LEN)) &
++					~PAGE_MASK;
++				buffer_info->dma = pci_map_page(adapter->pdev,
++					page, offset, buffer_info->length,
++					PCI_DMA_TODEVICE);
++				if (++next_to_use == tpd_ring->count)
++					next_to_use = 0;
++			}
++		}
++	} else {
++		/* not TSO */
++		buffer_info->length = buf_len;
++		page = virt_to_page(skb->data);
++		offset = (unsigned long)skb->data & ~PAGE_MASK;
++		buffer_info->dma = pci_map_page(adapter->pdev, page,
++			offset, buf_len, PCI_DMA_TODEVICE);
++		if (++next_to_use == tpd_ring->count)
++			next_to_use = 0;
++	}
++
++	for (f = 0; f < nr_frags; f++) {
++		struct skb_frag_struct *frag;
++		u16 i, nseg;
++
++		frag = &skb_shinfo(skb)->frags[f];
++		buf_len = frag->size;
++
++		nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
++			ATL1_MAX_TX_BUF_LEN;
++		for (i = 0; i < nseg; i++) {
++			buffer_info = &tpd_ring->buffer_info[next_to_use];
++			if (unlikely(buffer_info->skb))
++				BUG();
++			buffer_info->skb = NULL;
++			buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
++				ATL1_MAX_TX_BUF_LEN : buf_len;
++			buf_len -= buffer_info->length;
++			buffer_info->dma = pci_map_page(adapter->pdev,
++				frag->page,
++				frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
++				buffer_info->length, PCI_DMA_TODEVICE);
++
++			if (++next_to_use == tpd_ring->count)
++				next_to_use = 0;
++		}
++	}
++
++	/* last tpd's buffer-info */
++	buffer_info->skb = skb;
++}
++
++static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
++       struct tx_packet_desc *ptpd)
++{
++	/* spinlock held */
++	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++	struct atl1_buffer *buffer_info;
++	struct tx_packet_desc *tpd;
++	u16 j;
++	u32 val;
++	u16 next_to_use = (u16) atomic_read(&tpd_ring->next_to_use);
++
++	for (j = 0; j < count; j++) {
++		buffer_info = &tpd_ring->buffer_info[next_to_use];
++		tpd = ATL1_TPD_DESC(&adapter->tpd_ring, next_to_use);
++		if (tpd != ptpd)
++			memcpy(tpd, ptpd, sizeof(struct tx_packet_desc));
++		tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
++		tpd->word2 = (cpu_to_le16(buffer_info->length) &
++			TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT;
++
++		/*
++		 * if this is the first packet in a TSO chain, set
++		 * TPD_HDRFLAG, otherwise, clear it.
++		 */
++		val = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) &
++			TPD_SEGMENT_EN_MASK;
++		if (val) {
++			if (!j)
++				tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
++			else
++				tpd->word3 &= ~(1 << TPD_HDRFLAG_SHIFT);
++		}
++
++		if (j == (count - 1))
++			tpd->word3 |= 1 << TPD_EOP_SHIFT;
++
++		if (++next_to_use == tpd_ring->count)
++			next_to_use = 0;
++	}
++	/*
++	 * Force memory writes to complete before letting h/w
++	 * know there are new descriptors to fetch.  (Only
++	 * applicable for weak-ordered memory model archs,
++	 * such as IA-64).
++	 */
++	wmb();
++
++	atomic_set(&tpd_ring->next_to_use, next_to_use);
++}
++
++static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++	int len = skb->len;
++	int tso;
++	int count = 1;
++	int ret_val;
++	struct tx_packet_desc *ptpd;
++	u16 frag_size;
++	u16 vlan_tag;
++	unsigned long flags;
++	unsigned int nr_frags = 0;
++	unsigned int mss = 0;
++	unsigned int f;
++	unsigned int proto_hdr_len;
++
++	len -= skb->data_len;
++
++	if (unlikely(skb->len <= 0)) {
++		dev_kfree_skb_any(skb);
++		return NETDEV_TX_OK;
++	}
++
++	nr_frags = skb_shinfo(skb)->nr_frags;
++	for (f = 0; f < nr_frags; f++) {
++		frag_size = skb_shinfo(skb)->frags[f].size;
++		if (frag_size)
++			count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
++				ATL1_MAX_TX_BUF_LEN;
++	}
++
++	mss = skb_shinfo(skb)->gso_size;
++	if (mss) {
++		if (skb->protocol == ntohs(ETH_P_IP)) {
++			proto_hdr_len = (skb_transport_offset(skb) +
++					 tcp_hdrlen(skb));
++			if (unlikely(proto_hdr_len > len)) {
++				dev_kfree_skb_any(skb);
++				return NETDEV_TX_OK;
++			}
++			/* need additional TPD ? */
++			if (proto_hdr_len != len)
++				count += (len - proto_hdr_len +
++					ATL1_MAX_TX_BUF_LEN - 1) /
++					ATL1_MAX_TX_BUF_LEN;
++		}
++	}
++
++	if (!spin_trylock_irqsave(&adapter->lock, flags)) {
++		/* Can't get lock - tell upper layer to requeue */
++		if (netif_msg_tx_queued(adapter))
++			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++				"tx locked\n");
++		return NETDEV_TX_LOCKED;
++	}
++
++	if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
++		/* not enough descriptors */
++		netif_stop_queue(netdev);
++		spin_unlock_irqrestore(&adapter->lock, flags);
++		if (netif_msg_tx_queued(adapter))
++			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++				"tx busy\n");
++		return NETDEV_TX_BUSY;
++	}
++
++	ptpd = ATL1_TPD_DESC(tpd_ring,
++		(u16) atomic_read(&tpd_ring->next_to_use));
++	memset(ptpd, 0, sizeof(struct tx_packet_desc));
++
++	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
++		vlan_tag = vlan_tx_tag_get(skb);
++		vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
++			((vlan_tag >> 9) & 0x8);
++		ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
++		ptpd->word3 |= (vlan_tag & TPD_VL_TAGGED_MASK) <<
++			TPD_VL_TAGGED_SHIFT;
++	}
++
++	tso = atl1_tso(adapter, skb, ptpd);
++	if (tso < 0) {
++		spin_unlock_irqrestore(&adapter->lock, flags);
++		dev_kfree_skb_any(skb);
++		return NETDEV_TX_OK;
++	}
++
++	if (!tso) {
++		ret_val = atl1_tx_csum(adapter, skb, ptpd);
++		if (ret_val < 0) {
++			spin_unlock_irqrestore(&adapter->lock, flags);
++			dev_kfree_skb_any(skb);
++			return NETDEV_TX_OK;
++		}
++	}
++
++	atl1_tx_map(adapter, skb, ptpd);
++	atl1_tx_queue(adapter, count, ptpd);
++	atl1_update_mailbox(adapter);
++	spin_unlock_irqrestore(&adapter->lock, flags);
++	netdev->trans_start = jiffies;
++	return NETDEV_TX_OK;
++}
++
++/*
++ * atl1_intr - Interrupt Handler
++ * @irq: interrupt number
++ * @data: pointer to a network interface device structure
++ * @pt_regs: CPU registers structure
++ */
++static irqreturn_t atl1_intr(int irq, void *data)
++{
++	struct atl1_adapter *adapter = netdev_priv(data);
++	u32 status;
++	int max_ints = 10;
++
++	status = adapter->cmb.cmb->int_stats;
++	if (!status)
++		return IRQ_NONE;
++
++	do {
++		/* clear CMB interrupt status at once */
++		adapter->cmb.cmb->int_stats = 0;
++
++		if (status & ISR_GPHY)	/* clear phy status */
++			atlx_clear_phy_int(adapter);
++
++		/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
++		iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
++
++		/* check if SMB intr */
++		if (status & ISR_SMB)
++			atl1_inc_smb(adapter);
++
++		/* check if PCIE PHY Link down */
++		if (status & ISR_PHY_LINKDOWN) {
++			if (netif_msg_intr(adapter))
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"pcie phy link down %x\n", status);
++			if (netif_running(adapter->netdev)) {	/* reset MAC */
++				iowrite32(0, adapter->hw.hw_addr + REG_IMR);
++				schedule_work(&adapter->pcie_dma_to_rst_task);
++				return IRQ_HANDLED;
++			}
++		}
++
++		/* check if DMA read/write error ? */
++		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
++			if (netif_msg_intr(adapter))
++				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++					"pcie DMA r/w error (status = 0x%x)\n",
++					status);
++			iowrite32(0, adapter->hw.hw_addr + REG_IMR);
++			schedule_work(&adapter->pcie_dma_to_rst_task);
++			return IRQ_HANDLED;
++		}
++
++		/* link event */
++		if (status & ISR_GPHY) {
++			adapter->soft_stats.tx_carrier_errors++;
++			atl1_check_for_link(adapter);
++		}
++
++		/* transmit event */
++		if (status & ISR_CMB_TX)
++			atl1_intr_tx(adapter);
++
++		/* rx exception */
++		if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
++			ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
++			ISR_HOST_RRD_OV | ISR_CMB_RX))) {
++			if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
++				ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
++				ISR_HOST_RRD_OV))
++				if (netif_msg_intr(adapter))
++					dev_printk(KERN_DEBUG,
++						&adapter->pdev->dev,
++						"rx exception, ISR = 0x%x\n",
++						status);
++			atl1_intr_rx(adapter);
++		}
++
++		if (--max_ints < 0)
++			break;
++
++	} while ((status = adapter->cmb.cmb->int_stats));
++
++	/* re-enable Interrupt */
++	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
++	return IRQ_HANDLED;
++}
++
++/*
++ * atl1_watchdog - Timer Call-back
++ * @data: pointer to netdev cast into an unsigned long
++ */
++static void atl1_watchdog(unsigned long data)
++{
++	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
++
++	/* Reset the timer */
++	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
++}
++
++/*
++ * atl1_phy_config - Timer Call-back
++ * @data: pointer to netdev cast into an unsigned long
++ */
++static void atl1_phy_config(unsigned long data)
++{
++	struct atl1_adapter *adapter = (struct atl1_adapter *)data;
++	struct atl1_hw *hw = &adapter->hw;
++	unsigned long flags;
++
++	spin_lock_irqsave(&adapter->lock, flags);
++	adapter->phy_timer_pending = false;
++	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
++	atl1_write_phy_reg(hw, MII_ATLX_CR, hw->mii_1000t_ctrl_reg);
++	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
++	spin_unlock_irqrestore(&adapter->lock, flags);
++}
++
++/*
++ * Orphaned vendor comment left intact here:
++ * <vendor comment>
++ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
++ * will assert. We do soft reset <0x1400=1> according
++ * with the SPEC. BUT, it seemes that PCIE or DMA
++ * state-machine will not be reset. DMAR_TO_INT will
++ * assert again and again.
++ * </vendor comment>
++ */
++
++static int atl1_reset(struct atl1_adapter *adapter)
++{
++	int ret;
++	ret = atl1_reset_hw(&adapter->hw);
++	if (ret)
++		return ret;
++	return atl1_init_hw(&adapter->hw);
++}
++
++static s32 atl1_up(struct atl1_adapter *adapter)
++{
++	struct net_device *netdev = adapter->netdev;
++	int err;
++	int irq_flags = IRQF_SAMPLE_RANDOM;
++
++	/* hardware has been reset, we need to reload some things */
++	atlx_set_multi(netdev);
++	atl1_init_ring_ptrs(adapter);
++	atlx_restore_vlan(adapter);
++	err = atl1_alloc_rx_buffers(adapter);
++	if (unlikely(!err))
++		/* no RX BUFFER allocated */
++		return -ENOMEM;
++
++	if (unlikely(atl1_configure(adapter))) {
++		err = -EIO;
++		goto err_up;
++	}
++
++	err = pci_enable_msi(adapter->pdev);
++	if (err) {
++		if (netif_msg_ifup(adapter))
++			dev_info(&adapter->pdev->dev,
++				"Unable to enable MSI: %d\n", err);
++		irq_flags |= IRQF_SHARED;
++	}
++
++	err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,
++			netdev->name, netdev);
++	if (unlikely(err))
++		goto err_up;
++
++	mod_timer(&adapter->watchdog_timer, jiffies);
++	atlx_irq_enable(adapter);
++	atl1_check_link(adapter);
++	return 0;
++
++err_up:
++	pci_disable_msi(adapter->pdev);
++	/* free rx_buffers */
++	atl1_clean_rx_ring(adapter);
++	return err;
++}
++
++static void atl1_down(struct atl1_adapter *adapter)
++{
++	struct net_device *netdev = adapter->netdev;
++
++	del_timer_sync(&adapter->watchdog_timer);
++	del_timer_sync(&adapter->phy_config_timer);
++	adapter->phy_timer_pending = false;
++
++	atlx_irq_disable(adapter);
++	free_irq(adapter->pdev->irq, netdev);
++	pci_disable_msi(adapter->pdev);
++	atl1_reset_hw(&adapter->hw);
++	adapter->cmb.cmb->int_stats = 0;
++
++	adapter->link_speed = SPEED_0;
++	adapter->link_duplex = -1;
++	netif_carrier_off(netdev);
++	netif_stop_queue(netdev);
++
++	atl1_clean_tx_ring(adapter);
++	atl1_clean_rx_ring(adapter);
++}
++
++static void atl1_tx_timeout_task(struct work_struct *work)
++{
++	struct atl1_adapter *adapter =
++		container_of(work, struct atl1_adapter, tx_timeout_task);
++	struct net_device *netdev = adapter->netdev;
++
++	netif_device_detach(netdev);
++	atl1_down(adapter);
++	atl1_up(adapter);
++	netif_device_attach(netdev);
++}
++
++/*
++ * atl1_change_mtu - Change the Maximum Transfer Unit
++ * @netdev: network interface device structure
++ * @new_mtu: new value for maximum frame size
++ *
++ * Returns 0 on success, negative on failure
++ */
++static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	int old_mtu = netdev->mtu;
++	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
++
++	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
++	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
++		if (netif_msg_link(adapter))
++			dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
++		return -EINVAL;
++	}
++
++	adapter->hw.max_frame_size = max_frame;
++	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
++	adapter->rx_buffer_len = (max_frame + 7) & ~7;
++	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
++
++	netdev->mtu = new_mtu;
++	if ((old_mtu != new_mtu) && netif_running(netdev)) {
++		atl1_down(adapter);
++		atl1_up(adapter);
++	}
++
++	return 0;
++}
++
++/*
++ * atl1_open - Called when a network interface is made active
++ * @netdev: network interface device structure
++ *
++ * Returns 0 on success, negative value on failure
++ *
++ * The open entry point is called when a network interface is made
++ * active by the system (IFF_UP).  At this point all resources needed
++ * for transmit and receive operations are allocated, the interrupt
++ * handler is registered with the OS, the watchdog timer is started,
++ * and the stack is notified that the interface is ready.
++ */
++static int atl1_open(struct net_device *netdev)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	int err;
++
++	/* allocate transmit descriptors */
++	err = atl1_setup_ring_resources(adapter);
++	if (err)
++		return err;
++
++	err = atl1_up(adapter);
++	if (err)
++		goto err_up;
++
++	return 0;
++
++err_up:
++	atl1_reset(adapter);
++	return err;
++}
++
++/*
++ * atl1_close - Disables a network interface
++ * @netdev: network interface device structure
++ *
++ * Returns 0, this is not allowed to fail
++ *
++ * The close entry point is called when an interface is de-activated
++ * by the OS.  The hardware is still under the drivers control, but
++ * needs to be disabled.  A global MAC reset is issued to stop the
++ * hardware, and all transmit and receive resources are freed.
++ */
++static int atl1_close(struct net_device *netdev)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	atl1_down(adapter);
++	atl1_free_ring_resources(adapter);
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++	struct net_device *netdev = pci_get_drvdata(pdev);
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_hw *hw = &adapter->hw;
++	u32 ctrl = 0;
++	u32 wufc = adapter->wol;
++
++	netif_device_detach(netdev);
++	if (netif_running(netdev))
++		atl1_down(adapter);
++
++	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
++	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
++	if (ctrl & BMSR_LSTATUS)
++		wufc &= ~ATLX_WUFC_LNKC;
++
++	/* reduce speed to 10/100M */
++	if (wufc) {
++		atl1_phy_enter_power_saving(hw);
++		/* if resume, let driver to re- setup link */
++		hw->phy_configured = false;
++		atl1_set_mac_addr(hw);
++		atlx_set_multi(netdev);
++
++		ctrl = 0;
++		/* turn on magic packet wol */
++		if (wufc & ATLX_WUFC_MAG)
++			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
++
++		/* turn on Link change WOL */
++		if (wufc & ATLX_WUFC_LNKC)
++			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
++		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
++
++		/* turn on all-multi mode if wake on multicast is enabled */
++		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
++		ctrl &= ~MAC_CTRL_DBG;
++		ctrl &= ~MAC_CTRL_PROMIS_EN;
++		if (wufc & ATLX_WUFC_MC)
++			ctrl |= MAC_CTRL_MC_ALL_EN;
++		else
++			ctrl &= ~MAC_CTRL_MC_ALL_EN;
++
++		/* turn on broadcast mode if wake on-BC is enabled */
++		if (wufc & ATLX_WUFC_BC)
++			ctrl |= MAC_CTRL_BC_EN;
++		else
++			ctrl &= ~MAC_CTRL_BC_EN;
++
++		/* enable RX */
++		ctrl |= MAC_CTRL_RX_EN;
++		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
++		pci_enable_wake(pdev, PCI_D3hot, 1);
++		pci_enable_wake(pdev, PCI_D3cold, 1);
++	} else {
++		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
++		pci_enable_wake(pdev, PCI_D3hot, 0);
++		pci_enable_wake(pdev, PCI_D3cold, 0);
++	}
++
++	pci_save_state(pdev);
++	pci_disable_device(pdev);
++
++	pci_set_power_state(pdev, PCI_D3hot);
++
++	return 0;
++}
++
++static int atl1_resume(struct pci_dev *pdev)
++{
++	struct net_device *netdev = pci_get_drvdata(pdev);
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	u32 err;
++
++	pci_set_power_state(pdev, PCI_D0);
++	pci_restore_state(pdev);
++
++	/* FIXME: check and handle */
++	err = pci_enable_device(pdev);
++	pci_enable_wake(pdev, PCI_D3hot, 0);
++	pci_enable_wake(pdev, PCI_D3cold, 0);
++
++	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
++	atl1_reset(adapter);
++
++	if (netif_running(netdev))
++		atl1_up(adapter);
++	netif_device_attach(netdev);
++
++	atl1_via_workaround(adapter);
++
++	return 0;
++}
++#else
++#define atl1_suspend NULL
++#define atl1_resume NULL
++#endif
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++static void atl1_poll_controller(struct net_device *netdev)
++{
++	disable_irq(netdev->irq);
++	atl1_intr(netdev->irq, netdev);
++	enable_irq(netdev->irq);
++}
++#endif
++
++/*
++ * atl1_probe - Device Initialization Routine
++ * @pdev: PCI device information struct
++ * @ent: entry in atl1_pci_tbl
++ *
++ * Returns 0 on success, negative on failure
++ *
++ * atl1_probe initializes an adapter identified by a pci_dev structure.
++ * The OS initialization, configuring of the adapter private structure,
++ * and a hardware reset occur.
++ */
++static int __devinit atl1_probe(struct pci_dev *pdev,
++	const struct pci_device_id *ent)
++{
++	struct net_device *netdev;
++	struct atl1_adapter *adapter;
++	static int cards_found = 0;
++	int err;
++
++	err = pci_enable_device(pdev);
++	if (err)
++		return err;
++
++	/*
++	 * The atl1 chip can DMA to 64-bit addresses, but it uses a single
++	 * shared register for the high 32 bits, so only a single, aligned,
++	 * 4 GB physical address range can be used at a time.
++	 *
++	 * Supporting 64-bit DMA on this hardware is more trouble than it's
++	 * worth.  It is far easier to limit to 32-bit DMA than update
++	 * various kernel subsystems to support the mechanics required by a
++	 * fixed-high-32-bit system.
++	 */
++	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
++	if (err) {
++		dev_err(&pdev->dev, "no usable DMA configuration\n");
++		goto err_dma;
++	}
++	/*
++	 * Mark all PCI regions associated with PCI device
++	 * pdev as being reserved by owner atl1_driver_name
++	 */
++	err = pci_request_regions(pdev, ATLX_DRIVER_NAME);
++	if (err)
++		goto err_request_regions;
++
++	/*
++	 * Enables bus-mastering on the device and calls
++	 * pcibios_set_master to do the needed arch specific settings
++	 */
++	pci_set_master(pdev);
++
++	netdev = alloc_etherdev(sizeof(struct atl1_adapter));
++	if (!netdev) {
++		err = -ENOMEM;
++		goto err_alloc_etherdev;
++	}
++	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->msg_enable = netif_msg_init(debug, atl1_default_msg);
++
++	adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
++	if (!adapter->hw.hw_addr) {
++		err = -EIO;
++		goto err_pci_iomap;
++	}
++	/* get device revision number */
++	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
++		(REG_MASTER_CTRL + 2));
++	if (netif_msg_probe(adapter))
++		dev_info(&pdev->dev, "version %s\n", ATLX_DRIVER_VERSION);
++
++	/* set default ring resource counts */
++	adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
++	adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
++
++	adapter->mii.dev = netdev;
++	adapter->mii.mdio_read = mdio_read;
++	adapter->mii.mdio_write = mdio_write;
++	adapter->mii.phy_id_mask = 0x1f;
++	adapter->mii.reg_num_mask = 0x1f;
++
++	netdev->open = &atl1_open;
++	netdev->stop = &atl1_close;
++	netdev->hard_start_xmit = &atl1_xmit_frame;
++	netdev->get_stats = &atlx_get_stats;
++	netdev->set_multicast_list = &atlx_set_multi;
++	netdev->set_mac_address = &atl1_set_mac;
++	netdev->change_mtu = &atl1_change_mtu;
++	netdev->do_ioctl = &atlx_ioctl;
++	netdev->tx_timeout = &atlx_tx_timeout;
++	netdev->watchdog_timeo = 5 * HZ;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++	netdev->poll_controller = atl1_poll_controller;
++#endif
++	netdev->vlan_rx_register = atlx_vlan_rx_register;
++
++	netdev->ethtool_ops = &atl1_ethtool_ops;
++	adapter->bd_number = cards_found;
++
++	/* setup the private structure */
++	err = atl1_sw_init(adapter);
++	if (err)
++		goto err_common;
++
++	netdev->features = NETIF_F_HW_CSUM;
++	netdev->features |= NETIF_F_SG;
++	netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
++	netdev->features |= NETIF_F_TSO;
++	netdev->features |= NETIF_F_LLTX;
++
++	/*
++	 * patch for some L1 of old version,
++	 * the final version of L1 may not need these
++	 * patches
++	 */
++	/* atl1_pcie_patch(adapter); */
++
++	/* really reset GPHY core */
++	iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
++
++	/*
++	 * reset the controller to
++	 * put the device in a known good starting state
++	 */
++	if (atl1_reset_hw(&adapter->hw)) {
++		err = -EIO;
++		goto err_common;
++	}
++
++	/* copy the MAC address out of the EEPROM */
++	atl1_read_mac_addr(&adapter->hw);
++	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
++
++	if (!is_valid_ether_addr(netdev->dev_addr)) {
++		err = -EIO;
++		goto err_common;
++	}
++
++	atl1_check_options(adapter);
++
++	/* pre-init the MAC, and setup link */
++	err = atl1_init_hw(&adapter->hw);
++	if (err) {
++		err = -EIO;
++		goto err_common;
++	}
++
++	atl1_pcie_patch(adapter);
++	/* assume we have no link for now */
++	netif_carrier_off(netdev);
++	netif_stop_queue(netdev);
++
++	init_timer(&adapter->watchdog_timer);
++	adapter->watchdog_timer.function = &atl1_watchdog;
++	adapter->watchdog_timer.data = (unsigned long)adapter;
++
++	init_timer(&adapter->phy_config_timer);
++	adapter->phy_config_timer.function = &atl1_phy_config;
++	adapter->phy_config_timer.data = (unsigned long)adapter;
++	adapter->phy_timer_pending = false;
++
++	INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
++
++	INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task);
++
++	INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
++
++	err = register_netdev(netdev);
++	if (err)
++		goto err_common;
++
++	cards_found++;
++	atl1_via_workaround(adapter);
++	return 0;
++
++err_common:
++	pci_iounmap(pdev, adapter->hw.hw_addr);
++err_pci_iomap:
++	free_netdev(netdev);
++err_alloc_etherdev:
++	pci_release_regions(pdev);
++err_dma:
++err_request_regions:
++	pci_disable_device(pdev);
++	return err;
++}
++
++/*
++ * atl1_remove - Device Removal Routine
++ * @pdev: PCI device information struct
++ *
++ * atl1_remove is called by the PCI subsystem to alert the driver
++ * that it should release a PCI device.  The could be caused by a
++ * Hot-Plug event, or because the driver is going to be removed from
++ * memory.
++ */
++static void __devexit atl1_remove(struct pci_dev *pdev)
++{
++	struct net_device *netdev = pci_get_drvdata(pdev);
++	struct atl1_adapter *adapter;
++	/* Device not available. Return. */
++	if (!netdev)
++		return;
++
++	adapter = netdev_priv(netdev);
++
++	/*
++	 * Some atl1 boards lack persistent storage for their MAC, and get it
++	 * from the BIOS during POST.  If we've been messing with the MAC
++	 * address, we need to save the permanent one.
++	 */
++	if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
++		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
++			ETH_ALEN);
++		atl1_set_mac_addr(&adapter->hw);
++	}
++
++	iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
++	unregister_netdev(netdev);
++	pci_iounmap(pdev, adapter->hw.hw_addr);
++	pci_release_regions(pdev);
++	free_netdev(netdev);
++	pci_disable_device(pdev);
++}
++
++static struct pci_driver atl1_driver = {
++	.name = ATLX_DRIVER_NAME,
++	.id_table = atl1_pci_tbl,
++	.probe = atl1_probe,
++	.remove = __devexit_p(atl1_remove),
++	.suspend = atl1_suspend,
++	.resume = atl1_resume
++};
++
++/*
++ * atl1_exit_module - Driver Exit Cleanup Routine
++ *
++ * atl1_exit_module is called just before the driver is removed
++ * from memory.
++ */
++static void __exit atl1_exit_module(void)
++{
++	pci_unregister_driver(&atl1_driver);
++}
++
++/*
++ * atl1_init_module - Driver Registration Routine
++ *
++ * atl1_init_module is the first routine called when the driver is
++ * loaded. All it does is register with the PCI subsystem.
++ */
++static int __init atl1_init_module(void)
++{
++	return pci_register_driver(&atl1_driver);
++}
++
++module_init(atl1_init_module);
++module_exit(atl1_exit_module);
++
++struct atl1_stats {
++	char stat_string[ETH_GSTRING_LEN];
++	int sizeof_stat;
++	int stat_offset;
++};
++
++#define ATL1_STAT(m) \
++	sizeof(((struct atl1_adapter *)0)->m), offsetof(struct atl1_adapter, m)
++
++static struct atl1_stats atl1_gstrings_stats[] = {
++	{"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
++	{"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
++	{"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
++	{"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
++	{"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
++	{"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
++	{"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
++	{"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
++	{"multicast", ATL1_STAT(soft_stats.multicast)},
++	{"collisions", ATL1_STAT(soft_stats.collisions)},
++	{"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
++	{"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
++	{"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
++	{"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
++	{"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
++	{"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
++	{"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
++	{"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
++	{"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
++	{"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
++	{"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
++	{"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
++	{"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
++	{"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
++	{"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
++	{"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
++	{"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
++	{"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
++	{"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
++	{"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
++	{"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
++};
++
++static void atl1_get_ethtool_stats(struct net_device *netdev,
++	struct ethtool_stats *stats, u64 *data)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	int i;
++	char *p;
++
++	for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
++		p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
++		data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
++			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
++	}
++
++}
++
++static int atl1_get_sset_count(struct net_device *netdev, int sset)
++{
++	switch (sset) {
++	case ETH_SS_STATS:
++		return ARRAY_SIZE(atl1_gstrings_stats);
++	default:
++		return -EOPNOTSUPP;
++	}
++}
++
++static int atl1_get_settings(struct net_device *netdev,
++	struct ethtool_cmd *ecmd)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_hw *hw = &adapter->hw;
++
++	ecmd->supported = (SUPPORTED_10baseT_Half |
++			   SUPPORTED_10baseT_Full |
++			   SUPPORTED_100baseT_Half |
++			   SUPPORTED_100baseT_Full |
++			   SUPPORTED_1000baseT_Full |
++			   SUPPORTED_Autoneg | SUPPORTED_TP);
++	ecmd->advertising = ADVERTISED_TP;
++	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
++		ecmd->advertising |= ADVERTISED_Autoneg;
++		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
++			ecmd->advertising |= ADVERTISED_Autoneg;
++			ecmd->advertising |=
++			    (ADVERTISED_10baseT_Half |
++			     ADVERTISED_10baseT_Full |
++			     ADVERTISED_100baseT_Half |
++			     ADVERTISED_100baseT_Full |
++			     ADVERTISED_1000baseT_Full);
++		} else
++			ecmd->advertising |= (ADVERTISED_1000baseT_Full);
++	}
++	ecmd->port = PORT_TP;
++	ecmd->phy_address = 0;
++	ecmd->transceiver = XCVR_INTERNAL;
++
++	if (netif_carrier_ok(adapter->netdev)) {
++		u16 link_speed, link_duplex;
++		atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
++		ecmd->speed = link_speed;
++		if (link_duplex == FULL_DUPLEX)
++			ecmd->duplex = DUPLEX_FULL;
++		else
++			ecmd->duplex = DUPLEX_HALF;
++	} else {
++		ecmd->speed = -1;
++		ecmd->duplex = -1;
++	}
++	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++	    hw->media_type == MEDIA_TYPE_1000M_FULL)
++		ecmd->autoneg = AUTONEG_ENABLE;
++	else
++		ecmd->autoneg = AUTONEG_DISABLE;
++
++	return 0;
++}
++
++static int atl1_set_settings(struct net_device *netdev,
++	struct ethtool_cmd *ecmd)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_hw *hw = &adapter->hw;
++	u16 phy_data;
++	int ret_val = 0;
++	u16 old_media_type = hw->media_type;
++
++	if (netif_running(adapter->netdev)) {
++		if (netif_msg_link(adapter))
++			dev_dbg(&adapter->pdev->dev,
++				"ethtool shutting down adapter\n");
++		atl1_down(adapter);
++	}
++
++	if (ecmd->autoneg == AUTONEG_ENABLE)
++		hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
++	else {
++		if (ecmd->speed == SPEED_1000) {
++			if (ecmd->duplex != DUPLEX_FULL) {
++				if (netif_msg_link(adapter))
++					dev_warn(&adapter->pdev->dev,
++						"1000M half is invalid\n");
++				ret_val = -EINVAL;
++				goto exit_sset;
++			}
++			hw->media_type = MEDIA_TYPE_1000M_FULL;
++		} else if (ecmd->speed == SPEED_100) {
++			if (ecmd->duplex == DUPLEX_FULL)
++				hw->media_type = MEDIA_TYPE_100M_FULL;
++			else
++				hw->media_type = MEDIA_TYPE_100M_HALF;
++		} else {
++			if (ecmd->duplex == DUPLEX_FULL)
++				hw->media_type = MEDIA_TYPE_10M_FULL;
++			else
++				hw->media_type = MEDIA_TYPE_10M_HALF;
++		}
++	}
++	switch (hw->media_type) {
++	case MEDIA_TYPE_AUTO_SENSOR:
++		ecmd->advertising =
++		    ADVERTISED_10baseT_Half |
++		    ADVERTISED_10baseT_Full |
++		    ADVERTISED_100baseT_Half |
++		    ADVERTISED_100baseT_Full |
++		    ADVERTISED_1000baseT_Full |
++		    ADVERTISED_Autoneg | ADVERTISED_TP;
++		break;
++	case MEDIA_TYPE_1000M_FULL:
++		ecmd->advertising =
++		    ADVERTISED_1000baseT_Full |
++		    ADVERTISED_Autoneg | ADVERTISED_TP;
++		break;
++	default:
++		ecmd->advertising = 0;
++		break;
++	}
++	if (atl1_phy_setup_autoneg_adv(hw)) {
++		ret_val = -EINVAL;
++		if (netif_msg_link(adapter))
++			dev_warn(&adapter->pdev->dev,
++				"invalid ethtool speed/duplex setting\n");
++		goto exit_sset;
++	}
++	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++	    hw->media_type == MEDIA_TYPE_1000M_FULL)
++		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
++	else {
++		switch (hw->media_type) {
++		case MEDIA_TYPE_100M_FULL:
++			phy_data =
++			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
++			    MII_CR_RESET;
++			break;
++		case MEDIA_TYPE_100M_HALF:
++			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++			break;
++		case MEDIA_TYPE_10M_FULL:
++			phy_data =
++			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
++			break;
++		default:
++			/* MEDIA_TYPE_10M_HALF: */
++			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++			break;
++		}
++	}
++	atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++exit_sset:
++	if (ret_val)
++		hw->media_type = old_media_type;
++
++	if (netif_running(adapter->netdev)) {
++		if (netif_msg_link(adapter))
++			dev_dbg(&adapter->pdev->dev,
++				"ethtool starting adapter\n");
++		atl1_up(adapter);
++	} else if (!ret_val) {
++		if (netif_msg_link(adapter))
++			dev_dbg(&adapter->pdev->dev,
++				"ethtool resetting adapter\n");
++		atl1_reset(adapter);
++	}
++	return ret_val;
++}
++
++static void atl1_get_drvinfo(struct net_device *netdev,
++	struct ethtool_drvinfo *drvinfo)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++
++	strncpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
++	strncpy(drvinfo->version, ATLX_DRIVER_VERSION,
++		sizeof(drvinfo->version));
++	strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
++	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
++		sizeof(drvinfo->bus_info));
++	drvinfo->eedump_len = ATL1_EEDUMP_LEN;
++}
++
++static void atl1_get_wol(struct net_device *netdev,
++	struct ethtool_wolinfo *wol)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++
++	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
++	wol->wolopts = 0;
++	if (adapter->wol & ATLX_WUFC_EX)
++		wol->wolopts |= WAKE_UCAST;
++	if (adapter->wol & ATLX_WUFC_MC)
++		wol->wolopts |= WAKE_MCAST;
++	if (adapter->wol & ATLX_WUFC_BC)
++		wol->wolopts |= WAKE_BCAST;
++	if (adapter->wol & ATLX_WUFC_MAG)
++		wol->wolopts |= WAKE_MAGIC;
++	return;
++}
++
++static int atl1_set_wol(struct net_device *netdev,
++	struct ethtool_wolinfo *wol)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++
++	if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
++		return -EOPNOTSUPP;
++	adapter->wol = 0;
++	if (wol->wolopts & WAKE_UCAST)
++		adapter->wol |= ATLX_WUFC_EX;
++	if (wol->wolopts & WAKE_MCAST)
++		adapter->wol |= ATLX_WUFC_MC;
++	if (wol->wolopts & WAKE_BCAST)
++		adapter->wol |= ATLX_WUFC_BC;
++	if (wol->wolopts & WAKE_MAGIC)
++		adapter->wol |= ATLX_WUFC_MAG;
++	return 0;
++}
++
++static u32 atl1_get_msglevel(struct net_device *netdev)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	return adapter->msg_enable;
++}
++
++static void atl1_set_msglevel(struct net_device *netdev, u32 value)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	adapter->msg_enable = value;
++}
++
++static int atl1_get_regs_len(struct net_device *netdev)
++{
++	return ATL1_REG_COUNT * sizeof(u32);
++}
++
++static void atl1_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
++	void *p)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_hw *hw = &adapter->hw;
++	unsigned int i;
++	u32 *regbuf = p;
++
++	for (i = 0; i < ATL1_REG_COUNT; i++) {
++		/*
++		 * This switch statement avoids reserved regions
++		 * of register space.
++		 */
++		switch (i) {
++		case 6 ... 9:
++		case 14:
++		case 29 ... 31:
++		case 34 ... 63:
++		case 75 ... 127:
++		case 136 ... 1023:
++		case 1027 ... 1087:
++		case 1091 ... 1151:
++		case 1194 ... 1195:
++		case 1200 ... 1201:
++		case 1206 ... 1213:
++		case 1216 ... 1279:
++		case 1290 ... 1311:
++		case 1323 ... 1343:
++		case 1358 ... 1359:
++		case 1368 ... 1375:
++		case 1378 ... 1383:
++		case 1388 ... 1391:
++		case 1393 ... 1395:
++		case 1402 ... 1403:
++		case 1410 ... 1471:
++		case 1522 ... 1535:
++			/* reserved region; don't read it */
++			regbuf[i] = 0;
++			break;
++		default:
++			/* unreserved region */
++			regbuf[i] = ioread32(hw->hw_addr + (i * sizeof(u32)));
++		}
++	}
++}
++
++static void atl1_get_ringparam(struct net_device *netdev,
++	struct ethtool_ringparam *ring)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
++	struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
++
++	ring->rx_max_pending = ATL1_MAX_RFD;
++	ring->tx_max_pending = ATL1_MAX_TPD;
++	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;
++}
++
++static int atl1_set_ringparam(struct net_device *netdev,
++	struct ethtool_ringparam *ring)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
++	struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
++	struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
++
++	struct atl1_tpd_ring tpd_old, tpd_new;
++	struct atl1_rfd_ring rfd_old, rfd_new;
++	struct atl1_rrd_ring rrd_old, rrd_new;
++	struct atl1_ring_header rhdr_old, rhdr_new;
++	int err;
++
++	tpd_old = adapter->tpd_ring;
++	rfd_old = adapter->rfd_ring;
++	rrd_old = adapter->rrd_ring;
++	rhdr_old = adapter->ring_header;
++
++	if (netif_running(adapter->netdev))
++		atl1_down(adapter);
++
++	rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
++	rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
++			rfdr->count;
++	rfdr->count = (rfdr->count + 3) & ~3;
++	rrdr->count = rfdr->count;
++
++	tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
++	tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
++			tpdr->count;
++	tpdr->count = (tpdr->count + 3) & ~3;
++
++	if (netif_running(adapter->netdev)) {
++		/* try to get new resources before deleting old */
++		err = atl1_setup_ring_resources(adapter);
++		if (err)
++			goto err_setup_ring;
++
++		/*
++		 * save the new, restore the old in order to free it,
++		 * then restore the new back again
++		 */
++
++		rfd_new = adapter->rfd_ring;
++		rrd_new = adapter->rrd_ring;
++		tpd_new = adapter->tpd_ring;
++		rhdr_new = adapter->ring_header;
++		adapter->rfd_ring = rfd_old;
++		adapter->rrd_ring = rrd_old;
++		adapter->tpd_ring = tpd_old;
++		adapter->ring_header = rhdr_old;
++		atl1_free_ring_resources(adapter);
++		adapter->rfd_ring = rfd_new;
++		adapter->rrd_ring = rrd_new;
++		adapter->tpd_ring = tpd_new;
++		adapter->ring_header = rhdr_new;
++
++		err = atl1_up(adapter);
++		if (err)
++			return err;
++	}
++	return 0;
++
++err_setup_ring:
++	adapter->rfd_ring = rfd_old;
++	adapter->rrd_ring = rrd_old;
++	adapter->tpd_ring = tpd_old;
++	adapter->ring_header = rhdr_old;
++	atl1_up(adapter);
++	return err;
++}
++
++static void atl1_get_pauseparam(struct net_device *netdev,
++	struct ethtool_pauseparam *epause)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_hw *hw = &adapter->hw;
++
++	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
++		epause->autoneg = AUTONEG_ENABLE;
++	} else {
++		epause->autoneg = AUTONEG_DISABLE;
++	}
++	epause->rx_pause = 1;
++	epause->tx_pause = 1;
++}
++
++static int atl1_set_pauseparam(struct net_device *netdev,
++	struct ethtool_pauseparam *epause)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_hw *hw = &adapter->hw;
++
++	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
++		epause->autoneg = AUTONEG_ENABLE;
++	} else {
++		epause->autoneg = AUTONEG_DISABLE;
++	}
++
++	epause->rx_pause = 1;
++	epause->tx_pause = 1;
++
++	return 0;
++}
++
++/* FIXME: is this right? -- CHS */
++static u32 atl1_get_rx_csum(struct net_device *netdev)
++{
++	return 1;
++}
++
++static void atl1_get_strings(struct net_device *netdev, u32 stringset,
++	u8 *data)
++{
++	u8 *p = data;
++	int i;
++
++	switch (stringset) {
++	case ETH_SS_STATS:
++		for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
++			memcpy(p, atl1_gstrings_stats[i].stat_string,
++				ETH_GSTRING_LEN);
++			p += ETH_GSTRING_LEN;
++		}
++		break;
++	}
++}
++
++static int atl1_nway_reset(struct net_device *netdev)
++{
++	struct atl1_adapter *adapter = netdev_priv(netdev);
++	struct atl1_hw *hw = &adapter->hw;
++
++	if (netif_running(netdev)) {
++		u16 phy_data;
++		atl1_down(adapter);
++
++		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++			hw->media_type == MEDIA_TYPE_1000M_FULL) {
++			phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
++		} else {
++			switch (hw->media_type) {
++			case MEDIA_TYPE_100M_FULL:
++				phy_data = MII_CR_FULL_DUPLEX |
++					MII_CR_SPEED_100 | MII_CR_RESET;
++				break;
++			case MEDIA_TYPE_100M_HALF:
++				phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++				break;
++			case MEDIA_TYPE_10M_FULL:
++				phy_data = MII_CR_FULL_DUPLEX |
++					MII_CR_SPEED_10 | MII_CR_RESET;
++				break;
++			default:
++				/* MEDIA_TYPE_10M_HALF */
++				phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++			}
++		}
++		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++		atl1_up(adapter);
++	}
++	return 0;
++}
++
++const struct ethtool_ops atl1_ethtool_ops = {
++	.get_settings		= atl1_get_settings,
++	.set_settings		= atl1_set_settings,
++	.get_drvinfo		= atl1_get_drvinfo,
++	.get_wol		= atl1_get_wol,
++	.set_wol		= atl1_set_wol,
++	.get_msglevel		= atl1_get_msglevel,
++	.set_msglevel		= atl1_set_msglevel,
++	.get_regs_len		= atl1_get_regs_len,
++	.get_regs		= atl1_get_regs,
++	.get_ringparam		= atl1_get_ringparam,
++	.set_ringparam		= atl1_set_ringparam,
++	.get_pauseparam		= atl1_get_pauseparam,
++	.set_pauseparam		= atl1_set_pauseparam,
++	.get_rx_csum		= atl1_get_rx_csum,
++	.set_tx_csum		= ethtool_op_set_tx_hw_csum,
++	.get_link		= ethtool_op_get_link,
++	.set_sg			= ethtool_op_set_sg,
++	.get_strings		= atl1_get_strings,
++	.nway_reset		= atl1_nway_reset,
++	.get_ethtool_stats	= atl1_get_ethtool_stats,
++	.get_sset_count		= atl1_get_sset_count,
++	.set_tso		= ethtool_op_set_tso,
++};
+diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h
+new file mode 100644
+index 0000000..51893d6
+--- /dev/null
++++ b/drivers/net/atlx/atl1.h
+@@ -0,0 +1,796 @@
++/*
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ *
++ * Derived from Intel e1000 driver
++ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59
++ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
++ */
++
++#ifndef ATL1_H
++#define ATL1_H
++
++#include <linux/compiler.h>
++#include <linux/ethtool.h>
++#include <linux/if_vlan.h>
++#include <linux/mii.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/spinlock.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
++
++#include "atlx.h"
++
++#define ATLX_DRIVER_NAME "atl1"
++
++MODULE_DESCRIPTION("Atheros L1 Gigabit Ethernet Driver");
++
++#define atlx_adapter		atl1_adapter
++#define atlx_check_for_link	atl1_check_for_link
++#define atlx_check_link		atl1_check_link
++#define atlx_hash_mc_addr	atl1_hash_mc_addr
++#define atlx_hash_set		atl1_hash_set
++#define atlx_hw			atl1_hw
++#define atlx_mii_ioctl		atl1_mii_ioctl
++#define atlx_read_phy_reg	atl1_read_phy_reg
++#define atlx_set_mac		atl1_set_mac
++#define atlx_set_mac_addr	atl1_set_mac_addr
++
++struct atl1_adapter;
++struct atl1_hw;
++
++/* function prototypes needed by multiple files */
++u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
++void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
++s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
++void atl1_set_mac_addr(struct atl1_hw *hw);
++static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
++	int cmd);
++static u32 atl1_check_link(struct atl1_adapter *adapter);
++
++extern const struct ethtool_ops atl1_ethtool_ops;
++
++/* hardware definitions specific to L1 */
++
++/* Block IDLE Status Register */
++#define IDLE_STATUS_RXMAC			0x1
++#define IDLE_STATUS_TXMAC			0x2
++#define IDLE_STATUS_RXQ				0x4
++#define IDLE_STATUS_TXQ				0x8
++#define IDLE_STATUS_DMAR			0x10
++#define IDLE_STATUS_DMAW			0x20
++#define IDLE_STATUS_SMB				0x40
++#define IDLE_STATUS_CMB				0x80
++
++/* MDIO Control Register */
++#define MDIO_WAIT_TIMES				30
++
++/* MAC Control Register */
++#define MAC_CTRL_TX_PAUSE			0x10000
++#define MAC_CTRL_SCNT				0x20000
++#define MAC_CTRL_SRST_TX			0x40000
++#define MAC_CTRL_TX_SIMURST			0x80000
++#define MAC_CTRL_SPEED_SHIFT			20
++#define MAC_CTRL_SPEED_MASK			0x300000
++#define MAC_CTRL_SPEED_1000			0x2
++#define MAC_CTRL_SPEED_10_100			0x1
++#define MAC_CTRL_DBG_TX_BKPRESURE		0x400000
++#define MAC_CTRL_TX_HUGE			0x800000
++#define MAC_CTRL_RX_CHKSUM_EN			0x1000000
++#define MAC_CTRL_DBG				0x8000000
++
++/* Wake-On-Lan control register */
++#define WOL_CLK_SWITCH_EN			0x8000
++#define WOL_PT5_EN				0x200000
++#define WOL_PT6_EN				0x400000
++#define WOL_PT5_MATCH				0x8000000
++#define WOL_PT6_MATCH				0x10000000
++
++/* WOL Length ( 2 DWORD ) */
++#define REG_WOL_PATTERN_LEN			0x14A4
++#define WOL_PT_LEN_MASK				0x7F
++#define WOL_PT0_LEN_SHIFT			0
++#define WOL_PT1_LEN_SHIFT			8
++#define WOL_PT2_LEN_SHIFT			16
++#define WOL_PT3_LEN_SHIFT			24
++#define WOL_PT4_LEN_SHIFT			0
++#define WOL_PT5_LEN_SHIFT			8
++#define WOL_PT6_LEN_SHIFT			16
++
++/* Internal SRAM Partition Registers, low 32 bits */
++#define REG_SRAM_RFD_LEN			0x1504
++#define REG_SRAM_RRD_ADDR			0x1508
++#define REG_SRAM_RRD_LEN			0x150C
++#define REG_SRAM_TPD_ADDR			0x1510
++#define REG_SRAM_TPD_LEN			0x1514
++#define REG_SRAM_TRD_ADDR			0x1518
++#define REG_SRAM_TRD_LEN			0x151C
++#define REG_SRAM_RXF_ADDR			0x1520
++#define REG_SRAM_RXF_LEN			0x1524
++#define REG_SRAM_TXF_ADDR			0x1528
++#define REG_SRAM_TXF_LEN			0x152C
++#define REG_SRAM_TCPH_PATH_ADDR			0x1530
++#define SRAM_TCPH_ADDR_MASK			0xFFF
++#define SRAM_TCPH_ADDR_SHIFT			0
++#define SRAM_PATH_ADDR_MASK			0xFFF
++#define SRAM_PATH_ADDR_SHIFT			16
++
++/* Load Ptr Register */
++#define REG_LOAD_PTR				0x1534
++
++/* Descriptor Control registers, low 32 bits */
++#define REG_DESC_RFD_ADDR_LO			0x1544
++#define REG_DESC_RRD_ADDR_LO			0x1548
++#define REG_DESC_TPD_ADDR_LO			0x154C
++#define REG_DESC_CMB_ADDR_LO			0x1550
++#define REG_DESC_SMB_ADDR_LO			0x1554
++#define REG_DESC_RFD_RRD_RING_SIZE		0x1558
++#define DESC_RFD_RING_SIZE_MASK			0x7FF
++#define DESC_RFD_RING_SIZE_SHIFT		0
++#define DESC_RRD_RING_SIZE_MASK			0x7FF
++#define DESC_RRD_RING_SIZE_SHIFT		16
++#define REG_DESC_TPD_RING_SIZE			0x155C
++#define DESC_TPD_RING_SIZE_MASK			0x3FF
++#define DESC_TPD_RING_SIZE_SHIFT		0
++
++/* TXQ Control Register */
++#define REG_TXQ_CTRL				0x1580
++#define TXQ_CTRL_TPD_BURST_NUM_SHIFT		0
++#define TXQ_CTRL_TPD_BURST_NUM_MASK		0x1F
++#define TXQ_CTRL_EN				0x20
++#define TXQ_CTRL_ENH_MODE			0x40
++#define TXQ_CTRL_TPD_FETCH_TH_SHIFT		8
++#define TXQ_CTRL_TPD_FETCH_TH_MASK		0x3F
++#define TXQ_CTRL_TXF_BURST_NUM_SHIFT		16
++#define TXQ_CTRL_TXF_BURST_NUM_MASK		0xFFFF
++
++/* Jumbo packet Threshold for task offload */
++#define REG_TX_JUMBO_TASK_TH_TPD_IPG		0x1584
++#define TX_JUMBO_TASK_TH_MASK			0x7FF
++#define TX_JUMBO_TASK_TH_SHIFT			0
++#define TX_TPD_MIN_IPG_MASK			0x1F
++#define TX_TPD_MIN_IPG_SHIFT			16
++
++/* RXQ Control Register */
++#define REG_RXQ_CTRL				0x15A0
++#define RXQ_CTRL_RFD_BURST_NUM_SHIFT		0
++#define RXQ_CTRL_RFD_BURST_NUM_MASK		0xFF
++#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT		8
++#define RXQ_CTRL_RRD_BURST_THRESH_MASK		0xFF
++#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT		16
++#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK		0x1F
++#define RXQ_CTRL_CUT_THRU_EN			0x40000000
++#define RXQ_CTRL_EN				0x80000000
++
++/* Rx jumbo packet threshold and rrd  retirement timer */
++#define REG_RXQ_JMBOSZ_RRDTIM			0x15A4
++#define RXQ_JMBOSZ_TH_MASK			0x7FF
++#define RXQ_JMBOSZ_TH_SHIFT			0
++#define RXQ_JMBO_LKAH_MASK			0xF
++#define RXQ_JMBO_LKAH_SHIFT			11
++#define RXQ_RRD_TIMER_MASK			0xFFFF
++#define RXQ_RRD_TIMER_SHIFT			16
++
++/* RFD flow control register */
++#define REG_RXQ_RXF_PAUSE_THRESH		0x15A8
++#define RXQ_RXF_PAUSE_TH_HI_SHIFT		16
++#define RXQ_RXF_PAUSE_TH_HI_MASK		0xFFF
++#define RXQ_RXF_PAUSE_TH_LO_SHIFT		0
++#define RXQ_RXF_PAUSE_TH_LO_MASK		0xFFF
++
++/* RRD flow control register */
++#define REG_RXQ_RRD_PAUSE_THRESH		0x15AC
++#define RXQ_RRD_PAUSE_TH_HI_SHIFT		0
++#define RXQ_RRD_PAUSE_TH_HI_MASK		0xFFF
++#define RXQ_RRD_PAUSE_TH_LO_SHIFT		16
++#define RXQ_RRD_PAUSE_TH_LO_MASK		0xFFF
++
++/* DMA Engine Control Register */
++#define REG_DMA_CTRL				0x15C0
++#define DMA_CTRL_DMAR_IN_ORDER			0x1
++#define DMA_CTRL_DMAR_ENH_ORDER			0x2
++#define DMA_CTRL_DMAR_OUT_ORDER			0x4
++#define DMA_CTRL_RCB_VALUE			0x8
++#define DMA_CTRL_DMAR_BURST_LEN_SHIFT		4
++#define DMA_CTRL_DMAR_BURST_LEN_MASK		7
++#define DMA_CTRL_DMAW_BURST_LEN_SHIFT		7
++#define DMA_CTRL_DMAW_BURST_LEN_MASK		7
++#define DMA_CTRL_DMAR_EN			0x400
++#define DMA_CTRL_DMAW_EN			0x800
++
++/* CMB/SMB Control Register */
++#define REG_CSMB_CTRL				0x15D0
++#define CSMB_CTRL_CMB_NOW			1
++#define CSMB_CTRL_SMB_NOW			2
++#define CSMB_CTRL_CMB_EN			4
++#define CSMB_CTRL_SMB_EN			8
++
++/* CMB DMA Write Threshold Register */
++#define REG_CMB_WRITE_TH			0x15D4
++#define CMB_RRD_TH_SHIFT			0
++#define CMB_RRD_TH_MASK				0x7FF
++#define CMB_TPD_TH_SHIFT			16
++#define CMB_TPD_TH_MASK				0x7FF
++
++/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
++#define REG_CMB_WRITE_TIMER			0x15D8
++#define CMB_RX_TM_SHIFT				0
++#define CMB_RX_TM_MASK				0xFFFF
++#define CMB_TX_TM_SHIFT				16
++#define CMB_TX_TM_MASK				0xFFFF
++
++/* Number of packet received since last CMB write */
++#define REG_CMB_RX_PKT_CNT			0x15DC
++
++/* Number of packet transmitted since last CMB write */
++#define REG_CMB_TX_PKT_CNT			0x15E0
++
++/* SMB auto DMA timer register */
++#define REG_SMB_TIMER				0x15E4
++
++/* Mailbox Register */
++#define REG_MAILBOX				0x15F0
++#define MB_RFD_PROD_INDX_SHIFT			0
++#define MB_RFD_PROD_INDX_MASK			0x7FF
++#define MB_RRD_CONS_INDX_SHIFT			11
++#define MB_RRD_CONS_INDX_MASK			0x7FF
++#define MB_TPD_PROD_INDX_SHIFT			22
++#define MB_TPD_PROD_INDX_MASK			0x3FF
++
++/* Interrupt Status Register */
++#define ISR_SMB					0x1
++#define ISR_TIMER				0x2
++#define ISR_MANUAL				0x4
++#define ISR_RXF_OV				0x8
++#define ISR_RFD_UNRUN				0x10
++#define ISR_RRD_OV				0x20
++#define ISR_TXF_UNRUN				0x40
++#define ISR_LINK				0x80
++#define ISR_HOST_RFD_UNRUN			0x100
++#define ISR_HOST_RRD_OV				0x200
++#define ISR_DMAR_TO_RST				0x400
++#define ISR_DMAW_TO_RST				0x800
++#define ISR_GPHY				0x1000
++#define ISR_RX_PKT				0x10000
++#define ISR_TX_PKT				0x20000
++#define ISR_TX_DMA				0x40000
++#define ISR_RX_DMA				0x80000
++#define ISR_CMB_RX				0x100000
++#define ISR_CMB_TX				0x200000
++#define ISR_MAC_RX				0x400000
++#define ISR_MAC_TX				0x800000
++#define ISR_DIS_SMB				0x20000000
++#define ISR_DIS_DMA				0x40000000
++
++/* Normal Interrupt mask  */
++#define IMR_NORMAL_MASK	(\
++	ISR_SMB		|\
++	ISR_GPHY	|\
++	ISR_PHY_LINKDOWN|\
++	ISR_DMAR_TO_RST	|\
++	ISR_DMAW_TO_RST	|\
++	ISR_CMB_TX	|\
++	ISR_CMB_RX)
++
++/* Debug Interrupt Mask  (enable all interrupt) */
++#define IMR_DEBUG_MASK	(\
++	ISR_SMB		|\
++	ISR_TIMER	|\
++	ISR_MANUAL	|\
++	ISR_RXF_OV	|\
++	ISR_RFD_UNRUN	|\
++	ISR_RRD_OV	|\
++	ISR_TXF_UNRUN	|\
++	ISR_LINK	|\
++	ISR_CMB_TX	|\
++	ISR_CMB_RX	|\
++	ISR_RX_PKT	|\
++	ISR_TX_PKT	|\
++	ISR_MAC_RX	|\
++	ISR_MAC_TX)
++
++#define MEDIA_TYPE_1000M_FULL			1
++#define MEDIA_TYPE_100M_FULL			2
++#define MEDIA_TYPE_100M_HALF			3
++#define MEDIA_TYPE_10M_FULL			4
++#define MEDIA_TYPE_10M_HALF			5
++
++#define AUTONEG_ADVERTISE_SPEED_DEFAULT		0x002F	/* All but 1000-Half */
++
++#define MAX_JUMBO_FRAME_SIZE			10240
++
++#define ATL1_EEDUMP_LEN				48
++
++/* Statistics counters collected by the MAC */
++struct stats_msg_block {
++	/* rx */
++	u32 rx_ok;		/* good RX packets */
++	u32 rx_bcast;		/* good RX broadcast packets */
++	u32 rx_mcast;		/* good RX multicast packets */
++	u32 rx_pause;		/* RX pause frames */
++	u32 rx_ctrl;		/* RX control packets other than pause frames */
++	u32 rx_fcs_err;		/* RX packets with bad FCS */
++	u32 rx_len_err;		/* RX packets with length != actual size */
++	u32 rx_byte_cnt;	/* good bytes received. FCS is NOT included */
++	u32 rx_runt;		/* RX packets < 64 bytes with good FCS */
++	u32 rx_frag;		/* RX packets < 64 bytes with bad FCS */
++	u32 rx_sz_64;		/* 64 byte RX packets */
++	u32 rx_sz_65_127;
++	u32 rx_sz_128_255;
++	u32 rx_sz_256_511;
++	u32 rx_sz_512_1023;
++	u32 rx_sz_1024_1518;
++	u32 rx_sz_1519_max;	/* 1519 byte to MTU RX packets */
++	u32 rx_sz_ov;		/* truncated RX packets > MTU */
++	u32 rx_rxf_ov;		/* frames dropped due to RX FIFO overflow */
++	u32 rx_rrd_ov;		/* frames dropped due to RRD overflow */
++	u32 rx_align_err;	/* alignment errors */
++	u32 rx_bcast_byte_cnt;	/* RX broadcast bytes, excluding FCS */
++	u32 rx_mcast_byte_cnt;	/* RX multicast bytes, excluding FCS */
++	u32 rx_err_addr;	/* packets dropped due to address filtering */
++
++	/* tx */
++	u32 tx_ok;		/* good TX packets */
++	u32 tx_bcast;		/* good TX broadcast packets */
++	u32 tx_mcast;		/* good TX multicast packets */
++	u32 tx_pause;		/* TX pause frames */
++	u32 tx_exc_defer;	/* TX packets deferred excessively */
++	u32 tx_ctrl;		/* TX control frames, excluding pause frames */
++	u32 tx_defer;		/* TX packets deferred */
++	u32 tx_byte_cnt;	/* bytes transmitted, FCS is NOT included */
++	u32 tx_sz_64;		/* 64 byte TX packets */
++	u32 tx_sz_65_127;
++	u32 tx_sz_128_255;
++	u32 tx_sz_256_511;
++	u32 tx_sz_512_1023;
++	u32 tx_sz_1024_1518;
++	u32 tx_sz_1519_max;	/* 1519 byte to MTU TX packets */
++	u32 tx_1_col;		/* packets TX after a single collision */
++	u32 tx_2_col;		/* packets TX after multiple collisions */
++	u32 tx_late_col;	/* TX packets with late collisions */
++	u32 tx_abort_col;	/* TX packets aborted w/excessive collisions */
++	u32 tx_underrun;	/* TX packets aborted due to TX FIFO underrun
++				 * or TRD FIFO underrun */
++	u32 tx_rd_eop;		/* reads beyond the EOP into the next frame
++				 * when TRD was not written timely */
++	u32 tx_len_err;		/* TX packets where length != actual size */
++	u32 tx_trunc;		/* TX packets truncated due to size > MTU */
++	u32 tx_bcast_byte;	/* broadcast bytes transmitted, excluding FCS */
++	u32 tx_mcast_byte;	/* multicast bytes transmitted, excluding FCS */
++	u32 smb_updated;	/* 1: SMB Updated. This is used by software to
++				 * indicate the statistics update. Software
++				 * should clear this bit after retrieving the
++				 * statistics information. */
++};
++
++/* Coalescing Message Block */
++struct coals_msg_block {
++	u32 int_stats;		/* interrupt status */
++	u16 rrd_prod_idx;	/* TRD Producer Index. */
++	u16 rfd_cons_idx;	/* RFD Consumer Index. */
++	u16 update;		/* Selene sets this bit every time it DMAs the
++				 * CMB to host memory. Software should clear
++				 * this bit when CMB info is processed. */
++	u16 tpd_cons_idx;	/* TPD Consumer Index. */
++};
++
++/* RRD descriptor */
++struct rx_return_desc {
++	u8 num_buf;	/* Number of RFD buffers used by the received packet */
++	u8 resved;
++	u16 buf_indx;	/* RFD Index of the first buffer */
++	union {
++		u32 valid;
++		struct {
++			u16 rx_chksum;
++			u16 pkt_size;
++		} xsum_sz;
++	} xsz;
++
++	u16 pkt_flg;	/* Packet flags */
++	u16 err_flg;	/* Error flags */
++	u16 resved2;
++	u16 vlan_tag;	/* VLAN TAG */
++};
++
++#define PACKET_FLAG_ETH_TYPE	0x0080
++#define PACKET_FLAG_VLAN_INS	0x0100
++#define PACKET_FLAG_ERR		0x0200
++#define PACKET_FLAG_IPV4	0x0400
++#define PACKET_FLAG_UDP		0x0800
++#define PACKET_FLAG_TCP		0x1000
++#define PACKET_FLAG_BCAST	0x2000
++#define PACKET_FLAG_MCAST	0x4000
++#define PACKET_FLAG_PAUSE	0x8000
++
++#define ERR_FLAG_CRC		0x0001
++#define ERR_FLAG_CODE		0x0002
++#define ERR_FLAG_DRIBBLE	0x0004
++#define ERR_FLAG_RUNT		0x0008
++#define ERR_FLAG_OV		0x0010
++#define ERR_FLAG_TRUNC		0x0020
++#define ERR_FLAG_IP_CHKSUM	0x0040
++#define ERR_FLAG_L4_CHKSUM	0x0080
++#define ERR_FLAG_LEN		0x0100
++#define ERR_FLAG_DES_ADDR	0x0200
++
++/* RFD descriptor */
++struct rx_free_desc {
++	__le64 buffer_addr;	/* Address of the descriptor's data buffer */
++	__le16 buf_len;		/* Size of the receive buffer in host memory */
++	u16 coalese;		/* Update consumer index to host after the
++				 * reception of this frame */
++	/* __attribute__ ((packed)) is required */
++} __attribute__ ((packed));
++
++/*
++ * The L1 transmit packet descriptor is comprised of four 32-bit words.
++ *
++ *	31					0
++ *	+---------------------------------------+
++ *      |	Word 0: Buffer addr lo 		|
++ *      +---------------------------------------+
++ *      |	Word 1: Buffer addr hi		|
++ *      +---------------------------------------+
++ *      |		Word 2			|
++ *      +---------------------------------------+
++ *      |		Word 3			|
++ *      +---------------------------------------+
++ *
++ * Words 0 and 1 combine to form a 64-bit buffer address.
++ *
++ * Word 2 is self explanatory in the #define block below.
++ *
++ * Word 3 has two forms, depending upon the state of bits 3 and 4.
++ * If bits 3 and 4 are both zero, then bits 14:31 are unused by the
++ * hardware.  Otherwise, if either bit 3 or 4 is set, the definition
++ * of bits 14:31 vary according to the following depiction.
++ *
++ *	0	End of packet			0	End of packet
++ *	1	Coalesce			1	Coalesce
++ *	2	Insert VLAN tag			2	Insert VLAN tag
++ *	3	Custom csum enable = 0		3	Custom csum enable = 1
++ *	4	Segment enable = 1		4	Segment enable = 0
++ *	5	Generate IP checksum		5	Generate IP checksum
++ *	6	Generate TCP checksum		6	Generate TCP checksum
++ *	7	Generate UDP checksum		7	Generate UDP checksum
++ *	8	VLAN tagged			8	VLAN tagged
++ *	9	Ethernet frame type		9	Ethernet frame type
++ *	10-+ 					10-+
++ *	11 |	IP hdr length (10:13)		11 |	IP hdr length (10:13)
++ *	12 |	(num 32-bit words)		12 |	(num 32-bit words)
++ *	13-+					13-+
++ *	14-+					14	Unused
++ *	15 |	TCP hdr length (14:17)		15	Unused
++ *	16 |	(num 32-bit words)		16-+
++ *	17-+					17 |
++ *	18	Header TPD flag			18 |
++ *	19-+					19 |	Payload offset
++ *	20 |					20 |	    (16:23)
++ *	21 |					21 |
++ *	22 |					22 |
++ *	23 |					23-+
++ *	24 |					24-+
++ *	25 |	MSS (19:31)			25 |
++ *	26 |					26 |
++ *	27 |					27 |	Custom csum offset
++ *	28 |					28 |	     (24:31)
++ *	29 |					29 |
++ *	30 |					30 |
++ *	31-+					31-+
++ */
++
++/* tpd word 2 */
++#define TPD_BUFLEN_MASK		0x3FFF
++#define TPD_BUFLEN_SHIFT	0
++#define TPD_DMAINT_MASK		0x0001
++#define TPD_DMAINT_SHIFT	14
++#define TPD_PKTNT_MASK		0x0001
++#define TPD_PKTINT_SHIFT	15
++#define TPD_VLANTAG_MASK	0xFFFF
++#define TPD_VLAN_SHIFT		16
++
++/* tpd word 3 bits 0:13 */
++#define TPD_EOP_MASK		0x0001
++#define TPD_EOP_SHIFT		0
++#define TPD_COALESCE_MASK	0x0001
++#define TPD_COALESCE_SHIFT	1
++#define TPD_INS_VL_TAG_MASK	0x0001
++#define TPD_INS_VL_TAG_SHIFT	2
++#define TPD_CUST_CSUM_EN_MASK	0x0001
++#define TPD_CUST_CSUM_EN_SHIFT	3
++#define TPD_SEGMENT_EN_MASK	0x0001
++#define TPD_SEGMENT_EN_SHIFT	4
++#define TPD_IP_CSUM_MASK	0x0001
++#define TPD_IP_CSUM_SHIFT	5
++#define TPD_TCP_CSUM_MASK	0x0001
++#define TPD_TCP_CSUM_SHIFT	6
++#define TPD_UDP_CSUM_MASK	0x0001
++#define TPD_UDP_CSUM_SHIFT	7
++#define TPD_VL_TAGGED_MASK	0x0001
++#define TPD_VL_TAGGED_SHIFT	8
++#define TPD_ETHTYPE_MASK	0x0001
++#define TPD_ETHTYPE_SHIFT	9
++#define TPD_IPHL_MASK		0x000F
++#define TPD_IPHL_SHIFT		10
++
++/* tpd word 3 bits 14:31 if segment enabled */
++#define TPD_TCPHDRLEN_MASK	0x000F
++#define TPD_TCPHDRLEN_SHIFT	14
++#define TPD_HDRFLAG_MASK	0x0001
++#define TPD_HDRFLAG_SHIFT	18
++#define TPD_MSS_MASK		0x1FFF
++#define TPD_MSS_SHIFT		19
++
++/* tpd word 3 bits 16:31 if custom csum enabled */
++#define TPD_PLOADOFFSET_MASK	0x00FF
++#define TPD_PLOADOFFSET_SHIFT	16
++#define TPD_CCSUMOFFSET_MASK	0x00FF
++#define TPD_CCSUMOFFSET_SHIFT	24
++
++struct tx_packet_desc {
++	__le64 buffer_addr;
++	__le32 word2;
++	__le32 word3;
++};
++
++/* DMA Order Settings */
++enum atl1_dma_order {
++	atl1_dma_ord_in = 1,
++	atl1_dma_ord_enh = 2,
++	atl1_dma_ord_out = 4
++};
++
++enum atl1_dma_rcb {
++	atl1_rcb_64 = 0,
++	atl1_rcb_128 = 1
++};
++
++enum atl1_dma_req_block {
++	atl1_dma_req_128 = 0,
++	atl1_dma_req_256 = 1,
++	atl1_dma_req_512 = 2,
++	atl1_dma_req_1024 = 3,
++	atl1_dma_req_2048 = 4,
++	atl1_dma_req_4096 = 5
++};
++
++#define ATL1_MAX_INTR		3
++#define ATL1_MAX_TX_BUF_LEN	0x3000	/* 12288 bytes */
++
++#define ATL1_DEFAULT_TPD	256
++#define ATL1_MAX_TPD		1024
++#define ATL1_MIN_TPD		64
++#define ATL1_DEFAULT_RFD	512
++#define ATL1_MIN_RFD		128
++#define ATL1_MAX_RFD		2048
++#define ATL1_REG_COUNT		1538
++
++#define ATL1_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
++#define ATL1_RFD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_free_desc)
++#define ATL1_TPD_DESC(R, i)	ATL1_GET_DESC(R, i, struct tx_packet_desc)
++#define ATL1_RRD_DESC(R, i)	ATL1_GET_DESC(R, i, struct rx_return_desc)
++
++/*
++ * atl1_ring_header represents a single, contiguous block of DMA space
++ * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
++ * message blocks (cmb, smb) described below
++ */
++struct atl1_ring_header {
++	void *desc;		/* virtual address */
++	dma_addr_t dma;		/* physical address*/
++	unsigned int size;	/* length in bytes */
++};
++
++/*
++ * atl1_buffer is wrapper around a pointer to a socket buffer
++ * so a DMA handle can be stored along with the skb
++ */
++struct atl1_buffer {
++	struct sk_buff *skb;	/* socket buffer */
++	u16 length;		/* rx buffer length */
++	u16 alloced;		/* 1 if skb allocated */
++	dma_addr_t dma;
++};
++
++/* transmit packet descriptor (tpd) ring */
++struct atl1_tpd_ring {
++	void *desc;		/* descriptor ring virtual address */
++	dma_addr_t dma;		/* descriptor ring physical address */
++	u16 size;		/* descriptor ring length in bytes */
++	u16 count;		/* number of descriptors in the ring */
++	u16 hw_idx;		/* hardware index */
++	atomic_t next_to_clean;
++	atomic_t next_to_use;
++	struct atl1_buffer *buffer_info;
++};
++
++/* receive free descriptor (rfd) ring */
++struct atl1_rfd_ring {
++	void *desc;		/* descriptor ring virtual address */
++	dma_addr_t dma;		/* descriptor ring physical address */
++	u16 size;		/* descriptor ring length in bytes */
++	u16 count;		/* number of descriptors in the ring */
++	atomic_t next_to_use;
++	u16 next_to_clean;
++	struct atl1_buffer *buffer_info;
++};
++
++/* receive return descriptor (rrd) ring */
++struct atl1_rrd_ring {
++	void *desc;		/* descriptor ring virtual address */
++	dma_addr_t dma;		/* descriptor ring physical address */
++	unsigned int size;	/* descriptor ring length in bytes */
++	u16 count;		/* number of descriptors in the ring */
++	u16 next_to_use;
++	atomic_t next_to_clean;
++};
++
++/* coalescing message block (cmb) */
++struct atl1_cmb {
++	struct coals_msg_block *cmb;
++	dma_addr_t dma;
++};
++
++/* statistics message block (smb) */
++struct atl1_smb {
++	struct stats_msg_block *smb;
++	dma_addr_t dma;
++};
++
++/* Statistics counters */
++struct atl1_sft_stats {
++	u64 rx_packets;
++	u64 tx_packets;
++	u64 rx_bytes;
++	u64 tx_bytes;
++	u64 multicast;
++	u64 collisions;
++	u64 rx_errors;
++	u64 rx_length_errors;
++	u64 rx_crc_errors;
++	u64 rx_frame_errors;
++	u64 rx_fifo_errors;
++	u64 rx_missed_errors;
++	u64 tx_errors;
++	u64 tx_fifo_errors;
++	u64 tx_aborted_errors;
++	u64 tx_window_errors;
++	u64 tx_carrier_errors;
++	u64 tx_pause;		/* TX pause frames */
++	u64 excecol;		/* TX packets w/ excessive collisions */
++	u64 deffer;		/* TX packets deferred */
++	u64 scc;		/* packets TX after a single collision */
++	u64 mcc;		/* packets TX after multiple collisions */
++	u64 latecol;		/* TX packets w/ late collisions */
++	u64 tx_underun;		/* TX packets aborted due to TX FIFO underrun
++				 * or TRD FIFO underrun */
++	u64 tx_trunc;		/* TX packets truncated due to size > MTU */
++	u64 rx_pause;		/* num Pause packets received. */
++	u64 rx_rrd_ov;
++	u64 rx_trunc;
++};
++
++/* hardware structure */
++struct atl1_hw {
++	u8 __iomem *hw_addr;
++	struct atl1_adapter *back;
++	enum atl1_dma_order dma_ord;
++	enum atl1_dma_rcb rcb_value;
++	enum atl1_dma_req_block dmar_block;
++	enum atl1_dma_req_block dmaw_block;
++	u8 preamble_len;
++	u8 max_retry;
++	u8 jam_ipg;		/* IPG to start JAM for collision based flow
++				 * control in half-duplex mode. In units of
++				 * 8-bit time */
++	u8 ipgt;		/* Desired back to back inter-packet gap.
++				 * The default is 96-bit time */
++	u8 min_ifg;		/* Minimum number of IFG to enforce in between
++				 * receive frames. Frame gap below such IFP
++				 * is dropped */
++	u8 ipgr1;		/* 64bit Carrier-Sense window */
++	u8 ipgr2;		/* 96-bit IPG window */
++	u8 tpd_burst;		/* Number of TPD to prefetch in cache-aligned
++				 * burst. Each TPD is 16 bytes long */
++	u8 rfd_burst;		/* Number of RFD to prefetch in cache-aligned
++				 * burst. Each RFD is 12 bytes long */
++	u8 rfd_fetch_gap;
++	u8 rrd_burst;		/* Threshold number of RRDs that can be retired
++				 * in a burst. Each RRD is 16 bytes long */
++	u8 tpd_fetch_th;
++	u8 tpd_fetch_gap;
++	u16 tx_jumbo_task_th;
++	u16 txf_burst;		/* Number of data bytes to read in a cache-
++				 * aligned burst. Each SRAM entry is 8 bytes */
++	u16 rx_jumbo_th;	/* Jumbo packet size for non-VLAN packet. VLAN
++				 * packets should add 4 bytes */
++	u16 rx_jumbo_lkah;
++	u16 rrd_ret_timer;	/* RRD retirement timer. Decrement by 1 after
++				 * every 512ns passes. */
++	u16 lcol;		/* Collision Window */
++
++	u16 cmb_tpd;
++	u16 cmb_rrd;
++	u16 cmb_rx_timer;
++	u16 cmb_tx_timer;
++	u32 smb_timer;
++	u16 media_type;
++	u16 autoneg_advertised;
++
++	u16 mii_autoneg_adv_reg;
++	u16 mii_1000t_ctrl_reg;
++
++	u32 max_frame_size;
++	u32 min_frame_size;
++
++	u16 dev_rev;
++
++	/* spi flash */
++	u8 flash_vendor;
++
++	u8 mac_addr[ETH_ALEN];
++	u8 perm_mac_addr[ETH_ALEN];
++
++	bool phy_configured;
++};
++
++struct atl1_adapter {
++	struct net_device *netdev;
++	struct pci_dev *pdev;
++	struct net_device_stats net_stats;
++	struct atl1_sft_stats soft_stats;
++	struct vlan_group *vlgrp;
++	u32 rx_buffer_len;
++	u32 wol;
++	u16 link_speed;
++	u16 link_duplex;
++	spinlock_t lock;
++	struct work_struct tx_timeout_task;
++	struct work_struct link_chg_task;
++	struct work_struct pcie_dma_to_rst_task;
++	struct timer_list watchdog_timer;
++	struct timer_list phy_config_timer;
++	bool phy_timer_pending;
++
++	/* all descriptor rings' memory */
++	struct atl1_ring_header ring_header;
++
++	/* TX */
++	struct atl1_tpd_ring tpd_ring;
++	spinlock_t mb_lock;
++
++	/* RX */
++	struct atl1_rfd_ring rfd_ring;
++	struct atl1_rrd_ring rrd_ring;
++	u64 hw_csum_err;
++	u64 hw_csum_good;
++	u32 msg_enable;
++	u16 imt;		/* interrupt moderator timer (2us resolution) */
++	u16 ict;		/* interrupt clear timer (2us resolution */
++	struct mii_if_info mii;	/* MII interface info */
++
++	u32 bd_number;		/* board number */
++	bool pci_using_64;
++	struct atl1_hw hw;
++	struct atl1_smb smb;
++	struct atl1_cmb cmb;
++};
++
++#endif /* ATL1_H */
+diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
+new file mode 100644
+index 0000000..f06b854
+--- /dev/null
++++ b/drivers/net/atlx/atlx.c
+@@ -0,0 +1,256 @@
++/* atlx.c -- common functions for Attansic network drivers
++ *
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
++ *
++ * Derived from Intel e1000 driver
++ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59
++ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
++ */
++
++/* Including this file like a header is a temporary hack, I promise. -- CHS */
++#ifndef ATLX_C
++#define ATLX_C
++
++#include <linux/device.h>
++#include <linux/errno.h>
++#include <linux/etherdevice.h>
++#include <linux/if.h>
++#include <linux/netdevice.h>
++#include <linux/socket.h>
++#include <linux/sockios.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
++
++#include "atlx.h"
++
++static struct atlx_spi_flash_dev flash_table[] = {
++/*	MFR_NAME  WRSR  READ  PRGM  WREN  WRDI  RDSR  RDID  SEC_ERS CHIP_ERS */
++	{"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52,   0x62},
++	{"SST",   0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20,   0x60},
++	{"ST",    0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8,   0xC7},
++};
++
++static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
++{
++	switch (cmd) {
++	case SIOCGMIIPHY:
++	case SIOCGMIIREG:
++	case SIOCSMIIREG:
++		return atlx_mii_ioctl(netdev, ifr, cmd);
++	default:
++		return -EOPNOTSUPP;
++	}
++}
++
++/*
++ * atlx_set_mac - Change the Ethernet Address of the NIC
++ * @netdev: network interface device structure
++ * @p: pointer to an address structure
++ *
++ * Returns 0 on success, negative on failure
++ */
++static int atlx_set_mac(struct net_device *netdev, void *p)
++{
++	struct atlx_adapter *adapter = netdev_priv(netdev);
++	struct sockaddr *addr = p;
++
++	if (netif_running(netdev))
++		return -EBUSY;
++
++	if (!is_valid_ether_addr(addr->sa_data))
++		return -EADDRNOTAVAIL;
++
++	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
++	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
++
++	atlx_set_mac_addr(&adapter->hw);
++	return 0;
++}
++
++static void atlx_check_for_link(struct atlx_adapter *adapter)
++{
++	struct net_device *netdev = adapter->netdev;
++	u16 phy_data = 0;
++
++	spin_lock(&adapter->lock);
++	adapter->phy_timer_pending = false;
++	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
++	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
++	spin_unlock(&adapter->lock);
++
++	/* notify upper layer link down ASAP */
++	if (!(phy_data & BMSR_LSTATUS)) {
++		/* Link Down */
++		if (netif_carrier_ok(netdev)) {
++			/* old link state: Up */
++			dev_info(&adapter->pdev->dev, "%s link is down\n",
++				netdev->name);
++			adapter->link_speed = SPEED_0;
++			netif_carrier_off(netdev);
++			netif_stop_queue(netdev);
++		}
++	}
++	schedule_work(&adapter->link_chg_task);
++}
++
++/*
++ * atlx_set_multi - Multicast and Promiscuous mode set
++ * @netdev: network interface device structure
++ *
++ * The set_multi entry point is called whenever the multicast address
++ * list or the network interface flags are updated.  This routine is
++ * responsible for configuring the hardware for proper multicast,
++ * promiscuous mode, and all-multi behavior.
++ */
++static void atlx_set_multi(struct net_device *netdev)
++{
++	struct atlx_adapter *adapter = netdev_priv(netdev);
++	struct atlx_hw *hw = &adapter->hw;
++	struct dev_mc_list *mc_ptr;
++	u32 rctl;
++	u32 hash_value;
++
++	/* Check for Promiscuous and All Multicast modes */
++	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
++	if (netdev->flags & IFF_PROMISC)
++		rctl |= MAC_CTRL_PROMIS_EN;
++	else if (netdev->flags & IFF_ALLMULTI) {
++		rctl |= MAC_CTRL_MC_ALL_EN;
++		rctl &= ~MAC_CTRL_PROMIS_EN;
++	} else
++		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
++
++	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
++
++	/* clear the old settings from the multicast hash table */
++	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
++	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
++
++	/* compute mc addresses' hash value ,and put it into hash table */
++	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
++		hash_value = atlx_hash_mc_addr(hw, mc_ptr->dmi_addr);
++		atlx_hash_set(hw, hash_value);
++	}
++}
++
++/*
++ * atlx_irq_enable - Enable default interrupt generation settings
++ * @adapter: board private structure
++ */
++static void atlx_irq_enable(struct atlx_adapter *adapter)
++{
++	iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
++	ioread32(adapter->hw.hw_addr + REG_IMR);
++}
++
++/*
++ * atlx_irq_disable - Mask off interrupt generation on the NIC
++ * @adapter: board private structure
++ */
++static void atlx_irq_disable(struct atlx_adapter *adapter)
++{
++	iowrite32(0, adapter->hw.hw_addr + REG_IMR);
++	ioread32(adapter->hw.hw_addr + REG_IMR);
++	synchronize_irq(adapter->pdev->irq);
++}
++
++static void atlx_clear_phy_int(struct atlx_adapter *adapter)
++{
++	u16 phy_data;
++	unsigned long flags;
++
++	spin_lock_irqsave(&adapter->lock, flags);
++	atlx_read_phy_reg(&adapter->hw, 19, &phy_data);
++	spin_unlock_irqrestore(&adapter->lock, flags);
++}
++
++/*
++ * atlx_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 *atlx_get_stats(struct net_device *netdev)
++{
++	struct atlx_adapter *adapter = netdev_priv(netdev);
++	return &adapter->net_stats;
++}
++
++/*
++ * atlx_tx_timeout - Respond to a Tx Hang
++ * @netdev: network interface device structure
++ */
++static void atlx_tx_timeout(struct net_device *netdev)
++{
++	struct atlx_adapter *adapter = netdev_priv(netdev);
++	/* Do the reset outside of interrupt context */
++	schedule_work(&adapter->tx_timeout_task);
++}
++
++/*
++ * atlx_link_chg_task - deal with link change event Out of interrupt context
++ */
++static void atlx_link_chg_task(struct work_struct *work)
++{
++	struct atlx_adapter *adapter;
++	unsigned long flags;
++
++	adapter = container_of(work, struct atlx_adapter, link_chg_task);
++
++	spin_lock_irqsave(&adapter->lock, flags);
++	atlx_check_link(adapter);
++	spin_unlock_irqrestore(&adapter->lock, flags);
++}
++
++static void atlx_vlan_rx_register(struct net_device *netdev,
++	struct vlan_group *grp)
++{
++	struct atlx_adapter *adapter = netdev_priv(netdev);
++	unsigned long flags;
++	u32 ctrl;
++
++	spin_lock_irqsave(&adapter->lock, flags);
++	/* atlx_irq_disable(adapter); FIXME: confirm/remove */
++	adapter->vlgrp = grp;
++
++	if (grp) {
++		/* enable VLAN tag insert/strip */
++		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
++		ctrl |= MAC_CTRL_RMV_VLAN;
++		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
++	} else {
++		/* disable VLAN tag insert/strip */
++		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
++		ctrl &= ~MAC_CTRL_RMV_VLAN;
++		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
++	}
++
++	/* atlx_irq_enable(adapter); FIXME */
++	spin_unlock_irqrestore(&adapter->lock, flags);
++}
++
++static void atlx_restore_vlan(struct atlx_adapter *adapter)
++{
++	atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
++}
++
++#endif /* ATLX_C */
+diff --git a/drivers/net/atlx/atlx.h b/drivers/net/atlx/atlx.h
+new file mode 100644
+index 0000000..3be7c09
+--- /dev/null
++++ b/drivers/net/atlx/atlx.h
+@@ -0,0 +1,506 @@
++/* atlx_hw.h -- common hardware definitions for Attansic network drivers
++ *
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
++ *
++ * Derived from Intel e1000 driver
++ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59
++ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
++ */
++
++#ifndef ATLX_H
++#define ATLX_H
++
++#include <linux/module.h>
++#include <linux/types.h>
++
++#define ATLX_DRIVER_VERSION "2.1.1"
++MODULE_AUTHOR("Xiong Huang <xiong.huang at atheros.com>, \
++	Chris Snook <csnook at redhat.com>, Jay Cliburn <jcliburn at gmail.com>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(ATLX_DRIVER_VERSION);
++
++#define ATLX_ERR_PHY			2
++#define ATLX_ERR_PHY_SPEED		7
++#define ATLX_ERR_PHY_RES		8
++
++#define SPEED_0				0xffff
++#define SPEED_10			10
++#define SPEED_100			100
++#define SPEED_1000			1000
++#define HALF_DUPLEX			1
++#define FULL_DUPLEX			2
++
++#define MEDIA_TYPE_AUTO_SENSOR		0
++
++/* register definitions */
++#define REG_PM_CTRLSTAT			0x44
++
++#define REG_PCIE_CAP_LIST		0x58
++
++#define REG_VPD_CAP			0x6C
++#define VPD_CAP_ID_MASK			0xFF
++#define VPD_CAP_ID_SHIFT		0
++#define VPD_CAP_NEXT_PTR_MASK		0xFF
++#define VPD_CAP_NEXT_PTR_SHIFT		8
++#define VPD_CAP_VPD_ADDR_MASK		0x7FFF
++#define VPD_CAP_VPD_ADDR_SHIFT		16
++#define VPD_CAP_VPD_FLAG		0x80000000
++
++#define REG_VPD_DATA			0x70
++
++#define REG_SPI_FLASH_CTRL		0x200
++#define SPI_FLASH_CTRL_STS_NON_RDY	0x1
++#define SPI_FLASH_CTRL_STS_WEN		0x2
++#define SPI_FLASH_CTRL_STS_WPEN		0x80
++#define SPI_FLASH_CTRL_DEV_STS_MASK	0xFF
++#define SPI_FLASH_CTRL_DEV_STS_SHIFT	0
++#define SPI_FLASH_CTRL_INS_MASK		0x7
++#define SPI_FLASH_CTRL_INS_SHIFT	8
++#define SPI_FLASH_CTRL_START		0x800
++#define SPI_FLASH_CTRL_EN_VPD		0x2000
++#define SPI_FLASH_CTRL_LDSTART		0x8000
++#define SPI_FLASH_CTRL_CS_HI_MASK	0x3
++#define SPI_FLASH_CTRL_CS_HI_SHIFT	16
++#define SPI_FLASH_CTRL_CS_HOLD_MASK	0x3
++#define SPI_FLASH_CTRL_CS_HOLD_SHIFT	18
++#define SPI_FLASH_CTRL_CLK_LO_MASK	0x3
++#define SPI_FLASH_CTRL_CLK_LO_SHIFT	20
++#define SPI_FLASH_CTRL_CLK_HI_MASK	0x3
++#define SPI_FLASH_CTRL_CLK_HI_SHIFT	22
++#define SPI_FLASH_CTRL_CS_SETUP_MASK	0x3
++#define SPI_FLASH_CTRL_CS_SETUP_SHIFT	24
++#define SPI_FLASH_CTRL_EROM_PGSZ_MASK	0x3
++#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT	26
++#define SPI_FLASH_CTRL_WAIT_READY	0x10000000
++
++#define REG_SPI_ADDR			0x204
++
++#define REG_SPI_DATA			0x208
++
++#define REG_SPI_FLASH_CONFIG		0x20C
++#define SPI_FLASH_CONFIG_LD_ADDR_MASK	0xFFFFFF
++#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT	0
++#define SPI_FLASH_CONFIG_VPD_ADDR_MASK	0x3
++#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT	24
++#define SPI_FLASH_CONFIG_LD_EXIST	0x4000000
++
++#define REG_SPI_FLASH_OP_PROGRAM	0x210
++#define REG_SPI_FLASH_OP_SC_ERASE	0x211
++#define REG_SPI_FLASH_OP_CHIP_ERASE	0x212
++#define REG_SPI_FLASH_OP_RDID		0x213
++#define REG_SPI_FLASH_OP_WREN		0x214
++#define REG_SPI_FLASH_OP_RDSR		0x215
++#define REG_SPI_FLASH_OP_WRSR		0x216
++#define REG_SPI_FLASH_OP_READ		0x217
++
++#define REG_TWSI_CTRL			0x218
++#define TWSI_CTRL_LD_OFFSET_MASK	0xFF
++#define TWSI_CTRL_LD_OFFSET_SHIFT	0
++#define TWSI_CTRL_LD_SLV_ADDR_MASK	0x7
++#define TWSI_CTRL_LD_SLV_ADDR_SHIFT	8
++#define TWSI_CTRL_SW_LDSTART		0x800
++#define TWSI_CTRL_HW_LDSTART		0x1000
++#define TWSI_CTRL_SMB_SLV_ADDR_MASK	0x7F
++#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT	15
++#define TWSI_CTRL_LD_EXIST		0x400000
++#define TWSI_CTRL_READ_FREQ_SEL_MASK	0x3
++#define TWSI_CTRL_READ_FREQ_SEL_SHIFT	23
++#define TWSI_CTRL_FREQ_SEL_100K		0
++#define TWSI_CTRL_FREQ_SEL_200K		1
++#define TWSI_CTRL_FREQ_SEL_300K		2
++#define TWSI_CTRL_FREQ_SEL_400K		3
++#define TWSI_CTRL_SMB_SLV_ADDR		/* FIXME: define or remove */
++#define TWSI_CTRL_WRITE_FREQ_SEL_MASK	0x3
++#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT	24
++
++#define REG_PCIE_DEV_MISC_CTRL			0x21C
++#define PCIE_DEV_MISC_CTRL_EXT_PIPE		0x2
++#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS		0x1
++#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST		0x4
++#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN	0x8
++#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN	0x10
++
++#define REG_PCIE_PHYMISC		0x1000
++#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
++
++#define REG_PCIE_DLL_TX_CTRL1		0x1104
++#define PCIE_DLL_TX_CTRL1_SEL_NOR_CLK	0x400
++#define PCIE_DLL_TX_CTRL1_DEF		0x568
++
++#define REG_LTSSM_TEST_MODE		0x12FC
++#define LTSSM_TEST_MODE_DEF		0x6500
++
++/* Master Control Register */
++#define REG_MASTER_CTRL			0x1400
++#define MASTER_CTRL_SOFT_RST		0x1
++#define MASTER_CTRL_MTIMER_EN		0x2
++#define MASTER_CTRL_ITIMER_EN		0x4
++#define MASTER_CTRL_MANUAL_INT		0x8
++#define MASTER_CTRL_REV_NUM_SHIFT	16
++#define MASTER_CTRL_REV_NUM_MASK	0xFF
++#define MASTER_CTRL_DEV_ID_SHIFT	24
++#define MASTER_CTRL_DEV_ID_MASK		0xFF
++
++/* Timer Initial Value Register */
++#define REG_MANUAL_TIMER_INIT		0x1404
++
++/* IRQ Moderator Timer Initial Value Register */
++#define REG_IRQ_MODU_TIMER_INIT		0x1408
++
++#define REG_PHY_ENABLE			0x140C
++
++/* IRQ Anti-Lost Timer Initial Value Register */
++#define REG_CMBDISDMA_TIMER		0x140E
++
++/* Block IDLE Status Register */
++#define REG_IDLE_STATUS			0x1410
++
++/* MDIO Control Register */
++#define REG_MDIO_CTRL			0x1414
++#define MDIO_DATA_MASK			0xFFFF
++#define MDIO_DATA_SHIFT			0
++#define MDIO_REG_ADDR_MASK		0x1F
++#define MDIO_REG_ADDR_SHIFT		16
++#define MDIO_RW				0x200000
++#define MDIO_SUP_PREAMBLE		0x400000
++#define MDIO_START			0x800000
++#define MDIO_CLK_SEL_SHIFT		24
++#define MDIO_CLK_25_4			0
++#define MDIO_CLK_25_6			2
++#define MDIO_CLK_25_8			3
++#define MDIO_CLK_25_10			4
++#define MDIO_CLK_25_14			5
++#define MDIO_CLK_25_20			6
++#define MDIO_CLK_25_28			7
++#define MDIO_BUSY			0x8000000
++
++/* MII PHY Status Register */
++#define REG_PHY_STATUS			0x1418
++
++/* BIST Control and Status Register0 (for the Packet Memory) */
++#define REG_BIST0_CTRL			0x141C
++#define BIST0_NOW			0x1
++#define BIST0_SRAM_FAIL			0x2
++#define BIST0_FUSE_FLAG			0x4
++#define REG_BIST1_CTRL			0x1420
++#define BIST1_NOW			0x1
++#define BIST1_SRAM_FAIL			0x2
++#define BIST1_FUSE_FLAG			0x4
++
++/* SerDes Lock Detect Control and Status Register */
++#define REG_SERDES_LOCK			0x1424
++#define SERDES_LOCK_DETECT		1
++#define SERDES_LOCK_DETECT_EN		2
++
++/* MAC Control Register */
++#define REG_MAC_CTRL			0x1480
++#define MAC_CTRL_TX_EN			1
++#define MAC_CTRL_RX_EN			2
++#define MAC_CTRL_TX_FLOW		4
++#define MAC_CTRL_RX_FLOW		8
++#define MAC_CTRL_LOOPBACK		0x10
++#define MAC_CTRL_DUPLX			0x20
++#define MAC_CTRL_ADD_CRC		0x40
++#define MAC_CTRL_PAD			0x80
++#define MAC_CTRL_LENCHK			0x100
++#define MAC_CTRL_HUGE_EN		0x200
++#define MAC_CTRL_PRMLEN_SHIFT		10
++#define MAC_CTRL_PRMLEN_MASK		0xF
++#define MAC_CTRL_RMV_VLAN		0x4000
++#define MAC_CTRL_PROMIS_EN		0x8000
++#define MAC_CTRL_MC_ALL_EN		0x2000000
++#define MAC_CTRL_BC_EN			0x4000000
++
++/* MAC IPG/IFG Control Register */
++#define REG_MAC_IPG_IFG			0x1484
++#define MAC_IPG_IFG_IPGT_SHIFT		0
++#define MAC_IPG_IFG_IPGT_MASK		0x7F
++#define MAC_IPG_IFG_MIFG_SHIFT		8
++#define MAC_IPG_IFG_MIFG_MASK		0xFF
++#define MAC_IPG_IFG_IPGR1_SHIFT		16
++#define MAC_IPG_IFG_IPGR1_MASK		0x7F
++#define MAC_IPG_IFG_IPGR2_SHIFT		24
++#define MAC_IPG_IFG_IPGR2_MASK		0x7F
++
++/* MAC STATION ADDRESS */
++#define REG_MAC_STA_ADDR		0x1488
++
++/* Hash table for multicast address */
++#define REG_RX_HASH_TABLE		0x1490
++
++/* MAC Half-Duplex Control Register */
++#define REG_MAC_HALF_DUPLX_CTRL			0x1498
++#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT		0
++#define MAC_HALF_DUPLX_CTRL_LCOL_MASK		0x3FF
++#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT		12
++#define MAC_HALF_DUPLX_CTRL_RETRY_MASK		0xF
++#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN		0x10000
++#define MAC_HALF_DUPLX_CTRL_NO_BACK_C		0x20000
++#define MAC_HALF_DUPLX_CTRL_NO_BACK_P		0x40000
++#define MAC_HALF_DUPLX_CTRL_ABEBE		0x80000
++#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT		20
++#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK		0xF
++#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT	24
++#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK		0xF
++
++/* Maximum Frame Length Control Register */
++#define REG_MTU				0x149C
++
++/* Wake-On-Lan control register */
++#define REG_WOL_CTRL			0x14A0
++#define WOL_PATTERN_EN			0x1
++#define WOL_PATTERN_PME_EN		0x2
++#define WOL_MAGIC_EN			0x4
++#define WOL_MAGIC_PME_EN		0x8
++#define WOL_LINK_CHG_EN			0x10
++#define WOL_LINK_CHG_PME_EN		0x20
++#define WOL_PATTERN_ST			0x100
++#define WOL_MAGIC_ST			0x200
++#define WOL_LINKCHG_ST			0x400
++#define WOL_PT0_EN			0x10000
++#define WOL_PT1_EN			0x20000
++#define WOL_PT2_EN			0x40000
++#define WOL_PT3_EN			0x80000
++#define WOL_PT4_EN			0x100000
++#define WOL_PT0_MATCH			0x1000000
++#define WOL_PT1_MATCH			0x2000000
++#define WOL_PT2_MATCH			0x4000000
++#define WOL_PT3_MATCH			0x8000000
++#define WOL_PT4_MATCH			0x10000000
++
++/* Internal SRAM Partition Register, high 32 bits */
++#define REG_SRAM_RFD_ADDR		0x1500
++
++/* Descriptor Control register, high 32 bits */
++#define REG_DESC_BASE_ADDR_HI		0x1540
++
++/* Interrupt Status Register */
++#define REG_ISR				0x1600
++#define ISR_UR_DETECTED			0x1000000
++#define ISR_FERR_DETECTED		0x2000000
++#define ISR_NFERR_DETECTED		0x4000000
++#define ISR_CERR_DETECTED		0x8000000
++#define ISR_PHY_LINKDOWN		0x10000000
++#define ISR_DIS_INT			0x80000000
++
++/* Interrupt Mask Register */
++#define REG_IMR				0x1604
++
++#define REG_RFD_RRD_IDX			0x1800
++#define REG_TPD_IDX			0x1804
++
++/* MII definitions */
++
++/* PHY Common Register */
++#define MII_ATLX_CR			0x09
++#define MII_ATLX_SR			0x0A
++#define MII_ATLX_ESR			0x0F
++#define MII_ATLX_PSCR			0x10
++#define MII_ATLX_PSSR			0x11
++
++/* PHY Control Register */
++#define MII_CR_SPEED_SELECT_MSB		0x0040	/* bits 6,13: 10=1000, 01=100,
++						 * 00=10
++						 */
++#define MII_CR_COLL_TEST_ENABLE		0x0080	/* Collision test enable */
++#define MII_CR_FULL_DUPLEX		0x0100	/* FDX =1, half duplex =0 */
++#define MII_CR_RESTART_AUTO_NEG		0x0200	/* Restart auto negotiation */
++#define MII_CR_ISOLATE			0x0400	/* Isolate PHY from MII */
++#define MII_CR_POWER_DOWN		0x0800	/* Power down */
++#define MII_CR_AUTO_NEG_EN		0x1000	/* Auto Neg Enable */
++#define MII_CR_SPEED_SELECT_LSB		0x2000	/* bits 6,13: 10=1000, 01=100,
++						 * 00=10
++						 */
++#define MII_CR_LOOPBACK			0x4000	/* 0 = normal, 1 = loopback */
++#define MII_CR_RESET			0x8000	/* 0 = normal, 1 = PHY reset */
++#define MII_CR_SPEED_MASK		0x2040
++#define MII_CR_SPEED_1000		0x0040
++#define MII_CR_SPEED_100		0x2000
++#define MII_CR_SPEED_10			0x0000
++
++/* PHY Status Register */
++#define MII_SR_EXTENDED_CAPS		0x0001	/* Ext 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 stat info in Reg 0x0F */
++#define MII_SR_100T2_HD_CAPS		0x0200	/* 100T2 Half Duplex Capable */
++#define MII_SR_100T2_FD_CAPS		0x0400	/* 100T2 Full Duplex Capable */
++#define MII_SR_10T_HD_CAPS		0x0800	/* 10T   Half Duplex Capable */
++#define MII_SR_10T_FD_CAPS		0x1000	/* 10T   Full Duplex Capable */
++#define MII_SR_100X_HD_CAPS		0x2000	/* 100X  Half Duplex Capable */
++#define MII_SR_100X_FD_CAPS		0x4000	/* 100X  Full Duplex Capable */
++#define MII_SR_100T4_CAPS		0x8000	/* 100T4 Capable */
++
++/* Link partner ability register */
++#define MII_LPA_SLCT			0x001f	/* Same as advertise selector */
++#define MII_LPA_10HALF			0x0020	/* Can do 10mbps half-duplex */
++#define MII_LPA_10FULL			0x0040	/* Can do 10mbps full-duplex */
++#define MII_LPA_100HALF			0x0080	/* Can do 100mbps half-duplex */
++#define MII_LPA_100FULL			0x0100	/* Can do 100mbps full-duplex */
++#define MII_LPA_100BASE4		0x0200	/* 100BASE-T4 */
++#define MII_LPA_PAUSE			0x0400	/* PAUSE */
++#define MII_LPA_ASYPAUSE		0x0800	/* Asymmetrical PAUSE */
++#define MII_LPA_RFAULT			0x2000	/* Link partner faulted */
++#define MII_LPA_LPACK			0x4000	/* Link partner acked us */
++#define MII_LPA_NPAGE			0x8000	/* Next page bit */
++
++/* Autoneg Advertisement Register */
++#define MII_AR_SELECTOR_FIELD		0x0001	/* IEEE 802.3 CSMA/CD */
++#define MII_AR_10T_HD_CAPS		0x0020	/* 10T   Half Duplex Capable */
++#define MII_AR_10T_FD_CAPS		0x0040	/* 10T   Full Duplex Capable */
++#define MII_AR_100TX_HD_CAPS		0x0080	/* 100TX Half Duplex Capable */
++#define MII_AR_100TX_FD_CAPS		0x0100	/* 100TX Full Duplex Capable */
++#define MII_AR_100T4_CAPS		0x0200	/* 100T4 Capable */
++#define MII_AR_PAUSE			0x0400	/* Pause operation desired */
++#define MII_AR_ASM_DIR			0x0800	/* Asymmetric Pause Dir bit */
++#define MII_AR_REMOTE_FAULT		0x2000	/* Remote Fault detected */
++#define MII_AR_NEXT_PAGE		0x8000	/* Next Page ability support */
++#define MII_AR_SPEED_MASK		0x01E0
++#define MII_AR_DEFAULT_CAP_MASK		0x0DE0
++
++/* 1000BASE-T Control Register */
++#define MII_ATLX_CR_1000T_HD_CAPS	0x0100	/* Adv 1000T HD cap */
++#define MII_ATLX_CR_1000T_FD_CAPS	0x0200	/* Adv 1000T FD cap */
++#define MII_ATLX_CR_1000T_REPEATER_DTE	0x0400	/* 1=Repeater/switch device,
++						 * 0=DTE device */
++#define MII_ATLX_CR_1000T_MS_VALUE	0x0800	/* 1=Config PHY as Master,
++						 * 0=Configure PHY as Slave */
++#define MII_ATLX_CR_1000T_MS_ENABLE	0x1000	/* 1=Man Master/Slave config,
++						 * 0=Auto Master/Slave config
++						 */
++#define MII_ATLX_CR_1000T_TEST_MODE_NORMAL	0x0000	/* Normal Operation */
++#define MII_ATLX_CR_1000T_TEST_MODE_1	0x2000	/* Transmit Waveform test */
++#define MII_ATLX_CR_1000T_TEST_MODE_2	0x4000	/* Master Xmit Jitter test */
++#define MII_ATLX_CR_1000T_TEST_MODE_3	0x6000	/* Slave Xmit Jitter test */
++#define MII_ATLX_CR_1000T_TEST_MODE_4	0x8000	/* Xmitter Distortion test */
++#define MII_ATLX_CR_1000T_SPEED_MASK	0x0300
++#define MII_ATLX_CR_1000T_DEFAULT_CAP_MASK	0x0300
++
++/* 1000BASE-T Status Register */
++#define MII_ATLX_SR_1000T_LP_HD_CAPS	0x0400	/* LP is 1000T HD capable */
++#define MII_ATLX_SR_1000T_LP_FD_CAPS	0x0800	/* LP is 1000T FD capable */
++#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS	0x1000	/* Remote receiver OK */
++#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS	0x2000	/* Local receiver OK */
++#define MII_ATLX_SR_1000T_MS_CONFIG_RES		0x4000	/* 1=Local TX is Master
++							 * 0=Slave
++							 */
++#define MII_ATLX_SR_1000T_MS_CONFIG_FAULT	0x8000	/* Master/Slave config
++							 * fault */
++#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS_SHIFT	12
++#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS_SHIFT		13
++
++/* Extended Status Register */
++#define MII_ATLX_ESR_1000T_HD_CAPS	0x1000	/* 1000T HD capable */
++#define MII_ATLX_ESR_1000T_FD_CAPS	0x2000	/* 1000T FD capable */
++#define MII_ATLX_ESR_1000X_HD_CAPS	0x4000	/* 1000X HD capable */
++#define MII_ATLX_ESR_1000X_FD_CAPS	0x8000	/* 1000X FD capable */
++
++/* ATLX PHY Specific Control Register */
++#define MII_ATLX_PSCR_JABBER_DISABLE	0x0001	/* 1=Jabber Func disabled */
++#define MII_ATLX_PSCR_POLARITY_REVERSAL	0x0002	/* 1=Polarity Reversal enbld */
++#define MII_ATLX_PSCR_SQE_TEST		0x0004	/* 1=SQE Test enabled */
++#define MII_ATLX_PSCR_MAC_POWERDOWN	0x0008
++#define MII_ATLX_PSCR_CLK125_DISABLE	0x0010	/* 1=CLK125 low
++						 * 0=CLK125 toggling
++						 */
++#define MII_ATLX_PSCR_MDI_MANUAL_MODE	0x0000	/* MDI Crossover Mode bits 6:5,
++						 * Manual MDI configuration
++						 */
++#define MII_ATLX_PSCR_MDIX_MANUAL_MODE	0x0020	/* Manual MDIX configuration */
++#define MII_ATLX_PSCR_AUTO_X_1000T	0x0040	/* 1000BASE-T: Auto crossover
++						 * 100BASE-TX/10BASE-T: MDI
++						 * Mode */
++#define MII_ATLX_PSCR_AUTO_X_MODE	0x0060	/* Auto crossover enabled
++						 * all speeds.
++						 */
++#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE	0x0080	/* 1=Enable Extended
++							 * 10BASE-T distance
++							 * (Lower 10BASE-T RX
++							 * Threshold)
++							 * 0=Normal 10BASE-T RX
++							 * Threshold
++							 */
++#define MII_ATLX_PSCR_MII_5BIT_ENABLE	0x0100	/* 1=5-Bit interface in
++						 * 100BASE-TX
++						 * 0=MII interface in
++						 * 100BASE-TX
++						 */
++#define MII_ATLX_PSCR_SCRAMBLER_DISABLE	0x0200	/* 1=Scrambler dsbl */
++#define MII_ATLX_PSCR_FORCE_LINK_GOOD	0x0400	/* 1=Force link good */
++#define MII_ATLX_PSCR_ASSERT_CRS_ON_TX	0x0800	/* 1=Assert CRS on Transmit */
++#define MII_ATLX_PSCR_POLARITY_REVERSAL_SHIFT		1
++#define MII_ATLX_PSCR_AUTO_X_MODE_SHIFT			5
++#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE_SHIFT	7
++
++/* ATLX PHY Specific Status Register */
++#define MII_ATLX_PSSR_SPD_DPLX_RESOLVED	0x0800	/* 1=Speed & Duplex resolved */
++#define MII_ATLX_PSSR_DPLX		0x2000	/* 1=Duplex 0=Half Duplex */
++#define MII_ATLX_PSSR_SPEED		0xC000	/* Speed, bits 14:15 */
++#define MII_ATLX_PSSR_10MBS		0x0000	/* 00=10Mbs */
++#define MII_ATLX_PSSR_100MBS		0x4000	/* 01=100Mbs */
++#define MII_ATLX_PSSR_1000MBS		0x8000	/* 10=1000Mbs */
++
++/* PCI Command Register Bit Definitions */
++#define PCI_REG_COMMAND			0x04	/* PCI Command Register */
++#define CMD_IO_SPACE			0x0001
++#define CMD_MEMORY_SPACE		0x0002
++#define CMD_BUS_MASTER			0x0004
++
++/* Wake Up Filter Control */
++#define ATLX_WUFC_LNKC	0x00000001	/* Link Status Change Wakeup Enable */
++#define ATLX_WUFC_MAG	0x00000002	/* Magic Packet Wakeup Enable */
++#define ATLX_WUFC_EX	0x00000004	/* Directed Exact Wakeup Enable */
++#define ATLX_WUFC_MC	0x00000008	/* Multicast Wakeup Enable */
++#define ATLX_WUFC_BC	0x00000010	/* Broadcast Wakeup Enable */
++
++#define ADVERTISE_10_HALF		0x0001
++#define ADVERTISE_10_FULL		0x0002
++#define ADVERTISE_100_HALF		0x0004
++#define ADVERTISE_100_FULL		0x0008
++#define ADVERTISE_1000_HALF		0x0010
++#define ADVERTISE_1000_FULL		0x0020
++#define AUTONEG_ADVERTISE_10_100_ALL	0x000F	/* All 10/100 speeds */
++#define AUTONEG_ADVERTISE_10_ALL	0x0003	/* 10Mbps Full & Half speeds */
++
++#define PHY_AUTO_NEG_TIME		45	/* 4.5 Seconds */
++#define PHY_FORCE_TIME			20	/* 2.0 Seconds */
++
++/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA */
++#define EEPROM_SUM			0xBABA
++#define NODE_ADDRESS_SIZE		6
++
++struct atlx_spi_flash_dev {
++	const char *manu_name;	/* manufacturer id */
++	/* op-code */
++	u8 cmd_wrsr;
++	u8 cmd_read;
++	u8 cmd_program;
++	u8 cmd_wren;
++	u8 cmd_wrdi;
++	u8 cmd_rdsr;
++	u8 cmd_rdid;
++	u8 cmd_sector_erase;
++	u8 cmd_chip_erase;
++};
++
++#endif /* ATLX_H */
+diff --git a/drivers/net/atp.c b/drivers/net/atp.c
+index 62f09e5..3d44333 100644
+--- a/drivers/net/atp.c
++++ b/drivers/net/atp.c
+@@ -378,8 +378,8 @@ static void __init get_node_ID(struct net_device *dev)
+ 		sa_offset = 15;
+ 
+ 	for (i = 0; i < 3; i++)
+-		((u16 *)dev->dev_addr)[i] =
+-			be16_to_cpu(eeprom_op(ioaddr, EE_READ(sa_offset + i)));
++		((__be16 *)dev->dev_addr)[i] =
++			cpu_to_be16(eeprom_op(ioaddr, EE_READ(sa_offset + i)));
+ 
+ 	write_reg(ioaddr, CMR2, CMR2_NULL);
+ }
+diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
+index 504b7ce..3634b5f 100644
+--- a/drivers/net/au1000_eth.c
++++ b/drivers/net/au1000_eth.c
+@@ -701,7 +701,7 @@ static struct net_device * au1000_probe(int port_num)
+ 	aup->mii_bus.write = mdiobus_write;
+ 	aup->mii_bus.reset = mdiobus_reset;
+ 	aup->mii_bus.name = "au1000_eth_mii";
+-	aup->mii_bus.id = aup->mac_id;
++	snprintf(aup->mii_bus.id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
+ 	aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ 	for(i = 0; i < PHY_MAX_ADDR; ++i)
+ 		aup->mii_bus.irq[i] = PHY_POLL;
+@@ -709,11 +709,11 @@ static struct net_device * au1000_probe(int port_num)
+ 	/* if known, set corresponding PHY IRQs */
+ #if defined(AU1XXX_PHY_STATIC_CONFIG)
+ # if defined(AU1XXX_PHY0_IRQ)
+-	if (AU1XXX_PHY0_BUSID == aup->mii_bus.id)
++	if (AU1XXX_PHY0_BUSID == aup->mac_id)
+ 		aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
+ # endif
+ # if defined(AU1XXX_PHY1_IRQ)
+-	if (AU1XXX_PHY1_BUSID == aup->mii_bus.id)
++	if (AU1XXX_PHY1_BUSID == aup->mac_id)
+ 		aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
+ # endif
+ #endif
+diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
+index 194949a..0b4adf4 100644
+--- a/drivers/net/ax88796.c
++++ b/drivers/net/ax88796.c
+@@ -1005,3 +1005,4 @@ module_exit(axdrv_exit);
+ MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
+ MODULE_AUTHOR("Ben Dooks, <ben at simtec.co.uk>");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:ax88796");
+diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
+index 26b2dd5..4fec858 100644
+--- a/drivers/net/bfin_mac.c
++++ b/drivers/net/bfin_mac.c
+@@ -47,6 +47,7 @@
+ MODULE_AUTHOR(DRV_AUTHOR);
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION(DRV_DESC);
++MODULE_ALIAS("platform:bfin_mac");
+ 
+ #if defined(CONFIG_BFIN_MAC_USE_L1)
+ # define bfin_mac_alloc(dma_handle, size)  l1_data_sram_zalloc(size)
+@@ -969,7 +970,7 @@ static int __init bf537mac_probe(struct net_device *dev)
+ 	lp->mii_bus.write = mdiobus_write;
+ 	lp->mii_bus.reset = mdiobus_reset;
+ 	lp->mii_bus.name = "bfin_mac_mdio";
+-	lp->mii_bus.id = 0;
++	snprintf(lp->mii_bus.id, MII_BUS_ID_SIZE, "0");
+ 	lp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ 	for (i = 0; i < PHY_MAX_ADDR; ++i)
+ 		lp->mii_bus.irq[i] = PHY_POLL;
+@@ -1089,8 +1090,9 @@ static struct platform_driver bfin_mac_driver = {
+ 	.resume = bfin_mac_resume,
+ 	.suspend = bfin_mac_suspend,
+ 	.driver = {
+-		   .name = DRV_NAME,
+-		   },
++		.name = DRV_NAME,
++		.owner	= THIS_MODULE,
++	},
+ };
+ 
+ static int __init bfin_mac_init(void)
+@@ -1106,3 +1108,4 @@ static void __exit bfin_mac_cleanup(void)
+ }
+ 
+ module_exit(bfin_mac_cleanup);
++
+diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
+index d16e0e1..ebb539e 100644
+--- a/drivers/net/bonding/bond_3ad.c
++++ b/drivers/net/bonding/bond_3ad.c
+@@ -2429,7 +2429,7 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac
+ 	struct slave *slave = NULL;
+ 	int ret = NET_RX_DROP;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto out;
+ 
+ 	if (!(dev->flags & IFF_MASTER))
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 3f58c3d..5a67372 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -345,7 +345,7 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct
+ 	struct arp_pkt *arp = (struct arp_pkt *)skb->data;
+ 	int res = NET_RX_DROP;
+ 
+-	if (bond_dev->nd_net != &init_net)
++	if (dev_net(bond_dev) != &init_net)
+ 		goto out;
+ 
+ 	if (!(bond_dev->flags & IFF_MASTER))
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 0f06753..6e91b4b 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -2629,7 +2629,7 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
+ 	unsigned char *arp_ptr;
+ 	__be32 sip, tip;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto out;
+ 
+ 	if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
+@@ -2646,10 +2646,7 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
+ 	if (!slave || !slave_do_arp_validate(bond, slave))
+ 		goto out_unlock;
+ 
+-	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
+-	if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+-				 (2 * dev->addr_len) +
+-				 (2 * sizeof(u32)))))
++	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
+ 		goto out_unlock;
+ 
+ 	arp = arp_hdr(skb);
+@@ -3068,8 +3065,6 @@ out:
+ 
+ #ifdef CONFIG_PROC_FS
+ 
+-#define SEQ_START_TOKEN ((void *)1)
+-
+ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+ 	struct bonding *bond = seq->private;
+@@ -3473,7 +3468,7 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
+ {
+ 	struct net_device *event_dev = (struct net_device *)ptr;
+ 
+-	if (event_dev->nd_net != &init_net)
++	if (dev_net(event_dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	dprintk("event_dev: %s, event: %lx\n",
+@@ -3511,6 +3506,9 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
+ 	struct bonding *bond, *bond_next;
+ 	struct vlan_entry *vlan, *vlan_next;
+ 
++	if (dev_net(ifa->ifa_dev->dev) != &init_net)
++		return NOTIFY_DONE;
++
+ 	list_for_each_entry_safe(bond, bond_next, &bond_dev_list, bond_list) {
+ 		if (bond->dev == event_dev) {
+ 			switch (event) {
+diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
+index 14299f8..93e1363 100644
+--- a/drivers/net/cassini.c
++++ b/drivers/net/cassini.c
+@@ -532,8 +532,7 @@ static void cas_spare_free(struct cas *cp)
+ 	/* free spare buffers */
+ 	INIT_LIST_HEAD(&list);
+ 	spin_lock(&cp->rx_spare_lock);
+-	list_splice(&cp->rx_spare_list, &list);
+-	INIT_LIST_HEAD(&cp->rx_spare_list);
++	list_splice_init(&cp->rx_spare_list, &list);
+ 	spin_unlock(&cp->rx_spare_lock);
+ 	list_for_each_safe(elem, tmp, &list) {
+ 		cas_page_free(cp, list_entry(elem, cas_page_t, list));
+@@ -546,13 +545,11 @@ static void cas_spare_free(struct cas *cp)
+ 	 * lock than used everywhere else to manipulate this list.
+ 	 */
+ 	spin_lock(&cp->rx_inuse_lock);
+-	list_splice(&cp->rx_inuse_list, &list);
+-	INIT_LIST_HEAD(&cp->rx_inuse_list);
++	list_splice_init(&cp->rx_inuse_list, &list);
+ 	spin_unlock(&cp->rx_inuse_lock);
+ #else
+ 	spin_lock(&cp->rx_spare_lock);
+-	list_splice(&cp->rx_inuse_list, &list);
+-	INIT_LIST_HEAD(&cp->rx_inuse_list);
++	list_splice_init(&cp->rx_inuse_list, &list);
+ 	spin_unlock(&cp->rx_spare_lock);
+ #endif
+ 	list_for_each_safe(elem, tmp, &list) {
+@@ -573,8 +570,7 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags)
+ 	/* make a local copy of the list */
+ 	INIT_LIST_HEAD(&list);
+ 	spin_lock(&cp->rx_inuse_lock);
+-	list_splice(&cp->rx_inuse_list, &list);
+-	INIT_LIST_HEAD(&cp->rx_inuse_list);
++	list_splice_init(&cp->rx_inuse_list, &list);
+ 	spin_unlock(&cp->rx_inuse_lock);
+ 
+ 	list_for_each_safe(elem, tmp, &list) {
+diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
+index c85194f..2b5740b 100644
+--- a/drivers/net/cpmac.c
++++ b/drivers/net/cpmac.c
+@@ -42,6 +42,7 @@
+ MODULE_AUTHOR("Eugene Konev <ejka at imfi.kspu.ru>");
+ MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:cpmac");
+ 
+ static int debug_level = 8;
+ static int dumb_switch;
+@@ -987,7 +988,7 @@ static int external_switch;
+ static int __devinit cpmac_probe(struct platform_device *pdev)
+ {
+ 	int rc, phy_id, i;
+-	int mdio_bus_id = cpmac_mii.id;
++	char *mdio_bus_id = "0";
+ 	struct resource *mem;
+ 	struct cpmac_priv *priv;
+ 	struct net_device *dev;
+@@ -1008,8 +1009,6 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
+ 		if (external_switch || dumb_switch) {
+ 			struct fixed_phy_status status = {};
+ 
+-			mdio_bus_id = 0;
+-
+ 			/*
+ 			 * FIXME: this should be in the platform code!
+ 			 * Since there is not platform code at all (that is,
+@@ -1105,6 +1104,7 @@ static int __devexit cpmac_remove(struct platform_device *pdev)
+ 
+ static struct platform_driver cpmac_driver = {
+ 	.driver.name = "cpmac",
++	.driver.owner = THIS_MODULE,
+ 	.probe = cpmac_probe,
+ 	.remove = __devexit_p(cpmac_remove),
+ };
+@@ -1143,6 +1143,7 @@ int __devinit cpmac_init(void)
+ 	}
+ 
+ 	cpmac_mii.phy_mask = ~(mask | 0x80000000);
++	snprintf(cpmac_mii.id, MII_BUS_ID_SIZE, "0");
+ 
+ 	res = mdiobus_register(&cpmac_mii);
+ 	if (res)
+diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
+index eb305a0..4fdb13f 100644
+--- a/drivers/net/cxgb3/adapter.h
++++ b/drivers/net/cxgb3/adapter.h
+@@ -43,7 +43,6 @@
+ #include <linux/mutex.h>
+ #include <linux/bitops.h>
+ #include "t3cdev.h"
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+ 
+ struct vlan_group;
+diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
+index fd2e05b..05e5f59 100644
+--- a/drivers/net/cxgb3/cxgb3_main.c
++++ b/drivers/net/cxgb3/cxgb3_main.c
+@@ -1014,8 +1014,8 @@ static int offload_open(struct net_device *dev)
+ 		     adapter->port[0]->mtu : 0xffff);
+ 	init_smt(adapter);
+ 
+-	/* Never mind if the next step fails */
+-	sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group);
++	if (sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group))
++		dev_dbg(&dev->dev, "cannot create sysfs group\n");
+ 
+ 	/* Call back all registered clients */
+ 	cxgb3_add_clients(tdev);
+diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
+index 901c824..ff9c013 100644
+--- a/drivers/net/cxgb3/cxgb3_offload.c
++++ b/drivers/net/cxgb3/cxgb3_offload.c
+@@ -833,10 +833,26 @@ static int do_trace(struct t3cdev *dev, struct sk_buff *skb)
+ 	return 0;
+ }
+ 
++/*
++ * That skb would better have come from process_responses() where we abuse
++ * ->priority and ->csum to carry our data.  NB: if we get to per-arch
++ * ->csum, the things might get really interesting here.
++ */
++
++static inline u32 get_hwtid(struct sk_buff *skb)
++{
++	return ntohl((__force __be32)skb->priority) >> 8 & 0xfffff;
++}
++
++static inline u32 get_opcode(struct sk_buff *skb)
++{
++	return G_OPCODE(ntohl((__force __be32)skb->csum));
++}
++
+ static int do_term(struct t3cdev *dev, struct sk_buff *skb)
+ {
+-	unsigned int hwtid = ntohl(skb->priority) >> 8 & 0xfffff;
+-	unsigned int opcode = G_OPCODE(ntohl(skb->csum));
++	unsigned int hwtid = get_hwtid(skb);
++	unsigned int opcode = get_opcode(skb);
+ 	struct t3c_tid_entry *t3c_tid;
+ 
+ 	t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid);
+@@ -914,7 +930,7 @@ int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n)
+ {
+ 	while (n--) {
+ 		struct sk_buff *skb = *skbs++;
+-		unsigned int opcode = G_OPCODE(ntohl(skb->csum));
++		unsigned int opcode = get_opcode(skb);
+ 		int ret = cpl_handlers[opcode] (dev, skb);
+ 
+ #if VALIDATE_TID
+diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c
+index 865faee..f510140 100644
+--- a/drivers/net/cxgb3/l2t.c
++++ b/drivers/net/cxgb3/l2t.c
+@@ -407,7 +407,7 @@ found:
+ 			} else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE))
+ 				setup_l2e_send_pending(dev, NULL, e);
+ 		} else {
+-			e->state = neigh_is_connected(neigh) ?
++			e->state = neigh->nud_state & NUD_CONNECTED ?
+ 			    L2T_STATE_VALID : L2T_STATE_STALE;
+ 			if (memcmp(e->dmac, neigh->ha, 6))
+ 				setup_l2e_send_pending(dev, NULL, e);
+diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h
+index 77fcc1a..a18c8a1 100644
+--- a/drivers/net/cxgb3/t3cdev.h
++++ b/drivers/net/cxgb3/t3cdev.h
+@@ -34,7 +34,6 @@
+ 
+ #include <linux/list.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <linux/netdevice.h>
+ #include <linux/proc_fs.h>
+ #include <linux/skbuff.h>
+diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
+index ddc30c4..c062aac 100644
+--- a/drivers/net/defxx.c
++++ b/drivers/net/defxx.c
+@@ -971,7 +971,8 @@ static int __devinit dfx_driver_init(struct net_device *dev,
+ 	int alloc_size;			/* total buffer size needed */
+ 	char *top_v, *curr_v;		/* virtual addrs into memory block */
+ 	dma_addr_t top_p, curr_p;	/* physical addrs into memory block */
+-	u32 data, le32;			/* host data register value */
++	u32 data;			/* host data register value */
++	__le32 le32;
+ 	char *board_name = NULL;
+ 
+ 	DBG_printk("In dfx_driver_init...\n");
+diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
+index d63cc93..e6fe261 100644
+--- a/drivers/net/dm9000.c
++++ b/drivers/net/dm9000.c
+@@ -1418,3 +1418,4 @@ module_exit(dm9000_cleanup);
+ MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
+ MODULE_DESCRIPTION("Davicom DM9000 network driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:dm9000");
+diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
+index 3b84028..31feae1 100644
+--- a/drivers/net/e1000/e1000.h
++++ b/drivers/net/e1000/e1000.h
+@@ -161,13 +161,13 @@ struct e1000_buffer {
+ 	struct sk_buff *skb;
+ 	dma_addr_t dma;
+ 	unsigned long time_stamp;
+-	uint16_t length;
+-	uint16_t next_to_watch;
++	u16 length;
++	u16 next_to_watch;
+ };
+ 
+ 
+ struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
+-struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
++struct e1000_ps_page_dma { u64 ps_page_dma[PS_PAGE_BUFFERS]; };
+ 
+ struct e1000_tx_ring {
+ 	/* pointer to the descriptor ring memory */
+@@ -186,9 +186,9 @@ struct e1000_tx_ring {
+ 	struct e1000_buffer *buffer_info;
+ 
+ 	spinlock_t tx_lock;
+-	uint16_t tdh;
+-	uint16_t tdt;
+-	boolean_t last_tx_tso;
++	u16 tdh;
++	u16 tdt;
++	bool last_tx_tso;
+ };
+ 
+ struct e1000_rx_ring {
+@@ -213,8 +213,8 @@ struct e1000_rx_ring {
+ 	/* cpu for rx queue */
+ 	int cpu;
+ 
+-	uint16_t rdh;
+-	uint16_t rdt;
++	u16 rdh;
++	u16 rdt;
+ };
+ 
+ #define E1000_DESC_UNUSED(R) \
+@@ -237,31 +237,30 @@ struct e1000_adapter {
+ 	struct timer_list watchdog_timer;
+ 	struct timer_list phy_info_timer;
+ 	struct vlan_group *vlgrp;
+-	uint16_t mng_vlan_id;
+-	uint32_t bd_number;
+-	uint32_t rx_buffer_len;
+-	uint32_t wol;
+-	uint32_t smartspeed;
+-	uint32_t en_mng_pt;
+-	uint16_t link_speed;
+-	uint16_t link_duplex;
++	u16 mng_vlan_id;
++	u32 bd_number;
++	u32 rx_buffer_len;
++	u32 wol;
++	u32 smartspeed;
++	u32 en_mng_pt;
++	u16 link_speed;
++	u16 link_duplex;
+ 	spinlock_t stats_lock;
+ #ifdef CONFIG_E1000_NAPI
+ 	spinlock_t tx_queue_lock;
+ #endif
+-	atomic_t irq_sem;
+ 	unsigned int total_tx_bytes;
+ 	unsigned int total_tx_packets;
+ 	unsigned int total_rx_bytes;
+ 	unsigned int total_rx_packets;
+ 	/* Interrupt Throttle Rate */
+-	uint32_t itr;
+-	uint32_t itr_setting;
+-	uint16_t tx_itr;
+-	uint16_t rx_itr;
++	u32 itr;
++	u32 itr_setting;
++	u16 tx_itr;
++	u16 rx_itr;
+ 
+ 	struct work_struct reset_task;
+-	uint8_t fc_autoneg;
++	u8 fc_autoneg;
+ 
+ 	struct timer_list blink_timer;
+ 	unsigned long led_status;
+@@ -270,30 +269,30 @@ struct e1000_adapter {
+ 	struct e1000_tx_ring *tx_ring;      /* One per active queue */
+ 	unsigned int restart_queue;
+ 	unsigned long tx_queue_len;
+-	uint32_t txd_cmd;
+-	uint32_t tx_int_delay;
+-	uint32_t tx_abs_int_delay;
+-	uint32_t gotcl;
+-	uint64_t gotcl_old;
+-	uint64_t tpt_old;
+-	uint64_t colc_old;
+-	uint32_t tx_timeout_count;
+-	uint32_t tx_fifo_head;
+-	uint32_t tx_head_addr;
+-	uint32_t tx_fifo_size;
+-	uint8_t  tx_timeout_factor;
++	u32 txd_cmd;
++	u32 tx_int_delay;
++	u32 tx_abs_int_delay;
++	u32 gotcl;
++	u64 gotcl_old;
++	u64 tpt_old;
++	u64 colc_old;
++	u32 tx_timeout_count;
++	u32 tx_fifo_head;
++	u32 tx_head_addr;
++	u32 tx_fifo_size;
++	u8  tx_timeout_factor;
+ 	atomic_t tx_fifo_stall;
+-	boolean_t pcix_82544;
+-	boolean_t detect_tx_hung;
++	bool pcix_82544;
++	bool detect_tx_hung;
+ 
+ 	/* RX */
+ #ifdef CONFIG_E1000_NAPI
+-	boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+-			       struct e1000_rx_ring *rx_ring,
+-			       int *work_done, int work_to_do);
++	bool (*clean_rx) (struct e1000_adapter *adapter,
++			  struct e1000_rx_ring *rx_ring,
++			  int *work_done, int work_to_do);
+ #else
+-	boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+-			       struct e1000_rx_ring *rx_ring);
++	bool (*clean_rx) (struct e1000_adapter *adapter,
++			  struct e1000_rx_ring *rx_ring);
+ #endif
+ 	void (*alloc_rx_buf) (struct e1000_adapter *adapter,
+ 			      struct e1000_rx_ring *rx_ring,
+@@ -306,17 +305,17 @@ struct e1000_adapter {
+ 	int num_tx_queues;
+ 	int num_rx_queues;
+ 
+-	uint64_t hw_csum_err;
+-	uint64_t hw_csum_good;
+-	uint64_t rx_hdr_split;
+-	uint32_t alloc_rx_buff_failed;
+-	uint32_t rx_int_delay;
+-	uint32_t rx_abs_int_delay;
+-	boolean_t rx_csum;
++	u64 hw_csum_err;
++	u64 hw_csum_good;
++	u64 rx_hdr_split;
++	u32 alloc_rx_buff_failed;
++	u32 rx_int_delay;
++	u32 rx_abs_int_delay;
++	bool rx_csum;
+ 	unsigned int rx_ps_pages;
+-	uint32_t gorcl;
+-	uint64_t gorcl_old;
+-	uint16_t rx_ps_bsize0;
++	u32 gorcl;
++	u64 gorcl_old;
++	u16 rx_ps_bsize0;
+ 
+ 
+ 	/* OS defined structs */
+@@ -330,19 +329,19 @@ struct e1000_adapter {
+ 	struct e1000_phy_info phy_info;
+ 	struct e1000_phy_stats phy_stats;
+ 
+-	uint32_t test_icr;
++	u32 test_icr;
+ 	struct e1000_tx_ring test_tx_ring;
+ 	struct e1000_rx_ring test_rx_ring;
+ 
+ 	int msg_enable;
+-	boolean_t have_msi;
++	bool have_msi;
+ 
+ 	/* to not mess up cache alignment, always add to the bottom */
+-	boolean_t tso_force;
+-	boolean_t smart_power_down;	/* phy smart power down */
+-	boolean_t quad_port_a;
++	bool tso_force;
++	bool smart_power_down;	/* phy smart power down */
++	bool quad_port_a;
+ 	unsigned long flags;
+-	uint32_t eeprom_wol;
++	u32 eeprom_wol;
+ };
+ 
+ enum e1000_state_t {
+diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
+index 85e66f4..701531e 100644
+--- a/drivers/net/e1000/e1000_ethtool.c
++++ b/drivers/net/e1000/e1000_ethtool.c
+@@ -36,7 +36,7 @@ extern int e1000_up(struct e1000_adapter *adapter);
+ extern void e1000_down(struct e1000_adapter *adapter);
+ extern void e1000_reinit_locked(struct e1000_adapter *adapter);
+ extern void e1000_reset(struct e1000_adapter *adapter);
+-extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
++extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+ extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+ extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+ extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+@@ -289,7 +289,7 @@ e1000_set_pauseparam(struct net_device *netdev,
+ 	return retval;
+ }
+ 
+-static uint32_t
++static u32
+ e1000_get_rx_csum(struct net_device *netdev)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -297,7 +297,7 @@ e1000_get_rx_csum(struct net_device *netdev)
+ }
+ 
+ static int
+-e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
++e1000_set_rx_csum(struct net_device *netdev, u32 data)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	adapter->rx_csum = data;
+@@ -309,14 +309,14 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
+ 	return 0;
+ }
+ 
+-static uint32_t
++static u32
+ e1000_get_tx_csum(struct net_device *netdev)
+ {
+ 	return (netdev->features & NETIF_F_HW_CSUM) != 0;
+ }
+ 
+ static int
+-e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
++e1000_set_tx_csum(struct net_device *netdev, u32 data)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 
+@@ -335,7 +335,7 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
+ }
+ 
+ static int
+-e1000_set_tso(struct net_device *netdev, uint32_t data)
++e1000_set_tso(struct net_device *netdev, u32 data)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	if ((adapter->hw.mac_type < e1000_82544) ||
+@@ -353,11 +353,11 @@ e1000_set_tso(struct net_device *netdev, uint32_t data)
+ 		netdev->features &= ~NETIF_F_TSO6;
+ 
+ 	DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled");
+-	adapter->tso_force = TRUE;
++	adapter->tso_force = true;
+ 	return 0;
+ }
+ 
+-static uint32_t
++static u32
+ e1000_get_msglevel(struct net_device *netdev)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -365,7 +365,7 @@ e1000_get_msglevel(struct net_device *netdev)
+ }
+ 
+ static void
+-e1000_set_msglevel(struct net_device *netdev, uint32_t data)
++e1000_set_msglevel(struct net_device *netdev, u32 data)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	adapter->msg_enable = data;
+@@ -375,7 +375,7 @@ static int
+ e1000_get_regs_len(struct net_device *netdev)
+ {
+ #define E1000_REGS_LEN 32
+-	return E1000_REGS_LEN * sizeof(uint32_t);
++	return E1000_REGS_LEN * sizeof(u32);
+ }
+ 
+ static void
+@@ -384,10 +384,10 @@ e1000_get_regs(struct net_device *netdev,
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	struct e1000_hw *hw = &adapter->hw;
+-	uint32_t *regs_buff = p;
+-	uint16_t phy_data;
++	u32 *regs_buff = p;
++	u16 phy_data;
+ 
+-	memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t));
++	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
+ 
+ 	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
+ 
+@@ -412,44 +412,44 @@ e1000_get_regs(struct net_device *netdev,
+ 				    IGP01E1000_PHY_AGC_A);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+-		regs_buff[13] = (uint32_t)phy_data; /* cable length */
++		regs_buff[13] = (u32)phy_data; /* cable length */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ 				    IGP01E1000_PHY_AGC_B);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+-		regs_buff[14] = (uint32_t)phy_data; /* cable length */
++		regs_buff[14] = (u32)phy_data; /* cable length */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ 				    IGP01E1000_PHY_AGC_C);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+-		regs_buff[15] = (uint32_t)phy_data; /* cable length */
++		regs_buff[15] = (u32)phy_data; /* cable length */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ 				    IGP01E1000_PHY_AGC_D);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+-		regs_buff[16] = (uint32_t)phy_data; /* cable length */
++		regs_buff[16] = (u32)phy_data; /* cable length */
+ 		regs_buff[17] = 0; /* extended 10bt distance (not needed) */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+-		regs_buff[18] = (uint32_t)phy_data; /* cable polarity */
++		regs_buff[18] = (u32)phy_data; /* cable polarity */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ 				    IGP01E1000_PHY_PCS_INIT_REG);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+-		regs_buff[19] = (uint32_t)phy_data; /* cable polarity */
++		regs_buff[19] = (u32)phy_data; /* cable polarity */
+ 		regs_buff[20] = 0; /* polarity correction enabled (always) */
+ 		regs_buff[22] = 0; /* phy receive errors (unavailable) */
+ 		regs_buff[23] = regs_buff[18]; /* mdix mode */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+ 	} else {
+ 		e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+-		regs_buff[13] = (uint32_t)phy_data; /* cable length */
++		regs_buff[13] = (u32)phy_data; /* cable length */
+ 		regs_buff[14] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+ 		regs_buff[15] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+ 		regs_buff[16] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+ 		e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+-		regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */
++		regs_buff[17] = (u32)phy_data; /* extended 10bt distance */
+ 		regs_buff[18] = regs_buff[13]; /* cable polarity */
+ 		regs_buff[19] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+ 		regs_buff[20] = regs_buff[17]; /* polarity correction */
+@@ -459,7 +459,7 @@ e1000_get_regs(struct net_device *netdev,
+ 	}
+ 	regs_buff[21] = adapter->phy_stats.idle_errors;  /* phy idle errors */
+ 	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+-	regs_buff[24] = (uint32_t)phy_data;  /* phy local receiver status */
++	regs_buff[24] = (u32)phy_data;  /* phy local receiver status */
+ 	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
+ 	if (hw->mac_type >= e1000_82540 &&
+ 	    hw->mac_type < e1000_82571 &&
+@@ -477,14 +477,14 @@ e1000_get_eeprom_len(struct net_device *netdev)
+ 
+ static int
+ e1000_get_eeprom(struct net_device *netdev,
+-                      struct ethtool_eeprom *eeprom, uint8_t *bytes)
++                      struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	struct e1000_hw *hw = &adapter->hw;
+-	uint16_t *eeprom_buff;
++	u16 *eeprom_buff;
+ 	int first_word, last_word;
+ 	int ret_val = 0;
+-	uint16_t i;
++	u16 i;
+ 
+ 	if (eeprom->len == 0)
+ 		return -EINVAL;
+@@ -494,7 +494,7 @@ e1000_get_eeprom(struct net_device *netdev,
+ 	first_word = eeprom->offset >> 1;
+ 	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+ 
+-	eeprom_buff = kmalloc(sizeof(uint16_t) *
++	eeprom_buff = kmalloc(sizeof(u16) *
+ 			(last_word - first_word + 1), GFP_KERNEL);
+ 	if (!eeprom_buff)
+ 		return -ENOMEM;
+@@ -514,7 +514,7 @@ e1000_get_eeprom(struct net_device *netdev,
+ 	for (i = 0; i < last_word - first_word + 1; i++)
+ 		le16_to_cpus(&eeprom_buff[i]);
+ 
+-	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
++	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
+ 			eeprom->len);
+ 	kfree(eeprom_buff);
+ 
+@@ -523,14 +523,14 @@ e1000_get_eeprom(struct net_device *netdev,
+ 
+ static int
+ e1000_set_eeprom(struct net_device *netdev,
+-                      struct ethtool_eeprom *eeprom, uint8_t *bytes)
++                      struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	struct e1000_hw *hw = &adapter->hw;
+-	uint16_t *eeprom_buff;
++	u16 *eeprom_buff;
+ 	void *ptr;
+ 	int max_len, first_word, last_word, ret_val = 0;
+-	uint16_t i;
++	u16 i;
+ 
+ 	if (eeprom->len == 0)
+ 		return -EOPNOTSUPP;
+@@ -590,7 +590,7 @@ e1000_get_drvinfo(struct net_device *netdev,
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	char firmware_version[32];
+-	uint16_t eeprom_data;
++	u16 eeprom_data;
+ 
+ 	strncpy(drvinfo->driver,  e1000_driver_name, 32);
+ 	strncpy(drvinfo->version, e1000_driver_version, 32);
+@@ -674,13 +674,13 @@ e1000_set_ringparam(struct net_device *netdev,
+ 	adapter->tx_ring = txdr;
+ 	adapter->rx_ring = rxdr;
+ 
+-	rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
+-	rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
++	rxdr->count = max(ring->rx_pending,(u32)E1000_MIN_RXD);
++	rxdr->count = min(rxdr->count,(u32)(mac_type < e1000_82544 ?
+ 		E1000_MAX_RXD : E1000_MAX_82544_RXD));
+ 	rxdr->count = ALIGN(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+ 
+-	txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD);
+-	txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ?
++	txdr->count = max(ring->tx_pending,(u32)E1000_MIN_TXD);
++	txdr->count = min(txdr->count,(u32)(mac_type < e1000_82544 ?
+ 		E1000_MAX_TXD : E1000_MAX_82544_TXD));
+ 	txdr->count = ALIGN(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+ 
+@@ -728,13 +728,13 @@ err_setup:
+ 	return err;
+ }
+ 
+-static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data,
+-			     int reg, uint32_t mask, uint32_t write)
++static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
++			     int reg, u32 mask, u32 write)
+ {
+-	static const uint32_t test[] =
++	static const u32 test[] =
+ 		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
+-	uint8_t __iomem *address = adapter->hw.hw_addr + reg;
+-	uint32_t read;
++	u8 __iomem *address = adapter->hw.hw_addr + reg;
++	u32 read;
+ 	int i;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(test); i++) {
+@@ -751,11 +751,11 @@ static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data,
+ 	return false;
+ }
+ 
+-static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data,
+-			      int reg, uint32_t mask, uint32_t write)
++static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
++			      int reg, u32 mask, u32 write)
+ {
+-	uint8_t __iomem *address = adapter->hw.hw_addr + reg;
+-	uint32_t read;
++	u8 __iomem *address = adapter->hw.hw_addr + reg;
++	u32 read;
+ 
+ 	writel(write & mask, address);
+ 	read = readl(address);
+@@ -788,10 +788,10 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data,
+ 	} while (0)
+ 
+ static int
+-e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+ {
+-	uint32_t value, before, after;
+-	uint32_t i, toggle;
++	u32 value, before, after;
++	u32 i, toggle;
+ 
+ 	/* The status register is Read Only, so a write should fail.
+ 	 * Some bits that get toggled are ignored.
+@@ -884,11 +884,11 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
+ }
+ 
+ static int
+-e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
+ {
+-	uint16_t temp;
+-	uint16_t checksum = 0;
+-	uint16_t i;
++	u16 temp;
++	u16 checksum = 0;
++	u16 i;
+ 
+ 	*data = 0;
+ 	/* Read and add up the contents of the EEPROM */
+@@ -901,7 +901,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
+ 	}
+ 
+ 	/* If Checksum is not Correct return error else test passed */
+-	if ((checksum != (uint16_t) EEPROM_SUM) && !(*data))
++	if ((checksum != (u16) EEPROM_SUM) && !(*data))
+ 		*data = 2;
+ 
+ 	return *data;
+@@ -919,11 +919,12 @@ e1000_test_intr(int irq, void *data)
+ }
+ 
+ static int
+-e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+-	uint32_t mask, i=0, shared_int = TRUE;
+-	uint32_t irq = adapter->pdev->irq;
++	u32 mask, i = 0;
++	bool shared_int = true;
++	u32 irq = adapter->pdev->irq;
+ 
+ 	*data = 0;
+ 
+@@ -931,7 +932,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
+ 	/* Hook up test interrupt handler just for this test */
+ 	if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,
+ 	                 netdev))
+-		shared_int = FALSE;
++		shared_int = false;
+ 	else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,
+ 	         netdev->name, netdev)) {
+ 		*data = 1;
+@@ -1069,7 +1070,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+ 	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
+ 	struct pci_dev *pdev = adapter->pdev;
+-	uint32_t rctl;
++	u32 rctl;
+ 	int i, ret_val;
+ 
+ 	/* Setup Tx descriptor ring and Tx buffers */
+@@ -1095,8 +1096,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 	txdr->next_to_use = txdr->next_to_clean = 0;
+ 
+ 	E1000_WRITE_REG(&adapter->hw, TDBAL,
+-			((uint64_t) txdr->dma & 0x00000000FFFFFFFF));
+-	E1000_WRITE_REG(&adapter->hw, TDBAH, ((uint64_t) txdr->dma >> 32));
++			((u64) txdr->dma & 0x00000000FFFFFFFF));
++	E1000_WRITE_REG(&adapter->hw, TDBAH, ((u64) txdr->dma >> 32));
+ 	E1000_WRITE_REG(&adapter->hw, TDLEN,
+ 			txdr->count * sizeof(struct e1000_tx_desc));
+ 	E1000_WRITE_REG(&adapter->hw, TDH, 0);
+@@ -1152,8 +1153,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+ 	E1000_WRITE_REG(&adapter->hw, RDBAL,
+-			((uint64_t) rxdr->dma & 0xFFFFFFFF));
+-	E1000_WRITE_REG(&adapter->hw, RDBAH, ((uint64_t) rxdr->dma >> 32));
++			((u64) rxdr->dma & 0xFFFFFFFF));
++	E1000_WRITE_REG(&adapter->hw, RDBAH, ((u64) rxdr->dma >> 32));
+ 	E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size);
+ 	E1000_WRITE_REG(&adapter->hw, RDH, 0);
+ 	E1000_WRITE_REG(&adapter->hw, RDT, 0);
+@@ -1201,7 +1202,7 @@ e1000_phy_disable_receiver(struct e1000_adapter *adapter)
+ static void
+ e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+ {
+-	uint16_t phy_reg;
++	u16 phy_reg;
+ 
+ 	/* Because we reset the PHY above, we need to re-force TX_CLK in the
+ 	 * Extended PHY Specific Control Register to 25MHz clock.  This
+@@ -1225,8 +1226,8 @@ e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+ static int
+ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+ {
+-	uint32_t ctrl_reg;
+-	uint16_t phy_reg;
++	u32 ctrl_reg;
++	u16 phy_reg;
+ 
+ 	/* Setup the Device Control Register for PHY loopback test. */
+ 
+@@ -1292,10 +1293,10 @@ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+ static int
+ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ {
+-	uint32_t ctrl_reg = 0;
+-	uint32_t stat_reg = 0;
++	u32 ctrl_reg = 0;
++	u32 stat_reg = 0;
+ 
+-	adapter->hw.autoneg = FALSE;
++	adapter->hw.autoneg = false;
+ 
+ 	if (adapter->hw.phy_type == e1000_phy_m88) {
+ 		/* Auto-MDI/MDIX Off */
+@@ -1362,8 +1363,8 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ static int
+ e1000_set_phy_loopback(struct e1000_adapter *adapter)
+ {
+-	uint16_t phy_reg = 0;
+-	uint16_t count = 0;
++	u16 phy_reg = 0;
++	u16 count = 0;
+ 
+ 	switch (adapter->hw.mac_type) {
+ 	case e1000_82543:
+@@ -1415,7 +1416,7 @@ static int
+ e1000_setup_loopback_test(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+-	uint32_t rctl;
++	u32 rctl;
+ 
+ 	if (hw->media_type == e1000_media_type_fiber ||
+ 	    hw->media_type == e1000_media_type_internal_serdes) {
+@@ -1450,8 +1451,8 @@ static void
+ e1000_loopback_cleanup(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+-	uint32_t rctl;
+-	uint16_t phy_reg;
++	u32 rctl;
++	u16 phy_reg;
+ 
+ 	rctl = E1000_READ_REG(hw, RCTL);
+ 	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
+@@ -1473,7 +1474,7 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
+ 	case e1000_82545_rev_3:
+ 	case e1000_82546_rev_3:
+ 	default:
+-		hw->autoneg = TRUE;
++		hw->autoneg = true;
+ 		if (hw->phy_type == e1000_phy_gg82563)
+ 			e1000_write_phy_reg(hw,
+ 					    GG82563_PHY_KMRN_MODE_CTRL,
+@@ -1577,7 +1578,7 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
+ }
+ 
+ static int
+-e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
+ {
+ 	/* PHY loopback cannot be performed if SoL/IDER
+ 	 * sessions are active */
+@@ -1602,18 +1603,18 @@ out:
+ }
+ 
+ static int
+-e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_link_test(struct e1000_adapter *adapter, u64 *data)
+ {
+ 	*data = 0;
+ 	if (adapter->hw.media_type == e1000_media_type_internal_serdes) {
+ 		int i = 0;
+-		adapter->hw.serdes_link_down = TRUE;
++		adapter->hw.serdes_link_down = true;
+ 
+ 		/* On some blade server designs, link establishment
+ 		 * could take as long as 2-3 minutes */
+ 		do {
+ 			e1000_check_for_link(&adapter->hw);
+-			if (adapter->hw.serdes_link_down == FALSE)
++			if (!adapter->hw.serdes_link_down)
+ 				return *data;
+ 			msleep(20);
+ 		} while (i++ < 3750);
+@@ -1646,19 +1647,19 @@ e1000_get_sset_count(struct net_device *netdev, int sset)
+ 
+ static void
+ e1000_diag_test(struct net_device *netdev,
+-		   struct ethtool_test *eth_test, uint64_t *data)
++		   struct ethtool_test *eth_test, u64 *data)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+-	boolean_t if_running = netif_running(netdev);
++	bool if_running = netif_running(netdev);
+ 
+ 	set_bit(__E1000_TESTING, &adapter->flags);
+ 	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
+ 		/* Offline tests */
+ 
+ 		/* save speed, duplex, autoneg settings */
+-		uint16_t autoneg_advertised = adapter->hw.autoneg_advertised;
+-		uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;
+-		uint8_t autoneg = adapter->hw.autoneg;
++		u16 autoneg_advertised = adapter->hw.autoneg_advertised;
++		u8 forced_speed_duplex = adapter->hw.forced_speed_duplex;
++		u8 autoneg = adapter->hw.autoneg;
+ 
+ 		DPRINTK(HW, INFO, "offline testing starting\n");
+ 
+@@ -1876,7 +1877,7 @@ e1000_led_blink_callback(unsigned long data)
+ }
+ 
+ static int
+-e1000_phys_id(struct net_device *netdev, uint32_t data)
++e1000_phys_id(struct net_device *netdev, u32 data)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 
+@@ -1926,7 +1927,7 @@ e1000_nway_reset(struct net_device *netdev)
+ 
+ static void
+ e1000_get_ethtool_stats(struct net_device *netdev,
+-		struct ethtool_stats *stats, uint64_t *data)
++		struct ethtool_stats *stats, u64 *data)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	int i;
+@@ -1935,15 +1936,15 @@ e1000_get_ethtool_stats(struct net_device *netdev,
+ 	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+ 		char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
+ 		data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
+-			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
++			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ 	}
+ /*	BUG_ON(i != E1000_STATS_LEN); */
+ }
+ 
+ static void
+-e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
++e1000_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+ {
+-	uint8_t *p = data;
++	u8 *p = data;
+ 	int i;
+ 
+ 	switch (stringset) {
+diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
+index 7c6888c..9a4b6cb 100644
+--- a/drivers/net/e1000/e1000_hw.c
++++ b/drivers/net/e1000/e1000_hw.c
+@@ -33,106 +33,107 @@
+ 
+ #include "e1000_hw.h"
+ 
+-static int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
+-static void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
+-static int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data);
+-static int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
+-static int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
++static s32 e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask);
++static void e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask);
++static s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 *data);
++static s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 data);
++static s32 e1000_get_software_semaphore(struct e1000_hw *hw);
+ static void e1000_release_software_semaphore(struct e1000_hw *hw);
+ 
+-static uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
+-static int32_t e1000_check_downshift(struct e1000_hw *hw);
+-static int32_t e1000_check_polarity(struct e1000_hw *hw, e1000_rev_polarity *polarity);
++static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw);
++static s32 e1000_check_downshift(struct e1000_hw *hw);
++static s32 e1000_check_polarity(struct e1000_hw *hw, e1000_rev_polarity *polarity);
+ static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
+ static void e1000_clear_vfta(struct e1000_hw *hw);
+-static int32_t e1000_commit_shadow_ram(struct e1000_hw *hw);
+-static int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up);
+-static int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw);
+-static int32_t e1000_detect_gig_phy(struct e1000_hw *hw);
+-static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank);
+-static int32_t e1000_get_auto_rd_done(struct e1000_hw *hw);
+-static int32_t e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, uint16_t *max_length);
+-static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
+-static int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw);
+-static int32_t e1000_get_software_flag(struct e1000_hw *hw);
+-static int32_t e1000_ich8_cycle_init(struct e1000_hw *hw);
+-static int32_t e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout);
+-static int32_t e1000_id_led_init(struct e1000_hw *hw);
+-static int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size);
+-static int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
++static s32 e1000_commit_shadow_ram(struct e1000_hw *hw);
++static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
++						  bool link_up);
++static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
++static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
++static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank);
++static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
++static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, u16 *max_length);
++static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
++static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
++static s32 e1000_get_software_flag(struct e1000_hw *hw);
++static s32 e1000_ich8_cycle_init(struct e1000_hw *hw);
++static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout);
++static s32 e1000_id_led_init(struct e1000_hw *hw);
++static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, u32 cnf_base_addr, u32 cnf_size);
++static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw);
+ static void e1000_init_rx_addrs(struct e1000_hw *hw);
+ static void e1000_initialize_hardware_bits(struct e1000_hw *hw);
+-static boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
+-static int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
+-static int32_t e1000_mng_enable_host_if(struct e1000_hw *hw);
+-static int32_t e1000_mng_host_if_write(struct e1000_hw *hw, uint8_t *buffer, uint16_t length, uint16_t offset, uint8_t *sum);
+-static int32_t e1000_mng_write_cmd_header(struct e1000_hw* hw, struct e1000_host_mng_command_header* hdr);
+-static int32_t e1000_mng_write_commit(struct e1000_hw *hw);
+-static int32_t e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+-static int32_t e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+-static int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+-static int32_t e1000_write_eeprom_eewr(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+-static int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
+-static int32_t e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
++static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
++static s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
++static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum);
++static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw, struct e1000_host_mng_command_header* hdr);
++static s32 e1000_mng_write_commit(struct e1000_hw *hw);
++static s32 e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
++static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
++static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
++static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+ static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
+-static int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t *data);
+-static int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte);
+-static int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte);
+-static int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data);
+-static int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, uint16_t *data);
+-static int32_t e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, uint16_t data);
+-static int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+-static int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
++static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data);
++static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
++static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
++static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data);
++static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 *data);
++static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 data);
++static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
++static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+ static void e1000_release_software_flag(struct e1000_hw *hw);
+-static int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
+-static int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active);
+-static int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop);
++static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
++static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
++static s32 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop);
+ static void e1000_set_pci_express_master_disable(struct e1000_hw *hw);
+-static int32_t e1000_wait_autoneg(struct e1000_hw *hw);
+-static void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
+-static int32_t e1000_set_phy_type(struct e1000_hw *hw);
++static s32 e1000_wait_autoneg(struct e1000_hw *hw);
++static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value);
++static s32 e1000_set_phy_type(struct e1000_hw *hw);
+ static void e1000_phy_init_script(struct e1000_hw *hw);
+-static int32_t e1000_setup_copper_link(struct e1000_hw *hw);
+-static int32_t e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
+-static int32_t e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
+-static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw);
+-static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw);
+-static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
+-static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
+-static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data,
+-                                     uint16_t count);
+-static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw);
+-static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw);
+-static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset,
+-                                      uint16_t words, uint16_t *data);
+-static int32_t e1000_write_eeprom_microwire(struct e1000_hw *hw,
+-                                            uint16_t offset, uint16_t words,
+-                                            uint16_t *data);
+-static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw);
+-static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+-static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+-static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data,
+-                                    uint16_t count);
+-static int32_t e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+-                                      uint16_t phy_data);
+-static int32_t e1000_read_phy_reg_ex(struct e1000_hw *hw,uint32_t reg_addr,
+-                                     uint16_t *phy_data);
+-static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count);
+-static int32_t e1000_acquire_eeprom(struct e1000_hw *hw);
++static s32 e1000_setup_copper_link(struct e1000_hw *hw);
++static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
++static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
++static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
++static s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
++static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
++static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
++static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data,
++                                     u16 count);
++static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
++static s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
++static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
++                                      u16 words, u16 *data);
++static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw,
++                                            u16 offset, u16 words,
++                                            u16 *data);
++static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
++static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
++static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
++static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data,
++                                    u16 count);
++static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
++                                      u16 phy_data);
++static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw,u32 reg_addr,
++                                     u16 *phy_data);
++static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
++static s32 e1000_acquire_eeprom(struct e1000_hw *hw);
+ static void e1000_release_eeprom(struct e1000_hw *hw);
+ static void e1000_standby_eeprom(struct e1000_hw *hw);
+-static int32_t e1000_set_vco_speed(struct e1000_hw *hw);
+-static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw);
+-static int32_t e1000_set_phy_mode(struct e1000_hw *hw);
+-static int32_t e1000_host_if_read_cookie(struct e1000_hw *hw, uint8_t *buffer);
+-static uint8_t e1000_calculate_mng_checksum(char *buffer, uint32_t length);
+-static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
+-                                               uint16_t duplex);
+-static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
++static s32 e1000_set_vco_speed(struct e1000_hw *hw);
++static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
++static s32 e1000_set_phy_mode(struct e1000_hw *hw);
++static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer);
++static u8 e1000_calculate_mng_checksum(char *buffer, u32 length);
++static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
++                                               u16 duplex);
++static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
+ 
+ /* IGP cable length table */
+ static const
+-uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
++u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
+     { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
+       25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
+@@ -143,7 +144,7 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
+       110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
+ 
+ static const
+-uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
++u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
+     { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
+       0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
+       6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
+@@ -158,7 +159,7 @@ uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_set_phy_type(struct e1000_hw *hw)
+ {
+     DEBUGFUNC("e1000_set_phy_type");
+@@ -212,8 +213,8 @@ e1000_set_phy_type(struct e1000_hw *hw)
+ static void
+ e1000_phy_init_script(struct e1000_hw *hw)
+ {
+-    uint32_t ret_val;
+-    uint16_t phy_saved_data;
++    u32 ret_val;
++    u16 phy_saved_data;
+ 
+     DEBUGFUNC("e1000_phy_init_script");
+ 
+@@ -271,7 +272,7 @@ e1000_phy_init_script(struct e1000_hw *hw)
+         e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+ 
+         if (hw->mac_type == e1000_82547) {
+-            uint16_t fused, fine, coarse;
++            u16 fused, fine, coarse;
+ 
+             /* Move to analog registers page */
+             e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
+@@ -305,7 +306,7 @@ e1000_phy_init_script(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_set_mac_type(struct e1000_hw *hw)
+ {
+ 	DEBUGFUNC("e1000_set_mac_type");
+@@ -425,22 +426,22 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ 
+ 	switch (hw->mac_type) {
+ 	case e1000_ich8lan:
+-		hw->swfwhw_semaphore_present = TRUE;
+-		hw->asf_firmware_present = TRUE;
++		hw->swfwhw_semaphore_present = true;
++		hw->asf_firmware_present = true;
+ 		break;
+ 	case e1000_80003es2lan:
+-		hw->swfw_sync_present = TRUE;
++		hw->swfw_sync_present = true;
+ 		/* fall through */
+ 	case e1000_82571:
+ 	case e1000_82572:
+ 	case e1000_82573:
+-		hw->eeprom_semaphore_present = TRUE;
++		hw->eeprom_semaphore_present = true;
+ 		/* fall through */
+ 	case e1000_82541:
+ 	case e1000_82547:
+ 	case e1000_82541_rev_2:
+ 	case e1000_82547_rev_2:
+-		hw->asf_firmware_present = TRUE;
++		hw->asf_firmware_present = true;
+ 		break;
+ 	default:
+ 		break;
+@@ -450,20 +451,20 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ 	 * FD mode
+ 	 */
+ 	if (hw->mac_type == e1000_82543)
+-		hw->bad_tx_carr_stats_fd = TRUE;
++		hw->bad_tx_carr_stats_fd = true;
+ 
+ 	/* capable of receiving management packets to the host */
+ 	if (hw->mac_type >= e1000_82571)
+-		hw->has_manc2h = TRUE;
++		hw->has_manc2h = true;
+ 
+ 	/* In rare occasions, ESB2 systems would end up started without
+ 	 * the RX unit being turned on.
+ 	 */
+ 	if (hw->mac_type == e1000_80003es2lan)
+-		hw->rx_needs_kicking = TRUE;
++		hw->rx_needs_kicking = true;
+ 
+ 	if (hw->mac_type > e1000_82544)
+-		hw->has_smbus = TRUE;
++		hw->has_smbus = true;
+ 
+ 	return E1000_SUCCESS;
+ }
+@@ -476,13 +477,13 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ void
+ e1000_set_media_type(struct e1000_hw *hw)
+ {
+-    uint32_t status;
++    u32 status;
+ 
+     DEBUGFUNC("e1000_set_media_type");
+ 
+     if (hw->mac_type != e1000_82543) {
+         /* tbi_compatibility is only valid on 82543 */
+-        hw->tbi_compatibility_en = FALSE;
++        hw->tbi_compatibility_en = false;
+     }
+ 
+     switch (hw->device_id) {
+@@ -513,7 +514,7 @@ e1000_set_media_type(struct e1000_hw *hw)
+             if (status & E1000_STATUS_TBIMODE) {
+                 hw->media_type = e1000_media_type_fiber;
+                 /* tbi_compatibility not valid on fiber */
+-                hw->tbi_compatibility_en = FALSE;
++                hw->tbi_compatibility_en = false;
+             } else {
+                 hw->media_type = e1000_media_type_copper;
+             }
+@@ -527,17 +528,17 @@ e1000_set_media_type(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_reset_hw(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl;
+-    uint32_t ctrl_ext;
+-    uint32_t icr;
+-    uint32_t manc;
+-    uint32_t led_ctrl;
+-    uint32_t timeout;
+-    uint32_t extcnf_ctrl;
+-    int32_t ret_val;
++    u32 ctrl;
++    u32 ctrl_ext;
++    u32 icr;
++    u32 manc;
++    u32 led_ctrl;
++    u32 timeout;
++    u32 extcnf_ctrl;
++    s32 ret_val;
+ 
+     DEBUGFUNC("e1000_reset_hw");
+ 
+@@ -569,7 +570,7 @@ e1000_reset_hw(struct e1000_hw *hw)
+     E1000_WRITE_FLUSH(hw);
+ 
+     /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
+-    hw->tbi_compatibility_on = FALSE;
++    hw->tbi_compatibility_on = false;
+ 
+     /* Delay to allow any outstanding PCI transactions to complete before
+      * resetting the device
+@@ -682,7 +683,7 @@ e1000_reset_hw(struct e1000_hw *hw)
+             msleep(20);
+             break;
+         case e1000_82573:
+-            if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
++            if (!e1000_is_onboard_nvm_eeprom(hw)) {
+                 udelay(10);
+                 ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+                 ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+@@ -729,7 +730,7 @@ e1000_reset_hw(struct e1000_hw *hw)
+     }
+ 
+     if (hw->mac_type == e1000_ich8lan) {
+-        uint32_t kab = E1000_READ_REG(hw, KABGTXD);
++        u32 kab = E1000_READ_REG(hw, KABGTXD);
+         kab |= E1000_KABGTXD_BGSQLBIAS;
+         E1000_WRITE_REG(hw, KABGTXD, kab);
+     }
+@@ -751,10 +752,10 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
+ {
+     if ((hw->mac_type >= e1000_82571) && (!hw->initialize_hw_bits_disable)) {
+         /* Settings common to all PCI-express silicon */
+-        uint32_t reg_ctrl, reg_ctrl_ext;
+-        uint32_t reg_tarc0, reg_tarc1;
+-        uint32_t reg_tctl;
+-        uint32_t reg_txdctl, reg_txdctl1;
++        u32 reg_ctrl, reg_ctrl_ext;
++        u32 reg_tarc0, reg_tarc1;
++        u32 reg_tctl;
++        u32 reg_txdctl, reg_txdctl1;
+ 
+         /* link autonegotiation/sync workarounds */
+         reg_tarc0 = E1000_READ_REG(hw, TARC0);
+@@ -865,15 +866,15 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
+  * configuration and flow control settings. Clears all on-chip counters. Leaves
+  * the transmit and receive units disabled and uninitialized.
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_init_hw(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl;
+-    uint32_t i;
+-    int32_t ret_val;
+-    uint32_t mta_size;
+-    uint32_t reg_data;
+-    uint32_t ctrl_ext;
++    u32 ctrl;
++    u32 i;
++    s32 ret_val;
++    u32 mta_size;
++    u32 reg_data;
++    u32 ctrl_ext;
+ 
+     DEBUGFUNC("e1000_init_hw");
+ 
+@@ -1019,7 +1020,7 @@ e1000_init_hw(struct e1000_hw *hw)
+ 
+ 
+     if (hw->mac_type == e1000_82573) {
+-        uint32_t gcr = E1000_READ_REG(hw, GCR);
++        u32 gcr = E1000_READ_REG(hw, GCR);
+         gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
+         E1000_WRITE_REG(hw, GCR, gcr);
+     }
+@@ -1053,11 +1054,11 @@ e1000_init_hw(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code.
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
+ {
+-    uint16_t eeprom_data;
+-    int32_t  ret_val;
++    u16 eeprom_data;
++    s32  ret_val;
+ 
+     DEBUGFUNC("e1000_adjust_serdes_amplitude");
+ 
+@@ -1099,12 +1100,12 @@ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
+  * established. Assumes the hardware has previously been reset and the
+  * transmitter and receiver are not enabled.
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_setup_link(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl_ext;
+-    int32_t ret_val;
+-    uint16_t eeprom_data;
++    u32 ctrl_ext;
++    s32 ret_val;
++    u16 eeprom_data;
+ 
+     DEBUGFUNC("e1000_setup_link");
+ 
+@@ -1232,15 +1233,15 @@ e1000_setup_link(struct e1000_hw *hw)
+  * link. Assumes the hardware has been previously reset and the transmitter
+  * and receiver are not enabled.
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl;
+-    uint32_t status;
+-    uint32_t txcw = 0;
+-    uint32_t i;
+-    uint32_t signal = 0;
+-    int32_t ret_val;
++    u32 ctrl;
++    u32 status;
++    u32 txcw = 0;
++    u32 i;
++    u32 signal = 0;
++    s32 ret_val;
+ 
+     DEBUGFUNC("e1000_setup_fiber_serdes_link");
+ 
+@@ -1379,12 +1380,12 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_preconfig(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl;
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    u32 ctrl;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_copper_link_preconfig");
+ 
+@@ -1428,7 +1429,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
+     if (hw->mac_type <= e1000_82543 ||
+         hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
+         hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
+-        hw->phy_reset_disable = FALSE;
++        hw->phy_reset_disable = false;
+ 
+    return E1000_SUCCESS;
+ }
+@@ -1439,12 +1440,12 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ {
+-    uint32_t led_ctrl;
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    u32 led_ctrl;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_copper_link_igp_setup");
+ 
+@@ -1470,7 +1471,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+     /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
+     if (hw->phy_type == e1000_phy_igp) {
+         /* disable lplu d3 during driver init */
+-        ret_val = e1000_set_d3_lplu_state(hw, FALSE);
++        ret_val = e1000_set_d3_lplu_state(hw, false);
+         if (ret_val) {
+             DEBUGOUT("Error Disabling LPLU D3\n");
+             return ret_val;
+@@ -1478,7 +1479,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+     }
+ 
+     /* disable lplu d0 during driver init */
+-    ret_val = e1000_set_d0_lplu_state(hw, FALSE);
++    ret_val = e1000_set_d0_lplu_state(hw, false);
+     if (ret_val) {
+         DEBUGOUT("Error Disabling LPLU D0\n");
+         return ret_val;
+@@ -1586,12 +1587,12 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data;
+-    uint32_t reg_data;
++    s32 ret_val;
++    u16 phy_data;
++    u32 reg_data;
+ 
+     DEBUGFUNC("e1000_copper_link_ggp_setup");
+ 
+@@ -1691,7 +1692,7 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+          * firmware will have already initialized them.  We only initialize
+          * them if the HW is not in IAMT mode.
+          */
+-        if (e1000_check_mng_mode(hw) == FALSE) {
++        if (!e1000_check_mng_mode(hw)) {
+             /* Enable Electrical Idle on the PHY */
+             phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
+             ret_val = e1000_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+@@ -1734,11 +1735,11 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_copper_link_mgp_setup");
+ 
+@@ -1838,11 +1839,11 @@ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_autoneg(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_copper_link_autoneg");
+ 
+@@ -1892,7 +1893,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
+         }
+     }
+ 
+-    hw->get_link_status = TRUE;
++    hw->get_link_status = true;
+ 
+     return E1000_SUCCESS;
+ }
+@@ -1909,10 +1910,10 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_postconfig(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
++    s32 ret_val;
+     DEBUGFUNC("e1000_copper_link_postconfig");
+ 
+     if (hw->mac_type >= e1000_82544) {
+@@ -1932,7 +1933,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
+ 
+     /* Config DSP to improve Giga link quality */
+     if (hw->phy_type == e1000_phy_igp) {
+-        ret_val = e1000_config_dsp_after_link_change(hw, TRUE);
++        ret_val = e1000_config_dsp_after_link_change(hw, true);
+         if (ret_val) {
+             DEBUGOUT("Error Configuring DSP after link up\n");
+             return ret_val;
+@@ -1947,13 +1948,13 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_setup_copper_link(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t i;
+-    uint16_t phy_data;
+-    uint16_t reg_data;
++    s32 ret_val;
++    u16 i;
++    u16 phy_data;
++    u16 reg_data;
+ 
+     DEBUGFUNC("e1000_setup_copper_link");
+ 
+@@ -2061,12 +2062,12 @@ e1000_setup_copper_link(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
+-e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, uint16_t duplex)
++static s32
++e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
+ {
+-    int32_t ret_val = E1000_SUCCESS;
+-    uint32_t tipg;
+-    uint16_t reg_data;
++    s32 ret_val = E1000_SUCCESS;
++    u32 tipg;
++    u16 reg_data;
+ 
+     DEBUGFUNC("e1000_configure_kmrn_for_10_100");
+ 
+@@ -2097,12 +2098,12 @@ e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, uint16_t duplex)
+     return ret_val;
+ }
+ 
+-static int32_t
++static s32
+ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+ {
+-    int32_t ret_val = E1000_SUCCESS;
+-    uint16_t reg_data;
+-    uint32_t tipg;
++    s32 ret_val = E1000_SUCCESS;
++    u16 reg_data;
++    u32 tipg;
+ 
+     DEBUGFUNC("e1000_configure_kmrn_for_1000");
+ 
+@@ -2134,12 +2135,12 @@ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t mii_autoneg_adv_reg;
+-    uint16_t mii_1000t_ctrl_reg;
++    s32 ret_val;
++    u16 mii_autoneg_adv_reg;
++    u16 mii_1000t_ctrl_reg;
+ 
+     DEBUGFUNC("e1000_phy_setup_autoneg");
+ 
+@@ -2283,15 +2284,15 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl;
+-    int32_t ret_val;
+-    uint16_t mii_ctrl_reg;
+-    uint16_t mii_status_reg;
+-    uint16_t phy_data;
+-    uint16_t i;
++    u32 ctrl;
++    s32 ret_val;
++    u16 mii_ctrl_reg;
++    u16 mii_status_reg;
++    u16 phy_data;
++    u16 i;
+ 
+     DEBUGFUNC("e1000_phy_force_speed_duplex");
+ 
+@@ -2537,7 +2538,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+ void
+ e1000_config_collision_dist(struct e1000_hw *hw)
+ {
+-    uint32_t tctl, coll_dist;
++    u32 tctl, coll_dist;
+ 
+     DEBUGFUNC("e1000_config_collision_dist");
+ 
+@@ -2564,12 +2565,12 @@ e1000_config_collision_dist(struct e1000_hw *hw)
+ * The contents of the PHY register containing the needed information need to
+ * be passed in.
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_config_mac_to_phy(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl;
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    u32 ctrl;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_config_mac_to_phy");
+ 
+@@ -2623,10 +2624,10 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
+  * by the PHY rather than the MAC. Software must also configure these
+  * bits when link is forced on a fiber connection.
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_force_mac_fc(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl;
++    u32 ctrl;
+ 
+     DEBUGFUNC("e1000_force_mac_fc");
+ 
+@@ -2690,15 +2691,15 @@ e1000_force_mac_fc(struct e1000_hw *hw)
+  * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
+  * and RFCE bits will be automaticaly set to the negotiated flow control mode.
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_config_fc_after_link_up(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t mii_status_reg;
+-    uint16_t mii_nway_adv_reg;
+-    uint16_t mii_nway_lp_ability_reg;
+-    uint16_t speed;
+-    uint16_t duplex;
++    s32 ret_val;
++    u16 mii_status_reg;
++    u16 mii_nway_adv_reg;
++    u16 mii_nway_lp_ability_reg;
++    u16 speed;
++    u16 duplex;
+ 
+     DEBUGFUNC("e1000_config_fc_after_link_up");
+ 
+@@ -2895,17 +2896,17 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
+  *
+  * Called by any function that needs to check the link status of the adapter.
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_check_for_link(struct e1000_hw *hw)
+ {
+-    uint32_t rxcw = 0;
+-    uint32_t ctrl;
+-    uint32_t status;
+-    uint32_t rctl;
+-    uint32_t icr;
+-    uint32_t signal = 0;
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    u32 rxcw = 0;
++    u32 ctrl;
++    u32 status;
++    u32 rctl;
++    u32 icr;
++    u32 signal = 0;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_check_for_link");
+ 
+@@ -2923,7 +2924,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+         if (hw->media_type == e1000_media_type_fiber) {
+             signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
+             if (status & E1000_STATUS_LU)
+-                hw->get_link_status = FALSE;
++                hw->get_link_status = false;
+         }
+     }
+ 
+@@ -2947,7 +2948,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+             return ret_val;
+ 
+         if (phy_data & MII_SR_LINK_STATUS) {
+-            hw->get_link_status = FALSE;
++            hw->get_link_status = false;
+             /* Check if there was DownShift, must be checked immediately after
+              * link-up */
+             e1000_check_downshift(hw);
+@@ -2973,7 +2974,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ 
+         } else {
+             /* No link detected */
+-            e1000_config_dsp_after_link_change(hw, FALSE);
++            e1000_config_dsp_after_link_change(hw, false);
+             return 0;
+         }
+ 
+@@ -2983,7 +2984,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+         if (!hw->autoneg) return -E1000_ERR_CONFIG;
+ 
+         /* optimize the dsp settings for the igp phy */
+-        e1000_config_dsp_after_link_change(hw, TRUE);
++        e1000_config_dsp_after_link_change(hw, true);
+ 
+         /* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
+          * have Si on board that is 82544 or newer, Auto
+@@ -3021,7 +3022,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+          * at gigabit speed, we turn on TBI compatibility.
+          */
+         if (hw->tbi_compatibility_en) {
+-            uint16_t speed, duplex;
++            u16 speed, duplex;
+             ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+             if (ret_val) {
+                 DEBUGOUT("Error getting link speed and duplex\n");
+@@ -3036,7 +3037,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+                     rctl = E1000_READ_REG(hw, RCTL);
+                     rctl &= ~E1000_RCTL_SBP;
+                     E1000_WRITE_REG(hw, RCTL, rctl);
+-                    hw->tbi_compatibility_on = FALSE;
++                    hw->tbi_compatibility_on = false;
+                 }
+             } else {
+                 /* If TBI compatibility is was previously off, turn it on. For
+@@ -3045,7 +3046,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+                  * will look like CRC errors to to the hardware.
+                  */
+                 if (!hw->tbi_compatibility_on) {
+-                    hw->tbi_compatibility_on = TRUE;
++                    hw->tbi_compatibility_on = true;
+                     rctl = E1000_READ_REG(hw, RCTL);
+                     rctl |= E1000_RCTL_SBP;
+                     E1000_WRITE_REG(hw, RCTL, rctl);
+@@ -3098,7 +3099,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+         E1000_WRITE_REG(hw, TXCW, hw->txcw);
+         E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
+ 
+-        hw->serdes_link_down = FALSE;
++        hw->serdes_link_down = false;
+     }
+     /* If we force link for non-auto-negotiation switch, check link status
+      * based on MAC synchronization for internal serdes media type.
+@@ -3109,11 +3110,11 @@ e1000_check_for_link(struct e1000_hw *hw)
+         udelay(10);
+         if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
+             if (!(rxcw & E1000_RXCW_IV)) {
+-                hw->serdes_link_down = FALSE;
++                hw->serdes_link_down = false;
+                 DEBUGOUT("SERDES: Link is up.\n");
+             }
+         } else {
+-            hw->serdes_link_down = TRUE;
++            hw->serdes_link_down = true;
+             DEBUGOUT("SERDES: Link is down.\n");
+         }
+     }
+@@ -3131,14 +3132,14 @@ e1000_check_for_link(struct e1000_hw *hw)
+  * speed - Speed of the connection
+  * duplex - Duplex setting of the connection
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_get_speed_and_duplex(struct e1000_hw *hw,
+-                           uint16_t *speed,
+-                           uint16_t *duplex)
++                           u16 *speed,
++                           u16 *duplex)
+ {
+-    uint32_t status;
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    u32 status;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_get_speed_and_duplex");
+ 
+@@ -3213,12 +3214,12 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_wait_autoneg(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t i;
+-    uint16_t phy_data;
++    s32 ret_val;
++    u16 i;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_wait_autoneg");
+     DEBUGOUT("Waiting for Auto-Neg to complete.\n");
+@@ -3250,7 +3251,7 @@ e1000_wait_autoneg(struct e1000_hw *hw)
+ ******************************************************************************/
+ static void
+ e1000_raise_mdi_clk(struct e1000_hw *hw,
+-                    uint32_t *ctrl)
++                    u32 *ctrl)
+ {
+     /* Raise the clock input to the Management Data Clock (by setting the MDC
+      * bit), and then delay 10 microseconds.
+@@ -3268,7 +3269,7 @@ e1000_raise_mdi_clk(struct e1000_hw *hw,
+ ******************************************************************************/
+ static void
+ e1000_lower_mdi_clk(struct e1000_hw *hw,
+-                    uint32_t *ctrl)
++                    u32 *ctrl)
+ {
+     /* Lower the clock input to the Management Data Clock (by clearing the MDC
+      * bit), and then delay 10 microseconds.
+@@ -3289,11 +3290,11 @@ e1000_lower_mdi_clk(struct e1000_hw *hw,
+ ******************************************************************************/
+ static void
+ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
+-                         uint32_t data,
+-                         uint16_t count)
++                         u32 data,
++                         u16 count)
+ {
+-    uint32_t ctrl;
+-    uint32_t mask;
++    u32 ctrl;
++    u32 mask;
+ 
+     /* We need to shift "count" number of bits out to the PHY. So, the value
+      * in the "data" parameter will be shifted out to the PHY one bit at a
+@@ -3337,12 +3338,12 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
+ *
+ * Bits are shifted in in MSB to LSB order.
+ ******************************************************************************/
+-static uint16_t
++static u16
+ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl;
+-    uint16_t data = 0;
+-    uint8_t i;
++    u32 ctrl;
++    u16 data = 0;
++    u8 i;
+ 
+     /* In order to read a register from the PHY, we need to shift in a total
+      * of 18 bits from the PHY. The first two bit (turnaround) times are used
+@@ -3383,13 +3384,13 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+     return data;
+ }
+ 
+-static int32_t
+-e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
++static s32
++e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
+ {
+-    uint32_t swfw_sync = 0;
+-    uint32_t swmask = mask;
+-    uint32_t fwmask = mask << 16;
+-    int32_t timeout = 200;
++    u32 swfw_sync = 0;
++    u32 swmask = mask;
++    u32 fwmask = mask << 16;
++    s32 timeout = 200;
+ 
+     DEBUGFUNC("e1000_swfw_sync_acquire");
+ 
+@@ -3428,10 +3429,10 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
+ }
+ 
+ static void
+-e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
++e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
+ {
+-    uint32_t swfw_sync;
+-    uint32_t swmask = mask;
++    u32 swfw_sync;
++    u32 swmask = mask;
+ 
+     DEBUGFUNC("e1000_swfw_sync_release");
+ 
+@@ -3463,13 +3464,13 @@ e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_read_phy_reg(struct e1000_hw *hw,
+-                   uint32_t reg_addr,
+-                   uint16_t *phy_data)
++                   u32 reg_addr,
++                   u16 *phy_data)
+ {
+-    uint32_t ret_val;
+-    uint16_t swfw;
++    u32 ret_val;
++    u16 swfw;
+ 
+     DEBUGFUNC("e1000_read_phy_reg");
+ 
+@@ -3487,7 +3488,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
+         hw->phy_type == e1000_phy_igp_2) &&
+        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+-                                         (uint16_t)reg_addr);
++                                         (u16)reg_addr);
+         if (ret_val) {
+             e1000_swfw_sync_release(hw, swfw);
+             return ret_val;
+@@ -3498,14 +3499,14 @@ e1000_read_phy_reg(struct e1000_hw *hw,
+             /* Select Configuration Page */
+             if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+                 ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+-                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++                          (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+             } else {
+                 /* Use Alternative Page Select register to access
+                  * registers 30 and 31
+                  */
+                 ret_val = e1000_write_phy_reg_ex(hw,
+                                                  GG82563_PHY_PAGE_SELECT_ALT,
+-                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++                          (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+             }
+ 
+             if (ret_val) {
+@@ -3522,13 +3523,13 @@ e1000_read_phy_reg(struct e1000_hw *hw,
+     return ret_val;
+ }
+ 
+-static int32_t
+-e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+-                      uint16_t *phy_data)
++static s32
++e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
++                      u16 *phy_data)
+ {
+-    uint32_t i;
+-    uint32_t mdic = 0;
+-    const uint32_t phy_addr = 1;
++    u32 i;
++    u32 mdic = 0;
++    const u32 phy_addr = 1;
+ 
+     DEBUGFUNC("e1000_read_phy_reg_ex");
+ 
+@@ -3562,7 +3563,7 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+             DEBUGOUT("MDI Error\n");
+             return -E1000_ERR_PHY;
+         }
+-        *phy_data = (uint16_t) mdic;
++        *phy_data = (u16) mdic;
+     } else {
+         /* We must first send a preamble through the MDIO pin to signal the
+          * beginning of an MII instruction.  This is done by sending 32
+@@ -3602,12 +3603,12 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ ******************************************************************************/
+-int32_t
+-e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+-                    uint16_t phy_data)
++s32
++e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
++                    u16 phy_data)
+ {
+-    uint32_t ret_val;
+-    uint16_t swfw;
++    u32 ret_val;
++    u16 swfw;
+ 
+     DEBUGFUNC("e1000_write_phy_reg");
+ 
+@@ -3625,7 +3626,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+         hw->phy_type == e1000_phy_igp_2) &&
+        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+-                                         (uint16_t)reg_addr);
++                                         (u16)reg_addr);
+         if (ret_val) {
+             e1000_swfw_sync_release(hw, swfw);
+             return ret_val;
+@@ -3636,14 +3637,14 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+             /* Select Configuration Page */
+             if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+                 ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+-                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++                          (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+             } else {
+                 /* Use Alternative Page Select register to access
+                  * registers 30 and 31
+                  */
+                 ret_val = e1000_write_phy_reg_ex(hw,
+                                                  GG82563_PHY_PAGE_SELECT_ALT,
+-                          (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++                          (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+             }
+ 
+             if (ret_val) {
+@@ -3660,13 +3661,13 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+     return ret_val;
+ }
+ 
+-static int32_t
+-e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+-                       uint16_t phy_data)
++static s32
++e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
++                       u16 phy_data)
+ {
+-    uint32_t i;
+-    uint32_t mdic = 0;
+-    const uint32_t phy_addr = 1;
++    u32 i;
++    u32 mdic = 0;
++    const u32 phy_addr = 1;
+ 
+     DEBUGFUNC("e1000_write_phy_reg_ex");
+ 
+@@ -3680,7 +3681,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+          * for the PHY register in the MDI Control register.  The MAC will take
+          * care of interfacing with the PHY to send the desired data.
+          */
+-        mdic = (((uint32_t) phy_data) |
++        mdic = (((u32) phy_data) |
+                 (reg_addr << E1000_MDIC_REG_SHIFT) |
+                 (phy_addr << E1000_MDIC_PHY_SHIFT) |
+                 (E1000_MDIC_OP_WRITE));
+@@ -3714,7 +3715,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+         mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
+                 (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+         mdic <<= 16;
+-        mdic |= (uint32_t) phy_data;
++        mdic |= (u32) phy_data;
+ 
+         e1000_shift_out_mdi_bits(hw, mdic, 32);
+     }
+@@ -3722,13 +3723,13 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+     return E1000_SUCCESS;
+ }
+ 
+-static int32_t
++static s32
+ e1000_read_kmrn_reg(struct e1000_hw *hw,
+-                    uint32_t reg_addr,
+-                    uint16_t *data)
++                    u32 reg_addr,
++                    u16 *data)
+ {
+-    uint32_t reg_val;
+-    uint16_t swfw;
++    u32 reg_val;
++    u16 swfw;
+     DEBUGFUNC("e1000_read_kmrn_reg");
+ 
+     if ((hw->mac_type == e1000_80003es2lan) &&
+@@ -3749,19 +3750,19 @@ e1000_read_kmrn_reg(struct e1000_hw *hw,
+ 
+     /* Read the data returned */
+     reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+-    *data = (uint16_t)reg_val;
++    *data = (u16)reg_val;
+ 
+     e1000_swfw_sync_release(hw, swfw);
+     return E1000_SUCCESS;
+ }
+ 
+-static int32_t
++static s32
+ e1000_write_kmrn_reg(struct e1000_hw *hw,
+-                     uint32_t reg_addr,
+-                     uint16_t data)
++                     u32 reg_addr,
++                     u16 data)
+ {
+-    uint32_t reg_val;
+-    uint16_t swfw;
++    u32 reg_val;
++    u16 swfw;
+     DEBUGFUNC("e1000_write_kmrn_reg");
+ 
+     if ((hw->mac_type == e1000_80003es2lan) &&
+@@ -3787,13 +3788,13 @@ e1000_write_kmrn_reg(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_hw_reset(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl, ctrl_ext;
+-    uint32_t led_ctrl;
+-    int32_t ret_val;
+-    uint16_t swfw;
++    u32 ctrl, ctrl_ext;
++    u32 led_ctrl;
++    s32 ret_val;
++    u16 swfw;
+ 
+     DEBUGFUNC("e1000_phy_hw_reset");
+ 
+@@ -3881,11 +3882,11 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
+ *
+ * Sets bit 15 of the MII Control register
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_reset(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_phy_reset");
+ 
+@@ -3936,9 +3937,9 @@ e1000_phy_reset(struct e1000_hw *hw)
+ void
+ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+ {
+-    int32_t reg;
+-    uint16_t phy_data;
+-    int32_t retry = 0;
++    s32 reg;
++    u16 phy_data;
++    s32 retry = 0;
+ 
+     DEBUGFUNC("e1000_phy_powerdown_workaround");
+ 
+@@ -3986,13 +3987,13 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+ *
+ * hw - struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    int32_t reg;
+-    int32_t cnt;
+-    uint16_t phy_data;
++    s32 ret_val;
++    s32 reg;
++    s32 cnt;
++    u16 phy_data;
+ 
+     if (hw->kmrn_lock_loss_workaround_disabled)
+         return E1000_SUCCESS;
+@@ -4039,12 +4040,12 @@ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_detect_gig_phy(struct e1000_hw *hw)
+ {
+-    int32_t phy_init_status, ret_val;
+-    uint16_t phy_id_high, phy_id_low;
+-    boolean_t match = FALSE;
++    s32 phy_init_status, ret_val;
++    u16 phy_id_high, phy_id_low;
++    bool match = false;
+ 
+     DEBUGFUNC("e1000_detect_gig_phy");
+ 
+@@ -4075,46 +4076,46 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
+     if (ret_val)
+         return ret_val;
+ 
+-    hw->phy_id = (uint32_t) (phy_id_high << 16);
++    hw->phy_id = (u32) (phy_id_high << 16);
+     udelay(20);
+     ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
+     if (ret_val)
+         return ret_val;
+ 
+-    hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK);
+-    hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK;
++    hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK);
++    hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK;
+ 
+     switch (hw->mac_type) {
+     case e1000_82543:
+-        if (hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
++        if (hw->phy_id == M88E1000_E_PHY_ID) match = true;
+         break;
+     case e1000_82544:
+-        if (hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
++        if (hw->phy_id == M88E1000_I_PHY_ID) match = true;
+         break;
+     case e1000_82540:
+     case e1000_82545:
+     case e1000_82545_rev_3:
+     case e1000_82546:
+     case e1000_82546_rev_3:
+-        if (hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
++        if (hw->phy_id == M88E1011_I_PHY_ID) match = true;
+         break;
+     case e1000_82541:
+     case e1000_82541_rev_2:
+     case e1000_82547:
+     case e1000_82547_rev_2:
+-        if (hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
++        if (hw->phy_id == IGP01E1000_I_PHY_ID) match = true;
+         break;
+     case e1000_82573:
+-        if (hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
++        if (hw->phy_id == M88E1111_I_PHY_ID) match = true;
+         break;
+     case e1000_80003es2lan:
+-        if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
++        if (hw->phy_id == GG82563_E_PHY_ID) match = true;
+         break;
+     case e1000_ich8lan:
+-        if (hw->phy_id == IGP03E1000_E_PHY_ID) match = TRUE;
+-        if (hw->phy_id == IFE_E_PHY_ID) match = TRUE;
+-        if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = TRUE;
+-        if (hw->phy_id == IFE_C_E_PHY_ID) match = TRUE;
++        if (hw->phy_id == IGP03E1000_E_PHY_ID) match = true;
++        if (hw->phy_id == IFE_E_PHY_ID) match = true;
++        if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = true;
++        if (hw->phy_id == IFE_C_E_PHY_ID) match = true;
+         break;
+     default:
+         DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
+@@ -4135,10 +4136,10 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_reset_dsp(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
++    s32 ret_val;
+     DEBUGFUNC("e1000_phy_reset_dsp");
+ 
+     do {
+@@ -4162,12 +4163,12 @@ e1000_phy_reset_dsp(struct e1000_hw *hw)
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_igp_get_info(struct e1000_hw *hw,
+                        struct e1000_phy_info *phy_info)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data, min_length, max_length, average;
++    s32 ret_val;
++    u16 phy_data, min_length, max_length, average;
+     e1000_rev_polarity polarity;
+ 
+     DEBUGFUNC("e1000_phy_igp_get_info");
+@@ -4239,12 +4240,12 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_ife_get_info(struct e1000_hw *hw,
+                        struct e1000_phy_info *phy_info)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    s32 ret_val;
++    u16 phy_data;
+     e1000_rev_polarity polarity;
+ 
+     DEBUGFUNC("e1000_phy_ife_get_info");
+@@ -4289,12 +4290,12 @@ e1000_phy_ife_get_info(struct e1000_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_m88_get_info(struct e1000_hw *hw,
+                        struct e1000_phy_info *phy_info)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    s32 ret_val;
++    u16 phy_data;
+     e1000_rev_polarity polarity;
+ 
+     DEBUGFUNC("e1000_phy_m88_get_info");
+@@ -4368,12 +4369,12 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_get_info(struct e1000_hw *hw,
+                    struct e1000_phy_info *phy_info)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_phy_get_info");
+ 
+@@ -4414,7 +4415,7 @@ e1000_phy_get_info(struct e1000_hw *hw,
+         return e1000_phy_m88_get_info(hw, phy_info);
+ }
+ 
+-int32_t
++s32
+ e1000_validate_mdi_setting(struct e1000_hw *hw)
+ {
+     DEBUGFUNC("e1000_validate_mdi_settings");
+@@ -4435,13 +4436,13 @@ e1000_validate_mdi_setting(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_init_eeprom_params(struct e1000_hw *hw)
+ {
+     struct e1000_eeprom_info *eeprom = &hw->eeprom;
+-    uint32_t eecd = E1000_READ_REG(hw, EECD);
+-    int32_t ret_val = E1000_SUCCESS;
+-    uint16_t eeprom_size;
++    u32 eecd = E1000_READ_REG(hw, EECD);
++    s32 ret_val = E1000_SUCCESS;
++    u16 eeprom_size;
+ 
+     DEBUGFUNC("e1000_init_eeprom_params");
+ 
+@@ -4455,8 +4456,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+         eeprom->opcode_bits = 3;
+         eeprom->address_bits = 6;
+         eeprom->delay_usec = 50;
+-        eeprom->use_eerd = FALSE;
+-        eeprom->use_eewr = FALSE;
++        eeprom->use_eerd = false;
++        eeprom->use_eewr = false;
+         break;
+     case e1000_82540:
+     case e1000_82545:
+@@ -4473,8 +4474,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+             eeprom->word_size = 64;
+             eeprom->address_bits = 6;
+         }
+-        eeprom->use_eerd = FALSE;
+-        eeprom->use_eewr = FALSE;
++        eeprom->use_eerd = false;
++        eeprom->use_eewr = false;
+         break;
+     case e1000_82541:
+     case e1000_82541_rev_2:
+@@ -4503,8 +4504,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+                 eeprom->address_bits = 6;
+             }
+         }
+-        eeprom->use_eerd = FALSE;
+-        eeprom->use_eewr = FALSE;
++        eeprom->use_eerd = false;
++        eeprom->use_eewr = false;
+         break;
+     case e1000_82571:
+     case e1000_82572:
+@@ -4518,8 +4519,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+             eeprom->page_size = 8;
+             eeprom->address_bits = 8;
+         }
+-        eeprom->use_eerd = FALSE;
+-        eeprom->use_eewr = FALSE;
++        eeprom->use_eerd = false;
++        eeprom->use_eewr = false;
+         break;
+     case e1000_82573:
+         eeprom->type = e1000_eeprom_spi;
+@@ -4532,9 +4533,9 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+             eeprom->page_size = 8;
+             eeprom->address_bits = 8;
+         }
+-        eeprom->use_eerd = TRUE;
+-        eeprom->use_eewr = TRUE;
+-        if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
++        eeprom->use_eerd = true;
++        eeprom->use_eewr = true;
++        if (!e1000_is_onboard_nvm_eeprom(hw)) {
+             eeprom->type = e1000_eeprom_flash;
+             eeprom->word_size = 2048;
+ 
+@@ -4555,24 +4556,24 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+             eeprom->page_size = 8;
+             eeprom->address_bits = 8;
+         }
+-        eeprom->use_eerd = TRUE;
+-        eeprom->use_eewr = FALSE;
++        eeprom->use_eerd = true;
++        eeprom->use_eewr = false;
+         break;
+     case e1000_ich8lan:
+         {
+-        int32_t  i = 0;
+-        uint32_t flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG);
++        s32  i = 0;
++        u32 flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG);
+ 
+         eeprom->type = e1000_eeprom_ich8;
+-        eeprom->use_eerd = FALSE;
+-        eeprom->use_eewr = FALSE;
++        eeprom->use_eerd = false;
++        eeprom->use_eewr = false;
+         eeprom->word_size = E1000_SHADOW_RAM_WORDS;
+ 
+         /* Zero the shadow RAM structure. But don't load it from NVM
+          * so as to save time for driver init */
+         if (hw->eeprom_shadow_ram != NULL) {
+             for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+-                hw->eeprom_shadow_ram[i].modified = FALSE;
++                hw->eeprom_shadow_ram[i].modified = false;
+                 hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
+             }
+         }
+@@ -4585,7 +4586,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ 
+         hw->flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
+ 
+-        hw->flash_bank_size /= 2 * sizeof(uint16_t);
++        hw->flash_bank_size /= 2 * sizeof(u16);
+ 
+         break;
+         }
+@@ -4610,7 +4611,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+             if (eeprom_size)
+                 eeprom_size++;
+         } else {
+-            eeprom_size = (uint16_t)((eecd & E1000_EECD_SIZE_EX_MASK) >>
++            eeprom_size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+                           E1000_EECD_SIZE_EX_SHIFT);
+         }
+ 
+@@ -4627,7 +4628,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+  *****************************************************************************/
+ static void
+ e1000_raise_ee_clk(struct e1000_hw *hw,
+-                   uint32_t *eecd)
++                   u32 *eecd)
+ {
+     /* Raise the clock input to the EEPROM (by setting the SK bit), and then
+      * wait <delay> microseconds.
+@@ -4646,7 +4647,7 @@ e1000_raise_ee_clk(struct e1000_hw *hw,
+  *****************************************************************************/
+ static void
+ e1000_lower_ee_clk(struct e1000_hw *hw,
+-                   uint32_t *eecd)
++                   u32 *eecd)
+ {
+     /* Lower the clock input to the EEPROM (by clearing the SK bit), and then
+      * wait 50 microseconds.
+@@ -4666,12 +4667,12 @@ e1000_lower_ee_clk(struct e1000_hw *hw,
+  *****************************************************************************/
+ static void
+ e1000_shift_out_ee_bits(struct e1000_hw *hw,
+-                        uint16_t data,
+-                        uint16_t count)
++                        u16 data,
++                        u16 count)
+ {
+     struct e1000_eeprom_info *eeprom = &hw->eeprom;
+-    uint32_t eecd;
+-    uint32_t mask;
++    u32 eecd;
++    u32 mask;
+ 
+     /* We need to shift "count" bits out to the EEPROM. So, value in the
+      * "data" parameter will be shifted out to the EEPROM one bit at a time.
+@@ -4717,13 +4718,13 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-static uint16_t
++static u16
+ e1000_shift_in_ee_bits(struct e1000_hw *hw,
+-                       uint16_t count)
++                       u16 count)
+ {
+-    uint32_t eecd;
+-    uint32_t i;
+-    uint16_t data;
++    u32 eecd;
++    u32 i;
++    u16 data;
+ 
+     /* In order to read a register from the EEPROM, we need to shift 'count'
+      * bits in from the EEPROM. Bits are "shifted in" by raising the clock
+@@ -4761,11 +4762,11 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw,
+  * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
+  * function should be called before issuing a command to the EEPROM.
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_acquire_eeprom(struct e1000_hw *hw)
+ {
+     struct e1000_eeprom_info *eeprom = &hw->eeprom;
+-    uint32_t eecd, i=0;
++    u32 eecd, i=0;
+ 
+     DEBUGFUNC("e1000_acquire_eeprom");
+ 
+@@ -4824,7 +4825,7 @@ static void
+ e1000_standby_eeprom(struct e1000_hw *hw)
+ {
+     struct e1000_eeprom_info *eeprom = &hw->eeprom;
+-    uint32_t eecd;
++    u32 eecd;
+ 
+     eecd = E1000_READ_REG(hw, EECD);
+ 
+@@ -4872,7 +4873,7 @@ e1000_standby_eeprom(struct e1000_hw *hw)
+ static void
+ e1000_release_eeprom(struct e1000_hw *hw)
+ {
+-    uint32_t eecd;
++    u32 eecd;
+ 
+     DEBUGFUNC("e1000_release_eeprom");
+ 
+@@ -4920,11 +4921,11 @@ e1000_release_eeprom(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_spi_eeprom_ready(struct e1000_hw *hw)
+ {
+-    uint16_t retry_count = 0;
+-    uint8_t spi_stat_reg;
++    u16 retry_count = 0;
++    u8 spi_stat_reg;
+ 
+     DEBUGFUNC("e1000_spi_eeprom_ready");
+ 
+@@ -4937,7 +4938,7 @@ e1000_spi_eeprom_ready(struct e1000_hw *hw)
+     do {
+         e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
+                                 hw->eeprom.opcode_bits);
+-        spi_stat_reg = (uint8_t)e1000_shift_in_ee_bits(hw, 8);
++        spi_stat_reg = (u8)e1000_shift_in_ee_bits(hw, 8);
+         if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
+             break;
+ 
+@@ -4966,14 +4967,14 @@ e1000_spi_eeprom_ready(struct e1000_hw *hw)
+  * data - word read from the EEPROM
+  * words - number of words to read
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_read_eeprom(struct e1000_hw *hw,
+-                  uint16_t offset,
+-                  uint16_t words,
+-                  uint16_t *data)
++                  u16 offset,
++                  u16 words,
++                  u16 *data)
+ {
+     struct e1000_eeprom_info *eeprom = &hw->eeprom;
+-    uint32_t i = 0;
++    u32 i = 0;
+ 
+     DEBUGFUNC("e1000_read_eeprom");
+ 
+@@ -4994,15 +4995,14 @@ e1000_read_eeprom(struct e1000_hw *hw,
+      * directly. In this case, we need to acquire the EEPROM so that
+      * FW or other port software does not interrupt.
+      */
+-    if (e1000_is_onboard_nvm_eeprom(hw) == TRUE &&
+-        hw->eeprom.use_eerd == FALSE) {
++    if (e1000_is_onboard_nvm_eeprom(hw) && !hw->eeprom.use_eerd) {
+         /* Prepare the EEPROM for bit-bang reading */
+         if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+             return -E1000_ERR_EEPROM;
+     }
+ 
+     /* Eerd register EEPROM access requires no eeprom aquire/release */
+-    if (eeprom->use_eerd == TRUE)
++    if (eeprom->use_eerd)
+         return e1000_read_eeprom_eerd(hw, offset, words, data);
+ 
+     /* ICH EEPROM access is done via the ICH flash controller */
+@@ -5012,8 +5012,8 @@ e1000_read_eeprom(struct e1000_hw *hw,
+     /* Set up the SPI or Microwire EEPROM for bit-bang reading.  We have
+      * acquired the EEPROM at this point, so any returns should relase it */
+     if (eeprom->type == e1000_eeprom_spi) {
+-        uint16_t word_in;
+-        uint8_t read_opcode = EEPROM_READ_OPCODE_SPI;
++        u16 word_in;
++        u8 read_opcode = EEPROM_READ_OPCODE_SPI;
+ 
+         if (e1000_spi_eeprom_ready(hw)) {
+             e1000_release_eeprom(hw);
+@@ -5028,7 +5028,7 @@ e1000_read_eeprom(struct e1000_hw *hw,
+ 
+         /* Send the READ command (opcode + addr)  */
+         e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
+-        e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits);
++        e1000_shift_out_ee_bits(hw, (u16)(offset*2), eeprom->address_bits);
+ 
+         /* Read the data.  The address of the eeprom internally increments with
+          * each byte (spi) being read, saving on the overhead of eeprom setup
+@@ -5044,7 +5044,7 @@ e1000_read_eeprom(struct e1000_hw *hw,
+             /* Send the READ command (opcode + addr)  */
+             e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE,
+                                     eeprom->opcode_bits);
+-            e1000_shift_out_ee_bits(hw, (uint16_t)(offset + i),
++            e1000_shift_out_ee_bits(hw, (u16)(offset + i),
+                                     eeprom->address_bits);
+ 
+             /* Read the data.  For microwire, each word requires the overhead
+@@ -5068,14 +5068,14 @@ e1000_read_eeprom(struct e1000_hw *hw,
+  * data - word read from the EEPROM
+  * words - number of words to read
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_read_eeprom_eerd(struct e1000_hw *hw,
+-                  uint16_t offset,
+-                  uint16_t words,
+-                  uint16_t *data)
++                  u16 offset,
++                  u16 words,
++                  u16 *data)
+ {
+-    uint32_t i, eerd = 0;
+-    int32_t error = 0;
++    u32 i, eerd = 0;
++    s32 error = 0;
+ 
+     for (i = 0; i < words; i++) {
+         eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
+@@ -5102,15 +5102,15 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
+  * data - word read from the EEPROM
+  * words - number of words to read
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_write_eeprom_eewr(struct e1000_hw *hw,
+-                   uint16_t offset,
+-                   uint16_t words,
+-                   uint16_t *data)
++                   u16 offset,
++                   u16 words,
++                   u16 *data)
+ {
+-    uint32_t    register_value = 0;
+-    uint32_t    i              = 0;
+-    int32_t     error          = 0;
++    u32    register_value = 0;
++    u32    i              = 0;
++    s32     error          = 0;
+ 
+     if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
+         return -E1000_ERR_SWFW_SYNC;
+@@ -5143,12 +5143,12 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+ {
+-    uint32_t attempts = 100000;
+-    uint32_t i, reg = 0;
+-    int32_t done = E1000_ERR_EEPROM;
++    u32 attempts = 100000;
++    u32 i, reg = 0;
++    s32 done = E1000_ERR_EEPROM;
+ 
+     for (i = 0; i < attempts; i++) {
+         if (eerd == E1000_EEPROM_POLL_READ)
+@@ -5171,15 +5171,15 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ****************************************************************************/
+-static boolean_t
++static bool
+ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+ {
+-    uint32_t eecd = 0;
++    u32 eecd = 0;
+ 
+     DEBUGFUNC("e1000_is_onboard_nvm_eeprom");
+ 
+     if (hw->mac_type == e1000_ich8lan)
+-        return FALSE;
++        return false;
+ 
+     if (hw->mac_type == e1000_82573) {
+         eecd = E1000_READ_REG(hw, EECD);
+@@ -5189,10 +5189,10 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+ 
+         /* If both bits are set, device is Flash type */
+         if (eecd == 0x03) {
+-            return FALSE;
++            return false;
+         }
+     }
+-    return TRUE;
++    return true;
+ }
+ 
+ /******************************************************************************
+@@ -5204,16 +5204,15 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+  * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
+  * valid.
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+ {
+-    uint16_t checksum = 0;
+-    uint16_t i, eeprom_data;
++    u16 checksum = 0;
++    u16 i, eeprom_data;
+ 
+     DEBUGFUNC("e1000_validate_eeprom_checksum");
+ 
+-    if ((hw->mac_type == e1000_82573) &&
+-        (e1000_is_onboard_nvm_eeprom(hw) == FALSE)) {
++    if ((hw->mac_type == e1000_82573) && !e1000_is_onboard_nvm_eeprom(hw)) {
+         /* Check bit 4 of word 10h.  If it is 0, firmware is done updating
+          * 10h-12h.  Checksum may need to be fixed. */
+         e1000_read_eeprom(hw, 0x10, 1, &eeprom_data);
+@@ -5253,7 +5252,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+         checksum += eeprom_data;
+     }
+ 
+-    if (checksum == (uint16_t) EEPROM_SUM)
++    if (checksum == (u16) EEPROM_SUM)
+         return E1000_SUCCESS;
+     else {
+         DEBUGOUT("EEPROM Checksum Invalid\n");
+@@ -5269,12 +5268,12 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+  * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
+  * Writes the difference to word offset 63 of the EEPROM.
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_update_eeprom_checksum(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl_ext;
+-    uint16_t checksum = 0;
+-    uint16_t i, eeprom_data;
++    u32 ctrl_ext;
++    u16 checksum = 0;
++    u16 i, eeprom_data;
+ 
+     DEBUGFUNC("e1000_update_eeprom_checksum");
+ 
+@@ -5285,7 +5284,7 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
+         }
+         checksum += eeprom_data;
+     }
+-    checksum = (uint16_t) EEPROM_SUM - checksum;
++    checksum = (u16) EEPROM_SUM - checksum;
+     if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
+         DEBUGOUT("EEPROM Write Error\n");
+         return -E1000_ERR_EEPROM;
+@@ -5314,14 +5313,14 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
+  * If e1000_update_eeprom_checksum is not called after this function, the
+  * EEPROM will most likely contain an invalid checksum.
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_write_eeprom(struct e1000_hw *hw,
+-                   uint16_t offset,
+-                   uint16_t words,
+-                   uint16_t *data)
++                   u16 offset,
++                   u16 words,
++                   u16 *data)
+ {
+     struct e1000_eeprom_info *eeprom = &hw->eeprom;
+-    int32_t status = 0;
++    s32 status = 0;
+ 
+     DEBUGFUNC("e1000_write_eeprom");
+ 
+@@ -5339,7 +5338,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
+     }
+ 
+     /* 82573 writes only through eewr */
+-    if (eeprom->use_eewr == TRUE)
++    if (eeprom->use_eewr)
+         return e1000_write_eeprom_eewr(hw, offset, words, data);
+ 
+     if (eeprom->type == e1000_eeprom_ich8)
+@@ -5371,19 +5370,19 @@ e1000_write_eeprom(struct e1000_hw *hw,
+  * data - pointer to array of 8 bit words to be written to the EEPROM
+  *
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_write_eeprom_spi(struct e1000_hw *hw,
+-                       uint16_t offset,
+-                       uint16_t words,
+-                       uint16_t *data)
++                       u16 offset,
++                       u16 words,
++                       u16 *data)
+ {
+     struct e1000_eeprom_info *eeprom = &hw->eeprom;
+-    uint16_t widx = 0;
++    u16 widx = 0;
+ 
+     DEBUGFUNC("e1000_write_eeprom_spi");
+ 
+     while (widx < words) {
+-        uint8_t write_opcode = EEPROM_WRITE_OPCODE_SPI;
++        u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
+ 
+         if (e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM;
+ 
+@@ -5402,14 +5401,14 @@ e1000_write_eeprom_spi(struct e1000_hw *hw,
+         /* Send the Write command (8-bit opcode + addr) */
+         e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
+ 
+-        e1000_shift_out_ee_bits(hw, (uint16_t)((offset + widx)*2),
++        e1000_shift_out_ee_bits(hw, (u16)((offset + widx)*2),
+                                 eeprom->address_bits);
+ 
+         /* Send the data */
+ 
+         /* Loop to allow for up to whole page write (32 bytes) of eeprom */
+         while (widx < words) {
+-            uint16_t word_out = data[widx];
++            u16 word_out = data[widx];
+             word_out = (word_out >> 8) | (word_out << 8);
+             e1000_shift_out_ee_bits(hw, word_out, 16);
+             widx++;
+@@ -5437,16 +5436,16 @@ e1000_write_eeprom_spi(struct e1000_hw *hw,
+  * data - pointer to array of 16 bit words to be written to the EEPROM
+  *
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+-                             uint16_t offset,
+-                             uint16_t words,
+-                             uint16_t *data)
++                             u16 offset,
++                             u16 words,
++                             u16 *data)
+ {
+     struct e1000_eeprom_info *eeprom = &hw->eeprom;
+-    uint32_t eecd;
+-    uint16_t words_written = 0;
+-    uint16_t i = 0;
++    u32 eecd;
++    u16 words_written = 0;
++    u16 i = 0;
+ 
+     DEBUGFUNC("e1000_write_eeprom_microwire");
+ 
+@@ -5457,9 +5456,9 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+      * EEPROM into write/erase mode.
+      */
+     e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
+-                            (uint16_t)(eeprom->opcode_bits + 2));
++                            (u16)(eeprom->opcode_bits + 2));
+ 
+-    e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2));
++    e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
+ 
+     /* Prepare the EEPROM */
+     e1000_standby_eeprom(hw);
+@@ -5469,7 +5468,7 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+         e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
+                                 eeprom->opcode_bits);
+ 
+-        e1000_shift_out_ee_bits(hw, (uint16_t)(offset + words_written),
++        e1000_shift_out_ee_bits(hw, (u16)(offset + words_written),
+                                 eeprom->address_bits);
+ 
+         /* Send the data */
+@@ -5507,9 +5506,9 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+      * EEPROM out of write/erase mode.
+      */
+     e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
+-                            (uint16_t)(eeprom->opcode_bits + 2));
++                            (u16)(eeprom->opcode_bits + 2));
+ 
+-    e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2));
++    e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
+ 
+     return E1000_SUCCESS;
+ }
+@@ -5524,19 +5523,19 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+  * data - word read from the EEPROM
+  * words - number of words to read
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ {
+-    uint32_t attempts = 100000;
+-    uint32_t eecd = 0;
+-    uint32_t flop = 0;
+-    uint32_t i = 0;
+-    int32_t error = E1000_SUCCESS;
+-    uint32_t old_bank_offset = 0;
+-    uint32_t new_bank_offset = 0;
+-    uint8_t low_byte = 0;
+-    uint8_t high_byte = 0;
+-    boolean_t sector_write_failed = FALSE;
++    u32 attempts = 100000;
++    u32 eecd = 0;
++    u32 flop = 0;
++    u32 i = 0;
++    s32 error = E1000_SUCCESS;
++    u32 old_bank_offset = 0;
++    u32 new_bank_offset = 0;
++    u8 low_byte = 0;
++    u8 high_byte = 0;
++    bool sector_write_failed = false;
+ 
+     if (hw->mac_type == e1000_82573) {
+         /* The flop register will be used to determine if flash type is STM */
+@@ -5588,24 +5587,24 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+             e1000_erase_ich8_4k_segment(hw, 0);
+         }
+ 
+-        sector_write_failed = FALSE;
++        sector_write_failed = false;
+         /* Loop for every byte in the shadow RAM,
+          * which is in units of words. */
+         for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+             /* Determine whether to write the value stored
+              * in the other NVM bank or a modified value stored
+              * in the shadow RAM */
+-            if (hw->eeprom_shadow_ram[i].modified == TRUE) {
+-                low_byte = (uint8_t)hw->eeprom_shadow_ram[i].eeprom_word;
++            if (hw->eeprom_shadow_ram[i].modified) {
++                low_byte = (u8)hw->eeprom_shadow_ram[i].eeprom_word;
+                 udelay(100);
+                 error = e1000_verify_write_ich8_byte(hw,
+                             (i << 1) + new_bank_offset, low_byte);
+ 
+                 if (error != E1000_SUCCESS)
+-                    sector_write_failed = TRUE;
++                    sector_write_failed = true;
+                 else {
+                     high_byte =
+-                        (uint8_t)(hw->eeprom_shadow_ram[i].eeprom_word >> 8);
++                        (u8)(hw->eeprom_shadow_ram[i].eeprom_word >> 8);
+                     udelay(100);
+                 }
+             } else {
+@@ -5616,7 +5615,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+                             (i << 1) + new_bank_offset, low_byte);
+ 
+                 if (error != E1000_SUCCESS)
+-                    sector_write_failed = TRUE;
++                    sector_write_failed = true;
+                 else {
+                     e1000_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1,
+                                          &high_byte);
+@@ -5624,10 +5623,10 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+                 }
+             }
+ 
+-            /* If the write of the low byte was successful, go ahread and
++            /* If the write of the low byte was successful, go ahead and
+              * write the high byte while checking to make sure that if it
+              * is the signature byte, then it is handled properly */
+-            if (sector_write_failed == FALSE) {
++            if (!sector_write_failed) {
+                 /* If the word is 0x13, then make sure the signature bits
+                  * (15:14) are 11b until the commit has completed.
+                  * This will allow us to write 10b which indicates the
+@@ -5640,7 +5639,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+                 error = e1000_verify_write_ich8_byte(hw,
+                             (i << 1) + new_bank_offset + 1, high_byte);
+                 if (error != E1000_SUCCESS)
+-                    sector_write_failed = TRUE;
++                    sector_write_failed = true;
+ 
+             } else {
+                 /* If the write failed then break from the loop and
+@@ -5651,7 +5650,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ 
+         /* Don't bother writing the segment valid bits if sector
+          * programming failed. */
+-        if (sector_write_failed == FALSE) {
++        if (!sector_write_failed) {
+             /* Finally validate the new segment by setting bit 15:14
+              * to 10b in word 0x13 , this can be done without an
+              * erase as well since these bits are 11 to start with
+@@ -5673,7 +5672,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ 
+             /* Clear the now not used entry in the cache */
+             for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+-                hw->eeprom_shadow_ram[i].modified = FALSE;
++                hw->eeprom_shadow_ram[i].modified = false;
+                 hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
+             }
+         }
+@@ -5688,11 +5687,11 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_read_mac_addr(struct e1000_hw * hw)
+ {
+-    uint16_t offset;
+-    uint16_t eeprom_data, i;
++    u16 offset;
++    u16 eeprom_data, i;
+ 
+     DEBUGFUNC("e1000_read_mac_addr");
+ 
+@@ -5702,8 +5701,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
+             DEBUGOUT("EEPROM Read Error\n");
+             return -E1000_ERR_EEPROM;
+         }
+-        hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
+-        hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
++        hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF);
++        hw->perm_mac_addr[i+1] = (u8) (eeprom_data >> 8);
+     }
+ 
+     switch (hw->mac_type) {
+@@ -5735,8 +5734,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
+ static void
+ e1000_init_rx_addrs(struct e1000_hw *hw)
+ {
+-    uint32_t i;
+-    uint32_t rar_num;
++    u32 i;
++    u32 rar_num;
+ 
+     DEBUGFUNC("e1000_init_rx_addrs");
+ 
+@@ -5750,7 +5749,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
+     /* Reserve a spot for the Locally Administered Address to work around
+      * an 82571 issue in which a reset on one port will reload the MAC on
+      * the other port. */
+-    if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
++    if ((hw->mac_type == e1000_82571) && (hw->laa_is_present))
+         rar_num -= 1;
+     if (hw->mac_type == e1000_ich8lan)
+         rar_num = E1000_RAR_ENTRIES_ICH8LAN;
+@@ -5771,11 +5770,11 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
+  * hw - Struct containing variables accessed by shared code
+  * mc_addr - the multicast address to hash
+  *****************************************************************************/
+-uint32_t
++u32
+ e1000_hash_mc_addr(struct e1000_hw *hw,
+-                   uint8_t *mc_addr)
++                   u8 *mc_addr)
+ {
+-    uint32_t hash_value = 0;
++    u32 hash_value = 0;
+ 
+     /* The portion of the address that is used for the hash table is
+      * determined by the mc_filter_type setting.
+@@ -5788,37 +5787,37 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
+     case 0:
+         if (hw->mac_type == e1000_ich8lan) {
+             /* [47:38] i.e. 0x158 for above example address */
+-            hash_value = ((mc_addr[4] >> 6) | (((uint16_t) mc_addr[5]) << 2));
++            hash_value = ((mc_addr[4] >> 6) | (((u16) mc_addr[5]) << 2));
+         } else {
+             /* [47:36] i.e. 0x563 for above example address */
+-            hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
++            hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+         }
+         break;
+     case 1:
+         if (hw->mac_type == e1000_ich8lan) {
+             /* [46:37] i.e. 0x2B1 for above example address */
+-            hash_value = ((mc_addr[4] >> 5) | (((uint16_t) mc_addr[5]) << 3));
++            hash_value = ((mc_addr[4] >> 5) | (((u16) mc_addr[5]) << 3));
+         } else {
+             /* [46:35] i.e. 0xAC6 for above example address */
+-            hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
++            hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+         }
+         break;
+     case 2:
+         if (hw->mac_type == e1000_ich8lan) {
+             /*[45:36] i.e. 0x163 for above example address */
+-            hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
++            hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+         } else {
+             /* [45:34] i.e. 0x5D8 for above example address */
+-            hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
++            hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+         }
+         break;
+     case 3:
+         if (hw->mac_type == e1000_ich8lan) {
+             /* [43:34] i.e. 0x18D for above example address */
+-            hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
++            hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+         } else {
+             /* [43:32] i.e. 0x634 for above example address */
+-            hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
++            hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+         }
+         break;
+     }
+@@ -5838,11 +5837,11 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
+  *****************************************************************************/
+ void
+ e1000_mta_set(struct e1000_hw *hw,
+-              uint32_t hash_value)
++              u32 hash_value)
+ {
+-    uint32_t hash_bit, hash_reg;
+-    uint32_t mta;
+-    uint32_t temp;
++    u32 hash_bit, hash_reg;
++    u32 mta;
++    u32 temp;
+ 
+     /* The MTA is a register array of 128 32-bit registers.
+      * It is treated like an array of 4096 bits.  We want to set
+@@ -5887,18 +5886,18 @@ e1000_mta_set(struct e1000_hw *hw,
+  *****************************************************************************/
+ void
+ e1000_rar_set(struct e1000_hw *hw,
+-              uint8_t *addr,
+-              uint32_t index)
++              u8 *addr,
++              u32 index)
+ {
+-    uint32_t rar_low, rar_high;
++    u32 rar_low, rar_high;
+ 
+     /* HW expects these in little endian so we reverse the byte order
+      * from network order (big endian) to little endian
+      */
+-    rar_low = ((uint32_t) addr[0] |
+-               ((uint32_t) addr[1] << 8) |
+-               ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
+-    rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8));
++    rar_low = ((u32) addr[0] |
++               ((u32) addr[1] << 8) |
++               ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
++    rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+ 
+     /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
+      * unit hang.
+@@ -5922,7 +5921,7 @@ e1000_rar_set(struct e1000_hw *hw,
+     case e1000_82571:
+     case e1000_82572:
+     case e1000_80003es2lan:
+-        if (hw->leave_av_bit_off == TRUE)
++        if (hw->leave_av_bit_off)
+             break;
+     default:
+         /* Indicate to hardware the Address is Valid. */
+@@ -5945,10 +5944,10 @@ e1000_rar_set(struct e1000_hw *hw,
+  *****************************************************************************/
+ void
+ e1000_write_vfta(struct e1000_hw *hw,
+-                 uint32_t offset,
+-                 uint32_t value)
++                 u32 offset,
++                 u32 value)
+ {
+-    uint32_t temp;
++    u32 temp;
+ 
+     if (hw->mac_type == e1000_ich8lan)
+         return;
+@@ -5973,10 +5972,10 @@ e1000_write_vfta(struct e1000_hw *hw,
+ static void
+ e1000_clear_vfta(struct e1000_hw *hw)
+ {
+-    uint32_t offset;
+-    uint32_t vfta_value = 0;
+-    uint32_t vfta_offset = 0;
+-    uint32_t vfta_bit_in_reg = 0;
++    u32 offset;
++    u32 vfta_value = 0;
++    u32 vfta_offset = 0;
++    u32 vfta_bit_in_reg = 0;
+ 
+     if (hw->mac_type == e1000_ich8lan)
+         return;
+@@ -6004,15 +6003,15 @@ e1000_clear_vfta(struct e1000_hw *hw)
+     }
+ }
+ 
+-static int32_t
++static s32
+ e1000_id_led_init(struct e1000_hw * hw)
+ {
+-    uint32_t ledctl;
+-    const uint32_t ledctl_mask = 0x000000FF;
+-    const uint32_t ledctl_on = E1000_LEDCTL_MODE_LED_ON;
+-    const uint32_t ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
+-    uint16_t eeprom_data, i, temp;
+-    const uint16_t led_mask = 0x0F;
++    u32 ledctl;
++    const u32 ledctl_mask = 0x000000FF;
++    const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
++    const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
++    u16 eeprom_data, i, temp;
++    const u16 led_mask = 0x0F;
+ 
+     DEBUGFUNC("e1000_id_led_init");
+ 
+@@ -6087,11 +6086,11 @@ e1000_id_led_init(struct e1000_hw * hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_setup_led(struct e1000_hw *hw)
+ {
+-    uint32_t ledctl;
+-    int32_t ret_val = E1000_SUCCESS;
++    u32 ledctl;
++    s32 ret_val = E1000_SUCCESS;
+ 
+     DEBUGFUNC("e1000_setup_led");
+ 
+@@ -6112,7 +6111,7 @@ e1000_setup_led(struct e1000_hw *hw)
+         if (ret_val)
+             return ret_val;
+         ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
+-                                      (uint16_t)(hw->phy_spd_default &
++                                      (u16)(hw->phy_spd_default &
+                                       ~IGP01E1000_GMII_SPD));
+         if (ret_val)
+             return ret_val;
+@@ -6146,11 +6145,11 @@ e1000_setup_led(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_blink_led_start(struct e1000_hw *hw)
+ {
+-    int16_t  i;
+-    uint32_t ledctl_blink = 0;
++    s16  i;
++    u32 ledctl_blink = 0;
+ 
+     DEBUGFUNC("e1000_id_led_blink_on");
+ 
+@@ -6181,10 +6180,10 @@ e1000_blink_led_start(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_cleanup_led(struct e1000_hw *hw)
+ {
+-    int32_t ret_val = E1000_SUCCESS;
++    s32 ret_val = E1000_SUCCESS;
+ 
+     DEBUGFUNC("e1000_cleanup_led");
+ 
+@@ -6223,10 +6222,10 @@ e1000_cleanup_led(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_led_on(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl = E1000_READ_REG(hw, CTRL);
++    u32 ctrl = E1000_READ_REG(hw, CTRL);
+ 
+     DEBUGFUNC("e1000_led_on");
+ 
+@@ -6274,10 +6273,10 @@ e1000_led_on(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_led_off(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl = E1000_READ_REG(hw, CTRL);
++    u32 ctrl = E1000_READ_REG(hw, CTRL);
+ 
+     DEBUGFUNC("e1000_led_off");
+ 
+@@ -6328,7 +6327,7 @@ e1000_led_off(struct e1000_hw *hw)
+ static void
+ e1000_clear_hw_cntrs(struct e1000_hw *hw)
+ {
+-    volatile uint32_t temp;
++    volatile u32 temp;
+ 
+     temp = E1000_READ_REG(hw, CRCERRS);
+     temp = E1000_READ_REG(hw, SYMERRS);
+@@ -6425,7 +6424,7 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
+  * hw - Struct containing variables accessed by shared code
+  *
+  * Call this after e1000_init_hw. You may override the IFS defaults by setting
+- * hw->ifs_params_forced to TRUE. However, you must initialize hw->
++ * hw->ifs_params_forced to true. However, you must initialize hw->
+  * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
+  * before calling this function.
+  *****************************************************************************/
+@@ -6442,7 +6441,7 @@ e1000_reset_adaptive(struct e1000_hw *hw)
+             hw->ifs_step_size = IFS_STEP;
+             hw->ifs_ratio = IFS_RATIO;
+         }
+-        hw->in_ifs_mode = FALSE;
++        hw->in_ifs_mode = false;
+         E1000_WRITE_REG(hw, AIT, 0);
+     } else {
+         DEBUGOUT("Not in Adaptive IFS mode!\n");
+@@ -6465,7 +6464,7 @@ e1000_update_adaptive(struct e1000_hw *hw)
+     if (hw->adaptive_ifs) {
+         if ((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) {
+             if (hw->tx_packet_delta > MIN_NUM_XMITS) {
+-                hw->in_ifs_mode = TRUE;
++                hw->in_ifs_mode = true;
+                 if (hw->current_ifs_val < hw->ifs_max_val) {
+                     if (hw->current_ifs_val == 0)
+                         hw->current_ifs_val = hw->ifs_min_val;
+@@ -6477,7 +6476,7 @@ e1000_update_adaptive(struct e1000_hw *hw)
+         } else {
+             if (hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
+                 hw->current_ifs_val = 0;
+-                hw->in_ifs_mode = FALSE;
++                hw->in_ifs_mode = false;
+                 E1000_WRITE_REG(hw, AIT, 0);
+             }
+         }
+@@ -6496,10 +6495,10 @@ e1000_update_adaptive(struct e1000_hw *hw)
+ void
+ e1000_tbi_adjust_stats(struct e1000_hw *hw,
+                        struct e1000_hw_stats *stats,
+-                       uint32_t frame_len,
+-                       uint8_t *mac_addr)
++                       u32 frame_len,
++                       u8 *mac_addr)
+ {
+-    uint64_t carry_bit;
++    u64 carry_bit;
+ 
+     /* First adjust the frame length. */
+     frame_len--;
+@@ -6528,7 +6527,7 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
+      * since the test for a multicast frame will test positive on
+      * a broadcast frame.
+      */
+-    if ((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff))
++    if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff))
+         /* Broadcast packet */
+         stats->bprc++;
+     else if (*mac_addr & 0x01)
+@@ -6574,9 +6573,9 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
+ void
+ e1000_get_bus_info(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t pci_ex_link_status;
+-    uint32_t status;
++    s32 ret_val;
++    u16 pci_ex_link_status;
++    u32 status;
+ 
+     switch (hw->mac_type) {
+     case e1000_82542_rev2_0:
+@@ -6648,8 +6647,8 @@ e1000_get_bus_info(struct e1000_hw *hw)
+  *****************************************************************************/
+ static void
+ e1000_write_reg_io(struct e1000_hw *hw,
+-                   uint32_t offset,
+-                   uint32_t value)
++                   u32 offset,
++                   u32 value)
+ {
+     unsigned long io_addr = hw->io_base;
+     unsigned long io_data = hw->io_base + 4;
+@@ -6673,15 +6672,15 @@ e1000_write_reg_io(struct e1000_hw *hw,
+  * register to the minimum and maximum range.
+  * For IGP phy's, the function calculates the range by the AGC registers.
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_get_cable_length(struct e1000_hw *hw,
+-                       uint16_t *min_length,
+-                       uint16_t *max_length)
++                       u16 *min_length,
++                       u16 *max_length)
+ {
+-    int32_t ret_val;
+-    uint16_t agc_value = 0;
+-    uint16_t i, phy_data;
+-    uint16_t cable_length;
++    s32 ret_val;
++    u16 agc_value = 0;
++    u16 i, phy_data;
++    u16 cable_length;
+ 
+     DEBUGFUNC("e1000_get_cable_length");
+ 
+@@ -6752,9 +6751,9 @@ e1000_get_cable_length(struct e1000_hw *hw,
+             break;
+         }
+     } else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
+-        uint16_t cur_agc_value;
+-        uint16_t min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
+-        uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
++        u16 cur_agc_value;
++        u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
++        u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+                                                          {IGP01E1000_PHY_AGC_A,
+                                                           IGP01E1000_PHY_AGC_B,
+                                                           IGP01E1000_PHY_AGC_C,
+@@ -6800,9 +6799,9 @@ e1000_get_cable_length(struct e1000_hw *hw,
+                       IGP01E1000_AGC_RANGE;
+     } else if (hw->phy_type == e1000_phy_igp_2 ||
+                hw->phy_type == e1000_phy_igp_3) {
+-        uint16_t cur_agc_index, max_agc_index = 0;
+-        uint16_t min_agc_index = IGP02E1000_AGC_LENGTH_TABLE_SIZE - 1;
+-        uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
++        u16 cur_agc_index, max_agc_index = 0;
++        u16 min_agc_index = IGP02E1000_AGC_LENGTH_TABLE_SIZE - 1;
++        u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
+                                                          {IGP02E1000_PHY_AGC_A,
+                                                           IGP02E1000_PHY_AGC_B,
+                                                           IGP02E1000_PHY_AGC_C,
+@@ -6864,12 +6863,12 @@ e1000_get_cable_length(struct e1000_hw *hw,
+  * return 0.  If the link speed is 1000 Mbps the polarity status is in the
+  * IGP01E1000_PHY_PCS_INIT_REG.
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_check_polarity(struct e1000_hw *hw,
+                      e1000_rev_polarity *polarity)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_check_polarity");
+ 
+@@ -6940,11 +6939,11 @@ e1000_check_polarity(struct e1000_hw *hw,
+  * Link Health register.  In IGP this bit is latched high, so the driver must
+  * read it immediately after link is established.
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_check_downshift(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    s32 ret_val;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_check_downshift");
+ 
+@@ -6968,7 +6967,7 @@ e1000_check_downshift(struct e1000_hw *hw)
+                                M88E1000_PSSR_DOWNSHIFT_SHIFT;
+     } else if (hw->phy_type == e1000_phy_ife) {
+         /* e1000_phy_ife supports 10/100 speed only */
+-        hw->speed_downgraded = FALSE;
++        hw->speed_downgraded = false;
+     }
+ 
+     return E1000_SUCCESS;
+@@ -6986,18 +6985,18 @@ e1000_check_downshift(struct e1000_hw *hw)
+  *
+  ****************************************************************************/
+ 
+-static int32_t
++static s32
+ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
+-                                   boolean_t link_up)
++                                   bool link_up)
+ {
+-    int32_t ret_val;
+-    uint16_t phy_data, phy_saved_data, speed, duplex, i;
+-    uint16_t dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
++    s32 ret_val;
++    u16 phy_data, phy_saved_data, speed, duplex, i;
++    u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+                                         {IGP01E1000_PHY_AGC_PARAM_A,
+                                         IGP01E1000_PHY_AGC_PARAM_B,
+                                         IGP01E1000_PHY_AGC_PARAM_C,
+                                         IGP01E1000_PHY_AGC_PARAM_D};
+-    uint16_t min_length, max_length;
++    u16 min_length, max_length;
+ 
+     DEBUGFUNC("e1000_config_dsp_after_link_change");
+ 
+@@ -7039,8 +7038,8 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
+             if ((hw->ffe_config_state == e1000_ffe_config_enabled) &&
+                (min_length < e1000_igp_cable_length_50)) {
+ 
+-                uint16_t ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
+-                uint32_t idle_errs = 0;
++                u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
++                u32 idle_errs = 0;
+ 
+                 /* clear previous idle error counts */
+                 ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
+@@ -7174,11 +7173,11 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
+  *
+  * hw - Struct containing variables accessed by shared code
+  ****************************************************************************/
+-static int32_t
++static s32
+ e1000_set_phy_mode(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t eeprom_data;
++    s32 ret_val;
++    u16 eeprom_data;
+ 
+     DEBUGFUNC("e1000_set_phy_mode");
+ 
+@@ -7198,7 +7197,7 @@ e1000_set_phy_mode(struct e1000_hw *hw)
+             if (ret_val)
+                 return ret_val;
+ 
+-            hw->phy_reset_disable = FALSE;
++            hw->phy_reset_disable = false;
+         }
+     }
+ 
+@@ -7219,13 +7218,13 @@ e1000_set_phy_mode(struct e1000_hw *hw)
+  *
+  ****************************************************************************/
+ 
+-static int32_t
++static s32
+ e1000_set_d3_lplu_state(struct e1000_hw *hw,
+-                        boolean_t active)
++                        bool active)
+ {
+-    uint32_t phy_ctrl = 0;
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    u32 phy_ctrl = 0;
++    s32 ret_val;
++    u16 phy_data;
+     DEBUGFUNC("e1000_set_d3_lplu_state");
+ 
+     if (hw->phy_type != e1000_phy_igp && hw->phy_type != e1000_phy_igp_2
+@@ -7349,13 +7348,13 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
+  *
+  ****************************************************************************/
+ 
+-static int32_t
++static s32
+ e1000_set_d0_lplu_state(struct e1000_hw *hw,
+-                        boolean_t active)
++                        bool active)
+ {
+-    uint32_t phy_ctrl = 0;
+-    int32_t ret_val;
+-    uint16_t phy_data;
++    u32 phy_ctrl = 0;
++    s32 ret_val;
++    u16 phy_data;
+     DEBUGFUNC("e1000_set_d0_lplu_state");
+ 
+     if (hw->mac_type <= e1000_82547_rev_2)
+@@ -7440,12 +7439,12 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_set_vco_speed(struct e1000_hw *hw)
+ {
+-    int32_t  ret_val;
+-    uint16_t default_page = 0;
+-    uint16_t phy_data;
++    s32  ret_val;
++    u16 default_page = 0;
++    u16 phy_data;
+ 
+     DEBUGFUNC("e1000_set_vco_speed");
+ 
+@@ -7504,18 +7503,18 @@ e1000_set_vco_speed(struct e1000_hw *hw)
+  *
+  * returns: - E1000_SUCCESS .
+  ****************************************************************************/
+-static int32_t
+-e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
++static s32
++e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
+ {
+-    uint8_t i;
+-    uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET;
+-    uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH;
++    u8 i;
++    u32 offset = E1000_MNG_DHCP_COOKIE_OFFSET;
++    u8 length = E1000_MNG_DHCP_COOKIE_LENGTH;
+ 
+     length = (length >> 2);
+     offset = (offset >> 2);
+ 
+     for (i = 0; i < length; i++) {
+-        *((uint32_t *) buffer + i) =
++        *((u32 *) buffer + i) =
+             E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i);
+     }
+     return E1000_SUCCESS;
+@@ -7531,11 +7530,11 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
+  *            timeout
+  *          - E1000_SUCCESS for success.
+  ****************************************************************************/
+-static int32_t
++static s32
+ e1000_mng_enable_host_if(struct e1000_hw * hw)
+ {
+-    uint32_t hicr;
+-    uint8_t i;
++    u32 hicr;
++    u8 i;
+ 
+     /* Check that the host interface is enabled. */
+     hicr = E1000_READ_REG(hw, HICR);
+@@ -7565,14 +7564,14 @@ e1000_mng_enable_host_if(struct e1000_hw * hw)
+  *
+  * returns  - E1000_SUCCESS for success.
+  ****************************************************************************/
+-static int32_t
+-e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+-                        uint16_t length, uint16_t offset, uint8_t *sum)
++static s32
++e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer,
++                        u16 length, u16 offset, u8 *sum)
+ {
+-    uint8_t *tmp;
+-    uint8_t *bufptr = buffer;
+-    uint32_t data = 0;
+-    uint16_t remaining, i, j, prev_bytes;
++    u8 *tmp;
++    u8 *bufptr = buffer;
++    u32 data = 0;
++    u16 remaining, i, j, prev_bytes;
+ 
+     /* sum = only sum of the data and it is not checksum */
+ 
+@@ -7580,14 +7579,14 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+         return -E1000_ERR_PARAM;
+     }
+ 
+-    tmp = (uint8_t *)&data;
++    tmp = (u8 *)&data;
+     prev_bytes = offset & 0x3;
+     offset &= 0xFFFC;
+     offset >>= 2;
+ 
+     if (prev_bytes) {
+         data = E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset);
+-        for (j = prev_bytes; j < sizeof(uint32_t); j++) {
++        for (j = prev_bytes; j < sizeof(u32); j++) {
+             *(tmp + j) = *bufptr++;
+             *sum += *(tmp + j);
+         }
+@@ -7605,7 +7604,7 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+     /* The device driver writes the relevant command block into the
+      * ram area. */
+     for (i = 0; i < length; i++) {
+-        for (j = 0; j < sizeof(uint32_t); j++) {
++        for (j = 0; j < sizeof(u32); j++) {
+             *(tmp + j) = *bufptr++;
+             *sum += *(tmp + j);
+         }
+@@ -7613,7 +7612,7 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+         E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data);
+     }
+     if (remaining) {
+-        for (j = 0; j < sizeof(uint32_t); j++) {
++        for (j = 0; j < sizeof(u32); j++) {
+             if (j < remaining)
+                 *(tmp + j) = *bufptr++;
+             else
+@@ -7633,23 +7632,23 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+  *
+  * returns  - E1000_SUCCESS for success.
+  ****************************************************************************/
+-static int32_t
++static s32
+ e1000_mng_write_cmd_header(struct e1000_hw * hw,
+                            struct e1000_host_mng_command_header * hdr)
+ {
+-    uint16_t i;
+-    uint8_t sum;
+-    uint8_t *buffer;
++    u16 i;
++    u8 sum;
++    u8 *buffer;
+ 
+     /* Write the whole command header structure which includes sum of
+      * the buffer */
+ 
+-    uint16_t length = sizeof(struct e1000_host_mng_command_header);
++    u16 length = sizeof(struct e1000_host_mng_command_header);
+ 
+     sum = hdr->checksum;
+     hdr->checksum = 0;
+ 
+-    buffer = (uint8_t *) hdr;
++    buffer = (u8 *) hdr;
+     i = length;
+     while (i--)
+         sum += buffer[i];
+@@ -7659,7 +7658,7 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
+     length >>= 2;
+     /* The device driver writes the relevant command block into the ram area. */
+     for (i = 0; i < length; i++) {
+-        E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((uint32_t *) hdr + i));
++        E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *) hdr + i));
+         E1000_WRITE_FLUSH(hw);
+     }
+ 
+@@ -7673,10 +7672,10 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
+  *
+  * returns  - E1000_SUCCESS for success.
+  ****************************************************************************/
+-static int32_t
++static s32
+ e1000_mng_write_commit(struct e1000_hw * hw)
+ {
+-    uint32_t hicr;
++    u32 hicr;
+ 
+     hicr = E1000_READ_REG(hw, HICR);
+     /* Setting this bit tells the ARC that a new command is pending. */
+@@ -7689,35 +7688,35 @@ e1000_mng_write_commit(struct e1000_hw * hw)
+ /*****************************************************************************
+  * This function checks the mode of the firmware.
+  *
+- * returns  - TRUE when the mode is IAMT or FALSE.
++ * returns  - true when the mode is IAMT or false.
+  ****************************************************************************/
+-boolean_t
++bool
+ e1000_check_mng_mode(struct e1000_hw *hw)
+ {
+-    uint32_t fwsm;
++    u32 fwsm;
+ 
+     fwsm = E1000_READ_REG(hw, FWSM);
+ 
+     if (hw->mac_type == e1000_ich8lan) {
+         if ((fwsm & E1000_FWSM_MODE_MASK) ==
+             (E1000_MNG_ICH_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+-            return TRUE;
++            return true;
+     } else if ((fwsm & E1000_FWSM_MODE_MASK) ==
+                (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+-        return TRUE;
++        return true;
+ 
+-    return FALSE;
++    return false;
+ }
+ 
+ 
+ /*****************************************************************************
+  * This function writes the dhcp info .
+  ****************************************************************************/
+-int32_t
+-e1000_mng_write_dhcp_info(struct e1000_hw * hw, uint8_t *buffer,
+-                          uint16_t length)
++s32
++e1000_mng_write_dhcp_info(struct e1000_hw * hw, u8 *buffer,
++                          u16 length)
+ {
+-    int32_t ret_val;
++    s32 ret_val;
+     struct e1000_host_mng_command_header hdr;
+ 
+     hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
+@@ -7745,11 +7744,11 @@ e1000_mng_write_dhcp_info(struct e1000_hw * hw, uint8_t *buffer,
+  *
+  * returns  - checksum of buffer contents.
+  ****************************************************************************/
+-static uint8_t
+-e1000_calculate_mng_checksum(char *buffer, uint32_t length)
++static u8
++e1000_calculate_mng_checksum(char *buffer, u32 length)
+ {
+-    uint8_t sum = 0;
+-    uint32_t i;
++    u8 sum = 0;
++    u32 i;
+ 
+     if (!buffer)
+         return 0;
+@@ -7757,23 +7756,23 @@ e1000_calculate_mng_checksum(char *buffer, uint32_t length)
+     for (i=0; i < length; i++)
+         sum += buffer[i];
+ 
+-    return (uint8_t) (0 - sum);
++    return (u8) (0 - sum);
+ }
+ 
+ /*****************************************************************************
+  * This function checks whether tx pkt filtering needs to be enabled or not.
+  *
+- * returns  - TRUE for packet filtering or FALSE.
++ * returns  - true for packet filtering or false.
+  ****************************************************************************/
+-boolean_t
++bool
+ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ {
+     /* called in init as well as watchdog timer functions */
+ 
+-    int32_t ret_val, checksum;
+-    boolean_t tx_filter = FALSE;
++    s32 ret_val, checksum;
++    bool tx_filter = false;
+     struct e1000_host_mng_dhcp_cookie *hdr = &(hw->mng_cookie);
+-    uint8_t *buffer = (uint8_t *) &(hw->mng_cookie);
++    u8 *buffer = (u8 *) &(hw->mng_cookie);
+ 
+     if (e1000_check_mng_mode(hw)) {
+         ret_val = e1000_mng_enable_host_if(hw);
+@@ -7787,11 +7786,11 @@ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+                                                E1000_MNG_DHCP_COOKIE_LENGTH)) {
+                     if (hdr->status &
+                         E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT)
+-                        tx_filter = TRUE;
++                        tx_filter = true;
+                 } else
+-                    tx_filter = TRUE;
++                    tx_filter = true;
+             } else
+-                tx_filter = TRUE;
++                tx_filter = true;
+         }
+     }
+ 
+@@ -7804,41 +7803,41 @@ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *
+- * returns: - TRUE/FALSE
++ * returns: - true/false
+  *
+  *****************************************************************************/
+-uint32_t
++u32
+ e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+ {
+-    uint32_t manc;
+-    uint32_t fwsm, factps;
++    u32 manc;
++    u32 fwsm, factps;
+ 
+     if (hw->asf_firmware_present) {
+         manc = E1000_READ_REG(hw, MANC);
+ 
+         if (!(manc & E1000_MANC_RCV_TCO_EN) ||
+             !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+-            return FALSE;
+-        if (e1000_arc_subsystem_valid(hw) == TRUE) {
++            return false;
++        if (e1000_arc_subsystem_valid(hw)) {
+             fwsm = E1000_READ_REG(hw, FWSM);
+             factps = E1000_READ_REG(hw, FACTPS);
+ 
+             if ((((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT) ==
+                    e1000_mng_mode_pt) && !(factps & E1000_FACTPS_MNGCG))
+-                return TRUE;
++                return true;
+         } else
+             if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
+-                return TRUE;
++                return true;
+     }
+-    return FALSE;
++    return false;
+ }
+ 
+-static int32_t
++static s32
+ e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+ {
+-    int32_t ret_val;
+-    uint16_t mii_status_reg;
+-    uint16_t i;
++    s32 ret_val;
++    u16 mii_status_reg;
++    u16 i;
+ 
+     /* Polarity reversal workaround for forced 10F/10H links. */
+ 
+@@ -7930,7 +7929,7 @@ e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+ static void
+ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+ {
+-    uint32_t ctrl;
++    u32 ctrl;
+ 
+     DEBUGFUNC("e1000_set_pci_express_master_disable");
+ 
+@@ -7953,10 +7952,10 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+  *            E1000_SUCCESS master requests disabled.
+  *
+  ******************************************************************************/
+-int32_t
++s32
+ e1000_disable_pciex_master(struct e1000_hw *hw)
+ {
+-    int32_t timeout = MASTER_DISABLE_TIMEOUT;   /* 80ms */
++    s32 timeout = MASTER_DISABLE_TIMEOUT;   /* 80ms */
+ 
+     DEBUGFUNC("e1000_disable_pciex_master");
+ 
+@@ -7991,10 +7990,10 @@ e1000_disable_pciex_master(struct e1000_hw *hw)
+  *            E1000_SUCCESS at any other case.
+  *
+  ******************************************************************************/
+-static int32_t
++static s32
+ e1000_get_auto_rd_done(struct e1000_hw *hw)
+ {
+-    int32_t timeout = AUTO_READ_DONE_TIMEOUT;
++    s32 timeout = AUTO_READ_DONE_TIMEOUT;
+ 
+     DEBUGFUNC("e1000_get_auto_rd_done");
+ 
+@@ -8039,11 +8038,11 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
+  *            E1000_SUCCESS at any other case.
+  *
+  ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_phy_cfg_done(struct e1000_hw *hw)
+ {
+-    int32_t timeout = PHY_CFG_TIMEOUT;
+-    uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
++    s32 timeout = PHY_CFG_TIMEOUT;
++    u32 cfg_mask = E1000_EEPROM_CFG_DONE;
+ 
+     DEBUGFUNC("e1000_get_phy_cfg_done");
+ 
+@@ -8086,11 +8085,11 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
+  *            E1000_SUCCESS at any other case.
+  *
+  ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+ {
+-    int32_t timeout;
+-    uint32_t swsm;
++    s32 timeout;
++    u32 swsm;
+ 
+     DEBUGFUNC("e1000_get_hw_eeprom_semaphore");
+ 
+@@ -8139,7 +8138,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+ static void
+ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+ {
+-    uint32_t swsm;
++    u32 swsm;
+ 
+     DEBUGFUNC("e1000_put_hw_eeprom_semaphore");
+ 
+@@ -8165,11 +8164,11 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+  *            E1000_SUCCESS at any other case.
+  *
+  ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_software_semaphore(struct e1000_hw *hw)
+ {
+-    int32_t timeout = hw->eeprom.word_size + 1;
+-    uint32_t swsm;
++    s32 timeout = hw->eeprom.word_size + 1;
++    u32 swsm;
+ 
+     DEBUGFUNC("e1000_get_software_semaphore");
+ 
+@@ -8204,7 +8203,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
+ static void
+ e1000_release_software_semaphore(struct e1000_hw *hw)
+ {
+-    uint32_t swsm;
++    u32 swsm;
+ 
+     DEBUGFUNC("e1000_release_software_semaphore");
+ 
+@@ -8229,11 +8228,11 @@ e1000_release_software_semaphore(struct e1000_hw *hw)
+  *            E1000_SUCCESS
+  *
+  *****************************************************************************/
+-int32_t
++s32
+ e1000_check_phy_reset_block(struct e1000_hw *hw)
+ {
+-    uint32_t manc = 0;
+-    uint32_t fwsm = 0;
++    u32 manc = 0;
++    u32 fwsm = 0;
+ 
+     if (hw->mac_type == e1000_ich8lan) {
+         fwsm = E1000_READ_REG(hw, FWSM);
+@@ -8247,10 +8246,10 @@ e1000_check_phy_reset_block(struct e1000_hw *hw)
+         E1000_BLK_PHY_RESET : E1000_SUCCESS;
+ }
+ 
+-static uint8_t
++static u8
+ e1000_arc_subsystem_valid(struct e1000_hw *hw)
+ {
+-    uint32_t fwsm;
++    u32 fwsm;
+ 
+     /* On 8257x silicon, registers in the range of 0x8800 - 0x8FFC
+      * may not be provided a DMA clock when no manageability features are
+@@ -8264,14 +8263,14 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
+     case e1000_80003es2lan:
+         fwsm = E1000_READ_REG(hw, FWSM);
+         if ((fwsm & E1000_FWSM_MODE_MASK) != 0)
+-            return TRUE;
++            return true;
+         break;
+     case e1000_ich8lan:
+-        return TRUE;
++        return true;
+     default:
+         break;
+     }
+-    return FALSE;
++    return false;
+ }
+ 
+ 
+@@ -8284,10 +8283,10 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
+  * returns: E1000_SUCCESS
+  *
+  *****************************************************************************/
+-static int32_t
+-e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
++static s32
++e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
+ {
+-    uint32_t gcr_reg = 0;
++    u32 gcr_reg = 0;
+ 
+     DEBUGFUNC("e1000_set_pci_ex_no_snoop");
+ 
+@@ -8304,7 +8303,7 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
+         E1000_WRITE_REG(hw, GCR, gcr_reg);
+     }
+     if (hw->mac_type == e1000_ich8lan) {
+-        uint32_t ctrl_ext;
++        u32 ctrl_ext;
+ 
+         E1000_WRITE_REG(hw, GCR, PCI_EX_82566_SNOOP_ALL);
+ 
+@@ -8325,11 +8324,11 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
+  * hw: Struct containing variables accessed by shared code
+  *
+  ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_software_flag(struct e1000_hw *hw)
+ {
+-    int32_t timeout = PHY_CFG_TIMEOUT;
+-    uint32_t extcnf_ctrl;
++    s32 timeout = PHY_CFG_TIMEOUT;
++    u32 extcnf_ctrl;
+ 
+     DEBUGFUNC("e1000_get_software_flag");
+ 
+@@ -8367,7 +8366,7 @@ e1000_get_software_flag(struct e1000_hw *hw)
+ static void
+ e1000_release_software_flag(struct e1000_hw *hw)
+ {
+-    uint32_t extcnf_ctrl;
++    u32 extcnf_ctrl;
+ 
+     DEBUGFUNC("e1000_release_software_flag");
+ 
+@@ -8389,16 +8388,16 @@ e1000_release_software_flag(struct e1000_hw *hw)
+  * data - word read from the EEPROM
+  * words - number of words to read
+  *****************************************************************************/
+-static int32_t
+-e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+-                       uint16_t *data)
++static s32
++e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
++                       u16 *data)
+ {
+-    int32_t  error = E1000_SUCCESS;
+-    uint32_t flash_bank = 0;
+-    uint32_t act_offset = 0;
+-    uint32_t bank_offset = 0;
+-    uint16_t word = 0;
+-    uint16_t i = 0;
++    s32  error = E1000_SUCCESS;
++    u32 flash_bank = 0;
++    u32 act_offset = 0;
++    u32 bank_offset = 0;
++    u16 word = 0;
++    u16 i = 0;
+ 
+     /* We need to know which is the valid flash bank.  In the event
+      * that we didn't allocate eeprom_shadow_ram, we may not be
+@@ -8417,7 +8416,7 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+ 
+     for (i = 0; i < words; i++) {
+         if (hw->eeprom_shadow_ram != NULL &&
+-            hw->eeprom_shadow_ram[offset+i].modified == TRUE) {
++            hw->eeprom_shadow_ram[offset+i].modified) {
+             data[i] = hw->eeprom_shadow_ram[offset+i].eeprom_word;
+         } else {
+             /* The NVM part needs a byte offset, hence * 2 */
+@@ -8445,12 +8444,12 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+  * words - number of words to write
+  * data - words to write to the EEPROM
+  *****************************************************************************/
+-static int32_t
+-e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+-                        uint16_t *data)
++static s32
++e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
++                        u16 *data)
+ {
+-    uint32_t i = 0;
+-    int32_t error = E1000_SUCCESS;
++    u32 i = 0;
++    s32 error = E1000_SUCCESS;
+ 
+     error = e1000_get_software_flag(hw);
+     if (error != E1000_SUCCESS)
+@@ -8466,7 +8465,7 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+     if (hw->eeprom_shadow_ram != NULL) {
+         for (i = 0; i < words; i++) {
+             if ((offset + i) < E1000_SHADOW_RAM_WORDS) {
+-                hw->eeprom_shadow_ram[offset+i].modified = TRUE;
++                hw->eeprom_shadow_ram[offset+i].modified = true;
+                 hw->eeprom_shadow_ram[offset+i].eeprom_word = data[i];
+             } else {
+                 error = -E1000_ERR_EEPROM;
+@@ -8492,12 +8491,12 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+  *
+  * hw - The pointer to the hw structure
+  ****************************************************************************/
+-static int32_t
++static s32
+ e1000_ich8_cycle_init(struct e1000_hw *hw)
+ {
+     union ich8_hws_flash_status hsfsts;
+-    int32_t error = E1000_ERR_EEPROM;
+-    int32_t i     = 0;
++    s32 error = E1000_ERR_EEPROM;
++    s32 i     = 0;
+ 
+     DEBUGFUNC("e1000_ich8_cycle_init");
+ 
+@@ -8559,13 +8558,13 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
+  *
+  * hw - The pointer to the hw structure
+  ****************************************************************************/
+-static int32_t
+-e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
++static s32
++e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
+ {
+     union ich8_hws_flash_ctrl hsflctl;
+     union ich8_hws_flash_status hsfsts;
+-    int32_t error = E1000_ERR_EEPROM;
+-    uint32_t i = 0;
++    s32 error = E1000_ERR_EEPROM;
++    u32 i = 0;
+ 
+     /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
+     hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+@@ -8594,16 +8593,16 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
+  * size - Size of data to read, 1=byte 2=word
+  * data - Pointer to the word to store the value read.
+  *****************************************************************************/
+-static int32_t
+-e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+-                     uint32_t size, uint16_t* data)
++static s32
++e1000_read_ich8_data(struct e1000_hw *hw, u32 index,
++                     u32 size, u16* data)
+ {
+     union ich8_hws_flash_status hsfsts;
+     union ich8_hws_flash_ctrl hsflctl;
+-    uint32_t flash_linear_address;
+-    uint32_t flash_data = 0;
+-    int32_t error = -E1000_ERR_EEPROM;
+-    int32_t count = 0;
++    u32 flash_linear_address;
++    u32 flash_data = 0;
++    s32 error = -E1000_ERR_EEPROM;
++    s32 count = 0;
+ 
+     DEBUGFUNC("e1000_read_ich8_data");
+ 
+@@ -8641,9 +8640,9 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+         if (error == E1000_SUCCESS) {
+             flash_data = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0);
+             if (size == 1) {
+-                *data = (uint8_t)(flash_data & 0x000000FF);
++                *data = (u8)(flash_data & 0x000000FF);
+             } else if (size == 2) {
+-                *data = (uint16_t)(flash_data & 0x0000FFFF);
++                *data = (u16)(flash_data & 0x0000FFFF);
+             }
+             break;
+         } else {
+@@ -8673,16 +8672,16 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+  * size - Size of data to read, 1=byte 2=word
+  * data - The byte(s) to write to the NVM.
+  *****************************************************************************/
+-static int32_t
+-e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+-                      uint16_t data)
++static s32
++e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
++                      u16 data)
+ {
+     union ich8_hws_flash_status hsfsts;
+     union ich8_hws_flash_ctrl hsflctl;
+-    uint32_t flash_linear_address;
+-    uint32_t flash_data = 0;
+-    int32_t error = -E1000_ERR_EEPROM;
+-    int32_t count = 0;
++    u32 flash_linear_address;
++    u32 flash_data = 0;
++    s32 error = -E1000_ERR_EEPROM;
++    s32 count = 0;
+ 
+     DEBUGFUNC("e1000_write_ich8_data");
+ 
+@@ -8711,9 +8710,9 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+         E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address);
+ 
+         if (size == 1)
+-            flash_data = (uint32_t)data & 0x00FF;
++            flash_data = (u32)data & 0x00FF;
+         else
+-            flash_data = (uint32_t)data;
++            flash_data = (u32)data;
+ 
+         E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
+ 
+@@ -8748,15 +8747,15 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+  * index - The index of the byte to read.
+  * data - Pointer to a byte to store the value read.
+  *****************************************************************************/
+-static int32_t
+-e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
++static s32
++e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8* data)
+ {
+-    int32_t status = E1000_SUCCESS;
+-    uint16_t word = 0;
++    s32 status = E1000_SUCCESS;
++    u16 word = 0;
+ 
+     status = e1000_read_ich8_data(hw, index, 1, &word);
+     if (status == E1000_SUCCESS) {
+-        *data = (uint8_t)word;
++        *data = (u8)word;
+     }
+ 
+     return status;
+@@ -8771,11 +8770,11 @@ e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
+  * index - The index of the byte to write.
+  * byte - The byte to write to the NVM.
+  *****************************************************************************/
+-static int32_t
+-e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
++static s32
++e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
+ {
+-    int32_t error = E1000_SUCCESS;
+-    int32_t program_retries = 0;
++    s32 error = E1000_SUCCESS;
++    s32 program_retries = 0;
+ 
+     DEBUGOUT2("Byte := %2.2X Offset := %d\n", byte, index);
+ 
+@@ -8804,11 +8803,11 @@ e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
+  * index - The index of the byte to read.
+  * data - The byte to write to the NVM.
+  *****************************************************************************/
+-static int32_t
+-e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
++static s32
++e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
+ {
+-    int32_t status = E1000_SUCCESS;
+-    uint16_t word = (uint16_t)data;
++    s32 status = E1000_SUCCESS;
++    u16 word = (u16)data;
+ 
+     status = e1000_write_ich8_data(hw, index, 1, word);
+ 
+@@ -8822,10 +8821,10 @@ e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
+  * index - The starting byte index of the word to read.
+  * data - Pointer to a word to store the value read.
+  *****************************************************************************/
+-static int32_t
+-e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
++static s32
++e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
+ {
+-    int32_t status = E1000_SUCCESS;
++    s32 status = E1000_SUCCESS;
+     status = e1000_read_ich8_data(hw, index, 2, data);
+     return status;
+ }
+@@ -8841,19 +8840,19 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
+  * amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the
+  * bank size may be 4, 8 or 64 KBytes
+  *****************************************************************************/
+-static int32_t
+-e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
++static s32
++e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
+ {
+     union ich8_hws_flash_status hsfsts;
+     union ich8_hws_flash_ctrl hsflctl;
+-    uint32_t flash_linear_address;
+-    int32_t  count = 0;
+-    int32_t  error = E1000_ERR_EEPROM;
+-    int32_t  iteration;
+-    int32_t  sub_sector_size = 0;
+-    int32_t  bank_size;
+-    int32_t  j = 0;
+-    int32_t  error_flag = 0;
++    u32 flash_linear_address;
++    s32  count = 0;
++    s32  error = E1000_ERR_EEPROM;
++    s32  iteration;
++    s32  sub_sector_size = 0;
++    s32  bank_size;
++    s32  j = 0;
++    s32  error_flag = 0;
+ 
+     hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
+ 
+@@ -8931,16 +8930,16 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
+     return error;
+ }
+ 
+-static int32_t
++static s32
+ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+-                                      uint32_t cnf_base_addr, uint32_t cnf_size)
++                                      u32 cnf_base_addr, u32 cnf_size)
+ {
+-    uint32_t ret_val = E1000_SUCCESS;
+-    uint16_t word_addr, reg_data, reg_addr;
+-    uint16_t i;
++    u32 ret_val = E1000_SUCCESS;
++    u16 word_addr, reg_data, reg_addr;
++    u16 i;
+ 
+     /* cnf_base_addr is in DWORD */
+-    word_addr = (uint16_t)(cnf_base_addr << 1);
++    word_addr = (u16)(cnf_base_addr << 1);
+ 
+     /* cnf_size is returned in size of dwords */
+     for (i = 0; i < cnf_size; i++) {
+@@ -8956,7 +8955,7 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+         if (ret_val != E1000_SUCCESS)
+             return ret_val;
+ 
+-        ret_val = e1000_write_phy_reg_ex(hw, (uint32_t)reg_addr, reg_data);
++        ret_val = e1000_write_phy_reg_ex(hw, (u32)reg_addr, reg_data);
+ 
+         e1000_release_software_flag(hw);
+     }
+@@ -8973,10 +8972,10 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+  *
+  * hw: Struct containing variables accessed by shared code
+  *****************************************************************************/
+-static int32_t
++static s32
+ e1000_init_lcd_from_nvm(struct e1000_hw *hw)
+ {
+-    uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop;
++    u32 reg_data, cnf_base_addr, cnf_size, ret_val, loop;
+ 
+     if (hw->phy_type != e1000_phy_igp_3)
+           return E1000_SUCCESS;
+diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
+index a6c3c34..99fce2c 100644
+--- a/drivers/net/e1000/e1000_hw.h
++++ b/drivers/net/e1000/e1000_hw.h
+@@ -100,8 +100,8 @@ typedef enum {
+ } e1000_fc_type;
+ 
+ struct e1000_shadow_ram {
+-    uint16_t    eeprom_word;
+-    boolean_t   modified;
++    u16 eeprom_word;
++    bool modified;
+ };
+ 
+ /* PCI bus types */
+@@ -263,19 +263,19 @@ struct e1000_phy_info {
+ };
+ 
+ struct e1000_phy_stats {
+-    uint32_t idle_errors;
+-    uint32_t receive_errors;
++    u32 idle_errors;
++    u32 receive_errors;
+ };
+ 
+ struct e1000_eeprom_info {
+     e1000_eeprom_type type;
+-    uint16_t word_size;
+-    uint16_t opcode_bits;
+-    uint16_t address_bits;
+-    uint16_t delay_usec;
+-    uint16_t page_size;
+-    boolean_t use_eerd;
+-    boolean_t use_eewr;
++    u16 word_size;
++    u16 opcode_bits;
++    u16 address_bits;
++    u16 delay_usec;
++    u16 page_size;
++    bool use_eerd;
++    bool use_eewr;
+ };
+ 
+ /* Flex ASF Information */
+@@ -308,34 +308,34 @@ typedef enum {
+ 
+ /* Function prototypes */
+ /* Initialization */
+-int32_t e1000_reset_hw(struct e1000_hw *hw);
+-int32_t e1000_init_hw(struct e1000_hw *hw);
+-int32_t e1000_set_mac_type(struct e1000_hw *hw);
++s32 e1000_reset_hw(struct e1000_hw *hw);
++s32 e1000_init_hw(struct e1000_hw *hw);
++s32 e1000_set_mac_type(struct e1000_hw *hw);
+ void e1000_set_media_type(struct e1000_hw *hw);
+ 
+ /* Link Configuration */
+-int32_t e1000_setup_link(struct e1000_hw *hw);
+-int32_t e1000_phy_setup_autoneg(struct e1000_hw *hw);
++s32 e1000_setup_link(struct e1000_hw *hw);
++s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
+ void e1000_config_collision_dist(struct e1000_hw *hw);
+-int32_t e1000_check_for_link(struct e1000_hw *hw);
+-int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed, uint16_t *duplex);
+-int32_t e1000_force_mac_fc(struct e1000_hw *hw);
++s32 e1000_check_for_link(struct e1000_hw *hw);
++s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex);
++s32 e1000_force_mac_fc(struct e1000_hw *hw);
+ 
+ /* PHY */
+-int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
+-int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
+-int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
+-int32_t e1000_phy_reset(struct e1000_hw *hw);
+-int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+-int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
++s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data);
++s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 data);
++s32 e1000_phy_hw_reset(struct e1000_hw *hw);
++s32 e1000_phy_reset(struct e1000_hw *hw);
++s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++s32 e1000_validate_mdi_setting(struct e1000_hw *hw);
+ 
+ void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
+ 
+ /* EEPROM Functions */
+-int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
++s32 e1000_init_eeprom_params(struct e1000_hw *hw);
+ 
+ /* MNG HOST IF functions */
+-uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
++u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+ 
+ #define E1000_MNG_DHCP_TX_PAYLOAD_CMD   64
+ #define E1000_HI_MAX_MNG_DATA_LENGTH    0x6F8   /* Host Interface data length */
+@@ -354,80 +354,80 @@ uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+ #define E1000_VFTA_ENTRY_BIT_SHIFT_MASK              0x1F
+ 
+ struct e1000_host_mng_command_header {
+-    uint8_t command_id;
+-    uint8_t checksum;
+-    uint16_t reserved1;
+-    uint16_t reserved2;
+-    uint16_t command_length;
++    u8 command_id;
++    u8 checksum;
++    u16 reserved1;
++    u16 reserved2;
++    u16 command_length;
+ };
+ 
+ struct e1000_host_mng_command_info {
+     struct e1000_host_mng_command_header command_header;  /* Command Head/Command Result Head has 4 bytes */
+-    uint8_t command_data[E1000_HI_MAX_MNG_DATA_LENGTH];   /* Command data can length 0..0x658*/
++    u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];   /* Command data can length 0..0x658*/
+ };
+ #ifdef __BIG_ENDIAN
+ struct e1000_host_mng_dhcp_cookie{
+-    uint32_t signature;
+-    uint16_t vlan_id;
+-    uint8_t reserved0;
+-    uint8_t status;
+-    uint32_t reserved1;
+-    uint8_t checksum;
+-    uint8_t reserved3;
+-    uint16_t reserved2;
++    u32 signature;
++    u16 vlan_id;
++    u8 reserved0;
++    u8 status;
++    u32 reserved1;
++    u8 checksum;
++    u8 reserved3;
++    u16 reserved2;
+ };
+ #else
+ struct e1000_host_mng_dhcp_cookie{
+-    uint32_t signature;
+-    uint8_t status;
+-    uint8_t reserved0;
+-    uint16_t vlan_id;
+-    uint32_t reserved1;
+-    uint16_t reserved2;
+-    uint8_t reserved3;
+-    uint8_t checksum;
++    u32 signature;
++    u8 status;
++    u8 reserved0;
++    u16 vlan_id;
++    u32 reserved1;
++    u16 reserved2;
++    u8 reserved3;
++    u8 checksum;
+ };
+ #endif
+ 
+-int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
+-                                  uint16_t length);
+-boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
+-boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
+-int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
+-int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw);
+-int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
+-int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
+-int32_t e1000_read_mac_addr(struct e1000_hw * hw);
++s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer,
++                                  u16 length);
++bool e1000_check_mng_mode(struct e1000_hw *hw);
++bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
++s32 e1000_read_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 *data);
++s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw);
++s32 e1000_update_eeprom_checksum(struct e1000_hw *hw);
++s32 e1000_write_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 *data);
++s32 e1000_read_mac_addr(struct e1000_hw * hw);
+ 
+ /* Filters (multicast, vlan, receive) */
+-uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
+-void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
+-void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
+-void e1000_write_vfta(struct e1000_hw *hw, uint32_t offset, uint32_t value);
++u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 * mc_addr);
++void e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
++void e1000_rar_set(struct e1000_hw *hw, u8 * mc_addr, u32 rar_index);
++void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
+ 
+ /* LED functions */
+-int32_t e1000_setup_led(struct e1000_hw *hw);
+-int32_t e1000_cleanup_led(struct e1000_hw *hw);
+-int32_t e1000_led_on(struct e1000_hw *hw);
+-int32_t e1000_led_off(struct e1000_hw *hw);
+-int32_t e1000_blink_led_start(struct e1000_hw *hw);
++s32 e1000_setup_led(struct e1000_hw *hw);
++s32 e1000_cleanup_led(struct e1000_hw *hw);
++s32 e1000_led_on(struct e1000_hw *hw);
++s32 e1000_led_off(struct e1000_hw *hw);
++s32 e1000_blink_led_start(struct e1000_hw *hw);
+ 
+ /* Adaptive IFS Functions */
+ 
+ /* Everything else */
+ void e1000_reset_adaptive(struct e1000_hw *hw);
+ void e1000_update_adaptive(struct e1000_hw *hw);
+-void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr);
++void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, u32 frame_len, u8 * mac_addr);
+ void e1000_get_bus_info(struct e1000_hw *hw);
+ void e1000_pci_set_mwi(struct e1000_hw *hw);
+ void e1000_pci_clear_mwi(struct e1000_hw *hw);
+-int32_t e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value);
++s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+ void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc);
+ int e1000_pcix_get_mmrbc(struct e1000_hw *hw);
+ /* Port I/O is only supported on 82544 and newer */
+-void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
+-int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
+-int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
++void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value);
++s32 e1000_disable_pciex_master(struct e1000_hw *hw);
++s32 e1000_check_phy_reset_block(struct e1000_hw *hw);
+ 
+ 
+ #define E1000_READ_REG_IO(a, reg) \
+@@ -596,8 +596,8 @@ struct e1000_rx_desc {
+     __le64 buffer_addr; /* Address of the descriptor's data buffer */
+     __le16 length;     /* Length of data DMAed into data buffer */
+     __le16 csum;       /* Packet checksum */
+-    uint8_t status;      /* Descriptor status */
+-    uint8_t errors;      /* Descriptor Errors */
++    u8 status;      /* Descriptor status */
++    u8 errors;      /* Descriptor Errors */
+     __le16 special;
+ };
+ 
+@@ -718,15 +718,15 @@ struct e1000_tx_desc {
+         __le32 data;
+         struct {
+             __le16 length;    /* Data buffer length */
+-            uint8_t cso;        /* Checksum offset */
+-            uint8_t cmd;        /* Descriptor control */
++            u8 cso;        /* Checksum offset */
++            u8 cmd;        /* Descriptor control */
+         } flags;
+     } lower;
+     union {
+         __le32 data;
+         struct {
+-            uint8_t status;     /* Descriptor status */
+-            uint8_t css;        /* Checksum start */
++            u8 status;     /* Descriptor status */
++            u8 css;        /* Checksum start */
+             __le16 special;
+         } fields;
+     } upper;
+@@ -759,16 +759,16 @@ struct e1000_context_desc {
+     union {
+         __le32 ip_config;
+         struct {
+-            uint8_t ipcss;      /* IP checksum start */
+-            uint8_t ipcso;      /* IP checksum offset */
++            u8 ipcss;      /* IP checksum start */
++            u8 ipcso;      /* IP checksum offset */
+             __le16 ipcse;     /* IP checksum end */
+         } ip_fields;
+     } lower_setup;
+     union {
+         __le32 tcp_config;
+         struct {
+-            uint8_t tucss;      /* TCP checksum start */
+-            uint8_t tucso;      /* TCP checksum offset */
++            u8 tucss;      /* TCP checksum start */
++            u8 tucso;      /* TCP checksum offset */
+             __le16 tucse;     /* TCP checksum end */
+         } tcp_fields;
+     } upper_setup;
+@@ -776,8 +776,8 @@ struct e1000_context_desc {
+     union {
+         __le32 data;
+         struct {
+-            uint8_t status;     /* Descriptor status */
+-            uint8_t hdr_len;    /* Header length */
++            u8 status;     /* Descriptor status */
++            u8 hdr_len;    /* Header length */
+             __le16 mss;       /* Maximum segment size */
+         } fields;
+     } tcp_seg_setup;
+@@ -790,15 +790,15 @@ struct e1000_data_desc {
+         __le32 data;
+         struct {
+             __le16 length;    /* Data buffer length */
+-            uint8_t typ_len_ext;        /* */
+-            uint8_t cmd;        /* */
++            u8 typ_len_ext;        /* */
++            u8 cmd;        /* */
+         } flags;
+     } lower;
+     union {
+         __le32 data;
+         struct {
+-            uint8_t status;     /* Descriptor status */
+-            uint8_t popts;      /* Packet Options */
++            u8 status;     /* Descriptor status */
++            u8 popts;      /* Packet Options */
+             __le16 special;   /* */
+         } fields;
+     } upper;
+@@ -825,8 +825,8 @@ struct e1000_rar {
+ 
+ /* IPv4 Address Table Entry */
+ struct e1000_ipv4_at_entry {
+-    volatile uint32_t ipv4_addr;        /* IP Address (RW) */
+-    volatile uint32_t reserved;
++    volatile u32 ipv4_addr;        /* IP Address (RW) */
++    volatile u32 reserved;
+ };
+ 
+ /* Four wakeup IP addresses are supported */
+@@ -837,25 +837,25 @@ struct e1000_ipv4_at_entry {
+ 
+ /* IPv6 Address Table Entry */
+ struct e1000_ipv6_at_entry {
+-    volatile uint8_t ipv6_addr[16];
++    volatile u8 ipv6_addr[16];
+ };
+ 
+ /* Flexible Filter Length Table Entry */
+ struct e1000_fflt_entry {
+-    volatile uint32_t length;   /* Flexible Filter Length (RW) */
+-    volatile uint32_t reserved;
++    volatile u32 length;   /* Flexible Filter Length (RW) */
++    volatile u32 reserved;
+ };
+ 
+ /* Flexible Filter Mask Table Entry */
+ struct e1000_ffmt_entry {
+-    volatile uint32_t mask;     /* Flexible Filter Mask (RW) */
+-    volatile uint32_t reserved;
++    volatile u32 mask;     /* Flexible Filter Mask (RW) */
++    volatile u32 reserved;
+ };
+ 
+ /* Flexible Filter Value Table Entry */
+ struct e1000_ffvt_entry {
+-    volatile uint32_t value;    /* Flexible Filter Value (RW) */
+-    volatile uint32_t reserved;
++    volatile u32 value;    /* Flexible Filter Value (RW) */
++    volatile u32 reserved;
+ };
+ 
+ /* Four Flexible Filters are supported */
+@@ -1309,89 +1309,89 @@ struct e1000_ffvt_entry {
+ 
+ /* Statistics counters collected by the MAC */
+ struct e1000_hw_stats {
+-	uint64_t		crcerrs;
+-	uint64_t		algnerrc;
+-	uint64_t		symerrs;
+-	uint64_t		rxerrc;
+-	uint64_t		txerrc;
+-	uint64_t		mpc;
+-	uint64_t		scc;
+-	uint64_t		ecol;
+-	uint64_t		mcc;
+-	uint64_t		latecol;
+-	uint64_t		colc;
+-	uint64_t		dc;
+-	uint64_t		tncrs;
+-	uint64_t		sec;
+-	uint64_t		cexterr;
+-	uint64_t		rlec;
+-	uint64_t		xonrxc;
+-	uint64_t		xontxc;
+-	uint64_t		xoffrxc;
+-	uint64_t		xofftxc;
+-	uint64_t		fcruc;
+-	uint64_t		prc64;
+-	uint64_t		prc127;
+-	uint64_t		prc255;
+-	uint64_t		prc511;
+-	uint64_t		prc1023;
+-	uint64_t		prc1522;
+-	uint64_t		gprc;
+-	uint64_t		bprc;
+-	uint64_t		mprc;
+-	uint64_t		gptc;
+-	uint64_t		gorcl;
+-	uint64_t		gorch;
+-	uint64_t		gotcl;
+-	uint64_t		gotch;
+-	uint64_t		rnbc;
+-	uint64_t		ruc;
+-	uint64_t		rfc;
+-	uint64_t		roc;
+-	uint64_t		rlerrc;
+-	uint64_t		rjc;
+-	uint64_t		mgprc;
+-	uint64_t		mgpdc;
+-	uint64_t		mgptc;
+-	uint64_t		torl;
+-	uint64_t		torh;
+-	uint64_t		totl;
+-	uint64_t		toth;
+-	uint64_t		tpr;
+-	uint64_t		tpt;
+-	uint64_t		ptc64;
+-	uint64_t		ptc127;
+-	uint64_t		ptc255;
+-	uint64_t		ptc511;
+-	uint64_t		ptc1023;
+-	uint64_t		ptc1522;
+-	uint64_t		mptc;
+-	uint64_t		bptc;
+-	uint64_t		tsctc;
+-	uint64_t		tsctfc;
+-	uint64_t		iac;
+-	uint64_t		icrxptc;
+-	uint64_t		icrxatc;
+-	uint64_t		ictxptc;
+-	uint64_t		ictxatc;
+-	uint64_t		ictxqec;
+-	uint64_t		ictxqmtc;
+-	uint64_t		icrxdmtc;
+-	uint64_t		icrxoc;
++	u64		crcerrs;
++	u64		algnerrc;
++	u64		symerrs;
++	u64		rxerrc;
++	u64		txerrc;
++	u64		mpc;
++	u64		scc;
++	u64		ecol;
++	u64		mcc;
++	u64		latecol;
++	u64		colc;
++	u64		dc;
++	u64		tncrs;
++	u64		sec;
++	u64		cexterr;
++	u64		rlec;
++	u64		xonrxc;
++	u64		xontxc;
++	u64		xoffrxc;
++	u64		xofftxc;
++	u64		fcruc;
++	u64		prc64;
++	u64		prc127;
++	u64		prc255;
++	u64		prc511;
++	u64		prc1023;
++	u64		prc1522;
++	u64		gprc;
++	u64		bprc;
++	u64		mprc;
++	u64		gptc;
++	u64		gorcl;
++	u64		gorch;
++	u64		gotcl;
++	u64		gotch;
++	u64		rnbc;
++	u64		ruc;
++	u64		rfc;
++	u64		roc;
++	u64		rlerrc;
++	u64		rjc;
++	u64		mgprc;
++	u64		mgpdc;
++	u64		mgptc;
++	u64		torl;
++	u64		torh;
++	u64		totl;
++	u64		toth;
++	u64		tpr;
++	u64		tpt;
++	u64		ptc64;
++	u64		ptc127;
++	u64		ptc255;
++	u64		ptc511;
++	u64		ptc1023;
++	u64		ptc1522;
++	u64		mptc;
++	u64		bptc;
++	u64		tsctc;
++	u64		tsctfc;
++	u64		iac;
++	u64		icrxptc;
++	u64		icrxatc;
++	u64		ictxptc;
++	u64		ictxatc;
++	u64		ictxqec;
++	u64		ictxqmtc;
++	u64		icrxdmtc;
++	u64		icrxoc;
+ };
+ 
+ /* Structure containing variables used by the shared code (e1000_hw.c) */
+ struct e1000_hw {
+-	uint8_t __iomem		*hw_addr;
+-	uint8_t __iomem		*flash_address;
++	u8 __iomem		*hw_addr;
++	u8 __iomem		*flash_address;
+ 	e1000_mac_type		mac_type;
+ 	e1000_phy_type		phy_type;
+-	uint32_t		phy_init_script;
++	u32		phy_init_script;
+ 	e1000_media_type	media_type;
+ 	void			*back;
+ 	struct e1000_shadow_ram	*eeprom_shadow_ram;
+-	uint32_t		flash_bank_size;
+-	uint32_t		flash_base_addr;
++	u32		flash_bank_size;
++	u32		flash_base_addr;
+ 	e1000_fc_type		fc;
+ 	e1000_bus_speed		bus_speed;
+ 	e1000_bus_width		bus_width;
+@@ -1400,75 +1400,75 @@ struct e1000_hw {
+ 	e1000_ms_type		master_slave;
+ 	e1000_ms_type		original_master_slave;
+ 	e1000_ffe_config	ffe_config_state;
+-	uint32_t		asf_firmware_present;
+-	uint32_t		eeprom_semaphore_present;
+-	uint32_t		swfw_sync_present;
+-	uint32_t		swfwhw_semaphore_present;
++	u32		asf_firmware_present;
++	u32		eeprom_semaphore_present;
++	u32		swfw_sync_present;
++	u32		swfwhw_semaphore_present;
+ 	unsigned long		io_base;
+-	uint32_t		phy_id;
+-	uint32_t		phy_revision;
+-	uint32_t		phy_addr;
+-	uint32_t		original_fc;
+-	uint32_t		txcw;
+-	uint32_t		autoneg_failed;
+-	uint32_t		max_frame_size;
+-	uint32_t		min_frame_size;
+-	uint32_t		mc_filter_type;
+-	uint32_t		num_mc_addrs;
+-	uint32_t		collision_delta;
+-	uint32_t		tx_packet_delta;
+-	uint32_t		ledctl_default;
+-	uint32_t		ledctl_mode1;
+-	uint32_t		ledctl_mode2;
+-	boolean_t		tx_pkt_filtering;
++	u32		phy_id;
++	u32		phy_revision;
++	u32		phy_addr;
++	u32		original_fc;
++	u32		txcw;
++	u32		autoneg_failed;
++	u32		max_frame_size;
++	u32		min_frame_size;
++	u32		mc_filter_type;
++	u32		num_mc_addrs;
++	u32		collision_delta;
++	u32		tx_packet_delta;
++	u32		ledctl_default;
++	u32		ledctl_mode1;
++	u32		ledctl_mode2;
++	bool			tx_pkt_filtering;
+ 	struct e1000_host_mng_dhcp_cookie mng_cookie;
+-	uint16_t		phy_spd_default;
+-	uint16_t		autoneg_advertised;
+-	uint16_t		pci_cmd_word;
+-	uint16_t		fc_high_water;
+-	uint16_t		fc_low_water;
+-	uint16_t		fc_pause_time;
+-	uint16_t		current_ifs_val;
+-	uint16_t		ifs_min_val;
+-	uint16_t		ifs_max_val;
+-	uint16_t		ifs_step_size;
+-	uint16_t		ifs_ratio;
+-	uint16_t		device_id;
+-	uint16_t		vendor_id;
+-	uint16_t		subsystem_id;
+-	uint16_t		subsystem_vendor_id;
+-	uint8_t			revision_id;
+-	uint8_t			autoneg;
+-	uint8_t			mdix;
+-	uint8_t			forced_speed_duplex;
+-	uint8_t			wait_autoneg_complete;
+-	uint8_t			dma_fairness;
+-	uint8_t			mac_addr[NODE_ADDRESS_SIZE];
+-	uint8_t			perm_mac_addr[NODE_ADDRESS_SIZE];
+-	boolean_t		disable_polarity_correction;
+-	boolean_t		speed_downgraded;
++	u16		phy_spd_default;
++	u16		autoneg_advertised;
++	u16		pci_cmd_word;
++	u16		fc_high_water;
++	u16		fc_low_water;
++	u16		fc_pause_time;
++	u16		current_ifs_val;
++	u16		ifs_min_val;
++	u16		ifs_max_val;
++	u16		ifs_step_size;
++	u16		ifs_ratio;
++	u16		device_id;
++	u16		vendor_id;
++	u16		subsystem_id;
++	u16		subsystem_vendor_id;
++	u8			revision_id;
++	u8			autoneg;
++	u8			mdix;
++	u8			forced_speed_duplex;
++	u8			wait_autoneg_complete;
++	u8			dma_fairness;
++	u8			mac_addr[NODE_ADDRESS_SIZE];
++	u8			perm_mac_addr[NODE_ADDRESS_SIZE];
++	bool			disable_polarity_correction;
++	bool			speed_downgraded;
+ 	e1000_smart_speed	smart_speed;
+ 	e1000_dsp_config	dsp_config_state;
+-	boolean_t		get_link_status;
+-	boolean_t		serdes_link_down;
+-	boolean_t		tbi_compatibility_en;
+-	boolean_t		tbi_compatibility_on;
+-	boolean_t		laa_is_present;
+-	boolean_t		phy_reset_disable;
+-	boolean_t		initialize_hw_bits_disable;
+-	boolean_t		fc_send_xon;
+-	boolean_t		fc_strict_ieee;
+-	boolean_t		report_tx_early;
+-	boolean_t		adaptive_ifs;
+-	boolean_t		ifs_params_forced;
+-	boolean_t		in_ifs_mode;
+-	boolean_t		mng_reg_access_disabled;
+-	boolean_t		leave_av_bit_off;
+-	boolean_t		kmrn_lock_loss_workaround_disabled;
+-	boolean_t		bad_tx_carr_stats_fd;
+-	boolean_t		has_manc2h;
+-	boolean_t		rx_needs_kicking;
+-	boolean_t		has_smbus;
++	bool			get_link_status;
++	bool			serdes_link_down;
++	bool			tbi_compatibility_en;
++	bool			tbi_compatibility_on;
++	bool			laa_is_present;
++	bool			phy_reset_disable;
++	bool			initialize_hw_bits_disable;
++	bool			fc_send_xon;
++	bool			fc_strict_ieee;
++	bool			report_tx_early;
++	bool			adaptive_ifs;
++	bool			ifs_params_forced;
++	bool			in_ifs_mode;
++	bool			mng_reg_access_disabled;
++	bool			leave_av_bit_off;
++	bool			kmrn_lock_loss_workaround_disabled;
++	bool			bad_tx_carr_stats_fd;
++	bool			has_manc2h;
++	bool			rx_needs_kicking;
++	bool			has_smbus;
+ };
+ 
+ 
+@@ -2165,14 +2165,14 @@ typedef enum {
+ #define E1000_HI_COMMAND_TIMEOUT         500 /* Time in ms to process HI command */
+ 
+ struct e1000_host_command_header {
+-    uint8_t command_id;
+-    uint8_t command_length;
+-    uint8_t command_options;   /* I/F bits for command, status for return */
+-    uint8_t checksum;
++    u8 command_id;
++    u8 command_length;
++    u8 command_options;   /* I/F bits for command, status for return */
++    u8 checksum;
+ };
+ struct e1000_host_command_info {
+     struct e1000_host_command_header command_header;  /* Command Head/Command Result Head has 4 bytes */
+-    uint8_t command_data[E1000_HI_MAX_DATA_LENGTH];   /* Command data can length 0..252 */
++    u8 command_data[E1000_HI_MAX_DATA_LENGTH];   /* Command data can length 0..252 */
+ };
+ 
+ /* Host SMB register #0 */
+@@ -2495,7 +2495,7 @@ struct e1000_host_command_info {
+ /* Number of milliseconds we wait for PHY configuration done after MAC reset */
+ #define PHY_CFG_TIMEOUT             100
+ 
+-#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
++#define E1000_TX_BUFFER_SIZE ((u32)1514)
+ 
+ /* The carrier extension symbol, as received by the NIC. */
+ #define CARRIER_EXTENSION   0x0F
+@@ -2518,11 +2518,11 @@ struct e1000_host_command_info {
+  * Typical use:
+  *  ...
+  *  if (TBI_ACCEPT) {
+- *      accept_frame = TRUE;
++ *      accept_frame = true;
+  *      e1000_tbi_adjust_stats(adapter, MacAddress);
+  *      frame_length--;
+  *  } else {
+- *      accept_frame = FALSE;
++ *      accept_frame = false;
+  *  }
+  *  ...
+  */
+@@ -3312,68 +3312,68 @@ struct e1000_host_command_info {
+ /* Offset 04h HSFSTS */
+ union ich8_hws_flash_status {
+     struct ich8_hsfsts {
+-#ifdef E1000_BIG_ENDIAN
+-        uint16_t reserved2      :6;
+-        uint16_t fldesvalid     :1;
+-        uint16_t flockdn        :1;
+-        uint16_t flcdone        :1;
+-        uint16_t flcerr         :1;
+-        uint16_t dael           :1;
+-        uint16_t berasesz       :2;
+-        uint16_t flcinprog      :1;
+-        uint16_t reserved1      :2;
++#ifdef __BIG_ENDIAN
++        u16 reserved2      :6;
++        u16 fldesvalid     :1;
++        u16 flockdn        :1;
++        u16 flcdone        :1;
++        u16 flcerr         :1;
++        u16 dael           :1;
++        u16 berasesz       :2;
++        u16 flcinprog      :1;
++        u16 reserved1      :2;
+ #else
+-        uint16_t flcdone        :1;   /* bit 0 Flash Cycle Done */
+-        uint16_t flcerr         :1;   /* bit 1 Flash Cycle Error */
+-        uint16_t dael           :1;   /* bit 2 Direct Access error Log */
+-        uint16_t berasesz       :2;   /* bit 4:3 Block/Sector Erase Size */
+-        uint16_t flcinprog      :1;   /* bit 5 flash SPI cycle in Progress */
+-        uint16_t reserved1      :2;   /* bit 13:6 Reserved */
+-        uint16_t reserved2      :6;   /* bit 13:6 Reserved */
+-        uint16_t fldesvalid     :1;   /* bit 14 Flash Descriptor Valid */
+-        uint16_t flockdn        :1;   /* bit 15 Flash Configuration Lock-Down */
++        u16 flcdone        :1;   /* bit 0 Flash Cycle Done */
++        u16 flcerr         :1;   /* bit 1 Flash Cycle Error */
++        u16 dael           :1;   /* bit 2 Direct Access error Log */
++        u16 berasesz       :2;   /* bit 4:3 Block/Sector Erase Size */
++        u16 flcinprog      :1;   /* bit 5 flash SPI cycle in Progress */
++        u16 reserved1      :2;   /* bit 13:6 Reserved */
++        u16 reserved2      :6;   /* bit 13:6 Reserved */
++        u16 fldesvalid     :1;   /* bit 14 Flash Descriptor Valid */
++        u16 flockdn        :1;   /* bit 15 Flash Configuration Lock-Down */
+ #endif
+     } hsf_status;
+-    uint16_t regval;
++    u16 regval;
+ };
+ 
+ /* ICH8 GbE Flash Hardware Sequencing Flash control Register bit breakdown */
+ /* Offset 06h FLCTL */
+ union ich8_hws_flash_ctrl {
+     struct ich8_hsflctl {
+-#ifdef E1000_BIG_ENDIAN
+-        uint16_t fldbcount      :2;
+-        uint16_t flockdn        :6;
+-        uint16_t flcgo          :1;
+-        uint16_t flcycle        :2;
+-        uint16_t reserved       :5;
++#ifdef __BIG_ENDIAN
++        u16 fldbcount      :2;
++        u16 flockdn        :6;
++        u16 flcgo          :1;
++        u16 flcycle        :2;
++        u16 reserved       :5;
+ #else
+-        uint16_t flcgo          :1;   /* 0 Flash Cycle Go */
+-        uint16_t flcycle        :2;   /* 2:1 Flash Cycle */
+-        uint16_t reserved       :5;   /* 7:3 Reserved  */
+-        uint16_t fldbcount      :2;   /* 9:8 Flash Data Byte Count */
+-        uint16_t flockdn        :6;   /* 15:10 Reserved */
++        u16 flcgo          :1;   /* 0 Flash Cycle Go */
++        u16 flcycle        :2;   /* 2:1 Flash Cycle */
++        u16 reserved       :5;   /* 7:3 Reserved  */
++        u16 fldbcount      :2;   /* 9:8 Flash Data Byte Count */
++        u16 flockdn        :6;   /* 15:10 Reserved */
+ #endif
+     } hsf_ctrl;
+-    uint16_t regval;
++    u16 regval;
+ };
+ 
+ /* ICH8 Flash Region Access Permissions */
+ union ich8_hws_flash_regacc {
+     struct ich8_flracc {
+-#ifdef E1000_BIG_ENDIAN
+-        uint32_t gmwag          :8;
+-        uint32_t gmrag          :8;
+-        uint32_t grwa           :8;
+-        uint32_t grra           :8;
++#ifdef __BIG_ENDIAN
++        u32 gmwag          :8;
++        u32 gmrag          :8;
++        u32 grwa           :8;
++        u32 grra           :8;
+ #else
+-        uint32_t grra           :8;   /* 0:7 GbE region Read Access */
+-        uint32_t grwa           :8;   /* 8:15 GbE region Write Access */
+-        uint32_t gmrag          :8;   /* 23:16 GbE Master Read Access Grant  */
+-        uint32_t gmwag          :8;   /* 31:24 GbE Master Write Access Grant */
++        u32 grra           :8;   /* 0:7 GbE region Read Access */
++        u32 grwa           :8;   /* 8:15 GbE region Write Access */
++        u32 gmrag          :8;   /* 23:16 GbE Master Read Access Grant  */
++        u32 gmwag          :8;   /* 31:24 GbE Master Write Access Grant */
+ #endif
+     } hsf_flregacc;
+-    uint16_t regval;
++    u16 regval;
+ };
+ 
+ /* Miscellaneous PHY bit definitions. */
+diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
+index 0991648..59579b1 100644
+--- a/drivers/net/e1000/e1000_main.c
++++ b/drivers/net/e1000/e1000_main.c
+@@ -127,7 +127,7 @@ int e1000_up(struct e1000_adapter *adapter);
+ void e1000_down(struct e1000_adapter *adapter);
+ void e1000_reinit_locked(struct e1000_adapter *adapter);
+ void e1000_reset(struct e1000_adapter *adapter);
+-int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
++int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+ int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+ int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+ void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+@@ -169,21 +169,21 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
+ static int e1000_set_mac(struct net_device *netdev, void *p);
+ static irqreturn_t e1000_intr(int irq, void *data);
+ static irqreturn_t e1000_intr_msi(int irq, void *data);
+-static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
+-                                    struct e1000_tx_ring *tx_ring);
++static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
++			       struct e1000_tx_ring *tx_ring);
+ #ifdef CONFIG_E1000_NAPI
+ static int e1000_clean(struct napi_struct *napi, int budget);
+-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+-                                    struct e1000_rx_ring *rx_ring,
+-                                    int *work_done, int work_to_do);
+-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+-                                       struct e1000_rx_ring *rx_ring,
+-                                       int *work_done, int work_to_do);
++static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
++			       struct e1000_rx_ring *rx_ring,
++			       int *work_done, int work_to_do);
++static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
++				  struct e1000_rx_ring *rx_ring,
++				  int *work_done, int work_to_do);
+ #else
+-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+-                                    struct e1000_rx_ring *rx_ring);
+-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+-                                       struct e1000_rx_ring *rx_ring);
++static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
++			       struct e1000_rx_ring *rx_ring);
++static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
++				  struct e1000_rx_ring *rx_ring);
+ #endif
+ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+                                    struct e1000_rx_ring *rx_ring,
+@@ -203,8 +203,8 @@ static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
+                                        struct sk_buff *skb);
+ 
+ static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+-static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+-static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
++static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
++static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
+ static void e1000_restore_vlan(struct e1000_adapter *adapter);
+ 
+ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
+@@ -347,7 +347,6 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
+ static void
+ e1000_irq_disable(struct e1000_adapter *adapter)
+ {
+-	atomic_inc(&adapter->irq_sem);
+ 	E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+ 	E1000_WRITE_FLUSH(&adapter->hw);
+ 	synchronize_irq(adapter->pdev->irq);
+@@ -361,18 +360,16 @@ e1000_irq_disable(struct e1000_adapter *adapter)
+ static void
+ e1000_irq_enable(struct e1000_adapter *adapter)
+ {
+-	if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+-		E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
+-		E1000_WRITE_FLUSH(&adapter->hw);
+-	}
++	E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
++	E1000_WRITE_FLUSH(&adapter->hw);
+ }
+ 
+ static void
+ e1000_update_mng_vlan(struct e1000_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+-	uint16_t vid = adapter->hw.mng_cookie.vlan_id;
+-	uint16_t old_vid = adapter->mng_vlan_id;
++	u16 vid = adapter->hw.mng_cookie.vlan_id;
++	u16 old_vid = adapter->mng_vlan_id;
+ 	if (adapter->vlgrp) {
+ 		if (!vlan_group_get_device(adapter->vlgrp, vid)) {
+ 			if (adapter->hw.mng_cookie.status &
+@@ -382,7 +379,7 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
+ 			} else
+ 				adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+ 
+-			if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
++			if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
+ 					(vid != old_vid) &&
+ 			    !vlan_group_get_device(adapter->vlgrp, old_vid))
+ 				e1000_vlan_rx_kill_vid(netdev, old_vid);
+@@ -405,8 +402,8 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
+ static void
+ e1000_release_hw_control(struct e1000_adapter *adapter)
+ {
+-	uint32_t ctrl_ext;
+-	uint32_t swsm;
++	u32 ctrl_ext;
++	u32 swsm;
+ 
+ 	/* Let firmware taken over control of h/w */
+ 	switch (adapter->hw.mac_type) {
+@@ -442,8 +439,8 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
+ static void
+ e1000_get_hw_control(struct e1000_adapter *adapter)
+ {
+-	uint32_t ctrl_ext;
+-	uint32_t swsm;
++	u32 ctrl_ext;
++	u32 swsm;
+ 
+ 	/* Let firmware know the driver has taken over */
+ 	switch (adapter->hw.mac_type) {
+@@ -469,7 +466,7 @@ static void
+ e1000_init_manageability(struct e1000_adapter *adapter)
+ {
+ 	if (adapter->en_mng_pt) {
+-		uint32_t manc = E1000_READ_REG(&adapter->hw, MANC);
++		u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+ 
+ 		/* disable hardware interception of ARP */
+ 		manc &= ~(E1000_MANC_ARP_EN);
+@@ -478,7 +475,7 @@ e1000_init_manageability(struct e1000_adapter *adapter)
+ 		/* this will probably generate destination unreachable messages
+ 		 * from the host OS, but the packets will be handled on SMBUS */
+ 		if (adapter->hw.has_manc2h) {
+-			uint32_t manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
++			u32 manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
+ 
+ 			manc |= E1000_MANC_EN_MNG2HOST;
+ #define E1000_MNG2HOST_PORT_623 (1 << 5)
+@@ -496,7 +493,7 @@ static void
+ e1000_release_manageability(struct e1000_adapter *adapter)
+ {
+ 	if (adapter->en_mng_pt) {
+-		uint32_t manc = E1000_READ_REG(&adapter->hw, MANC);
++		u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+ 
+ 		/* re-enable hardware interception of ARP */
+ 		manc |= E1000_MANC_ARP_EN;
+@@ -569,7 +566,7 @@ int e1000_up(struct e1000_adapter *adapter)
+ 
+ void e1000_power_up_phy(struct e1000_adapter *adapter)
+ {
+-	uint16_t mii_reg = 0;
++	u16 mii_reg = 0;
+ 
+ 	/* Just clear the power down bit to wake the phy back up */
+ 	if (adapter->hw.media_type == e1000_media_type_copper) {
+@@ -584,13 +581,13 @@ void e1000_power_up_phy(struct e1000_adapter *adapter)
+ static void e1000_power_down_phy(struct e1000_adapter *adapter)
+ {
+ 	/* 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 *
++	 * The PHY cannot be powered down if any of the following is true *
+ 	 * (a) WoL is enabled
+ 	 * (b) AMT is active
+ 	 * (c) SoL/IDER session is active */
+ 	if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
+ 	   adapter->hw.media_type == e1000_media_type_copper) {
+-		uint16_t mii_reg = 0;
++		u16 mii_reg = 0;
+ 
+ 		switch (adapter->hw.mac_type) {
+ 		case e1000_82540:
+@@ -638,7 +635,6 @@ e1000_down(struct e1000_adapter *adapter)
+ 
+ #ifdef CONFIG_E1000_NAPI
+ 	napi_disable(&adapter->napi);
+-	atomic_set(&adapter->irq_sem, 0);
+ #endif
+ 	e1000_irq_disable(adapter);
+ 
+@@ -671,9 +667,9 @@ e1000_reinit_locked(struct e1000_adapter *adapter)
+ void
+ e1000_reset(struct e1000_adapter *adapter)
+ {
+-	uint32_t pba = 0, tx_space, min_tx_space, min_rx_space;
+-	uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
+-	boolean_t legacy_pba_adjust = FALSE;
++	u32 pba = 0, tx_space, min_tx_space, min_rx_space;
++	u16 fc_high_water_mark = E1000_FC_HIGH_DIFF;
++	bool legacy_pba_adjust = false;
+ 
+ 	/* Repartition Pba for greater than 9k mtu
+ 	 * To take effect CTRL.RST is required.
+@@ -687,7 +683,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ 	case e1000_82540:
+ 	case e1000_82541:
+ 	case e1000_82541_rev_2:
+-		legacy_pba_adjust = TRUE;
++		legacy_pba_adjust = true;
+ 		pba = E1000_PBA_48K;
+ 		break;
+ 	case e1000_82545:
+@@ -698,7 +694,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ 		break;
+ 	case e1000_82547:
+ 	case e1000_82547_rev_2:
+-		legacy_pba_adjust = TRUE;
++		legacy_pba_adjust = true;
+ 		pba = E1000_PBA_30K;
+ 		break;
+ 	case e1000_82571:
+@@ -716,7 +712,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ 		break;
+ 	}
+ 
+-	if (legacy_pba_adjust == TRUE) {
++	if (legacy_pba_adjust) {
+ 		if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
+ 			pba -= 8; /* allocate more FIFO for Tx */
+ 
+@@ -819,7 +815,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ 	    adapter->hw.mac_type <= e1000_82547_rev_2 &&
+ 	    adapter->hw.autoneg == 1 &&
+ 	    adapter->hw.autoneg_advertised == ADVERTISE_1000_FULL) {
+-		uint32_t ctrl = E1000_READ_REG(&adapter->hw, CTRL);
++		u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ 		/* clear phy power management bit if we are in gig only mode,
+ 		 * which if enabled will attempt negotiation to 100Mb, which
+ 		 * can cause a loss of link at power off or driver unload */
+@@ -836,7 +832,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ 	if (!adapter->smart_power_down &&
+ 	    (adapter->hw.mac_type == e1000_82571 ||
+ 	     adapter->hw.mac_type == e1000_82572)) {
+-		uint16_t phy_data = 0;
++		u16 phy_data = 0;
+ 		/* speed up time to link by disabling smart power down, ignore
+ 		 * the return value of this function because there is nothing
+ 		 * different we would do if it failed */
+@@ -930,8 +926,8 @@ e1000_probe(struct pci_dev *pdev,
+ 	static int cards_found = 0;
+ 	static int global_quad_port_a = 0; /* global ksp3 port a indication */
+ 	int i, err, pci_using_dac;
+-	uint16_t eeprom_data = 0;
+-	uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
++	u16 eeprom_data = 0;
++	u16 eeprom_apme_mask = E1000_EEPROM_APME;
+ 	DECLARE_MAC_BUF(mac);
+ 
+ 	if ((err = pci_enable_device(pdev)))
+@@ -1366,15 +1362,15 @@ e1000_sw_init(struct e1000_adapter *adapter)
+ 
+ 	e1000_set_media_type(hw);
+ 
+-	hw->wait_autoneg_complete = FALSE;
+-	hw->tbi_compatibility_en = TRUE;
+-	hw->adaptive_ifs = TRUE;
++	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->disable_polarity_correction = false;
+ 		hw->master_slave = E1000_MASTER_SLAVE;
+ 	}
+ 
+@@ -1396,7 +1392,6 @@ e1000_sw_init(struct e1000_adapter *adapter)
+ #endif
+ 
+ 	/* Explicitly disable IRQ since the NIC can be in any state. */
+-	atomic_set(&adapter->irq_sem, 0);
+ 	e1000_irq_disable(adapter);
+ 
+ 	spin_lock_init(&adapter->stats_lock);
+@@ -1576,7 +1571,7 @@ e1000_close(struct net_device *netdev)
+  * @start: address of beginning of memory
+  * @len: length of memory
+  **/
+-static boolean_t
++static bool
+ e1000_check_64k_bound(struct e1000_adapter *adapter,
+ 		      void *start, unsigned long len)
+ {
+@@ -1587,10 +1582,10 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
+ 	 * write location to cross 64k boundary due to errata 23 */
+ 	if (adapter->hw.mac_type == e1000_82545 ||
+ 	    adapter->hw.mac_type == e1000_82546) {
+-		return ((begin ^ (end - 1)) >> 16) != 0 ? FALSE : TRUE;
++		return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
+ 	}
+ 
+-	return TRUE;
++	return true;
+ }
+ 
+ /**
+@@ -1707,10 +1702,10 @@ e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+ static void
+ e1000_configure_tx(struct e1000_adapter *adapter)
+ {
+-	uint64_t tdba;
++	u64 tdba;
+ 	struct e1000_hw *hw = &adapter->hw;
+-	uint32_t tdlen, tctl, tipg, tarc;
+-	uint32_t ipgr1, ipgr2;
++	u32 tdlen, tctl, tipg, tarc;
++	u32 ipgr1, ipgr2;
+ 
+ 	/* Setup the HW Tx Head and Tail descriptor pointers */
+ 
+@@ -1952,10 +1947,10 @@ e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+ static void
+ e1000_setup_rctl(struct e1000_adapter *adapter)
+ {
+-	uint32_t rctl, rfctl;
+-	uint32_t psrctl = 0;
++	u32 rctl, rfctl;
++	u32 psrctl = 0;
+ #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
+-	uint32_t pages = 0;
++	u32 pages = 0;
+ #endif
+ 
+ 	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+@@ -2070,9 +2065,9 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
+ static void
+ e1000_configure_rx(struct e1000_adapter *adapter)
+ {
+-	uint64_t rdba;
++	u64 rdba;
+ 	struct e1000_hw *hw = &adapter->hw;
+-	uint32_t rdlen, rctl, rxcsum, ctrl_ext;
++	u32 rdlen, rctl, rxcsum, ctrl_ext;
+ 
+ 	if (adapter->rx_ps_pages) {
+ 		/* this is a 32 byte descriptor */
+@@ -2133,7 +2128,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
+ 	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
+ 	if (hw->mac_type >= e1000_82543) {
+ 		rxcsum = E1000_READ_REG(hw, RXCSUM);
+-		if (adapter->rx_csum == TRUE) {
++		if (adapter->rx_csum) {
+ 			rxcsum |= E1000_RXCSUM_TUOFL;
+ 
+ 			/* Enable 82571 IPv4 payload checksum for UDP fragments
+@@ -2392,7 +2387,7 @@ static void
+ e1000_enter_82542_rst(struct e1000_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+-	uint32_t rctl;
++	u32 rctl;
+ 
+ 	e1000_pci_clear_mwi(&adapter->hw);
+ 
+@@ -2410,7 +2405,7 @@ static void
+ e1000_leave_82542_rst(struct e1000_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+-	uint32_t rctl;
++	u32 rctl;
+ 
+ 	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ 	rctl &= ~E1000_RCTL_RST;
+@@ -2495,8 +2490,8 @@ e1000_set_rx_mode(struct net_device *netdev)
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	struct dev_addr_list *uc_ptr;
+ 	struct dev_addr_list *mc_ptr;
+-	uint32_t rctl;
+-	uint32_t hash_value;
++	u32 rctl;
++	u32 hash_value;
+ 	int i, rar_entries = E1000_RAR_ENTRIES;
+ 	int mta_reg_count = (hw->mac_type == e1000_ich8lan) ?
+ 				E1000_NUM_MTA_REGISTERS_ICH8LAN :
+@@ -2600,7 +2595,7 @@ e1000_82547_tx_fifo_stall(unsigned long data)
+ {
+ 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ 	struct net_device *netdev = adapter->netdev;
+-	uint32_t tctl;
++	u32 tctl;
+ 
+ 	if (atomic_read(&adapter->tx_fifo_stall)) {
+ 		if ((E1000_READ_REG(&adapter->hw, TDT) ==
+@@ -2642,8 +2637,8 @@ e1000_watchdog(unsigned long data)
+ 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ 	struct net_device *netdev = adapter->netdev;
+ 	struct e1000_tx_ring *txdr = adapter->tx_ring;
+-	uint32_t link, tctl;
+-	int32_t ret_val;
++	u32 link, tctl;
++	s32 ret_val;
+ 
+ 	ret_val = e1000_check_for_link(&adapter->hw);
+ 	if ((ret_val == E1000_ERR_PHY) &&
+@@ -2668,8 +2663,8 @@ e1000_watchdog(unsigned long data)
+ 
+ 	if (link) {
+ 		if (!netif_carrier_ok(netdev)) {
+-			uint32_t ctrl;
+-			boolean_t txb2b = 1;
++			u32 ctrl;
++			bool txb2b = true;
+ 			e1000_get_speed_and_duplex(&adapter->hw,
+ 			                           &adapter->link_speed,
+ 			                           &adapter->link_duplex);
+@@ -2691,12 +2686,12 @@ e1000_watchdog(unsigned long data)
+ 			adapter->tx_timeout_factor = 1;
+ 			switch (adapter->link_speed) {
+ 			case SPEED_10:
+-				txb2b = 0;
++				txb2b = false;
+ 				netdev->tx_queue_len = 10;
+ 				adapter->tx_timeout_factor = 8;
+ 				break;
+ 			case SPEED_100:
+-				txb2b = 0;
++				txb2b = false;
+ 				netdev->tx_queue_len = 100;
+ 				/* maybe add some timeout factor ? */
+ 				break;
+@@ -2704,8 +2699,8 @@ e1000_watchdog(unsigned long data)
+ 
+ 			if ((adapter->hw.mac_type == e1000_82571 ||
+ 			     adapter->hw.mac_type == e1000_82572) &&
+-			    txb2b == 0) {
+-				uint32_t tarc0;
++			    !txb2b) {
++				u32 tarc0;
+ 				tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
+ 				tarc0 &= ~(1 << 21);
+ 				E1000_WRITE_REG(&adapter->hw, TARC0, tarc0);
+@@ -2747,7 +2742,7 @@ e1000_watchdog(unsigned long data)
+ 			/* make sure the receive unit is started */
+ 			if (adapter->hw.rx_needs_kicking) {
+ 				struct e1000_hw *hw = &adapter->hw;
+-				uint32_t rctl = E1000_READ_REG(hw, RCTL);
++				u32 rctl = E1000_READ_REG(hw, RCTL);
+ 				E1000_WRITE_REG(hw, RCTL, rctl | E1000_RCTL_EN);
+ 			}
+ 		}
+@@ -2802,7 +2797,7 @@ e1000_watchdog(unsigned long data)
+ 	E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
+ 
+ 	/* Force detection of hung controller every watchdog period */
+-	adapter->detect_tx_hung = TRUE;
++	adapter->detect_tx_hung = true;
+ 
+ 	/* With 82571 controllers, LAA may be overwritten due to controller
+ 	 * reset from the other port. Set the appropriate LAA in RAR[0] */
+@@ -2837,7 +2832,7 @@ enum latency_range {
+  * @bytes: the number of bytes during this measurement interval
+  **/
+ static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
+-                                   uint16_t itr_setting,
++                                   u16 itr_setting,
+                                    int packets,
+                                    int bytes)
+ {
+@@ -2889,8 +2884,8 @@ update_itr_done:
+ static void e1000_set_itr(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+-	uint16_t current_itr;
+-	uint32_t new_itr = adapter->itr;
++	u16 current_itr;
++	u32 new_itr = adapter->itr;
+ 
+ 	if (unlikely(hw->mac_type < e1000_82540))
+ 		return;
+@@ -2964,9 +2959,9 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ 	struct e1000_context_desc *context_desc;
+ 	struct e1000_buffer *buffer_info;
+ 	unsigned int i;
+-	uint32_t cmd_length = 0;
+-	uint16_t ipcse = 0, tucse, mss;
+-	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
++	u32 cmd_length = 0;
++	u16 ipcse = 0, tucse, mss;
++	u8 ipcss, ipcso, tucss, tucso, hdr_len;
+ 	int err;
+ 
+ 	if (skb_is_gso(skb)) {
+@@ -3025,19 +3020,19 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ 		if (++i == tx_ring->count) i = 0;
+ 		tx_ring->next_to_use = i;
+ 
+-		return TRUE;
++		return true;
+ 	}
+-	return FALSE;
++	return false;
+ }
+ 
+-static boolean_t
++static bool
+ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+               struct sk_buff *skb)
+ {
+ 	struct e1000_context_desc *context_desc;
+ 	struct e1000_buffer *buffer_info;
+ 	unsigned int i;
+-	uint8_t css;
++	u8 css;
+ 
+ 	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ 		css = skb_transport_offset(skb);
+@@ -3060,10 +3055,10 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ 		if (unlikely(++i == tx_ring->count)) i = 0;
+ 		tx_ring->next_to_use = i;
+ 
+-		return TRUE;
++		return true;
+ 	}
+ 
+-	return FALSE;
++	return false;
+ }
+ 
+ #define E1000_MAX_TXD_PWR	12
+@@ -3182,7 +3177,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ {
+ 	struct e1000_tx_desc *tx_desc = NULL;
+ 	struct e1000_buffer *buffer_info;
+-	uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
++	u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
+ 	unsigned int i;
+ 
+ 	if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
+@@ -3246,8 +3241,8 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ static int
+ e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
+ {
+-	uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
+-	uint32_t skb_fifo_len = skb->len + E1000_FIFO_HDR;
++	u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
++	u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
+ 
+ 	skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR);
+ 
+@@ -3274,7 +3269,7 @@ static int
+ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
+ {
+ 	struct e1000_hw *hw =  &adapter->hw;
+-	uint16_t length, offset;
++	u16 length, offset;
+ 	if (vlan_tx_tag_present(skb)) {
+ 		if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+ 			( adapter->hw.mng_cookie.status &
+@@ -3285,17 +3280,17 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
+ 		struct ethhdr *eth = (struct ethhdr *) skb->data;
+ 		if ((htons(ETH_P_IP) == eth->h_proto)) {
+ 			const struct iphdr *ip =
+-				(struct iphdr *)((uint8_t *)skb->data+14);
++				(struct iphdr *)((u8 *)skb->data+14);
+ 			if (IPPROTO_UDP == ip->protocol) {
+ 				struct udphdr *udp =
+-					(struct udphdr *)((uint8_t *)ip +
++					(struct udphdr *)((u8 *)ip +
+ 						(ip->ihl << 2));
+ 				if (ntohs(udp->dest) == 67) {
+-					offset = (uint8_t *)udp + 8 - skb->data;
++					offset = (u8 *)udp + 8 - skb->data;
+ 					length = skb->len - offset;
+ 
+ 					return e1000_mng_write_dhcp_info(hw,
+-							(uint8_t *)udp + 8,
++							(u8 *)udp + 8,
+ 							length);
+ 				}
+ 			}
+@@ -3375,7 +3370,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 	 * overrun the FIFO, adjust the max buffer len if mss
+ 	 * drops. */
+ 	if (mss) {
+-		uint8_t hdr_len;
++		u8 hdr_len;
+ 		max_per_txd = min(mss << 2, max_per_txd);
+ 		max_txd_pwr = fls(max_per_txd) - 1;
+ 
+@@ -3562,7 +3557,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+-	uint16_t eeprom_data = 0;
++	u16 eeprom_data = 0;
+ 
+ 	if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+ 	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+@@ -3657,7 +3652,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	struct pci_dev *pdev = adapter->pdev;
+ 	unsigned long flags;
+-	uint16_t phy_tmp;
++	u16 phy_tmp;
+ 
+ #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
+ 
+@@ -3834,13 +3829,10 @@ e1000_intr_msi(int irq, void *data)
+ #ifndef CONFIG_E1000_NAPI
+ 	int i;
+ #endif
+-	uint32_t icr = E1000_READ_REG(hw, ICR);
++	u32 icr = E1000_READ_REG(hw, ICR);
++
++	/* in NAPI mode read ICR disables interrupts using IAM */
+ 
+-#ifdef CONFIG_E1000_NAPI
+-	/* read ICR disables interrupts using IAM, so keep up with our
+-	 * enable/disable accounting */
+-	atomic_inc(&adapter->irq_sem);
+-#endif
+ 	if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ 		hw->get_link_status = 1;
+ 		/* 80003ES2LAN workaround-- For packet buffer work-around on
+@@ -3849,7 +3841,7 @@ e1000_intr_msi(int irq, void *data)
+ 		if (netif_carrier_ok(netdev) &&
+ 		    (adapter->hw.mac_type == e1000_80003es2lan)) {
+ 			/* disable receives */
+-			uint32_t rctl = E1000_READ_REG(hw, RCTL);
++			u32 rctl = E1000_READ_REG(hw, RCTL);
+ 			E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ 		}
+ 		/* guard against interrupt when we're going down */
+@@ -3896,7 +3888,7 @@ e1000_intr(int irq, void *data)
+ 	struct net_device *netdev = data;
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	struct e1000_hw *hw = &adapter->hw;
+-	uint32_t rctl, icr = E1000_READ_REG(hw, ICR);
++	u32 rctl, icr = E1000_READ_REG(hw, ICR);
+ #ifndef CONFIG_E1000_NAPI
+ 	int i;
+ #endif
+@@ -3910,12 +3902,8 @@ e1000_intr(int irq, void *data)
+ 	             !(icr & E1000_ICR_INT_ASSERTED)))
+ 		return IRQ_NONE;
+ 
+-	/* Interrupt Auto-Mask...upon reading ICR,
+-	 * interrupts are masked.  No need for the
+-	 * IMC write, but it does mean we should
+-	 * account for it ASAP. */
+-	if (likely(hw->mac_type >= e1000_82571))
+-		atomic_inc(&adapter->irq_sem);
++	/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked.  No
++	 * need for the IMC write */
+ #endif
+ 
+ 	if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
+@@ -3939,7 +3927,6 @@ e1000_intr(int irq, void *data)
+ #ifdef CONFIG_E1000_NAPI
+ 	if (unlikely(hw->mac_type < e1000_82571)) {
+ 		/* disable interrupts, without the synchronize_irq bit */
+-		atomic_inc(&adapter->irq_sem);
+ 		E1000_WRITE_REG(hw, IMC, ~0);
+ 		E1000_WRITE_FLUSH(hw);
+ 	}
+@@ -3964,10 +3951,8 @@ e1000_intr(int irq, void *data)
+ 	 * in dead lock. Writing IMC forces 82547 into
+ 	 * de-assertion state.
+ 	 */
+-	if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) {
+-		atomic_inc(&adapter->irq_sem);
++	if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
+ 		E1000_WRITE_REG(hw, IMC, ~0);
+-	}
+ 
+ 	adapter->total_tx_bytes = 0;
+ 	adapter->total_rx_bytes = 0;
+@@ -4038,7 +4023,7 @@ e1000_clean(struct napi_struct *napi, int budget)
+  * @adapter: board private structure
+  **/
+ 
+-static boolean_t
++static bool
+ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+                    struct e1000_tx_ring *tx_ring)
+ {
+@@ -4049,7 +4034,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ #ifdef CONFIG_E1000_NAPI
+ 	unsigned int count = 0;
+ #endif
+-	boolean_t cleaned = FALSE;
++	bool cleaned = false;
+ 	unsigned int total_tx_bytes=0, total_tx_packets=0;
+ 
+ 	i = tx_ring->next_to_clean;
+@@ -4057,7 +4042,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
+ 
+ 	while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+-		for (cleaned = FALSE; !cleaned; ) {
++		for (cleaned = false; !cleaned; ) {
+ 			tx_desc = E1000_TX_DESC(*tx_ring, i);
+ 			buffer_info = &tx_ring->buffer_info[i];
+ 			cleaned = (i == eop);
+@@ -4105,7 +4090,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ 	if (adapter->detect_tx_hung) {
+ 		/* Detect a transmit hang in hardware, this serializes the
+ 		 * check with the clearing of time_stamp and movement of i */
+-		adapter->detect_tx_hung = FALSE;
++		adapter->detect_tx_hung = false;
+ 		if (tx_ring->buffer_info[eop].dma &&
+ 		    time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
+ 		               (adapter->tx_timeout_factor * HZ))
+@@ -4154,11 +4139,11 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ 
+ static void
+ e1000_rx_checksum(struct e1000_adapter *adapter,
+-		  uint32_t status_err, uint32_t csum,
++		  u32 status_err, u32 csum,
+ 		  struct sk_buff *skb)
+ {
+-	uint16_t status = (uint16_t)status_err;
+-	uint8_t errors = (uint8_t)(status_err >> 24);
++	u16 status = (u16)status_err;
++	u8 errors = (u8)(status_err >> 24);
+ 	skb->ip_summed = CHECKSUM_NONE;
+ 
+ 	/* 82543 or newer only */
+@@ -4200,7 +4185,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
+  * @adapter: board private structure
+  **/
+ 
+-static boolean_t
++static bool
+ #ifdef CONFIG_E1000_NAPI
+ e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                    struct e1000_rx_ring *rx_ring,
+@@ -4215,11 +4200,11 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ 	struct e1000_rx_desc *rx_desc, *next_rxd;
+ 	struct e1000_buffer *buffer_info, *next_buffer;
+ 	unsigned long flags;
+-	uint32_t length;
+-	uint8_t last_byte;
++	u32 length;
++	u8 last_byte;
+ 	unsigned int i;
+ 	int cleaned_count = 0;
+-	boolean_t cleaned = FALSE;
++	bool cleaned = false;
+ 	unsigned int total_rx_bytes=0, total_rx_packets=0;
+ 
+ 	i = rx_ring->next_to_clean;
+@@ -4247,7 +4232,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ 
+ 		next_buffer = &rx_ring->buffer_info[i];
+ 
+-		cleaned = TRUE;
++		cleaned = true;
+ 		cleaned_count++;
+ 		pci_unmap_single(pdev,
+ 		                 buffer_info->dma,
+@@ -4316,8 +4301,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ 
+ 		/* Receive Checksum Offload */
+ 		e1000_rx_checksum(adapter,
+-				  (uint32_t)(status) |
+-				  ((uint32_t)(rx_desc->errors) << 24),
++				  (u32)(status) |
++				  ((u32)(rx_desc->errors) << 24),
+ 				  le16_to_cpu(rx_desc->csum), skb);
+ 
+ 		skb->protocol = eth_type_trans(skb, netdev);
+@@ -4373,7 +4358,7 @@ next_desc:
+  * @adapter: board private structure
+  **/
+ 
+-static boolean_t
++static bool
+ #ifdef CONFIG_E1000_NAPI
+ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+                       struct e1000_rx_ring *rx_ring,
+@@ -4391,9 +4376,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ 	struct e1000_ps_page_dma *ps_page_dma;
+ 	struct sk_buff *skb;
+ 	unsigned int i, j;
+-	uint32_t length, staterr;
++	u32 length, staterr;
+ 	int cleaned_count = 0;
+-	boolean_t cleaned = FALSE;
++	bool cleaned = false;
+ 	unsigned int total_rx_bytes=0, total_rx_packets=0;
+ 
+ 	i = rx_ring->next_to_clean;
+@@ -4420,7 +4405,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ 
+ 		next_buffer = &rx_ring->buffer_info[i];
+ 
+-		cleaned = TRUE;
++		cleaned = true;
+ 		cleaned_count++;
+ 		pci_unmap_single(pdev, buffer_info->dma,
+ 				 buffer_info->length,
+@@ -4774,8 +4759,8 @@ no_buffers:
+ static void
+ e1000_smartspeed(struct e1000_adapter *adapter)
+ {
+-	uint16_t phy_status;
+-	uint16_t phy_ctrl;
++	u16 phy_status;
++	u16 phy_ctrl;
+ 
+ 	if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
+ 	   !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
+@@ -4854,8 +4839,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	struct mii_ioctl_data *data = if_mii(ifr);
+ 	int retval;
+-	uint16_t mii_reg;
+-	uint16_t spddplx;
++	u16 mii_reg;
++	u16 spddplx;
+ 	unsigned long flags;
+ 
+ 	if (adapter->hw.media_type != e1000_media_type_copper)
+@@ -4974,11 +4959,11 @@ e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
+ 	pcix_set_mmrbc(adapter->pdev, mmrbc);
+ }
+ 
+-int32_t
+-e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
++s32
++e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
+ {
+     struct e1000_adapter *adapter = hw->back;
+-    uint16_t cap_offset;
++    u16 cap_offset;
+ 
+     cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+     if (!cap_offset)
+@@ -4990,7 +4975,7 @@ e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
+ }
+ 
+ void
+-e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)
++e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
+ {
+ 	outl(value, port);
+ }
+@@ -4999,9 +4984,10 @@ static void
+ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+-	uint32_t ctrl, rctl;
++	u32 ctrl, rctl;
+ 
+-	e1000_irq_disable(adapter);
++	if (!test_bit(__E1000_DOWN, &adapter->flags))
++		e1000_irq_disable(adapter);
+ 	adapter->vlgrp = grp;
+ 
+ 	if (grp) {
+@@ -5030,7 +5016,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ 			rctl &= ~E1000_RCTL_VFE;
+ 			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ 			if (adapter->mng_vlan_id !=
+-			    (uint16_t)E1000_MNG_VLAN_NONE) {
++			    (u16)E1000_MNG_VLAN_NONE) {
+ 				e1000_vlan_rx_kill_vid(netdev,
+ 				                       adapter->mng_vlan_id);
+ 				adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+@@ -5038,14 +5024,15 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ 		}
+ 	}
+ 
+-	e1000_irq_enable(adapter);
++	if (!test_bit(__E1000_DOWN, &adapter->flags))
++		e1000_irq_enable(adapter);
+ }
+ 
+ static void
+-e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
++e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+-	uint32_t vfta, index;
++	u32 vfta, index;
+ 
+ 	if ((adapter->hw.mng_cookie.status &
+ 	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+@@ -5059,14 +5046,16 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
+ }
+ 
+ static void
+-e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
++e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+-	uint32_t vfta, index;
++	u32 vfta, index;
+ 
+-	e1000_irq_disable(adapter);
++	if (!test_bit(__E1000_DOWN, &adapter->flags))
++		e1000_irq_disable(adapter);
+ 	vlan_group_set_device(adapter->vlgrp, vid, NULL);
+-	e1000_irq_enable(adapter);
++	if (!test_bit(__E1000_DOWN, &adapter->flags))
++		e1000_irq_enable(adapter);
+ 
+ 	if ((adapter->hw.mng_cookie.status &
+ 	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+@@ -5089,7 +5078,7 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
+ 	e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ 
+ 	if (adapter->vlgrp) {
+-		uint16_t vid;
++		u16 vid;
+ 		for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ 			if (!vlan_group_get_device(adapter->vlgrp, vid))
+ 				continue;
+@@ -5099,7 +5088,7 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
+ }
+ 
+ int
+-e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
++e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
+ {
+ 	adapter->hw.autoneg = 0;
+ 
+@@ -5140,8 +5129,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+-	uint32_t ctrl, ctrl_ext, rctl, status;
+-	uint32_t wufc = adapter->wol;
++	u32 ctrl, ctrl_ext, rctl, status;
++	u32 wufc = adapter->wol;
+ #ifdef CONFIG_PM
+ 	int retval = 0;
+ #endif
+@@ -5238,7 +5227,7 @@ e1000_resume(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+-	uint32_t err;
++	u32 err;
+ 
+ 	pci_set_power_state(pdev, PCI_D0);
+ 	pci_restore_state(pdev);
+diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
+index 10af742..365626d 100644
+--- a/drivers/net/e1000/e1000_osdep.h
++++ b/drivers/net/e1000/e1000_osdep.h
+@@ -41,13 +41,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+ 
+-typedef enum {
+-#undef FALSE
+-    FALSE = 0,
+-#undef TRUE
+-    TRUE = 1
+-} boolean_t;
+-
+ #ifdef DBG
+ #define DEBUGOUT(S)		printk(KERN_DEBUG S "\n")
+ #define DEBUGOUT1(S, A...)	printk(KERN_DEBUG S "\n", A)
+diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
+index 7fe2031..462351c 100644
+--- a/drivers/net/e1000e/82571.c
++++ b/drivers/net/e1000e/82571.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -29,6 +29,9 @@
+ /*
+  * 82571EB Gigabit Ethernet Controller
+  * 82571EB Gigabit Ethernet Controller (Fiber)
++ * 82571EB Dual Port Gigabit Mezzanine Adapter
++ * 82571EB Quad Port Gigabit Mezzanine Adapter
++ * 82571PT Gigabit PT Quad Port Server ExpressModule
+  * 82572EI Gigabit Ethernet Controller (Copper)
+  * 82572EI Gigabit Ethernet Controller (Fiber)
+  * 82572EI Gigabit Ethernet Controller
+@@ -72,7 +75,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
+ 	struct e1000_phy_info *phy = &hw->phy;
+ 	s32 ret_val;
+ 
+-	if (hw->media_type != e1000_media_type_copper) {
++	if (hw->phy.media_type != e1000_media_type_copper) {
+ 		phy->type = e1000_phy_none;
+ 		return 0;
+ 	}
+@@ -150,7 +153,8 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
+ 		if (((eecd >> 15) & 0x3) == 0x3) {
+ 			nvm->type = e1000_nvm_flash_hw;
+ 			nvm->word_size = 2048;
+-			/* Autonomous Flash update bit must be cleared due
++			/*
++			 * Autonomous Flash update bit must be cleared due
+ 			 * to Flash update issue.
+ 			 */
+ 			eecd &= ~E1000_EECD_AUPDEN;
+@@ -159,13 +163,18 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
+ 		}
+ 		/* Fall Through */
+ 	default:
+-		nvm->type	= e1000_nvm_eeprom_spi;
++		nvm->type = e1000_nvm_eeprom_spi;
+ 		size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ 				  E1000_EECD_SIZE_EX_SHIFT);
+-		/* Added to a constant, "size" becomes the left-shift value
++		/*
++		 * Added to a constant, "size" becomes the left-shift value
+ 		 * for setting word_size.
+ 		 */
+ 		size += NVM_WORD_SIZE_BASE_SHIFT;
++
++		/* EEPROM access above 16k is unsupported */
++		if (size > 14)
++			size = 14;
+ 		nvm->word_size	= 1 << size;
+ 		break;
+ 	}
+@@ -190,16 +199,16 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
+ 	case E1000_DEV_ID_82571EB_FIBER:
+ 	case E1000_DEV_ID_82572EI_FIBER:
+ 	case E1000_DEV_ID_82571EB_QUAD_FIBER:
+-		hw->media_type = e1000_media_type_fiber;
++		hw->phy.media_type = e1000_media_type_fiber;
+ 		break;
+ 	case E1000_DEV_ID_82571EB_SERDES:
+ 	case E1000_DEV_ID_82572EI_SERDES:
+ 	case E1000_DEV_ID_82571EB_SERDES_DUAL:
+ 	case E1000_DEV_ID_82571EB_SERDES_QUAD:
+-		hw->media_type = e1000_media_type_internal_serdes;
++		hw->phy.media_type = e1000_media_type_internal_serdes;
+ 		break;
+ 	default:
+-		hw->media_type = e1000_media_type_copper;
++		hw->phy.media_type = e1000_media_type_copper;
+ 		break;
+ 	}
+ 
+@@ -208,25 +217,28 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
+ 	/* Set rar entry count */
+ 	mac->rar_entry_count = E1000_RAR_ENTRIES;
+ 	/* Set if manageability features are enabled. */
+-	mac->arc_subsystem_valid =
+-		(er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;
++	mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;
+ 
+ 	/* check for link */
+-	switch (hw->media_type) {
++	switch (hw->phy.media_type) {
+ 	case e1000_media_type_copper:
+ 		func->setup_physical_interface = e1000_setup_copper_link_82571;
+ 		func->check_for_link = e1000e_check_for_copper_link;
+ 		func->get_link_up_info = e1000e_get_speed_and_duplex_copper;
+ 		break;
+ 	case e1000_media_type_fiber:
+-		func->setup_physical_interface = e1000_setup_fiber_serdes_link_82571;
++		func->setup_physical_interface =
++			e1000_setup_fiber_serdes_link_82571;
+ 		func->check_for_link = e1000e_check_for_fiber_link;
+-		func->get_link_up_info = e1000e_get_speed_and_duplex_fiber_serdes;
++		func->get_link_up_info =
++			e1000e_get_speed_and_duplex_fiber_serdes;
+ 		break;
+ 	case e1000_media_type_internal_serdes:
+-		func->setup_physical_interface = e1000_setup_fiber_serdes_link_82571;
++		func->setup_physical_interface =
++			e1000_setup_fiber_serdes_link_82571;
+ 		func->check_for_link = e1000e_check_for_serdes_link;
+-		func->get_link_up_info = e1000e_get_speed_and_duplex_fiber_serdes;
++		func->get_link_up_info =
++			e1000e_get_speed_and_duplex_fiber_serdes;
+ 		break;
+ 	default:
+ 		return -E1000_ERR_CONFIG;
+@@ -236,7 +248,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
+ 	return 0;
+ }
+ 
+-static s32 e1000_get_invariants_82571(struct e1000_adapter *adapter)
++static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	static int global_quad_port_a; /* global port a indication */
+@@ -322,10 +334,12 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
+ 	switch (hw->mac.type) {
+ 	case e1000_82571:
+ 	case e1000_82572:
+-		/* The 82571 firmware may still be configuring the PHY.
++		/*
++		 * The 82571 firmware may still be configuring the PHY.
+ 		 * In this case, we cannot access the PHY until the
+ 		 * configuration is done.  So we explicitly set the
+-		 * PHY ID. */
++		 * PHY ID.
++		 */
+ 		phy->id = IGP01E1000_I_PHY_ID;
+ 		break;
+ 	case e1000_82573:
+@@ -479,8 +493,10 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* If our nvm is an EEPROM, then we're done
+-	 * otherwise, commit the checksum to the flash NVM. */
++	/*
++	 * If our nvm is an EEPROM, then we're done
++	 * otherwise, commit the checksum to the flash NVM.
++	 */
+ 	if (hw->nvm.type != e1000_nvm_flash_hw)
+ 		return ret_val;
+ 
+@@ -496,7 +512,8 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
+ 
+ 	/* Reset the firmware if using STM opcode. */
+ 	if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) {
+-		/* The enabling of and the actual reset must be done
++		/*
++		 * The enabling of and the actual reset must be done
+ 		 * in two write cycles.
+ 		 */
+ 		ew32(HICR, E1000_HICR_FW_RESET_ENABLE);
+@@ -557,8 +574,10 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
+ 	u32 eewr = 0;
+ 	s32 ret_val = 0;
+ 
+-	/* A check for invalid values:  offset too large, too many words,
+-	 * and not enough words. */
++	/*
++	 * A check for invalid values:  offset too large, too many words,
++	 * and not enough words.
++	 */
+ 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+ 	    (words == 0)) {
+ 		hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+@@ -645,30 +664,32 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
+ 	} else {
+ 		data &= ~IGP02E1000_PM_D0_LPLU;
+ 		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
+-		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
++		/*
++		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+ 		 * during Dx states where the power conservation is most
+ 		 * important.  During driver activity we should enable
+-		 * SmartSpeed, so performance is maintained. */
++		 * SmartSpeed, so performance is maintained.
++		 */
+ 		if (phy->smart_speed == e1000_smart_speed_on) {
+ 			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     &data);
++					   &data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+ 			data |= IGP01E1000_PSCFR_SMART_SPEED;
+ 			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     data);
++					   data);
+ 			if (ret_val)
+ 				return ret_val;
+ 		} else if (phy->smart_speed == e1000_smart_speed_off) {
+ 			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     &data);
++					   &data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+ 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ 			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     data);
++					   data);
+ 			if (ret_val)
+ 				return ret_val;
+ 		}
+@@ -693,7 +714,8 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
+ 	s32 ret_val;
+ 	u16 i = 0;
+ 
+-	/* Prevent the PCI-E bus from sticking if there is no TLP connection
++	/*
++	 * Prevent the PCI-E bus from sticking if there is no TLP connection
+ 	 * on the last TLP read/write transaction when MAC is reset.
+ 	 */
+ 	ret_val = e1000e_disable_pcie_master(hw);
+@@ -709,8 +731,10 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
+ 
+ 	msleep(10);
+ 
+-	/* Must acquire the MDIO ownership before MAC reset.
+-	 * Ownership defaults to firmware after a reset. */
++	/*
++	 * Must acquire the MDIO ownership before MAC reset.
++	 * Ownership defaults to firmware after a reset.
++	 */
+ 	if (hw->mac.type == e1000_82573) {
+ 		extcnf_ctrl = er32(EXTCNF_CTRL);
+ 		extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+@@ -747,7 +771,8 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
+ 		/* We don't want to continue accessing MAC registers. */
+ 		return ret_val;
+ 
+-	/* Phy configuration from NVM just starts after EECD_AUTO_RD is set.
++	/*
++	 * Phy configuration from NVM just starts after EECD_AUTO_RD is set.
+ 	 * Need to wait for Phy configuration completion before accessing
+ 	 * NVM and Phy.
+ 	 */
+@@ -793,7 +818,8 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
+ 	e1000e_clear_vfta(hw);
+ 
+ 	/* Setup the receive address. */
+-	/* If, however, a locally administered address was assigned to the
++	/*
++	 * If, however, a locally administered address was assigned to the
+ 	 * 82571, we must reserve a RAR for it to work around an issue where
+ 	 * resetting one port will reload the MAC on the other port.
+ 	 */
+@@ -810,19 +836,19 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
+ 	ret_val = e1000_setup_link_82571(hw);
+ 
+ 	/* Set the transmit descriptor write-back policy */
+-	reg_data = er32(TXDCTL);
++	reg_data = er32(TXDCTL(0));
+ 	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+ 		   E1000_TXDCTL_FULL_TX_DESC_WB |
+ 		   E1000_TXDCTL_COUNT_DESC;
+-	ew32(TXDCTL, reg_data);
++	ew32(TXDCTL(0), reg_data);
+ 
+ 	/* ...for both queues. */
+ 	if (mac->type != e1000_82573) {
+-		reg_data = er32(TXDCTL1);
++		reg_data = er32(TXDCTL(1));
+ 		reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+ 			   E1000_TXDCTL_FULL_TX_DESC_WB |
+ 			   E1000_TXDCTL_COUNT_DESC;
+-		ew32(TXDCTL1, reg_data);
++		ew32(TXDCTL(1), reg_data);
+ 	} else {
+ 		e1000e_enable_tx_pkt_filtering(hw);
+ 		reg_data = er32(GCR);
+@@ -830,7 +856,8 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
+ 		ew32(GCR, reg_data);
+ 	}
+ 
+-	/* Clear all of the statistics registers (clear on read).  It is
++	/*
++	 * Clear all of the statistics registers (clear on read).  It is
+ 	 * important that we do this after we have tried to establish link
+ 	 * because the symbol error count will increment wildly if there
+ 	 * is no link.
+@@ -851,17 +878,17 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
+ 	u32 reg;
+ 
+ 	/* Transmit Descriptor Control 0 */
+-	reg = er32(TXDCTL);
++	reg = er32(TXDCTL(0));
+ 	reg |= (1 << 22);
+-	ew32(TXDCTL, reg);
++	ew32(TXDCTL(0), reg);
+ 
+ 	/* Transmit Descriptor Control 1 */
+-	reg = er32(TXDCTL1);
++	reg = er32(TXDCTL(1));
+ 	reg |= (1 << 22);
+-	ew32(TXDCTL1, reg);
++	ew32(TXDCTL(1), reg);
+ 
+ 	/* Transmit Arbitration Control 0 */
+-	reg = er32(TARC0);
++	reg = er32(TARC(0));
+ 	reg &= ~(0xF << 27); /* 30:27 */
+ 	switch (hw->mac.type) {
+ 	case e1000_82571:
+@@ -871,10 +898,10 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
+ 	default:
+ 		break;
+ 	}
+-	ew32(TARC0, reg);
++	ew32(TARC(0), reg);
+ 
+ 	/* Transmit Arbitration Control 1 */
+-	reg = er32(TARC1);
++	reg = er32(TARC(1));
+ 	switch (hw->mac.type) {
+ 	case e1000_82571:
+ 	case e1000_82572:
+@@ -884,7 +911,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
+ 			reg &= ~(1 << 28);
+ 		else
+ 			reg |= (1 << 28);
+-		ew32(TARC1, reg);
++		ew32(TARC(1), reg);
+ 		break;
+ 	default:
+ 		break;
+@@ -922,7 +949,8 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
+ 
+ 	if (hw->mac.type == e1000_82573) {
+ 		if (hw->mng_cookie.vlan_id != 0) {
+-			/* The VFTA is a 4096b bit-field, each identifying
++			/*
++			 * The VFTA is a 4096b bit-field, each identifying
+ 			 * a single VLAN ID.  The following operations
+ 			 * determine which 32b entry (i.e. offset) into the
+ 			 * array we want to set the VLAN ID (i.e. bit) of
+@@ -936,7 +964,8 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
+ 		}
+ 	}
+ 	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+-		/* If the offset we want to clear is the same offset of the
++		/*
++		 * If the offset we want to clear is the same offset of the
+ 		 * manageability VLAN ID, then clear all bits except that of
+ 		 * the manageability unit.
+ 		 */
+@@ -947,7 +976,7 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
+ }
+ 
+ /**
+- *  e1000_mc_addr_list_update_82571 - Update Multicast addresses
++ *  e1000_update_mc_addr_list_82571 - 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
+@@ -959,7 +988,7 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
+  *  The parameter rar_count will usually be hw->mac.rar_entry_count
+  *  unless there are workarounds that change this.
+  **/
+-static void e1000_mc_addr_list_update_82571(struct e1000_hw *hw,
++static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw,
+ 					    u8 *mc_addr_list,
+ 					    u32 mc_addr_count,
+ 					    u32 rar_used_count,
+@@ -968,8 +997,8 @@ static void e1000_mc_addr_list_update_82571(struct e1000_hw *hw,
+ 	if (e1000e_get_laa_state_82571(hw))
+ 		rar_count--;
+ 
+-	e1000e_mc_addr_list_update_generic(hw, mc_addr_list, mc_addr_count,
+-					  rar_used_count, rar_count);
++	e1000e_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count,
++					   rar_used_count, rar_count);
+ }
+ 
+ /**
+@@ -984,12 +1013,13 @@ static void e1000_mc_addr_list_update_82571(struct e1000_hw *hw,
+  **/
+ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
+ {
+-	/* 82573 does not have a word in the NVM to determine
++	/*
++	 * 82573 does not have a word in the NVM to determine
+ 	 * the default flow control setting, so we explicitly
+ 	 * set it to full.
+ 	 */
+ 	if (hw->mac.type == e1000_82573)
+-		hw->mac.fc = e1000_fc_full;
++		hw->fc.type = e1000_fc_full;
+ 
+ 	return e1000e_setup_link(hw);
+ }
+@@ -1050,14 +1080,14 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
+ 	switch (hw->mac.type) {
+ 	case e1000_82571:
+ 	case e1000_82572:
+-		/* If SerDes loopback mode is entered, there is no form
++		/*
++		 * If SerDes loopback mode is entered, there is no form
+ 		 * of reset to take the adapter out of that mode.  So we
+ 		 * have to explicitly take the adapter out of loopback
+ 		 * mode.  This prevents drivers from twiddling their thumbs
+ 		 * if another tool failed to take it out of loopback mode.
+ 		 */
+-		ew32(SCTL,
+-				E1000_SCTL_DISABLE_SERDES_LOOPBACK);
++		ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
+ 		break;
+ 	default:
+ 		break;
+@@ -1124,7 +1154,8 @@ void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state)
+ 
+ 	/* If workaround is activated... */
+ 	if (state)
+-		/* Hold a copy of the LAA in RAR[14] This is done so that
++		/*
++		 * Hold a copy of the LAA in RAR[14] This is done so that
+ 		 * between the time RAR[0] gets clobbered and the time it
+ 		 * gets fixed, the actual LAA is in one of the RARs and no
+ 		 * incoming packets directed to this port are dropped.
+@@ -1152,7 +1183,8 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
+ 	if (nvm->type != e1000_nvm_flash_hw)
+ 		return 0;
+ 
+-	/* Check bit 4 of word 10h.  If it is 0, firmware is done updating
++	/*
++	 * Check bit 4 of word 10h.  If it is 0, firmware is done updating
+ 	 * 10h-12h.  Checksum may need to be fixed.
+ 	 */
+ 	ret_val = e1000_read_nvm(hw, 0x10, 1, &data);
+@@ -1160,7 +1192,8 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
+ 		return ret_val;
+ 
+ 	if (!(data & 0x10)) {
+-		/* Read 0x23 and check bit 15.  This bit is a 1
++		/*
++		 * Read 0x23 and check bit 15.  This bit is a 1
+ 		 * when the checksum has already been fixed.  If
+ 		 * the checksum is still wrong and this bit is a
+ 		 * 1, we need to return bad checksum.  Otherwise,
+@@ -1240,7 +1273,7 @@ static struct e1000_mac_operations e82571_mac_ops = {
+ 	/* .get_link_up_info: media type dependent */
+ 	.led_on			= e1000e_led_on_generic,
+ 	.led_off		= e1000e_led_off_generic,
+-	.mc_addr_list_update	= e1000_mc_addr_list_update_82571,
++	.update_mc_addr_list	= e1000_update_mc_addr_list_82571,
+ 	.reset_hw		= e1000_reset_hw_82571,
+ 	.init_hw		= e1000_init_hw_82571,
+ 	.setup_link		= e1000_setup_link_82571,
+@@ -1293,18 +1326,16 @@ struct e1000_info e1000_82571_info = {
+ 	.mac			= e1000_82571,
+ 	.flags			= FLAG_HAS_HW_VLAN_FILTER
+ 				  | FLAG_HAS_JUMBO_FRAMES
+-				  | FLAG_HAS_STATS_PTC_PRC
+ 				  | FLAG_HAS_WOL
+ 				  | FLAG_APME_IN_CTRL3
+ 				  | FLAG_RX_CSUM_ENABLED
+ 				  | FLAG_HAS_CTRLEXT_ON_LOAD
+-				  | FLAG_HAS_STATS_ICR_ICT
+ 				  | FLAG_HAS_SMART_POWER_DOWN
+ 				  | FLAG_RESET_OVERWRITES_LAA /* errata */
+ 				  | FLAG_TARC_SPEED_MODE_BIT /* errata */
+ 				  | FLAG_APME_CHECK_PORT_B,
+ 	.pba			= 38,
+-	.get_invariants		= e1000_get_invariants_82571,
++	.get_variants		= e1000_get_variants_82571,
+ 	.mac_ops		= &e82571_mac_ops,
+ 	.phy_ops		= &e82_phy_ops_igp,
+ 	.nvm_ops		= &e82571_nvm_ops,
+@@ -1314,15 +1345,13 @@ struct e1000_info e1000_82572_info = {
+ 	.mac			= e1000_82572,
+ 	.flags			= FLAG_HAS_HW_VLAN_FILTER
+ 				  | FLAG_HAS_JUMBO_FRAMES
+-				  | FLAG_HAS_STATS_PTC_PRC
+ 				  | FLAG_HAS_WOL
+ 				  | FLAG_APME_IN_CTRL3
+ 				  | FLAG_RX_CSUM_ENABLED
+ 				  | FLAG_HAS_CTRLEXT_ON_LOAD
+-				  | FLAG_HAS_STATS_ICR_ICT
+ 				  | FLAG_TARC_SPEED_MODE_BIT, /* errata */
+ 	.pba			= 38,
+-	.get_invariants		= e1000_get_invariants_82571,
++	.get_variants		= e1000_get_variants_82571,
+ 	.mac_ops		= &e82571_mac_ops,
+ 	.phy_ops		= &e82_phy_ops_igp,
+ 	.nvm_ops		= &e82571_nvm_ops,
+@@ -1332,17 +1361,15 @@ struct e1000_info e1000_82573_info = {
+ 	.mac			= e1000_82573,
+ 	.flags			= FLAG_HAS_HW_VLAN_FILTER
+ 				  | FLAG_HAS_JUMBO_FRAMES
+-				  | FLAG_HAS_STATS_PTC_PRC
+ 				  | FLAG_HAS_WOL
+ 				  | FLAG_APME_IN_CTRL3
+ 				  | FLAG_RX_CSUM_ENABLED
+-				  | FLAG_HAS_STATS_ICR_ICT
+ 				  | FLAG_HAS_SMART_POWER_DOWN
+ 				  | FLAG_HAS_AMT
+ 				  | FLAG_HAS_ERT
+ 				  | FLAG_HAS_SWSM_ON_LOAD,
+ 	.pba			= 20,
+-	.get_invariants		= e1000_get_invariants_82571,
++	.get_variants		= e1000_get_variants_82571,
+ 	.mac_ops		= &e82571_mac_ops,
+ 	.phy_ops		= &e82_phy_ops_m88,
+ 	.nvm_ops		= &e82571_nvm_ops,
+diff --git a/drivers/net/e1000e/Makefile b/drivers/net/e1000e/Makefile
+index 650f866..360c913 100644
+--- a/drivers/net/e1000e/Makefile
++++ b/drivers/net/e1000e/Makefile
+@@ -1,7 +1,7 @@
+ ################################################################################
+ #
+ # Intel PRO/1000 Linux driver
+-# Copyright(c) 1999 - 2007 Intel Corporation.
++# Copyright(c) 1999 - 2008 Intel Corporation.
+ #
+ # This program is free software; you can redistribute it and/or modify it
+ # under the terms and conditions of the GNU General Public License,
+diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
+index a4f511f..2a53875 100644
+--- a/drivers/net/e1000e/defines.h
++++ b/drivers/net/e1000e/defines.h
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -120,10 +120,10 @@
+ #define E1000_MANC_ARP_EN        0x00002000 /* Enable ARP Request Filtering */
+ #define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
+ #define E1000_MANC_BLK_PHY_RST_ON_IDE   0x00040000 /* Block phy resets */
+-#define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000 /* Enable MAC address
+-						    * filtering */
+-#define E1000_MANC_EN_MNG2HOST   0x00200000 /* Enable MNG packets to host
+-					     * memory */
++/* Enable MAC address filtering */
++#define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000
++/* Enable MNG packets to host memory */
++#define E1000_MANC_EN_MNG2HOST   0x00200000
+ 
+ /* Receive Control */
+ #define E1000_RCTL_EN             0x00000002    /* enable */
+@@ -135,25 +135,26 @@
+ #define E1000_RCTL_LBM_MAC        0x00000040    /* MAC loopback mode */
+ #define E1000_RCTL_LBM_TCVR       0x000000C0    /* tcvr loopback mode */
+ #define E1000_RCTL_DTYP_PS        0x00000400    /* Packet Split descriptor */
+-#define E1000_RCTL_RDMTS_HALF     0x00000000    /* rx desc min threshold size */
++#define E1000_RCTL_RDMTS_HALF     0x00000000    /* Rx desc min threshold size */
+ #define E1000_RCTL_MO_SHIFT       12            /* multicast offset shift */
+ #define E1000_RCTL_BAM            0x00008000    /* broadcast enable */
+ /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
+-#define E1000_RCTL_SZ_2048        0x00000000    /* rx buffer size 2048 */
+-#define E1000_RCTL_SZ_1024        0x00010000    /* rx buffer size 1024 */
+-#define E1000_RCTL_SZ_512         0x00020000    /* rx buffer size 512 */
+-#define E1000_RCTL_SZ_256         0x00030000    /* rx buffer size 256 */
++#define E1000_RCTL_SZ_2048        0x00000000    /* Rx buffer size 2048 */
++#define E1000_RCTL_SZ_1024        0x00010000    /* Rx buffer size 1024 */
++#define E1000_RCTL_SZ_512         0x00020000    /* Rx buffer size 512 */
++#define E1000_RCTL_SZ_256         0x00030000    /* Rx buffer size 256 */
+ /* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
+-#define E1000_RCTL_SZ_16384       0x00010000    /* rx buffer size 16384 */
+-#define E1000_RCTL_SZ_8192        0x00020000    /* rx buffer size 8192 */
+-#define E1000_RCTL_SZ_4096        0x00030000    /* rx buffer size 4096 */
++#define E1000_RCTL_SZ_16384       0x00010000    /* Rx buffer size 16384 */
++#define E1000_RCTL_SZ_8192        0x00020000    /* Rx buffer size 8192 */
++#define E1000_RCTL_SZ_4096        0x00030000    /* Rx buffer size 4096 */
+ #define E1000_RCTL_VFE            0x00040000    /* vlan filter enable */
+ #define E1000_RCTL_CFIEN          0x00080000    /* canonical form enable */
+ #define E1000_RCTL_CFI            0x00100000    /* canonical form indicator */
+ #define E1000_RCTL_BSEX           0x02000000    /* Buffer size extension */
+ #define E1000_RCTL_SECRC          0x04000000    /* Strip Ethernet CRC */
+ 
+-/* Use byte values for the following shift parameters
++/*
++ * Use byte values for the following shift parameters
+  * Usage:
+  *     psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
+  *                  E1000_PSRCTL_BSIZE0_MASK) |
+@@ -183,6 +184,7 @@
+ #define E1000_SWFW_EEP_SM   0x1
+ #define E1000_SWFW_PHY0_SM  0x2
+ #define E1000_SWFW_PHY1_SM  0x4
++#define E1000_SWFW_CSR_SM   0x8
+ 
+ /* Device Control */
+ #define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
+@@ -206,7 +208,8 @@
+ #define E1000_CTRL_VME      0x40000000  /* IEEE VLAN mode enable */
+ #define E1000_CTRL_PHY_RST  0x80000000  /* PHY Reset */
+ 
+-/* Bit definitions for the Management Data IO (MDIO) and Management Data
++/*
++ * Bit definitions for the Management Data IO (MDIO) and Management Data
+  * Clock (MDC) pins in the Device Control Register.
+  */
+ 
+@@ -279,7 +282,7 @@
+ #define E1000_TXD_STAT_TC    0x00000004 /* Tx Underrun */
+ 
+ /* Transmit Control */
+-#define E1000_TCTL_EN     0x00000002    /* enable tx */
++#define E1000_TCTL_EN     0x00000002    /* enable Tx */
+ #define E1000_TCTL_PSP    0x00000008    /* pad short packets */
+ #define E1000_TCTL_CT     0x00000ff0    /* collision threshold */
+ #define E1000_TCTL_COLD   0x003ff000    /* collision distance */
+@@ -337,8 +340,8 @@
+ #define E1000_KABGTXD_BGSQLBIAS           0x00050000
+ 
+ /* PBA constants */
+-#define E1000_PBA_8K  0x0008    /* 8KB, default Rx allocation */
+-#define E1000_PBA_16K 0x0010    /* 16KB, default TX allocation */
++#define E1000_PBA_8K  0x0008    /* 8KB */
++#define E1000_PBA_16K 0x0010    /* 16KB */
+ 
+ #define E1000_PBS_16K E1000_PBA_16K
+ 
+@@ -356,12 +359,13 @@
+ /* Interrupt Cause Read */
+ #define E1000_ICR_TXDW          0x00000001 /* Transmit desc written back */
+ #define E1000_ICR_LSC           0x00000004 /* Link Status Change */
+-#define E1000_ICR_RXSEQ         0x00000008 /* rx sequence error */
+-#define E1000_ICR_RXDMT0        0x00000010 /* rx desc min. threshold (0) */
+-#define E1000_ICR_RXT0          0x00000080 /* rx timer intr (ring 0) */
++#define E1000_ICR_RXSEQ         0x00000008 /* Rx sequence error */
++#define E1000_ICR_RXDMT0        0x00000010 /* Rx desc min. threshold (0) */
++#define E1000_ICR_RXT0          0x00000080 /* Rx timer intr (ring 0) */
+ #define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver should claim the interrupt */
+ 
+-/* This defines the bits that are set in the Interrupt Mask
++/*
++ * 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
+@@ -379,21 +383,22 @@
+ /* Interrupt Mask Set */
+ #define E1000_IMS_TXDW      E1000_ICR_TXDW      /* Transmit desc written back */
+ #define E1000_IMS_LSC       E1000_ICR_LSC       /* Link Status Change */
+-#define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* rx sequence error */
+-#define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold */
+-#define E1000_IMS_RXT0      E1000_ICR_RXT0      /* rx timer intr */
++#define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* Rx sequence error */
++#define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* Rx desc min. threshold */
++#define E1000_IMS_RXT0      E1000_ICR_RXT0      /* Rx timer intr */
+ 
+ /* Interrupt Cause Set */
+ #define E1000_ICS_LSC       E1000_ICR_LSC       /* Link Status Change */
+ #define E1000_ICS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold */
++#define E1000_ICS_RXDMT0    E1000_ICR_RXDMT0    /* Rx desc min. threshold */
+ 
+ /* Transmit Descriptor Control */
+ #define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
+ #define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
+ #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+ #define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
+-#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
+-					      still to be processed. */
++/* Enable the counting of desc. still to be processed. */
++#define E1000_TXDCTL_COUNT_DESC 0x00400000
+ 
+ /* Flow Control Constants */
+ #define FLOW_CONTROL_ADDRESS_LOW  0x00C28001
+@@ -404,7 +409,8 @@
+ #define E1000_VLAN_FILTER_TBL_SIZE 128  /* VLAN Filter Table (4096 bits) */
+ 
+ /* Receive Address */
+-/* Number of high/low register pairs in the RAR. The RAR (Receive Address
++/*
++ * Number of high/low register pairs in the RAR. The RAR (Receive Address
+  * Registers) holds the directed and multicast addresses that we monitor.
+  * Technically, we have 16 spots.  However, we reserve one of these spots
+  * (RAR[15]) for our directed address used by controllers with
+@@ -522,8 +528,10 @@
+ #define PHY_ID2          0x03 /* Phy Id Reg (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 Reg */
+ #define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
+ #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
++#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
+ 
+ /* NVM Control */
+ #define E1000_EECD_SK        0x00000001 /* NVM Clock */
+@@ -533,8 +541,8 @@
+ #define E1000_EECD_REQ       0x00000040 /* NVM Access Request */
+ #define E1000_EECD_GNT       0x00000080 /* NVM Access Grant */
+ #define E1000_EECD_SIZE      0x00000200 /* NVM Size (0=64 word 1=256 word) */
+-#define E1000_EECD_ADDR_BITS 0x00000400 /* NVM Addressing bits based on type
+-					 * (0-small, 1-large) */
++/* NVM Addressing bits based on type (0-small, 1-large) */
++#define E1000_EECD_ADDR_BITS 0x00000400
+ #define E1000_NVM_GRANT_ATTEMPTS   1000 /* NVM # attempts to gain grant */
+ #define E1000_EECD_AUTO_RD          0x00000200  /* NVM Auto Read done */
+ #define E1000_EECD_SIZE_EX_MASK     0x00007800  /* NVM Size */
+@@ -626,7 +634,8 @@
+ #define MAX_PHY_MULTI_PAGE_REG 0xF
+ 
+ /* Bit definitions for valid PHY IDs. */
+-/* I = Integrated
++/*
++ * I = Integrated
+  * E = External
+  */
+ #define M88E1000_E_PHY_ID    0x01410C50
+@@ -653,37 +662,37 @@
+ #define M88E1000_PSCR_MDI_MANUAL_MODE  0x0000  /* MDI Crossover Mode bits 6:5 */
+ 					       /* Manual MDI configuration */
+ #define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020  /* Manual MDIX configuration */
+-#define M88E1000_PSCR_AUTO_X_1000T     0x0040  /* 1000BASE-T: Auto crossover,
+-						*  100BASE-TX/10BASE-T:
+-						*  MDI Mode
+-						*/
+-#define M88E1000_PSCR_AUTO_X_MODE      0x0060  /* Auto crossover enabled
+-						* all speeds.
+-						*/
+-					/* 1=Enable Extended 10BASE-T distance
+-					 * (Lower 10BASE-T RX Threshold)
+-					 * 0=Normal 10BASE-T RX Threshold */
+-					/* 1=5-Bit interface in 100BASE-TX
+-					 * 0=MII interface in 100BASE-TX */
+-#define M88E1000_PSCR_ASSERT_CRS_ON_TX     0x0800 /* 1=Assert CRS on Transmit */
++/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
++#define M88E1000_PSCR_AUTO_X_1000T     0x0040
++/* Auto crossover enabled all speeds */
++#define M88E1000_PSCR_AUTO_X_MODE      0x0060
++/*
++ * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold)
++ * 0=Normal 10BASE-T Rx Threshold
++ */
++#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
+ 
+ /* M88E1000 PHY Specific Status Register */
+ #define M88E1000_PSSR_REV_POLARITY       0x0002 /* 1=Polarity reversed */
+ #define M88E1000_PSSR_DOWNSHIFT          0x0020 /* 1=Downshifted */
+ #define M88E1000_PSSR_MDIX               0x0040 /* 1=MDIX; 0=MDI */
+-#define M88E1000_PSSR_CABLE_LENGTH       0x0380 /* 0=<50M;1=50-80M;2=80-110M;
+-					    * 3=110-140M;4=>140M */
++/* 0=<50M; 1=50-80M; 2=80-110M; 3=110-140M; 4=>140M */
++#define M88E1000_PSSR_CABLE_LENGTH       0x0380
+ #define M88E1000_PSSR_SPEED              0xC000 /* Speed, bits 14:15 */
+ #define M88E1000_PSSR_1000MBS            0x8000 /* 10=1000Mbs */
+ 
+ #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
+ 
+-/* Number of times we will attempt to autonegotiate before downshifting if we
+- * are the master */
++/*
++ * Number of times we will attempt to autonegotiate before downshifting if we
++ * are the master
++ */
+ #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
+ #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X   0x0000
+-/* Number of times we will attempt to autonegotiate before downshifting if we
+- * are the slave */
++/*
++ * Number of times we will attempt to autonegotiate before downshifting if we
++ * are the slave
++ */
+ #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK  0x0300
+ #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X    0x0100
+ #define M88E1000_EPSCR_TX_CLK_25      0x0070 /* 25  MHz TX_CLK */
+@@ -692,7 +701,8 @@
+ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK  0x0E00
+ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X    0x0800
+ 
+-/* Bits...
++/*
++ * Bits...
+  * 15-5: page
+  * 4-0: register offset
+  */
+diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
+index 327c062..38bfd0d 100644
+--- a/drivers/net/e1000e/e1000.h
++++ b/drivers/net/e1000e/e1000.h
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -61,14 +61,17 @@ struct e1000_info;
+ 	ndev_printk(KERN_NOTICE , netdev, format, ## arg)
+ 
+ 
+-/* TX/RX descriptor defines */
++/* Tx/Rx descriptor defines */
+ #define E1000_DEFAULT_TXD		256
+ #define E1000_MAX_TXD			4096
+-#define E1000_MIN_TXD			80
++#define E1000_MIN_TXD			64
+ 
+ #define E1000_DEFAULT_RXD		256
+ #define E1000_MAX_RXD			4096
+-#define E1000_MIN_RXD			80
++#define E1000_MIN_RXD			64
++
++#define E1000_MIN_ITR_USECS		10 /* 100000 irq/sec */
++#define E1000_MAX_ITR_USECS		10000 /* 100    irq/sec */
+ 
+ /* Early Receive defines */
+ #define E1000_ERT_2048			0x100
+@@ -114,13 +117,13 @@ struct e1000_buffer {
+ 	dma_addr_t dma;
+ 	struct sk_buff *skb;
+ 	union {
+-		/* TX */
++		/* Tx */
+ 		struct {
+ 			unsigned long time_stamp;
+ 			u16 length;
+ 			u16 next_to_watch;
+ 		};
+-		/* RX */
++		/* Rx */
+ 		/* arrays of page information for packet split */
+ 		struct e1000_ps_page *ps_pages;
+ 	};
+@@ -147,6 +150,18 @@ struct e1000_ring {
+ 	struct e1000_queue_stats stats;
+ };
+ 
++/* PHY register snapshot values */
++struct e1000_phy_regs {
++	u16 bmcr;		/* basic mode control register    */
++	u16 bmsr;		/* basic mode status register     */
++	u16 advertise;		/* auto-negotiation advertisement */
++	u16 lpa;		/* link partner ability register  */
++	u16 expansion;		/* auto-negotiation expansion reg */
++	u16 ctrl1000;		/* 1000BASE-T control register    */
++	u16 stat1000;		/* 1000BASE-T status register     */
++	u16 estatus;		/* extended status register       */
++};
++
+ /* board specific private data structure */
+ struct e1000_adapter {
+ 	struct timer_list watchdog_timer;
+@@ -167,9 +182,6 @@ struct e1000_adapter {
+ 
+ 	spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
+ 
+-	/* this is still needed for 82571 and above */
+-	atomic_t irq_sem;
+-
+ 	/* track device up/down/testing state */
+ 	unsigned long state;
+ 
+@@ -180,7 +192,7 @@ struct e1000_adapter {
+ 	u16 rx_itr;
+ 
+ 	/*
+-	 * TX
++	 * Tx
+ 	 */
+ 	struct e1000_ring *tx_ring /* One per active queue */
+ 						____cacheline_aligned_in_smp;
+@@ -202,11 +214,11 @@ struct e1000_adapter {
+ 	unsigned int total_rx_bytes;
+ 	unsigned int total_rx_packets;
+ 
+-	/* TX stats */
++	/* Tx stats */
+ 	u64 tpt_old;
+ 	u64 colc_old;
+-	u64 gotcl_old;
+-	u32 gotcl;
++	u32 gotc;
++	u64 gotc_old;
+ 	u32 tx_timeout_count;
+ 	u32 tx_fifo_head;
+ 	u32 tx_head_addr;
+@@ -214,7 +226,7 @@ struct e1000_adapter {
+ 	u32 tx_dma_failed;
+ 
+ 	/*
+-	 * RX
++	 * Rx
+ 	 */
+ 	bool (*clean_rx) (struct e1000_adapter *adapter,
+ 			  int *work_done, int work_to_do)
+@@ -226,17 +238,19 @@ struct e1000_adapter {
+ 	u32 rx_int_delay;
+ 	u32 rx_abs_int_delay;
+ 
+-	/* RX stats */
++	/* Rx stats */
+ 	u64 hw_csum_err;
+ 	u64 hw_csum_good;
+ 	u64 rx_hdr_split;
+-	u64 gorcl_old;
+-	u32 gorcl;
++	u32 gorc;
++	u64 gorc_old;
+ 	u32 alloc_rx_buff_failed;
+ 	u32 rx_dma_failed;
+ 
+ 	unsigned int rx_ps_pages;
+ 	u16 rx_ps_bsize0;
++	u32 max_frame_size;
++	u32 min_frame_size;
+ 
+ 	/* OS defined structs */
+ 	struct net_device *netdev;
+@@ -251,6 +265,9 @@ struct e1000_adapter {
+ 	struct e1000_phy_info phy_info;
+ 	struct e1000_phy_stats phy_stats;
+ 
++	/* Snapshot of PHY registers */
++	struct e1000_phy_regs phy_regs;
++
+ 	struct e1000_ring test_tx_ring;
+ 	struct e1000_ring test_rx_ring;
+ 	u32 test_icr;
+@@ -261,7 +278,7 @@ struct e1000_adapter {
+ 	u32 wol;
+ 	u32 pba;
+ 
+-	u8 fc_autoneg;
++	bool fc_autoneg;
+ 
+ 	unsigned long led_status;
+ 
+@@ -272,7 +289,7 @@ struct e1000_info {
+ 	enum e1000_mac_type	mac;
+ 	unsigned int		flags;
+ 	u32			pba;
+-	s32			(*get_invariants)(struct e1000_adapter *);
++	s32			(*get_variants)(struct e1000_adapter *);
+ 	struct e1000_mac_operations *mac_ops;
+ 	struct e1000_phy_operations *phy_ops;
+ 	struct e1000_nvm_operations *nvm_ops;
+@@ -287,8 +304,6 @@ struct e1000_info {
+ #define FLAG_HAS_CTRLEXT_ON_LOAD          (1 << 5)
+ #define FLAG_HAS_SWSM_ON_LOAD             (1 << 6)
+ #define FLAG_HAS_JUMBO_FRAMES             (1 << 7)
+-#define FLAG_HAS_STATS_ICR_ICT            (1 << 9)
+-#define FLAG_HAS_STATS_PTC_PRC            (1 << 10)
+ #define FLAG_HAS_SMART_POWER_DOWN         (1 << 11)
+ #define FLAG_IS_QUAD_PORT_A               (1 << 12)
+ #define FLAG_IS_QUAD_PORT                 (1 << 13)
+@@ -308,6 +323,7 @@ struct e1000_info {
+ #define FLAG_MSI_ENABLED                  (1 << 27)
+ #define FLAG_RX_CSUM_ENABLED              (1 << 28)
+ #define FLAG_TSO_FORCE                    (1 << 29)
++#define FLAG_RX_RESTART_NOW               (1 << 30)
+ 
+ #define E1000_RX_DESC_PS(R, i)	    \
+ 	(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
+@@ -357,7 +373,7 @@ extern struct e1000_info e1000_ich8_info;
+ extern struct e1000_info e1000_ich9_info;
+ extern struct e1000_info e1000_es2_info;
+ 
+-extern s32 e1000e_read_part_num(struct e1000_hw *hw, u32 *part_num);
++extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
+ 
+ extern s32  e1000e_commit_phy(struct e1000_hw *hw);
+ 
+@@ -390,9 +406,11 @@ extern s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw);
+ extern s32 e1000e_setup_link(struct e1000_hw *hw);
+ extern void e1000e_clear_vfta(struct e1000_hw *hw);
+ extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
+-extern void e1000e_mc_addr_list_update_generic(struct e1000_hw *hw,
+-				       u8 *mc_addr_list, u32 mc_addr_count,
+-				       u32 rar_used_count, u32 rar_count);
++extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
++					       u8 *mc_addr_list,
++					       u32 mc_addr_count,
++					       u32 rar_used_count,
++					       u32 rar_count);
+ extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
+ extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw);
+ extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop);
+@@ -431,6 +449,8 @@ extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+ extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
+ 			       u32 usec_interval, bool *success);
+ extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw);
++extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
++extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
+ extern s32 e1000e_check_downshift(struct e1000_hw *hw);
+ 
+ static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
+@@ -462,7 +482,6 @@ extern s32 e1000e_acquire_nvm(struct e1000_hw *hw);
+ extern s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+ extern s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw);
+ extern s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
+-extern s32 e1000e_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+ extern s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+ extern s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw);
+ extern void e1000e_release_nvm(struct e1000_hw *hw);
+diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
+index 88657ad..dc552d7 100644
+--- a/drivers/net/e1000e/es2lan.c
++++ b/drivers/net/e1000e/es2lan.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -41,6 +41,7 @@
+ #define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL	 0x00
+ #define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL	 0x02
+ #define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL	 0x10
++#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE	 0x1F
+ 
+ #define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS	 0x0008
+ #define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS	 0x0800
+@@ -48,6 +49,7 @@
+ 
+ #define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004
+ #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT	 0x0000
++#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE		 0x2000
+ 
+ #define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
+ #define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN	 0x00010000
+@@ -85,6 +87,9 @@
+ /* Kumeran Mode Control Register (Page 193, Register 16) */
+ #define GG82563_KMCR_PASS_FALSE_CARRIER		 0x0800
+ 
++/* Max number of times Kumeran read/write should be validated */
++#define GG82563_MAX_KMRN_RETRY  0x5
++
+ /* Power Management Control Register (Page 193, Register 20) */
+ #define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE	 0x0001
+ 					   /* 1=Enable SERDES Electrical Idle */
+@@ -92,7 +97,8 @@
+ /* In-Band Control Register (Page 194, Register 18) */
+ #define GG82563_ICR_DIS_PADDING			 0x0010 /* Disable Padding */
+ 
+-/* A table for the GG82563 cable length where the range is defined
++/*
++ * A table for the GG82563 cable length where the range is defined
+  * with a lower bound at "index" and the upper bound at
+  * "index + 5".
+  */
+@@ -118,7 +124,7 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
+ 	struct e1000_phy_info *phy = &hw->phy;
+ 	s32 ret_val;
+ 
+-	if (hw->media_type != e1000_media_type_copper) {
++	if (hw->phy.media_type != e1000_media_type_copper) {
+ 		phy->type	= e1000_phy_none;
+ 		return 0;
+ 	}
+@@ -167,15 +173,20 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
+ 		break;
+ 	}
+ 
+-	nvm->type	       = e1000_nvm_eeprom_spi;
++	nvm->type = e1000_nvm_eeprom_spi;
+ 
+ 	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ 			  E1000_EECD_SIZE_EX_SHIFT);
+ 
+-	/* Added to a constant, "size" becomes the left-shift value
++	/*
++	 * Added to a constant, "size" becomes the left-shift value
+ 	 * for setting word_size.
+ 	 */
+ 	size += NVM_WORD_SIZE_BASE_SHIFT;
++
++	/* EEPROM access above 16k is unsupported */
++	if (size > 14)
++		size = 14;
+ 	nvm->word_size	= 1 << size;
+ 
+ 	return 0;
+@@ -196,10 +207,10 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
+ 	/* Set media type */
+ 	switch (adapter->pdev->device) {
+ 	case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
+-		hw->media_type = e1000_media_type_internal_serdes;
++		hw->phy.media_type = e1000_media_type_internal_serdes;
+ 		break;
+ 	default:
+-		hw->media_type = e1000_media_type_copper;
++		hw->phy.media_type = e1000_media_type_copper;
+ 		break;
+ 	}
+ 
+@@ -208,11 +219,10 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
+ 	/* Set rar entry count */
+ 	mac->rar_entry_count = E1000_RAR_ENTRIES;
+ 	/* Set if manageability features are enabled. */
+-	mac->arc_subsystem_valid =
+-		(er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;
++	mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;
+ 
+ 	/* check for link */
+-	switch (hw->media_type) {
++	switch (hw->phy.media_type) {
+ 	case e1000_media_type_copper:
+ 		func->setup_physical_interface = e1000_setup_copper_link_80003es2lan;
+ 		func->check_for_link = e1000e_check_for_copper_link;
+@@ -233,7 +243,7 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
+ 	return 0;
+ }
+ 
+-static s32 e1000_get_invariants_80003es2lan(struct e1000_adapter *adapter)
++static s32 e1000_get_variants_80003es2lan(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	s32 rc;
+@@ -265,6 +275,7 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
+ 	u16 mask;
+ 
+ 	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
++	mask |= E1000_SWFW_CSR_SM;
+ 
+ 	return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
+ }
+@@ -281,6 +292,8 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
+ 	u16 mask;
+ 
+ 	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
++	mask |= E1000_SWFW_CSR_SM;
++
+ 	e1000_release_swfw_sync_80003es2lan(hw, mask);
+ }
+ 
+@@ -344,8 +357,10 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
+ 		if (!(swfw_sync & (fwmask | swmask)))
+ 			break;
+ 
+-		/* Firmware currently using resource (fwmask)
+-		 * or other software thread using resource (swmask) */
++		/*
++		 * Firmware currently using resource (fwmask)
++		 * or other software thread using resource (swmask)
++		 */
+ 		e1000e_put_hw_semaphore(hw);
+ 		mdelay(5);
+ 		i++;
+@@ -403,41 +418,51 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
+ 	u32 page_select;
+ 	u16 temp;
+ 
++	ret_val = e1000_acquire_phy_80003es2lan(hw);
++	if (ret_val)
++		return ret_val;
++
+ 	/* Select Configuration Page */
+-	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
++	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+ 		page_select = GG82563_PHY_PAGE_SELECT;
+-	else
+-		/* Use Alternative Page Select register to access
++	} else {
++		/*
++		 * Use Alternative Page Select register to access
+ 		 * registers 30 and 31
+ 		 */
+ 		page_select = GG82563_PHY_PAGE_SELECT_ALT;
++	}
+ 
+ 	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
+-	ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp);
+-	if (ret_val)
++	ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
++	if (ret_val) {
++		e1000_release_phy_80003es2lan(hw);
+ 		return ret_val;
++	}
+ 
+-	/* The "ready" bit in the MDIC register may be incorrectly set
++	/*
++	 * The "ready" bit in the MDIC register may be incorrectly set
+ 	 * before the device has completed the "Page Select" MDI
+ 	 * transaction.  So we wait 200us after each MDI command...
+ 	 */
+ 	udelay(200);
+ 
+ 	/* ...and verify the command was successful. */
+-	ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp);
++	ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
+ 
+ 	if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
+ 		ret_val = -E1000_ERR_PHY;
++		e1000_release_phy_80003es2lan(hw);
+ 		return ret_val;
+ 	}
+ 
+ 	udelay(200);
+ 
+-	ret_val = e1000e_read_phy_reg_m88(hw,
+-					 MAX_PHY_REG_ADDRESS & offset,
+-					 data);
++	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++					   data);
+ 
+ 	udelay(200);
++	e1000_release_phy_80003es2lan(hw);
+ 
+ 	return ret_val;
+ }
+@@ -458,40 +483,51 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
+ 	u32 page_select;
+ 	u16 temp;
+ 
++	ret_val = e1000_acquire_phy_80003es2lan(hw);
++	if (ret_val)
++		return ret_val;
++
+ 	/* Select Configuration Page */
+-	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
++	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+ 		page_select = GG82563_PHY_PAGE_SELECT;
+-	else
+-		/* Use Alternative Page Select register to access
++	} else {
++		/*
++		 * Use Alternative Page Select register to access
+ 		 * registers 30 and 31
+ 		 */
+ 		page_select = GG82563_PHY_PAGE_SELECT_ALT;
++	}
+ 
+ 	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
+-	ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp);
+-	if (ret_val)
++	ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
++	if (ret_val) {
++		e1000_release_phy_80003es2lan(hw);
+ 		return ret_val;
++	}
+ 
+ 
+-	/* The "ready" bit in the MDIC register may be incorrectly set
++	/*
++	 * The "ready" bit in the MDIC register may be incorrectly set
+ 	 * before the device has completed the "Page Select" MDI
+ 	 * transaction.  So we wait 200us after each MDI command...
+ 	 */
+ 	udelay(200);
+ 
+ 	/* ...and verify the command was successful. */
+-	ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp);
++	ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
+ 
+-	if (((u16)offset >> GG82563_PAGE_SHIFT) != temp)
++	if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
++		e1000_release_phy_80003es2lan(hw);
+ 		return -E1000_ERR_PHY;
++	}
+ 
+ 	udelay(200);
+ 
+-	ret_val = e1000e_write_phy_reg_m88(hw,
+-					  MAX_PHY_REG_ADDRESS & offset,
+-					  data);
++	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++					    data);
+ 
+ 	udelay(200);
++	e1000_release_phy_80003es2lan(hw);
+ 
+ 	return ret_val;
+ }
+@@ -554,7 +590,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+ 	u16 phy_data;
+ 	bool link;
+ 
+-	/* Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
++	/*
++	 * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
+ 	 * forced whenever speed and duplex are forced.
+ 	 */
+ 	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+@@ -583,7 +620,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+ 
+ 	udelay(1);
+ 
+-	if (hw->phy.wait_for_link) {
++	if (hw->phy.autoneg_wait_to_complete) {
+ 		hw_dbg(hw, "Waiting for forced speed/duplex link "
+ 			 "on GG82563 phy.\n");
+ 
+@@ -593,7 +630,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+ 			return ret_val;
+ 
+ 		if (!link) {
+-			/* We didn't get link.
++			/*
++			 * We didn't get link.
+ 			 * Reset the DSP and cross our fingers.
+ 			 */
+ 			ret_val = e1000e_phy_reset_dsp(hw);
+@@ -612,7 +650,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* Resetting the phy means we need to verify the TX_CLK corresponds
++	/*
++	 * Resetting the phy means we need to verify the TX_CLK corresponds
+ 	 * to the link speed.  10Mbps -> 2.5MHz, else 25MHz.
+ 	 */
+ 	phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
+@@ -621,7 +660,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+ 	else
+ 		phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
+ 
+-	/* In addition, we must re-enable CRS on Tx for both half and full
++	/*
++	 * In addition, we must re-enable CRS on Tx for both half and full
+ 	 * duplex.
+ 	 */
+ 	phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+@@ -671,7 +711,7 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
+ {
+ 	s32 ret_val;
+ 
+-	if (hw->media_type == e1000_media_type_copper) {
++	if (hw->phy.media_type == e1000_media_type_copper) {
+ 		ret_val = e1000e_get_speed_and_duplex_copper(hw,
+ 								    speed,
+ 								    duplex);
+@@ -704,7 +744,8 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
+ 	u32 icr;
+ 	s32 ret_val;
+ 
+-	/* Prevent the PCI-E bus from sticking if there is no TLP connection
++	/*
++	 * Prevent the PCI-E bus from sticking if there is no TLP connection
+ 	 * on the last TLP read/write transaction when MAC is reset.
+ 	 */
+ 	ret_val = e1000e_disable_pcie_master(hw);
+@@ -776,16 +817,16 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
+ 	ret_val = e1000e_setup_link(hw);
+ 
+ 	/* Set the transmit descriptor write-back policy */
+-	reg_data = er32(TXDCTL);
++	reg_data = er32(TXDCTL(0));
+ 	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+ 		   E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
+-	ew32(TXDCTL, reg_data);
++	ew32(TXDCTL(0), reg_data);
+ 
+ 	/* ...for both queues. */
+-	reg_data = er32(TXDCTL1);
++	reg_data = er32(TXDCTL(1));
+ 	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+ 		   E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
+-	ew32(TXDCTL1, reg_data);
++	ew32(TXDCTL(1), reg_data);
+ 
+ 	/* Enable retransmit on late collisions */
+ 	reg_data = er32(TCTL);
+@@ -808,7 +849,8 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
+ 	reg_data &= ~0x00100000;
+ 	E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data);
+ 
+-	/* Clear all of the statistics registers (clear on read).  It is
++	/*
++	 * Clear all of the statistics registers (clear on read).  It is
+ 	 * important that we do this after we have tried to establish link
+ 	 * because the symbol error count will increment wildly if there
+ 	 * is no link.
+@@ -829,29 +871,29 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
+ 	u32 reg;
+ 
+ 	/* Transmit Descriptor Control 0 */
+-	reg = er32(TXDCTL);
++	reg = er32(TXDCTL(0));
+ 	reg |= (1 << 22);
+-	ew32(TXDCTL, reg);
++	ew32(TXDCTL(0), reg);
+ 
+ 	/* Transmit Descriptor Control 1 */
+-	reg = er32(TXDCTL1);
++	reg = er32(TXDCTL(1));
+ 	reg |= (1 << 22);
+-	ew32(TXDCTL1, reg);
++	ew32(TXDCTL(1), reg);
+ 
+ 	/* Transmit Arbitration Control 0 */
+-	reg = er32(TARC0);
++	reg = er32(TARC(0));
+ 	reg &= ~(0xF << 27); /* 30:27 */
+-	if (hw->media_type != e1000_media_type_copper)
++	if (hw->phy.media_type != e1000_media_type_copper)
+ 		reg &= ~(1 << 20);
+-	ew32(TARC0, reg);
++	ew32(TARC(0), reg);
+ 
+ 	/* Transmit Arbitration Control 1 */
+-	reg = er32(TARC1);
++	reg = er32(TARC(1));
+ 	if (er32(TCTL) & E1000_TCTL_MULR)
+ 		reg &= ~(1 << 28);
+ 	else
+ 		reg |= (1 << 28);
+-	ew32(TARC1, reg);
++	ew32(TARC(1), reg);
+ }
+ 
+ /**
+@@ -865,10 +907,10 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ 	struct e1000_phy_info *phy = &hw->phy;
+ 	s32 ret_val;
+ 	u32 ctrl_ext;
+-	u16 data;
++	u32 i = 0;
++	u16 data, data2;
+ 
+-	ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL,
+-				     &data);
++	ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
+ 	if (ret_val)
+ 		return ret_val;
+ 
+@@ -876,12 +918,12 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ 	/* Use 25MHz for both link down and 1000Base-T for Tx clock. */
+ 	data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
+ 
+-	ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL,
+-				      data);
++	ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* Options:
++	/*
++	 * Options:
+ 	 *   MDI/MDI-X = 0 (default)
+ 	 *   0 - Auto for all speeds
+ 	 *   1 - MDI mode
+@@ -907,7 +949,8 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ 		break;
+ 	}
+ 
+-	/* Options:
++	/*
++	 * Options:
+ 	 *   disable_polarity_correction = 0 (default)
+ 	 *       Automatic Correction for Reversed Cable Polarity
+ 	 *   0 - Disabled
+@@ -928,14 +971,25 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ 		return ret_val;
+ 	}
+ 
+-	/* Bypass RX and TX FIFO's */
+-	ret_val = e1000e_write_kmrn_reg(hw,
+-				E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
+-				E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
++	/* Bypass Rx and Tx FIFO's */
++	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
++					E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
+ 					E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
+ 	if (ret_val)
+ 		return ret_val;
+ 
++	ret_val = e1000e_read_kmrn_reg(hw,
++				       E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
++				       &data);
++	if (ret_val)
++		return ret_val;
++	data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
++	ret_val = e1000e_write_kmrn_reg(hw,
++					E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
++					data);
++	if (ret_val)
++		return ret_val;
++
+ 	ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data);
+ 	if (ret_val)
+ 		return ret_val;
+@@ -953,7 +1007,8 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* Do not init these registers when the HW is in IAMT mode, since the
++	/*
++	 * Do not init these registers when the HW is in IAMT mode, since the
+ 	 * firmware will have already initialized them.  We only initialize
+ 	 * them if the HW is not in IAMT mode.
+ 	 */
+@@ -964,9 +1019,18 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ 		if (ret_val)
+ 			return ret_val;
+ 
+-		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data);
+-		if (ret_val)
+-			return ret_val;
++		do {
++			ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
++					   &data);
++			if (ret_val)
++				return ret_val;
++
++			ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
++					   &data2);
++			if (ret_val)
++				return ret_val;
++			i++;
++		} while ((data != data2) && (i < GG82563_MAX_KMRN_RETRY));
+ 
+ 		data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+ 		ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data);
+@@ -974,7 +1038,8 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ 			return ret_val;
+ 	}
+ 
+-	/* Workaround: Disable padding in Kumeran interface in the MAC
++	/*
++	 * Workaround: Disable padding in Kumeran interface in the MAC
+ 	 * and in the PHY to avoid CRC errors.
+ 	 */
+ 	ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data);
+@@ -1007,9 +1072,11 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
+ 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ 	ew32(CTRL, ctrl);
+ 
+-	/* Set the mac to wait the maximum time between each
++	/*
++	 * Set the mac to wait the maximum time between each
+ 	 * iteration and increase the max iterations when
+-	 * polling the phy; this fixes erroneous timeouts at 10Mbps. */
++	 * polling the phy; this fixes erroneous timeouts at 10Mbps.
++	 */
+ 	ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+ 	if (ret_val)
+ 		return ret_val;
+@@ -1026,9 +1093,8 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 	reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
+-	ret_val = e1000e_write_kmrn_reg(hw,
+-				       E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
+-				       reg_data);
++	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
++					reg_data);
+ 	if (ret_val)
+ 		return ret_val;
+ 
+@@ -1053,12 +1119,12 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
+ {
+ 	s32 ret_val;
+ 	u32 tipg;
+-	u16 reg_data;
++	u32 i = 0;
++	u16 reg_data, reg_data2;
+ 
+ 	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
+-	ret_val = e1000e_write_kmrn_reg(hw,
+-				       E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
+-				       reg_data);
++	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
++					reg_data);
+ 	if (ret_val)
+ 		return ret_val;
+ 
+@@ -1068,9 +1134,16 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
+ 	tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
+ 	ew32(TIPG, tipg);
+ 
+-	ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
+-	if (ret_val)
+-		return ret_val;
++	do {
++		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
++		if (ret_val)
++			return ret_val;
++
++		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data2);
++		if (ret_val)
++			return ret_val;
++		i++;
++	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
+ 
+ 	if (duplex == HALF_DUPLEX)
+ 		reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
+@@ -1092,13 +1165,13 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
+ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
+ {
+ 	s32 ret_val;
+-	u16 reg_data;
++	u16 reg_data, reg_data2;
+ 	u32 tipg;
++	u32 i = 0;
+ 
+ 	reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
+-	ret_val = e1000e_write_kmrn_reg(hw,
+-				       E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
+-				       reg_data);
++	ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
++					reg_data);
+ 	if (ret_val)
+ 		return ret_val;
+ 
+@@ -1108,9 +1181,16 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
+ 	tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
+ 	ew32(TIPG, tipg);
+ 
+-	ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
+-	if (ret_val)
+-		return ret_val;
++	do {
++		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
++		if (ret_val)
++			return ret_val;
++
++		ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data2);
++		if (ret_val)
++			return ret_val;
++		i++;
++	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
+ 
+ 	reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+ 	ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+@@ -1175,7 +1255,7 @@ static struct e1000_mac_operations es2_mac_ops = {
+ 	.get_link_up_info	= e1000_get_link_up_info_80003es2lan,
+ 	.led_on			= e1000e_led_on_generic,
+ 	.led_off		= e1000e_led_off_generic,
+-	.mc_addr_list_update	= e1000e_mc_addr_list_update_generic,
++	.update_mc_addr_list	= e1000e_update_mc_addr_list_generic,
+ 	.reset_hw		= e1000_reset_hw_80003es2lan,
+ 	.init_hw		= e1000_init_hw_80003es2lan,
+ 	.setup_link		= e1000e_setup_link,
+@@ -1212,19 +1292,17 @@ struct e1000_info e1000_es2_info = {
+ 	.mac			= e1000_80003es2lan,
+ 	.flags			= FLAG_HAS_HW_VLAN_FILTER
+ 				  | FLAG_HAS_JUMBO_FRAMES
+-				  | FLAG_HAS_STATS_PTC_PRC
+ 				  | FLAG_HAS_WOL
+ 				  | FLAG_APME_IN_CTRL3
+ 				  | FLAG_RX_CSUM_ENABLED
+ 				  | FLAG_HAS_CTRLEXT_ON_LOAD
+-				  | FLAG_HAS_STATS_ICR_ICT
+ 				  | FLAG_RX_NEEDS_RESTART /* errata */
+ 				  | FLAG_TARC_SET_BIT_ZERO /* errata */
+ 				  | FLAG_APME_CHECK_PORT_B
+ 				  | FLAG_DISABLE_FC_PAUSE_TIME /* errata */
+ 				  | FLAG_TIPG_MEDIUM_FOR_80003ESLAN,
+ 	.pba			= 38,
+-	.get_invariants		= e1000_get_invariants_80003es2lan,
++	.get_variants		= e1000_get_variants_80003es2lan,
+ 	.mac_ops		= &es2_mac_ops,
+ 	.phy_ops		= &es2_phy_ops,
+ 	.nvm_ops		= &es2_nvm_ops,
+diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
+index f77a742..ce045ac 100644
+--- a/drivers/net/e1000e/ethtool.c
++++ b/drivers/net/e1000e/ethtool.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -46,8 +46,8 @@ struct e1000_stats {
+ static const struct e1000_stats e1000_gstrings_stats[] = {
+ 	{ "rx_packets", E1000_STAT(stats.gprc) },
+ 	{ "tx_packets", E1000_STAT(stats.gptc) },
+-	{ "rx_bytes", E1000_STAT(stats.gorcl) },
+-	{ "tx_bytes", E1000_STAT(stats.gotcl) },
++	{ "rx_bytes", E1000_STAT(stats.gorc) },
++	{ "tx_bytes", E1000_STAT(stats.gotc) },
+ 	{ "rx_broadcast", E1000_STAT(stats.bprc) },
+ 	{ "tx_broadcast", E1000_STAT(stats.bptc) },
+ 	{ "rx_multicast", E1000_STAT(stats.mprc) },
+@@ -83,7 +83,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
+ 	{ "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
+ 	{ "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
+ 	{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
+-	{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
++	{ "rx_long_byte_count", E1000_STAT(stats.gorc) },
+ 	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
+ 	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
+ 	{ "rx_header_split", E1000_STAT(rx_hdr_split) },
+@@ -102,7 +102,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
+ 	"Interrupt test (offline)", "Loopback test  (offline)",
+ 	"Link test   (on/offline)"
+ };
+-#define E1000_TEST_LEN	ARRAY_SIZE(e1000_gstrings_test)
++#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
+ 
+ static int e1000_get_settings(struct net_device *netdev,
+ 			      struct ethtool_cmd *ecmd)
+@@ -111,7 +111,7 @@ static int e1000_get_settings(struct net_device *netdev,
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 status;
+ 
+-	if (hw->media_type == e1000_media_type_copper) {
++	if (hw->phy.media_type == e1000_media_type_copper) {
+ 
+ 		ecmd->supported = (SUPPORTED_10baseT_Half |
+ 				   SUPPORTED_10baseT_Full |
+@@ -165,7 +165,7 @@ static int e1000_get_settings(struct net_device *netdev,
+ 		ecmd->duplex = -1;
+ 	}
+ 
+-	ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) ||
++	ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
+ 			 hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+ 	return 0;
+ }
+@@ -187,7 +187,7 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
+ 	mac->autoneg = 0;
+ 
+ 	/* Fiber NICs only allow 1000 gbps Full duplex */
+-	if ((adapter->hw.media_type == e1000_media_type_fiber) &&
++	if ((adapter->hw.phy.media_type == e1000_media_type_fiber) &&
+ 		spddplx != (SPEED_1000 + DUPLEX_FULL)) {
+ 		ndev_err(adapter->netdev, "Unsupported Speed/Duplex "
+ 			 "configuration\n");
+@@ -226,8 +226,10 @@ static int e1000_set_settings(struct net_device *netdev,
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	struct e1000_hw *hw = &adapter->hw;
+ 
+-	/* When SoL/IDER sessions are active, autoneg/speed/duplex
+-	 * cannot be changed */
++	/*
++	 * When SoL/IDER sessions are active, autoneg/speed/duplex
++	 * cannot be changed
++	 */
+ 	if (e1000_check_reset_block(hw)) {
+ 		ndev_err(netdev, "Cannot change link "
+ 			 "characteristics when SoL/IDER is active.\n");
+@@ -239,7 +241,7 @@ static int e1000_set_settings(struct net_device *netdev,
+ 
+ 	if (ecmd->autoneg == AUTONEG_ENABLE) {
+ 		hw->mac.autoneg = 1;
+-		if (hw->media_type == e1000_media_type_fiber)
++		if (hw->phy.media_type == e1000_media_type_fiber)
+ 			hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
+ 						     ADVERTISED_FIBRE |
+ 						     ADVERTISED_Autoneg;
+@@ -248,6 +250,8 @@ static int e1000_set_settings(struct net_device *netdev,
+ 						     ADVERTISED_TP |
+ 						     ADVERTISED_Autoneg;
+ 		ecmd->advertising = hw->phy.autoneg_advertised;
++		if (adapter->fc_autoneg)
++			hw->fc.original_type = e1000_fc_default;
+ 	} else {
+ 		if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {
+ 			clear_bit(__E1000_RESETTING, &adapter->state);
+@@ -277,11 +281,11 @@ static void e1000_get_pauseparam(struct net_device *netdev,
+ 	pause->autoneg =
+ 		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+ 
+-	if (hw->mac.fc == e1000_fc_rx_pause) {
++	if (hw->fc.type == e1000_fc_rx_pause) {
+ 		pause->rx_pause = 1;
+-	} else if (hw->mac.fc == e1000_fc_tx_pause) {
++	} else if (hw->fc.type == e1000_fc_tx_pause) {
+ 		pause->tx_pause = 1;
+-	} else if (hw->mac.fc == e1000_fc_full) {
++	} else if (hw->fc.type == e1000_fc_full) {
+ 		pause->rx_pause = 1;
+ 		pause->tx_pause = 1;
+ 	}
+@@ -300,18 +304,18 @@ static int e1000_set_pauseparam(struct net_device *netdev,
+ 		msleep(1);
+ 
+ 	if (pause->rx_pause && pause->tx_pause)
+-		hw->mac.fc = e1000_fc_full;
++		hw->fc.type = e1000_fc_full;
+ 	else if (pause->rx_pause && !pause->tx_pause)
+-		hw->mac.fc = e1000_fc_rx_pause;
++		hw->fc.type = e1000_fc_rx_pause;
+ 	else if (!pause->rx_pause && pause->tx_pause)
+-		hw->mac.fc = e1000_fc_tx_pause;
++		hw->fc.type = e1000_fc_tx_pause;
+ 	else if (!pause->rx_pause && !pause->tx_pause)
+-		hw->mac.fc = e1000_fc_none;
++		hw->fc.type = e1000_fc_none;
+ 
+-	hw->mac.original_fc = hw->mac.fc;
++	hw->fc.original_type = hw->fc.type;
+ 
+ 	if (adapter->fc_autoneg == AUTONEG_ENABLE) {
+-		hw->mac.fc = e1000_fc_default;
++		hw->fc.type = e1000_fc_default;
+ 		if (netif_running(adapter->netdev)) {
+ 			e1000e_down(adapter);
+ 			e1000e_up(adapter);
+@@ -319,7 +323,7 @@ static int e1000_set_pauseparam(struct net_device *netdev,
+ 			e1000e_reset(adapter);
+ 		}
+ 	} else {
+-		retval = ((hw->media_type == e1000_media_type_fiber) ?
++		retval = ((hw->phy.media_type == e1000_media_type_fiber) ?
+ 			  hw->mac.ops.setup_link(hw) : e1000e_force_mac_fc(hw));
+ 	}
+ 
+@@ -558,8 +562,10 @@ static int e1000_set_eeprom(struct net_device *netdev,
+ 	ret_val = e1000_write_nvm(hw, first_word,
+ 				  last_word - first_word + 1, eeprom_buff);
+ 
+-	/* Update the checksum over the first part of the EEPROM if needed
+-	 * and flush shadow RAM for 82573 controllers */
++	/*
++	 * Update the checksum over the first part of the EEPROM if needed
++	 * and flush shadow RAM for 82573 controllers
++	 */
+ 	if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG) ||
+ 			       (hw->mac.type == e1000_82573)))
+ 		e1000e_update_nvm_checksum(hw);
+@@ -578,8 +584,10 @@ static void e1000_get_drvinfo(struct net_device *netdev,
+ 	strncpy(drvinfo->driver,  e1000e_driver_name, 32);
+ 	strncpy(drvinfo->version, e1000e_driver_version, 32);
+ 
+-	/* EEPROM image version # is reported as firmware version # for
+-	 * PCI-E controllers */
++	/*
++	 * EEPROM image version # is reported as firmware version # for
++	 * PCI-E controllers
++	 */
+ 	e1000_read_nvm(&adapter->hw, 5, 1, &eeprom_data);
+ 	sprintf(firmware_version, "%d.%d-%d",
+ 		(eeprom_data & 0xF000) >> 12,
+@@ -633,10 +641,17 @@ static int e1000_set_ringparam(struct net_device *netdev,
+ 	tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ 	if (!tx_ring)
+ 		goto err_alloc_tx;
++	/*
++	 * use a memcpy to save any previously configured
++	 * items like napi structs from having to be
++	 * reinitialized
++	 */
++	memcpy(tx_ring, tx_old, sizeof(struct e1000_ring));
+ 
+ 	rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ 	if (!rx_ring)
+ 		goto err_alloc_rx;
++	memcpy(rx_ring, rx_old, sizeof(struct e1000_ring));
+ 
+ 	adapter->tx_ring = tx_ring;
+ 	adapter->rx_ring = rx_ring;
+@@ -658,8 +673,10 @@ static int e1000_set_ringparam(struct net_device *netdev,
+ 		if (err)
+ 			goto err_setup_tx;
+ 
+-		/* save the new, restore the old in order to free it,
+-		 * then restore the new back again */
++		/*
++		 * restore the old in order to free it,
++		 * then add in the new
++		 */
+ 		adapter->rx_ring = rx_old;
+ 		adapter->tx_ring = tx_old;
+ 		e1000e_free_rx_resources(adapter);
+@@ -690,61 +707,55 @@ err_setup:
+ 	return err;
+ }
+ 
+-static bool reg_pattern_test_array(struct e1000_adapter *adapter, u64 *data,
+-				   int reg, int offset, u32 mask, u32 write)
++static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
++			     int reg, int offset, u32 mask, u32 write)
+ {
+-	int i;
+-	u32 read;
++	u32 pat, val;
+ 	static const u32 test[] =
+ 		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
+-	for (i = 0; i < ARRAY_SIZE(test); i++) {
++	for (pat = 0; pat < ARRAY_SIZE(test); pat++) {
+ 		E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset,
+-				      (test[i] & write));
+-		read = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset);
+-		if (read != (test[i] & write & mask)) {
++				      (test[pat] & write));
++		val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset);
++		if (val != (test[pat] & write & mask)) {
+ 			ndev_err(adapter->netdev, "pattern test reg %04X "
+ 				 "failed: got 0x%08X expected 0x%08X\n",
+ 				 reg + offset,
+-				 read, (test[i] & write & mask));
++				 val, (test[pat] & write & mask));
+ 			*data = reg;
+-			return true;
++			return 1;
+ 		}
+ 	}
+-	return false;
++	return 0;
+ }
+ 
+ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
+ 			      int reg, u32 mask, u32 write)
+ {
+-	u32 read;
++	u32 val;
+ 	__ew32(&adapter->hw, reg, write & mask);
+-	read = __er32(&adapter->hw, reg);
+-	if ((write & mask) != (read & mask)) {
++	val = __er32(&adapter->hw, reg);
++	if ((write & mask) != (val & mask)) {
+ 		ndev_err(adapter->netdev, "set/check reg %04X test failed: "
+-			 "got 0x%08X expected 0x%08X\n", reg, (read & mask),
++			 "got 0x%08X expected 0x%08X\n", reg, (val & mask),
+ 			 (write & mask));
+ 		*data = reg;
+-		return true;
++		return 1;
+ 	}
+-	return false;
++	return 0;
+ }
+-
+-#define REG_PATTERN_TEST(R, M, W) \
+-	do { \
+-		if (reg_pattern_test_array(adapter, data, R, 0, M, W)) \
+-			return 1; \
+-	} while (0)
+-
+-#define REG_PATTERN_TEST_ARRAY(R, offset, M, W) \
+-	do { \
+-		if (reg_pattern_test_array(adapter, data, R, offset, M, W)) \
+-			return 1; \
++#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write)                       \
++	do {                                                                   \
++		if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \
++			return 1;                                              \
+ 	} while (0)
++#define REG_PATTERN_TEST(reg, mask, write)                                     \
++	REG_PATTERN_TEST_ARRAY(reg, 0, mask, write)
+ 
+-#define REG_SET_AND_CHECK(R, M, W) \
+-	do { \
+-		if (reg_set_and_check(adapter, data, R, M, W)) \
+-			return 1; \
++#define REG_SET_AND_CHECK(reg, mask, write)                                    \
++	do {                                                                   \
++		if (reg_set_and_check(adapter, data, reg, mask, write))        \
++			return 1;                                              \
+ 	} while (0)
+ 
+ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+@@ -758,7 +769,8 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+ 	u32 i;
+ 	u32 toggle;
+ 
+-	/* The status register is Read Only, so a write should fail.
++	/*
++	 * The status register is Read Only, so a write should fail.
+ 	 * Some bits that get toggled are ignored.
+ 	 */
+ 	switch (mac->type) {
+@@ -908,7 +920,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+ 		mask = 1 << i;
+ 
+ 		if (!shared_int) {
+-			/* Disable the interrupt to be reported in
++			/*
++			 * Disable the interrupt to be reported in
+ 			 * the cause register and then force the same
+ 			 * interrupt and see if one gets posted.  If
+ 			 * an interrupt was posted to the bus, the
+@@ -925,7 +938,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+ 			}
+ 		}
+ 
+-		/* Enable the interrupt to be reported in
++		/*
++		 * Enable the interrupt to be reported in
+ 		 * the cause register and then force the same
+ 		 * interrupt and see if one gets posted.  If
+ 		 * an interrupt was not posted to the bus, the
+@@ -942,7 +956,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+ 		}
+ 
+ 		if (!shared_int) {
+-			/* Disable the other interrupts to be reported in
++			/*
++			 * Disable the other interrupts to be reported in
+ 			 * the cause register and then force the other
+ 			 * interrupts and see if any get posted.  If
+ 			 * an interrupt was posted to the bus, the
+@@ -1024,7 +1039,6 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 	struct pci_dev *pdev = adapter->pdev;
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 rctl;
+-	int size;
+ 	int i;
+ 	int ret_val;
+ 
+@@ -1033,13 +1047,13 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 	if (!tx_ring->count)
+ 		tx_ring->count = E1000_DEFAULT_TXD;
+ 
+-	size = tx_ring->count * sizeof(struct e1000_buffer);
+-	tx_ring->buffer_info = kmalloc(size, GFP_KERNEL);
+-	if (!tx_ring->buffer_info) {
++	tx_ring->buffer_info = kcalloc(tx_ring->count,
++				       sizeof(struct e1000_buffer),
++				       GFP_KERNEL);
++	if (!(tx_ring->buffer_info)) {
+ 		ret_val = 1;
+ 		goto err_nomem;
+ 	}
+-	memset(tx_ring->buffer_info, 0, size);
+ 
+ 	tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);
+ 	tx_ring->size = ALIGN(tx_ring->size, 4096);
+@@ -1049,21 +1063,17 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 		ret_val = 2;
+ 		goto err_nomem;
+ 	}
+-	memset(tx_ring->desc, 0, tx_ring->size);
+ 	tx_ring->next_to_use = 0;
+ 	tx_ring->next_to_clean = 0;
+ 
+-	ew32(TDBAL,
+-			((u64) tx_ring->dma & 0x00000000FFFFFFFF));
++	ew32(TDBAL, ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
+ 	ew32(TDBAH, ((u64) tx_ring->dma >> 32));
+-	ew32(TDLEN,
+-			tx_ring->count * sizeof(struct e1000_tx_desc));
++	ew32(TDLEN, tx_ring->count * sizeof(struct e1000_tx_desc));
+ 	ew32(TDH, 0);
+ 	ew32(TDT, 0);
+-	ew32(TCTL,
+-			E1000_TCTL_PSP | E1000_TCTL_EN |
+-			E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
+-			E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
++	ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR |
++	     E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
++	     E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
+ 
+ 	for (i = 0; i < tx_ring->count; i++) {
+ 		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
+@@ -1085,12 +1095,11 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 			ret_val = 4;
+ 			goto err_nomem;
+ 		}
+-		tx_desc->buffer_addr = cpu_to_le64(
+-					 tx_ring->buffer_info[i].dma);
++		tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);
+ 		tx_desc->lower.data = cpu_to_le32(skb->len);
+ 		tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |
+ 						   E1000_TXD_CMD_IFCS |
+-						   E1000_TXD_CMD_RPS);
++						   E1000_TXD_CMD_RS);
+ 		tx_desc->upper.data = 0;
+ 	}
+ 
+@@ -1099,13 +1108,13 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 	if (!rx_ring->count)
+ 		rx_ring->count = E1000_DEFAULT_RXD;
+ 
+-	size = rx_ring->count * sizeof(struct e1000_buffer);
+-	rx_ring->buffer_info = kmalloc(size, GFP_KERNEL);
+-	if (!rx_ring->buffer_info) {
++	rx_ring->buffer_info = kcalloc(rx_ring->count,
++				       sizeof(struct e1000_buffer),
++				       GFP_KERNEL);
++	if (!(rx_ring->buffer_info)) {
+ 		ret_val = 5;
+ 		goto err_nomem;
+ 	}
+-	memset(rx_ring->buffer_info, 0, size);
+ 
+ 	rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc);
+ 	rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
+@@ -1114,7 +1123,6 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 		ret_val = 6;
+ 		goto err_nomem;
+ 	}
+-	memset(rx_ring->desc, 0, rx_ring->size);
+ 	rx_ring->next_to_use = 0;
+ 	rx_ring->next_to_clean = 0;
+ 
+@@ -1126,6 +1134,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ 	ew32(RDH, 0);
+ 	ew32(RDT, 0);
+ 	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
++		E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE |
++		E1000_RCTL_SBP | E1000_RCTL_SECRC |
+ 		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+ 		(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
+ 	ew32(RCTL, rctl);
+@@ -1175,21 +1185,22 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ 	u32 ctrl_reg = 0;
+ 	u32 stat_reg = 0;
+ 
+-	adapter->hw.mac.autoneg = 0;
++	hw->mac.autoneg = 0;
+ 
+-	if (adapter->hw.phy.type == e1000_phy_m88) {
++	if (hw->phy.type == e1000_phy_m88) {
+ 		/* Auto-MDI/MDIX Off */
+ 		e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
+ 		/* reset to update Auto-MDI/MDIX */
+ 		e1e_wphy(hw, PHY_CONTROL, 0x9140);
+ 		/* autoneg off */
+ 		e1e_wphy(hw, PHY_CONTROL, 0x8140);
+-	} else if (adapter->hw.phy.type == e1000_phy_gg82563)
++	} else if (hw->phy.type == e1000_phy_gg82563)
+ 		e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC);
+ 
+ 	ctrl_reg = er32(CTRL);
+ 
+-	if (adapter->hw.phy.type == e1000_phy_ife) {
++	switch (hw->phy.type) {
++	case e1000_phy_ife:
+ 		/* force 100, set loopback */
+ 		e1e_wphy(hw, PHY_CONTROL, 0x6100);
+ 
+@@ -1199,9 +1210,11 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ 			     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+ 			     E1000_CTRL_SPD_100 |/* Force Speed to 100 */
+ 			     E1000_CTRL_FD);	 /* Force Duplex to FULL */
+-	} else {
++		break;
++	default:
+ 		/* force 1000, set loopback */
+ 		e1e_wphy(hw, PHY_CONTROL, 0x4140);
++		mdelay(250);
+ 
+ 		/* Now set up the MAC to the same speed/duplex as the PHY. */
+ 		ctrl_reg = er32(CTRL);
+@@ -1210,14 +1223,20 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ 			     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+ 			     E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
+ 			     E1000_CTRL_FD);	 /* Force Duplex to FULL */
++
++		if ((adapter->hw.mac.type == e1000_ich8lan) ||
++		    (adapter->hw.mac.type == e1000_ich9lan))
++			ctrl_reg |= E1000_CTRL_SLU;	/* Set Link Up */
+ 	}
+ 
+-	if (adapter->hw.media_type == e1000_media_type_copper &&
+-	   adapter->hw.phy.type == e1000_phy_m88) {
++	if (hw->phy.media_type == e1000_media_type_copper &&
++	    hw->phy.type == e1000_phy_m88) {
+ 		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
+ 	} else {
+-		/* Set the ILOS bit on the fiber Nic if half duplex link is
+-		 * detected. */
++		/*
++		 * Set the ILOS bit on the fiber Nic if half duplex link is
++		 * detected.
++		 */
+ 		stat_reg = er32(STATUS);
+ 		if ((stat_reg & E1000_STATUS_FD) == 0)
+ 			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
+@@ -1225,10 +1244,11 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ 
+ 	ew32(CTRL, ctrl_reg);
+ 
+-	/* Disable the receiver on the PHY so when a cable is plugged in, the
++	/*
++	 * Disable the receiver on the PHY so when a cable is plugged in, the
+ 	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
+ 	 */
+-	if (adapter->hw.phy.type == e1000_phy_m88)
++	if (hw->phy.type == e1000_phy_m88)
+ 		e1000_phy_disable_receiver(adapter);
+ 
+ 	udelay(500);
+@@ -1244,8 +1264,10 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
+ 
+ 	/* special requirements for 82571/82572 fiber adapters */
+ 
+-	/* jump through hoops to make sure link is up because serdes
+-	 * link is hardwired up */
++	/*
++	 * jump through hoops to make sure link is up because serdes
++	 * link is hardwired up
++	 */
+ 	ctrl |= E1000_CTRL_SLU;
+ 	ew32(CTRL, ctrl);
+ 
+@@ -1263,8 +1285,10 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
+ 		ew32(CTRL, ctrl);
+ 	}
+ 
+-	/* special write to serdes control register to enable SerDes analog
+-	 * loopback */
++	/*
++	 * special write to serdes control register to enable SerDes analog
++	 * loopback
++	 */
+ #define E1000_SERDES_LB_ON 0x410
+ 	ew32(SCTL, E1000_SERDES_LB_ON);
+ 	msleep(10);
+@@ -1279,8 +1303,10 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
+ 	u32 ctrlext = er32(CTRL_EXT);
+ 	u32 ctrl = er32(CTRL);
+ 
+-	/* save CTRL_EXT to restore later, reuse an empty variable (unused
+-	   on mac_type 80003es2lan) */
++	/*
++	 * save CTRL_EXT to restore later, reuse an empty variable (unused
++	 * on mac_type 80003es2lan)
++	 */
+ 	adapter->tx_fifo_head = ctrlext;
+ 
+ 	/* clear the serdes mode bits, putting the device into mac loopback */
+@@ -1302,7 +1328,7 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
+ #define KMRNCTRLSTA_OPMODE (0x1F << 16)
+ #define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582
+ 	ew32(KMRNCTRLSTA,
+-		(KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII));
++	     (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII));
+ 
+ 	return 0;
+ }
+@@ -1312,8 +1338,8 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 rctl;
+ 
+-	if (hw->media_type == e1000_media_type_fiber ||
+-	    hw->media_type == e1000_media_type_internal_serdes) {
++	if (hw->phy.media_type == e1000_media_type_fiber ||
++	    hw->phy.media_type == e1000_media_type_internal_serdes) {
+ 		switch (hw->mac.type) {
+ 		case e1000_80003es2lan:
+ 			return e1000_set_es2lan_mac_loopback(adapter);
+@@ -1328,7 +1354,7 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
+ 			ew32(RCTL, rctl);
+ 			return 0;
+ 		}
+-	} else if (hw->media_type == e1000_media_type_copper) {
++	} else if (hw->phy.media_type == e1000_media_type_copper) {
+ 		return e1000_integrated_phy_loopback(adapter);
+ 	}
+ 
+@@ -1347,18 +1373,17 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
+ 
+ 	switch (hw->mac.type) {
+ 	case e1000_80003es2lan:
+-		if (hw->media_type == e1000_media_type_fiber ||
+-		    hw->media_type == e1000_media_type_internal_serdes) {
++		if (hw->phy.media_type == e1000_media_type_fiber ||
++		    hw->phy.media_type == e1000_media_type_internal_serdes) {
+ 			/* restore CTRL_EXT, stealing space from tx_fifo_head */
+-			ew32(CTRL_EXT,
+-					adapter->tx_fifo_head);
++			ew32(CTRL_EXT, adapter->tx_fifo_head);
+ 			adapter->tx_fifo_head = 0;
+ 		}
+ 		/* fall through */
+ 	case e1000_82571:
+ 	case e1000_82572:
+-		if (hw->media_type == e1000_media_type_fiber ||
+-		    hw->media_type == e1000_media_type_internal_serdes) {
++		if (hw->phy.media_type == e1000_media_type_fiber ||
++		    hw->phy.media_type == e1000_media_type_internal_serdes) {
+ #define E1000_SERDES_LB_OFF 0x400
+ 			ew32(SCTL, E1000_SERDES_LB_OFF);
+ 			msleep(10);
+@@ -1414,7 +1439,8 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+ 
+ 	ew32(RDT, rx_ring->count - 1);
+ 
+-	/* Calculate the loop count based on the largest descriptor ring
++	/*
++	 * Calculate the loop count based on the largest descriptor ring
+ 	 * The idea is to wrap the largest ring a number of times using 64
+ 	 * send/receive pairs during each loop
+ 	 */
+@@ -1428,8 +1454,8 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+ 	l = 0;
+ 	for (j = 0; j <= lc; j++) { /* loop count loop */
+ 		for (i = 0; i < 64; i++) { /* send the packets */
+-			e1000_create_lbtest_frame(
+-				tx_ring->buffer_info[i].skb, 1024);
++			e1000_create_lbtest_frame(tx_ring->buffer_info[k].skb,
++						  1024);
+ 			pci_dma_sync_single_for_device(pdev,
+ 					tx_ring->buffer_info[k].dma,
+ 					tx_ring->buffer_info[k].length,
+@@ -1454,7 +1480,8 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+ 			l++;
+ 			if (l == rx_ring->count)
+ 				l = 0;
+-			/* time + 20 msecs (200 msecs on 2.4) is more than
++			/*
++			 * 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
+ 			 */
+@@ -1463,7 +1490,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+ 			ret_val = 13; /* ret_val is the same as mis-compare */
+ 			break;
+ 		}
+-		if (jiffies >= (time + 2)) {
++		if (jiffies >= (time + 20)) {
+ 			ret_val = 14; /* error code for time out error */
+ 			break;
+ 		}
+@@ -1473,8 +1500,10 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+ 
+ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
+ {
+-	/* PHY loopback cannot be performed if SoL/IDER
+-	 * sessions are active */
++	/*
++	 * PHY loopback cannot be performed if SoL/IDER
++	 * sessions are active
++	 */
+ 	if (e1000_check_reset_block(&adapter->hw)) {
+ 		ndev_err(adapter->netdev, "Cannot do PHY loopback test "
+ 			 "when SoL/IDER is active.\n");
+@@ -1504,12 +1533,14 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
+ 	struct e1000_hw *hw = &adapter->hw;
+ 
+ 	*data = 0;
+-	if (hw->media_type == e1000_media_type_internal_serdes) {
++	if (hw->phy.media_type == e1000_media_type_internal_serdes) {
+ 		int i = 0;
+ 		hw->mac.serdes_has_link = 0;
+ 
+-		/* On some blade server designs, link establishment
+-		 * could take as long as 2-3 minutes */
++		/*
++		 * On some blade server designs, link establishment
++		 * could take as long as 2-3 minutes
++		 */
+ 		do {
+ 			hw->mac.ops.check_for_link(hw);
+ 			if (hw->mac.serdes_has_link)
+@@ -1562,8 +1593,10 @@ static void e1000_diag_test(struct net_device *netdev,
+ 
+ 		ndev_info(netdev, "offline testing starting\n");
+ 
+-		/* Link test performed before hardware reset so autoneg doesn't
+-		 * interfere with test result */
++		/*
++		 * 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;
+ 
+@@ -1596,9 +1629,9 @@ static void e1000_diag_test(struct net_device *netdev,
+ 		adapter->hw.mac.autoneg = autoneg;
+ 
+ 		/* force this routine to wait until autoneg complete/timeout */
+-		adapter->hw.phy.wait_for_link = 1;
++		adapter->hw.phy.autoneg_wait_to_complete = 1;
+ 		e1000e_reset(adapter);
+-		adapter->hw.phy.wait_for_link = 0;
++		adapter->hw.phy.autoneg_wait_to_complete = 0;
+ 
+ 		clear_bit(__E1000_TESTING, &adapter->state);
+ 		if (if_running)
+@@ -1737,6 +1770,47 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
+ 	return 0;
+ }
+ 
++static int e1000_get_coalesce(struct net_device *netdev,
++			      struct ethtool_coalesce *ec)
++{
++	struct e1000_adapter *adapter = netdev_priv(netdev);
++
++	if (adapter->itr_setting <= 3)
++		ec->rx_coalesce_usecs = adapter->itr_setting;
++	else
++		ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
++
++	return 0;
++}
++
++static int e1000_set_coalesce(struct net_device *netdev,
++			      struct ethtool_coalesce *ec)
++{
++	struct e1000_adapter *adapter = netdev_priv(netdev);
++	struct e1000_hw *hw = &adapter->hw;
++
++	if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
++	    ((ec->rx_coalesce_usecs > 3) &&
++	     (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
++	    (ec->rx_coalesce_usecs == 2))
++		return -EINVAL;
++
++	if (ec->rx_coalesce_usecs <= 3) {
++		adapter->itr = 20000;
++		adapter->itr_setting = ec->rx_coalesce_usecs;
++	} else {
++		adapter->itr = (1000000 / ec->rx_coalesce_usecs);
++		adapter->itr_setting = adapter->itr & ~3;
++	}
++
++	if (adapter->itr_setting != 0)
++		ew32(ITR, 1000000000 / (adapter->itr * 256));
++	else
++		ew32(ITR, 0);
++
++	return 0;
++}
++
+ static int e1000_nway_reset(struct net_device *netdev)
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -1768,8 +1842,7 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
+ 
+ 	switch (stringset) {
+ 	case ETH_SS_TEST:
+-		memcpy(data, *e1000_gstrings_test,
+-			sizeof(e1000_gstrings_test));
++		memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test));
+ 		break;
+ 	case ETH_SS_STATS:
+ 		for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+@@ -1813,6 +1886,8 @@ static const struct ethtool_ops e1000_ethtool_ops = {
+ 	.phys_id		= e1000_phys_id,
+ 	.get_ethtool_stats	= e1000_get_ethtool_stats,
+ 	.get_sset_count		= e1000e_get_sset_count,
++	.get_coalesce		= e1000_get_coalesce,
++	.set_coalesce		= e1000_set_coalesce,
+ };
+ 
+ void e1000e_set_ethtool_ops(struct net_device *netdev)
+diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
+index 916025b..a930e6d 100644
+--- a/drivers/net/e1000e/hw.h
++++ b/drivers/net/e1000e/hw.h
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -66,14 +66,14 @@ enum e1e_registers {
+ 	E1000_IMS      = 0x000D0, /* Interrupt Mask Set - RW */
+ 	E1000_IMC      = 0x000D8, /* Interrupt Mask Clear - WO */
+ 	E1000_IAM      = 0x000E0, /* Interrupt Acknowledge Auto Mask */
+-	E1000_RCTL     = 0x00100, /* RX Control - RW */
++	E1000_RCTL     = 0x00100, /* Rx Control - RW */
+ 	E1000_FCTTV    = 0x00170, /* Flow Control Transmit Timer Value - RW */
+-	E1000_TXCW     = 0x00178, /* TX Configuration Word - RW */
+-	E1000_RXCW     = 0x00180, /* RX Configuration Word - RO */
+-	E1000_TCTL     = 0x00400, /* TX Control - RW */
+-	E1000_TCTL_EXT = 0x00404, /* Extended TX Control - RW */
+-	E1000_TIPG     = 0x00410, /* TX Inter-packet gap -RW */
+-	E1000_AIT      = 0x00458, /* Adaptive Interframe Spacing Throttle - RW */
++	E1000_TXCW     = 0x00178, /* Tx Configuration Word - RW */
++	E1000_RXCW     = 0x00180, /* Rx Configuration Word - RO */
++	E1000_TCTL     = 0x00400, /* Tx Control - RW */
++	E1000_TCTL_EXT = 0x00404, /* Extended Tx Control - RW */
++	E1000_TIPG     = 0x00410, /* Tx Inter-packet gap -RW */
++	E1000_AIT      = 0x00458, /* Adaptive Interframe Spacing Throttle -RW */
+ 	E1000_LEDCTL   = 0x00E00, /* LED Control - RW */
+ 	E1000_EXTCNF_CTRL  = 0x00F00, /* Extended Configuration Control */
+ 	E1000_EXTCNF_SIZE  = 0x00F08, /* Extended Configuration Size */
+@@ -87,12 +87,14 @@ enum e1e_registers {
+ 	E1000_FCRTL    = 0x02160, /* Flow Control Receive Threshold Low - RW */
+ 	E1000_FCRTH    = 0x02168, /* Flow Control Receive Threshold High - RW */
+ 	E1000_PSRCTL   = 0x02170, /* Packet Split Receive Control - RW */
+-	E1000_RDBAL    = 0x02800, /* RX Descriptor Base Address Low - RW */
+-	E1000_RDBAH    = 0x02804, /* RX Descriptor Base Address High - RW */
+-	E1000_RDLEN    = 0x02808, /* RX Descriptor Length - RW */
+-	E1000_RDH      = 0x02810, /* RX Descriptor Head - RW */
+-	E1000_RDT      = 0x02818, /* RX Descriptor Tail - RW */
+-	E1000_RDTR     = 0x02820, /* RX Delay Timer - RW */
++	E1000_RDBAL    = 0x02800, /* Rx Descriptor Base Address Low - RW */
++	E1000_RDBAH    = 0x02804, /* Rx Descriptor Base Address High - RW */
++	E1000_RDLEN    = 0x02808, /* Rx Descriptor Length - RW */
++	E1000_RDH      = 0x02810, /* Rx Descriptor Head - RW */
++	E1000_RDT      = 0x02818, /* Rx Descriptor Tail - RW */
++	E1000_RDTR     = 0x02820, /* Rx Delay Timer - RW */
++	E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */
++#define E1000_RXDCTL(_n)   (E1000_RXDCTL_BASE + (_n << 8))
+ 	E1000_RADV     = 0x0282C, /* RX Interrupt Absolute Delay Timer - RW */
+ 
+ /* Convenience macros
+@@ -105,17 +107,17 @@ enum e1e_registers {
+  */
+ #define E1000_RDBAL_REG(_n)   (E1000_RDBAL + (_n << 8))
+ 	E1000_KABGTXD  = 0x03004, /* AFE Band Gap Transmit Ref Data */
+-	E1000_TDBAL    = 0x03800, /* TX Descriptor Base Address Low - RW */
+-	E1000_TDBAH    = 0x03804, /* TX Descriptor Base Address High - RW */
+-	E1000_TDLEN    = 0x03808, /* TX Descriptor Length - RW */
+-	E1000_TDH      = 0x03810, /* TX Descriptor Head - RW */
+-	E1000_TDT      = 0x03818, /* TX Descriptor Tail - RW */
+-	E1000_TIDV     = 0x03820, /* TX Interrupt Delay Value - RW */
+-	E1000_TXDCTL   = 0x03828, /* TX Descriptor Control - RW */
+-	E1000_TADV     = 0x0382C, /* TX Interrupt Absolute Delay Val - RW */
+-	E1000_TARC0    = 0x03840, /* TX Arbitration Count (0) */
+-	E1000_TXDCTL1  = 0x03928, /* TX Descriptor Control (1) - RW */
+-	E1000_TARC1    = 0x03940, /* TX Arbitration Count (1) */
++	E1000_TDBAL    = 0x03800, /* Tx Descriptor Base Address Low - RW */
++	E1000_TDBAH    = 0x03804, /* Tx Descriptor Base Address High - RW */
++	E1000_TDLEN    = 0x03808, /* Tx Descriptor Length - RW */
++	E1000_TDH      = 0x03810, /* Tx Descriptor Head - RW */
++	E1000_TDT      = 0x03818, /* Tx Descriptor Tail - RW */
++	E1000_TIDV     = 0x03820, /* Tx Interrupt Delay Value - RW */
++	E1000_TXDCTL_BASE = 0x03828, /* Tx Descriptor Control - RW */
++#define E1000_TXDCTL(_n)   (E1000_TXDCTL_BASE + (_n << 8))
++	E1000_TADV     = 0x0382C, /* Tx Interrupt Absolute Delay Val - RW */
++	E1000_TARC_BASE = 0x03840, /* Tx Arbitration Count (0) */
++#define E1000_TARC(_n)   (E1000_TARC_BASE + (_n << 8))
+ 	E1000_CRCERRS  = 0x04000, /* CRC Error Count - R/clr */
+ 	E1000_ALGNERRC = 0x04004, /* Alignment Error Count - R/clr */
+ 	E1000_SYMERRS  = 0x04008, /* Symbol Error Count - R/clr */
+@@ -127,53 +129,53 @@ enum e1e_registers {
+ 	E1000_LATECOL  = 0x04020, /* Late Collision Count - R/clr */
+ 	E1000_COLC     = 0x04028, /* Collision Count - R/clr */
+ 	E1000_DC       = 0x04030, /* Defer Count - R/clr */
+-	E1000_TNCRS    = 0x04034, /* TX-No CRS - R/clr */
++	E1000_TNCRS    = 0x04034, /* Tx-No CRS - R/clr */
+ 	E1000_SEC      = 0x04038, /* Sequence Error Count - R/clr */
+ 	E1000_CEXTERR  = 0x0403C, /* Carrier Extension Error Count - R/clr */
+ 	E1000_RLEC     = 0x04040, /* Receive Length Error Count - R/clr */
+-	E1000_XONRXC   = 0x04048, /* XON RX Count - R/clr */
+-	E1000_XONTXC   = 0x0404C, /* XON TX Count - R/clr */
+-	E1000_XOFFRXC  = 0x04050, /* XOFF RX Count - R/clr */
+-	E1000_XOFFTXC  = 0x04054, /* XOFF TX Count - R/clr */
+-	E1000_FCRUC    = 0x04058, /* Flow Control RX Unsupported Count- R/clr */
+-	E1000_PRC64    = 0x0405C, /* Packets RX (64 bytes) - R/clr */
+-	E1000_PRC127   = 0x04060, /* Packets RX (65-127 bytes) - R/clr */
+-	E1000_PRC255   = 0x04064, /* Packets RX (128-255 bytes) - R/clr */
+-	E1000_PRC511   = 0x04068, /* Packets RX (255-511 bytes) - R/clr */
+-	E1000_PRC1023  = 0x0406C, /* Packets RX (512-1023 bytes) - R/clr */
+-	E1000_PRC1522  = 0x04070, /* Packets RX (1024-1522 bytes) - R/clr */
+-	E1000_GPRC     = 0x04074, /* Good Packets RX Count - R/clr */
+-	E1000_BPRC     = 0x04078, /* Broadcast Packets RX Count - R/clr */
+-	E1000_MPRC     = 0x0407C, /* Multicast Packets RX Count - R/clr */
+-	E1000_GPTC     = 0x04080, /* Good Packets TX Count - R/clr */
+-	E1000_GORCL    = 0x04088, /* Good Octets RX Count Low - R/clr */
+-	E1000_GORCH    = 0x0408C, /* Good Octets RX Count High - R/clr */
+-	E1000_GOTCL    = 0x04090, /* Good Octets TX Count Low - R/clr */
+-	E1000_GOTCH    = 0x04094, /* Good Octets TX Count High - R/clr */
+-	E1000_RNBC     = 0x040A0, /* RX No Buffers Count - R/clr */
+-	E1000_RUC      = 0x040A4, /* RX Undersize Count - R/clr */
+-	E1000_RFC      = 0x040A8, /* RX Fragment Count - R/clr */
+-	E1000_ROC      = 0x040AC, /* RX Oversize Count - R/clr */
+-	E1000_RJC      = 0x040B0, /* RX Jabber Count - R/clr */
+-	E1000_MGTPRC   = 0x040B4, /* Management Packets RX Count - R/clr */
++	E1000_XONRXC   = 0x04048, /* XON Rx Count - R/clr */
++	E1000_XONTXC   = 0x0404C, /* XON Tx Count - R/clr */
++	E1000_XOFFRXC  = 0x04050, /* XOFF Rx Count - R/clr */
++	E1000_XOFFTXC  = 0x04054, /* XOFF Tx Count - R/clr */
++	E1000_FCRUC    = 0x04058, /* Flow Control Rx Unsupported Count- R/clr */
++	E1000_PRC64    = 0x0405C, /* Packets Rx (64 bytes) - R/clr */
++	E1000_PRC127   = 0x04060, /* Packets Rx (65-127 bytes) - R/clr */
++	E1000_PRC255   = 0x04064, /* Packets Rx (128-255 bytes) - R/clr */
++	E1000_PRC511   = 0x04068, /* Packets Rx (255-511 bytes) - R/clr */
++	E1000_PRC1023  = 0x0406C, /* Packets Rx (512-1023 bytes) - R/clr */
++	E1000_PRC1522  = 0x04070, /* Packets Rx (1024-1522 bytes) - R/clr */
++	E1000_GPRC     = 0x04074, /* Good Packets Rx Count - R/clr */
++	E1000_BPRC     = 0x04078, /* Broadcast Packets Rx Count - R/clr */
++	E1000_MPRC     = 0x0407C, /* Multicast Packets Rx Count - R/clr */
++	E1000_GPTC     = 0x04080, /* Good Packets Tx Count - R/clr */
++	E1000_GORCL    = 0x04088, /* Good Octets Rx Count Low - R/clr */
++	E1000_GORCH    = 0x0408C, /* Good Octets Rx Count High - R/clr */
++	E1000_GOTCL    = 0x04090, /* Good Octets Tx Count Low - R/clr */
++	E1000_GOTCH    = 0x04094, /* Good Octets Tx Count High - R/clr */
++	E1000_RNBC     = 0x040A0, /* Rx No Buffers Count - R/clr */
++	E1000_RUC      = 0x040A4, /* Rx Undersize Count - R/clr */
++	E1000_RFC      = 0x040A8, /* Rx Fragment Count - R/clr */
++	E1000_ROC      = 0x040AC, /* Rx Oversize Count - R/clr */
++	E1000_RJC      = 0x040B0, /* Rx Jabber Count - R/clr */
++	E1000_MGTPRC   = 0x040B4, /* Management Packets Rx Count - R/clr */
+ 	E1000_MGTPDC   = 0x040B8, /* Management Packets Dropped Count - R/clr */
+-	E1000_MGTPTC   = 0x040BC, /* Management Packets TX Count - R/clr */
+-	E1000_TORL     = 0x040C0, /* Total Octets RX Low - R/clr */
+-	E1000_TORH     = 0x040C4, /* Total Octets RX High - R/clr */
+-	E1000_TOTL     = 0x040C8, /* Total Octets TX Low - R/clr */
+-	E1000_TOTH     = 0x040CC, /* Total Octets TX High - R/clr */
+-	E1000_TPR      = 0x040D0, /* Total Packets RX - R/clr */
+-	E1000_TPT      = 0x040D4, /* Total Packets TX - R/clr */
+-	E1000_PTC64    = 0x040D8, /* Packets TX (64 bytes) - R/clr */
+-	E1000_PTC127   = 0x040DC, /* Packets TX (65-127 bytes) - R/clr */
+-	E1000_PTC255   = 0x040E0, /* Packets TX (128-255 bytes) - R/clr */
+-	E1000_PTC511   = 0x040E4, /* Packets TX (256-511 bytes) - R/clr */
+-	E1000_PTC1023  = 0x040E8, /* Packets TX (512-1023 bytes) - R/clr */
+-	E1000_PTC1522  = 0x040EC, /* Packets TX (1024-1522 Bytes) - R/clr */
+-	E1000_MPTC     = 0x040F0, /* Multicast Packets TX Count - R/clr */
+-	E1000_BPTC     = 0x040F4, /* Broadcast Packets TX Count - R/clr */
+-	E1000_TSCTC    = 0x040F8, /* TCP Segmentation Context TX - R/clr */
+-	E1000_TSCTFC   = 0x040FC, /* TCP Segmentation Context TX Fail - R/clr */
++	E1000_MGTPTC   = 0x040BC, /* Management Packets Tx Count - R/clr */
++	E1000_TORL     = 0x040C0, /* Total Octets Rx Low - R/clr */
++	E1000_TORH     = 0x040C4, /* Total Octets Rx High - R/clr */
++	E1000_TOTL     = 0x040C8, /* Total Octets Tx Low - R/clr */
++	E1000_TOTH     = 0x040CC, /* Total Octets Tx High - R/clr */
++	E1000_TPR      = 0x040D0, /* Total Packets Rx - R/clr */
++	E1000_TPT      = 0x040D4, /* Total Packets Tx - R/clr */
++	E1000_PTC64    = 0x040D8, /* Packets Tx (64 bytes) - R/clr */
++	E1000_PTC127   = 0x040DC, /* Packets Tx (65-127 bytes) - R/clr */
++	E1000_PTC255   = 0x040E0, /* Packets Tx (128-255 bytes) - R/clr */
++	E1000_PTC511   = 0x040E4, /* Packets Tx (256-511 bytes) - R/clr */
++	E1000_PTC1023  = 0x040E8, /* Packets Tx (512-1023 bytes) - R/clr */
++	E1000_PTC1522  = 0x040EC, /* Packets Tx (1024-1522 Bytes) - R/clr */
++	E1000_MPTC     = 0x040F0, /* Multicast Packets Tx Count - R/clr */
++	E1000_BPTC     = 0x040F4, /* Broadcast Packets Tx Count - R/clr */
++	E1000_TSCTC    = 0x040F8, /* TCP Segmentation Context Tx - R/clr */
++	E1000_TSCTFC   = 0x040FC, /* TCP Segmentation Context Tx Fail - R/clr */
+ 	E1000_IAC      = 0x04100, /* Interrupt Assertion Count */
+ 	E1000_ICRXPTC  = 0x04104, /* Irq Cause Rx Packet Timer Expire Count */
+ 	E1000_ICRXATC  = 0x04108, /* Irq Cause Rx Abs Timer Expire Count */
+@@ -183,7 +185,7 @@ enum e1e_registers {
+ 	E1000_ICTXQMTC = 0x0411C, /* Irq Cause Tx Queue MinThreshold Count */
+ 	E1000_ICRXDMTC = 0x04120, /* Irq Cause Rx Desc MinThreshold Count */
+ 	E1000_ICRXOC   = 0x04124, /* Irq Cause Receiver Overrun Count */
+-	E1000_RXCSUM   = 0x05000, /* RX Checksum Control - RW */
++	E1000_RXCSUM   = 0x05000, /* Rx Checksum Control - RW */
+ 	E1000_RFCTL    = 0x05008, /* Receive Filter Control */
+ 	E1000_MTA      = 0x05200, /* Multicast Table Array - RW Array */
+ 	E1000_RA       = 0x05400, /* Receive Address - RW Array */
+@@ -250,8 +252,8 @@ enum e1e_registers {
+ #define E1000_VFTA_ENTRY_BIT_SHIFT_MASK	0x1F
+ 
+ #define E1000_HICR_EN			0x01  /* Enable bit - RO */
+-#define E1000_HICR_C			0x02  /* Driver sets this bit when done
+-					       * to put command in RAM */
++/* Driver sets this bit when done to put command in RAM */
++#define E1000_HICR_C			0x02
+ #define E1000_HICR_FW_RESET_ENABLE	0x40
+ #define E1000_HICR_FW_RESET		0x80
+ 
+@@ -400,7 +402,7 @@ enum e1000_rev_polarity{
+ 	e1000_rev_polarity_undefined = 0xFF
+ };
+ 
+-enum e1000_fc_mode {
++enum e1000_fc_type {
+ 	e1000_fc_none = 0,
+ 	e1000_fc_rx_pause,
+ 	e1000_fc_tx_pause,
+@@ -590,10 +592,8 @@ struct e1000_hw_stats {
+ 	u64 bprc;
+ 	u64 mprc;
+ 	u64 gptc;
+-	u64 gorcl;
+-	u64 gorch;
+-	u64 gotcl;
+-	u64 gotch;
++	u64 gorc;
++	u64 gotc;
+ 	u64 rnbc;
+ 	u64 ruc;
+ 	u64 rfc;
+@@ -602,10 +602,8 @@ struct e1000_hw_stats {
+ 	u64 mgprc;
+ 	u64 mgpdc;
+ 	u64 mgptc;
+-	u64 torl;
+-	u64 torh;
+-	u64 totl;
+-	u64 toth;
++	u64 tor;
++	u64 tot;
+ 	u64 tpr;
+ 	u64 tpt;
+ 	u64 ptc64;
+@@ -685,8 +683,7 @@ struct e1000_mac_operations {
+ 	s32  (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+ 	s32  (*led_on)(struct e1000_hw *);
+ 	s32  (*led_off)(struct e1000_hw *);
+-	void (*mc_addr_list_update)(struct e1000_hw *, u8 *, u32, u32,
+-					 u32);
++	void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32);
+ 	s32  (*reset_hw)(struct e1000_hw *);
+ 	s32  (*init_hw)(struct e1000_hw *);
+ 	s32  (*setup_link)(struct e1000_hw *);
+@@ -728,16 +725,12 @@ struct e1000_mac_info {
+ 	u8 perm_addr[6];
+ 
+ 	enum e1000_mac_type type;
+-	enum e1000_fc_mode  fc;
+-	enum e1000_fc_mode  original_fc;
+ 
+ 	u32 collision_delta;
+ 	u32 ledctl_default;
+ 	u32 ledctl_mode1;
+ 	u32 ledctl_mode2;
+-	u32 max_frame_size;
+ 	u32 mc_filter_type;
+-	u32 min_frame_size;
+ 	u32 tx_packet_delta;
+ 	u32 txcw;
+ 
+@@ -748,9 +741,6 @@ struct e1000_mac_info {
+ 	u16 ifs_step_size;
+ 	u16 mta_reg_count;
+ 	u16 rar_entry_count;
+-	u16 fc_high_water;
+-	u16 fc_low_water;
+-	u16 fc_pause_time;
+ 
+ 	u8  forced_speed_duplex;
+ 
+@@ -780,6 +770,8 @@ struct e1000_phy_info {
+ 	u32 reset_delay_us; /* in usec */
+ 	u32 revision;
+ 
++	enum e1000_media_type media_type;
++
+ 	u16 autoneg_advertised;
+ 	u16 autoneg_mask;
+ 	u16 cable_length;
+@@ -792,7 +784,7 @@ struct e1000_phy_info {
+ 	bool is_mdix;
+ 	bool polarity_correction;
+ 	bool speed_downgraded;
+-	bool wait_for_link;
++	bool autoneg_wait_to_complete;
+ };
+ 
+ struct e1000_nvm_info {
+@@ -817,6 +809,16 @@ struct e1000_bus_info {
+ 	u16 func;
+ };
+ 
++struct e1000_fc_info {
++	u32 high_water;          /* Flow control high-water mark */
++	u32 low_water;           /* Flow control low-water mark */
++	u16 pause_time;          /* Flow control pause timer */
++	bool send_xon;           /* Flow control send XON */
++	bool strict_ieee;        /* Strict IEEE mode */
++	enum e1000_fc_type type; /* Type of flow control */
++	enum e1000_fc_type original_type;
++};
++
+ struct e1000_dev_spec_82571 {
+ 	bool laa_is_present;
+ 	bool alt_mac_addr_is_present;
+@@ -841,6 +843,7 @@ struct e1000_hw {
+ 	u8 __iomem *flash_address;
+ 
+ 	struct e1000_mac_info  mac;
++	struct e1000_fc_info   fc;
+ 	struct e1000_phy_info  phy;
+ 	struct e1000_nvm_info  nvm;
+ 	struct e1000_bus_info  bus;
+@@ -850,8 +853,6 @@ struct e1000_hw {
+ 		struct e1000_dev_spec_82571	e82571;
+ 		struct e1000_dev_spec_ich8lan	ich8lan;
+ 	} dev_spec;
+-
+-	enum e1000_media_type media_type;
+ };
+ 
+ #ifdef DEBUG
+diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
+index 0ae3955..768485d 100644
+--- a/drivers/net/e1000e/ich8lan.c
++++ b/drivers/net/e1000e/ich8lan.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -243,8 +243,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
+ 	u32 sector_end_addr;
+ 	u16 i;
+ 
+-	/* Can't read flash registers if the register set isn't mapped.
+-	 */
++	/* Can't read flash registers if the register set isn't mapped. */
+ 	if (!hw->flash_address) {
+ 		hw_dbg(hw, "ERROR: Flash registers not mapped\n");
+ 		return -E1000_ERR_CONFIG;
+@@ -254,17 +253,21 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
+ 
+ 	gfpreg = er32flash(ICH_FLASH_GFPREG);
+ 
+-	/* sector_X_addr is a "sector"-aligned address (4096 bytes)
++	/*
++	 * sector_X_addr is a "sector"-aligned address (4096 bytes)
+ 	 * Add 1 to sector_end_addr since this sector is included in
+-	 * the overall size. */
++	 * the overall size.
++	 */
+ 	sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
+ 	sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
+ 
+ 	/* flash_base_addr is byte-aligned */
+ 	nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
+ 
+-	/* find total size of the NVM, then cut in half since the total
+-	 * size represents two separate NVM banks. */
++	/*
++	 * find total size of the NVM, then cut in half since the total
++	 * size represents two separate NVM banks.
++	 */
+ 	nvm->flash_bank_size = (sector_end_addr - sector_base_addr)
+ 				<< FLASH_SECTOR_ADDR_SHIFT;
+ 	nvm->flash_bank_size /= 2;
+@@ -295,7 +298,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
+ 	struct e1000_mac_info *mac = &hw->mac;
+ 
+ 	/* Set media type function pointer */
+-	hw->media_type = e1000_media_type_copper;
++	hw->phy.media_type = e1000_media_type_copper;
+ 
+ 	/* Set mta register count */
+ 	mac->mta_reg_count = 32;
+@@ -313,7 +316,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
+ 	return 0;
+ }
+ 
+-static s32 e1000_get_invariants_ich8lan(struct e1000_adapter *adapter)
++static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	s32 rc;
+@@ -450,7 +453,7 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
+ 
+ 	udelay(1);
+ 
+-	if (phy->wait_for_link) {
++	if (phy->autoneg_wait_to_complete) {
+ 		hw_dbg(hw, "Waiting for forced speed/duplex link on IFE phy.\n");
+ 
+ 		ret_val = e1000e_phy_has_link_generic(hw,
+@@ -496,7 +499,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* Initialize the PHY from the NVM on ICH platforms.  This
++	/*
++	 * Initialize the PHY from the NVM on ICH platforms.  This
+ 	 * is needed due to an issue where the NVM configuration is
+ 	 * not properly autoloaded after power transitions.
+ 	 * Therefore, after each PHY reset, we will load the
+@@ -523,7 +527,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+ 			udelay(100);
+ 		} while ((!data) && --loop);
+ 
+-		/* If basic configuration is incomplete before the above loop
++		/*
++		 * If basic configuration is incomplete before the above loop
+ 		 * count reaches 0, loading the configuration from NVM will
+ 		 * leave the PHY in a bad state possibly resulting in no link.
+ 		 */
+@@ -536,8 +541,10 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+ 		data &= ~E1000_STATUS_LAN_INIT_DONE;
+ 		ew32(STATUS, data);
+ 
+-		/* Make sure HW does not configure LCD from PHY
+-		 * extended configuration before SW configuration */
++		/*
++		 * Make sure HW does not configure LCD from PHY
++		 * extended configuration before SW configuration
++		 */
+ 		data = er32(EXTCNF_CTRL);
+ 		if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+ 			return 0;
+@@ -551,8 +558,7 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+ 		cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
+ 		cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
+ 
+-		/* Configure LCD from extended configuration
+-		 * region. */
++		/* Configure LCD from extended configuration region. */
+ 
+ 		/* cnf_base_addr is in DWORD */
+ 		word_addr = (u16)(cnf_base_addr << 1);
+@@ -681,8 +687,8 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw)
+ 	s32 ret_val;
+ 	u16 phy_data, offset, mask;
+ 
+-	/* Polarity is determined based on the reversal feature
+-	 * being enabled.
++	/*
++	 * Polarity is determined based on the reversal feature being enabled.
+ 	 */
+ 	if (phy->polarity_correction) {
+ 		offset	= IFE_PHY_EXTENDED_STATUS_CONTROL;
+@@ -731,8 +737,10 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
+ 		phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
+ 		ew32(PHY_CTRL, phy_ctrl);
+ 
+-		/* Call gig speed drop workaround on LPLU before accessing
+-		 * any PHY registers */
++		/*
++		 * Call gig speed drop workaround on LPLU before accessing
++		 * any PHY registers
++		 */
+ 		if ((hw->mac.type == e1000_ich8lan) &&
+ 		    (hw->phy.type == e1000_phy_igp_3))
+ 			e1000e_gig_downshift_workaround_ich8lan(hw);
+@@ -747,30 +755,32 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
+ 		phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
+ 		ew32(PHY_CTRL, phy_ctrl);
+ 
+-		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
++		/*
++		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+ 		 * during Dx states where the power conservation is most
+ 		 * important.  During driver activity we should enable
+-		 * SmartSpeed, so performance is maintained. */
++		 * SmartSpeed, so performance is maintained.
++		 */
+ 		if (phy->smart_speed == e1000_smart_speed_on) {
+ 			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						    &data);
++					   &data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+ 			data |= IGP01E1000_PSCFR_SMART_SPEED;
+ 			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     data);
++					   data);
+ 			if (ret_val)
+ 				return ret_val;
+ 		} else if (phy->smart_speed == e1000_smart_speed_off) {
+ 			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						    &data);
++					   &data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+ 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ 			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     data);
++					   data);
+ 			if (ret_val)
+ 				return ret_val;
+ 		}
+@@ -804,34 +814,32 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
+ 	if (!active) {
+ 		phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
+ 		ew32(PHY_CTRL, phy_ctrl);
+-		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
++		/*
++		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+ 		 * during Dx states where the power conservation is most
+ 		 * important.  During driver activity we should enable
+-		 * SmartSpeed, so performance is maintained. */
++		 * SmartSpeed, so performance is maintained.
++		 */
+ 		if (phy->smart_speed == e1000_smart_speed_on) {
+-			ret_val = e1e_rphy(hw,
+-						    IGP01E1000_PHY_PORT_CONFIG,
+-						    &data);
++			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++					   &data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+ 			data |= IGP01E1000_PSCFR_SMART_SPEED;
+-			ret_val = e1e_wphy(hw,
+-						     IGP01E1000_PHY_PORT_CONFIG,
+-						     data);
++			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++					   data);
+ 			if (ret_val)
+ 				return ret_val;
+ 		} else if (phy->smart_speed == e1000_smart_speed_off) {
+-			ret_val = e1e_rphy(hw,
+-						    IGP01E1000_PHY_PORT_CONFIG,
+-						    &data);
++			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++					   &data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+ 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+-			ret_val = e1e_wphy(hw,
+-						     IGP01E1000_PHY_PORT_CONFIG,
+-						     data);
++			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++					   data);
+ 			if (ret_val)
+ 				return ret_val;
+ 		}
+@@ -841,23 +849,21 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
+ 		phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
+ 		ew32(PHY_CTRL, phy_ctrl);
+ 
+-		/* Call gig speed drop workaround on LPLU before accessing
+-		 * any PHY registers */
++		/*
++		 * Call gig speed drop workaround on LPLU before accessing
++		 * any PHY registers
++		 */
+ 		if ((hw->mac.type == e1000_ich8lan) &&
+ 		    (hw->phy.type == e1000_phy_igp_3))
+ 			e1000e_gig_downshift_workaround_ich8lan(hw);
+ 
+ 		/* When LPLU is enabled, we should disable SmartSpeed */
+-		ret_val = e1e_rphy(hw,
+-					    IGP01E1000_PHY_PORT_CONFIG,
+-					    &data);
++		ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);
+ 		if (ret_val)
+ 			return ret_val;
+ 
+ 		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+-		ret_val = e1e_wphy(hw,
+-					     IGP01E1000_PHY_PORT_CONFIG,
+-					     data);
++		ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);
+ 	}
+ 
+ 	return 0;
+@@ -944,7 +950,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
+ 
+ 	ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+ 
+-	/* Either we should have a hardware SPI cycle in progress
++	/*
++	 * Either we should have a hardware SPI cycle in progress
+ 	 * bit to check against, in order to start a new cycle or
+ 	 * FDONE bit should be changed in the hardware so that it
+ 	 * is 1 after hardware reset, which can then be used as an
+@@ -953,15 +960,19 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
+ 	 */
+ 
+ 	if (hsfsts.hsf_status.flcinprog == 0) {
+-		/* There is no cycle running at present,
+-		 * so we can start a cycle */
+-		/* Begin by setting Flash Cycle Done. */
++		/*
++		 * There is no cycle running at present,
++		 * so we can start a cycle
++		 * Begin by setting Flash Cycle Done.
++		 */
+ 		hsfsts.hsf_status.flcdone = 1;
+ 		ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+ 		ret_val = 0;
+ 	} else {
+-		/* otherwise poll for sometime so the current
+-		 * cycle has a chance to end before giving up. */
++		/*
++		 * otherwise poll for sometime so the current
++		 * cycle has a chance to end before giving up.
++		 */
+ 		for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
+ 			hsfsts.regval = __er16flash(hw, ICH_FLASH_HSFSTS);
+ 			if (hsfsts.hsf_status.flcinprog == 0) {
+@@ -971,8 +982,10 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
+ 			udelay(1);
+ 		}
+ 		if (ret_val == 0) {
+-			/* Successful in waiting for previous cycle to timeout,
+-			 * now set the Flash Cycle Done. */
++			/*
++			 * Successful in waiting for previous cycle to timeout,
++			 * now set the Flash Cycle Done.
++			 */
+ 			hsfsts.hsf_status.flcdone = 1;
+ 			ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+ 		} else {
+@@ -1077,10 +1090,12 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+ 		ret_val = e1000_flash_cycle_ich8lan(hw,
+ 						ICH_FLASH_READ_COMMAND_TIMEOUT);
+ 
+-		/* Check if FCERR is set to 1, if set to 1, clear it
++		/*
++		 * Check if FCERR is set to 1, if set to 1, clear it
+ 		 * and try the whole sequence a few more times, else
+ 		 * read in (shift in) the Flash Data0, the order is
+-		 * least significant byte first msb to lsb */
++		 * least significant byte first msb to lsb
++		 */
+ 		if (ret_val == 0) {
+ 			flash_data = er32flash(ICH_FLASH_FDATA0);
+ 			if (size == 1) {
+@@ -1090,7 +1105,8 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+ 			}
+ 			break;
+ 		} else {
+-			/* If we've gotten here, then things are probably
++			/*
++			 * If we've gotten here, then things are probably
+ 			 * completely hosed, but if the error condition is
+ 			 * detected, it won't hurt to give it another try...
+ 			 * ICH_FLASH_CYCLE_REPEAT_COUNT times.
+@@ -1168,18 +1184,20 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ 
+ 	ret_val = e1000e_update_nvm_checksum_generic(hw);
+ 	if (ret_val)
+-		return ret_val;;
++		return ret_val;
+ 
+ 	if (nvm->type != e1000_nvm_flash_sw)
+-		return ret_val;;
++		return ret_val;
+ 
+ 	ret_val = e1000_acquire_swflag_ich8lan(hw);
+ 	if (ret_val)
+-		return ret_val;;
++		return ret_val;
+ 
+-	/* We're writing to the opposite bank so if we're on bank 1,
++	/*
++	 * We're writing to the opposite bank so if we're on bank 1,
+ 	 * write to bank 0 etc.  We also need to erase the segment that
+-	 * is going to be written */
++	 * is going to be written
++	 */
+ 	if (!(er32(EECD) & E1000_EECD_SEC1VAL)) {
+ 		new_bank_offset = nvm->flash_bank_size;
+ 		old_bank_offset = 0;
+@@ -1191,9 +1209,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ 	}
+ 
+ 	for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
+-		/* Determine whether to write the value stored
++		/*
++		 * Determine whether to write the value stored
+ 		 * in the other NVM bank or a modified value stored
+-		 * in the shadow RAM */
++		 * in the shadow RAM
++		 */
+ 		if (dev_spec->shadow_ram[i].modified) {
+ 			data = dev_spec->shadow_ram[i].value;
+ 		} else {
+@@ -1202,12 +1222,14 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ 						      &data);
+ 		}
+ 
+-		/* If the word is 0x13, then make sure the signature bits
++		/*
++		 * If the word is 0x13, then make sure the signature bits
+ 		 * (15:14) are 11b until the commit has completed.
+ 		 * This will allow us to write 10b which indicates the
+ 		 * signature is valid.  We want to do this after the write
+ 		 * has completed so that we don't mark the segment valid
+-		 * while the write is still in progress */
++		 * while the write is still in progress
++		 */
+ 		if (i == E1000_ICH_NVM_SIG_WORD)
+ 			data |= E1000_ICH_NVM_SIG_MASK;
+ 
+@@ -1230,18 +1252,22 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ 			break;
+ 	}
+ 
+-	/* Don't bother writing the segment valid bits if sector
+-	 * programming failed. */
++	/*
++	 * Don't bother writing the segment valid bits if sector
++	 * programming failed.
++	 */
+ 	if (ret_val) {
+ 		hw_dbg(hw, "Flash commit failed.\n");
+ 		e1000_release_swflag_ich8lan(hw);
+ 		return ret_val;
+ 	}
+ 
+-	/* Finally validate the new segment by setting bit 15:14
++	/*
++	 * Finally validate the new segment by setting bit 15:14
+ 	 * to 10b in word 0x13 , this can be done without an
+ 	 * erase as well since these bits are 11 to start with
+-	 * and we need to change bit 14 to 0b */
++	 * and we need to change bit 14 to 0b
++	 */
+ 	act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
+ 	e1000_read_flash_word_ich8lan(hw, act_offset, &data);
+ 	data &= 0xBFFF;
+@@ -1253,10 +1279,12 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ 		return ret_val;
+ 	}
+ 
+-	/* And invalidate the previously valid segment by setting
++	/*
++	 * And invalidate the previously valid segment by setting
+ 	 * its signature word (0x13) high_byte to 0b. This can be
+ 	 * done without an erase because flash erase sets all bits
+-	 * to 1's. We can write 1's to 0's without an erase */
++	 * to 1's. We can write 1's to 0's without an erase
++	 */
+ 	act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
+ 	ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
+ 	if (ret_val) {
+@@ -1272,7 +1300,8 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ 
+ 	e1000_release_swflag_ich8lan(hw);
+ 
+-	/* Reload the EEPROM, or else modifications will not appear
++	/*
++	 * Reload the EEPROM, or else modifications will not appear
+ 	 * until after the next adapter reset.
+ 	 */
+ 	e1000e_reload_nvm(hw);
+@@ -1294,7 +1323,8 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ 	s32 ret_val;
+ 	u16 data;
+ 
+-	/* Read 0x19 and check bit 6.  If this bit is 0, the checksum
++	/*
++	 * Read 0x19 and check bit 6.  If this bit is 0, the checksum
+ 	 * needs to be fixed.  This bit is an indication that the NVM
+ 	 * was prepared by OEM software and did not calculate the
+ 	 * checksum...a likely scenario.
+@@ -1364,14 +1394,17 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+ 
+ 		ew32flash(ICH_FLASH_FDATA0, flash_data);
+ 
+-		/* check if FCERR is set to 1 , if set to 1, clear it
+-		 * and try the whole sequence a few more times else done */
++		/*
++		 * check if FCERR is set to 1 , if set to 1, clear it
++		 * and try the whole sequence a few more times else done
++		 */
+ 		ret_val = e1000_flash_cycle_ich8lan(hw,
+ 					       ICH_FLASH_WRITE_COMMAND_TIMEOUT);
+ 		if (!ret_val)
+ 			break;
+ 
+-		/* If we're here, then things are most likely
++		/*
++		 * If we're here, then things are most likely
+ 		 * completely hosed, but if the error condition
+ 		 * is detected, it won't hurt to give it another
+ 		 * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
+@@ -1462,9 +1495,10 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
+ 
+ 	hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
+ 
+-	/* Determine HW Sector size: Read BERASE bits of hw flash status
+-	 * register */
+-	/* 00: The Hw sector is 256 bytes, hence we need to erase 16
++	/*
++	 * Determine HW Sector size: Read BERASE bits of hw flash status
++	 * register
++	 * 00: The Hw sector is 256 bytes, hence we need to erase 16
+ 	 *     consecutive sectors.  The start index for the nth Hw sector
+ 	 *     can be calculated as = bank * 4096 + n * 256
+ 	 * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.
+@@ -1511,13 +1545,16 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
+ 			if (ret_val)
+ 				return ret_val;
+ 
+-			/* Write a value 11 (block Erase) in Flash
+-			 * Cycle field in hw flash control */
++			/*
++			 * Write a value 11 (block Erase) in Flash
++			 * Cycle field in hw flash control
++			 */
+ 			hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
+ 			hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
+ 			ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
+ 
+-			/* Write the last 24 bits of an index within the
++			/*
++			 * Write the last 24 bits of an index within the
+ 			 * block into Flash Linear address field in Flash
+ 			 * Address.
+ 			 */
+@@ -1529,13 +1566,14 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
+ 			if (ret_val == 0)
+ 				break;
+ 
+-			/* Check if FCERR is set to 1.  If 1,
++			/*
++			 * Check if FCERR is set to 1.  If 1,
+ 			 * clear it and try the whole sequence
+-			 * a few more times else Done */
++			 * a few more times else Done
++			 */
+ 			hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
+ 			if (hsfsts.hsf_status.flcerr == 1)
+-				/* repeat for some time before
+-				 * giving up */
++				/* repeat for some time before giving up */
+ 				continue;
+ 			else if (hsfsts.hsf_status.flcdone == 0)
+ 				return ret_val;
+@@ -1585,7 +1623,8 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
+ 
+ 	ret_val = e1000e_get_bus_info_pcie(hw);
+ 
+-	/* ICH devices are "PCI Express"-ish.  They have
++	/*
++	 * ICH devices are "PCI Express"-ish.  They have
+ 	 * a configuration space, but do not contain
+ 	 * PCI Express Capability registers, so bus width
+ 	 * must be hardcoded.
+@@ -1608,7 +1647,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
+ 	u32 ctrl, icr, kab;
+ 	s32 ret_val;
+ 
+-	/* Prevent the PCI-E bus from sticking if there is no TLP connection
++	/*
++	 * Prevent the PCI-E bus from sticking if there is no TLP connection
+ 	 * on the last TLP read/write transaction when MAC is reset.
+ 	 */
+ 	ret_val = e1000e_disable_pcie_master(hw);
+@@ -1619,7 +1659,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
+ 	hw_dbg(hw, "Masking off all interrupts\n");
+ 	ew32(IMC, 0xffffffff);
+ 
+-	/* Disable the Transmit and Receive units.  Then delay to allow
++	/*
++	 * Disable the Transmit and Receive units.  Then delay to allow
+ 	 * any pending transactions to complete before we hit the MAC
+ 	 * with the global reset.
+ 	 */
+@@ -1640,7 +1681,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
+ 	ctrl = er32(CTRL);
+ 
+ 	if (!e1000_check_reset_block(hw)) {
+-		/* PHY HW reset requires MAC CORE reset at the same
++		/*
++		 * PHY HW reset requires MAC CORE reset at the same
+ 		 * time to make sure the interface between MAC and the
+ 		 * external PHY is reset.
+ 		 */
+@@ -1711,21 +1753,23 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
+ 	ret_val = e1000_setup_link_ich8lan(hw);
+ 
+ 	/* Set the transmit descriptor write-back policy for both queues */
+-	txdctl = er32(TXDCTL);
++	txdctl = er32(TXDCTL(0));
+ 	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
+ 		 E1000_TXDCTL_FULL_TX_DESC_WB;
+ 	txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
+ 		 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
+-	ew32(TXDCTL, txdctl);
+-	txdctl = er32(TXDCTL1);
++	ew32(TXDCTL(0), txdctl);
++	txdctl = er32(TXDCTL(1));
+ 	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
+ 		 E1000_TXDCTL_FULL_TX_DESC_WB;
+ 	txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
+ 		 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
+-	ew32(TXDCTL1, txdctl);
++	ew32(TXDCTL(1), txdctl);
+ 
+-	/* ICH8 has opposite polarity of no_snoop bits.
+-	 * By default, we should use snoop behavior. */
++	/*
++	 * ICH8 has opposite polarity of no_snoop bits.
++	 * By default, we should use snoop behavior.
++	 */
+ 	if (mac->type == e1000_ich8lan)
+ 		snoop = PCIE_ICH8_SNOOP_ALL;
+ 	else
+@@ -1736,7 +1780,8 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
+ 	ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+ 	ew32(CTRL_EXT, ctrl_ext);
+ 
+-	/* Clear all of the statistics registers (clear on read).  It is
++	/*
++	 * Clear all of the statistics registers (clear on read).  It is
+ 	 * important that we do this after we have tried to establish link
+ 	 * because the symbol error count will increment wildly if there
+ 	 * is no link.
+@@ -1762,30 +1807,30 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
+ 	ew32(CTRL_EXT, reg);
+ 
+ 	/* Transmit Descriptor Control 0 */
+-	reg = er32(TXDCTL);
++	reg = er32(TXDCTL(0));
+ 	reg |= (1 << 22);
+-	ew32(TXDCTL, reg);
++	ew32(TXDCTL(0), reg);
+ 
+ 	/* Transmit Descriptor Control 1 */
+-	reg = er32(TXDCTL1);
++	reg = er32(TXDCTL(1));
+ 	reg |= (1 << 22);
+-	ew32(TXDCTL1, reg);
++	ew32(TXDCTL(1), reg);
+ 
+ 	/* Transmit Arbitration Control 0 */
+-	reg = er32(TARC0);
++	reg = er32(TARC(0));
+ 	if (hw->mac.type == e1000_ich8lan)
+ 		reg |= (1 << 28) | (1 << 29);
+ 	reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27);
+-	ew32(TARC0, reg);
++	ew32(TARC(0), reg);
+ 
+ 	/* Transmit Arbitration Control 1 */
+-	reg = er32(TARC1);
++	reg = er32(TARC(1));
+ 	if (er32(TCTL) & E1000_TCTL_MULR)
+ 		reg &= ~(1 << 28);
+ 	else
+ 		reg |= (1 << 28);
+ 	reg |= (1 << 24) | (1 << 26) | (1 << 30);
+-	ew32(TARC1, reg);
++	ew32(TARC(1), reg);
+ 
+ 	/* Device Status */
+ 	if (hw->mac.type == e1000_ich8lan) {
+@@ -1807,29 +1852,29 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
+  **/
+ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
+ {
+-	struct e1000_mac_info *mac = &hw->mac;
+ 	s32 ret_val;
+ 
+ 	if (e1000_check_reset_block(hw))
+ 		return 0;
+ 
+-	/* ICH parts do not have a word in the NVM to determine
++	/*
++	 * ICH parts do not have a word in the NVM to determine
+ 	 * the default flow control setting, so we explicitly
+ 	 * set it to full.
+ 	 */
+-	if (mac->fc == e1000_fc_default)
+-		mac->fc = e1000_fc_full;
++	if (hw->fc.type == e1000_fc_default)
++		hw->fc.type = e1000_fc_full;
+ 
+-	mac->original_fc = mac->fc;
++	hw->fc.original_type = hw->fc.type;
+ 
+-	hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", mac->fc);
++	hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", hw->fc.type);
+ 
+ 	/* Continue to configure the copper link. */
+ 	ret_val = e1000_setup_copper_link_ich8lan(hw);
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	ew32(FCTTV, mac->fc_pause_time);
++	ew32(FCTTV, hw->fc.pause_time);
+ 
+ 	return e1000e_set_fc_watermarks(hw);
+ }
+@@ -1853,9 +1898,11 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
+ 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ 	ew32(CTRL, ctrl);
+ 
+-	/* Set the mac to wait the maximum time between each iteration
++	/*
++	 * Set the mac to wait the maximum time between each iteration
+ 	 * and increase the max iterations when polling the phy;
+-	 * this fixes erroneous timeouts at 10Mbps. */
++	 * this fixes erroneous timeouts at 10Mbps.
++	 */
+ 	ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+ 	if (ret_val)
+ 		return ret_val;
+@@ -1882,7 +1929,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
+  *  @speed: pointer to store current link speed
+  *  @duplex: pointer to store the current link duplex
+  *
+- *  Calls the generic get_speed_and_duplex to retreive the current link
++ *  Calls the generic get_speed_and_duplex to retrieve the current link
+  *  information and then calls the Kumeran lock loss workaround for links at
+  *  gigabit speeds.
+  **/
+@@ -1930,9 +1977,11 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
+ 	if (!dev_spec->kmrn_lock_loss_workaround_enabled)
+ 		return 0;
+ 
+-	/* Make sure link is up before proceeding.  If not just return.
++	/*
++	 * Make sure link is up before proceeding.  If not just return.
+ 	 * Attempting this while link is negotiating fouled up link
+-	 * stability */
++	 * stability
++	 */
+ 	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
+ 	if (!link)
+ 		return 0;
+@@ -1961,8 +2010,10 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
+ 		     E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
+ 	ew32(PHY_CTRL, phy_ctrl);
+ 
+-	/* Call gig speed drop workaround on Gig disable before accessing
+-	 * any PHY registers */
++	/*
++	 * Call gig speed drop workaround on Gig disable before accessing
++	 * any PHY registers
++	 */
+ 	e1000e_gig_downshift_workaround_ich8lan(hw);
+ 
+ 	/* unable to acquire PCS lock */
+@@ -1970,7 +2021,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
+ }
+ 
+ /**
+- *  e1000_set_kmrn_lock_loss_workaound_ich8lan - Set Kumeran workaround state
++ *  e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state
+  *  @hw: pointer to the HW structure
+  *  @state: boolean value used to set the current Kumeran workaround state
+  *
+@@ -2017,8 +2068,10 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
+ 			E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
+ 		ew32(PHY_CTRL, reg);
+ 
+-		/* Call gig speed drop workaround on Gig disable before
+-		 * accessing any PHY registers */
++		/*
++		 * Call gig speed drop workaround on Gig disable before
++		 * accessing any PHY registers
++		 */
+ 		if (hw->mac.type == e1000_ich8lan)
+ 			e1000e_gig_downshift_workaround_ich8lan(hw);
+ 
+@@ -2158,7 +2211,7 @@ static struct e1000_mac_operations ich8_mac_ops = {
+ 	.get_link_up_info	= e1000_get_link_up_info_ich8lan,
+ 	.led_on			= e1000_led_on_ich8lan,
+ 	.led_off		= e1000_led_off_ich8lan,
+-	.mc_addr_list_update	= e1000e_mc_addr_list_update_generic,
++	.update_mc_addr_list	= e1000e_update_mc_addr_list_generic,
+ 	.reset_hw		= e1000_reset_hw_ich8lan,
+ 	.init_hw		= e1000_init_hw_ich8lan,
+ 	.setup_link		= e1000_setup_link_ich8lan,
+@@ -2200,7 +2253,7 @@ struct e1000_info e1000_ich8_info = {
+ 				  | FLAG_HAS_FLASH
+ 				  | FLAG_APME_IN_WUC,
+ 	.pba			= 8,
+-	.get_invariants		= e1000_get_invariants_ich8lan,
++	.get_variants		= e1000_get_variants_ich8lan,
+ 	.mac_ops		= &ich8_mac_ops,
+ 	.phy_ops		= &ich8_phy_ops,
+ 	.nvm_ops		= &ich8_nvm_ops,
+@@ -2217,7 +2270,7 @@ struct e1000_info e1000_ich9_info = {
+ 				  | FLAG_HAS_FLASH
+ 				  | FLAG_APME_IN_WUC,
+ 	.pba			= 10,
+-	.get_invariants		= e1000_get_invariants_ich8lan,
++	.get_variants		= e1000_get_variants_ich8lan,
+ 	.mac_ops		= &ich8_mac_ops,
+ 	.phy_ops		= &ich8_phy_ops,
+ 	.nvm_ops		= &ich8_nvm_ops,
+diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
+index 95f75a4..f1f4e9d 100644
+--- a/drivers/net/e1000e/lib.c
++++ b/drivers/net/e1000e/lib.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -43,8 +43,8 @@ enum e1000_mng_mode {
+ 
+ #define E1000_FACTPS_MNGCG		0x20000000
+ 
+-#define E1000_IAMT_SIGNATURE		0x544D4149 /* Intel(R) Active Management
+-						    * Technology signature */
++/* Intel(R) Active Management Technology signature */
++#define E1000_IAMT_SIGNATURE		0x544D4149
+ 
+ /**
+  *  e1000e_get_bus_info_pcie - Get PCIe bus information
+@@ -142,7 +142,8 @@ void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
+ {
+ 	u32 rar_low, rar_high;
+ 
+-	/* HW expects these in little endian so we reverse the byte order
++	/*
++	 * HW expects these in little endian so we reverse the byte order
+ 	 * from network order (big endian) to little endian
+ 	 */
+ 	rar_low = ((u32) addr[0] |
+@@ -171,7 +172,8 @@ static void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
+ {
+ 	u32 hash_bit, hash_reg, mta;
+ 
+-	/* The MTA is a register array of 32-bit registers. It is
++	/*
++	 * The MTA is a register array of 32-bit registers. It is
+ 	 * treated like an array of (32*mta_reg_count) bits.  We want to
+ 	 * set bit BitArray[hash_value]. So we figure out what register
+ 	 * the bit is in, read it, OR in the new bit, then write
+@@ -208,12 +210,15 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+ 	/* Register count multiplied by bits per register */
+ 	hash_mask = (hw->mac.mta_reg_count * 32) - 1;
+ 
+-	/* For a mc_filter_type of 0, bit_shift is the number of left-shifts
+-	 * where 0xFF would still fall within the hash mask. */
++	/*
++	 * For a mc_filter_type of 0, bit_shift is the number of left-shifts
++	 * where 0xFF would still fall within the hash mask.
++	 */
+ 	while (hash_mask >> bit_shift != 0xFF)
+ 		bit_shift++;
+ 
+-	/* The portion of the address that is used for the hash table
++	/*
++	 * The portion of the address that is used for the hash table
+ 	 * is determined by the mc_filter_type setting.
+ 	 * The algorithm is such that there is a total of 8 bits of shifting.
+ 	 * The bit_shift for a mc_filter_type of 0 represents the number of
+@@ -224,8 +229,8 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+ 	 * cases are a variation of this algorithm...essentially raising the
+ 	 * number of bits to shift mc_addr[5] left, while still keeping the
+ 	 * 8-bit shifting total.
+-	 */
+-	/* For example, given the following Destination MAC Address and an
++	 *
++	 * For example, given the following Destination MAC Address and an
+ 	 * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask),
+ 	 * we can see that the bit_shift for case 0 is 4.  These are the hash
+ 	 * values resulting from each mc_filter_type...
+@@ -260,7 +265,7 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+ }
+ 
+ /**
+- *  e1000e_mc_addr_list_update_generic - Update Multicast addresses
++ *  e1000e_update_mc_addr_list_generic - 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
+@@ -272,14 +277,15 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+  *  The parameter rar_count will usually be hw->mac.rar_entry_count
+  *  unless there are workarounds that change this.
+  **/
+-void e1000e_mc_addr_list_update_generic(struct e1000_hw *hw,
+-				       u8 *mc_addr_list, u32 mc_addr_count,
+-				       u32 rar_used_count, u32 rar_count)
++void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
++					u8 *mc_addr_list, u32 mc_addr_count,
++					u32 rar_used_count, u32 rar_count)
+ {
+ 	u32 hash_value;
+ 	u32 i;
+ 
+-	/* Load the first set of multicast addresses into the exact
++	/*
++	 * 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.
+ 	 */
+@@ -375,7 +381,8 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
+ 	s32 ret_val;
+ 	bool link;
+ 
+-	/* We only want to go out to the PHY registers to see if Auto-Neg
++	/*
++	 * We only want to go out to the PHY registers to see if Auto-Neg
+ 	 * has completed and/or if our link status has changed.  The
+ 	 * get_link_status flag is set upon receiving a Link Status
+ 	 * Change or Rx Sequence Error interrupt.
+@@ -383,7 +390,8 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
+ 	if (!mac->get_link_status)
+ 		return 0;
+ 
+-	/* First we want to see if the MII Status Register reports
++	/*
++	 * First we want to see if the MII Status Register reports
+ 	 * link.  If so, then we want to get the current speed/duplex
+ 	 * of the PHY.
+ 	 */
+@@ -396,11 +404,14 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
+ 
+ 	mac->get_link_status = 0;
+ 
+-	/* Check if there was DownShift, must be checked
+-	 * immediately after link-up */
++	/*
++	 * Check if there was DownShift, must be checked
++	 * immediately after link-up
++	 */
+ 	e1000e_check_downshift(hw);
+ 
+-	/* If we are forcing speed/duplex, then we simply return since
++	/*
++	 * If we are forcing speed/duplex, then we simply return since
+ 	 * we have already determined whether we have link or not.
+ 	 */
+ 	if (!mac->autoneg) {
+@@ -408,13 +419,15 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
+ 		return ret_val;
+ 	}
+ 
+-	/* Auto-Neg is enabled.  Auto Speed Detection takes care
++	/*
++	 * Auto-Neg is enabled.  Auto Speed Detection takes care
+ 	 * of MAC speed/duplex configuration.  So we only need to
+ 	 * configure Collision Distance in the MAC.
+ 	 */
+ 	e1000e_config_collision_dist(hw);
+ 
+-	/* Configure Flow Control now that Auto-Neg has completed.
++	/*
++	 * Configure Flow Control now that Auto-Neg has completed.
+ 	 * First, we need to restore the desired flow control
+ 	 * settings because we may have had to re-autoneg with a
+ 	 * different link partner.
+@@ -446,7 +459,8 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
+ 	status = er32(STATUS);
+ 	rxcw = er32(RXCW);
+ 
+-	/* If we don't have link (auto-negotiation failed or link partner
++	/*
++	 * If we don't have link (auto-negotiation failed or link partner
+ 	 * cannot auto-negotiate), the cable is plugged in (we have signal),
+ 	 * and our link partner is not trying to auto-negotiate with us (we
+ 	 * are receiving idles or data), we need to force link up. We also
+@@ -477,7 +491,8 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
+ 			return ret_val;
+ 		}
+ 	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
+-		/* If we are forcing link and we are receiving /C/ ordered
++		/*
++		 * If we are forcing link and we are receiving /C/ ordered
+ 		 * sets, re-enable auto-negotiation in the TXCW register
+ 		 * and disable forced link in the Device Control register
+ 		 * in an attempt to auto-negotiate with our link partner.
+@@ -511,7 +526,8 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
+ 	status = er32(STATUS);
+ 	rxcw = er32(RXCW);
+ 
+-	/* If we don't have link (auto-negotiation failed or link partner
++	/*
++	 * If we don't have link (auto-negotiation failed or link partner
+ 	 * cannot auto-negotiate), and our link partner is not trying to
+ 	 * auto-negotiate with us (we are receiving idles or data),
+ 	 * we need to force link up. We also need to give auto-negotiation
+@@ -540,7 +556,8 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
+ 			return ret_val;
+ 		}
+ 	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
+-		/* If we are forcing link and we are receiving /C/ ordered
++		/*
++		 * If we are forcing link and we are receiving /C/ ordered
+ 		 * sets, re-enable auto-negotiation in the TXCW register
+ 		 * and disable forced link in the Device Control register
+ 		 * in an attempt to auto-negotiate with our link partner.
+@@ -551,7 +568,8 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
+ 
+ 		mac->serdes_has_link = 1;
+ 	} else if (!(E1000_TXCW_ANE & er32(TXCW))) {
+-		/* If we force link for non-auto-negotiation switch, check
++		/*
++		 * If we force link for non-auto-negotiation switch, check
+ 		 * link status based on MAC synchronization for internal
+ 		 * serdes media type.
+ 		 */
+@@ -585,11 +603,11 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
+  **/
+ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
+ {
+-	struct e1000_mac_info *mac = &hw->mac;
+ 	s32 ret_val;
+ 	u16 nvm_data;
+ 
+-	/* Read and store word 0x0F of the EEPROM. This word contains bits
++	/*
++	 * Read and store word 0x0F of the EEPROM. This word contains bits
+ 	 * that determine the hardware's default PAUSE (flow control) mode,
+ 	 * a bit that determines whether the HW defaults to enabling or
+ 	 * disabling auto-negotiation, and the direction of the
+@@ -605,12 +623,12 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
+ 	}
+ 
+ 	if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
+-		mac->fc = e1000_fc_none;
++		hw->fc.type = e1000_fc_none;
+ 	else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
+ 		 NVM_WORD0F_ASM_DIR)
+-		mac->fc = e1000_fc_tx_pause;
++		hw->fc.type = e1000_fc_tx_pause;
+ 	else
+-		mac->fc = e1000_fc_full;
++		hw->fc.type = e1000_fc_full;
+ 
+ 	return 0;
+ }
+@@ -630,7 +648,8 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
+ 	struct e1000_mac_info *mac = &hw->mac;
+ 	s32 ret_val;
+ 
+-	/* In the case of the phy reset being blocked, we already have a link.
++	/*
++	 * In the case of the phy reset being blocked, we already have a link.
+ 	 * We do not need to set it up again.
+ 	 */
+ 	if (e1000_check_reset_block(hw))
+@@ -640,26 +659,28 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
+ 	 * If flow control is set to default, set flow control based on
+ 	 * the EEPROM flow control settings.
+ 	 */
+-	if (mac->fc == e1000_fc_default) {
++	if (hw->fc.type == e1000_fc_default) {
+ 		ret_val = e1000_set_default_fc_generic(hw);
+ 		if (ret_val)
+ 			return ret_val;
+ 	}
+ 
+-	/* We want to save off the original Flow Control configuration just
++	/*
++	 * We want to save off the original Flow Control configuration just
+ 	 * in case we get disconnected and then reconnected into a different
+ 	 * hub or switch with different Flow Control capabilities.
+ 	 */
+-	mac->original_fc = mac->fc;
++	hw->fc.original_type = hw->fc.type;
+ 
+-	hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", mac->fc);
++	hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", hw->fc.type);
+ 
+ 	/* Call the necessary media_type subroutine to configure the link. */
+ 	ret_val = mac->ops.setup_physical_interface(hw);
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* Initialize the flow control address, type, and PAUSE timer
++	/*
++	 * Initialize the flow control address, type, and PAUSE timer
+ 	 * registers to their default values.  This is done even if flow
+ 	 * control is disabled, because it does not hurt anything to
+ 	 * initialize these registers.
+@@ -669,7 +690,7 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
+ 	ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+ 	ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
+ 
+-	ew32(FCTTV, mac->fc_pause_time);
++	ew32(FCTTV, hw->fc.pause_time);
+ 
+ 	return e1000e_set_fc_watermarks(hw);
+ }
+@@ -686,7 +707,8 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
+ 	struct e1000_mac_info *mac = &hw->mac;
+ 	u32 txcw;
+ 
+-	/* Check for a software override of the flow control settings, and
++	/*
++	 * Check for a software override of the flow control settings, and
+ 	 * setup the device accordingly.  If auto-negotiation is enabled, then
+ 	 * software will have to set the "PAUSE" bits to the correct value in
+ 	 * the Transmit Config Word Register (TXCW) and re-start auto-
+@@ -700,31 +722,34 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
+ 	 *	  but not send pause frames).
+ 	 *      2:  Tx flow control is enabled (we can send pause frames but we
+ 	 *	  do not support receiving pause frames).
+-	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
++	 *      3:  Both Rx and Tx flow control (symmetric) are enabled.
+ 	 */
+-	switch (mac->fc) {
++	switch (hw->fc.type) {
+ 	case e1000_fc_none:
+ 		/* Flow control completely disabled by a software over-ride. */
+ 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
+ 		break;
+ 	case e1000_fc_rx_pause:
+-		/* RX Flow control is enabled and TX Flow control is disabled
++		/*
++		 * Rx Flow control is enabled and Tx Flow control is disabled
+ 		 * by a software over-ride. Since there really isn't a way to
+-		 * advertise that we are capable of RX Pause ONLY, we will
+-		 * advertise that we support both symmetric and asymmetric RX
++		 * advertise that we are capable of Rx Pause ONLY, we will
++		 * advertise that we support both symmetric and asymmetric Rx
+ 		 * PAUSE.  Later, we will disable the adapter's ability to send
+ 		 * PAUSE frames.
+ 		 */
+ 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+ 		break;
+ 	case e1000_fc_tx_pause:
+-		/* TX Flow control is enabled, and RX Flow control is disabled,
++		/*
++		 * Tx Flow control is enabled, and Rx Flow control is disabled,
+ 		 * by a software over-ride.
+ 		 */
+ 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
+ 		break;
+ 	case e1000_fc_full:
+-		/* Flow control (both RX and TX) is enabled by a software
++		/*
++		 * Flow control (both Rx and Tx) is enabled by a software
+ 		 * over-ride.
+ 		 */
+ 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+@@ -754,7 +779,8 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
+ 	u32 i, status;
+ 	s32 ret_val;
+ 
+-	/* If we have a signal (the cable is plugged in, or assumed true for
++	/*
++	 * If we have a signal (the cable is plugged in, or assumed true for
+ 	 * serdes media) then poll for a "Link-Up" indication in the Device
+ 	 * Status Register.  Time-out if a link isn't seen in 500 milliseconds
+ 	 * seconds (Auto-negotiation should complete in less than 500
+@@ -769,7 +795,8 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
+ 	if (i == FIBER_LINK_UP_LIMIT) {
+ 		hw_dbg(hw, "Never got a valid link from auto-neg!!!\n");
+ 		mac->autoneg_failed = 1;
+-		/* AutoNeg failed to achieve a link, so we'll call
++		/*
++		 * AutoNeg failed to achieve a link, so we'll call
+ 		 * mac->check_for_link. This routine will force the
+ 		 * link up if we detect a signal. This will allow us to
+ 		 * communicate with non-autonegotiating link partners.
+@@ -811,7 +838,8 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* Since auto-negotiation is enabled, take the link out of reset (the
++	/*
++	 * Since auto-negotiation is enabled, take the link out of reset (the
+ 	 * link will be in reset, because we previously reset the chip). This
+ 	 * will restart auto-negotiation.  If auto-negotiation is successful
+ 	 * then the link-up status bit will be set and the flow control enable
+@@ -823,11 +851,12 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
+ 	e1e_flush();
+ 	msleep(1);
+ 
+-	/* For these adapters, the SW defineable pin 1 is set when the optics
++	/*
++	 * For these adapters, the SW definable pin 1 is set when the optics
+ 	 * detect a signal.  If we have a signal, then poll for a "Link-Up"
+ 	 * indication.
+ 	 */
+-	if (hw->media_type == e1000_media_type_internal_serdes ||
++	if (hw->phy.media_type == e1000_media_type_internal_serdes ||
+ 	    (er32(CTRL) & E1000_CTRL_SWDPIN1)) {
+ 		ret_val = e1000_poll_fiber_serdes_link_generic(hw);
+ 	} else {
+@@ -864,27 +893,28 @@ void e1000e_config_collision_dist(struct e1000_hw *hw)
+  *
+  *  Sets the flow control high/low threshold (watermark) registers.  If
+  *  flow control XON frame transmission is enabled, then set XON frame
+- *  tansmission as well.
++ *  transmission as well.
+  **/
+ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
+ {
+-	struct e1000_mac_info *mac = &hw->mac;
+ 	u32 fcrtl = 0, fcrth = 0;
+ 
+-	/* Set the flow control receive threshold registers.  Normally,
++	/*
++	 * Set the flow control receive threshold registers.  Normally,
+ 	 * these registers will be set to a default threshold that may be
+ 	 * adjusted later by the driver's runtime code.  However, if the
+ 	 * ability to transmit pause frames is not enabled, then these
+ 	 * registers will be set to 0.
+ 	 */
+-	if (mac->fc & e1000_fc_tx_pause) {
+-		/* We need to set up the Receive Threshold high and low water
++	if (hw->fc.type & e1000_fc_tx_pause) {
++		/*
++		 * We need to set up the Receive Threshold high and low water
+ 		 * marks as well as (optionally) enabling the transmission of
+ 		 * XON frames.
+ 		 */
+-		fcrtl = mac->fc_low_water;
++		fcrtl = hw->fc.low_water;
+ 		fcrtl |= E1000_FCRTL_XONE;
+-		fcrth = mac->fc_high_water;
++		fcrth = hw->fc.high_water;
+ 	}
+ 	ew32(FCRTL, fcrtl);
+ 	ew32(FCRTH, fcrth);
+@@ -904,18 +934,18 @@ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
+  **/
+ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
+ {
+-	struct e1000_mac_info *mac = &hw->mac;
+ 	u32 ctrl;
+ 
+ 	ctrl = er32(CTRL);
+ 
+-	/* Because we didn't get link via the internal auto-negotiation
++	/*
++	 * Because we didn't get link via the internal auto-negotiation
+ 	 * mechanism (we either forced link or we got link via PHY
+ 	 * auto-neg), we have to manually enable/disable transmit an
+ 	 * receive flow control.
+ 	 *
+ 	 * The "Case" statement below enables/disable flow control
+-	 * according to the "mac->fc" parameter.
++	 * according to the "hw->fc.type" parameter.
+ 	 *
+ 	 * The possible values of the "fc" parameter are:
+ 	 *      0:  Flow control is completely disabled
+@@ -923,12 +953,12 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
+ 	 *	  frames but not send pause frames).
+ 	 *      2:  Tx flow control is enabled (we can send pause frames
+ 	 *	  frames but we do not receive pause frames).
+-	 *      3:  Both Rx and TX flow control (symmetric) is enabled.
++	 *      3:  Both Rx and Tx flow control (symmetric) is enabled.
+ 	 *  other:  No other values should be possible at this point.
+ 	 */
+-	hw_dbg(hw, "mac->fc = %u\n", mac->fc);
++	hw_dbg(hw, "hw->fc.type = %u\n", hw->fc.type);
+ 
+-	switch (mac->fc) {
++	switch (hw->fc.type) {
+ 	case e1000_fc_none:
+ 		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
+ 		break;
+@@ -970,16 +1000,17 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ 	u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
+ 	u16 speed, duplex;
+ 
+-	/* Check for the case where we have fiber media and auto-neg failed
++	/*
++	 * Check for the case where we have fiber media and auto-neg failed
+ 	 * so we had to force link.  In this case, we need to force the
+ 	 * configuration of the MAC to match the "fc" parameter.
+ 	 */
+ 	if (mac->autoneg_failed) {
+-		if (hw->media_type == e1000_media_type_fiber ||
+-		    hw->media_type == e1000_media_type_internal_serdes)
++		if (hw->phy.media_type == e1000_media_type_fiber ||
++		    hw->phy.media_type == e1000_media_type_internal_serdes)
+ 			ret_val = e1000e_force_mac_fc(hw);
+ 	} else {
+-		if (hw->media_type == e1000_media_type_copper)
++		if (hw->phy.media_type == e1000_media_type_copper)
+ 			ret_val = e1000e_force_mac_fc(hw);
+ 	}
+ 
+@@ -988,13 +1019,15 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ 		return ret_val;
+ 	}
+ 
+-	/* Check for the case where we have copper media and auto-neg is
++	/*
++	 * Check for the case where we have copper media and auto-neg is
+ 	 * enabled.  In this case, we need to check and see if Auto-Neg
+ 	 * has completed, and if so, how the PHY and link partner has
+ 	 * flow control configured.
+ 	 */
+-	if ((hw->media_type == e1000_media_type_copper) && mac->autoneg) {
+-		/* Read the MII Status Register and check to see if AutoNeg
++	if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
++		/*
++		 * Read the MII Status Register and check to see if AutoNeg
+ 		 * has completed.  We read this twice because this reg has
+ 		 * some "sticky" (latched) bits.
+ 		 */
+@@ -1011,7 +1044,8 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ 			return ret_val;
+ 		}
+ 
+-		/* The AutoNeg process has completed, so we now need to
++		/*
++		 * The AutoNeg process has completed, so we now need to
+ 		 * read both the Auto Negotiation Advertisement
+ 		 * Register (Address 4) and the Auto_Negotiation Base
+ 		 * Page Ability Register (Address 5) to determine how
+@@ -1024,7 +1058,8 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ 		if (ret_val)
+ 			return ret_val;
+ 
+-		/* Two bits in the Auto Negotiation Advertisement Register
++		/*
++		 * Two bits in the Auto Negotiation Advertisement Register
+ 		 * (Address 4) and two bits in the Auto Negotiation Base
+ 		 * Page Ability Register (Address 5) determine flow control
+ 		 * for both the PHY and the link partner.  The following
+@@ -1045,8 +1080,8 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ 		 *   1   |    1    |   0   |    0    | e1000_fc_none
+ 		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+ 		 *
+-		 */
+-		/* Are both PAUSE bits set to 1?  If so, this implies
++		 *
++		 * Are both PAUSE bits set to 1?  If so, this implies
+ 		 * Symmetric Flow Control is enabled at both ends.  The
+ 		 * ASM_DIR bits are irrelevant per the spec.
+ 		 *
+@@ -1060,22 +1095,24 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ 		 */
+ 		if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+ 		    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
+-			/* Now we need to check if the user selected RX ONLY
++			/*
++			 * Now we need to check if the user selected Rx ONLY
+ 			 * of pause frames.  In this case, we had to advertise
+-			 * FULL flow control because we could not advertise RX
++			 * FULL flow control because we could not advertise Rx
+ 			 * ONLY. Hence, we must now check to see if we need to
+ 			 * turn OFF  the TRANSMISSION of PAUSE frames.
+ 			 */
+-			if (mac->original_fc == e1000_fc_full) {
+-				mac->fc = e1000_fc_full;
++			if (hw->fc.original_type == e1000_fc_full) {
++				hw->fc.type = e1000_fc_full;
+ 				hw_dbg(hw, "Flow Control = FULL.\r\n");
+ 			} else {
+-				mac->fc = e1000_fc_rx_pause;
++				hw->fc.type = e1000_fc_rx_pause;
+ 				hw_dbg(hw, "Flow Control = "
+ 					 "RX PAUSE frames only.\r\n");
+ 			}
+ 		}
+-		/* For receiving PAUSE frames ONLY.
++		/*
++		 * For receiving PAUSE frames ONLY.
+ 		 *
+ 		 *   LOCAL DEVICE  |   LINK PARTNER
+ 		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+@@ -1087,10 +1124,11 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ 			  (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ 			  (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ 			  (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+-			mac->fc = e1000_fc_tx_pause;
+-			hw_dbg(hw, "Flow Control = TX PAUSE frames only.\r\n");
++			hw->fc.type = e1000_fc_tx_pause;
++			hw_dbg(hw, "Flow Control = Tx PAUSE frames only.\r\n");
+ 		}
+-		/* For transmitting PAUSE frames ONLY.
++		/*
++		 * For transmitting PAUSE frames ONLY.
+ 		 *
+ 		 *   LOCAL DEVICE  |   LINK PARTNER
+ 		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+@@ -1102,18 +1140,19 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ 			 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ 			 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ 			 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+-			mac->fc = e1000_fc_rx_pause;
+-			hw_dbg(hw, "Flow Control = RX PAUSE frames only.\r\n");
++			hw->fc.type = e1000_fc_rx_pause;
++			hw_dbg(hw, "Flow Control = Rx PAUSE frames only.\r\n");
+ 		} else {
+ 			/*
+ 			 * Per the IEEE spec, at this point flow control
+ 			 * should be disabled.
+ 			 */
+-			mac->fc = e1000_fc_none;
++			hw->fc.type = e1000_fc_none;
+ 			hw_dbg(hw, "Flow Control = NONE.\r\n");
+ 		}
+ 
+-		/* Now we need to do one last check...  If we auto-
++		/*
++		 * Now we need to do one last check...  If we auto-
+ 		 * negotiated to HALF DUPLEX, flow control should not be
+ 		 * enabled per IEEE 802.3 spec.
+ 		 */
+@@ -1124,9 +1163,10 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ 		}
+ 
+ 		if (duplex == HALF_DUPLEX)
+-			mac->fc = e1000_fc_none;
++			hw->fc.type = e1000_fc_none;
+ 
+-		/* Now we call a subroutine to actually force the MAC
++		/*
++		 * Now we call a subroutine to actually force the MAC
+ 		 * controller to use the correct flow control settings.
+ 		 */
+ 		ret_val = e1000e_force_mac_fc(hw);
+@@ -1393,13 +1433,15 @@ s32 e1000e_blink_led(struct e1000_hw *hw)
+ 	u32 ledctl_blink = 0;
+ 	u32 i;
+ 
+-	if (hw->media_type == e1000_media_type_fiber) {
++	if (hw->phy.media_type == e1000_media_type_fiber) {
+ 		/* always blink LED0 for PCI-E fiber */
+ 		ledctl_blink = E1000_LEDCTL_LED0_BLINK |
+ 		     (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
+ 	} else {
+-		/* set the blink bit for each LED that's "on" (0x0E)
+-		 * in ledctl_mode2 */
++		/*
++		 * set the blink bit for each LED that's "on" (0x0E)
++		 * in ledctl_mode2
++		 */
+ 		ledctl_blink = hw->mac.ledctl_mode2;
+ 		for (i = 0; i < 4; i++)
+ 			if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
+@@ -1423,7 +1465,7 @@ s32 e1000e_led_on_generic(struct e1000_hw *hw)
+ {
+ 	u32 ctrl;
+ 
+-	switch (hw->media_type) {
++	switch (hw->phy.media_type) {
+ 	case e1000_media_type_fiber:
+ 		ctrl = er32(CTRL);
+ 		ctrl &= ~E1000_CTRL_SWDPIN0;
+@@ -1450,7 +1492,7 @@ s32 e1000e_led_off_generic(struct e1000_hw *hw)
+ {
+ 	u32 ctrl;
+ 
+-	switch (hw->media_type) {
++	switch (hw->phy.media_type) {
+ 	case e1000_media_type_fiber:
+ 		ctrl = er32(CTRL);
+ 		ctrl |= E1000_CTRL_SWDPIN0;
+@@ -1562,8 +1604,7 @@ void e1000e_update_adaptive(struct e1000_hw *hw)
+ 				else
+ 					mac->current_ifs_val +=
+ 						mac->ifs_step_size;
+-				ew32(AIT,
+-						mac->current_ifs_val);
++				ew32(AIT, mac->current_ifs_val);
+ 			}
+ 		}
+ 	} else {
+@@ -1826,10 +1867,12 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
+ 		udelay(1);
+ 		timeout = NVM_MAX_RETRY_SPI;
+ 
+-		/* Read "Status Register" repeatedly until the LSB is cleared.
++		/*
++		 * Read "Status Register" repeatedly until the LSB is cleared.
+ 		 * The EEPROM will signal that the command has been completed
+ 		 * by clearing bit 0 of the internal status register.  If it's
+-		 * not cleared within 'timeout', then error out. */
++		 * not cleared within 'timeout', then error out.
++		 */
+ 		while (timeout) {
+ 			e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
+ 						 hw->nvm.opcode_bits);
+@@ -1852,62 +1895,6 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
+ }
+ 
+ /**
+- *  e1000e_read_nvm_spi - Reads EEPROM using SPI
+- *  @hw: pointer to the HW structure
+- *  @offset: offset of word in the EEPROM to read
+- *  @words: number of words to read
+- *  @data: word read from the EEPROM
+- *
+- *  Reads a 16 bit word from the EEPROM.
+- **/
+-s32 e1000e_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+-{
+-	struct e1000_nvm_info *nvm = &hw->nvm;
+-	u32 i = 0;
+-	s32 ret_val;
+-	u16 word_in;
+-	u8 read_opcode = NVM_READ_OPCODE_SPI;
+-
+-	/* A check for invalid values:  offset too large, too many words,
+-	 * and not enough words. */
+-	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+-	    (words == 0)) {
+-		hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+-		return -E1000_ERR_NVM;
+-	}
+-
+-	ret_val = nvm->ops.acquire_nvm(hw);
+-	if (ret_val)
+-		return ret_val;
+-
+-	ret_val = e1000_ready_nvm_eeprom(hw);
+-	if (ret_val) {
+-		nvm->ops.release_nvm(hw);
+-		return ret_val;
+-	}
+-
+-	e1000_standby_nvm(hw);
+-
+-	if ((nvm->address_bits == 8) && (offset >= 128))
+-		read_opcode |= NVM_A8_OPCODE_SPI;
+-
+-	/* Send the READ command (opcode + addr) */
+-	e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
+-	e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
+-
+-	/* Read the data.  SPI NVMs increment the address with each byte
+-	 * read and will roll over if reading beyond the end.  This allows
+-	 * us to read the whole NVM from any offset */
+-	for (i = 0; i < words; i++) {
+-		word_in = e1000_shift_in_eec_bits(hw, 16);
+-		data[i] = (word_in >> 8) | (word_in << 8);
+-	}
+-
+-	nvm->ops.release_nvm(hw);
+-	return 0;
+-}
+-
+-/**
+  *  e1000e_read_nvm_eerd - Reads EEPROM using EERD register
+  *  @hw: pointer to the HW structure
+  *  @offset: offset of word in the EEPROM to read
+@@ -1922,8 +1909,10 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+ 	u32 i, eerd = 0;
+ 	s32 ret_val = 0;
+ 
+-	/* A check for invalid values:  offset too large, too many words,
+-	 * and not enough words. */
++	/*
++	 * A check for invalid values:  offset too large, too many words,
++	 * too many words for the offset, and not enough words.
++	 */
+ 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+ 	    (words == 0)) {
+ 		hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+@@ -1939,8 +1928,7 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+ 		if (ret_val)
+ 			break;
+ 
+-		data[i] = (er32(EERD) >>
+-			   E1000_NVM_RW_REG_DATA);
++		data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
+ 	}
+ 
+ 	return ret_val;
+@@ -1964,8 +1952,10 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+ 	s32 ret_val;
+ 	u16 widx = 0;
+ 
+-	/* A check for invalid values:  offset too large, too many words,
+-	 * and not enough words. */
++	/*
++	 * A check for invalid values:  offset too large, too many words,
++	 * and not enough words.
++	 */
+ 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+ 	    (words == 0)) {
+ 		hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+@@ -1995,8 +1985,10 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+ 
+ 		e1000_standby_nvm(hw);
+ 
+-		/* Some SPI eeproms use the 8th address bit embedded in the
+-		 * opcode */
++		/*
++		 * Some SPI eeproms use the 8th address bit embedded in the
++		 * opcode
++		 */
+ 		if ((nvm->address_bits == 8) && (offset >= 128))
+ 			write_opcode |= NVM_A8_OPCODE_SPI;
+ 
+@@ -2041,9 +2033,9 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
+ 		/* Check for an alternate MAC address.  An alternate MAC
+ 		 * address can be setup by pre-boot software and must be
+ 		 * treated like a permanent address and must override the
+-		 * actual permanent MAC address. */
++		 * actual permanent MAC address.*/
+ 		ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
+-						&mac_addr_offset);
++					 &mac_addr_offset);
+ 		if (ret_val) {
+ 			hw_dbg(hw, "NVM Read Error\n");
+ 			return ret_val;
+@@ -2056,7 +2048,7 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
+ 				mac_addr_offset += ETH_ALEN/sizeof(u16);
+ 
+ 			/* make sure we have a valid mac address here
+-			 * before using it */
++			* before using it */
+ 			ret_val = e1000_read_nvm(hw, mac_addr_offset, 1,
+ 						 &nvm_data);
+ 			if (ret_val) {
+@@ -2068,7 +2060,7 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
+ 		}
+ 
+ 		if (mac_addr_offset)
+-			hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
++		hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
+ 	}
+ 
+ 	for (i = 0; i < ETH_ALEN; i += 2) {
+@@ -2244,7 +2236,7 @@ bool e1000e_check_mng_mode(struct e1000_hw *hw)
+ }
+ 
+ /**
+- *  e1000e_enable_tx_pkt_filtering - Enable packet filtering on TX
++ *  e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx
+  *  @hw: pointer to the HW structure
+  *
+  *  Enables packet filtering on transmit packets if manageability is enabled
+@@ -2264,7 +2256,8 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ 		return 0;
+ 	}
+ 
+-	/* If we can't read from the host interface for whatever
++	/*
++	 * If we can't read from the host interface for whatever
+ 	 * reason, disable filtering.
+ 	 */
+ 	ret_val = e1000_mng_enable_host_if(hw);
+@@ -2282,7 +2275,8 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ 	hdr->checksum = 0;
+ 	csum = e1000_calculate_checksum((u8 *)hdr,
+ 					E1000_MNG_DHCP_COOKIE_LENGTH);
+-	/* If either the checksums or signature don't match, then
++	/*
++	 * If either the checksums or signature don't match, then
+ 	 * the cookie area isn't considered valid, in which case we
+ 	 * take the safe route of assuming Tx filtering is enabled.
+ 	 */
+@@ -2374,8 +2368,10 @@ static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
+ 	/* Calculate length in DWORDs */
+ 	length >>= 2;
+ 
+-	/* The device driver writes the relevant command block into the
+-	 * ram area. */
++	/*
++	 * The device driver writes the relevant command block into the
++	 * ram area.
++	 */
+ 	for (i = 0; i < length; i++) {
+ 		for (j = 0; j < sizeof(u32); j++) {
+ 			*(tmp + j) = *bufptr++;
+@@ -2481,7 +2477,7 @@ bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
+ 	return ret_val;
+ }
+ 
+-s32 e1000e_read_part_num(struct e1000_hw *hw, u32 *part_num)
++s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
+ {
+ 	s32 ret_val;
+ 	u16 nvm_data;
+@@ -2491,14 +2487,14 @@ s32 e1000e_read_part_num(struct e1000_hw *hw, u32 *part_num)
+ 		hw_dbg(hw, "NVM Read Error\n");
+ 		return ret_val;
+ 	}
+-	*part_num = (u32)(nvm_data << 16);
++	*pba_num = (u32)(nvm_data << 16);
+ 
+ 	ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
+ 	if (ret_val) {
+ 		hw_dbg(hw, "NVM Read Error\n");
+ 		return ret_val;
+ 	}
+-	*part_num |= nvm_data;
++	*pba_num |= nvm_data;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
+index fc5c63f..8991ab8 100644
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -46,7 +46,7 @@
+ 
+ #include "e1000.h"
+ 
+-#define DRV_VERSION "0.2.0"
++#define DRV_VERSION "0.2.1"
+ char e1000e_driver_name[] = "e1000e";
+ const char e1000e_driver_version[] = DRV_VERSION;
+ 
+@@ -82,7 +82,7 @@ static int e1000_desc_unused(struct e1000_ring *ring)
+ }
+ 
+ /**
+- * e1000_receive_skb - helper function to handle rx indications
++ * e1000_receive_skb - helper function to handle Rx indications
+  * @adapter: board private structure
+  * @status: descriptor status field as written by hardware
+  * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
+@@ -138,8 +138,9 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
+ 		/* TCP checksum is good */
+ 		skb->ip_summed = CHECKSUM_UNNECESSARY;
+ 	} else {
+-		/* IP fragment with UDP payload */
+-		/* Hardware complements the payload checksum, so we undo it
++		/*
++		 * IP fragment with UDP payload
++		 * Hardware complements the payload checksum, so we undo it
+ 		 * and then put the value in host order for further stack use.
+ 		 */
+ 		__sum16 sum = (__force __sum16)htons(csum);
+@@ -182,7 +183,8 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ 			break;
+ 		}
+ 
+-		/* Make buffer alignment 2 beyond a 16 byte boundary
++		/*
++		 * Make buffer alignment 2 beyond a 16 byte boundary
+ 		 * this will result in a 16 byte aligned IP header after
+ 		 * the 14 byte MAC header is removed
+ 		 */
+@@ -213,10 +215,12 @@ map_skb:
+ 		if (i-- == 0)
+ 			i = (rx_ring->count - 1);
+ 
+-		/* Force memory writes to complete before letting h/w
++		/*
++		 * Force memory writes to complete before letting h/w
+ 		 * know there are new descriptors to fetch.  (Only
+ 		 * applicable for weak-ordered memory model archs,
+-		 * such as IA-64). */
++		 * such as IA-64).
++		 */
+ 		wmb();
+ 		writel(i, adapter->hw.hw_addr + rx_ring->tail);
+ 	}
+@@ -285,7 +289,8 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+ 			break;
+ 		}
+ 
+-		/* Make buffer alignment 2 beyond a 16 byte boundary
++		/*
++		 * Make buffer alignment 2 beyond a 16 byte boundary
+ 		 * this will result in a 16 byte aligned IP header after
+ 		 * the 14 byte MAC header is removed
+ 		 */
+@@ -319,12 +324,15 @@ no_buffers:
+ 		if (!(i--))
+ 			i = (rx_ring->count - 1);
+ 
+-		/* Force memory writes to complete before letting h/w
++		/*
++		 * Force memory writes to complete before letting h/w
+ 		 * know there are new descriptors to fetch.  (Only
+ 		 * applicable for weak-ordered memory model archs,
+-		 * such as IA-64). */
++		 * such as IA-64).
++		 */
+ 		wmb();
+-		/* Hardware increments by 16 bytes, but packet split
++		/*
++		 * Hardware increments by 16 bytes, but packet split
+ 		 * descriptors are 32 bytes...so we increment tail
+ 		 * twice as much.
+ 		 */
+@@ -409,9 +417,11 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ 		total_rx_bytes += length;
+ 		total_rx_packets++;
+ 
+-		/* code added for copybreak, this should improve
++		/*
++		 * code added for copybreak, this should improve
+ 		 * performance for small packets with large amounts
+-		 * of reassembly being done in the stack */
++		 * of reassembly being done in the stack
++		 */
+ 		if (length < copybreak) {
+ 			struct sk_buff *new_skb =
+ 			    netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
+@@ -456,10 +466,10 @@ next_desc:
+ 	if (cleaned_count)
+ 		adapter->alloc_rx_buf(adapter, cleaned_count);
+ 
+-	adapter->total_rx_packets += total_rx_packets;
+ 	adapter->total_rx_bytes += total_rx_bytes;
+-	adapter->net_stats.rx_packets += total_rx_packets;
++	adapter->total_rx_packets += total_rx_packets;
+ 	adapter->net_stats.rx_bytes += total_rx_bytes;
++	adapter->net_stats.rx_packets += total_rx_packets;
+ 	return cleaned;
+ }
+ 
+@@ -581,22 +591,23 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
+ 	}
+ 
+ 	if (adapter->detect_tx_hung) {
+-		/* Detect a transmit hang in hardware, this serializes the
+-		 * check with the clearing of time_stamp and movement of i */
++		/*
++		 * Detect a transmit hang in hardware, this serializes the
++		 * check with the clearing of time_stamp and movement of i
++		 */
+ 		adapter->detect_tx_hung = 0;
+ 		if (tx_ring->buffer_info[eop].dma &&
+ 		    time_after(jiffies, tx_ring->buffer_info[eop].time_stamp
+ 			       + (adapter->tx_timeout_factor * HZ))
+-		    && !(er32(STATUS) &
+-			 E1000_STATUS_TXOFF)) {
++		    && !(er32(STATUS) & E1000_STATUS_TXOFF)) {
+ 			e1000_print_tx_hang(adapter);
+ 			netif_stop_queue(netdev);
+ 		}
+ 	}
+ 	adapter->total_tx_bytes += total_tx_bytes;
+ 	adapter->total_tx_packets += total_tx_packets;
+-	adapter->net_stats.tx_packets += total_tx_packets;
+ 	adapter->net_stats.tx_bytes += total_tx_bytes;
++	adapter->net_stats.tx_packets += total_tx_packets;
+ 	return cleaned;
+ }
+ 
+@@ -677,21 +688,28 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ 		skb_put(skb, length);
+ 
+ 		{
+-		/* this looks ugly, but it seems compiler issues make it
+-		   more efficient than reusing j */
++		/*
++		 * this looks ugly, but it seems compiler issues make it
++		 * more efficient than reusing j
++		 */
+ 		int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
+ 
+-		/* page alloc/put takes too long and effects small packet
+-		 * throughput, so unsplit small packets and save the alloc/put*/
++		/*
++		 * page alloc/put takes too long and effects small packet
++		 * throughput, so unsplit small packets and save the alloc/put
++		 * only valid in softirq (napi) context to call kmap_*
++		 */
+ 		if (l1 && (l1 <= copybreak) &&
+ 		    ((length + l1) <= adapter->rx_ps_bsize0)) {
+ 			u8 *vaddr;
+ 
+ 			ps_page = &buffer_info->ps_pages[0];
+ 
+-			/* there is no documentation about how to call
++			/*
++			 * there is no documentation about how to call
+ 			 * kmap_atomic, so we can't hold the mapping
+-			 * very long */
++			 * very long
++			 */
+ 			pci_dma_sync_single_for_cpu(pdev, ps_page->dma,
+ 				PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ 			vaddr = kmap_atomic(ps_page->page, KM_SKB_DATA_SOFTIRQ);
+@@ -757,10 +775,10 @@ next_desc:
+ 	if (cleaned_count)
+ 		adapter->alloc_rx_buf(adapter, cleaned_count);
+ 
+-	adapter->total_rx_packets += total_rx_packets;
+ 	adapter->total_rx_bytes += total_rx_bytes;
+-	adapter->net_stats.rx_packets += total_rx_packets;
++	adapter->total_rx_packets += total_rx_packets;
+ 	adapter->net_stats.rx_bytes += total_rx_bytes;
++	adapter->net_stats.rx_packets += total_rx_packets;
+ 	return cleaned;
+ }
+ 
+@@ -836,26 +854,31 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 icr = er32(ICR);
+ 
+-	/* read ICR disables interrupts using IAM, so keep up with our
+-	 * enable/disable accounting */
+-	atomic_inc(&adapter->irq_sem);
++	/*
++	 * read ICR disables interrupts using IAM
++	 */
+ 
+ 	if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ 		hw->mac.get_link_status = 1;
+-		/* ICH8 workaround-- Call gig speed drop workaround on cable
+-		 * disconnect (LSC) before accessing any PHY registers */
++		/*
++		 * ICH8 workaround-- Call gig speed drop workaround on cable
++		 * disconnect (LSC) before accessing any PHY registers
++		 */
+ 		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
+ 		    (!(er32(STATUS) & E1000_STATUS_LU)))
+ 			e1000e_gig_downshift_workaround_ich8lan(hw);
+ 
+-		/* 80003ES2LAN workaround-- For packet buffer work-around on
++		/*
++		 * 80003ES2LAN workaround-- For packet buffer work-around on
+ 		 * link down event; disable receives here in the ISR and reset
+-		 * adapter in watchdog */
++		 * adapter in watchdog
++		 */
+ 		if (netif_carrier_ok(netdev) &&
+ 		    adapter->flags & FLAG_RX_NEEDS_RESTART) {
+ 			/* disable receives */
+ 			u32 rctl = er32(RCTL);
+ 			ew32(RCTL, rctl & ~E1000_RCTL_EN);
++			adapter->flags |= FLAG_RX_RESTART_NOW;
+ 		}
+ 		/* guard against interrupt when we're going down */
+ 		if (!test_bit(__E1000_DOWN, &adapter->state))
+@@ -868,8 +891,6 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
+ 		adapter->total_rx_bytes = 0;
+ 		adapter->total_rx_packets = 0;
+ 		__netif_rx_schedule(netdev, &adapter->napi);
+-	} else {
+-		atomic_dec(&adapter->irq_sem);
+ 	}
+ 
+ 	return IRQ_HANDLED;
+@@ -890,26 +911,31 @@ static irqreturn_t e1000_intr(int irq, void *data)
+ 	if (!icr)
+ 		return IRQ_NONE;  /* Not our interrupt */
+ 
+-	/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
+-	 * not set, then the adapter didn't send an interrupt */
++	/*
++	 * IMS will not auto-mask if INT_ASSERTED is not set, and if it is
++	 * not set, then the adapter didn't send an interrupt
++	 */
+ 	if (!(icr & E1000_ICR_INT_ASSERTED))
+ 		return IRQ_NONE;
+ 
+-	/* Interrupt Auto-Mask...upon reading ICR,
++	/*
++	 * Interrupt Auto-Mask...upon reading ICR,
+ 	 * interrupts are masked.  No need for the
+-	 * IMC write, but it does mean we should
+-	 * account for it ASAP. */
+-	atomic_inc(&adapter->irq_sem);
++	 * IMC write
++	 */
+ 
+ 	if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ 		hw->mac.get_link_status = 1;
+-		/* ICH8 workaround-- Call gig speed drop workaround on cable
+-		 * disconnect (LSC) before accessing any PHY registers */
++		/*
++		 * ICH8 workaround-- Call gig speed drop workaround on cable
++		 * disconnect (LSC) before accessing any PHY registers
++		 */
+ 		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
+ 		    (!(er32(STATUS) & E1000_STATUS_LU)))
+ 			e1000e_gig_downshift_workaround_ich8lan(hw);
+ 
+-		/* 80003ES2LAN workaround--
++		/*
++		 * 80003ES2LAN workaround--
+ 		 * For packet buffer work-around on link down event;
+ 		 * disable receives here in the ISR and
+ 		 * reset adapter in watchdog
+@@ -919,6 +945,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
+ 			/* disable receives */
+ 			rctl = er32(RCTL);
+ 			ew32(RCTL, rctl & ~E1000_RCTL_EN);
++			adapter->flags |= FLAG_RX_RESTART_NOW;
+ 		}
+ 		/* guard against interrupt when we're going down */
+ 		if (!test_bit(__E1000_DOWN, &adapter->state))
+@@ -931,8 +958,6 @@ static irqreturn_t e1000_intr(int irq, void *data)
+ 		adapter->total_rx_bytes = 0;
+ 		adapter->total_rx_packets = 0;
+ 		__netif_rx_schedule(netdev, &adapter->napi);
+-	} else {
+-		atomic_dec(&adapter->irq_sem);
+ 	}
+ 
+ 	return IRQ_HANDLED;
+@@ -983,7 +1008,6 @@ static void e1000_irq_disable(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+ 
+-	atomic_inc(&adapter->irq_sem);
+ 	ew32(IMC, ~0);
+ 	e1e_flush();
+ 	synchronize_irq(adapter->pdev->irq);
+@@ -996,10 +1020,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+ 
+-	if (atomic_dec_and_test(&adapter->irq_sem)) {
+-		ew32(IMS, IMS_ENABLE_MASK);
+-		e1e_flush();
+-	}
++	ew32(IMS, IMS_ENABLE_MASK);
++	e1e_flush();
+ }
+ 
+ /**
+@@ -1023,8 +1045,7 @@ static void e1000_get_hw_control(struct e1000_adapter *adapter)
+ 		ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD);
+ 	} else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) {
+ 		ctrl_ext = er32(CTRL_EXT);
+-		ew32(CTRL_EXT,
+-				ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
++		ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+ 	}
+ }
+ 
+@@ -1050,8 +1071,7 @@ static void e1000_release_hw_control(struct e1000_adapter *adapter)
+ 		ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD);
+ 	} else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) {
+ 		ctrl_ext = er32(CTRL_EXT);
+-		ew32(CTRL_EXT,
+-				ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
++		ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+ 	}
+ }
+ 
+@@ -1353,9 +1373,11 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
+ 
+ set_itr_now:
+ 	if (new_itr != adapter->itr) {
+-		/* this attempts to bias the interrupt rate towards Bulk
++		/*
++		 * this attempts to bias the interrupt rate towards Bulk
+ 		 * by adding intermediate steps when interrupt rate is
+-		 * increasing */
++		 * increasing
++		 */
+ 		new_itr = new_itr > adapter->itr ?
+ 			     min(adapter->itr + (new_itr >> 2), new_itr) :
+ 			     new_itr;
+@@ -1366,7 +1388,7 @@ set_itr_now:
+ 
+ /**
+  * e1000_clean - NAPI Rx polling callback
+- * @adapter: board private structure
++ * @napi: struct associated with this polling callback
+  * @budget: amount of packets driver is allowed to process this poll
+  **/
+ static int e1000_clean(struct napi_struct *napi, int budget)
+@@ -1378,10 +1400,12 @@ static int e1000_clean(struct napi_struct *napi, int budget)
+ 	/* Must NOT use netdev_priv macro here. */
+ 	adapter = poll_dev->priv;
+ 
+-	/* e1000_clean is called per-cpu.  This lock protects
++	/*
++	 * e1000_clean is called per-cpu.  This lock protects
+ 	 * tx_ring from being cleaned by multiple cpus
+ 	 * simultaneously.  A failure obtaining the lock means
+-	 * tx_ring is currently being cleaned anyway. */
++	 * tx_ring is currently being cleaned anyway.
++	 */
+ 	if (spin_trylock(&adapter->tx_queue_lock)) {
+ 		tx_cleaned = e1000_clean_tx_irq(adapter);
+ 		spin_unlock(&adapter->tx_queue_lock);
+@@ -1427,9 +1451,12 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 vfta, index;
+ 
+-	e1000_irq_disable(adapter);
++	if (!test_bit(__E1000_DOWN, &adapter->state))
++		e1000_irq_disable(adapter);
+ 	vlan_group_set_device(adapter->vlgrp, vid, NULL);
+-	e1000_irq_enable(adapter);
++
++	if (!test_bit(__E1000_DOWN, &adapter->state))
++		e1000_irq_enable(adapter);
+ 
+ 	if ((adapter->hw.mng_cookie.status &
+ 	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
+@@ -1480,7 +1507,8 @@ static void e1000_vlan_rx_register(struct net_device *netdev,
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 ctrl, rctl;
+ 
+-	e1000_irq_disable(adapter);
++	if (!test_bit(__E1000_DOWN, &adapter->state))
++		e1000_irq_disable(adapter);
+ 	adapter->vlgrp = grp;
+ 
+ 	if (grp) {
+@@ -1517,7 +1545,8 @@ static void e1000_vlan_rx_register(struct net_device *netdev,
+ 		}
+ 	}
+ 
+-	e1000_irq_enable(adapter);
++	if (!test_bit(__E1000_DOWN, &adapter->state))
++		e1000_irq_enable(adapter);
+ }
+ 
+ static void e1000_restore_vlan(struct e1000_adapter *adapter)
+@@ -1546,9 +1575,11 @@ static void e1000_init_manageability(struct e1000_adapter *adapter)
+ 
+ 	manc = er32(MANC);
+ 
+-	/* enable receiving management packets to the host. this will probably
++	/*
++	 * enable receiving management packets to the host. this will probably
+ 	 * generate destination unreachable messages from the host OS, but
+-	 * the packets will be handled on SMBUS */
++	 * the packets will be handled on SMBUS
++	 */
+ 	manc |= E1000_MANC_EN_MNG2HOST;
+ 	manc2h = er32(MANC2H);
+ #define E1000_MNG2HOST_PORT_623 (1 << 5)
+@@ -1598,7 +1629,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
+ 
+ 	/* Set the Tx Interrupt Delay register */
+ 	ew32(TIDV, adapter->tx_int_delay);
+-	/* tx irq moderation */
++	/* Tx irq moderation */
+ 	ew32(TADV, adapter->tx_abs_int_delay);
+ 
+ 	/* Program the Transmit Control Register */
+@@ -1608,22 +1639,24 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
+ 		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+ 
+ 	if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) {
+-		tarc = er32(TARC0);
+-		/* set the speed mode bit, we'll clear it if we're not at
+-		 * gigabit link later */
++		tarc = er32(TARC(0));
++		/*
++		 * set the speed mode bit, we'll clear it if we're not at
++		 * gigabit link later
++		 */
+ #define SPEED_MODE_BIT (1 << 21)
+ 		tarc |= SPEED_MODE_BIT;
+-		ew32(TARC0, tarc);
++		ew32(TARC(0), tarc);
+ 	}
+ 
+ 	/* errata: program both queues to unweighted RR */
+ 	if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) {
+-		tarc = er32(TARC0);
++		tarc = er32(TARC(0));
+ 		tarc |= 1;
+-		ew32(TARC0, tarc);
+-		tarc = er32(TARC1);
++		ew32(TARC(0), tarc);
++		tarc = er32(TARC(1));
+ 		tarc |= 1;
+-		ew32(TARC1, tarc);
++		ew32(TARC(1), tarc);
+ 	}
+ 
+ 	e1000e_config_collision_dist(hw);
+@@ -1731,8 +1764,10 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
+ 		/* Configure extra packet-split registers */
+ 		rfctl = er32(RFCTL);
+ 		rfctl |= E1000_RFCTL_EXTEN;
+-		/* disable packet split support for IPv6 extension headers,
+-		 * because some malformed IPv6 headers can hang the RX */
++		/*
++		 * disable packet split support for IPv6 extension headers,
++		 * because some malformed IPv6 headers can hang the Rx
++		 */
+ 		rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
+ 			  E1000_RFCTL_NEW_IPV6_EXT_DIS);
+ 
+@@ -1761,6 +1796,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
+ 	}
+ 
+ 	ew32(RCTL, rctl);
++	/* just started the receive unit, no need to restart */
++	adapter->flags &= ~FLAG_RX_RESTART_NOW;
+ }
+ 
+ /**
+@@ -1801,8 +1838,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ 	/* irq moderation */
+ 	ew32(RADV, adapter->rx_abs_int_delay);
+ 	if (adapter->itr_setting != 0)
+-		ew32(ITR,
+-			1000000000 / (adapter->itr * 256));
++		ew32(ITR, 1000000000 / (adapter->itr * 256));
+ 
+ 	ctrl_ext = er32(CTRL_EXT);
+ 	/* Reset delay timers after every interrupt */
+@@ -1813,8 +1849,10 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ 	ew32(CTRL_EXT, ctrl_ext);
+ 	e1e_flush();
+ 
+-	/* Setup the HW Rx Head and Tail Descriptor Pointers and
+-	 * the Base and Length of the Rx Descriptor Ring */
++	/*
++	 * Setup the HW Rx Head and Tail Descriptor Pointers and
++	 * the Base and Length of the Rx Descriptor Ring
++	 */
+ 	rdba = rx_ring->dma;
+ 	ew32(RDBAL, (rdba & DMA_32BIT_MASK));
+ 	ew32(RDBAH, (rdba >> 32));
+@@ -1829,8 +1867,10 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ 	if (adapter->flags & FLAG_RX_CSUM_ENABLED) {
+ 		rxcsum |= E1000_RXCSUM_TUOFL;
+ 
+-		/* IPv4 payload checksum for UDP fragments must be
+-		 * used in conjunction with packet-split. */
++		/*
++		 * IPv4 payload checksum for UDP fragments must be
++		 * used in conjunction with packet-split.
++		 */
+ 		if (adapter->rx_ps_pages)
+ 			rxcsum |= E1000_RXCSUM_IPPCSE;
+ 	} else {
+@@ -1839,9 +1879,11 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ 	}
+ 	ew32(RXCSUM, rxcsum);
+ 
+-	/* Enable early receives on supported devices, only takes effect when
++	/*
++	 * Enable early receives on supported devices, only takes effect when
+ 	 * 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 */
++	 * units), e.g. using jumbo frames when setting to E1000_ERT_2048
++	 */
+ 	if ((adapter->flags & FLAG_HAS_ERT) &&
+ 	    (adapter->netdev->mtu > ETH_DATA_LEN))
+ 		ew32(ERT, E1000_ERT_2048);
+@@ -1851,7 +1893,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ }
+ 
+ /**
+- *  e1000_mc_addr_list_update - Update Multicast addresses
++ *  e1000_update_mc_addr_list - 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
+@@ -1865,11 +1907,11 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+  *  exists and all implementations are handled in the generic version of this
+  *  function.
+  **/
+-static void e1000_mc_addr_list_update(struct e1000_hw *hw, u8 *mc_addr_list,
+-			       u32 mc_addr_count, u32 rar_used_count,
+-			       u32 rar_count)
++static void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
++				      u32 mc_addr_count, u32 rar_used_count,
++				      u32 rar_count)
+ {
+-	hw->mac.ops.mc_addr_list_update(hw, mc_addr_list, mc_addr_count,
++	hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count,
+ 				        rar_used_count, rar_count);
+ }
+ 
+@@ -1923,7 +1965,7 @@ static void e1000_set_multi(struct net_device *netdev)
+ 			mc_ptr = mc_ptr->next;
+ 		}
+ 
+-		e1000_mc_addr_list_update(hw, mta_list, i, 1,
++		e1000_update_mc_addr_list(hw, mta_list, i, 1,
+ 					  mac->rar_entry_count);
+ 		kfree(mta_list);
+ 	} else {
+@@ -1931,13 +1973,12 @@ static void e1000_set_multi(struct net_device *netdev)
+ 		 * if we're called from probe, we might not have
+ 		 * anything to do here, so clear out the list
+ 		 */
+-		e1000_mc_addr_list_update(hw, NULL, 0, 1,
+-					  mac->rar_entry_count);
++		e1000_update_mc_addr_list(hw, NULL, 0, 1, mac->rar_entry_count);
+ 	}
+ }
+ 
+ /**
+- * e1000_configure - configure the hardware for RX and TX
++ * e1000_configure - configure the hardware for Rx and Tx
+  * @adapter: private board structure
+  **/
+ static void e1000_configure(struct e1000_adapter *adapter)
+@@ -1950,8 +1991,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
+ 	e1000_configure_tx(adapter);
+ 	e1000_setup_rctl(adapter);
+ 	e1000_configure_rx(adapter);
+-	adapter->alloc_rx_buf(adapter,
+-			      e1000_desc_unused(adapter->rx_ring));
++	adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring));
+ }
+ 
+ /**
+@@ -1967,9 +2007,11 @@ void e1000e_power_up_phy(struct e1000_adapter *adapter)
+ 	u16 mii_reg = 0;
+ 
+ 	/* Just clear the power down bit to wake the phy back up */
+-	if (adapter->hw.media_type == e1000_media_type_copper) {
+-		/* according to the manual, the phy will retain its
+-		 * settings across a power-down/up cycle */
++	if (adapter->hw.phy.media_type == e1000_media_type_copper) {
++		/*
++		 * According to the manual, the phy will retain its
++		 * settings across a power-down/up cycle
++		 */
+ 		e1e_rphy(&adapter->hw, PHY_CONTROL, &mii_reg);
+ 		mii_reg &= ~MII_CR_POWER_DOWN;
+ 		e1e_wphy(&adapter->hw, PHY_CONTROL, mii_reg);
+@@ -1994,12 +2036,11 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter)
+ 		return;
+ 
+ 	/* non-copper PHY? */
+-	if (adapter->hw.media_type != e1000_media_type_copper)
++	if (adapter->hw.phy.media_type != e1000_media_type_copper)
+ 		return;
+ 
+ 	/* reset is blocked because of a SoL/IDER session */
+-	if (e1000e_check_mng_mode(hw) ||
+-	    e1000_check_reset_block(hw))
++	if (e1000e_check_mng_mode(hw) || e1000_check_reset_block(hw))
+ 		return;
+ 
+ 	/* manageability (AMT) is enabled */
+@@ -2019,51 +2060,61 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter)
+  * This function boots the hardware and enables some settings that
+  * require a configuration cycle of the hardware - those cannot be
+  * set/changed during runtime. After reset the device needs to be
+- * properly configured for rx, tx etc.
++ * properly configured for Rx, Tx etc.
+  */
+ void e1000e_reset(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_mac_info *mac = &adapter->hw.mac;
++	struct e1000_fc_info *fc = &adapter->hw.fc;
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 tx_space, min_tx_space, min_rx_space;
+-	u32 pba;
++	u32 pba = adapter->pba;
+ 	u16 hwm;
+ 
+-	ew32(PBA, adapter->pba);
++	/* reset Packet Buffer Allocation to default */
++	ew32(PBA, pba);
+ 
+-	if (mac->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN ) {
+-		/* To maintain wire speed transmits, the Tx FIFO should be
++	if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) {
++		/*
++		 * To maintain wire speed transmits, the Tx FIFO should be
+ 		 * large enough to accommodate two full transmit packets,
+ 		 * rounded up to the next 1KB and expressed in KB.  Likewise,
+ 		 * the Rx FIFO should be large enough to accommodate at least
+ 		 * one full receive packet and is similarly rounded up and
+-		 * expressed in KB. */
++		 * expressed in KB.
++		 */
+ 		pba = er32(PBA);
+ 		/* upper 16 bits has Tx packet buffer allocation size in KB */
+ 		tx_space = pba >> 16;
+ 		/* lower 16 bits has Rx packet buffer allocation size in KB */
+ 		pba &= 0xffff;
+-		/* the tx fifo also stores 16 bytes of information about the tx
+-		 * but don't include ethernet FCS because hardware appends it */
+-		min_tx_space = (mac->max_frame_size +
++		/*
++		 * the Tx fifo also stores 16 bytes of information about the tx
++		 * but don't include ethernet FCS because hardware appends it
++		 */
++		min_tx_space = (adapter->max_frame_size +
+ 				sizeof(struct e1000_tx_desc) -
+ 				ETH_FCS_LEN) * 2;
+ 		min_tx_space = ALIGN(min_tx_space, 1024);
+ 		min_tx_space >>= 10;
+ 		/* software strips receive CRC, so leave room for it */
+-		min_rx_space = mac->max_frame_size;
++		min_rx_space = adapter->max_frame_size;
+ 		min_rx_space = ALIGN(min_rx_space, 1024);
+ 		min_rx_space >>= 10;
+ 
+-		/* If current Tx allocation is less than the min Tx FIFO size,
++		/*
++		 * If current Tx allocation is less than the min Tx FIFO size,
+ 		 * and the min Tx FIFO size is less than the current Rx FIFO
+-		 * allocation, take space away from current Rx allocation */
++		 * allocation, take space away from current Rx allocation
++		 */
+ 		if ((tx_space < min_tx_space) &&
+ 		    ((min_tx_space - tx_space) < pba)) {
+ 			pba -= min_tx_space - tx_space;
+ 
+-			/* if short on rx space, rx wins and must trump tx
+-			 * adjustment or use Early Receive if available */
++			/*
++			 * if short on Rx space, Rx wins and must trump tx
++			 * adjustment or use Early Receive if available
++			 */
+ 			if ((pba < min_rx_space) &&
+ 			    (!(adapter->flags & FLAG_HAS_ERT)))
+ 				/* ERT enabled in e1000_configure_rx */
+@@ -2074,29 +2125,33 @@ void e1000e_reset(struct e1000_adapter *adapter)
+ 	}
+ 
+ 
+-	/* flow control settings */
+-	/* The high water mark must be low enough to fit one full frame
++	/*
++	 * flow control settings
++	 *
++	 * The high water mark must be low enough to fit one full frame
+ 	 * (or the size used for early receive) above it in the Rx FIFO.
+ 	 * Set it to the lower of:
+ 	 * - 90% of the Rx FIFO size, and
+ 	 * - the full Rx FIFO size minus the early receive size (for parts
+ 	 *   with ERT support assuming ERT set to E1000_ERT_2048), or
+-	 * - the full Rx FIFO size minus one full frame */
++	 * - the full Rx FIFO size minus one full frame
++	 */
+ 	if (adapter->flags & FLAG_HAS_ERT)
+-		hwm = min(((adapter->pba << 10) * 9 / 10),
+-			  ((adapter->pba << 10) - (E1000_ERT_2048 << 3)));
++		hwm = min(((pba << 10) * 9 / 10),
++			  ((pba << 10) - (E1000_ERT_2048 << 3)));
+ 	else
+-		hwm = min(((adapter->pba << 10) * 9 / 10),
+-			  ((adapter->pba << 10) - mac->max_frame_size));
++		hwm = min(((pba << 10) * 9 / 10),
++			  ((pba << 10) - adapter->max_frame_size));
+ 
+-	mac->fc_high_water = hwm & 0xFFF8; /* 8-byte granularity */
+-	mac->fc_low_water = mac->fc_high_water - 8;
++	fc->high_water = hwm & 0xFFF8; /* 8-byte granularity */
++	fc->low_water = fc->high_water - 8;
+ 
+ 	if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)
+-		mac->fc_pause_time = 0xFFFF;
++		fc->pause_time = 0xFFFF;
+ 	else
+-		mac->fc_pause_time = E1000_FC_PAUSE_TIME;
+-	mac->fc = mac->original_fc;
++		fc->pause_time = E1000_FC_PAUSE_TIME;
++	fc->send_xon = 1;
++	fc->type = fc->original_type;
+ 
+ 	/* Allow time for pending master requests to run */
+ 	mac->ops.reset_hw(hw);
+@@ -2115,9 +2170,11 @@ void e1000e_reset(struct e1000_adapter *adapter)
+ 
+ 	if (!(adapter->flags & FLAG_SMART_POWER_DOWN)) {
+ 		u16 phy_data = 0;
+-		/* speed up time to link by disabling smart power down, ignore
++		/*
++		 * speed up time to link by disabling smart power down, ignore
+ 		 * the return value of this function because there is nothing
+-		 * different we would do if it failed */
++		 * different we would do if it failed
++		 */
+ 		e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
+ 		phy_data &= ~IGP02E1000_PM_SPD;
+ 		e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
+@@ -2147,8 +2204,10 @@ void e1000e_down(struct e1000_adapter *adapter)
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 tctl, rctl;
+ 
+-	/* signal that we're down so the interrupt handler does not
+-	 * reschedule our watchdog timer */
++	/*
++	 * signal that we're down so the interrupt handler does not
++	 * reschedule our watchdog timer
++	 */
+ 	set_bit(__E1000_DOWN, &adapter->state);
+ 
+ 	/* disable receives in the hardware */
+@@ -2167,7 +2226,6 @@ void e1000e_down(struct e1000_adapter *adapter)
+ 	msleep(10);
+ 
+ 	napi_disable(&adapter->napi);
+-	atomic_set(&adapter->irq_sem, 0);
+ 	e1000_irq_disable(adapter);
+ 
+ 	del_timer_sync(&adapter->watchdog_timer);
+@@ -2208,13 +2266,12 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter)
+  **/
+ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
+ {
+-	struct e1000_hw *hw = &adapter->hw;
+ 	struct net_device *netdev = adapter->netdev;
+ 
+ 	adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN;
+ 	adapter->rx_ps_bsize0 = 128;
+-	hw->mac.max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+-	hw->mac.min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
++	adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
++	adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+ 
+ 	adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ 	if (!adapter->tx_ring)
+@@ -2227,7 +2284,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
+ 	spin_lock_init(&adapter->tx_queue_lock);
+ 
+ 	/* Explicitly disable IRQ since the NIC can be in any state. */
+-	atomic_set(&adapter->irq_sem, 0);
+ 	e1000_irq_disable(adapter);
+ 
+ 	spin_lock_init(&adapter->stats_lock);
+@@ -2281,16 +2337,20 @@ static int e1000_open(struct net_device *netdev)
+ 	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
+ 		e1000_update_mng_vlan(adapter);
+ 
+-	/* If AMT is enabled, let the firmware know that the network
+-	 * interface is now open */
++	/*
++	 * If AMT is enabled, let the firmware know that the network
++	 * interface is now open
++	 */
+ 	if ((adapter->flags & FLAG_HAS_AMT) &&
+ 	    e1000e_check_mng_mode(&adapter->hw))
+ 		e1000_get_hw_control(adapter);
+ 
+-	/* before we allocate an interrupt, we must be ready to handle it.
++	/*
++	 * before we allocate an interrupt, we must be ready to handle it.
+ 	 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
+ 	 * as soon as we call pci_request_irq, so we have to setup our
+-	 * clean_rx handler before we do so.  */
++	 * clean_rx handler before we do so.
++	 */
+ 	e1000_configure(adapter);
+ 
+ 	err = e1000_request_irq(adapter);
+@@ -2344,16 +2404,20 @@ static int e1000_close(struct net_device *netdev)
+ 	e1000e_free_tx_resources(adapter);
+ 	e1000e_free_rx_resources(adapter);
+ 
+-	/* kill manageability vlan ID if supported, but not if a vlan with
+-	 * the same ID is registered on the host OS (let 8021q kill it) */
++	/*
++	 * kill manageability vlan ID if supported, but not if a vlan with
++	 * the same ID is registered on the host OS (let 8021q kill it)
++	 */
+ 	if ((adapter->hw.mng_cookie.status &
+ 			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
+ 	     !(adapter->vlgrp &&
+ 	       vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id)))
+ 		e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+ 
+-	/* If AMT is enabled, let the firmware know that the network
+-	 * interface is now closed */
++	/*
++	 * If AMT is enabled, let the firmware know that the network
++	 * interface is now closed
++	 */
+ 	if ((adapter->flags & FLAG_HAS_AMT) &&
+ 	    e1000e_check_mng_mode(&adapter->hw))
+ 		e1000_release_hw_control(adapter);
+@@ -2384,12 +2448,14 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
+ 		/* activate the work around */
+ 		e1000e_set_laa_state_82571(&adapter->hw, 1);
+ 
+-		/* Hold a copy of the LAA in RAR[14] This is done so that
++		/*
++		 * Hold a copy of the LAA in RAR[14] This is done so that
+ 		 * between the time RAR[0] gets clobbered  and the time it
+ 		 * gets fixed (in e1000_watchdog), the actual LAA is in one
+ 		 * of the RARs and no incoming packets directed to this port
+ 		 * are dropped. Eventually the LAA will be in RAR[0] and
+-		 * RAR[14] */
++		 * RAR[14]
++		 */
+ 		e1000e_rar_set(&adapter->hw,
+ 			      adapter->hw.mac.addr,
+ 			      adapter->hw.mac.rar_entry_count - 1);
+@@ -2398,8 +2464,10 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
+ 	return 0;
+ }
+ 
+-/* Need to wait a few seconds after link up to get diagnostic information from
+- * the phy */
++/*
++ * Need to wait a few seconds after link up to get diagnostic information from
++ * the phy
++ */
+ static void e1000_update_phy_info(unsigned long data)
+ {
+ 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+@@ -2430,63 +2498,35 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+ 
+ 	spin_lock_irqsave(&adapter->stats_lock, irq_flags);
+ 
+-	/* these counters are modified from e1000_adjust_tbi_stats,
++	/*
++	 * these counters are modified from e1000_adjust_tbi_stats,
+ 	 * called from the interrupt context, so they must only
+ 	 * be written while holding adapter->stats_lock
+ 	 */
+ 
+ 	adapter->stats.crcerrs += er32(CRCERRS);
+ 	adapter->stats.gprc += er32(GPRC);
+-	adapter->stats.gorcl += er32(GORCL);
+-	adapter->stats.gorch += er32(GORCH);
++	adapter->stats.gorc += er32(GORCL);
++	er32(GORCH); /* Clear gorc */
+ 	adapter->stats.bprc += er32(BPRC);
+ 	adapter->stats.mprc += er32(MPRC);
+ 	adapter->stats.roc += er32(ROC);
+ 
+-	if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) {
+-		adapter->stats.prc64 += er32(PRC64);
+-		adapter->stats.prc127 += er32(PRC127);
+-		adapter->stats.prc255 += er32(PRC255);
+-		adapter->stats.prc511 += er32(PRC511);
+-		adapter->stats.prc1023 += er32(PRC1023);
+-		adapter->stats.prc1522 += er32(PRC1522);
+-		adapter->stats.symerrs += er32(SYMERRS);
+-		adapter->stats.sec += er32(SEC);
+-	}
+-
+ 	adapter->stats.mpc += er32(MPC);
+ 	adapter->stats.scc += er32(SCC);
+ 	adapter->stats.ecol += er32(ECOL);
+ 	adapter->stats.mcc += er32(MCC);
+ 	adapter->stats.latecol += er32(LATECOL);
+ 	adapter->stats.dc += er32(DC);
+-	adapter->stats.rlec += er32(RLEC);
+ 	adapter->stats.xonrxc += er32(XONRXC);
+ 	adapter->stats.xontxc += er32(XONTXC);
+ 	adapter->stats.xoffrxc += er32(XOFFRXC);
+ 	adapter->stats.xofftxc += er32(XOFFTXC);
+-	adapter->stats.fcruc += er32(FCRUC);
+ 	adapter->stats.gptc += er32(GPTC);
+-	adapter->stats.gotcl += er32(GOTCL);
+-	adapter->stats.gotch += er32(GOTCH);
++	adapter->stats.gotc += er32(GOTCL);
++	er32(GOTCH); /* Clear gotc */
+ 	adapter->stats.rnbc += er32(RNBC);
+ 	adapter->stats.ruc += er32(RUC);
+-	adapter->stats.rfc += er32(RFC);
+-	adapter->stats.rjc += er32(RJC);
+-	adapter->stats.torl += er32(TORL);
+-	adapter->stats.torh += er32(TORH);
+-	adapter->stats.totl += er32(TOTL);
+-	adapter->stats.toth += er32(TOTH);
+-	adapter->stats.tpr += er32(TPR);
+-
+-	if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) {
+-		adapter->stats.ptc64 += er32(PTC64);
+-		adapter->stats.ptc127 += er32(PTC127);
+-		adapter->stats.ptc255 += er32(PTC255);
+-		adapter->stats.ptc511 += er32(PTC511);
+-		adapter->stats.ptc1023 += er32(PTC1023);
+-		adapter->stats.ptc1522 += er32(PTC1522);
+-	}
+ 
+ 	adapter->stats.mptc += er32(MPTC);
+ 	adapter->stats.bptc += er32(BPTC);
+@@ -2505,27 +2545,16 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+ 	adapter->stats.tsctc += er32(TSCTC);
+ 	adapter->stats.tsctfc += er32(TSCTFC);
+ 
+-	adapter->stats.iac += er32(IAC);
+-
+-	if (adapter->flags & FLAG_HAS_STATS_ICR_ICT) {
+-		adapter->stats.icrxoc += er32(ICRXOC);
+-		adapter->stats.icrxptc += er32(ICRXPTC);
+-		adapter->stats.icrxatc += er32(ICRXATC);
+-		adapter->stats.ictxptc += er32(ICTXPTC);
+-		adapter->stats.ictxatc += er32(ICTXATC);
+-		adapter->stats.ictxqec += er32(ICTXQEC);
+-		adapter->stats.ictxqmtc += er32(ICTXQMTC);
+-		adapter->stats.icrxdmtc += er32(ICRXDMTC);
+-	}
+-
+ 	/* Fill out the OS statistics structure */
+ 	adapter->net_stats.multicast = adapter->stats.mprc;
+ 	adapter->net_stats.collisions = adapter->stats.colc;
+ 
+ 	/* Rx Errors */
+ 
+-	/* RLEC on some newer hardware can be incorrect so build
+-	* our own version based on RUC and ROC */
++	/*
++	 * RLEC on some newer hardware can be incorrect so build
++	 * our own version based on RUC and ROC
++	 */
+ 	adapter->net_stats.rx_errors = adapter->stats.rxerrc +
+ 		adapter->stats.crcerrs + adapter->stats.algnerrc +
+ 		adapter->stats.ruc + adapter->stats.roc +
+@@ -2546,7 +2575,7 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+ 	/* Tx Dropped needs to be maintained elsewhere */
+ 
+ 	/* Phy Stats */
+-	if (hw->media_type == e1000_media_type_copper) {
++	if (hw->phy.media_type == e1000_media_type_copper) {
+ 		if ((adapter->link_speed == SPEED_1000) &&
+ 		   (!e1e_rphy(hw, PHY_1000T_STATUS, &phy_tmp))) {
+ 			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
+@@ -2562,10 +2591,58 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+ 	spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
+ }
+ 
++/**
++ * e1000_phy_read_status - Update the PHY register status snapshot
++ * @adapter: board private structure
++ **/
++static void e1000_phy_read_status(struct e1000_adapter *adapter)
++{
++	struct e1000_hw *hw = &adapter->hw;
++	struct e1000_phy_regs *phy = &adapter->phy_regs;
++	int ret_val;
++	unsigned long irq_flags;
++
++
++	spin_lock_irqsave(&adapter->stats_lock, irq_flags);
++
++	if ((er32(STATUS) & E1000_STATUS_LU) &&
++	    (adapter->hw.phy.media_type == e1000_media_type_copper)) {
++		ret_val  = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr);
++		ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr);
++		ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise);
++		ret_val |= e1e_rphy(hw, PHY_LP_ABILITY, &phy->lpa);
++		ret_val |= e1e_rphy(hw, PHY_AUTONEG_EXP, &phy->expansion);
++		ret_val |= e1e_rphy(hw, PHY_1000T_CTRL, &phy->ctrl1000);
++		ret_val |= e1e_rphy(hw, PHY_1000T_STATUS, &phy->stat1000);
++		ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus);
++		if (ret_val)
++			ndev_warn(adapter->netdev,
++				  "Error reading PHY register\n");
++	} else {
++		/*
++		 * Do not read PHY registers if link is not up
++		 * Set values to typical power-on defaults
++		 */
++		phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX);
++		phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL |
++			     BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE |
++			     BMSR_ERCAP);
++		phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP |
++				  ADVERTISE_ALL | ADVERTISE_CSMA);
++		phy->lpa = 0;
++		phy->expansion = EXPANSION_ENABLENPAGE;
++		phy->ctrl1000 = ADVERTISE_1000FULL;
++		phy->stat1000 = 0;
++		phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);
++	}
++
++	spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
++}
++
+ static void e1000_print_link_info(struct e1000_adapter *adapter)
+ {
+-	struct net_device *netdev = adapter->netdev;
+ 	struct e1000_hw *hw = &adapter->hw;
++	struct net_device *netdev = adapter->netdev;
+ 	u32 ctrl = er32(CTRL);
+ 
+ 	ndev_info(netdev,
+@@ -2579,6 +2656,62 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
+ 		((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
+ }
+ 
++static bool e1000_has_link(struct e1000_adapter *adapter)
++{
++	struct e1000_hw *hw = &adapter->hw;
++	bool link_active = 0;
++	s32 ret_val = 0;
++
++	/*
++	 * get_link_status is set on LSC (link status) interrupt or
++	 * Rx sequence error interrupt.  get_link_status will stay
++	 * false until the check_for_link establishes link
++	 * for copper adapters ONLY
++	 */
++	switch (hw->phy.media_type) {
++	case e1000_media_type_copper:
++		if (hw->mac.get_link_status) {
++			ret_val = hw->mac.ops.check_for_link(hw);
++			link_active = !hw->mac.get_link_status;
++		} else {
++			link_active = 1;
++		}
++		break;
++	case e1000_media_type_fiber:
++		ret_val = hw->mac.ops.check_for_link(hw);
++		link_active = !!(er32(STATUS) & E1000_STATUS_LU);
++		break;
++	case e1000_media_type_internal_serdes:
++		ret_val = hw->mac.ops.check_for_link(hw);
++		link_active = adapter->hw.mac.serdes_has_link;
++		break;
++	default:
++	case e1000_media_type_unknown:
++		break;
++	}
++
++	if ((ret_val == E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) &&
++	    (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
++		/* See e1000_kmrn_lock_loss_workaround_ich8lan() */
++		ndev_info(adapter->netdev,
++			  "Gigabit has been disabled, downgrading speed\n");
++	}
++
++	return link_active;
++}
++
++static void e1000e_enable_receives(struct e1000_adapter *adapter)
++{
++	/* make sure the receive unit is started */
++	if ((adapter->flags & FLAG_RX_NEEDS_RESTART) &&
++	    (adapter->flags & FLAG_RX_RESTART_NOW)) {
++		struct e1000_hw *hw = &adapter->hw;
++		u32 rctl = er32(RCTL);
++		ew32(RCTL, rctl | E1000_RCTL_EN);
++		adapter->flags &= ~FLAG_RX_RESTART_NOW;
++	}
++}
++
+ /**
+  * e1000_watchdog - Timer Call-back
+  * @data: pointer to adapter cast into an unsigned long
+@@ -2597,48 +2730,36 @@ static void e1000_watchdog_task(struct work_struct *work)
+ {
+ 	struct e1000_adapter *adapter = container_of(work,
+ 					struct e1000_adapter, watchdog_task);
+-
+ 	struct net_device *netdev = adapter->netdev;
+ 	struct e1000_mac_info *mac = &adapter->hw.mac;
+ 	struct e1000_ring *tx_ring = adapter->tx_ring;
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 link, tctl;
+-	s32 ret_val;
+ 	int tx_pending = 0;
+ 
+-	if ((netif_carrier_ok(netdev)) &&
+-	    (er32(STATUS) & E1000_STATUS_LU))
++	link = e1000_has_link(adapter);
++	if ((netif_carrier_ok(netdev)) && link) {
++		e1000e_enable_receives(adapter);
+ 		goto link_up;
+-
+-	ret_val = mac->ops.check_for_link(hw);
+-	if ((ret_val == E1000_ERR_PHY) &&
+-	    (adapter->hw.phy.type == e1000_phy_igp_3) &&
+-	    (er32(CTRL) &
+-	     E1000_PHY_CTRL_GBE_DISABLE)) {
+-		/* See e1000_kmrn_lock_loss_workaround_ich8lan() */
+-		ndev_info(netdev,
+-			"Gigabit has been disabled, downgrading speed\n");
+ 	}
+ 
+ 	if ((e1000e_enable_tx_pkt_filtering(hw)) &&
+ 	    (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id))
+ 		e1000_update_mng_vlan(adapter);
+ 
+-	if ((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
+-	   !(er32(TXCW) & E1000_TXCW_ANE))
+-		link = adapter->hw.mac.serdes_has_link;
+-	else
+-		link = er32(STATUS) & E1000_STATUS_LU;
+-
+ 	if (link) {
+ 		if (!netif_carrier_ok(netdev)) {
+ 			bool txb2b = 1;
++			/* update snapshot of PHY registers on LSC */
++			e1000_phy_read_status(adapter);
+ 			mac->ops.get_link_up_info(&adapter->hw,
+ 						   &adapter->link_speed,
+ 						   &adapter->link_duplex);
+ 			e1000_print_link_info(adapter);
+-			/* tweak tx_queue_len according to speed/duplex
+-			 * and adjust the timeout factor */
++			/*
++			 * tweak tx_queue_len according to speed/duplex
++			 * and adjust the timeout factor
++			 */
+ 			netdev->tx_queue_len = adapter->tx_queue_len;
+ 			adapter->tx_timeout_factor = 1;
+ 			switch (adapter->link_speed) {
+@@ -2654,18 +2775,22 @@ static void e1000_watchdog_task(struct work_struct *work)
+ 				break;
+ 			}
+ 
+-			/* workaround: re-program speed mode bit after
+-			 * link-up event */
++			/*
++			 * workaround: re-program speed mode bit after
++			 * link-up event
++			 */
+ 			if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) &&
+ 			    !txb2b) {
+ 				u32 tarc0;
+-				tarc0 = er32(TARC0);
++				tarc0 = er32(TARC(0));
+ 				tarc0 &= ~SPEED_MODE_BIT;
+-				ew32(TARC0, tarc0);
++				ew32(TARC(0), tarc0);
+ 			}
+ 
+-			/* disable TSO for pcie and 10/100 speeds, to avoid
+-			 * some hardware issues */
++			/*
++			 * disable TSO for pcie and 10/100 speeds, to avoid
++			 * some hardware issues
++			 */
+ 			if (!(adapter->flags & FLAG_TSO_FORCE)) {
+ 				switch (adapter->link_speed) {
+ 				case SPEED_10:
+@@ -2685,8 +2810,10 @@ static void e1000_watchdog_task(struct work_struct *work)
+ 				}
+ 			}
+ 
+-			/* enable transmits in the hardware, need to do this
+-			 * after setting TARC0 */
++			/*
++			 * enable transmits in the hardware, need to do this
++			 * after setting TARC(0)
++			 */
+ 			tctl = er32(TCTL);
+ 			tctl |= E1000_TCTL_EN;
+ 			ew32(TCTL, tctl);
+@@ -2697,13 +2824,6 @@ static void e1000_watchdog_task(struct work_struct *work)
+ 			if (!test_bit(__E1000_DOWN, &adapter->state))
+ 				mod_timer(&adapter->phy_info_timer,
+ 					  round_jiffies(jiffies + 2 * HZ));
+-		} else {
+-			/* make sure the receive unit is started */
+-			if (adapter->flags & FLAG_RX_NEEDS_RESTART) {
+-				u32 rctl = er32(RCTL);
+-				ew32(RCTL, rctl |
+-						E1000_RCTL_EN);
+-			}
+ 		}
+ 	} else {
+ 		if (netif_carrier_ok(netdev)) {
+@@ -2729,10 +2849,10 @@ link_up:
+ 	mac->collision_delta = adapter->stats.colc - adapter->colc_old;
+ 	adapter->colc_old = adapter->stats.colc;
+ 
+-	adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
+-	adapter->gorcl_old = adapter->stats.gorcl;
+-	adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
+-	adapter->gotcl_old = adapter->stats.gotcl;
++	adapter->gorc = adapter->stats.gorc - adapter->gorc_old;
++	adapter->gorc_old = adapter->stats.gorc;
++	adapter->gotc = adapter->stats.gotc - adapter->gotc_old;
++	adapter->gotc_old = adapter->stats.gotc;
+ 
+ 	e1000e_update_adaptive(&adapter->hw);
+ 
+@@ -2740,23 +2860,27 @@ link_up:
+ 		tx_pending = (e1000_desc_unused(tx_ring) + 1 <
+ 			       tx_ring->count);
+ 		if (tx_pending) {
+-			/* We've lost link, so the controller stops DMA,
++			/*
++			 * We've lost link, so the controller stops DMA,
+ 			 * but we've got queued Tx work that's never going
+ 			 * to get done, so reset controller to flush Tx.
+-			 * (Do the reset outside of interrupt context). */
++			 * (Do the reset outside of interrupt context).
++			 */
+ 			adapter->tx_timeout_count++;
+ 			schedule_work(&adapter->reset_task);
+ 		}
+ 	}
+ 
+-	/* Cause software interrupt to ensure rx ring is cleaned */
++	/* Cause software interrupt to ensure Rx ring is cleaned */
+ 	ew32(ICS, E1000_ICS_RXDMT0);
+ 
+ 	/* Force detection of hung controller every watchdog period */
+ 	adapter->detect_tx_hung = 1;
+ 
+-	/* With 82571 controllers, LAA may be overwritten due to controller
+-	 * reset from the other port. Set the appropriate LAA in RAR[0] */
++	/*
++	 * With 82571 controllers, LAA may be overwritten due to controller
++	 * reset from the other port. Set the appropriate LAA in RAR[0]
++	 */
+ 	if (e1000e_get_laa_state_82571(hw))
+ 		e1000e_rar_set(hw, adapter->hw.mac.addr, 0);
+ 
+@@ -3032,16 +3156,20 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
+ 
+ 	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
+ 
+-	/* Force memory writes to complete before letting h/w
++	/*
++	 * Force memory writes to complete before letting h/w
+ 	 * know there are new descriptors to fetch.  (Only
+ 	 * applicable for weak-ordered memory model archs,
+-	 * such as IA-64). */
++	 * such as IA-64).
++	 */
+ 	wmb();
+ 
+ 	tx_ring->next_to_use = i;
+ 	writel(i, adapter->hw.hw_addr + tx_ring->tail);
+-	/* we need this if more than one processor can write to our tail
+-	 * at a time, it synchronizes IO on IA64/Altix systems */
++	/*
++	 * we need this if more than one processor can write to our tail
++	 * at a time, it synchronizes IO on IA64/Altix systems
++	 */
+ 	mmiowb();
+ }
+ 
+@@ -3089,13 +3217,17 @@ static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 
+ 	netif_stop_queue(netdev);
+-	/* Herbert's original patch had:
++	/*
++	 * Herbert's original patch had:
+ 	 *  smp_mb__after_netif_stop_queue();
+-	 * but since that doesn't exist yet, just open code it. */
++	 * but since that doesn't exist yet, just open code it.
++	 */
+ 	smp_mb();
+ 
+-	/* We need to check again in a case another CPU has just
+-	 * made room available. */
++	/*
++	 * We need to check again in a case another CPU has just
++	 * made room available.
++	 */
+ 	if (e1000_desc_unused(adapter->tx_ring) < size)
+ 		return -EBUSY;
+ 
+@@ -3142,21 +3274,29 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 	}
+ 
+ 	mss = skb_shinfo(skb)->gso_size;
+-	/* The controller does a simple calculation to
++	/*
++	 * The controller does a simple calculation to
+ 	 * make sure there is enough room in the FIFO before
+ 	 * initiating the DMA for each buffer.  The calc is:
+ 	 * 4 = ceil(buffer len/mss).  To make sure we don't
+ 	 * overrun the FIFO, adjust the max buffer len if mss
+-	 * drops. */
++	 * drops.
++	 */
+ 	if (mss) {
+ 		u8 hdr_len;
+ 		max_per_txd = min(mss << 2, max_per_txd);
+ 		max_txd_pwr = fls(max_per_txd) - 1;
+ 
+-		/* TSO Workaround for 82571/2/3 Controllers -- if skb->data
+-		* points to just header, pull a few bytes of payload from
+-		* frags into skb->data */
++		/*
++		 * TSO Workaround for 82571/2/3 Controllers -- if skb->data
++		 * points to just header, pull a few bytes of payload from
++		 * frags into skb->data
++		 */
+ 		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
++		/*
++		 * we do this workaround for ES2LAN, but it is un-necessary,
++		 * avoiding it could save a lot of cycles
++		 */
+ 		if (skb->data_len && (hdr_len == len)) {
+ 			unsigned int pull_size;
+ 
+@@ -3190,8 +3330,10 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 		/* Collision - tell upper layer to requeue */
+ 		return NETDEV_TX_LOCKED;
+ 
+-	/* need: count + 2 desc gap to keep tail from touching
+-	 * head, otherwise try next time */
++	/*
++	 * need: count + 2 desc gap to keep tail from touching
++	 * head, otherwise try next time
++	 */
+ 	if (e1000_maybe_stop_tx(netdev, count + 2)) {
+ 		spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags);
+ 		return NETDEV_TX_BUSY;
+@@ -3216,9 +3358,11 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 	else if (e1000_tx_csum(adapter, skb))
+ 		tx_flags |= E1000_TX_FLAGS_CSUM;
+ 
+-	/* Old method was to assume IPv4 packet by default if TSO was enabled.
++	/*
++	 * Old method was to assume IPv4 packet by default if TSO was enabled.
+ 	 * 82571 hardware supports TSO capabilities for IPv6 as well...
+-	 * no longer assume, we must. */
++	 * no longer assume, we must.
++	 */
+ 	if (skb->protocol == htons(ETH_P_IP))
+ 		tx_flags |= E1000_TX_FLAGS_IPV4;
+ 
+@@ -3316,14 +3460,16 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
+ 	while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
+ 		msleep(1);
+ 	/* e1000e_down has a dependency on max_frame_size */
+-	adapter->hw.mac.max_frame_size = max_frame;
++	adapter->max_frame_size = max_frame;
+ 	if (netif_running(netdev))
+ 		e1000e_down(adapter);
+ 
+-	/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
++	/*
++	 * NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+ 	 * means we reserve 2 more, this pushes us to allocate from the next
+ 	 * larger slab size.
+-	 * i.e. RXBUFFER_2048 --> size-4096 slab */
++	 * i.e. RXBUFFER_2048 --> size-4096 slab
++	 */
+ 
+ 	if (max_frame <= 256)
+ 		adapter->rx_buffer_len = 256;
+@@ -3340,7 +3486,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
+ 	if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) ||
+ 	     (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN))
+ 		adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN
+-					 + ETH_FCS_LEN ;
++					 + ETH_FCS_LEN;
+ 
+ 	ndev_info(netdev, "changing MTU from %d to %d\n",
+ 		netdev->mtu, new_mtu);
+@@ -3361,9 +3507,8 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 	struct mii_ioctl_data *data = if_mii(ifr);
+-	unsigned long irq_flags;
+ 
+-	if (adapter->hw.media_type != e1000_media_type_copper)
++	if (adapter->hw.phy.media_type != e1000_media_type_copper)
+ 		return -EOPNOTSUPP;
+ 
+ 	switch (cmd) {
+@@ -3373,13 +3518,40 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
+ 	case SIOCGMIIREG:
+ 		if (!capable(CAP_NET_ADMIN))
+ 			return -EPERM;
+-		spin_lock_irqsave(&adapter->stats_lock, irq_flags);
+-		if (e1e_rphy(&adapter->hw, data->reg_num & 0x1F,
+-				   &data->val_out)) {
+-			spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
++		switch (data->reg_num & 0x1F) {
++		case MII_BMCR:
++			data->val_out = adapter->phy_regs.bmcr;
++			break;
++		case MII_BMSR:
++			data->val_out = adapter->phy_regs.bmsr;
++			break;
++		case MII_PHYSID1:
++			data->val_out = (adapter->hw.phy.id >> 16);
++			break;
++		case MII_PHYSID2:
++			data->val_out = (adapter->hw.phy.id & 0xFFFF);
++			break;
++		case MII_ADVERTISE:
++			data->val_out = adapter->phy_regs.advertise;
++			break;
++		case MII_LPA:
++			data->val_out = adapter->phy_regs.lpa;
++			break;
++		case MII_EXPANSION:
++			data->val_out = adapter->phy_regs.expansion;
++			break;
++		case MII_CTRL1000:
++			data->val_out = adapter->phy_regs.ctrl1000;
++			break;
++		case MII_STAT1000:
++			data->val_out = adapter->phy_regs.stat1000;
++			break;
++		case MII_ESTATUS:
++			data->val_out = adapter->phy_regs.estatus;
++			break;
++		default:
+ 			return -EIO;
+ 		}
+-		spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
+ 		break;
+ 	case SIOCSMIIREG:
+ 	default:
+@@ -3445,8 +3617,9 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+ 			E1000_CTRL_EN_PHY_PWR_MGMT;
+ 		ew32(CTRL, ctrl);
+ 
+-		if (adapter->hw.media_type == e1000_media_type_fiber ||
+-		   adapter->hw.media_type == e1000_media_type_internal_serdes) {
++		if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
++		    adapter->hw.phy.media_type ==
++		    e1000_media_type_internal_serdes) {
+ 			/* keep the laser running in D3 */
+ 			ctrl_ext = er32(CTRL_EXT);
+ 			ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
+@@ -3476,8 +3649,10 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+ 	if (adapter->hw.phy.type == e1000_phy_igp_3)
+ 		e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
+ 
+-	/* Release control of h/w to f/w.  If f/w is AMT enabled, this
+-	 * would have already happened in close and is redundant. */
++	/*
++	 * Release control of h/w to f/w.  If f/w is AMT enabled, this
++	 * would have already happened in close and is redundant.
++	 */
+ 	e1000_release_hw_control(adapter);
+ 
+ 	pci_disable_device(pdev);
+@@ -3552,9 +3727,11 @@ static int e1000_resume(struct pci_dev *pdev)
+ 
+ 	netif_device_attach(netdev);
+ 
+-	/* If the controller has AMT, do not set DRV_LOAD until the interface
++	/*
++	 * If the controller has AMT, do not set DRV_LOAD until the interface
+ 	 * is up.  For all other cases, let the f/w know that the h/w is now
+-	 * under the control of the driver. */
++	 * under the control of the driver.
++	 */
+ 	if (!(adapter->flags & FLAG_HAS_AMT) || !e1000e_check_mng_mode(&adapter->hw))
+ 		e1000_get_hw_control(adapter);
+ 
+@@ -3630,6 +3807,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
+ 		return PCI_ERS_RESULT_DISCONNECT;
+ 	}
+ 	pci_set_master(pdev);
++	pci_restore_state(pdev);
+ 
+ 	pci_enable_wake(pdev, PCI_D3hot, 0);
+ 	pci_enable_wake(pdev, PCI_D3cold, 0);
+@@ -3665,9 +3843,11 @@ static void e1000_io_resume(struct pci_dev *pdev)
+ 
+ 	netif_device_attach(netdev);
+ 
+-	/* If the controller has AMT, do not set DRV_LOAD until the interface
++	/*
++	 * If the controller has AMT, do not set DRV_LOAD until the interface
+ 	 * is up.  For all other cases, let the f/w know that the h/w is now
+-	 * under the control of the driver. */
++	 * under the control of the driver.
++	 */
+ 	if (!(adapter->flags & FLAG_HAS_AMT) ||
+ 	    !e1000e_check_mng_mode(&adapter->hw))
+ 		e1000_get_hw_control(adapter);
+@@ -3678,7 +3858,7 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	struct net_device *netdev = adapter->netdev;
+-	u32 part_num;
++	u32 pba_num;
+ 
+ 	/* print bus type/speed/width info */
+ 	ndev_info(netdev, "(PCI Express:2.5GB/s:%s) "
+@@ -3693,10 +3873,10 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
+ 	ndev_info(netdev, "Intel(R) PRO/%s Network Connection\n",
+ 		  (hw->phy.type == e1000_phy_ife)
+ 		   ? "10/100" : "1000");
+-	e1000e_read_part_num(hw, &part_num);
++	e1000e_read_pba_num(hw, &pba_num);
+ 	ndev_info(netdev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
+ 		  hw->mac.type, hw->phy.type,
+-		  (part_num >> 8), (part_num & 0xff));
++		  (pba_num >> 8), (pba_num & 0xff));
+ }
+ 
+ /**
+@@ -3754,6 +3934,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ 		goto err_pci_reg;
+ 
+ 	pci_set_master(pdev);
++	pci_save_state(pdev);
+ 
+ 	err = -ENOMEM;
+ 	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
+@@ -3828,16 +4009,16 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ 	memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops));
+ 	memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops));
+ 
+-	err = ei->get_invariants(adapter);
++	err = ei->get_variants(adapter);
+ 	if (err)
+ 		goto err_hw_init;
+ 
+ 	hw->mac.ops.get_bus_info(&adapter->hw);
+ 
+-	adapter->hw.phy.wait_for_link = 0;
++	adapter->hw.phy.autoneg_wait_to_complete = 0;
+ 
+ 	/* Copper options */
+-	if (adapter->hw.media_type == e1000_media_type_copper) {
++	if (adapter->hw.phy.media_type == e1000_media_type_copper) {
+ 		adapter->hw.phy.mdix = AUTO_ALL_MODES;
+ 		adapter->hw.phy.disable_polarity_correction = 0;
+ 		adapter->hw.phy.ms_type = e1000_ms_hw_default;
+@@ -3861,15 +4042,19 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ 	if (pci_using_dac)
+ 		netdev->features |= NETIF_F_HIGHDMA;
+ 
+-	/* We should not be using LLTX anymore, but we are still TX faster with
+-	 * it. */
++	/*
++	 * We should not be using LLTX anymore, but we are still Tx faster with
++	 * it.
++	 */
+ 	netdev->features |= NETIF_F_LLTX;
+ 
+ 	if (e1000e_enable_mng_pass_thru(&adapter->hw))
+ 		adapter->flags |= FLAG_MNG_PT_ENABLED;
+ 
+-	/* before reading the NVM, reset the controller to
+-	 * put the device in a known good starting state */
++	/*
++	 * before reading the NVM, reset the controller to
++	 * put the device in a known good starting state
++	 */
+ 	adapter->hw.mac.ops.reset_hw(&adapter->hw);
+ 
+ 	/*
+@@ -3919,8 +4104,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ 	/* Initialize link parameters. User can change them with ethtool */
+ 	adapter->hw.mac.autoneg = 1;
+ 	adapter->fc_autoneg = 1;
+-	adapter->hw.mac.original_fc = e1000_fc_default;
+-	adapter->hw.mac.fc = e1000_fc_default;
++	adapter->hw.fc.original_type = e1000_fc_default;
++	adapter->hw.fc.type = e1000_fc_default;
+ 	adapter->hw.phy.autoneg_advertised = 0x2f;
+ 
+ 	/* ring size defaults */
+@@ -3963,9 +4148,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ 	/* reset the hardware with the new settings */
+ 	e1000e_reset(adapter);
+ 
+-	/* If the controller has AMT, do not set DRV_LOAD until the interface
++	/*
++	 * If the controller has AMT, do not set DRV_LOAD until the interface
+ 	 * is up.  For all other cases, let the f/w know that the h/w is now
+-	 * under the control of the driver. */
++	 * under the control of the driver.
++	 */
+ 	if (!(adapter->flags & FLAG_HAS_AMT) ||
+ 	    !e1000e_check_mng_mode(&adapter->hw))
+ 		e1000_get_hw_control(adapter);
+@@ -4022,16 +4209,20 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 
+-	/* flush_scheduled work may reschedule our watchdog task, so
+-	 * explicitly disable watchdog tasks from being rescheduled  */
++	/*
++	 * flush_scheduled work may reschedule our watchdog task, so
++	 * explicitly disable watchdog tasks from being rescheduled
++	 */
+ 	set_bit(__E1000_DOWN, &adapter->state);
+ 	del_timer_sync(&adapter->watchdog_timer);
+ 	del_timer_sync(&adapter->phy_info_timer);
+ 
+ 	flush_scheduled_work();
+ 
+-	/* Release control of h/w to f/w.  If f/w is AMT enabled, this
+-	 * would have already happened in close and is redundant. */
++	/*
++	 * Release control of h/w to f/w.  If f/w is AMT enabled, this
++	 * would have already happened in close and is redundant.
++	 */
+ 	e1000_release_hw_control(adapter);
+ 
+ 	unregister_netdev(netdev);
+@@ -4069,13 +4260,16 @@ static struct pci_device_id e1000_pci_tbl[] = {
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD), board_82571 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER), board_82571 },
++
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI), board_82572 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_COPPER), board_82572 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_FIBER), board_82572 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_SERDES), board_82572 },
++
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E), board_82573 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E_IAMT), board_82573 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 },
++
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT),
+ 	  board_80003es2lan },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_SPT),
+@@ -4084,6 +4278,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
+ 	  board_80003es2lan },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_SPT),
+ 	  board_80003es2lan },
++
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE), board_ich8lan },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_G), board_ich8lan },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_GT), board_ich8lan },
+@@ -4091,6 +4286,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan },
++
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_GT), board_ich9lan },
+@@ -4108,7 +4304,7 @@ static struct pci_driver e1000_driver = {
+ 	.probe    = e1000_probe,
+ 	.remove   = __devexit_p(e1000_remove),
+ #ifdef CONFIG_PM
+-	/* Power Managment Hooks */
++	/* Power Management Hooks */
+ 	.suspend  = e1000_suspend,
+ 	.resume   = e1000_resume,
+ #endif
+@@ -4127,7 +4323,7 @@ static int __init e1000_init_module(void)
+ 	int ret;
+ 	printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Driver - %s\n",
+ 	       e1000e_driver_name, e1000e_driver_version);
+-	printk(KERN_INFO "%s: Copyright (c) 1999-2007 Intel Corporation.\n",
++	printk(KERN_INFO "%s: Copyright (c) 1999-2008 Intel Corporation.\n",
+ 	       e1000e_driver_name);
+ 	ret = pci_register_driver(&e1000_driver);
+ 
+diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
+index df266c3..a66b92e 100644
+--- a/drivers/net/e1000e/param.c
++++ b/drivers/net/e1000e/param.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -30,7 +30,8 @@
+ 
+ #include "e1000.h"
+ 
+-/* This is the only thing that needs to be changed to adjust the
++/*
++ * This is the only thing that needs to be changed to adjust the
+  * maximum number of ports that the driver can manage.
+  */
+ 
+@@ -46,7 +47,8 @@ module_param(copybreak, uint, 0644);
+ MODULE_PARM_DESC(copybreak,
+ 	"Maximum size of packet that is copied to a new buffer on receive");
+ 
+-/* All parameters are treated the same, as an integer array of values.
++/*
++ * All parameters are treated the same, as an integer array of values.
+  * This macro just reduces the need to repeat the same declaration code
+  * over and over (plus this helps to avoid typo bugs).
+  */
+@@ -60,8 +62,9 @@ MODULE_PARM_DESC(copybreak,
+ 	MODULE_PARM_DESC(X, desc);
+ 
+ 
+-/* Transmit Interrupt Delay in units of 1.024 microseconds
+- *  Tx interrupt delay needs to typically be set to something non zero
++/*
++ * Transmit Interrupt Delay in units of 1.024 microseconds
++ * Tx interrupt delay needs to typically be set to something non zero
+  *
+  * Valid Range: 0-65535
+  */
+@@ -70,7 +73,8 @@ E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
+ #define MAX_TXDELAY 0xFFFF
+ #define MIN_TXDELAY 0
+ 
+-/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
++/*
++ * Transmit Absolute Interrupt Delay in units of 1.024 microseconds
+  *
+  * Valid Range: 0-65535
+  */
+@@ -79,8 +83,9 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
+ #define MAX_TXABSDELAY 0xFFFF
+ #define MIN_TXABSDELAY 0
+ 
+-/* Receive Interrupt Delay in units of 1.024 microseconds
+- *   hardware will likely hang if you set this to anything but zero.
++/*
++ * Receive Interrupt Delay in units of 1.024 microseconds
++ * hardware will likely hang if you set this to anything but zero.
+  *
+  * Valid Range: 0-65535
+  */
+@@ -89,7 +94,8 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
+ #define MAX_RXDELAY 0xFFFF
+ #define MIN_RXDELAY 0
+ 
+-/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
++/*
++ * Receive Absolute Interrupt Delay in units of 1.024 microseconds
+  *
+  * Valid Range: 0-65535
+  */
+@@ -98,7 +104,8 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
+ #define MAX_RXABSDELAY 0xFFFF
+ #define MIN_RXABSDELAY 0
+ 
+-/* Interrupt Throttle Rate (interrupts/sec)
++/*
++ * Interrupt Throttle Rate (interrupts/sec)
+  *
+  * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
+  */
+@@ -107,7 +114,8 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
+ #define MAX_ITR 100000
+ #define MIN_ITR 100
+ 
+-/* Enable Smart Power Down of the PHY
++/*
++ * Enable Smart Power Down of the PHY
+  *
+  * Valid Range: 0, 1
+  *
+@@ -115,7 +123,8 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
+  */
+ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
+ 
+-/* Enable Kumeran Lock Loss workaround
++/*
++ * Enable Kumeran Lock Loss workaround
+  *
+  * Valid Range: 0, 1
+  *
+diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
+index dab3c46..e102332 100644
+--- a/drivers/net/e1000e/phy.c
++++ b/drivers/net/e1000e/phy.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+ 
+   Intel PRO/1000 Linux driver
+-  Copyright(c) 1999 - 2007 Intel Corporation.
++  Copyright(c) 1999 - 2008 Intel Corporation.
+ 
+   This program is free software; you can redistribute it and/or modify it
+   under the terms and conditions of the GNU General Public License,
+@@ -116,7 +116,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
+ }
+ 
+ /**
+- *  e1000_read_phy_reg_mdic - Read MDI control register
++ *  e1000e_read_phy_reg_mdic - Read MDI control register
+  *  @hw: pointer to the HW structure
+  *  @offset: register offset to be read
+  *  @data: pointer to the read data
+@@ -124,7 +124,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
+  *  Reads the MDI control register in the PHY at offset and stores the
+  *  information read to data.
+  **/
+-static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
++s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ {
+ 	struct e1000_phy_info *phy = &hw->phy;
+ 	u32 i, mdic = 0;
+@@ -134,7 +134,8 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ 		return -E1000_ERR_PARAM;
+ 	}
+ 
+-	/* Set up Op-code, Phy Address, and register offset in the MDI
++	/*
++	 * Set up Op-code, Phy Address, and register offset in the MDI
+ 	 * Control register.  The MAC will take care of interfacing with the
+ 	 * PHY to retrieve the desired data.
+ 	 */
+@@ -144,8 +145,12 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ 
+ 	ew32(MDIC, mdic);
+ 
+-	/* Poll the ready bit to see if the MDI read completed */
+-	for (i = 0; i < 64; i++) {
++	/*
++	 * Poll the ready bit to see if the MDI read completed
++	 * Increasing the time out as testing showed failures with
++	 * the lower time out
++	 */
++	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+ 		udelay(50);
+ 		mdic = er32(MDIC);
+ 		if (mdic & E1000_MDIC_READY)
+@@ -165,14 +170,14 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ }
+ 
+ /**
+- *  e1000_write_phy_reg_mdic - Write MDI control register
++ *  e1000e_write_phy_reg_mdic - Write MDI control register
+  *  @hw: pointer to the HW structure
+  *  @offset: register offset to write to
+  *  @data: data to write to register at offset
+  *
+  *  Writes data to MDI control register in the PHY at offset.
+  **/
+-static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
++s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ {
+ 	struct e1000_phy_info *phy = &hw->phy;
+ 	u32 i, mdic = 0;
+@@ -182,7 +187,8 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ 		return -E1000_ERR_PARAM;
+ 	}
+ 
+-	/* Set up Op-code, Phy Address, and register offset in the MDI
++	/*
++	 * Set up Op-code, Phy Address, and register offset in the MDI
+ 	 * Control register.  The MAC will take care of interfacing with the
+ 	 * PHY to retrieve the desired data.
+ 	 */
+@@ -193,9 +199,13 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ 
+ 	ew32(MDIC, mdic);
+ 
+-	/* Poll the ready bit to see if the MDI read completed */
+-	for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) {
+-		udelay(5);
++	/*
++	 * Poll the ready bit to see if the MDI read completed
++	 * Increasing the time out as testing showed failures with
++	 * the lower time out
++	 */
++	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
++		udelay(50);
+ 		mdic = er32(MDIC);
+ 		if (mdic & E1000_MDIC_READY)
+ 			break;
+@@ -204,6 +214,10 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ 		hw_dbg(hw, "MDI Write did not complete\n");
+ 		return -E1000_ERR_PHY;
+ 	}
++	if (mdic & E1000_MDIC_ERROR) {
++		hw_dbg(hw, "MDI Error\n");
++		return -E1000_ERR_PHY;
++	}
+ 
+ 	return 0;
+ }
+@@ -226,9 +240,8 @@ s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	ret_val = e1000_read_phy_reg_mdic(hw,
+-					  MAX_PHY_REG_ADDRESS & offset,
+-					  data);
++	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++					   data);
+ 
+ 	hw->phy.ops.release_phy(hw);
+ 
+@@ -252,9 +265,8 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	ret_val = e1000_write_phy_reg_mdic(hw,
+-					   MAX_PHY_REG_ADDRESS & offset,
+-					   data);
++	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++					    data);
+ 
+ 	hw->phy.ops.release_phy(hw);
+ 
+@@ -280,18 +292,17 @@ s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+ 		return ret_val;
+ 
+ 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
+-		ret_val = e1000_write_phy_reg_mdic(hw,
+-						   IGP01E1000_PHY_PAGE_SELECT,
+-						   (u16)offset);
++		ret_val = e1000e_write_phy_reg_mdic(hw,
++						    IGP01E1000_PHY_PAGE_SELECT,
++						    (u16)offset);
+ 		if (ret_val) {
+ 			hw->phy.ops.release_phy(hw);
+ 			return ret_val;
+ 		}
+ 	}
+ 
+-	ret_val = e1000_read_phy_reg_mdic(hw,
+-					  MAX_PHY_REG_ADDRESS & offset,
+-					  data);
++	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++					   data);
+ 
+ 	hw->phy.ops.release_phy(hw);
+ 
+@@ -316,18 +327,17 @@ s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+ 		return ret_val;
+ 
+ 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
+-		ret_val = e1000_write_phy_reg_mdic(hw,
+-						   IGP01E1000_PHY_PAGE_SELECT,
+-						   (u16)offset);
++		ret_val = e1000e_write_phy_reg_mdic(hw,
++						    IGP01E1000_PHY_PAGE_SELECT,
++						    (u16)offset);
+ 		if (ret_val) {
+ 			hw->phy.ops.release_phy(hw);
+ 			return ret_val;
+ 		}
+ 	}
+ 
+-	ret_val = e1000_write_phy_reg_mdic(hw,
+-					   MAX_PHY_REG_ADDRESS & offset,
+-					   data);
++	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++					    data);
+ 
+ 	hw->phy.ops.release_phy(hw);
+ 
+@@ -409,14 +419,17 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
+ 	s32 ret_val;
+ 	u16 phy_data;
+ 
+-	/* Enable CRS on TX. This must be set for half-duplex operation. */
++	/* Enable CRS on Tx. This must be set for half-duplex operation. */
+ 	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
++	/* For newer PHYs this bit is downshift enable */
++	if (phy->type == e1000_phy_m88)
++		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+ 
+-	/* Options:
++	/*
++	 * Options:
+ 	 *   MDI/MDI-X = 0 (default)
+ 	 *   0 - Auto for all speeds
+ 	 *   1 - MDI mode
+@@ -441,7 +454,8 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
+ 		break;
+ 	}
+ 
+-	/* Options:
++	/*
++	 * Options:
+ 	 *   disable_polarity_correction = 0 (default)
+ 	 *       Automatic Correction for Reversed Cable Polarity
+ 	 *   0 - Disabled
+@@ -455,8 +469,9 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	if (phy->revision < 4) {
+-		/* Force TX_CLK in the Extended PHY Specific Control Register
++	if ((phy->type == e1000_phy_m88) && (phy->revision < 4)) {
++		/*
++		 * Force TX_CLK in the Extended PHY Specific Control Register
+ 		 * to 25MHz clock.
+ 		 */
+ 		ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
+@@ -509,8 +524,11 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
+ 		return ret_val;
+ 	}
+ 
+-	/* Wait 15ms for MAC to configure PHY from NVM settings. */
+-	msleep(15);
++	/*
++	 * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
++	 * timeout issues when LFS is enabled.
++	 */
++	msleep(100);
+ 
+ 	/* disable lplu d0 during driver init */
+ 	ret_val = e1000_set_d0_lplu_state(hw, 0);
+@@ -543,19 +561,21 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
+ 
+ 	/* set auto-master slave resolution settings */
+ 	if (hw->mac.autoneg) {
+-		/* when autonegotiation advertisement is only 1000Mbps then we
++		/*
++		 * when autonegotiation advertisement is only 1000Mbps then we
+ 		 * should disable SmartSpeed and enable Auto MasterSlave
+-		 * resolution as hardware default. */
++		 * resolution as hardware default.
++		 */
+ 		if (phy->autoneg_advertised == ADVERTISE_1000_FULL) {
+ 			/* Disable SmartSpeed */
+ 			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     &data);
++					   &data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+ 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ 			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     data);
++					   data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+@@ -630,14 +650,16 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ 			return ret_val;
+ 	}
+ 
+-	/* Need to parse both autoneg_advertised and fc and set up
++	/*
++	 * Need to parse both autoneg_advertised and fc and set up
+ 	 * the appropriate PHY registers.  First we will parse for
+ 	 * autoneg_advertised software override.  Since we can advertise
+ 	 * a plethora of combinations, we need to check each bit
+ 	 * individually.
+ 	 */
+ 
+-	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
++	/*
++	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ 	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ 	 * the  1000Base-T Control Register (Address 9).
+ 	 */
+@@ -683,7 +705,8 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ 		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
+ 	}
+ 
+-	/* Check for a software override of the flow control settings, and
++	/*
++	 * Check for a software override of the flow control settings, and
+ 	 * setup the PHY advertisement registers accordingly.  If
+ 	 * auto-negotiation is enabled, then software will have to set the
+ 	 * "PAUSE" bits to the correct value in the Auto-Negotiation
+@@ -696,38 +719,42 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ 	 *	  but not send pause frames).
+ 	 *      2:  Tx flow control is enabled (we can send pause frames
+ 	 *	  but we do not support receiving pause frames).
+-	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
++	 *      3:  Both Rx and Tx flow control (symmetric) are enabled.
+ 	 *  other:  No software override.  The flow control configuration
+ 	 *	  in the EEPROM is used.
+ 	 */
+-	switch (hw->mac.fc) {
++	switch (hw->fc.type) {
+ 	case e1000_fc_none:
+-		/* Flow control (RX & TX) is completely disabled by a
++		/*
++		 * Flow control (Rx & Tx) is completely disabled by a
+ 		 * software over-ride.
+ 		 */
+ 		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+ 		break;
+ 	case e1000_fc_rx_pause:
+-		/* RX Flow control is enabled, and TX Flow control is
++		/*
++		 * Rx Flow control is enabled, and Tx Flow control is
+ 		 * disabled, by a software over-ride.
+-		 */
+-		/* Since there really isn't a way to advertise that we are
+-		 * capable of RX Pause ONLY, we will advertise that we
+-		 * support both symmetric and asymmetric RX PAUSE.  Later
++		 *
++		 * Since there really isn't a way to advertise that we are
++		 * capable of Rx Pause ONLY, we will advertise that we
++		 * support both symmetric and asymmetric Rx PAUSE.  Later
+ 		 * (in e1000e_config_fc_after_link_up) we will disable the
+ 		 * hw's ability to send PAUSE frames.
+ 		 */
+ 		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+ 		break;
+ 	case e1000_fc_tx_pause:
+-		/* TX Flow control is enabled, and RX Flow control is
++		/*
++		 * Tx Flow control is enabled, and Rx Flow control is
+ 		 * disabled, by a software over-ride.
+ 		 */
+ 		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
+ 		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
+ 		break;
+ 	case e1000_fc_full:
+-		/* Flow control (both RX and TX) is enabled by a software
++		/*
++		 * Flow control (both Rx and Tx) is enabled by a software
+ 		 * over-ride.
+ 		 */
+ 		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+@@ -758,7 +785,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+  *  Performs initial bounds checking on autoneg advertisement parameter, then
+  *  configure to advertise the full capability.  Setup the PHY to autoneg
+  *  and restart the negotiation process between the link partner.  If
+- *  wait_for_link, then wait for autoneg to complete before exiting.
++ *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
+  **/
+ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+ {
+@@ -766,12 +793,14 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+ 	s32 ret_val;
+ 	u16 phy_ctrl;
+ 
+-	/* Perform some bounds checking on the autoneg advertisement
++	/*
++	 * Perform some bounds checking on the autoneg advertisement
+ 	 * parameter.
+ 	 */
+ 	phy->autoneg_advertised &= phy->autoneg_mask;
+ 
+-	/* If autoneg_advertised is zero, we assume it was not defaulted
++	/*
++	 * If autoneg_advertised is zero, we assume it was not defaulted
+ 	 * by the calling code so we set to advertise full capability.
+ 	 */
+ 	if (phy->autoneg_advertised == 0)
+@@ -785,7 +814,8 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+ 	}
+ 	hw_dbg(hw, "Restarting Auto-Neg\n");
+ 
+-	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
++	/*
++	 * Restart auto-negotiation by setting the Auto Neg Enable bit and
+ 	 * the Auto Neg Restart bit in the PHY control register.
+ 	 */
+ 	ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl);
+@@ -797,10 +827,11 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* Does the user want to wait for Auto-Neg to complete here, or
++	/*
++	 * Does the user want to wait for Auto-Neg to complete here, or
+ 	 * check at a later time (for example, callback routine).
+ 	 */
+-	if (phy->wait_for_link) {
++	if (phy->autoneg_wait_to_complete) {
+ 		ret_val = e1000_wait_autoneg(hw);
+ 		if (ret_val) {
+ 			hw_dbg(hw, "Error while waiting for "
+@@ -829,14 +860,18 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
+ 	bool link;
+ 
+ 	if (hw->mac.autoneg) {
+-		/* Setup autoneg and flow control advertisement and perform
+-		 * autonegotiation. */
++		/*
++		 * Setup autoneg and flow control advertisement and perform
++		 * autonegotiation.
++		 */
+ 		ret_val = e1000_copper_link_autoneg(hw);
+ 		if (ret_val)
+ 			return ret_val;
+ 	} else {
+-		/* PHY will be set to 10H, 10F, 100H or 100F
+-		 * depending on user settings. */
++		/*
++		 * PHY will be set to 10H, 10F, 100H or 100F
++		 * depending on user settings.
++		 */
+ 		hw_dbg(hw, "Forcing Speed and Duplex\n");
+ 		ret_val = e1000_phy_force_speed_duplex(hw);
+ 		if (ret_val) {
+@@ -845,7 +880,8 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
+ 		}
+ 	}
+ 
+-	/* Check link status. Wait up to 100 microseconds for link to become
++	/*
++	 * Check link status. Wait up to 100 microseconds for link to become
+ 	 * valid.
+ 	 */
+ 	ret_val = e1000e_phy_has_link_generic(hw,
+@@ -891,7 +927,8 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
++	/*
++	 * Clear Auto-Crossover to force MDI manually.  IGP requires MDI
+ 	 * forced whenever speed and duplex are forced.
+ 	 */
+ 	ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+@@ -909,7 +946,7 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
+ 
+ 	udelay(1);
+ 
+-	if (phy->wait_for_link) {
++	if (phy->autoneg_wait_to_complete) {
+ 		hw_dbg(hw, "Waiting for forced speed/duplex link on IGP phy.\n");
+ 
+ 		ret_val = e1000e_phy_has_link_generic(hw,
+@@ -941,7 +978,7 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
+  *  Calls the PHY setup function to force speed and duplex.  Clears the
+  *  auto-crossover to force MDI manually.  Resets the PHY to commit the
+  *  changes.  If time expires while waiting for link up, we reset the DSP.
+- *  After reset, TX_CLK and CRS on TX must be set.  Return successful upon
++ *  After reset, TX_CLK and CRS on Tx must be set.  Return successful upon
+  *  successful completion, else return corresponding error code.
+  **/
+ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+@@ -951,7 +988,8 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+ 	u16 phy_data;
+ 	bool link;
+ 
+-	/* Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
++	/*
++	 * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
+ 	 * forced whenever speed and duplex are forced.
+ 	 */
+ 	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+@@ -980,7 +1018,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+ 
+ 	udelay(1);
+ 
+-	if (phy->wait_for_link) {
++	if (phy->autoneg_wait_to_complete) {
+ 		hw_dbg(hw, "Waiting for forced speed/duplex link on M88 phy.\n");
+ 
+ 		ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+@@ -989,10 +1027,12 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+ 			return ret_val;
+ 
+ 		if (!link) {
+-			/* We didn't get link.
++			/*
++			 * We didn't get link.
+ 			 * Reset the DSP and cross our fingers.
+ 			 */
+-			ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT, 0x001d);
++			ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT,
++					   0x001d);
+ 			if (ret_val)
+ 				return ret_val;
+ 			ret_val = e1000e_phy_reset_dsp(hw);
+@@ -1011,7 +1051,8 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* Resetting the phy means we need to re-force TX_CLK in the
++	/*
++	 * Resetting the phy means we need to re-force TX_CLK in the
+ 	 * Extended PHY Specific Control Register to 25MHz clock from
+ 	 * the reset value of 2.5MHz.
+ 	 */
+@@ -1020,7 +1061,8 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+ 	if (ret_val)
+ 		return ret_val;
+ 
+-	/* In addition, we must re-enable CRS on Tx for both half and full
++	/*
++	 * In addition, we must re-enable CRS on Tx for both half and full
+ 	 * duplex.
+ 	 */
+ 	ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+@@ -1051,7 +1093,7 @@ void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
+ 	u32 ctrl;
+ 
+ 	/* Turn off flow control when forcing speed/duplex */
+-	mac->fc = e1000_fc_none;
++	hw->fc.type = e1000_fc_none;
+ 
+ 	/* Force speed/duplex on the mac */
+ 	ctrl = er32(CTRL);
+@@ -1119,35 +1161,35 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active)
+ 
+ 	if (!active) {
+ 		data &= ~IGP02E1000_PM_D3_LPLU;
+-		ret_val = e1e_wphy(hw,
+-					     IGP02E1000_PHY_POWER_MGMT,
+-					     data);
++		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
+ 		if (ret_val)
+ 			return ret_val;
+-		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
++		/*
++		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+ 		 * during Dx states where the power conservation is most
+ 		 * important.  During driver activity we should enable
+-		 * SmartSpeed, so performance is maintained. */
++		 * SmartSpeed, so performance is maintained.
++		 */
+ 		if (phy->smart_speed == e1000_smart_speed_on) {
+ 			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						    &data);
++					   &data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+ 			data |= IGP01E1000_PSCFR_SMART_SPEED;
+ 			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     data);
++					   data);
+ 			if (ret_val)
+ 				return ret_val;
+ 		} else if (phy->smart_speed == e1000_smart_speed_off) {
+ 			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     &data);
++					   &data);
+ 			if (ret_val)
+ 				return ret_val;
+ 
+ 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ 			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+-						     data);
++					   data);
+ 			if (ret_val)
+ 				return ret_val;
+ 		}
+@@ -1249,8 +1291,10 @@ static s32 e1000_check_polarity_igp(struct e1000_hw *hw)
+ 	s32 ret_val;
+ 	u16 data, offset, mask;
+ 
+-	/* Polarity is determined based on the speed of
+-	 * our connection. */
++	/*
++	 * Polarity is determined based on the speed of
++	 * our connection.
++	 */
+ 	ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data);
+ 	if (ret_val)
+ 		return ret_val;
+@@ -1260,7 +1304,8 @@ static s32 e1000_check_polarity_igp(struct e1000_hw *hw)
+ 		offset	= IGP01E1000_PHY_PCS_INIT_REG;
+ 		mask	= IGP01E1000_PHY_POLARITY_MASK;
+ 	} else {
+-		/* This really only applies to 10Mbps since
++		/*
++		 * This really only applies to 10Mbps since
+ 		 * there is no polarity for 100Mbps (always 0).
+ 		 */
+ 		offset	= IGP01E1000_PHY_PORT_STATUS;
+@@ -1278,7 +1323,7 @@ static s32 e1000_check_polarity_igp(struct e1000_hw *hw)
+ }
+ 
+ /**
+- *  e1000_wait_autoneg - Wait for auto-neg compeletion
++ *  e1000_wait_autoneg - Wait for auto-neg completion
+  *  @hw: pointer to the HW structure
+  *
+  *  Waits for auto-negotiation to complete or for the auto-negotiation time
+@@ -1302,7 +1347,8 @@ static s32 e1000_wait_autoneg(struct e1000_hw *hw)
+ 		msleep(100);
+ 	}
+ 
+-	/* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
++	/*
++	 * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
+ 	 * has completed.
+ 	 */
+ 	return ret_val;
+@@ -1324,7 +1370,8 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
+ 	u16 i, phy_status;
+ 
+ 	for (i = 0; i < iterations; i++) {
+-		/* Some PHYs require the PHY_STATUS register to be read
++		/*
++		 * Some PHYs require the PHY_STATUS register to be read
+ 		 * twice due to the link bit being sticky.  No harm doing
+ 		 * it across the board.
+ 		 */
+@@ -1412,10 +1459,12 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
+ 		if (ret_val)
+ 			return ret_val;
+ 
+-		/* Getting bits 15:9, which represent the combination of
++		/*
++		 * Getting bits 15:9, which represent the combination of
+ 		 * course and fine gain values.  The result is a number
+ 		 * that can be put into the lookup table to obtain the
+-		 * approximate cable length. */
++		 * approximate cable length.
++		 */
+ 		cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+ 				IGP02E1000_AGC_LENGTH_MASK;
+ 
+@@ -1466,7 +1515,7 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
+ 	u16 phy_data;
+ 	bool link;
+ 
+-	if (hw->media_type != e1000_media_type_copper) {
++	if (hw->phy.media_type != e1000_media_type_copper) {
+ 		hw_dbg(hw, "Phy info is only valid for copper media\n");
+ 		return -E1000_ERR_CONFIG;
+ 	}
+diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
+index a8d3280..f5dacce 100644
+--- a/drivers/net/ehea/ehea.h
++++ b/drivers/net/ehea/ehea.h
+@@ -422,7 +422,7 @@ struct ehea_fw_handle_entry {
+ struct ehea_fw_handle_array {
+ 	struct ehea_fw_handle_entry *arr;
+ 	int num_entries;
+-	struct semaphore lock;
++	struct mutex lock;
+ };
+ 
+ struct ehea_bcmc_reg_entry {
+@@ -435,7 +435,7 @@ struct ehea_bcmc_reg_entry {
+ struct ehea_bcmc_reg_array {
+ 	struct ehea_bcmc_reg_entry *arr;
+ 	int num_entries;
+-	struct semaphore lock;
++	struct mutex lock;
+ };
+ 
+ #define EHEA_PORT_UP 1
+@@ -453,7 +453,7 @@ struct ehea_port {
+ 	struct vlan_group *vgrp;
+ 	struct ehea_eq *qp_eq;
+ 	struct work_struct reset_task;
+-	struct semaphore port_lock;
++	struct mutex port_lock;
+ 	char int_aff_name[EHEA_IRQ_NAME_SIZE];
+ 	int allmulti;			 /* Indicates IFF_ALLMULTI state */
+ 	int promisc;		 	 /* Indicates IFF_PROMISC state */
+diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
+index f460b62..f9bc21c 100644
+--- a/drivers/net/ehea/ehea_main.c
++++ b/drivers/net/ehea/ehea_main.c
+@@ -36,6 +36,7 @@
+ #include <linux/notifier.h>
+ #include <linux/reboot.h>
+ #include <asm/kexec.h>
++#include <linux/mutex.h>
+ 
+ #include <net/ip.h>
+ 
+@@ -99,7 +100,7 @@ static int port_name_cnt;
+ static LIST_HEAD(adapter_list);
+ u64 ehea_driver_flags;
+ struct work_struct ehea_rereg_mr_task;
+-struct semaphore dlpar_mem_lock;
++static DEFINE_MUTEX(dlpar_mem_lock);
+ struct ehea_fw_handle_array ehea_fw_handles;
+ struct ehea_bcmc_reg_array ehea_bcmc_regs;
+ 
+@@ -1761,7 +1762,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
+ 
+ 	memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
+ 
+-	down(&ehea_bcmc_regs.lock);
++	mutex_lock(&ehea_bcmc_regs.lock);
+ 
+ 	/* Deregister old MAC in pHYP */
+ 	ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
+@@ -1779,7 +1780,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
+ 
+ out_upregs:
+ 	ehea_update_bcmc_registrations();
+-	up(&ehea_bcmc_regs.lock);
++	mutex_unlock(&ehea_bcmc_regs.lock);
+ out_free:
+ 	kfree(cb0);
+ out:
+@@ -1941,7 +1942,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
+ 	}
+ 	ehea_promiscuous(dev, 0);
+ 
+-	down(&ehea_bcmc_regs.lock);
++	mutex_lock(&ehea_bcmc_regs.lock);
+ 
+ 	if (dev->flags & IFF_ALLMULTI) {
+ 		ehea_allmulti(dev, 1);
+@@ -1972,7 +1973,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
+ 	}
+ out:
+ 	ehea_update_bcmc_registrations();
+-	up(&ehea_bcmc_regs.lock);
++	mutex_unlock(&ehea_bcmc_regs.lock);
+ 	return;
+ }
+ 
+@@ -2455,7 +2456,7 @@ static int ehea_up(struct net_device *dev)
+ 	if (port->state == EHEA_PORT_UP)
+ 		return 0;
+ 
+-	down(&ehea_fw_handles.lock);
++	mutex_lock(&ehea_fw_handles.lock);
+ 
+ 	ret = ehea_port_res_setup(port, port->num_def_qps,
+ 				  port->num_add_tx_qps);
+@@ -2493,7 +2494,7 @@ static int ehea_up(struct net_device *dev)
+ 		}
+ 	}
+ 
+-	down(&ehea_bcmc_regs.lock);
++	mutex_lock(&ehea_bcmc_regs.lock);
+ 
+ 	ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
+ 	if (ret) {
+@@ -2516,10 +2517,10 @@ out:
+ 		ehea_info("Failed starting %s. ret=%i", dev->name, ret);
+ 
+ 	ehea_update_bcmc_registrations();
+-	up(&ehea_bcmc_regs.lock);
++	mutex_unlock(&ehea_bcmc_regs.lock);
+ 
+ 	ehea_update_firmware_handles();
+-	up(&ehea_fw_handles.lock);
++	mutex_unlock(&ehea_fw_handles.lock);
+ 
+ 	return ret;
+ }
+@@ -2545,7 +2546,7 @@ static int ehea_open(struct net_device *dev)
+ 	int ret;
+ 	struct ehea_port *port = netdev_priv(dev);
+ 
+-	down(&port->port_lock);
++	mutex_lock(&port->port_lock);
+ 
+ 	if (netif_msg_ifup(port))
+ 		ehea_info("enabling port %s", dev->name);
+@@ -2556,7 +2557,7 @@ static int ehea_open(struct net_device *dev)
+ 		netif_start_queue(dev);
+ 	}
+ 
+-	up(&port->port_lock);
++	mutex_unlock(&port->port_lock);
+ 
+ 	return ret;
+ }
+@@ -2569,18 +2570,18 @@ static int ehea_down(struct net_device *dev)
+ 	if (port->state == EHEA_PORT_DOWN)
+ 		return 0;
+ 
+-	down(&ehea_bcmc_regs.lock);
++	mutex_lock(&ehea_fw_handles.lock);
++
++	mutex_lock(&ehea_bcmc_regs.lock);
+ 	ehea_drop_multicast_list(dev);
+ 	ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
+ 
+ 	ehea_free_interrupts(dev);
+ 
+-	down(&ehea_fw_handles.lock);
+-
+ 	port->state = EHEA_PORT_DOWN;
+ 
+ 	ehea_update_bcmc_registrations();
+-	up(&ehea_bcmc_regs.lock);
++	mutex_unlock(&ehea_bcmc_regs.lock);
+ 
+ 	ret = ehea_clean_all_portres(port);
+ 	if (ret)
+@@ -2588,7 +2589,7 @@ static int ehea_down(struct net_device *dev)
+ 			  dev->name, ret);
+ 
+ 	ehea_update_firmware_handles();
+-	up(&ehea_fw_handles.lock);
++	mutex_unlock(&ehea_fw_handles.lock);
+ 
+ 	return ret;
+ }
+@@ -2602,15 +2603,15 @@ static int ehea_stop(struct net_device *dev)
+ 		ehea_info("disabling port %s", dev->name);
+ 
+ 	flush_scheduled_work();
+-	down(&port->port_lock);
++	mutex_lock(&port->port_lock);
+ 	netif_stop_queue(dev);
+ 	port_napi_disable(port);
+ 	ret = ehea_down(dev);
+-	up(&port->port_lock);
++	mutex_unlock(&port->port_lock);
+ 	return ret;
+ }
+ 
+-void ehea_purge_sq(struct ehea_qp *orig_qp)
++static void ehea_purge_sq(struct ehea_qp *orig_qp)
+ {
+ 	struct ehea_qp qp = *orig_qp;
+ 	struct ehea_qp_init_attr *init_attr = &qp.init_attr;
+@@ -2624,7 +2625,7 @@ void ehea_purge_sq(struct ehea_qp *orig_qp)
+ 	}
+ }
+ 
+-void ehea_flush_sq(struct ehea_port *port)
++static void ehea_flush_sq(struct ehea_port *port)
+ {
+ 	int i;
+ 
+@@ -2820,7 +2821,7 @@ static void ehea_reset_port(struct work_struct *work)
+ 	struct net_device *dev = port->netdev;
+ 
+ 	port->resets++;
+-	down(&port->port_lock);
++	mutex_lock(&port->port_lock);
+ 	netif_stop_queue(dev);
+ 
+ 	port_napi_disable(port);
+@@ -2840,7 +2841,7 @@ static void ehea_reset_port(struct work_struct *work)
+ 
+ 	netif_wake_queue(dev);
+ out:
+-	up(&port->port_lock);
++	mutex_unlock(&port->port_lock);
+ 	return;
+ }
+ 
+@@ -2849,7 +2850,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
+ 	int ret, i;
+ 	struct ehea_adapter *adapter;
+ 
+-	down(&dlpar_mem_lock);
++	mutex_lock(&dlpar_mem_lock);
+ 	ehea_info("LPAR memory enlarged - re-initializing driver");
+ 
+ 	list_for_each_entry(adapter, &adapter_list, list)
+@@ -2857,22 +2858,24 @@ static void ehea_rereg_mrs(struct work_struct *work)
+ 			/* Shutdown all ports */
+ 			for (i = 0; i < EHEA_MAX_PORTS; i++) {
+ 				struct ehea_port *port = adapter->port[i];
++				struct net_device *dev;
+ 
+-				if (port) {
+-					struct net_device *dev = port->netdev;
++				if (!port)
++					continue;
+ 
+-					if (dev->flags & IFF_UP) {
+-						down(&port->port_lock);
+-						netif_stop_queue(dev);
+-						ehea_flush_sq(port);
+-						ret = ehea_stop_qps(dev);
+-						if (ret) {
+-							up(&port->port_lock);
+-							goto out;
+-						}
+-						port_napi_disable(port);
+-						up(&port->port_lock);
++				dev = port->netdev;
++
++				if (dev->flags & IFF_UP) {
++					mutex_lock(&port->port_lock);
++					netif_stop_queue(dev);
++					ehea_flush_sq(port);
++					ret = ehea_stop_qps(dev);
++					if (ret) {
++						mutex_unlock(&port->port_lock);
++						goto out;
+ 					}
++					port_napi_disable(port);
++					mutex_unlock(&port->port_lock);
+ 				}
+ 			}
+ 
+@@ -2912,17 +2915,17 @@ static void ehea_rereg_mrs(struct work_struct *work)
+ 					struct net_device *dev = port->netdev;
+ 
+ 					if (dev->flags & IFF_UP) {
+-						down(&port->port_lock);
++						mutex_lock(&port->port_lock);
+ 						port_napi_enable(port);
+ 						ret = ehea_restart_qps(dev);
+ 						if (!ret)
+ 							netif_wake_queue(dev);
+-						up(&port->port_lock);
++						mutex_unlock(&port->port_lock);
+ 					}
+ 				}
+ 			}
+ 		}
+-       up(&dlpar_mem_lock);
++       mutex_unlock(&dlpar_mem_lock);
+        ehea_info("re-initializing driver complete");
+ out:
+ 	return;
+@@ -3083,7 +3086,7 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
+ 
+ 	port = netdev_priv(dev);
+ 
+-	sema_init(&port->port_lock, 1);
++	mutex_init(&port->port_lock);
+ 	port->state = EHEA_PORT_DOWN;
+ 	port->sig_comp_iv = sq_entries / 10;
+ 
+@@ -3362,7 +3365,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev,
+ 		ehea_error("Invalid ibmebus device probed");
+ 		return -EINVAL;
+ 	}
+-	down(&ehea_fw_handles.lock);
++	mutex_lock(&ehea_fw_handles.lock);
+ 
+ 	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
+ 	if (!adapter) {
+@@ -3446,7 +3449,7 @@ out_free_ad:
+ 
+ out:
+ 	ehea_update_firmware_handles();
+-	up(&ehea_fw_handles.lock);
++	mutex_unlock(&ehea_fw_handles.lock);
+ 	return ret;
+ }
+ 
+@@ -3465,7 +3468,7 @@ static int __devexit ehea_remove(struct of_device *dev)
+ 
+ 	flush_scheduled_work();
+ 
+-	down(&ehea_fw_handles.lock);
++	mutex_lock(&ehea_fw_handles.lock);
+ 
+ 	ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
+ 	tasklet_kill(&adapter->neq_tasklet);
+@@ -3476,7 +3479,7 @@ static int __devexit ehea_remove(struct of_device *dev)
+ 	kfree(adapter);
+ 
+ 	ehea_update_firmware_handles();
+-	up(&ehea_fw_handles.lock);
++	mutex_unlock(&ehea_fw_handles.lock);
+ 
+ 	return 0;
+ }
+@@ -3563,9 +3566,8 @@ int __init ehea_module_init(void)
+ 	memset(&ehea_fw_handles, 0, sizeof(ehea_fw_handles));
+ 	memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
+ 
+-	sema_init(&dlpar_mem_lock, 1);
+-	sema_init(&ehea_fw_handles.lock, 1);
+-	sema_init(&ehea_bcmc_regs.lock, 1);
++	mutex_init(&ehea_fw_handles.lock);
++	mutex_init(&ehea_bcmc_regs.lock);
+ 
+ 	ret = check_module_parm();
+ 	if (ret)
+diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
+index fe59c27..e5e6352 100644
+--- a/drivers/net/fec_mpc52xx.c
++++ b/drivers/net/fec_mpc52xx.c
+@@ -198,7 +198,7 @@ static int mpc52xx_fec_init_phy(struct net_device *dev)
+ 	struct phy_device *phydev;
+ 	char phy_id[BUS_ID_SIZE];
+ 
+-	snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT,
++	snprintf(phy_id, BUS_ID_SIZE, "%x:%02x",
+ 			(unsigned int)dev->base_addr, priv->phy_addr);
+ 
+ 	priv->link = PHY_DOWN;
+diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c
+index 1d0cd1d..f563444 100644
+--- a/drivers/net/fec_mpc52xx_phy.c
++++ b/drivers/net/fec_mpc52xx_phy.c
+@@ -124,7 +124,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_i
+ 		goto out_free;
+ 	}
+ 
+-	bus->id = res.start;
++	snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ 	bus->priv = priv;
+ 
+ 	bus->dev = dev;
+diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
+index 9f088a4..35f66d4 100644
+--- a/drivers/net/forcedeth.c
++++ b/drivers/net/forcedeth.c
+@@ -29,90 +29,6 @@
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  *
+- * Changelog:
+- * 	0.01: 05 Oct 2003: First release that compiles without warnings.
+- * 	0.02: 05 Oct 2003: Fix bug for nv_drain_tx: do not try to free NULL skbs.
+- * 			   Check all PCI BARs for the register window.
+- * 			   udelay added to mii_rw.
+- * 	0.03: 06 Oct 2003: Initialize dev->irq.
+- * 	0.04: 07 Oct 2003: Initialize np->lock, reduce handled irqs, add printks.
+- * 	0.05: 09 Oct 2003: printk removed again, irq status print tx_timeout.
+- * 	0.06: 10 Oct 2003: MAC Address read updated, pff flag generation updated,
+- * 			   irq mask updated
+- * 	0.07: 14 Oct 2003: Further irq mask updates.
+- * 	0.08: 20 Oct 2003: rx_desc.Length initialization added, nv_alloc_rx refill
+- * 			   added into irq handler, NULL check for drain_ring.
+- * 	0.09: 20 Oct 2003: Basic link speed irq implementation. Only handle the
+- * 			   requested interrupt sources.
+- * 	0.10: 20 Oct 2003: First cleanup for release.
+- * 	0.11: 21 Oct 2003: hexdump for tx added, rx buffer sizes increased.
+- * 			   MAC Address init fix, set_multicast cleanup.
+- * 	0.12: 23 Oct 2003: Cleanups for release.
+- * 	0.13: 25 Oct 2003: Limit for concurrent tx packets increased to 10.
+- * 			   Set link speed correctly. start rx before starting
+- * 			   tx (nv_start_rx sets the link speed).
+- * 	0.14: 25 Oct 2003: Nic dependant irq mask.
+- * 	0.15: 08 Nov 2003: fix smp deadlock with set_multicast_list during
+- * 			   open.
+- * 	0.16: 15 Nov 2003: include file cleanup for ppc64, rx buffer size
+- * 			   increased to 1628 bytes.
+- * 	0.17: 16 Nov 2003: undo rx buffer size increase. Substract 1 from
+- * 			   the tx length.
+- * 	0.18: 17 Nov 2003: fix oops due to late initialization of dev_stats
+- * 	0.19: 29 Nov 2003: Handle RxNoBuf, detect & handle invalid mac
+- * 			   addresses, really stop rx if already running
+- * 			   in nv_start_rx, clean up a bit.
+- * 	0.20: 07 Dec 2003: alloc fixes
+- * 	0.21: 12 Jan 2004: additional alloc fix, nic polling fix.
+- *	0.22: 19 Jan 2004: reprogram timer to a sane rate, avoid lockup
+- *			   on close.
+- *	0.23: 26 Jan 2004: various small cleanups
+- *	0.24: 27 Feb 2004: make driver even less anonymous in backtraces
+- *	0.25: 09 Mar 2004: wol support
+- *	0.26: 03 Jun 2004: netdriver specific annotation, sparse-related fixes
+- *	0.27: 19 Jun 2004: Gigabit support, new descriptor rings,
+- *			   added CK804/MCP04 device IDs, code fixes
+- *			   for registers, link status and other minor fixes.
+- *	0.28: 21 Jun 2004: Big cleanup, making driver mostly endian safe
+- *	0.29: 31 Aug 2004: Add backup timer for link change notification.
+- *	0.30: 25 Sep 2004: rx checksum support for nf 250 Gb. Add rx reset
+- *			   into nv_close, otherwise reenabling for wol can
+- *			   cause DMA to kfree'd memory.
+- *	0.31: 14 Nov 2004: ethtool support for getting/setting link
+- *			   capabilities.
+- *	0.32: 16 Apr 2005: RX_ERROR4 handling added.
+- *	0.33: 16 May 2005: Support for MCP51 added.
+- *	0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics.
+- *	0.35: 26 Jun 2005: Support for MCP55 added.
+- *	0.36: 28 Jun 2005: Add jumbo frame support.
+- *	0.37: 10 Jul 2005: Additional ethtool support, cleanup of pci id list
+- *	0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of
+- *			   per-packet flags.
+- *	0.39: 18 Jul 2005: Add 64bit descriptor support.
+- *	0.40: 19 Jul 2005: Add support for mac address change.
+- *	0.41: 30 Jul 2005: Write back original MAC in nv_close instead
+- *			   of nv_remove
+- *	0.42: 06 Aug 2005: Fix lack of link speed initialization
+- *			   in the second (and later) nv_open call
+- *	0.43: 10 Aug 2005: Add support for tx checksum.
+- *	0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
+- *	0.45: 18 Sep 2005: Remove nv_stop/start_rx from every link check
+- *	0.46: 20 Oct 2005: Add irq optimization modes.
+- *	0.47: 26 Oct 2005: Add phyaddr 0 in phy scan.
+- *	0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single
+- *	0.49: 10 Dec 2005: Fix tso for large buffers.
+- *	0.50: 20 Jan 2006: Add 8021pq tagging support.
+- *	0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings.
+- *	0.52: 20 Jan 2006: Add MSI/MSIX support.
+- *	0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
+- *	0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
+- *	0.55: 22 Mar 2006: Add flow control (pause frame).
+- *	0.56: 22 Mar 2006: Additional ethtool config and moduleparam support.
+- *	0.57: 14 May 2006: Mac address set in probe/remove and order corrections.
+- *	0.58: 30 Oct 2006: Added support for sideband management unit.
+- *	0.59: 30 Oct 2006: Added support for recoverable error.
+- *	0.60: 20 Jan 2007: Code optimizations for rings, rx & tx data paths, and stats.
+- *
+  * Known bugs:
+  * We suspect that on some hardware no TX done interrupts are generated.
+  * This means recovery from netif_stop_queue only happens if the hw timer
+@@ -123,11 +39,6 @@
+  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
+  * superfluous timer interrupts from the nic.
+  */
+-#ifdef CONFIG_FORCEDETH_NAPI
+-#define DRIVERNAPI "-NAPI"
+-#else
+-#define DRIVERNAPI
+-#endif
+ #define FORCEDETH_VERSION		"0.61"
+ #define DRV_NAME			"forcedeth"
+ 
+@@ -185,6 +96,7 @@
+ #define DEV_HAS_PAUSEFRAME_TX_V2   0x10000  /* device supports tx pause frames version 2 */
+ #define DEV_HAS_PAUSEFRAME_TX_V3   0x20000  /* device supports tx pause frames version 3 */
+ #define DEV_NEED_TX_LIMIT          0x40000  /* device needs to limit tx */
++#define DEV_HAS_GEAR_MODE          0x80000  /* device supports gear mode */
+ 
+ enum {
+ 	NvRegIrqStatus = 0x000,
+@@ -263,11 +175,13 @@ enum {
+ 	NvRegReceiverStatus = 0x98,
+ #define NVREG_RCVSTAT_BUSY	0x01
+ 
+-	NvRegRandomSeed = 0x9c,
+-#define NVREG_RNDSEED_MASK	0x00ff
+-#define NVREG_RNDSEED_FORCE	0x7f00
+-#define NVREG_RNDSEED_FORCE2	0x2d00
+-#define NVREG_RNDSEED_FORCE3	0x7400
++	NvRegSlotTime = 0x9c,
++#define NVREG_SLOTTIME_LEGBF_ENABLED	0x80000000
++#define NVREG_SLOTTIME_10_100_FULL	0x00007f00
++#define NVREG_SLOTTIME_1000_FULL 	0x0003ff00
++#define NVREG_SLOTTIME_HALF		0x0000ff00
++#define NVREG_SLOTTIME_DEFAULT	 	0x00007f00
++#define NVREG_SLOTTIME_MASK		0x000000ff
+ 
+ 	NvRegTxDeferral = 0xA0,
+ #define NVREG_TX_DEFERRAL_DEFAULT		0x15050f
+@@ -290,6 +204,11 @@ enum {
+ 
+ 	NvRegPhyInterface = 0xC0,
+ #define PHY_RGMII		0x10000000
++	NvRegBackOffControl = 0xC4,
++#define NVREG_BKOFFCTRL_DEFAULT			0x70000000
++#define NVREG_BKOFFCTRL_SEED_MASK		0x000003ff
++#define NVREG_BKOFFCTRL_SELECT			24
++#define NVREG_BKOFFCTRL_GEAR			12
+ 
+ 	NvRegTxRingPhysAddr = 0x100,
+ 	NvRegRxRingPhysAddr = 0x104,
+@@ -441,6 +360,7 @@ union ring_type {
+ 
+ #define NV_TX_LASTPACKET	(1<<16)
+ #define NV_TX_RETRYERROR	(1<<19)
++#define NV_TX_RETRYCOUNT_MASK	(0xF<<20)
+ #define NV_TX_FORCED_INTERRUPT	(1<<24)
+ #define NV_TX_DEFERRED		(1<<26)
+ #define NV_TX_CARRIERLOST	(1<<27)
+@@ -451,6 +371,7 @@ union ring_type {
+ 
+ #define NV_TX2_LASTPACKET	(1<<29)
+ #define NV_TX2_RETRYERROR	(1<<18)
++#define NV_TX2_RETRYCOUNT_MASK	(0xF<<19)
+ #define NV_TX2_FORCED_INTERRUPT	(1<<30)
+ #define NV_TX2_DEFERRED		(1<<25)
+ #define NV_TX2_CARRIERLOST	(1<<26)
+@@ -562,16 +483,22 @@ union ring_type {
+ #define DESC_VER_3	3
+ 
+ /* PHY defines */
+-#define PHY_OUI_MARVELL	0x5043
+-#define PHY_OUI_CICADA	0x03f1
+-#define PHY_OUI_VITESSE	0x01c1
+-#define PHY_OUI_REALTEK	0x0732
++#define PHY_OUI_MARVELL		0x5043
++#define PHY_OUI_CICADA		0x03f1
++#define PHY_OUI_VITESSE		0x01c1
++#define PHY_OUI_REALTEK		0x0732
++#define PHY_OUI_REALTEK2	0x0020
+ #define PHYID1_OUI_MASK	0x03ff
+ #define PHYID1_OUI_SHFT	6
+ #define PHYID2_OUI_MASK	0xfc00
+ #define PHYID2_OUI_SHFT	10
+ #define PHYID2_MODEL_MASK		0x03f0
+-#define PHY_MODEL_MARVELL_E3016		0x220
++#define PHY_MODEL_REALTEK_8211		0x0110
++#define PHY_REV_MASK			0x0001
++#define PHY_REV_REALTEK_8211B		0x0000
++#define PHY_REV_REALTEK_8211C		0x0001
++#define PHY_MODEL_REALTEK_8201		0x0200
++#define PHY_MODEL_MARVELL_E3016		0x0220
+ #define PHY_MARVELL_E3016_INITMASK	0x0300
+ #define PHY_CICADA_INIT1	0x0f000
+ #define PHY_CICADA_INIT2	0x0e00
+@@ -598,10 +525,18 @@ union ring_type {
+ #define PHY_REALTEK_INIT_REG1	0x1f
+ #define PHY_REALTEK_INIT_REG2	0x19
+ #define PHY_REALTEK_INIT_REG3	0x13
++#define PHY_REALTEK_INIT_REG4	0x14
++#define PHY_REALTEK_INIT_REG5	0x18
++#define PHY_REALTEK_INIT_REG6	0x11
+ #define PHY_REALTEK_INIT1	0x0000
+ #define PHY_REALTEK_INIT2	0x8e00
+ #define PHY_REALTEK_INIT3	0x0001
+ #define PHY_REALTEK_INIT4	0xad17
++#define PHY_REALTEK_INIT5	0xfb54
++#define PHY_REALTEK_INIT6	0xf5c7
++#define PHY_REALTEK_INIT7	0x1000
++#define PHY_REALTEK_INIT8	0x0003
++#define PHY_REALTEK_INIT_MSK1	0x0003
+ 
+ #define PHY_GIGABIT	0x0100
+ 
+@@ -780,6 +715,7 @@ struct fe_priv {
+ 	int wolenabled;
+ 	unsigned int phy_oui;
+ 	unsigned int phy_model;
++	unsigned int phy_rev;
+ 	u16 gigabit;
+ 	int intr_test;
+ 	int recover_error;
+@@ -793,6 +729,7 @@ struct fe_priv {
+ 	u32 txrxctl_bits;
+ 	u32 vlanctl_bits;
+ 	u32 driver_data;
++	u32 device_id;
+ 	u32 register_size;
+ 	int rx_csum;
+ 	u32 mac_in_use;
+@@ -903,6 +840,16 @@ enum {
+ };
+ static int dma_64bit = NV_DMA_64BIT_ENABLED;
+ 
++/*
++ * Crossover Detection
++ * Realtek 8201 phy + some OEM boards do not work properly.
++ */
++enum {
++	NV_CROSSOVER_DETECTION_DISABLED,
++	NV_CROSSOVER_DETECTION_ENABLED
++};
++static int phy_cross = NV_CROSSOVER_DETECTION_DISABLED;
++
+ static inline struct fe_priv *get_nvpriv(struct net_device *dev)
+ {
+ 	return netdev_priv(dev);
+@@ -930,6 +877,13 @@ static inline u32 nv_descr_getlength_ex(struct ring_desc_ex *prd, u32 v)
+ 	return le32_to_cpu(prd->flaglen) & LEN_MASK_V2;
+ }
+ 
++static bool nv_optimized(struct fe_priv *np)
++{
++	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++		return false;
++	return true;
++}
++
+ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
+ 				int delay, int delaymax, const char *msg)
+ {
+@@ -966,7 +920,7 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
+ 	struct fe_priv *np = get_nvpriv(dev);
+ 	u8 __iomem *base = get_hwbase(dev);
+ 
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++	if (!nv_optimized(np)) {
+ 		if (rxtx_flags & NV_SETUP_RX_RING) {
+ 			writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr);
+ 		}
+@@ -989,7 +943,7 @@ static void free_rings(struct net_device *dev)
+ {
+ 	struct fe_priv *np = get_nvpriv(dev);
+ 
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++	if (!nv_optimized(np)) {
+ 		if (np->rx_ring.orig)
+ 			pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
+ 					    np->rx_ring.orig, np->ring_addr);
+@@ -1160,25 +1114,53 @@ static int phy_init(struct net_device *dev)
+ 		}
+ 	}
+ 	if (np->phy_oui == PHY_OUI_REALTEK) {
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
+-		}
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
+-		}
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
+-		}
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
++		if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
++		    np->phy_rev == PHY_REV_REALTEK_8211B) {
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
+ 		}
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
++		if (np->phy_model == PHY_MODEL_REALTEK_8201) {
++			if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
++				phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
++				phy_reserved |= PHY_REALTEK_INIT7;
++				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
++					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++					return PHY_ERROR;
++				}
++			}
+ 		}
+ 	}
+ 
+@@ -1318,26 +1300,71 @@ static int phy_init(struct net_device *dev)
+ 		}
+ 	}
+ 	if (np->phy_oui == PHY_OUI_REALTEK) {
+-		/* reset could have cleared these out, set them back */
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
+-		}
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
+-		}
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
+-		}
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
++		if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
++		    np->phy_rev == PHY_REV_REALTEK_8211B) {
++			/* reset could have cleared these out, set them back */
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
++			if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++				printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++				return PHY_ERROR;
++			}
+ 		}
+-		if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+-			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+-			return PHY_ERROR;
++		if (np->phy_model == PHY_MODEL_REALTEK_8201) {
++			if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
++			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
++				phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
++				phy_reserved |= PHY_REALTEK_INIT7;
++				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
++					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++					return PHY_ERROR;
++				}
++			}
++			if (phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
++				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
++					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++					return PHY_ERROR;
++				}
++				phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ);
++				phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
++				phy_reserved |= PHY_REALTEK_INIT3;
++				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved)) {
++					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++					return PHY_ERROR;
++				}
++				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++					printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++					return PHY_ERROR;
++				}
++			}
+ 		}
+ 	}
+ 
+@@ -1435,6 +1462,18 @@ static void nv_stop_tx(struct net_device *dev)
+ 		       base + NvRegTransmitPoll);
+ }
+ 
++static void nv_start_rxtx(struct net_device *dev)
++{
++	nv_start_rx(dev);
++	nv_start_tx(dev);
++}
++
++static void nv_stop_rxtx(struct net_device *dev)
++{
++	nv_stop_rx(dev);
++	nv_stop_tx(dev);
++}
++
+ static void nv_txrx_reset(struct net_device *dev)
+ {
+ 	struct fe_priv *np = netdev_priv(dev);
+@@ -1657,7 +1696,7 @@ static void nv_do_rx_refill(unsigned long data)
+ 	} else {
+ 		disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ 	}
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++	if (!nv_optimized(np))
+ 		retcode = nv_alloc_rx(dev);
+ 	else
+ 		retcode = nv_alloc_rx_optimized(dev);
+@@ -1682,8 +1721,10 @@ static void nv_init_rx(struct net_device *dev)
+ {
+ 	struct fe_priv *np = netdev_priv(dev);
+ 	int i;
++
+ 	np->get_rx = np->put_rx = np->first_rx = np->rx_ring;
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++
++	if (!nv_optimized(np))
+ 		np->last_rx.orig = &np->rx_ring.orig[np->rx_ring_size-1];
+ 	else
+ 		np->last_rx.ex = &np->rx_ring.ex[np->rx_ring_size-1];
+@@ -1691,7 +1732,7 @@ static void nv_init_rx(struct net_device *dev)
+ 	np->last_rx_ctx = &np->rx_skb[np->rx_ring_size-1];
+ 
+ 	for (i = 0; i < np->rx_ring_size; i++) {
+-		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++		if (!nv_optimized(np)) {
+ 			np->rx_ring.orig[i].flaglen = 0;
+ 			np->rx_ring.orig[i].buf = 0;
+ 		} else {
+@@ -1709,8 +1750,10 @@ static void nv_init_tx(struct net_device *dev)
+ {
+ 	struct fe_priv *np = netdev_priv(dev);
+ 	int i;
++
+ 	np->get_tx = np->put_tx = np->first_tx = np->tx_ring;
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++
++	if (!nv_optimized(np))
+ 		np->last_tx.orig = &np->tx_ring.orig[np->tx_ring_size-1];
+ 	else
+ 		np->last_tx.ex = &np->tx_ring.ex[np->tx_ring_size-1];
+@@ -1721,7 +1764,7 @@ static void nv_init_tx(struct net_device *dev)
+ 	np->tx_end_flip = NULL;
+ 
+ 	for (i = 0; i < np->tx_ring_size; i++) {
+-		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++		if (!nv_optimized(np)) {
+ 			np->tx_ring.orig[i].flaglen = 0;
+ 			np->tx_ring.orig[i].buf = 0;
+ 		} else {
+@@ -1744,7 +1787,8 @@ static int nv_init_ring(struct net_device *dev)
+ 
+ 	nv_init_tx(dev);
+ 	nv_init_rx(dev);
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++
++	if (!nv_optimized(np))
+ 		return nv_alloc_rx(dev);
+ 	else
+ 		return nv_alloc_rx_optimized(dev);
+@@ -1775,7 +1819,7 @@ static void nv_drain_tx(struct net_device *dev)
+ 	unsigned int i;
+ 
+ 	for (i = 0; i < np->tx_ring_size; i++) {
+-		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++		if (!nv_optimized(np)) {
+ 			np->tx_ring.orig[i].flaglen = 0;
+ 			np->tx_ring.orig[i].buf = 0;
+ 		} else {
+@@ -1802,7 +1846,7 @@ static void nv_drain_rx(struct net_device *dev)
+ 	int i;
+ 
+ 	for (i = 0; i < np->rx_ring_size; i++) {
+-		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++		if (!nv_optimized(np)) {
+ 			np->rx_ring.orig[i].flaglen = 0;
+ 			np->rx_ring.orig[i].buf = 0;
+ 		} else {
+@@ -1823,7 +1867,7 @@ static void nv_drain_rx(struct net_device *dev)
+ 	}
+ }
+ 
+-static void drain_ring(struct net_device *dev)
++static void nv_drain_rxtx(struct net_device *dev)
+ {
+ 	nv_drain_tx(dev);
+ 	nv_drain_rx(dev);
+@@ -1834,6 +1878,115 @@ static inline u32 nv_get_empty_tx_slots(struct fe_priv *np)
+ 	return (u32)(np->tx_ring_size - ((np->tx_ring_size + (np->put_tx_ctx - np->get_tx_ctx)) % np->tx_ring_size));
+ }
+ 
++static void nv_legacybackoff_reseed(struct net_device *dev)
++{
++	u8 __iomem *base = get_hwbase(dev);
++	u32 reg;
++	u32 low;
++	int tx_status = 0;
++
++	reg = readl(base + NvRegSlotTime) & ~NVREG_SLOTTIME_MASK;
++	get_random_bytes(&low, sizeof(low));
++	reg |= low & NVREG_SLOTTIME_MASK;
++
++	/* Need to stop tx before change takes effect.
++	 * Caller has already gained np->lock.
++	 */
++	tx_status = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START;
++	if (tx_status)
++		nv_stop_tx(dev);
++	nv_stop_rx(dev);
++	writel(reg, base + NvRegSlotTime);
++	if (tx_status)
++		nv_start_tx(dev);
++	nv_start_rx(dev);
++}
++
++/* Gear Backoff Seeds */
++#define BACKOFF_SEEDSET_ROWS	8
++#define BACKOFF_SEEDSET_LFSRS	15
++
++/* Known Good seed sets */
++static const u32 main_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
++    {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
++    {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974},
++    {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
++    {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974},
++    {266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984},
++    {266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984},
++    {366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800,  84},
++    {466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184}};
++
++static const u32 gear_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
++    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
++    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
++    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397},
++    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
++    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
++    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
++    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
++    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}};
++
++static void nv_gear_backoff_reseed(struct net_device *dev)
++{
++	u8 __iomem *base = get_hwbase(dev);
++	u32 miniseed1, miniseed2, miniseed2_reversed, miniseed3, miniseed3_reversed;
++	u32 temp, seedset, combinedSeed;
++	int i;
++
++	/* Setup seed for free running LFSR */
++	/* We are going to read the time stamp counter 3 times
++	   and swizzle bits around to increase randomness */
++	get_random_bytes(&miniseed1, sizeof(miniseed1));
++	miniseed1 &= 0x0fff;
++	if (miniseed1 == 0)
++		miniseed1 = 0xabc;
++
++	get_random_bytes(&miniseed2, sizeof(miniseed2));
++	miniseed2 &= 0x0fff;
++	if (miniseed2 == 0)
++		miniseed2 = 0xabc;
++	miniseed2_reversed =
++		((miniseed2 & 0xF00) >> 8) |
++		 (miniseed2 & 0x0F0) |
++		 ((miniseed2 & 0x00F) << 8);
++
++	get_random_bytes(&miniseed3, sizeof(miniseed3));
++	miniseed3 &= 0x0fff;
++	if (miniseed3 == 0)
++		miniseed3 = 0xabc;
++	miniseed3_reversed =
++		((miniseed3 & 0xF00) >> 8) |
++		 (miniseed3 & 0x0F0) |
++		 ((miniseed3 & 0x00F) << 8);
++
++	combinedSeed = ((miniseed1 ^ miniseed2_reversed) << 12) |
++		       (miniseed2 ^ miniseed3_reversed);
++
++	/* Seeds can not be zero */
++	if ((combinedSeed & NVREG_BKOFFCTRL_SEED_MASK) == 0)
++		combinedSeed |= 0x08;
++	if ((combinedSeed & (NVREG_BKOFFCTRL_SEED_MASK << NVREG_BKOFFCTRL_GEAR)) == 0)
++		combinedSeed |= 0x8000;
++
++	/* No need to disable tx here */
++	temp = NVREG_BKOFFCTRL_DEFAULT | (0 << NVREG_BKOFFCTRL_SELECT);
++	temp |= combinedSeed & NVREG_BKOFFCTRL_SEED_MASK;
++	temp |= combinedSeed >> NVREG_BKOFFCTRL_GEAR;
++	writel(temp,base + NvRegBackOffControl);
++
++    	/* Setup seeds for all gear LFSRs. */
++	get_random_bytes(&seedset, sizeof(seedset));
++	seedset = seedset % BACKOFF_SEEDSET_ROWS;
++	for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; i++)
++	{
++		temp = NVREG_BKOFFCTRL_DEFAULT | (i << NVREG_BKOFFCTRL_SELECT);
++		temp |= main_seedset[seedset][i-1] & 0x3ff;
++		temp |= ((gear_seedset[seedset][i-1] & 0x3ff) << NVREG_BKOFFCTRL_GEAR);
++		writel(temp, base + NvRegBackOffControl);
++	}
++}
++
+ /*
+  * nv_start_xmit: dev->hard_start_xmit function
+  * Called with netif_tx_lock held.
+@@ -2153,6 +2306,8 @@ static void nv_tx_done(struct net_device *dev)
+ 						dev->stats.tx_fifo_errors++;
+ 					if (flags & NV_TX_CARRIERLOST)
+ 						dev->stats.tx_carrier_errors++;
++					if ((flags & NV_TX_RETRYERROR) && !(flags & NV_TX_RETRYCOUNT_MASK))
++						nv_legacybackoff_reseed(dev);
+ 					dev->stats.tx_errors++;
+ 				} else {
+ 					dev->stats.tx_packets++;
+@@ -2168,6 +2323,8 @@ static void nv_tx_done(struct net_device *dev)
+ 						dev->stats.tx_fifo_errors++;
+ 					if (flags & NV_TX2_CARRIERLOST)
+ 						dev->stats.tx_carrier_errors++;
++					if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK))
++						nv_legacybackoff_reseed(dev);
+ 					dev->stats.tx_errors++;
+ 				} else {
+ 					dev->stats.tx_packets++;
+@@ -2209,6 +2366,15 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit)
+ 		if (flags & NV_TX2_LASTPACKET) {
+ 			if (!(flags & NV_TX2_ERROR))
+ 				dev->stats.tx_packets++;
++			else {
++				if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK)) {
++					if (np->driver_data & DEV_HAS_GEAR_MODE)
++						nv_gear_backoff_reseed(dev);
++					else
++						nv_legacybackoff_reseed(dev);
++				}
++			}
++
+ 			dev_kfree_skb_any(np->get_tx_ctx->skb);
+ 			np->get_tx_ctx->skb = NULL;
+ 
+@@ -2260,7 +2426,7 @@ static void nv_tx_timeout(struct net_device *dev)
+ 		}
+ 		printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
+ 		for (i=0;i<np->tx_ring_size;i+= 4) {
+-			if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++			if (!nv_optimized(np)) {
+ 				printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
+ 				       i,
+ 				       le32_to_cpu(np->tx_ring.orig[i].buf),
+@@ -2296,7 +2462,7 @@ static void nv_tx_timeout(struct net_device *dev)
+ 	nv_stop_tx(dev);
+ 
+ 	/* 2) check that the packets were not sent already: */
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++	if (!nv_optimized(np))
+ 		nv_tx_done(dev);
+ 	else
+ 		nv_tx_done_optimized(dev, np->tx_ring_size);
+@@ -2663,12 +2829,10 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
+ 		netif_tx_lock_bh(dev);
+ 		spin_lock(&np->lock);
+ 		/* stop engines */
+-		nv_stop_rx(dev);
+-		nv_stop_tx(dev);
++		nv_stop_rxtx(dev);
+ 		nv_txrx_reset(dev);
+ 		/* drain rx queue */
+-		nv_drain_rx(dev);
+-		nv_drain_tx(dev);
++		nv_drain_rxtx(dev);
+ 		/* reinit driver view of the rx queue */
+ 		set_bufsize(dev);
+ 		if (nv_init_ring(dev)) {
+@@ -2685,8 +2849,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
+ 		pci_push(base);
+ 
+ 		/* restart rx engine */
+-		nv_start_rx(dev);
+-		nv_start_tx(dev);
++		nv_start_rxtx(dev);
+ 		spin_unlock(&np->lock);
+ 		netif_tx_unlock_bh(dev);
+ 		nv_enable_irq(dev);
+@@ -2973,15 +3136,14 @@ set_speed:
+ 	}
+ 
+ 	if (np->gigabit == PHY_GIGABIT) {
+-		phyreg = readl(base + NvRegRandomSeed);
++		phyreg = readl(base + NvRegSlotTime);
+ 		phyreg &= ~(0x3FF00);
+-		if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
+-			phyreg |= NVREG_RNDSEED_FORCE3;
+-		else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
+-			phyreg |= NVREG_RNDSEED_FORCE2;
++		if (((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) ||
++		    ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100))
++			phyreg |= NVREG_SLOTTIME_10_100_FULL;
+ 		else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
+-			phyreg |= NVREG_RNDSEED_FORCE;
+-		writel(phyreg, base + NvRegRandomSeed);
++			phyreg |= NVREG_SLOTTIME_1000_FULL;
++		writel(phyreg, base + NvRegSlotTime);
+ 	}
+ 
+ 	phyreg = readl(base + NvRegPhyInterface);
+@@ -3393,7 +3555,7 @@ static int nv_napi_poll(struct napi_struct *napi, int budget)
+ 	unsigned long flags;
+ 	int pkts, retcode;
+ 
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++	if (!nv_optimized(np)) {
+ 		pkts = nv_rx_process(dev, budget);
+ 		retcode = nv_alloc_rx(dev);
+ 	} else {
+@@ -3634,7 +3796,7 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
+ 	if (intr_test) {
+ 		handler = nv_nic_irq_test;
+ 	} else {
+-		if (np->desc_ver == DESC_VER_3)
++		if (nv_optimized(np))
+ 			handler = nv_nic_irq_optimized;
+ 		else
+ 			handler = nv_nic_irq;
+@@ -3787,12 +3949,10 @@ static void nv_do_nic_poll(unsigned long data)
+ 			netif_tx_lock_bh(dev);
+ 			spin_lock(&np->lock);
+ 			/* stop engines */
+-			nv_stop_rx(dev);
+-			nv_stop_tx(dev);
++			nv_stop_rxtx(dev);
+ 			nv_txrx_reset(dev);
+ 			/* drain rx queue */
+-			nv_drain_rx(dev);
+-			nv_drain_tx(dev);
++			nv_drain_rxtx(dev);
+ 			/* reinit driver view of the rx queue */
+ 			set_bufsize(dev);
+ 			if (nv_init_ring(dev)) {
+@@ -3809,8 +3969,7 @@ static void nv_do_nic_poll(unsigned long data)
+ 			pci_push(base);
+ 
+ 			/* restart rx engine */
+-			nv_start_rx(dev);
+-			nv_start_tx(dev);
++			nv_start_rxtx(dev);
+ 			spin_unlock(&np->lock);
+ 			netif_tx_unlock_bh(dev);
+ 		}
+@@ -3821,7 +3980,7 @@ static void nv_do_nic_poll(unsigned long data)
+ 	pci_push(base);
+ 
+ 	if (!using_multi_irqs(dev)) {
+-		if (np->desc_ver == DESC_VER_3)
++		if (nv_optimized(np))
+ 			nv_nic_irq_optimized(0, dev);
+ 		else
+ 			nv_nic_irq(0, dev);
+@@ -3860,7 +4019,8 @@ static void nv_do_stats_poll(unsigned long data)
+ 	nv_get_hw_stats(dev);
+ 
+ 	if (!np->in_shutdown)
+-		mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
++		mod_timer(&np->stats_poll,
++			round_jiffies(jiffies + STATS_INTERVAL));
+ }
+ 
+ static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+@@ -4018,8 +4178,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ 		netif_tx_lock_bh(dev);
+ 		spin_lock(&np->lock);
+ 		/* stop engines */
+-		nv_stop_rx(dev);
+-		nv_stop_tx(dev);
++		nv_stop_rxtx(dev);
+ 		spin_unlock(&np->lock);
+ 		netif_tx_unlock_bh(dev);
+ 	}
+@@ -4125,8 +4284,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ 	}
+ 
+ 	if (netif_running(dev)) {
+-		nv_start_rx(dev);
+-		nv_start_tx(dev);
++		nv_start_rxtx(dev);
+ 		nv_enable_irq(dev);
+ 	}
+ 
+@@ -4169,8 +4327,7 @@ static int nv_nway_reset(struct net_device *dev)
+ 			netif_tx_lock_bh(dev);
+ 			spin_lock(&np->lock);
+ 			/* stop engines */
+-			nv_stop_rx(dev);
+-			nv_stop_tx(dev);
++			nv_stop_rxtx(dev);
+ 			spin_unlock(&np->lock);
+ 			netif_tx_unlock_bh(dev);
+ 			printk(KERN_INFO "%s: link down.\n", dev->name);
+@@ -4190,8 +4347,7 @@ static int nv_nway_reset(struct net_device *dev)
+ 		}
+ 
+ 		if (netif_running(dev)) {
+-			nv_start_rx(dev);
+-			nv_start_tx(dev);
++			nv_start_rxtx(dev);
+ 			nv_enable_irq(dev);
+ 		}
+ 		ret = 0;
+@@ -4248,7 +4404,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ 	}
+ 
+ 	/* allocate new rings */
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++	if (!nv_optimized(np)) {
+ 		rxtx_ring = pci_alloc_consistent(np->pci_dev,
+ 					    sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
+ 					    &ring_addr);
+@@ -4261,7 +4417,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ 	tx_skbuff = kmalloc(sizeof(struct nv_skb_map) * ring->tx_pending, GFP_KERNEL);
+ 	if (!rxtx_ring || !rx_skbuff || !tx_skbuff) {
+ 		/* fall back to old rings */
+-		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++		if (!nv_optimized(np)) {
+ 			if (rxtx_ring)
+ 				pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
+ 						    rxtx_ring, ring_addr);
+@@ -4282,12 +4438,10 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ 		netif_tx_lock_bh(dev);
+ 		spin_lock(&np->lock);
+ 		/* stop engines */
+-		nv_stop_rx(dev);
+-		nv_stop_tx(dev);
++		nv_stop_rxtx(dev);
+ 		nv_txrx_reset(dev);
+ 		/* drain queues */
+-		nv_drain_rx(dev);
+-		nv_drain_tx(dev);
++		nv_drain_rxtx(dev);
+ 		/* delete queues */
+ 		free_rings(dev);
+ 	}
+@@ -4295,7 +4449,8 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ 	/* set new values */
+ 	np->rx_ring_size = ring->rx_pending;
+ 	np->tx_ring_size = ring->tx_pending;
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++
++	if (!nv_optimized(np)) {
+ 		np->rx_ring.orig = (struct ring_desc*)rxtx_ring;
+ 		np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size];
+ 	} else {
+@@ -4327,8 +4482,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ 		pci_push(base);
+ 
+ 		/* restart engines */
+-		nv_start_rx(dev);
+-		nv_start_tx(dev);
++		nv_start_rxtx(dev);
+ 		spin_unlock(&np->lock);
+ 		netif_tx_unlock_bh(dev);
+ 		nv_enable_irq(dev);
+@@ -4369,8 +4523,7 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
+ 		netif_tx_lock_bh(dev);
+ 		spin_lock(&np->lock);
+ 		/* stop engines */
+-		nv_stop_rx(dev);
+-		nv_stop_tx(dev);
++		nv_stop_rxtx(dev);
+ 		spin_unlock(&np->lock);
+ 		netif_tx_unlock_bh(dev);
+ 	}
+@@ -4411,8 +4564,7 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
+ 	}
+ 
+ 	if (netif_running(dev)) {
+-		nv_start_rx(dev);
+-		nv_start_tx(dev);
++		nv_start_rxtx(dev);
+ 		nv_enable_irq(dev);
+ 	}
+ 	return 0;
+@@ -4648,8 +4800,7 @@ static int nv_loopback_test(struct net_device *dev)
+ 	pci_push(base);
+ 
+ 	/* restart rx engine */
+-	nv_start_rx(dev);
+-	nv_start_tx(dev);
++	nv_start_rxtx(dev);
+ 
+ 	/* setup packet for tx */
+ 	pkt_len = ETH_DATA_LEN;
+@@ -4667,7 +4818,7 @@ static int nv_loopback_test(struct net_device *dev)
+ 	for (i = 0; i < pkt_len; i++)
+ 		pkt_data[i] = (u8)(i & 0xff);
+ 
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++	if (!nv_optimized(np)) {
+ 		np->tx_ring.orig[0].buf = cpu_to_le32(test_dma_addr);
+ 		np->tx_ring.orig[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+ 	} else {
+@@ -4681,7 +4832,7 @@ static int nv_loopback_test(struct net_device *dev)
+ 	msleep(500);
+ 
+ 	/* check for rx of the packet */
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++	if (!nv_optimized(np)) {
+ 		flags = le32_to_cpu(np->rx_ring.orig[0].flaglen);
+ 		len = nv_descr_getlength(&np->rx_ring.orig[0], np->desc_ver);
+ 
+@@ -4727,12 +4878,10 @@ static int nv_loopback_test(struct net_device *dev)
+ 	dev_kfree_skb_any(tx_skb);
+  out:
+ 	/* stop engines */
+-	nv_stop_rx(dev);
+-	nv_stop_tx(dev);
++	nv_stop_rxtx(dev);
+ 	nv_txrx_reset(dev);
+ 	/* drain rx queue */
+-	nv_drain_rx(dev);
+-	nv_drain_tx(dev);
++	nv_drain_rxtx(dev);
+ 
+ 	if (netif_running(dev)) {
+ 		writel(misc1_flags, base + NvRegMisc1);
+@@ -4770,12 +4919,10 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
+ 				writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
+ 			}
+ 			/* stop engines */
+-			nv_stop_rx(dev);
+-			nv_stop_tx(dev);
++			nv_stop_rxtx(dev);
+ 			nv_txrx_reset(dev);
+ 			/* drain rx queue */
+-			nv_drain_rx(dev);
+-			nv_drain_tx(dev);
++			nv_drain_rxtx(dev);
+ 			spin_unlock_irq(&np->lock);
+ 			netif_tx_unlock_bh(dev);
+ 		}
+@@ -4816,8 +4963,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
+ 			writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+ 			pci_push(base);
+ 			/* restart rx engine */
+-			nv_start_rx(dev);
+-			nv_start_tx(dev);
++			nv_start_rxtx(dev);
+ 			netif_start_queue(dev);
+ #ifdef CONFIG_FORCEDETH_NAPI
+ 			napi_enable(&np->napi);
+@@ -4927,6 +5073,7 @@ static int nv_open(struct net_device *dev)
+ 	u8 __iomem *base = get_hwbase(dev);
+ 	int ret = 1;
+ 	int oom, i;
++	u32 low;
+ 
+ 	dprintk(KERN_DEBUG "nv_open: begin\n");
+ 
+@@ -4986,8 +5133,20 @@ static int nv_open(struct net_device *dev)
+ 	writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+ 
+ 	writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
+-	get_random_bytes(&i, sizeof(i));
+-	writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
++
++	get_random_bytes(&low, sizeof(low));
++	low &= NVREG_SLOTTIME_MASK;
++	if (np->desc_ver == DESC_VER_1) {
++		writel(low|NVREG_SLOTTIME_DEFAULT, base + NvRegSlotTime);
++	} else {
++		if (!(np->driver_data & DEV_HAS_GEAR_MODE)) {
++			/* setup legacy backoff */
++			writel(NVREG_SLOTTIME_LEGBF_ENABLED|NVREG_SLOTTIME_10_100_FULL|low, base + NvRegSlotTime);
++		} else {
++			writel(NVREG_SLOTTIME_10_100_FULL, base + NvRegSlotTime);
++			nv_gear_backoff_reseed(dev);
++		}
++	}
+ 	writel(NVREG_TX_DEFERRAL_DEFAULT, base + NvRegTxDeferral);
+ 	writel(NVREG_RX_DEFERRAL_DEFAULT, base + NvRegRxDeferral);
+ 	if (poll_interval == -1) {
+@@ -5046,8 +5205,7 @@ static int nv_open(struct net_device *dev)
+ 	 * to init hw */
+ 	np->linkspeed = 0;
+ 	ret = nv_update_linkspeed(dev);
+-	nv_start_rx(dev);
+-	nv_start_tx(dev);
++	nv_start_rxtx(dev);
+ 	netif_start_queue(dev);
+ #ifdef CONFIG_FORCEDETH_NAPI
+ 	napi_enable(&np->napi);
+@@ -5064,13 +5222,14 @@ static int nv_open(struct net_device *dev)
+ 
+ 	/* start statistics timer */
+ 	if (np->driver_data & (DEV_HAS_STATISTICS_V1|DEV_HAS_STATISTICS_V2))
+-		mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
++		mod_timer(&np->stats_poll,
++			round_jiffies(jiffies + STATS_INTERVAL));
+ 
+ 	spin_unlock_irq(&np->lock);
+ 
+ 	return 0;
+ out_drain:
+-	drain_ring(dev);
++	nv_drain_rxtx(dev);
+ 	return ret;
+ }
+ 
+@@ -5093,8 +5252,7 @@ static int nv_close(struct net_device *dev)
+ 
+ 	netif_stop_queue(dev);
+ 	spin_lock_irq(&np->lock);
+-	nv_stop_tx(dev);
+-	nv_stop_rx(dev);
++	nv_stop_rxtx(dev);
+ 	nv_txrx_reset(dev);
+ 
+ 	/* disable interrupts on the nic or we will lock up */
+@@ -5107,7 +5265,7 @@ static int nv_close(struct net_device *dev)
+ 
+ 	nv_free_irq(dev);
+ 
+-	drain_ring(dev);
++	nv_drain_rxtx(dev);
+ 
+ 	if (np->wolenabled) {
+ 		writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
+@@ -5195,6 +5353,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
+ 
+ 	/* copy of driver data */
+ 	np->driver_data = id->driver_data;
++	/* copy of device id */
++	np->device_id = id->device;
+ 
+ 	/* handle different descriptor versions */
+ 	if (id->driver_data & DEV_HAS_HIGH_DMA) {
+@@ -5267,7 +5427,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
+ 	np->rx_ring_size = RX_RING_DEFAULT;
+ 	np->tx_ring_size = TX_RING_DEFAULT;
+ 
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++	if (!nv_optimized(np)) {
+ 		np->rx_ring.orig = pci_alloc_consistent(pci_dev,
+ 					sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
+ 					&np->ring_addr);
+@@ -5289,7 +5449,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
+ 
+ 	dev->open = nv_open;
+ 	dev->stop = nv_close;
+-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++
++	if (!nv_optimized(np))
+ 		dev->hard_start_xmit = nv_start_xmit;
+ 	else
+ 		dev->hard_start_xmit = nv_start_xmit_optimized;
+@@ -5483,6 +5644,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
+ 			pci_name(pci_dev), id1, id2, phyaddr);
+ 		np->phyaddr = phyaddr;
+ 		np->phy_oui = id1 | id2;
++
++		/* Realtek hardcoded phy id1 to all zero's on certain phys */
++		if (np->phy_oui == PHY_OUI_REALTEK2)
++			np->phy_oui = PHY_OUI_REALTEK;
++		/* Setup phy revision for Realtek */
++		if (np->phy_oui == PHY_OUI_REALTEK && np->phy_model == PHY_MODEL_REALTEK_8211)
++			np->phy_rev = mii_rw(dev, phyaddr, MII_RESV1, MII_READ) & PHY_REV_MASK;
++
+ 		break;
+ 	}
+ 	if (i == 33) {
+@@ -5561,6 +5730,28 @@ out:
+ 	return err;
+ }
+ 
++static void nv_restore_phy(struct net_device *dev)
++{
++	struct fe_priv *np = netdev_priv(dev);
++	u16 phy_reserved, mii_control;
++
++	if (np->phy_oui == PHY_OUI_REALTEK &&
++	    np->phy_model == PHY_MODEL_REALTEK_8201 &&
++	    phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
++		mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3);
++		phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ);
++		phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
++		phy_reserved |= PHY_REALTEK_INIT8;
++		mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved);
++		mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1);
++
++		/* restart auto negotiation */
++		mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
++		mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
++		mii_rw(dev, np->phyaddr, MII_BMCR, mii_control);
++	}
++}
++
+ static void __devexit nv_remove(struct pci_dev *pci_dev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pci_dev);
+@@ -5577,6 +5768,9 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
+ 	writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV,
+ 	       base + NvRegTransmitPoll);
+ 
++	/* restore any phy related changes */
++	nv_restore_phy(dev);
++
+ 	/* free all structures */
+ 	free_rings(dev);
+ 	iounmap(get_hwbase(dev));
+@@ -5716,83 +5910,83 @@ static struct pci_device_id pci_tbl[] = {
+ 	},
+ 	{	/* MCP65 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP65 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP65 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP65 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP67 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP67 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP67 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP67 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP73 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP73 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP73 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP73 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP77 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP77 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP77 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP77 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP79 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP79 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP79 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{	/* MCP79 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ 	},
+ 	{0,},
+ };
+@@ -5828,6 +6022,8 @@ module_param(msix, int, 0);
+ MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0.");
+ module_param(dma_64bit, int, 0);
+ MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0.");
++module_param(phy_cross, int, 0);
++MODULE_PARM_DESC(phy_cross, "Phy crossover detection for Realtek 8201 phy is enabled by setting to 1 and disabled by setting to 0.");
+ 
+ MODULE_AUTHOR("Manfred Spraul <manfred at colorfullife.com>");
+ MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
+diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
+index 940e204..67b4b07 100644
+--- a/drivers/net/fs_enet/fs_enet-main.c
++++ b/drivers/net/fs_enet/fs_enet-main.c
+@@ -1178,7 +1178,7 @@ static int __devinit find_phy(struct device_node *np,
+ 
+ 	data  = of_get_property(np, "fixed-link", NULL);
+ 	if (data) {
+-		snprintf(fpi->bus_id, 16, PHY_ID_FMT, 0, *data);
++		snprintf(fpi->bus_id, 16, "%x:%02x", 0, *data);
+ 		return 0;
+ 	}
+ 
+@@ -1202,7 +1202,7 @@ static int __devinit find_phy(struct device_node *np,
+ 	if (!data || len != 4)
+ 		goto out_put_mdio;
+ 
+-	snprintf(fpi->bus_id, 16, PHY_ID_FMT, res.start, *data);
++	snprintf(fpi->bus_id, 16, "%x:%02x", res.start, *data);
+ 
+ out_put_mdio:
+ 	of_node_put(mdionode);
+diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
+index b8e4a73..1620030 100644
+--- a/drivers/net/fs_enet/mii-bitbang.c
++++ b/drivers/net/fs_enet/mii-bitbang.c
+@@ -130,7 +130,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
+ 	 * we get is an int, and the odds of multiple bitbang mdio buses
+ 	 * is low enough that it's not worth going too crazy.
+ 	 */
+-	bus->id = res.start;
++	snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ 
+ 	data = of_get_property(np, "fsl,mdio-pin", &len);
+ 	if (!data || len != 4)
+@@ -307,7 +307,7 @@ static int __devinit fs_enet_mdio_probe(struct device *dev)
+ 		return -ENOMEM;
+ 
+ 	new_bus->name = "BB MII Bus",
+-	new_bus->id = pdev->id;
++	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+ 
+ 	new_bus->phy_mask = ~0x9;
+ 	pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
+diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
+index a89cf15..ba75efc 100644
+--- a/drivers/net/fs_enet/mii-fec.c
++++ b/drivers/net/fs_enet/mii-fec.c
+@@ -196,7 +196,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
+ 	if (ret)
+ 		return ret;
+ 
+-	new_bus->id = res.start;
++	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ 
+ 	fec->fecp = ioremap(res.start, res.end - res.start + 1);
+ 	if (!fec->fecp)
+@@ -309,7 +309,7 @@ static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
+ 	new_bus->read = &fs_enet_fec_mii_read,
+ 	new_bus->write = &fs_enet_fec_mii_write,
+ 	new_bus->reset = &fs_enet_fec_mii_reset,
+-	new_bus->id = pdev->id;
++	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+ 
+ 	pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
+ 
+diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
+index 718cf77..99a4b99 100644
+--- a/drivers/net/gianfar.c
++++ b/drivers/net/gianfar.c
+@@ -98,7 +98,6 @@
+ #include "gianfar_mii.h"
+ 
+ #define TX_TIMEOUT      (1*HZ)
+-#define SKB_ALLOC_TIMEOUT 1000000
+ #undef BRIEF_GFAR_ERRORS
+ #undef VERBOSE_GFAR_ERRORS
+ 
+@@ -115,7 +114,9 @@ static int gfar_enet_open(struct net_device *dev);
+ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
+ static void gfar_timeout(struct net_device *dev);
+ static int gfar_close(struct net_device *dev);
+-struct sk_buff *gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp);
++struct sk_buff *gfar_new_skb(struct net_device *dev);
++static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
++		struct sk_buff *skb);
+ static int gfar_set_mac_address(struct net_device *dev);
+ static int gfar_change_mtu(struct net_device *dev, int new_mtu);
+ static irqreturn_t gfar_error(int irq, void *dev_id);
+@@ -783,14 +784,21 @@ int startup_gfar(struct net_device *dev)
+ 
+ 	rxbdp = priv->rx_bd_base;
+ 	for (i = 0; i < priv->rx_ring_size; i++) {
+-		struct sk_buff *skb = NULL;
++		struct sk_buff *skb;
+ 
+-		rxbdp->status = 0;
++		skb = gfar_new_skb(dev);
+ 
+-		skb = gfar_new_skb(dev, rxbdp);
++		if (!skb) {
++			printk(KERN_ERR "%s: Can't allocate RX buffers\n",
++					dev->name);
++
++			goto err_rxalloc_fail;
++		}
+ 
+ 		priv->rx_skbuff[i] = skb;
+ 
++		gfar_new_rxbdp(dev, rxbdp, skb);
++
+ 		rxbdp++;
+ 	}
+ 
+@@ -916,6 +924,7 @@ rx_irq_fail:
+ tx_irq_fail:
+ 	free_irq(priv->interruptError, dev);
+ err_irq_fail:
++err_rxalloc_fail:	
+ rx_skb_fail:
+ 	free_skb_resources(priv);
+ tx_skb_fail:
+@@ -1185,7 +1194,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
+ 	int frame_size = new_mtu + ETH_HLEN;
+ 
+ 	if (priv->vlan_enable)
+-		frame_size += VLAN_ETH_HLEN;
++		frame_size += VLAN_HLEN;
+ 
+ 	if (gfar_uses_fcb(priv))
+ 		frame_size += GMAC_FCB_LEN;
+@@ -1250,17 +1259,12 @@ static void gfar_timeout(struct net_device *dev)
+ }
+ 
+ /* Interrupt Handler for Transmit complete */
+-static irqreturn_t gfar_transmit(int irq, void *dev_id)
++int gfar_clean_tx_ring(struct net_device *dev)
+ {
+-	struct net_device *dev = (struct net_device *) dev_id;
+-	struct gfar_private *priv = netdev_priv(dev);
+ 	struct txbd8 *bdp;
++	struct gfar_private *priv = netdev_priv(dev);
++	int howmany = 0;
+ 
+-	/* Clear IEVENT */
+-	gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
+-
+-	/* Lock priv */
+-	spin_lock(&priv->txlock);
+ 	bdp = priv->dirty_tx;
+ 	while ((bdp->status & TXBD_READY) == 0) {
+ 		/* If dirty_tx and cur_tx are the same, then either the */
+@@ -1269,7 +1273,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
+ 		if ((bdp == priv->cur_tx) && (netif_queue_stopped(dev) == 0))
+ 			break;
+ 
+-		dev->stats.tx_packets++;
++		howmany++;
+ 
+ 		/* Deferred means some collisions occurred during transmit, */
+ 		/* but we eventually sent the packet. */
+@@ -1278,11 +1282,15 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
+ 
+ 		/* Free the sk buffer associated with this TxBD */
+ 		dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]);
++
+ 		priv->tx_skbuff[priv->skb_dirtytx] = NULL;
+ 		priv->skb_dirtytx =
+ 		    (priv->skb_dirtytx +
+ 		     1) & TX_RING_MOD_MASK(priv->tx_ring_size);
+ 
++		/* Clean BD length for empty detection */
++		bdp->length = 0;
++
+ 		/* update bdp to point at next bd in the ring (wrapping if necessary) */
+ 		if (bdp->status & TXBD_WRAP)
+ 			bdp = priv->tx_bd_base;
+@@ -1297,31 +1305,69 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
+ 			netif_wake_queue(dev);
+ 	} /* while ((bdp->status & TXBD_READY) == 0) */
+ 
++	dev->stats.tx_packets += howmany;
++
++	return howmany;
++}
++
++/* Interrupt Handler for Transmit complete */
++static irqreturn_t gfar_transmit(int irq, void *dev_id)
++{
++	struct net_device *dev = (struct net_device *) dev_id;
++	struct gfar_private *priv = netdev_priv(dev);
++
++	/* Clear IEVENT */
++	gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
++
++	/* Lock priv */
++	spin_lock(&priv->txlock);
++
++	gfar_clean_tx_ring(dev);
++
+ 	/* If we are coalescing the interrupts, reset the timer */
+ 	/* Otherwise, clear it */
+-	if (priv->txcoalescing)
++	if (likely(priv->txcoalescing)) {
++		gfar_write(&priv->regs->txic, 0);
+ 		gfar_write(&priv->regs->txic,
+ 			   mk_ic_value(priv->txcount, priv->txtime));
+-	else
+-		gfar_write(&priv->regs->txic, 0);
++	}
+ 
+ 	spin_unlock(&priv->txlock);
+ 
+ 	return IRQ_HANDLED;
+ }
+ 
+-struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
++static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
++		struct sk_buff *skb)
++{
++	struct gfar_private *priv = netdev_priv(dev);
++	u32 * status_len = (u32 *)bdp;
++	u16 flags;
++
++	bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
++			priv->rx_buffer_size, DMA_FROM_DEVICE);
++
++	flags = RXBD_EMPTY | RXBD_INTERRUPT;
++
++	if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
++		flags |= RXBD_WRAP;
++
++	eieio();
++
++	*status_len = (u32)flags << 16;
++}
++
++
++struct sk_buff * gfar_new_skb(struct net_device *dev)
+ {
+ 	unsigned int alignamount;
+ 	struct gfar_private *priv = netdev_priv(dev);
+ 	struct sk_buff *skb = NULL;
+-	unsigned int timeout = SKB_ALLOC_TIMEOUT;
+ 
+ 	/* We have to allocate the skb, so keep trying till we succeed */
+-	while ((!skb) && timeout--)
+-		skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
++	skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
+ 
+-	if (NULL == skb)
++	if (!skb)
+ 		return NULL;
+ 
+ 	alignamount = RXBUF_ALIGNMENT -
+@@ -1332,15 +1378,6 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
+ 	 */
+ 	skb_reserve(skb, alignamount);
+ 
+-	bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
+-			priv->rx_buffer_size, DMA_FROM_DEVICE);
+-
+-	bdp->length = 0;
+-
+-	/* Mark the buffer empty */
+-	eieio();
+-	bdp->status |= (RXBD_EMPTY | RXBD_INTERRUPT);
+-
+ 	return skb;
+ }
+ 
+@@ -1392,15 +1429,15 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
+ 	unsigned long flags;
+ #endif
+ 
+-	/* Clear IEVENT, so rx interrupt isn't called again
+-	 * because of this interrupt */
+-	gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
+-
+ 	/* support NAPI */
+ #ifdef CONFIG_GFAR_NAPI
++	/* Clear IEVENT, so interrupts aren't called again
++	 * because of the packets that have already arrived */
++	gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK);
++
+ 	if (netif_rx_schedule_prep(dev, &priv->napi)) {
+ 		tempval = gfar_read(&priv->regs->imask);
+-		tempval &= IMASK_RX_DISABLED;
++		tempval &= IMASK_RTX_DISABLED;
+ 		gfar_write(&priv->regs->imask, tempval);
+ 
+ 		__netif_rx_schedule(dev, &priv->napi);
+@@ -1411,17 +1448,20 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
+ 				gfar_read(&priv->regs->imask));
+ 	}
+ #else
++	/* Clear IEVENT, so rx interrupt isn't called again
++	 * because of this interrupt */
++	gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
+ 
+ 	spin_lock_irqsave(&priv->rxlock, flags);
+ 	gfar_clean_rx_ring(dev, priv->rx_ring_size);
+ 
+ 	/* If we are coalescing interrupts, update the timer */
+ 	/* Otherwise, clear it */
+-	if (priv->rxcoalescing)
++	if (likely(priv->rxcoalescing)) {
++		gfar_write(&priv->regs->rxic, 0);
+ 		gfar_write(&priv->regs->rxic,
+ 			   mk_ic_value(priv->rxcount, priv->rxtime));
+-	else
+-		gfar_write(&priv->regs->rxic, 0);
++	}
+ 
+ 	spin_unlock_irqrestore(&priv->rxlock, flags);
+ #endif
+@@ -1523,12 +1563,31 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+ 	bdp = priv->cur_rx;
+ 
+ 	while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
++		struct sk_buff *newskb;
+ 		rmb();
++
++		/* Add another skb for the future */
++		newskb = gfar_new_skb(dev);
++
+ 		skb = priv->rx_skbuff[priv->skb_currx];
+ 
+-		if (!(bdp->status &
+-		      (RXBD_LARGE | RXBD_SHORT | RXBD_NONOCTET
+-		       | RXBD_CRCERR | RXBD_OVERRUN | RXBD_TRUNCATED))) {
++		/* We drop the frame if we failed to allocate a new buffer */
++		if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
++				 bdp->status & RXBD_ERR)) {
++			count_errors(bdp->status, dev);
++
++			if (unlikely(!newskb))
++				newskb = skb;
++
++			if (skb) {
++				dma_unmap_single(&priv->dev->dev,
++						bdp->bufPtr,
++						priv->rx_buffer_size,
++						DMA_FROM_DEVICE);
++
++				dev_kfree_skb_any(skb);
++			}
++		} else {
+ 			/* Increment the number of packets */
+ 			dev->stats.rx_packets++;
+ 			howmany++;
+@@ -1539,23 +1598,14 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+ 			gfar_process_frame(dev, skb, pkt_len);
+ 
+ 			dev->stats.rx_bytes += pkt_len;
+-		} else {
+-			count_errors(bdp->status, dev);
+-
+-			if (skb)
+-				dev_kfree_skb_any(skb);
+-
+-			priv->rx_skbuff[priv->skb_currx] = NULL;
+ 		}
+ 
+ 		dev->last_rx = jiffies;
+ 
+-		/* Clear the status flags for this buffer */
+-		bdp->status &= ~RXBD_STATS;
++		priv->rx_skbuff[priv->skb_currx] = newskb;
+ 
+-		/* Add another skb for the future */
+-		skb = gfar_new_skb(dev, bdp);
+-		priv->rx_skbuff[priv->skb_currx] = skb;
++		/* Setup the new bdp */
++		gfar_new_rxbdp(dev, bdp, newskb);
+ 
+ 		/* Update to the next pointer */
+ 		if (bdp->status & RXBD_WRAP)
+@@ -1565,9 +1615,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+ 
+ 		/* update to point at the next skb */
+ 		priv->skb_currx =
+-		    (priv->skb_currx +
+-		     1) & RX_RING_MOD_MASK(priv->rx_ring_size);
+-
++		    (priv->skb_currx + 1) &
++		    RX_RING_MOD_MASK(priv->rx_ring_size);
+ 	}
+ 
+ 	/* Update the current rxbd pointer to be the next one */
+@@ -1582,6 +1631,13 @@ static int gfar_poll(struct napi_struct *napi, int budget)
+ 	struct gfar_private *priv = container_of(napi, struct gfar_private, napi);
+ 	struct net_device *dev = priv->dev;
+ 	int howmany;
++	unsigned long flags;
++
++	/* If we fail to get the lock, don't bother with the TX BDs */
++	if (spin_trylock_irqsave(&priv->txlock, flags)) {
++		gfar_clean_tx_ring(dev);
++		spin_unlock_irqrestore(&priv->txlock, flags);
++	}
+ 
+ 	howmany = gfar_clean_rx_ring(dev, budget);
+ 
+@@ -1595,11 +1651,11 @@ static int gfar_poll(struct napi_struct *napi, int budget)
+ 
+ 		/* If we are coalescing interrupts, update the timer */
+ 		/* Otherwise, clear it */
+-		if (priv->rxcoalescing)
++		if (likely(priv->rxcoalescing)) {
++			gfar_write(&priv->regs->rxic, 0);
+ 			gfar_write(&priv->regs->rxic,
+ 				   mk_ic_value(priv->rxcount, priv->rxtime));
+-		else
+-			gfar_write(&priv->regs->rxic, 0);
++		}
+ 	}
+ 
+ 	return howmany;
+@@ -1975,12 +2031,16 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:fsl-gianfar");
++
+ /* Structure for a device driver */
+ static struct platform_driver gfar_driver = {
+ 	.probe = gfar_probe,
+ 	.remove = gfar_remove,
+ 	.driver	= {
+ 		.name = "fsl-gianfar",
++		.owner = THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
+index 46cd773..0d08836 100644
+--- a/drivers/net/gianfar.h
++++ b/drivers/net/gianfar.h
+@@ -102,7 +102,7 @@ extern const char gfar_driver_version[];
+ #define DEFAULT_FIFO_TX_STARVE 0x40
+ #define DEFAULT_FIFO_TX_STARVE_OFF 0x80
+ #define DEFAULT_BD_STASH 1
+-#define DEFAULT_STASH_LENGTH	64
++#define DEFAULT_STASH_LENGTH	96
+ #define DEFAULT_STASH_INDEX	0
+ 
+ /* The number of Exact Match registers */
+@@ -124,11 +124,18 @@ extern const char gfar_driver_version[];
+ 
+ #define DEFAULT_TX_COALESCE 1
+ #define DEFAULT_TXCOUNT	16
+-#define DEFAULT_TXTIME	4
++#define DEFAULT_TXTIME	21
+ 
++#define DEFAULT_RXTIME	21
++
++/* Non NAPI Case */
++#ifndef CONFIG_GFAR_NAPI
+ #define DEFAULT_RX_COALESCE 1
+ #define DEFAULT_RXCOUNT	16
+-#define DEFAULT_RXTIME	4
++#else
++#define DEFAULT_RX_COALESCE 0
++#define DEFAULT_RXCOUNT	0
++#endif /* CONFIG_GFAR_NAPI */
+ 
+ #define TBIPA_VALUE		0x1f
+ #define MIIMCFG_INIT_VALUE	0x00000007
+@@ -242,6 +249,7 @@ extern const char gfar_driver_version[];
+ #define IEVENT_PERR		0x00000001
+ #define IEVENT_RX_MASK          (IEVENT_RXB0 | IEVENT_RXF0)
+ #define IEVENT_TX_MASK          (IEVENT_TXB | IEVENT_TXF)
++#define IEVENT_RTX_MASK         (IEVENT_RX_MASK | IEVENT_TX_MASK)
+ #define IEVENT_ERR_MASK         \
+ (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
+  IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
+@@ -269,11 +277,12 @@ extern const char gfar_driver_version[];
+ #define IMASK_FIQ		0x00000004
+ #define IMASK_DPE		0x00000002
+ #define IMASK_PERR		0x00000001
+-#define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY)
+ #define IMASK_DEFAULT  (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \
+ 		IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
+ 		IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
+ 		| IMASK_PERR)
++#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \
++			   & IMASK_DEFAULT)
+ 
+ /* Fifo management */
+ #define FIFO_TX_THR_MASK	0x01ff
+@@ -340,6 +349,9 @@ extern const char gfar_driver_version[];
+ #define RXBD_OVERRUN		0x0002
+ #define RXBD_TRUNCATED		0x0001
+ #define RXBD_STATS		0x01ff
++#define RXBD_ERR		(RXBD_LARGE | RXBD_SHORT | RXBD_NONOCTET 	\
++				| RXBD_CRCERR | RXBD_OVERRUN			\
++				| RXBD_TRUNCATED)
+ 
+ /* Rx FCB status field bits */
+ #define RXFCB_VLN		0x8000
+diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
+index 2432762..b889892 100644
+--- a/drivers/net/gianfar_mii.c
++++ b/drivers/net/gianfar_mii.c
+@@ -173,7 +173,7 @@ int gfar_mdio_probe(struct device *dev)
+ 	new_bus->read = &gfar_mdio_read,
+ 	new_bus->write = &gfar_mdio_write,
+ 	new_bus->reset = &gfar_mdio_reset,
+-	new_bus->id = pdev->id;
++	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+ 
+ 	pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
+ 
+diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
+index 0a9b751..1da55dd 100644
+--- a/drivers/net/hamradio/6pack.c
++++ b/drivers/net/hamradio/6pack.c
+@@ -33,7 +33,7 @@
+ #include <linux/init.h>
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+ 
+ #define SIXPACK_VERSION    "Revision: 0.3.0"
+diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
+index 5ddf8b0..5f4b4c6 100644
+--- a/drivers/net/hamradio/bpqether.c
++++ b/drivers/net/hamradio/bpqether.c
+@@ -172,7 +172,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
+ 	struct ethhdr *eth;
+ 	struct bpqdev *bpq;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto drop;
+ 
+ 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+@@ -553,7 +553,7 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
+ {
+ 	struct net_device *dev = (struct net_device *)ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (!dev_is_ethdev(dev))
+diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
+index e04bf99..0b94833 100644
+--- a/drivers/net/hamradio/dmascc.c
++++ b/drivers/net/hamradio/dmascc.c
+@@ -1083,15 +1083,12 @@ static void start_timer(struct scc_priv *priv, int t, int r15)
+ 	if (t == 0) {
+ 		tm_isr(priv);
+ 	} else if (t > 0) {
+-		save_flags(flags);
+-		cli();
+ 		outb(t & 0xFF, priv->tmr_cnt);
+ 		outb((t >> 8) & 0xFF, priv->tmr_cnt);
+ 		if (priv->type != TYPE_TWIN) {
+ 			write_scc(priv, R15, r15 | CTSIE);
+ 			priv->rr0 |= CTS;
+ 		}
+-		restore_flags(flags);
+ 	}
+ }
+ 
+diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
+index 378a239..5d2108c 100644
+--- a/drivers/net/ibm_newemac/core.c
++++ b/drivers/net/ibm_newemac/core.c
+@@ -43,6 +43,8 @@
+ #include <asm/io.h>
+ #include <asm/dma.h>
+ #include <asm/uaccess.h>
++#include <asm/dcr.h>
++#include <asm/dcr-regs.h>
+ 
+ #include "core.h"
+ 
+@@ -127,10 +129,35 @@ static struct device_node *emac_boot_list[EMAC_BOOT_LIST_SIZE];
+ static inline void emac_report_timeout_error(struct emac_instance *dev,
+ 					     const char *error)
+ {
+-	if (net_ratelimit())
++	if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX |
++				  EMAC_FTR_440EP_PHY_CLK_FIX))
++		DBG(dev, "%s" NL, error);
++	else if (net_ratelimit())
+ 		printk(KERN_ERR "%s: %s\n", dev->ndev->name, error);
+ }
+ 
++/* EMAC PHY clock workaround:
++ * 440EP/440GR has more sane SDR0_MFR register implementation than 440GX,
++ * which allows controlling each EMAC clock
++ */
++static inline void emac_rx_clk_tx(struct emac_instance *dev)
++{
++#ifdef CONFIG_PPC_DCR_NATIVE
++	if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
++		dcri_clrset(SDR0, SDR0_MFR,
++			    0, SDR0_MFR_ECS >> dev->cell_index);
++#endif
++}
++
++static inline void emac_rx_clk_default(struct emac_instance *dev)
++{
++#ifdef CONFIG_PPC_DCR_NATIVE
++	if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
++		dcri_clrset(SDR0, SDR0_MFR,
++			    SDR0_MFR_ECS >> dev->cell_index, 0);
++#endif
++}
++
+ /* PHY polling intervals */
+ #define PHY_POLL_LINK_ON	HZ
+ #define PHY_POLL_LINK_OFF	(HZ / 5)
+@@ -524,7 +551,10 @@ static int emac_configure(struct emac_instance *dev)
+ 		rx_size = dev->rx_fifo_size_gige;
+ 
+ 		if (dev->ndev->mtu > ETH_DATA_LEN) {
+-			mr1 |= EMAC_MR1_JPSM;
++			if (emac_has_feature(dev, EMAC_FTR_EMAC4))
++				mr1 |= EMAC4_MR1_JPSM;
++			else
++				mr1 |= EMAC_MR1_JPSM;
+ 			dev->stop_timeout = STOP_TIMEOUT_1000_JUMBO;
+ 		} else
+ 			dev->stop_timeout = STOP_TIMEOUT_1000;
+@@ -708,7 +738,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
+ 		rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
+ 
+ 	/* Wait for management interface to become idle */
+-	n = 10;
++	n = 20;
+ 	while (!emac_phy_done(dev, in_be32(&p->stacr))) {
+ 		udelay(1);
+ 		if (!--n) {
+@@ -733,7 +763,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
+ 	out_be32(&p->stacr, r);
+ 
+ 	/* Wait for read to complete */
+-	n = 100;
++	n = 200;
+ 	while (!emac_phy_done(dev, (r = in_be32(&p->stacr)))) {
+ 		udelay(1);
+ 		if (!--n) {
+@@ -780,7 +810,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
+ 		rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
+ 
+ 	/* Wait for management interface to be idle */
+-	n = 10;
++	n = 20;
+ 	while (!emac_phy_done(dev, in_be32(&p->stacr))) {
+ 		udelay(1);
+ 		if (!--n) {
+@@ -806,7 +836,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
+ 	out_be32(&p->stacr, r);
+ 
+ 	/* Wait for write to complete */
+-	n = 100;
++	n = 200;
+ 	while (!emac_phy_done(dev, in_be32(&p->stacr))) {
+ 		udelay(1);
+ 		if (!--n) {
+@@ -1094,9 +1124,11 @@ static int emac_open(struct net_device *ndev)
+ 		int link_poll_interval;
+ 		if (dev->phy.def->ops->poll_link(&dev->phy)) {
+ 			dev->phy.def->ops->read_link(&dev->phy);
++			emac_rx_clk_default(dev);
+ 			netif_carrier_on(dev->ndev);
+ 			link_poll_interval = PHY_POLL_LINK_ON;
+ 		} else {
++			emac_rx_clk_tx(dev);
+ 			netif_carrier_off(dev->ndev);
+ 			link_poll_interval = PHY_POLL_LINK_OFF;
+ 		}
+@@ -1174,6 +1206,7 @@ static void emac_link_timer(struct work_struct *work)
+ 
+ 	if (dev->phy.def->ops->poll_link(&dev->phy)) {
+ 		if (!netif_carrier_ok(dev->ndev)) {
++			emac_rx_clk_default(dev);
+ 			/* Get new link parameters */
+ 			dev->phy.def->ops->read_link(&dev->phy);
+ 
+@@ -1186,6 +1219,7 @@ static void emac_link_timer(struct work_struct *work)
+ 		link_poll_interval = PHY_POLL_LINK_ON;
+ 	} else {
+ 		if (netif_carrier_ok(dev->ndev)) {
++			emac_rx_clk_tx(dev);
+ 			netif_carrier_off(dev->ndev);
+ 			netif_tx_disable(dev->ndev);
+ 			emac_reinitialize(dev);
+@@ -2237,7 +2271,7 @@ static int __devinit emac_of_bus_notify(struct notifier_block *nb,
+ 	return 0;
+ }
+ 
+-static struct notifier_block emac_of_bus_notifier = {
++static struct notifier_block emac_of_bus_notifier __devinitdata = {
+ 	.notifier_call = emac_of_bus_notify
+ };
+ 
+@@ -2330,6 +2364,19 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
+ 	dev->phy.mdio_read = emac_mdio_read;
+ 	dev->phy.mdio_write = emac_mdio_write;
+ 
++	/* Enable internal clock source */
++#ifdef CONFIG_PPC_DCR_NATIVE
++	if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
++		dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
++#endif
++	/* PHY clock workaround */
++	emac_rx_clk_tx(dev);
++
++	/* Enable internal clock source on 440GX*/
++#ifdef CONFIG_PPC_DCR_NATIVE
++	if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
++		dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
++#endif
+ 	/* Configure EMAC with defaults so we can at least use MDIO
+ 	 * This is needed mostly for 440GX
+ 	 */
+@@ -2362,6 +2409,12 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
+ 			if (!emac_mii_phy_probe(&dev->phy, i))
+ 				break;
+ 		}
++
++	/* Enable external clock source */
++#ifdef CONFIG_PPC_DCR_NATIVE
++	if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
++		dcri_clrset(SDR0, SDR0_MFR, SDR0_MFR_ECS, 0);
++#endif
+ 	mutex_unlock(&emac_phy_map_lock);
+ 	if (i == 0x20) {
+ 		printk(KERN_WARNING "%s: can't find PHY!\n", np->full_name);
+@@ -2487,8 +2540,15 @@ static int __devinit emac_init_config(struct emac_instance *dev)
+ 	}
+ 
+ 	/* Check EMAC version */
+-	if (of_device_is_compatible(np, "ibm,emac4"))
++	if (of_device_is_compatible(np, "ibm,emac4")) {
+ 		dev->features |= EMAC_FTR_EMAC4;
++		if (of_device_is_compatible(np, "ibm,emac-440gx"))
++			dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX;
++	} else {
++		if (of_device_is_compatible(np, "ibm,emac-440ep") ||
++		    of_device_is_compatible(np, "ibm,emac-440gr"))
++			dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
++	}
+ 
+ 	/* Fixup some feature bits based on the device tree */
+ 	if (of_get_property(np, "has-inverted-stacr-oc", NULL))
+@@ -2559,8 +2619,11 @@ static int __devinit emac_probe(struct of_device *ofdev,
+ 	struct device_node **blist = NULL;
+ 	int err, i;
+ 
+-	/* Skip unused/unwired EMACS */
+-	if (of_get_property(np, "unused", NULL))
++	/* Skip unused/unwired EMACS.  We leave the check for an unused
++	 * property here for now, but new flat device trees should set a
++	 * status property to "disabled" instead.
++	 */
++	if (of_get_property(np, "unused", NULL) || !of_device_is_available(np))
+ 		return -ENODEV;
+ 
+ 	/* Find ourselves in the bootlist if we are there */
+diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h
+index 4e74d82..1683db9 100644
+--- a/drivers/net/ibm_newemac/core.h
++++ b/drivers/net/ibm_newemac/core.h
+@@ -301,6 +301,14 @@ struct emac_instance {
+  * Set if we have new type STACR with STAOPC
+  */
+ #define EMAC_FTR_HAS_NEW_STACR		0x00000040
++/*
++ * Set if we need phy clock workaround for 440gx
++ */
++#define EMAC_FTR_440GX_PHY_CLK_FIX	0x00000080
++/*
++ * Set if we need phy clock workaround for 440ep or 440gr
++ */
++#define EMAC_FTR_440EP_PHY_CLK_FIX	0x00000100
+ 
+ 
+ /* Right now, we don't quite handle the always/possible masks on the
+@@ -312,8 +320,8 @@ enum {
+ 
+ 	EMAC_FTRS_POSSIBLE	=
+ #ifdef CONFIG_IBM_NEW_EMAC_EMAC4
+-	    EMAC_FTR_EMAC4	| EMAC_FTR_HAS_NEW_STACR	|
+-	    EMAC_FTR_STACR_OC_INVERT	|
++	    EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR |
++	    EMAC_FTR_STACR_OC_INVERT | EMAC_FTR_440GX_PHY_CLK_FIX |
+ #endif
+ #ifdef CONFIG_IBM_NEW_EMAC_TAH
+ 	    EMAC_FTR_HAS_TAH	|
+@@ -324,7 +332,7 @@ enum {
+ #ifdef CONFIG_IBM_NEW_EMAC_RGMII
+ 	    EMAC_FTR_HAS_RGMII	|
+ #endif
+-	    0,
++	EMAC_FTR_440EP_PHY_CLK_FIX,
+ };
+ 
+ static inline int emac_has_feature(struct emac_instance *dev,
+diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
+index 6869f08..10c267b 100644
+--- a/drivers/net/ibm_newemac/mal.c
++++ b/drivers/net/ibm_newemac/mal.c
+@@ -61,8 +61,8 @@ int __devinit mal_register_commac(struct mal_instance	*mal,
+ 	return 0;
+ }
+ 
+-void __devexit mal_unregister_commac(struct mal_instance	*mal,
+-				     struct mal_commac		*commac)
++void mal_unregister_commac(struct mal_instance	*mal,
++		struct mal_commac *commac)
+ {
+ 	unsigned long flags;
+ 
+@@ -136,6 +136,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
+ {
+ 	unsigned long flags;
+ 
++	/*
++	 * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple
++	 * of 8, but enabling in MAL_RXCASR needs the divided by 8 value
++	 * for the bitmask
++	 */
++	if (!(channel % 8))
++		channel >>= 3;
++
+ 	spin_lock_irqsave(&mal->lock, flags);
+ 
+ 	MAL_DBG(mal, "enable_rx(%d)" NL, channel);
+@@ -148,6 +156,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
+ 
+ void mal_disable_rx_channel(struct mal_instance *mal, int channel)
+ {
++	/*
++	 * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple
++	 * of 8, but enabling in MAL_RXCASR needs the divided by 8 value
++	 * for the bitmask
++	 */
++	if (!(channel % 8))
++		channel >>= 3;
++
+ 	set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel));
+ 
+ 	MAL_DBG(mal, "disable_rx(%d)" NL, channel);
+diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c
+index 5757788..e32da3d 100644
+--- a/drivers/net/ibm_newemac/rgmii.c
++++ b/drivers/net/ibm_newemac/rgmii.c
+@@ -179,7 +179,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input)
+ 	mutex_unlock(&dev->lock);
+ }
+ 
+-void __devexit rgmii_detach(struct of_device *ofdev, int input)
++void rgmii_detach(struct of_device *ofdev, int input)
+ {
+ 	struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 	struct rgmii_regs __iomem *p = dev->base;
+diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c
+index b023d10..30173a9 100644
+--- a/drivers/net/ibm_newemac/tah.c
++++ b/drivers/net/ibm_newemac/tah.c
+@@ -35,7 +35,7 @@ int __devinit tah_attach(struct of_device *ofdev, int channel)
+ 	return 0;
+ }
+ 
+-void __devexit tah_detach(struct of_device *ofdev, int channel)
++void tah_detach(struct of_device *ofdev, int channel)
+ {
+ 	struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 
+diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c
+index 2ea472a..17b1541 100644
+--- a/drivers/net/ibm_newemac/zmii.c
++++ b/drivers/net/ibm_newemac/zmii.c
+@@ -189,7 +189,7 @@ void zmii_set_speed(struct of_device *ofdev, int input, int speed)
+ 	mutex_unlock(&dev->lock);
+ }
+ 
+-void __devexit zmii_detach(struct of_device *ofdev, int input)
++void zmii_detach(struct of_device *ofdev, int input)
+ {
+ 	struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+ 
+diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
+index 57772be..ce4fc2e 100644
+--- a/drivers/net/ibmveth.c
++++ b/drivers/net/ibmveth.c
+@@ -49,7 +49,6 @@
+ #include <linux/in.h>
+ #include <linux/ip.h>
+ #include <net/net_namespace.h>
+-#include <asm/semaphore.h>
+ #include <asm/hvcall.h>
+ #include <asm/atomic.h>
+ #include <asm/vio.h>
+@@ -1259,26 +1258,7 @@ static void ibmveth_proc_unregister_driver(void)
+ 	remove_proc_entry(IBMVETH_PROC_DIR, init_net.proc_net);
+ }
+ 
+-static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos)
+-{
+-	if (*pos == 0) {
+-		return (void *)1;
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-static void *ibmveth_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+-{
+-	++*pos;
+-	return NULL;
+-}
+-
+-static void ibmveth_seq_stop(struct seq_file *seq, void *v)
+-{
+-}
+-
+-static int ibmveth_seq_show(struct seq_file *seq, void *v)
++static int ibmveth_show(struct seq_file *seq, void *v)
+ {
+ 	struct ibmveth_adapter *adapter = seq->private;
+ 	char *current_mac = ((char*) &adapter->netdev->dev_addr);
+@@ -1302,27 +1282,10 @@ static int ibmveth_seq_show(struct seq_file *seq, void *v)
+ 
+ 	return 0;
+ }
+-static struct seq_operations ibmveth_seq_ops = {
+-	.start = ibmveth_seq_start,
+-	.next  = ibmveth_seq_next,
+-	.stop  = ibmveth_seq_stop,
+-	.show  = ibmveth_seq_show,
+-};
+ 
+ static int ibmveth_proc_open(struct inode *inode, struct file *file)
+ {
+-	struct seq_file *seq;
+-	struct proc_dir_entry *proc;
+-	int rc;
+-
+-	rc = seq_open(file, &ibmveth_seq_ops);
+-	if (!rc) {
+-		/* recover the pointer buried in proc_dir_entry data */
+-		seq = file->private_data;
+-		proc = PDE(inode);
+-		seq->private = proc->data;
+-	}
+-	return rc;
++	return single_open(file, ibmveth_show, PDE(inode)->data);
+ }
+ 
+ static const struct file_operations ibmveth_proc_fops = {
+@@ -1330,7 +1293,7 @@ static const struct file_operations ibmveth_proc_fops = {
+ 	.open    = ibmveth_proc_open,
+ 	.read    = seq_read,
+ 	.llseek  = seq_lseek,
+-	.release = seq_release,
++	.release = single_release,
+ };
+ 
+ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
+diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
+index aaee02e..ae398f0 100644
+--- a/drivers/net/igb/igb_main.c
++++ b/drivers/net/igb/igb_main.c
+@@ -871,6 +871,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
+ 		goto err_pci_reg;
+ 
+ 	pci_set_master(pdev);
++	pci_save_state(pdev);
+ 
+ 	err = -ENOMEM;
+ 	netdev = alloc_etherdev(sizeof(struct igb_adapter));
+@@ -4079,6 +4080,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
+ 		return PCI_ERS_RESULT_DISCONNECT;
+ 	}
+ 	pci_set_master(pdev);
++	pci_restore_state(pdev);
+ 
+ 	pci_enable_wake(pdev, PCI_D3hot, 0);
+ 	pci_enable_wake(pdev, PCI_D3cold, 0);
+diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
+index 9f58452..083b0dd 100644
+--- a/drivers/net/irda/ali-ircc.c
++++ b/drivers/net/irda/ali-ircc.c
+@@ -60,6 +60,7 @@ static struct platform_driver ali_ircc_driver = {
+ 	.resume		= ali_ircc_resume,
+ 	.driver		= {
+ 		.name	= ALI_IRCC_DRIVER_NAME,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -2256,6 +2257,7 @@ static void FIR2SIR(int iobase)
+ MODULE_AUTHOR("Benjamin Kong <benjamin_kong at ali.com.tw>");
+ MODULE_DESCRIPTION("ALi FIR Controller Driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:" ALI_IRCC_DRIVER_NAME);
+ 
+ 
+ module_param_array(io, int, NULL, 0);
+diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
+index 8c09344..d5c2d27 100644
+--- a/drivers/net/irda/pxaficp_ir.c
++++ b/drivers/net/irda/pxaficp_ir.c
+@@ -36,6 +36,7 @@
+ #include <asm/hardware.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ 
+ #ifdef CONFIG_MACH_MAINSTONE
+ #include <asm/arch/mainstone.h>
+@@ -831,6 +832,11 @@ static int pxa_irda_probe(struct platform_device *pdev)
+ 	if (err)
+ 		goto err_mem_5;
+ 
++	if (si->pdata->startup)
++		err = si->pdata->startup(si->dev);
++	if (err)
++		goto err_startup;
++
+ 	dev->hard_start_xmit	= pxa_irda_hard_xmit;
+ 	dev->open		= pxa_irda_start;
+ 	dev->stop		= pxa_irda_stop;
+@@ -856,6 +862,9 @@ static int pxa_irda_probe(struct platform_device *pdev)
+ 		dev_set_drvdata(&pdev->dev, dev);
+ 
+ 	if (err) {
++		if (si->pdata->shutdown)
++			si->pdata->shutdown(si->dev);
++err_startup:
+ 		kfree(si->tx_buff.head);
+ err_mem_5:
+ 		kfree(si->rx_buff.head);
+@@ -881,6 +890,8 @@ static int pxa_irda_remove(struct platform_device *_dev)
+ 	if (dev) {
+ 		struct pxa_irda *si = netdev_priv(dev);
+ 		unregister_netdev(dev);
++		if (si->pdata->shutdown)
++			si->pdata->shutdown(si->dev);
+ 		kfree(si->tx_buff.head);
+ 		kfree(si->rx_buff.head);
+ 		clk_put(si->fir_clk);
+@@ -897,6 +908,7 @@ static int pxa_irda_remove(struct platform_device *_dev)
+ static struct platform_driver pxa_ir_driver = {
+ 	.driver         = {
+ 		.name   = "pxa2xx-ir",
++		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= pxa_irda_probe,
+ 	.remove		= pxa_irda_remove,
+@@ -918,3 +930,4 @@ module_init(pxa_irda_init);
+ module_exit(pxa_irda_exit);
+ 
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pxa2xx-ir");
+diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
+index 056639f..1bc8518 100644
+--- a/drivers/net/irda/sa1100_ir.c
++++ b/drivers/net/irda/sa1100_ir.c
+@@ -1008,6 +1008,7 @@ static struct platform_driver sa1100ir_driver = {
+ 	.resume		= sa1100_irda_resume,
+ 	.driver		= {
+ 		.name	= "sa11x0-ir",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -1041,3 +1042,4 @@ MODULE_LICENSE("GPL");
+ MODULE_PARM_DESC(power_level, "IrDA power level, 1 (low) to 3 (high)");
+ MODULE_PARM_DESC(tx_lpm, "Enable transmitter low power (1.6us) mode");
+ MODULE_PARM_DESC(max_rate, "Maximum baud rate (4000000, 115200, 57600, 38400, 19200, 9600)");
++MODULE_ALIAS("platform:sa11x0-ir");
+diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
+index 58d3bb6..b8d0639 100644
+--- a/drivers/net/iseries_veth.c
++++ b/drivers/net/iseries_veth.c
+@@ -308,7 +308,8 @@ static void veth_complete_allocation(void *parm, int number)
+ 
+ static int veth_allocate_events(HvLpIndex rlp, int number)
+ {
+-	struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 };
++	struct veth_allocation vc =
++		{ COMPLETION_INITIALIZER_ONSTACK(vc.c), 0 };
+ 
+ 	mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan,
+ 			    sizeof(struct veth_lpevent), number,
+diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
+index 3d2e721..16f9c75 100644
+--- a/drivers/net/ixgb/ixgb.h
++++ b/drivers/net/ixgb/ixgb.h
+@@ -117,8 +117,8 @@ struct ixgb_buffer {
+ 	struct sk_buff *skb;
+ 	dma_addr_t dma;
+ 	unsigned long time_stamp;
+-	uint16_t length;
+-	uint16_t next_to_watch;
++	u16 length;
++	u16 next_to_watch;
+ };
+ 
+ struct ixgb_desc_ring {
+@@ -152,13 +152,12 @@ struct ixgb_desc_ring {
+ struct ixgb_adapter {
+ 	struct timer_list watchdog_timer;
+ 	struct vlan_group *vlgrp;
+-	uint32_t bd_number;
+-	uint32_t rx_buffer_len;
+-	uint32_t part_num;
+-	uint16_t link_speed;
+-	uint16_t link_duplex;
++	u32 bd_number;
++	u32 rx_buffer_len;
++	u32 part_num;
++	u16 link_speed;
++	u16 link_duplex;
+ 	spinlock_t tx_lock;
+-	atomic_t irq_sem;
+ 	struct work_struct tx_timeout_task;
+ 
+ 	struct timer_list blink_timer;
+@@ -168,20 +167,20 @@ struct ixgb_adapter {
+ 	struct ixgb_desc_ring tx_ring ____cacheline_aligned_in_smp;
+ 	unsigned int restart_queue;
+ 	unsigned long timeo_start;
+-	uint32_t tx_cmd_type;
+-	uint64_t hw_csum_tx_good;
+-	uint64_t hw_csum_tx_error;
+-	uint32_t tx_int_delay;
+-	uint32_t tx_timeout_count;
+-	boolean_t tx_int_delay_enable;
+-	boolean_t detect_tx_hung;
++	u32 tx_cmd_type;
++	u64 hw_csum_tx_good;
++	u64 hw_csum_tx_error;
++	u32 tx_int_delay;
++	u32 tx_timeout_count;
++	bool tx_int_delay_enable;
++	bool detect_tx_hung;
+ 
+ 	/* RX */
+ 	struct ixgb_desc_ring rx_ring;
+-	uint64_t hw_csum_rx_error;
+-	uint64_t hw_csum_rx_good;
+-	uint32_t rx_int_delay;
+-	boolean_t rx_csum;
++	u64 hw_csum_rx_error;
++	u64 hw_csum_rx_good;
++	u32 rx_int_delay;
++	bool rx_csum;
+ 
+ 	/* OS defined structs */
+ 	struct napi_struct napi;
+@@ -193,8 +192,17 @@ struct ixgb_adapter {
+ 	struct ixgb_hw hw;
+ 	u16 msg_enable;
+ 	struct ixgb_hw_stats stats;
+-	uint32_t alloc_rx_buff_failed;
+-	boolean_t have_msi;
++	u32 alloc_rx_buff_failed;
++	bool have_msi;
++	unsigned long flags;
++};
++
++enum ixgb_state_t {
++	/* TBD
++	__IXGB_TESTING,
++	__IXGB_RESETTING,
++	*/
++	__IXGB_DOWN
+ };
+ 
+ /* Exported from other modules */
+@@ -203,4 +211,14 @@ extern void ixgb_set_ethtool_ops(struct net_device *netdev);
+ extern char ixgb_driver_name[];
+ extern const char ixgb_driver_version[];
+ 
++extern int ixgb_up(struct ixgb_adapter *adapter);
++extern void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
++extern void ixgb_reset(struct ixgb_adapter *adapter);
++extern int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
++extern int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
++extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
++extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
++extern void ixgb_update_stats(struct ixgb_adapter *adapter);
++
++
+ #endif /* _IXGB_H_ */
+diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
+index e8eb0fd..2f7ed52 100644
+--- a/drivers/net/ixgb/ixgb_ee.c
++++ b/drivers/net/ixgb/ixgb_ee.c
+@@ -29,14 +29,14 @@
+ #include "ixgb_hw.h"
+ #include "ixgb_ee.h"
+ /* Local prototypes */
+-static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw);
++static u16 ixgb_shift_in_bits(struct ixgb_hw *hw);
+ 
+ static void ixgb_shift_out_bits(struct ixgb_hw *hw,
+-				uint16_t data,
+-				uint16_t count);
++				u16 data,
++				u16 count);
+ static void ixgb_standby_eeprom(struct ixgb_hw *hw);
+ 
+-static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw);
++static bool ixgb_wait_eeprom_command(struct ixgb_hw *hw);
+ 
+ static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
+ 
+@@ -48,7 +48,7 @@ static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
+  *****************************************************************************/
+ static void
+ ixgb_raise_clock(struct ixgb_hw *hw,
+-		  uint32_t *eecd_reg)
++		  u32 *eecd_reg)
+ {
+ 	/* Raise the clock input to the EEPROM (by setting the SK bit), and then
+ 	 *  wait 50 microseconds.
+@@ -67,7 +67,7 @@ ixgb_raise_clock(struct ixgb_hw *hw,
+  *****************************************************************************/
+ static void
+ ixgb_lower_clock(struct ixgb_hw *hw,
+-		  uint32_t *eecd_reg)
++		  u32 *eecd_reg)
+ {
+ 	/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
+ 	 * wait 50 microseconds.
+@@ -87,11 +87,11 @@ ixgb_lower_clock(struct ixgb_hw *hw,
+  *****************************************************************************/
+ static void
+ ixgb_shift_out_bits(struct ixgb_hw *hw,
+-					 uint16_t data,
+-					 uint16_t count)
++					 u16 data,
++					 u16 count)
+ {
+-	uint32_t eecd_reg;
+-	uint32_t mask;
++	u32 eecd_reg;
++	u32 mask;
+ 
+ 	/* We need to shift "count" bits out to the EEPROM. So, value in the
+ 	 * "data" parameter will be shifted out to the EEPROM one bit at a time.
+@@ -133,12 +133,12 @@ ixgb_shift_out_bits(struct ixgb_hw *hw,
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-static uint16_t
++static u16
+ ixgb_shift_in_bits(struct ixgb_hw *hw)
+ {
+-	uint32_t eecd_reg;
+-	uint32_t i;
+-	uint16_t data;
++	u32 eecd_reg;
++	u32 i;
++	u16 data;
+ 
+ 	/* In order to read a register from the EEPROM, we need to shift 16 bits
+ 	 * in from the EEPROM. Bits are "shifted in" by raising the clock input to
+@@ -179,7 +179,7 @@ ixgb_shift_in_bits(struct ixgb_hw *hw)
+ static void
+ ixgb_setup_eeprom(struct ixgb_hw *hw)
+ {
+-	uint32_t eecd_reg;
++	u32 eecd_reg;
+ 
+ 	eecd_reg = IXGB_READ_REG(hw, EECD);
+ 
+@@ -201,7 +201,7 @@ ixgb_setup_eeprom(struct ixgb_hw *hw)
+ static void
+ ixgb_standby_eeprom(struct ixgb_hw *hw)
+ {
+-	uint32_t eecd_reg;
++	u32 eecd_reg;
+ 
+ 	eecd_reg = IXGB_READ_REG(hw, EECD);
+ 
+@@ -235,7 +235,7 @@ ixgb_standby_eeprom(struct ixgb_hw *hw)
+ static void
+ ixgb_clock_eeprom(struct ixgb_hw *hw)
+ {
+-	uint32_t eecd_reg;
++	u32 eecd_reg;
+ 
+ 	eecd_reg = IXGB_READ_REG(hw, EECD);
+ 
+@@ -259,7 +259,7 @@ ixgb_clock_eeprom(struct ixgb_hw *hw)
+ static void
+ ixgb_cleanup_eeprom(struct ixgb_hw *hw)
+ {
+-	uint32_t eecd_reg;
++	u32 eecd_reg;
+ 
+ 	eecd_reg = IXGB_READ_REG(hw, EECD);
+ 
+@@ -279,14 +279,14 @@ ixgb_cleanup_eeprom(struct ixgb_hw *hw)
+  * The command is done when the EEPROM's data out pin goes high.
+  *
+  * Returns:
+- *      TRUE: EEPROM data pin is high before timeout.
+- *      FALSE:  Time expired.
++ *      true: EEPROM data pin is high before timeout.
++ *      false:  Time expired.
+  *****************************************************************************/
+-static boolean_t
++static bool
+ ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+ {
+-	uint32_t eecd_reg;
+-	uint32_t i;
++	u32 eecd_reg;
++	u32 i;
+ 
+ 	/* Toggle the CS line.  This in effect tells to EEPROM to actually execute
+ 	 * the command in question.
+@@ -301,12 +301,12 @@ ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+ 		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);
+ }
+ 
+ /******************************************************************************
+@@ -319,22 +319,22 @@ ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+  * valid.
+  *
+  * Returns:
+- *  TRUE: Checksum is valid
+- *  FALSE: Checksum is not valid.
++ *  true: Checksum is valid
++ *  false: Checksum is not valid.
+  *****************************************************************************/
+-boolean_t
++bool
+ ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
+ {
+-	uint16_t checksum = 0;
+-	uint16_t i;
++	u16 checksum = 0;
++	u16 i;
+ 
+ 	for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
+ 		checksum += ixgb_read_eeprom(hw, i);
+ 
+-	if(checksum == (uint16_t) EEPROM_SUM)
+-		return (TRUE);
++	if(checksum == (u16) EEPROM_SUM)
++		return (true);
+ 	else
+-		return (FALSE);
++		return (false);
+ }
+ 
+ /******************************************************************************
+@@ -348,13 +348,13 @@ ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
+ void
+ ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
+ {
+-	uint16_t checksum = 0;
+-	uint16_t i;
++	u16 checksum = 0;
++	u16 i;
+ 
+ 	for(i = 0; i < EEPROM_CHECKSUM_REG; i++)
+ 		checksum += ixgb_read_eeprom(hw, i);
+ 
+-	checksum = (uint16_t) EEPROM_SUM - checksum;
++	checksum = (u16) EEPROM_SUM - checksum;
+ 
+ 	ixgb_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum);
+ 	return;
+@@ -372,7 +372,7 @@ ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
+  *
+  *****************************************************************************/
+ void
+-ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
++ixgb_write_eeprom(struct ixgb_hw *hw, u16 offset, u16 data)
+ {
+ 	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+ 
+@@ -425,11 +425,11 @@ ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
+  * Returns:
+  *  The 16-bit value read from the eeprom
+  *****************************************************************************/
+-uint16_t
++u16
+ ixgb_read_eeprom(struct ixgb_hw *hw,
+-		  uint16_t offset)
++		  u16 offset)
+ {
+-	uint16_t data;
++	u16 data;
+ 
+ 	/*  Prepare the EEPROM for reading  */
+ 	ixgb_setup_eeprom(hw);
+@@ -457,14 +457,14 @@ ixgb_read_eeprom(struct ixgb_hw *hw,
+  * hw - Struct containing variables accessed by shared code
+  *
+  * Returns:
+- *      TRUE: if eeprom read is successful
+- *      FALSE: otherwise.
++ *      true: if eeprom read is successful
++ *      false: otherwise.
+  *****************************************************************************/
+-boolean_t
++bool
+ ixgb_get_eeprom_data(struct ixgb_hw *hw)
+ {
+-	uint16_t i;
+-	uint16_t checksum = 0;
++	u16 i;
++	u16 checksum = 0;
+ 	struct ixgb_ee_map_type *ee_map;
+ 
+ 	DEBUGFUNC("ixgb_get_eeprom_data");
+@@ -473,27 +473,27 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
+ 
+ 	DEBUGOUT("ixgb_ee: Reading eeprom data\n");
+ 	for(i = 0; i < IXGB_EEPROM_SIZE ; i++) {
+-		uint16_t ee_data;
++		u16 ee_data;
+ 		ee_data = ixgb_read_eeprom(hw, i);
+ 		checksum += ee_data;
+ 		hw->eeprom[i] = cpu_to_le16(ee_data);
+ 	}
+ 
+-	if (checksum != (uint16_t) EEPROM_SUM) {
++	if (checksum != (u16) EEPROM_SUM) {
+ 		DEBUGOUT("ixgb_ee: Checksum invalid.\n");
+ 		/* 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)) {
+ 		DEBUGOUT("ixgb_ee: Signature invalid.\n");
+-		return(FALSE);
++		return(false);
+ 	}
+ 
+-	return(TRUE);
++	return(true);
+ }
+ 
+ /******************************************************************************
+@@ -503,17 +503,17 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
+  * hw - Struct containing variables accessed by shared code
+  *
+  * Returns:
+- *      TRUE: eeprom signature was good and the eeprom read was successful
+- *      FALSE: otherwise.
++ *      true: eeprom signature was good and the eeprom read was successful
++ *      false: otherwise.
+  ******************************************************************************/
+-static boolean_t
++static bool
+ ixgb_check_and_get_eeprom_data (struct ixgb_hw* hw)
+ {
+ 	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+ 
+ 	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);
+ 	}
+@@ -529,11 +529,11 @@ ixgb_check_and_get_eeprom_data (struct ixgb_hw* hw)
+  *          Word at indexed offset in eeprom, if valid, 0 otherwise.
+  ******************************************************************************/
+ __le16
+-ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index)
++ixgb_get_eeprom_word(struct ixgb_hw *hw, u16 index)
+ {
+ 
+ 	if ((index < IXGB_EEPROM_SIZE) &&
+-		(ixgb_check_and_get_eeprom_data(hw) == TRUE)) {
++		(ixgb_check_and_get_eeprom_data(hw) == true)) {
+ 	   return(hw->eeprom[index]);
+ 	}
+ 
+@@ -550,14 +550,14 @@ ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index)
+  ******************************************************************************/
+ void
+ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
+-			uint8_t *mac_addr)
++			u8 *mac_addr)
+ {
+ 	int i;
+ 	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+ 
+ 	DEBUGFUNC("ixgb_get_ee_mac_addr");
+ 
+-	if (ixgb_check_and_get_eeprom_data(hw) == TRUE) {
++	if (ixgb_check_and_get_eeprom_data(hw) == true) {
+ 		for (i = 0; i < IXGB_ETH_LENGTH_OF_ADDRESS; i++) {
+ 			mac_addr[i] = ee_map->mac_addr[i];
+ 			DEBUGOUT2("mac(%d) = %.2X\n", i, mac_addr[i]);
+@@ -574,10 +574,10 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
+  * Returns:
+  *          PBA number if EEPROM contents are valid, 0 otherwise
+  ******************************************************************************/
+-uint32_t
++u32
+ ixgb_get_ee_pba_number(struct ixgb_hw *hw)
+ {
+-	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
++	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));
+ 
+@@ -593,12 +593,12 @@ ixgb_get_ee_pba_number(struct ixgb_hw *hw)
+  * Returns:
+  *          Device Id if EEPROM contents are valid, 0 otherwise
+  ******************************************************************************/
+-uint16_t
++u16
+ ixgb_get_ee_device_id(struct ixgb_hw *hw)
+ {
+ 	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+ 
+-	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
++	if (ixgb_check_and_get_eeprom_data(hw) == true)
+ 		return (le16_to_cpu(ee_map->device_id));
+ 
+ 	return (0);
+diff --git a/drivers/net/ixgb/ixgb_ee.h b/drivers/net/ixgb/ixgb_ee.h
+index 7908bf3..4b7bd0d 100644
+--- a/drivers/net/ixgb/ixgb_ee.h
++++ b/drivers/net/ixgb/ixgb_ee.h
+@@ -75,7 +75,7 @@
+ 
+ /* EEPROM structure */
+ struct ixgb_ee_map_type {
+-	uint8_t mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];
++	u8 mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];
+ 	__le16 compatibility;
+ 	__le16 reserved1[4];
+ 	__le32 pba_number;
+@@ -88,19 +88,19 @@ struct ixgb_ee_map_type {
+ 	__le16 oem_reserved[16];
+ 	__le16 swdpins_reg;
+ 	__le16 circuit_ctrl_reg;
+-	uint8_t d3_power;
+-	uint8_t d0_power;
++	u8 d3_power;
++	u8 d0_power;
+ 	__le16 reserved2[28];
+ 	__le16 checksum;
+ };
+ 
+ /* EEPROM Functions */
+-uint16_t ixgb_read_eeprom(struct ixgb_hw *hw, uint16_t reg);
++u16 ixgb_read_eeprom(struct ixgb_hw *hw, u16 reg);
+ 
+-boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
++bool ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
+ 
+ void ixgb_update_eeprom_checksum(struct ixgb_hw *hw);
+ 
+-void ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t reg, uint16_t data);
++void ixgb_write_eeprom(struct ixgb_hw *hw, u16 reg, u16 data);
+ 
+ #endif				/* IXGB_EE_H */
+diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
+index 75f3a68..8464d8a 100644
+--- a/drivers/net/ixgb/ixgb_ethtool.c
++++ b/drivers/net/ixgb/ixgb_ethtool.c
+@@ -32,15 +32,6 @@
+ 
+ #include <asm/uaccess.h>
+ 
+-extern int ixgb_up(struct ixgb_adapter *adapter);
+-extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
+-extern void ixgb_reset(struct ixgb_adapter *adapter);
+-extern int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+-extern int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+-extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+-extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+-extern void ixgb_update_stats(struct ixgb_adapter *adapter);
+-
+ #define IXGB_ALL_RAR_ENTRIES 16
+ 
+ struct ixgb_stats {
+@@ -136,7 +127,7 @@ ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+ 		return -EINVAL;
+ 	
+ 	if(netif_running(adapter->netdev)) {
+-		ixgb_down(adapter, TRUE);
++		ixgb_down(adapter, true);
+ 		ixgb_reset(adapter);
+ 		ixgb_up(adapter);
+ 		ixgb_set_speed_duplex(netdev);
+@@ -185,7 +176,7 @@ ixgb_set_pauseparam(struct net_device *netdev,
+ 		hw->fc.type = ixgb_fc_none;
+ 
+ 	if(netif_running(adapter->netdev)) {
+-		ixgb_down(adapter, TRUE);
++		ixgb_down(adapter, true);
+ 		ixgb_up(adapter);
+ 		ixgb_set_speed_duplex(netdev);
+ 	} else
+@@ -194,7 +185,7 @@ ixgb_set_pauseparam(struct net_device *netdev,
+ 	return 0;
+ }
+ 
+-static uint32_t
++static u32
+ ixgb_get_rx_csum(struct net_device *netdev)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+@@ -203,14 +194,14 @@ ixgb_get_rx_csum(struct net_device *netdev)
+ }
+ 
+ static int
+-ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
++ixgb_set_rx_csum(struct net_device *netdev, u32 data)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 
+ 	adapter->rx_csum = data;
+ 
+ 	if(netif_running(netdev)) {
+-		ixgb_down(adapter,TRUE);
++		ixgb_down(adapter, true);
+ 		ixgb_up(adapter);
+ 		ixgb_set_speed_duplex(netdev);
+ 	} else
+@@ -218,14 +209,14 @@ ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
+ 	return 0;
+ }
+ 	
+-static uint32_t
++static u32
+ ixgb_get_tx_csum(struct net_device *netdev)
+ {
+ 	return (netdev->features & NETIF_F_HW_CSUM) != 0;
+ }
+ 
+ static int
+-ixgb_set_tx_csum(struct net_device *netdev, uint32_t data)
++ixgb_set_tx_csum(struct net_device *netdev, u32 data)
+ {
+ 	if (data)
+ 		netdev->features |= NETIF_F_HW_CSUM;
+@@ -236,7 +227,7 @@ ixgb_set_tx_csum(struct net_device *netdev, uint32_t data)
+ }
+ 
+ static int
+-ixgb_set_tso(struct net_device *netdev, uint32_t data)
++ixgb_set_tso(struct net_device *netdev, u32 data)
+ {
+ 	if(data)
+ 		netdev->features |= NETIF_F_TSO;
+@@ -245,7 +236,7 @@ ixgb_set_tso(struct net_device *netdev, uint32_t data)
+ 	return 0;
+ } 
+ 
+-static uint32_t
++static u32
+ ixgb_get_msglevel(struct net_device *netdev)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+@@ -253,7 +244,7 @@ ixgb_get_msglevel(struct net_device *netdev)
+ }
+ 
+ static void
+-ixgb_set_msglevel(struct net_device *netdev, uint32_t data)
++ixgb_set_msglevel(struct net_device *netdev, u32 data)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 	adapter->msg_enable = data;
+@@ -263,7 +254,7 @@ ixgb_set_msglevel(struct net_device *netdev, uint32_t data)
+ static int 
+ ixgb_get_regs_len(struct net_device *netdev)
+ {
+-#define IXGB_REG_DUMP_LEN  136*sizeof(uint32_t)
++#define IXGB_REG_DUMP_LEN  136*sizeof(u32)
+ 	return IXGB_REG_DUMP_LEN;
+ }
+ 
+@@ -273,9 +264,9 @@ ixgb_get_regs(struct net_device *netdev,
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 	struct ixgb_hw *hw = &adapter->hw;
+-	uint32_t *reg = p;
+-	uint32_t *reg_start = reg;
+-	uint8_t i;
++	u32 *reg = p;
++	u32 *reg_start = reg;
++	u8 i;
+ 
+ 	/* the 1 (one) below indicates an attempt at versioning, if the
+ 	 * interface in ethtool or the driver changes, this 1 should be
+@@ -404,7 +395,7 @@ ixgb_get_regs(struct net_device *netdev,
+ 	*reg++ = IXGB_GET_STAT(adapter, xofftxc);	/* 134 */
+ 	*reg++ = IXGB_GET_STAT(adapter, rjc);	/* 135 */
+ 
+-	regs->len = (reg - reg_start) * sizeof(uint32_t);
++	regs->len = (reg - reg_start) * sizeof(u32);
+ }
+ 
+ static int
+@@ -416,7 +407,7 @@ ixgb_get_eeprom_len(struct net_device *netdev)
+ 
+ static int
+ ixgb_get_eeprom(struct net_device *netdev,
+-		  struct ethtool_eeprom *eeprom, uint8_t *bytes)
++		  struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 	struct ixgb_hw *hw = &adapter->hw;
+@@ -454,7 +445,7 @@ ixgb_get_eeprom(struct net_device *netdev,
+ 		eeprom_buff[i] = ixgb_get_eeprom_word(hw, (first_word + i));
+ 	}
+ 
+-	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
++	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
+ 			eeprom->len);
+ 	kfree(eeprom_buff);
+ 
+@@ -464,14 +455,14 @@ geeprom_error:
+ 
+ static int
+ ixgb_set_eeprom(struct net_device *netdev,
+-		  struct ethtool_eeprom *eeprom, uint8_t *bytes)
++		  struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 	struct ixgb_hw *hw = &adapter->hw;
+-	uint16_t *eeprom_buff;
++	u16 *eeprom_buff;
+ 	void *ptr;
+ 	int max_len, first_word, last_word;
+-	uint16_t i;
++	u16 i;
+ 
+ 	if(eeprom->len == 0)
+ 		return -EINVAL;
+@@ -570,14 +561,14 @@ ixgb_set_ringparam(struct net_device *netdev,
+ 		return -EINVAL;
+ 
+ 	if(netif_running(adapter->netdev))
+-		ixgb_down(adapter,TRUE);
++		ixgb_down(adapter, true);
+ 
+-	rxdr->count = max(ring->rx_pending,(uint32_t)MIN_RXD);
+-	rxdr->count = min(rxdr->count,(uint32_t)MAX_RXD);
++	rxdr->count = max(ring->rx_pending,(u32)MIN_RXD);
++	rxdr->count = min(rxdr->count,(u32)MAX_RXD);
+ 	rxdr->count = ALIGN(rxdr->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
+ 
+-	txdr->count = max(ring->tx_pending,(uint32_t)MIN_TXD);
+-	txdr->count = min(txdr->count,(uint32_t)MAX_TXD);
++	txdr->count = max(ring->tx_pending,(u32)MIN_TXD);
++	txdr->count = min(txdr->count,(u32)MAX_TXD);
+ 	txdr->count = ALIGN(txdr->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
+ 
+ 	if(netif_running(adapter->netdev)) {
+@@ -633,7 +624,7 @@ ixgb_led_blink_callback(unsigned long data)
+ }
+ 
+ static int
+-ixgb_phys_id(struct net_device *netdev, uint32_t data)
++ixgb_phys_id(struct net_device *netdev, u32 data)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 
+@@ -669,7 +660,7 @@ ixgb_get_sset_count(struct net_device *netdev, int sset)
+ 
+ static void 
+ ixgb_get_ethtool_stats(struct net_device *netdev, 
+-		struct ethtool_stats *stats, uint64_t *data)
++		struct ethtool_stats *stats, u64 *data)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 	int i;
+@@ -678,12 +669,12 @@ ixgb_get_ethtool_stats(struct net_device *netdev,
+ 	for(i = 0; i < IXGB_STATS_LEN; i++) {
+ 		char *p = (char *)adapter+ixgb_gstrings_stats[i].stat_offset;	
+ 		data[i] = (ixgb_gstrings_stats[i].sizeof_stat == 
+-			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
++			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ 	}
+ }
+ 
+ static void 
+-ixgb_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
++ixgb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+ {
+ 	int i;
+ 
+diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
+index 80a8b98..04d2003 100644
+--- a/drivers/net/ixgb/ixgb_hw.c
++++ b/drivers/net/ixgb/ixgb_hw.c
+@@ -35,13 +35,13 @@
+ 
+ /*  Local function prototypes */
+ 
+-static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t * mc_addr);
++static u32 ixgb_hash_mc_addr(struct ixgb_hw *hw, u8 * mc_addr);
+ 
+-static void ixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value);
++static void ixgb_mta_set(struct ixgb_hw *hw, u32 hash_value);
+ 
+ static void ixgb_get_bus_info(struct ixgb_hw *hw);
+ 
+-static boolean_t ixgb_link_reset(struct ixgb_hw *hw);
++static bool ixgb_link_reset(struct ixgb_hw *hw);
+ 
+ static void ixgb_optics_reset(struct ixgb_hw *hw);
+ 
+@@ -55,18 +55,18 @@ static void ixgb_clear_vfta(struct ixgb_hw *hw);
+ 
+ static void ixgb_init_rx_addrs(struct ixgb_hw *hw);
+ 
+-static uint16_t ixgb_read_phy_reg(struct ixgb_hw *hw,
+-				  uint32_t reg_address,
+-				  uint32_t phy_address,
+-				  uint32_t device_type);
++static u16 ixgb_read_phy_reg(struct ixgb_hw *hw,
++				  u32 reg_address,
++				  u32 phy_address,
++				  u32 device_type);
+ 
+-static boolean_t ixgb_setup_fc(struct ixgb_hw *hw);
++static bool ixgb_setup_fc(struct ixgb_hw *hw);
+ 
+-static boolean_t mac_addr_valid(uint8_t *mac_addr);
++static bool mac_addr_valid(u8 *mac_addr);
+ 
+-static uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
++static u32 ixgb_mac_reset(struct ixgb_hw *hw)
+ {
+-	uint32_t ctrl_reg;
++	u32 ctrl_reg;
+ 
+ 	ctrl_reg =  IXGB_CTRL0_RST |
+ 				IXGB_CTRL0_SDP3_DIR |   /* All pins are Output=1 */
+@@ -114,11 +114,11 @@ static uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-boolean_t
++bool
+ ixgb_adapter_stop(struct ixgb_hw *hw)
+ {
+-	uint32_t ctrl_reg;
+-	uint32_t icr_reg;
++	u32 ctrl_reg;
++	u32 icr_reg;
+ 
+ 	DEBUGFUNC("ixgb_adapter_stop");
+ 
+@@ -127,13 +127,13 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
+ 	 */
+ 	if(hw->adapter_stopped) {
+ 		DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
+-		return FALSE;
++		return false;
+ 	}
+ 
+ 	/* Set the Adapter Stopped flag so other driver functions stop
+ 	 * touching the Hardware.
+ 	 */
+-	hw->adapter_stopped = TRUE;
++	hw->adapter_stopped = true;
+ 
+ 	/* Clear interrupt mask to stop board from generating interrupts */
+ 	DEBUGOUT("Masking off all interrupts\n");
+@@ -179,8 +179,8 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
+ static ixgb_xpak_vendor
+ ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
+ {
+-	uint32_t i;
+-	uint16_t vendor_name[5];
++	u32 i;
++	u16 vendor_name[5];
+ 	ixgb_xpak_vendor xpak_vendor;
+ 
+ 	DEBUGFUNC("ixgb_identify_xpak_vendor");
+@@ -286,15 +286,15 @@ ixgb_identify_phy(struct ixgb_hw *hw)
+  * Leaves the transmit and receive units disabled and uninitialized.
+  *
+  * Returns:
+- *      TRUE if successful,
+- *      FALSE if unrecoverable problems were encountered.
++ *      true if successful,
++ *      false if unrecoverable problems were encountered.
+  *****************************************************************************/
+-boolean_t
++bool
+ ixgb_init_hw(struct ixgb_hw *hw)
+ {
+-	uint32_t i;
+-	uint32_t ctrl_reg;
+-	boolean_t status;
++	u32 i;
++	u32 ctrl_reg;
++	bool status;
+ 
+ 	DEBUGFUNC("ixgb_init_hw");
+ 
+@@ -318,9 +318,8 @@ ixgb_init_hw(struct ixgb_hw *hw)
+ 	/* Delay a few ms just to allow the reset to complete */
+ 	msleep(IXGB_DELAY_AFTER_EE_RESET);
+ 
+-	if (ixgb_get_eeprom_data(hw) == FALSE) {
+-		return(FALSE);
+-	}
++	if (!ixgb_get_eeprom_data(hw))
++		return false;
+ 
+ 	/* Use the device id to determine the type of phy/transceiver. */
+ 	hw->device_id = ixgb_get_ee_device_id(hw);
+@@ -337,11 +336,11 @@ ixgb_init_hw(struct ixgb_hw *hw)
+ 	 */
+ 	if (!mac_addr_valid(hw->curr_mac_addr)) {
+ 		DEBUGOUT("MAC address invalid after ixgb_init_rx_addrs\n");
+-		return(FALSE);
++		return(false);
+ 	}
+ 
+ 	/* tell the routines in this file they can access hardware again */
+-	hw->adapter_stopped = FALSE;
++	hw->adapter_stopped = false;
+ 
+ 	/* Fill in the bus_info structure */
+ 	ixgb_get_bus_info(hw);
+@@ -378,7 +377,7 @@ ixgb_init_hw(struct ixgb_hw *hw)
+ static void
+ ixgb_init_rx_addrs(struct ixgb_hw *hw)
+ {
+-	uint32_t i;
++	u32 i;
+ 
+ 	DEBUGFUNC("ixgb_init_rx_addrs");
+ 
+@@ -438,13 +437,13 @@ ixgb_init_rx_addrs(struct ixgb_hw *hw)
+  *****************************************************************************/
+ void
+ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+-			  uint8_t *mc_addr_list,
+-			  uint32_t mc_addr_count,
+-			  uint32_t pad)
++			  u8 *mc_addr_list,
++			  u32 mc_addr_count,
++			  u32 pad)
+ {
+-	uint32_t hash_value;
+-	uint32_t i;
+-	uint32_t rar_used_count = 1;		/* RAR[0] is used for our MAC address */
++	u32 hash_value;
++	u32 i;
++	u32 rar_used_count = 1;		/* RAR[0] is used for our MAC address */
+ 
+ 	DEBUGFUNC("ixgb_mc_addr_list_update");
+ 
+@@ -516,11 +515,11 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+  * Returns:
+  *      The hash value
+  *****************************************************************************/
+-static uint32_t
++static u32
+ ixgb_hash_mc_addr(struct ixgb_hw *hw,
+-		   uint8_t *mc_addr)
++		   u8 *mc_addr)
+ {
+-	uint32_t hash_value = 0;
++	u32 hash_value = 0;
+ 
+ 	DEBUGFUNC("ixgb_hash_mc_addr");
+ 
+@@ -534,18 +533,18 @@ ixgb_hash_mc_addr(struct ixgb_hw *hw,
+ 	case 0:
+ 		/* [47:36] i.e. 0x563 for above example address */
+ 		hash_value =
+-		    ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
++		    ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ 		break;
+ 	case 1:		/* [46:35] i.e. 0xAC6 for above example address */
+ 		hash_value =
+-		    ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
++		    ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+ 		break;
+ 	case 2:		/* [45:34] i.e. 0x5D8 for above example address */
+ 		hash_value =
+-		    ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
++		    ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ 		break;
+ 	case 3:		/* [43:32] i.e. 0x634 for above example address */
+-		hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
++		hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+ 		break;
+ 	default:
+ 		/* Invalid mc_filter_type, what should we do? */
+@@ -566,10 +565,10 @@ ixgb_hash_mc_addr(struct ixgb_hw *hw,
+  *****************************************************************************/
+ static void
+ ixgb_mta_set(struct ixgb_hw *hw,
+-		  uint32_t hash_value)
++		  u32 hash_value)
+ {
+-	uint32_t hash_bit, hash_reg;
+-	uint32_t mta_reg;
++	u32 hash_bit, hash_reg;
++	u32 mta_reg;
+ 
+ 	/* The MTA is a register array of 128 32-bit registers.
+ 	 * It is treated like an array of 4096 bits.  We want to set
+@@ -600,23 +599,23 @@ ixgb_mta_set(struct ixgb_hw *hw,
+  *****************************************************************************/
+ void
+ ixgb_rar_set(struct ixgb_hw *hw,
+-		  uint8_t *addr,
+-		  uint32_t index)
++		  u8 *addr,
++		  u32 index)
+ {
+-	uint32_t rar_low, rar_high;
++	u32 rar_low, rar_high;
+ 
+ 	DEBUGFUNC("ixgb_rar_set");
+ 
+ 	/* HW expects these in little endian so we reverse the byte order
+ 	 * from network order (big endian) to little endian
+ 	 */
+-	rar_low = ((uint32_t) addr[0] |
+-		   ((uint32_t)addr[1] << 8) |
+-		   ((uint32_t)addr[2] << 16) |
+-		   ((uint32_t)addr[3] << 24));
++	rar_low = ((u32) addr[0] |
++		   ((u32)addr[1] << 8) |
++		   ((u32)addr[2] << 16) |
++		   ((u32)addr[3] << 24));
+ 
+-	rar_high = ((uint32_t) addr[4] |
+-			((uint32_t)addr[5] << 8) |
++	rar_high = ((u32) addr[4] |
++			((u32)addr[5] << 8) |
+ 			IXGB_RAH_AV);
+ 
+ 	IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
+@@ -633,8 +632,8 @@ ixgb_rar_set(struct ixgb_hw *hw,
+  *****************************************************************************/
+ void
+ ixgb_write_vfta(struct ixgb_hw *hw,
+-		 uint32_t offset,
+-		 uint32_t value)
++		 u32 offset,
++		 u32 value)
+ {
+ 	IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+ 	return;
+@@ -648,7 +647,7 @@ ixgb_write_vfta(struct ixgb_hw *hw,
+ static void
+ ixgb_clear_vfta(struct ixgb_hw *hw)
+ {
+-	uint32_t offset;
++	u32 offset;
+ 
+ 	for(offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
+ 		IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
+@@ -661,12 +660,12 @@ ixgb_clear_vfta(struct ixgb_hw *hw)
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+ 
+-static boolean_t
++static bool
+ ixgb_setup_fc(struct ixgb_hw *hw)
+ {
+-	uint32_t ctrl_reg;
+-	uint32_t pap_reg = 0;   /* by default, assume no pause time */
+-	boolean_t status = TRUE;
++	u32 ctrl_reg;
++	u32 pap_reg = 0;   /* by default, assume no pause time */
++	bool status = true;
+ 
+ 	DEBUGFUNC("ixgb_setup_fc");
+ 
+@@ -763,15 +762,15 @@ ixgb_setup_fc(struct ixgb_hw *hw)
+  * This requires that first an address cycle command is sent, followed by a
+  * read command.
+  *****************************************************************************/
+-static uint16_t
++static u16
+ ixgb_read_phy_reg(struct ixgb_hw *hw,
+-		uint32_t reg_address,
+-		uint32_t phy_address,
+-		uint32_t device_type)
++		u32 reg_address,
++		u32 phy_address,
++		u32 device_type)
+ {
+-	uint32_t i;
+-	uint32_t data;
+-	uint32_t command = 0;
++	u32 i;
++	u32 data;
++	u32 command = 0;
+ 
+ 	ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
+ 	ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
+@@ -836,7 +835,7 @@ ixgb_read_phy_reg(struct ixgb_hw *hw,
+ 	 */
+ 	data = IXGB_READ_REG(hw, MSRWD);
+ 	data >>= IXGB_MSRWD_READ_DATA_SHIFT;
+-	return((uint16_t) data);
++	return((u16) data);
+ }
+ 
+ /******************************************************************************
+@@ -858,20 +857,20 @@ ixgb_read_phy_reg(struct ixgb_hw *hw,
+  *****************************************************************************/
+ static void
+ ixgb_write_phy_reg(struct ixgb_hw *hw,
+-			uint32_t reg_address,
+-			uint32_t phy_address,
+-			uint32_t device_type,
+-			uint16_t data)
++			u32 reg_address,
++			u32 phy_address,
++			u32 device_type,
++			u16 data)
+ {
+-	uint32_t i;
+-	uint32_t command = 0;
++	u32 i;
++	u32 command = 0;
+ 
+ 	ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
+ 	ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
+ 	ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
+ 
+ 	/* Put the data in the MDIO Read/Write Data register */
+-	IXGB_WRITE_REG(hw, MSRWD, (uint32_t)data);
++	IXGB_WRITE_REG(hw, MSRWD, (u32)data);
+ 
+ 	/* Setup and write the address cycle command */
+ 	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT)  |
+@@ -940,8 +939,8 @@ ixgb_write_phy_reg(struct ixgb_hw *hw,
+ void
+ ixgb_check_for_link(struct ixgb_hw *hw)
+ {
+-	uint32_t status_reg;
+-	uint32_t xpcss_reg;
++	u32 status_reg;
++	u32 xpcss_reg;
+ 
+ 	DEBUGFUNC("ixgb_check_for_link");
+ 
+@@ -950,7 +949,7 @@ ixgb_check_for_link(struct ixgb_hw *hw)
+ 
+ 	if ((xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
+ 	    (status_reg & IXGB_STATUS_LU)) {
+-		hw->link_up = TRUE;
++		hw->link_up = true;
+ 	} else if (!(xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
+ 		   (status_reg & IXGB_STATUS_LU)) {
+ 		DEBUGOUT("XPCSS Not Aligned while Status:LU is set.\n");
+@@ -974,10 +973,10 @@ ixgb_check_for_link(struct ixgb_hw *hw)
+  *
+  * Called by any function that needs to check the link status of the adapter.
+  *****************************************************************************/
+-boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
++bool ixgb_check_for_bad_link(struct ixgb_hw *hw)
+ {
+-	uint32_t newLFC, newRFC;
+-	boolean_t bad_link_returncode = FALSE;
++	u32 newLFC, newRFC;
++	bool bad_link_returncode = false;
+ 
+ 	if (hw->phy_type == ixgb_phy_type_txn17401) {
+ 		newLFC = IXGB_READ_REG(hw, LFC);
+@@ -986,7 +985,7 @@ boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
+ 		    || (hw->lastRFC + 250 < newRFC)) {
+ 			DEBUGOUT
+ 			    ("BAD LINK! too many LFC/RFC since last check\n");
+-			bad_link_returncode = TRUE;
++			bad_link_returncode = true;
+ 		}
+ 		hw->lastLFC = newLFC;
+ 		hw->lastRFC = newRFC;
+@@ -1003,7 +1002,7 @@ boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
+ static void
+ ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
+ {
+-	volatile uint32_t temp_reg;
++	volatile u32 temp_reg;
+ 
+ 	DEBUGFUNC("ixgb_clear_hw_cntrs");
+ 
+@@ -1084,7 +1083,7 @@ ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
+ void
+ ixgb_led_on(struct ixgb_hw *hw)
+ {
+-	uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
++	u32 ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+ 
+ 	/* To turn on the LED, clear software-definable pin 0 (SDP0). */
+ 	ctrl0_reg &= ~IXGB_CTRL0_SDP0;
+@@ -1100,7 +1099,7 @@ ixgb_led_on(struct ixgb_hw *hw)
+ void
+ ixgb_led_off(struct ixgb_hw *hw)
+ {
+-	uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
++	u32 ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+ 
+ 	/* To turn off the LED, set software-definable pin 0 (SDP0). */
+ 	ctrl0_reg |= IXGB_CTRL0_SDP0;
+@@ -1116,7 +1115,7 @@ ixgb_led_off(struct ixgb_hw *hw)
+ static void
+ ixgb_get_bus_info(struct ixgb_hw *hw)
+ {
+-	uint32_t status_reg;
++	u32 status_reg;
+ 
+ 	status_reg = IXGB_READ_REG(hw, STATUS);
+ 
+@@ -1155,21 +1154,21 @@ ixgb_get_bus_info(struct ixgb_hw *hw)
+  * mac_addr - pointer to MAC address.
+  *
+  *****************************************************************************/
+-static boolean_t
+-mac_addr_valid(uint8_t *mac_addr)
++static bool
++mac_addr_valid(u8 *mac_addr)
+ {
+-	boolean_t is_valid = TRUE;
++	bool is_valid = true;
+ 	DEBUGFUNC("mac_addr_valid");
+ 
+ 	/* Make sure it is not a multicast address */
+ 	if (IS_MULTICAST(mac_addr)) {
+ 		DEBUGOUT("MAC address is multicast\n");
+-		is_valid = FALSE;
++		is_valid = false;
+ 	}
+ 	/* Not a broadcast address */
+ 	else if (IS_BROADCAST(mac_addr)) {
+ 		DEBUGOUT("MAC address is broadcast\n");
+-		is_valid = FALSE;
++		is_valid = false;
+ 	}
+ 	/* Reject the zero address */
+ 	else if (mac_addr[0] == 0 &&
+@@ -1179,7 +1178,7 @@ mac_addr_valid(uint8_t *mac_addr)
+ 			 mac_addr[4] == 0 &&
+ 			 mac_addr[5] == 0) {
+ 		DEBUGOUT("MAC address is all zeros\n");
+-		is_valid = FALSE;
++		is_valid = false;
+ 	}
+ 	return (is_valid);
+ }
+@@ -1190,12 +1189,12 @@ mac_addr_valid(uint8_t *mac_addr)
+  *
+  * hw - Struct containing variables accessed by shared code
+  *****************************************************************************/
+-static boolean_t
++static bool
+ ixgb_link_reset(struct ixgb_hw *hw)
+ {
+-	boolean_t link_status = FALSE;
+-	uint8_t wait_retries = MAX_RESET_ITERATIONS;
+-	uint8_t lrst_retries = MAX_RESET_ITERATIONS;
++	bool link_status = false;
++	u8 wait_retries = MAX_RESET_ITERATIONS;
++	u8 lrst_retries = MAX_RESET_ITERATIONS;
+ 
+ 	do {
+ 		/* Reset the link */
+@@ -1208,7 +1207,7 @@ ixgb_link_reset(struct ixgb_hw *hw)
+ 			link_status =
+ 			    ((IXGB_READ_REG(hw, STATUS) & IXGB_STATUS_LU)
+ 			     && (IXGB_READ_REG(hw, XPCSS) &
+-				 IXGB_XPCSS_ALIGN_STATUS)) ? TRUE : FALSE;
++				 IXGB_XPCSS_ALIGN_STATUS)) ? true : false;
+ 		} while (!link_status && --wait_retries);
+ 
+ 	} while (!link_status && --lrst_retries);
+@@ -1225,7 +1224,7 @@ static void
+ ixgb_optics_reset(struct ixgb_hw *hw)
+ {
+ 	if (hw->phy_type == ixgb_phy_type_txn17401) {
+-		uint16_t mdio_reg;
++		u16 mdio_reg;
+ 
+ 		ixgb_write_phy_reg(hw,
+ 					MDIO_PMA_PMD_CR1,
+diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
+index 4f176ff..39cfa47 100644
+--- a/drivers/net/ixgb/ixgb_hw.h
++++ b/drivers/net/ixgb/ixgb_hw.h
+@@ -538,8 +538,8 @@ struct ixgb_rx_desc {
+ 	__le64 buff_addr;
+ 	__le16 length;
+ 	__le16 reserved;
+-	uint8_t status;
+-	uint8_t errors;
++	u8 status;
++	u8 errors;
+ 	__le16 special;
+ };
+ 
+@@ -570,8 +570,8 @@ struct ixgb_rx_desc {
+ struct ixgb_tx_desc {
+ 	__le64 buff_addr;
+ 	__le32 cmd_type_len;
+-	uint8_t status;
+-	uint8_t popts;
++	u8 status;
++	u8 popts;
+ 	__le16 vlan;
+ };
+ 
+@@ -595,15 +595,15 @@ struct ixgb_tx_desc {
+ #define IXGB_TX_DESC_SPECIAL_PRI_SHIFT  IXGB_RX_DESC_SPECIAL_PRI_SHIFT	/* Priority is in upper 3 of 16 */
+ 
+ struct ixgb_context_desc {
+-	uint8_t ipcss;
+-	uint8_t ipcso;
++	u8 ipcss;
++	u8 ipcso;
+ 	__le16 ipcse;
+-	uint8_t tucss;
+-	uint8_t tucso;
++	u8 tucss;
++	u8 tucso;
+ 	__le16 tucse;
+ 	__le32 cmd_type_len;
+-	uint8_t status;
+-	uint8_t hdr_len;
++	u8 status;
++	u8 hdr_len;
+ 	__le16 mss;
+ };
+ 
+@@ -637,33 +637,33 @@ struct ixgb_context_desc {
+ 
+ /* This structure takes a 64k flash and maps it for identification commands */
+ struct ixgb_flash_buffer {
+-	uint8_t manufacturer_id;
+-	uint8_t device_id;
+-	uint8_t filler1[0x2AA8];
+-	uint8_t cmd2;
+-	uint8_t filler2[0x2AAA];
+-	uint8_t cmd1;
+-	uint8_t filler3[0xAAAA];
++	u8 manufacturer_id;
++	u8 device_id;
++	u8 filler1[0x2AA8];
++	u8 cmd2;
++	u8 filler2[0x2AAA];
++	u8 cmd1;
++	u8 filler3[0xAAAA];
+ };
+ 
+ /*
+  * This is a little-endian specific check.
+  */
+ #define IS_MULTICAST(Address) \
+-    (boolean_t)(((uint8_t *)(Address))[0] & ((uint8_t)0x01))
++    (bool)(((u8 *)(Address))[0] & ((u8)0x01))
+ 
+ /*
+  * Check whether an address is broadcast.
+  */
+ #define IS_BROADCAST(Address)               \
+-    ((((uint8_t *)(Address))[0] == ((uint8_t)0xff)) && (((uint8_t *)(Address))[1] == ((uint8_t)0xff)))
++    ((((u8 *)(Address))[0] == ((u8)0xff)) && (((u8 *)(Address))[1] == ((u8)0xff)))
+ 
+ /* Flow control parameters */
+ struct ixgb_fc {
+-	uint32_t high_water;	/* Flow Control High-water          */
+-	uint32_t low_water;	/* Flow Control Low-water           */
+-	uint16_t pause_time;	/* Flow Control Pause timer         */
+-	boolean_t send_xon;	/* Flow control send XON            */
++	u32 high_water;	/* Flow Control High-water          */
++	u32 low_water;	/* Flow Control Low-water           */
++	u16 pause_time;	/* Flow Control Pause timer         */
++	bool send_xon;		/* Flow control send XON            */
+ 	ixgb_fc_type type;	/* Type of flow control             */
+ };
+ 
+@@ -685,139 +685,139 @@ struct ixgb_bus {
+ };
+ 
+ struct ixgb_hw {
+-	uint8_t __iomem *hw_addr;/* Base Address of the hardware     */
++	u8 __iomem *hw_addr;/* Base Address of the hardware     */
+ 	void *back;		/* Pointer to OS-dependent struct   */
+ 	struct ixgb_fc fc;	/* Flow control parameters          */
+ 	struct ixgb_bus bus;	/* Bus parameters                   */
+-	uint32_t phy_id;	/* Phy Identifier                   */
+-	uint32_t phy_addr;	/* XGMII address of Phy             */
++	u32 phy_id;	/* Phy Identifier                   */
++	u32 phy_addr;	/* XGMII address of Phy             */
+ 	ixgb_mac_type mac_type;	/* Identifier for MAC controller    */
+ 	ixgb_phy_type phy_type;	/* Transceiver/phy identifier       */
+-	uint32_t max_frame_size;	/* Maximum frame size supported     */
+-	uint32_t mc_filter_type;	/* Multicast filter hash type       */
+-	uint32_t num_mc_addrs;	/* Number of current Multicast addrs */
+-	uint8_t curr_mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];	/* Individual address currently programmed in MAC */
+-	uint32_t num_tx_desc;	/* Number of Transmit descriptors   */
+-	uint32_t num_rx_desc;	/* Number of Receive descriptors    */
+-	uint32_t rx_buffer_size;	/* Size of Receive buffer           */
+-	boolean_t link_up;	/* TRUE if link is valid            */
+-	boolean_t adapter_stopped;	/* State of adapter                 */
+-	uint16_t device_id;	/* device id from PCI configuration space */
+-	uint16_t vendor_id;	/* vendor id from PCI configuration space */
+-	uint8_t revision_id;	/* revision id from PCI configuration space */
+-	uint16_t subsystem_vendor_id;	/* subsystem vendor id from PCI configuration space */
+-	uint16_t subsystem_id;	/* subsystem id from PCI configuration space */
+-	uint32_t bar0;		/* Base Address registers           */
+-	uint32_t bar1;
+-	uint32_t bar2;
+-	uint32_t bar3;
+-	uint16_t pci_cmd_word;	/* PCI command register id from PCI configuration space */
++	u32 max_frame_size;	/* Maximum frame size supported     */
++	u32 mc_filter_type;	/* Multicast filter hash type       */
++	u32 num_mc_addrs;	/* Number of current Multicast addrs */
++	u8 curr_mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];	/* Individual address currently programmed in MAC */
++	u32 num_tx_desc;	/* Number of Transmit descriptors   */
++	u32 num_rx_desc;	/* Number of Receive descriptors    */
++	u32 rx_buffer_size;	/* Size of Receive buffer           */
++	bool link_up;		/* true if link is valid            */
++	bool adapter_stopped;	/* State of adapter                 */
++	u16 device_id;	/* device id from PCI configuration space */
++	u16 vendor_id;	/* vendor id from PCI configuration space */
++	u8 revision_id;	/* revision id from PCI configuration space */
++	u16 subsystem_vendor_id;	/* subsystem vendor id from PCI configuration space */
++	u16 subsystem_id;	/* subsystem id from PCI configuration space */
++	u32 bar0;		/* Base Address registers           */
++	u32 bar1;
++	u32 bar2;
++	u32 bar3;
++	u16 pci_cmd_word;	/* PCI command register id from PCI configuration space */
+ 	__le16 eeprom[IXGB_EEPROM_SIZE];	/* EEPROM contents read at init time  */
+ 	unsigned long io_base;	/* Our I/O mapped location */
+-	uint32_t lastLFC;
+-	uint32_t lastRFC;
++	u32 lastLFC;
++	u32 lastRFC;
+ };
+ 
+ /* Statistics reported by the hardware */
+ struct ixgb_hw_stats {
+-	uint64_t tprl;
+-	uint64_t tprh;
+-	uint64_t gprcl;
+-	uint64_t gprch;
+-	uint64_t bprcl;
+-	uint64_t bprch;
+-	uint64_t mprcl;
+-	uint64_t mprch;
+-	uint64_t uprcl;
+-	uint64_t uprch;
+-	uint64_t vprcl;
+-	uint64_t vprch;
+-	uint64_t jprcl;
+-	uint64_t jprch;
+-	uint64_t gorcl;
+-	uint64_t gorch;
+-	uint64_t torl;
+-	uint64_t torh;
+-	uint64_t rnbc;
+-	uint64_t ruc;
+-	uint64_t roc;
+-	uint64_t rlec;
+-	uint64_t crcerrs;
+-	uint64_t icbc;
+-	uint64_t ecbc;
+-	uint64_t mpc;
+-	uint64_t tptl;
+-	uint64_t tpth;
+-	uint64_t gptcl;
+-	uint64_t gptch;
+-	uint64_t bptcl;
+-	uint64_t bptch;
+-	uint64_t mptcl;
+-	uint64_t mptch;
+-	uint64_t uptcl;
+-	uint64_t uptch;
+-	uint64_t vptcl;
+-	uint64_t vptch;
+-	uint64_t jptcl;
+-	uint64_t jptch;
+-	uint64_t gotcl;
+-	uint64_t gotch;
+-	uint64_t totl;
+-	uint64_t toth;
+-	uint64_t dc;
+-	uint64_t plt64c;
+-	uint64_t tsctc;
+-	uint64_t tsctfc;
+-	uint64_t ibic;
+-	uint64_t rfc;
+-	uint64_t lfc;
+-	uint64_t pfrc;
+-	uint64_t pftc;
+-	uint64_t mcfrc;
+-	uint64_t mcftc;
+-	uint64_t xonrxc;
+-	uint64_t xontxc;
+-	uint64_t xoffrxc;
+-	uint64_t xofftxc;
+-	uint64_t rjc;
++	u64 tprl;
++	u64 tprh;
++	u64 gprcl;
++	u64 gprch;
++	u64 bprcl;
++	u64 bprch;
++	u64 mprcl;
++	u64 mprch;
++	u64 uprcl;
++	u64 uprch;
++	u64 vprcl;
++	u64 vprch;
++	u64 jprcl;
++	u64 jprch;
++	u64 gorcl;
++	u64 gorch;
++	u64 torl;
++	u64 torh;
++	u64 rnbc;
++	u64 ruc;
++	u64 roc;
++	u64 rlec;
++	u64 crcerrs;
++	u64 icbc;
++	u64 ecbc;
++	u64 mpc;
++	u64 tptl;
++	u64 tpth;
++	u64 gptcl;
++	u64 gptch;
++	u64 bptcl;
++	u64 bptch;
++	u64 mptcl;
++	u64 mptch;
++	u64 uptcl;
++	u64 uptch;
++	u64 vptcl;
++	u64 vptch;
++	u64 jptcl;
++	u64 jptch;
++	u64 gotcl;
++	u64 gotch;
++	u64 totl;
++	u64 toth;
++	u64 dc;
++	u64 plt64c;
++	u64 tsctc;
++	u64 tsctfc;
++	u64 ibic;
++	u64 rfc;
++	u64 lfc;
++	u64 pfrc;
++	u64 pftc;
++	u64 mcfrc;
++	u64 mcftc;
++	u64 xonrxc;
++	u64 xontxc;
++	u64 xoffrxc;
++	u64 xofftxc;
++	u64 rjc;
+ };
+ 
+ /* Function Prototypes */
+-extern boolean_t ixgb_adapter_stop(struct ixgb_hw *hw);
+-extern boolean_t ixgb_init_hw(struct ixgb_hw *hw);
+-extern boolean_t ixgb_adapter_start(struct ixgb_hw *hw);
++extern bool ixgb_adapter_stop(struct ixgb_hw *hw);
++extern bool ixgb_init_hw(struct ixgb_hw *hw);
++extern bool ixgb_adapter_start(struct ixgb_hw *hw);
+ extern void ixgb_check_for_link(struct ixgb_hw *hw);
+-extern boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw);
++extern bool ixgb_check_for_bad_link(struct ixgb_hw *hw);
+ 
+ extern void ixgb_rar_set(struct ixgb_hw *hw,
+-				uint8_t *addr,
+-				uint32_t index);
++				u8 *addr,
++				u32 index);
+ 
+ 
+ /* Filters (multicast, vlan, receive) */
+ extern void ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+-				   uint8_t *mc_addr_list,
+-				   uint32_t mc_addr_count,
+-				   uint32_t pad);
++				   u8 *mc_addr_list,
++				   u32 mc_addr_count,
++				   u32 pad);
+ 
+ /* Vfta functions */
+ extern void ixgb_write_vfta(struct ixgb_hw *hw,
+-				 uint32_t offset,
+-				 uint32_t value);
++				 u32 offset,
++				 u32 value);
+ 
+ /* Access functions to eeprom data */
+-void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
+-uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
+-uint16_t ixgb_get_ee_device_id(struct ixgb_hw *hw);
+-boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw);
+-__le16 ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index);
++void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, u8 *mac_addr);
++u32 ixgb_get_ee_pba_number(struct ixgb_hw *hw);
++u16 ixgb_get_ee_device_id(struct ixgb_hw *hw);
++bool ixgb_get_eeprom_data(struct ixgb_hw *hw);
++__le16 ixgb_get_eeprom_word(struct ixgb_hw *hw, u16 index);
+ 
+ /* Everything else */
+ void ixgb_led_on(struct ixgb_hw *hw);
+ void ixgb_led_off(struct ixgb_hw *hw);
+ void ixgb_write_pci_cfg(struct ixgb_hw *hw,
+-			 uint32_t reg,
+-			 uint16_t * value);
++			 u32 reg,
++			 u16 * value);
+ 
+ 
+ #endif /* _IXGB_HW_H_ */
+diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
+index 6738b4d..cb8dadd 100644
+--- a/drivers/net/ixgb/ixgb_main.c
++++ b/drivers/net/ixgb/ixgb_main.c
+@@ -67,7 +67,7 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
+ /* Local Function Prototypes */
+ 
+ int ixgb_up(struct ixgb_adapter *adapter);
+-void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
++void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
+ void ixgb_reset(struct ixgb_adapter *adapter);
+ int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+ int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+@@ -94,22 +94,22 @@ static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
+ static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
+ static int ixgb_set_mac(struct net_device *netdev, void *p);
+ static irqreturn_t ixgb_intr(int irq, void *data);
+-static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
++static bool ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
+ 
+ #ifdef CONFIG_IXGB_NAPI
+ static int ixgb_clean(struct napi_struct *napi, int budget);
+-static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
+-				   int *work_done, int work_to_do);
++static bool ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
++			      int *work_done, int work_to_do);
+ #else
+-static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
++static bool ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
+ #endif
+ static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
+ static void ixgb_tx_timeout(struct net_device *dev);
+ static void ixgb_tx_timeout_task(struct work_struct *work);
+ static void ixgb_vlan_rx_register(struct net_device *netdev,
+ 				  struct vlan_group *grp);
+-static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+-static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
++static void ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
++static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
+ static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
+ 
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+@@ -197,7 +197,6 @@ module_exit(ixgb_exit_module);
+ static void
+ ixgb_irq_disable(struct ixgb_adapter *adapter)
+ {
+-	atomic_inc(&adapter->irq_sem);
+ 	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
+ 	IXGB_WRITE_FLUSH(&adapter->hw);
+ 	synchronize_irq(adapter->pdev->irq);
+@@ -211,14 +210,12 @@ ixgb_irq_disable(struct ixgb_adapter *adapter)
+ static void
+ ixgb_irq_enable(struct ixgb_adapter *adapter)
+ {
+-	if(atomic_dec_and_test(&adapter->irq_sem)) {
+-		u32 val = IXGB_INT_RXT0 | IXGB_INT_RXDMT0 |
+-			  IXGB_INT_TXDW | IXGB_INT_LSC;
+-		if (adapter->hw.subsystem_vendor_id == SUN_SUBVENDOR_ID)
+-			val |= IXGB_INT_GPI0;
+-		IXGB_WRITE_REG(&adapter->hw, IMS, val);
+-		IXGB_WRITE_FLUSH(&adapter->hw);
+-	}
++	u32 val = IXGB_INT_RXT0 | IXGB_INT_RXDMT0 |
++		  IXGB_INT_TXDW | IXGB_INT_LSC;
++	if (adapter->hw.subsystem_vendor_id == SUN_SUBVENDOR_ID)
++		val |= IXGB_INT_GPI0;
++	IXGB_WRITE_REG(&adapter->hw, IMS, val);
++	IXGB_WRITE_FLUSH(&adapter->hw);
+ }
+ 
+ int
+@@ -274,7 +271,7 @@ ixgb_up(struct ixgb_adapter *adapter)
+ 
+ 		if(hw->max_frame_size >
+ 		   IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
+-			uint32_t ctrl0 = IXGB_READ_REG(hw, CTRL0);
++			u32 ctrl0 = IXGB_READ_REG(hw, CTRL0);
+ 
+ 			if(!(ctrl0 & IXGB_CTRL0_JFE)) {
+ 				ctrl0 |= IXGB_CTRL0_JFE;
+@@ -283,26 +280,30 @@ ixgb_up(struct ixgb_adapter *adapter)
+ 		}
+ 	}
+ 
+-	mod_timer(&adapter->watchdog_timer, jiffies);
++	clear_bit(__IXGB_DOWN, &adapter->flags);
+ 
+ #ifdef CONFIG_IXGB_NAPI
+ 	napi_enable(&adapter->napi);
+ #endif
+ 	ixgb_irq_enable(adapter);
+ 
++	mod_timer(&adapter->watchdog_timer, jiffies);
++
+ 	return 0;
+ }
+ 
+ void
+-ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
++ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+ 
++	/* prevent the interrupt handler from restarting watchdog */
++	set_bit(__IXGB_DOWN, &adapter->flags);
++
+ #ifdef CONFIG_IXGB_NAPI
+ 	napi_disable(&adapter->napi);
+-	atomic_set(&adapter->irq_sem, 0);
+ #endif
+-
++	/* waiting for NAPI to complete can re-enable interrupts */
+ 	ixgb_irq_disable(adapter);
+ 	free_irq(adapter->pdev->irq, netdev);
+ 
+@@ -589,9 +590,9 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
+ 	/* enable flow control to be programmed */
+ 	hw->fc.send_xon = 1;
+ 
+-	atomic_set(&adapter->irq_sem, 1);
+ 	spin_lock_init(&adapter->tx_lock);
+ 
++	set_bit(__IXGB_DOWN, &adapter->flags);
+ 	return 0;
+ }
+ 
+@@ -656,7 +657,7 @@ ixgb_close(struct net_device *netdev)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 
+-	ixgb_down(adapter, TRUE);
++	ixgb_down(adapter, true);
+ 
+ 	ixgb_free_tx_resources(adapter);
+ 	ixgb_free_rx_resources(adapter);
+@@ -717,9 +718,9 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
+ static void
+ ixgb_configure_tx(struct ixgb_adapter *adapter)
+ {
+-	uint64_t tdba = adapter->tx_ring.dma;
+-	uint32_t tdlen = adapter->tx_ring.count * sizeof(struct ixgb_tx_desc);
+-	uint32_t tctl;
++	u64 tdba = adapter->tx_ring.dma;
++	u32 tdlen = adapter->tx_ring.count * sizeof(struct ixgb_tx_desc);
++	u32 tctl;
+ 	struct ixgb_hw *hw = &adapter->hw;
+ 
+ 	/* Setup the Base and Length of the Tx Descriptor Ring 
+@@ -805,7 +806,7 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
+ static void
+ ixgb_setup_rctl(struct ixgb_adapter *adapter)
+ {
+-	uint32_t rctl;
++	u32 rctl;
+ 
+ 	rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+ 
+@@ -840,12 +841,12 @@ ixgb_setup_rctl(struct ixgb_adapter *adapter)
+ static void
+ ixgb_configure_rx(struct ixgb_adapter *adapter)
+ {
+-	uint64_t rdba = adapter->rx_ring.dma;
+-	uint32_t rdlen = adapter->rx_ring.count * sizeof(struct ixgb_rx_desc);
++	u64 rdba = adapter->rx_ring.dma;
++	u32 rdlen = adapter->rx_ring.count * sizeof(struct ixgb_rx_desc);
+ 	struct ixgb_hw *hw = &adapter->hw;
+-	uint32_t rctl;
+-	uint32_t rxcsum;
+-	uint32_t rxdctl;
++	u32 rctl;
++	u32 rxcsum;
++	u32 rxdctl;
+ 
+ 	/* make sure receives are disabled while setting up the descriptors */
+ 
+@@ -881,7 +882,7 @@ ixgb_configure_rx(struct ixgb_adapter *adapter)
+ 	IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
+ 
+ 	/* Enable Receive Checksum Offload for TCP and UDP */
+-	if(adapter->rx_csum == TRUE) {
++	if (adapter->rx_csum) {
+ 		rxcsum = IXGB_READ_REG(hw, RXCSUM);
+ 		rxcsum |= IXGB_RXCSUM_TUOFL;
+ 		IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
+@@ -1078,7 +1079,7 @@ ixgb_set_multi(struct net_device *netdev)
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 	struct ixgb_hw *hw = &adapter->hw;
+ 	struct dev_mc_list *mc_ptr;
+-	uint32_t rctl;
++	u32 rctl;
+ 	int i;
+ 
+ 	/* Check for Promiscuous and All Multicast modes */
+@@ -1098,7 +1099,7 @@ ixgb_set_multi(struct net_device *netdev)
+ 		rctl |= IXGB_RCTL_MPE;
+ 		IXGB_WRITE_REG(hw, RCTL, rctl);
+ 	} else {
+-		uint8_t mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES *
++		u8 mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES *
+ 			    IXGB_ETH_LENGTH_OF_ADDRESS];
+ 
+ 		IXGB_WRITE_REG(hw, RCTL, rctl);
+@@ -1164,7 +1165,7 @@ ixgb_watchdog(unsigned long data)
+ 	}
+ 
+ 	/* Force detection of hung controller every watchdog period */
+-	adapter->detect_tx_hung = TRUE;
++	adapter->detect_tx_hung = true;
+ 
+ 	/* generate an interrupt to force clean up of any stragglers */
+ 	IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);
+@@ -1182,8 +1183,8 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ {
+ 	struct ixgb_context_desc *context_desc;
+ 	unsigned int i;
+-	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+-	uint16_t ipcse, tucse, mss;
++	u8 ipcss, ipcso, tucss, tucso, hdr_len;
++	u16 ipcse, tucse, mss;
+ 	int err;
+ 
+ 	if (likely(skb_is_gso(skb))) {
+@@ -1243,12 +1244,12 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ 	return 0;
+ }
+ 
+-static boolean_t
++static bool
+ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ {
+ 	struct ixgb_context_desc *context_desc;
+ 	unsigned int i;
+-	uint8_t css, cso;
++	u8 css, cso;
+ 
+ 	if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ 		struct ixgb_buffer *buffer_info;
+@@ -1264,7 +1265,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ 		context_desc->tucso = cso;
+ 		context_desc->tucse = 0;
+ 		/* zero out any previously existing data in one instruction */
+-		*(uint32_t *)&(context_desc->ipcss) = 0;
++		*(u32 *)&(context_desc->ipcss) = 0;
+ 		context_desc->status = 0;
+ 		context_desc->hdr_len = 0;
+ 		context_desc->mss = 0;
+@@ -1275,10 +1276,10 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ 		if(++i == adapter->tx_ring.count) i = 0;
+ 		adapter->tx_ring.next_to_use = i;
+ 
+-		return TRUE;
++		return true;
+ 	}
+ 
+-	return FALSE;
++	return false;
+ }
+ 
+ #define IXGB_MAX_TXD_PWR	14
+@@ -1371,9 +1372,9 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
+ 	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+ 	struct ixgb_tx_desc *tx_desc = NULL;
+ 	struct ixgb_buffer *buffer_info;
+-	uint32_t cmd_type_len = adapter->tx_cmd_type;
+-	uint8_t status = 0;
+-	uint8_t popts = 0;
++	u32 cmd_type_len = adapter->tx_cmd_type;
++	u8 status = 0;
++	u8 popts = 0;
+ 	unsigned int i;
+ 
+ 	if(tx_flags & IXGB_TX_FLAGS_TSO) {
+@@ -1464,14 +1465,18 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 	int vlan_id = 0;
+ 	int tso;
+ 
++	if (test_bit(__IXGB_DOWN, &adapter->flags)) {
++		dev_kfree_skb(skb);
++		return NETDEV_TX_OK;
++	}
++
+ 	if(skb->len <= 0) {
+ 		dev_kfree_skb_any(skb);
+ 		return 0;
+ 	}
+ 
+ #ifdef NETIF_F_LLTX
+-	local_irq_save(flags);
+-	if (!spin_trylock(&adapter->tx_lock)) {
++	if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
+ 		/* Collision - tell upper layer to requeue */
+ 		local_irq_restore(flags);
+ 		return NETDEV_TX_LOCKED;
+@@ -1548,7 +1553,7 @@ ixgb_tx_timeout_task(struct work_struct *work)
+ 		container_of(work, struct ixgb_adapter, tx_timeout_task);
+ 
+ 	adapter->tx_timeout_count++;
+-	ixgb_down(adapter, TRUE);
++	ixgb_down(adapter, true);
+ 	ixgb_up(adapter);
+ }
+ 
+@@ -1595,7 +1600,7 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
+ 	netdev->mtu = new_mtu;
+ 
+ 	if ((old_max_frame != max_frame) && netif_running(netdev)) {
+-		ixgb_down(adapter, TRUE);
++		ixgb_down(adapter, true);
+ 		ixgb_up(adapter);
+ 	}
+ 
+@@ -1745,7 +1750,7 @@ ixgb_intr(int irq, void *data)
+ 	struct net_device *netdev = data;
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 	struct ixgb_hw *hw = &adapter->hw;
+-	uint32_t icr = IXGB_READ_REG(hw, ICR);
++	u32 icr = IXGB_READ_REG(hw, ICR);
+ #ifndef CONFIG_IXGB_NAPI
+ 	unsigned int i;
+ #endif
+@@ -1753,9 +1758,9 @@ ixgb_intr(int irq, void *data)
+ 	if(unlikely(!icr))
+ 		return IRQ_NONE;  /* Not our interrupt */
+ 
+-	if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
+-		mod_timer(&adapter->watchdog_timer, jiffies);
+-	}
++	if (unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)))
++		if (!test_bit(__IXGB_DOWN, &adapter->flags))
++			mod_timer(&adapter->watchdog_timer, jiffies);
+ 
+ #ifdef CONFIG_IXGB_NAPI
+ 	if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+@@ -1764,7 +1769,6 @@ ixgb_intr(int irq, void *data)
+ 		  of the posted write is intentionally left out.
+ 		*/
+ 
+-		atomic_inc(&adapter->irq_sem);
+ 		IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
+ 		__netif_rx_schedule(netdev, &adapter->napi);
+ 	}
+@@ -1812,7 +1816,7 @@ ixgb_clean(struct napi_struct *napi, int budget)
+  * @adapter: board private structure
+  **/
+ 
+-static boolean_t
++static bool
+ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+ {
+ 	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+@@ -1820,7 +1824,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+ 	struct ixgb_tx_desc *tx_desc, *eop_desc;
+ 	struct ixgb_buffer *buffer_info;
+ 	unsigned int i, eop;
+-	boolean_t cleaned = FALSE;
++	bool cleaned = false;
+ 
+ 	i = tx_ring->next_to_clean;
+ 	eop = tx_ring->buffer_info[i].next_to_watch;
+@@ -1828,7 +1832,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+ 
+ 	while(eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
+ 
+-		for(cleaned = FALSE; !cleaned; ) {
++		for (cleaned = false; !cleaned; ) {
+ 			tx_desc = IXGB_TX_DESC(*tx_ring, i);
+ 			buffer_info = &tx_ring->buffer_info[i];
+ 
+@@ -1839,7 +1843,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+ 
+ 			ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
+ 
+-			*(uint32_t *)&(tx_desc->status) = 0;
++			*(u32 *)&(tx_desc->status) = 0;
+ 
+ 			cleaned = (i == eop);
+ 			if(++i == tx_ring->count) i = 0;
+@@ -1862,7 +1866,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+ 	if(adapter->detect_tx_hung) {
+ 		/* detect a transmit hang in hardware, this serializes the
+ 		 * check with the clearing of time_stamp and movement of i */
+-		adapter->detect_tx_hung = FALSE;
++		adapter->detect_tx_hung = false;
+ 		if (tx_ring->buffer_info[eop].dma &&
+ 		   time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ)
+ 		   && !(IXGB_READ_REG(&adapter->hw, STATUS) &
+@@ -1932,7 +1936,7 @@ ixgb_rx_checksum(struct ixgb_adapter *adapter,
+  * @adapter: board private structure
+  **/
+ 
+-static boolean_t
++static bool
+ #ifdef CONFIG_IXGB_NAPI
+ ixgb_clean_rx_irq(struct ixgb_adapter *adapter, int *work_done, int work_to_do)
+ #else
+@@ -1944,9 +1948,9 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
+ 	struct pci_dev *pdev = adapter->pdev;
+ 	struct ixgb_rx_desc *rx_desc, *next_rxd;
+ 	struct ixgb_buffer *buffer_info, *next_buffer, *next2_buffer;
+-	uint32_t length;
++	u32 length;
+ 	unsigned int i, j;
+-	boolean_t cleaned = FALSE;
++	bool cleaned = false;
+ 
+ 	i = rx_ring->next_to_clean;
+ 	rx_desc = IXGB_RX_DESC(*rx_ring, i);
+@@ -1980,7 +1984,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
+ 		next_skb = next_buffer->skb;
+ 		prefetch(next_skb);
+ 
+-		cleaned = TRUE;
++		cleaned = true;
+ 
+ 		pci_unmap_single(pdev,
+ 				 buffer_info->dma,
+@@ -2162,7 +2166,7 @@ static void
+ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+-	uint32_t ctrl, rctl;
++	u32 ctrl, rctl;
+ 
+ 	ixgb_irq_disable(adapter);
+ 	adapter->vlgrp = grp;
+@@ -2193,14 +2197,16 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ 		IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+ 	}
+ 
+-	ixgb_irq_enable(adapter);
++	/* don't enable interrupts unless we are UP */
++	if (adapter->netdev->flags & IFF_UP)
++		ixgb_irq_enable(adapter);
+ }
+ 
+ static void
+-ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
++ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+-	uint32_t vfta, index;
++	u32 vfta, index;
+ 
+ 	/* add VID to filter table */
+ 
+@@ -2211,18 +2217,20 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
+ }
+ 
+ static void
+-ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
++ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+ {
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+-	uint32_t vfta, index;
++	u32 vfta, index;
+ 
+ 	ixgb_irq_disable(adapter);
+ 
+ 	vlan_group_set_device(adapter->vlgrp, vid, NULL);
+ 
+-	ixgb_irq_enable(adapter);
++	/* don't enable interrupts unless we are UP */
++	if (adapter->netdev->flags & IFF_UP)
++		ixgb_irq_enable(adapter);
+ 
+-	/* remove VID from filter table*/
++	/* remove VID from filter table */
+ 
+ 	index = (vid >> 5) & 0x7F;
+ 	vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+@@ -2236,7 +2244,7 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter)
+ 	ixgb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ 
+ 	if(adapter->vlgrp) {
+-		uint16_t vid;
++		u16 vid;
+ 		for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ 			if(!vlan_group_get_device(adapter->vlgrp, vid))
+ 				continue;
+@@ -2277,7 +2285,7 @@ static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
+ 	struct ixgb_adapter *adapter = netdev_priv(netdev);
+ 
+ 	if(netif_running(netdev))
+-		ixgb_down(adapter, TRUE);
++		ixgb_down(adapter, true);
+ 
+ 	pci_disable_device(pdev);
+ 
+diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
+index 9e04a6b..4be1b27 100644
+--- a/drivers/net/ixgb/ixgb_osdep.h
++++ b/drivers/net/ixgb/ixgb_osdep.h
+@@ -39,13 +39,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+ 
+-typedef enum {
+-#undef FALSE
+-	FALSE = 0,
+-#undef TRUE
+-	TRUE = 1
+-} boolean_t;
+-
+ #undef ASSERT
+ #define ASSERT(x)	if(!(x)) BUG()
+ #define MSGOUT(S, A, B)	printk(KERN_DEBUG S "\n", A, B)
+diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
+index d0bf206..d981134 100644
+--- a/drivers/net/ixgbe/ixgbe.h
++++ b/drivers/net/ixgbe/ixgbe.h
+@@ -36,6 +36,9 @@
+ #include "ixgbe_type.h"
+ #include "ixgbe_common.h"
+ 
++#ifdef CONFIG_DCA
++#include <linux/dca.h>
++#endif
+ 
+ #define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args)
+ 
+@@ -120,7 +123,6 @@ struct ixgbe_queue_stats {
+ };
+ 
+ struct ixgbe_ring {
+-	struct ixgbe_adapter *adapter;	/* backlink */
+ 	void *desc;			/* descriptor ring memory */
+ 	dma_addr_t dma;			/* phys. address of descriptor ring */
+ 	unsigned int size;		/* length in bytes */
+@@ -128,6 +130,7 @@ struct ixgbe_ring {
+ 	unsigned int next_to_use;
+ 	unsigned int next_to_clean;
+ 
++	int queue_index; /* needed for multiqueue queue management */
+ 	union {
+ 		struct ixgbe_tx_buffer *tx_buffer_info;
+ 		struct ixgbe_rx_buffer *rx_buffer_info;
+@@ -136,8 +139,21 @@ struct ixgbe_ring {
+ 	u16 head;
+ 	u16 tail;
+ 
++	unsigned int total_bytes;
++	unsigned int total_packets;
+ 
++	u16 reg_idx; /* holds the special value that gets the hardware register
++		      * offset associated with this ring, which is different
++		      * for DCE and RSS modes */
++
++#ifdef CONFIG_DCA
++	/* cpu for tx queue */
++	int cpu;
++#endif
+ 	struct ixgbe_queue_stats stats;
++	u8 v_idx; /* maps directly to the index for this ring in the hardware
++		   * vector array, can also be used for finding the bit in EICR
++		   * and friends that represents the vector for this ring */
+ 
+ 	u32 eims_value;
+ 	u16 itr_register;
+@@ -146,6 +162,33 @@ struct ixgbe_ring {
+ 	u16 work_limit;                /* max work per interrupt */
+ };
+ 
++#define RING_F_VMDQ 1
++#define RING_F_RSS  2
++#define IXGBE_MAX_RSS_INDICES  16
++#define IXGBE_MAX_VMDQ_INDICES 16
++struct ixgbe_ring_feature {
++	int indices;
++	int mask;
++};
++
++#define MAX_RX_QUEUES 64
++#define MAX_TX_QUEUES 32
++
++/* MAX_MSIX_Q_VECTORS of these are allocated,
++ * but we only use one per queue-specific vector.
++ */
++struct ixgbe_q_vector {
++	struct ixgbe_adapter *adapter;
++	struct napi_struct napi;
++	DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */
++	DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
++	u8 rxr_count;     /* Rx ring count assigned to this vector */
++	u8 txr_count;     /* Tx ring count assigned to this vector */
++	u8 tx_eitr;
++	u8 rx_eitr;
++	u32 eitr;
++};
++
+ /* Helper macros to switch between ints/sec and what the register uses.
+  * And yes, it's the same math going both ways.
+  */
+@@ -166,6 +209,14 @@ struct ixgbe_ring {
+ 
+ #define IXGBE_MAX_JUMBO_FRAME_SIZE        16128
+ 
++#define OTHER_VECTOR 1
++#define NON_Q_VECTORS (OTHER_VECTOR)
++
++#define MAX_MSIX_Q_VECTORS 16
++#define MIN_MSIX_Q_VECTORS 2
++#define MAX_MSIX_COUNT (MAX_MSIX_Q_VECTORS + NON_Q_VECTORS)
++#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NON_Q_VECTORS)
++
+ /* board specific private data structure */
+ struct ixgbe_adapter {
+ 	struct timer_list watchdog_timer;
+@@ -173,10 +224,16 @@ struct ixgbe_adapter {
+ 	u16 bd_number;
+ 	u16 rx_buf_len;
+ 	struct work_struct reset_task;
++	struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS];
++	char name[MAX_MSIX_COUNT][IFNAMSIZ + 5];
++
++	/* Interrupt Throttle Rate */
++	u32 itr_setting;
++	u16 eitr_low;
++	u16 eitr_high;
+ 
+ 	/* TX */
+ 	struct ixgbe_ring *tx_ring;	/* One per active queue */
+-	struct napi_struct napi;
+ 	u64 restart_queue;
+ 	u64 lsc_int;
+ 	u64 hw_tso_ctxt;
+@@ -192,22 +249,27 @@ struct ixgbe_adapter {
+ 	u64 non_eop_descs;
+ 	int num_tx_queues;
+ 	int num_rx_queues;
++	int num_msix_vectors;
++	struct ixgbe_ring_feature ring_feature[3];
+ 	struct msix_entry *msix_entries;
+ 
+ 	u64 rx_hdr_split;
+ 	u32 alloc_rx_page_failed;
+ 	u32 alloc_rx_buff_failed;
+ 
++	/* Some features need tri-state capability,
++	 * thus the additional *_CAPABLE flags.
++	 */
+ 	u32 flags;
+-#define IXGBE_FLAG_RX_CSUM_ENABLED              (u32)(1)
++#define IXGBE_FLAG_RX_CSUM_ENABLED              (u32)(1 << 0)
+ #define IXGBE_FLAG_MSI_ENABLED                  (u32)(1 << 1)
+-#define IXGBE_FLAG_MSIX_ENABLED			(u32)(1 << 2)
+-#define IXGBE_FLAG_RX_PS_ENABLED		(u32)(1 << 3)
+-#define IXGBE_FLAG_IN_NETPOLL			(u32)(1 << 4)
+-
+-	/* Interrupt Throttle Rate */
+-	u32 rx_eitr;
+-	u32 tx_eitr;
++#define IXGBE_FLAG_MSIX_ENABLED                 (u32)(1 << 2)
++#define IXGBE_FLAG_RX_PS_ENABLED                (u32)(1 << 3)
++#define IXGBE_FLAG_IN_NETPOLL                   (u32)(1 << 4)
++#define IXGBE_FLAG_IMIR_ENABLED                 (u32)(1 << 5)
++#define IXGBE_FLAG_RSS_ENABLED                  (u32)(1 << 6)
++#define IXGBE_FLAG_VMDQ_ENABLED                 (u32)(1 << 7)
++#define IXGBE_FLAG_DCA_ENABLED                  (u32)(1 << 8)
+ 
+ 	/* OS defined structs */
+ 	struct net_device *netdev;
+@@ -218,7 +280,10 @@ struct ixgbe_adapter {
+ 	struct ixgbe_hw hw;
+ 	u16 msg_enable;
+ 	struct ixgbe_hw_stats stats;
+-	char lsc_name[IFNAMSIZ + 5];
++
++	/* Interrupt Throttle Rate */
++	u32 rx_eitr;
++	u32 tx_eitr;
+ 
+ 	unsigned long state;
+ 	u64 tx_busy;
+diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
+index a119cbd..4e46377 100644
+--- a/drivers/net/ixgbe/ixgbe_ethtool.c
++++ b/drivers/net/ixgbe/ixgbe_ethtool.c
+@@ -246,13 +246,26 @@ static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
+ 
+ static int ixgbe_set_tso(struct net_device *netdev, u32 data)
+ {
+-
+ 	if (data) {
+ 		netdev->features |= NETIF_F_TSO;
+ 		netdev->features |= NETIF_F_TSO6;
+ 	} else {
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++		struct ixgbe_adapter *adapter = netdev_priv(netdev);
++		int i;
++#endif
++		netif_stop_queue(netdev);
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++		for (i = 0; i < adapter->num_tx_queues; i++)
++			netif_stop_subqueue(netdev, i);
++#endif
+ 		netdev->features &= ~NETIF_F_TSO;
+ 		netdev->features &= ~NETIF_F_TSO6;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++		for (i = 0; i < adapter->num_tx_queues; i++)
++			netif_start_subqueue(netdev, i);
++#endif
++		netif_start_queue(netdev);
+ 	}
+ 	return 0;
+ }
+@@ -873,13 +886,13 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
+ {
+ 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ 
+-	if (adapter->rx_eitr == 0)
+-		ec->rx_coalesce_usecs = 0;
++	if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
++		ec->rx_coalesce_usecs = adapter->rx_eitr;
+ 	else
+ 		ec->rx_coalesce_usecs = 1000000 / adapter->rx_eitr;
+ 
+-	if (adapter->tx_eitr == 0)
+-		ec->tx_coalesce_usecs = 0;
++	if (adapter->tx_eitr < IXGBE_MIN_ITR_USECS)
++		ec->tx_coalesce_usecs = adapter->tx_eitr;
+ 	else
+ 		ec->tx_coalesce_usecs = 1000000 / adapter->tx_eitr;
+ 
+@@ -893,22 +906,26 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
+ 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ 
+ 	if ((ec->rx_coalesce_usecs > IXGBE_MAX_ITR_USECS) ||
+-	    ((ec->rx_coalesce_usecs > 0) &&
++	    ((ec->rx_coalesce_usecs != 0) &&
++	     (ec->rx_coalesce_usecs != 1) &&
++	     (ec->rx_coalesce_usecs != 3) &&
+ 	     (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
+ 		return -EINVAL;
+ 	if ((ec->tx_coalesce_usecs > IXGBE_MAX_ITR_USECS) ||
+-	    ((ec->tx_coalesce_usecs > 0) &&
++	    ((ec->tx_coalesce_usecs != 0) &&
++	     (ec->tx_coalesce_usecs != 1) &&
++	     (ec->tx_coalesce_usecs != 3) &&
+ 	     (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
+ 		return -EINVAL;
+ 
+ 	/* convert to rate of irq's per second */
+-	if (ec->rx_coalesce_usecs == 0)
+-		adapter->rx_eitr = 0;
++	if (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
++		adapter->rx_eitr = ec->rx_coalesce_usecs;
+ 	else
+ 		adapter->rx_eitr = (1000000 / ec->rx_coalesce_usecs);
+ 
+-	if (ec->tx_coalesce_usecs == 0)
+-		adapter->tx_eitr = 0;
++	if (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
++		adapter->tx_eitr = ec->rx_coalesce_usecs;
+ 	else
+ 		adapter->tx_eitr = (1000000 / ec->tx_coalesce_usecs);
+ 
+diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
+index c2095ce..7b85922 100644
+--- a/drivers/net/ixgbe/ixgbe_main.c
++++ b/drivers/net/ixgbe/ixgbe_main.c
+@@ -48,7 +48,7 @@ char ixgbe_driver_name[] = "ixgbe";
+ static const char ixgbe_driver_string[] =
+ 	"Intel(R) 10 Gigabit PCI Express Network Driver";
+ 
+-#define DRV_VERSION "1.1.18"
++#define DRV_VERSION "1.3.18-k2"
+ const char ixgbe_driver_version[] = DRV_VERSION;
+ static const char ixgbe_copyright[] =
+ 	 "Copyright (c) 1999-2007 Intel Corporation.";
+@@ -80,6 +80,16 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
+ };
+ MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);
+ 
++#ifdef CONFIG_DCA
++static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
++			    void *p);
++static struct notifier_block dca_notifier = {
++	.notifier_call = ixgbe_notify_dca,
++	.next          = NULL,
++	.priority      = 0
++};
++#endif
++
+ MODULE_AUTHOR("Intel Corporation, <linux.nics at intel.com>");
+ MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
+ MODULE_LICENSE("GPL");
+@@ -256,26 +266,125 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
+ 		 * sees the new next_to_clean.
+ 		 */
+ 		smp_mb();
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++		if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
++		    !test_bit(__IXGBE_DOWN, &adapter->state)) {
++			netif_wake_subqueue(netdev, tx_ring->queue_index);
++			adapter->restart_queue++;
++		}
++#else
+ 		if (netif_queue_stopped(netdev) &&
+ 		    !test_bit(__IXGBE_DOWN, &adapter->state)) {
+ 			netif_wake_queue(netdev);
+ 			adapter->restart_queue++;
+ 		}
++#endif
+ 	}
+ 
+ 	if (adapter->detect_tx_hung)
+ 		if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc))
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++			netif_stop_subqueue(netdev, tx_ring->queue_index);
++#else
+ 			netif_stop_queue(netdev);
++#endif
+ 
+ 	if (total_tx_packets >= tx_ring->work_limit)
+ 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value);
+ 
++	tx_ring->total_bytes += total_tx_bytes;
++	tx_ring->total_packets += total_tx_packets;
+ 	adapter->net_stats.tx_bytes += total_tx_bytes;
+ 	adapter->net_stats.tx_packets += total_tx_packets;
+ 	cleaned = total_tx_packets ? true : false;
+ 	return cleaned;
+ }
+ 
++#ifdef CONFIG_DCA
++static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
++				struct ixgbe_ring *rxr)
++{
++	u32 rxctrl;
++	int cpu = get_cpu();
++	int q = rxr - adapter->rx_ring;
++
++	if (rxr->cpu != cpu) {
++		rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q));
++		rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK;
++		rxctrl |= dca_get_tag(cpu);
++		rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
++		rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
++		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl);
++		rxr->cpu = cpu;
++	}
++	put_cpu();
++}
++
++static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
++				struct ixgbe_ring *txr)
++{
++	u32 txctrl;
++	int cpu = get_cpu();
++	int q = txr - adapter->tx_ring;
++
++	if (txr->cpu != cpu) {
++		txctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q));
++		txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK;
++		txctrl |= dca_get_tag(cpu);
++		txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
++		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q), txctrl);
++		txr->cpu = cpu;
++	}
++	put_cpu();
++}
++
++static void ixgbe_setup_dca(struct ixgbe_adapter *adapter)
++{
++	int i;
++
++	if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
++		return;
++
++	for (i = 0; i < adapter->num_tx_queues; i++) {
++		adapter->tx_ring[i].cpu = -1;
++		ixgbe_update_tx_dca(adapter, &adapter->tx_ring[i]);
++	}
++	for (i = 0; i < adapter->num_rx_queues; i++) {
++		adapter->rx_ring[i].cpu = -1;
++		ixgbe_update_rx_dca(adapter, &adapter->rx_ring[i]);
++	}
++}
++
++static int __ixgbe_notify_dca(struct device *dev, void *data)
++{
++	struct net_device *netdev = dev_get_drvdata(dev);
++	struct ixgbe_adapter *adapter = netdev_priv(netdev);
++	unsigned long event = *(unsigned long *)data;
++
++	switch (event) {
++	case DCA_PROVIDER_ADD:
++		adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
++		/* Always use CB2 mode, difference is masked
++		 * in the CB driver. */
++		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
++		if (dca_add_requester(dev) == 0) {
++			ixgbe_setup_dca(adapter);
++			break;
++		}
++		/* Fall Through since DCA is disabled. */
++	case DCA_PROVIDER_REMOVE:
++		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
++			dca_remove_requester(dev);
++			adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
++			IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
++		}
++		break;
++	}
++
++	return 0;
++}
++
++#endif /* CONFIG_DCA */
+ /**
+  * ixgbe_receive_skb - Send a completed packet up the stack
+  * @adapter: board private structure
+@@ -556,10 +665,15 @@ next_desc:
+ 	adapter->net_stats.rx_bytes += total_rx_bytes;
+ 	adapter->net_stats.rx_packets += total_rx_packets;
+ 
++	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;
++
+ 	return cleaned;
+ }
+ 
+-#define IXGBE_MAX_INTR 10
++static int ixgbe_clean_rxonly(struct napi_struct *, int);
+ /**
+  * ixgbe_configure_msix - Configure MSI-X hardware
+  * @adapter: board private structure
+@@ -569,28 +683,195 @@ next_desc:
+  **/
+ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
+ {
+-	int i, vector = 0;
++	struct ixgbe_q_vector *q_vector;
++	int i, j, q_vectors, v_idx, r_idx;
++	u32 mask;
+ 
+-	for (i = 0; i < adapter->num_tx_queues; i++) {
+-		ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(i),
+-			       IXGBE_MSIX_VECTOR(vector));
+-		writel(EITR_INTS_PER_SEC_TO_REG(adapter->tx_eitr),
+-		       adapter->hw.hw_addr + adapter->tx_ring[i].itr_register);
+-		vector++;
+-	}
++	q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ 
+-	for (i = 0; i < adapter->num_rx_queues; i++) {
+-		ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(i),
+-			       IXGBE_MSIX_VECTOR(vector));
+-		writel(EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr),
+-		       adapter->hw.hw_addr + adapter->rx_ring[i].itr_register);
+-		vector++;
++	/* Populate the IVAR table and set the ITR values to the
++	 * corresponding register.
++	 */
++	for (v_idx = 0; v_idx < q_vectors; v_idx++) {
++		q_vector = &adapter->q_vector[v_idx];
++		/* XXX for_each_bit(...) */
++		r_idx = find_first_bit(q_vector->rxr_idx,
++				      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, IXGBE_IVAR_RX_QUEUE(j), v_idx);
++			r_idx = find_next_bit(q_vector->rxr_idx,
++					      adapter->num_rx_queues,
++					      r_idx + 1);
++		}
++		r_idx = find_first_bit(q_vector->txr_idx,
++				       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, IXGBE_IVAR_TX_QUEUE(j), v_idx);
++			r_idx = find_next_bit(q_vector->txr_idx,
++					      adapter->num_tx_queues,
++					      r_idx + 1);
++		}
++
++		/* if this is a tx only vector use half the irq (tx) rate */
++		if (q_vector->txr_count && !q_vector->rxr_count)
++			q_vector->eitr = adapter->tx_eitr;
++		else
++			/* rx only or mixed */
++			q_vector->eitr = adapter->rx_eitr;
++
++		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx),
++				EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
+ 	}
+ 
+-	vector = adapter->num_tx_queues + adapter->num_rx_queues;
+-	ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX,
+-		       IXGBE_MSIX_VECTOR(vector));
+-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(vector), 1950);
++	ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX, v_idx);
++	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950);
++
++	/* set up to autoclear timer, lsc, and the vectors */
++	mask = IXGBE_EIMS_ENABLE_MASK;
++	mask &= ~IXGBE_EIMS_OTHER;
++	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask);
++}
++
++enum latency_range {
++	lowest_latency = 0,
++	low_latency = 1,
++	bulk_latency = 2,
++	latency_invalid = 255
++};
++
++/**
++ * ixgbe_update_itr - update the dynamic ITR value based on statistics
++ * @adapter: pointer to adapter
++ * @eitr: eitr setting (ints per sec) to give last timeslice
++ * @itr_setting: current throttle rate in ints/second
++ * @packets: the number of packets during this measurement interval
++ * @bytes: the number of bytes during this measurement interval
++ *
++ *      Stores a new ITR value based on packets and byte
++ *      counts during the last interrupt.  The advantage of per interrupt
++ *      computation is faster updates and more accurate ITR for the current
++ *      traffic pattern.  Constants in this function were computed
++ *      based on theoretical maximum wire speed and thresholds were set based
++ *      on testing data as well as attempting to minimize response time
++ *      while increasing bulk throughput.
++ *      this functionality is controlled by the InterruptThrottleRate module
++ *      parameter (see ixgbe_param.c)
++ **/
++static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
++			   u32 eitr, u8 itr_setting,
++			   int packets, int bytes)
++{
++	unsigned int retval = itr_setting;
++	u32 timepassed_us;
++	u64 bytes_perint;
++
++	if (packets == 0)
++		goto update_itr_done;
++
++
++	/* simple throttlerate management
++	 *    0-20MB/s lowest (100000 ints/s)
++	 *   20-100MB/s low   (20000 ints/s)
++	 *  100-1249MB/s bulk (8000 ints/s)
++	 */
++	/* what was last interrupt timeslice? */
++	timepassed_us = 1000000/eitr;
++	bytes_perint = bytes / timepassed_us; /* bytes/usec */
++
++	switch (itr_setting) {
++	case lowest_latency:
++		if (bytes_perint > adapter->eitr_low)
++			retval = low_latency;
++		break;
++	case low_latency:
++		if (bytes_perint > adapter->eitr_high)
++			retval = bulk_latency;
++		else if (bytes_perint <= adapter->eitr_low)
++			retval = lowest_latency;
++		break;
++	case bulk_latency:
++		if (bytes_perint <= adapter->eitr_high)
++			retval = low_latency;
++		break;
++	}
++
++update_itr_done:
++	return retval;
++}
++
++static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
++{
++	struct ixgbe_adapter *adapter = q_vector->adapter;
++	struct ixgbe_hw *hw = &adapter->hw;
++	u32 new_itr;
++	u8 current_itr, ret_itr;
++	int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) /
++			      sizeof(struct ixgbe_q_vector);
++	struct ixgbe_ring *rx_ring, *tx_ring;
++
++	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
++	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_eitr,
++					   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_eitr = ((q_vector->tx_eitr > ret_itr) ?
++				    q_vector->tx_eitr - 1 : ret_itr);
++		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
++				      r_idx + 1);
++	}
++
++	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
++	for (i = 0; i < q_vector->rxr_count; i++) {
++		rx_ring = &(adapter->rx_ring[r_idx]);
++		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
++					   q_vector->rx_eitr,
++					   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_eitr = ((q_vector->rx_eitr > ret_itr) ?
++				    q_vector->rx_eitr - 1 : ret_itr);
++		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
++				      r_idx + 1);
++	}
++
++	current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
++
++	switch (current_itr) {
++	/* counts and packets in update_itr are dependent on these numbers */
++	case lowest_latency:
++		new_itr = 100000;
++		break;
++	case low_latency:
++		new_itr = 20000; /* aka hwitr = ~200 */
++		break;
++	case bulk_latency:
++	default:
++		new_itr = 8000;
++		break;
++	}
++
++	if (new_itr != q_vector->eitr) {
++		u32 itr_reg;
++		/* do an exponential smoothing */
++		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
++		q_vector->eitr = new_itr;
++		itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
++		/* must write high and low 16 bits to reset counter */
++		DPRINTK(TX_ERR, DEBUG, "writing eitr(%d): %08X\n", v_idx,
++			itr_reg);
++		IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg | (itr_reg)<<16);
++	}
++
++	return;
+ }
+ 
+ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
+@@ -614,153 +895,302 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
+ 
+ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
+ {
+-	struct ixgbe_ring *txr = data;
+-	struct ixgbe_adapter *adapter = txr->adapter;
++	struct ixgbe_q_vector *q_vector = data;
++	struct ixgbe_adapter  *adapter = q_vector->adapter;
++	struct ixgbe_ring     *txr;
++	int i, r_idx;
+ 
+-	ixgbe_clean_tx_irq(adapter, txr);
++	if (!q_vector->txr_count)
++		return IRQ_HANDLED;
++
++	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
++	for (i = 0; i < q_vector->txr_count; i++) {
++		txr = &(adapter->tx_ring[r_idx]);
++#ifdef CONFIG_DCA
++		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
++			ixgbe_update_tx_dca(adapter, txr);
++#endif
++		txr->total_bytes = 0;
++		txr->total_packets = 0;
++		ixgbe_clean_tx_irq(adapter, txr);
++		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
++				      r_idx + 1);
++	}
+ 
+ 	return IRQ_HANDLED;
+ }
+ 
++/**
++ * ixgbe_msix_clean_rx - single unshared vector rx clean (all queues)
++ * @irq: unused
++ * @data: pointer to our q_vector struct for this interrupt vector
++ **/
+ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
+ {
+-	struct ixgbe_ring *rxr = data;
+-	struct ixgbe_adapter *adapter = rxr->adapter;
++	struct ixgbe_q_vector *q_vector = data;
++	struct ixgbe_adapter  *adapter = q_vector->adapter;
++	struct ixgbe_ring  *rxr;
++	int r_idx;
++
++	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
++	if (!q_vector->rxr_count)
++		return IRQ_HANDLED;
++
++	rxr = &(adapter->rx_ring[r_idx]);
++	/* disable interrupts on this vector only */
++	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->v_idx);
++	rxr->total_bytes = 0;
++	rxr->total_packets = 0;
++	netif_rx_schedule(adapter->netdev, &q_vector->napi);
++
++	return IRQ_HANDLED;
++}
++
++static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
++{
++	ixgbe_msix_clean_rx(irq, data);
++	ixgbe_msix_clean_tx(irq, data);
+ 
+-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->eims_value);
+-	netif_rx_schedule(adapter->netdev, &adapter->napi);
+ 	return IRQ_HANDLED;
+ }
+ 
++/**
++ * ixgbe_clean_rxonly - msix (aka one shot) rx clean routine
++ * @napi: napi struct with our devices info in it
++ * @budget: amount of work driver is allowed to do this pass, in packets
++ *
++ **/
+ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
+ {
+-	struct ixgbe_adapter *adapter = container_of(napi,
+-					struct ixgbe_adapter, napi);
+-	struct net_device *netdev = adapter->netdev;
++	struct ixgbe_q_vector *q_vector =
++			       container_of(napi, struct ixgbe_q_vector, napi);
++	struct ixgbe_adapter *adapter = q_vector->adapter;
++	struct ixgbe_ring *rxr;
+ 	int work_done = 0;
+-	struct ixgbe_ring *rxr = adapter->rx_ring;
++	long r_idx;
+ 
+-	/* Keep link state information with original netdev */
+-	if (!netif_carrier_ok(netdev))
+-		goto quit_polling;
++	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
++	rxr = &(adapter->rx_ring[r_idx]);
++#ifdef CONFIG_DCA
++	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
++		ixgbe_update_rx_dca(adapter, rxr);
++#endif
+ 
+ 	ixgbe_clean_rx_irq(adapter, rxr, &work_done, budget);
+ 
+-	/* If no Tx and not enough Rx work done, exit the polling mode */
+-	if ((work_done < budget) || !netif_running(netdev)) {
+-quit_polling:
+-		netif_rx_complete(netdev, napi);
++	/* If all Rx work done, exit the polling mode */
++	if (work_done < budget) {
++		netif_rx_complete(adapter->netdev, napi);
++		if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
++			ixgbe_set_itr_msix(q_vector);
+ 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
+-			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
+-					rxr->eims_value);
++			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rxr->v_idx);
+ 	}
+ 
+ 	return work_done;
+ }
+ 
++static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
++				     int r_idx)
++{
++	a->q_vector[v_idx].adapter = a;
++	set_bit(r_idx, a->q_vector[v_idx].rxr_idx);
++	a->q_vector[v_idx].rxr_count++;
++	a->rx_ring[r_idx].v_idx = 1 << v_idx;
++}
++
++static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
++				     int r_idx)
++{
++	a->q_vector[v_idx].adapter = a;
++	set_bit(r_idx, a->q_vector[v_idx].txr_idx);
++	a->q_vector[v_idx].txr_count++;
++	a->tx_ring[r_idx].v_idx = 1 << v_idx;
++}
++
+ /**
+- * ixgbe_setup_msix - Initialize MSI-X interrupts
++ * ixgbe_map_rings_to_vectors - Maps descriptor rings to vectors
++ * @adapter: board private structure to initialize
++ * @vectors: allotted vector count for descriptor rings
+  *
+- * ixgbe_setup_msix allocates MSI-X vectors and requests
+- * interrutps from the kernel.
++ * This function maps descriptor rings to the queue-specific vectors
++ * we were allotted through the MSI-X enabling code.  Ideally, we'd have
++ * one vector per ring/queue, but on a constrained vector budget, we
++ * group the rings as "efficiently" as possible.  You would add new
++ * mapping configurations in here.
+  **/
+-static int ixgbe_setup_msix(struct ixgbe_adapter *adapter)
+-{
+-	struct net_device *netdev = adapter->netdev;
+-	int i, int_vector = 0, err = 0;
+-	int max_msix_count;
++static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter,
++				      int vectors)
++{
++	int v_start = 0;
++	int rxr_idx = 0, txr_idx = 0;
++	int rxr_remaining = adapter->num_rx_queues;
++	int txr_remaining = adapter->num_tx_queues;
++	int i, j;
++	int rqpv, tqpv;
++	int err = 0;
++
++	/* No mapping required if MSI-X is disabled. */
++	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
++		goto out;
+ 
+-	/* +1 for the LSC interrupt */
+-	max_msix_count = adapter->num_rx_queues + adapter->num_tx_queues + 1;
+-	adapter->msix_entries = kcalloc(max_msix_count,
+-					sizeof(struct msix_entry), GFP_KERNEL);
+-	if (!adapter->msix_entries)
+-		return -ENOMEM;
++	/*
++	 * The ideal configuration...
++	 * We have enough vectors to map one per queue.
++	 */
++	if (vectors == adapter->num_rx_queues + adapter->num_tx_queues) {
++		for (; rxr_idx < rxr_remaining; v_start++, rxr_idx++)
++			map_vector_to_rxq(adapter, v_start, rxr_idx);
+ 
+-	for (i = 0; i < max_msix_count; i++)
+-		adapter->msix_entries[i].entry = i;
++		for (; txr_idx < txr_remaining; v_start++, txr_idx++)
++			map_vector_to_txq(adapter, v_start, txr_idx);
+ 
+-	err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
+-			      max_msix_count);
+-	if (err)
+ 		goto out;
++	}
+ 
+-	for (i = 0; i < adapter->num_tx_queues; i++) {
+-		sprintf(adapter->tx_ring[i].name, "%s-tx%d", netdev->name, i);
+-		err = request_irq(adapter->msix_entries[int_vector].vector,
+-				  &ixgbe_msix_clean_tx,
+-				  0,
+-				  adapter->tx_ring[i].name,
+-				  &(adapter->tx_ring[i]));
+-		if (err) {
+-			DPRINTK(PROBE, ERR,
+-				"request_irq failed for MSIX interrupt "
+-				"Error: %d\n", err);
+-			goto release_irqs;
++	/*
++	 * If we don't have enough vectors for a 1-to-1
++	 * mapping, we'll have to group them so there are
++	 * multiple queues per vector.
++	 */
++	/* Re-adjusting *qpv takes care of the remainder. */
++	for (i = v_start; i < vectors; i++) {
++		rqpv = DIV_ROUND_UP(rxr_remaining, vectors - i);
++		for (j = 0; j < rqpv; j++) {
++			map_vector_to_rxq(adapter, i, rxr_idx);
++			rxr_idx++;
++			rxr_remaining--;
++		}
++	}
++	for (i = v_start; i < vectors; i++) {
++		tqpv = DIV_ROUND_UP(txr_remaining, vectors - i);
++		for (j = 0; j < tqpv; j++) {
++			map_vector_to_txq(adapter, i, txr_idx);
++			txr_idx++;
++			txr_remaining--;
+ 		}
+-		adapter->tx_ring[i].eims_value =
+-		    (1 << IXGBE_MSIX_VECTOR(int_vector));
+-		adapter->tx_ring[i].itr_register = IXGBE_EITR(int_vector);
+-		int_vector++;
+ 	}
+ 
+-	for (i = 0; i < adapter->num_rx_queues; i++) {
+-		if (strlen(netdev->name) < (IFNAMSIZ - 5))
+-			sprintf(adapter->rx_ring[i].name,
+-				"%s-rx%d", netdev->name, i);
+-		else
+-			memcpy(adapter->rx_ring[i].name,
+-			       netdev->name, IFNAMSIZ);
+-		err = request_irq(adapter->msix_entries[int_vector].vector,
+-				  &ixgbe_msix_clean_rx, 0,
+-				  adapter->rx_ring[i].name,
+-				  &(adapter->rx_ring[i]));
++out:
++	return err;
++}
++
++/**
++ * ixgbe_request_msix_irqs - Initialize MSI-X interrupts
++ * @adapter: board private structure
++ *
++ * ixgbe_request_msix_irqs allocates MSI-X vectors and requests
++ * interrupts from the kernel.
++ **/
++static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
++{
++	struct net_device *netdev = adapter->netdev;
++	irqreturn_t (*handler)(int, void *);
++	int i, vector, q_vectors, err;
++
++	/* Decrement for Other and TCP Timer vectors */
++	q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++
++	/* Map the Tx/Rx rings to the vectors we were allotted. */
++	err = ixgbe_map_rings_to_vectors(adapter, q_vectors);
++	if (err)
++		goto out;
++
++#define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \
++			 (!(_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]);
++		sprintf(adapter->name[vector], "%s:v%d-%s",
++			netdev->name, vector,
++			(handler == &ixgbe_msix_clean_rx) ? "Rx" :
++			 ((handler == &ixgbe_msix_clean_tx) ? "Tx" : "TxRx"));
++		err = request_irq(adapter->msix_entries[vector].vector,
++				  handler, 0, adapter->name[vector],
++				  &(adapter->q_vector[vector]));
+ 		if (err) {
+ 			DPRINTK(PROBE, ERR,
+ 				"request_irq failed for MSIX interrupt "
+ 				"Error: %d\n", err);
+-			goto release_irqs;
++			goto free_queue_irqs;
+ 		}
+-
+-		adapter->rx_ring[i].eims_value =
+-		    (1 << IXGBE_MSIX_VECTOR(int_vector));
+-		adapter->rx_ring[i].itr_register = IXGBE_EITR(int_vector);
+-		int_vector++;
+ 	}
+ 
+-	sprintf(adapter->lsc_name, "%s-lsc", netdev->name);
+-	err = request_irq(adapter->msix_entries[int_vector].vector,
+-			  &ixgbe_msix_lsc, 0, adapter->lsc_name, netdev);
++	sprintf(adapter->name[vector], "%s:lsc", netdev->name);
++	err = request_irq(adapter->msix_entries[vector].vector,
++			  &ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
+ 	if (err) {
+ 		DPRINTK(PROBE, ERR,
+ 			"request_irq for msix_lsc failed: %d\n", err);
+-		goto release_irqs;
++		goto free_queue_irqs;
+ 	}
+ 
+-	/* FIXME: implement netif_napi_remove() instead */
+-	adapter->napi.poll = ixgbe_clean_rxonly;
+-	adapter->flags |= IXGBE_FLAG_MSIX_ENABLED;
+ 	return 0;
+ 
+-release_irqs:
+-	int_vector--;
+-	for (; int_vector >= adapter->num_tx_queues; int_vector--)
+-		free_irq(adapter->msix_entries[int_vector].vector,
+-			 &(adapter->rx_ring[int_vector -
+-					    adapter->num_tx_queues]));
+-
+-	for (; int_vector >= 0; int_vector--)
+-		free_irq(adapter->msix_entries[int_vector].vector,
+-			 &(adapter->tx_ring[int_vector]));
+-out:
++free_queue_irqs:
++	for (i = vector - 1; i >= 0; i--)
++		free_irq(adapter->msix_entries[--vector].vector,
++			 &(adapter->q_vector[i]));
++	adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
++	pci_disable_msix(adapter->pdev);
+ 	kfree(adapter->msix_entries);
+ 	adapter->msix_entries = NULL;
+-	adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
++out:
+ 	return err;
+ }
+ 
++static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
++{
++	struct ixgbe_hw *hw = &adapter->hw;
++	struct ixgbe_q_vector *q_vector = adapter->q_vector;
++	u8 current_itr;
++	u32 new_itr = q_vector->eitr;
++	struct ixgbe_ring *rx_ring = &adapter->rx_ring[0];
++	struct ixgbe_ring *tx_ring = &adapter->tx_ring[0];
++
++	q_vector->tx_eitr = ixgbe_update_itr(adapter, new_itr,
++					     q_vector->tx_eitr,
++					     tx_ring->total_packets,
++					     tx_ring->total_bytes);
++	q_vector->rx_eitr = ixgbe_update_itr(adapter, new_itr,
++					     q_vector->rx_eitr,
++					     rx_ring->total_packets,
++					     rx_ring->total_bytes);
++
++	current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
++
++	switch (current_itr) {
++	/* counts and packets in update_itr are dependent on these numbers */
++	case lowest_latency:
++		new_itr = 100000;
++		break;
++	case low_latency:
++		new_itr = 20000; /* aka hwitr = ~200 */
++		break;
++	case bulk_latency:
++		new_itr = 8000;
++		break;
++	default:
++		break;
++	}
++
++	if (new_itr != q_vector->eitr) {
++		u32 itr_reg;
++		/* do an exponential smoothing */
++		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
++		q_vector->eitr = new_itr;
++		itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
++		/* must write high and low 16 bits to reset counter */
++		IXGBE_WRITE_REG(hw, IXGBE_EITR(0), itr_reg | (itr_reg)<<16);
++	}
++
++	return;
++}
++
++static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter);
++
+ /**
+- * ixgbe_intr - Interrupt Handler
++ * ixgbe_intr - legacy mode Interrupt Handler
+  * @irq: interrupt number
+  * @data: pointer to a network interface device structure
+  * @pt_regs: CPU registers structure
+@@ -772,8 +1202,10 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
+ 	struct ixgbe_hw *hw = &adapter->hw;
+ 	u32 eicr;
+ 
+-	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
+ 
++	/* for NAPI, using EIAM to auto-mask tx/rx interrupt bits on read
++	 * therefore no explict interrupt disable is necessary */
++	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
+ 	if (!eicr)
+ 		return IRQ_NONE;	/* Not our interrupt */
+ 
+@@ -782,16 +1214,33 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
+ 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ 			mod_timer(&adapter->watchdog_timer, jiffies);
+ 	}
+-	if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+-		/* Disable interrupts and register for poll. The flush of the
+-		 * posted write is intentionally left out. */
+-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
+-		__netif_rx_schedule(netdev, &adapter->napi);
++
++
++	if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) {
++		adapter->tx_ring[0].total_packets = 0;
++		adapter->tx_ring[0].total_bytes = 0;
++		adapter->rx_ring[0].total_packets = 0;
++		adapter->rx_ring[0].total_bytes = 0;
++		/* would disable interrupts here but EIAM disabled it */
++		__netif_rx_schedule(netdev, &adapter->q_vector[0].napi);
+ 	}
+ 
+ 	return IRQ_HANDLED;
+ }
+ 
++static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter)
++{
++	int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++
++	for (i = 0; i < q_vectors; i++) {
++		struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
++		bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES);
++		bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES);
++		q_vector->rxr_count = 0;
++		q_vector->txr_count = 0;
++	}
++}
++
+ /**
+  * ixgbe_request_irq - initialize interrupts
+  * @adapter: board private structure
+@@ -799,40 +1248,24 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
+  * Attempts to configure interrupts using the best available
+  * capabilities of the hardware and kernel.
+  **/
+-static int ixgbe_request_irq(struct ixgbe_adapter *adapter, u32 *num_rx_queues)
++static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+-	int flags, err;
+-	irq_handler_t handler = ixgbe_intr;
+-
+-	flags = IRQF_SHARED;
+-
+-	err = ixgbe_setup_msix(adapter);
+-	if (!err)
+-		goto request_done;
+-
+-	/*
+-	 * if we can't do MSI-X, fall through and try MSI
+-	 * No need to reallocate memory since we're decreasing the number of
+-	 * queues. We just won't use the other ones, also it is freed correctly
+-	 * on ixgbe_remove.
+-	 */
+-	*num_rx_queues = 1;
++	int err;
+ 
+-	/* do MSI */
+-	err = pci_enable_msi(adapter->pdev);
+-	if (!err) {
+-		adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
+-		flags &= ~IRQF_SHARED;
+-		handler = &ixgbe_intr;
++	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++		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);
++	} else {
++		err = request_irq(adapter->pdev->irq, &ixgbe_intr, IRQF_SHARED,
++				  netdev->name, netdev);
+ 	}
+ 
+-	err = request_irq(adapter->pdev->irq, handler, flags,
+-			  netdev->name, netdev);
+ 	if (err)
+ 		DPRINTK(PROBE, ERR, "request_irq failed, Error %d\n", err);
+ 
+-request_done:
+ 	return err;
+ }
+ 
+@@ -841,28 +1274,22 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
+ 	struct net_device *netdev = adapter->netdev;
+ 
+ 	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+-		int i;
++		int i, q_vectors;
+ 
+-		for (i = 0; i < adapter->num_tx_queues; i++)
+-			free_irq(adapter->msix_entries[i].vector,
+-				 &(adapter->tx_ring[i]));
+-		for (i = 0; i < adapter->num_rx_queues; i++)
+-			free_irq(adapter->msix_entries[i +
+-						adapter->num_tx_queues].vector,
+-				&(adapter->rx_ring[i]));
+-		i = adapter->num_rx_queues + adapter->num_tx_queues;
++		q_vectors = adapter->num_msix_vectors;
++
++		i = q_vectors - 1;
+ 		free_irq(adapter->msix_entries[i].vector, netdev);
+-		pci_disable_msix(adapter->pdev);
+-		kfree(adapter->msix_entries);
+-		adapter->msix_entries = NULL;
+-		adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
+-		return;
+-	}
+ 
+-	free_irq(adapter->pdev->irq, netdev);
+-	if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
+-		pci_disable_msi(adapter->pdev);
+-		adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;
++		i--;
++		for (; i >= 0; i--) {
++			free_irq(adapter->msix_entries[i].vector,
++				 &(adapter->q_vector[i]));
++		}
++
++		ixgbe_reset_q_vectors(adapter);
++	} else {
++		free_irq(adapter->pdev->irq, netdev);
+ 	}
+ }
+ 
+@@ -874,7 +1301,13 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
+ {
+ 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
+ 	IXGBE_WRITE_FLUSH(&adapter->hw);
+-	synchronize_irq(adapter->pdev->irq);
++	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++		int i;
++		for (i = 0; i < adapter->num_msix_vectors; i++)
++			synchronize_irq(adapter->msix_entries[i].vector);
++	} else {
++		synchronize_irq(adapter->pdev->irq);
++	}
+ }
+ 
+ /**
+@@ -883,12 +1316,9 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
+  **/
+ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
+ {
+-	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC,
+-				(IXGBE_EIMS_ENABLE_MASK &
+-				 ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC)));
+-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
+-			IXGBE_EIMS_ENABLE_MASK);
++	u32 mask;
++	mask = IXGBE_EIMS_ENABLE_MASK;
++	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
+ 	IXGBE_WRITE_FLUSH(&adapter->hw);
+ }
+ 
+@@ -898,20 +1328,18 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
+  **/
+ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
+ {
+-	int i;
+ 	struct ixgbe_hw *hw = &adapter->hw;
+ 
+-	if (adapter->rx_eitr)
+-		IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
+-				EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr));
+-
+-	/* for re-triggering the interrupt in non-NAPI mode */
+-	adapter->rx_ring[0].eims_value = (1 << IXGBE_MSIX_VECTOR(0));
+-	adapter->tx_ring[0].eims_value = (1 << IXGBE_MSIX_VECTOR(0));
++	IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
++			EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr));
+ 
+ 	ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(0), 0);
+-	for (i = 0; i < adapter->num_tx_queues; i++)
+-		ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(i), i);
++	ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(0), 0);
++
++	map_vector_to_rxq(adapter, 0, 0);
++	map_vector_to_txq(adapter, 0, 0);
++
++	DPRINTK(HW, INFO, "Legacy interrupt IVAR setup done\n");
+ }
+ 
+ /**
+@@ -924,23 +1352,29 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
+ {
+ 	u64 tdba;
+ 	struct ixgbe_hw *hw = &adapter->hw;
+-	u32 i, tdlen;
++	u32 i, j, tdlen, txctrl;
+ 
+ 	/* Setup the HW Tx Head and Tail descriptor pointers */
+ 	for (i = 0; i < adapter->num_tx_queues; i++) {
++		j = adapter->tx_ring[i].reg_idx;
+ 		tdba = adapter->tx_ring[i].dma;
+ 		tdlen = adapter->tx_ring[i].count *
+-		    sizeof(union ixgbe_adv_tx_desc);
+-		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(i), (tdba & DMA_32BIT_MASK));
+-		IXGBE_WRITE_REG(hw, IXGBE_TDBAH(i), (tdba >> 32));
+-		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(i), tdlen);
+-		IXGBE_WRITE_REG(hw, IXGBE_TDH(i), 0);
+-		IXGBE_WRITE_REG(hw, IXGBE_TDT(i), 0);
+-		adapter->tx_ring[i].head = IXGBE_TDH(i);
+-		adapter->tx_ring[i].tail = IXGBE_TDT(i);
++			sizeof(union ixgbe_adv_tx_desc);
++		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
++				(tdba & DMA_32BIT_MASK));
++		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.
++		 */
++		txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
++		txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
++		IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl);
+ 	}
+-
+-	IXGBE_WRITE_REG(hw, IXGBE_TIPG, IXGBE_TIPG_FIBER_DEFAULT);
+ }
+ 
+ #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
+@@ -959,13 +1393,12 @@ static void ixgbe_configure_rx(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;
+ 	u32 random[10];
+-	u32 reta, mrqc;
+-	int i;
+ 	u32 fctrl, hlreg0;
+-	u32 srrctl;
+ 	u32 pages;
++	u32 reta = 0, mrqc, srrctl;
+ 
+ 	/* Decide whether to use packet split mode or not */
+ 	if (netdev->mtu > ETH_DATA_LEN)
+@@ -985,6 +1418,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+ 
+ 	fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+ 	fctrl |= IXGBE_FCTRL_BAM;
++	fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */
+ 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
+ 
+ 	hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+@@ -1036,37 +1470,23 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+ 		adapter->rx_ring[i].tail = IXGBE_RDT(i);
+ 	}
+ 
+-	if (adapter->num_rx_queues > 1) {
+-		/* Random 40bytes used as random key in RSS hash function */
+-		get_random_bytes(&random[0], 40);
+-
+-		switch (adapter->num_rx_queues) {
+-		case 8:
+-		case 4:
+-			/* Bits [3:0] in each byte refers the Rx queue no */
+-			reta = 0x00010203;
+-			break;
+-		case 2:
+-			reta = 0x00010001;
+-			break;
+-		default:
+-			reta = 0x00000000;
+-			break;
+-		}
+-
++	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
+ 		/* Fill out redirection table */
+-		for (i = 0; i < 32; i++) {
+-			IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RETA(0), i, reta);
+-			if (adapter->num_rx_queues > 4) {
+-				i++;
+-				IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RETA(0), i,
+-						      0x04050607);
+-			}
++		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 */
++		/* XXX use a random constant here to glue certain flows */
++		get_random_bytes(&random[0], 40);
+ 		for (i = 0; i < 10; i++)
+-			IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RSSRK(0), i, random[i]);
++			IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), random[i]);
+ 
+ 		mrqc = IXGBE_MRQC_RSSEN
+ 		    /* Perform hash on these packet types */
+@@ -1080,26 +1500,23 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+ 		    | IXGBE_MRQC_RSS_FIELD_IPV6_UDP
+ 		    | IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
+ 		IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
++	}
+ 
+-		/* Multiqueue and packet checksumming are mutually exclusive. */
+-		rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
++	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;
+-		IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+-	} else {
+-		/* Enable Receive Checksum Offload for TCP and UDP */
+-		rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
+-		if (adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED) {
+-			/* Enable IPv4 payload checksum for UDP fragments
+-			 * Must be used in conjunction with packet-split. */
+-			rxcsum |= IXGBE_RXCSUM_IPPCSE;
+-		} else {
+-			/* don't need to clear IPPCSE as it defaults to 0 */
+-		}
+-		IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+ 	}
+-	/* Enable Receives */
+-	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
+-	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
++	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);
+ }
+ 
+ static void ixgbe_vlan_rx_register(struct net_device *netdev,
+@@ -1219,6 +1636,42 @@ static void ixgbe_set_multi(struct net_device *netdev)
+ 
+ }
+ 
++static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
++{
++	int q_idx;
++	struct ixgbe_q_vector *q_vector;
++	int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++
++	/* legacy and MSI only use one vector */
++	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
++		q_vectors = 1;
++
++	for (q_idx = 0; q_idx < q_vectors; q_idx++) {
++		q_vector = &adapter->q_vector[q_idx];
++		if (!q_vector->rxr_count)
++			continue;
++		napi_enable(&q_vector->napi);
++	}
++}
++
++static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
++{
++	int q_idx;
++	struct ixgbe_q_vector *q_vector;
++	int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++
++	/* legacy and MSI only use one vector */
++	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
++		q_vectors = 1;
++
++	for (q_idx = 0; q_idx < q_vectors; q_idx++) {
++		q_vector = &adapter->q_vector[q_idx];
++		if (!q_vector->rxr_count)
++			continue;
++		napi_disable(&q_vector->napi);
++	}
++}
++
+ static void ixgbe_configure(struct ixgbe_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+@@ -1238,30 +1691,35 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
+ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+-	int i;
+-	u32 gpie = 0;
+ 	struct ixgbe_hw *hw = &adapter->hw;
+-	u32 txdctl, rxdctl, mhadd;
++	int i, j = 0;
+ 	int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
++	u32 txdctl, rxdctl, mhadd;
++	u32 gpie;
+ 
+ 	ixgbe_get_hw_control(adapter);
+ 
+-	if (adapter->flags & (IXGBE_FLAG_MSIX_ENABLED |
+-			      IXGBE_FLAG_MSI_ENABLED)) {
++	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 = (IXGBE_GPIE_EIAME |
+-				IXGBE_GPIE_PBA_SUPPORT);
++			gpie = 0;
+ 		}
+-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_GPIE, gpie);
+-		gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
++		/* XXX: to interrupt immediately for EICS writes, enable this */
++		/* gpie |= IXGBE_GPIE_EIMEN; */
++		IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+ 	}
+ 
+-	mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
++	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
++		/* legacy interrupts, use EIAM to auto-mask when reading EICR,
++		 * specifically only auto mask tx and rx interrupts */
++		IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
++	}
+ 
++	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;
+@@ -1270,15 +1728,21 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
+ 	}
+ 
+ 	for (i = 0; i < adapter->num_tx_queues; i++) {
+-		txdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(i));
++		j = adapter->tx_ring[i].reg_idx;
++		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
+ 		txdctl |= IXGBE_TXDCTL_ENABLE;
+-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(i), txdctl);
++		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
+ 	}
+ 
+ 	for (i = 0; i < adapter->num_rx_queues; i++) {
+-		rxdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(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(&adapter->hw, IXGBE_RXDCTL(i), rxdctl);
++		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), rxdctl);
+ 	}
+ 	/* enable all receives */
+ 	rxdctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+@@ -1291,7 +1755,11 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
+ 		ixgbe_configure_msi_and_legacy(adapter);
+ 
+ 	clear_bit(__IXGBE_DOWN, &adapter->state);
+-	napi_enable(&adapter->napi);
++	ixgbe_napi_enable_all(adapter);
++
++	/* clear any pending interrupts, may auto mask */
++	IXGBE_READ_REG(hw, IXGBE_EICR);
++
+ 	ixgbe_irq_enable(adapter);
+ 
+ 	/* bring the link up in the watchdog, this could race with our first
+@@ -1333,7 +1801,7 @@ static int ixgbe_resume(struct pci_dev *pdev)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+-	u32 err, num_rx_queues = adapter->num_rx_queues;
++	u32 err;
+ 
+ 	pci_set_power_state(pdev, PCI_D0);
+ 	pci_restore_state(pdev);
+@@ -1349,7 +1817,7 @@ static int ixgbe_resume(struct pci_dev *pdev)
+ 	pci_enable_wake(pdev, PCI_D3cold, 0);
+ 
+ 	if (netif_running(netdev)) {
+-		err = ixgbe_request_irq(adapter, &num_rx_queues);
++		err = ixgbe_request_irq(adapter);
+ 		if (err)
+ 			return err;
+ 	}
+@@ -1449,27 +1917,27 @@ static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter,
+ }
+ 
+ /**
+- * ixgbe_clean_all_tx_rings - Free Tx Buffers for all queues
++ * ixgbe_clean_all_rx_rings - Free Rx Buffers for all queues
+  * @adapter: board private structure
+  **/
+-static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
++static void ixgbe_clean_all_rx_rings(struct ixgbe_adapter *adapter)
+ {
+ 	int i;
+ 
+-	for (i = 0; i < adapter->num_tx_queues; i++)
+-		ixgbe_clean_tx_ring(adapter, &adapter->tx_ring[i]);
++	for (i = 0; i < adapter->num_rx_queues; i++)
++		ixgbe_clean_rx_ring(adapter, &adapter->rx_ring[i]);
+ }
+ 
+ /**
+- * ixgbe_clean_all_rx_rings - Free Rx Buffers for all queues
++ * ixgbe_clean_all_tx_rings - Free Tx Buffers for all queues
+  * @adapter: board private structure
+  **/
+-static void ixgbe_clean_all_rx_rings(struct ixgbe_adapter *adapter)
++static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
+ {
+ 	int i;
+ 
+-	for (i = 0; i < adapter->num_rx_queues; i++)
+-		ixgbe_clean_rx_ring(adapter, &adapter->rx_ring[i]);
++	for (i = 0; i < adapter->num_tx_queues; i++)
++		ixgbe_clean_tx_ring(adapter, &adapter->tx_ring[i]);
+ }
+ 
+ void ixgbe_down(struct ixgbe_adapter *adapter)
+@@ -1493,10 +1961,9 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
+ 	IXGBE_WRITE_FLUSH(&adapter->hw);
+ 	msleep(10);
+ 
+-	napi_disable(&adapter->napi);
+-
+ 	ixgbe_irq_disable(adapter);
+ 
++	ixgbe_napi_disable_all(adapter);
+ 	del_timer_sync(&adapter->watchdog_timer);
+ 
+ 	netif_carrier_off(netdev);
+@@ -1547,27 +2014,37 @@ static void ixgbe_shutdown(struct pci_dev *pdev)
+ }
+ 
+ /**
+- * ixgbe_clean - NAPI Rx polling callback
+- * @adapter: board private structure
++ * ixgbe_poll - NAPI Rx polling callback
++ * @napi: structure for representing this polling device
++ * @budget: how many packets driver is allowed to clean
++ *
++ * This function is used for legacy and MSI, NAPI mode
+  **/
+-static int ixgbe_clean(struct napi_struct *napi, int budget)
++static int ixgbe_poll(struct napi_struct *napi, int budget)
+ {
+-	struct ixgbe_adapter *adapter = container_of(napi,
+-					struct ixgbe_adapter, napi);
+-	struct net_device *netdev = adapter->netdev;
++	struct ixgbe_q_vector *q_vector = container_of(napi,
++					  struct ixgbe_q_vector, napi);
++	struct ixgbe_adapter *adapter = q_vector->adapter;
+ 	int tx_cleaned = 0, work_done = 0;
+ 
+-	/* In non-MSIX case, there is no multi-Tx/Rx queue */
++#ifdef CONFIG_DCA
++	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
++		ixgbe_update_tx_dca(adapter, adapter->tx_ring);
++		ixgbe_update_rx_dca(adapter, adapter->rx_ring);
++	}
++#endif
++
+ 	tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring);
+-	ixgbe_clean_rx_irq(adapter, &adapter->rx_ring[0], &work_done,
+-			   budget);
++	ixgbe_clean_rx_irq(adapter, adapter->rx_ring, &work_done, budget);
+ 
+ 	if (tx_cleaned)
+ 		work_done = budget;
+ 
+ 	/* If budget not fully consumed, exit the polling mode */
+ 	if (work_done < budget) {
+-		netif_rx_complete(netdev, napi);
++		netif_rx_complete(adapter->netdev, napi);
++		if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
++			ixgbe_set_itr(adapter);
+ 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ 			ixgbe_irq_enable(adapter);
+ 	}
+@@ -1597,6 +2074,136 @@ static void ixgbe_reset_task(struct work_struct *work)
+ 	ixgbe_reinit_locked(adapter);
+ }
+ 
++static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
++				       int vectors)
++{
++	int err, vector_threshold;
++
++	/* We'll want at least 3 (vector_threshold):
++	 * 1) TxQ[0] Cleanup
++	 * 2) RxQ[0] Cleanup
++	 * 3) Other (Link Status Change, etc.)
++	 * 4) TCP Timer (optional)
++	 */
++	vector_threshold = MIN_MSIX_COUNT;
++
++	/* The more we get, the more we will assign to Tx/Rx Cleanup
++	 * for the separate queues...where Rx Cleanup >= Tx Cleanup.
++	 * Right now, we simply care about how many we'll get; we'll
++	 * set them up later while requesting irq's.
++	 */
++	while (vectors >= vector_threshold) {
++		err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
++				      vectors);
++		if (!err) /* Success in acquiring all requested vectors. */
++			break;
++		else if (err < 0)
++			vectors = 0; /* Nasty failure, quit now */
++		else /* err == number of vectors we should try again with */
++			vectors = err;
++	}
++
++	if (vectors < vector_threshold) {
++		/* Can't allocate enough MSI-X interrupts?  Oh well.
++		 * This just means we'll go with either a single MSI
++		 * vector or fall back to legacy interrupts.
++		 */
++		DPRINTK(HW, DEBUG, "Unable to allocate MSI-X interrupts\n");
++		adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
++		kfree(adapter->msix_entries);
++		adapter->msix_entries = NULL;
++		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
++		adapter->num_tx_queues = 1;
++		adapter->num_rx_queues = 1;
++	} else {
++		adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */
++		adapter->num_msix_vectors = vectors;
++	}
++}
++
++static void __devinit ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
++{
++	int nrq, ntq;
++	int feature_mask = 0, rss_i, rss_m;
++
++	/* Number of supported queues */
++	switch (adapter->hw.mac.type) {
++	case ixgbe_mac_82598EB:
++		rss_i = adapter->ring_feature[RING_F_RSS].indices;
++		rss_m = 0;
++		feature_mask |= IXGBE_FLAG_RSS_ENABLED;
++
++		switch (adapter->flags & feature_mask) {
++		case (IXGBE_FLAG_RSS_ENABLED):
++			rss_m = 0xF;
++			nrq = rss_i;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++			ntq = rss_i;
++#else
++			ntq = 1;
++#endif
++			break;
++		case 0:
++		default:
++			rss_i = 0;
++			rss_m = 0;
++			nrq = 1;
++			ntq = 1;
++			break;
++		}
++
++		adapter->ring_feature[RING_F_RSS].indices = rss_i;
++		adapter->ring_feature[RING_F_RSS].mask = rss_m;
++		break;
++	default:
++		nrq = 1;
++		ntq = 1;
++		break;
++	}
++
++	adapter->num_rx_queues = nrq;
++	adapter->num_tx_queues = ntq;
++}
++
++/**
++ * ixgbe_cache_ring_register - Descriptor ring to register mapping
++ * @adapter: board private structure to initialize
++ *
++ * Once we know the feature-set enabled for the device, we'll cache
++ * the register offset the descriptor ring is assigned to.
++ **/
++static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
++{
++	/* TODO: Remove all uses of the indices in the cases where multiple
++	 *       features are OR'd together, if the feature set makes sense.
++	 */
++	int feature_mask = 0, rss_i;
++	int i, txr_idx, rxr_idx;
++
++	/* Number of supported queues */
++	switch (adapter->hw.mac.type) {
++	case ixgbe_mac_82598EB:
++		rss_i = adapter->ring_feature[RING_F_RSS].indices;
++		txr_idx = 0;
++		rxr_idx = 0;
++		feature_mask |= IXGBE_FLAG_RSS_ENABLED;
++		switch (adapter->flags & feature_mask) {
++		case (IXGBE_FLAG_RSS_ENABLED):
++			for (i = 0; i < adapter->num_rx_queues; i++)
++				adapter->rx_ring[i].reg_idx = i;
++			for (i = 0; i < adapter->num_tx_queues; i++)
++				adapter->tx_ring[i].reg_idx = i;
++			break;
++		case 0:
++		default:
++			break;
++		}
++		break;
++	default:
++		break;
++	}
++}
++
+ /**
+  * ixgbe_alloc_queues - Allocate memory for all rings
+  * @adapter: board private structure to initialize
+@@ -1612,25 +2219,167 @@ static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
+ 	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
+ 				   sizeof(struct ixgbe_ring), GFP_KERNEL);
+ 	if (!adapter->tx_ring)
+-		return -ENOMEM;
+-
+-	for (i = 0; i < adapter->num_tx_queues; i++)
+-		adapter->tx_ring[i].count = IXGBE_DEFAULT_TXD;
++		goto err_tx_ring_allocation;
+ 
+ 	adapter->rx_ring = kcalloc(adapter->num_rx_queues,
+ 				   sizeof(struct ixgbe_ring), GFP_KERNEL);
+-	if (!adapter->rx_ring) {
+-		kfree(adapter->tx_ring);
+-		return -ENOMEM;
+-	}
++	if (!adapter->rx_ring)
++		goto err_rx_ring_allocation;
+ 
++	for (i = 0; i < adapter->num_tx_queues; i++) {
++		adapter->tx_ring[i].count = IXGBE_DEFAULT_TXD;
++		adapter->tx_ring[i].queue_index = i;
++	}
+ 	for (i = 0; i < adapter->num_rx_queues; i++) {
+-		adapter->rx_ring[i].adapter = adapter;
+-		adapter->rx_ring[i].itr_register = IXGBE_EITR(i);
+ 		adapter->rx_ring[i].count = IXGBE_DEFAULT_RXD;
++		adapter->rx_ring[i].queue_index = i;
++	}
++
++	ixgbe_cache_ring_register(adapter);
++
++	return 0;
++
++err_rx_ring_allocation:
++	kfree(adapter->tx_ring);
++err_tx_ring_allocation:
++	return -ENOMEM;
++}
++
++/**
++ * ixgbe_set_interrupt_capability - set MSI-X or MSI if supported
++ * @adapter: board private structure to initialize
++ *
++ * Attempt to configure the interrupts using the best available
++ * capabilities of the hardware and the kernel.
++ **/
++static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
++						    *adapter)
++{
++	int err = 0;
++	int vector, v_budget;
++
++	/*
++	 * It's easy to be greedy for MSI-X vectors, but it really
++	 * doesn't do us much good if we have a lot more vectors
++	 * than CPU's.  So let's be conservative and only ask for
++	 * (roughly) twice the number of vectors as there are CPU's.
++	 */
++	v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues,
++		       (int)(num_online_cpus() * 2)) + NON_Q_VECTORS;
++
++	/*
++	 * At the same time, hardware can only support a maximum of
++	 * MAX_MSIX_COUNT vectors.  With features such as RSS and VMDq,
++	 * we can easily reach upwards of 64 Rx descriptor queues and
++	 * 32 Tx queues.  Thus, we cap it off in those rare cases where
++	 * the cpu count also exceeds our vector limit.
++	 */
++	v_budget = min(v_budget, MAX_MSIX_COUNT);
++
++	/* 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);
++	if (!adapter->msix_entries) {
++		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
++		ixgbe_set_num_queues(adapter);
++		kfree(adapter->tx_ring);
++		kfree(adapter->rx_ring);
++		err = ixgbe_alloc_queues(adapter);
++		if (err) {
++			DPRINTK(PROBE, ERR, "Unable to allocate memory "
++					    "for queues\n");
++			goto out;
++		}
++
++		goto try_msi;
++	}
++
++	for (vector = 0; vector < v_budget; vector++)
++		adapter->msix_entries[vector].entry = vector;
++
++	ixgbe_acquire_msix_vectors(adapter, v_budget);
++
++	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
++		goto out;
++
++try_msi:
++	err = pci_enable_msi(adapter->pdev);
++	if (!err) {
++		adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
++	} else {
++		DPRINTK(HW, DEBUG, "Unable to allocate MSI interrupt, "
++				   "falling back to legacy.  Error: %d\n", err);
++		/* reset err */
++		err = 0;
++	}
++
++out:
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	/* Notify the stack of the (possibly) reduced Tx Queue count. */
++	adapter->netdev->egress_subqueue_count = adapter->num_tx_queues;
++#endif
++
++	return err;
++}
++
++static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
++{
++	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++		adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
++		pci_disable_msix(adapter->pdev);
++		kfree(adapter->msix_entries);
++		adapter->msix_entries = NULL;
++	} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
++		adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;
++		pci_disable_msi(adapter->pdev);
+ 	}
++	return;
++}
++
++/**
++ * ixgbe_init_interrupt_scheme - Determine proper interrupt scheme
++ * @adapter: board private structure to initialize
++ *
++ * We determine which interrupt scheme to use based on...
++ * - Kernel support (MSI, MSI-X)
++ *   - which can be user-defined (via MODULE_PARAM)
++ * - Hardware queue count (num_*_queues)
++ *   - defined by miscellaneous hardware support/features (RSS, etc.)
++ **/
++static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
++{
++	int err;
++
++	/* Number of supported queues */
++	ixgbe_set_num_queues(adapter);
++
++	err = ixgbe_alloc_queues(adapter);
++	if (err) {
++		DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
++		goto err_alloc_queues;
++	}
++
++	err = ixgbe_set_interrupt_capability(adapter);
++	if (err) {
++		DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n");
++		goto err_set_interrupt;
++	}
++
++	DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, "
++			   "Tx Queue count = %u\n",
++		(adapter->num_rx_queues > 1) ? "Enabled" :
++		"Disabled", adapter->num_rx_queues, adapter->num_tx_queues);
++
++	set_bit(__IXGBE_DOWN, &adapter->state);
+ 
+ 	return 0;
++
++err_set_interrupt:
++	kfree(adapter->tx_ring);
++	kfree(adapter->rx_ring);
++err_alloc_queues:
++	return err;
+ }
+ 
+ /**
+@@ -1645,11 +2394,22 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
+ {
+ 	struct ixgbe_hw *hw = &adapter->hw;
+ 	struct pci_dev *pdev = adapter->pdev;
++	unsigned int rss;
++
++	/* Set capability flags */
++	rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
++	adapter->ring_feature[RING_F_RSS].indices = rss;
++	adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
++
++	/* Enable Dynamic interrupt throttling by default */
++	adapter->rx_eitr = 1;
++	adapter->tx_eitr = 1;
+ 
+ 	/* default flow control settings */
+ 	hw->fc.original_type = ixgbe_fc_full;
+ 	hw->fc.type = ixgbe_fc_full;
+ 
++	/* select 10G link by default */
+ 	hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN;
+ 	if (hw->mac.ops.reset(hw)) {
+ 		dev_err(&pdev->dev, "HW Init failed\n");
+@@ -1667,16 +2427,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
+ 		return -EIO;
+ 	}
+ 
+-	/* Set the default values */
+-	adapter->num_rx_queues = IXGBE_DEFAULT_RXQ;
+-	adapter->num_tx_queues = 1;
++	/* enable rx csum by default */
+ 	adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
+ 
+-	if (ixgbe_alloc_queues(adapter)) {
+-		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+-		return -ENOMEM;
+-	}
+-
+ 	set_bit(__IXGBE_DOWN, &adapter->state);
+ 
+ 	return 0;
+@@ -1716,7 +2469,6 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
+ 		return -ENOMEM;
+ 	}
+ 
+-	txdr->adapter = adapter;
+ 	txdr->next_to_use = 0;
+ 	txdr->next_to_clean = 0;
+ 	txdr->work_limit = txdr->count;
+@@ -1735,7 +2487,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
+ 			     struct ixgbe_ring *rxdr)
+ {
+ 	struct pci_dev *pdev = adapter->pdev;
+-	int size, desc_len;
++	int size;
+ 
+ 	size = sizeof(struct ixgbe_rx_buffer) * rxdr->count;
+ 	rxdr->rx_buffer_info = vmalloc(size);
+@@ -1746,10 +2498,8 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
+ 	}
+ 	memset(rxdr->rx_buffer_info, 0, size);
+ 
+-	desc_len = sizeof(union ixgbe_adv_rx_desc);
+-
+ 	/* Round up to nearest 4K */
+-	rxdr->size = rxdr->count * desc_len;
++	rxdr->size = rxdr->count * sizeof(union ixgbe_adv_rx_desc);
+ 	rxdr->size = ALIGN(rxdr->size, 4096);
+ 
+ 	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+@@ -1763,7 +2513,6 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
+ 
+ 	rxdr->next_to_clean = 0;
+ 	rxdr->next_to_use = 0;
+-	rxdr->adapter = adapter;
+ 
+ 	return 0;
+ }
+@@ -1841,8 +2590,7 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)
+ }
+ 
+ /**
+- * ixgbe_setup_all_tx_resources - wrapper to allocate Tx resources
+- *				  (Descriptors) for all queues
++ * ixgbe_setup_all_tx_resources - allocate all queues Tx resources
+  * @adapter: board private structure
+  *
+  * If this function returns with an error, then it's possible one or
+@@ -1868,8 +2616,7 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
+ }
+ 
+ /**
+- * ixgbe_setup_all_rx_resources - wrapper to allocate Rx resources
+- *				  (Descriptors) for all queues
++ * ixgbe_setup_all_rx_resources - allocate all queues Rx resources
+  * @adapter: board private structure
+  *
+  * If this function returns with an error, then it's possible one or
+@@ -1911,6 +2658,9 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
+ 	    (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
+ 		return -EINVAL;
+ 
++	DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n",
++		netdev->mtu, new_mtu);
++	/* must set new MTU before calling down or up */
+ 	netdev->mtu = new_mtu;
+ 
+ 	if (netif_running(netdev))
+@@ -1935,23 +2685,16 @@ static int ixgbe_open(struct net_device *netdev)
+ {
+ 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ 	int err;
+-	u32 num_rx_queues = adapter->num_rx_queues;
+ 
+ 	/* disallow open during test */
+ 	if (test_bit(__IXGBE_TESTING, &adapter->state))
+ 		return -EBUSY;
+ 
+-try_intr_reinit:
+ 	/* allocate transmit descriptors */
+ 	err = ixgbe_setup_all_tx_resources(adapter);
+ 	if (err)
+ 		goto err_setup_tx;
+ 
+-	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
+-		num_rx_queues = 1;
+-		adapter->num_rx_queues = num_rx_queues;
+-	}
+-
+ 	/* allocate receive descriptors */
+ 	err = ixgbe_setup_all_rx_resources(adapter);
+ 	if (err)
+@@ -1959,31 +2702,10 @@ try_intr_reinit:
+ 
+ 	ixgbe_configure(adapter);
+ 
+-	err = ixgbe_request_irq(adapter, &num_rx_queues);
++	err = ixgbe_request_irq(adapter);
+ 	if (err)
+ 		goto err_req_irq;
+ 
+-	/* ixgbe_request might have reduced num_rx_queues */
+-	if (num_rx_queues < adapter->num_rx_queues) {
+-		/* We didn't get MSI-X, so we need to release everything,
+-		 * set our Rx queue count to num_rx_queues, and redo the
+-		 * whole init process.
+-		 */
+-		ixgbe_free_irq(adapter);
+-		if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
+-			pci_disable_msi(adapter->pdev);
+-			adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;
+-		}
+-		ixgbe_free_all_rx_resources(adapter);
+-		ixgbe_free_all_tx_resources(adapter);
+-		adapter->num_rx_queues = num_rx_queues;
+-
+-		/* Reset the hardware, and start over. */
+-		ixgbe_reset(adapter);
+-
+-		goto try_intr_reinit;
+-	}
+-
+ 	err = ixgbe_up_complete(adapter);
+ 	if (err)
+ 		goto err_up;
+@@ -2119,6 +2841,9 @@ static void ixgbe_watchdog(unsigned long data)
+ 	struct net_device *netdev = adapter->netdev;
+ 	bool link_up;
+ 	u32 link_speed = 0;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	int i;
++#endif
+ 
+ 	adapter->hw.mac.ops.check_link(&adapter->hw, &(link_speed), &link_up);
+ 
+@@ -2140,6 +2865,10 @@ static void ixgbe_watchdog(unsigned long data)
+ 
+ 			netif_carrier_on(netdev);
+ 			netif_wake_queue(netdev);
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++			for (i = 0; i < adapter->num_tx_queues; i++)
++				netif_wake_subqueue(netdev, i);
++#endif
+ 		} else {
+ 			/* Force detection of hung controller */
+ 			adapter->detect_tx_hung = true;
+@@ -2154,10 +2883,23 @@ static void ixgbe_watchdog(unsigned long data)
+ 
+ 	ixgbe_update_stats(adapter);
+ 
+-	/* Reset the timer */
+-	if (!test_bit(__IXGBE_DOWN, &adapter->state))
++	if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
++		/* Cause software interrupt to ensure rx rings are cleaned */
++		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++			u32 eics =
++			 (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1;
++			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, eics);
++		} else {
++			/* for legacy and MSI interrupts don't set any bits that
++			 * are enabled for EIAM, because this operation would
++			 * set *both* EIMS and EICS for any bit in EIAM */
++			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
++				     (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
++		}
++		/* Reset the timer */
+ 		mod_timer(&adapter->watchdog_timer,
+ 			  round_jiffies(jiffies + 2 * HZ));
++	}
+ }
+ 
+ static int ixgbe_tso(struct ixgbe_adapter *adapter,
+@@ -2170,7 +2912,6 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
+ 	struct ixgbe_tx_buffer *tx_buffer_info;
+ 	u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
+ 	u32 mss_l4len_idx = 0, l4len;
+-	*hdr_len = 0;
+ 
+ 	if (skb_is_gso(skb)) {
+ 		if (skb_header_cloned(skb)) {
+@@ -2454,7 +3195,11 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
+ {
+ 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ 
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	netif_stop_subqueue(netdev, tx_ring->queue_index);
++#else
+ 	netif_stop_queue(netdev);
++#endif
+ 	/* Herbert's original patch had:
+ 	 *  smp_mb__after_netif_stop_queue();
+ 	 * but since that doesn't exist yet, just open code it. */
+@@ -2466,7 +3211,11 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
+ 		return -EBUSY;
+ 
+ 	/* A reprieve! - use start_queue because it doesn't call schedule */
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	netif_wake_subqueue(netdev, tx_ring->queue_index);
++#else
+ 	netif_wake_queue(netdev);
++#endif
+ 	++adapter->restart_queue;
+ 	return 0;
+ }
+@@ -2487,15 +3236,18 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 	unsigned int len = skb->len;
+ 	unsigned int first;
+ 	unsigned int tx_flags = 0;
+-	u8 hdr_len;
+-	int tso;
++	u8 hdr_len = 0;
++	int r_idx = 0, tso;
+ 	unsigned int mss = 0;
+ 	int count = 0;
+ 	unsigned int f;
+ 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
+ 	len -= skb->data_len;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	r_idx = (adapter->num_tx_queues - 1) & skb->queue_mapping;
++#endif
++	tx_ring = &adapter->tx_ring[r_idx];
+ 
+-	tx_ring = adapter->tx_ring;
+ 
+ 	if (skb->len <= 0) {
+ 		dev_kfree_skb(skb);
+@@ -2604,6 +3356,31 @@ static void ixgbe_netpoll(struct net_device *netdev)
+ #endif
+ 
+ /**
++ * ixgbe_napi_add_all - prep napi structs for use
++ * @adapter: private struct
++ * helper function to napi_add each possible q_vector->napi
++ */
++static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
++{
++	int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++	int (*poll)(struct napi_struct *, int);
++
++	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++		poll = &ixgbe_clean_rxonly;
++	} else {
++		poll = &ixgbe_poll;
++		/* only one q_vector for legacy modes */
++		q_vectors = 1;
++	}
++
++	for (i = 0; i < q_vectors; i++) {
++		struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
++		netif_napi_add(adapter->netdev, &q_vector->napi,
++			       (*poll), 64);
++	}
++}
++
++/**
+  * ixgbe_probe - Device Initialization Routine
+  * @pdev: PCI device information struct
+  * @ent: entry in ixgbe_pci_tbl
+@@ -2654,8 +3431,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ 	}
+ 
+ 	pci_set_master(pdev);
++	pci_save_state(pdev);
+ 
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), MAX_TX_QUEUES);
++#else
+ 	netdev = alloc_etherdev(sizeof(struct ixgbe_adapter));
++#endif
+ 	if (!netdev) {
+ 		err = -ENOMEM;
+ 		goto err_alloc_etherdev;
+@@ -2696,7 +3478,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ 	ixgbe_set_ethtool_ops(netdev);
+ 	netdev->tx_timeout = &ixgbe_tx_timeout;
+ 	netdev->watchdog_timeo = 5 * HZ;
+-	netif_napi_add(netdev, &adapter->napi, ixgbe_clean, 64);
+ 	netdev->vlan_rx_register = ixgbe_vlan_rx_register;
+ 	netdev->vlan_rx_add_vid = ixgbe_vlan_rx_add_vid;
+ 	netdev->vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid;
+@@ -2719,6 +3500,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ 
+ 	/* Setup hw api */
+ 	memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops));
++	hw->mac.type  = ii->mac;
+ 
+ 	err = ii->get_invariants(hw);
+ 	if (err)
+@@ -2741,6 +3523,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ 	if (pci_using_dac)
+ 		netdev->features |= NETIF_F_HIGHDMA;
+ 
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	netdev->features |= NETIF_F_MULTI_QUEUE;
++#endif
+ 
+ 	/* make sure the EEPROM is good */
+ 	if (ixgbe_validate_eeprom_checksum(hw, NULL) < 0) {
+@@ -2770,9 +3555,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ 	hw->fc.low_water = IXGBE_DEFAULT_FCRTL;
+ 	hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
+ 
+-	/* Interrupt Throttle Rate */
+-	adapter->rx_eitr = (1000000 / IXGBE_DEFAULT_ITR_RX_USECS);
+-	adapter->tx_eitr = (1000000 / IXGBE_DEFAULT_ITR_TX_USECS);
++	err = ixgbe_init_interrupt_scheme(adapter);
++	if (err)
++		goto err_sw_init;
+ 
+ 	/* print bus type/speed/width info */
+ 	pci_read_config_word(pdev, IXGBE_PCI_LINK_STATUS, &link_status);
+@@ -2808,12 +3593,27 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ 
+ 	netif_carrier_off(netdev);
+ 	netif_stop_queue(netdev);
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	for (i = 0; i < adapter->num_tx_queues; i++)
++		netif_stop_subqueue(netdev, i);
++#endif
++
++	ixgbe_napi_add_all(adapter);
+ 
+ 	strcpy(netdev->name, "eth%d");
+ 	err = register_netdev(netdev);
+ 	if (err)
+ 		goto err_register;
+ 
++#ifdef CONFIG_DCA
++	if (dca_add_requester(&pdev->dev) == 0) {
++		adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
++		/* always use CB2 mode, difference is masked
++		 * in the CB driver */
++		IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2);
++		ixgbe_setup_dca(adapter);
++	}
++#endif
+ 
+ 	dev_info(&pdev->dev, "Intel(R) 10 Gigabit Network Connection\n");
+ 	cards_found++;
+@@ -2823,6 +3623,7 @@ err_register:
+ 	ixgbe_release_hw_control(adapter);
+ err_hw_init:
+ err_sw_init:
++	ixgbe_reset_interrupt_capability(adapter);
+ err_eeprom:
+ 	iounmap(hw->hw_addr);
+ err_ioremap:
+@@ -2854,16 +3655,27 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
+ 
+ 	flush_scheduled_work();
+ 
++#ifdef CONFIG_DCA
++	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
++		adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
++		dca_remove_requester(&pdev->dev);
++		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
++	}
++
++#endif
+ 	unregister_netdev(netdev);
+ 
+-	ixgbe_release_hw_control(adapter);
++	ixgbe_reset_interrupt_capability(adapter);
+ 
+-	kfree(adapter->tx_ring);
+-	kfree(adapter->rx_ring);
++	ixgbe_release_hw_control(adapter);
+ 
+ 	iounmap(adapter->hw.hw_addr);
+ 	pci_release_regions(pdev);
+ 
++	DPRINTK(PROBE, INFO, "complete\n");
++	kfree(adapter->tx_ring);
++	kfree(adapter->rx_ring);
++
+ 	free_netdev(netdev);
+ 
+ 	pci_disable_device(pdev);
+@@ -2910,6 +3722,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
+ 		return PCI_ERS_RESULT_DISCONNECT;
+ 	}
+ 	pci_set_master(pdev);
++	pci_restore_state(pdev);
+ 
+ 	pci_enable_wake(pdev, PCI_D3hot, 0);
+ 	pci_enable_wake(pdev, PCI_D3cold, 0);
+@@ -2975,6 +3788,10 @@ static int __init ixgbe_init_module(void)
+ 
+ 	printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright);
+ 
++#ifdef CONFIG_DCA
++	dca_register_notify(&dca_notifier);
++
++#endif
+ 	ret = pci_register_driver(&ixgbe_driver);
+ 	return ret;
+ }
+@@ -2988,8 +3805,25 @@ module_init(ixgbe_init_module);
+  **/
+ static void __exit ixgbe_exit_module(void)
+ {
++#ifdef CONFIG_DCA
++	dca_unregister_notify(&dca_notifier);
++#endif
+ 	pci_unregister_driver(&ixgbe_driver);
+ }
++
++#ifdef CONFIG_DCA
++static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
++			    void *p)
++{
++	int ret_val;
++
++	ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event,
++					 __ixgbe_notify_dca);
++
++	return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
++}
++#endif /* CONFIG_DCA */
++
+ module_exit(ixgbe_exit_module);
+ 
+ /* ixgbe_main.c */
+diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
+index 5c154fe..0794482 100644
+--- a/drivers/net/jazzsonic.c
++++ b/drivers/net/jazzsonic.c
+@@ -249,6 +249,7 @@ out:
+ MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
+ module_param(sonic_debug, int, 0);
+ MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
++MODULE_ALIAS("platform:jazzsonic");
+ 
+ #include "sonic.c"
+ 
+@@ -271,6 +272,7 @@ static struct platform_driver jazz_sonic_driver = {
+ 	.remove	= __devexit_p(jazz_sonic_device_remove),
+ 	.driver	= {
+ 		.name	= jazz_sonic_string,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/drivers/net/korina.c b/drivers/net/korina.c
+new file mode 100644
+index 0000000..e185763
+--- /dev/null
++++ b/drivers/net/korina.c
+@@ -0,0 +1,1230 @@
++/*
++ *  Driver for the IDT RC32434 (Korina) on-chip ethernet controller.
++ *
++ *  Copyright 2004 IDT Inc. (rischelp at idt.com)
++ *  Copyright 2006 Felix Fietkau <nbd at openwrt.org>
++ *  Copyright 2008 Florian Fainelli <florian at openwrt.org>
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
++ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
++ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
++ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
++ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
++ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
++ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ *  You should have received a copy of the  GNU General Public License along
++ *  with this program; if not, write  to the Free Software Foundation, Inc.,
++ *  675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ *  Writing to a DMA status register:
++ *
++ *  When writing to the status register, you should mask the bit you have
++ *  been testing the status register with. Both Tx and Rx DMA registers
++ *  should stick to this procedure.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/moduleparam.h>
++#include <linux/sched.h>
++#include <linux/ctype.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/errno.h>
++#include <linux/platform_device.h>
++#include <linux/mii.h>
++#include <linux/ethtool.h>
++#include <linux/crc32.h>
++
++#include <asm/bootinfo.h>
++#include <asm/system.h>
++#include <asm/bitops.h>
++#include <asm/pgtable.h>
++#include <asm/segment.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++
++#include <asm/mach-rc32434/rb.h>
++#include <asm/mach-rc32434/rc32434.h>
++#include <asm/mach-rc32434/eth.h>
++#include <asm/mach-rc32434/dma_v.h>
++
++#define DRV_NAME        "korina"
++#define DRV_VERSION     "0.10"
++#define DRV_RELDATE     "04Mar2008"
++
++#define STATION_ADDRESS_HIGH(dev) (((dev)->dev_addr[0] << 8) | \
++				   ((dev)->dev_addr[1]))
++#define STATION_ADDRESS_LOW(dev)  (((dev)->dev_addr[2] << 24) | \
++				   ((dev)->dev_addr[3] << 16) | \
++				   ((dev)->dev_addr[4] << 8)  | \
++				   ((dev)->dev_addr[5]))
++
++#define MII_CLOCK 1250000 	/* no more than 2.5MHz */
++
++/* the following must be powers of two */
++#define KORINA_NUM_RDS	64  /* number of receive descriptors */
++#define KORINA_NUM_TDS	64  /* number of transmit descriptors */
++
++#define KORINA_RBSIZE	536 /* size of one resource buffer = Ether MTU */
++#define KORINA_RDS_MASK	(KORINA_NUM_RDS - 1)
++#define KORINA_TDS_MASK	(KORINA_NUM_TDS - 1)
++#define RD_RING_SIZE 	(KORINA_NUM_RDS * sizeof(struct dma_desc))
++#define TD_RING_SIZE	(KORINA_NUM_TDS * sizeof(struct dma_desc))
++
++#define TX_TIMEOUT 	(6000 * HZ / 1000)
++
++enum chain_status { desc_filled, desc_empty };
++#define IS_DMA_FINISHED(X)   (((X) & (DMA_DESC_FINI)) != 0)
++#define IS_DMA_DONE(X)   (((X) & (DMA_DESC_DONE)) != 0)
++#define RCVPKT_LENGTH(X)     (((X) & ETH_RX_LEN) >> ETH_RX_LEN_BIT)
++
++/* Information that need to be kept for each board. */
++struct korina_private {
++	struct eth_regs *eth_regs;
++	struct dma_reg *rx_dma_regs;
++	struct dma_reg *tx_dma_regs;
++	struct dma_desc *td_ring; /* transmit descriptor ring */
++	struct dma_desc *rd_ring; /* receive descriptor ring  */
++
++	struct sk_buff *tx_skb[KORINA_NUM_TDS];
++	struct sk_buff *rx_skb[KORINA_NUM_RDS];
++
++	int rx_next_done;
++	int rx_chain_head;
++	int rx_chain_tail;
++	enum chain_status rx_chain_status;
++
++	int tx_next_done;
++	int tx_chain_head;
++	int tx_chain_tail;
++	enum chain_status tx_chain_status;
++	int tx_count;
++	int tx_full;
++
++	int rx_irq;
++	int tx_irq;
++	int ovr_irq;
++	int und_irq;
++
++	spinlock_t lock;        /* NIC xmit lock */
++
++	int dma_halt_cnt;
++	int dma_run_cnt;
++	struct napi_struct napi;
++	struct mii_if_info mii_if;
++	struct net_device *dev;
++	int phy_addr;
++};
++
++extern unsigned int idt_cpu_freq;
++
++static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr)
++{
++	writel(0, &ch->dmandptr);
++	writel(dma_addr, &ch->dmadptr);
++}
++
++static inline void korina_abort_dma(struct net_device *dev,
++					struct dma_reg *ch)
++{
++       if (readl(&ch->dmac) & DMA_CHAN_RUN_BIT) {
++	       writel(0x10, &ch->dmac);
++
++	       while (!(readl(&ch->dmas) & DMA_STAT_HALT))
++		       dev->trans_start = jiffies;
++
++	       writel(0, &ch->dmas);
++       }
++
++       writel(0, &ch->dmadptr);
++       writel(0, &ch->dmandptr);
++}
++
++static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr)
++{
++	writel(dma_addr, &ch->dmandptr);
++}
++
++static void korina_abort_tx(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++
++	korina_abort_dma(dev, lp->tx_dma_regs);
++}
++
++static void korina_abort_rx(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++
++	korina_abort_dma(dev, lp->rx_dma_regs);
++}
++
++static void korina_start_rx(struct korina_private *lp,
++					struct dma_desc *rd)
++{
++	korina_start_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++static void korina_chain_rx(struct korina_private *lp,
++					struct dma_desc *rd)
++{
++	korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++/* transmit packet */
++static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	unsigned long flags;
++	u32 length;
++	u32 chain_index;
++	struct dma_desc *td;
++
++	spin_lock_irqsave(&lp->lock, flags);
++
++	td = &lp->td_ring[lp->tx_chain_tail];
++
++	/* stop queue when full, drop pkts if queue already full */
++	if (lp->tx_count >= (KORINA_NUM_TDS - 2)) {
++		lp->tx_full = 1;
++
++		if (lp->tx_count == (KORINA_NUM_TDS - 2))
++			netif_stop_queue(dev);
++		else {
++			dev->stats.tx_dropped++;
++			dev_kfree_skb_any(skb);
++			spin_unlock_irqrestore(&lp->lock, flags);
++
++			return NETDEV_TX_BUSY;
++		}
++	}
++
++	lp->tx_count++;
++
++	lp->tx_skb[lp->tx_chain_tail] = skb;
++
++	length = skb->len;
++	dma_cache_wback((u32)skb->data, skb->len);
++
++	/* Setup the transmit descriptor. */
++	dma_cache_inv((u32) td, sizeof(*td));
++	td->ca = CPHYSADDR(skb->data);
++	chain_index = (lp->tx_chain_tail - 1) &
++			KORINA_TDS_MASK;
++
++	if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) {
++		if (lp->tx_chain_status == desc_empty) {
++			/* Update tail */
++			td->control = DMA_COUNT(length) |
++					DMA_DESC_COF | DMA_DESC_IOF;
++			/* Move tail */
++			lp->tx_chain_tail = chain_index;
++			/* Write to NDPTR */
++			writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
++					&lp->tx_dma_regs->dmandptr);
++			/* Move head to tail */
++			lp->tx_chain_head = lp->tx_chain_tail;
++		} else {
++			/* Update tail */
++			td->control = DMA_COUNT(length) |
++					DMA_DESC_COF | DMA_DESC_IOF;
++			/* Link to prev */
++			lp->td_ring[chain_index].control &=
++					~DMA_DESC_COF;
++			/* Link to prev */
++			lp->td_ring[chain_index].link =  CPHYSADDR(td);
++			/* Move tail */
++			lp->tx_chain_tail = chain_index;
++			/* Write to NDPTR */
++			writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
++					&(lp->tx_dma_regs->dmandptr));
++			/* Move head to tail */
++			lp->tx_chain_head = lp->tx_chain_tail;
++			lp->tx_chain_status = desc_empty;
++		}
++	} else {
++		if (lp->tx_chain_status == desc_empty) {
++			/* Update tail */
++			td->control = DMA_COUNT(length) |
++					DMA_DESC_COF | DMA_DESC_IOF;
++			/* Move tail */
++			lp->tx_chain_tail = chain_index;
++			lp->tx_chain_status = desc_filled;
++			netif_stop_queue(dev);
++		} else {
++			/* Update tail */
++			td->control = DMA_COUNT(length) |
++					DMA_DESC_COF | DMA_DESC_IOF;
++			lp->td_ring[chain_index].control &=
++					~DMA_DESC_COF;
++			lp->td_ring[chain_index].link =  CPHYSADDR(td);
++			lp->tx_chain_tail = chain_index;
++		}
++	}
++	dma_cache_wback((u32) td, sizeof(*td));
++
++	dev->trans_start = jiffies;
++	spin_unlock_irqrestore(&lp->lock, flags);
++
++	return NETDEV_TX_OK;
++}
++
++static int mdio_read(struct net_device *dev, int mii_id, int reg)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	int ret;
++
++	mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
++
++	writel(0, &lp->eth_regs->miimcfg);
++	writel(0, &lp->eth_regs->miimcmd);
++	writel(mii_id | reg, &lp->eth_regs->miimaddr);
++	writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
++
++	ret = (int)(readl(&lp->eth_regs->miimrdd));
++	return ret;
++}
++
++static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
++{
++	struct korina_private *lp = netdev_priv(dev);
++
++	mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
++
++	writel(0, &lp->eth_regs->miimcfg);
++	writel(1, &lp->eth_regs->miimcmd);
++	writel(mii_id | reg, &lp->eth_regs->miimaddr);
++	writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
++	writel(val, &lp->eth_regs->miimwtd);
++}
++
++/* Ethernet Rx DMA interrupt */
++static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
++{
++	struct net_device *dev = dev_id;
++	struct korina_private *lp = netdev_priv(dev);
++	u32 dmas, dmasm;
++	irqreturn_t retval;
++
++	dmas = readl(&lp->rx_dma_regs->dmas);
++	if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
++		netif_rx_schedule_prep(dev, &lp->napi);
++
++		dmasm = readl(&lp->rx_dma_regs->dmasm);
++		writel(dmasm | (DMA_STAT_DONE |
++				DMA_STAT_HALT | DMA_STAT_ERR),
++				&lp->rx_dma_regs->dmasm);
++
++		if (dmas & DMA_STAT_ERR)
++			printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
++
++		retval = IRQ_HANDLED;
++	} else
++		retval = IRQ_NONE;
++
++	return retval;
++}
++
++static int korina_rx(struct net_device *dev, int limit)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done];
++	struct sk_buff *skb, *skb_new;
++	u8 *pkt_buf;
++	u32 devcs, pkt_len, dmas, rx_free_desc;
++	int count;
++
++	dma_cache_inv((u32)rd, sizeof(*rd));
++
++	for (count = 0; count < limit; count++) {
++
++		devcs = rd->devcs;
++
++		/* Update statistics counters */
++		if (devcs & ETH_RX_CRC)
++			dev->stats.rx_crc_errors++;
++		if (devcs & ETH_RX_LOR)
++			dev->stats.rx_length_errors++;
++		if (devcs & ETH_RX_LE)
++			dev->stats.rx_length_errors++;
++		if (devcs & ETH_RX_OVR)
++			dev->stats.rx_over_errors++;
++		if (devcs & ETH_RX_CV)
++			dev->stats.rx_frame_errors++;
++		if (devcs & ETH_RX_CES)
++			dev->stats.rx_length_errors++;
++		if (devcs & ETH_RX_MP)
++			dev->stats.multicast++;
++
++		if ((devcs & ETH_RX_LD) != ETH_RX_LD) {
++			/* check that this is a whole packet
++			 * WARNING: DMA_FD bit incorrectly set
++			 * in Rc32434 (errata ref #077) */
++			dev->stats.rx_errors++;
++			dev->stats.rx_dropped++;
++		}
++
++		while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) {
++			/* init the var. used for the later
++			 * operations within the while loop */
++			skb_new = NULL;
++			pkt_len = RCVPKT_LENGTH(devcs);
++			skb = lp->rx_skb[lp->rx_next_done];
++
++			if ((devcs & ETH_RX_ROK)) {
++				/* must be the (first and) last
++				 * descriptor then */
++				pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
++
++				/* invalidate the cache */
++				dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
++
++				/* Malloc up new buffer. */
++				skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
++
++				if (!skb_new)
++					break;
++				/* Do not count the CRC */
++				skb_put(skb, pkt_len - 4);
++				skb->protocol = eth_type_trans(skb, dev);
++
++				/* Pass the packet to upper layers */
++				netif_receive_skb(skb);
++				dev->last_rx = jiffies;
++				dev->stats.rx_packets++;
++				dev->stats.rx_bytes += pkt_len;
++
++				/* Update the mcast stats */
++				if (devcs & ETH_RX_MP)
++					dev->stats.multicast++;
++
++				lp->rx_skb[lp->rx_next_done] = skb_new;
++			}
++
++			rd->devcs = 0;
++
++			/* Restore descriptor's curr_addr */
++			if (skb_new)
++				rd->ca = CPHYSADDR(skb_new->data);
++			else
++				rd->ca = CPHYSADDR(skb->data);
++
++			rd->control = DMA_COUNT(KORINA_RBSIZE) |
++				DMA_DESC_COD | DMA_DESC_IOD;
++			lp->rd_ring[(lp->rx_next_done - 1) &
++				KORINA_RDS_MASK].control &=
++				~DMA_DESC_COD;
++
++			lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
++			dma_cache_wback((u32)rd, sizeof(*rd));
++			rd = &lp->rd_ring[lp->rx_next_done];
++			writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
++		}
++	}
++
++	dmas = readl(&lp->rx_dma_regs->dmas);
++
++	if (dmas & DMA_STAT_HALT) {
++		writel(~(DMA_STAT_HALT | DMA_STAT_ERR),
++				&lp->rx_dma_regs->dmas);
++
++		lp->dma_halt_cnt++;
++		rd->devcs = 0;
++		skb = lp->rx_skb[lp->rx_next_done];
++		rd->ca = CPHYSADDR(skb->data);
++		dma_cache_wback((u32)rd, sizeof(*rd));
++		korina_chain_rx(lp, rd);
++	}
++
++	return count;
++}
++
++static int korina_poll(struct napi_struct *napi, int budget)
++{
++	struct korina_private *lp =
++		container_of(napi, struct korina_private, napi);
++	struct net_device *dev = lp->dev;
++	int work_done;
++
++	work_done = korina_rx(dev, budget);
++	if (work_done < budget) {
++		netif_rx_complete(dev, napi);
++
++		writel(readl(&lp->rx_dma_regs->dmasm) &
++			~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
++			&lp->rx_dma_regs->dmasm);
++	}
++	return work_done;
++}
++
++/*
++ * Set or clear the multicast filter for this adaptor.
++ */
++static void korina_multicast_list(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	unsigned long flags;
++	struct dev_mc_list *dmi = dev->mc_list;
++	u32 recognise = ETH_ARC_AB;	/* always accept broadcasts */
++	int i;
++
++	/* Set promiscuous mode */
++	if (dev->flags & IFF_PROMISC)
++		recognise |= ETH_ARC_PRO;
++
++	else if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 4))
++		/* All multicast and broadcast */
++		recognise |= ETH_ARC_AM;
++
++	/* Build the hash table */
++	if (dev->mc_count > 4) {
++		u16 hash_table[4];
++		u32 crc;
++
++		for (i = 0; i < 4; i++)
++			hash_table[i] = 0;
++
++		for (i = 0; i < dev->mc_count; i++) {
++			char *addrs = dmi->dmi_addr;
++
++			dmi = dmi->next;
++
++			if (!(*addrs & 1))
++				continue;
++
++			crc = ether_crc_le(6, addrs);
++			crc >>= 26;
++			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
++		}
++		/* Accept filtered multicast */
++		recognise |= ETH_ARC_AFM;
++
++		/* Fill the MAC hash tables with their values */
++		writel((u32)(hash_table[1] << 16 | hash_table[0]),
++					&lp->eth_regs->ethhash0);
++		writel((u32)(hash_table[3] << 16 | hash_table[2]),
++					&lp->eth_regs->ethhash1);
++	}
++
++	spin_lock_irqsave(&lp->lock, flags);
++	writel(recognise, &lp->eth_regs->etharc);
++	spin_unlock_irqrestore(&lp->lock, flags);
++}
++
++static void korina_tx(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	struct dma_desc *td = &lp->td_ring[lp->tx_next_done];
++	u32 devcs;
++	u32 dmas;
++
++	spin_lock(&lp->lock);
++
++	/* Process all desc that are done */
++	while (IS_DMA_FINISHED(td->control)) {
++		if (lp->tx_full == 1) {
++			netif_wake_queue(dev);
++			lp->tx_full = 0;
++		}
++
++		devcs = lp->td_ring[lp->tx_next_done].devcs;
++		if ((devcs & (ETH_TX_FD | ETH_TX_LD)) !=
++				(ETH_TX_FD | ETH_TX_LD)) {
++			dev->stats.tx_errors++;
++			dev->stats.tx_dropped++;
++
++			/* Should never happen */
++			printk(KERN_ERR DRV_NAME "%s: split tx ignored\n",
++							dev->name);
++		} else if (devcs & ETH_TX_TOK) {
++			dev->stats.tx_packets++;
++			dev->stats.tx_bytes +=
++					lp->tx_skb[lp->tx_next_done]->len;
++		} else {
++			dev->stats.tx_errors++;
++			dev->stats.tx_dropped++;
++
++			/* Underflow */
++			if (devcs & ETH_TX_UND)
++				dev->stats.tx_fifo_errors++;
++
++			/* Oversized frame */
++			if (devcs & ETH_TX_OF)
++				dev->stats.tx_aborted_errors++;
++
++			/* Excessive deferrals */
++			if (devcs & ETH_TX_ED)
++				dev->stats.tx_carrier_errors++;
++
++			/* Collisions: medium busy */
++			if (devcs & ETH_TX_EC)
++				dev->stats.collisions++;
++
++			/* Late collision */
++			if (devcs & ETH_TX_LC)
++				dev->stats.tx_window_errors++;
++		}
++
++		/* We must always free the original skb */
++		if (lp->tx_skb[lp->tx_next_done]) {
++			dev_kfree_skb_any(lp->tx_skb[lp->tx_next_done]);
++			lp->tx_skb[lp->tx_next_done] = NULL;
++		}
++
++		lp->td_ring[lp->tx_next_done].control = DMA_DESC_IOF;
++		lp->td_ring[lp->tx_next_done].devcs = ETH_TX_FD | ETH_TX_LD;
++		lp->td_ring[lp->tx_next_done].link = 0;
++		lp->td_ring[lp->tx_next_done].ca = 0;
++		lp->tx_count--;
++
++		/* Go on to next transmission */
++		lp->tx_next_done = (lp->tx_next_done + 1) & KORINA_TDS_MASK;
++		td = &lp->td_ring[lp->tx_next_done];
++
++	}
++
++	/* Clear the DMA status register */
++	dmas = readl(&lp->tx_dma_regs->dmas);
++	writel(~dmas, &lp->tx_dma_regs->dmas);
++
++	writel(readl(&lp->tx_dma_regs->dmasm) &
++			~(DMA_STAT_FINI | DMA_STAT_ERR),
++			&lp->tx_dma_regs->dmasm);
++
++	spin_unlock(&lp->lock);
++}
++
++static irqreturn_t
++korina_tx_dma_interrupt(int irq, void *dev_id)
++{
++	struct net_device *dev = dev_id;
++	struct korina_private *lp = netdev_priv(dev);
++	u32 dmas, dmasm;
++	irqreturn_t retval;
++
++	dmas = readl(&lp->tx_dma_regs->dmas);
++
++	if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
++		korina_tx(dev);
++
++		dmasm = readl(&lp->tx_dma_regs->dmasm);
++		writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
++				&lp->tx_dma_regs->dmasm);
++
++		if (lp->tx_chain_status == desc_filled &&
++			(readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
++			writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
++				&(lp->tx_dma_regs->dmandptr));
++			lp->tx_chain_status = desc_empty;
++			lp->tx_chain_head = lp->tx_chain_tail;
++			dev->trans_start = jiffies;
++		}
++		if (dmas & DMA_STAT_ERR)
++			printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
++
++		retval = IRQ_HANDLED;
++	} else
++		retval = IRQ_NONE;
++
++	return retval;
++}
++
++
++static void korina_check_media(struct net_device *dev, unsigned int init_media)
++{
++	struct korina_private *lp = netdev_priv(dev);
++
++	mii_check_media(&lp->mii_if, 0, init_media);
++
++	if (lp->mii_if.full_duplex)
++		writel(readl(&lp->eth_regs->ethmac2) | ETH_MAC2_FD,
++						&lp->eth_regs->ethmac2);
++	else
++		writel(readl(&lp->eth_regs->ethmac2) & ~ETH_MAC2_FD,
++						&lp->eth_regs->ethmac2);
++}
++
++static void korina_set_carrier(struct mii_if_info *mii)
++{
++	if (mii->force_media) {
++		/* autoneg is off: Link is always assumed to be up */
++		if (!netif_carrier_ok(mii->dev))
++			netif_carrier_on(mii->dev);
++	} else  /* Let MMI library update carrier status */
++		korina_check_media(mii->dev, 0);
++}
++
++static int korina_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	struct mii_ioctl_data *data = if_mii(rq);
++	int rc;
++
++	if (!netif_running(dev))
++		return -EINVAL;
++	spin_lock_irq(&lp->lock);
++	rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
++	spin_unlock_irq(&lp->lock);
++	korina_set_carrier(&lp->mii_if);
++
++	return rc;
++}
++
++/* ethtool helpers */
++static void netdev_get_drvinfo(struct net_device *dev,
++			struct ethtool_drvinfo *info)
++{
++	struct korina_private *lp = netdev_priv(dev);
++
++	strcpy(info->driver, DRV_NAME);
++	strcpy(info->version, DRV_VERSION);
++	strcpy(info->bus_info, lp->dev->name);
++}
++
++static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	int rc;
++
++	spin_lock_irq(&lp->lock);
++	rc = mii_ethtool_gset(&lp->mii_if, cmd);
++	spin_unlock_irq(&lp->lock);
++
++	return rc;
++}
++
++static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	int rc;
++
++	spin_lock_irq(&lp->lock);
++	rc = mii_ethtool_sset(&lp->mii_if, cmd);
++	spin_unlock_irq(&lp->lock);
++	korina_set_carrier(&lp->mii_if);
++
++	return rc;
++}
++
++static u32 netdev_get_link(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++
++	return mii_link_ok(&lp->mii_if);
++}
++
++static struct ethtool_ops netdev_ethtool_ops = {
++	.get_drvinfo            = netdev_get_drvinfo,
++	.get_settings           = netdev_get_settings,
++	.set_settings           = netdev_set_settings,
++	.get_link               = netdev_get_link,
++};
++
++static void korina_alloc_ring(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	int i;
++
++	/* Initialize the transmit descriptors */
++	for (i = 0; i < KORINA_NUM_TDS; i++) {
++		lp->td_ring[i].control = DMA_DESC_IOF;
++		lp->td_ring[i].devcs = ETH_TX_FD | ETH_TX_LD;
++		lp->td_ring[i].ca = 0;
++		lp->td_ring[i].link = 0;
++	}
++	lp->tx_next_done = lp->tx_chain_head = lp->tx_chain_tail =
++			lp->tx_full = lp->tx_count = 0;
++	lp->tx_chain_status = desc_empty;
++
++	/* Initialize the receive descriptors */
++	for (i = 0; i < KORINA_NUM_RDS; i++) {
++		struct sk_buff *skb = lp->rx_skb[i];
++
++		skb = dev_alloc_skb(KORINA_RBSIZE + 2);
++		if (!skb)
++			break;
++		skb_reserve(skb, 2);
++		lp->rx_skb[i] = skb;
++		lp->rd_ring[i].control = DMA_DESC_IOD |
++				DMA_COUNT(KORINA_RBSIZE);
++		lp->rd_ring[i].devcs = 0;
++		lp->rd_ring[i].ca = CPHYSADDR(skb->data);
++		lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[i+1]);
++	}
++
++	/* loop back */
++	lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[0]);
++	lp->rx_next_done  = 0;
++
++	lp->rd_ring[i].control |= DMA_DESC_COD;
++	lp->rx_chain_head = 0;
++	lp->rx_chain_tail = 0;
++	lp->rx_chain_status = desc_empty;
++}
++
++static void korina_free_ring(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	int i;
++
++	for (i = 0; i < KORINA_NUM_RDS; i++) {
++		lp->rd_ring[i].control = 0;
++		if (lp->rx_skb[i])
++			dev_kfree_skb_any(lp->rx_skb[i]);
++		lp->rx_skb[i] = NULL;
++	}
++
++	for (i = 0; i < KORINA_NUM_TDS; i++) {
++		lp->td_ring[i].control = 0;
++		if (lp->tx_skb[i])
++			dev_kfree_skb_any(lp->tx_skb[i]);
++		lp->tx_skb[i] = NULL;
++	}
++}
++
++/*
++ * Initialize the RC32434 ethernet controller.
++ */
++static int korina_init(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++
++	/* Disable DMA */
++	korina_abort_tx(dev);
++	korina_abort_rx(dev);
++
++	/* reset ethernet logic */
++	writel(0, &lp->eth_regs->ethintfc);
++	while ((readl(&lp->eth_regs->ethintfc) & ETH_INT_FC_RIP))
++		dev->trans_start = jiffies;
++
++	/* Enable Ethernet Interface */
++	writel(ETH_INT_FC_EN, &lp->eth_regs->ethintfc);
++
++	/* Allocate rings */
++	korina_alloc_ring(dev);
++
++	writel(0, &lp->rx_dma_regs->dmas);
++	/* Start Rx DMA */
++	korina_start_rx(lp, &lp->rd_ring[0]);
++
++	writel(readl(&lp->tx_dma_regs->dmasm) &
++			~(DMA_STAT_FINI | DMA_STAT_ERR),
++			&lp->tx_dma_regs->dmasm);
++	writel(readl(&lp->rx_dma_regs->dmasm) &
++			~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
++			&lp->rx_dma_regs->dmasm);
++
++	/* Accept only packets destined for this Ethernet device address */
++	writel(ETH_ARC_AB, &lp->eth_regs->etharc);
++
++	/* Set all Ether station address registers to their initial values */
++	writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal0);
++	writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah0);
++
++	writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal1);
++	writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah1);
++
++	writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal2);
++	writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah2);
++
++	writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal3);
++	writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah3);
++
++
++	/* Frame Length Checking, Pad Enable, CRC Enable, Full Duplex set */
++	writel(ETH_MAC2_PE | ETH_MAC2_CEN | ETH_MAC2_FD,
++			&lp->eth_regs->ethmac2);
++
++	/* Back to back inter-packet-gap */
++	writel(0x15, &lp->eth_regs->ethipgt);
++	/* Non - Back to back inter-packet-gap */
++	writel(0x12, &lp->eth_regs->ethipgr);
++
++	/* Management Clock Prescaler Divisor
++	 * Clock independent setting */
++	writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1,
++		       &lp->eth_regs->ethmcp);
++
++	/* don't transmit until fifo contains 48b */
++	writel(48, &lp->eth_regs->ethfifott);
++
++	writel(ETH_MAC1_RE, &lp->eth_regs->ethmac1);
++
++	napi_enable(&lp->napi);
++	netif_start_queue(dev);
++
++	return 0;
++}
++
++/*
++ * Restart the RC32434 ethernet controller.
++ * FIXME: check the return status where we call it
++ */
++static int korina_restart(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	int ret;
++
++	/*
++	 * Disable interrupts
++	 */
++	disable_irq(lp->rx_irq);
++	disable_irq(lp->tx_irq);
++	disable_irq(lp->ovr_irq);
++	disable_irq(lp->und_irq);
++
++	writel(readl(&lp->tx_dma_regs->dmasm) |
++				DMA_STAT_FINI | DMA_STAT_ERR,
++				&lp->tx_dma_regs->dmasm);
++	writel(readl(&lp->rx_dma_regs->dmasm) |
++				DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
++				&lp->rx_dma_regs->dmasm);
++
++	korina_free_ring(dev);
++
++	ret = korina_init(dev);
++	if (ret < 0) {
++		printk(KERN_ERR DRV_NAME "%s: cannot restart device\n",
++								dev->name);
++		return ret;
++	}
++	korina_multicast_list(dev);
++
++	enable_irq(lp->und_irq);
++	enable_irq(lp->ovr_irq);
++	enable_irq(lp->tx_irq);
++	enable_irq(lp->rx_irq);
++
++	return ret;
++}
++
++static void korina_clear_and_restart(struct net_device *dev, u32 value)
++{
++	struct korina_private *lp = netdev_priv(dev);
++
++	netif_stop_queue(dev);
++	writel(value, &lp->eth_regs->ethintfc);
++	korina_restart(dev);
++}
++
++/* Ethernet Tx Underflow interrupt */
++static irqreturn_t korina_und_interrupt(int irq, void *dev_id)
++{
++	struct net_device *dev = dev_id;
++	struct korina_private *lp = netdev_priv(dev);
++	unsigned int und;
++
++	spin_lock(&lp->lock);
++
++	und = readl(&lp->eth_regs->ethintfc);
++
++	if (und & ETH_INT_FC_UND)
++		korina_clear_and_restart(dev, und & ~ETH_INT_FC_UND);
++
++	spin_unlock(&lp->lock);
++
++	return IRQ_HANDLED;
++}
++
++static void korina_tx_timeout(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	unsigned long flags;
++
++	spin_lock_irqsave(&lp->lock, flags);
++	korina_restart(dev);
++	spin_unlock_irqrestore(&lp->lock, flags);
++}
++
++/* Ethernet Rx Overflow interrupt */
++static irqreturn_t
++korina_ovr_interrupt(int irq, void *dev_id)
++{
++	struct net_device *dev = dev_id;
++	struct korina_private *lp = netdev_priv(dev);
++	unsigned int ovr;
++
++	spin_lock(&lp->lock);
++	ovr = readl(&lp->eth_regs->ethintfc);
++
++	if (ovr & ETH_INT_FC_OVR)
++		korina_clear_and_restart(dev, ovr & ~ETH_INT_FC_OVR);
++
++	spin_unlock(&lp->lock);
++
++	return IRQ_HANDLED;
++}
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++static void korina_poll_controller(struct net_device *dev)
++{
++	disable_irq(dev->irq);
++	korina_tx_dma_interrupt(dev->irq, dev);
++	enable_irq(dev->irq);
++}
++#endif
++
++static int korina_open(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	int ret;
++
++	/* Initialize */
++	ret = korina_init(dev);
++	if (ret < 0) {
++		printk(KERN_ERR DRV_NAME "%s: cannot open device\n", dev->name);
++		goto out;
++	}
++
++	/* Install the interrupt handler
++	 * that handles the Done Finished
++	 * Ovr and Und Events */
++	ret = request_irq(lp->rx_irq, &korina_rx_dma_interrupt,
++		IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Rx", dev);
++	if (ret < 0) {
++		printk(KERN_ERR DRV_NAME "%s: unable to get Rx DMA IRQ %d\n",
++		    dev->name, lp->rx_irq);
++		goto err_release;
++	}
++	ret = request_irq(lp->tx_irq, &korina_tx_dma_interrupt,
++		IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Tx", dev);
++	if (ret < 0) {
++		printk(KERN_ERR DRV_NAME "%s: unable to get Tx DMA IRQ %d\n",
++		    dev->name, lp->tx_irq);
++		goto err_free_rx_irq;
++	}
++
++	/* Install handler for overrun error. */
++	ret = request_irq(lp->ovr_irq, &korina_ovr_interrupt,
++			IRQF_SHARED | IRQF_DISABLED, "Ethernet Overflow", dev);
++	if (ret < 0) {
++		printk(KERN_ERR DRV_NAME"%s: unable to get OVR IRQ %d\n",
++		    dev->name, lp->ovr_irq);
++		goto err_free_tx_irq;
++	}
++
++	/* Install handler for underflow error. */
++	ret = request_irq(lp->und_irq, &korina_und_interrupt,
++			IRQF_SHARED | IRQF_DISABLED, "Ethernet Underflow", dev);
++	if (ret < 0) {
++		printk(KERN_ERR DRV_NAME "%s: unable to get UND IRQ %d\n",
++		    dev->name, lp->und_irq);
++		goto err_free_ovr_irq;
++	}
++out:
++	return ret;
++
++err_free_ovr_irq:
++	free_irq(lp->ovr_irq, dev);
++err_free_tx_irq:
++	free_irq(lp->tx_irq, dev);
++err_free_rx_irq:
++	free_irq(lp->rx_irq, dev);
++err_release:
++	korina_free_ring(dev);
++	goto out;
++}
++
++static int korina_close(struct net_device *dev)
++{
++	struct korina_private *lp = netdev_priv(dev);
++	u32 tmp;
++
++	/* Disable interrupts */
++	disable_irq(lp->rx_irq);
++	disable_irq(lp->tx_irq);
++	disable_irq(lp->ovr_irq);
++	disable_irq(lp->und_irq);
++
++	korina_abort_tx(dev);
++	tmp = readl(&lp->tx_dma_regs->dmasm);
++	tmp = tmp | DMA_STAT_FINI | DMA_STAT_ERR;
++	writel(tmp, &lp->tx_dma_regs->dmasm);
++
++	korina_abort_rx(dev);
++	tmp = readl(&lp->rx_dma_regs->dmasm);
++	tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
++	writel(tmp, &lp->rx_dma_regs->dmasm);
++
++	korina_free_ring(dev);
++
++	free_irq(lp->rx_irq, dev);
++	free_irq(lp->tx_irq, dev);
++	free_irq(lp->ovr_irq, dev);
++	free_irq(lp->und_irq, dev);
++
++	return 0;
++}
++
++static int korina_probe(struct platform_device *pdev)
++{
++	struct korina_device *bif = platform_get_drvdata(pdev);
++	struct korina_private *lp;
++	struct net_device *dev;
++	struct resource *r;
++	int rc;
++
++	dev = alloc_etherdev(sizeof(struct korina_private));
++	if (!dev) {
++		printk(KERN_ERR DRV_NAME ": alloc_etherdev failed\n");
++		return -ENOMEM;
++	}
++	SET_NETDEV_DEV(dev, &pdev->dev);
++	platform_set_drvdata(pdev, dev);
++	lp = netdev_priv(dev);
++
++	bif->dev = dev;
++	memcpy(dev->dev_addr, bif->mac, 6);
++
++	lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx");
++	lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx");
++	lp->ovr_irq = platform_get_irq_byname(pdev, "korina_ovr");
++	lp->und_irq = platform_get_irq_byname(pdev, "korina_und");
++
++	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs");
++	dev->base_addr = r->start;
++	lp->eth_regs = ioremap_nocache(r->start, r->end - r->start);
++	if (!lp->eth_regs) {
++		printk(KERN_ERR DRV_NAME "cannot remap registers\n");
++		rc = -ENXIO;
++		goto probe_err_out;
++	}
++
++	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx");
++	lp->rx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
++	if (!lp->rx_dma_regs) {
++		printk(KERN_ERR DRV_NAME "cannot remap Rx DMA registers\n");
++		rc = -ENXIO;
++		goto probe_err_dma_rx;
++	}
++
++	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx");
++	lp->tx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
++	if (!lp->tx_dma_regs) {
++		printk(KERN_ERR DRV_NAME "cannot remap Tx DMA registers\n");
++		rc = -ENXIO;
++		goto probe_err_dma_tx;
++	}
++
++	lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
++	if (!lp->td_ring) {
++		printk(KERN_ERR DRV_NAME "cannot allocate descriptors\n");
++		rc = -ENXIO;
++		goto probe_err_td_ring;
++	}
++
++	dma_cache_inv((unsigned long)(lp->td_ring),
++			TD_RING_SIZE + RD_RING_SIZE);
++
++	/* now convert TD_RING pointer to KSEG1 */
++	lp->td_ring = (struct dma_desc *)KSEG1ADDR(lp->td_ring);
++	lp->rd_ring = &lp->td_ring[KORINA_NUM_TDS];
++
++	spin_lock_init(&lp->lock);
++	/* just use the rx dma irq */
++	dev->irq = lp->rx_irq;
++	lp->dev = dev;
++
++	dev->open = korina_open;
++	dev->stop = korina_close;
++	dev->hard_start_xmit = korina_send_packet;
++	dev->set_multicast_list = &korina_multicast_list;
++	dev->ethtool_ops = &netdev_ethtool_ops;
++	dev->tx_timeout = korina_tx_timeout;
++	dev->watchdog_timeo = TX_TIMEOUT;
++	dev->do_ioctl = &korina_ioctl;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++	dev->poll_controller = korina_poll_controller;
++#endif
++	netif_napi_add(dev, &lp->napi, korina_poll, 64);
++
++	lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05);
++	lp->mii_if.dev = dev;
++	lp->mii_if.mdio_read = mdio_read;
++	lp->mii_if.mdio_write = mdio_write;
++	lp->mii_if.phy_id = lp->phy_addr;
++	lp->mii_if.phy_id_mask = 0x1f;
++	lp->mii_if.reg_num_mask = 0x1f;
++
++	rc = register_netdev(dev);
++	if (rc < 0) {
++		printk(KERN_ERR DRV_NAME
++			": cannot register net device %d\n", rc);
++		goto probe_err_register;
++	}
++out:
++	return rc;
++
++probe_err_register:
++	kfree(lp->td_ring);
++probe_err_td_ring:
++	iounmap(lp->tx_dma_regs);
++probe_err_dma_tx:
++	iounmap(lp->rx_dma_regs);
++probe_err_dma_rx:
++	iounmap(lp->eth_regs);
++probe_err_out:
++	free_netdev(dev);
++	goto out;
++}
++
++static int korina_remove(struct platform_device *pdev)
++{
++	struct korina_device *bif = platform_get_drvdata(pdev);
++	struct korina_private *lp = netdev_priv(bif->dev);
++
++	iounmap(lp->eth_regs);
++	iounmap(lp->rx_dma_regs);
++	iounmap(lp->tx_dma_regs);
++
++	platform_set_drvdata(pdev, NULL);
++	unregister_netdev(bif->dev);
++	free_netdev(bif->dev);
++
++	return 0;
++}
++
++static struct platform_driver korina_driver = {
++	.driver.name = "korina",
++	.probe = korina_probe,
++	.remove = korina_remove,
++};
++
++static int __init korina_init_module(void)
++{
++	return platform_driver_register(&korina_driver);
++}
++
++static void korina_cleanup_module(void)
++{
++	return platform_driver_unregister(&korina_driver);
++}
++
++module_init(korina_init_module);
++module_exit(korina_cleanup_module);
++
++MODULE_AUTHOR("Philip Rischel <rischelp at idt.com>");
++MODULE_AUTHOR("Felix Fietkau <nbd at openwrt.org>");
++MODULE_AUTHOR("Florian Fainelli <florian at openwrt.org>");
++MODULE_DESCRIPTION("IDT RC32434 (Korina) Ethernet driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
+index f2a6e71..41b774b 100644
+--- a/drivers/net/loopback.c
++++ b/drivers/net/loopback.c
+@@ -258,7 +258,7 @@ static __net_init int loopback_net_init(struct net *net)
+ 	if (!dev)
+ 		goto out;
+ 
+-	dev->nd_net = net;
++	dev_net_set(dev, net);
+ 	err = register_netdev(dev);
+ 	if (err)
+ 		goto out_free_netdev;
+diff --git a/drivers/net/macb.c b/drivers/net/macb.c
+index 489c7c3..92dccd4 100644
+--- a/drivers/net/macb.c
++++ b/drivers/net/macb.c
+@@ -246,7 +246,7 @@ static int macb_mii_init(struct macb *bp)
+ 	bp->mii_bus.read = &macb_mdio_read;
+ 	bp->mii_bus.write = &macb_mdio_write;
+ 	bp->mii_bus.reset = &macb_mdio_reset;
+-	bp->mii_bus.id = bp->pdev->id;
++	snprintf(bp->mii_bus.id, MII_BUS_ID_SIZE, "%x", bp->pdev->id);
+ 	bp->mii_bus.priv = bp;
+ 	bp->mii_bus.dev = &bp->dev->dev;
+ 	pdata = bp->pdev->dev.platform_data;
+@@ -1281,6 +1281,7 @@ static struct platform_driver macb_driver = {
+ 	.remove		= __exit_p(macb_remove),
+ 	.driver		= {
+ 		.name		= "macb",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -1300,3 +1301,4 @@ module_exit(macb_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Atmel MACB Ethernet driver");
+ MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen at atmel.com>");
++MODULE_ALIAS("platform:macb");
+diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
+index f651a81..2056cfc 100644
+--- a/drivers/net/macvlan.c
++++ b/drivers/net/macvlan.c
+@@ -402,7 +402,7 @@ static int macvlan_newlink(struct net_device *dev,
+ 	if (!tb[IFLA_LINK])
+ 		return -EINVAL;
+ 
+-	lowerdev = __dev_get_by_index(dev->nd_net, nla_get_u32(tb[IFLA_LINK]));
++	lowerdev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK]));
+ 	if (lowerdev == NULL)
+ 		return -ENODEV;
+ 
+diff --git a/drivers/net/meth.c b/drivers/net/meth.c
+index cdaa8fc..0b32648 100644
+--- a/drivers/net/meth.c
++++ b/drivers/net/meth.c
+@@ -830,6 +830,7 @@ static struct platform_driver meth_driver = {
+ 	.remove	= __devexit_p(meth_remove),
+ 	.driver = {
+ 		.name	= "meth",
++		.owner	= THIS_MODULE,
+ 	}
+ };
+ 
+@@ -855,3 +856,4 @@ module_exit(meth_exit_module);
+ MODULE_AUTHOR("Ilya Volynets <ilya at theIlya.com>");
+ MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:meth");
+diff --git a/drivers/net/mlx4/catas.c b/drivers/net/mlx4/catas.c
+index 6b32ec9..aa95287 100644
+--- a/drivers/net/mlx4/catas.c
++++ b/drivers/net/mlx4/catas.c
+@@ -69,7 +69,7 @@ static void poll_catas(unsigned long dev_ptr)
+ 	if (readl(priv->catas_err.map)) {
+ 		dump_err_buf(dev);
+ 
+-		mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0);
++		mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, 0);
+ 
+ 		if (internal_err_reset) {
+ 			spin_lock(&catas_lock);
+diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
+index db49051..70dff94 100644
+--- a/drivers/net/mlx4/cmd.c
++++ b/drivers/net/mlx4/cmd.c
+@@ -106,7 +106,8 @@ struct mlx4_cmd_context {
+ 	u16			token;
+ };
+ 
+-static int mlx4_status_to_errno(u8 status) {
++static int mlx4_status_to_errno(u8 status)
++{
+ 	static const int trans_table[] = {
+ 		[CMD_STAT_INTERNAL_ERR]	  = -EIO,
+ 		[CMD_STAT_BAD_OP]	  = -EPERM,
+diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
+index d4441fe..caa5bcf 100644
+--- a/drivers/net/mlx4/cq.c
++++ b/drivers/net/mlx4/cq.c
+@@ -38,6 +38,7 @@
+ #include <linux/hardirq.h>
+ 
+ #include <linux/mlx4/cmd.h>
++#include <linux/mlx4/cq.h>
+ 
+ #include "mlx4.h"
+ #include "icm.h"
+@@ -47,21 +48,19 @@ struct mlx4_cq_context {
+ 	u16			reserved1[3];
+ 	__be16			page_offset;
+ 	__be32			logsize_usrpage;
+-	u8			reserved2;
+-	u8			cq_period;
+-	u8			reserved3;
+-	u8			cq_max_count;
+-	u8			reserved4[3];
++	__be16			cq_period;
++	__be16			cq_max_count;
++	u8			reserved2[3];
+ 	u8			comp_eqn;
+ 	u8			log_page_size;
+-	u8			reserved5[2];
++	u8			reserved3[2];
+ 	u8			mtt_base_addr_h;
+ 	__be32			mtt_base_addr_l;
+ 	__be32			last_notified_index;
+ 	__be32			solicit_producer_index;
+ 	__be32			consumer_index;
+ 	__be32			producer_index;
+-	u32			reserved6[2];
++	u32			reserved4[2];
+ 	__be64			db_rec_addr;
+ };
+ 
+@@ -121,6 +120,13 @@ static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ 			MLX4_CMD_TIME_CLASS_A);
+ }
+ 
++static int mlx4_MODIFY_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
++			 int cq_num, u32 opmod)
++{
++	return mlx4_cmd(dev, mailbox->dma, cq_num, opmod, MLX4_CMD_MODIFY_CQ,
++			MLX4_CMD_TIME_CLASS_A);
++}
++
+ static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ 			 int cq_num)
+ {
+@@ -129,6 +135,58 @@ static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ 			    MLX4_CMD_TIME_CLASS_A);
+ }
+ 
++int mlx4_cq_modify(struct mlx4_dev *dev, struct mlx4_cq *cq,
++		   u16 count, u16 period)
++{
++	struct mlx4_cmd_mailbox *mailbox;
++	struct mlx4_cq_context *cq_context;
++	int err;
++
++	mailbox = mlx4_alloc_cmd_mailbox(dev);
++	if (IS_ERR(mailbox))
++		return PTR_ERR(mailbox);
++
++	cq_context = mailbox->buf;
++	memset(cq_context, 0, sizeof *cq_context);
++
++	cq_context->cq_max_count = cpu_to_be16(count);
++	cq_context->cq_period    = cpu_to_be16(period);
++
++	err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 1);
++
++	mlx4_free_cmd_mailbox(dev, mailbox);
++	return err;
++}
++EXPORT_SYMBOL_GPL(mlx4_cq_modify);
++
++int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
++		   int entries, struct mlx4_mtt *mtt)
++{
++	struct mlx4_cmd_mailbox *mailbox;
++	struct mlx4_cq_context *cq_context;
++	u64 mtt_addr;
++	int err;
++
++	mailbox = mlx4_alloc_cmd_mailbox(dev);
++	if (IS_ERR(mailbox))
++		return PTR_ERR(mailbox);
++
++	cq_context = mailbox->buf;
++	memset(cq_context, 0, sizeof *cq_context);
++
++	cq_context->logsize_usrpage = cpu_to_be32(ilog2(entries) << 24);
++	cq_context->log_page_size   = mtt->page_shift - 12;
++	mtt_addr = mlx4_mtt_addr(dev, mtt);
++	cq_context->mtt_base_addr_h = mtt_addr >> 32;
++	cq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
++
++	err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 1);
++
++	mlx4_free_cmd_mailbox(dev, mailbox);
++	return err;
++}
++EXPORT_SYMBOL_GPL(mlx4_cq_resize);
++
+ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
+ 		  struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq)
+ {
+diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
+index 9c36c20..e141a15 100644
+--- a/drivers/net/mlx4/eq.c
++++ b/drivers/net/mlx4/eq.c
+@@ -202,7 +202,10 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
+ 			break;
+ 
+ 		case MLX4_EVENT_TYPE_PORT_CHANGE:
+-			mlx4_dispatch_event(dev, eqe->type, eqe->subtype,
++			mlx4_dispatch_event(dev,
++					    eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_ACTIVE ?
++					    MLX4_DEV_EVENT_PORT_UP :
++					    MLX4_DEV_EVENT_PORT_DOWN,
+ 					    be32_to_cpu(eqe->event.port_change.port) >> 28);
+ 			break;
+ 
+diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
+index 61dc495..d82f275 100644
+--- a/drivers/net/mlx4/fw.c
++++ b/drivers/net/mlx4/fw.c
+@@ -133,6 +133,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
+ #define QUERY_DEV_CAP_MAX_AV_OFFSET		0x27
+ #define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET		0x29
+ #define QUERY_DEV_CAP_MAX_RES_QP_OFFSET		0x2b
++#define QUERY_DEV_CAP_MAX_GSO_OFFSET		0x2d
+ #define QUERY_DEV_CAP_MAX_RDMA_OFFSET		0x2f
+ #define QUERY_DEV_CAP_RSZ_SRQ_OFFSET		0x33
+ #define QUERY_DEV_CAP_ACK_DELAY_OFFSET		0x35
+@@ -215,6 +216,13 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
+ 	dev_cap->max_requester_per_qp = 1 << (field & 0x3f);
+ 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET);
+ 	dev_cap->max_responder_per_qp = 1 << (field & 0x3f);
++	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GSO_OFFSET);
++	field &= 0x1f;
++	if (!field)
++		dev_cap->max_gso_sz = 0;
++	else
++		dev_cap->max_gso_sz = 1 << field;
++
+ 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET);
+ 	dev_cap->max_rdma_global = 1 << (field & 0x3f);
+ 	MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
+@@ -377,6 +385,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
+ 		 dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg);
+ 	mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
+ 		 dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg);
++	mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz);
+ 
+ 	dump_dev_cap_flags(dev, dev_cap->flags);
+ 
+@@ -696,6 +705,10 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
+ 	/* Check port for UD address vector: */
+ 	*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1);
+ 
++	/* Enable IPoIB checksumming if we can: */
++	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
++		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3);
++
+ 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
+ 
+ 	MLX4_PUT(inbox, param->qpc_base,      INIT_HCA_QPC_BASE_OFFSET);
+diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
+index e16dec8..306cb9b 100644
+--- a/drivers/net/mlx4/fw.h
++++ b/drivers/net/mlx4/fw.h
+@@ -96,6 +96,7 @@ struct mlx4_dev_cap {
+ 	u8  bmme_flags;
+ 	u32 reserved_lkey;
+ 	u64 max_icm_sz;
++	int max_gso_sz;
+ };
+ 
+ struct mlx4_adapter {
+diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c
+index be5d9e9..4a6c4d5 100644
+--- a/drivers/net/mlx4/intf.c
++++ b/drivers/net/mlx4/intf.c
+@@ -30,8 +30,6 @@
+  * SOFTWARE.
+  */
+ 
+-#include <linux/mlx4/driver.h>
+-
+ #include "mlx4.h"
+ 
+ struct mlx4_device_context {
+@@ -113,8 +111,7 @@ void mlx4_unregister_interface(struct mlx4_interface *intf)
+ }
+ EXPORT_SYMBOL_GPL(mlx4_unregister_interface);
+ 
+-void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type,
+-			 int subtype, int port)
++void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int port)
+ {
+ 	struct mlx4_priv *priv = mlx4_priv(dev);
+ 	struct mlx4_device_context *dev_ctx;
+@@ -124,8 +121,7 @@ void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type,
+ 
+ 	list_for_each_entry(dev_ctx, &priv->ctx_list, list)
+ 		if (dev_ctx->intf->event)
+-			dev_ctx->intf->event(dev, dev_ctx->context, type,
+-					     subtype, port);
++			dev_ctx->intf->event(dev, dev_ctx->context, type, port);
+ 
+ 	spin_unlock_irqrestore(&priv->ctx_lock, flags);
+ }
+diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
+index 08bfc13..49a4aca 100644
+--- a/drivers/net/mlx4/main.c
++++ b/drivers/net/mlx4/main.c
+@@ -76,7 +76,7 @@ static char mlx4_version[] __devinitdata =
+ 	DRV_VERSION " (" DRV_RELDATE ")\n";
+ 
+ static struct mlx4_profile default_profile = {
+-	.num_qp		= 1 << 16,
++	.num_qp		= 1 << 17,
+ 	.num_srq	= 1 << 16,
+ 	.rdmarc_per_qp	= 1 << 4,
+ 	.num_cq		= 1 << 16,
+@@ -159,6 +159,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
+ 	dev->caps.page_size_cap	     = ~(u32) (dev_cap->min_page_sz - 1);
+ 	dev->caps.flags		     = dev_cap->flags;
+ 	dev->caps.stat_rate_support  = dev_cap->stat_rate_support;
++	dev->caps.max_gso_sz	     = dev_cap->max_gso_sz;
+ 
+ 	return 0;
+ }
+@@ -735,8 +736,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	}
+ 
+ 	/*
+-	 * Check for BARs.  We expect 0: 1MB, 2: 8MB, 4: DDR (may not
+-	 * be present)
++	 * Check for BARs.  We expect 0: 1MB
+ 	 */
+ 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
+ 	    pci_resource_len(pdev, 0) != 1 << 20) {
+diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
+index a99e772..57f7f1f 100644
+--- a/drivers/net/mlx4/mcg.c
++++ b/drivers/net/mlx4/mcg.c
+@@ -190,10 +190,6 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
+ 		}
+ 		index += dev->caps.num_mgms;
+ 
+-		err = mlx4_READ_MCG(dev, index, mailbox);
+-		if (err)
+-			goto out;
+-
+ 		memset(mgm, 0, sizeof *mgm);
+ 		memcpy(mgm->gid, gid, 16);
+ 	}
+@@ -301,12 +297,10 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
+ 	mgm->qp[loc]       = mgm->qp[i - 1];
+ 	mgm->qp[i - 1]     = 0;
+ 
+-	err = mlx4_WRITE_MCG(dev, index, mailbox);
+-	if (err)
+-		goto out;
+-
+-	if (i != 1)
++	if (i != 1) {
++		err = mlx4_WRITE_MCG(dev, index, mailbox);
+ 		goto out;
++	}
+ 
+ 	if (prev == -1) {
+ 		/* Remove entry from MGM */
+diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
+index 53a1cdd..7333681 100644
+--- a/drivers/net/mlx4/mlx4.h
++++ b/drivers/net/mlx4/mlx4.h
+@@ -42,6 +42,7 @@
+ #include <linux/timer.h>
+ 
+ #include <linux/mlx4/device.h>
++#include <linux/mlx4/driver.h>
+ #include <linux/mlx4/doorbell.h>
+ 
+ #define DRV_NAME	"mlx4_core"
+@@ -313,8 +314,7 @@ void mlx4_catas_cleanup(void);
+ int mlx4_restart_one(struct pci_dev *pdev);
+ int mlx4_register_device(struct mlx4_dev *dev);
+ void mlx4_unregister_device(struct mlx4_dev *dev);
+-void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type,
+-			 int subtype, int port);
++void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int port);
+ 
+ struct mlx4_dev_cap;
+ struct mlx4_init_hca_param;
+diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
+index 771139e..381b36e 100644
+--- a/drivers/net/mv643xx_eth.c
++++ b/drivers/net/mv643xx_eth.c
+@@ -3,7 +3,8 @@
+  * Copyright (C) 2002 Matthew Dharm <mdharm at momenco.com>
+  *
+  * Based on the 64360 driver from:
+- * Copyright (C) 2002 rabeeh at galileo.co.il
++ * Copyright (C) 2002 Rabeeh Khoury <rabeeh at galileo.co.il>
++ *		      Rabeeh Khoury <rabeeh at marvell.com>
+  *
+  * Copyright (C) 2003 PMC-Sierra, Inc.,
+  *	written by Manish Lachwani
+@@ -16,6 +17,9 @@
+  * Copyright (C) 2004 Steven J. Hill <sjhill1 at rockwellcollins.com>
+  *				     <sjhill at realitydiluted.com>
+  *
++ * Copyright (C) 2007-2008 Marvell Semiconductor
++ *			   Lennert Buytenhek <buytenh at marvell.com>
++ *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+  * as published by the Free Software Foundation; either version 2
+@@ -63,20 +67,6 @@
+ #define MV643XX_TX_FAST_REFILL
+ #undef	MV643XX_COAL
+ 
+-/*
+- * Number of RX / TX descriptors on RX / TX rings.
+- * Note that allocating RX descriptors is done by allocating the RX
+- * ring AND a preallocated RX buffers (skb's) for each descriptor.
+- * The TX descriptors only allocates the TX descriptors ring,
+- * with no pre allocated TX buffers (skb's are allocated by higher layers.
+- */
+-
+-/* Default TX ring size is 1000 descriptors */
+-#define MV643XX_DEFAULT_TX_QUEUE_SIZE 1000
+-
+-/* Default RX ring size is 400 descriptors */
+-#define MV643XX_DEFAULT_RX_QUEUE_SIZE 400
+-
+ #define MV643XX_TX_COAL 100
+ #ifdef MV643XX_COAL
+ #define MV643XX_RX_COAL 100
+@@ -434,14 +424,6 @@ typedef enum _eth_func_ret_status {
+ 	ETH_QUEUE_LAST_RESOURCE	/* Ring resources about to exhaust.	*/
+ } ETH_FUNC_RET_STATUS;
+ 
+-typedef enum _eth_target {
+-	ETH_TARGET_DRAM,
+-	ETH_TARGET_DEVICE,
+-	ETH_TARGET_CBS,
+-	ETH_TARGET_PCI0,
+-	ETH_TARGET_PCI1
+-} ETH_TARGET;
+-
+ /* These are for big-endian machines.  Little endian needs different
+  * definitions.
+  */
+@@ -586,43 +568,44 @@ struct mv643xx_private {
+ 
+ /* Static function declarations */
+ static void eth_port_init(struct mv643xx_private *mp);
+-static void eth_port_reset(unsigned int eth_port_num);
++static void eth_port_reset(struct mv643xx_private *mp);
+ static void eth_port_start(struct net_device *dev);
+ 
+-static void ethernet_phy_reset(unsigned int eth_port_num);
++static void ethernet_phy_reset(struct mv643xx_private *mp);
+ 
+-static void eth_port_write_smi_reg(unsigned int eth_port_num,
++static void eth_port_write_smi_reg(struct mv643xx_private *mp,
+ 				   unsigned int phy_reg, unsigned int value);
+ 
+-static void eth_port_read_smi_reg(unsigned int eth_port_num,
++static void eth_port_read_smi_reg(struct mv643xx_private *mp,
+ 				  unsigned int phy_reg, unsigned int *value);
+ 
+-static void eth_clear_mib_counters(unsigned int eth_port_num);
++static void eth_clear_mib_counters(struct mv643xx_private *mp);
+ 
+ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
+ 					    struct pkt_info *p_pkt_info);
+ static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
+ 					      struct pkt_info *p_pkt_info);
+ 
+-static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr);
+-static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr);
++static void eth_port_uc_addr_get(struct mv643xx_private *mp,
++				 unsigned char *p_addr);
++static void eth_port_uc_addr_set(struct mv643xx_private *mp,
++				 unsigned char *p_addr);
+ static void eth_port_set_multicast_list(struct net_device *);
+-static void mv643xx_eth_port_enable_tx(unsigned int port_num,
++static void mv643xx_eth_port_enable_tx(struct mv643xx_private *mp,
+ 						unsigned int queues);
+-static void mv643xx_eth_port_enable_rx(unsigned int port_num,
++static void mv643xx_eth_port_enable_rx(struct mv643xx_private *mp,
+ 						unsigned int queues);
+-static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num);
+-static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num);
++static unsigned int mv643xx_eth_port_disable_tx(struct mv643xx_private *mp);
++static unsigned int mv643xx_eth_port_disable_rx(struct mv643xx_private *mp);
+ static int mv643xx_eth_open(struct net_device *);
+ static int mv643xx_eth_stop(struct net_device *);
+-static int mv643xx_eth_change_mtu(struct net_device *, int);
+-static void eth_port_init_mac_tables(unsigned int eth_port_num);
++static void eth_port_init_mac_tables(struct mv643xx_private *mp);
+ #ifdef MV643XX_NAPI
+ static int mv643xx_poll(struct napi_struct *napi, int budget);
+ #endif
+-static int ethernet_phy_get(unsigned int eth_port_num);
+-static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
+-static int ethernet_phy_detect(unsigned int eth_port_num);
++static int ethernet_phy_get(struct mv643xx_private *mp);
++static void ethernet_phy_set(struct mv643xx_private *mp, int phy_addr);
++static int ethernet_phy_detect(struct mv643xx_private *mp);
+ static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location);
+ static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val);
+ static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+@@ -636,12 +619,12 @@ static void __iomem *mv643xx_eth_base;
+ /* used to protect SMI_REG, which is shared across ports */
+ static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
+ 
+-static inline u32 mv_read(int offset)
++static inline u32 rdl(struct mv643xx_private *mp, int offset)
+ {
+ 	return readl(mv643xx_eth_base + offset);
+ }
+ 
+-static inline void mv_write(int offset, u32 data)
++static inline void wrl(struct mv643xx_private *mp, int offset, u32 data)
+ {
+ 	writel(data, mv643xx_eth_base + offset);
+ }
+@@ -659,18 +642,19 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
+ 		return -EINVAL;
+ 
+ 	dev->mtu = new_mtu;
++	if (!netif_running(dev))
++		return 0;
++
+ 	/*
+-	 * Stop then re-open the interface. This will allocate RX skb's with
+-	 * the new MTU.
+-	 * There is a possible danger that the open will not successed, due
+-	 * to memory is full, which might fail the open function.
++	 * Stop and then re-open the interface. This will allocate RX
++	 * skbs of the new MTU.
++	 * There is a possible danger that the open will not succeed,
++	 * due to memory being full, which might fail the open function.
+ 	 */
+-	if (netif_running(dev)) {
+-		mv643xx_eth_stop(dev);
+-		if (mv643xx_eth_open(dev))
+-			printk(KERN_ERR
+-				"%s: Fatal error on opening device\n",
+-				dev->name);
++	mv643xx_eth_stop(dev);
++	if (mv643xx_eth_open(dev)) {
++		printk(KERN_ERR "%s: Fatal error on opening device\n",
++			dev->name);
+ 	}
+ 
+ 	return 0;
+@@ -748,10 +732,9 @@ static inline void mv643xx_eth_rx_refill_descs_timer_wrapper(unsigned long data)
+ static void mv643xx_eth_update_mac_address(struct net_device *dev)
+ {
+ 	struct mv643xx_private *mp = netdev_priv(dev);
+-	unsigned int port_num = mp->port_num;
+ 
+-	eth_port_init_mac_tables(port_num);
+-	eth_port_uc_addr_set(port_num, dev->dev_addr);
++	eth_port_init_mac_tables(mp);
++	eth_port_uc_addr_set(mp, dev->dev_addr);
+ }
+ 
+ /*
+@@ -767,12 +750,12 @@ static void mv643xx_eth_set_rx_mode(struct net_device *dev)
+ 	struct mv643xx_private *mp = netdev_priv(dev);
+ 	u32 config_reg;
+ 
+-	config_reg = mv_read(PORT_CONFIG_REG(mp->port_num));
++	config_reg = rdl(mp, PORT_CONFIG_REG(mp->port_num));
+ 	if (dev->flags & IFF_PROMISC)
+ 		config_reg |= (u32) UNICAST_PROMISCUOUS_MODE;
+ 	else
+ 		config_reg &= ~(u32) UNICAST_PROMISCUOUS_MODE;
+-	mv_write(PORT_CONFIG_REG(mp->port_num), config_reg);
++	wrl(mp, PORT_CONFIG_REG(mp->port_num), config_reg);
+ 
+ 	eth_port_set_multicast_list(dev);
+ }
+@@ -826,14 +809,14 @@ static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly)
+ {
+ 	struct mv643xx_private *mp = container_of(ugly, struct mv643xx_private,
+ 						  tx_timeout_task);
+-	struct net_device *dev = mp->mii.dev; /* yuck */
++	struct net_device *dev = mp->dev;
+ 
+ 	if (!netif_running(dev))
+ 		return;
+ 
+ 	netif_stop_queue(dev);
+ 
+-	eth_port_reset(mp->port_num);
++	eth_port_reset(mp);
+ 	eth_port_start(dev);
+ 
+ 	if (mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB)
+@@ -845,7 +828,7 @@ static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly)
+  *
+  * If force is non-zero, frees uncompleted descriptors as well
+  */
+-int mv643xx_eth_free_tx_descs(struct net_device *dev, int force)
++static int mv643xx_eth_free_tx_descs(struct net_device *dev, int force)
+ {
+ 	struct mv643xx_private *mp = netdev_priv(dev);
+ 	struct eth_tx_desc *desc;
+@@ -1008,7 +991,7 @@ static void mv643xx_eth_update_pscr(struct net_device *dev,
+ 	u32 o_pscr, n_pscr;
+ 	unsigned int queues;
+ 
+-	o_pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
++	o_pscr = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
+ 	n_pscr = o_pscr;
+ 
+ 	/* clear speed, duplex and rx buffer size fields */
+@@ -1031,16 +1014,16 @@ static void mv643xx_eth_update_pscr(struct net_device *dev,
+ 
+ 	if (n_pscr != o_pscr) {
+ 		if ((o_pscr & SERIAL_PORT_ENABLE) == 0)
+-			mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
++			wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
+ 		else {
+-			queues = mv643xx_eth_port_disable_tx(port_num);
++			queues = mv643xx_eth_port_disable_tx(mp);
+ 
+ 			o_pscr &= ~SERIAL_PORT_ENABLE;
+-			mv_write(PORT_SERIAL_CONTROL_REG(port_num), o_pscr);
+-			mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
+-			mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
++			wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), o_pscr);
++			wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
++			wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
+ 			if (queues)
+-				mv643xx_eth_port_enable_tx(port_num, queues);
++				mv643xx_eth_port_enable_tx(mp, queues);
+ 		}
+ 	}
+ }
+@@ -1064,13 +1047,13 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+ 	unsigned int port_num = mp->port_num;
+ 
+ 	/* Read interrupt cause registers */
+-	eth_int_cause = mv_read(INTERRUPT_CAUSE_REG(port_num)) &
++	eth_int_cause = rdl(mp, INTERRUPT_CAUSE_REG(port_num)) &
+ 						ETH_INT_UNMASK_ALL;
+ 	if (eth_int_cause & ETH_INT_CAUSE_EXT) {
+-		eth_int_cause_ext = mv_read(
++		eth_int_cause_ext = rdl(mp,
+ 			INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
+ 						ETH_INT_UNMASK_ALL_EXT;
+-		mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num),
++		wrl(mp, INTERRUPT_CAUSE_EXTEND_REG(port_num),
+ 							~eth_int_cause_ext);
+ 	}
+ 
+@@ -1081,8 +1064,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+ 		if (mii_link_ok(&mp->mii)) {
+ 			mii_ethtool_gset(&mp->mii, &cmd);
+ 			mv643xx_eth_update_pscr(dev, &cmd);
+-			mv643xx_eth_port_enable_tx(port_num,
+-						   ETH_TX_QUEUES_ENABLED);
++			mv643xx_eth_port_enable_tx(mp, ETH_TX_QUEUES_ENABLED);
+ 			if (!netif_carrier_ok(dev)) {
+ 				netif_carrier_on(dev);
+ 				if (mp->tx_ring_size - mp->tx_desc_count >=
+@@ -1098,10 +1080,10 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+ #ifdef MV643XX_NAPI
+ 	if (eth_int_cause & ETH_INT_CAUSE_RX) {
+ 		/* schedule the NAPI poll routine to maintain port */
+-		mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
++		wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+ 
+ 		/* wait for previous write to complete */
+-		mv_read(INTERRUPT_MASK_REG(port_num));
++		rdl(mp, INTERRUPT_MASK_REG(port_num));
+ 
+ 		netif_rx_schedule(dev, &mp->napi);
+ 	}
+@@ -1136,7 +1118,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+  *	, and the required delay of the interrupt in usec.
+  *
+  * INPUT:
+- *	unsigned int eth_port_num	Ethernet port number
++ *	struct mv643xx_private *mp	Ethernet port
+  *	unsigned int t_clk		t_clk of the MV-643xx chip in HZ units
+  *	unsigned int delay		Delay in usec
+  *
+@@ -1147,15 +1129,16 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+  *	The interrupt coalescing value set in the gigE port.
+  *
+  */
+-static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
++static unsigned int eth_port_set_rx_coal(struct mv643xx_private *mp,
+ 					unsigned int t_clk, unsigned int delay)
+ {
++	unsigned int port_num = mp->port_num;
+ 	unsigned int coal = ((t_clk / 1000000) * delay) / 64;
+ 
+ 	/* Set RX Coalescing mechanism */
+-	mv_write(SDMA_CONFIG_REG(eth_port_num),
++	wrl(mp, SDMA_CONFIG_REG(port_num),
+ 		((coal & 0x3fff) << 8) |
+-		(mv_read(SDMA_CONFIG_REG(eth_port_num))
++		(rdl(mp, SDMA_CONFIG_REG(port_num))
+ 			& 0xffc000ff));
+ 
+ 	return coal;
+@@ -1174,7 +1157,7 @@ static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
+  *	MV-643xx chip and the required delay in the interrupt in uSec
+  *
+  * INPUT:
+- *	unsigned int eth_port_num	Ethernet port number
++ *	struct mv643xx_private *mp	Ethernet port
+  *	unsigned int t_clk		t_clk of the MV-643xx chip in HZ units
+  *	unsigned int delay		Delay in uSeconds
+  *
+@@ -1185,13 +1168,14 @@ static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
+  *	The interrupt coalescing value set in the gigE port.
+  *
+  */
+-static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
++static unsigned int eth_port_set_tx_coal(struct mv643xx_private *mp,
+ 					unsigned int t_clk, unsigned int delay)
+ {
+-	unsigned int coal;
+-	coal = ((t_clk / 1000000) * delay) / 64;
++	unsigned int coal = ((t_clk / 1000000) * delay) / 64;
++
+ 	/* Set TX Coalescing mechanism */
+-	mv_write(TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num), coal << 4);
++	wrl(mp, TX_FIFO_URGENT_THRESHOLD_REG(mp->port_num), coal << 4);
++
+ 	return coal;
+ }
+ 
+@@ -1327,16 +1311,15 @@ static int mv643xx_eth_open(struct net_device *dev)
+ 	int err;
+ 
+ 	/* Clear any pending ethernet port interrupts */
+-	mv_write(INTERRUPT_CAUSE_REG(port_num), 0);
+-	mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
++	wrl(mp, INTERRUPT_CAUSE_REG(port_num), 0);
++	wrl(mp, INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+ 	/* wait for previous write to complete */
+-	mv_read (INTERRUPT_CAUSE_EXTEND_REG(port_num));
++	rdl(mp, INTERRUPT_CAUSE_EXTEND_REG(port_num));
+ 
+ 	err = request_irq(dev->irq, mv643xx_eth_int_handler,
+ 			IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev);
+ 	if (err) {
+-		printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
+-								port_num);
++		printk(KERN_ERR "%s: Can not assign IRQ\n", dev->name);
+ 		return -EAGAIN;
+ 	}
+ 
+@@ -1430,17 +1413,17 @@ static int mv643xx_eth_open(struct net_device *dev)
+ 
+ #ifdef MV643XX_COAL
+ 	mp->rx_int_coal =
+-		eth_port_set_rx_coal(port_num, 133000000, MV643XX_RX_COAL);
++		eth_port_set_rx_coal(mp, 133000000, MV643XX_RX_COAL);
+ #endif
+ 
+ 	mp->tx_int_coal =
+-		eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
++		eth_port_set_tx_coal(mp, 133000000, MV643XX_TX_COAL);
+ 
+ 	/* Unmask phy and link status changes interrupts */
+-	mv_write(INTERRUPT_EXTEND_MASK_REG(port_num), ETH_INT_UNMASK_ALL_EXT);
++	wrl(mp, INTERRUPT_EXTEND_MASK_REG(port_num), ETH_INT_UNMASK_ALL_EXT);
+ 
+ 	/* Unmask RX buffer and TX end interrupt */
+-	mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
++	wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ 
+ 	return 0;
+ 
+@@ -1459,7 +1442,7 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev)
+ 	struct mv643xx_private *mp = netdev_priv(dev);
+ 
+ 	/* Stop Tx Queues */
+-	mv643xx_eth_port_disable_tx(mp->port_num);
++	mv643xx_eth_port_disable_tx(mp);
+ 
+ 	/* Free outstanding skb's on TX ring */
+ 	mv643xx_eth_free_all_tx_descs(dev);
+@@ -1477,11 +1460,10 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev)
+ static void mv643xx_eth_free_rx_rings(struct net_device *dev)
+ {
+ 	struct mv643xx_private *mp = netdev_priv(dev);
+-	unsigned int port_num = mp->port_num;
+ 	int curr;
+ 
+ 	/* Stop RX Queues */
+-	mv643xx_eth_port_disable_rx(port_num);
++	mv643xx_eth_port_disable_rx(mp);
+ 
+ 	/* Free preallocated skb's on RX rings */
+ 	for (curr = 0; mp->rx_desc_count && curr < mp->rx_ring_size; curr++) {
+@@ -1520,9 +1502,9 @@ static int mv643xx_eth_stop(struct net_device *dev)
+ 	unsigned int port_num = mp->port_num;
+ 
+ 	/* Mask all interrupts on ethernet port */
+-	mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
++	wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+ 	/* wait for previous write to complete */
+-	mv_read(INTERRUPT_MASK_REG(port_num));
++	rdl(mp, INTERRUPT_MASK_REG(port_num));
+ 
+ #ifdef MV643XX_NAPI
+ 	napi_disable(&mp->napi);
+@@ -1530,7 +1512,7 @@ static int mv643xx_eth_stop(struct net_device *dev)
+ 	netif_carrier_off(dev);
+ 	netif_stop_queue(dev);
+ 
+-	eth_port_reset(mp->port_num);
++	eth_port_reset(mp);
+ 
+ 	mv643xx_eth_free_tx_rings(dev);
+ 	mv643xx_eth_free_rx_rings(dev);
+@@ -1561,15 +1543,15 @@ static int mv643xx_poll(struct napi_struct *napi, int budget)
+ #endif
+ 
+ 	work_done = 0;
+-	if ((mv_read(RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
++	if ((rdl(mp, RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
+ 	    != (u32) mp->rx_used_desc_q)
+ 		work_done = mv643xx_eth_receive_queue(dev, budget);
+ 
+ 	if (work_done < budget) {
+ 		netif_rx_complete(dev, napi);
+-		mv_write(INTERRUPT_CAUSE_REG(port_num), 0);
+-		mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+-		mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
++		wrl(mp, INTERRUPT_CAUSE_REG(port_num), 0);
++		wrl(mp, INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
++		wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ 	}
+ 
+ 	return work_done;
+@@ -1723,7 +1705,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp,
+ 
+ 	/* ensure all descriptors are written before poking hardware */
+ 	wmb();
+-	mv643xx_eth_port_enable_tx(mp->port_num, ETH_TX_QUEUES_ENABLED);
++	mv643xx_eth_port_enable_tx(mp, ETH_TX_QUEUES_ENABLED);
+ 
+ 	mp->tx_desc_count += nr_frags + 1;
+ }
+@@ -1739,25 +1721,23 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	unsigned long flags;
+ 
+ 	BUG_ON(netif_queue_stopped(dev));
+-	BUG_ON(skb == NULL);
++
++	if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) {
++		stats->tx_dropped++;
++		printk(KERN_DEBUG "%s: failed to linearize tiny "
++				"unaligned fragment\n", dev->name);
++		return NETDEV_TX_BUSY;
++	}
++
++	spin_lock_irqsave(&mp->lock, flags);
+ 
+ 	if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
+ 		printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
+ 		netif_stop_queue(dev);
+-		return 1;
+-	}
+-
+-	if (has_tiny_unaligned_frags(skb)) {
+-		if (__skb_linearize(skb)) {
+-			stats->tx_dropped++;
+-			printk(KERN_DEBUG "%s: failed to linearize tiny "
+-					"unaligned fragment\n", dev->name);
+-			return 1;
+-		}
++		spin_unlock_irqrestore(&mp->lock, flags);
++		return NETDEV_TX_BUSY;
+ 	}
+ 
+-	spin_lock_irqsave(&mp->lock, flags);
+-
+ 	eth_tx_submit_descs_for_skb(mp, skb);
+ 	stats->tx_bytes += skb->len;
+ 	stats->tx_packets++;
+@@ -1768,7 +1748,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 	spin_unlock_irqrestore(&mp->lock, flags);
+ 
+-	return 0;		/* success */
++	return NETDEV_TX_OK;
+ }
+ 
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+@@ -1777,13 +1757,13 @@ static void mv643xx_netpoll(struct net_device *netdev)
+ 	struct mv643xx_private *mp = netdev_priv(netdev);
+ 	int port_num = mp->port_num;
+ 
+-	mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
++	wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+ 	/* wait for previous write to complete */
+-	mv_read(INTERRUPT_MASK_REG(port_num));
++	rdl(mp, INTERRUPT_MASK_REG(port_num));
+ 
+ 	mv643xx_eth_int_handler(netdev->irq, netdev);
+ 
+-	mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
++	wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ }
+ #endif
+ 
+@@ -1900,7 +1880,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
+ 	port_num = mp->port_num = pd->port_number;
+ 
+ 	/* set default config values */
+-	eth_port_uc_addr_get(port_num, dev->dev_addr);
++	eth_port_uc_addr_get(mp, dev->dev_addr);
+ 	mp->rx_ring_size = PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
+ 	mp->tx_ring_size = PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
+ 
+@@ -1908,7 +1888,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
+ 		memcpy(dev->dev_addr, pd->mac_addr, 6);
+ 
+ 	if (pd->phy_addr || pd->force_phy_addr)
+-		ethernet_phy_set(port_num, pd->phy_addr);
++		ethernet_phy_set(mp, pd->phy_addr);
+ 
+ 	if (pd->rx_queue_size)
+ 		mp->rx_ring_size = pd->rx_queue_size;
+@@ -1933,19 +1913,18 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
+ 	mp->mii.dev = dev;
+ 	mp->mii.mdio_read = mv643xx_mdio_read;
+ 	mp->mii.mdio_write = mv643xx_mdio_write;
+-	mp->mii.phy_id = ethernet_phy_get(port_num);
++	mp->mii.phy_id = ethernet_phy_get(mp);
+ 	mp->mii.phy_id_mask = 0x3f;
+ 	mp->mii.reg_num_mask = 0x1f;
+ 
+-	err = ethernet_phy_detect(port_num);
++	err = ethernet_phy_detect(mp);
+ 	if (err) {
+-		pr_debug("MV643xx ethernet port %d: "
+-					"No PHY detected at addr %d\n",
+-					port_num, ethernet_phy_get(port_num));
++		pr_debug("%s: No PHY detected at addr %d\n",
++				dev->name, ethernet_phy_get(mp));
+ 		goto out;
+ 	}
+ 
+-	ethernet_phy_reset(port_num);
++	ethernet_phy_reset(mp);
+ 	mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii);
+ 	mv643xx_init_ethtool_cmd(dev, mp->mii.phy_id, speed, duplex, &cmd);
+ 	mv643xx_eth_update_pscr(dev, &cmd);
+@@ -2006,9 +1985,11 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
+ 
+ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
+ {
++	static int mv643xx_version_printed = 0;
+ 	struct resource *res;
+ 
+-	printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
++	if (!mv643xx_version_printed++)
++		printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
+ 
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	if (res == NULL)
+@@ -2037,10 +2018,10 @@ static void mv643xx_eth_shutdown(struct platform_device *pdev)
+ 	unsigned int port_num = mp->port_num;
+ 
+ 	/* Mask all interrupts on ethernet port */
+-	mv_write(INTERRUPT_MASK_REG(port_num), 0);
+-	mv_read (INTERRUPT_MASK_REG(port_num));
++	wrl(mp, INTERRUPT_MASK_REG(port_num), 0);
++	rdl(mp, INTERRUPT_MASK_REG(port_num));
+ 
+-	eth_port_reset(port_num);
++	eth_port_reset(mp);
+ }
+ 
+ static struct platform_driver mv643xx_eth_driver = {
+@@ -2049,6 +2030,7 @@ static struct platform_driver mv643xx_eth_driver = {
+ 	.shutdown = mv643xx_eth_shutdown,
+ 	.driver = {
+ 		.name = MV643XX_ETH_NAME,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -2057,6 +2039,7 @@ static struct platform_driver mv643xx_eth_shared_driver = {
+ 	.remove = mv643xx_eth_shared_remove,
+ 	.driver = {
+ 		.name = MV643XX_ETH_SHARED_NAME,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -2104,7 +2087,8 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR(	"Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani"
+ 		" and Dale Farnsworth");
+ MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
+-MODULE_ALIAS("platform:mv643xx_eth");
++MODULE_ALIAS("platform:" MV643XX_ETH_NAME);
++MODULE_ALIAS("platform:" MV643XX_ETH_SHARED_NAME);
+ 
+ /*
+  * The second part is the low level driver of the gigE ethernet ports.
+@@ -2229,12 +2213,9 @@ MODULE_ALIAS("platform:mv643xx_eth");
+  *		return_info	Tx/Rx user resource return information.
+  */
+ 
+-/* PHY routines */
+-static int ethernet_phy_get(unsigned int eth_port_num);
+-static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
+-
+ /* Ethernet Port routines */
+-static void eth_port_set_filter_table_entry(int table, unsigned char entry);
++static void eth_port_set_filter_table_entry(struct mv643xx_private *mp,
++					    int table, unsigned char entry);
+ 
+ /*
+  * eth_port_init - Initialize the Ethernet port driver
+@@ -2264,9 +2245,9 @@ static void eth_port_init(struct mv643xx_private *mp)
+ {
+ 	mp->rx_resource_err = 0;
+ 
+-	eth_port_reset(mp->port_num);
++	eth_port_reset(mp);
+ 
+-	eth_port_init_mac_tables(mp->port_num);
++	eth_port_init_mac_tables(mp);
+ }
+ 
+ /*
+@@ -2306,28 +2287,28 @@ static void eth_port_start(struct net_device *dev)
+ 
+ 	/* Assignment of Tx CTRP of given queue */
+ 	tx_curr_desc = mp->tx_curr_desc_q;
+-	mv_write(TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
++	wrl(mp, TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ 		(u32)((struct eth_tx_desc *)mp->tx_desc_dma + tx_curr_desc));
+ 
+ 	/* Assignment of Rx CRDP of given queue */
+ 	rx_curr_desc = mp->rx_curr_desc_q;
+-	mv_write(RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
++	wrl(mp, RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ 		(u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
+ 
+ 	/* Add the assigned Ethernet address to the port's address table */
+-	eth_port_uc_addr_set(port_num, dev->dev_addr);
++	eth_port_uc_addr_set(mp, dev->dev_addr);
+ 
+ 	/* Assign port configuration and command. */
+-	mv_write(PORT_CONFIG_REG(port_num),
++	wrl(mp, PORT_CONFIG_REG(port_num),
+ 			  PORT_CONFIG_DEFAULT_VALUE);
+ 
+-	mv_write(PORT_CONFIG_EXTEND_REG(port_num),
++	wrl(mp, PORT_CONFIG_EXTEND_REG(port_num),
+ 			  PORT_CONFIG_EXTEND_DEFAULT_VALUE);
+ 
+-	pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
++	pscr = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
+ 
+ 	pscr &= ~(SERIAL_PORT_ENABLE | FORCE_LINK_PASS);
+-	mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
++	wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
+ 
+ 	pscr |= DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
+ 		DISABLE_AUTO_NEG_SPEED_GMII    |
+@@ -2335,32 +2316,34 @@ static void eth_port_start(struct net_device *dev)
+ 		DO_NOT_FORCE_LINK_FAIL	   |
+ 		SERIAL_PORT_CONTROL_RESERVED;
+ 
+-	mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
++	wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
+ 
+ 	pscr |= SERIAL_PORT_ENABLE;
+-	mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
++	wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
+ 
+ 	/* Assign port SDMA configuration */
+-	mv_write(SDMA_CONFIG_REG(port_num),
++	wrl(mp, SDMA_CONFIG_REG(port_num),
+ 			  PORT_SDMA_CONFIG_DEFAULT_VALUE);
+ 
+ 	/* Enable port Rx. */
+-	mv643xx_eth_port_enable_rx(port_num, ETH_RX_QUEUES_ENABLED);
++	mv643xx_eth_port_enable_rx(mp, ETH_RX_QUEUES_ENABLED);
+ 
+ 	/* Disable port bandwidth limits by clearing MTU register */
+-	mv_write(MAXIMUM_TRANSMIT_UNIT(port_num), 0);
++	wrl(mp, MAXIMUM_TRANSMIT_UNIT(port_num), 0);
+ 
+ 	/* save phy settings across reset */
+ 	mv643xx_get_settings(dev, &ethtool_cmd);
+-	ethernet_phy_reset(mp->port_num);
++	ethernet_phy_reset(mp);
+ 	mv643xx_set_settings(dev, &ethtool_cmd);
+ }
+ 
+ /*
+  * eth_port_uc_addr_set - Write a MAC address into the port's hw registers
+  */
+-static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr)
++static void eth_port_uc_addr_set(struct mv643xx_private *mp,
++				 unsigned char *p_addr)
+ {
++	unsigned int port_num = mp->port_num;
+ 	unsigned int mac_h;
+ 	unsigned int mac_l;
+ 	int table;
+@@ -2369,24 +2352,26 @@ static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr)
+ 	mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
+ 							(p_addr[3] << 0);
+ 
+-	mv_write(MAC_ADDR_LOW(port_num), mac_l);
+-	mv_write(MAC_ADDR_HIGH(port_num), mac_h);
++	wrl(mp, MAC_ADDR_LOW(port_num), mac_l);
++	wrl(mp, MAC_ADDR_HIGH(port_num), mac_h);
+ 
+ 	/* Accept frames with this address */
+ 	table = DA_FILTER_UNICAST_TABLE_BASE(port_num);
+-	eth_port_set_filter_table_entry(table, p_addr[5] & 0x0f);
++	eth_port_set_filter_table_entry(mp, table, p_addr[5] & 0x0f);
+ }
+ 
+ /*
+  * eth_port_uc_addr_get - Read the MAC address from the port's hw registers
+  */
+-static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr)
++static void eth_port_uc_addr_get(struct mv643xx_private *mp,
++				 unsigned char *p_addr)
+ {
++	unsigned int port_num = mp->port_num;
+ 	unsigned int mac_h;
+ 	unsigned int mac_l;
+ 
+-	mac_h = mv_read(MAC_ADDR_HIGH(port_num));
+-	mac_l = mv_read(MAC_ADDR_LOW(port_num));
++	mac_h = rdl(mp, MAC_ADDR_HIGH(port_num));
++	mac_l = rdl(mp, MAC_ADDR_LOW(port_num));
+ 
+ 	p_addr[0] = (mac_h >> 24) & 0xff;
+ 	p_addr[1] = (mac_h >> 16) & 0xff;
+@@ -2405,7 +2390,8 @@ static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr)
+  *	3-1	Queue			(ETH_Q0=0)
+  *	7-4	Reserved = 0;
+  */
+-static void eth_port_set_filter_table_entry(int table, unsigned char entry)
++static void eth_port_set_filter_table_entry(struct mv643xx_private *mp,
++					    int table, unsigned char entry)
+ {
+ 	unsigned int table_reg;
+ 	unsigned int tbl_offset;
+@@ -2415,9 +2401,9 @@ static void eth_port_set_filter_table_entry(int table, unsigned char entry)
+ 	reg_offset = entry % 4;		/* Entry offset within the register */
+ 
+ 	/* Set "accepts frame bit" at specified table entry */
+-	table_reg = mv_read(table + tbl_offset);
++	table_reg = rdl(mp, table + tbl_offset);
+ 	table_reg |= 0x01 << (8 * reg_offset);
+-	mv_write(table + tbl_offset, table_reg);
++	wrl(mp, table + tbl_offset, table_reg);
+ }
+ 
+ /*
+@@ -2434,8 +2420,9 @@ static void eth_port_set_filter_table_entry(int table, unsigned char entry)
+  * In either case, eth_port_set_filter_table_entry() is then called
+  * to set to set the actual table entry.
+  */
+-static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
++static void eth_port_mc_addr(struct mv643xx_private *mp, unsigned char *p_addr)
+ {
++	unsigned int port_num = mp->port_num;
+ 	unsigned int mac_h;
+ 	unsigned int mac_l;
+ 	unsigned char crc_result = 0;
+@@ -2446,9 +2433,8 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
+ 
+ 	if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) &&
+ 	    (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) {
+-		table = DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+-					(eth_port_num);
+-		eth_port_set_filter_table_entry(table, p_addr[5]);
++		table = DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port_num);
++		eth_port_set_filter_table_entry(mp, table, p_addr[5]);
+ 		return;
+ 	}
+ 
+@@ -2520,8 +2506,8 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
+ 	for (i = 0; i < 8; i++)
+ 		crc_result = crc_result | (crc[i] << i);
+ 
+-	table = DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
+-	eth_port_set_filter_table_entry(table, crc_result);
++	table = DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port_num);
++	eth_port_set_filter_table_entry(mp, table, crc_result);
+ }
+ 
+ /*
+@@ -2550,7 +2536,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ 			 * 3-1  Queue	 ETH_Q0=0
+ 			 * 7-4  Reserved = 0;
+ 			 */
+-			mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
++			wrl(mp, DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ 
+ 			/* Set all entries in DA filter other multicast
+ 			 * table (Ex_dFOMT)
+@@ -2560,7 +2546,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ 			 * 3-1  Queue	 ETH_Q0=0
+ 			 * 7-4  Reserved = 0;
+ 			 */
+-			mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
++			wrl(mp, DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ 		}
+ 		return;
+ 	}
+@@ -2570,11 +2556,11 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ 	 */
+ 	for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ 		/* Clear DA filter special multicast table (Ex_dFSMT) */
+-		mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
++		wrl(mp, DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ 				(eth_port_num) + table_index, 0);
+ 
+ 		/* Clear DA filter other multicast table (Ex_dFOMT) */
+-		mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
++		wrl(mp, DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ 				(eth_port_num) + table_index, 0);
+ 	}
+ 
+@@ -2583,7 +2569,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ 			(i < 256) && (mc_list != NULL) && (i < dev->mc_count);
+ 			i++, mc_list = mc_list->next)
+ 		if (mc_list->dmi_addrlen == 6)
+-			eth_port_mc_addr(eth_port_num, mc_list->dmi_addr);
++			eth_port_mc_addr(mp, mc_list->dmi_addr);
+ }
+ 
+ /*
+@@ -2594,7 +2580,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+  *	Other Multicast) and set each entry to 0.
+  *
+  * INPUT:
+- *	unsigned int	eth_port_num	Ethernet Port number.
++ *	struct mv643xx_private *mp	Ethernet Port.
+  *
+  * OUTPUT:
+  *	Multicast and Unicast packets are rejected.
+@@ -2602,22 +2588,23 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+  * RETURN:
+  *	None.
+  */
+-static void eth_port_init_mac_tables(unsigned int eth_port_num)
++static void eth_port_init_mac_tables(struct mv643xx_private *mp)
+ {
++	unsigned int port_num = mp->port_num;
+ 	int table_index;
+ 
+ 	/* Clear DA filter unicast table (Ex_dFUT) */
+ 	for (table_index = 0; table_index <= 0xC; table_index += 4)
+-		mv_write(DA_FILTER_UNICAST_TABLE_BASE
+-					(eth_port_num) + table_index, 0);
++		wrl(mp, DA_FILTER_UNICAST_TABLE_BASE(port_num) +
++					table_index, 0);
+ 
+ 	for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ 		/* Clear DA filter special multicast table (Ex_dFSMT) */
+-		mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+-					(eth_port_num) + table_index, 0);
++		wrl(mp, DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port_num) +
++					table_index, 0);
+ 		/* Clear DA filter other multicast table (Ex_dFOMT) */
+-		mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+-					(eth_port_num) + table_index, 0);
++		wrl(mp, DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port_num) +
++					table_index, 0);
+ 	}
+ }
+ 
+@@ -2629,7 +2616,7 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
+  *	A read from the MIB counter will reset the counter.
+  *
+  * INPUT:
+- *	unsigned int	eth_port_num	Ethernet Port number.
++ *	struct mv643xx_private *mp	Ethernet Port.
+  *
+  * OUTPUT:
+  *	After reading all MIB counters, the counters resets.
+@@ -2638,19 +2625,20 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
+  *	MIB counter value.
+  *
+  */
+-static void eth_clear_mib_counters(unsigned int eth_port_num)
++static void eth_clear_mib_counters(struct mv643xx_private *mp)
+ {
++	unsigned int port_num = mp->port_num;
+ 	int i;
+ 
+ 	/* Perform dummy reads from MIB counters */
+ 	for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION;
+ 									i += 4)
+-		mv_read(MIB_COUNTERS_BASE(eth_port_num) + i);
++		rdl(mp, MIB_COUNTERS_BASE(port_num) + i);
+ }
+ 
+ static inline u32 read_mib(struct mv643xx_private *mp, int offset)
+ {
+-	return mv_read(MIB_COUNTERS_BASE(mp->port_num) + offset);
++	return rdl(mp, MIB_COUNTERS_BASE(mp->port_num) + offset);
+ }
+ 
+ static void eth_update_mib_counters(struct mv643xx_private *mp)
+@@ -2686,7 +2674,7 @@ static void eth_update_mib_counters(struct mv643xx_private *mp)
+  *	the specified port.
+  *
+  * INPUT:
+- *	unsigned int	eth_port_num	Ethernet Port number.
++ *	struct mv643xx_private *mp	Ethernet Port.
+  *
+  * OUTPUT:
+  *	None
+@@ -2696,22 +2684,22 @@ static void eth_update_mib_counters(struct mv643xx_private *mp)
+  *	-ENODEV on failure
+  *
+  */
+-static int ethernet_phy_detect(unsigned int port_num)
++static int ethernet_phy_detect(struct mv643xx_private *mp)
+ {
+ 	unsigned int phy_reg_data0;
+ 	int auto_neg;
+ 
+-	eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
++	eth_port_read_smi_reg(mp, 0, &phy_reg_data0);
+ 	auto_neg = phy_reg_data0 & 0x1000;
+ 	phy_reg_data0 ^= 0x1000;	/* invert auto_neg */
+-	eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
++	eth_port_write_smi_reg(mp, 0, phy_reg_data0);
+ 
+-	eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
++	eth_port_read_smi_reg(mp, 0, &phy_reg_data0);
+ 	if ((phy_reg_data0 & 0x1000) == auto_neg)
+ 		return -ENODEV;				/* change didn't take */
+ 
+ 	phy_reg_data0 ^= 0x1000;
+-	eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
++	eth_port_write_smi_reg(mp, 0, phy_reg_data0);
+ 	return 0;
+ }
+ 
+@@ -2722,7 +2710,7 @@ static int ethernet_phy_detect(unsigned int port_num)
+  *	This routine returns the given ethernet port PHY address.
+  *
+  * INPUT:
+- *	unsigned int	eth_port_num	Ethernet Port number.
++ *	struct mv643xx_private *mp	Ethernet Port.
+  *
+  * OUTPUT:
+  *	None.
+@@ -2731,13 +2719,13 @@ static int ethernet_phy_detect(unsigned int port_num)
+  *	PHY address.
+  *
+  */
+-static int ethernet_phy_get(unsigned int eth_port_num)
++static int ethernet_phy_get(struct mv643xx_private *mp)
+ {
+ 	unsigned int reg_data;
+ 
+-	reg_data = mv_read(PHY_ADDR_REG);
++	reg_data = rdl(mp, PHY_ADDR_REG);
+ 
+-	return ((reg_data >> (5 * eth_port_num)) & 0x1f);
++	return ((reg_data >> (5 * mp->port_num)) & 0x1f);
+ }
+ 
+ /*
+@@ -2747,7 +2735,7 @@ static int ethernet_phy_get(unsigned int eth_port_num)
+  *	This routine sets the given ethernet port PHY address.
+  *
+  * INPUT:
+- *	unsigned int	eth_port_num	Ethernet Port number.
++ *	struct mv643xx_private *mp	Ethernet Port.
+  *	int		phy_addr	PHY address.
+  *
+  * OUTPUT:
+@@ -2757,15 +2745,15 @@ static int ethernet_phy_get(unsigned int eth_port_num)
+  *	None.
+  *
+  */
+-static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
++static void ethernet_phy_set(struct mv643xx_private *mp, int phy_addr)
+ {
+ 	u32 reg_data;
+-	int addr_shift = 5 * eth_port_num;
++	int addr_shift = 5 * mp->port_num;
+ 
+-	reg_data = mv_read(PHY_ADDR_REG);
++	reg_data = rdl(mp, PHY_ADDR_REG);
+ 	reg_data &= ~(0x1f << addr_shift);
+ 	reg_data |= (phy_addr & 0x1f) << addr_shift;
+-	mv_write(PHY_ADDR_REG, reg_data);
++	wrl(mp, PHY_ADDR_REG, reg_data);
+ }
+ 
+ /*
+@@ -2775,7 +2763,7 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
+  *	This routine utilizes the SMI interface to reset the ethernet port PHY.
+  *
+  * INPUT:
+- *	unsigned int	eth_port_num	Ethernet Port number.
++ *	struct mv643xx_private *mp	Ethernet Port.
+  *
+  * OUTPUT:
+  *	The PHY is reset.
+@@ -2784,51 +2772,52 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
+  *	None.
+  *
+  */
+-static void ethernet_phy_reset(unsigned int eth_port_num)
++static void ethernet_phy_reset(struct mv643xx_private *mp)
+ {
+ 	unsigned int phy_reg_data;
+ 
+ 	/* Reset the PHY */
+-	eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
++	eth_port_read_smi_reg(mp, 0, &phy_reg_data);
+ 	phy_reg_data |= 0x8000;	/* Set bit 15 to reset the PHY */
+-	eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
++	eth_port_write_smi_reg(mp, 0, phy_reg_data);
+ 
+ 	/* wait for PHY to come out of reset */
+ 	do {
+ 		udelay(1);
+-		eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
++		eth_port_read_smi_reg(mp, 0, &phy_reg_data);
+ 	} while (phy_reg_data & 0x8000);
+ }
+ 
+-static void mv643xx_eth_port_enable_tx(unsigned int port_num,
++static void mv643xx_eth_port_enable_tx(struct mv643xx_private *mp,
+ 					unsigned int queues)
+ {
+-	mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), queues);
++	wrl(mp, TRANSMIT_QUEUE_COMMAND_REG(mp->port_num), queues);
+ }
+ 
+-static void mv643xx_eth_port_enable_rx(unsigned int port_num,
++static void mv643xx_eth_port_enable_rx(struct mv643xx_private *mp,
+ 					unsigned int queues)
+ {
+-	mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), queues);
++	wrl(mp, RECEIVE_QUEUE_COMMAND_REG(mp->port_num), queues);
+ }
+ 
+-static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
++static unsigned int mv643xx_eth_port_disable_tx(struct mv643xx_private *mp)
+ {
++	unsigned int port_num = mp->port_num;
+ 	u32 queues;
+ 
+ 	/* Stop Tx port activity. Check port Tx activity. */
+-	queues = mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF;
++	queues = rdl(mp, TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF;
+ 	if (queues) {
+ 		/* Issue stop command for active queues only */
+-		mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), (queues << 8));
++		wrl(mp, TRANSMIT_QUEUE_COMMAND_REG(port_num), (queues << 8));
+ 
+ 		/* Wait for all Tx activity to terminate. */
+ 		/* Check port cause register that all Tx queues are stopped */
+-		while (mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF)
++		while (rdl(mp, TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF)
+ 			udelay(PHY_WAIT_MICRO_SECONDS);
+ 
+ 		/* Wait for Tx FIFO to empty */
+-		while (mv_read(PORT_STATUS_REG(port_num)) &
++		while (rdl(mp, PORT_STATUS_REG(port_num)) &
+ 							ETH_PORT_TX_FIFO_EMPTY)
+ 			udelay(PHY_WAIT_MICRO_SECONDS);
+ 	}
+@@ -2836,19 +2825,20 @@ static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
+ 	return queues;
+ }
+ 
+-static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
++static unsigned int mv643xx_eth_port_disable_rx(struct mv643xx_private *mp)
+ {
++	unsigned int port_num = mp->port_num;
+ 	u32 queues;
+ 
+ 	/* Stop Rx port activity. Check port Rx activity. */
+-	queues = mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF;
++	queues = rdl(mp, RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF;
+ 	if (queues) {
+ 		/* Issue stop command for active queues only */
+-		mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), (queues << 8));
++		wrl(mp, RECEIVE_QUEUE_COMMAND_REG(port_num), (queues << 8));
+ 
+ 		/* Wait for all Rx activity to terminate. */
+ 		/* Check port cause register that all Rx queues are stopped */
+-		while (mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF)
++		while (rdl(mp, RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF)
+ 			udelay(PHY_WAIT_MICRO_SECONDS);
+ 	}
+ 
+@@ -2864,7 +2854,7 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
+  *	idle state after this command is performed and the port is disabled.
+  *
+  * INPUT:
+- *	unsigned int	eth_port_num	Ethernet Port number.
++ *	struct mv643xx_private *mp	Ethernet Port.
+  *
+  * OUTPUT:
+  *	Channel activity is halted.
+@@ -2873,22 +2863,23 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
+  *	None.
+  *
+  */
+-static void eth_port_reset(unsigned int port_num)
++static void eth_port_reset(struct mv643xx_private *mp)
+ {
++	unsigned int port_num = mp->port_num;
+ 	unsigned int reg_data;
+ 
+-	mv643xx_eth_port_disable_tx(port_num);
+-	mv643xx_eth_port_disable_rx(port_num);
++	mv643xx_eth_port_disable_tx(mp);
++	mv643xx_eth_port_disable_rx(mp);
+ 
+ 	/* Clear all MIB counters */
+-	eth_clear_mib_counters(port_num);
++	eth_clear_mib_counters(mp);
+ 
+ 	/* Reset the Enable bit in the Configuration Register */
+-	reg_data = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
++	reg_data = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
+ 	reg_data &= ~(SERIAL_PORT_ENABLE		|
+ 			DO_NOT_FORCE_LINK_FAIL	|
+ 			FORCE_LINK_PASS);
+-	mv_write(PORT_SERIAL_CONTROL_REG(port_num), reg_data);
++	wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), reg_data);
+ }
+ 
+ 
+@@ -2900,7 +2891,7 @@ static void eth_port_reset(unsigned int port_num)
+  *	order to perform PHY register read.
+  *
+  * INPUT:
+- *	unsigned int	port_num	Ethernet Port number.
++ *	struct mv643xx_private *mp	Ethernet Port.
+  *	unsigned int	phy_reg		PHY register address offset.
+  *	unsigned int	*value		Register value buffer.
+  *
+@@ -2912,10 +2903,10 @@ static void eth_port_reset(unsigned int port_num)
+  *	true otherwise.
+  *
+  */
+-static void eth_port_read_smi_reg(unsigned int port_num,
++static void eth_port_read_smi_reg(struct mv643xx_private *mp,
+ 				unsigned int phy_reg, unsigned int *value)
+ {
+-	int phy_addr = ethernet_phy_get(port_num);
++	int phy_addr = ethernet_phy_get(mp);
+ 	unsigned long flags;
+ 	int i;
+ 
+@@ -2923,27 +2914,27 @@ static void eth_port_read_smi_reg(unsigned int port_num,
+ 	spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
+ 
+ 	/* wait for the SMI register to become available */
+-	for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
++	for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) {
+ 		if (i == PHY_WAIT_ITERATIONS) {
+-			printk("mv643xx PHY busy timeout, port %d\n", port_num);
++			printk("%s: PHY busy timeout\n", mp->dev->name);
+ 			goto out;
+ 		}
+ 		udelay(PHY_WAIT_MICRO_SECONDS);
+ 	}
+ 
+-	mv_write(SMI_REG,
++	wrl(mp, SMI_REG,
+ 		(phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
+ 
+ 	/* now wait for the data to be valid */
+-	for (i = 0; !(mv_read(SMI_REG) & ETH_SMI_READ_VALID); i++) {
++	for (i = 0; !(rdl(mp, SMI_REG) & ETH_SMI_READ_VALID); i++) {
+ 		if (i == PHY_WAIT_ITERATIONS) {
+-			printk("mv643xx PHY read timeout, port %d\n", port_num);
++			printk("%s: PHY read timeout\n", mp->dev->name);
+ 			goto out;
+ 		}
+ 		udelay(PHY_WAIT_MICRO_SECONDS);
+ 	}
+ 
+-	*value = mv_read(SMI_REG) & 0xffff;
++	*value = rdl(mp, SMI_REG) & 0xffff;
+ out:
+ 	spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
+ }
+@@ -2956,7 +2947,7 @@ out:
+  *	order to perform writes to PHY registers.
+  *
+  * INPUT:
+- *	unsigned int	eth_port_num	Ethernet Port number.
++ *	struct mv643xx_private *mp	Ethernet Port.
+  *	unsigned int	phy_reg		PHY register address offset.
+  *	unsigned int	value		Register value.
+  *
+@@ -2968,29 +2959,28 @@ out:
+  *	true otherwise.
+  *
+  */
+-static void eth_port_write_smi_reg(unsigned int eth_port_num,
++static void eth_port_write_smi_reg(struct mv643xx_private *mp,
+ 				   unsigned int phy_reg, unsigned int value)
+ {
+ 	int phy_addr;
+ 	int i;
+ 	unsigned long flags;
+ 
+-	phy_addr = ethernet_phy_get(eth_port_num);
++	phy_addr = ethernet_phy_get(mp);
+ 
+ 	/* the SMI register is a shared resource */
+ 	spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
+ 
+ 	/* wait for the SMI register to become available */
+-	for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
++	for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) {
+ 		if (i == PHY_WAIT_ITERATIONS) {
+-			printk("mv643xx PHY busy timeout, port %d\n",
+-								eth_port_num);
++			printk("%s: PHY busy timeout\n", mp->dev->name);
+ 			goto out;
+ 		}
+ 		udelay(PHY_WAIT_MICRO_SECONDS);
+ 	}
+ 
+-	mv_write(SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
++	wrl(mp, SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
+ 				ETH_SMI_OPCODE_WRITE | (value & 0xffff));
+ out:
+ 	spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
+@@ -3001,17 +2991,17 @@ out:
+  */
+ static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location)
+ {
+-	int val;
+ 	struct mv643xx_private *mp = netdev_priv(dev);
++	int val;
+ 
+-	eth_port_read_smi_reg(mp->port_num, location, &val);
++	eth_port_read_smi_reg(mp, location, &val);
+ 	return val;
+ }
+ 
+ static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val)
+ {
+ 	struct mv643xx_private *mp = netdev_priv(dev);
+-	eth_port_write_smi_reg(mp->port_num, location, val);
++	eth_port_write_smi_reg(mp, location, val);
+ }
+ 
+ /*
+@@ -3156,7 +3146,7 @@ struct mv643xx_stats {
+ 	int stat_offset;
+ };
+ 
+-#define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \
++#define MV643XX_STAT(m) FIELD_SIZEOF(struct mv643xx_private, m), \
+ 					offsetof(struct mv643xx_private, m)
+ 
+ static const struct mv643xx_stats mv643xx_gstrings_stats[] = {
+diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
+index 385f69c..46119bb 100644
+--- a/drivers/net/natsemi.c
++++ b/drivers/net/natsemi.c
+@@ -511,10 +511,10 @@ enum PhyCtrl_bits {
+ /* Note that using only 32 bit fields simplifies conversion to big-endian
+    architectures. */
+ struct netdev_desc {
+-	u32 next_desc;
+-	s32 cmd_status;
+-	u32 addr;
+-	u32 software_use;
++	__le32 next_desc;
++	__le32 cmd_status;
++	__le32 addr;
++	__le32 software_use;
+ };
+ 
+ /* Bits in network_desc.status */
+@@ -786,7 +786,8 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
+ 	struct netdev_private *np;
+ 	int i, option, irq, chip_idx = ent->driver_data;
+ 	static int find_cnt = -1;
+-	unsigned long iostart, iosize;
++	resource_size_t iostart;
++	unsigned long iosize;
+ 	void __iomem *ioaddr;
+ 	const int pcibar = 1; /* PCI base address register */
+ 	int prev_eedata;
+@@ -946,10 +947,11 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
+ 		goto err_create_file;
+ 
+ 	if (netif_msg_drv(np)) {
+-		printk(KERN_INFO "natsemi %s: %s at %#08lx "
++		printk(KERN_INFO "natsemi %s: %s at %#08llx "
+ 		       "(%s), %s, IRQ %d",
+-		       dev->name, natsemi_pci_info[chip_idx].name, iostart,
+-		       pci_name(np->pci_dev), print_mac(mac, dev->dev_addr), irq);
++		       dev->name, natsemi_pci_info[chip_idx].name,
++		       (unsigned long long)iostart, pci_name(np->pci_dev),
++		       print_mac(mac, dev->dev_addr), irq);
+ 		if (dev->if_port == PORT_TP)
+ 			printk(", port TP.\n");
+ 		else if (np->ignore_phy)
+@@ -2018,7 +2020,7 @@ static void drain_rx(struct net_device *dev)
+ 	/* Free all the skbuffs in the Rx queue. */
+ 	for (i = 0; i < RX_RING_SIZE; i++) {
+ 		np->rx_ring[i].cmd_status = 0;
+-		np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
++		np->rx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */
+ 		if (np->rx_skbuff[i]) {
+ 			pci_unmap_single(np->pci_dev,
+ 				np->rx_dma[i], buflen,
+diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
+index 78d34af..dc442e3 100644
+--- a/drivers/net/netx-eth.c
++++ b/drivers/net/netx-eth.c
+@@ -502,4 +502,4 @@ module_exit(netx_eth_cleanup);
+ 
+ MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+ MODULE_LICENSE("GPL");
+-
++MODULE_ALIAS("platform:" CARDNAME);
+diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
+index 7f20a03..8cb29f5 100644
+--- a/drivers/net/netxen/netxen_nic.h
++++ b/drivers/net/netxen/netxen_nic.h
+@@ -95,23 +95,6 @@
+ 
+ #define ADDR_IN_WINDOW1(off)	\
+ 	((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0
+-/*
+- * In netxen_nic_down(), we must wait for any pending callback requests into
+- * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be
+- * reenabled right after it is deleted in netxen_nic_down(). FLUSH_SCHEDULED_WORK()
+- * does this synchronization.
+- *
+- * Normally, schedule_work()/flush_scheduled_work() could have worked, but
+- * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off()
+- * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a
+- * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause
+- * linkwatch_event() to be executed which also attempts to acquire the rtnl
+- * lock thus causing a deadlock.
+- */
+-
+-#define SCHEDULE_WORK(tp)	queue_work(netxen_workq, tp)
+-#define FLUSH_SCHEDULED_WORK()	flush_workqueue(netxen_workq)
+-extern struct workqueue_struct *netxen_workq;
+ 
+ /*
+  * normalize a 64MB crb address to 32MB PCI window
+@@ -1050,7 +1033,6 @@ void netxen_halt_pegs(struct netxen_adapter *adapter);
+ int netxen_rom_se(struct netxen_adapter *adapter, int addr);
+ 
+ /* Functions from netxen_nic_isr.c */
+-int netxen_nic_link_ok(struct netxen_adapter *adapter);
+ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter);
+ void netxen_initialize_adapter_hw(struct netxen_adapter *adapter);
+ void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
+diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
+index 160f605..24d027e 100644
+--- a/drivers/net/netxen/netxen_nic_hdr.h
++++ b/drivers/net/netxen/netxen_nic_hdr.h
+@@ -34,7 +34,6 @@
+ #include <linux/kernel.h>
+ #include <linux/version.h>
+ 
+-#include <asm/semaphore.h>
+ #include <linux/spinlock.h>
+ #include <asm/irq.h>
+ #include <linux/init.h>
+diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
+index 05748ca..af73564 100644
+--- a/drivers/net/netxen/netxen_nic_hw.c
++++ b/drivers/net/netxen/netxen_nic_hw.c
+@@ -1132,8 +1132,8 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
+ 	u32 fw_minor = 0;
+ 	u32 fw_build = 0;
+ 	char brd_name[NETXEN_MAX_SHORT_NAME];
+-	struct netxen_new_user_info user_info;
+-	int i, addr = NETXEN_USER_START;
++	char serial_num[32];
++	int i, addr;
+ 	__le32 *ptr32;
+ 
+ 	struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
+@@ -1150,10 +1150,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
+ 		valid = 0;
+ 	}
+ 	if (valid) {
+-		ptr32 = (u32 *) & user_info;
+-		for (i = 0;
+-		     i < sizeof(struct netxen_new_user_info) / sizeof(u32);
+-		     i++) {
++		ptr32 = (u32 *)&serial_num;
++		addr = NETXEN_USER_START +
++		       offsetof(struct netxen_new_user_info, serial_num);
++		for (i = 0; i < 8; i++) {
+ 			if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
+ 				printk("%s: ERROR reading %s board userarea.\n",
+ 				       netxen_nic_driver_name,
+@@ -1163,10 +1163,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
+ 			ptr32++;
+ 			addr += sizeof(u32);
+ 		}
++
+ 		get_brd_name_by_type(board_info->board_type, brd_name);
+ 
+ 		printk("NetXen %s Board S/N %s  Chip id 0x%x\n",
+-		       brd_name, user_info.serial_num, board_info->chip_id);
++		       brd_name, serial_num, board_info->chip_id);
+ 
+ 		printk("NetXen %s Board #%d, Chip id 0x%x\n",
+ 		       board_info->board_type == 0x0b ? "XGB" : "GBE",
+diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
+index c81313b..f487615 100644
+--- a/drivers/net/netxen/netxen_nic_isr.c
++++ b/drivers/net/netxen/netxen_nic_isr.c
+@@ -172,6 +172,7 @@ void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
+ 	netxen_nic_isr_other(adapter);
+ }
+ 
++#if 0
+ int netxen_nic_link_ok(struct netxen_adapter *adapter)
+ {
+ 	switch (adapter->ahw.board_type) {
+@@ -189,6 +190,7 @@ int netxen_nic_link_ok(struct netxen_adapter *adapter)
+ 
+ 	return 0;
+ }
++#endif  /*  0  */
+ 
+ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
+ {
+diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
+index a8fb439..7144c25 100644
+--- a/drivers/net/netxen/netxen_nic_main.c
++++ b/drivers/net/netxen/netxen_nic_main.c
+@@ -86,7 +86,24 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
+ 
+ MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
+ 
+-struct workqueue_struct *netxen_workq;
++/*
++ * In netxen_nic_down(), we must wait for any pending callback requests into
++ * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be
++ * reenabled right after it is deleted in netxen_nic_down().
++ * FLUSH_SCHEDULED_WORK()  does this synchronization.
++ *
++ * Normally, schedule_work()/flush_scheduled_work() could have worked, but
++ * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off()
++ * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a
++ * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause
++ * linkwatch_event() to be executed which also attempts to acquire the rtnl
++ * lock thus causing a deadlock.
++ */
++
++static struct workqueue_struct *netxen_workq;
++#define SCHEDULE_WORK(tp)	queue_work(netxen_workq, tp)
++#define FLUSH_SCHEDULED_WORK()	flush_workqueue(netxen_workq)
++
+ static void netxen_watchdog(unsigned long);
+ 
+ static void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
+index 26aa8fe..a316dcc 100644
+--- a/drivers/net/ni52.c
++++ b/drivers/net/ni52.c
+@@ -134,10 +134,10 @@ static int fifo = 0x8;	/* don't change */
+ #define ni_disint()   { outb(0, dev->base_addr + NI52_INTDIS); }
+ #define ni_enaint()   { outb(0, dev->base_addr + NI52_INTENA); }
+ 
+-#define make32(ptr16) (p->memtop + (short) (ptr16))
+-#define make24(ptr32) ((unsigned long)(ptr32)) - p->base
+-#define make16(ptr32) ((unsigned short) ((unsigned long)(ptr32)\
+-					- (unsigned long) p->memtop))
++#define make32(ptr16) ((void __iomem *)(p->memtop + (short) (ptr16)))
++#define make24(ptr32) ((char __iomem *)(ptr32)) - p->base
++#define make16(ptr32) ((unsigned short) ((char __iomem *)(ptr32)\
++					- p->memtop))
+ 
+ /******************* how to calculate the buffers *****************************
+ 
+@@ -179,34 +179,35 @@ static void    ni52_timeout(struct net_device *dev);
+ 
+ /* helper-functions */
+ static int     init586(struct net_device *dev);
+-static int     check586(struct net_device *dev, char *where, unsigned size);
++static int     check586(struct net_device *dev, unsigned size);
+ static void    alloc586(struct net_device *dev);
+ static void    startrecv586(struct net_device *dev);
+-static void   *alloc_rfa(struct net_device *dev, void *ptr);
++static void   __iomem *alloc_rfa(struct net_device *dev, void __iomem *ptr);
+ static void    ni52_rcv_int(struct net_device *dev);
+ static void    ni52_xmt_int(struct net_device *dev);
+ static void    ni52_rnr_int(struct net_device *dev);
+ 
+ struct priv {
+ 	struct net_device_stats stats;
+-	unsigned long base;
+-	char *memtop;
++	char __iomem *base;
++	char __iomem *mapped;
++	char __iomem *memtop;
+ 	spinlock_t spinlock;
+ 	int reset;
+-	struct rfd_struct *rfd_last, *rfd_top, *rfd_first;
+-	struct scp_struct *scp;
+-	struct iscp_struct *iscp;
+-	struct scb_struct *scb;
+-	struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS];
++	struct rfd_struct __iomem *rfd_last, *rfd_top, *rfd_first;
++	struct scp_struct __iomem *scp;
++	struct iscp_struct __iomem *iscp;
++	struct scb_struct __iomem *scb;
++	struct tbd_struct __iomem *xmit_buffs[NUM_XMIT_BUFFS];
+ #if (NUM_XMIT_BUFFS == 1)
+-	struct transmit_cmd_struct *xmit_cmds[2];
+-	struct nop_cmd_struct *nop_cmds[2];
++	struct transmit_cmd_struct __iomem *xmit_cmds[2];
++	struct nop_cmd_struct __iomem *nop_cmds[2];
+ #else
+-	struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
+-	struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
++	struct transmit_cmd_struct __iomem *xmit_cmds[NUM_XMIT_BUFFS];
++	struct nop_cmd_struct __iomem *nop_cmds[NUM_XMIT_BUFFS];
+ #endif
+ 	int nop_point, num_recv_buffs;
+-	char *xmit_cbuffs[NUM_XMIT_BUFFS];
++	char __iomem *xmit_cbuffs[NUM_XMIT_BUFFS];
+ 	int xmit_count, xmit_last;
+ };
+ 
+@@ -240,7 +241,8 @@ static void wait_for_scb_cmd_ruc(struct net_device *dev)
+ 		udelay(4);
+ 		if (i == 16383) {
+ 			printk(KERN_ERR "%s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!!\n",
+-				dev->name, p->scb->cmd_ruc, p->scb->rus);
++				dev->name, readb(&p->scb->cmd_ruc),
++				readb(&p->scb->rus));
+ 			if (!p->reset) {
+ 				p->reset = 1;
+ 				ni_reset586();
+@@ -249,9 +251,9 @@ static void wait_for_scb_cmd_ruc(struct net_device *dev)
+ 	}
+ }
+ 
+-static void wait_for_stat_compl(void *p)
++static void wait_for_stat_compl(void __iomem *p)
+ {
+-	struct nop_cmd_struct *addr = p;
++	struct nop_cmd_struct __iomem *addr = p;
+ 	int i;
+ 	for (i = 0; i < 32767; i++) {
+ 		if (readw(&((addr)->cmd_status)) & STAT_COMPL)
+@@ -293,47 +295,58 @@ static int ni52_open(struct net_device *dev)
+ 	return 0; /* most done by init */
+ }
+ 
++static int check_iscp(struct net_device *dev, void __iomem *addr)
++{
++	struct iscp_struct __iomem *iscp = addr;
++	struct priv *p = dev->priv;
++	memset_io(iscp, 0, sizeof(struct iscp_struct));
++
++	writel(make24(iscp), &p->scp->iscp);
++	writeb(1, &iscp->busy);
++
++	ni_reset586();
++	ni_attn586();
++	mdelay(32);	/* wait a while... */
++	/* i82586 clears 'busy' after successful init */
++	if (readb(&iscp->busy))
++		return 0;
++	return 1;
++}
++
+ /**********************************************
+  * Check to see if there's an 82586 out there.
+  */
+-static int check586(struct net_device *dev, char *where, unsigned size)
++static int check586(struct net_device *dev, unsigned size)
+ {
+-	struct priv pb;
+-	struct priv *p = /* (struct priv *) dev->priv*/ &pb;
+-	char *iscp_addrs[2];
++	struct priv *p = dev->priv;
+ 	int i;
+ 
+-	p->base = (unsigned long) isa_bus_to_virt((unsigned long)where)
+-							+ size - 0x01000000;
+-	p->memtop = isa_bus_to_virt((unsigned long)where) + size;
+-	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
+-	memset_io((char *)p->scp, 0, sizeof(struct scp_struct));
++	p->mapped = ioremap(dev->mem_start, size);
++	if (!p->mapped)
++		return 0;
++
++	p->base = p->mapped + size - 0x01000000;
++	p->memtop = p->mapped + size;
++	p->scp = (struct scp_struct __iomem *)(p->base + SCP_DEFAULT_ADDRESS);
++	p->scb	= (struct scb_struct __iomem *)	p->mapped;
++	p->iscp = (struct iscp_struct __iomem *)p->scp - 1;
++	memset_io(p->scp, 0, sizeof(struct scp_struct));
+ 	for (i = 0; i < sizeof(struct scp_struct); i++)
+ 		/* memory was writeable? */
+-		if (readb((char *)p->scp + i))
+-			return 0;
++		if (readb((char __iomem *)p->scp + i))
++			goto Enodev;
+ 	writeb(SYSBUSVAL, &p->scp->sysbus);	/* 1 = 8Bit-Bus, 0 = 16 Bit */
+ 	if (readb(&p->scp->sysbus) != SYSBUSVAL)
+-		return 0;
+-
+-	iscp_addrs[0] = isa_bus_to_virt((unsigned long)where);
+-	iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
++		goto Enodev;
+ 
+-	for (i = 0; i < 2; i++) {
+-		p->iscp = (struct iscp_struct *) iscp_addrs[i];
+-		memset_io((char *)p->iscp, 0, sizeof(struct iscp_struct));
+-
+-		writel(make24(p->iscp), &p->scp->iscp);
+-		writeb(1, &p->iscp->busy);
+-
+-		ni_reset586();
+-		ni_attn586();
+-		mdelay(32);	/* wait a while... */
+-		/* i82586 clears 'busy' after successful init */
+-		if (readb(&p->iscp->busy))
+-			return 0;
+-	}
++	if (!check_iscp(dev, p->mapped))
++		goto Enodev;
++	if (!check_iscp(dev, p->iscp))
++		goto Enodev;
+ 	return 1;
++Enodev:
++	iounmap(p->mapped);
++	return 0;
+ }
+ 
+ /******************************************************************
+@@ -346,13 +359,6 @@ static void alloc586(struct net_device *dev)
+ 	ni_reset586();
+ 	mdelay(32);
+ 
+-	spin_lock_init(&p->spinlock);
+-
+-	p->scp	= (struct scp_struct *)	(p->base + SCP_DEFAULT_ADDRESS);
+-	p->scb	= (struct scb_struct *)	isa_bus_to_virt(dev->mem_start);
+-	p->iscp = (struct iscp_struct *)
+-			((char *)p->scp - sizeof(struct iscp_struct));
+-
+ 	memset_io(p->iscp, 0, sizeof(struct iscp_struct));
+ 	memset_io(p->scp , 0, sizeof(struct scp_struct));
+ 
+@@ -371,7 +377,7 @@ static void alloc586(struct net_device *dev)
+ 
+ 	p->reset = 0;
+ 
+-	memset_io((char *)p->scb, 0, sizeof(struct scb_struct));
++	memset_io(p->scb, 0, sizeof(struct scb_struct));
+ }
+ 
+ /* set: io,irq,memstart,memend or set it when calling insmod */
+@@ -387,12 +393,15 @@ struct net_device * __init ni52_probe(int unit)
+ {
+ 	struct net_device *dev = alloc_etherdev(sizeof(struct priv));
+ 	static int ports[] = {0x300, 0x280, 0x360 , 0x320 , 0x340, 0};
++	struct priv *p;
+ 	int *port;
+ 	int err = 0;
+ 
+ 	if (!dev)
+ 		return ERR_PTR(-ENOMEM);
+ 
++	p = dev->priv;
++
+ 	if (unit >= 0) {
+ 		sprintf(dev->name, "eth%d", unit);
+ 		netdev_boot_setup_check(dev);
+@@ -427,6 +436,7 @@ got_it:
+ 		goto out1;
+ 	return dev;
+ out1:
++	iounmap(p->mapped);
+ 	release_region(dev->base_addr, NI52_TOTAL_SIZE);
+ out:
+ 	free_netdev(dev);
+@@ -436,12 +446,15 @@ out:
+ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ {
+ 	int i, size, retval;
++	struct priv *priv = dev->priv;
+ 
+ 	dev->base_addr = ioaddr;
+ 	dev->irq = irq;
+ 	dev->mem_start = memstart;
+ 	dev->mem_end = memend;
+ 
++	spin_lock_init(&priv->spinlock);
++
+ 	if (!request_region(ioaddr, NI52_TOTAL_SIZE, DRV_NAME))
+ 		return -EBUSY;
+ 
+@@ -474,7 +487,7 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ 		retval = -ENODEV;
+ 		goto out;
+ 	}
+-	if (!check586(dev, (char *)dev->mem_start, size)) {
++	if (!check586(dev, size)) {
+ 		printk(KERN_ERR "?memcheck, Can't find memory at 0x%lx with size %d!\n", dev->mem_start, size);
+ 		retval = -ENODEV;
+ 		goto out;
+@@ -483,9 +496,9 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ 	if (dev->mem_start != 0) {
+ 		/* no auto-mem-probe */
+ 		size = 0x4000; /* check for 16K mem */
+-		if (!check586(dev, (char *) dev->mem_start, size)) {
++		if (!check586(dev, size)) {
+ 			size = 0x2000; /* check for 8K mem */
+-			if (!check586(dev, (char *)dev->mem_start, size)) {
++			if (!check586(dev, size)) {
+ 				printk(KERN_ERR "?memprobe, Can't find memory at 0x%lx!\n", dev->mem_start);
+ 				retval = -ENODEV;
+ 				goto out;
+@@ -504,11 +517,11 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ 			}
+ 			dev->mem_start = memaddrs[i];
+ 			size = 0x2000; /* check for 8K mem */
+-			if (check586(dev, (char *)dev->mem_start, size))
++			if (check586(dev, size))
+ 				/* 8K-check */
+ 				break;
+ 			size = 0x4000; /* check for 16K mem */
+-			if (check586(dev, (char *)dev->mem_start, size))
++			if (check586(dev, size))
+ 				/* 16K-check */
+ 				break;
+ 		}
+@@ -517,19 +530,13 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ 	dev->mem_end = dev->mem_start + size;
+ #endif
+ 
+-	memset((char *)dev->priv, 0, sizeof(struct priv));
+-
+-	((struct priv *)(dev->priv))->memtop =
+-				isa_bus_to_virt(dev->mem_start) + size;
+-	((struct priv *)(dev->priv))->base =  (unsigned long)
+-			isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
+ 	alloc586(dev);
+ 
+ 	/* set number of receive-buffs according to memsize */
+ 	if (size == 0x2000)
+-		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;
++		priv->num_recv_buffs = NUM_RECV_BUFFS_8;
+ 	else
+-		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
++		priv->num_recv_buffs = NUM_RECV_BUFFS_16;
+ 
+ 	printk(KERN_DEBUG "Memaddr: 0x%lx, Memsize: %d, ",
+ 				dev->mem_start, size);
+@@ -546,6 +553,7 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ 		if (!dev->irq) {
+ 			printk("?autoirq, Failed to detect IRQ line!\n");
+ 			retval = -EAGAIN;
++			iounmap(priv->mapped);
+ 			goto out;
+ 		}
+ 		printk("IRQ %d (autodetected).\n", dev->irq);
+@@ -578,19 +586,19 @@ out:
+ 
+ static int init586(struct net_device *dev)
+ {
+-	void *ptr;
++	void __iomem *ptr;
+ 	int i, result = 0;
+ 	struct priv *p = (struct priv *)dev->priv;
+-	struct configure_cmd_struct *cfg_cmd;
+-	struct iasetup_cmd_struct *ias_cmd;
+-	struct tdr_cmd_struct *tdr_cmd;
+-	struct mcsetup_cmd_struct *mc_cmd;
++	struct configure_cmd_struct __iomem *cfg_cmd;
++	struct iasetup_cmd_struct __iomem *ias_cmd;
++	struct tdr_cmd_struct __iomem *tdr_cmd;
++	struct mcsetup_cmd_struct __iomem *mc_cmd;
+ 	struct dev_mc_list *dmi = dev->mc_list;
+ 	int num_addrs = dev->mc_count;
+ 
+-	ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));
++	ptr = p->scb + 1;
+ 
+-	cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */
++	cfg_cmd = ptr; /* configure-command */
+ 	writew(0, &cfg_cmd->cmd_status);
+ 	writew(CMD_CONFIGURE | CMD_LAST, &cfg_cmd->cmd_cmd);
+ 	writew(0xFFFF, &cfg_cmd->cmd_link);
+@@ -609,7 +617,7 @@ static int init586(struct net_device *dev)
+ 	writeb(0xf2, &cfg_cmd->time_high);
+ 	writeb(0x00, &cfg_cmd->promisc);;
+ 	if (dev->flags & IFF_ALLMULTI) {
+-		int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
++		int len = ((char __iomem *)p->iscp - (char __iomem *)ptr - 8) / 6;
+ 		if (num_addrs > len) {
+ 			printk(KERN_ERR "%s: switching to promisc. mode\n",
+ 				dev->name);
+@@ -620,7 +628,7 @@ static int init586(struct net_device *dev)
+ 		writeb(0x01, &cfg_cmd->promisc);
+ 	writeb(0x00, &cfg_cmd->carr_coll);
+ 	writew(make16(cfg_cmd), &p->scb->cbl_offset);
+-	writew(0, &p->scb->cmd_ruc);
++	writeb(0, &p->scb->cmd_ruc);
+ 
+ 	writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */
+ 	ni_attn586();
+@@ -638,13 +646,13 @@ static int init586(struct net_device *dev)
+ 	 * individual address setup
+ 	 */
+ 
+-	ias_cmd = (struct iasetup_cmd_struct *)ptr;
++	ias_cmd = ptr;
+ 
+ 	writew(0, &ias_cmd->cmd_status);
+ 	writew(CMD_IASETUP | CMD_LAST, &ias_cmd->cmd_cmd);
+ 	writew(0xffff, &ias_cmd->cmd_link);
+ 
+-	memcpy_toio((char *)&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN);
++	memcpy_toio(&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN);
+ 
+ 	writew(make16(ias_cmd), &p->scb->cbl_offset);
+ 
+@@ -663,7 +671,7 @@ static int init586(struct net_device *dev)
+ 	 * TDR, wire check .. e.g. no resistor e.t.c
+ 	 */
+ 
+-	tdr_cmd = (struct tdr_cmd_struct *)ptr;
++	tdr_cmd = ptr;
+ 
+ 	writew(0, &tdr_cmd->cmd_status);
+ 	writew(CMD_TDR | CMD_LAST, &tdr_cmd->cmd_cmd);
+@@ -707,14 +715,14 @@ static int init586(struct net_device *dev)
+ 	 * Multicast setup
+ 	 */
+ 	if (num_addrs && !(dev->flags & IFF_PROMISC)) {
+-		mc_cmd = (struct mcsetup_cmd_struct *) ptr;
++		mc_cmd = ptr;
+ 		writew(0, &mc_cmd->cmd_status);
+ 		writew(CMD_MCSETUP | CMD_LAST, &mc_cmd->cmd_cmd);
+ 		writew(0xffff, &mc_cmd->cmd_link);
+ 		writew(num_addrs * 6, &mc_cmd->mc_cnt);
+ 
+ 		for (i = 0; i < num_addrs; i++, dmi = dmi->next)
+-			memcpy_toio((char *) mc_cmd->mc_list[i],
++			memcpy_toio(mc_cmd->mc_list[i],
+ 							dmi->dmi_addr, 6);
+ 
+ 		writew(make16(mc_cmd), &p->scb->cbl_offset);
+@@ -733,43 +741,43 @@ static int init586(struct net_device *dev)
+ 	 */
+ #if (NUM_XMIT_BUFFS == 1)
+ 	for (i = 0; i < 2; i++) {
+-		p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
++		p->nop_cmds[i] = ptr;
+ 		writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd);
+ 		writew(0, &p->nop_cmds[i]->cmd_status);
+ 		writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link);
+-		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
++		ptr = ptr + sizeof(struct nop_cmd_struct);
+ 	}
+ #else
+ 	for (i = 0; i < NUM_XMIT_BUFFS; i++) {
+-		p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
++		p->nop_cmds[i] = ptr;
+ 		writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd);
+ 		writew(0, &p->nop_cmds[i]->cmd_status);
+ 		writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link);
+-		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
++		ptr = ptr + sizeof(struct nop_cmd_struct);
+ 	}
+ #endif
+ 
+-	ptr = alloc_rfa(dev, (void *)ptr); /* init receive-frame-area */
++	ptr = alloc_rfa(dev, ptr); /* init receive-frame-area */
+ 
+ 	/*
+ 	 * alloc xmit-buffs / init xmit_cmds
+ 	 */
+ 	for (i = 0; i < NUM_XMIT_BUFFS; i++) {
+ 		/* Transmit cmd/buff 0 */
+-		p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr;
+-		ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
+-		p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */
+-		ptr = (char *) ptr + XMIT_BUFF_SIZE;
+-		p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */
+-		ptr = (char *) ptr + sizeof(struct tbd_struct);
+-		if ((void *)ptr > (void *)p->iscp) {
++		p->xmit_cmds[i] = ptr;
++		ptr = ptr + sizeof(struct transmit_cmd_struct);
++		p->xmit_cbuffs[i] = ptr; /* char-buffs */
++		ptr = ptr + XMIT_BUFF_SIZE;
++		p->xmit_buffs[i] = ptr; /* TBD */
++		ptr = ptr + sizeof(struct tbd_struct);
++		if ((void __iomem *)ptr > (void __iomem *)p->iscp) {
+ 			printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n",
+ 				dev->name);
+ 			return 1;
+ 		}
+-		memset_io((char *)(p->xmit_cmds[i]), 0,
++		memset_io(p->xmit_cmds[i], 0,
+ 					sizeof(struct transmit_cmd_struct));
+-		memset_io((char *)(p->xmit_buffs[i]), 0,
++		memset_io(p->xmit_buffs[i], 0,
+ 					sizeof(struct tbd_struct));
+ 		writew(make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]),
+ 					&p->xmit_cmds[i]->cmd_link);
+@@ -816,14 +824,14 @@ static int init586(struct net_device *dev)
+  * It sets up the Receive Frame Area (RFA).
+  */
+ 
+-static void *alloc_rfa(struct net_device *dev, void *ptr)
++static void __iomem *alloc_rfa(struct net_device *dev, void __iomem *ptr)
+ {
+-	struct rfd_struct *rfd = (struct rfd_struct *)ptr;
+-	struct rbd_struct *rbd;
++	struct rfd_struct __iomem *rfd = ptr;
++	struct rbd_struct __iomem *rbd;
+ 	int i;
+ 	struct priv *p = (struct priv *) dev->priv;
+ 
+-	memset_io((char *) rfd, 0,
++	memset_io(rfd, 0,
+ 		sizeof(struct rfd_struct) * (p->num_recv_buffs + rfdadd));
+ 	p->rfd_first = rfd;
+ 
+@@ -835,20 +843,19 @@ static void *alloc_rfa(struct net_device *dev, void *ptr)
+ 	/* RU suspend */
+ 	writeb(RFD_SUSP, &rfd[p->num_recv_buffs-1+rfdadd].last);
+ 
+-	ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd));
++	ptr = rfd + (p->num_recv_buffs + rfdadd);
+ 
+-	rbd = (struct rbd_struct *) ptr;
+-	ptr = (void *) (rbd + p->num_recv_buffs);
++	rbd = ptr;
++	ptr = rbd + p->num_recv_buffs;
+ 
+ 	 /* clr descriptors */
+-	memset_io((char *)rbd, 0,
+-			sizeof(struct rbd_struct) * (p->num_recv_buffs));
++	memset_io(rbd, 0, sizeof(struct rbd_struct) * (p->num_recv_buffs));
+ 
+ 	for (i = 0; i < p->num_recv_buffs; i++) {
+ 		writew(make16(rbd + (i+1) % p->num_recv_buffs), &rbd[i].next);
+ 		writew(RECV_BUFF_SIZE, &rbd[i].size);
+ 		writel(make24(ptr), &rbd[i].buffer);
+-		ptr = (char *) ptr + RECV_BUFF_SIZE;
++		ptr = ptr + RECV_BUFF_SIZE;
+ 	}
+ 	p->rfd_top	= p->rfd_first;
+ 	p->rfd_last = p->rfd_first + (p->num_recv_buffs - 1 + rfdadd);
+@@ -892,7 +899,7 @@ static irqreturn_t ni52_interrupt(int irq, void *dev_id)
+ 			if (readb(&p->scb->rus) & RU_SUSPEND) {
+ 				/* special case: RU_SUSPEND */
+ 				wait_for_scb_cmd(dev);
+-				p->scb->cmd_ruc = RUC_RESUME;
++				writeb(RUC_RESUME, &p->scb->cmd_ruc);
+ 				ni_attn586();
+ 				wait_for_scb_cmd_ruc(dev);
+ 			} else {
+@@ -919,7 +926,7 @@ static irqreturn_t ni52_interrupt(int irq, void *dev_id)
+ 
+ 		/* Wait for ack. (ni52_xmt_int can be faster than ack!!) */
+ 		wait_for_scb_cmd(dev);
+-		if (p->scb->cmd_cuc) {	 /* timed out? */
++		if (readb(&p->scb->cmd_cuc)) {	 /* timed out? */
+ 			printk(KERN_ERR "%s: Acknowledge timed out.\n",
+ 				dev->name);
+ 			ni_disint();
+@@ -942,14 +949,14 @@ static void ni52_rcv_int(struct net_device *dev)
+ 	int status, cnt = 0;
+ 	unsigned short totlen;
+ 	struct sk_buff *skb;
+-	struct rbd_struct *rbd;
++	struct rbd_struct __iomem *rbd;
+ 	struct priv *p = (struct priv *)dev->priv;
+ 
+ 	if (debuglevel > 0)
+ 		printk("R");
+ 
+ 	for (; (status = readb(&p->rfd_top->stat_high)) & RFD_COMPL;) {
+-		rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
++		rbd = make32(readw(&p->rfd_top->rbd_offset));
+ 		if (status & RFD_OK) { /* frame received without error? */
+ 			totlen = readw(&rbd->status);
+ 			if (totlen & RBD_LAST) {
+@@ -960,7 +967,7 @@ static void ni52_rcv_int(struct net_device *dev)
+ 				if (skb != NULL) {
+ 					skb_reserve(skb, 2);
+ 					skb_put(skb, totlen);
+-					skb_copy_to_linear_data(skb, (char *)p->base + (unsigned long) rbd->buffer, totlen);
++					memcpy_fromio(skb->data, p->base + readl(&rbd->buffer), totlen);
+ 					skb->protocol = eth_type_trans(skb, dev);
+ 					netif_rx(skb);
+ 					dev->last_rx = jiffies;
+@@ -979,7 +986,7 @@ static void ni52_rcv_int(struct net_device *dev)
+ 						break;
+ 					}
+ 					writew(0, &rbd->status);
+-					rbd = (struct rbd_struct *) make32(readl(&rbd->next));
++					rbd = make32(readw(&rbd->next));
+ 				}
+ 				totlen += rstat & RBD_MASK;
+ 				writew(0, &rbd->status);
+@@ -997,7 +1004,7 @@ static void ni52_rcv_int(struct net_device *dev)
+ 		writew(0xffff, &p->rfd_top->rbd_offset);
+ 		writeb(0, &p->rfd_last->last);	/* delete RFD_SUSP	*/
+ 		p->rfd_last = p->rfd_top;
+-		p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */
++		p->rfd_top = make32(readw(&p->rfd_top->next)); /* step to next RFD */
+ 		writew(make16(p->rfd_top), &p->scb->rfa_offset);
+ 
+ 		if (debuglevel > 0)
+@@ -1042,11 +1049,12 @@ static void ni52_rnr_int(struct net_device *dev)
+ 	ni_attn586();
+ 	wait_for_scb_cmd_ruc(dev);		/* wait for accept cmd. */
+ 
+-	alloc_rfa(dev, (char *)p->rfd_first);
++	alloc_rfa(dev, p->rfd_first);
+ 	/* maybe add a check here, before restarting the RU */
+ 	startrecv586(dev); /* restart RU */
+ 
+-	printk(KERN_ERR "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->rus);
++	printk(KERN_ERR "%s: Receive-Unit restarted. Status: %04x\n",
++		dev->name, readb(&p->scb->rus));
+ 
+ }
+ 
+@@ -1178,12 +1186,11 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
+ 
+ 	netif_stop_queue(dev);
+ 
+-	skb_copy_from_linear_data(skb, (char *)p->xmit_cbuffs[p->xmit_count],
+-							skb->len);
++	memcpy_toio(p->xmit_cbuffs[p->xmit_count], skb->data, skb->len);
+ 	len = skb->len;
+ 	if (len < ETH_ZLEN) {
+ 		len = ETH_ZLEN;
+-		memset((char *)p->xmit_cbuffs[p->xmit_count]+skb->len, 0,
++		memset_io(p->xmit_cbuffs[p->xmit_count]+skb->len, 0,
+ 							len - skb->len);
+ 	}
+ 
+@@ -1191,14 +1198,14 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
+ #	ifdef NO_NOPCOMMANDS
+ 
+ #ifdef DEBUG
+-	if (p->scb->cus & CU_ACTIVE) {
++	if (readb(&p->scb->cus) & CU_ACTIVE) {
+ 		printk(KERN_ERR "%s: Hmmm .. CU is still running and we wanna send a new packet.\n", dev->name);
+ 		printk(KERN_ERR "%s: stat: %04x %04x\n",
+ 				dev->name, readb(&p->scb->cus),
+ 				readw(&p->xmit_cmds[0]->cmd_status));
+ 	}
+ #endif
+-	writew(TBD_LAST | len, &p->xmit_buffs[0]->size);;
++	writew(TBD_LAST | len, &p->xmit_buffs[0]->size);
+ 	for (i = 0; i < 16; i++) {
+ 		writew(0, &p->xmit_cmds[0]->cmd_status);
+ 		wait_for_scb_cmd(dev);
+@@ -1330,7 +1337,9 @@ int __init init_module(void)
+ 
+ void __exit cleanup_module(void)
+ {
++	struct priv *p = dev_ni52->priv;
+ 	unregister_netdev(dev_ni52);
++	iounmap(p->mapped);
+ 	release_region(dev_ni52->base_addr, NI52_TOTAL_SIZE);
+ 	free_netdev(dev_ni52);
+ }
+diff --git a/drivers/net/ni52.h b/drivers/net/ni52.h
+index 1f28a4d..0a03b28 100644
+--- a/drivers/net/ni52.h
++++ b/drivers/net/ni52.h
+@@ -39,8 +39,8 @@ struct scp_struct
+ 	u16 zero_dum0;	/* has to be zero */
+ 	u8 sysbus;	/* 0=16Bit,1=8Bit */
+ 	u8 zero_dum1;	/* has to be zero for 586 */
+-	u8 zero_dum2;
+-	u8 zero_dum3;
++	u16 zero_dum2;
++	u16 zero_dum3;
+ 	u32 iscp;		/* pointer to the iscp-block */
+ };
+ 
+diff --git a/drivers/net/niu.c b/drivers/net/niu.c
+index d11ba61..4009c4c 100644
+--- a/drivers/net/niu.c
++++ b/drivers/net/niu.c
+@@ -33,8 +33,8 @@
+ 
+ #define DRV_MODULE_NAME		"niu"
+ #define PFX DRV_MODULE_NAME	": "
+-#define DRV_MODULE_VERSION	"0.7"
+-#define DRV_MODULE_RELDATE	"February 18, 2008"
++#define DRV_MODULE_VERSION	"0.8"
++#define DRV_MODULE_RELDATE	"April 24, 2008"
+ 
+ static char version[] __devinitdata =
+ 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+@@ -113,6 +113,8 @@ do {	if ((np)->msg_enable & NETIF_MSG_##TYPE) \
+ #define niu_unlock_parent(np, flags) \
+ 	spin_unlock_irqrestore(&np->parent->lock, flags)
+ 
++static int serdes_init_10g_serdes(struct niu *np);
++
+ static int __niu_wait_bits_clear_mac(struct niu *np, unsigned long reg,
+ 				     u64 bits, int limit, int delay)
+ {
+@@ -671,11 +673,16 @@ static int serdes_init_10g(struct niu *np)
+ 	}
+ 
+ 	if ((sig & mask) != val) {
++		if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
++			np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
++			return 0;
++		}
+ 		dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
+ 			"[%08x]\n", np->port, (int) (sig & mask), (int) val);
+ 		return -ENODEV;
+ 	}
+-
++	if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
++		np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+ 	return 0;
+ }
+ 
+@@ -706,6 +713,251 @@ static int serdes_init_1g(struct niu *np)
+ 	return 0;
+ }
+ 
++static int serdes_init_1g_serdes(struct niu *np)
++{
++	struct niu_link_config *lp = &np->link_config;
++	unsigned long ctrl_reg, test_cfg_reg, pll_cfg, i;
++	u64 ctrl_val, test_cfg_val, sig, mask, val;
++	int err;
++	u64 reset_val, val_rd;
++
++	val = ENET_SERDES_PLL_HRATE0 | ENET_SERDES_PLL_HRATE1 |
++		ENET_SERDES_PLL_HRATE2 | ENET_SERDES_PLL_HRATE3 |
++		ENET_SERDES_PLL_FBDIV0;
++	switch (np->port) {
++	case 0:
++		reset_val =  ENET_SERDES_RESET_0;
++		ctrl_reg = ENET_SERDES_0_CTRL_CFG;
++		test_cfg_reg = ENET_SERDES_0_TEST_CFG;
++		pll_cfg = ENET_SERDES_0_PLL_CFG;
++		break;
++	case 1:
++		reset_val =  ENET_SERDES_RESET_1;
++		ctrl_reg = ENET_SERDES_1_CTRL_CFG;
++		test_cfg_reg = ENET_SERDES_1_TEST_CFG;
++		pll_cfg = ENET_SERDES_1_PLL_CFG;
++		break;
++
++	default:
++		return -EINVAL;
++	}
++	ctrl_val = (ENET_SERDES_CTRL_SDET_0 |
++		    ENET_SERDES_CTRL_SDET_1 |
++		    ENET_SERDES_CTRL_SDET_2 |
++		    ENET_SERDES_CTRL_SDET_3 |
++		    (0x5 << ENET_SERDES_CTRL_EMPH_0_SHIFT) |
++		    (0x5 << ENET_SERDES_CTRL_EMPH_1_SHIFT) |
++		    (0x5 << ENET_SERDES_CTRL_EMPH_2_SHIFT) |
++		    (0x5 << ENET_SERDES_CTRL_EMPH_3_SHIFT) |
++		    (0x1 << ENET_SERDES_CTRL_LADJ_0_SHIFT) |
++		    (0x1 << ENET_SERDES_CTRL_LADJ_1_SHIFT) |
++		    (0x1 << ENET_SERDES_CTRL_LADJ_2_SHIFT) |
++		    (0x1 << ENET_SERDES_CTRL_LADJ_3_SHIFT));
++	test_cfg_val = 0;
++
++	if (lp->loopback_mode == LOOPBACK_PHY) {
++		test_cfg_val |= ((ENET_TEST_MD_PAD_LOOPBACK <<
++				  ENET_SERDES_TEST_MD_0_SHIFT) |
++				 (ENET_TEST_MD_PAD_LOOPBACK <<
++				  ENET_SERDES_TEST_MD_1_SHIFT) |
++				 (ENET_TEST_MD_PAD_LOOPBACK <<
++				  ENET_SERDES_TEST_MD_2_SHIFT) |
++				 (ENET_TEST_MD_PAD_LOOPBACK <<
++				  ENET_SERDES_TEST_MD_3_SHIFT));
++	}
++
++	nw64(ENET_SERDES_RESET, reset_val);
++	mdelay(20);
++	val_rd = nr64(ENET_SERDES_RESET);
++	val_rd &= ~reset_val;
++	nw64(pll_cfg, val);
++	nw64(ctrl_reg, ctrl_val);
++	nw64(test_cfg_reg, test_cfg_val);
++	nw64(ENET_SERDES_RESET, val_rd);
++	mdelay(2000);
++
++	/* Initialize all 4 lanes of the SERDES.  */
++	for (i = 0; i < 4; i++) {
++		u32 rxtx_ctrl, glue0;
++
++		err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl);
++		if (err)
++			return err;
++		err = esr_read_glue0(np, i, &glue0);
++		if (err)
++			return err;
++
++		rxtx_ctrl &= ~(ESR_RXTX_CTRL_VMUXLO);
++		rxtx_ctrl |= (ESR_RXTX_CTRL_ENSTRETCH |
++			      (2 << ESR_RXTX_CTRL_VMUXLO_SHIFT));
++
++		glue0 &= ~(ESR_GLUE_CTRL0_SRATE |
++			   ESR_GLUE_CTRL0_THCNT |
++			   ESR_GLUE_CTRL0_BLTIME);
++		glue0 |= (ESR_GLUE_CTRL0_RXLOSENAB |
++			  (0xf << ESR_GLUE_CTRL0_SRATE_SHIFT) |
++			  (0xff << ESR_GLUE_CTRL0_THCNT_SHIFT) |
++			  (BLTIME_300_CYCLES <<
++			   ESR_GLUE_CTRL0_BLTIME_SHIFT));
++
++		err = esr_write_rxtx_ctrl(np, i, rxtx_ctrl);
++		if (err)
++			return err;
++		err = esr_write_glue0(np, i, glue0);
++		if (err)
++			return err;
++	}
++
++
++	sig = nr64(ESR_INT_SIGNALS);
++	switch (np->port) {
++	case 0:
++		val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0);
++		mask = val;
++		break;
++
++	case 1:
++		val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1);
++		mask = val;
++		break;
++
++	default:
++		return -EINVAL;
++	}
++
++	if ((sig & mask) != val) {
++		dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
++			"[%08x]\n", np->port, (int) (sig & mask), (int) val);
++		return -ENODEV;
++	}
++
++	return 0;
++}
++
++static int link_status_1g_serdes(struct niu *np, int *link_up_p)
++{
++	struct niu_link_config *lp = &np->link_config;
++	int link_up;
++	u64 val;
++	u16 current_speed;
++	unsigned long flags;
++	u8 current_duplex;
++
++	link_up = 0;
++	current_speed = SPEED_INVALID;
++	current_duplex = DUPLEX_INVALID;
++
++	spin_lock_irqsave(&np->lock, flags);
++
++	val = nr64_pcs(PCS_MII_STAT);
++
++	if (val & PCS_MII_STAT_LINK_STATUS) {
++		link_up = 1;
++		current_speed = SPEED_1000;
++		current_duplex = DUPLEX_FULL;
++	}
++
++	lp->active_speed = current_speed;
++	lp->active_duplex = current_duplex;
++	spin_unlock_irqrestore(&np->lock, flags);
++
++	*link_up_p = link_up;
++	return 0;
++}
++
++
++static int link_status_10g_serdes(struct niu *np, int *link_up_p)
++{
++	unsigned long flags;
++	struct niu_link_config *lp = &np->link_config;
++	int link_up = 0;
++	int link_ok = 1;
++	u64 val, val2;
++	u16 current_speed;
++	u8 current_duplex;
++
++	if (!(np->flags & NIU_FLAGS_10G))
++		return link_status_1g_serdes(np, link_up_p);
++
++	current_speed = SPEED_INVALID;
++	current_duplex = DUPLEX_INVALID;
++	spin_lock_irqsave(&np->lock, flags);
++
++	val = nr64_xpcs(XPCS_STATUS(0));
++	val2 = nr64_mac(XMAC_INTER2);
++	if (val2 & 0x01000000)
++		link_ok = 0;
++
++	if ((val & 0x1000ULL) && link_ok) {
++		link_up = 1;
++		current_speed = SPEED_10000;
++		current_duplex = DUPLEX_FULL;
++	}
++	lp->active_speed = current_speed;
++	lp->active_duplex = current_duplex;
++	spin_unlock_irqrestore(&np->lock, flags);
++	*link_up_p = link_up;
++	return 0;
++}
++
++
++static int link_status_1g_rgmii(struct niu *np, int *link_up_p)
++{
++	struct niu_link_config *lp = &np->link_config;
++	u16 current_speed, bmsr;
++	unsigned long flags;
++	u8 current_duplex;
++	int err, link_up;
++
++	link_up = 0;
++	current_speed = SPEED_INVALID;
++	current_duplex = DUPLEX_INVALID;
++
++	spin_lock_irqsave(&np->lock, flags);
++
++	err = -EINVAL;
++
++	err = mii_read(np, np->phy_addr, MII_BMSR);
++	if (err < 0)
++		goto out;
++
++	bmsr = err;
++	if (bmsr & BMSR_LSTATUS) {
++		u16 adv, lpa, common, estat;
++
++		err = mii_read(np, np->phy_addr, MII_ADVERTISE);
++		if (err < 0)
++			goto out;
++		adv = err;
++
++		err = mii_read(np, np->phy_addr, MII_LPA);
++		if (err < 0)
++			goto out;
++		lpa = err;
++
++		common = adv & lpa;
++
++		err = mii_read(np, np->phy_addr, MII_ESTATUS);
++		if (err < 0)
++			goto out;
++		estat = err;
++		link_up = 1;
++		current_speed = SPEED_1000;
++		current_duplex = DUPLEX_FULL;
++
++	}
++	lp->active_speed = current_speed;
++	lp->active_duplex = current_duplex;
++	err = 0;
++
++out:
++	spin_unlock_irqrestore(&np->lock, flags);
++
++	*link_up_p = link_up;
++	return err;
++}
++
++
+ static int bcm8704_reset(struct niu *np)
+ {
+ 	int err, limit;
+@@ -751,6 +1003,28 @@ static int bcm8704_user_dev3_readback(struct niu *np, int reg)
+ 	return 0;
+ }
+ 
++static int bcm8706_init_user_dev3(struct niu *np)
++{
++	int err;
++
++
++	err = mdio_read(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
++			BCM8704_USER_OPT_DIGITAL_CTRL);
++	if (err < 0)
++		return err;
++	err &= ~USER_ODIG_CTRL_GPIOS;
++	err |= (0x3 << USER_ODIG_CTRL_GPIOS_SHIFT);
++	err |=  USER_ODIG_CTRL_RESV2;
++	err = mdio_write(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
++			 BCM8704_USER_OPT_DIGITAL_CTRL, err);
++	if (err)
++		return err;
++
++	mdelay(1000);
++
++	return 0;
++}
++
+ static int bcm8704_init_user_dev3(struct niu *np)
+ {
+ 	int err;
+@@ -880,33 +1154,11 @@ static int xcvr_init_10g_mrvl88x2011(struct niu *np)
+ 			  MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX);
+ }
+ 
+-static int xcvr_init_10g_bcm8704(struct niu *np)
++
++static int xcvr_diag_bcm870x(struct niu *np)
+ {
+-	struct niu_link_config *lp = &np->link_config;
+ 	u16 analog_stat0, tx_alarm_status;
+-	int err;
+-
+-	err = bcm8704_reset(np);
+-	if (err)
+-		return err;
+-
+-	err = bcm8704_init_user_dev3(np);
+-	if (err)
+-		return err;
+-
+-	err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+-			MII_BMCR);
+-	if (err < 0)
+-		return err;
+-	err &= ~BMCR_LOOPBACK;
+-
+-	if (lp->loopback_mode == LOOPBACK_MAC)
+-		err |= BMCR_LOOPBACK;
+-
+-	err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+-			 MII_BMCR, err);
+-	if (err)
+-		return err;
++	int err = 0;
+ 
+ #if 1
+ 	err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
+@@ -964,6 +1216,89 @@ static int xcvr_init_10g_bcm8704(struct niu *np)
+ 	return 0;
+ }
+ 
++static int xcvr_10g_set_lb_bcm870x(struct niu *np)
++{
++	struct niu_link_config *lp = &np->link_config;
++	int err;
++
++	err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
++			MII_BMCR);
++	if (err < 0)
++		return err;
++
++	err &= ~BMCR_LOOPBACK;
++
++	if (lp->loopback_mode == LOOPBACK_MAC)
++		err |= BMCR_LOOPBACK;
++
++	err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
++			 MII_BMCR, err);
++	if (err)
++		return err;
++
++	return 0;
++}
++
++static int xcvr_init_10g_bcm8706(struct niu *np)
++{
++	int err = 0;
++	u64 val;
++
++	if ((np->flags & NIU_FLAGS_HOTPLUG_PHY) &&
++	    (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) == 0)
++			return err;
++
++	val = nr64_mac(XMAC_CONFIG);
++	val &= ~XMAC_CONFIG_LED_POLARITY;
++	val |= XMAC_CONFIG_FORCE_LED_ON;
++	nw64_mac(XMAC_CONFIG, val);
++
++	val = nr64(MIF_CONFIG);
++	val |= MIF_CONFIG_INDIRECT_MODE;
++	nw64(MIF_CONFIG, val);
++
++	err = bcm8704_reset(np);
++	if (err)
++		return err;
++
++	err = xcvr_10g_set_lb_bcm870x(np);
++	if (err)
++		return err;
++
++	err = bcm8706_init_user_dev3(np);
++	if (err)
++		return err;
++
++	err = xcvr_diag_bcm870x(np);
++	if (err)
++		return err;
++
++	return 0;
++}
++
++static int xcvr_init_10g_bcm8704(struct niu *np)
++{
++	int err;
++
++	err = bcm8704_reset(np);
++	if (err)
++		return err;
++
++	err = bcm8704_init_user_dev3(np);
++	if (err)
++		return err;
++
++	err = xcvr_10g_set_lb_bcm870x(np);
++	if (err)
++		return err;
++
++	err =  xcvr_diag_bcm870x(np);
++	if (err)
++		return err;
++
++	return 0;
++}
++
+ static int xcvr_init_10g(struct niu *np)
+ {
+ 	int phy_id, err;
+@@ -1022,6 +1357,69 @@ static int mii_reset(struct niu *np)
+ 	return 0;
+ }
+ 
++
++
++static int xcvr_init_1g_rgmii(struct niu *np)
++{
++	int err;
++	u64 val;
++	u16 bmcr, bmsr, estat;
++
++	val = nr64(MIF_CONFIG);
++	val &= ~MIF_CONFIG_INDIRECT_MODE;
++	nw64(MIF_CONFIG, val);
++
++	err = mii_reset(np);
++	if (err)
++		return err;
++
++	err = mii_read(np, np->phy_addr, MII_BMSR);
++	if (err < 0)
++		return err;
++	bmsr = err;
++
++	estat = 0;
++	if (bmsr & BMSR_ESTATEN) {
++		err = mii_read(np, np->phy_addr, MII_ESTATUS);
++		if (err < 0)
++			return err;
++		estat = err;
++	}
++
++	bmcr = 0;
++	err = mii_write(np, np->phy_addr, MII_BMCR, bmcr);
++	if (err)
++		return err;
++
++	if (bmsr & BMSR_ESTATEN) {
++		u16 ctrl1000 = 0;
++
++		if (estat & ESTATUS_1000_TFULL)
++			ctrl1000 |= ADVERTISE_1000FULL;
++		err = mii_write(np, np->phy_addr, MII_CTRL1000, ctrl1000);
++		if (err)
++			return err;
++	}
++
++	bmcr = (BMCR_SPEED1000 | BMCR_FULLDPLX);
++
++	err = mii_write(np, np->phy_addr, MII_BMCR, bmcr);
++	if (err)
++		return err;
++
++	err = mii_read(np, np->phy_addr, MII_BMCR);
++	if (err < 0)
++		return err;
++	bmcr = mii_read(np, np->phy_addr, MII_BMCR);
++
++	err = mii_read(np, np->phy_addr, MII_BMSR);
++	if (err < 0)
++		return err;
++
++	return 0;
++}
++
++
+ static int mii_init_common(struct niu *np)
+ {
+ 	struct niu_link_config *lp = &np->link_config;
+@@ -1238,6 +1636,59 @@ out:
+ 	return err;
+ }
+ 
++static int link_status_10g_bcm8706(struct niu *np, int *link_up_p)
++{
++	int err, link_up;
++	link_up = 0;
++
++	err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
++			BCM8704_PMD_RCV_SIGDET);
++	if (err < 0)
++		goto out;
++	if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
++		err = 0;
++		goto out;
++	}
++
++	err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
++			BCM8704_PCS_10G_R_STATUS);
++	if (err < 0)
++		goto out;
++
++	if (!(err & PCS_10G_R_STATUS_BLK_LOCK)) {
++		err = 0;
++		goto out;
++	}
++
++	err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
++			BCM8704_PHYXS_XGXS_LANE_STAT);
++	if (err < 0)
++		goto out;
++	if (err != (PHYXS_XGXS_LANE_STAT_ALINGED |
++		    PHYXS_XGXS_LANE_STAT_MAGIC |
++		    PHYXS_XGXS_LANE_STAT_PATTEST |
++		    PHYXS_XGXS_LANE_STAT_LANE3 |
++		    PHYXS_XGXS_LANE_STAT_LANE2 |
++		    PHYXS_XGXS_LANE_STAT_LANE1 |
++		    PHYXS_XGXS_LANE_STAT_LANE0)) {
++		err = 0;
++		np->link_config.active_speed = SPEED_INVALID;
++		np->link_config.active_duplex = DUPLEX_INVALID;
++		goto out;
++	}
++
++	link_up = 1;
++	np->link_config.active_speed = SPEED_10000;
++	np->link_config.active_duplex = DUPLEX_FULL;
++	err = 0;
++
++out:
++	*link_up_p = link_up;
++	if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
++		err = 0;
++	return err;
++}
++
+ static int link_status_10g_bcom(struct niu *np, int *link_up_p)
+ {
+ 	int err, link_up;
+@@ -1317,6 +1768,82 @@ static int link_status_10g(struct niu *np, int *link_up_p)
+ 	return err;
+ }
+ 
++static int niu_10g_phy_present(struct niu *np)
++{
++	u64 sig, mask, val;
++
++	sig = nr64(ESR_INT_SIGNALS);
++	switch (np->port) {
++	case 0:
++		mask = ESR_INT_SIGNALS_P0_BITS;
++		val = (ESR_INT_SRDY0_P0 |
++		       ESR_INT_DET0_P0 |
++		       ESR_INT_XSRDY_P0 |
++		       ESR_INT_XDP_P0_CH3 |
++		       ESR_INT_XDP_P0_CH2 |
++		       ESR_INT_XDP_P0_CH1 |
++		       ESR_INT_XDP_P0_CH0);
++		break;
++
++	case 1:
++		mask = ESR_INT_SIGNALS_P1_BITS;
++		val = (ESR_INT_SRDY0_P1 |
++		       ESR_INT_DET0_P1 |
++		       ESR_INT_XSRDY_P1 |
++		       ESR_INT_XDP_P1_CH3 |
++		       ESR_INT_XDP_P1_CH2 |
++		       ESR_INT_XDP_P1_CH1 |
++		       ESR_INT_XDP_P1_CH0);
++		break;
++
++	default:
++		return 0;
++	}
++
++	if ((sig & mask) != val)
++		return 0;
++	return 1;
++}
++
++static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
++{
++	unsigned long flags;
++	int err = 0;
++	int phy_present;
++	int phy_present_prev;
++
++	spin_lock_irqsave(&np->lock, flags);
++
++	if (np->link_config.loopback_mode == LOOPBACK_DISABLED) {
++		phy_present_prev = (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) ?
++			1 : 0;
++		phy_present = niu_10g_phy_present(np);
++		if (phy_present != phy_present_prev) {
++			/* state change */
++			if (phy_present) {
++				np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
++				if (np->phy_ops->xcvr_init)
++					err = np->phy_ops->xcvr_init(np);
++				if (err) {
++					/* debounce */
++					np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
++				}
++			} else {
++				np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
++				*link_up_p = 0;
++				niuwarn(LINK, "%s: Hotplug PHY Removed\n",
++					np->dev->name);
++			}
++		}
++		if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT)
++			err = link_status_10g_bcm8706(np, link_up_p);
++	}
++
++	spin_unlock_irqrestore(&np->lock, flags);
++
++	return err;
++}
++
+ static int link_status_1g(struct niu *np, int *link_up_p)
+ {
+ 	struct niu_link_config *lp = &np->link_config;
+@@ -1429,6 +1956,16 @@ static void niu_timer(unsigned long __opaque)
+ 	add_timer(&np->timer);
+ }
+ 
++static const struct niu_phy_ops phy_ops_10g_serdes = {
++	.serdes_init		= serdes_init_10g_serdes,
++	.link_status		= link_status_10g_serdes,
++};
++
++static const struct niu_phy_ops phy_ops_1g_rgmii = {
++	.xcvr_init		= xcvr_init_1g_rgmii,
++	.link_status		= link_status_1g_rgmii,
++};
++
+ static const struct niu_phy_ops phy_ops_10g_fiber_niu = {
+ 	.serdes_init		= serdes_init_niu,
+ 	.xcvr_init		= xcvr_init_10g,
+@@ -1441,6 +1978,12 @@ static const struct niu_phy_ops phy_ops_10g_fiber = {
+ 	.link_status		= link_status_10g,
+ };
+ 
++static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = {
++	.serdes_init		= serdes_init_10g,
++	.xcvr_init		= xcvr_init_10g_bcm8706,
++	.link_status		= link_status_10g_hotplug,
++};
++
+ static const struct niu_phy_ops phy_ops_10g_copper = {
+ 	.serdes_init		= serdes_init_10g,
+ 	.link_status		= link_status_10g, /* XXX */
+@@ -1472,6 +2015,11 @@ static const struct niu_phy_template phy_template_10g_fiber = {
+ 	.phy_addr_base	= 8,
+ };
+ 
++static const struct niu_phy_template phy_template_10g_fiber_hotplug = {
++	.ops		= &phy_ops_10g_fiber_hotplug,
++	.phy_addr_base	= 8,
++};
++
+ static const struct niu_phy_template phy_template_10g_copper = {
+ 	.ops		= &phy_ops_10g_copper,
+ 	.phy_addr_base	= 10,
+@@ -1487,6 +2035,152 @@ static const struct niu_phy_template phy_template_1g_copper = {
+ 	.phy_addr_base	= 0,
+ };
+ 
++static const struct niu_phy_template phy_template_1g_rgmii = {
++	.ops		= &phy_ops_1g_rgmii,
++	.phy_addr_base	= 0,
++};
++
++static const struct niu_phy_template phy_template_10g_serdes = {
++	.ops		= &phy_ops_10g_serdes,
++	.phy_addr_base	= 0,
++};
++
++static int niu_atca_port_num[4] = {
++	0, 0,  11, 10
++};
++
++static int serdes_init_10g_serdes(struct niu *np)
++{
++	struct niu_link_config *lp = &np->link_config;
++	unsigned long ctrl_reg, test_cfg_reg, pll_cfg, i;
++	u64 ctrl_val, test_cfg_val, sig, mask, val;
++	int err;
++	u64 reset_val;
++
++	switch (np->port) {
++	case 0:
++		reset_val =  ENET_SERDES_RESET_0;
++		ctrl_reg = ENET_SERDES_0_CTRL_CFG;
++		test_cfg_reg = ENET_SERDES_0_TEST_CFG;
++		pll_cfg = ENET_SERDES_0_PLL_CFG;
++		break;
++	case 1:
++		reset_val =  ENET_SERDES_RESET_1;
++		ctrl_reg = ENET_SERDES_1_CTRL_CFG;
++		test_cfg_reg = ENET_SERDES_1_TEST_CFG;
++		pll_cfg = ENET_SERDES_1_PLL_CFG;
++		break;
++
++	default:
++		return -EINVAL;
++	}
++	ctrl_val = (ENET_SERDES_CTRL_SDET_0 |
++		    ENET_SERDES_CTRL_SDET_1 |
++		    ENET_SERDES_CTRL_SDET_2 |
++		    ENET_SERDES_CTRL_SDET_3 |
++		    (0x5 << ENET_SERDES_CTRL_EMPH_0_SHIFT) |
++		    (0x5 << ENET_SERDES_CTRL_EMPH_1_SHIFT) |
++		    (0x5 << ENET_SERDES_CTRL_EMPH_2_SHIFT) |
++		    (0x5 << ENET_SERDES_CTRL_EMPH_3_SHIFT) |
++		    (0x1 << ENET_SERDES_CTRL_LADJ_0_SHIFT) |
++		    (0x1 << ENET_SERDES_CTRL_LADJ_1_SHIFT) |
++		    (0x1 << ENET_SERDES_CTRL_LADJ_2_SHIFT) |
++		    (0x1 << ENET_SERDES_CTRL_LADJ_3_SHIFT));
++	test_cfg_val = 0;
++
++	if (lp->loopback_mode == LOOPBACK_PHY) {
++		test_cfg_val |= ((ENET_TEST_MD_PAD_LOOPBACK <<
++				  ENET_SERDES_TEST_MD_0_SHIFT) |
++				 (ENET_TEST_MD_PAD_LOOPBACK <<
++				  ENET_SERDES_TEST_MD_1_SHIFT) |
++				 (ENET_TEST_MD_PAD_LOOPBACK <<
++				  ENET_SERDES_TEST_MD_2_SHIFT) |
++				 (ENET_TEST_MD_PAD_LOOPBACK <<
++				  ENET_SERDES_TEST_MD_3_SHIFT));
++	}
++
++	esr_reset(np);
++	nw64(pll_cfg, ENET_SERDES_PLL_FBDIV2);
++	nw64(ctrl_reg, ctrl_val);
++	nw64(test_cfg_reg, test_cfg_val);
++
++	/* Initialize all 4 lanes of the SERDES.  */
++	for (i = 0; i < 4; i++) {
++		u32 rxtx_ctrl, glue0;
++
++		err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl);
++		if (err)
++			return err;
++		err = esr_read_glue0(np, i, &glue0);
++		if (err)
++			return err;
++
++		rxtx_ctrl &= ~(ESR_RXTX_CTRL_VMUXLO);
++		rxtx_ctrl |= (ESR_RXTX_CTRL_ENSTRETCH |
++			      (2 << ESR_RXTX_CTRL_VMUXLO_SHIFT));
++
++		glue0 &= ~(ESR_GLUE_CTRL0_SRATE |
++			   ESR_GLUE_CTRL0_THCNT |
++			   ESR_GLUE_CTRL0_BLTIME);
++		glue0 |= (ESR_GLUE_CTRL0_RXLOSENAB |
++			  (0xf << ESR_GLUE_CTRL0_SRATE_SHIFT) |
++			  (0xff << ESR_GLUE_CTRL0_THCNT_SHIFT) |
++			  (BLTIME_300_CYCLES <<
++			   ESR_GLUE_CTRL0_BLTIME_SHIFT));
++
++		err = esr_write_rxtx_ctrl(np, i, rxtx_ctrl);
++		if (err)
++			return err;
++		err = esr_write_glue0(np, i, glue0);
++		if (err)
++			return err;
++	}
++
++
++	sig = nr64(ESR_INT_SIGNALS);
++	switch (np->port) {
++	case 0:
++		mask = ESR_INT_SIGNALS_P0_BITS;
++		val = (ESR_INT_SRDY0_P0 |
++		       ESR_INT_DET0_P0 |
++		       ESR_INT_XSRDY_P0 |
++		       ESR_INT_XDP_P0_CH3 |
++		       ESR_INT_XDP_P0_CH2 |
++		       ESR_INT_XDP_P0_CH1 |
++		       ESR_INT_XDP_P0_CH0);
++		break;
++
++	case 1:
++		mask = ESR_INT_SIGNALS_P1_BITS;
++		val = (ESR_INT_SRDY0_P1 |
++		       ESR_INT_DET0_P1 |
++		       ESR_INT_XSRDY_P1 |
++		       ESR_INT_XDP_P1_CH3 |
++		       ESR_INT_XDP_P1_CH2 |
++		       ESR_INT_XDP_P1_CH1 |
++		       ESR_INT_XDP_P1_CH0);
++		break;
++
++	default:
++		return -EINVAL;
++	}
++
++	if ((sig & mask) != val) {
++		int err;
++		err = serdes_init_1g_serdes(np);
++		if (!err) {
++			np->flags &= ~NIU_FLAGS_10G;
++			np->mac_xcvr = MAC_XCVR_PCS;
++		}  else {
++			dev_err(np->device, PFX "Port %u 10G/1G SERDES Link Failed \n",
++			 np->port);
++			return -ENODEV;
++		}
++	}
++
++	return 0;
++}
++
+ static int niu_determine_phy_disposition(struct niu *np)
+ {
+ 	struct niu_parent *parent = np->parent;
+@@ -1498,7 +2192,10 @@ static int niu_determine_phy_disposition(struct niu *np)
+ 		tp = &phy_template_niu;
+ 		phy_addr_off += np->port;
+ 	} else {
+-		switch (np->flags & (NIU_FLAGS_10G | NIU_FLAGS_FIBER)) {
++		switch (np->flags &
++			(NIU_FLAGS_10G |
++			 NIU_FLAGS_FIBER |
++			 NIU_FLAGS_XCVR_SERDES)) {
+ 		case 0:
+ 			/* 1G copper */
+ 			tp = &phy_template_1g_copper;
+@@ -1527,6 +2224,32 @@ static int niu_determine_phy_disposition(struct niu *np)
+ 			    plat_type == PLAT_TYPE_VF_P1)
+ 				phy_addr_off = 8;
+ 			phy_addr_off += np->port;
++			if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
++				tp = &phy_template_10g_fiber_hotplug;
++				if (np->port == 0)
++					phy_addr_off = 8;
++				if (np->port == 1)
++					phy_addr_off = 12;
++			}
++			break;
++
++		case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
++		case NIU_FLAGS_XCVR_SERDES | NIU_FLAGS_FIBER:
++		case NIU_FLAGS_XCVR_SERDES:
++			switch(np->port) {
++			case 0:
++			case 1:
++				tp = &phy_template_10g_serdes;
++				break;
++			case 2:
++			case 3:
++				tp = &phy_template_1g_rgmii;
++				break;
++			default:
++				return -EINVAL;
++				break;
++			}
++			phy_addr_off = niu_atca_port_num[np->port];
+ 			break;
+ 
+ 		default:
+@@ -4139,6 +4862,12 @@ static void niu_init_xif_xmac(struct niu *np)
+ 	struct niu_link_config *lp = &np->link_config;
+ 	u64 val;
+ 
++	if (np->flags & NIU_FLAGS_XCVR_SERDES) {
++		val = nr64(MIF_CONFIG);
++		val |= MIF_CONFIG_ATCA_GE;
++		nw64(MIF_CONFIG, val);
++	}
++
+ 	val = nr64_mac(XMAC_CONFIG);
+ 	val &= ~XMAC_CONFIG_SEL_POR_CLK_SRC;
+ 
+@@ -4155,7 +4884,8 @@ static void niu_init_xif_xmac(struct niu *np)
+ 		val &= ~XMAC_CONFIG_LFS_DISABLE;
+ 	} else {
+ 		val |= XMAC_CONFIG_LFS_DISABLE;
+-		if (!(np->flags & NIU_FLAGS_FIBER))
++		if (!(np->flags & NIU_FLAGS_FIBER) &&
++		    !(np->flags & NIU_FLAGS_XCVR_SERDES))
+ 			val |= XMAC_CONFIG_1G_PCS_BYPASS;
+ 		else
+ 			val &= ~XMAC_CONFIG_1G_PCS_BYPASS;
+@@ -4224,16 +4954,26 @@ static void niu_init_xif(struct niu *np)
+ 
+ static void niu_pcs_mii_reset(struct niu *np)
+ {
++	int limit = 1000;
+ 	u64 val = nr64_pcs(PCS_MII_CTL);
+ 	val |= PCS_MII_CTL_RST;
+ 	nw64_pcs(PCS_MII_CTL, val);
++	while ((--limit >= 0) && (val & PCS_MII_CTL_RST)) {
++		udelay(100);
++		val = nr64_pcs(PCS_MII_CTL);
++	}
+ }
+ 
+ static void niu_xpcs_reset(struct niu *np)
+ {
++	int limit = 1000;
+ 	u64 val = nr64_xpcs(XPCS_CONTROL1);
+ 	val |= XPCS_CONTROL1_RESET;
+ 	nw64_xpcs(XPCS_CONTROL1, val);
++	while ((--limit >= 0) && (val & XPCS_CONTROL1_RESET)) {
++		udelay(100);
++		val = nr64_xpcs(XPCS_CONTROL1);
++	}
+ }
+ 
+ static int niu_init_pcs(struct niu *np)
+@@ -4241,7 +4981,9 @@ static int niu_init_pcs(struct niu *np)
+ 	struct niu_link_config *lp = &np->link_config;
+ 	u64 val;
+ 
+-	switch (np->flags & (NIU_FLAGS_10G | NIU_FLAGS_FIBER)) {
++	switch (np->flags & (NIU_FLAGS_10G |
++			     NIU_FLAGS_FIBER |
++			     NIU_FLAGS_XCVR_SERDES)) {
+ 	case NIU_FLAGS_FIBER:
+ 		/* 1G fiber */
+ 		nw64_pcs(PCS_CONF, PCS_CONF_MASK | PCS_CONF_ENABLE);
+@@ -4251,6 +4993,8 @@ static int niu_init_pcs(struct niu *np)
+ 
+ 	case NIU_FLAGS_10G:
+ 	case NIU_FLAGS_10G | NIU_FLAGS_FIBER:
++	case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
++		/* 10G SERDES */
+ 		if (!(np->flags & NIU_FLAGS_XMAC))
+ 			return -EINVAL;
+ 
+@@ -4273,8 +5017,18 @@ static int niu_init_pcs(struct niu *np)
+ 		(void) nr64_xpcs(XPCS_SYMERR_CNT23);
+ 		break;
+ 
++
++	case NIU_FLAGS_XCVR_SERDES:
++		/* 1G SERDES */
++		niu_pcs_mii_reset(np);
++		nw64_pcs(PCS_CONF, PCS_CONF_MASK | PCS_CONF_ENABLE);
++		nw64_pcs(PCS_DPATH_MODE, 0);
++		break;
++
+ 	case 0:
+ 		/* 1G copper */
++	case NIU_FLAGS_XCVR_SERDES | NIU_FLAGS_FIBER:
++		/* 1G RGMII FIBER */
+ 		nw64_pcs(PCS_DPATH_MODE, PCS_DPATH_MODE_MII);
+ 		niu_pcs_mii_reset(np);
+ 		break;
+@@ -6254,6 +7008,37 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np,
+ 	return 0;
+ }
+ 
++/* niu board models have a trailing dash version incremented
++ * with HW rev change. Need to ingnore the  dash version while
++ * checking for match
++ *
++ * for example, for the 10G card the current vpd.board_model
++ * is 501-5283-04, of which -04 is the  dash version and have
++ * to be ignored
++ */
++static int niu_board_model_match(struct niu *np, const char *model)
++{
++	return !strncmp(np->vpd.board_model, model, strlen(model));
++}
++
++static int niu_pci_vpd_get_nports(struct niu *np)
++{
++	int ports = 0;
++
++	if ((niu_board_model_match(np, NIU_QGC_LP_BM_STR)) ||
++	    (niu_board_model_match(np, NIU_QGC_PEM_BM_STR)) ||
++	    (niu_board_model_match(np, NIU_ALONSO_BM_STR))) {
++		ports = 4;
++	} else if ((niu_board_model_match(np, NIU_2XGF_LP_BM_STR)) ||
++		   (niu_board_model_match(np, NIU_2XGF_PEM_BM_STR)) ||
++		   (niu_board_model_match(np, NIU_FOXXY_BM_STR)) ||
++		   (niu_board_model_match(np, NIU_2XGF_MRVL_BM_STR))) {
++		ports = 2;
++	}
++
++	return ports;
++}
++
+ static void __devinit niu_pci_vpd_validate(struct niu *np)
+ {
+ 	struct net_device *dev = np->dev;
+@@ -6268,7 +7053,22 @@ static void __devinit niu_pci_vpd_validate(struct niu *np)
+ 		return;
+ 	}
+ 
+-	if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
++	if (!strcmp(np->vpd.model, "SUNW,CP3220") ||
++	    !strcmp(np->vpd.model, "SUNW,CP3260")) {
++		np->flags |= NIU_FLAGS_10G;
++		np->flags &= ~NIU_FLAGS_FIBER;
++		np->flags |= NIU_FLAGS_XCVR_SERDES;
++		np->mac_xcvr = MAC_XCVR_PCS;
++		if (np->port > 1) {
++			np->flags |= NIU_FLAGS_FIBER;
++			np->flags &= ~NIU_FLAGS_10G;
++		}
++		if (np->flags & NIU_FLAGS_10G)
++			 np->mac_xcvr = MAC_XCVR_XPCS;
++	} else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
++		np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
++			      NIU_FLAGS_HOTPLUG_PHY);
++	} else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
+ 		dev_err(np->device, PFX "Illegal phy string [%s].\n",
+ 			np->vpd.phy_type);
+ 		dev_err(np->device, PFX "Falling back to SPROM.\n");
+@@ -6456,11 +7256,17 @@ static int __devinit niu_get_and_validate_port(struct niu *np)
+ 		if (parent->plat_type == PLAT_TYPE_NIU) {
+ 			parent->num_ports = 2;
+ 		} else {
+-			parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
+-				ESPC_NUM_PORTS_MACS_VAL;
+-
+-			if (!parent->num_ports)
+-				parent->num_ports = 4;
++			parent->num_ports = niu_pci_vpd_get_nports(np);
++			if (!parent->num_ports) {
++				/* Fall back to SPROM as last resort.
++				 * This will fail on most cards.
++				 */
++				parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
++					ESPC_NUM_PORTS_MACS_VAL;
++
++				if (!parent->num_ports)
++					return -ENODEV;
++			}
+ 		}
+ 	}
+ 
+@@ -6484,7 +7290,8 @@ static int __devinit phy_record(struct niu_parent *parent,
+ 		return 0;
+ 	if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) {
+ 		if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) &&
+-		    ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011))
++		    ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011) &&
++		    ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8706))
+ 			return 0;
+ 	} else {
+ 		if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R)
+@@ -6731,80 +7538,98 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
+ 	u32 val;
+ 	int err;
+ 
+-	err = fill_phy_probe_info(np, parent, info);
+-	if (err)
+-		return err;
+-
+-	num_10g = count_10g_ports(info, &lowest_10g);
+-	num_1g = count_1g_ports(info, &lowest_1g);
+-
+-	switch ((num_10g << 4) | num_1g) {
+-	case 0x24:
+-		if (lowest_1g == 10)
+-			parent->plat_type = PLAT_TYPE_VF_P0;
+-		else if (lowest_1g == 26)
+-			parent->plat_type = PLAT_TYPE_VF_P1;
+-		else
+-			goto unknown_vg_1g_port;
+-
+-		/* fallthru */
+-	case 0x22:
+-		val = (phy_encode(PORT_TYPE_10G, 0) |
+-		       phy_encode(PORT_TYPE_10G, 1) |
++	if (!strcmp(np->vpd.model, "SUNW,CP3220") ||
++	    !strcmp(np->vpd.model, "SUNW,CP3260")) {
++		num_10g = 0;
++		num_1g = 2;
++		parent->plat_type = PLAT_TYPE_ATCA_CP3220;
++		parent->num_ports = 4;
++		val = (phy_encode(PORT_TYPE_1G, 0) |
++		       phy_encode(PORT_TYPE_1G, 1) |
+ 		       phy_encode(PORT_TYPE_1G, 2) |
+ 		       phy_encode(PORT_TYPE_1G, 3));
+-		break;
+-
+-	case 0x20:
++	} else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
++		num_10g = 2;
++		num_1g = 0;
++		parent->num_ports = 2;
+ 		val = (phy_encode(PORT_TYPE_10G, 0) |
+ 		       phy_encode(PORT_TYPE_10G, 1));
+-		break;
++	} else {
++		err = fill_phy_probe_info(np, parent, info);
++		if (err)
++			return err;
+ 
+-	case 0x10:
+-		val = phy_encode(PORT_TYPE_10G, np->port);
+-		break;
++		num_10g = count_10g_ports(info, &lowest_10g);
++		num_1g = count_1g_ports(info, &lowest_1g);
+ 
+-	case 0x14:
+-		if (lowest_1g == 10)
+-			parent->plat_type = PLAT_TYPE_VF_P0;
+-		else if (lowest_1g == 26)
+-			parent->plat_type = PLAT_TYPE_VF_P1;
+-		else
+-			goto unknown_vg_1g_port;
++		switch ((num_10g << 4) | num_1g) {
++		case 0x24:
++			if (lowest_1g == 10)
++				parent->plat_type = PLAT_TYPE_VF_P0;
++			else if (lowest_1g == 26)
++				parent->plat_type = PLAT_TYPE_VF_P1;
++			else
++				goto unknown_vg_1g_port;
+ 
+-		/* fallthru */
+-	case 0x13:
+-		if ((lowest_10g & 0x7) == 0)
++			/* fallthru */
++		case 0x22:
+ 			val = (phy_encode(PORT_TYPE_10G, 0) |
+-			       phy_encode(PORT_TYPE_1G, 1) |
+-			       phy_encode(PORT_TYPE_1G, 2) |
+-			       phy_encode(PORT_TYPE_1G, 3));
+-		else
+-			val = (phy_encode(PORT_TYPE_1G, 0) |
+ 			       phy_encode(PORT_TYPE_10G, 1) |
+ 			       phy_encode(PORT_TYPE_1G, 2) |
+ 			       phy_encode(PORT_TYPE_1G, 3));
+-		break;
++			break;
+ 
+-	case 0x04:
+-		if (lowest_1g == 10)
+-			parent->plat_type = PLAT_TYPE_VF_P0;
+-		else if (lowest_1g == 26)
+-			parent->plat_type = PLAT_TYPE_VF_P1;
+-		else
+-			goto unknown_vg_1g_port;
++		case 0x20:
++			val = (phy_encode(PORT_TYPE_10G, 0) |
++			       phy_encode(PORT_TYPE_10G, 1));
++			break;
+ 
+-		val = (phy_encode(PORT_TYPE_1G, 0) |
+-		       phy_encode(PORT_TYPE_1G, 1) |
+-		       phy_encode(PORT_TYPE_1G, 2) |
+-		       phy_encode(PORT_TYPE_1G, 3));
+-		break;
++		case 0x10:
++			val = phy_encode(PORT_TYPE_10G, np->port);
++			break;
+ 
+-	default:
+-		printk(KERN_ERR PFX "Unsupported port config "
+-		       "10G[%d] 1G[%d]\n",
+-		       num_10g, num_1g);
+-		return -EINVAL;
++		case 0x14:
++			if (lowest_1g == 10)
++				parent->plat_type = PLAT_TYPE_VF_P0;
++			else if (lowest_1g == 26)
++				parent->plat_type = PLAT_TYPE_VF_P1;
++			else
++				goto unknown_vg_1g_port;
++
++			/* fallthru */
++		case 0x13:
++			if ((lowest_10g & 0x7) == 0)
++				val = (phy_encode(PORT_TYPE_10G, 0) |
++				       phy_encode(PORT_TYPE_1G, 1) |
++				       phy_encode(PORT_TYPE_1G, 2) |
++				       phy_encode(PORT_TYPE_1G, 3));
++			else
++				val = (phy_encode(PORT_TYPE_1G, 0) |
++				       phy_encode(PORT_TYPE_10G, 1) |
++				       phy_encode(PORT_TYPE_1G, 2) |
++				       phy_encode(PORT_TYPE_1G, 3));
++			break;
++
++		case 0x04:
++			if (lowest_1g == 10)
++				parent->plat_type = PLAT_TYPE_VF_P0;
++			else if (lowest_1g == 26)
++				parent->plat_type = PLAT_TYPE_VF_P1;
++			else
++				goto unknown_vg_1g_port;
++
++			val = (phy_encode(PORT_TYPE_1G, 0) |
++			       phy_encode(PORT_TYPE_1G, 1) |
++			       phy_encode(PORT_TYPE_1G, 2) |
++			       phy_encode(PORT_TYPE_1G, 3));
++			break;
++
++		default:
++			printk(KERN_ERR PFX "Unsupported port config "
++			       "10G[%d] 1G[%d]\n",
++			       num_10g, num_1g);
++			return -EINVAL;
++		}
+ 	}
+ 
+ 	parent->port_phy = val;
+@@ -7189,15 +8014,16 @@ static int __devinit niu_get_invariants(struct niu *np)
+ 
+ 	have_props = !err;
+ 
+-	err = niu_get_and_validate_port(np);
+-	if (err)
+-		return err;
+-
+ 	err = niu_init_mac_ipp_pcs_base(np);
+ 	if (err)
+ 		return err;
+ 
+-	if (!have_props) {
++	if (have_props) {
++		err = niu_get_and_validate_port(np);
++		if (err)
++			return err;
++
++	} else  {
+ 		if (np->parent->plat_type == PLAT_TYPE_NIU)
+ 			return -EINVAL;
+ 
+@@ -7209,10 +8035,17 @@ static int __devinit niu_get_invariants(struct niu *np)
+ 			niu_pci_vpd_fetch(np, offset);
+ 		nw64(ESPC_PIO_EN, 0);
+ 
+-		if (np->flags & NIU_FLAGS_VPD_VALID)
++		if (np->flags & NIU_FLAGS_VPD_VALID) {
+ 			niu_pci_vpd_validate(np);
++			err = niu_get_and_validate_port(np);
++			if (err)
++				return err;
++		}
+ 
+ 		if (!(np->flags & NIU_FLAGS_VPD_VALID)) {
++			err = niu_get_and_validate_port(np);
++			if (err)
++				return err;
+ 			err = niu_pci_probe_sprom(np);
+ 			if (err)
+ 				return err;
+@@ -7599,14 +8432,25 @@ static void __devinit niu_device_announce(struct niu *np)
+ 	pr_info("%s: NIU Ethernet %s\n",
+ 		dev->name, print_mac(mac, dev->dev_addr));
+ 
+-	pr_info("%s: Port type[%s] mode[%s:%s] XCVR[%s] phy[%s]\n",
+-		dev->name,
+-		(np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"),
+-		(np->flags & NIU_FLAGS_10G ? "10G" : "1G"),
+-		(np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"),
+-		(np->mac_xcvr == MAC_XCVR_MII ? "MII" :
+-		 (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")),
+-		np->vpd.phy_type);
++	if (np->parent->plat_type == PLAT_TYPE_ATCA_CP3220) {
++		pr_info("%s: Port type[%s] mode[%s:%s] XCVR[%s] phy[%s]\n",
++				dev->name,
++				(np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"),
++				(np->flags & NIU_FLAGS_10G ? "10G" : "1G"),
++				(np->flags & NIU_FLAGS_FIBER ? "RGMII FIBER" : "SERDES"),
++				(np->mac_xcvr == MAC_XCVR_MII ? "MII" :
++				 (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")),
++				np->vpd.phy_type);
++	} else {
++		pr_info("%s: Port type[%s] mode[%s:%s] XCVR[%s] phy[%s]\n",
++				dev->name,
++				(np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"),
++				(np->flags & NIU_FLAGS_10G ? "10G" : "1G"),
++				(np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"),
++				(np->mac_xcvr == MAC_XCVR_MII ? "MII" :
++				 (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")),
++				np->vpd.phy_type);
++	}
+ }
+ 
+ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
+diff --git a/drivers/net/niu.h b/drivers/net/niu.h
+index 59dc05f..97ffbe1 100644
+--- a/drivers/net/niu.h
++++ b/drivers/net/niu.h
+@@ -2537,6 +2537,7 @@ struct fcram_hash_ipv6 {
+ 
+ #define NIU_PHY_ID_MASK			0xfffff0f0
+ #define NIU_PHY_ID_BCM8704		0x00206030
++#define NIU_PHY_ID_BCM8706		0x00206035
+ #define NIU_PHY_ID_BCM5464R		0x002060b0
+ #define NIU_PHY_ID_MRVL88X2011		0x01410020
+ 
+@@ -2937,6 +2938,15 @@ struct rx_ring_info {
+ 
+ #define NIU_MAX_MTU		9216
+ 
++/* VPD strings */
++#define	NIU_QGC_LP_BM_STR	"501-7606"
++#define	NIU_2XGF_LP_BM_STR	"501-7283"
++#define	NIU_QGC_PEM_BM_STR	"501-7765"
++#define	NIU_2XGF_PEM_BM_STR	"501-7626"
++#define	NIU_ALONSO_BM_STR	"373-0202"
++#define	NIU_FOXXY_BM_STR	"501-7961"
++#define	NIU_2XGF_MRVL_BM_STR	"SK-6E82"
++
+ #define NIU_VPD_MIN_MAJOR	3
+ #define NIU_VPD_MIN_MINOR	4
+ 
+@@ -3061,6 +3071,7 @@ struct niu_parent {
+ #define PLAT_TYPE_NIU		0x02
+ #define PLAT_TYPE_VF_P0		0x03
+ #define PLAT_TYPE_VF_P1		0x04
++#define PLAT_TYPE_ATCA_CP3220	0x08
+ 
+ 	u8			num_ports;
+ 
+@@ -3198,10 +3209,13 @@ struct niu {
+ 	struct niu_parent		*parent;
+ 
+ 	u32				flags;
++#define NIU_FLAGS_HOTPLUG_PHY_PRESENT	0x02000000 /* Removebale PHY detected*/
++#define NIU_FLAGS_HOTPLUG_PHY		0x01000000 /* Removebale PHY */
++#define NIU_FLAGS_VPD_VALID		0x00800000 /* VPD has valid version */
+ #define NIU_FLAGS_MSIX			0x00400000 /* MSI-X in use */
+ #define NIU_FLAGS_MCAST			0x00200000 /* multicast filter enabled */
+ #define NIU_FLAGS_PROMISC		0x00100000 /* PROMISC enabled */
+-#define NIU_FLAGS_VPD_VALID		0x00080000 /* VPD has valid version */
++#define NIU_FLAGS_XCVR_SERDES		0x00080000 /* 0=PHY 1=SERDES */
+ #define NIU_FLAGS_10G			0x00040000 /* 0=1G 1=10G */
+ #define NIU_FLAGS_FIBER			0x00020000 /* 0=COPPER 1=FIBER */
+ #define NIU_FLAGS_XMAC			0x00010000 /* 0=BMAC 1=XMAC */
+diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
+index 2e39e02..3b2a6c5 100644
+--- a/drivers/net/pasemi_mac.c
++++ b/drivers/net/pasemi_mac.c
+@@ -55,15 +55,10 @@
+  * - Multiqueue RX/TX
+  */
+ 
+-
+-/* Must be a power of two */
+-#define RX_RING_SIZE 2048
+-#define TX_RING_SIZE 4096
+-
+ #define LRO_MAX_AGGR 64
+ 
+ #define PE_MIN_MTU	64
+-#define PE_MAX_MTU	1500
++#define PE_MAX_MTU	9000
+ #define PE_DEF_MTU	ETH_DATA_LEN
+ 
+ #define DEFAULT_MSG_ENABLE	  \
+@@ -76,16 +71,6 @@
+ 	 NETIF_MSG_RX_ERR	| \
+ 	 NETIF_MSG_TX_ERR)
+ 
+-#define TX_DESC(tx, num)	((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
+-#define TX_DESC_INFO(tx, num)	((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
+-#define RX_DESC(rx, num)	((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
+-#define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
+-#define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
+-
+-#define RING_USED(ring)		(((ring)->next_to_fill - (ring)->next_to_clean) \
+-				 & ((ring)->size - 1))
+-#define RING_AVAIL(ring)	((ring->size) - RING_USED(ring))
+-
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR ("Olof Johansson <olof at lixom.net>");
+ MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
+@@ -94,6 +79,8 @@ static int debug = -1;	/* -1 == use DEFAULT_MSG_ENABLE as value */
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
+ 
++extern const struct ethtool_ops pasemi_mac_ethtool_ops;
++
+ static int translation_enabled(void)
+ {
+ #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
+@@ -322,6 +309,104 @@ static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
+ 	return (nfrags + 3) & ~1;
+ }
+ 
++static struct pasemi_mac_csring *pasemi_mac_setup_csring(struct pasemi_mac *mac)
++{
++	struct pasemi_mac_csring *ring;
++	u32 val;
++	unsigned int cfg;
++	int chno;
++
++	ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring),
++				       offsetof(struct pasemi_mac_csring, chan));
++
++	if (!ring) {
++		dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n");
++		goto out_chan;
++	}
++
++	chno = ring->chan.chno;
++
++	ring->size = CS_RING_SIZE;
++	ring->next_to_fill = 0;
++
++	/* Allocate descriptors */
++	if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE))
++		goto out_ring_desc;
++
++	write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno),
++		      PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma));
++	val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32);
++	val |= PAS_DMA_TXCHAN_BASEU_SIZ(CS_RING_SIZE >> 3);
++
++	write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val);
++
++	ring->events[0] = pasemi_dma_alloc_flag();
++	ring->events[1] = pasemi_dma_alloc_flag();
++	if (ring->events[0] < 0 || ring->events[1] < 0)
++		goto out_flags;
++
++	pasemi_dma_clear_flag(ring->events[0]);
++	pasemi_dma_clear_flag(ring->events[1]);
++
++	ring->fun = pasemi_dma_alloc_fun();
++	if (ring->fun < 0)
++		goto out_fun;
++
++	cfg = PAS_DMA_TXCHAN_CFG_TY_FUNC | PAS_DMA_TXCHAN_CFG_UP |
++	      PAS_DMA_TXCHAN_CFG_TATTR(ring->fun) |
++	      PAS_DMA_TXCHAN_CFG_LPSQ | PAS_DMA_TXCHAN_CFG_LPDQ;
++
++	if (translation_enabled())
++		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
++
++	write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg);
++
++	/* enable channel */
++	pasemi_dma_start_chan(&ring->chan, PAS_DMA_TXCHAN_TCMDSTA_SZ |
++					   PAS_DMA_TXCHAN_TCMDSTA_DB |
++					   PAS_DMA_TXCHAN_TCMDSTA_DE |
++					   PAS_DMA_TXCHAN_TCMDSTA_DA);
++
++	return ring;
++
++out_fun:
++out_flags:
++	if (ring->events[0] >= 0)
++		pasemi_dma_free_flag(ring->events[0]);
++	if (ring->events[1] >= 0)
++		pasemi_dma_free_flag(ring->events[1]);
++	pasemi_dma_free_ring(&ring->chan);
++out_ring_desc:
++	pasemi_dma_free_chan(&ring->chan);
++out_chan:
++
++	return NULL;
++}
++
++static void pasemi_mac_setup_csrings(struct pasemi_mac *mac)
++{
++	int i;
++	mac->cs[0] = pasemi_mac_setup_csring(mac);
++	if (mac->type == MAC_TYPE_XAUI)
++		mac->cs[1] = pasemi_mac_setup_csring(mac);
++	else
++		mac->cs[1] = 0;
++
++	for (i = 0; i < MAX_CS; i++)
++		if (mac->cs[i])
++			mac->num_cs++;
++}
++
++static void pasemi_mac_free_csring(struct pasemi_mac_csring *csring)
++{
++	pasemi_dma_stop_chan(&csring->chan);
++	pasemi_dma_free_flag(csring->events[0]);
++	pasemi_dma_free_flag(csring->events[1]);
++	pasemi_dma_free_ring(&csring->chan);
++	pasemi_dma_free_chan(&csring->chan);
++	pasemi_dma_free_fun(csring->fun);
++}
++
+ static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
+ {
+ 	struct pasemi_mac_rxring *ring;
+@@ -445,7 +530,7 @@ pasemi_mac_setup_tx_resources(const struct net_device *dev)
+ 	cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
+ 	      PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
+ 	      PAS_DMA_TXCHAN_CFG_UP |
+-	      PAS_DMA_TXCHAN_CFG_WT(2);
++	      PAS_DMA_TXCHAN_CFG_WT(4);
+ 
+ 	if (translation_enabled())
+ 		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
+@@ -810,13 +895,21 @@ restart:
+ 		u64 mactx = TX_DESC(txring, i);
+ 		struct sk_buff *skb;
+ 
+-		skb = TX_DESC_INFO(txring, i+1).skb;
+-		nr_frags = TX_DESC_INFO(txring, i).dma;
+-
+ 		if ((mactx  & XCT_MACTX_E) ||
+ 		    (*chan->status & PAS_STATUS_ERROR))
+ 			pasemi_mac_tx_error(mac, mactx);
+ 
++		/* Skip over control descriptors */
++		if (!(mactx & XCT_MACTX_LLEN_M)) {
++			TX_DESC(txring, i) = 0;
++			TX_DESC(txring, i+1) = 0;
++			buf_count = 2;
++			continue;
++		}
++
++		skb = TX_DESC_INFO(txring, i+1).skb;
++		nr_frags = TX_DESC_INFO(txring, i).dma;
++
+ 		if (unlikely(mactx & XCT_MACTX_O))
+ 			/* Not yet transmitted */
+ 			break;
+@@ -1012,7 +1105,7 @@ static int pasemi_mac_phy_init(struct net_device *dev)
+ 		goto err;
+ 
+ 	phy_id = *prop;
+-	snprintf(mac->phy_id, BUS_ID_SIZE, PHY_ID_FMT, (int)r.start, phy_id);
++	snprintf(mac->phy_id, BUS_ID_SIZE, "%x:%02x", (int)r.start, phy_id);
+ 
+ 	of_node_put(phy_dn);
+ 
+@@ -1041,13 +1134,7 @@ static int pasemi_mac_open(struct net_device *dev)
+ {
+ 	struct pasemi_mac *mac = netdev_priv(dev);
+ 	unsigned int flags;
+-	int ret;
+-
+-	/* enable rx section */
+-	write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
+-
+-	/* enable tx section */
+-	write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
++	int i, ret;
+ 
+ 	flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
+ 		PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
+@@ -1064,6 +1151,19 @@ static int pasemi_mac_open(struct net_device *dev)
+ 	if (!mac->tx)
+ 		goto out_tx_ring;
+ 
++	/* We might already have allocated rings in case mtu was changed
++	 * before interface was brought up.
++	 */
++	if (dev->mtu > 1500 && !mac->num_cs) {
++		pasemi_mac_setup_csrings(mac);
++		if (!mac->num_cs)
++			goto out_tx_ring;
++	}
++
++	/* Zero out rmon counters */
++	for (i = 0; i < 32; i++)
++		write_mac_reg(mac, PAS_MAC_RMON(i), 0);
++
+ 	/* 0x3ff with 33MHz clock is about 31us */
+ 	write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
+ 		      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
+@@ -1247,7 +1347,7 @@ static int pasemi_mac_close(struct net_device *dev)
+ {
+ 	struct pasemi_mac *mac = netdev_priv(dev);
+ 	unsigned int sta;
+-	int rxch, txch;
++	int rxch, txch, i;
+ 
+ 	rxch = rx_ring(mac)->chan.chno;
+ 	txch = tx_ring(mac)->chan.chno;
+@@ -1292,6 +1392,13 @@ static int pasemi_mac_close(struct net_device *dev)
+ 	free_irq(mac->tx->chan.irq, mac->tx);
+ 	free_irq(mac->rx->chan.irq, mac->rx);
+ 
++	for (i = 0; i < mac->num_cs; i++) {
++		pasemi_mac_free_csring(mac->cs[i]);
++		mac->cs[i] = NULL;
++	}
++
++	mac->num_cs = 0;
++
+ 	/* Free resources */
+ 	pasemi_mac_free_rx_resources(mac);
+ 	pasemi_mac_free_tx_resources(mac);
+@@ -1299,35 +1406,113 @@ static int pasemi_mac_close(struct net_device *dev)
+ 	return 0;
+ }
+ 
++static void pasemi_mac_queue_csdesc(const struct sk_buff *skb,
++				    const dma_addr_t *map,
++				    const unsigned int *map_size,
++				    struct pasemi_mac_txring *txring,
++				    struct pasemi_mac_csring *csring)
++{
++	u64 fund;
++	dma_addr_t cs_dest;
++	const int nh_off = skb_network_offset(skb);
++	const int nh_len = skb_network_header_len(skb);
++	const int nfrags = skb_shinfo(skb)->nr_frags;
++	int cs_size, i, fill, hdr, cpyhdr, evt;
++	dma_addr_t csdma;
++
++	fund = XCT_FUN_ST | XCT_FUN_RR_8BRES |
++	       XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
++	       XCT_FUN_CRM_SIG | XCT_FUN_LLEN(skb->len - nh_off) |
++	       XCT_FUN_SHL(nh_len >> 2) | XCT_FUN_SE;
++
++	switch (ip_hdr(skb)->protocol) {
++	case IPPROTO_TCP:
++		fund |= XCT_FUN_SIG_TCP4;
++		/* TCP checksum is 16 bytes into the header */
++		cs_dest = map[0] + skb_transport_offset(skb) + 16;
++		break;
++	case IPPROTO_UDP:
++		fund |= XCT_FUN_SIG_UDP4;
++		/* UDP checksum is 6 bytes into the header */
++		cs_dest = map[0] + skb_transport_offset(skb) + 6;
++		break;
++	default:
++		BUG();
++	}
++
++	/* Do the checksum offloaded */
++	fill = csring->next_to_fill;
++	hdr = fill;
++
++	CS_DESC(csring, fill++) = fund;
++	/* Room for 8BRES. Checksum result is really 2 bytes into it */
++	csdma = csring->chan.ring_dma + (fill & (CS_RING_SIZE-1)) * 8 + 2;
++	CS_DESC(csring, fill++) = 0;
++
++	CS_DESC(csring, fill) = XCT_PTR_LEN(map_size[0]-nh_off) | XCT_PTR_ADDR(map[0]+nh_off);
++	for (i = 1; i <= nfrags; i++)
++		CS_DESC(csring, fill+i) = XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
++
++	fill += i;
++	if (fill & 1)
++		fill++;
++
++	/* Copy the result into the TCP packet */
++	cpyhdr = fill;
++	CS_DESC(csring, fill++) = XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
++				  XCT_FUN_LLEN(2) | XCT_FUN_SE;
++	CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(cs_dest) | XCT_PTR_T;
++	CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(csdma);
++	fill++;
++
++	evt = !csring->last_event;
++	csring->last_event = evt;
++
++	/* Event handshaking with MAC TX */
++	CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
++				  CTRL_CMD_ETYPE_SET | CTRL_CMD_REG(csring->events[evt]);
++	CS_DESC(csring, fill++) = 0;
++	CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
++				  CTRL_CMD_ETYPE_WCLR | CTRL_CMD_REG(csring->events[!evt]);
++	CS_DESC(csring, fill++) = 0;
++	csring->next_to_fill = fill & (CS_RING_SIZE-1);
++
++	cs_size = fill - hdr;
++	write_dma_reg(PAS_DMA_TXCHAN_INCR(csring->chan.chno), (cs_size) >> 1);
++
++	/* TX-side event handshaking */
++	fill = txring->next_to_fill;
++	TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
++				  CTRL_CMD_ETYPE_WSET | CTRL_CMD_REG(csring->events[evt]);
++	TX_DESC(txring, fill++) = 0;
++	TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
++				  CTRL_CMD_ETYPE_CLR | CTRL_CMD_REG(csring->events[!evt]);
++	TX_DESC(txring, fill++) = 0;
++	txring->next_to_fill = fill;
++
++	write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
++
++	return;
++}
++
+ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
+ {
+-	struct pasemi_mac *mac = netdev_priv(dev);
+-	struct pasemi_mac_txring *txring;
+-	u64 dflags, mactx;
++	struct pasemi_mac * const mac = netdev_priv(dev);
++	struct pasemi_mac_txring * const txring = tx_ring(mac);
++	struct pasemi_mac_csring *csring;
++	u64 dflags = 0;
++	u64 mactx;
+ 	dma_addr_t map[MAX_SKB_FRAGS+1];
+ 	unsigned int map_size[MAX_SKB_FRAGS+1];
+ 	unsigned long flags;
+ 	int i, nfrags;
+ 	int fill;
++	const int nh_off = skb_network_offset(skb);
++	const int nh_len = skb_network_header_len(skb);
+ 
+-	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
+-
+-	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+-		const unsigned char *nh = skb_network_header(skb);
++	prefetch(&txring->ring_info);
+ 
+-		switch (ip_hdr(skb)->protocol) {
+-		case IPPROTO_TCP:
+-			dflags |= XCT_MACTX_CSUM_TCP;
+-			dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
+-			dflags |= XCT_MACTX_IPO(nh - skb->data);
+-			break;
+-		case IPPROTO_UDP:
+-			dflags |= XCT_MACTX_CSUM_UDP;
+-			dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
+-			dflags |= XCT_MACTX_IPO(nh - skb->data);
+-			break;
+-		}
+-	}
++	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
+ 
+ 	nfrags = skb_shinfo(skb)->nr_frags;
+ 
+@@ -1350,24 +1535,46 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
+ 		}
+ 	}
+ 
+-	mactx = dflags | XCT_MACTX_LLEN(skb->len);
++	if (skb->ip_summed == CHECKSUM_PARTIAL && skb->len <= 1540) {
++		switch (ip_hdr(skb)->protocol) {
++		case IPPROTO_TCP:
++			dflags |= XCT_MACTX_CSUM_TCP;
++			dflags |= XCT_MACTX_IPH(nh_len >> 2);
++			dflags |= XCT_MACTX_IPO(nh_off);
++			break;
++		case IPPROTO_UDP:
++			dflags |= XCT_MACTX_CSUM_UDP;
++			dflags |= XCT_MACTX_IPH(nh_len >> 2);
++			dflags |= XCT_MACTX_IPO(nh_off);
++			break;
++		default:
++			WARN_ON(1);
++		}
++	}
+ 
+-	txring = tx_ring(mac);
++	mactx = dflags | XCT_MACTX_LLEN(skb->len);
+ 
+ 	spin_lock_irqsave(&txring->lock, flags);
+ 
+-	fill = txring->next_to_fill;
+-
+ 	/* Avoid stepping on the same cache line that the DMA controller
+ 	 * is currently about to send, so leave at least 8 words available.
+ 	 * Total free space needed is mactx + fragments + 8
+ 	 */
+-	if (RING_AVAIL(txring) < nfrags + 10) {
++	if (RING_AVAIL(txring) < nfrags + 14) {
+ 		/* no room -- stop the queue and wait for tx intr */
+ 		netif_stop_queue(dev);
+ 		goto out_err;
+ 	}
+ 
++	/* Queue up checksum + event descriptors, if needed */
++	if (mac->num_cs && skb->ip_summed == CHECKSUM_PARTIAL && skb->len > 1540) {
++		csring = mac->cs[mac->last_cs];
++		mac->last_cs = (mac->last_cs + 1) % mac->num_cs;
++
++		pasemi_mac_queue_csdesc(skb, map, map_size, txring, csring);
++	}
++
++	fill = txring->next_to_fill;
+ 	TX_DESC(txring, fill) = mactx;
+ 	TX_DESC_INFO(txring, fill).dma = nfrags;
+ 	fill++;
+@@ -1441,12 +1648,33 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget)
+ 	return pkts;
+ }
+ 
++#ifdef CONFIG_NET_POLL_CONTROLLER
++/*
++ * Polling 'interrupt' - used by things like netconsole to send skbs
++ * without having to re-enable interrupts. It's not called while
++ * the interrupt routine is executing.
++ */
++static void pasemi_mac_netpoll(struct net_device *dev)
++{
++	const struct pasemi_mac *mac = netdev_priv(dev);
++
++	disable_irq(mac->tx->chan.irq);
++	pasemi_mac_tx_intr(mac->tx->chan.irq, mac->tx);
++	enable_irq(mac->tx->chan.irq);
++
++	disable_irq(mac->rx->chan.irq);
++	pasemi_mac_rx_intr(mac->rx->chan.irq, mac->rx);
++	enable_irq(mac->rx->chan.irq);
++}
++#endif
++
+ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+ {
+ 	struct pasemi_mac *mac = netdev_priv(dev);
+ 	unsigned int reg;
+-	unsigned int rcmdsta;
++	unsigned int rcmdsta = 0;
+ 	int running;
++	int ret = 0;
+ 
+ 	if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
+ 		return -EINVAL;
+@@ -1468,6 +1696,16 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+ 		pasemi_mac_pause_rxint(mac);
+ 		pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
+ 		pasemi_mac_free_rx_buffers(mac);
++
++	}
++
++	/* Setup checksum channels if large MTU and none already allocated */
++	if (new_mtu > 1500 && !mac->num_cs) {
++		pasemi_mac_setup_csrings(mac);
++		if (!mac->num_cs) {
++			ret = -ENOMEM;
++			goto out;
++		}
+ 	}
+ 
+ 	/* Change maxf, i.e. what size frames are accepted.
+@@ -1482,6 +1720,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+ 	/* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
+ 	mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
+ 
++out:
+ 	if (running) {
+ 		write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
+ 			      rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
+@@ -1494,7 +1733,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+ 		pasemi_mac_intf_enable(mac);
+ 	}
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ static int __devinit
+@@ -1528,7 +1767,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
+ 
+ 	dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
+-			NETIF_F_HIGHDMA;
++			NETIF_F_HIGHDMA | NETIF_F_GSO;
+ 
+ 	mac->lro_mgr.max_aggr = LRO_MAX_AGGR;
+ 	mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
+@@ -1588,8 +1827,12 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	dev->mtu = PE_DEF_MTU;
+ 	/* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
+ 	mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++	dev->poll_controller = pasemi_mac_netpoll;
++#endif
+ 
+ 	dev->change_mtu = pasemi_mac_change_mtu;
++	dev->ethtool_ops = &pasemi_mac_ethtool_ops;
+ 
+ 	if (err)
+ 		goto out;
+diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
+index 99e7b93..1a115ec 100644
+--- a/drivers/net/pasemi_mac.h
++++ b/drivers/net/pasemi_mac.h
+@@ -26,7 +26,14 @@
+ #include <linux/spinlock.h>
+ #include <linux/phy.h>
+ 
++/* Must be a power of two */
++#define RX_RING_SIZE 2048
++#define TX_RING_SIZE 4096
++#define CS_RING_SIZE (TX_RING_SIZE*2)
++
++
+ #define MAX_LRO_DESCRIPTORS 8
++#define MAX_CS	2
+ 
+ struct pasemi_mac_txring {
+ 	struct pasemi_dmachan chan; /* Must be first */
+@@ -51,6 +58,15 @@ struct pasemi_mac_rxring {
+ 	struct pasemi_mac *mac;	/* Needed in intr handler */
+ };
+ 
++struct pasemi_mac_csring {
++	struct pasemi_dmachan chan;
++	unsigned int	size;
++	unsigned int	next_to_fill;
++	int		events[2];
++	int		last_event;
++	int		fun;
++};
++
+ struct pasemi_mac {
+ 	struct net_device *netdev;
+ 	struct pci_dev *pdev;
+@@ -60,10 +76,12 @@ struct pasemi_mac {
+ 	struct napi_struct napi;
+ 
+ 	int		bufsz; /* RX ring buffer size */
++	int		last_cs;
++	int		num_cs;
++	u32		dma_if;
+ 	u8		type;
+ #define MAC_TYPE_GMAC	1
+ #define MAC_TYPE_XAUI	2
+-	u32	dma_if;
+ 
+ 	u8		mac_addr[6];
+ 
+@@ -74,6 +92,7 @@ struct pasemi_mac {
+ 
+ 	struct pasemi_mac_txring *tx;
+ 	struct pasemi_mac_rxring *rx;
++	struct pasemi_mac_csring *cs[MAX_CS];
+ 	char		tx_irq_name[10];		/* "eth%d tx" */
+ 	char		rx_irq_name[10];		/* "eth%d rx" */
+ 	int	link;
+@@ -90,6 +109,16 @@ struct pasemi_mac_buffer {
+ 	dma_addr_t	dma;
+ };
+ 
++#define TX_DESC(tx, num)	((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
++#define TX_DESC_INFO(tx, num)	((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
++#define RX_DESC(rx, num)	((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
++#define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
++#define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
++#define CS_DESC(cs, num)	((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
++
++#define RING_USED(ring)	(((ring)->next_to_fill - (ring)->next_to_clean) \
++				& ((ring)->size - 1))
++#define RING_AVAIL(ring)	((ring->size) - RING_USED(ring))
+ 
+ /* PCI register offsets and formats */
+ 
+@@ -101,6 +130,7 @@ enum {
+ 	PAS_MAC_CFG_ADR0 = 0x8c,
+ 	PAS_MAC_CFG_ADR1 = 0x90,
+ 	PAS_MAC_CFG_TXP = 0x98,
++	PAS_MAC_CFG_RMON = 0x100,
+ 	PAS_MAC_IPC_CHNL = 0x208,
+ };
+ 
+@@ -172,6 +202,8 @@ enum {
+ #define PAS_MAC_CFG_TXP_TIFG(x)		(((x) << PAS_MAC_CFG_TXP_TIFG_S) & \
+ 					 PAS_MAC_CFG_TXP_TIFG_M)
+ 
++#define PAS_MAC_RMON(r)			(0x100+(r)*4)
++
+ #define PAS_MAC_IPC_CHNL_DCHNO_M	0x003f0000
+ #define PAS_MAC_IPC_CHNL_DCHNO_S	16
+ #define PAS_MAC_IPC_CHNL_DCHNO(x)	(((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \
+@@ -181,4 +213,5 @@ enum {
+ #define PAS_MAC_IPC_CHNL_BCH(x)		(((x) << PAS_MAC_IPC_CHNL_BCH_S) & \
+ 					 PAS_MAC_IPC_CHNL_BCH_M)
+ 
++
+ #endif /* PASEMI_MAC_H */
+diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c
+new file mode 100644
+index 0000000..5e8df3a
+--- /dev/null
++++ b/drivers/net/pasemi_mac_ethtool.c
+@@ -0,0 +1,159 @@
++/*
++ * Copyright (C) 2006-2008 PA Semi, Inc
++ *
++ * Ethtool hooks for the PA Semi PWRficient onchip 1G/10G Ethernet MACs
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
++ */
++
++
++#include <linux/netdevice.h>
++#include <linux/ethtool.h>
++#include <linux/pci.h>
++#include <linux/inet_lro.h>
++
++#include <asm/pasemi_dma.h>
++#include "pasemi_mac.h"
++
++static struct {
++	const char str[ETH_GSTRING_LEN];
++} ethtool_stats_keys[] = {
++	{ "rx-drops" },
++	{ "rx-bytes" },
++	{ "rx-packets" },
++	{ "rx-broadcast-packets" },
++	{ "rx-multicast-packets" },
++	{ "rx-crc-errors" },
++	{ "rx-undersize-errors" },
++	{ "rx-oversize-errors" },
++	{ "rx-short-fragment-errors" },
++	{ "rx-jabber-errors" },
++	{ "rx-64-byte-packets" },
++	{ "rx-65-127-byte-packets" },
++	{ "rx-128-255-byte-packets" },
++	{ "rx-256-511-byte-packets" },
++	{ "rx-512-1023-byte-packets" },
++	{ "rx-1024-1518-byte-packets" },
++	{ "rx-pause-frames" },
++	{ "tx-bytes" },
++	{ "tx-packets" },
++	{ "tx-broadcast-packets" },
++	{ "tx-multicast-packets" },
++	{ "tx-collisions" },
++	{ "tx-late-collisions" },
++	{ "tx-excessive-collisions" },
++	{ "tx-crc-errors" },
++	{ "tx-undersize-errors" },
++	{ "tx-oversize-errors" },
++	{ "tx-64-byte-packets" },
++	{ "tx-65-127-byte-packets" },
++	{ "tx-128-255-byte-packets" },
++	{ "tx-256-511-byte-packets" },
++	{ "tx-512-1023-byte-packets" },
++	{ "tx-1024-1518-byte-packets" },
++};
++
++static int
++pasemi_mac_ethtool_get_settings(struct net_device *netdev,
++			       struct ethtool_cmd *cmd)
++{
++	struct pasemi_mac *mac = netdev_priv(netdev);
++	struct phy_device *phydev = mac->phydev;
++
++	return phy_ethtool_gset(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)
++{
++	struct pasemi_mac *mac = netdev_priv(netdev);
++	return mac->msg_enable;
++}
++
++static void
++pasemi_mac_ethtool_set_msglevel(struct net_device *netdev,
++				u32 level)
++{
++	struct pasemi_mac *mac = netdev_priv(netdev);
++	mac->msg_enable = level;
++}
++
++
++static void
++pasemi_mac_ethtool_get_ringparam(struct net_device *netdev,
++				 struct ethtool_ringparam *ering)
++{
++	struct pasemi_mac *mac = netdev->priv;
++
++	ering->tx_max_pending = TX_RING_SIZE/2;
++	ering->tx_pending = RING_USED(mac->tx)/2;
++	ering->rx_max_pending = RX_RING_SIZE/4;
++	ering->rx_pending = RING_USED(mac->rx)/4;
++}
++
++static int pasemi_mac_get_sset_count(struct net_device *netdev, int sset)
++{
++	switch (sset) {
++	case ETH_SS_STATS:
++		return ARRAY_SIZE(ethtool_stats_keys);
++	default:
++		return -EOPNOTSUPP;
++	}
++}
++
++static void pasemi_mac_get_ethtool_stats(struct net_device *netdev,
++		struct ethtool_stats *stats, u64 *data)
++{
++	struct pasemi_mac *mac = netdev->priv;
++	int i;
++
++	data[0] = pasemi_read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if))
++			>> PAS_DMA_RXINT_RCMDSTA_DROPS_S;
++	for (i = 0; i < 32; i++)
++		data[1+i] = pasemi_read_mac_reg(mac->dma_if, PAS_MAC_RMON(i));
++}
++
++static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset,
++				   u8 *data)
++{
++	memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
++}
++
++const struct ethtool_ops pasemi_mac_ethtool_ops = {
++	.get_settings		= pasemi_mac_ethtool_get_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,
++	.get_ringparam          = pasemi_mac_ethtool_get_ringparam,
++	.get_strings		= pasemi_mac_get_strings,
++	.get_sset_count		= pasemi_mac_get_sset_count,
++	.get_ethtool_stats	= pasemi_mac_get_ethtool_stats,
++};
++
+diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
+index 5b80358..60c5cfe 100644
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -99,6 +99,41 @@ static int bcm54xx_config_intr(struct phy_device *phydev)
+ 	return err;
+ }
+ 
++static int bcm5481_config_aneg(struct phy_device *phydev)
++{
++	int ret;
++
++	/* Aneg firsly. */
++	ret = genphy_config_aneg(phydev);
++
++	/* Then we can set up the delay. */
++	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
++		u16 reg;
++
++		/*
++		 * There is no BCM5481 specification available, so down
++		 * here is everything we know about "register 0x18". This
++		 * at least helps BCM5481 to successfuly receive packets
++		 * on MPC8360E-RDK board. Peter Barada <peterb at logicpd.com>
++		 * says: "This sets delay between the RXD and RXC signals
++		 * instead of using trace lengths to achieve timing".
++		 */
++
++		/* Set RDX clk delay. */
++		reg = 0x7 | (0x7 << 12);
++		phy_write(phydev, 0x18, reg);
++
++		reg = phy_read(phydev, 0x18);
++		/* Set RDX-RXC skew. */
++		reg |= (1 << 8);
++		/* Write bits 14:0. */
++		reg |= (1 << 15);
++		phy_write(phydev, 0x18, reg);
++	}
++
++	return ret;
++}
++
+ static struct phy_driver bcm5411_driver = {
+ 	.phy_id		= 0x00206070,
+ 	.phy_id_mask	= 0xfffffff0,
+@@ -141,8 +176,36 @@ static struct phy_driver bcm5461_driver = {
+ 	.driver 	= { .owner = THIS_MODULE },
+ };
+ 
++static struct phy_driver bcm5464_driver = {
++	.phy_id		= 0x002060b0,
++	.phy_id_mask	= 0xfffffff0,
++	.name		= "Broadcom BCM5464",
++	.features	= PHY_GBIT_FEATURES,
++	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
++	.config_init	= bcm54xx_config_init,
++	.config_aneg	= genphy_config_aneg,
++	.read_status	= genphy_read_status,
++	.ack_interrupt	= bcm54xx_ack_interrupt,
++	.config_intr	= bcm54xx_config_intr,
++	.driver 	= { .owner = THIS_MODULE },
++};
++
++static struct phy_driver bcm5481_driver = {
++	.phy_id		= 0x0143bca0,
++	.phy_id_mask	= 0xfffffff0,
++	.name		= "Broadcom BCM5481",
++	.features	= PHY_GBIT_FEATURES,
++	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
++	.config_init	= bcm54xx_config_init,
++	.config_aneg	= bcm5481_config_aneg,
++	.read_status	= genphy_read_status,
++	.ack_interrupt	= bcm54xx_ack_interrupt,
++	.config_intr	= bcm54xx_config_intr,
++	.driver 	= { .owner = THIS_MODULE },
++};
++
+ static struct phy_driver bcm5482_driver = {
+-    .phy_id		= 0x0143bcb0,
++	.phy_id		= 0x0143bcb0,
+ 	.phy_id_mask	= 0xfffffff0,
+ 	.name		= "Broadcom BCM5482",
+ 	.features	= PHY_GBIT_FEATURES,
+@@ -168,12 +231,22 @@ static int __init broadcom_init(void)
+ 	ret = phy_driver_register(&bcm5461_driver);
+ 	if (ret)
+ 		goto out_5461;
++	ret = phy_driver_register(&bcm5464_driver);
++	if (ret)
++		goto out_5464;
++	ret = phy_driver_register(&bcm5481_driver);
++	if (ret)
++		goto out_5481;
+ 	ret = phy_driver_register(&bcm5482_driver);
+ 	if (ret)
+ 		goto out_5482;
+ 	return ret;
+ 
+ out_5482:
++	phy_driver_unregister(&bcm5481_driver);
++out_5481:
++	phy_driver_unregister(&bcm5464_driver);
++out_5464:
+ 	phy_driver_unregister(&bcm5461_driver);
+ out_5461:
+ 	phy_driver_unregister(&bcm5421_driver);
+@@ -186,6 +259,8 @@ out_5411:
+ static void __exit broadcom_exit(void)
+ {
+ 	phy_driver_unregister(&bcm5482_driver);
++	phy_driver_unregister(&bcm5481_driver);
++	phy_driver_unregister(&bcm5464_driver);
+ 	phy_driver_unregister(&bcm5461_driver);
+ 	phy_driver_unregister(&bcm5421_driver);
+ 	phy_driver_unregister(&bcm5411_driver);
+diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
+index ca9b040..4e07956 100644
+--- a/drivers/net/phy/fixed.c
++++ b/drivers/net/phy/fixed.c
+@@ -213,7 +213,7 @@ static int __init fixed_mdio_bus_init(void)
+ 		goto err_pdev;
+ 	}
+ 
+-	fmb->mii_bus.id = 0;
++	snprintf(fmb->mii_bus.id, MII_BUS_ID_SIZE, "0");
+ 	fmb->mii_bus.name = "Fixed MDIO Bus";
+ 	fmb->mii_bus.dev = &pdev->dev;
+ 	fmb->mii_bus.read = &fixed_mdio_read;
+diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
+index 963630c..94e0b7e 100644
+--- a/drivers/net/phy/mdio_bus.c
++++ b/drivers/net/phy/mdio_bus.c
+@@ -89,6 +89,9 @@ int mdiobus_register(struct mii_bus *bus)
+ 
+ 			phydev->bus = bus;
+ 
++			/* Run all of the fixups for this PHY */
++			phy_scan_fixups(phydev);
++
+ 			err = device_register(&phydev->dev);
+ 
+ 			if (err) {
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index 12fccb1..3c18bb5 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -406,8 +406,10 @@ int phy_mii_ioctl(struct phy_device *phydev,
+ 		
+ 		if (mii_data->reg_num == MII_BMCR 
+ 				&& val & BMCR_RESET
+-				&& phydev->drv->config_init)
++				&& phydev->drv->config_init) {
++			phy_scan_fixups(phydev);
+ 			phydev->drv->config_init(phydev);
++		}
+ 		break;
+ 
+ 	default:
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index f4c4fd8..ddf8d51 100644
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -53,6 +53,96 @@ static void phy_device_release(struct device *dev)
+ 	phy_device_free(to_phy_device(dev));
+ }
+ 
++static LIST_HEAD(phy_fixup_list);
++static DEFINE_MUTEX(phy_fixup_lock);
++
++/*
++ * Creates a new phy_fixup and adds it to the list
++ * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID)
++ * @phy_uid: Used to match against phydev->phy_id (the UID of the PHY)
++ * 	It can also be PHY_ANY_UID
++ * @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before
++ * 	comparison
++ * @run: The actual code to be run when a matching PHY is found
++ */
++int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
++		int (*run)(struct phy_device *))
++{
++	struct phy_fixup *fixup;
++
++	fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL);
++	if (!fixup)
++		return -ENOMEM;
++
++	strncpy(fixup->bus_id, bus_id, BUS_ID_SIZE);
++	fixup->phy_uid = phy_uid;
++	fixup->phy_uid_mask = phy_uid_mask;
++	fixup->run = run;
++
++	mutex_lock(&phy_fixup_lock);
++	list_add_tail(&fixup->list, &phy_fixup_list);
++	mutex_unlock(&phy_fixup_lock);
++
++	return 0;
++}
++EXPORT_SYMBOL(phy_register_fixup);
++
++/* Registers a fixup to be run on any PHY with the UID in phy_uid */
++int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
++		int (*run)(struct phy_device *))
++{
++	return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run);
++}
++EXPORT_SYMBOL(phy_register_fixup_for_uid);
++
++/* Registers a fixup to be run on the PHY with id string bus_id */
++int phy_register_fixup_for_id(const char *bus_id,
++		int (*run)(struct phy_device *))
++{
++	return phy_register_fixup(bus_id, PHY_ANY_UID, 0xffffffff, run);
++}
++EXPORT_SYMBOL(phy_register_fixup_for_id);
++
++/*
++ * Returns 1 if fixup matches phydev in bus_id and phy_uid.
++ * Fixups can be set to match any in one or more fields.
++ */
++static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
++{
++	if (strcmp(fixup->bus_id, phydev->dev.bus_id) != 0)
++		if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
++			return 0;
++
++	if ((fixup->phy_uid & fixup->phy_uid_mask) !=
++			(phydev->phy_id & fixup->phy_uid_mask))
++		if (fixup->phy_uid != PHY_ANY_UID)
++			return 0;
++
++	return 1;
++}
++
++/* Runs any matching fixups for this phydev */
++int phy_scan_fixups(struct phy_device *phydev)
++{
++	struct phy_fixup *fixup;
++
++	mutex_lock(&phy_fixup_lock);
++	list_for_each_entry(fixup, &phy_fixup_list, list) {
++		if (phy_needs_fixup(phydev, fixup)) {
++			int err;
++
++			err = fixup->run(phydev);
++
++			if (err < 0)
++				return err;
++		}
++	}
++	mutex_unlock(&phy_fixup_lock);
++
++	return 0;
++}
++EXPORT_SYMBOL(phy_scan_fixups);
++
+ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
+ {
+ 	struct phy_device *dev;
+@@ -86,35 +176,55 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
+ EXPORT_SYMBOL(phy_device_create);
+ 
+ /**
+- * get_phy_device - reads the specified PHY device and returns its @phy_device struct
++ * get_phy_id - reads the specified addr for its ID.
+  * @bus: the target MII bus
+  * @addr: PHY address on the MII bus
++ * @phy_id: where to store the ID retrieved.
+  *
+  * Description: Reads the ID registers of the PHY at @addr on the
+- *   @bus, then allocates and returns the phy_device to represent it.
++ *   @bus, stores it in @phy_id and returns zero on success.
+  */
+-struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
++int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
+ {
+ 	int phy_reg;
+-	u32 phy_id;
+-	struct phy_device *dev = NULL;
+ 
+ 	/* Grab the bits from PHYIR1, and put them
+ 	 * in the upper half */
+ 	phy_reg = bus->read(bus, addr, MII_PHYSID1);
+ 
+ 	if (phy_reg < 0)
+-		return ERR_PTR(phy_reg);
++		return -EIO;
+ 
+-	phy_id = (phy_reg & 0xffff) << 16;
++	*phy_id = (phy_reg & 0xffff) << 16;
+ 
+ 	/* Grab the bits from PHYIR2, and put them in the lower half */
+ 	phy_reg = bus->read(bus, addr, MII_PHYSID2);
+ 
+ 	if (phy_reg < 0)
+-		return ERR_PTR(phy_reg);
++		return -EIO;
++
++	*phy_id |= (phy_reg & 0xffff);
++
++	return 0;
++}
++
++/**
++ * get_phy_device - reads the specified PHY device and returns its @phy_device struct
++ * @bus: the target MII bus
++ * @addr: PHY address on the MII bus
++ *
++ * Description: Reads the ID registers of the PHY at @addr on the
++ *   @bus, then allocates and returns the phy_device to represent it.
++ */
++struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
++{
++	struct phy_device *dev = NULL;
++	u32 phy_id;
++	int r;
+ 
+-	phy_id |= (phy_reg & 0xffff);
++	r = get_phy_id(bus, addr, &phy_id);
++	if (r)
++		return ERR_PTR(r);
+ 
+ 	/* If the phy_id is all Fs, there is no device there */
+ 	if (0xffffffff == phy_id)
+@@ -159,13 +269,13 @@ void phy_prepare_link(struct phy_device *phydev,
+  *   choose to call only the subset of functions which provide
+  *   the desired functionality.
+  */
+-struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
++struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
+ 		void (*handler)(struct net_device *), u32 flags,
+ 		phy_interface_t interface)
+ {
+ 	struct phy_device *phydev;
+ 
+-	phydev = phy_attach(dev, phy_id, flags, interface);
++	phydev = phy_attach(dev, bus_id, flags, interface);
+ 
+ 	if (IS_ERR(phydev))
+ 		return phydev;
+@@ -206,7 +316,7 @@ static int phy_compare_id(struct device *dev, void *data)
+ /**
+  * phy_attach - attach a network device to a particular PHY device
+  * @dev: network device to attach
+- * @phy_id: PHY device to attach
++ * @bus_id: PHY device to attach
+  * @flags: PHY device's dev_flags
+  * @interface: PHY device's interface
+  *
+@@ -218,7 +328,7 @@ static int phy_compare_id(struct device *dev, void *data)
+  *     change.  The phy_device is returned to the attaching driver.
+  */
+ struct phy_device *phy_attach(struct net_device *dev,
+-		const char *phy_id, u32 flags, phy_interface_t interface)
++		const char *bus_id, u32 flags, phy_interface_t interface)
+ {
+ 	struct bus_type *bus = &mdio_bus_type;
+ 	struct phy_device *phydev;
+@@ -226,12 +336,12 @@ struct phy_device *phy_attach(struct net_device *dev,
+ 
+ 	/* Search the list of PHY devices on the mdio bus for the
+ 	 * PHY with the requested name */
+-	d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id);
++	d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id);
+ 
+ 	if (d) {
+ 		phydev = to_phy_device(d);
+ 	} else {
+-		printk(KERN_ERR "%s not found\n", phy_id);
++		printk(KERN_ERR "%s not found\n", bus_id);
+ 		return ERR_PTR(-ENODEV);
+ 	}
+ 
+@@ -251,7 +361,7 @@ struct phy_device *phy_attach(struct net_device *dev,
+ 
+ 	if (phydev->attached_dev) {
+ 		printk(KERN_ERR "%s: %s already attached\n",
+-				dev->name, phy_id);
++				dev->name, bus_id);
+ 		return ERR_PTR(-EBUSY);
+ 	}
+ 
+@@ -267,6 +377,11 @@ struct phy_device *phy_attach(struct net_device *dev,
+ 	if (phydev->drv->config_init) {
+ 		int err;
+ 
++		err = phy_scan_fixups(phydev);
++
++		if (err < 0)
++			return ERR_PTR(err);
++
+ 		err = phydev->drv->config_init(phydev);
+ 
+ 		if (err < 0)
+@@ -375,6 +490,7 @@ EXPORT_SYMBOL(genphy_config_advert);
+  */
+ int genphy_setup_forced(struct phy_device *phydev)
+ {
++	int err;
+ 	int ctl = 0;
+ 
+ 	phydev->pause = phydev->asym_pause = 0;
+@@ -387,17 +503,26 @@ int genphy_setup_forced(struct phy_device *phydev)
+ 	if (DUPLEX_FULL == phydev->duplex)
+ 		ctl |= BMCR_FULLDPLX;
+ 	
+-	ctl = phy_write(phydev, MII_BMCR, ctl);
++	err = phy_write(phydev, MII_BMCR, ctl);
+ 
+-	if (ctl < 0)
+-		return ctl;
++	if (err < 0)
++		return err;
++
++	/*
++	 * Run the fixups on this PHY, just in case the
++	 * board code needs to change something after a reset
++	 */
++	err = phy_scan_fixups(phydev);
++
++	if (err < 0)
++		return err;
+ 
+ 	/* We just reset the device, so we'd better configure any
+ 	 * settings the PHY requires to operate */
+ 	if (phydev->drv->config_init)
+-		ctl = phydev->drv->config_init(phydev);
++		err = phydev->drv->config_init(phydev);
+ 
+-	return ctl;
++	return err;
+ }
+ 
+ 
+diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
+index 4dc5b4b..d3207c0 100644
+--- a/drivers/net/ppp_generic.c
++++ b/drivers/net/ppp_generic.c
+@@ -123,7 +123,6 @@ struct ppp {
+ 	u32		minseq;		/* MP: min of most recent seqnos */
+ 	struct sk_buff_head mrq;	/* MP: receive reconstruction queue */
+ #endif /* CONFIG_PPP_MULTILINK */
+-	struct net_device_stats stats;	/* statistics */
+ #ifdef CONFIG_PPP_FILTER
+ 	struct sock_filter *pass_filter;	/* filter for packets to pass */
+ 	struct sock_filter *active_filter;/* filter for pkts to reset idle */
+@@ -914,18 +913,10 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+  outf:
+ 	kfree_skb(skb);
+-	++ppp->stats.tx_dropped;
++	++ppp->dev->stats.tx_dropped;
+ 	return 0;
+ }
+ 
+-static struct net_device_stats *
+-ppp_net_stats(struct net_device *dev)
+-{
+-	struct ppp *ppp = (struct ppp *) dev->priv;
+-
+-	return &ppp->stats;
+-}
+-
+ static int
+ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+@@ -1095,8 +1086,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
+ #endif /* CONFIG_PPP_FILTER */
+ 	}
+ 
+-	++ppp->stats.tx_packets;
+-	ppp->stats.tx_bytes += skb->len - 2;
++	++ppp->dev->stats.tx_packets;
++	ppp->dev->stats.tx_bytes += skb->len - 2;
+ 
+ 	switch (proto) {
+ 	case PPP_IP:
+@@ -1171,7 +1162,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
+  drop:
+ 	if (skb)
+ 		kfree_skb(skb);
+-	++ppp->stats.tx_errors;
++	++ppp->dev->stats.tx_errors;
+ }
+ 
+ /*
+@@ -1409,7 +1400,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
+ 	spin_unlock_bh(&pch->downl);
+ 	if (ppp->debug & 1)
+ 		printk(KERN_ERR "PPP: no memory (fragment)\n");
+-	++ppp->stats.tx_errors;
++	++ppp->dev->stats.tx_errors;
+ 	++ppp->nxseq;
+ 	return 1;	/* abandon the frame */
+ }
+@@ -1538,7 +1529,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+ 
+ 	if (skb->len > 0)
+ 		/* note: a 0-length skb is used as an error indication */
+-		++ppp->stats.rx_length_errors;
++		++ppp->dev->stats.rx_length_errors;
+ 
+ 	kfree_skb(skb);
+ 	ppp_receive_error(ppp);
+@@ -1547,7 +1538,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+ static void
+ ppp_receive_error(struct ppp *ppp)
+ {
+-	++ppp->stats.rx_errors;
++	++ppp->dev->stats.rx_errors;
+ 	if (ppp->vj)
+ 		slhc_toss(ppp->vj);
+ }
+@@ -1627,8 +1618,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
+ 		break;
+ 	}
+ 
+-	++ppp->stats.rx_packets;
+-	ppp->stats.rx_bytes += skb->len - 2;
++	++ppp->dev->stats.rx_packets;
++	ppp->dev->stats.rx_bytes += skb->len - 2;
+ 
+ 	npi = proto_to_npindex(proto);
+ 	if (npi < 0) {
+@@ -1806,7 +1797,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+ 	 */
+ 	if (seq_before(seq, ppp->nextseq)) {
+ 		kfree_skb(skb);
+-		++ppp->stats.rx_dropped;
++		++ppp->dev->stats.rx_dropped;
+ 		ppp_receive_error(ppp);
+ 		return;
+ 	}
+@@ -1928,7 +1919,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
+ 		/* Got a complete packet yet? */
+ 		if (lost == 0 && (p->BEbits & E) && (head->BEbits & B)) {
+ 			if (len > ppp->mrru + 2) {
+-				++ppp->stats.rx_length_errors;
++				++ppp->dev->stats.rx_length_errors;
+ 				printk(KERN_DEBUG "PPP: reconstructed packet"
+ 				       " is too long (%d)\n", len);
+ 			} else if (p == head) {
+@@ -1937,7 +1928,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
+ 				skb = skb_get(p);
+ 				break;
+ 			} else if ((skb = dev_alloc_skb(len)) == NULL) {
+-				++ppp->stats.rx_missed_errors;
++				++ppp->dev->stats.rx_missed_errors;
+ 				printk(KERN_DEBUG "PPP: no memory for "
+ 				       "reconstructed packet");
+ 			} else {
+@@ -1966,7 +1957,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
+ 			if (ppp->debug & 1)
+ 				printk(KERN_DEBUG "  missed pkts %u..%u\n",
+ 				       ppp->nextseq, head->sequence-1);
+-			++ppp->stats.rx_dropped;
++			++ppp->dev->stats.rx_dropped;
+ 			ppp_receive_error(ppp);
+ 		}
+ 
+@@ -2377,12 +2368,12 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
+ 	struct slcompress *vj = ppp->vj;
+ 
+ 	memset(st, 0, sizeof(*st));
+-	st->p.ppp_ipackets = ppp->stats.rx_packets;
+-	st->p.ppp_ierrors = ppp->stats.rx_errors;
+-	st->p.ppp_ibytes = ppp->stats.rx_bytes;
+-	st->p.ppp_opackets = ppp->stats.tx_packets;
+-	st->p.ppp_oerrors = ppp->stats.tx_errors;
+-	st->p.ppp_obytes = ppp->stats.tx_bytes;
++	st->p.ppp_ipackets = ppp->dev->stats.rx_packets;
++	st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
++	st->p.ppp_ibytes = ppp->dev->stats.rx_bytes;
++	st->p.ppp_opackets = ppp->dev->stats.tx_packets;
++	st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
++	st->p.ppp_obytes = ppp->dev->stats.tx_bytes;
+ 	if (!vj)
+ 		return;
+ 	st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
+@@ -2436,7 +2427,6 @@ ppp_create_interface(int unit, int *retp)
+ 	dev->priv = ppp;
+ 
+ 	dev->hard_start_xmit = ppp_start_xmit;
+-	dev->get_stats = ppp_net_stats;
+ 	dev->do_ioctl = ppp_net_ioctl;
+ 
+ 	ret = -EEXIST;
+diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
+index ac0ac98..4fad4dd 100644
+--- a/drivers/net/pppoe.c
++++ b/drivers/net/pppoe.c
+@@ -301,7 +301,7 @@ static int pppoe_device_event(struct notifier_block *this,
+ {
+ 	struct net_device *dev = (struct net_device *) ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	/* Only look at sockets that are using this specific device. */
+@@ -392,7 +392,7 @@ static int pppoe_rcv(struct sk_buff *skb,
+ 	if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
+ 		goto out;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto drop;
+ 
+ 	if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
+@@ -424,7 +424,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
+ 	struct pppoe_hdr *ph;
+ 	struct pppox_sock *po;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto abort;
+ 
+ 	if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
+diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
+index 7eb6e7e..e365efb 100644
+--- a/drivers/net/ps3_gelic_net.c
++++ b/drivers/net/ps3_gelic_net.c
+@@ -1266,6 +1266,85 @@ int gelic_net_set_rx_csum(struct net_device *netdev, u32 data)
+ 	return 0;
+ }
+ 
++static void gelic_net_get_wol(struct net_device *netdev,
++			      struct ethtool_wolinfo *wol)
++{
++	if (0 <= ps3_compare_firmware_version(2, 2, 0))
++		wol->supported = WAKE_MAGIC;
++	else
++		wol->supported = 0;
++
++	wol->wolopts = ps3_sys_manager_get_wol() ? wol->supported : 0;
++	memset(&wol->sopass, 0, sizeof(wol->sopass));
++}
++static int gelic_net_set_wol(struct net_device *netdev,
++			     struct ethtool_wolinfo *wol)
++{
++	int status;
++	struct gelic_card *card;
++	u64 v1, v2;
++
++	if (ps3_compare_firmware_version(2, 2, 0) < 0 ||
++	    !capable(CAP_NET_ADMIN))
++		return -EPERM;
++
++	if (wol->wolopts & ~WAKE_MAGIC)
++		return -EINVAL;
++
++	card = netdev_card(netdev);
++	if (wol->wolopts & WAKE_MAGIC) {
++		status = lv1_net_control(bus_id(card), dev_id(card),
++					 GELIC_LV1_SET_WOL,
++					 GELIC_LV1_WOL_MAGIC_PACKET,
++					 0, GELIC_LV1_WOL_MP_ENABLE,
++					 &v1, &v2);
++		if (status) {
++			pr_info("%s: enabling WOL failed %d\n", __func__,
++				status);
++			status = -EIO;
++			goto done;
++		}
++		status = lv1_net_control(bus_id(card), dev_id(card),
++					 GELIC_LV1_SET_WOL,
++					 GELIC_LV1_WOL_ADD_MATCH_ADDR,
++					 0, GELIC_LV1_WOL_MATCH_ALL,
++					 &v1, &v2);
++		if (!status)
++			ps3_sys_manager_set_wol(1);
++		else {
++			pr_info("%s: enabling WOL filter failed %d\n",
++				__func__, status);
++			status = -EIO;
++		}
++	} else {
++		status = lv1_net_control(bus_id(card), dev_id(card),
++					 GELIC_LV1_SET_WOL,
++					 GELIC_LV1_WOL_MAGIC_PACKET,
++					 0, GELIC_LV1_WOL_MP_DISABLE,
++					 &v1, &v2);
++		if (status) {
++			pr_info("%s: disabling WOL failed %d\n", __func__,
++				status);
++			status = -EIO;
++			goto done;
++		}
++		status = lv1_net_control(bus_id(card), dev_id(card),
++					 GELIC_LV1_SET_WOL,
++					 GELIC_LV1_WOL_DELETE_MATCH_ADDR,
++					 0, GELIC_LV1_WOL_MATCH_ALL,
++					 &v1, &v2);
++		if (!status)
++			ps3_sys_manager_set_wol(0);
++		else {
++			pr_info("%s: removing WOL filter failed %d\n",
++				__func__, status);
++			status = -EIO;
++		}
++	}
++done:
++	return status;
++}
++
+ static struct ethtool_ops gelic_ether_ethtool_ops = {
+ 	.get_drvinfo	= gelic_net_get_drvinfo,
+ 	.get_settings	= gelic_ether_get_settings,
+@@ -1274,6 +1353,8 @@ static struct ethtool_ops gelic_ether_ethtool_ops = {
+ 	.set_tx_csum	= ethtool_op_set_tx_csum,
+ 	.get_rx_csum	= gelic_net_get_rx_csum,
+ 	.set_rx_csum	= gelic_net_set_rx_csum,
++	.get_wol	= gelic_net_get_wol,
++	.set_wol	= gelic_net_set_wol,
+ };
+ 
+ /**
+diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h
+index 1d39d06..520f143 100644
+--- a/drivers/net/ps3_gelic_net.h
++++ b/drivers/net/ps3_gelic_net.h
+@@ -182,12 +182,32 @@ enum gelic_lv1_net_control_code {
+ 	GELIC_LV1_GET_ETH_PORT_STATUS	= 2,
+ 	GELIC_LV1_SET_NEGOTIATION_MODE	= 3,
+ 	GELIC_LV1_GET_VLAN_ID		= 4,
++	GELIC_LV1_SET_WOL		= 5,
+ 	GELIC_LV1_GET_CHANNEL           = 6,
+ 	GELIC_LV1_POST_WLAN_CMD		= 9,
+ 	GELIC_LV1_GET_WLAN_CMD_RESULT	= 10,
+ 	GELIC_LV1_GET_WLAN_EVENT	= 11
+ };
+ 
++/* for GELIC_LV1_SET_WOL */
++enum gelic_lv1_wol_command {
++	GELIC_LV1_WOL_MAGIC_PACKET	= 1,
++	GELIC_LV1_WOL_ADD_MATCH_ADDR	= 6,
++	GELIC_LV1_WOL_DELETE_MATCH_ADDR	= 7,
++};
++
++/* for GELIC_LV1_WOL_MAGIC_PACKET */
++enum gelic_lv1_wol_mp_arg {
++	GELIC_LV1_WOL_MP_DISABLE	= 0,
++	GELIC_LV1_WOL_MP_ENABLE		= 1,
++};
++
++/* for GELIC_LV1_WOL_{ADD,DELETE}_MATCH_ADDR */
++enum gelic_lv1_wol_match_arg {
++	GELIC_LV1_WOL_MATCH_INDIVIDUAL	= 0,
++	GELIC_LV1_WOL_MATCH_ALL		= 1,
++};
++
+ /* status returened from GET_ETH_PORT_STATUS */
+ enum gelic_lv1_ether_port_status {
+ 	GELIC_LV1_ETHER_LINK_UP		= 0x0000000000000001L,
+diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c
+index c16de51..0d32123 100644
+--- a/drivers/net/ps3_gelic_wireless.c
++++ b/drivers/net/ps3_gelic_wireless.c
+@@ -87,7 +87,7 @@ static inline int wpa2_capable(void)
+ 
+ static inline int precise_ie(void)
+ {
+-	return 0; /* FIXME */
++	return (0 <= ps3_compare_firmware_version(2, 2, 0));
+ }
+ /*
+  * post_eurus_cmd helpers
+diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
+index a6aeb9d..b7f7b22 100644
+--- a/drivers/net/qla3xxx.c
++++ b/drivers/net/qla3xxx.c
+@@ -2472,8 +2472,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
+ 
+ 	if (seg_cnt == 1) {
+ 		/* Terminate the last segment. */
+-		oal_entry->len =
+-		    cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
++		oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
+ 	} else {
+ 		oal = tx_cb->oal;
+ 		for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) {
+@@ -2530,8 +2529,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
+ 					  frag->size);
+ 		}
+ 		/* Terminate the last segment. */
+-		oal_entry->len =
+-		    cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
++		oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
+ 	}
+ 
+ 	return NETDEV_TX_OK;
+diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
+index c082cf0..157fd93 100644
+--- a/drivers/net/s2io.c
++++ b/drivers/net/s2io.c
+@@ -50,6 +50,8 @@
+  *                 Possible values '1' for enable , '0' for disable.
+  *                 Default is '2' - which means disable in promisc mode
+  *                 and enable in non-promiscuous mode.
++ * multiq: This parameter used to enable/disable MULTIQUEUE support.
++ *      Possible values '1' for enable and '0' for disable. Default is '0'
+  ************************************************************************/
+ 
+ #include <linux/module.h>
+@@ -84,7 +86,7 @@
+ #include "s2io.h"
+ #include "s2io-regs.h"
+ 
+-#define DRV_VERSION "2.0.26.20"
++#define DRV_VERSION "2.0.26.22"
+ 
+ /* S2io Driver name & version. */
+ static char s2io_driver_name[] = "Neterion";
+@@ -115,20 +117,6 @@ static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
+ 
+ #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
+ 				      ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
+-#define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status))
+-#define PANIC	1
+-#define LOW	2
+-static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring)
+-{
+-	struct mac_info *mac_control;
+-
+-	mac_control = &sp->mac_control;
+-	if (rxb_size <= rxd_count[sp->rxd_mode])
+-		return PANIC;
+-	else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
+-		return  LOW;
+-	return 0;
+-}
+ 
+ static inline int is_s2io_card_up(const struct s2io_nic * sp)
+ {
+@@ -386,6 +374,26 @@ static void s2io_vlan_rx_register(struct net_device *dev,
+ /* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
+ static int vlan_strip_flag;
+ 
++/* Unregister the vlan */
++static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
++{
++	int i;
++	struct s2io_nic *nic = dev->priv;
++	unsigned long flags[MAX_TX_FIFOS];
++	struct mac_info *mac_control = &nic->mac_control;
++	struct config_param *config = &nic->config;
++
++	for (i = 0; i < config->tx_fifo_num; i++)
++		spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags[i]);
++
++	if (nic->vlgrp)
++		vlan_group_set_device(nic->vlgrp, vid, NULL);
++
++	for (i = config->tx_fifo_num - 1; i >= 0; i--)
++		spin_unlock_irqrestore(&mac_control->fifos[i].tx_lock,
++			flags[i]);
++}
++
+ /*
+  * Constants to be programmed into the Xena's registers, to configure
+  * the XAUI.
+@@ -456,10 +464,9 @@ MODULE_VERSION(DRV_VERSION);
+ 
+ 
+ /* Module Loadable parameters. */
+-S2IO_PARM_INT(tx_fifo_num, 1);
++S2IO_PARM_INT(tx_fifo_num, FIFO_DEFAULT_NUM);
+ S2IO_PARM_INT(rx_ring_num, 1);
+-
+-
++S2IO_PARM_INT(multiq, 0);
+ S2IO_PARM_INT(rx_ring_mode, 1);
+ S2IO_PARM_INT(use_continuous_tx_intrs, 1);
+ S2IO_PARM_INT(rmac_pause_time, 0x100);
+@@ -469,6 +476,8 @@ S2IO_PARM_INT(shared_splits, 0);
+ S2IO_PARM_INT(tmac_util_period, 5);
+ S2IO_PARM_INT(rmac_util_period, 5);
+ S2IO_PARM_INT(l3l4hdr_size, 128);
++/* 0 is no steering, 1 is Priority steering, 2 is Default steering */
++S2IO_PARM_INT(tx_steering_type, TX_DEFAULT_STEERING);
+ /* Frequency of Rx desc syncs expressed as power of 2 */
+ S2IO_PARM_INT(rxsync_frequency, 3);
+ /* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
+@@ -533,6 +542,101 @@ static struct pci_driver s2io_driver = {
+ /* A simplifier macro used both by init and free shared_mem Fns(). */
+ #define TXD_MEM_PAGE_CNT(len, per_each) ((len+per_each - 1) / per_each)
+ 
++/* netqueue manipulation helper functions */
++static inline void s2io_stop_all_tx_queue(struct s2io_nic *sp)
++{
++	int i;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	if (sp->config.multiq) {
++		for (i = 0; i < sp->config.tx_fifo_num; i++)
++			netif_stop_subqueue(sp->dev, i);
++	} else
++#endif
++	{
++		for (i = 0; i < sp->config.tx_fifo_num; i++)
++			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_STOP;
++		netif_stop_queue(sp->dev);
++	}
++}
++
++static inline void s2io_stop_tx_queue(struct s2io_nic *sp, int fifo_no)
++{
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	if (sp->config.multiq)
++		netif_stop_subqueue(sp->dev, fifo_no);
++	else
++#endif
++	{
++		sp->mac_control.fifos[fifo_no].queue_state =
++			FIFO_QUEUE_STOP;
++		netif_stop_queue(sp->dev);
++	}
++}
++
++static inline void s2io_start_all_tx_queue(struct s2io_nic *sp)
++{
++	int i;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	if (sp->config.multiq) {
++		for (i = 0; i < sp->config.tx_fifo_num; i++)
++			netif_start_subqueue(sp->dev, i);
++	} else
++#endif
++	{
++		for (i = 0; i < sp->config.tx_fifo_num; i++)
++			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
++		netif_start_queue(sp->dev);
++	}
++}
++
++static inline void s2io_start_tx_queue(struct s2io_nic *sp, int fifo_no)
++{
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	if (sp->config.multiq)
++		netif_start_subqueue(sp->dev, fifo_no);
++	else
++#endif
++	{
++		sp->mac_control.fifos[fifo_no].queue_state =
++			FIFO_QUEUE_START;
++		netif_start_queue(sp->dev);
++	}
++}
++
++static inline void s2io_wake_all_tx_queue(struct s2io_nic *sp)
++{
++	int i;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	if (sp->config.multiq) {
++		for (i = 0; i < sp->config.tx_fifo_num; i++)
++			netif_wake_subqueue(sp->dev, i);
++	} else
++#endif
++	{
++		for (i = 0; i < sp->config.tx_fifo_num; i++)
++			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
++		netif_wake_queue(sp->dev);
++	}
++}
++
++static inline void s2io_wake_tx_queue(
++	struct fifo_info *fifo, int cnt, u8 multiq)
++{
++
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	if (multiq) {
++		if (cnt && __netif_subqueue_stopped(fifo->dev, fifo->fifo_no))
++			netif_wake_subqueue(fifo->dev, fifo->fifo_no);
++	} else
++#endif
++	if (cnt && (fifo->queue_state == FIFO_QUEUE_STOP)) {
++		if (netif_queue_stopped(fifo->dev)) {
++			fifo->queue_state = FIFO_QUEUE_START;
++			netif_wake_queue(fifo->dev);
++		}
++	}
++}
++
+ /**
+  * init_shared_mem - Allocation and Initialization of Memory
+  * @nic: Device private variable.
+@@ -614,6 +718,7 @@ static int init_shared_mem(struct s2io_nic *nic)
+ 		mac_control->fifos[i].fifo_no = i;
+ 		mac_control->fifos[i].nic = nic;
+ 		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2;
++		mac_control->fifos[i].dev = dev;
+ 
+ 		for (j = 0; j < page_num; j++) {
+ 			int k = 0;
+@@ -2339,7 +2444,7 @@ static void free_tx_buffers(struct s2io_nic *nic)
+ 	for (i = 0; i < config->tx_fifo_num; i++) {
+ 		unsigned long flags;
+ 		spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags);
+-		for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
++		for (j = 0; j < config->tx_cfg[i].fifo_len; j++) {
+ 			txdp = (struct TxD *) \
+ 			mac_control->fifos[i].list_info[j].list_virt_addr;
+ 			skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
+@@ -2425,7 +2530,6 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+ 	struct config_param *config;
+ 	u64 tmp;
+ 	struct buffAdd *ba;
+-	unsigned long flags;
+ 	struct RxD_t *first_rxdp = NULL;
+ 	u64 Buffer0_ptr = 0, Buffer1_ptr = 0;
+ 	struct RxD1 *rxdp1;
+@@ -2473,15 +2577,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+ 			DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
+ 				  dev->name, rxdp);
+ 		}
+-		if(!napi) {
+-			spin_lock_irqsave(&nic->put_lock, flags);
+-			mac_control->rings[ring_no].put_pos =
+-			(block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
+-			spin_unlock_irqrestore(&nic->put_lock, flags);
+-		} else {
+-			mac_control->rings[ring_no].put_pos =
+-			(block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
+-		}
++
+ 		if ((rxdp->Control_1 & RXD_OWN_XENA) &&
+ 			((nic->rxd_mode == RXD_MODE_3B) &&
+ 				(rxdp->Control_2 & s2BIT(0)))) {
+@@ -2859,7 +2955,7 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ {
+ 	struct s2io_nic *nic = ring_data->nic;
+ 	struct net_device *dev = (struct net_device *) nic->dev;
+-	int get_block, put_block, put_offset;
++	int get_block, put_block;
+ 	struct rx_curr_get_info get_info, put_info;
+ 	struct RxD_t *rxdp;
+ 	struct sk_buff *skb;
+@@ -2868,19 +2964,11 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ 	struct RxD1* rxdp1;
+ 	struct RxD3* rxdp3;
+ 
+-	spin_lock(&nic->rx_lock);
+-
+ 	get_info = ring_data->rx_curr_get_info;
+ 	get_block = get_info.block_index;
+ 	memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info));
+ 	put_block = put_info.block_index;
+ 	rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr;
+-	if (!napi) {
+-		spin_lock(&nic->put_lock);
+-		put_offset = ring_data->put_pos;
+-		spin_unlock(&nic->put_lock);
+-	} else
+-		put_offset = ring_data->put_pos;
+ 
+ 	while (RXD_IS_UP2DT(rxdp)) {
+ 		/*
+@@ -2897,7 +2985,6 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ 			DBG_PRINT(ERR_DBG, "%s: The skb is ",
+ 				  dev->name);
+ 			DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
+-			spin_unlock(&nic->rx_lock);
+ 			return;
+ 		}
+ 		if (nic->rxd_mode == RXD_MODE_1) {
+@@ -2948,13 +3035,11 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ 			struct lro *lro = &nic->lro0_n[i];
+ 			if (lro->in_use) {
+ 				update_L3L4_header(nic, lro);
+-				queue_rx_frame(lro->parent);
++				queue_rx_frame(lro->parent, lro->vlan_tag);
+ 				clear_lro_session(lro);
+ 			}
+ 		}
+ 	}
+-
+-	spin_unlock(&nic->rx_lock);
+ }
+ 
+ /**
+@@ -2972,10 +3057,10 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ static void tx_intr_handler(struct fifo_info *fifo_data)
+ {
+ 	struct s2io_nic *nic = fifo_data->nic;
+-	struct net_device *dev = (struct net_device *) nic->dev;
+ 	struct tx_curr_get_info get_info, put_info;
+-	struct sk_buff *skb;
++	struct sk_buff *skb = NULL;
+ 	struct TxD *txdlp;
++	int pkt_cnt = 0;
+ 	unsigned long flags = 0;
+ 	u8 err_mask;
+ 
+@@ -3036,6 +3121,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
+ 			DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
+ 			return;
+ 		}
++		pkt_cnt++;
+ 
+ 		/* Updating the statistics block */
+ 		nic->stats.tx_bytes += skb->len;
+@@ -3051,8 +3137,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
+ 		    get_info.offset;
+ 	}
+ 
+-	if (netif_queue_stopped(dev))
+-		netif_wake_queue(dev);
++	s2io_wake_tx_queue(fifo_data, pkt_cnt, nic->config.multiq);
+ 
+ 	spin_unlock_irqrestore(&fifo_data->tx_lock, flags);
+ }
+@@ -3933,8 +4018,7 @@ static int s2io_open(struct net_device *dev)
+ 		err = -ENODEV;
+ 		goto hw_init_failed;
+ 	}
+-
+-	netif_start_queue(dev);
++	s2io_start_all_tx_queue(sp);
+ 	return 0;
+ 
+ hw_init_failed:
+@@ -3979,8 +4063,7 @@ static int s2io_close(struct net_device *dev)
+ 	if (!is_s2io_card_up(sp))
+ 		return 0;
+ 
+-	netif_stop_queue(dev);
+-
++	s2io_stop_all_tx_queue(sp);
+ 	/* delete all populated mac entries */
+ 	for (offset = 1; offset < config->max_mc_addr; offset++) {
+ 		tmp64 = do_s2io_read_unicast_mc(sp, offset);
+@@ -3988,7 +4071,6 @@ static int s2io_close(struct net_device *dev)
+ 			do_s2io_delete_unicast_mc(sp, tmp64);
+ 	}
+ 
+-	/* Reset card, kill tasklet and free Tx and Rx buffers. */
+ 	s2io_card_down(sp);
+ 
+ 	return 0;
+@@ -4016,11 +4098,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	struct TxFIFO_element __iomem *tx_fifo;
+ 	unsigned long flags = 0;
+ 	u16 vlan_tag = 0;
+-	int vlan_priority = 0;
+ 	struct fifo_info *fifo = NULL;
+ 	struct mac_info *mac_control;
+ 	struct config_param *config;
++	int do_spin_lock = 1;
+ 	int offload_type;
++	int enable_per_list_interrupt = 0;
+ 	struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
+ 
+ 	mac_control = &sp->mac_control;
+@@ -4042,15 +4125,67 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	}
+ 
+ 	queue = 0;
+-	/* Get Fifo number to Transmit based on vlan priority */
+-	if (sp->vlgrp && vlan_tx_tag_present(skb)) {
++	if (sp->vlgrp && vlan_tx_tag_present(skb))
+ 		vlan_tag = vlan_tx_tag_get(skb);
+-		vlan_priority = vlan_tag >> 13;
+-		queue = config->fifo_mapping[vlan_priority];
++	if (sp->config.tx_steering_type == TX_DEFAULT_STEERING) {
++		if (skb->protocol == htons(ETH_P_IP)) {
++			struct iphdr *ip;
++			struct tcphdr *th;
++			ip = ip_hdr(skb);
++
++			if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
++				th = (struct tcphdr *)(((unsigned char *)ip) +
++						ip->ihl*4);
++
++				if (ip->protocol == IPPROTO_TCP) {
++					queue_len = sp->total_tcp_fifos;
++					queue = (ntohs(th->source) +
++							ntohs(th->dest)) &
++					    sp->fifo_selector[queue_len - 1];
++					if (queue >= queue_len)
++						queue = queue_len - 1;
++				} else if (ip->protocol == IPPROTO_UDP) {
++					queue_len = sp->total_udp_fifos;
++					queue = (ntohs(th->source) +
++							ntohs(th->dest)) &
++					    sp->fifo_selector[queue_len - 1];
++					if (queue >= queue_len)
++						queue = queue_len - 1;
++					queue += sp->udp_fifo_idx;
++					if (skb->len > 1024)
++						enable_per_list_interrupt = 1;
++					do_spin_lock = 0;
++				}
++			}
++		}
++	} else if (sp->config.tx_steering_type == TX_PRIORITY_STEERING)
++		/* get fifo number based on skb->priority value */
++		queue = config->fifo_mapping
++					[skb->priority & (MAX_TX_FIFOS - 1)];
++	fifo = &mac_control->fifos[queue];
++
++	if (do_spin_lock)
++		spin_lock_irqsave(&fifo->tx_lock, flags);
++	else {
++		if (unlikely(!spin_trylock_irqsave(&fifo->tx_lock, flags)))
++			return NETDEV_TX_LOCKED;
++	}
++
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	if (sp->config.multiq) {
++		if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
++			spin_unlock_irqrestore(&fifo->tx_lock, flags);
++			return NETDEV_TX_BUSY;
++		}
++	} else
++#endif
++	if (unlikely(fifo->queue_state == FIFO_QUEUE_STOP)) {
++		if (netif_queue_stopped(dev)) {
++			spin_unlock_irqrestore(&fifo->tx_lock, flags);
++			return NETDEV_TX_BUSY;
++		}
+ 	}
+ 
+-	fifo = &mac_control->fifos[queue];
+-	spin_lock_irqsave(&fifo->tx_lock, flags);
+ 	put_off = (u16) fifo->tx_curr_put_info.offset;
+ 	get_off = (u16) fifo->tx_curr_get_info.offset;
+ 	txdp = (struct TxD *) fifo->list_info[put_off].list_virt_addr;
+@@ -4060,7 +4195,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	if (txdp->Host_Control ||
+ 		   ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
+ 		DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
+-		netif_stop_queue(dev);
++		s2io_stop_tx_queue(sp, fifo->fifo_no);
+ 		dev_kfree_skb(skb);
+ 		spin_unlock_irqrestore(&fifo->tx_lock, flags);
+ 		return 0;
+@@ -4079,8 +4214,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	txdp->Control_1 |= TXD_GATHER_CODE_FIRST;
+ 	txdp->Control_1 |= TXD_LIST_OWN_XENA;
+ 	txdp->Control_2 |= TXD_INT_NUMBER(fifo->fifo_no);
+-
+-	if (sp->vlgrp && vlan_tx_tag_present(skb)) {
++	if (enable_per_list_interrupt)
++		if (put_off & (queue_len >> 5))
++			txdp->Control_2 |= TXD_INT_TYPE_PER_LIST;
++	if (vlan_tag) {
+ 		txdp->Control_2 |= TXD_VLAN_ENABLE;
+ 		txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
+ 	}
+@@ -4095,11 +4232,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
+ 		txdp->Control_1 |= TXD_BUFFER0_SIZE(8);
+ #ifdef __BIG_ENDIAN
++		/* both variants do cpu_to_be64(be32_to_cpu(...)) */
+ 		fifo->ufo_in_band_v[put_off] =
+-				(u64)skb_shinfo(skb)->ip6_frag_id;
++				(__force u64)skb_shinfo(skb)->ip6_frag_id;
+ #else
+ 		fifo->ufo_in_band_v[put_off] =
+-				(u64)skb_shinfo(skb)->ip6_frag_id << 32;
++				(__force u64)skb_shinfo(skb)->ip6_frag_id << 32;
+ #endif
+ 		txdp->Host_Control = (unsigned long)fifo->ufo_in_band_v;
+ 		txdp->Buffer_Pointer = pci_map_single(sp->pdev,
+@@ -4166,7 +4304,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		DBG_PRINT(TX_DBG,
+ 			  "No free TxDs for xmit, Put: 0x%x Get:0x%x\n",
+ 			  put_off, get_off);
+-		netif_stop_queue(dev);
++		s2io_stop_tx_queue(sp, fifo->fifo_no);
+ 	}
+ 	mac_control->stats_info->sw_stat.mem_allocated += skb->truesize;
+ 	dev->trans_start = jiffies;
+@@ -4178,7 +4316,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	return 0;
+ pci_map_failed:
+ 	stats->pci_map_fail_cnt++;
+-	netif_stop_queue(dev);
++	s2io_stop_tx_queue(sp, fifo->fifo_no);
+ 	stats->mem_freed += skb->truesize;
+ 	dev_kfree_skb(skb);
+ 	spin_unlock_irqrestore(&fifo->tx_lock, flags);
+@@ -4197,29 +4335,9 @@ s2io_alarm_handle(unsigned long data)
+ 
+ static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n)
+ {
+-	int rxb_size, level;
+-
+-	if (!sp->lro) {
+-		rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+-		level = rx_buffer_level(sp, rxb_size, rng_n);
+-
+-		if ((level == PANIC) && (!TASKLET_IN_USE)) {
+-			int ret;
+-			DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+-			DBG_PRINT(INTR_DBG, "PANIC levels\n");
+-			if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+-				DBG_PRINT(INFO_DBG, "Out of memory in %s",
+-					  __FUNCTION__);
+-				clear_bit(0, (&sp->tasklet_status));
+-				return -1;
+-			}
+-			clear_bit(0, (&sp->tasklet_status));
+-		} else if (level == LOW)
+-			tasklet_schedule(&sp->task);
+-
+-	} else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
+-			DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name);
+-			DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
++	if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
++		DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name);
++		DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
+ 	}
+ 	return 0;
+ }
+@@ -4590,7 +4708,7 @@ static void s2io_handle_errors(void * dev_id)
+ 	return;
+ 
+ reset:
+-	netif_stop_queue(dev);
++	s2io_stop_all_tx_queue(sp);
+ 	schedule_work(&sp->rst_timer_task);
+ 	sw_stat->soft_reset_cnt++;
+ 	return;
+@@ -6577,16 +6695,15 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
+ 
+ 	dev->mtu = new_mtu;
+ 	if (netif_running(dev)) {
++		s2io_stop_all_tx_queue(sp);
+ 		s2io_card_down(sp);
+-		netif_stop_queue(dev);
+ 		ret = s2io_card_up(sp);
+ 		if (ret) {
+ 			DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
+ 				  __FUNCTION__);
+ 			return ret;
+ 		}
+-		if (netif_queue_stopped(dev))
+-			netif_wake_queue(dev);
++		s2io_wake_all_tx_queue(sp);
+ 	} else { /* Device is down */
+ 		struct XENA_dev_config __iomem *bar0 = sp->bar0;
+ 		u64 val64 = new_mtu;
+@@ -6598,49 +6715,6 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
+ }
+ 
+ /**
+- *  s2io_tasklet - Bottom half of the ISR.
+- *  @dev_adr : address of the device structure in dma_addr_t format.
+- *  Description:
+- *  This is the tasklet or the bottom half of the ISR. This is
+- *  an extension of the ISR which is scheduled by the scheduler to be run
+- *  when the load on the CPU is low. All low priority tasks of the ISR can
+- *  be pushed into the tasklet. For now the tasklet is used only to
+- *  replenish the Rx buffers in the Rx buffer descriptors.
+- *  Return value:
+- *  void.
+- */
+-
+-static void s2io_tasklet(unsigned long dev_addr)
+-{
+-	struct net_device *dev = (struct net_device *) dev_addr;
+-	struct s2io_nic *sp = dev->priv;
+-	int i, ret;
+-	struct mac_info *mac_control;
+-	struct config_param *config;
+-
+-	mac_control = &sp->mac_control;
+-	config = &sp->config;
+-
+-	if (!TASKLET_IN_USE) {
+-		for (i = 0; i < config->rx_ring_num; i++) {
+-			ret = fill_rx_buffers(sp, i);
+-			if (ret == -ENOMEM) {
+-				DBG_PRINT(INFO_DBG, "%s: Out of ",
+-					  dev->name);
+-				DBG_PRINT(INFO_DBG, "memory in tasklet\n");
+-				break;
+-			} else if (ret == -EFILL) {
+-				DBG_PRINT(INFO_DBG,
+-					  "%s: Rx Ring %d is full\n",
+-					  dev->name, i);
+-				break;
+-			}
+-		}
+-		clear_bit(0, (&sp->tasklet_status));
+-	}
+-}
+-
+-/**
+  * s2io_set_link - Set the LInk status
+  * @data: long pointer to device private structue
+  * Description: Sets the link status for the adapter
+@@ -6694,7 +6768,7 @@ static void s2io_set_link(struct work_struct *work)
+ 			} else {
+ 				DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name);
+ 				DBG_PRINT(ERR_DBG, "device is not Quiescent\n");
+-				netif_stop_queue(dev);
++				s2io_stop_all_tx_queue(nic);
+ 			}
+ 		}
+ 		val64 = readq(&bar0->adapter_control);
+@@ -6921,11 +6995,11 @@ static int s2io_add_isr(struct s2io_nic * sp)
+ 				if(!(sp->msix_info[i].addr &&
+ 					sp->msix_info[i].data)) {
+ 					DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx "
+-						"Data:0x%lx\n",sp->desc[i],
++						"Data:0x%llx\n",sp->desc[i],
+ 						(unsigned long long)
+ 						sp->msix_info[i].addr,
+-						(unsigned long)
+-						ntohl(sp->msix_info[i].data));
++						(unsigned long long)
++						sp->msix_info[i].data);
+ 				} else {
+ 					msix_tx_cnt++;
+ 				}
+@@ -6939,11 +7013,11 @@ static int s2io_add_isr(struct s2io_nic * sp)
+ 				if(!(sp->msix_info[i].addr &&
+ 					sp->msix_info[i].data)) {
+ 					DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx "
+-						"Data:0x%lx\n",sp->desc[i],
++						"Data:0x%llx\n",sp->desc[i],
+ 						(unsigned long long)
+ 						sp->msix_info[i].addr,
+-						(unsigned long)
+-						ntohl(sp->msix_info[i].data));
++						(unsigned long long)
++						sp->msix_info[i].data);
+ 				} else {
+ 					msix_rx_cnt++;
+ 				}
+@@ -6989,7 +7063,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
+ {
+ 	int cnt = 0;
+ 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
+-	unsigned long flags;
+ 	register u64 val64 = 0;
+ 	struct config_param *config;
+ 	config = &sp->config;
+@@ -7014,9 +7087,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
+ 
+ 	s2io_rem_isr(sp);
+ 
+-	/* Kill tasklet. */
+-	tasklet_kill(&sp->task);
+-
+ 	/* Check if the device is Quiescent and then Reset the NIC */
+ 	while(do_io) {
+ 		/* As per the HW requirement we need to replenish the
+@@ -7051,9 +7121,7 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
+ 	free_tx_buffers(sp);
+ 
+ 	/* Free all Rx buffers */
+-	spin_lock_irqsave(&sp->rx_lock, flags);
+ 	free_rx_buffers(sp);
+-	spin_unlock_irqrestore(&sp->rx_lock, flags);
+ 
+ 	clear_bit(__S2IO_STATE_LINK_TASK, &(sp->state));
+ }
+@@ -7142,9 +7210,6 @@ static int s2io_card_up(struct s2io_nic * sp)
+ 
+ 	S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
+ 
+-	/* Enable tasklet for the device */
+-	tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
+-
+ 	/*  Enable select interrupts */
+ 	en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS);
+ 	if (sp->config.intr_type != INTA)
+@@ -7184,7 +7249,7 @@ static void s2io_restart_nic(struct work_struct *work)
+ 		DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
+ 			  dev->name);
+ 	}
+-	netif_wake_queue(dev);
++	s2io_wake_all_tx_queue(sp);
+ 	DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
+ 		  dev->name);
+ out_unlock:
+@@ -7374,7 +7439,8 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ 					{
+ 						lro_append_pkt(sp, lro,
+ 							skb, tcp_len);
+-						queue_rx_frame(lro->parent);
++						queue_rx_frame(lro->parent,
++							lro->vlan_tag);
+ 						clear_lro_session(lro);
+ 						sp->mac_control.stats_info->
+ 						    sw_stat.flush_max_pkts++;
+@@ -7385,7 +7451,8 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ 							lro->frags_len;
+ 						sp->mac_control.stats_info->
+ 						     sw_stat.sending_both++;
+-						queue_rx_frame(lro->parent);
++						queue_rx_frame(lro->parent,
++							lro->vlan_tag);
+ 						clear_lro_session(lro);
+ 						goto send_up;
+ 					case 0: /* sessions exceeded */
+@@ -7411,31 +7478,12 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ 			 */
+ 			skb->ip_summed = CHECKSUM_NONE;
+ 		}
+-	} else {
++	} else
+ 		skb->ip_summed = CHECKSUM_NONE;
+-	}
++
+ 	sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
+-	if (!sp->lro) {
+-		skb->protocol = eth_type_trans(skb, dev);
+-		if ((sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2) &&
+-			vlan_strip_flag)) {
+-			/* Queueing the vlan frame to the upper layer */
+-			if (napi)
+-				vlan_hwaccel_receive_skb(skb, sp->vlgrp,
+-					RXD_GET_VLAN_TAG(rxdp->Control_2));
+-			else
+-				vlan_hwaccel_rx(skb, sp->vlgrp,
+-					RXD_GET_VLAN_TAG(rxdp->Control_2));
+-		} else {
+-			if (napi)
+-				netif_receive_skb(skb);
+-			else
+-				netif_rx(skb);
+-		}
+-	} else {
+ send_up:
+-		queue_rx_frame(skb);
+-	}
++	queue_rx_frame(skb, RXD_GET_VLAN_TAG(rxdp->Control_2));
+ 	dev->last_rx = jiffies;
+ aggregate:
+ 	atomic_dec(&sp->rx_bufs_left[ring_no]);
+@@ -7463,6 +7511,7 @@ static void s2io_link(struct s2io_nic * sp, int link)
+ 		init_tti(sp, link);
+ 		if (link == LINK_DOWN) {
+ 			DBG_PRINT(ERR_DBG, "%s: Link down\n", dev->name);
++			s2io_stop_all_tx_queue(sp);
+ 			netif_carrier_off(dev);
+ 			if(sp->mac_control.stats_info->sw_stat.link_up_cnt)
+ 			sp->mac_control.stats_info->sw_stat.link_up_time =
+@@ -7475,6 +7524,7 @@ static void s2io_link(struct s2io_nic * sp, int link)
+ 				jiffies - sp->start_time;
+ 			sp->mac_control.stats_info->sw_stat.link_up_cnt++;
+ 			netif_carrier_on(dev);
++			s2io_wake_all_tx_queue(sp);
+ 		}
+ 	}
+ 	sp->last_link_state = link;
+@@ -7511,20 +7561,48 @@ static void s2io_init_pci(struct s2io_nic * sp)
+ 	pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
+ }
+ 
+-static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
++static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
++	u8 *dev_multiq)
+ {
+ 	if ((tx_fifo_num > MAX_TX_FIFOS) ||
+-		(tx_fifo_num < FIFO_DEFAULT_NUM)) {
++		(tx_fifo_num < 1)) {
+ 		DBG_PRINT(ERR_DBG, "s2io: Requested number of tx fifos "
+ 			"(%d) not supported\n", tx_fifo_num);
+-		tx_fifo_num =
+-			((tx_fifo_num > MAX_TX_FIFOS)? MAX_TX_FIFOS :
+-			((tx_fifo_num < FIFO_DEFAULT_NUM) ? FIFO_DEFAULT_NUM :
+-			tx_fifo_num));
++
++		if (tx_fifo_num < 1)
++			tx_fifo_num = 1;
++		else
++			tx_fifo_num = MAX_TX_FIFOS;
++
+ 		DBG_PRINT(ERR_DBG, "s2io: Default to %d ", tx_fifo_num);
+ 		DBG_PRINT(ERR_DBG, "tx fifos\n");
+ 	}
+ 
++#ifndef CONFIG_NETDEVICES_MULTIQUEUE
++	if (multiq) {
++		DBG_PRINT(ERR_DBG, "s2io: Multiqueue support not enabled\n");
++		multiq = 0;
++	}
++#endif
++	if (multiq)
++		*dev_multiq = multiq;
++
++	if (tx_steering_type && (1 == tx_fifo_num)) {
++		if (tx_steering_type != TX_DEFAULT_STEERING)
++			DBG_PRINT(ERR_DBG,
++				"s2io: Tx steering is not supported with "
++				"one fifo. Disabling Tx steering.\n");
++		tx_steering_type = NO_STEERING;
++	}
++
++	if ((tx_steering_type < NO_STEERING) ||
++		(tx_steering_type > TX_DEFAULT_STEERING)) {
++		DBG_PRINT(ERR_DBG, "s2io: Requested transmit steering not "
++			 "supported\n");
++		DBG_PRINT(ERR_DBG, "s2io: Disabling transmit steering\n");
++		tx_steering_type = NO_STEERING;
++	}
++
+ 	if ( rx_ring_num > 8) {
+ 		DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
+ 			 "supported\n");
+@@ -7616,9 +7694,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ 	struct config_param *config;
+ 	int mode;
+ 	u8 dev_intr_type = intr_type;
++	u8 dev_multiq = 0;
+ 	DECLARE_MAC_BUF(mac);
+ 
+-	if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
++	ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
++	if (ret)
+ 		return ret;
+ 
+ 	if ((ret = pci_enable_device(pdev))) {
+@@ -7649,7 +7729,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ 		pci_disable_device(pdev);
+ 		return -ENODEV;
+ 	}
+-
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	if (dev_multiq)
++		dev = alloc_etherdev_mq(sizeof(struct s2io_nic), tx_fifo_num);
++	else
++#endif
+ 	dev = alloc_etherdev(sizeof(struct s2io_nic));
+ 	if (dev == NULL) {
+ 		DBG_PRINT(ERR_DBG, "Device allocation failed\n");
+@@ -7698,17 +7782,45 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ 	config = &sp->config;
+ 
+ 	config->napi = napi;
++	config->tx_steering_type = tx_steering_type;
+ 
+ 	/* Tx side parameters. */
+-	config->tx_fifo_num = tx_fifo_num;
+-	for (i = 0; i < MAX_TX_FIFOS; i++) {
++	if (config->tx_steering_type == TX_PRIORITY_STEERING)
++		config->tx_fifo_num = MAX_TX_FIFOS;
++	else
++		config->tx_fifo_num = tx_fifo_num;
++
++	/* Initialize the fifos used for tx steering */
++	if (config->tx_fifo_num < 5) {
++			if (config->tx_fifo_num  == 1)
++				sp->total_tcp_fifos = 1;
++			else
++				sp->total_tcp_fifos = config->tx_fifo_num - 1;
++			sp->udp_fifo_idx = config->tx_fifo_num - 1;
++			sp->total_udp_fifos = 1;
++			sp->other_fifo_idx = sp->total_tcp_fifos - 1;
++	} else {
++		sp->total_tcp_fifos = (tx_fifo_num - FIFO_UDP_MAX_NUM -
++						FIFO_OTHER_MAX_NUM);
++		sp->udp_fifo_idx = sp->total_tcp_fifos;
++		sp->total_udp_fifos = FIFO_UDP_MAX_NUM;
++		sp->other_fifo_idx = sp->udp_fifo_idx + FIFO_UDP_MAX_NUM;
++	}
++
++	config->multiq = dev_multiq;
++	for (i = 0; i < config->tx_fifo_num; i++) {
+ 		config->tx_cfg[i].fifo_len = tx_fifo_len[i];
+ 		config->tx_cfg[i].fifo_priority = i;
+ 	}
+ 
+ 	/* mapping the QoS priority to the configured fifos */
+ 	for (i = 0; i < MAX_TX_FIFOS; i++)
+-		config->fifo_mapping[i] = fifo_map[config->tx_fifo_num][i];
++		config->fifo_mapping[i] = fifo_map[config->tx_fifo_num - 1][i];
++
++	/* map the hashing selector table to the configured fifos */
++	for (i = 0; i < config->tx_fifo_num; i++)
++		sp->fifo_selector[i] = fifo_selector[i];
++
+ 
+ 	config->tx_intr_type = TXD_INT_TYPE_UTILZ;
+ 	for (i = 0; i < config->tx_fifo_num; i++) {
+@@ -7793,6 +7905,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ 	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+ 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ 	dev->vlan_rx_register = s2io_vlan_rx_register;
++	dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
+ 
+ 	/*
+ 	 * will use eth_mac_addr() for  dev->set_mac_address
+@@ -7813,7 +7926,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ 		dev->features |= NETIF_F_UFO;
+ 		dev->features |= NETIF_F_HW_CSUM;
+ 	}
+-
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++	if (config->multiq)
++		dev->features |= NETIF_F_MULTI_QUEUE;
++#endif
+ 	dev->tx_timeout = &s2io_tx_watchdog;
+ 	dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
+ 	INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
+@@ -7896,20 +8012,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ 	s2io_reset(sp);
+ 
+ 	/*
+-	 * Initialize the tasklet status and link state flags
++	 * Initialize link state flags
+ 	 * and the card state parameter
+ 	 */
+-	sp->tasklet_status = 0;
+ 	sp->state = 0;
+ 
+ 	/* Initialize spinlocks */
+ 	for (i = 0; i < sp->config.tx_fifo_num; i++)
+ 		spin_lock_init(&mac_control->fifos[i].tx_lock);
+ 
+-	if (!napi)
+-		spin_lock_init(&sp->put_lock);
+-	spin_lock_init(&sp->rx_lock);
+-
+ 	/*
+ 	 * SXE-002: Configure link and activity LED to init state
+ 	 * on driver load.
+@@ -7962,6 +8073,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ 
+ 	if (napi)
+ 		DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
++
++	DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name,
++		sp->config.tx_fifo_num);
++
+ 	switch(sp->config.intr_type) {
+ 		case INTA:
+ 		    DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
+@@ -7970,6 +8085,29 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ 		    DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
+ 		    break;
+ 	}
++	if (sp->config.multiq) {
++	for (i = 0; i < sp->config.tx_fifo_num; i++)
++		mac_control->fifos[i].multiq = config->multiq;
++		DBG_PRINT(ERR_DBG, "%s: Multiqueue support enabled\n",
++			dev->name);
++	} else
++		DBG_PRINT(ERR_DBG, "%s: Multiqueue support disabled\n",
++			dev->name);
++
++	switch (sp->config.tx_steering_type) {
++	case NO_STEERING:
++		DBG_PRINT(ERR_DBG, "%s: No steering enabled for"
++			" transmit\n", dev->name);
++			break;
++	case TX_PRIORITY_STEERING:
++		DBG_PRINT(ERR_DBG, "%s: Priority steering enabled for"
++			" transmit\n", dev->name);
++		break;
++	case TX_DEFAULT_STEERING:
++		DBG_PRINT(ERR_DBG, "%s: Default steering enabled for"
++			" transmit\n", dev->name);
++	}
++
+ 	if (sp->lro)
+ 		DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
+ 			  dev->name);
+@@ -8064,7 +8202,8 @@ module_init(s2io_starter);
+ module_exit(s2io_closer);
+ 
+ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
+-		struct tcphdr **tcp, struct RxD_t *rxdp)
++		struct tcphdr **tcp, struct RxD_t *rxdp,
++		struct s2io_nic *sp)
+ {
+ 	int ip_off;
+ 	u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len;
+@@ -8075,19 +8214,20 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
+ 		return -1;
+ 	}
+ 
+-	/* TODO:
+-	 * By default the VLAN field in the MAC is stripped by the card, if this
+-	 * feature is turned off in rx_pa_cfg register, then the ip_off field
+-	 * has to be shifted by a further 2 bytes
+-	 */
+-	switch (l2_type) {
+-		case 0: /* DIX type */
+-		case 4: /* DIX type with VLAN */
+-			ip_off = HEADER_ETHERNET_II_802_3_SIZE;
+-			break;
++	/* Checking for DIX type or DIX type with VLAN */
++	if ((l2_type == 0)
++		|| (l2_type == 4)) {
++		ip_off = HEADER_ETHERNET_II_802_3_SIZE;
++		/*
++		 * If vlan stripping is disabled and the frame is VLAN tagged,
++		 * shift the offset by the VLAN header size bytes.
++		 */
++		if ((!vlan_strip_flag) &&
++			(rxdp->Control_1 & RXD_FRAME_VLAN_TAG))
++			ip_off += HEADER_VLAN_SIZE;
++	} else {
+ 		/* LLC, SNAP etc are considered non-mergeable */
+-		default:
+-			return -1;
++		return -1;
+ 	}
+ 
+ 	*ip = (struct iphdr *)((u8 *)buffer + ip_off);
+@@ -8114,7 +8254,7 @@ static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp)
+ }
+ 
+ static void initiate_new_session(struct lro *lro, u8 *l2h,
+-		     struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len)
++	struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len, u16 vlan_tag)
+ {
+ 	DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+ 	lro->l2h = l2h;
+@@ -8125,6 +8265,7 @@ static void initiate_new_session(struct lro *lro, u8 *l2h,
+ 	lro->sg_num = 1;
+ 	lro->total_len = ntohs(ip->tot_len);
+ 	lro->frags_len = 0;
++	lro->vlan_tag = vlan_tag;
+ 	/*
+ 	 * check if we saw TCP timestamp. Other consistency checks have
+ 	 * already been done.
+@@ -8256,15 +8397,16 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
+ 	struct iphdr *ip;
+ 	struct tcphdr *tcph;
+ 	int ret = 0, i;
++	u16 vlan_tag = 0;
+ 
+ 	if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp,
+-					 rxdp))) {
++					 rxdp, sp))) {
+ 		DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n",
+ 			  ip->saddr, ip->daddr);
+-	} else {
++	} else
+ 		return ret;
+-	}
+ 
++	vlan_tag = RXD_GET_VLAN_TAG(rxdp->Control_2);
+ 	tcph = (struct tcphdr *)*tcp;
+ 	*tcp_len = get_l4_pyld_length(ip, tcph);
+ 	for (i=0; i<MAX_LRO_SESSIONS; i++) {
+@@ -8324,7 +8466,8 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
+ 
+ 	switch (ret) {
+ 		case 3:
+-			initiate_new_session(*lro, buffer, ip, tcph, *tcp_len);
++			initiate_new_session(*lro, buffer, ip, tcph, *tcp_len,
++								vlan_tag);
+ 			break;
+ 		case 2:
+ 			update_L3L4_header(sp, *lro);
+@@ -8352,15 +8495,25 @@ static void clear_lro_session(struct lro *lro)
+ 	memset(lro, 0, lro_struct_size);
+ }
+ 
+-static void queue_rx_frame(struct sk_buff *skb)
++static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
+ {
+ 	struct net_device *dev = skb->dev;
++	struct s2io_nic *sp = dev->priv;
+ 
+ 	skb->protocol = eth_type_trans(skb, dev);
+-	if (napi)
+-		netif_receive_skb(skb);
+-	else
+-		netif_rx(skb);
++	if (sp->vlgrp && vlan_tag
++		&& (vlan_strip_flag)) {
++		/* Queueing the vlan frame to the upper layer */
++		if (sp->config.napi)
++			vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag);
++		else
++			vlan_hwaccel_rx(skb, sp->vlgrp, vlan_tag);
++	} else {
++		if (sp->config.napi)
++			netif_receive_skb(skb);
++		else
++			netif_rx(skb);
++	}
+ }
+ 
+ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
+diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
+index 64b88eb..ce53a02 100644
+--- a/drivers/net/s2io.h
++++ b/drivers/net/s2io.h
+@@ -360,7 +360,10 @@ struct stat_block {
+ #define MAX_TX_FIFOS 8
+ #define MAX_RX_RINGS 8
+ 
+-#define FIFO_DEFAULT_NUM	1
++#define FIFO_DEFAULT_NUM	5
++#define FIFO_UDP_MAX_NUM			2 /* 0 - even, 1 -odd ports */
++#define FIFO_OTHER_MAX_NUM			1
++
+ 
+ #define MAX_RX_DESC_1  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 127 )
+ #define MAX_RX_DESC_2  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 )
+@@ -379,6 +382,8 @@ static int fifo_map[][MAX_TX_FIFOS] = {
+ 	{0, 1, 2, 3, 4, 5, 6, 7},
+ };
+ 
++static u16 fifo_selector[MAX_TX_FIFOS] = {0, 1, 3, 3, 7, 7, 7, 7};
++
+ /* Maintains Per FIFO related information. */
+ struct tx_fifo_config {
+ #define	MAX_AVAILABLE_TXDS	8192
+@@ -431,6 +436,12 @@ struct config_param {
+ /* Tx Side */
+ 	u32 tx_fifo_num;	/*Number of Tx FIFOs */
+ 
++	/* 0-No steering, 1-Priority steering, 2-Default fifo map */
++#define	NO_STEERING				0
++#define	TX_PRIORITY_STEERING			0x1
++#define TX_DEFAULT_STEERING 			0x2
++	u8 tx_steering_type;
++
+ 	u8 fifo_mapping[MAX_TX_FIFOS];
+ 	struct tx_fifo_config tx_cfg[MAX_TX_FIFOS];	/*Per-Tx FIFO config */
+ 	u32 max_txds;		/*Max no. of Tx buffer descriptor per TxDL */
+@@ -464,6 +475,7 @@ struct config_param {
+ 	int max_mc_addr;	/* xena=64 herc=256 */
+ 	int max_mac_addr;	/* xena=16 herc=64 */
+ 	int mc_start_offset;	/* xena=16 herc=64 */
++	u8 multiq;
+ };
+ 
+ /* Structure representing MAC Addrs */
+@@ -534,6 +546,7 @@ struct RxD_t {
+ #define RXD_OWN_XENA            s2BIT(7)
+ #define RXD_T_CODE              (s2BIT(12)|s2BIT(13)|s2BIT(14)|s2BIT(15))
+ #define RXD_FRAME_PROTO         vBIT(0xFFFF,24,8)
++#define RXD_FRAME_VLAN_TAG      s2BIT(24)
+ #define RXD_FRAME_PROTO_IPV4    s2BIT(27)
+ #define RXD_FRAME_PROTO_IPV6    s2BIT(28)
+ #define RXD_FRAME_IP_FRAG	s2BIT(29)
+@@ -690,9 +703,6 @@ struct ring_info {
+ 	 */
+ 	struct rx_curr_get_info rx_curr_get_info;
+ 
+-	/* Index to the absolute position of the put pointer of Rx ring */
+-	int put_pos;
+-
+ 	/* Buffer Address store. */
+ 	struct buffAdd **ba;
+ 	struct s2io_nic *nic;
+@@ -720,6 +730,15 @@ struct fifo_info {
+ 	 * the buffers
+ 	 */
+ 	struct tx_curr_get_info tx_curr_get_info;
++#define FIFO_QUEUE_START 0
++#define FIFO_QUEUE_STOP 1
++	int queue_state;
++
++	/* copy of sp->dev pointer */
++	struct net_device *dev;
++
++	/* copy of multiq status */
++	u8 multiq;
+ 
+ 	/* Per fifo lock */
+ 	spinlock_t tx_lock;
+@@ -808,10 +827,11 @@ struct lro {
+ 	int		sg_num;
+ 	int		in_use;
+ 	__be16		window;
++	u16             vlan_tag;
+ 	u32		cur_tsval;
+ 	__be32		cur_tsecr;
+ 	u8		saw_ts;
+-};
++} ____cacheline_aligned;
+ 
+ /* These flags represent the devices temporary state */
+ enum s2io_device_state_t
+@@ -845,8 +865,6 @@ struct s2io_nic {
+ 	int device_enabled_once;
+ 
+ 	char name[60];
+-	struct tasklet_struct task;
+-	volatile unsigned long tasklet_status;
+ 
+ 	/* Timer that handles I/O errors/exceptions */
+ 	struct timer_list alarm_timer;
+@@ -856,8 +874,6 @@ struct s2io_nic {
+ 
+ 	atomic_t rx_bufs_left[MAX_RX_RINGS];
+ 
+-	spinlock_t put_lock;
+-
+ #define PROMISC     1
+ #define ALL_MULTI   2
+ 
+@@ -885,6 +901,27 @@ struct s2io_nic {
+ 	 */
+ 	int rx_csum;
+ 
++	/* Below variables are used for fifo selection to transmit a packet */
++	u16 fifo_selector[MAX_TX_FIFOS];
++
++	/* Total fifos for tcp packets */
++	u8 total_tcp_fifos;
++
++	/*
++	* Beginning index of udp for udp packets
++	* Value will be equal to
++	* (tx_fifo_num - FIFO_UDP_MAX_NUM - FIFO_OTHER_MAX_NUM)
++	*/
++	u8 udp_fifo_idx;
++
++	u8 total_udp_fifos;
++
++	/*
++	 * Beginning index of fifo for all other packets
++	 * Value will be equal to (tx_fifo_num - FIFO_OTHER_MAX_NUM)
++	*/
++	u8 other_fifo_idx;
++
+ 	/*  after blink, the adapter must be restored with original
+ 	 *  values.
+ 	 */
+@@ -920,7 +957,6 @@ struct s2io_nic {
+ 	u8		lro;
+ 	u16		lro_max_aggr_per_sess;
+ 	volatile unsigned long state;
+-	spinlock_t	rx_lock;
+ 	u64		general_int_mask;
+ #define VPD_STRING_LEN 80
+ 	u8  product_name[VPD_STRING_LEN];
+@@ -1050,7 +1086,6 @@ static void s2io_handle_errors(void * dev_id);
+ static int s2io_starter(void);
+ static void s2io_closer(void);
+ static void s2io_tx_watchdog(struct net_device *dev);
+-static void s2io_tasklet(unsigned long dev_addr);
+ static void s2io_set_multicast(struct net_device *dev);
+ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp);
+ static void s2io_link(struct s2io_nic * sp, int link);
+@@ -1087,7 +1122,7 @@ static int
+ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
+ 		      struct RxD_t *rxdp, struct s2io_nic *sp);
+ static void clear_lro_session(struct lro *lro);
+-static void queue_rx_frame(struct sk_buff *skb);
++static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag);
+ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro);
+ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
+ 			   struct sk_buff *skb, u32 tcp_len);
+diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
+index 487f9d2..5986cec 100644
+--- a/drivers/net/sb1000.c
++++ b/drivers/net/sb1000.c
+@@ -88,31 +88,31 @@ static int sb1000_close(struct net_device *dev);
+ 
+ 
+ /* SB1000 hardware routines to be used during open/configuration phases */
+-static inline int card_wait_for_busy_clear(const int ioaddr[],
++static int card_wait_for_busy_clear(const int ioaddr[],
+ 	const char* name);
+-static inline int card_wait_for_ready(const int ioaddr[], const char* name,
++static int card_wait_for_ready(const int ioaddr[], const char* name,
+ 	unsigned char in[]);
+ static int card_send_command(const int ioaddr[], const char* name,
+ 	const unsigned char out[], unsigned char in[]);
+ 
+ /* SB1000 hardware routines to be used during frame rx interrupt */
+-static inline int sb1000_wait_for_ready(const int ioaddr[], const char* name);
+-static inline int sb1000_wait_for_ready_clear(const int ioaddr[],
++static int sb1000_wait_for_ready(const int ioaddr[], const char* name);
++static int sb1000_wait_for_ready_clear(const int ioaddr[],
+ 	const char* name);
+-static inline void sb1000_send_command(const int ioaddr[], const char* name,
++static void sb1000_send_command(const int ioaddr[], const char* name,
+ 	const unsigned char out[]);
+-static inline void sb1000_read_status(const int ioaddr[], unsigned char in[]);
+-static inline void sb1000_issue_read_command(const int ioaddr[],
++static void sb1000_read_status(const int ioaddr[], unsigned char in[]);
++static void sb1000_issue_read_command(const int ioaddr[],
+ 	const char* name);
+ 
+ /* SB1000 commands for open/configuration */
+-static inline int sb1000_reset(const int ioaddr[], const char* name);
+-static inline int sb1000_check_CRC(const int ioaddr[], const char* name);
++static int sb1000_reset(const int ioaddr[], const char* name);
++static int sb1000_check_CRC(const int ioaddr[], const char* name);
+ static inline int sb1000_start_get_set_command(const int ioaddr[],
+ 	const char* name);
+-static inline int sb1000_end_get_set_command(const int ioaddr[],
++static int sb1000_end_get_set_command(const int ioaddr[],
+ 	const char* name);
+-static inline int sb1000_activate(const int ioaddr[], const char* name);
++static int sb1000_activate(const int ioaddr[], const char* name);
+ static int sb1000_get_firmware_version(const int ioaddr[],
+ 	const char* name, unsigned char version[], int do_end);
+ static int sb1000_get_frequency(const int ioaddr[], const char* name,
+@@ -125,8 +125,8 @@ static int sb1000_set_PIDs(const int ioaddr[], const char* name,
+ 	const short PID[]);
+ 
+ /* SB1000 commands for frame rx interrupt */
+-static inline int sb1000_rx(struct net_device *dev);
+-static inline void sb1000_error_dpc(struct net_device *dev);
++static int sb1000_rx(struct net_device *dev);
++static void sb1000_error_dpc(struct net_device *dev);
+ 
+ static const struct pnp_device_id sb1000_pnp_ids[] = {
+ 	{ "GIC1000", 0 },
+@@ -250,7 +250,7 @@ static struct pnp_driver sb1000_driver = {
+ static const int TimeOutJiffies = (875 * HZ) / 100;
+ 
+ /* Card Wait For Busy Clear (cannot be used during an interrupt) */
+-static inline int
++static int
+ card_wait_for_busy_clear(const int ioaddr[], const char* name)
+ {
+ 	unsigned char a;
+@@ -274,7 +274,7 @@ card_wait_for_busy_clear(const int ioaddr[], const char* name)
+ }
+ 
+ /* Card Wait For Ready (cannot be used during an interrupt) */
+-static inline int
++static int
+ card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[])
+ {
+ 	unsigned char a;
+@@ -354,7 +354,7 @@ card_send_command(const int ioaddr[], const char* name,
+ static const int Sb1000TimeOutJiffies = 7 * HZ;
+ 
+ /* Card Wait For Ready (to be used during frame rx) */
+-static inline int
++static int
+ sb1000_wait_for_ready(const int ioaddr[], const char* name)
+ {
+ 	unsigned long timeout;
+@@ -380,7 +380,7 @@ sb1000_wait_for_ready(const int ioaddr[], const char* name)
+ }
+ 
+ /* Card Wait For Ready Clear (to be used during frame rx) */
+-static inline int
++static int
+ sb1000_wait_for_ready_clear(const int ioaddr[], const char* name)
+ {
+ 	unsigned long timeout;
+@@ -405,7 +405,7 @@ sb1000_wait_for_ready_clear(const int ioaddr[], const char* name)
+ }
+ 
+ /* Card Send Command (to be used during frame rx) */
+-static inline void
++static void
+ sb1000_send_command(const int ioaddr[], const char* name,
+ 	const unsigned char out[])
+ {
+@@ -422,7 +422,7 @@ sb1000_send_command(const int ioaddr[], const char* name,
+ }
+ 
+ /* Card Read Status (to be used during frame rx) */
+-static inline void
++static void
+ sb1000_read_status(const int ioaddr[], unsigned char in[])
+ {
+ 	in[1] = inb(ioaddr[0] + 1);
+@@ -434,10 +434,10 @@ sb1000_read_status(const int ioaddr[], unsigned char in[])
+ }
+ 
+ /* Issue Read Command (to be used during frame rx) */
+-static inline void
++static void
+ sb1000_issue_read_command(const int ioaddr[], const char* name)
+ {
+-	const unsigned char Command0[6] = {0x20, 0x00, 0x00, 0x01, 0x00, 0x00};
++	static const unsigned char Command0[6] = {0x20, 0x00, 0x00, 0x01, 0x00, 0x00};
+ 
+ 	sb1000_wait_for_ready_clear(ioaddr, name);
+ 	outb(0xa0, ioaddr[0] + 6);
+@@ -450,12 +450,13 @@ sb1000_issue_read_command(const int ioaddr[], const char* name)
+  * SB1000 commands for open/configuration
+  */
+ /* reset SB1000 card */
+-static inline int
++static int
+ sb1000_reset(const int ioaddr[], const char* name)
+ {
++	static const unsigned char Command0[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
++
+ 	unsigned char st[7];
+ 	int port, status;
+-	const unsigned char Command0[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
+ 
+ 	port = ioaddr[1] + 6;
+ 	outb(0x4, port);
+@@ -479,12 +480,13 @@ sb1000_reset(const int ioaddr[], const char* name)
+ }
+ 
+ /* check SB1000 firmware CRC */
+-static inline int
++static int
+ sb1000_check_CRC(const int ioaddr[], const char* name)
+ {
++	static const unsigned char Command0[6] = {0x80, 0x1f, 0x00, 0x00, 0x00, 0x00};
++
+ 	unsigned char st[7];
+ 	int crc, status;
+-	const unsigned char Command0[6] = {0x80, 0x1f, 0x00, 0x00, 0x00, 0x00};
+ 
+ 	/* check CRC */
+ 	if ((status = card_send_command(ioaddr, name, Command0, st)))
+@@ -498,32 +500,35 @@ sb1000_check_CRC(const int ioaddr[], const char* name)
+ static inline int
+ sb1000_start_get_set_command(const int ioaddr[], const char* name)
+ {
++	static const unsigned char Command0[6] = {0x80, 0x1b, 0x00, 0x00, 0x00, 0x00};
++
+ 	unsigned char st[7];
+-	const unsigned char Command0[6] = {0x80, 0x1b, 0x00, 0x00, 0x00, 0x00};
+ 
+ 	return card_send_command(ioaddr, name, Command0, st);
+ }
+ 
+-static inline int
++static int
+ sb1000_end_get_set_command(const int ioaddr[], const char* name)
+ {
++	static const unsigned char Command0[6] = {0x80, 0x1b, 0x02, 0x00, 0x00, 0x00};
++	static const unsigned char Command1[6] = {0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
++
+ 	unsigned char st[7];
+ 	int status;
+-	const unsigned char Command0[6] = {0x80, 0x1b, 0x02, 0x00, 0x00, 0x00};
+-	const unsigned char Command1[6] = {0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
+ 
+ 	if ((status = card_send_command(ioaddr, name, Command0, st)))
+ 		return status;
+ 	return card_send_command(ioaddr, name, Command1, st);
+ }
+ 
+-static inline int
++static int
+ sb1000_activate(const int ioaddr[], const char* name)
+ {
++	static const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00};
++	static const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
++
+ 	unsigned char st[7];
+ 	int status;
+-	const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00};
+-	const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
+ 
+ 	ssleep(1);
+ 	if ((status = card_send_command(ioaddr, name, Command0, st)))
+@@ -544,9 +549,10 @@ static int
+ sb1000_get_firmware_version(const int ioaddr[], const char* name,
+ 	unsigned char version[], int do_end)
+ {
++	static const unsigned char Command0[6] = {0x80, 0x23, 0x00, 0x00, 0x00, 0x00};
++
+ 	unsigned char st[7];
+ 	int status;
+-	const unsigned char Command0[6] = {0x80, 0x23, 0x00, 0x00, 0x00, 0x00};
+ 
+ 	if ((status = sb1000_start_get_set_command(ioaddr, name)))
+ 		return status;
+@@ -566,9 +572,10 @@ sb1000_get_firmware_version(const int ioaddr[], const char* name,
+ static int
+ sb1000_get_frequency(const int ioaddr[], const char* name, int* frequency)
+ {
++	static const unsigned char Command0[6] = {0x80, 0x44, 0x00, 0x00, 0x00, 0x00};
++
+ 	unsigned char st[7];
+ 	int status;
+-	const unsigned char Command0[6] = {0x80, 0x44, 0x00, 0x00, 0x00, 0x00};
+ 
+ 	udelay(1000);
+ 	if ((status = sb1000_start_get_set_command(ioaddr, name)))
+@@ -613,12 +620,13 @@ sb1000_set_frequency(const int ioaddr[], const char* name, int frequency)
+ static int
+ sb1000_get_PIDs(const int ioaddr[], const char* name, short PID[])
+ {
++	static const unsigned char Command0[6] = {0x80, 0x40, 0x00, 0x00, 0x00, 0x00};
++	static const unsigned char Command1[6] = {0x80, 0x41, 0x00, 0x00, 0x00, 0x00};
++	static const unsigned char Command2[6] = {0x80, 0x42, 0x00, 0x00, 0x00, 0x00};
++	static const unsigned char Command3[6] = {0x80, 0x43, 0x00, 0x00, 0x00, 0x00};
++
+ 	unsigned char st[7];
+ 	int status;
+-	const unsigned char Command0[6] = {0x80, 0x40, 0x00, 0x00, 0x00, 0x00};
+-	const unsigned char Command1[6] = {0x80, 0x41, 0x00, 0x00, 0x00, 0x00};
+-	const unsigned char Command2[6] = {0x80, 0x42, 0x00, 0x00, 0x00, 0x00};
+-	const unsigned char Command3[6] = {0x80, 0x43, 0x00, 0x00, 0x00, 0x00};
+ 
+ 	udelay(1000);
+ 	if ((status = sb1000_start_get_set_command(ioaddr, name)))
+@@ -647,6 +655,8 @@ sb1000_get_PIDs(const int ioaddr[], const char* name, short PID[])
+ static int
+ sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
+ {
++	static const unsigned char Command4[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
++
+ 	unsigned char st[7];
+ 	short p;
+ 	int status;
+@@ -654,7 +664,6 @@ sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
+ 	unsigned char Command1[6] = {0x80, 0x32, 0x00, 0x00, 0x00, 0x00};
+ 	unsigned char Command2[6] = {0x80, 0x33, 0x00, 0x00, 0x00, 0x00};
+ 	unsigned char Command3[6] = {0x80, 0x34, 0x00, 0x00, 0x00, 0x00};
+-	const unsigned char Command4[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
+ 
+ 	udelay(1000);
+ 	if ((status = sb1000_start_get_set_command(ioaddr, name)))
+@@ -694,7 +703,7 @@ sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
+ }
+ 
+ 
+-static inline void
++static void
+ sb1000_print_status_buffer(const char* name, unsigned char st[],
+ 	unsigned char buffer[], int size)
+ {
+@@ -725,7 +734,7 @@ sb1000_print_status_buffer(const char* name, unsigned char st[],
+ /* receive a single frame and assemble datagram
+  * (this is the heart of the interrupt routine)
+  */
+-static inline int
++static int
+ sb1000_rx(struct net_device *dev)
+ {
+ 
+@@ -888,14 +897,15 @@ dropped_frame:
+ 	return -1;
+ }
+ 
+-static inline void
++static void
+ sb1000_error_dpc(struct net_device *dev)
+ {
++	static const unsigned char Command0[6] = {0x80, 0x26, 0x00, 0x00, 0x00, 0x00};
++
+ 	char *name;
+ 	unsigned char st[5];
+ 	int ioaddr[2];
+ 	struct sb1000_private *lp = netdev_priv(dev);
+-	const unsigned char Command0[6] = {0x80, 0x26, 0x00, 0x00, 0x00, 0x00};
+ 	const int ErrorDpcCounterInitialize = 200;
+ 
+ 	ioaddr[0] = dev->base_addr;
+@@ -1077,14 +1087,15 @@ sb1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ /* SB1000 interrupt handler. */
+ static irqreturn_t sb1000_interrupt(int irq, void *dev_id)
+ {
++	static const unsigned char Command0[6] = {0x80, 0x2c, 0x00, 0x00, 0x00, 0x00};
++	static const unsigned char Command1[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
++
+ 	char *name;
+ 	unsigned char st;
+ 	int ioaddr[2];
+ 	struct net_device *dev = dev_id;
+ 	struct sb1000_private *lp = netdev_priv(dev);
+ 
+-	const unsigned char Command0[6] = {0x80, 0x2c, 0x00, 0x00, 0x00, 0x00};
+-	const unsigned char Command1[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
+ 	const int MaxRxErrorCount = 6;
+ 
+ 	ioaddr[0] = dev->base_addr;
+diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
+index 7b53d65..888b7de 100644
+--- a/drivers/net/sb1250-mac.c
++++ b/drivers/net/sb1250-mac.c
+@@ -2374,7 +2374,7 @@ static int sbmac_init(struct platform_device *pldev, long long base)
+ 	       dev->name, base, print_mac(mac, eaddr));
+ 
+ 	sc->mii_bus.name = sbmac_mdio_string;
+-	sc->mii_bus.id = idx;
++	snprintf(sc->mii_bus.id, MII_BUS_ID_SIZE, "%x", idx);
+ 	sc->mii_bus.priv = sc;
+ 	sc->mii_bus.read = sbmac_mii_read;
+ 	sc->mii_bus.write = sbmac_mii_write;
+diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
+index 15fcee5..f64a860 100644
+--- a/drivers/net/sc92031.c
++++ b/drivers/net/sc92031.c
+@@ -311,7 +311,6 @@ struct sc92031_priv {
+ 
+ 	/* for dev->get_stats */
+ 	long			rx_value;
+-	struct net_device_stats	stats;
+ };
+ 
+ /* I don't know which registers can be safely read; however, I can guess
+@@ -421,7 +420,7 @@ static void _sc92031_tx_clear(struct net_device *dev)
+ 
+ 	while (priv->tx_head - priv->tx_tail > 0) {
+ 		priv->tx_tail++;
+-		priv->stats.tx_dropped++;
++		dev->stats.tx_dropped++;
+ 	}
+ 	priv->tx_head = priv->tx_tail = 0;
+ }
+@@ -676,27 +675,27 @@ static void _sc92031_tx_tasklet(struct net_device *dev)
+ 		priv->tx_tail++;
+ 
+ 		if (tx_status & TxStatOK) {
+-			priv->stats.tx_bytes += tx_status & 0x1fff;
+-			priv->stats.tx_packets++;
++			dev->stats.tx_bytes += tx_status & 0x1fff;
++			dev->stats.tx_packets++;
+ 			/* Note: TxCarrierLost is always asserted at 100mbps. */
+-			priv->stats.collisions += (tx_status >> 22) & 0xf;
++			dev->stats.collisions += (tx_status >> 22) & 0xf;
+ 		}
+ 
+ 		if (tx_status & (TxOutOfWindow | TxAborted)) {
+-			priv->stats.tx_errors++;
++			dev->stats.tx_errors++;
+ 
+ 			if (tx_status & TxAborted)
+-				priv->stats.tx_aborted_errors++;
++				dev->stats.tx_aborted_errors++;
+ 
+ 			if (tx_status & TxCarrierLost)
+-				priv->stats.tx_carrier_errors++;
++				dev->stats.tx_carrier_errors++;
+ 
+ 			if (tx_status & TxOutOfWindow)
+-				priv->stats.tx_window_errors++;
++				dev->stats.tx_window_errors++;
+ 		}
+ 
+ 		if (tx_status & TxUnderrun)
+-			priv->stats.tx_fifo_errors++;
++			dev->stats.tx_fifo_errors++;
+ 	}
+ 
+ 	if (priv->tx_tail != old_tx_tail)
+@@ -704,27 +703,29 @@ static void _sc92031_tx_tasklet(struct net_device *dev)
+ 			netif_wake_queue(dev);
+ }
+ 
+-static void _sc92031_rx_tasklet_error(u32 rx_status,
+-		struct sc92031_priv *priv, unsigned rx_size)
++static void _sc92031_rx_tasklet_error(struct net_device *dev,
++				      u32 rx_status, unsigned rx_size)
+ {
+ 	if(rx_size > (MAX_ETH_FRAME_SIZE + 4) || rx_size < 16) {
+-		priv->stats.rx_errors++;
+-		priv->stats.rx_length_errors++;
++		dev->stats.rx_errors++;
++		dev->stats.rx_length_errors++;
+ 	}
+ 
+ 	if (!(rx_status & RxStatesOK)) {
+-		priv->stats.rx_errors++;
++		dev->stats.rx_errors++;
+ 
+ 		if (rx_status & (RxHugeFrame | RxSmallFrame))
+-			priv->stats.rx_length_errors++;
++			dev->stats.rx_length_errors++;
+ 
+ 		if (rx_status & RxBadAlign)
+-			priv->stats.rx_frame_errors++;
++			dev->stats.rx_frame_errors++;
+ 
+ 		if (!(rx_status & RxCRCOK))
+-			priv->stats.rx_crc_errors++;
+-	} else
++			dev->stats.rx_crc_errors++;
++	} else {
++		struct sc92031_priv *priv = netdev_priv(dev);
+ 		priv->rx_loss++;
++	}
+ }
+ 
+ static void _sc92031_rx_tasklet(struct net_device *dev)
+@@ -783,7 +784,7 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
+ 				|| rx_size > (MAX_ETH_FRAME_SIZE + 4)
+ 				|| rx_size < 16
+ 				|| !(rx_status & RxStatesOK))) {
+-			_sc92031_rx_tasklet_error(rx_status, priv, rx_size);
++			_sc92031_rx_tasklet_error(dev, rx_status, rx_size);
+ 			break;
+ 		}
+ 
+@@ -795,7 +796,7 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
+ 
+ 		rx_len -= rx_size_align + 4;
+ 
+-		skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
++		skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN);
+ 		if (unlikely(!skb)) {
+ 			if (printk_ratelimit())
+ 				printk(KERN_ERR "%s: Couldn't allocate a skb_buff for a packet of size %u\n",
+@@ -818,11 +819,11 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
+ 		dev->last_rx = jiffies;
+ 		netif_rx(skb);
+ 
+-		priv->stats.rx_bytes += pkt_size;
+-		priv->stats.rx_packets++;
++		dev->stats.rx_bytes += pkt_size;
++		dev->stats.rx_packets++;
+ 
+ 		if (rx_status & Rx_Multicast)
+-			priv->stats.multicast++;
++			dev->stats.multicast++;
+ 
+ 	next:
+ 		rx_ring_offset = (rx_ring_offset + rx_size_align) % RX_BUF_LEN;
+@@ -835,13 +836,11 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
+ 
+ static void _sc92031_link_tasklet(struct net_device *dev)
+ {
+-	struct sc92031_priv *priv = netdev_priv(dev);
+-
+ 	if (_sc92031_check_media(dev))
+ 		netif_wake_queue(dev);
+ 	else {
+ 		netif_stop_queue(dev);
+-		priv->stats.tx_carrier_errors++;
++		dev->stats.tx_carrier_errors++;
+ 	}
+ }
+ 
+@@ -866,11 +865,11 @@ static void sc92031_tasklet(unsigned long data)
+ 		_sc92031_rx_tasklet(dev);
+ 
+ 	if (intr_status & RxOverflow)
+-		priv->stats.rx_errors++;
++		dev->stats.rx_errors++;
+ 
+ 	if (intr_status & TimeOut) {
+-		priv->stats.rx_errors++;
+-		priv->stats.rx_length_errors++;
++		dev->stats.rx_errors++;
++		dev->stats.rx_length_errors++;
+ 	}
+ 
+ 	if (intr_status & (LinkFail | LinkOK))
+@@ -936,38 +935,36 @@ static struct net_device_stats *sc92031_get_stats(struct net_device *dev)
+ 
+ 		if (temp == 0xffff) {
+ 			priv->rx_value += temp;
+-			priv->stats.rx_fifo_errors = priv->rx_value;
+-		} else {
+-			priv->stats.rx_fifo_errors = temp + priv->rx_value;
+-		}
++			dev->stats.rx_fifo_errors = priv->rx_value;
++		} else
++			dev->stats.rx_fifo_errors = temp + priv->rx_value;
+ 
+ 		spin_unlock_bh(&priv->lock);
+ 	}
+ 
+-	return &priv->stats;
++	return &dev->stats;
+ }
+ 
+ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+-	int err = 0;
+ 	struct sc92031_priv *priv = netdev_priv(dev);
+ 	void __iomem *port_base = priv->port_base;
+-
+ 	unsigned len;
+ 	unsigned entry;
+ 	u32 tx_status;
+ 
++	if (skb_padto(skb, ETH_ZLEN))
++		return NETDEV_TX_OK;
++
+ 	if (unlikely(skb->len > TX_BUF_SIZE)) {
+-		err = -EMSGSIZE;
+-		priv->stats.tx_dropped++;
++		dev->stats.tx_dropped++;
+ 		goto out;
+ 	}
+ 
+ 	spin_lock(&priv->lock);
+ 
+ 	if (unlikely(!netif_carrier_ok(dev))) {
+-		err = -ENOLINK;
+-		priv->stats.tx_dropped++;
++		dev->stats.tx_dropped++;
+ 		goto out_unlock;
+ 	}
+ 
+@@ -978,11 +975,6 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	skb_copy_and_csum_dev(skb, priv->tx_bufs + entry * TX_BUF_SIZE);
+ 
+ 	len = skb->len;
+-	if (unlikely(len < ETH_ZLEN)) {
+-		memset(priv->tx_bufs + entry * TX_BUF_SIZE + len,
+-				0, ETH_ZLEN - len);
+-		len = ETH_ZLEN;
+-	}
+ 
+ 	wmb();
+ 
+@@ -1009,7 +1001,7 @@ out_unlock:
+ out:
+ 	dev_kfree_skb(skb);
+ 
+-	return err;
++	return NETDEV_TX_OK;
+ }
+ 
+ static int sc92031_open(struct net_device *dev)
+diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
+index 78994ed..6261201 100644
+--- a/drivers/net/sgiseeq.c
++++ b/drivers/net/sgiseeq.c
+@@ -825,7 +825,8 @@ static struct platform_driver sgiseeq_driver = {
+ 	.probe	= sgiseeq_probe,
+ 	.remove	= __devexit_p(sgiseeq_remove),
+ 	.driver = {
+-		.name	= "sgiseeq"
++		.name	= "sgiseeq",
++		.owner	= THIS_MODULE,
+ 	}
+ };
+ 
+@@ -850,3 +851,4 @@ module_exit(sgiseeq_module_exit);
+ MODULE_DESCRIPTION("SGI Seeq 8003 driver");
+ MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips at linux-mips.org>");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:sgiseeq");
+diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
+deleted file mode 100644
+index afd900d..0000000
+--- a/drivers/net/sk98lin/Makefile
++++ /dev/null
+@@ -1,87 +0,0 @@
+-#
+-# Makefile for the SysKonnect SK-98xx device driver.
+-#
+-
+-
+-#
+-# Standalone driver params
+-# SKPARAM += -DSK_KERNEL_24
+-# SKPARAM += -DSK_KERNEL_24_26
+-# SKPARAM += -DSK_KERNEL_26
+-# SKPARAM += -DSK_KERNEL_22_24
+-
+-obj-$(CONFIG_SK98LIN) += sk98lin.o
+-sk98lin-objs    :=	\
+-		skge.o		\
+-		skethtool.o	\
+-		skdim.o		\
+-		skaddr.o	\
+-		skgehwt.o	\
+-		skgeinit.o	\
+-		skgepnmi.o	\
+-		skgesirq.o	\
+-		ski2c.o		\
+-		sklm80.o	\
+-		skqueue.o	\
+-		skrlmt.o	\
+-		sktimer.o	\
+-		skvpd.o		\
+-		skxmac2.o
+-
+-# DBGDEF =  \
+-# -DDEBUG
+-
+-ifdef DEBUG
+-DBGDEF +=  \
+--DSK_DEBUG_CHKMOD=0x00000000L \
+--DSK_DEBUG_CHKCAT=0x00000000L
+-endif
+-
+-
+-# **** possible debug modules for SK_DEBUG_CHKMOD *****************
+-# SK_DBGMOD_MERR        0x00000001L     /* general module error indication */
+-# SK_DBGMOD_HWM         0x00000002L     /* Hardware init module */
+-# SK_DBGMOD_RLMT        0x00000004L     /* RLMT module */
+-# SK_DBGMOD_VPD         0x00000008L     /* VPD module */
+-# SK_DBGMOD_I2C         0x00000010L     /* I2C module */
+-# SK_DBGMOD_PNMI        0x00000020L     /* PNMI module */
+-# SK_DBGMOD_CSUM        0x00000040L     /* CSUM module */
+-# SK_DBGMOD_ADDR        0x00000080L     /* ADDR module */
+-# SK_DBGMOD_DRV         0x00010000L     /* DRV module */
+-
+-# **** possible debug categories for SK_DEBUG_CHKCAT **************
+-# *** common modules ***
+-# SK_DBGCAT_INIT        0x00000001L     module/driver initialization
+-# SK_DBGCAT_CTRL        0x00000002L     controlling: add/rmv MCA/MAC and other controls (IOCTL)
+-# SK_DBGCAT_ERR         0x00000004L     error handling paths
+-# SK_DBGCAT_TX          0x00000008L     transmit path
+-# SK_DBGCAT_RX          0x00000010L     receive path
+-# SK_DBGCAT_IRQ         0x00000020L     general IRQ handling
+-# SK_DBGCAT_QUEUE       0x00000040L     any queue management
+-# SK_DBGCAT_DUMP        0x00000080L     large data output e.g. hex dump
+-# SK_DBGCAT_FATAL       0x00000100L     large data output e.g. hex dump
+-
+-# *** driver (file skge.c) ***
+-# SK_DBGCAT_DRV_ENTRY           0x00010000      entry points
+-# SK_DBGCAT_DRV_???             0x00020000      not used
+-# SK_DBGCAT_DRV_MCA             0x00040000      multicast
+-# SK_DBGCAT_DRV_TX_PROGRESS     0x00080000      tx path
+-# SK_DBGCAT_DRV_RX_PROGRESS     0x00100000      rx path
+-# SK_DBGCAT_DRV_PROGRESS        0x00200000      general runtime
+-# SK_DBGCAT_DRV_???             0x00400000      not used
+-# SK_DBGCAT_DRV_PROM            0x00800000      promiscuous mode
+-# SK_DBGCAT_DRV_TX_FRAME        0x01000000      display tx frames
+-# SK_DBGCAT_DRV_ERROR           0x02000000      error conditions
+-# SK_DBGCAT_DRV_INT_SRC         0x04000000      interrupts sources
+-# SK_DBGCAT_DRV_EVENT           0x08000000      driver events
+-
+-EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
+-
+-clean:
+-	rm -f core *.o *.a *.s
+-
+-
+-
+-
+-
+-
+diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h
+deleted file mode 100644
+index 4e2dbbf..0000000
+--- a/drivers/net/sk98lin/h/lm80.h
++++ /dev/null
+@@ -1,179 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	lm80.h	
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.6 $
+- * Date:	$Date: 2003/05/13 17:26:52 $
+- * Purpose:	Contains all defines for the LM80 Chip
+- *		(National Semiconductor).
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_LM80_H
+-#define __INC_LM80_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif	/* __cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-/*
+- * LM80 register definition
+- *
+- * All registers are 8 bit wide
+- */
+-#define LM80_CFG			0x00	/* Configuration Register */
+-#define LM80_ISRC_1			0x01	/* Interrupt Status Register 1 */
+-#define LM80_ISRC_2			0x02	/* Interrupt Status Register 2 */
+-#define LM80_IMSK_1			0x03	/* Interrupt Mask Register 1 */
+-#define LM80_IMSK_2			0x04	/* Interrupt Mask Register 2 */
+-#define LM80_FAN_CTRL		0x05	/* Fan Devisor/RST#/OS# Register */
+-#define LM80_TEMP_CTRL		0x06	/* OS# Config, Temp Res. Reg */
+-	/* 0x07 - 0x1f reserved	*/
+-	/* current values */
+-#define LM80_VT0_IN			0x20	/* current Voltage 0 value */
+-#define LM80_VT1_IN			0x21	/* current Voltage 1 value */
+-#define LM80_VT2_IN			0x22	/* current Voltage 2 value */
+-#define LM80_VT3_IN			0x23	/* current Voltage 3 value */
+-#define LM80_VT4_IN			0x24	/* current Voltage 4 value */
+-#define LM80_VT5_IN			0x25	/* current Voltage 5 value */
+-#define LM80_VT6_IN			0x26	/* current Voltage 6 value */
+-#define LM80_TEMP_IN		0x27	/* current Temperature value */
+-#define LM80_FAN1_IN		0x28	/* current Fan 1 count */
+-#define LM80_FAN2_IN		0x29	/* current Fan 2 count */
+-	/* limit values */
+-#define LM80_VT0_HIGH_LIM	0x2a	/* high limit val for Voltage 0 */
+-#define LM80_VT0_LOW_LIM	0x2b	/* low limit val for Voltage 0 */
+-#define LM80_VT1_HIGH_LIM	0x2c	/* high limit val for Voltage 1 */
+-#define LM80_VT1_LOW_LIM	0x2d	/* low limit val for Voltage 1 */
+-#define LM80_VT2_HIGH_LIM	0x2e	/* high limit val for Voltage 2 */
+-#define LM80_VT2_LOW_LIM	0x2f	/* low limit val for Voltage 2 */
+-#define LM80_VT3_HIGH_LIM	0x30	/* high limit val for Voltage 3 */
+-#define LM80_VT3_LOW_LIM	0x31	/* low limit val for Voltage 3 */
+-#define LM80_VT4_HIGH_LIM	0x32	/* high limit val for Voltage 4 */
+-#define LM80_VT4_LOW_LIM	0x33	/* low limit val for Voltage 4 */
+-#define LM80_VT5_HIGH_LIM	0x34	/* high limit val for Voltage 5 */
+-#define LM80_VT5_LOW_LIM	0x35	/* low limit val for Voltage 5 */
+-#define LM80_VT6_HIGH_LIM	0x36	/* high limit val for Voltage 6 */
+-#define LM80_VT6_LOW_LIM	0x37	/* low limit val for Voltage 6 */
+-#define LM80_THOT_LIM_UP	0x38	/* hot temperature limit (high) */
+-#define LM80_THOT_LIM_LO	0x39	/* hot temperature limit (low) */
+-#define LM80_TOS_LIM_UP		0x3a	/* OS temperature limit (high) */
+-#define LM80_TOS_LIM_LO		0x3b	/* OS temperature limit (low) */
+-#define LM80_FAN1_COUNT_LIM	0x3c	/* Fan 1 count limit (high) */
+-#define LM80_FAN2_COUNT_LIM	0x3d	/* Fan 2 count limit (low) */
+-	/* 0x3e - 0x3f reserved	*/
+-
+-/*
+- * LM80 bit definitions
+- */
+-
+-/*	LM80_CFG		Configuration Register */
+-#define LM80_CFG_START		(1<<0)	/* start monitoring operation */
+-#define LM80_CFG_INT_ENA	(1<<1)	/* enables the INT# Interrupt output */
+-#define LM80_CFG_INT_POL	(1<<2)	/* INT# pol: 0 act low, 1 act high */
+-#define LM80_CFG_INT_CLR	(1<<3)	/* disables INT#/RST_OUT#/OS# outputs */
+-#define LM80_CFG_RESET		(1<<4)	/* signals a reset */
+-#define LM80_CFG_CHASS_CLR	(1<<5)	/* clears Chassis Intrusion (CI) pin */
+-#define LM80_CFG_GPO		(1<<6)	/* drives the GPO# pin */
+-#define LM80_CFG_INIT		(1<<7)	/* restore power on defaults */
+-
+-/*	LM80_ISRC_1		Interrupt Status Register 1 */
+-/*	LM80_IMSK_1		Interrupt Mask Register 1 */
+-#define LM80_IS_VT0			(1<<0)	/* limit exceeded for Voltage 0 */
+-#define LM80_IS_VT1			(1<<1)	/* limit exceeded for Voltage 1 */
+-#define LM80_IS_VT2			(1<<2)	/* limit exceeded for Voltage 2 */
+-#define LM80_IS_VT3			(1<<3)	/* limit exceeded for Voltage 3 */
+-#define LM80_IS_VT4			(1<<4)	/* limit exceeded for Voltage 4 */
+-#define LM80_IS_VT5			(1<<5)	/* limit exceeded for Voltage 5 */
+-#define LM80_IS_VT6			(1<<6)	/* limit exceeded for Voltage 6 */
+-#define LM80_IS_INT_IN		(1<<7)	/* state of INT_IN# */
+-
+-/*	LM80_ISRC_2		Interrupt Status Register 2 */
+-/*	LM80_IMSK_2		Interrupt Mask Register 2 */
+-#define LM80_IS_TEMP		(1<<0)	/* HOT temperature limit exceeded */
+-#define LM80_IS_BTI			(1<<1)	/* state of BTI# pin */
+-#define LM80_IS_FAN1		(1<<2)	/* count limit exceeded for Fan 1 */
+-#define LM80_IS_FAN2		(1<<3)	/* count limit exceeded for Fan 2 */
+-#define LM80_IS_CI			(1<<4)	/* Chassis Intrusion occured */
+-#define LM80_IS_OS			(1<<5)	/* OS temperature limit exceeded */
+-	/* bit 6 and 7 are reserved in LM80_ISRC_2 */
+-#define LM80_IS_HT_IRQ_MD	(1<<6)	/* Hot temperature interrupt mode */
+-#define LM80_IS_OT_IRQ_MD	(1<<7)	/* OS temperature interrupt mode */
+-
+-/*	LM80_FAN_CTRL		Fan Devisor/RST#/OS# Register */
+-#define LM80_FAN1_MD_SEL	(1<<0)	/* Fan 1 mode select */
+-#define LM80_FAN2_MD_SEL	(1<<1)	/* Fan 2 mode select */
+-#define LM80_FAN1_PRM_CTL	(3<<2)	/* Fan 1 speed control */
+-#define LM80_FAN2_PRM_CTL	(3<<4)	/* Fan 2 speed control */
+-#define LM80_FAN_OS_ENA		(1<<6)	/* enable OS mode on RST_OUT#/OS# pins*/
+-#define LM80_FAN_RST_ENA	(1<<7)	/* sets RST_OUT#/OS# pins in RST mode */
+-
+-/*	LM80_TEMP_CTRL		OS# Config, Temp Res. Reg */
+-#define LM80_TEMP_OS_STAT	(1<<0)	/* mirrors the state of RST_OUT#/OS# */
+-#define LM80_TEMP_OS_POL	(1<<1)	/* select OS# polarity */
+-#define LM80_TEMP_OS_MODE	(1<<2)	/* selects Interrupt mode */
+-#define LM80_TEMP_RES		(1<<3)	/* selects 9 or 11 bit temp resulution*/
+-#define LM80_TEMP_LSB		(0xf<<4)/* 4 LSBs of 11 bit temp data */
+-#define LM80_TEMP_LSB_9		(1<<7)	/* LSB of 9 bit temperature data */
+-
+-	/* 0x07 - 0x1f reserved	*/
+-/*	LM80_VT0_IN		current Voltage 0 value */
+-/*	LM80_VT1_IN		current Voltage 1 value */
+-/*	LM80_VT2_IN		current Voltage 2 value */
+-/*	LM80_VT3_IN		current Voltage 3 value */
+-/*	LM80_VT4_IN		current Voltage 4 value */
+-/*	LM80_VT5_IN		current Voltage 5 value */
+-/*	LM80_VT6_IN		current Voltage 6 value */
+-/*	LM80_TEMP_IN		current temperature value */
+-/*	LM80_FAN1_IN		current Fan 1 count */
+-/*	LM80_FAN2_IN		current Fan 2 count */
+-/*	LM80_VT0_HIGH_LIM	high limit val for Voltage 0 */
+-/*	LM80_VT0_LOW_LIM	low limit val for Voltage 0 */
+-/*	LM80_VT1_HIGH_LIM	high limit val for Voltage 1 */
+-/*	LM80_VT1_LOW_LIM	low limit val for Voltage 1 */
+-/*	LM80_VT2_HIGH_LIM	high limit val for Voltage 2 */
+-/*	LM80_VT2_LOW_LIM	low limit val for Voltage 2 */
+-/*	LM80_VT3_HIGH_LIM	high limit val for Voltage 3 */
+-/*	LM80_VT3_LOW_LIM	low limit val for Voltage 3 */
+-/*	LM80_VT4_HIGH_LIM	high limit val for Voltage 4 */
+-/*	LM80_VT4_LOW_LIM	low limit val for Voltage 4 */
+-/*	LM80_VT5_HIGH_LIM	high limit val for Voltage 5 */
+-/*	LM80_VT5_LOW_LIM	low limit val for Voltage 5 */
+-/*	LM80_VT6_HIGH_LIM	high limit val for Voltage 6 */
+-/*	LM80_VT6_LOW_LIM	low limit val for Voltage 6 */
+-/*	LM80_THOT_LIM_UP	hot temperature limit (high) */
+-/*	LM80_THOT_LIM_LO	hot temperature limit (low) */
+-/*	LM80_TOS_LIM_UP		OS temperature limit (high) */
+-/*	LM80_TOS_LIM_LO		OS temperature limit (low) */
+-/*	LM80_FAN1_COUNT_LIM	Fan 1 count limit (high) */
+-/*	LM80_FAN2_COUNT_LIM	Fan 2 count limit (low) */
+-	/* 0x3e - 0x3f reserved	*/
+-
+-#define LM80_ADDR		0x28	/* LM80 default addr */
+-
+-/* typedefs *******************************************************************/
+-
+-
+-/* function prototypes ********************************************************/
+-
+-#ifdef __cplusplus
+-}
+-#endif	/* __cplusplus */
+-
+-#endif	/* __INC_LM80_H */
+diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h
+deleted file mode 100644
+index 423ad06..0000000
+--- a/drivers/net/sk98lin/h/skaddr.h
++++ /dev/null
+@@ -1,285 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skaddr.h
+- * Project:	Gigabit Ethernet Adapters, ADDR-Modul
+- * Version:	$Revision: 1.29 $
+- * Date:	$Date: 2003/05/13 16:57:24 $
+- * Purpose:	Header file for Address Management (MC, UC, Prom).
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This module is intended to manage multicast addresses and promiscuous mode
+- * on GEnesis adapters.
+- *
+- * Include File Hierarchy:
+- *
+- *	"skdrv1st.h"
+- *	...
+- *	"sktypes.h"
+- *	"skqueue.h"
+- *	"skaddr.h"
+- *	...
+- *	"skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKADDR_H
+-#define __INC_SKADDR_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif	/* cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-#define SK_MAC_ADDR_LEN				6	/* Length of MAC address. */
+-#define	SK_MAX_ADDRS				14	/* #Addrs for exact match. */
+-
+-/* ----- Common return values ----- */
+-
+-#define SK_ADDR_SUCCESS				0	/* Function returned successfully. */
+-#define SK_ADDR_ILLEGAL_PORT			100	/* Port number too high. */
+-#define SK_ADDR_TOO_EARLY			101	/* Function called too early. */
+-
+-/* ----- Clear/Add flag bits ----- */
+-
+-#define SK_ADDR_PERMANENT			1	/* RLMT Address */
+-
+-/* ----- Additional Clear flag bits ----- */
+-
+-#define SK_MC_SW_ONLY				2	/* Do not update HW when clearing. */
+-
+-/* ----- Override flag bits ----- */
+-
+-#define SK_ADDR_LOGICAL_ADDRESS		0
+-#define SK_ADDR_VIRTUAL_ADDRESS		(SK_ADDR_LOGICAL_ADDRESS)	/* old */
+-#define SK_ADDR_PHYSICAL_ADDRESS	1
+-#define SK_ADDR_CLEAR_LOGICAL		2
+-#define SK_ADDR_SET_LOGICAL			4
+-
+-/* ----- Override return values ----- */
+-
+-#define SK_ADDR_OVERRIDE_SUCCESS	(SK_ADDR_SUCCESS)
+-#define SK_ADDR_DUPLICATE_ADDRESS	1
+-#define SK_ADDR_MULTICAST_ADDRESS	2
+-
+-/* ----- Partitioning of excact match table ----- */
+-
+-#define SK_ADDR_EXACT_MATCHES		16	/* #Exact match entries. */
+-
+-#define SK_ADDR_FIRST_MATCH_RLMT	1
+-#define SK_ADDR_LAST_MATCH_RLMT		2
+-#define SK_ADDR_FIRST_MATCH_DRV		3
+-#define SK_ADDR_LAST_MATCH_DRV		(SK_ADDR_EXACT_MATCHES - 1)
+-
+-/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */
+-
+-#define SK_MC_FILTERING_EXACT		0	/* Exact filtering. */
+-#define SK_MC_FILTERING_INEXACT		1	/* Inexact filtering. */
+-
+-/* ----- Additional SkAddrMcAdd return values ----- */
+-
+-#define SK_MC_ILLEGAL_ADDRESS		2	/* Illegal address. */
+-#define SK_MC_ILLEGAL_PORT			3	/* Illegal port (not the active one). */
+-#define SK_MC_RLMT_OVERFLOW			4	/* Too many RLMT mc addresses. */
+-
+-/* Promiscuous mode bits ----- */
+-
+-#define SK_PROM_MODE_NONE			0	/* Normal receive. */
+-#define SK_PROM_MODE_LLC			1	/* Receive all LLC frames. */
+-#define SK_PROM_MODE_ALL_MC			2	/* Receive all multicast frames. */
+-/* #define SK_PROM_MODE_NON_LLC		4 */	/* Receive all non-LLC frames. */
+-
+-/* Macros */
+-
+-#ifdef OLD_STUFF
+-#ifndef SK_ADDR_EQUAL
+-/*
+- * "&" instead of "&&" allows better optimization on IA-64.
+- * The replacement is safe here, as all bytes exist.
+- */
+-#ifndef SK_ADDR_DWORD_COMPARE
+-#define SK_ADDR_EQUAL(A1,A2)	( \
+-	(((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \
+-	(((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \
+-	(((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \
+-	(((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \
+-	(((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \
+-	(((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0]))
+-#else	/* SK_ADDR_DWORD_COMPARE */
+-#define SK_ADDR_EQUAL(A1,A2)	( \
+-	(*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \
+-	(*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0])))
+-#endif	/* SK_ADDR_DWORD_COMPARE */
+-#endif	/* SK_ADDR_EQUAL */
+-#endif /* 0 */
+-
+-#ifndef SK_ADDR_EQUAL
+-#ifndef SK_ADDR_DWORD_COMPARE
+-#define SK_ADDR_EQUAL(A1,A2)	( \
+-	(((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \
+-	(((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \
+-	(((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \
+-	(((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \
+-	(((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \
+-	(((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0]))
+-#else	/* SK_ADDR_DWORD_COMPARE */
+-#define SK_ADDR_EQUAL(A1,A2)	( \
+-	(*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \
+-	*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \
+-	(*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \
+-	*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0])))
+-#endif	/* SK_ADDR_DWORD_COMPARE */
+-#endif	/* SK_ADDR_EQUAL */
+-
+-/* typedefs *******************************************************************/
+-
+-typedef struct s_MacAddr {
+-	SK_U8	a[SK_MAC_ADDR_LEN];
+-} SK_MAC_ADDR;
+-
+-
+-/* SK_FILTER is used to ensure alignment of the filter. */
+-typedef union s_InexactFilter {
+-	SK_U8	Bytes[8];
+-	SK_U64	Val;	/* Dummy entry for alignment only. */
+-} SK_FILTER64;
+-
+-
+-typedef struct s_AddrNet SK_ADDR_NET;
+-
+-
+-typedef struct s_AddrPort {
+-
+-/* ----- Public part (read-only) ----- */
+-
+-	SK_MAC_ADDR	CurrentMacAddress;	/* Current physical MAC Address. */
+-	SK_MAC_ADDR	PermanentMacAddress;	/* Permanent physical MAC Address. */
+-	int		PromMode;		/* Promiscuous Mode. */
+-
+-/* ----- Private part ----- */
+-
+-	SK_MAC_ADDR	PreviousMacAddress;	/* Prev. phys. MAC Address. */
+-	SK_BOOL		CurrentMacAddressSet;	/* CurrentMacAddress is set. */
+-	SK_U8		Align01;
+-
+-	SK_U32		FirstExactMatchRlmt;
+-	SK_U32		NextExactMatchRlmt;
+-	SK_U32		FirstExactMatchDrv;
+-	SK_U32		NextExactMatchDrv;
+-	SK_MAC_ADDR	Exact[SK_ADDR_EXACT_MATCHES];
+-	SK_FILTER64	InexactFilter;			/* For 64-bit hash register. */
+-	SK_FILTER64	InexactRlmtFilter;		/* For 64-bit hash register. */
+-	SK_FILTER64	InexactDrvFilter;		/* For 64-bit hash register. */
+-} SK_ADDR_PORT;
+-
+-
+-struct s_AddrNet {
+-/* ----- Public part (read-only) ----- */
+-
+-	SK_MAC_ADDR		CurrentMacAddress;	/* Logical MAC Address. */
+-	SK_MAC_ADDR		PermanentMacAddress;	/* Logical MAC Address. */
+-
+-/* ----- Private part ----- */
+-
+-	SK_U32			ActivePort;		/* View of module ADDR. */
+-	SK_BOOL			CurrentMacAddressSet;	/* CurrentMacAddress is set. */
+-	SK_U8			Align01;
+-	SK_U16			Align02;
+-};
+-
+-
+-typedef struct s_Addr {
+-
+-/* ----- Public part (read-only) ----- */
+-
+-	SK_ADDR_NET		Net[SK_MAX_NETS];
+-	SK_ADDR_PORT	Port[SK_MAX_MACS];
+-
+-/* ----- Private part ----- */
+-} SK_ADDR;
+-
+-/* function prototypes ********************************************************/
+-
+-#ifndef SK_KR_PROTO
+-
+-/* Functions provided by SkAddr */
+-
+-/* ANSI/C++ compliant function prototypes */
+-
+-extern	int	SkAddrInit(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int	Level);
+-
+-extern	int	SkAddrMcClear(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	SK_U32	PortNumber,
+-	int	Flags);
+-
+-extern	int	SkAddrMcAdd(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	SK_U32		PortNumber,
+-	SK_MAC_ADDR	*pMc,
+-	int		Flags);
+-
+-extern	int	SkAddrMcUpdate(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	SK_U32	PortNumber);
+-
+-extern	int	SkAddrOverride(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	SK_U32		PortNumber,
+-	SK_MAC_ADDR	SK_FAR *pNewAddr,
+-	int		Flags);
+-
+-extern	int	SkAddrPromiscuousChange(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	SK_U32	PortNumber,
+-	int	NewPromMode);
+-
+-#ifndef SK_SLIM
+-extern	int	SkAddrSwap(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	SK_U32	FromPortNumber,
+-	SK_U32	ToPortNumber);
+-#endif
+-
+-#else	/* defined(SK_KR_PROTO)) */
+-
+-/* Non-ANSI/C++ compliant function prototypes */
+-
+-#error KR-style prototypes are not yet provided.
+-
+-#endif	/* defined(SK_KR_PROTO)) */
+-
+-
+-#ifdef __cplusplus
+-}
+-#endif	/* __cplusplus */
+-
+-#endif	/* __INC_SKADDR_H */
+diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h
+deleted file mode 100644
+index 6e256bd..0000000
+--- a/drivers/net/sk98lin/h/skcsum.h
++++ /dev/null
+@@ -1,213 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skcsum.h
+- * Project:	GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
+- * Version:	$Revision: 1.10 $
+- * Date:	$Date: 2003/08/20 13:59:57 $
+- * Purpose:	Store/verify Internet checksum in send/receive packets.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2001 SysKonnect GmbH.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * Public header file for the "GEnesis" common module "CSUM".
+- *
+- * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
+- * and is the code name of this SysKonnect project.
+- *
+- * Compilation Options:
+- *
+- *	SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
+- *	empty module.
+- *
+- *	SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
+- *	definitions. In this case, all SKCS_PROTO_xxx definitions must be made
+- *	external.
+- *
+- *	SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
+- *	definitions. In this case, all SKCS_STATUS_xxx definitions must be made
+- *	external.
+- *
+- * Include File Hierarchy:
+- *
+- *	"h/skcsum.h"
+- *	 "h/sktypes.h"
+- *	 "h/skqueue.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKCSUM_H
+-#define __INC_SKCSUM_H
+-
+-#include "h/sktypes.h"
+-#include "h/skqueue.h"
+-
+-/* defines ********************************************************************/
+-
+-/*
+- * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags'  if no user
+- * overwrite.
+- */
+-#ifndef SKCS_OVERWRITE_PROTO	/* User overwrite? */
+-#define SKCS_PROTO_IP	0x1	/* IP (Internet Protocol version 4) */
+-#define SKCS_PROTO_TCP	0x2	/* TCP (Transmission Control Protocol) */
+-#define SKCS_PROTO_UDP	0x4	/* UDP (User Datagram Protocol) */
+-
+-/* Indices for protocol statistics. */
+-#define SKCS_PROTO_STATS_IP	0
+-#define SKCS_PROTO_STATS_UDP	1
+-#define SKCS_PROTO_STATS_TCP	2
+-#define SKCS_NUM_PROTOCOLS	3	/* Number of supported protocols. */
+-#endif	/* !SKCS_OVERWRITE_PROTO */
+-
+-/*
+- * Define the default SKCS_STATUS type and values if no user overwrite.
+- *
+- *	SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
+- *	SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
+- *	SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
+- *	SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
+- *	SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
+- *	SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
+- *	SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
+- *	SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
+- *	SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
+- *	SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
+- *	SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. 
+- */
+-#ifndef SKCS_OVERWRITE_STATUS	/* User overwrite? */
+-#define SKCS_STATUS	int	/* Define status type. */
+-
+-#define SKCS_STATUS_UNKNOWN_IP_VERSION	1
+-#define SKCS_STATUS_IP_CSUM_ERROR		2
+-#define SKCS_STATUS_IP_FRAGMENT			3
+-#define SKCS_STATUS_IP_CSUM_OK			4
+-#define SKCS_STATUS_TCP_CSUM_ERROR		5
+-#define SKCS_STATUS_UDP_CSUM_ERROR		6
+-#define SKCS_STATUS_TCP_CSUM_OK			7
+-#define SKCS_STATUS_UDP_CSUM_OK			8
+-/* needed for Microsoft */
+-#define SKCS_STATUS_IP_CSUM_ERROR_UDP	9
+-#define SKCS_STATUS_IP_CSUM_ERROR_TCP	10
+-/* UDP checksum may be omitted */
+-#define SKCS_STATUS_IP_CSUM_OK_NO_UDP	11
+-#endif	/* !SKCS_OVERWRITE_STATUS */
+-
+-/* Clear protocol statistics event. */
+-#define SK_CSUM_EVENT_CLEAR_PROTO_STATS	1
+-
+-/*
+- * Add two values in one's complement.
+- *
+- * Note: One of the two input values may be "longer" than 16-bit, but then the
+- * resulting sum may be 17 bits long. In this case, add zero to the result using
+- * SKCS_OC_ADD() again.
+- *
+- *	Result = Value1 + Value2
+- */
+-#define SKCS_OC_ADD(Result, Value1, Value2) {				\
+-	unsigned long Sum;						\
+-									\
+-	Sum = (unsigned long) (Value1) + (unsigned long) (Value2);	\
+-	/* Add-in any carry. */						\
+-	(Result) = (Sum & 0xffff) + (Sum >> 16);			\
+-}
+-
+-/*
+- * Subtract two values in one's complement.
+- *
+- *	Result = Value1 - Value2
+- */
+-#define SKCS_OC_SUB(Result, Value1, Value2)	\
+-	SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff)
+-
+-/* typedefs *******************************************************************/
+-
+-/*
+- * SKCS_PROTO_STATS - The CSUM protocol statistics structure.
+- *
+- * There is one instance of this structure for each protocol supported.
+- */
+-typedef struct s_CsProtocolStatistics {
+-	SK_U64 RxOkCts;		/* Receive checksum ok. */
+-	SK_U64 RxUnableCts;	/* Unable to verify receive checksum. */
+-	SK_U64 RxErrCts;	/* Receive checksum error. */
+-	SK_U64 TxOkCts;		/* Transmit checksum ok. */
+-	SK_U64 TxUnableCts;	/* Unable to calculate checksum in hw. */
+-} SKCS_PROTO_STATS;
+-
+-/*
+- * s_Csum - The CSUM module context structure.
+- */
+-typedef struct s_Csum {
+-	/* Enabled receive SK_PROTO_XXX bit flags. */
+-	unsigned ReceiveFlags[SK_MAX_NETS];
+-#ifdef TX_CSUM
+-	unsigned TransmitFlags[SK_MAX_NETS];
+-#endif /* TX_CSUM */
+-
+-	/* The protocol statistics structure; one per supported protocol. */
+-	SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS];
+-} SK_CSUM;
+-
+-/*
+- * SKCS_PACKET_INFO - The packet information structure.
+- */
+-typedef struct s_CsPacketInfo {
+-	/* Bit field specifiying the desired/found protocols. */
+-	unsigned ProtocolFlags;
+-
+-	/* Length of complete IP header, including any option fields. */
+-	unsigned IpHeaderLength;
+-
+-	/* IP header checksum. */
+-	unsigned IpHeaderChecksum;
+-
+-	/* TCP/UDP pseudo header checksum. */
+-	unsigned PseudoHeaderChecksum;
+-} SKCS_PACKET_INFO;
+-
+-/* function prototypes ********************************************************/
+-
+-#ifndef SK_CS_CALCULATE_CHECKSUM
+-extern unsigned SkCsCalculateChecksum(
+-	void		*pData,
+-	unsigned	Length);
+-#endif /* SK_CS_CALCULATE_CHECKSUM */
+-
+-extern int SkCsEvent(
+-	SK_AC		*pAc,
+-	SK_IOC		Ioc,
+-	SK_U32		Event,
+-	SK_EVPARA	Param);
+-
+-extern SKCS_STATUS SkCsGetReceiveInfo(
+-	SK_AC		*pAc,
+-	void		*pIpHeader,
+-	unsigned	Checksum1,
+-	unsigned	Checksum2,
+-	int			NetNumber);
+-
+-extern void SkCsSetReceiveFlags(
+-	SK_AC		*pAc,
+-	unsigned	ReceiveFlags,
+-	unsigned	*pChecksum1Offset,
+-	unsigned	*pChecksum2Offset,
+-	int			NetNumber);
+-
+-#endif	/* __INC_SKCSUM_H */
+diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h
+deleted file mode 100644
+index 3cba171..0000000
+--- a/drivers/net/sk98lin/h/skdebug.h
++++ /dev/null
+@@ -1,74 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skdebug.h
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.14 $
+- * Date:	$Date: 2003/05/13 17:26:00 $
+- * Purpose:	SK specific DEBUG support
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKDEBUG_H
+-#define __INC_SKDEBUG_H
+-
+-#ifdef	DEBUG
+-#ifndef SK_DBG_MSG
+-#define SK_DBG_MSG(pAC,comp,cat,arg) \
+-		if ( ((comp) & SK_DBG_CHKMOD(pAC)) && 	\
+-		      ((cat) & SK_DBG_CHKCAT(pAC)) ) { 	\
+-			SK_DBG_PRINTF arg ;		\
+-		}
+-#endif
+-#else
+-#define SK_DBG_MSG(pAC,comp,lev,arg)
+-#endif
+-
+-/* PLS NOTE:
+- * =========
+- * Due to any restrictions of kernel printf routines do not use other
+- * format identifiers as: %x %d %c %s .
+- * Never use any combined format identifiers such as: %lx %ld in your
+- * printf - argument (arg) because some OS specific kernel printfs may
+- * only support some basic identifiers.
+- */
+-
+-/* Debug modules */
+-
+-#define SK_DBGMOD_MERR	0x00000001L	/* general module error indication */
+-#define SK_DBGMOD_HWM	0x00000002L	/* Hardware init module */
+-#define SK_DBGMOD_RLMT	0x00000004L	/* RLMT module */
+-#define SK_DBGMOD_VPD	0x00000008L	/* VPD module */
+-#define SK_DBGMOD_I2C	0x00000010L	/* I2C module */
+-#define SK_DBGMOD_PNMI	0x00000020L	/* PNMI module */
+-#define SK_DBGMOD_CSUM	0x00000040L	/* CSUM module */
+-#define SK_DBGMOD_ADDR	0x00000080L	/* ADDR module */
+-#define SK_DBGMOD_PECP	0x00000100L	/* PECP module */
+-#define SK_DBGMOD_POWM	0x00000200L	/* Power Management module */
+-
+-/* Debug events */
+-
+-#define SK_DBGCAT_INIT	0x00000001L	/* module/driver initialization */
+-#define SK_DBGCAT_CTRL	0x00000002L	/* controlling devices */
+-#define SK_DBGCAT_ERR	0x00000004L	/* error handling paths */
+-#define SK_DBGCAT_TX	0x00000008L	/* transmit path */
+-#define SK_DBGCAT_RX	0x00000010L	/* receive path */
+-#define SK_DBGCAT_IRQ	0x00000020L	/* general IRQ handling */
+-#define SK_DBGCAT_QUEUE	0x00000040L	/* any queue management */
+-#define SK_DBGCAT_DUMP	0x00000080L	/* large data output e.g. hex dump */
+-#define SK_DBGCAT_FATAL	0x00000100L	/* fatal error */
+-
+-#endif	/* __INC_SKDEBUG_H */
+diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
+deleted file mode 100644
+index 91b8d4f..0000000
+--- a/drivers/net/sk98lin/h/skdrv1st.h
++++ /dev/null
+@@ -1,188 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skdrv1st.h
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.4 $
+- * Date:	$Date: 2003/11/12 14:28:14 $
+- * Purpose:	First header file for driver and all other modules
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This is the first include file of the driver, which includes all
+- * neccessary system header files and some of the GEnesis header files.
+- * It also defines some basic items.
+- *
+- * Include File Hierarchy:
+- *
+- *	see skge.c
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKDRV1ST_H
+-#define __INC_SKDRV1ST_H
+-
+-typedef struct s_AC	SK_AC;
+-
+-/* Set card versions */
+-#define SK_FAR
+-
+-/* override some default functions with optimized linux functions */
+-
+-#define SK_PNMI_STORE_U16(p,v)		memcpy((char*)(p),(char*)&(v),2)
+-#define SK_PNMI_STORE_U32(p,v)		memcpy((char*)(p),(char*)&(v),4)
+-#define SK_PNMI_STORE_U64(p,v)		memcpy((char*)(p),(char*)&(v),8)
+-#define SK_PNMI_READ_U16(p,v)		memcpy((char*)&(v),(char*)(p),2)
+-#define SK_PNMI_READ_U32(p,v)		memcpy((char*)&(v),(char*)(p),4)
+-#define SK_PNMI_READ_U64(p,v)		memcpy((char*)&(v),(char*)(p),8)
+-
+-#define SK_ADDR_EQUAL(a1,a2)		(!memcmp(a1,a2,6))
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/ioport.h>
+-#include <linux/slab.h>
+-#include <linux/interrupt.h>
+-#include <linux/pci.h>
+-#include <linux/bitops.h>
+-#include <asm/byteorder.h>
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/skbuff.h>
+-
+-#include <linux/init.h>
+-#include <asm/uaccess.h>
+-#include <net/checksum.h>
+-
+-#define SK_CS_CALCULATE_CHECKSUM
+-#ifndef CONFIG_X86_64
+-#define SkCsCalculateChecksum(p,l)	((~ip_compute_csum(p, l)) & 0xffff)
+-#else
+-#define SkCsCalculateChecksum(p,l)	((~ip_fast_csum(p, l)) & 0xffff)
+-#endif
+-
+-#include	"h/sktypes.h"
+-#include	"h/skerror.h"
+-#include	"h/skdebug.h"
+-#include	"h/lm80.h"
+-#include	"h/xmac_ii.h"
+-
+-#ifdef __LITTLE_ENDIAN
+-#define SK_LITTLE_ENDIAN
+-#else
+-#define SK_BIG_ENDIAN
+-#endif
+-
+-#define SK_NET_DEVICE	net_device
+-
+-
+-/* we use gethrtime(), return unit: nanoseconds */
+-#define SK_TICKS_PER_SEC	100
+-
+-#define	SK_MEM_MAPPED_IO
+-
+-// #define SK_RLMT_SLOW_LOOKAHEAD
+-
+-#define SK_MAX_MACS		2
+-#define SK_MAX_NETS		2
+-
+-#define SK_IOC			char __iomem *
+-
+-typedef struct s_DrvRlmtMbuf SK_MBUF;
+-
+-#define	SK_CONST64	INT64_C
+-#define	SK_CONSTU64	UINT64_C
+-
+-#define SK_MEMCPY(dest,src,size)	memcpy(dest,src,size)
+-#define SK_MEMCMP(s1,s2,size)		memcmp(s1,s2,size)
+-#define SK_MEMSET(dest,val,size)	memset(dest,val,size)
+-#define SK_STRLEN(pStr)			strlen((char*)(pStr))
+-#define SK_STRNCPY(pDest,pSrc,size)	strncpy((char*)(pDest),(char*)(pSrc),size)
+-#define SK_STRCMP(pStr1,pStr2)		strcmp((char*)(pStr1),(char*)(pStr2))
+-
+-/* macros to access the adapter */
+-#define SK_OUT8(b,a,v)		writeb((v), ((b)+(a)))	
+-#define SK_OUT16(b,a,v)		writew((v), ((b)+(a)))	
+-#define SK_OUT32(b,a,v)		writel((v), ((b)+(a)))	
+-#define SK_IN8(b,a,pv)		(*(pv) = readb((b)+(a)))
+-#define SK_IN16(b,a,pv)		(*(pv) = readw((b)+(a)))
+-#define SK_IN32(b,a,pv)		(*(pv) = readl((b)+(a)))
+-
+-#define int8_t		char
+-#define int16_t		short
+-#define int32_t		long
+-#define int64_t		long long
+-#define uint8_t		u_char
+-#define uint16_t	u_short
+-#define uint32_t	u_long
+-#define uint64_t	unsigned long long
+-#define t_scalar_t	int
+-#define t_uscalar_t	unsigned int
+-#define uintptr_t	unsigned long
+-
+-#define __CONCAT__(A,B) A##B
+-
+-#define INT32_C(a)		__CONCAT__(a,L)
+-#define INT64_C(a)		__CONCAT__(a,LL)
+-#define UINT32_C(a)		__CONCAT__(a,UL)
+-#define UINT64_C(a)		__CONCAT__(a,ULL)
+-
+-#ifdef DEBUG
+-#define SK_DBG_PRINTF		printk
+-#ifndef SK_DEBUG_CHKMOD
+-#define SK_DEBUG_CHKMOD		0
+-#endif
+-#ifndef SK_DEBUG_CHKCAT
+-#define SK_DEBUG_CHKCAT		0
+-#endif
+-/* those come from the makefile */
+-#define SK_DBG_CHKMOD(pAC)	(SK_DEBUG_CHKMOD)
+-#define SK_DBG_CHKCAT(pAC)	(SK_DEBUG_CHKCAT)
+-
+-extern void SkDbgPrintf(const char *format,...);
+-
+-#define SK_DBGMOD_DRV			0x00010000
+-
+-/**** possible driver debug categories ********************************/
+-#define SK_DBGCAT_DRV_ENTRY		0x00010000
+-#define SK_DBGCAT_DRV_SAP		0x00020000
+-#define SK_DBGCAT_DRV_MCA		0x00040000
+-#define SK_DBGCAT_DRV_TX_PROGRESS	0x00080000
+-#define SK_DBGCAT_DRV_RX_PROGRESS	0x00100000
+-#define SK_DBGCAT_DRV_PROGRESS		0x00200000
+-#define SK_DBGCAT_DRV_MSG		0x00400000
+-#define SK_DBGCAT_DRV_PROM		0x00800000
+-#define SK_DBGCAT_DRV_TX_FRAME		0x01000000
+-#define SK_DBGCAT_DRV_ERROR		0x02000000
+-#define SK_DBGCAT_DRV_INT_SRC		0x04000000
+-#define SK_DBGCAT_DRV_EVENT		0x08000000
+-
+-#endif
+-
+-#define SK_ERR_LOG		SkErrorLog
+-
+-extern void SkErrorLog(SK_AC*, int, int, char*);
+-
+-#endif
+-
+diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
+deleted file mode 100644
+index 3fa6717..0000000
+--- a/drivers/net/sk98lin/h/skdrv2nd.h
++++ /dev/null
+@@ -1,447 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skdrv2nd.h
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.10 $
+- * Date:	$Date: 2003/12/11 16:04:45 $
+- * Purpose:	Second header file for driver and all other modules
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This is the second include file of the driver, which includes all other
+- * neccessary files and defines all structures and constants used by the
+- * driver and the common modules.
+- *
+- * Include File Hierarchy:
+- *
+- *	see skge.c
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKDRV2ND_H
+-#define __INC_SKDRV2ND_H
+-
+-#include "h/skqueue.h"
+-#include "h/skgehwt.h"
+-#include "h/sktimer.h"
+-#include "h/ski2c.h"
+-#include "h/skgepnmi.h"
+-#include "h/skvpd.h"
+-#include "h/skgehw.h"
+-#include "h/skgeinit.h"
+-#include "h/skaddr.h"
+-#include "h/skgesirq.h"
+-#include "h/skcsum.h"
+-#include "h/skrlmt.h"
+-#include "h/skgedrv.h"
+-
+-
+-extern SK_MBUF		*SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
+-extern void		SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
+-extern SK_U64		SkOsGetTime(SK_AC*);
+-extern int		SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
+-extern int		SkPciReadCfgWord(SK_AC*, int, SK_U16*);
+-extern int		SkPciReadCfgByte(SK_AC*, int, SK_U8*);
+-extern int		SkPciWriteCfgWord(SK_AC*, int, SK_U16);
+-extern int		SkPciWriteCfgByte(SK_AC*, int, SK_U8);
+-extern int		SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
+-
+-#ifdef SK_DIAG_SUPPORT
+-extern int		SkDrvEnterDiagMode(SK_AC *pAc);
+-extern int		SkDrvLeaveDiagMode(SK_AC *pAc);
+-#endif
+-
+-struct s_DrvRlmtMbuf {
+-	SK_MBUF		*pNext;		/* Pointer to next RLMT Mbuf. */
+-	SK_U8		*pData;		/* Data buffer (virtually contig.). */
+-	unsigned	Size;		/* Data buffer size. */
+-	unsigned	Length;		/* Length of packet (<= Size). */
+-	SK_U32		PortIdx;	/* Receiving/transmitting port. */
+-#ifdef SK_RLMT_MBUF_PRIVATE
+-	SK_RLMT_MBUF	Rlmt;		/* Private part for RLMT. */
+-#endif  /* SK_RLMT_MBUF_PRIVATE */
+-	struct sk_buff	*pOs;		/* Pointer to message block */
+-};
+-
+-
+-/*
+- * Time macros
+- */
+-#if SK_TICKS_PER_SEC == 100
+-#define SK_PNMI_HUNDREDS_SEC(t)	(t)
+-#else
+-#define SK_PNMI_HUNDREDS_SEC(t)	((((unsigned long)t) * 100) / \
+-										(SK_TICKS_PER_SEC))
+-#endif
+-
+-/*
+- * New SkOsGetTime
+- */
+-#define SkOsGetTimeCurrent(pAC, pUsec) {\
+-	struct timeval t;\
+-	do_gettimeofday(&t);\
+-	*pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\
+-}
+-
+-
+-/*
+- * ioctl definitions
+- */
+-#define		SK_IOCTL_BASE		(SIOCDEVPRIVATE)
+-#define		SK_IOCTL_GETMIB		(SK_IOCTL_BASE + 0)
+-#define		SK_IOCTL_SETMIB		(SK_IOCTL_BASE + 1)
+-#define		SK_IOCTL_PRESETMIB	(SK_IOCTL_BASE + 2)
+-#define		SK_IOCTL_GEN		(SK_IOCTL_BASE + 3)
+-#define		SK_IOCTL_DIAG		(SK_IOCTL_BASE + 4)
+-
+-typedef struct s_IOCTL	SK_GE_IOCTL;
+-
+-struct s_IOCTL {
+-	char __user *	pData;
+-	unsigned int	Len;
+-};
+-
+-
+-/*
+- * define sizes of descriptor rings in bytes
+- */
+-
+-#define		TX_RING_SIZE	(8*1024)
+-#define		RX_RING_SIZE	(24*1024)
+-
+-/*
+- * Buffer size for ethernet packets
+- */
+-#define	ETH_BUF_SIZE	1540
+-#define	ETH_MAX_MTU	1514
+-#define ETH_MIN_MTU	60
+-#define ETH_MULTICAST_BIT	0x01
+-#define SK_JUMBO_MTU	9000
+-
+-/*
+- * transmit priority selects the queue: LOW=asynchron, HIGH=synchron
+- */
+-#define TX_PRIO_LOW	0
+-#define TX_PRIO_HIGH	1
+-
+-/*
+- * alignment of rx/tx descriptors
+- */
+-#define DESCR_ALIGN	64
+-
+-/*
+- * definitions for pnmi. TODO
+- */
+-#define SK_DRIVER_RESET(pAC, IoC)	0
+-#define SK_DRIVER_SENDEVENT(pAC, IoC)	0
+-#define SK_DRIVER_SELFTEST(pAC, IoC)	0
+-/* For get mtu you must add an own function */
+-#define SK_DRIVER_GET_MTU(pAc,IoC,i)	0
+-#define SK_DRIVER_SET_MTU(pAc,IoC,i,v)	0
+-#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v)	0
+-
+-/*
+-** Interim definition of SK_DRV_TIMER placed in this file until 
+-** common modules have been finalized
+-*/
+-#define SK_DRV_TIMER			11 
+-#define	SK_DRV_MODERATION_TIMER		1
+-#define SK_DRV_MODERATION_TIMER_LENGTH  1000000  /* 1 second */
+-#define SK_DRV_RX_CLEANUP_TIMER		2
+-#define SK_DRV_RX_CLEANUP_TIMER_LENGTH	1000000	 /* 100 millisecs */
+-
+-/*
+-** Definitions regarding transmitting frames 
+-** any calculating any checksum.
+-*/
+-#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6
+-#define C_LEN_ETHERMAC_HEADER_SRC_ADDR  6
+-#define C_LEN_ETHERMAC_HEADER_LENTYPE   2
+-#define C_LEN_ETHERMAC_HEADER           ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \
+-                                          (C_LEN_ETHERMAC_HEADER_SRC_ADDR)  + \
+-                                          (C_LEN_ETHERMAC_HEADER_LENTYPE) )
+-
+-#define C_LEN_ETHERMTU_MINSIZE          46
+-#define C_LEN_ETHERMTU_MAXSIZE_STD      1500
+-#define C_LEN_ETHERMTU_MAXSIZE_JUMBO    9000
+-
+-#define C_LEN_ETHERNET_MINSIZE          ( (C_LEN_ETHERMAC_HEADER) + \
+-                                          (C_LEN_ETHERMTU_MINSIZE) )
+-
+-#define C_OFFSET_IPHEADER               C_LEN_ETHERMAC_HEADER
+-#define C_OFFSET_IPHEADER_IPPROTO       9
+-#define C_OFFSET_TCPHEADER_TCPCS        16
+-#define C_OFFSET_UDPHEADER_UDPCS        6
+-
+-#define C_OFFSET_IPPROTO                ( (C_LEN_ETHERMAC_HEADER) + \
+-                                          (C_OFFSET_IPHEADER_IPPROTO) )
+-
+-#define C_PROTO_ID_UDP                  17       /* refer to RFC 790 or Stevens'   */
+-#define C_PROTO_ID_TCP                  6        /* TCP/IP illustrated for details */
+-
+-/* TX and RX descriptors *****************************************************/
+-
+-typedef struct s_RxD RXD; /* the receive descriptor */
+-
+-struct s_RxD {
+-	volatile SK_U32	RBControl;	/* Receive Buffer Control */
+-	SK_U32		VNextRxd;	/* Next receive descriptor,low dword */
+-	SK_U32		VDataLow;	/* Receive buffer Addr, low dword */
+-	SK_U32		VDataHigh;	/* Receive buffer Addr, high dword */
+-	SK_U32		FrameStat;	/* Receive Frame Status word */
+-	SK_U32		TimeStamp;	/* Time stamp from XMAC */
+-	SK_U32		TcpSums;	/* TCP Sum 2 / TCP Sum 1 */
+-	SK_U32		TcpSumStarts;	/* TCP Sum Start 2 / TCP Sum Start 1 */
+-	RXD		*pNextRxd;	/* Pointer to next Rxd */
+-	struct sk_buff	*pMBuf;		/* Pointer to Linux' socket buffer */
+-};
+-
+-typedef struct s_TxD TXD; /* the transmit descriptor */
+-
+-struct s_TxD {
+-	volatile SK_U32	TBControl;	/* Transmit Buffer Control */
+-	SK_U32		VNextTxd;	/* Next transmit descriptor,low dword */
+-	SK_U32		VDataLow;	/* Transmit Buffer Addr, low dword */
+-	SK_U32		VDataHigh;	/* Transmit Buffer Addr, high dword */
+-	SK_U32		FrameStat;	/* Transmit Frame Status Word */
+-	SK_U32		TcpSumOfs;	/* Reserved / TCP Sum Offset */
+-	SK_U16		TcpSumSt;	/* TCP Sum Start */
+-	SK_U16		TcpSumWr;	/* TCP Sum Write */
+-	SK_U32		TcpReserved;	/* not used */
+-	TXD		*pNextTxd;	/* Pointer to next Txd */
+-	struct sk_buff	*pMBuf;		/* Pointer to Linux' socket buffer */
+-};
+-
+-/* Used interrupt bits in the interrupts source register *********************/
+-
+-#define DRIVER_IRQS	((IS_IRQ_SW)   | \
+-			(IS_R1_F)      |(IS_R2_F)  | \
+-			(IS_XS1_F)     |(IS_XA1_F) | \
+-			(IS_XS2_F)     |(IS_XA2_F))
+-
+-#define SPECIAL_IRQS	((IS_HW_ERR)   |(IS_I2C_READY)  | \
+-			(IS_EXT_REG)   |(IS_TIMINT)     | \
+-			(IS_PA_TO_RX1) |(IS_PA_TO_RX2)  | \
+-			(IS_PA_TO_TX1) |(IS_PA_TO_TX2)  | \
+-			(IS_MAC1)      |(IS_LNK_SYNC_M1)| \
+-			(IS_MAC2)      |(IS_LNK_SYNC_M2)| \
+-			(IS_R1_C)      |(IS_R2_C)       | \
+-			(IS_XS1_C)     |(IS_XA1_C)      | \
+-			(IS_XS2_C)     |(IS_XA2_C))
+-
+-#define IRQ_MASK	((IS_IRQ_SW)   | \
+-			(IS_R1_B)      |(IS_R1_F)     |(IS_R2_B) |(IS_R2_F) | \
+-			(IS_XS1_B)     |(IS_XS1_F)    |(IS_XA1_B)|(IS_XA1_F)| \
+-			(IS_XS2_B)     |(IS_XS2_F)    |(IS_XA2_B)|(IS_XA2_F)| \
+-			(IS_HW_ERR)    |(IS_I2C_READY)| \
+-			(IS_EXT_REG)   |(IS_TIMINT)   | \
+-			(IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
+-			(IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
+-			(IS_MAC1)      |(IS_MAC2)     | \
+-			(IS_R1_C)      |(IS_R2_C)     | \
+-			(IS_XS1_C)     |(IS_XA1_C)    | \
+-			(IS_XS2_C)     |(IS_XA2_C))
+-
+-#define IRQ_HWE_MASK	(IS_ERR_MSK) /* enable all HW irqs */
+-
+-typedef struct s_DevNet DEV_NET;
+-
+-struct s_DevNet {
+-	int             PortNr;
+-	int             NetNr;
+-	SK_AC   *pAC;
+-};  
+-
+-typedef struct s_TxPort		TX_PORT;
+-
+-struct s_TxPort {
+-	/* the transmit descriptor rings */
+-	caddr_t		pTxDescrRing;	/* descriptor area memory */
+-	SK_U64		VTxDescrRing;	/* descr. area bus virt. addr. */
+-	TXD		*pTxdRingHead;	/* Head of Tx rings */
+-	TXD		*pTxdRingTail;	/* Tail of Tx rings */
+-	TXD		*pTxdRingPrev;	/* descriptor sent previously */
+-	int		TxdRingFree;	/* # of free entrys */
+-	spinlock_t	TxDesRingLock;	/* serialize descriptor accesses */
+-	SK_IOC		HwAddr;		/* bmu registers address */
+-	int		PortIndex;	/* index number of port (0 or 1) */
+-};
+-
+-typedef struct s_RxPort		RX_PORT;
+-
+-struct s_RxPort {
+-	/* the receive descriptor rings */
+-	caddr_t		pRxDescrRing;	/* descriptor area memory */
+-	SK_U64		VRxDescrRing;   /* descr. area bus virt. addr. */
+-	RXD		*pRxdRingHead;	/* Head of Rx rings */
+-	RXD		*pRxdRingTail;	/* Tail of Rx rings */
+-	RXD		*pRxdRingPrev;	/* descriptor given to BMU previously */
+-	int		RxdRingFree;	/* # of free entrys */
+-	int		RxCsum;		/* use receive checksum hardware */
+-	spinlock_t	RxDesRingLock;	/* serialize descriptor accesses */
+-	int		RxFillLimit;	/* limit for buffers in ring */
+-	SK_IOC		HwAddr;		/* bmu registers address */
+-	int		PortIndex;	/* index number of port (0 or 1) */
+-};
+-
+-/* Definitions needed for interrupt moderation *******************************/
+-
+-#define IRQ_EOF_AS_TX     ((IS_XA1_F)     | (IS_XA2_F))
+-#define IRQ_EOF_SY_TX     ((IS_XS1_F)     | (IS_XS2_F))
+-#define IRQ_MASK_TX_ONLY  ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX))
+-#define IRQ_MASK_RX_ONLY  ((IS_R1_F)      | (IS_R2_F))
+-#define IRQ_MASK_SP_ONLY  (SPECIAL_IRQS)
+-#define IRQ_MASK_TX_RX    ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
+-#define IRQ_MASK_SP_RX    ((SPECIAL_IRQS)    | (IRQ_MASK_RX_ONLY))
+-#define IRQ_MASK_SP_TX    ((SPECIAL_IRQS)    | (IRQ_MASK_TX_ONLY))
+-#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS)    | (IRQ_MASK_TX_RX))
+-
+-#define C_INT_MOD_NONE                 1
+-#define C_INT_MOD_STATIC               2
+-#define C_INT_MOD_DYNAMIC              4
+-
+-#define C_CLK_FREQ_GENESIS      53215000 /* shorter: 53.125 MHz  */
+-#define C_CLK_FREQ_YUKON        78215000 /* shorter: 78.125 MHz  */
+-
+-#define C_INTS_PER_SEC_DEFAULT      2000 
+-#define C_INT_MOD_ENABLE_PERCENTAGE   50 /* if higher 50% enable */
+-#define C_INT_MOD_DISABLE_PERCENTAGE  50 /* if lower 50% disable */
+-#define C_INT_MOD_IPS_LOWER_RANGE     30
+-#define C_INT_MOD_IPS_UPPER_RANGE     40000
+-
+-
+-typedef struct s_DynIrqModInfo  DIM_INFO;
+-struct s_DynIrqModInfo {
+-	unsigned long   PrevTimeVal;
+-	unsigned int    PrevSysLoad;
+-	unsigned int    PrevUsedTime;
+-	unsigned int    PrevTotalTime;
+-	int             PrevUsedDescrRatio;
+-	int             NbrProcessedDescr;
+-        SK_U64          PrevPort0RxIntrCts;
+-        SK_U64          PrevPort1RxIntrCts;
+-        SK_U64          PrevPort0TxIntrCts;
+-        SK_U64          PrevPort1TxIntrCts;
+-	SK_BOOL         ModJustEnabled;     /* Moderation just enabled yes/no */
+-
+-	int             MaxModIntsPerSec;            /* Moderation Threshold */
+-	int             MaxModIntsPerSecUpperLimit;  /* Upper limit for DIM  */
+-	int             MaxModIntsPerSecLowerLimit;  /* Lower limit for DIM  */
+-
+-	long            MaskIrqModeration;   /* ModIrqType (eg. 'TxRx')      */
+-	SK_BOOL         DisplayStats;        /* Stats yes/no                 */
+-	SK_BOOL         AutoSizing;          /* Resize DIM-timer on/off      */
+-	int             IntModTypeSelect;    /* EnableIntMod (eg. 'dynamic') */
+-
+-	SK_TIMER        ModTimer; /* just some timer */
+-};
+-
+-typedef struct s_PerStrm	PER_STRM;
+-
+-#define SK_ALLOC_IRQ	0x00000001
+-
+-#ifdef SK_DIAG_SUPPORT
+-#define	DIAG_ACTIVE		1
+-#define	DIAG_NOTACTIVE		0
+-#endif
+-
+-/****************************************************************************
+- * Per board structure / Adapter Context structure:
+- *	Allocated within attach(9e) and freed within detach(9e).
+- *	Contains all 'per device' necessary handles, flags, locks etc.:
+- */
+-struct s_AC  {
+-	SK_GEINIT	GIni;		/* GE init struct */
+-	SK_PNMI		Pnmi;		/* PNMI data struct */
+-	SK_VPD		vpd;		/* vpd data struct */
+-	SK_QUEUE	Event;		/* Event queue */
+-	SK_HWT		Hwt;		/* Hardware Timer control struct */
+-	SK_TIMCTRL	Tim;		/* Software Timer control struct */
+-	SK_I2C		I2c;		/* I2C relevant data structure */
+-	SK_ADDR		Addr;		/* for Address module */
+-	SK_CSUM		Csum;		/* for checksum module */
+-	SK_RLMT		Rlmt;		/* for rlmt module */
+-	spinlock_t	SlowPathLock;	/* Normal IRQ lock */
+-	struct timer_list BlinkTimer;	/* for LED blinking */
+-	int		LedsOn;
+-	SK_PNMI_STRUCT_DATA PnmiStruct;	/* structure to get all Pnmi-Data */
+-	int			RlmtMode;	/* link check mode to set */
+-	int			RlmtNets;	/* Number of nets */
+-	
+-	SK_IOC		IoBase;		/* register set of adapter */
+-	int		BoardLevel;	/* level of active hw init (0-2) */
+-
+-	SK_U32		AllocFlag;	/* flag allocation of resources */
+-	struct pci_dev	*PciDev;	/* for access to pci config space */
+-	struct SK_NET_DEVICE	*dev[2];	/* pointer to device struct */
+-
+-	int		RxBufSize;	/* length of receive buffers */
+-        struct net_device_stats stats;	/* linux 'netstat -i' statistics */
+-	int		Index;		/* internal board index number */
+-
+-	/* adapter RAM sizes for queues of active port */
+-	int		RxQueueSize;	/* memory used for receive queue */
+-	int		TxSQueueSize;	/* memory used for sync. tx queue */
+-	int		TxAQueueSize;	/* memory used for async. tx queue */
+-
+-	int		PromiscCount;	/* promiscuous mode counter  */
+-	int		AllMultiCount;  /* allmulticast mode counter */
+-	int		MulticCount;	/* number of different MC    */
+-					/*  addresses for this board */
+-					/*  (may be more than HW can)*/
+-
+-	int		HWRevision;	/* Hardware revision */
+-	int		ActivePort;	/* the active XMAC port */
+-	int		MaxPorts;		/* number of activated ports */
+-	int		TxDescrPerRing;	/* # of descriptors per tx ring */
+-	int		RxDescrPerRing;	/* # of descriptors per rx ring */
+-
+-	caddr_t		pDescrMem;	/* Pointer to the descriptor area */
+-	dma_addr_t	pDescrMemDMA;	/* PCI DMA address of area */
+-
+-	/* the port structures with descriptor rings */
+-	TX_PORT		TxPort[SK_MAX_MACS][2];
+-	RX_PORT		RxPort[SK_MAX_MACS];
+-
+-	SK_BOOL		CheckQueue;	/* check event queue soon */
+-	SK_TIMER        DrvCleanupTimer;/* to check for pending descriptors */
+-	DIM_INFO        DynIrqModInfo;  /* all data related to DIM */
+-
+-	/* Only for tests */
+-	int		PortDown;
+-	int		ChipsetType;	/*  Chipset family type 
+-					 *  0 == Genesis family support
+-					 *  1 == Yukon family support
+-					 */
+-#ifdef SK_DIAG_SUPPORT
+-	SK_U32		DiagModeActive;		/* is diag active?	*/
+-	SK_BOOL		DiagFlowCtrl;		/* for control purposes	*/
+-	SK_PNMI_STRUCT_DATA PnmiBackup;		/* backup structure for all Pnmi-Data */
+-	SK_BOOL         WasIfUp[SK_MAX_MACS];   /* for OpenClose while 
+-						 * DIAG is busy with NIC 
+-						 */
+-#endif
+-
+-};
+-
+-
+-#endif /* __INC_SKDRV2ND_H */
+-
+diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h
+deleted file mode 100644
+index da062f7..0000000
+--- a/drivers/net/sk98lin/h/skerror.h
++++ /dev/null
+@@ -1,55 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skerror.h
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.7 $
+- * Date:	$Date: 2003/05/13 17:25:13 $
+- * Purpose:	SK specific Error log support
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef _INC_SKERROR_H_
+-#define _INC_SKERROR_H_
+-
+-/*
+- * Define Error Classes
+- */
+-#define	SK_ERRCL_OTHER		(0)		/* Other error */
+-#define	SK_ERRCL_CONFIG		(1L<<0)	/* Configuration error */
+-#define	SK_ERRCL_INIT		(1L<<1)	/* Initialization error */
+-#define	SK_ERRCL_NORES		(1L<<2)	/* Out of Resources error */
+-#define	SK_ERRCL_SW			(1L<<3)	/* Internal Software error */
+-#define	SK_ERRCL_HW			(1L<<4)	/* Hardware Failure */
+-#define	SK_ERRCL_COMM		(1L<<5)	/* Communication error */
+-
+-
+-/*
+- * Define Error Code Bases
+- */
+-#define	SK_ERRBASE_RLMT		 100	/* Base Error number for RLMT */
+-#define	SK_ERRBASE_HWINIT	 200	/* Base Error number for HWInit */
+-#define	SK_ERRBASE_VPD		 300	/* Base Error number for VPD */
+-#define	SK_ERRBASE_PNMI		 400	/* Base Error number for PNMI */
+-#define	SK_ERRBASE_CSUM		 500	/* Base Error number for Checksum */
+-#define	SK_ERRBASE_SIRQ		 600	/* Base Error number for Special IRQ */
+-#define	SK_ERRBASE_I2C		 700	/* Base Error number for I2C module */
+-#define	SK_ERRBASE_QUEUE	 800	/* Base Error number for Scheduler */
+-#define	SK_ERRBASE_ADDR		 900	/* Base Error number for Address module */
+-#define SK_ERRBASE_PECP		1000    /* Base Error number for PECP */
+-#define	SK_ERRBASE_DRV		1100	/* Base Error number for Driver */
+-
+-#endif	/* _INC_SKERROR_H_ */
+diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h
+deleted file mode 100644
+index 44fd4c3..0000000
+--- a/drivers/net/sk98lin/h/skgedrv.h
++++ /dev/null
+@@ -1,51 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skgedrv.h
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.10 $
+- * Date:	$Date: 2003/07/04 12:25:01 $
+- * Purpose:	Interface with the driver
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKGEDRV_H_
+-#define __INC_SKGEDRV_H_
+-
+-/* defines ********************************************************************/
+-
+-/*
+- * Define the driver events.
+- * Usually the events are defined by the destination module.
+- * In case of the driver we put the definition of the events here.
+- */
+-#define SK_DRV_PORT_RESET		 1	/* The port needs to be reset */
+-#define SK_DRV_NET_UP   		 2	/* The net is operational */
+-#define SK_DRV_NET_DOWN			 3	/* The net is down */
+-#define SK_DRV_SWITCH_SOFT		 4	/* Ports switch with both links connected */
+-#define SK_DRV_SWITCH_HARD		 5	/* Port switch due to link failure */
+-#define SK_DRV_RLMT_SEND		 6	/* Send a RLMT packet */
+-#define SK_DRV_ADAP_FAIL		 7	/* The whole adapter fails */
+-#define SK_DRV_PORT_FAIL		 8	/* One port fails */
+-#define SK_DRV_SWITCH_INTERN	 9	/* Port switch by the driver itself */
+-#define SK_DRV_POWER_DOWN		10	/* Power down mode */
+-#define SK_DRV_TIMER			11	/* Timer for free use */
+-#ifdef SK_NO_RLMT
+-#define SK_DRV_LINK_UP  		12	/* Link Up event for driver */
+-#define SK_DRV_LINK_DOWN		13	/* Link Down event for driver */
+-#endif
+-#define SK_DRV_DOWNSHIFT_DET	14	/* Downshift 4-Pair / 2-Pair (YUKON only) */
+-#endif /* __INC_SKGEDRV_H_ */
+diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
+deleted file mode 100644
+index f6282b7..0000000
+--- a/drivers/net/sk98lin/h/skgehw.h
++++ /dev/null
+@@ -1,2126 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skgehw.h
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.56 $
+- * Date:	$Date: 2003/09/23 09:01:00 $
+- * Purpose:	Defines and Macros for the Gigabit Ethernet Adapter Product Family
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKGEHW_H
+-#define __INC_SKGEHW_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif	/* __cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-#define BIT_31		(1UL << 31)
+-#define BIT_30		(1L << 30)
+-#define BIT_29		(1L << 29)
+-#define BIT_28		(1L << 28)
+-#define BIT_27		(1L << 27)
+-#define BIT_26		(1L << 26)
+-#define BIT_25		(1L << 25)
+-#define BIT_24		(1L << 24)
+-#define BIT_23		(1L << 23)
+-#define BIT_22		(1L << 22)
+-#define BIT_21		(1L << 21)
+-#define BIT_20		(1L << 20)
+-#define BIT_19		(1L << 19)
+-#define BIT_18		(1L << 18)
+-#define BIT_17		(1L << 17)
+-#define BIT_16		(1L << 16)
+-#define BIT_15		(1L << 15)
+-#define BIT_14		(1L << 14)
+-#define BIT_13		(1L << 13)
+-#define BIT_12		(1L << 12)
+-#define BIT_11		(1L << 11)
+-#define BIT_10		(1L << 10)
+-#define BIT_9		(1L << 9)
+-#define BIT_8		(1L << 8)
+-#define BIT_7		(1L << 7)
+-#define BIT_6		(1L << 6)
+-#define BIT_5		(1L << 5)
+-#define BIT_4		(1L << 4)
+-#define BIT_3		(1L << 3)
+-#define BIT_2		(1L << 2)
+-#define BIT_1		(1L << 1)
+-#define BIT_0		1L
+-
+-#define BIT_15S		(1U << 15)
+-#define BIT_14S		(1 << 14)
+-#define BIT_13S		(1 << 13)
+-#define BIT_12S		(1 << 12)
+-#define BIT_11S		(1 << 11)
+-#define BIT_10S		(1 << 10)
+-#define BIT_9S		(1 << 9)
+-#define BIT_8S		(1 << 8)
+-#define BIT_7S 		(1 << 7)
+-#define BIT_6S		(1 << 6)
+-#define BIT_5S		(1 << 5)
+-#define BIT_4S		(1 << 4)
+-#define BIT_3S		(1 << 3)
+-#define BIT_2S		(1 << 2)
+-#define BIT_1S		(1 << 1)
+-#define BIT_0S		1
+-
+-#define SHIFT31(x)	((x) << 31)
+-#define SHIFT30(x)	((x) << 30)
+-#define SHIFT29(x)	((x) << 29)
+-#define SHIFT28(x)	((x) << 28)
+-#define SHIFT27(x)	((x) << 27)
+-#define SHIFT26(x)	((x) << 26)
+-#define SHIFT25(x)	((x) << 25)
+-#define SHIFT24(x)	((x) << 24)
+-#define SHIFT23(x)	((x) << 23)
+-#define SHIFT22(x)	((x) << 22)
+-#define SHIFT21(x)	((x) << 21)
+-#define SHIFT20(x)	((x) << 20)
+-#define SHIFT19(x)	((x) << 19)
+-#define SHIFT18(x)	((x) << 18)
+-#define SHIFT17(x)	((x) << 17)
+-#define SHIFT16(x)	((x) << 16)
+-#define SHIFT15(x)	((x) << 15)
+-#define SHIFT14(x)	((x) << 14)
+-#define SHIFT13(x)	((x) << 13)
+-#define SHIFT12(x)	((x) << 12)
+-#define SHIFT11(x)	((x) << 11)
+-#define SHIFT10(x)	((x) << 10)
+-#define SHIFT9(x)	((x) << 9)
+-#define SHIFT8(x)	((x) << 8)
+-#define SHIFT7(x)	((x) << 7)
+-#define SHIFT6(x)	((x) << 6)
+-#define SHIFT5(x)	((x) << 5)
+-#define SHIFT4(x)	((x) << 4)
+-#define SHIFT3(x)	((x) << 3)
+-#define SHIFT2(x)	((x) << 2)
+-#define SHIFT1(x)	((x) << 1)
+-#define SHIFT0(x)	((x) << 0)
+-
+-/*
+- * Configuration Space header
+- * Since this module is used for different OS', those may be
+- * duplicate on some of them (e.g. Linux). But to keep the
+- * common source, we have to live with this...
+- */
+-#define PCI_VENDOR_ID	0x00	/* 16 bit	Vendor ID */
+-#define PCI_DEVICE_ID	0x02	/* 16 bit	Device ID */
+-#define PCI_COMMAND		0x04	/* 16 bit	Command */
+-#define PCI_STATUS		0x06	/* 16 bit	Status */
+-#define PCI_REV_ID		0x08	/*  8 bit	Revision ID */
+-#define PCI_CLASS_CODE	0x09	/* 24 bit	Class Code */
+-#define PCI_CACHE_LSZ	0x0c	/*  8 bit	Cache Line Size */
+-#define PCI_LAT_TIM		0x0d	/*  8 bit	Latency Timer */
+-#define PCI_HEADER_T	0x0e	/*  8 bit	Header Type */
+-#define PCI_BIST		0x0f	/*  8 bit	Built-in selftest */
+-#define PCI_BASE_1ST	0x10	/* 32 bit	1st Base address */
+-#define PCI_BASE_2ND	0x14	/* 32 bit	2nd Base address */
+-	/* Byte 0x18..0x2b:	reserved */
+-#define PCI_SUB_VID		0x2c	/* 16 bit	Subsystem Vendor ID */
+-#define PCI_SUB_ID		0x2e	/* 16 bit	Subsystem ID */
+-#define PCI_BASE_ROM	0x30	/* 32 bit	Expansion ROM Base Address */
+-#define PCI_CAP_PTR		0x34	/*  8 bit 	Capabilities Ptr */
+-	/* Byte 0x35..0x3b:	reserved */
+-#define PCI_IRQ_LINE	0x3c	/*  8 bit	Interrupt Line */
+-#define PCI_IRQ_PIN		0x3d	/*  8 bit	Interrupt Pin */
+-#define PCI_MIN_GNT		0x3e	/*  8 bit	Min_Gnt */
+-#define PCI_MAX_LAT		0x3f	/*  8 bit	Max_Lat */
+-	/* Device Dependent Region */
+-#define PCI_OUR_REG_1	0x40	/* 32 bit 	Our Register 1 */
+-#define PCI_OUR_REG_2	0x44	/* 32 bit 	Our Register 2 */
+-	/* Power Management Region */
+-#define PCI_PM_CAP_ID	0x48	/*  8 bit 	Power Management Cap. ID */
+-#define PCI_PM_NITEM	0x49	/*  8 bit 	Next Item Ptr */
+-#define PCI_PM_CAP_REG	0x4a	/* 16 bit 	Power Management Capabilities */
+-#define PCI_PM_CTL_STS	0x4c	/* 16 bit 	Power Manag. Control/Status */
+-	/* Byte 0x4e:	reserved */
+-#define PCI_PM_DAT_REG	0x4f	/*  8 bit 	Power Manag. Data Register */
+-	/* VPD Region */
+-#define PCI_VPD_CAP_ID	0x50	/*  8 bit 	VPD Cap. ID */
+-#define PCI_VPD_NITEM	0x51	/*  8 bit 	Next Item Ptr */
+-#define PCI_VPD_ADR_REG	0x52	/* 16 bit 	VPD Address Register */
+-#define PCI_VPD_DAT_REG	0x54	/* 32 bit 	VPD Data Register */
+-	/* Byte 0x58..0x59:	reserved */
+-#define PCI_SER_LD_CTRL	0x5a	/* 16 bit 	SEEPROM Loader Ctrl (YUKON only) */
+-	/* Byte 0x5c..0xff:	reserved */
+-
+-/*
+- * I2C Address (PCI Config)
+- *
+- * Note: The temperature and voltage sensors are relocated on a different
+- *	 I2C bus.
+- */
+-#define I2C_ADDR_VPD	0xa0	/* I2C address for the VPD EEPROM */
+-
+-/*
+- * Define Bits and Values of the registers
+- */
+-/*	PCI_COMMAND	16 bit	Command */
+-								/* Bit 15..11:	reserved */
+-#define PCI_INT_DIS		BIT_10S		/* Interrupt INTx# disable (PCI 2.3) */
+-#define PCI_FBTEN		BIT_9S		/* Fast Back-To-Back enable */
+-#define PCI_SERREN		BIT_8S		/* SERR enable */
+-#define PCI_ADSTEP		BIT_7S		/* Address Stepping */
+-#define PCI_PERREN		BIT_6S		/* Parity Report Response enable */
+-#define PCI_VGA_SNOOP	BIT_5S		/* VGA palette snoop */
+-#define PCI_MWIEN		BIT_4S		/* Memory write an inv cycl ena */
+-#define PCI_SCYCEN		BIT_3S		/* Special Cycle enable */
+-#define PCI_BMEN		BIT_2S		/* Bus Master enable */
+-#define PCI_MEMEN		BIT_1S		/* Memory Space Access enable */
+-#define PCI_IOEN		BIT_0S		/* I/O Space Access enable */
+-
+-#define PCI_COMMAND_VAL	(PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\
+-						 PCI_BMEN | PCI_MEMEN | PCI_IOEN)
+-
+-/*	PCI_STATUS	16 bit	Status */
+-#define PCI_PERR		BIT_15S		/* Parity Error */
+-#define PCI_SERR		BIT_14S		/* Signaled SERR */
+-#define PCI_RMABORT		BIT_13S		/* Received Master Abort */
+-#define PCI_RTABORT		BIT_12S		/* Received Target Abort */
+-								/* Bit 11:	reserved */
+-#define PCI_DEVSEL		(3<<9)		/* Bit 10.. 9:	DEVSEL Timing */
+-#define PCI_DEV_FAST	(0<<9)		/*		fast */
+-#define PCI_DEV_MEDIUM	(1<<9)		/*		medium */
+-#define PCI_DEV_SLOW	(2<<9)		/*		slow */
+-#define PCI_DATAPERR	BIT_8S		/* DATA Parity error detected */
+-#define PCI_FB2BCAP		BIT_7S		/* Fast Back-to-Back Capability */
+-#define PCI_UDF			BIT_6S		/* User Defined Features */
+-#define PCI_66MHZCAP	BIT_5S		/* 66 MHz PCI bus clock capable */
+-#define PCI_NEWCAP		BIT_4S		/* New cap. list implemented */
+-#define PCI_INT_STAT	BIT_3S		/* Interrupt INTx# Status (PCI 2.3) */
+-								/* Bit  2.. 0:	reserved */
+-
+-#define PCI_ERRBITS	(PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\
+-			PCI_DATAPERR)
+-
+-/*	PCI_CLASS_CODE	24 bit	Class Code */
+-/*	Byte 2:		Base Class		(02) */
+-/*	Byte 1:		SubClass		(00) */
+-/*	Byte 0:		Programming Interface	(00) */
+-
+-/*	PCI_CACHE_LSZ	8 bit	Cache Line Size */
+-/*	Possible values: 0,2,4,8,16,32,64,128	*/
+-
+-/*	PCI_HEADER_T	8 bit	Header Type */
+-#define PCI_HD_MF_DEV	BIT_7S	/* 0= single, 1= multi-func dev */
+-#define PCI_HD_TYPE		0x7f	/* Bit 6..0:	Header Layout 0= normal */
+-
+-/*	PCI_BIST	8 bit	Built-in selftest */
+-/*	Built-in Self test not supported (optional) */
+-
+-/*	PCI_BASE_1ST	32 bit	1st Base address */
+-#define PCI_MEMSIZE		0x4000L		/* use 16 kB Memory Base */
+-#define PCI_MEMBASE_MSK 0xffffc000L	/* Bit 31..14:	Memory Base Address */
+-#define PCI_MEMSIZE_MSK 0x00003ff0L	/* Bit 13.. 4:	Memory Size Req. */
+-#define PCI_PREFEN		BIT_3		/* Prefetchable */
+-#define PCI_MEM_TYP		(3L<<2)		/* Bit	2.. 1:	Memory Type */
+-#define PCI_MEM32BIT	(0L<<1)		/* Base addr anywhere in 32 Bit range */
+-#define PCI_MEM1M		(1L<<1)		/* Base addr below 1 MegaByte */
+-#define PCI_MEM64BIT	(2L<<1)		/* Base addr anywhere in 64 Bit range */
+-#define PCI_MEMSPACE	BIT_0		/* Memory Space Indicator */
+-
+-/*	PCI_BASE_2ND	32 bit	2nd Base address */
+-#define PCI_IOBASE		0xffffff00L	/* Bit 31.. 8:	I/O Base address */
+-#define PCI_IOSIZE		0x000000fcL	/* Bit	7.. 2:	I/O Size Requirements */
+-									/* Bit	1:	reserved */
+-#define PCI_IOSPACE		BIT_0		/* I/O Space Indicator */
+-
+-/*	PCI_BASE_ROM	32 bit	Expansion ROM Base Address */
+-#define PCI_ROMBASE_MSK	0xfffe0000L	/* Bit 31..17:	ROM Base address */
+-#define PCI_ROMBASE_SIZ	(0x1cL<<14)	/* Bit 16..14:	Treat as Base or Size */
+-#define PCI_ROMSIZE		(0x38L<<11)	/* Bit 13..11:	ROM Size Requirements */
+-									/* Bit 10.. 1:	reserved */
+-#define PCI_ROMEN		BIT_0		/* Address Decode enable */
+-
+-/* Device Dependent Region */
+-/*	PCI_OUR_REG_1		32 bit	Our Register 1 */
+-									/* Bit 31..29:	reserved */
+-#define PCI_PHY_COMA	BIT_28		/* Set PHY to Coma Mode (YUKON only) */
+-#define PCI_TEST_CAL	BIT_27		/* Test PCI buffer calib. (YUKON only) */
+-#define PCI_EN_CAL		BIT_26		/* Enable PCI buffer calib. (YUKON only) */
+-#define PCI_VIO			BIT_25		/* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */
+-#define PCI_DIS_BOOT	BIT_24		/* Disable BOOT via ROM */
+-#define PCI_EN_IO		BIT_23		/* Mapping to I/O space */
+-#define PCI_EN_FPROM	BIT_22		/* Enable FLASH mapping to memory */
+-									/*		1 = Map Flash to memory */
+-									/*		0 = Disable addr. dec */
+-#define PCI_PAGESIZE	(3L<<20)	/* Bit 21..20:	FLASH Page Size	*/
+-#define PCI_PAGE_16		(0L<<20)	/*		16 k pages	*/
+-#define PCI_PAGE_32K	(1L<<20)	/*		32 k pages	*/
+-#define PCI_PAGE_64K	(2L<<20)	/*		64 k pages	*/
+-#define PCI_PAGE_128K	(3L<<20)	/*		128 k pages	*/
+-									/* Bit 19:	reserved	*/
+-#define PCI_PAGEREG		(7L<<16)	/* Bit 18..16:	Page Register	*/
+-#define PCI_NOTAR		BIT_15		/* No turnaround cycle */
+-#define PCI_FORCE_BE	BIT_14		/* Assert all BEs on MR */
+-#define PCI_DIS_MRL		BIT_13		/* Disable Mem Read Line */
+-#define PCI_DIS_MRM		BIT_12		/* Disable Mem Read Multiple */
+-#define PCI_DIS_MWI		BIT_11		/* Disable Mem Write & Invalidate */
+-#define PCI_DISC_CLS	BIT_10		/* Disc: cacheLsz bound */
+-#define PCI_BURST_DIS	BIT_9		/* Burst Disable */
+-#define PCI_DIS_PCI_CLK	BIT_8		/* Disable PCI clock driving */
+-#define PCI_SKEW_DAS	(0xfL<<4)	/* Bit	7.. 4:	Skew Ctrl, DAS Ext */
+-#define PCI_SKEW_BASE	0xfL		/* Bit	3.. 0:	Skew Ctrl, Base	*/
+-
+-
+-/*	PCI_OUR_REG_2		32 bit	Our Register 2 */
+-#define PCI_VPD_WR_THR	(0xffL<<24)	/* Bit 31..24:	VPD Write Threshold */
+-#define PCI_DEV_SEL		(0x7fL<<17)	/* Bit 23..17:	EEPROM Device Select */
+-#define PCI_VPD_ROM_SZ	(7L<<14)	/* Bit 16..14:	VPD ROM Size	*/
+-									/* Bit 13..12:	reserved	*/
+-#define PCI_PATCH_DIR	(0xfL<<8)	/* Bit 11.. 8:	Ext Patches dir 3..0 */
+-#define PCI_PATCH_DIR_3	BIT_11
+-#define PCI_PATCH_DIR_2	BIT_10
+-#define PCI_PATCH_DIR_1	BIT_9
+-#define PCI_PATCH_DIR_0	BIT_8
+-#define PCI_EXT_PATCHS	(0xfL<<4)	/* Bit	7.. 4:	Extended Patches 3..0 */
+-#define PCI_EXT_PATCH_3	BIT_7
+-#define PCI_EXT_PATCH_2	BIT_6
+-#define PCI_EXT_PATCH_1	BIT_5
+-#define PCI_EXT_PATCH_0	BIT_4
+-#define PCI_EN_DUMMY_RD	BIT_3		/* Enable Dummy Read */
+-#define PCI_REV_DESC	BIT_2		/* Reverse Desc. Bytes */
+-									/* Bit	1:	reserved */
+-#define PCI_USEDATA64	BIT_0		/* Use 64Bit Data bus ext */
+-
+-
+-/* Power Management Region */
+-/*	PCI_PM_CAP_REG		16 bit	Power Management Capabilities */
+-#define PCI_PME_SUP_MSK	(0x1f<<11)	/* Bit 15..11:	PM Event Support Mask */
+-#define PCI_PME_D3C_SUP	BIT_15S		/* PME from D3cold Support (if Vaux) */
+-#define PCI_PME_D3H_SUP	BIT_14S		/* PME from D3hot Support */
+-#define PCI_PME_D2_SUP	BIT_13S		/* PME from D2 Support */
+-#define PCI_PME_D1_SUP	BIT_12S		/* PME from D1 Support */
+-#define PCI_PME_D0_SUP	BIT_11S		/* PME from D0 Support */
+-#define PCI_PM_D2_SUP	BIT_10S		/* D2 Support in 33 MHz mode */
+-#define PCI_PM_D1_SUP	BIT_9S		/* D1 Support */
+-									/* Bit	8.. 6:	reserved */
+-#define PCI_PM_DSI		BIT_5S		/* Device Specific Initialization */
+-#define PCI_PM_APS		BIT_4S		/* Auxialiary Power Source */
+-#define PCI_PME_CLOCK	BIT_3S		/* PM Event Clock */
+-#define PCI_PM_VER_MSK		7		/* Bit	2.. 0:	PM PCI Spec. version */
+-
+-/*	PCI_PM_CTL_STS		16 bit	Power Management Control/Status */
+-#define PCI_PME_STATUS	BIT_15S		/* PME Status (YUKON only) */
+-#define PCI_PM_DAT_SCL	(3<<13)		/* Bit 14..13:	Data Reg. scaling factor */
+-#define PCI_PM_DAT_SEL	(0xf<<9)	/* Bit 12.. 9:	PM data selector field */
+-#define PCI_PME_EN		BIT_8S		/* Enable PME# generation (YUKON only) */
+-									/* Bit	7.. 2:	reserved */
+-#define PCI_PM_STATE_MSK	3		/* Bit	1.. 0:	Power Management State */
+-
+-#define PCI_PM_STATE_D0		0		/* D0:	Operational (default) */
+-#define PCI_PM_STATE_D1		1		/* D1:	(YUKON only) */
+-#define PCI_PM_STATE_D2		2		/* D2:	(YUKON only) */
+-#define PCI_PM_STATE_D3 	3		/* D3:	HOT, Power Down and Reset */
+-
+-/* VPD Region */
+-/*	PCI_VPD_ADR_REG		16 bit	VPD Address Register */
+-#define PCI_VPD_FLAG	BIT_15S		/* starts VPD rd/wr cycle */
+-#define PCI_VPD_ADR_MSK	0x7fffL		/* Bit 14.. 0:	VPD address mask */
+-
+-/*	Control Register File (Address Map) */
+-
+-/*
+- *	Bank 0
+- */
+-#define B0_RAP			0x0000	/*  8 bit	Register Address Port */
+-	/* 0x0001 - 0x0003:	reserved */
+-#define B0_CTST			0x0004	/* 16 bit	Control/Status register */
+-#define B0_LED			0x0006	/*  8 Bit	LED register */
+-#define B0_POWER_CTRL	0x0007	/*  8 Bit	Power Control reg (YUKON only) */
+-#define B0_ISRC			0x0008	/* 32 bit	Interrupt Source Register */
+-#define B0_IMSK			0x000c	/* 32 bit	Interrupt Mask Register */
+-#define B0_HWE_ISRC		0x0010	/* 32 bit	HW Error Interrupt Src Reg */
+-#define B0_HWE_IMSK		0x0014	/* 32 bit	HW Error Interrupt Mask Reg */
+-#define B0_SP_ISRC		0x0018	/* 32 bit	Special Interrupt Source Reg */
+-	/* 0x001c:		reserved */
+-
+-/* B0 XMAC 1 registers (GENESIS only) */
+-#define B0_XM1_IMSK		0x0020	/* 16 bit r/w	XMAC 1 Interrupt Mask Register*/
+-	/* 0x0022 - 0x0027:	reserved */
+-#define B0_XM1_ISRC		0x0028	/* 16 bit ro	XMAC 1 Interrupt Status Reg */
+-	/* 0x002a - 0x002f:	reserved */
+-#define B0_XM1_PHY_ADDR 0x0030	/* 16 bit r/w	XMAC 1 PHY Address Register */
+-	/* 0x0032 - 0x0033:	reserved */
+-#define B0_XM1_PHY_DATA 0x0034	/* 16 bit r/w	XMAC 1 PHY Data Register */
+-	/* 0x0036 - 0x003f:	reserved */
+-
+-/* B0 XMAC 2 registers (GENESIS only) */
+-#define B0_XM2_IMSK		0x0040	/* 16 bit r/w	XMAC 2 Interrupt Mask Register*/
+-	/* 0x0042 - 0x0047:	reserved */
+-#define B0_XM2_ISRC		0x0048	/* 16 bit ro	XMAC 2 Interrupt Status Reg */
+-	/* 0x004a - 0x004f:	reserved */
+-#define B0_XM2_PHY_ADDR 0x0050	/* 16 bit r/w	XMAC 2 PHY Address Register */
+-	/* 0x0052 - 0x0053:	reserved */
+-#define B0_XM2_PHY_DATA 0x0054	/* 16 bit r/w	XMAC 2 PHY Data Register */
+-	/* 0x0056 - 0x005f:	reserved */
+-
+-/* BMU Control Status Registers */
+-#define B0_R1_CSR		0x0060	/* 32 bit	BMU Ctrl/Stat Rx Queue 1 */
+-#define B0_R2_CSR		0x0064	/* 32 bit	BMU Ctrl/Stat Rx Queue 2 */
+-#define B0_XS1_CSR		0x0068	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
+-#define B0_XA1_CSR		0x006c	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 1*/
+-#define B0_XS2_CSR		0x0070	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
+-#define B0_XA2_CSR		0x0074	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 2*/
+-	/* 0x0078 - 0x007f:	reserved */
+-
+-/*
+- *	Bank 1
+- *	- completely empty (this is the RAP Block window)
+- *	Note: if RAP = 1 this page is reserved
+- */
+-
+-/*
+- *	Bank 2
+- */
+-/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */
+-#define B2_MAC_1		0x0100	/* NA reg	 MAC Address 1 */
+-	/* 0x0106 - 0x0107:	reserved */
+-#define B2_MAC_2		0x0108	/* NA reg	 MAC Address 2 */
+-	/* 0x010e - 0x010f:	reserved */
+-#define B2_MAC_3		0x0110	/* NA reg	 MAC Address 3 */
+-	/* 0x0116 - 0x0117:	reserved */
+-#define B2_CONN_TYP		0x0118	/*  8 bit	Connector type */
+-#define B2_PMD_TYP		0x0119	/*  8 bit	PMD type */
+-#define B2_MAC_CFG		0x011a	/*  8 bit	MAC Configuration / Chip Revision */
+-#define B2_CHIP_ID		0x011b	/*  8 bit 	Chip Identification Number */
+-	/* Eprom registers are currently of no use */
+-#define B2_E_0			0x011c	/*  8 bit	EPROM Byte 0 (ext. SRAM size */
+-#define B2_E_1			0x011d	/*  8 bit	EPROM Byte 1 (PHY type) */
+-#define B2_E_2			0x011e	/*  8 bit	EPROM Byte 2 */
+-#define B2_E_3			0x011f	/*  8 bit	EPROM Byte 3 */
+-#define B2_FAR			0x0120	/* 32 bit	Flash-Prom Addr Reg/Cnt */
+-#define B2_FDP			0x0124	/*  8 bit	Flash-Prom Data Port */
+-	/* 0x0125 - 0x0127:	reserved */
+-#define B2_LD_CTRL		0x0128	/*  8 bit	EPROM loader control register */
+-#define B2_LD_TEST		0x0129	/*  8 bit	EPROM loader test register */
+-	/* 0x012a - 0x012f:	reserved */
+-#define B2_TI_INI		0x0130	/* 32 bit	Timer Init Value */
+-#define B2_TI_VAL		0x0134	/* 32 bit	Timer Value */
+-#define B2_TI_CTRL		0x0138	/*  8 bit	Timer Control */
+-#define B2_TI_TEST		0x0139	/*  8 Bit	Timer Test */
+-	/* 0x013a - 0x013f:	reserved */
+-#define B2_IRQM_INI		0x0140	/* 32 bit	IRQ Moderation Timer Init Reg.*/
+-#define B2_IRQM_VAL		0x0144	/* 32 bit	IRQ Moderation Timer Value */
+-#define B2_IRQM_CTRL	0x0148	/*  8 bit	IRQ Moderation Timer Control */
+-#define B2_IRQM_TEST	0x0149	/*  8 bit	IRQ Moderation Timer Test */
+-#define B2_IRQM_MSK 	0x014c	/* 32 bit	IRQ Moderation Mask */
+-#define B2_IRQM_HWE_MSK 0x0150	/* 32 bit	IRQ Moderation HW Error Mask */
+-	/* 0x0154 - 0x0157:	reserved */
+-#define B2_TST_CTRL1	0x0158	/*  8 bit	Test Control Register 1 */
+-#define B2_TST_CTRL2	0x0159	/*  8 bit	Test Control Register 2 */
+-	/* 0x015a - 0x015b:	reserved */
+-#define B2_GP_IO		0x015c	/* 32 bit	General Purpose I/O Register */
+-#define B2_I2C_CTRL		0x0160	/* 32 bit	I2C HW Control Register */
+-#define B2_I2C_DATA		0x0164	/* 32 bit	I2C HW Data Register */
+-#define B2_I2C_IRQ		0x0168	/* 32 bit	I2C HW IRQ Register */
+-#define B2_I2C_SW		0x016c	/* 32 bit	I2C SW Port Register */
+-
+-/* Blink Source Counter (GENESIS only) */
+-#define B2_BSC_INI		0x0170	/* 32 bit	Blink Source Counter Init Val */
+-#define B2_BSC_VAL		0x0174	/* 32 bit	Blink Source Counter Value */
+-#define B2_BSC_CTRL		0x0178	/*  8 bit	Blink Source Counter Control */
+-#define B2_BSC_STAT		0x0179	/*  8 bit	Blink Source Counter Status */
+-#define B2_BSC_TST		0x017a	/* 16 bit	Blink Source Counter Test Reg */
+-	/* 0x017c - 0x017f:	reserved */
+-
+-/*
+- *	Bank 3
+- */
+-/* RAM Random Registers */
+-#define B3_RAM_ADDR		0x0180	/* 32 bit	RAM Address, to read or write */
+-#define B3_RAM_DATA_LO	0x0184	/* 32 bit	RAM Data Word (low dWord) */
+-#define B3_RAM_DATA_HI	0x0188	/* 32 bit	RAM Data Word (high dWord) */
+-	/* 0x018c - 0x018f:	reserved */
+-
+-/* RAM Interface Registers */
+-/*
+- * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
+- * not usable in SW. Please notice these are NOT real timeouts, these are
+- * the number of qWords transferred continuously.
+- */
+-#define B3_RI_WTO_R1	0x0190	/*  8 bit	WR Timeout Queue R1		(TO0) */
+-#define B3_RI_WTO_XA1	0x0191	/*  8 bit	WR Timeout Queue XA1	(TO1) */
+-#define B3_RI_WTO_XS1	0x0192	/*  8 bit	WR Timeout Queue XS1	(TO2) */
+-#define B3_RI_RTO_R1	0x0193	/*  8 bit	RD Timeout Queue R1		(TO3) */
+-#define B3_RI_RTO_XA1	0x0194	/*  8 bit	RD Timeout Queue XA1	(TO4) */
+-#define B3_RI_RTO_XS1	0x0195	/*  8 bit	RD Timeout Queue XS1	(TO5) */
+-#define B3_RI_WTO_R2	0x0196	/*  8 bit	WR Timeout Queue R2		(TO6) */
+-#define B3_RI_WTO_XA2	0x0197	/*  8 bit	WR Timeout Queue XA2	(TO7) */
+-#define B3_RI_WTO_XS2	0x0198	/*  8 bit	WR Timeout Queue XS2	(TO8) */
+-#define B3_RI_RTO_R2	0x0199	/*  8 bit	RD Timeout Queue R2		(TO9) */
+-#define B3_RI_RTO_XA2	0x019a	/*  8 bit	RD Timeout Queue XA2	(TO10)*/
+-#define B3_RI_RTO_XS2	0x019b	/*  8 bit	RD Timeout Queue XS2	(TO11)*/
+-#define B3_RI_TO_VAL	0x019c	/*  8 bit	Current Timeout Count Val */
+-	/* 0x019d - 0x019f:	reserved */
+-#define B3_RI_CTRL		0x01a0	/* 16 bit	RAM Interface Control Register */
+-#define B3_RI_TEST		0x01a2	/*  8 bit	RAM Interface Test Register */
+-	/* 0x01a3 - 0x01af:	reserved */
+-
+-/* MAC Arbiter Registers (GENESIS only) */
+-/* these are the no. of qWord transferred continuously and NOT real timeouts */
+-#define B3_MA_TOINI_RX1	0x01b0	/*  8 bit	Timeout Init Val Rx Path MAC 1 */
+-#define B3_MA_TOINI_RX2	0x01b1	/*  8 bit	Timeout Init Val Rx Path MAC 2 */
+-#define B3_MA_TOINI_TX1	0x01b2	/*  8 bit	Timeout Init Val Tx Path MAC 1 */
+-#define B3_MA_TOINI_TX2	0x01b3	/*  8 bit	Timeout Init Val Tx Path MAC 2 */
+-#define B3_MA_TOVAL_RX1	0x01b4	/*  8 bit	Timeout Value Rx Path MAC 1 */
+-#define B3_MA_TOVAL_RX2	0x01b5	/*  8 bit	Timeout Value Rx Path MAC 1 */
+-#define B3_MA_TOVAL_TX1	0x01b6	/*  8 bit	Timeout Value Tx Path MAC 2 */
+-#define B3_MA_TOVAL_TX2	0x01b7	/*  8 bit	Timeout Value Tx Path MAC 2 */
+-#define B3_MA_TO_CTRL	0x01b8	/* 16 bit	MAC Arbiter Timeout Ctrl Reg */
+-#define B3_MA_TO_TEST	0x01ba	/* 16 bit	MAC Arbiter Timeout Test Reg */
+-	/* 0x01bc - 0x01bf:	reserved */
+-#define B3_MA_RCINI_RX1	0x01c0	/*  8 bit	Recovery Init Val Rx Path MAC 1 */
+-#define B3_MA_RCINI_RX2	0x01c1	/*  8 bit	Recovery Init Val Rx Path MAC 2 */
+-#define B3_MA_RCINI_TX1	0x01c2	/*  8 bit	Recovery Init Val Tx Path MAC 1 */
+-#define B3_MA_RCINI_TX2	0x01c3	/*  8 bit	Recovery Init Val Tx Path MAC 2 */
+-#define B3_MA_RCVAL_RX1	0x01c4	/*  8 bit	Recovery Value Rx Path MAC 1 */
+-#define B3_MA_RCVAL_RX2	0x01c5	/*  8 bit	Recovery Value Rx Path MAC 1 */
+-#define B3_MA_RCVAL_TX1	0x01c6	/*  8 bit	Recovery Value Tx Path MAC 2 */
+-#define B3_MA_RCVAL_TX2	0x01c7	/*  8 bit	Recovery Value Tx Path MAC 2 */
+-#define B3_MA_RC_CTRL	0x01c8	/* 16 bit	MAC Arbiter Recovery Ctrl Reg */
+-#define B3_MA_RC_TEST	0x01ca	/* 16 bit	MAC Arbiter Recovery Test Reg */
+-	/* 0x01cc - 0x01cf:	reserved */
+-
+-/* Packet Arbiter Registers (GENESIS only) */
+-/* these are real timeouts */
+-#define B3_PA_TOINI_RX1	0x01d0	/* 16 bit	Timeout Init Val Rx Path MAC 1 */
+-	/* 0x01d2 - 0x01d3:	reserved */
+-#define B3_PA_TOINI_RX2	0x01d4	/* 16 bit	Timeout Init Val Rx Path MAC 2 */
+-	/* 0x01d6 - 0x01d7:	reserved */
+-#define B3_PA_TOINI_TX1	0x01d8	/* 16 bit	Timeout Init Val Tx Path MAC 1 */
+-	/* 0x01da - 0x01db:	reserved */
+-#define B3_PA_TOINI_TX2	0x01dc	/* 16 bit	Timeout Init Val Tx Path MAC 2 */
+-	/* 0x01de - 0x01df:	reserved */
+-#define B3_PA_TOVAL_RX1	0x01e0	/* 16 bit	Timeout Val Rx Path MAC 1 */
+-	/* 0x01e2 - 0x01e3:	reserved */
+-#define B3_PA_TOVAL_RX2	0x01e4	/* 16 bit	Timeout Val Rx Path MAC 2 */
+-	/* 0x01e6 - 0x01e7:	reserved */
+-#define B3_PA_TOVAL_TX1	0x01e8	/* 16 bit	Timeout Val Tx Path MAC 1 */
+-	/* 0x01ea - 0x01eb:	reserved */
+-#define B3_PA_TOVAL_TX2	0x01ec	/* 16 bit	Timeout Val Tx Path MAC 2 */
+-	/* 0x01ee - 0x01ef:	reserved */
+-#define B3_PA_CTRL	0x01f0	/* 16 bit	Packet Arbiter Ctrl Register */
+-#define B3_PA_TEST	0x01f2	/* 16 bit	Packet Arbiter Test Register */
+-	/* 0x01f4 - 0x01ff:	reserved */
+-
+-/*
+- *	Bank 4 - 5
+- */
+-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+-#define TXA_ITI_INI		0x0200	/* 32 bit	Tx Arb Interval Timer Init Val*/
+-#define TXA_ITI_VAL		0x0204	/* 32 bit	Tx Arb Interval Timer Value */
+-#define TXA_LIM_INI		0x0208	/* 32 bit	Tx Arb Limit Counter Init Val */
+-#define TXA_LIM_VAL		0x020c	/* 32 bit	Tx Arb Limit Counter Value */
+-#define TXA_CTRL		0x0210	/*  8 bit	Tx Arbiter Control Register */
+-#define TXA_TEST		0x0211	/*  8 bit	Tx Arbiter Test Register */
+-#define TXA_STAT		0x0212	/*  8 bit	Tx Arbiter Status Register */
+-	/* 0x0213 - 0x027f:	reserved */
+-	/* 0x0280 - 0x0292:	MAC 2 */
+-	/* 0x0213 - 0x027f:	reserved */
+-
+-/*
+- *	Bank 6
+- */
+-/* External registers (GENESIS only) */
+-#define B6_EXT_REG		0x0300
+-
+-/*
+- *	Bank 7
+- */
+-/* This is a copy of the Configuration register file (lower half) */
+-#define B7_CFG_SPC		0x0380
+-
+-/*
+- *	Bank 8 - 15
+- */
+-/* Receive and Transmit Queue Registers, use Q_ADDR() to access */
+-#define B8_Q_REGS		0x0400
+-
+-/* Queue Register Offsets, use Q_ADDR() to access */
+-#define Q_D		0x00	/* 8*32	bit	Current Descriptor */
+-#define Q_DA_L	0x20	/* 32 bit	Current Descriptor Address Low dWord */
+-#define Q_DA_H	0x24	/* 32 bit	Current Descriptor Address High dWord */
+-#define Q_AC_L	0x28	/* 32 bit	Current Address Counter Low dWord */
+-#define Q_AC_H	0x2c	/* 32 bit	Current Address Counter High dWord */
+-#define Q_BC	0x30	/* 32 bit	Current Byte Counter */
+-#define Q_CSR	0x34	/* 32 bit	BMU Control/Status Register */
+-#define Q_F		0x38	/* 32 bit	Flag Register */
+-#define Q_T1	0x3c	/* 32 bit	Test Register 1 */
+-#define Q_T1_TR	0x3c	/*  8 bit	Test Register 1 Transfer SM */
+-#define Q_T1_WR	0x3d	/*  8 bit	Test Register 1 Write Descriptor SM */
+-#define Q_T1_RD	0x3e	/*  8 bit	Test Register 1 Read Descriptor SM */
+-#define Q_T1_SV	0x3f	/*  8 bit	Test Register 1 Supervisor SM */
+-#define Q_T2	0x40	/* 32 bit	Test Register 2	*/
+-#define Q_T3	0x44	/* 32 bit	Test Register 3	*/
+-	/* 0x48 - 0x7f:	reserved */
+-
+-/*
+- *	Bank 16 - 23
+- */
+-/* RAM Buffer Registers */
+-#define B16_RAM_REGS	0x0800
+-
+-/* RAM Buffer Register Offsets, use RB_ADDR() to access */
+-#define RB_START		0x00	/* 32 bit	RAM Buffer Start Address */
+-#define RB_END			0x04	/* 32 bit	RAM Buffer End Address */
+-#define RB_WP			0x08	/* 32 bit	RAM Buffer Write Pointer */
+-#define RB_RP			0x0c	/* 32 bit	RAM Buffer Read Pointer */
+-#define RB_RX_UTPP		0x10	/* 32 bit	Rx Upper Threshold, Pause Pack */
+-#define RB_RX_LTPP		0x14	/* 32 bit	Rx Lower Threshold, Pause Pack */
+-#define RB_RX_UTHP		0x18	/* 32 bit	Rx Upper Threshold, High Prio */
+-#define RB_RX_LTHP		0x1c	/* 32 bit	Rx Lower Threshold, High Prio */
+-	/* 0x10 - 0x1f:	reserved at Tx RAM Buffer Registers */
+-#define RB_PC			0x20	/* 32 bit	RAM Buffer Packet Counter */
+-#define RB_LEV			0x24	/* 32 bit	RAM Buffer Level Register */
+-#define RB_CTRL			0x28	/*  8 bit	RAM Buffer Control Register */
+-#define RB_TST1			0x29	/*  8 bit	RAM Buffer Test Register 1 */
+-#define RB_TST2			0x2A	/*  8 bit	RAM Buffer Test Register 2 */
+-	/* 0x2c - 0x7f:	reserved */
+-
+-/*
+- *	Bank 24
+- */
+-/*
+- * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only)
+- * use MR_ADDR() to access
+- */
+-#define RX_MFF_EA		0x0c00	/* 32 bit	Receive MAC FIFO End Address */
+-#define RX_MFF_WP		0x0c04	/* 32 bit 	Receive MAC FIFO Write Pointer */
+-	/* 0x0c08 - 0x0c0b:	reserved */
+-#define RX_MFF_RP		0x0c0c	/* 32 bit	Receive MAC FIFO Read Pointer */
+-#define RX_MFF_PC		0x0c10	/* 32 bit	Receive MAC FIFO Packet Cnt */
+-#define RX_MFF_LEV		0x0c14	/* 32 bit	Receive MAC FIFO Level */
+-#define RX_MFF_CTRL1	0x0c18	/* 16 bit	Receive MAC FIFO Control Reg 1*/
+-#define RX_MFF_STAT_TO	0x0c1a	/*  8 bit	Receive MAC Status Timeout */
+-#define RX_MFF_TIST_TO	0x0c1b	/*  8 bit	Receive MAC Time Stamp Timeout */
+-#define RX_MFF_CTRL2	0x0c1c	/*  8 bit	Receive MAC FIFO Control Reg 2*/
+-#define RX_MFF_TST1		0x0c1d	/*  8 bit	Receive MAC FIFO Test Reg 1 */
+-#define RX_MFF_TST2		0x0c1e	/*  8 bit	Receive MAC FIFO Test Reg 2 */
+-	/* 0x0c1f:	reserved */
+-#define RX_LED_INI		0x0c20	/* 32 bit	Receive LED Cnt Init Value */
+-#define RX_LED_VAL		0x0c24	/* 32 bit	Receive LED Cnt Current Value */
+-#define RX_LED_CTRL		0x0c28	/*  8 bit	Receive LED Cnt Control Reg */
+-#define RX_LED_TST		0x0c29	/*  8 bit	Receive LED Cnt Test Register */
+-	/* 0x0c2a - 0x0c2f:	reserved */
+-#define LNK_SYNC_INI	0x0c30	/* 32 bit	Link Sync Cnt Init Value */
+-#define LNK_SYNC_VAL	0x0c34	/* 32 bit	Link Sync Cnt Current Value */
+-#define LNK_SYNC_CTRL	0x0c38	/*  8 bit	Link Sync Cnt Control Register */
+-#define LNK_SYNC_TST	0x0c39	/*  8 bit	Link Sync Cnt Test Register */
+-	/* 0x0c3a - 0x0c3b:	reserved */
+-#define LNK_LED_REG		0x0c3c	/*  8 bit	Link LED Register */
+-	/* 0x0c3d - 0x0c3f:	reserved */
+-
+-/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */
+-#define RX_GMF_EA		0x0c40	/* 32 bit	Rx GMAC FIFO End Address */
+-#define RX_GMF_AF_THR	0x0c44	/* 32 bit	Rx GMAC FIFO Almost Full Thresh. */
+-#define RX_GMF_CTRL_T	0x0c48	/* 32 bit	Rx GMAC FIFO Control/Test */
+-#define RX_GMF_FL_MSK	0x0c4c	/* 32 bit	Rx GMAC FIFO Flush Mask */
+-#define RX_GMF_FL_THR	0x0c50	/* 32 bit	Rx GMAC FIFO Flush Threshold */
+-	/* 0x0c54 - 0x0c5f:	reserved */
+-#define RX_GMF_WP		0x0c60	/* 32 bit 	Rx GMAC FIFO Write Pointer */
+-	/* 0x0c64 - 0x0c67:	reserved */
+-#define RX_GMF_WLEV		0x0c68	/* 32 bit 	Rx GMAC FIFO Write Level */
+-	/* 0x0c6c - 0x0c6f:	reserved */
+-#define RX_GMF_RP		0x0c70	/* 32 bit 	Rx GMAC FIFO Read Pointer */
+-	/* 0x0c74 - 0x0c77:	reserved */
+-#define RX_GMF_RLEV		0x0c78	/* 32 bit 	Rx GMAC FIFO Read Level */
+-	/* 0x0c7c - 0x0c7f:	reserved */
+-
+-/*
+- *	Bank 25
+- */
+-	/* 0x0c80 - 0x0cbf:	MAC 2 */
+-	/* 0x0cc0 - 0x0cff:	reserved */
+-
+-/*
+- *	Bank 26
+- */
+-/*
+- * Transmit MAC FIFO and Transmit LED Registers (GENESIS only),
+- * use MR_ADDR() to access
+- */
+-#define TX_MFF_EA		0x0d00	/* 32 bit	Transmit MAC FIFO End Address */
+-#define TX_MFF_WP		0x0d04	/* 32 bit 	Transmit MAC FIFO WR Pointer */
+-#define TX_MFF_WSP		0x0d08	/* 32 bit	Transmit MAC FIFO WR Shadow Ptr */
+-#define TX_MFF_RP		0x0d0c	/* 32 bit	Transmit MAC FIFO RD Pointer */
+-#define TX_MFF_PC		0x0d10	/* 32 bit	Transmit MAC FIFO Packet Cnt */
+-#define TX_MFF_LEV		0x0d14	/* 32 bit	Transmit MAC FIFO Level */
+-#define TX_MFF_CTRL1	0x0d18	/* 16 bit	Transmit MAC FIFO Ctrl Reg 1 */
+-#define TX_MFF_WAF		0x0d1a	/*  8 bit	Transmit MAC Wait after flush */
+-	/* 0x0c1b:	reserved */
+-#define TX_MFF_CTRL2	0x0d1c	/*  8 bit	Transmit MAC FIFO Ctrl Reg 2 */
+-#define TX_MFF_TST1		0x0d1d	/*  8 bit	Transmit MAC FIFO Test Reg 1 */
+-#define TX_MFF_TST2		0x0d1e	/*  8 bit	Transmit MAC FIFO Test Reg 2 */
+-	/* 0x0d1f:	reserved */
+-#define TX_LED_INI		0x0d20	/* 32 bit	Transmit LED Cnt Init Value */
+-#define TX_LED_VAL		0x0d24	/* 32 bit	Transmit LED Cnt Current Val */
+-#define TX_LED_CTRL		0x0d28	/*  8 bit	Transmit LED Cnt Control Reg */
+-#define TX_LED_TST		0x0d29	/*  8 bit	Transmit LED Cnt Test Reg */
+-	/* 0x0d2a - 0x0d3f:	reserved */
+-
+-/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */
+-#define TX_GMF_EA		0x0d40	/* 32 bit	Tx GMAC FIFO End Address */
+-#define TX_GMF_AE_THR	0x0d44	/* 32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
+-#define TX_GMF_CTRL_T	0x0d48	/* 32 bit	Tx GMAC FIFO Control/Test */
+-	/* 0x0d4c - 0x0d5f:	reserved */
+-#define TX_GMF_WP		0x0d60	/* 32 bit 	Tx GMAC FIFO Write Pointer */
+-#define TX_GMF_WSP		0x0d64	/* 32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
+-#define TX_GMF_WLEV		0x0d68	/* 32 bit 	Tx GMAC FIFO Write Level */
+-	/* 0x0d6c - 0x0d6f:	reserved */
+-#define TX_GMF_RP		0x0d70	/* 32 bit 	Tx GMAC FIFO Read Pointer */
+-#define TX_GMF_RSTP		0x0d74	/* 32 bit 	Tx GMAC FIFO Restart Pointer */
+-#define TX_GMF_RLEV		0x0d78	/* 32 bit 	Tx GMAC FIFO Read Level */
+-	/* 0x0d7c - 0x0d7f:	reserved */
+-
+-/*
+- *	Bank 27
+- */
+-	/* 0x0d80 - 0x0dbf:	MAC 2 */
+-	/* 0x0daa - 0x0dff:	reserved */
+-
+-/*
+- *	Bank 28
+- */
+-/* Descriptor Poll Timer Registers */
+-#define B28_DPT_INI		0x0e00	/* 24 bit	Descriptor Poll Timer Init Val */
+-#define B28_DPT_VAL		0x0e04	/* 24 bit	Descriptor Poll Timer Curr Val */
+-#define B28_DPT_CTRL	0x0e08	/*  8 bit	Descriptor Poll Timer Ctrl Reg */
+-	/* 0x0e09:	reserved */
+-#define B28_DPT_TST		0x0e0a	/*  8 bit	Descriptor Poll Timer Test Reg */
+-	/* 0x0e0b:	reserved */
+-
+-/* Time Stamp Timer Registers (YUKON only) */
+-	/* 0x0e10:	reserved */
+-#define GMAC_TI_ST_VAL	0x0e14	/* 32 bit	Time Stamp Timer Curr Val */
+-#define GMAC_TI_ST_CTRL	0x0e18	/*  8 bit	Time Stamp Timer Ctrl Reg */
+-	/* 0x0e19:	reserved */
+-#define GMAC_TI_ST_TST	0x0e1a	/*  8 bit	Time Stamp Timer Test Reg */
+-	/* 0x0e1b - 0x0e7f:	reserved */
+-
+-/*
+- *	Bank 29
+- */
+-	/* 0x0e80 - 0x0efc:	reserved */
+-
+-/*
+- *	Bank 30
+- */
+-/* GMAC and GPHY Control Registers (YUKON only) */
+-#define GMAC_CTRL		0x0f00	/* 32 bit	GMAC Control Reg */
+-#define GPHY_CTRL		0x0f04	/* 32 bit	GPHY Control Reg */
+-#define GMAC_IRQ_SRC	0x0f08	/*  8 bit	GMAC Interrupt Source Reg */
+-	/* 0x0f09 - 0x0f0b:	reserved */
+-#define GMAC_IRQ_MSK	0x0f0c	/*  8 bit	GMAC Interrupt Mask Reg */
+-	/* 0x0f0d - 0x0f0f:	reserved */
+-#define GMAC_LINK_CTRL	0x0f10	/* 16 bit	Link Control Reg */
+-	/* 0x0f14 - 0x0f1f:	reserved */
+-
+-/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
+-
+-#define WOL_REG_OFFS	0x20	/* HW-Bug: Address is + 0x20 against spec. */
+-
+-#define WOL_CTRL_STAT	0x0f20	/* 16 bit	WOL Control/Status Reg */
+-#define WOL_MATCH_CTL	0x0f22	/*  8 bit	WOL Match Control Reg */
+-#define WOL_MATCH_RES	0x0f23	/*  8 bit	WOL Match Result Reg */
+-#define WOL_MAC_ADDR_LO	0x0f24	/* 32 bit	WOL MAC Address Low */
+-#define WOL_MAC_ADDR_HI	0x0f28	/* 16 bit	WOL MAC Address High */
+-#define WOL_PATT_RPTR	0x0f2c	/*  8 bit	WOL Pattern Read Ptr */
+-
+-/* use this macro to access above registers */
+-#define WOL_REG(Reg)	((Reg) + (pAC->GIni.GIWolOffs))
+-
+-
+-/* WOL Pattern Length Registers (YUKON only) */
+-
+-#define WOL_PATT_LEN_LO	0x0f30		/* 32 bit	WOL Pattern Length 3..0 */
+-#define WOL_PATT_LEN_HI	0x0f34		/* 24 bit	WOL Pattern Length 6..4 */
+-
+-/* WOL Pattern Counter Registers (YUKON only) */
+-
+-#define WOL_PATT_CNT_0	0x0f38		/* 32 bit	WOL Pattern Counter 3..0 */
+-#define WOL_PATT_CNT_4	0x0f3c		/* 24 bit	WOL Pattern Counter 6..4 */
+-	/* 0x0f40 - 0x0f7f:	reserved */
+-
+-/*
+- *	Bank 31
+- */
+-/* 0x0f80 - 0x0fff:	reserved */
+-
+-/*
+- *	Bank 32	- 33
+- */
+-#define WOL_PATT_RAM_1	0x1000	/*  WOL Pattern RAM Link 1 */
+-
+-/*
+- *	Bank 0x22 - 0x3f
+- */
+-/* 0x1100 - 0x1fff:	reserved */
+-
+-/*
+- *	Bank 0x40 - 0x4f
+- */
+-#define BASE_XMAC_1		0x2000	/* XMAC 1 registers */
+-
+-/*
+- *	Bank 0x50 - 0x5f
+- */
+-
+-#define BASE_GMAC_1		0x2800	/* GMAC 1 registers */
+-
+-/*
+- *	Bank 0x60 - 0x6f
+- */
+-#define BASE_XMAC_2		0x3000	/* XMAC 2 registers */
+-
+-/*
+- *	Bank 0x70 - 0x7f
+- */
+-#define BASE_GMAC_2		0x3800	/* GMAC 2 registers */
+-
+-/*
+- *	Control Register Bit Definitions:
+- */
+-/*	B0_RAP		8 bit	Register Address Port */
+-								/* Bit 7:	reserved */
+-#define RAP_RAP			0x3f	/* Bit 6..0:	0 = block 0,..,6f = block 6f */
+-
+-/*	B0_CTST			16 bit	Control/Status register */
+-								/* Bit 15..14:	reserved */
+-#define CS_CLK_RUN_HOT	BIT_13S		/* CLK_RUN hot m. (YUKON-Lite only) */
+-#define CS_CLK_RUN_RST	BIT_12S		/* CLK_RUN reset  (YUKON-Lite only) */
+-#define CS_CLK_RUN_ENA	BIT_11S		/* CLK_RUN enable (YUKON-Lite only) */
+-#define CS_VAUX_AVAIL	BIT_10S		/* VAUX available (YUKON only) */
+-#define CS_BUS_CLOCK	BIT_9S		/* Bus Clock 0/1 = 33/66 MHz */
+-#define CS_BUS_SLOT_SZ	BIT_8S		/* Slot Size 0/1 = 32/64 bit slot */
+-#define CS_ST_SW_IRQ	BIT_7S		/* Set IRQ SW Request */
+-#define CS_CL_SW_IRQ	BIT_6S		/* Clear IRQ SW Request */
+-#define CS_STOP_DONE	BIT_5S		/* Stop Master is finished */
+-#define CS_STOP_MAST	BIT_4S		/* Command Bit to stop the master */
+-#define CS_MRST_CLR		BIT_3S		/* Clear Master reset	*/
+-#define CS_MRST_SET		BIT_2S		/* Set Master reset	*/
+-#define CS_RST_CLR		BIT_1S		/* Clear Software reset	*/
+-#define CS_RST_SET		BIT_0S		/* Set   Software reset	*/
+-
+-/*	B0_LED			 8 Bit	LED register */
+-								/* Bit  7.. 2:	reserved */
+-#define LED_STAT_ON		BIT_1S		/* Status LED on	*/
+-#define LED_STAT_OFF	BIT_0S		/* Status LED off	*/
+-
+-/*	B0_POWER_CTRL	 8 Bit	Power Control reg (YUKON only) */
+-#define PC_VAUX_ENA		BIT_7		/* Switch VAUX Enable  */
+-#define PC_VAUX_DIS		BIT_6       /* Switch VAUX Disable */
+-#define PC_VCC_ENA		BIT_5       /* Switch VCC Enable  */
+-#define PC_VCC_DIS		BIT_4       /* Switch VCC Disable */
+-#define PC_VAUX_ON		BIT_3       /* Switch VAUX On  */
+-#define PC_VAUX_OFF		BIT_2       /* Switch VAUX Off */
+-#define PC_VCC_ON		BIT_1       /* Switch VCC On  */
+-#define PC_VCC_OFF		BIT_0       /* Switch VCC Off */
+-
+-/*	B0_ISRC			32 bit	Interrupt Source Register */
+-/*	B0_IMSK			32 bit	Interrupt Mask Register */
+-/*	B0_SP_ISRC		32 bit	Special Interrupt Source Reg */
+-/*	B2_IRQM_MSK 	32 bit	IRQ Moderation Mask */
+-#define IS_ALL_MSK		0xbfffffffUL	/* All Interrupt bits */
+-#define IS_HW_ERR		BIT_31		/* Interrupt HW Error */
+-								/* Bit 30:	reserved */
+-#define IS_PA_TO_RX1	BIT_29		/* Packet Arb Timeout Rx1 */
+-#define IS_PA_TO_RX2	BIT_28		/* Packet Arb Timeout Rx2 */
+-#define IS_PA_TO_TX1	BIT_27		/* Packet Arb Timeout Tx1 */
+-#define IS_PA_TO_TX2	BIT_26		/* Packet Arb Timeout Tx2 */
+-#define IS_I2C_READY	BIT_25		/* IRQ on end of I2C Tx */
+-#define IS_IRQ_SW		BIT_24		/* SW forced IRQ	*/
+-#define IS_EXT_REG		BIT_23		/* IRQ from LM80 or PHY (GENESIS only) */
+-									/* IRQ from PHY (YUKON only) */
+-#define IS_TIMINT		BIT_22		/* IRQ from Timer	*/
+-#define IS_MAC1			BIT_21		/* IRQ from MAC 1	*/
+-#define IS_LNK_SYNC_M1	BIT_20		/* Link Sync Cnt wrap MAC 1 */
+-#define IS_MAC2			BIT_19		/* IRQ from MAC 2	*/
+-#define IS_LNK_SYNC_M2	BIT_18		/* Link Sync Cnt wrap MAC 2 */
+-/* Receive Queue 1 */
+-#define IS_R1_B			BIT_17		/* Q_R1 End of Buffer */
+-#define IS_R1_F			BIT_16		/* Q_R1 End of Frame */
+-#define IS_R1_C			BIT_15		/* Q_R1 Encoding Error */
+-/* Receive Queue 2 */
+-#define IS_R2_B			BIT_14		/* Q_R2 End of Buffer */
+-#define IS_R2_F			BIT_13		/* Q_R2 End of Frame */
+-#define IS_R2_C			BIT_12		/* Q_R2 Encoding Error */
+-/* Synchronous Transmit Queue 1 */
+-#define IS_XS1_B		BIT_11		/* Q_XS1 End of Buffer */
+-#define IS_XS1_F		BIT_10		/* Q_XS1 End of Frame */
+-#define IS_XS1_C		BIT_9		/* Q_XS1 Encoding Error */
+-/* Asynchronous Transmit Queue 1 */
+-#define IS_XA1_B		BIT_8		/* Q_XA1 End of Buffer */
+-#define IS_XA1_F		BIT_7		/* Q_XA1 End of Frame */
+-#define IS_XA1_C		BIT_6		/* Q_XA1 Encoding Error */
+-/* Synchronous Transmit Queue 2 */
+-#define IS_XS2_B		BIT_5		/* Q_XS2 End of Buffer */
+-#define IS_XS2_F		BIT_4		/* Q_XS2 End of Frame */
+-#define IS_XS2_C		BIT_3		/* Q_XS2 Encoding Error */
+-/* Asynchronous Transmit Queue 2 */
+-#define IS_XA2_B		BIT_2		/* Q_XA2 End of Buffer */
+-#define IS_XA2_F		BIT_1		/* Q_XA2 End of Frame */
+-#define IS_XA2_C		BIT_0		/* Q_XA2 Encoding Error */
+-
+-
+-/*	B0_HWE_ISRC		32 bit	HW Error Interrupt Src Reg */
+-/*	B0_HWE_IMSK		32 bit	HW Error Interrupt Mask Reg */
+-/*	B2_IRQM_HWE_MSK	32 bit	IRQ Moderation HW Error Mask */
+-#define IS_ERR_MSK		0x00000fffL	/* 		All Error bits */
+-								/* Bit 31..14:	reserved */
+-#define IS_IRQ_TIST_OV	BIT_13	/* Time Stamp Timer Overflow (YUKON only) */
+-#define IS_IRQ_SENSOR	BIT_12	/* IRQ from Sensor (YUKON only) */
+-#define IS_IRQ_MST_ERR	BIT_11	/* IRQ master error detected */
+-#define IS_IRQ_STAT		BIT_10	/* IRQ status exception */
+-#define IS_NO_STAT_M1	BIT_9	/* No Rx Status from MAC 1 */
+-#define IS_NO_STAT_M2	BIT_8	/* No Rx Status from MAC 2 */
+-#define IS_NO_TIST_M1	BIT_7	/* No Time Stamp from MAC 1 */
+-#define IS_NO_TIST_M2	BIT_6	/* No Time Stamp from MAC 2 */
+-#define IS_RAM_RD_PAR	BIT_5	/* RAM Read  Parity Error */
+-#define IS_RAM_WR_PAR	BIT_4	/* RAM Write Parity Error */
+-#define IS_M1_PAR_ERR	BIT_3	/* MAC 1 Parity Error */
+-#define IS_M2_PAR_ERR	BIT_2	/* MAC 2 Parity Error */
+-#define IS_R1_PAR_ERR	BIT_1	/* Queue R1 Parity Error */
+-#define IS_R2_PAR_ERR	BIT_0	/* Queue R2 Parity Error */
+-
+-/*	B2_CONN_TYP		 8 bit	Connector type */
+-/*	B2_PMD_TYP		 8 bit	PMD type */
+-/*	Values of connector and PMD type comply to SysKonnect internal std */
+-
+-/*	B2_MAC_CFG		 8 bit	MAC Configuration / Chip Revision */
+-#define CFG_CHIP_R_MSK	(0xf<<4)	/* Bit 7.. 4: Chip Revision */
+-									/* Bit 3.. 2:	reserved */
+-#define CFG_DIS_M2_CLK	BIT_1S		/* Disable Clock for 2nd MAC */
+-#define CFG_SNG_MAC		BIT_0S		/* MAC Config: 0=2 MACs / 1=1 MAC*/
+-
+-/*	B2_CHIP_ID		 8 bit 	Chip Identification Number */
+-#define CHIP_ID_GENESIS		0x0a	/* Chip ID for GENESIS */
+-#define CHIP_ID_YUKON		0xb0	/* Chip ID for YUKON */
+-#define CHIP_ID_YUKON_LITE	0xb1	/* Chip ID for YUKON-Lite (Rev. A1-A3) */
+-#define CHIP_ID_YUKON_LP	0xb2	/* Chip ID for YUKON-LP */
+-
+-#define CHIP_REV_YU_LITE_A1	3		/* Chip Rev. for YUKON-Lite A1,A2 */
+-#define CHIP_REV_YU_LITE_A3	7		/* Chip Rev. for YUKON-Lite A3 */
+-
+-/*	B2_FAR			32 bit	Flash-Prom Addr Reg/Cnt */
+-#define FAR_ADDR		0x1ffffL	/* Bit 16.. 0:	FPROM Address mask */
+-
+-/*	B2_LD_CTRL		 8 bit	EPROM loader control register */
+-/*	Bits are currently reserved */
+-
+-/*	B2_LD_TEST		 8 bit	EPROM loader test register */
+-								/* Bit 7.. 4:	reserved */
+-#define LD_T_ON			BIT_3S	/* Loader Test mode on */
+-#define LD_T_OFF		BIT_2S	/* Loader Test mode off */
+-#define LD_T_STEP		BIT_1S	/* Decrement FPROM addr. Counter */
+-#define LD_START		BIT_0S	/* Start loading FPROM */
+-
+-/*
+- *	Timer Section
+- */
+-/*	B2_TI_CTRL		 8 bit	Timer control */
+-/*	B2_IRQM_CTRL	 8 bit	IRQ Moderation Timer Control */
+-								/* Bit 7.. 3:	reserved */
+-#define TIM_START		BIT_2S	/* Start Timer */
+-#define TIM_STOP		BIT_1S	/* Stop  Timer */
+-#define TIM_CLR_IRQ		BIT_0S	/* Clear Timer IRQ (!IRQM) */
+-
+-/*	B2_TI_TEST		 8 Bit	Timer Test */
+-/*	B2_IRQM_TEST	 8 bit	IRQ Moderation Timer Test */
+-/*	B28_DPT_TST		 8 bit	Descriptor Poll Timer Test Reg */
+-								/* Bit 7.. 3:	reserved */
+-#define TIM_T_ON		BIT_2S	/* Test mode on */
+-#define TIM_T_OFF		BIT_1S	/* Test mode off */
+-#define TIM_T_STEP		BIT_0S	/* Test step */
+-
+-/*	B28_DPT_INI	32 bit	Descriptor Poll Timer Init Val */
+-/*	B28_DPT_VAL	32 bit	Descriptor Poll Timer Curr Val */
+-								/* Bit 31..24:	reserved */
+-#define DPT_MSK		0x00ffffffL	/* Bit 23.. 0:	Desc Poll Timer Bits */
+-
+-/*	B28_DPT_CTRL	 8 bit	Descriptor Poll Timer Ctrl Reg */
+-								/* Bit  7.. 2:	reserved */
+-#define DPT_START		BIT_1S	/* Start Descriptor Poll Timer */
+-#define DPT_STOP		BIT_0S	/* Stop  Descriptor Poll Timer */
+-
+-/*	B2_E_3			 8 bit 	lower 4 bits used for HW self test result */
+-#define B2_E3_RES_MASK	0x0f
+-
+-/*	B2_TST_CTRL1	 8 bit	Test Control Register 1 */
+-#define TST_FRC_DPERR_MR	BIT_7S	/* force DATAPERR on MST RD */
+-#define TST_FRC_DPERR_MW	BIT_6S	/* force DATAPERR on MST WR */
+-#define TST_FRC_DPERR_TR	BIT_5S	/* force DATAPERR on TRG RD */
+-#define TST_FRC_DPERR_TW	BIT_4S	/* force DATAPERR on TRG WR */
+-#define TST_FRC_APERR_M		BIT_3S	/* force ADDRPERR on MST */
+-#define TST_FRC_APERR_T		BIT_2S	/* force ADDRPERR on TRG */
+-#define TST_CFG_WRITE_ON	BIT_1S	/* Enable  Config Reg WR */
+-#define TST_CFG_WRITE_OFF	BIT_0S	/* Disable Config Reg WR */
+-
+-/*	B2_TST_CTRL2	 8 bit	Test Control Register 2 */
+-									/* Bit 7.. 4:	reserved */
+-			/* force the following error on the next master read/write	*/
+-#define TST_FRC_DPERR_MR64	BIT_3S	/* DataPERR RD 64	*/
+-#define TST_FRC_DPERR_MW64	BIT_2S	/* DataPERR WR 64	*/
+-#define TST_FRC_APERR_1M64	BIT_1S	/* AddrPERR on 1. phase */
+-#define TST_FRC_APERR_2M64	BIT_0S	/* AddrPERR on 2. phase */
+-
+-/*	B2_GP_IO		32 bit	General Purpose I/O Register */
+-							/* Bit 31..26:	reserved */
+-#define GP_DIR_9	BIT_25	/* IO_9 direct, 0=In/1=Out */
+-#define GP_DIR_8	BIT_24	/* IO_8 direct, 0=In/1=Out */
+-#define GP_DIR_7	BIT_23	/* IO_7 direct, 0=In/1=Out */
+-#define GP_DIR_6	BIT_22	/* IO_6 direct, 0=In/1=Out */
+-#define GP_DIR_5	BIT_21	/* IO_5 direct, 0=In/1=Out */
+-#define GP_DIR_4	BIT_20	/* IO_4 direct, 0=In/1=Out */
+-#define GP_DIR_3	BIT_19	/* IO_3 direct, 0=In/1=Out */
+-#define GP_DIR_2	BIT_18	/* IO_2 direct, 0=In/1=Out */
+-#define GP_DIR_1	BIT_17	/* IO_1 direct, 0=In/1=Out */
+-#define GP_DIR_0	BIT_16	/* IO_0 direct, 0=In/1=Out */
+-						/* Bit 15..10:	reserved */
+-#define GP_IO_9		BIT_9	/* IO_9 pin */
+-#define GP_IO_8		BIT_8	/* IO_8 pin */
+-#define GP_IO_7		BIT_7	/* IO_7 pin */
+-#define GP_IO_6		BIT_6	/* IO_6 pin */
+-#define GP_IO_5		BIT_5	/* IO_5 pin */
+-#define GP_IO_4		BIT_4	/* IO_4 pin */
+-#define GP_IO_3		BIT_3	/* IO_3 pin */
+-#define GP_IO_2		BIT_2	/* IO_2 pin */
+-#define GP_IO_1		BIT_1	/* IO_1 pin */
+-#define GP_IO_0		BIT_0	/* IO_0 pin */
+-
+-/*	B2_I2C_CTRL		32 bit	I2C HW Control Register */
+-#define I2C_FLAG		BIT_31		/* Start read/write if WR */
+-#define I2C_ADDR		(0x7fffL<<16)	/* Bit 30..16:	Addr to be RD/WR */
+-#define I2C_DEV_SEL		(0x7fL<<9)		/* Bit 15.. 9:	I2C Device Select */
+-								/* Bit	8.. 5:	reserved	*/
+-#define I2C_BURST_LEN	BIT_4		/* Burst Len, 1/4 bytes */
+-#define I2C_DEV_SIZE	(7<<1)		/* Bit	3.. 1:	I2C Device Size	*/
+-#define I2C_025K_DEV	(0<<1)		/*		0: 256 Bytes or smal. */
+-#define I2C_05K_DEV		(1<<1)		/* 		1: 512	Bytes	*/
+-#define I2C_1K_DEV		(2<<1)		/*		2: 1024 Bytes	*/
+-#define I2C_2K_DEV		(3<<1)		/*		3: 2048	Bytes	*/
+-#define I2C_4K_DEV		(4<<1)		/*		4: 4096 Bytes	*/
+-#define I2C_8K_DEV		(5<<1)		/*		5: 8192 Bytes	*/
+-#define I2C_16K_DEV		(6<<1)		/*		6: 16384 Bytes	*/
+-#define I2C_32K_DEV		(7<<1)		/*		7: 32768 Bytes	*/
+-#define I2C_STOP		BIT_0		/* Interrupt I2C transfer */
+-
+-/*	B2_I2C_IRQ		32 bit	I2C HW IRQ Register */
+-								/* Bit 31.. 1	reserved */
+-#define I2C_CLR_IRQ		BIT_0	/* Clear I2C IRQ */
+-
+-/*	B2_I2C_SW		32 bit (8 bit access)	I2C HW SW Port Register */
+-								/* Bit  7.. 3:	reserved */
+-#define I2C_DATA_DIR	BIT_2S		/* direction of I2C_DATA */
+-#define I2C_DATA		BIT_1S		/* I2C Data Port	*/
+-#define I2C_CLK			BIT_0S		/* I2C Clock Port	*/
+-
+-/*
+- * I2C Address
+- */
+-#define I2C_SENS_ADDR	LM80_ADDR	/* I2C Sensor Address, (Volt and Temp)*/
+-
+-
+-/*	B2_BSC_CTRL		 8 bit	Blink Source Counter Control */
+-							/* Bit  7.. 2:	reserved */
+-#define BSC_START	BIT_1S		/* Start Blink Source Counter */
+-#define BSC_STOP	BIT_0S		/* Stop  Blink Source Counter */
+-
+-/*	B2_BSC_STAT		 8 bit	Blink Source Counter Status */
+-							/* Bit  7.. 1:	reserved */
+-#define BSC_SRC		BIT_0S		/* Blink Source, 0=Off / 1=On */
+-
+-/*	B2_BSC_TST		16 bit	Blink Source Counter Test Reg */
+-#define BSC_T_ON	BIT_2S		/* Test mode on */
+-#define BSC_T_OFF	BIT_1S		/* Test mode off */
+-#define BSC_T_STEP	BIT_0S		/* Test step */
+-
+-
+-/*	B3_RAM_ADDR		32 bit	RAM Address, to read or write */
+-					/* Bit 31..19:	reserved */
+-#define RAM_ADR_RAN	0x0007ffffL	/* Bit 18.. 0:	RAM Address Range */
+-
+-/* RAM Interface Registers */
+-/*	B3_RI_CTRL		16 bit	RAM Iface Control Register */
+-								/* Bit 15..10:	reserved */
+-#define RI_CLR_RD_PERR	BIT_9S	/* Clear IRQ RAM Read Parity Err */
+-#define RI_CLR_WR_PERR	BIT_8S	/* Clear IRQ RAM Write Parity Err*/
+-								/* Bit	7.. 2:	reserved */
+-#define RI_RST_CLR		BIT_1S	/* Clear RAM Interface Reset */
+-#define RI_RST_SET		BIT_0S	/* Set   RAM Interface Reset */
+-
+-/*	B3_RI_TEST		 8 bit	RAM Iface Test Register */
+-								/* Bit 15.. 4:	reserved */
+-#define RI_T_EV			BIT_3S	/* Timeout Event occured */
+-#define RI_T_ON			BIT_2S	/* Timeout Timer Test On */
+-#define RI_T_OFF		BIT_1S	/* Timeout Timer Test Off */
+-#define RI_T_STEP		BIT_0S	/* Timeout Timer Step */
+-
+-/* MAC Arbiter Registers */
+-/*	B3_MA_TO_CTRL	16 bit	MAC Arbiter Timeout Ctrl Reg */
+-								/* Bit 15.. 4:	reserved */
+-#define MA_FOE_ON		BIT_3S	/* XMAC Fast Output Enable ON */
+-#define MA_FOE_OFF		BIT_2S	/* XMAC Fast Output Enable OFF */
+-#define MA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
+-#define MA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
+-
+-/*	B3_MA_RC_CTRL	16 bit	MAC Arbiter Recovery Ctrl Reg */
+-								/* Bit 15.. 8:	reserved */
+-#define MA_ENA_REC_TX2	BIT_7S	/* Enable  Recovery Timer TX2 */
+-#define MA_DIS_REC_TX2	BIT_6S	/* Disable Recovery Timer TX2 */
+-#define MA_ENA_REC_TX1	BIT_5S	/* Enable  Recovery Timer TX1 */
+-#define MA_DIS_REC_TX1	BIT_4S	/* Disable Recovery Timer TX1 */
+-#define MA_ENA_REC_RX2	BIT_3S	/* Enable  Recovery Timer RX2 */
+-#define MA_DIS_REC_RX2	BIT_2S	/* Disable Recovery Timer RX2 */
+-#define MA_ENA_REC_RX1	BIT_1S	/* Enable  Recovery Timer RX1 */
+-#define MA_DIS_REC_RX1	BIT_0S	/* Disable Recovery Timer RX1 */
+-
+-/* Packet Arbiter Registers */
+-/*	B3_PA_CTRL		16 bit	Packet Arbiter Ctrl Register */
+-								/* Bit 15..14:	reserved */
+-#define PA_CLR_TO_TX2	BIT_13S	/* Clear IRQ Packet Timeout TX2 */
+-#define PA_CLR_TO_TX1	BIT_12S	/* Clear IRQ Packet Timeout TX1 */
+-#define PA_CLR_TO_RX2	BIT_11S	/* Clear IRQ Packet Timeout RX2 */
+-#define PA_CLR_TO_RX1	BIT_10S	/* Clear IRQ Packet Timeout RX1 */
+-#define PA_ENA_TO_TX2	BIT_9S	/* Enable  Timeout Timer TX2 */
+-#define PA_DIS_TO_TX2	BIT_8S	/* Disable Timeout Timer TX2 */
+-#define PA_ENA_TO_TX1	BIT_7S	/* Enable  Timeout Timer TX1 */
+-#define PA_DIS_TO_TX1	BIT_6S	/* Disable Timeout Timer TX1 */
+-#define PA_ENA_TO_RX2	BIT_5S	/* Enable  Timeout Timer RX2 */
+-#define PA_DIS_TO_RX2	BIT_4S	/* Disable Timeout Timer RX2 */
+-#define PA_ENA_TO_RX1	BIT_3S	/* Enable  Timeout Timer RX1 */
+-#define PA_DIS_TO_RX1	BIT_2S	/* Disable Timeout Timer RX1 */
+-#define PA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
+-#define PA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
+-
+-#define PA_ENA_TO_ALL	(PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
+-						PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
+-
+-/* Rx/Tx Path related Arbiter Test Registers */
+-/*	B3_MA_TO_TEST	16 bit	MAC Arbiter Timeout Test Reg */
+-/*	B3_MA_RC_TEST	16 bit	MAC Arbiter Recovery Test Reg */
+-/*	B3_PA_TEST		16 bit	Packet Arbiter Test Register */
+-/*			Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
+-#define TX2_T_EV	BIT_15S		/* TX2 Timeout/Recv Event occured */
+-#define TX2_T_ON	BIT_14S		/* TX2 Timeout/Recv Timer Test On */
+-#define TX2_T_OFF	BIT_13S		/* TX2 Timeout/Recv Timer Tst Off */
+-#define TX2_T_STEP	BIT_12S		/* TX2 Timeout/Recv Timer Step */
+-#define TX1_T_EV	BIT_11S		/* TX1 Timeout/Recv Event occured */
+-#define TX1_T_ON	BIT_10S		/* TX1 Timeout/Recv Timer Test On */
+-#define TX1_T_OFF	BIT_9S		/* TX1 Timeout/Recv Timer Tst Off */
+-#define TX1_T_STEP	BIT_8S		/* TX1 Timeout/Recv Timer Step */
+-#define RX2_T_EV	BIT_7S		/* RX2 Timeout/Recv Event occured */
+-#define RX2_T_ON	BIT_6S		/* RX2 Timeout/Recv Timer Test On */
+-#define RX2_T_OFF	BIT_5S		/* RX2 Timeout/Recv Timer Tst Off */
+-#define RX2_T_STEP	BIT_4S		/* RX2 Timeout/Recv Timer Step */
+-#define RX1_T_EV	BIT_3S		/* RX1 Timeout/Recv Event occured */
+-#define RX1_T_ON	BIT_2S		/* RX1 Timeout/Recv Timer Test On */
+-#define RX1_T_OFF	BIT_1S		/* RX1 Timeout/Recv Timer Tst Off */
+-#define RX1_T_STEP	BIT_0S		/* RX1 Timeout/Recv Timer Step */
+-
+-
+-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+-/*	TXA_ITI_INI		32 bit	Tx Arb Interval Timer Init Val */
+-/*	TXA_ITI_VAL		32 bit	Tx Arb Interval Timer Value */
+-/*	TXA_LIM_INI		32 bit	Tx Arb Limit Counter Init Val */
+-/*	TXA_LIM_VAL		32 bit	Tx Arb Limit Counter Value */
+-								/* Bit 31..24:	reserved */
+-#define TXA_MAX_VAL	0x00ffffffUL/* Bit 23.. 0:	Max TXA Timer/Cnt Val */
+-
+-/*	TXA_CTRL		 8 bit	Tx Arbiter Control Register */
+-#define TXA_ENA_FSYNC	BIT_7S	/* Enable  force of sync Tx queue */
+-#define TXA_DIS_FSYNC	BIT_6S	/* Disable force of sync Tx queue */
+-#define TXA_ENA_ALLOC	BIT_5S	/* Enable  alloc of free bandwidth */
+-#define TXA_DIS_ALLOC	BIT_4S	/* Disable alloc of free bandwidth */
+-#define TXA_START_RC	BIT_3S	/* Start sync Rate Control */
+-#define TXA_STOP_RC		BIT_2S	/* Stop  sync Rate Control */
+-#define TXA_ENA_ARB		BIT_1S	/* Enable  Tx Arbiter */
+-#define TXA_DIS_ARB		BIT_0S	/* Disable Tx Arbiter */
+-
+-/*	TXA_TEST		 8 bit	Tx Arbiter Test Register */
+-								/* Bit 7.. 6:	reserved */
+-#define TXA_INT_T_ON	BIT_5S	/* Tx Arb Interval Timer Test On */
+-#define TXA_INT_T_OFF	BIT_4S	/* Tx Arb Interval Timer Test Off */
+-#define TXA_INT_T_STEP	BIT_3S	/* Tx Arb Interval Timer Step */
+-#define TXA_LIM_T_ON	BIT_2S	/* Tx Arb Limit Timer Test On */
+-#define TXA_LIM_T_OFF	BIT_1S	/* Tx Arb Limit Timer Test Off */
+-#define TXA_LIM_T_STEP	BIT_0S	/* Tx Arb Limit Timer Step */
+-
+-/*	TXA_STAT		 8 bit	Tx Arbiter Status Register */
+-								/* Bit 7.. 1:	reserved */
+-#define TXA_PRIO_XS		BIT_0S	/* sync queue has prio to send */
+-
+-/*	Q_BC			32 bit	Current Byte Counter */
+-								/* Bit 31..16:	reserved */
+-#define BC_MAX			0xffff	/* Bit 15.. 0:	Byte counter */
+-
+-/* BMU Control Status Registers */
+-/*	B0_R1_CSR		32 bit	BMU Ctrl/Stat Rx Queue 1 */
+-/*	B0_R2_CSR		32 bit	BMU Ctrl/Stat Rx Queue 2 */
+-/*	B0_XA1_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
+-/*	B0_XS1_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 1 */
+-/*	B0_XA2_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
+-/*	B0_XS2_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 2 */
+-/*	Q_CSR			32 bit	BMU Control/Status Register */
+-								/* Bit 31..25:	reserved */
+-#define CSR_SV_IDLE		BIT_24		/* BMU SM Idle */
+-								/* Bit 23..22:	reserved */
+-#define CSR_DESC_CLR	BIT_21		/* Clear Reset for Descr */
+-#define CSR_DESC_SET	BIT_20		/* Set   Reset for Descr */
+-#define CSR_FIFO_CLR	BIT_19		/* Clear Reset for FIFO */
+-#define CSR_FIFO_SET	BIT_18		/* Set   Reset for FIFO */
+-#define CSR_HPI_RUN		BIT_17		/* Release HPI SM */
+-#define CSR_HPI_RST		BIT_16		/* Reset   HPI SM to Idle */
+-#define CSR_SV_RUN		BIT_15		/* Release Supervisor SM */
+-#define CSR_SV_RST		BIT_14		/* Reset   Supervisor SM */
+-#define CSR_DREAD_RUN	BIT_13		/* Release Descr Read SM */
+-#define CSR_DREAD_RST	BIT_12		/* Reset   Descr Read SM */
+-#define CSR_DWRITE_RUN	BIT_11		/* Release Descr Write SM */
+-#define CSR_DWRITE_RST	BIT_10		/* Reset   Descr Write SM */
+-#define CSR_TRANS_RUN	BIT_9		/* Release Transfer SM */
+-#define CSR_TRANS_RST	BIT_8		/* Reset   Transfer SM */
+-#define CSR_ENA_POL		BIT_7		/* Enable  Descr Polling */
+-#define CSR_DIS_POL		BIT_6		/* Disable Descr Polling */
+-#define CSR_STOP		BIT_5		/* Stop  Rx/Tx Queue */
+-#define CSR_START		BIT_4		/* Start Rx/Tx Queue */
+-#define CSR_IRQ_CL_P	BIT_3		/* (Rx)	Clear Parity IRQ */
+-#define CSR_IRQ_CL_B	BIT_2		/* Clear EOB IRQ */
+-#define CSR_IRQ_CL_F	BIT_1		/* Clear EOF IRQ */
+-#define CSR_IRQ_CL_C	BIT_0		/* Clear ERR IRQ */
+-
+-#define CSR_SET_RESET	(CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
+-						CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
+-						CSR_TRANS_RST)
+-#define CSR_CLR_RESET	(CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
+-						CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
+-						CSR_TRANS_RUN)
+-
+-/*	Q_F				32 bit	Flag Register */
+-									/* Bit 31..28:	reserved */
+-#define F_ALM_FULL		BIT_27		/* Rx FIFO: almost full */
+-#define F_EMPTY			BIT_27		/* Tx FIFO: empty flag */
+-#define F_FIFO_EOF		BIT_26		/* Tag (EOF Flag) bit in FIFO */
+-#define F_WM_REACHED	BIT_25		/* Watermark reached */
+-									/* reserved */
+-#define F_FIFO_LEVEL	(0x1fL<<16)	/* Bit 23..16:	# of Qwords in FIFO */
+-									/* Bit 15..11: 	reserved */
+-#define F_WATER_MARK	0x0007ffL	/* Bit 10.. 0:	Watermark */
+-
+-/*	Q_T1			32 bit	Test Register 1 */
+-/*		Holds four State Machine control Bytes */
+-#define SM_CTRL_SV_MSK	(0xffL<<24)	/* Bit 31..24:	Control Supervisor SM */
+-#define SM_CTRL_RD_MSK	(0xffL<<16)	/* Bit 23..16:	Control Read Desc SM */
+-#define SM_CTRL_WR_MSK	(0xffL<<8)	/* Bit 15.. 8:	Control Write Desc SM */
+-#define SM_CTRL_TR_MSK	0xffL		/* Bit	7.. 0:	Control Transfer SM */
+-
+-/*	Q_T1_TR			 8 bit	Test Register 1 Transfer SM */
+-/*	Q_T1_WR			 8 bit	Test Register 1 Write Descriptor SM */
+-/*	Q_T1_RD			 8 bit	Test Register 1 Read Descriptor SM */
+-/*	Q_T1_SV			 8 bit	Test Register 1 Supervisor SM */
+-
+-/* The control status byte of each machine looks like ... */
+-#define SM_STATE		0xf0	/* Bit 7.. 4:	State which shall be loaded */
+-#define SM_LOAD			BIT_3S	/* Load the SM with SM_STATE */
+-#define SM_TEST_ON		BIT_2S	/* Switch on SM Test Mode */
+-#define SM_TEST_OFF		BIT_1S	/* Go off the Test Mode */
+-#define SM_STEP			BIT_0S	/* Step the State Machine */
+-/* The encoding of the states is not supported by the Diagnostics Tool */
+-
+-/*	Q_T2			32 bit	Test Register 2	*/
+-								/* Bit 31.. 8:	reserved */
+-#define T2_AC_T_ON		BIT_7	/* Address Counter Test Mode on */
+-#define T2_AC_T_OFF		BIT_6	/* Address Counter Test Mode off */
+-#define T2_BC_T_ON		BIT_5	/* Byte Counter Test Mode on */
+-#define T2_BC_T_OFF		BIT_4	/* Byte Counter Test Mode off */
+-#define T2_STEP04		BIT_3	/* Inc AC/Dec BC by 4 */
+-#define T2_STEP03		BIT_2	/* Inc AC/Dec BC by 3 */
+-#define T2_STEP02		BIT_1	/* Inc AC/Dec BC by 2 */
+-#define T2_STEP01		BIT_0	/* Inc AC/Dec BC by 1 */
+-
+-/*	Q_T3			32 bit	Test Register 3	*/
+-								/* Bit 31.. 7:	reserved */
+-#define T3_MUX_MSK		(7<<4)	/* Bit  6.. 4:	Mux Position */
+-								/* Bit  3:	reserved */
+-#define T3_VRAM_MSK		7		/* Bit  2.. 0:	Virtual RAM Buffer Address */
+-
+-/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+-/*	RB_START		32 bit	RAM Buffer Start Address */
+-/*	RB_END			32 bit	RAM Buffer End Address */
+-/*	RB_WP			32 bit	RAM Buffer Write Pointer */
+-/*	RB_RP			32 bit	RAM Buffer Read Pointer */
+-/*	RB_RX_UTPP		32 bit	Rx Upper Threshold, Pause Pack */
+-/*	RB_RX_LTPP		32 bit	Rx Lower Threshold, Pause Pack */
+-/*	RB_RX_UTHP		32 bit	Rx Upper Threshold, High Prio */
+-/*	RB_RX_LTHP		32 bit	Rx Lower Threshold, High Prio */
+-/*	RB_PC			32 bit	RAM Buffer Packet Counter */
+-/*	RB_LEV			32 bit	RAM Buffer Level Register */
+-				/* Bit 31..19:	reserved */
+-#define RB_MSK	0x0007ffff	/* Bit 18.. 0:	RAM Buffer Pointer Bits */
+-
+-/*	RB_TST2			 8 bit	RAM Buffer Test Register 2 */
+-								/* Bit 7.. 4:	reserved */
+-#define RB_PC_DEC		BIT_3S	/* Packet Counter Decrem */
+-#define RB_PC_T_ON		BIT_2S	/* Packet Counter Test On */
+-#define RB_PC_T_OFF		BIT_1S	/* Packet Counter Tst Off */
+-#define RB_PC_INC		BIT_0S	/* Packet Counter Increm */
+-
+-/*	RB_TST1			 8 bit	RAM Buffer Test Register 1 */
+-							/* Bit 7:	reserved */
+-#define RB_WP_T_ON		BIT_6S	/* Write Pointer Test On */
+-#define RB_WP_T_OFF		BIT_5S	/* Write Pointer Test Off */
+-#define RB_WP_INC		BIT_4S	/* Write Pointer Increm */
+-								/* Bit 3:	reserved */
+-#define RB_RP_T_ON		BIT_2S	/* Read Pointer Test On */
+-#define RB_RP_T_OFF		BIT_1S	/* Read Pointer Test Off */
+-#define RB_RP_DEC		BIT_0S	/* Read Pointer Decrement */
+-
+-/*	RB_CTRL			 8 bit	RAM Buffer Control Register */
+-								/* Bit 7.. 6:	reserved */
+-#define RB_ENA_STFWD	BIT_5S	/* Enable  Store & Forward */
+-#define RB_DIS_STFWD	BIT_4S	/* Disable Store & Forward */
+-#define RB_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
+-#define RB_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
+-#define RB_RST_CLR		BIT_1S	/* Clear RAM Buf STM Reset */
+-#define RB_RST_SET		BIT_0S	/* Set   RAM Buf STM Reset */
+-
+-
+-/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
+-
+-/*	RX_MFF_EA		32 bit	Receive MAC FIFO End Address */
+-/*	RX_MFF_WP		32 bit 	Receive MAC FIFO Write Pointer */
+-/*	RX_MFF_RP		32 bit	Receive MAC FIFO Read Pointer */
+-/*	RX_MFF_PC		32 bit	Receive MAC FIFO Packet Counter */
+-/*	RX_MFF_LEV		32 bit	Receive MAC FIFO Level */
+-/*	TX_MFF_EA		32 bit	Transmit MAC FIFO End Address */
+-/*	TX_MFF_WP		32 bit 	Transmit MAC FIFO Write Pointer */
+-/*	TX_MFF_WSP		32 bit	Transmit MAC FIFO WR Shadow Pointer */
+-/*	TX_MFF_RP		32 bit	Transmit MAC FIFO Read Pointer */
+-/*	TX_MFF_PC		32 bit	Transmit MAC FIFO Packet Cnt */
+-/*	TX_MFF_LEV		32 bit	Transmit MAC FIFO Level */
+-								/* Bit 31.. 6:	reserved */
+-#define MFF_MSK			0x007fL	/* Bit	5.. 0:	MAC FIFO Address/Ptr Bits */
+-
+-/*	RX_MFF_CTRL1	16 bit	Receive MAC FIFO Control Reg 1 */
+-								/* Bit 15..14:	reserved */
+-#define MFF_ENA_RDY_PAT	BIT_13S		/* Enable  Ready Patch */
+-#define MFF_DIS_RDY_PAT	BIT_12S		/* Disable Ready Patch */
+-#define MFF_ENA_TIM_PAT	BIT_11S		/* Enable  Timing Patch */
+-#define MFF_DIS_TIM_PAT	BIT_10S		/* Disable Timing Patch */
+-#define MFF_ENA_ALM_FUL	BIT_9S		/* Enable  AlmostFull Sign */
+-#define MFF_DIS_ALM_FUL	BIT_8S		/* Disable AlmostFull Sign */
+-#define MFF_ENA_PAUSE	BIT_7S		/* Enable  Pause Signaling */
+-#define MFF_DIS_PAUSE	BIT_6S		/* Disable Pause Signaling */
+-#define MFF_ENA_FLUSH	BIT_5S		/* Enable  Frame Flushing */
+-#define MFF_DIS_FLUSH	BIT_4S		/* Disable Frame Flushing */
+-#define MFF_ENA_TIST	BIT_3S		/* Enable  Time Stamp Gener */
+-#define MFF_DIS_TIST	BIT_2S		/* Disable Time Stamp Gener */
+-#define MFF_CLR_INTIST	BIT_1S		/* Clear IRQ No Time Stamp */
+-#define MFF_CLR_INSTAT	BIT_0S		/* Clear IRQ No Status */
+-
+-#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
+-
+-/*	TX_MFF_CTRL1	16 bit	Transmit MAC FIFO Control Reg 1 */
+-#define MFF_CLR_PERR	BIT_15S		/* Clear Parity Error IRQ */
+-								/* Bit 14:	reserved */
+-#define MFF_ENA_PKT_REC	BIT_13S		/* Enable  Packet Recovery */
+-#define MFF_DIS_PKT_REC BIT_12S		/* Disable Packet Recovery */
+-/*	MFF_ENA_TIM_PAT	 (see RX_MFF_CTRL1) Bit 11:	Enable  Timing Patch */
+-/*	MFF_DIS_TIM_PAT	 (see RX_MFF_CTRL1) Bit 10:	Disable Timing Patch */
+-/*	MFF_ENA_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 9:	Enable  Almost Full Sign */
+-/*	MFF_DIS_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 8:	Disable Almost Full Sign */
+-#define MFF_ENA_W4E		BIT_7S		/* Enable  Wait for Empty */
+-#define MFF_DIS_W4E		BIT_6S		/* Disable Wait for Empty */
+-/*	MFF_ENA_FLUSH	 (see RX_MFF_CTRL1) Bit	 5:	Enable  Frame Flushing */
+-/*	MFF_DIS_FLUSH	 (see RX_MFF_CTRL1) Bit	 4:	Disable Frame Flushing */
+-#define MFF_ENA_LOOPB	BIT_3S		/* Enable  Loopback */
+-#define MFF_DIS_LOOPB	BIT_2S		/* Disable Loopback */
+-#define MFF_CLR_MAC_RST	BIT_1S		/* Clear XMAC Reset */
+-#define MFF_SET_MAC_RST	BIT_0S		/* Set   XMAC Reset */
+-
+-#define MFF_TX_CTRL_DEF	(MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
+-
+-/*	RX_MFF_TST2	 	 8 bit	Receive MAC FIFO Test Register 2 */
+-/*	TX_MFF_TST2	 	 8 bit	Transmit MAC FIFO Test Register 2 */
+-								/* Bit 7:	reserved */
+-#define MFF_WSP_T_ON	BIT_6S	/* Tx: Write Shadow Ptr TestOn */
+-#define MFF_WSP_T_OFF	BIT_5S	/* Tx: Write Shadow Ptr TstOff */
+-#define MFF_WSP_INC		BIT_4S	/* Tx: Write Shadow Ptr Increment */
+-#define MFF_PC_DEC		BIT_3S	/* Packet Counter Decrement */
+-#define MFF_PC_T_ON		BIT_2S	/* Packet Counter Test On */
+-#define MFF_PC_T_OFF	BIT_1S	/* Packet Counter Test Off */
+-#define MFF_PC_INC		BIT_0S	/* Packet Counter Increment */
+-
+-/*	RX_MFF_TST1	 	 8 bit	Receive MAC FIFO Test Register 1 */
+-/*	TX_MFF_TST1	 	 8 bit	Transmit MAC FIFO Test Register 1 */
+-					/* Bit 7:	reserved */
+-#define MFF_WP_T_ON		BIT_6S	/* Write Pointer Test On */
+-#define MFF_WP_T_OFF	BIT_5S	/* Write Pointer Test Off */
+-#define MFF_WP_INC		BIT_4S	/* Write Pointer Increm */
+-							/* Bit 3:	reserved */
+-#define MFF_RP_T_ON		BIT_2S	/* Read Pointer Test On */
+-#define MFF_RP_T_OFF	BIT_1S	/* Read Pointer Test Off */
+-#define MFF_RP_DEC		BIT_0S	/* Read Pointer Decrement */
+-
+-/*	RX_MFF_CTRL2	 8 bit	Receive MAC FIFO Control Reg 2 */
+-/*	TX_MFF_CTRL2	 8 bit	Transmit MAC FIFO Control Reg 2 */
+-								/* Bit 7..4:	reserved */
+-#define MFF_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
+-#define MFF_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
+-#define MFF_RST_CLR		BIT_1S	/* Clear MAC FIFO Reset */
+-#define MFF_RST_SET		BIT_0S	/* Set   MAC FIFO Reset */
+-
+-
+-/*	Link LED Counter Registers (GENESIS only) */
+-
+-/*	RX_LED_CTRL		 8 bit	Receive LED Cnt Control Reg */
+-/*	TX_LED_CTRL		 8 bit	Transmit LED Cnt Control Reg */
+-/*	LNK_SYNC_CTRL	 8 bit	Link Sync Cnt Control Register */
+-							/* Bit 7.. 3:	reserved */
+-#define LED_START		BIT_2S	/* Start Timer */
+-#define LED_STOP		BIT_1S	/* Stop Timer */
+-#define LED_STATE		BIT_0S	/* Rx/Tx: LED State, 1=LED on */
+-#define LED_CLR_IRQ		BIT_0S	/* Lnk: 	Clear Link IRQ */
+-
+-/*	RX_LED_TST		 8 bit	Receive LED Cnt Test Register */
+-/*	TX_LED_TST		 8 bit	Transmit LED Cnt Test Register */
+-/*	LNK_SYNC_TST	 8 bit	Link Sync Cnt Test Register */
+-							/* Bit 7.. 3:	reserved */
+-#define LED_T_ON		BIT_2S	/* LED Counter Test mode On */
+-#define LED_T_OFF		BIT_1S	/* LED Counter Test mode Off */
+-#define LED_T_STEP		BIT_0S	/* LED Counter Step */
+-
+-/*	LNK_LED_REG	 	 8 bit	Link LED Register */
+-								/* Bit 7.. 6:	reserved */
+-#define LED_BLK_ON		BIT_5S	/* Link LED Blinking On */
+-#define LED_BLK_OFF		BIT_4S	/* Link LED Blinking Off */
+-#define LED_SYNC_ON		BIT_3S	/* Use Sync Wire to switch LED */
+-#define LED_SYNC_OFF	BIT_2S	/* Disable Sync Wire Input */
+-#define LED_ON			BIT_1S	/* switch LED on */
+-#define LED_OFF			BIT_0S	/* switch LED off */
+-
+-/*	Receive and Transmit GMAC FIFO Registers (YUKON only) */
+-
+-/*	RX_GMF_EA		32 bit	Rx GMAC FIFO End Address */
+-/*	RX_GMF_AF_THR	32 bit	Rx GMAC FIFO Almost Full Thresh. */
+-/*	RX_GMF_WP		32 bit 	Rx GMAC FIFO Write Pointer */
+-/*	RX_GMF_WLEV		32 bit 	Rx GMAC FIFO Write Level */
+-/*	RX_GMF_RP		32 bit 	Rx GMAC FIFO Read Pointer */
+-/*	RX_GMF_RLEV		32 bit 	Rx GMAC FIFO Read Level */
+-/*	TX_GMF_EA		32 bit	Tx GMAC FIFO End Address */
+-/*	TX_GMF_AE_THR	32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
+-/*	TX_GMF_WP		32 bit 	Tx GMAC FIFO Write Pointer */
+-/*	TX_GMF_WSP		32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
+-/*	TX_GMF_WLEV		32 bit 	Tx GMAC FIFO Write Level */
+-/*	TX_GMF_RP		32 bit 	Tx GMAC FIFO Read Pointer */
+-/*	TX_GMF_RSTP		32 bit 	Tx GMAC FIFO Restart Pointer */
+-/*	TX_GMF_RLEV		32 bit 	Tx GMAC FIFO Read Level */
+-
+-/*	RX_GMF_CTRL_T	32 bit	Rx GMAC FIFO Control/Test */
+-						/* Bits 31..15:	reserved */
+-#define GMF_WP_TST_ON	BIT_14		/* Write Pointer Test On */
+-#define GMF_WP_TST_OFF	BIT_13		/* Write Pointer Test Off */
+-#define GMF_WP_STEP		BIT_12		/* Write Pointer Step/Increment */
+-						/* Bit 11:	reserved */
+-#define GMF_RP_TST_ON	BIT_10		/* Read Pointer Test On */
+-#define GMF_RP_TST_OFF	BIT_9		/* Read Pointer Test Off */
+-#define GMF_RP_STEP		BIT_8		/* Read Pointer Step/Increment */
+-#define GMF_RX_F_FL_ON	BIT_7		/* Rx FIFO Flush Mode On */
+-#define GMF_RX_F_FL_OFF	BIT_6		/* Rx FIFO Flush Mode Off */
+-#define GMF_CLI_RX_FO	BIT_5		/* Clear IRQ Rx FIFO Overrun */
+-#define GMF_CLI_RX_FC	BIT_4		/* Clear IRQ Rx Frame Complete */
+-#define GMF_OPER_ON		BIT_3		/* Operational Mode On */
+-#define GMF_OPER_OFF	BIT_2		/* Operational Mode Off */
+-#define GMF_RST_CLR		BIT_1		/* Clear GMAC FIFO Reset */
+-#define GMF_RST_SET		BIT_0		/* Set   GMAC FIFO Reset */
+-
+-/*	TX_GMF_CTRL_T	32 bit	Tx GMAC FIFO Control/Test */
+-						/* Bits 31..19:	reserved */
+-#define GMF_WSP_TST_ON	BIT_18		/* Write Shadow Pointer Test On */
+-#define GMF_WSP_TST_OFF	BIT_17		/* Write Shadow Pointer Test Off */
+-#define GMF_WSP_STEP	BIT_16		/* Write Shadow Pointer Step/Increment */
+-						/* Bits 15..7: same as for RX_GMF_CTRL_T */
+-#define GMF_CLI_TX_FU	BIT_6		/* Clear IRQ Tx FIFO Underrun */
+-#define GMF_CLI_TX_FC	BIT_5		/* Clear IRQ Tx Frame Complete */
+-#define GMF_CLI_TX_PE	BIT_4		/* Clear IRQ Tx Parity Error */
+-						/* Bits 3..0: same as for RX_GMF_CTRL_T */
+-
+-#define GMF_RX_CTRL_DEF		(GMF_OPER_ON | GMF_RX_F_FL_ON)
+-#define GMF_TX_CTRL_DEF		GMF_OPER_ON
+-
+-#define RX_GMF_FL_THR_DEF	0x0a	/* Rx GMAC FIFO Flush Threshold default */
+-
+-/*	GMAC_TI_ST_CTRL	 8 bit	Time Stamp Timer Ctrl Reg (YUKON only) */
+-								/* Bit 7.. 3:	reserved */
+-#define GMT_ST_START	BIT_2S		/* Start Time Stamp Timer */
+-#define GMT_ST_STOP		BIT_1S		/* Stop  Time Stamp Timer */
+-#define GMT_ST_CLR_IRQ	BIT_0S		/* Clear Time Stamp Timer IRQ */
+-
+-/*	GMAC_CTRL		32 bit	GMAC Control Reg (YUKON only) */
+-						/* Bits 31.. 8:	reserved */
+-#define GMC_H_BURST_ON	BIT_7		/* Half Duplex Burst Mode On */
+-#define GMC_H_BURST_OFF	BIT_6		/* Half Duplex Burst Mode Off */
+-#define GMC_F_LOOPB_ON	BIT_5		/* FIFO Loopback On */
+-#define GMC_F_LOOPB_OFF	BIT_4		/* FIFO Loopback Off */
+-#define GMC_PAUSE_ON	BIT_3		/* Pause On */
+-#define GMC_PAUSE_OFF	BIT_2		/* Pause Off */
+-#define GMC_RST_CLR		BIT_1		/* Clear GMAC Reset */
+-#define GMC_RST_SET		BIT_0		/* Set   GMAC Reset */
+-
+-/*	GPHY_CTRL		32 bit	GPHY Control Reg (YUKON only) */
+-						/* Bits 31..29:	reserved */
+-#define GPC_SEL_BDT		BIT_28	/* Select Bi-Dir. Transfer for MDC/MDIO */
+-#define GPC_INT_POL_HI	BIT_27	/* IRQ Polarity is Active HIGH */
+-#define GPC_75_OHM		BIT_26	/* Use 75 Ohm Termination instead of 50 */
+-#define GPC_DIS_FC		BIT_25	/* Disable Automatic Fiber/Copper Detection */
+-#define GPC_DIS_SLEEP	BIT_24	/* Disable Energy Detect */
+-#define GPC_HWCFG_M_3	BIT_23	/* HWCFG_MODE[3] */
+-#define GPC_HWCFG_M_2	BIT_22	/* HWCFG_MODE[2] */
+-#define GPC_HWCFG_M_1	BIT_21	/* HWCFG_MODE[1] */
+-#define GPC_HWCFG_M_0	BIT_20	/* HWCFG_MODE[0] */
+-#define GPC_ANEG_0		BIT_19	/* ANEG[0] */
+-#define GPC_ENA_XC		BIT_18	/* Enable MDI crossover */
+-#define GPC_DIS_125		BIT_17	/* Disable 125 MHz clock */
+-#define GPC_ANEG_3		BIT_16	/* ANEG[3] */
+-#define GPC_ANEG_2		BIT_15	/* ANEG[2] */
+-#define GPC_ANEG_1		BIT_14	/* ANEG[1] */
+-#define GPC_ENA_PAUSE	BIT_13	/* Enable Pause (SYM_OR_REM) */
+-#define GPC_PHYADDR_4	BIT_12	/* Bit 4 of Phy Addr */
+-#define GPC_PHYADDR_3	BIT_11	/* Bit 3 of Phy Addr */
+-#define GPC_PHYADDR_2	BIT_10	/* Bit 2 of Phy Addr */
+-#define GPC_PHYADDR_1	BIT_9	/* Bit 1 of Phy Addr */
+-#define GPC_PHYADDR_0	BIT_8	/* Bit 0 of Phy Addr */
+-						/* Bits  7..2:	reserved */
+-#define GPC_RST_CLR		BIT_1	/* Clear GPHY Reset */
+-#define GPC_RST_SET		BIT_0	/* Set   GPHY Reset */
+-
+-#define GPC_HWCFG_GMII_COP	(GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \
+-							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+-
+-#define GPC_HWCFG_GMII_FIB	(				 GPC_HWCFG_M_2 | \
+-							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+-
+-#define GPC_ANEG_ADV_ALL_M	(GPC_ANEG_3 | GPC_ANEG_2 | \
+-							 GPC_ANEG_1 | GPC_ANEG_0)
+-
+-/* forced speed and duplex mode (don't mix with other ANEG bits) */
+-#define GPC_FRC10MBIT_HALF	0
+-#define GPC_FRC10MBIT_FULL	GPC_ANEG_0
+-#define GPC_FRC100MBIT_HALF	GPC_ANEG_1
+-#define GPC_FRC100MBIT_FULL	(GPC_ANEG_0 | GPC_ANEG_1)
+-
+-/* auto-negotiation with limited advertised speeds */
+-/* mix only with master/slave settings (for copper) */
+-#define GPC_ADV_1000_HALF	GPC_ANEG_2
+-#define GPC_ADV_1000_FULL	GPC_ANEG_3
+-#define GPC_ADV_ALL			(GPC_ANEG_2 | GPC_ANEG_3)
+-
+-/* master/slave settings */
+-/* only for copper with 1000 Mbps */
+-#define GPC_FORCE_MASTER	0
+-#define GPC_FORCE_SLAVE		GPC_ANEG_0
+-#define GPC_PREF_MASTER		GPC_ANEG_1
+-#define GPC_PREF_SLAVE		(GPC_ANEG_1 | GPC_ANEG_0)
+-
+-/*	GMAC_IRQ_SRC	 8 bit	GMAC Interrupt Source Reg (YUKON only) */
+-/*	GMAC_IRQ_MSK	 8 bit	GMAC Interrupt Mask   Reg (YUKON only) */
+-#define GM_IS_TX_CO_OV	BIT_5		/* Transmit Counter Overflow IRQ */
+-#define GM_IS_RX_CO_OV	BIT_4		/* Receive Counter Overflow IRQ */
+-#define GM_IS_TX_FF_UR	BIT_3		/* Transmit FIFO Underrun */
+-#define GM_IS_TX_COMPL	BIT_2		/* Frame Transmission Complete */
+-#define GM_IS_RX_FF_OR	BIT_1		/* Receive FIFO Overrun */
+-#define GM_IS_RX_COMPL	BIT_0		/* Frame Reception Complete */
+-
+-#define GMAC_DEF_MSK	(GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \
+-						GM_IS_TX_FF_UR)
+-
+-/*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
+-						/* Bits 15.. 2:	reserved */
+-#define GMLC_RST_CLR	BIT_1S		/* Clear GMAC Link Reset */
+-#define GMLC_RST_SET	BIT_0S		/* Set   GMAC Link Reset */
+-
+-
+-/*	WOL_CTRL_STAT	16 bit	WOL Control/Status Reg */
+-#define WOL_CTL_LINK_CHG_OCC			BIT_15S
+-#define WOL_CTL_MAGIC_PKT_OCC			BIT_14S
+-#define WOL_CTL_PATTERN_OCC				BIT_13S
+-
+-#define WOL_CTL_CLEAR_RESULT			BIT_12S
+-
+-#define WOL_CTL_ENA_PME_ON_LINK_CHG		BIT_11S
+-#define WOL_CTL_DIS_PME_ON_LINK_CHG		BIT_10S
+-#define WOL_CTL_ENA_PME_ON_MAGIC_PKT	BIT_9S
+-#define WOL_CTL_DIS_PME_ON_MAGIC_PKT	BIT_8S
+-#define WOL_CTL_ENA_PME_ON_PATTERN		BIT_7S
+-#define WOL_CTL_DIS_PME_ON_PATTERN		BIT_6S
+-
+-#define WOL_CTL_ENA_LINK_CHG_UNIT		BIT_5S
+-#define WOL_CTL_DIS_LINK_CHG_UNIT		BIT_4S
+-#define WOL_CTL_ENA_MAGIC_PKT_UNIT		BIT_3S
+-#define WOL_CTL_DIS_MAGIC_PKT_UNIT		BIT_2S
+-#define WOL_CTL_ENA_PATTERN_UNIT		BIT_1S
+-#define WOL_CTL_DIS_PATTERN_UNIT		BIT_0S
+-
+-#define WOL_CTL_DEFAULT				\
+-	(WOL_CTL_DIS_PME_ON_LINK_CHG |	\
+-	WOL_CTL_DIS_PME_ON_PATTERN |	\
+-	WOL_CTL_DIS_PME_ON_MAGIC_PKT |	\
+-	WOL_CTL_DIS_LINK_CHG_UNIT |		\
+-	WOL_CTL_DIS_PATTERN_UNIT |		\
+-	WOL_CTL_DIS_MAGIC_PKT_UNIT)
+-
+-/*	WOL_MATCH_CTL	 8 bit	WOL Match Control Reg */
+-#define WOL_CTL_PATT_ENA(x)				(BIT_0 << (x))
+-
+-#define SK_NUM_WOL_PATTERN		7
+-#define SK_PATTERN_PER_WORD		4
+-#define SK_BITMASK_PATTERN		7
+-#define SK_POW_PATTERN_LENGTH	128
+-
+-#define WOL_LENGTH_MSK		0x7f
+-#define WOL_LENGTH_SHIFT	8
+-
+-
+-/* Receive and Transmit Descriptors ******************************************/
+-
+-/* Transmit Descriptor struct */
+-typedef	struct s_HwTxd {
+-	SK_U32 volatile	TxCtrl;	/* Transmit Buffer Control Field */
+-	SK_U32	TxNext;			/* Physical Address Pointer to the next TxD */
+-	SK_U32	TxAdrLo;		/* Physical Tx Buffer Address lower dword */
+-	SK_U32	TxAdrHi;		/* Physical Tx Buffer Address upper dword */
+-	SK_U32	TxStat;			/* Transmit Frame Status Word */
+-#ifndef	SK_USE_REV_DESC
+-	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
+-	SK_U16	TxRes1;			/* 16 bit reserved field */
+-	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
+-	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
+-#else	/* SK_USE_REV_DESC */
+-	SK_U16	TxRes1;			/* 16 bit reserved field */
+-	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
+-	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
+-	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
+-#endif	/* SK_USE_REV_DESC */
+-	SK_U32  TxRes2;			/* 32 bit reserved field */
+-} SK_HWTXD;
+-
+-/* Receive Descriptor struct */
+-typedef	struct s_HwRxd {
+-	SK_U32 volatile RxCtrl;	/* Receive Buffer Control Field */
+-	SK_U32	RxNext;			/* Physical Address Pointer to the next RxD */
+-	SK_U32	RxAdrLo;		/* Physical Rx Buffer Address lower dword */
+-	SK_U32	RxAdrHi;		/* Physical Rx Buffer Address upper dword */
+-	SK_U32	RxStat;			/* Receive Frame Status Word */
+-	SK_U32	RxTiSt;			/* Receive Time Stamp (from XMAC on GENESIS) */
+-#ifndef	SK_USE_REV_DESC
+-	SK_U16	RxTcpSum1;		/* TCP Checksum 1 */
+-	SK_U16	RxTcpSum2;		/* TCP Checksum 2 */
+-	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
+-	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
+-#else	/* SK_USE_REV_DESC */
+-	SK_U16	RxTcpSum2;		/* TCP Checksum 2 */
+-	SK_U16	RxTcpSum1;		/* TCP Checksum 1 */
+-	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
+-	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
+-#endif	/* SK_USE_REV_DESC */
+-} SK_HWRXD;
+-
+-/*
+- * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2)
+- * should set the define SK_USE_REV_DESC.
+- * Structures are 'normaly' not endianess dependent. But in
+- * this case the SK_U16 fields are bound to bit positions inside the
+- * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord.
+- * The bit positions inside a DWord are of course endianess dependent and
+- * swaps if the DWord is swapped by the hardware.
+- */
+-
+-
+-/* Descriptor Bit Definition */
+-/*	TxCtrl		Transmit Buffer Control Field */
+-/*	RxCtrl		Receive  Buffer Control Field */
+-#define BMU_OWN			BIT_31	/* OWN bit: 0=host/1=BMU */
+-#define BMU_STF			BIT_30	/* Start of Frame */
+-#define BMU_EOF			BIT_29	/* End of Frame */
+-#define BMU_IRQ_EOB		BIT_28	/* Req "End of Buffer" IRQ */
+-#define BMU_IRQ_EOF		BIT_27	/* Req "End of Frame" IRQ */
+-/* TxCtrl specific bits */
+-#define BMU_STFWD		BIT_26	/* (Tx)	Store & Forward Frame */
+-#define BMU_NO_FCS		BIT_25	/* (Tx) Disable MAC FCS (CRC) generation */
+-#define BMU_SW			BIT_24	/* (Tx)	1 bit res. for SW use */
+-/* RxCtrl specific bits */
+-#define BMU_DEV_0		BIT_26	/* (Rx)	Transfer data to Dev0 */
+-#define BMU_STAT_VAL	BIT_25	/* (Rx)	Rx Status Valid */
+-#define BMU_TIST_VAL	BIT_24	/* (Rx)	Rx TimeStamp Valid */
+-								/* Bit 23..16:	BMU Check Opcodes */
+-#define BMU_CHECK		(0x55L<<16)	/* Default BMU check */
+-#define BMU_TCP_CHECK	(0x56L<<16)	/* Descr with TCP ext */
+-#define BMU_UDP_CHECK	(0x57L<<16)	/* Descr with UDP ext (YUKON only) */
+-#define BMU_BBC			0xffffL	/* Bit 15.. 0:	Buffer Byte Counter */
+-
+-/*	TxStat		Transmit Frame Status Word */
+-/*	RxStat		Receive Frame Status Word */
+-/*
+- *Note: TxStat is reserved for ASIC loopback mode only
+- *
+- *	The Bits of the Status words are defined in xmac_ii.h
+- *	(see XMR_FS bits)
+- */
+-
+-/* macros ********************************************************************/
+-
+-/* Receive and Transmit Queues */
+-#define Q_R1	0x0000		/* Receive Queue 1 */
+-#define Q_R2	0x0080		/* Receive Queue 2 */
+-#define Q_XS1	0x0200		/* Synchronous Transmit Queue 1 */
+-#define Q_XA1	0x0280		/* Asynchronous Transmit Queue 1 */
+-#define Q_XS2	0x0300		/* Synchronous Transmit Queue 2 */
+-#define Q_XA2	0x0380		/* Asynchronous Transmit Queue 2 */
+-
+-/*
+- *	Macro Q_ADDR()
+- *
+- *	Use this macro to access the Receive and Transmit Queue Registers.
+- *
+- * para:
+- *	Queue	Queue to access.
+- *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
+- *	Offs	Queue register offset.
+- *				Values: Q_D, Q_DA_L ... Q_T2, Q_T3
+- *
+- * usage	SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal)
+- */
+-#define Q_ADDR(Queue, Offs)	(B8_Q_REGS + (Queue) + (Offs))
+-
+-/*
+- *	Macro RB_ADDR()
+- *
+- *	Use this macro to access the RAM Buffer Registers.
+- *
+- * para:
+- *	Queue	Queue to access.
+- *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
+- *	Offs	Queue register offset.
+- *				Values: RB_START, RB_END ... RB_LEV, RB_CTRL
+- *
+- * usage	SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal)
+- */
+-#define RB_ADDR(Queue, Offs)	(B16_RAM_REGS + (Queue) + (Offs))
+-
+-
+-/* MAC Related Registers */
+-#define MAC_1		0	/* belongs to the port near the slot */
+-#define MAC_2		1	/* belongs to the port far away from the slot */
+-
+-/*
+- *	Macro MR_ADDR()
+- *
+- *	Use this macro to access a MAC Related Registers inside the ASIC.
+- *
+- * para:
+- *	Mac		MAC to access.
+- *				Values: MAC_1, MAC_2
+- *	Offs	MAC register offset.
+- *				Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG,
+- *						TX_MFF_EA, TX_MFF_WP ... TX_LED_TST
+- *
+- * usage	SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
+- */
+-#define MR_ADDR(Mac, Offs)	(((Mac) << 7) + (Offs))
+-
+-#ifdef	SK_LITTLE_ENDIAN
+-#define XM_WORD_LO	0
+-#define XM_WORD_HI	1
+-#else	/* !SK_LITTLE_ENDIAN */
+-#define XM_WORD_LO	1
+-#define XM_WORD_HI	0
+-#endif	/* !SK_LITTLE_ENDIAN */
+-
+-
+-/*
+- * macros to access the XMAC (GENESIS only)
+- *
+- * XM_IN16(),		to read a 16 bit register (e.g. XM_MMU_CMD)
+- * XM_OUT16(),		to write a 16 bit register (e.g. XM_MMU_CMD)
+- * XM_IN32(),		to read a 32 bit register (e.g. XM_TX_EV_CNT)
+- * XM_OUT32(),		to write a 32 bit register (e.g. XM_TX_EV_CNT)
+- * XM_INADDR(),		to read a network address register (e.g. XM_SRC_CHK)
+- * XM_OUTADDR(),	to write a network address register (e.g. XM_SRC_CHK)
+- * XM_INHASH(),		to read the XM_HSM_CHK register
+- * XM_OUTHASH()		to write the XM_HSM_CHK register
+- *
+- * para:
+- *	Mac		XMAC to access		values: MAC_1 or MAC_2
+- *	IoC		I/O context needed for SK I/O macros
+- *	Reg		XMAC Register to read or write
+- *	(p)Val	Value or pointer to the value which should be read or written
+- *
+- * usage:	XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value);
+- */
+-
+-#define XMA(Mac, Reg)									\
+-	((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1))
+-
+-#define XM_IN16(IoC, Mac, Reg, pVal)					\
+-	SK_IN16((IoC), XMA((Mac), (Reg)), (pVal))
+-
+-#define XM_OUT16(IoC, Mac, Reg, Val)					\
+-	SK_OUT16((IoC), XMA((Mac), (Reg)), (Val))
+-
+-#define XM_IN32(IoC, Mac, Reg, pVal) {					\
+-	SK_IN16((IoC), XMA((Mac), (Reg)),					\
+-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]);		\
+-	SK_IN16((IoC), XMA((Mac), (Reg+2)),					\
+-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]);		\
+-}
+-
+-#define XM_OUT32(IoC, Mac, Reg, Val) {										\
+-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL));			\
+-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\
+-}
+-
+-/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */
+-
+-#define XM_INADDR(IoC, Mac, Reg, pVal) {				\
+-	SK_U16	Word;										\
+-	SK_U8	*pByte;										\
+-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
+-	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
+-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word);			\
+-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word);			\
+-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-}
+-
+-#define XM_OUTADDR(IoC, Mac, Reg, pVal) {				\
+-	SK_U8	SK_FAR *pByte;								\
+-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
+-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
+-		(((SK_U16)(pByte[0]) & 0x00ff) |				\
+-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)		\
+-		(((SK_U16)(pByte[2]) & 0x00ff) |				\
+-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16)		\
+-		(((SK_U16)(pByte[4]) & 0x00ff) |				\
+-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
+-}
+-
+-#define XM_INHASH(IoC, Mac, Reg, pVal) {				\
+-	SK_U16	Word;										\
+-	SK_U8	SK_FAR *pByte;								\
+-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
+-	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
+-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word);			\
+-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word);			\
+-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word);			\
+-	pByte[6] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-}
+-
+-#define XM_OUTHASH(IoC, Mac, Reg, pVal) {				\
+-	SK_U8	SK_FAR *pByte;								\
+-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
+-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
+-		(((SK_U16)(pByte[0]) & 0x00ff)|					\
+-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)		\
+-		(((SK_U16)(pByte[2]) & 0x00ff)|					\
+-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16)		\
+-		(((SK_U16)(pByte[4]) & 0x00ff)|					\
+-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16)		\
+-		(((SK_U16)(pByte[6]) & 0x00ff)|					\
+-		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
+-}
+-
+-/*
+- * macros to access the GMAC (YUKON only)
+- *
+- * GM_IN16(),		to read  a 16 bit register (e.g. GM_GP_STAT)
+- * GM_OUT16(),		to write a 16 bit register (e.g. GM_GP_CTRL)
+- * GM_IN32(),		to read  a 32 bit register (e.g. GM_)
+- * GM_OUT32(),		to write a 32 bit register (e.g. GM_)
+- * GM_INADDR(),		to read  a network address register (e.g. GM_SRC_ADDR_1L)
+- * GM_OUTADDR(),	to write a network address register (e.g. GM_SRC_ADDR_2L)
+- * GM_INHASH(),		to read  the GM_MC_ADDR_H1 register
+- * GM_OUTHASH()		to write the GM_MC_ADDR_H1 register
+- *
+- * para:
+- *	Mac		GMAC to access		values: MAC_1 or MAC_2
+- *	IoC		I/O context needed for SK I/O macros
+- *	Reg		GMAC Register to read or write
+- *	(p)Val	Value or pointer to the value which should be read or written
+- *
+- * usage:	GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value);
+- */
+-
+-#define GMA(Mac, Reg)									\
+-	((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg))
+-
+-#define GM_IN16(IoC, Mac, Reg, pVal)					\
+-	SK_IN16((IoC), GMA((Mac), (Reg)), (pVal))
+-
+-#define GM_OUT16(IoC, Mac, Reg, Val)					\
+-	SK_OUT16((IoC), GMA((Mac), (Reg)), (Val))
+-
+-#define GM_IN32(IoC, Mac, Reg, pVal) {					\
+-	SK_IN16((IoC), GMA((Mac), (Reg)),					\
+-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]);		\
+-	SK_IN16((IoC), GMA((Mac), (Reg+4)),					\
+-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]);		\
+-}
+-
+-#define GM_OUT32(IoC, Mac, Reg, Val) {										\
+-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL));			\
+-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\
+-}
+-
+-#define GM_INADDR(IoC, Mac, Reg, pVal) {				\
+-	SK_U16	Word;										\
+-	SK_U8	*pByte;										\
+-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
+-	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);			\
+-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word);			\
+-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word);			\
+-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-}
+-
+-#define GM_OUTADDR(IoC, Mac, Reg, pVal) {				\
+-	SK_U8	SK_FAR *pByte;								\
+-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
+-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
+-		(((SK_U16)(pByte[0]) & 0x00ff) |				\
+-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)		\
+-		(((SK_U16)(pByte[2]) & 0x00ff) |				\
+-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16)		\
+-		(((SK_U16)(pByte[4]) & 0x00ff) |				\
+-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
+-}
+-
+-#define GM_INHASH(IoC, Mac, Reg, pVal) {				\
+-	SK_U16	Word;										\
+-	SK_U8	*pByte;										\
+-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
+-	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);			\
+-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word);			\
+-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word);			\
+-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-	SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word);		\
+-	pByte[6] = (SK_U8)(Word  & 0x00ff);					\
+-	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
+-}
+-
+-#define GM_OUTHASH(IoC, Mac, Reg, pVal) {				\
+-	SK_U8	*pByte;										\
+-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
+-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
+-		(((SK_U16)(pByte[0]) & 0x00ff)|					\
+-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)		\
+-		(((SK_U16)(pByte[2]) & 0x00ff)|					\
+-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16)		\
+-		(((SK_U16)(pByte[4]) & 0x00ff)|					\
+-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
+-	SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16)		\
+-		(((SK_U16)(pByte[6]) & 0x00ff)|					\
+-		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
+-}
+-
+-/*
+- * Different MAC Types
+- */
+-#define SK_MAC_XMAC		0	/* Xaqti XMAC II */
+-#define SK_MAC_GMAC		1	/* Marvell GMAC */
+-
+-/*
+- * Different PHY Types
+- */
+-#define SK_PHY_XMAC			0	/* integrated in XMAC II */
+-#define SK_PHY_BCOM			1	/* Broadcom BCM5400 */
+-#define SK_PHY_LONE			2	/* Level One LXT1000 */
+-#define SK_PHY_NAT			3	/* National DP83891 */
+-#define SK_PHY_MARV_COPPER	4	/* Marvell 88E1011S */
+-#define SK_PHY_MARV_FIBER	5	/* Marvell 88E1011S working on fiber */
+-
+-/*
+- * PHY addresses (bits 12..8 of PHY address reg)
+- */
+-#define PHY_ADDR_XMAC	(0<<8)
+-#define PHY_ADDR_BCOM	(1<<8)
+-#define PHY_ADDR_LONE	(3<<8)
+-#define PHY_ADDR_NAT	(0<<8)
+-
+-/* GPHY address (bits 15..11 of SMI control reg) */
+-#define PHY_ADDR_MARV	0
+-
+-/*
+- * macros to access the PHY
+- *
+- * PHY_READ()		read a 16 bit value from the PHY
+- * PHY_WRITE()		write a 16 bit value to the PHY
+- *
+- * para:
+- * 	IoC		I/O context needed for SK I/O macros
+- * 	pPort	Pointer to port struct for PhyAddr
+- * 	Mac		XMAC to access		values: MAC_1 or MAC_2
+- * 	PhyReg	PHY Register to read or write
+- * 	(p)Val	Value or pointer to the value which should be read or
+- *			written.
+- *
+- * usage:	PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value);
+- * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never
+- *          comes back. This is checked in DEBUG mode.
+- */
+-#ifndef DEBUG
+-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
+-	SK_U16 Mmu;  														\
+-																		\
+-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
+-	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
+-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
+-		do {  															\
+-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
+-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
+-		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
+-	}  																	\
+-}
+-#else
+-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
+-	SK_U16 Mmu;  														\
+-	int __i = 0;														\
+-																		\
+-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
+-	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
+-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
+-		do {  															\
+-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
+-			__i++;														\
+-			if (__i > 100000) {											\
+-				SK_DBG_PRINTF("*****************************\n");		\
+-				SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n");		\
+-				SK_DBG_PRINTF("*****************************\n");		\
+-				break;													\
+-			}															\
+-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
+-		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
+-	}  																	\
+-}
+-#endif /* DEBUG */
+-
+-#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) {						\
+-	SK_U16 Mmu;															\
+-																		\
+-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
+-		do {  															\
+-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
+-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
+-	}  																	\
+-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
+-	XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val));							\
+-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
+-		do {  															\
+-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
+-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
+-	}  																	\
+-}
+-
+-/*
+- *	Macro PCI_C()
+- *
+- *	Use this macro to access PCI config register from the I/O space.
+- *
+- * para:
+- *	Addr	PCI configuration register to access.
+- *			Values:	PCI_VENDOR_ID ... PCI_VPD_ADR_REG,
+- *
+- * usage	SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal);
+- */
+-#define PCI_C(Addr)	(B7_CFG_SPC + (Addr))	/* PCI Config Space */
+-
+-/*
+- *	Macro SK_HW_ADDR(Base, Addr)
+- *
+- *	Calculates the effective HW address
+- *
+- * para:
+- *	Base	I/O or memory base address
+- *	Addr	Address offset
+- *
+- * usage:	May be used in SK_INxx and SK_OUTxx macros
+- *		#define SK_IN8(pAC, Addr, pVal) ...\
+- *			*pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr)))
+- */
+-#ifdef SK_MEM_MAPPED_IO
+-#define SK_HW_ADDR(Base, Addr)	((Base) + (Addr))
+-#else  /* SK_MEM_MAPPED_IO */
+-#define SK_HW_ADDR(Base, Addr)	\
+-			((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0)))
+-#endif /* SK_MEM_MAPPED_IO */
+-
+-#define SZ_LONG	(sizeof(SK_U32))
+-
+-/*
+- *	Macro SK_HWAC_LINK_LED()
+- *
+- *	Use this macro to set the link LED mode.
+- * para:
+- *	pAC		Pointer to adapter context struct
+- *	IoC		I/O context needed for SK I/O macros
+- *  Port	Port number
+- *	Mode	Mode to set for this LED
+- */
+-#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \
+-	SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode);
+-
+-
+-/* typedefs *******************************************************************/
+-
+-
+-/* function prototypes ********************************************************/
+-
+-#ifdef __cplusplus
+-}
+-#endif	/* __cplusplus */
+-
+-#endif	/* __INC_SKGEHW_H */
+diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h
+deleted file mode 100644
+index e6b0016..0000000
+--- a/drivers/net/sk98lin/h/skgehwt.h
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skhwt.h
+- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version:	$Revision: 1.7 $
+- * Date:	$Date: 2003/09/16 12:55:08 $
+- * Purpose:	Defines for the hardware timer functions
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKGEHWT.H	contains all defines and types for the timer functions
+- */
+-
+-#ifndef	_SKGEHWT_H_
+-#define _SKGEHWT_H_
+-
+-/*
+- * SK Hardware Timer
+- * - needed wherever the HWT module is used
+- * - use in Adapters context name pAC->Hwt
+- */
+-typedef	struct s_Hwt {
+-	SK_U32		TStart;	/* HWT start */
+-	SK_U32		TStop;	/* HWT stop */
+-	int		TActive;	/* HWT: flag : active/inactive */
+-} SK_HWT;
+-
+-extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc);
+-extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time);
+-extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc);
+-extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc);
+-extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc);
+-#endif	/* _SKGEHWT_H_ */
+diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h
+deleted file mode 100644
+index d9b6f6d..0000000
+--- a/drivers/net/sk98lin/h/skgei2c.h
++++ /dev/null
+@@ -1,210 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skgei2c.h
+- * Project:	Gigabit Ethernet Adapters, TWSI-Module
+- * Version:	$Revision: 1.25 $
+- * Date:	$Date: 2003/10/20 09:06:05 $
+- * Purpose:	Special defines for TWSI
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKGEI2C.H	contains all SK-98xx specific defines for the TWSI handling
+- */
+-
+-#ifndef _INC_SKGEI2C_H_
+-#define _INC_SKGEI2C_H_
+-
+-/*
+- * Macros to access the B2_I2C_CTRL
+- */
+-#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
+-	SK_OUT32(IoC, B2_I2C_CTRL,\
+-		(flag ? 0x80000000UL : 0x0L) | \
+-		(((SK_U32)reg << 16) & I2C_ADDR) | \
+-		(((SK_U32)dev << 9) & I2C_DEV_SEL) | \
+-		(dev_size & I2C_DEV_SIZE) | \
+-		((burst << 4) & I2C_BURST_LEN))
+-
+-#define SK_I2C_STOP(IoC) {				\
+-	SK_U32	I2cCtrl;				\
+-	SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl);		\
+-	SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP);	\
+-}
+-
+-#define SK_I2C_GET_CTL(IoC, pI2cCtrl)	SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
+-
+-/*
+- * Macros to access the TWSI SW Registers
+- */
+-#define SK_I2C_SET_BIT(IoC, SetBits) {			\
+-	SK_U8	OrgBits;				\
+-	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
+-	SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits));	\
+-}
+-
+-#define SK_I2C_CLR_BIT(IoC, ClrBits) {			\
+-	SK_U8	OrgBits;				\
+-	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
+-	SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits)));	\
+-}
+-
+-#define SK_I2C_GET_SW(IoC, pI2cSw)	SK_IN8(IoC, B2_I2C_SW, pI2cSw)
+-
+-/*
+- * define the possible sensor states
+- */
+-#define	SK_SEN_IDLE		0	/* Idle: sensor not read */
+-#define	SK_SEN_VALUE	1	/* Value Read cycle */
+-#define	SK_SEN_VALEXT	2	/* Extended Value Read cycle */
+-
+-/*
+- * Conversion factor to convert read Voltage sensor to milli Volt
+- * Conversion factor to convert read Temperature sensor to 10th degree Celsius
+- */
+-#define	SK_LM80_VT_LSB		22	/* 22mV LSB resolution */
+-#define	SK_LM80_TEMP_LSB	10	/* 1 degree LSB resolution */
+-#define	SK_LM80_TEMPEXT_LSB	 5	/* 0.5 degree LSB resolution for ext. val. */
+-
+-/*
+- * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
+- * assuming: 6500rpm, 4 pulses, divisor 1
+- */
+-#define SK_LM80_FAN_FAKTOR	((22500L*60)/(1*2))
+-
+-/*
+- * Define sensor management data
+- * Maximum is reached on Genesis copper dual port and Yukon-64
+- * Board specific maximum is in pAC->I2c.MaxSens
+- */
+-#define	SK_MAX_SENSORS	8	/* maximal no. of installed sensors */
+-#define	SK_MIN_SENSORS	5	/* minimal no. of installed sensors */
+-
+-/*
+- * To watch the state machine (SM) use the timer in two ways
+- * instead of one as hitherto
+- */
+-#define	SK_TIMER_WATCH_SM		0	/* Watch the SM to finish in a spec. time */
+-#define	SK_TIMER_NEW_GAUGING	1	/* Start a new gauging when timer expires */
+-
+-/*
+- * Defines for the individual thresholds
+- */
+-
+-/* Temperature sensor */
+-#define	SK_SEN_TEMP_HIGH_ERR	800	/* Temperature High Err  Threshold */
+-#define	SK_SEN_TEMP_HIGH_WARN	700	/* Temperature High Warn Threshold */
+-#define	SK_SEN_TEMP_LOW_WARN	100	/* Temperature Low  Warn Threshold */
+-#define	SK_SEN_TEMP_LOW_ERR		  0	/* Temperature Low  Err  Threshold */
+-
+-/* VCC which should be 5 V */
+-#define	SK_SEN_PCI_5V_HIGH_ERR		5588	/* Voltage PCI High Err  Threshold */
+-#define	SK_SEN_PCI_5V_HIGH_WARN		5346	/* Voltage PCI High Warn Threshold */
+-#define	SK_SEN_PCI_5V_LOW_WARN		4664	/* Voltage PCI Low  Warn Threshold */
+-#define	SK_SEN_PCI_5V_LOW_ERR		4422	/* Voltage PCI Low  Err  Threshold */
+-
+-/*
+- * VIO may be 5 V or 3.3 V. Initialization takes two parts:
+- * 1. Initialize lowest lower limit and highest higher limit.
+- * 2. After the first value is read correct the upper or the lower limit to
+- *    the appropriate C constant.
+- *
+- * Warning limits are +-5% of the exepected voltage.
+- * Error limits are +-10% of the expected voltage.
+- */
+-
+-/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
+-
+-#define	SK_SEN_PCI_IO_5V_HIGH_ERR	5566	/* + 10% V PCI-IO High Err Threshold */
+-#define	SK_SEN_PCI_IO_5V_HIGH_WARN	5324	/* +  5% V PCI-IO High Warn Threshold */
+-					/*		5000	mVolt */
+-#define	SK_SEN_PCI_IO_5V_LOW_WARN	4686	/* -  5% V PCI-IO Low Warn Threshold */
+-#define	SK_SEN_PCI_IO_5V_LOW_ERR	4444	/* - 10% V PCI-IO Low Err Threshold */
+-
+-#define	SK_SEN_PCI_IO_RANGE_LIMITER	4000	/* 4000 mV range delimiter */
+-
+-/* correction values for the second pass */
+-#define	SK_SEN_PCI_IO_3V3_HIGH_ERR	3850	/* + 15% V PCI-IO High Err Threshold */
+-#define	SK_SEN_PCI_IO_3V3_HIGH_WARN	3674	/* + 10% V PCI-IO High Warn Threshold */
+-					/*		3300	mVolt */
+-#define	SK_SEN_PCI_IO_3V3_LOW_WARN	2926	/* - 10% V PCI-IO Low Warn Threshold */
+-#define	SK_SEN_PCI_IO_3V3_LOW_ERR	2772	/* - 15% V PCI-IO Low Err  Threshold */
+-
+-/*
+- * VDD voltage
+- */
+-#define	SK_SEN_VDD_HIGH_ERR		3630	/* Voltage ASIC High Err  Threshold */
+-#define	SK_SEN_VDD_HIGH_WARN	3476	/* Voltage ASIC High Warn Threshold */
+-#define	SK_SEN_VDD_LOW_WARN		3146	/* Voltage ASIC Low  Warn Threshold */
+-#define	SK_SEN_VDD_LOW_ERR		2970	/* Voltage ASIC Low  Err  Threshold */
+-
+-/*
+- * PHY PLL 3V3 voltage
+- */
+-#define	SK_SEN_PLL_3V3_HIGH_ERR		3630	/* Voltage PMA High Err  Threshold */
+-#define	SK_SEN_PLL_3V3_HIGH_WARN	3476	/* Voltage PMA High Warn Threshold */
+-#define	SK_SEN_PLL_3V3_LOW_WARN		3146	/* Voltage PMA Low  Warn Threshold */
+-#define	SK_SEN_PLL_3V3_LOW_ERR		2970	/* Voltage PMA Low  Err  Threshold */
+-
+-/*
+- * VAUX (YUKON only)
+- */
+-#define	SK_SEN_VAUX_3V3_HIGH_ERR	3630	/* Voltage VAUX High Err Threshold */
+-#define	SK_SEN_VAUX_3V3_HIGH_WARN	3476	/* Voltage VAUX High Warn Threshold */
+-#define	SK_SEN_VAUX_3V3_LOW_WARN	3146	/* Voltage VAUX Low Warn Threshold */
+-#define	SK_SEN_VAUX_3V3_LOW_ERR		2970	/* Voltage VAUX Low Err Threshold */
+-#define	SK_SEN_VAUX_0V_WARN_ERR		   0	/* if VAUX not present */
+-#define	SK_SEN_VAUX_RANGE_LIMITER	1000	/* 1000 mV range delimiter */
+-
+-/*
+- * PHY 2V5 voltage
+- */
+-#define	SK_SEN_PHY_2V5_HIGH_ERR		2750	/* Voltage PHY High Err Threshold */
+-#define	SK_SEN_PHY_2V5_HIGH_WARN	2640	/* Voltage PHY High Warn Threshold */
+-#define	SK_SEN_PHY_2V5_LOW_WARN		2376	/* Voltage PHY Low Warn Threshold */
+-#define	SK_SEN_PHY_2V5_LOW_ERR		2222	/* Voltage PHY Low Err Threshold */
+-
+-/*
+- * ASIC Core 1V5 voltage (YUKON only)
+- */
+-#define	SK_SEN_CORE_1V5_HIGH_ERR	1650	/* Voltage ASIC Core High Err Threshold */
+-#define	SK_SEN_CORE_1V5_HIGH_WARN	1575	/* Voltage ASIC Core High Warn Threshold */
+-#define	SK_SEN_CORE_1V5_LOW_WARN	1425	/* Voltage ASIC Core Low Warn Threshold */
+-#define	SK_SEN_CORE_1V5_LOW_ERR 	1350	/* Voltage ASIC Core Low Err Threshold */
+-
+-/*
+- * FAN 1 speed
+- */
+-/* assuming: 6500rpm +-15%, 4 pulses,
+- * warning at:	80 %
+- * error at:	70 %
+- * no upper limit
+- */
+-#define	SK_SEN_FAN_HIGH_ERR		20000	/* FAN Speed High Err Threshold */
+-#define	SK_SEN_FAN_HIGH_WARN	20000	/* FAN Speed High Warn Threshold */
+-#define	SK_SEN_FAN_LOW_WARN		 5200	/* FAN Speed Low Warn Threshold */
+-#define	SK_SEN_FAN_LOW_ERR		 4550	/* FAN Speed Low Err Threshold */
+-
+-/*
+- * Some Voltages need dynamic thresholds
+- */
+-#define	SK_SEN_DYN_INIT_NONE		 0  /* No dynamic init of thresholds */
+-#define	SK_SEN_DYN_INIT_PCI_IO		10  /* Init PCI-IO with new thresholds */
+-#define	SK_SEN_DYN_INIT_VAUX		11  /* Init VAUX with new thresholds */
+-
+-extern	int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
+-#endif	/* n_INC_SKGEI2C_H */
+diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h
+deleted file mode 100644
+index 143e635..0000000
+--- a/drivers/net/sk98lin/h/skgeinit.h
++++ /dev/null
+@@ -1,797 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skgeinit.h
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.83 $
+- * Date:	$Date: 2003/09/16 14:07:37 $
+- * Purpose:	Structures and prototypes for the GE Init Module
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKGEINIT_H_
+-#define __INC_SKGEINIT_H_
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif	/* __cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-#define SK_TEST_VAL		0x11335577UL
+-
+-/* modifying Link LED behaviour (used with SkGeLinkLED()) */
+-#define SK_LNK_OFF		LED_OFF
+-#define SK_LNK_ON		(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
+-#define SK_LNK_BLINK	(LED_ON | LED_BLK_ON  | LED_SYNC_ON)
+-#define SK_LNK_PERM		(LED_ON | LED_BLK_OFF | LED_SYNC_ON)
+-#define SK_LNK_TST		(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
+-
+-/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */
+-#define SK_LED_OFF		LED_OFF
+-#define SK_LED_ACTIVE	(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
+-#define SK_LED_STANDBY	(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
+-
+-/* addressing LED Registers in SkGeXmitLED() */
+-#define XMIT_LED_INI	0
+-#define XMIT_LED_CNT	(RX_LED_VAL - RX_LED_INI)
+-#define XMIT_LED_CTRL	(RX_LED_CTRL- RX_LED_INI)
+-#define XMIT_LED_TST	(RX_LED_TST - RX_LED_INI)
+-
+-/* parameter 'Mode' when calling SkGeXmitLED() */
+-#define SK_LED_DIS	0
+-#define SK_LED_ENA	1
+-#define SK_LED_TST	2
+-
+-/* Counter and Timer constants, for a host clock of 62.5 MHz */
+-#define SK_XMIT_DUR		0x002faf08UL	/*  50 ms */
+-#define SK_BLK_DUR		0x01dcd650UL	/* 500 ms */
+-
+-#define SK_DPOLL_DEF	0x00ee6b28UL	/* 250 ms at 62.5 MHz */
+-
+-#define SK_DPOLL_MAX	0x00ffffffUL	/* 268 ms at 62.5 MHz */
+-										/* 215 ms at 78.12 MHz */
+-
+-#define SK_FACT_62		100			/* is given in percent */
+-#define SK_FACT_53		 85         /* on GENESIS:	53.12 MHz */
+-#define SK_FACT_78		125			/* on YUKON:	78.12 MHz */
+-
+-/* Timeout values */
+-#define SK_MAC_TO_53	72			/* MAC arbiter timeout */
+-#define SK_PKT_TO_53	0x2000		/* Packet arbiter timeout */
+-#define SK_PKT_TO_MAX	0xffff		/* Maximum value */
+-#define SK_RI_TO_53		36			/* RAM interface timeout */
+-
+-#define SK_PHY_ACC_TO	600000		/* PHY access timeout */
+-
+-/* RAM Buffer High Pause Threshold values */
+-#define SK_RB_ULPP		( 8 * 1024)	/* Upper Level in kB/8 */
+-#define SK_RB_LLPP_S	(10 * 1024)	/* Lower Level for small Queues */
+-#define SK_RB_LLPP_B	(16 * 1024)	/* Lower Level for big Queues */
+-
+-#ifndef SK_BMU_RX_WM
+-#define SK_BMU_RX_WM	0x600		/* BMU Rx Watermark */
+-#endif
+-#ifndef SK_BMU_TX_WM
+-#define SK_BMU_TX_WM	0x600		/* BMU Tx Watermark */
+-#endif
+-
+-/* XMAC II Rx High Watermark */
+-#define SK_XM_RX_HI_WM	0x05aa		/* 1450 */
+-
+-/* XMAC II Tx Threshold */
+-#define SK_XM_THR_REDL	0x01fb		/* .. for redundant link usage */
+-#define SK_XM_THR_SL	0x01fb		/* .. for single link adapters */
+-#define SK_XM_THR_MULL	0x01fb		/* .. for multiple link usage */
+-#define SK_XM_THR_JUMBO	0x03fc		/* .. for jumbo frame usage */
+-
+-/* values for GIPortUsage */
+-#define SK_RED_LINK		1		/* redundant link usage */
+-#define SK_MUL_LINK		2		/* multiple link usage */
+-#define SK_JUMBO_LINK	3		/* driver uses jumbo frames */
+-
+-/* Minimum RAM Buffer Rx Queue Size */
+-#define SK_MIN_RXQ_SIZE	16		/* 16 kB */
+-
+-/* Minimum RAM Buffer Tx Queue Size */
+-#define SK_MIN_TXQ_SIZE	16		/* 16 kB */
+-
+-/* Queue Size units */
+-#define QZ_UNITS		0x7
+-#define QZ_STEP			8
+-
+-/* Percentage of queue size from whole memory */
+-/* 80 % for receive */
+-#define RAM_QUOTA_RX	80L
+-/* 0% for sync transfer */
+-#define	RAM_QUOTA_SYNC	0L
+-/* the rest (20%) is taken for async transfer */
+-
+-/* Get the rounded queue size in Bytes in 8k steps */
+-#define ROUND_QUEUE_SIZE(SizeInBytes)					\
+-	((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) &	\
+-	~(QZ_STEP-1))
+-
+-/* Get the rounded queue size in KBytes in 8k steps */
+-#define ROUND_QUEUE_SIZE_KB(Kilobytes) \
+-	ROUND_QUEUE_SIZE((Kilobytes) * 1024L)
+-
+-/* Types of RAM Buffer Queues */
+-#define SK_RX_SRAM_Q	1	/* small receive queue */
+-#define SK_RX_BRAM_Q	2	/* big receive queue */
+-#define SK_TX_RAM_Q		3	/* small or big transmit queue */
+-
+-/* parameter 'Dir' when calling SkGeStopPort() */
+-#define SK_STOP_TX	1	/* Stops the transmit path, resets the XMAC */
+-#define SK_STOP_RX	2	/* Stops the receive path */
+-#define SK_STOP_ALL	3	/* Stops Rx and Tx path, resets the XMAC */
+-
+-/* parameter 'RstMode' when calling SkGeStopPort() */
+-#define SK_SOFT_RST	1	/* perform a software reset */
+-#define SK_HARD_RST	2	/* perform a hardware reset */
+-
+-/* Init Levels */
+-#define SK_INIT_DATA	0	/* Init level 0: init data structures */
+-#define SK_INIT_IO		1	/* Init level 1: init with IOs */
+-#define SK_INIT_RUN		2	/* Init level 2: init for run time */
+-
+-/* Link Mode Parameter */
+-#define SK_LMODE_HALF		1	/* Half Duplex Mode */
+-#define SK_LMODE_FULL		2	/* Full Duplex Mode */
+-#define SK_LMODE_AUTOHALF	3	/* AutoHalf Duplex Mode */
+-#define SK_LMODE_AUTOFULL	4	/* AutoFull Duplex Mode */
+-#define SK_LMODE_AUTOBOTH	5	/* AutoBoth Duplex Mode */
+-#define SK_LMODE_AUTOSENSE	6	/* configured mode auto sensing */
+-#define SK_LMODE_INDETERMINATED	7	/* indeterminated */
+-
+-/* Auto-negotiation timeout in 100ms granularity */
+-#define SK_AND_MAX_TO		6	/* Wait 600 msec before link comes up */
+-
+-/* Auto-negotiation error codes */
+-#define SK_AND_OK			0	/* no error */
+-#define SK_AND_OTHER		1	/* other error than below */
+-#define SK_AND_DUP_CAP		2	/* Duplex capabilities error */
+-
+-
+-/* Link Speed Capabilities */
+-#define SK_LSPEED_CAP_AUTO			(1<<0)	/* Automatic resolution */
+-#define SK_LSPEED_CAP_10MBPS		(1<<1)	/* 10 Mbps */
+-#define SK_LSPEED_CAP_100MBPS		(1<<2)	/* 100 Mbps */
+-#define SK_LSPEED_CAP_1000MBPS		(1<<3)	/* 1000 Mbps */
+-#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */
+-
+-/* Link Speed Parameter */
+-#define SK_LSPEED_AUTO				1	/* Automatic resolution */
+-#define SK_LSPEED_10MBPS			2	/* 10 Mbps */
+-#define SK_LSPEED_100MBPS			3	/* 100 Mbps */
+-#define SK_LSPEED_1000MBPS			4	/* 1000 Mbps */
+-#define SK_LSPEED_INDETERMINATED	5	/* indeterminated */
+-
+-/* Link Speed Current State */
+-#define SK_LSPEED_STAT_UNKNOWN		1
+-#define SK_LSPEED_STAT_10MBPS		2
+-#define SK_LSPEED_STAT_100MBPS 		3
+-#define SK_LSPEED_STAT_1000MBPS		4
+-#define SK_LSPEED_STAT_INDETERMINATED 5
+-
+-
+-/* Link Capability Parameter */
+-#define SK_LMODE_CAP_HALF		(1<<0)	/* Half Duplex Mode */
+-#define SK_LMODE_CAP_FULL		(1<<1)	/* Full Duplex Mode */
+-#define SK_LMODE_CAP_AUTOHALF	(1<<2)	/* AutoHalf Duplex Mode */
+-#define SK_LMODE_CAP_AUTOFULL	(1<<3)	/* AutoFull Duplex Mode */
+-#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */
+-
+-/* Link Mode Current State */
+-#define SK_LMODE_STAT_UNKNOWN	1	/* Unknown Duplex Mode */
+-#define SK_LMODE_STAT_HALF		2	/* Half Duplex Mode */
+-#define SK_LMODE_STAT_FULL		3	/* Full Duplex Mode */
+-#define SK_LMODE_STAT_AUTOHALF	4	/* Half Duplex Mode obtained by Auto-Neg */
+-#define SK_LMODE_STAT_AUTOFULL	5	/* Full Duplex Mode obtained by Auto-Neg */
+-#define SK_LMODE_STAT_INDETERMINATED 6	/* indeterminated */
+-
+-/* Flow Control Mode Parameter (and capabilities) */
+-#define SK_FLOW_MODE_NONE		1	/* No Flow-Control */
+-#define SK_FLOW_MODE_LOC_SEND	2	/* Local station sends PAUSE */
+-#define SK_FLOW_MODE_SYMMETRIC	3	/* Both stations may send PAUSE */
+-#define SK_FLOW_MODE_SYM_OR_REM	4	/* Both stations may send PAUSE or
+-					 * just the remote station may send PAUSE
+-					 */
+-#define SK_FLOW_MODE_INDETERMINATED 5	/* indeterminated */
+-
+-/* Flow Control Status Parameter */
+-#define SK_FLOW_STAT_NONE		1	/* No Flow Control */
+-#define SK_FLOW_STAT_REM_SEND	2	/* Remote Station sends PAUSE */
+-#define SK_FLOW_STAT_LOC_SEND	3	/* Local station sends PAUSE */
+-#define SK_FLOW_STAT_SYMMETRIC	4	/* Both station may send PAUSE */
+-#define SK_FLOW_STAT_INDETERMINATED 5	/* indeterminated */
+-
+-/* Master/Slave Mode Capabilities */
+-#define SK_MS_CAP_AUTO		(1<<0)	/* Automatic resolution */
+-#define SK_MS_CAP_MASTER	(1<<1)	/* This station is master */
+-#define SK_MS_CAP_SLAVE		(1<<2)	/* This station is slave */
+-#define SK_MS_CAP_INDETERMINATED (1<<3)	/* indeterminated */
+-
+-/* Set Master/Slave Mode Parameter (and capabilities) */
+-#define SK_MS_MODE_AUTO		1	/* Automatic resolution */
+-#define SK_MS_MODE_MASTER	2	/* This station is master */
+-#define SK_MS_MODE_SLAVE	3	/* This station is slave */
+-#define SK_MS_MODE_INDETERMINATED 4	/* indeterminated */
+-
+-/* Master/Slave Status Parameter */
+-#define SK_MS_STAT_UNSET	1	/* The M/S status is not set */
+-#define SK_MS_STAT_MASTER	2	/* This station is master */
+-#define SK_MS_STAT_SLAVE	3	/* This station is slave */
+-#define SK_MS_STAT_FAULT	4	/* M/S resolution failed */
+-#define SK_MS_STAT_INDETERMINATED 5	/* indeterminated */
+-
+-/* parameter 'Mode' when calling SkXmSetRxCmd() */
+-#define SK_STRIP_FCS_ON		(1<<0)	/* Enable  FCS stripping of Rx frames */
+-#define SK_STRIP_FCS_OFF	(1<<1)	/* Disable FCS stripping of Rx frames */
+-#define SK_STRIP_PAD_ON		(1<<2)	/* Enable  pad byte stripping of Rx fr */
+-#define SK_STRIP_PAD_OFF	(1<<3)	/* Disable pad byte stripping of Rx fr */
+-#define SK_LENERR_OK_ON		(1<<4)	/* Don't chk fr for in range len error */
+-#define SK_LENERR_OK_OFF	(1<<5)	/* Check frames for in range len error */
+-#define SK_BIG_PK_OK_ON		(1<<6)	/* Don't set Rx Error bit for big frames */
+-#define SK_BIG_PK_OK_OFF	(1<<7)	/* Set Rx Error bit for big frames */
+-#define SK_SELF_RX_ON		(1<<8)	/* Enable  Rx of own packets */
+-#define SK_SELF_RX_OFF		(1<<9)	/* Disable Rx of own packets */
+-
+-/* parameter 'Para' when calling SkMacSetRxTxEn() */
+-#define SK_MAC_LOOPB_ON		(1<<0)	/* Enable  MAC Loopback Mode */
+-#define SK_MAC_LOOPB_OFF	(1<<1)	/* Disable MAC Loopback Mode */
+-#define SK_PHY_LOOPB_ON		(1<<2)	/* Enable  PHY Loopback Mode */
+-#define SK_PHY_LOOPB_OFF	(1<<3)	/* Disable PHY Loopback Mode */
+-#define SK_PHY_FULLD_ON		(1<<4)	/* Enable  GMII Full Duplex */
+-#define SK_PHY_FULLD_OFF	(1<<5)	/* Disable GMII Full Duplex */
+-
+-/* States of PState */
+-#define SK_PRT_RESET	0	/* the port is reset */
+-#define SK_PRT_STOP		1	/* the port is stopped (similar to SW reset) */
+-#define SK_PRT_INIT		2	/* the port is initialized */
+-#define SK_PRT_RUN		3	/* the port has an active link */
+-
+-/* PHY power down modes */
+-#define PHY_PM_OPERATIONAL_MODE		0	/* PHY operational mode */
+-#define PHY_PM_DEEP_SLEEP			1	/* coma mode --> minimal power */
+-#define PHY_PM_IEEE_POWER_DOWN		2	/* IEEE 22.2.4.1.5 compl. power down */
+-#define PHY_PM_ENERGY_DETECT		3	/* energy detect */
+-#define PHY_PM_ENERGY_DETECT_PLUS	4	/* energy detect plus */
+-
+-/* Default receive frame limit for Workaround of XMAC Errata */
+-#define SK_DEF_RX_WA_LIM	SK_CONSTU64(100)
+-
+-/* values for GILedBlinkCtrl (LED Blink Control) */
+-#define SK_ACT_LED_BLINK	(1<<0)	/* Active LED blinking */
+-#define SK_DUP_LED_NORMAL	(1<<1)	/* Duplex LED normal */
+-#define SK_LED_LINK100_ON	(1<<2)	/* Link 100M LED on */
+-
+-/* Link Partner Status */
+-#define SK_LIPA_UNKNOWN	0	/* Link partner is in unknown state */
+-#define SK_LIPA_MANUAL	1	/* Link partner is in detected manual state */
+-#define SK_LIPA_AUTO	2	/* Link partner is in auto-negotiation state */
+-
+-/* Maximum Restarts before restart is ignored (3Com WA) */
+-#define SK_MAX_LRESTART	3	/* Max. 3 times the link is restarted */
+-
+-/* Max. Auto-neg. timeouts before link detection in sense mode is reset */
+-#define SK_MAX_ANEG_TO	10	/* Max. 10 times the sense mode is reset */
+-
+-/* structures *****************************************************************/
+-
+-/*
+- * MAC specific functions
+- */
+-typedef struct s_GeMacFunc {
+-	int  (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
+-	int  (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
+-							SK_U16 StatAddr, SK_U32 SK_FAR *pVal);
+-	int  (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
+-	int  (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
+-						   SK_U16 IStatus, SK_U64 SK_FAR *pVal);
+-} SK_GEMACFUNC;
+-
+-/*
+- * Port Structure
+- */
+-typedef	struct s_GePort {
+-#ifndef SK_DIAG
+-	SK_TIMER	PWaTimer;	/* Workaround Timer */
+-	SK_TIMER	HalfDupChkTimer;
+-#endif /* SK_DIAG */
+-	SK_U32	PPrevShorts;	/* Previous Short Counter checking */
+-	SK_U32	PPrevFcs;		/* Previous FCS Error Counter checking */
+-	SK_U64	PPrevRx;		/* Previous RxOk Counter checking */
+-	SK_U64	PRxLim;			/* Previous RxOk Counter checking */
+-	SK_U64	LastOctets;		/* For half duplex hang check */
+-	int		PLinkResCt;		/* Link Restart Counter */
+-	int		PAutoNegTimeOut;/* Auto-negotiation timeout current value */
+-	int		PAutoNegTOCt;	/* Auto-negotiation Timeout Counter */
+-	int		PRxQSize;		/* Port Rx Queue Size in kB */
+-	int		PXSQSize;		/* Port Synchronous  Transmit Queue Size in kB */
+-	int		PXAQSize;		/* Port Asynchronous Transmit Queue Size in kB */
+-	SK_U32	PRxQRamStart;	/* Receive Queue RAM Buffer Start Address */
+-	SK_U32	PRxQRamEnd;		/* Receive Queue RAM Buffer End Address */
+-	SK_U32	PXsQRamStart;	/* Sync Tx Queue RAM Buffer Start Address */
+-	SK_U32	PXsQRamEnd;		/* Sync Tx Queue RAM Buffer End Address */
+-	SK_U32	PXaQRamStart;	/* Async Tx Queue RAM Buffer Start Address */
+-	SK_U32	PXaQRamEnd;		/* Async Tx Queue RAM Buffer End Address */
+-	SK_U32	PRxOverCnt;		/* Receive Overflow Counter */
+-	int		PRxQOff;		/* Rx Queue Address Offset */
+-	int		PXsQOff;		/* Synchronous Tx Queue Address Offset */
+-	int		PXaQOff;		/* Asynchronous Tx Queue Address Offset */
+-	int		PhyType;		/* PHY used on this port */
+-	int		PState;			/* Port status (reset, stop, init, run) */
+-	SK_U16	PhyId1;			/* PHY Id1 on this port */
+-	SK_U16	PhyAddr;		/* MDIO/MDC PHY address */
+-	SK_U16	PIsave;			/* Saved Interrupt status word */
+-	SK_U16	PSsave;			/* Saved PHY status word */
+-	SK_U16	PGmANegAdv;		/* Saved GPhy AutoNegAdvertisment register */
+-	SK_BOOL	PHWLinkUp;		/* The hardware Link is up (wiring) */
+-	SK_BOOL	PLinkBroken;	/* Is Link broken ? */
+-	SK_BOOL	PCheckPar;		/* Do we check for parity errors ? */
+-	SK_BOOL	HalfDupTimerActive;
+-	SK_U8	PLinkCap;		/* Link Capabilities */
+-	SK_U8	PLinkModeConf;	/* Link Mode configured */
+-	SK_U8	PLinkMode;		/* Link Mode currently used */
+-	SK_U8	PLinkModeStatus;/* Link Mode Status */
+-	SK_U8	PLinkSpeedCap;	/* Link Speed Capabilities(10/100/1000 Mbps) */
+-	SK_U8	PLinkSpeed;		/* configured Link Speed (10/100/1000 Mbps) */
+-	SK_U8	PLinkSpeedUsed;	/* current Link Speed (10/100/1000 Mbps) */
+-	SK_U8	PFlowCtrlCap;	/* Flow Control Capabilities */
+-	SK_U8	PFlowCtrlMode;	/* Flow Control Mode */
+-	SK_U8	PFlowCtrlStatus;/* Flow Control Status */
+-	SK_U8	PMSCap;			/* Master/Slave Capabilities */
+-	SK_U8	PMSMode;		/* Master/Slave Mode */
+-	SK_U8	PMSStatus;		/* Master/Slave Status */
+-	SK_BOOL	PAutoNegFail;	/* Auto-negotiation fail flag */
+-	SK_U8	PLipaAutoNeg;	/* Auto-negotiation possible with Link Partner */
+-	SK_U8	PCableLen;		/* Cable Length */
+-	SK_U8	PMdiPairLen[4];	/* MDI[0..3] Pair Length */
+-	SK_U8	PMdiPairSts[4];	/* MDI[0..3] Pair Diagnostic Status */
+-	SK_U8	PPhyPowerState;	/* PHY current power state */
+-	int		PMacColThres;	/* MAC Collision Threshold */
+-	int		PMacJamLen;		/* MAC Jam length */
+-	int		PMacJamIpgVal;	/* MAC Jam IPG */
+-	int		PMacJamIpgData;	/* MAC IPG Jam to Data */
+-	int		PMacIpgData;	/* MAC Data IPG */
+-	SK_BOOL PMacLimit4;		/* reset collision counter and backoff algorithm */
+-} SK_GEPORT;
+-
+-/*
+- * Gigabit Ethernet Initialization Struct
+- * (has to be included in the adapter context)
+- */
+-typedef	struct s_GeInit {
+-	int			GIChipId;		/* Chip Identification Number */
+-	int			GIChipRev;		/* Chip Revision Number */
+-	SK_U8		GIPciHwRev;		/* PCI HW Revision Number */
+-	SK_BOOL		GIGenesis;		/* Genesis adapter ? */
+-	SK_BOOL		GIYukon;		/* YUKON-A1/Bx chip */
+-	SK_BOOL		GIYukonLite;	/* YUKON-Lite chip */
+-	SK_BOOL		GICopperType;	/* Copper Type adapter ? */
+-	SK_BOOL		GIPciSlot64;	/* 64-bit PCI Slot */
+-	SK_BOOL		GIPciClock66;	/* 66 MHz PCI Clock */
+-	SK_BOOL		GIVauxAvail;	/* VAUX available (YUKON) */
+-	SK_BOOL		GIYukon32Bit;	/* 32-Bit YUKON adapter */
+-	SK_U16		GILedBlinkCtrl;	/* LED Blink Control */
+-	int			GIMacsFound;	/* Number of MACs found on this adapter */
+-	int			GIMacType;		/* MAC Type used on this adapter */
+-	int			GIHstClkFact;	/* Host Clock Factor (62.5 / HstClk * 100) */
+-	int			GIPortUsage;	/* Driver Port Usage */
+-	int			GILevel;		/* Initialization Level completed */
+-	int			GIRamSize;		/* The RAM size of the adapter in kB */
+-	int			GIWolOffs;		/* WOL Register Offset (HW-Bug in Rev. A) */
+-	SK_U32		GIRamOffs;		/* RAM Address Offset for addr calculation */
+-	SK_U32		GIPollTimerVal;	/* Descr. Poll Timer Init Val (HstClk ticks) */
+-	SK_U32		GIValIrqMask;	/* Value for Interrupt Mask */
+-	SK_U32		GITimeStampCnt;	/* Time Stamp High Counter (YUKON only) */
+-	SK_GEPORT	GP[SK_MAX_MACS];/* Port Dependent Information */
+-	SK_GEMACFUNC GIFunc;		/* MAC depedent functions */
+-} SK_GEINIT;
+-
+-/*
+- * Error numbers and messages for skxmac2.c and skgeinit.c
+- */
+-#define SKERR_HWI_E001		(SK_ERRBASE_HWINIT)
+-#define SKERR_HWI_E001MSG	"SkXmClrExactAddr() has got illegal parameters"
+-#define SKERR_HWI_E002		(SKERR_HWI_E001+1)
+-#define SKERR_HWI_E002MSG	"SkGeInit(): Level 1 call missing"
+-#define SKERR_HWI_E003		(SKERR_HWI_E002+1)
+-#define SKERR_HWI_E003MSG	"SkGeInit() called with illegal init Level"
+-#define SKERR_HWI_E004		(SKERR_HWI_E003+1)
+-#define SKERR_HWI_E004MSG	"SkGeInitPort(): Queue Size illegal configured"
+-#define SKERR_HWI_E005		(SKERR_HWI_E004+1)
+-#define SKERR_HWI_E005MSG	"SkGeInitPort(): cannot init running ports"
+-#define SKERR_HWI_E006		(SKERR_HWI_E005+1)
+-#define SKERR_HWI_E006MSG	"SkGeMacInit(): PState does not match HW state"
+-#define SKERR_HWI_E007		(SKERR_HWI_E006+1)
+-#define SKERR_HWI_E007MSG	"SkXmInitDupMd() called with invalid Dup Mode"
+-#define SKERR_HWI_E008		(SKERR_HWI_E007+1)
+-#define SKERR_HWI_E008MSG	"SkXmSetRxCmd() called with invalid Mode"
+-#define SKERR_HWI_E009		(SKERR_HWI_E008+1)
+-#define SKERR_HWI_E009MSG	"SkGeCfgSync() called although PXSQSize zero"
+-#define SKERR_HWI_E010		(SKERR_HWI_E009+1)
+-#define SKERR_HWI_E010MSG	"SkGeCfgSync() called with invalid parameters"
+-#define SKERR_HWI_E011		(SKERR_HWI_E010+1)
+-#define SKERR_HWI_E011MSG	"SkGeInitPort(): Receive Queue Size too small"
+-#define SKERR_HWI_E012		(SKERR_HWI_E011+1)
+-#define SKERR_HWI_E012MSG	"SkGeInitPort(): invalid Queue Size specified"
+-#define SKERR_HWI_E013		(SKERR_HWI_E012+1)
+-#define SKERR_HWI_E013MSG	"SkGeInitPort(): cfg changed for running queue"
+-#define SKERR_HWI_E014		(SKERR_HWI_E013+1)
+-#define SKERR_HWI_E014MSG	"SkGeInitPort(): unknown GIPortUsage specified"
+-#define SKERR_HWI_E015		(SKERR_HWI_E014+1)
+-#define SKERR_HWI_E015MSG	"Illegal Link mode parameter"
+-#define SKERR_HWI_E016		(SKERR_HWI_E015+1)
+-#define SKERR_HWI_E016MSG	"Illegal Flow control mode parameter"
+-#define SKERR_HWI_E017		(SKERR_HWI_E016+1)
+-#define SKERR_HWI_E017MSG	"Illegal value specified for GIPollTimerVal"
+-#define SKERR_HWI_E018		(SKERR_HWI_E017+1)
+-#define SKERR_HWI_E018MSG	"FATAL: SkGeStopPort() does not terminate (Tx)"
+-#define SKERR_HWI_E019		(SKERR_HWI_E018+1)
+-#define SKERR_HWI_E019MSG	"Illegal Speed parameter"
+-#define SKERR_HWI_E020		(SKERR_HWI_E019+1)
+-#define SKERR_HWI_E020MSG	"Illegal Master/Slave parameter"
+-#define SKERR_HWI_E021		(SKERR_HWI_E020+1)
+-#define	SKERR_HWI_E021MSG	"MacUpdateStats(): cannot update statistic counter"
+-#define	SKERR_HWI_E022		(SKERR_HWI_E021+1)
+-#define	SKERR_HWI_E022MSG	"MacStatistic(): illegal statistic base address"
+-#define SKERR_HWI_E023		(SKERR_HWI_E022+1)
+-#define SKERR_HWI_E023MSG	"SkGeInitPort(): Transmit Queue Size too small"
+-#define SKERR_HWI_E024		(SKERR_HWI_E023+1)
+-#define SKERR_HWI_E024MSG	"FATAL: SkGeStopPort() does not terminate (Rx)"
+-#define SKERR_HWI_E025		(SKERR_HWI_E024+1)
+-#define SKERR_HWI_E025MSG	""
+-
+-/* function prototypes ********************************************************/
+-
+-#ifndef	SK_KR_PROTO
+-
+-/*
+- * public functions in skgeinit.c
+- */
+-extern void	SkGePollTxD(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_BOOL PollTxD);
+-
+-extern void	SkGeYellowLED(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		State);
+-
+-extern int	SkGeCfgSync(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_U32	IntTime,
+-	SK_U32	LimCount,
+-	int		SyncMode);
+-
+-extern void	SkGeLoadLnkSyncCnt(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_U32	CntVal);
+-
+-extern void	SkGeStopPort(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	int		Dir,
+-	int		RstMode);
+-
+-extern int	SkGeInit(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Level);
+-
+-extern void	SkGeDeInit(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC);
+-
+-extern int	SkGeInitPort(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void	SkGeXmitLED(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Led,
+-	int		Mode);
+-
+-extern int	SkGeInitAssignRamToQueues(
+-	SK_AC	*pAC,
+-	int		ActivePort,
+-	SK_BOOL	DualNet);
+-
+-/*
+- * public functions in skxmac2.c
+- */
+-extern void SkMacRxTxDisable(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void	SkMacSoftRst(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void	SkMacHardRst(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void	SkXmInitMac(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void	SkGmInitMac(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void SkMacInitPhy(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_BOOL	DoLoop);
+-
+-extern void SkMacIrqDisable(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void	SkMacFlushTxFifo(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void	SkMacIrq(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern int	SkMacAutoNegDone(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void	SkMacAutoNegLipaPhy(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_U16	IStatus);
+-
+-extern int  SkMacRxTxEnable(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port);
+-
+-extern void	SkMacPromiscMode(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_BOOL	Enable);
+-
+-extern void	SkMacHashing(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_BOOL	Enable);
+-
+-extern void	SkXmPhyRead(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	int		Addr,
+-	SK_U16	SK_FAR *pVal);
+-
+-extern void	SkXmPhyWrite(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	int		Addr,
+-	SK_U16	Val);
+-
+-extern void	SkGmPhyRead(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	int		Addr,
+-	SK_U16	SK_FAR *pVal);
+-
+-extern void	SkGmPhyWrite(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	int		Addr,
+-	SK_U16	Val);
+-
+-extern void	SkXmClrExactAddr(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	int		StartNum,
+-	int		StopNum);
+-
+-extern void	SkXmAutoNegLipaXmac(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_U16	IStatus);
+-
+-extern int SkXmUpdateStats(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	unsigned int Port);
+-
+-extern int SkGmUpdateStats(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	unsigned int Port);
+-
+-extern int SkXmMacStatistic(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	unsigned int Port,
+-	SK_U16	StatAddr,
+-	SK_U32	SK_FAR *pVal);
+-
+-extern int SkGmMacStatistic(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	unsigned int Port,
+-	SK_U16	StatAddr,
+-	SK_U32	SK_FAR *pVal);
+-
+-extern int SkXmResetCounter(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	unsigned int Port);
+-
+-extern int SkGmResetCounter(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	unsigned int Port);
+-
+-extern int SkXmOverflowStatus(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	unsigned int Port,
+-	SK_U16  IStatus,
+-	SK_U64	SK_FAR *pStatus);
+-
+-extern int SkGmOverflowStatus(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	unsigned int Port,
+-	SK_U16	MacStatus,
+-	SK_U64	SK_FAR *pStatus);
+-
+-extern int SkGmCableDiagStatus(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_BOOL	StartTest);
+-
+-#ifdef SK_DIAG
+-extern void	SkGePhyRead(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	int		Addr,
+-	SK_U16	*pVal);
+-
+-extern void	SkGePhyWrite(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	int		Addr,
+-	SK_U16	Val);
+-
+-extern void	SkMacSetRxCmd(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	int		Mode);
+-extern void	SkMacCrcGener(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_BOOL	Enable);
+-extern void	SkMacTimeStamp(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_BOOL	Enable);
+-extern void	SkXmSendCont(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Port,
+-	SK_BOOL	Enable);
+-#endif /* SK_DIAG */
+-
+-#else	/* SK_KR_PROTO */
+-
+-/*
+- * public functions in skgeinit.c
+- */
+-extern void	SkGePollTxD();
+-extern void	SkGeYellowLED();
+-extern int	SkGeCfgSync();
+-extern void	SkGeLoadLnkSyncCnt();
+-extern void	SkGeStopPort();
+-extern int	SkGeInit();
+-extern void	SkGeDeInit();
+-extern int	SkGeInitPort();
+-extern void	SkGeXmitLED();
+-extern int	SkGeInitAssignRamToQueues();
+-
+-/*
+- * public functions in skxmac2.c
+- */
+-extern void SkMacRxTxDisable();
+-extern void	SkMacSoftRst();
+-extern void	SkMacHardRst();
+-extern void SkMacInitPhy();
+-extern int  SkMacRxTxEnable();
+-extern void SkMacPromiscMode();
+-extern void SkMacHashing();
+-extern void SkMacIrqDisable();
+-extern void	SkMacFlushTxFifo();
+-extern void	SkMacIrq();
+-extern int	SkMacAutoNegDone();
+-extern void	SkMacAutoNegLipaPhy();
+-extern void	SkXmInitMac();
+-extern void	SkXmPhyRead();
+-extern void	SkXmPhyWrite();
+-extern void	SkGmInitMac();
+-extern void	SkGmPhyRead();
+-extern void	SkGmPhyWrite();
+-extern void	SkXmClrExactAddr();
+-extern void	SkXmAutoNegLipaXmac();
+-extern int	SkXmUpdateStats();
+-extern int	SkGmUpdateStats();
+-extern int	SkXmMacStatistic();
+-extern int	SkGmMacStatistic();
+-extern int	SkXmResetCounter();
+-extern int	SkGmResetCounter();
+-extern int	SkXmOverflowStatus();
+-extern int	SkGmOverflowStatus();
+-extern int	SkGmCableDiagStatus();
+-
+-#ifdef SK_DIAG
+-extern void	SkGePhyRead();
+-extern void	SkGePhyWrite();
+-extern void	SkMacSetRxCmd();
+-extern void	SkMacCrcGener();
+-extern void	SkMacTimeStamp();
+-extern void	SkXmSendCont();
+-#endif /* SK_DIAG */
+-
+-#endif	/* SK_KR_PROTO */
+-
+-#ifdef __cplusplus
+-}
+-#endif	/* __cplusplus */
+-
+-#endif	/* __INC_SKGEINIT_H_ */
+diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
+deleted file mode 100644
+index ddd304f..0000000
+--- a/drivers/net/sk98lin/h/skgepnm2.h
++++ /dev/null
+@@ -1,334 +0,0 @@
+-/*****************************************************************************
+- *
+- * Name:	skgepnm2.h
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.36 $
+- * Date:	$Date: 2003/05/23 12:45:13 $
+- * Purpose:	Defines for Private Network Management Interface
+- *
+- ****************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef _SKGEPNM2_H_
+-#define _SKGEPNM2_H_
+-
+-/*
+- * General definitions
+- */
+-#define SK_PNMI_CHIPSET_XMAC	1	/* XMAC11800FP */
+-#define SK_PNMI_CHIPSET_YUKON	2	/* YUKON */
+-
+-#define	SK_PNMI_BUS_PCI		1	/* PCI bus*/
+-
+-/*
+- * Actions
+- */
+-#define SK_PNMI_ACT_IDLE		1
+-#define SK_PNMI_ACT_RESET		2
+-#define SK_PNMI_ACT_SELFTEST	3
+-#define SK_PNMI_ACT_RESETCNT	4
+-
+-/*
+- * VPD releated defines
+- */
+-
+-#define SK_PNMI_VPD_RW		1
+-#define SK_PNMI_VPD_RO		2
+-
+-#define SK_PNMI_VPD_OK			0
+-#define SK_PNMI_VPD_NOTFOUND	1
+-#define SK_PNMI_VPD_CUT			2
+-#define SK_PNMI_VPD_TIMEOUT		3
+-#define SK_PNMI_VPD_FULL		4
+-#define SK_PNMI_VPD_NOWRITE		5
+-#define SK_PNMI_VPD_FATAL		6
+-
+-#define SK_PNMI_VPD_IGNORE	0
+-#define SK_PNMI_VPD_CREATE	1
+-#define SK_PNMI_VPD_DELETE	2
+-
+-
+-/*
+- * RLMT related defines
+- */
+-#define SK_PNMI_DEF_RLMT_CHG_THRES	240	/* 4 changes per minute */
+-
+-
+-/*
+- * VCT internal status values
+- */
+-#define SK_PNMI_VCT_PENDING	32
+-#define SK_PNMI_VCT_TEST_DONE	64
+-#define SK_PNMI_VCT_LINK	128
+-
+-/*
+- * Internal table definitions
+- */
+-#define SK_PNMI_GET		0
+-#define SK_PNMI_PRESET	1
+-#define SK_PNMI_SET		2
+-
+-#define SK_PNMI_RO		0
+-#define SK_PNMI_RW		1
+-#define SK_PNMI_WO		2
+-
+-typedef struct s_OidTabEntry {
+-	SK_U32			Id;
+-	SK_U32			InstanceNo;
+-	unsigned int	StructSize;
+-	unsigned int	Offset;
+-	int				Access;
+-	int				(* Func)(SK_AC *pAc, SK_IOC pIo, int action,
+-							 SK_U32 Id, char* pBuf, unsigned int* pLen,
+-							 SK_U32 Instance, unsigned int TableIndex,
+-							 SK_U32 NetNumber);
+-	SK_U16			Param;
+-} SK_PNMI_TAB_ENTRY;
+-
+-
+-/*
+- * Trap lengths
+- */
+-#define SK_PNMI_TRAP_SIMPLE_LEN			17
+-#define SK_PNMI_TRAP_SENSOR_LEN_BASE	46
+-#define SK_PNMI_TRAP_RLMT_CHANGE_LEN	23
+-#define SK_PNMI_TRAP_RLMT_PORT_LEN		23
+-
+-/*
+- * Number of MAC types supported
+- */
+-#define SK_PNMI_MAC_TYPES	(SK_MAC_GMAC + 1)
+-
+-/*
+- * MAC statistic data list (overall set for MAC types used)
+- */
+-enum SK_MACSTATS {
+-	SK_PNMI_HTX				= 0,
+-	SK_PNMI_HTX_OCTET,
+-	SK_PNMI_HTX_OCTETHIGH 	= SK_PNMI_HTX_OCTET,
+-	SK_PNMI_HTX_OCTETLOW,
+-	SK_PNMI_HTX_BROADCAST,
+-	SK_PNMI_HTX_MULTICAST,
+-	SK_PNMI_HTX_UNICAST,
+-	SK_PNMI_HTX_BURST,
+-	SK_PNMI_HTX_PMACC,
+-	SK_PNMI_HTX_MACC,
+-	SK_PNMI_HTX_COL,
+-	SK_PNMI_HTX_SINGLE_COL,
+-	SK_PNMI_HTX_MULTI_COL,
+-	SK_PNMI_HTX_EXCESS_COL,
+-	SK_PNMI_HTX_LATE_COL,
+-	SK_PNMI_HTX_DEFFERAL,
+-	SK_PNMI_HTX_EXCESS_DEF,
+-	SK_PNMI_HTX_UNDERRUN,
+-	SK_PNMI_HTX_CARRIER,
+-	SK_PNMI_HTX_UTILUNDER,
+-	SK_PNMI_HTX_UTILOVER,
+-	SK_PNMI_HTX_64,
+-	SK_PNMI_HTX_127,
+-	SK_PNMI_HTX_255,
+-	SK_PNMI_HTX_511,
+-	SK_PNMI_HTX_1023,
+-	SK_PNMI_HTX_MAX,
+-	SK_PNMI_HTX_LONGFRAMES,
+-	SK_PNMI_HTX_SYNC,
+-	SK_PNMI_HTX_SYNC_OCTET,
+-	SK_PNMI_HTX_RESERVED,
+-	
+-	SK_PNMI_HRX,
+-	SK_PNMI_HRX_OCTET,
+-	SK_PNMI_HRX_OCTETHIGH	= SK_PNMI_HRX_OCTET,
+-	SK_PNMI_HRX_OCTETLOW,
+-	SK_PNMI_HRX_BADOCTET,
+-	SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET,
+-	SK_PNMI_HRX_BADOCTETLOW,
+-	SK_PNMI_HRX_BROADCAST,
+-	SK_PNMI_HRX_MULTICAST,
+-	SK_PNMI_HRX_UNICAST,
+-	SK_PNMI_HRX_PMACC,
+-	SK_PNMI_HRX_MACC,
+-	SK_PNMI_HRX_PMACC_ERR,
+-	SK_PNMI_HRX_MACC_UNKWN,
+-	SK_PNMI_HRX_BURST,
+-	SK_PNMI_HRX_MISSED,
+-	SK_PNMI_HRX_FRAMING,
+-	SK_PNMI_HRX_UNDERSIZE,
+-	SK_PNMI_HRX_OVERFLOW,
+-	SK_PNMI_HRX_JABBER,
+-	SK_PNMI_HRX_CARRIER,
+-	SK_PNMI_HRX_IRLENGTH,
+-	SK_PNMI_HRX_SYMBOL,
+-	SK_PNMI_HRX_SHORTS,
+-	SK_PNMI_HRX_RUNT,
+-	SK_PNMI_HRX_TOO_LONG,
+-	SK_PNMI_HRX_FCS,
+-	SK_PNMI_HRX_CEXT,
+-	SK_PNMI_HRX_UTILUNDER,
+-	SK_PNMI_HRX_UTILOVER,
+-	SK_PNMI_HRX_64,
+-	SK_PNMI_HRX_127,
+-	SK_PNMI_HRX_255,
+-	SK_PNMI_HRX_511,
+-	SK_PNMI_HRX_1023,
+-	SK_PNMI_HRX_MAX,
+-	SK_PNMI_HRX_LONGFRAMES,
+-	
+-	SK_PNMI_HRX_RESERVED,
+-	
+-	SK_PNMI_MAX_IDX		/* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */
+-};
+-
+-/*
+- * MAC specific data
+- */
+-typedef struct s_PnmiStatAddr {
+-	SK_U16		Reg;		/* MAC register containing the value */
+-	SK_BOOL		GetOffset;	/* TRUE: Offset managed by PNMI (call GetStatVal())*/
+-} SK_PNMI_STATADDR;
+-
+-
+-/*
+- * SK_PNMI_STRUCT_DATA copy offset evaluation macros
+- */
+-#define SK_PNMI_OFF(e)		((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
+-#define SK_PNMI_MAI_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
+-#define SK_PNMI_VPD_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e))
+-#define SK_PNMI_SEN_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e))
+-#define SK_PNMI_CHK_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e))
+-#define SK_PNMI_STA_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e))
+-#define SK_PNMI_CNF_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e))
+-#define SK_PNMI_RLM_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e))
+-#define SK_PNMI_MON_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e))
+-#define SK_PNMI_TRP_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e))
+-
+-#define SK_PNMI_SET_STAT(b,s,o)	{SK_U32	Val32; char *pVal; \
+-					Val32 = (s); \
+-					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
+-						&(((SK_PNMI_STRUCT_DATA *)0)-> \
+-						ReturnStatus.ErrorStatus)); \
+-					SK_PNMI_STORE_U32(pVal, Val32); \
+-					Val32 = (o); \
+-					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
+-						&(((SK_PNMI_STRUCT_DATA *)0)-> \
+-						ReturnStatus.ErrorOffset)); \
+-					SK_PNMI_STORE_U32(pVal, Val32);}
+-
+-/*
+- * Time macros
+- */
+-#ifndef SK_PNMI_HUNDREDS_SEC
+-#if SK_TICKS_PER_SEC == 100
+-#define SK_PNMI_HUNDREDS_SEC(t)	(t)
+-#else
+-#define SK_PNMI_HUNDREDS_SEC(t)	(((t) * 100) / (SK_TICKS_PER_SEC))
+-#endif /* !SK_TICKS_PER_SEC */
+-#endif /* !SK_PNMI_HUNDREDS_SEC */
+-
+-/*
+- * Macros to work around alignment problems
+- */
+-#ifndef SK_PNMI_STORE_U16
+-#define SK_PNMI_STORE_U16(p,v)	{*(char *)(p) = *((char *)&(v)); \
+-					*((char *)(p) + 1) = \
+-						*(((char *)&(v)) + 1);}
+-#endif
+-
+-#ifndef SK_PNMI_STORE_U32
+-#define SK_PNMI_STORE_U32(p,v)	{*(char *)(p) = *((char *)&(v)); \
+-					*((char *)(p) + 1) = \
+-						*(((char *)&(v)) + 1); \
+-					*((char *)(p) + 2) = \
+-						*(((char *)&(v)) + 2); \
+-					*((char *)(p) + 3) = \
+-						*(((char *)&(v)) + 3);}
+-#endif
+-
+-#ifndef SK_PNMI_STORE_U64
+-#define SK_PNMI_STORE_U64(p,v)	{*(char *)(p) = *((char *)&(v)); \
+-					*((char *)(p) + 1) = \
+-						*(((char *)&(v)) + 1); \
+-					*((char *)(p) + 2) = \
+-						*(((char *)&(v)) + 2); \
+-					*((char *)(p) + 3) = \
+-						*(((char *)&(v)) + 3); \
+-					*((char *)(p) + 4) = \
+-						*(((char *)&(v)) + 4); \
+-					*((char *)(p) + 5) = \
+-						*(((char *)&(v)) + 5); \
+-					*((char *)(p) + 6) = \
+-						*(((char *)&(v)) + 6); \
+-					*((char *)(p) + 7) = \
+-						*(((char *)&(v)) + 7);}
+-#endif
+-
+-#ifndef SK_PNMI_READ_U16
+-#define SK_PNMI_READ_U16(p,v)	{*((char *)&(v)) = *(char *)(p); \
+-					*(((char *)&(v)) + 1) = \
+-						*((char *)(p) + 1);}
+-#endif
+-
+-#ifndef SK_PNMI_READ_U32
+-#define SK_PNMI_READ_U32(p,v)	{*((char *)&(v)) = *(char *)(p); \
+-					*(((char *)&(v)) + 1) = \
+-						*((char *)(p) + 1); \
+-					*(((char *)&(v)) + 2) = \
+-						*((char *)(p) + 2); \
+-					*(((char *)&(v)) + 3) = \
+-						*((char *)(p) + 3);}
+-#endif
+-
+-#ifndef SK_PNMI_READ_U64
+-#define SK_PNMI_READ_U64(p,v)	{*((char *)&(v)) = *(char *)(p); \
+-					*(((char *)&(v)) + 1) = \
+-						*((char *)(p) + 1); \
+-					*(((char *)&(v)) + 2) = \
+-						*((char *)(p) + 2); \
+-					*(((char *)&(v)) + 3) = \
+-						*((char *)(p) + 3); \
+-					*(((char *)&(v)) + 4) = \
+-						*((char *)(p) + 4); \
+-					*(((char *)&(v)) + 5) = \
+-						*((char *)(p) + 5); \
+-					*(((char *)&(v)) + 6) = \
+-						*((char *)(p) + 6); \
+-					*(((char *)&(v)) + 7) = \
+-						*((char *)(p) + 7);}
+-#endif
+-
+-/*
+- * Macros for Debug
+- */
+-#ifdef DEBUG
+-
+-#define SK_PNMI_CHECKFLAGS(vSt)	{if (pAC->Pnmi.MacUpdatedFlag > 0 || \
+-					pAC->Pnmi.RlmtUpdatedFlag > 0 || \
+-					pAC->Pnmi.SirqUpdatedFlag > 0) { \
+-						SK_DBG_MSG(pAC, \
+-						SK_DBGMOD_PNMI, \
+-						SK_DBGCAT_CTRL,	\
+-						("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \
+-						vSt, \
+-						pAC->Pnmi.MacUpdatedFlag, \
+-						pAC->Pnmi.RlmtUpdatedFlag, \
+-						pAC->Pnmi.SirqUpdatedFlag))}}
+-
+-#else	/* !DEBUG */
+-
+-#define SK_PNMI_CHECKFLAGS(vSt)	/* Nothing */
+-
+-#endif	/* !DEBUG */
+-
+-#endif	/* _SKGEPNM2_H_ */
+diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h
+deleted file mode 100644
+index 1ed214c..0000000
+--- a/drivers/net/sk98lin/h/skgepnmi.h
++++ /dev/null
+@@ -1,962 +0,0 @@
+-/*****************************************************************************
+- *
+- * Name:	skgepnmi.h
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.62 $
+- * Date:	$Date: 2003/08/15 12:31:52 $
+- * Purpose:	Defines for Private Network Management Interface
+- *
+- ****************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef _SKGEPNMI_H_
+-#define _SKGEPNMI_H_
+-
+-/*
+- * Include dependencies
+- */
+-#include "h/sktypes.h"
+-#include "h/skerror.h"
+-#include "h/sktimer.h"
+-#include "h/ski2c.h"
+-#include "h/skaddr.h"
+-#include "h/skrlmt.h"
+-#include "h/skvpd.h"
+-
+-/*
+- * Management Database Version
+- */
+-#define SK_PNMI_MDB_VERSION		0x00030001	/* 3.1 */
+-
+-
+-/*
+- * Event definitions
+- */
+-#define SK_PNMI_EVT_SIRQ_OVERFLOW		1	/* Counter overflow */
+-#define SK_PNMI_EVT_SEN_WAR_LOW			2	/* Lower war thres exceeded */
+-#define SK_PNMI_EVT_SEN_WAR_UPP			3	/* Upper war thres exceeded */
+-#define SK_PNMI_EVT_SEN_ERR_LOW			4	/* Lower err thres exceeded */
+-#define SK_PNMI_EVT_SEN_ERR_UPP			5	/* Upper err thres exceeded */
+-#define SK_PNMI_EVT_CHG_EST_TIMER		6	/* Timer event for RLMT Chg */
+-#define SK_PNMI_EVT_UTILIZATION_TIMER	7	/* Timer event for Utiliza. */
+-#define SK_PNMI_EVT_CLEAR_COUNTER		8	/* Clear statistic counters */
+-#define SK_PNMI_EVT_XMAC_RESET			9	/* XMAC will be reset */
+-
+-#define SK_PNMI_EVT_RLMT_PORT_UP		10	/* Port came logically up */
+-#define SK_PNMI_EVT_RLMT_PORT_DOWN		11	/* Port went logically down */
+-#define SK_PNMI_EVT_RLMT_SEGMENTATION	13	/* Two SP root bridges found */
+-#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN	14	/* Port went logically down */
+-#define SK_PNMI_EVT_RLMT_ACTIVE_UP		15	/* Port came logically up */
+-#define SK_PNMI_EVT_RLMT_SET_NETS		16	/* 1. Parameter is number of nets
+-												1 = single net; 2 = dual net */
+-#define SK_PNMI_EVT_VCT_RESET		17	/* VCT port reset timer event started with SET. */
+-
+-
+-/*
+- * Return values
+- */
+-#define SK_PNMI_ERR_OK				0
+-#define SK_PNMI_ERR_GENERAL			1
+-#define SK_PNMI_ERR_TOO_SHORT		2
+-#define SK_PNMI_ERR_BAD_VALUE		3
+-#define SK_PNMI_ERR_READ_ONLY		4
+-#define SK_PNMI_ERR_UNKNOWN_OID		5
+-#define SK_PNMI_ERR_UNKNOWN_INST	6
+-#define SK_PNMI_ERR_UNKNOWN_NET 	7
+-#define SK_PNMI_ERR_NOT_SUPPORTED	10
+-
+-
+-/*
+- * Return values of driver reset function SK_DRIVER_RESET() and
+- * driver event function SK_DRIVER_EVENT()
+- */
+-#define SK_PNMI_ERR_OK			0
+-#define SK_PNMI_ERR_FAIL		1
+-
+-
+-/*
+- * Return values of driver test function SK_DRIVER_SELFTEST()
+- */
+-#define SK_PNMI_TST_UNKNOWN		(1 << 0)
+-#define SK_PNMI_TST_TRANCEIVER		(1 << 1)
+-#define SK_PNMI_TST_ASIC		(1 << 2)
+-#define SK_PNMI_TST_SENSOR		(1 << 3)
+-#define SK_PNMI_TST_POWERMGMT		(1 << 4)
+-#define SK_PNMI_TST_PCI			(1 << 5)
+-#define SK_PNMI_TST_MAC			(1 << 6)
+-
+-
+-/*
+- * RLMT specific definitions
+- */
+-#define SK_PNMI_RLMT_STATUS_STANDBY	1
+-#define SK_PNMI_RLMT_STATUS_ACTIVE	2
+-#define SK_PNMI_RLMT_STATUS_ERROR	3
+-
+-#define SK_PNMI_RLMT_LSTAT_PHY_DOWN	1
+-#define SK_PNMI_RLMT_LSTAT_AUTONEG	2
+-#define SK_PNMI_RLMT_LSTAT_LOG_DOWN	3
+-#define SK_PNMI_RLMT_LSTAT_LOG_UP	4
+-#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5
+-
+-#define SK_PNMI_RLMT_MODE_CHK_LINK	(SK_RLMT_CHECK_LINK)
+-#define SK_PNMI_RLMT_MODE_CHK_RX	(SK_RLMT_CHECK_LOC_LINK)
+-#define SK_PNMI_RLMT_MODE_CHK_SPT	(SK_RLMT_CHECK_SEG)
+-/* #define SK_PNMI_RLMT_MODE_CHK_EX */
+-
+-/*
+- * OID definition
+- */
+-#ifndef _NDIS_	/* Check, whether NDIS already included OIDs */
+-
+-#define OID_GEN_XMIT_OK					0x00020101
+-#define OID_GEN_RCV_OK					0x00020102
+-#define OID_GEN_XMIT_ERROR				0x00020103
+-#define OID_GEN_RCV_ERROR				0x00020104
+-#define OID_GEN_RCV_NO_BUFFER			0x00020105
+-
+-/* #define OID_GEN_DIRECTED_BYTES_XMIT	0x00020201 */
+-#define OID_GEN_DIRECTED_FRAMES_XMIT	0x00020202
+-/* #define OID_GEN_MULTICAST_BYTES_XMIT	0x00020203 */
+-#define OID_GEN_MULTICAST_FRAMES_XMIT	0x00020204
+-/* #define OID_GEN_BROADCAST_BYTES_XMIT	0x00020205 */
+-#define OID_GEN_BROADCAST_FRAMES_XMIT	0x00020206
+-/* #define OID_GEN_DIRECTED_BYTES_RCV	0x00020207 */
+-#define OID_GEN_DIRECTED_FRAMES_RCV		0x00020208
+-/* #define OID_GEN_MULTICAST_BYTES_RCV	0x00020209 */
+-#define OID_GEN_MULTICAST_FRAMES_RCV	0x0002020A
+-/* #define OID_GEN_BROADCAST_BYTES_RCV	0x0002020B */
+-#define OID_GEN_BROADCAST_FRAMES_RCV	0x0002020C
+-#define OID_GEN_RCV_CRC_ERROR			0x0002020D
+-#define OID_GEN_TRANSMIT_QUEUE_LENGTH	0x0002020E
+-
+-#define OID_802_3_PERMANENT_ADDRESS		0x01010101
+-#define OID_802_3_CURRENT_ADDRESS		0x01010102
+-/* #define OID_802_3_MULTICAST_LIST		0x01010103 */
+-/* #define OID_802_3_MAXIMUM_LIST_SIZE	0x01010104 */
+-/* #define OID_802_3_MAC_OPTIONS		0x01010105 */
+-			
+-#define OID_802_3_RCV_ERROR_ALIGNMENT	0x01020101
+-#define OID_802_3_XMIT_ONE_COLLISION	0x01020102
+-#define OID_802_3_XMIT_MORE_COLLISIONS	0x01020103
+-#define OID_802_3_XMIT_DEFERRED			0x01020201
+-#define OID_802_3_XMIT_MAX_COLLISIONS	0x01020202
+-#define OID_802_3_RCV_OVERRUN			0x01020203
+-#define OID_802_3_XMIT_UNDERRUN			0x01020204
+-#define OID_802_3_XMIT_TIMES_CRS_LOST	0x01020206
+-#define OID_802_3_XMIT_LATE_COLLISIONS	0x01020207
+-
+-/*
+- * PnP and PM OIDs
+- */
+-#ifdef SK_POWER_MGMT
+-#define OID_PNP_CAPABILITIES			0xFD010100
+-#define OID_PNP_SET_POWER				0xFD010101
+-#define OID_PNP_QUERY_POWER				0xFD010102
+-#define OID_PNP_ADD_WAKE_UP_PATTERN		0xFD010103
+-#define OID_PNP_REMOVE_WAKE_UP_PATTERN	0xFD010104
+-#define OID_PNP_ENABLE_WAKE_UP			0xFD010106
+-#endif /* SK_POWER_MGMT */
+-
+-#endif /* _NDIS_ */
+-
+-#define OID_SKGE_MDB_VERSION			0xFF010100
+-#define OID_SKGE_SUPPORTED_LIST			0xFF010101
+-#define OID_SKGE_VPD_FREE_BYTES			0xFF010102
+-#define OID_SKGE_VPD_ENTRIES_LIST		0xFF010103
+-#define OID_SKGE_VPD_ENTRIES_NUMBER		0xFF010104
+-#define OID_SKGE_VPD_KEY				0xFF010105
+-#define OID_SKGE_VPD_VALUE				0xFF010106
+-#define OID_SKGE_VPD_ACCESS				0xFF010107
+-#define OID_SKGE_VPD_ACTION				0xFF010108
+-			
+-#define OID_SKGE_PORT_NUMBER			0xFF010110
+-#define OID_SKGE_DEVICE_TYPE			0xFF010111
+-#define OID_SKGE_DRIVER_DESCR			0xFF010112
+-#define OID_SKGE_DRIVER_VERSION			0xFF010113
+-#define OID_SKGE_HW_DESCR				0xFF010114
+-#define OID_SKGE_HW_VERSION				0xFF010115
+-#define OID_SKGE_CHIPSET				0xFF010116
+-#define OID_SKGE_ACTION					0xFF010117
+-#define OID_SKGE_RESULT					0xFF010118
+-#define OID_SKGE_BUS_TYPE				0xFF010119
+-#define OID_SKGE_BUS_SPEED				0xFF01011A
+-#define OID_SKGE_BUS_WIDTH				0xFF01011B
+-/* 0xFF01011C unused */
+-#define OID_SKGE_DIAG_ACTION			0xFF01011D
+-#define OID_SKGE_DIAG_RESULT			0xFF01011E
+-#define OID_SKGE_MTU					0xFF01011F
+-#define OID_SKGE_PHYS_CUR_ADDR			0xFF010120
+-#define OID_SKGE_PHYS_FAC_ADDR			0xFF010121
+-#define OID_SKGE_PMD					0xFF010122
+-#define OID_SKGE_CONNECTOR				0xFF010123
+-#define OID_SKGE_LINK_CAP				0xFF010124
+-#define OID_SKGE_LINK_MODE				0xFF010125
+-#define OID_SKGE_LINK_MODE_STATUS		0xFF010126
+-#define OID_SKGE_LINK_STATUS			0xFF010127
+-#define OID_SKGE_FLOWCTRL_CAP			0xFF010128
+-#define OID_SKGE_FLOWCTRL_MODE			0xFF010129
+-#define OID_SKGE_FLOWCTRL_STATUS		0xFF01012A
+-#define OID_SKGE_PHY_OPERATION_CAP		0xFF01012B
+-#define OID_SKGE_PHY_OPERATION_MODE		0xFF01012C
+-#define OID_SKGE_PHY_OPERATION_STATUS	0xFF01012D
+-#define OID_SKGE_MULTICAST_LIST			0xFF01012E
+-#define OID_SKGE_CURRENT_PACKET_FILTER	0xFF01012F
+-
+-#define OID_SKGE_TRAP					0xFF010130
+-#define OID_SKGE_TRAP_NUMBER			0xFF010131
+-
+-#define OID_SKGE_RLMT_MODE				0xFF010140
+-#define OID_SKGE_RLMT_PORT_NUMBER		0xFF010141
+-#define OID_SKGE_RLMT_PORT_ACTIVE		0xFF010142
+-#define OID_SKGE_RLMT_PORT_PREFERRED	0xFF010143
+-#define OID_SKGE_INTERMEDIATE_SUPPORT	0xFF010160
+-
+-#define OID_SKGE_SPEED_CAP				0xFF010170
+-#define OID_SKGE_SPEED_MODE				0xFF010171
+-#define OID_SKGE_SPEED_STATUS			0xFF010172
+-
+-#define OID_SKGE_BOARDLEVEL				0xFF010180
+-
+-#define OID_SKGE_SENSOR_NUMBER			0xFF020100			
+-#define OID_SKGE_SENSOR_INDEX			0xFF020101
+-#define OID_SKGE_SENSOR_DESCR			0xFF020102
+-#define OID_SKGE_SENSOR_TYPE			0xFF020103
+-#define OID_SKGE_SENSOR_VALUE			0xFF020104
+-#define OID_SKGE_SENSOR_WAR_THRES_LOW	0xFF020105
+-#define OID_SKGE_SENSOR_WAR_THRES_UPP	0xFF020106
+-#define OID_SKGE_SENSOR_ERR_THRES_LOW	0xFF020107
+-#define OID_SKGE_SENSOR_ERR_THRES_UPP	0xFF020108
+-#define OID_SKGE_SENSOR_STATUS			0xFF020109
+-#define OID_SKGE_SENSOR_WAR_CTS			0xFF02010A
+-#define OID_SKGE_SENSOR_ERR_CTS			0xFF02010B
+-#define OID_SKGE_SENSOR_WAR_TIME		0xFF02010C
+-#define OID_SKGE_SENSOR_ERR_TIME		0xFF02010D
+-
+-#define OID_SKGE_CHKSM_NUMBER			0xFF020110
+-#define OID_SKGE_CHKSM_RX_OK_CTS		0xFF020111
+-#define OID_SKGE_CHKSM_RX_UNABLE_CTS	0xFF020112
+-#define OID_SKGE_CHKSM_RX_ERR_CTS		0xFF020113
+-#define OID_SKGE_CHKSM_TX_OK_CTS		0xFF020114
+-#define OID_SKGE_CHKSM_TX_UNABLE_CTS	0xFF020115
+-
+-#define OID_SKGE_STAT_TX				0xFF020120
+-#define OID_SKGE_STAT_TX_OCTETS			0xFF020121
+-#define OID_SKGE_STAT_TX_BROADCAST		0xFF020122
+-#define OID_SKGE_STAT_TX_MULTICAST		0xFF020123
+-#define OID_SKGE_STAT_TX_UNICAST		0xFF020124
+-#define OID_SKGE_STAT_TX_LONGFRAMES		0xFF020125
+-#define OID_SKGE_STAT_TX_BURST			0xFF020126
+-#define OID_SKGE_STAT_TX_PFLOWC			0xFF020127
+-#define OID_SKGE_STAT_TX_FLOWC			0xFF020128
+-#define OID_SKGE_STAT_TX_SINGLE_COL		0xFF020129
+-#define OID_SKGE_STAT_TX_MULTI_COL		0xFF02012A
+-#define OID_SKGE_STAT_TX_EXCESS_COL		0xFF02012B
+-#define OID_SKGE_STAT_TX_LATE_COL		0xFF02012C
+-#define OID_SKGE_STAT_TX_DEFFERAL		0xFF02012D
+-#define OID_SKGE_STAT_TX_EXCESS_DEF		0xFF02012E
+-#define OID_SKGE_STAT_TX_UNDERRUN		0xFF02012F
+-#define OID_SKGE_STAT_TX_CARRIER		0xFF020130
+-/* #define OID_SKGE_STAT_TX_UTIL		0xFF020131 */
+-#define OID_SKGE_STAT_TX_64				0xFF020132
+-#define OID_SKGE_STAT_TX_127			0xFF020133
+-#define OID_SKGE_STAT_TX_255			0xFF020134
+-#define OID_SKGE_STAT_TX_511			0xFF020135
+-#define OID_SKGE_STAT_TX_1023			0xFF020136
+-#define OID_SKGE_STAT_TX_MAX			0xFF020137
+-#define OID_SKGE_STAT_TX_SYNC			0xFF020138
+-#define OID_SKGE_STAT_TX_SYNC_OCTETS	0xFF020139
+-#define OID_SKGE_STAT_RX				0xFF02013A
+-#define OID_SKGE_STAT_RX_OCTETS			0xFF02013B
+-#define OID_SKGE_STAT_RX_BROADCAST		0xFF02013C
+-#define OID_SKGE_STAT_RX_MULTICAST		0xFF02013D
+-#define OID_SKGE_STAT_RX_UNICAST		0xFF02013E
+-#define OID_SKGE_STAT_RX_PFLOWC			0xFF02013F
+-#define OID_SKGE_STAT_RX_FLOWC			0xFF020140
+-#define OID_SKGE_STAT_RX_PFLOWC_ERR		0xFF020141
+-#define OID_SKGE_STAT_RX_FLOWC_UNKWN	0xFF020142
+-#define OID_SKGE_STAT_RX_BURST			0xFF020143
+-#define OID_SKGE_STAT_RX_MISSED			0xFF020144
+-#define OID_SKGE_STAT_RX_FRAMING		0xFF020145
+-#define OID_SKGE_STAT_RX_OVERFLOW		0xFF020146
+-#define OID_SKGE_STAT_RX_JABBER			0xFF020147
+-#define OID_SKGE_STAT_RX_CARRIER		0xFF020148
+-#define OID_SKGE_STAT_RX_IR_LENGTH		0xFF020149
+-#define OID_SKGE_STAT_RX_SYMBOL			0xFF02014A
+-#define OID_SKGE_STAT_RX_SHORTS			0xFF02014B
+-#define OID_SKGE_STAT_RX_RUNT			0xFF02014C
+-#define OID_SKGE_STAT_RX_CEXT			0xFF02014D
+-#define OID_SKGE_STAT_RX_TOO_LONG		0xFF02014E
+-#define OID_SKGE_STAT_RX_FCS			0xFF02014F
+-/* #define OID_SKGE_STAT_RX_UTIL		0xFF020150 */
+-#define OID_SKGE_STAT_RX_64				0xFF020151
+-#define OID_SKGE_STAT_RX_127			0xFF020152
+-#define OID_SKGE_STAT_RX_255			0xFF020153
+-#define OID_SKGE_STAT_RX_511			0xFF020154
+-#define OID_SKGE_STAT_RX_1023			0xFF020155
+-#define OID_SKGE_STAT_RX_MAX			0xFF020156
+-#define OID_SKGE_STAT_RX_LONGFRAMES		0xFF020157
+-
+-#define OID_SKGE_RLMT_CHANGE_CTS		0xFF020160
+-#define OID_SKGE_RLMT_CHANGE_TIME		0xFF020161
+-#define OID_SKGE_RLMT_CHANGE_ESTIM		0xFF020162
+-#define OID_SKGE_RLMT_CHANGE_THRES		0xFF020163
+-
+-#define OID_SKGE_RLMT_PORT_INDEX		0xFF020164
+-#define OID_SKGE_RLMT_STATUS			0xFF020165
+-#define OID_SKGE_RLMT_TX_HELLO_CTS		0xFF020166
+-#define OID_SKGE_RLMT_RX_HELLO_CTS		0xFF020167
+-#define OID_SKGE_RLMT_TX_SP_REQ_CTS		0xFF020168
+-#define OID_SKGE_RLMT_RX_SP_CTS			0xFF020169
+-
+-#define OID_SKGE_RLMT_MONITOR_NUMBER	0xFF010150
+-#define OID_SKGE_RLMT_MONITOR_INDEX		0xFF010151
+-#define OID_SKGE_RLMT_MONITOR_ADDR		0xFF010152
+-#define OID_SKGE_RLMT_MONITOR_ERRS		0xFF010153
+-#define OID_SKGE_RLMT_MONITOR_TIMESTAMP	0xFF010154
+-#define OID_SKGE_RLMT_MONITOR_ADMIN		0xFF010155
+-
+-#define OID_SKGE_TX_SW_QUEUE_LEN		0xFF020170
+-#define OID_SKGE_TX_SW_QUEUE_MAX		0xFF020171
+-#define OID_SKGE_TX_RETRY				0xFF020172
+-#define OID_SKGE_RX_INTR_CTS			0xFF020173
+-#define OID_SKGE_TX_INTR_CTS			0xFF020174
+-#define OID_SKGE_RX_NO_BUF_CTS			0xFF020175
+-#define OID_SKGE_TX_NO_BUF_CTS			0xFF020176
+-#define OID_SKGE_TX_USED_DESCR_NO		0xFF020177
+-#define OID_SKGE_RX_DELIVERED_CTS		0xFF020178
+-#define OID_SKGE_RX_OCTETS_DELIV_CTS	0xFF020179
+-#define OID_SKGE_RX_HW_ERROR_CTS		0xFF02017A
+-#define OID_SKGE_TX_HW_ERROR_CTS		0xFF02017B
+-#define OID_SKGE_IN_ERRORS_CTS			0xFF02017C
+-#define OID_SKGE_OUT_ERROR_CTS			0xFF02017D
+-#define OID_SKGE_ERR_RECOVERY_CTS		0xFF02017E
+-#define OID_SKGE_SYSUPTIME				0xFF02017F
+-
+-#define OID_SKGE_ALL_DATA				0xFF020190
+-
+-/* Defines for VCT. */
+-#define OID_SKGE_VCT_GET				0xFF020200
+-#define OID_SKGE_VCT_SET				0xFF020201
+-#define OID_SKGE_VCT_STATUS				0xFF020202
+-
+-#ifdef SK_DIAG_SUPPORT
+-/* Defines for driver DIAG mode. */
+-#define OID_SKGE_DIAG_MODE				0xFF020204
+-#endif /* SK_DIAG_SUPPORT */
+-
+-/* New OIDs */
+-#define OID_SKGE_DRIVER_RELDATE			0xFF020210
+-#define OID_SKGE_DRIVER_FILENAME		0xFF020211
+-#define OID_SKGE_CHIPID					0xFF020212
+-#define OID_SKGE_RAMSIZE				0xFF020213
+-#define OID_SKGE_VAUXAVAIL				0xFF020214
+-#define OID_SKGE_PHY_TYPE				0xFF020215
+-#define OID_SKGE_PHY_LP_MODE			0xFF020216
+-
+-/* VCT struct to store a backup copy of VCT data after a port reset. */
+-typedef struct s_PnmiVct {
+-	SK_U8			VctStatus;
+-	SK_U8			PCableLen;
+-	SK_U32			PMdiPairLen[4];
+-	SK_U8			PMdiPairSts[4];
+-} SK_PNMI_VCT;
+-
+-
+-/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */
+-#define SK_PNMI_VCT_NONE		0
+-#define SK_PNMI_VCT_OLD_VCT_DATA	1
+-#define SK_PNMI_VCT_NEW_VCT_DATA	2
+-#define SK_PNMI_VCT_OLD_DSP_DATA	4
+-#define SK_PNMI_VCT_NEW_DSP_DATA	8
+-#define SK_PNMI_VCT_RUNNING		16
+-
+-
+-/* VCT cable test status. */
+-#define SK_PNMI_VCT_NORMAL_CABLE		0
+-#define SK_PNMI_VCT_SHORT_CABLE			1
+-#define SK_PNMI_VCT_OPEN_CABLE			2
+-#define SK_PNMI_VCT_TEST_FAIL			3
+-#define SK_PNMI_VCT_IMPEDANCE_MISMATCH		4
+-
+-#define	OID_SKGE_TRAP_SEN_WAR_LOW		500
+-#define OID_SKGE_TRAP_SEN_WAR_UPP		501
+-#define	OID_SKGE_TRAP_SEN_ERR_LOW		502
+-#define OID_SKGE_TRAP_SEN_ERR_UPP		503
+-#define OID_SKGE_TRAP_RLMT_CHANGE_THRES	520
+-#define OID_SKGE_TRAP_RLMT_CHANGE_PORT	521
+-#define OID_SKGE_TRAP_RLMT_PORT_DOWN	522
+-#define OID_SKGE_TRAP_RLMT_PORT_UP		523
+-#define OID_SKGE_TRAP_RLMT_SEGMENTATION	524
+-
+-#ifdef SK_DIAG_SUPPORT
+-/* Defines for driver DIAG mode. */
+-#define SK_DIAG_ATTACHED	2
+-#define SK_DIAG_RUNNING		1
+-#define SK_DIAG_IDLE		0
+-#endif /* SK_DIAG_SUPPORT */
+-
+-/*
+- * Generic PNMI IOCTL subcommand definitions.
+- */
+-#define	SK_GET_SINGLE_VAR		1
+-#define	SK_SET_SINGLE_VAR		2
+-#define	SK_PRESET_SINGLE_VAR	3
+-#define	SK_GET_FULL_MIB			4
+-#define	SK_SET_FULL_MIB			5
+-#define	SK_PRESET_FULL_MIB		6
+-
+-
+-/*
+- * Define error numbers and messages for syslog
+- */
+-#define SK_PNMI_ERR001		(SK_ERRBASE_PNMI + 1)
+-#define SK_PNMI_ERR001MSG	"SkPnmiGetStruct: Unknown OID"
+-#define SK_PNMI_ERR002		(SK_ERRBASE_PNMI + 2)
+-#define SK_PNMI_ERR002MSG	"SkPnmiGetStruct: Cannot read VPD keys"
+-#define SK_PNMI_ERR003		(SK_ERRBASE_PNMI + 3)
+-#define SK_PNMI_ERR003MSG	"OidStruct: Called with wrong OID"
+-#define SK_PNMI_ERR004		(SK_ERRBASE_PNMI + 4)
+-#define SK_PNMI_ERR004MSG	"OidStruct: Called with wrong action"
+-#define SK_PNMI_ERR005		(SK_ERRBASE_PNMI + 5)
+-#define SK_PNMI_ERR005MSG	"Perform: Cannot reset driver"
+-#define SK_PNMI_ERR006		(SK_ERRBASE_PNMI + 6)
+-#define SK_PNMI_ERR006MSG	"Perform: Unknown OID action command"
+-#define SK_PNMI_ERR007		(SK_ERRBASE_PNMI + 7)
+-#define SK_PNMI_ERR007MSG	"General: Driver description not initialized"
+-#define SK_PNMI_ERR008		(SK_ERRBASE_PNMI + 8)
+-#define SK_PNMI_ERR008MSG	"Addr: Tried to get unknown OID"
+-#define SK_PNMI_ERR009		(SK_ERRBASE_PNMI + 9)
+-#define SK_PNMI_ERR009MSG	"Addr: Unknown OID"
+-#define SK_PNMI_ERR010		(SK_ERRBASE_PNMI + 10)
+-#define SK_PNMI_ERR010MSG	"CsumStat: Unknown OID"
+-#define SK_PNMI_ERR011		(SK_ERRBASE_PNMI + 11)
+-#define SK_PNMI_ERR011MSG	"SensorStat: Sensor descr string too long"
+-#define SK_PNMI_ERR012		(SK_ERRBASE_PNMI + 12)
+-#define SK_PNMI_ERR012MSG	"SensorStat: Unknown OID"
+-#define SK_PNMI_ERR013		(SK_ERRBASE_PNMI + 13)
+-#define SK_PNMI_ERR013MSG	""
+-#define SK_PNMI_ERR014		(SK_ERRBASE_PNMI + 14)
+-#define SK_PNMI_ERR014MSG	"Vpd: Cannot read VPD keys"
+-#define SK_PNMI_ERR015		(SK_ERRBASE_PNMI + 15)
+-#define SK_PNMI_ERR015MSG	"Vpd: Internal array for VPD keys to small"
+-#define SK_PNMI_ERR016		(SK_ERRBASE_PNMI + 16)
+-#define SK_PNMI_ERR016MSG	"Vpd: Key string too long"
+-#define SK_PNMI_ERR017		(SK_ERRBASE_PNMI + 17)
+-#define SK_PNMI_ERR017MSG	"Vpd: Invalid VPD status pointer"
+-#define SK_PNMI_ERR018		(SK_ERRBASE_PNMI + 18)
+-#define SK_PNMI_ERR018MSG	"Vpd: VPD data not valid"
+-#define SK_PNMI_ERR019		(SK_ERRBASE_PNMI + 19)
+-#define SK_PNMI_ERR019MSG	"Vpd: VPD entries list string too long"
+-#define SK_PNMI_ERR021		(SK_ERRBASE_PNMI + 21)
+-#define SK_PNMI_ERR021MSG	"Vpd: VPD data string too long"
+-#define SK_PNMI_ERR022		(SK_ERRBASE_PNMI + 22)
+-#define SK_PNMI_ERR022MSG	"Vpd: VPD data string too long should be errored before"
+-#define SK_PNMI_ERR023		(SK_ERRBASE_PNMI + 23)
+-#define SK_PNMI_ERR023MSG	"Vpd: Unknown OID in get action"
+-#define SK_PNMI_ERR024		(SK_ERRBASE_PNMI + 24)
+-#define SK_PNMI_ERR024MSG	"Vpd: Unknown OID in preset/set action"
+-#define SK_PNMI_ERR025		(SK_ERRBASE_PNMI + 25)
+-#define SK_PNMI_ERR025MSG	"Vpd: Cannot write VPD after modify entry"
+-#define SK_PNMI_ERR026		(SK_ERRBASE_PNMI + 26)
+-#define SK_PNMI_ERR026MSG	"Vpd: Cannot update VPD"
+-#define SK_PNMI_ERR027		(SK_ERRBASE_PNMI + 27)
+-#define SK_PNMI_ERR027MSG	"Vpd: Cannot delete VPD entry"
+-#define SK_PNMI_ERR028		(SK_ERRBASE_PNMI + 28)
+-#define SK_PNMI_ERR028MSG	"Vpd: Cannot update VPD after delete entry"
+-#define SK_PNMI_ERR029		(SK_ERRBASE_PNMI + 29)
+-#define SK_PNMI_ERR029MSG	"General: Driver description string too long"
+-#define SK_PNMI_ERR030		(SK_ERRBASE_PNMI + 30)
+-#define SK_PNMI_ERR030MSG	"General: Driver version not initialized"
+-#define SK_PNMI_ERR031		(SK_ERRBASE_PNMI + 31)
+-#define SK_PNMI_ERR031MSG	"General: Driver version string too long"
+-#define SK_PNMI_ERR032		(SK_ERRBASE_PNMI + 32)
+-#define SK_PNMI_ERR032MSG	"General: Cannot read VPD Name for HW descr"
+-#define SK_PNMI_ERR033		(SK_ERRBASE_PNMI + 33)
+-#define SK_PNMI_ERR033MSG	"General: HW description string too long"
+-#define SK_PNMI_ERR034		(SK_ERRBASE_PNMI + 34)
+-#define SK_PNMI_ERR034MSG	"General: Unknown OID"
+-#define SK_PNMI_ERR035		(SK_ERRBASE_PNMI + 35)
+-#define SK_PNMI_ERR035MSG	"Rlmt: Unknown OID"
+-#define SK_PNMI_ERR036		(SK_ERRBASE_PNMI + 36)
+-#define SK_PNMI_ERR036MSG	""
+-#define SK_PNMI_ERR037		(SK_ERRBASE_PNMI + 37)
+-#define SK_PNMI_ERR037MSG	"Rlmt: SK_RLMT_MODE_CHANGE event return not 0"
+-#define SK_PNMI_ERR038		(SK_ERRBASE_PNMI + 38)
+-#define SK_PNMI_ERR038MSG	"Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0"
+-#define SK_PNMI_ERR039		(SK_ERRBASE_PNMI + 39)
+-#define SK_PNMI_ERR039MSG	"RlmtStat: Unknown OID"
+-#define SK_PNMI_ERR040		(SK_ERRBASE_PNMI + 40)
+-#define SK_PNMI_ERR040MSG	"PowerManagement: Unknown OID"
+-#define SK_PNMI_ERR041		(SK_ERRBASE_PNMI + 41)
+-#define SK_PNMI_ERR041MSG	"MacPrivateConf: Unknown OID"
+-#define SK_PNMI_ERR042		(SK_ERRBASE_PNMI + 42)
+-#define SK_PNMI_ERR042MSG	"MacPrivateConf: SK_HWEV_SET_ROLE returned not 0"
+-#define SK_PNMI_ERR043		(SK_ERRBASE_PNMI + 43)
+-#define SK_PNMI_ERR043MSG	"MacPrivateConf: SK_HWEV_SET_LMODE returned not 0"
+-#define SK_PNMI_ERR044		(SK_ERRBASE_PNMI + 44)
+-#define SK_PNMI_ERR044MSG	"MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0"
+-#define SK_PNMI_ERR045		(SK_ERRBASE_PNMI + 45)
+-#define SK_PNMI_ERR045MSG	"MacPrivateConf: SK_HWEV_SET_SPEED returned not 0"
+-#define SK_PNMI_ERR046		(SK_ERRBASE_PNMI + 46)
+-#define SK_PNMI_ERR046MSG	"Monitor: Unknown OID"
+-#define SK_PNMI_ERR047		(SK_ERRBASE_PNMI + 47)
+-#define SK_PNMI_ERR047MSG	"SirqUpdate: Event function returns not 0"
+-#define SK_PNMI_ERR048		(SK_ERRBASE_PNMI + 48)
+-#define SK_PNMI_ERR048MSG	"RlmtUpdate: Event function returns not 0"
+-#define SK_PNMI_ERR049		(SK_ERRBASE_PNMI + 49)
+-#define SK_PNMI_ERR049MSG	"SkPnmiInit: Invalid size of 'CounterOffset' struct!!"
+-#define SK_PNMI_ERR050		(SK_ERRBASE_PNMI + 50)
+-#define SK_PNMI_ERR050MSG	"SkPnmiInit: Invalid size of 'StatAddr' table!!"
+-#define SK_PNMI_ERR051		(SK_ERRBASE_PNMI + 51)
+-#define SK_PNMI_ERR051MSG	"SkPnmiEvent: Port switch suspicious"
+-#define SK_PNMI_ERR052		(SK_ERRBASE_PNMI + 52)
+-#define SK_PNMI_ERR052MSG	""
+-#define SK_PNMI_ERR053		(SK_ERRBASE_PNMI + 53)
+-#define SK_PNMI_ERR053MSG	"General: Driver release date not initialized"
+-#define SK_PNMI_ERR054		(SK_ERRBASE_PNMI + 54)
+-#define SK_PNMI_ERR054MSG	"General: Driver release date string too long"
+-#define SK_PNMI_ERR055		(SK_ERRBASE_PNMI + 55)
+-#define SK_PNMI_ERR055MSG	"General: Driver file name not initialized"
+-#define SK_PNMI_ERR056		(SK_ERRBASE_PNMI + 56)
+-#define SK_PNMI_ERR056MSG	"General: Driver file name string too long"
+-
+-/*
+- * Management counter macros called by the driver
+- */
+-#define SK_PNMI_SET_DRIVER_DESCR(pAC,v)	((pAC)->Pnmi.pDriverDescription = \
+-	(char *)(v))
+-
+-#define SK_PNMI_SET_DRIVER_VER(pAC,v)	((pAC)->Pnmi.pDriverVersion = \
+-	(char *)(v))
+-
+-#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v)	((pAC)->Pnmi.pDriverReleaseDate = \
+-	(char *)(v))
+-
+-#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v)	((pAC)->Pnmi.pDriverFileName = \
+-	(char *)(v))
+-
+-#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \
+-	{ \
+-		(pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \
+-		if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \
+-			(pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \
+-		} \
+-	}
+-#define SK_PNMI_CNT_TX_RETRY(pAC,p)	(((pAC)->Pnmi.Port[p].TxRetryCts)++)
+-#define SK_PNMI_CNT_RX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].RxIntrCts)++)
+-#define SK_PNMI_CNT_TX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].TxIntrCts)++)
+-#define SK_PNMI_CNT_NO_RX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].RxNoBufCts)++)
+-#define SK_PNMI_CNT_NO_TX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].TxNoBufCts)++)
+-#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \
+-	((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v));
+-#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \
+-	{ \
+-		((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \
+-		(pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \
+-	}
+-#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p)	(((pAC)->Pnmi.Port[p].ErrRecoveryCts)++);
+-
+-#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \
+-	{ \
+-		if ((p) < SK_MAX_MACS) { \
+-			((pAC)->Pnmi.Port[p].StatSyncCts)++; \
+-			(pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \
+-		} \
+-	}
+-
+-#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \
+-	{ \
+-		if ((p) < SK_MAX_MACS) { \
+-			((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \
+-		} \
+-	}
+-
+-#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \
+-	{ \
+-		if ((p) < SK_MAX_MACS) { \
+-			((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \
+-		} \
+-	}
+-
+-#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \
+-	{ \
+-		if ((p) < SK_MAX_MACS) { \
+-			((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \
+-		} \
+-	}
+-
+-/*
+- * Conversion Macros
+- */
+-#define SK_PNMI_PORT_INST2LOG(i)	((unsigned int)(i) - 1)
+-#define SK_PNMI_PORT_LOG2INST(l)	((unsigned int)(l) + 1)
+-#define SK_PNMI_PORT_PHYS2LOG(p)	((unsigned int)(p) + 1)
+-#define SK_PNMI_PORT_LOG2PHYS(pAC,l)	((unsigned int)(l) - 1)
+-#define SK_PNMI_PORT_PHYS2INST(pAC,p)	\
+-	(pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2))
+-#define SK_PNMI_PORT_INST2PHYS(pAC,i)	((unsigned int)(i) - 2)
+-
+-/*
+- * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct
+- */
+-#define SK_PNMI_VPD_KEY_SIZE	5
+-#define SK_PNMI_VPD_BUFSIZE		(VPD_SIZE)
+-#define SK_PNMI_VPD_ENTRIES		(VPD_SIZE / 4)
+-#define SK_PNMI_VPD_DATALEN		128 /*  Number of data bytes */
+-
+-#define SK_PNMI_MULTICAST_LISTLEN	64
+-#define SK_PNMI_SENSOR_ENTRIES		(SK_MAX_SENSORS)
+-#define SK_PNMI_CHECKSUM_ENTRIES	3
+-#define SK_PNMI_MAC_ENTRIES			(SK_MAX_MACS + 1)
+-#define SK_PNMI_MONITOR_ENTRIES		20
+-#define SK_PNMI_TRAP_ENTRIES		10
+-#define SK_PNMI_TRAPLEN				128
+-#define SK_PNMI_STRINGLEN1			80
+-#define SK_PNMI_STRINGLEN2			25
+-#define SK_PNMI_TRAP_QUEUE_LEN		512
+-
+-typedef struct s_PnmiVpd {
+-	char			VpdKey[SK_PNMI_VPD_KEY_SIZE];
+-	char			VpdValue[SK_PNMI_VPD_DATALEN];
+-	SK_U8			VpdAccess;
+-	SK_U8			VpdAction;
+-} SK_PNMI_VPD;
+-
+-typedef struct s_PnmiSensor {
+-	SK_U8			SensorIndex;
+-	char			SensorDescr[SK_PNMI_STRINGLEN2];
+-	SK_U8			SensorType;
+-	SK_U32			SensorValue;
+-	SK_U32			SensorWarningThresholdLow;
+-	SK_U32			SensorWarningThresholdHigh;
+-	SK_U32			SensorErrorThresholdLow;
+-	SK_U32			SensorErrorThresholdHigh;
+-	SK_U8			SensorStatus;
+-	SK_U64			SensorWarningCts;
+-	SK_U64			SensorErrorCts;
+-	SK_U64			SensorWarningTimestamp;
+-	SK_U64			SensorErrorTimestamp;
+-} SK_PNMI_SENSOR;
+-
+-typedef struct s_PnmiChecksum {
+-	SK_U64			ChecksumRxOkCts;
+-	SK_U64			ChecksumRxUnableCts;
+-	SK_U64			ChecksumRxErrCts;
+-	SK_U64			ChecksumTxOkCts;
+-	SK_U64			ChecksumTxUnableCts;
+-} SK_PNMI_CHECKSUM;
+-
+-typedef struct s_PnmiStat {
+-	SK_U64			StatTxOkCts;
+-	SK_U64			StatTxOctetsOkCts;
+-	SK_U64			StatTxBroadcastOkCts;
+-	SK_U64			StatTxMulticastOkCts;
+-	SK_U64			StatTxUnicastOkCts;
+-	SK_U64			StatTxLongFramesCts;
+-	SK_U64			StatTxBurstCts;
+-	SK_U64			StatTxPauseMacCtrlCts;
+-	SK_U64			StatTxMacCtrlCts;
+-	SK_U64			StatTxSingleCollisionCts;
+-	SK_U64			StatTxMultipleCollisionCts;
+-	SK_U64			StatTxExcessiveCollisionCts;
+-	SK_U64			StatTxLateCollisionCts;
+-	SK_U64			StatTxDeferralCts;
+-	SK_U64			StatTxExcessiveDeferralCts;
+-	SK_U64			StatTxFifoUnderrunCts;
+-	SK_U64			StatTxCarrierCts;
+-	SK_U64			Dummy1; /* StatTxUtilization */
+-	SK_U64			StatTx64Cts;
+-	SK_U64			StatTx127Cts;
+-	SK_U64			StatTx255Cts;
+-	SK_U64			StatTx511Cts;
+-	SK_U64			StatTx1023Cts;
+-	SK_U64			StatTxMaxCts;
+-	SK_U64			StatTxSyncCts;
+-	SK_U64			StatTxSyncOctetsCts;
+-	SK_U64			StatRxOkCts;
+-	SK_U64			StatRxOctetsOkCts;
+-	SK_U64			StatRxBroadcastOkCts;
+-	SK_U64			StatRxMulticastOkCts;
+-	SK_U64			StatRxUnicastOkCts;
+-	SK_U64			StatRxLongFramesCts;
+-	SK_U64			StatRxPauseMacCtrlCts;
+-	SK_U64			StatRxMacCtrlCts;
+-	SK_U64			StatRxPauseMacCtrlErrorCts;
+-	SK_U64			StatRxMacCtrlUnknownCts;
+-	SK_U64			StatRxBurstCts;
+-	SK_U64			StatRxMissedCts;
+-	SK_U64			StatRxFramingCts;
+-	SK_U64			StatRxFifoOverflowCts;
+-	SK_U64			StatRxJabberCts;
+-	SK_U64			StatRxCarrierCts;
+-	SK_U64			StatRxIRLengthCts;
+-	SK_U64			StatRxSymbolCts;
+-	SK_U64			StatRxShortsCts;
+-	SK_U64			StatRxRuntCts;
+-	SK_U64			StatRxCextCts;
+-	SK_U64			StatRxTooLongCts;
+-	SK_U64			StatRxFcsCts;
+-	SK_U64			Dummy2; /* StatRxUtilization */
+-	SK_U64			StatRx64Cts;
+-	SK_U64			StatRx127Cts;
+-	SK_U64			StatRx255Cts;
+-	SK_U64			StatRx511Cts;
+-	SK_U64			StatRx1023Cts;
+-	SK_U64			StatRxMaxCts;
+-} SK_PNMI_STAT;
+-
+-typedef struct s_PnmiConf {
+-	char			ConfMacCurrentAddr[6];
+-	char			ConfMacFactoryAddr[6];
+-	SK_U8			ConfPMD;
+-	SK_U8			ConfConnector;
+-	SK_U32			ConfPhyType;
+-	SK_U32			ConfPhyMode;
+-	SK_U8			ConfLinkCapability;
+-	SK_U8			ConfLinkMode;
+-	SK_U8			ConfLinkModeStatus;
+-	SK_U8			ConfLinkStatus;
+-	SK_U8			ConfFlowCtrlCapability;
+-	SK_U8			ConfFlowCtrlMode;
+-	SK_U8			ConfFlowCtrlStatus;
+-	SK_U8			ConfPhyOperationCapability;
+-	SK_U8			ConfPhyOperationMode;
+-	SK_U8			ConfPhyOperationStatus;
+-	SK_U8			ConfSpeedCapability;
+-	SK_U8			ConfSpeedMode;
+-	SK_U8			ConfSpeedStatus;
+-} SK_PNMI_CONF;
+-
+-typedef struct s_PnmiRlmt {
+-	SK_U32			RlmtIndex;
+-	SK_U32			RlmtStatus;
+-	SK_U64			RlmtTxHelloCts;
+-	SK_U64			RlmtRxHelloCts;
+-	SK_U64			RlmtTxSpHelloReqCts;
+-	SK_U64			RlmtRxSpHelloCts;
+-} SK_PNMI_RLMT;
+-
+-typedef struct s_PnmiRlmtMonitor {
+-	SK_U32			RlmtMonitorIndex;
+-	char			RlmtMonitorAddr[6];
+-	SK_U64			RlmtMonitorErrorCts;
+-	SK_U64			RlmtMonitorTimestamp;
+-	SK_U8			RlmtMonitorAdmin;
+-} SK_PNMI_RLMT_MONITOR;
+-
+-typedef struct s_PnmiRequestStatus {
+-	SK_U32			ErrorStatus;
+-	SK_U32			ErrorOffset;
+-} SK_PNMI_REQUEST_STATUS;
+-
+-typedef struct s_PnmiStrucData {
+-	SK_U32			MgmtDBVersion;
+-	SK_PNMI_REQUEST_STATUS	ReturnStatus;
+-	SK_U32			VpdFreeBytes;
+-	char			VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE];
+-	SK_U32			VpdEntriesNumber;
+-	SK_PNMI_VPD		Vpd[SK_PNMI_VPD_ENTRIES];
+-	SK_U32			PortNumber;
+-	SK_U32			DeviceType;
+-	char			DriverDescr[SK_PNMI_STRINGLEN1];
+-	char			DriverVersion[SK_PNMI_STRINGLEN2];
+-	char			DriverReleaseDate[SK_PNMI_STRINGLEN1];
+-	char			DriverFileName[SK_PNMI_STRINGLEN1];
+-	char			HwDescr[SK_PNMI_STRINGLEN1];
+-	char			HwVersion[SK_PNMI_STRINGLEN2];
+-	SK_U16			Chipset;
+-	SK_U32			ChipId;
+-	SK_U8			VauxAvail;
+-	SK_U32			RamSize;
+-	SK_U32			MtuSize;
+-	SK_U32			Action;
+-	SK_U32			TestResult;
+-	SK_U8			BusType;
+-	SK_U8			BusSpeed;
+-	SK_U8			BusWidth;
+-	SK_U8			SensorNumber;
+-	SK_PNMI_SENSOR	Sensor[SK_PNMI_SENSOR_ENTRIES];
+-	SK_U8			ChecksumNumber;
+-	SK_PNMI_CHECKSUM	Checksum[SK_PNMI_CHECKSUM_ENTRIES];
+-	SK_PNMI_STAT	Stat[SK_PNMI_MAC_ENTRIES];
+-	SK_PNMI_CONF	Conf[SK_PNMI_MAC_ENTRIES];
+-	SK_U8			RlmtMode;
+-	SK_U32			RlmtPortNumber;
+-	SK_U8			RlmtPortActive;
+-	SK_U8			RlmtPortPreferred;
+-	SK_U64			RlmtChangeCts;
+-	SK_U64			RlmtChangeTime;
+-	SK_U64			RlmtChangeEstimate;
+-	SK_U64			RlmtChangeThreshold;
+-	SK_PNMI_RLMT	Rlmt[SK_MAX_MACS];
+-	SK_U32			RlmtMonitorNumber;
+-	SK_PNMI_RLMT_MONITOR	RlmtMonitor[SK_PNMI_MONITOR_ENTRIES];
+-	SK_U32			TrapNumber;
+-	SK_U8			Trap[SK_PNMI_TRAP_QUEUE_LEN];
+-	SK_U64			TxSwQueueLen;
+-	SK_U64			TxSwQueueMax;
+-	SK_U64			TxRetryCts;
+-	SK_U64			RxIntrCts;
+-	SK_U64			TxIntrCts;
+-	SK_U64			RxNoBufCts;
+-	SK_U64			TxNoBufCts;
+-	SK_U64			TxUsedDescrNo;
+-	SK_U64			RxDeliveredCts;
+-	SK_U64			RxOctetsDeliveredCts;
+-	SK_U64			RxHwErrorsCts;
+-	SK_U64			TxHwErrorsCts;
+-	SK_U64			InErrorsCts;
+-	SK_U64			OutErrorsCts;
+-	SK_U64			ErrRecoveryCts;
+-	SK_U64			SysUpTime;
+-} SK_PNMI_STRUCT_DATA;
+-
+-#define SK_PNMI_STRUCT_SIZE	(sizeof(SK_PNMI_STRUCT_DATA))
+-#define SK_PNMI_MIN_STRUCT_SIZE	((unsigned int)(SK_UPTR)\
+-				 &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes))
+-														/*
+-														 * ReturnStatus field
+-														 * must be located
+-														 * before VpdFreeBytes
+-														 */
+-
+-/*
+- * Various definitions
+- */
+-#define SK_PNMI_MAX_PROTOS		3
+-
+-#define SK_PNMI_CNT_NO			66	/* Must have the value of the enum
+-									 * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK
+-									 * for check while init phase 1
+-									 */
+-
+-/*
+- * Estimate data structure
+- */
+-typedef struct s_PnmiEstimate {
+-	unsigned int	EstValueIndex;
+-	SK_U64			EstValue[7];
+-	SK_U64			Estimate;
+-	SK_TIMER		EstTimer;
+-} SK_PNMI_ESTIMATE;
+-
+-
+-/*
+- * VCT timer data structure
+- */
+-typedef struct s_VctTimer {
+-	SK_TIMER		VctTimer;
+-} SK_PNMI_VCT_TIMER;
+-
+-
+-/*
+- * PNMI specific adapter context structure
+- */
+-typedef struct s_PnmiPort {
+-	SK_U64			StatSyncCts;
+-	SK_U64			StatSyncOctetsCts;
+-	SK_U64			StatRxLongFrameCts;
+-	SK_U64			StatRxFrameTooLongCts;
+-	SK_U64			StatRxPMaccErr;
+-	SK_U64			TxSwQueueLen;
+-	SK_U64			TxSwQueueMax;
+-	SK_U64			TxRetryCts;
+-	SK_U64			RxIntrCts;
+-	SK_U64			TxIntrCts;
+-	SK_U64			RxNoBufCts;
+-	SK_U64			TxNoBufCts;
+-	SK_U64			TxUsedDescrNo;
+-	SK_U64			RxDeliveredCts;
+-	SK_U64			RxOctetsDeliveredCts;
+-	SK_U64			RxHwErrorsCts;
+-	SK_U64			TxHwErrorsCts;
+-	SK_U64			InErrorsCts;
+-	SK_U64			OutErrorsCts;
+-	SK_U64			ErrRecoveryCts;
+-	SK_U64			RxShortZeroMark;
+-	SK_U64			CounterOffset[SK_PNMI_CNT_NO];
+-	SK_U32			CounterHigh[SK_PNMI_CNT_NO];
+-	SK_BOOL			ActiveFlag;
+-	SK_U8			Align[3];
+-} SK_PNMI_PORT;
+-
+-
+-typedef struct s_PnmiData {
+-	SK_PNMI_PORT	Port	[SK_MAX_MACS];
+-	SK_PNMI_PORT	BufPort	[SK_MAX_MACS]; /* 2002-09-13 pweber  */
+-	SK_U64			VirtualCounterOffset[SK_PNMI_CNT_NO];
+-	SK_U32			TestResult;
+-	char			HwVersion[10];
+-	SK_U16			Align01;
+-
+-	char			*pDriverDescription;
+-	char			*pDriverVersion;
+-	char			*pDriverReleaseDate;
+-	char			*pDriverFileName;
+-
+-	int				MacUpdatedFlag;
+-	int				RlmtUpdatedFlag;
+-	int				SirqUpdatedFlag;
+-
+-	SK_U64			RlmtChangeCts;
+-	SK_U64			RlmtChangeTime;
+-	SK_PNMI_ESTIMATE	RlmtChangeEstimate;
+-	SK_U64			RlmtChangeThreshold;
+-
+-	SK_U64			StartUpTime;
+-	SK_U32			DeviceType;
+-	char			PciBusSpeed;
+-	char			PciBusWidth;
+-	char			Chipset;
+-	char			PMD;
+-	char			Connector;
+-	SK_BOOL			DualNetActiveFlag;
+-	SK_U16			Align02;
+-
+-	char			TrapBuf[SK_PNMI_TRAP_QUEUE_LEN];
+-	unsigned int	TrapBufFree;
+-	unsigned int	TrapQueueBeg;
+-	unsigned int	TrapQueueEnd;
+-	unsigned int	TrapBufPad;
+-	unsigned int	TrapUnique;
+-	SK_U8		VctStatus[SK_MAX_MACS];
+-	SK_PNMI_VCT	VctBackup[SK_MAX_MACS];
+-	SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS];
+-#ifdef SK_DIAG_SUPPORT
+-	SK_U32			DiagAttached;
+-#endif /* SK_DIAG_SUPPORT */
+-} SK_PNMI;
+-
+-
+-/*
+- * Function prototypes
+- */
+-extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level);
+-extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
+-	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
+-extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
+-	unsigned int *pLen, SK_U32 NetIndex);
+-extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
+-	unsigned int *pLen, SK_U32 NetIndex);
+-extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
+-	unsigned int *pLen, SK_U32 NetIndex);
+-extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event,
+-	SK_EVPARA Param);
+-extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
+-	unsigned int * pLen, SK_U32 NetIndex);
+-
+-#endif
+diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h
+deleted file mode 100644
+index 3eec627..0000000
+--- a/drivers/net/sk98lin/h/skgesirq.h
++++ /dev/null
+@@ -1,110 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skgesirq.h
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.30 $
+- * Date:	$Date: 2003/07/04 12:34:13 $
+- * Purpose:	SK specific Gigabit Ethernet special IRQ functions
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef _INC_SKGESIRQ_H_
+-#define _INC_SKGESIRQ_H_
+-
+-/* Define return codes of SkGePortCheckUp and CheckShort */
+-#define	SK_HW_PS_NONE		0	/* No action needed */
+-#define	SK_HW_PS_RESTART	1	/* Restart needed */
+-#define	SK_HW_PS_LINK		2	/* Link Up actions needed */
+-
+-/*
+- * Define the Event the special IRQ/INI module can handle
+- */
+-#define SK_HWEV_WATIM			1	/* Timeout for WA Errata #2 XMAC */
+-#define SK_HWEV_PORT_START		2	/* Port Start Event by RLMT */
+-#define SK_HWEV_PORT_STOP		3	/* Port Stop Event by RLMT */
+-#define SK_HWEV_CLEAR_STAT		4	/* Clear Statistics by PNMI */
+-#define SK_HWEV_UPDATE_STAT		5	/* Update Statistics by PNMI */
+-#define SK_HWEV_SET_LMODE		6	/* Set Link Mode by PNMI */
+-#define SK_HWEV_SET_FLOWMODE	7	/* Set Flow Control Mode by PNMI */
+-#define SK_HWEV_SET_ROLE		8	/* Set Master/Slave (Role) by PNMI */
+-#define SK_HWEV_SET_SPEED		9	/* Set Link Speed by PNMI */
+-#define SK_HWEV_HALFDUP_CHK		10	/* Half Duplex Hangup Workaround */
+-
+-#define SK_WA_ACT_TIME		(5000000UL)	/* 5 sec */
+-#define SK_WA_INA_TIME		(100000UL)	/* 100 msec */
+-
+-#define SK_HALFDUP_CHK_TIME	(10000UL)	/* 10 msec */
+-
+-/*
+- * Define the error numbers and messages
+- */
+-#define SKERR_SIRQ_E001		(SK_ERRBASE_SIRQ+0)
+-#define SKERR_SIRQ_E001MSG	"Unknown event"
+-#define SKERR_SIRQ_E002		(SKERR_SIRQ_E001+1)
+-#define SKERR_SIRQ_E002MSG	"Packet timeout RX1"
+-#define SKERR_SIRQ_E003		(SKERR_SIRQ_E002+1)
+-#define SKERR_SIRQ_E003MSG	"Packet timeout RX2"
+-#define SKERR_SIRQ_E004		(SKERR_SIRQ_E003+1)
+-#define SKERR_SIRQ_E004MSG	"MAC 1 not correctly initialized"
+-#define SKERR_SIRQ_E005		(SKERR_SIRQ_E004+1)
+-#define SKERR_SIRQ_E005MSG	"MAC 2 not correctly initialized"
+-#define SKERR_SIRQ_E006		(SKERR_SIRQ_E005+1)
+-#define SKERR_SIRQ_E006MSG	"CHECK failure R1"
+-#define SKERR_SIRQ_E007		(SKERR_SIRQ_E006+1)
+-#define SKERR_SIRQ_E007MSG	"CHECK failure R2"
+-#define SKERR_SIRQ_E008		(SKERR_SIRQ_E007+1)
+-#define SKERR_SIRQ_E008MSG	"CHECK failure XS1"
+-#define SKERR_SIRQ_E009		(SKERR_SIRQ_E008+1)
+-#define SKERR_SIRQ_E009MSG	"CHECK failure XA1"
+-#define SKERR_SIRQ_E010		(SKERR_SIRQ_E009+1)
+-#define SKERR_SIRQ_E010MSG	"CHECK failure XS2"
+-#define SKERR_SIRQ_E011		(SKERR_SIRQ_E010+1)
+-#define SKERR_SIRQ_E011MSG	"CHECK failure XA2"
+-#define SKERR_SIRQ_E012		(SKERR_SIRQ_E011+1)
+-#define SKERR_SIRQ_E012MSG	"unexpected IRQ Master error"
+-#define SKERR_SIRQ_E013		(SKERR_SIRQ_E012+1)
+-#define SKERR_SIRQ_E013MSG	"unexpected IRQ Status error"
+-#define SKERR_SIRQ_E014		(SKERR_SIRQ_E013+1)
+-#define SKERR_SIRQ_E014MSG	"Parity error on RAM (read)"
+-#define SKERR_SIRQ_E015		(SKERR_SIRQ_E014+1)
+-#define SKERR_SIRQ_E015MSG	"Parity error on RAM (write)"
+-#define SKERR_SIRQ_E016		(SKERR_SIRQ_E015+1)
+-#define SKERR_SIRQ_E016MSG	"Parity error MAC 1"
+-#define SKERR_SIRQ_E017		(SKERR_SIRQ_E016+1)
+-#define SKERR_SIRQ_E017MSG	"Parity error MAC 2"
+-#define SKERR_SIRQ_E018		(SKERR_SIRQ_E017+1)
+-#define SKERR_SIRQ_E018MSG	"Parity error RX 1"
+-#define SKERR_SIRQ_E019		(SKERR_SIRQ_E018+1)
+-#define SKERR_SIRQ_E019MSG	"Parity error RX 2"
+-#define SKERR_SIRQ_E020		(SKERR_SIRQ_E019+1)
+-#define SKERR_SIRQ_E020MSG	"MAC transmit FIFO underrun"
+-#define SKERR_SIRQ_E021		(SKERR_SIRQ_E020+1)
+-#define SKERR_SIRQ_E021MSG	"Spurious TWSI interrupt"
+-#define SKERR_SIRQ_E022		(SKERR_SIRQ_E021+1)
+-#define SKERR_SIRQ_E022MSG	"Cable pair swap error"
+-#define SKERR_SIRQ_E023		(SKERR_SIRQ_E022+1)
+-#define SKERR_SIRQ_E023MSG	"Auto-negotiation error"
+-#define SKERR_SIRQ_E024		(SKERR_SIRQ_E023+1)
+-#define SKERR_SIRQ_E024MSG	"FIFO overflow error"
+-#define SKERR_SIRQ_E025		(SKERR_SIRQ_E024+1)
+-#define SKERR_SIRQ_E025MSG	"2 Pair Downshift detected"
+-
+-extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
+-extern int  SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
+-extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
+-
+-#endif	/* _INC_SKGESIRQ_H_ */
+diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h
+deleted file mode 100644
+index 6a63f4a..0000000
+--- a/drivers/net/sk98lin/h/ski2c.h
++++ /dev/null
+@@ -1,174 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	ski2c.h
+- * Project:	Gigabit Ethernet Adapters, TWSI-Module
+- * Version:	$Revision: 1.35 $
+- * Date:	$Date: 2003/10/20 09:06:30 $
+- * Purpose:	Defines to access Voltage and Temperature Sensor
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKI2C.H	contains all I2C specific defines
+- */
+-
+-#ifndef _SKI2C_H_
+-#define _SKI2C_H_
+-
+-typedef struct  s_Sensor SK_SENSOR;
+-
+-#include "h/skgei2c.h"
+-
+-/*
+- * Define the I2C events.
+- */
+-#define SK_I2CEV_IRQ	1	/* IRQ happened Event */
+-#define SK_I2CEV_TIM	2	/* Timeout event */
+-#define SK_I2CEV_CLEAR	3	/* Clear MIB Values */
+-
+-/*
+- * Define READ and WRITE Constants.
+- */
+-#define I2C_READ	0
+-#define I2C_WRITE	1
+-#define I2C_BURST	1
+-#define I2C_SINGLE	0
+-
+-#define SKERR_I2C_E001		(SK_ERRBASE_I2C+0)
+-#define SKERR_I2C_E001MSG	"Sensor index unknown"
+-#define SKERR_I2C_E002		(SKERR_I2C_E001+1)
+-#define SKERR_I2C_E002MSG	"TWSI: transfer does not complete"
+-#define SKERR_I2C_E003		(SKERR_I2C_E002+1)
+-#define SKERR_I2C_E003MSG	"LM80: NAK on device send"
+-#define SKERR_I2C_E004		(SKERR_I2C_E003+1)
+-#define SKERR_I2C_E004MSG	"LM80: NAK on register send"
+-#define SKERR_I2C_E005		(SKERR_I2C_E004+1)
+-#define SKERR_I2C_E005MSG	"LM80: NAK on device (2) send"
+-#define SKERR_I2C_E006		(SKERR_I2C_E005+1)
+-#define SKERR_I2C_E006MSG	"Unknown event"
+-#define SKERR_I2C_E007		(SKERR_I2C_E006+1)
+-#define SKERR_I2C_E007MSG	"LM80 read out of state"
+-#define SKERR_I2C_E008		(SKERR_I2C_E007+1)
+-#define SKERR_I2C_E008MSG	"Unexpected sensor read completed"
+-#define SKERR_I2C_E009		(SKERR_I2C_E008+1)
+-#define SKERR_I2C_E009MSG	"WARNING: temperature sensor out of range"
+-#define SKERR_I2C_E010		(SKERR_I2C_E009+1)
+-#define SKERR_I2C_E010MSG	"WARNING: voltage sensor out of range"
+-#define SKERR_I2C_E011		(SKERR_I2C_E010+1)
+-#define SKERR_I2C_E011MSG	"ERROR: temperature sensor out of range"
+-#define SKERR_I2C_E012		(SKERR_I2C_E011+1)
+-#define SKERR_I2C_E012MSG	"ERROR: voltage sensor out of range"
+-#define SKERR_I2C_E013		(SKERR_I2C_E012+1)
+-#define SKERR_I2C_E013MSG	"ERROR: couldn't init sensor"
+-#define SKERR_I2C_E014		(SKERR_I2C_E013+1)
+-#define SKERR_I2C_E014MSG	"WARNING: fan sensor out of range"
+-#define SKERR_I2C_E015		(SKERR_I2C_E014+1)
+-#define SKERR_I2C_E015MSG	"ERROR: fan sensor out of range"
+-#define SKERR_I2C_E016		(SKERR_I2C_E015+1)
+-#define SKERR_I2C_E016MSG	"TWSI: active transfer does not complete"
+-
+-/*
+- * Define Timeout values
+- */
+-#define SK_I2C_TIM_LONG		2000000L	/* 2 seconds */
+-#define SK_I2C_TIM_SHORT	 100000L	/* 100 milliseconds */
+-#define SK_I2C_TIM_WATCH	1000000L	/* 1 second */
+-
+-/*
+- * Define trap and error log hold times
+- */
+-#ifndef	SK_SEN_ERR_TR_HOLD
+-#define SK_SEN_ERR_TR_HOLD		(4*SK_TICKS_PER_SEC)
+-#endif
+-#ifndef	SK_SEN_ERR_LOG_HOLD
+-#define SK_SEN_ERR_LOG_HOLD		(60*SK_TICKS_PER_SEC)
+-#endif
+-#ifndef	SK_SEN_WARN_TR_HOLD
+-#define SK_SEN_WARN_TR_HOLD		(15*SK_TICKS_PER_SEC)
+-#endif
+-#ifndef	SK_SEN_WARN_LOG_HOLD
+-#define SK_SEN_WARN_LOG_HOLD	(15*60*SK_TICKS_PER_SEC)
+-#endif
+-
+-/*
+- * Defines for SenType
+- */
+-#define SK_SEN_UNKNOWN	0
+-#define SK_SEN_TEMP		1
+-#define SK_SEN_VOLT		2
+-#define SK_SEN_FAN		3
+-
+-/*
+- * Define for the SenErrorFlag
+- */
+-#define SK_SEN_ERR_NOT_PRESENT	0	/* Error Flag: Sensor not present */
+-#define SK_SEN_ERR_OK			1	/* Error Flag: O.K. */
+-#define SK_SEN_ERR_WARN			2	/* Error Flag: Warning */
+-#define SK_SEN_ERR_ERR			3	/* Error Flag: Error */
+-#define SK_SEN_ERR_FAULTY		4	/* Error Flag: Faulty */
+-
+-/*
+- * Define the Sensor struct
+- */
+-struct	s_Sensor {
+-	char	*SenDesc;			/* Description */
+-	int		SenType;			/* Voltage or Temperature */
+-	SK_I32	SenValue;			/* Current value of the sensor */
+-	SK_I32	SenThreErrHigh;		/* High error Threshhold of this sensor */
+-	SK_I32	SenThreWarnHigh;	/* High warning Threshhold of this sensor */
+-	SK_I32	SenThreErrLow;		/* Lower error Threshold of the sensor */
+-	SK_I32	SenThreWarnLow;		/* Lower warning Threshold of the sensor */
+-	int		SenErrFlag;			/* Sensor indicated an error */
+-	SK_BOOL	SenInit;			/* Is sensor initialized ? */
+-	SK_U64	SenErrCts;			/* Error trap counter */
+-	SK_U64	SenWarnCts;			/* Warning trap counter */
+-	SK_U64	SenBegErrTS;		/* Begin error timestamp */
+-	SK_U64	SenBegWarnTS;		/* Begin warning timestamp */
+-	SK_U64	SenLastErrTrapTS;	/* Last error trap timestamp */
+-	SK_U64	SenLastErrLogTS;	/* Last error log timestamp */
+-	SK_U64	SenLastWarnTrapTS;	/* Last warning trap timestamp */
+-	SK_U64	SenLastWarnLogTS;	/* Last warning log timestamp */
+-	int		SenState;			/* Sensor State (see HW specific include) */
+-	int		(*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
+-								/* Sensors read function */
+-	SK_U16	SenReg;				/* Register Address for this sensor */
+-	SK_U8	SenDev;				/* Device Selection for this sensor */
+-};
+-
+-typedef	struct	s_I2c {
+-	SK_SENSOR	SenTable[SK_MAX_SENSORS];	/* Sensor Table */
+-	int			CurrSens;	/* Which sensor is currently queried */
+-	int			MaxSens;	/* Max. number of sensors */
+-	int			TimerMode;	/* Use the timer also to watch the state machine */
+-	int			InitLevel;	/* Initialized Level */
+-#ifndef SK_DIAG
+-	int			DummyReads;	/* Number of non-checked dummy reads */
+-	SK_TIMER	SenTimer;	/* Sensors timer */
+-#endif /* !SK_DIAG */
+-} SK_I2C;
+-
+-extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
+-#ifdef SK_DIAG
+-extern	SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
+-						 int Burst);
+-#else /* !SK_DIAG */
+-extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
+-extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
+-extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
+-#endif /* !SK_DIAG */
+-#endif /* n_SKI2C_H */
+-
+diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h
+deleted file mode 100644
+index 2ec40d4..0000000
+--- a/drivers/net/sk98lin/h/skqueue.h
++++ /dev/null
+@@ -1,94 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skqueue.h
+- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version:	$Revision: 1.16 $
+- * Date:	$Date: 2003/09/16 12:50:32 $
+- * Purpose:	Defines for the Event queue
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKQUEUE.H	contains all defines and types for the event queue
+- */
+-
+-#ifndef _SKQUEUE_H_
+-#define _SKQUEUE_H_
+-
+-
+-/*
+- * define the event classes to be served
+- */
+-#define	SKGE_DRV	1	/* Driver Event Class */
+-#define	SKGE_RLMT	2	/* RLMT Event Class */
+-#define	SKGE_I2C	3	/* I2C Event Class */
+-#define	SKGE_PNMI	4	/* PNMI Event Class */
+-#define	SKGE_CSUM	5	/* Checksum Event Class */
+-#define	SKGE_HWAC	6	/* Hardware Access Event Class */
+-
+-#define	SKGE_SWT	9	/* Software Timer Event Class */
+-#define	SKGE_LACP	10	/* LACP Aggregation Event Class */
+-#define	SKGE_RSF	11	/* RSF Aggregation Event Class */
+-#define	SKGE_MARKER	12	/* MARKER Aggregation Event Class */
+-#define	SKGE_FD		13	/* FD Distributor Event Class */
+-
+-/*
+- * define event queue as circular buffer
+- */
+-#define SK_MAX_EVENT	64
+-
+-/*
+- * Parameter union for the Para stuff
+- */
+-typedef	union u_EvPara {
+-	void	*pParaPtr;	/* Parameter Pointer */
+-	SK_U64	Para64;		/* Parameter 64bit version */
+-	SK_U32	Para32[2];	/* Parameter Array of 32bit parameters */
+-} SK_EVPARA;
+-
+-/*
+- * Event Queue
+- *	skqueue.c
+- * events are class/value pairs
+- *	class	is addressee, e.g. RLMT, PNMI etc.
+- *	value	is command, e.g. line state change, ring op change etc.
+- */
+-typedef	struct s_EventElem {
+-	SK_U32		Class;			/* Event class */
+-	SK_U32		Event;			/* Event value */
+-	SK_EVPARA	Para;			/* Event parameter */
+-} SK_EVENTELEM;
+-
+-typedef	struct s_Queue {
+-	SK_EVENTELEM	EvQueue[SK_MAX_EVENT];
+-	SK_EVENTELEM	*EvPut;
+-	SK_EVENTELEM	*EvGet;
+-} SK_QUEUE;
+-
+-extern	void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level);
+-extern	void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event,
+-	SK_EVPARA Para);
+-extern	int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc);
+-
+-
+-/* Define Error Numbers and messages */
+-#define	SKERR_Q_E001	(SK_ERRBASE_QUEUE+0)
+-#define	SKERR_Q_E001MSG	"Event queue overflow"
+-#define	SKERR_Q_E002	(SKERR_Q_E001+1)
+-#define	SKERR_Q_E002MSG	"Undefined event class"
+-#endif	/* _SKQUEUE_H_ */
+-
+diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h
+deleted file mode 100644
+index ca75dfd..0000000
+--- a/drivers/net/sk98lin/h/skrlmt.h
++++ /dev/null
+@@ -1,438 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skrlmt.h
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.37 $
+- * Date:	$Date: 2003/04/15 09:43:43 $
+- * Purpose:	Header file for Redundant Link ManagemenT.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This is the header file for Redundant Link ManagemenT.
+- *
+- * Include File Hierarchy:
+- *
+- *	"skdrv1st.h"
+- *	...
+- *	"sktypes.h"
+- *	"skqueue.h"
+- *	"skaddr.h"
+- *	"skrlmt.h"
+- *	...
+- *	"skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKRLMT_H
+-#define __INC_SKRLMT_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif	/* cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-#define	SK_RLMT_NET_DOWN_TEMP	1	/* NET_DOWN due to last port down. */
+-#define	SK_RLMT_NET_DOWN_FINAL	2	/* NET_DOWN due to RLMT_STOP. */
+-
+-/* ----- Default queue sizes - must be multiples of 8 KB ----- */
+-
+-/* Less than 8 KB free in RX queue => pause frames. */
+-#define SK_RLMT_STANDBY_QRXSIZE	128	/* Size of rx standby queue in KB. */
+-#define SK_RLMT_STANDBY_QXASIZE	32	/* Size of async standby queue in KB. */
+-#define SK_RLMT_STANDBY_QXSSIZE	0	/* Size of sync standby queue in KB. */
+-
+-#define SK_RLMT_MAX_TX_BUF_SIZE	60	/* Maximum RLMT transmit size. */
+-
+-/* ----- PORT states ----- */
+-
+-#define SK_RLMT_PS_INIT			0	/* Port state: Init. */
+-#define SK_RLMT_PS_LINK_DOWN	1	/* Port state: Link down. */
+-#define SK_RLMT_PS_DOWN			2	/* Port state: Port down. */
+-#define SK_RLMT_PS_GOING_UP		3	/* Port state: Going up. */
+-#define SK_RLMT_PS_UP			4	/* Port state: Up. */
+-
+-/* ----- RLMT states ----- */
+-
+-#define SK_RLMT_RS_INIT			0	/* RLMT state: Init. */
+-#define SK_RLMT_RS_NET_DOWN		1	/* RLMT state: Net down. */
+-#define SK_RLMT_RS_NET_UP		2	/* RLMT state: Net up. */
+-
+-/* ----- PORT events ----- */
+-
+-#define SK_RLMT_LINK_UP			1001	/* Link came up. */
+-#define SK_RLMT_LINK_DOWN		1002	/* Link went down. */
+-#define SK_RLMT_PORT_ADDR		1003	/* Port address changed. */
+-
+-/* ----- RLMT events ----- */
+-
+-#define SK_RLMT_START			2001	/* Start RLMT. */
+-#define SK_RLMT_STOP			2002	/* Stop RLMT. */
+-#define SK_RLMT_PACKET_RECEIVED	2003	/* Packet was received for RLMT. */
+-#define SK_RLMT_STATS_CLEAR		2004	/* Clear statistics. */
+-#define SK_RLMT_STATS_UPDATE	2005	/* Update statistics. */
+-#define SK_RLMT_PREFPORT_CHANGE	2006	/* Change preferred port. */
+-#define SK_RLMT_MODE_CHANGE		2007	/* New RlmtMode. */
+-#define SK_RLMT_SET_NETS		2008	/* Number of Nets (1 or 2). */
+-
+-/* ----- RLMT mode bits ----- */
+-
+-/*
+- * CAUTION:	These defines are private to RLMT.
+- *			Please use the RLMT mode defines below.
+- */
+-
+-#define SK_RLMT_CHECK_LINK		  1		/* Check Link. */
+-#define SK_RLMT_CHECK_LOC_LINK	  2		/* Check other link on same adapter. */
+-#define SK_RLMT_CHECK_SEG		  4		/* Check segmentation. */
+-
+-#ifndef RLMT_CHECK_REMOTE
+-#define SK_RLMT_CHECK_OTHERS	SK_RLMT_CHECK_LOC_LINK
+-#else	/* RLMT_CHECK_REMOTE */
+-#define SK_RLMT_CHECK_REM_LINK	  8		/* Check link(s) on other adapter(s). */
+-#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED	3
+-#define SK_RLMT_CHECK_OTHERS	\
+-		(SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
+-#endif	/* RLMT_CHECK_REMOTE */
+-
+-#ifndef SK_RLMT_ENABLE_TRANSPARENT
+-#define SK_RLMT_TRANSPARENT		  0		/* RLMT transparent - inactive. */
+-#else	/* SK_RLMT_ENABLE_TRANSPARENT */
+-#define SK_RLMT_TRANSPARENT		128		/* RLMT transparent. */
+-#endif	/* SK_RLMT_ENABLE_TRANSPARENT */
+-
+-/* ----- RLMT modes ----- */
+-
+-/* Check Link State. */
+-#define SK_RLMT_MODE_CLS	(SK_RLMT_CHECK_LINK)
+-
+-/* Check Local Ports: check other links on the same adapter. */
+-#define SK_RLMT_MODE_CLP	(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK)
+-
+-/* Check Local Ports and Segmentation Status. */
+-#define SK_RLMT_MODE_CLPSS	\
+-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG)
+-
+-#ifdef RLMT_CHECK_REMOTE
+-/* Check Local and Remote Ports: check links (local or remote). */
+-	Name of define TBD!
+-#define SK_RLMT_MODE_CRP	\
+-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
+-
+-/* Check Local and Remote Ports and Segmentation Status. */
+-	Name of define TBD!
+-#define SK_RLMT_MODE_CRPSS	\
+-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \
+-		SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG)
+-#endif	/* RLMT_CHECK_REMOTE */
+-
+-/* ----- RLMT lookahead result bits ----- */
+-
+-#define SK_RLMT_RX_RLMT			1	/* Give packet to RLMT. */
+-#define SK_RLMT_RX_PROTOCOL		2	/* Give packet to protocol. */
+-
+-/* Macros */
+-
+-#if 0
+-SK_AC		*pAC		/* adapter context */
+-SK_U32		PortNum		/* receiving port */
+-unsigned	PktLen		/* received packet's length */
+-SK_BOOL		IsBc		/* Flag: packet is broadcast */
+-unsigned	*pOffset	/* offs. of bytes to present to SK_RLMT_LOOKAHEAD */
+-unsigned	*pNumBytes	/* #Bytes to present to SK_RLMT_LOOKAHEAD */
+-#endif	/* 0 */
+-
+-#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \
+-	SK_AC	*_pAC; \
+-	SK_U32	_PortNum; \
+-	_pAC = (pAC); \
+-	_PortNum = (SK_U32)(PortNum); \
+-	/* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \
+-	_pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \
+-    if (_pAC->Rlmt.RlmtOff) { \
+-		*(pNumBytes) = 0; \
+-    } \
+-    else {\
+-        if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \
+-    		*(pNumBytes) = 0; \
+-    	} \
+-    	else if (IsBc) { \
+-    		if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \
+-    			*(pNumBytes) = 6; \
+-    			*(pOffset) = 6; \
+-    		} \
+-    		else { \
+-    			*(pNumBytes) = 0; \
+-    		} \
+-    	} \
+-    	else { \
+-    		if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \
+-    			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+-    			*(pNumBytes) = 0; \
+-    		} \
+-    		else { \
+-    			*(pNumBytes) = 6; \
+-    			*(pOffset) = 0; \
+-    		} \
+-    	} \
+-    } \
+-}
+-
+-#if 0
+-SK_AC		*pAC		/* adapter context */
+-SK_U32		PortNum		/* receiving port */
+-SK_U8		*pLaPacket,	/* received packet's data (points to pOffset) */
+-SK_BOOL		IsBc		/* Flag: packet is broadcast */
+-SK_BOOL		IsMc		/* Flag: packet is multicast */
+-unsigned	*pForRlmt	/* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */
+-SK_RLMT_LOOKAHEAD() expects *pNumBytes from
+-packet offset *pOffset (s.a.) at *pLaPacket.
+-
+-If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is
+-BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler
+-can trash unneeded parts of the if construction.
+-#endif	/* 0 */
+-
+-#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \
+-	SK_AC	*_pAC; \
+-	SK_U32	_PortNum; \
+-	SK_U8	*_pLaPacket; \
+-	_pAC = (pAC); \
+-	_PortNum = (SK_U32)(PortNum); \
+-	_pLaPacket = (SK_U8 *)(pLaPacket); \
+-	if (IsBc) {\
+-		if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \
+-			_PortNum].Net->NetNumber].CurrentMacAddress.a)) { \
+-			_pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \
+-			_pAC->Rlmt.CheckSwitch = SK_TRUE; \
+-		} \
+-		/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+-		*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+-	} \
+-	else if (IsMc) { \
+-		if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \
+-			_pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \
+-			if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \
+-				*(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \
+-			} \
+-			else { \
+-				*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+-			} \
+-		} \
+-		else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \
+-			*(pForRlmt) = SK_RLMT_RX_RLMT; \
+-		} \
+-		else { \
+-			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+-			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+-		} \
+-	} \
+-	else { \
+-		if (SK_ADDR_EQUAL( \
+-			_pLaPacket, \
+-			_pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \
+-			*(pForRlmt) = SK_RLMT_RX_RLMT; \
+-		} \
+-		else { \
+-			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+-			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+-		} \
+-	} \
+-}
+-
+-#ifdef SK_RLMT_FAST_LOOKAHEAD
+-Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead.
+-#endif	/* SK_RLMT_FAST_LOOKAHEAD */
+-#ifdef SK_RLMT_SLOW_LOOKAHEAD
+-Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead.
+-#endif	/* SK_RLMT_SLOW_LOOKAHEAD */
+-
+-/* typedefs *******************************************************************/
+-
+-#ifdef SK_RLMT_MBUF_PRIVATE
+-typedef struct s_RlmtMbuf {
+-	some content
+-} SK_RLMT_MBUF;
+-#endif	/* SK_RLMT_MBUF_PRIVATE */
+-
+-
+-#ifdef SK_LA_INFO
+-typedef struct s_Rlmt_PacketInfo {
+-	unsigned	PacketLength;			/* Length of packet. */
+-	unsigned	PacketType;				/* Directed/Multicast/Broadcast. */
+-} SK_RLMT_PINFO;
+-#endif	/* SK_LA_INFO */
+-
+-
+-typedef struct s_RootId {
+-	SK_U8		Id[8];					/* Root Bridge Id. */
+-} SK_RLMT_ROOT_ID;
+-
+-
+-typedef struct s_port {
+-	SK_MAC_ADDR	CheckAddr;
+-	SK_BOOL		SuspectTx;
+-} SK_PORT_CHECK;
+-
+-
+-typedef struct s_RlmtNet SK_RLMT_NET;
+-
+-
+-typedef struct s_RlmtPort {
+-
+-/* ----- Public part (read-only) ----- */
+-
+-	SK_U8			PortState;				/* Current state of this port. */
+-
+-	/* For PNMI */
+-	SK_BOOL			LinkDown;
+-	SK_BOOL			PortDown;
+-	SK_U8			Align01;
+-
+-	SK_U32			PortNumber;				/* Number of port on adapter. */
+-	SK_RLMT_NET *	Net;					/* Net port belongs to. */
+-
+-	SK_U64			TxHelloCts;
+-	SK_U64			RxHelloCts;
+-	SK_U64			TxSpHelloReqCts;
+-	SK_U64			RxSpHelloCts;
+-
+-/* ----- Private part ----- */
+-
+-/*	SK_U64			PacketsRx; */				/* Total packets received. */
+-	SK_U32			PacketsPerTimeSlot;		/* Packets rxed between TOs. */
+-/*	SK_U32			DataPacketsPerTimeSlot; */	/* Data packets ... */
+-	SK_U32			BpduPacketsPerTimeSlot;	/* BPDU packets rxed in TS. */
+-	SK_U64			BcTimeStamp;			/* Time of last BC receive. */
+-	SK_U64			GuTimeStamp;			/* Time of entering GOING_UP. */
+-
+-	SK_TIMER		UpTimer;				/* Timer struct Link/Port up. */
+-	SK_TIMER		DownRxTimer;			/* Timer struct down rx. */
+-	SK_TIMER		DownTxTimer;			/* Timer struct down tx. */
+-
+-	SK_U32			CheckingState;			/* Checking State. */
+-
+-	SK_ADDR_PORT *	AddrPort;
+-
+-	SK_U8			Random[4];				/* Random value. */
+-	unsigned		PortsChecked;			/* #ports checked. */
+-	unsigned		PortsSuspect;			/* #ports checked that are s. */
+-	SK_PORT_CHECK	PortCheck[1];
+-/*	SK_PORT_CHECK	PortCheck[SK_MAX_MACS - 1]; */
+-
+-	SK_BOOL			PortStarted;			/* Port is started. */
+-	SK_BOOL			PortNoRx;				/* NoRx for >= 1 time slot. */
+-	SK_BOOL			RootIdSet;
+-	SK_RLMT_ROOT_ID	Root;					/* Root Bridge Id. */
+-} SK_RLMT_PORT;
+-
+-
+-struct s_RlmtNet {
+-
+-/* ----- Public part (read-only) ----- */
+-
+-	SK_U32			NetNumber;			/* Number of net. */
+-
+-	SK_RLMT_PORT *	Port[SK_MAX_MACS];	/* Ports that belong to this net. */
+-	SK_U32			NumPorts;			/* Number of ports. */
+-	SK_U32			PrefPort;			/* Preferred port. */
+-
+-	/* For PNMI */
+-
+-	SK_U32			ChgBcPrio;			/* Change Priority of last broadcast received */
+-	SK_U32			RlmtMode;			/* Check ... */
+-	SK_U32			ActivePort;			/* Active port. */
+-	SK_U32			Preference;		/* 0xFFFFFFFF: Automatic. */
+-
+-	SK_U8			RlmtState;			/* Current RLMT state. */
+-
+-/* ----- Private part ----- */
+-	SK_BOOL			RootIdSet;
+-	SK_U16			Align01;
+-
+-	int				LinksUp;			/* #Links up. */
+-	int				PortsUp;			/* #Ports up. */
+-	SK_U32			TimeoutValue;		/* RLMT timeout value. */
+-
+-	SK_U32			CheckingState;		/* Checking State. */
+-	SK_RLMT_ROOT_ID	Root;				/* Root Bridge Id. */
+-
+-	SK_TIMER		LocTimer;			/* Timer struct. */
+-	SK_TIMER		SegTimer;			/* Timer struct. */
+-};
+-
+-
+-typedef struct s_Rlmt {
+-
+-/* ----- Public part (read-only) ----- */
+-
+-	SK_U32			NumNets;			/* Number of nets. */
+-	SK_U32			NetsStarted;		/* Number of nets started. */
+-	SK_RLMT_NET		Net[SK_MAX_NETS];	/* Array of available nets. */
+-	SK_RLMT_PORT	Port[SK_MAX_MACS];	/* Array of available ports. */
+-
+-/* ----- Private part ----- */
+-	SK_BOOL			CheckSwitch;
+-	SK_BOOL			RlmtOff;            /* set to zero if the Mac addresses 
+-                                           are equal or the second one 
+-                                           is zero */
+-	SK_U16			Align01;
+-
+-} SK_RLMT;
+-
+-
+-extern	SK_MAC_ADDR	BridgeMcAddr;
+-extern	SK_MAC_ADDR	SkRlmtMcAddr;
+-
+-/* function prototypes ********************************************************/
+-
+-
+-#ifndef SK_KR_PROTO
+-
+-/* Functions provided by SkRlmt */
+-
+-/* ANSI/C++ compliant function prototypes */
+-
+-extern	void	SkRlmtInit(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	int		Level);
+-
+-extern	int	SkRlmtEvent(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	SK_U32		Event,
+-	SK_EVPARA	Para);
+-
+-#else	/* defined(SK_KR_PROTO) */
+-
+-/* Non-ANSI/C++ compliant function prototypes */
+-
+-#error KR-style function prototypes are not yet provided.
+-
+-#endif	/* defined(SK_KR_PROTO)) */
+-
+-
+-#ifdef __cplusplus
+-}
+-#endif	/* __cplusplus */
+-
+-#endif	/* __INC_SKRLMT_H */
+diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h
+deleted file mode 100644
+index 04e6d7c..0000000
+--- a/drivers/net/sk98lin/h/sktimer.h
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	sktimer.h
+- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version:	$Revision: 1.11 $
+- * Date:	$Date: 2003/09/16 12:58:18 $
+- * Purpose:	Defines for the timer functions
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKTIMER.H	contains all defines and types for the timer functions
+- */
+-
+-#ifndef	_SKTIMER_H_
+-#define _SKTIMER_H_
+-
+-#include "h/skqueue.h"
+-
+-/*
+- * SK timer
+- * - needed wherever a timer is used. Put this in your data structure
+- *   wherever you want.
+- */
+-typedef	struct s_Timer SK_TIMER;
+-
+-struct s_Timer {
+-	SK_TIMER	*TmNext;	/* linked list */
+-	SK_U32		TmClass;	/* Timer Event class */
+-	SK_U32		TmEvent;	/* Timer Event value */
+-	SK_EVPARA	TmPara;		/* Timer Event parameter */
+-	SK_U32		TmDelta;	/* delta time */
+-	int			TmActive;	/* flag: active/inactive */
+-};
+-
+-/*
+- * Timer control struct.
+- * - use in Adapters context name pAC->Tim
+- */
+-typedef	struct s_TimCtrl {
+-	SK_TIMER	*StQueue;	/* Head of Timer queue */
+-} SK_TIMCTRL;
+-
+-extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level);
+-extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer);
+-extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer,
+-	SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para);
+-extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc);
+-#endif	/* _SKTIMER_H_ */
+diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h
+deleted file mode 100644
+index 40edc96..0000000
+--- a/drivers/net/sk98lin/h/sktypes.h
++++ /dev/null
+@@ -1,69 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	sktypes.h
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.2 $
+- * Date:	$Date: 2003/10/07 08:16:51 $
+- * Purpose:	Define data types for Linux
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+- 
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * In this file, all data types that are needed by the common modules
+- * are mapped to Linux data types.
+- * 
+- *
+- * Include File Hierarchy:
+- *
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKTYPES_H
+-#define __INC_SKTYPES_H
+-
+-
+-/* defines *******************************************************************/
+-
+-/*
+- * Data types with a specific size. 'I' = signed, 'U' = unsigned.
+- */
+-#define SK_I8	s8
+-#define SK_U8	u8
+-#define SK_I16	s16
+-#define SK_U16	u16
+-#define SK_I32	s32
+-#define SK_U32	u32
+-#define SK_I64	s64
+-#define SK_U64	u64
+-
+-#define SK_UPTR	ulong		/* casting pointer <-> integral */
+-
+-/*
+-* Boolean type.
+-*/
+-#define SK_BOOL		SK_U8
+-#define SK_FALSE	0
+-#define SK_TRUE		(!SK_FALSE)
+-
+-/* typedefs *******************************************************************/
+-
+-/* function prototypes ********************************************************/
+-
+-#endif	/* __INC_SKTYPES_H */
+diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h
+deleted file mode 100644
+index a1a7294..0000000
+--- a/drivers/net/sk98lin/h/skversion.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	version.h
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.5 $
+- * Date:	$Date: 2003/10/07 08:16:51 $
+- * Purpose:	SK specific Error log support
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifdef	lint
+-static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
+-static const char SysKonnectBuildNumber[] =
+-	"@(#)SK-BUILD: 6.23 PL: 01"; 
+-#endif	/* !defined(lint) */
+-
+-#define BOOT_STRING	"sk98lin: Network Device Driver v6.23\n" \
+-			"(C)Copyright 1999-2004 Marvell(R)."
+-
+-#define VER_STRING	"6.23"
+-#define DRIVER_FILE_NAME	"sk98lin"
+-#define DRIVER_REL_DATE		"Feb-13-2004"
+-
+-
+diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
+deleted file mode 100644
+index fdd9e48..0000000
+--- a/drivers/net/sk98lin/h/skvpd.h
++++ /dev/null
+@@ -1,248 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skvpd.h
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.15 $
+- * Date:	$Date: 2003/01/13 10:39:38 $
+- * Purpose:	Defines and Macros for VPD handling
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2003 SysKonnect GmbH.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * skvpd.h	contains Diagnostic specific defines for VPD handling
+- */
+-
+-#ifndef __INC_SKVPD_H_
+-#define __INC_SKVPD_H_
+-
+-/*
+- * Define Resource Type Identifiers and VPD keywords
+- */
+-#define	RES_ID		0x82	/* Resource Type ID String (Product Name) */
+-#define RES_VPD_R	0x90	/* start of VPD read only area */
+-#define RES_VPD_W	0x91	/* start of VPD read/write area */
+-#define RES_END		0x78	/* Resource Type End Tag */
+-
+-#ifndef VPD_NAME
+-#define VPD_NAME	"Name"	/* Product Name, VPD name of RES_ID */
+-#endif	/* VPD_NAME */
+-#define VPD_PN		"PN"	/* Adapter Part Number */
+-#define	VPD_EC		"EC"	/* Adapter Engineering Level */
+-#define VPD_MN		"MN"	/* Manufacture ID */
+-#define VPD_SN		"SN"	/* Serial Number */
+-#define VPD_CP		"CP"	/* Extended Capability */
+-#define VPD_RV		"RV"	/* Checksum and Reserved */
+-#define	VPD_YA		"YA"	/* Asset Tag Identifier */
+-#define VPD_VL		"VL"	/* First Error Log Message (SK specific) */
+-#define VPD_VF		"VF"	/* Second Error Log Message (SK specific) */
+-#define VPD_RW		"RW"	/* Remaining Read / Write Area */
+-
+-/* 'type' values for vpd_setup_para() */
+-#define VPD_RO_KEY	1	/* RO keys are "PN", "EC", "MN", "SN", "RV" */
+-#define VPD_RW_KEY	2	/* RW keys are "Yx", "Vx", and "RW" */
+-
+-/* 'op' values for vpd_setup_para() */
+-#define	ADD_KEY		1	/* add the key at the pos "RV" or "RW" */
+-#define OWR_KEY		2	/* overwrite key if already exists */
+-
+-/*
+- * Define READ and WRITE Constants.
+- */
+-
+-#define VPD_DEV_ID_GENESIS 	0x4300
+-
+-#define	VPD_SIZE_YUKON		256
+-#define	VPD_SIZE_GENESIS	512
+-#define	VPD_SIZE			512
+-#define VPD_READ	0x0000
+-#define VPD_WRITE	0x8000
+-
+-#define VPD_STOP(pAC,IoC)	VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE)
+-
+-#define VPD_GET_RES_LEN(p)	((unsigned int) \
+-					(* (SK_U8 *)&(p)[1]) |\
+-					((* (SK_U8 *)&(p)[2]) << 8))
+-#define VPD_GET_VPD_LEN(p)	((unsigned int)(* (SK_U8 *)&(p)[2]))
+-#define VPD_GET_VAL(p)		((char *)&(p)[3])
+-
+-#define VPD_MAX_LEN	50
+-
+-/* VPD status */
+-	/* bit 7..1 reserved */
+-#define VPD_VALID	(1<<0)	/* VPD data buffer, vpd_free_ro, */
+-							/* and vpd_free_rw valid	 */
+-
+-/*
+- * VPD structs
+- */
+-typedef	struct s_vpd_status {
+-	unsigned short	Align01;			/* Alignment */
+-	unsigned short	vpd_status;			/* VPD status, description see above */
+-	int				vpd_free_ro;		/* unused bytes in read only area */
+-	int				vpd_free_rw;		/* bytes available in read/write area */
+-} SK_VPD_STATUS;
+-
+-typedef	struct s_vpd {
+-	SK_VPD_STATUS	v;					/* VPD status structure */
+-	char			vpd_buf[VPD_SIZE];	/* VPD buffer */
+-	int				rom_size;			/* VPD ROM Size from PCI_OUR_REG_2 */
+-	int				vpd_size;			/* saved VPD-size */
+-} SK_VPD;
+-
+-typedef	struct s_vpd_para {
+-	unsigned int	p_len;	/* parameter length */
+-	char			*p_val;	/* points to the value */
+-} SK_VPD_PARA;
+-
+-/*
+- * structure of Large Resource Type Identifiers
+- */
+-
+-/* was removed because of alignment problems */
+-
+-/*
+- * structure of VPD keywords
+- */
+-typedef	struct s_vpd_key {
+-	char			p_key[2];	/* 2 bytes ID string */
+-	unsigned char	p_len;		/* 1 byte length */
+-	char			p_val;		/* start of the value string */
+-} SK_VPD_KEY;
+-
+-
+-/*
+- * System specific VPD macros
+- */
+-#ifndef SKDIAG
+-#ifndef VPD_DO_IO
+-#define VPD_OUT8(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgByte(pAC,Addr,Val)
+-#define VPD_OUT16(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgWord(pAC,Addr,Val)
+-#define VPD_IN8(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgByte(pAC,Addr,pVal)
+-#define VPD_IN16(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgWord(pAC,Addr,pVal)
+-#define VPD_IN32(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgDWord(pAC,Addr,pVal)
+-#else	/* VPD_DO_IO */
+-#define VPD_OUT8(pAC,IoC,Addr,Val)	SK_OUT8(IoC,PCI_C(Addr),Val)
+-#define VPD_OUT16(pAC,IoC,Addr,Val)	SK_OUT16(IoC,PCI_C(Addr),Val)
+-#define VPD_IN8(pAC,IoC,Addr,pVal)	SK_IN8(IoC,PCI_C(Addr),pVal)
+-#define VPD_IN16(pAC,IoC,Addr,pVal)	SK_IN16(IoC,PCI_C(Addr),pVal)
+-#define VPD_IN32(pAC,IoC,Addr,pVal)	SK_IN32(IoC,PCI_C(Addr),pVal)
+-#endif	/* VPD_DO_IO */
+-#else	/* SKDIAG */
+-#define VPD_OUT8(pAC,Ioc,Addr,Val) {			\
+-		if ((pAC)->DgT.DgUseCfgCycle)			\
+-			SkPciWriteCfgByte(pAC,Addr,Val);	\
+-		else									\
+-			SK_OUT8(pAC,PCI_C(Addr),Val);		\
+-		}
+-#define VPD_OUT16(pAC,Ioc,Addr,Val) {			\
+-		if ((pAC)->DgT.DgUseCfgCycle)			\
+-			SkPciWriteCfgWord(pAC,Addr,Val);	\
+-		else						\
+-			SK_OUT16(pAC,PCI_C(Addr),Val);		\
+-		}
+-#define VPD_IN8(pAC,Ioc,Addr,pVal) {			\
+-		if ((pAC)->DgT.DgUseCfgCycle) 			\
+-			SkPciReadCfgByte(pAC,Addr,pVal);	\
+-		else						\
+-			SK_IN8(pAC,PCI_C(Addr),pVal); 		\
+-		}
+-#define VPD_IN16(pAC,Ioc,Addr,pVal) {			\
+-		if ((pAC)->DgT.DgUseCfgCycle) 			\
+-			SkPciReadCfgWord(pAC,Addr,pVal);	\
+-		else						\
+-			SK_IN16(pAC,PCI_C(Addr),pVal); 		\
+-		}
+-#define VPD_IN32(pAC,Ioc,Addr,pVal) {			\
+-		if ((pAC)->DgT.DgUseCfgCycle)			\
+-			SkPciReadCfgDWord(pAC,Addr,pVal);	\
+-		else						\
+-			SK_IN32(pAC,PCI_C(Addr),pVal);		\
+-		}
+-#endif	/* nSKDIAG */
+-
+-/* function prototypes ********************************************************/
+-
+-#ifndef	SK_KR_PROTO
+-#ifdef SKDIAG
+-extern SK_U32	VpdReadDWord(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	int			addr);
+-#endif	/* SKDIAG */
+-
+-extern SK_VPD_STATUS	*VpdStat(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC);
+-
+-extern int	VpdKeys(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	char		*buf,
+-	int			*len,
+-	int			*elements);
+-
+-extern int	VpdRead(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	const char	*key,
+-	char		*buf,
+-	int			*len);
+-
+-extern SK_BOOL	VpdMayWrite(
+-	char		*key);
+-
+-extern int	VpdWrite(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	const char	*key,
+-	const char	*buf);
+-
+-extern int	VpdDelete(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	char		*key);
+-
+-extern int	VpdUpdate(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC);
+-
+-#ifdef	SKDIAG
+-extern int	VpdReadBlock(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	char		*buf,
+-	int			addr,
+-	int			len);
+-
+-extern int	VpdWriteBlock(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	char		*buf,
+-	int			addr,
+-	int			len);
+-#endif	/* SKDIAG */
+-#else	/* SK_KR_PROTO */
+-extern SK_U32	VpdReadDWord();
+-extern SK_VPD_STATUS	*VpdStat();
+-extern int	VpdKeys();
+-extern int	VpdRead();
+-extern SK_BOOL	VpdMayWrite();
+-extern int	VpdWrite();
+-extern int	VpdDelete();
+-extern int	VpdUpdate();
+-#endif	/* SK_KR_PROTO */
+-
+-#endif	/* __INC_SKVPD_H_ */
+diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
+deleted file mode 100644
+index 7f8e6d0..0000000
+--- a/drivers/net/sk98lin/h/xmac_ii.h
++++ /dev/null
+@@ -1,1579 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	xmac_ii.h
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.52 $
+- * Date:	$Date: 2003/10/02 16:35:50 $
+- * Purpose:	Defines and Macros for Gigabit Ethernet Controller
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_XMAC_H
+-#define __INC_XMAC_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif	/* __cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-/*
+- * XMAC II registers
+- *
+- * The XMAC registers are 16 or 32 bits wide.
+- * The XMACs host processor interface is set to 16 bit mode,
+- * therefore ALL registers will be addressed with 16 bit accesses.
+- *
+- * The following macros are provided to access the XMAC registers
+- * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(),
+- * XM_INHASH(), and XM_OUTHASH().
+- * The macros are defined in SkGeHw.h.
+- *
+- * Note:	NA reg	= Network Address e.g DA, SA etc.
+- *
+- */
+-#define XM_MMU_CMD		0x0000	/* 16 bit r/w	MMU Command Register */
+-	/* 0x0004:		reserved */
+-#define XM_POFF			0x0008	/* 32 bit r/w	Packet Offset Register */
+-#define XM_BURST		0x000c	/* 32 bit r/w	Burst Register for half duplex*/
+-#define XM_1L_VLAN_TAG	0x0010	/* 16 bit r/w	One Level VLAN Tag ID */
+-#define XM_2L_VLAN_TAG	0x0014	/* 16 bit r/w	Two Level VLAN Tag ID */
+-	/* 0x0018 - 0x001e:	reserved */
+-#define XM_TX_CMD		0x0020	/* 16 bit r/w	Transmit Command Register */
+-#define XM_TX_RT_LIM	0x0024	/* 16 bit r/w	Transmit Retry Limit Register */
+-#define XM_TX_STIME		0x0028	/* 16 bit r/w	Transmit Slottime Register */
+-#define XM_TX_IPG		0x002c	/* 16 bit r/w	Transmit Inter Packet Gap */
+-#define XM_RX_CMD		0x0030	/* 16 bit r/w	Receive Command Register */
+-#define XM_PHY_ADDR		0x0034	/* 16 bit r/w	PHY Address Register */
+-#define XM_PHY_DATA		0x0038	/* 16 bit r/w	PHY Data Register */
+-	/* 0x003c: 		reserved */
+-#define XM_GP_PORT		0x0040	/* 32 bit r/w	General Purpose Port Register */
+-#define XM_IMSK			0x0044	/* 16 bit r/w	Interrupt Mask Register */
+-#define XM_ISRC			0x0048	/* 16 bit r/o	Interrupt Status Register */
+-#define XM_HW_CFG		0x004c	/* 16 bit r/w	Hardware Config Register */
+-	/* 0x0050 - 0x005e:	reserved */
+-#define XM_TX_LO_WM		0x0060	/* 16 bit r/w	Tx FIFO Low Water Mark */
+-#define XM_TX_HI_WM		0x0062	/* 16 bit r/w	Tx FIFO High Water Mark */
+-#define XM_TX_THR		0x0064	/* 16 bit r/w	Tx Request Threshold */
+-#define XM_HT_THR		0x0066	/* 16 bit r/w	Host Request Threshold */
+-#define XM_PAUSE_DA		0x0068	/* NA reg r/w	Pause Destination Address */
+-	/* 0x006e: 		reserved */
+-#define XM_CTL_PARA		0x0070	/* 32 bit r/w	Control Parameter Register */
+-#define XM_MAC_OPCODE	0x0074	/* 16 bit r/w	Opcode for MAC control frames */
+-#define XM_MAC_PTIME	0x0076	/* 16 bit r/w	Pause time for MAC ctrl frames*/
+-#define XM_TX_STAT		0x0078	/* 32 bit r/o	Tx Status LIFO Register */
+-
+-	/* 0x0080 - 0x00fc:	16 NA reg r/w	Exact Match Address Registers */
+-	/* 				use the XM_EXM() macro to address */
+-#define XM_EXM_START	0x0080	/* r/w	Start Address of the EXM Regs */
+-
+-	/*
+-	 * XM_EXM(Reg)
+-	 *
+-	 * returns the XMAC address offset of specified Exact Match Addr Reg
+-	 *
+-	 * para:	Reg	EXM register to addr	(0 .. 15)
+-	 *
+-	 * usage:	XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]);
+-	 */
+-#define XM_EXM(Reg)	(XM_EXM_START + ((Reg) << 3))
+-
+-#define XM_SRC_CHK		0x0100	/* NA reg r/w	Source Check Address Register */
+-#define XM_SA			0x0108	/* NA reg r/w	Station Address Register */
+-#define XM_HSM			0x0110	/* 64 bit r/w	Hash Match Address Registers */
+-#define XM_RX_LO_WM		0x0118	/* 16 bit r/w	Receive Low Water Mark */
+-#define XM_RX_HI_WM		0x011a	/* 16 bit r/w	Receive High Water Mark */
+-#define XM_RX_THR		0x011c	/* 32 bit r/w	Receive Request Threshold */
+-#define XM_DEV_ID		0x0120	/* 32 bit r/o	Device ID Register */
+-#define XM_MODE			0x0124	/* 32 bit r/w	Mode Register */
+-#define XM_LSA			0x0128	/* NA reg r/o	Last Source Register */
+-	/* 0x012e:		reserved */
+-#define XM_TS_READ		0x0130	/* 32 bit r/o	Time Stamp Read Register */
+-#define XM_TS_LOAD		0x0134	/* 32 bit r/o	Time Stamp Load Value */
+-	/* 0x0138 - 0x01fe:	reserved */
+-#define XM_STAT_CMD	0x0200	/* 16 bit r/w	Statistics Command Register */
+-#define XM_RX_CNT_EV	0x0204	/* 32 bit r/o	Rx Counter Event Register */
+-#define XM_TX_CNT_EV	0x0208	/* 32 bit r/o	Tx Counter Event Register */
+-#define XM_RX_EV_MSK	0x020c	/* 32 bit r/w	Rx Counter Event Mask */
+-#define XM_TX_EV_MSK	0x0210	/* 32 bit r/w	Tx Counter Event Mask */
+-	/* 0x0204 - 0x027e:	reserved */
+-#define XM_TXF_OK		0x0280	/* 32 bit r/o	Frames Transmitted OK Conuter */
+-#define XM_TXO_OK_HI	0x0284	/* 32 bit r/o	Octets Transmitted OK High Cnt*/
+-#define XM_TXO_OK_LO	0x0288	/* 32 bit r/o	Octets Transmitted OK Low Cnt */
+-#define XM_TXF_BC_OK	0x028c	/* 32 bit r/o	Broadcast Frames Xmitted OK */
+-#define XM_TXF_MC_OK	0x0290	/* 32 bit r/o	Multicast Frames Xmitted OK */
+-#define XM_TXF_UC_OK	0x0294	/* 32 bit r/o	Unicast Frames Xmitted OK */
+-#define XM_TXF_LONG		0x0298	/* 32 bit r/o	Tx Long Frame Counter */
+-#define XM_TXE_BURST	0x029c	/* 32 bit r/o	Tx Burst Event Counter */
+-#define XM_TXF_MPAUSE	0x02a0	/* 32 bit r/o	Tx Pause MAC Ctrl Frame Cnt */
+-#define XM_TXF_MCTRL	0x02a4	/* 32 bit r/o	Tx MAC Ctrl Frame Counter */
+-#define XM_TXF_SNG_COL	0x02a8	/* 32 bit r/o	Tx Single Collision Counter */
+-#define XM_TXF_MUL_COL	0x02ac	/* 32 bit r/o	Tx Multiple Collision Counter */
+-#define XM_TXF_ABO_COL	0x02b0	/* 32 bit r/o	Tx aborted due to Exces. Col. */
+-#define XM_TXF_LAT_COL	0x02b4	/* 32 bit r/o	Tx Late Collision Counter */
+-#define XM_TXF_DEF		0x02b8	/* 32 bit r/o	Tx Deferred Frame Counter */
+-#define XM_TXF_EX_DEF	0x02bc	/* 32 bit r/o	Tx Excessive Deferall Counter */
+-#define XM_TXE_FIFO_UR	0x02c0	/* 32 bit r/o	Tx FIFO Underrun Event Cnt */
+-#define XM_TXE_CS_ERR	0x02c4	/* 32 bit r/o	Tx Carrier Sense Error Cnt */
+-#define XM_TXP_UTIL		0x02c8	/* 32 bit r/o	Tx Utilization in % */
+-	/* 0x02cc - 0x02ce:	reserved */
+-#define XM_TXF_64B		0x02d0	/* 32 bit r/o	64 Byte Tx Frame Counter */
+-#define XM_TXF_127B		0x02d4	/* 32 bit r/o	65-127 Byte Tx Frame Counter */
+-#define XM_TXF_255B		0x02d8	/* 32 bit r/o	128-255 Byte Tx Frame Counter */
+-#define XM_TXF_511B		0x02dc	/* 32 bit r/o	256-511 Byte Tx Frame Counter */
+-#define XM_TXF_1023B	0x02e0	/* 32 bit r/o	512-1023 Byte Tx Frame Counter*/
+-#define XM_TXF_MAX_SZ	0x02e4	/* 32 bit r/o	1024-MaxSize Byte Tx Frame Cnt*/
+-	/* 0x02e8 - 0x02fe:	reserved */
+-#define XM_RXF_OK		0x0300	/* 32 bit r/o	Frames Received OK */
+-#define XM_RXO_OK_HI	0x0304	/* 32 bit r/o	Octets Received OK High Cnt */
+-#define XM_RXO_OK_LO	0x0308	/* 32 bit r/o	Octets Received OK Low Counter*/
+-#define XM_RXF_BC_OK	0x030c	/* 32 bit r/o	Broadcast Frames Received OK */
+-#define XM_RXF_MC_OK	0x0310	/* 32 bit r/o	Multicast Frames Received OK */
+-#define XM_RXF_UC_OK	0x0314	/* 32 bit r/o	Unicast Frames Received OK */
+-#define XM_RXF_MPAUSE	0x0318	/* 32 bit r/o	Rx Pause MAC Ctrl Frame Cnt */
+-#define XM_RXF_MCTRL	0x031c	/* 32 bit r/o	Rx MAC Ctrl Frame Counter */
+-#define XM_RXF_INV_MP	0x0320	/* 32 bit r/o	Rx invalid Pause Frame Cnt */
+-#define XM_RXF_INV_MOC	0x0324	/* 32 bit r/o	Rx Frames with inv. MAC Opcode*/
+-#define XM_RXE_BURST	0x0328	/* 32 bit r/o	Rx Burst Event Counter */
+-#define XM_RXE_FMISS	0x032c	/* 32 bit r/o	Rx Missed Frames Event Cnt */
+-#define XM_RXF_FRA_ERR	0x0330	/* 32 bit r/o	Rx Framing Error Counter */
+-#define XM_RXE_FIFO_OV	0x0334	/* 32 bit r/o	Rx FIFO overflow Event Cnt */
+-#define XM_RXF_JAB_PKT	0x0338	/* 32 bit r/o	Rx Jabber Packet Frame Cnt */
+-#define XM_RXE_CAR_ERR	0x033c	/* 32 bit r/o	Rx Carrier Event Error Cnt */
+-#define XM_RXF_LEN_ERR	0x0340	/* 32 bit r/o	Rx in Range Length Error */
+-#define XM_RXE_SYM_ERR	0x0344	/* 32 bit r/o	Rx Symbol Error Counter */
+-#define XM_RXE_SHT_ERR	0x0348	/* 32 bit r/o	Rx Short Event Error Cnt */
+-#define XM_RXE_RUNT		0x034c	/* 32 bit r/o	Rx Runt Event Counter */
+-#define XM_RXF_LNG_ERR	0x0350	/* 32 bit r/o	Rx Frame too Long Error Cnt */
+-#define XM_RXF_FCS_ERR	0x0354	/* 32 bit r/o	Rx Frame Check Seq. Error Cnt */
+-	/* 0x0358 - 0x035a:	reserved */
+-#define XM_RXF_CEX_ERR	0x035c	/* 32 bit r/o	Rx Carrier Ext Error Frame Cnt*/
+-#define XM_RXP_UTIL		0x0360	/* 32 bit r/o	Rx Utilization in % */
+-	/* 0x0364 - 0x0366:	reserved */
+-#define XM_RXF_64B		0x0368	/* 32 bit r/o	64 Byte Rx Frame Counter */
+-#define XM_RXF_127B		0x036c	/* 32 bit r/o	65-127 Byte Rx Frame Counter */
+-#define XM_RXF_255B		0x0370	/* 32 bit r/o	128-255 Byte Rx Frame Counter */
+-#define XM_RXF_511B		0x0374	/* 32 bit r/o	256-511 Byte Rx Frame Counter */
+-#define XM_RXF_1023B	0x0378	/* 32 bit r/o	512-1023 Byte Rx Frame Counter*/
+-#define XM_RXF_MAX_SZ	0x037c	/* 32 bit r/o	1024-MaxSize Byte Rx Frame Cnt*/
+-	/* 0x02e8 - 0x02fe:	reserved */
+-
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * XMAC Bit Definitions
+- *
+- * If the bit access behaviour differs from the register access behaviour
+- * (r/w, r/o) this is documented after the bit number.
+- * The following bit access behaviours are used:
+- *	(sc)	self clearing
+- *	(ro)	read only
+- */
+-
+-/*	XM_MMU_CMD	16 bit r/w	MMU Command Register */
+-								/* Bit 15..13:	reserved */
+-#define XM_MMU_PHY_RDY	(1<<12)	/* Bit 12:	PHY Read Ready */
+-#define XM_MMU_PHY_BUSY	(1<<11)	/* Bit 11:	PHY Busy */
+-#define XM_MMU_IGN_PF	(1<<10)	/* Bit 10:	Ignore Pause Frame */
+-#define XM_MMU_MAC_LB	(1<<9)	/* Bit  9:	Enable MAC Loopback */
+-								/* Bit  8:	reserved */
+-#define XM_MMU_FRC_COL	(1<<7)	/* Bit  7:	Force Collision */
+-#define XM_MMU_SIM_COL	(1<<6)	/* Bit  6:	Simulate Collision */
+-#define XM_MMU_NO_PRE	(1<<5)	/* Bit  5:	No MDIO Preamble */
+-#define XM_MMU_GMII_FD	(1<<4)	/* Bit  4:	GMII uses Full Duplex */
+-#define XM_MMU_RAT_CTRL	(1<<3)	/* Bit  3:	Enable Rate Control */
+-#define XM_MMU_GMII_LOOP (1<<2)	/* Bit  2:	PHY is in Loopback Mode */
+-#define XM_MMU_ENA_RX	(1<<1)	/* Bit  1:	Enable Receiver */
+-#define XM_MMU_ENA_TX	(1<<0)	/* Bit  0:	Enable Transmitter */
+-
+-
+-/*	XM_TX_CMD	16 bit r/w	Transmit Command Register */
+-								/* Bit 15..7:	reserved */
+-#define XM_TX_BK2BK		(1<<6)	/* Bit  6:	Ignor Carrier Sense (Tx Bk2Bk)*/
+-#define XM_TX_ENC_BYP	(1<<5)	/* Bit  5:	Set Encoder in Bypass Mode */
+-#define XM_TX_SAM_LINE	(1<<4)	/* Bit  4: (sc)	Start utilization calculation */
+-#define XM_TX_NO_GIG_MD	(1<<3)	/* Bit  3:	Disable Carrier Extension */
+-#define XM_TX_NO_PRE	(1<<2)	/* Bit  2:	Disable Preamble Generation */
+-#define XM_TX_NO_CRC	(1<<1)	/* Bit  1:	Disable CRC Generation */
+-#define XM_TX_AUTO_PAD	(1<<0)	/* Bit  0:	Enable Automatic Padding */
+-
+-
+-/*	XM_TX_RT_LIM	16 bit r/w	Transmit Retry Limit Register */
+-								/* Bit 15..5:	reserved */
+-#define XM_RT_LIM_MSK	0x1f	/* Bit  4..0:	Tx Retry Limit */
+-
+-
+-/*	XM_TX_STIME	16 bit r/w	Transmit Slottime Register */
+-								/* Bit 15..7:	reserved */
+-#define XM_STIME_MSK	0x7f	/* Bit  6..0:	Tx Slottime bits */
+-
+-
+-/*	XM_TX_IPG	16 bit r/w	Transmit Inter Packet Gap */
+-								/* Bit 15..8:	reserved */
+-#define XM_IPG_MSK		0xff	/* Bit  7..0:	IPG value bits */
+-
+-
+-/*	XM_RX_CMD	16 bit r/w	Receive Command Register */
+-								/* Bit 15..9:	reserved */
+-#define XM_RX_LENERR_OK (1<<8)	/* Bit  8	don't set Rx Err bit for */
+-								/*		inrange error packets */
+-#define XM_RX_BIG_PK_OK	(1<<7)	/* Bit  7	don't set Rx Err bit for */
+-								/*		jumbo packets */
+-#define XM_RX_IPG_CAP	(1<<6)	/* Bit  6	repl. type field with IPG */
+-#define XM_RX_TP_MD		(1<<5)	/* Bit  5:	Enable transparent Mode */
+-#define XM_RX_STRIP_FCS	(1<<4)	/* Bit  4:	Enable FCS Stripping */
+-#define XM_RX_SELF_RX	(1<<3)	/* Bit  3: 	Enable Rx of own packets */
+-#define XM_RX_SAM_LINE	(1<<2)	/* Bit  2: (sc)	Start utilization calculation */
+-#define XM_RX_STRIP_PAD	(1<<1)	/* Bit  1:	Strip pad bytes of Rx frames */
+-#define XM_RX_DIS_CEXT	(1<<0)	/* Bit  0:	Disable carrier ext. check */
+-
+-
+-/*	XM_PHY_ADDR	16 bit r/w	PHY Address Register */
+-								/* Bit 15..5:	reserved */
+-#define XM_PHY_ADDR_SZ	0x1f	/* Bit  4..0:	PHY Address bits */
+-
+-
+-/*	XM_GP_PORT	32 bit r/w	General Purpose Port Register */
+-								/* Bit 31..7:	reserved */
+-#define XM_GP_ANIP		(1L<<6)	/* Bit  6: (ro)	Auto-Neg. in progress */
+-#define XM_GP_FRC_INT	(1L<<5)	/* Bit  5: (sc)	Force Interrupt */
+-								/* Bit  4:	reserved */
+-#define XM_GP_RES_MAC	(1L<<3)	/* Bit  3: (sc)	Reset MAC and FIFOs */
+-#define XM_GP_RES_STAT	(1L<<2)	/* Bit  2: (sc)	Reset the statistics module */
+-								/* Bit  1:	reserved */
+-#define XM_GP_INP_ASS	(1L<<0)	/* Bit  0: (ro) GP Input Pin asserted */
+-
+-
+-/*	XM_IMSK		16 bit r/w	Interrupt Mask Register */
+-/*	XM_ISRC		16 bit r/o	Interrupt Status Register */
+-								/* Bit 15:	reserved */
+-#define XM_IS_LNK_AE	(1<<14) /* Bit 14:	Link Asynchronous Event */
+-#define XM_IS_TX_ABORT	(1<<13) /* Bit 13:	Transmit Abort, late Col. etc */
+-#define XM_IS_FRC_INT	(1<<12) /* Bit 12:	Force INT bit set in GP */
+-#define XM_IS_INP_ASS	(1<<11)	/* Bit 11:	Input Asserted, GP bit 0 set */
+-#define XM_IS_LIPA_RC	(1<<10)	/* Bit 10:	Link Partner requests config */
+-#define XM_IS_RX_PAGE	(1<<9)	/* Bit  9:	Page Received */
+-#define XM_IS_TX_PAGE	(1<<8)	/* Bit  8:	Next Page Loaded for Transmit */
+-#define XM_IS_AND		(1<<7)	/* Bit  7:	Auto-Negotiation Done */
+-#define XM_IS_TSC_OV	(1<<6)	/* Bit  6:	Time Stamp Counter Overflow */
+-#define XM_IS_RXC_OV	(1<<5)	/* Bit  5:	Rx Counter Event Overflow */
+-#define XM_IS_TXC_OV	(1<<4)	/* Bit  4:	Tx Counter Event Overflow */
+-#define XM_IS_RXF_OV	(1<<3)	/* Bit  3:	Receive FIFO Overflow */
+-#define XM_IS_TXF_UR	(1<<2)	/* Bit  2:	Transmit FIFO Underrun */
+-#define XM_IS_TX_COMP	(1<<1)	/* Bit  1:	Frame Tx Complete */
+-#define XM_IS_RX_COMP	(1<<0)	/* Bit  0:	Frame Rx Complete */
+-
+-#define XM_DEF_MSK	(~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\
+-			XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR))
+-
+-
+-/*	XM_HW_CFG	16 bit r/w	Hardware Config Register */
+-								/* Bit 15.. 4:	reserved */
+-#define XM_HW_GEN_EOP	(1<<3)	/* Bit  3:	generate End of Packet pulse */
+-#define XM_HW_COM4SIG	(1<<2)	/* Bit  2:	use Comma Detect for Sig. Det.*/
+-								/* Bit  1:	reserved */
+-#define XM_HW_GMII_MD	(1<<0)	/* Bit  0:	GMII Interface selected */
+-
+-
+-/*	XM_TX_LO_WM	16 bit r/w	Tx FIFO Low Water Mark */
+-/*	XM_TX_HI_WM	16 bit r/w	Tx FIFO High Water Mark */
+-								/* Bit 15..10	reserved */
+-#define XM_TX_WM_MSK	0x01ff	/* Bit  9.. 0	Tx FIFO Watermark bits */
+-
+-/*	XM_TX_THR	16 bit r/w	Tx Request Threshold */
+-/*	XM_HT_THR	16 bit r/w	Host Request Threshold */
+-/*	XM_RX_THR	16 bit r/w	Rx Request Threshold */
+-								/* Bit 15..11	reserved */
+-#define XM_THR_MSK		0x03ff	/* Bit 10.. 0	Rx/Tx Request Threshold bits */
+-
+-
+-/*	XM_TX_STAT	32 bit r/o	Tx Status LIFO Register */
+-#define XM_ST_VALID		(1UL<<31)	/* Bit 31:	Status Valid */
+-#define XM_ST_BYTE_CNT	(0x3fffL<<17)	/* Bit 30..17:	Tx frame Length */
+-#define XM_ST_RETRY_CNT	(0x1fL<<12)	/* Bit 16..12:	Retry Count */
+-#define XM_ST_EX_COL	(1L<<11)	/* Bit 11:	Excessive Collisions */
+-#define XM_ST_EX_DEF	(1L<<10)	/* Bit 10:	Excessive Deferral */
+-#define XM_ST_BURST		(1L<<9)		/* Bit  9:	p. xmitted in burst md*/
+-#define XM_ST_DEFER		(1L<<8)		/* Bit  8:	packet was defered */
+-#define XM_ST_BC		(1L<<7)		/* Bit  7:	Broadcast packet */
+-#define XM_ST_MC		(1L<<6)		/* Bit  6:	Multicast packet */
+-#define XM_ST_UC		(1L<<5)		/* Bit  5:	Unicast packet */
+-#define XM_ST_TX_UR		(1L<<4)		/* Bit  4:	FIFO Underrun occured */
+-#define XM_ST_CS_ERR	(1L<<3)		/* Bit  3:	Carrier Sense Error */
+-#define XM_ST_LAT_COL	(1L<<2)		/* Bit  2:	Late Collision Error */
+-#define XM_ST_MUL_COL	(1L<<1)		/* Bit  1:	Multiple Collisions */
+-#define XM_ST_SGN_COL	(1L<<0)		/* Bit  0:	Single Collision */
+-
+-/*	XM_RX_LO_WM	16 bit r/w	Receive Low Water Mark */
+-/*	XM_RX_HI_WM	16 bit r/w	Receive High Water Mark */
+-									/* Bit 15..11:	reserved */
+-#define XM_RX_WM_MSK	0x03ff		/* Bit 11.. 0:	Rx FIFO Watermark bits */
+-
+-
+-/*	XM_DEV_ID	32 bit r/o	Device ID Register */
+-#define XM_DEV_OUI	(0x00ffffffUL<<8)	/* Bit 31..8:	Device OUI */
+-#define XM_DEV_REV	(0x07L << 5)		/* Bit  7..5:	Chip Rev Num */
+-
+-
+-/*	XM_MODE		32 bit r/w	Mode Register */
+-									/* Bit 31..27:	reserved */
+-#define XM_MD_ENA_REJ	(1L<<26)	/* Bit 26:	Enable Frame Reject */
+-#define XM_MD_SPOE_E	(1L<<25)	/* Bit 25:	Send Pause on Edge */
+-									/* 		extern generated */
+-#define XM_MD_TX_REP	(1L<<24)	/* Bit 24:	Transmit Repeater Mode */
+-#define XM_MD_SPOFF_I	(1L<<23)	/* Bit 23:	Send Pause on FIFO full */
+-									/*		intern generated */
+-#define XM_MD_LE_STW	(1L<<22)	/* Bit 22:	Rx Stat Word in Little Endian */
+-#define XM_MD_TX_CONT	(1L<<21)	/* Bit 21:	Send Continuous */
+-#define XM_MD_TX_PAUSE	(1L<<20)	/* Bit 20: (sc)	Send Pause Frame */
+-#define XM_MD_ATS		(1L<<19)	/* Bit 19:	Append Time Stamp */
+-#define XM_MD_SPOL_I	(1L<<18)	/* Bit 18:	Send Pause on Low */
+-									/*		intern generated */
+-#define XM_MD_SPOH_I	(1L<<17)	/* Bit 17:	Send Pause on High */
+-									/*		intern generated */
+-#define XM_MD_CAP		(1L<<16)	/* Bit 16:	Check Address Pair */
+-#define XM_MD_ENA_HASH	(1L<<15)	/* Bit 15:	Enable Hashing */
+-#define XM_MD_CSA		(1L<<14)	/* Bit 14:	Check Station Address */
+-#define XM_MD_CAA		(1L<<13)	/* Bit 13:	Check Address Array */
+-#define XM_MD_RX_MCTRL	(1L<<12)	/* Bit 12:	Rx MAC Control Frame */
+-#define XM_MD_RX_RUNT	(1L<<11)	/* Bit 11:	Rx Runt Frames */
+-#define XM_MD_RX_IRLE	(1L<<10)	/* Bit 10:	Rx in Range Len Err Frame */
+-#define XM_MD_RX_LONG	(1L<<9)		/* Bit  9:	Rx Long Frame */
+-#define XM_MD_RX_CRCE	(1L<<8)		/* Bit  8:	Rx CRC Error Frame */
+-#define XM_MD_RX_ERR	(1L<<7)		/* Bit  7:	Rx Error Frame */
+-#define XM_MD_DIS_UC	(1L<<6)		/* Bit  6:	Disable Rx Unicast */
+-#define XM_MD_DIS_MC	(1L<<5)		/* Bit  5:	Disable Rx Multicast */
+-#define XM_MD_DIS_BC	(1L<<4)		/* Bit  4:	Disable Rx Broadcast */
+-#define XM_MD_ENA_PROM	(1L<<3)		/* Bit  3:	Enable Promiscuous */
+-#define XM_MD_ENA_BE	(1L<<2)		/* Bit  2:	Enable Big Endian */
+-#define XM_MD_FTF		(1L<<1)		/* Bit  1: (sc)	Flush Tx FIFO */
+-#define XM_MD_FRF		(1L<<0)		/* Bit  0: (sc)	Flush Rx FIFO */
+-
+-#define XM_PAUSE_MODE	(XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
+-#define XM_DEF_MODE		(XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
+-				XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
+-
+-/*	XM_STAT_CMD	16 bit r/w	Statistics Command Register */
+-								/* Bit 16..6:	reserved */
+-#define XM_SC_SNP_RXC	(1<<5)	/* Bit  5: (sc)	Snap Rx Counters */
+-#define XM_SC_SNP_TXC	(1<<4)	/* Bit  4: (sc)	Snap Tx Counters */
+-#define XM_SC_CP_RXC	(1<<3)	/* Bit  3: 	Copy Rx Counters Continuously */
+-#define XM_SC_CP_TXC	(1<<2)	/* Bit  2:	Copy Tx Counters Continuously */
+-#define XM_SC_CLR_RXC	(1<<1)	/* Bit  1: (sc)	Clear Rx Counters */
+-#define XM_SC_CLR_TXC	(1<<0)	/* Bit  0: (sc) Clear Tx Counters */
+-
+-
+-/*	XM_RX_CNT_EV	32 bit r/o	Rx Counter Event Register */
+-/*	XM_RX_EV_MSK	32 bit r/w	Rx Counter Event Mask */
+-#define XMR_MAX_SZ_OV	(1UL<<31)	/* Bit 31:	1024-MaxSize Rx Cnt Ov*/
+-#define XMR_1023B_OV	(1L<<30)	/* Bit 30:	512-1023Byte Rx Cnt Ov*/
+-#define XMR_511B_OV		(1L<<29)	/* Bit 29:	256-511 Byte Rx Cnt Ov*/
+-#define XMR_255B_OV		(1L<<28)	/* Bit 28:	128-255 Byte Rx Cnt Ov*/
+-#define XMR_127B_OV		(1L<<27)	/* Bit 27:	65-127 Byte Rx Cnt Ov */
+-#define XMR_64B_OV		(1L<<26)	/* Bit 26:	64 Byte Rx Cnt Ov */
+-#define XMR_UTIL_OV		(1L<<25)	/* Bit 25:	Rx Util Cnt Overflow */
+-#define XMR_UTIL_UR		(1L<<24)	/* Bit 24:	Rx Util Cnt Underrun */
+-#define XMR_CEX_ERR_OV	(1L<<23)	/* Bit 23:	CEXT Err Cnt Ov */
+-									/* Bit 22:	reserved */
+-#define XMR_FCS_ERR_OV	(1L<<21)	/* Bit 21:	Rx FCS Error Cnt Ov */
+-#define XMR_LNG_ERR_OV	(1L<<20)	/* Bit 20:	Rx too Long Err Cnt Ov*/
+-#define XMR_RUNT_OV		(1L<<19)	/* Bit 19:	Runt Event Cnt Ov */
+-#define XMR_SHT_ERR_OV	(1L<<18)	/* Bit 18:	Rx Short Ev Err Cnt Ov*/
+-#define XMR_SYM_ERR_OV	(1L<<17)	/* Bit 17:	Rx Sym Err Cnt Ov */
+-									/* Bit 16:	reserved */
+-#define XMR_CAR_ERR_OV	(1L<<15)	/* Bit 15:	Rx Carr Ev Err Cnt Ov */
+-#define XMR_JAB_PKT_OV	(1L<<14)	/* Bit 14:	Rx Jabb Packet Cnt Ov */
+-#define XMR_FIFO_OV		(1L<<13)	/* Bit 13:	Rx FIFO Ov Ev Cnt Ov */
+-#define XMR_FRA_ERR_OV	(1L<<12)	/* Bit 12:	Rx Framing Err Cnt Ov */
+-#define XMR_FMISS_OV	(1L<<11)	/* Bit 11:	Rx Missed Ev Cnt Ov */
+-#define XMR_BURST		(1L<<10)	/* Bit 10:	Rx Burst Event Cnt Ov */
+-#define XMR_INV_MOC		(1L<<9)		/* Bit  9:	Rx with inv. MAC OC Ov*/
+-#define XMR_INV_MP		(1L<<8)		/* Bit  8:	Rx inv Pause Frame Ov */
+-#define XMR_MCTRL_OV	(1L<<7)		/* Bit  7:	Rx MAC Ctrl-F Cnt Ov */
+-#define XMR_MPAUSE_OV	(1L<<6)		/* Bit  6:	Rx Pause MAC Ctrl-F Ov*/
+-#define XMR_UC_OK_OV	(1L<<5)		/* Bit  5:	Rx Unicast Frame CntOv*/
+-#define XMR_MC_OK_OV	(1L<<4)		/* Bit  4:	Rx Multicast Cnt Ov */
+-#define XMR_BC_OK_OV	(1L<<3)		/* Bit  3:	Rx Broadcast Cnt Ov */
+-#define XMR_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Rx OK Low CntOv*/
+-#define XMR_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Rx OK Hi Cnt Ov*/
+-#define XMR_OK_OV		(1L<<0)		/* Bit  0:	Frames Received Ok Ov */
+-
+-#define XMR_DEF_MSK		(XMR_OK_LO_OV | XMR_OK_HI_OV)
+-
+-/*	XM_TX_CNT_EV	32 bit r/o	Tx Counter Event Register */
+-/*	XM_TX_EV_MSK	32 bit r/w	Tx Counter Event Mask */
+-									/* Bit 31..26:	reserved */
+-#define XMT_MAX_SZ_OV	(1L<<25)	/* Bit 25:	1024-MaxSize Tx Cnt Ov*/
+-#define XMT_1023B_OV	(1L<<24)	/* Bit 24:	512-1023Byte Tx Cnt Ov*/
+-#define XMT_511B_OV		(1L<<23)	/* Bit 23:	256-511 Byte Tx Cnt Ov*/
+-#define XMT_255B_OV		(1L<<22)	/* Bit 22:	128-255 Byte Tx Cnt Ov*/
+-#define XMT_127B_OV		(1L<<21)	/* Bit 21:	65-127 Byte Tx Cnt Ov */
+-#define XMT_64B_OV		(1L<<20)	/* Bit 20:	64 Byte Tx Cnt Ov */
+-#define XMT_UTIL_OV		(1L<<19)	/* Bit 19:	Tx Util Cnt Overflow */
+-#define XMT_UTIL_UR		(1L<<18)	/* Bit 18:	Tx Util Cnt Underrun */
+-#define XMT_CS_ERR_OV	(1L<<17)	/* Bit 17:	Tx Carr Sen Err Cnt Ov*/
+-#define XMT_FIFO_UR_OV	(1L<<16)	/* Bit 16:	Tx FIFO Ur Ev Cnt Ov */
+-#define XMT_EX_DEF_OV	(1L<<15)	/* Bit 15:	Tx Ex Deferall Cnt Ov */
+-#define XMT_DEF			(1L<<14)	/* Bit 14:	Tx Deferred Cnt Ov */
+-#define XMT_LAT_COL_OV	(1L<<13)	/* Bit 13:	Tx Late Col Cnt Ov */
+-#define XMT_ABO_COL_OV	(1L<<12)	/* Bit 12:	Tx abo dueto Ex Col Ov*/
+-#define XMT_MUL_COL_OV	(1L<<11)	/* Bit 11:	Tx Mult Col Cnt Ov */
+-#define XMT_SNG_COL		(1L<<10)	/* Bit 10:	Tx Single Col Cnt Ov */
+-#define XMT_MCTRL_OV	(1L<<9)		/* Bit  9:	Tx MAC Ctrl Counter Ov*/
+-#define XMT_MPAUSE		(1L<<8)		/* Bit  8:	Tx Pause MAC Ctrl-F Ov*/
+-#define XMT_BURST		(1L<<7)		/* Bit  7:	Tx Burst Event Cnt Ov */
+-#define XMT_LONG		(1L<<6)		/* Bit  6:	Tx Long Frame Cnt Ov */
+-#define XMT_UC_OK_OV	(1L<<5)		/* Bit  5:	Tx Unicast Cnt Ov */
+-#define XMT_MC_OK_OV	(1L<<4)		/* Bit  4:	Tx Multicast Cnt Ov */
+-#define XMT_BC_OK_OV	(1L<<3)		/* Bit  3:	Tx Broadcast Cnt Ov */
+-#define XMT_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Tx OK Low CntOv*/
+-#define XMT_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Tx OK Hi Cnt Ov*/
+-#define XMT_OK_OV		(1L<<0)		/* Bit  0:	Frames Tx Ok Ov */
+-
+-#define XMT_DEF_MSK		(XMT_OK_LO_OV | XMT_OK_HI_OV)
+-
+-/*
+- * Receive Frame Status Encoding
+- */
+-#define XMR_FS_LEN	(0x3fffUL<<18)	/* Bit 31..18:	Rx Frame Length */
+-#define XMR_FS_2L_VLAN	(1L<<17)	/* Bit 17:	tagged wh 2Lev VLAN ID*/
+-#define XMR_FS_1L_VLAN	(1L<<16)	/* Bit 16:	tagged wh 1Lev VLAN ID*/
+-#define XMR_FS_BC		(1L<<15)	/* Bit 15:	Broadcast Frame */
+-#define XMR_FS_MC		(1L<<14)	/* Bit 14:	Multicast Frame */
+-#define XMR_FS_UC		(1L<<13)	/* Bit 13:	Unicast Frame */
+-									/* Bit 12:	reserved */
+-#define XMR_FS_BURST	(1L<<11)	/* Bit 11:	Burst Mode */
+-#define XMR_FS_CEX_ERR	(1L<<10)	/* Bit 10:	Carrier Ext. Error */
+-#define XMR_FS_802_3	(1L<<9)		/* Bit  9:	802.3 Frame */
+-#define XMR_FS_COL_ERR	(1L<<8)		/* Bit  8:	Collision Error */
+-#define XMR_FS_CAR_ERR	(1L<<7)		/* Bit  7:	Carrier Event Error */
+-#define XMR_FS_LEN_ERR	(1L<<6)		/* Bit  6:	In-Range Length Error */
+-#define XMR_FS_FRA_ERR	(1L<<5)		/* Bit  5:	Framing Error */
+-#define XMR_FS_RUNT		(1L<<4)		/* Bit  4:	Runt Frame */
+-#define XMR_FS_LNG_ERR	(1L<<3)		/* Bit  3:	Giant (Jumbo) Frame */
+-#define XMR_FS_FCS_ERR	(1L<<2)		/* Bit  2:	Frame Check Sequ Err */
+-#define XMR_FS_ERR		(1L<<1)		/* Bit  1:	Frame Error */
+-#define XMR_FS_MCTRL	(1L<<0)		/* Bit  0:	MAC Control Packet */
+-
+-/*
+- * XMR_FS_ERR will be set if
+- *	XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
+- *	XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
+- * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
+- * XMR_FS_ERR unless the corresponding bit in the Receive Command
+- * Register is set.
+- */
+-#define XMR_FS_ANY_ERR	XMR_FS_ERR
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * XMAC-PHY Registers, indirect addressed over the XMAC
+- */
+-#define PHY_XMAC_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+-#define PHY_XMAC_STAT		0x01	/* 16 bit r/w	PHY Status Register */
+-#define PHY_XMAC_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
+-#define PHY_XMAC_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
+-#define PHY_XMAC_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+-#define PHY_XMAC_AUNE_LP	0x05	/* 16 bit r/o	Link Partner Abi Reg */
+-#define PHY_XMAC_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+-#define PHY_XMAC_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+-#define PHY_XMAC_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
+-	/* 0x09 - 0x0e:		reserved */
+-#define PHY_XMAC_EXT_STAT	0x0f	/* 16 bit r/o	Ext Status Register */
+-#define PHY_XMAC_RES_ABI	0x10	/* 16 bit r/o	PHY Resolved Ability */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * Broadcom-PHY Registers, indirect addressed over XMAC
+- */
+-#define PHY_BCOM_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+-#define PHY_BCOM_STAT		0x01	/* 16 bit r/o	PHY Status Register */
+-#define PHY_BCOM_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
+-#define PHY_BCOM_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
+-#define PHY_BCOM_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+-#define PHY_BCOM_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
+-#define PHY_BCOM_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+-#define PHY_BCOM_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+-#define PHY_BCOM_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
+-	/* Broadcom-specific registers */
+-#define PHY_BCOM_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Ctrl Reg */
+-#define PHY_BCOM_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
+-	/* 0x0b - 0x0e:		reserved */
+-#define PHY_BCOM_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
+-#define PHY_BCOM_P_EXT_CTRL	0x10	/* 16 bit r/w	PHY Extended Ctrl Reg */
+-#define PHY_BCOM_P_EXT_STAT	0x11	/* 16 bit r/o	PHY Extended Stat Reg */
+-#define PHY_BCOM_RE_CTR		0x12	/* 16 bit r/w	Receive Error Counter */
+-#define PHY_BCOM_FC_CTR		0x13	/* 16 bit r/w	False Carrier Sense Cnt */
+-#define PHY_BCOM_RNO_CTR	0x14	/* 16 bit r/w	Receiver NOT_OK Cnt */
+-	/* 0x15 - 0x17:		reserved */
+-#define PHY_BCOM_AUX_CTRL	0x18	/* 16 bit r/w	Auxiliary Control Reg */
+-#define PHY_BCOM_AUX_STAT	0x19	/* 16 bit r/o	Auxiliary Stat Summary */
+-#define PHY_BCOM_INT_STAT	0x1a	/* 16 bit r/o	Interrupt Status Reg */
+-#define PHY_BCOM_INT_MASK	0x1b	/* 16 bit r/w	Interrupt Mask Reg */
+-	/* 0x1c:		reserved */
+-	/* 0x1d - 0x1f:		test registers */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * Marvel-PHY Registers, indirect addressed over GMAC
+- */
+-#define PHY_MARV_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+-#define PHY_MARV_STAT		0x01	/* 16 bit r/o	PHY Status Register */
+-#define PHY_MARV_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
+-#define PHY_MARV_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
+-#define PHY_MARV_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+-#define PHY_MARV_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
+-#define PHY_MARV_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+-#define PHY_MARV_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+-#define PHY_MARV_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
+-	/* Marvel-specific registers */
+-#define PHY_MARV_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Ctrl Reg */
+-#define PHY_MARV_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
+-	/* 0x0b - 0x0e:		reserved */
+-#define PHY_MARV_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
+-#define PHY_MARV_PHY_CTRL	0x10	/* 16 bit r/w	PHY Specific Ctrl Reg */
+-#define PHY_MARV_PHY_STAT	0x11	/* 16 bit r/o	PHY Specific Stat Reg */
+-#define PHY_MARV_INT_MASK	0x12	/* 16 bit r/w	Interrupt Mask Reg */
+-#define PHY_MARV_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
+-#define PHY_MARV_EXT_CTRL	0x14	/* 16 bit r/w	Ext. PHY Specific Ctrl */
+-#define PHY_MARV_RXE_CNT	0x15	/* 16 bit r/w	Receive Error Counter */
+-#define PHY_MARV_EXT_ADR	0x16	/* 16 bit r/w	Ext. Ad. for Cable Diag. */
+-	/* 0x17:		reserved */
+-#define PHY_MARV_LED_CTRL	0x18	/* 16 bit r/w	LED Control Reg */
+-#define PHY_MARV_LED_OVER	0x19	/* 16 bit r/w	Manual LED Override Reg */
+-#define PHY_MARV_EXT_CTRL_2	0x1a	/* 16 bit r/w	Ext. PHY Specific Ctrl 2 */
+-#define PHY_MARV_EXT_P_STAT	0x1b	/* 16 bit r/w	Ext. PHY Spec. Stat Reg */
+-#define PHY_MARV_CABLE_DIAG	0x1c	/* 16 bit r/o	Cable Diagnostic Reg */
+-	/* 0x1d - 0x1f:		reserved */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * Level One-PHY Registers, indirect addressed over XMAC
+- */
+-#define PHY_LONE_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+-#define PHY_LONE_STAT		0x01	/* 16 bit r/o	PHY Status Register */
+-#define PHY_LONE_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
+-#define PHY_LONE_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
+-#define PHY_LONE_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+-#define PHY_LONE_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
+-#define PHY_LONE_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+-#define PHY_LONE_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+-#define PHY_LONE_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
+-	/* Level One-specific registers */
+-#define PHY_LONE_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg*/
+-#define PHY_LONE_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
+-	/* 0x0b -0x0e:		reserved */
+-#define PHY_LONE_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
+-#define PHY_LONE_PORT_CFG	0x10	/* 16 bit r/w	Port Configuration Reg*/
+-#define PHY_LONE_Q_STAT		0x11	/* 16 bit r/o	Quick Status Reg */
+-#define PHY_LONE_INT_ENAB	0x12	/* 16 bit r/w	Interrupt Enable Reg */
+-#define PHY_LONE_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
+-#define PHY_LONE_LED_CFG	0x14	/* 16 bit r/w	LED Configuration Reg */
+-#define PHY_LONE_PORT_CTRL	0x15	/* 16 bit r/w	Port Control Reg */
+-#define PHY_LONE_CIM		0x16	/* 16 bit r/o	CIM Reg */
+-	/* 0x17 -0x1c:		reserved */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * National-PHY Registers, indirect addressed over XMAC
+- */
+-#define PHY_NAT_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
+-#define PHY_NAT_STAT		0x01	/* 16 bit r/w	PHY Status Register */
+-#define PHY_NAT_ID0			0x02	/* 16 bit r/o	PHY ID0 Register */
+-#define PHY_NAT_ID1			0x03	/* 16 bit r/o	PHY ID1 Register */
+-#define PHY_NAT_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
+-#define PHY_NAT_AUNE_LP		0x05	/* 16 bit r/o	Link Partner Ability Reg */
+-#define PHY_NAT_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
+-#define PHY_NAT_NEPG		0x07	/* 16 bit r/w	Next Page Register */
+-#define PHY_NAT_NEPG_LP		0x08	/* 16 bit r/o	Next Page Link Partner Reg */
+-	/* National-specific registers */
+-#define PHY_NAT_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg */
+-#define PHY_NAT_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
+-	/* 0x0b -0x0e:		reserved */
+-#define PHY_NAT_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Register */
+-#define PHY_NAT_EXT_CTRL1	0x10	/* 16 bit r/o	Extended Control Reg1 */
+-#define PHY_NAT_Q_STAT1		0x11	/* 16 bit r/o	Quick Status Reg1 */
+-#define PHY_NAT_10B_OP		0x12	/* 16 bit r/o	10Base-T Operations Reg */
+-#define PHY_NAT_EXT_CTRL2	0x13	/* 16 bit r/o	Extended Control Reg1 */
+-#define PHY_NAT_Q_STAT2		0x14	/* 16 bit r/o	Quick Status Reg2 */
+-	/* 0x15 -0x18:		reserved */
+-#define PHY_NAT_PHY_ADDR	0x19	/* 16 bit r/o	PHY Address Register */
+-
+-
+-/*----------------------------------------------------------------------------*/
+-
+-/*
+- * PHY bit definitions
+- * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are
+- * XMAC/Broadcom/LevelOne/National/Marvell-specific.
+- * All other are general.
+- */
+-
+-/*****  PHY_XMAC_CTRL	16 bit r/w	PHY Control Register *****/
+-/*****  PHY_BCOM_CTRL	16 bit r/w	PHY Control Register *****/
+-/*****  PHY_MARV_CTRL	16 bit r/w	PHY Status Register *****/
+-/*****  PHY_LONE_CTRL	16 bit r/w	PHY Control Register *****/
+-#define PHY_CT_RESET	(1<<15)	/* Bit 15: (sc)	clear all PHY related regs */
+-#define PHY_CT_LOOP		(1<<14)	/* Bit 14:	enable Loopback over PHY */
+-#define PHY_CT_SPS_LSB	(1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */
+-#define PHY_CT_ANE		(1<<12)	/* Bit 12:	Auto-Negotiation Enabled */
+-#define PHY_CT_PDOWN	(1<<11)	/* Bit 11: (BC,L1) Power Down Mode */
+-#define PHY_CT_ISOL		(1<<10)	/* Bit 10: (BC,L1) Isolate Mode */
+-#define PHY_CT_RE_CFG	(1<<9)	/* Bit  9: (sc) Restart Auto-Negotiation */
+-#define PHY_CT_DUP_MD	(1<<8)	/* Bit  8:	Duplex Mode */
+-#define PHY_CT_COL_TST	(1<<7)	/* Bit  7: (BC,L1) Collision Test enabled */
+-#define PHY_CT_SPS_MSB	(1<<6)	/* Bit  6: (BC,L1) Speed select, upper bit */
+-								/* Bit  5..0:	reserved */
+-
+-#define PHY_CT_SP1000	PHY_CT_SPS_MSB	/* enable speed of 1000 Mbps */
+-#define PHY_CT_SP100	PHY_CT_SPS_LSB	/* enable speed of  100 Mbps */
+-#define PHY_CT_SP10		(0)				/* enable speed of   10 Mbps */
+-
+-
+-/*****  PHY_XMAC_STAT	16 bit r/w	PHY Status Register *****/
+-/*****  PHY_BCOM_STAT	16 bit r/w	PHY Status Register *****/
+-/*****  PHY_MARV_STAT	16 bit r/w	PHY Status Register *****/
+-/*****  PHY_LONE_STAT	16 bit r/w	PHY Status Register *****/
+-								/* Bit 15..9:	reserved */
+-				/*	(BC/L1) 100/10 Mbps cap bits ignored*/
+-#define PHY_ST_EXT_ST	(1<<8)	/* Bit  8:	Extended Status Present */
+-								/* Bit  7:	reserved */
+-#define PHY_ST_PRE_SUP	(1<<6)	/* Bit  6: (BC/L1) preamble suppression */
+-#define PHY_ST_AN_OVER	(1<<5)	/* Bit  5:	Auto-Negotiation Over */
+-#define PHY_ST_REM_FLT	(1<<4)	/* Bit  4:	Remote Fault Condition Occured */
+-#define PHY_ST_AN_CAP	(1<<3)	/* Bit  3:	Auto-Negotiation Capability */
+-#define PHY_ST_LSYNC	(1<<2)	/* Bit  2:	Link Synchronized */
+-#define PHY_ST_JAB_DET	(1<<1)	/* Bit  1: (BC/L1) Jabber Detected */
+-#define PHY_ST_EXT_REG	(1<<0)	/* Bit  0:	Extended Register available */
+-
+-
+-/*****	PHY_XMAC_ID1		16 bit r/o	PHY ID1 Register */
+-/*****	PHY_BCOM_ID1		16 bit r/o	PHY ID1 Register */
+-/*****	PHY_MARV_ID1		16 bit r/o	PHY ID1 Register */
+-/*****	PHY_LONE_ID1		16 bit r/o	PHY ID1 Register */
+-#define PHY_I1_OUI_MSK	(0x3f<<10)	/* Bit 15..10:	Organization Unique ID */
+-#define PHY_I1_MOD_NUM	(0x3f<<4)	/* Bit  9.. 4:	Model Number */
+-#define PHY_I1_REV_MSK	0x0f		/* Bit  3.. 0:	Revision Number */
+-
+-/* different Broadcom PHY Ids */
+-#define PHY_BCOM_ID1_A1		0x6041
+-#define PHY_BCOM_ID1_B2		0x6043
+-#define PHY_BCOM_ID1_C0		0x6044
+-#define PHY_BCOM_ID1_C5		0x6047
+-
+-
+-/*****  PHY_XMAC_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+-/*****  PHY_XMAC_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
+-#define PHY_AN_NXT_PG	(1<<15)	/* Bit 15:	Request Next Page */
+-#define PHY_X_AN_ACK	(1<<14)	/* Bit 14: (ro)	Acknowledge Received */
+-#define PHY_X_AN_RFB	(3<<12)	/* Bit 13..12:	Remote Fault Bits */
+-								/* Bit 11.. 9:	reserved */
+-#define PHY_X_AN_PAUSE	(3<<7)	/* Bit  8.. 7:	Pause Bits */
+-#define PHY_X_AN_HD		(1<<6)	/* Bit  6:	Half Duplex */
+-#define PHY_X_AN_FD		(1<<5)	/* Bit  5:	Full Duplex */
+-								/* Bit  4.. 0:	reserved */
+-
+-/*****  PHY_BCOM_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+-/*****  PHY_BCOM_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
+-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
+-								/* Bit 14:	reserved */
+-#define PHY_B_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
+-								/* Bit 12:	reserved */
+-#define PHY_B_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
+-#define PHY_B_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
+-								/* Bit  9..5:	100/10 BT cap bits ingnored */
+-#define PHY_B_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
+-
+-/*****  PHY_LONE_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+-/*****  PHY_LONE_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
+-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
+-								/* Bit 14:	reserved */
+-#define PHY_L_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
+-								/* Bit 12:	reserved */
+-#define PHY_L_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
+-#define PHY_L_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
+-								/* Bit  9..5:	100/10 BT cap bits ingnored */
+-#define PHY_L_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
+-
+-/*****  PHY_NAT_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+-/*****  PHY_NAT_AUNE_LP		16 bit r/o	Link Partner Ability Reg *****/
+-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
+-								/* Bit 14:	reserved */
+-#define PHY_N_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
+-								/* Bit 12:	reserved */
+-#define PHY_N_AN_100F	(1<<11)	/* Bit 11:	100Base-T2 FD Support */
+-#define PHY_N_AN_100H	(1<<10)	/* Bit 10:	100Base-T2 HD Support */
+-								/* Bit  9..5:	100/10 BT cap bits ingnored */
+-#define PHY_N_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
+-
+-/* field type definition for PHY_x_AN_SEL */
+-#define PHY_SEL_TYPE	0x01	/* 00001 = Ethernet */
+-
+-/*****  PHY_XMAC_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
+-								/* Bit 15..4:	reserved */
+-#define PHY_ANE_LP_NP	(1<<3)	/* Bit  3:	Link Partner can Next Page */
+-#define PHY_ANE_LOC_NP	(1<<2)	/* Bit  2:	Local PHY can Next Page */
+-#define PHY_ANE_RX_PG	(1<<1)	/* Bit  1:	Page Received */
+-								/* Bit  0:	reserved */
+-
+-/*****  PHY_BCOM_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
+-/*****  PHY_LONE_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
+-/*****  PHY_MARV_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
+-								/* Bit 15..5:	reserved */
+-#define PHY_ANE_PAR_DF	(1<<4)	/* Bit  4:	Parallel Detection Fault */
+-/*	PHY_ANE_LP_NP		(see XMAC) Bit  3:	Link Partner can Next Page */
+-/*	PHY_ANE_LOC_NP		(see XMAC) Bit  2:	Local PHY can Next Page */
+-/*	PHY_ANE_RX_PG		(see XMAC) Bit  1:	Page Received */
+-#define PHY_ANE_LP_CAP	(1<<0)	/* Bit  0:	Link Partner Auto-Neg. Cap. */ 	
+-
+-/*****  PHY_XMAC_NEPG		16 bit r/w	Next Page Register *****/
+-/*****  PHY_BCOM_NEPG		16 bit r/w	Next Page Register *****/
+-/*****  PHY_LONE_NEPG		16 bit r/w	Next Page Register *****/
+-/*****  PHY_XMAC_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
+-/*****  PHY_BCOM_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
+-/*****  PHY_LONE_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
+-#define PHY_NP_MORE		(1<<15)	/* Bit 15:	More, Next Pages to follow */
+-#define PHY_NP_ACK1		(1<<14)	/* Bit 14: (ro)	Ack1, for receiving a message */
+-#define PHY_NP_MSG_VAL	(1<<13)	/* Bit 13:	Message Page valid */
+-#define PHY_NP_ACK2		(1<<12)	/* Bit 12:	Ack2, comply with msg content */
+-#define PHY_NP_TOG		(1<<11)	/* Bit 11:	Toggle Bit, ensure sync */
+-#define PHY_NP_MSG		0x07ff	/* Bit 10..0:	Message from/to Link Partner */
+-
+-/*
+- * XMAC-Specific
+- */
+-/*****  PHY_XMAC_EXT_STAT	16 bit r/w	Extended Status Register *****/
+-#define PHY_X_EX_FD		(1<<15)	/* Bit 15:	Device Supports Full Duplex */
+-#define PHY_X_EX_HD		(1<<14)	/* Bit 14:	Device Supports Half Duplex */
+-								/* Bit 13..0:	reserved */
+-
+-/*****  PHY_XMAC_RES_ABI	16 bit r/o	PHY Resolved Ability *****/
+-								/* Bit 15..9:	reserved */
+-#define PHY_X_RS_PAUSE	(3<<7)	/* Bit  8..7:	selected Pause Mode */
+-#define PHY_X_RS_HD		(1<<6)	/* Bit  6:	Half Duplex Mode selected */
+-#define PHY_X_RS_FD		(1<<5)	/* Bit  5:	Full Duplex Mode selected */
+-#define PHY_X_RS_ABLMIS (1<<4)	/* Bit  4:	duplex or pause cap mismatch */
+-#define PHY_X_RS_PAUMIS (1<<3)	/* Bit  3:	pause capability mismatch */
+-								/* Bit  2..0:	reserved */
+-/*
+- * Remote Fault Bits (PHY_X_AN_RFB) encoding
+- */
+-#define X_RFB_OK		(0<<12)	/* Bit 13..12	No errors, Link OK */
+-#define X_RFB_LF		(1<<12)	/* Bit 13..12	Link Failure */
+-#define X_RFB_OFF		(2<<12)	/* Bit 13..12	Offline */
+-#define X_RFB_AN_ERR	(3<<12)	/* Bit 13..12	Auto-Negotiation Error */
+-
+-/*
+- * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding
+- */
+-#define PHY_X_P_NO_PAUSE	(0<<7)	/* Bit  8..7:	no Pause Mode */
+-#define PHY_X_P_SYM_MD		(1<<7)	/* Bit  8..7:	symmetric Pause Mode */
+-#define PHY_X_P_ASYM_MD		(2<<7)	/* Bit  8..7:	asymmetric Pause Mode */
+-#define PHY_X_P_BOTH_MD		(3<<7)	/* Bit  8..7:	both Pause Mode */
+-
+-
+-/*
+- * Broadcom-Specific
+- */
+-/*****  PHY_BCOM_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+-#define PHY_B_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
+-#define PHY_B_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
+-#define PHY_B_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
+-#define PHY_B_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
+-#define PHY_B_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
+-#define PHY_B_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
+-									/* Bit  7..0:	reserved */
+-
+-/*****  PHY_BCOM_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+-/*****  PHY_MARV_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+-#define PHY_B_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
+-#define PHY_B_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
+-#define PHY_B_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
+-#define PHY_B_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
+-#define PHY_B_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
+-#define PHY_B_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
+-									/* Bit  9..8:	reserved */
+-#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
+-
+-/*****  PHY_BCOM_EXT_STAT	16 bit r/o	Extended Status Register *****/
+-#define PHY_B_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
+-#define PHY_B_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
+-#define PHY_B_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
+-#define PHY_B_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
+-									/* Bit 11..0:	reserved */
+-
+-/*****  PHY_BCOM_P_EXT_CTRL	16 bit r/w	PHY Extended Control Reg *****/
+-#define PHY_B_PEC_MAC_PHY	(1<<15)	/* Bit 15:	10BIT/GMI-Interface */
+-#define PHY_B_PEC_DIS_CROSS	(1<<14)	/* Bit 14:	Disable MDI Crossover */
+-#define PHY_B_PEC_TX_DIS	(1<<13)	/* Bit 13:	Tx output Disabled */
+-#define PHY_B_PEC_INT_DIS	(1<<12)	/* Bit 12:	Interrupts Disabled */
+-#define PHY_B_PEC_F_INT		(1<<11)	/* Bit 11:	Force Interrupt */
+-#define PHY_B_PEC_BY_45		(1<<10)	/* Bit 10:	Bypass 4B5B-Decoder */
+-#define PHY_B_PEC_BY_SCR	(1<<9)	/* Bit  9:	Bypass Scrambler */
+-#define PHY_B_PEC_BY_MLT3	(1<<8)	/* Bit  8:	Bypass MLT3 Encoder */
+-#define PHY_B_PEC_BY_RXA	(1<<7)	/* Bit  7:	Bypass Rx Alignm. */
+-#define PHY_B_PEC_RES_SCR	(1<<6)	/* Bit  6:	Reset Scrambler */
+-#define PHY_B_PEC_EN_LTR	(1<<5)	/* Bit  5:	Ena LED Traffic Mode */
+-#define PHY_B_PEC_LED_ON	(1<<4)	/* Bit  4:	Force LED's on */
+-#define PHY_B_PEC_LED_OFF	(1<<3)	/* Bit  3:	Force LED's off */
+-#define PHY_B_PEC_EX_IPG	(1<<2)	/* Bit  2:	Extend Tx IPG Mode */
+-#define PHY_B_PEC_3_LED		(1<<1)	/* Bit  1:	Three Link LED mode */
+-#define PHY_B_PEC_HIGH_LA	(1<<0)	/* Bit  0:	GMII FIFO Elasticy */
+-
+-/*****  PHY_BCOM_P_EXT_STAT	16 bit r/o	PHY Extended Status Reg *****/
+-									/* Bit 15..14:	reserved */
+-#define PHY_B_PES_CROSS_STAT	(1<<13)	/* Bit 13:	MDI Crossover Status */
+-#define PHY_B_PES_INT_STAT	(1<<12)	/* Bit 12:	Interrupt Status */
+-#define PHY_B_PES_RRS		(1<<11)	/* Bit 11:	Remote Receiver Stat. */
+-#define PHY_B_PES_LRS		(1<<10)	/* Bit 10:	Local Receiver Stat. */
+-#define PHY_B_PES_LOCKED	(1<<9)	/* Bit  9:	Locked */
+-#define PHY_B_PES_LS		(1<<8)	/* Bit  8:	Link Status */
+-#define PHY_B_PES_RF		(1<<7)	/* Bit  7:	Remote Fault */
+-#define PHY_B_PES_CE_ER		(1<<6)	/* Bit  6:	Carrier Ext Error */
+-#define PHY_B_PES_BAD_SSD	(1<<5)	/* Bit  5:	Bad SSD */
+-#define PHY_B_PES_BAD_ESD	(1<<4)	/* Bit  4:	Bad ESD */
+-#define PHY_B_PES_RX_ER		(1<<3)	/* Bit  3:	Receive Error */
+-#define PHY_B_PES_TX_ER		(1<<2)	/* Bit  2:	Transmit Error */
+-#define PHY_B_PES_LOCK_ER	(1<<1)	/* Bit  1:	Lock Error */
+-#define PHY_B_PES_MLT3_ER	(1<<0)	/* Bit  0:	MLT3 code Error */
+-
+-/*****  PHY_BCOM_FC_CTR		16 bit r/w	False Carrier Counter *****/
+-									/* Bit 15..8:	reserved */
+-#define PHY_B_FC_CTR		0xff	/* Bit  7..0:	False Carrier Counter */
+-
+-/*****  PHY_BCOM_RNO_CTR	16 bit r/w	Receive NOT_OK Counter *****/
+-#define PHY_B_RC_LOC_MSK	0xff00	/* Bit 15..8:	Local Rx NOT_OK cnt */
+-#define PHY_B_RC_REM_MSK	0x00ff	/* Bit  7..0:	Remote Rx NOT_OK cnt */
+-
+-/*****  PHY_BCOM_AUX_CTRL	16 bit r/w	Auxiliary Control Reg *****/
+-#define PHY_B_AC_L_SQE		(1<<15)	/* Bit 15:	Low Squelch */
+-#define PHY_B_AC_LONG_PACK	(1<<14)	/* Bit 14:	Rx Long Packets */
+-#define PHY_B_AC_ER_CTRL	(3<<12)	/* Bit 13..12:	Edgerate Control */
+-									/* Bit 11:	reserved */
+-#define PHY_B_AC_TX_TST		(1<<10) /* Bit 10:	Tx test bit, always 1 */
+-									/* Bit  9.. 8:	reserved */
+-#define PHY_B_AC_DIS_PRF	(1<<7)	/* Bit  7:	dis part resp filter */
+-									/* Bit  6:	reserved */
+-#define PHY_B_AC_DIS_PM		(1<<5)	/* Bit  5:	dis power management */
+-									/* Bit  4:	reserved */
+-#define PHY_B_AC_DIAG		(1<<3)	/* Bit  3:	Diagnostic Mode */
+-									/* Bit  2.. 0:	reserved */
+-
+-/*****  PHY_BCOM_AUX_STAT	16 bit r/o	Auxiliary Status Reg *****/
+-#define PHY_B_AS_AN_C		(1<<15)	/* Bit 15:	AutoNeg complete */
+-#define PHY_B_AS_AN_CA		(1<<14)	/* Bit 14:	AN Complete Ack */
+-#define PHY_B_AS_ANACK_D	(1<<13)	/* Bit 13:	AN Ack Detect */
+-#define PHY_B_AS_ANAB_D		(1<<12)	/* Bit 12:	AN Ability Detect */
+-#define PHY_B_AS_NPW		(1<<11)	/* Bit 11:	AN Next Page Wait */
+-#define PHY_B_AS_AN_RES_MSK	(7<<8)	/* Bit 10..8:	AN HDC */
+-#define PHY_B_AS_PDF		(1<<7)	/* Bit  7:	Parallel Detect. Fault */
+-#define PHY_B_AS_RF			(1<<6)	/* Bit  6:	Remote Fault */
+-#define PHY_B_AS_ANP_R		(1<<5)	/* Bit  5:	AN Page Received */
+-#define PHY_B_AS_LP_ANAB	(1<<4)	/* Bit  4:	LP AN Ability */
+-#define PHY_B_AS_LP_NPAB	(1<<3)	/* Bit  3:	LP Next Page Ability */
+-#define PHY_B_AS_LS			(1<<2)	/* Bit  2:	Link Status */
+-#define PHY_B_AS_PRR		(1<<1)	/* Bit  1:	Pause Resolution-Rx */
+-#define PHY_B_AS_PRT		(1<<0)	/* Bit  0:	Pause Resolution-Tx */
+-
+-#define PHY_B_AS_PAUSE_MSK	(PHY_B_AS_PRR | PHY_B_AS_PRT)
+-
+-/*****  PHY_BCOM_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
+-/*****  PHY_BCOM_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
+-									/* Bit 15:	reserved */
+-#define PHY_B_IS_PSE		(1<<14)	/* Bit 14:	Pair Swap Error */
+-#define PHY_B_IS_MDXI_SC	(1<<13)	/* Bit 13:	MDIX Status Change */
+-#define PHY_B_IS_HCT		(1<<12)	/* Bit 12:	counter above 32k */
+-#define PHY_B_IS_LCT		(1<<11)	/* Bit 11:	counter above 128 */
+-#define PHY_B_IS_AN_PR		(1<<10)	/* Bit 10:	Page Received */
+-#define PHY_B_IS_NO_HDCL	(1<<9)	/* Bit  9:	No HCD Link */
+-#define PHY_B_IS_NO_HDC		(1<<8)	/* Bit  8:	No HCD */
+-#define PHY_B_IS_NEG_USHDC	(1<<7)	/* Bit  7:	Negotiated Unsup. HCD */
+-#define PHY_B_IS_SCR_S_ER	(1<<6)	/* Bit  6:	Scrambler Sync Error */
+-#define PHY_B_IS_RRS_CHANGE	(1<<5)	/* Bit  5:	Remote Rx Stat Change */
+-#define PHY_B_IS_LRS_CHANGE	(1<<4)	/* Bit  4:	Local Rx Stat Change */
+-#define PHY_B_IS_DUP_CHANGE	(1<<3)	/* Bit  3:	Duplex Mode Change */
+-#define PHY_B_IS_LSP_CHANGE	(1<<2)	/* Bit  2:	Link Speed Change */
+-#define PHY_B_IS_LST_CHANGE	(1<<1)	/* Bit  1:	Link Status Changed */
+-#define PHY_B_IS_CRC_ER		(1<<0)	/* Bit  0:	CRC Error */
+-
+-#define PHY_B_DEF_MSK	(~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
+-
+-/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
+-#define PHY_B_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
+-#define PHY_B_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
+-#define PHY_B_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
+-#define PHY_B_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
+-
+-/*
+- * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
+- */
+-#define PHY_B_RES_1000FD	(7<<8)	/* Bit 10..8:	1000Base-T Full Dup. */
+-#define PHY_B_RES_1000HD	(6<<8)	/* Bit 10..8:	1000Base-T Half Dup. */
+-/* others: 100/10: invalid for us */
+-
+-/*
+- * Level One-Specific
+- */
+-/*****  PHY_LONE_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+-#define PHY_L_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
+-#define PHY_L_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
+-#define PHY_L_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
+-#define PHY_L_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
+-#define PHY_L_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
+-#define PHY_L_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
+-									/* Bit  7..0:	reserved */
+-
+-/*****  PHY_LONE_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+-#define PHY_L_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
+-#define PHY_L_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
+-#define PHY_L_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
+-#define PHY_L_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
+-#define PHY_L_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
+-#define PHY_L_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
+-									/* Bit  9..8:	reserved */
+-#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
+-
+-/*****  PHY_LONE_EXT_STAT	16 bit r/o	Extended Status Register *****/
+-#define PHY_L_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
+-#define PHY_L_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
+-#define PHY_L_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
+-#define PHY_L_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
+-									/* Bit 11..0:	reserved */
+-
+-/*****  PHY_LONE_PORT_CFG	16 bit r/w	Port Configuration Reg *****/
+-#define PHY_L_PC_REP_MODE	(1<<15)	/* Bit 15:	Repeater Mode */
+-									/* Bit 14:	reserved */
+-#define PHY_L_PC_TX_DIS		(1<<13)	/* Bit 13:	Tx output Disabled */
+-#define PHY_L_PC_BY_SCR		(1<<12)	/* Bit 12:	Bypass Scrambler */
+-#define PHY_L_PC_BY_45		(1<<11)	/* Bit 11:	Bypass 4B5B-Decoder */
+-#define PHY_L_PC_JAB_DIS	(1<<10)	/* Bit 10:	Jabber Disabled */
+-#define PHY_L_PC_SQE		(1<<9)	/* Bit  9:	Enable Heartbeat */
+-#define PHY_L_PC_TP_LOOP	(1<<8)	/* Bit  8:	TP Loopback */
+-#define PHY_L_PC_SSS		(1<<7)	/* Bit  7:	Smart Speed Selection */
+-#define PHY_L_PC_FIFO_SIZE	(1<<6)	/* Bit  6:	FIFO Size */
+-#define PHY_L_PC_PRE_EN		(1<<5)	/* Bit  5:	Preamble Enable */
+-#define PHY_L_PC_CIM		(1<<4)	/* Bit  4:	Carrier Integrity Mon */
+-#define PHY_L_PC_10_SER		(1<<3)	/* Bit  3:	Use Serial Output */
+-#define PHY_L_PC_ANISOL		(1<<2)	/* Bit  2:	Unisolate Port */
+-#define PHY_L_PC_TEN_BIT	(1<<1)	/* Bit  1:	10bit iface mode on */
+-#define PHY_L_PC_ALTCLOCK	(1<<0)	/* Bit  0: (ro)	ALTCLOCK Mode on */
+-
+-/*****  PHY_LONE_Q_STAT		16 bit r/o	Quick Status Reg *****/
+-#define PHY_L_QS_D_RATE		(3<<14)	/* Bit 15..14:	Data Rate */
+-#define PHY_L_QS_TX_STAT	(1<<13)	/* Bit 13:	Transmitting */
+-#define PHY_L_QS_RX_STAT	(1<<12)	/* Bit 12:	Receiving */
+-#define PHY_L_QS_COL_STAT	(1<<11)	/* Bit 11:	Collision */
+-#define PHY_L_QS_L_STAT		(1<<10)	/* Bit 10:	Link is up */
+-#define PHY_L_QS_DUP_MOD	(1<<9)	/* Bit  9:	Full/Half Duplex */
+-#define PHY_L_QS_AN			(1<<8)	/* Bit  8:	AutoNeg is On */
+-#define PHY_L_QS_AN_C		(1<<7)	/* Bit  7:	AN is Complete */
+-#define PHY_L_QS_LLE		(7<<4)	/* Bit  6:	Line Length Estim. */
+-#define PHY_L_QS_PAUSE		(1<<3)	/* Bit  3:	LP advertised Pause */
+-#define PHY_L_QS_AS_PAUSE	(1<<2)	/* Bit  2:	LP adv. asym. Pause */
+-#define PHY_L_QS_ISOLATE	(1<<1)	/* Bit  1:	CIM Isolated */
+-#define PHY_L_QS_EVENT		(1<<0)	/* Bit  0:	Event has occurred */
+-
+-/*****  PHY_LONE_INT_ENAB	16 bit r/w	Interrupt Enable Reg *****/
+-/*****  PHY_LONE_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
+-									/* Bit 15..14:	reserved */
+-#define PHY_L_IS_AN_F		(1<<13)	/* Bit 13:	Auto-Negotiation fault */
+-									/* Bit 12:	not described */
+-#define PHY_L_IS_CROSS		(1<<11)	/* Bit 11:	Crossover used */
+-#define PHY_L_IS_POL		(1<<10)	/* Bit 10:	Polarity correct. used */
+-#define PHY_L_IS_SS			(1<<9)	/* Bit  9:	Smart Speed Downgrade */
+-#define PHY_L_IS_CFULL		(1<<8)	/* Bit  8:	Counter Full */
+-#define PHY_L_IS_AN_C		(1<<7)	/* Bit  7:	AutoNeg Complete */
+-#define PHY_L_IS_SPEED		(1<<6)	/* Bit  6:	Speed Changed */
+-#define PHY_L_IS_DUP		(1<<5)	/* Bit  5:	Duplex Changed */
+-#define PHY_L_IS_LS			(1<<4)	/* Bit  4:	Link Status Changed */
+-#define PHY_L_IS_ISOL		(1<<3)	/* Bit  3:	Isolate Occured */
+-#define PHY_L_IS_MDINT		(1<<2)	/* Bit  2: (ro)	STAT: MII Int Pending */
+-#define PHY_L_IS_INTEN		(1<<1)	/* Bit  1:	ENAB: Enable IRQs */
+-#define PHY_L_IS_FORCE		(1<<0)	/* Bit  0:	ENAB: Force Interrupt */
+-
+-/* int. mask */
+-#define PHY_L_DEF_MSK		(PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
+-
+-/*****  PHY_LONE_LED_CFG	16 bit r/w	LED Configuration Reg *****/
+-#define PHY_L_LC_LEDC		(3<<14)	/* Bit 15..14:	Col/Blink/On/Off */
+-#define PHY_L_LC_LEDR		(3<<12)	/* Bit 13..12:	Rx/Blink/On/Off */
+-#define PHY_L_LC_LEDT		(3<<10)	/* Bit 11..10:	Tx/Blink/On/Off */
+-#define PHY_L_LC_LEDG		(3<<8)	/* Bit  9..8:	Giga/Blink/On/Off */
+-#define PHY_L_LC_LEDS		(3<<6)	/* Bit  7..6:	10-100/Blink/On/Off */
+-#define PHY_L_LC_LEDL		(3<<4)	/* Bit  5..4:	Link/Blink/On/Off */
+-#define PHY_L_LC_LEDF		(3<<2)	/* Bit  3..2:	Duplex/Blink/On/Off */
+-#define PHY_L_LC_PSTRECH	(1<<1)	/* Bit  1:	Strech LED Pulses */
+-#define PHY_L_LC_FREQ		(1<<0)	/* Bit  0:	30/100 ms */
+-
+-/*****  PHY_LONE_PORT_CTRL	16 bit r/w	Port Control Reg *****/
+-#define PHY_L_PC_TX_TCLK	(1<<15)	/* Bit 15:	Enable TX_TCLK */
+-									/* Bit 14:	reserved */
+-#define PHY_L_PC_ALT_NP		(1<<13)	/* Bit 14:	Alternate Next Page */
+-#define PHY_L_PC_GMII_ALT	(1<<12)	/* Bit 13:	Alternate GMII driver */
+-									/* Bit 11:	reserved */
+-#define PHY_L_PC_TEN_CRS	(1<<10)	/* Bit 10:	Extend CRS*/
+-									/* Bit  9..0:	not described */
+-
+-/*****  PHY_LONE_CIM		16 bit r/o	CIM Reg *****/
+-#define PHY_L_CIM_ISOL		(255<<8)/* Bit 15..8:	Isolate Count */
+-#define PHY_L_CIM_FALSE_CAR	(255<<0)/* Bit  7..0:	False Carrier Count */
+-
+-
+-/*
+- * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
+- */
+-#define PHY_L_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
+-#define PHY_L_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
+-#define PHY_L_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
+-#define PHY_L_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
+-
+-
+-/*
+- * National-Specific
+- */
+-/*****  PHY_NAT_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+-#define PHY_N_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
+-#define PHY_N_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
+-#define PHY_N_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
+-#define PHY_N_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
+-#define PHY_N_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
+-#define PHY_N_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
+-#define PHY_N_1000C_APC		(1<<7)	/* Bit  7:	Asymmetric Pause Cap. */
+-									/* Bit  6..0:	reserved */
+-
+-/*****  PHY_NAT_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+-#define PHY_N_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
+-#define PHY_N_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
+-#define PHY_N_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
+-#define PHY_N_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status*/
+-#define PHY_N_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
+-#define PHY_N_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
+-#define PHY_N_1000C_LP_APC	(1<<9)	/* Bit  9:	LP Asym. Pause Cap. */
+-									/* Bit  8:	reserved */
+-#define PHY_N_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
+-
+-/*****  PHY_NAT_EXT_STAT	16 bit r/o	Extended Status Register *****/
+-#define PHY_N_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
+-#define PHY_N_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
+-#define PHY_N_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
+-#define PHY_N_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
+-									/* Bit 11..0:	reserved */
+-
+-/* todo: those are still missing */
+-/*****  PHY_NAT_EXT_CTRL1	16 bit r/o	Extended Control Reg1 *****/
+-/*****  PHY_NAT_Q_STAT1		16 bit r/o	Quick Status Reg1 *****/
+-/*****  PHY_NAT_10B_OP		16 bit r/o	10Base-T Operations Reg *****/
+-/*****  PHY_NAT_EXT_CTRL2	16 bit r/o	Extended Control Reg1 *****/
+-/*****  PHY_NAT_Q_STAT2		16 bit r/o	Quick Status Reg2 *****/
+-/*****  PHY_NAT_PHY_ADDR	16 bit r/o	PHY Address Register *****/
+-
+-/*
+- * Marvell-Specific
+- */
+-/*****  PHY_MARV_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
+-/*****  PHY_MARV_AUNE_LP	16 bit r/w	Link Part Ability Reg *****/
+-#define PHY_M_AN_NXT_PG		BIT_15	/* Request Next Page */
+-#define PHY_M_AN_ACK		BIT_14	/* (ro)	Acknowledge Received */
+-#define PHY_M_AN_RF			BIT_13	/* Remote Fault */
+-									/* Bit 12:	reserved */
+-#define PHY_M_AN_ASP		BIT_11	/* Asymmetric Pause */
+-#define PHY_M_AN_PC			BIT_10	/* MAC Pause implemented */
+-#define PHY_M_AN_100_FD		BIT_8	/* Advertise 100Base-TX Full Duplex */
+-#define PHY_M_AN_100_HD		BIT_7	/* Advertise 100Base-TX Half Duplex */
+-#define PHY_M_AN_10_FD		BIT_6	/* Advertise 10Base-TX Full Duplex */
+-#define PHY_M_AN_10_HD		BIT_5	/* Advertise 10Base-TX Half Duplex */
+-
+-/* special defines for FIBER (88E1011S only) */
+-#define PHY_M_AN_ASP_X		BIT_8	/* Asymmetric Pause */
+-#define PHY_M_AN_PC_X		BIT_7	/* MAC Pause implemented */
+-#define PHY_M_AN_1000X_AHD	BIT_6	/* Advertise 10000Base-X Half Duplex */
+-#define PHY_M_AN_1000X_AFD	BIT_5	/* Advertise 10000Base-X Full Duplex */
+-
+-/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+-#define PHY_M_P_NO_PAUSE_X	(0<<7)	/* Bit  8.. 7:	no Pause Mode */
+-#define PHY_M_P_SYM_MD_X	(1<<7)	/* Bit  8.. 7:	symmetric Pause Mode */
+-#define PHY_M_P_ASYM_MD_X	(2<<7)	/* Bit  8.. 7:	asymmetric Pause Mode */
+-#define PHY_M_P_BOTH_MD_X	(3<<7)	/* Bit  8.. 7:	both Pause Mode */
+-
+-/*****  PHY_MARV_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+-#define PHY_M_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
+-#define PHY_M_1000C_MSE		(1<<12)	/* Bit 12:	Manual Master/Slave Enable */
+-#define PHY_M_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration (1=Master) */
+-#define PHY_M_1000C_MPD		(1<<10)	/* Bit 10:	Multi-Port Device */
+-#define PHY_M_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
+-#define PHY_M_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
+-									/* Bit  7..0:	reserved */
+-
+-/*****  PHY_MARV_PHY_CTRL	16 bit r/w	PHY Specific Ctrl Reg *****/
+-#define PHY_M_PC_TX_FFD_MSK	(3<<14)	/* Bit 15..14:	Tx FIFO Depth Mask */
+-#define PHY_M_PC_RX_FFD_MSK	(3<<12)	/* Bit 13..12:	Rx FIFO Depth Mask */
+-#define PHY_M_PC_ASS_CRS_TX	(1<<11)	/* Bit 11:	Assert CRS on Transmit */
+-#define PHY_M_PC_FL_GOOD	(1<<10)	/* Bit 10:	Force Link Good */
+-#define PHY_M_PC_EN_DET_MSK	(3<<8)	/* Bit  9.. 8:	Energy Detect Mask */
+-#define PHY_M_PC_ENA_EXT_D	(1<<7)	/* Bit  7:	Enable Ext. Distance (10BT) */
+-#define PHY_M_PC_MDIX_MSK	(3<<5)	/* Bit  6.. 5:	MDI/MDIX Config. Mask */
+-#define PHY_M_PC_DIS_125CLK	(1<<4)	/* Bit  4:	Disable 125 CLK */
+-#define PHY_M_PC_MAC_POW_UP	(1<<3)	/* Bit  3:	MAC Power up */
+-#define PHY_M_PC_SQE_T_ENA	(1<<2)	/* Bit  2:	SQE Test Enabled */
+-#define PHY_M_PC_POL_R_DIS	(1<<1)	/* Bit  1:	Polarity Reversal Disabled */
+-#define PHY_M_PC_DIS_JABBER	(1<<0)	/* Bit  0:	Disable Jabber */
+-
+-#define PHY_M_PC_EN_DET			SHIFT8(2)	/* Energy Detect (Mode 1) */
+-#define PHY_M_PC_EN_DET_PLUS	SHIFT8(3)	/* Energy Detect Plus (Mode 2) */
+-
+-#define PHY_M_PC_MDI_XMODE(x)	SHIFT5(x)	
+-#define PHY_M_PC_MAN_MDI	0    	/* 00 = Manual MDI configuration */
+-#define PHY_M_PC_MAN_MDIX	1		/* 01 = Manual MDIX configuration */
+-#define PHY_M_PC_ENA_AUTO	3		/* 11 = Enable Automatic Crossover */
+-
+-/*****  PHY_MARV_PHY_STAT	16 bit r/o	PHY Specific Status Reg *****/
+-#define PHY_M_PS_SPEED_MSK	(3<<14)	/* Bit 15..14:	Speed Mask */
+-#define PHY_M_PS_SPEED_1000	(1<<15)	/*       10 = 1000 Mbps */
+-#define PHY_M_PS_SPEED_100	(1<<14)	/*       01 =  100 Mbps */
+-#define PHY_M_PS_SPEED_10	0		/*       00 =   10 Mbps */
+-#define PHY_M_PS_FULL_DUP	(1<<13)	/* Bit 13:	Full Duplex */
+-#define PHY_M_PS_PAGE_REC	(1<<12)	/* Bit 12:	Page Received */
+-#define PHY_M_PS_SPDUP_RES	(1<<11)	/* Bit 11:	Speed & Duplex Resolved */
+-#define PHY_M_PS_LINK_UP	(1<<10)	/* Bit 10:	Link Up */
+-#define PHY_M_PS_CABLE_MSK	(3<<7)	/* Bit  9.. 7:	Cable Length Mask */
+-#define PHY_M_PS_MDI_X_STAT	(1<<6)	/* Bit  6:	MDI Crossover Stat (1=MDIX) */
+-#define PHY_M_PS_DOWNS_STAT	(1<<5)	/* Bit  5:	Downshift Status (1=downsh.) */
+-#define PHY_M_PS_ENDET_STAT	(1<<4)	/* Bit  4:	Energy Detect Status (1=act) */
+-#define PHY_M_PS_TX_P_EN	(1<<3)	/* Bit  3:	Tx Pause Enabled */
+-#define PHY_M_PS_RX_P_EN	(1<<2)	/* Bit  2:	Rx Pause Enabled */
+-#define PHY_M_PS_POL_REV	(1<<1)	/* Bit  1:	Polarity Reversed */
+-#define PHY_M_PC_JABBER		(1<<0)	/* Bit  0:	Jabber */
+-
+-#define PHY_M_PS_PAUSE_MSK	(PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+-
+-/*****  PHY_MARV_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
+-/*****  PHY_MARV_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
+-#define PHY_M_IS_AN_ERROR	(1<<15)	/* Bit 15:	Auto-Negotiation Error */
+-#define PHY_M_IS_LSP_CHANGE	(1<<14)	/* Bit 14:	Link Speed Changed */
+-#define PHY_M_IS_DUP_CHANGE	(1<<13)	/* Bit 13:	Duplex Mode Changed */
+-#define PHY_M_IS_AN_PR		(1<<12)	/* Bit 12:	Page Received */
+-#define PHY_M_IS_AN_COMPL	(1<<11)	/* Bit 11:	Auto-Negotiation Completed */
+-#define PHY_M_IS_LST_CHANGE	(1<<10)	/* Bit 10:	Link Status Changed */
+-#define PHY_M_IS_SYMB_ERROR	(1<<9)	/* Bit  9:	Symbol Error */
+-#define PHY_M_IS_FALSE_CARR	(1<<8)	/* Bit  8:	False Carrier */
+-#define PHY_M_IS_FIFO_ERROR	(1<<7)	/* Bit  7:	FIFO Overflow/Underrun Error */
+-#define PHY_M_IS_MDI_CHANGE	(1<<6)	/* Bit  6:	MDI Crossover Changed */
+-#define PHY_M_IS_DOWNSH_DET	(1<<5)	/* Bit  5:	Downshift Detected */
+-#define PHY_M_IS_END_CHANGE	(1<<4)	/* Bit  4:	Energy Detect Changed */
+-									/* Bit  3..2:	reserved */
+-#define PHY_M_IS_POL_CHANGE	(1<<1)	/* Bit  1:	Polarity Changed */
+-#define PHY_M_IS_JABBER		(1<<0)	/* Bit  0:	Jabber */
+-
+-#define PHY_M_DEF_MSK		(PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \
+-							PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
+-
+-/*****  PHY_MARV_EXT_CTRL	16 bit r/w	Ext. PHY Specific Ctrl *****/
+-#define PHY_M_EC_M_DSC_MSK	(3<<10)	/* Bit 11..10:	Master downshift counter */
+-#define PHY_M_EC_S_DSC_MSK	(3<<8)	/* Bit  9.. 8:	Slave  downshift counter */
+-#define PHY_M_EC_MAC_S_MSK	(7<<4)	/* Bit  6.. 4:	Def. MAC interface speed */
+-#define PHY_M_EC_FIB_AN_ENA	(1<<3)	/* Bit  3:	Fiber Auto-Neg. Enable */
+-
+-#define PHY_M_EC_M_DSC(x)		SHIFT10(x)	/* 00=1x; 01=2x; 10=3x; 11=4x */
+-#define PHY_M_EC_S_DSC(x)		SHIFT8(x)	/* 00=dis; 01=1x; 10=2x; 11=3x */
+-#define PHY_M_EC_MAC_S(x)		SHIFT4(x)	/* 01X=0; 110=2.5; 111=25 (MHz) */
+-
+-#define MAC_TX_CLK_0_MHZ	2
+-#define MAC_TX_CLK_2_5_MHZ	6
+-#define MAC_TX_CLK_25_MHZ	7
+-
+-/*****  PHY_MARV_LED_CTRL	16 bit r/w	LED Control Reg *****/
+-#define PHY_M_LEDC_DIS_LED	(1<<15)	/* Bit 15:	Disable LED */
+-#define PHY_M_LEDC_PULS_MSK	(7<<12)	/* Bit 14..12:  Pulse Stretch Mask */
+-#define PHY_M_LEDC_F_INT	(1<<11)	/* Bit 11:	Force Interrupt */
+-#define PHY_M_LEDC_BL_R_MSK	(7<<8)	/* Bit 10.. 8:  Blink Rate Mask */
+-									/* Bit  7.. 5:	reserved */
+-#define PHY_M_LEDC_LINK_MSK	(3<<3)	/* Bit  4.. 3:	Link Control Mask */
+-#define PHY_M_LEDC_DP_CTRL	(1<<2)	/* Bit  2:	Duplex Control */
+-#define PHY_M_LEDC_RX_CTRL	(1<<1)	/* Bit  1:	Rx activity / Link */
+-#define PHY_M_LEDC_TX_CTRL	(1<<0)	/* Bit  0:	Tx activity / Link */
+-
+-#define PHY_M_LED_PULS_DUR(x)	SHIFT12(x)	/* Pulse Stretch Duration */
+-
+-#define	PULS_NO_STR		0		/* no pulse stretching */
+-#define	PULS_21MS		1		/* 21 ms to 42 ms */
+-#define PULS_42MS		2		/* 42 ms to 84 ms */
+-#define PULS_84MS		3		/* 84 ms to 170 ms */
+-#define PULS_170MS		4		/* 170 ms to 340 ms */
+-#define PULS_340MS		5		/* 340 ms to 670 ms */
+-#define PULS_670MS		6		/* 670 ms to 1.3 s */
+-#define PULS_1300MS		7		/* 1.3 s to 2.7 s */
+-
+-#define PHY_M_LED_BLINK_RT(x)	SHIFT8(x)	/* Blink Rate */
+-
+-#define BLINK_42MS		0		/* 42 ms */
+-#define BLINK_84MS		1		/* 84 ms */
+-#define BLINK_170MS		2		/* 170 ms */
+-#define BLINK_340MS		3		/* 340 ms */
+-#define BLINK_670MS		4		/* 670 ms */
+-								/* values 5 - 7: reserved */
+-
+-/*****  PHY_MARV_LED_OVER	16 bit r/w	Manual LED Override Reg *****/
+-#define PHY_M_LED_MO_DUP(x)		SHIFT10(x)	/* Bit 11..10:  Duplex */
+-#define PHY_M_LED_MO_10(x)		SHIFT8(x)	/* Bit  9.. 8:  Link 10 */
+-#define PHY_M_LED_MO_100(x)		SHIFT6(x)	/* Bit  7.. 6:  Link 100 */
+-#define PHY_M_LED_MO_1000(x)	SHIFT4(x)	/* Bit  5.. 4:  Link 1000 */
+-#define PHY_M_LED_MO_RX(x)		SHIFT2(x)	/* Bit  3.. 2:  Rx */
+-#define PHY_M_LED_MO_TX(x)		SHIFT0(x)	/* Bit  1.. 0:  Tx */
+-
+-#define MO_LED_NORM			0
+-#define MO_LED_BLINK		1
+-#define MO_LED_OFF			2
+-#define MO_LED_ON			3
+-
+-/*****  PHY_MARV_EXT_CTRL_2	16 bit r/w	Ext. PHY Specific Ctrl 2 *****/
+-									/* Bit 15.. 7:	reserved */
+-#define PHY_M_EC2_FI_IMPED	(1<<6)	/* Bit  6:	Fiber Input  Impedance */
+-#define PHY_M_EC2_FO_IMPED	(1<<5)	/* Bit  5:	Fiber Output Impedance */
+-#define PHY_M_EC2_FO_M_CLK	(1<<4)	/* Bit  4:	Fiber Mode Clock Enable */
+-#define PHY_M_EC2_FO_BOOST	(1<<3)	/* Bit  3:	Fiber Output Boost */
+-#define PHY_M_EC2_FO_AM_MSK	7		/* Bit  2.. 0:	Fiber Output Amplitude */
+-
+-/*****	PHY_MARV_EXT_P_STAT 16 bit r/w	Ext. PHY Specific Status *****/
+-#define PHY_M_FC_AUTO_SEL	(1<<15)	/* Bit 15:	Fiber/Copper Auto Sel. dis. */
+-#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14:	Fiber/Copper Autoneg. reg acc */
+-#define PHY_M_FC_RESULUTION (1<<13)	/* Bit 13:	Fiber/Copper Resulution */
+-#define PHY_M_SER_IF_AN_BP  (1<<12) /* Bit 12:	Ser IF autoneg. bypass enable */
+-#define PHY_M_SER_IF_BP_ST	(1<<11) /* Bit 11:	Ser IF autoneg. bypass status */
+-#define PHY_M_IRQ_POLARITY	(1<<10) /* Bit 10:	IRQ polarity */
+-									/* Bit 9..4: reserved */
+-#define PHY_M_UNDOC1		(1<< 7) /* undocumented bit !! */
+-#define PHY_M_MODE_MASK		(0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */
+-
+-
+-/*****  PHY_MARV_CABLE_DIAG	16 bit r/o	Cable Diagnostic Reg *****/
+-#define PHY_M_CABD_ENA_TEST	(1<<15)	/* Bit 15:	Enable Test */
+-#define PHY_M_CABD_STAT_MSK	(3<<13)	/* Bit 14..13:	Status */
+-									/* Bit 12.. 8:	reserved */
+-#define PHY_M_CABD_DIST_MSK	0xff	/* Bit  7.. 0:	Distance */
+-
+-/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
+-#define CABD_STAT_NORMAL	0
+-#define CABD_STAT_SHORT		1
+-#define CABD_STAT_OPEN		2
+-#define CABD_STAT_FAIL		3
+-
+-
+-/*
+- * GMAC registers
+- *
+- * The GMAC registers are 16 or 32 bits wide.
+- * The GMACs host processor interface is 16 bits wide,
+- * therefore ALL registers will be addressed with 16 bit accesses.
+- *
+- * The following macros are provided to access the GMAC registers
+- * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(),
+- * GM_INHASH(), and GM_OUTHASH().
+- * The macros are defined in SkGeHw.h.
+- *
+- * Note:	NA reg	= Network Address e.g DA, SA etc.
+- *
+- */
+-
+-/* Port Registers */
+-#define GM_GP_STAT		0x0000		/* 16 bit r/o	General Purpose Status */
+-#define GM_GP_CTRL		0x0004		/* 16 bit r/w	General Purpose Control */
+-#define GM_TX_CTRL		0x0008		/* 16 bit r/w	Transmit Control Reg. */
+-#define GM_RX_CTRL		0x000c		/* 16 bit r/w	Receive Control Reg. */
+-#define GM_TX_FLOW_CTRL	0x0010		/* 16 bit r/w	Transmit Flow-Control */
+-#define GM_TX_PARAM		0x0014		/* 16 bit r/w	Transmit Parameter Reg. */
+-#define GM_SERIAL_MODE	0x0018		/* 16 bit r/w	Serial Mode Register */
+-
+-/* Source Address Registers */
+-#define GM_SRC_ADDR_1L	0x001c		/* 16 bit r/w	Source Address 1 (low) */
+-#define GM_SRC_ADDR_1M	0x0020		/* 16 bit r/w	Source Address 1 (middle) */
+-#define GM_SRC_ADDR_1H	0x0024		/* 16 bit r/w	Source Address 1 (high) */
+-#define GM_SRC_ADDR_2L	0x0028		/* 16 bit r/w	Source Address 2 (low) */
+-#define GM_SRC_ADDR_2M	0x002c		/* 16 bit r/w	Source Address 2 (middle) */
+-#define GM_SRC_ADDR_2H	0x0030		/* 16 bit r/w	Source Address 2 (high) */
+-
+-/* Multicast Address Hash Registers */
+-#define GM_MC_ADDR_H1	0x0034		/* 16 bit r/w	Multicast Address Hash 1 */
+-#define GM_MC_ADDR_H2	0x0038		/* 16 bit r/w	Multicast Address Hash 2 */
+-#define GM_MC_ADDR_H3	0x003c		/* 16 bit r/w	Multicast Address Hash 3 */
+-#define GM_MC_ADDR_H4	0x0040		/* 16 bit r/w	Multicast Address Hash 4 */
+-
+-/* Interrupt Source Registers */
+-#define GM_TX_IRQ_SRC	0x0044		/* 16 bit r/o	Tx Overflow IRQ Source */
+-#define GM_RX_IRQ_SRC	0x0048		/* 16 bit r/o	Rx Overflow IRQ Source */
+-#define GM_TR_IRQ_SRC	0x004c		/* 16 bit r/o	Tx/Rx Over. IRQ Source */
+-
+-/* Interrupt Mask Registers */
+-#define GM_TX_IRQ_MSK	0x0050		/* 16 bit r/w	Tx Overflow IRQ Mask */
+-#define GM_RX_IRQ_MSK	0x0054		/* 16 bit r/w	Rx Overflow IRQ Mask */
+-#define GM_TR_IRQ_MSK	0x0058		/* 16 bit r/w	Tx/Rx Over. IRQ Mask */
+-
+-/* Serial Management Interface (SMI) Registers */
+-#define GM_SMI_CTRL		0x0080		/* 16 bit r/w	SMI Control Register */
+-#define GM_SMI_DATA		0x0084		/* 16 bit r/w	SMI Data Register */
+-#define GM_PHY_ADDR		0x0088		/* 16 bit r/w	GPHY Address Register */
+-
+-/* MIB Counters */
+-#define GM_MIB_CNT_BASE	0x0100		/* Base Address of MIB Counters */
+-#define GM_MIB_CNT_SIZE	44			/* Number of MIB Counters */
+-
+-/*
+- * MIB Counters base address definitions (low word) -
+- * use offset 4 for access to high word	(32 bit r/o)
+- */
+-#define GM_RXF_UC_OK \
+-			(GM_MIB_CNT_BASE + 0)	/* Unicast Frames Received OK */
+-#define GM_RXF_BC_OK \
+-			(GM_MIB_CNT_BASE + 8)	/* Broadcast Frames Received OK */
+-#define GM_RXF_MPAUSE \
+-			(GM_MIB_CNT_BASE + 16)	/* Pause MAC Ctrl Frames Received */
+-#define GM_RXF_MC_OK \
+-			(GM_MIB_CNT_BASE + 24)	/* Multicast Frames Received OK */
+-#define GM_RXF_FCS_ERR \
+-			(GM_MIB_CNT_BASE + 32)	/* Rx Frame Check Seq. Error */
+-	/* GM_MIB_CNT_BASE + 40:	reserved */
+-#define GM_RXO_OK_LO \
+-			(GM_MIB_CNT_BASE + 48)	/* Octets Received OK Low */
+-#define GM_RXO_OK_HI \
+-			(GM_MIB_CNT_BASE + 56)	/* Octets Received OK High */
+-#define GM_RXO_ERR_LO \
+-			(GM_MIB_CNT_BASE + 64)	/* Octets Received Invalid Low */
+-#define GM_RXO_ERR_HI \
+-			(GM_MIB_CNT_BASE + 72)	/* Octets Received Invalid High */
+-#define GM_RXF_SHT \
+-			(GM_MIB_CNT_BASE + 80)	/* Frames <64 Byte Received OK */
+-#define GM_RXE_FRAG \
+-			(GM_MIB_CNT_BASE + 88)	/* Frames <64 Byte Received with FCS Err */
+-#define GM_RXF_64B \
+-			(GM_MIB_CNT_BASE + 96)	/* 64 Byte Rx Frame */
+-#define GM_RXF_127B \
+-			(GM_MIB_CNT_BASE + 104)	/* 65-127 Byte Rx Frame */
+-#define GM_RXF_255B \
+-			(GM_MIB_CNT_BASE + 112)	/* 128-255 Byte Rx Frame */
+-#define GM_RXF_511B \
+-			(GM_MIB_CNT_BASE + 120)	/* 256-511 Byte Rx Frame */
+-#define GM_RXF_1023B \
+-			(GM_MIB_CNT_BASE + 128)	/* 512-1023 Byte Rx Frame */
+-#define GM_RXF_1518B \
+-			(GM_MIB_CNT_BASE + 136)	/* 1024-1518 Byte Rx Frame */
+-#define GM_RXF_MAX_SZ \
+-			(GM_MIB_CNT_BASE + 144)	/* 1519-MaxSize Byte Rx Frame */
+-#define GM_RXF_LNG_ERR \
+-			(GM_MIB_CNT_BASE + 152)	/* Rx Frame too Long Error */
+-#define GM_RXF_JAB_PKT \
+-			(GM_MIB_CNT_BASE + 160)	/* Rx Jabber Packet Frame */
+-	/* GM_MIB_CNT_BASE + 168:	reserved */
+-#define GM_RXE_FIFO_OV \
+-			(GM_MIB_CNT_BASE + 176)	/* Rx FIFO overflow Event */
+-	/* GM_MIB_CNT_BASE + 184:	reserved */
+-#define GM_TXF_UC_OK \
+-			(GM_MIB_CNT_BASE + 192)	/* Unicast Frames Xmitted OK */
+-#define GM_TXF_BC_OK \
+-			(GM_MIB_CNT_BASE + 200)	/* Broadcast Frames Xmitted OK */
+-#define GM_TXF_MPAUSE \
+-			(GM_MIB_CNT_BASE + 208)	/* Pause MAC Ctrl Frames Xmitted */
+-#define GM_TXF_MC_OK \
+-			(GM_MIB_CNT_BASE + 216)	/* Multicast Frames Xmitted OK */
+-#define GM_TXO_OK_LO \
+-			(GM_MIB_CNT_BASE + 224)	/* Octets Transmitted OK Low */
+-#define GM_TXO_OK_HI \
+-			(GM_MIB_CNT_BASE + 232)	/* Octets Transmitted OK High */
+-#define GM_TXF_64B \
+-			(GM_MIB_CNT_BASE + 240)	/* 64 Byte Tx Frame */
+-#define GM_TXF_127B \
+-			(GM_MIB_CNT_BASE + 248)	/* 65-127 Byte Tx Frame */
+-#define GM_TXF_255B \
+-			(GM_MIB_CNT_BASE + 256)	/* 128-255 Byte Tx Frame */
+-#define GM_TXF_511B \
+-			(GM_MIB_CNT_BASE + 264)	/* 256-511 Byte Tx Frame */
+-#define GM_TXF_1023B \
+-			(GM_MIB_CNT_BASE + 272)	/* 512-1023 Byte Tx Frame */
+-#define GM_TXF_1518B \
+-			(GM_MIB_CNT_BASE + 280)	/* 1024-1518 Byte Tx Frame */
+-#define GM_TXF_MAX_SZ \
+-			(GM_MIB_CNT_BASE + 288)	/* 1519-MaxSize Byte Tx Frame */
+-	/* GM_MIB_CNT_BASE + 296:	reserved */
+-#define GM_TXF_COL \
+-			(GM_MIB_CNT_BASE + 304)	/* Tx Collision */
+-#define GM_TXF_LAT_COL \
+-			(GM_MIB_CNT_BASE + 312)	/* Tx Late Collision */
+-#define GM_TXF_ABO_COL \
+-			(GM_MIB_CNT_BASE + 320)	/* Tx aborted due to Exces. Col. */
+-#define GM_TXF_MUL_COL \
+-			(GM_MIB_CNT_BASE + 328)	/* Tx Multiple Collision */
+-#define GM_TXF_SNG_COL \
+-			(GM_MIB_CNT_BASE + 336)	/* Tx Single Collision */
+-#define GM_TXE_FIFO_UR \
+-			(GM_MIB_CNT_BASE + 344)	/* Tx FIFO Underrun Event */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * GMAC Bit Definitions
+- *
+- * If the bit access behaviour differs from the register access behaviour
+- * (r/w, r/o) this is documented after the bit number.
+- * The following bit access behaviours are used:
+- *	(sc)	self clearing
+- *	(r/o)	read only
+- */
+-
+-/*	GM_GP_STAT	16 bit r/o	General Purpose Status Register */
+-#define GM_GPSR_SPEED		(1<<15) /* Bit 15:	Port Speed (1 = 100 Mbps) */
+-#define GM_GPSR_DUPLEX		(1<<14) /* Bit 14:	Duplex Mode (1 = Full) */
+-#define GM_GPSR_FC_TX_DIS	(1<<13) /* Bit 13:	Tx Flow-Control Mode Disabled */
+-#define GM_GPSR_LINK_UP		(1<<12)	/* Bit 12:	Link Up Status */
+-#define GM_GPSR_PAUSE		(1<<11)	/* Bit 11:	Pause State */
+-#define GM_GPSR_TX_ACTIVE	(1<<10)	/* Bit 10:	Tx in Progress */
+-#define GM_GPSR_EXC_COL		(1<<9)	/* Bit  9:	Excessive Collisions Occured */
+-#define GM_GPSR_LAT_COL		(1<<8)	/* Bit  8:	Late Collisions Occured */
+-								/* Bit  7..6:	reserved */
+-#define GM_GPSR_PHY_ST_CH	(1<<5)	/* Bit  5:	PHY Status Change */
+-#define GM_GPSR_GIG_SPEED	(1<<4)	/* Bit  4:	Gigabit Speed (1 = 1000 Mbps) */
+-#define GM_GPSR_PART_MODE	(1<<3)	/* Bit  3:	Partition mode */
+-#define GM_GPSR_FC_RX_DIS	(1<<2)	/* Bit  2:	Rx Flow-Control Mode Disabled */
+-#define GM_GPSR_PROM_EN		(1<<1)	/* Bit  1:	Promiscuous Mode Enabled */
+-								/* Bit  0:	reserved */
+-	
+-/*	GM_GP_CTRL	16 bit r/w	General Purpose Control Register */
+-								/* Bit 15:	reserved */
+-#define GM_GPCR_PROM_ENA	(1<<14)	/* Bit 14:	Enable Promiscuous Mode */
+-#define GM_GPCR_FC_TX_DIS	(1<<13) /* Bit 13:	Disable Tx Flow-Control Mode */
+-#define GM_GPCR_TX_ENA		(1<<12) /* Bit 12:	Enable Transmit */
+-#define GM_GPCR_RX_ENA		(1<<11) /* Bit 11:	Enable Receive */
+-#define GM_GPCR_BURST_ENA	(1<<10)	/* Bit 10:	Enable Burst Mode */
+-#define GM_GPCR_LOOP_ENA	(1<<9)	/* Bit  9:	Enable MAC Loopback Mode */
+-#define GM_GPCR_PART_ENA	(1<<8)	/* Bit  8:	Enable Partition Mode */
+-#define GM_GPCR_GIGS_ENA	(1<<7)	/* Bit  7:	Gigabit Speed (1000 Mbps) */
+-#define GM_GPCR_FL_PASS		(1<<6)	/* Bit  6:	Force Link Pass */
+-#define GM_GPCR_DUP_FULL	(1<<5)	/* Bit  5:	Full Duplex Mode */
+-#define GM_GPCR_FC_RX_DIS	(1<<4)	/* Bit  4:	Disable Rx Flow-Control Mode */
+-#define GM_GPCR_SPEED_100	(1<<3)  /* Bit  3:	Port Speed 100 Mbps */
+-#define GM_GPCR_AU_DUP_DIS	(1<<2)	/* Bit  2:	Disable Auto-Update Duplex */
+-#define GM_GPCR_AU_FCT_DIS	(1<<1)	/* Bit  1:	Disable Auto-Update Flow-C. */
+-#define GM_GPCR_AU_SPD_DIS	(1<<0)	/* Bit  0:	Disable Auto-Update Speed */
+-
+-#define GM_GPCR_SPEED_1000	(GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+-#define GM_GPCR_AU_ALL_DIS	(GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\
+-							 GM_GPCR_AU_SPD_DIS)
+-	
+-/*	GM_TX_CTRL				16 bit r/w	Transmit Control Register */
+-#define GM_TXCR_FORCE_JAM	(1<<15)	/* Bit 15:	Force Jam / Flow-Control */
+-#define GM_TXCR_CRC_DIS		(1<<14)	/* Bit 14:	Disable insertion of CRC */
+-#define GM_TXCR_PAD_DIS		(1<<13)	/* Bit 13:	Disable padding of packets */
+-#define GM_TXCR_COL_THR_MSK	(7<<10)	/* Bit 12..10:	Collision Threshold */
+-
+-#define TX_COL_THR(x)		(SHIFT10(x) & GM_TXCR_COL_THR_MSK)
+-
+-#define TX_COL_DEF			0x04
+-	
+-/*	GM_RX_CTRL				16 bit r/w	Receive Control Register */
+-#define GM_RXCR_UCF_ENA		(1<<15)	/* Bit 15:	Enable Unicast filtering */
+-#define GM_RXCR_MCF_ENA		(1<<14)	/* Bit 14:	Enable Multicast filtering */
+-#define GM_RXCR_CRC_DIS		(1<<13)	/* Bit 13:	Remove 4-byte CRC */
+-#define GM_RXCR_PASS_FC		(1<<12)	/* Bit 12:	Pass FC packets to FIFO */
+-	
+-/*	GM_TX_PARAM				16 bit r/w	Transmit Parameter Register */
+-#define GM_TXPA_JAMLEN_MSK	(0x03<<14)	/* Bit 15..14:	Jam Length */
+-#define GM_TXPA_JAMIPG_MSK	(0x1f<<9)	/* Bit 13..9:	Jam IPG */
+-#define GM_TXPA_JAMDAT_MSK	(0x1f<<4)	/* Bit  8..4:	IPG Jam to Data */
+-								/* Bit  3..0:	reserved */
+-
+-#define TX_JAM_LEN_VAL(x)	(SHIFT14(x) & GM_TXPA_JAMLEN_MSK)
+-#define TX_JAM_IPG_VAL(x)	(SHIFT9(x) & GM_TXPA_JAMIPG_MSK)
+-#define TX_IPG_JAM_DATA(x)	(SHIFT4(x) & GM_TXPA_JAMDAT_MSK)
+-
+-#define TX_JAM_LEN_DEF		0x03
+-#define TX_JAM_IPG_DEF		0x0b
+-#define TX_IPG_JAM_DEF		0x1c
+-
+-/*	GM_SERIAL_MODE			16 bit r/w	Serial Mode Register */
+-#define GM_SMOD_DATABL_MSK	(0x1f<<11)	/* Bit 15..11:	Data Blinder (r/o) */
+-#define GM_SMOD_LIMIT_4		(1<<10)	/* Bit 10:	4 consecutive Tx trials */
+-#define GM_SMOD_VLAN_ENA	(1<<9)	/* Bit  9:	Enable VLAN  (Max. Frame Len) */
+-#define GM_SMOD_JUMBO_ENA	(1<<8)	/* Bit  8:	Enable Jumbo (Max. Frame Len) */
+-								/* Bit  7..5:	reserved */
+-#define GM_SMOD_IPG_MSK		0x1f	/* Bit 4..0:	Inter-Packet Gap (IPG) */
+-	
+-#define DATA_BLIND_VAL(x)	(SHIFT11(x) & GM_SMOD_DATABL_MSK)
+-#define DATA_BLIND_DEF		0x04
+-
+-#define IPG_DATA_VAL(x)		(x & GM_SMOD_IPG_MSK)
+-#define IPG_DATA_DEF		0x1e
+-
+-/*	GM_SMI_CTRL				16 bit r/w	SMI Control Register */
+-#define GM_SMI_CT_PHY_A_MSK	(0x1f<<11)	/* Bit 15..11:	PHY Device Address */
+-#define GM_SMI_CT_REG_A_MSK	(0x1f<<6)	/* Bit 10.. 6:	PHY Register Address */
+-#define GM_SMI_CT_OP_RD		(1<<5)	/* Bit  5:	OpCode Read (0=Write)*/
+-#define GM_SMI_CT_RD_VAL	(1<<4)	/* Bit  4:	Read Valid (Read completed) */
+-#define GM_SMI_CT_BUSY		(1<<3)	/* Bit  3:	Busy (Operation in progress) */
+-								/* Bit   2..0:	reserved */
+-	
+-#define GM_SMI_CT_PHY_AD(x)	(SHIFT11(x) & GM_SMI_CT_PHY_A_MSK)
+-#define GM_SMI_CT_REG_AD(x)	(SHIFT6(x) & GM_SMI_CT_REG_A_MSK)
+-
+-	/*	GM_PHY_ADDR				16 bit r/w	GPHY Address Register */
+-								/* Bit  15..6:	reserved */
+-#define GM_PAR_MIB_CLR		(1<<5)	/* Bit  5:	Set MIB Clear Counter Mode */
+-#define GM_PAR_MIB_TST		(1<<4)	/* Bit  4:	MIB Load Counter (Test Mode) */
+-								/* Bit   3..0:	reserved */
+-	
+-/* Receive Frame Status Encoding */
+-#define GMR_FS_LEN	(0xffffUL<<16)	/* Bit 31..16:	Rx Frame Length */
+-								/* Bit  15..14:	reserved */
+-#define GMR_FS_VLAN		(1L<<13)	/* Bit 13:	VLAN Packet */
+-#define GMR_FS_JABBER	(1L<<12)	/* Bit 12:	Jabber Packet */
+-#define GMR_FS_UN_SIZE	(1L<<11)	/* Bit 11:	Undersize Packet */
+-#define GMR_FS_MC		(1L<<10)	/* Bit 10:	Multicast Packet */
+-#define GMR_FS_BC		(1L<<9)		/* Bit  9:	Broadcast Packet */
+-#define GMR_FS_RX_OK	(1L<<8)		/* Bit  8:	Receive OK (Good Packet) */
+-#define GMR_FS_GOOD_FC	(1L<<7)		/* Bit  7:	Good Flow-Control Packet */
+-#define GMR_FS_BAD_FC	(1L<<6)		/* Bit  6:	Bad  Flow-Control Packet */
+-#define GMR_FS_MII_ERR	(1L<<5)		/* Bit  5:	MII Error */
+-#define GMR_FS_LONG_ERR	(1L<<4)		/* Bit  4:	Too Long Packet */
+-#define GMR_FS_FRAGMENT	(1L<<3)		/* Bit  3:	Fragment */
+-								/* Bit  2:	reserved */
+-#define GMR_FS_CRC_ERR	(1L<<1)		/* Bit  1:	CRC Error */
+-#define GMR_FS_RX_FF_OV	(1L<<0)		/* Bit  0:	Rx FIFO Overflow */
+-
+-/*
+- * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
+- */
+-#define GMR_FS_ANY_ERR	(GMR_FS_CRC_ERR | \
+-			GMR_FS_LONG_ERR | \
+-			GMR_FS_MII_ERR | \
+-			GMR_FS_BAD_FC | \
+-			GMR_FS_GOOD_FC | \
+-			GMR_FS_JABBER)
+-
+-/* Rx GMAC FIFO Flush Mask (default) */
+-#define RX_FF_FL_DEF_MSK	(GMR_FS_CRC_ERR | \
+-			GMR_FS_RX_FF_OV | \
+-			GMR_FS_MII_ERR | \
+-			GMR_FS_BAD_FC | \
+-			GMR_FS_GOOD_FC | \
+-			GMR_FS_UN_SIZE | \
+-			GMR_FS_JABBER)
+-
+-/* typedefs *******************************************************************/
+-
+-
+-/* function prototypes ********************************************************/
+-
+-#ifdef __cplusplus
+-}
+-#endif	/* __cplusplus */
+-
+-#endif	/* __INC_XMAC_H */
+diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
+deleted file mode 100644
+index 6e6c56a..0000000
+--- a/drivers/net/sk98lin/skaddr.c
++++ /dev/null
+@@ -1,1788 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skaddr.c
+- * Project:	Gigabit Ethernet Adapters, ADDR-Module
+- * Version:	$Revision: 1.52 $
+- * Date:	$Date: 2003/06/02 13:46:15 $
+- * Purpose:	Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This module is intended to manage multicast addresses, address override,
+- * and promiscuous mode on GEnesis and Yukon adapters.
+- *
+- * Address Layout:
+- *	port address:		physical MAC address
+- *	1st exact match:	logical MAC address (GEnesis only)
+- *	2nd exact match:	RLMT multicast (GEnesis only)
+- *	exact match 3-13:	OS-specific multicasts (GEnesis only)
+- *
+- * Include File Hierarchy:
+- *
+- *	"skdrv1st.h"
+- *	"skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
+-#endif /* DEBUG ||!LINT || !SK_SLIM */
+-
+-#define __SKADDR_C
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif	/* cplusplus */
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-
+-/* defines ********************************************************************/
+-
+-
+-#define XMAC_POLY	0xEDB88320UL	/* CRC32-Poly - XMAC: Little Endian */
+-#define GMAC_POLY	0x04C11DB7L	/* CRC16-Poly - GMAC: Little Endian */
+-#define HASH_BITS	6				/* #bits in hash */
+-#define	SK_MC_BIT	0x01
+-
+-/* Error numbers and messages. */
+-
+-#define SKERR_ADDR_E001		(SK_ERRBASE_ADDR + 0)
+-#define SKERR_ADDR_E001MSG	"Bad Flags."
+-#define SKERR_ADDR_E002		(SKERR_ADDR_E001 + 1)
+-#define SKERR_ADDR_E002MSG	"New Error."
+-
+-/* typedefs *******************************************************************/
+-
+-/* None. */
+-
+-/* global variables ***********************************************************/
+-
+-/* 64-bit hash values with all bits set. */
+-
+-static const SK_U16	OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
+-
+-/* local variables ************************************************************/
+-
+-#ifdef DEBUG
+-static int	Next0[SK_MAX_MACS] = {0};
+-#endif	/* DEBUG */
+-
+-static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+-			   SK_MAC_ADDR *pMc, int Flags);
+-static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+-			     int Flags);
+-static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
+-static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
+-				       SK_U32 PortNumber, int NewPromMode);
+-static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+-			   SK_MAC_ADDR *pMc, int Flags);
+-static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+-			     int Flags);
+-static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
+-static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
+-				       SK_U32 PortNumber, int NewPromMode);
+-
+-/* functions ******************************************************************/
+-
+-/******************************************************************************
+- *
+- *	SkAddrInit - initialize data, set state to init
+- *
+- * Description:
+- *
+- *	SK_INIT_DATA
+- *	============
+- *
+- *	This routine clears the multicast tables and resets promiscuous mode.
+- *	Some entries are reserved for the "logical MAC address", the
+- *	SK-RLMT multicast address, and the BPDU multicast address.
+- *
+- *
+- *	SK_INIT_IO
+- *	==========
+- *
+- *	All permanent MAC addresses are read from EPROM.
+- *	If the current MAC addresses are not already set in software,
+- *	they are set to the values of the permanent addresses.
+- *	The current addresses are written to the corresponding MAC.
+- *
+- *
+- *	SK_INIT_RUN
+- *	===========
+- *
+- *	Nothing.
+- *
+- * Context:
+- *	init, pageable
+- *
+- * Returns:
+- *	SK_ADDR_SUCCESS
+- */
+-int	SkAddrInit(
+-SK_AC	*pAC,	/* the adapter context */
+-SK_IOC	IoC,	/* I/O context */
+-int		Level)	/* initialization level */
+-{
+-	int			j;
+-	SK_U32		i;
+-	SK_U8		*InAddr;
+-	SK_U16		*OutAddr;
+-	SK_ADDR_PORT	*pAPort;
+-
+-	switch (Level) {
+-	case SK_INIT_DATA:
+-		SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0,
+-            (SK_U16) sizeof(SK_ADDR));
+-
+-		for (i = 0; i < SK_MAX_MACS; i++) {
+-			pAPort = &pAC->Addr.Port[i];
+-			pAPort->PromMode = SK_PROM_MODE_NONE;
+-			
+-			pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+-			pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+-			pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+-			pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+-		}
+-#ifdef xDEBUG
+-		for (i = 0; i < SK_MAX_MACS; i++) {
+-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
+-				SK_ADDR_FIRST_MATCH_RLMT) {
+-				Next0[i] |= 4;
+-			}
+-		}
+-#endif	/* DEBUG */
+-		/* pAC->Addr.InitDone = SK_INIT_DATA; */
+-		break;
+-
+-    case SK_INIT_IO:
+-#ifndef SK_NO_RLMT
+-		for (i = 0; i < SK_MAX_NETS; i++) {
+-			pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
+-		}
+-#endif /* !SK_NO_RLMT */
+-#ifdef xDEBUG
+-		for (i = 0; i < SK_MAX_MACS; i++) {
+-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
+-				SK_ADDR_FIRST_MATCH_RLMT) {
+-				Next0[i] |= 8;
+-			}
+-		}
+-#endif	/* DEBUG */
+-		
+-		/* Read permanent logical MAC address from Control Register File. */
+-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+-			InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
+-			SK_IN8(IoC, B2_MAC_1 + j, InAddr);
+-		}
+-
+-		if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
+-			/* Set the current logical MAC address to the permanent one. */
+-			pAC->Addr.Net[0].CurrentMacAddress =
+-				pAC->Addr.Net[0].PermanentMacAddress;
+-			pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
+-		}
+-
+-		/* Set the current logical MAC address. */
+-		pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
+-			pAC->Addr.Net[0].CurrentMacAddress;
+-#if SK_MAX_NETS > 1
+-		/* Set logical MAC address for net 2 to (log | 3). */
+-		if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
+-			pAC->Addr.Net[1].PermanentMacAddress =
+-				pAC->Addr.Net[0].PermanentMacAddress;
+-			pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
+-			/* Set the current logical MAC address to the permanent one. */
+-			pAC->Addr.Net[1].CurrentMacAddress =
+-				pAC->Addr.Net[1].PermanentMacAddress;
+-			pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
+-		}
+-#endif	/* SK_MAX_NETS > 1 */
+-
+-#ifdef DEBUG
+-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+-				("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
+-					i,
+-					pAC->Addr.Net[i].PermanentMacAddress.a[0],
+-					pAC->Addr.Net[i].PermanentMacAddress.a[1],
+-					pAC->Addr.Net[i].PermanentMacAddress.a[2],
+-					pAC->Addr.Net[i].PermanentMacAddress.a[3],
+-					pAC->Addr.Net[i].PermanentMacAddress.a[4],
+-					pAC->Addr.Net[i].PermanentMacAddress.a[5]))
+-			
+-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+-				("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
+-					i,
+-					pAC->Addr.Net[i].CurrentMacAddress.a[0],
+-					pAC->Addr.Net[i].CurrentMacAddress.a[1],
+-					pAC->Addr.Net[i].CurrentMacAddress.a[2],
+-					pAC->Addr.Net[i].CurrentMacAddress.a[3],
+-					pAC->Addr.Net[i].CurrentMacAddress.a[4],
+-					pAC->Addr.Net[i].CurrentMacAddress.a[5]))
+-		}
+-#endif	/* DEBUG */
+-
+-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+-			pAPort = &pAC->Addr.Port[i];
+-
+-			/* Read permanent port addresses from Control Register File. */
+-			for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+-				InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
+-				SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
+-			}
+-
+-			if (!pAPort->CurrentMacAddressSet) {
+-				/*
+-				 * Set the current and previous physical MAC address
+-				 * of this port to its permanent MAC address.
+-				 */
+-				pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
+-				pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
+-				pAPort->CurrentMacAddressSet = SK_TRUE;
+-			}
+-
+-			/* Set port's current physical MAC address. */
+-			OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+-#ifdef GENESIS
+-			if (pAC->GIni.GIGenesis) {
+-				XM_OUTADDR(IoC, i, XM_SA, OutAddr);
+-			}
+-#endif /* GENESIS */
+-#ifdef YUKON
+-			if (!pAC->GIni.GIGenesis) {
+-				GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
+-			}
+-#endif /* YUKON */
+-#ifdef DEBUG
+-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+-				("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+-					pAPort->PermanentMacAddress.a[0],
+-					pAPort->PermanentMacAddress.a[1],
+-					pAPort->PermanentMacAddress.a[2],
+-					pAPort->PermanentMacAddress.a[3],
+-					pAPort->PermanentMacAddress.a[4],
+-					pAPort->PermanentMacAddress.a[5]))
+-			
+-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+-				("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+-					pAPort->CurrentMacAddress.a[0],
+-					pAPort->CurrentMacAddress.a[1],
+-					pAPort->CurrentMacAddress.a[2],
+-					pAPort->CurrentMacAddress.a[3],
+-					pAPort->CurrentMacAddress.a[4],
+-					pAPort->CurrentMacAddress.a[5]))
+-#endif /* DEBUG */
+-		}
+-		/* pAC->Addr.InitDone = SK_INIT_IO; */
+-		break;
+-
+-	case SK_INIT_RUN:
+-#ifdef xDEBUG
+-		for (i = 0; i < SK_MAX_MACS; i++) {
+-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
+-				SK_ADDR_FIRST_MATCH_RLMT) {
+-				Next0[i] |= 16;
+-			}
+-		}
+-#endif	/* DEBUG */
+-
+-		/* pAC->Addr.InitDone = SK_INIT_RUN; */
+-		break;
+-
+-	default:	/* error */
+-		break;
+-	}
+-
+-	return (SK_ADDR_SUCCESS);
+-	
+-}	/* SkAddrInit */
+-
+-#ifndef SK_SLIM
+-
+-/******************************************************************************
+- *
+- *	SkAddrMcClear - clear the multicast table
+- *
+- * Description:
+- *	This routine clears the multicast table.
+- *
+- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
+- *	immediately.
+- *
+- *	It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
+- *	to the adapter in use. The real work is done there.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
+- *	may be called after SK_INIT_IO without limitation
+- *
+- * Returns:
+- *	SK_ADDR_SUCCESS
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-int	SkAddrMcClear(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* I/O context */
+-SK_U32	PortNumber,	/* Index of affected port */
+-int		Flags)		/* permanent/non-perm, sw-only */
+-{
+-	int ReturnCode;
+-	
+-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+-		return (SK_ADDR_ILLEGAL_PORT);
+-	}
+-	
+-	if (pAC->GIni.GIGenesis) {
+-		ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
+-	}
+-	else {
+-		ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
+-	}
+-
+-	return (ReturnCode);
+-
+-}	/* SkAddrMcClear */
+-
+-#endif /* !SK_SLIM */
+-
+-#ifndef SK_SLIM
+-
+-/******************************************************************************
+- *
+- *	SkAddrXmacMcClear - clear the multicast table
+- *
+- * Description:
+- *	This routine clears the multicast table
+- *	(either entry 2 or entries 3-16 and InexactFilter) of the given port.
+- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
+- *	immediately.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
+- *	may be called after SK_INIT_IO without limitation
+- *
+- * Returns:
+- *	SK_ADDR_SUCCESS
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-static int	SkAddrXmacMcClear(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* I/O context */
+-SK_U32	PortNumber,	/* Index of affected port */
+-int		Flags)		/* permanent/non-perm, sw-only */
+-{
+-	int i;
+-
+-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
+-
+-		/* Clear RLMT multicast addresses. */
+-		pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+-	}
+-	else {	/* not permanent => DRV */
+-
+-		/* Clear InexactFilter */
+-		for (i = 0; i < 8; i++) {
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+-		}
+-
+-		/* Clear DRV multicast addresses. */
+-
+-		pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+-	}
+-
+-	if (!(Flags & SK_MC_SW_ONLY)) {
+-		(void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
+-	}
+-
+-	return (SK_ADDR_SUCCESS);
+-	
+-}	/* SkAddrXmacMcClear */
+-
+-#endif /* !SK_SLIM */
+-
+-#ifndef SK_SLIM
+-
+-/******************************************************************************
+- *
+- *	SkAddrGmacMcClear - clear the multicast table
+- *
+- * Description:
+- *	This routine clears the multicast hashing table (InexactFilter)
+- *	(either the RLMT or the driver bits) of the given port.
+- *
+- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
+- *	immediately.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
+- *	may be called after SK_INIT_IO without limitation
+- *
+- * Returns:
+- *	SK_ADDR_SUCCESS
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-static int	SkAddrGmacMcClear(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* I/O context */
+-SK_U32	PortNumber,	/* Index of affected port */
+-int		Flags)		/* permanent/non-perm, sw-only */
+-{
+-	int i;
+-
+-#ifdef DEBUG
+-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
+-#endif	/* DEBUG */
+-
+-	/* Clear InexactFilter */
+-	for (i = 0; i < 8; i++) {
+-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+-	}
+-	
+-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
+-		
+-		/* Copy DRV bits to InexactFilter. */
+-		for (i = 0; i < 8; i++) {
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+-				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
+-			
+-			/* Clear InexactRlmtFilter. */
+-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
+-
+-		}		
+-	}
+-	else {	/* not permanent => DRV */
+-		
+-		/* Copy RLMT bits to InexactFilter. */
+-		for (i = 0; i < 8; i++) {
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+-				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
+-			
+-			/* Clear InexactDrvFilter. */
+-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
+-		}
+-	}
+-	
+-#ifdef DEBUG
+-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
+-#endif	/* DEBUG */
+-	
+-	if (!(Flags & SK_MC_SW_ONLY)) {
+-		(void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
+-	}
+-	
+-	return (SK_ADDR_SUCCESS);
+-
+-}	/* SkAddrGmacMcClear */
+-
+-#ifndef SK_ADDR_CHEAT
+-
+-/******************************************************************************
+- *
+- *	SkXmacMcHash - hash multicast address
+- *
+- * Description:
+- *	This routine computes the hash value for a multicast address.
+- *	A CRC32 algorithm is used.
+- *
+- * Notes:
+- *	The code was adapted from the XaQti data sheet.
+- *
+- * Context:
+- *	runtime, pageable
+- *
+- * Returns:
+- *	Hash value of multicast address.
+- */
+-static SK_U32 SkXmacMcHash(
+-unsigned char *pMc)	/* Multicast address */
+-{
+-	SK_U32 Idx;
+-	SK_U32 Bit;
+-	SK_U32 Data;
+-	SK_U32 Crc;
+-
+-	Crc = 0xFFFFFFFFUL;
+-	for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
+-		Data = *pMc++;
+-		for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
+-			Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
+-		}
+-	}
+-
+-	return (Crc & ((1 << HASH_BITS) - 1));
+-
+-}	/* SkXmacMcHash */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGmacMcHash - hash multicast address
+- *
+- * Description:
+- *	This routine computes the hash value for a multicast address.
+- *	A CRC16 algorithm is used.
+- *
+- * Notes:
+- *
+- *
+- * Context:
+- *	runtime, pageable
+- *
+- * Returns:
+- *	Hash value of multicast address.
+- */
+-static SK_U32 SkGmacMcHash(
+-unsigned char *pMc)	/* Multicast address */
+-{
+-	SK_U32 Data;
+-	SK_U32 TmpData;
+-	SK_U32 Crc;
+-	int Byte;
+-	int Bit;
+-
+-	Crc = 0xFFFFFFFFUL;
+-	for (Byte = 0; Byte < 6; Byte++) {
+-		/* Get next byte. */
+-		Data = (SK_U32) pMc[Byte];
+-		
+-		/* Change bit order in byte. */
+-		TmpData = Data;
+-		for (Bit = 0; Bit < 8; Bit++) {
+-			if (TmpData & 1L) {
+-				Data |=  1L << (7 - Bit);
+-			}
+-			else {
+-				Data &= ~(1L << (7 - Bit));
+-			}
+-			TmpData >>= 1;
+-		}
+-		
+-		Crc ^= (Data << 24);
+-		for (Bit = 0; Bit < 8; Bit++) {
+-			if (Crc & 0x80000000) {
+-				Crc = (Crc << 1) ^ GMAC_POLY;
+-			}
+-			else {
+-				Crc <<= 1;
+-			}
+-		}
+-	}
+-	
+-	return (Crc & ((1 << HASH_BITS) - 1));
+-
+-}	/* SkGmacMcHash */
+-
+-#endif	/* !SK_ADDR_CHEAT */
+-
+-/******************************************************************************
+- *
+- *	SkAddrMcAdd - add a multicast address to a port
+- *
+- * Description:
+- *	This routine enables reception for a given address on the given port.
+- *
+- *	It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
+- *	adapter in use. The real work is done there.
+- *
+- * Notes:
+- *	The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_DATA
+- *
+- * Returns:
+- *	SK_MC_FILTERING_EXACT
+- *	SK_MC_FILTERING_INEXACT
+- *	SK_MC_ILLEGAL_ADDRESS
+- *	SK_MC_ILLEGAL_PORT
+- *	SK_MC_RLMT_OVERFLOW
+- */
+-int	SkAddrMcAdd(
+-SK_AC		*pAC,		/* adapter context */
+-SK_IOC		IoC,		/* I/O context */
+-SK_U32		PortNumber,	/* Port Number */
+-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
+-int			Flags)		/* permanent/non-permanent */
+-{
+-	int ReturnCode;
+-	
+-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+-		return (SK_ADDR_ILLEGAL_PORT);
+-	}
+-	
+-	if (pAC->GIni.GIGenesis) {
+-		ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
+-	}
+-	else {
+-		ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
+-	}
+-
+-	return (ReturnCode);
+-
+-}	/* SkAddrMcAdd */
+-
+-
+-/******************************************************************************
+- *
+- *	SkAddrXmacMcAdd - add a multicast address to a port
+- *
+- * Description:
+- *	This routine enables reception for a given address on the given port.
+- *
+- * Notes:
+- *	The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- *	The multicast bit is only checked if there are no free exact match
+- *	entries.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_DATA
+- *
+- * Returns:
+- *	SK_MC_FILTERING_EXACT
+- *	SK_MC_FILTERING_INEXACT
+- *	SK_MC_ILLEGAL_ADDRESS
+- *	SK_MC_RLMT_OVERFLOW
+- */
+-static int	SkAddrXmacMcAdd(
+-SK_AC		*pAC,		/* adapter context */
+-SK_IOC		IoC,		/* I/O context */
+-SK_U32		PortNumber,	/* Port Number */
+-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
+-int		Flags)		/* permanent/non-permanent */
+-{
+-	int	i;
+-	SK_U8	Inexact;
+-#ifndef SK_ADDR_CHEAT
+-	SK_U32 HashBit;
+-#endif	/* !defined(SK_ADDR_CHEAT) */
+-
+-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
+-#ifdef xDEBUG
+-		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
+-			SK_ADDR_FIRST_MATCH_RLMT) {
+-			Next0[PortNumber] |= 1;
+-			return (SK_MC_RLMT_OVERFLOW);
+-		}
+-#endif	/* DEBUG */
+-		
+-		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
+-			SK_ADDR_LAST_MATCH_RLMT) {
+-			return (SK_MC_RLMT_OVERFLOW);
+-		}
+-
+-		/* Set a RLMT multicast address. */
+-
+-		pAC->Addr.Port[PortNumber].Exact[
+-			pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
+-
+-		return (SK_MC_FILTERING_EXACT);
+-	}
+-
+-#ifdef xDEBUG
+-	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
+-		SK_ADDR_FIRST_MATCH_DRV) {
+-			Next0[PortNumber] |= 2;
+-		return (SK_MC_RLMT_OVERFLOW);
+-	}
+-#endif	/* DEBUG */
+-	
+-	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
+-
+-		/* Set exact match entry. */
+-		pAC->Addr.Port[PortNumber].Exact[
+-			pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
+-
+-		/* Clear InexactFilter */
+-		for (i = 0; i < 8; i++) {
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+-		}
+-	}
+-	else {
+-		if (!(pMc->a[0] & SK_MC_BIT)) {
+-			/* Hashing only possible with multicast addresses */
+-			return (SK_MC_ILLEGAL_ADDRESS);
+-		}
+-#ifndef SK_ADDR_CHEAT
+-		/* Compute hash value of address. */
+-		HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
+-
+-		/* Add bit to InexactFilter. */
+-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
+-			1 << (HashBit % 8);
+-#else	/* SK_ADDR_CHEAT */
+-		/* Set all bits in InexactFilter. */
+-		for (i = 0; i < 8; i++) {
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
+-		}
+-#endif	/* SK_ADDR_CHEAT */
+-	}
+-
+-	for (Inexact = 0, i = 0; i < 8; i++) {
+-		Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+-	}
+-
+-	if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
+-		return (SK_MC_FILTERING_EXACT);
+-	}
+-	else {
+-		return (SK_MC_FILTERING_INEXACT);
+-	}
+-
+-}	/* SkAddrXmacMcAdd */
+-
+-
+-/******************************************************************************
+- *
+- *	SkAddrGmacMcAdd - add a multicast address to a port
+- *
+- * Description:
+- *	This routine enables reception for a given address on the given port.
+- *
+- * Notes:
+- *	The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_DATA
+- *
+- * Returns:
+- *	SK_MC_FILTERING_INEXACT
+- *	SK_MC_ILLEGAL_ADDRESS
+- */
+-static int	SkAddrGmacMcAdd(
+-SK_AC		*pAC,		/* adapter context */
+-SK_IOC		IoC,		/* I/O context */
+-SK_U32		PortNumber,	/* Port Number */
+-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
+-int		Flags)		/* permanent/non-permanent */
+-{
+-	int	i;
+-#ifndef SK_ADDR_CHEAT
+-	SK_U32 HashBit;
+-#endif	/* !defined(SK_ADDR_CHEAT) */
+-		
+-	if (!(pMc->a[0] & SK_MC_BIT)) {
+-		/* Hashing only possible with multicast addresses */
+-		return (SK_MC_ILLEGAL_ADDRESS);
+-	}
+-	
+-#ifndef SK_ADDR_CHEAT
+-	
+-	/* Compute hash value of address. */
+-	HashBit = SkGmacMcHash(&pMc->a[0]);
+-	
+-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
+-		
+-		/* Add bit to InexactRlmtFilter. */
+-		pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
+-			1 << (HashBit % 8);
+-		
+-		/* Copy bit to InexactFilter. */
+-		for (i = 0; i < 8; i++) {
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+-				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
+-		}
+-#ifdef DEBUG
+-		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
+-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
+-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
+-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
+-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
+-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
+-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
+-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
+-#endif	/* DEBUG */
+-	}
+-	else {	/* not permanent => DRV */
+-		
+-		/* Add bit to InexactDrvFilter. */
+-		pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
+-			1 << (HashBit % 8);
+-		
+-		/* Copy bit to InexactFilter. */
+-		for (i = 0; i < 8; i++) {
+-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+-				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
+-		}
+-#ifdef DEBUG
+-		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
+-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
+-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
+-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
+-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
+-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
+-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
+-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
+-#endif	/* DEBUG */
+-	}
+-	
+-#else	/* SK_ADDR_CHEAT */
+-	
+-	/* Set all bits in InexactFilter. */
+-	for (i = 0; i < 8; i++) {
+-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
+-	}
+-#endif	/* SK_ADDR_CHEAT */
+-		
+-	return (SK_MC_FILTERING_INEXACT);
+-	
+-}	/* SkAddrGmacMcAdd */
+-
+-#endif /* !SK_SLIM */
+-
+-/******************************************************************************
+- *
+- *	SkAddrMcUpdate - update the HW MC address table and set the MAC address
+- *
+- * Description:
+- *	This routine enables reception of the addresses contained in a local
+- *	table for a given port.
+- *	It also programs the port's current physical MAC address.
+- *
+- *	It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
+- *	to the adapter in use. The real work is done there.
+- *
+- * Notes:
+- *	The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	SK_MC_FILTERING_EXACT
+- *	SK_MC_FILTERING_INEXACT
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-int	SkAddrMcUpdate(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* I/O context */
+-SK_U32	PortNumber)	/* Port Number */
+-{
+-	int ReturnCode = 0;
+-#if (!defined(SK_SLIM) || defined(DEBUG))
+-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+-		return (SK_ADDR_ILLEGAL_PORT);
+-	}
+-#endif /* !SK_SLIM || DEBUG */
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
+-	}
+-#endif /* GENESIS */
+-#ifdef YUKON
+-	if (!pAC->GIni.GIGenesis) {
+-		ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
+-	}
+-#endif /* YUKON */
+-	return (ReturnCode);
+-
+-}	/* SkAddrMcUpdate */
+-
+-
+-#ifdef GENESIS
+-
+-/******************************************************************************
+- *
+- *	SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
+- *
+- * Description:
+- *	This routine enables reception of the addresses contained in a local
+- *	table for a given port.
+- *	It also programs the port's current physical MAC address.
+- *
+- * Notes:
+- *	The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	SK_MC_FILTERING_EXACT
+- *	SK_MC_FILTERING_INEXACT
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-static int	SkAddrXmacMcUpdate(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* I/O context */
+-SK_U32	PortNumber)	/* Port Number */
+-{
+-	SK_U32		i;
+-	SK_U8		Inexact;
+-	SK_U16		*OutAddr;
+-	SK_ADDR_PORT	*pAPort;
+-
+-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
+-	
+-	pAPort = &pAC->Addr.Port[PortNumber];
+-
+-#ifdef DEBUG
+-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
+-#endif /* DEBUG */
+-
+-	/* Start with 0 to also program the logical MAC address. */
+-	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
+-		/* Set exact match address i on XMAC */
+-		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
+-		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
+-	}
+-
+-	/* Clear other permanent exact match addresses on XMAC */
+-	if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
+-		
+-		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
+-			SK_ADDR_LAST_MATCH_RLMT);
+-	}
+-
+-	for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
+-		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
+-		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
+-	}
+-
+-	/* Clear other non-permanent exact match addresses on XMAC */
+-	if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
+-		
+-		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
+-			SK_ADDR_LAST_MATCH_DRV);
+-	}
+-
+-	for (Inexact = 0, i = 0; i < 8; i++) {
+-		Inexact |= pAPort->InexactFilter.Bytes[i];
+-	}
+-
+-	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
+-		
+-		/* Set all bits in 64-bit hash register. */
+-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
+-		
+-		/* Enable Hashing */
+-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	}
+-	else if (Inexact != 0) {
+-		
+-		/* Set 64-bit hash register to InexactFilter. */
+-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
+-		
+-		/* Enable Hashing */
+-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	}
+-	else {
+-		/* Disable Hashing */
+-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
+-	}
+-
+-	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
+-		(void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+-	}
+-
+-	/* Set port's current physical MAC address. */
+-	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+-	
+-	XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
+-
+-#ifdef xDEBUG
+-	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
+-		SK_U8		InAddr8[6];
+-		SK_U16		*InAddr;
+-
+-		/* Get exact match address i from port PortNumber. */
+-		InAddr = (SK_U16 *) &InAddr8[0];
+-		
+-		XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
+-		
+-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-			("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
+-			 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
+-				i,
+-				PortNumber,
+-				InAddr8[0],
+-				InAddr8[1],
+-				InAddr8[2],
+-				InAddr8[3],
+-				InAddr8[4],
+-				InAddr8[5],
+-				pAPort->Exact[i].a[0],
+-				pAPort->Exact[i].a[1],
+-				pAPort->Exact[i].a[2],
+-				pAPort->Exact[i].a[3],
+-				pAPort->Exact[i].a[4],
+-				pAPort->Exact[i].a[5]))
+-	}
+-#endif /* DEBUG */
+-
+-	/* Determine return value. */
+-	if (Inexact == 0 && pAPort->PromMode == 0) {
+-		return (SK_MC_FILTERING_EXACT);
+-	}
+-	else {
+-		return (SK_MC_FILTERING_INEXACT);
+-	}
+-	
+-}	/* SkAddrXmacMcUpdate */
+-
+-#endif  /* GENESIS */
+-
+-#ifdef YUKON
+-
+-/******************************************************************************
+- *
+- *	SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
+- *
+- * Description:
+- *	This routine enables reception of the addresses contained in a local
+- *	table for a given port.
+- *	It also programs the port's current physical MAC address.
+- *
+- * Notes:
+- *	The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	SK_MC_FILTERING_EXACT
+- *	SK_MC_FILTERING_INEXACT
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-static int	SkAddrGmacMcUpdate(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* I/O context */
+-SK_U32	PortNumber)	/* Port Number */
+-{
+-#ifndef SK_SLIM
+-	SK_U32		i;
+-	SK_U8		Inexact;
+-#endif	/* not SK_SLIM */
+-	SK_U16		*OutAddr;
+-	SK_ADDR_PORT	*pAPort;
+-
+-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
+-	
+-	pAPort = &pAC->Addr.Port[PortNumber];
+-
+-#ifdef DEBUG
+-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
+-#endif /* DEBUG */
+-	
+-#ifndef SK_SLIM
+-	for (Inexact = 0, i = 0; i < 8; i++) {
+-		Inexact |= pAPort->InexactFilter.Bytes[i];
+-	}
+-	
+-	/* Set 64-bit hash register to InexactFilter. */
+-	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
+-		&pAPort->InexactFilter.Bytes[0]);
+-	
+-	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {				
+-		
+-		/* Set all bits in 64-bit hash register. */
+-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+-		
+-		/* Enable Hashing */
+-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	}
+-	else {	
+-		/* Enable Hashing. */
+-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	}
+-	
+-	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
+-		(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+-	}
+-#else /* SK_SLIM */
+-
+-	/* Set all bits in 64-bit hash register. */
+-	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+-
+-	/* Enable Hashing */
+-	SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	
+-	(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+-	
+-#endif /* SK_SLIM */
+-	
+-	/* Set port's current physical MAC address. */
+-	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+-	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
+-	
+-	/* Set port's current logical MAC address. */
+-	OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
+-	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
+-	
+-#ifdef DEBUG
+-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+-			pAPort->Exact[0].a[0],
+-			pAPort->Exact[0].a[1],
+-			pAPort->Exact[0].a[2],
+-			pAPort->Exact[0].a[3],
+-			pAPort->Exact[0].a[4],
+-			pAPort->Exact[0].a[5]))
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-		("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+-			pAPort->CurrentMacAddress.a[0],
+-			pAPort->CurrentMacAddress.a[1],
+-			pAPort->CurrentMacAddress.a[2],
+-			pAPort->CurrentMacAddress.a[3],
+-			pAPort->CurrentMacAddress.a[4],
+-			pAPort->CurrentMacAddress.a[5]))
+-#endif /* DEBUG */
+-	
+-#ifndef SK_SLIM
+-	/* Determine return value. */
+-	if (Inexact == 0 && pAPort->PromMode == 0) {
+-		return (SK_MC_FILTERING_EXACT);
+-	}
+-	else {
+-		return (SK_MC_FILTERING_INEXACT);
+-	}
+-#else /* SK_SLIM */
+-	return (SK_MC_FILTERING_INEXACT);
+-#endif /* SK_SLIM */
+-	
+-}	/* SkAddrGmacMcUpdate */
+-
+-#endif /* YUKON */
+-
+-#ifndef SK_NO_MAO
+-
+-/******************************************************************************
+- *
+- *	SkAddrOverride - override a port's MAC address
+- *
+- * Description:
+- *	This routine overrides the MAC address of one port.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	SK_ADDR_SUCCESS if successful.
+- *	SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
+- *	SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
+- *	SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
+- */
+-int	SkAddrOverride(
+-SK_AC		*pAC,				/* adapter context */
+-SK_IOC		IoC,				/* I/O context */
+-SK_U32		PortNumber,			/* Port Number */
+-SK_MAC_ADDR	SK_FAR *pNewAddr,	/* new MAC address */
+-int			Flags)				/* logical/physical MAC address */
+-{
+-#ifndef SK_NO_RLMT
+-	SK_EVPARA	Para;
+-#endif /* !SK_NO_RLMT */
+-	SK_U32		NetNumber;
+-	SK_U32		i;
+-	SK_U16		SK_FAR *OutAddr;
+-
+-#ifndef SK_NO_RLMT
+-	NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
+-#else
+-	NetNumber = 0;
+-#endif /* SK_NO_RLMT */
+-#if (!defined(SK_SLIM) || defined(DEBUG))
+-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+-		return (SK_ADDR_ILLEGAL_PORT);
+-	}
+-#endif /* !SK_SLIM || DEBUG */
+-	if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
+-		return (SK_ADDR_MULTICAST_ADDRESS);
+-	}
+-
+-	if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
+-		return (SK_ADDR_TOO_EARLY);
+-	}
+-
+-	if (Flags & SK_ADDR_SET_LOGICAL) {	/* Activate logical MAC address. */
+-		/* Parameter *pNewAddr is ignored. */
+-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+-				return (SK_ADDR_TOO_EARLY);
+-			}
+-		}
+-#ifndef SK_NO_RLMT
+-		/* Set PortNumber to number of net's active port. */
+-		PortNumber = pAC->Rlmt.Net[NetNumber].
+-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
+-#endif /* !SK_NO_RLMT */
+-		pAC->Addr.Port[PortNumber].Exact[0] =
+-			pAC->Addr.Net[NetNumber].CurrentMacAddress;
+-
+-		/* Write address to first exact match entry of active port. */
+-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
+-	}
+-	else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
+-		/* Deactivate logical MAC address. */
+-		/* Parameter *pNewAddr is ignored. */
+-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+-				return (SK_ADDR_TOO_EARLY);
+-			}
+-		}
+-#ifndef SK_NO_RLMT
+-		/* Set PortNumber to number of net's active port. */
+-		PortNumber = pAC->Rlmt.Net[NetNumber].
+-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
+-#endif /* !SK_NO_RLMT */
+-		for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
+-			pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
+-		}
+-
+-		/* Write address to first exact match entry of active port. */
+-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
+-	}
+-	else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) {	/* Physical MAC address. */
+-		if (SK_ADDR_EQUAL(pNewAddr->a,
+-			pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
+-			return (SK_ADDR_DUPLICATE_ADDRESS);
+-		}
+-
+-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+-				return (SK_ADDR_TOO_EARLY);
+-			}
+-
+-			if (SK_ADDR_EQUAL(pNewAddr->a,
+-				pAC->Addr.Port[i].CurrentMacAddress.a)) {
+-				if (i == PortNumber) {
+-					return (SK_ADDR_SUCCESS);
+-				}
+-				else {
+-					return (SK_ADDR_DUPLICATE_ADDRESS);
+-				}
+-			}
+-		}
+-
+-		pAC->Addr.Port[PortNumber].PreviousMacAddress =
+-			pAC->Addr.Port[PortNumber].CurrentMacAddress;
+-		pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
+-
+-		/* Change port's physical MAC address. */
+-		OutAddr = (SK_U16 SK_FAR *) pNewAddr;
+-#ifdef GENESIS
+-		if (pAC->GIni.GIGenesis) {
+-			XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
+-		}
+-#endif /* GENESIS */
+-#ifdef YUKON
+-		if (!pAC->GIni.GIGenesis) {
+-			GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
+-		}
+-#endif /* YUKON */
+-
+-#ifndef SK_NO_RLMT
+-		/* Report address change to RLMT. */
+-		Para.Para32[0] = PortNumber;
+-		Para.Para32[0] = -1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
+-#endif /* !SK_NO_RLMT */
+-	}
+-	else {	/* Logical MAC address. */
+-		if (SK_ADDR_EQUAL(pNewAddr->a,
+-			pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
+-			return (SK_ADDR_SUCCESS);
+-		}
+-		
+-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+-				return (SK_ADDR_TOO_EARLY);
+-			}
+-
+-			if (SK_ADDR_EQUAL(pNewAddr->a,
+-				pAC->Addr.Port[i].CurrentMacAddress.a)) {
+-				return (SK_ADDR_DUPLICATE_ADDRESS);
+-			}
+-		}
+-		
+-		/*
+-		 * In case that the physical and the logical MAC addresses are equal
+-		 * we must also change the physical MAC address here.
+-		 * In this case we have an adapter which initially was programmed with
+-		 * two identical MAC addresses.
+-		 */
+-		if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
+-				pAC->Addr.Port[PortNumber].Exact[0].a)) {
+-			
+-			pAC->Addr.Port[PortNumber].PreviousMacAddress =
+-				pAC->Addr.Port[PortNumber].CurrentMacAddress;
+-			pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
+-			
+-#ifndef SK_NO_RLMT
+-			/* Report address change to RLMT. */
+-			Para.Para32[0] = PortNumber;
+-			Para.Para32[0] = -1;
+-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
+-#endif /* !SK_NO_RLMT */
+-		}
+-		
+-#ifndef SK_NO_RLMT
+-		/* Set PortNumber to number of net's active port. */
+-		PortNumber = pAC->Rlmt.Net[NetNumber].
+-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
+-#endif /* !SK_NO_RLMT */
+-		pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
+-		pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
+-#ifdef DEBUG
+-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-			("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
+-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
+-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
+-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
+-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
+-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
+-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
+-		
+-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+-			("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
+-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
+-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
+-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
+-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
+-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
+-#endif /* DEBUG */
+-
+-        /* Write address to first exact match entry of active port. */
+-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
+-	}
+-
+-	return (SK_ADDR_SUCCESS);
+-	
+-}	/* SkAddrOverride */
+-
+-
+-#endif /* SK_NO_MAO */
+-
+-/******************************************************************************
+- *
+- *	SkAddrPromiscuousChange - set promiscuous mode for given port
+- *
+- * Description:
+- *	This routine manages promiscuous mode:
+- *	- none
+- *	- all LLC frames
+- *	- all MC frames
+- *
+- *	It calls either SkAddrXmacPromiscuousChange or
+- *	SkAddrGmacPromiscuousChange, according to the adapter in use.
+- *	The real work is done there.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	SK_ADDR_SUCCESS
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-int	SkAddrPromiscuousChange(
+-SK_AC	*pAC,			/* adapter context */
+-SK_IOC	IoC,			/* I/O context */
+-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
+-int		NewPromMode)	/* new promiscuous mode */
+-{
+-	int ReturnCode = 0;
+-#if (!defined(SK_SLIM) || defined(DEBUG))
+-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+-		return (SK_ADDR_ILLEGAL_PORT);
+-	}
+-#endif /* !SK_SLIM || DEBUG */
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		ReturnCode =
+-			SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
+-	}
+-#endif /* GENESIS */
+-#ifdef YUKON
+-	if (!pAC->GIni.GIGenesis) {
+-		ReturnCode =
+-			SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
+-	}
+-#endif /* YUKON */
+-
+-	return (ReturnCode);
+-
+-}	/* SkAddrPromiscuousChange */
+-
+-#ifdef GENESIS
+-
+-/******************************************************************************
+- *
+- *	SkAddrXmacPromiscuousChange - set promiscuous mode for given port
+- *
+- * Description:
+- *	This routine manages promiscuous mode:
+- *	- none
+- *	- all LLC frames
+- *	- all MC frames
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	SK_ADDR_SUCCESS
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-static int	SkAddrXmacPromiscuousChange(
+-SK_AC	*pAC,			/* adapter context */
+-SK_IOC	IoC,			/* I/O context */
+-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
+-int		NewPromMode)	/* new promiscuous mode */
+-{
+-	int			i;
+-	SK_BOOL		InexactModeBit;
+-	SK_U8		Inexact;
+-	SK_U8		HwInexact;
+-	SK_FILTER64	HwInexactFilter;
+-	SK_U16		LoMode;		/* Lower 16 bits of XMAC Mode Register. */
+-	int			CurPromMode = SK_PROM_MODE_NONE;
+-
+-	/* Read CurPromMode from Hardware. */
+-	XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
+-
+-	if ((LoMode & XM_MD_ENA_PROM) != 0) {
+-		/* Promiscuous mode! */
+-		CurPromMode |= SK_PROM_MODE_LLC;
+-	}
+-	
+-	for (Inexact = 0xFF, i = 0; i < 8; i++) {
+-		Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+-	}
+-	if (Inexact == 0xFF) {
+-		CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
+-	}
+-	else {
+-		/* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
+-		XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
+-		
+-		InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
+-
+-		/* Read 64-bit hash register from XMAC */
+-		XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
+-
+-		for (HwInexact = 0xFF, i = 0; i < 8; i++) {
+-			HwInexact &= HwInexactFilter.Bytes[i];
+-		}
+-
+-		if (InexactModeBit && (HwInexact == 0xFF)) {
+-			CurPromMode |= SK_PROM_MODE_ALL_MC;
+-		}
+-	}
+-
+-	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
+-
+-	if (NewPromMode == CurPromMode) {
+-		return (SK_ADDR_SUCCESS);
+-	}
+-
+-	if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
+-		!(CurPromMode & SK_PROM_MODE_ALL_MC)) {	/* All MC. */
+-		
+-		/* Set all bits in 64-bit hash register. */
+-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
+-
+-		/* Enable Hashing */
+-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	}
+-	else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
+-		!(NewPromMode & SK_PROM_MODE_ALL_MC)) {	/* Norm MC. */
+-		for (Inexact = 0, i = 0; i < 8; i++) {
+-			Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+-		}
+-		if (Inexact == 0) {
+-			/* Disable Hashing */
+-			SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
+-		}
+-		else {
+-			/* Set 64-bit hash register to InexactFilter. */
+-			XM_OUTHASH(IoC, PortNumber, XM_HSM,
+-				&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
+-
+-			/* Enable Hashing */
+-			SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-		}
+-	}
+-
+-	if ((NewPromMode & SK_PROM_MODE_LLC) &&
+-		!(CurPromMode & SK_PROM_MODE_LLC)) {	/* Prom. LLC */
+-		/* Set the MAC in Promiscuous Mode */
+-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	}
+-	else if ((CurPromMode & SK_PROM_MODE_LLC) &&
+-		!(NewPromMode & SK_PROM_MODE_LLC)) {	/* Norm. LLC. */
+-		/* Clear Promiscuous Mode */
+-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
+-	}
+-	
+-	return (SK_ADDR_SUCCESS);
+-	
+-}	/* SkAddrXmacPromiscuousChange */
+-
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+-
+-/******************************************************************************
+- *
+- *	SkAddrGmacPromiscuousChange - set promiscuous mode for given port
+- *
+- * Description:
+- *	This routine manages promiscuous mode:
+- *	- none
+- *	- all LLC frames
+- *	- all MC frames
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	SK_ADDR_SUCCESS
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-static int	SkAddrGmacPromiscuousChange(
+-SK_AC	*pAC,			/* adapter context */
+-SK_IOC	IoC,			/* I/O context */
+-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
+-int		NewPromMode)	/* new promiscuous mode */
+-{
+-	SK_U16		ReceiveControl;	/* GMAC Receive Control Register */
+-	int		CurPromMode = SK_PROM_MODE_NONE;
+-
+-	/* Read CurPromMode from Hardware. */
+-	GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
+-
+-	if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
+-		/* Promiscuous mode! */
+-		CurPromMode |= SK_PROM_MODE_LLC;
+-	}
+-
+-	if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
+-		/* All Multicast mode! */
+-		CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
+-	}
+-
+-	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
+-
+-	if (NewPromMode == CurPromMode) {
+-		return (SK_ADDR_SUCCESS);
+-	}
+-	
+-	if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
+-		!(CurPromMode & SK_PROM_MODE_ALL_MC)) {	/* All MC */
+-		
+-		/* Set all bits in 64-bit hash register. */
+-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+-		
+-		/* Enable Hashing */
+-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	}
+-	
+-	if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
+-		!(NewPromMode & SK_PROM_MODE_ALL_MC)) {	/* Norm. MC */
+-
+-		/* Set 64-bit hash register to InexactFilter. */
+-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
+-			&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
+-
+-		/* Enable Hashing. */
+-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	}
+-
+-	if ((NewPromMode & SK_PROM_MODE_LLC) &&
+-		!(CurPromMode & SK_PROM_MODE_LLC)) {	/* Prom. LLC */
+-		
+-		/* Set the MAC to Promiscuous Mode. */
+-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
+-	}
+-	else if ((CurPromMode & SK_PROM_MODE_LLC) &&
+-		!(NewPromMode & SK_PROM_MODE_LLC)) {	/* Norm. LLC */
+-		
+-		/* Clear Promiscuous Mode. */
+-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
+-	}
+-
+-	return (SK_ADDR_SUCCESS);
+-	
+-}	/* SkAddrGmacPromiscuousChange */
+-
+-#endif /* YUKON */
+-
+-#ifndef SK_SLIM
+-
+-/******************************************************************************
+- *
+- *	SkAddrSwap - swap address info
+- *
+- * Description:
+- *	This routine swaps address info of two ports.
+- *
+- * Context:
+- *	runtime, pageable
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	SK_ADDR_SUCCESS
+- *	SK_ADDR_ILLEGAL_PORT
+- */
+-int	SkAddrSwap(
+-SK_AC	*pAC,			/* adapter context */
+-SK_IOC	IoC,			/* I/O context */
+-SK_U32	FromPortNumber,		/* Port1 Index */
+-SK_U32	ToPortNumber)		/* Port2 Index */
+-{
+-	int			i;
+-	SK_U8		Byte;
+-	SK_MAC_ADDR	MacAddr;
+-	SK_U32		DWord;
+-
+-	if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+-		return (SK_ADDR_ILLEGAL_PORT);
+-	}
+-
+-	if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+-		return (SK_ADDR_ILLEGAL_PORT);
+-	}
+-
+-	if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
+-		return (SK_ADDR_ILLEGAL_PORT);
+-	}
+-
+-	/*
+-	 * Swap:
+-	 * - Exact Match Entries (GEnesis and Yukon)
+-	 *   Yukon uses first entry for the logical MAC
+-	 *   address (stored in the second GMAC register).
+-	 * - FirstExactMatchRlmt (GEnesis only)
+-	 * - NextExactMatchRlmt (GEnesis only)
+-	 * - FirstExactMatchDrv (GEnesis only)
+-	 * - NextExactMatchDrv (GEnesis only)
+-	 * - 64-bit filter (InexactFilter)
+-	 * - Promiscuous Mode
+-	 * of ports.
+-	 */
+-
+-	for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
+-		MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
+-		pAC->Addr.Port[FromPortNumber].Exact[i] =
+-			pAC->Addr.Port[ToPortNumber].Exact[i];
+-		pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
+-	}
+-
+-	for (i = 0; i < 8; i++) {
+-		Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
+-		pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
+-			pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
+-		pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
+-	}
+-	
+-	i = pAC->Addr.Port[FromPortNumber].PromMode;
+-	pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
+-	pAC->Addr.Port[ToPortNumber].PromMode = i;
+-	
+-	if (pAC->GIni.GIGenesis) {
+-		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
+-		pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
+-			pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
+-		pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
+-		
+-		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
+-		pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
+-			pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
+-		pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
+-		
+-		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
+-		pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
+-			pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
+-		pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
+-		
+-		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
+-		pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
+-			pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
+-		pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
+-	}
+-	
+-	/* CAUTION: Solution works if only ports of one adapter are in use. */
+-	for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
+-		Net->NetNumber].NumPorts; i++) {
+-		if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
+-			Port[i]->PortNumber == ToPortNumber) {
+-			pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
+-				ActivePort = i;
+-			/* 20001207 RA: Was "ToPortNumber;". */
+-		}
+-	}
+-	
+-	(void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
+-	(void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
+-
+-	return (SK_ADDR_SUCCESS);
+-	
+-}	/* SkAddrSwap */
+-
+-#endif /* !SK_SLIM */
+-
+-#ifdef __cplusplus
+-}
+-#endif	/* __cplusplus */
+-
+diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
+deleted file mode 100644
+index 37ce03f..0000000
+--- a/drivers/net/sk98lin/skdim.c
++++ /dev/null
+@@ -1,742 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skdim.c
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.5 $
+- * Date:	$Date: 2003/11/28 12:55:40 $
+- * Purpose:	All functions to maintain interrupt moderation
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This module is intended to manage the dynamic interrupt moderation on both   
+- * GEnesis and Yukon adapters.
+- *
+- * Include File Hierarchy:
+- *
+- *	"skdrv1st.h"
+- *	"skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef	lint
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect.";
+-#endif
+-
+-#define __SKADDR_C
+-
+-#ifdef __cplusplus
+-#error C++ is not yet supported.
+-extern "C" {
+-#endif
+-
+-/*******************************************************************************
+-**
+-** Includes
+-**
+-*******************************************************************************/
+-
+-#ifndef __INC_SKDRV1ST_H
+-#include "h/skdrv1st.h"
+-#endif
+-
+-#ifndef __INC_SKDRV2ND_H
+-#include "h/skdrv2nd.h"
+-#endif
+-
+-#include	<linux/kernel_stat.h>
+-
+-/*******************************************************************************
+-**
+-** Defines
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-**
+-** Typedefs
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-**
+-** Local function prototypes 
+-**
+-*******************************************************************************/
+-
+-static unsigned int GetCurrentSystemLoad(SK_AC *pAC);
+-static SK_U64       GetIsrCalls(SK_AC *pAC);
+-static SK_BOOL      IsIntModEnabled(SK_AC *pAC);
+-static void         SetCurrIntCtr(SK_AC *pAC);
+-static void         EnableIntMod(SK_AC *pAC); 
+-static void         DisableIntMod(SK_AC *pAC);
+-static void         ResizeDimTimerDuration(SK_AC *pAC);
+-static void         DisplaySelectedModerationType(SK_AC *pAC);
+-static void         DisplaySelectedModerationMask(SK_AC *pAC);
+-static void         DisplayDescrRatio(SK_AC *pAC);
+-
+-/*******************************************************************************
+-**
+-** Global variables
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-**
+-** Local variables
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-**
+-** Global functions 
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-** Function     : SkDimModerate
+-** Description  : Called in every ISR to check if moderation is to be applied
+-**                or not for the current number of interrupts
+-** Programmer   : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns      : void (!)
+-** Notes        : -
+-*******************************************************************************/
+-
+-void 
+-SkDimModerate(SK_AC *pAC) {
+-    unsigned int CurrSysLoad    = 0;  /* expressed in percent */
+-    unsigned int LoadIncrease   = 0;  /* expressed in percent */
+-    SK_U64       ThresholdInts  = 0;
+-    SK_U64       IsrCallsPerSec = 0;
+-
+-#define M_DIMINFO pAC->DynIrqModInfo
+-
+-    if (!IsIntModEnabled(pAC)) {
+-        if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+-            CurrSysLoad = GetCurrentSystemLoad(pAC);
+-            if (CurrSysLoad > 75) {
+-                    /* 
+-                    ** More than 75% total system load! Enable the moderation 
+-                    ** to shield the system against too many interrupts.
+-                    */
+-                    EnableIntMod(pAC);
+-            } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) {
+-                LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad);
+-                if (LoadIncrease > ((M_DIMINFO.PrevSysLoad *
+-                                         C_INT_MOD_ENABLE_PERCENTAGE) / 100)) {
+-                    if (CurrSysLoad > 10) {
+-                        /* 
+-                        ** More than 50% increase with respect to the 
+-                        ** previous load of the system. Most likely this 
+-                        ** is due to our ISR-proc...
+-                        */
+-                        EnableIntMod(pAC);
+-                    }
+-                }
+-            } else {
+-                /*
+-                ** Neither too much system load at all nor too much increase
+-                ** with respect to the previous system load. Hence, we can leave
+-                ** the ISR-handling like it is without enabling moderation.
+-                */
+-            }
+-            M_DIMINFO.PrevSysLoad = CurrSysLoad;
+-        }   
+-    } else {
+-        if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+-            ThresholdInts  = ((M_DIMINFO.MaxModIntsPerSec *
+-                                   C_INT_MOD_DISABLE_PERCENTAGE) / 100);
+-            IsrCallsPerSec = GetIsrCalls(pAC);
+-            if (IsrCallsPerSec <= ThresholdInts) {
+-                /* 
+-                ** The number of interrupts within the last second is 
+-                ** lower than the disable_percentage of the desried 
+-                ** maxrate. Therefore we can disable the moderation.
+-                */
+-                DisableIntMod(pAC);
+-                M_DIMINFO.MaxModIntsPerSec = 
+-                   (M_DIMINFO.MaxModIntsPerSecUpperLimit +
+-                    M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2;
+-            } else {
+-                /*
+-                ** The number of interrupts per sec is the same as expected.
+-                ** Evalulate the descriptor-ratio. If it has changed, a resize 
+-                ** in the moderation timer might be useful
+-                */
+-                if (M_DIMINFO.AutoSizing) {
+-                    ResizeDimTimerDuration(pAC);
+-                }
+-            }
+-        }
+-    }
+-
+-    /*
+-    ** Some information to the log...
+-    */
+-    if (M_DIMINFO.DisplayStats) {
+-        DisplaySelectedModerationType(pAC);
+-        DisplaySelectedModerationMask(pAC);
+-        DisplayDescrRatio(pAC);
+-    }
+-
+-    M_DIMINFO.NbrProcessedDescr = 0; 
+-    SetCurrIntCtr(pAC);
+-}
+-
+-/*******************************************************************************
+-** Function     : SkDimStartModerationTimer
+-** Description  : Starts the audit-timer for the dynamic interrupt moderation
+-** Programmer   : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns      : void (!)
+-** Notes        : -
+-*******************************************************************************/
+-
+-void 
+-SkDimStartModerationTimer(SK_AC *pAC) {
+-    SK_EVPARA    EventParam;   /* Event struct for timer event */
+- 
+-    SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
+-    EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
+-    SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer,
+-                 SK_DRV_MODERATION_TIMER_LENGTH,
+-                 SKGE_DRV, SK_DRV_TIMER, EventParam);
+-}
+-
+-/*******************************************************************************
+-** Function     : SkDimEnableModerationIfNeeded
+-** Description  : Either enables or disables moderation
+-** Programmer   : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns      : void (!)
+-** Notes        : This function is called when a particular adapter is opened
+-**                There is no Disable function, because when all interrupts 
+-**                might be disable, the moderation timer has no meaning at all
+-******************************************************************************/
+-
+-void
+-SkDimEnableModerationIfNeeded(SK_AC *pAC) {
+-
+-    if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
+-        EnableIntMod(pAC);   /* notification print in this function */
+-    } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+-        SkDimStartModerationTimer(pAC);
+-        if (M_DIMINFO.DisplayStats) {
+-            printk("Dynamic moderation has been enabled\n");
+-        }
+-    } else {
+-        if (M_DIMINFO.DisplayStats) {
+-            printk("No moderation has been enabled\n");
+-        }
+-    }
+-}
+-
+-/*******************************************************************************
+-** Function     : SkDimDisplayModerationSettings
+-** Description  : Displays the current settings regarding interrupt moderation
+-** Programmer   : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns      : void (!)
+-** Notes        : -
+-*******************************************************************************/
+-
+-void 
+-SkDimDisplayModerationSettings(SK_AC *pAC) {
+-    DisplaySelectedModerationType(pAC);
+-    DisplaySelectedModerationMask(pAC);
+-}
+-
+-/*******************************************************************************
+-**
+-** Local functions 
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-** Function     : GetCurrentSystemLoad
+-** Description  : Retrieves the current system load of the system. This load
+-**                is evaluated for all processors within the system.
+-** Programmer   : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns      : unsigned int: load expressed in percentage
+-** Notes        : The possible range being returned is from 0 up to 100.
+-**                Whereas 0 means 'no load at all' and 100 'system fully loaded'
+-**                It is impossible to determine what actually causes the system
+-**                to be in 100%, but maybe that is due to too much interrupts.
+-*******************************************************************************/
+-
+-static unsigned int
+-GetCurrentSystemLoad(SK_AC *pAC) {
+-	unsigned long jif         = jiffies;
+-	unsigned int  UserTime    = 0;
+-	unsigned int  SystemTime  = 0;
+-	unsigned int  NiceTime    = 0;
+-	unsigned int  IdleTime    = 0;
+-	unsigned int  TotalTime   = 0;
+-	unsigned int  UsedTime    = 0;
+-	unsigned int  SystemLoad  = 0;
+-
+-	/* unsigned int  NbrCpu      = 0; */
+-
+-	/*
+-	** The following lines have been commented out, because
+-	** from kernel 2.5.44 onwards, the kernel-owned structure
+-	**
+-	**      struct kernel_stat kstat
+-	**
+-	** is not marked as an exported symbol in the file
+-	**
+-	**      kernel/ksyms.c 
+-	**
+-	** As a consequence, using this driver as KLM is not possible
+-	** and any access of the structure kernel_stat via the 
+-	** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided.
+-	**
+-	** The kstat-information might be added again in future 
+-	** versions of the 2.5.xx kernel, but for the time being, 
+-	** number of interrupts will serve as indication how much 
+-	** load we currently have... 
+-	**
+-	** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) {
+-	**	UserTime   = UserTime   + kstat_cpu(NbrCpu).cpustat.user;
+-	**	NiceTime   = NiceTime   + kstat_cpu(NbrCpu).cpustat.nice;
+-	**	SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system;
+-	** }
+-	*/
+-	SK_U64 ThresholdInts  = 0;
+-	SK_U64 IsrCallsPerSec = 0;
+-
+-	ThresholdInts  = ((M_DIMINFO.MaxModIntsPerSec *
+-			   C_INT_MOD_ENABLE_PERCENTAGE) + 100);
+-	IsrCallsPerSec = GetIsrCalls(pAC);
+-	if (IsrCallsPerSec >= ThresholdInts) {
+-	    /*
+-	    ** We do not know how much the real CPU-load is!
+-	    ** Return 80% as a default in order to activate DIM
+-	    */
+-	    SystemLoad = 80;
+-	    return (SystemLoad);  
+-	} 
+-
+-	UsedTime  = UserTime + NiceTime + SystemTime;
+-
+-	IdleTime  = jif * num_online_cpus() - UsedTime;
+-	TotalTime = UsedTime + IdleTime;
+-
+-	SystemLoad = ( 100 * (UsedTime  - M_DIMINFO.PrevUsedTime) ) /
+-						(TotalTime - M_DIMINFO.PrevTotalTime);
+-
+-	if (M_DIMINFO.DisplayStats) {
+-		printk("Current system load is: %u\n", SystemLoad);
+-	}
+-
+-	M_DIMINFO.PrevTotalTime = TotalTime;
+-	M_DIMINFO.PrevUsedTime  = UsedTime;
+-
+-	return (SystemLoad);
+-}
+-
+-/*******************************************************************************
+-** Function     : GetIsrCalls
+-** Description  : Depending on the selected moderation mask, this function will
+-**                return the number of interrupts handled in the previous time-
+-**                frame. This evaluated number is based on the current number 
+-**                of interrupts stored in PNMI-context and the previous stored 
+-**                interrupts.
+-** Programmer   : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns      : int:   the number of interrupts being executed in the last
+-**                       timeframe
+-** Notes        : It makes only sense to call this function, when dynamic 
+-**                interrupt moderation is applied
+-*******************************************************************************/
+-
+-static SK_U64
+-GetIsrCalls(SK_AC *pAC) {
+-    SK_U64   RxPort0IntDiff = 0;
+-    SK_U64   RxPort1IntDiff = 0;
+-    SK_U64   TxPort0IntDiff = 0;
+-    SK_U64   TxPort1IntDiff = 0;
+-
+-    if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) {
+-        if (pAC->GIni.GIMacsFound == 2) {
+-            TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - 
+-                             pAC->DynIrqModInfo.PrevPort1TxIntrCts;
+-        }
+-        TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
+-                         pAC->DynIrqModInfo.PrevPort0TxIntrCts;
+-    } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) {
+-        if (pAC->GIni.GIMacsFound == 2) {
+-            RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
+-                             pAC->DynIrqModInfo.PrevPort1RxIntrCts;
+-        }
+-        RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
+-                         pAC->DynIrqModInfo.PrevPort0RxIntrCts;
+-    } else {
+-        if (pAC->GIni.GIMacsFound == 2) {
+-            RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
+-                             pAC->DynIrqModInfo.PrevPort1RxIntrCts;
+-            TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - 
+-                             pAC->DynIrqModInfo.PrevPort1TxIntrCts;
+-        } 
+-        RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
+-                         pAC->DynIrqModInfo.PrevPort0RxIntrCts;
+-        TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
+-                         pAC->DynIrqModInfo.PrevPort0TxIntrCts;
+-    }
+-
+-    return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff);
+-}
+-
+-/*******************************************************************************
+-** Function     : GetRxCalls
+-** Description  : This function will return the number of times a receive inter-
+-**                rupt was processed. This is needed to evaluate any resizing 
+-**                factor.
+-** Programmer   : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns      : SK_U64: the number of RX-ints being processed
+-** Notes        : It makes only sense to call this function, when dynamic 
+-**                interrupt moderation is applied
+-*******************************************************************************/
+-
+-static SK_U64
+-GetRxCalls(SK_AC *pAC) {
+-    SK_U64   RxPort0IntDiff = 0;
+-    SK_U64   RxPort1IntDiff = 0;
+-
+-    if (pAC->GIni.GIMacsFound == 2) {
+-        RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
+-                         pAC->DynIrqModInfo.PrevPort1RxIntrCts;
+-    }
+-    RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
+-                     pAC->DynIrqModInfo.PrevPort0RxIntrCts;
+-
+-    return (RxPort0IntDiff + RxPort1IntDiff);
+-}
+-
+-/*******************************************************************************
+-** Function     : SetCurrIntCtr
+-** Description  : Will store the current number orf occured interrupts in the 
+-**                adapter context. This is needed to evaluated the number of 
+-**                interrupts within a current timeframe.
+-** Programmer   : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns      : void (!)
+-** Notes        : -
+-*******************************************************************************/
+-
+-static void
+-SetCurrIntCtr(SK_AC *pAC) {
+-    if (pAC->GIni.GIMacsFound == 2) {
+-        pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
+-        pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
+-    } 
+-    pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
+-    pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
+-}
+-
+-/*******************************************************************************
+-** Function     : IsIntModEnabled()
+-** Description  : Retrieves the current value of the interrupts moderation
+-**                command register. Its content determines whether any 
+-**                moderation is running or not.
+-** Programmer   : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns      : SK_TRUE  : if mod timer running
+-**                SK_FALSE : if no moderation is being performed
+-** Notes        : -
+-*******************************************************************************/
+-
+-static SK_BOOL
+-IsIntModEnabled(SK_AC *pAC) {
+-    unsigned long CtrCmd;
+-
+-    SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
+-    if ((CtrCmd & TIM_START) == TIM_START) {
+-       return SK_TRUE;
+-    } else {
+-       return SK_FALSE;
+-    }
+-}
+-
+-/*******************************************************************************
+-** Function     : EnableIntMod()
+-** Description  : Enables the interrupt moderation using the values stored in
+-**                in the pAC->DynIntMod data structure
+-** Programmer   : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns      : -
+-** Notes        : -
+-*******************************************************************************/
+-
+-static void
+-EnableIntMod(SK_AC *pAC) {
+-    unsigned long ModBase;
+-
+-    if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+-       ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
+-    } else {
+-       ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
+-    }
+-
+-    SK_OUT32(pAC->IoBase, B2_IRQM_INI,  ModBase);
+-    SK_OUT32(pAC->IoBase, B2_IRQM_MSK,  pAC->DynIrqModInfo.MaskIrqModeration);
+-    SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
+-    if (M_DIMINFO.DisplayStats) {
+-        printk("Enabled interrupt moderation (%i ints/sec)\n",
+-               M_DIMINFO.MaxModIntsPerSec);
+-    }
+-}
+-
+-/*******************************************************************************
+-** Function     : DisableIntMod()
+-** Description  : Disables the interrupt moderation independent of what inter-
+-**                rupts are running or not
+-** Programmer   : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns      : -
+-** Notes        : -
+-*******************************************************************************/
+-
+-static void 
+-DisableIntMod(SK_AC *pAC) {
+-
+-    SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
+-    if (M_DIMINFO.DisplayStats) {
+-        printk("Disabled interrupt moderation\n");
+-    }
+-} 
+-
+-/*******************************************************************************
+-** Function     : ResizeDimTimerDuration();
+-** Description  : Checks the current used descriptor ratio and resizes the 
+-**                duration timer (longer/smaller) if possible. 
+-** Programmer   : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns      : -
+-** Notes        : There are both maximum and minimum timer duration value. 
+-**                This function assumes that interrupt moderation is already
+-**                enabled!
+-*******************************************************************************/
+-
+-static void 
+-ResizeDimTimerDuration(SK_AC *pAC) {
+-    SK_BOOL IncreaseTimerDuration;
+-    int     TotalMaxNbrDescr;
+-    int     UsedDescrRatio;
+-    int     RatioDiffAbs;
+-    int     RatioDiffRel;
+-    int     NewMaxModIntsPerSec;
+-    int     ModAdjValue;
+-    long    ModBase;
+-
+-    /*
+-    ** Check first if we are allowed to perform any modification
+-    */
+-    if (IsIntModEnabled(pAC)) { 
+-        if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) {
+-            return; 
+-        } else {
+-            if (M_DIMINFO.ModJustEnabled) {
+-                M_DIMINFO.ModJustEnabled = SK_FALSE;
+-                return;
+-            }
+-        }
+-    }
+-
+-    /*
+-    ** If we got until here, we have to evaluate the amount of the
+-    ** descriptor ratio change...
+-    */
+-    TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
+-    UsedDescrRatio   = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr;
+-
+-    if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) {
+-        RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio);
+-        RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio;
+-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
+-        IncreaseTimerDuration = SK_FALSE;  /* in other words: DECREASE */
+-    } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) {
+-        RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
+-        RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
+-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
+-        IncreaseTimerDuration = SK_TRUE;   /* in other words: INCREASE */
+-    } else {
+-        RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
+-        RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
+-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
+-        IncreaseTimerDuration = SK_TRUE;   /* in other words: INCREASE */
+-    }
+-
+-    /*
+-    ** Now we can determine the change in percent
+-    */
+-    if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) {
+-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
+-    } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) {
+-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
+-    } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) {
+-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
+-    } else {
+-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
+-    }
+-
+-    if (IncreaseTimerDuration) {
+-       NewMaxModIntsPerSec =  M_DIMINFO.MaxModIntsPerSec +
+-                             (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
+-    } else {
+-       NewMaxModIntsPerSec =  M_DIMINFO.MaxModIntsPerSec -
+-                             (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
+-    }
+-
+-    /* 
+-    ** Check if we exceed boundaries...
+-    */
+-    if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) ||
+-         (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) {
+-        if (M_DIMINFO.DisplayStats) {
+-            printk("Cannot change ModTim from %i to %i ints/sec\n",
+-                   M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
+-        }
+-        return;
+-    } else {
+-        if (M_DIMINFO.DisplayStats) {
+-            printk("Resized ModTim from %i to %i ints/sec\n",
+-                   M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
+-        }
+-    }
+-
+-    M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec;
+-
+-    if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+-        ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
+-    } else {
+-        ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
+-    }
+-
+-    /* 
+-    ** We do not need to touch any other registers
+-    */
+-    SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
+-} 
+-
+-/*******************************************************************************
+-** Function     : DisplaySelectedModerationType()
+-** Description  : Displays what type of moderation we have
+-** Programmer   : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns      : void!
+-** Notes        : -
+-*******************************************************************************/
+-
+-static void
+-DisplaySelectedModerationType(SK_AC *pAC) {
+-
+-    if (pAC->DynIrqModInfo.DisplayStats) {
+-        if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
+-             printk("Static int moderation runs with %i INTS/sec\n",
+-                    pAC->DynIrqModInfo.MaxModIntsPerSec);
+-        } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+-             if (IsIntModEnabled(pAC)) {
+-                printk("Dynamic int moderation runs with %i INTS/sec\n",
+-                       pAC->DynIrqModInfo.MaxModIntsPerSec);
+-             } else {
+-                printk("Dynamic int moderation currently not applied\n");
+-             }
+-        } else {
+-             printk("No interrupt moderation selected!\n");
+-        }
+-    }
+-}
+-
+-/*******************************************************************************
+-** Function     : DisplaySelectedModerationMask()
+-** Description  : Displays what interrupts are moderated
+-** Programmer   : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns      : void!
+-** Notes        : -
+-*******************************************************************************/
+-
+-static void
+-DisplaySelectedModerationMask(SK_AC *pAC) {
+-
+-    if (pAC->DynIrqModInfo.DisplayStats) {
+-        if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) {
+-            switch (pAC->DynIrqModInfo.MaskIrqModeration) {
+-                case IRQ_MASK_TX_ONLY: 
+-                   printk("Only Tx-interrupts are moderated\n");
+-                   break;
+-                case IRQ_MASK_RX_ONLY: 
+-                   printk("Only Rx-interrupts are moderated\n");
+-                   break;
+-                case IRQ_MASK_SP_ONLY: 
+-                   printk("Only special-interrupts are moderated\n");
+-                   break;
+-                case IRQ_MASK_TX_RX: 
+-                   printk("Tx- and Rx-interrupts are moderated\n");
+-                   break;
+-                case IRQ_MASK_SP_RX: 
+-                   printk("Special- and Rx-interrupts are moderated\n");
+-                   break;
+-                case IRQ_MASK_SP_TX: 
+-                   printk("Special- and Tx-interrupts are moderated\n");
+-                   break;
+-                case IRQ_MASK_RX_TX_SP:
+-                   printk("All Rx-, Tx and special-interrupts are moderated\n");
+-                   break;
+-                default:
+-                   printk("Don't know what is moderated\n");
+-                   break;
+-            }
+-        } else {
+-            printk("No specific interrupts masked for moderation\n");
+-        }
+-    } 
+-}
+-
+-/*******************************************************************************
+-** Function     : DisplayDescrRatio
+-** Description  : Like the name states...
+-** Programmer   : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns      : void!
+-** Notes        : -
+-*******************************************************************************/
+-
+-static void
+-DisplayDescrRatio(SK_AC *pAC) {
+-    int TotalMaxNbrDescr = 0;
+-
+-    if (pAC->DynIrqModInfo.DisplayStats) {
+-        TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
+-        printk("Ratio descriptors: %i/%i\n",
+-               M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr);
+-    }
+-}
+-
+-/*******************************************************************************
+-**
+-** End of file
+-**
+-*******************************************************************************/
+diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
+deleted file mode 100644
+index 5a6da89..0000000
+--- a/drivers/net/sk98lin/skethtool.c
++++ /dev/null
+@@ -1,627 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:        skethtool.c
+- * Project:     GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:     $Revision: 1.7 $
+- * Date:        $Date: 2004/09/29 13:32:07 $
+- * Purpose:     All functions regarding ethtool handling
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2004 Marvell.
+- *
+- *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet 
+- *      Server Adapters.
+- *
+- *	Author: Ralph Roesler (rroesler at syskonnect.de)
+- *	        Mirko Lindner (mlindner at syskonnect.de)
+- *
+- *	Address all question to: linux at syskonnect.de
+- *
+- *	The technical manual for the adapters is available from SysKonnect's
+- *	web pages: www.syskonnect.com
+- *	
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- *****************************************************************************/
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-#include "h/skversion.h"
+-
+-#include <linux/ethtool.h>
+-#include <linux/timer.h>
+-#include <linux/delay.h>
+-
+-/******************************************************************************
+- *
+- * Defines
+- *
+- *****************************************************************************/
+-
+-#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half  | SUPPORTED_10baseT_Full  | \
+-                         SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
+-                         SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
+-                         SUPPORTED_TP)
+-
+-#define ADV_COPPER_ALL  (ADVERTISED_10baseT_Half  | ADVERTISED_10baseT_Full  | \
+-                         ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+-                         ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
+-                         ADVERTISED_TP)
+-
+-#define SUPP_FIBRE_ALL  (SUPPORTED_1000baseT_Full | \
+-                         SUPPORTED_FIBRE          | \
+-                         SUPPORTED_Autoneg)
+-
+-#define ADV_FIBRE_ALL   (ADVERTISED_1000baseT_Full | \
+-                         ADVERTISED_FIBRE          | \
+-                         ADVERTISED_Autoneg)
+-
+-
+-/******************************************************************************
+- *
+- * Local Functions
+- *
+- *****************************************************************************/
+-
+-/*****************************************************************************
+- *
+- * 	getSettings - retrieves the current settings of the selected adapter
+- *
+- * Description:
+- *	The current configuration of the selected adapter is returned.
+- *	This configuration involves a)speed, b)duplex and c)autoneg plus
+- *	a number of other variables.
+- *
+- * Returns:    always 0
+- *
+- */
+-static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
+-{
+-	const DEV_NET *pNet = netdev_priv(dev);
+-	int port = pNet->PortNr;
+-	const SK_AC *pAC = pNet->pAC;
+-	const SK_GEPORT *pPort = &pAC->GIni.GP[port];
+-
+-	static int DuplexAutoNegConfMap[9][3]= {
+-		{ -1                     , -1         , -1              },
+-		{ 0                      , -1         , -1              },
+-		{ SK_LMODE_HALF          , DUPLEX_HALF, AUTONEG_DISABLE },
+-		{ SK_LMODE_FULL          , DUPLEX_FULL, AUTONEG_DISABLE },
+-		{ SK_LMODE_AUTOHALF      , DUPLEX_HALF, AUTONEG_ENABLE  },
+-		{ SK_LMODE_AUTOFULL      , DUPLEX_FULL, AUTONEG_ENABLE  },
+-		{ SK_LMODE_AUTOBOTH      , DUPLEX_FULL, AUTONEG_ENABLE  },
+-		{ SK_LMODE_AUTOSENSE     , -1         , -1              },
+-		{ SK_LMODE_INDETERMINATED, -1         , -1              }
+-	};
+-	static int SpeedConfMap[6][2] = {
+-		{ 0                       , -1         },
+-		{ SK_LSPEED_AUTO          , -1         },
+-		{ SK_LSPEED_10MBPS        , SPEED_10   },
+-		{ SK_LSPEED_100MBPS       , SPEED_100  },
+-		{ SK_LSPEED_1000MBPS      , SPEED_1000 },
+-		{ SK_LSPEED_INDETERMINATED, -1         }
+-	};
+-	static int AdvSpeedMap[6][2] = {
+-		{ 0                       , -1         },
+-		{ SK_LSPEED_AUTO          , -1         },
+-		{ SK_LSPEED_10MBPS        , ADVERTISED_10baseT_Half   | ADVERTISED_10baseT_Full },
+-		{ SK_LSPEED_100MBPS       , ADVERTISED_100baseT_Half  | ADVERTISED_100baseT_Full },
+-		{ SK_LSPEED_1000MBPS      , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
+-		{ SK_LSPEED_INDETERMINATED, -1         }
+-	};
+-
+-	ecmd->phy_address = port;
+-	ecmd->speed       = SpeedConfMap[pPort->PLinkSpeedUsed][1];
+-	ecmd->duplex      = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
+-	ecmd->autoneg     = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
+-	ecmd->transceiver = XCVR_INTERNAL;
+-
+-	if (pAC->GIni.GICopperType) {
+-		ecmd->port        = PORT_TP;
+-		ecmd->supported   = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
+-		if (pAC->GIni.GIGenesis) {
+-			ecmd->supported &= ~(SUPPORTED_10baseT_Half);
+-			ecmd->supported &= ~(SUPPORTED_10baseT_Full);
+-			ecmd->supported &= ~(SUPPORTED_100baseT_Half);
+-			ecmd->supported &= ~(SUPPORTED_100baseT_Full);
+-		} else {
+-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+-				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
+-			} 
+-#ifdef CHIP_ID_YUKON_FE
+-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
+-				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
+-				ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
+-			}
+-#endif
+-		}
+-		if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
+-			ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
+-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+-				ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
+-			} 
+-		} else {
+-			ecmd->advertising = ecmd->supported;
+-		}
+-
+-		if (ecmd->autoneg == AUTONEG_ENABLE) 
+-			ecmd->advertising |= ADVERTISED_Autoneg;
+-	} else {
+-		ecmd->port        = PORT_FIBRE;
+-		ecmd->supported   = SUPP_FIBRE_ALL;
+-		ecmd->advertising = ADV_FIBRE_ALL;
+-	}
+-	return 0;
+-}
+-
+-/*
+- * MIB infrastructure uses instance value starting at 1
+- * based on board and port.
+- */
+-static inline u32 pnmiInstance(const DEV_NET *pNet)
+-{
+-	return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr;
+-}
+-
+-/*****************************************************************************
+- *
+- *	setSettings - configures the settings of a selected adapter
+- *
+- * Description:
+- *	Possible settings that may be altered are a)speed, b)duplex or 
+- *	c)autonegotiation.
+- *
+- * Returns:
+- *	0:	everything fine, no error
+- *	<0:	the return value is the error code of the failure 
+- */
+-static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
+-{
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-	u32 instance;
+-	char buf[4];
+-	int len = 1;
+-
+-	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100 
+-	    && ecmd->speed != SPEED_1000)
+-		return -EINVAL;
+-
+-	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
+-		return -EINVAL;
+-
+-	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
+-		return -EINVAL;
+-
+-	if (ecmd->autoneg == AUTONEG_DISABLE)
+-		*buf = (ecmd->duplex == DUPLEX_FULL) 
+-			? SK_LMODE_FULL : SK_LMODE_HALF;
+-	else
+-		*buf = (ecmd->duplex == DUPLEX_FULL) 
+-			? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF;
+-	
+-	instance = pnmiInstance(pNet);
+-	if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, 
+-			   &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
+-		return -EINVAL;
+-
+-	switch(ecmd->speed) {
+-	case SPEED_1000:
+-		*buf = SK_LSPEED_1000MBPS;
+-		break;
+-	case SPEED_100:
+-		*buf = SK_LSPEED_100MBPS;
+-		break;
+-	case SPEED_10:
+-		*buf = SK_LSPEED_10MBPS;
+-	}
+-
+-	if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
+-			 &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
+-		return -EINVAL;
+-
+-	return 0;
+-}
+-
+-/*****************************************************************************
+- *
+- * 	getDriverInfo - returns generic driver and adapter information
+- *
+- * Description:
+- *	Generic driver information is returned via this function, such as
+- *	the name of the driver, its version and and firmware version.
+- *	In addition to this, the location of the selected adapter is 
+- *	returned as a bus info string (e.g. '01:05.0').
+- *	
+- * Returns:	N/A
+- *
+- */
+-static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info)
+-{
+-	const DEV_NET	*pNet = netdev_priv(dev);
+-	const SK_AC *pAC = pNet->pAC;
+-	char vers[32];
+-
+-	snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)",
+-		(pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf);
+-
+-	strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
+-	strcpy(info->version, vers);
+-	strcpy(info->fw_version, "N/A");
+-	strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
+-}
+-
+-/*
+- * Ethtool statistics support.
+- */
+-static const char StringsStats[][ETH_GSTRING_LEN] = {
+-	"rx_packets",	"tx_packets",
+-	"rx_bytes",	"tx_bytes",
+-	"rx_errors",	"tx_errors",	
+-	"rx_dropped",	"tx_dropped",
+-	"multicasts",	"collisions",	
+-	"rx_length_errors",		"rx_buffer_overflow_errors",
+-	"rx_crc_errors",		"rx_frame_errors",
+-	"rx_too_short_errors",		"rx_too_long_errors",
+-	"rx_carrier_extension_errors",	"rx_symbol_errors",
+-	"rx_llc_mac_size_errors",	"rx_carrier_errors",	
+-	"rx_jabber_errors",		"rx_missed_errors",
+-	"tx_abort_collision_errors",	"tx_carrier_errors",
+-	"tx_buffer_underrun_errors",	"tx_heartbeat_errors",
+-	"tx_window_errors",
+-};
+-
+-static int getStatsCount(struct net_device *dev)
+-{
+-	return ARRAY_SIZE(StringsStats);
+-}
+-
+-static void getStrings(struct net_device *dev, u32 stringset, u8 *data)
+-{
+-	switch(stringset) {
+-	case ETH_SS_STATS:
+-		memcpy(data, *StringsStats, sizeof(StringsStats));
+-		break;
+-	}
+-}
+-
+-static void getEthtoolStats(struct net_device *dev,
+-			    struct ethtool_stats *stats, u64 *data)
+-{
+-	const DEV_NET	*pNet = netdev_priv(dev);
+-	const SK_AC *pAC = pNet->pAC;
+-	const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
+-
+-	*data++ = pPnmiStruct->Stat[0].StatRxOkCts;
+-	*data++ = pPnmiStruct->Stat[0].StatTxOkCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts;
+-	*data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts;
+-	*data++ = pPnmiStruct->InErrorsCts;
+-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
+-	*data++ = pPnmiStruct->RxNoBufCts;
+-	*data++ = pPnmiStruct->TxNoBufCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts;
+-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxRuntCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxFcsCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxFramingCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxShortsCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxTooLongCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxCextCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxSymbolCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxCarrierCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxJabberCts;
+-	*data++ = pPnmiStruct->Stat[0].StatRxMissedCts;
+-	*data++ = pAC->stats.tx_aborted_errors;
+-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
+-	*data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts;
+-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
+-	*data++ = pAC->stats.tx_window_errors;
+-}
+-
+-
+-/*****************************************************************************
+- *
+- * 	toggleLeds - Changes the LED state of an adapter
+- *
+- * Description:
+- *	This function changes the current state of all LEDs of an adapter so
+- *	that it can be located by a user. 
+- *
+- * Returns:	N/A
+- *
+- */
+-static void toggleLeds(DEV_NET *pNet, int on)
+-{
+-	SK_AC *pAC = pNet->pAC;
+-	int port = pNet->PortNr;
+-	void __iomem *io = pAC->IoBase;
+-
+-	if (pAC->GIni.GIGenesis) {
+-		SK_OUT8(io, MR_ADDR(port,LNK_LED_REG), 
+-			on ? SK_LNK_ON : SK_LNK_OFF);
+-		SkGeYellowLED(pAC, io, 
+-			      on ? (LED_ON >> 1) : (LED_OFF >> 1));
+-		SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI),
+-			    on ? SK_LED_TST : SK_LED_DIS);
+-
+-		if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM)
+-			SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL, 
+-				     on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF);
+-		else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE)
+-			SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG,
+-				     on ? 0x0800 : PHY_L_LC_LEDT);
+-		else
+-			SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI),
+-				    on ? SK_LED_TST : SK_LED_DIS);
+-	} else {
+-		const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON)  |
+-				      PHY_M_LED_MO_10(MO_LED_ON)   |
+-				      PHY_M_LED_MO_100(MO_LED_ON)  |
+-				      PHY_M_LED_MO_1000(MO_LED_ON) | 
+-				      PHY_M_LED_MO_RX(MO_LED_ON));
+-		const u16  YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF)  |
+-					PHY_M_LED_MO_10(MO_LED_OFF)   |
+-					PHY_M_LED_MO_100(MO_LED_OFF)  |
+-					PHY_M_LED_MO_1000(MO_LED_OFF) | 
+-					PHY_M_LED_MO_RX(MO_LED_OFF));
+-	
+-
+-		SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0);
+-		SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER, 
+-			     on ? YukLedOn : YukLedOff);
+-	}
+-}
+-
+-/*****************************************************************************
+- *
+- * 	skGeBlinkTimer - Changes the LED state of an adapter
+- *
+- * Description:
+- *	This function changes the current state of all LEDs of an adapter so
+- *	that it can be located by a user. If the requested time interval for
+- *	this test has elapsed, this function cleans up everything that was 
+- *	temporarily setup during the locate NIC test. This involves of course
+- *	also closing or opening any adapter so that the initial board state 
+- *	is recovered.
+- *
+- * Returns:	N/A
+- *
+- */
+-void SkGeBlinkTimer(unsigned long data)
+-{
+-	struct net_device *dev = (struct net_device *) data;
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-
+-	toggleLeds(pNet, pAC->LedsOn);
+-
+-	pAC->LedsOn = !pAC->LedsOn;
+-	mod_timer(&pAC->BlinkTimer, jiffies + HZ/4);
+-}
+-
+-/*****************************************************************************
+- *
+- * 	locateDevice - start the locate NIC feature of the elected adapter 
+- *
+- * Description:
+- *	This function is used if the user want to locate a particular NIC.
+- *	All LEDs are regularly switched on and off, so the NIC can easily
+- *	be identified.
+- *
+- * Returns:	
+- *	==0:	everything fine, no error, locateNIC test was started
+- *	!=0:	one locateNIC test runs already
+- *
+- */
+-static int locateDevice(struct net_device *dev, u32 data)
+-{
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-
+-	if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+-		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+-
+-	/* start blinking */
+-	pAC->LedsOn = 0;
+-	mod_timer(&pAC->BlinkTimer, jiffies);
+-	msleep_interruptible(data * 1000);
+-	del_timer_sync(&pAC->BlinkTimer);
+-	toggleLeds(pNet, 0);
+-
+-	return 0;
+-}
+-
+-/*****************************************************************************
+- *
+- * 	getPauseParams - retrieves the pause parameters
+- *
+- * Description:
+- *	All current pause parameters of a selected adapter are placed 
+- *	in the passed ethtool_pauseparam structure and are returned.
+- *
+- * Returns:	N/A
+- *
+- */
+-static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause) 
+-{
+-	DEV_NET	*pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-	SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
+-
+-	epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
+-		  (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM);
+-
+-	epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND);
+-	epause->autoneg = epause->rx_pause || epause->tx_pause;
+-}
+-
+-/*****************************************************************************
+- *
+- *	setPauseParams - configures the pause parameters of an adapter
+- *
+- * Description:
+- *	This function sets the Rx or Tx pause parameters 
+- *
+- * Returns:
+- *	==0:	everything fine, no error
+- *	!=0:	the return value is the error code of the failure 
+- */
+-static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause)
+-{
+-	DEV_NET	*pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-	SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
+-	u32	instance = pnmiInstance(pNet);
+-	struct ethtool_pauseparam old;
+-	u8	oldspeed = pPort->PLinkSpeedUsed;
+-	char	buf[4];
+-	int	len = 1;
+-	int ret;
+-
+-	/*
+-	** we have to determine the current settings to see if 
+-	** the operator requested any modification of the flow 
+-	** control parameters...
+-	*/
+-	getPauseParams(dev, &old);
+-
+-	/*
+-	** perform modifications regarding the changes 
+-	** requested by the operator
+-	*/
+-	if (epause->autoneg != old.autoneg) 
+-		*buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC;
+-	else {
+-		if (epause->rx_pause && epause->tx_pause) 
+-			*buf = SK_FLOW_MODE_SYMMETRIC;
+-		else if (epause->rx_pause && !epause->tx_pause)
+-			*buf =  SK_FLOW_MODE_SYM_OR_REM;
+-		else if (!epause->rx_pause && epause->tx_pause)
+-			*buf =  SK_FLOW_MODE_LOC_SEND;
+-		else
+-			*buf = SK_FLOW_MODE_NONE;
+-	}
+-
+-	ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
+-			 &buf, &len, instance, pNet->NetNr);
+-
+-	if (ret != SK_PNMI_ERR_OK) {
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
+-			   ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret));
+-		goto err;
+-	}
+-
+-	/*
+-	** It may be that autoneg has been disabled! Therefore
+-	** set the speed to the previously used value...
+-	*/
+-	if (!epause->autoneg) {
+-		len = 1;
+-		ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
+-				   &oldspeed, &len, instance, pNet->NetNr);
+-		if (ret != SK_PNMI_ERR_OK) 
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
+-				   ("ethtool (sk98lin): error setting speed (%i)\n", ret));
+-	}
+- err:
+-        return ret ? -EIO : 0;
+-}
+-
+-/* Only Yukon supports checksum offload. */
+-static int setScatterGather(struct net_device *dev, u32 data)
+-{
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-
+-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+-		return -EOPNOTSUPP;
+-	return ethtool_op_set_sg(dev, data);
+-}
+-
+-static int setTxCsum(struct net_device *dev, u32 data)
+-{
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-
+-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+-		return -EOPNOTSUPP;
+-
+-	return ethtool_op_set_tx_csum(dev, data);
+-}
+-
+-static u32 getRxCsum(struct net_device *dev)
+-{
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-
+-	return pAC->RxPort[pNet->PortNr].RxCsum;
+-}
+-
+-static int setRxCsum(struct net_device *dev, u32 data)
+-{
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-
+-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+-		return -EOPNOTSUPP;
+-
+-	pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
+-	return 0;
+-}
+-
+-static int getRegsLen(struct net_device *dev)
+-{
+-	return 0x4000;
+-}
+-
+-/*
+- * Returns copy of whole control register region
+- * Note: skip RAM address register because accessing it will
+- * 	 cause bus hangs!
+- */
+-static void getRegs(struct net_device *dev, struct ethtool_regs *regs,
+-			  void *p)
+-{
+-	DEV_NET *pNet = netdev_priv(dev);
+-	const void __iomem *io = pNet->pAC->IoBase;
+-
+-	regs->version = 1;
+-	memset(p, 0, regs->len);
+-	memcpy_fromio(p, io, B3_RAM_ADDR);
+-
+-	memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+-		      regs->len - B3_RI_WTO_R1);
+-}
+-
+-const struct ethtool_ops SkGeEthtoolOps = {
+-	.get_settings		= getSettings,
+-	.set_settings		= setSettings,
+-	.get_drvinfo		= getDriverInfo,
+-	.get_strings		= getStrings,
+-	.get_stats_count	= getStatsCount,
+-	.get_ethtool_stats	= getEthtoolStats,
+-	.phys_id		= locateDevice,
+-	.get_pauseparam		= getPauseParams,
+-	.set_pauseparam		= setPauseParams,
+-	.get_link		= ethtool_op_get_link,
+-	.get_sg			= ethtool_op_get_sg,
+-	.set_sg			= setScatterGather,
+-	.get_tx_csum		= ethtool_op_get_tx_csum,
+-	.set_tx_csum		= setTxCsum,
+-	.get_rx_csum		= getRxCsum,
+-	.set_rx_csum		= setRxCsum,
+-	.get_regs		= getRegs,
+-	.get_regs_len		= getRegsLen,
+-};
+diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
+deleted file mode 100644
+index 20890e4..0000000
+--- a/drivers/net/sk98lin/skge.c
++++ /dev/null
+@@ -1,5218 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skge.c
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.45 $
+- * Date:       	$Date: 2004/02/12 14:41:02 $
+- * Purpose:	The main driver source module
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet 
+- *      Server Adapters.
+- *
+- *	Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
+- *	SysKonnects GEnesis Solaris driver
+- *	Author: Christoph Goos (cgoos at syskonnect.de)
+- *	        Mirko Lindner (mlindner at syskonnect.de)
+- *
+- *	Address all question to: linux at syskonnect.de
+- *
+- *	The technical manual for the adapters is available from SysKonnect's
+- *	web pages: www.syskonnect.com
+- *	Goto "Support" and search Knowledge Base for "manual".
+- *	
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Possible compiler options (#define xxx / -Dxxx):
+- *
+- *	debugging can be enable by changing SK_DEBUG_CHKMOD and
+- *	SK_DEBUG_CHKCAT in makefile (described there).
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- *	This is the main module of the Linux GE driver.
+- *	
+- *	All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h
+- *	are part of SysKonnect's COMMON MODULES for the SK-98xx adapters.
+- *	Those are used for drivers on multiple OS', so some thing may seem
+- *	unnecessary complicated on Linux. Please do not try to 'clean up'
+- *	them without VERY good reasons, because this will make it more
+- *	difficult to keep the Linux driver in synchronisation with the
+- *	other versions.
+- *
+- * Include file hierarchy:
+- *
+- *	<linux/module.h>
+- *
+- *	"h/skdrv1st.h"
+- *		<linux/types.h>
+- *		<linux/kernel.h>
+- *		<linux/string.h>
+- *		<linux/errno.h>
+- *		<linux/ioport.h>
+- *		<linux/slab.h>
+- *		<linux/interrupt.h>
+- *		<linux/pci.h>
+- *		<linux/bitops.h>
+- *		<asm/byteorder.h>
+- *		<asm/io.h>
+- *		<linux/netdevice.h>
+- *		<linux/etherdevice.h>
+- *		<linux/skbuff.h>
+- *	    those three depending on kernel version used:
+- *		<linux/bios32.h>
+- *		<linux/init.h>
+- *		<asm/uaccess.h>
+- *		<net/checksum.h>
+- *
+- *		"h/skerror.h"
+- *		"h/skdebug.h"
+- *		"h/sktypes.h"
+- *		"h/lm80.h"
+- *		"h/xmac_ii.h"
+- *
+- *      "h/skdrv2nd.h"
+- *		"h/skqueue.h"
+- *		"h/skgehwt.h"
+- *		"h/sktimer.h"
+- *		"h/ski2c.h"
+- *		"h/skgepnmi.h"
+- *		"h/skvpd.h"
+- *		"h/skgehw.h"
+- *		"h/skgeinit.h"
+- *		"h/skaddr.h"
+- *		"h/skgesirq.h"
+- *		"h/skrlmt.h"
+- *
+- ******************************************************************************/
+-
+-#include	"h/skversion.h"
+-
+-#include	<linux/in.h>
+-#include	<linux/module.h>
+-#include	<linux/moduleparam.h>
+-#include	<linux/init.h>
+-#include	<linux/dma-mapping.h>
+-#include	<linux/ip.h>
+-#include	<linux/mii.h>
+-#include	<linux/mm.h>
+-
+-#include	"h/skdrv1st.h"
+-#include	"h/skdrv2nd.h"
+-
+-/*******************************************************************************
+- *
+- * Defines
+- *
+- ******************************************************************************/
+-
+-/* for debuging on x86 only */
+-/* #define BREAKPOINT() asm(" int $3"); */
+-
+-/* use the transmit hw checksum driver functionality */
+-#define USE_SK_TX_CHECKSUM
+-
+-/* use the receive hw checksum driver functionality */
+-#define USE_SK_RX_CHECKSUM
+-
+-/* use the scatter-gather functionality with sendfile() */
+-#define SK_ZEROCOPY
+-
+-/* use of a transmit complete interrupt */
+-#define USE_TX_COMPLETE
+-
+-/*
+- * threshold for copying small receive frames
+- * set to 0 to avoid copying, set to 9001 to copy all frames
+- */
+-#define SK_COPY_THRESHOLD	50
+-
+-/* number of adapters that can be configured via command line params */
+-#define SK_MAX_CARD_PARAM	16
+-
+-
+-
+-/*
+- * use those defines for a compile-in version of the driver instead
+- * of command line parameters
+- */
+-// #define LINK_SPEED_A	{"Auto", }
+-// #define LINK_SPEED_B	{"Auto", }
+-// #define AUTO_NEG_A	{"Sense", }
+-// #define AUTO_NEG_B	{"Sense", }
+-// #define DUP_CAP_A	{"Both", }
+-// #define DUP_CAP_B	{"Both", }
+-// #define FLOW_CTRL_A	{"SymOrRem", }
+-// #define FLOW_CTRL_B	{"SymOrRem", }
+-// #define ROLE_A	{"Auto", }
+-// #define ROLE_B	{"Auto", }
+-// #define PREF_PORT	{"A", }
+-// #define CON_TYPE 	{"Auto", }
+-// #define RLMT_MODE	{"CheckLinkState", }
+-
+-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
+-#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
+-#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
+-
+-
+-/* Set blink mode*/
+-#define OEM_CONFIG_VALUE (	SK_ACT_LED_BLINK | \
+-				SK_DUP_LED_NORMAL | \
+-				SK_LED_LINK100_ON)
+-
+-
+-/* Isr return value */
+-#define SkIsrRetVar	irqreturn_t
+-#define SkIsrRetNone	IRQ_NONE
+-#define SkIsrRetHandled	IRQ_HANDLED
+-
+-
+-/*******************************************************************************
+- *
+- * Local Function Prototypes
+- *
+- ******************************************************************************/
+-
+-static void	FreeResources(struct SK_NET_DEVICE *dev);
+-static int	SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
+-static SK_BOOL	BoardAllocMem(SK_AC *pAC);
+-static void	BoardFreeMem(SK_AC *pAC);
+-static void	BoardInitMem(SK_AC *pAC);
+-static void	SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
+-static SkIsrRetVar	SkGeIsr(int irq, void *dev_id);
+-static SkIsrRetVar	SkGeIsrOnePort(int irq, void *dev_id);
+-static int	SkGeOpen(struct SK_NET_DEVICE *dev);
+-static int	SkGeClose(struct SK_NET_DEVICE *dev);
+-static int	SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
+-static int	SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
+-static void	SkGeSetRxMode(struct SK_NET_DEVICE *dev);
+-static struct	net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
+-static int	SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
+-static void	GetConfiguration(SK_AC*);
+-static int	XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
+-static void	FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
+-static void	FillRxRing(SK_AC*, RX_PORT*);
+-static SK_BOOL	FillRxDescriptor(SK_AC*, RX_PORT*);
+-static void	ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
+-static void	ClearAndStartRx(SK_AC*, int);
+-static void	ClearTxIrq(SK_AC*, int, int);
+-static void	ClearRxRing(SK_AC*, RX_PORT*);
+-static void	ClearTxRing(SK_AC*, TX_PORT*);
+-static int	SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
+-static void	PortReInitBmu(SK_AC*, int);
+-static int	SkGeIocMib(DEV_NET*, unsigned int, int);
+-static int	SkGeInitPCI(SK_AC *pAC);
+-static void	StartDrvCleanupTimer(SK_AC *pAC);
+-static void	StopDrvCleanupTimer(SK_AC *pAC);
+-static int	XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
+-
+-#ifdef SK_DIAG_SUPPORT
+-static SK_U32   ParseDeviceNbrFromSlotName(const char *SlotName);
+-static int      SkDrvInitAdapter(SK_AC *pAC, int devNbr);
+-static int      SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
+-#endif
+-
+-/*******************************************************************************
+- *
+- * Extern Function Prototypes
+- *
+- ******************************************************************************/
+-extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);	
+-extern void SkDimDisplayModerationSettings(SK_AC *pAC);
+-extern void SkDimStartModerationTimer(SK_AC *pAC);
+-extern void SkDimModerate(SK_AC *pAC);
+-extern void SkGeBlinkTimer(unsigned long data);
+-
+-#ifdef DEBUG
+-static void	DumpMsg(struct sk_buff*, char*);
+-static void	DumpData(char*, int);
+-static void	DumpLong(char*, int);
+-#endif
+-
+-/* global variables *********************************************************/
+-static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
+-extern const struct ethtool_ops SkGeEthtoolOps;
+-
+-/* local variables **********************************************************/
+-static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
+-static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
+-
+-/*****************************************************************************
+- *
+- *	SkPciWriteCfgDWord - write a 32 bit value to pci config space
+- *
+- * Description:
+- *	This routine writes a 32 bit value to the pci configuration
+- *	space.
+- *
+- * Returns:
+- *	0 - indicate everything worked ok.
+- *	!= 0 - error indication
+- */
+-static inline int SkPciWriteCfgDWord(
+-SK_AC *pAC,	/* Adapter Control structure pointer */
+-int PciAddr,		/* PCI register address */
+-SK_U32 Val)		/* pointer to store the read value */
+-{
+-	pci_write_config_dword(pAC->PciDev, PciAddr, Val);
+-	return(0);
+-} /* SkPciWriteCfgDWord */
+-
+-/*****************************************************************************
+- *
+- * 	SkGeInitPCI - Init the PCI resources
+- *
+- * Description:
+- *	This function initialize the PCI resources and IO
+- *
+- * Returns:
+- *	0 - indicate everything worked ok.
+- *	!= 0 - error indication
+- */
+-static __devinit int SkGeInitPCI(SK_AC *pAC)
+-{
+-	struct SK_NET_DEVICE *dev = pAC->dev[0];
+-	struct pci_dev *pdev = pAC->PciDev;
+-	int retval;
+-
+-	dev->mem_start = pci_resource_start (pdev, 0);
+-	pci_set_master(pdev);
+-
+-	retval = pci_request_regions(pdev, "sk98lin");
+-	if (retval)
+-		goto out;
+-
+-#ifdef SK_BIG_ENDIAN
+-	/*
+-	 * On big endian machines, we use the adapter's aibility of
+-	 * reading the descriptors as big endian.
+-	 */
+-	{
+-		SK_U32		our2;
+-		SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
+-		our2 |= PCI_REV_DESC;
+-		SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
+-	}
+-#endif
+-
+-	/*
+-	 * Remap the regs into kernel space.
+-	 */
+-	pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
+-	if (!pAC->IoBase) {
+-		retval = -EIO;
+-		goto out_release;
+-	}
+-
+-	return 0;
+-
+- out_release:
+-	pci_release_regions(pdev);
+- out:
+-	return retval;
+-}
+-
+-
+-/*****************************************************************************
+- *
+- * 	FreeResources - release resources allocated for adapter
+- *
+- * Description:
+- *	This function releases the IRQ, unmaps the IO and
+- *	frees the desriptor ring.
+- *
+- * Returns: N/A
+- *	
+- */
+-static void FreeResources(struct SK_NET_DEVICE *dev)
+-{
+-SK_U32 AllocFlag;
+-DEV_NET		*pNet;
+-SK_AC		*pAC;
+-
+-	pNet = netdev_priv(dev);
+-	pAC = pNet->pAC;
+-	AllocFlag = pAC->AllocFlag;
+-	if (pAC->PciDev) {
+-		pci_release_regions(pAC->PciDev);
+-	}
+-	if (AllocFlag & SK_ALLOC_IRQ) {
+-		free_irq(dev->irq, dev);
+-	}
+-	if (pAC->IoBase) {
+-		iounmap(pAC->IoBase);
+-	}
+-	if (pAC->pDescrMem) {
+-		BoardFreeMem(pAC);
+-	}
+-	
+-} /* FreeResources */
+-
+-MODULE_AUTHOR("Mirko Lindner <mlindner at syskonnect.de>");
+-MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
+-MODULE_LICENSE("GPL");
+-
+-#ifdef LINK_SPEED_A
+-static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
+-#else
+-static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef LINK_SPEED_B
+-static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
+-#else
+-static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef AUTO_NEG_A
+-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
+-#else
+-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef DUP_CAP_A
+-static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A;
+-#else
+-static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef FLOW_CTRL_A
+-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A;
+-#else
+-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef ROLE_A
+-static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A;
+-#else
+-static char *Role_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef AUTO_NEG_B
+-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B;
+-#else
+-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef DUP_CAP_B
+-static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B;
+-#else
+-static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef FLOW_CTRL_B
+-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B;
+-#else
+-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef ROLE_B
+-static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;
+-#else
+-static char *Role_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef CON_TYPE
+-static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE;
+-#else
+-static char *ConType[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef PREF_PORT
+-static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;
+-#else
+-static char *PrefPort[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef RLMT_MODE
+-static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
+-#else
+-static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-static int   IntsPerSec[SK_MAX_CARD_PARAM];
+-static char *Moderation[SK_MAX_CARD_PARAM];
+-static char *ModerationMask[SK_MAX_CARD_PARAM];
+-static char *AutoSizing[SK_MAX_CARD_PARAM];
+-static char *Stats[SK_MAX_CARD_PARAM];
+-
+-module_param_array(Speed_A, charp, NULL, 0);
+-module_param_array(Speed_B, charp, NULL, 0);
+-module_param_array(AutoNeg_A, charp, NULL, 0);
+-module_param_array(AutoNeg_B, charp, NULL, 0);
+-module_param_array(DupCap_A, charp, NULL, 0);
+-module_param_array(DupCap_B, charp, NULL, 0);
+-module_param_array(FlowCtrl_A, charp, NULL, 0);
+-module_param_array(FlowCtrl_B, charp, NULL, 0);
+-module_param_array(Role_A, charp, NULL, 0);
+-module_param_array(Role_B, charp, NULL, 0);
+-module_param_array(ConType, charp, NULL, 0);
+-module_param_array(PrefPort, charp, NULL, 0);
+-module_param_array(RlmtMode, charp, NULL, 0);
+-/* used for interrupt moderation */
+-module_param_array(IntsPerSec, int, NULL, 0);
+-module_param_array(Moderation, charp, NULL, 0);
+-module_param_array(Stats, charp, NULL, 0);
+-module_param_array(ModerationMask, charp, NULL, 0);
+-module_param_array(AutoSizing, charp, NULL, 0);
+-
+-/*****************************************************************************
+- *
+- * 	SkGeBoardInit - do level 0 and 1 initialization
+- *
+- * Description:
+- *	This function prepares the board hardware for running. The desriptor
+- *	ring is set up, the IRQ is allocated and the configuration settings
+- *	are examined.
+- *
+- * Returns:
+- *	0, if everything is ok
+- *	!=0, on error
+- */
+-static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
+-{
+-short	i;
+-unsigned long Flags;
+-char	*DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
+-char	*VerStr	= VER_STRING;
+-int	Ret;			/* return code of request_irq */
+-SK_BOOL	DualNet;
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
+-	for (i=0; i<SK_MAX_MACS; i++) {
+-		pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0];
+-		pAC->TxPort[i][0].PortIndex = i;
+-		pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i];
+-		pAC->RxPort[i].PortIndex = i;
+-	}
+-
+-	/* Initialize the mutexes */
+-	for (i=0; i<SK_MAX_MACS; i++) {
+-		spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
+-		spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
+-	}
+-	spin_lock_init(&pAC->SlowPathLock);
+-
+-	/* setup phy_id blink timer */
+-	pAC->BlinkTimer.function = SkGeBlinkTimer;
+-	pAC->BlinkTimer.data = (unsigned long) dev;
+-	init_timer(&pAC->BlinkTimer);
+-
+-	/* level 0 init common modules here */
+-	
+-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-	/* Does a RESET on board ...*/
+-	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
+-		printk("HWInit (0) failed.\n");
+-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-		return -EIO;
+-	}
+-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_DATA);
+-	SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
+-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA);
+-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA);
+-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA);
+-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
+-
+-	pAC->BoardLevel = SK_INIT_DATA;
+-	pAC->RxBufSize  = ETH_BUF_SIZE;
+-
+-	SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
+-	SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
+-
+-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+-	/* level 1 init common modules here (HW init) */
+-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
+-		printk("sk98lin: HWInit (1) failed.\n");
+-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-		return -EIO;
+-	}
+-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
+-	SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
+-
+-	/* Set chipset type support */
+-	pAC->ChipsetType = 0;
+-	if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
+-		(pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) {
+-		pAC->ChipsetType = 1;
+-	}
+-
+-	GetConfiguration(pAC);
+-	if (pAC->RlmtNets == 2) {
+-		pAC->GIni.GIPortUsage = SK_MUL_LINK;
+-	}
+-
+-	pAC->BoardLevel = SK_INIT_IO;
+-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+-	if (pAC->GIni.GIMacsFound == 2) {
+-		 Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
+-	} else if (pAC->GIni.GIMacsFound == 1) {
+-		Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED,
+-			"sk98lin", dev);
+-	} else {
+-		printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
+-		       pAC->GIni.GIMacsFound);
+-		return -EIO;
+-	}
+-
+-	if (Ret) {
+-		printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
+-		       dev->irq);
+-		return Ret;
+-	}
+-	pAC->AllocFlag |= SK_ALLOC_IRQ;
+-
+-	/* Alloc memory for this board (Mem for RxD/TxD) : */
+-	if(!BoardAllocMem(pAC)) {
+-		printk("No memory for descriptor rings.\n");
+-		return -ENOMEM;
+-	}
+-
+-	BoardInitMem(pAC);
+-	/* tschilling: New common function with minimum size check. */
+-	DualNet = SK_FALSE;
+-	if (pAC->RlmtNets == 2) {
+-		DualNet = SK_TRUE;
+-	}
+-	
+-	if (SkGeInitAssignRamToQueues(
+-		pAC,
+-		pAC->ActivePort,
+-		DualNet)) {
+-		BoardFreeMem(pAC);
+-		printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
+-		return -EIO;
+-	}
+-
+-	return (0);
+-} /* SkGeBoardInit */
+-
+-
+-/*****************************************************************************
+- *
+- * 	BoardAllocMem - allocate the memory for the descriptor rings
+- *
+- * Description:
+- *	This function allocates the memory for all descriptor rings.
+- *	Each ring is aligned for the desriptor alignment and no ring
+- *	has a 4 GByte boundary in it (because the upper 32 bit must
+- *	be constant for all descriptiors in one rings).
+- *
+- * Returns:
+- *	SK_TRUE, if all memory could be allocated
+- *	SK_FALSE, if not
+- */
+-static __devinit SK_BOOL BoardAllocMem(SK_AC	*pAC)
+-{
+-caddr_t		pDescrMem;	/* pointer to descriptor memory area */
+-size_t		AllocLength;	/* length of complete descriptor area */
+-int		i;		/* loop counter */
+-unsigned long	BusAddr;
+-
+-	
+-	/* rings plus one for alignment (do not cross 4 GB boundary) */
+-	/* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */
+-#if (BITS_PER_LONG == 32)
+-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
+-#else
+-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+-		+ RX_RING_SIZE + 8;
+-#endif
+-
+-	pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
+-					 &pAC->pDescrMemDMA);
+-
+-	if (pDescrMem == NULL) {
+-		return (SK_FALSE);
+-	}
+-	pAC->pDescrMem = pDescrMem;
+-	BusAddr = (unsigned long) pAC->pDescrMemDMA;
+-
+-	/* Descriptors need 8 byte alignment, and this is ensured
+-	 * by pci_alloc_consistent.
+-	 */
+-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+-			("TX%d/A: pDescrMem: %lX,   PhysDescrMem: %lX\n",
+-			i, (unsigned long) pDescrMem,
+-			BusAddr));
+-		pAC->TxPort[i][0].pTxDescrRing = pDescrMem;
+-		pAC->TxPort[i][0].VTxDescrRing = BusAddr;
+-		pDescrMem += TX_RING_SIZE;
+-		BusAddr += TX_RING_SIZE;
+-	
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+-			("RX%d: pDescrMem: %lX,   PhysDescrMem: %lX\n",
+-			i, (unsigned long) pDescrMem,
+-			(unsigned long)BusAddr));
+-		pAC->RxPort[i].pRxDescrRing = pDescrMem;
+-		pAC->RxPort[i].VRxDescrRing = BusAddr;
+-		pDescrMem += RX_RING_SIZE;
+-		BusAddr += RX_RING_SIZE;
+-	} /* for */
+-	
+-	return (SK_TRUE);
+-} /* BoardAllocMem */
+-
+-
+-/****************************************************************************
+- *
+- *	BoardFreeMem - reverse of BoardAllocMem
+- *
+- * Description:
+- *	Free all memory allocated in BoardAllocMem: adapter context,
+- *	descriptor rings, locks.
+- *
+- * Returns:	N/A
+- */
+-static void BoardFreeMem(
+-SK_AC		*pAC)
+-{
+-size_t		AllocLength;	/* length of complete descriptor area */
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("BoardFreeMem\n"));
+-#if (BITS_PER_LONG == 32)
+-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
+-#else
+-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+-		+ RX_RING_SIZE + 8;
+-#endif
+-
+-	pci_free_consistent(pAC->PciDev, AllocLength,
+-			    pAC->pDescrMem, pAC->pDescrMemDMA);
+-	pAC->pDescrMem = NULL;
+-} /* BoardFreeMem */
+-
+-
+-/*****************************************************************************
+- *
+- * 	BoardInitMem - initiate the descriptor rings
+- *
+- * Description:
+- *	This function sets the descriptor rings up in memory.
+- *	The adapter is initialized with the descriptor start addresses.
+- *
+- * Returns:	N/A
+- */
+-static __devinit void BoardInitMem(SK_AC *pAC)
+-{
+-int	i;		/* loop counter */
+-int	RxDescrSize;	/* the size of a rx descriptor rounded up to alignment*/
+-int	TxDescrSize;	/* the size of a tx descriptor rounded up to alignment*/
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("BoardInitMem\n"));
+-
+-	RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
+-	pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
+-	TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
+-	pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
+-	
+-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+-		SetupRing(
+-			pAC,
+-			pAC->TxPort[i][0].pTxDescrRing,
+-			pAC->TxPort[i][0].VTxDescrRing,
+-			(RXD**)&pAC->TxPort[i][0].pTxdRingHead,
+-			(RXD**)&pAC->TxPort[i][0].pTxdRingTail,
+-			(RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
+-			&pAC->TxPort[i][0].TxdRingFree,
+-			SK_TRUE);
+-		SetupRing(
+-			pAC,
+-			pAC->RxPort[i].pRxDescrRing,
+-			pAC->RxPort[i].VRxDescrRing,
+-			&pAC->RxPort[i].pRxdRingHead,
+-			&pAC->RxPort[i].pRxdRingTail,
+-			&pAC->RxPort[i].pRxdRingPrev,
+-			&pAC->RxPort[i].RxdRingFree,
+-			SK_FALSE);
+-	}
+-} /* BoardInitMem */
+-
+-
+-/*****************************************************************************
+- *
+- * 	SetupRing - create one descriptor ring
+- *
+- * Description:
+- *	This function creates one descriptor ring in the given memory area.
+- *	The head, tail and number of free descriptors in the ring are set.
+- *
+- * Returns:
+- *	none
+- */
+-static void SetupRing(
+-SK_AC		*pAC,
+-void		*pMemArea,	/* a pointer to the memory area for the ring */
+-uintptr_t	VMemArea,	/* the virtual bus address of the memory area */
+-RXD		**ppRingHead,	/* address where the head should be written */
+-RXD		**ppRingTail,	/* address where the tail should be written */
+-RXD		**ppRingPrev,	/* address where the tail should be written */
+-int		*pRingFree,	/* address where the # of free descr. goes */
+-SK_BOOL		IsTx)		/* flag: is this a tx ring */
+-{
+-int	i;		/* loop counter */
+-int	DescrSize;	/* the size of a descriptor rounded up to alignment*/
+-int	DescrNum;	/* number of descriptors per ring */
+-RXD	*pDescr;	/* pointer to a descriptor (receive or transmit) */
+-RXD	*pNextDescr;	/* pointer to the next descriptor */
+-RXD	*pPrevDescr;	/* pointer to the previous descriptor */
+-uintptr_t VNextDescr;	/* the virtual bus address of the next descriptor */
+-
+-	if (IsTx == SK_TRUE) {
+-		DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
+-			DESCR_ALIGN;
+-		DescrNum = TX_RING_SIZE / DescrSize;
+-	} else {
+-		DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
+-			DESCR_ALIGN;
+-		DescrNum = RX_RING_SIZE / DescrSize;
+-	}
+-	
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+-		("Descriptor size: %d   Descriptor Number: %d\n",
+-		DescrSize,DescrNum));
+-	
+-	pDescr = (RXD*) pMemArea;
+-	pPrevDescr = NULL;
+-	pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
+-	VNextDescr = VMemArea + DescrSize;
+-	for(i=0; i<DescrNum; i++) {
+-		/* set the pointers right */
+-		pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
+-		pDescr->pNextRxd = pNextDescr;
+-		if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN;
+-
+-		/* advance one step */
+-		pPrevDescr = pDescr;
+-		pDescr = pNextDescr;
+-		pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
+-		VNextDescr += DescrSize;
+-	}
+-	pPrevDescr->pNextRxd = (RXD*) pMemArea;
+-	pPrevDescr->VNextRxd = VMemArea;
+-	pDescr = (RXD*) pMemArea;
+-	*ppRingHead = (RXD*) pMemArea;
+-	*ppRingTail = *ppRingHead;
+-	*ppRingPrev = pPrevDescr;
+-	*pRingFree = DescrNum;
+-} /* SetupRing */
+-
+-
+-/*****************************************************************************
+- *
+- * 	PortReInitBmu - re-initiate the descriptor rings for one port
+- *
+- * Description:
+- *	This function reinitializes the descriptor rings of one port
+- *	in memory. The port must be stopped before.
+- *	The HW is initialized with the descriptor start addresses.
+- *
+- * Returns:
+- *	none
+- */
+-static void PortReInitBmu(
+-SK_AC	*pAC,		/* pointer to adapter context */
+-int	PortIndex)	/* index of the port for which to re-init */
+-{
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("PortReInitBmu "));
+-
+-	/* set address of first descriptor of ring in BMU */
+-	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L,
+-		(uint32_t)(((caddr_t)
+-		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
+-		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
+-		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &
+-		0xFFFFFFFF));
+-	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H,
+-		(uint32_t)(((caddr_t)
+-		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
+-		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
+-		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));
+-	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L,
+-		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
+-		pAC->RxPort[PortIndex].pRxDescrRing +
+-		pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));
+-	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H,
+-		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
+-		pAC->RxPort[PortIndex].pRxDescrRing +
+-		pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
+-} /* PortReInitBmu */
+-
+-
+-/****************************************************************************
+- *
+- *	SkGeIsr - handle adapter interrupts
+- *
+- * Description:
+- *	The interrupt routine is called when the network adapter
+- *	generates an interrupt. It may also be called if another device
+- *	shares this interrupt vector with the driver.
+- *
+- * Returns: N/A
+- *
+- */
+-static SkIsrRetVar SkGeIsr(int irq, void *dev_id)
+-{
+-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
+-DEV_NET		*pNet;
+-SK_AC		*pAC;
+-SK_U32		IntSrc;		/* interrupts source register contents */	
+-
+-	pNet = netdev_priv(dev);
+-	pAC = pNet->pAC;
+-	
+-	/*
+-	 * Check and process if its our interrupt
+-	 */
+-	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
+-	if (IntSrc == 0) {
+-		return SkIsrRetNone;
+-	}
+-
+-	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
+-#if 0 /* software irq currently not used */
+-		if (IntSrc & IS_IRQ_SW) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("Software IRQ\n"));
+-		}
+-#endif
+-		if (IntSrc & IS_R1_F) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("EOF RX1 IRQ\n"));
+-			ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+-			SK_PNMI_CNT_RX_INTR(pAC, 0);
+-		}
+-		if (IntSrc & IS_R2_F) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("EOF RX2 IRQ\n"));
+-			ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+-			SK_PNMI_CNT_RX_INTR(pAC, 1);
+-		}
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+-		if (IntSrc & IS_XA1_F) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("EOF AS TX1 IRQ\n"));
+-			SK_PNMI_CNT_TX_INTR(pAC, 0);
+-			spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+-			FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+-			spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+-		}
+-		if (IntSrc & IS_XA2_F) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("EOF AS TX2 IRQ\n"));
+-			SK_PNMI_CNT_TX_INTR(pAC, 1);
+-			spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+-			FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
+-			spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+-		}
+-#if 0 /* only if sync. queues used */
+-		if (IntSrc & IS_XS1_F) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("EOF SY TX1 IRQ\n"));
+-			SK_PNMI_CNT_TX_INTR(pAC, 1);
+-			spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+-			FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
+-			spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+-			ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
+-		}
+-		if (IntSrc & IS_XS2_F) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("EOF SY TX2 IRQ\n"));
+-			SK_PNMI_CNT_TX_INTR(pAC, 1);
+-			spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
+-			FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
+-			spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
+-			ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
+-		}
+-#endif
+-#endif
+-
+-		/* do all IO at once */
+-		if (IntSrc & IS_R1_F)
+-			ClearAndStartRx(pAC, 0);
+-		if (IntSrc & IS_R2_F)
+-			ClearAndStartRx(pAC, 1);
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+-		if (IntSrc & IS_XA1_F)
+-			ClearTxIrq(pAC, 0, TX_PRIO_LOW);
+-		if (IntSrc & IS_XA2_F)
+-			ClearTxIrq(pAC, 1, TX_PRIO_LOW);
+-#endif
+-		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
+-	} /* while (IntSrc & IRQ_MASK != 0) */
+-
+-	IntSrc &= pAC->GIni.GIValIrqMask;
+-	if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+-			("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
+-		pAC->CheckQueue = SK_FALSE;
+-		spin_lock(&pAC->SlowPathLock);
+-		if (IntSrc & SPECIAL_IRQS)
+-			SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+-
+-		SkEventDispatcher(pAC, pAC->IoBase);
+-		spin_unlock(&pAC->SlowPathLock);
+-	}
+-	/*
+-	 * do it all again is case we cleared an interrupt that
+-	 * came in after handling the ring (OUTs may be delayed
+-	 * in hardware buffers, but are through after IN)
+-	 *
+-	 * rroesler: has been commented out and shifted to
+-	 *           SkGeDrvEvent(), because it is timer
+-	 *           guarded now
+-	 *
+-	ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+-	ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+-	 */
+-
+-	if (pAC->CheckQueue) {
+-		pAC->CheckQueue = SK_FALSE;
+-		spin_lock(&pAC->SlowPathLock);
+-		SkEventDispatcher(pAC, pAC->IoBase);
+-		spin_unlock(&pAC->SlowPathLock);
+-	}
+-
+-	/* IRQ is processed - Enable IRQs again*/
+-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+-
+-		return SkIsrRetHandled;
+-} /* SkGeIsr */
+-
+-
+-/****************************************************************************
+- *
+- *	SkGeIsrOnePort - handle adapter interrupts for single port adapter
+- *
+- * Description:
+- *	The interrupt routine is called when the network adapter
+- *	generates an interrupt. It may also be called if another device
+- *	shares this interrupt vector with the driver.
+- *	This is the same as above, but handles only one port.
+- *
+- * Returns: N/A
+- *
+- */
+-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id)
+-{
+-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
+-DEV_NET		*pNet;
+-SK_AC		*pAC;
+-SK_U32		IntSrc;		/* interrupts source register contents */	
+-
+-	pNet = netdev_priv(dev);
+-	pAC = pNet->pAC;
+-	
+-	/*
+-	 * Check and process if its our interrupt
+-	 */
+-	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
+-	if (IntSrc == 0) {
+-		return SkIsrRetNone;
+-	}
+-	
+-	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
+-#if 0 /* software irq currently not used */
+-		if (IntSrc & IS_IRQ_SW) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("Software IRQ\n"));
+-		}
+-#endif
+-		if (IntSrc & IS_R1_F) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("EOF RX1 IRQ\n"));
+-			ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+-			SK_PNMI_CNT_RX_INTR(pAC, 0);
+-		}
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+-		if (IntSrc & IS_XA1_F) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("EOF AS TX1 IRQ\n"));
+-			SK_PNMI_CNT_TX_INTR(pAC, 0);
+-			spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+-			FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+-			spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+-		}
+-#if 0 /* only if sync. queues used */
+-		if (IntSrc & IS_XS1_F) {
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_INT_SRC,
+-				("EOF SY TX1 IRQ\n"));
+-			SK_PNMI_CNT_TX_INTR(pAC, 0);
+-			spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+-			FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
+-			spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+-			ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
+-		}
+-#endif
+-#endif
+-
+-		/* do all IO at once */
+-		if (IntSrc & IS_R1_F)
+-			ClearAndStartRx(pAC, 0);
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+-		if (IntSrc & IS_XA1_F)
+-			ClearTxIrq(pAC, 0, TX_PRIO_LOW);
+-#endif
+-		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
+-	} /* while (IntSrc & IRQ_MASK != 0) */
+-	
+-	IntSrc &= pAC->GIni.GIValIrqMask;
+-	if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+-			("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
+-		pAC->CheckQueue = SK_FALSE;
+-		spin_lock(&pAC->SlowPathLock);
+-		if (IntSrc & SPECIAL_IRQS)
+-			SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+-
+-		SkEventDispatcher(pAC, pAC->IoBase);
+-		spin_unlock(&pAC->SlowPathLock);
+-	}
+-	/*
+-	 * do it all again is case we cleared an interrupt that
+-	 * came in after handling the ring (OUTs may be delayed
+-	 * in hardware buffers, but are through after IN)
+-	 *
+-	 * rroesler: has been commented out and shifted to
+-	 *           SkGeDrvEvent(), because it is timer
+-	 *           guarded now
+-	 *
+-	ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+-	 */
+-
+-	/* IRQ is processed - Enable IRQs again*/
+-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+-
+-		return SkIsrRetHandled;
+-} /* SkGeIsrOnePort */
+-
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-/****************************************************************************
+- *
+- * 	SkGePollController - polling receive, for netconsole
+- *
+- * Description:
+- *	Polling receive - used by netconsole and other diagnostic tools
+- *	to allow network i/o with interrupts disabled.
+- *
+- * Returns: N/A
+- */
+-static void SkGePollController(struct net_device *dev)
+-{
+-	disable_irq(dev->irq);
+-	SkGeIsr(dev->irq, dev);
+-	enable_irq(dev->irq);
+-}
+-#endif
+-
+-/****************************************************************************
+- *
+- *	SkGeOpen - handle start of initialized adapter
+- *
+- * Description:
+- *	This function starts the initialized adapter.
+- *	The board level variable is set and the adapter is
+- *	brought to full functionality.
+- *	The device flags are set for operation.
+- *	Do all necessary level 2 initialization, enable interrupts and
+- *	give start command to RLMT.
+- *
+- * Returns:
+- *	0 on success
+- *	!= 0 on error
+- */
+-static int SkGeOpen(
+-struct SK_NET_DEVICE	*dev)
+-{
+-	DEV_NET			*pNet;
+-	SK_AC			*pAC;
+-	unsigned long	Flags;		/* for spin lock */
+-	int				i;
+-	SK_EVPARA		EvPara;		/* an event parameter union */
+-
+-	pNet = netdev_priv(dev);
+-	pAC = pNet->pAC;
+-	
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
+-
+-#ifdef SK_DIAG_SUPPORT
+-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
+-		if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+-			return (-1);   /* still in use by diag; deny actions */
+-		} 
+-	}
+-#endif
+-
+-	/* Set blink mode */
+-	if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab ))
+-		pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
+-
+-	if (pAC->BoardLevel == SK_INIT_DATA) {
+-		/* level 1 init common modules here */
+-		if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
+-			printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
+-			return (-1);
+-		}
+-		SkI2cInit	(pAC, pAC->IoBase, SK_INIT_IO);
+-		SkEventInit	(pAC, pAC->IoBase, SK_INIT_IO);
+-		SkPnmiInit	(pAC, pAC->IoBase, SK_INIT_IO);
+-		SkAddrInit	(pAC, pAC->IoBase, SK_INIT_IO);
+-		SkRlmtInit	(pAC, pAC->IoBase, SK_INIT_IO);
+-		SkTimerInit	(pAC, pAC->IoBase, SK_INIT_IO);
+-		pAC->BoardLevel = SK_INIT_IO;
+-	}
+-
+-	if (pAC->BoardLevel != SK_INIT_RUN) {
+-		/* tschilling: Level 2 init modules here, check return value. */
+-		if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
+-			printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
+-			return (-1);
+-		}
+-		SkI2cInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+-		SkEventInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+-		SkPnmiInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+-		SkAddrInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+-		SkRlmtInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+-		SkTimerInit	(pAC, pAC->IoBase, SK_INIT_RUN);
+-		pAC->BoardLevel = SK_INIT_RUN;
+-	}
+-
+-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+-		/* Enable transmit descriptor polling. */
+-		SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
+-		FillRxRing(pAC, &pAC->RxPort[i]);
+-	}
+-	SkGeYellowLED(pAC, pAC->IoBase, 1);
+-
+-	StartDrvCleanupTimer(pAC);
+-	SkDimEnableModerationIfNeeded(pAC);	
+-	SkDimDisplayModerationSettings(pAC);
+-
+-	pAC->GIni.GIValIrqMask &= IRQ_MASK;
+-
+-	/* enable Interrupts */
+-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+-	SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
+-
+-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-
+-	if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) {
+-		EvPara.Para32[0] = pAC->RlmtNets;
+-		EvPara.Para32[1] = -1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
+-			EvPara);
+-		EvPara.Para32[0] = pAC->RlmtMode;
+-		EvPara.Para32[1] = 0;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
+-			EvPara);
+-	}
+-
+-	EvPara.Para32[0] = pNet->NetNr;
+-	EvPara.Para32[1] = -1;
+-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+-	SkEventDispatcher(pAC, pAC->IoBase);
+-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+-	pAC->MaxPorts++;
+-
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeOpen suceeded\n"));
+-
+-	return (0);
+-} /* SkGeOpen */
+-
+-
+-/****************************************************************************
+- *
+- *	SkGeClose - Stop initialized adapter
+- *
+- * Description:
+- *	Close initialized adapter.
+- *
+- * Returns:
+- *	0 - on success
+- *	error code - on error
+- */
+-static int SkGeClose(
+-struct SK_NET_DEVICE	*dev)
+-{
+-	DEV_NET		*pNet;
+-	DEV_NET		*newPtrNet;
+-	SK_AC		*pAC;
+-
+-	unsigned long	Flags;		/* for spin lock */
+-	int		i;
+-	int		PortIdx;
+-	SK_EVPARA	EvPara;
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
+-
+-	pNet = netdev_priv(dev);
+-	pAC = pNet->pAC;
+-
+-#ifdef SK_DIAG_SUPPORT
+-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
+-		if (pAC->DiagFlowCtrl == SK_FALSE) {
+-			/* 
+-			** notify that the interface which has been closed
+-			** by operator interaction must not be started up 
+-			** again when the DIAG has finished. 
+-			*/
+-			newPtrNet = netdev_priv(pAC->dev[0]);
+-			if (newPtrNet == pNet) {
+-				pAC->WasIfUp[0] = SK_FALSE;
+-			} else {
+-				pAC->WasIfUp[1] = SK_FALSE;
+-			}
+-			return 0; /* return to system everything is fine... */
+-		} else {
+-			pAC->DiagFlowCtrl = SK_FALSE;
+-		}
+-	}
+-#endif
+-
+-	netif_stop_queue(dev);
+-
+-	if (pAC->RlmtNets == 1)
+-		PortIdx = pAC->ActivePort;
+-	else
+-		PortIdx = pNet->NetNr;
+-
+-        StopDrvCleanupTimer(pAC);
+-
+-	/*
+-	 * Clear multicast table, promiscuous mode ....
+-	 */
+-	SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
+-	SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+-		SK_PROM_MODE_NONE);
+-
+-	if (pAC->MaxPorts == 1) {
+-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-		/* disable interrupts */
+-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+-		EvPara.Para32[0] = pNet->NetNr;
+-		EvPara.Para32[1] = -1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+-		SkEventDispatcher(pAC, pAC->IoBase);
+-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+-		/* stop the hardware */
+-		SkGeDeInit(pAC, pAC->IoBase);
+-		pAC->BoardLevel = SK_INIT_DATA;
+-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-	} else {
+-
+-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-		EvPara.Para32[0] = pNet->NetNr;
+-		EvPara.Para32[1] = -1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+-		SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara);
+-		SkEventDispatcher(pAC, pAC->IoBase);
+-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-		
+-		/* Stop port */
+-		spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
+-			[TX_PRIO_LOW].TxDesRingLock, Flags);
+-		SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
+-			SK_STOP_ALL, SK_HARD_RST);
+-		spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
+-			[TX_PRIO_LOW].TxDesRingLock, Flags);
+-	}
+-
+-	if (pAC->RlmtNets == 1) {
+-		/* clear all descriptor rings */
+-		for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+-			ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
+-			ClearRxRing(pAC, &pAC->RxPort[i]);
+-			ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
+-		}
+-	} else {
+-		/* clear port descriptor rings */
+-		ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
+-		ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
+-		ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
+-	}
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeClose: done "));
+-
+-	SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
+-	SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), 
+-			sizeof(SK_PNMI_STRUCT_DATA));
+-
+-	pAC->MaxPorts--;
+-
+-	return (0);
+-} /* SkGeClose */
+-
+-
+-/*****************************************************************************
+- *
+- * 	SkGeXmit - Linux frame transmit function
+- *
+- * Description:
+- *	The system calls this function to send frames onto the wire.
+- *	It puts the frame in the tx descriptor ring. If the ring is
+- *	full then, the 'tbusy' flag is set.
+- *
+- * Returns:
+- *	0, if everything is ok
+- *	!=0, on error
+- * WARNING: returning 1 in 'tbusy' case caused system crashes (double
+- *	allocated skb's) !!!
+- */
+-static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
+-{
+-DEV_NET		*pNet;
+-SK_AC		*pAC;
+-int			Rc;	/* return code of XmitFrame */
+-
+-	pNet = netdev_priv(dev);
+-	pAC = pNet->pAC;
+-
+-	if ((!skb_shinfo(skb)->nr_frags) ||
+-		(pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
+-		/* Don't activate scatter-gather and hardware checksum */
+-
+-		if (pAC->RlmtNets == 2)
+-			Rc = XmitFrame(
+-				pAC,
+-				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+-				skb);
+-		else
+-			Rc = XmitFrame(
+-				pAC,
+-				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+-				skb);
+-	} else {
+-		/* scatter-gather and hardware TCP checksumming anabled*/
+-		if (pAC->RlmtNets == 2)
+-			Rc = XmitFrameSG(
+-				pAC,
+-				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+-				skb);
+-		else
+-			Rc = XmitFrameSG(
+-				pAC,
+-				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+-				skb);
+-	}
+-
+-	/* Transmitter out of resources? */
+-	if (Rc <= 0) {
+-		netif_stop_queue(dev);
+-	}
+-
+-	/* If not taken, give buffer ownership back to the
+-	 * queueing layer.
+-	 */
+-	if (Rc < 0)
+-		return (1);
+-
+-	dev->trans_start = jiffies;
+-	return (0);
+-} /* SkGeXmit */
+-
+-
+-/*****************************************************************************
+- *
+- * 	XmitFrame - fill one socket buffer into the transmit ring
+- *
+- * Description:
+- *	This function puts a message into the transmit descriptor ring
+- *	if there is a descriptors left.
+- *	Linux skb's consist of only one continuous buffer.
+- *	The first step locks the ring. It is held locked
+- *	all time to avoid problems with SWITCH_../PORT_RESET.
+- *	Then the descriptoris allocated.
+- *	The second part is linking the buffer to the descriptor.
+- *	At the very last, the Control field of the descriptor
+- *	is made valid for the BMU and a start TX command is given
+- *	if necessary.
+- *
+- * Returns:
+- *	> 0 - on succes: the number of bytes in the message
+- *	= 0 - on resource shortage: this frame sent or dropped, now
+- *		the ring is full ( -> set tbusy)
+- *	< 0 - on failure: other problems ( -> return failure to upper layers)
+- */
+-static int XmitFrame(
+-SK_AC 		*pAC,		/* pointer to adapter context           */
+-TX_PORT		*pTxPort,	/* pointer to struct of port to send to */
+-struct sk_buff	*pMessage)	/* pointer to send-message              */
+-{
+-	TXD		*pTxd;		/* the rxd to fill */
+-	TXD		*pOldTxd;
+-	unsigned long	 Flags;
+-	SK_U64		 PhysAddr;
+-	int		 BytesSend = pMessage->len;
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
+-
+-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+-#ifndef USE_TX_COMPLETE
+-	FreeTxDescriptors(pAC, pTxPort);
+-#endif
+-	if (pTxPort->TxdRingFree == 0) {
+-		/* 
+-		** no enough free descriptors in ring at the moment.
+-		** Maybe free'ing some old one help?
+-		*/
+-		FreeTxDescriptors(pAC, pTxPort);
+-		if (pTxPort->TxdRingFree == 0) {
+-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+-			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_TX_PROGRESS,
+-				("XmitFrame failed\n"));
+-			/* 
+-			** the desired message can not be sent
+-			** Because tbusy seems to be set, the message 
+-			** should not be freed here. It will be used 
+-			** by the scheduler of the ethernet handler 
+-			*/
+-			return (-1);
+-		}
+-	}
+-
+-	/*
+-	** If the passed socket buffer is of smaller MTU-size than 60,
+-	** copy everything into new buffer and fill all bytes between
+-	** the original packet end and the new packet end of 60 with 0x00.
+-	** This is to resolve faulty padding by the HW with 0xaa bytes.
+-	*/
+-	if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
+-		if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) {
+-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+-			return 0;
+-		}
+-		pMessage->len = C_LEN_ETHERNET_MINSIZE;
+-	}
+-
+-	/* 
+-	** advance head counter behind descriptor needed for this frame, 
+-	** so that needed descriptor is reserved from that on. The next
+-	** action will be to add the passed buffer to the TX-descriptor
+-	*/
+-	pTxd = pTxPort->pTxdRingHead;
+-	pTxPort->pTxdRingHead = pTxd->pNextTxd;
+-	pTxPort->TxdRingFree--;
+-
+-#ifdef SK_DUMP_TX
+-	DumpMsg(pMessage, "XmitFrame");
+-#endif
+-
+-	/* 
+-	** First step is to map the data to be sent via the adapter onto
+-	** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4
+-	** and 2.6 need to use pci_map_page() for that mapping.
+-	*/
+-	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+-					virt_to_page(pMessage->data),
+-					((unsigned long) pMessage->data & ~PAGE_MASK),
+-					pMessage->len,
+-					PCI_DMA_TODEVICE);
+-	pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+-	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+-	pTxd->pMBuf     = pMessage;
+-
+-	if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
+-		u16 hdrlen = skb_transport_offset(pMessage);
+-		u16 offset = hdrlen + pMessage->csum_offset;
+-
+-		if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
+-			(pAC->GIni.GIChipRev == 0) &&
+-			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
+-			pTxd->TBControl = BMU_TCP_CHECK;
+-		} else {
+-			pTxd->TBControl = BMU_UDP_CHECK;
+-		}
+-
+-		pTxd->TcpSumOfs = 0;
+-		pTxd->TcpSumSt  = hdrlen;
+-		pTxd->TcpSumWr  = offset;
+-
+-		pTxd->TBControl |= BMU_OWN | BMU_STF | 
+-				   BMU_SW  | BMU_EOF |
+-#ifdef USE_TX_COMPLETE
+-				   BMU_IRQ_EOF |
+-#endif
+-				   pMessage->len;
+-        } else {
+-		pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK | 
+-				  BMU_SW  | BMU_EOF |
+-#ifdef USE_TX_COMPLETE
+-				   BMU_IRQ_EOF |
+-#endif
+-			pMessage->len;
+-	}
+-
+-	/* 
+-	** If previous descriptor already done, give TX start cmd 
+-	*/
+-	pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd);
+-	if ((pOldTxd->TBControl & BMU_OWN) == 0) {
+-		SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+-	}	
+-
+-	/* 
+-	** after releasing the lock, the skb may immediately be free'd 
+-	*/
+-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+-	if (pTxPort->TxdRingFree != 0) {
+-		return (BytesSend);
+-	} else {
+-		return (0);
+-	}
+-
+-} /* XmitFrame */
+-
+-/*****************************************************************************
+- *
+- * 	XmitFrameSG - fill one socket buffer into the transmit ring
+- *                (use SG and TCP/UDP hardware checksumming)
+- *
+- * Description:
+- *	This function puts a message into the transmit descriptor ring
+- *	if there is a descriptors left.
+- *
+- * Returns:
+- *	> 0 - on succes: the number of bytes in the message
+- *	= 0 - on resource shortage: this frame sent or dropped, now
+- *		the ring is full ( -> set tbusy)
+- *	< 0 - on failure: other problems ( -> return failure to upper layers)
+- */
+-static int XmitFrameSG(
+-SK_AC 		*pAC,		/* pointer to adapter context           */
+-TX_PORT		*pTxPort,	/* pointer to struct of port to send to */
+-struct sk_buff	*pMessage)	/* pointer to send-message              */
+-{
+-
+-	TXD		*pTxd;
+-	TXD		*pTxdFst;
+-	TXD		*pTxdLst;
+-	int 	 	 CurrFrag;
+-	int		 BytesSend;
+-	skb_frag_t	*sk_frag;
+-	SK_U64		 PhysAddr;
+-	unsigned long	 Flags;
+-	SK_U32		 Control;
+-
+-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+-#ifndef USE_TX_COMPLETE
+-	FreeTxDescriptors(pAC, pTxPort);
+-#endif
+-	if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
+-		FreeTxDescriptors(pAC, pTxPort);
+-		if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
+-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+-			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_TX_PROGRESS,
+-				("XmitFrameSG failed - Ring full\n"));
+-				/* this message can not be sent now */
+-			return(-1);
+-		}
+-	}
+-
+-	pTxd      = pTxPort->pTxdRingHead;
+-	pTxdFst   = pTxd;
+-	pTxdLst   = pTxd;
+-	BytesSend = 0;
+-
+-	/* 
+-	** Map the first fragment (header) into the DMA-space
+-	*/
+-	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+-			virt_to_page(pMessage->data),
+-			((unsigned long) pMessage->data & ~PAGE_MASK),
+-			skb_headlen(pMessage),
+-			PCI_DMA_TODEVICE);
+-
+-	pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+-	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+-
+-	/* 
+-	** Does the HW need to evaluate checksum for TCP or UDP packets? 
+-	*/
+-	if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
+-		u16 hdrlen = skb_transport_offset(pMessage);
+-		u16 offset = hdrlen + pMessage->csum_offset;
+-
+-		Control = BMU_STFWD;
+-
+-		/* 
+-		** We have to use the opcode for tcp here,  because the
+-		** opcode for udp is not working in the hardware yet 
+-		** (Revision 2.0)
+-		*/
+-		if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
+-			(pAC->GIni.GIChipRev == 0) &&
+-			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
+-			Control |= BMU_TCP_CHECK;
+-		} else {
+-			Control |= BMU_UDP_CHECK;
+-		}
+-
+-		pTxd->TcpSumOfs = 0;
+-		pTxd->TcpSumSt  = hdrlen;
+-		pTxd->TcpSumWr  = offset;
+-	} else
+-		Control = BMU_CHECK | BMU_SW;
+-
+-	pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
+-
+-	pTxd = pTxd->pNextTxd;
+-	pTxPort->TxdRingFree--;
+-	BytesSend += skb_headlen(pMessage);
+-
+-	/* 
+-	** Browse over all SG fragments and map each of them into the DMA space
+-	*/
+-	for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) {
+-		sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag];
+-		/* 
+-		** we already have the proper value in entry
+-		*/
+-		PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+-						 sk_frag->page,
+-						 sk_frag->page_offset,
+-						 sk_frag->size,
+-						 PCI_DMA_TODEVICE);
+-
+-		pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+-		pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+-		pTxd->pMBuf     = pMessage;
+-		
+-		pTxd->TBControl = Control | BMU_OWN | sk_frag->size;
+-
+-		/* 
+-		** Do we have the last fragment? 
+-		*/
+-		if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags )  {
+-#ifdef USE_TX_COMPLETE
+-			pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
+-#else
+-			pTxd->TBControl |= BMU_EOF;
+-#endif
+-			pTxdFst->TBControl |= BMU_OWN | BMU_SW;
+-		}
+-		pTxdLst = pTxd;
+-		pTxd    = pTxd->pNextTxd;
+-		pTxPort->TxdRingFree--;
+-		BytesSend += sk_frag->size;
+-	}
+-
+-	/* 
+-	** If previous descriptor already done, give TX start cmd 
+-	*/
+-	if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) {
+-		SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+-	}
+-
+-	pTxPort->pTxdRingPrev = pTxdLst;
+-	pTxPort->pTxdRingHead = pTxd;
+-
+-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+-
+-	if (pTxPort->TxdRingFree > 0) {
+-		return (BytesSend);
+-	} else {
+-		return (0);
+-	}
+-}
+-
+-/*****************************************************************************
+- *
+- * 	FreeTxDescriptors - release descriptors from the descriptor ring
+- *
+- * Description:
+- *	This function releases descriptors from a transmit ring if they
+- *	have been sent by the BMU.
+- *	If a descriptors is sent, it can be freed and the message can
+- *	be freed, too.
+- *	The SOFTWARE controllable bit is used to prevent running around a
+- *	completely free ring for ever. If this bit is no set in the
+- *	frame (by XmitFrame), this frame has never been sent or is
+- *	already freed.
+- *	The Tx descriptor ring lock must be held while calling this function !!!
+- *
+- * Returns:
+- *	none
+- */
+-static void FreeTxDescriptors(
+-SK_AC	*pAC,		/* pointer to the adapter context */
+-TX_PORT	*pTxPort)	/* pointer to destination port structure */
+-{
+-TXD	*pTxd;		/* pointer to the checked descriptor */
+-TXD	*pNewTail;	/* pointer to 'end' of the ring */
+-SK_U32	Control;	/* TBControl field of descriptor */
+-SK_U64	PhysAddr;	/* address of DMA mapping */
+-
+-	pNewTail = pTxPort->pTxdRingTail;
+-	pTxd     = pNewTail;
+-	/*
+-	** loop forever; exits if BMU_SW bit not set in start frame
+-	** or BMU_OWN bit set in any frame
+-	*/
+-	while (1) {
+-		Control = pTxd->TBControl;
+-		if ((Control & BMU_SW) == 0) {
+-			/*
+-			** software controllable bit is set in first
+-			** fragment when given to BMU. Not set means that
+-			** this fragment was never sent or is already
+-			** freed ( -> ring completely free now).
+-			*/
+-			pTxPort->pTxdRingTail = pTxd;
+-			netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
+-			return;
+-		}
+-		if (Control & BMU_OWN) {
+-			pTxPort->pTxdRingTail = pTxd;
+-			if (pTxPort->TxdRingFree > 0) {
+-				netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
+-			}
+-			return;
+-		}
+-		
+-		/* 
+-		** release the DMA mapping, because until not unmapped
+-		** this buffer is considered being under control of the
+-		** adapter card!
+-		*/
+-		PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
+-		PhysAddr |= (SK_U64) pTxd->VDataLow;
+-		pci_unmap_page(pAC->PciDev, PhysAddr,
+-				 pTxd->pMBuf->len,
+-				 PCI_DMA_TODEVICE);
+-
+-		if (Control & BMU_EOF)
+-			DEV_KFREE_SKB_ANY(pTxd->pMBuf);	/* free message */
+-
+-		pTxPort->TxdRingFree++;
+-		pTxd->TBControl &= ~BMU_SW;
+-		pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
+-	} /* while(forever) */
+-} /* FreeTxDescriptors */
+-
+-/*****************************************************************************
+- *
+- * 	FillRxRing - fill the receive ring with valid descriptors
+- *
+- * Description:
+- *	This function fills the receive ring descriptors with data
+- *	segments and makes them valid for the BMU.
+- *	The active ring is filled completely, if possible.
+- *	The non-active ring is filled only partial to save memory.
+- *
+- * Description of rx ring structure:
+- *	head - points to the descriptor which will be used next by the BMU
+- *	tail - points to the next descriptor to give to the BMU
+- *	
+- * Returns:	N/A
+- */
+-static void FillRxRing(
+-SK_AC		*pAC,		/* pointer to the adapter context */
+-RX_PORT		*pRxPort)	/* ptr to port struct for which the ring
+-				   should be filled */
+-{
+-unsigned long	Flags;
+-
+-	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
+-	while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {
+-		if(!FillRxDescriptor(pAC, pRxPort))
+-			break;
+-	}
+-	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
+-} /* FillRxRing */
+-
+-
+-/*****************************************************************************
+- *
+- * 	FillRxDescriptor - fill one buffer into the receive ring
+- *
+- * Description:
+- *	The function allocates a new receive buffer and
+- *	puts it into the next descriptor.
+- *
+- * Returns:
+- *	SK_TRUE - a buffer was added to the ring
+- *	SK_FALSE - a buffer could not be added
+- */
+-static SK_BOOL FillRxDescriptor(
+-SK_AC		*pAC,		/* pointer to the adapter context struct */
+-RX_PORT		*pRxPort)	/* ptr to port struct of ring to fill */
+-{
+-struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
+-RXD		*pRxd;		/* the rxd to fill */
+-SK_U16		Length;		/* data fragment length */
+-SK_U64		PhysAddr;	/* physical address of a rx buffer */
+-
+-	pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);
+-	if (pMsgBlock == NULL) {
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-			SK_DBGCAT_DRV_ENTRY,
+-			("%s: Allocation of rx buffer failed !\n",
+-			pAC->dev[pRxPort->PortIndex]->name));
+-		SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex);
+-		return(SK_FALSE);
+-	}
+-	skb_reserve(pMsgBlock, 2); /* to align IP frames */
+-	/* skb allocated ok, so add buffer */
+-	pRxd = pRxPort->pRxdRingTail;
+-	pRxPort->pRxdRingTail = pRxd->pNextRxd;
+-	pRxPort->RxdRingFree--;
+-	Length = pAC->RxBufSize;
+-	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+-		virt_to_page(pMsgBlock->data),
+-		((unsigned long) pMsgBlock->data &
+-		~PAGE_MASK),
+-		pAC->RxBufSize - 2,
+-		PCI_DMA_FROMDEVICE);
+-
+-	pRxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
+-	pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+-	pRxd->pMBuf     = pMsgBlock;
+-	pRxd->RBControl = BMU_OWN       | 
+-			  BMU_STF       | 
+-			  BMU_IRQ_EOF   | 
+-			  BMU_TCP_CHECK | 
+-			  Length;
+-	return (SK_TRUE);
+-
+-} /* FillRxDescriptor */
+-
+-
+-/*****************************************************************************
+- *
+- * 	ReQueueRxBuffer - fill one buffer back into the receive ring
+- *
+- * Description:
+- *	Fill a given buffer back into the rx ring. The buffer
+- *	has been previously allocated and aligned, and its phys.
+- *	address calculated, so this is no more necessary.
+- *
+- * Returns: N/A
+- */
+-static void ReQueueRxBuffer(
+-SK_AC		*pAC,		/* pointer to the adapter context struct */
+-RX_PORT		*pRxPort,	/* ptr to port struct of ring to fill */
+-struct sk_buff	*pMsg,		/* pointer to the buffer */
+-SK_U32		PhysHigh,	/* phys address high dword */
+-SK_U32		PhysLow)	/* phys address low dword */
+-{
+-RXD		*pRxd;		/* the rxd to fill */
+-SK_U16		Length;		/* data fragment length */
+-
+-	pRxd = pRxPort->pRxdRingTail;
+-	pRxPort->pRxdRingTail = pRxd->pNextRxd;
+-	pRxPort->RxdRingFree--;
+-	Length = pAC->RxBufSize;
+-
+-	pRxd->VDataLow  = PhysLow;
+-	pRxd->VDataHigh = PhysHigh;
+-	pRxd->pMBuf     = pMsg;
+-	pRxd->RBControl = BMU_OWN       | 
+-			  BMU_STF       |
+-			  BMU_IRQ_EOF   | 
+-			  BMU_TCP_CHECK | 
+-			  Length;
+-	return;
+-} /* ReQueueRxBuffer */
+-
+-/*****************************************************************************
+- *
+- * 	ReceiveIrq - handle a receive IRQ
+- *
+- * Description:
+- *	This function is called when a receive IRQ is set.
+- *	It walks the receive descriptor ring and sends up all
+- *	frames that are complete.
+- *
+- * Returns:	N/A
+- */
+-static void ReceiveIrq(
+-	SK_AC		*pAC,			/* pointer to adapter context */
+-	RX_PORT		*pRxPort,		/* pointer to receive port struct */
+-	SK_BOOL		SlowPathLock)	/* indicates if SlowPathLock is needed */
+-{
+-RXD				*pRxd;			/* pointer to receive descriptors */
+-SK_U32			Control;		/* control field of descriptor */
+-struct sk_buff	*pMsg;			/* pointer to message holding frame */
+-struct sk_buff	*pNewMsg;		/* pointer to a new message for copying frame */
+-int				FrameLength;	/* total length of received frame */
+-SK_MBUF			*pRlmtMbuf;		/* ptr to a buffer for giving a frame to rlmt */
+-SK_EVPARA		EvPara;			/* an event parameter union */	
+-unsigned long	Flags;			/* for spin lock */
+-int				PortIndex = pRxPort->PortIndex;
+-unsigned int	Offset;
+-unsigned int	NumBytes;
+-unsigned int	ForRlmt;
+-SK_BOOL			IsBc;
+-SK_BOOL			IsMc;
+-SK_BOOL  IsBadFrame; 			/* Bad frame */
+-
+-SK_U32			FrameStat;
+-SK_U64			PhysAddr;
+-
+-rx_start:	
+-	/* do forever; exit if BMU_OWN found */
+-	for ( pRxd = pRxPort->pRxdRingHead ;
+-		  pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
+-		  pRxd = pRxd->pNextRxd,
+-		  pRxPort->pRxdRingHead = pRxd,
+-		  pRxPort->RxdRingFree ++) {
+-
+-		/*
+-		 * For a better understanding of this loop
+-		 * Go through every descriptor beginning at the head
+-		 * Please note: the ring might be completely received so the OWN bit
+-		 * set is not a good crirteria to leave that loop.
+-		 * Therefore the RingFree counter is used.
+-		 * On entry of this loop pRxd is a pointer to the Rxd that needs
+-		 * to be checked next.
+-		 */
+-
+-		Control = pRxd->RBControl;
+-	
+-		/* check if this descriptor is ready */
+-		if ((Control & BMU_OWN) != 0) {
+-			/* this descriptor is not yet ready */
+-			/* This is the usual end of the loop */
+-			/* We don't need to start the ring again */
+-			FillRxRing(pAC, pRxPort);
+-			return;
+-		}
+-                pAC->DynIrqModInfo.NbrProcessedDescr++;
+-
+-		/* get length of frame and check it */
+-		FrameLength = Control & BMU_BBC;
+-		if (FrameLength > pAC->RxBufSize) {
+-			goto rx_failed;
+-		}
+-
+-		/* check for STF and EOF */
+-		if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {
+-			goto rx_failed;
+-		}
+-
+-		/* here we have a complete frame in the ring */
+-		pMsg = pRxd->pMBuf;
+-
+-		FrameStat = pRxd->FrameStat;
+-
+-		/* check for frame length mismatch */
+-#define XMR_FS_LEN_SHIFT        18
+-#define GMR_FS_LEN_SHIFT        16
+-		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+-			if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
+-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-					SK_DBGCAT_DRV_RX_PROGRESS,
+-					("skge: Frame length mismatch (%u/%u).\n",
+-					FrameLength,
+-					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+-				goto rx_failed;
+-			}
+-		}
+-		else {
+-			if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
+-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-					SK_DBGCAT_DRV_RX_PROGRESS,
+-					("skge: Frame length mismatch (%u/%u).\n",
+-					FrameLength,
+-					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+-				goto rx_failed;
+-			}
+-		}
+-
+-		/* Set Rx Status */
+-		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+-			IsBc = (FrameStat & XMR_FS_BC) != 0;
+-			IsMc = (FrameStat & XMR_FS_MC) != 0;
+-			IsBadFrame = (FrameStat &
+-				(XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
+-		} else {
+-			IsBc = (FrameStat & GMR_FS_BC) != 0;
+-			IsMc = (FrameStat & GMR_FS_MC) != 0;
+-			IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
+-							((FrameStat & GMR_FS_RX_OK) == 0));
+-		}
+-
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
+-			("Received frame of length %d on port %d\n",
+-			FrameLength, PortIndex));
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
+-			("Number of free rx descriptors: %d\n",
+-			pRxPort->RxdRingFree));
+-/* DumpMsg(pMsg, "Rx");	*/
+-
+-		if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
+-#if 0
+-			(FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
+-#endif
+-			/* there is a receive error in this frame */
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_RX_PROGRESS,
+-				("skge: Error in received frame, dropped!\n"
+-				"Control: %x\nRxStat: %x\n",
+-				Control, FrameStat));
+-
+-			ReQueueRxBuffer(pAC, pRxPort, pMsg,
+-				pRxd->VDataHigh, pRxd->VDataLow);
+-
+-			continue;
+-		}
+-
+-		/*
+-		 * if short frame then copy data to reduce memory waste
+-		 */
+-		if ((FrameLength < SK_COPY_THRESHOLD) &&
+-			((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) {
+-			/*
+-			 * Short frame detected and allocation successfull
+-			 */
+-			/* use new skb and copy data */
+-			skb_reserve(pNewMsg, 2);
+-			skb_put(pNewMsg, FrameLength);
+-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+-			PhysAddr |= (SK_U64) pRxd->VDataLow;
+-
+-			pci_dma_sync_single_for_cpu(pAC->PciDev,
+-						    (dma_addr_t) PhysAddr,
+-						    FrameLength,
+-						    PCI_DMA_FROMDEVICE);
+-			skb_copy_to_linear_data(pNewMsg, pMsg, FrameLength);
+-
+-			pci_dma_sync_single_for_device(pAC->PciDev,
+-						       (dma_addr_t) PhysAddr,
+-						       FrameLength,
+-						       PCI_DMA_FROMDEVICE);
+-			ReQueueRxBuffer(pAC, pRxPort, pMsg,
+-				pRxd->VDataHigh, pRxd->VDataLow);
+-
+-			pMsg = pNewMsg;
+-
+-		}
+-		else {
+-			/*
+-			 * if large frame, or SKB allocation failed, pass
+-			 * the SKB directly to the networking
+-			 */
+-
+-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+-			PhysAddr |= (SK_U64) pRxd->VDataLow;
+-
+-			/* release the DMA mapping */
+-			pci_unmap_single(pAC->PciDev,
+-					 PhysAddr,
+-					 pAC->RxBufSize - 2,
+-					 PCI_DMA_FROMDEVICE);
+-
+-			/* set length in message */
+-			skb_put(pMsg, FrameLength);
+-		} /* frame > SK_COPY_TRESHOLD */
+-
+-#ifdef USE_SK_RX_CHECKSUM
+-		pMsg->csum = pRxd->TcpSums & 0xffff;
+-		pMsg->ip_summed = CHECKSUM_COMPLETE;
+-#else
+-		pMsg->ip_summed = CHECKSUM_NONE;
+-#endif
+-
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("V"));
+-		ForRlmt = SK_RLMT_RX_PROTOCOL;
+-#if 0
+-		IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
+-#endif
+-		SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
+-			IsBc, &Offset, &NumBytes);
+-		if (NumBytes != 0) {
+-#if 0
+-			IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
+-#endif
+-			SK_RLMT_LOOKAHEAD(pAC, PortIndex,
+-				&pMsg->data[Offset],
+-				IsBc, IsMc, &ForRlmt);
+-		}
+-		if (ForRlmt == SK_RLMT_RX_PROTOCOL) {
+-					SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("W"));
+-			/* send up only frames from active port */
+-			if ((PortIndex == pAC->ActivePort) ||
+-				(pAC->RlmtNets == 2)) {
+-				/* frame for upper layer */
+-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));
+-#ifdef xDEBUG
+-				DumpMsg(pMsg, "Rx");
+-#endif
+-				SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
+-					FrameLength, pRxPort->PortIndex);
+-
+-				pMsg->protocol = eth_type_trans(pMsg,
+-					pAC->dev[pRxPort->PortIndex]);
+-				netif_rx(pMsg);
+-				pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
+-			}
+-			else {
+-				/* drop frame */
+-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-					SK_DBGCAT_DRV_RX_PROGRESS,
+-					("D"));
+-				DEV_KFREE_SKB(pMsg);
+-			}
+-			
+-		} /* if not for rlmt */
+-		else {
+-			/* packet for rlmt */
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-				SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
+-			pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
+-				pAC->IoBase, FrameLength);
+-			if (pRlmtMbuf != NULL) {
+-				pRlmtMbuf->pNext = NULL;
+-				pRlmtMbuf->Length = FrameLength;
+-				pRlmtMbuf->PortIdx = PortIndex;
+-				EvPara.pParaPtr = pRlmtMbuf;
+-				memcpy((char*)(pRlmtMbuf->pData),
+-					   (char*)(pMsg->data),
+-					   FrameLength);
+-
+-				/* SlowPathLock needed? */
+-				if (SlowPathLock == SK_TRUE) {
+-					spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-					SkEventQueue(pAC, SKGE_RLMT,
+-						SK_RLMT_PACKET_RECEIVED,
+-						EvPara);
+-					pAC->CheckQueue = SK_TRUE;
+-					spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-				} else {
+-					SkEventQueue(pAC, SKGE_RLMT,
+-						SK_RLMT_PACKET_RECEIVED,
+-						EvPara);
+-					pAC->CheckQueue = SK_TRUE;
+-				}
+-
+-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+-					SK_DBGCAT_DRV_RX_PROGRESS,
+-					("Q"));
+-			}
+-			if ((pAC->dev[pRxPort->PortIndex]->flags &
+-				(IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
+-				(ForRlmt & SK_RLMT_RX_PROTOCOL) ==
+-				SK_RLMT_RX_PROTOCOL) {
+-				pMsg->protocol = eth_type_trans(pMsg,
+-					pAC->dev[pRxPort->PortIndex]);
+-				netif_rx(pMsg);
+-				pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
+-			}
+-			else {
+-				DEV_KFREE_SKB(pMsg);
+-			}
+-
+-		} /* if packet for rlmt */
+-	} /* for ... scanning the RXD ring */
+-
+-	/* RXD ring is empty -> fill and restart */
+-	FillRxRing(pAC, pRxPort);
+-	/* do not start if called from Close */
+-	if (pAC->BoardLevel > SK_INIT_DATA) {
+-		ClearAndStartRx(pAC, PortIndex);
+-	}
+-	return;
+-
+-rx_failed:
+-	/* remove error frame */
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
+-		("Schrottdescriptor, length: 0x%x\n", FrameLength));
+-
+-	/* release the DMA mapping */
+-
+-	PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+-	PhysAddr |= (SK_U64) pRxd->VDataLow;
+-	pci_unmap_page(pAC->PciDev,
+-			 PhysAddr,
+-			 pAC->RxBufSize - 2,
+-			 PCI_DMA_FROMDEVICE);
+-	DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
+-	pRxd->pMBuf = NULL;
+-	pRxPort->RxdRingFree++;
+-	pRxPort->pRxdRingHead = pRxd->pNextRxd;
+-	goto rx_start;
+-
+-} /* ReceiveIrq */
+-
+-
+-/*****************************************************************************
+- *
+- * 	ClearAndStartRx - give a start receive command to BMU, clear IRQ
+- *
+- * Description:
+- *	This function sends a start command and a clear interrupt
+- *	command for one receive queue to the BMU.
+- *
+- * Returns: N/A
+- *	none
+- */
+-static void ClearAndStartRx(
+-SK_AC	*pAC,		/* pointer to the adapter context */
+-int	PortIndex)	/* index of the receive port (XMAC) */
+-{
+-	SK_OUT8(pAC->IoBase,
+-		RxQueueAddr[PortIndex]+Q_CSR,
+-		CSR_START | CSR_IRQ_CL_F);
+-} /* ClearAndStartRx */
+-
+-
+-/*****************************************************************************
+- *
+- * 	ClearTxIrq - give a clear transmit IRQ command to BMU
+- *
+- * Description:
+- *	This function sends a clear tx IRQ command for one
+- *	transmit queue to the BMU.
+- *
+- * Returns: N/A
+- */
+-static void ClearTxIrq(
+-SK_AC	*pAC,		/* pointer to the adapter context */
+-int	PortIndex,	/* index of the transmit port (XMAC) */
+-int	Prio)		/* priority or normal queue */
+-{
+-	SK_OUT8(pAC->IoBase, 
+-		TxQueueAddr[PortIndex][Prio]+Q_CSR,
+-		CSR_IRQ_CL_F);
+-} /* ClearTxIrq */
+-
+-
+-/*****************************************************************************
+- *
+- * 	ClearRxRing - remove all buffers from the receive ring
+- *
+- * Description:
+- *	This function removes all receive buffers from the ring.
+- *	The receive BMU must be stopped before calling this function.
+- *
+- * Returns: N/A
+- */
+-static void ClearRxRing(
+-SK_AC	*pAC,		/* pointer to adapter context */
+-RX_PORT	*pRxPort)	/* pointer to rx port struct */
+-{
+-RXD		*pRxd;	/* pointer to the current descriptor */
+-unsigned long	Flags;
+-SK_U64		PhysAddr;
+-
+-	if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
+-		return;
+-	}
+-	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
+-	pRxd = pRxPort->pRxdRingHead;
+-	do {
+-		if (pRxd->pMBuf != NULL) {
+-
+-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+-			PhysAddr |= (SK_U64) pRxd->VDataLow;
+-			pci_unmap_page(pAC->PciDev,
+-					 PhysAddr,
+-					 pAC->RxBufSize - 2,
+-					 PCI_DMA_FROMDEVICE);
+-			DEV_KFREE_SKB(pRxd->pMBuf);
+-			pRxd->pMBuf = NULL;
+-		}
+-		pRxd->RBControl &= BMU_OWN;
+-		pRxd = pRxd->pNextRxd;
+-		pRxPort->RxdRingFree++;
+-	} while (pRxd != pRxPort->pRxdRingTail);
+-	pRxPort->pRxdRingTail = pRxPort->pRxdRingHead;
+-	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
+-} /* ClearRxRing */
+-
+-/*****************************************************************************
+- *
+- *	ClearTxRing - remove all buffers from the transmit ring
+- *
+- * Description:
+- *	This function removes all transmit buffers from the ring.
+- *	The transmit BMU must be stopped before calling this function
+- *	and transmitting at the upper level must be disabled.
+- *	The BMU own bit of all descriptors is cleared, the rest is
+- *	done by calling FreeTxDescriptors.
+- *
+- * Returns: N/A
+- */
+-static void ClearTxRing(
+-SK_AC	*pAC,		/* pointer to adapter context */
+-TX_PORT	*pTxPort)	/* pointer to tx prt struct */
+-{
+-TXD		*pTxd;		/* pointer to the current descriptor */
+-int		i;
+-unsigned long	Flags;
+-
+-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+-	pTxd = pTxPort->pTxdRingHead;
+-	for (i=0; i<pAC->TxDescrPerRing; i++) {
+-		pTxd->TBControl &= ~BMU_OWN;
+-		pTxd = pTxd->pNextTxd;
+-	}
+-	FreeTxDescriptors(pAC, pTxPort);
+-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+-} /* ClearTxRing */
+-
+-/*****************************************************************************
+- *
+- * 	SkGeSetMacAddr - Set the hardware MAC address
+- *
+- * Description:
+- *	This function sets the MAC address used by the adapter.
+- *
+- * Returns:
+- *	0, if everything is ok
+- *	!=0, on error
+- */
+-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
+-{
+-
+-DEV_NET *pNet = netdev_priv(dev);
+-SK_AC	*pAC = pNet->pAC;
+-
+-struct sockaddr	*addr = p;
+-unsigned long	Flags;
+-	
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeSetMacAddr starts now...\n"));
+-	if(netif_running(dev))
+-		return -EBUSY;
+-
+-	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
+-	
+-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-
+-	if (pAC->RlmtNets == 2)
+-		SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
+-			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
+-	else
+-		SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
+-			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
+-
+-	
+-	
+-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-	return 0;
+-} /* SkGeSetMacAddr */
+-
+-
+-/*****************************************************************************
+- *
+- * 	SkGeSetRxMode - set receive mode
+- *
+- * Description:
+- *	This function sets the receive mode of an adapter. The adapter
+- *	supports promiscuous mode, allmulticast mode and a number of
+- *	multicast addresses. If more multicast addresses the available
+- *	are selected, a hash function in the hardware is used.
+- *
+- * Returns:
+- *	0, if everything is ok
+- *	!=0, on error
+- */
+-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
+-{
+-
+-DEV_NET		*pNet;
+-SK_AC		*pAC;
+-
+-struct dev_mc_list	*pMcList;
+-int			i;
+-int			PortIdx;
+-unsigned long		Flags;
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeSetRxMode starts now... "));
+-
+-	pNet = netdev_priv(dev);
+-	pAC = pNet->pAC;
+-	if (pAC->RlmtNets == 1)
+-		PortIdx = pAC->ActivePort;
+-	else
+-		PortIdx = pNet->NetNr;
+-
+-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-	if (dev->flags & IFF_PROMISC) {
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-			("PROMISCUOUS mode\n"));
+-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+-			SK_PROM_MODE_LLC);
+-	} else if (dev->flags & IFF_ALLMULTI) {
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-			("ALLMULTI mode\n"));
+-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+-			SK_PROM_MODE_ALL_MC);
+-	} else {
+-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+-			SK_PROM_MODE_NONE);
+-		SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
+-
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-			("Number of MC entries: %d ", dev->mc_count));
+-		
+-		pMcList = dev->mc_list;
+-		for (i=0; i<dev->mc_count; i++, pMcList = pMcList->next) {
+-			SkAddrMcAdd(pAC, pAC->IoBase, PortIdx,
+-				(SK_MAC_ADDR*)pMcList->dmi_addr, 0);
+-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA,
+-				("%02x:%02x:%02x:%02x:%02x:%02x\n",
+-				pMcList->dmi_addr[0],
+-				pMcList->dmi_addr[1],
+-				pMcList->dmi_addr[2],
+-				pMcList->dmi_addr[3],
+-				pMcList->dmi_addr[4],
+-				pMcList->dmi_addr[5]));
+-		}
+-		SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
+-	}
+-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-	
+-	return;
+-} /* SkGeSetRxMode */
+-
+-
+-/*****************************************************************************
+- *
+- * 	SkGeChangeMtu - set the MTU to another value
+- *
+- * Description:
+- *	This function sets is called whenever the MTU size is changed
+- *	(ifconfig mtu xxx dev ethX). If the MTU is bigger than standard
+- *	ethernet MTU size, long frame support is activated.
+- *
+- * Returns:
+- *	0, if everything is ok
+- *	!=0, on error
+- */
+-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
+-{
+-DEV_NET		*pNet;
+-struct net_device *pOtherDev;
+-SK_AC		*pAC;
+-unsigned long	Flags;
+-int		i;
+-SK_EVPARA 	EvPara;
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeChangeMtu starts now...\n"));
+-
+-	pNet = netdev_priv(dev);
+-	pAC  = pNet->pAC;
+-
+-	if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
+-		return -EINVAL;
+-	}
+-
+-	if(pAC->BoardLevel != SK_INIT_RUN) {
+-		return -EINVAL;
+-	}
+-
+-#ifdef SK_DIAG_SUPPORT
+-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
+-		if (pAC->DiagFlowCtrl == SK_FALSE) {
+-			return -1; /* still in use, deny any actions of MTU */
+-		} else {
+-			pAC->DiagFlowCtrl = SK_FALSE;
+-		}
+-	}
+-#endif
+-
+-	pOtherDev = pAC->dev[1 - pNet->NetNr];
+-
+-	if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
+-	     && (NewMtu <= 1500))
+-		return 0;
+-
+-	pAC->RxBufSize = NewMtu + 32;
+-	dev->mtu = NewMtu;
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("New MTU: %d\n", NewMtu));
+-
+-	/* 
+-	** Prevent any reconfiguration while changing the MTU 
+-	** by disabling any interrupts 
+-	*/
+-	SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-
+-	/* 
+-	** Notify RLMT that any ports are to be stopped
+-	*/
+-	EvPara.Para32[0] =  0;
+-	EvPara.Para32[1] = -1;
+-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+-		EvPara.Para32[0] =  1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+-	} else {
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+-	}
+-
+-	/*
+-	** After calling the SkEventDispatcher(), RLMT is aware about
+-	** the stopped ports -> configuration can take place!
+-	*/
+-	SkEventDispatcher(pAC, pAC->IoBase);
+-
+-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+-		spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
+-		netif_stop_queue(pAC->dev[i]);
+-
+-	}
+-
+-	/*
+-	** Depending on the desired MTU size change, a different number of 
+-	** RX buffers need to be allocated
+-	*/
+-	if (NewMtu > 1500) {
+-	    /* 
+-	    ** Use less rx buffers 
+-	    */
+-	    for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+-		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+-		    pAC->RxPort[i].RxFillLimit =  pAC->RxDescrPerRing -
+-						 (pAC->RxDescrPerRing / 4);
+-		} else {
+-		    if (i == pAC->ActivePort) {
+-			pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 
+-						    (pAC->RxDescrPerRing / 4);
+-		    } else {
+-			pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 
+-						    (pAC->RxDescrPerRing / 10);
+-		    }
+-		}
+-	    }
+-	} else {
+-	    /* 
+-	    ** Use the normal amount of rx buffers 
+-	    */
+-	    for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+-		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+-		    pAC->RxPort[i].RxFillLimit = 1;
+-		} else {
+-		    if (i == pAC->ActivePort) {
+-			pAC->RxPort[i].RxFillLimit = 1;
+-		    } else {
+-			pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+-						    (pAC->RxDescrPerRing / 4);
+-		    }
+-		}
+-	    }
+-	}
+-	
+-	SkGeDeInit(pAC, pAC->IoBase);
+-
+-	/*
+-	** enable/disable hardware support for long frames
+-	*/
+-	if (NewMtu > 1500) {
+-// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
+-		pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
+-	} else {
+-	    if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+-		pAC->GIni.GIPortUsage = SK_MUL_LINK;
+-	    } else {
+-		pAC->GIni.GIPortUsage = SK_RED_LINK;
+-	    }
+-	}
+-
+-	SkGeInit(   pAC, pAC->IoBase, SK_INIT_IO);
+-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
+-	SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
+-	
+-	/*
+-	** tschilling:
+-	** Speed and others are set back to default in level 1 init!
+-	*/
+-	GetConfiguration(pAC);
+-	
+-	SkGeInit(   pAC, pAC->IoBase, SK_INIT_RUN);
+-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_RUN);
+-	SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN);
+-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN);
+-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN);
+-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN);
+-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN);
+-
+-	/*
+-	** clear and reinit the rx rings here
+-	*/
+-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+-		ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
+-		ClearRxRing(pAC, &pAC->RxPort[i]);
+-		FillRxRing(pAC, &pAC->RxPort[i]);
+-
+-		/* 
+-		** Enable transmit descriptor polling
+-		*/
+-		SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
+-		FillRxRing(pAC, &pAC->RxPort[i]);
+-	};
+-
+-	SkGeYellowLED(pAC, pAC->IoBase, 1);
+-	SkDimEnableModerationIfNeeded(pAC);	
+-	SkDimDisplayModerationSettings(pAC);
+-
+-	netif_start_queue(pAC->dev[pNet->PortNr]);
+-	for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
+-		spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
+-	}
+-
+-	/* 
+-	** Enable Interrupts again 
+-	*/
+-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+-	SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
+-
+-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+-	SkEventDispatcher(pAC, pAC->IoBase);
+-
+-	/* 
+-	** Notify RLMT about the changing and restarting one (or more) ports
+-	*/
+-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+-		EvPara.Para32[0] = pAC->RlmtNets;
+-		EvPara.Para32[1] = -1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara);
+-		EvPara.Para32[0] = pNet->PortNr;
+-		EvPara.Para32[1] = -1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+-			
+-		if (netif_running(pOtherDev)) {
+-			DEV_NET *pOtherNet = netdev_priv(pOtherDev);
+-			EvPara.Para32[0] = pOtherNet->PortNr;
+-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+-		}
+-	} else {
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+-	}
+-
+-	SkEventDispatcher(pAC, pAC->IoBase);
+-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-	
+-	/*
+-	** While testing this driver with latest kernel 2.5 (2.5.70), it 
+-	** seems as if upper layers have a problem to handle a successful
+-	** return value of '0'. If such a zero is returned, the complete 
+-	** system hangs for several minutes (!), which is in acceptable.
+-	**
+-	** Currently it is not clear, what the exact reason for this problem
+-	** is. The implemented workaround for 2.5 is to return the desired 
+-	** new MTU size if all needed changes for the new MTU size where 
+-	** performed. In kernels 2.2 and 2.4, a zero value is returned,
+-	** which indicates the successful change of the mtu-size.
+-	*/
+-	return NewMtu;
+-
+-} /* SkGeChangeMtu */
+-
+-
+-/*****************************************************************************
+- *
+- * 	SkGeStats - return ethernet device statistics
+- *
+- * Description:
+- *	This function return statistic data about the ethernet device
+- *	to the operating system.
+- *
+- * Returns:
+- *	pointer to the statistic structure.
+- */
+-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
+-{
+-DEV_NET *pNet = netdev_priv(dev);
+-SK_AC	*pAC = pNet->pAC;
+-SK_PNMI_STRUCT_DATA *pPnmiStruct;       /* structure for all Pnmi-Data */
+-SK_PNMI_STAT    *pPnmiStat;             /* pointer to virtual XMAC stat. data */
+-SK_PNMI_CONF    *pPnmiConf;             /* pointer to virtual link config. */
+-unsigned int    Size;                   /* size of pnmi struct */
+-unsigned long	Flags;			/* for spin lock */
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeStats starts now...\n"));
+-	pPnmiStruct = &pAC->PnmiStruct;
+-
+-#ifdef SK_DIAG_SUPPORT
+-        if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
+-                (pAC->BoardLevel == SK_INIT_RUN)) {
+-#endif
+-        SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA));
+-        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-        Size = SK_PNMI_STRUCT_SIZE;
+-		SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr);
+-        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-#ifdef SK_DIAG_SUPPORT
+-	}
+-#endif
+-
+-        pPnmiStat = &pPnmiStruct->Stat[0];
+-        pPnmiConf = &pPnmiStruct->Conf[0];
+-
+-	pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF;
+-	pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
+-	pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
+-	pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
+-	
+-        if (dev->mtu <= 1500) {
+-                pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+-        } else {
+-                pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
+-                        pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
+-	}
+-
+-
+-	if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12)
+-		pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts;
+-
+-	pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
+-	pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
+-	pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
+-	pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF;
+-	pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
+-
+-	/* detailed rx_errors: */
+-	pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF;
+-	pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
+-	pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF;
+-	pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF;
+-	pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
+-	pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF;
+-
+-	/* detailed tx_errors */
+-	pAC->stats.tx_aborted_errors = (SK_U32) 0;
+-	pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
+-	pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF;
+-	pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
+-	pAC->stats.tx_window_errors = (SK_U32) 0;
+-
+-	return(&pAC->stats);
+-} /* SkGeStats */
+-
+-/*
+- * Basic MII register access
+- */
+-static int SkGeMiiIoctl(struct net_device *dev,
+-			struct mii_ioctl_data *data, int cmd)
+-{
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-	SK_IOC IoC = pAC->IoBase;
+-	int Port = pNet->PortNr;
+-	SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
+-	unsigned long Flags;
+-	int err = 0;
+-	int reg = data->reg_num & 0x1f;
+-	SK_U16 val = data->val_in;
+-
+-	if (!netif_running(dev))
+-		return -ENODEV;	/* Phy still in reset */
+-
+-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-	switch(cmd) {
+-	case SIOCGMIIPHY:
+-		data->phy_id = pPrt->PhyAddr;
+-
+-		/* fallthru */
+-	case SIOCGMIIREG:
+-		if (pAC->GIni.GIGenesis)
+-			SkXmPhyRead(pAC, IoC, Port, reg, &val);
+-		else
+-			SkGmPhyRead(pAC, IoC, Port, reg, &val);
+-
+-		data->val_out = val;
+-		break;
+-
+-	case SIOCSMIIREG:
+-		if (!capable(CAP_NET_ADMIN))
+-			err = -EPERM;
+-
+-		else if (pAC->GIni.GIGenesis)
+-			SkXmPhyWrite(pAC, IoC, Port, reg, val);
+-		else
+-			SkGmPhyWrite(pAC, IoC, Port, reg, val);
+-		break;
+-	default:
+-		err = -EOPNOTSUPP;
+-	}
+-        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-	return err;
+-}
+-
+-
+-/*****************************************************************************
+- *
+- * 	SkGeIoctl - IO-control function
+- *
+- * Description:
+- *	This function is called if an ioctl is issued on the device.
+- *	There are three subfunction for reading, writing and test-writing
+- *	the private MIB data structure (useful for SysKonnect-internal tools).
+- *
+- * Returns:
+- *	0, if everything is ok
+- *	!=0, on error
+- */
+-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
+-{
+-DEV_NET		*pNet;
+-SK_AC		*pAC;
+-void		*pMemBuf;
+-struct pci_dev  *pdev = NULL;
+-SK_GE_IOCTL	Ioctl;
+-unsigned int	Err = 0;
+-int		Size = 0;
+-int             Ret = 0;
+-unsigned int	Length = 0;
+-int		HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeIoctl starts now...\n"));
+-
+-	pNet = netdev_priv(dev);
+-	pAC = pNet->pAC;
+-	
+-	if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG)
+-	    return SkGeMiiIoctl(dev, if_mii(rq), cmd);
+-
+-	if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
+-		return -EFAULT;
+-	}
+-
+-	switch(cmd) {
+-	case SK_IOCTL_SETMIB:
+-	case SK_IOCTL_PRESETMIB:
+-		if (!capable(CAP_NET_ADMIN)) return -EPERM;
+- 	case SK_IOCTL_GETMIB:
+-		if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
+-			Ioctl.Len<sizeof(pAC->PnmiStruct)?
+-			Ioctl.Len : sizeof(pAC->PnmiStruct))) {
+-			return -EFAULT;
+-		}
+-		Size = SkGeIocMib(pNet, Ioctl.Len, cmd);
+-		if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct,
+-			Ioctl.Len<Size? Ioctl.Len : Size)) {
+-			return -EFAULT;
+-		}
+-		Ioctl.Len = Size;
+-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+-			return -EFAULT;
+-		}
+-		break;
+-	case SK_IOCTL_GEN:
+-		if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
+-			Length = Ioctl.Len;
+-		} else {
+-			Length = sizeof(pAC->PnmiStruct) + HeaderLength;
+-		}
+-		if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
+-			return -ENOMEM;
+-		}
+-		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
+-			Err = -EFAULT;
+-			goto fault_gen;
+-		}
+-		if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
+-			Err = -EFAULT;
+-			goto fault_gen;
+-		}
+-		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
+-			Err = -EFAULT;
+-			goto fault_gen;
+-		}
+-		Ioctl.Len = Length;
+-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+-			Err = -EFAULT;
+-			goto fault_gen;
+-		}
+-fault_gen:
+-		kfree(pMemBuf); /* cleanup everything */
+-		break;
+-#ifdef SK_DIAG_SUPPORT
+-       case SK_IOCTL_DIAG:
+-		if (!capable(CAP_NET_ADMIN)) return -EPERM;
+-		if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
+-			Length = Ioctl.Len;
+-		} else {
+-			Length = sizeof(pAC->PnmiStruct) + HeaderLength;
+-		}
+-		if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
+-			return -ENOMEM;
+-		}
+-		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
+-			Err = -EFAULT;
+-			goto fault_diag;
+-		}
+-		pdev = pAC->PciDev;
+-		Length = 3 * sizeof(SK_U32);  /* Error, Bus and Device */
+-		/* 
+-		** While coding this new IOCTL interface, only a few lines of code
+-		** are to to be added. Therefore no dedicated function has been 
+-		** added. If more functionality is added, a separate function 
+-		** should be used...
+-		*/
+-		* ((SK_U32 *)pMemBuf) = 0;
+-		* ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
+-		* ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
+-		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
+-			Err = -EFAULT;
+-			goto fault_diag;
+-		}
+-		Ioctl.Len = Length;
+-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+-			Err = -EFAULT;
+-			goto fault_diag;
+-		}
+-fault_diag:
+-		kfree(pMemBuf); /* cleanup everything */
+-		break;
+-#endif
+-	default:
+-		Err = -EOPNOTSUPP;
+-	}
+-
+-	return(Err);
+-
+-} /* SkGeIoctl */
+-
+-
+-/*****************************************************************************
+- *
+- * 	SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message
+- *
+- * Description:
+- *	This function reads/writes the MIB data using PNMI (Private Network
+- *	Management Interface).
+- *	The destination for the data must be provided with the
+- *	ioctl call and is given to the driver in the form of
+- *	a user space address.
+- *	Copying from the user-provided data area into kernel messages
+- *	and back is done by copy_from_user and copy_to_user calls in
+- *	SkGeIoctl.
+- *
+- * Returns:
+- *	returned size from PNMI call
+- */
+-static int SkGeIocMib(
+-DEV_NET		*pNet,	/* pointer to the adapter context */
+-unsigned int	Size,	/* length of ioctl data */
+-int		mode)	/* flag for set/preset */
+-{
+-unsigned long	Flags;	/* for spin lock */
+-SK_AC		*pAC;
+-
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("SkGeIocMib starts now...\n"));
+-	pAC = pNet->pAC;
+-	/* access MIB */
+-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-	switch(mode) {
+-	case SK_IOCTL_GETMIB:
+-		SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
+-			pNet->NetNr);
+-		break;
+-	case SK_IOCTL_PRESETMIB:
+-		SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
+-			pNet->NetNr);
+-		break;
+-	case SK_IOCTL_SETMIB:
+-		SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
+-			pNet->NetNr);
+-		break;
+-	default:
+-		break;
+-	}
+-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+-		("MIB data access succeeded\n"));
+-	return (Size);
+-} /* SkGeIocMib */
+-
+-
+-/*****************************************************************************
+- *
+- * 	GetConfiguration - read configuration information
+- *
+- * Description:
+- *	This function reads per-adapter configuration information from
+- *	the options provided on the command line.
+- *
+- * Returns:
+- *	none
+- */
+-static void GetConfiguration(
+-SK_AC	*pAC)	/* pointer to the adapter context structure */
+-{
+-SK_I32	Port;		/* preferred port */
+-SK_BOOL	AutoSet;
+-SK_BOOL DupSet;
+-int	LinkSpeed          = SK_LSPEED_AUTO;	/* Link speed */
+-int	AutoNeg            = 1;			/* autoneg off (0) or on (1) */
+-int	DuplexCap          = 0;			/* 0=both,1=full,2=half */
+-int	FlowCtrl           = SK_FLOW_MODE_SYM_OR_REM;	/* FlowControl  */
+-int	MSMode             = SK_MS_MODE_AUTO;	/* master/slave mode    */
+-
+-SK_BOOL IsConTypeDefined   = SK_TRUE;
+-SK_BOOL IsLinkSpeedDefined = SK_TRUE;
+-SK_BOOL IsFlowCtrlDefined  = SK_TRUE;
+-SK_BOOL IsRoleDefined      = SK_TRUE;
+-SK_BOOL IsModeDefined      = SK_TRUE;
+-/*
+- *	The two parameters AutoNeg. and DuplexCap. map to one configuration
+- *	parameter. The mapping is described by this table:
+- *	DuplexCap ->	|	both	|	full	|	half	|
+- *	AutoNeg		|		|		|		|
+- *	-----------------------------------------------------------------
+- *	Off		|    illegal	|	Full	|	Half	|
+- *	-----------------------------------------------------------------
+- *	On		|   AutoBoth	|   AutoFull	|   AutoHalf	|
+- *	-----------------------------------------------------------------
+- *	Sense		|   AutoSense	|   AutoSense	|   AutoSense	|
+- */
+-int	Capabilities[3][3] =
+-		{ {                -1, SK_LMODE_FULL     , SK_LMODE_HALF     },
+-		  {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
+-		  {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
+-
+-#define DC_BOTH	0
+-#define DC_FULL 1
+-#define DC_HALF 2
+-#define AN_OFF	0
+-#define AN_ON	1
+-#define AN_SENS	2
+-#define M_CurrPort pAC->GIni.GP[Port]
+-
+-
+-	/*
+-	** Set the default values first for both ports!
+-	*/
+-	for (Port = 0; Port < SK_MAX_MACS; Port++) {
+-		M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+-		M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+-		M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+-		M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
+-	}
+-
+-	/*
+-	** Check merged parameter ConType. If it has not been used,
+-	** verify any other parameter (e.g. AutoNeg) and use default values. 
+-	**
+-	** Stating both ConType and other lowlevel link parameters is also
+-	** possible. If this is the case, the passed ConType-parameter is 
+-	** overwritten by the lowlevel link parameter.
+-	**
+-	** The following settings are used for a merged ConType-parameter:
+-	**
+-	** ConType   DupCap   AutoNeg   FlowCtrl      Role      Speed
+-	** -------   ------   -------   --------   ----------   -----
+-	**  Auto      Both      On      SymOrRem      Auto       Auto
+-	**  100FD     Full      Off       None      <ignored>    100
+-	**  100HD     Half      Off       None      <ignored>    100
+-	**  10FD      Full      Off       None      <ignored>    10
+-	**  10HD      Half      Off       None      <ignored>    10
+-	** 
+-	** This ConType parameter is used for all ports of the adapter!
+-	*/
+-        if ( (ConType != NULL)                && 
+-	     (pAC->Index < SK_MAX_CARD_PARAM) &&
+-	     (ConType[pAC->Index] != NULL) ) {
+-
+-			/* Check chipset family */
+-			if ((!pAC->ChipsetType) && 
+-				(strcmp(ConType[pAC->Index],"Auto")!=0) &&
+-				(strcmp(ConType[pAC->Index],"")!=0)) {
+-				/* Set the speed parameter back */
+-					printk("sk98lin: Illegal value \"%s\" " 
+-							"for ConType."
+-							" Using Auto.\n", 
+-							ConType[pAC->Index]);
+-
+-					sprintf(ConType[pAC->Index], "Auto");	
+-			}
+-
+-				if (strcmp(ConType[pAC->Index],"")==0) {
+-			IsConTypeDefined = SK_FALSE; /* No ConType defined */
+-				} else if (strcmp(ConType[pAC->Index],"Auto")==0) {
+-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+-			M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+-			M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
+-		    }
+-                } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
+-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+-			M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
+-		    }
+-                } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
+-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+-			M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
+-		    }
+-                } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
+-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+-			M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
+-		    }
+-                } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
+-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
+-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
+-			M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
+-		    }
+-                } else { 
+-		    printk("sk98lin: Illegal value \"%s\" for ConType\n", 
+-			ConType[pAC->Index]);
+-		    IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
+-		}
+-        } else {
+-	    IsConTypeDefined = SK_FALSE; /* No ConType defined */
+-	}
+-
+-	/*
+-	** Parse any parameter settings for port A:
+-	** a) any LinkSpeed stated?
+-	*/
+-	if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		Speed_A[pAC->Index] != NULL) {
+-		if (strcmp(Speed_A[pAC->Index],"")==0) {
+-		    IsLinkSpeedDefined = SK_FALSE;
+-		} else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
+-		    LinkSpeed = SK_LSPEED_AUTO;
+-		} else if (strcmp(Speed_A[pAC->Index],"10")==0) {
+-		    LinkSpeed = SK_LSPEED_10MBPS;
+-		} else if (strcmp(Speed_A[pAC->Index],"100")==0) {
+-		    LinkSpeed = SK_LSPEED_100MBPS;
+-		} else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
+-		    LinkSpeed = SK_LSPEED_1000MBPS;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for Speed_A\n",
+-			Speed_A[pAC->Index]);
+-		    IsLinkSpeedDefined = SK_FALSE;
+-		}
+-	} else {
+-	    IsLinkSpeedDefined = SK_FALSE;
+-	}
+-
+-	/* 
+-	** Check speed parameter: 
+-	**    Only copper type adapter and GE V2 cards 
+-	*/
+-	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
+-		((LinkSpeed != SK_LSPEED_AUTO) &&
+-		(LinkSpeed != SK_LSPEED_1000MBPS))) {
+-		printk("sk98lin: Illegal value for Speed_A. "
+-			"Not a copper card or GE V2 card\n    Using "
+-			"speed 1000\n");
+-		LinkSpeed = SK_LSPEED_1000MBPS;
+-	}
+-	
+-	/*	
+-	** Decide whether to set new config value if somethig valid has
+-	** been received.
+-	*/
+-	if (IsLinkSpeedDefined) {
+-		pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
+-	} 
+-
+-	/* 
+-	** b) Any Autonegotiation and DuplexCapabilities set?
+-	**    Please note that both belong together...
+-	*/
+-	AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
+-	AutoSet = SK_FALSE;
+-	if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		AutoNeg_A[pAC->Index] != NULL) {
+-		AutoSet = SK_TRUE;
+-		if (strcmp(AutoNeg_A[pAC->Index],"")==0) {
+-		    AutoSet = SK_FALSE;
+-		} else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
+-		    AutoNeg = AN_ON;
+-		} else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
+-		    AutoNeg = AN_OFF;
+-		} else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
+-		    AutoNeg = AN_SENS;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n",
+-			AutoNeg_A[pAC->Index]);
+-		}
+-	}
+-
+-	DuplexCap = DC_BOTH;
+-	DupSet    = SK_FALSE;
+-	if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		DupCap_A[pAC->Index] != NULL) {
+-		DupSet = SK_TRUE;
+-		if (strcmp(DupCap_A[pAC->Index],"")==0) {
+-		    DupSet = SK_FALSE;
+-		} else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
+-		    DuplexCap = DC_BOTH;
+-		} else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
+-		    DuplexCap = DC_FULL;
+-		} else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
+-		    DuplexCap = DC_HALF;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for DupCap_A\n",
+-			DupCap_A[pAC->Index]);
+-		}
+-	}
+-
+-	/* 
+-	** Check for illegal combinations 
+-	*/
+-	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
+-		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
+-		(DuplexCap == SK_LMODE_STAT_HALF)) &&
+-		(pAC->ChipsetType)) {
+-		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
+-					"    Using Full Duplex.\n");
+-				DuplexCap = DC_FULL;
+-	}
+-
+-	if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
+-		printk("sk98lin, Port A: DuplexCapabilities"
+-			" ignored using Sense mode\n");
+-	}
+-
+-	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
+-		printk("sk98lin: Port A: Illegal combination"
+-			" of values AutoNeg. and DuplexCap.\n    Using "
+-			"Full Duplex\n");
+-		DuplexCap = DC_FULL;
+-	}
+-
+-	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
+-		DuplexCap = DC_FULL;
+-	}
+-	
+-	if (!AutoSet && DupSet) {
+-		printk("sk98lin: Port A: Duplex setting not"
+-			" possible in\n    default AutoNegotiation mode"
+-			" (Sense).\n    Using AutoNegotiation On\n");
+-		AutoNeg = AN_ON;
+-	}
+-	
+-	/* 
+-	** set the desired mode 
+-	*/
+-	if (AutoSet || DupSet) {
+-	    pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+-	}
+-	
+-	/* 
+-	** c) Any Flowcontrol-parameter set?
+-	*/
+-	if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		FlowCtrl_A[pAC->Index] != NULL) {
+-		if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) {
+-		    IsFlowCtrlDefined = SK_FALSE;
+-		} else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
+-		    FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+-		} else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
+-		    FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+-		} else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
+-		    FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+-		} else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
+-		    FlowCtrl = SK_FLOW_MODE_NONE;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n",
+-                        FlowCtrl_A[pAC->Index]);
+-		    IsFlowCtrlDefined = SK_FALSE;
+-		}
+-	} else {
+-	   IsFlowCtrlDefined = SK_FALSE;
+-	}
+-
+-	if (IsFlowCtrlDefined) {
+-	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
+-		printk("sk98lin: Port A: FlowControl"
+-			" impossible without AutoNegotiation,"
+-			" disabled\n");
+-		FlowCtrl = SK_FLOW_MODE_NONE;
+-	    }
+-	    pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
+-	}
+-
+-	/*
+-	** d) What is with the RoleParameter?
+-	*/
+-	if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		Role_A[pAC->Index] != NULL) {
+-		if (strcmp(Role_A[pAC->Index],"")==0) {
+-		   IsRoleDefined = SK_FALSE;
+-		} else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
+-		    MSMode = SK_MS_MODE_AUTO;
+-		} else if (strcmp(Role_A[pAC->Index],"Master")==0) {
+-		    MSMode = SK_MS_MODE_MASTER;
+-		} else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
+-		    MSMode = SK_MS_MODE_SLAVE;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for Role_A\n",
+-			Role_A[pAC->Index]);
+-		    IsRoleDefined = SK_FALSE;
+-		}
+-	} else {
+-	   IsRoleDefined = SK_FALSE;
+-	}
+-
+-	if (IsRoleDefined == SK_TRUE) {
+-	    pAC->GIni.GP[0].PMSMode = MSMode;
+-	}
+-	
+-
+-	
+-	/* 
+-	** Parse any parameter settings for port B:
+-	** a) any LinkSpeed stated?
+-	*/
+-	IsConTypeDefined   = SK_TRUE;
+-	IsLinkSpeedDefined = SK_TRUE;
+-	IsFlowCtrlDefined  = SK_TRUE;
+-	IsModeDefined      = SK_TRUE;
+-
+-	if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		Speed_B[pAC->Index] != NULL) {
+-		if (strcmp(Speed_B[pAC->Index],"")==0) {
+-		    IsLinkSpeedDefined = SK_FALSE;
+-		} else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
+-		    LinkSpeed = SK_LSPEED_AUTO;
+-		} else if (strcmp(Speed_B[pAC->Index],"10")==0) {
+-		    LinkSpeed = SK_LSPEED_10MBPS;
+-		} else if (strcmp(Speed_B[pAC->Index],"100")==0) {
+-		    LinkSpeed = SK_LSPEED_100MBPS;
+-		} else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
+-		    LinkSpeed = SK_LSPEED_1000MBPS;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for Speed_B\n",
+-			Speed_B[pAC->Index]);
+-		    IsLinkSpeedDefined = SK_FALSE;
+-		}
+-	} else {
+-	    IsLinkSpeedDefined = SK_FALSE;
+-	}
+-
+-	/* 
+-	** Check speed parameter:
+-	**    Only copper type adapter and GE V2 cards 
+-	*/
+-	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
+-		((LinkSpeed != SK_LSPEED_AUTO) &&
+-		(LinkSpeed != SK_LSPEED_1000MBPS))) {
+-		printk("sk98lin: Illegal value for Speed_B. "
+-			"Not a copper card or GE V2 card\n    Using "
+-			"speed 1000\n");
+-		LinkSpeed = SK_LSPEED_1000MBPS;
+-	}
+-
+-	/*      
+-	** Decide whether to set new config value if somethig valid has
+-	** been received.
+-	*/
+-        if (IsLinkSpeedDefined) {
+-	    pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
+-	}
+-
+-	/* 
+-	** b) Any Autonegotiation and DuplexCapabilities set?
+-	**    Please note that both belong together...
+-	*/
+-	AutoNeg = AN_SENS; /* default: do auto Sense */
+-	AutoSet = SK_FALSE;
+-	if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		AutoNeg_B[pAC->Index] != NULL) {
+-		AutoSet = SK_TRUE;
+-		if (strcmp(AutoNeg_B[pAC->Index],"")==0) {
+-		    AutoSet = SK_FALSE;
+-		} else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
+-		    AutoNeg = AN_ON;
+-		} else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
+-		    AutoNeg = AN_OFF;
+-		} else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
+-		    AutoNeg = AN_SENS;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n",
+-			AutoNeg_B[pAC->Index]);
+-		}
+-	}
+-
+-	DuplexCap = DC_BOTH;
+-	DupSet    = SK_FALSE;
+-	if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		DupCap_B[pAC->Index] != NULL) {
+-		DupSet = SK_TRUE;
+-		if (strcmp(DupCap_B[pAC->Index],"")==0) {
+-		    DupSet = SK_FALSE;
+-		} else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
+-		    DuplexCap = DC_BOTH;
+-		} else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
+-		    DuplexCap = DC_FULL;
+-		} else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
+-		    DuplexCap = DC_HALF;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for DupCap_B\n",
+-			DupCap_B[pAC->Index]);
+-		}
+-	}
+-
+-	
+-	/* 
+-	** Check for illegal combinations 
+-	*/
+-	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
+-		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
+-		(DuplexCap == SK_LMODE_STAT_HALF)) &&
+-		(pAC->ChipsetType)) {
+-		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
+-					"    Using Full Duplex.\n");
+-				DuplexCap = DC_FULL;
+-	}
+-
+-	if (AutoSet && AutoNeg==AN_SENS && DupSet) {
+-		printk("sk98lin, Port B: DuplexCapabilities"
+-			" ignored using Sense mode\n");
+-	}
+-
+-	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
+-		printk("sk98lin: Port B: Illegal combination"
+-			" of values AutoNeg. and DuplexCap.\n    Using "
+-			"Full Duplex\n");
+-		DuplexCap = DC_FULL;
+-	}
+-
+-	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
+-		DuplexCap = DC_FULL;
+-	}
+-	
+-	if (!AutoSet && DupSet) {
+-		printk("sk98lin: Port B: Duplex setting not"
+-			" possible in\n    default AutoNegotiation mode"
+-			" (Sense).\n    Using AutoNegotiation On\n");
+-		AutoNeg = AN_ON;
+-	}
+-
+-	/* 
+-	** set the desired mode 
+-	*/
+-	if (AutoSet || DupSet) {
+-	    pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+-	}
+-
+-	/*
+-	** c) Any FlowCtrl parameter set?
+-	*/
+-	if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		FlowCtrl_B[pAC->Index] != NULL) {
+-		if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) {
+-		    IsFlowCtrlDefined = SK_FALSE;
+-		} else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
+-		    FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+-		} else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
+-		    FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+-		} else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
+-		    FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+-		} else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
+-		    FlowCtrl = SK_FLOW_MODE_NONE;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n",
+-			FlowCtrl_B[pAC->Index]);
+-		    IsFlowCtrlDefined = SK_FALSE;
+-		}
+-	} else {
+-		IsFlowCtrlDefined = SK_FALSE;
+-	}
+-
+-	if (IsFlowCtrlDefined) {
+-	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
+-		printk("sk98lin: Port B: FlowControl"
+-			" impossible without AutoNegotiation,"
+-			" disabled\n");
+-		FlowCtrl = SK_FLOW_MODE_NONE;
+-	    }
+-	    pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
+-	}
+-
+-	/*
+-	** d) What is the RoleParameter?
+-	*/
+-	if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		Role_B[pAC->Index] != NULL) {
+-		if (strcmp(Role_B[pAC->Index],"")==0) {
+-		    IsRoleDefined = SK_FALSE;
+-		} else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
+-		    MSMode = SK_MS_MODE_AUTO;
+-		} else if (strcmp(Role_B[pAC->Index],"Master")==0) {
+-		    MSMode = SK_MS_MODE_MASTER;
+-		} else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
+-		    MSMode = SK_MS_MODE_SLAVE;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for Role_B\n",
+-			Role_B[pAC->Index]);
+-		    IsRoleDefined = SK_FALSE;
+-		}
+-	} else {
+-	    IsRoleDefined = SK_FALSE;
+-	}
+-
+-	if (IsRoleDefined) {
+-	    pAC->GIni.GP[1].PMSMode = MSMode;
+-	}
+-	
+-	/*
+-	** Evaluate settings for both ports
+-	*/
+-	pAC->ActivePort = 0;
+-	if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		PrefPort[pAC->Index] != NULL) {
+-		if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */
+-			pAC->ActivePort             =  0;
+-			pAC->Rlmt.Net[0].Preference = -1; /* auto */
+-			pAC->Rlmt.Net[0].PrefPort   =  0;
+-		} else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
+-			/*
+-			** do not set ActivePort here, thus a port
+-			** switch is issued after net up.
+-			*/
+-			Port                        = 0;
+-			pAC->Rlmt.Net[0].Preference = Port;
+-			pAC->Rlmt.Net[0].PrefPort   = Port;
+-		} else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
+-			/*
+-			** do not set ActivePort here, thus a port
+-			** switch is issued after net up.
+-			*/
+-			if (pAC->GIni.GIMacsFound == 1) {
+-				printk("sk98lin: Illegal value \"B\" for PrefPort.\n"
+-					"      Port B not available on single port adapters.\n");
+-
+-				pAC->ActivePort             =  0;
+-				pAC->Rlmt.Net[0].Preference = -1; /* auto */
+-				pAC->Rlmt.Net[0].PrefPort   =  0;
+-			} else {
+-				Port                        = 1;
+-				pAC->Rlmt.Net[0].Preference = Port;
+-				pAC->Rlmt.Net[0].PrefPort   = Port;
+-			}
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for PrefPort\n",
+-			PrefPort[pAC->Index]);
+-		}
+-	}
+-
+-	pAC->RlmtNets = 1;
+-
+-	if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+-		RlmtMode[pAC->Index] != NULL) {
+-		if (strcmp(RlmtMode[pAC->Index], "") == 0) {
+-			pAC->RlmtMode = 0;
+-		} else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
+-			pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+-		} else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
+-			pAC->RlmtMode = SK_RLMT_CHECK_LINK |
+-					SK_RLMT_CHECK_LOC_LINK;
+-		} else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
+-			pAC->RlmtMode = SK_RLMT_CHECK_LINK     |
+-					SK_RLMT_CHECK_LOC_LINK |
+-					SK_RLMT_CHECK_SEG;
+-		} else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
+-			(pAC->GIni.GIMacsFound == 2)) {
+-			pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+-			pAC->RlmtNets = 2;
+-		} else {
+-		    printk("sk98lin: Illegal value \"%s\" for"
+-			" RlmtMode, using default\n", 
+-			RlmtMode[pAC->Index]);
+-			pAC->RlmtMode = 0;
+-		}
+-	} else {
+-		pAC->RlmtMode = 0;
+-	}
+-	
+-	/*
+-	** Check the interrupt moderation parameters
+-	*/
+-	if (Moderation[pAC->Index] != NULL) {
+-		if (strcmp(Moderation[pAC->Index], "") == 0) {
+-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+-		} else if (strcmp(Moderation[pAC->Index], "Static") == 0) {
+-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
+-		} else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) {
+-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC;
+-		} else if (strcmp(Moderation[pAC->Index], "None") == 0) {
+-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+-		} else {
+-	   		printk("sk98lin: Illegal value \"%s\" for Moderation.\n"
+-				"      Disable interrupt moderation.\n",
+-				Moderation[pAC->Index]);
+-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+-		}
+-	} else {
+-		pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+-	}
+-
+-	if (Stats[pAC->Index] != NULL) {
+-		if (strcmp(Stats[pAC->Index], "Yes") == 0) {
+-			pAC->DynIrqModInfo.DisplayStats = SK_TRUE;
+-		} else {
+-			pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
+-		}
+-	} else {
+-		pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
+-	}
+-
+-	if (ModerationMask[pAC->Index] != NULL) {
+-		if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
+-		} else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY;
+-		} else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY;
+-		} else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
+-		} else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
+-		} else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+-		} else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+-		} else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
+-		} else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
+-		} else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+-		} else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+-		} else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+-		} else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+-		} else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+-		} else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) {
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+-		} else { /* some rubbish */
+-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
+-		}
+-	} else {  /* operator has stated nothing */
+-		pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+-	}
+-
+-	if (AutoSizing[pAC->Index] != NULL) {
+-		if (strcmp(AutoSizing[pAC->Index], "On") == 0) {
+-			pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+-		} else {
+-			pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+-		}
+-	} else {  /* operator has stated nothing */
+-		pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+-	}
+-
+-	if (IntsPerSec[pAC->Index] != 0) {
+-		if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) || 
+-			(IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) {
+-	   		printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n"
+-				"      Using default value of %i.\n", 
+-				IntsPerSec[pAC->Index],
+-				C_INT_MOD_IPS_LOWER_RANGE,
+-				C_INT_MOD_IPS_UPPER_RANGE,
+-				C_INTS_PER_SEC_DEFAULT);
+-			pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+-		} else {
+-			pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
+-		}
+-	} else {
+-		pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+-	}
+-
+-	/*
+-	** Evaluate upper and lower moderation threshold
+-	*/
+-	pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
+-		pAC->DynIrqModInfo.MaxModIntsPerSec +
+-		(pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
+-
+-	pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
+-		pAC->DynIrqModInfo.MaxModIntsPerSec -
+-		(pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
+-
+-	pAC->DynIrqModInfo.PrevTimeVal = jiffies;  /* initial value */
+-
+-
+-} /* GetConfiguration */
+-
+-
+-/*****************************************************************************
+- *
+- * 	ProductStr - return a adapter identification string from vpd
+- *
+- * Description:
+- *	This function reads the product name string from the vpd area
+- *	and puts it the field pAC->DeviceString.
+- *
+- * Returns: N/A
+- */
+-static inline int ProductStr(
+-	SK_AC	*pAC,		/* pointer to adapter context */
+-	char    *DeviceStr,	/* result string */
+-	int      StrLen		/* length of the string */
+-)
+-{
+-char	Keyword[] = VPD_NAME;	/* vpd productname identifier */
+-int	ReturnCode;		/* return code from vpd_read */
+-unsigned long Flags;
+-
+-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-	ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
+-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+-	return ReturnCode;
+-} /* ProductStr */
+-
+-/*****************************************************************************
+- *
+- *      StartDrvCleanupTimer - Start timer to check for descriptors which
+- *                             might be placed in descriptor ring, but
+- *                             havent been handled up to now
+- *
+- * Description:
+- *      This function requests a HW-timer fo the Yukon card. The actions to
+- *      perform when this timer expires, are located in the SkDrvEvent().
+- *
+- * Returns: N/A
+- */
+-static void
+-StartDrvCleanupTimer(SK_AC *pAC) {
+-    SK_EVPARA    EventParam;   /* Event struct for timer event */
+-
+-    SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
+-    EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER;
+-    SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer,
+-                 SK_DRV_RX_CLEANUP_TIMER_LENGTH,
+-                 SKGE_DRV, SK_DRV_TIMER, EventParam);
+-}
+-
+-/*****************************************************************************
+- *
+- *      StopDrvCleanupTimer - Stop timer to check for descriptors
+- *
+- * Description:
+- *      This function requests a HW-timer fo the Yukon card. The actions to
+- *      perform when this timer expires, are located in the SkDrvEvent().
+- *
+- * Returns: N/A
+- */
+-static void
+-StopDrvCleanupTimer(SK_AC *pAC) {
+-    SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer);
+-    SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER));
+-}
+-
+-/****************************************************************************/
+-/* functions for common modules *********************************************/
+-/****************************************************************************/
+-
+-
+-/*****************************************************************************
+- *
+- *	SkDrvAllocRlmtMbuf - allocate an RLMT mbuf
+- *
+- * Description:
+- *	This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure
+- *	is embedded into a socket buff data area.
+- *
+- * Context:
+- *	runtime
+- *
+- * Returns:
+- *	NULL or pointer to Mbuf.
+- */
+-SK_MBUF *SkDrvAllocRlmtMbuf(
+-SK_AC		*pAC,		/* pointer to adapter context */
+-SK_IOC		IoC,		/* the IO-context */
+-unsigned	BufferSize)	/* size of the requested buffer */
+-{
+-SK_MBUF		*pRlmtMbuf;	/* pointer to a new rlmt-mbuf structure */
+-struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
+-
+-	pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC);
+-	if (pMsgBlock == NULL) {
+-		return (NULL);
+-	}
+-	pRlmtMbuf = (SK_MBUF*) pMsgBlock->data;
+-	skb_reserve(pMsgBlock, sizeof(SK_MBUF));
+-	pRlmtMbuf->pNext = NULL;
+-	pRlmtMbuf->pOs = pMsgBlock;
+-	pRlmtMbuf->pData = pMsgBlock->data;	/* Data buffer. */
+-	pRlmtMbuf->Size = BufferSize;		/* Data buffer size. */
+-	pRlmtMbuf->Length = 0;		/* Length of packet (<= Size). */
+-	return (pRlmtMbuf);
+-
+-} /* SkDrvAllocRlmtMbuf */
+-
+-
+-/*****************************************************************************
+- *
+- *	SkDrvFreeRlmtMbuf - free an RLMT mbuf
+- *
+- * Description:
+- *	This routine frees one or more RLMT mbuf(s).
+- *
+- * Context:
+- *	runtime
+- *
+- * Returns:
+- *	Nothing
+- */
+-void  SkDrvFreeRlmtMbuf(
+-SK_AC		*pAC,		/* pointer to adapter context */
+-SK_IOC		IoC,		/* the IO-context */
+-SK_MBUF		*pMbuf)		/* size of the requested buffer */
+-{
+-SK_MBUF		*pFreeMbuf;
+-SK_MBUF		*pNextMbuf;
+-
+-	pFreeMbuf = pMbuf;
+-	do {
+-		pNextMbuf = pFreeMbuf->pNext;
+-		DEV_KFREE_SKB_ANY(pFreeMbuf->pOs);
+-		pFreeMbuf = pNextMbuf;
+-	} while ( pFreeMbuf != NULL );
+-} /* SkDrvFreeRlmtMbuf */
+-
+-
+-/*****************************************************************************
+- *
+- *	SkOsGetTime - provide a time value
+- *
+- * Description:
+- *	This routine provides a time value. The unit is 1/HZ (defined by Linux).
+- *	It is not used for absolute time, but only for time differences.
+- *
+- *
+- * Returns:
+- *	Time value
+- */
+-SK_U64 SkOsGetTime(SK_AC *pAC)
+-{
+-	SK_U64	PrivateJiffies;
+-	SkOsGetTimeCurrent(pAC, &PrivateJiffies);
+-	return PrivateJiffies;
+-} /* SkOsGetTime */
+-
+-
+-/*****************************************************************************
+- *
+- *	SkPciReadCfgDWord - read a 32 bit value from pci config space
+- *
+- * Description:
+- *	This routine reads a 32 bit value from the pci configuration
+- *	space.
+- *
+- * Returns:
+- *	0 - indicate everything worked ok.
+- *	!= 0 - error indication
+- */
+-int SkPciReadCfgDWord(
+-SK_AC *pAC,		/* Adapter Control structure pointer */
+-int PciAddr,		/* PCI register address */
+-SK_U32 *pVal)		/* pointer to store the read value */
+-{
+-	pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
+-	return(0);
+-} /* SkPciReadCfgDWord */
+-
+-
+-/*****************************************************************************
+- *
+- *	SkPciReadCfgWord - read a 16 bit value from pci config space
+- *
+- * Description:
+- *	This routine reads a 16 bit value from the pci configuration
+- *	space.
+- *
+- * Returns:
+- *	0 - indicate everything worked ok.
+- *	!= 0 - error indication
+- */
+-int SkPciReadCfgWord(
+-SK_AC *pAC,	/* Adapter Control structure pointer */
+-int PciAddr,		/* PCI register address */
+-SK_U16 *pVal)		/* pointer to store the read value */
+-{
+-	pci_read_config_word(pAC->PciDev, PciAddr, pVal);
+-	return(0);
+-} /* SkPciReadCfgWord */
+-
+-
+-/*****************************************************************************
+- *
+- *	SkPciReadCfgByte - read a 8 bit value from pci config space
+- *
+- * Description:
+- *	This routine reads a 8 bit value from the pci configuration
+- *	space.
+- *
+- * Returns:
+- *	0 - indicate everything worked ok.
+- *	!= 0 - error indication
+- */
+-int SkPciReadCfgByte(
+-SK_AC *pAC,	/* Adapter Control structure pointer */
+-int PciAddr,		/* PCI register address */
+-SK_U8 *pVal)		/* pointer to store the read value */
+-{
+-	pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
+-	return(0);
+-} /* SkPciReadCfgByte */
+-
+-
+-/*****************************************************************************
+- *
+- *	SkPciWriteCfgWord - write a 16 bit value to pci config space
+- *
+- * Description:
+- *	This routine writes a 16 bit value to the pci configuration
+- *	space. The flag PciConfigUp indicates whether the config space
+- *	is accesible or must be set up first.
+- *
+- * Returns:
+- *	0 - indicate everything worked ok.
+- *	!= 0 - error indication
+- */
+-int SkPciWriteCfgWord(
+-SK_AC *pAC,	/* Adapter Control structure pointer */
+-int PciAddr,		/* PCI register address */
+-SK_U16 Val)		/* pointer to store the read value */
+-{
+-	pci_write_config_word(pAC->PciDev, PciAddr, Val);
+-	return(0);
+-} /* SkPciWriteCfgWord */
+-
+-
+-/*****************************************************************************
+- *
+- *	SkPciWriteCfgWord - write a 8 bit value to pci config space
+- *
+- * Description:
+- *	This routine writes a 8 bit value to the pci configuration
+- *	space. The flag PciConfigUp indicates whether the config space
+- *	is accesible or must be set up first.
+- *
+- * Returns:
+- *	0 - indicate everything worked ok.
+- *	!= 0 - error indication
+- */
+-int SkPciWriteCfgByte(
+-SK_AC *pAC,	/* Adapter Control structure pointer */
+-int PciAddr,		/* PCI register address */
+-SK_U8 Val)		/* pointer to store the read value */
+-{
+-	pci_write_config_byte(pAC->PciDev, PciAddr, Val);
+-	return(0);
+-} /* SkPciWriteCfgByte */
+-
+-
+-/*****************************************************************************
+- *
+- *	SkDrvEvent - handle driver events
+- *
+- * Description:
+- *	This function handles events from all modules directed to the driver
+- *
+- * Context:
+- *	Is called under protection of slow path lock.
+- *
+- * Returns:
+- *	0 if everything ok
+- *	< 0  on error
+- *	
+- */
+-int SkDrvEvent(
+-SK_AC *pAC,		/* pointer to adapter context */
+-SK_IOC IoC,		/* io-context */
+-SK_U32 Event,		/* event-id */
+-SK_EVPARA Param)	/* event-parameter */
+-{
+-SK_MBUF		*pRlmtMbuf;	/* pointer to a rlmt-mbuf structure */
+-struct sk_buff	*pMsg;		/* pointer to a message block */
+-int		FromPort;	/* the port from which we switch away */
+-int		ToPort;		/* the port we switch to */
+-SK_EVPARA	NewPara;	/* parameter for further events */
+-int		Stat;
+-unsigned long	Flags;
+-SK_BOOL		DualNet;
+-
+-	switch (Event) {
+-	case SK_DRV_ADAP_FAIL:
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+-			("ADAPTER FAIL EVENT\n"));
+-		printk("%s: Adapter failed.\n", pAC->dev[0]->name);
+-		/* disable interrupts */
+-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+-		/* cgoos */
+-		break;
+-	case SK_DRV_PORT_FAIL:
+-		FromPort = Param.Para32[0];
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+-			("PORT FAIL EVENT, Port: %d\n", FromPort));
+-		if (FromPort == 0) {
+-			printk("%s: Port A failed.\n", pAC->dev[0]->name);
+-		} else {
+-			printk("%s: Port B failed.\n", pAC->dev[1]->name);
+-		}
+-		/* cgoos */
+-		break;
+-	case SK_DRV_PORT_RESET:	 /* SK_U32 PortIdx */
+-		/* action list 4 */
+-		FromPort = Param.Para32[0];
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+-			("PORT RESET EVENT, Port: %d ", FromPort));
+-		NewPara.Para64 = FromPort;
+-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
+-		spin_lock_irqsave(
+-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+-			Flags);
+-
+-		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
+-		netif_carrier_off(pAC->dev[Param.Para32[0]]);
+-		spin_unlock_irqrestore(
+-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+-			Flags);
+-		
+-		/* clear rx ring from received frames */
+-		ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
+-		
+-		ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
+-		spin_lock_irqsave(
+-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+-			Flags);
+-		
+-		/* tschilling: Handling of return value inserted. */
+-		if (SkGeInitPort(pAC, IoC, FromPort)) {
+-			if (FromPort == 0) {
+-				printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
+-			} else {
+-				printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
+-			}
+-		}
+-		SkAddrMcUpdate(pAC,IoC, FromPort);
+-		PortReInitBmu(pAC, FromPort);
+-		SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
+-		ClearAndStartRx(pAC, FromPort);
+-		spin_unlock_irqrestore(
+-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+-			Flags);
+-		break;
+-	case SK_DRV_NET_UP:	 /* SK_U32 PortIdx */
+-	{	struct net_device *dev = pAC->dev[Param.Para32[0]];
+-		/* action list 5 */
+-		FromPort = Param.Para32[0];
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+-			("NET UP EVENT, Port: %d ", Param.Para32[0]));
+-		/* Mac update */
+-		SkAddrMcUpdate(pAC,IoC, FromPort);
+-
+-		if (DoPrintInterfaceChange) {
+-		printk("%s: network connection up using"
+-			" port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
+-
+-		/* tschilling: Values changed according to LinkSpeedUsed. */
+-		Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
+-		if (Stat == SK_LSPEED_STAT_10MBPS) {
+-			printk("    speed:           10\n");
+-		} else if (Stat == SK_LSPEED_STAT_100MBPS) {
+-			printk("    speed:           100\n");
+-		} else if (Stat == SK_LSPEED_STAT_1000MBPS) {
+-			printk("    speed:           1000\n");
+-		} else {
+-			printk("    speed:           unknown\n");
+-		}
+-
+-
+-		Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
+-		if (Stat == SK_LMODE_STAT_AUTOHALF ||
+-			Stat == SK_LMODE_STAT_AUTOFULL) {
+-			printk("    autonegotiation: yes\n");
+-		}
+-		else {
+-			printk("    autonegotiation: no\n");
+-		}
+-		if (Stat == SK_LMODE_STAT_AUTOHALF ||
+-			Stat == SK_LMODE_STAT_HALF) {
+-			printk("    duplex mode:     half\n");
+-		}
+-		else {
+-			printk("    duplex mode:     full\n");
+-		}
+-		Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
+-		if (Stat == SK_FLOW_STAT_REM_SEND ) {
+-			printk("    flowctrl:        remote send\n");
+-		}
+-		else if (Stat == SK_FLOW_STAT_LOC_SEND ){
+-			printk("    flowctrl:        local send\n");
+-		}
+-		else if (Stat == SK_FLOW_STAT_SYMMETRIC ){
+-			printk("    flowctrl:        symmetric\n");
+-		}
+-		else {
+-			printk("    flowctrl:        none\n");
+-		}
+-		
+-		/* tschilling: Check against CopperType now. */
+-		if ((pAC->GIni.GICopperType == SK_TRUE) &&
+-			(pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
+-			SK_LSPEED_STAT_1000MBPS)) {
+-			Stat = pAC->GIni.GP[FromPort].PMSStatus;
+-			if (Stat == SK_MS_STAT_MASTER ) {
+-				printk("    role:            master\n");
+-			}
+-			else if (Stat == SK_MS_STAT_SLAVE ) {
+-				printk("    role:            slave\n");
+-			}
+-			else {
+-				printk("    role:            ???\n");
+-			}
+-		}
+-
+-		/* 
+-		   Display dim (dynamic interrupt moderation) 
+-		   informations
+-		 */
+-		if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC)
+-			printk("    irq moderation:  static (%d ints/sec)\n",
+-					pAC->DynIrqModInfo.MaxModIntsPerSec);
+-		else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC)
+-			printk("    irq moderation:  dynamic (%d ints/sec)\n",
+-					pAC->DynIrqModInfo.MaxModIntsPerSec);
+-		else
+-			printk("    irq moderation:  disabled\n");
+-
+-
+-		printk("    scatter-gather:  %s\n",
+-		       (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
+-		printk("    tx-checksum:     %s\n",
+-		       (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
+-		printk("    rx-checksum:     %s\n",
+-		       pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
+-
+-		} else {
+-                        DoPrintInterfaceChange = SK_TRUE;
+-                }
+-	
+-		if ((Param.Para32[0] != pAC->ActivePort) &&
+-			(pAC->RlmtNets == 1)) {
+-			NewPara.Para32[0] = pAC->ActivePort;
+-			NewPara.Para32[1] = Param.Para32[0];
+-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
+-				NewPara);
+-		}
+-
+-		/* Inform the world that link protocol is up. */
+-		netif_carrier_on(dev);
+-		break;
+-	}
+-	case SK_DRV_NET_DOWN:	 /* SK_U32 Reason */
+-		/* action list 7 */
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+-			("NET DOWN EVENT "));
+-		if (DoPrintInterfaceChange) {
+-			printk("%s: network connection down\n", 
+-				pAC->dev[Param.Para32[1]]->name);
+-		} else {
+-			DoPrintInterfaceChange = SK_TRUE;
+-		}
+-		netif_carrier_off(pAC->dev[Param.Para32[1]]);
+-		break;
+-	case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+-			("PORT SWITCH HARD "));
+-	case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
+-	/* action list 6 */
+-		printk("%s: switching to port %c\n", pAC->dev[0]->name,
+-			'A'+Param.Para32[1]);
+-	case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
+-		FromPort = Param.Para32[0];
+-		ToPort = Param.Para32[1];
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+-			("PORT SWITCH EVENT, From: %d  To: %d (Pref %d) ",
+-			FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort));
+-		NewPara.Para64 = FromPort;
+-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
+-		NewPara.Para64 = ToPort;
+-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
+-		spin_lock_irqsave(
+-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+-			Flags);
+-		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+-		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
+-		SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
+-		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+-		spin_unlock_irqrestore(
+-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+-			Flags);
+-
+-		ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
+-		ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
+-		
+-		ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
+-		ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
+-		spin_lock_irqsave(
+-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+-			Flags);
+-		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+-		pAC->ActivePort = ToPort;
+-#if 0
+-		SetQueueSizes(pAC);
+-#else
+-		/* tschilling: New common function with minimum size check. */
+-		DualNet = SK_FALSE;
+-		if (pAC->RlmtNets == 2) {
+-			DualNet = SK_TRUE;
+-		}
+-		
+-		if (SkGeInitAssignRamToQueues(
+-			pAC,
+-			pAC->ActivePort,
+-			DualNet)) {
+-			spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+-			spin_unlock_irqrestore(
+-				&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+-				Flags);
+-			printk("SkGeInitAssignRamToQueues failed.\n");
+-			break;
+-		}
+-#endif
+-		/* tschilling: Handling of return values inserted. */
+-		if (SkGeInitPort(pAC, IoC, FromPort) ||
+-			SkGeInitPort(pAC, IoC, ToPort)) {
+-			printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
+-		}
+-		if (Event == SK_DRV_SWITCH_SOFT) {
+-			SkMacRxTxEnable(pAC, IoC, FromPort);
+-		}
+-		SkMacRxTxEnable(pAC, IoC, ToPort);
+-		SkAddrSwap(pAC, IoC, FromPort, ToPort);
+-		SkAddrMcUpdate(pAC, IoC, FromPort);
+-		SkAddrMcUpdate(pAC, IoC, ToPort);
+-		PortReInitBmu(pAC, FromPort);
+-		PortReInitBmu(pAC, ToPort);
+-		SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
+-		SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
+-		ClearAndStartRx(pAC, FromPort);
+-		ClearAndStartRx(pAC, ToPort);
+-		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+-		spin_unlock_irqrestore(
+-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+-			Flags);
+-		break;
+-	case SK_DRV_RLMT_SEND:	 /* SK_MBUF *pMb */
+-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+-			("RLS "));
+-		pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
+-		pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
+-		skb_put(pMsg, pRlmtMbuf->Length);
+-		if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
+-			pMsg) < 0)
+-
+-			DEV_KFREE_SKB_ANY(pMsg);
+-		break;
+-	case SK_DRV_TIMER:
+-		if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
+-			/*
+-			** expiration of the moderation timer implies that
+-			** dynamic moderation is to be applied
+-			*/
+-			SkDimStartModerationTimer(pAC);
+-			SkDimModerate(pAC);
+-                        if (pAC->DynIrqModInfo.DisplayStats) {
+-			    SkDimDisplayModerationSettings(pAC);
+-                        }
+-                } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) {
+-			/*
+-			** check if we need to check for descriptors which
+-			** haven't been handled the last millisecs
+-			*/
+-			StartDrvCleanupTimer(pAC);
+-			if (pAC->GIni.GIMacsFound == 2) {
+-				ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE);
+-			}
+-			ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE);
+-		} else {
+-			printk("Expiration of unknown timer\n");
+-		}
+-		break;
+-	default:
+-		break;
+-	}
+-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+-		("END EVENT "));
+-	
+-	return (0);
+-} /* SkDrvEvent */
+-
+-
+-/*****************************************************************************
+- *
+- *	SkErrorLog - log errors
+- *
+- * Description:
+- *	This function logs errors to the system buffer and to the console
+- *
+- * Returns:
+- *	0 if everything ok
+- *	< 0  on error
+- *	
+- */
+-void SkErrorLog(
+-SK_AC	*pAC,
+-int	ErrClass,
+-int	ErrNum,
+-char	*pErrorMsg)
+-{
+-char	ClassStr[80];
+-
+-	switch (ErrClass) {
+-	case SK_ERRCL_OTHER:
+-		strcpy(ClassStr, "Other error");
+-		break;
+-	case SK_ERRCL_CONFIG:
+-		strcpy(ClassStr, "Configuration error");
+-		break;
+-	case SK_ERRCL_INIT:
+-		strcpy(ClassStr, "Initialization error");
+-		break;
+-	case SK_ERRCL_NORES:
+-		strcpy(ClassStr, "Out of resources error");
+-		break;
+-	case SK_ERRCL_SW:
+-		strcpy(ClassStr, "internal Software error");
+-		break;
+-	case SK_ERRCL_HW:
+-		strcpy(ClassStr, "Hardware failure");
+-		break;
+-	case SK_ERRCL_COMM:
+-		strcpy(ClassStr, "Communication error");
+-		break;
+-	}
+-	printk(KERN_INFO "%s: -- ERROR --\n        Class:  %s\n"
+-		"        Nr:  0x%x\n        Msg:  %s\n", pAC->dev[0]->name,
+-		ClassStr, ErrNum, pErrorMsg);
+-
+-} /* SkErrorLog */
+-
+-#ifdef SK_DIAG_SUPPORT
+-
+-/*****************************************************************************
+- *
+- *	SkDrvEnterDiagMode - handles DIAG attach request
+- *
+- * Description:
+- *	Notify the kernel to NOT access the card any longer due to DIAG
+- *	Deinitialize the Card
+- *
+- * Returns:
+- *	int
+- */
+-int SkDrvEnterDiagMode(
+-SK_AC   *pAc)   /* pointer to adapter context */
+-{
+-	DEV_NET *pNet = netdev_priv(pAc->dev[0]);
+-	SK_AC   *pAC  = pNet->pAC;
+-
+-	SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), 
+-			sizeof(SK_PNMI_STRUCT_DATA));
+-
+-	pAC->DiagModeActive = DIAG_ACTIVE;
+-	if (pAC->BoardLevel > SK_INIT_DATA) {
+-		if (netif_running(pAC->dev[0])) {
+-			pAC->WasIfUp[0] = SK_TRUE;
+-			pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose      */
+-			DoPrintInterfaceChange = SK_FALSE;
+-			SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
+-		} else {
+-			pAC->WasIfUp[0] = SK_FALSE;
+-		}
+-		if (pNet != netdev_priv(pAC->dev[1])) {
+-			pNet = netdev_priv(pAC->dev[1]);
+-			if (netif_running(pAC->dev[1])) {
+-				pAC->WasIfUp[1] = SK_TRUE;
+-				pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+-				DoPrintInterfaceChange = SK_FALSE;
+-				SkDrvDeInitAdapter(pAC, 1);  /* do SkGeClose  */
+-			} else {
+-				pAC->WasIfUp[1] = SK_FALSE;
+-			}
+-		}
+-		pAC->BoardLevel = SK_INIT_DATA;
+-	}
+-	return(0);
+-}
+-
+-/*****************************************************************************
+- *
+- *	SkDrvLeaveDiagMode - handles DIAG detach request
+- *
+- * Description:
+- *	Notify the kernel to may access the card again after use by DIAG
+- *	Initialize the Card
+- *
+- * Returns:
+- * 	int
+- */
+-int SkDrvLeaveDiagMode(
+-SK_AC   *pAc)   /* pointer to adapter control context */
+-{ 
+-	SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup), 
+-			sizeof(SK_PNMI_STRUCT_DATA));
+-	pAc->DiagModeActive    = DIAG_NOTACTIVE;
+-	pAc->Pnmi.DiagAttached = SK_DIAG_IDLE;
+-        if (pAc->WasIfUp[0] == SK_TRUE) {
+-                pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+-		DoPrintInterfaceChange = SK_FALSE;
+-                SkDrvInitAdapter(pAc, 0);    /* first device  */
+-        }
+-        if (pAc->WasIfUp[1] == SK_TRUE) {
+-                pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+-		DoPrintInterfaceChange = SK_FALSE;
+-                SkDrvInitAdapter(pAc, 1);    /* second device */
+-        }
+-	return(0);
+-}
+-
+-/*****************************************************************************
+- *
+- *	ParseDeviceNbrFromSlotName - Evaluate PCI device number
+- *
+- * Description:
+- * 	This function parses the PCI slot name information string and will
+- *	retrieve the devcie number out of it. The slot_name maintianed by
+- *	linux is in the form of '02:0a.0', whereas the first two characters 
+- *	represent the bus number in hex (in the sample above this is 
+- *	pci bus 0x02) and the next two characters the device number (0x0a).
+- *
+- * Returns:
+- *	SK_U32: The device number from the PCI slot name
+- */ 
+-
+-static SK_U32 ParseDeviceNbrFromSlotName(
+-const char *SlotName)   /* pointer to pci slot name eg. '02:0a.0' */
+-{
+-	char	*CurrCharPos	= (char *) SlotName;
+-	int	FirstNibble	= -1;
+-	int	SecondNibble	= -1;
+-	SK_U32	Result		=  0;
+-
+-	while (*CurrCharPos != '\0') {
+-		if (*CurrCharPos == ':') { 
+-			while (*CurrCharPos != '.') {
+-				CurrCharPos++;  
+-				if (	(*CurrCharPos >= '0') && 
+-					(*CurrCharPos <= '9')) {
+-					if (FirstNibble == -1) {
+-						/* dec. value for '0' */
+-						FirstNibble = *CurrCharPos - 48;
+-					} else {
+-						SecondNibble = *CurrCharPos - 48;
+-					}  
+-				} else if (	(*CurrCharPos >= 'a') && 
+-						(*CurrCharPos <= 'f')  ) {
+-					if (FirstNibble == -1) {
+-						FirstNibble = *CurrCharPos - 87; 
+-					} else {
+-						SecondNibble = *CurrCharPos - 87; 
+-					}
+-				} else {
+-					Result = 0;
+-				}
+-			}
+-
+-			Result = FirstNibble;
+-			Result = Result << 4; /* first nibble is higher one */
+-			Result = Result | SecondNibble;
+-		}
+-		CurrCharPos++;   /* next character */
+-	}
+-	return (Result);
+-}
+-
+-/****************************************************************************
+- *
+- *	SkDrvDeInitAdapter - deinitialize adapter (this function is only 
+- *				called if Diag attaches to that card)
+- *
+- * Description:
+- *	Close initialized adapter.
+- *
+- * Returns:
+- *	0 - on success
+- *	error code - on error
+- */
+-static int SkDrvDeInitAdapter(
+-SK_AC   *pAC,		/* pointer to adapter context   */
+-int      devNbr)	/* what device is to be handled */
+-{
+-	struct SK_NET_DEVICE *dev;
+-
+-	dev = pAC->dev[devNbr];
+-
+-	/* On Linux 2.6 the network driver does NOT mess with reference
+-	** counts.  The driver MUST be able to be unloaded at any time
+-	** due to the possibility of hotplug.
+-	*/
+-	if (SkGeClose(dev) != 0) {
+-		return (-1);
+-	}
+-	return (0);
+-
+-} /* SkDrvDeInitAdapter() */
+-
+-/****************************************************************************
+- *
+- *	SkDrvInitAdapter - Initialize adapter (this function is only 
+- *				called if Diag deattaches from that card)
+- *
+- * Description:
+- *	Close initialized adapter.
+- *
+- * Returns:
+- *	0 - on success
+- *	error code - on error
+- */
+-static int SkDrvInitAdapter(
+-SK_AC   *pAC,		/* pointer to adapter context   */
+-int      devNbr)	/* what device is to be handled */
+-{
+-	struct SK_NET_DEVICE *dev;
+-
+-	dev = pAC->dev[devNbr];
+-
+-	if (SkGeOpen(dev) != 0) {
+-		return (-1);
+-	}
+-
+-	/*
+-	** Use correct MTU size and indicate to kernel TX queue can be started
+-	*/ 
+-	if (SkGeChangeMtu(dev, dev->mtu) != 0) {
+-		return (-1);
+-	} 
+-	return (0);
+-
+-} /* SkDrvInitAdapter */
+-
+-#endif
+-
+-#ifdef DEBUG
+-/****************************************************************************/
+-/* "debug only" section *****************************************************/
+-/****************************************************************************/
+-
+-
+-/*****************************************************************************
+- *
+- *	DumpMsg - print a frame
+- *
+- * Description:
+- *	This function prints frames to the system logfile/to the console.
+- *
+- * Returns: N/A
+- *	
+- */
+-static void DumpMsg(struct sk_buff *skb, char *str)
+-{
+-	int	msglen;
+-
+-	if (skb == NULL) {
+-		printk("DumpMsg(): NULL-Message\n");
+-		return;
+-	}
+-
+-	if (skb->data == NULL) {
+-		printk("DumpMsg(): Message empty\n");
+-		return;
+-	}
+-
+-	msglen = skb->len;
+-	if (msglen > 64)
+-		msglen = 64;
+-
+-	printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len);
+-
+-	DumpData((char *)skb->data, msglen);
+-
+-	printk("------- End of message ---------\n");
+-} /* DumpMsg */
+-
+-
+-
+-/*****************************************************************************
+- *
+- *	DumpData - print a data area
+- *
+- * Description:
+- *	This function prints a area of data to the system logfile/to the
+- *	console.
+- *
+- * Returns: N/A
+- *	
+- */
+-static void DumpData(char *p, int size)
+-{
+-register int    i;
+-int	haddr, addr;
+-char	hex_buffer[180];
+-char	asc_buffer[180];
+-char	HEXCHAR[] = "0123456789ABCDEF";
+-
+-	addr = 0;
+-	haddr = 0;
+-	hex_buffer[0] = 0;
+-	asc_buffer[0] = 0;
+-	for (i=0; i < size; ) {
+-		if (*p >= '0' && *p <='z')
+-			asc_buffer[addr] = *p;
+-		else
+-			asc_buffer[addr] = '.';
+-		addr++;
+-		asc_buffer[addr] = 0;
+-		hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4];
+-		haddr++;
+-		hex_buffer[haddr] = HEXCHAR[*p & 0x0f];
+-		haddr++;
+-		hex_buffer[haddr] = ' ';
+-		haddr++;
+-		hex_buffer[haddr] = 0;
+-		p++;
+-		i++;
+-		if (i%16 == 0) {
+-			printk("%s  %s\n", hex_buffer, asc_buffer);
+-			addr = 0;
+-			haddr = 0;
+-		}
+-	}
+-} /* DumpData */
+-
+-
+-/*****************************************************************************
+- *
+- *	DumpLong - print a data area as long values
+- *
+- * Description:
+- *	This function prints a area of data to the system logfile/to the
+- *	console.
+- *
+- * Returns: N/A
+- *	
+- */
+-static void DumpLong(char *pc, int size)
+-{
+-register int    i;
+-int	haddr, addr;
+-char	hex_buffer[180];
+-char	asc_buffer[180];
+-char	HEXCHAR[] = "0123456789ABCDEF";
+-long	*p;
+-int	l;
+-
+-	addr = 0;
+-	haddr = 0;
+-	hex_buffer[0] = 0;
+-	asc_buffer[0] = 0;
+-	p = (long*) pc;
+-	for (i=0; i < size; ) {
+-		l = (long) *p;
+-		hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf];
+-		haddr++;
+-		hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf];
+-		haddr++;
+-		hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf];
+-		haddr++;
+-		hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf];
+-		haddr++;
+-		hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf];
+-		haddr++;
+-		hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf];
+-		haddr++;
+-		hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf];
+-		haddr++;
+-		hex_buffer[haddr] = HEXCHAR[l & 0x0f];
+-		haddr++;
+-		hex_buffer[haddr] = ' ';
+-		haddr++;
+-		hex_buffer[haddr] = 0;
+-		p++;
+-		i++;
+-		if (i%8 == 0) {
+-			printk("%4x %s\n", (i-8)*4, hex_buffer);
+-			haddr = 0;
+-		}
+-	}
+-	printk("------------------------\n");
+-} /* DumpLong */
+-
+-#endif
+-
+-static int __devinit skge_probe_one(struct pci_dev *pdev,
+-		const struct pci_device_id *ent)
+-{
+-	SK_AC			*pAC;
+-	DEV_NET			*pNet = NULL;
+-	struct net_device	*dev = NULL;
+-	static int boards_found = 0;
+-	int error = -ENODEV;
+-	int using_dac = 0;
+-	char DeviceStr[80];
+-
+-	if (pci_enable_device(pdev))
+-		goto out;
+- 
+-	/* Configure DMA attributes. */
+-	if (sizeof(dma_addr_t) > sizeof(u32) &&
+-	    !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+-		using_dac = 1;
+-		error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+-		if (error < 0) {
+-			printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
+-			       "for consistent allocations\n", pci_name(pdev));
+-			goto out_disable_device;
+-		}
+-	} else {
+-		error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+-		if (error) {
+-			printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
+-			       pci_name(pdev));
+-			goto out_disable_device;
+-		}
+-	}
+-
+- 	error = -ENOMEM;
+- 	dev = alloc_etherdev(sizeof(DEV_NET));
+- 	if (!dev) {
+-		printk(KERN_ERR "sk98lin: unable to allocate etherdev "
+-		       "structure!\n");
+-		goto out_disable_device;
+-	}
+-
+-	pNet = netdev_priv(dev);
+-	pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
+-	if (!pNet->pAC) {
+-		printk(KERN_ERR "sk98lin: unable to allocate adapter "
+-		       "structure!\n");
+-		goto out_free_netdev;
+-	}
+-
+-	pAC = pNet->pAC;
+-	pAC->PciDev = pdev;
+-
+-	pAC->dev[0] = dev;
+-	pAC->dev[1] = dev;
+-	pAC->CheckQueue = SK_FALSE;
+-
+-	dev->irq = pdev->irq;
+-
+-	error = SkGeInitPCI(pAC);
+-	if (error) {
+-		printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
+-		goto out_free_netdev;
+-	}
+-
+-	dev->open =		&SkGeOpen;
+-	dev->stop =		&SkGeClose;
+-	dev->hard_start_xmit =	&SkGeXmit;
+-	dev->get_stats =	&SkGeStats;
+-	dev->set_multicast_list = &SkGeSetRxMode;
+-	dev->set_mac_address =	&SkGeSetMacAddr;
+-	dev->do_ioctl =		&SkGeIoctl;
+-	dev->change_mtu =	&SkGeChangeMtu;
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-	dev->poll_controller =	&SkGePollController;
+-#endif
+-	SET_NETDEV_DEV(dev, &pdev->dev);
+-	SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
+-
+-	/* Use only if yukon hardware */
+-	if (pAC->ChipsetType) {
+-#ifdef USE_SK_TX_CHECKSUM
+-		dev->features |= NETIF_F_IP_CSUM;
+-#endif
+-#ifdef SK_ZEROCOPY
+-		dev->features |= NETIF_F_SG;
+-#endif
+-#ifdef USE_SK_RX_CHECKSUM
+-		pAC->RxPort[0].RxCsum = 1;
+-#endif
+-	}
+-
+-	if (using_dac)
+-		dev->features |= NETIF_F_HIGHDMA;
+-
+-	pAC->Index = boards_found++;
+-
+-	error = SkGeBoardInit(dev, pAC);
+-	if (error)
+-		goto out_free_netdev;
+-
+-	/* Read Adapter name from VPD */
+-	if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
+-		error = -EIO;
+-		printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
+-		goto out_free_resources;
+-	}
+-
+-	/* Register net device */
+-	error = register_netdev(dev);
+-	if (error) {
+-		printk(KERN_ERR "sk98lin: Could not register device.\n");
+-		goto out_free_resources;
+-	}
+-
+-	/* Print adapter specific string from vpd */
+-	printk("%s: %s\n", dev->name, DeviceStr);
+-
+-	/* Print configuration settings */
+-	printk("      PrefPort:%c  RlmtMode:%s\n",
+-		'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
+-		(pAC->RlmtMode==0)  ? "Check Link State" :
+-		((pAC->RlmtMode==1) ? "Check Link State" :
+-		((pAC->RlmtMode==3) ? "Check Local Port" :
+-		((pAC->RlmtMode==7) ? "Check Segmentation" :
+-		((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
+-
+-	SkGeYellowLED(pAC, pAC->IoBase, 1);
+-
+-	memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
+-	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+-
+-	pNet->PortNr = 0;
+-	pNet->NetNr  = 0;
+-
+-	boards_found++;
+-
+-	pci_set_drvdata(pdev, dev);
+-
+-	/* More then one port found */
+-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+-		dev = alloc_etherdev(sizeof(DEV_NET));
+-		if (!dev) {
+-			printk(KERN_ERR "sk98lin: unable to allocate etherdev "
+-				"structure!\n");
+-			goto single_port;
+-		}
+-
+-		pNet          = netdev_priv(dev);
+-		pNet->PortNr  = 1;
+-		pNet->NetNr   = 1;
+-		pNet->pAC     = pAC;
+-
+-		dev->open               = &SkGeOpen;
+-		dev->stop               = &SkGeClose;
+-		dev->hard_start_xmit    = &SkGeXmit;
+-		dev->get_stats          = &SkGeStats;
+-		dev->set_multicast_list = &SkGeSetRxMode;
+-		dev->set_mac_address    = &SkGeSetMacAddr;
+-		dev->do_ioctl           = &SkGeIoctl;
+-		dev->change_mtu         = &SkGeChangeMtu;
+-		SET_NETDEV_DEV(dev, &pdev->dev);
+-		SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
+-
+-		if (pAC->ChipsetType) {
+-#ifdef USE_SK_TX_CHECKSUM
+-			dev->features |= NETIF_F_IP_CSUM;
+-#endif
+-#ifdef SK_ZEROCOPY
+-			dev->features |= NETIF_F_SG;
+-#endif
+-#ifdef USE_SK_RX_CHECKSUM
+-			pAC->RxPort[1].RxCsum = 1;
+-#endif
+-		}
+-
+-		if (using_dac)
+-			dev->features |= NETIF_F_HIGHDMA;
+-
+-		error = register_netdev(dev);
+-		if (error) {
+-			printk(KERN_ERR "sk98lin: Could not register device"
+-			       " for second port. (%d)\n", error);
+-			free_netdev(dev);
+-			goto single_port;
+-		}
+-
+-		pAC->dev[1]   = dev;
+-		memcpy(&dev->dev_addr,
+-		       &pAC->Addr.Net[1].CurrentMacAddress, 6);
+-		memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+-
+-		printk("%s: %s\n", dev->name, DeviceStr);
+-		printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
+-	}
+-
+-single_port:
+-
+-	/* Save the hardware revision */
+-	pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
+-		(pAC->GIni.GIPciHwRev & 0x0F);
+-
+-	/* Set driver globals */
+-	pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
+-	pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
+-
+-	memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
+-	memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
+-
+-	return 0;
+-
+- out_free_resources:
+-	FreeResources(dev);
+- out_free_netdev:
+-	free_netdev(dev);
+- out_disable_device:
+-	pci_disable_device(pdev);
+- out:
+-	return error;
+-}
+-
+-static void __devexit skge_remove_one(struct pci_dev *pdev)
+-{
+-	struct net_device *dev = pci_get_drvdata(pdev);
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-	struct net_device *otherdev = pAC->dev[1];
+-
+-	unregister_netdev(dev);
+-
+-	SkGeYellowLED(pAC, pAC->IoBase, 0);
+-
+-	if (pAC->BoardLevel == SK_INIT_RUN) {
+-		SK_EVPARA EvPara;
+-		unsigned long Flags;
+-
+-		/* board is still alive */
+-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-		EvPara.Para32[0] = 0;
+-		EvPara.Para32[1] = -1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+-		EvPara.Para32[0] = 1;
+-		EvPara.Para32[1] = -1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+-		SkEventDispatcher(pAC, pAC->IoBase);
+-		/* disable interrupts */
+-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+-		SkGeDeInit(pAC, pAC->IoBase);
+-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-		pAC->BoardLevel = SK_INIT_DATA;
+-		/* We do NOT check here, if IRQ was pending, of course*/
+-	}
+-
+-	if (pAC->BoardLevel == SK_INIT_IO) {
+-		/* board is still alive */
+-		SkGeDeInit(pAC, pAC->IoBase);
+-		pAC->BoardLevel = SK_INIT_DATA;
+-	}
+-
+-	FreeResources(dev);
+-	free_netdev(dev);
+-	if (otherdev != dev)
+-		free_netdev(otherdev);
+-	kfree(pAC);
+-}
+-
+-#ifdef CONFIG_PM
+-static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+-	struct net_device *dev = pci_get_drvdata(pdev);
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-	struct net_device *otherdev = pAC->dev[1];
+-
+-	if (netif_running(dev)) {
+-		netif_carrier_off(dev);
+-		DoPrintInterfaceChange = SK_FALSE;
+-		SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
+-		netif_device_detach(dev);
+-	}
+-	if (otherdev != dev) {
+-		if (netif_running(otherdev)) {
+-			netif_carrier_off(otherdev);
+-			DoPrintInterfaceChange = SK_FALSE;
+-			SkDrvDeInitAdapter(pAC, 1);  /* performs SkGeClose */
+-			netif_device_detach(otherdev);
+-		}
+-	}
+-
+-	pci_save_state(pdev);
+-	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+-	if (pAC->AllocFlag & SK_ALLOC_IRQ) {
+-		free_irq(dev->irq, dev);
+-	}
+-	pci_disable_device(pdev);
+-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+-
+-	return 0;
+-}
+-
+-static int skge_resume(struct pci_dev *pdev)
+-{
+-	struct net_device *dev = pci_get_drvdata(pdev);
+-	DEV_NET *pNet = netdev_priv(dev);
+-	SK_AC *pAC = pNet->pAC;
+-	struct net_device *otherdev = pAC->dev[1];
+-	int ret;
+-
+-	pci_set_power_state(pdev, PCI_D0);
+-	pci_restore_state(pdev);
+-	ret = pci_enable_device(pdev);
+-	if (ret) {
+-		printk(KERN_WARNING "sk98lin: unable to enable device %s "
+-				"in resume\n", dev->name);
+-		goto err_out;
+-	}
+-	pci_set_master(pdev);
+-	if (pAC->GIni.GIMacsFound == 2)
+-		ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
+-	else
+-		ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "sk98lin", dev);
+-	if (ret) {
+-		printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
+-		ret = -EBUSY;
+-		goto err_out_disable_pdev;
+-	}
+-
+-	netif_device_attach(dev);
+-	if (netif_running(dev)) {
+-		DoPrintInterfaceChange = SK_FALSE;
+-		SkDrvInitAdapter(pAC, 0);    /* first device  */
+-	}
+-	if (otherdev != dev) {
+-		netif_device_attach(otherdev);
+-		if (netif_running(otherdev)) {
+-			DoPrintInterfaceChange = SK_FALSE;
+-			SkDrvInitAdapter(pAC, 1);    /* second device  */
+-		}
+-	}
+-
+-	return 0;
+-
+-err_out_disable_pdev:
+-	pci_disable_device(pdev);
+-err_out:
+-	pAC->AllocFlag &= ~SK_ALLOC_IRQ;
+-	dev->irq = 0;
+-	return ret;
+-}
+-#else
+-#define skge_suspend NULL
+-#define skge_resume NULL
+-#endif
+-
+-static struct pci_device_id skge_pci_tbl[] = {
+-#ifdef SK98LIN_ALL_DEVICES
+-	{ PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-#endif
+-#ifdef GENESIS
+-	/* Generic SysKonnect SK-98xx Gigabit Ethernet Server Adapter */	
+-	{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-#endif
+-	/* Generic SysKonnect SK-98xx V2.0 Gigabit Ethernet Adapter */	
+-	{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-#ifdef SK98LIN_ALL_DEVICES
+-/* DLink card does not have valid VPD so this driver gags
+- *	{ PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- */
+-	{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
+-	{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-#endif
+-	{ 0 }
+-};
+-
+-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
+-
+-static struct pci_driver skge_driver = {
+-	.name		= "sk98lin",
+-	.id_table	= skge_pci_tbl,
+-	.probe		= skge_probe_one,
+-	.remove		= __devexit_p(skge_remove_one),
+-	.suspend	= skge_suspend,
+-	.resume		= skge_resume,
+-};
+-
+-static int __init skge_init(void)
+-{
+-	printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
+-	       " and is scheduled for removal\n");
+-
+-	return pci_register_driver(&skge_driver);
+-}
+-
+-static void __exit skge_exit(void)
+-{
+-	pci_unregister_driver(&skge_driver);
+-}
+-
+-module_init(skge_init);
+-module_exit(skge_exit);
+diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c
+deleted file mode 100644
+index db67099..0000000
+--- a/drivers/net/sk98lin/skgehwt.c
++++ /dev/null
+@@ -1,171 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skgehwt.c
+- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version:	$Revision: 1.15 $
+- * Date:	$Date: 2003/09/16 13:41:23 $
+- * Purpose:	Hardware Timer
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- *	Event queue and dispatcher
+- */
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+-
+-#ifdef __C2MAN__
+-/*
+- *   Hardware Timer function queue management.
+- */
+-intro()
+-{}
+-#endif
+-
+-/*
+- * Prototypes of local functions.
+- */
+-#define	SK_HWT_MAX	(65000)
+-
+-/* correction factor */
+-#define	SK_HWT_FAC	(1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100)
+-
+-/*
+- * Initialize hardware timer.
+- *
+- * Must be called during init level 1.
+- */
+-void	SkHwtInit(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	Ioc)	/* IoContext */
+-{
+-	pAC->Hwt.TStart = 0 ;
+-	pAC->Hwt.TStop	= 0 ;
+-	pAC->Hwt.TActive = SK_FALSE;
+-
+-	SkHwtStop(pAC, Ioc);
+-}
+-
+-/*
+- *
+- * Start hardware timer (clock ticks are 16us).
+- *
+- */
+-void	SkHwtStart(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	Ioc,	/* IoContext */
+-SK_U32	Time)	/* Time in units of 16us to load the timer with. */
+-{
+-	SK_U32	Cnt;
+-
+-	if (Time > SK_HWT_MAX)
+-		Time = SK_HWT_MAX;
+-
+-	pAC->Hwt.TStart = Time;
+-	pAC->Hwt.TStop = 0L;
+-
+-	Cnt = Time;
+-
+-	/*
+-	 * if time < 16 us
+-	 *	time = 16 us
+-	 */
+-	if (!Cnt) {
+-		Cnt++;
+-	}
+-
+-	SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC);
+-	
+-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_START);	/* Start timer. */
+-
+-	pAC->Hwt.TActive = SK_TRUE;
+-}
+-
+-/*
+- * Stop hardware timer.
+- * and clear the timer IRQ
+- */
+-void	SkHwtStop(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	Ioc)	/* IoContext */
+-{
+-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP);
+-	
+-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ);
+-
+-	pAC->Hwt.TActive = SK_FALSE;
+-}
+-
+-
+-/*
+- *	Stop hardware timer and read time elapsed since last start.
+- *
+- * returns
+- *	The elapsed time since last start in units of 16us.
+- *
+- */
+-SK_U32	SkHwtRead(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	Ioc)	/* IoContext */
+-{
+-	SK_U32	TRead;
+-	SK_U32	IStatus;
+-
+-	if (pAC->Hwt.TActive) {
+-		
+-		SkHwtStop(pAC, Ioc);
+-
+-		SK_IN32(Ioc, B2_TI_VAL, &TRead);
+-		TRead /= SK_HWT_FAC;
+-
+-		SK_IN32(Ioc, B0_ISRC, &IStatus);
+-
+-		/* Check if timer expired (or wraped around) */
+-		if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) {
+-			
+-			SkHwtStop(pAC, Ioc);
+-			
+-			pAC->Hwt.TStop = pAC->Hwt.TStart;
+-		}
+-		else {
+-			
+-			pAC->Hwt.TStop = pAC->Hwt.TStart - TRead;
+-		}
+-	}
+-	return(pAC->Hwt.TStop);
+-}
+-
+-/*
+- * interrupt source= timer
+- */
+-void	SkHwtIsr(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	Ioc)	/* IoContext */
+-{
+-	SkHwtStop(pAC, Ioc);
+-	
+-	pAC->Hwt.TStop = pAC->Hwt.TStart;
+-	
+-	SkTimerDone(pAC, Ioc);
+-}
+-
+-/* End of file */
+diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
+deleted file mode 100644
+index 67f1d6a..0000000
+--- a/drivers/net/sk98lin/skgeinit.c
++++ /dev/null
+@@ -1,2005 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skgeinit.c
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.97 $
+- * Date:	$Date: 2003/10/02 16:45:31 $
+- * Purpose:	Contains functions to initialize the adapter
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-
+-/* global variables ***********************************************************/
+-
+-/* local variables ************************************************************/
+-
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-struct s_QOffTab {
+-	int	RxQOff;		/* Receive Queue Address Offset */
+-	int	XsQOff;		/* Sync Tx Queue Address Offset */
+-	int	XaQOff;		/* Async Tx Queue Address Offset */
+-};
+-static struct s_QOffTab QOffTab[] = {
+-	{Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2}
+-};
+-
+-struct s_Config {
+-	char	ScanString[8];
+-	SK_U32	Value;
+-};
+-
+-static struct s_Config OemConfig = {
+-	{'O','E','M','_','C','o','n','f'},
+-#ifdef SK_OEM_CONFIG
+-	OEM_CONFIG_VALUE,
+-#else
+-	0,
+-#endif
+-};
+-
+-/******************************************************************************
+- *
+- *	SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings
+- *
+- * Description:
+- *	Enable or disable the descriptor polling of the transmit descriptor
+- *	ring(s) (TxD) for port 'Port'.
+- *	The new configuration is *not* saved over any SkGeStopPort() and
+- *	SkGeInitPort() calls.
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGePollTxD(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_BOOL PollTxD)	/* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
+-{
+-	SK_GEPORT *pPrt;
+-	SK_U32	DWord;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL);
+-
+-	if (pPrt->PXSQSize != 0) {
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord);
+-	}
+-	
+-	if (pPrt->PXAQSize != 0) {
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord);
+-	}
+-}	/* SkGePollTxD */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeYellowLED() - Switch the yellow LED on or off.
+- *
+- * Description:
+- *	Switch the yellow LED on or off.
+- *
+- * Note:
+- *	This function may be called any time after SkGeInit(Level 1).
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGeYellowLED(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		State)		/* yellow LED state, 0 = OFF, 0 != ON */
+-{
+-	if (State == 0) {
+-		/* Switch yellow LED OFF */
+-		SK_OUT8(IoC, B0_LED, LED_STAT_OFF);
+-	}
+-	else {
+-		/* Switch yellow LED ON */
+-		SK_OUT8(IoC, B0_LED, LED_STAT_ON);
+-	}
+-}	/* SkGeYellowLED */
+-
+-
+-#if (!defined(SK_SLIM) || defined(GENESIS))
+-/******************************************************************************
+- *
+- *	SkGeXmitLED() - Modify the Operational Mode of a transmission LED.
+- *
+- * Description:
+- *	The Rx or Tx LED which is specified by 'Led' will be
+- *	enabled, disabled or switched on in test mode.
+- *
+- * Note:
+- *	'Led' must contain the address offset of the LEDs INI register.
+- *
+- * Usage:
+- *	SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGeXmitLED(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Led,		/* offset to the LED Init Value register */
+-int		Mode)		/* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */
+-{
+-	SK_U32	LedIni;
+-
+-	switch (Mode) {
+-	case SK_LED_ENA:
+-		LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+-		SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni);
+-		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
+-		break;
+-	case SK_LED_TST:
+-		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON);
+-		SK_OUT32(IoC, Led + XMIT_LED_CNT, 100);
+-		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
+-		break;
+-	case SK_LED_DIS:
+-	default:
+-		/*
+-		 * Do NOT stop the LED Timer here. The LED might be
+-		 * in on state. But it needs to go off.
+-		 */
+-		SK_OUT32(IoC, Led + XMIT_LED_CNT, 0);
+-		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF);
+-		break;
+-	}
+-			
+-	/*
+-	 * 1000BT: The Transmit LED is driven by the PHY.
+-	 * But the default LED configuration is used for
+-	 * Level One and Broadcom PHYs.
+-	 * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.)
+-	 * (In this case it has to be added here. But we will see. XXX)
+-	 */
+-}	/* SkGeXmitLED */
+-#endif	/* !SK_SLIM || GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- *	DoCalcAddr() - Calculates the start and the end address of a queue.
+- *
+- * Description:
+- *	This function calculates the start and the end address of a queue.
+- *  Afterwards the 'StartVal' is incremented to the next start position.
+- *	If the port is already initialized the calculated values
+- *	will be checked against the configured values and an
+- *	error will be returned, if they are not equal.
+- *	If the port is not initialized the values will be written to
+- *	*StartAdr and *EndAddr.
+- *
+- * Returns:
+- *	0:	success
+- *	1:	configuration error
+- */
+-static int DoCalcAddr(
+-SK_AC		*pAC, 				/* adapter context */
+-SK_GEPORT	SK_FAR *pPrt,		/* port index */
+-int			QuSize,				/* size of the queue to configure in kB */
+-SK_U32		SK_FAR *StartVal,	/* start value for address calculation */
+-SK_U32		SK_FAR *QuStartAddr,/* start addr to calculate */
+-SK_U32		SK_FAR *QuEndAddr)	/* end address to calculate */
+-{
+-	SK_U32	EndVal;
+-	SK_U32	NextStart;
+-	int		Rtv;
+-
+-	Rtv = 0;
+-	if (QuSize == 0) {
+-		EndVal = *StartVal;
+-		NextStart = EndVal;
+-	}
+-	else {
+-		EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1;
+-		NextStart = EndVal + 1;
+-	}
+-
+-	if (pPrt->PState >= SK_PRT_INIT) {
+-		if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) {
+-			Rtv = 1;
+-		}
+-	}
+-	else {
+-		*QuStartAddr = *StartVal;
+-		*QuEndAddr = EndVal;
+-	}
+-
+-	*StartVal = NextStart;
+-	return(Rtv);
+-}	/* DoCalcAddr */
+-
+-/******************************************************************************
+- *
+- *	SkGeInitAssignRamToQueues() - allocate default queue sizes
+- *
+- * Description:
+- *	This function assigns the memory to the different queues and ports.
+- *	When DualNet is set to SK_TRUE all ports get the same amount of memory.
+- *  Otherwise the first port gets most of the memory and all the
+- *	other ports just the required minimum.
+- *	This function can only be called when pAC->GIni.GIRamSize and
+- *	pAC->GIni.GIMacsFound have been initialized, usually this happens
+- *	at init level 1
+- *
+- * Returns:
+- *	0 - ok
+- *	1 - invalid input values
+- *	2 - not enough memory
+- */
+-
+-int SkGeInitAssignRamToQueues(
+-SK_AC	*pAC,			/* Adapter context */
+-int		ActivePort,		/* Active Port in RLMT mode */
+-SK_BOOL	DualNet)		/* adapter context */
+-{
+-	int	i;
+-	int	UsedKilobytes;			/* memory already assigned */
+-	int	ActivePortKilobytes;	/* memory available for active port */
+-	SK_GEPORT *pGePort;
+-
+-	UsedKilobytes = 0;
+-
+-	if (ActivePort >= pAC->GIni.GIMacsFound) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+-			("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n",
+-			ActivePort));
+-		return(1);
+-	}
+-	if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) +
+-		((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+-			("SkGeInitAssignRamToQueues: Not enough memory (%d)\n",
+-			 pAC->GIni.GIRamSize));
+-		return(2);
+-	}
+-
+-	if (DualNet) {
+-		/* every port gets the same amount of memory */
+-		ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound;
+-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-
+-			pGePort = &pAC->GIni.GP[i];
+-			
+-			/* take away the minimum memory for active queues */
+-			ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
+-
+-			/* receive queue gets the minimum + 80% of the rest */
+-			pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((
+-				ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100))
+-				+ SK_MIN_RXQ_SIZE;
+-
+-			ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
+-
+-			/* synchronous transmit queue */
+-			pGePort->PXSQSize = 0;
+-
+-			/* asynchronous transmit queue */
+-			pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes +
+-				SK_MIN_TXQ_SIZE);
+-		}
+-	}
+-	else {	
+-		/* Rlmt Mode or single link adapter */
+-
+-		/* Set standby queue size defaults for all standby ports */
+-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-
+-			if (i != ActivePort) {
+-				pGePort = &pAC->GIni.GP[i];
+-
+-				pGePort->PRxQSize = SK_MIN_RXQ_SIZE;
+-				pGePort->PXAQSize = SK_MIN_TXQ_SIZE;
+-				pGePort->PXSQSize = 0;
+-
+-				/* Count used RAM */
+-				UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize;
+-			}
+-		}
+-		/* what's left? */
+-		ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes;
+-
+-		/* assign it to the active port */
+-		/* first take away the minimum memory */
+-		ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
+-		pGePort = &pAC->GIni.GP[ActivePort];
+-
+-		/* receive queue get's the minimum + 80% of the rest */
+-		pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes *
+-			(unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE;
+-
+-		ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
+-
+-		/* synchronous transmit queue */
+-		pGePort->PXSQSize = 0;
+-
+-		/* asynchronous transmit queue */
+-		pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) +
+-			SK_MIN_TXQ_SIZE;
+-	}
+-#ifdef VCPU
+-	VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n",
+-		pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize);
+-#endif /* VCPU */
+-
+-	return(0);
+-}	/* SkGeInitAssignRamToQueues */
+-
+-/******************************************************************************
+- *
+- *	SkGeCheckQSize() - Checks the Adapters Queue Size Configuration
+- *
+- * Description:
+- *	This function verifies the Queue Size Configuration specified
+- *	in the variables PRxQSize, PXSQSize, and PXAQSize of all
+- *	used ports.
+- *	This requirements must be fullfilled to have a valid configuration:
+- *		- The size of all queues must not exceed GIRamSize.
+- *		- The queue sizes must be specified in units of 8 kB.
+- *		- The size of Rx queues of available ports must not be
+- *		  smaller than 16 kB.
+- *		- The size of at least one Tx queue (synch. or asynch.)
+- *        of available ports must not be smaller than 16 kB
+- *        when Jumbo Frames are used.
+- *		- The RAM start and end addresses must not be changed
+- *		  for ports which are already initialized.
+- *	Furthermore SkGeCheckQSize() defines the Start and End Addresses
+- *  of all ports and stores them into the HWAC port	structure.
+- *
+- * Returns:
+- *	0:	Queue Size Configuration valid
+- *	1:	Queue Size Configuration invalid
+- */
+-static int SkGeCheckQSize(
+-SK_AC	 *pAC,		/* adapter context */
+-int		 Port)		/* port index */
+-{
+-	SK_GEPORT *pPrt;
+-	int	i;
+-	int	Rtv;
+-	int	Rtv2;
+-	SK_U32	StartAddr;
+-#ifndef SK_SLIM
+-	int	UsedMem;	/* total memory used (max. found ports) */
+-#endif	
+-
+-	Rtv = 0;
+-	
+-#ifndef SK_SLIM
+-
+-	UsedMem = 0;
+-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-		pPrt = &pAC->GIni.GP[i];
+-
+-		if ((pPrt->PRxQSize & QZ_UNITS) != 0 ||
+-			(pPrt->PXSQSize & QZ_UNITS) != 0 ||
+-			(pPrt->PXAQSize & QZ_UNITS) != 0) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
+-			return(1);
+-		}
+-
+-		if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG);
+-			return(1);
+-		}
+-		
+-		/*
+-		 * the size of at least one Tx queue (synch. or asynch.) has to be > 0.
+-		 * if Jumbo Frames are used, this size has to be >= 16 kB.
+-		 */
+-		if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) ||
+-			(pAC->GIni.GIPortUsage == SK_JUMBO_LINK &&
+-            ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
+-			 (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) {
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG);
+-				return(1);
+-		}
+-		
+-		UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize;
+-	}
+-	
+-	if (UsedMem > pAC->GIni.GIRamSize) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
+-		return(1);
+-	}
+-#endif	/* !SK_SLIM */
+-
+-	/* Now start address calculation */
+-	StartAddr = pAC->GIni.GIRamOffs;
+-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-		pPrt = &pAC->GIni.GP[i];
+-
+-		/* Calculate/Check values for the receive queue */
+-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr,
+-			&pPrt->PRxQRamStart, &pPrt->PRxQRamEnd);
+-		Rtv |= Rtv2;
+-
+-		/* Calculate/Check values for the synchronous Tx queue */
+-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr,
+-			&pPrt->PXsQRamStart, &pPrt->PXsQRamEnd);
+-		Rtv |= Rtv2;
+-
+-		/* Calculate/Check values for the asynchronous Tx queue */
+-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr,
+-			&pPrt->PXaQRamStart, &pPrt->PXaQRamEnd);
+-		Rtv |= Rtv2;
+-
+-		if (Rtv) {
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG);
+-			return(1);
+-		}
+-	}
+-
+-	return(0);
+-}	/* SkGeCheckQSize */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkGeInitMacArb() - Initialize the MAC Arbiter
+- *
+- * Description:
+- *	This function initializes the MAC Arbiter.
+- *	It must not be called if there is still an
+- *	initialized or active port.
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGeInitMacArb(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC)		/* IO context */
+-{
+-	/* release local reset */
+-	SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR);
+-
+-	/* configure timeout values */
+-	SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53);
+-	SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53);
+-	SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53);
+-	SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53);
+-
+-	SK_OUT8(IoC, B3_MA_RCINI_RX1, 0);
+-	SK_OUT8(IoC, B3_MA_RCINI_RX2, 0);
+-	SK_OUT8(IoC, B3_MA_RCINI_TX1, 0);
+-	SK_OUT8(IoC, B3_MA_RCINI_TX2, 0);
+-
+-	/* recovery values are needed for XMAC II Rev. B2 only */
+-	/* Fast Output Enable Mode was intended to use with Rev. B2, but now? */
+-
+-	/*
+-	 * There is no start or enable button to push, therefore
+-	 * the MAC arbiter is configured and enabled now.
+-	 */
+-}	/* SkGeInitMacArb */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeInitPktArb() - Initialize the Packet Arbiter
+- *
+- * Description:
+- *	This function initializes the Packet Arbiter.
+- *	It must not be called if there is still an
+- *	initialized or active port.
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGeInitPktArb(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC)		/* IO context */
+-{
+-	/* release local reset */
+-	SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR);
+-
+-	/* configure timeout values */
+-	SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
+-	SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
+-	SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
+-	SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
+-
+-	/*
+-	 * enable timeout timers if jumbo frames not used
+-	 * NOTE: the packet arbiter timeout interrupt is needed for
+-	 * half duplex hangup workaround
+-	 */
+-	if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) {
+-		if (pAC->GIni.GIMacsFound == 1) {
+-			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1);
+-		}
+-		else {
+-			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2);
+-		}
+-	}
+-}	/* SkGeInitPktArb */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeInitMacFifo() - Initialize the MAC FIFOs
+- *
+- * Description:
+- *	Initialize all MAC FIFOs of the specified port
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGeInitMacFifo(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_U16	Word;
+-#ifdef VCPU
+-	SK_U32	DWord;
+-#endif /* VCPU */
+-	/*
+-	 * For each FIFO:
+-	 *	- release local reset
+-	 *	- use default value for MAC FIFO size
+-	 *	- setup defaults for the control register
+-	 *	- enable the FIFO
+-	 */
+-	
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		/* Configure Rx MAC FIFO */
+-		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR);
+-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF);
+-		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
+-	
+-		/* Configure Tx MAC FIFO */
+-		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR);
+-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
+-		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
+-	
+-		/* Enable frame flushing if jumbo frames used */
+-		if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+-			SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH);
+-		}
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		/* set Rx GMAC FIFO Flush Mask */
+-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK);
+-		
+-		Word = (SK_U16)GMF_RX_CTRL_DEF;
+-
+-		/* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
+-		if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+-
+-			Word &= ~GMF_RX_F_FL_ON;
+-		}
+-		
+-		/* Configure Rx MAC FIFO */
+-		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
+-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word);
+-		
+-		/* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */
+-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+-		
+-		/* Configure Tx MAC FIFO */
+-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
+-		SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
+-		
+-#ifdef VCPU
+-		SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord);
+-		SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord);
+-#endif /* VCPU */
+-		
+-		/* set Tx GMAC FIFO Almost Empty Threshold */
+-/*		SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */
+-	}
+-#endif /* YUKON */
+-
+-}	/* SkGeInitMacFifo */
+-
+-#ifdef	SK_LNK_SYNC_CNT
+-/******************************************************************************
+- *
+- *	SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting
+- *
+- * Description:
+- *	This function starts the Link Sync Counter of the specified
+- *	port and enables the generation of an Link Sync IRQ.
+- *	The Link Sync Counter may be used to detect an active link,
+- *	if autonegotiation is not used.
+- *
+- * Note:
+- *	o To ensure receiving the Link Sync Event the LinkSyncCounter
+- *	  should be initialized BEFORE clearing the XMAC's reset!
+- *	o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this
+- *	  function.
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGeLoadLnkSyncCnt(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_U32	CntVal)		/* Counter value */
+-{
+-	SK_U32	OrgIMsk;
+-	SK_U32	NewIMsk;
+-	SK_U32	ISrc;
+-	SK_BOOL	IrqPend;
+-
+-	/* stop counter */
+-	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP);
+-
+-	/*
+-	 * ASIC problem:
+-	 * Each time starting the Link Sync Counter an IRQ is generated
+-	 * by the adapter. See problem report entry from 21.07.98
+-	 *
+-	 * Workaround:	Disable Link Sync IRQ and clear the unexpeced IRQ
+-	 *		if no IRQ is already pending.
+-	 */
+-	IrqPend = SK_FALSE;
+-	SK_IN32(IoC, B0_ISRC, &ISrc);
+-	SK_IN32(IoC, B0_IMSK, &OrgIMsk);
+-	if (Port == MAC_1) {
+-		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1;
+-		if ((ISrc & IS_LNK_SYNC_M1) != 0) {
+-			IrqPend = SK_TRUE;
+-		}
+-	}
+-	else {
+-		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2;
+-		if ((ISrc & IS_LNK_SYNC_M2) != 0) {
+-			IrqPend = SK_TRUE;
+-		}
+-	}
+-	if (!IrqPend) {
+-		SK_OUT32(IoC, B0_IMSK, NewIMsk);
+-	}
+-
+-	/* load counter */
+-	SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal);
+-
+-	/* start counter */
+-	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START);
+-
+-	if (!IrqPend) {
+-		/* clear the unexpected IRQ, and restore the interrupt mask */
+-		SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ);
+-		SK_OUT32(IoC, B0_IMSK, OrgIMsk);
+-	}
+-}	/* SkGeLoadLnkSyncCnt*/
+-#endif	/* SK_LNK_SYNC_CNT */
+-
+-#if defined(SK_DIAG) || defined(SK_CFG_SYNC)
+-/******************************************************************************
+- *
+- *	SkGeCfgSync() - Configure synchronous bandwidth for this port.
+- *
+- * Description:
+- *	This function may be used to configure synchronous bandwidth
+- *	to the specified port. This may be done any time after
+- *	initializing the port. The configuration values are NOT saved
+- *	in the HWAC port structure and will be overwritten any
+- *	time when stopping and starting the port.
+- *	Any values for the synchronous configuration will be ignored
+- *	if the size of the synchronous queue is zero!
+- *
+- *	The default configuration for the synchronous service is
+- *	TXA_ENA_FSYNC. This means if the size of
+- *	the synchronous queue is unequal zero but no specific
+- *	synchronous bandwidth is configured, the synchronous queue
+- *	will always have the 'unlimited' transmit priority!
+- *
+- *	This mode will be restored if the synchronous bandwidth is
+- *	deallocated ('IntTime' = 0 and 'LimCount' = 0).
+- *
+- * Returns:
+- *	0:	success
+- *	1:	parameter configuration error
+- *	2:	try to configure quality of service although no
+- *		synchronous queue is configured
+- */
+-int SkGeCfgSync(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_U32	IntTime,	/* Interval Timer Value in units of 8ns */
+-SK_U32	LimCount,	/* Number of bytes to transfer during IntTime */
+-int		SyncMode)	/* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */
+-{
+-	int Rtv;
+-
+-	Rtv = 0;
+-
+-	/* check the parameters */
+-	if (LimCount > IntTime ||
+-		(LimCount == 0 && IntTime != 0) ||
+-		(LimCount != 0 && IntTime == 0)) {
+-
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
+-		return(1);
+-	}
+-	
+-	if (pAC->GIni.GP[Port].PXSQSize == 0) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG);
+-		return(2);
+-	}
+-	
+-	/* calculate register values */
+-	IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100;
+-	LimCount = LimCount / 8;
+-	
+-	if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
+-		return(1);
+-	}
+-
+-	/*
+-	 * - Enable 'Force Sync' to ensure the synchronous queue
+-	 *   has the priority while configuring the new values.
+-	 * - Also 'disable alloc' to ensure the settings complies
+-	 *   to the SyncMode parameter.
+-	 * - Disable 'Rate Control' to configure the new values.
+-	 * - write IntTime and LimCount
+-	 * - start 'Rate Control' and disable 'Force Sync'
+-	 *   if Interval Timer or Limit Counter not zero.
+-	 */
+-	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+-		TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+-	
+-	SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime);
+-	SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount);
+-	
+-	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+-		(SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC)));
+-	
+-	if (IntTime != 0 || LimCount != 0) {
+-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC);
+-	}
+-
+-	return(0);
+-}	/* SkGeCfgSync */
+-#endif /* SK_DIAG || SK_CFG_SYNC*/
+-
+-
+-/******************************************************************************
+- *
+- *	DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue
+- *
+- * Desccription:
+- *	If the queue is used, enable and initialize it.
+- *	Make sure the queue is still reset, if it is not used.
+- *
+- * Returns:
+- *	nothing
+- */
+-static void DoInitRamQueue(
+-SK_AC	*pAC,			/* adapter context */
+-SK_IOC	IoC,			/* IO context */
+-int		QuIoOffs,		/* Queue IO Address Offset */
+-SK_U32	QuStartAddr,	/* Queue Start Address */
+-SK_U32	QuEndAddr,		/* Queue End Address */
+-int		QuType)			/* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */
+-{
+-	SK_U32	RxUpThresVal;
+-	SK_U32	RxLoThresVal;
+-
+-	if (QuStartAddr != QuEndAddr) {
+-		/* calculate thresholds, assume we have a big Rx queue */
+-		RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8;
+-		RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8;
+-
+-		/* build HW address format */
+-		QuStartAddr = QuStartAddr / 8;
+-		QuEndAddr = QuEndAddr / 8;
+-
+-		/* release local reset */
+-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR);
+-
+-		/* configure addresses */
+-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr);
+-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr);
+-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr);
+-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr);
+-
+-		switch (QuType) {
+-		case SK_RX_SRAM_Q:
+-			/* configure threshold for small Rx Queue */
+-			RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8;
+-
+-			/* continue with SK_RX_BRAM_Q */
+-		case SK_RX_BRAM_Q:
+-			/* write threshold for Rx Queue */
+-
+-			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal);
+-			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal);
+-
+-			/* the high priority threshold not used */
+-			break;
+-		case SK_TX_RAM_Q:
+-			/*
+-			 * Do NOT use Store & Forward under normal operation due to
+-			 * performance optimization (GENESIS only).
+-			 * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB)
+-			 * or YUKON is used ((GMAC Tx FIFO is only 1 kB)
+-			 * we NEED Store & Forward of the RAM buffer.
+-			 */
+-			if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK ||
+-				pAC->GIni.GIYukon) {
+-				/* enable Store & Forward Mode for the Tx Side */
+-				SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD);
+-			}
+-			break;
+-		}
+-
+-		/* set queue operational */
+-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD);
+-	}
+-	else {
+-		/* ensure the queue is still disabled */
+-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET);
+-	}
+-}	/* DoInitRamQueue */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeInitRamBufs() - Initialize the RAM Buffer Queues
+- *
+- * Description:
+- *	Initialize all RAM Buffer Queues of the specified port
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGeInitRamBufs(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT *pPrt;
+-	int RxQType;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) {
+-		RxQType = SK_RX_SRAM_Q; 	/* small Rx Queue */
+-	}
+-	else {
+-		RxQType = SK_RX_BRAM_Q;		/* big Rx Queue */
+-	}
+-
+-	DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart,
+-		pPrt->PRxQRamEnd, RxQType);
+-	
+-	DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart,
+-		pPrt->PXsQRamEnd, SK_TX_RAM_Q);
+-	
+-	DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
+-		pPrt->PXaQRamEnd, SK_TX_RAM_Q);
+-
+-}	/* SkGeInitRamBufs */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeInitRamIface() - Initialize the RAM Interface
+- *
+- * Description:
+- *	This function initializes the Adapters RAM Interface.
+- *
+- * Note:
+- *	This function is used in the diagnostics.
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGeInitRamIface(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC)		/* IO context */
+-{
+-	/* release local reset */
+-	SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR);
+-
+-	/* configure timeout values */
+-	SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53);
+-	SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53);
+-
+-}	/* SkGeInitRamIface */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeInitBmu() - Initialize the BMU state machines
+- *
+- * Description:
+- *	Initialize all BMU state machines of the specified port
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGeInitBmu(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U32		RxWm;
+-	SK_U32		TxWm;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	RxWm = SK_BMU_RX_WM;
+-	TxWm = SK_BMU_TX_WM;
+-	
+-	if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
+-		/* for better performance */
+-		RxWm /= 2;
+-		TxWm /= 2;
+-	}
+-
+-	/* Rx Queue: Release all local resets and set the watermark */
+-	SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
+-	SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
+-
+-	/*
+-	 * Tx Queue: Release all local resets if the queue is used !
+-	 * 		set watermark
+-	 */
+-	if (pPrt->PXSQSize != 0) {
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
+-	}
+-	
+-	if (pPrt->PXAQSize != 0) {
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
+-	}
+-	/*
+-	 * Do NOT enable the descriptor poll timers here, because
+-	 * the descriptor addresses are not specified yet.
+-	 */
+-}	/* SkGeInitBmu */
+-
+-
+-/******************************************************************************
+- *
+- *	TestStopBit() -	Test the stop bit of the queue
+- *
+- * Description:
+- *	Stopping a queue is not as simple as it seems to be.
+- *	If descriptor polling is enabled, it may happen
+- *	that RX/TX stop is done and SV idle is NOT set.
+- *	In this case we have to issue another stop command.
+- *
+- * Returns:
+- *	The queues control status register
+- */
+-static SK_U32 TestStopBit(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO Context */
+-int		QuIoOffs)	/* Queue IO Address Offset */
+-{
+-	SK_U32	QuCsr;	/* CSR contents */
+-
+-	SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
+-	
+-	if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
+-		/* Stop Descriptor overridden by start command */
+-		SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
+-
+-		SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
+-	}
+-	
+-	return(QuCsr);
+-}	/* TestStopBit */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'.
+- *
+- * Description:
+- *	After calling this function the descriptor rings and Rx and Tx
+- *	queues of this port may be reconfigured.
+- *
+- *	It is possible to stop the receive and transmit path separate or
+- *	both together.
+- *
+- *	Dir =	SK_STOP_TX 	Stops the transmit path only and resets the MAC.
+- *				The receive queue is still active and
+- *				the pending Rx frames may be still transferred
+- *				into the RxD.
+- *		SK_STOP_RX	Stop the receive path. The tansmit path
+- *				has to be stopped once before.
+- *		SK_STOP_ALL	SK_STOP_TX + SK_STOP_RX
+- *
+- *	RstMode = SK_SOFT_RST	Resets the MAC. The PHY is still alive.
+- *			SK_HARD_RST	Resets the MAC and the PHY.
+- *
+- * Example:
+- *	1) A Link Down event was signaled for a port. Therefore the activity
+- *	of this port should be stopped and a hardware reset should be issued
+- *	to enable the workaround of XMAC Errata #2. But the received frames
+- *	should not be discarded.
+- *		...
+- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST);
+- *		(transfer all pending Rx frames)
+- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST);
+- *		...
+- *
+- *	2) An event was issued which request the driver to switch
+- *	the 'virtual active' link to an other already active port
+- *	as soon as possible. The frames in the receive queue of this
+- *	port may be lost. But the PHY must not be reset during this
+- *	event.
+- *		...
+- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST);
+- *		...
+- *
+- * Extended Description:
+- *	If SK_STOP_TX is set,
+- *		o disable the MAC's receive and transmitter to prevent
+- *		  from sending incomplete frames
+- *		o stop the port's transmit queues before terminating the
+- *		  BMUs to prevent from performing incomplete PCI cycles
+- *		  on the PCI bus
+- *		- The network Rx and Tx activity and PCI Tx transfer is
+- *		  disabled now.
+- *		o reset the MAC depending on the RstMode
+- *		o Stop Interval Timer and Limit Counter of Tx Arbiter,
+- *		  also disable Force Sync bit and Enable Alloc bit.
+- *		o perform a local reset of the port's Tx path
+- *			- reset the PCI FIFO of the async Tx queue
+- *			- reset the PCI FIFO of the sync Tx queue
+- *			- reset the RAM Buffer async Tx queue
+- *			- reset the RAM Buffer sync Tx queue
+- *			- reset the MAC Tx FIFO
+- *		o switch Link and Tx LED off, stop the LED counters
+- *
+- *	If SK_STOP_RX is set,
+- *		o stop the port's receive queue
+- *		- The path data transfer activity is fully stopped now.
+- *		o perform a local reset of the port's Rx path
+- *			- reset the PCI FIFO of the Rx queue
+- *			- reset the RAM Buffer receive queue
+- *			- reset the MAC Rx FIFO
+- *		o switch Rx LED off, stop the LED counter
+- *
+- *	If all ports are stopped,
+- *		o reset the RAM Interface.
+- *
+- * Notes:
+- *	o This function may be called during the driver states RESET_PORT and
+- *	  SWITCH_PORT.
+- */
+-void SkGeStopPort(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* I/O context */
+-int		Port,	/* port to stop (MAC_1 + n) */
+-int		Dir,	/* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
+-int		RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
+-{
+-#ifndef SK_DIAG
+-	SK_EVPARA Para;
+-#endif /* !SK_DIAG */
+-	SK_GEPORT *pPrt;
+-	SK_U32	DWord;
+-	SK_U32	XsCsr;
+-	SK_U32	XaCsr;
+-	SK_U64	ToutStart;
+-	int		i;
+-	int		ToutCnt;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if ((Dir & SK_STOP_TX) != 0) {
+-		/* disable receiver and transmitter */
+-		SkMacRxTxDisable(pAC, IoC, Port);
+-		
+-		/* stop both transmit queues */
+-		/*
+-		 * If the BMU is in the reset state CSR_STOP will terminate
+-		 * immediately.
+-		 */
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP);
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP);
+-
+-		ToutStart = SkOsGetTime(pAC);
+-		ToutCnt = 0;
+-		do {
+-			/*
+-			 * Clear packet arbiter timeout to make sure
+-			 * this loop will terminate.
+-			 */
+-			SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
+-				PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
+-
+-			/*
+-			 * If the transfer stucks at the MAC the STOP command will not
+-			 * terminate if we don't flush the XMAC's transmit FIFO !
+-			 */
+-			SkMacFlushTxFifo(pAC, IoC, Port);
+-
+-			XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
+-			XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
+-
+-			if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
+-				/*
+-				 * Timeout of 1/18 second reached.
+-				 * This needs to be checked at 1/18 sec only.
+-				 */
+-				ToutCnt++;
+-				if (ToutCnt > 1) {
+-					/* Might be a problem when the driver event handler
+-					 * calls StopPort again. XXX.
+-					 */
+-
+-					/* Fatal Error, Loop aborted */
+-					SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018,
+-						SKERR_HWI_E018MSG);
+-#ifndef SK_DIAG
+-					Para.Para64 = Port;
+-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-#endif /* !SK_DIAG */
+-					return;
+-				}
+-				/*
+-				 * Cache incoherency workaround: Assume a start command
+-				 * has been lost while sending the frame.
+-				 */
+-				ToutStart = SkOsGetTime(pAC);
+-
+-				if ((XsCsr & CSR_STOP) != 0) {
+-					SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START);
+-				}
+-				if ((XaCsr & CSR_STOP) != 0) {
+-					SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START);
+-				}
+-			}
+-
+-			/*
+-			 * Because of the ASIC problem report entry from 21.08.1998 it is
+-			 * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
+-			 */
+-		} while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE ||
+-				 (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
+-
+-		/* Reset the MAC depending on the RstMode */
+-		if (RstMode == SK_SOFT_RST) {
+-			SkMacSoftRst(pAC, IoC, Port);
+-		}
+-		else {
+-			SkMacHardRst(pAC, IoC, Port);
+-		}
+- 		
+-		/* Disable Force Sync bit and Enable Alloc bit */
+-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+-			TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+-		
+-		/* Stop Interval Timer and Limit Counter of Tx Arbiter */
+-		SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L);
+-		SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L);
+-
+-		/* Perform a local reset of the port's Tx path */
+-
+-		/* Reset the PCI FIFO of the async Tx queue */
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
+-		/* Reset the PCI FIFO of the sync Tx queue */
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
+-		/* Reset the RAM Buffer async Tx queue */
+-		SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
+-		/* Reset the RAM Buffer sync Tx queue */
+-		SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET);
+-		
+-		/* Reset Tx MAC FIFO */
+-#ifdef GENESIS
+-		if (pAC->GIni.GIGenesis) {
+-			/* Note: MFF_RST_SET does NOT reset the XMAC ! */
+-			SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET);
+-
+-			/* switch Link and Tx LED off, stop the LED counters */
+-			/* Link LED is switched off by the RLMT and the Diag itself */
+-			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS);
+-		}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-		if (pAC->GIni.GIYukon) {
+-			/* Reset TX MAC FIFO */
+-			SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
+-		}
+-#endif /* YUKON */
+-	}
+-
+-	if ((Dir & SK_STOP_RX) != 0) {
+-		/*
+-		 * The RX Stop Command will not terminate if no buffers
+-		 * are queued in the RxD ring. But it will always reach
+-		 * the Idle state. Therefore we can use this feature to
+-		 * stop the transfer of received packets.
+-		 */
+-		/* stop the port's receive queue */
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP);
+-		
+-		i = 100;
+-		do {
+-			/*
+-			 * Clear packet arbiter timeout to make sure
+-			 * this loop will terminate
+-			 */
+-			SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
+-				PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
+-
+-			DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff);
+-
+-			/* timeout if i==0 (bug fix for #10748) */
+-			if (--i == 0) {
+-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
+-					SKERR_HWI_E024MSG);
+-				break;
+-			}
+-			/*
+-			 * because of the ASIC problem report entry from 21.08.98
+-			 * it is required to wait until CSR_STOP is reset and
+-			 * CSR_SV_IDLE is set.
+-			 */
+-		} while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
+-
+-		/* The path data transfer activity is fully stopped now */
+-
+-		/* Perform a local reset of the port's Rx path */
+-
+-		 /*	Reset the PCI FIFO of the Rx queue */
+-		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
+-		/* Reset the RAM Buffer receive queue */
+-		SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET);
+-
+-		/* Reset Rx MAC FIFO */
+-#ifdef GENESIS
+-		if (pAC->GIni.GIGenesis) {
+-			
+-			SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET);
+-
+-			/* switch Rx LED off, stop the LED counter */
+-			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS);
+-		}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-		if (pAC->GIni.GIYukon) {
+-			/* Reset Rx MAC FIFO */
+-			SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
+-		}
+-#endif /* YUKON */
+-	}
+-}	/* SkGeStopPort */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeInit0() - Level 0 Initialization
+- *
+- * Description:
+- *	- Initialize the BMU address offsets
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGeInit0(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC)		/* IO context */
+-{
+-	int i;
+-	SK_GEPORT *pPrt;
+-
+-	for (i = 0; i < SK_MAX_MACS; i++) {
+-		pPrt = &pAC->GIni.GP[i];
+-
+-		pPrt->PState = SK_PRT_RESET;
+-		pPrt->PRxQOff = QOffTab[i].RxQOff;
+-		pPrt->PXsQOff = QOffTab[i].XsQOff;
+-		pPrt->PXaQOff = QOffTab[i].XaQOff;
+-		pPrt->PCheckPar = SK_FALSE;
+-		pPrt->PIsave = 0;
+-		pPrt->PPrevShorts = 0;
+-		pPrt->PLinkResCt = 0;
+-		pPrt->PAutoNegTOCt = 0;
+-		pPrt->PPrevRx = 0;
+-		pPrt->PPrevFcs = 0;
+-		pPrt->PRxLim = SK_DEF_RX_WA_LIM;
+-		pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
+-		pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS;
+-		pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS;
+-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN;
+-		pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE;
+-		pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
+-		pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL |
+-			SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL);
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+-		pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
+-		pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+-		pPrt->PMSCap = 0;
+-		pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO;
+-		pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET;
+-		pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
+-		pPrt->PAutoNegFail = SK_FALSE;
+-		pPrt->PHWLinkUp = SK_FALSE;
+-		pPrt->PLinkBroken = SK_TRUE; /* See WA code */
+-		pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
+-		pPrt->PMacColThres = TX_COL_DEF;
+-		pPrt->PMacJamLen = TX_JAM_LEN_DEF;
+-		pPrt->PMacJamIpgVal	= TX_JAM_IPG_DEF;
+-		pPrt->PMacJamIpgData = TX_IPG_JAM_DEF;
+-		pPrt->PMacIpgData = IPG_DATA_DEF;
+-		pPrt->PMacLimit4 = SK_FALSE;
+-	}
+-
+-	pAC->GIni.GIPortUsage = SK_RED_LINK;
+-	pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value;
+-	pAC->GIni.GIValIrqMask = IS_ALL_MSK;
+-
+-}	/* SkGeInit0*/
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeInit1() - Level 1 Initialization
+- *
+- * Description:
+- *	o Do a software reset.
+- *	o Clear all reset bits.
+- *	o Verify that the detected hardware is present.
+- *	  Return an error if not.
+- *	o Get the hardware configuration
+- *		+ Read the number of MACs/Ports.
+- *		+ Read the RAM size.
+- *		+ Read the PCI Revision Id.
+- *		+ Find out the adapters host clock speed
+- *		+ Read and check the PHY type
+- *
+- * Returns:
+- *	0:	success
+- *	5:	Unexpected PHY type detected
+- *	6:	HW self test failed
+- */
+-static int SkGeInit1(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC)		/* IO context */
+-{
+-	SK_U8	Byte;
+-	SK_U16	Word;
+-	SK_U16	CtrlStat;
+-	SK_U32	DWord;
+-	int	RetVal;
+-	int	i;
+-
+-	RetVal = 0;
+-
+-	/* save CLK_RUN bits (YUKON-Lite) */
+-	SK_IN16(IoC, B0_CTST, &CtrlStat);
+-
+-	/* do the SW-reset */
+-	SK_OUT8(IoC, B0_CTST, CS_RST_SET);
+-
+-	/* release the SW-reset */
+-	SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
+-
+-	/* reset all error bits in the PCI STATUS register */
+-	/*
+-	 * Note: PCI Cfg cycles cannot be used, because they are not
+-	 *		 available on some platforms after 'boot time'.
+-	 */
+-	SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
+-	
+-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+-	SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+-
+-	/* release Master Reset */
+-	SK_OUT8(IoC, B0_CTST, CS_MRST_CLR);
+-
+-#ifdef CLK_RUN
+-	CtrlStat |= CS_CLK_RUN_ENA;
+-#endif /* CLK_RUN */
+-
+-	/* restore CLK_RUN bits */
+-	SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat &
+-		(CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)));
+-
+-	/* read Chip Identification Number */
+-	SK_IN8(IoC, B2_CHIP_ID, &Byte);
+-	pAC->GIni.GIChipId = Byte;
+-	
+-	/* read number of MACs */
+-	SK_IN8(IoC, B2_MAC_CFG, &Byte);
+-	pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
+-	
+-	/* get Chip Revision Number */
+-	pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4);
+-
+-	/* get diff. PCI parameters */
+-	SK_IN16(IoC, B0_CTST, &CtrlStat);
+-	
+-	/* read the adapters RAM size */
+-	SK_IN8(IoC, B2_E_0, &Byte);
+-	
+-	pAC->GIni.GIGenesis = SK_FALSE;
+-	pAC->GIni.GIYukon = SK_FALSE;
+-	pAC->GIni.GIYukonLite = SK_FALSE;
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+-
+-		pAC->GIni.GIGenesis = SK_TRUE;
+-
+-		if (Byte == (SK_U8)3) {						
+-			/* special case: 4 x 64k x 36, offset = 0x80000 */
+-			pAC->GIni.GIRamSize = 1024;
+-			pAC->GIni.GIRamOffs = (SK_U32)512 * 1024;
+-		}
+-		else {
+-			pAC->GIni.GIRamSize = (int)Byte * 512;
+-			pAC->GIni.GIRamOffs = 0;
+-		}
+-		/* all GE adapters work with 53.125 MHz host clock */
+-		pAC->GIni.GIHstClkFact = SK_FACT_53;
+-		
+-		/* set Descr. Poll Timer Init Value to 250 ms */
+-		pAC->GIni.GIPollTimerVal =
+-			SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
+-		
+-		pAC->GIni.GIYukon = SK_TRUE;
+-		
+-		pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4;
+-		
+-		pAC->GIni.GIRamOffs = 0;
+-		
+-		/* WA for chip Rev. A */
+-		pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON &&
+-			pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0;
+-		
+-		/* get PM Capabilities of PCI config space */
+-		SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word);
+-
+-		/* check if VAUX is available */
+-		if (((CtrlStat & CS_VAUX_AVAIL) != 0) &&
+-			/* check also if PME from D3cold is set */
+-			((Word & PCI_PME_D3C_SUP) != 0)) {
+-			/* set entry in GE init struct */
+-			pAC->GIni.GIVauxAvail = SK_TRUE;
+-		}
+-		
+-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
+-			/* this is Rev. A1 */
+-			pAC->GIni.GIYukonLite = SK_TRUE;
+-		}
+-		else {
+-			/* save Flash-Address Register */
+-			SK_IN32(IoC, B2_FAR, &DWord);
+-
+-			/* test Flash-Address Register */
+-			SK_OUT8(IoC, B2_FAR + 3, 0xff);
+-			SK_IN8(IoC, B2_FAR + 3, &Byte);
+-
+-			if (Byte != 0) {
+-				/* this is Rev. A0 */
+-				pAC->GIni.GIYukonLite = SK_TRUE;
+-
+-				/* restore Flash-Address Register */
+-				SK_OUT32(IoC, B2_FAR, DWord);
+-			}
+-		}
+-
+-		/* switch power to VCC (WA for VAUX problem) */
+-		SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
+-			PC_VAUX_OFF | PC_VCC_ON));
+-
+-		/* read the Interrupt source */
+-		SK_IN32(IoC, B0_ISRC, &DWord);
+-		
+-		if ((DWord & IS_HW_ERR) != 0) {
+-			/* read the HW Error Interrupt source */
+-			SK_IN32(IoC, B0_HWE_ISRC, &DWord);
+-			
+-			if ((DWord & IS_IRQ_SENSOR) != 0) {
+-				/* disable HW Error IRQ */
+-				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
+-			}
+-		}
+-		
+-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-			/* set GMAC Link Control reset */
+-			SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+-
+-			/* clear GMAC Link Control reset */
+-			SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+-		}
+-		/* all YU chips work with 78.125 MHz host clock */
+-		pAC->GIni.GIHstClkFact = SK_FACT_78;
+-		
+-		pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;	/* 215 ms */
+-	}
+-#endif /* YUKON */
+-
+-	/* check if 64-bit PCI Slot is present */
+-	pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
+-	
+-	/* check if 66 MHz PCI Clock is active */
+-	pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
+-
+-	/* read PCI HW Revision Id. */
+-	SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte);
+-	pAC->GIni.GIPciHwRev = Byte;
+-
+-	/* read the PMD type */
+-	SK_IN8(IoC, B2_PMD_TYP, &Byte);
+-	pAC->GIni.GICopperType = (SK_U8)(Byte == 'T');
+-
+-	/* read the PHY type */
+-	SK_IN8(IoC, B2_E_1, &Byte);
+-
+-	Byte &= 0x0f;	/* the PHY type is stored in the lower nibble */
+-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-		
+-#ifdef GENESIS
+-		if (pAC->GIni.GIGenesis) {
+-			switch (Byte) {
+-			case SK_PHY_XMAC:
+-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC;
+-				break;
+-			case SK_PHY_BCOM:
+-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM;
+-				pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
+-					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
+-				break;
+-#ifdef OTHER_PHY
+-			case SK_PHY_LONE:
+-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE;
+-				break;
+-			case SK_PHY_NAT:
+-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT;
+-				break;
+-#endif /* OTHER_PHY */
+-			default:
+-				/* ERROR: unexpected PHY type detected */
+-				RetVal = 5;
+-				break;
+-			}
+-		}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-		if (pAC->GIni.GIYukon) {
+-			
+-			if (Byte < (SK_U8)SK_PHY_MARV_COPPER) {
+-				/* if this field is not initialized */
+-				Byte = (SK_U8)SK_PHY_MARV_COPPER;
+-				
+-				pAC->GIni.GICopperType = SK_TRUE;
+-			}
+-			
+-			pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV;
+-			
+-			if (pAC->GIni.GICopperType) {
+-
+-				pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO |
+-					SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS |
+-					SK_LSPEED_CAP_1000MBPS);
+-				
+-				pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
+-				
+-				pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
+-					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
+-			}
+-			else {
+-				Byte = (SK_U8)SK_PHY_MARV_FIBER;
+-			}
+-		}
+-#endif /* YUKON */
+-		
+-		pAC->GIni.GP[i].PhyType = (int)Byte;
+-		
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+-			("PHY type: %d  PHY addr: %04x\n", Byte,
+-			pAC->GIni.GP[i].PhyAddr));
+-	}
+-	
+-	/* get MAC Type & set function pointers dependent on */
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		pAC->GIni.GIMacType = SK_MAC_XMAC;
+-
+-		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkXmUpdateStats;
+-		pAC->GIni.GIFunc.pFnMacStatistic	= SkXmMacStatistic;
+-		pAC->GIni.GIFunc.pFnMacResetCounter	= SkXmResetCounter;
+-		pAC->GIni.GIFunc.pFnMacOverflow		= SkXmOverflowStatus;
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		
+-		pAC->GIni.GIMacType = SK_MAC_GMAC;
+-
+-		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkGmUpdateStats;
+-		pAC->GIni.GIFunc.pFnMacStatistic	= SkGmMacStatistic;
+-		pAC->GIni.GIFunc.pFnMacResetCounter	= SkGmResetCounter;
+-		pAC->GIni.GIFunc.pFnMacOverflow		= SkGmOverflowStatus;
+-
+-#ifdef SPECIAL_HANDLING
+-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+-			/* check HW self test result */
+-			SK_IN8(IoC, B2_E_3, &Byte);
+-			if (Byte & B2_E3_RES_MASK) {
+-				RetVal = 6;
+-			}
+-		}
+-#endif
+-	}
+-#endif /* YUKON */
+-	
+-	return(RetVal);
+-}	/* SkGeInit1 */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeInit2() - Level 2 Initialization
+- *
+- * Description:
+- *	- start the Blink Source Counter
+- *	- start the Descriptor Poll Timer
+- *	- configure the MAC-Arbiter
+- *	- configure the Packet-Arbiter
+- *	- enable the Tx Arbiters
+- *	- enable the RAM Interface Arbiter
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGeInit2(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC)		/* IO context */
+-{
+-#ifdef GENESIS
+-	SK_U32	DWord;
+-#endif /* GENESIS */
+-	int		i;
+-
+-	/* start the Descriptor Poll Timer */
+-	if (pAC->GIni.GIPollTimerVal != 0) {
+-		if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) {
+-			pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG);
+-		}
+-		SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal);
+-		SK_OUT8(IoC, B28_DPT_CTRL, DPT_START);
+-	}
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		/* start the Blink Source Counter */
+-		DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+-
+-		SK_OUT32(IoC, B2_BSC_INI, DWord);
+-		SK_OUT8(IoC, B2_BSC_CTRL, BSC_START);
+-
+-		/*
+-		 * Configure the MAC Arbiter and the Packet Arbiter.
+-		 * They will be started once and never be stopped.
+-		 */
+-		SkGeInitMacArb(pAC, IoC);
+-
+-		SkGeInitPktArb(pAC, IoC);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		/* start Time Stamp Timer */
+-		SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START);
+-	}
+-#endif /* YUKON */
+-
+-	/* enable the Tx Arbiters */
+-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-		SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB);
+-	}
+-
+-	/* enable the RAM Interface Arbiter */
+-	SkGeInitRamIface(pAC, IoC);
+-
+-}	/* SkGeInit2 */
+-
+-/******************************************************************************
+- *
+- *	SkGeInit() - Initialize the GE Adapter with the specified level.
+- *
+- * Description:
+- *	Level	0:	Initialize the Module structures.
+- *	Level	1:	Generic Hardware Initialization. The IOP/MemBase pointer has
+- *				to be set before calling this level.
+- *
+- *			o Do a software reset.
+- *			o Clear all reset bits.
+- *			o Verify that the detected hardware is present.
+- *			  Return an error if not.
+- *			o Get the hardware configuration
+- *				+ Set GIMacsFound with the number of MACs.
+- *				+ Store the RAM size in GIRamSize.
+- *				+ Save the PCI Revision ID in GIPciHwRev.
+- *			o return an error
+- *				if Number of MACs > SK_MAX_MACS
+- *
+- *			After returning from Level 0 the adapter
+- *			may be accessed with IO operations.
+- *
+- *	Level	2:	start the Blink Source Counter
+- *
+- * Returns:
+- *	0:	success
+- *	1:	Number of MACs exceeds SK_MAX_MACS	(after level 1)
+- *	2:	Adapter not present or not accessible
+- *	3:	Illegal initialization level
+- *	4:	Initialization Level 1 Call missing
+- *	5:	Unexpected PHY type detected
+- *	6:	HW self test failed
+- */
+-int	SkGeInit(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Level)		/* initialization level */
+-{
+-	int		RetVal;		/* return value */
+-	SK_U32	DWord;
+-
+-	RetVal = 0;
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+-		("SkGeInit(Level %d)\n", Level));
+-
+-	switch (Level) {
+-	case SK_INIT_DATA:
+-		/* Initialization Level 0 */
+-		SkGeInit0(pAC, IoC);
+-		pAC->GIni.GILevel = SK_INIT_DATA;
+-		break;
+-	
+-	case SK_INIT_IO:
+-		/* Initialization Level 1 */
+-		RetVal = SkGeInit1(pAC, IoC);
+-		if (RetVal != 0) {
+-			break;
+-		}
+-
+-		/* check if the adapter seems to be accessible */
+-		SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL);
+-		SK_IN32(IoC, B2_IRQM_INI, &DWord);
+-		SK_OUT32(IoC, B2_IRQM_INI, 0L);
+-		
+-		if (DWord != SK_TEST_VAL) {
+-			RetVal = 2;
+-			break;
+-		}
+-
+-		/* check if the number of GIMacsFound matches SK_MAX_MACS */
+-		if (pAC->GIni.GIMacsFound > SK_MAX_MACS) {
+-			RetVal = 1;
+-			break;
+-		}
+-
+-		/* Level 1 successfully passed */
+-		pAC->GIni.GILevel = SK_INIT_IO;
+-		break;
+-	
+-	case SK_INIT_RUN:
+-		/* Initialization Level 2 */
+-		if (pAC->GIni.GILevel != SK_INIT_IO) {
+-#ifndef SK_DIAG
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG);
+-#endif /* !SK_DIAG */
+-			RetVal = 4;
+-			break;
+-		}
+-		SkGeInit2(pAC, IoC);
+-
+-		/* Level 2 successfully passed */
+-		pAC->GIni.GILevel = SK_INIT_RUN;
+-		break;
+-	
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG);
+-		RetVal = 3;
+-		break;
+-	}
+-
+-	return(RetVal);
+-}	/* SkGeInit */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeDeInit() - Deinitialize the adapter
+- *
+- * Description:
+- *	All ports of the adapter will be stopped if not already done.
+- *	Do a software reset and switch off all LEDs.
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGeDeInit(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC)		/* IO context */
+-{
+-	int	i;
+-	SK_U16	Word;
+-
+-#if (!defined(SK_SLIM) && !defined(VCPU))
+-	/* ensure I2C is ready */
+-	SkI2cWaitIrq(pAC, IoC);
+-#endif	
+-
+-	/* stop all current transfer activity */
+-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-		if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
+-			pAC->GIni.GP[i].PState != SK_PRT_RESET) {
+-
+-			SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
+-		}
+-	}
+-
+-	/* Reset all bits in the PCI STATUS register */
+-	/*
+-	 * Note: PCI Cfg cycles cannot be used, because they are not
+-	 *	 available on some platforms after 'boot time'.
+-	 */
+-	SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
+-	
+-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+-	SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+-
+-	/* do the reset, all LEDs are switched off now */
+-	SK_OUT8(IoC, B0_CTST, CS_RST_SET);
+-	
+-	pAC->GIni.GILevel = SK_INIT_DATA;
+-}	/* SkGeDeInit */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeInitPort()	Initialize the specified port.
+- *
+- * Description:
+- *	PRxQSize, PXSQSize, and PXAQSize has to be
+- *	configured for the specified port before calling this function.
+- *  The descriptor rings has to be initialized too.
+- *
+- *	o (Re)configure queues of the specified port.
+- *	o configure the MAC of the specified port.
+- *	o put ASIC and MAC(s) in operational mode.
+- *	o initialize Rx/Tx and Sync LED
+- *	o initialize RAM Buffers and MAC FIFOs
+- *
+- *	The port is ready to connect when returning.
+- *
+- * Note:
+- *	The MAC's Rx and Tx state machine is still disabled when returning.
+- *
+- * Returns:
+- *	0:	success
+- *	1:	Queue size initialization error. The configured values
+- *		for PRxQSize, PXSQSize, or PXAQSize are invalid for one
+- *		or more queues. The specified port was NOT initialized.
+- *		An error log entry was generated.
+- *	2:	The port has to be stopped before it can be initialized again.
+- */
+-int SkGeInitPort(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port to configure */
+-{
+-	SK_GEPORT *pPrt;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (SkGeCheckQSize(pAC, Port) != 0) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG);
+-		return(1);
+-	}
+-	
+-	if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG);
+-		return(2);
+-	}
+-
+-	/* configuration ok, initialize the Port now */
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		/* initialize Rx, Tx and Link LED */
+-		/*
+-		 * If 1000BT Phy needs LED initialization than swap
+-		 * LED and XMAC initialization order
+-		 */
+-		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
+-		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA);
+-		/* The Link LED is initialized by RLMT or Diagnostics itself */
+-		
+-		SkXmInitMac(pAC, IoC, Port);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-
+-		SkGmInitMac(pAC, IoC, Port);
+-	}
+-#endif /* YUKON */
+-	
+-	/* do NOT initialize the Link Sync Counter */
+-
+-	SkGeInitMacFifo(pAC, IoC, Port);
+-	
+-	SkGeInitRamBufs(pAC, IoC, Port);
+-	
+-	if (pPrt->PXSQSize != 0) {
+-		/* enable Force Sync bit if synchronous queue available */
+-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC);
+-	}
+-	
+-	SkGeInitBmu(pAC, IoC, Port);
+-
+-	/* mark port as initialized */
+-	pPrt->PState = SK_PRT_INIT;
+-
+-	return(0);
+-}	/* SkGeInitPort */
+diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c
+deleted file mode 100644
+index fde4508..0000000
+--- a/drivers/net/sk98lin/skgemib.c
++++ /dev/null
+@@ -1,1075 +0,0 @@
+-/*****************************************************************************
+- *
+- * Name:	skgemib.c
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.11 $
+- * Date:	$Date: 2003/09/15 13:38:12 $
+- * Purpose:	Private Network Management Interface Management Database
+- *
+- ****************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * PRIVATE OID handler function prototypes
+- */
+-PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action,
+-	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action,
+-	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int* pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-
+-#ifdef SK_POWER_MGMT
+-PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-#endif /* SK_POWER_MGMT */
+-
+-#ifdef SK_DIAG_SUPPORT
+-PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
+-	unsigned int TableIndex, SK_U32 NetIndex);
+-#endif /* SK_DIAG_SUPPORT */
+-
+-
+-/* defines *******************************************************************/
+-#define ID_TABLE_SIZE	ARRAY_SIZE(IdTable)
+-
+-
+-/* global variables **********************************************************/
+-
+-/*
+- * Table to correlate OID with handler function and index to
+- * hardware register stored in StatAddress if applicable.
+- */
+-PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = {
+-	{OID_GEN_XMIT_OK,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX},
+-	{OID_GEN_RCV_OK,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX},
+-	{OID_GEN_XMIT_ERROR,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, General, 0},
+-	{OID_GEN_RCV_ERROR,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, General, 0},
+-	{OID_GEN_RCV_NO_BUFFER,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, General, 0},
+-	{OID_GEN_DIRECTED_FRAMES_XMIT,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST},
+-	{OID_GEN_MULTICAST_FRAMES_XMIT,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST},
+-	{OID_GEN_BROADCAST_FRAMES_XMIT,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST},
+-	{OID_GEN_DIRECTED_FRAMES_RCV,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST},
+-	{OID_GEN_MULTICAST_FRAMES_RCV,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST},
+-	{OID_GEN_BROADCAST_FRAMES_RCV,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST},
+-	{OID_GEN_RCV_CRC_ERROR,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS},
+-	{OID_GEN_TRANSMIT_QUEUE_LENGTH,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, General, 0},
+-	{OID_802_3_PERMANENT_ADDRESS,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, 0},
+-	{OID_802_3_CURRENT_ADDRESS,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, 0},
+-	{OID_802_3_RCV_ERROR_ALIGNMENT,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING},
+-	{OID_802_3_XMIT_ONE_COLLISION,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL},
+-	{OID_802_3_XMIT_MORE_COLLISIONS,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL},
+-	{OID_802_3_XMIT_DEFERRED,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL},
+-	{OID_802_3_XMIT_MAX_COLLISIONS,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL},
+-	{OID_802_3_RCV_OVERRUN,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW},
+-	{OID_802_3_XMIT_UNDERRUN,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN},
+-	{OID_802_3_XMIT_TIMES_CRS_LOST,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER},
+-	{OID_802_3_XMIT_LATE_COLLISIONS,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL},
+-#ifdef SK_POWER_MGMT
+-	{OID_PNP_CAPABILITIES,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, PowerManagement, 0},
+-	{OID_PNP_SET_POWER,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_WO, PowerManagement, 0},
+-	{OID_PNP_QUERY_POWER,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, PowerManagement, 0},
+-	{OID_PNP_ADD_WAKE_UP_PATTERN,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_WO, PowerManagement, 0},
+-	{OID_PNP_REMOVE_WAKE_UP_PATTERN,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_WO, PowerManagement, 0},
+-	{OID_PNP_ENABLE_WAKE_UP,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RW, PowerManagement, 0},
+-#endif /* SK_POWER_MGMT */
+-#ifdef SK_DIAG_SUPPORT
+-	{OID_SKGE_DIAG_MODE,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RW, DiagActions, 0},
+-#endif /* SK_DIAG_SUPPORT */
+-	{OID_SKGE_MDB_VERSION,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(MgmtDBVersion),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_SUPPORTED_LIST,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_ALL_DATA,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RW, OidStruct, 0},
+-	{OID_SKGE_VPD_FREE_BYTES,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(VpdFreeBytes),
+-		SK_PNMI_RO, Vpd, 0},
+-	{OID_SKGE_VPD_ENTRIES_LIST,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(VpdEntriesList),
+-		SK_PNMI_RO, Vpd, 0},
+-	{OID_SKGE_VPD_ENTRIES_NUMBER,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(VpdEntriesNumber),
+-		SK_PNMI_RO, Vpd, 0},
+-	{OID_SKGE_VPD_KEY,
+-		SK_PNMI_VPD_ENTRIES,
+-		sizeof(SK_PNMI_VPD),
+-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey),
+-		SK_PNMI_RO, Vpd, 0},
+-	{OID_SKGE_VPD_VALUE,
+-		SK_PNMI_VPD_ENTRIES,
+-		sizeof(SK_PNMI_VPD),
+-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue),
+-		SK_PNMI_RO, Vpd, 0},
+-	{OID_SKGE_VPD_ACCESS,
+-		SK_PNMI_VPD_ENTRIES,
+-		sizeof(SK_PNMI_VPD),
+-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess),
+-		SK_PNMI_RO, Vpd, 0},
+-	{OID_SKGE_VPD_ACTION,
+-		SK_PNMI_VPD_ENTRIES,
+-		sizeof(SK_PNMI_VPD),
+-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction),
+-		SK_PNMI_RW, Vpd, 0},
+-	{OID_SKGE_PORT_NUMBER,		
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(PortNumber),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_DEVICE_TYPE,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(DeviceType),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_DRIVER_DESCR,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(DriverDescr),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_DRIVER_VERSION,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(DriverVersion),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_DRIVER_RELDATE,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(DriverReleaseDate),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_DRIVER_FILENAME,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(DriverFileName),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_HW_DESCR,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(HwDescr),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_HW_VERSION,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(HwVersion),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_CHIPSET,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(Chipset),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_CHIPID,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(ChipId),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_RAMSIZE,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RamSize),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_VAUXAVAIL,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(VauxAvail),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_ACTION,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(Action),
+-		SK_PNMI_RW, Perform, 0},
+-	{OID_SKGE_RESULT,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(TestResult),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_BUS_TYPE,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(BusType),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_BUS_SPEED,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(BusSpeed),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_BUS_WIDTH,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(BusWidth),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_TX_SW_QUEUE_LEN,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(TxSwQueueLen),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_TX_SW_QUEUE_MAX,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(TxSwQueueMax),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_TX_RETRY,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(TxRetryCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_RX_INTR_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RxIntrCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_TX_INTR_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(TxIntrCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_RX_NO_BUF_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RxNoBufCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_TX_NO_BUF_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(TxNoBufCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_TX_USED_DESCR_NO,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(TxUsedDescrNo),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_RX_DELIVERED_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RxDeliveredCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_RX_OCTETS_DELIV_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_RX_HW_ERROR_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RxHwErrorsCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_TX_HW_ERROR_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(TxHwErrorsCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_IN_ERRORS_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(InErrorsCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_OUT_ERROR_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(OutErrorsCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_ERR_RECOVERY_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(ErrRecoveryCts),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_SYSUPTIME,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(SysUpTime),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_SENSOR_NUMBER,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(SensorNumber),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_SENSOR_INDEX,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_DESCR,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_TYPE,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_VALUE,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_WAR_THRES_LOW,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_WAR_THRES_UPP,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_ERR_THRES_LOW,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_ERR_THRES_UPP,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_STATUS,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_WAR_CTS,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_ERR_CTS,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_WAR_TIME,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_SENSOR_ERR_TIME,
+-		SK_PNMI_SENSOR_ENTRIES,
+-		sizeof(SK_PNMI_SENSOR),
+-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp),
+-		SK_PNMI_RO, SensorStat, 0},
+-	{OID_SKGE_CHKSM_NUMBER,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(ChecksumNumber),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_CHKSM_RX_OK_CTS,
+-		SKCS_NUM_PROTOCOLS,
+-		sizeof(SK_PNMI_CHECKSUM),
+-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts),
+-		SK_PNMI_RO, CsumStat, 0},
+-	{OID_SKGE_CHKSM_RX_UNABLE_CTS,
+-		SKCS_NUM_PROTOCOLS,
+-		sizeof(SK_PNMI_CHECKSUM),
+-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts),
+-		SK_PNMI_RO, CsumStat, 0},
+-	{OID_SKGE_CHKSM_RX_ERR_CTS,
+-		SKCS_NUM_PROTOCOLS,
+-		sizeof(SK_PNMI_CHECKSUM),
+-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts),
+-		SK_PNMI_RO, CsumStat, 0},
+-	{OID_SKGE_CHKSM_TX_OK_CTS,
+-		SKCS_NUM_PROTOCOLS,
+-		sizeof(SK_PNMI_CHECKSUM),
+-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts),
+-		SK_PNMI_RO, CsumStat, 0},
+-	{OID_SKGE_CHKSM_TX_UNABLE_CTS,
+-		SKCS_NUM_PROTOCOLS,
+-		sizeof(SK_PNMI_CHECKSUM),
+-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts),
+-		SK_PNMI_RO, CsumStat, 0},
+-	{OID_SKGE_STAT_TX,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX},
+-	{OID_SKGE_STAT_TX_OCTETS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET},
+-	{OID_SKGE_STAT_TX_BROADCAST,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST},
+-	{OID_SKGE_STAT_TX_MULTICAST,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST},
+-	{OID_SKGE_STAT_TX_UNICAST,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST},
+-	{OID_SKGE_STAT_TX_LONGFRAMES,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES},
+-	{OID_SKGE_STAT_TX_BURST,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST},
+-	{OID_SKGE_STAT_TX_PFLOWC,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC},
+-	{OID_SKGE_STAT_TX_FLOWC,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC},
+-	{OID_SKGE_STAT_TX_SINGLE_COL,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL},
+-	{OID_SKGE_STAT_TX_MULTI_COL,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL},
+-	{OID_SKGE_STAT_TX_EXCESS_COL,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL},
+-	{OID_SKGE_STAT_TX_LATE_COL,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL},
+-	{OID_SKGE_STAT_TX_DEFFERAL,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL},
+-	{OID_SKGE_STAT_TX_EXCESS_DEF,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF},
+-	{OID_SKGE_STAT_TX_UNDERRUN,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN},
+-	{OID_SKGE_STAT_TX_CARRIER,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER},
+-/*	{OID_SKGE_STAT_TX_UTIL,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization),
+-		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
+-	{OID_SKGE_STAT_TX_64,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64},
+-	{OID_SKGE_STAT_TX_127,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127},
+-	{OID_SKGE_STAT_TX_255,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255},
+-	{OID_SKGE_STAT_TX_511,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511},
+-	{OID_SKGE_STAT_TX_1023,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023},
+-	{OID_SKGE_STAT_TX_MAX,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX},
+-	{OID_SKGE_STAT_TX_SYNC,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC},
+-	{OID_SKGE_STAT_TX_SYNC_OCTETS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET},
+-	{OID_SKGE_STAT_RX,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX},
+-	{OID_SKGE_STAT_RX_OCTETS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET},
+-	{OID_SKGE_STAT_RX_BROADCAST,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST},
+-	{OID_SKGE_STAT_RX_MULTICAST,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST},
+-	{OID_SKGE_STAT_RX_UNICAST,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST},
+-	{OID_SKGE_STAT_RX_LONGFRAMES,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES},
+-	{OID_SKGE_STAT_RX_PFLOWC,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC},
+-	{OID_SKGE_STAT_RX_FLOWC,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC},
+-	{OID_SKGE_STAT_RX_PFLOWC_ERR,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR},
+-	{OID_SKGE_STAT_RX_FLOWC_UNKWN,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN},
+-	{OID_SKGE_STAT_RX_BURST,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST},
+-	{OID_SKGE_STAT_RX_MISSED,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED},
+-	{OID_SKGE_STAT_RX_FRAMING,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING},
+-	{OID_SKGE_STAT_RX_OVERFLOW,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW},
+-	{OID_SKGE_STAT_RX_JABBER,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER},
+-	{OID_SKGE_STAT_RX_CARRIER,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER},
+-	{OID_SKGE_STAT_RX_IR_LENGTH,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH},
+-	{OID_SKGE_STAT_RX_SYMBOL,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL},
+-	{OID_SKGE_STAT_RX_SHORTS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS},
+-	{OID_SKGE_STAT_RX_RUNT,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT},
+-	{OID_SKGE_STAT_RX_CEXT,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT},
+-	{OID_SKGE_STAT_RX_TOO_LONG,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG},
+-	{OID_SKGE_STAT_RX_FCS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS},
+-/*	{OID_SKGE_STAT_RX_UTIL,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization),
+-		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
+-	{OID_SKGE_STAT_RX_64,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64},
+-	{OID_SKGE_STAT_RX_127,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127},
+-	{OID_SKGE_STAT_RX_255,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255},
+-	{OID_SKGE_STAT_RX_511,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511},
+-	{OID_SKGE_STAT_RX_1023,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023},
+-	{OID_SKGE_STAT_RX_MAX,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_STAT),
+-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts),
+-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX},
+-	{OID_SKGE_PHYS_CUR_ADDR,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr),
+-		SK_PNMI_RW, Addr, 0},
+-	{OID_SKGE_PHYS_FAC_ADDR,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr),
+-		SK_PNMI_RO, Addr, 0},
+-	{OID_SKGE_PMD,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_CONNECTOR,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_PHY_TYPE,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_LINK_CAP,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_LINK_MODE,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode),
+-		SK_PNMI_RW, MacPrivateConf, 0},
+-	{OID_SKGE_LINK_MODE_STATUS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_LINK_STATUS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_FLOWCTRL_CAP,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_FLOWCTRL_MODE,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode),
+-		SK_PNMI_RW, MacPrivateConf, 0},
+-	{OID_SKGE_FLOWCTRL_STATUS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_PHY_OPERATION_CAP,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_PHY_OPERATION_MODE,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode),
+-		SK_PNMI_RW, MacPrivateConf, 0},
+-	{OID_SKGE_PHY_OPERATION_STATUS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_SPEED_CAP,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_SPEED_MODE,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode),
+-		SK_PNMI_RW, MacPrivateConf, 0},
+-	{OID_SKGE_SPEED_STATUS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_CONF),
+-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus),
+-		SK_PNMI_RO, MacPrivateConf, 0},
+-	{OID_SKGE_TRAP,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(Trap),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_TRAP_NUMBER,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(TrapNumber),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_RLMT_MODE,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RlmtMode),
+-		SK_PNMI_RW, Rlmt, 0},
+-	{OID_SKGE_RLMT_PORT_NUMBER,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RlmtPortNumber),
+-		SK_PNMI_RO, Rlmt, 0},
+-	{OID_SKGE_RLMT_PORT_ACTIVE,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RlmtPortActive),
+-		SK_PNMI_RO, Rlmt, 0},
+-	{OID_SKGE_RLMT_PORT_PREFERRED,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RlmtPortPreferred),
+-		SK_PNMI_RW, Rlmt, 0},
+-	{OID_SKGE_RLMT_CHANGE_CTS,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RlmtChangeCts),
+-		SK_PNMI_RO, Rlmt, 0},
+-	{OID_SKGE_RLMT_CHANGE_TIME,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RlmtChangeTime),
+-		SK_PNMI_RO, Rlmt, 0},
+-	{OID_SKGE_RLMT_CHANGE_ESTIM,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RlmtChangeEstimate),
+-		SK_PNMI_RO, Rlmt, 0},
+-	{OID_SKGE_RLMT_CHANGE_THRES,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RlmtChangeThreshold),
+-		SK_PNMI_RW, Rlmt, 0},
+-	{OID_SKGE_RLMT_PORT_INDEX,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_RLMT),
+-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex),
+-		SK_PNMI_RO, RlmtStat, 0},
+-	{OID_SKGE_RLMT_STATUS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_RLMT),
+-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus),
+-		SK_PNMI_RO, RlmtStat, 0},
+-	{OID_SKGE_RLMT_TX_HELLO_CTS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_RLMT),
+-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts),
+-		SK_PNMI_RO, RlmtStat, 0},
+-	{OID_SKGE_RLMT_RX_HELLO_CTS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_RLMT),
+-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts),
+-		SK_PNMI_RO, RlmtStat, 0},
+-	{OID_SKGE_RLMT_TX_SP_REQ_CTS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_RLMT),
+-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts),
+-		SK_PNMI_RO, RlmtStat, 0},
+-	{OID_SKGE_RLMT_RX_SP_CTS,
+-		SK_PNMI_MAC_ENTRIES,
+-		sizeof(SK_PNMI_RLMT),
+-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts),
+-		SK_PNMI_RO, RlmtStat, 0},
+-	{OID_SKGE_RLMT_MONITOR_NUMBER,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(RlmtMonitorNumber),
+-		SK_PNMI_RO, General, 0},
+-	{OID_SKGE_RLMT_MONITOR_INDEX,
+-		SK_PNMI_MONITOR_ENTRIES,
+-		sizeof(SK_PNMI_RLMT_MONITOR),
+-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex),
+-		SK_PNMI_RO, Monitor, 0},
+-	{OID_SKGE_RLMT_MONITOR_ADDR,
+-		SK_PNMI_MONITOR_ENTRIES,
+-		sizeof(SK_PNMI_RLMT_MONITOR),
+-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr),
+-		SK_PNMI_RO, Monitor, 0},
+-	{OID_SKGE_RLMT_MONITOR_ERRS,
+-		SK_PNMI_MONITOR_ENTRIES,
+-		sizeof(SK_PNMI_RLMT_MONITOR),
+-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts),
+-		SK_PNMI_RO, Monitor, 0},
+-	{OID_SKGE_RLMT_MONITOR_TIMESTAMP,
+-		SK_PNMI_MONITOR_ENTRIES,
+-		sizeof(SK_PNMI_RLMT_MONITOR),
+-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp),
+-		SK_PNMI_RO, Monitor, 0},
+-	{OID_SKGE_RLMT_MONITOR_ADMIN,
+-		SK_PNMI_MONITOR_ENTRIES,
+-		sizeof(SK_PNMI_RLMT_MONITOR),
+-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin),
+-		SK_PNMI_RW, Monitor, 0},
+-	{OID_SKGE_MTU,
+-		1,
+-		0,
+-		SK_PNMI_MAI_OFF(MtuSize),
+-		SK_PNMI_RW, MacPrivateConf, 0},
+-	{OID_SKGE_VCT_GET,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Vct, 0},
+-	{OID_SKGE_VCT_SET,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_WO, Vct, 0},
+-	{OID_SKGE_VCT_STATUS,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, Vct, 0},
+-	{OID_SKGE_BOARDLEVEL,
+-		0,
+-		0,
+-		0,
+-		SK_PNMI_RO, General, 0},
+-};
+-
+diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
+deleted file mode 100644
+index 876bb21..0000000
+--- a/drivers/net/sk98lin/skgepnmi.c
++++ /dev/null
+@@ -1,8198 +0,0 @@
+-/*****************************************************************************
+- *
+- * Name:	skgepnmi.c
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.111 $
+- * Date:	$Date: 2003/09/15 13:35:35 $
+- * Purpose:	Private Network Management Interface
+- *
+- ****************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-
+-#ifndef _lint
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
+-#endif /* !_lint */
+-
+-#include "h/skdrv1st.h"
+-#include "h/sktypes.h"
+-#include "h/xmac_ii.h"
+-#include "h/skdebug.h"
+-#include "h/skqueue.h"
+-#include "h/skgepnmi.h"
+-#include "h/skgesirq.h"
+-#include "h/skcsum.h"
+-#include "h/skvpd.h"
+-#include "h/skgehw.h"
+-#include "h/skgeinit.h"
+-#include "h/skdrv2nd.h"
+-#include "h/skgepnm2.h"
+-#ifdef SK_POWER_MGMT
+-#include "h/skgepmgt.h"
+-#endif
+-/* defines *******************************************************************/
+-
+-#ifndef DEBUG
+-#define PNMI_STATIC	static
+-#else	/* DEBUG */
+-#define PNMI_STATIC
+-#endif /* DEBUG */
+-
+-/*
+- * Public Function prototypes
+- */
+-int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
+-int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
+-	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
+-int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
+-	unsigned int *pLen, SK_U32 NetIndex);
+-int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
+-	unsigned int *pLen, SK_U32 NetIndex);
+-int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
+-	unsigned int *pLen, SK_U32 NetIndex);
+-int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
+-int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
+-	unsigned int * pLen, SK_U32 NetIndex);
+-
+-
+-/*
+- * Private Function prototypes
+- */
+-
+-PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
+-	PhysPortIndex);
+-PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
+-	PhysPortIndex);
+-PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
+-PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
+-PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
+-	unsigned int PhysPortIndex, unsigned int StatIndex);
+-PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
+-	unsigned int StatIndex, SK_U32 NetIndex);
+-PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
+-PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
+-	unsigned int *pEntries);
+-PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
+-	unsigned int KeyArrLen, unsigned int *pKeyNo);
+-PNMI_STATIC int LookupId(SK_U32 Id);
+-PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
+-	unsigned int LastMac);
+-PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
+-	unsigned int *pLen, SK_U32 NetIndex);
+-PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
+-	char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
+-PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
+-PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
+-	unsigned int PortIndex);
+-PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
+-	unsigned int SensorIndex);
+-PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
+-PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
+-PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
+-PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
+-PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
+-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
+-	unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
+-
+-/*
+- * Table to correlate OID with handler function and index to
+- * hardware register stored in StatAddress if applicable.
+- */
+-#include "skgemib.c"
+-
+-/* global variables **********************************************************/
+-
+-/*
+- * Overflow status register bit table and corresponding counter
+- * dependent on MAC type - the number relates to the size of overflow
+- * mask returned by the pFnMacOverflow function
+- */
+-PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
+-/* Bit0  */	{ SK_PNMI_HTX, 				SK_PNMI_HTX_UNICAST},
+-/* Bit1  */	{ SK_PNMI_HTX_OCTETHIGH, 	SK_PNMI_HTX_BROADCAST},
+-/* Bit2  */	{ SK_PNMI_HTX_OCTETLOW, 	SK_PNMI_HTX_PMACC},
+-/* Bit3  */	{ SK_PNMI_HTX_BROADCAST, 	SK_PNMI_HTX_MULTICAST},
+-/* Bit4  */	{ SK_PNMI_HTX_MULTICAST, 	SK_PNMI_HTX_OCTETLOW},
+-/* Bit5  */	{ SK_PNMI_HTX_UNICAST, 		SK_PNMI_HTX_OCTETHIGH},
+-/* Bit6  */	{ SK_PNMI_HTX_LONGFRAMES, 	SK_PNMI_HTX_64},
+-/* Bit7  */	{ SK_PNMI_HTX_BURST, 		SK_PNMI_HTX_127},
+-/* Bit8  */	{ SK_PNMI_HTX_PMACC, 		SK_PNMI_HTX_255},
+-/* Bit9  */	{ SK_PNMI_HTX_MACC, 		SK_PNMI_HTX_511},
+-/* Bit10 */	{ SK_PNMI_HTX_SINGLE_COL, 	SK_PNMI_HTX_1023},
+-/* Bit11 */	{ SK_PNMI_HTX_MULTI_COL, 	SK_PNMI_HTX_MAX},
+-/* Bit12 */	{ SK_PNMI_HTX_EXCESS_COL, 	SK_PNMI_HTX_LONGFRAMES},
+-/* Bit13 */	{ SK_PNMI_HTX_LATE_COL, 	SK_PNMI_HTX_RESERVED},
+-/* Bit14 */	{ SK_PNMI_HTX_DEFFERAL, 	SK_PNMI_HTX_COL},
+-/* Bit15 */	{ SK_PNMI_HTX_EXCESS_DEF, 	SK_PNMI_HTX_LATE_COL},
+-/* Bit16 */	{ SK_PNMI_HTX_UNDERRUN, 	SK_PNMI_HTX_EXCESS_COL},
+-/* Bit17 */	{ SK_PNMI_HTX_CARRIER, 		SK_PNMI_HTX_MULTI_COL},
+-/* Bit18 */	{ SK_PNMI_HTX_UTILUNDER, 	SK_PNMI_HTX_SINGLE_COL},
+-/* Bit19 */	{ SK_PNMI_HTX_UTILOVER, 	SK_PNMI_HTX_UNDERRUN},
+-/* Bit20 */	{ SK_PNMI_HTX_64, 			SK_PNMI_HTX_RESERVED},
+-/* Bit21 */	{ SK_PNMI_HTX_127, 			SK_PNMI_HTX_RESERVED},
+-/* Bit22 */	{ SK_PNMI_HTX_255, 			SK_PNMI_HTX_RESERVED},
+-/* Bit23 */	{ SK_PNMI_HTX_511, 			SK_PNMI_HTX_RESERVED},
+-/* Bit24 */	{ SK_PNMI_HTX_1023, 		SK_PNMI_HTX_RESERVED},
+-/* Bit25 */	{ SK_PNMI_HTX_MAX, 			SK_PNMI_HTX_RESERVED},
+-/* Bit26 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+-/* Bit27 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+-/* Bit28 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+-/* Bit29 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+-/* Bit30 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+-/* Bit31 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
+-/* Bit32 */	{ SK_PNMI_HRX, 				SK_PNMI_HRX_UNICAST},
+-/* Bit33 */	{ SK_PNMI_HRX_OCTETHIGH, 	SK_PNMI_HRX_BROADCAST},
+-/* Bit34 */	{ SK_PNMI_HRX_OCTETLOW, 	SK_PNMI_HRX_PMACC},
+-/* Bit35 */	{ SK_PNMI_HRX_BROADCAST, 	SK_PNMI_HRX_MULTICAST},
+-/* Bit36 */	{ SK_PNMI_HRX_MULTICAST, 	SK_PNMI_HRX_FCS},
+-/* Bit37 */	{ SK_PNMI_HRX_UNICAST, 		SK_PNMI_HRX_RESERVED},
+-/* Bit38 */	{ SK_PNMI_HRX_PMACC, 		SK_PNMI_HRX_OCTETLOW},
+-/* Bit39 */	{ SK_PNMI_HRX_MACC, 		SK_PNMI_HRX_OCTETHIGH},
+-/* Bit40 */	{ SK_PNMI_HRX_PMACC_ERR, 	SK_PNMI_HRX_BADOCTETLOW},
+-/* Bit41 */	{ SK_PNMI_HRX_MACC_UNKWN,	SK_PNMI_HRX_BADOCTETHIGH},
+-/* Bit42 */	{ SK_PNMI_HRX_BURST, 		SK_PNMI_HRX_UNDERSIZE},
+-/* Bit43 */	{ SK_PNMI_HRX_MISSED, 		SK_PNMI_HRX_RUNT},
+-/* Bit44 */	{ SK_PNMI_HRX_FRAMING, 		SK_PNMI_HRX_64},
+-/* Bit45 */	{ SK_PNMI_HRX_OVERFLOW, 	SK_PNMI_HRX_127},
+-/* Bit46 */	{ SK_PNMI_HRX_JABBER, 		SK_PNMI_HRX_255},
+-/* Bit47 */	{ SK_PNMI_HRX_CARRIER, 		SK_PNMI_HRX_511},
+-/* Bit48 */	{ SK_PNMI_HRX_IRLENGTH, 	SK_PNMI_HRX_1023},
+-/* Bit49 */	{ SK_PNMI_HRX_SYMBOL, 		SK_PNMI_HRX_MAX},
+-/* Bit50 */	{ SK_PNMI_HRX_SHORTS, 		SK_PNMI_HRX_LONGFRAMES},
+-/* Bit51 */	{ SK_PNMI_HRX_RUNT, 		SK_PNMI_HRX_TOO_LONG},
+-/* Bit52 */	{ SK_PNMI_HRX_TOO_LONG, 	SK_PNMI_HRX_JABBER},
+-/* Bit53 */	{ SK_PNMI_HRX_FCS, 			SK_PNMI_HRX_RESERVED},
+-/* Bit54 */	{ SK_PNMI_HRX_RESERVED, 	SK_PNMI_HRX_OVERFLOW},
+-/* Bit55 */	{ SK_PNMI_HRX_CEXT, 		SK_PNMI_HRX_RESERVED},
+-/* Bit56 */	{ SK_PNMI_HRX_UTILUNDER, 	SK_PNMI_HRX_RESERVED},
+-/* Bit57 */	{ SK_PNMI_HRX_UTILOVER, 	SK_PNMI_HRX_RESERVED},
+-/* Bit58 */	{ SK_PNMI_HRX_64, 			SK_PNMI_HRX_RESERVED},
+-/* Bit59 */	{ SK_PNMI_HRX_127, 			SK_PNMI_HRX_RESERVED},
+-/* Bit60 */	{ SK_PNMI_HRX_255, 			SK_PNMI_HRX_RESERVED},
+-/* Bit61 */	{ SK_PNMI_HRX_511, 			SK_PNMI_HRX_RESERVED},
+-/* Bit62 */	{ SK_PNMI_HRX_1023, 		SK_PNMI_HRX_RESERVED},
+-/* Bit63 */	{ SK_PNMI_HRX_MAX, 			SK_PNMI_HRX_RESERVED}
+-};
+-
+-/*
+- * Table for hardware register saving on resets and port switches
+- */
+-PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
+-	/* SK_PNMI_HTX */
+-	{{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_OCTETHIGH */
+-	{{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
+-	/* SK_PNMI_HTX_OCTETLOW */
+-	{{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
+-	/* SK_PNMI_HTX_BROADCAST */
+-	{{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
+-	/* SK_PNMI_HTX_MULTICAST */
+-	{{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
+-	/* SK_PNMI_HTX_UNICAST */
+-	{{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
+-	/* SK_PNMI_HTX_BURST */
+-	{{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_PMACC */
+-	{{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
+-	/* SK_PNMI_HTX_MACC */
+-	{{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_COL */
+-	{{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
+-	/* SK_PNMI_HTX_SINGLE_COL */
+-	{{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
+-	/* SK_PNMI_HTX_MULTI_COL */
+-	{{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
+-	/* SK_PNMI_HTX_EXCESS_COL */
+-	{{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
+-	/* SK_PNMI_HTX_LATE_COL */
+-	{{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
+-	/* SK_PNMI_HTX_DEFFERAL */
+-	{{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_EXCESS_DEF */
+-	{{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_UNDERRUN */
+-	{{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
+-	/* SK_PNMI_HTX_CARRIER */
+-	{{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_UTILUNDER */
+-	{{0, SK_FALSE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_UTILOVER */
+-	{{0, SK_FALSE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_64 */
+-	{{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
+-	/* SK_PNMI_HTX_127 */
+-	{{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
+-	/* SK_PNMI_HTX_255 */
+-	{{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
+-	/* SK_PNMI_HTX_511 */
+-	{{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
+-	/* SK_PNMI_HTX_1023 */
+-	{{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
+-	/* SK_PNMI_HTX_MAX */
+-	{{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
+-	/* SK_PNMI_HTX_LONGFRAMES  */
+-	{{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
+-	/* SK_PNMI_HTX_SYNC */
+-	{{0, SK_FALSE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_SYNC_OCTET */
+-	{{0, SK_FALSE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HTX_RESERVED */
+-	{{0, SK_FALSE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX */
+-	{{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_OCTETHIGH */
+-	{{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
+-	/* SK_PNMI_HRX_OCTETLOW */
+-	{{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
+-	/* SK_PNMI_HRX_BADOCTETHIGH */
+-	{{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
+-	/* SK_PNMI_HRX_BADOCTETLOW */
+-	{{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
+-	/* SK_PNMI_HRX_BROADCAST */
+-	{{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
+-	/* SK_PNMI_HRX_MULTICAST */
+-	{{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
+-	/* SK_PNMI_HRX_UNICAST */
+-	{{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
+-	/* SK_PNMI_HRX_PMACC */
+-	{{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
+-	/* SK_PNMI_HRX_MACC */
+-	{{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_PMACC_ERR */
+-	{{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_MACC_UNKWN */
+-	{{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_BURST */
+-	{{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_MISSED */
+-	{{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_FRAMING */
+-	{{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_UNDERSIZE */
+-	{{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
+-	/* SK_PNMI_HRX_OVERFLOW */
+-	{{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
+-	/* SK_PNMI_HRX_JABBER */
+-	{{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
+-	/* SK_PNMI_HRX_CARRIER */
+-	{{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_IRLENGTH */
+-	{{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_SYMBOL */
+-	{{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_SHORTS */
+-	{{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_RUNT */
+-	{{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
+-	/* SK_PNMI_HRX_TOO_LONG */
+-	{{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
+-	/* SK_PNMI_HRX_FCS */
+-	{{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
+-	/* SK_PNMI_HRX_CEXT */
+-	{{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_UTILUNDER */
+-	{{0, SK_FALSE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_UTILOVER */
+-	{{0, SK_FALSE}, {0, SK_FALSE}},
+-	/* SK_PNMI_HRX_64 */
+-	{{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
+-	/* SK_PNMI_HRX_127 */
+-	{{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
+-	/* SK_PNMI_HRX_255 */
+-	{{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
+-	/* SK_PNMI_HRX_511 */
+-	{{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
+-	/* SK_PNMI_HRX_1023 */
+-	{{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
+-	/* SK_PNMI_HRX_MAX */
+-	{{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
+-	/* SK_PNMI_HRX_LONGFRAMES */
+-	{{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
+-	/* SK_PNMI_HRX_RESERVED */
+-	{{0, SK_FALSE}, {0, SK_FALSE}}
+-};
+-
+-
+-/*****************************************************************************
+- *
+- * Public functions
+- *
+- */
+-
+-/*****************************************************************************
+- *
+- * SkPnmiInit - Init function of PNMI
+- *
+- * Description:
+- *	SK_INIT_DATA: Initialises the data structures
+- *	SK_INIT_IO:   Resets the XMAC statistics, determines the device and
+- *	              connector type.
+- *	SK_INIT_RUN:  Starts a timer event for port switch per hour
+- *	              calculation.
+- *
+- * Returns:
+- *	Always 0
+- */
+-int SkPnmiInit(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Level)		/* Initialization level */
+-{
+-	unsigned int	PortMax;	/* Number of ports */
+-	unsigned int	PortIndex;	/* Current port index in loop */
+-	SK_U16		Val16;		/* Multiple purpose 16 bit variable */
+-	SK_U8		Val8;		/* Mulitple purpose 8 bit variable */
+-	SK_EVPARA	EventParam;	/* Event struct for timer event */
+-	SK_PNMI_VCT	*pVctBackupData;
+-
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-		("PNMI: SkPnmiInit: Called, level=%d\n", Level));
+-
+-	switch (Level) {
+-
+-	case SK_INIT_DATA:
+-		SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
+-		pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
+-		pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+-		pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
+-		for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
+-
+-			pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
+-			pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
+-		}
+-
+-#ifdef SK_PNMI_CHECK
+-		if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
+-			
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
+-					   ("CounterOffset struct size (%d) differs from "
+-						"SK_PNMI_MAX_IDX (%d)\n",
+-						SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
+-		}
+-
+-#endif /* SK_PNMI_CHECK */
+-		break;
+-
+-	case SK_INIT_IO:
+-		/*
+-		 * Reset MAC counters
+-		 */
+-		PortMax = pAC->GIni.GIMacsFound;
+-
+-		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
+-
+-			pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
+-		}
+-		
+-		/* Initialize DSP variables for Vct() to 0xff => Never written! */		
+-		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
+-			pAC->GIni.GP[PortIndex].PCableLen = 0xff;
+-			pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
+-			pVctBackupData->PCableLen = 0xff;
+-		}
+-		
+-		/*
+-		 * Get pci bus speed
+-		 */
+-		SK_IN16(IoC, B0_CTST, &Val16);
+-		if ((Val16 & CS_BUS_CLOCK) == 0) {
+-
+-			pAC->Pnmi.PciBusSpeed = 33;
+-		}
+-		else {
+-			pAC->Pnmi.PciBusSpeed = 66;
+-		}
+-
+-		/*
+-		 * Get pci bus width
+-		 */
+-		SK_IN16(IoC, B0_CTST, &Val16);
+-		if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
+-
+-			pAC->Pnmi.PciBusWidth = 32;
+-		}
+-		else {
+-			pAC->Pnmi.PciBusWidth = 64;
+-		}
+-
+-		/*
+-		 * Get chipset
+-		 */
+-		switch (pAC->GIni.GIChipId) {
+-		case CHIP_ID_GENESIS:
+-			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
+-			break;
+-
+-		case CHIP_ID_YUKON:
+-			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
+-			break;
+-
+-		default:
+-			break;
+-		}
+-
+-		/*
+-		 * Get PMD and DeviceType
+-		 */
+-		SK_IN8(IoC, B2_PMD_TYP, &Val8);
+-		switch (Val8) {
+-		case 'S':
+-			pAC->Pnmi.PMD = 3;
+-			if (pAC->GIni.GIMacsFound > 1) {
+-
+-				pAC->Pnmi.DeviceType = 0x00020002;
+-			}
+-			else {
+-				pAC->Pnmi.DeviceType = 0x00020001;
+-			}
+-			break;
+-
+-		case 'L':
+-			pAC->Pnmi.PMD = 2;
+-			if (pAC->GIni.GIMacsFound > 1) {
+-
+-				pAC->Pnmi.DeviceType = 0x00020004;
+-			}
+-			else {
+-				pAC->Pnmi.DeviceType = 0x00020003;
+-			}
+-			break;
+-
+-		case 'C':
+-			pAC->Pnmi.PMD = 4;
+-			if (pAC->GIni.GIMacsFound > 1) {
+-
+-				pAC->Pnmi.DeviceType = 0x00020006;
+-			}
+-			else {
+-				pAC->Pnmi.DeviceType = 0x00020005;
+-			}
+-			break;
+-
+-		case 'T':
+-			pAC->Pnmi.PMD = 5;
+-			if (pAC->GIni.GIMacsFound > 1) {
+-
+-				pAC->Pnmi.DeviceType = 0x00020008;
+-			}
+-			else {
+-				pAC->Pnmi.DeviceType = 0x00020007;
+-			}
+-			break;
+-
+-		default :
+-			pAC->Pnmi.PMD = 1;
+-			pAC->Pnmi.DeviceType = 0;
+-			break;
+-		}
+-
+-		/*
+-		 * Get connector
+-		 */
+-		SK_IN8(IoC, B2_CONN_TYP, &Val8);
+-		switch (Val8) {
+-		case 'C':
+-			pAC->Pnmi.Connector = 2;
+-			break;
+-
+-		case 'D':
+-			pAC->Pnmi.Connector = 3;
+-			break;
+-
+-		case 'F':
+-			pAC->Pnmi.Connector = 4;
+-			break;
+-
+-		case 'J':
+-			pAC->Pnmi.Connector = 5;
+-			break;
+-
+-		case 'V':
+-			pAC->Pnmi.Connector = 6;
+-			break;
+-
+-		default:
+-			pAC->Pnmi.Connector = 1;
+-			break;
+-		}
+-		break;
+-
+-	case SK_INIT_RUN:
+-		/*
+-		 * Start timer for RLMT change counter
+-		 */
+-		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+-		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
+-			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
+-			EventParam);
+-		break;
+-
+-	default:
+-		break; /* Nothing todo */
+-	}
+-
+-	return (0);
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiGetVar - Retrieves the value of a single OID
+- *
+- * Description:
+- *	Calls a general sub-function for all this stuff. If the instance
+- *	-1 is passed, the values of all instances are returned in an
+- *	array of values.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
+- *	                         the data.
+- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-static int SkPnmiGetVar(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-void *pBuf,		/* Buffer to which the management data will be copied */
+-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-		("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+-			Id, *pLen, Instance, NetIndex));
+-
+-	return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
+-		Instance, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiPreSetVar - Presets the value of a single OID
+- *
+- * Description:
+- *	Calls a general sub-function for all this stuff. The preset does
+- *	the same as a set, but returns just before finally setting the
+- *	new value. This is useful to check if a set might be successfull.
+- *	If the instance -1 is passed, an array of values is supposed and
+- *	all instances of the OID will be set.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-static int SkPnmiPreSetVar(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-void *pBuf,		/* Buffer to which the management data will be copied */
+-unsigned int *pLen,	/* Total length of management data */
+-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-		("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+-			Id, *pLen, Instance, NetIndex));
+-
+-
+-	return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
+-		Instance, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiSetVar - Sets the value of a single OID
+- *
+- * Description:
+- *	Calls a general sub-function for all this stuff. The preset does
+- *	the same as a set, but returns just before finally setting the
+- *	new value. This is useful to check if a set might be successfull.
+- *	If the instance -1 is passed, an array of values is supposed and
+- *	all instances of the OID will be set.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-int SkPnmiSetVar(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-void *pBuf,		/* Buffer to which the management data will be copied */
+-unsigned int *pLen,	/* Total length of management data */
+-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-		("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+-			Id, *pLen, Instance, NetIndex));
+-
+-	return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
+-		Instance, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
+- *
+- * Description:
+- *	Runs through the IdTable, queries the single OIDs and stores the
+- *	returned data into the management database structure
+- *	SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
+- *	is stored in the IdTable. The return value of the function will also
+- *	be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
+- *	minimum size of SK_PNMI_MIN_STRUCT_SIZE.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
+- *	                         the data.
+- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
+- */
+-int SkPnmiGetStruct(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-void *pBuf,		/* Buffer to which the management data will be copied. */
+-unsigned int *pLen,	/* Length of buffer */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	int		Ret;
+-	unsigned int	TableIndex;
+-	unsigned int	DstOffset;
+-	unsigned int	InstanceNo;
+-	unsigned int	InstanceCnt;
+-	SK_U32		Instance;
+-	unsigned int	TmpLen;
+-	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
+-
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-		("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
+-			*pLen, NetIndex));
+-
+-	if (*pLen < SK_PNMI_STRUCT_SIZE) {
+-
+-		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
+-
+-			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
+-				(SK_U32)(-1));
+-		}
+-
+-		*pLen = SK_PNMI_STRUCT_SIZE;
+-		return (SK_PNMI_ERR_TOO_SHORT);
+-	}
+-
+-    /*
+-     * Check NetIndex
+-     */
+-	if (NetIndex >= pAC->Rlmt.NumNets) {
+-		return (SK_PNMI_ERR_UNKNOWN_NET);
+-	}
+-
+-	/* Update statistic */
+-	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
+-
+-	if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
+-		SK_PNMI_ERR_OK) {
+-
+-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+-		return (Ret);
+-	}
+-
+-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+-
+-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+-		return (Ret);
+-	}
+-
+-	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
+-
+-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+-		return (Ret);
+-	}
+-
+-	/*
+-	 * Increment semaphores to indicate that an update was
+-	 * already done
+-	 */
+-	pAC->Pnmi.MacUpdatedFlag ++;
+-	pAC->Pnmi.RlmtUpdatedFlag ++;
+-	pAC->Pnmi.SirqUpdatedFlag ++;
+-
+-	/* Get vpd keys for instance calculation */
+-	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
+-	if (Ret != SK_PNMI_ERR_OK) {
+-
+-		pAC->Pnmi.MacUpdatedFlag --;
+-		pAC->Pnmi.RlmtUpdatedFlag --;
+-		pAC->Pnmi.SirqUpdatedFlag --;
+-
+-		SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-
+-	/* Retrieve values */
+-	SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
+-	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
+-
+-		InstanceNo = IdTable[TableIndex].InstanceNo;
+-		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
+-			InstanceCnt ++) {
+-
+-			DstOffset = IdTable[TableIndex].Offset +
+-				(InstanceCnt - 1) *
+-				IdTable[TableIndex].StructSize;
+-
+-			/*
+-			 * For the VPD the instance is not an index number
+-			 * but the key itself. Determin with the instance
+-			 * counter the VPD key to be used.
+-			 */
+-			if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
+-				IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
+-				IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
+-				IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
+-
+-				SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
+-			}
+-			else {
+-				Instance = (SK_U32)InstanceCnt;
+-			}
+-
+-			TmpLen = *pLen - DstOffset;
+-			Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
+-				IdTable[TableIndex].Id, (char *)pBuf +
+-				DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
+-
+-			/*
+-			 * An unknown instance error means that we reached
+-			 * the last instance of that variable. Proceed with
+-			 * the next OID in the table and ignore the return
+-			 * code.
+-			 */
+-			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
+-
+-                break;
+-			}
+-
+-			if (Ret != SK_PNMI_ERR_OK) {
+-
+-				pAC->Pnmi.MacUpdatedFlag --;
+-				pAC->Pnmi.RlmtUpdatedFlag --;
+-				pAC->Pnmi.SirqUpdatedFlag --;
+-
+-				SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+-				SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
+-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+-				return (Ret);
+-			}
+-		}
+-	}
+-
+-	pAC->Pnmi.MacUpdatedFlag --;
+-	pAC->Pnmi.RlmtUpdatedFlag --;
+-	pAC->Pnmi.SirqUpdatedFlag --;
+-
+-	*pLen = SK_PNMI_STRUCT_SIZE;
+-	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+-	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
+- *
+- * Description:
+- *	Calls a general sub-function for all this set stuff. The preset does
+- *	the same as a set, but returns just before finally setting the
+- *	new value. This is useful to check if a set might be successfull.
+- *	The sub-function runs through the IdTable, checks which OIDs are able
+- *	to set, and calls the handler function of the OID to perform the
+- *	preset. The return value of the function will also be stored in
+- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
+- *	SK_PNMI_MIN_STRUCT_SIZE.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- */
+-int SkPnmiPreSetStruct(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-void *pBuf,		/* Buffer which contains the data to be set */
+-unsigned int *pLen,	/* Length of buffer */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-		("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
+-			*pLen, NetIndex));
+-
+-	return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
+-    					pLen, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
+- *
+- * Description:
+- *	Calls a general sub-function for all this set stuff. The return value
+- *	of the function will also be stored in SK_PNMI_STRUCT_DATA if the
+- *	passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
+- *	The sub-function runs through the IdTable, checks which OIDs are able
+- *	to set, and calls the handler function of the OID to perform the
+- *	set. The return value of the function will also be stored in
+- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
+- *	SK_PNMI_MIN_STRUCT_SIZE.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- */
+-int SkPnmiSetStruct(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-void *pBuf,		/* Buffer which contains the data to be set */
+-unsigned int *pLen,	/* Length of buffer */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-		("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
+-			*pLen, NetIndex));
+-
+-	return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
+-    					pLen, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiEvent - Event handler
+- *
+- * Description:
+- *	Handles the following events:
+- *	SK_PNMI_EVT_SIRQ_OVERFLOW     When a hardware counter overflows an
+- *	                              interrupt will be generated which is
+- *	                              first handled by SIRQ which generates a
+- *	                              this event. The event increments the
+- *	                              upper 32 bit of the 64 bit counter.
+- *	SK_PNMI_EVT_SEN_XXX           The event is generated by the I2C module
+- *	                              when a sensor reports a warning or
+- *	                              error. The event will store a trap
+- *	                              message in the trap buffer.
+- *	SK_PNMI_EVT_CHG_EST_TIMER     The timer event was initiated by this
+- *	                              module and is used to calculate the
+- *	                              port switches per hour.
+- *	SK_PNMI_EVT_CLEAR_COUNTER     The event clears all counters and
+- *	                              timestamps.
+- *	SK_PNMI_EVT_XMAC_RESET        The event is generated by the driver
+- *	                              before a hard reset of the XMAC is
+- *	                              performed. All counters will be saved
+- *	                              and added to the hardware counter
+- *	                              values after reset to grant continuous
+- *	                              counter values.
+- *	SK_PNMI_EVT_RLMT_PORT_UP      Generated by RLMT to notify that a port
+- *	                              went logically up. A trap message will
+- *	                              be stored to the trap buffer.
+- *	SK_PNMI_EVT_RLMT_PORT_DOWN    Generated by RLMT to notify that a port
+- *	                              went logically down. A trap message will
+- *	                              be stored to the trap buffer.
+- *	SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
+- *	                              spanning tree root bridges were
+- *	                              detected. A trap message will be stored
+- *	                              to the trap buffer.
+- *	SK_PNMI_EVT_RLMT_ACTIVE_DOWN  Notifies PNMI that an active port went
+- *	                              down. PNMI will not further add the
+- *	                              statistic values to the virtual port.
+- *	SK_PNMI_EVT_RLMT_ACTIVE_UP    Notifies PNMI that a port went up and
+- *	                              is now an active port. PNMI will now
+- *	                              add the statistic data of this port to
+- *	                              the virtual port.
+- *	SK_PNMI_EVT_RLMT_SET_NETS     Notifies PNMI about the net mode. The first parameter
+- *	                              contains the number of nets. 1 means single net, 2 means
+- *	                              dual net. The second parameter is -1
+- *
+- * Returns:
+- *	Always 0
+- */
+-int SkPnmiEvent(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-SK_U32 Event,		/* Event-Id */
+-SK_EVPARA Param)	/* Event dependent parameter */
+-{
+-	unsigned int	PhysPortIndex;
+-    unsigned int	MaxNetNumber;
+-	int			CounterIndex;
+-	int			Ret;
+-	SK_U16		MacStatus;
+-	SK_U64		OverflowStatus;
+-	SK_U64		Mask;
+-	int			MacType;
+-	SK_U64		Value;
+-	SK_U32		Val32;
+-	SK_U16		Register;
+-	SK_EVPARA	EventParam;
+-	SK_U64		NewestValue;
+-	SK_U64		OldestValue;
+-	SK_U64		Delta;
+-	SK_PNMI_ESTIMATE *pEst;
+-	SK_U32		NetIndex;
+-	SK_GEPORT	*pPrt;
+-	SK_PNMI_VCT	*pVctBackupData;
+-	SK_U32		RetCode;
+-	int		i;
+-	SK_U32		CableLength;
+-
+-
+-#ifdef DEBUG
+-	if (Event != SK_PNMI_EVT_XMAC_RESET) {
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-			("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
+-			(unsigned int)Event, (unsigned int)Param.Para64));
+-	}
+-#endif /* DEBUG */
+-	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
+-
+-	MacType = pAC->GIni.GIMacType;
+-	
+-	switch (Event) {
+-
+-	case SK_PNMI_EVT_SIRQ_OVERFLOW:
+-		PhysPortIndex = (int)Param.Para32[0];
+-		MacStatus = (SK_U16)Param.Para32[1];
+-#ifdef DEBUG
+-		if (PhysPortIndex >= SK_MAX_MACS) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
+-				 " wrong, PhysPortIndex=0x%x\n",
+-				PhysPortIndex));
+-			return (0);
+-		}
+-#endif /* DEBUG */
+-		OverflowStatus = 0;
+-
+-		/*
+-		 * Check which source caused an overflow interrupt.
+-		 */
+-		if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
+-				MacStatus, &OverflowStatus) != 0) ||
+-			(OverflowStatus == 0)) {
+-
+-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+-			return (0);
+-		}
+-
+-		/*
+-		 * Check the overflow status register and increment
+-		 * the upper dword of corresponding counter.
+-		 */
+-		for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
+-			CounterIndex ++) {
+-
+-			Mask = (SK_U64)1 << CounterIndex;
+-			if ((OverflowStatus & Mask) == 0) {
+-
+-				continue;
+-			}
+-
+-			switch (StatOvrflwBit[CounterIndex][MacType]) {
+-
+-			case SK_PNMI_HTX_UTILUNDER:
+-			case SK_PNMI_HTX_UTILOVER:
+-				if (MacType == SK_MAC_XMAC) {
+-					XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
+-					Register |= XM_TX_SAM_LINE;
+-					XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
+-				}
+-				break;
+-
+-			case SK_PNMI_HRX_UTILUNDER:
+-			case SK_PNMI_HRX_UTILOVER:
+-				if (MacType == SK_MAC_XMAC) {
+-					XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
+-					Register |= XM_RX_SAM_LINE;
+-					XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
+-				}
+-				break;
+-
+-			case SK_PNMI_HTX_OCTETHIGH:
+-			case SK_PNMI_HTX_OCTETLOW:
+-			case SK_PNMI_HTX_RESERVED:
+-			case SK_PNMI_HRX_OCTETHIGH:
+-			case SK_PNMI_HRX_OCTETLOW:
+-			case SK_PNMI_HRX_IRLENGTH:
+-			case SK_PNMI_HRX_RESERVED:
+-			
+-			/*
+-			 * the following counters aren't be handled (id > 63)
+-			 */
+-			case SK_PNMI_HTX_SYNC:
+-			case SK_PNMI_HTX_SYNC_OCTET:
+-				break;
+-
+-			case SK_PNMI_HRX_LONGFRAMES:
+-				if (MacType == SK_MAC_GMAC) {
+-					pAC->Pnmi.Port[PhysPortIndex].
+-						CounterHigh[CounterIndex] ++;
+-				}
+-				break;
+-
+-			default:
+-				pAC->Pnmi.Port[PhysPortIndex].
+-					CounterHigh[CounterIndex] ++;
+-			}
+-		}
+-		break;
+-
+-	case SK_PNMI_EVT_SEN_WAR_LOW:
+-#ifdef DEBUG
+-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
+-				(unsigned int)Param.Para64));
+-			return (0);
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * Store a trap message in the trap buffer and generate
+-		 * an event for user space applications with the
+-		 * SK_DRIVER_SENDEVENT macro.
+-		 */
+-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
+-			(unsigned int)Param.Para64);
+-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-		break;
+-
+-	case SK_PNMI_EVT_SEN_WAR_UPP:
+-#ifdef DEBUG
+-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
+-				(unsigned int)Param.Para64));
+-			return (0);
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * Store a trap message in the trap buffer and generate
+-		 * an event for user space applications with the
+-		 * SK_DRIVER_SENDEVENT macro.
+-		 */
+-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
+-			(unsigned int)Param.Para64);
+-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-		break;
+-
+-	case SK_PNMI_EVT_SEN_ERR_LOW:
+-#ifdef DEBUG
+-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
+-				(unsigned int)Param.Para64));
+-			return (0);
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * Store a trap message in the trap buffer and generate
+-		 * an event for user space applications with the
+-		 * SK_DRIVER_SENDEVENT macro.
+-		 */
+-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
+-			(unsigned int)Param.Para64);
+-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-		break;
+-	
+-	case SK_PNMI_EVT_SEN_ERR_UPP:
+-#ifdef DEBUG
+-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
+-				(unsigned int)Param.Para64));
+-			return (0);
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * Store a trap message in the trap buffer and generate
+-		 * an event for user space applications with the
+-		 * SK_DRIVER_SENDEVENT macro.
+-		 */
+-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
+-			(unsigned int)Param.Para64);
+-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-		break;
+-
+-	case SK_PNMI_EVT_CHG_EST_TIMER:
+-		/*
+-		 * Calculate port switch average on a per hour basis
+-		 *   Time interval for check       : 28125 ms
+-		 *   Number of values for average  : 8
+-		 *
+-		 * Be careful in changing these values, on change check
+-		 *   - typedef of SK_PNMI_ESTIMATE (Size of EstValue
+-		 *     array one less than value number)
+-		 *   - Timer initialization SkTimerStart() in SkPnmiInit
+-		 *   - Delta value below must be multiplicated with
+-		 *     power of 2
+-		 *
+-		 */
+-		pEst = &pAC->Pnmi.RlmtChangeEstimate;
+-		CounterIndex = pEst->EstValueIndex + 1;
+-		if (CounterIndex == 7) {
+-
+-			CounterIndex = 0;
+-		}
+-		pEst->EstValueIndex = CounterIndex;
+-
+-		NewestValue = pAC->Pnmi.RlmtChangeCts;
+-		OldestValue = pEst->EstValue[CounterIndex];
+-		pEst->EstValue[CounterIndex] = NewestValue;
+-
+-		/*
+-		 * Calculate average. Delta stores the number of
+-		 * port switches per 28125 * 8 = 225000 ms
+-		 */
+-		if (NewestValue >= OldestValue) {
+-
+-			Delta = NewestValue - OldestValue;
+-		}
+-		else {
+-			/* Overflow situation */
+-			Delta = (SK_U64)(0 - OldestValue) + NewestValue;
+-		}
+-
+-		/*
+-		 * Extrapolate delta to port switches per hour.
+-		 *     Estimate = Delta * (3600000 / 225000)
+-		 *              = Delta * 16
+-		 *              = Delta << 4
+-		 */
+-		pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
+-
+-		/*
+-		 * Check if threshold is exceeded. If the threshold is
+-		 * permanently exceeded every 28125 ms an event will be
+-		 * generated to remind the user of this condition.
+-		 */
+-		if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
+-			(pAC->Pnmi.RlmtChangeEstimate.Estimate >=
+-			pAC->Pnmi.RlmtChangeThreshold)) {
+-
+-			QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
+-			(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-		}
+-
+-		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+-		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
+-			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
+-			EventParam);
+-		break;
+-
+-	case SK_PNMI_EVT_CLEAR_COUNTER:
+-		/*
+-		 *  Param.Para32[0] contains the NetIndex (0 ..1).
+-		 *  Param.Para32[1] is reserved, contains -1.
+-		 */
+-		NetIndex = (SK_U32)Param.Para32[0];
+-
+-#ifdef DEBUG
+-		if (NetIndex >= pAC->Rlmt.NumNets) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
+-				NetIndex));
+-
+-			return (0);
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * Set all counters and timestamps to zero.
+-		 * The according NetIndex is required as a
+-		 * parameter of the event.
+-		 */
+-		ResetCounter(pAC, IoC, NetIndex);
+-		break;
+-
+-	case SK_PNMI_EVT_XMAC_RESET:
+-		/*
+-		 * To grant continuous counter values store the current
+-		 * XMAC statistic values to the entries 1..n of the
+-		 * CounterOffset array. XMAC Errata #2
+-		 */
+-#ifdef DEBUG
+-		if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
+-				(unsigned int)Param.Para64));
+-			return (0);
+-		}
+-#endif
+-		PhysPortIndex = (unsigned int)Param.Para64;
+-
+-		/*
+-		 * Update XMAC statistic to get fresh values
+-		 */
+-		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+-		if (Ret != SK_PNMI_ERR_OK) {
+-
+-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+-			return (0);
+-		}
+-		/*
+-		 * Increment semaphore to indicate that an update was
+-		 * already done
+-		 */
+-		pAC->Pnmi.MacUpdatedFlag ++;
+-
+-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+-			CounterIndex ++) {
+-
+-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
+-
+-				continue;
+-			}
+-
+-			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
+-				GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
+-			
+-			pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
+-		}
+-
+-		pAC->Pnmi.MacUpdatedFlag --;
+-		break;
+-
+-	case SK_PNMI_EVT_RLMT_PORT_UP:
+-		PhysPortIndex = (unsigned int)Param.Para32[0];
+-#ifdef DEBUG
+-		if (PhysPortIndex >= SK_MAX_MACS) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
+-                 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
+-
+-			return (0);
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * Store a trap message in the trap buffer and generate an event for
+-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
+-		 */
+-		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
+-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-
+-		/* Bugfix for XMAC errata (#10620)*/
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Add incremental difference to offset (#10620)*/
+-			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-				XM_RXE_SHT_ERR, &Val32);
+-			
+-			Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
+-				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
+-			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
+-				Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
+-		}
+-		
+-		/* Tell VctStatus() that a link was up meanwhile. */
+-		pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;		
+-		break;
+-
+-    case SK_PNMI_EVT_RLMT_PORT_DOWN:
+-		PhysPortIndex = (unsigned int)Param.Para32[0];
+-
+-#ifdef DEBUG
+-		if (PhysPortIndex >= SK_MAX_MACS) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
+-                 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
+-
+-			return (0);
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * Store a trap message in the trap buffer and generate an event for
+-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
+-		 */
+-		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
+-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-
+-		/* Bugfix #10620 - get zero level for incremental difference */
+-		if (MacType == SK_MAC_XMAC) {
+-
+-			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-				XM_RXE_SHT_ERR, &Val32);
+-			
+-			pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
+-				(((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
+-				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
+-		}
+-		break;
+-
+-	case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
+-		PhysPortIndex = (unsigned int)Param.Para32[0];
+-		NetIndex = (SK_U32)Param.Para32[1];
+-
+-#ifdef DEBUG
+-		if (PhysPortIndex >= SK_MAX_MACS) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
+-				PhysPortIndex));
+-		}
+-
+-		if (NetIndex >= pAC->Rlmt.NumNets) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
+-				NetIndex));
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * For now, ignore event if NetIndex != 0.
+-		 */
+-		if (Param.Para32[1] != 0) {
+-
+-			return (0);
+-		}
+-
+-		/*
+-		 * Nothing to do if port is already inactive
+-		 */
+-		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+-			return (0);
+-		}
+-
+-		/*
+-		 * Update statistic counters to calculate new offset for the virtual
+-		 * port and increment semaphore to indicate that an update was already
+-		 * done.
+-		 */
+-		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
+-			SK_PNMI_ERR_OK) {
+-
+-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+-			return (0);
+-		}
+-		pAC->Pnmi.MacUpdatedFlag ++;
+-
+-		/*
+-		 * Calculate new counter offset for virtual port to grant continous
+-		 * counting on port switches. The virtual port consists of all currently
+-		 * active ports. The port down event indicates that a port is removed
+-		 * from the virtual port. Therefore add the counter value of the removed
+-		 * port to the CounterOffset for the virtual port to grant the same
+-		 * counter value.
+-		 */
+-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+-			CounterIndex ++) {
+-
+-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
+-
+-				continue;
+-			}
+-
+-			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
+-
+-			pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
+-		}
+-
+-		/*
+-		 * Set port to inactive
+-		 */
+-		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
+-
+-		pAC->Pnmi.MacUpdatedFlag --;
+-		break;
+-
+-	case SK_PNMI_EVT_RLMT_ACTIVE_UP:
+-		PhysPortIndex = (unsigned int)Param.Para32[0];
+-		NetIndex = (SK_U32)Param.Para32[1];
+-
+-#ifdef DEBUG
+-		if (PhysPortIndex >= SK_MAX_MACS) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
+-				PhysPortIndex));
+-		}
+-
+-		if (NetIndex >= pAC->Rlmt.NumNets) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
+-				NetIndex));
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * For now, ignore event if NetIndex != 0.
+-		 */
+-		if (Param.Para32[1] != 0) {
+-
+-			return (0);
+-		}
+-
+-		/*
+-		 * Nothing to do if port is already active
+-		 */
+-		if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+-			return (0);
+-		}
+-
+-		/*
+-		 * Statistic maintenance
+-		 */
+-		pAC->Pnmi.RlmtChangeCts ++;
+-		pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+-
+-		/*
+-		 * Store a trap message in the trap buffer and generate an event for
+-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
+-		 */
+-		QueueRlmtNewMacTrap(pAC, PhysPortIndex);
+-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-
+-		/*
+-		 * Update statistic counters to calculate new offset for the virtual
+-		 * port and increment semaphore to indicate that an update was
+-		 * already done.
+-		 */
+-		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
+-			SK_PNMI_ERR_OK) {
+-
+-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+-			return (0);
+-		}
+-		pAC->Pnmi.MacUpdatedFlag ++;
+-
+-		/*
+-		 * Calculate new counter offset for virtual port to grant continous
+-		 * counting on port switches. A new port is added to the virtual port.
+-		 * Therefore substract the counter value of the new port from the
+-		 * CounterOffset for the virtual port to grant the same value.
+-		 */
+-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+-			CounterIndex ++) {
+-
+-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
+-
+-				continue;
+-			}
+-
+-			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
+-
+-			pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
+-		}
+-
+-		/* Set port to active */
+-		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
+-
+-		pAC->Pnmi.MacUpdatedFlag --;
+-		break;
+-
+-	case SK_PNMI_EVT_RLMT_SEGMENTATION:
+-		/*
+-		 * Para.Para32[0] contains the NetIndex.
+-		 */
+-
+-		/*
+-		 * Store a trap message in the trap buffer and generate an event for
+-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
+-		 */
+-		QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
+-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-		break;
+-
+-    case SK_PNMI_EVT_RLMT_SET_NETS:
+-		/*
+-		 *  Param.Para32[0] contains the number of Nets.
+-		 *  Param.Para32[1] is reserved, contains -1.
+-		 */
+-	    /*
+-    	 * Check number of nets
+-		 */
+-		MaxNetNumber = pAC->GIni.GIMacsFound;
+-		if (((unsigned int)Param.Para32[0] < 1)
+-			|| ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
+-			return (SK_PNMI_ERR_UNKNOWN_NET);
+-		}
+-
+-        if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
+-        	pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
+-        }
+-        else { /* dual net mode */
+-        	pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
+-        }
+-        break;
+-
+-    case SK_PNMI_EVT_VCT_RESET:
+-		PhysPortIndex = Param.Para32[0];
+-		pPrt = &pAC->GIni.GP[PhysPortIndex];
+-		pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
+-		
+-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
+-			RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
+-			if (RetCode == 2) {
+-				/*
+-				 * VCT test is still running.
+-				 * Start VCT timer counter again.
+-				 */
+-				SK_MEMSET((char *) &Param, 0, sizeof(Param));
+-				Param.Para32[0] = PhysPortIndex;
+-				Param.Para32[1] = -1;
+-				SkTimerStart(pAC, IoC,
+-					&pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
+-				4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
+-				break;
+-			}
+-			pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
+-			pAC->Pnmi.VctStatus[PhysPortIndex] |=
+-				(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
+-			
+-			/* Copy results for later use to PNMI struct. */
+-			for (i = 0; i < 4; i++)  {
+-				if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
+-					if ((pPrt->PMdiPairLen[i] > 35) &&
+-						(pPrt->PMdiPairLen[i] < 0xff)) {
+-						pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
+-					}
+-				}
+-				if ((pPrt->PMdiPairLen[i] > 35) &&
+-					(pPrt->PMdiPairLen[i] != 0xff)) {
+-					CableLength = 1000 *
+-						(((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
+-				}
+-				else {
+-					CableLength = 0;
+-				}
+-				pVctBackupData->PMdiPairLen[i] = CableLength;
+-				pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
+-			}
+-			
+-			Param.Para32[0] = PhysPortIndex;
+-			Param.Para32[1] = -1;
+-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
+-			SkEventDispatcher(pAC, IoC);
+-		}
+-		
+-		break;
+-
+-	default:
+-		break;
+-	}
+-
+-	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+-	return (0);
+-}
+-
+-
+-/******************************************************************************
+- *
+- * Private functions
+- *
+- */
+-
+-/*****************************************************************************
+- *
+- * PnmiVar - Gets, presets, and sets single OIDs
+- *
+- * Description:
+- *	Looks up the requested OID, calls the corresponding handler
+- *	function, and passes the parameters with the get, preset, or
+- *	set command. The function is called by SkGePnmiGetVar,
+- *	SkGePnmiPreSetVar, or SkGePnmiSetVar.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_XXX. For details have a look at the description of the
+- *	calling functions.
+- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
+- */
+-PNMI_STATIC int PnmiVar(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* Total length of pBuf management data  */
+-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	unsigned int	TableIndex;
+-	int		Ret;
+-
+-
+-	if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_UNKNOWN_OID);
+-	}
+-	
+-    /* Check NetIndex */
+-	if (NetIndex >= pAC->Rlmt.NumNets) {
+-		return (SK_PNMI_ERR_UNKNOWN_NET);
+-	}
+-
+-	SK_PNMI_CHECKFLAGS("PnmiVar: On call");
+-
+-	Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
+-		Instance, TableIndex, NetIndex);
+-
+-	SK_PNMI_CHECKFLAGS("PnmiVar: On return");
+-
+-	return (Ret);
+-}
+-
+-/*****************************************************************************
+- *
+- * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
+- *
+- * Description:
+- *	The return value of the function will also be stored in
+- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
+- *	SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
+- *	checks which OIDs are able to set, and calls the handler function of
+- *	the OID to perform the set. The return value of the function will
+- *	also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
+- *	minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
+- *	by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_XXX. The codes are described in the calling functions.
+- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
+- */
+-PNMI_STATIC int PnmiStruct(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int  Action,	/* PRESET/SET action to be performed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* Length of pBuf management data buffer */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	int		Ret;
+-	unsigned int	TableIndex;
+-	unsigned int	DstOffset;
+-	unsigned int	Len;
+-	unsigned int	InstanceNo;
+-	unsigned int	InstanceCnt;
+-	SK_U32		Instance;
+-	SK_U32		Id;
+-
+-
+-	/* Check if the passed buffer has the right size */
+-	if (*pLen < SK_PNMI_STRUCT_SIZE) {
+-
+-		/* Check if we can return the error within the buffer */
+-		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
+-
+-			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
+-				(SK_U32)(-1));
+-		}
+-
+-		*pLen = SK_PNMI_STRUCT_SIZE;
+-		return (SK_PNMI_ERR_TOO_SHORT);
+-	}
+-	
+-    /* Check NetIndex */
+-	if (NetIndex >= pAC->Rlmt.NumNets) {
+-		return (SK_PNMI_ERR_UNKNOWN_NET);
+-	}
+-	
+-	SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
+-
+-	/*
+-	 * Update the values of RLMT and SIRQ and increment semaphores to
+-	 * indicate that an update was already done.
+-	 */
+-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+-
+-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+-		return (Ret);
+-	}
+-
+-	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
+-
+-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+-		return (Ret);
+-	}
+-
+-	pAC->Pnmi.RlmtUpdatedFlag ++;
+-	pAC->Pnmi.SirqUpdatedFlag ++;
+-
+-	/* Preset/Set values */
+-	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
+-
+-		if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
+-			(IdTable[TableIndex].Access != SK_PNMI_WO)) {
+-
+-			continue;
+-		}
+-
+-		InstanceNo = IdTable[TableIndex].InstanceNo;
+-		Id = IdTable[TableIndex].Id;
+-
+-		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
+-			InstanceCnt ++) {
+-
+-			DstOffset = IdTable[TableIndex].Offset +
+-				(InstanceCnt - 1) *
+-				IdTable[TableIndex].StructSize;
+-
+-			/*
+-			 * Because VPD multiple instance variables are
+-			 * not setable we do not need to evaluate VPD
+-			 * instances. Have a look to VPD instance
+-			 * calculation in SkPnmiGetStruct().
+-			 */
+-			Instance = (SK_U32)InstanceCnt;
+-
+-			/*
+-			 * Evaluate needed buffer length
+-			 */
+-			Len = 0;
+-			Ret = IdTable[TableIndex].Func(pAC, IoC,
+-				SK_PNMI_GET, IdTable[TableIndex].Id,
+-				NULL, &Len, Instance, TableIndex, NetIndex);
+-
+-			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
+-
+-				break;
+-			}
+-			if (Ret != SK_PNMI_ERR_TOO_SHORT) {
+-
+-				pAC->Pnmi.RlmtUpdatedFlag --;
+-				pAC->Pnmi.SirqUpdatedFlag --;
+-
+-				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+-				SK_PNMI_SET_STAT(pBuf,
+-					SK_PNMI_ERR_GENERAL, DstOffset);
+-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-			if (Id == OID_SKGE_VPD_ACTION) {
+-
+-				switch (*(pBuf + DstOffset)) {
+-
+-				case SK_PNMI_VPD_CREATE:
+-					Len = 3 + *(pBuf + DstOffset + 3);
+-					break;
+-
+-				case SK_PNMI_VPD_DELETE:
+-					Len = 3;
+-					break;
+-
+-				default:
+-					Len = 1;
+-					break;
+-				}
+-			}
+-
+-			/* Call the OID handler function */
+-			Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
+-				IdTable[TableIndex].Id, pBuf + DstOffset,
+-				&Len, Instance, TableIndex, NetIndex);
+-
+-			if (Ret != SK_PNMI_ERR_OK) {
+-
+-				pAC->Pnmi.RlmtUpdatedFlag --;
+-				pAC->Pnmi.SirqUpdatedFlag --;
+-
+-				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+-				SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
+-					DstOffset);
+-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-		}
+-	}
+-
+-	pAC->Pnmi.RlmtUpdatedFlag --;
+-	pAC->Pnmi.SirqUpdatedFlag --;
+-
+-	SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+-	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * LookupId - Lookup an OID in the IdTable
+- *
+- * Description:
+- *	Scans the IdTable to find the table entry of an OID.
+- *
+- * Returns:
+- *	The table index or -1 if not found.
+- */
+-PNMI_STATIC int LookupId(
+-SK_U32 Id)		/* Object identifier to be searched */
+-{
+-	int i;
+-
+-	for (i = 0; i < ID_TABLE_SIZE; i++) {
+-
+-		if (IdTable[i].Id == Id) {
+-
+-			return i;
+-		}
+-	}
+-
+-	return (-1);
+-}
+-
+-/*****************************************************************************
+- *
+- * OidStruct - Handler of OID_SKGE_ALL_DATA
+- *
+- * Description:
+- *	This OID performs a Get/Preset/SetStruct call and returns all data
+- *	in a SK_PNMI_STRUCT_DATA structure.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int OidStruct(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	if (Id != OID_SKGE_ALL_DATA) {
+-
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
+-			SK_PNMI_ERR003MSG);
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-
+-	/*
+-	 * Check instance. We only handle single instance variables
+-	 */
+-	if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_UNKNOWN_INST);
+-	}
+-
+-	switch (Action) {
+-
+-	case SK_PNMI_GET:
+-		return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
+-
+-	case SK_PNMI_PRESET:
+-		return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
+-
+-	case SK_PNMI_SET:
+-		return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
+-	}
+-
+-	SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
+-
+-	*pLen = 0;
+-	return (SK_PNMI_ERR_GENERAL);
+-}
+-
+-/*****************************************************************************
+- *
+- * Perform - OID handler of OID_SKGE_ACTION
+- *
+- * Description:
+- *	None.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int Perform(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	int	Ret;
+-	SK_U32	ActionOp;
+-
+-
+-	/*
+-	 * Check instance. We only handle single instance variables
+-	 */
+-	if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_UNKNOWN_INST);
+-	}
+-
+-	if (*pLen < sizeof(SK_U32)) {
+-
+-		*pLen = sizeof(SK_U32);
+-		return (SK_PNMI_ERR_TOO_SHORT);
+-	}
+-
+-	/* Check if a get should be performed */
+-	if (Action == SK_PNMI_GET) {
+-
+-		/* A get is easy. We always return the same value */
+-		ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
+-		SK_PNMI_STORE_U32(pBuf, ActionOp);
+-		*pLen = sizeof(SK_U32);
+-
+-		return (SK_PNMI_ERR_OK);
+-	}
+-
+-	/* Continue with PRESET/SET action */
+-	if (*pLen > sizeof(SK_U32)) {
+-
+-		return (SK_PNMI_ERR_BAD_VALUE);
+-	}
+-
+-	/* Check if the command is a known one */
+-	SK_PNMI_READ_U32(pBuf, ActionOp);
+-	if (*pLen > sizeof(SK_U32) ||
+-		(ActionOp != SK_PNMI_ACT_IDLE &&
+-		ActionOp != SK_PNMI_ACT_RESET &&
+-		ActionOp != SK_PNMI_ACT_SELFTEST &&
+-		ActionOp != SK_PNMI_ACT_RESETCNT)) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_BAD_VALUE);
+-	}
+-
+-	/* A preset ends here */
+-	if (Action == SK_PNMI_PRESET) {
+-
+-		return (SK_PNMI_ERR_OK);
+-	}
+-
+-	switch (ActionOp) {
+-
+-	case SK_PNMI_ACT_IDLE:
+-		/* Nothing to do */
+-		break;
+-
+-	case SK_PNMI_ACT_RESET:
+-		/*
+-		 * Perform a driver reset or something that comes near
+-		 * to this.
+-		 */
+-		Ret = SK_DRIVER_RESET(pAC, IoC);
+-		if (Ret != 0) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
+-				SK_PNMI_ERR005MSG);
+-
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-		break;
+-
+-	case SK_PNMI_ACT_SELFTEST:
+-		/*
+-		 * Perform a driver selftest or something similar to this.
+-		 * Currently this feature is not used and will probably
+-		 * implemented in another way.
+-		 */
+-		Ret = SK_DRIVER_SELFTEST(pAC, IoC);
+-		pAC->Pnmi.TestResult = Ret;
+-		break;
+-
+-	case SK_PNMI_ACT_RESETCNT:
+-		/* Set all counters and timestamps to zero */
+-		ResetCounter(pAC, IoC, NetIndex);
+-		break;
+-
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
+-			SK_PNMI_ERR006MSG);
+-
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
+- *
+- * Description:
+- *	Retrieves the statistic values of the virtual port (logical
+- *	index 0). Only special OIDs of NDIS are handled which consist
+- *	of a 32 bit instead of a 64 bit value. The OIDs are public
+- *	because perhaps some other platform can use them too.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int Mac8023Stat(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex,	/* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	int     Ret;
+-	SK_U64  StatVal;
+-	SK_U32  StatVal32;
+-	SK_BOOL Is64BitReq = SK_FALSE;
+-
+-	/*
+-	 * Only the active Mac is returned
+-	 */
+-	if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_UNKNOWN_INST);
+-	}
+-
+-	/*
+-	 * Check action type
+-	 */
+-	if (Action != SK_PNMI_GET) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_READ_ONLY);
+-	}
+-
+-	/* Check length */
+-	switch (Id) {
+-
+-	case OID_802_3_PERMANENT_ADDRESS:
+-	case OID_802_3_CURRENT_ADDRESS:
+-		if (*pLen < sizeof(SK_MAC_ADDR)) {
+-
+-			*pLen = sizeof(SK_MAC_ADDR);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	default:
+-#ifndef SK_NDIS_64BIT_CTR
+-		if (*pLen < sizeof(SK_U32)) {
+-			*pLen = sizeof(SK_U32);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-
+-#else /* SK_NDIS_64BIT_CTR */
+-
+-		/* for compatibility, at least 32bit are required for OID */
+-		if (*pLen < sizeof(SK_U32)) {
+-			/*
+-			* but indicate handling for 64bit values,
+-			* if insufficient space is provided
+-			*/
+-			*pLen = sizeof(SK_U64);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-
+-		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
+-#endif /* SK_NDIS_64BIT_CTR */
+-		break;
+-	}
+-
+-	/*
+-	 * Update all statistics, because we retrieve virtual MAC, which
+-	 * consists of multiple physical statistics and increment semaphore
+-	 * to indicate that an update was already done.
+-	 */
+-	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+-	if ( Ret != SK_PNMI_ERR_OK) {
+-
+-		*pLen = 0;
+-		return (Ret);
+-	}
+-	pAC->Pnmi.MacUpdatedFlag ++;
+-
+-	/*
+-	 * Get value (MAC Index 0 identifies the virtual MAC)
+-	 */
+-	switch (Id) {
+-
+-	case OID_802_3_PERMANENT_ADDRESS:
+-		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
+-		*pLen = sizeof(SK_MAC_ADDR);
+-		break;
+-
+-	case OID_802_3_CURRENT_ADDRESS:
+-		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
+-		*pLen = sizeof(SK_MAC_ADDR);
+-		break;
+-
+-	default:
+-		StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
+-
+-		/* by default 32bit values are evaluated */
+-		if (!Is64BitReq) {
+-			StatVal32 = (SK_U32)StatVal;
+-			SK_PNMI_STORE_U32(pBuf, StatVal32);
+-			*pLen = sizeof(SK_U32);
+-		}
+-		else {
+-			SK_PNMI_STORE_U64(pBuf, StatVal);
+-			*pLen = sizeof(SK_U64);
+-		}
+-		break;
+-	}
+-
+-	pAC->Pnmi.MacUpdatedFlag --;
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
+- *
+- * Description:
+- *	Retrieves the MAC statistic data.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int MacPrivateStat(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	unsigned int	LogPortMax;
+-	unsigned int	LogPortIndex;
+-	unsigned int	PhysPortMax;
+-	unsigned int	Limit;
+-	unsigned int	Offset;
+-	int				MacType;
+-	int				Ret;
+-	SK_U64			StatVal;
+-	
+-	
+-
+-	/* Calculate instance if wished. MAC index 0 is the virtual MAC */
+-	PhysPortMax = pAC->GIni.GIMacsFound;
+-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+-	
+-	MacType = pAC->GIni.GIMacType;
+-
+-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
+-		LogPortMax--;
+-	}
+-
+-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
+-		/* Check instance range */
+-		if ((Instance < 1) || (Instance > LogPortMax)) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_UNKNOWN_INST);
+-		}
+-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+-		Limit = LogPortIndex + 1;
+-	}
+-
+-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
+-
+-		LogPortIndex = 0;
+-		Limit = LogPortMax;
+-	}
+-
+-	/* Check action */
+-	if (Action != SK_PNMI_GET) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_READ_ONLY);
+-	}
+-
+-	/* Check length */
+-	if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
+-
+-		*pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
+-		return (SK_PNMI_ERR_TOO_SHORT);
+-	}
+-
+-	/*
+-	 * Update MAC statistic and increment semaphore to indicate that
+-	 * an update was already done.
+-	 */
+-	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+-	if (Ret != SK_PNMI_ERR_OK) {
+-
+-		*pLen = 0;
+-		return (Ret);
+-	}
+-	pAC->Pnmi.MacUpdatedFlag ++;
+-
+-	/* Get value */
+-	Offset = 0;
+-	for (; LogPortIndex < Limit; LogPortIndex ++) {
+-
+-		switch (Id) {
+-
+-/* XXX not yet implemented due to XMAC problems
+-		case OID_SKGE_STAT_TX_UTIL:
+-			return (SK_PNMI_ERR_GENERAL);
+-*/
+-/* XXX not yet implemented due to XMAC problems
+-		case OID_SKGE_STAT_RX_UTIL:
+-			return (SK_PNMI_ERR_GENERAL);
+-*/
+-		case OID_SKGE_STAT_RX:
+-			if (MacType == SK_MAC_GMAC) {
+-				StatVal =
+-					GetStatVal(pAC, IoC, LogPortIndex,
+-							   SK_PNMI_HRX_BROADCAST, NetIndex) +
+-					GetStatVal(pAC, IoC, LogPortIndex,
+-							   SK_PNMI_HRX_MULTICAST, NetIndex) +
+-					GetStatVal(pAC, IoC, LogPortIndex,
+-							   SK_PNMI_HRX_UNICAST, NetIndex) +
+-					GetStatVal(pAC, IoC, LogPortIndex,
+-							   SK_PNMI_HRX_UNDERSIZE, NetIndex);
+-			}
+-			else {
+-				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
+-					IdTable[TableIndex].Param, NetIndex);
+-			}
+-			break;
+-
+-		case OID_SKGE_STAT_TX:
+-			if (MacType == SK_MAC_GMAC) {
+-				StatVal =
+-					GetStatVal(pAC, IoC, LogPortIndex,
+-							   SK_PNMI_HTX_BROADCAST, NetIndex) +
+-					GetStatVal(pAC, IoC, LogPortIndex,
+-							   SK_PNMI_HTX_MULTICAST, NetIndex) +
+-					GetStatVal(pAC, IoC, LogPortIndex,
+-							   SK_PNMI_HTX_UNICAST, NetIndex);
+-			}
+-			else {
+-				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
+-					IdTable[TableIndex].Param, NetIndex);
+-			}
+-			break;
+-
+-		default:
+-			StatVal = GetStatVal(pAC, IoC, LogPortIndex,
+-				IdTable[TableIndex].Param, NetIndex);
+-		}
+-		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
+-
+-		Offset += sizeof(SK_U64);
+-	}
+-	*pLen = Offset;
+-
+-	pAC->Pnmi.MacUpdatedFlag --;
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
+- *
+- * Description:
+- *	Get/Presets/Sets the current and factory MAC address. The MAC
+- *	address of the virtual port, which is reported to the OS, may
+- *	not be changed, but the physical ones. A set to the virtual port
+- *	will be ignored. No error should be reported because otherwise
+- *	a multiple instance set (-1) would always fail.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int Addr(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	int		Ret;
+-	unsigned int	LogPortMax;
+-	unsigned int	PhysPortMax;
+-	unsigned int	LogPortIndex;
+-	unsigned int	PhysPortIndex;
+-	unsigned int	Limit;
+-	unsigned int	Offset = 0;
+-
+-	/*
+-	 * Calculate instance if wished. MAC index 0 is the virtual
+-	 * MAC.
+-	 */
+-	PhysPortMax = pAC->GIni.GIMacsFound;
+-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+-
+-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
+-		LogPortMax--;
+-	}
+-
+-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
+-		/* Check instance range */
+-		if ((Instance < 1) || (Instance > LogPortMax)) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_UNKNOWN_INST);
+-		}
+-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+-		Limit = LogPortIndex + 1;
+-	}
+-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
+-
+-		LogPortIndex = 0;
+-		Limit = LogPortMax;
+-	}
+-
+-	/*
+-	 * Perform Action
+-	 */
+-	if (Action == SK_PNMI_GET) {
+-
+-		/* Check length */
+-		if (*pLen < (Limit - LogPortIndex) * 6) {
+-
+-			*pLen = (Limit - LogPortIndex) * 6;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-
+-		/*
+-		 * Get value
+-		 */
+-		for (; LogPortIndex < Limit; LogPortIndex ++) {
+-
+-			switch (Id) {
+-
+-			case OID_SKGE_PHYS_CUR_ADDR:
+-				if (LogPortIndex == 0) {
+-					CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
+-				}
+-				else {
+-					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+-
+-					CopyMac(pBuf + Offset,
+-						&pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
+-				}
+-				Offset += 6;
+-				break;
+-
+-			case OID_SKGE_PHYS_FAC_ADDR:
+-				if (LogPortIndex == 0) {
+-					CopyMac(pBuf + Offset,
+-						&pAC->Addr.Net[NetIndex].PermanentMacAddress);
+-				}
+-				else {
+-					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-						pAC, LogPortIndex);
+-
+-					CopyMac(pBuf + Offset,
+-						&pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
+-				}
+-				Offset += 6;
+-				break;
+-
+-			default:
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
+-					SK_PNMI_ERR008MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-		}
+-
+-		*pLen = Offset;
+-	}
+-	else {
+-		/*
+-		 * The logical MAC address may not be changed only
+-		 * the physical ones
+-		 */
+-		if (Id == OID_SKGE_PHYS_FAC_ADDR) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_READ_ONLY);
+-		}
+-
+-		/*
+-		 * Only the current address may be changed
+-		 */
+-		if (Id != OID_SKGE_PHYS_CUR_ADDR) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
+-				SK_PNMI_ERR009MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		/* Check length */
+-		if (*pLen < (Limit - LogPortIndex) * 6) {
+-
+-			*pLen = (Limit - LogPortIndex) * 6;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		if (*pLen > (Limit - LogPortIndex) * 6) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_BAD_VALUE);
+-		}
+-
+-		/*
+-		 * Check Action
+-		 */
+-		if (Action == SK_PNMI_PRESET) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_OK);
+-		}
+-
+-		/*
+-		 * Set OID_SKGE_MAC_CUR_ADDR
+-		 */
+-		for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
+-
+-			/*
+-			 * A set to virtual port and set of broadcast
+-			 * address will be ignored
+-			 */
+-			if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
+-				"\xff\xff\xff\xff\xff\xff", 6) == 0) {
+-
+-				continue;
+-			}
+-
+-			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
+-				LogPortIndex);
+-
+-			Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
+-				(SK_MAC_ADDR *)(pBuf + Offset),
+-				(LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
+-				SK_ADDR_PHYSICAL_ADDRESS));
+-			if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
+-
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-		}
+-		*pLen = Offset;
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
+- *
+- * Description:
+- *	Retrieves the statistic values of the CSUM module. The CSUM data
+- *	structure must be available in the SK_AC even if the CSUM module
+- *	is not included, because PNMI reads the statistic data from the
+- *	CSUM part of SK_AC directly.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int CsumStat(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	unsigned int	Index;
+-	unsigned int	Limit;
+-	unsigned int	Offset = 0;
+-	SK_U64		StatVal;
+-
+-
+-	/*
+-	 * Calculate instance if wished
+-	 */
+-	if (Instance != (SK_U32)(-1)) {
+-
+-		if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_UNKNOWN_INST);
+-		}
+-		Index = (unsigned int)Instance - 1;
+-		Limit = Index + 1;
+-	}
+-	else {
+-		Index = 0;
+-		Limit = SKCS_NUM_PROTOCOLS;
+-	}
+-
+-	/*
+-	 * Check action
+-	 */
+-	if (Action != SK_PNMI_GET) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_READ_ONLY);
+-	}
+-
+-	/* Check length */
+-	if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
+-
+-		*pLen = (Limit - Index) * sizeof(SK_U64);
+-		return (SK_PNMI_ERR_TOO_SHORT);
+-	}
+-
+-	/*
+-	 * Get value
+-	 */
+-	for (; Index < Limit; Index ++) {
+-
+-		switch (Id) {
+-
+-		case OID_SKGE_CHKSM_RX_OK_CTS:
+-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
+-			break;
+-
+-		case OID_SKGE_CHKSM_RX_UNABLE_CTS:
+-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
+-			break;
+-
+-		case OID_SKGE_CHKSM_RX_ERR_CTS:
+-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
+-			break;
+-
+-		case OID_SKGE_CHKSM_TX_OK_CTS:
+-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
+-			break;
+-
+-		case OID_SKGE_CHKSM_TX_UNABLE_CTS:
+-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
+-			break;
+-
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
+-				SK_PNMI_ERR010MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
+-		Offset += sizeof(SK_U64);
+-	}
+-
+-	/*
+-	 * Store used buffer space
+-	 */
+-	*pLen = Offset;
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
+- *
+- * Description:
+- *	Retrieves the statistic values of the I2C module, which handles
+- *	the temperature and voltage sensors.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int SensorStat(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	unsigned int	i;
+-	unsigned int	Index;
+-	unsigned int	Limit;
+-	unsigned int	Offset;
+-	unsigned int	Len;
+-	SK_U32		Val32;
+-	SK_U64		Val64;
+-
+-
+-	/*
+-	 * Calculate instance if wished
+-	 */
+-	if ((Instance != (SK_U32)(-1))) {
+-
+-		if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_UNKNOWN_INST);
+-		}
+-
+-		Index = (unsigned int)Instance -1;
+-		Limit = (unsigned int)Instance;
+-	}
+-	else {
+-		Index = 0;
+-		Limit = (unsigned int) pAC->I2c.MaxSens;
+-	}
+-
+-	/*
+-	 * Check action
+-	 */
+-	if (Action != SK_PNMI_GET) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_READ_ONLY);
+-	}
+-
+-	/* Check length */
+-	switch (Id) {
+-
+-	case OID_SKGE_SENSOR_VALUE:
+-	case OID_SKGE_SENSOR_WAR_THRES_LOW:
+-	case OID_SKGE_SENSOR_WAR_THRES_UPP:
+-	case OID_SKGE_SENSOR_ERR_THRES_LOW:
+-	case OID_SKGE_SENSOR_ERR_THRES_UPP:
+-		if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
+-
+-			*pLen = (Limit - Index) * sizeof(SK_U32);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	case OID_SKGE_SENSOR_DESCR:
+-		for (Offset = 0, i = Index; i < Limit; i ++) {
+-
+-			Len = (unsigned int)
+-				SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
+-			if (Len >= SK_PNMI_STRINGLEN2) {
+-
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
+-					SK_PNMI_ERR011MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-			Offset += Len;
+-		}
+-		if (*pLen < Offset) {
+-
+-			*pLen = Offset;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	case OID_SKGE_SENSOR_INDEX:
+-	case OID_SKGE_SENSOR_TYPE:
+-	case OID_SKGE_SENSOR_STATUS:
+-		if (*pLen < Limit - Index) {
+-
+-			*pLen = Limit - Index;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	case OID_SKGE_SENSOR_WAR_CTS:
+-	case OID_SKGE_SENSOR_WAR_TIME:
+-	case OID_SKGE_SENSOR_ERR_CTS:
+-	case OID_SKGE_SENSOR_ERR_TIME:
+-		if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
+-
+-			*pLen = (Limit - Index) * sizeof(SK_U64);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
+-			SK_PNMI_ERR012MSG);
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_GENERAL);
+-
+-	}
+-
+-	/*
+-	 * Get value
+-	 */
+-	for (Offset = 0; Index < Limit; Index ++) {
+-
+-		switch (Id) {
+-
+-		case OID_SKGE_SENSOR_INDEX:
+-			*(pBuf + Offset) = (char)Index;
+-			Offset += sizeof(char);
+-			break;
+-
+-		case OID_SKGE_SENSOR_DESCR:
+-			Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
+-			SK_MEMCPY(pBuf + Offset + 1,
+-				pAC->I2c.SenTable[Index].SenDesc, Len);
+-			*(pBuf + Offset) = (char)Len;
+-			Offset += Len + 1;
+-			break;
+-
+-		case OID_SKGE_SENSOR_TYPE:
+-			*(pBuf + Offset) =
+-				(char)pAC->I2c.SenTable[Index].SenType;
+-			Offset += sizeof(char);
+-			break;
+-
+-		case OID_SKGE_SENSOR_VALUE:
+-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
+-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-			Offset += sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_SENSOR_WAR_THRES_LOW:
+-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
+-				SenThreWarnLow;
+-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-			Offset += sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_SENSOR_WAR_THRES_UPP:
+-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
+-				SenThreWarnHigh;
+-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-			Offset += sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_SENSOR_ERR_THRES_LOW:
+-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
+-				SenThreErrLow;
+-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-			Offset += sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_SENSOR_ERR_THRES_UPP:
+-			Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
+-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-			Offset += sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_SENSOR_STATUS:
+-			*(pBuf + Offset) =
+-				(char)pAC->I2c.SenTable[Index].SenErrFlag;
+-			Offset += sizeof(char);
+-			break;
+-
+-		case OID_SKGE_SENSOR_WAR_CTS:
+-			Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
+-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+-			Offset += sizeof(SK_U64);
+-			break;
+-
+-		case OID_SKGE_SENSOR_ERR_CTS:
+-			Val64 = pAC->I2c.SenTable[Index].SenErrCts;
+-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+-			Offset += sizeof(SK_U64);
+-			break;
+-
+-		case OID_SKGE_SENSOR_WAR_TIME:
+-			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
+-				SenBegWarnTS);
+-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+-			Offset += sizeof(SK_U64);
+-			break;
+-
+-		case OID_SKGE_SENSOR_ERR_TIME:
+-			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
+-				SenBegErrTS);
+-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+-			Offset += sizeof(SK_U64);
+-			break;
+-
+-		default:
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+-				("SensorStat: Unknown OID should be handled before"));
+-
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-	}
+-
+-	/*
+-	 * Store used buffer space
+-	 */
+-	*pLen = Offset;
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Vpd - OID handler function of OID_SKGE_VPD_XXX
+- *
+- * Description:
+- *	Get/preset/set of VPD data. As instance the name of a VPD key
+- *	can be passed. The Instance parameter is a SK_U32 and can be
+- *	used as a string buffer for the VPD key, because their maximum
+- *	length is 4 byte.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int Vpd(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	SK_VPD_STATUS	*pVpdStatus;
+-	unsigned int	BufLen;
+-	char		Buf[256];
+-	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
+-	char		KeyStr[SK_PNMI_VPD_KEY_SIZE];
+-	unsigned int	KeyNo;
+-	unsigned int	Offset;
+-	unsigned int	Index;
+-	unsigned int	FirstIndex;
+-	unsigned int	LastIndex;
+-	unsigned int	Len;
+-	int		Ret;
+-	SK_U32		Val32;
+-
+-	/*
+-	 * Get array of all currently stored VPD keys
+-	 */
+-	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
+-	if (Ret != SK_PNMI_ERR_OK) {
+-		*pLen = 0;
+-		return (Ret);
+-	}
+-
+-	/*
+-	 * If instance is not -1, try to find the requested VPD key for
+-	 * the multiple instance variables. The other OIDs as for example
+-	 * OID VPD_ACTION are single instance variables and must be
+-	 * handled separatly.
+-	 */
+-	FirstIndex = 0;
+-	LastIndex = KeyNo;
+-
+-	if ((Instance != (SK_U32)(-1))) {
+-
+-		if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
+-			Id == OID_SKGE_VPD_ACCESS) {
+-
+-			SK_STRNCPY(KeyStr, (char *)&Instance, 4);
+-			KeyStr[4] = 0;
+-
+-			for (Index = 0; Index < KeyNo; Index ++) {
+-
+-				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
+-					FirstIndex = Index;
+-					LastIndex = Index+1;
+-					break;
+-				}
+-			}
+-			if (Index == KeyNo) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_UNKNOWN_INST);
+-			}
+-		}
+-		else if (Instance != 1) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_UNKNOWN_INST);
+-		}
+-	}
+-
+-	/*
+-	 * Get value, if a query should be performed
+-	 */
+-	if (Action == SK_PNMI_GET) {
+-
+-		switch (Id) {
+-
+-		case OID_SKGE_VPD_FREE_BYTES:
+-			/* Check length of buffer */
+-			if (*pLen < sizeof(SK_U32)) {
+-
+-				*pLen = sizeof(SK_U32);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			/* Get number of free bytes */
+-			pVpdStatus = VpdStat(pAC, IoC);
+-			if (pVpdStatus == NULL) {
+-
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
+-					SK_PNMI_ERR017MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-			if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
+-
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
+-					SK_PNMI_ERR018MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-			
+-			Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
+-			SK_PNMI_STORE_U32(pBuf, Val32);
+-			*pLen = sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_VPD_ENTRIES_LIST:
+-			/* Check length */
+-			for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
+-
+-				Len += SK_STRLEN(KeyArr[Index]) + 1;
+-			}
+-			if (*pLen < Len) {
+-
+-				*pLen = Len;
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-
+-			/* Get value */
+-			*(pBuf) = (char)Len - 1;
+-			for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
+-
+-				Len = SK_STRLEN(KeyArr[Index]);
+-				SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
+-
+-				Offset += Len;
+-
+-				if (Index < KeyNo - 1) {
+-
+-					*(pBuf + Offset) = ' ';
+-					Offset ++;
+-				}
+-			}
+-			*pLen = Offset;
+-			break;
+-
+-		case OID_SKGE_VPD_ENTRIES_NUMBER:
+-			/* Check length */
+-			if (*pLen < sizeof(SK_U32)) {
+-
+-				*pLen = sizeof(SK_U32);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-
+-			Val32 = (SK_U32)KeyNo;
+-			SK_PNMI_STORE_U32(pBuf, Val32);
+-			*pLen = sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_VPD_KEY:
+-			/* Check buffer length, if it is large enough */
+-			for (Len = 0, Index = FirstIndex;
+-				Index < LastIndex; Index ++) {
+-
+-				Len += SK_STRLEN(KeyArr[Index]) + 1;
+-			}
+-			if (*pLen < Len) {
+-
+-				*pLen = Len;
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-
+-			/*
+-			 * Get the key to an intermediate buffer, because
+-			 * we have to prepend a length byte.
+-			 */
+-			for (Offset = 0, Index = FirstIndex;
+-				Index < LastIndex; Index ++) {
+-
+-				Len = SK_STRLEN(KeyArr[Index]);
+-
+-				*(pBuf + Offset) = (char)Len;
+-				SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
+-					Len);
+-				Offset += Len + 1;
+-			}
+-			*pLen = Offset;
+-			break;
+-
+-		case OID_SKGE_VPD_VALUE:
+-			/* Check the buffer length if it is large enough */
+-			for (Offset = 0, Index = FirstIndex;
+-				Index < LastIndex; Index ++) {
+-
+-				BufLen = 256;
+-				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
+-					(int *)&BufLen) > 0 ||
+-					BufLen >= SK_PNMI_VPD_DATALEN) {
+-
+-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-						SK_PNMI_ERR021,
+-						SK_PNMI_ERR021MSG);
+-
+-					return (SK_PNMI_ERR_GENERAL);
+-				}
+-				Offset += BufLen + 1;
+-			}
+-			if (*pLen < Offset) {
+-
+-				*pLen = Offset;
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-
+-			/*
+-			 * Get the value to an intermediate buffer, because
+-			 * we have to prepend a length byte.
+-			 */
+-			for (Offset = 0, Index = FirstIndex;
+-				Index < LastIndex; Index ++) {
+-
+-				BufLen = 256;
+-				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
+-					(int *)&BufLen) > 0 ||
+-					BufLen >= SK_PNMI_VPD_DATALEN) {
+-
+-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-						SK_PNMI_ERR022,
+-						SK_PNMI_ERR022MSG);
+-
+-					*pLen = 0;
+-					return (SK_PNMI_ERR_GENERAL);
+-				}
+-
+-				*(pBuf + Offset) = (char)BufLen;
+-				SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
+-				Offset += BufLen + 1;
+-			}
+-			*pLen = Offset;
+-			break;
+-
+-		case OID_SKGE_VPD_ACCESS:
+-			if (*pLen < LastIndex - FirstIndex) {
+-
+-				*pLen = LastIndex - FirstIndex;
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-
+-			for (Offset = 0, Index = FirstIndex;
+-				Index < LastIndex; Index ++) {
+-
+-				if (VpdMayWrite(KeyArr[Index])) {
+-
+-					*(pBuf + Offset) = SK_PNMI_VPD_RW;
+-				}
+-				else {
+-					*(pBuf + Offset) = SK_PNMI_VPD_RO;
+-				}
+-				Offset ++;
+-			}
+-			*pLen = Offset;
+-			break;
+-
+-		case OID_SKGE_VPD_ACTION:
+-			Offset = LastIndex - FirstIndex;
+-			if (*pLen < Offset) {
+-
+-				*pLen = Offset;
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			SK_MEMSET(pBuf, 0, Offset);
+-			*pLen = Offset;
+-			break;
+-
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
+-				SK_PNMI_ERR023MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-	}
+-	else {
+-		/* The only OID which can be set is VPD_ACTION */
+-		if (Id != OID_SKGE_VPD_ACTION) {
+-
+-			if (Id == OID_SKGE_VPD_FREE_BYTES ||
+-				Id == OID_SKGE_VPD_ENTRIES_LIST ||
+-				Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
+-				Id == OID_SKGE_VPD_KEY ||
+-				Id == OID_SKGE_VPD_VALUE ||
+-				Id == OID_SKGE_VPD_ACCESS) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_READ_ONLY);
+-			}
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
+-				SK_PNMI_ERR024MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		/*
+-		 * From this point we handle VPD_ACTION. Check the buffer
+-		 * length. It should at least have the size of one byte.
+-		 */
+-		if (*pLen < 1) {
+-
+-			*pLen = 1;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-
+-		/*
+-		 * The first byte contains the VPD action type we should
+-		 * perform.
+-		 */
+-		switch (*pBuf) {
+-
+-		case SK_PNMI_VPD_IGNORE:
+-			/* Nothing to do */
+-			break;
+-
+-		case SK_PNMI_VPD_CREATE:
+-			/*
+-			 * We have to create a new VPD entry or we modify
+-			 * an existing one. Check first the buffer length.
+-			 */
+-			if (*pLen < 4) {
+-
+-				*pLen = 4;
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			KeyStr[0] = pBuf[1];
+-			KeyStr[1] = pBuf[2];
+-			KeyStr[2] = 0;
+-
+-			/*
+-			 * Is the entry writable or does it belong to the
+-			 * read-only area?
+-			 */
+-			if (!VpdMayWrite(KeyStr)) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-
+-			Offset = (int)pBuf[3] & 0xFF;
+-
+-			SK_MEMCPY(Buf, pBuf + 4, Offset);
+-			Buf[Offset] = 0;
+-
+-			/* A preset ends here */
+-			if (Action == SK_PNMI_PRESET) {
+-
+-				return (SK_PNMI_ERR_OK);
+-			}
+-
+-			/* Write the new entry or modify an existing one */
+-			Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
+-			if (Ret == SK_PNMI_VPD_NOWRITE ) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-			else if (Ret != SK_PNMI_VPD_OK) {
+-
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
+-					SK_PNMI_ERR025MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-
+-			/*
+-			 * Perform an update of the VPD data. This is
+-			 * not mandantory, but just to be sure.
+-			 */
+-			Ret = VpdUpdate(pAC, IoC);
+-			if (Ret != SK_PNMI_VPD_OK) {
+-
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
+-					SK_PNMI_ERR026MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-			break;
+-
+-		case SK_PNMI_VPD_DELETE:
+-			/* Check if the buffer size is plausible */
+-			if (*pLen < 3) {
+-
+-				*pLen = 3;
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			if (*pLen > 3) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-			KeyStr[0] = pBuf[1];
+-			KeyStr[1] = pBuf[2];
+-			KeyStr[2] = 0;
+-
+-			/* Find the passed key in the array */
+-			for (Index = 0; Index < KeyNo; Index ++) {
+-
+-				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
+-
+-					break;
+-				}
+-			}
+-			/*
+-			 * If we cannot find the key it is wrong, so we
+-			 * return an appropriate error value.
+-			 */
+-			if (Index == KeyNo) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-
+-			if (Action == SK_PNMI_PRESET) {
+-
+-				return (SK_PNMI_ERR_OK);
+-			}
+-
+-			/* Ok, you wanted it and you will get it */
+-			Ret = VpdDelete(pAC, IoC, KeyStr);
+-			if (Ret != SK_PNMI_VPD_OK) {
+-
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
+-					SK_PNMI_ERR027MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-
+-			/*
+-			 * Perform an update of the VPD data. This is
+-			 * not mandantory, but just to be sure.
+-			 */
+-			Ret = VpdUpdate(pAC, IoC);
+-			if (Ret != SK_PNMI_VPD_OK) {
+-
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
+-					SK_PNMI_ERR028MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-			break;
+-
+-		default:
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_BAD_VALUE);
+-		}
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * General - OID handler function of various single instance OIDs
+- *
+- * Description:
+- *	The code is simple. No description necessary.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int General(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	int		Ret;
+-	unsigned int	Index;
+-	unsigned int	Len;
+-	unsigned int	Offset;
+-	unsigned int	Val;
+-	SK_U8		Val8;
+-	SK_U16		Val16;
+-	SK_U32		Val32;
+-	SK_U64		Val64;
+-	SK_U64		Val64RxHwErrs = 0;
+-	SK_U64		Val64TxHwErrs = 0;
+-	SK_BOOL		Is64BitReq = SK_FALSE;
+-	char		Buf[256];
+-	int			MacType;
+-
+-	/*
+-	 * Check instance. We only handle single instance variables.
+-	 */
+-	if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_UNKNOWN_INST);
+-	}
+-
+-	/*
+-	 * Check action. We only allow get requests.
+-	 */
+-	if (Action != SK_PNMI_GET) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_READ_ONLY);
+-	}
+-	
+-	MacType = pAC->GIni.GIMacType;
+-	
+-	/*
+-	 * Check length for the various supported OIDs
+-	 */
+-	switch (Id) {
+-
+-	case OID_GEN_XMIT_ERROR:
+-	case OID_GEN_RCV_ERROR:
+-	case OID_GEN_RCV_NO_BUFFER:
+-#ifndef SK_NDIS_64BIT_CTR
+-		if (*pLen < sizeof(SK_U32)) {
+-			*pLen = sizeof(SK_U32);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-
+-#else /* SK_NDIS_64BIT_CTR */
+-
+-		/*
+-		 * for compatibility, at least 32bit are required for oid
+-		 */
+-		if (*pLen < sizeof(SK_U32)) {
+-			/*
+-			* but indicate handling for 64bit values,
+-			* if insufficient space is provided
+-			*/
+-			*pLen = sizeof(SK_U64);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-
+-		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
+-#endif /* SK_NDIS_64BIT_CTR */
+-		break;
+-
+-	case OID_SKGE_PORT_NUMBER:
+-	case OID_SKGE_DEVICE_TYPE:
+-	case OID_SKGE_RESULT:
+-	case OID_SKGE_RLMT_MONITOR_NUMBER:
+-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+-	case OID_SKGE_TRAP_NUMBER:
+-	case OID_SKGE_MDB_VERSION:
+-	case OID_SKGE_BOARDLEVEL:
+-	case OID_SKGE_CHIPID:
+-	case OID_SKGE_RAMSIZE:
+-		if (*pLen < sizeof(SK_U32)) {
+-
+-			*pLen = sizeof(SK_U32);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	case OID_SKGE_CHIPSET:
+-		if (*pLen < sizeof(SK_U16)) {
+-
+-			*pLen = sizeof(SK_U16);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	case OID_SKGE_BUS_TYPE:
+-	case OID_SKGE_BUS_SPEED:
+-	case OID_SKGE_BUS_WIDTH:
+-	case OID_SKGE_SENSOR_NUMBER:
+-	case OID_SKGE_CHKSM_NUMBER:
+-	case OID_SKGE_VAUXAVAIL:
+-		if (*pLen < sizeof(SK_U8)) {
+-
+-			*pLen = sizeof(SK_U8);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	case OID_SKGE_TX_SW_QUEUE_LEN:
+-	case OID_SKGE_TX_SW_QUEUE_MAX:
+-	case OID_SKGE_TX_RETRY:
+-	case OID_SKGE_RX_INTR_CTS:
+-	case OID_SKGE_TX_INTR_CTS:
+-	case OID_SKGE_RX_NO_BUF_CTS:
+-	case OID_SKGE_TX_NO_BUF_CTS:
+-	case OID_SKGE_TX_USED_DESCR_NO:
+-	case OID_SKGE_RX_DELIVERED_CTS:
+-	case OID_SKGE_RX_OCTETS_DELIV_CTS:
+-	case OID_SKGE_RX_HW_ERROR_CTS:
+-	case OID_SKGE_TX_HW_ERROR_CTS:
+-	case OID_SKGE_IN_ERRORS_CTS:
+-	case OID_SKGE_OUT_ERROR_CTS:
+-	case OID_SKGE_ERR_RECOVERY_CTS:
+-	case OID_SKGE_SYSUPTIME:
+-		if (*pLen < sizeof(SK_U64)) {
+-
+-			*pLen = sizeof(SK_U64);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	default:
+-		/* Checked later */
+-		break;
+-	}
+-
+-	/* Update statistic */
+-	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
+-		Id == OID_SKGE_TX_HW_ERROR_CTS ||
+-		Id == OID_SKGE_IN_ERRORS_CTS ||
+-		Id == OID_SKGE_OUT_ERROR_CTS ||
+-		Id == OID_GEN_XMIT_ERROR ||
+-		Id == OID_GEN_RCV_ERROR) {
+-
+-		/* Force the XMAC to update its statistic counters and
+-		 * Increment semaphore to indicate that an update was
+-		 * already done.
+-		 */
+-		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+-		if (Ret != SK_PNMI_ERR_OK) {
+-
+-			*pLen = 0;
+-			return (Ret);
+-		}
+-		pAC->Pnmi.MacUpdatedFlag ++;
+-
+-		/*
+-		 * Some OIDs consist of multiple hardware counters. Those
+-		 * values which are contained in all of them will be added
+-		 * now.
+-		 */
+-		switch (Id) {
+-
+-		case OID_SKGE_RX_HW_ERROR_CTS:
+-		case OID_SKGE_IN_ERRORS_CTS:
+-		case OID_GEN_RCV_ERROR:
+-			Val64RxHwErrs =
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
+-	        break;
+-
+-		case OID_SKGE_TX_HW_ERROR_CTS:
+-		case OID_SKGE_OUT_ERROR_CTS:
+-		case OID_GEN_XMIT_ERROR:
+-			Val64TxHwErrs =
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
+-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
+-			break;
+-		}
+-	}
+-
+-	/*
+-	 * Retrieve value
+-	 */
+-	switch (Id) {
+-
+-	case OID_SKGE_SUPPORTED_LIST:
+-		Len = ID_TABLE_SIZE * sizeof(SK_U32);
+-		if (*pLen < Len) {
+-
+-			*pLen = Len;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		for (Offset = 0, Index = 0; Offset < Len;
+-			Offset += sizeof(SK_U32), Index ++) {
+-
+-			Val32 = (SK_U32)IdTable[Index].Id;
+-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-		}
+-		*pLen = Len;
+-		break;
+-
+-	case OID_SKGE_BOARDLEVEL:
+-		Val32 = (SK_U32)pAC->GIni.GILevel;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	case OID_SKGE_PORT_NUMBER:
+-		Val32 = (SK_U32)pAC->GIni.GIMacsFound;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	case OID_SKGE_DEVICE_TYPE:
+-		Val32 = (SK_U32)pAC->Pnmi.DeviceType;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	case OID_SKGE_DRIVER_DESCR:
+-		if (pAC->Pnmi.pDriverDescription == NULL) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
+-				SK_PNMI_ERR007MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
+-		if (Len > SK_PNMI_STRINGLEN1) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
+-				SK_PNMI_ERR029MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		if (*pLen < Len) {
+-
+-			*pLen = Len;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		*pBuf = (char)(Len - 1);
+-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
+-		*pLen = Len;
+-		break;
+-
+-	case OID_SKGE_DRIVER_VERSION:
+-		if (pAC->Pnmi.pDriverVersion == NULL) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
+-				SK_PNMI_ERR030MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
+-		if (Len > SK_PNMI_STRINGLEN1) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
+-				SK_PNMI_ERR031MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		if (*pLen < Len) {
+-
+-			*pLen = Len;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		*pBuf = (char)(Len - 1);
+-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
+-		*pLen = Len;
+-		break;
+-
+-	case OID_SKGE_DRIVER_RELDATE:
+-		if (pAC->Pnmi.pDriverReleaseDate == NULL) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
+-				SK_PNMI_ERR053MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
+-		if (Len > SK_PNMI_STRINGLEN1) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
+-				SK_PNMI_ERR054MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		if (*pLen < Len) {
+-
+-			*pLen = Len;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		*pBuf = (char)(Len - 1);
+-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
+-		*pLen = Len;
+-		break;
+-
+-	case OID_SKGE_DRIVER_FILENAME:
+-		if (pAC->Pnmi.pDriverFileName == NULL) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
+-				SK_PNMI_ERR055MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
+-		if (Len > SK_PNMI_STRINGLEN1) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
+-				SK_PNMI_ERR056MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		if (*pLen < Len) {
+-
+-			*pLen = Len;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		*pBuf = (char)(Len - 1);
+-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
+-		*pLen = Len;
+-		break;
+-
+-	case OID_SKGE_HW_DESCR:
+-		/*
+-		 * The hardware description is located in the VPD. This
+-		 * query may move to the initialisation routine. But
+-		 * the VPD data is cached and therefore a call here
+-		 * will not make much difference.
+-		 */
+-		Len = 256;
+-		if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
+-				SK_PNMI_ERR032MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-		Len ++;
+-		if (Len > SK_PNMI_STRINGLEN1) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
+-				SK_PNMI_ERR033MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-		if (*pLen < Len) {
+-
+-			*pLen = Len;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		*pBuf = (char)(Len - 1);
+-		SK_MEMCPY(pBuf + 1, Buf, Len - 1);
+-		*pLen = Len;
+-		break;
+-
+-	case OID_SKGE_HW_VERSION:
+-		/* Oh, I love to do some string manipulation */
+-		if (*pLen < 5) {
+-
+-			*pLen = 5;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
+-		pBuf[0] = 4;
+-		pBuf[1] = 'v';
+-		pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
+-		pBuf[3] = '.';
+-		pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
+-		*pLen = 5;
+-		break;
+-
+-	case OID_SKGE_CHIPSET:
+-		Val16 = pAC->Pnmi.Chipset;
+-		SK_PNMI_STORE_U16(pBuf, Val16);
+-		*pLen = sizeof(SK_U16);
+-		break;
+-
+-	case OID_SKGE_CHIPID:
+-		Val32 = pAC->GIni.GIChipId;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	case OID_SKGE_RAMSIZE:
+-		Val32 = pAC->GIni.GIRamSize;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	case OID_SKGE_VAUXAVAIL:
+-		*pBuf = (char) pAC->GIni.GIVauxAvail;
+-		*pLen = sizeof(char);
+-		break;
+-
+-	case OID_SKGE_BUS_TYPE:
+-		*pBuf = (char) SK_PNMI_BUS_PCI;
+-		*pLen = sizeof(char);
+-		break;
+-
+-	case OID_SKGE_BUS_SPEED:
+-		*pBuf = pAC->Pnmi.PciBusSpeed;
+-		*pLen = sizeof(char);
+-		break;
+-
+-	case OID_SKGE_BUS_WIDTH:
+-		*pBuf = pAC->Pnmi.PciBusWidth;
+-		*pLen = sizeof(char);
+-		break;
+-
+-	case OID_SKGE_RESULT:
+-		Val32 = pAC->Pnmi.TestResult;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	case OID_SKGE_SENSOR_NUMBER:
+-		*pBuf = (char)pAC->I2c.MaxSens;
+-		*pLen = sizeof(char);
+-		break;
+-
+-	case OID_SKGE_CHKSM_NUMBER:
+-		*pBuf = SKCS_NUM_PROTOCOLS;
+-		*pLen = sizeof(char);
+-		break;
+-
+-	case OID_SKGE_TRAP_NUMBER:
+-		GetTrapQueueLen(pAC, &Len, &Val);
+-		Val32 = (SK_U32)Val;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	case OID_SKGE_TRAP:
+-		GetTrapQueueLen(pAC, &Len, &Val);
+-		if (*pLen < Len) {
+-
+-			*pLen = Len;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		CopyTrapQueue(pAC, pBuf);
+-		*pLen = Len;
+-		break;
+-
+-	case OID_SKGE_RLMT_MONITOR_NUMBER:
+-/* XXX Not yet implemented by RLMT therefore we return zero elements */
+-		Val32 = 0;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	case OID_SKGE_TX_SW_QUEUE_LEN:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
+-					pAC->Pnmi.BufPort[1].TxSwQueueLen;
+-			}			
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
+-					pAC->Pnmi.Port[1].TxSwQueueLen;
+-			}			
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-
+-	case OID_SKGE_TX_SW_QUEUE_MAX:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
+-					pAC->Pnmi.BufPort[1].TxSwQueueMax;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
+-					pAC->Pnmi.Port[1].TxSwQueueMax;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_TX_RETRY:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
+-					pAC->Pnmi.BufPort[1].TxRetryCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].TxRetryCts +
+-					pAC->Pnmi.Port[1].TxRetryCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_RX_INTR_CTS:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
+-					pAC->Pnmi.BufPort[1].RxIntrCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].RxIntrCts +
+-					pAC->Pnmi.Port[1].RxIntrCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_TX_INTR_CTS:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
+-					pAC->Pnmi.BufPort[1].TxIntrCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].TxIntrCts +
+-					pAC->Pnmi.Port[1].TxIntrCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_RX_NO_BUF_CTS:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
+-					pAC->Pnmi.BufPort[1].RxNoBufCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
+-					pAC->Pnmi.Port[1].RxNoBufCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_TX_NO_BUF_CTS:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
+-					pAC->Pnmi.BufPort[1].TxNoBufCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
+-					pAC->Pnmi.Port[1].TxNoBufCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_TX_USED_DESCR_NO:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
+-					pAC->Pnmi.BufPort[1].TxUsedDescrNo;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
+-					pAC->Pnmi.Port[1].TxUsedDescrNo;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_RX_DELIVERED_CTS:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
+-					pAC->Pnmi.BufPort[1].RxDeliveredCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
+-					pAC->Pnmi.Port[1].RxDeliveredCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_RX_OCTETS_DELIV_CTS:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
+-					pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
+-					pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_RX_HW_ERROR_CTS:
+-		SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_TX_HW_ERROR_CTS:
+-		SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_IN_ERRORS_CTS:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = Val64RxHwErrs +
+-					pAC->Pnmi.BufPort[0].RxNoBufCts +
+-					pAC->Pnmi.BufPort[1].RxNoBufCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = Val64RxHwErrs +
+-					pAC->Pnmi.Port[0].RxNoBufCts +
+-					pAC->Pnmi.Port[1].RxNoBufCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_OUT_ERROR_CTS:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = Val64TxHwErrs +
+-					pAC->Pnmi.BufPort[0].TxNoBufCts +
+-					pAC->Pnmi.BufPort[1].TxNoBufCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = Val64TxHwErrs +
+-					pAC->Pnmi.Port[0].TxNoBufCts +
+-					pAC->Pnmi.Port[1].TxNoBufCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_ERR_RECOVERY_CTS:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
+-					pAC->Pnmi.BufPort[1].ErrRecoveryCts;
+-			}
+-		}
+-		else {
+-			/* Dual net mode */
+-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-				Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
+-			}
+-			/* Single net mode */
+-			else {
+-				Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
+-					pAC->Pnmi.Port[1].ErrRecoveryCts;
+-			}
+-		}
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_SYSUPTIME:
+-		Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+-		Val64 -= pAC->Pnmi.StartUpTime;
+-		SK_PNMI_STORE_U64(pBuf, Val64);
+-		*pLen = sizeof(SK_U64);
+-		break;
+-
+-	case OID_SKGE_MDB_VERSION:
+-		Val32 = SK_PNMI_MDB_VERSION;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	case OID_GEN_RCV_ERROR:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+-		}
+-		else {
+-			Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+-		}
+-
+-		/*
+-		 * by default 32bit values are evaluated
+-		 */
+-		if (!Is64BitReq) {
+-			Val32 = (SK_U32)Val64;
+-			SK_PNMI_STORE_U32(pBuf, Val32);
+-			*pLen = sizeof(SK_U32);
+-		}
+-		else {
+-			SK_PNMI_STORE_U64(pBuf, Val64);
+-			*pLen = sizeof(SK_U64);
+-		}
+-		break;
+-
+-	case OID_GEN_XMIT_ERROR:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+-		}
+-		else {
+-			Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+-		}
+-
+-		/*
+-		 * by default 32bit values are evaluated
+-		 */
+-		if (!Is64BitReq) {
+-			Val32 = (SK_U32)Val64;
+-			SK_PNMI_STORE_U32(pBuf, Val32);
+-			*pLen = sizeof(SK_U32);
+-		}
+-		else {
+-			SK_PNMI_STORE_U64(pBuf, Val64);
+-			*pLen = sizeof(SK_U64);
+-		}
+-		break;
+-
+-	case OID_GEN_RCV_NO_BUFFER:
+-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-		if (MacType == SK_MAC_XMAC) {
+-			Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+-		}
+-		else {
+-			Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+-		}
+-
+-		/*
+-		 * by default 32bit values are evaluated
+-		 */
+-		if (!Is64BitReq) {
+-			Val32 = (SK_U32)Val64;
+-			SK_PNMI_STORE_U32(pBuf, Val32);
+-			*pLen = sizeof(SK_U32);
+-		}
+-		else {
+-			SK_PNMI_STORE_U64(pBuf, Val64);
+-			*pLen = sizeof(SK_U64);
+-		}
+-		break;
+-
+-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+-		Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
+-		SK_PNMI_STORE_U32(pBuf, Val32);
+-		*pLen = sizeof(SK_U32);
+-		break;
+-
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
+-			SK_PNMI_ERR034MSG);
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-
+-	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
+-		Id == OID_SKGE_TX_HW_ERROR_CTS ||
+-		Id == OID_SKGE_IN_ERRORS_CTS ||
+-		Id == OID_SKGE_OUT_ERROR_CTS ||
+-		Id == OID_GEN_XMIT_ERROR ||
+-		Id == OID_GEN_RCV_ERROR) {
+-
+-		pAC->Pnmi.MacUpdatedFlag --;
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
+- *
+- * Description:
+- *	Get/Presets/Sets the RLMT OIDs.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int Rlmt(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	int		Ret;
+-	unsigned int	PhysPortIndex;
+-	unsigned int	PhysPortMax;
+-	SK_EVPARA	EventParam;
+-	SK_U32		Val32;
+-	SK_U64		Val64;
+-
+-
+-	/*
+-	 * Check instance. Only single instance OIDs are allowed here.
+-	 */
+-	if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_UNKNOWN_INST);
+-	}
+-
+-	/*
+-	 * Perform the requested action.
+-	 */
+-	if (Action == SK_PNMI_GET) {
+-
+-		/*
+-		 * Check if the buffer length is large enough.
+-		 */
+-
+-		switch (Id) {
+-
+-		case OID_SKGE_RLMT_MODE:
+-		case OID_SKGE_RLMT_PORT_ACTIVE:
+-		case OID_SKGE_RLMT_PORT_PREFERRED:
+-			if (*pLen < sizeof(SK_U8)) {
+-
+-				*pLen = sizeof(SK_U8);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			break;
+-
+-		case OID_SKGE_RLMT_PORT_NUMBER:
+-			if (*pLen < sizeof(SK_U32)) {
+-
+-				*pLen = sizeof(SK_U32);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			break;
+-
+-		case OID_SKGE_RLMT_CHANGE_CTS:
+-		case OID_SKGE_RLMT_CHANGE_TIME:
+-		case OID_SKGE_RLMT_CHANGE_ESTIM:
+-		case OID_SKGE_RLMT_CHANGE_THRES:
+-			if (*pLen < sizeof(SK_U64)) {
+-
+-				*pLen = sizeof(SK_U64);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			break;
+-
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
+-				SK_PNMI_ERR035MSG);
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		/*
+-		 * Update RLMT statistic and increment semaphores to indicate
+-		 * that an update was already done. Maybe RLMT will hold its
+-		 * statistic always up to date some time. Then we can
+-		 * remove this type of call.
+-		 */
+-		if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+-
+-			*pLen = 0;
+-			return (Ret);
+-		}
+-		pAC->Pnmi.RlmtUpdatedFlag ++;
+-
+-		/*
+-		 * Retrieve Value
+-		*/
+-		switch (Id) {
+-
+-		case OID_SKGE_RLMT_MODE:
+-			*pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
+-			*pLen = sizeof(char);
+-			break;
+-
+-		case OID_SKGE_RLMT_PORT_NUMBER:
+-			Val32 = (SK_U32)pAC->GIni.GIMacsFound;
+-			SK_PNMI_STORE_U32(pBuf, Val32);
+-			*pLen = sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_RLMT_PORT_ACTIVE:
+-			*pBuf = 0;
+-			/*
+-			 * If multiple ports may become active this OID
+-			 * doesn't make sense any more. A new variable in
+-			 * the port structure should be created. However,
+-			 * for this variable the first active port is
+-			 * returned.
+-			 */
+-			PhysPortMax = pAC->GIni.GIMacsFound;
+-
+-			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+-				PhysPortIndex ++) {
+-
+-				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+-					*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
+-					break;
+-				}
+-			}
+-			*pLen = sizeof(char);
+-			break;
+-
+-		case OID_SKGE_RLMT_PORT_PREFERRED:
+-			*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
+-			*pLen = sizeof(char);
+-			break;
+-
+-		case OID_SKGE_RLMT_CHANGE_CTS:
+-			Val64 = pAC->Pnmi.RlmtChangeCts;
+-			SK_PNMI_STORE_U64(pBuf, Val64);
+-			*pLen = sizeof(SK_U64);
+-			break;
+-
+-		case OID_SKGE_RLMT_CHANGE_TIME:
+-			Val64 = pAC->Pnmi.RlmtChangeTime;
+-			SK_PNMI_STORE_U64(pBuf, Val64);
+-			*pLen = sizeof(SK_U64);
+-			break;
+-
+-		case OID_SKGE_RLMT_CHANGE_ESTIM:
+-			Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
+-			SK_PNMI_STORE_U64(pBuf, Val64);
+-			*pLen = sizeof(SK_U64);
+-			break;
+-
+-		case OID_SKGE_RLMT_CHANGE_THRES:
+-			Val64 = pAC->Pnmi.RlmtChangeThreshold;
+-			SK_PNMI_STORE_U64(pBuf, Val64);
+-			*pLen = sizeof(SK_U64);
+-			break;
+-
+-		default:
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+-				("Rlmt: Unknown OID should be handled before"));
+-
+-			pAC->Pnmi.RlmtUpdatedFlag --;
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		pAC->Pnmi.RlmtUpdatedFlag --;
+-	}
+-	else {
+-		/* Perform a preset or set */
+-		switch (Id) {
+-
+-		case OID_SKGE_RLMT_MODE:
+-			/* Check if the buffer length is plausible */
+-			if (*pLen < sizeof(char)) {
+-
+-				*pLen = sizeof(char);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			/* Check if the value range is correct */
+-			if (*pLen != sizeof(char) ||
+-				(*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
+-				*(SK_U8 *)pBuf > 15) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-			/* The preset ends here */
+-			if (Action == SK_PNMI_PRESET) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_OK);
+-			}
+-			/* Send an event to RLMT to change the mode */
+-			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+-			EventParam.Para32[0] |= (SK_U32)(*pBuf);
+-			EventParam.Para32[1] = 0;
+-			if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
+-				EventParam) > 0) {
+-
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
+-					SK_PNMI_ERR037MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-			break;
+-
+-		case OID_SKGE_RLMT_PORT_PREFERRED:
+-			/* Check if the buffer length is plausible */
+-			if (*pLen < sizeof(char)) {
+-
+-				*pLen = sizeof(char);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			/* Check if the value range is correct */
+-			if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
+-				(SK_U8)pAC->GIni.GIMacsFound) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-			/* The preset ends here */
+-			if (Action == SK_PNMI_PRESET) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_OK);
+-			}
+-
+-			/*
+-			 * Send an event to RLMT change the preferred port.
+-			 * A param of -1 means automatic mode. RLMT will
+-			 * make the decision which is the preferred port.
+-			 */
+-			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+-			EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
+-			EventParam.Para32[1] = NetIndex;
+-			if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
+-				EventParam) > 0) {
+-
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
+-					SK_PNMI_ERR038MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-			break;
+-
+-		case OID_SKGE_RLMT_CHANGE_THRES:
+-			/* Check if the buffer length is plausible */
+-			if (*pLen < sizeof(SK_U64)) {
+-
+-				*pLen = sizeof(SK_U64);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			/*
+-			 * There are not many restrictions to the
+-			 * value range.
+-			 */
+-			if (*pLen != sizeof(SK_U64)) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-			/* A preset ends here */
+-			if (Action == SK_PNMI_PRESET) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_OK);
+-			}
+-			/*
+-			 * Store the new threshold, which will be taken
+-			 * on the next timer event.
+-			 */
+-			SK_PNMI_READ_U64(pBuf, Val64);
+-			pAC->Pnmi.RlmtChangeThreshold = Val64;
+-			break;
+-
+-		default:
+-			/* The other OIDs are not be able for set */
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_READ_ONLY);
+-		}
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
+- *
+- * Description:
+- *	Performs get requests on multiple instance variables.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int RlmtStat(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	unsigned int	PhysPortMax;
+-	unsigned int	PhysPortIndex;
+-	unsigned int	Limit;
+-	unsigned int	Offset;
+-	int		Ret;
+-	SK_U32		Val32;
+-	SK_U64		Val64;
+-
+-	/*
+-	 * Calculate the port indexes from the instance.
+-	 */
+-	PhysPortMax = pAC->GIni.GIMacsFound;
+-
+-	if ((Instance != (SK_U32)(-1))) {
+-		/* Check instance range */
+-		if ((Instance < 1) || (Instance > PhysPortMax)) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_UNKNOWN_INST);
+-		}
+-
+-		/* Single net mode */
+-		PhysPortIndex = Instance - 1;
+-
+-		/* Dual net mode */
+-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-			PhysPortIndex = NetIndex;
+-		}
+-
+-		/* Both net modes */
+-		Limit = PhysPortIndex + 1;
+-	}
+-	else {
+-		/* Single net mode */
+-		PhysPortIndex = 0;
+-		Limit = PhysPortMax;
+-
+-		/* Dual net mode */
+-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-			PhysPortIndex = NetIndex;
+-			Limit = PhysPortIndex + 1;
+-		}
+-	}
+-
+-	/*
+-	 * Currently only get requests are allowed.
+-	 */
+-	if (Action != SK_PNMI_GET) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_READ_ONLY);
+-	}
+-
+-	/*
+-	 * Check if the buffer length is large enough.
+-	 */
+-	switch (Id) {
+-
+-	case OID_SKGE_RLMT_PORT_INDEX:
+-	case OID_SKGE_RLMT_STATUS:
+-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
+-
+-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	case OID_SKGE_RLMT_TX_HELLO_CTS:
+-	case OID_SKGE_RLMT_RX_HELLO_CTS:
+-	case OID_SKGE_RLMT_TX_SP_REQ_CTS:
+-	case OID_SKGE_RLMT_RX_SP_CTS:
+-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
+-
+-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
+-			SK_PNMI_ERR039MSG);
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_GENERAL);
+-
+-	}
+-
+-	/*
+-	 * Update statistic and increment semaphores to indicate that
+-	 * an update was already done.
+-	 */
+-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+-
+-		*pLen = 0;
+-		return (Ret);
+-	}
+-	pAC->Pnmi.RlmtUpdatedFlag ++;
+-
+-	/*
+-	 * Get value
+-	 */
+-	Offset = 0;
+-	for (; PhysPortIndex < Limit; PhysPortIndex ++) {
+-
+-		switch (Id) {
+-
+-		case OID_SKGE_RLMT_PORT_INDEX:
+-			Val32 = PhysPortIndex;
+-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-			Offset += sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_RLMT_STATUS:
+-			if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
+-				SK_RLMT_PS_INIT ||
+-				pAC->Rlmt.Port[PhysPortIndex].PortState ==
+-				SK_RLMT_PS_DOWN) {
+-
+-				Val32 = SK_PNMI_RLMT_STATUS_ERROR;
+-			}
+-			else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+-				Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
+-			}
+-			else {
+-				Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
+-			}
+-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-			Offset += sizeof(SK_U32);
+-			break;
+-
+-		case OID_SKGE_RLMT_TX_HELLO_CTS:
+-			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
+-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+-			Offset += sizeof(SK_U64);
+-			break;
+-
+-		case OID_SKGE_RLMT_RX_HELLO_CTS:
+-			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
+-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+-			Offset += sizeof(SK_U64);
+-			break;
+-
+-		case OID_SKGE_RLMT_TX_SP_REQ_CTS:
+-			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
+-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+-			Offset += sizeof(SK_U64);
+-			break;
+-
+-		case OID_SKGE_RLMT_RX_SP_CTS:
+-			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
+-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+-			Offset += sizeof(SK_U64);
+-			break;
+-
+-		default:
+-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+-				("RlmtStat: Unknown OID should be errored before"));
+-
+-			pAC->Pnmi.RlmtUpdatedFlag --;
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-	}
+-	*pLen = Offset;
+-
+-	pAC->Pnmi.RlmtUpdatedFlag --;
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * MacPrivateConf - OID handler function of OIDs concerning the configuration
+- *
+- * Description:
+- *	Get/Presets/Sets the OIDs concerning the configuration.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int MacPrivateConf(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	unsigned int	PhysPortMax;
+-	unsigned int	PhysPortIndex;
+-	unsigned int	LogPortMax;
+-	unsigned int	LogPortIndex;
+-	unsigned int	Limit;
+-	unsigned int	Offset;
+-	char		Val8;
+-	char 		*pBufPtr;
+-	int			Ret;
+-	SK_EVPARA	EventParam;
+-	SK_U32		Val32;
+-
+-	/*
+-	 * Calculate instance if wished. MAC index 0 is the virtual MAC.
+-	 */
+-	PhysPortMax = pAC->GIni.GIMacsFound;
+-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+-
+-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
+-		LogPortMax--;
+-	}
+-
+-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
+-		/* Check instance range */
+-		if ((Instance < 1) || (Instance > LogPortMax)) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_UNKNOWN_INST);
+-		}
+-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+-		Limit = LogPortIndex + 1;
+-	}
+-
+-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
+-
+-		LogPortIndex = 0;
+-		Limit = LogPortMax;
+-	}
+-
+-	/*
+-	 * Perform action
+-	 */
+-	if (Action == SK_PNMI_GET) {
+-
+-		/* Check length */
+-		switch (Id) {
+-
+-		case OID_SKGE_PMD:
+-		case OID_SKGE_CONNECTOR:
+-		case OID_SKGE_LINK_CAP:
+-		case OID_SKGE_LINK_MODE:
+-		case OID_SKGE_LINK_MODE_STATUS:
+-		case OID_SKGE_LINK_STATUS:
+-		case OID_SKGE_FLOWCTRL_CAP:
+-		case OID_SKGE_FLOWCTRL_MODE:
+-		case OID_SKGE_FLOWCTRL_STATUS:
+-		case OID_SKGE_PHY_OPERATION_CAP:
+-		case OID_SKGE_PHY_OPERATION_MODE:
+-		case OID_SKGE_PHY_OPERATION_STATUS:
+-		case OID_SKGE_SPEED_CAP:
+-		case OID_SKGE_SPEED_MODE:
+-		case OID_SKGE_SPEED_STATUS:
+-			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
+-
+-				*pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			break;
+-
+-        case OID_SKGE_MTU:
+-        case OID_SKGE_PHY_TYPE:
+-			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
+-
+-				*pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			break;
+-
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
+-				SK_PNMI_ERR041MSG);
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		/*
+-		 * Update statistic and increment semaphore to indicate
+-		 * that an update was already done.
+-		 */
+-		if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
+-
+-			*pLen = 0;
+-			return (Ret);
+-		}
+-		pAC->Pnmi.SirqUpdatedFlag ++;
+-
+-		/*
+-		 * Get value
+-		 */
+-		Offset = 0;
+-		for (; LogPortIndex < Limit; LogPortIndex ++) {
+-
+-			pBufPtr = pBuf + Offset;
+-			
+-			switch (Id) {
+-
+-			case OID_SKGE_PMD:
+-				*pBufPtr = pAC->Pnmi.PMD;
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_CONNECTOR:
+-				*pBufPtr = pAC->Pnmi.Connector;
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_PHY_TYPE:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						continue;
+-					}
+-					else {
+-						/* Get value for physical ports */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-						Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
+-						SK_PNMI_STORE_U32(pBufPtr, Val32);
+-					}
+-				}
+-				else { /* DualNetMode */
+-					
+-					Val32 = pAC->GIni.GP[NetIndex].PhyType;
+-					SK_PNMI_STORE_U32(pBufPtr, Val32);
+-				}
+-				Offset += sizeof(SK_U32);
+-				break;
+-
+-			case OID_SKGE_LINK_CAP:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical ports */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
+-					}
+-				}
+-				else { /* DualNetMode */
+-					
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_LINK_MODE:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical ports */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
+-					}
+-				}
+-				else { /* DualNetMode */
+-				
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_LINK_MODE_STATUS:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical port */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-
+-						*pBufPtr =
+-							CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
+-					}
+-				}
+-				else { /* DualNetMode */
+-					
+-					*pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_LINK_STATUS:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical ports */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-	
+-						*pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
+-					}
+-				}
+-				else { /* DualNetMode */
+-
+-					*pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_FLOWCTRL_CAP:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical ports */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-	
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
+-					}
+-				}
+-				else { /* DualNetMode */
+-				
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_FLOWCTRL_MODE:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical port */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-	
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
+-					}
+-				}
+-				else { /* DualNetMode */
+-
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_FLOWCTRL_STATUS:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical port */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-	
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
+-					}
+-				}
+-				else { /* DualNetMode */
+-
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_PHY_OPERATION_CAP:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical ports */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-	
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
+-					}
+-				}
+-				else { /* DualNetMode */
+-				
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_PHY_OPERATION_MODE:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical port */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
+-					}
+-				}
+-				else { /* DualNetMode */
+-				
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_PHY_OPERATION_STATUS:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical port */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-	
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
+-					}
+-				}
+-				else {
+-				
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_SPEED_CAP:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical ports */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-	
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
+-					}
+-				}
+-				else { /* DualNetMode */
+-				
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_SPEED_MODE:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical port */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-	
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
+-					}
+-				}
+-				else { /* DualNetMode */
+-
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-
+-			case OID_SKGE_SPEED_STATUS:
+-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+-					if (LogPortIndex == 0) {
+-						/* Get value for virtual port */
+-						VirtualConf(pAC, IoC, Id, pBufPtr);
+-					}
+-					else {
+-						/* Get value for physical port */
+-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+-							pAC, LogPortIndex);
+-	
+-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
+-					}
+-				}
+-				else { /* DualNetMode */
+-
+-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
+-				}
+-				Offset += sizeof(char);
+-				break;
+-			
+-			case OID_SKGE_MTU:
+-				Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
+-				SK_PNMI_STORE_U32(pBufPtr, Val32);
+-				Offset += sizeof(SK_U32);
+-				break;
+-
+-			default:
+-				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+-					("MacPrivateConf: Unknown OID should be handled before"));
+-
+-				pAC->Pnmi.SirqUpdatedFlag --;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-		}
+-		*pLen = Offset;
+-		pAC->Pnmi.SirqUpdatedFlag --;
+-
+-		return (SK_PNMI_ERR_OK);
+-	}
+-
+-	/*
+-	 * From here SET or PRESET action. Check if the passed
+-	 * buffer length is plausible.
+-	 */
+-	switch (Id) {
+-
+-	case OID_SKGE_LINK_MODE:
+-	case OID_SKGE_FLOWCTRL_MODE:
+-	case OID_SKGE_PHY_OPERATION_MODE:
+-	case OID_SKGE_SPEED_MODE:
+-		if (*pLen < Limit - LogPortIndex) {
+-
+-			*pLen = Limit - LogPortIndex;
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		if (*pLen != Limit - LogPortIndex) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_BAD_VALUE);
+-		}
+-		break;
+-
+-	case OID_SKGE_MTU:
+-		if (*pLen < sizeof(SK_U32)) {
+-
+-			*pLen = sizeof(SK_U32);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		if (*pLen != sizeof(SK_U32)) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_BAD_VALUE);
+-		}
+-		break;
+-
+-    default:
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_READ_ONLY);
+-	}
+-
+-	/*
+-	 * Perform preset or set
+-	 */
+-	Offset = 0;
+-	for (; LogPortIndex < Limit; LogPortIndex ++) {
+-
+-		switch (Id) {
+-
+-		case OID_SKGE_LINK_MODE:
+-			/* Check the value range */
+-			Val8 = *(pBuf + Offset);
+-			if (Val8 == 0) {
+-
+-				Offset += sizeof(char);
+-				break;
+-			}
+-			if (Val8 < SK_LMODE_HALF ||
+-				(LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
+-				(LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-
+-			/* The preset ends here */
+-			if (Action == SK_PNMI_PRESET) {
+-
+-				return (SK_PNMI_ERR_OK);
+-			}
+-
+-			if (LogPortIndex == 0) {
+-
+-				/*
+-				 * The virtual port consists of all currently
+-				 * active ports. Find them and send an event
+-				 * with the new link mode to SIRQ.
+-				 */
+-				for (PhysPortIndex = 0;
+-					PhysPortIndex < PhysPortMax;
+-					PhysPortIndex ++) {
+-
+-					if (!pAC->Pnmi.Port[PhysPortIndex].
+-						ActiveFlag) {
+-
+-						continue;
+-					}
+-
+-					EventParam.Para32[0] = PhysPortIndex;
+-					EventParam.Para32[1] = (SK_U32)Val8;
+-					if (SkGeSirqEvent(pAC, IoC,
+-						SK_HWEV_SET_LMODE,
+-						EventParam) > 0) {
+-
+-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-							SK_PNMI_ERR043,
+-							SK_PNMI_ERR043MSG);
+-
+-						*pLen = 0;
+-						return (SK_PNMI_ERR_GENERAL);
+-					}
+-				}
+-			}
+-			else {
+-				/*
+-				 * Send an event with the new link mode to
+-				 * the SIRQ module.
+-				 */
+-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+-					pAC, LogPortIndex);
+-				EventParam.Para32[1] = (SK_U32)Val8;
+-				if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
+-					EventParam) > 0) {
+-
+-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-						SK_PNMI_ERR043,
+-						SK_PNMI_ERR043MSG);
+-
+-					*pLen = 0;
+-					return (SK_PNMI_ERR_GENERAL);
+-				}
+-			}
+-			Offset += sizeof(char);
+-			break;
+-
+-		case OID_SKGE_FLOWCTRL_MODE:
+-			/* Check the value range */
+-			Val8 = *(pBuf + Offset);
+-			if (Val8 == 0) {
+-
+-				Offset += sizeof(char);
+-				break;
+-			}
+-			if (Val8 < SK_FLOW_MODE_NONE ||
+-				(LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
+-				(LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-
+-			/* The preset ends here */
+-			if (Action == SK_PNMI_PRESET) {
+-
+-				return (SK_PNMI_ERR_OK);
+-			}
+-
+-			if (LogPortIndex == 0) {
+-
+-				/*
+-				 * The virtual port consists of all currently
+-				 * active ports. Find them and send an event
+-				 * with the new flow control mode to SIRQ.
+-				 */
+-				for (PhysPortIndex = 0;
+-					PhysPortIndex < PhysPortMax;
+-					PhysPortIndex ++) {
+-
+-					if (!pAC->Pnmi.Port[PhysPortIndex].
+-						ActiveFlag) {
+-
+-						continue;
+-					}
+-
+-					EventParam.Para32[0] = PhysPortIndex;
+-					EventParam.Para32[1] = (SK_U32)Val8;
+-					if (SkGeSirqEvent(pAC, IoC,
+-						SK_HWEV_SET_FLOWMODE,
+-						EventParam) > 0) {
+-
+-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-							SK_PNMI_ERR044,
+-							SK_PNMI_ERR044MSG);
+-
+-						*pLen = 0;
+-						return (SK_PNMI_ERR_GENERAL);
+-					}
+-				}
+-			}
+-			else {
+-				/*
+-				 * Send an event with the new flow control
+-				 * mode to the SIRQ module.
+-				 */
+-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+-					pAC, LogPortIndex);
+-				EventParam.Para32[1] = (SK_U32)Val8;
+-				if (SkGeSirqEvent(pAC, IoC,
+-					SK_HWEV_SET_FLOWMODE, EventParam)
+-					> 0) {
+-
+-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-						SK_PNMI_ERR044,
+-						SK_PNMI_ERR044MSG);
+-
+-					*pLen = 0;
+-					return (SK_PNMI_ERR_GENERAL);
+-				}
+-			}
+-			Offset += sizeof(char);
+-			break;
+-
+-		case OID_SKGE_PHY_OPERATION_MODE :
+-			/* Check the value range */
+-			Val8 = *(pBuf + Offset);
+-			if (Val8 == 0) {
+-				/* mode of this port remains unchanged */
+-				Offset += sizeof(char);
+-				break;
+-			}
+-			if (Val8 < SK_MS_MODE_AUTO ||
+-				(LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
+-				(LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-
+-			/* The preset ends here */
+-			if (Action == SK_PNMI_PRESET) {
+-
+-				return (SK_PNMI_ERR_OK);
+-			}
+-
+-			if (LogPortIndex == 0) {
+-
+-				/*
+-				 * The virtual port consists of all currently
+-				 * active ports. Find them and send an event
+-				 * with new master/slave (role) mode to SIRQ.
+-				 */
+-				for (PhysPortIndex = 0;
+-					PhysPortIndex < PhysPortMax;
+-					PhysPortIndex ++) {
+-
+-					if (!pAC->Pnmi.Port[PhysPortIndex].
+-						ActiveFlag) {
+-
+-						continue;
+-					}
+-
+-					EventParam.Para32[0] = PhysPortIndex;
+-					EventParam.Para32[1] = (SK_U32)Val8;
+-					if (SkGeSirqEvent(pAC, IoC,
+-						SK_HWEV_SET_ROLE,
+-						EventParam) > 0) {
+-
+-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-							SK_PNMI_ERR042,
+-							SK_PNMI_ERR042MSG);
+-
+-						*pLen = 0;
+-						return (SK_PNMI_ERR_GENERAL);
+-					}
+-				}
+-			}
+-			else {
+-				/*
+-				 * Send an event with the new master/slave
+-				 * (role) mode to the SIRQ module.
+-				 */
+-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+-					pAC, LogPortIndex);
+-				EventParam.Para32[1] = (SK_U32)Val8;
+-				if (SkGeSirqEvent(pAC, IoC,
+-					SK_HWEV_SET_ROLE, EventParam) > 0) {
+-
+-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-						SK_PNMI_ERR042,
+-						SK_PNMI_ERR042MSG);
+-
+-					*pLen = 0;
+-					return (SK_PNMI_ERR_GENERAL);
+-				}
+-			}
+-
+-			Offset += sizeof(char);
+-			break;
+-
+-		case OID_SKGE_SPEED_MODE:
+-			/* Check the value range */
+-			Val8 = *(pBuf + Offset);
+-			if (Val8 == 0) {
+-
+-				Offset += sizeof(char);
+-				break;
+-			}
+-			if (Val8 < (SK_LSPEED_AUTO) ||
+-				(LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
+-				(LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-
+-			/* The preset ends here */
+-			if (Action == SK_PNMI_PRESET) {
+-
+-				return (SK_PNMI_ERR_OK);
+-			}
+-
+-			if (LogPortIndex == 0) {
+-
+-				/*
+-				 * The virtual port consists of all currently
+-				 * active ports. Find them and send an event
+-				 * with the new flow control mode to SIRQ.
+-				 */
+-				for (PhysPortIndex = 0;
+-					PhysPortIndex < PhysPortMax;
+-					PhysPortIndex ++) {
+-
+-					if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+-						continue;
+-					}
+-
+-					EventParam.Para32[0] = PhysPortIndex;
+-					EventParam.Para32[1] = (SK_U32)Val8;
+-					if (SkGeSirqEvent(pAC, IoC,
+-						SK_HWEV_SET_SPEED,
+-						EventParam) > 0) {
+-
+-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-							SK_PNMI_ERR045,
+-							SK_PNMI_ERR045MSG);
+-
+-						*pLen = 0;
+-						return (SK_PNMI_ERR_GENERAL);
+-					}
+-				}
+-			}
+-			else {
+-				/*
+-				 * Send an event with the new flow control
+-				 * mode to the SIRQ module.
+-				 */
+-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+-					pAC, LogPortIndex);
+-				EventParam.Para32[1] = (SK_U32)Val8;
+-				if (SkGeSirqEvent(pAC, IoC,
+-					SK_HWEV_SET_SPEED,
+-					EventParam) > 0) {
+-
+-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
+-						SK_PNMI_ERR045,
+-						SK_PNMI_ERR045MSG);
+-
+-					*pLen = 0;
+-					return (SK_PNMI_ERR_GENERAL);
+-				}
+-			}
+-			Offset += sizeof(char);
+-			break;
+-
+-		case OID_SKGE_MTU :
+-			/* Check the value range */
+-			Val32 = *(SK_U32*)(pBuf + Offset);
+-			if (Val32 == 0) {
+-				/* mtu of this port remains unchanged */
+-				Offset += sizeof(SK_U32);
+-				break;
+-			}
+-			if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_BAD_VALUE);
+-			}
+-
+-			/* The preset ends here */
+-			if (Action == SK_PNMI_PRESET) {
+-				return (SK_PNMI_ERR_OK);
+-			}
+-
+-			if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-
+-			Offset += sizeof(SK_U32);
+-			break;
+-		
+-		default:
+-            SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+-                ("MacPrivateConf: Unknown OID should be handled before set"));
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Monitor - OID handler function for RLMT_MONITOR_XXX
+- *
+- * Description:
+- *	Because RLMT currently does not support the monitoring of
+- *	remote adapter cards, we return always an empty table.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
+- *	                         value range.
+- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-PNMI_STATIC int Monitor(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	unsigned int	Index;
+-	unsigned int	Limit;
+-	unsigned int	Offset;
+-	unsigned int	Entries;
+-
+-	
+-	/*
+-	 * Calculate instance if wished.
+-	 */
+-	/* XXX Not yet implemented. Return always an empty table. */
+-	Entries = 0;
+-
+-	if ((Instance != (SK_U32)(-1))) {
+-
+-		if ((Instance < 1) || (Instance > Entries)) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_UNKNOWN_INST);
+-		}
+-
+-		Index = (unsigned int)Instance - 1;
+-		Limit = (unsigned int)Instance;
+-	}
+-	else {
+-		Index = 0;
+-		Limit = Entries;
+-	}
+-
+-	/*
+-	 * Get/Set value
+-	*/
+-	if (Action == SK_PNMI_GET) {
+-
+-		for (Offset=0; Index < Limit; Index ++) {
+-
+-			switch (Id) {
+-
+-			case OID_SKGE_RLMT_MONITOR_INDEX:
+-			case OID_SKGE_RLMT_MONITOR_ADDR:
+-			case OID_SKGE_RLMT_MONITOR_ERRS:
+-			case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
+-			case OID_SKGE_RLMT_MONITOR_ADMIN:
+-				break;
+-
+-			default:
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
+-					SK_PNMI_ERR046MSG);
+-
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-		}
+-		*pLen = Offset;
+-	}
+-	else {
+-		/* Only MONITOR_ADMIN can be set */
+-		if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_READ_ONLY);
+-		}
+-
+-		/* Check if the length is plausible */
+-		if (*pLen < (Limit - Index)) {
+-
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		/* Okay, we have a wide value range */
+-		if (*pLen != (Limit - Index)) {
+-
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_BAD_VALUE);
+-		}
+-/*
+-		for (Offset=0; Index < Limit; Index ++) {
+-		}
+-*/
+-/*
+- * XXX Not yet implemented. Return always BAD_VALUE, because the table
+- * is empty.
+- */
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_BAD_VALUE);
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * VirtualConf - Calculates the values of configuration OIDs for virtual port
+- *
+- * Description:
+- *	We handle here the get of the configuration group OIDs, which are
+- *	a little bit complicated. The virtual port consists of all currently
+- *	active physical ports. If multiple ports are active and configured
+- *	differently we get in some trouble to return a single value. So we
+- *	get the value of the first active port and compare it with that of
+- *	the other active ports. If they are not the same, we return a value
+- *	that indicates that the state is indeterminated.
+- *
+- * Returns:
+- *	Nothing
+- */
+-PNMI_STATIC void VirtualConf(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf)		/* Buffer used for the management data transfer */
+-{
+-	unsigned int	PhysPortMax;
+-	unsigned int	PhysPortIndex;
+-	SK_U8		Val8;
+-	SK_U32		Val32;
+-	SK_BOOL		PortActiveFlag;
+-	SK_GEPORT	*pPrt;
+-
+-	*pBuf = 0;
+-	PortActiveFlag = SK_FALSE;
+-	PhysPortMax = pAC->GIni.GIMacsFound;
+-	
+-	for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+-		PhysPortIndex ++) {
+-
+-		pPrt = &pAC->GIni.GP[PhysPortIndex];
+-
+-		/* Check if the physical port is active */
+-		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+-			continue;
+-		}
+-
+-		PortActiveFlag = SK_TRUE;
+-
+-		switch (Id) {
+-
+-		case OID_SKGE_PHY_TYPE:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-				Val32 = pPrt->PhyType;
+-				SK_PNMI_STORE_U32(pBuf, Val32);
+-				continue;
+-			}
+-
+-		case OID_SKGE_LINK_CAP:
+-
+-			/*
+-			 * Different capabilities should not happen, but
+-			 * in the case of the cases OR them all together.
+-			 * From a curious point of view the virtual port
+-			 * is capable of all found capabilities.
+-			 */
+-			*pBuf |= pPrt->PLinkCap;
+-			break;
+-
+-		case OID_SKGE_LINK_MODE:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = pPrt->PLinkModeConf;
+-				continue;
+-			}
+-
+-			/*
+-			 * If we find an active port with a different link
+-			 * mode than the first one we return a value that
+-			 * indicates that the link mode is indeterminated.
+-			 */
+-			if (*pBuf != pPrt->PLinkModeConf) {
+-
+-				*pBuf = SK_LMODE_INDETERMINATED;
+-			}
+-			break;
+-
+-		case OID_SKGE_LINK_MODE_STATUS:
+-			/* Get the link mode of the physical port */
+-			Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
+-
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = Val8;
+-				continue;
+-			}
+-
+-			/*
+-			 * If we find an active port with a different link
+-			 * mode status than the first one we return a value
+-			 * that indicates that the link mode status is
+-			 * indeterminated.
+-			 */
+-			if (*pBuf != Val8) {
+-
+-				*pBuf = SK_LMODE_STAT_INDETERMINATED;
+-			}
+-			break;
+-
+-		case OID_SKGE_LINK_STATUS:
+-			/* Get the link status of the physical port */
+-			Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
+-
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = Val8;
+-				continue;
+-			}
+-
+-			/*
+-			 * If we find an active port with a different link
+-			 * status than the first one, we return a value
+-			 * that indicates that the link status is
+-			 * indeterminated.
+-			 */
+-			if (*pBuf != Val8) {
+-
+-				*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
+-			}
+-			break;
+-
+-		case OID_SKGE_FLOWCTRL_CAP:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = pPrt->PFlowCtrlCap;
+-				continue;
+-			}
+-
+-			/*
+-			 * From a curious point of view the virtual port
+-			 * is capable of all found capabilities.
+-			 */
+-			*pBuf |= pPrt->PFlowCtrlCap;
+-			break;
+-
+-		case OID_SKGE_FLOWCTRL_MODE:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = pPrt->PFlowCtrlMode;
+-				continue;
+-			}
+-
+-			/*
+-			 * If we find an active port with a different flow
+-			 * control mode than the first one, we return a value
+-			 * that indicates that the mode is indeterminated.
+-			 */
+-			if (*pBuf != pPrt->PFlowCtrlMode) {
+-
+-				*pBuf = SK_FLOW_MODE_INDETERMINATED;
+-			}
+-			break;
+-
+-		case OID_SKGE_FLOWCTRL_STATUS:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = pPrt->PFlowCtrlStatus;
+-				continue;
+-			}
+-
+-			/*
+-			 * If we find an active port with a different flow
+-			 * control status than the first one, we return a
+-			 * value that indicates that the status is
+-			 * indeterminated.
+-			 */
+-			if (*pBuf != pPrt->PFlowCtrlStatus) {
+-
+-				*pBuf = SK_FLOW_STAT_INDETERMINATED;
+-			}
+-			break;
+-		
+-		case OID_SKGE_PHY_OPERATION_CAP:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = pPrt->PMSCap;
+-				continue;
+-			}
+-
+-			/*
+-			 * From a curious point of view the virtual port
+-			 * is capable of all found capabilities.
+-			 */
+-			*pBuf |= pPrt->PMSCap;
+-			break;
+-
+-		case OID_SKGE_PHY_OPERATION_MODE:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = pPrt->PMSMode;
+-				continue;
+-			}
+-
+-			/*
+-			 * If we find an active port with a different master/
+-			 * slave mode than the first one, we return a value
+-			 * that indicates that the mode is indeterminated.
+-			 */
+-			if (*pBuf != pPrt->PMSMode) {
+-
+-				*pBuf = SK_MS_MODE_INDETERMINATED;
+-			}
+-			break;
+-
+-		case OID_SKGE_PHY_OPERATION_STATUS:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = pPrt->PMSStatus;
+-				continue;
+-			}
+-
+-			/*
+-			 * If we find an active port with a different master/
+-			 * slave status than the first one, we return a
+-			 * value that indicates that the status is
+-			 * indeterminated.
+-			 */
+-			if (*pBuf != pPrt->PMSStatus) {
+-
+-				*pBuf = SK_MS_STAT_INDETERMINATED;
+-			}
+-			break;
+-		
+-		case OID_SKGE_SPEED_MODE:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = pPrt->PLinkSpeed;
+-				continue;
+-			}
+-
+-			/*
+-			 * If we find an active port with a different flow
+-			 * control mode than the first one, we return a value
+-			 * that indicates that the mode is indeterminated.
+-			 */
+-			if (*pBuf != pPrt->PLinkSpeed) {
+-
+-				*pBuf = SK_LSPEED_INDETERMINATED;
+-			}
+-			break;
+-		
+-		case OID_SKGE_SPEED_STATUS:
+-			/* Check if it is the first active port */
+-			if (*pBuf == 0) {
+-
+-				*pBuf = pPrt->PLinkSpeedUsed;
+-				continue;
+-			}
+-
+-			/*
+-			 * If we find an active port with a different flow
+-			 * control status than the first one, we return a
+-			 * value that indicates that the status is
+-			 * indeterminated.
+-			 */
+-			if (*pBuf != pPrt->PLinkSpeedUsed) {
+-
+-				*pBuf = SK_LSPEED_STAT_INDETERMINATED;
+-			}
+-			break;
+-		}
+-	}
+-
+-	/*
+-	 * If no port is active return an indeterminated answer
+-	 */
+-	if (!PortActiveFlag) {
+-
+-		switch (Id) {
+-
+-		case OID_SKGE_LINK_CAP:
+-			*pBuf = SK_LMODE_CAP_INDETERMINATED;
+-			break;
+-
+-		case OID_SKGE_LINK_MODE:
+-			*pBuf = SK_LMODE_INDETERMINATED;
+-			break;
+-
+-		case OID_SKGE_LINK_MODE_STATUS:
+-			*pBuf = SK_LMODE_STAT_INDETERMINATED;
+-			break;
+-
+-		case OID_SKGE_LINK_STATUS:
+-			*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
+-			break;
+-
+-		case OID_SKGE_FLOWCTRL_CAP:
+-		case OID_SKGE_FLOWCTRL_MODE:
+-			*pBuf = SK_FLOW_MODE_INDETERMINATED;
+-			break;
+-
+-		case OID_SKGE_FLOWCTRL_STATUS:
+-			*pBuf = SK_FLOW_STAT_INDETERMINATED;
+-			break;
+-			
+-		case OID_SKGE_PHY_OPERATION_CAP:
+-			*pBuf = SK_MS_CAP_INDETERMINATED;
+-			break;
+-
+-		case OID_SKGE_PHY_OPERATION_MODE:
+-			*pBuf = SK_MS_MODE_INDETERMINATED;
+-			break;
+-
+-		case OID_SKGE_PHY_OPERATION_STATUS:
+-			*pBuf = SK_MS_STAT_INDETERMINATED;
+-			break;
+-		case OID_SKGE_SPEED_CAP:
+-			*pBuf = SK_LSPEED_CAP_INDETERMINATED;
+-			break;
+-
+-		case OID_SKGE_SPEED_MODE:
+-			*pBuf = SK_LSPEED_INDETERMINATED;
+-			break;
+-
+-		case OID_SKGE_SPEED_STATUS:
+-			*pBuf = SK_LSPEED_STAT_INDETERMINATED;
+-			break;
+-		}
+-	}
+-}
+-
+-/*****************************************************************************
+- *
+- * CalculateLinkStatus - Determins the link status of a physical port
+- *
+- * Description:
+- *	Determins the link status the following way:
+- *	  LSTAT_PHY_DOWN:  Link is down
+- *	  LSTAT_AUTONEG:   Auto-negotiation failed
+- *	  LSTAT_LOG_DOWN:  Link is up but RLMT did not yet put the port
+- *	                   logically up.
+- *	  LSTAT_LOG_UP:    RLMT marked the port as up
+- *
+- * Returns:
+- *	Link status of physical port
+- */
+-PNMI_STATIC SK_U8 CalculateLinkStatus(
+-SK_AC *pAC,			/* Pointer to adapter context */
+-SK_IOC IoC,			/* IO context handle */
+-unsigned int PhysPortIndex)	/* Physical port index */
+-{
+-	SK_U8	Result;
+-
+-	if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
+-
+-		Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
+-	}
+-	else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
+-
+-		Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
+-				}
+-	else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
+-
+-		Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
+-	}
+-	else {
+-		Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
+-	}
+-
+-	return (Result);
+-}
+-
+-/*****************************************************************************
+- *
+- * CalculateLinkModeStatus - Determins the link mode status of a phys. port
+- *
+- * Description:
+- *	The COMMON module only tells us if the mode is half or full duplex.
+- *	But in the decade of auto sensing it is useful for the user to
+- *	know if the mode was negotiated or forced. Therefore we have a
+- *	look to the mode, which was last used by the negotiation process.
+- *
+- * Returns:
+- *	The link mode status
+- */
+-PNMI_STATIC SK_U8 CalculateLinkModeStatus(
+-SK_AC *pAC,			/* Pointer to adapter context */
+-SK_IOC IoC,			/* IO context handle */
+-unsigned int PhysPortIndex)	/* Physical port index */
+-{
+-	SK_U8	Result;
+-
+-	/* Get the current mode, which can be full or half duplex */
+-	Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
+-
+-	/* Check if no valid mode could be found (link is down) */
+-	if (Result < SK_LMODE_STAT_HALF) {
+-
+-		Result = SK_LMODE_STAT_UNKNOWN;
+-	}
+-	else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
+-
+-		/*
+-		 * Auto-negotiation was used to bring up the link. Change
+-		 * the already found duplex status that it indicates
+-		 * auto-negotiation was involved.
+-		 */
+-		if (Result == SK_LMODE_STAT_HALF) {
+-
+-			Result = SK_LMODE_STAT_AUTOHALF;
+-		}
+-		else if (Result == SK_LMODE_STAT_FULL) {
+-
+-			Result = SK_LMODE_STAT_AUTOFULL;
+-		}
+-	}
+-
+-	return (Result);
+-}
+-
+-/*****************************************************************************
+- *
+- * GetVpdKeyArr - Obtain an array of VPD keys
+- *
+- * Description:
+- *	Read the VPD keys and build an array of VPD keys, which are
+- *	easy to access.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK	     Task successfully performed.
+- *	SK_PNMI_ERR_GENERAL  Something went wrong.
+- */
+-PNMI_STATIC int GetVpdKeyArr(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-char *pKeyArr,		/* Ptr KeyArray */
+-unsigned int KeyArrLen,	/* Length of array in bytes */
+-unsigned int *pKeyNo)	/* Number of keys */
+-{
+-	unsigned int		BufKeysLen = SK_PNMI_VPD_BUFSIZE;
+-	char			BufKeys[SK_PNMI_VPD_BUFSIZE];
+-	unsigned int		StartOffset;
+-	unsigned int		Offset;
+-	int			Index;
+-	int			Ret;
+-
+-
+-	SK_MEMSET(pKeyArr, 0, KeyArrLen);
+-
+-	/*
+-	 * Get VPD key list
+-	 */
+-	Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
+-		(int *)pKeyNo);
+-	if (Ret > 0) {
+-
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
+-			SK_PNMI_ERR014MSG);
+-
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-	/* If no keys are available return now */
+-	if (*pKeyNo == 0 || BufKeysLen == 0) {
+-
+-		return (SK_PNMI_ERR_OK);
+-	}
+-	/*
+-	 * If the key list is too long for us trunc it and give a
+-	 * errorlog notification. This case should not happen because
+-	 * the maximum number of keys is limited due to RAM limitations
+-	 */
+-	if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
+-
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
+-			SK_PNMI_ERR015MSG);
+-
+-		*pKeyNo = SK_PNMI_VPD_ENTRIES;
+-	}
+-
+-	/*
+-	 * Now build an array of fixed string length size and copy
+-	 * the keys together.
+-	 */
+-	for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
+-		Offset ++) {
+-
+-		if (BufKeys[Offset] != 0) {
+-
+-			continue;
+-		}
+-
+-		if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
+-				SK_PNMI_ERR016MSG);
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-
+-		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
+-			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
+-
+-		Index ++;
+-		StartOffset = Offset + 1;
+-	}
+-
+-	/* Last key not zero terminated? Get it anyway */
+-	if (StartOffset < Offset) {
+-
+-		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
+-			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * SirqUpdate - Let the SIRQ update its internal values
+- *
+- * Description:
+- *	Just to be sure that the SIRQ module holds its internal data
+- *	structures up to date, we send an update event before we make
+- *	any access.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK	     Task successfully performed.
+- *	SK_PNMI_ERR_GENERAL  Something went wrong.
+- */
+-PNMI_STATIC int SirqUpdate(
+-SK_AC *pAC,	/* Pointer to adapter context */
+-SK_IOC IoC)	/* IO context handle */
+-{
+-	SK_EVPARA	EventParam;
+-
+-
+-	/* Was the module already updated during the current PNMI call? */
+-	if (pAC->Pnmi.SirqUpdatedFlag > 0) {
+-
+-		return (SK_PNMI_ERR_OK);
+-	}
+-
+-	/* Send an synchronuous update event to the module */
+-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+-	if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
+-
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
+-			SK_PNMI_ERR047MSG);
+-
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * RlmtUpdate - Let the RLMT update its internal values
+- *
+- * Description:
+- *	Just to be sure that the RLMT module holds its internal data
+- *	structures up to date, we send an update event before we make
+- *	any access.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK	     Task successfully performed.
+- *	SK_PNMI_ERR_GENERAL  Something went wrong.
+- */
+-PNMI_STATIC int RlmtUpdate(
+-SK_AC *pAC,	/* Pointer to adapter context */
+-SK_IOC IoC,	/* IO context handle */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
+-{
+-	SK_EVPARA	EventParam;
+-
+-
+-	/* Was the module already updated during the current PNMI call? */
+-	if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
+-
+-		return (SK_PNMI_ERR_OK);
+-	}
+-
+-	/* Send an synchronuous update event to the module */
+-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+-	EventParam.Para32[0] = NetIndex;
+-	EventParam.Para32[1] = (SK_U32)-1;
+-	if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
+-
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
+-			SK_PNMI_ERR048MSG);
+-
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * MacUpdate - Force the XMAC to output the current statistic
+- *
+- * Description:
+- *	The XMAC holds its statistic internally. To obtain the current
+- *	values we must send a command so that the statistic data will
+- *	be written to a predefined memory area on the adapter.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK	     Task successfully performed.
+- *	SK_PNMI_ERR_GENERAL  Something went wrong.
+- */
+-PNMI_STATIC int MacUpdate(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-unsigned int FirstMac,	/* Index of the first Mac to be updated */
+-unsigned int LastMac)	/* Index of the last Mac to be updated */
+-{
+-	unsigned int	MacIndex;
+-
+-	/*
+-	 * Were the statistics already updated during the
+-	 * current PNMI call?
+-	 */
+-	if (pAC->Pnmi.MacUpdatedFlag > 0) {
+-
+-		return (SK_PNMI_ERR_OK);
+-	}
+-
+-	/* Send an update command to all MACs specified */
+-	for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
+-
+-		/*
+-		 * 2002-09-13 pweber:	Freeze the current SW counters.
+-		 *                      (That should be done as close as
+-		 *                      possible to the update of the
+-		 *                      HW counters)
+-		 */
+-		if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
+-			pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
+-		}
+-			
+-		/* 2002-09-13 pweber:  Update the HW counter  */
+-		if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
+-
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-	}
+-
+-	return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * GetStatVal - Retrieve an XMAC statistic counter
+- *
+- * Description:
+- *	Retrieves the statistic counter of a virtual or physical port. The
+- *	virtual port is identified by the index 0. It consists of all
+- *	currently active ports. To obtain the counter value for this port
+- *	we must add the statistic counter of all active ports. To grant
+- *	continuous counter values for the virtual port even when port
+- *	switches occur we must additionally add a delta value, which was
+- *	calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
+- *
+- * Returns:
+- *	Requested statistic value
+- */
+-PNMI_STATIC SK_U64 GetStatVal(
+-SK_AC *pAC,					/* Pointer to adapter context */
+-SK_IOC IoC,					/* IO context handle */
+-unsigned int LogPortIndex,	/* Index of the logical Port to be processed */
+-unsigned int StatIndex,		/* Index to statistic value */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
+-{
+-	unsigned int	PhysPortIndex;
+-	unsigned int	PhysPortMax;
+-	SK_U64			Val = 0;
+-
+-
+-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {	/* Dual net mode */
+-
+-		PhysPortIndex = NetIndex;
+-		
+-		Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+-	}
+-	else {	/* Single Net mode */
+-
+-		if (LogPortIndex == 0) {
+-
+-			PhysPortMax = pAC->GIni.GIMacsFound;
+-
+-			/* Add counter of all active ports */
+-			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+-				PhysPortIndex ++) {
+-
+-				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+-					Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+-				}
+-			}
+-
+-			/* Correct value because of port switches */
+-			Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
+-		}
+-		else {
+-			/* Get counter value of physical port */
+-			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+-			
+-			Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+-		}
+-	}
+-	return (Val);
+-}
+-
+-/*****************************************************************************
+- *
+- * GetPhysStatVal - Get counter value for physical port
+- *
+- * Description:
+- *	Builds a 64bit counter value. Except for the octet counters
+- *	the lower 32bit are counted in hardware and the upper 32bit
+- *	in software by monitoring counter overflow interrupts in the
+- *	event handler. To grant continous counter values during XMAC
+- *	resets (caused by a workaround) we must add a delta value.
+- *	The delta was calculated in the event handler when a
+- *	SK_PNMI_EVT_XMAC_RESET was received.
+- *
+- * Returns:
+- *	Counter value
+- */
+-PNMI_STATIC SK_U64 GetPhysStatVal(
+-SK_AC *pAC,					/* Pointer to adapter context */
+-SK_IOC IoC,					/* IO context handle */
+-unsigned int PhysPortIndex,	/* Index of the logical Port to be processed */
+-unsigned int StatIndex)		/* Index to statistic value */
+-{
+-	SK_U64	Val = 0;
+-	SK_U32	LowVal = 0;
+-	SK_U32	HighVal = 0;
+-	SK_U16	Word;
+-	int		MacType;
+-	unsigned int HelpIndex;
+-	SK_GEPORT	*pPrt;
+-	
+-	SK_PNMI_PORT	*pPnmiPrt;
+-	SK_GEMACFUNC	*pFnMac;
+-	
+-	pPrt = &pAC->GIni.GP[PhysPortIndex];
+-	
+-	MacType = pAC->GIni.GIMacType;
+-	
+-	/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+-	if (MacType == SK_MAC_XMAC) {
+-		pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
+-	}
+-	else {
+-		pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
+-	}
+-	
+-	pFnMac   = &pAC->GIni.GIFunc;
+-
+-	switch (StatIndex) {
+-	case SK_PNMI_HTX:
+-		if (MacType == SK_MAC_GMAC) {
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-							StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
+-							&LowVal);
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-							StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
+-							&HighVal);
+-			LowVal += HighVal;
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-							StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
+-							&HighVal);
+-			LowVal += HighVal;
+-		}
+-		else {
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-										  StatAddr[StatIndex][MacType].Reg,
+-										  &LowVal);
+-		}
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		break;
+-	
+-	case SK_PNMI_HRX:
+-		if (MacType == SK_MAC_GMAC) {
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-							StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
+-							&LowVal);
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-							StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
+-							&HighVal);
+-			LowVal += HighVal;
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-							StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
+-							&HighVal);
+-			LowVal += HighVal;
+-		}
+-		else {
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-										  StatAddr[StatIndex][MacType].Reg,
+-										  &LowVal);
+-		}
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		break;
+-
+-	case SK_PNMI_HTX_OCTET:
+-	case SK_PNMI_HRX_OCTET:
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex][MacType].Reg,
+-									  &HighVal);
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex + 1][MacType].Reg,
+-									  &LowVal);
+-		break;
+-
+-	case SK_PNMI_HTX_BURST:
+-	case SK_PNMI_HTX_EXCESS_DEF:
+-	case SK_PNMI_HTX_CARRIER:
+-		/* Not supported by GMAC */
+-		if (MacType == SK_MAC_GMAC) {
+-			return (Val);
+-		}
+-
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex][MacType].Reg,
+-									  &LowVal);
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		break;
+-
+-	case SK_PNMI_HTX_MACC:
+-		/* GMAC only supports PAUSE MAC control frames */
+-		if (MacType == SK_MAC_GMAC) {
+-			HelpIndex = SK_PNMI_HTX_PMACC;
+-		}
+-		else {
+-			HelpIndex = StatIndex;
+-		}
+-		
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-								StatAddr[HelpIndex][MacType].Reg,
+-								&LowVal);
+-
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		break;
+-
+-	case SK_PNMI_HTX_COL:
+-	case SK_PNMI_HRX_UNDERSIZE:
+-		/* Not supported by XMAC */
+-		if (MacType == SK_MAC_XMAC) {
+-			return (Val);
+-		}
+-
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex][MacType].Reg,
+-									  &LowVal);
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		break;
+-
+-	case SK_PNMI_HTX_DEFFERAL:
+-		/* Not supported by GMAC */
+-		if (MacType == SK_MAC_GMAC) {
+-			return (Val);
+-		}
+-		
+-		/*
+-		 * XMAC counts frames with deferred transmission
+-		 * even in full-duplex mode.
+-		 *
+-		 * In full-duplex mode the counter remains constant!
+-		 */
+-		if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
+-			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
+-
+-			LowVal = 0;
+-			HighVal = 0;
+-		}
+-		else {
+-			/* Otherwise get contents of hardware register */
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-										  StatAddr[StatIndex][MacType].Reg,
+-										  &LowVal);
+-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		}
+-		break;
+-
+-	case SK_PNMI_HRX_BADOCTET:
+-		/* Not supported by XMAC */
+-		if (MacType == SK_MAC_XMAC) {
+-			return (Val);
+-		}
+-
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex][MacType].Reg,
+-									  &HighVal);
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex + 1][MacType].Reg,
+-                                      &LowVal);
+-		break;
+-
+-	case SK_PNMI_HTX_OCTETLOW:
+-	case SK_PNMI_HRX_OCTETLOW:
+-	case SK_PNMI_HRX_BADOCTETLOW:
+-		return (Val);
+-
+-	case SK_PNMI_HRX_LONGFRAMES:
+-		/* For XMAC the SW counter is managed by PNMI */
+-		if (MacType == SK_MAC_XMAC) {
+-			return (pPnmiPrt->StatRxLongFrameCts);
+-		}
+-		
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex][MacType].Reg,
+-									  &LowVal);
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		break;
+-		
+-	case SK_PNMI_HRX_TOO_LONG:
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-								StatAddr[StatIndex][MacType].Reg,
+-								&LowVal);
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		
+-		Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+-
+-		if (MacType == SK_MAC_GMAC) {
+-			/* For GMAC the SW counter is additionally managed by PNMI */
+-			Val += pPnmiPrt->StatRxFrameTooLongCts;
+-		}
+-		else {
+-			/*
+-			 * Frames longer than IEEE 802.3 frame max size are counted
+-			 * by XMAC in frame_too_long counter even reception of long
+-			 * frames was enabled and the frame was correct.
+-			 * So correct the value by subtracting RxLongFrame counter.
+-			 */
+-			Val -= pPnmiPrt->StatRxLongFrameCts;
+-		}
+-
+-		LowVal = (SK_U32)Val;
+-		HighVal = (SK_U32)(Val >> 32);
+-		break;
+-		
+-	case SK_PNMI_HRX_SHORTS:
+-		/* Not supported by GMAC */
+-		if (MacType == SK_MAC_GMAC) {
+-			/* GM_RXE_FRAG?? */
+-			return (Val);
+-		}
+-		
+-		/*
+-		 * XMAC counts short frame errors even if link down (#10620)
+-		 *
+-		 * If link-down the counter remains constant
+-		 */
+-		if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
+-
+-			/* Otherwise get incremental difference */
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-										  StatAddr[StatIndex][MacType].Reg,
+-										  &LowVal);
+-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-
+-			Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+-			Val -= pPnmiPrt->RxShortZeroMark;
+-
+-			LowVal = (SK_U32)Val;
+-			HighVal = (SK_U32)(Val >> 32);
+-		}
+-		break;
+-
+-	case SK_PNMI_HRX_MACC:
+-	case SK_PNMI_HRX_MACC_UNKWN:
+-	case SK_PNMI_HRX_BURST:
+-	case SK_PNMI_HRX_MISSED:
+-	case SK_PNMI_HRX_FRAMING:
+-	case SK_PNMI_HRX_CARRIER:
+-	case SK_PNMI_HRX_IRLENGTH:
+-	case SK_PNMI_HRX_SYMBOL:
+-	case SK_PNMI_HRX_CEXT:
+-		/* Not supported by GMAC */
+-		if (MacType == SK_MAC_GMAC) {
+-			return (Val);
+-		}
+-
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex][MacType].Reg,
+-									  &LowVal);
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		break;
+-
+-	case SK_PNMI_HRX_PMACC_ERR:
+-		/* For GMAC the SW counter is managed by PNMI */
+-		if (MacType == SK_MAC_GMAC) {
+-			return (pPnmiPrt->StatRxPMaccErr);
+-		}
+-		
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex][MacType].Reg,
+-									  &LowVal);
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		break;
+-
+-	/* SW counter managed by PNMI */
+-	case SK_PNMI_HTX_SYNC:
+-		LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
+-		HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
+-		break;
+-
+-	/* SW counter managed by PNMI */
+-	case SK_PNMI_HTX_SYNC_OCTET:
+-		LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
+-		HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
+-		break;
+-
+-	case SK_PNMI_HRX_FCS:
+-		/*
+-		 * Broadcom filters FCS errors and counts it in
+-		 * Receive Error Counter register
+-		 */
+-		if (pPrt->PhyType == SK_PHY_BCOM) {
+-			/* do not read while not initialized (PHY_READ hangs!)*/
+-			if (pPrt->PState != SK_PRT_RESET) {
+-				SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
+-				
+-				LowVal = Word;
+-			}
+-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		}
+-		else {
+-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-										  StatAddr[StatIndex][MacType].Reg,
+-										  &LowVal);
+-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		}
+-		break;
+-
+-	default:
+-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+-									  StatAddr[StatIndex][MacType].Reg,
+-									  &LowVal);
+-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-		break;
+-	}
+-
+-	Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+-
+-	/* Correct value because of possible XMAC reset. XMAC Errata #2 */
+-	Val += pPnmiPrt->CounterOffset[StatIndex];
+-
+-	return (Val);
+-}
+-
+-/*****************************************************************************
+- *
+- * ResetCounter - Set all counters and timestamps to zero
+- *
+- * Description:
+- *	Notifies other common modules which store statistic data to
+- *	reset their counters and finally reset our own counters.
+- *
+- * Returns:
+- *	Nothing
+- */
+-PNMI_STATIC void ResetCounter(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-SK_U32 NetIndex)
+-{
+-	unsigned int	PhysPortIndex;
+-	SK_EVPARA	EventParam;
+-
+-
+-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+-
+-	/* Notify sensor module */
+-	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
+-
+-	/* Notify RLMT module */
+-	EventParam.Para32[0] = NetIndex;
+-	EventParam.Para32[1] = (SK_U32)-1;
+-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
+-	EventParam.Para32[1] = 0;
+-
+-	/* Notify SIRQ module */
+-	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
+-
+-	/* Notify CSUM module */
+-#ifdef SK_USE_CSUM
+-	EventParam.Para32[0] = NetIndex;
+-	EventParam.Para32[1] = (SK_U32)-1;
+-	SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
+-		EventParam);
+-#endif /* SK_USE_CSUM */
+-	
+-	/* Clear XMAC statistic */
+-	for (PhysPortIndex = 0; PhysPortIndex <
+-		(unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
+-
+-		(void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
+-
+-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
+-			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
+-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+-			CounterOffset, 0, sizeof(pAC->Pnmi.Port[
+-			PhysPortIndex].CounterOffset));
+-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
+-			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
+-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+-			StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
+-			PhysPortIndex].StatSyncOctetsCts));
+-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+-			StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
+-			PhysPortIndex].StatRxLongFrameCts));
+-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+-				  StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
+-			PhysPortIndex].StatRxFrameTooLongCts));
+-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+-				  StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
+-			PhysPortIndex].StatRxPMaccErr));
+-	}
+-
+-	/*
+-	 * Clear local statistics
+-	 */
+-	SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
+-		  sizeof(pAC->Pnmi.VirtualCounterOffset));
+-	pAC->Pnmi.RlmtChangeCts = 0;
+-	pAC->Pnmi.RlmtChangeTime = 0;
+-	SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
+-		sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
+-	pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
+-	pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
+-	pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
+-	pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
+-	pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
+-	pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
+-	pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
+-	pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
+-	pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
+-	pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
+-	pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
+-	pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
+-}
+-
+-/*****************************************************************************
+- *
+- * GetTrapEntry - Get an entry in the trap buffer
+- *
+- * Description:
+- *	The trap buffer stores various events. A user application somehow
+- *	gets notified that an event occured and retrieves the trap buffer
+- *	contens (or simply polls the buffer). The buffer is organized as
+- *	a ring which stores the newest traps at the beginning. The oldest
+- *	traps are overwritten by the newest ones. Each trap entry has a
+- *	unique number, so that applications may detect new trap entries.
+- *
+- * Returns:
+- *	A pointer to the trap entry
+- */
+-PNMI_STATIC char* GetTrapEntry(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_U32 TrapId,		/* SNMP ID of the trap */
+-unsigned int Size)	/* Space needed for trap entry */
+-{
+-	unsigned int		BufPad = pAC->Pnmi.TrapBufPad;
+-	unsigned int		BufFree = pAC->Pnmi.TrapBufFree;
+-	unsigned int		Beg = pAC->Pnmi.TrapQueueBeg;
+-	unsigned int		End = pAC->Pnmi.TrapQueueEnd;
+-	char			*pBuf = &pAC->Pnmi.TrapBuf[0];
+-	int			Wrap;
+-	unsigned int		NeededSpace;
+-	unsigned int		EntrySize;
+-	SK_U32			Val32;
+-	SK_U64			Val64;
+-
+-
+-	/* Last byte of entry will get a copy of the entry length */
+-	Size ++;
+-
+-	/*
+-	 * Calculate needed buffer space */
+-	if (Beg >= Size) {
+-
+-		NeededSpace = Size;
+-		Wrap = SK_FALSE;
+-	}
+-	else {
+-		NeededSpace = Beg + Size;
+-		Wrap = SK_TRUE;
+-	}
+-
+-	/*
+-	 * Check if enough buffer space is provided. Otherwise
+-	 * free some entries. Leave one byte space between begin
+-	 * and end of buffer to make it possible to detect whether
+-	 * the buffer is full or empty
+-	 */
+-	while (BufFree < NeededSpace + 1) {
+-
+-		if (End == 0) {
+-
+-			End = SK_PNMI_TRAP_QUEUE_LEN;
+-		}
+-
+-		EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
+-		BufFree += EntrySize;
+-		End -= EntrySize;
+-#ifdef DEBUG
+-		SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
+-#endif /* DEBUG */
+-		if (End == BufPad) {
+-#ifdef DEBUG
+-			SK_MEMSET(pBuf, (char)(-1), End);
+-#endif /* DEBUG */
+-			BufFree += End;
+-			End = 0;
+-			BufPad = 0;
+-		}
+-	}
+-
+-	/*
+-	 * Insert new entry as first entry. Newest entries are
+-	 * stored at the beginning of the queue.
+-	 */
+-	if (Wrap) {
+-
+-		BufPad = Beg;
+-		Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
+-	}
+-	else {
+-		Beg = Beg - Size;
+-	}
+-	BufFree -= NeededSpace;
+-
+-	/* Save the current offsets */
+-	pAC->Pnmi.TrapQueueBeg = Beg;
+-	pAC->Pnmi.TrapQueueEnd = End;
+-	pAC->Pnmi.TrapBufPad = BufPad;
+-	pAC->Pnmi.TrapBufFree = BufFree;
+-
+-	/* Initialize the trap entry */
+-	*(pBuf + Beg + Size - 1) = (char)Size;
+-	*(pBuf + Beg) = (char)Size;
+-	Val32 = (pAC->Pnmi.TrapUnique) ++;
+-	SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
+-	SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
+-	Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+-	SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
+-
+-	return (pBuf + Beg);
+-}
+-
+-/*****************************************************************************
+- *
+- * CopyTrapQueue - Copies the trap buffer for the TRAP OID
+- *
+- * Description:
+- *	On a query of the TRAP OID the trap buffer contents will be
+- *	copied continuously to the request buffer, which must be large
+- *	enough. No length check is performed.
+- *
+- * Returns:
+- *	Nothing
+- */
+-PNMI_STATIC void CopyTrapQueue(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-char *pDstBuf)		/* Buffer to which the queued traps will be copied */
+-{
+-	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
+-	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
+-	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
+-	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
+-	unsigned int	Len;
+-	unsigned int	DstOff = 0;
+-
+-
+-	while (Trap != End) {
+-
+-		Len = (unsigned int)*(pBuf + Trap);
+-
+-		/*
+-		 * Last byte containing a copy of the length will
+-		 * not be copied.
+-		 */
+-		*(pDstBuf + DstOff) = (char)(Len - 1);
+-		SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
+-		DstOff += Len - 1;
+-
+-		Trap += Len;
+-		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
+-
+-			Trap = BufPad;
+-		}
+-	}
+-}
+-
+-/*****************************************************************************
+- *
+- * GetTrapQueueLen - Get the length of the trap buffer
+- *
+- * Description:
+- *	Evaluates the number of currently stored traps and the needed
+- *	buffer size to retrieve them.
+- *
+- * Returns:
+- *	Nothing
+- */
+-PNMI_STATIC void GetTrapQueueLen(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-unsigned int *pLen,	/* Length in Bytes of all queued traps */
+-unsigned int *pEntries)	/* Returns number of trapes stored in queue */
+-{
+-	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
+-	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
+-	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
+-	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
+-	unsigned int	Len;
+-	unsigned int	Entries = 0;
+-	unsigned int	TotalLen = 0;
+-
+-
+-	while (Trap != End) {
+-
+-		Len = (unsigned int)*(pBuf + Trap);
+-		TotalLen += Len - 1;
+-		Entries ++;
+-
+-		Trap += Len;
+-		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
+-
+-			Trap = BufPad;
+-		}
+-	}
+-
+-	*pEntries = Entries;
+-	*pLen = TotalLen;
+-}
+-
+-/*****************************************************************************
+- *
+- * QueueSimpleTrap - Store a simple trap to the trap buffer
+- *
+- * Description:
+- *	A simple trap is a trap with now additional data. It consists
+- *	simply of a trap code.
+- *
+- * Returns:
+- *	Nothing
+- */
+-PNMI_STATIC void QueueSimpleTrap(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_U32 TrapId)		/* Type of sensor trap */
+-{
+-	GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
+-}
+-
+-/*****************************************************************************
+- *
+- * QueueSensorTrap - Stores a sensor trap in the trap buffer
+- *
+- * Description:
+- *	Gets an entry in the trap buffer and fills it with sensor related
+- *	data.
+- *
+- * Returns:
+- *	Nothing
+- */
+-PNMI_STATIC void QueueSensorTrap(
+-SK_AC *pAC,			/* Pointer to adapter context */
+-SK_U32 TrapId,			/* Type of sensor trap */
+-unsigned int SensorIndex)	/* Index of sensor which caused the trap */
+-{
+-	char		*pBuf;
+-	unsigned int	Offset;
+-	unsigned int	DescrLen;
+-	SK_U32		Val32;
+-
+-
+-	/* Get trap buffer entry */
+-	DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
+-	pBuf = GetTrapEntry(pAC, TrapId,
+-		SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
+-	Offset = SK_PNMI_TRAP_SIMPLE_LEN;
+-
+-	/* Store additionally sensor trap related data */
+-	Val32 = OID_SKGE_SENSOR_INDEX;
+-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-	*(pBuf + Offset + 4) = 4;
+-	Val32 = (SK_U32)SensorIndex;
+-	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
+-	Offset += 9;
+-	
+-	Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
+-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-	*(pBuf + Offset + 4) = (char)DescrLen;
+-	SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
+-		DescrLen);
+-	Offset += DescrLen + 5;
+-
+-	Val32 = OID_SKGE_SENSOR_TYPE;
+-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-	*(pBuf + Offset + 4) = 1;
+-	*(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
+-	Offset += 6;
+-
+-	Val32 = OID_SKGE_SENSOR_VALUE;
+-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+-	*(pBuf + Offset + 4) = 4;
+-	Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
+-	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
+-}
+-
+-/*****************************************************************************
+- *
+- * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
+- *
+- * Description:
+- *	Nothing further to explain.
+- *
+- * Returns:
+- *	Nothing
+- */
+-PNMI_STATIC void QueueRlmtNewMacTrap(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-unsigned int ActiveMac)	/* Index (0..n) of the currently active port */
+-{
+-	char	*pBuf;
+-	SK_U32	Val32;
+-
+-
+-	pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
+-		SK_PNMI_TRAP_RLMT_CHANGE_LEN);
+-
+-	Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
+-	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
+-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
+-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
+-}
+-
+-/*****************************************************************************
+- *
+- * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
+- *
+- * Description:
+- *	Nothing further to explain.
+- *
+- * Returns:
+- *	Nothing
+- */
+-PNMI_STATIC void QueueRlmtPortTrap(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_U32 TrapId,		/* Type of RLMT port trap */
+-unsigned int PortIndex)	/* Index of the port, which changed its state */
+-{
+-	char	*pBuf;
+-	SK_U32	Val32;
+-
+-
+-	pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
+-
+-	Val32 = OID_SKGE_RLMT_PORT_INDEX;
+-	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
+-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
+-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
+-}
+-
+-/*****************************************************************************
+- *
+- * CopyMac - Copies a MAC address
+- *
+- * Description:
+- *	Nothing further to explain.
+- *
+- * Returns:
+- *	Nothing
+- */
+-PNMI_STATIC void CopyMac(
+-char *pDst,		/* Pointer to destination buffer */
+-SK_MAC_ADDR *pMac)	/* Pointer of Source */
+-{
+-	int	i;
+-
+-
+-	for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
+-
+-		*(pDst + i) = pMac->a[i];
+-	}
+-}
+-
+-#ifdef SK_POWER_MGMT
+-/*****************************************************************************
+- *
+- * PowerManagement - OID handler function of PowerManagement OIDs
+- *
+- * Description:
+- *	The code is simple. No description necessary.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                               exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-
+-PNMI_STATIC int PowerManagement(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* Get/PreSet/Set action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
+-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
+-{
+-	
+-	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
+-
+-	/*
+-	 * Check instance. We only handle single instance variables
+-	 */
+-	if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_UNKNOWN_INST);
+-	}
+-	
+-    
+-    /* Check length */
+-    switch (Id) {
+-
+-    case OID_PNP_CAPABILITIES:
+-        if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
+-
+-            *pLen = sizeof(SK_PNP_CAPABILITIES);
+-            return (SK_PNMI_ERR_TOO_SHORT);
+-        }
+-        break;
+-
+-	case OID_PNP_SET_POWER:
+-    case OID_PNP_QUERY_POWER:
+-    	if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
+-    	{
+-    		*pLen = sizeof(SK_DEVICE_POWER_STATE);
+-    		return (SK_PNMI_ERR_TOO_SHORT);
+-    	}
+-        break;
+-
+-    case OID_PNP_ADD_WAKE_UP_PATTERN:
+-    case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+-		if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
+-
+-			*pLen = sizeof(SK_PM_PACKET_PATTERN);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-    case OID_PNP_ENABLE_WAKE_UP:
+-        if (*pLen < sizeof(SK_U32)) {
+-
+-            *pLen = sizeof(SK_U32);
+-            return (SK_PNMI_ERR_TOO_SHORT);
+-        }
+-        break;
+-    }
+-	
+-    /*
+-	 * Perform action
+-	 */
+-	if (Action == SK_PNMI_GET) {
+-
+-		/*
+-		 * Get value
+-		 */
+-		switch (Id) {
+-
+-		case OID_PNP_CAPABILITIES:
+-			RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
+-			break;
+-
+-		case OID_PNP_QUERY_POWER:
+-			/* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
+-			 the miniport to indicate whether it can transition its NIC
+-			 to the low-power state.
+-			 A miniport driver must always return NDIS_STATUS_SUCCESS
+-			 to a query of OID_PNP_QUERY_POWER. */
+-			*pLen = sizeof(SK_DEVICE_POWER_STATE);
+-            RetCode = SK_PNMI_ERR_OK;
+-			break;
+-
+-			/* NDIS handles these OIDs as write-only.
+-			 * So in case of get action the buffer with written length = 0
+-			 * is returned
+-			 */
+-		case OID_PNP_SET_POWER:
+-		case OID_PNP_ADD_WAKE_UP_PATTERN:
+-		case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+-			*pLen = 0;	
+-            RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
+-			break;
+-
+-		case OID_PNP_ENABLE_WAKE_UP:
+-			RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
+-			break;
+-
+-		default:
+-			RetCode = SK_PNMI_ERR_GENERAL;
+-			break;
+-		}
+-
+-		return (RetCode);
+-	}
+-	
+-
+-	/*
+-	 * Perform preset or set
+-	 */
+-	
+-	/* POWER module does not support PRESET action */
+-	if (Action == SK_PNMI_PRESET) {
+-		return (SK_PNMI_ERR_OK);
+-	}
+-
+-	switch (Id) {
+-	case OID_PNP_SET_POWER:
+-		RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);	
+-		break;
+-
+-	case OID_PNP_ADD_WAKE_UP_PATTERN:
+-		RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);	
+-		break;
+-		
+-	case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+-		RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);	
+-		break;
+-		
+-	case OID_PNP_ENABLE_WAKE_UP:
+-		RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
+-		break;
+-		
+-	default:
+-		RetCode = SK_PNMI_ERR_READ_ONLY;
+-	}
+-	
+-	return (RetCode);
+-}
+-#endif /* SK_POWER_MGMT */
+-
+-#ifdef SK_DIAG_SUPPORT
+-/*****************************************************************************
+- *
+- * DiagActions - OID handler function of Diagnostic driver 
+- *
+- * Description:
+- *	The code is simple. No description necessary.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-
+-PNMI_STATIC int DiagActions(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-
+-	SK_U32	DiagStatus;
+-	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
+-
+-	/*
+-	 * Check instance. We only handle single instance variables.
+-	 */
+-	if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_UNKNOWN_INST);
+-	}
+-
+-	/*
+-	 * Check length.
+-	 */
+-	switch (Id) {
+-
+-	case OID_SKGE_DIAG_MODE:
+-		if (*pLen < sizeof(SK_U32)) {
+-
+-			*pLen = sizeof(SK_U32);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-
+-	/* Perform action. */
+-
+-	/* GET value. */
+-	if (Action == SK_PNMI_GET) {
+-
+-		switch (Id) {
+-
+-		case OID_SKGE_DIAG_MODE:
+-			DiagStatus = pAC->Pnmi.DiagAttached;
+-			SK_PNMI_STORE_U32(pBuf, DiagStatus);
+-			*pLen = sizeof(SK_U32);	
+-			RetCode = SK_PNMI_ERR_OK;
+-			break;
+-
+-		default:
+-			*pLen = 0;	
+-			RetCode = SK_PNMI_ERR_GENERAL;
+-			break;
+-		}
+-		return (RetCode); 
+-	}
+-
+-	/* From here SET or PRESET value. */
+-	
+-	/* PRESET value is not supported. */
+-	if (Action == SK_PNMI_PRESET) {
+-		return (SK_PNMI_ERR_OK); 
+-	}
+-
+-	/* SET value. */
+-	switch (Id) {
+-		case OID_SKGE_DIAG_MODE:
+-
+-			/* Handle the SET. */
+-			switch (*pBuf) {
+-
+-				/* Attach the DIAG to this adapter. */
+-				case SK_DIAG_ATTACHED:
+-					/* Check if we come from running */
+-					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+-
+-						RetCode = SkDrvLeaveDiagMode(pAC);
+-
+-					}
+-					else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
+-
+-						RetCode = SK_PNMI_ERR_OK;
+-					}	
+-					
+-					else {
+-
+-						RetCode = SK_PNMI_ERR_GENERAL;
+-
+-					}
+-					
+-					if (RetCode == SK_PNMI_ERR_OK) {
+-
+-						pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
+-					}
+-					break;
+-
+-				/* Enter the DIAG mode in the driver. */
+-				case SK_DIAG_RUNNING:
+-					RetCode = SK_PNMI_ERR_OK;
+-					
+-					/*
+-					 * If DiagAttached is set, we can tell the driver
+-					 * to enter the DIAG mode.
+-					 */
+-					if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
+-						/* If DiagMode is not active, we can enter it. */
+-						if (!pAC->DiagModeActive) {
+-
+-							RetCode = SkDrvEnterDiagMode(pAC); 
+-						}
+-						else {
+-
+-							RetCode = SK_PNMI_ERR_GENERAL;
+-						}
+-					}
+-					else {
+-
+-						RetCode = SK_PNMI_ERR_GENERAL;
+-					}
+-					
+-					if (RetCode == SK_PNMI_ERR_OK) {
+-
+-						pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
+-					}
+-					break;
+-
+-				case SK_DIAG_IDLE:
+-					/* Check if we come from running */
+-					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+-
+-						RetCode = SkDrvLeaveDiagMode(pAC);
+-
+-					}
+-					else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
+-
+-						RetCode = SK_PNMI_ERR_OK;
+-					}	
+-					
+-					else {
+-
+-						RetCode = SK_PNMI_ERR_GENERAL;
+-
+-					}
+-
+-					if (RetCode == SK_PNMI_ERR_OK) {
+-
+-						pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
+-					}
+-					break;
+-
+-				default:
+-					RetCode = SK_PNMI_ERR_BAD_VALUE;
+-					break;
+-			}
+-			break;
+-
+-		default:
+-			RetCode = SK_PNMI_ERR_GENERAL;
+-	}
+-
+-	if (RetCode == SK_PNMI_ERR_OK) {
+-		*pLen = sizeof(SK_U32);
+-	}
+-	else {
+-
+-		*pLen = 0;
+-	}
+-	return (RetCode);
+-}
+-#endif /* SK_DIAG_SUPPORT */
+-
+-/*****************************************************************************
+- *
+- * Vct - OID handler function of  OIDs
+- *
+- * Description:
+- *	The code is simple. No description necessary.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was performed successfully.
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
+- *	                         the correct data (e.g. a 32bit value is
+- *	                         needed, but a 16 bit value was passed).
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter).
+- *	SK_PNMI_ERR_READ_ONLY	 Only the Get action is allowed.
+- *
+- */
+-
+-PNMI_STATIC int Vct(
+-SK_AC *pAC,		/* Pointer to adapter context */
+-SK_IOC IoC,		/* IO context handle */
+-int Action,		/* GET/PRESET/SET action */
+-SK_U32 Id,		/* Object ID that is to be processed */
+-char *pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance,	/* Instance (-1,2..n) that is to be queried */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_PNMI_VCT	*pVctBackupData;
+-	SK_U32		LogPortMax;
+-	SK_U32		PhysPortMax;
+-	SK_U32		PhysPortIndex;
+-	SK_U32		Limit;
+-	SK_U32		Offset;
+-	SK_BOOL		Link;
+-	SK_U32		RetCode = SK_PNMI_ERR_GENERAL;
+-	int		i;
+-	SK_EVPARA	Para;
+-	SK_U32		CableLength;
+-	
+-	/*
+-	 * Calculate the port indexes from the instance.
+-	 */
+-	PhysPortMax = pAC->GIni.GIMacsFound;
+-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+-	
+-	/* Dual net mode? */
+-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-		LogPortMax--;
+-	}
+-	
+-	if ((Instance != (SK_U32) (-1))) {
+-		/* Check instance range. */
+-		if ((Instance < 2) || (Instance > LogPortMax)) {
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_UNKNOWN_INST);
+-		}
+-		
+-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+-			PhysPortIndex = NetIndex;
+-		}
+-		else {
+-			PhysPortIndex = Instance - 2;
+-		}
+-		Limit = PhysPortIndex + 1;
+-	}
+-	else {
+-		/*
+-		 * Instance == (SK_U32) (-1), get all Instances of that OID.
+-		 *
+-		 * Not implemented yet. May be used in future releases.
+-		 */
+-		PhysPortIndex = 0;
+-		Limit = PhysPortMax;
+-	}
+-	
+-	pPrt = &pAC->GIni.GP[PhysPortIndex];
+-	if (pPrt->PHWLinkUp) {
+-		Link = SK_TRUE;
+-	}
+-	else {
+-		Link = SK_FALSE;
+-	}
+-	
+-	/* Check MAC type */
+-	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-	
+-	/* Initialize backup data pointer. */
+-	pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
+-	
+-	/* Check action type */
+-	if (Action == SK_PNMI_GET) {
+-		/* Check length */
+-		switch (Id) {
+-		
+-		case OID_SKGE_VCT_GET:
+-			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
+-				*pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			break;
+-		
+-		case OID_SKGE_VCT_STATUS:
+-			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
+-				*pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
+-				return (SK_PNMI_ERR_TOO_SHORT);
+-			}
+-			break;
+-		
+-		default:
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}	
+-		
+-		/* Get value */
+-		Offset = 0;
+-		for (; PhysPortIndex < Limit; PhysPortIndex++) {
+-			switch (Id) {
+-			
+-			case OID_SKGE_VCT_GET:
+-				if ((Link == SK_FALSE) &&
+-					(pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
+-					RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
+-					if (RetCode == 0) {
+-						pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
+-						pAC->Pnmi.VctStatus[PhysPortIndex] |=
+-							(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
+-						
+-						/* Copy results for later use to PNMI struct. */
+-						for (i = 0; i < 4; i++)  {
+-							if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
+-								if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
+-									pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
+-								}
+-							}
+-							if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
+-								CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
+-							}
+-							else {
+-								CableLength = 0;
+-							}
+-							pVctBackupData->PMdiPairLen[i] = CableLength;
+-							pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
+-						}
+-
+-						Para.Para32[0] = PhysPortIndex;
+-						Para.Para32[1] = -1;
+-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+-						SkEventDispatcher(pAC, IoC);
+-					}
+-					else {
+-						; /* VCT test is running. */
+-					}
+-				}
+-				
+-				/* Get all results. */
+-				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
+-				Offset += sizeof(SK_U8);
+-				*(pBuf + Offset) = pPrt->PCableLen;
+-				Offset += sizeof(SK_U8);
+-				for (i = 0; i < 4; i++)  {
+-					SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
+-					Offset += sizeof(SK_U32);
+-				}
+-				for (i = 0; i < 4; i++)  {
+-					*(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
+-					Offset += sizeof(SK_U8);
+-				}
+-				
+-				RetCode = SK_PNMI_ERR_OK;
+-				break;
+-		
+-			case OID_SKGE_VCT_STATUS:
+-				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
+-				Offset += sizeof(SK_U8);
+-				RetCode = SK_PNMI_ERR_OK;
+-				break;
+-			
+-			default:
+-				*pLen = 0;
+-				return (SK_PNMI_ERR_GENERAL);
+-			}
+-		} /* for */
+-		*pLen = Offset;
+-		return (RetCode);
+-	
+-	} /* if SK_PNMI_GET */
+-	
+-	/*
+-	 * From here SET or PRESET action. Check if the passed
+-	 * buffer length is plausible.
+-	 */
+-	
+-	/* Check length */
+-	switch (Id) {
+-	case OID_SKGE_VCT_SET:
+-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
+-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
+-			return (SK_PNMI_ERR_TOO_SHORT);
+-		}
+-		break;
+-	
+-	default:
+-		*pLen = 0;
+-		return (SK_PNMI_ERR_GENERAL);
+-	}
+-	
+-	/*
+-	 * Perform preset or set.
+-	 */
+-	
+-	/* VCT does not support PRESET action. */
+-	if (Action == SK_PNMI_PRESET) {
+-		return (SK_PNMI_ERR_OK);
+-	}
+-	
+-	Offset = 0;
+-	for (; PhysPortIndex < Limit; PhysPortIndex++) {
+-		switch (Id) {
+-		case OID_SKGE_VCT_SET: /* Start VCT test. */
+-			if (Link == SK_FALSE) {
+-				SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
+-				
+-				RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
+-				if (RetCode == 0) { /* RetCode: 0 => Start! */
+-					pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
+-					pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
+-					pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
+-					
+-					/*
+-					 * Start VCT timer counter.
+-					 */
+-					SK_MEMSET((char *) &Para, 0, sizeof(Para));
+-					Para.Para32[0] = PhysPortIndex;
+-					Para.Para32[1] = -1;
+-					SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
+-						4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
+-					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+-					RetCode = SK_PNMI_ERR_OK;
+-				}
+-				else { /* RetCode: 2 => Running! */
+-					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+-					RetCode = SK_PNMI_ERR_OK;
+-				}
+-			}
+-			else { /* RetCode: 4 => Link! */
+-				RetCode = 4;
+-				SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+-				RetCode = SK_PNMI_ERR_OK;
+-			}
+-			Offset += sizeof(SK_U32);
+-			break;
+-	
+-		default:
+-			*pLen = 0;
+-			return (SK_PNMI_ERR_GENERAL);
+-		}
+-	} /* for */
+-	*pLen = Offset;
+-	return (RetCode);
+-
+-} /* Vct */
+-
+-
+-PNMI_STATIC void CheckVctStatus(
+-SK_AC		*pAC,
+-SK_IOC		IoC,
+-char		*pBuf,
+-SK_U32		Offset,
+-SK_U32		PhysPortIndex)
+-{
+-	SK_GEPORT 	*pPrt;
+-	SK_PNMI_VCT	*pVctData;
+-	SK_U32		RetCode;
+-	
+-	pPrt = &pAC->GIni.GP[PhysPortIndex];
+-	
+-	pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
+-	pVctData->VctStatus = SK_PNMI_VCT_NONE;
+-	
+-	if (!pPrt->PHWLinkUp) {
+-		
+-		/* Was a VCT test ever made before? */
+-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
+-			if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
+-				pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
+-			}
+-			else {
+-				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
+-			}
+-		}
+-		
+-		/* Check VCT test status. */
+-		RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
+-		if (RetCode == 2) { /* VCT test is running. */
+-			pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
+-		}
+-		else { /* VCT data was copied to pAC here. Check PENDING state. */
+-			if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
+-				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
+-			}
+-		}
+-		
+-		if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
+-			pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
+-		}
+-	}
+-	else {
+-		
+-		/* Was a VCT test ever made before? */
+-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
+-			pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
+-			pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
+-		}
+-		
+-		/* DSP only valid in 100/1000 modes. */
+-		if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
+-			SK_LSPEED_STAT_10MBPS) {	
+-			pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
+-		}
+-	}
+-} /* CheckVctStatus */
+-
+-
+-/*****************************************************************************
+- *
+- *      SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
+- *                       PNMI function depending on the subcommand and
+- *                       returns all data belonging to the complete database
+- *                       or OID request.
+- *
+- * Description:
+- *	Looks up the requested subcommand, calls the corresponding handler
+- *	function and passes all required parameters to it.
+- *	The function is called by the driver. It is needed to handle the new
+- *  generic PNMI IOCTL. This IOCTL is given to the driver and contains both
+- *  the OID and a subcommand to decide what kind of request has to be done.
+- *
+- * Returns:
+- *	SK_PNMI_ERR_OK           The request was successfully performed
+- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
+- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
+- *	                         the data.
+- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
+- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- *                           exist (e.g. port instance 3 on a two port
+- *	                         adapter.
+- */
+-int SkPnmiGenIoctl(
+-SK_AC		*pAC,		/* Pointer to adapter context struct */
+-SK_IOC		IoC,		/* I/O context */
+-void		*pBuf,		/* Buffer used for the management data transfer */
+-unsigned int *pLen,		/* Length of buffer */
+-SK_U32		NetIndex)	/* NetIndex (0..n), in single net mode always zero */
+-{
+-SK_I32	Mode;			/* Store value of subcommand. */
+-SK_U32	Oid;			/* Store value of OID. */
+-int		ReturnCode;		/* Store return value to show status of PNMI action. */
+-int 	HeaderLength;	/* Length of desired action plus OID. */
+-
+-	ReturnCode = SK_PNMI_ERR_GENERAL;
+-	
+-	SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
+-	SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
+-	HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
+-	*pLen = *pLen - HeaderLength;
+-	SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
+-	
+-	switch(Mode) {
+-	case SK_GET_SINGLE_VAR:
+-		ReturnCode = SkPnmiGetVar(pAC, IoC, Oid, 
+-				(char *) pBuf + sizeof(SK_I32), pLen,
+-				((SK_U32) (-1)), NetIndex);
+-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
+-		*pLen = *pLen + sizeof(SK_I32);
+-		break;
+-	case SK_PRESET_SINGLE_VAR:
+-		ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid, 
+-				(char *) pBuf + sizeof(SK_I32), pLen,
+-				((SK_U32) (-1)), NetIndex);
+-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
+-		*pLen = *pLen + sizeof(SK_I32);
+-		break;
+-	case SK_SET_SINGLE_VAR:
+-		ReturnCode = SkPnmiSetVar(pAC, IoC, Oid, 
+-				(char *) pBuf + sizeof(SK_I32), pLen,
+-				((SK_U32) (-1)), NetIndex);
+-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
+-		*pLen = *pLen + sizeof(SK_I32);
+-		break;
+-	case SK_GET_FULL_MIB:
+-		ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
+-		break;
+-	case SK_PRESET_FULL_MIB:
+-		ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
+-		break;
+-	case SK_SET_FULL_MIB:
+-		ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
+-		break;
+-	default:
+-		break;
+-	}
+-	
+-	return (ReturnCode);
+-
+-} /* SkGeIocGen */
+diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c
+deleted file mode 100644
+index e5ee6d6..0000000
+--- a/drivers/net/sk98lin/skgesirq.c
++++ /dev/null
+@@ -1,2229 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skgesirq.c
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.92 $
+- * Date:	$Date: 2003/09/16 14:37:07 $
+- * Purpose:	Special IRQ module
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- *	Special Interrupt handler
+- *
+- *	The following abstract should show how this module is included
+- *	in the driver path:
+- *
+- *	In the ISR of the driver the bits for frame transmission complete and
+- *	for receive complete are checked and handled by the driver itself.
+- *	The bits of the slow path mask are checked after that and then the
+- *	entry into the so-called "slow path" is prepared. It is an implementors
+- *	decision whether this is executed directly or just scheduled by
+- *	disabling the mask. In the interrupt service routine some events may be
+- *	generated, so it would be a good idea to call the EventDispatcher
+- *	right after this ISR.
+- *
+- *	The Interrupt source register of the adapter is NOT read by this module.
+- *  SO if the drivers implementor needs a while loop around the
+- *	slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
+- *	each loop entered.
+- *
+- *	However, the MAC Interrupt status registers are read in a while loop.
+- *
+- */
+-
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+-#ifndef SK_SLIM
+-#include "h/skgepnmi.h"		/* PNMI Definitions */
+-#include "h/skrlmt.h"		/* RLMT Definitions */
+-#endif
+-#include "h/skdrv2nd.h"		/* Adapter Control and Driver specific Def. */
+-
+-/* local function prototypes */
+-#ifdef GENESIS
+-static int	SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
+-static int	SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void	SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
+-#endif /* GENESIS */
+-#ifdef YUKON
+-static int	SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void	SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
+-#endif /* YUKON */
+-#ifdef OTHER_PHY
+-static int	SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
+-static int	SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void	SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
+-#endif /* OTHER_PHY */
+-
+-#ifdef GENESIS
+-/*
+- * array of Rx counter from XMAC which are checked
+- * in AutoSense mode to check whether a link is not able to auto-negotiate.
+- */
+-static const SK_U16 SkGeRxRegs[]= {
+-	XM_RXF_64B,
+-	XM_RXF_127B,
+-	XM_RXF_255B,
+-	XM_RXF_511B,
+-	XM_RXF_1023B,
+-	XM_RXF_MAX_SZ
+-} ;
+-#endif /* GENESIS */
+-
+-#ifdef __C2MAN__
+-/*
+- *	Special IRQ function
+- *
+- *	General Description:
+- *
+- */
+-intro()
+-{}
+-#endif
+-
+-/******************************************************************************
+- *
+- *	SkHWInitDefSense() - Default Autosensing mode initialization
+- *
+- * Description: sets the PLinkMode for HWInit
+- *
+- * Returns: N/A
+- */
+-static void SkHWInitDefSense(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	pPrt->PAutoNegTimeOut = 0;
+-
+-	if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
+-		pPrt->PLinkMode = pPrt->PLinkModeConf;
+-		return;
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-		("AutoSensing: First mode %d on Port %d\n",
+-		(int)SK_LMODE_AUTOFULL, Port));
+-
+-	pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
+-
+-	return;
+-}	/* SkHWInitDefSense */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkHWSenseGetNext() - Get Next Autosensing Mode
+- *
+- * Description: gets the appropriate next mode
+- *
+- * Note:
+- *
+- */
+-static SK_U8 SkHWSenseGetNext(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	pPrt->PAutoNegTimeOut = 0;
+-
+-    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+-		/* Leave all as configured */
+-		return(pPrt->PLinkModeConf);
+-	}
+-
+-    if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
+-		/* Return next mode AUTOBOTH */
+-        return ((SK_U8)SK_LMODE_AUTOBOTH);
+-	}
+-
+-	/* Return default autofull */
+-    return ((SK_U8)SK_LMODE_AUTOFULL);
+-}	/* SkHWSenseGetNext */
+-
+-
+-/******************************************************************************
+- *
+- *	SkHWSenseSetNext() - Autosensing Set next mode
+- *
+- * Description:	sets the appropriate next mode
+- *
+- * Returns: N/A
+- */
+-static void SkHWSenseSetNext(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_U8	NewMode)	/* New Mode to be written in sense mode */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	pPrt->PAutoNegTimeOut = 0;
+-
+-    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+-		return;
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-		("AutoSensing: next mode %d on Port %d\n",
+-		(int)NewMode, Port));
+-
+-	pPrt->PLinkMode = NewMode;
+-
+-	return;
+-}	/* SkHWSenseSetNext */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- *	SkHWLinkDown() - Link Down handling
+- *
+- * Description: handles the hardware link down signal
+- *
+- * Returns: N/A
+- */
+-void SkHWLinkDown(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* Disable all MAC interrupts */
+-	SkMacIrqDisable(pAC, IoC, Port);
+-
+-	/* Disable Receiver and Transmitter */
+-	SkMacRxTxDisable(pAC, IoC, Port);
+-	
+-	/* Init default sense mode */
+-	SkHWInitDefSense(pAC, IoC, Port);
+-
+-	if (pPrt->PHWLinkUp == SK_FALSE) {
+-		return;
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-		("Link down Port %d\n", Port));
+-
+-	/* Set Link to DOWN */
+-	pPrt->PHWLinkUp = SK_FALSE;
+-
+-	/* Reset Port stati */
+-    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+-    pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
+-
+-	/* Re-init Phy especially when the AutoSense default is set now */
+-	SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
+-
+-	/* GP0: used for workaround of Rev. C Errata 2 */
+-
+-	/* Do NOT signal to RLMT */
+-
+-	/* Do NOT start the timer here */
+-}	/* SkHWLinkDown */
+-
+-
+-/******************************************************************************
+- *
+- *	SkHWLinkUp() - Link Up handling
+- *
+- * Description: handles the hardware link up signal
+- *
+- * Returns: N/A
+- */
+-static void SkHWLinkUp(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PHWLinkUp) {
+-		/* We do NOT need to proceed on active link */
+-		return;
+-	}
+-
+-	pPrt->PHWLinkUp = SK_TRUE;
+-	pPrt->PAutoNegFail = SK_FALSE;
+-    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+-
+-    if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
+-        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
+-        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
+-		/* Link is up and no Auto-negotiation should be done */
+-
+-		/* Link speed should be the configured one */
+-		switch (pPrt->PLinkSpeed) {
+-		case SK_LSPEED_AUTO:
+-			/* default is 1000 Mbps */
+-		case SK_LSPEED_1000MBPS:
+-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+-			break;
+-		case SK_LSPEED_100MBPS:
+-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
+-			break;
+-		case SK_LSPEED_10MBPS:
+-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
+-			break;
+-		}
+-
+-		/* Set Link Mode Status */
+-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+-			pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
+-		}
+-		else {
+-            pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
+-		}
+-
+-		/* No flow control without auto-negotiation */
+-        pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+-
+-		/* enable Rx/Tx */
+-        (void)SkMacRxTxEnable(pAC, IoC, Port);
+-	}
+-}	/* SkHWLinkUp */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacParity() - MAC parity workaround
+- *
+- * Description: handles MAC parity errors correctly
+- *
+- * Returns: N/A
+- */
+-static void SkMacParity(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index of the port failed */
+-{
+-	SK_EVPARA	Para;
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	SK_U32		TxMax;		/* Tx Max Size Counter */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* Clear IRQ Tx Parity Error */
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-
+-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		/* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
+-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
+-			(SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
+-			pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
+-	}
+-#endif /* YUKON */
+-	
+-	if (pPrt->PCheckPar) {
+-
+-		if (Port == MAC_1) {
+-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
+-		}
+-		else {
+-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
+-		}
+-		Para.Para64 = Port;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-		
+-		Para.Para32[0] = Port;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-
+-		return;
+-	}
+-
+-	/* Check whether frames with a size of 1k were sent */
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		/* Snap statistic counters */
+-		(void)SkXmUpdateStats(pAC, IoC, Port);
+-		
+-		(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-
+-		(void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
+-	}
+-#endif /* YUKON */
+-	
+-	if (TxMax > 0) {
+-		/* From now on check the parity */
+-		pPrt->PCheckPar = SK_TRUE;
+-	}
+-}	/* SkMacParity */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeHwErr() - Hardware Error service routine
+- *
+- * Description: handles all HW Error interrupts
+- *
+- * Returns: N/A
+- */
+-static void SkGeHwErr(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-SK_U32	HwStatus)	/* Interrupt status word */
+-{
+-	SK_EVPARA	Para;
+-	SK_U16		Word;
+-
+-	if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
+-		/* PCI Errors occured */
+-		if ((HwStatus & IS_IRQ_STAT) != 0) {
+-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
+-		}
+-		else {
+-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
+-		}
+-
+-		/* Reset all bits in the PCI STATUS register */
+-		SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
+-		
+-		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+-        SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+-		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+-
+-		Para.Para64 = 0;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+-	}
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-
+-		if ((HwStatus & IS_NO_STAT_M1) != 0) {
+-			/* Ignore it */
+-			/* This situation is also indicated in the descriptor */
+-			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+-		}
+-
+-		if ((HwStatus & IS_NO_STAT_M2) != 0) {
+-			/* Ignore it */
+-			/* This situation is also indicated in the descriptor */
+-			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+-		}
+-
+-		if ((HwStatus & IS_NO_TIST_M1) != 0) {
+-			/* Ignore it */
+-			/* This situation is also indicated in the descriptor */
+-			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
+-		}
+-
+-		if ((HwStatus & IS_NO_TIST_M2) != 0) {
+-			/* Ignore it */
+-			/* This situation is also indicated in the descriptor */
+-			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
+-		}
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		/* This is necessary only for Rx timing measurements */
+-		if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
+-			/* increment Time Stamp Timer counter (high) */
+-			pAC->GIni.GITimeStampCnt++;
+-
+-			/* Clear Time Stamp Timer IRQ */
+-			SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
+-		}
+-
+-		if ((HwStatus & IS_IRQ_SENSOR) != 0) {
+-			/* no sensors on 32-bit Yukon */
+-			if (pAC->GIni.GIYukon32Bit) {
+-				/* disable HW Error IRQ */
+-				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
+-			}
+-		}
+-	}
+-#endif /* YUKON */
+-
+-	if ((HwStatus & IS_RAM_RD_PAR) != 0) {
+-		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
+-		Para.Para64 = 0;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+-	}
+-
+-	if ((HwStatus & IS_RAM_WR_PAR) != 0) {
+-		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
+-		Para.Para64 = 0;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+-	}
+-
+-	if ((HwStatus & IS_M1_PAR_ERR) != 0) {
+-		SkMacParity(pAC, IoC, MAC_1);
+-	}
+-
+-	if ((HwStatus & IS_M2_PAR_ERR) != 0) {
+-		SkMacParity(pAC, IoC, MAC_2);
+-	}
+-
+-	if ((HwStatus & IS_R1_PAR_ERR) != 0) {
+-		/* Clear IRQ */
+-		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
+-
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
+-		Para.Para64 = MAC_1;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-		
+-		Para.Para32[0] = MAC_1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-
+-	if ((HwStatus & IS_R2_PAR_ERR) != 0) {
+-		/* Clear IRQ */
+-		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
+-
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
+-		Para.Para64 = MAC_2;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-		
+-		Para.Para32[0] = MAC_2;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-}	/* SkGeHwErr */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeSirqIsr() - Special Interrupt Service Routine
+- *
+- * Description: handles all non data transfer specific interrupts (slow path)
+- *
+- * Returns: N/A
+- */
+-void SkGeSirqIsr(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-SK_U32	Istatus)	/* Interrupt status word */
+-{
+-	SK_EVPARA	Para;
+-	SK_U32		RegVal32;	/* Read register value */
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	SK_U16 		PhyInt;
+-	int			i;
+-
+-	if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
+-		/* read the HW Error Interrupt source */
+-		SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+-		
+-		SkGeHwErr(pAC, IoC, RegVal32);
+-	}
+-
+-	/*
+-	 * Packet Timeout interrupts
+-	 */
+-	/* Check whether MACs are correctly initialized */
+-	if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
+-		pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
+-		/* MAC 1 was not initialized but Packet timeout occured */
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
+-			SKERR_SIRQ_E004MSG);
+-	}
+-
+-	if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
+-	    pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
+-		/* MAC 2 was not initialized but Packet timeout occured */
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
+-			SKERR_SIRQ_E005MSG);
+-	}
+-
+-	if ((Istatus & IS_PA_TO_RX1) != 0) {
+-		/* Means network is filling us up */
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
+-			SKERR_SIRQ_E002MSG);
+-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
+-	}
+-
+-	if ((Istatus & IS_PA_TO_RX2) != 0) {
+-		/* Means network is filling us up */
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
+-			SKERR_SIRQ_E003MSG);
+-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
+-	}
+-
+-	if ((Istatus & IS_PA_TO_TX1) != 0) {
+-		
+-		pPrt = &pAC->GIni.GP[0];
+-
+-		/* May be a normal situation in a server with a slow network */
+-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
+-
+-#ifdef GENESIS
+-		if (pAC->GIni.GIGenesis) {
+-			/*
+-			 * workaround: if in half duplex mode, check for Tx hangup.
+-			 * Read number of TX'ed bytes, wait for 10 ms, then compare
+-			 * the number with current value. If nothing changed, we assume
+-			 * that Tx is hanging and do a FIFO flush (see event routine).
+-			 */
+-			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+-				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
+-				!pPrt->HalfDupTimerActive) {
+-				/*
+-				 * many more pack. arb. timeouts may come in between,
+-				 * we ignore those
+-				 */
+-				pPrt->HalfDupTimerActive = SK_TRUE;
+-				/* Snap statistic counters */
+-				(void)SkXmUpdateStats(pAC, IoC, 0);
+-
+-				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
+-
+-				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
+-				
+-				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
+-
+-				pPrt->LastOctets += RegVal32;
+-				
+-				Para.Para32[0] = 0;
+-				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
+-					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
+-			}
+-		}
+-#endif /* GENESIS */
+-	}
+-
+-	if ((Istatus & IS_PA_TO_TX2) != 0) {
+-		
+-		pPrt = &pAC->GIni.GP[1];
+-
+-		/* May be a normal situation in a server with a slow network */
+-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
+-
+-#ifdef GENESIS
+-		if (pAC->GIni.GIGenesis) {
+-			/* workaround: see above */
+-			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+-				 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
+-				!pPrt->HalfDupTimerActive) {
+-				pPrt->HalfDupTimerActive = SK_TRUE;
+-				/* Snap statistic counters */
+-				(void)SkXmUpdateStats(pAC, IoC, 1);
+-
+-				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
+-
+-				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
+-				
+-				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
+-
+-				pPrt->LastOctets += RegVal32;
+-				
+-				Para.Para32[0] = 1;
+-				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
+-					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
+-			}
+-		}
+-#endif /* GENESIS */
+-	}
+-
+-	/* Check interrupts of the particular queues */
+-	if ((Istatus & IS_R1_C) != 0) {
+-		/* Clear IRQ */
+-		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
+-			SKERR_SIRQ_E006MSG);
+-		Para.Para64 = MAC_1;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-		Para.Para32[0] = MAC_1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-
+-	if ((Istatus & IS_R2_C) != 0) {
+-		/* Clear IRQ */
+-		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
+-			SKERR_SIRQ_E007MSG);
+-		Para.Para64 = MAC_2;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-		Para.Para32[0] = MAC_2;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-
+-	if ((Istatus & IS_XS1_C) != 0) {
+-		/* Clear IRQ */
+-		SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
+-			SKERR_SIRQ_E008MSG);
+-		Para.Para64 = MAC_1;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-		Para.Para32[0] = MAC_1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-
+-	if ((Istatus & IS_XA1_C) != 0) {
+-		/* Clear IRQ */
+-		SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
+-			SKERR_SIRQ_E009MSG);
+-		Para.Para64 = MAC_1;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-		Para.Para32[0] = MAC_1;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-
+-	if ((Istatus & IS_XS2_C) != 0) {
+-		/* Clear IRQ */
+-		SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
+-			SKERR_SIRQ_E010MSG);
+-		Para.Para64 = MAC_2;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-		Para.Para32[0] = MAC_2;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-
+-	if ((Istatus & IS_XA2_C) != 0) {
+-		/* Clear IRQ */
+-		SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
+-			SKERR_SIRQ_E011MSG);
+-		Para.Para64 = MAC_2;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-		Para.Para32[0] = MAC_2;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-
+-	/* External reg interrupt */
+-	if ((Istatus & IS_EXT_REG) != 0) {
+-		/* Test IRQs from PHY */
+-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-			
+-			pPrt = &pAC->GIni.GP[i];
+-			
+-			if (pPrt->PState == SK_PRT_RESET) {
+-				continue;
+-			}
+-			
+-#ifdef GENESIS
+-			if (pAC->GIni.GIGenesis) {
+-				
+-				switch (pPrt->PhyType) {
+-				
+-				case SK_PHY_XMAC:
+-					break;
+-				
+-				case SK_PHY_BCOM:
+-					SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
+-	
+-					if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
+-						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-							("Port %d Bcom Int: 0x%04X\n",
+-							i, PhyInt));
+-						SkPhyIsrBcom(pAC, IoC, i, PhyInt);
+-					}
+-					break;
+-#ifdef OTHER_PHY
+-				case SK_PHY_LONE:
+-					SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
+-					
+-					if ((PhyInt & PHY_L_DEF_MSK) != 0) {
+-						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-							("Port %d Lone Int: %x\n",
+-							i, PhyInt));
+-						SkPhyIsrLone(pAC, IoC, i, PhyInt);
+-					}
+-					break;
+-#endif /* OTHER_PHY */
+-				}
+-			}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-			if (pAC->GIni.GIYukon) {
+-				/* Read PHY Interrupt Status */
+-				SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
+-
+-				if ((PhyInt & PHY_M_DEF_MSK) != 0) {
+-					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-						("Port %d Marv Int: 0x%04X\n",
+-						i, PhyInt));
+-					SkPhyIsrGmac(pAC, IoC, i, PhyInt);
+-				}
+-			}
+-#endif /* YUKON */
+-		}
+-	}
+-
+-	/* I2C Ready interrupt */
+-	if ((Istatus & IS_I2C_READY) != 0) {
+-#ifdef SK_SLIM
+-        SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+-#else		
+-		SkI2cIsr(pAC, IoC);
+-#endif		
+-	}
+-
+-	/* SW forced interrupt */
+-	if ((Istatus & IS_IRQ_SW) != 0) {
+-		/* clear the software IRQ */
+-		SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
+-	}
+-
+-	if ((Istatus & IS_LNK_SYNC_M1) != 0) {
+-		/*
+-		 * We do NOT need the Link Sync interrupt, because it shows
+-		 * us only a link going down.
+-		 */
+-		/* clear interrupt */
+-		SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
+-	}
+-
+-	/* Check MAC after link sync counter */
+-	if ((Istatus & IS_MAC1) != 0) {
+-		/* IRQ from MAC 1 */
+-		SkMacIrq(pAC, IoC, MAC_1);
+-	}
+-
+-	if ((Istatus & IS_LNK_SYNC_M2) != 0) {
+-		/*
+-		 * We do NOT need the Link Sync interrupt, because it shows
+-		 * us only a link going down.
+-		 */
+-		/* clear interrupt */
+-		SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
+-	}
+-
+-	/* Check MAC after link sync counter */
+-	if ((Istatus & IS_MAC2) != 0) {
+-		/* IRQ from MAC 2 */
+-		SkMacIrq(pAC, IoC, MAC_2);
+-	}
+-
+-	/* Timer interrupt (served last) */
+-	if ((Istatus & IS_TIMINT) != 0) {
+-		/* check for HW Errors */
+-		if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
+-			/* read the HW Error Interrupt source */
+-			SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+-
+-			SkGeHwErr(pAC, IoC, RegVal32);
+-		}
+-
+-		SkHwtIsr(pAC, IoC);
+-	}
+-
+-}	/* SkGeSirqIsr */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
+- *
+- * return:
+- *	0	o.k. nothing needed
+- *	1	Restart needed on this port
+- */
+-static int SkGePortCheckShorts(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO Context */
+-int		Port)		/* Which port should be checked */
+-{
+-	SK_U32		Shorts;			/* Short Event Counter */
+-	SK_U32		CheckShorts;	/* Check value for Short Event Counter */
+-	SK_U64		RxCts;			/* Rx Counter (packets on network) */
+-	SK_U32		RxTmp;			/* Rx temp. Counter */
+-	SK_U32		FcsErrCts;		/* FCS Error Counter */
+-	SK_GEPORT	*pPrt;			/* GIni Port struct pointer */
+-	int			Rtv;			/* Return value */
+-	int			i;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* Default: no action */
+-	Rtv = SK_HW_PS_NONE;
+-
+-	(void)SkXmUpdateStats(pAC, IoC, Port);
+-
+-	/* Extra precaution: check for short Event counter */
+-	(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
+-
+-	/*
+-	 * Read Rx counters (packets seen on the network and not necessarily
+-	 * really received.
+-	 */
+-	RxCts = 0;
+-
+-	for (i = 0; i < ARRAY_SIZE(SkGeRxRegs); i++) {
+-		
+-		(void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
+-		
+-		RxCts += (SK_U64)RxTmp;
+-	}
+-
+-	/* On default: check shorts against zero */
+-	CheckShorts = 0;
+-
+-	/* Extra precaution on active links */
+-	if (pPrt->PHWLinkUp) {
+-		/* Reset Link Restart counter */
+-		pPrt->PLinkResCt = 0;
+-		pPrt->PAutoNegTOCt = 0;
+-
+-		/* If link is up check for 2 */
+-		CheckShorts = 2;
+-
+-		(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
+-		
+-		if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+-		    pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
+-		    (pPrt->PLinkMode == SK_LMODE_HALF ||
+-			 pPrt->PLinkMode == SK_LMODE_FULL)) {
+-			/*
+-			 * This is autosensing and we are in the fallback
+-			 * manual full/half duplex mode.
+-			 */
+-			if (RxCts == pPrt->PPrevRx) {
+-				/* Nothing received, restart link */
+-				pPrt->PPrevFcs = FcsErrCts;
+-				pPrt->PPrevShorts = Shorts;
+-				
+-				return(SK_HW_PS_RESTART);
+-			}
+-			else {
+-				pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
+-			}
+-		}
+-
+-		if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
+-		    (!(FcsErrCts - pPrt->PPrevFcs))) {
+-			/*
+-			 * Note: The compare with zero above has to be done the way shown,
+-			 * otherwise the Linux driver will have a problem.
+-			 */
+-			/*
+-			 * We received a bunch of frames or no CRC error occured on the
+-			 * network -> ok.
+-			 */
+-			pPrt->PPrevRx = RxCts;
+-			pPrt->PPrevFcs = FcsErrCts;
+-			pPrt->PPrevShorts = Shorts;
+-
+-			return(SK_HW_PS_NONE);
+-		}
+-
+-		pPrt->PPrevFcs = FcsErrCts;
+-	}
+-
+-
+-	if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-			("Short Event Count Restart Port %d \n", Port));
+-		Rtv = SK_HW_PS_RESTART;
+-	}
+-
+-	pPrt->PPrevShorts = Shorts;
+-	pPrt->PPrevRx = RxCts;
+-
+-	return(Rtv);
+-}	/* SkGePortCheckShorts */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- * SkGePortCheckUp() - Check if the link is up
+- *
+- * return:
+- *	0	o.k. nothing needed
+- *	1	Restart needed on this port
+- *	2	Link came up
+- */
+-static int SkGePortCheckUp(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO Context */
+-int		Port)		/* Which port should be checked */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	SK_BOOL		AutoNeg;	/* Is Auto-negotiation used ? */
+-	int			Rtv;		/* Return value */
+-
+-	Rtv = SK_HW_PS_NONE;
+-	
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+-		AutoNeg = SK_FALSE;
+-	}
+-	else {
+-		AutoNeg = SK_TRUE;
+-	}
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-
+-		switch (pPrt->PhyType) {
+-		
+-		case SK_PHY_XMAC:
+-			Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
+-			break;
+-		case SK_PHY_BCOM:
+-			Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
+-			break;
+-#ifdef OTHER_PHY
+-		case SK_PHY_LONE:
+-			Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
+-			break;
+-		case SK_PHY_NAT:
+-			Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
+-			break;
+-#endif /* OTHER_PHY */
+-		}
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		
+-		Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
+-	}
+-#endif /* YUKON */
+-
+-	return(Rtv);	
+-}	/* SkGePortCheckUp */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
+- *
+- * return:
+- *	0	o.k. nothing needed
+- *	1	Restart needed on this port
+- *	2	Link came up
+- */
+-static int SkGePortCheckUpXmac(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO Context */
+-int		Port,		/* Which port should be checked */
+-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+-{
+-	SK_U32		Shorts;		/* Short Event Counter */
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	int			Done;
+-	SK_U32		GpReg;		/* General Purpose register value */
+-	SK_U16		Isrc;		/* Interrupt source register */
+-	SK_U16		IsrcSum;	/* Interrupt source register sum */
+-	SK_U16		LpAb;		/* Link Partner Ability */
+-	SK_U16		ResAb;		/* Resolved Ability */
+-	SK_U16		ExtStat;	/* Extended Status Register */
+-	SK_U8		NextMode;	/* Next AutoSensing Mode */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PHWLinkUp) {
+-		if (pPrt->PhyType != SK_PHY_XMAC) {
+-			return(SK_HW_PS_NONE);
+-		}
+-		else {
+-			return(SkGePortCheckShorts(pAC, IoC, Port));
+-		}
+-	}
+-
+-	IsrcSum = pPrt->PIsave;
+-	pPrt->PIsave = 0;
+-
+-	/* Now wait for each port's link */
+-	if (pPrt->PLinkBroken) {
+-		/* Link was broken */
+-		XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
+-
+-		if ((GpReg & XM_GP_INP_ASS) == 0) {
+-			/* The Link is in sync */
+-			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+-			IsrcSum |= Isrc;
+-			SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
+-			
+-			if ((Isrc & XM_IS_INP_ASS) == 0) {
+-				/* It has been in sync since last time */
+-				/* Restart the PORT */
+-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-					("Link in sync Restart Port %d\n", Port));
+-
+-				(void)SkXmUpdateStats(pAC, IoC, Port);
+-
+-				/* We now need to reinitialize the PrevShorts counter */
+-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
+-				pPrt->PPrevShorts = Shorts;
+-
+-				pPrt->PLinkBroken = SK_FALSE;
+-
+-				/*
+-				 * Link Restart Workaround:
+-				 *  it may be possible that the other Link side
+-				 *  restarts its link as well an we detect
+-				 *  another LinkBroken. To prevent this
+-				 *  happening we check for a maximum number
+-				 *  of consecutive restart. If those happens,
+-				 *  we do NOT restart the active link and
+-				 *  check whether the link is now o.k.
+-				 */
+-				pPrt->PLinkResCt++;
+-				
+-				pPrt->PAutoNegTimeOut = 0;
+-
+-				if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
+-					return(SK_HW_PS_RESTART);
+-				}
+-
+-				pPrt->PLinkResCt = 0;
+-				
+-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-					("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
+-			}
+-			else {
+-				pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
+-				
+-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-					("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
+-
+-				/* Do nothing more if link is broken */
+-				return(SK_HW_PS_NONE);
+-			}
+-		}
+-		else {
+-			/* Do nothing more if link is broken */
+-			return(SK_HW_PS_NONE);
+-		}
+-
+-	}
+-	else {
+-		/* Link was not broken, check if it is */
+-		XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+-		IsrcSum |= Isrc;
+-		if ((Isrc & XM_IS_INP_ASS) != 0) {
+-			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+-			IsrcSum |= Isrc;
+-			if ((Isrc & XM_IS_INP_ASS) != 0) {
+-				XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+-				IsrcSum |= Isrc;
+-				if ((Isrc & XM_IS_INP_ASS) != 0) {
+-					pPrt->PLinkBroken = SK_TRUE;
+-					/* Re-Init Link partner Autoneg flag */
+-					pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
+-					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-						("Link broken Port %d\n", Port));
+-
+-					/* Cable removed-> reinit sense mode */
+-					SkHWInitDefSense(pAC, IoC, Port);
+-
+-					return(SK_HW_PS_RESTART);
+-				}
+-			}
+-		}
+-		else {
+-			SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
+-			
+-			if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
+-				return(SK_HW_PS_RESTART);
+-			}
+-		}
+-	}
+-
+-	/*
+-	 * here we usually can check whether the link is in sync and
+-	 * auto-negotiation is done.
+-	 */
+-	XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
+-	XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+-	IsrcSum |= Isrc;
+-
+-	SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
+-	
+-	if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
+-		if ((GpReg & XM_GP_INP_ASS) == 0) {
+-			/* Save Auto-negotiation Done interrupt only if link is in sync */
+-			pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
+-		}
+-#ifdef DEBUG
+-		if ((pPrt->PIsave & XM_IS_AND) != 0) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-				("AutoNeg done rescheduled Port %d\n", Port));
+-		}
+-#endif /* DEBUG */
+-		return(SK_HW_PS_NONE);
+-	}
+-
+-	if (AutoNeg) {
+-		if ((IsrcSum & XM_IS_AND) != 0) {
+-			SkHWLinkUp(pAC, IoC, Port);
+-			Done = SkMacAutoNegDone(pAC, IoC, Port);
+-			if (Done != SK_AND_OK) {
+-				/* Get PHY parameters, for debugging only */
+-				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
+-				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
+-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-					("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
+-					 Port, LpAb, ResAb));
+-					
+-				/* Try next possible mode */
+-				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
+-				SkHWLinkDown(pAC, IoC, Port);
+-				if (Done == SK_AND_DUP_CAP) {
+-					/* GoTo next mode */
+-					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
+-				}
+-
+-				return(SK_HW_PS_RESTART);
+-			}
+-			/*
+-			 * Dummy Read extended status to prevent extra link down/ups
+-			 * (clear Page Received bit if set)
+-			 */
+-			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
+-			
+-			return(SK_HW_PS_LINK);
+-		}
+-		
+-		/* AutoNeg not done, but HW link is up. Check for timeouts */
+-		pPrt->PAutoNegTimeOut++;
+-		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
+-			/* Increase the Timeout counter */
+-			pPrt->PAutoNegTOCt++;
+-
+-			/* Timeout occured */
+-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-				("AutoNeg timeout Port %d\n", Port));
+-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+-				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
+-				/* Set Link manually up */
+-				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
+-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-					("Set manual full duplex Port %d\n", Port));
+-			}
+-
+-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+-				pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
+-				pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
+-				/*
+-				 * This is rather complicated.
+-				 * we need to check here whether the LIPA_AUTO
+-				 * we saw before is false alert. We saw at one
+-				 * switch ( SR8800) that on boot time it sends
+-				 * just one auto-neg packet and does no further
+-				 * auto-negotiation.
+-				 * Solution: we restart the autosensing after
+-				 * a few timeouts.
+-				 */
+-				pPrt->PAutoNegTOCt = 0;
+-				pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
+-				SkHWInitDefSense(pAC, IoC, Port);
+-			}
+-
+-			/* Do the restart */
+-			return(SK_HW_PS_RESTART);
+-		}
+-	}
+-	else {
+-		/* Link is up and we don't need more */
+-#ifdef DEBUG
+-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-				("ERROR: Lipa auto detected on port %d\n", Port));
+-		}
+-#endif /* DEBUG */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-			("Link sync(GP), Port %d\n", Port));
+-		SkHWLinkUp(pAC, IoC, Port);
+-		
+-		/*
+-		 * Link sync (GP) and so assume a good connection. But if not received
+-		 * a bunch of frames received in a time slot (maybe broken tx cable)
+-		 * the port is restart.
+-		 */
+-		return(SK_HW_PS_LINK);
+-	}
+-
+-	return(SK_HW_PS_NONE);
+-}	/* SkGePortCheckUpXmac */
+-
+-
+-/******************************************************************************
+- *
+- * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
+- *
+- * return:
+- *	0	o.k. nothing needed
+- *	1	Restart needed on this port
+- *	2	Link came up
+- */
+-static int SkGePortCheckUpBcom(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO Context */
+-int		Port,		/* Which port should be checked */
+-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	int			Done;
+-	SK_U16		Isrc;		/* Interrupt source register */
+-	SK_U16		PhyStat;	/* Phy Status Register */
+-	SK_U16		ResAb;		/* Master/Slave resolution */
+-	SK_U16		Ctrl;		/* Broadcom control flags */
+-#ifdef DEBUG
+-	SK_U16		LpAb;
+-	SK_U16		ExtStat;
+-#endif /* DEBUG */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* Check for No HCD Link events (#10523) */
+-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
+-
+-#ifdef xDEBUG
+-	if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) ==
+-		(PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
+-
+-		SK_U32	Stat1, Stat2, Stat3;
+-
+-		Stat1 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
+-		CMSMPrintString(
+-			pAC->pConfigTable,
+-			MSG_TYPE_RUNTIME_INFO,
+-			"CheckUp1 - Stat: %x, Mask: %x",
+-			(void *)Isrc,
+-			(void *)Stat1);
+-
+-		Stat1 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
+-		Stat1 = Stat1 << 16 | Stat2;
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
+-		Stat3 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
+-		Stat2 = Stat2 << 16 | Stat3;
+-		CMSMPrintString(
+-			pAC->pConfigTable,
+-			MSG_TYPE_RUNTIME_INFO,
+-			"Ctrl/Stat: %x, AN Adv/LP: %x",
+-			(void *)Stat1,
+-			(void *)Stat2);
+-
+-		Stat1 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
+-		Stat1 = Stat1 << 16 | Stat2;
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
+-		Stat3 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
+-		Stat2 = Stat2 << 16 | Stat3;
+-		CMSMPrintString(
+-			pAC->pConfigTable,
+-			MSG_TYPE_RUNTIME_INFO,
+-			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
+-			(void *)Stat1,
+-			(void *)Stat2);
+-
+-		Stat1 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
+-		Stat1 = Stat1 << 16 | Stat2;
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
+-		Stat3 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
+-		Stat2 = Stat2 << 16 | Stat3;
+-		CMSMPrintString(
+-			pAC->pConfigTable,
+-			MSG_TYPE_RUNTIME_INFO,
+-			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
+-			(void *)Stat1,
+-			(void *)Stat2);
+-	}
+-#endif /* DEBUG */
+-
+-	if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
+-		/*
+-		 * Workaround BCom Errata:
+-		 *	enable and disable loopback mode if "NO HCD" occurs.
+-		 */
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
+-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
+-			(SK_U16)(Ctrl | PHY_CT_LOOP));
+-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
+-			(SK_U16)(Ctrl & ~PHY_CT_LOOP));
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("No HCD Link event, Port %d\n", Port));
+-#ifdef xDEBUG
+-		CMSMPrintString(
+-			pAC->pConfigTable,
+-			MSG_TYPE_RUNTIME_INFO,
+-			"No HCD link event, port %d.",
+-			(void *)Port,
+-			(void *)NULL);
+-#endif /* DEBUG */
+-	}
+-
+-	/* Not obsolete: link status bit is latched to 0 and autoclearing! */
+-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+-
+-	if (pPrt->PHWLinkUp) {
+-		return(SK_HW_PS_NONE);
+-	}
+-
+-#ifdef xDEBUG
+-	{
+-		SK_U32	Stat1, Stat2, Stat3;
+-
+-		Stat1 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
+-		CMSMPrintString(
+-			pAC->pConfigTable,
+-			MSG_TYPE_RUNTIME_INFO,
+-			"CheckUp1a - Stat: %x, Mask: %x",
+-			(void *)Isrc,
+-			(void *)Stat1);
+-
+-		Stat1 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+-		Stat1 = Stat1 << 16 | PhyStat;
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
+-		Stat3 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
+-		Stat2 = Stat2 << 16 | Stat3;
+-		CMSMPrintString(
+-			pAC->pConfigTable,
+-			MSG_TYPE_RUNTIME_INFO,
+-			"Ctrl/Stat: %x, AN Adv/LP: %x",
+-			(void *)Stat1,
+-			(void *)Stat2);
+-
+-		Stat1 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
+-		Stat1 = Stat1 << 16 | Stat2;
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
+-		Stat3 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+-		Stat2 = Stat2 << 16 | ResAb;
+-		CMSMPrintString(
+-			pAC->pConfigTable,
+-			MSG_TYPE_RUNTIME_INFO,
+-			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
+-			(void *)Stat1,
+-			(void *)Stat2);
+-
+-		Stat1 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
+-		Stat1 = Stat1 << 16 | Stat2;
+-		Stat2 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
+-		Stat3 = 0;
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
+-		Stat2 = Stat2 << 16 | Stat3;
+-		CMSMPrintString(
+-			pAC->pConfigTable,
+-			MSG_TYPE_RUNTIME_INFO,
+-			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
+-			(void *)Stat1,
+-			(void *)Stat2);
+-	}
+-#endif /* DEBUG */
+-
+-	/*
+-	 * Here we usually can check whether the link is in sync and
+-	 * auto-negotiation is done.
+-	 */
+-
+-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+-
+-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
+-
+-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+-
+-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
+-		/* Error */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Master/Slave Fault port %d\n", Port));
+-		
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
+-		
+-		return(SK_HW_PS_RESTART);
+-	}
+-
+-	if ((PhyStat & PHY_ST_LSYNC) == 0) {
+-		return(SK_HW_PS_NONE);
+-	}
+-	
+-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Port %d, ResAb: 0x%04X\n", Port, ResAb));
+-
+-	if (AutoNeg) {
+-		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
+-			
+-			SkHWLinkUp(pAC, IoC, Port);
+-			
+-			Done = SkMacAutoNegDone(pAC, IoC, Port);
+-			
+-			if (Done != SK_AND_OK) {
+-#ifdef DEBUG
+-				/* Get PHY parameters, for debugging only */
+-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
+-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
+-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
+-					Port, LpAb, ExtStat));
+-#endif /* DEBUG */
+-				return(SK_HW_PS_RESTART);
+-			}
+-			else {
+-#ifdef xDEBUG
+-				/* Dummy read ISR to prevent extra link downs/ups */
+-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
+-
+-				if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
+-					CMSMPrintString(
+-						pAC->pConfigTable,
+-						MSG_TYPE_RUNTIME_INFO,
+-						"CheckUp2 - Stat: %x",
+-						(void *)ExtStat,
+-						(void *)NULL);
+-				}
+-#endif /* DEBUG */
+-				return(SK_HW_PS_LINK);
+-			}
+-		}
+-	}
+-	else {	/* !AutoNeg */
+-		/* Link is up and we don't need more. */
+-#ifdef DEBUG
+-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-				("ERROR: Lipa auto detected on port %d\n", Port));
+-		}
+-#endif /* DEBUG */
+-
+-#ifdef xDEBUG
+-		/* Dummy read ISR to prevent extra link downs/ups */
+-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
+-
+-		if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
+-			CMSMPrintString(
+-				pAC->pConfigTable,
+-				MSG_TYPE_RUNTIME_INFO,
+-				"CheckUp3 - Stat: %x",
+-				(void *)ExtStat,
+-				(void *)NULL);
+-		}
+-#endif /* DEBUG */
+-		
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-			("Link sync(GP), Port %d\n", Port));
+-		SkHWLinkUp(pAC, IoC, Port);
+-		
+-		return(SK_HW_PS_LINK);
+-	}
+-
+-	return(SK_HW_PS_NONE);
+-}	/* SkGePortCheckUpBcom */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
+- *
+- * return:
+- *	0	o.k. nothing needed
+- *	1	Restart needed on this port
+- *	2	Link came up
+- */
+-static int SkGePortCheckUpGmac(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO Context */
+-int		Port,		/* Which port should be checked */
+-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	int			Done;
+-	SK_U16		PhyIsrc;	/* PHY Interrupt source */
+-	SK_U16		PhyStat;	/* PPY Status */
+-	SK_U16		PhySpecStat;/* PHY Specific Status */
+-	SK_U16		ResAb;		/* Master/Slave resolution */
+-	SK_EVPARA	Para;
+-#ifdef DEBUG
+-	SK_U16		Word;		/* I/O helper */
+-#endif /* DEBUG */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PHWLinkUp) {
+-		return(SK_HW_PS_NONE);
+-	}
+-
+-	/* Read PHY Status */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
+-
+-	/* Read PHY Interrupt Status */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
+-
+-	if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
+-	}
+-
+-	if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
+-	}
+-
+-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+-	
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
+-
+-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
+-		/* Error */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Master/Slave Fault port %d\n", Port));
+-		
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
+-		
+-		return(SK_HW_PS_RESTART);
+-	}
+-
+-	/* Read PHY Specific Status */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
+-
+-#ifdef DEBUG
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
+-
+-	if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
+-		(PhySpecStat & PHY_M_PS_PAGE_REC) != 0)  {
+-		/* Read PHY Next Page Link Partner */
+-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Page Received, NextPage: 0x%04X\n", Word));
+-	}
+-#endif /* DEBUG */
+-
+-	if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
+-		return(SK_HW_PS_NONE);
+-	}
+-	
+-	if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
+-		(PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
+-		/* Downshift detected */
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
+-		
+-		Para.Para64 = Port;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
+-		
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
+-	}
+-
+-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+-	
+-	pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
+-	
+-	if (AutoNeg) {
+-		/* Auto-Negotiation Over ? */
+-		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
+-			
+-			SkHWLinkUp(pAC, IoC, Port);
+-			
+-			Done = SkMacAutoNegDone(pAC, IoC, Port);
+-			
+-			if (Done != SK_AND_OK) {
+-				return(SK_HW_PS_RESTART);
+-			}
+-			
+-			return(SK_HW_PS_LINK);
+-		}
+-	}
+-	else {	/* !AutoNeg */
+-		/* Link is up and we don't need more */
+-#ifdef DEBUG
+-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-				("ERROR: Lipa auto detected on port %d\n", Port));
+-		}
+-#endif /* DEBUG */
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-			("Link sync, Port %d\n", Port));
+-		SkHWLinkUp(pAC, IoC, Port);
+-		
+-		return(SK_HW_PS_LINK);
+-	}
+-
+-	return(SK_HW_PS_NONE);
+-}	/* SkGePortCheckUpGmac */
+-#endif /* YUKON */
+-
+-
+-#ifdef OTHER_PHY
+-/******************************************************************************
+- *
+- * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
+- *
+- * return:
+- *	0	o.k. nothing needed
+- *	1	Restart needed on this port
+- *	2	Link came up
+- */
+-static int SkGePortCheckUpLone(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO Context */
+-int		Port,		/* Which port should be checked */
+-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	int			Done;
+-	SK_U16		Isrc;		/* Interrupt source register */
+-	SK_U16		LpAb;		/* Link Partner Ability */
+-	SK_U16		ExtStat;	/* Extended Status Register */
+-	SK_U16		PhyStat;	/* Phy Status Register */
+-	SK_U16		StatSum;
+-	SK_U8		NextMode;	/* Next AutoSensing Mode */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PHWLinkUp) {
+-		return(SK_HW_PS_NONE);
+-	}
+-
+-	StatSum = pPrt->PIsave;
+-	pPrt->PIsave = 0;
+-
+-	/*
+-	 * here we usually can check whether the link is in sync and
+-	 * auto-negotiation is done.
+-	 */
+-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
+-	StatSum |= PhyStat;
+-
+-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+-	
+-	if ((PhyStat & PHY_ST_LSYNC) == 0) {
+-		/* Save Auto-negotiation Done bit */
+-		pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
+-#ifdef DEBUG
+-		if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-				("AutoNeg done rescheduled Port %d\n", Port));
+-		}
+-#endif /* DEBUG */
+-		return(SK_HW_PS_NONE);
+-	}
+-
+-	if (AutoNeg) {
+-		if ((StatSum & PHY_ST_AN_OVER) != 0) {
+-			SkHWLinkUp(pAC, IoC, Port);
+-			Done = SkMacAutoNegDone(pAC, IoC, Port);
+-			if (Done != SK_AND_OK) {
+-				/* Get PHY parameters, for debugging only */
+-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
+-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
+-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
+-					 Port, LpAb, ExtStat));
+-					
+-				/* Try next possible mode */
+-				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
+-				SkHWLinkDown(pAC, IoC, Port);
+-				if (Done == SK_AND_DUP_CAP) {
+-					/* GoTo next mode */
+-					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
+-				}
+-
+-				return(SK_HW_PS_RESTART);
+-
+-			}
+-			else {
+-				/*
+-				 * Dummy Read interrupt status to prevent
+-				 * extra link down/ups
+-				 */
+-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
+-				return(SK_HW_PS_LINK);
+-			}
+-		}
+-		
+-		/* AutoNeg not done, but HW link is up. Check for timeouts */
+-		pPrt->PAutoNegTimeOut++;
+-		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
+-			/* Timeout occured */
+-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-				("AutoNeg timeout Port %d\n", Port));
+-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+-				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
+-				/* Set Link manually up */
+-				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
+-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-					("Set manual full duplex Port %d\n", Port));
+-			}
+-
+-			/* Do the restart */
+-			return(SK_HW_PS_RESTART);
+-		}
+-	}
+-	else {
+-		/* Link is up and we don't need more */
+-#ifdef DEBUG
+-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-				("ERROR: Lipa auto detected on port %d\n", Port));
+-		}
+-#endif /* DEBUG */
+-
+-		/*
+-		 * Dummy Read interrupt status to prevent
+-		 * extra link down/ups
+-		 */
+-		SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
+-		
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-			("Link sync(GP), Port %d\n", Port));
+-		SkHWLinkUp(pAC, IoC, Port);
+-		
+-		return(SK_HW_PS_LINK);
+-	}
+-
+-	return(SK_HW_PS_NONE);
+-}	/* SkGePortCheckUpLone */
+-
+-
+-/******************************************************************************
+- *
+- * SkGePortCheckUpNat() - Check if the link is up on National PHY
+- *
+- * return:
+- *	0	o.k. nothing needed
+- *	1	Restart needed on this port
+- *	2	Link came up
+- */
+-static int SkGePortCheckUpNat(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO Context */
+-int		Port,		/* Which port should be checked */
+-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
+-{
+-	/* todo: National */
+-	return(SK_HW_PS_NONE);
+-}	/* SkGePortCheckUpNat */
+-#endif /* OTHER_PHY */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGeSirqEvent() - Event Service Routine
+- *
+- * Description:
+- *
+- * Notes:
+- */
+-int	SkGeSirqEvent(
+-SK_AC		*pAC,		/* Adapter Context */
+-SK_IOC		IoC,		/* Io Context */
+-SK_U32		Event,		/* Module specific Event */
+-SK_EVPARA	Para)		/* Event specific Parameter */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	SK_U32		Port;
+-	SK_U32		Val32;
+-	int			PortStat;
+-	SK_U8		Val8;
+-#ifdef GENESIS
+-	SK_U64		Octets;
+-#endif /* GENESIS */
+-
+-	Port = Para.Para32[0];
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	switch (Event) {
+-	case SK_HWEV_WATIM:
+-		if (pPrt->PState == SK_PRT_RESET) {
+-		
+-			PortStat = SK_HW_PS_NONE;
+-		}
+-		else {
+-			/* Check whether port came up */
+-			PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
+-		}
+-
+-		switch (PortStat) {
+-		case SK_HW_PS_RESTART:
+-			if (pPrt->PHWLinkUp) {
+-				/* Set Link to down */
+-				SkHWLinkDown(pAC, IoC, (int)Port);
+-
+-				/*
+-				 * Signal directly to RLMT to ensure correct
+-				 * sequence of SWITCH and RESET event.
+-				 */
+-				SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+-			}
+-
+-			/* Restart needed */
+-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+-			break;
+-
+-		case SK_HW_PS_LINK:
+-			/* Signal to RLMT */
+-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
+-			break;
+-		}
+-		
+-		/* Start again the check Timer */
+-		if (pPrt->PHWLinkUp) {
+-			Val32 = SK_WA_ACT_TIME;
+-		}
+-		else {
+-			Val32 = SK_WA_INA_TIME;
+-		}
+-
+-		/* Todo: still needed for non-XMAC PHYs??? */
+-		/* Start workaround Errata #2 timer */
+-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
+-			SKGE_HWAC, SK_HWEV_WATIM, Para);
+-		break;
+-
+-	case SK_HWEV_PORT_START:
+-		if (pPrt->PHWLinkUp) {
+-			/*
+-			 * Signal directly to RLMT to ensure correct
+-			 * sequence of SWITCH and RESET event.
+-			 */
+-			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+-		}
+-
+-		SkHWLinkDown(pAC, IoC, (int)Port);
+-
+-		/* Schedule Port RESET */
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+-
+-		/* Start workaround Errata #2 timer */
+-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+-			SKGE_HWAC, SK_HWEV_WATIM, Para);
+-		break;
+-
+-	case SK_HWEV_PORT_STOP:
+-		if (pPrt->PHWLinkUp) {
+-			/*
+-			 * Signal directly to RLMT to ensure correct
+-			 * sequence of SWITCH and RESET event.
+-			 */
+-			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+-		}
+-
+-		/* Stop Workaround Timer */
+-		SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
+-
+-		SkHWLinkDown(pAC, IoC, (int)Port);
+-		break;
+-
+-	case SK_HWEV_UPDATE_STAT:
+-		/* We do NOT need to update any statistics */
+-		break;
+-
+-	case SK_HWEV_CLEAR_STAT:
+-		/* We do NOT need to clear any statistics */
+-		for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
+-			pPrt->PPrevRx = 0;
+-			pPrt->PPrevFcs = 0;
+-			pPrt->PPrevShorts = 0;
+-		}
+-		break;
+-
+-	case SK_HWEV_SET_LMODE:
+-		Val8 = (SK_U8)Para.Para32[1];
+-		if (pPrt->PLinkModeConf != Val8) {
+-			/* Set New link mode */
+-			pPrt->PLinkModeConf = Val8;
+-
+-			/* Restart Port */
+-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+-		}
+-		break;
+-
+-	case SK_HWEV_SET_FLOWMODE:
+-		Val8 = (SK_U8)Para.Para32[1];
+-		if (pPrt->PFlowCtrlMode != Val8) {
+-			/* Set New Flow Control mode */
+-			pPrt->PFlowCtrlMode = Val8;
+-
+-			/* Restart Port */
+-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+-		}
+-		break;
+-
+-	case SK_HWEV_SET_ROLE:
+-		/* not possible for fiber */
+-		if (!pAC->GIni.GICopperType) {
+-			break;
+-		}
+-		Val8 = (SK_U8)Para.Para32[1];
+-		if (pPrt->PMSMode != Val8) {
+-			/* Set New Role (Master/Slave) mode */
+-			pPrt->PMSMode = Val8;
+-
+-			/* Restart Port */
+-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+-		}
+-		break;
+-
+-	case SK_HWEV_SET_SPEED:
+-		if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+-			break;
+-		}
+-		Val8 = (SK_U8)Para.Para32[1];
+-		if (pPrt->PLinkSpeed != Val8) {
+-			/* Set New Speed parameter */
+-			pPrt->PLinkSpeed = Val8;
+-
+-			/* Restart Port */
+-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+-		}
+-		break;
+-
+-#ifdef GENESIS
+-	case SK_HWEV_HALFDUP_CHK:
+-		if (pAC->GIni.GIGenesis) {
+-			/*
+-			 * half duplex hangup workaround.
+-			 * See packet arbiter timeout interrupt for description
+-			 */
+-			pPrt->HalfDupTimerActive = SK_FALSE;
+-			if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+-				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
+-				/* Snap statistic counters */
+-				(void)SkXmUpdateStats(pAC, IoC, Port);
+-
+-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
+-
+-				Octets = (SK_U64)Val32 << 32;
+-				
+-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
+-
+-				Octets += Val32;
+-				
+-				if (pPrt->LastOctets == Octets) {
+-					/* Tx hanging, a FIFO flush restarts it */
+-					SkMacFlushTxFifo(pAC, IoC, Port);
+-				}
+-			}
+-		}
+-		break;
+-#endif /* GENESIS */
+-	
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
+-		break;
+-	}
+-
+-	return(0);
+-}	/* SkGeSirqEvent */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkPhyIsrBcom() - PHY interrupt service routine
+- *
+- * Description: handles all interrupts from BCom PHY
+- *
+- * Returns: N/A
+- */
+-static void SkPhyIsrBcom(
+-SK_AC		*pAC,		/* Adapter Context */
+-SK_IOC		IoC,		/* Io Context */
+-int			Port,		/* Port Num = PHY Num */
+-SK_U16		IStatus)	/* Interrupt Status */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	SK_EVPARA	Para;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if ((IStatus & PHY_B_IS_PSE) != 0) {
+-		/* Incorrectable pair swap error */
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
+-			SKERR_SIRQ_E022MSG);
+-	}
+-	
+-	if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
+-
+-		SkHWLinkDown(pAC, IoC, Port);
+-
+-		Para.Para32[0] = (SK_U32)Port;
+-		/* Signal to RLMT */
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-
+-		/* Start workaround Errata #2 timer */
+-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+-			SKGE_HWAC, SK_HWEV_WATIM, Para);
+-	}
+-
+-}	/* SkPhyIsrBcom */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- *	SkPhyIsrGmac() - PHY interrupt service routine
+- *
+- * Description: handles all interrupts from Marvell PHY
+- *
+- * Returns: N/A
+- */
+-static void SkPhyIsrGmac(
+-SK_AC		*pAC,		/* Adapter Context */
+-SK_IOC		IoC,		/* Io Context */
+-int			Port,		/* Port Num = PHY Num */
+-SK_U16		IStatus)	/* Interrupt Status */
+-{
+-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
+-	SK_EVPARA	Para;
+-	SK_U16		Word;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
+-
+-		SkHWLinkDown(pAC, IoC, Port);
+-
+-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNeg.Adv: 0x%04X\n", Word));
+-		
+-		/* Set Auto-negotiation advertisement */
+-		if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
+-			/* restore Asymmetric Pause bit */
+-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
+-				(SK_U16)(Word | PHY_M_AN_ASP));
+-		}
+-		
+-		Para.Para32[0] = (SK_U32)Port;
+-		/* Signal to RLMT */
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-	
+-	if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
+-		/* Auto-Negotiation Error */
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
+-	}
+-	
+-	if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
+-		/* FIFO Overflow/Underrun Error */
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
+-	}
+-	
+-}	/* SkPhyIsrGmac */
+-#endif /* YUKON */
+-
+-
+-#ifdef OTHER_PHY
+-/******************************************************************************
+- *
+- *	SkPhyIsrLone() - PHY interrupt service routine
+- *
+- * Description: handles all interrupts from LONE PHY
+- *
+- * Returns: N/A
+- */
+-static void SkPhyIsrLone(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* Io Context */
+-int		Port,		/* Port Num = PHY Num */
+-SK_U16	IStatus)	/* Interrupt Status */
+-{
+-	SK_EVPARA	Para;
+-
+-	if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
+-		
+-		SkHWLinkDown(pAC, IoC, Port);
+-
+-		Para.Para32[0] = (SK_U32)Port;
+-		/* Signal to RLMT */
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-	}
+-
+-}	/* SkPhyIsrLone */
+-#endif /* OTHER_PHY */
+-
+-/* End of File */
+diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c
+deleted file mode 100644
+index 79bf57c..0000000
+--- a/drivers/net/sk98lin/ski2c.c
++++ /dev/null
+@@ -1,1296 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	ski2c.c
+- * Project:	Gigabit Ethernet Adapters, TWSI-Module
+- * Version:	$Revision: 1.59 $
+- * Date:	$Date: 2003/10/20 09:07:25 $
+- * Purpose:	Functions to access Voltage and Temperature Sensor
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- *	I2C Protocol
+- */
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. ";
+-#endif
+-
+-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+-#include "h/lm80.h"
+-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+-
+-#ifdef __C2MAN__
+-/*
+-	I2C protocol implementation.
+-
+-	General Description:
+-
+-	The I2C protocol is used for the temperature sensors and for
+-	the serial EEPROM which hold the configuration.
+-
+-	This file covers functions that allow to read write and do
+-	some bulk requests a specified I2C address.
+-
+-	The Genesis has 2 I2C buses. One for the EEPROM which holds
+-	the VPD Data and one for temperature and voltage sensor.
+-	The following picture shows the I2C buses, I2C devices and
+-	their control registers.
+-
+-	Note: The VPD functions are in skvpd.c
+-.
+-.	PCI Config I2C Bus for VPD Data:
+-.
+-.		      +------------+
+-.		      | VPD EEPROM |
+-.		      +------------+
+-.			     |
+-.			     | <-- I2C
+-.			     |
+-.		 +-----------+-----------+
+-.		 |			 |
+-.	+-----------------+	+-----------------+
+-.	| PCI_VPD_ADR_REG |	| PCI_VPD_DAT_REG |
+-.	+-----------------+	+-----------------+
+-.
+-.
+-.	I2C Bus for LM80 sensor:
+-.
+-.			+-----------------+
+-.			| Temperature and |
+-.			| Voltage Sensor  |
+-.			| 	LM80	  |
+-.			+-----------------+
+-.				|
+-.				|
+-.			I2C --> |
+-.				|
+-.			     +----+
+-.	     +-------------->| OR |<--+
+-.	     |		     +----+   |
+-.     +------+------+		      |
+-.     |		    |		      |
+-. +--------+	+--------+	+----------+
+-. | B2_I2C |	| B2_I2C |	|  B2_I2C  |
+-. | _CTRL  |	| _DATA  |	|   _SW    |
+-. +--------+	+--------+	+----------+
+-.
+-	The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
+-	and B2_I2C_DATA registers.
+-	For driver software it is recommended to use the I2C control and
+-	data register, because I2C bus timing is done by the ASIC and
+-	an interrupt may be received when the I2C request is completed.
+-
+-	Clock Rate Timing:			MIN	MAX	generated by
+-		VPD EEPROM:			50 kHz	100 kHz		HW
+-		LM80 over I2C Ctrl/Data reg.	50 kHz	100 kHz		HW
+-		LM80 over B2_I2C_SW register	0	400 kHz		SW
+-
+-	Note:	The clock generated by the hardware is dependend on the
+-		PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
+-		clock is 50 kHz.
+- */
+-intro()
+-{}
+-#endif
+-
+-#ifdef SK_DIAG
+-/*
+- * I2C Fast Mode timing values used by the LM80.
+- * If new devices are added to the I2C bus the timing values have to be checked.
+- */
+-#ifndef I2C_SLOW_TIMING
+-#define	T_CLK_LOW			1300L	/* clock low time in ns */
+-#define	T_CLK_HIGH		 	 600L	/* clock high time in ns */
+-#define T_DATA_IN_SETUP		 100L	/* data in Set-up Time */
+-#define T_START_HOLD		 600L	/* start condition hold time */
+-#define T_START_SETUP		 600L	/* start condition Set-up time */
+-#define	T_STOP_SETUP		 600L	/* stop condition Set-up time */
+-#define T_BUS_IDLE			1300L	/* time the bus must free after Tx */
+-#define	T_CLK_2_DATA_OUT	 900L	/* max. clock low to data output valid */
+-#else	/* I2C_SLOW_TIMING */
+-/* I2C Standard Mode Timing */
+-#define	T_CLK_LOW			4700L	/* clock low time in ns */
+-#define	T_CLK_HIGH			4000L	/* clock high time in ns */
+-#define T_DATA_IN_SETUP		 250L	/* data in Set-up Time */
+-#define T_START_HOLD		4000L	/* start condition hold time */
+-#define T_START_SETUP		4700L	/* start condition Set-up time */
+-#define	T_STOP_SETUP		4000L	/* stop condition Set-up time */
+-#define T_BUS_IDLE			4700L	/* time the bus must free after Tx */
+-#endif	/* !I2C_SLOW_TIMING */
+-
+-#define NS2BCLK(x)	(((x)*125)/10000)
+-
+-/*
+- * I2C Wire Operations
+- *
+- * About I2C_CLK_LOW():
+- *
+- * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
+- * clock to low, to prevent the ASIC and the I2C data client from driving the
+- * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client
+- * send an 'ACK'). See also Concentrator Bugreport No. 10192.
+- */
+-#define I2C_DATA_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA)
+-#define	I2C_DATA_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA)
+-#define	I2C_DATA_OUT(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
+-#define	I2C_DATA_IN(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
+-#define	I2C_CLK_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_CLK)
+-#define	I2C_CLK_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
+-#define	I2C_START_COND(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK)
+-
+-#define NS2CLKT(x)	((x*125L)/10000)
+-
+-/*--------------- I2C Interface Register Functions --------------- */
+-
+-/*
+- * sending one bit
+- */
+-void SkI2cSndBit(
+-SK_IOC	IoC,	/* I/O Context */
+-SK_U8	Bit)	/* Bit to send */
+-{
+-	I2C_DATA_OUT(IoC);
+-	if (Bit) {
+-		I2C_DATA_HIGH(IoC);
+-	}
+-	else {
+-		I2C_DATA_LOW(IoC);
+-	}
+-	SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
+-	I2C_CLK_HIGH(IoC);
+-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
+-	I2C_CLK_LOW(IoC);
+-}	/* SkI2cSndBit*/
+-
+-
+-/*
+- * Signal a start to the I2C Bus.
+- *
+- * A start is signaled when data goes to low in a high clock cycle.
+- *
+- * Ends with Clock Low.
+- *
+- * Status: not tested
+- */
+-void SkI2cStart(
+-SK_IOC	IoC)	/* I/O Context */
+-{
+-	/* Init data and Clock to output lines */
+-	/* Set Data high */
+-	I2C_DATA_OUT(IoC);
+-	I2C_DATA_HIGH(IoC);
+-	/* Set Clock high */
+-	I2C_CLK_HIGH(IoC);
+-
+-	SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
+-
+-	/* Set Data Low */
+-	I2C_DATA_LOW(IoC);
+-
+-	SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
+-
+-	/* Clock low without Data to Input */
+-	I2C_START_COND(IoC);
+-
+-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
+-}	/* SkI2cStart */
+-
+-
+-void SkI2cStop(
+-SK_IOC	IoC)	/* I/O Context */
+-{
+-	/* Init data and Clock to output lines */
+-	/* Set Data low */
+-	I2C_DATA_OUT(IoC);
+-	I2C_DATA_LOW(IoC);
+-
+-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
+-
+-	/* Set Clock high */
+-	I2C_CLK_HIGH(IoC);
+-
+-	SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
+-
+-	/*
+-	 * Set Data High:	Do it by setting the Data Line to Input.
+-	 *			Because of a pull up resistor the Data Line
+-	 *			floods to high.
+-	 */
+-	I2C_DATA_IN(IoC);
+-
+-	/*
+-	 *	When I2C activity is stopped
+-	 *	 o	DATA should be set to input and
+-	 *	 o	CLOCK should be set to high!
+-	 */
+-	SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
+-}	/* SkI2cStop */
+-
+-
+-/*
+- * Receive just one bit via the I2C bus.
+- *
+- * Note:	Clock must be set to LOW before calling this function.
+- *
+- * Returns The received bit.
+- */
+-int SkI2cRcvBit(
+-SK_IOC	IoC)	/* I/O Context */
+-{
+-	int	Bit;
+-	SK_U8	I2cSwCtrl;
+-
+-	/* Init data as input line */
+-	I2C_DATA_IN(IoC);
+-
+-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
+-
+-	I2C_CLK_HIGH(IoC);
+-
+-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
+-
+-	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
+-	
+-	Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
+-
+-	I2C_CLK_LOW(IoC);
+-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
+-
+-	return(Bit);
+-}	/* SkI2cRcvBit */
+-
+-
+-/*
+- * Receive an ACK.
+- *
+- * returns	0 If acknowledged
+- *		1 in case of an error
+- */
+-int SkI2cRcvAck(
+-SK_IOC	IoC)	/* I/O Context */
+-{
+-	/*
+-	 * Received bit must be zero.
+-	 */
+-	return(SkI2cRcvBit(IoC) != 0);
+-}	/* SkI2cRcvAck */
+-
+-
+-/*
+- * Send an NACK.
+- */
+-void SkI2cSndNAck(
+-SK_IOC	IoC)	/* I/O Context */
+-{
+-	/*
+-	 * Received bit must be zero.
+-	 */
+-	SkI2cSndBit(IoC, 1);
+-}	/* SkI2cSndNAck */
+-
+-
+-/*
+- * Send an ACK.
+- */
+-void SkI2cSndAck(
+-SK_IOC IoC)	/* I/O Context */
+-{
+-	/*
+-	 * Received bit must be zero.
+-	 */
+-	SkI2cSndBit(IoC, 0);
+-}	/* SkI2cSndAck */
+-
+-
+-/*
+- * Send one byte to the I2C device and wait for ACK.
+- *
+- * Return acknowleged status.
+- */
+-int SkI2cSndByte(
+-SK_IOC	IoC,	/* I/O Context */
+-int		Byte)	/* byte to send */
+-{
+-	int	i;
+-
+-	for (i = 0; i < 8; i++) {
+-		if (Byte & (1<<(7-i))) {
+-			SkI2cSndBit(IoC, 1);
+-		}
+-		else {
+-			SkI2cSndBit(IoC, 0);
+-		}
+-	}
+-
+-	return(SkI2cRcvAck(IoC));
+-}	/* SkI2cSndByte */
+-
+-
+-/*
+- * Receive one byte and ack it.
+- *
+- * Return byte.
+- */
+-int SkI2cRcvByte(
+-SK_IOC	IoC,	/* I/O Context */
+-int		Last)	/* Last Byte Flag */
+-{
+-	int	i;
+-	int	Byte = 0;
+-
+-	for (i = 0; i < 8; i++) {
+-		Byte <<= 1;
+-		Byte |= SkI2cRcvBit(IoC);
+-	}
+-
+-	if (Last) {
+-		SkI2cSndNAck(IoC);
+-	}
+-	else {
+-		SkI2cSndAck(IoC);
+-	}
+-
+-	return(Byte);
+-}	/* SkI2cRcvByte */
+-
+-
+-/*
+- * Start dialog and send device address
+- *
+- * Return 0 if acknowleged, 1 in case of an error
+- */
+-int	SkI2cSndDev(
+-SK_IOC	IoC,	/* I/O Context */
+-int		Addr,	/* Device Address */
+-int		Rw)		/* Read / Write Flag */
+-{
+-	SkI2cStart(IoC);
+-	Rw = ~Rw;
+-	Rw &= I2C_WRITE;
+-	return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
+-}	/* SkI2cSndDev */
+-
+-#endif /* SK_DIAG */
+-
+-/*----------------- I2C CTRL Register Functions ----------*/
+-
+-/*
+- * waits for a completion of an I2C transfer
+- *
+- * returns	0:	success, transfer completes
+- *			1:	error,	 transfer does not complete, I2C transfer
+- *						 killed, wait loop terminated.
+- */
+-static int	SkI2cWait(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC,	/* I/O Context */
+-int		Event)	/* complete event to wait for (I2C_READ or I2C_WRITE) */
+-{
+-	SK_U64	StartTime;
+-	SK_U64	CurrentTime;
+-	SK_U32	I2cCtrl;
+-
+-	StartTime = SkOsGetTime(pAC);
+-	
+-	do {
+-		CurrentTime = SkOsGetTime(pAC);
+-
+-		if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
+-			
+-			SK_I2C_STOP(IoC);
+-#ifndef SK_DIAG
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
+-#endif /* !SK_DIAG */
+-			return(1);
+-		}
+-		
+-		SK_I2C_GET_CTL(IoC, &I2cCtrl);
+-
+-#ifdef xYUKON_DBG
+-		printf("StartTime=%lu, CurrentTime=%lu\n",
+-			StartTime, CurrentTime);
+-		if (kbhit()) {
+-			return(1);
+-		}
+-#endif /* YUKON_DBG */
+-	
+-	} while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
+-
+-	return(0);
+-}	/* SkI2cWait */
+-
+-
+-/*
+- * waits for a completion of an I2C transfer
+- *
+- * Returns
+- *	Nothing
+- */
+-void SkI2cWaitIrq(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC)	/* I/O Context */
+-{
+-	SK_SENSOR	*pSen;
+-	SK_U64		StartTime;
+-	SK_U32		IrqSrc;
+-
+-	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+-
+-	if (pSen->SenState == SK_SEN_IDLE) {
+-		return;
+-	}
+-
+-	StartTime = SkOsGetTime(pAC);
+-	
+-	do {
+-		if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
+-			
+-			SK_I2C_STOP(IoC);
+-#ifndef SK_DIAG
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
+-#endif /* !SK_DIAG */
+-			return;
+-		}
+-		
+-		SK_IN32(IoC, B0_ISRC, &IrqSrc);
+-
+-	} while ((IrqSrc & IS_I2C_READY) == 0);
+-
+-	pSen->SenState = SK_SEN_IDLE;
+-	return;
+-}	/* SkI2cWaitIrq */
+-
+-/*
+- * writes a single byte or 4 bytes into the I2C device
+- *
+- * returns	0:	success
+- *			1:	error
+- */
+-static int SkI2cWrite(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-SK_U32	I2cData,	/* I2C Data to write */
+-int		I2cDev,		/* I2C Device Address */
+-int		I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
+-int		I2cReg,		/* I2C Device Register Address */
+-int		I2cBurst)	/* I2C Burst Flag */
+-{
+-	SK_OUT32(IoC, B2_I2C_DATA, I2cData);
+-	
+-	SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
+-	
+-	return(SkI2cWait(pAC, IoC, I2C_WRITE));
+-}	/* SkI2cWrite*/
+-
+-
+-#ifdef	SK_DIAG
+-/*
+- * reads a single byte or 4 bytes from the I2C device
+- *
+- * returns	the word read
+- */
+-SK_U32 SkI2cRead(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-int		I2cDev,		/* I2C Device Address */
+-int		I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
+-int		I2cReg,		/* I2C Device Register Address */
+-int		I2cBurst)	/* I2C Burst Flag */
+-{
+-	SK_U32	Data;
+-
+-	SK_OUT32(IoC, B2_I2C_DATA, 0);
+-	SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
+-	
+-	if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
+-		w_print("%s\n", SKERR_I2C_E002MSG);
+-	}
+-	
+-	SK_IN32(IoC, B2_I2C_DATA, &Data);
+-	
+-	return(Data);
+-}	/* SkI2cRead */
+-#endif /* SK_DIAG */
+-
+-
+-/*
+- * read a sensor's value
+- *
+- * This function reads a sensor's value from the I2C sensor chip. The sensor
+- * is defined by its index into the sensors database in the struct pAC points
+- * to.
+- * Returns
+- *		1 if the read is completed
+- *		0 if the read must be continued (I2C Bus still allocated)
+- */
+-static int	SkI2cReadSensor(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_SENSOR	*pSen)	/* Sensor to be read */
+-{
+-    if (pSen->SenRead != NULL) {
+-        return((*pSen->SenRead)(pAC, IoC, pSen));
+-    }
+-	else {
+-        return(0); /* no success */
+-	}
+-}	/* SkI2cReadSensor */
+-
+-/*
+- * Do the Init state 0 initialization
+- */
+-static int SkI2cInit0(
+-SK_AC	*pAC)	/* Adapter Context */
+-{
+-	int	i;
+-
+-	/* Begin with first sensor */
+-	pAC->I2c.CurrSens = 0;
+-	
+-	/* Begin with timeout control for state machine */
+-	pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
+-	
+-	/* Set sensor number to zero */
+-	pAC->I2c.MaxSens = 0;
+-
+-#ifndef SK_DIAG
+-	/* Initialize Number of Dummy Reads */
+-	pAC->I2c.DummyReads = SK_MAX_SENSORS;
+-#endif
+-
+-	for (i = 0; i < SK_MAX_SENSORS; i++) {
+-		pAC->I2c.SenTable[i].SenDesc = "unknown";
+-		pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN;
+-		pAC->I2c.SenTable[i].SenThreErrHigh = 0;
+-		pAC->I2c.SenTable[i].SenThreErrLow = 0;
+-		pAC->I2c.SenTable[i].SenThreWarnHigh = 0;
+-		pAC->I2c.SenTable[i].SenThreWarnLow = 0;
+-		pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
+-		pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE;
+-		pAC->I2c.SenTable[i].SenValue = 0;
+-		pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
+-		pAC->I2c.SenTable[i].SenErrCts = 0;
+-		pAC->I2c.SenTable[i].SenBegErrTS = 0;
+-		pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
+-		pAC->I2c.SenTable[i].SenRead = NULL;
+-		pAC->I2c.SenTable[i].SenDev = 0;
+-	}
+-
+-	/* Now we are "INIT data"ed */
+-	pAC->I2c.InitLevel = SK_INIT_DATA;
+-	return(0);
+-}	/* SkI2cInit0*/
+-
+-
+-/*
+- * Do the init state 1 initialization
+- *
+- * initialize the following register of the LM80:
+- * Configuration register:
+- * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
+- *
+- * Interrupt Mask Register 1:
+- * - all interrupts are Disabled (0xff)
+- *
+- * Interrupt Mask Register 2:
+- * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
+- *
+- * Fan Divisor/RST_OUT register:
+- * - Divisors set to 1 (bits 00), all others 0s.
+- *
+- * OS# Configuration/Temperature resolution Register:
+- * - all 0s
+- *
+- */
+-static int SkI2cInit1(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC)	/* I/O Context */
+-{
+-    int i;
+-    SK_U8 I2cSwCtrl;
+-	SK_GEPORT *pPrt;	/* GIni Port struct pointer */
+-
+-	if (pAC->I2c.InitLevel != SK_INIT_DATA) {
+-		/* ReInit not needed in I2C module */
+-		return(0);
+-	}
+-
+-    /* Set the Direction of I2C-Data Pin to IN */
+-    SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
+-    /* Check for 32-Bit Yukon with Low at I2C-Data Pin */
+-	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
+-
+-	if ((I2cSwCtrl & I2C_DATA) == 0) {
+-		/* this is a 32-Bit board */
+-		pAC->GIni.GIYukon32Bit = SK_TRUE;
+-        return(0);
+-    }
+-
+-	/* Check for 64 Bit Yukon without sensors */
+-	if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
+-        return(0);
+-    }
+-
+-	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
+-	
+-	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
+-	
+-	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
+-	
+-	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
+-	
+-	(void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
+-		LM80_CFG, 0);
+-	
+-	/*
+-	 * MaxSens has to be updated here, because PhyType is not
+-	 * set when performing Init Level 0
+-	 */
+-    pAC->I2c.MaxSens = 5;
+-	
+-	pPrt = &pAC->GIni.GP[0];
+-	
+-	if (pAC->GIni.GIGenesis) {
+-		if (pPrt->PhyType == SK_PHY_BCOM) {
+-			if (pAC->GIni.GIMacsFound == 1) {
+-				pAC->I2c.MaxSens += 1;
+-			}
+-			else {
+-				pAC->I2c.MaxSens += 3;
+-			}
+-		}
+-	}
+-	else {
+-		pAC->I2c.MaxSens += 3;
+-	}
+-	
+-	for (i = 0; i < pAC->I2c.MaxSens; i++) {
+-		switch (i) {
+-		case 0:
+-			pAC->I2c.SenTable[i].SenDesc = "Temperature";
+-			pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP;
+-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
+-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
+-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
+-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
+-			pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN;
+-			break;
+-		case 1:
+-			pAC->I2c.SenTable[i].SenDesc = "Voltage PCI";
+-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
+-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
+-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
+-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
+-			pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN;
+-			break;
+-		case 2:
+-			pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO";
+-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
+-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
+-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
+-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
+-			pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN;
+-			pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO;
+-			break;
+-		case 3:
+-			pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC";
+-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
+-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
+-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
+-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR;
+-			pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN;
+-			break;
+-		case 4:
+-			if (pAC->GIni.GIGenesis) {
+-				if (pPrt->PhyType == SK_PHY_BCOM) {
+-					pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL";
+-					pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+-					pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+-				}
+-				else {
+-					pAC->I2c.SenTable[i].SenDesc = "Voltage PMA";
+-					pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+-					pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+-				}
+-			}
+-			else {
+-				pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX";
+-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
+-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
+-				if (pAC->GIni.GIVauxAvail) {
+-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
+-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
+-				}
+-				else {
+-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
+-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
+-				}
+-			}
+-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+-			pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
+-			break;
+-		case 5:
+-			if (pAC->GIni.GIGenesis) {
+-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
+-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
+-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
+-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
+-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
+-			}
+-			else {
+-				pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5";
+-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
+-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
+-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
+-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
+-			}
+-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+-			pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
+-			break;
+-		case 6:
+-			if (pAC->GIni.GIGenesis) {
+-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
+-			}
+-			else {
+-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
+-			}
+-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+-			pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN;
+-			break;
+-		case 7:
+-			if (pAC->GIni.GIGenesis) {
+-				pAC->I2c.SenTable[i].SenDesc = "Speed Fan";
+-				pAC->I2c.SenTable[i].SenType = SK_SEN_FAN;
+-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
+-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
+-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
+-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR;
+-				pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
+-			}
+-			else {
+-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
+-				pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
+-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
+-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
+-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
+-				pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN;
+-			}
+-			break;
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
+-				SKERR_I2C_E001, SKERR_I2C_E001MSG);
+-			break;
+-		}
+-
+-		pAC->I2c.SenTable[i].SenValue = 0;
+-		pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
+-		pAC->I2c.SenTable[i].SenErrCts = 0;
+-		pAC->I2c.SenTable[i].SenBegErrTS = 0;
+-		pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
+-		pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor;
+-		pAC->I2c.SenTable[i].SenDev = LM80_ADDR;
+-	}
+-
+-#ifndef SK_DIAG
+-	pAC->I2c.DummyReads = pAC->I2c.MaxSens;
+-#endif /* !SK_DIAG */
+-	
+-	/* Clear I2C IRQ */
+-	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+-	
+-	/* Now we are I/O initialized */
+-	pAC->I2c.InitLevel = SK_INIT_IO;
+-	return(0);
+-}	/* SkI2cInit1 */
+-
+-
+-/*
+- * Init level 2: Start first sensor read.
+- */
+-static int SkI2cInit2(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC)	/* I/O Context */
+-{
+-	int		ReadComplete;
+-	SK_SENSOR	*pSen;
+-
+-	if (pAC->I2c.InitLevel != SK_INIT_IO) {
+-		/* ReInit not needed in I2C module */
+-		/* Init0 and Init2 not permitted */
+-		return(0);
+-	}
+-
+-	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+-	ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+-
+-	if (ReadComplete) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
+-	}
+-
+-	/* Now we are correctly initialized */
+-	pAC->I2c.InitLevel = SK_INIT_RUN;
+-
+-	return(0);
+-}	/* SkI2cInit2*/
+-
+-
+-/*
+- * Initialize I2C devices
+- *
+- * Get the first voltage value and discard it.
+- * Go into temperature read mode. A default pointer is not set.
+- *
+- * The things to be done depend on the init level in the parameter list:
+- * Level 0:
+- *	Initialize only the data structures. Do NOT access hardware.
+- * Level 1:
+- *	Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
+- * Level 2:
+- *	Everything is possible. Interrupts may be used from now on.
+- *
+- * return:
+- *	0 = success
+- *	other = error.
+- */
+-int	SkI2cInit(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC,	/* I/O Context needed in levels 1 and 2 */
+-int		Level)	/* Init Level */
+-{
+-
+-	switch (Level) {
+-	case SK_INIT_DATA:
+-		return(SkI2cInit0(pAC));
+-	case SK_INIT_IO:
+-		return(SkI2cInit1(pAC, IoC));
+-	case SK_INIT_RUN:
+-		return(SkI2cInit2(pAC, IoC));
+-	default:
+-		break;
+-	}
+-
+-	return(0);
+-}	/* SkI2cInit */
+-
+-
+-#ifndef SK_DIAG
+-
+-/*
+- * Interrupt service function for the I2C Interface
+- *
+- * Clears the Interrupt source
+- *
+- * Reads the register and check it for sending a trap.
+- *
+- * Starts the timer if necessary.
+- */
+-void SkI2cIsr(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC)	/* I/O Context */
+-{
+-	SK_EVPARA	Para;
+-
+-	/* Clear I2C IRQ */
+-	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+-
+-	Para.Para64 = 0;
+-	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
+-}	/* SkI2cIsr */
+-
+-
+-/*
+- * Check this sensors Value against the threshold and send events.
+- */
+-static void SkI2cCheckSensor(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_SENSOR	*pSen)
+-{
+-	SK_EVPARA	ParaLocal;
+-	SK_BOOL		TooHigh;	/* Is sensor too high? */
+-	SK_BOOL		TooLow;		/* Is sensor too low? */
+-	SK_U64		CurrTime;	/* Current Time */
+-	SK_BOOL		DoTrapSend;	/* We need to send a trap */
+-	SK_BOOL		DoErrLog;	/* We need to log the error */
+-	SK_BOOL		IsError;	/* We need to log the error */
+-
+-	/* Check Dummy Reads first */
+-	if (pAC->I2c.DummyReads > 0) {
+-		pAC->I2c.DummyReads--;
+-		return;
+-	}
+-
+-	/* Get the current time */
+-	CurrTime = SkOsGetTime(pAC);
+-
+-	/* Set para to the most useful setting: The current sensor. */
+-	ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
+-
+-	/* Check the Value against the thresholds. First: Error Thresholds */
+-	TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
+-	TooLow = (pSen->SenValue < pSen->SenThreErrLow);
+-		
+-	IsError = SK_FALSE;
+-	if (TooHigh || TooLow) {
+-		/* Error condition is satisfied */
+-		DoTrapSend = SK_TRUE;
+-		DoErrLog = SK_TRUE;
+-
+-		/* Now error condition is satisfied */
+-		IsError = SK_TRUE;
+-
+-		if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
+-			/* This state is the former one */
+-
+-			/* So check first whether we have to send a trap */
+-			if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
+-			    CurrTime) {
+-				/*
+-				 * Do NOT send the Trap. The hold back time
+-				 * has to run out first.
+-				 */
+-				DoTrapSend = SK_FALSE;
+-			}
+-
+-			/* Check now whether we have to log an Error */
+-			if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
+-			    CurrTime) {
+-				/*
+-				 * Do NOT log the error. The hold back time
+-				 * has to run out first.
+-				 */
+-				DoErrLog = SK_FALSE;
+-			}
+-		}
+-		else {
+-			/* We came from a different state -> Set Begin Time Stamp */
+-			pSen->SenBegErrTS = CurrTime;
+-			pSen->SenErrFlag = SK_SEN_ERR_ERR;
+-		}
+-
+-		if (DoTrapSend) {
+-			/* Set current Time */
+-			pSen->SenLastErrTrapTS = CurrTime;
+-			pSen->SenErrCts++;
+-
+-			/* Queue PNMI Event */
+-			SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
+-				SK_PNMI_EVT_SEN_ERR_UPP :
+-				SK_PNMI_EVT_SEN_ERR_LOW),
+-				ParaLocal);
+-		}
+-
+-		if (DoErrLog) {
+-			/* Set current Time */
+-			pSen->SenLastErrLogTS = CurrTime;
+-
+-			if (pSen->SenType == SK_SEN_TEMP) {
+-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
+-			}
+-			else if (pSen->SenType == SK_SEN_VOLT) {
+-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
+-			}
+-			else {
+-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
+-			}
+-		}
+-	}
+-
+-	/* Check the Value against the thresholds */
+-	/* 2nd: Warning thresholds */
+-	TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
+-	TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
+-		
+-	if (!IsError && (TooHigh || TooLow)) {
+-		/* Error condition is satisfied */
+-		DoTrapSend = SK_TRUE;
+-		DoErrLog = SK_TRUE;
+-
+-		if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
+-			/* This state is the former one */
+-
+-			/* So check first whether we have to send a trap */
+-			if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
+-				/*
+-				 * Do NOT send the Trap. The hold back time
+-				 * has to run out first.
+-				 */
+-				DoTrapSend = SK_FALSE;
+-			}
+-
+-			/* Check now whether we have to log an Error */
+-			if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
+-				/*
+-				 * Do NOT log the error. The hold back time
+-				 * has to run out first.
+-				 */
+-				DoErrLog = SK_FALSE;
+-			}
+-		}
+-		else {
+-			/* We came from a different state -> Set Begin Time Stamp */
+-			pSen->SenBegWarnTS = CurrTime;
+-			pSen->SenErrFlag = SK_SEN_ERR_WARN;
+-		}
+-
+-		if (DoTrapSend) {
+-			/* Set current Time */
+-			pSen->SenLastWarnTrapTS = CurrTime;
+-			pSen->SenWarnCts++;
+-
+-			/* Queue PNMI Event */
+-			SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
+-				SK_PNMI_EVT_SEN_WAR_UPP :
+-				SK_PNMI_EVT_SEN_WAR_LOW),
+-				ParaLocal);
+-		}
+-
+-		if (DoErrLog) {
+-			/* Set current Time */
+-			pSen->SenLastWarnLogTS = CurrTime;
+-
+-			if (pSen->SenType == SK_SEN_TEMP) {
+-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
+-			}
+-			else if (pSen->SenType == SK_SEN_VOLT) {
+-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
+-			}
+-			else {
+-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
+-			}
+-		}
+-	}
+-
+-	/* Check for NO error at all */
+-	if (!IsError && !TooHigh && !TooLow) {
+-		/* Set o.k. Status if no error and no warning condition */
+-		pSen->SenErrFlag = SK_SEN_ERR_OK;
+-	}
+-
+-	/* End of check against the thresholds */
+-
+-	/* Bug fix AF: 16.Aug.2001: Correct the init base
+-	 * of LM80 sensor.
+-	 */
+-	if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
+-
+-        pSen->SenInit = SK_SEN_DYN_INIT_NONE;
+-
+-		if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
+-			/* 5V PCI-IO Voltage */
+-			pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
+-			pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
+-		}
+-		else {
+-			/* 3.3V PCI-IO Voltage */
+-			pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
+-			pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
+-		}
+-	}
+-	
+-#ifdef TEST_ONLY
+-    /* Dynamic thresholds also for VAUX of LM80 sensor */
+-	if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
+-
+-        pSen->SenInit = SK_SEN_DYN_INIT_NONE;
+-
+-		/* 3.3V VAUX Voltage */
+-		if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
+-			pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
+-			pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
+-		}
+-		/* 0V VAUX Voltage */
+-		else {
+-			pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
+-			pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
+-		}
+-	}
+-
+-	/*
+-	 * Check initialization state:
+-	 * The VIO Thresholds need adaption
+-	 */
+-	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
+-	     pSen->SenValue > SK_SEN_WARNLOW2C &&
+-	     pSen->SenValue < SK_SEN_WARNHIGH2) {
+-		pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
+-		pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
+-		pSen->SenInit = SK_TRUE;
+-	}
+-
+-	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
+-	     pSen->SenValue > SK_SEN_WARNLOW2 &&
+-	     pSen->SenValue < SK_SEN_WARNHIGH2C) {
+-		pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
+-		pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
+-		pSen->SenInit = SK_TRUE;
+-	}
+-#endif
+-
+-	if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
+-	}
+-}	/* SkI2cCheckSensor */
+-
+-
+-/*
+- * The only Event to be served is the timeout event
+- *
+- */
+-int	SkI2cEvent(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_U32		Event,	/* Module specific Event */
+-SK_EVPARA	Para)	/* Event specific Parameter */
+-{
+-	int			ReadComplete;
+-	SK_SENSOR	*pSen;
+-	SK_U32		Time;
+-	SK_EVPARA	ParaLocal;
+-	int			i;
+-
+-	/* New case: no sensors */
+-	if (pAC->I2c.MaxSens == 0) {
+-		return(0);
+-	}
+-
+-	switch (Event) {
+-	case SK_I2CEV_IRQ:
+-		pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+-		ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+-
+-		if (ReadComplete) {
+-			/* Check sensor against defined thresholds */
+-			SkI2cCheckSensor(pAC, pSen);
+-
+-			/* Increment Current sensor and set appropriate Timeout */
+-			pAC->I2c.CurrSens++;
+-			if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
+-				pAC->I2c.CurrSens = 0;
+-				Time = SK_I2C_TIM_LONG;
+-			}
+-			else {
+-				Time = SK_I2C_TIM_SHORT;
+-			}
+-
+-			/* Start Timer */
+-			ParaLocal.Para64 = (SK_U64)0;
+-
+-			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+-			
+-			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+-		}
+-        else {
+-			/* Start Timer */
+-			ParaLocal.Para64 = (SK_U64)0;
+-
+-			pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
+-
+-            SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
+-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+-		}
+-		break;
+-	case SK_I2CEV_TIM:
+-		if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
+-
+-			ParaLocal.Para64 = (SK_U64)0;
+-			SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
+-
+-			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+-			ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+-
+-			if (ReadComplete) {
+-				/* Check sensor against defined thresholds */
+-				SkI2cCheckSensor(pAC, pSen);
+-
+-				/* Increment Current sensor and set appropriate Timeout */
+-				pAC->I2c.CurrSens++;
+-				if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
+-					pAC->I2c.CurrSens = 0;
+-					Time = SK_I2C_TIM_LONG;
+-				}
+-				else {
+-					Time = SK_I2C_TIM_SHORT;
+-				}
+-
+-				/* Start Timer */
+-				ParaLocal.Para64 = (SK_U64)0;
+-
+-				pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+-
+-				SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+-					SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+-			}
+-		}
+-		else {
+-			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+-			pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
+-			SK_I2C_STOP(IoC);
+-
+-			/* Increment Current sensor and set appropriate Timeout */
+-			pAC->I2c.CurrSens++;
+-			if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
+-				pAC->I2c.CurrSens = 0;
+-				Time = SK_I2C_TIM_LONG;
+-			}
+-			else {
+-				Time = SK_I2C_TIM_SHORT;
+-			}
+-
+-			/* Start Timer */
+-			ParaLocal.Para64 = (SK_U64)0;
+-
+-			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+-
+-			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+-		}
+-		break;
+-	case SK_I2CEV_CLEAR:
+-		for (i = 0; i < SK_MAX_SENSORS; i++) {
+-			pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
+-			pAC->I2c.SenTable[i].SenErrCts = 0;
+-			pAC->I2c.SenTable[i].SenWarnCts = 0;
+-			pAC->I2c.SenTable[i].SenBegErrTS = 0;
+-			pAC->I2c.SenTable[i].SenBegWarnTS = 0;
+-			pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0;
+-			pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0;
+-			pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0;
+-			pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0;
+-		}
+-		break;
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
+-	}
+-
+-	return(0);
+-}	/* SkI2cEvent*/
+-
+-#endif /* !SK_DIAG */
+diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c
+deleted file mode 100644
+index a204f5b..0000000
+--- a/drivers/net/sk98lin/sklm80.c
++++ /dev/null
+@@ -1,141 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	sklm80.c
+- * Project:	Gigabit Ethernet Adapters, TWSI-Module
+- * Version:	$Revision: 1.22 $
+- * Date:	$Date: 2003/10/20 09:08:21 $
+- * Purpose:	Functions to access Voltage and Temperature Sensor (LM80)
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+-	LM80 functions
+-*/
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. ";
+-#endif
+-
+-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+-#include "h/lm80.h"
+-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+-
+-#define	BREAK_OR_WAIT(pAC,IoC,Event)	break
+-
+-/*
+- * read a sensors value (LM80 specific)
+- *
+- * This function reads a sensors value from the I2C sensor chip LM80.
+- * The sensor is defined by its index into the sensors database in the struct
+- * pAC points to.
+- *
+- * Returns	1 if the read is completed
+- *		0 if the read must be continued (I2C Bus still allocated)
+- */
+-int SkLm80ReadSensor(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context needed in level 1 and 2 */
+-SK_SENSOR	*pSen)	/* Sensor to be read */
+-{
+-	SK_I32		Value;
+-
+-	switch (pSen->SenState) {
+-	case SK_SEN_IDLE:
+-		/* Send address to ADDR register */
+-		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0);
+-
+-		pSen->SenState = SK_SEN_VALUE ;
+-		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
+-	
+-	case SK_SEN_VALUE:
+-		/* Read value from data register */
+-		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
+-		
+-		Value &= 0xff; /* only least significant byte is valid */
+-
+-		/* Do NOT check the Value against the thresholds */
+-		/* Checking is done in the calling instance */
+-
+-		if (pSen->SenType == SK_SEN_VOLT) {
+-			/* Voltage sensor */
+-			pSen->SenValue = Value * SK_LM80_VT_LSB;
+-			pSen->SenState = SK_SEN_IDLE ;
+-			return(1);
+-		}
+-
+-		if (pSen->SenType == SK_SEN_FAN) {
+-			if (Value != 0 && Value != 0xff) {
+-				/* Fan speed counter */
+-				pSen->SenValue = SK_LM80_FAN_FAKTOR/Value;
+-			}
+-			else {
+-				/* Indicate Fan error */
+-				pSen->SenValue = 0;
+-			}
+-			pSen->SenState = SK_SEN_IDLE ;
+-			return(1);
+-		}
+-
+-		/* First: correct the value: it might be negative */
+-		if ((Value & 0x80) != 0) {
+-			/* Value is negative */
+-			Value = Value - 256;
+-		}
+-
+-		/* We have a temperature sensor and need to get the signed extension.
+-		 * For now we get the extension from the last reading, so in the normal
+-		 * case we won't see flickering temperatures.
+-		 */
+-		pSen->SenValue = (Value * SK_LM80_TEMP_LSB) +
+-			(pSen->SenValue % SK_LM80_TEMP_LSB);
+-
+-		/* Send address to ADDR register */
+-		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
+-
+-		pSen->SenState = SK_SEN_VALEXT ;
+-		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
+-	
+-	case SK_SEN_VALEXT:
+-		/* Read value from data register */
+-		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
+-		Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */
+-
+-		/* cut the LSB bit */
+-		pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) *
+-			SK_LM80_TEMP_LSB);
+-
+-		if (pSen->SenValue < 0) {
+-			/* Value negative: The bit value must be subtracted */
+-			pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
+-		}
+-		else {
+-			/* Value positive: The bit value must be added */
+-			pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
+-		}
+-
+-		pSen->SenState = SK_SEN_IDLE ;
+-		return(1);
+-	
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG);
+-		return(1);
+-	}
+-
+-	/* Not completed */
+-	return(0);
+-}
+-
+diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c
+deleted file mode 100644
+index 0275b4f..0000000
+--- a/drivers/net/sk98lin/skqueue.c
++++ /dev/null
+@@ -1,179 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skqueue.c
+- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version:	$Revision: 1.20 $
+- * Date:	$Date: 2003/09/16 13:44:00 $
+- * Purpose:	Management of an event queue.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-
+-/*
+- *	Event queue and dispatcher
+- */
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+-#include "h/skqueue.h"		/* Queue Definitions */
+-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+-
+-#ifdef __C2MAN__
+-/*
+-	Event queue management.
+-
+-	General Description:
+-
+- */
+-intro()
+-{}
+-#endif
+-
+-#define PRINTF(a,b,c)
+-
+-/*
+- * init event queue management
+- *
+- * Must be called during init level 0.
+- */
+-void	SkEventInit(
+-SK_AC	*pAC,	/* Adapter context */
+-SK_IOC	Ioc,	/* IO context */
+-int		Level)	/* Init level */
+-{
+-	switch (Level) {
+-	case SK_INIT_DATA:
+-		pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue;
+-		break;
+-	default:
+-		break;
+-	}
+-}
+-
+-/*
+- * add event to queue
+- */
+-void	SkEventQueue(
+-SK_AC		*pAC,	/* Adapters context */
+-SK_U32		Class,	/* Event Class */
+-SK_U32		Event,	/* Event to be queued */
+-SK_EVPARA	Para)	/* Event parameter */
+-{
+-	pAC->Event.EvPut->Class = Class;
+-	pAC->Event.EvPut->Event = Event;
+-	pAC->Event.EvPut->Para = Para;
+-	
+-	if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
+-		pAC->Event.EvPut = pAC->Event.EvQueue;
+-
+-	if (pAC->Event.EvPut == pAC->Event.EvGet) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
+-	}
+-}
+-
+-/*
+- * event dispatcher
+- *	while event queue is not empty
+- *		get event from queue
+- *		send command to state machine
+- *	end
+- *	return error reported by individual Event function
+- *		0 if no error occured.
+- */
+-int	SkEventDispatcher(
+-SK_AC	*pAC,	/* Adapters Context */
+-SK_IOC	Ioc)	/* Io context */
+-{
+-	SK_EVENTELEM	*pEv;	/* pointer into queue */
+-	SK_U32			Class;
+-	int			Rtv;
+-
+-	pEv = pAC->Event.EvGet;
+-	
+-	PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put);
+-	
+-	while (pEv != pAC->Event.EvPut) {
+-		PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event);
+-
+-		switch (Class = pEv->Class) {
+-#ifndef SK_USE_LAC_EV
+-#ifndef SK_SLIM
+-		case SKGE_RLMT:		/* RLMT Event */
+-			Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-		case SKGE_I2C:		/* I2C Event */
+-			Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-		case SKGE_PNMI:		/* PNMI Event */
+-			Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-#endif	/* not SK_SLIM */
+-#endif	/* not SK_USE_LAC_EV */
+-		case SKGE_DRV:		/* Driver Event */
+-			Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-#ifndef SK_USE_SW_TIMER
+-		case SKGE_HWAC:
+-			Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-#else /* !SK_USE_SW_TIMER */
+-        case SKGE_SWT :
+-			Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-#endif /* !SK_USE_SW_TIMER */
+-#ifdef SK_USE_LAC_EV
+-		case SKGE_LACP :
+-			Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-		case SKGE_RSF :
+-			Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-		case SKGE_MARKER :
+-			Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-		case SKGE_FD :
+-			Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-#endif /* SK_USE_LAC_EV */
+-#ifdef	SK_USE_CSUM
+-		case SKGE_CSUM :
+-			Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para);
+-			break;
+-#endif	/* SK_USE_CSUM */
+-		default :
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG);
+-			Rtv = 0;
+-		}
+-
+-		if (Rtv != 0) {
+-			return(Rtv);
+-		}
+-
+-		if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT])
+-			pEv = pAC->Event.EvQueue;
+-
+-		/* Renew get: it is used in queue_events to detect overruns */
+-		pAC->Event.EvGet = pEv;
+-	}
+-
+-	return(0);
+-}
+-
+-/* End of file */
+diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c
+deleted file mode 100644
+index be8d1cc..0000000
+--- a/drivers/net/sk98lin/skrlmt.c
++++ /dev/null
+@@ -1,3257 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skrlmt.c
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.69 $
+- * Date:	$Date: 2003/04/15 09:39:22 $
+- * Purpose:	Manage links on SK-NET Adapters, esp. redundant ones.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters.
+- * It is mainly intended for adapters with more than one link.
+- * For such adapters, this module realizes Redundant Link ManagemenT (RLMT).
+- *
+- * Include File Hierarchy:
+- *
+- *	"skdrv1st.h"
+- *	"skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef	lint
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell.";
+-#endif	/* !defined(lint) */
+-
+-#define __SKRLMT_C
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif	/* cplusplus */
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-
+-/* defines ********************************************************************/
+-
+-#ifndef SK_HWAC_LINK_LED
+-#define SK_HWAC_LINK_LED(a,b,c,d)
+-#endif	/* !defined(SK_HWAC_LINK_LED) */
+-
+-#ifndef DEBUG
+-#define RLMT_STATIC	static
+-#else	/* DEBUG */
+-#define RLMT_STATIC
+-
+-#ifndef SK_LITTLE_ENDIAN
+-/* First 32 bits */
+-#define OFFS_LO32	1
+-
+-/* Second 32 bits */
+-#define OFFS_HI32	0
+-#else	/* SK_LITTLE_ENDIAN */
+-/* First 32 bits */
+-#define OFFS_LO32	0
+-
+-/* Second 32 bits */
+-#define OFFS_HI32	1
+-#endif	/* SK_LITTLE_ENDIAN */
+-
+-#endif	/* DEBUG */
+-
+-/* ----- Private timeout values ----- */
+-
+-#define SK_RLMT_MIN_TO_VAL			   125000	/* 1/8 sec. */
+-#define SK_RLMT_DEF_TO_VAL			  1000000	/* 1 sec. */
+-#define SK_RLMT_PORTDOWN_TIM_VAL	   900000	/* another 0.9 sec. */
+-#define SK_RLMT_PORTSTART_TIM_VAL	   100000	/* 0.1 sec. */
+-#define SK_RLMT_PORTUP_TIM_VAL		  2500000	/* 2.5 sec. */
+-#define SK_RLMT_SEG_TO_VAL			900000000	/* 15 min. */
+-
+-/* Assume tick counter increment is 1 - may be set OS-dependent. */
+-#ifndef SK_TICK_INCR
+-#define SK_TICK_INCR	SK_CONSTU64(1)
+-#endif	/* !defined(SK_TICK_INCR) */
+-
+-/*
+- * Amount that a time stamp must be later to be recognized as "substantially
+- * later". This is about 1/128 sec, but above 1 tick counter increment.
+- */
+-#define SK_RLMT_BC_DELTA		(1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \
+-									(SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR))
+-
+-/* ----- Private RLMT defaults ----- */
+-
+-#define SK_RLMT_DEF_PREF_PORT	0					/* "Lower" port. */
+-#define SK_RLMT_DEF_MODE 		SK_RLMT_CHECK_LINK	/* Default RLMT Mode. */
+-
+-/* ----- Private RLMT checking states ----- */
+-
+-#define SK_RLMT_RCS_SEG			1		/* RLMT Check State: check seg. */
+-#define SK_RLMT_RCS_START_SEG	2		/* RLMT Check State: start check seg. */
+-#define SK_RLMT_RCS_SEND_SEG	4		/* RLMT Check State: send BPDU packet */
+-#define SK_RLMT_RCS_REPORT_SEG	8		/* RLMT Check State: report seg. */
+-
+-/* ----- Private PORT checking states ----- */
+-
+-#define SK_RLMT_PCS_TX			1		/* Port Check State: check tx. */
+-#define SK_RLMT_PCS_RX			2		/* Port Check State: check rx. */
+-
+-/* ----- Private PORT events ----- */
+-
+-/* Note: Update simulation when changing these. */
+-#define SK_RLMT_PORTSTART_TIM	1100	/* Port start timeout. */
+-#define SK_RLMT_PORTUP_TIM		1101	/* Port can now go up. */
+-#define SK_RLMT_PORTDOWN_RX_TIM	1102	/* Port did not receive once ... */
+-#define SK_RLMT_PORTDOWN		1103	/* Port went down. */
+-#define SK_RLMT_PORTDOWN_TX_TIM	1104	/* Partner did not receive ... */
+-
+-/* ----- Private RLMT events ----- */
+-
+-/* Note: Update simulation when changing these. */
+-#define SK_RLMT_TIM				2100	/* RLMT timeout. */
+-#define SK_RLMT_SEG_TIM			2101	/* RLMT segmentation check timeout. */
+-
+-#define TO_SHORTEN(tim)	((tim) / 2)
+-
+-/* Error numbers and messages. */
+-#define SKERR_RLMT_E001		(SK_ERRBASE_RLMT + 0)
+-#define SKERR_RLMT_E001_MSG	"No Packet."
+-#define SKERR_RLMT_E002		(SKERR_RLMT_E001 + 1)
+-#define SKERR_RLMT_E002_MSG	"Short Packet."
+-#define SKERR_RLMT_E003		(SKERR_RLMT_E002 + 1)
+-#define SKERR_RLMT_E003_MSG	"Unknown RLMT event."
+-#define SKERR_RLMT_E004		(SKERR_RLMT_E003 + 1)
+-#define SKERR_RLMT_E004_MSG	"PortsUp incorrect."
+-#define SKERR_RLMT_E005		(SKERR_RLMT_E004 + 1)
+-#define SKERR_RLMT_E005_MSG	\
+- "Net seems to be segmented (different root bridges are reported on the ports)."
+-#define SKERR_RLMT_E006		(SKERR_RLMT_E005 + 1)
+-#define SKERR_RLMT_E006_MSG	"Duplicate MAC Address detected."
+-#define SKERR_RLMT_E007		(SKERR_RLMT_E006 + 1)
+-#define SKERR_RLMT_E007_MSG	"LinksUp incorrect."
+-#define SKERR_RLMT_E008		(SKERR_RLMT_E007 + 1)
+-#define SKERR_RLMT_E008_MSG	"Port not started but link came up."
+-#define SKERR_RLMT_E009		(SKERR_RLMT_E008 + 1)
+-#define SKERR_RLMT_E009_MSG	"Corrected illegal setting of Preferred Port."
+-#define SKERR_RLMT_E010		(SKERR_RLMT_E009 + 1)
+-#define SKERR_RLMT_E010_MSG	"Ignored illegal Preferred Port."
+-
+-/* LLC field values. */
+-#define LLC_COMMAND_RESPONSE_BIT		1
+-#define LLC_TEST_COMMAND				0xE3
+-#define LLC_UI							0x03
+-
+-/* RLMT Packet fields. */
+-#define	SK_RLMT_DSAP					0
+-#define	SK_RLMT_SSAP					0
+-#define SK_RLMT_CTRL					(LLC_TEST_COMMAND)
+-#define SK_RLMT_INDICATOR0				0x53	/* S */
+-#define SK_RLMT_INDICATOR1				0x4B	/* K */
+-#define SK_RLMT_INDICATOR2				0x2D	/* - */
+-#define SK_RLMT_INDICATOR3				0x52	/* R */
+-#define SK_RLMT_INDICATOR4				0x4C	/* L */
+-#define SK_RLMT_INDICATOR5				0x4D	/* M */
+-#define SK_RLMT_INDICATOR6				0x54	/* T */
+-#define SK_RLMT_PACKET_VERSION			0
+-
+-/* RLMT SPT Flag values. */
+-#define	SK_RLMT_SPT_FLAG_CHANGE			0x01
+-#define	SK_RLMT_SPT_FLAG_CHANGE_ACK		0x80
+-
+-/* RLMT SPT Packet fields. */
+-#define	SK_RLMT_SPT_DSAP				0x42
+-#define	SK_RLMT_SPT_SSAP				0x42
+-#define SK_RLMT_SPT_CTRL				(LLC_UI)
+-#define	SK_RLMT_SPT_PROTOCOL_ID0		0x00
+-#define	SK_RLMT_SPT_PROTOCOL_ID1		0x00
+-#define	SK_RLMT_SPT_PROTOCOL_VERSION_ID	0x00
+-#define	SK_RLMT_SPT_BPDU_TYPE			0x00
+-#define	SK_RLMT_SPT_FLAGS				0x00	/* ?? */
+-#define	SK_RLMT_SPT_ROOT_ID0			0xFF	/* Lowest possible priority. */
+-#define	SK_RLMT_SPT_ROOT_ID1			0xFF	/* Lowest possible priority. */
+-
+-/* Remaining 6 bytes will be the current port address. */
+-#define	SK_RLMT_SPT_ROOT_PATH_COST0		0x00
+-#define	SK_RLMT_SPT_ROOT_PATH_COST1		0x00
+-#define	SK_RLMT_SPT_ROOT_PATH_COST2		0x00
+-#define	SK_RLMT_SPT_ROOT_PATH_COST3		0x00
+-#define	SK_RLMT_SPT_BRIDGE_ID0			0xFF	/* Lowest possible priority. */
+-#define	SK_RLMT_SPT_BRIDGE_ID1			0xFF	/* Lowest possible priority. */
+-
+-/* Remaining 6 bytes will be the current port address. */
+-#define	SK_RLMT_SPT_PORT_ID0			0xFF	/* Lowest possible priority. */
+-#define	SK_RLMT_SPT_PORT_ID1			0xFF	/* Lowest possible priority. */
+-#define	SK_RLMT_SPT_MSG_AGE0			0x00
+-#define	SK_RLMT_SPT_MSG_AGE1			0x00
+-#define	SK_RLMT_SPT_MAX_AGE0			0x00
+-#define	SK_RLMT_SPT_MAX_AGE1			0xFF
+-#define	SK_RLMT_SPT_HELLO_TIME0			0x00
+-#define	SK_RLMT_SPT_HELLO_TIME1			0xFF
+-#define	SK_RLMT_SPT_FWD_DELAY0			0x00
+-#define	SK_RLMT_SPT_FWD_DELAY1			0x40
+-
+-/* Size defines. */
+-#define SK_RLMT_MIN_PACKET_SIZE			34
+-#define SK_RLMT_MAX_PACKET_SIZE			(SK_RLMT_MAX_TX_BUF_SIZE)
+-#define SK_PACKET_DATA_LEN				(SK_RLMT_MAX_PACKET_SIZE - \
+-										SK_RLMT_MIN_PACKET_SIZE)
+-
+-/* ----- RLMT packet types ----- */
+-#define SK_PACKET_ANNOUNCE				1	/* Port announcement. */
+-#define SK_PACKET_ALIVE					2	/* Alive packet to port. */
+-#define SK_PACKET_ADDR_CHANGED			3	/* Port address changed. */
+-#define SK_PACKET_CHECK_TX				4	/* Check your tx line. */
+-
+-#ifdef SK_LITTLE_ENDIAN
+-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \
+-	SK_U8	*_Addr = (SK_U8*)(Addr); \
+-	SK_U16	_Val = (SK_U16)(Val); \
+-	*_Addr++ = (SK_U8)(_Val >> 8); \
+-	*_Addr = (SK_U8)(_Val & 0xFF); \
+-}
+-#endif	/* SK_LITTLE_ENDIAN */
+-
+-#ifdef SK_BIG_ENDIAN
+-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))
+-#endif	/* SK_BIG_ENDIAN */
+-
+-#define AUTONEG_FAILED	SK_FALSE
+-#define AUTONEG_SUCCESS	SK_TRUE
+-
+-
+-/* typedefs *******************************************************************/
+-
+-/* RLMT packet.  Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */
+-typedef struct s_RlmtPacket {
+-	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
+-	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
+-	SK_U8	TypeLen[2];
+-	SK_U8	DSap;
+-	SK_U8	SSap;
+-	SK_U8	Ctrl;
+-	SK_U8	Indicator[7];
+-	SK_U8	RlmtPacketType[2];
+-	SK_U8	Align1[2];
+-	SK_U8	Random[4];				/* Random value of requesting(!) station. */
+-	SK_U8	RlmtPacketVersion[2];	/* RLMT Packet version. */
+-	SK_U8	Data[SK_PACKET_DATA_LEN];
+-} SK_RLMT_PACKET;
+-
+-typedef struct s_SpTreeRlmtPacket {
+-	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
+-	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
+-	SK_U8	TypeLen[2];
+-	SK_U8	DSap;
+-	SK_U8	SSap;
+-	SK_U8	Ctrl;
+-	SK_U8	ProtocolId[2];
+-	SK_U8	ProtocolVersionId;
+-	SK_U8	BpduType;
+-	SK_U8	Flags;
+-	SK_U8	RootId[8];
+-	SK_U8	RootPathCost[4];
+-	SK_U8	BridgeId[8];
+-	SK_U8	PortId[2];
+-	SK_U8	MessageAge[2];
+-	SK_U8	MaxAge[2];
+-	SK_U8	HelloTime[2];
+-	SK_U8	ForwardDelay[2];
+-} SK_SPTREE_PACKET;
+-
+-/* global variables ***********************************************************/
+-
+-SK_MAC_ADDR	SkRlmtMcAddr =	{{0x01,  0x00,  0x5A,  0x52,  0x4C,  0x4D}};
+-SK_MAC_ADDR	BridgeMcAddr =	{{0x01,  0x80,  0xC2,  0x00,  0x00,  0x00}};
+-
+-/* local variables ************************************************************/
+-
+-/* None. */
+-
+-/* functions ******************************************************************/
+-
+-RLMT_STATIC void	SkRlmtCheckSwitch(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	SK_U32	NetIdx);
+-RLMT_STATIC void	SkRlmtCheckSeg(
+-	SK_AC	*pAC,
+-	SK_IOC	IoC,
+-	SK_U32	NetIdx);
+-RLMT_STATIC void	SkRlmtEvtSetNets(
+-	SK_AC		*pAC,
+-	SK_IOC		IoC,
+-	SK_EVPARA	Para);
+-
+-/******************************************************************************
+- *
+- *	SkRlmtInit - initialize data, set state to init
+- *
+- * Description:
+- *
+- *	SK_INIT_DATA
+- *	============
+- *
+- *	This routine initializes all RLMT-related variables to a known state.
+- *	The initial state is SK_RLMT_RS_INIT.
+- *	All ports are initialized to SK_RLMT_PS_INIT.
+- *
+- *
+- *	SK_INIT_IO
+- *	==========
+- *
+- *	Nothing.
+- *
+- *
+- *	SK_INIT_RUN
+- *	===========
+- *
+- *	Determine the adapter's random value.
+- *	Set the hw registers, the "logical MAC address", the
+- *	RLMT multicast address, and eventually the BPDU multicast address.
+- *
+- * Context:
+- *	init, pageable
+- *
+- * Returns:
+- *	Nothing.
+- */
+-void	SkRlmtInit(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC,	/* I/O Context */
+-int		Level)	/* Initialization Level */
+-{
+-	SK_U32		i, j;
+-	SK_U64		Random;
+-	SK_EVPARA	Para;
+-    SK_MAC_ADDR		VirtualMacAddress;
+-    SK_MAC_ADDR		PhysicalAMacAddress;
+-    SK_BOOL		VirtualMacAddressSet;
+-    SK_BOOL		PhysicalAMacAddressSet;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
+-		("RLMT Init level %d.\n", Level))
+-
+-	switch (Level) {
+-	case SK_INIT_DATA:	/* Initialize data structures. */
+-		SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT));
+-
+-		for (i = 0; i < SK_MAX_MACS; i++) {
+-			pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT;
+-			pAC->Rlmt.Port[i].LinkDown = SK_TRUE;
+-			pAC->Rlmt.Port[i].PortDown = SK_TRUE;
+-			pAC->Rlmt.Port[i].PortStarted = SK_FALSE;
+-			pAC->Rlmt.Port[i].PortNoRx = SK_FALSE;
+-			pAC->Rlmt.Port[i].RootIdSet = SK_FALSE;
+-			pAC->Rlmt.Port[i].PortNumber = i;
+-			pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0];
+-			pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i];
+-		}
+-
+-		pAC->Rlmt.NumNets = 1;
+-		for (i = 0; i < SK_MAX_NETS; i++) {
+-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
+-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
+-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
+-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* Automatic. */
+-			/* Just assuming. */
+-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
+-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
+-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
+-			pAC->Rlmt.Net[i].NetNumber = i;
+-		}
+-
+-		pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0];
+-		pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1];
+-#if SK_MAX_NETS > 1
+-		pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1];
+-#endif	/* SK_MAX_NETS > 1 */
+-		break;
+-
+-	case SK_INIT_IO:	/* GIMacsFound first available here. */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
+-			("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound))
+-
+-		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
+-
+-		/* Initialize HW registers? */
+-		if (pAC->GIni.GIMacsFound == 1) {
+-			Para.Para32[0] = SK_RLMT_MODE_CLS;
+-			Para.Para32[1] = 0;
+-			(void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para);
+-		}
+-		break;
+-
+-	case SK_INIT_RUN:
+-		/* Ensure RLMT is set to one net. */
+-		if (pAC->Rlmt.NumNets > 1) {
+-			Para.Para32[0] = 1;
+-			Para.Para32[1] = -1;
+-			SkRlmtEvtSetNets(pAC, IoC, Para);
+-		}
+-
+-		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-			Random = SkOsGetTime(pAC);
+-			*(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random;
+-
+-			for (j = 0; j < 4; j++) {
+-				pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort->
+-					CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j];
+-			}
+-
+-			(void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
+-			
+-			/* Add RLMT MC address. */
+-			(void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT);
+-
+-			if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) {
+-				/* Add BPDU MC address. */
+-				(void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT);
+-			}
+-
+-			(void)SkAddrMcUpdate(pAC, IoC, i);
+-		}
+-
+-    	VirtualMacAddressSet = SK_FALSE;
+-		/* Read virtual MAC address from Control Register File. */
+-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+-			
+-            SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]);
+-            VirtualMacAddressSet |= VirtualMacAddress.a[j];
+-		}
+-    	
+-        PhysicalAMacAddressSet = SK_FALSE;
+-		/* Read physical MAC address for MAC A from Control Register File. */
+-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+-			
+-            SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]);
+-            PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j];
+-		}
+-
+-        /* check if the two mac addresses contain reasonable values */
+-        if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) {
+-
+-            pAC->Rlmt.RlmtOff = SK_TRUE;
+-        }
+-
+-        /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
+-           and the RLMT_LOOKAHEAD macros */
+-        else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) {
+-
+-            pAC->Rlmt.RlmtOff = SK_TRUE;
+-        }
+-		else {
+-			pAC->Rlmt.RlmtOff = SK_FALSE;
+-		}
+-		break;
+-
+-	default:	/* error */
+-		break;
+-	}
+-	return;
+-}	/* SkRlmtInit */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtBuildCheckChain - build the check chain
+- *
+- * Description:
+- *	This routine builds the local check chain:
+- *	- Each port that is up checks the next port.
+- *	- The last port that is up checks the first port that is up.
+- *
+- * Notes:
+- *	- Currently only local ports are considered when building the chain.
+- *	- Currently the SuspectState is just reset;
+- *	  it would be better to save it ...
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtBuildCheckChain(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_U32	NetIdx)	/* Net Number */
+-{
+-	SK_U32			i;
+-	SK_U32			NumMacsUp;
+-	SK_RLMT_PORT *	FirstMacUp;
+-	SK_RLMT_PORT *	PrevMacUp;
+-
+-	FirstMacUp	= NULL;
+-	PrevMacUp	= NULL;
+-	
+-	if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
+-		for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) {
+-			pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
+-		}
+-		return;	/* Done. */
+-	}
+-			
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SkRlmtBuildCheckChain.\n"))
+-
+-	NumMacsUp = 0;
+-
+-	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
+-		pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
+-		pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0;
+-		pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &=
+-			~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX);
+-
+-		/*
+-		 * If more than two links are detected we should consider
+-		 * checking at least two other ports:
+-		 * 1. the next port that is not LinkDown and
+-		 * 2. the next port that is not PortDown.
+-		 */
+-		if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
+-			if (NumMacsUp == 0) {
+-				FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
+-			}
+-			else {
+-				PrevMacUp->PortCheck[
+-					pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr =
+-					pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress;
+-				PrevMacUp->PortCheck[
+-					PrevMacUp->PortsChecked].SuspectTx = SK_FALSE;
+-				PrevMacUp->PortsChecked++;
+-			}
+-			PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
+-			NumMacsUp++;
+-		}
+-	}
+-
+-	if (NumMacsUp > 1) {
+-		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr =
+-			FirstMacUp->AddrPort->CurrentMacAddress;
+-		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx =
+-			SK_FALSE;
+-		PrevMacUp->PortsChecked++;
+-	}
+-
+-#ifdef DEBUG
+-	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Port %d checks %d other ports: %2X.\n", i,
+-				pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked,
+-				pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]))
+-	}
+-#endif	/* DEBUG */
+-
+-	return;
+-}	/* SkRlmtBuildCheckChain */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtBuildPacket - build an RLMT packet
+- *
+- * Description:
+- *	This routine sets up an RLMT packet.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	NULL or pointer to RLMT mbuf
+- */
+-RLMT_STATIC SK_MBUF	*SkRlmtBuildPacket(
+-SK_AC		*pAC,		/* Adapter Context */
+-SK_IOC		IoC,		/* I/O Context */
+-SK_U32		PortNumber,	/* Sending port */
+-SK_U16		PacketType,	/* RLMT packet type */
+-SK_MAC_ADDR	*SrcAddr,	/* Source address */
+-SK_MAC_ADDR	*DestAddr)	/* Destination address */
+-{
+-	int		i;
+-	SK_U16		Length;
+-	SK_MBUF		*pMb;
+-	SK_RLMT_PACKET	*pPacket;
+-
+-#ifdef DEBUG
+-	SK_U8	CheckSrc  = 0;
+-	SK_U8	CheckDest = 0;
+-	
+-	for (i = 0; i < SK_MAC_ADDR_LEN; ++i) {
+-		CheckSrc  |= SrcAddr->a[i];
+-		CheckDest |= DestAddr->a[i];
+-	}
+-
+-	if ((CheckSrc == 0) || (CheckDest == 0)) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,
+-			("SkRlmtBuildPacket: Invalid %s%saddr.\n",
+-			 (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")))
+-	}
+-#endif
+-
+-	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) {
+-		pPacket = (SK_RLMT_PACKET*)pMb->pData;
+-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+-			pPacket->DstAddr[i] = DestAddr->a[i];
+-			pPacket->SrcAddr[i] = SrcAddr->a[i];
+-		}
+-		pPacket->DSap = SK_RLMT_DSAP;
+-		pPacket->SSap = SK_RLMT_SSAP;
+-		pPacket->Ctrl = SK_RLMT_CTRL;
+-		pPacket->Indicator[0] = SK_RLMT_INDICATOR0;
+-		pPacket->Indicator[1] = SK_RLMT_INDICATOR1;
+-		pPacket->Indicator[2] = SK_RLMT_INDICATOR2;
+-		pPacket->Indicator[3] = SK_RLMT_INDICATOR3;
+-		pPacket->Indicator[4] = SK_RLMT_INDICATOR4;
+-		pPacket->Indicator[5] = SK_RLMT_INDICATOR5;
+-		pPacket->Indicator[6] = SK_RLMT_INDICATOR6;
+-
+-		SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]);
+-
+-		for (i = 0; i < 4; i++) {
+-			pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i];
+-		}
+-		
+-		SK_U16_TO_NETWORK_ORDER(
+-			SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]);
+-
+-		for (i = 0; i < SK_PACKET_DATA_LEN; i++) {
+-			pPacket->Data[i] = 0x00;
+-		}
+-
+-		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
+-		pMb->Length = Length;
+-		pMb->PortIdx = PortNumber;
+-		Length -= 14;
+-		SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);
+-
+-		if (PacketType == SK_PACKET_ALIVE) {
+-			pAC->Rlmt.Port[PortNumber].TxHelloCts++;
+-		}
+-	}
+-
+-	return (pMb);
+-}	/* SkRlmtBuildPacket */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtBuildSpanningTreePacket - build spanning tree check packet
+- *
+- * Description:
+- *	This routine sets up a BPDU packet for spanning tree check.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	NULL or pointer to RLMT mbuf
+- */
+-RLMT_STATIC SK_MBUF	*SkRlmtBuildSpanningTreePacket(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-SK_U32	PortNumber)	/* Sending port */
+-{
+-	unsigned			i;
+-	SK_U16				Length;
+-	SK_MBUF				*pMb;
+-	SK_SPTREE_PACKET	*pSPacket;
+-
+-	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=
+-		NULL) {
+-		pSPacket = (SK_SPTREE_PACKET*)pMb->pData;
+-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+-			pSPacket->DstAddr[i] = BridgeMcAddr.a[i];
+-			pSPacket->SrcAddr[i] =
+-				pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
+-		}
+-		pSPacket->DSap = SK_RLMT_SPT_DSAP;
+-		pSPacket->SSap = SK_RLMT_SPT_SSAP;
+-		pSPacket->Ctrl = SK_RLMT_SPT_CTRL;
+-
+-		pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0;
+-		pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1;
+-		pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID;
+-		pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE;
+-		pSPacket->Flags = SK_RLMT_SPT_FLAGS;
+-		pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0;
+-		pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1;
+-		pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0;
+-		pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1;
+-		pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2;
+-		pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3;
+-		pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0;
+-		pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1;
+-
+-		/*
+-		 * Use logical MAC address as bridge ID and filter these packets
+-		 * on receive.
+-		 */
+-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+-			pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] =
+-				pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber].
+-					CurrentMacAddress.a[i];
+-		}
+-		pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0;
+-		pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1;
+-		pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0;
+-		pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1;
+-		pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0;
+-		pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1;
+-		pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0;
+-		pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1;
+-		pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0;
+-		pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1;
+-
+-		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
+-		pMb->Length = Length;
+-		pMb->PortIdx = PortNumber;
+-		Length -= 14;
+-		SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]);
+-
+-		pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++;
+-	}
+-
+-	return (pMb);
+-}	/* SkRlmtBuildSpanningTreePacket */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtSend - build and send check packets
+- *
+- * Description:
+- *	Depending on the RLMT state and the checking state, several packets
+- *	are sent through the indicated port.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	Nothing.
+- */
+-RLMT_STATIC void	SkRlmtSend(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-SK_U32	PortNumber)	/* Sending port */
+-{
+-	unsigned	j;
+-	SK_EVPARA	Para;
+-	SK_RLMT_PORT	*pRPort;
+-
+-	pRPort = &pAC->Rlmt.Port[PortNumber];
+-	if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
+-		if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) {
+-			/* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
+-			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
+-				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+-				&SkRlmtMcAddr)) != NULL) {
+-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+-			}
+-		}
+-		else {
+-			/*
+-			 * Send a directed RLMT packet to all ports that are
+-			 * checked by the indicated port.
+-			 */
+-			for (j = 0; j < pRPort->PortsChecked; j++) {
+-				if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
+-					SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+-					&pRPort->PortCheck[j].CheckAddr)) != NULL) {
+-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+-				}
+-			}
+-		}
+-	}
+-
+-	if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
+-		(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) {
+-		/*
+-		 * Send a BPDU packet to make a connected switch tell us
+-		 * the correct root bridge.
+-		 */
+-		if ((Para.pParaPtr =
+-			SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) {
+-			pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG;
+-			pRPort->RootIdSet = SK_FALSE;
+-
+-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX,
+-				("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber))
+-		}
+-	}
+-	return;
+-}	/* SkRlmtSend */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtPortReceives - check if port is (going) down and bring it up
+- *
+- * Description:
+- *	This routine checks if a port who received a non-BPDU packet
+- *	needs to go up or needs to be stopped going down.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	Nothing.
+- */
+-RLMT_STATIC void	SkRlmtPortReceives(
+-SK_AC	*pAC,			/* Adapter Context */
+-SK_IOC	IoC,			/* I/O Context */
+-SK_U32	PortNumber)		/* Port to check */
+-{
+-	SK_RLMT_PORT	*pRPort;
+-	SK_EVPARA		Para;
+-
+-	pRPort = &pAC->Rlmt.Port[PortNumber];
+-	pRPort->PortNoRx = SK_FALSE;
+-
+-	if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
+-		!(pRPort->CheckingState & SK_RLMT_PCS_TX)) {
+-		/*
+-		 * Port is marked down (rx), but received a non-BPDU packet.
+-		 * Bring it up.
+-		 */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-			("SkRlmtPacketReceive: Received on PortDown.\n"))
+-
+-		pRPort->PortState = SK_RLMT_PS_GOING_UP;
+-		pRPort->GuTimeStamp = SkOsGetTime(pAC);
+-		Para.Para32[0] = PortNumber;
+-		Para.Para32[1] = (SK_U32)-1;
+-		SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
+-			SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para);
+-		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
+-		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
+-		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+-	}	/* PortDown && !SuspectTx */
+-	else if (pRPort->CheckingState & SK_RLMT_PCS_RX) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-			("SkRlmtPacketReceive: Stop bringing port down.\n"))
+-		SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+-		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
+-		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
+-		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+-	}	/* PortGoingDown */
+-
+-	return;
+-}	/* SkRlmtPortReceives */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtPacketReceive - receive a packet for closer examination
+- *
+- * Description:
+- *	This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	Nothing.
+- */
+-RLMT_STATIC void	SkRlmtPacketReceive(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC,	/* I/O Context */
+-SK_MBUF	*pMb)	/* Received packet */
+-{
+-#ifdef xDEBUG
+-	extern	void DumpData(char *p, int size);
+-#endif	/* DEBUG */
+-	int					i;
+-	unsigned			j;
+-	SK_U16				PacketType;
+-	SK_U32				PortNumber;
+-	SK_ADDR_PORT		*pAPort;
+-	SK_RLMT_PORT		*pRPort;
+-	SK_RLMT_PACKET		*pRPacket;
+-	SK_SPTREE_PACKET	*pSPacket;
+-	SK_EVPARA			Para;
+-
+-	PortNumber	= pMb->PortIdx;
+-	pAPort = &pAC->Addr.Port[PortNumber];
+-	pRPort = &pAC->Rlmt.Port[PortNumber];
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-		("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber))
+-
+-	pRPacket = (SK_RLMT_PACKET*)pMb->pData;
+-	pSPacket = (SK_SPTREE_PACKET*)pRPacket;
+-
+-#ifdef xDEBUG
+-	DumpData((char *)pRPacket, 32);
+-#endif	/* DEBUG */
+-
+-	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) {
+-		SkRlmtPortReceives(pAC, IoC, PortNumber);
+-	}
+-	
+-	/* Check destination address. */
+-
+-	if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) &&
+-		!SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) &&
+-		!SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) {
+-
+-		/* Not sent to current MAC or registered MC address => Trash it. */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-			("SkRlmtPacketReceive: Not for me.\n"))
+-
+-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-		return;
+-	}
+-	else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) {
+-
+-		/*
+-		 * Was sent by same port (may happen during port switching
+-		 * or in case of duplicate MAC addresses).
+-		 */
+-
+-		/*
+-		 * Check for duplicate address here:
+-		 * If Packet.Random != My.Random => DupAddr.
+-		 */
+-		for (i = 3; i >= 0; i--) {
+-			if (pRPort->Random[i] != pRPacket->Random[i]) {
+-				break;
+-			}
+-		}
+-
+-		/*
+-		 * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
+-		 * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
+-		 * pRPacket->SSap).
+-		 */
+-		if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP &&
+-			pRPacket->Ctrl == SK_RLMT_CTRL &&
+-			pRPacket->SSap == SK_RLMT_SSAP &&
+-			pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
+-			pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
+-			pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
+-			pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
+-			pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
+-			pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
+-			pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-				("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
+-
+-			/* Error Log entry. */
+-			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG);
+-		}
+-		else {
+-			/* Simply trash it. */
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-				("SkRlmtPacketReceive: Sent by me.\n"))
+-		}
+-
+-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-		return;
+-	}
+-
+-	/* Check SuspectTx entries. */
+-	if (pRPort->PortsSuspect > 0) {
+-		for (j = 0; j < pRPort->PortsChecked; j++) {
+-			if (pRPort->PortCheck[j].SuspectTx &&
+-				SK_ADDR_EQUAL(
+-					pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) {
+-				pRPort->PortCheck[j].SuspectTx = SK_FALSE;
+-				pRPort->PortsSuspect--;
+-				break;
+-			}
+-		}
+-	}
+-
+-	/* Determine type of packet. */
+-	if (pRPacket->DSap == SK_RLMT_DSAP &&
+-		pRPacket->Ctrl == SK_RLMT_CTRL &&
+-		(pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP &&
+-		pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
+-		pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
+-		pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
+-		pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
+-		pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
+-		pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
+-		pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
+-
+-		/* It's an RLMT packet. */
+-		PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) |
+-			pRPacket->RlmtPacketType[1]);
+-
+-		switch (PacketType) {
+-		case SK_PACKET_ANNOUNCE:	/* Not yet used. */
+-#if 0
+-			/* Build the check chain. */
+-			SkRlmtBuildCheckChain(pAC);
+-#endif	/* 0 */
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-				("SkRlmtPacketReceive: Announce.\n"))
+-
+-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-			break;
+-
+-		case SK_PACKET_ALIVE:
+-			if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) {
+-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-					("SkRlmtPacketReceive: Alive Reply.\n"))
+-
+-				if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) ||
+-					SK_ADDR_EQUAL(
+-						pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) {
+-					/* Obviously we could send something. */
+-					if (pRPort->CheckingState & SK_RLMT_PCS_TX) {
+-						pRPort->CheckingState &=  ~SK_RLMT_PCS_TX;
+-						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+-					}
+-
+-					if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
+-						!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
+-						pRPort->PortState = SK_RLMT_PS_GOING_UP;
+-						pRPort->GuTimeStamp = SkOsGetTime(pAC);
+-
+-						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+-
+-						Para.Para32[0] = PortNumber;
+-						Para.Para32[1] = (SK_U32)-1;
+-						SkTimerStart(pAC, IoC, &pRPort->UpTimer,
+-							SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT,
+-							SK_RLMT_PORTUP_TIM, Para);
+-					}
+-				}
+-
+-				/* Mark sending port as alive? */
+-				SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-			}
+-			else {	/* Alive Request Packet. */
+-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-					("SkRlmtPacketReceive: Alive Request.\n"))
+-
+-				pRPort->RxHelloCts++;
+-
+-				/* Answer. */
+-				for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+-					pRPacket->DstAddr[i] = pRPacket->SrcAddr[i];
+-					pRPacket->SrcAddr[i] =
+-						pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
+-				}
+-				pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT;
+-
+-				Para.pParaPtr = pMb;
+-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+-			}
+-			break;
+-
+-		case SK_PACKET_CHECK_TX:
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-				("SkRlmtPacketReceive: Check your tx line.\n"))
+-
+-			/* A port checking us requests us to check our tx line. */
+-			pRPort->CheckingState |= SK_RLMT_PCS_TX;
+-
+-			/* Start PortDownTx timer. */
+-			Para.Para32[0] = PortNumber;
+-			Para.Para32[1] = (SK_U32)-1;
+-			SkTimerStart(pAC, IoC, &pRPort->DownTxTimer,
+-				SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
+-				SK_RLMT_PORTDOWN_TX_TIM, Para);
+-
+-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-
+-			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
+-				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+-				&SkRlmtMcAddr)) != NULL) {
+-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+-			}
+-			break;
+-
+-		case SK_PACKET_ADDR_CHANGED:
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-				("SkRlmtPacketReceive: Address Change.\n"))
+-
+-			/* Build the check chain. */
+-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-			break;
+-
+-		default:
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-				("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
+-
+-			/* RA;:;: ??? */
+-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-		}
+-	}
+-	else if (pSPacket->DSap == SK_RLMT_SPT_DSAP &&
+-		pSPacket->Ctrl == SK_RLMT_SPT_CTRL &&
+-		(pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-			("SkRlmtPacketReceive: BPDU Packet.\n"))
+-
+-		/* Spanning Tree packet. */
+-		pRPort->RxSpHelloCts++;
+-
+-		if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt.
+-			Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) {
+-			/*
+-			 * Check segmentation if a new root bridge is set and
+-			 * the segmentation check is not currently running.
+-			 */
+-			if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) &&
+-				(pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
+-				(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG)
+-				!= 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState &
+-				SK_RLMT_RCS_SEG) == 0) {
+-				pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
+-					SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
+-			}
+-
+-			/* Store tree view of this port. */
+-			for (i = 0; i < 8; i++) {
+-				pRPort->Root.Id[i] = pSPacket->RootId[i];
+-			}
+-			pRPort->RootIdSet = SK_TRUE;
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
+-				("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+-					PortNumber,
+-					pRPort->Root.Id[0], pRPort->Root.Id[1],
+-					pRPort->Root.Id[2], pRPort->Root.Id[3],
+-					pRPort->Root.Id[4], pRPort->Root.Id[5],
+-					pRPort->Root.Id[6], pRPort->Root.Id[7]))
+-		}
+-
+-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-		if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState &
+-			SK_RLMT_RCS_REPORT_SEG) != 0) {
+-			SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber);
+-		}
+-	}
+-	else {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+-			("SkRlmtPacketReceive: Unknown Packet Type.\n"))
+-
+-		/* Unknown packet. */
+-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-	}
+-	return;
+-}	/* SkRlmtPacketReceive */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtCheckPort - check if a port works
+- *
+- * Description:
+- *	This routine checks if a port whose link is up received something
+- *	and if it seems to transmit successfully.
+- *
+- *	# PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
+- *	# PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
+- *	# RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
+- *
+- *	if (Rx - RxBpdu == 0) {	# No rx.
+- *		if (state == PsUp) {
+- *			PortCheckingState |= ChkRx
+- *		}
+- *		if (ModeCheckSeg && (Timeout ==
+- *			TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
+- *			RlmtCheckingState |= ChkSeg)
+- *			PortCheckingState |= ChkSeg
+- *		}
+- *		NewTimeout = TO_SHORTEN(Timeout)
+- *		if (NewTimeout < RLMT_MIN_TIMEOUT) {
+- *			NewTimeout = RLMT_MIN_TIMEOUT
+- *			PortState = PsDown
+- *			...
+- *		}
+- *	}
+- *	else {	# something was received
+- *		# Set counter to 0 at LinkDown?
+- *		#   No - rx may be reported after LinkDown ???
+- *		PortCheckingState &= ~ChkRx
+- *		NewTimeout = RLMT_DEFAULT_TIMEOUT
+- *		if (RxAck == 0) {
+- *			possible reasons:
+- *			is my tx line bad? --
+- *				send RLMT multicast and report
+- *				back internally? (only possible
+- *				between ports on same adapter)
+- *		}
+- *		if (RxChk == 0) {
+- *			possible reasons:
+- *			- tx line of port set to check me
+- *			  maybe bad
+- *			- no other port/adapter available or set
+- *			  to check me
+- *			- adapter checking me has a longer
+- *			  timeout
+- *			??? anything that can be done here?
+- *		}
+- *	}
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	New timeout value.
+- */
+-RLMT_STATIC SK_U32	SkRlmtCheckPort(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-SK_U32	PortNumber)	/* Port to check */
+-{
+-	unsigned		i;
+-	SK_U32			NewTimeout;
+-	SK_RLMT_PORT	*pRPort;
+-	SK_EVPARA		Para;
+-
+-	pRPort = &pAC->Rlmt.Port[PortNumber];
+-
+-	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
+-				PortNumber, pRPort->PacketsPerTimeSlot))
+-
+-		/*
+-		 * Check segmentation if there was no receive at least twice
+-		 * in a row (PortNoRx is already set) and the segmentation
+-		 * check is not currently running.
+-		 */
+-
+-		if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
+-			(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
+-			!(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) {
+-			pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
+-				SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
+-		}
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
+-				pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX))
+-
+-		if (pRPort->PortState != SK_RLMT_PS_DOWN) {
+-			NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue);
+-			if (NewTimeout < SK_RLMT_MIN_TO_VAL) {
+-				NewTimeout = SK_RLMT_MIN_TO_VAL;
+-			}
+-
+-			if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
+-				Para.Para32[0] = PortNumber;
+-				pRPort->CheckingState |= SK_RLMT_PCS_RX;
+-
+-				/*
+-				 * What shall we do if the port checked by this one receives
+-				 * our request frames?  What's bad - our rx line or his tx line?
+-				 */
+-				Para.Para32[1] = (SK_U32)-1;
+-				SkTimerStart(pAC, IoC, &pRPort->DownRxTimer,
+-					SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
+-					SK_RLMT_PORTDOWN_RX_TIM, Para);
+-
+-				for (i = 0; i < pRPort->PortsChecked; i++) {
+-					if (pRPort->PortCheck[i].SuspectTx) {
+-						continue;
+-					}
+-					pRPort->PortCheck[i].SuspectTx = SK_TRUE;
+-					pRPort->PortsSuspect++;
+-					if ((Para.pParaPtr =
+-						SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX,
+-							&pAC->Addr.Port[PortNumber].CurrentMacAddress,
+-							&pRPort->PortCheck[i].CheckAddr)) != NULL) {
+-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+-					}
+-				}
+-			}
+-		}
+-		else {	/* PortDown -- or all partners suspect. */
+-			NewTimeout = SK_RLMT_DEF_TO_VAL;
+-		}
+-		pRPort->PortNoRx = SK_TRUE;
+-	}
+-	else {	/* A non-BPDU packet was received. */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
+-				PortNumber,
+-				pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot,
+-				pRPort->PacketsPerTimeSlot))
+-		
+-		SkRlmtPortReceives(pAC, IoC, PortNumber);
+-		if (pAC->Rlmt.CheckSwitch) {
+-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+-		}
+-
+-		NewTimeout = SK_RLMT_DEF_TO_VAL;
+-	}
+-
+-	return (NewTimeout);
+-}	/* SkRlmtCheckPort */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
+- *
+- * Description:
+- *	This routine selects the port that received a broadcast frame
+- *	substantially later than all other ports.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL	SkRlmtSelectBcRx(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-SK_U32	Active,		/* Active port */
+-SK_U32	PrefPort,	/* Preferred port */
+-SK_U32	*pSelect)	/* New active port */
+-{
+-	SK_U64		BcTimeStamp;
+-	SK_U32		i;
+-	SK_BOOL		PortFound;
+-
+-	BcTimeStamp = 0;	/* Not totally necessary, but feeling better. */
+-	PortFound = SK_FALSE;
+-	
+-	/* Select port with the latest TimeStamp. */
+-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
+-				i,
+-   				pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx,
+-				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32),
+-				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)))
+-
+-		if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) {
+-			if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) {
+-				BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp;
+-				*pSelect = i;
+-				PortFound = SK_TRUE;
+-			}
+-		}
+-	}
+-
+-	if (PortFound) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Port %d received the last broadcast.\n", *pSelect))
+-
+-		/* Look if another port's time stamp is similar. */
+-		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-			if (i == *pSelect) {
+-				continue;
+-			}
+-			if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx &&
+-				(pAC->Rlmt.Port[i].BcTimeStamp >
+-				 BcTimeStamp - SK_RLMT_BC_DELTA ||
+-				pAC->Rlmt.Port[i].BcTimeStamp +
+-				 SK_RLMT_BC_DELTA > BcTimeStamp)) {
+-				PortFound = SK_FALSE;
+-				
+-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-					("Port %d received a broadcast at a similar time.\n", i))
+-				break;
+-			}
+-		}
+-	}
+-
+-#ifdef DEBUG
+-	if (PortFound) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
+-			 "latest broadcast (%u).\n",
+-				*pSelect,
+-				BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp))
+-	}
+-#endif	/* DEBUG */
+-
+-	return (PortFound);
+-}	/* SkRlmtSelectBcRx */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
+- *
+- * Description:
+- *	This routine selects a good port (it is PortUp && !SuspectRx).
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL	SkRlmtSelectNotSuspect(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-SK_U32	Active,		/* Active port */
+-SK_U32	PrefPort,	/* Preferred port */
+-SK_U32	*pSelect)	/* New active port */
+-{
+-	SK_U32		i;
+-	SK_BOOL		PortFound;
+-
+-	PortFound = SK_FALSE;
+-
+-	/* Select first port that is PortUp && !SuspectRx. */
+-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-		if (!pAC->Rlmt.Port[i].PortDown &&
+-			!(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) {
+-			*pSelect = i;
+-			if (!pAC->Rlmt.Port[Active].PortDown &&
+-				!(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) {
+-				*pSelect = Active;
+-			}
+-			if (!pAC->Rlmt.Port[PrefPort].PortDown &&
+-				!(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) {
+-				*pSelect = PrefPort;
+-			}
+-			PortFound = SK_TRUE;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-				("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
+-					*pSelect))
+-			break;
+-		}
+-	}
+-	return (PortFound);
+-}	/* SkRlmtSelectNotSuspect */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
+- *
+- * Description:
+- *	This routine selects a port that is up.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL	SkRlmtSelectUp(
+-SK_AC	*pAC,			/* Adapter Context */
+-SK_IOC	IoC,			/* I/O Context */
+-SK_U32	Active,			/* Active port */
+-SK_U32	PrefPort,		/* Preferred port */
+-SK_U32	*pSelect,		/* New active port */
+-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
+-{
+-	SK_U32		i;
+-	SK_BOOL		PortFound;
+-
+-	PortFound = SK_FALSE;
+-
+-	/* Select first port that is PortUp. */
+-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP &&
+-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+-			*pSelect = i;
+-			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP &&
+-				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
+-				*pSelect = Active;
+-			}
+-			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP &&
+-				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
+-				*pSelect = PrefPort;
+-			}
+-			PortFound = SK_TRUE;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-				("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect))
+-			break;
+-		}
+-	}
+-	return (PortFound);
+-}	/* SkRlmtSelectUp */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
+- *
+- * Description:
+- *	This routine selects the port that is going up for the longest time.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL	SkRlmtSelectGoingUp(
+-SK_AC	*pAC,			/* Adapter Context */
+-SK_IOC	IoC,			/* I/O Context */
+-SK_U32	Active,			/* Active port */
+-SK_U32	PrefPort,		/* Preferred port */
+-SK_U32	*pSelect,		/* New active port */
+-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
+-{
+-	SK_U64		GuTimeStamp;
+-	SK_U32		i;
+-	SK_BOOL		PortFound;
+-
+-	GuTimeStamp = 0;
+-	PortFound = SK_FALSE;
+-
+-	/* Select port that is PortGoingUp for the longest time. */
+-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
+-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+-			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
+-			*pSelect = i;
+-			PortFound = SK_TRUE;
+-			break;
+-		}
+-	}
+-
+-	if (!PortFound) {
+-		return (SK_FALSE);
+-	}
+-
+-	for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
+-			pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp &&
+-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+-			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
+-			*pSelect = i;
+-		}
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect))
+-	return (SK_TRUE);
+-}	/* SkRlmtSelectGoingUp */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
+- *
+- * Description:
+- *	This routine selects a port that is down.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL	SkRlmtSelectDown(
+-SK_AC	*pAC,			/* Adapter Context */
+-SK_IOC	IoC,			/* I/O Context */
+-SK_U32	Active,			/* Active port */
+-SK_U32	PrefPort,		/* Preferred port */
+-SK_U32	*pSelect,		/* New active port */
+-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
+-{
+-	SK_U32		i;
+-	SK_BOOL		PortFound;
+-
+-	PortFound = SK_FALSE;
+-
+-	/* Select first port that is PortDown. */
+-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN &&
+-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+-			*pSelect = i;
+-			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN &&
+-				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
+-				*pSelect = Active;
+-			}
+-			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN &&
+-				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
+-				*pSelect = PrefPort;
+-			}
+-			PortFound = SK_TRUE;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-				("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect))
+-			break;
+-		}
+-	}
+-	return (PortFound);
+-}	/* SkRlmtSelectDown */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtCheckSwitch - select new active port and switch to it
+- *
+- * Description:
+- *	This routine decides which port should be the active one and queues
+- *	port switching if necessary.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	Nothing.
+- */
+-RLMT_STATIC void	SkRlmtCheckSwitch(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC,	/* I/O Context */
+-SK_U32	NetIdx)	/* Net index */
+-{
+-	SK_EVPARA	Para;
+-	SK_U32		Active;
+-	SK_U32		PrefPort;
+-	SK_U32		i;
+-	SK_BOOL		PortFound;
+-
+-	Active = pAC->Rlmt.Net[NetIdx].ActivePort;	/* Index of active port. */
+-	PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort;	/* Index of preferred port. */
+-	PortFound = SK_FALSE;
+-	pAC->Rlmt.CheckSwitch = SK_FALSE;
+-
+-#if 0	/* RW 2001/10/18 - active port becomes always prefered one */
+-	if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */
+-		/* disable auto-fail back */
+-		PrefPort = Active;
+-	}
+-#endif
+-
+-	if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) {
+-		/* Last link went down - shut down the net. */
+-		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN;
+-		Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP;
+-		Para.Para32[1] = NetIdx;
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para);
+-
+-		Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+-			Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
+-		Para.Para32[1] = NetIdx;
+-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
+-		return;
+-	}	/* pAC->Rlmt.LinksUp == 0 */
+-	else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 &&
+-		pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) {
+-		/* First link came up - get the net up. */
+-		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP;
+-
+-		/*
+-		 * If pAC->Rlmt.ActivePort != Para.Para32[0],
+-		 * the DRV switches to the port that came up.
+-		 */
+-		for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
+-			if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
+-				if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) {
+-					i = Active;
+-				}
+-				if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) {
+-					i = PrefPort;
+-				}
+-				PortFound = SK_TRUE;
+-				break;
+-			}
+-		}
+-
+-		if (PortFound) {
+-			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
+-			Para.Para32[1] = NetIdx;
+-			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
+-
+-			pAC->Rlmt.Net[NetIdx].ActivePort = i;
+-			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
+-			Para.Para32[1] = NetIdx;
+-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
+-
+-			if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+-				(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
+-				pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
+-				SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
+-				CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
+-				/*
+-				 * Send announce packet to RLMT multicast address to force
+-				 * switches to learn the new location of the logical MAC address.
+-				 */
+-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+-			}
+-		}
+-		else {
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG);
+-		}
+-
+-		return;
+-	}	/* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
+-	else {	/* Cannot be reached in dual-net mode. */
+-		Para.Para32[0] = Active;
+-
+-		/*
+-		 * Preselection:
+-		 *	If RLMT Mode != CheckLinkState
+-		 *		select port that received a broadcast frame substantially later
+-		 *		than all other ports
+-		 *	else select first port that is not SuspectRx
+-		 *	else select first port that is PortUp
+-		 *	else select port that is PortGoingUp for the longest time
+-		 *	else select first port that is PortDown
+-		 *	else stop.
+-		 *
+-		 * For the preselected port:
+-		 *	If ActivePort is equal in quality, select ActivePort.
+-		 *
+-		 *	If PrefPort is equal in quality, select PrefPort.
+-		 *
+-		 *	If ActivePort != SelectedPort,
+-		 *		If old ActivePort is LinkDown,
+-		 *			SwitchHard
+-		 *		else
+-		 *			SwitchSoft
+-		 */
+-		/* check of ChgBcPrio flag added */
+-		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
+-			(!pAC->Rlmt.Net[0].ChgBcPrio)) {
+-			
+-			if (!PortFound) {
+-				PortFound = SkRlmtSelectBcRx(
+-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+-			}
+-
+-			if (!PortFound) {
+-				PortFound = SkRlmtSelectNotSuspect(
+-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+-			}
+-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
+-
+-		/* with changed priority for last broadcast received */
+-		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
+-			(pAC->Rlmt.Net[0].ChgBcPrio)) {
+-			if (!PortFound) {
+-				PortFound = SkRlmtSelectNotSuspect(
+-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+-			}
+-
+-			if (!PortFound) {
+-				PortFound = SkRlmtSelectBcRx(
+-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+-			}
+-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
+-
+-		if (!PortFound) {
+-			PortFound = SkRlmtSelectUp(
+-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
+-		}
+-
+-		if (!PortFound) {
+-			PortFound = SkRlmtSelectUp(
+-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
+-		}
+-
+-		if (!PortFound) {
+-			PortFound = SkRlmtSelectGoingUp(
+-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
+-		}
+-
+-		if (!PortFound) {
+-			PortFound = SkRlmtSelectGoingUp(
+-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
+-		}
+-
+-		if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) {
+-			if (!PortFound) {
+-				PortFound = SkRlmtSelectDown(pAC, IoC,
+-					Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
+-			}
+-
+-			if (!PortFound) {
+-				PortFound = SkRlmtSelectDown(pAC, IoC,
+-					Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
+-			}
+-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
+-
+-		if (PortFound) {
+-
+-			if (Para.Para32[1] != Active) {
+-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-					("Active: %d, Para1: %d.\n", Active, Para.Para32[1]))
+-				pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1];
+-				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+-					Port[Para.Para32[0]]->PortNumber;
+-				Para.Para32[1] = pAC->Rlmt.Net[NetIdx].
+-					Port[Para.Para32[1]]->PortNumber;
+-				SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE);
+-				if (pAC->Rlmt.Port[Active].LinkDown) {
+-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para);
+-				}
+-				else {
+-					SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
+-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para);
+-				}
+-				Para.Para32[1] = NetIdx;
+-				Para.Para32[0] =
+-					pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber;
+-				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
+-				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+-					Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
+-				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
+-				if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+-					(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0],
+-					SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress,
+-					&SkRlmtMcAddr)) != NULL) {
+-					/*
+-					 * Send announce packet to RLMT multicast address to force
+-					 * switches to learn the new location of the logical
+-					 * MAC address.
+-					 */
+-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+-				}	/* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
+-			}	/* Para.Para32[1] != Active */
+-		}	/* PortFound */
+-		else {
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG);
+-		}
+-	}	/* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
+-	return;
+-}	/* SkRlmtCheckSwitch */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtCheckSeg - Report if segmentation is detected
+- *
+- * Description:
+- *	This routine checks if the ports see different root bridges and reports
+- *	segmentation in such a case.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	Nothing.
+- */
+-RLMT_STATIC void	SkRlmtCheckSeg(
+-SK_AC	*pAC,	/* Adapter Context */
+-SK_IOC	IoC,	/* I/O Context */
+-SK_U32	NetIdx)	/* Net number */
+-{
+-	SK_EVPARA	Para;
+-	SK_RLMT_NET	*pNet;
+-	SK_U32		i, j;
+-	SK_BOOL		Equal;
+-
+-	pNet = &pAC->Rlmt.Net[NetIdx];
+-	pNet->RootIdSet = SK_FALSE;
+-	Equal = SK_TRUE;
+-
+-	for (i = 0; i < pNet->NumPorts; i++) {
+-		if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) {
+-			continue;
+-		}
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
+-			("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i,
+-				pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1],
+-				pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3],
+-				pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5],
+-				pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]))
+-
+-		if (!pNet->RootIdSet) {
+-			pNet->Root = pNet->Port[i]->Root;
+-			pNet->RootIdSet = SK_TRUE;
+-			continue;
+-		}
+-
+-		for (j = 0; j < 8; j ++) {
+-			Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j];
+-			if (!Equal) {
+-				break;
+-			}
+-		}
+-		
+-		if (!Equal) {
+-			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG);
+-			Para.Para32[0] = NetIdx;
+-			Para.Para32[1] = (SK_U32)-1;
+-			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para);
+-
+-			pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG;
+-
+-			/* 2000-03-06 RA: New. */
+-			Para.Para32[0] = NetIdx;
+-			Para.Para32[1] = (SK_U32)-1;
+-			SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL,
+-				SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
+-			break;
+-		}
+-	}	/* for (i = 0; i < pNet->NumPorts; i++) */
+-
+-	/* 2000-03-06 RA: Moved here. */
+-	/* Segmentation check not running anymore. */
+-	pNet->CheckingState &= ~SK_RLMT_RCS_SEG;
+-
+-}	/* SkRlmtCheckSeg */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtPortStart - initialize port variables and start port
+- *
+- * Description:
+- *	This routine initializes a port's variables and issues a PORT_START
+- *	to the HWAC module.  This handles retries if the start fails or the
+- *	link eventually goes down.
+- *
+- * Context:
+- *	runtime, pageable?
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtPortStart(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-SK_U32	PortNumber)	/* Port number */
+-{
+-	SK_EVPARA	Para;
+-
+-	pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN;
+-	pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE;
+-	pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE;
+-	pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE;
+-	pAC->Rlmt.Port[PortNumber].CheckingState = 0;
+-	pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
+-	Para.Para32[0] = PortNumber;
+-	Para.Para32[1] = (SK_U32)-1;
+-	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+-}	/* SkRlmtPortStart */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtPortStartTim - PORT_START_TIM
+- *
+- * Description:
+- *	This routine handles PORT_START_TIM events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtPortStartTim(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
+-{
+-	SK_U32			i;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+-		if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	/*
+-	 * Used to start non-preferred ports if the preferred one
+-	 * does not come up.
+-	 * This timeout needs only be set when starting the first
+-	 * (preferred) port.
+-	 */
+-	if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
+-		/* PORT_START failed. */
+-		for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) {
+-			if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) {
+-				SkRlmtPortStart(pAC, IoC,
+-					pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber);
+-			}
+-		}
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
+-}	/* SkRlmtEvtPortStartTim */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtLinkUp - LINK_UP
+- *
+- * Description:
+- *	This routine handles LLINK_UP events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtLinkUp(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
+-{
+-	SK_U32			i;
+-	SK_RLMT_PORT	*pRPort;
+-	SK_EVPARA		Para2;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+-	if (!pRPort->PortStarted) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG);
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-				("SK_RLMT_LINK_UP Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (!pRPort->LinkDown) {
+-		/* RA;:;: Any better solution? */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_LINK_UP Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
+-	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+-	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+-
+-	/* Do something if timer already fired? */
+-
+-	pRPort->LinkDown = SK_FALSE;
+-	pRPort->PortState = SK_RLMT_PS_GOING_UP;
+-	pRPort->GuTimeStamp = SkOsGetTime(pAC);
+-	pRPort->BcTimeStamp = 0;
+-	pRPort->Net->LinksUp++;
+-	if (pRPort->Net->LinksUp == 1) {
+-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE);
+-	}
+-	else {
+-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
+-	}
+-
+-	for (i = 0; i < pRPort->Net->NumPorts; i++) {
+-		if (!pRPort->Net->Port[i]->PortStarted) {
+-			SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber);
+-		}
+-	}
+-
+-	SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+-
+-	if (pRPort->Net->LinksUp >= 2) {
+-		if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
+-			/* Build the check chain. */
+-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+-		}
+-	}
+-
+-	/* If the first link comes up, start the periodical RLMT timeout. */
+-	if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 &&
+-		(pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) {
+-		Para2.Para32[0] = pRPort->Net->NetNumber;
+-		Para2.Para32[1] = (SK_U32)-1;
+-		SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer,
+-			pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2);
+-	}
+-
+-	Para2 = Para;
+-	Para2.Para32[1] = (SK_U32)-1;
+-	SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
+-		SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2);
+-	
+-	/* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
+-	if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+-		(pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
+-		(Para2.pParaPtr =
+-			SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
+-			&pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
+-		) != NULL) {
+-		/* Send "new" packet to RLMT multicast address. */
+-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
+-	}
+-
+-	if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) {
+-		if ((Para2.pParaPtr =
+-			SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) {
+-			pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE;
+-			pRPort->Net->CheckingState |=
+-				SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
+-
+-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
+-
+-			Para.Para32[1] = (SK_U32)-1;
+-			SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer,
+-				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
+-		}
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_LINK_UP Event END.\n"))
+-}	/* SkRlmtEvtLinkUp */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtPortUpTim - PORT_UP_TIM
+- *
+- * Description:
+- *	This routine handles PORT_UP_TIM events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtPortUpTim(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
+-{
+-	SK_RLMT_PORT	*pRPort;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+-	if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]))
+-		return;
+-	}
+-
+-	pRPort->PortDown = SK_FALSE;
+-	pRPort->PortState = SK_RLMT_PS_UP;
+-	pRPort->Net->PortsUp++;
+-	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
+-		if (pAC->Rlmt.NumNets <= 1) {
+-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+-		}
+-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para);
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PORTUP_TIM Event END.\n"))
+-}	/* SkRlmtEvtPortUpTim */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtPortDownTim - PORT_DOWN_*
+- *
+- * Description:
+- *	This routine handles PORT_DOWN_* events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtPortDownX(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_U32		Event,	/* Event code */
+-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
+-{
+-	SK_RLMT_PORT	*pRPort;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
+-			Para.Para32[0], Event))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+-	if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM &&
+-		!(pRPort->CheckingState & SK_RLMT_PCS_TX))) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event))
+-		return;
+-	}
+-	
+-	/* Stop port's timers. */
+-	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
+-	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+-	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+-
+-	if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) {
+-		pRPort->PortState = SK_RLMT_PS_DOWN;
+-	}
+-
+-	if (!pRPort->PortDown) {
+-		pRPort->Net->PortsUp--;
+-		pRPort->PortDown = SK_TRUE;
+-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para);
+-	}
+-
+-	pRPort->PacketsPerTimeSlot = 0;
+-	/* pRPort->DataPacketsPerTimeSlot = 0; */
+-	pRPort->BpduPacketsPerTimeSlot = 0;
+-	pRPort->BcTimeStamp = 0;
+-
+-	/*
+-	 * RA;:;: To be checked:
+-	 * - actions at RLMT_STOP: We should not switch anymore.
+-	 */
+-	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
+-		if (Para.Para32[0] ==
+-			pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) {
+-			/* Active Port went down. */
+-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+-		}
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event))
+-}	/* SkRlmtEvtPortDownX */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtLinkDown - LINK_DOWN
+- *
+- * Description:
+- *	This routine handles LINK_DOWN events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtLinkDown(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
+-{
+-	SK_RLMT_PORT	*pRPort;
+-
+-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+-	if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
+-		pRPort->Net->LinksUp--;
+-		pRPort->LinkDown = SK_TRUE;
+-		pRPort->PortState = SK_RLMT_PS_LINK_DOWN;
+-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF);
+-
+-		if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) {
+-			/* Build the check chain. */
+-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+-		}
+-
+-		/* Ensure that port is marked down. */
+-		Para.Para32[1] = -1;
+-		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para);
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_LINK_DOWN Event END.\n"))
+-}	/* SkRlmtEvtLinkDown */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtPortAddr - PORT_ADDR
+- *
+- * Description:
+- *	This routine handles PORT_ADDR events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtPortAddr(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
+-{
+-	SK_U32			i, j;
+-	SK_RLMT_PORT	*pRPort;
+-	SK_MAC_ADDR		*pOldMacAddr;
+-	SK_MAC_ADDR		*pNewMacAddr;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	/* Port's physical MAC address changed. */
+-	pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress;
+-	pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress;
+-
+-	/*
+-	 * NOTE: This is not scalable for solutions where ports are
+-	 *	 checked remotely.  There, we need to send an RLMT
+-	 *	 address change packet - and how do we ensure delivery?
+-	 */
+-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-		pRPort = &pAC->Rlmt.Port[i];
+-		for (j = 0; j < pRPort->PortsChecked; j++) {
+-			if (SK_ADDR_EQUAL(
+-				pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) {
+-				pRPort->PortCheck[j].CheckAddr = *pNewMacAddr;
+-			}
+-		}
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_PORT_ADDR Event END.\n"))
+-}	/* SkRlmtEvtPortAddr */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtStart - START
+- *
+- * Description:
+- *	This routine handles START events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtStart(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+-{
+-	SK_EVPARA	Para2;
+-	SK_U32		PortIdx;
+-	SK_U32		PortNumber;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_START Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad NetNumber %d.\n", Para.Para32[0]))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_START Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_START Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("All nets should have been started.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_START Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >=
+-		pAC->Rlmt.Net[Para.Para32[0]].NumPorts) {
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG);
+-
+-		/* Change PrefPort to internal default. */
+-		Para2.Para32[0] = 0xFFFFFFFF;
+-		Para2.Para32[1] = Para.Para32[0];
+-		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2);
+-	}
+-
+-	PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort;
+-	PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber;
+-
+-	pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0;
+-	pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0;
+-	pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0;
+-	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN;
+-
+-	/* Start preferred port. */
+-	SkRlmtPortStart(pAC, IoC, PortNumber);
+-
+-	/* Start Timer (for first port only). */
+-	Para2.Para32[0] = PortNumber;
+-	Para2.Para32[1] = (SK_U32)-1;
+-	SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer,
+-		SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2);
+-
+-	pAC->Rlmt.NetsStarted++;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_START Event END.\n"))
+-}	/* SkRlmtEvtStart */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtStop - STOP
+- *
+- * Description:
+- *	This routine handles STOP events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtStop(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+-{
+-	SK_EVPARA	Para2;
+-	SK_U32		PortNumber;
+-	SK_U32		i;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_STOP Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad NetNumber %d.\n", Para.Para32[0]))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_STOP Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_STOP Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (pAC->Rlmt.NetsStarted == 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("All nets are stopped.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_STOP Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	/* Stop RLMT timers. */
+-	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer);
+-	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer);
+-
+-	/* Stop net. */
+-	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT;
+-	pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE;
+-	Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL;
+-	Para2.Para32[1] = Para.Para32[0];			/* Net# */
+-	SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2);
+-
+-	/* Stop ports. */
+-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+-		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
+-		if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) {
+-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer);
+-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer);
+-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer);
+-
+-			pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT;
+-			pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
+-			pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE;
+-			Para2.Para32[0] = PortNumber;
+-			Para2.Para32[1] = (SK_U32)-1;
+-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2);
+-		}
+-	}
+-
+-	pAC->Rlmt.NetsStarted--;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_STOP Event END.\n"))
+-}	/* SkRlmtEvtStop */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtTim - TIM
+- *
+- * Description:
+- *	This routine handles TIM events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtTim(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+-{
+-	SK_RLMT_PORT	*pRPort;
+-	SK_U32			Timeout;
+-	SK_U32			NewTimeout;
+-	SK_U32			PortNumber;
+-	SK_U32			i;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_TIM Event BEGIN.\n"))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_TIM Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 ||
+-		pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) {
+-		/* Mode changed or all links down: No more link checking. */
+-		return;
+-	}
+-
+-#if 0
+-	pAC->Rlmt.SwitchCheckCounter--;
+-	if (pAC->Rlmt.SwitchCheckCounter == 0) {
+-		pAC->Rlmt.SwitchCheckCounter;
+-	}
+-#endif	/* 0 */
+-
+-	NewTimeout = SK_RLMT_DEF_TO_VAL;
+-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+-		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
+-		pRPort = &pAC->Rlmt.Port[PortNumber];
+-		if (!pRPort->LinkDown) {
+-			Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber);
+-			if (Timeout < NewTimeout) {
+-				NewTimeout = Timeout;
+-			}
+-
+-			/*
+-			 * These counters should be set to 0 for all ports before the
+-			 * first frame is sent in the next loop.
+-			 */
+-			pRPort->PacketsPerTimeSlot = 0;
+-			/* pRPort->DataPacketsPerTimeSlot = 0; */
+-			pRPort->BpduPacketsPerTimeSlot = 0;
+-		}
+-	}
+-	pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout;
+-
+-	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) {
+-		/*
+-		 * If checking remote ports, also send packets if
+-		 *   (LinksUp == 1) &&
+-		 *   this port checks at least one (remote) port.
+-		 */
+-
+-		/*
+-		 * Must be new loop, as SkRlmtCheckPort can request to
+-		 * check segmentation when e.g. checking the last port.
+-		 */
+-		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+-			if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) {
+-				SkRlmtSend(pAC, IoC,
+-					pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber);
+-			}
+-		}
+-	}
+-
+-	SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer,
+-		pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM,
+-		Para);
+-
+-	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 &&
+-		(pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) &&
+-		(pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) {
+-		SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer,
+-			SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
+-		pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG;
+-		pAC->Rlmt.Net[Para.Para32[0]].CheckingState |=
+-			SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_TIM Event END.\n"))
+-}	/* SkRlmtEvtTim */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtSegTim - SEG_TIM
+- *
+- * Description:
+- *	This routine handles SEG_TIM events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtSegTim(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+-{
+-#ifdef xDEBUG
+-	int j;
+-#endif	/* DEBUG */
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_SEG_TIM Event BEGIN.\n"))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_SEG_TIM Event EMPTY.\n"))
+-		return;
+-	}
+-
+-#ifdef xDEBUG
+-	for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) {
+-		SK_ADDR_PORT	*pAPort;
+-		SK_U32			k;
+-		SK_U16			*InAddr;
+-		SK_U8			InAddr8[6];
+-
+-		InAddr = (SK_U16 *)&InAddr8[0];
+-		pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort;
+-		for (k = 0; k < pAPort->NextExactMatchRlmt; k++) {
+-			/* Get exact match address k from port j. */
+-			XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
+-				XM_EXM(k), InAddr);
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-				("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x --  %02x %02x %02x %02x %02x %02x.\n",
+-					k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
+-					InAddr8[0], InAddr8[1], InAddr8[2],
+-					InAddr8[3], InAddr8[4], InAddr8[5],
+-					pAPort->Exact[k].a[0], pAPort->Exact[k].a[1],
+-					pAPort->Exact[k].a[2], pAPort->Exact[k].a[3],
+-					pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]))
+-		}
+-	}
+-#endif	/* xDEBUG */
+-				
+-	SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]);
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_SEG_TIM Event END.\n"))
+-}	/* SkRlmtEvtSegTim */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtPacketRx - PACKET_RECEIVED
+- *
+- * Description:
+- *	This routine handles PACKET_RECEIVED events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtPacketRx(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_MBUF *pMb */
+-{
+-	SK_MBUF	*pMb;
+-	SK_MBUF	*pNextMb;
+-	SK_U32	NetNumber;
+-
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
+-
+-	/* Should we ignore frames during port switching? */
+-
+-#ifdef DEBUG
+-	pMb = Para.pParaPtr;
+-	if (pMb == NULL) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"))
+-	}
+-	else if (pMb->pNext != NULL) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("More than one mbuf or pMb->pNext not set.\n"))
+-	}
+-#endif	/* DEBUG */
+-
+-	for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) {
+-		pNextMb = pMb->pNext;
+-		pMb->pNext = NULL;
+-
+-		NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber;
+-		if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) {
+-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-		}
+-		else {
+-			SkRlmtPacketReceive(pAC, IoC, pMb);
+-		}
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PACKET_RECEIVED Event END.\n"))
+-}	/* SkRlmtEvtPacketRx */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtStatsClear - STATS_CLEAR
+- *
+- * Description:
+- *	This routine handles STATS_CLEAR events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtStatsClear(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+-{
+-	SK_U32			i;
+-	SK_RLMT_PORT	*pRPort;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad NetNumber %d.\n", Para.Para32[0]))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	/* Clear statistics for logical and physical ports. */
+-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+-		pRPort =
+-			&pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber];
+-		pRPort->TxHelloCts = 0;
+-		pRPort->RxHelloCts = 0;
+-		pRPort->TxSpHelloReqCts = 0;
+-		pRPort->RxSpHelloCts = 0;
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_STATS_CLEAR Event END.\n"))
+-}	/* SkRlmtEvtStatsClear */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtStatsUpdate - STATS_UPDATE
+- *
+- * Description:
+- *	This routine handles STATS_UPDATE events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtStatsUpdate(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
+-{
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad NetNumber %d.\n", Para.Para32[0]))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	/* Update statistics - currently always up-to-date. */
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_STATS_UPDATE Event END.\n"))
+-}	/* SkRlmtEvtStatsUpdate */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtPrefportChange - PREFPORT_CHANGE
+- *
+- * Description:
+- *	This routine handles PREFPORT_CHANGE events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtPrefportChange(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 PortIndex; SK_U32 NetNumber */
+-{
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+-	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad NetNumber %d.\n", Para.Para32[1]))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	/* 0xFFFFFFFF == auto-mode. */
+-	if (Para.Para32[0] == 0xFFFFFFFF) {
+-		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT;
+-	}
+-	else {
+-		if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) {
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG);
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-				("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
+-			return;
+-		}
+-
+-		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0];
+-	}
+-
+-	pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0];
+-
+-	if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
+-		SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]);
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
+-}	/* SkRlmtEvtPrefportChange */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtSetNets - SET_NETS
+- *
+- * Description:
+- *	This routine handles SET_NETS events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtSetNets(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 NumNets; SK_U32 -1 */
+-{
+-	int i;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_SET_NETS Event BEGIN.\n"))
+-
+-	if (Para.Para32[1] != (SK_U32)-1) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad Parameter.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS ||
+-		Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad number of nets: %d.\n", Para.Para32[0]))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (Para.Para32[0] == pAC->Rlmt.NumNets) {	/* No change. */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	/* Entering and leaving dual mode only allowed while nets are stopped. */
+-	if (pAC->Rlmt.NetsStarted > 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Changing dual mode only allowed while all nets are stopped.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	if (Para.Para32[0] == 1) {
+-		if (pAC->Rlmt.NumNets > 1) {
+-			/* Clear logical MAC addr from second net's active port. */
+-			(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
+-				Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL);
+-			pAC->Rlmt.Net[1].NumPorts = 0;
+-		}
+-
+-		pAC->Rlmt.NumNets = Para.Para32[0];
+-		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
+-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
+-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
+-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
+-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
+-			/* Just assuming. */
+-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
+-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
+-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
+-			pAC->Rlmt.Net[i].NetNumber = i;
+-		}
+-
+-		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0];
+-		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
+-
+-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("RLMT: Changed to one net with two ports.\n"))
+-	}
+-	else if (Para.Para32[0] == 2) {
+-		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1];
+-		pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1;
+-		pAC->Rlmt.Net[0].NumPorts =
+-			pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts;
+-		
+-		pAC->Rlmt.NumNets = Para.Para32[0];
+-		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
+-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
+-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
+-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
+-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
+-			/* Just assuming. */
+-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
+-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
+-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
+-
+-			pAC->Rlmt.Net[i].NetNumber = i;
+-		}
+-
+-		/* Set logical MAC addr on second net's active port. */
+-		(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
+-			Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL);
+-
+-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("RLMT: Changed to two nets with one port each.\n"))
+-	}
+-	else {
+-		/* Not implemented for more than two nets. */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SetNets not implemented for more than two nets.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_SET_NETS Event END.\n"))
+-}	/* SkRlmtSetNets */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvtModeChange - MODE_CHANGE
+- *
+- * Description:
+- *	This routine handles MODE_CHANGE events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	Nothing
+- */
+-RLMT_STATIC void	SkRlmtEvtModeChange(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_EVPARA	Para)	/* SK_U32 NewMode; SK_U32 NetNumber */
+-{
+-	SK_EVPARA	Para2;
+-	SK_U32		i;
+-	SK_U32		PrevRlmtMode;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-		("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
+-
+-	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Bad NetNumber %d.\n", Para.Para32[1]))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	Para.Para32[0] |= SK_RLMT_CHECK_LINK;
+-
+-	if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) &&
+-		Para.Para32[0] != SK_RLMT_MODE_CLS) {
+-		pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS;
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Forced RLMT mode to CLS on single port net.\n"))
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
+-		return;
+-	}
+-
+-	/* Update RLMT mode. */
+-	PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode;
+-	pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0];
+-
+-	if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) !=
+-		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
+-		/* SK_RLMT_CHECK_LOC_LINK bit changed. */
+-		if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 &&
+-			pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 &&
+-			pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) {
+-			/* 20001207 RA: Was "PortsUp == 1". */
+-			Para2.Para32[0] = Para.Para32[1];
+-			Para2.Para32[1] = (SK_U32)-1;
+-			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer,
+-				pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue,
+-				SKGE_RLMT, SK_RLMT_TIM, Para2);
+-		}
+-	}
+-
+-	if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) !=
+-		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) {
+-		/* SK_RLMT_CHECK_SEG bit changed. */
+-		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) {
+-			(void)SkAddrMcClear(pAC, IoC,
+-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
+-				SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
+-
+-			/* Add RLMT MC address. */
+-			(void)SkAddrMcAdd(pAC, IoC,
+-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
+-				&SkRlmtMcAddr, SK_ADDR_PERMANENT);
+-
+-			if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode &
+-				SK_RLMT_CHECK_SEG) != 0) {
+-				/* Add BPDU MC address. */
+-				(void)SkAddrMcAdd(pAC, IoC,
+-					pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
+-					&BridgeMcAddr, SK_ADDR_PERMANENT);
+-
+-				if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
+-					if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown &&
+-						(Para2.pParaPtr = SkRlmtBuildSpanningTreePacket(
+-						pAC, IoC, i)) != NULL) {
+-						pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet =
+-							SK_FALSE;
+-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
+-					}
+-				}
+-			}
+-			(void)SkAddrMcUpdate(pAC, IoC,
+-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber);
+-		}	/* for ... */
+-
+-		if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) {
+-			Para2.Para32[0] = Para.Para32[1];
+-			Para2.Para32[1] = (SK_U32)-1;
+-			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer,
+-				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2);
+-		}
+-	}	/* SK_RLMT_CHECK_SEG bit changed. */
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("SK_RLMT_MODE_CHANGE Event END.\n"))
+-}	/* SkRlmtEvtModeChange */
+-
+-
+-/******************************************************************************
+- *
+- *	SkRlmtEvent - a PORT- or an RLMT-specific event happened
+- *
+- * Description:
+- *	This routine calls subroutines to handle PORT- and RLMT-specific events.
+- *
+- * Context:
+- *	runtime, pageable?
+- *	may be called after SK_INIT_IO
+- *
+- * Returns:
+- *	0
+- */
+-int	SkRlmtEvent(
+-SK_AC		*pAC,	/* Adapter Context */
+-SK_IOC		IoC,	/* I/O Context */
+-SK_U32		Event,	/* Event code */
+-SK_EVPARA	Para)	/* Event-specific parameter */
+-{
+-	switch (Event) {
+-	
+-	/* ----- PORT events ----- */
+-
+-	case SK_RLMT_PORTSTART_TIM:	/* From RLMT via TIME. */
+-		SkRlmtEvtPortStartTim(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_LINK_UP:		/* From SIRQ. */
+-		SkRlmtEvtLinkUp(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_PORTUP_TIM:	/* From RLMT via TIME. */
+-		SkRlmtEvtPortUpTim(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_PORTDOWN:			/* From RLMT. */
+-	case SK_RLMT_PORTDOWN_RX_TIM:	/* From RLMT via TIME. */
+-	case SK_RLMT_PORTDOWN_TX_TIM:	/* From RLMT via TIME. */
+-		SkRlmtEvtPortDownX(pAC, IoC, Event, Para);
+-		break;
+-	case SK_RLMT_LINK_DOWN:		/* From SIRQ. */
+-		SkRlmtEvtLinkDown(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_PORT_ADDR:		/* From ADDR. */
+-		SkRlmtEvtPortAddr(pAC, IoC, Para);
+-		break;
+-
+-	/* ----- RLMT events ----- */
+-
+-	case SK_RLMT_START:		/* From DRV. */
+-		SkRlmtEvtStart(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_STOP:		/* From DRV. */
+-		SkRlmtEvtStop(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_TIM:		/* From RLMT via TIME. */
+-		SkRlmtEvtTim(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_SEG_TIM:
+-		SkRlmtEvtSegTim(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_PACKET_RECEIVED:	/* From DRV. */
+-		SkRlmtEvtPacketRx(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_STATS_CLEAR:	/* From PNMI. */
+-		SkRlmtEvtStatsClear(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_STATS_UPDATE:	/* From PNMI. */
+-		SkRlmtEvtStatsUpdate(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_PREFPORT_CHANGE:	/* From PNMI. */
+-		SkRlmtEvtPrefportChange(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_MODE_CHANGE:	/* From PNMI. */
+-		SkRlmtEvtModeChange(pAC, IoC, Para);
+-		break;
+-	case SK_RLMT_SET_NETS:	/* From DRV. */
+-		SkRlmtEvtSetNets(pAC, IoC, Para);
+-		break;
+-
+-	/* ----- Unknown events ----- */
+-
+-	default:	/* Create error log entry. */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+-			("Unknown RLMT Event %d.\n", Event))
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG);
+-		break;
+-	}	/* switch() */
+-
+-	return (0);
+-}	/* SkRlmtEvent */
+-
+-#ifdef __cplusplus
+-}
+-#endif	/* __cplusplus */
+diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c
+deleted file mode 100644
+index 4e46295..0000000
+--- a/drivers/net/sk98lin/sktimer.c
++++ /dev/null
+@@ -1,250 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	sktimer.c
+- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version:	$Revision: 1.14 $
+- * Date:	$Date: 2003/09/16 13:46:51 $
+- * Purpose:	High level timer functions.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect GmbH.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-
+-/*
+- *	Event queue and dispatcher
+- */
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
+-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
+-
+-#ifdef __C2MAN__
+-/*
+-	Event queue management.
+-
+-	General Description:
+-
+- */
+-intro()
+-{}
+-#endif
+-
+-
+-/* Forward declaration */
+-static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
+-
+-
+-/*
+- * Inits the software timer
+- *
+- * needs to be called during Init level 1.
+- */
+-void	SkTimerInit(
+-SK_AC	*pAC,		/* Adapters context */
+-SK_IOC	Ioc,		/* IoContext */
+-int		Level)		/* Init Level */
+-{
+-	switch (Level) {
+-	case SK_INIT_DATA:
+-		pAC->Tim.StQueue = NULL;
+-		break;
+-	case SK_INIT_IO:
+-		SkHwtInit(pAC, Ioc);
+-		SkTimerDone(pAC, Ioc);
+-		break;
+-	default:
+-		break;
+-	}
+-}
+-
+-/*
+- * Stops a high level timer
+- * - If a timer is not in the queue the function returns normally, too.
+- */
+-void	SkTimerStop(
+-SK_AC		*pAC,		/* Adapters context */
+-SK_IOC		Ioc,		/* IoContext */
+-SK_TIMER	*pTimer)	/* Timer Pointer to be started */
+-{
+-	SK_TIMER	**ppTimPrev;
+-	SK_TIMER	*pTm;
+-
+-	/*
+-	 * remove timer from queue
+-	 */
+-	pTimer->TmActive = SK_FALSE;
+-	
+-	if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
+-		SkHwtStop(pAC, Ioc);
+-	}
+-	
+-	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
+-		ppTimPrev = &pTm->TmNext ) {
+-		
+-		if (pTm == pTimer) {
+-			/*
+-			 * Timer found in queue
+-			 * - dequeue it and
+-			 * - correct delta of the next timer
+-			 */
+-			*ppTimPrev = pTm->TmNext;
+-
+-			if (pTm->TmNext) {
+-				/* correct delta of next timer in queue */
+-				pTm->TmNext->TmDelta += pTm->TmDelta;
+-			}
+-			return;
+-		}
+-	}
+-}
+-
+-/*
+- * Start a high level software timer
+- */
+-void	SkTimerStart(
+-SK_AC		*pAC,		/* Adapters context */
+-SK_IOC		Ioc,		/* IoContext */
+-SK_TIMER	*pTimer,	/* Timer Pointer to be started */
+-SK_U32		Time,		/* Time value */
+-SK_U32		Class,		/* Event Class for this timer */
+-SK_U32		Event,		/* Event Value for this timer */
+-SK_EVPARA	Para)		/* Event Parameter for this timer */
+-{
+-	SK_TIMER	**ppTimPrev;
+-	SK_TIMER	*pTm;
+-	SK_U32		Delta;
+-
+-	Time /= 16;		/* input is uS, clock ticks are 16uS */
+-	
+-	if (!Time)
+-		Time = 1;
+-
+-	SkTimerStop(pAC, Ioc, pTimer);
+-
+-	pTimer->TmClass = Class;
+-	pTimer->TmEvent = Event;
+-	pTimer->TmPara = Para;
+-	pTimer->TmActive = SK_TRUE;
+-
+-	if (!pAC->Tim.StQueue) {
+-		/* First Timer to be started */
+-		pAC->Tim.StQueue = pTimer;
+-		pTimer->TmNext = NULL;
+-		pTimer->TmDelta = Time;
+-		
+-		SkHwtStart(pAC, Ioc, Time);
+-		
+-		return;
+-	}
+-
+-	/*
+-	 * timer correction
+-	 */
+-	timer_done(pAC, Ioc, 0);
+-
+-	/*
+-	 * find position in queue
+-	 */
+-	Delta = 0;
+-	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
+-		ppTimPrev = &pTm->TmNext ) {
+-		
+-		if (Delta + pTm->TmDelta > Time) {
+-			/* Position found */
+-			/* Here the timer needs to be inserted. */
+-			break;
+-		}
+-		Delta += pTm->TmDelta;
+-	}
+-
+-	/* insert in queue */
+-	*ppTimPrev = pTimer;
+-	pTimer->TmNext = pTm;
+-	pTimer->TmDelta = Time - Delta;
+-
+-	if (pTm) {
+-		/* There is a next timer
+-		 * -> correct its Delta value.
+-		 */
+-		pTm->TmDelta -= pTimer->TmDelta;
+-	}
+-
+-	/* restart with first */
+-	SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
+-}
+-
+-
+-void	SkTimerDone(
+-SK_AC	*pAC,		/* Adapters context */
+-SK_IOC	Ioc)		/* IoContext */
+-{
+-	timer_done(pAC, Ioc, 1);
+-}
+-
+-
+-static void	timer_done(
+-SK_AC	*pAC,		/* Adapters context */
+-SK_IOC	Ioc,		/* IoContext */
+-int		Restart)	/* Do we need to restart the Hardware timer ? */
+-{
+-	SK_U32		Delta;
+-	SK_TIMER	*pTm;
+-	SK_TIMER	*pTComp;	/* Timer completed now now */
+-	SK_TIMER	**ppLast;	/* Next field of Last timer to be deq */
+-	int		Done = 0;
+-
+-	Delta = SkHwtRead(pAC, Ioc);
+-	
+-	ppLast = &pAC->Tim.StQueue;
+-	pTm = pAC->Tim.StQueue;
+-	while (pTm && !Done) {
+-		if (Delta >= pTm->TmDelta) {
+-			/* Timer ran out */
+-			pTm->TmActive = SK_FALSE;
+-			Delta -= pTm->TmDelta;
+-			ppLast = &pTm->TmNext;
+-			pTm = pTm->TmNext;
+-		}
+-		else {
+-			/* We found the first timer that did not run out */
+-			pTm->TmDelta -= Delta;
+-			Delta = 0;
+-			Done = 1;
+-		}
+-	}
+-	*ppLast = NULL;
+-	/*
+-	 * pTm points to the first Timer that did not run out.
+-	 * StQueue points to the first Timer that run out.
+-	 */
+-
+-	for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
+-		SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
+-	}
+-
+-	/* Set head of timer queue to the first timer that did not run out */
+-	pAC->Tim.StQueue = pTm;
+-
+-	if (Restart && pAC->Tim.StQueue) {
+-		/* Restart HW timer */
+-		SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
+-	}
+-}
+-
+-/* End of file */
+diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c
+deleted file mode 100644
+index 1e662aa..0000000
+--- a/drivers/net/sk98lin/skvpd.c
++++ /dev/null
+@@ -1,1091 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skvpd.c
+- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
+- * Version:	$Revision: 1.37 $
+- * Date:	$Date: 2003/01/13 10:42:45 $
+- * Purpose:	Shared software to read and write VPD data
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2003 SysKonnect GmbH.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+-	Please refer skvpd.txt for information how to include this module
+- */
+-static const char SysKonnectFileId[] =
+-	"@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
+-
+-#include "h/skdrv1st.h"
+-#include "h/sktypes.h"
+-#include "h/skdebug.h"
+-#include "h/skdrv2nd.h"
+-
+-/*
+- * Static functions
+- */
+-#ifndef SK_KR_PROTO
+-static SK_VPD_PARA	*vpd_find_para(
+-	SK_AC	*pAC,
+-	const char	*key,
+-	SK_VPD_PARA *p);
+-#else	/* SK_KR_PROTO */
+-static SK_VPD_PARA	*vpd_find_para();
+-#endif	/* SK_KR_PROTO */
+-
+-/*
+- * waits for a completion of a VPD transfer
+- * The VPD transfer must complete within SK_TICKS_PER_SEC/16
+- *
+- * returns	0:	success, transfer completes
+- *		error	exit(9) with a error message
+- */
+-static int VpdWait(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	IoC,	/* IO Context */
+-int		event)	/* event to wait for (VPD_READ / VPD_write) completion*/
+-{
+-	SK_U64	start_time;
+-	SK_U16	state;
+-
+-	SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-		("VPD wait for %s\n", event?"Write":"Read"));
+-	start_time = SkOsGetTime(pAC);
+-	do {
+-		if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
+-
+-			/* Bug fix AF: Thu Mar 28 2002
+-			 * Do not call: VPD_STOP(pAC, IoC);
+-			 * A pending VPD read cycle can not be aborted by writing
+-			 * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
+-			 * Although the write threshold in the OUR-register protects
+-			 * VPD read only space from being overwritten this does not
+-			 * protect a VPD read from being `converted` into a VPD write
+-			 * operation (on the fly). As a consequence the VPD_STOP would
+-			 * delete VPD read only data. In case of any problems with the
+-			 * I2C bus we exit the loop here. The I2C read operation can
+-			 * not be aborted except by a reset (->LR).
+-			 */
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
+-				("ERROR:VPD wait timeout\n"));
+-			return(1);
+-		}
+-		
+-		VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
+-		
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-			("state = %x, event %x\n",state,event));
+-	} while((int)(state & PCI_VPD_FLAG) == event);
+-
+-	return(0);
+-}
+-
+-#ifdef SKDIAG
+-
+-/*
+- * Read the dword at address 'addr' from the VPD EEPROM.
+- *
+- * Needed Time:	MIN 1,3 ms	MAX 2,6 ms
+- *
+- * Note: The DWord is returned in the endianess of the machine the routine
+- *       is running on.
+- *
+- * Returns the data read.
+- */
+-SK_U32 VpdReadDWord(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	IoC,	/* IO Context */
+-int		addr)	/* VPD address */
+-{
+-	SK_U32	Rtv;
+-
+-	/* start VPD read */
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-		("VPD read dword at 0x%x\n",addr));
+-	addr &= ~VPD_WRITE;		/* ensure the R/W bit is set to read */
+-
+-	VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
+-
+-	/* ignore return code here */
+-	(void)VpdWait(pAC, IoC, VPD_READ);
+-
+-	/* Don't swap here, it's a data stream of bytes */
+-	Rtv = 0;
+-
+-	VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-		("VPD read dword data = 0x%x\n",Rtv));
+-	return(Rtv);
+-}
+-
+-#endif	/* SKDIAG */
+-
+-/*
+- *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
+- *	or to the I2C EEPROM.
+- *
+- * Returns number of bytes read / written.
+- */
+-static int VpdWriteStream(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	IoC,	/* IO Context */
+-char	*buf,	/* data buffer */
+-int		Addr,	/* VPD start address */
+-int		Len)	/* number of bytes to read / to write */
+-{
+-	int		i;
+-	int		j;
+-	SK_U16	AdrReg;
+-	int		Rtv;
+-	SK_U8	* pComp;	/* Compare pointer */
+-	SK_U8	Data;		/* Input Data for Compare */
+-
+-	/* Init Compare Pointer */
+-	pComp = (SK_U8 *) buf;
+-
+-	for (i = 0; i < Len; i++, buf++) {
+-		if ((i%sizeof(SK_U32)) == 0) {
+-			/*
+-			 * At the begin of each cycle read the Data Reg
+-			 * So it is initialized even if only a few bytes
+-			 * are written.
+-			 */
+-			AdrReg = (SK_U16) Addr;
+-			AdrReg &= ~VPD_WRITE;	/* READ operation */
+-
+-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+-
+-			/* Wait for termination */
+-			Rtv = VpdWait(pAC, IoC, VPD_READ);
+-			if (Rtv != 0) {
+-				return(i);
+-			}
+-		}
+-
+-		/* Write current Byte */
+-		VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
+-				*(SK_U8*)buf);
+-
+-		if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
+-			/* New Address needs to be written to VPD_ADDR reg */
+-			AdrReg = (SK_U16) Addr;
+-			Addr += sizeof(SK_U32);
+-			AdrReg |= VPD_WRITE;	/* WRITE operation */
+-
+-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+-
+-			/* Wait for termination */
+-			Rtv = VpdWait(pAC, IoC, VPD_WRITE);
+-			if (Rtv != 0) {
+-				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-					("Write Timed Out\n"));
+-				return(i - (i%sizeof(SK_U32)));
+-			}
+-
+-			/*
+-			 * Now re-read to verify
+-			 */
+-			AdrReg &= ~VPD_WRITE;	/* READ operation */
+-
+-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+-
+-			/* Wait for termination */
+-			Rtv = VpdWait(pAC, IoC, VPD_READ);
+-			if (Rtv != 0) {
+-				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-					("Verify Timed Out\n"));
+-				return(i - (i%sizeof(SK_U32)));
+-			}
+-
+-			for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
+-				
+-				VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
+-				
+-				if (Data != *pComp) {
+-					/* Verify Error */
+-					SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-						("WriteStream Verify Error\n"));
+-					return(i - (i%sizeof(SK_U32)) + j);
+-				}
+-			}
+-		}
+-	}
+-
+-	return(Len);
+-}
+-	
+-
+-/*
+- *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
+- *	or to the I2C EEPROM.
+- *
+- * Returns number of bytes read / written.
+- */
+-static int VpdReadStream(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	IoC,	/* IO Context */
+-char	*buf,	/* data buffer */
+-int		Addr,	/* VPD start address */
+-int		Len)	/* number of bytes to read / to write */
+-{
+-	int		i;
+-	SK_U16	AdrReg;
+-	int		Rtv;
+-
+-	for (i = 0; i < Len; i++, buf++) {
+-		if ((i%sizeof(SK_U32)) == 0) {
+-			/* New Address needs to be written to VPD_ADDR reg */
+-			AdrReg = (SK_U16) Addr;
+-			Addr += sizeof(SK_U32);
+-			AdrReg &= ~VPD_WRITE;	/* READ operation */
+-
+-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+-
+-			/* Wait for termination */
+-			Rtv = VpdWait(pAC, IoC, VPD_READ);
+-			if (Rtv != 0) {
+-				return(i);
+-			}
+-		}
+-		VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
+-			(SK_U8 *)buf);
+-	}
+-
+-	return(Len);
+-}
+-
+-/*
+- *	Read ore writes 'len' bytes of VPD data, starting at 'addr' from
+- *	or to the I2C EEPROM.
+- *
+- * Returns number of bytes read / written.
+- */
+-static int VpdTransferBlock(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	IoC,	/* IO Context */
+-char	*buf,	/* data buffer */
+-int		addr,	/* VPD start address */
+-int		len,	/* number of bytes to read / to write */
+-int		dir)	/* transfer direction may be VPD_READ or VPD_WRITE */
+-{
+-	int		Rtv;	/* Return value */
+-	int		vpd_rom_size;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-		("VPD %s block, addr = 0x%x, len = %d\n",
+-		dir ? "write" : "read", addr, len));
+-
+-	if (len == 0)
+-		return(0);
+-
+-	vpd_rom_size = pAC->vpd.rom_size;
+-	
+-	if (addr > vpd_rom_size - 4) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+-			("Address error: 0x%x, exp. < 0x%x\n",
+-			addr, vpd_rom_size - 4));
+-		return(0);
+-	}
+-	
+-	if (addr + len > vpd_rom_size) {
+-		len = vpd_rom_size - addr;
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-			("Warning: len was cut to %d\n", len));
+-	}
+-
+-	if (dir == VPD_READ) {
+-		Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
+-	}
+-	else {
+-		Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
+-	}
+-
+-	return(Rtv);
+-}
+-
+-#ifdef SKDIAG
+-
+-/*
+- *	Read 'len' bytes of VPD data, starting at 'addr'.
+- *
+- * Returns number of bytes read.
+- */
+-int VpdReadBlock(
+-SK_AC	*pAC,	/* pAC pointer */
+-SK_IOC	IoC,	/* IO Context */
+-char	*buf,	/* buffer were the data should be stored */
+-int		addr,	/* start reading at the VPD address */
+-int		len)	/* number of bytes to read */
+-{
+-	return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
+-}
+-
+-/*
+- *	Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
+- *
+- * Returns number of bytes writes.
+- */
+-int VpdWriteBlock(
+-SK_AC	*pAC,	/* pAC pointer */
+-SK_IOC	IoC,	/* IO Context */
+-char	*buf,	/* buffer, holds the data to write */
+-int		addr,	/* start writing at the VPD address */
+-int		len)	/* number of bytes to write */
+-{
+-	return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
+-}
+-#endif	/* SKDIAG */
+-
+-/*
+- * (re)initialize the VPD buffer
+- *
+- * Reads the VPD data from the EEPROM into the VPD buffer.
+- * Get the remaining read only and read / write space.
+- *
+- * return	0:	success
+- *		1:	fatal VPD error
+- */
+-static int VpdInit(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	IoC)	/* IO Context */
+-{
+-	SK_VPD_PARA *r, rp;	/* RW or RV */
+-	int		i;
+-	unsigned char	x;
+-	int		vpd_size;
+-	SK_U16	dev_id;
+-	SK_U32	our_reg2;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
+-	
+-	VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
+-	
+-	VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
+-	
+-	pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
+-	
+-	/*
+-	 * this function might get used before the hardware is initialized
+-	 * therefore we cannot always trust in GIChipId
+-	 */
+-	if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
+-		dev_id != VPD_DEV_ID_GENESIS) ||
+-		((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
+-		!pAC->GIni.GIGenesis)) {
+-
+-		/* for Yukon the VPD size is always 256 */
+-		vpd_size = VPD_SIZE_YUKON;
+-	}
+-	else {
+-		/* Genesis uses the maximum ROM size up to 512 for VPD */
+-		if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
+-			vpd_size = VPD_SIZE_GENESIS;
+-		}
+-		else {
+-			vpd_size = pAC->vpd.rom_size;
+-		}
+-	}
+-
+-	/* read the VPD data into the VPD buffer */
+-	if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ)
+-		!= vpd_size) {
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-			("Block Read Error\n"));
+-		return(1);
+-	}
+-	
+-	pAC->vpd.vpd_size = vpd_size;
+-
+-	/* Asus K8V Se Deluxe bugfix. Correct VPD content */
+-	/* MBo April 2004 */
+-	if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) &&
+-	    ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
+-	    ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) {
+-		printk("sk98lin: Asus mainboard with buggy VPD? "
+-				"Correcting data.\n");
+-		pAC->vpd.vpd_buf[0x40] = 0x38;
+-	}
+-
+-
+-	/* find the end tag of the RO area */
+-	if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+-			("Encoding Error: RV Tag not found\n"));
+-		return(1);
+-	}
+-	
+-	if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
+-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+-			("Encoding Error: Invalid VPD struct size\n"));
+-		return(1);
+-	}
+-	pAC->vpd.v.vpd_free_ro = r->p_len - 1;
+-
+-	/* test the checksum */
+-	for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
+-		x += pAC->vpd.vpd_buf[i];
+-	}
+-	
+-	if (x != 0) {
+-		/* checksum error */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+-			("VPD Checksum Error\n"));
+-		return(1);
+-	}
+-
+-	/* find and check the end tag of the RW area */
+-	if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+-			("Encoding Error: RV Tag not found\n"));
+-		return(1);
+-	}
+-	
+-	if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+-			("Encoding Error: Invalid VPD struct size\n"));
+-		return(1);
+-	}
+-	pAC->vpd.v.vpd_free_rw = r->p_len;
+-
+-	/* everything seems to be ok */
+-	if (pAC->GIni.GIChipId != 0) {
+-		pAC->vpd.v.vpd_status |= VPD_VALID;
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
+-		("done. Free RO = %d, Free RW = %d\n",
+-		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
+-
+-	return(0);
+-}
+-
+-/*
+- *	find the Keyword 'key' in the VPD buffer and fills the
+- *	parameter struct 'p' with it's values
+- *
+- * returns	*p	success
+- *		0:	parameter was not found or VPD encoding error
+- */
+-static SK_VPD_PARA *vpd_find_para(
+-SK_AC		*pAC,	/* common data base */
+-const char	*key,	/* keyword to find (e.g. "MN") */
+-SK_VPD_PARA *p)		/* parameter description struct */
+-{
+-	char *v	;	/* points to VPD buffer */
+-	int max;	/* Maximum Number of Iterations */
+-
+-	v = pAC->vpd.vpd_buf;
+-	max = 128;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-		("VPD find para %s .. ",key));
+-
+-	/* check mandatory resource type ID string (Product Name) */
+-	if (*v != (char)RES_ID) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+-			("Error: 0x%x missing\n", RES_ID));
+-		return NULL;
+-	}
+-
+-	if (strcmp(key, VPD_NAME) == 0) {
+-		p->p_len = VPD_GET_RES_LEN(v);
+-		p->p_val = VPD_GET_VAL(v);
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-			("found, len = %d\n", p->p_len));
+-		return(p);
+-	}
+-
+-	v += 3 + VPD_GET_RES_LEN(v) + 3;
+-	for (;; ) {
+-		if (SK_MEMCMP(key,v,2) == 0) {
+-			p->p_len = VPD_GET_VPD_LEN(v);
+-			p->p_val = VPD_GET_VAL(v);
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-				("found, len = %d\n",p->p_len));
+-			return(p);
+-		}
+-
+-		/* exit when reaching the "RW" Tag or the maximum of itera. */
+-		max--;
+-		if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
+-			break;
+-		}
+-
+-		if (SK_MEMCMP(VPD_RV,v,2) == 0) {
+-			v += 3 + VPD_GET_VPD_LEN(v) + 3;	/* skip VPD-W */
+-		}
+-		else {
+-			v += 3 + VPD_GET_VPD_LEN(v);
+-		}
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-			("scanning '%c%c' len = %d\n",v[0],v[1],v[2]));
+-	}
+-
+-#ifdef DEBUG
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
+-	if (max == 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+-			("Key/Len Encoding error\n"));
+-	}
+-#endif /* DEBUG */
+-	return NULL;
+-}
+-
+-/*
+- *	Move 'n' bytes. Begin with the last byte if 'n' is > 0,
+- *	Start with the last byte if n is < 0.
+- *
+- * returns nothing
+- */
+-static void vpd_move_para(
+-char	*start,		/* start of memory block */
+-char	*end,		/* end of memory block to move */
+-int		n)			/* number of bytes the memory block has to be moved */
+-{
+-	char *p;
+-	int i;		/* number of byte copied */
+-
+-	if (n == 0)
+-		return;
+-
+-	i = (int) (end - start + 1);
+-	if (n < 0) {
+-		p = start + n;
+-		while (i != 0) {
+-			*p++ = *start++;
+-			i--;
+-		}
+-	}
+-	else {
+-		p = end + n;
+-		while (i != 0) {
+-			*p-- = *end--;
+-			i--;
+-		}
+-	}
+-}
+-
+-/*
+- *	setup the VPD keyword 'key' at 'ip'.
+- *
+- * returns nothing
+- */
+-static void vpd_insert_key(
+-const char	*key,	/* keyword to insert */
+-const char	*buf,	/* buffer with the keyword value */
+-int		len,		/* length of the value string */
+-char	*ip)		/* inseration point */
+-{
+-	SK_VPD_KEY *p;
+-
+-	p = (SK_VPD_KEY *) ip;
+-	p->p_key[0] = key[0];
+-	p->p_key[1] = key[1];
+-	p->p_len = (unsigned char) len;
+-	SK_MEMCPY(&p->p_val,buf,len);
+-}
+-
+-/*
+- *	Setup the VPD end tag "RV" / "RW".
+- *	Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
+- *
+- * returns	0:	success
+- *		1:	encoding error
+- */
+-static int vpd_mod_endtag(
+-SK_AC	*pAC,		/* common data base */
+-char	*etp)		/* end pointer input position */
+-{
+-	SK_VPD_KEY *p;
+-	unsigned char	x;
+-	int	i;
+-	int	vpd_size;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-		("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1]));
+-
+-	vpd_size = pAC->vpd.vpd_size;
+-
+-	p = (SK_VPD_KEY *) etp;
+-
+-	if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
+-		/* something wrong here, encoding error */
+-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+-			("Encoding Error: invalid end tag\n"));
+-		return(1);
+-	}
+-	if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
+-		/* create "RW" tag */
+-		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
+-		pAC->vpd.v.vpd_free_rw = (int) p->p_len;
+-		i = pAC->vpd.v.vpd_free_rw;
+-		etp += 3;
+-	}
+-	else {
+-		/* create "RV" tag */
+-		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
+-		pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
+-
+-		/* setup checksum */
+-		for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
+-			x += pAC->vpd.vpd_buf[i];
+-		}
+-		p->p_val = (char) 0 - x;
+-		i = pAC->vpd.v.vpd_free_ro;
+-		etp += 4;
+-	}
+-	while (i) {
+-		*etp++ = 0x00;
+-		i--;
+-	}
+-
+-	return(0);
+-}
+-
+-/*
+- *	Insert a VPD keyword into the VPD buffer.
+- *
+- *	The keyword 'key' is inserted at the position 'ip' in the
+- *	VPD buffer.
+- *	The keywords behind the input position will
+- *	be moved. The VPD end tag "RV" or "RW" is generated again.
+- *
+- * returns	0:	success
+- *		2:	value string was cut
+- *		4:	VPD full, keyword was not written
+- *		6:	fatal VPD error
+- *
+- */
+-static int	VpdSetupPara(
+-SK_AC	*pAC,		/* common data base */
+-const char	*key,	/* keyword to insert */
+-const char	*buf,	/* buffer with the keyword value */
+-int		len,		/* length of the keyword value */
+-int		type,		/* VPD_RO_KEY or VPD_RW_KEY */
+-int		op)			/* operation to do: ADD_KEY or OWR_KEY */
+-{
+-	SK_VPD_PARA vp;
+-	char	*etp;		/* end tag position */
+-	int	free;		/* remaining space in selected area */
+-	char	*ip;		/* input position inside the VPD buffer */
+-	int	rtv;		/* return code */
+-	int	head;		/* additional haeder bytes to move */
+-	int	found;		/* additinoal bytes if the keyword was found */
+-	int vpd_size;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-		("VPD setup para key = %s, val = %s\n",key,buf));
+-	
+-	vpd_size = pAC->vpd.vpd_size;
+-
+-	rtv = 0;
+-	ip = NULL;
+-	if (type == VPD_RW_KEY) {
+-		/* end tag is "RW" */
+-		free = pAC->vpd.v.vpd_free_rw;
+-		etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
+-	}
+-	else {
+-		/* end tag is "RV" */
+-		free = pAC->vpd.v.vpd_free_ro;
+-		etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
+-	}
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-		("Free RO = %d, Free RW = %d\n",
+-		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
+-
+-	head = 0;
+-	found = 0;
+-	if (op == OWR_KEY) {
+-		if (vpd_find_para(pAC, key, &vp)) {
+-			found = 3;
+-			ip = vp.p_val - 3;
+-			free += vp.p_len + 3;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-				("Overwrite Key\n"));
+-		}
+-		else {
+-			op = ADD_KEY;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+-				("Add Key\n"));
+-		}
+-	}
+-	if (op == ADD_KEY) {
+-		ip = etp;
+-		vp.p_len = 0;
+-		head = 3;
+-	}
+-
+-	if (len + 3 > free) {
+-		if (free < 7) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-				("VPD Buffer Overflow, keyword not written\n"));
+-			return(4);
+-		}
+-		/* cut it again */
+-		len = free - 3;
+-		rtv = 2;
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-			("VPD Buffer Full, Keyword was cut\n"));
+-	}
+-
+-	vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
+-	vpd_insert_key(key, buf, len, ip);
+-	if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
+-		pAC->vpd.v.vpd_status &= ~VPD_VALID;
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-			("VPD Encoding Error\n"));
+-		return(6);
+-	}
+-
+-	return(rtv);
+-}
+-
+-
+-/*
+- *	Read the contents of the VPD EEPROM and copy it to the
+- *	VPD buffer if not already done.
+- *
+- * return:	A pointer to the vpd_status structure. The structure contains
+- *		this fields.
+- */
+-SK_VPD_STATUS *VpdStat(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	IoC)	/* IO Context */
+-{
+-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+-		(void)VpdInit(pAC, IoC);
+-	}
+-	return(&pAC->vpd.v);
+-}
+-
+-
+-/*
+- *	Read the contents of the VPD EEPROM and copy it to the VPD
+- *	buffer if not already done.
+- *	Scan the VPD buffer for VPD keywords and create the VPD
+- *	keyword list by copying the keywords to 'buf', all after
+- *	each other and terminated with a '\0'.
+- *
+- * Exceptions:	o The Resource Type ID String (product name) is called "Name"
+- *		o The VPD end tags 'RV' and 'RW' are not listed
+- *
+- *	The number of copied keywords is counted in 'elements'.
+- *
+- * returns	0:	success
+- *		2:	buffer overfull, one or more keywords are missing
+- *		6:	fatal VPD error
+- *
+- *	example values after returning:
+- *
+- *		buf =	"Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
+- *		*len =		30
+- *		*elements =	 9
+- */
+-int VpdKeys(
+-SK_AC	*pAC,		/* common data base */
+-SK_IOC	IoC,		/* IO Context */
+-char	*buf,		/* buffer where to copy the keywords */
+-int		*len,		/* buffer length */
+-int		*elements)	/* number of keywords returned */
+-{
+-	char *v;
+-	int n;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
+-	*elements = 0;
+-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+-		if (VpdInit(pAC, IoC) != 0) {
+-			*len = 0;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-				("VPD Init Error, terminated\n"));
+-			return(6);
+-		}
+-	}
+-
+-	if ((signed)strlen(VPD_NAME) + 1 <= *len) {
+-		v = pAC->vpd.vpd_buf;
+-		strcpy(buf,VPD_NAME);
+-		n = strlen(VPD_NAME) + 1;
+-		buf += n;
+-		*elements = 1;
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+-			("'%c%c' ",v[0],v[1]));
+-	}
+-	else {
+-		*len = 0;
+-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
+-			("buffer overflow\n"));
+-		return(2);
+-	}
+-
+-	v += 3 + VPD_GET_RES_LEN(v) + 3;
+-	for (;; ) {
+-		/* exit when reaching the "RW" Tag */
+-		if (SK_MEMCMP(VPD_RW,v,2) == 0) {
+-			break;
+-		}
+-
+-		if (SK_MEMCMP(VPD_RV,v,2) == 0) {
+-			v += 3 + VPD_GET_VPD_LEN(v) + 3;	/* skip VPD-W */
+-			continue;
+-		}
+-
+-		if (n+3 <= *len) {
+-			SK_MEMCPY(buf,v,2);
+-			buf += 2;
+-			*buf++ = '\0';
+-			n += 3;
+-			v += 3 + VPD_GET_VPD_LEN(v);
+-			*elements += 1;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+-				("'%c%c' ",v[0],v[1]));
+-		}
+-		else {
+-			*len = n;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-				("buffer overflow\n"));
+-			return(2);
+-		}
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
+-	*len = n;
+-	return(0);
+-}
+-
+-
+-/*
+- *	Read the contents of the VPD EEPROM and copy it to the
+- *	VPD buffer if not already done. Search for the VPD keyword
+- *	'key' and copy its value to 'buf'. Add a terminating '\0'.
+- *	If the value does not fit into the buffer cut it after
+- *	'len' - 1 bytes.
+- *
+- * returns	0:	success
+- *		1:	keyword not found
+- *		2:	value string was cut
+- *		3:	VPD transfer timeout
+- *		6:	fatal VPD error
+- */
+-int VpdRead(
+-SK_AC		*pAC,	/* common data base */
+-SK_IOC		IoC,	/* IO Context */
+-const char	*key,	/* keyword to read (e.g. "MN") */
+-char		*buf,	/* buffer where to copy the keyword value */
+-int			*len)	/* buffer length */
+-{
+-	SK_VPD_PARA *p, vp;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
+-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+-		if (VpdInit(pAC, IoC) != 0) {
+-			*len = 0;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-				("VPD init error\n"));
+-			return(6);
+-		}
+-	}
+-
+-	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
+-		if (p->p_len > (*(unsigned *)len)-1) {
+-			p->p_len = *len - 1;
+-		}
+-		SK_MEMCPY(buf, p->p_val, p->p_len);
+-		buf[p->p_len] = '\0';
+-		*len = p->p_len;
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+-			("%c%c%c%c.., len = %d\n",
+-			buf[0],buf[1],buf[2],buf[3],*len));
+-	}
+-	else {
+-		*len = 0;
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
+-		return(1);
+-	}
+-	return(0);
+-}
+-
+-
+-/*
+- *	Check whether a given key may be written
+- *
+- * returns
+- *	SK_TRUE		Yes it may be written
+- *	SK_FALSE	No it may be written
+- */
+-SK_BOOL VpdMayWrite(
+-char	*key)	/* keyword to write (allowed values "Yx", "Vx") */
+-{
+-	if ((*key != 'Y' && *key != 'V') ||
+-		key[1] < '0' || key[1] > 'Z' ||
+-		(key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
+-
+-		return(SK_FALSE);
+-	}
+-	return(SK_TRUE);
+-}
+-
+-/*
+- *	Read the contents of the VPD EEPROM and copy it to the VPD
+- *	buffer if not already done. Insert/overwrite the keyword 'key'
+- *	in the VPD buffer. Cut the keyword value if it does not fit
+- *	into the VPD read / write area.
+- *
+- * returns	0:	success
+- *		2:	value string was cut
+- *		3:	VPD transfer timeout
+- *		4:	VPD full, keyword was not written
+- *		5:	keyword cannot be written
+- *		6:	fatal VPD error
+- */
+-int VpdWrite(
+-SK_AC		*pAC,	/* common data base */
+-SK_IOC		IoC,	/* IO Context */
+-const char	*key,	/* keyword to write (allowed values "Yx", "Vx") */
+-const char	*buf)	/* buffer where the keyword value can be read from */
+-{
+-	int len;		/* length of the keyword to write */
+-	int rtv;		/* return code */
+-	int rtv2;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
+-		("VPD write %s = %s\n",key,buf));
+-
+-	if ((*key != 'Y' && *key != 'V') ||
+-		key[1] < '0' || key[1] > 'Z' ||
+-		(key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-			("illegal key tag, keyword not written\n"));
+-		return(5);
+-	}
+-
+-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+-		if (VpdInit(pAC, IoC) != 0) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-				("VPD init error\n"));
+-			return(6);
+-		}
+-	}
+-
+-	rtv = 0;
+-	len = strlen(buf);
+-	if (len > VPD_MAX_LEN) {
+-		/* cut it */
+-		len = VPD_MAX_LEN;
+-		rtv = 2;
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-			("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
+-	}
+-	if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-			("VPD write error\n"));
+-		return(rtv2);
+-	}
+-
+-	return(rtv);
+-}
+-
+-/*
+- *	Read the contents of the VPD EEPROM and copy it to the
+- *	VPD buffer if not already done. Remove the VPD keyword
+- *	'key' from the VPD buffer.
+- *	Only the keywords in the read/write area can be deleted.
+- *	Keywords in the read only area cannot be deleted.
+- *
+- * returns	0:	success, keyword was removed
+- *		1:	keyword not found
+- *		5:	keyword cannot be deleted
+- *		6:	fatal VPD error
+- */
+-int VpdDelete(
+-SK_AC	*pAC,	/* common data base */
+-SK_IOC	IoC,	/* IO Context */
+-char	*key)	/* keyword to read (e.g. "MN") */
+-{
+-	SK_VPD_PARA *p, vp;
+-	char *etp;
+-	int	vpd_size;
+-
+-	vpd_size = pAC->vpd.vpd_size;
+-
+-	SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
+-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+-		if (VpdInit(pAC, IoC) != 0) {
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-				("VPD init error\n"));
+-			return(6);
+-		}
+-	}
+-
+-	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
+-		if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
+-			/* try to delete read only keyword */
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-				("cannot delete RO keyword\n"));
+-			return(5);
+-		}
+-
+-		etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
+-
+-		vpd_move_para(vp.p_val+vp.p_len, etp+2,
+-			- ((int)(vp.p_len + 3)));
+-		if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
+-			pAC->vpd.v.vpd_status &= ~VPD_VALID;
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-				("VPD encoding error\n"));
+-			return(6);
+-		}
+-	}
+-	else {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-			("keyword not found\n"));
+-		return(1);
+-	}
+-
+-	return(0);
+-}
+-
+-/*
+- *	If the VPD buffer contains valid data write the VPD
+- *	read/write area back to the VPD EEPROM.
+- *
+- * returns	0:	success
+- *		3:	VPD transfer timeout
+- */
+-int VpdUpdate(
+-SK_AC	*pAC,	/* Adapters context */
+-SK_IOC	IoC)	/* IO Context */
+-{
+-	int vpd_size;
+-
+-	vpd_size = pAC->vpd.vpd_size;
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
+-	if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
+-		if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
+-			vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
+-
+-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+-				("transfer timed out\n"));
+-			return(3);
+-		}
+-	}
+-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));
+-	return(0);
+-}
+-
+diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
+deleted file mode 100644
+index b4e7502..0000000
+--- a/drivers/net/sk98lin/skxmac2.c
++++ /dev/null
+@@ -1,4160 +0,0 @@
+-/******************************************************************************
+- *
+- * Name:	skxmac2.c
+- * Project:	Gigabit Ethernet Adapters, Common Modules
+- * Version:	$Revision: 1.102 $
+- * Date:	$Date: 2003/10/02 16:53:58 $
+- * Purpose:	Contains functions to initialize the MACs and PHYs
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- *	(C)Copyright 1998-2002 SysKonnect.
+- *	(C)Copyright 2002-2003 Marvell.
+- *
+- *	This program is free software; you can redistribute it and/or modify
+- *	it under the terms of the GNU General Public License as published by
+- *	the Free Software Foundation; either version 2 of the License, or
+- *	(at your option) any later version.
+- *
+- *	The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-
+-/* typedefs *******************************************************************/
+-
+-/* BCOM PHY magic pattern list */
+-typedef struct s_PhyHack {
+-	int		PhyReg;		/* Phy register */
+-	SK_U16	PhyVal;		/* Value to write */
+-} BCOM_HACK;
+-
+-/* local variables ************************************************************/
+-
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+-	"@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#ifdef GENESIS
+-static BCOM_HACK BcomRegA1Hack[] = {
+- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
+- { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
+- { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
+- { 0, 0 }
+-};
+-static BCOM_HACK BcomRegC0Hack[] = {
+- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
+- { 0x15, 0x0A04 }, { 0x18, 0x0420 },
+- { 0, 0 }
+-};
+-#endif
+-
+-/* function prototypes ********************************************************/
+-#ifdef GENESIS
+-static void	SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void	SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
+-static int	SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
+-static int	SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
+-#endif /* GENESIS */
+-#ifdef YUKON
+-static void	SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
+-static int	SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
+-#endif /* YUKON */
+-#ifdef OTHER_PHY
+-static void	SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void	SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
+-static int	SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
+-static int	SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
+-#endif /* OTHER_PHY */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkXmPhyRead() - Read from XMAC PHY register
+- *
+- * Description:	reads a 16-bit word from XMAC PHY or ext. PHY
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkXmPhyRead(
+-SK_AC	*pAC,			/* Adapter Context */
+-SK_IOC	IoC,			/* I/O Context */
+-int		Port,			/* Port Index (MAC_1 + n) */
+-int		PhyReg,			/* Register Address (Offset) */
+-SK_U16	SK_FAR *pVal)	/* Pointer to Value */
+-{
+-	SK_U16		Mmu;
+-	SK_GEPORT	*pPrt;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-	
+-	/* write the PHY register's address */
+-	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
+-	
+-	/* get the PHY register's value */
+-	XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
+-	
+-	if (pPrt->PhyType != SK_PHY_XMAC) {
+-		do {
+-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+-			/* wait until 'Ready' is set */
+-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);
+-
+-		/* get the PHY register's value */
+-		XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
+-	}
+-}	/* SkXmPhyRead */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmPhyWrite() - Write to XMAC PHY register
+- *
+- * Description:	writes a 16-bit word to XMAC PHY or ext. PHY
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkXmPhyWrite(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-int		PhyReg,		/* Register Address (Offset) */
+-SK_U16	Val)		/* Value */
+-{
+-	SK_U16		Mmu;
+-	SK_GEPORT	*pPrt;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-	
+-	if (pPrt->PhyType != SK_PHY_XMAC) {
+-		do {
+-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+-			/* wait until 'Busy' is cleared */
+-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
+-	}
+-	
+-	/* write the PHY register's address */
+-	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
+-	
+-	/* write the PHY register's value */
+-	XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
+-	
+-	if (pPrt->PhyType != SK_PHY_XMAC) {
+-		do {
+-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+-			/* wait until 'Busy' is cleared */
+-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
+-	}
+-}	/* SkXmPhyWrite */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- *	SkGmPhyRead() - Read from GPHY register
+- *
+- * Description:	reads a 16-bit word from GPHY through MDIO
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGmPhyRead(
+-SK_AC	*pAC,			/* Adapter Context */
+-SK_IOC	IoC,			/* I/O Context */
+-int		Port,			/* Port Index (MAC_1 + n) */
+-int		PhyReg,			/* Register Address (Offset) */
+-SK_U16	SK_FAR *pVal)	/* Pointer to Value */
+-{
+-	SK_U16	Ctrl;
+-	SK_GEPORT	*pPrt;
+-#ifdef VCPU
+-	u_long SimCyle;
+-	u_long SimLowTime;
+-	
+-	VCPUgetTime(&SimCyle, &SimLowTime);
+-	VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
+-		PhyReg, SimCyle, SimLowTime);
+-#endif /* VCPU */
+-	
+-	pPrt = &pAC->GIni.GP[Port];
+-	
+-	/* set PHY-Register offset and 'Read' OpCode (= 1) */
+-	*pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
+-		GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
+-
+-	GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
+-
+-	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+-	
+-	/* additional check for MDC/MDIO activity */
+-	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
+-		*pVal = 0;
+-		return;
+-	}
+-
+-	*pVal |= GM_SMI_CT_BUSY;
+-	
+-	do {
+-#ifdef VCPU
+-		VCPUwaitTime(1000);
+-#endif /* VCPU */
+-
+-		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+-
+-	/* wait until 'ReadValid' is set */
+-	} while (Ctrl == *pVal);
+-	
+-	/* get the PHY register's value */
+-	GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
+-
+-#ifdef VCPU
+-	VCPUgetTime(&SimCyle, &SimLowTime);
+-	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
+-		SimCyle, SimLowTime);
+-#endif /* VCPU */
+-
+-}	/* SkGmPhyRead */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGmPhyWrite() - Write to GPHY register
+- *
+- * Description:	writes a 16-bit word to GPHY through MDIO
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGmPhyWrite(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-int		PhyReg,		/* Register Address (Offset) */
+-SK_U16	Val)		/* Value */
+-{
+-	SK_U16	Ctrl;
+-	SK_GEPORT	*pPrt;
+-#ifdef VCPU
+-	SK_U32	DWord;
+-	u_long	SimCyle;
+-	u_long	SimLowTime;
+-	
+-	VCPUgetTime(&SimCyle, &SimLowTime);
+-	VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
+-		PhyReg, Val, SimCyle, SimLowTime);
+-#endif /* VCPU */
+-	
+-	pPrt = &pAC->GIni.GP[Port];
+-	
+-	/* write the PHY register's value */
+-	GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
+-	
+-	/* set PHY-Register offset and 'Write' OpCode (= 0) */
+-	Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
+-
+-	GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
+-
+-	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+-	
+-	/* additional check for MDC/MDIO activity */
+-	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
+-		return;
+-	}
+-	
+-	Val |= GM_SMI_CT_BUSY;
+-
+-	do {
+-#ifdef VCPU
+-		/* read Timer value */
+-		SK_IN32(IoC, B2_TI_VAL, &DWord);
+-
+-		VCPUwaitTime(1000);
+-#endif /* VCPU */
+-
+-		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+-
+-	/* wait until 'Busy' is cleared */
+-	} while (Ctrl == Val);
+-	
+-#ifdef VCPU
+-	VCPUgetTime(&SimCyle, &SimLowTime);
+-	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
+-		SimCyle, SimLowTime);
+-#endif /* VCPU */
+-
+-}	/* SkGmPhyWrite */
+-#endif /* YUKON */
+-
+-
+-#ifdef SK_DIAG
+-/******************************************************************************
+- *
+- *	SkGePhyRead() - Read from PHY register
+- *
+- * Description:	calls a read PHY routine dep. on board type
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGePhyRead(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-int		PhyReg,		/* Register Address (Offset) */
+-SK_U16	*pVal)		/* Pointer to Value */
+-{
+-	void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
+-
+-	if (pAC->GIni.GIGenesis) {
+-		r_func = SkXmPhyRead;
+-	}
+-	else {
+-		r_func = SkGmPhyRead;
+-	}
+-	
+-	r_func(pAC, IoC, Port, PhyReg, pVal);
+-}	/* SkGePhyRead */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGePhyWrite() - Write to PHY register
+- *
+- * Description:	calls a write PHY routine dep. on board type
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGePhyWrite(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* I/O Context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-int		PhyReg,		/* Register Address (Offset) */
+-SK_U16	Val)		/* Value */
+-{
+-	void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
+-
+-	if (pAC->GIni.GIGenesis) {
+-		w_func = SkXmPhyWrite;
+-	}
+-	else {
+-		w_func = SkGmPhyWrite;
+-	}
+-	
+-	w_func(pAC, IoC, Port, PhyReg, Val);
+-}	/* SkGePhyWrite */
+-#endif /* SK_DIAG */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacPromiscMode() - Enable / Disable Promiscuous Mode
+- *
+- * Description:
+- *   enables / disables promiscuous mode by setting Mode Register (XMAC) or
+- *   Receive Control Register (GMAC) dep. on board type   	
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacPromiscMode(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port,	/* Port Index (MAC_1 + n) */
+-SK_BOOL	Enable)	/* Enable / Disable */
+-{
+-#ifdef YUKON
+-	SK_U16	RcReg;
+-#endif
+-#ifdef GENESIS
+-	SK_U32	MdReg;
+-#endif	
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-		/* enable or disable promiscuous mode */
+-		if (Enable) {
+-			MdReg |= XM_MD_ENA_PROM;
+-		}
+-		else {
+-			MdReg &= ~XM_MD_ENA_PROM;
+-		}
+-		/* setup Mode Register */
+-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		
+-		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
+-		
+-		/* enable or disable unicast and multicast filtering */
+-		if (Enable) {
+-			RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+-		}
+-		else {
+-			RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+-		}
+-		/* setup Receive Control Register */
+-		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
+-	}
+-#endif /* YUKON */
+-
+-}	/* SkMacPromiscMode*/
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacHashing() - Enable / Disable Hashing
+- *
+- * Description:
+- *   enables / disables hashing by setting Mode Register (XMAC) or
+- *   Receive Control Register (GMAC) dep. on board type		
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacHashing(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port,	/* Port Index (MAC_1 + n) */
+-SK_BOOL	Enable)	/* Enable / Disable */
+-{
+-#ifdef YUKON
+-	SK_U16	RcReg;
+-#endif	
+-#ifdef GENESIS
+-	SK_U32	MdReg;
+-#endif
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-		/* enable or disable hashing */
+-		if (Enable) {
+-			MdReg |= XM_MD_ENA_HASH;
+-		}
+-		else {
+-			MdReg &= ~XM_MD_ENA_HASH;
+-		}
+-		/* setup Mode Register */
+-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		
+-		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
+-		
+-		/* enable or disable multicast filtering */
+-		if (Enable) {
+-			RcReg |= GM_RXCR_MCF_ENA;
+-		}
+-		else {
+-			RcReg &= ~GM_RXCR_MCF_ENA;
+-		}
+-		/* setup Receive Control Register */
+-		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
+-	}
+-#endif /* YUKON */
+-
+-}	/* SkMacHashing*/
+-
+-
+-#ifdef SK_DIAG
+-/******************************************************************************
+- *
+- *	SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
+- *
+- * Description:
+- *	The features
+- *	 - FCS stripping,					SK_STRIP_FCS_ON/OFF
+- *	 - pad byte stripping,				SK_STRIP_PAD_ON/OFF
+- *	 - don't set XMR_FS_ERR in status	SK_LENERR_OK_ON/OFF
+- *	   for inrange length error frames
+- *	 - don't set XMR_FS_ERR in status	SK_BIG_PK_OK_ON/OFF
+- *	   for frames > 1514 bytes
+- *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
+- *
+- *	for incoming packets may be enabled/disabled by this function.
+- *	Additional modes may be added later.
+- *	Multiple modes can be enabled/disabled at the same time.
+- *	The new configuration is written to the Rx Command register immediately.
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmSetRxCmd(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
+-					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
+-{
+-	SK_U16	OldRxCmd;
+-	SK_U16	RxCmd;
+-
+-	XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
+-
+-	RxCmd = OldRxCmd;
+-	
+-	switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
+-	case SK_STRIP_FCS_ON:
+-		RxCmd |= XM_RX_STRIP_FCS;
+-		break;
+-	case SK_STRIP_FCS_OFF:
+-		RxCmd &= ~XM_RX_STRIP_FCS;
+-		break;
+-	}
+-
+-	switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
+-	case SK_STRIP_PAD_ON:
+-		RxCmd |= XM_RX_STRIP_PAD;
+-		break;
+-	case SK_STRIP_PAD_OFF:
+-		RxCmd &= ~XM_RX_STRIP_PAD;
+-		break;
+-	}
+-
+-	switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
+-	case SK_LENERR_OK_ON:
+-		RxCmd |= XM_RX_LENERR_OK;
+-		break;
+-	case SK_LENERR_OK_OFF:
+-		RxCmd &= ~XM_RX_LENERR_OK;
+-		break;
+-	}
+-
+-	switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
+-	case SK_BIG_PK_OK_ON:
+-		RxCmd |= XM_RX_BIG_PK_OK;
+-		break;
+-	case SK_BIG_PK_OK_OFF:
+-		RxCmd &= ~XM_RX_BIG_PK_OK;
+-		break;
+-	}
+-
+-	switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
+-	case SK_SELF_RX_ON:
+-		RxCmd |= XM_RX_SELF_RX;
+-		break;
+-	case SK_SELF_RX_OFF:
+-		RxCmd &= ~XM_RX_SELF_RX;
+-		break;
+-	}
+-
+-	/* Write the new mode to the Rx command register if required */
+-	if (OldRxCmd != RxCmd) {
+-		XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
+-	}
+-}	/* SkXmSetRxCmd */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
+- *
+- * Description:
+- *	The features
+- *	 - FCS (CRC) stripping,				SK_STRIP_FCS_ON/OFF
+- *	 - don't set GMR_FS_LONG_ERR		SK_BIG_PK_OK_ON/OFF
+- *	   for frames > 1514 bytes
+- *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
+- *
+- *	for incoming packets may be enabled/disabled by this function.
+- *	Additional modes may be added later.
+- *	Multiple modes can be enabled/disabled at the same time.
+- *	The new configuration is written to the Rx Command register immediately.
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGmSetRxCmd(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
+-					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
+-{
+-	SK_U16	OldRxCmd;
+-	SK_U16	RxCmd;
+-
+-	if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
+-		
+-		GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
+-
+-		RxCmd = OldRxCmd;
+-
+-		if ((Mode & SK_STRIP_FCS_ON) != 0) {
+-			RxCmd |= GM_RXCR_CRC_DIS;
+-		}
+-		else {
+-			RxCmd &= ~GM_RXCR_CRC_DIS;
+-		}
+-		/* Write the new mode to the Rx control register if required */
+-		if (OldRxCmd != RxCmd) {
+-			GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
+-		}
+-	}
+-
+-	if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
+-		
+-		GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
+-
+-		RxCmd = OldRxCmd;
+-
+-		if ((Mode & SK_BIG_PK_OK_ON) != 0) {
+-			RxCmd |= GM_SMOD_JUMBO_ENA;
+-		}
+-		else {
+-			RxCmd &= ~GM_SMOD_JUMBO_ENA;
+-		}
+-		/* Write the new mode to the Rx control register if required */
+-		if (OldRxCmd != RxCmd) {
+-			GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
+-		}
+-	}
+-}	/* SkGmSetRxCmd */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
+- *
+- * Description:	modifies the MAC's Rx Control reg. dep. on board type
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacSetRxCmd(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-int		Mode)		/* Rx Mode */
+-{
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		SkXmSetRxCmd(pAC, IoC, Port, Mode);
+-	}
+-	else {
+-		
+-		SkGmSetRxCmd(pAC, IoC, Port, Mode);
+-	}
+-
+-}	/* SkMacSetRxCmd */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacCrcGener() - Enable / Disable CRC Generation
+- *
+- * Description:	enables / disables CRC generation dep. on board type
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacCrcGener(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port,	/* Port Index (MAC_1 + n) */
+-SK_BOOL	Enable)	/* Enable / Disable */
+-{
+-	SK_U16	Word;
+-
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		XM_IN16(IoC, Port, XM_TX_CMD, &Word);
+-
+-		if (Enable) {
+-			Word &= ~XM_TX_NO_CRC;
+-		}
+-		else {
+-			Word |= XM_TX_NO_CRC;
+-		}
+-		/* setup Tx Command Register */
+-		XM_OUT16(IoC, Port, XM_TX_CMD, Word);
+-	}
+-	else {
+-		
+-		GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
+-		
+-		if (Enable) {
+-			Word &= ~GM_TXCR_CRC_DIS;
+-		}
+-		else {
+-			Word |= GM_TXCR_CRC_DIS;
+-		}
+-		/* setup Tx Control Register */
+-		GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
+-	}
+-
+-}	/* SkMacCrcGener*/
+-
+-#endif /* SK_DIAG */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkXmClrExactAddr() - Clear Exact Match Address Registers
+- *
+- * Description:
+- *	All Exact Match Address registers of the XMAC 'Port' will be
+- *	cleared starting with 'StartNum' up to (and including) the
+- *	Exact Match address number of 'StopNum'.
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkXmClrExactAddr(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-int		StartNum,	/* Begin with this Address Register Index (0..15) */
+-int		StopNum)	/* Stop after finished with this Register Idx (0..15) */
+-{
+-	int		i;
+-	SK_U16	ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
+-
+-	if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
+-		StartNum > StopNum) {
+-
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
+-		return;
+-	}
+-
+-	for (i = StartNum; i <= StopNum; i++) {
+-		XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
+-	}
+-}	/* SkXmClrExactAddr */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
+- *
+- * Description:
+- *	Flush the transmit FIFO of the MAC specified by the index 'Port'
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacFlushTxFifo(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-#ifdef GENESIS
+-	SK_U32	MdReg;
+-
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-
+-		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		/* no way to flush the FIFO we have to issue a reset */
+-		/* TBD */
+-	}
+-#endif /* YUKON */
+-
+-}	/* SkMacFlushTxFifo */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacFlushRxFifo() - Flush the MAC's receive FIFO
+- *
+- * Description:
+- *	Flush the receive FIFO of the MAC specified by the index 'Port'
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkMacFlushRxFifo(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-#ifdef GENESIS
+-	SK_U32	MdReg;
+-
+-	if (pAC->GIni.GIGenesis) {
+-
+-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-
+-		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		/* no way to flush the FIFO we have to issue a reset */
+-		/* TBD */
+-	}
+-#endif /* YUKON */
+-
+-}	/* SkMacFlushRxFifo */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkXmSoftRst() - Do a XMAC software reset
+- *
+- * Description:
+- *	The PHY registers should not be destroyed during this
+- *	kind of software reset. Therefore the XMAC Software Reset
+- *	(XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
+- *
+- *	The software reset is done by
+- *		- disabling the Rx and Tx state machine,
+- *		- resetting the statistics module,
+- *		- clear all other significant XMAC Mode,
+- *		  Command, and Control Registers
+- *		- clearing the Hash Register and the
+- *		  Exact Match Address registers, and
+- *		- flushing the XMAC's Rx and Tx FIFOs.
+- *
+- * Note:
+- *	Another requirement when stopping the XMAC is to
+- *	avoid sending corrupted frames on the network.
+- *	Disabling the Tx state machine will NOT interrupt
+- *	the currently transmitted frame. But we must take care
+- *	that the Tx FIFO is cleared AFTER the current frame
+- *	is complete sent to the network.
+- *
+- *	It takes about 12ns to send a frame with 1538 bytes.
+- *	One PCI clock goes at least 15ns (66MHz). Therefore
+- *	after reading XM_GP_PORT back, we are sure that the
+- *	transmitter is disabled AND idle. And this means
+- *	we may flush the transmit FIFO now.
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmSoftRst(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_U16	ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
+-	
+-	/* reset the statistics module */
+-	XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
+-
+-	/* disable all XMAC IRQs */
+-	XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
+-	
+-	XM_OUT32(IoC, Port, XM_MODE, 0);		/* clear Mode Reg */
+-	
+-	XM_OUT16(IoC, Port, XM_TX_CMD, 0);		/* reset TX CMD Reg */
+-	XM_OUT16(IoC, Port, XM_RX_CMD, 0);		/* reset RX CMD Reg */
+-	
+-	/* disable all PHY IRQs */
+-	switch (pAC->GIni.GP[Port].PhyType) {
+-	case SK_PHY_BCOM:
+-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
+-			break;
+-#ifdef OTHER_PHY
+-		case SK_PHY_LONE:
+-			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
+-			break;
+-		case SK_PHY_NAT:
+-			/* todo: National
+-			 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
+-			break;
+-#endif /* OTHER_PHY */
+-	}
+-
+-	/* clear the Hash Register */
+-	XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
+-
+-	/* clear the Exact Match Address registers */
+-	SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
+-	
+-	/* clear the Source Check Address registers */
+-	XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
+-
+-}	/* SkXmSoftRst */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmHardRst() - Do a XMAC hardware reset
+- *
+- * Description:
+- *	The XMAC of the specified 'Port' and all connected devices
+- *	(PHY and SERDES) will receive a reset signal on its *Reset pins.
+- *	External PHYs must be reset by clearing a bit in the GPIO register
+- *  (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
+- *
+- * ATTENTION:
+- * 	It is absolutely necessary to reset the SW_RST Bit first
+- *	before calling this function.
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmHardRst(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_U32	Reg;
+-	int		i;
+-	int		TOut;
+-	SK_U16	Word;
+-
+-	for (i = 0; i < 4; i++) {
+-		/* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
+-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+-
+-		TOut = 0;
+-		do {
+-			if (TOut++ > 10000) {
+-				/*
+-				 * Adapter seems to be in RESET state.
+-				 * Registers cannot be written.
+-				 */
+-				return;
+-			}
+-
+-			SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+-			
+-			SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
+-		
+-		} while ((Word & MFF_SET_MAC_RST) == 0);
+-	}
+-
+-	/* For external PHYs there must be special handling */
+-	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
+-		
+-		SK_IN32(IoC, B2_GP_IO, &Reg);
+-		
+-		if (Port == 0) {
+-			Reg |= GP_DIR_0; 	/* set to output */
+-			Reg &= ~GP_IO_0;	/* set PHY reset (active low) */
+-		}
+-		else {
+-			Reg |= GP_DIR_2;	/* set to output */
+-			Reg &= ~GP_IO_2;	/* set PHY reset (active low) */
+-		}
+-		/* reset external PHY */
+-		SK_OUT32(IoC, B2_GP_IO, Reg);
+-
+-		/* short delay */
+-		SK_IN32(IoC, B2_GP_IO, &Reg);
+-	}
+-}	/* SkXmHardRst */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmClearRst() - Release the PHY & XMAC reset
+- *
+- * Description:
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmClearRst(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_U32	DWord;
+-	
+-	/* clear HW reset */
+-	SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+-
+-	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
+-
+-		SK_IN32(IoC, B2_GP_IO, &DWord);
+-
+-		if (Port == 0) {
+-			DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
+-		}
+-		else {
+-			DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
+-		}
+-		/* Clear PHY reset */
+-		SK_OUT32(IoC, B2_GP_IO, DWord);
+-
+-		/* Enable GMII interface */
+-		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
+-	}
+-}	/* SkXmClearRst */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- *	SkGmSoftRst() - Do a GMAC software reset
+- *
+- * Description:
+- *	The GPHY registers should not be destroyed during this
+- *	kind of software reset.
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGmSoftRst(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_U16	EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
+-	SK_U16  RxCtrl;
+-
+-	/* reset the statistics module */
+-
+-	/* disable all GMAC IRQs */
+-	SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
+-	
+-	/* disable all PHY IRQs */
+-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
+-	
+-	/* clear the Hash Register */
+-	GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
+-
+-	/* Enable Unicast and Multicast filtering */
+-	GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
+-	
+-	GM_OUT16(IoC, Port, GM_RX_CTRL,
+-		(SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
+-
+-}	/* SkGmSoftRst */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGmHardRst() - Do a GMAC hardware reset
+- *
+- * Description:
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGmHardRst(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_U32	DWord;
+-	
+-	/* WA code for COMA mode */
+-	if (pAC->GIni.GIYukonLite &&
+-		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
+-		
+-		SK_IN32(IoC, B2_GP_IO, &DWord);
+-
+-		DWord |= (GP_DIR_9 | GP_IO_9);
+-
+-		/* set PHY reset */
+-		SK_OUT32(IoC, B2_GP_IO, DWord);
+-	}
+-
+-	/* set GPHY Control reset */
+-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
+-
+-	/* set GMAC Control reset */
+-	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
+-
+-}	/* SkGmHardRst */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGmClearRst() - Release the GPHY & GMAC reset
+- *
+- * Description:
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGmClearRst(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_U32	DWord;
+-	
+-#ifdef XXX
+-		/* clear GMAC Control reset */
+-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
+-
+-		/* set GMAC Control reset */
+-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
+-#endif /* XXX */
+-
+-	/* WA code for COMA mode */
+-	if (pAC->GIni.GIYukonLite &&
+-		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
+-		
+-		SK_IN32(IoC, B2_GP_IO, &DWord);
+-
+-		DWord |= GP_DIR_9;		/* set to output */
+-		DWord &= ~GP_IO_9;		/* clear PHY reset (active high) */
+-
+-		/* clear PHY reset */
+-		SK_OUT32(IoC, B2_GP_IO, DWord);
+-	}
+-
+-	/* set HWCFG_MODE */
+-	DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
+-		GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
+-		(pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
+-		GPC_HWCFG_GMII_FIB);
+-
+-	/* set GPHY Control reset */
+-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
+-
+-	/* release GPHY Control reset */
+-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
+-
+-#ifdef VCPU
+-	VCpuWait(9000);
+-#endif /* VCPU */
+-
+-	/* clear GMAC Control reset */
+-	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+-
+-#ifdef VCPU
+-	VCpuWait(2000);
+-	
+-	SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
+-			
+-	SK_IN32(IoC, B0_ISRC, &DWord);
+-#endif /* VCPU */
+-
+-}	/* SkGmClearRst */
+-#endif /* YUKON */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacSoftRst() - Do a MAC software reset
+- *
+- * Description:	calls a MAC software reset routine dep. on board type
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacSoftRst(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* disable receiver and transmitter */
+-	SkMacRxTxDisable(pAC, IoC, Port);
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		SkXmSoftRst(pAC, IoC, Port);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		
+-		SkGmSoftRst(pAC, IoC, Port);
+-	}
+-#endif /* YUKON */
+-
+-	/* flush the MAC's Rx and Tx FIFOs */
+-	SkMacFlushTxFifo(pAC, IoC, Port);
+-	
+-	SkMacFlushRxFifo(pAC, IoC, Port);
+-
+-	pPrt->PState = SK_PRT_STOP;
+-
+-}	/* SkMacSoftRst */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacHardRst() - Do a MAC hardware reset
+- *
+- * Description:	calls a MAC hardware reset routine dep. on board type
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacHardRst(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port)	/* Port Index (MAC_1 + n) */
+-{
+-	
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		SkXmHardRst(pAC, IoC, Port);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		
+-		SkGmHardRst(pAC, IoC, Port);
+-	}
+-#endif /* YUKON */
+-
+-	pAC->GIni.GP[Port].PState = SK_PRT_RESET;
+-
+-}	/* SkMacHardRst */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkXmInitMac() - Initialize the XMAC II
+- *
+- * Description:
+- *	Initialize the XMAC of the specified port.
+- *	The XMAC must be reset or stopped before calling this function.
+- *
+- * Note:
+- *	The XMAC's Rx and Tx state machine is still disabled when returning.
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkXmInitMac(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	int			i;
+-	SK_U16		SWord;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PState == SK_PRT_STOP) {
+-		/* Port State: SK_PRT_STOP */
+-		/* Verify that the reset bit is cleared */
+-		SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
+-
+-		if ((SWord & MFF_SET_MAC_RST) != 0) {
+-			/* PState does not match HW state */
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
+-			/* Correct it */
+-			pPrt->PState = SK_PRT_RESET;
+-		}
+-	}
+-
+-	if (pPrt->PState == SK_PRT_RESET) {
+-
+-		SkXmClearRst(pAC, IoC, Port);
+-
+-		if (pPrt->PhyType != SK_PHY_XMAC) {
+-			/* read Id from external PHY (all have the same address) */
+-			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
+-
+-			/*
+-			 * Optimize MDIO transfer by suppressing preamble.
+-			 * Must be done AFTER first access to BCOM chip.
+-			 */
+-			XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
+-			
+-			XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
+-
+-			if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
+-				/*
+-				 * Workaround BCOM Errata for the C0 type.
+-				 * Write magic patterns to reserved registers.
+-				 */
+-				i = 0;
+-				while (BcomRegC0Hack[i].PhyReg != 0) {
+-					SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
+-						BcomRegC0Hack[i].PhyVal);
+-					i++;
+-				}
+-			}
+-			else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
+-				/*
+-				 * Workaround BCOM Errata for the A1 type.
+-				 * Write magic patterns to reserved registers.
+-				 */
+-				i = 0;
+-				while (BcomRegA1Hack[i].PhyReg != 0) {
+-					SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
+-						BcomRegA1Hack[i].PhyVal);
+-					i++;
+-				}
+-			}
+-
+-			/*
+-			 * Workaround BCOM Errata (#10523) for all BCom PHYs.
+-			 * Disable Power Management after reset.
+-			 */
+-			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
+-			
+-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+-				(SK_U16)(SWord | PHY_B_AC_DIS_PM));
+-
+-			/* PHY LED initialization is done in SkGeXmitLED() */
+-		}
+-
+-		/* Dummy read the Interrupt source register */
+-		XM_IN16(IoC, Port, XM_ISRC, &SWord);
+-		
+-		/*
+-		 * The auto-negotiation process starts immediately after
+-		 * clearing the reset. The auto-negotiation process should be
+-		 * started by the SIRQ, therefore stop it here immediately.
+-		 */
+-		SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
+-
+-#ifdef TEST_ONLY
+-		/* temp. code: enable signal detect */
+-		/* WARNING: do not override GMII setting above */
+-		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
+-#endif
+-	}
+-
+-	/*
+-	 * configure the XMACs Station Address
+-	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
+-	 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
+-	 */
+-	for (i = 0; i < 3; i++) {
+-		/*
+-		 * The following 2 statements are together endianess
+-		 * independent. Remember this when changing.
+-		 */
+-		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
+-		
+-		XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
+-	}
+-
+-	/* Tx Inter Packet Gap (XM_TX_IPG):	use default */
+-	/* Tx High Water Mark (XM_TX_HI_WM):	use default */
+-	/* Tx Low Water Mark (XM_TX_LO_WM):	use default */
+-	/* Host Request Threshold (XM_HT_THR):	use default */
+-	/* Rx Request Threshold (XM_RX_THR):	use default */
+-	/* Rx Low Water Mark (XM_RX_LO_WM):	use default */
+-
+-	/* configure Rx High Water Mark (XM_RX_HI_WM) */
+-	XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
+-
+-	/* Configure Tx Request Threshold */
+-	SWord = SK_XM_THR_SL;				/* for single port */
+-
+-	if (pAC->GIni.GIMacsFound > 1) {
+-		switch (pAC->GIni.GIPortUsage) {
+-		case SK_RED_LINK:
+-			SWord = SK_XM_THR_REDL;		/* redundant link */
+-			break;
+-		case SK_MUL_LINK:
+-			SWord = SK_XM_THR_MULL;		/* load balancing */
+-			break;
+-		case SK_JUMBO_LINK:
+-			SWord = SK_XM_THR_JUMBO;	/* jumbo frames */
+-			break;
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
+-			break;
+-		}
+-	}
+-	XM_OUT16(IoC, Port, XM_TX_THR, SWord);
+-
+-	/* setup register defaults for the Tx Command Register */
+-	XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
+-
+-	/* setup register defaults for the Rx Command Register */
+-	SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
+-
+-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+-		SWord |= XM_RX_BIG_PK_OK;
+-	}
+-
+-	if (pPrt->PLinkMode == SK_LMODE_HALF) {
+-		/*
+-		 * If in manual half duplex mode the other side might be in
+-		 * full duplex mode, so ignore if a carrier extension is not seen
+-		 * on frames received
+-		 */
+-		SWord |= XM_RX_DIS_CEXT;
+-	}
+-	
+-	XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
+-
+-	/*
+-	 * setup register defaults for the Mode Register
+-	 *	- Don't strip error frames to avoid Store & Forward
+-	 *	  on the Rx side.
+-	 *	- Enable 'Check Station Address' bit
+-	 *	- Enable 'Check Address Array' bit
+-	 */
+-	XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
+-
+-	/*
+-	 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
+-	 *	- Enable all bits excepting 'Octets Rx OK Low CntOv'
+-	 *	  and 'Octets Rx OK Hi Cnt Ov'.
+-	 */
+-	XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
+-
+-	/*
+-	 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
+-	 *	- Enable all bits excepting 'Octets Tx OK Low CntOv'
+-	 *	  and 'Octets Tx OK Hi Cnt Ov'.
+-	 */
+-	XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
+-
+-	/*
+-	 * Do NOT init XMAC interrupt mask here.
+-	 * All interrupts remain disable until link comes up!
+-	 */
+-
+-	/*
+-	 * Any additional configuration changes may be done now.
+-	 * The last action is to enable the Rx and Tx state machine.
+-	 * This should be done after the auto-negotiation process
+-	 * has been completed successfully.
+-	 */
+-}	/* SkXmInitMac */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- *	SkGmInitMac() - Initialize the GMAC
+- *
+- * Description:
+- *	Initialize the GMAC of the specified port.
+- *	The GMAC must be reset or stopped before calling this function.
+- *
+- * Note:
+- *	The GMAC's Rx and Tx state machine is still disabled when returning.
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkGmInitMac(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	int			i;
+-	SK_U16		SWord;
+-	SK_U32		DWord;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PState == SK_PRT_STOP) {
+-		/* Port State: SK_PRT_STOP */
+-		/* Verify that the reset bit is cleared */
+-		SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
+-		
+-		if ((DWord & GMC_RST_SET) != 0) {
+-			/* PState does not match HW state */
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
+-			/* Correct it */
+-			pPrt->PState = SK_PRT_RESET;
+-		}
+-	}
+-
+-	if (pPrt->PState == SK_PRT_RESET) {
+-		
+-		SkGmHardRst(pAC, IoC, Port);
+-
+-		SkGmClearRst(pAC, IoC, Port);
+-		
+-		/* Auto-negotiation ? */
+-		if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+-			/* Auto-negotiation disabled */
+-
+-			/* get General Purpose Control */
+-			GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
+-
+-			/* disable auto-update for speed, duplex and flow-control */
+-			SWord |= GM_GPCR_AU_ALL_DIS;
+-			
+-			/* setup General Purpose Control Register */
+-			GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
+-			
+-			SWord = GM_GPCR_AU_ALL_DIS;
+-		}
+-		else {
+-			SWord = 0;
+-		}
+-
+-		/* speed settings */
+-		switch (pPrt->PLinkSpeed) {
+-		case SK_LSPEED_AUTO:
+-		case SK_LSPEED_1000MBPS:
+-			SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
+-			break;
+-		case SK_LSPEED_100MBPS:
+-			SWord |= GM_GPCR_SPEED_100;
+-			break;
+-		case SK_LSPEED_10MBPS:
+-			break;
+-		}
+-
+-		/* duplex settings */
+-		if (pPrt->PLinkMode != SK_LMODE_HALF) {
+-			/* set full duplex */
+-			SWord |= GM_GPCR_DUP_FULL;
+-		}
+-
+-		/* flow-control settings */
+-		switch (pPrt->PFlowCtrlMode) {
+-		case SK_FLOW_MODE_NONE:
+-			/* set Pause Off */
+-			SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
+-			/* disable Tx & Rx flow-control */
+-			SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+-			break;
+-		case SK_FLOW_MODE_LOC_SEND:
+-			/* disable Rx flow-control */
+-			SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+-			break;
+-		case SK_FLOW_MODE_SYMMETRIC:
+-		case SK_FLOW_MODE_SYM_OR_REM:
+-			/* enable Tx & Rx flow-control */
+-			break;
+-		}
+-
+-		/* setup General Purpose Control Register */
+-		GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
+-
+-		/* dummy read the Interrupt Source Register */
+-		SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
+-		
+-#ifndef VCPU
+-		/* read Id from PHY */
+-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
+-		
+-		SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
+-#endif /* VCPU */
+-	}
+-
+-	(void)SkGmResetCounter(pAC, IoC, Port);
+-
+-	/* setup Transmit Control Register */
+-	GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
+-
+-	/* setup Receive Control Register */
+-	GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
+-		GM_RXCR_CRC_DIS);
+-
+-	/* setup Transmit Flow Control Register */
+-	GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
+-
+-	/* setup Transmit Parameter Register */
+-#ifdef VCPU
+-	GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
+-#endif /* VCPU */
+-
+-    SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
+-			TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
+-			TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
+-	
+-	GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
+-
+-	/* configure the Serial Mode Register */
+-#ifdef VCPU
+-	GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
+-#endif /* VCPU */
+-	
+-	SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
+-
+-	if (pPrt->PMacLimit4) {
+-		/* reset of collision counter after 4 consecutive collisions */
+-		SWord |= GM_SMOD_LIMIT_4;
+-	}
+-
+-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+-		/* enable jumbo mode (Max. Frame Length = 9018) */
+-		SWord |= GM_SMOD_JUMBO_ENA;
+-	}
+-	
+-	GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
+-	
+-	/*
+-	 * configure the GMACs Station Addresses
+-	 * in PROM you can find our addresses at:
+-	 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
+-	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
+-	 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
+-	 */
+-
+-	for (i = 0; i < 3; i++) {
+-		/*
+-		 * The following 2 statements are together endianess
+-		 * independent. Remember this when changing.
+-		 */
+-		/* physical address: will be used for pause frames */
+-		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
+-
+-#ifdef WA_DEV_16
+-		/* WA for deviation #16 */
+-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
+-			/* swap the address bytes */
+-			SWord = ((SWord & 0xff00) >> 8)	| ((SWord & 0x00ff) << 8);
+-
+-			/* write to register in reversed order */
+-			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
+-		}
+-		else {
+-			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
+-		}
+-#else		
+-		GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
+-#endif /* WA_DEV_16 */
+-		
+-		/* virtual address: will be used for data */
+-		SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
+-
+-		GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
+-		
+-		/* reset Multicast filtering Hash registers 1-3 */
+-		GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
+-	}
+-
+-	/* reset Multicast filtering Hash register 4 */
+-	GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
+-
+-	/* enable interrupt mask for counter overflows */
+-	GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
+-	GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
+-	GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
+-
+-#if defined(SK_DIAG) || defined(DEBUG)
+-	/* read General Purpose Status */
+-	GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("MAC Stat Reg.=0x%04X\n", SWord));
+-#endif /* SK_DIAG || DEBUG */
+-
+-#ifdef SK_DIAG
+-	c_print("MAC Stat Reg=0x%04X\n", SWord);
+-#endif /* SK_DIAG */
+-
+-}	/* SkGmInitMac */
+-#endif /* YUKON */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkXmInitDupMd() - Initialize the XMACs Duplex Mode
+- *
+- * Description:
+- *	This function initializes the XMACs Duplex Mode.
+- *	It should be called after successfully finishing
+- *	the Auto-negotiation Process
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmInitDupMd(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	switch (pAC->GIni.GP[Port].PLinkModeStatus) {
+-	case SK_LMODE_STAT_AUTOHALF:
+-	case SK_LMODE_STAT_HALF:
+-		/* Configuration Actions for Half Duplex Mode */
+-		/*
+-		 * XM_BURST = default value. We are probable not quick
+-		 * 	enough at the 'XMAC' bus to burst 8kB.
+-		 *	The XMAC stops bursting if no transmit frames
+-		 *	are available or the burst limit is exceeded.
+-		 */
+-		/* XM_TX_RT_LIM = default value (15) */
+-		/* XM_TX_STIME = default value (0xff = 4096 bit times) */
+-		break;
+-	case SK_LMODE_STAT_AUTOFULL:
+-	case SK_LMODE_STAT_FULL:
+-		/* Configuration Actions for Full Duplex Mode */
+-		/*
+-		 * The duplex mode is configured by the PHY,
+-		 * therefore it seems to be that there is nothing
+-		 * to do here.
+-		 */
+-		break;
+-	case SK_LMODE_STAT_UNKNOWN:
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
+-		break;
+-	}
+-}	/* SkXmInitDupMd */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
+- *
+- * Description:
+- *	This function initializes the Pause Mode which should
+- *	be used for this port.
+- *	It should be called after successfully finishing
+- *	the Auto-negotiation Process
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmInitPauseMd(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U32		DWord;
+-	SK_U16		Word;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+-	
+-	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
+-		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
+-
+-		/* Disable Pause Frame Reception */
+-		Word |= XM_MMU_IGN_PF;
+-	}
+-	else {
+-		/*
+-		 * enabling pause frame reception is required for 1000BT
+-		 * because the XMAC is not reset if the link is going down
+-		 */
+-		/* Enable Pause Frame Reception */
+-		Word &= ~XM_MMU_IGN_PF;
+-	}	
+-	
+-	XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
+-
+-	XM_IN32(IoC, Port, XM_MODE, &DWord);
+-
+-	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
+-		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
+-
+-		/*
+-		 * Configure Pause Frame Generation
+-		 * Use internal and external Pause Frame Generation.
+-		 * Sending pause frames is edge triggered.
+-		 * Send a Pause frame with the maximum pause time if
+-		 * internal oder external FIFO full condition occurs.
+-		 * Send a zero pause time frame to re-start transmission.
+-		 */
+-
+-		/* XM_PAUSE_DA = '010000C28001' (default) */
+-
+-		/* XM_MAC_PTIME = 0xffff (maximum) */
+-		/* remember this value is defined in big endian (!) */
+-		XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
+-
+-		/* Set Pause Mode in Mode Register */
+-		DWord |= XM_PAUSE_MODE;
+-
+-		/* Set Pause Mode in MAC Rx FIFO */
+-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
+-	}
+-	else {
+-		/*
+-		 * disable pause frame generation is required for 1000BT
+-		 * because the XMAC is not reset if the link is going down
+-		 */
+-		/* Disable Pause Mode in Mode Register */
+-		DWord &= ~XM_PAUSE_MODE;
+-
+-		/* Disable Pause Mode in MAC Rx FIFO */
+-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
+-	}
+-	
+-	XM_OUT32(IoC, Port, XM_MODE, DWord);
+-}	/* SkXmInitPauseMd*/
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmInitPhyXmac() - Initialize the XMAC Phy registers
+- *
+- * Description:	initializes all the XMACs Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmInitPhyXmac(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		Ctrl;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-	Ctrl = 0;
+-	
+-	/* Auto-negotiation ? */
+-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("InitPhyXmac: no auto-negotiation Port %d\n", Port));
+-		/* Set DuplexMode in Config register */
+-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+-			Ctrl |= PHY_CT_DUP_MD;
+-		}
+-
+-		/*
+-		 * Do NOT enable Auto-negotiation here. This would hold
+-		 * the link down because no IDLEs are transmitted
+-		 */
+-	}
+-	else {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("InitPhyXmac: with auto-negotiation Port %d\n", Port));
+-		/* Set Auto-negotiation advertisement */
+-
+-		/* Set Full/half duplex capabilities */
+-		switch (pPrt->PLinkMode) {
+-		case SK_LMODE_AUTOHALF:
+-			Ctrl |= PHY_X_AN_HD;
+-			break;
+-		case SK_LMODE_AUTOFULL:
+-			Ctrl |= PHY_X_AN_FD;
+-			break;
+-		case SK_LMODE_AUTOBOTH:
+-			Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
+-			break;
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+-				SKERR_HWI_E015MSG);
+-		}
+-
+-		/* Set Flow-control capabilities */
+-		switch (pPrt->PFlowCtrlMode) {
+-		case SK_FLOW_MODE_NONE:
+-			Ctrl |= PHY_X_P_NO_PAUSE;
+-			break;
+-		case SK_FLOW_MODE_LOC_SEND:
+-			Ctrl |= PHY_X_P_ASYM_MD;
+-			break;
+-		case SK_FLOW_MODE_SYMMETRIC:
+-			Ctrl |= PHY_X_P_SYM_MD;
+-			break;
+-		case SK_FLOW_MODE_SYM_OR_REM:
+-			Ctrl |= PHY_X_P_BOTH_MD;
+-			break;
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+-				SKERR_HWI_E016MSG);
+-		}
+-
+-		/* Write AutoNeg Advertisement Register */
+-		SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
+-
+-		/* Restart Auto-negotiation */
+-		Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
+-	}
+-
+-	if (DoLoop) {
+-		/* Set the Phy Loopback bit, too */
+-		Ctrl |= PHY_CT_LOOP;
+-	}
+-
+-	/* Write to the Phy control register */
+-	SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
+-}	/* SkXmInitPhyXmac */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
+- *
+- * Description:	initializes all the Broadcom Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmInitPhyBcom(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		Ctrl1;
+-	SK_U16		Ctrl2;
+-	SK_U16		Ctrl3;
+-	SK_U16		Ctrl4;
+-	SK_U16		Ctrl5;
+-
+-	Ctrl1 = PHY_CT_SP1000;
+-	Ctrl2 = 0;
+-	Ctrl3 = PHY_SEL_TYPE;
+-	Ctrl4 = PHY_B_PEC_EN_LTR;
+-	Ctrl5 = PHY_B_AC_TX_TST;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* manually Master/Slave ? */
+-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+-		Ctrl2 |= PHY_B_1000C_MSE;
+-		
+-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+-			Ctrl2 |= PHY_B_1000C_MSC;
+-		}
+-	}
+-	/* Auto-negotiation ? */
+-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("InitPhyBcom: no auto-negotiation Port %d\n", Port));
+-		/* Set DuplexMode in Config register */
+-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+-			Ctrl1 |= PHY_CT_DUP_MD;
+-		}
+-
+-		/* Determine Master/Slave manually if not already done */
+-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+-			Ctrl2 |= PHY_B_1000C_MSE;	/* set it to Slave */
+-		}
+-
+-		/*
+-		 * Do NOT enable Auto-negotiation here. This would hold
+-		 * the link down because no IDLES are transmitted
+-		 */
+-	}
+-	else {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("InitPhyBcom: with auto-negotiation Port %d\n", Port));
+-		/* Set Auto-negotiation advertisement */
+-
+-		/*
+-		 * Workaround BCOM Errata #1 for the C5 type.
+-		 * 1000Base-T Link Acquisition Failure in Slave Mode
+-		 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
+-		 */
+-		Ctrl2 |= PHY_B_1000C_RD;
+-		
+-		 /* Set Full/half duplex capabilities */
+-		switch (pPrt->PLinkMode) {
+-		case SK_LMODE_AUTOHALF:
+-			Ctrl2 |= PHY_B_1000C_AHD;
+-			break;
+-		case SK_LMODE_AUTOFULL:
+-			Ctrl2 |= PHY_B_1000C_AFD;
+-			break;
+-		case SK_LMODE_AUTOBOTH:
+-			Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
+-			break;
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+-				SKERR_HWI_E015MSG);
+-		}
+-
+-		/* Set Flow-control capabilities */
+-		switch (pPrt->PFlowCtrlMode) {
+-		case SK_FLOW_MODE_NONE:
+-			Ctrl3 |= PHY_B_P_NO_PAUSE;
+-			break;
+-		case SK_FLOW_MODE_LOC_SEND:
+-			Ctrl3 |= PHY_B_P_ASYM_MD;
+-			break;
+-		case SK_FLOW_MODE_SYMMETRIC:
+-			Ctrl3 |= PHY_B_P_SYM_MD;
+-			break;
+-		case SK_FLOW_MODE_SYM_OR_REM:
+-			Ctrl3 |= PHY_B_P_BOTH_MD;
+-			break;
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+-				SKERR_HWI_E016MSG);
+-		}
+-
+-		/* Restart Auto-negotiation */
+-		Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
+-	}
+-	
+-	/* Initialize LED register here? */
+-	/* No. Please do it in SkDgXmitLed() (if required) and swap
+-	   init order of LEDs and XMAC. (MAl) */
+-	
+-	/* Write 1000Base-T Control Register */
+-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
+-	
+-	/* Write AutoNeg Advertisement Register */
+-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
+-	
+-	if (DoLoop) {
+-		/* Set the Phy Loopback bit, too */
+-		Ctrl1 |= PHY_CT_LOOP;
+-	}
+-
+-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+-		/* configure FIFO to high latency for transmission of ext. packets */
+-		Ctrl4 |= PHY_B_PEC_HIGH_LA;
+-
+-		/* configure reception of extended packets */
+-		Ctrl5 |= PHY_B_AC_LONG_PACK;
+-
+-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
+-	}
+-
+-	/* Configure LED Traffic Mode and Jumbo Frame usage if specified */
+-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
+-	
+-	/* Write to the Phy control register */
+-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("PHY Control Reg=0x%04X\n", Ctrl1));
+-}	/* SkXmInitPhyBcom */
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- *	SkGmInitPhyMarv() - Initialize the Marvell Phy registers
+- *
+- * Description:	initializes all the Marvell Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGmInitPhyMarv(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		PhyCtrl;
+-	SK_U16		C1000BaseT;
+-	SK_U16		AutoNegAdv;
+-	SK_U16		ExtPhyCtrl;
+-	SK_U16		LedCtrl;
+-	SK_BOOL		AutoNeg;
+-#if defined(SK_DIAG) || defined(DEBUG)
+-	SK_U16		PhyStat;
+-	SK_U16		PhyStat1;
+-	SK_U16		PhySpecStat;
+-#endif /* SK_DIAG || DEBUG */
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* Auto-negotiation ? */
+-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+-		AutoNeg = SK_FALSE;
+-	}
+-	else {
+-		AutoNeg = SK_TRUE;
+-	}
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("InitPhyMarv: Port %d, auto-negotiation %s\n",
+-		 Port, AutoNeg ? "ON" : "OFF"));
+-
+-#ifdef VCPU
+-	VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
+-		Port, DoLoop);
+-#else /* VCPU */
+-	if (DoLoop) {
+-		/* Set 'MAC Power up'-bit, set Manual MDI configuration */
+-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
+-			PHY_M_PC_MAC_POW_UP);
+-	}
+-	else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
+-		/* Read Ext. PHY Specific Control */
+-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
+-		
+-		ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+-			PHY_M_EC_MAC_S_MSK);
+-		
+-		ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
+-			PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+-	
+-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
+-	}
+-
+-	/* Read PHY Control */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
+-
+-	if (!AutoNeg) {
+-		/* Disable Auto-negotiation */
+-		PhyCtrl &= ~PHY_CT_ANE;
+-	}
+-
+-	PhyCtrl |= PHY_CT_RESET;
+-	/* Assert software reset */
+-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
+-#endif /* VCPU */
+-
+-	PhyCtrl = 0 /* PHY_CT_COL_TST */;
+-	C1000BaseT = 0;
+-	AutoNegAdv = PHY_SEL_TYPE;
+-
+-	/* manually Master/Slave ? */
+-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+-		/* enable Manual Master/Slave */
+-		C1000BaseT |= PHY_M_1000C_MSE;
+-		
+-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+-			C1000BaseT |= PHY_M_1000C_MSC;	/* set it to Master */
+-		}
+-	}
+-	
+-	/* Auto-negotiation ? */
+-	if (!AutoNeg) {
+-		
+-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+-			/* Set Full Duplex Mode */
+-			PhyCtrl |= PHY_CT_DUP_MD;
+-		}
+-
+-		/* Set Master/Slave manually if not already done */
+-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+-			C1000BaseT |= PHY_M_1000C_MSE;	/* set it to Slave */
+-		}
+-
+-		/* Set Speed */
+-		switch (pPrt->PLinkSpeed) {
+-		case SK_LSPEED_AUTO:
+-		case SK_LSPEED_1000MBPS:
+-			PhyCtrl |= PHY_CT_SP1000;
+-			break;
+-		case SK_LSPEED_100MBPS:
+-			PhyCtrl |= PHY_CT_SP100;
+-			break;
+-		case SK_LSPEED_10MBPS:
+-			break;
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
+-				SKERR_HWI_E019MSG);
+-		}
+-
+-		if (!DoLoop) {
+-			PhyCtrl |= PHY_CT_RESET;
+-		}
+-	}
+-	else {
+-		/* Set Auto-negotiation advertisement */
+-		
+-		if (pAC->GIni.GICopperType) {
+-			/* Set Speed capabilities */
+-			switch (pPrt->PLinkSpeed) {
+-			case SK_LSPEED_AUTO:
+-				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
+-				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+-					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+-				break;
+-			case SK_LSPEED_1000MBPS:
+-				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
+-				break;
+-			case SK_LSPEED_100MBPS:
+-				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+-					/* advertise 10Base-T also */
+-					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+-				break;
+-			case SK_LSPEED_10MBPS:
+-				AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+-				break;
+-			default:
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
+-					SKERR_HWI_E019MSG);
+-			}
+-
+-			/* Set Full/half duplex capabilities */
+-			switch (pPrt->PLinkMode) {
+-			case SK_LMODE_AUTOHALF:
+-				C1000BaseT &= ~PHY_M_1000C_AFD;
+-				AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
+-				break;
+-			case SK_LMODE_AUTOFULL:
+-				C1000BaseT &= ~PHY_M_1000C_AHD;
+-				AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
+-				break;
+-			case SK_LMODE_AUTOBOTH:
+-				break;
+-			default:
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+-					SKERR_HWI_E015MSG);
+-			}
+-			
+-			/* Set Flow-control capabilities */
+-			switch (pPrt->PFlowCtrlMode) {
+-			case SK_FLOW_MODE_NONE:
+-				AutoNegAdv |= PHY_B_P_NO_PAUSE;
+-				break;
+-			case SK_FLOW_MODE_LOC_SEND:
+-				AutoNegAdv |= PHY_B_P_ASYM_MD;
+-				break;
+-			case SK_FLOW_MODE_SYMMETRIC:
+-				AutoNegAdv |= PHY_B_P_SYM_MD;
+-				break;
+-			case SK_FLOW_MODE_SYM_OR_REM:
+-				AutoNegAdv |= PHY_B_P_BOTH_MD;
+-				break;
+-			default:
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+-					SKERR_HWI_E016MSG);
+-			}
+-		}
+-		else {	/* special defines for FIBER (88E1011S only) */
+-			
+-			/* Set Full/half duplex capabilities */
+-			switch (pPrt->PLinkMode) {
+-			case SK_LMODE_AUTOHALF:
+-				AutoNegAdv |= PHY_M_AN_1000X_AHD;
+-				break;
+-			case SK_LMODE_AUTOFULL:
+-				AutoNegAdv |= PHY_M_AN_1000X_AFD;
+-				break;
+-			case SK_LMODE_AUTOBOTH:
+-				AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
+-				break;
+-			default:
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+-					SKERR_HWI_E015MSG);
+-			}
+-			
+-			/* Set Flow-control capabilities */
+-			switch (pPrt->PFlowCtrlMode) {
+-			case SK_FLOW_MODE_NONE:
+-				AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
+-				break;
+-			case SK_FLOW_MODE_LOC_SEND:
+-				AutoNegAdv |= PHY_M_P_ASYM_MD_X;
+-				break;
+-			case SK_FLOW_MODE_SYMMETRIC:
+-				AutoNegAdv |= PHY_M_P_SYM_MD_X;
+-				break;
+-			case SK_FLOW_MODE_SYM_OR_REM:
+-				AutoNegAdv |= PHY_M_P_BOTH_MD_X;
+-				break;
+-			default:
+-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+-					SKERR_HWI_E016MSG);
+-			}
+-		}
+-
+-		if (!DoLoop) {
+-			/* Restart Auto-negotiation */
+-			PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+-		}
+-	}
+-	
+-#ifdef VCPU
+-	/*
+-	 * E-mail from Gu Lin (08-03-2002):
+-	 */
+-	
+-	/* Program PHY register 30 as 16'h0708 for simulation speed up */
+-	SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
+-	
+-	VCpuWait(2000);
+-
+-#else /* VCPU */
+-	
+-	/* Write 1000Base-T Control Register */
+-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
+-	
+-	/* Write AutoNeg Advertisement Register */
+-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
+-#endif /* VCPU */
+-	
+-	if (DoLoop) {
+-		/* Set the PHY Loopback bit */
+-		PhyCtrl |= PHY_CT_LOOP;
+-
+-#ifdef XXX
+-		/* Program PHY register 16 as 16'h0400 to force link good */
+-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
+-#endif /* XXX */
+-
+-#ifndef VCPU
+-		if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
+-			/* Write Ext. PHY Specific Control */
+-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
+-				(SK_U16)((pPrt->PLinkSpeed + 2) << 4));
+-		}
+-#endif /* VCPU */
+-	}
+-#ifdef TEST_ONLY
+-	else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
+-			/* Write PHY Specific Control */
+-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
+-				PHY_M_PC_EN_DET_MSK);
+-	}
+-#endif
+-
+-	/* Write to the PHY Control register */
+-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
+-
+-#ifdef VCPU
+-	VCpuWait(2000);
+-#else
+-
+-	LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
+-
+-	if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
+-		LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
+-	}
+-
+-	if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
+-		LedCtrl |= PHY_M_LEDC_DP_CTRL;
+-	}
+-	
+-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
+-
+-	if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
+-		/* only in forced 100 Mbps mode */
+-		if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
+-
+-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
+-				PHY_M_LED_MO_100(MO_LED_ON));
+-		}
+-	}
+-
+-#ifdef SK_DIAG
+-	c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
+-	c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
+-	c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
+-	c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
+-#endif /* SK_DIAG */
+-
+-#if defined(SK_DIAG) || defined(DEBUG)
+-	/* Read PHY Control */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
+-	
+-	/* Read 1000Base-T Control Register */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("1000B-T Ctrl =0x%04X\n", C1000BaseT));
+-	
+-	/* Read AutoNeg Advertisement Register */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
+-	
+-	/* Read Ext. PHY Specific Control */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
+-	
+-	/* Read PHY Status */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("PHY Stat Reg.=0x%04X\n", PhyStat));
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("PHY Stat Reg.=0x%04X\n", PhyStat1));
+-	
+-	/* Read PHY Specific Status */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("PHY Spec Stat=0x%04X\n", PhySpecStat));
+-#endif /* SK_DIAG || DEBUG */
+-
+-#ifdef SK_DIAG
+-	c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
+-	c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
+-	c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
+-	c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
+-	c_print("PHY Stat Reg=0x%04X\n", PhyStat);
+-	c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
+-	c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
+-#endif /* SK_DIAG */
+-
+-#endif /* VCPU */
+-
+-}	/* SkGmInitPhyMarv */
+-#endif /* YUKON */
+-
+-
+-#ifdef OTHER_PHY
+-/******************************************************************************
+- *
+- *	SkXmInitPhyLone() - Initialize the Level One Phy registers
+- *
+- * Description:	initializes all the Level One Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmInitPhyLone(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		Ctrl1;
+-	SK_U16		Ctrl2;
+-	SK_U16		Ctrl3;
+-
+-	Ctrl1 = PHY_CT_SP1000;
+-	Ctrl2 = 0;
+-	Ctrl3 = PHY_SEL_TYPE;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* manually Master/Slave ? */
+-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+-		Ctrl2 |= PHY_L_1000C_MSE;
+-		
+-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+-			Ctrl2 |= PHY_L_1000C_MSC;
+-		}
+-	}
+-	/* Auto-negotiation ? */
+-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+-		/*
+-		 * level one spec say: "1000 Mbps: manual mode not allowed"
+-		 * but lets see what happens...
+-		 */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("InitPhyLone: no auto-negotiation Port %d\n", Port));
+-		/* Set DuplexMode in Config register */
+-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+-			Ctrl1 |= PHY_CT_DUP_MD;
+-		}
+-
+-		/* Determine Master/Slave manually if not already done */
+-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+-			Ctrl2 |= PHY_L_1000C_MSE;	/* set it to Slave */
+-		}
+-
+-		/*
+-		 * Do NOT enable Auto-negotiation here. This would hold
+-		 * the link down because no IDLES are transmitted
+-		 */
+-	}
+-	else {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("InitPhyLone: with auto-negotiation Port %d\n", Port));
+-		/* Set Auto-negotiation advertisement */
+-
+-		/* Set Full/half duplex capabilities */
+-		switch (pPrt->PLinkMode) {
+-		case SK_LMODE_AUTOHALF:
+-			Ctrl2 |= PHY_L_1000C_AHD;
+-			break;
+-		case SK_LMODE_AUTOFULL:
+-			Ctrl2 |= PHY_L_1000C_AFD;
+-			break;
+-		case SK_LMODE_AUTOBOTH:
+-			Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
+-			break;
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+-				SKERR_HWI_E015MSG);
+-		}
+-
+-		/* Set Flow-control capabilities */
+-		switch (pPrt->PFlowCtrlMode) {
+-		case SK_FLOW_MODE_NONE:
+-			Ctrl3 |= PHY_L_P_NO_PAUSE;
+-			break;
+-		case SK_FLOW_MODE_LOC_SEND:
+-			Ctrl3 |= PHY_L_P_ASYM_MD;
+-			break;
+-		case SK_FLOW_MODE_SYMMETRIC:
+-			Ctrl3 |= PHY_L_P_SYM_MD;
+-			break;
+-		case SK_FLOW_MODE_SYM_OR_REM:
+-			Ctrl3 |= PHY_L_P_BOTH_MD;
+-			break;
+-		default:
+-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+-				SKERR_HWI_E016MSG);
+-		}
+-
+-		/* Restart Auto-negotiation */
+-		Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
+-	}
+-	
+-	/* Write 1000Base-T Control Register */
+-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
+-	
+-	/* Write AutoNeg Advertisement Register */
+-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
+-
+-	if (DoLoop) {
+-		/* Set the Phy Loopback bit, too */
+-		Ctrl1 |= PHY_CT_LOOP;
+-	}
+-
+-	/* Write to the Phy control register */
+-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("PHY Control Reg=0x%04X\n", Ctrl1));
+-}	/* SkXmInitPhyLone */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmInitPhyNat() - Initialize the National Phy registers
+- *
+- * Description:	initializes all the National Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmInitPhyNat(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
+-{
+-/* todo: National */
+-}	/* SkXmInitPhyNat */
+-#endif /* OTHER_PHY */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacInitPhy() - Initialize the PHY registers
+- *
+- * Description:	calls the Init PHY routines dep. on board type
+- *
+- * Note:
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacInitPhy(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
+-{
+-	SK_GEPORT	*pPrt;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		switch (pPrt->PhyType) {
+-		case SK_PHY_XMAC:
+-			SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
+-			break;
+-		case SK_PHY_BCOM:
+-			SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
+-			break;
+-#ifdef OTHER_PHY
+-		case SK_PHY_LONE:
+-			SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
+-			break;
+-		case SK_PHY_NAT:
+-			SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
+-			break;
+-#endif /* OTHER_PHY */
+-		}
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		
+-		SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
+-	}
+-#endif /* YUKON */
+-
+-}	/* SkMacInitPhy */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkXmAutoNegDoneXmac() - Auto-negotiation handling
+- *
+- * Description:
+- *	This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- *	SK_AND_OK	o.k.
+- *	SK_AND_DUP_CAP 	Duplex capability error happened
+- *	SK_AND_OTHER 	Other error happened
+- */
+-static int SkXmAutoNegDoneXmac(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		ResAb;		/* Resolved Ability */
+-	SK_U16		LPAb;		/* Link Partner Ability */
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("AutoNegDoneXmac, Port %d\n", Port));
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* Get PHY parameters */
+-	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
+-	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
+-
+-	if ((LPAb & PHY_X_AN_RFB) != 0) {
+-		/* At least one of the remote fault bit is set */
+-		/* Error */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		return(SK_AND_OTHER);
+-	}
+-
+-	/* Check Duplex mismatch */
+-	if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+-	}
+-	else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+-	}
+-	else {
+-		/* Error */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		return(SK_AND_DUP_CAP);
+-	}
+-
+-	/* Check PAUSE mismatch */
+-	/* We are NOT using chapter 4.23 of the Xaqti manual */
+-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+-	if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
+-	     pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
+-	    (LPAb & PHY_X_P_SYM_MD) != 0) {
+-		/* Symmetric PAUSE */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+-	}
+-	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
+-		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
+-		/* Enable PAUSE receive, disable PAUSE transmit */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+-	}
+-	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
+-		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
+-		/* Disable PAUSE receive, enable PAUSE transmit */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+-	}
+-	else {
+-		/* PAUSE mismatch -> no PAUSE */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+-	}
+-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+-
+-	return(SK_AND_OK);
+-}	/* SkXmAutoNegDoneXmac */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmAutoNegDoneBcom() - Auto-negotiation handling
+- *
+- * Description:
+- *	This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- *	SK_AND_OK	o.k.
+- *	SK_AND_DUP_CAP 	Duplex capability error happened
+- *	SK_AND_OTHER 	Other error happened
+- */
+-static int SkXmAutoNegDoneBcom(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		LPAb;		/* Link Partner Ability */
+-	SK_U16		AuxStat;	/* Auxiliary Status */
+-
+-#ifdef TEST_ONLY
+-01-Sep-2000 RA;:;:
+-	SK_U16		ResAb;		/* Resolved Ability */
+-#endif	/* 0 */
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("AutoNegDoneBcom, Port %d\n", Port));
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* Get PHY parameters */
+-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
+-#ifdef TEST_ONLY
+-01-Sep-2000 RA;:;:
+-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+-#endif	/* 0 */
+-	
+-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
+-
+-	if ((LPAb & PHY_B_AN_RF) != 0) {
+-		/* Remote fault bit is set: Error */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		return(SK_AND_OTHER);
+-	}
+-
+-	/* Check Duplex mismatch */
+-	if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+-	}
+-	else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+-	}
+-	else {
+-		/* Error */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		return(SK_AND_DUP_CAP);
+-	}
+-	
+-#ifdef TEST_ONLY
+-01-Sep-2000 RA;:;:
+-	/* Check Master/Slave resolution */
+-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Master/Slave Fault Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
+-		return(SK_AND_OTHER);
+-	}
+-	
+-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+-#endif	/* 0 */
+-
+-	/* Check PAUSE mismatch ??? */
+-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+-	if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
+-		/* Symmetric PAUSE */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+-	}
+-	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
+-		/* Enable PAUSE receive, disable PAUSE transmit */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+-	}
+-	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
+-		/* Disable PAUSE receive, enable PAUSE transmit */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+-	}
+-	else {
+-		/* PAUSE mismatch -> no PAUSE */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+-	}
+-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+-
+-	return(SK_AND_OK);
+-}	/* SkXmAutoNegDoneBcom */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- *	SkGmAutoNegDoneMarv() - Auto-negotiation handling
+- *
+- * Description:
+- *	This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- *	SK_AND_OK	o.k.
+- *	SK_AND_DUP_CAP 	Duplex capability error happened
+- *	SK_AND_OTHER 	Other error happened
+- */
+-static int SkGmAutoNegDoneMarv(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		LPAb;		/* Link Partner Ability */
+-	SK_U16		ResAb;		/* Resolved Ability */
+-	SK_U16		AuxStat;	/* Auxiliary Status */
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("AutoNegDoneMarv, Port %d\n", Port));
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* Get PHY parameters */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("Link P.Abil.=0x%04X\n", LPAb));
+-	
+-	if ((LPAb & PHY_M_AN_RF) != 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		return(SK_AND_OTHER);
+-	}
+-
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
+-	
+-	/* Check Master/Slave resolution */
+-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Master/Slave Fault Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
+-		return(SK_AND_OTHER);
+-	}
+-	
+-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+-		(SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
+-	
+-	/* Read PHY Specific Status */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
+-	
+-	/* Check Speed & Duplex resolved */
+-	if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+-		return(SK_AND_DUP_CAP);
+-	}
+-	
+-	if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+-	}
+-	else {
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+-	}
+-	
+-	/* Check PAUSE mismatch ??? */
+-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+-	if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
+-		/* Symmetric PAUSE */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+-	}
+-	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
+-		/* Enable PAUSE receive, disable PAUSE transmit */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+-	}
+-	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
+-		/* Disable PAUSE receive, enable PAUSE transmit */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+-	}
+-	else {
+-		/* PAUSE mismatch -> no PAUSE */
+-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+-	}
+-	
+-	/* set used link speed */
+-	switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
+-	case (unsigned)PHY_M_PS_SPEED_1000:
+-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+-		break;
+-	case PHY_M_PS_SPEED_100:
+-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
+-		break;
+-	default:
+-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
+-	}
+-
+-	return(SK_AND_OK);
+-}	/* SkGmAutoNegDoneMarv */
+-#endif /* YUKON */
+-
+-
+-#ifdef OTHER_PHY
+-/******************************************************************************
+- *
+- *	SkXmAutoNegDoneLone() - Auto-negotiation handling
+- *
+- * Description:
+- *	This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- *	SK_AND_OK	o.k.
+- *	SK_AND_DUP_CAP 	Duplex capability error happened
+- *	SK_AND_OTHER 	Other error happened
+- */
+-static int SkXmAutoNegDoneLone(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		ResAb;		/* Resolved Ability */
+-	SK_U16		LPAb;		/* Link Partner Ability */
+-	SK_U16		QuickStat;	/* Auxiliary Status */
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("AutoNegDoneLone, Port %d\n", Port));
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	/* Get PHY parameters */
+-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
+-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
+-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
+-
+-	if ((LPAb & PHY_L_AN_RF) != 0) {
+-		/* Remote fault bit is set */
+-		/* Error */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		return(SK_AND_OTHER);
+-	}
+-
+-	/* Check Duplex mismatch */
+-	if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+-	}
+-	else {
+-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+-	}
+-	
+-	/* Check Master/Slave resolution */
+-	if ((ResAb & PHY_L_1000S_MSF) != 0) {
+-		/* Error */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("Master/Slave Fault Port %d\n", Port));
+-		pPrt->PAutoNegFail = SK_TRUE;
+-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
+-		return(SK_AND_OTHER);
+-	}
+-	else if (ResAb & PHY_L_1000S_MSR) {
+-		pPrt->PMSStatus = SK_MS_STAT_MASTER;
+-	}
+-	else {
+-		pPrt->PMSStatus = SK_MS_STAT_SLAVE;
+-	}
+-
+-	/* Check PAUSE mismatch */
+-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+-	/* we must manually resolve the abilities here */
+-	pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+-	
+-	switch (pPrt->PFlowCtrlMode) {
+-	case SK_FLOW_MODE_NONE:
+-		/* default */
+-		break;
+-	case SK_FLOW_MODE_LOC_SEND:
+-		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
+-			(PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
+-			/* Disable PAUSE receive, enable PAUSE transmit */
+-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+-		}
+-		break;
+-	case SK_FLOW_MODE_SYMMETRIC:
+-		if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
+-			/* Symmetric PAUSE */
+-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+-		}
+-		break;
+-	case SK_FLOW_MODE_SYM_OR_REM:
+-		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
+-			PHY_L_QS_AS_PAUSE) {
+-			/* Enable PAUSE receive, disable PAUSE transmit */
+-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+-		}
+-		else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
+-			/* Symmetric PAUSE */
+-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+-		}
+-		break;
+-	default:
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+-			SKERR_HWI_E016MSG);
+-	}
+-	
+-	return(SK_AND_OK);
+-}	/* SkXmAutoNegDoneLone */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmAutoNegDoneNat() - Auto-negotiation handling
+- *
+- * Description:
+- *	This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- *	SK_AND_OK	o.k.
+- *	SK_AND_DUP_CAP 	Duplex capability error happened
+- *	SK_AND_OTHER 	Other error happened
+- */
+-static int SkXmAutoNegDoneNat(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-/* todo: National */
+-	return(SK_AND_OK);
+-}	/* SkXmAutoNegDoneNat */
+-#endif /* OTHER_PHY */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacAutoNegDone() - Auto-negotiation handling
+- *
+- * Description:	calls the auto-negotiation done routines dep. on board type
+- *
+- * Returns:
+- *	SK_AND_OK	o.k.
+- *	SK_AND_DUP_CAP 	Duplex capability error happened
+- *	SK_AND_OTHER 	Other error happened
+- */
+-int	SkMacAutoNegDone(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	int	Rtv;
+-
+-	Rtv = SK_AND_OK;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		switch (pPrt->PhyType) {
+-		
+-		case SK_PHY_XMAC:
+-			Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
+-			break;
+-		case SK_PHY_BCOM:
+-			Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
+-			break;
+-#ifdef OTHER_PHY
+-		case SK_PHY_LONE:
+-			Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
+-			break;
+-		case SK_PHY_NAT:
+-			Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
+-			break;
+-#endif /* OTHER_PHY */
+-		default:
+-			return(SK_AND_OTHER);
+-		}
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		
+-		Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
+-	}
+-#endif /* YUKON */
+-	
+-	if (Rtv != SK_AND_OK) {
+-		return(Rtv);
+-	}
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("AutoNeg done Port %d\n", Port));
+-	
+-	/* We checked everything and may now enable the link */
+-	pPrt->PAutoNegFail = SK_FALSE;
+-
+-	SkMacRxTxEnable(pAC, IoC, Port);
+-	
+-	return(SK_AND_OK);
+-}	/* SkMacAutoNegDone */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
+- *
+- * Description:	enables Rx/Tx dep. on board type
+- *
+- * Returns:
+- *	0	o.k.
+- *	!= 0	Error happened
+- */
+-int SkMacRxTxEnable(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		Reg;		/* 16-bit register value */
+-	SK_U16		IntMask;	/* MAC interrupt mask */
+-#ifdef GENESIS
+-	SK_U16		SWord;
+-#endif
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (!pPrt->PHWLinkUp) {
+-		/* The Hardware link is NOT up */
+-		return(0);
+-	}
+-
+-	if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
+-	     pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
+-	     pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
+-	     pPrt->PAutoNegFail) {
+-		/* Auto-negotiation is not done or failed */
+-		return(0);
+-	}
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		/* set Duplex Mode and Pause Mode */
+-		SkXmInitDupMd(pAC, IoC, Port);
+-		
+-		SkXmInitPauseMd(pAC, IoC, Port);
+-	
+-		/*
+-		 * Initialize the Interrupt Mask Register. Default IRQs are...
+-		 *	- Link Asynchronous Event
+-		 *	- Link Partner requests config
+-		 *	- Auto Negotiation Done
+-		 *	- Rx Counter Event Overflow
+-		 *	- Tx Counter Event Overflow
+-		 *	- Transmit FIFO Underrun
+-		 */
+-		IntMask = XM_DEF_MSK;
+-
+-#ifdef DEBUG
+-		/* add IRQ for Receive FIFO Overflow */
+-		IntMask &= ~XM_IS_RXF_OV;
+-#endif /* DEBUG */
+-		
+-		if (pPrt->PhyType != SK_PHY_XMAC) {
+-			/* disable GP0 interrupt bit */
+-			IntMask |= XM_IS_INP_ASS;
+-		}
+-		XM_OUT16(IoC, Port, XM_IMSK, IntMask);
+-	
+-		/* get MMU Command Reg. */
+-		XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
+-		
+-		if (pPrt->PhyType != SK_PHY_XMAC &&
+-			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
+-			 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
+-			/* set to Full Duplex */
+-			Reg |= XM_MMU_GMII_FD;
+-		}
+-		
+-		switch (pPrt->PhyType) {
+-		case SK_PHY_BCOM:
+-			/*
+-			 * Workaround BCOM Errata (#10523) for all BCom Phys
+-			 * Enable Power Management after link up
+-			 */
+-			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
+-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+-				(SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
+-            SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
+-				(SK_U16)PHY_B_DEF_MSK);
+-			break;
+-#ifdef OTHER_PHY
+-		case SK_PHY_LONE:
+-			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
+-			break;
+-		case SK_PHY_NAT:
+-			/* todo National:
+-			SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
+-			/* no interrupts possible from National ??? */
+-			break;
+-#endif /* OTHER_PHY */
+-		}
+-		
+-		/* enable Rx/Tx */
+-		XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		/*
+-		 * Initialize the Interrupt Mask Register. Default IRQs are...
+-		 *	- Rx Counter Event Overflow
+-		 *	- Tx Counter Event Overflow
+-		 *	- Transmit FIFO Underrun
+-		 */
+-		IntMask = GMAC_DEF_MSK;
+-
+-#ifdef DEBUG
+-		/* add IRQ for Receive FIFO Overrun */
+-		IntMask |= GM_IS_RX_FF_OR;
+-#endif /* DEBUG */
+-		
+-		SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
+-		
+-		/* get General Purpose Control */
+-		GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
+-		
+-		if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
+-			pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
+-			/* set to Full Duplex */
+-			Reg |= GM_GPCR_DUP_FULL;
+-		}
+-		
+-		/* enable Rx/Tx */
+-        GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
+-			GM_GPCR_TX_ENA));
+-
+-#ifndef VCPU
+-		/* Enable all PHY interrupts */
+-        SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
+-			(SK_U16)PHY_M_DEF_MSK);
+-#endif /* VCPU */
+-	}
+-#endif /* YUKON */
+-					
+-	return(0);
+-
+-}	/* SkMacRxTxEnable */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacRxTxDisable() - Disable Receiver and Transmitter
+- *
+- * Description:	disables Rx/Tx dep. on board type
+- *
+- * Returns: N/A
+- */
+-void SkMacRxTxDisable(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_U16	Word;
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+-		
+-		XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
+-	
+-		/* dummy read to ensure writing */
+-		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		
+-		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+-
+-        GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
+-			GM_GPCR_TX_ENA)));
+-
+-		/* dummy read to ensure writing */
+-		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+-	}
+-#endif /* YUKON */
+-
+-}	/* SkMacRxTxDisable */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacIrqDisable() - Disable IRQ from MAC
+- *
+- * Description:	sets the IRQ-mask to disable IRQ dep. on board type
+- *
+- * Returns: N/A
+- */
+-void SkMacIrqDisable(
+-SK_AC	*pAC,		/* Adapter Context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-#ifdef GENESIS
+-	SK_U16		Word;
+-#endif
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		
+-		/* disable all XMAC IRQs */
+-		XM_OUT16(IoC, Port, XM_IMSK, 0xffff);	
+-		
+-		/* Disable all PHY interrupts */
+-		switch (pPrt->PhyType) {
+-			case SK_PHY_BCOM:
+-				/* Make sure that PHY is initialized */
+-				if (pPrt->PState != SK_PRT_RESET) {
+-					/* NOT allowed if BCOM is in RESET state */
+-					/* Workaround BCOM Errata (#10523) all BCom */
+-					/* Disable Power Management if link is down */
+-					SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
+-					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+-						(SK_U16)(Word | PHY_B_AC_DIS_PM));
+-					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
+-				}
+-				break;
+-#ifdef OTHER_PHY
+-			case SK_PHY_LONE:
+-				SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
+-				break;
+-			case SK_PHY_NAT:
+-				/* todo: National
+-				SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
+-				break;
+-#endif /* OTHER_PHY */
+-		}
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		/* disable all GMAC IRQs */
+-		SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
+-		
+-#ifndef VCPU
+-		/* Disable all PHY interrupts */
+-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
+-#endif /* VCPU */
+-	}
+-#endif /* YUKON */
+-
+-}	/* SkMacIrqDisable */
+-
+-
+-#ifdef SK_DIAG
+-/******************************************************************************
+- *
+- *	SkXmSendCont() - Enable / Disable Send Continuous Mode
+- *
+- * Description:	enable / disable Send Continuous Mode on XMAC
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkXmSendCont(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port,	/* Port Index (MAC_1 + n) */
+-SK_BOOL	Enable)	/* Enable / Disable */
+-{
+-	SK_U32	MdReg;
+-
+-	XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-
+-	if (Enable) {
+-		MdReg |= XM_MD_TX_CONT;
+-	}
+-	else {
+-		MdReg &= ~XM_MD_TX_CONT;
+-	}
+-	/* setup Mode Register */
+-	XM_OUT32(IoC, Port, XM_MODE, MdReg);
+-
+-}	/* SkXmSendCont */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacTimeStamp() - Enable / Disable Time Stamp
+- *
+- * Description:	enable / disable Time Stamp generation for Rx packets
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacTimeStamp(
+-SK_AC	*pAC,	/* adapter context */
+-SK_IOC	IoC,	/* IO context */
+-int		Port,	/* Port Index (MAC_1 + n) */
+-SK_BOOL	Enable)	/* Enable / Disable */
+-{
+-	SK_U32	MdReg;
+-	SK_U8	TimeCtrl;
+-
+-	if (pAC->GIni.GIGenesis) {
+-
+-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-
+-		if (Enable) {
+-			MdReg |= XM_MD_ATS;
+-		}
+-		else {
+-			MdReg &= ~XM_MD_ATS;
+-		}
+-		/* setup Mode Register */
+-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+-	}
+-	else {
+-		if (Enable) {
+-			TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
+-		}
+-		else {
+-			TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
+-		}
+-		/* Start/Stop Time Stamp Timer */
+-		SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
+-	}
+-
+-}	/* SkMacTimeStamp*/
+-
+-#else /* !SK_DIAG */
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
+- *
+- *	This function analyses the Interrupt status word. If any of the
+- *	Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
+- *	is set true.
+- */
+-void SkXmAutoNegLipaXmac(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_U16	IStatus)	/* Interrupt Status word to analyse */
+-{
+-	SK_GEPORT	*pPrt;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
+-		(IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
+-			Port, IStatus));
+-		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
+-	}
+-}	/* SkXmAutoNegLipaXmac */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
+- *
+- *	This function analyses the PHY status word.
+- *  If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
+- *	is set true.
+- */
+-void SkMacAutoNegLipaPhy(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_U16	PhyStat)	/* PHY Status word to analyse */
+-{
+-	SK_GEPORT	*pPrt;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
+-		(PhyStat & PHY_ST_AN_OVER) != 0) {
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
+-			Port, PhyStat));
+-		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
+-	}
+-}	/* SkMacAutoNegLipaPhy */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkXmIrq() - Interrupt Service Routine
+- *
+- * Description:	services an Interrupt Request of the XMAC
+- *
+- * Note:
+- *	With an external PHY, some interrupt bits are not meaningfull any more:
+- *	- LinkAsyncEvent (bit #14)              XM_IS_LNK_AE
+- *	- LinkPartnerReqConfig (bit #10)	XM_IS_LIPA_RC
+- *	- Page Received (bit #9)		XM_IS_RX_PAGE
+- *	- NextPageLoadedForXmt (bit #8)		XM_IS_TX_PAGE
+- *	- AutoNegDone (bit #7)			XM_IS_AND
+- *	Also probably not valid any more is the GP0 input bit:
+- *	- GPRegisterBit0set			XM_IS_INP_ASS
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkXmIrq(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_EVPARA	Para;
+-	SK_U16		IStatus;	/* Interrupt status read from the XMAC */
+-	SK_U16		IStatus2;
+-#ifdef SK_SLIM
+-    SK_U64      OverflowStatus;
+-#endif	
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-	
+-	XM_IN16(IoC, Port, XM_ISRC, &IStatus);
+-	
+-	/* LinkPartner Auto-negable? */
+-	if (pPrt->PhyType == SK_PHY_XMAC) {
+-		SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
+-	}
+-	else {
+-		/* mask bits that are not used with ext. PHY */
+-		IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
+-			XM_IS_RX_PAGE | XM_IS_TX_PAGE |
+-			XM_IS_AND | XM_IS_INP_ASS);
+-	}
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-		("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
+-
+-	if (!pPrt->PHWLinkUp) {
+-		/* Spurious XMAC interrupt */
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-			("SkXmIrq: spurious interrupt on Port %d\n", Port));
+-		return;
+-	}
+-
+-	if ((IStatus & XM_IS_INP_ASS) != 0) {
+-		/* Reread ISR Register if link is not in sync */
+-		XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
+-
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-			("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
+-			 Port, IStatus, IStatus2));
+-		IStatus &= ~XM_IS_INP_ASS;
+-		IStatus |= IStatus2;
+-	}
+-
+-	if ((IStatus & XM_IS_LNK_AE) != 0) {
+-		/* not used, GP0 is used instead */
+-	}
+-
+-	if ((IStatus & XM_IS_TX_ABORT) != 0) {
+-		/* not used */
+-	}
+-
+-	if ((IStatus & XM_IS_FRC_INT) != 0) {
+-		/* not used, use ASIC IRQ instead if needed */
+-	}
+-
+-	if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
+-		SkHWLinkDown(pAC, IoC, Port);
+-
+-		/* Signal to RLMT */
+-		Para.Para32[0] = (SK_U32)Port;
+-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-
+-		/* Start workaround Errata #2 timer */
+-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+-			SKGE_HWAC, SK_HWEV_WATIM, Para);
+-	}
+-
+-	if ((IStatus & XM_IS_RX_PAGE) != 0) {
+-		/* not used */
+-	}
+-
+-	if ((IStatus & XM_IS_TX_PAGE) != 0) {
+-		/* not used */
+-	}
+-
+-	if ((IStatus & XM_IS_AND) != 0) {
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-			("SkXmIrq: AND on link that is up Port %d\n", Port));
+-	}
+-
+-	if ((IStatus & XM_IS_TSC_OV) != 0) {
+-		/* not used */
+-	}
+-
+-	/* Combined Tx & Rx Counter Overflow SIRQ Event */
+-	if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
+-#ifdef SK_SLIM
+-		SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
+-#else
+-		Para.Para32[0] = (SK_U32)Port;
+-		Para.Para32[1] = (SK_U32)IStatus;
+-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
+-#endif /* SK_SLIM */
+-	}
+-
+-	if ((IStatus & XM_IS_RXF_OV) != 0) {
+-		/* normal situation -> no effect */
+-#ifdef DEBUG
+-		pPrt->PRxOverCnt++;
+-#endif /* DEBUG */
+-	}
+-
+-	if ((IStatus & XM_IS_TXF_UR) != 0) {
+-		/* may NOT happen -> error log */
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
+-	}
+-
+-	if ((IStatus & XM_IS_TX_COMP) != 0) {
+-		/* not served here */
+-	}
+-
+-	if ((IStatus & XM_IS_RX_COMP) != 0) {
+-		/* not served here */
+-	}
+-}	/* SkXmIrq */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- *	SkGmIrq() - Interrupt Service Routine
+- *
+- * Description:	services an Interrupt Request of the GMAC
+- *
+- * Note:
+- *
+- * Returns:
+- *	nothing
+- */
+-static void SkGmIrq(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U8		IStatus;	/* Interrupt status */
+-#ifdef SK_SLIM
+-    SK_U64      OverflowStatus;
+-#else
+-	SK_EVPARA	Para;
+-#endif	
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-	
+-	SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
+-	
+-#ifdef XXX
+-	/* LinkPartner Auto-negable? */
+-	SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
+-#endif /* XXX */
+-	
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+-		("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
+-
+-	/* Combined Tx & Rx Counter Overflow SIRQ Event */
+-	if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
+-		/* these IRQs will be cleared by reading GMACs register */
+-#ifdef SK_SLIM
+-        SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
+-#else
+-		Para.Para32[0] = (SK_U32)Port;
+-		Para.Para32[1] = (SK_U32)IStatus;
+-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
+-#endif		
+-	}
+-
+-	if (IStatus & GM_IS_RX_FF_OR) {
+-		/* clear GMAC Rx FIFO Overrun IRQ */
+-		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
+-#ifdef DEBUG
+-		pPrt->PRxOverCnt++;
+-#endif /* DEBUG */
+-	}
+-
+-	if (IStatus & GM_IS_TX_FF_UR) {
+-		/* clear GMAC Tx FIFO Underrun IRQ */
+-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
+-		/* may NOT happen -> error log */
+-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
+-	}
+-
+-	if (IStatus & GM_IS_TX_COMPL) {
+-		/* not served here */
+-	}
+-
+-	if (IStatus & GM_IS_RX_COMPL) {
+-		/* not served here */
+-	}
+-}	/* SkGmIrq */
+-#endif /* YUKON */
+-
+-
+-/******************************************************************************
+- *
+- *	SkMacIrq() - Interrupt Service Routine for MAC
+- *
+- * Description:	calls the Interrupt Service Routine dep. on board type
+- *
+- * Returns:
+- *	nothing
+- */
+-void SkMacIrq(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-int		Port)		/* Port Index (MAC_1 + n) */
+-{
+-#ifdef GENESIS
+-	if (pAC->GIni.GIGenesis) {
+-		/* IRQ from XMAC */
+-		SkXmIrq(pAC, IoC, Port);
+-	}
+-#endif /* GENESIS */
+-	
+-#ifdef YUKON
+-	if (pAC->GIni.GIYukon) {
+-		/* IRQ from GMAC */
+-		SkGmIrq(pAC, IoC, Port);
+-	}
+-#endif /* YUKON */
+-
+-}	/* SkMacIrq */
+-
+-#endif /* !SK_DIAG */
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- *	SkXmUpdateStats() - Force the XMAC to output the current statistic
+- *
+- * Description:
+- *	The XMAC holds its statistic internally. To obtain the current
+- *	values a command must be sent so that the statistic data will
+- *	be written to a predefined memory area on the adapter.
+- *
+- * Returns:
+- *	0:  success
+- *	1:  something went wrong
+- */
+-int SkXmUpdateStats(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-unsigned int Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_GEPORT	*pPrt;
+-	SK_U16		StatReg;
+-	int			WaitIndex;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-	WaitIndex = 0;
+-
+-	/* Send an update command to XMAC specified */
+-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
+-
+-	/*
+-	 * It is an auto-clearing register. If the command bits
+-	 * went to zero again, the statistics are transferred.
+-	 * Normally the command should be executed immediately.
+-	 * But just to be sure we execute a loop.
+-	 */
+-	do {
+-
+-		XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
+-		
+-		if (++WaitIndex > 10) {
+-
+-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
+-
+-			return(1);
+-		}
+-	} while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
+-	
+-	return(0);
+-}	/* SkXmUpdateStats */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmMacStatistic() - Get XMAC counter value
+- *
+- * Description:
+- *	Gets the 32bit counter value. Except for the octet counters
+- *	the lower 32bit are counted in hardware and the upper 32bit
+- *	must be counted in software by monitoring counter overflow interrupts.
+- *
+- * Returns:
+- *	0:  success
+- *	1:  something went wrong
+- */
+-int SkXmMacStatistic(
+-SK_AC	*pAC,			/* adapter context */
+-SK_IOC	IoC,			/* IO context */
+-unsigned int Port,		/* Port Index (MAC_1 + n) */
+-SK_U16	StatAddr,		/* MIB counter base address */
+-SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
+-{
+-	if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
+-		
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
+-		
+-		return(1);
+-	}
+-	
+-	XM_IN32(IoC, Port, StatAddr, pVal);
+-
+-	return(0);
+-}	/* SkXmMacStatistic */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmResetCounter() - Clear MAC statistic counter
+- *
+- * Description:
+- *	Force the XMAC to clear its statistic counter.
+- *
+- * Returns:
+- *	0:  success
+- *	1:  something went wrong
+- */
+-int SkXmResetCounter(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-unsigned int Port)	/* Port Index (MAC_1 + n) */
+-{
+-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+-	/* Clear two times according to Errata #3 */
+-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+-
+-	return(0);
+-}	/* SkXmResetCounter */
+-
+-
+-/******************************************************************************
+- *
+- *	SkXmOverflowStatus() - Gets the status of counter overflow interrupt
+- *
+- * Description:
+- *	Checks the source causing an counter overflow interrupt. On success the
+- *	resulting counter overflow status is written to <pStatus>, whereas the
+- *	upper dword stores the XMAC ReceiveCounterEvent register and the lower
+- *	dword the XMAC TransmitCounterEvent register.
+- *
+- * Note:
+- *	For XMAC the interrupt source is a self-clearing register, so the source
+- *	must be checked only once. SIRQ module does another check to be sure
+- *	that no interrupt get lost during process time.
+- *
+- * Returns:
+- *	0:  success
+- *	1:  something went wrong
+- */
+-int SkXmOverflowStatus(
+-SK_AC	*pAC,				/* adapter context */
+-SK_IOC	IoC,				/* IO context */
+-unsigned int Port,			/* Port Index (MAC_1 + n) */
+-SK_U16	IStatus,			/* Interupt Status from MAC */
+-SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
+-{
+-	SK_U64	Status;	/* Overflow status */
+-	SK_U32	RegVal;
+-
+-	Status = 0;
+-
+-	if ((IStatus & XM_IS_RXC_OV) != 0) {
+-
+-		XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
+-		Status |= (SK_U64)RegVal << 32;
+-	}
+-	
+-	if ((IStatus & XM_IS_TXC_OV) != 0) {
+-
+-		XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
+-		Status |= (SK_U64)RegVal;
+-	}
+-
+-	*pStatus = Status;
+-
+-	return(0);
+-}	/* SkXmOverflowStatus */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- *	SkGmUpdateStats() - Force the GMAC to output the current statistic
+- *
+- * Description:
+- *	Empty function for GMAC. Statistic data is accessible in direct way.
+- *
+- * Returns:
+- *	0:  success
+- *	1:  something went wrong
+- */
+-int SkGmUpdateStats(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-unsigned int Port)	/* Port Index (MAC_1 + n) */
+-{
+-	return(0);
+-}
+-
+-
+-/******************************************************************************
+- *
+- *	SkGmMacStatistic() - Get GMAC counter value
+- *
+- * Description:
+- *	Gets the 32bit counter value. Except for the octet counters
+- *	the lower 32bit are counted in hardware and the upper 32bit
+- *	must be counted in software by monitoring counter overflow interrupts.
+- *
+- * Returns:
+- *	0:  success
+- *	1:  something went wrong
+- */
+-int SkGmMacStatistic(
+-SK_AC	*pAC,			/* adapter context */
+-SK_IOC	IoC,			/* IO context */
+-unsigned int Port,		/* Port Index (MAC_1 + n) */
+-SK_U16	StatAddr,		/* MIB counter base address */
+-SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
+-{
+-
+-	if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
+-		
+-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
+-		
+-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-			("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
+-		return(1);
+-	}
+-		
+-	GM_IN32(IoC, Port, StatAddr, pVal);
+-
+-	return(0);
+-}	/* SkGmMacStatistic */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGmResetCounter() - Clear MAC statistic counter
+- *
+- * Description:
+- *	Force GMAC to clear its statistic counter.
+- *
+- * Returns:
+- *	0:  success
+- *	1:  something went wrong
+- */
+-int SkGmResetCounter(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,		/* IO context */
+-unsigned int Port)	/* Port Index (MAC_1 + n) */
+-{
+-	SK_U16	Reg;	/* Phy Address Register */
+-	SK_U16	Word;
+-	int		i;
+-
+-	GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
+-
+-	/* set MIB Clear Counter Mode */
+-	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
+-	
+-	/* read all MIB Counters with Clear Mode set */
+-	for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
+-		/* the reset is performed only when the lower 16 bits are read */
+-		GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
+-	}
+-	
+-	/* clear MIB Clear Counter Mode */
+-	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
+-	
+-	return(0);
+-}	/* SkGmResetCounter */
+-
+-
+-/******************************************************************************
+- *
+- *	SkGmOverflowStatus() - Gets the status of counter overflow interrupt
+- *
+- * Description:
+- *	Checks the source causing an counter overflow interrupt. On success the
+- *	resulting counter overflow status is written to <pStatus>, whereas the
+- *	the following bit coding is used:
+- *	63:56 - unused
+- *	55:48 - TxRx interrupt register bit7:0
+- *	32:47 - Rx interrupt register
+- *	31:24 - unused
+- *	23:16 - TxRx interrupt register bit15:8
+- *	15:0  - Tx interrupt register
+- *
+- * Returns:
+- *	0:  success
+- *	1:  something went wrong
+- */
+-int SkGmOverflowStatus(
+-SK_AC	*pAC,				/* adapter context */
+-SK_IOC	IoC,				/* IO context */
+-unsigned int Port,			/* Port Index (MAC_1 + n) */
+-SK_U16	IStatus,			/* Interupt Status from MAC */
+-SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
+-{
+-	SK_U64	Status;		/* Overflow status */
+-	SK_U16	RegVal;
+-
+-	Status = 0;
+-
+-	if ((IStatus & GM_IS_RX_CO_OV) != 0) {
+-		/* this register is self-clearing after read */
+-		GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
+-		Status |= (SK_U64)RegVal << 32;
+-	}
+-	
+-	if ((IStatus & GM_IS_TX_CO_OV) != 0) {
+-		/* this register is self-clearing after read */
+-		GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
+-		Status |= (SK_U64)RegVal;
+-	}
+-	
+-	/* this register is self-clearing after read */
+-	GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
+-	/* Rx overflow interrupt register bits (LoByte)*/
+-	Status |= (SK_U64)((SK_U8)RegVal) << 48;
+-	/* Tx overflow interrupt register bits (HiByte)*/
+-	Status |= (SK_U64)(RegVal >> 8) << 16;
+-
+-	*pStatus = Status;
+-
+-	return(0);
+-}	/* SkGmOverflowStatus */
+-
+-
+-#ifndef SK_SLIM
+-/******************************************************************************
+- *
+- *	SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
+- *
+- * Description:
+- *  starts the cable diagnostic test if 'StartTest' is true
+- *  gets the results if 'StartTest' is true
+- *
+- * NOTE:	this test is meaningful only when link is down
+- *	
+- * Returns:
+- *	0:  success
+- *	1:	no YUKON copper
+- *	2:	test in progress
+- */
+-int SkGmCableDiagStatus(
+-SK_AC	*pAC,		/* adapter context */
+-SK_IOC	IoC,   		/* IO context */
+-int		Port,		/* Port Index (MAC_1 + n) */
+-SK_BOOL	StartTest)	/* flag for start / get result */
+-{
+-	int		i;
+-	SK_U16	RegVal;
+-	SK_GEPORT	*pPrt;
+-
+-	pPrt = &pAC->GIni.GP[Port];
+-
+-	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+-		
+-		return(1);
+-	}
+-
+-	if (StartTest) {
+-		/* only start the cable test */
+-		if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
+-			/* apply TDR workaround from Marvell */
+-			SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
+-			
+-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
+-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
+-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
+-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
+-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
+-		}
+-
+-		/* set address to 0 for MDI[0] */
+-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
+-
+-		/* Read Cable Diagnostic Reg */
+-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
+-
+-		/* start Cable Diagnostic Test */
+-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
+-			(SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
+-	
+-		return(0);
+-	}
+-	
+-	/* Read Cable Diagnostic Reg */
+-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
+-
+-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+-		("PHY Cable Diag.=0x%04X\n", RegVal));
+-
+-	if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
+-		/* test is running */
+-		return(2);
+-	}
+-
+-	/* get the test results */
+-	for (i = 0; i < 4; i++)  {
+-		/* set address to i for MDI[i] */
+-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
+-
+-		/* get Cable Diagnostic values */
+-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
+-
+-		pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
+-
+-		pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
+-	}
+-
+-	return(0);
+-}	/* SkGmCableDiagStatus */
+-#endif /* !SK_SLIM */
+-#endif /* YUKON */
+-
+-/* End of file */
+diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c
+index 76dc8ad..6028bbb 100644
+--- a/drivers/net/skfp/fplustm.c
++++ b/drivers/net/skfp/fplustm.c
+@@ -401,18 +401,18 @@ static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
+ /* int len ;		 length of the frame including the FC */
+ {
+ 	int	i ;
+-	u_int	*p ;
++	__le32	*p ;
+ 
+ 	CHECK_NPP() ;
+ 	MARW(off) ;		/* set memory address reg for writes */
+ 
+-	p = (u_int *) mac ;
++	p = (__le32 *) mac ;
+ 	for (i = (len + 3)/4 ; i ; i--) {
+ 		if (i == 1) {
+ 			/* last word, set the tag bit */
+ 			outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;
+ 		}
+-		write_mdr(smc,MDR_REVERSE(*p)) ;
++		write_mdr(smc,le32_to_cpu(*p)) ;
+ 		p++ ;
+ 	}
+ 
+@@ -444,7 +444,7 @@ static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
+  */
+ static void directed_beacon(struct s_smc *smc)
+ {
+-	SK_LOC_DECL(u_int,a[2]) ;
++	SK_LOC_DECL(__le32,a[2]) ;
+ 
+ 	/*
+ 	 * set UNA in frame
+@@ -458,9 +458,9 @@ static void directed_beacon(struct s_smc *smc)
+ 	CHECK_NPP() ;
+ 	 /* set memory address reg for writes */
+ 	MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;
+-	write_mdr(smc,MDR_REVERSE(a[0])) ;
++	write_mdr(smc,le32_to_cpu(a[0])) ;
+ 	outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;	/* set the tag bit */
+-	write_mdr(smc,MDR_REVERSE(a[1])) ;
++	write_mdr(smc,le32_to_cpu(a[1])) ;
+ 
+ 	outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;
+ }
+diff --git a/drivers/net/skfp/h/fplustm.h b/drivers/net/skfp/h/fplustm.h
+index 98bbf65..6d738e1 100644
+--- a/drivers/net/skfp/h/fplustm.h
++++ b/drivers/net/skfp/h/fplustm.h
+@@ -50,12 +50,12 @@ struct err_st {
+  *	Transmit Descriptor struct
+  */
+ struct s_smt_fp_txd {
+-	u_int txd_tbctrl ;		/* transmit buffer control */
+-	u_int txd_txdscr ;		/* transmit frame status word */
+-	u_int txd_tbadr ;		/* physical tx buffer address */
+-	u_int txd_ntdadr ;		/* physical pointer to the next TxD */
++	__le32 txd_tbctrl ;		/* transmit buffer control */
++	__le32 txd_txdscr ;		/* transmit frame status word */
++	__le32 txd_tbadr ;		/* physical tx buffer address */
++	__le32 txd_ntdadr ;		/* physical pointer to the next TxD */
+ #ifdef	ENA_64BIT_SUP
+-	u_int txd_tbadr_hi ;		/* physical tx buffer addr (high dword)*/
++	__le32 txd_tbadr_hi ;		/* physical tx buffer addr (high dword)*/
+ #endif
+ 	char far *txd_virt ;		/* virtual pointer to the data frag */
+ 					/* virt pointer to the next TxD */
+@@ -67,12 +67,12 @@ struct s_smt_fp_txd {
+  *	Receive Descriptor struct
+  */
+ struct s_smt_fp_rxd {
+-	u_int rxd_rbctrl ;		/* receive buffer control */
+-	u_int rxd_rfsw ;		/* receive frame status word */
+-	u_int rxd_rbadr ;		/* physical rx buffer address */
+-	u_int rxd_nrdadr ;		/* physical pointer to the next RxD */
++	__le32 rxd_rbctrl ;		/* receive buffer control */
++	__le32 rxd_rfsw ;		/* receive frame status word */
++	__le32 rxd_rbadr ;		/* physical rx buffer address */
++	__le32 rxd_nrdadr ;		/* physical pointer to the next RxD */
+ #ifdef	ENA_64BIT_SUP
+-	u_int rxd_rbadr_hi ;		/* physical tx buffer addr (high dword)*/
++	__le32 rxd_rbadr_hi ;		/* physical tx buffer addr (high dword)*/
+ #endif
+ 	char far *rxd_virt ;		/* virtual pointer to the data frag */
+ 					/* virt pointer to the next RxD */
+diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c
+index 46e3393..4218e97 100644
+--- a/drivers/net/skfp/hwmtm.c
++++ b/drivers/net/skfp/hwmtm.c
+@@ -208,7 +208,7 @@ SMbuf* smt_get_mbuf(struct s_smc *smc);
+ #if	defined(NDIS_OS2) || defined(ODI2)
+ #define CR_READ(var)	((var) & 0xffff0000 | ((var) & 0xffff))
+ #else
+-#define CR_READ(var)	(u_long)(var)
++#define CR_READ(var)	(__le32)(var)
+ #endif
+ 
+ #define IMASK_SLOW	(IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
+@@ -343,16 +343,16 @@ static u_long init_descr_ring(struct s_smc *smc,
+ 	for (i=count-1, d1=start; i ; i--) {
+ 		d2 = d1 ;
+ 		d1++ ;		/* descr is owned by the host */
+-		d2->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
++		d2->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
+ 		d2->r.rxd_next = &d1->r ;
+ 		phys = mac_drv_virt2phys(smc,(void *)d1) ;
+-		d2->r.rxd_nrdadr = AIX_REVERSE(phys) ;
++		d2->r.rxd_nrdadr = cpu_to_le32(phys) ;
+ 	}
+ 	DB_GEN("descr ring ends at = %x ",(void *)d1,0,3) ;
+-	d1->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
++	d1->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
+ 	d1->r.rxd_next = &start->r ;
+ 	phys = mac_drv_virt2phys(smc,(void *)start) ;
+-	d1->r.rxd_nrdadr = AIX_REVERSE(phys) ;
++	d1->r.rxd_nrdadr = cpu_to_le32(phys) ;
+ 
+ 	for (i=count, d1=start; i ; i--) {
+ 		DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
+@@ -376,7 +376,7 @@ static void init_txd_ring(struct s_smc *smc)
+ 	DB_GEN("Init async TxD ring, %d TxDs ",HWM_ASYNC_TXD_COUNT,0,3) ;
+ 	(void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+ 		HWM_ASYNC_TXD_COUNT) ;
+-	phys = AIX_REVERSE(ds->txd_ntdadr) ;
++	phys = le32_to_cpu(ds->txd_ntdadr) ;
+ 	ds++ ;
+ 	queue->tx_curr_put = queue->tx_curr_get = ds ;
+ 	ds-- ;
+@@ -390,7 +390,7 @@ static void init_txd_ring(struct s_smc *smc)
+ 	DB_GEN("Init sync TxD ring, %d TxDs ",HWM_SYNC_TXD_COUNT,0,3) ;
+ 	(void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+ 		HWM_SYNC_TXD_COUNT) ;
+-	phys = AIX_REVERSE(ds->txd_ntdadr) ;
++	phys = le32_to_cpu(ds->txd_ntdadr) ;
+ 	ds++ ;
+ 	queue->tx_curr_put = queue->tx_curr_get = ds ;
+ 	queue->tx_free = HWM_SYNC_TXD_COUNT ;
+@@ -412,7 +412,7 @@ static void init_rxd_ring(struct s_smc *smc)
+ 	DB_GEN("Init RxD ring, %d RxDs ",SMT_R1_RXD_COUNT,0,3) ;
+ 	(void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+ 		SMT_R1_RXD_COUNT) ;
+-	phys = AIX_REVERSE(ds->rxd_nrdadr) ;
++	phys = le32_to_cpu(ds->rxd_nrdadr) ;
+ 	ds++ ;
+ 	queue->rx_curr_put = queue->rx_curr_get = ds ;
+ 	queue->rx_free = SMT_R1_RXD_COUNT ;
+@@ -607,12 +607,12 @@ static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
+ 	for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {
+ 		t = t->txd_next ;
+ 	}
+-	phys = AIX_REVERSE(t->txd_ntdadr) ;
++	phys = le32_to_cpu(t->txd_ntdadr) ;
+ 
+ 	t = queue->tx_curr_get ;
+ 	while (tx_used) {
+ 		DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
+-		tbctrl = AIX_REVERSE(t->txd_tbctrl) ;
++		tbctrl = le32_to_cpu(t->txd_tbctrl) ;
+ 
+ 		if (tbctrl & BMU_OWN) {
+ 			if (tbctrl & BMU_STF) {
+@@ -622,10 +622,10 @@ static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
+ 				/*
+ 				 * repair the descriptor
+ 				 */
+-				t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
++				t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ 			}
+ 		}
+-		phys = AIX_REVERSE(t->txd_ntdadr) ;
++		phys = le32_to_cpu(t->txd_ntdadr) ;
+ 		DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ 		t = t->txd_next ;
+ 		tx_used-- ;
+@@ -659,12 +659,12 @@ static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
+ 	for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {
+ 		r = r->rxd_next ;
+ 	}
+-	phys = AIX_REVERSE(r->rxd_nrdadr) ;
++	phys = le32_to_cpu(r->rxd_nrdadr) ;
+ 
+ 	r = queue->rx_curr_get ;
+ 	while (rx_used) {
+ 		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+-		rbctrl = AIX_REVERSE(r->rxd_rbctrl) ;
++		rbctrl = le32_to_cpu(r->rxd_rbctrl) ;
+ 
+ 		if (rbctrl & BMU_OWN) {
+ 			if (rbctrl & BMU_STF) {
+@@ -674,10 +674,10 @@ static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
+ 				/*
+ 				 * repair the descriptor
+ 				 */
+-				r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
++				r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ 			}
+ 		}
+-		phys = AIX_REVERSE(r->rxd_nrdadr) ;
++		phys = le32_to_cpu(r->rxd_nrdadr) ;
+ 		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ 		r = r->rxd_next ;
+ 		rx_used-- ;
+@@ -1094,8 +1094,7 @@ void process_receive(struct s_smc *smc)
+ 		do {
+ 			DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ;
+ 			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+-			rbctrl = CR_READ(r->rxd_rbctrl) ;
+-			rbctrl = AIX_REVERSE(rbctrl) ;
++			rbctrl = le32_to_cpu(CR_READ(r->rxd_rbctrl));
+ 
+ 			if (rbctrl & BMU_OWN) {
+ 				NDD_TRACE("RHxE",r,rfsw,rbctrl) ;
+@@ -1118,7 +1117,7 @@ void process_receive(struct s_smc *smc)
+ 				smc->os.hwm.detec_count = 0 ;
+ 				goto rx_end ;
+ 			}
+-			rfsw = AIX_REVERSE(r->rxd_rfsw) ;
++			rfsw = le32_to_cpu(r->rxd_rfsw) ;
+ 			if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {
+ 				/*
+ 				 * The BMU_STF bit is deleted, 1 frame is
+@@ -1151,7 +1150,7 @@ void process_receive(struct s_smc *smc)
+ 		/* may be next 2 DRV_BUF_FLUSH() can be skipped, because */
+ 		/* BMU_ST_BUF will not be changed by the ASIC */
+ 		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+-		while (rx_used && !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
++		while (rx_used && !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
+ 			DB_RX("Check STF bit in %x",(void *)r,0,5) ;
+ 			r = r->rxd_next ;
+ 			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+@@ -1171,7 +1170,7 @@ void process_receive(struct s_smc *smc)
+ 		/*
+ 		 * ASIC Errata no. 7 (STF - Bit Bug)
+ 		 */
+-		rxd->rxd_rbctrl &= AIX_REVERSE(~BMU_STF) ;
++		rxd->rxd_rbctrl &= cpu_to_le32(~BMU_STF) ;
+ 
+ 		for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){
+ 			DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
+@@ -1287,7 +1286,7 @@ void process_receive(struct s_smc *smc)
+ 			hwm_cpy_rxd2mb(rxd,data,len) ;
+ #else
+ 			for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){
+-				n = AIX_REVERSE(r->rxd_rbctrl) & RD_LENGTH ;
++				n = le32_to_cpu(r->rxd_rbctrl) & RD_LENGTH ;
+ 				DB_RX("cp SMT frame to mb: len = %d",n,0,6) ;
+ 				memcpy(data,r->rxd_virt,n) ;
+ 				data += n ;
+@@ -1426,14 +1425,14 @@ void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+ 		 int frame_status)
+ {
+ 	struct s_smt_fp_rxd volatile *r ;
+-	u_int	rbctrl ;
++	__le32	rbctrl;
+ 
+ 	NDD_TRACE("RHfB",virt,len,frame_status) ;
+ 	DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ;
+ 	r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;
+ 	r->rxd_virt = virt ;
+-	r->rxd_rbadr = AIX_REVERSE(phys) ;
+-	rbctrl = AIX_REVERSE( (((u_long)frame_status &
++	r->rxd_rbadr = cpu_to_le32(phys) ;
++	rbctrl = cpu_to_le32( (((__u32)frame_status &
+ 		(FIRST_FRAG|LAST_FRAG))<<26) |
+ 		(((u_long) frame_status & FIRST_FRAG) << 21) |
+ 		BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;
+@@ -1444,7 +1443,7 @@ void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+ 	smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;
+ 	smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;
+ 	smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;
+-	NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ;
++	NDD_TRACE("RHfE",r,le32_to_cpu(r->rxd_rbadr),0) ;
+ }
+ 
+ /*
+@@ -1494,15 +1493,15 @@ void mac_drv_clear_rx_queue(struct s_smc *smc)
+ 	while (queue->rx_used) {
+ 		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ 		DB_RX("switch OWN bit of RxD 0x%x ",r,0,5) ;
+-		r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
++		r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ 		frag_count = 1 ;
+ 		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ 		r = r->rxd_next ;
+ 		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ 		while (r != queue->rx_curr_put &&
+-			!(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
++			!(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
+ 			DB_RX("Check STF bit in %x",(void *)r,0,5) ;
+-			r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
++			r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ 			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ 			r = r->rxd_next ;
+ 			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+@@ -1640,7 +1639,7 @@ void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+ {
+ 	struct s_smt_fp_txd volatile *t ;
+ 	struct s_smt_tx_queue *queue ;
+-	u_int	tbctrl ;
++	__le32	tbctrl ;
+ 
+ 	queue = smc->os.hwm.tx_p ;
+ 
+@@ -1657,9 +1656,9 @@ void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+ 		/* '*t' is already defined */
+ 		DB_TX("LAN_TX: TxD = %x, virt = %x ",t,virt,3) ;
+ 		t->txd_virt = virt ;
+-		t->txd_txdscr = AIX_REVERSE(smc->os.hwm.tx_descr) ;
+-		t->txd_tbadr = AIX_REVERSE(phys) ;
+-		tbctrl = AIX_REVERSE((((u_long)frame_status &
++		t->txd_txdscr = cpu_to_le32(smc->os.hwm.tx_descr) ;
++		t->txd_tbadr = cpu_to_le32(phys) ;
++		tbctrl = cpu_to_le32((((__u32)frame_status &
+ 			(FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
+ 			BMU_OWN|BMU_CHECK |len) ;
+ 		t->txd_tbctrl = tbctrl ;
+@@ -1826,7 +1825,7 @@ void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
+ 	struct s_smt_tx_queue *queue ;
+ 	struct s_smt_fp_txd volatile *t ;
+ 	u_long	phys ;
+-	u_int	tbctrl ;
++	__le32	tbctrl;
+ 
+ 	NDD_TRACE("THSB",mb,fc,0) ;
+ 	DB_TX("smt_send_mbuf: mb = 0x%x, fc = 0x%x",mb,fc,4) ;
+@@ -1894,14 +1893,14 @@ void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
+ 			DB_TX("init TxD = 0x%x",(void *)t,0,5) ;
+ 			if (i == frag_count-1) {
+ 				frame_status |= LAST_FRAG ;
+-				t->txd_txdscr = AIX_REVERSE(TX_DESCRIPTOR |
+-					(((u_long)(mb->sm_len-1)&3) << 27)) ;
++				t->txd_txdscr = cpu_to_le32(TX_DESCRIPTOR |
++					(((__u32)(mb->sm_len-1)&3) << 27)) ;
+ 			}
+ 			t->txd_virt = virt[i] ;
+ 			phys = dma_master(smc, (void far *)virt[i],
+ 				frag_len[i], DMA_RD|SMT_BUF) ;
+-			t->txd_tbadr = AIX_REVERSE(phys) ;
+-			tbctrl = AIX_REVERSE((((u_long) frame_status &
++			t->txd_tbadr = cpu_to_le32(phys) ;
++			tbctrl = cpu_to_le32((((__u32)frame_status &
+ 				(FIRST_FRAG|LAST_FRAG)) << 26) |
+ 				BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ;
+ 			t->txd_tbctrl = tbctrl ;
+@@ -1971,8 +1970,7 @@ static void mac_drv_clear_txd(struct s_smc *smc)
+ 			do {
+ 				DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ;
+ 				DB_TX("check OWN/EOF bit of TxD 0x%x",t1,0,5) ;
+-				tbctrl = CR_READ(t1->txd_tbctrl) ;
+-				tbctrl = AIX_REVERSE(tbctrl) ;
++				tbctrl = le32_to_cpu(CR_READ(t1->txd_tbctrl));
+ 
+ 				if (tbctrl & BMU_OWN || !queue->tx_used){
+ 					DB_TX("End of TxDs queue %d",i,0,4) ;
+@@ -1984,7 +1982,7 @@ static void mac_drv_clear_txd(struct s_smc *smc)
+ 
+ 			t1 = queue->tx_curr_get ;
+ 			for (n = frag_count; n; n--) {
+-				tbctrl = AIX_REVERSE(t1->txd_tbctrl) ;
++				tbctrl = le32_to_cpu(t1->txd_tbctrl) ;
+ 				dma_complete(smc,
+ 					(union s_fp_descr volatile *) t1,
+ 					(int) (DMA_RD |
+@@ -2064,7 +2062,7 @@ void mac_drv_clear_tx_queue(struct s_smc *smc)
+ 		while (tx_used) {
+ 			DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
+ 			DB_TX("switch OWN bit of TxD 0x%x ",t,0,5) ;
+-			t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
++			t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ 			DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ 			t = t->txd_next ;
+ 			tx_used-- ;
+@@ -2086,10 +2084,10 @@ void mac_drv_clear_tx_queue(struct s_smc *smc)
+ 		 * tx_curr_get and tx_curr_put to this position
+ 		 */
+ 		if (i == QUEUE_S) {
+-			outpd(ADDR(B5_XS_DA),AIX_REVERSE(t->txd_ntdadr)) ;
++			outpd(ADDR(B5_XS_DA),le32_to_cpu(t->txd_ntdadr)) ;
+ 		}
+ 		else {
+-			outpd(ADDR(B5_XA_DA),AIX_REVERSE(t->txd_ntdadr)) ;
++			outpd(ADDR(B5_XA_DA),le32_to_cpu(t->txd_ntdadr)) ;
+ 		}
+ 
+ 		queue->tx_curr_put = queue->tx_curr_get->txd_next ;
+diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
+index 7cf9b9f..a2b092b 100644
+--- a/drivers/net/skfp/skfddi.c
++++ b/drivers/net/skfp/skfddi.c
+@@ -495,7 +495,7 @@ static int skfp_open(struct net_device *dev)
+ 
+ 	PRINTK(KERN_INFO "entering skfp_open\n");
+ 	/* Register IRQ - support shared interrupts by passing device ptr */
+-	err = request_irq(dev->irq, (void *) skfp_interrupt, IRQF_SHARED,
++	err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED,
+ 			  dev->name, dev);
+ 	if (err)
+ 		return err;
+@@ -1644,7 +1644,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+ 		// Get RIF length from Routing Control (RC) field.
+ 		cp = virt + FDDI_MAC_HDR_LEN;	// Point behind MAC header.
+ 
+-		ri = ntohs(*((unsigned short *) cp));
++		ri = ntohs(*((__be16 *) cp));
+ 		RifLength = ri & FDDI_RCF_LEN_MASK;
+ 		if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) {
+ 			printk("fddi: Invalid RIF.\n");
+diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
+index 76cc1d3..4e28002 100644
+--- a/drivers/net/smc911x.c
++++ b/drivers/net/smc911x.c
+@@ -92,6 +92,7 @@ module_param(tx_fifo_kb, int, 0400);
+ MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)");
+ 
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:smc911x");
+ 
+ /*
+  * The internal workings of the driver.  If you are changing anything
+@@ -243,7 +244,7 @@ static void smc911x_reset(struct net_device *dev)
+ 		do {
+ 			udelay(10);
+ 			reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_;
+-		} while ( timeout-- && !reg);
++		} while (--timeout && !reg);
+ 		if (timeout == 0) {
+ 			PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name);
+ 			return;
+@@ -267,7 +268,7 @@ static void smc911x_reset(struct net_device *dev)
+ 				resets++;
+ 				break;
+ 			}
+-		} while ( timeout-- && (reg & HW_CFG_SRST_));
++		} while (--timeout && (reg & HW_CFG_SRST_));
+ 	}
+ 	if (timeout == 0) {
+ 		PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name);
+@@ -413,7 +414,7 @@ static inline void smc911x_drop_pkt(struct net_device *dev)
+ 		do {
+ 			udelay(10);
+ 			reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_;
+-		} while ( timeout-- && reg);
++		} while (--timeout && reg);
+ 		if (timeout == 0) {
+ 			PRINTK("%s: timeout waiting for RX fast forward\n", dev->name);
+ 		}
+@@ -2262,6 +2263,7 @@ static struct platform_driver smc911x_driver = {
+ 	.resume	 = smc911x_drv_resume,
+ 	.driver	 = {
+ 		.name	 = CARDNAME,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
+index 63a54e2..a188e33 100644
+--- a/drivers/net/smc91x.c
++++ b/drivers/net/smc91x.c
+@@ -132,6 +132,7 @@ module_param(watchdog, int, 0400);
+ MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+ 
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:smc91x");
+ 
+ /*
+  * The internal workings of the driver.  If you are changing anything
+@@ -220,22 +221,22 @@ static void PRINT_PKT(u_char *buf, int length)
+ 
+ 
+ /* this enables an interrupt in the interrupt mask register */
+-#define SMC_ENABLE_INT(x) do {						\
++#define SMC_ENABLE_INT(lp, x) do {					\
+ 	unsigned char mask;						\
+ 	spin_lock_irq(&lp->lock);					\
+-	mask = SMC_GET_INT_MASK();					\
++	mask = SMC_GET_INT_MASK(lp);					\
+ 	mask |= (x);							\
+-	SMC_SET_INT_MASK(mask);						\
++	SMC_SET_INT_MASK(lp, mask);					\
+ 	spin_unlock_irq(&lp->lock);					\
+ } while (0)
+ 
+ /* this disables an interrupt from the interrupt mask register */
+-#define SMC_DISABLE_INT(x) do {						\
++#define SMC_DISABLE_INT(lp, x) do {					\
+ 	unsigned char mask;						\
+ 	spin_lock_irq(&lp->lock);					\
+-	mask = SMC_GET_INT_MASK();					\
++	mask = SMC_GET_INT_MASK(lp);					\
+ 	mask &= ~(x);							\
+-	SMC_SET_INT_MASK(mask);						\
++	SMC_SET_INT_MASK(lp, mask);					\
+ 	spin_unlock_irq(&lp->lock);					\
+ } while (0)
+ 
+@@ -244,10 +245,10 @@ static void PRINT_PKT(u_char *buf, int length)
+  * if at all, but let's avoid deadlocking the system if the hardware
+  * decides to go south.
+  */
+-#define SMC_WAIT_MMU_BUSY() do {					\
+-	if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) {			\
++#define SMC_WAIT_MMU_BUSY(lp) do {					\
++	if (unlikely(SMC_GET_MMU_CMD(lp) & MC_BUSY)) {		\
+ 		unsigned long timeout = jiffies + 2;			\
+-		while (SMC_GET_MMU_CMD() & MC_BUSY) {			\
++		while (SMC_GET_MMU_CMD(lp) & MC_BUSY) {		\
+ 			if (time_after(jiffies, timeout)) {		\
+ 				printk("%s: timeout %s line %d\n",	\
+ 					dev->name, __FILE__, __LINE__);	\
+@@ -273,8 +274,8 @@ static void smc_reset(struct net_device *dev)
+ 
+ 	/* Disable all interrupts, block TX tasklet */
+ 	spin_lock_irq(&lp->lock);
+-	SMC_SELECT_BANK(2);
+-	SMC_SET_INT_MASK(0);
++	SMC_SELECT_BANK(lp, 2);
++	SMC_SET_INT_MASK(lp, 0);
+ 	pending_skb = lp->pending_tx_skb;
+ 	lp->pending_tx_skb = NULL;
+ 	spin_unlock_irq(&lp->lock);
+@@ -290,15 +291,15 @@ static void smc_reset(struct net_device *dev)
+ 	 * This resets the registers mostly to defaults, but doesn't
+ 	 * affect EEPROM.  That seems unnecessary
+ 	 */
+-	SMC_SELECT_BANK(0);
+-	SMC_SET_RCR(RCR_SOFTRST);
++	SMC_SELECT_BANK(lp, 0);
++	SMC_SET_RCR(lp, RCR_SOFTRST);
+ 
+ 	/*
+ 	 * Setup the Configuration Register
+ 	 * This is necessary because the CONFIG_REG is not affected
+ 	 * by a soft reset
+ 	 */
+-	SMC_SELECT_BANK(1);
++	SMC_SELECT_BANK(lp, 1);
+ 
+ 	cfg = CONFIG_DEFAULT;
+ 
+@@ -316,7 +317,7 @@ static void smc_reset(struct net_device *dev)
+ 	 */
+ 	cfg |= CONFIG_EPH_POWER_EN;
+ 
+-	SMC_SET_CONFIG(cfg);
++	SMC_SET_CONFIG(lp, cfg);
+ 
+ 	/* this should pause enough for the chip to be happy */
+ 	/*
+@@ -329,12 +330,12 @@ static void smc_reset(struct net_device *dev)
+ 	udelay(1);
+ 
+ 	/* Disable transmit and receive functionality */
+-	SMC_SELECT_BANK(0);
+-	SMC_SET_RCR(RCR_CLEAR);
+-	SMC_SET_TCR(TCR_CLEAR);
++	SMC_SELECT_BANK(lp, 0);
++	SMC_SET_RCR(lp, RCR_CLEAR);
++	SMC_SET_TCR(lp, TCR_CLEAR);
+ 
+-	SMC_SELECT_BANK(1);
+-	ctl = SMC_GET_CTL() | CTL_LE_ENABLE;
++	SMC_SELECT_BANK(lp, 1);
++	ctl = SMC_GET_CTL(lp) | CTL_LE_ENABLE;
+ 
+ 	/*
+ 	 * Set the control register to automatically release successfully
+@@ -345,12 +346,12 @@ static void smc_reset(struct net_device *dev)
+ 		ctl |= CTL_AUTO_RELEASE;
+ 	else
+ 		ctl &= ~CTL_AUTO_RELEASE;
+-	SMC_SET_CTL(ctl);
++	SMC_SET_CTL(lp, ctl);
+ 
+ 	/* Reset the MMU */
+-	SMC_SELECT_BANK(2);
+-	SMC_SET_MMU_CMD(MC_RESET);
+-	SMC_WAIT_MMU_BUSY();
++	SMC_SELECT_BANK(lp, 2);
++	SMC_SET_MMU_CMD(lp, MC_RESET);
++	SMC_WAIT_MMU_BUSY(lp);
+ }
+ 
+ /*
+@@ -365,19 +366,19 @@ static void smc_enable(struct net_device *dev)
+ 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ 
+ 	/* see the header file for options in TCR/RCR DEFAULT */
+-	SMC_SELECT_BANK(0);
+-	SMC_SET_TCR(lp->tcr_cur_mode);
+-	SMC_SET_RCR(lp->rcr_cur_mode);
++	SMC_SELECT_BANK(lp, 0);
++	SMC_SET_TCR(lp, lp->tcr_cur_mode);
++	SMC_SET_RCR(lp, lp->rcr_cur_mode);
+ 
+-	SMC_SELECT_BANK(1);
+-	SMC_SET_MAC_ADDR(dev->dev_addr);
++	SMC_SELECT_BANK(lp, 1);
++	SMC_SET_MAC_ADDR(lp, dev->dev_addr);
+ 
+ 	/* now, enable interrupts */
+ 	mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT;
+ 	if (lp->version >= (CHIP_91100 << 4))
+ 		mask |= IM_MDINT;
+-	SMC_SELECT_BANK(2);
+-	SMC_SET_INT_MASK(mask);
++	SMC_SELECT_BANK(lp, 2);
++	SMC_SET_INT_MASK(lp, mask);
+ 
+ 	/*
+ 	 * From this point the register bank must _NOT_ be switched away
+@@ -400,8 +401,8 @@ static void smc_shutdown(struct net_device *dev)
+ 
+ 	/* no more interrupts for me */
+ 	spin_lock_irq(&lp->lock);
+-	SMC_SELECT_BANK(2);
+-	SMC_SET_INT_MASK(0);
++	SMC_SELECT_BANK(lp, 2);
++	SMC_SET_INT_MASK(lp, 0);
+ 	pending_skb = lp->pending_tx_skb;
+ 	lp->pending_tx_skb = NULL;
+ 	spin_unlock_irq(&lp->lock);
+@@ -409,14 +410,14 @@ static void smc_shutdown(struct net_device *dev)
+ 		dev_kfree_skb(pending_skb);
+ 
+ 	/* and tell the card to stay away from that nasty outside world */
+-	SMC_SELECT_BANK(0);
+-	SMC_SET_RCR(RCR_CLEAR);
+-	SMC_SET_TCR(TCR_CLEAR);
++	SMC_SELECT_BANK(lp, 0);
++	SMC_SET_RCR(lp, RCR_CLEAR);
++	SMC_SET_TCR(lp, TCR_CLEAR);
+ 
+ #ifdef POWER_DOWN
+ 	/* finally, shut the chip down */
+-	SMC_SELECT_BANK(1);
+-	SMC_SET_CONFIG(SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN);
++	SMC_SELECT_BANK(lp, 1);
++	SMC_SET_CONFIG(lp, SMC_GET_CONFIG(lp) & ~CONFIG_EPH_POWER_EN);
+ #endif
+ }
+ 
+@@ -431,17 +432,17 @@ static inline void  smc_rcv(struct net_device *dev)
+ 
+ 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+ 
+-	packet_number = SMC_GET_RXFIFO();
++	packet_number = SMC_GET_RXFIFO(lp);
+ 	if (unlikely(packet_number & RXFIFO_REMPTY)) {
+ 		PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name);
+ 		return;
+ 	}
+ 
+ 	/* read from start of packet */
+-	SMC_SET_PTR(PTR_READ | PTR_RCV | PTR_AUTOINC);
++	SMC_SET_PTR(lp, PTR_READ | PTR_RCV | PTR_AUTOINC);
+ 
+ 	/* First two words are status and packet length */
+-	SMC_GET_PKT_HDR(status, packet_len);
++	SMC_GET_PKT_HDR(lp, status, packet_len);
+ 	packet_len &= 0x07ff;  /* mask off top bits */
+ 	DBG(2, "%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n",
+ 		dev->name, packet_number, status,
+@@ -460,8 +461,8 @@ static inline void  smc_rcv(struct net_device *dev)
+ 					dev->name, packet_len, status);
+ 			status |= RS_TOOSHORT;
+ 		}
+-		SMC_WAIT_MMU_BUSY();
+-		SMC_SET_MMU_CMD(MC_RELEASE);
++		SMC_WAIT_MMU_BUSY(lp);
++		SMC_SET_MMU_CMD(lp, MC_RELEASE);
+ 		dev->stats.rx_errors++;
+ 		if (status & RS_ALGNERR)
+ 			dev->stats.rx_frame_errors++;
+@@ -490,8 +491,8 @@ static inline void  smc_rcv(struct net_device *dev)
+ 		if (unlikely(skb == NULL)) {
+ 			printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
+ 				dev->name);
+-			SMC_WAIT_MMU_BUSY();
+-			SMC_SET_MMU_CMD(MC_RELEASE);
++			SMC_WAIT_MMU_BUSY(lp);
++			SMC_SET_MMU_CMD(lp, MC_RELEASE);
+ 			dev->stats.rx_dropped++;
+ 			return;
+ 		}
+@@ -510,10 +511,10 @@ static inline void  smc_rcv(struct net_device *dev)
+ 		 */
+ 		data_len = packet_len - ((status & RS_ODDFRAME) ? 5 : 6);
+ 		data = skb_put(skb, data_len);
+-		SMC_PULL_DATA(data, packet_len - 4);
++		SMC_PULL_DATA(lp, data, packet_len - 4);
+ 
+-		SMC_WAIT_MMU_BUSY();
+-		SMC_SET_MMU_CMD(MC_RELEASE);
++		SMC_WAIT_MMU_BUSY(lp);
++		SMC_SET_MMU_CMD(lp, MC_RELEASE);
+ 
+ 		PRINT_PKT(data, packet_len - 4);
+ 
+@@ -591,7 +592,7 @@ static void smc_hardware_send_pkt(unsigned long data)
+ 	}
+ 	lp->pending_tx_skb = NULL;
+ 
+-	packet_no = SMC_GET_AR();
++	packet_no = SMC_GET_AR(lp);
+ 	if (unlikely(packet_no & AR_FAILED)) {
+ 		printk("%s: Memory allocation failed.\n", dev->name);
+ 		dev->stats.tx_errors++;
+@@ -601,8 +602,8 @@ static void smc_hardware_send_pkt(unsigned long data)
+ 	}
+ 
+ 	/* point to the beginning of the packet */
+-	SMC_SET_PN(packet_no);
+-	SMC_SET_PTR(PTR_AUTOINC);
++	SMC_SET_PN(lp, packet_no);
++	SMC_SET_PTR(lp, PTR_AUTOINC);
+ 
+ 	buf = skb->data;
+ 	len = skb->len;
+@@ -614,13 +615,13 @@ static void smc_hardware_send_pkt(unsigned long data)
+ 	 * Send the packet length (+6 for status words, length, and ctl.
+ 	 * The card will pad to 64 bytes with zeroes if packet is too small.
+ 	 */
+-	SMC_PUT_PKT_HDR(0, len + 6);
++	SMC_PUT_PKT_HDR(lp, 0, len + 6);
+ 
+ 	/* send the actual data */
+-	SMC_PUSH_DATA(buf, len & ~1);
++	SMC_PUSH_DATA(lp, buf, len & ~1);
+ 
+ 	/* Send final ctl word with the last byte if there is one */
+-	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG);
++	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));
+ 
+ 	/*
+ 	 * If THROTTLE_TX_PKTS is set, we stop the queue here. This will
+@@ -634,14 +635,14 @@ static void smc_hardware_send_pkt(unsigned long data)
+ 		netif_stop_queue(dev);
+ 
+ 	/* queue the packet for TX */
+-	SMC_SET_MMU_CMD(MC_ENQUEUE);
++	SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
+ 	smc_special_unlock(&lp->lock);
+ 
+ 	dev->trans_start = jiffies;
+ 	dev->stats.tx_packets++;
+ 	dev->stats.tx_bytes += len;
+ 
+-	SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
++	SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT);
+ 
+ done:	if (!THROTTLE_TX_PKTS)
+ 		netif_wake_queue(dev);
+@@ -688,7 +689,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	smc_special_lock(&lp->lock);
+ 
+ 	/* now, try to allocate the memory */
+-	SMC_SET_MMU_CMD(MC_ALLOC | numPages);
++	SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages);
+ 
+ 	/*
+ 	 * Poll the chip for a short amount of time in case the
+@@ -696,9 +697,9 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	 */
+ 	poll_count = MEMORY_WAIT_TIME;
+ 	do {
+-		status = SMC_GET_INT();
++		status = SMC_GET_INT(lp);
+ 		if (status & IM_ALLOC_INT) {
+-			SMC_ACK_INT(IM_ALLOC_INT);
++			SMC_ACK_INT(lp, IM_ALLOC_INT);
+   			break;
+ 		}
+    	} while (--poll_count);
+@@ -710,7 +711,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		/* oh well, wait until the chip finds memory later */
+ 		netif_stop_queue(dev);
+ 		DBG(2, "%s: TX memory allocation deferred.\n", dev->name);
+-		SMC_ENABLE_INT(IM_ALLOC_INT);
++		SMC_ENABLE_INT(lp, IM_ALLOC_INT);
+    	} else {
+ 		/*
+ 		 * Allocation succeeded: push packet to the chip's own memory
+@@ -736,19 +737,19 @@ static void smc_tx(struct net_device *dev)
+ 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+ 
+ 	/* If the TX FIFO is empty then nothing to do */
+-	packet_no = SMC_GET_TXFIFO();
++	packet_no = SMC_GET_TXFIFO(lp);
+ 	if (unlikely(packet_no & TXFIFO_TEMPTY)) {
+ 		PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name);
+ 		return;
+ 	}
+ 
+ 	/* select packet to read from */
+-	saved_packet = SMC_GET_PN();
+-	SMC_SET_PN(packet_no);
++	saved_packet = SMC_GET_PN(lp);
++	SMC_SET_PN(lp, packet_no);
+ 
+ 	/* read the first word (status word) from this packet */
+-	SMC_SET_PTR(PTR_AUTOINC | PTR_READ);
+-	SMC_GET_PKT_HDR(tx_status, pkt_len);
++	SMC_SET_PTR(lp, PTR_AUTOINC | PTR_READ);
++	SMC_GET_PKT_HDR(lp, tx_status, pkt_len);
+ 	DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n",
+ 		dev->name, tx_status, packet_no);
+ 
+@@ -771,17 +772,17 @@ static void smc_tx(struct net_device *dev)
+ 	}
+ 
+ 	/* kill the packet */
+-	SMC_WAIT_MMU_BUSY();
+-	SMC_SET_MMU_CMD(MC_FREEPKT);
++	SMC_WAIT_MMU_BUSY(lp);
++	SMC_SET_MMU_CMD(lp, MC_FREEPKT);
+ 
+ 	/* Don't restore Packet Number Reg until busy bit is cleared */
+-	SMC_WAIT_MMU_BUSY();
+-	SMC_SET_PN(saved_packet);
++	SMC_WAIT_MMU_BUSY(lp);
++	SMC_SET_PN(lp, saved_packet);
+ 
+ 	/* re-enable transmit */
+-	SMC_SELECT_BANK(0);
+-	SMC_SET_TCR(lp->tcr_cur_mode);
+-	SMC_SELECT_BANK(2);
++	SMC_SELECT_BANK(lp, 0);
++	SMC_SET_TCR(lp, lp->tcr_cur_mode);
++	SMC_SELECT_BANK(lp, 2);
+ }
+ 
+ 
+@@ -793,7 +794,7 @@ static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
+ 	void __iomem *ioaddr = lp->base;
+ 	unsigned int mii_reg, mask;
+ 
+-	mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
++	mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO);
+ 	mii_reg |= MII_MDOE;
+ 
+ 	for (mask = 1 << (bits - 1); mask; mask >>= 1) {
+@@ -802,9 +803,9 @@ static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
+ 		else
+ 			mii_reg &= ~MII_MDO;
+ 
+-		SMC_SET_MII(mii_reg);
++		SMC_SET_MII(lp, mii_reg);
+ 		udelay(MII_DELAY);
+-		SMC_SET_MII(mii_reg | MII_MCLK);
++		SMC_SET_MII(lp, mii_reg | MII_MCLK);
+ 		udelay(MII_DELAY);
+ 	}
+ }
+@@ -815,16 +816,16 @@ static unsigned int smc_mii_in(struct net_device *dev, int bits)
+ 	void __iomem *ioaddr = lp->base;
+ 	unsigned int mii_reg, mask, val;
+ 
+-	mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
+-	SMC_SET_MII(mii_reg);
++	mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO);
++	SMC_SET_MII(lp, mii_reg);
+ 
+ 	for (mask = 1 << (bits - 1), val = 0; mask; mask >>= 1) {
+-		if (SMC_GET_MII() & MII_MDI)
++		if (SMC_GET_MII(lp) & MII_MDI)
+ 			val |= mask;
+ 
+-		SMC_SET_MII(mii_reg);
++		SMC_SET_MII(lp, mii_reg);
+ 		udelay(MII_DELAY);
+-		SMC_SET_MII(mii_reg | MII_MCLK);
++		SMC_SET_MII(lp, mii_reg | MII_MCLK);
+ 		udelay(MII_DELAY);
+ 	}
+ 
+@@ -840,7 +841,7 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
+ 	void __iomem *ioaddr = lp->base;
+ 	unsigned int phydata;
+ 
+-	SMC_SELECT_BANK(3);
++	SMC_SELECT_BANK(lp, 3);
+ 
+ 	/* Idle - 32 ones */
+ 	smc_mii_out(dev, 0xffffffff, 32);
+@@ -852,12 +853,12 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
+ 	phydata = smc_mii_in(dev, 18);
+ 
+ 	/* Return to idle state */
+-	SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO));
++	SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
+ 
+ 	DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+ 		__FUNCTION__, phyaddr, phyreg, phydata);
+ 
+-	SMC_SELECT_BANK(2);
++	SMC_SELECT_BANK(lp, 2);
+ 	return phydata;
+ }
+ 
+@@ -870,7 +871,7 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
+ 	struct smc_local *lp = netdev_priv(dev);
+ 	void __iomem *ioaddr = lp->base;
+ 
+-	SMC_SELECT_BANK(3);
++	SMC_SELECT_BANK(lp, 3);
+ 
+ 	/* Idle - 32 ones */
+ 	smc_mii_out(dev, 0xffffffff, 32);
+@@ -879,12 +880,12 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
+ 	smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32);
+ 
+ 	/* Return to idle state */
+-	SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO));
++	SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
+ 
+ 	DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+ 		__FUNCTION__, phyaddr, phyreg, phydata);
+ 
+-	SMC_SELECT_BANK(2);
++	SMC_SELECT_BANK(lp, 2);
+ }
+ 
+ /*
+@@ -957,9 +958,9 @@ static int smc_phy_fixed(struct net_device *dev)
+ 	smc_phy_write(dev, phyaddr, MII_BMCR, bmcr);
+ 
+ 	/* Re-Configure the Receive/Phy Control register */
+-	SMC_SELECT_BANK(0);
+-	SMC_SET_RPC(lp->rpc_cur_mode);
+-	SMC_SELECT_BANK(2);
++	SMC_SELECT_BANK(lp, 0);
++	SMC_SET_RPC(lp, lp->rpc_cur_mode);
++	SMC_SELECT_BANK(lp, 2);
+ 
+ 	return 1;
+ }
+@@ -1050,8 +1051,8 @@ static void smc_phy_check_media(struct net_device *dev, int init)
+ 			lp->tcr_cur_mode &= ~TCR_SWFDUP;
+ 		}
+ 
+-		SMC_SELECT_BANK(0);
+-		SMC_SET_TCR(lp->tcr_cur_mode);
++		SMC_SELECT_BANK(lp, 0);
++		SMC_SET_TCR(lp, lp->tcr_cur_mode);
+ 	}
+ }
+ 
+@@ -1100,8 +1101,8 @@ static void smc_phy_configure(struct work_struct *work)
+ 		PHY_INT_SPDDET | PHY_INT_DPLXDET);
+ 
+ 	/* Configure the Receive/Phy Control register */
+-	SMC_SELECT_BANK(0);
+-	SMC_SET_RPC(lp->rpc_cur_mode);
++	SMC_SELECT_BANK(lp, 0);
++	SMC_SET_RPC(lp, lp->rpc_cur_mode);
+ 
+ 	/* If the user requested no auto neg, then go set his request */
+ 	if (lp->mii.force_media) {
+@@ -1158,7 +1159,7 @@ static void smc_phy_configure(struct work_struct *work)
+ 	smc_phy_check_media(dev, 1);
+ 
+ smc_phy_configure_exit:
+-	SMC_SELECT_BANK(2);
++	SMC_SELECT_BANK(lp, 2);
+ 	spin_unlock_irq(&lp->lock);
+ 	lp->work_pending = 0;
+ }
+@@ -1200,9 +1201,9 @@ static void smc_10bt_check_media(struct net_device *dev, int init)
+ 
+ 	old_carrier = netif_carrier_ok(dev) ? 1 : 0;
+ 
+-	SMC_SELECT_BANK(0);
+-	new_carrier = (SMC_GET_EPH_STATUS() & ES_LINK_OK) ? 1 : 0;
+-	SMC_SELECT_BANK(2);
++	SMC_SELECT_BANK(lp, 0);
++	new_carrier = (SMC_GET_EPH_STATUS(lp) & ES_LINK_OK) ? 1 : 0;
++	SMC_SELECT_BANK(lp, 2);
+ 
+ 	if (init || (old_carrier != new_carrier)) {
+ 		if (!new_carrier) {
+@@ -1224,11 +1225,11 @@ static void smc_eph_interrupt(struct net_device *dev)
+ 
+ 	smc_10bt_check_media(dev, 0);
+ 
+-	SMC_SELECT_BANK(1);
+-	ctl = SMC_GET_CTL();
+-	SMC_SET_CTL(ctl & ~CTL_LE_ENABLE);
+-	SMC_SET_CTL(ctl);
+-	SMC_SELECT_BANK(2);
++	SMC_SELECT_BANK(lp, 1);
++	ctl = SMC_GET_CTL(lp);
++	SMC_SET_CTL(lp, ctl & ~CTL_LE_ENABLE);
++	SMC_SET_CTL(lp, ctl);
++	SMC_SELECT_BANK(lp, 2);
+ }
+ 
+ /*
+@@ -1252,22 +1253,22 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
+ 	 * ISR. */
+ 	SMC_INTERRUPT_PREAMBLE;
+ 
+-	saved_pointer = SMC_GET_PTR();
+-	mask = SMC_GET_INT_MASK();
+-	SMC_SET_INT_MASK(0);
++	saved_pointer = SMC_GET_PTR(lp);
++	mask = SMC_GET_INT_MASK(lp);
++	SMC_SET_INT_MASK(lp, 0);
+ 
+ 	/* set a timeout value, so I don't stay here forever */
+ 	timeout = MAX_IRQ_LOOPS;
+ 
+ 	do {
+-		status = SMC_GET_INT();
++		status = SMC_GET_INT(lp);
+ 
+ 		DBG(2, "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
+ 			dev->name, status, mask,
+-			({ int meminfo; SMC_SELECT_BANK(0);
+-			   meminfo = SMC_GET_MIR();
+-			   SMC_SELECT_BANK(2); meminfo; }),
+-			SMC_GET_FIFO());
++			({ int meminfo; SMC_SELECT_BANK(lp, 0);
++			   meminfo = SMC_GET_MIR(lp);
++			   SMC_SELECT_BANK(lp, 2); meminfo; }),
++			SMC_GET_FIFO(lp));
+ 
+ 		status &= mask;
+ 		if (!status)
+@@ -1277,7 +1278,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
+ 			/* do this before RX as it will free memory quickly */
+ 			DBG(3, "%s: TX int\n", dev->name);
+ 			smc_tx(dev);
+-			SMC_ACK_INT(IM_TX_INT);
++			SMC_ACK_INT(lp, IM_TX_INT);
+ 			if (THROTTLE_TX_PKTS)
+ 				netif_wake_queue(dev);
+ 		} else if (status & IM_RCV_INT) {
+@@ -1292,9 +1293,9 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
+ 			mask &= ~IM_TX_EMPTY_INT;
+ 
+ 			/* update stats */
+-			SMC_SELECT_BANK(0);
+-			card_stats = SMC_GET_COUNTER();
+-			SMC_SELECT_BANK(2);
++			SMC_SELECT_BANK(lp, 0);
++			card_stats = SMC_GET_COUNTER(lp);
++			SMC_SELECT_BANK(lp, 2);
+ 
+ 			/* single collisions */
+ 			dev->stats.collisions += card_stats & 0xF;
+@@ -1304,26 +1305,26 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
+ 			dev->stats.collisions += card_stats & 0xF;
+ 		} else if (status & IM_RX_OVRN_INT) {
+ 			DBG(1, "%s: RX overrun (EPH_ST 0x%04x)\n", dev->name,
+-			       ({ int eph_st; SMC_SELECT_BANK(0);
+-				  eph_st = SMC_GET_EPH_STATUS();
+-				  SMC_SELECT_BANK(2); eph_st; }) );
+-			SMC_ACK_INT(IM_RX_OVRN_INT);
++			       ({ int eph_st; SMC_SELECT_BANK(lp, 0);
++				  eph_st = SMC_GET_EPH_STATUS(lp);
++				  SMC_SELECT_BANK(lp, 2); eph_st; }));
++			SMC_ACK_INT(lp, IM_RX_OVRN_INT);
+ 			dev->stats.rx_errors++;
+ 			dev->stats.rx_fifo_errors++;
+ 		} else if (status & IM_EPH_INT) {
+ 			smc_eph_interrupt(dev);
+ 		} else if (status & IM_MDINT) {
+-			SMC_ACK_INT(IM_MDINT);
++			SMC_ACK_INT(lp, IM_MDINT);
+ 			smc_phy_interrupt(dev);
+ 		} else if (status & IM_ERCV_INT) {
+-			SMC_ACK_INT(IM_ERCV_INT);
++			SMC_ACK_INT(lp, IM_ERCV_INT);
+ 			PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
+ 		}
+ 	} while (--timeout);
+ 
+ 	/* restore register states */
+-	SMC_SET_PTR(saved_pointer);
+-	SMC_SET_INT_MASK(mask);
++	SMC_SET_PTR(lp, saved_pointer);
++	SMC_SET_INT_MASK(lp, mask);
+ 	spin_unlock(&lp->lock);
+ 
+ #ifndef CONFIG_NET_POLL_CONTROLLER
+@@ -1368,13 +1369,13 @@ static void smc_timeout(struct net_device *dev)
+ 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+ 
+ 	spin_lock_irq(&lp->lock);
+-	status = SMC_GET_INT();
+-	mask = SMC_GET_INT_MASK();
+-	fifo = SMC_GET_FIFO();
+-	SMC_SELECT_BANK(0);
+-	eph_st = SMC_GET_EPH_STATUS();
+-	meminfo = SMC_GET_MIR();
+-	SMC_SELECT_BANK(2);
++	status = SMC_GET_INT(lp);
++	mask = SMC_GET_INT_MASK(lp);
++	fifo = SMC_GET_FIFO(lp);
++	SMC_SELECT_BANK(lp, 0);
++	eph_st = SMC_GET_EPH_STATUS(lp);
++	meminfo = SMC_GET_MIR(lp);
++	SMC_SELECT_BANK(lp, 2);
+ 	spin_unlock_irq(&lp->lock);
+ 	PRINTK( "%s: TX timeout (INT 0x%02x INTMASK 0x%02x "
+ 		"MEM 0x%04x FIFO 0x%04x EPH_ST 0x%04x)\n",
+@@ -1494,13 +1495,13 @@ static void smc_set_multicast_list(struct net_device *dev)
+ 	}
+ 
+ 	spin_lock_irq(&lp->lock);
+-	SMC_SELECT_BANK(0);
+-	SMC_SET_RCR(lp->rcr_cur_mode);
++	SMC_SELECT_BANK(lp, 0);
++	SMC_SET_RCR(lp, lp->rcr_cur_mode);
+ 	if (update_multicast) {
+-		SMC_SELECT_BANK(3);
+-		SMC_SET_MCAST(multicast_table);
++		SMC_SELECT_BANK(lp, 3);
++		SMC_SET_MCAST(lp, multicast_table);
+ 	}
+-	SMC_SELECT_BANK(2);
++	SMC_SELECT_BANK(lp, 2);
+ 	spin_unlock_irq(&lp->lock);
+ }
+ 
+@@ -1704,8 +1705,9 @@ static const struct ethtool_ops smc_ethtool_ops = {
+  * I just deleted auto_irq.c, since it was never built...
+  *   --jgarzik
+  */
+-static int __init smc_findirq(void __iomem *ioaddr)
++static int __init smc_findirq(struct smc_local *lp)
+ {
++	void __iomem *ioaddr = lp->base;
+ 	int timeout = 20;
+ 	unsigned long cookie;
+ 
+@@ -1719,14 +1721,14 @@ static int __init smc_findirq(void __iomem *ioaddr)
+ 	 * when done.
+ 	 */
+ 	/* enable ALLOCation interrupts ONLY */
+-	SMC_SELECT_BANK(2);
+-	SMC_SET_INT_MASK(IM_ALLOC_INT);
++	SMC_SELECT_BANK(lp, 2);
++	SMC_SET_INT_MASK(lp, IM_ALLOC_INT);
+ 
+ 	/*
+  	 * Allocate 512 bytes of memory.  Note that the chip was just
+ 	 * reset so all the memory is available
+ 	 */
+-	SMC_SET_MMU_CMD(MC_ALLOC | 1);
++	SMC_SET_MMU_CMD(lp, MC_ALLOC | 1);
+ 
+ 	/*
+ 	 * Wait until positive that the interrupt has been generated
+@@ -1734,7 +1736,7 @@ static int __init smc_findirq(void __iomem *ioaddr)
+ 	do {
+ 		int int_status;
+ 		udelay(10);
+-		int_status = SMC_GET_INT();
++		int_status = SMC_GET_INT(lp);
+ 		if (int_status & IM_ALLOC_INT)
+ 			break;		/* got the interrupt */
+ 	} while (--timeout);
+@@ -1747,7 +1749,7 @@ static int __init smc_findirq(void __iomem *ioaddr)
+ 	 */
+ 
+ 	/* and disable all interrupts again */
+-	SMC_SET_INT_MASK(0);
++	SMC_SET_INT_MASK(lp, 0);
+ 
+ 	/* and return what I found */
+ 	return probe_irq_off(cookie);
+@@ -1790,7 +1792,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ 	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
+ 
+ 	/* First, see if the high byte is 0x33 */
+-	val = SMC_CURRENT_BANK();
++	val = SMC_CURRENT_BANK(lp);
+ 	DBG(2, "%s: bank signature probe returned 0x%04x\n", CARDNAME, val);
+ 	if ((val & 0xFF00) != 0x3300) {
+ 		if ((val & 0xFF) == 0x33) {
+@@ -1806,8 +1808,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ 	 * The above MIGHT indicate a device, but I need to write to
+ 	 * further test this.
+ 	 */
+-	SMC_SELECT_BANK(0);
+-	val = SMC_CURRENT_BANK();
++	SMC_SELECT_BANK(lp, 0);
++	val = SMC_CURRENT_BANK(lp);
+ 	if ((val & 0xFF00) != 0x3300) {
+ 		retval = -ENODEV;
+ 		goto err_out;
+@@ -1819,8 +1821,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ 	 * register to bank 1, so I can access the base address
+ 	 * register
+ 	 */
+-	SMC_SELECT_BANK(1);
+-	val = SMC_GET_BASE();
++	SMC_SELECT_BANK(lp, 1);
++	val = SMC_GET_BASE(lp);
+ 	val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
+ 	if (((unsigned int)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) {
+ 		printk("%s: IOADDR %p doesn't match configuration (%x).\n",
+@@ -1832,8 +1834,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ 	 * recognize.  These might need to be added to later,
+ 	 * as future revisions could be added.
+ 	 */
+-	SMC_SELECT_BANK(3);
+-	revision_register = SMC_GET_REV();
++	SMC_SELECT_BANK(lp, 3);
++	revision_register = SMC_GET_REV(lp);
+ 	DBG(2, "%s: revision = 0x%04x\n", CARDNAME, revision_register);
+ 	version_string = chip_ids[ (revision_register >> 4) & 0xF];
+ 	if (!version_string || (revision_register & 0xff00) != 0x3300) {
+@@ -1857,8 +1859,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ 	spin_lock_init(&lp->lock);
+ 
+ 	/* Get the MAC address */
+-	SMC_SELECT_BANK(1);
+-	SMC_GET_MAC_ADDR(dev->dev_addr);
++	SMC_SELECT_BANK(lp, 1);
++	SMC_GET_MAC_ADDR(lp, dev->dev_addr);
+ 
+ 	/* now, reset the chip, and put it into a known state */
+ 	smc_reset(dev);
+@@ -1883,7 +1885,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ 
+ 		trials = 3;
+ 		while (trials--) {
+-			dev->irq = smc_findirq(ioaddr);
++			dev->irq = smc_findirq(lp);
+ 			if (dev->irq)
+ 				break;
+ 			/* kick the card and try again */
+@@ -1998,6 +2000,8 @@ err_out:
+ 
+ static int smc_enable_device(struct platform_device *pdev)
+ {
++	struct net_device *ndev = platform_get_drvdata(pdev);
++	struct smc_local *lp = netdev_priv(ndev);
+ 	unsigned long flags;
+ 	unsigned char ecor, ecsr;
+ 	void __iomem *addr;
+@@ -2040,7 +2044,7 @@ static int smc_enable_device(struct platform_device *pdev)
+ 	 * Set the appropriate byte/word mode.
+ 	 */
+ 	ecsr = readb(addr + (ECSR << SMC_IO_SHIFT)) & ~ECSR_IOIS8;
+-	if (!SMC_CAN_USE_16BIT)
++	if (!SMC_16BIT(lp))
+ 		ecsr |= ECSR_IOIS8;
+ 	writeb(ecsr, addr + (ECSR << SMC_IO_SHIFT));
+ 	local_irq_restore(flags);
+@@ -2125,10 +2129,11 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
+  */
+ static int smc_drv_probe(struct platform_device *pdev)
+ {
++	struct smc91x_platdata *pd = pdev->dev.platform_data;
++	struct smc_local *lp;
+ 	struct net_device *ndev;
+ 	struct resource *res, *ires;
+ 	unsigned int __iomem *addr;
+-	unsigned long irq_flags = SMC_IRQ_FLAGS;
+ 	int ret;
+ 
+ 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+@@ -2153,6 +2158,27 @@ static int smc_drv_probe(struct platform_device *pdev)
+ 	}
+ 	SET_NETDEV_DEV(ndev, &pdev->dev);
+ 
++	/* get configuration from platform data, only allow use of
++	 * bus width if both SMC_CAN_USE_xxx and SMC91X_USE_xxx are set.
++	 */
++
++	lp = netdev_priv(ndev);
++	lp->cfg.irq_flags = SMC_IRQ_FLAGS;
++
++#ifdef SMC_DYNAMIC_BUS_CONFIG
++	if (pd)
++		memcpy(&lp->cfg, pd, sizeof(lp->cfg));
++	else {
++		lp->cfg.flags = SMC91X_USE_8BIT;
++		lp->cfg.flags |= SMC91X_USE_16BIT;
++		lp->cfg.flags |= SMC91X_USE_32BIT;
++	}
++
++	lp->cfg.flags &= ~(SMC_CAN_USE_8BIT ? 0 : SMC91X_USE_8BIT);
++	lp->cfg.flags &= ~(SMC_CAN_USE_16BIT ? 0 : SMC91X_USE_16BIT);
++	lp->cfg.flags &= ~(SMC_CAN_USE_32BIT ? 0 : SMC91X_USE_32BIT);
++#endif
++
+ 	ndev->dma = (unsigned char)-1;
+ 
+ 	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+@@ -2163,7 +2189,7 @@ static int smc_drv_probe(struct platform_device *pdev)
+ 
+ 	ndev->irq = ires->start;
+ 	if (SMC_IRQ_FLAGS == -1)
+-		irq_flags = ires->flags & IRQF_TRIGGER_MASK;
++		lp->cfg.irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+ 
+ 	ret = smc_request_attrib(pdev);
+ 	if (ret)
+@@ -2171,6 +2197,7 @@ static int smc_drv_probe(struct platform_device *pdev)
+ #if defined(CONFIG_SA1100_ASSABET)
+ 	NCR_0 |= NCR_ENET_OSC_EN;
+ #endif
++	platform_set_drvdata(pdev, ndev);
+ 	ret = smc_enable_device(pdev);
+ 	if (ret)
+ 		goto out_release_attrib;
+@@ -2189,8 +2216,7 @@ static int smc_drv_probe(struct platform_device *pdev)
+ 	}
+ #endif
+ 
+-	platform_set_drvdata(pdev, ndev);
+-	ret = smc_probe(ndev, addr, irq_flags);
++	ret = smc_probe(ndev, addr, lp->cfg.irq_flags);
+ 	if (ret != 0)
+ 		goto out_iounmap;
+ 
+@@ -2283,6 +2309,7 @@ static struct platform_driver smc_driver = {
+ 	.resume		= smc_drv_resume,
+ 	.driver		= {
+ 		.name	= CARDNAME,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
+index 51d4134..69e97a1 100644
+--- a/drivers/net/smc91x.h
++++ b/drivers/net/smc91x.h
+@@ -34,6 +34,7 @@
+ #ifndef _SMC91X_H_
+ #define _SMC91X_H_
+ 
++#include <linux/smc91x.h>
+ 
+ /*
+  * Define your architecture specific bus configuration parameters here.
+@@ -291,36 +292,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
+ #define SMC_insw(a, r, p, l)	insw((a) + (r), p, l)
+ #define SMC_outsw(a, r, p, l)	outsw((a) + (r), p, l)
+ 
+-#elif   defined(CONFIG_SUPERH)
+-
+-#ifdef CONFIG_SOLUTION_ENGINE
+-#define SMC_IRQ_FLAGS		(0)
+-#define SMC_CAN_USE_8BIT       0
+-#define SMC_CAN_USE_16BIT      1
+-#define SMC_CAN_USE_32BIT      0
+-#define SMC_IO_SHIFT           0
+-#define SMC_NOWAIT             1
+-
+-#define SMC_inw(a, r)          inw((a) + (r))
+-#define SMC_outw(v, a, r)      outw(v, (a) + (r))
+-#define SMC_insw(a, r, p, l)   insw((a) + (r), p, l)
+-#define SMC_outsw(a, r, p, l)  outsw((a) + (r), p, l)
+-
+-#else /* BOARDS */
+-
+-#define SMC_CAN_USE_8BIT       1
+-#define SMC_CAN_USE_16BIT      1
+-#define SMC_CAN_USE_32BIT      0
+-
+-#define SMC_inb(a, r)          inb((a) + (r))
+-#define SMC_inw(a, r)          inw((a) + (r))
+-#define SMC_outb(v, a, r)      outb(v, (a) + (r))
+-#define SMC_outw(v, a, r)      outw(v, (a) + (r))
+-#define SMC_insw(a, r, p, l)   insw((a) + (r), p, l)
+-#define SMC_outsw(a, r, p, l)  outsw((a) + (r), p, l)
+-
+-#endif  /* BOARDS */
+-
+ #elif   defined(CONFIG_M32R)
+ 
+ #define SMC_CAN_USE_8BIT	0
+@@ -475,12 +446,15 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
+ #define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+ #define SMC_outw(v, a, r)	writew(v, (a) + (r))
+ #define SMC_outl(v, a, r)	writel(v, (a) + (r))
++#define SMC_insw(a, r, p, l)	readsw((a) + (r), p, l)
++#define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
+ #define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
+ #define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
+ 
+ #define RPC_LSA_DEFAULT		RPC_LED_100_10
+ #define RPC_LSB_DEFAULT		RPC_LED_TX_RX
+ 
++#define SMC_DYNAMIC_BUS_CONFIG
+ #endif
+ 
+ 
+@@ -526,8 +500,19 @@ struct smc_local {
+ #endif
+ 	void __iomem *base;
+ 	void __iomem *datacs;
++
++	struct smc91x_platdata cfg;
+ };
+ 
++#ifdef SMC_DYNAMIC_BUS_CONFIG
++#define SMC_8BIT(p) (((p)->cfg.flags & SMC91X_USE_8BIT) && SMC_CAN_USE_8BIT)
++#define SMC_16BIT(p) (((p)->cfg.flags & SMC91X_USE_16BIT) && SMC_CAN_USE_16BIT)
++#define SMC_32BIT(p) (((p)->cfg.flags & SMC91X_USE_32BIT) && SMC_CAN_USE_32BIT)
++#else
++#define SMC_8BIT(p) SMC_CAN_USE_8BIT
++#define SMC_16BIT(p) SMC_CAN_USE_16BIT
++#define SMC_32BIT(p) SMC_CAN_USE_32BIT
++#endif
+ 
+ #ifdef SMC_USE_PXA_DMA
+ /*
+@@ -720,7 +705,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // Transmit Control Register
+ /* BANK 0  */
+-#define TCR_REG 	SMC_REG(0x0000, 0)
++#define TCR_REG(lp) 	SMC_REG(lp, 0x0000, 0)
+ #define TCR_ENABLE	0x0001	// When 1 we can transmit
+ #define TCR_LOOP	0x0002	// Controls output pin LBK
+ #define TCR_FORCOL	0x0004	// When 1 will force a collision
+@@ -739,7 +724,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // EPH Status Register
+ /* BANK 0  */
+-#define EPH_STATUS_REG	SMC_REG(0x0002, 0)
++#define EPH_STATUS_REG(lp)	SMC_REG(lp, 0x0002, 0)
+ #define ES_TX_SUC	0x0001	// Last TX was successful
+ #define ES_SNGL_COL	0x0002	// Single collision detected for last tx
+ #define ES_MUL_COL	0x0004	// Multiple collisions detected for last tx
+@@ -758,7 +743,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // Receive Control Register
+ /* BANK 0  */
+-#define RCR_REG		SMC_REG(0x0004, 0)
++#define RCR_REG(lp)		SMC_REG(lp, 0x0004, 0)
+ #define RCR_RX_ABORT	0x0001	// Set if a rx frame was aborted
+ #define RCR_PRMS	0x0002	// Enable promiscuous mode
+ #define RCR_ALMUL	0x0004	// When set accepts all multicast frames
+@@ -775,17 +760,17 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // Counter Register
+ /* BANK 0  */
+-#define COUNTER_REG	SMC_REG(0x0006, 0)
++#define COUNTER_REG(lp)	SMC_REG(lp, 0x0006, 0)
+ 
+ 
+ // Memory Information Register
+ /* BANK 0  */
+-#define MIR_REG		SMC_REG(0x0008, 0)
++#define MIR_REG(lp)		SMC_REG(lp, 0x0008, 0)
+ 
+ 
+ // Receive/Phy Control Register
+ /* BANK 0  */
+-#define RPC_REG		SMC_REG(0x000A, 0)
++#define RPC_REG(lp)		SMC_REG(lp, 0x000A, 0)
+ #define RPC_SPEED	0x2000	// When 1 PHY is in 100Mbps mode.
+ #define RPC_DPLX	0x1000	// When 1 PHY is in Full-Duplex Mode
+ #define RPC_ANEG	0x0800	// When 1 PHY is in Auto-Negotiate Mode
+@@ -819,7 +804,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // Configuration Reg
+ /* BANK 1 */
+-#define CONFIG_REG	SMC_REG(0x0000,	1)
++#define CONFIG_REG(lp)	SMC_REG(lp, 0x0000,	1)
+ #define CONFIG_EXT_PHY	0x0200	// 1=external MII, 0=internal Phy
+ #define CONFIG_GPCNTRL	0x0400	// Inverse value drives pin nCNTRL
+ #define CONFIG_NO_WAIT	0x1000	// When 1 no extra wait states on ISA bus
+@@ -831,24 +816,24 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // Base Address Register
+ /* BANK 1 */
+-#define BASE_REG	SMC_REG(0x0002, 1)
++#define BASE_REG(lp)	SMC_REG(lp, 0x0002, 1)
+ 
+ 
+ // Individual Address Registers
+ /* BANK 1 */
+-#define ADDR0_REG	SMC_REG(0x0004, 1)
+-#define ADDR1_REG	SMC_REG(0x0006, 1)
+-#define ADDR2_REG	SMC_REG(0x0008, 1)
++#define ADDR0_REG(lp)	SMC_REG(lp, 0x0004, 1)
++#define ADDR1_REG(lp)	SMC_REG(lp, 0x0006, 1)
++#define ADDR2_REG(lp)	SMC_REG(lp, 0x0008, 1)
+ 
+ 
+ // General Purpose Register
+ /* BANK 1 */
+-#define GP_REG		SMC_REG(0x000A, 1)
++#define GP_REG(lp)		SMC_REG(lp, 0x000A, 1)
+ 
+ 
+ // Control Register
+ /* BANK 1 */
+-#define CTL_REG		SMC_REG(0x000C, 1)
++#define CTL_REG(lp)		SMC_REG(lp, 0x000C, 1)
+ #define CTL_RCV_BAD	0x4000 // When 1 bad CRC packets are received
+ #define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically
+ #define CTL_LE_ENABLE	0x0080 // When 1 enables Link Error interrupt
+@@ -861,7 +846,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // MMU Command Register
+ /* BANK 2 */
+-#define MMU_CMD_REG	SMC_REG(0x0000, 2)
++#define MMU_CMD_REG(lp)	SMC_REG(lp, 0x0000, 2)
+ #define MC_BUSY		1	// When 1 the last release has not completed
+ #define MC_NOP		(0<<5)	// No Op
+ #define MC_ALLOC	(1<<5) 	// OR with number of 256 byte packets
+@@ -875,30 +860,30 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // Packet Number Register
+ /* BANK 2 */
+-#define PN_REG		SMC_REG(0x0002, 2)
++#define PN_REG(lp)		SMC_REG(lp, 0x0002, 2)
+ 
+ 
+ // Allocation Result Register
+ /* BANK 2 */
+-#define AR_REG		SMC_REG(0x0003, 2)
++#define AR_REG(lp)		SMC_REG(lp, 0x0003, 2)
+ #define AR_FAILED	0x80	// Alocation Failed
+ 
+ 
+ // TX FIFO Ports Register
+ /* BANK 2 */
+-#define TXFIFO_REG	SMC_REG(0x0004, 2)
++#define TXFIFO_REG(lp)	SMC_REG(lp, 0x0004, 2)
+ #define TXFIFO_TEMPTY	0x80	// TX FIFO Empty
+ 
+ // RX FIFO Ports Register
+ /* BANK 2 */
+-#define RXFIFO_REG	SMC_REG(0x0005, 2)
++#define RXFIFO_REG(lp)	SMC_REG(lp, 0x0005, 2)
+ #define RXFIFO_REMPTY	0x80	// RX FIFO Empty
+ 
+-#define FIFO_REG	SMC_REG(0x0004, 2)
++#define FIFO_REG(lp)	SMC_REG(lp, 0x0004, 2)
+ 
+ // Pointer Register
+ /* BANK 2 */
+-#define PTR_REG		SMC_REG(0x0006, 2)
++#define PTR_REG(lp)		SMC_REG(lp, 0x0006, 2)
+ #define PTR_RCV		0x8000 // 1=Receive area, 0=Transmit area
+ #define PTR_AUTOINC 	0x4000 // Auto increment the pointer on each access
+ #define PTR_READ	0x2000 // When 1 the operation is a read
+@@ -906,17 +891,17 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // Data Register
+ /* BANK 2 */
+-#define DATA_REG	SMC_REG(0x0008, 2)
++#define DATA_REG(lp)	SMC_REG(lp, 0x0008, 2)
+ 
+ 
+ // Interrupt Status/Acknowledge Register
+ /* BANK 2 */
+-#define INT_REG		SMC_REG(0x000C, 2)
++#define INT_REG(lp)		SMC_REG(lp, 0x000C, 2)
+ 
+ 
+ // Interrupt Mask Register
+ /* BANK 2 */
+-#define IM_REG		SMC_REG(0x000D, 2)
++#define IM_REG(lp)		SMC_REG(lp, 0x000D, 2)
+ #define IM_MDINT	0x80 // PHY MI Register 18 Interrupt
+ #define IM_ERCV_INT	0x40 // Early Receive Interrupt
+ #define IM_EPH_INT	0x20 // Set by Ethernet Protocol Handler section
+@@ -929,15 +914,15 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ 
+ // Multicast Table Registers
+ /* BANK 3 */
+-#define MCAST_REG1	SMC_REG(0x0000, 3)
+-#define MCAST_REG2	SMC_REG(0x0002, 3)
+-#define MCAST_REG3	SMC_REG(0x0004, 3)
+-#define MCAST_REG4	SMC_REG(0x0006, 3)
++#define MCAST_REG1(lp)	SMC_REG(lp, 0x0000, 3)
++#define MCAST_REG2(lp)	SMC_REG(lp, 0x0002, 3)
++#define MCAST_REG3(lp)	SMC_REG(lp, 0x0004, 3)
++#define MCAST_REG4(lp)	SMC_REG(lp, 0x0006, 3)
+ 
+ 
+ // Management Interface Register (MII)
+ /* BANK 3 */
+-#define MII_REG		SMC_REG(0x0008, 3)
++#define MII_REG(lp)		SMC_REG(lp, 0x0008, 3)
+ #define MII_MSK_CRS100	0x4000 // Disables CRS100 detection during tx half dup
+ #define MII_MDOE	0x0008 // MII Output Enable
+ #define MII_MCLK	0x0004 // MII Clock, pin MDCLK
+@@ -948,20 +933,20 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ // Revision Register
+ /* BANK 3 */
+ /* ( hi: chip id   low: rev # ) */
+-#define REV_REG		SMC_REG(0x000A, 3)
++#define REV_REG(lp)		SMC_REG(lp, 0x000A, 3)
+ 
+ 
+ // Early RCV Register
+ /* BANK 3 */
+ /* this is NOT on SMC9192 */
+-#define ERCV_REG	SMC_REG(0x000C, 3)
++#define ERCV_REG(lp)	SMC_REG(lp, 0x000C, 3)
+ #define ERCV_RCV_DISCRD	0x0080 // When 1 discards a packet being received
+ #define ERCV_THRESHOLD	0x001F // ERCV Threshold Mask
+ 
+ 
+ // External Register
+ /* BANK 7 */
+-#define EXT_REG		SMC_REG(0x0000, 7)
++#define EXT_REG(lp)		SMC_REG(lp, 0x0000, 7)
+ 
+ 
+ #define CHIP_9192	3
+@@ -1085,9 +1070,9 @@ static const char * chip_ids[ 16 ] =  {
+  */
+ 
+ #if SMC_DEBUG > 0
+-#define SMC_REG(reg, bank)						\
++#define SMC_REG(lp, reg, bank)					\
+ 	({								\
+-		int __b = SMC_CURRENT_BANK();				\
++		int __b = SMC_CURRENT_BANK(lp);			\
+ 		if (unlikely((__b & ~0xf0) != (0x3300 | bank))) {	\
+ 			printk( "%s: bank reg screwed (0x%04x)\n",	\
+ 				CARDNAME, __b );			\
+@@ -1096,7 +1081,7 @@ static const char * chip_ids[ 16 ] =  {
+ 		reg<<SMC_IO_SHIFT;					\
+ 	})
+ #else
+-#define SMC_REG(reg, bank)	(reg<<SMC_IO_SHIFT)
++#define SMC_REG(lp, reg, bank)	(reg<<SMC_IO_SHIFT)
+ #endif
+ 
+ /*
+@@ -1108,212 +1093,215 @@ static const char * chip_ids[ 16 ] =  {
+  *
+  * Enforce it on any 32-bit capable setup for now.
+  */
+-#define SMC_MUST_ALIGN_WRITE	SMC_CAN_USE_32BIT
++#define SMC_MUST_ALIGN_WRITE(lp)	SMC_32BIT(lp)
+ 
+-#define SMC_GET_PN()							\
+-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, PN_REG))		\
+-				: (SMC_inw(ioaddr, PN_REG) & 0xFF) )
++#define SMC_GET_PN(lp)						\
++	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, PN_REG(lp)))	\
++				: (SMC_inw(ioaddr, PN_REG(lp)) & 0xFF))
+ 
+-#define SMC_SET_PN(x)							\
++#define SMC_SET_PN(lp, x)						\
+ 	do {								\
+-		if (SMC_MUST_ALIGN_WRITE)				\
+-			SMC_outl((x)<<16, ioaddr, SMC_REG(0, 2));	\
+-		else if (SMC_CAN_USE_8BIT)				\
+-			SMC_outb(x, ioaddr, PN_REG);			\
++		if (SMC_MUST_ALIGN_WRITE(lp))				\
++			SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 0, 2));	\
++		else if (SMC_8BIT(lp))				\
++			SMC_outb(x, ioaddr, PN_REG(lp));		\
+ 		else							\
+-			SMC_outw(x, ioaddr, PN_REG);			\
++			SMC_outw(x, ioaddr, PN_REG(lp));		\
+ 	} while (0)
+ 
+-#define SMC_GET_AR()							\
+-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, AR_REG))		\
+-	  			: (SMC_inw(ioaddr, PN_REG) >> 8) )
++#define SMC_GET_AR(lp)						\
++	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, AR_REG(lp)))	\
++				: (SMC_inw(ioaddr, PN_REG(lp)) >> 8))
+ 
+-#define SMC_GET_TXFIFO()						\
+-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, TXFIFO_REG))		\
+-				: (SMC_inw(ioaddr, TXFIFO_REG) & 0xFF) )
++#define SMC_GET_TXFIFO(lp)						\
++	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, TXFIFO_REG(lp)))	\
++				: (SMC_inw(ioaddr, TXFIFO_REG(lp)) & 0xFF))
+ 
+-#define SMC_GET_RXFIFO()						\
+-	  ( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, RXFIFO_REG))		\
+-				: (SMC_inw(ioaddr, TXFIFO_REG) >> 8) )
++#define SMC_GET_RXFIFO(lp)						\
++	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, RXFIFO_REG(lp)))	\
++				: (SMC_inw(ioaddr, TXFIFO_REG(lp)) >> 8))
+ 
+-#define SMC_GET_INT()							\
+-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, INT_REG))		\
+-				: (SMC_inw(ioaddr, INT_REG) & 0xFF) )
++#define SMC_GET_INT(lp)						\
++	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, INT_REG(lp)))	\
++				: (SMC_inw(ioaddr, INT_REG(lp)) & 0xFF))
+ 
+-#define SMC_ACK_INT(x)							\
++#define SMC_ACK_INT(lp, x)						\
+ 	do {								\
+-		if (SMC_CAN_USE_8BIT)					\
+-			SMC_outb(x, ioaddr, INT_REG);			\
++		if (SMC_8BIT(lp))					\
++			SMC_outb(x, ioaddr, INT_REG(lp));		\
+ 		else {							\
+ 			unsigned long __flags;				\
+ 			int __mask;					\
+ 			local_irq_save(__flags);			\
+-			__mask = SMC_inw( ioaddr, INT_REG ) & ~0xff;	\
+-			SMC_outw( __mask | (x), ioaddr, INT_REG );	\
++			__mask = SMC_inw(ioaddr, INT_REG(lp)) & ~0xff; \
++			SMC_outw(__mask | (x), ioaddr, INT_REG(lp));	\
+ 			local_irq_restore(__flags);			\
+ 		}							\
+ 	} while (0)
+ 
+-#define SMC_GET_INT_MASK()						\
+-	( SMC_CAN_USE_8BIT	? (SMC_inb(ioaddr, IM_REG))		\
+-				: (SMC_inw( ioaddr, INT_REG ) >> 8) )
++#define SMC_GET_INT_MASK(lp)						\
++	(SMC_8BIT(lp)	? (SMC_inb(ioaddr, IM_REG(lp)))	\
++				: (SMC_inw(ioaddr, INT_REG(lp)) >> 8))
+ 
+-#define SMC_SET_INT_MASK(x)						\
++#define SMC_SET_INT_MASK(lp, x)					\
+ 	do {								\
+-		if (SMC_CAN_USE_8BIT)					\
+-			SMC_outb(x, ioaddr, IM_REG);			\
++		if (SMC_8BIT(lp))					\
++			SMC_outb(x, ioaddr, IM_REG(lp));		\
+ 		else							\
+-			SMC_outw((x) << 8, ioaddr, INT_REG);		\
++			SMC_outw((x) << 8, ioaddr, INT_REG(lp));	\
+ 	} while (0)
+ 
+-#define SMC_CURRENT_BANK()	SMC_inw(ioaddr, BANK_SELECT)
++#define SMC_CURRENT_BANK(lp)	SMC_inw(ioaddr, BANK_SELECT)
+ 
+-#define SMC_SELECT_BANK(x)						\
++#define SMC_SELECT_BANK(lp, x)					\
+ 	do {								\
+-		if (SMC_MUST_ALIGN_WRITE)				\
++		if (SMC_MUST_ALIGN_WRITE(lp))				\
+ 			SMC_outl((x)<<16, ioaddr, 12<<SMC_IO_SHIFT);	\
+ 		else							\
+ 			SMC_outw(x, ioaddr, BANK_SELECT);		\
+ 	} while (0)
+ 
+-#define SMC_GET_BASE()		SMC_inw(ioaddr, BASE_REG)
++#define SMC_GET_BASE(lp)		SMC_inw(ioaddr, BASE_REG(lp))
+ 
+-#define SMC_SET_BASE(x)		SMC_outw(x, ioaddr, BASE_REG)
++#define SMC_SET_BASE(lp, x)		SMC_outw(x, ioaddr, BASE_REG(lp))
+ 
+-#define SMC_GET_CONFIG()	SMC_inw(ioaddr, CONFIG_REG)
++#define SMC_GET_CONFIG(lp)	SMC_inw(ioaddr, CONFIG_REG(lp))
+ 
+-#define SMC_SET_CONFIG(x)	SMC_outw(x, ioaddr, CONFIG_REG)
++#define SMC_SET_CONFIG(lp, x)	SMC_outw(x, ioaddr, CONFIG_REG(lp))
+ 
+-#define SMC_GET_COUNTER()	SMC_inw(ioaddr, COUNTER_REG)
++#define SMC_GET_COUNTER(lp)	SMC_inw(ioaddr, COUNTER_REG(lp))
+ 
+-#define SMC_GET_CTL()		SMC_inw(ioaddr, CTL_REG)
++#define SMC_GET_CTL(lp)		SMC_inw(ioaddr, CTL_REG(lp))
+ 
+-#define SMC_SET_CTL(x)		SMC_outw(x, ioaddr, CTL_REG)
++#define SMC_SET_CTL(lp, x)		SMC_outw(x, ioaddr, CTL_REG(lp))
+ 
+-#define SMC_GET_MII()		SMC_inw(ioaddr, MII_REG)
++#define SMC_GET_MII(lp)		SMC_inw(ioaddr, MII_REG(lp))
+ 
+-#define SMC_SET_MII(x)		SMC_outw(x, ioaddr, MII_REG)
++#define SMC_SET_MII(lp, x)		SMC_outw(x, ioaddr, MII_REG(lp))
+ 
+-#define SMC_GET_MIR()		SMC_inw(ioaddr, MIR_REG)
++#define SMC_GET_MIR(lp)		SMC_inw(ioaddr, MIR_REG(lp))
+ 
+-#define SMC_SET_MIR(x)		SMC_outw(x, ioaddr, MIR_REG)
++#define SMC_SET_MIR(lp, x)		SMC_outw(x, ioaddr, MIR_REG(lp))
+ 
+-#define SMC_GET_MMU_CMD()	SMC_inw(ioaddr, MMU_CMD_REG)
++#define SMC_GET_MMU_CMD(lp)	SMC_inw(ioaddr, MMU_CMD_REG(lp))
+ 
+-#define SMC_SET_MMU_CMD(x)	SMC_outw(x, ioaddr, MMU_CMD_REG)
++#define SMC_SET_MMU_CMD(lp, x)	SMC_outw(x, ioaddr, MMU_CMD_REG(lp))
+ 
+-#define SMC_GET_FIFO()		SMC_inw(ioaddr, FIFO_REG)
++#define SMC_GET_FIFO(lp)		SMC_inw(ioaddr, FIFO_REG(lp))
+ 
+-#define SMC_GET_PTR()		SMC_inw(ioaddr, PTR_REG)
++#define SMC_GET_PTR(lp)		SMC_inw(ioaddr, PTR_REG(lp))
+ 
+-#define SMC_SET_PTR(x)							\
++#define SMC_SET_PTR(lp, x)						\
+ 	do {								\
+-		if (SMC_MUST_ALIGN_WRITE)				\
+-			SMC_outl((x)<<16, ioaddr, SMC_REG(4, 2));	\
++		if (SMC_MUST_ALIGN_WRITE(lp))				\
++			SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 4, 2));	\
+ 		else							\
+-			SMC_outw(x, ioaddr, PTR_REG);			\
++			SMC_outw(x, ioaddr, PTR_REG(lp));		\
+ 	} while (0)
+ 
+-#define SMC_GET_EPH_STATUS()	SMC_inw(ioaddr, EPH_STATUS_REG)
++#define SMC_GET_EPH_STATUS(lp)	SMC_inw(ioaddr, EPH_STATUS_REG(lp))
+ 
+-#define SMC_GET_RCR()		SMC_inw(ioaddr, RCR_REG)
++#define SMC_GET_RCR(lp)		SMC_inw(ioaddr, RCR_REG(lp))
+ 
+-#define SMC_SET_RCR(x)		SMC_outw(x, ioaddr, RCR_REG)
++#define SMC_SET_RCR(lp, x)		SMC_outw(x, ioaddr, RCR_REG(lp))
+ 
+-#define SMC_GET_REV()		SMC_inw(ioaddr, REV_REG)
++#define SMC_GET_REV(lp)		SMC_inw(ioaddr, REV_REG(lp))
+ 
+-#define SMC_GET_RPC()		SMC_inw(ioaddr, RPC_REG)
++#define SMC_GET_RPC(lp)		SMC_inw(ioaddr, RPC_REG(lp))
+ 
+-#define SMC_SET_RPC(x)							\
++#define SMC_SET_RPC(lp, x)						\
+ 	do {								\
+-		if (SMC_MUST_ALIGN_WRITE)				\
+-			SMC_outl((x)<<16, ioaddr, SMC_REG(8, 0));	\
++		if (SMC_MUST_ALIGN_WRITE(lp))				\
++			SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 0));	\
+ 		else							\
+-			SMC_outw(x, ioaddr, RPC_REG);			\
++			SMC_outw(x, ioaddr, RPC_REG(lp));		\
+ 	} while (0)
+ 
+-#define SMC_GET_TCR()		SMC_inw(ioaddr, TCR_REG)
++#define SMC_GET_TCR(lp)		SMC_inw(ioaddr, TCR_REG(lp))
+ 
+-#define SMC_SET_TCR(x)		SMC_outw(x, ioaddr, TCR_REG)
++#define SMC_SET_TCR(lp, x)		SMC_outw(x, ioaddr, TCR_REG(lp))
+ 
+ #ifndef SMC_GET_MAC_ADDR
+-#define SMC_GET_MAC_ADDR(addr)						\
++#define SMC_GET_MAC_ADDR(lp, addr)					\
+ 	do {								\
+ 		unsigned int __v;					\
+-		__v = SMC_inw( ioaddr, ADDR0_REG );			\
++		__v = SMC_inw(ioaddr, ADDR0_REG(lp));			\
+ 		addr[0] = __v; addr[1] = __v >> 8;			\
+-		__v = SMC_inw( ioaddr, ADDR1_REG );			\
++		__v = SMC_inw(ioaddr, ADDR1_REG(lp));			\
+ 		addr[2] = __v; addr[3] = __v >> 8;			\
+-		__v = SMC_inw( ioaddr, ADDR2_REG );			\
++		__v = SMC_inw(ioaddr, ADDR2_REG(lp));			\
+ 		addr[4] = __v; addr[5] = __v >> 8;			\
+ 	} while (0)
+ #endif
+ 
+-#define SMC_SET_MAC_ADDR(addr)						\
++#define SMC_SET_MAC_ADDR(lp, addr)					\
+ 	do {								\
+-		SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG );	\
+-		SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG );	\
+-		SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG );	\
++		SMC_outw(addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
++		SMC_outw(addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
++		SMC_outw(addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
+ 	} while (0)
+ 
+-#define SMC_SET_MCAST(x)						\
++#define SMC_SET_MCAST(lp, x)						\
+ 	do {								\
+ 		const unsigned char *mt = (x);				\
+-		SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 );	\
+-		SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 );	\
+-		SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 );	\
+-		SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 );	\
++		SMC_outw(mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
++		SMC_outw(mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
++		SMC_outw(mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
++		SMC_outw(mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
+ 	} while (0)
+ 
+-#define SMC_PUT_PKT_HDR(status, length)					\
++#define SMC_PUT_PKT_HDR(lp, status, length)				\
+ 	do {								\
+-		if (SMC_CAN_USE_32BIT)					\
+-			SMC_outl((status) | (length)<<16, ioaddr, DATA_REG); \
++		if (SMC_32BIT(lp))					\
++			SMC_outl((status) | (length)<<16, ioaddr,	\
++				 DATA_REG(lp));			\
+ 		else {							\
+-			SMC_outw(status, ioaddr, DATA_REG);		\
+-			SMC_outw(length, ioaddr, DATA_REG);		\
++			SMC_outw(status, ioaddr, DATA_REG(lp));	\
++			SMC_outw(length, ioaddr, DATA_REG(lp));	\
+ 		}							\
+ 	} while (0)
+ 
+-#define SMC_GET_PKT_HDR(status, length)					\
++#define SMC_GET_PKT_HDR(lp, status, length)				\
+ 	do {								\
+-		if (SMC_CAN_USE_32BIT) {				\
+-			unsigned int __val = SMC_inl(ioaddr, DATA_REG);	\
++		if (SMC_32BIT(lp)) {				\
++			unsigned int __val = SMC_inl(ioaddr, DATA_REG(lp)); \
+ 			(status) = __val & 0xffff;			\
+ 			(length) = __val >> 16;				\
+ 		} else {						\
+-			(status) = SMC_inw(ioaddr, DATA_REG);		\
+-			(length) = SMC_inw(ioaddr, DATA_REG);		\
++			(status) = SMC_inw(ioaddr, DATA_REG(lp));	\
++			(length) = SMC_inw(ioaddr, DATA_REG(lp));	\
+ 		}							\
+ 	} while (0)
+ 
+-#define SMC_PUSH_DATA(p, l)						\
++#define SMC_PUSH_DATA(lp, p, l)					\
+ 	do {								\
+-		if (SMC_CAN_USE_32BIT) {				\
++		if (SMC_32BIT(lp)) {				\
+ 			void *__ptr = (p);				\
+ 			int __len = (l);				\
+ 			void __iomem *__ioaddr = ioaddr;		\
+ 			if (__len >= 2 && (unsigned long)__ptr & 2) {	\
+ 				__len -= 2;				\
+-				SMC_outw(*(u16 *)__ptr, ioaddr, DATA_REG); \
++				SMC_outw(*(u16 *)__ptr, ioaddr,		\
++					DATA_REG(lp));		\
+ 				__ptr += 2;				\
+ 			}						\
+ 			if (SMC_CAN_USE_DATACS && lp->datacs)		\
+ 				__ioaddr = lp->datacs;			\
+-			SMC_outsl(__ioaddr, DATA_REG, __ptr, __len>>2);	\
++			SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
+ 			if (__len & 2) {				\
+ 				__ptr += (__len & ~3);			\
+-				SMC_outw(*((u16 *)__ptr), ioaddr, DATA_REG); \
++				SMC_outw(*((u16 *)__ptr), ioaddr,	\
++					 DATA_REG(lp));		\
+ 			}						\
+-		} else if (SMC_CAN_USE_16BIT)				\
+-			SMC_outsw(ioaddr, DATA_REG, p, (l) >> 1);	\
+-		else if (SMC_CAN_USE_8BIT)				\
+-			SMC_outsb(ioaddr, DATA_REG, p, l);		\
++		} else if (SMC_16BIT(lp))				\
++			SMC_outsw(ioaddr, DATA_REG(lp), p, (l) >> 1);	\
++		else if (SMC_8BIT(lp))				\
++			SMC_outsb(ioaddr, DATA_REG(lp), p, l);	\
+ 	} while (0)
+ 
+-#define SMC_PULL_DATA(p, l)						\
++#define SMC_PULL_DATA(lp, p, l)					\
+ 	do {								\
+-		if (SMC_CAN_USE_32BIT) {				\
++		if (SMC_32BIT(lp)) {				\
+ 			void *__ptr = (p);				\
+ 			int __len = (l);				\
+ 			void __iomem *__ioaddr = ioaddr;		\
+@@ -1333,16 +1321,17 @@ static const char * chip_ids[ 16 ] =  {
+ 				 */					\
+ 				__ptr -= 2;				\
+ 				__len += 2;				\
+-				SMC_SET_PTR(2|PTR_READ|PTR_RCV|PTR_AUTOINC); \
++				SMC_SET_PTR(lp,			\
++					2|PTR_READ|PTR_RCV|PTR_AUTOINC); \
+ 			}						\
+ 			if (SMC_CAN_USE_DATACS && lp->datacs)		\
+ 				__ioaddr = lp->datacs;			\
+ 			__len += 2;					\
+-			SMC_insl(__ioaddr, DATA_REG, __ptr, __len>>2);	\
+-		} else if (SMC_CAN_USE_16BIT)				\
+-			SMC_insw(ioaddr, DATA_REG, p, (l) >> 1);	\
+-		else if (SMC_CAN_USE_8BIT)				\
+-			SMC_insb(ioaddr, DATA_REG, p, l);		\
++			SMC_insl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
++		} else if (SMC_16BIT(lp))				\
++			SMC_insw(ioaddr, DATA_REG(lp), p, (l) >> 1);	\
++		else if (SMC_8BIT(lp))				\
++			SMC_insb(ioaddr, DATA_REG(lp), p, l);		\
+ 	} while (0)
+ 
+ #endif  /* _SMC91X_H_ */
+diff --git a/drivers/net/sni_82596.c b/drivers/net/sni_82596.c
+index 2cf6794..854ccf2 100644
+--- a/drivers/net/sni_82596.c
++++ b/drivers/net/sni_82596.c
+@@ -44,6 +44,7 @@ static const char sni_82596_string[] = "snirm_82596";
+ MODULE_AUTHOR("Thomas Bogendoerfer");
+ MODULE_DESCRIPTION("i82596 driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:snirm_82596");
+ module_param(i596_debug, int, 0);
+ MODULE_PARM_DESC(i596_debug, "82596 debug mask");
+ 
+@@ -166,6 +167,7 @@ static struct platform_driver sni_82596_driver = {
+ 	.remove	= __devexit_p(sni_82596_driver_remove),
+ 	.driver	= {
+ 		.name	= sni_82596_string,
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
+index bccae7e..4776716 100644
+--- a/drivers/net/spider_net.c
++++ b/drivers/net/spider_net.c
+@@ -1399,6 +1399,8 @@ spider_net_link_reset(struct net_device *netdev)
+ 	spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+ 
+ 	/* reset phy and setup aneg */
++	card->aneg_count = 0;
++	card->medium = BCM54XX_COPPER;
+ 	spider_net_setup_aneg(card);
+ 	mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
+ 
+@@ -1413,18 +1415,12 @@ spider_net_link_reset(struct net_device *netdev)
+  * found when an interrupt is presented
+  */
+ static void
+-spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
++spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg,
++			    u32 error_reg1, u32 error_reg2)
+ {
+-	u32 error_reg1, error_reg2;
+ 	u32 i;
+ 	int show_error = 1;
+ 
+-	error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
+-	error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+-
+-	error_reg1 &= SPIDER_NET_INT1_MASK_VALUE;
+-	error_reg2 &= SPIDER_NET_INT2_MASK_VALUE;
+-
+ 	/* check GHIINT0STS ************************************/
+ 	if (status_reg)
+ 		for (i = 0; i < 32; i++)
+@@ -1654,12 +1650,15 @@ spider_net_interrupt(int irq, void *ptr)
+ {
+ 	struct net_device *netdev = ptr;
+ 	struct spider_net_card *card = netdev_priv(netdev);
+-	u32 status_reg;
++	u32 status_reg, error_reg1, error_reg2;
+ 
+ 	status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
+-	status_reg &= SPIDER_NET_INT0_MASK_VALUE;
++	error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
++	error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+ 
+-	if (!status_reg)
++	if (!(status_reg & SPIDER_NET_INT0_MASK_VALUE) &&
++	    !(error_reg1 & SPIDER_NET_INT1_MASK_VALUE) &&
++	    !(error_reg2 & SPIDER_NET_INT2_MASK_VALUE))
+ 		return IRQ_NONE;
+ 
+ 	if (status_reg & SPIDER_NET_RXINT ) {
+@@ -1674,7 +1673,8 @@ spider_net_interrupt(int irq, void *ptr)
+ 		spider_net_link_reset(netdev);
+ 
+ 	if (status_reg & SPIDER_NET_ERRINT )
+-		spider_net_handle_error_irq(card, status_reg);
++		spider_net_handle_error_irq(card, status_reg,
++					    error_reg1, error_reg2);
+ 
+ 	/* clear interrupt sources */
+ 	spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg);
+@@ -1982,6 +1982,8 @@ spider_net_open(struct net_device *netdev)
+ 		goto init_firmware_failed;
+ 
+ 	/* start probing with copper */
++	card->aneg_count = 0;
++	card->medium = BCM54XX_COPPER;
+ 	spider_net_setup_aneg(card);
+ 	if (card->phy.def->phy_id)
+ 		mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
+@@ -2043,7 +2045,8 @@ static void spider_net_link_phy(unsigned long data)
+ 	/* if link didn't come up after SPIDER_NET_ANEG_TIMEOUT tries, setup phy again */
+ 	if (card->aneg_count > SPIDER_NET_ANEG_TIMEOUT) {
+ 
+-		pr_info("%s: link is down trying to bring it up\n", card->netdev->name);
++		pr_debug("%s: link is down trying to bring it up\n",
++			 card->netdev->name);
+ 
+ 		switch (card->medium) {
+ 		case BCM54XX_COPPER:
+@@ -2094,9 +2097,10 @@ static void spider_net_link_phy(unsigned long data)
+ 
+ 	card->aneg_count = 0;
+ 
+-	pr_debug("Found %s with %i Mbps, %s-duplex %sautoneg.\n",
+-		phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half",
+-		phy->autoneg==1 ? "" : "no ");
++	pr_info("%s: link up, %i Mbps, %s-duplex %sautoneg.\n",
++		card->netdev->name, phy->speed,
++		phy->duplex == 1 ? "Full" : "Half",
++		phy->autoneg == 1 ? "" : "no ");
+ 
+ 	return;
+ }
+diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
+index e1d05c0..05f74cb 100644
+--- a/drivers/net/spider_net.h
++++ b/drivers/net/spider_net.h
+@@ -52,7 +52,7 @@ extern char spider_net_driver_name[];
+ 
+ #define SPIDER_NET_TX_TIMER			(HZ/5)
+ #define SPIDER_NET_ANEG_TIMER			(HZ)
+-#define SPIDER_NET_ANEG_TIMEOUT			2
++#define SPIDER_NET_ANEG_TIMEOUT			5
+ 
+ #define SPIDER_NET_RX_CSUM_DEFAULT		1
+ 
+@@ -159,9 +159,8 @@ extern char spider_net_driver_name[];
+ 
+ /** interrupt mask registers */
+ #define SPIDER_NET_INT0_MASK_VALUE	0x3f7fe2c7
+-#define SPIDER_NET_INT1_MASK_VALUE	0xffff7ff7
+-/* no MAC aborts -> auto retransmission */
+-#define SPIDER_NET_INT2_MASK_VALUE	0xffef7ff1
++#define SPIDER_NET_INT1_MASK_VALUE	0x0000fff2
++#define SPIDER_NET_INT2_MASK_VALUE	0x000003f1
+ 
+ /* we rely on flagged descriptor interrupts */
+ #define SPIDER_NET_FRAMENUM_VALUE	0x00000000
+diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
+index 370d329..10e4e85 100644
+--- a/drivers/net/tc35815.c
++++ b/drivers/net/tc35815.c
+@@ -23,9 +23,9 @@
+  */
+ 
+ #ifdef TC35815_NAPI
+-#define DRV_VERSION	"1.36-NAPI"
++#define DRV_VERSION	"1.37-NAPI"
+ #else
+-#define DRV_VERSION	"1.36"
++#define DRV_VERSION	"1.37"
+ #endif
+ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
+ #define MODNAME			"tc35815"
+@@ -47,8 +47,8 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
+ #include <linux/skbuff.h>
+ #include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/mii.h>
+-#include <linux/ethtool.h>
++#include <linux/phy.h>
++#include <linux/workqueue.h>
+ #include <linux/platform_device.h>
+ #include <asm/io.h>
+ #include <asm/byteorder.h>
+@@ -60,16 +60,16 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
+ #define WORKAROUND_100HALF_PROMISC
+ /* #define TC35815_USE_PACKEDBUFFER */
+ 
+-typedef enum {
++enum tc35815_chiptype {
+ 	TC35815CF = 0,
+ 	TC35815_NWU,
+ 	TC35815_TX4939,
+-} board_t;
++};
+ 
+-/* indexed by board_t, above */
++/* indexed by tc35815_chiptype, above */
+ static const struct {
+ 	const char *name;
+-} board_info[] __devinitdata = {
++} chip_info[] __devinitdata = {
+ 	{ "TOSHIBA TC35815CF 10/100BaseTX" },
+ 	{ "TOSHIBA TC35815 with Wake on LAN" },
+ 	{ "TOSHIBA TC35815/TX4939" },
+@@ -81,209 +81,208 @@ static const struct pci_device_id tc35815_pci_tbl[] = {
+ 	{PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939), .driver_data = TC35815_TX4939 },
+ 	{0,}
+ };
+-MODULE_DEVICE_TABLE (pci, tc35815_pci_tbl);
++MODULE_DEVICE_TABLE(pci, tc35815_pci_tbl);
+ 
+ /* see MODULE_PARM_DESC */
+ static struct tc35815_options {
+ 	int speed;
+ 	int duplex;
+-	int doforce;
+ } options;
+ 
+ /*
+  * Registers
+  */
+ struct tc35815_regs {
+-	volatile __u32 DMA_Ctl;		/* 0x00 */
+-	volatile __u32 TxFrmPtr;
+-	volatile __u32 TxThrsh;
+-	volatile __u32 TxPollCtr;
+-	volatile __u32 BLFrmPtr;
+-	volatile __u32 RxFragSize;
+-	volatile __u32 Int_En;
+-	volatile __u32 FDA_Bas;
+-	volatile __u32 FDA_Lim;		/* 0x20 */
+-	volatile __u32 Int_Src;
+-	volatile __u32 unused0[2];
+-	volatile __u32 PauseCnt;
+-	volatile __u32 RemPauCnt;
+-	volatile __u32 TxCtlFrmStat;
+-	volatile __u32 unused1;
+-	volatile __u32 MAC_Ctl;		/* 0x40 */
+-	volatile __u32 CAM_Ctl;
+-	volatile __u32 Tx_Ctl;
+-	volatile __u32 Tx_Stat;
+-	volatile __u32 Rx_Ctl;
+-	volatile __u32 Rx_Stat;
+-	volatile __u32 MD_Data;
+-	volatile __u32 MD_CA;
+-	volatile __u32 CAM_Adr;		/* 0x60 */
+-	volatile __u32 CAM_Data;
+-	volatile __u32 CAM_Ena;
+-	volatile __u32 PROM_Ctl;
+-	volatile __u32 PROM_Data;
+-	volatile __u32 Algn_Cnt;
+-	volatile __u32 CRC_Cnt;
+-	volatile __u32 Miss_Cnt;
++	__u32 DMA_Ctl;		/* 0x00 */
++	__u32 TxFrmPtr;
++	__u32 TxThrsh;
++	__u32 TxPollCtr;
++	__u32 BLFrmPtr;
++	__u32 RxFragSize;
++	__u32 Int_En;
++	__u32 FDA_Bas;
++	__u32 FDA_Lim;		/* 0x20 */
++	__u32 Int_Src;
++	__u32 unused0[2];
++	__u32 PauseCnt;
++	__u32 RemPauCnt;
++	__u32 TxCtlFrmStat;
++	__u32 unused1;
++	__u32 MAC_Ctl;		/* 0x40 */
++	__u32 CAM_Ctl;
++	__u32 Tx_Ctl;
++	__u32 Tx_Stat;
++	__u32 Rx_Ctl;
++	__u32 Rx_Stat;
++	__u32 MD_Data;
++	__u32 MD_CA;
++	__u32 CAM_Adr;		/* 0x60 */
++	__u32 CAM_Data;
++	__u32 CAM_Ena;
++	__u32 PROM_Ctl;
++	__u32 PROM_Data;
++	__u32 Algn_Cnt;
++	__u32 CRC_Cnt;
++	__u32 Miss_Cnt;
+ };
+ 
+ /*
+  * Bit assignments
+  */
+ /* DMA_Ctl bit asign ------------------------------------------------------- */
+-#define DMA_RxAlign            0x00c00000 /* 1:Reception Alignment           */
+-#define DMA_RxAlign_1          0x00400000
+-#define DMA_RxAlign_2          0x00800000
+-#define DMA_RxAlign_3          0x00c00000
+-#define DMA_M66EnStat          0x00080000 /* 1:66MHz Enable State            */
+-#define DMA_IntMask            0x00040000 /* 1:Interupt mask                 */
+-#define DMA_SWIntReq           0x00020000 /* 1:Software Interrupt request    */
+-#define DMA_TxWakeUp           0x00010000 /* 1:Transmit Wake Up              */
+-#define DMA_RxBigE             0x00008000 /* 1:Receive Big Endian            */
+-#define DMA_TxBigE             0x00004000 /* 1:Transmit Big Endian           */
+-#define DMA_TestMode           0x00002000 /* 1:Test Mode                     */
+-#define DMA_PowrMgmnt          0x00001000 /* 1:Power Management              */
+-#define DMA_DmBurst_Mask       0x000001fc /* DMA Burst size                  */
++#define DMA_RxAlign	       0x00c00000 /* 1:Reception Alignment	     */
++#define DMA_RxAlign_1	       0x00400000
++#define DMA_RxAlign_2	       0x00800000
++#define DMA_RxAlign_3	       0x00c00000
++#define DMA_M66EnStat	       0x00080000 /* 1:66MHz Enable State	     */
++#define DMA_IntMask	       0x00040000 /* 1:Interupt mask		     */
++#define DMA_SWIntReq	       0x00020000 /* 1:Software Interrupt request    */
++#define DMA_TxWakeUp	       0x00010000 /* 1:Transmit Wake Up		     */
++#define DMA_RxBigE	       0x00008000 /* 1:Receive Big Endian	     */
++#define DMA_TxBigE	       0x00004000 /* 1:Transmit Big Endian	     */
++#define DMA_TestMode	       0x00002000 /* 1:Test Mode		     */
++#define DMA_PowrMgmnt	       0x00001000 /* 1:Power Management		     */
++#define DMA_DmBurst_Mask       0x000001fc /* DMA Burst size		     */
+ 
+ /* RxFragSize bit asign ---------------------------------------------------- */
+-#define RxFrag_EnPack          0x00008000 /* 1:Enable Packing                */
+-#define RxFrag_MinFragMask     0x00000ffc /* Minimum Fragment                */
++#define RxFrag_EnPack	       0x00008000 /* 1:Enable Packing		     */
++#define RxFrag_MinFragMask     0x00000ffc /* Minimum Fragment		     */
+ 
+ /* MAC_Ctl bit asign ------------------------------------------------------- */
+-#define MAC_Link10             0x00008000 /* 1:Link Status 10Mbits           */
+-#define MAC_EnMissRoll         0x00002000 /* 1:Enable Missed Roll            */
+-#define MAC_MissRoll           0x00000400 /* 1:Missed Roll                   */
+-#define MAC_Loop10             0x00000080 /* 1:Loop 10 Mbps                  */
+-#define MAC_Conn_Auto          0x00000000 /*00:Connection mode (Automatic)   */
+-#define MAC_Conn_10M           0x00000020 /*01:                (10Mbps endec)*/
+-#define MAC_Conn_Mll           0x00000040 /*10:                (Mll clock)   */
+-#define MAC_MacLoop            0x00000010 /* 1:MAC Loopback                  */
+-#define MAC_FullDup            0x00000008 /* 1:Full Duplex 0:Half Duplex     */
+-#define MAC_Reset              0x00000004 /* 1:Software Reset                */
+-#define MAC_HaltImm            0x00000002 /* 1:Halt Immediate                */
+-#define MAC_HaltReq            0x00000001 /* 1:Halt request                  */
++#define MAC_Link10	       0x00008000 /* 1:Link Status 10Mbits	     */
++#define MAC_EnMissRoll	       0x00002000 /* 1:Enable Missed Roll	     */
++#define MAC_MissRoll	       0x00000400 /* 1:Missed Roll		     */
++#define MAC_Loop10	       0x00000080 /* 1:Loop 10 Mbps		     */
++#define MAC_Conn_Auto	       0x00000000 /*00:Connection mode (Automatic)   */
++#define MAC_Conn_10M	       0x00000020 /*01:		       (10Mbps endec)*/
++#define MAC_Conn_Mll	       0x00000040 /*10:		       (Mll clock)   */
++#define MAC_MacLoop	       0x00000010 /* 1:MAC Loopback		     */
++#define MAC_FullDup	       0x00000008 /* 1:Full Duplex 0:Half Duplex     */
++#define MAC_Reset	       0x00000004 /* 1:Software Reset		     */
++#define MAC_HaltImm	       0x00000002 /* 1:Halt Immediate		     */
++#define MAC_HaltReq	       0x00000001 /* 1:Halt request		     */
+ 
+ /* PROM_Ctl bit asign ------------------------------------------------------ */
+-#define PROM_Busy              0x00008000 /* 1:Busy (Start Operation)        */
+-#define PROM_Read              0x00004000 /*10:Read operation                */
+-#define PROM_Write             0x00002000 /*01:Write operation               */
+-#define PROM_Erase             0x00006000 /*11:Erase operation               */
+-                                          /*00:Enable or Disable Writting,   */
+-                                          /*      as specified in PROM_Addr. */
+-#define PROM_Addr_Ena          0x00000030 /*11xxxx:PROM Write enable         */
+-                                          /*00xxxx:           disable        */
++#define PROM_Busy	       0x00008000 /* 1:Busy (Start Operation)	     */
++#define PROM_Read	       0x00004000 /*10:Read operation		     */
++#define PROM_Write	       0x00002000 /*01:Write operation		     */
++#define PROM_Erase	       0x00006000 /*11:Erase operation		     */
++					  /*00:Enable or Disable Writting,   */
++					  /*	  as specified in PROM_Addr. */
++#define PROM_Addr_Ena	       0x00000030 /*11xxxx:PROM Write enable	     */
++					  /*00xxxx:	      disable	     */
+ 
+ /* CAM_Ctl bit asign ------------------------------------------------------- */
+-#define CAM_CompEn             0x00000010 /* 1:CAM Compare Enable            */
+-#define CAM_NegCAM             0x00000008 /* 1:Reject packets CAM recognizes,*/
+-                                          /*                    accept other */
+-#define CAM_BroadAcc           0x00000004 /* 1:Broadcast assept              */
+-#define CAM_GroupAcc           0x00000002 /* 1:Multicast assept              */
+-#define CAM_StationAcc         0x00000001 /* 1:unicast accept                */
++#define CAM_CompEn	       0x00000010 /* 1:CAM Compare Enable	     */
++#define CAM_NegCAM	       0x00000008 /* 1:Reject packets CAM recognizes,*/
++					  /*			accept other */
++#define CAM_BroadAcc	       0x00000004 /* 1:Broadcast assept		     */
++#define CAM_GroupAcc	       0x00000002 /* 1:Multicast assept		     */
++#define CAM_StationAcc	       0x00000001 /* 1:unicast accept		     */
+ 
+ /* CAM_Ena bit asign ------------------------------------------------------- */
+-#define CAM_ENTRY_MAX                  21   /* CAM Data entry max count      */
++#define CAM_ENTRY_MAX		       21   /* CAM Data entry max count	     */
+ #define CAM_Ena_Mask ((1<<CAM_ENTRY_MAX)-1) /* CAM Enable bits (Max 21bits)  */
+-#define CAM_Ena_Bit(index)         (1<<(index))
++#define CAM_Ena_Bit(index)	(1 << (index))
+ #define CAM_ENTRY_DESTINATION	0
+ #define CAM_ENTRY_SOURCE	1
+ #define CAM_ENTRY_MACCTL	20
+ 
+ /* Tx_Ctl bit asign -------------------------------------------------------- */
+-#define Tx_En                  0x00000001 /* 1:Transmit enable               */
+-#define Tx_TxHalt              0x00000002 /* 1:Transmit Halt Request         */
+-#define Tx_NoPad               0x00000004 /* 1:Suppress Padding              */
+-#define Tx_NoCRC               0x00000008 /* 1:Suppress Padding              */
+-#define Tx_FBack               0x00000010 /* 1:Fast Back-off                 */
+-#define Tx_EnUnder             0x00000100 /* 1:Enable Underrun               */
+-#define Tx_EnExDefer           0x00000200 /* 1:Enable Excessive Deferral     */
+-#define Tx_EnLCarr             0x00000400 /* 1:Enable Lost Carrier           */
+-#define Tx_EnExColl            0x00000800 /* 1:Enable Excessive Collision    */
+-#define Tx_EnLateColl          0x00001000 /* 1:Enable Late Collision         */
+-#define Tx_EnTxPar             0x00002000 /* 1:Enable Transmit Parity        */
+-#define Tx_EnComp              0x00004000 /* 1:Enable Completion             */
++#define Tx_En		       0x00000001 /* 1:Transmit enable		     */
++#define Tx_TxHalt	       0x00000002 /* 1:Transmit Halt Request	     */
++#define Tx_NoPad	       0x00000004 /* 1:Suppress Padding		     */
++#define Tx_NoCRC	       0x00000008 /* 1:Suppress Padding		     */
++#define Tx_FBack	       0x00000010 /* 1:Fast Back-off		     */
++#define Tx_EnUnder	       0x00000100 /* 1:Enable Underrun		     */
++#define Tx_EnExDefer	       0x00000200 /* 1:Enable Excessive Deferral     */
++#define Tx_EnLCarr	       0x00000400 /* 1:Enable Lost Carrier	     */
++#define Tx_EnExColl	       0x00000800 /* 1:Enable Excessive Collision    */
++#define Tx_EnLateColl	       0x00001000 /* 1:Enable Late Collision	     */
++#define Tx_EnTxPar	       0x00002000 /* 1:Enable Transmit Parity	     */
++#define Tx_EnComp	       0x00004000 /* 1:Enable Completion	     */
+ 
+ /* Tx_Stat bit asign ------------------------------------------------------- */
+-#define Tx_TxColl_MASK         0x0000000F /* Tx Collision Count              */
+-#define Tx_ExColl              0x00000010 /* Excessive Collision             */
+-#define Tx_TXDefer             0x00000020 /* Transmit Defered                */
+-#define Tx_Paused              0x00000040 /* Transmit Paused                 */
+-#define Tx_IntTx               0x00000080 /* Interrupt on Tx                 */
+-#define Tx_Under               0x00000100 /* Underrun                        */
+-#define Tx_Defer               0x00000200 /* Deferral                        */
+-#define Tx_NCarr               0x00000400 /* No Carrier                      */
+-#define Tx_10Stat              0x00000800 /* 10Mbps Status                   */
+-#define Tx_LateColl            0x00001000 /* Late Collision                  */
+-#define Tx_TxPar               0x00002000 /* Tx Parity Error                 */
+-#define Tx_Comp                0x00004000 /* Completion                      */
+-#define Tx_Halted              0x00008000 /* Tx Halted                       */
+-#define Tx_SQErr               0x00010000 /* Signal Quality Error(SQE)       */
++#define Tx_TxColl_MASK	       0x0000000F /* Tx Collision Count		     */
++#define Tx_ExColl	       0x00000010 /* Excessive Collision	     */
++#define Tx_TXDefer	       0x00000020 /* Transmit Defered		     */
++#define Tx_Paused	       0x00000040 /* Transmit Paused		     */
++#define Tx_IntTx	       0x00000080 /* Interrupt on Tx		     */
++#define Tx_Under	       0x00000100 /* Underrun			     */
++#define Tx_Defer	       0x00000200 /* Deferral			     */
++#define Tx_NCarr	       0x00000400 /* No Carrier			     */
++#define Tx_10Stat	       0x00000800 /* 10Mbps Status		     */
++#define Tx_LateColl	       0x00001000 /* Late Collision		     */
++#define Tx_TxPar	       0x00002000 /* Tx Parity Error		     */
++#define Tx_Comp		       0x00004000 /* Completion			     */
++#define Tx_Halted	       0x00008000 /* Tx Halted			     */
++#define Tx_SQErr	       0x00010000 /* Signal Quality Error(SQE)	     */
+ 
+ /* Rx_Ctl bit asign -------------------------------------------------------- */
+-#define Rx_EnGood              0x00004000 /* 1:Enable Good                   */
+-#define Rx_EnRxPar             0x00002000 /* 1:Enable Receive Parity         */
+-#define Rx_EnLongErr           0x00000800 /* 1:Enable Long Error             */
+-#define Rx_EnOver              0x00000400 /* 1:Enable OverFlow               */
+-#define Rx_EnCRCErr            0x00000200 /* 1:Enable CRC Error              */
+-#define Rx_EnAlign             0x00000100 /* 1:Enable Alignment              */
+-#define Rx_IgnoreCRC           0x00000040 /* 1:Ignore CRC Value              */
+-#define Rx_StripCRC            0x00000010 /* 1:Strip CRC Value               */
+-#define Rx_ShortEn             0x00000008 /* 1:Short Enable                  */
+-#define Rx_LongEn              0x00000004 /* 1:Long Enable                   */
+-#define Rx_RxHalt              0x00000002 /* 1:Receive Halt Request          */
+-#define Rx_RxEn                0x00000001 /* 1:Receive Intrrupt Enable       */
++#define Rx_EnGood	       0x00004000 /* 1:Enable Good		     */
++#define Rx_EnRxPar	       0x00002000 /* 1:Enable Receive Parity	     */
++#define Rx_EnLongErr	       0x00000800 /* 1:Enable Long Error	     */
++#define Rx_EnOver	       0x00000400 /* 1:Enable OverFlow		     */
++#define Rx_EnCRCErr	       0x00000200 /* 1:Enable CRC Error		     */
++#define Rx_EnAlign	       0x00000100 /* 1:Enable Alignment		     */
++#define Rx_IgnoreCRC	       0x00000040 /* 1:Ignore CRC Value		     */
++#define Rx_StripCRC	       0x00000010 /* 1:Strip CRC Value		     */
++#define Rx_ShortEn	       0x00000008 /* 1:Short Enable		     */
++#define Rx_LongEn	       0x00000004 /* 1:Long Enable		     */
++#define Rx_RxHalt	       0x00000002 /* 1:Receive Halt Request	     */
++#define Rx_RxEn		       0x00000001 /* 1:Receive Intrrupt Enable	     */
+ 
+ /* Rx_Stat bit asign ------------------------------------------------------- */
+-#define Rx_Halted              0x00008000 /* Rx Halted                       */
+-#define Rx_Good                0x00004000 /* Rx Good                         */
+-#define Rx_RxPar               0x00002000 /* Rx Parity Error                 */
+-                            /* 0x00001000    not use                         */
+-#define Rx_LongErr             0x00000800 /* Rx Long Error                   */
+-#define Rx_Over                0x00000400 /* Rx Overflow                     */
+-#define Rx_CRCErr              0x00000200 /* Rx CRC Error                    */
+-#define Rx_Align               0x00000100 /* Rx Alignment Error              */
+-#define Rx_10Stat              0x00000080 /* Rx 10Mbps Status                */
+-#define Rx_IntRx               0x00000040 /* Rx Interrupt                    */
+-#define Rx_CtlRecd             0x00000020 /* Rx Control Receive              */
+-
+-#define Rx_Stat_Mask           0x0000EFC0 /* Rx All Status Mask              */
++#define Rx_Halted	       0x00008000 /* Rx Halted			     */
++#define Rx_Good		       0x00004000 /* Rx Good			     */
++#define Rx_RxPar	       0x00002000 /* Rx Parity Error		     */
++			    /* 0x00001000    not use			     */
++#define Rx_LongErr	       0x00000800 /* Rx Long Error		     */
++#define Rx_Over		       0x00000400 /* Rx Overflow		     */
++#define Rx_CRCErr	       0x00000200 /* Rx CRC Error		     */
++#define Rx_Align	       0x00000100 /* Rx Alignment Error		     */
++#define Rx_10Stat	       0x00000080 /* Rx 10Mbps Status		     */
++#define Rx_IntRx	       0x00000040 /* Rx Interrupt		     */
++#define Rx_CtlRecd	       0x00000020 /* Rx Control Receive		     */
++
++#define Rx_Stat_Mask	       0x0000EFC0 /* Rx All Status Mask		     */
+ 
+ /* Int_En bit asign -------------------------------------------------------- */
+-#define Int_NRAbtEn            0x00000800 /* 1:Non-recoverable Abort Enable  */
+-#define Int_TxCtlCmpEn         0x00000400 /* 1:Transmit Control Complete Enable */
+-#define Int_DmParErrEn         0x00000200 /* 1:DMA Parity Error Enable       */
+-#define Int_DParDEn            0x00000100 /* 1:Data Parity Error Enable      */
+-#define Int_EarNotEn           0x00000080 /* 1:Early Notify Enable           */
+-#define Int_DParErrEn          0x00000040 /* 1:Detected Parity Error Enable  */
+-#define Int_SSysErrEn          0x00000020 /* 1:Signalled System Error Enable */
+-#define Int_RMasAbtEn          0x00000010 /* 1:Received Master Abort Enable  */
+-#define Int_RTargAbtEn         0x00000008 /* 1:Received Target Abort Enable  */
+-#define Int_STargAbtEn         0x00000004 /* 1:Signalled Target Abort Enable */
+-#define Int_BLExEn             0x00000002 /* 1:Buffer List Exhausted Enable  */
+-#define Int_FDAExEn            0x00000001 /* 1:Free Descriptor Area          */
+-                                          /*               Exhausted Enable  */
++#define Int_NRAbtEn	       0x00000800 /* 1:Non-recoverable Abort Enable  */
++#define Int_TxCtlCmpEn	       0x00000400 /* 1:Transmit Ctl Complete Enable  */
++#define Int_DmParErrEn	       0x00000200 /* 1:DMA Parity Error Enable	     */
++#define Int_DParDEn	       0x00000100 /* 1:Data Parity Error Enable	     */
++#define Int_EarNotEn	       0x00000080 /* 1:Early Notify Enable	     */
++#define Int_DParErrEn	       0x00000040 /* 1:Detected Parity Error Enable  */
++#define Int_SSysErrEn	       0x00000020 /* 1:Signalled System Error Enable */
++#define Int_RMasAbtEn	       0x00000010 /* 1:Received Master Abort Enable  */
++#define Int_RTargAbtEn	       0x00000008 /* 1:Received Target Abort Enable  */
++#define Int_STargAbtEn	       0x00000004 /* 1:Signalled Target Abort Enable */
++#define Int_BLExEn	       0x00000002 /* 1:Buffer List Exhausted Enable  */
++#define Int_FDAExEn	       0x00000001 /* 1:Free Descriptor Area	     */
++					  /*		   Exhausted Enable  */
+ 
+ /* Int_Src bit asign ------------------------------------------------------- */
+-#define Int_NRabt              0x00004000 /* 1:Non Recoverable error         */
+-#define Int_DmParErrStat       0x00002000 /* 1:DMA Parity Error & Clear      */
+-#define Int_BLEx               0x00001000 /* 1:Buffer List Empty & Clear     */
+-#define Int_FDAEx              0x00000800 /* 1:FDA Empty & Clear             */
+-#define Int_IntNRAbt           0x00000400 /* 1:Non Recoverable Abort         */
+-#define	Int_IntCmp             0x00000200 /* 1:MAC control packet complete   */
+-#define Int_IntExBD            0x00000100 /* 1:Interrupt Extra BD & Clear    */
+-#define Int_DmParErr           0x00000080 /* 1:DMA Parity Error & Clear      */
+-#define Int_IntEarNot          0x00000040 /* 1:Receive Data write & Clear    */
+-#define Int_SWInt              0x00000020 /* 1:Software request & Clear      */
+-#define Int_IntBLEx            0x00000010 /* 1:Buffer List Empty & Clear     */
+-#define Int_IntFDAEx           0x00000008 /* 1:FDA Empty & Clear             */
+-#define Int_IntPCI             0x00000004 /* 1:PCI controller & Clear        */
+-#define Int_IntMacRx           0x00000002 /* 1:Rx controller & Clear         */
+-#define Int_IntMacTx           0x00000001 /* 1:Tx controller & Clear         */
++#define Int_NRabt	       0x00004000 /* 1:Non Recoverable error	     */
++#define Int_DmParErrStat       0x00002000 /* 1:DMA Parity Error & Clear	     */
++#define Int_BLEx	       0x00001000 /* 1:Buffer List Empty & Clear     */
++#define Int_FDAEx	       0x00000800 /* 1:FDA Empty & Clear	     */
++#define Int_IntNRAbt	       0x00000400 /* 1:Non Recoverable Abort	     */
++#define Int_IntCmp	       0x00000200 /* 1:MAC control packet complete   */
++#define Int_IntExBD	       0x00000100 /* 1:Interrupt Extra BD & Clear    */
++#define Int_DmParErr	       0x00000080 /* 1:DMA Parity Error & Clear	     */
++#define Int_IntEarNot	       0x00000040 /* 1:Receive Data write & Clear    */
++#define Int_SWInt	       0x00000020 /* 1:Software request & Clear	     */
++#define Int_IntBLEx	       0x00000010 /* 1:Buffer List Empty & Clear     */
++#define Int_IntFDAEx	       0x00000008 /* 1:FDA Empty & Clear	     */
++#define Int_IntPCI	       0x00000004 /* 1:PCI controller & Clear	     */
++#define Int_IntMacRx	       0x00000002 /* 1:Rx controller & Clear	     */
++#define Int_IntMacTx	       0x00000001 /* 1:Tx controller & Clear	     */
+ 
+ /* MD_CA bit asign --------------------------------------------------------- */
+-#define MD_CA_PreSup           0x00001000 /* 1:Preamble Supress              */
+-#define MD_CA_Busy             0x00000800 /* 1:Busy (Start Operation)        */
+-#define MD_CA_Wr               0x00000400 /* 1:Write 0:Read                  */
++#define MD_CA_PreSup	       0x00001000 /* 1:Preamble Supress		     */
++#define MD_CA_Busy	       0x00000800 /* 1:Busy (Start Operation)	     */
++#define MD_CA_Wr	       0x00000400 /* 1:Write 0:Read		     */
+ 
+ 
+ /*
+@@ -307,24 +306,24 @@ struct BDesc {
+ #define FD_ALIGN	16
+ 
+ /* Frame Descripter bit asign ---------------------------------------------- */
+-#define FD_FDLength_MASK       0x0000FFFF /* Length MASK                     */
+-#define FD_BDCnt_MASK          0x001F0000 /* BD count MASK in FD             */
+-#define FD_FrmOpt_MASK         0x7C000000 /* Frame option MASK               */
++#define FD_FDLength_MASK       0x0000FFFF /* Length MASK		     */
++#define FD_BDCnt_MASK	       0x001F0000 /* BD count MASK in FD	     */
++#define FD_FrmOpt_MASK	       0x7C000000 /* Frame option MASK		     */
+ #define FD_FrmOpt_BigEndian    0x40000000 /* Tx/Rx */
+-#define FD_FrmOpt_IntTx        0x20000000 /* Tx only */
+-#define FD_FrmOpt_NoCRC        0x10000000 /* Tx only */
++#define FD_FrmOpt_IntTx	       0x20000000 /* Tx only */
++#define FD_FrmOpt_NoCRC	       0x10000000 /* Tx only */
+ #define FD_FrmOpt_NoPadding    0x08000000 /* Tx only */
+ #define FD_FrmOpt_Packing      0x04000000 /* Rx only */
+-#define FD_CownsFD             0x80000000 /* FD Controller owner bit         */
+-#define FD_Next_EOL            0x00000001 /* FD EOL indicator                */
+-#define FD_BDCnt_SHIFT         16
++#define FD_CownsFD	       0x80000000 /* FD Controller owner bit	     */
++#define FD_Next_EOL	       0x00000001 /* FD EOL indicator		     */
++#define FD_BDCnt_SHIFT	       16
+ 
+ /* Buffer Descripter bit asign --------------------------------------------- */
+-#define BD_BuffLength_MASK     0x0000FFFF /* Recieve Data Size               */
+-#define BD_RxBDID_MASK         0x00FF0000 /* BD ID Number MASK               */
+-#define BD_RxBDSeqN_MASK       0x7F000000 /* Rx BD Sequence Number           */
+-#define BD_CownsBD             0x80000000 /* BD Controller owner bit         */
+-#define BD_RxBDID_SHIFT        16
++#define BD_BuffLength_MASK     0x0000FFFF /* Recieve Data Size		     */
++#define BD_RxBDID_MASK	       0x00FF0000 /* BD ID Number MASK		     */
++#define BD_RxBDSeqN_MASK       0x7F000000 /* Rx BD Sequence Number	     */
++#define BD_CownsBD	       0x80000000 /* BD Controller owner bit	     */
++#define BD_RxBDID_SHIFT	       16
+ #define BD_RxBDSeqN_SHIFT      24
+ 
+ 
+@@ -348,13 +347,15 @@ struct BDesc {
+ 	Int_STargAbtEn | \
+ 	Int_BLExEn  | Int_FDAExEn) /* maybe 0xb7f*/
+ #define DMA_CTL_CMD	DMA_BURST_SIZE
+-#define HAVE_DMA_RXALIGN(lp)	likely((lp)->boardtype != TC35815CF)
++#define HAVE_DMA_RXALIGN(lp)	likely((lp)->chiptype != TC35815CF)
+ 
+ /* Tuning parameters */
+ #define DMA_BURST_SIZE	32
+ #define TX_THRESHOLD	1024
+-#define TX_THRESHOLD_MAX 1536       /* used threshold with packet max byte for low pci transfer ability.*/
+-#define TX_THRESHOLD_KEEP_LIMIT 10  /* setting threshold max value when overrun error occured this count. */
++/* used threshold with packet max byte for low pci transfer ability.*/
++#define TX_THRESHOLD_MAX 1536
++/* setting threshold max value when overrun error occured this count. */
++#define TX_THRESHOLD_KEEP_LIMIT 10
+ 
+ /* 16 + RX_BUF_NUM * 8 + RX_FD_NUM * 16 + TX_FD_NUM * 32 <= PAGE_SIZE*FD_PAGE_NUM */
+ #ifdef TC35815_USE_PACKEDBUFFER
+@@ -396,21 +397,12 @@ struct FrFD {
+ };
+ 
+ 
+-#define tc_readl(addr)	readl(addr)
+-#define tc_writel(d, addr)	writel(d, addr)
++#define tc_readl(addr)	ioread32(addr)
++#define tc_writel(d, addr)	iowrite32(d, addr)
+ 
+ #define TC35815_TX_TIMEOUT  msecs_to_jiffies(400)
+ 
+-/* Timer state engine. */
+-enum tc35815_timer_state {
+-	arbwait  = 0,	/* Waiting for auto negotiation to complete.          */
+-	lupwait  = 1,	/* Auto-neg complete, awaiting link-up status.        */
+-	ltrywait = 2,	/* Forcing try of all modes, from fastest to slowest. */
+-	asleep   = 3,	/* Time inactive.                                     */
+-	lcheck   = 4,	/* Check link status.                                 */
+-};
+-
+-/* Information that need to be kept for each board. */
++/* Information that need to be kept for each controller. */
+ struct tc35815_local {
+ 	struct pci_dev *pci_dev;
+ 
+@@ -418,12 +410,11 @@ struct tc35815_local {
+ 	struct napi_struct napi;
+ 
+ 	/* statistics */
+-	struct net_device_stats stats;
+ 	struct {
+ 		int max_tx_qlen;
+ 		int tx_ints;
+ 		int rx_ints;
+-	        int tx_underrun;
++		int tx_underrun;
+ 	} lstats;
+ 
+ 	/* Tx control lock.  This protects the transmit buffer ring
+@@ -433,12 +424,12 @@ struct tc35815_local {
+ 	 */
+ 	spinlock_t lock;
+ 
+-	int phy_addr;
+-	int fullduplex;
+-	unsigned short saved_lpa;
+-	struct timer_list timer;
+-	enum tc35815_timer_state timer_state; /* State of auto-neg timer. */
+-	unsigned int timer_ticks;	/* Number of clicks at each state  */
++	struct mii_bus mii_bus;
++	struct phy_device *phy_dev;
++	int duplex;
++	int speed;
++	int link;
++	struct work_struct restart_work;
+ 
+ 	/*
+ 	 * Transmitting: Batch Mode.
+@@ -452,7 +443,7 @@ struct tc35815_local {
+ 	 *	RX_BUF_NUM BD in Free Buffer FD.
+ 	 *	One Free Buffer BD has ETH_FRAME_LEN data buffer.
+ 	 */
+-	void * fd_buf;	/* for TxFD, RxFD, FrFD */
++	void *fd_buf;	/* for TxFD, RxFD, FrFD */
+ 	dma_addr_t fd_buf_dma;
+ 	struct TxFD *tfd_base;
+ 	unsigned int tfd_start;
+@@ -463,7 +454,7 @@ struct tc35815_local {
+ 	struct FrFD *fbl_ptr;
+ #ifdef TC35815_USE_PACKEDBUFFER
+ 	unsigned char fbl_curid;
+-	void * data_buf[RX_BUF_NUM];		/* packing */
++	void *data_buf[RX_BUF_NUM];		/* packing */
+ 	dma_addr_t data_buf_dma[RX_BUF_NUM];
+ 	struct {
+ 		struct sk_buff *skb;
+@@ -476,10 +467,8 @@ struct tc35815_local {
+ 		dma_addr_t skb_dma;
+ 	} tx_skbs[TX_FD_NUM], rx_skbs[RX_BUF_NUM];
+ #endif
+-	struct mii_if_info mii;
+-	unsigned short mii_id[2];
+ 	u32 msg_enable;
+-	board_t boardtype;
++	enum tc35815_chiptype chiptype;
+ };
+ 
+ static inline dma_addr_t fd_virt_to_bus(struct tc35815_local *lp, void *virt)
+@@ -506,13 +495,14 @@ static inline void *rxbuf_bus_to_virt(struct tc35815_local *lp, dma_addr_t bus)
+ }
+ 
+ #define TC35815_DMA_SYNC_ONDEMAND
+-static void* alloc_rxbuf_page(struct pci_dev *hwdev, dma_addr_t *dma_handle)
++static void *alloc_rxbuf_page(struct pci_dev *hwdev, dma_addr_t *dma_handle)
+ {
+ #ifdef TC35815_DMA_SYNC_ONDEMAND
+ 	void *buf;
+ 	/* pci_map + pci_dma_sync will be more effective than
+ 	 * pci_alloc_consistent on some archs. */
+-	if ((buf = (void *)__get_free_page(GFP_ATOMIC)) == NULL)
++	buf = (void *)__get_free_page(GFP_ATOMIC);
++	if (!buf)
+ 		return NULL;
+ 	*dma_handle = pci_map_single(hwdev, buf, PAGE_SIZE,
+ 				     PCI_DMA_FROMDEVICE);
+@@ -577,7 +567,7 @@ static void	tc35815_txdone(struct net_device *dev);
+ static int	tc35815_close(struct net_device *dev);
+ static struct	net_device_stats *tc35815_get_stats(struct net_device *dev);
+ static void	tc35815_set_multicast_list(struct net_device *dev);
+-static void     tc35815_tx_timeout(struct net_device *dev);
++static void	tc35815_tx_timeout(struct net_device *dev);
+ static int	tc35815_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void	tc35815_poll_controller(struct net_device *dev);
+@@ -585,21 +575,225 @@ static void	tc35815_poll_controller(struct net_device *dev);
+ static const struct ethtool_ops tc35815_ethtool_ops;
+ 
+ /* Example routines you must write ;->. */
+-static void 	tc35815_chip_reset(struct net_device *dev);
+-static void 	tc35815_chip_init(struct net_device *dev);
+-static void	tc35815_find_phy(struct net_device *dev);
+-static void 	tc35815_phy_chip_init(struct net_device *dev);
++static void	tc35815_chip_reset(struct net_device *dev);
++static void	tc35815_chip_init(struct net_device *dev);
+ 
+ #ifdef DEBUG
+ static void	panic_queues(struct net_device *dev);
+ #endif
+ 
+-static void tc35815_timer(unsigned long data);
+-static void tc35815_start_auto_negotiation(struct net_device *dev,
+-					   struct ethtool_cmd *ep);
+-static int tc_mdio_read(struct net_device *dev, int phy_id, int location);
+-static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
+-			  int val);
++static void tc35815_restart_work(struct work_struct *work);
++
++static int tc_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
++{
++	struct net_device *dev = bus->priv;
++	struct tc35815_regs __iomem *tr =
++		(struct tc35815_regs __iomem *)dev->base_addr;
++	unsigned long timeout = jiffies + 10;
++
++	tc_writel(MD_CA_Busy | (mii_id << 5) | (regnum & 0x1f), &tr->MD_CA);
++	while (tc_readl(&tr->MD_CA) & MD_CA_Busy) {
++		if (time_after(jiffies, timeout))
++			return -EIO;
++		cpu_relax();
++	}
++	return tc_readl(&tr->MD_Data) & 0xffff;
++}
++
++static int tc_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 val)
++{
++	struct net_device *dev = bus->priv;
++	struct tc35815_regs __iomem *tr =
++		(struct tc35815_regs __iomem *)dev->base_addr;
++	unsigned long timeout = jiffies + 10;
++
++	tc_writel(val, &tr->MD_Data);
++	tc_writel(MD_CA_Busy | MD_CA_Wr | (mii_id << 5) | (regnum & 0x1f),
++		  &tr->MD_CA);
++	while (tc_readl(&tr->MD_CA) & MD_CA_Busy) {
++		if (time_after(jiffies, timeout))
++			return -EIO;
++		cpu_relax();
++	}
++	return 0;
++}
++
++static void tc_handle_link_change(struct net_device *dev)
++{
++	struct tc35815_local *lp = netdev_priv(dev);
++	struct phy_device *phydev = lp->phy_dev;
++	unsigned long flags;
++	int status_change = 0;
++
++	spin_lock_irqsave(&lp->lock, flags);
++	if (phydev->link &&
++	    (lp->speed != phydev->speed || lp->duplex != phydev->duplex)) {
++		struct tc35815_regs __iomem *tr =
++			(struct tc35815_regs __iomem *)dev->base_addr;
++		u32 reg;
++
++		reg = tc_readl(&tr->MAC_Ctl);
++		reg |= MAC_HaltReq;
++		tc_writel(reg, &tr->MAC_Ctl);
++		if (phydev->duplex == DUPLEX_FULL)
++			reg |= MAC_FullDup;
++		else
++			reg &= ~MAC_FullDup;
++		tc_writel(reg, &tr->MAC_Ctl);
++		reg &= ~MAC_HaltReq;
++		tc_writel(reg, &tr->MAC_Ctl);
++
++		/*
++		 * TX4939 PCFG.SPEEDn bit will be changed on
++		 * NETDEV_CHANGE event.
++		 */
++
++#if !defined(NO_CHECK_CARRIER) && defined(WORKAROUND_LOSTCAR)
++		/*
++		 * WORKAROUND: enable LostCrS only if half duplex
++		 * operation.
++		 * (TX4939 does not have EnLCarr)
++		 */
++		if (phydev->duplex == DUPLEX_HALF &&
++		    lp->chiptype != TC35815_TX4939)
++			tc_writel(tc_readl(&tr->Tx_Ctl) | Tx_EnLCarr,
++				  &tr->Tx_Ctl);
++#endif
++
++		lp->speed = phydev->speed;
++		lp->duplex = phydev->duplex;
++		status_change = 1;
++	}
++
++	if (phydev->link != lp->link) {
++		if (phydev->link) {
++#ifdef WORKAROUND_100HALF_PROMISC
++			/* delayed promiscuous enabling */
++			if (dev->flags & IFF_PROMISC)
++				tc35815_set_multicast_list(dev);
++#endif
++			netif_schedule(dev);
++		} else {
++			lp->speed = 0;
++			lp->duplex = -1;
++		}
++		lp->link = phydev->link;
++
++		status_change = 1;
++	}
++	spin_unlock_irqrestore(&lp->lock, flags);
++
++	if (status_change && netif_msg_link(lp)) {
++		phy_print_status(phydev);
++#ifdef DEBUG
++		printk(KERN_DEBUG
++		       "%s: MII BMCR %04x BMSR %04x LPA %04x\n",
++		       dev->name,
++		       phy_read(phydev, MII_BMCR),
++		       phy_read(phydev, MII_BMSR),
++		       phy_read(phydev, MII_LPA));
++#endif
++	}
++}
++
++static int tc_mii_probe(struct net_device *dev)
++{
++	struct tc35815_local *lp = netdev_priv(dev);
++	struct phy_device *phydev = NULL;
++	int phy_addr;
++	u32 dropmask;
++
++	/* find the first phy */
++	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
++		if (lp->mii_bus.phy_map[phy_addr]) {
++			if (phydev) {
++				printk(KERN_ERR "%s: multiple PHYs found\n",
++				       dev->name);
++				return -EINVAL;
++			}
++			phydev = lp->mii_bus.phy_map[phy_addr];
++			break;
++		}
++	}
++
++	if (!phydev) {
++		printk(KERN_ERR "%s: no PHY found\n", dev->name);
++		return -ENODEV;
++	}
++
++	/* attach the mac to the phy */
++	phydev = phy_connect(dev, phydev->dev.bus_id,
++			     &tc_handle_link_change, 0,
++			     lp->chiptype == TC35815_TX4939 ?
++			     PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII);
++	if (IS_ERR(phydev)) {
++		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
++		return PTR_ERR(phydev);
++	}
++	printk(KERN_INFO "%s: attached PHY driver [%s] "
++		"(mii_bus:phy_addr=%s, id=%x)\n",
++		dev->name, phydev->drv->name, phydev->dev.bus_id,
++		phydev->phy_id);
++
++	/* mask with MAC supported features */
++	phydev->supported &= PHY_BASIC_FEATURES;
++	dropmask = 0;
++	if (options.speed == 10)
++		dropmask |= SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
++	else if (options.speed == 100)
++		dropmask |= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full;
++	if (options.duplex == 1)
++		dropmask |= SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full;
++	else if (options.duplex == 2)
++		dropmask |= SUPPORTED_10baseT_Half | SUPPORTED_100baseT_Half;
++	phydev->supported &= ~dropmask;
++	phydev->advertising = phydev->supported;
++
++	lp->link = 0;
++	lp->speed = 0;
++	lp->duplex = -1;
++	lp->phy_dev = phydev;
++
++	return 0;
++}
++
++static int tc_mii_init(struct net_device *dev)
++{
++	struct tc35815_local *lp = netdev_priv(dev);
++	int err;
++	int i;
++
++	lp->mii_bus.name = "tc35815_mii_bus";
++	lp->mii_bus.read = tc_mdio_read;
++	lp->mii_bus.write = tc_mdio_write;
++	snprintf(lp->mii_bus.id, MII_BUS_ID_SIZE, "%x",
++		 (lp->pci_dev->bus->number << 8) | lp->pci_dev->devfn);
++	lp->mii_bus.priv = dev;
++	lp->mii_bus.dev = &lp->pci_dev->dev;
++	lp->mii_bus.irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
++	if (!lp->mii_bus.irq) {
++		err = -ENOMEM;
++		goto err_out;
++	}
++
++	for (i = 0; i < PHY_MAX_ADDR; i++)
++		lp->mii_bus.irq[i] = PHY_POLL;
++
++	err = mdiobus_register(&lp->mii_bus);
++	if (err)
++		goto err_out_free_mdio_irq;
++	err = tc_mii_probe(dev);
++	if (err)
++		goto err_out_unregister_bus;
++	return 0;
++
++err_out_unregister_bus:
++	mdiobus_unregister(&lp->mii_bus);
++err_out_free_mdio_irq:
++	kfree(lp->mii_bus.irq);
++err_out:
++	return err;
++}
+ 
+ #ifdef CONFIG_CPU_TX49XX
+ /*
+@@ -617,7 +811,7 @@ static int __devinit tc35815_mac_match(struct device *dev, void *data)
+ 
+ static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	struct device *pd = bus_find_device(&platform_bus_type, NULL,
+ 					    lp->pci_dev, tc35815_mac_match);
+ 	if (pd) {
+@@ -635,7 +829,7 @@ static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+ }
+ #endif
+ 
+-static int __devinit tc35815_init_dev_addr (struct net_device *dev)
++static int __devinit tc35815_init_dev_addr(struct net_device *dev)
+ {
+ 	struct tc35815_regs __iomem *tr =
+ 		(struct tc35815_regs __iomem *)dev->base_addr;
+@@ -657,21 +851,21 @@ static int __devinit tc35815_init_dev_addr (struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static int __devinit tc35815_init_one (struct pci_dev *pdev,
+-				       const struct pci_device_id *ent)
++static int __devinit tc35815_init_one(struct pci_dev *pdev,
++				      const struct pci_device_id *ent)
+ {
+ 	void __iomem *ioaddr = NULL;
+ 	struct net_device *dev;
+ 	struct tc35815_local *lp;
+ 	int rc;
+-	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
++	DECLARE_MAC_BUF(mac);
+ 
+ 	static int printed_version;
+ 	if (!printed_version++) {
+ 		printk(version);
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+-			   "speed:%d duplex:%d doforce:%d\n",
+-			   options.speed, options.duplex, options.doforce);
++			   "speed:%d duplex:%d\n",
++			   options.speed, options.duplex);
+ 	}
+ 
+ 	if (!pdev->irq) {
+@@ -680,55 +874,24 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
+ 	}
+ 
+ 	/* dev zeroed in alloc_etherdev */
+-	dev = alloc_etherdev (sizeof (*lp));
++	dev = alloc_etherdev(sizeof(*lp));
+ 	if (dev == NULL) {
+ 		dev_err(&pdev->dev, "unable to alloc new ethernet\n");
+ 		return -ENOMEM;
+ 	}
+ 	SET_NETDEV_DEV(dev, &pdev->dev);
+-	lp = dev->priv;
++	lp = netdev_priv(dev);
+ 	lp->dev = dev;
+ 
+ 	/* enable device (incl. PCI PM wakeup), and bus-mastering */
+-	rc = pci_enable_device (pdev);
++	rc = pcim_enable_device(pdev);
+ 	if (rc)
+ 		goto err_out;
+-
+-	mmio_start = pci_resource_start (pdev, 1);
+-	mmio_end = pci_resource_end (pdev, 1);
+-	mmio_flags = pci_resource_flags (pdev, 1);
+-	mmio_len = pci_resource_len (pdev, 1);
+-
+-	/* set this immediately, we need to know before
+-	 * we talk to the chip directly */
+-
+-	/* make sure PCI base addr 1 is MMIO */
+-	if (!(mmio_flags & IORESOURCE_MEM)) {
+-		dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
+-		rc = -ENODEV;
+-		goto err_out;
+-	}
+-
+-	/* check for weird/broken PCI region reporting */
+-	if ((mmio_len < sizeof(struct tc35815_regs))) {
+-		dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n");
+-		rc = -ENODEV;
+-		goto err_out;
+-	}
+-
+-	rc = pci_request_regions (pdev, MODNAME);
++	rc = pcim_iomap_regions(pdev, 1 << 1, MODNAME);
+ 	if (rc)
+ 		goto err_out;
+-
+-	pci_set_master (pdev);
+-
+-	/* ioremap MMIO region */
+-	ioaddr = ioremap (mmio_start, mmio_len);
+-	if (ioaddr == NULL) {
+-		dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
+-		rc = -EIO;
+-		goto err_out_free_res;
+-	}
++	pci_set_master(pdev);
++	ioaddr = pcim_iomap_table(pdev)[1];
+ 
+ 	/* Initialize the device structure. */
+ 	dev->open = tc35815_open;
+@@ -748,11 +911,12 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
+ #endif
+ 
+ 	dev->irq = pdev->irq;
+-	dev->base_addr = (unsigned long) ioaddr;
++	dev->base_addr = (unsigned long)ioaddr;
+ 
++	INIT_WORK(&lp->restart_work, tc35815_restart_work);
+ 	spin_lock_init(&lp->lock);
+ 	lp->pci_dev = pdev;
+-	lp->boardtype = ent->driver_data;
++	lp->chiptype = ent->driver_data;
+ 
+ 	lp->msg_enable = NETIF_MSG_TX_ERR | NETIF_MSG_HW | NETIF_MSG_DRV | NETIF_MSG_LINK;
+ 	pci_set_drvdata(pdev, dev);
+@@ -766,68 +930,49 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
+ 		random_ether_addr(dev->dev_addr);
+ 	}
+ 
+-	rc = register_netdev (dev);
++	rc = register_netdev(dev);
+ 	if (rc)
+-		goto err_out_unmap;
++		goto err_out;
+ 
+ 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+-	printk(KERN_INFO "%s: %s at 0x%lx, "
+-		"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
+-		"IRQ %d\n",
++	printk(KERN_INFO "%s: %s at 0x%lx, %s, IRQ %d\n",
+ 		dev->name,
+-		board_info[ent->driver_data].name,
++		chip_info[ent->driver_data].name,
+ 		dev->base_addr,
+-		dev->dev_addr[0], dev->dev_addr[1],
+-		dev->dev_addr[2], dev->dev_addr[3],
+-		dev->dev_addr[4], dev->dev_addr[5],
++		print_mac(mac, dev->dev_addr),
+ 		dev->irq);
+ 
+-	setup_timer(&lp->timer, tc35815_timer, (unsigned long) dev);
+-	lp->mii.dev = dev;
+-	lp->mii.mdio_read = tc_mdio_read;
+-	lp->mii.mdio_write = tc_mdio_write;
+-	lp->mii.phy_id_mask = 0x1f;
+-	lp->mii.reg_num_mask = 0x1f;
+-	tc35815_find_phy(dev);
+-	lp->mii.phy_id = lp->phy_addr;
+-	lp->mii.full_duplex = 0;
+-	lp->mii.force_media = 0;
++	rc = tc_mii_init(dev);
++	if (rc)
++		goto err_out_unregister;
+ 
+ 	return 0;
+ 
+-err_out_unmap:
+-	iounmap(ioaddr);
+-err_out_free_res:
+-	pci_release_regions (pdev);
++err_out_unregister:
++	unregister_netdev(dev);
+ err_out:
+-	free_netdev (dev);
++	free_netdev(dev);
+ 	return rc;
+ }
+ 
+ 
+-static void __devexit tc35815_remove_one (struct pci_dev *pdev)
++static void __devexit tc35815_remove_one(struct pci_dev *pdev)
+ {
+-	struct net_device *dev = pci_get_drvdata (pdev);
+-	unsigned long mmio_addr;
+-
+-	mmio_addr = dev->base_addr;
+-
+-	unregister_netdev (dev);
+-
+-	if (mmio_addr) {
+-		iounmap ((void __iomem *)mmio_addr);
+-		pci_release_regions (pdev);
+-	}
+-
+-	free_netdev (dev);
++	struct net_device *dev = pci_get_drvdata(pdev);
++	struct tc35815_local *lp = netdev_priv(dev);
+ 
+-	pci_set_drvdata (pdev, NULL);
++	phy_disconnect(lp->phy_dev);
++	mdiobus_unregister(&lp->mii_bus);
++	kfree(lp->mii_bus.irq);
++	unregister_netdev(dev);
++	free_netdev(dev);
++	pci_set_drvdata(pdev, NULL);
+ }
+ 
+ static int
+ tc35815_init_queues(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	int i;
+ 	unsigned long fd_addr;
+ 
+@@ -838,11 +983,17 @@ tc35815_init_queues(struct net_device *dev)
+ 		       sizeof(struct TxFD) * TX_FD_NUM >
+ 		       PAGE_SIZE * FD_PAGE_NUM);
+ 
+-		if ((lp->fd_buf = pci_alloc_consistent(lp->pci_dev, PAGE_SIZE * FD_PAGE_NUM, &lp->fd_buf_dma)) == 0)
++		lp->fd_buf = pci_alloc_consistent(lp->pci_dev,
++						  PAGE_SIZE * FD_PAGE_NUM,
++						  &lp->fd_buf_dma);
++		if (!lp->fd_buf)
+ 			return -ENOMEM;
+ 		for (i = 0; i < RX_BUF_NUM; i++) {
+ #ifdef TC35815_USE_PACKEDBUFFER
+-			if ((lp->data_buf[i] = alloc_rxbuf_page(lp->pci_dev, &lp->data_buf_dma[i])) == NULL) {
++			lp->data_buf[i] =
++				alloc_rxbuf_page(lp->pci_dev,
++						 &lp->data_buf_dma[i]);
++			if (!lp->data_buf[i]) {
+ 				while (--i >= 0) {
+ 					free_rxbuf_page(lp->pci_dev,
+ 							lp->data_buf[i],
+@@ -885,18 +1036,17 @@ tc35815_init_queues(struct net_device *dev)
+ #endif
+ 		printk("\n");
+ 	} else {
+-		for (i = 0; i < FD_PAGE_NUM; i++) {
+-			clear_page((void *)((unsigned long)lp->fd_buf + i * PAGE_SIZE));
+-		}
++		for (i = 0; i < FD_PAGE_NUM; i++)
++			clear_page((void *)((unsigned long)lp->fd_buf +
++					    i * PAGE_SIZE));
+ 	}
+ 	fd_addr = (unsigned long)lp->fd_buf;
+ 
+ 	/* Free Descriptors (for Receive) */
+ 	lp->rfd_base = (struct RxFD *)fd_addr;
+ 	fd_addr += sizeof(struct RxFD) * RX_FD_NUM;
+-	for (i = 0; i < RX_FD_NUM; i++) {
++	for (i = 0; i < RX_FD_NUM; i++)
+ 		lp->rfd_base[i].fd.FDCtl = cpu_to_le32(FD_CownsFD);
+-	}
+ 	lp->rfd_cur = lp->rfd_base;
+ 	lp->rfd_limit = (struct RxFD *)fd_addr - (RX_FD_RESERVE + 1);
+ 
+@@ -964,7 +1114,7 @@ tc35815_init_queues(struct net_device *dev)
+ static void
+ tc35815_clear_queues(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	int i;
+ 
+ 	for (i = 0; i < TX_FD_NUM; i++) {
+@@ -995,7 +1145,7 @@ tc35815_clear_queues(struct net_device *dev)
+ static void
+ tc35815_free_queues(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	int i;
+ 
+ 	if (lp->tfd_base) {
+@@ -1076,7 +1226,7 @@ dump_rxfd(struct RxFD *fd)
+ 	       le32_to_cpu(fd->fd.FDStat),
+ 	       le32_to_cpu(fd->fd.FDCtl));
+ 	if (le32_to_cpu(fd->fd.FDCtl) & FD_CownsFD)
+-	    return 0;
++		return 0;
+ 	printk("BD: ");
+ 	for (i = 0; i < bd_count; i++)
+ 		printk(" %08x %08x",
+@@ -1109,7 +1259,7 @@ dump_frfd(struct FrFD *fd)
+ static void
+ panic_queues(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	int i;
+ 
+ 	printk("TxFD base %p, start %u, end %u\n",
+@@ -1128,42 +1278,33 @@ panic_queues(struct net_device *dev)
+ }
+ #endif
+ 
+-static void print_eth(char *add)
++static void print_eth(const u8 *add)
+ {
+-	int i;
++	DECLARE_MAC_BUF(mac);
+ 
+-	printk("print_eth(%p)\n", add);
+-	for (i = 0; i < 6; i++)
+-		printk(" %2.2X", (unsigned char) add[i + 6]);
+-	printk(" =>");
+-	for (i = 0; i < 6; i++)
+-		printk(" %2.2X", (unsigned char) add[i]);
+-	printk(" : %2.2X%2.2X\n", (unsigned char) add[12], (unsigned char) add[13]);
++	printk(KERN_DEBUG "print_eth(%p)\n", add);
++	printk(KERN_DEBUG " %s =>", print_mac(mac, add + 6));
++	printk(KERN_CONT " %s : %02x%02x\n",
++		print_mac(mac, add), add[12], add[13]);
+ }
+ 
+ static int tc35815_tx_full(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	return ((lp->tfd_start + 1) % TX_FD_NUM == lp->tfd_end);
+ }
+ 
+ static void tc35815_restart(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
+-	int pid = lp->phy_addr;
+-	int do_phy_reset = 1;
+-	del_timer(&lp->timer);		/* Kill if running	*/
+-
+-	if (lp->mii_id[0] == 0x0016 && (lp->mii_id[1] & 0xfc00) == 0xf800) {
+-		/* Resetting PHY cause problem on some chip... (SEEQ 80221) */
+-		do_phy_reset = 0;
+-	}
+-	if (do_phy_reset) {
++	struct tc35815_local *lp = netdev_priv(dev);
++
++	if (lp->phy_dev) {
+ 		int timeout;
+-		tc_mdio_write(dev, pid, MII_BMCR, BMCR_RESET);
++
++		phy_write(lp->phy_dev, MII_BMCR, BMCR_RESET);
+ 		timeout = 100;
+ 		while (--timeout) {
+-			if (!(tc_mdio_read(dev, pid, MII_BMCR) & BMCR_RESET))
++			if (!(phy_read(lp->phy_dev, MII_BMCR) & BMCR_RESET))
+ 				break;
+ 			udelay(1);
+ 		}
+@@ -1171,16 +1312,40 @@ static void tc35815_restart(struct net_device *dev)
+ 			printk(KERN_ERR "%s: BMCR reset failed.\n", dev->name);
+ 	}
+ 
++	spin_lock_irq(&lp->lock);
+ 	tc35815_chip_reset(dev);
+ 	tc35815_clear_queues(dev);
+ 	tc35815_chip_init(dev);
+ 	/* Reconfigure CAM again since tc35815_chip_init() initialize it. */
+ 	tc35815_set_multicast_list(dev);
++	spin_unlock_irq(&lp->lock);
++
++	netif_wake_queue(dev);
++}
++
++static void tc35815_restart_work(struct work_struct *work)
++{
++	struct tc35815_local *lp =
++		container_of(work, struct tc35815_local, restart_work);
++	struct net_device *dev = lp->dev;
++
++	tc35815_restart(dev);
++}
++
++static void tc35815_schedule_restart(struct net_device *dev)
++{
++	struct tc35815_local *lp = netdev_priv(dev);
++	struct tc35815_regs __iomem *tr =
++		(struct tc35815_regs __iomem *)dev->base_addr;
++
++	/* disable interrupts */
++	tc_writel(0, &tr->Int_En);
++	tc_writel(tc_readl(&tr->DMA_Ctl) | DMA_IntMask, &tr->DMA_Ctl);
++	schedule_work(&lp->restart_work);
+ }
+ 
+ static void tc35815_tx_timeout(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
+ 	struct tc35815_regs __iomem *tr =
+ 		(struct tc35815_regs __iomem *)dev->base_addr;
+ 
+@@ -1188,28 +1353,12 @@ static void tc35815_tx_timeout(struct net_device *dev)
+ 	       dev->name, tc_readl(&tr->Tx_Stat));
+ 
+ 	/* Try to restart the adaptor. */
+-	spin_lock_irq(&lp->lock);
+-	tc35815_restart(dev);
+-	spin_unlock_irq(&lp->lock);
+-
+-	lp->stats.tx_errors++;
+-
+-	/* If we have space available to accept new transmit
+-	 * requests, wake up the queueing layer.  This would
+-	 * be the case if the chipset_init() call above just
+-	 * flushes out the tx queue and empties it.
+-	 *
+-	 * If instead, the tx queue is retained then the
+-	 * netif_wake_queue() call should be placed in the
+-	 * TX completion interrupt handler of the driver instead
+-	 * of here.
+-	 */
+-	if (!tc35815_tx_full(dev))
+-		netif_wake_queue(dev);
++	tc35815_schedule_restart(dev);
++	dev->stats.tx_errors++;
+ }
+ 
+ /*
+- * Open/initialize the board. This is called (in the current kernel)
++ * Open/initialize the controller. This is called (in the current kernel)
+  * sometime after booting when the 'ifconfig' program is run.
+  *
+  * This routine should set everything up anew at each open, even
+@@ -1219,17 +1368,16 @@ static void tc35815_tx_timeout(struct net_device *dev)
+ static int
+ tc35815_open(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 
+ 	/*
+ 	 * This is used if the interrupt line can turned off (shared).
+ 	 * See 3c503.c for an example of selecting the IRQ at config-time.
+ 	 */
+-	if (request_irq(dev->irq, &tc35815_interrupt, IRQF_SHARED, dev->name, dev)) {
++	if (request_irq(dev->irq, &tc35815_interrupt, IRQF_SHARED,
++			dev->name, dev))
+ 		return -EAGAIN;
+-	}
+ 
+-	del_timer(&lp->timer);		/* Kill if running	*/
+ 	tc35815_chip_reset(dev);
+ 
+ 	if (tc35815_init_queues(dev) != 0) {
+@@ -1246,6 +1394,9 @@ tc35815_open(struct net_device *dev)
+ 	tc35815_chip_init(dev);
+ 	spin_unlock_irq(&lp->lock);
+ 
++	/* schedule a link state check */
++	phy_start(lp->phy_dev);
++
+ 	/* We are now ready to accept transmit requeusts from
+ 	 * the queueing layer of the networking.
+ 	 */
+@@ -1261,7 +1412,7 @@ tc35815_open(struct net_device *dev)
+  */
+ static int tc35815_send_packet(struct sk_buff *skb, struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	struct TxFD *txfd;
+ 	unsigned long flags;
+ 
+@@ -1366,7 +1517,7 @@ static void tc35815_fatal_error_interrupt(struct net_device *dev, u32 status)
+ 		panic("%s: Too many fatal errors.", dev->name);
+ 	printk(KERN_WARNING "%s: Resetting ...\n", dev->name);
+ 	/* Try to restart the adaptor. */
+-	tc35815_restart(dev);
++	tc35815_schedule_restart(dev);
+ }
+ 
+ #ifdef TC35815_NAPI
+@@ -1375,7 +1526,7 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status, int limit)
+ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
+ #endif
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	struct tc35815_regs __iomem *tr =
+ 		(struct tc35815_regs __iomem *)dev->base_addr;
+ 	int ret = -1;
+@@ -1392,7 +1543,7 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
+ 		printk(KERN_WARNING
+ 		       "%s: Free Descriptor Area Exhausted (%#x).\n",
+ 		       dev->name, status);
+-		lp->stats.rx_dropped++;
++		dev->stats.rx_dropped++;
+ 		ret = 0;
+ 	}
+ 	if (status & Int_IntBLEx) {
+@@ -1401,14 +1552,14 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
+ 		printk(KERN_WARNING
+ 		       "%s: Buffer List Exhausted (%#x).\n",
+ 		       dev->name, status);
+-		lp->stats.rx_dropped++;
++		dev->stats.rx_dropped++;
+ 		ret = 0;
+ 	}
+ 	if (status & Int_IntExBD) {
+ 		printk(KERN_WARNING
+ 		       "%s: Excessive Buffer Descriptiors (%#x).\n",
+ 		       dev->name, status);
+-		lp->stats.rx_length_errors++;
++		dev->stats.rx_length_errors++;
+ 		ret = 0;
+ 	}
+ 
+@@ -1492,7 +1643,7 @@ static void
+ tc35815_rx(struct net_device *dev)
+ #endif
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	unsigned int fdctl;
+ 	int i;
+ 	int buf_free_count = 0;
+@@ -1532,7 +1683,7 @@ tc35815_rx(struct net_device *dev)
+ 			if (skb == NULL) {
+ 				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
+ 				       dev->name);
+-				lp->stats.rx_dropped++;
++				dev->stats.rx_dropped++;
+ 				break;
+ 			}
+ 			skb_reserve(skb, 2);   /* 16 bit alignment */
+@@ -1602,10 +1753,10 @@ tc35815_rx(struct net_device *dev)
+ 			netif_rx(skb);
+ #endif
+ 			dev->last_rx = jiffies;
+-			lp->stats.rx_packets++;
+-			lp->stats.rx_bytes += pkt_len;
++			dev->stats.rx_packets++;
++			dev->stats.rx_bytes += pkt_len;
+ 		} else {
+-			lp->stats.rx_errors++;
++			dev->stats.rx_errors++;
+ 			printk(KERN_DEBUG "%s: Rx error (status %x)\n",
+ 			       dev->name, status & Rx_Stat_Mask);
+ 			/* WORKAROUND: LongErr and CRCErr means Overflow. */
+@@ -1613,10 +1764,14 @@ tc35815_rx(struct net_device *dev)
+ 				status &= ~(Rx_LongErr|Rx_CRCErr);
+ 				status |= Rx_Over;
+ 			}
+-			if (status & Rx_LongErr) lp->stats.rx_length_errors++;
+-			if (status & Rx_Over) lp->stats.rx_fifo_errors++;
+-			if (status & Rx_CRCErr) lp->stats.rx_crc_errors++;
+-			if (status & Rx_Align) lp->stats.rx_frame_errors++;
++			if (status & Rx_LongErr)
++				dev->stats.rx_length_errors++;
++			if (status & Rx_Over)
++				dev->stats.rx_fifo_errors++;
++			if (status & Rx_CRCErr)
++				dev->stats.rx_crc_errors++;
++			if (status & Rx_Align)
++				dev->stats.rx_frame_errors++;
+ 		}
+ 
+ 		if (bd_count > 0) {
+@@ -1772,40 +1927,39 @@ static int tc35815_poll(struct napi_struct *napi, int budget)
+ static void
+ tc35815_check_tx_stat(struct net_device *dev, int status)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	const char *msg = NULL;
+ 
+ 	/* count collisions */
+ 	if (status & Tx_ExColl)
+-		lp->stats.collisions += 16;
++		dev->stats.collisions += 16;
+ 	if (status & Tx_TxColl_MASK)
+-		lp->stats.collisions += status & Tx_TxColl_MASK;
++		dev->stats.collisions += status & Tx_TxColl_MASK;
+ 
+ #ifndef NO_CHECK_CARRIER
+ 	/* TX4939 does not have NCarr */
+-	if (lp->boardtype == TC35815_TX4939)
++	if (lp->chiptype == TC35815_TX4939)
+ 		status &= ~Tx_NCarr;
+ #ifdef WORKAROUND_LOSTCAR
+ 	/* WORKAROUND: ignore LostCrS in full duplex operation */
+-	if ((lp->timer_state != asleep && lp->timer_state != lcheck)
+-	    || lp->fullduplex)
++	if (!lp->link || lp->duplex == DUPLEX_FULL)
+ 		status &= ~Tx_NCarr;
+ #endif
+ #endif
+ 
+ 	if (!(status & TX_STA_ERR)) {
+ 		/* no error. */
+-		lp->stats.tx_packets++;
++		dev->stats.tx_packets++;
+ 		return;
+ 	}
+ 
+-	lp->stats.tx_errors++;
++	dev->stats.tx_errors++;
+ 	if (status & Tx_ExColl) {
+-		lp->stats.tx_aborted_errors++;
++		dev->stats.tx_aborted_errors++;
+ 		msg = "Excessive Collision.";
+ 	}
+ 	if (status & Tx_Under) {
+-		lp->stats.tx_fifo_errors++;
++		dev->stats.tx_fifo_errors++;
+ 		msg = "Tx FIFO Underrun.";
+ 		if (lp->lstats.tx_underrun < TX_THRESHOLD_KEEP_LIMIT) {
+ 			lp->lstats.tx_underrun++;
+@@ -1818,25 +1972,25 @@ tc35815_check_tx_stat(struct net_device *dev, int status)
+ 		}
+ 	}
+ 	if (status & Tx_Defer) {
+-		lp->stats.tx_fifo_errors++;
++		dev->stats.tx_fifo_errors++;
+ 		msg = "Excessive Deferral.";
+ 	}
+ #ifndef NO_CHECK_CARRIER
+ 	if (status & Tx_NCarr) {
+-		lp->stats.tx_carrier_errors++;
++		dev->stats.tx_carrier_errors++;
+ 		msg = "Lost Carrier Sense.";
+ 	}
+ #endif
+ 	if (status & Tx_LateColl) {
+-		lp->stats.tx_aborted_errors++;
++		dev->stats.tx_aborted_errors++;
+ 		msg = "Late Collision.";
+ 	}
+ 	if (status & Tx_TxPar) {
+-		lp->stats.tx_fifo_errors++;
++		dev->stats.tx_fifo_errors++;
+ 		msg = "Transmit Parity Error.";
+ 	}
+ 	if (status & Tx_SQErr) {
+-		lp->stats.tx_heartbeat_errors++;
++		dev->stats.tx_heartbeat_errors++;
+ 		msg = "Signal Quality Error.";
+ 	}
+ 	if (msg && netif_msg_tx_err(lp))
+@@ -1849,7 +2003,7 @@ tc35815_check_tx_stat(struct net_device *dev, int status)
+ static void
+ tc35815_txdone(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	struct TxFD *txfd;
+ 	unsigned int fdctl;
+ 
+@@ -1878,7 +2032,7 @@ tc35815_txdone(struct net_device *dev)
+ 		BUG_ON(lp->tx_skbs[lp->tfd_end].skb != skb);
+ #endif
+ 		if (skb) {
+-			lp->stats.tx_bytes += skb->len;
++			dev->stats.tx_bytes += skb->len;
+ 			pci_unmap_single(lp->pci_dev, lp->tx_skbs[lp->tfd_end].skb_dma, skb->len, PCI_DMA_TODEVICE);
+ 			lp->tx_skbs[lp->tfd_end].skb = NULL;
+ 			lp->tx_skbs[lp->tfd_end].skb_dma = 0;
+@@ -1904,7 +2058,7 @@ tc35815_txdone(struct net_device *dev)
+ 				struct tc35815_regs __iomem *tr =
+ 					(struct tc35815_regs __iomem *)dev->base_addr;
+ 				int head = (lp->tfd_start + TX_FD_NUM - 1) % TX_FD_NUM;
+-				struct TxFD* txhead = &lp->tfd_base[head];
++				struct TxFD *txhead = &lp->tfd_base[head];
+ 				int qlen = (lp->tfd_start + TX_FD_NUM
+ 					    - lp->tfd_end) % TX_FD_NUM;
+ 
+@@ -1939,7 +2093,7 @@ tc35815_txdone(struct net_device *dev)
+ 	 * condition, and space has now been made available,
+ 	 * wake up the queue.
+ 	 */
+-	if (netif_queue_stopped(dev) && ! tc35815_tx_full(dev))
++	if (netif_queue_stopped(dev) && !tc35815_tx_full(dev))
+ 		netif_wake_queue(dev);
+ }
+ 
+@@ -1947,16 +2101,17 @@ tc35815_txdone(struct net_device *dev)
+ static int
+ tc35815_close(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 
+ 	netif_stop_queue(dev);
+ #ifdef TC35815_NAPI
+ 	napi_disable(&lp->napi);
+ #endif
++	if (lp->phy_dev)
++		phy_stop(lp->phy_dev);
++	cancel_work_sync(&lp->restart_work);
+ 
+ 	/* Flush the Tx and disable Rx here. */
+-
+-	del_timer(&lp->timer);		/* Kill if running	*/
+ 	tc35815_chip_reset(dev);
+ 	free_irq(dev->irq, dev);
+ 
+@@ -1972,34 +2127,30 @@ tc35815_close(struct net_device *dev)
+  */
+ static struct net_device_stats *tc35815_get_stats(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
+ 	struct tc35815_regs __iomem *tr =
+ 		(struct tc35815_regs __iomem *)dev->base_addr;
+-	if (netif_running(dev)) {
++	if (netif_running(dev))
+ 		/* Update the statistics from the device registers. */
+-		lp->stats.rx_missed_errors = tc_readl(&tr->Miss_Cnt);
+-	}
++		dev->stats.rx_missed_errors = tc_readl(&tr->Miss_Cnt);
+ 
+-	return &lp->stats;
++	return &dev->stats;
+ }
+ 
+ static void tc35815_set_cam_entry(struct net_device *dev, int index, unsigned char *addr)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	struct tc35815_regs __iomem *tr =
+ 		(struct tc35815_regs __iomem *)dev->base_addr;
+ 	int cam_index = index * 6;
+ 	u32 cam_data;
+ 	u32 saved_addr;
++	DECLARE_MAC_BUF(mac);
++
+ 	saved_addr = tc_readl(&tr->CAM_Adr);
+ 
+-	if (netif_msg_hw(lp)) {
+-		int i;
+-		printk(KERN_DEBUG "%s: CAM %d:", dev->name, index);
+-		for (i = 0; i < 6; i++)
+-			printk(" %02x", addr[i]);
+-		printk("\n");
+-	}
++	if (netif_msg_hw(lp))
++		printk(KERN_DEBUG "%s: CAM %d: %s\n",
++			dev->name, index, print_mac(mac, addr));
+ 	if (index & 1) {
+ 		/* read modify write */
+ 		tc_writel(cam_index - 2, &tr->CAM_Adr);
+@@ -2039,28 +2190,24 @@ tc35815_set_multicast_list(struct net_device *dev)
+ 	struct tc35815_regs __iomem *tr =
+ 		(struct tc35815_regs __iomem *)dev->base_addr;
+ 
+-	if (dev->flags&IFF_PROMISC)
+-	{
++	if (dev->flags & IFF_PROMISC) {
+ #ifdef WORKAROUND_100HALF_PROMISC
+ 		/* With some (all?) 100MHalf HUB, controller will hang
+ 		 * if we enabled promiscuous mode before linkup... */
+-		struct tc35815_local *lp = dev->priv;
+-		int pid = lp->phy_addr;
+-		if (!(tc_mdio_read(dev, pid, MII_BMSR) & BMSR_LSTATUS))
++		struct tc35815_local *lp = netdev_priv(dev);
++
++		if (!lp->link)
+ 			return;
+ #endif
+ 		/* Enable promiscuous mode */
+ 		tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc | CAM_StationAcc, &tr->CAM_Ctl);
+-	}
+-	else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > CAM_ENTRY_MAX - 3)
+-	{
++	} else if ((dev->flags & IFF_ALLMULTI) ||
++		  dev->mc_count > CAM_ENTRY_MAX - 3) {
+ 		/* CAM 0, 1, 20 are reserved. */
+ 		/* Disable promiscuous mode, use normal mode. */
+ 		tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc, &tr->CAM_Ctl);
+-	}
+-	else if(dev->mc_count)
+-	{
+-		struct dev_mc_list* cur_addr = dev->mc_list;
++	} else if (dev->mc_count) {
++		struct dev_mc_list *cur_addr = dev->mc_list;
+ 		int i;
+ 		int ena_bits = CAM_Ena_Bit(CAM_ENTRY_SOURCE);
+ 
+@@ -2075,8 +2222,7 @@ tc35815_set_multicast_list(struct net_device *dev)
+ 		}
+ 		tc_writel(ena_bits, &tr->CAM_Ena);
+ 		tc_writel(CAM_CompEn | CAM_BroadAcc, &tr->CAM_Ctl);
+-	}
+-	else {
++	} else {
+ 		tc_writel(CAM_Ena_Bit(CAM_ENTRY_SOURCE), &tr->CAM_Ena);
+ 		tc_writel(CAM_CompEn | CAM_BroadAcc, &tr->CAM_Ctl);
+ 	}
+@@ -2084,7 +2230,7 @@ tc35815_set_multicast_list(struct net_device *dev)
+ 
+ static void tc35815_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	strcpy(info->driver, MODNAME);
+ 	strcpy(info->version, DRV_VERSION);
+ 	strcpy(info->bus_info, pci_name(lp->pci_dev));
+@@ -2092,78 +2238,37 @@ static void tc35815_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *
+ 
+ static int tc35815_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+-	struct tc35815_local *lp = dev->priv;
+-	spin_lock_irq(&lp->lock);
+-	mii_ethtool_gset(&lp->mii, cmd);
+-	spin_unlock_irq(&lp->lock);
+-	return 0;
+-}
+-
+-static int tc35815_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+-{
+-	struct tc35815_local *lp = dev->priv;
+-	int rc;
+-#if 1	/* use our negotiation method... */
+-	/* Verify the settings we care about. */
+-	if (cmd->autoneg != AUTONEG_ENABLE &&
+-	    cmd->autoneg != AUTONEG_DISABLE)
+-		return -EINVAL;
+-	if (cmd->autoneg == AUTONEG_DISABLE &&
+-	    ((cmd->speed != SPEED_100 &&
+-	      cmd->speed != SPEED_10) ||
+-	     (cmd->duplex != DUPLEX_HALF &&
+-	      cmd->duplex != DUPLEX_FULL)))
+-		return -EINVAL;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 
+-	/* Ok, do it to it. */
+-	spin_lock_irq(&lp->lock);
+-	del_timer(&lp->timer);
+-	tc35815_start_auto_negotiation(dev, cmd);
+-	spin_unlock_irq(&lp->lock);
+-	rc = 0;
+-#else
+-	spin_lock_irq(&lp->lock);
+-	rc = mii_ethtool_sset(&lp->mii, cmd);
+-	spin_unlock_irq(&lp->lock);
+-#endif
+-	return rc;
++	if (!lp->phy_dev)
++		return -ENODEV;
++	return phy_ethtool_gset(lp->phy_dev, cmd);
+ }
+ 
+-static int tc35815_nway_reset(struct net_device *dev)
++static int tc35815_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+-	struct tc35815_local *lp = dev->priv;
+-	int rc;
+-	spin_lock_irq(&lp->lock);
+-	rc = mii_nway_restart(&lp->mii);
+-	spin_unlock_irq(&lp->lock);
+-	return rc;
+-}
++	struct tc35815_local *lp = netdev_priv(dev);
+ 
+-static u32 tc35815_get_link(struct net_device *dev)
+-{
+-	struct tc35815_local *lp = dev->priv;
+-	int rc;
+-	spin_lock_irq(&lp->lock);
+-	rc = mii_link_ok(&lp->mii);
+-	spin_unlock_irq(&lp->lock);
+-	return rc;
++	if (!lp->phy_dev)
++		return -ENODEV;
++	return phy_ethtool_sset(lp->phy_dev, cmd);
+ }
+ 
+ static u32 tc35815_get_msglevel(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	return lp->msg_enable;
+ }
+ 
+ static void tc35815_set_msglevel(struct net_device *dev, u32 datum)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	lp->msg_enable = datum;
+ }
+ 
+ static int tc35815_get_sset_count(struct net_device *dev, int sset)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 
+ 	switch (sset) {
+ 	case ETH_SS_STATS:
+@@ -2175,7 +2280,7 @@ static int tc35815_get_sset_count(struct net_device *dev, int sset)
+ 
+ static void tc35815_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	data[0] = lp->lstats.max_tx_qlen;
+ 	data[1] = lp->lstats.tx_ints;
+ 	data[2] = lp->lstats.rx_ints;
+@@ -2200,8 +2305,7 @@ static const struct ethtool_ops tc35815_ethtool_ops = {
+ 	.get_drvinfo		= tc35815_get_drvinfo,
+ 	.get_settings		= tc35815_get_settings,
+ 	.set_settings		= tc35815_set_settings,
+-	.nway_reset		= tc35815_nway_reset,
+-	.get_link		= tc35815_get_link,
++	.get_link		= ethtool_op_get_link,
+ 	.get_msglevel		= tc35815_get_msglevel,
+ 	.set_msglevel		= tc35815_set_msglevel,
+ 	.get_strings		= tc35815_get_strings,
+@@ -2211,611 +2315,13 @@ static const struct ethtool_ops tc35815_ethtool_ops = {
+ 
+ static int tc35815_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+-	struct tc35815_local *lp = dev->priv;
+-	int rc;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 
+ 	if (!netif_running(dev))
+ 		return -EINVAL;
+-
+-	spin_lock_irq(&lp->lock);
+-	rc = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
+-	spin_unlock_irq(&lp->lock);
+-
+-	return rc;
+-}
+-
+-static int tc_mdio_read(struct net_device *dev, int phy_id, int location)
+-{
+-	struct tc35815_regs __iomem *tr =
+-		(struct tc35815_regs __iomem *)dev->base_addr;
+-	u32 data;
+-	tc_writel(MD_CA_Busy | (phy_id << 5) | location, &tr->MD_CA);
+-	while (tc_readl(&tr->MD_CA) & MD_CA_Busy)
+-		;
+-	data = tc_readl(&tr->MD_Data);
+-	return data & 0xffff;
+-}
+-
+-static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
+-			  int val)
+-{
+-	struct tc35815_regs __iomem *tr =
+-		(struct tc35815_regs __iomem *)dev->base_addr;
+-	tc_writel(val, &tr->MD_Data);
+-	tc_writel(MD_CA_Busy | MD_CA_Wr | (phy_id << 5) | location, &tr->MD_CA);
+-	while (tc_readl(&tr->MD_CA) & MD_CA_Busy)
+-		;
+-}
+-
+-/* Auto negotiation.  The scheme is very simple.  We have a timer routine
+- * that keeps watching the auto negotiation process as it progresses.
+- * The DP83840 is first told to start doing it's thing, we set up the time
+- * and place the timer state machine in it's initial state.
+- *
+- * Here the timer peeks at the DP83840 status registers at each click to see
+- * if the auto negotiation has completed, we assume here that the DP83840 PHY
+- * will time out at some point and just tell us what (didn't) happen.  For
+- * complete coverage we only allow so many of the ticks at this level to run,
+- * when this has expired we print a warning message and try another strategy.
+- * This "other" strategy is to force the interface into various speed/duplex
+- * configurations and we stop when we see a link-up condition before the
+- * maximum number of "peek" ticks have occurred.
+- *
+- * Once a valid link status has been detected we configure the BigMAC and
+- * the rest of the Happy Meal to speak the most efficient protocol we could
+- * get a clean link for.  The priority for link configurations, highest first
+- * is:
+- *                 100 Base-T Full Duplex
+- *                 100 Base-T Half Duplex
+- *                 10 Base-T Full Duplex
+- *                 10 Base-T Half Duplex
+- *
+- * We start a new timer now, after a successful auto negotiation status has
+- * been detected.  This timer just waits for the link-up bit to get set in
+- * the BMCR of the DP83840.  When this occurs we print a kernel log message
+- * describing the link type in use and the fact that it is up.
+- *
+- * If a fatal error of some sort is signalled and detected in the interrupt
+- * service routine, and the chip is reset, or the link is ifconfig'd down
+- * and then back up, this entire process repeats itself all over again.
+- */
+-/* Note: Above comments are come from sunhme driver. */
+-
+-static int tc35815_try_next_permutation(struct net_device *dev)
+-{
+-	struct tc35815_local *lp = dev->priv;
+-	int pid = lp->phy_addr;
+-	unsigned short bmcr;
+-
+-	bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-
+-	/* Downgrade from full to half duplex.  Only possible via ethtool.  */
+-	if (bmcr & BMCR_FULLDPLX) {
+-		bmcr &= ~BMCR_FULLDPLX;
+-		printk(KERN_DEBUG "%s: try next permutation (BMCR %x)\n", dev->name, bmcr);
+-		tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+-		return 0;
+-	}
+-
+-	/* Downgrade from 100 to 10. */
+-	if (bmcr & BMCR_SPEED100) {
+-		bmcr &= ~BMCR_SPEED100;
+-		printk(KERN_DEBUG "%s: try next permutation (BMCR %x)\n", dev->name, bmcr);
+-		tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+-		return 0;
+-	}
+-
+-	/* We've tried everything. */
+-	return -1;
+-}
+-
+-static void
+-tc35815_display_link_mode(struct net_device *dev)
+-{
+-	struct tc35815_local *lp = dev->priv;
+-	int pid = lp->phy_addr;
+-	unsigned short lpa, bmcr;
+-	char *speed = "", *duplex = "";
+-
+-	lpa = tc_mdio_read(dev, pid, MII_LPA);
+-	bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-	if (options.speed ? (bmcr & BMCR_SPEED100) : (lpa & (LPA_100HALF | LPA_100FULL)))
+-		speed = "100Mb/s";
+-	else
+-		speed = "10Mb/s";
+-	if (options.duplex ? (bmcr & BMCR_FULLDPLX) : (lpa & (LPA_100FULL | LPA_10FULL)))
+-		duplex = "Full Duplex";
+-	else
+-		duplex = "Half Duplex";
+-
+-	if (netif_msg_link(lp))
+-		printk(KERN_INFO "%s: Link is up at %s, %s.\n",
+-		       dev->name, speed, duplex);
+-	printk(KERN_DEBUG "%s: MII BMCR %04x BMSR %04x LPA %04x\n",
+-	       dev->name,
+-	       bmcr, tc_mdio_read(dev, pid, MII_BMSR), lpa);
+-}
+-
+-static void tc35815_display_forced_link_mode(struct net_device *dev)
+-{
+-	struct tc35815_local *lp = dev->priv;
+-	int pid = lp->phy_addr;
+-	unsigned short bmcr;
+-	char *speed = "", *duplex = "";
+-
+-	bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-	if (bmcr & BMCR_SPEED100)
+-		speed = "100Mb/s";
+-	else
+-		speed = "10Mb/s";
+-	if (bmcr & BMCR_FULLDPLX)
+-		duplex = "Full Duplex.\n";
+-	else
+-		duplex = "Half Duplex.\n";
+-
+-	if (netif_msg_link(lp))
+-		printk(KERN_INFO "%s: Link has been forced up at %s, %s",
+-		       dev->name, speed, duplex);
+-}
+-
+-static void tc35815_set_link_modes(struct net_device *dev)
+-{
+-	struct tc35815_local *lp = dev->priv;
+-	struct tc35815_regs __iomem *tr =
+-		(struct tc35815_regs __iomem *)dev->base_addr;
+-	int pid = lp->phy_addr;
+-	unsigned short bmcr, lpa;
+-	int speed;
+-
+-	if (lp->timer_state == arbwait) {
+-		lpa = tc_mdio_read(dev, pid, MII_LPA);
+-		bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-		printk(KERN_DEBUG "%s: MII BMCR %04x BMSR %04x LPA %04x\n",
+-		       dev->name,
+-		       bmcr, tc_mdio_read(dev, pid, MII_BMSR), lpa);
+-		if (!(lpa & (LPA_10HALF | LPA_10FULL |
+-			     LPA_100HALF | LPA_100FULL))) {
+-			/* fall back to 10HALF */
+-			printk(KERN_INFO "%s: bad ability %04x - falling back to 10HD.\n",
+-			       dev->name, lpa);
+-			lpa = LPA_10HALF;
+-		}
+-		if (options.duplex ? (bmcr & BMCR_FULLDPLX) : (lpa & (LPA_100FULL | LPA_10FULL)))
+-			lp->fullduplex = 1;
+-		else
+-			lp->fullduplex = 0;
+-		if (options.speed ? (bmcr & BMCR_SPEED100) : (lpa & (LPA_100HALF | LPA_100FULL)))
+-			speed = 100;
+-		else
+-			speed = 10;
+-	} else {
+-		/* Forcing a link mode. */
+-		bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-		if (bmcr & BMCR_FULLDPLX)
+-			lp->fullduplex = 1;
+-		else
+-			lp->fullduplex = 0;
+-		if (bmcr & BMCR_SPEED100)
+-			speed = 100;
+-		else
+-			speed = 10;
+-	}
+-
+-	tc_writel(tc_readl(&tr->MAC_Ctl) | MAC_HaltReq, &tr->MAC_Ctl);
+-	if (lp->fullduplex) {
+-		tc_writel(tc_readl(&tr->MAC_Ctl) | MAC_FullDup, &tr->MAC_Ctl);
+-	} else {
+-		tc_writel(tc_readl(&tr->MAC_Ctl) & ~MAC_FullDup, &tr->MAC_Ctl);
+-	}
+-	tc_writel(tc_readl(&tr->MAC_Ctl) & ~MAC_HaltReq, &tr->MAC_Ctl);
+-
+-	/* TX4939 PCFG.SPEEDn bit will be changed on NETDEV_CHANGE event. */
+-
+-#ifndef NO_CHECK_CARRIER
+-	/* TX4939 does not have EnLCarr */
+-	if (lp->boardtype != TC35815_TX4939) {
+-#ifdef WORKAROUND_LOSTCAR
+-		/* WORKAROUND: enable LostCrS only if half duplex operation */
+-		if (!lp->fullduplex && lp->boardtype != TC35815_TX4939)
+-			tc_writel(tc_readl(&tr->Tx_Ctl) | Tx_EnLCarr, &tr->Tx_Ctl);
+-#endif
+-	}
+-#endif
+-	lp->mii.full_duplex = lp->fullduplex;
+-}
+-
+-static void tc35815_timer(unsigned long data)
+-{
+-	struct net_device *dev = (struct net_device *)data;
+-	struct tc35815_local *lp = dev->priv;
+-	int pid = lp->phy_addr;
+-	unsigned short bmsr, bmcr, lpa;
+-	int restart_timer = 0;
+-
+-	spin_lock_irq(&lp->lock);
+-
+-	lp->timer_ticks++;
+-	switch (lp->timer_state) {
+-	case arbwait:
+-		/*
+-		 * Only allow for 5 ticks, thats 10 seconds and much too
+-		 * long to wait for arbitration to complete.
+-		 */
+-		/* TC35815 need more times... */
+-		if (lp->timer_ticks >= 10) {
+-			/* Enter force mode. */
+-			if (!options.doforce) {
+-				printk(KERN_NOTICE "%s: Auto-Negotiation unsuccessful,"
+-				       " cable probblem?\n", dev->name);
+-				/* Try to restart the adaptor. */
+-				tc35815_restart(dev);
+-				goto out;
+-			}
+-			printk(KERN_NOTICE "%s: Auto-Negotiation unsuccessful,"
+-			       " trying force link mode\n", dev->name);
+-			printk(KERN_DEBUG "%s: BMCR %x BMSR %x\n", dev->name,
+-			       tc_mdio_read(dev, pid, MII_BMCR),
+-			       tc_mdio_read(dev, pid, MII_BMSR));
+-			bmcr = BMCR_SPEED100;
+-			tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+-
+-			/*
+-			 * OK, seems we need do disable the transceiver
+-			 * for the first tick to make sure we get an
+-			 * accurate link state at the second tick.
+-			 */
+-
+-			lp->timer_state = ltrywait;
+-			lp->timer_ticks = 0;
+-			restart_timer = 1;
+-		} else {
+-			/* Anything interesting happen? */
+-			bmsr = tc_mdio_read(dev, pid, MII_BMSR);
+-			if (bmsr & BMSR_ANEGCOMPLETE) {
+-				/* Just what we've been waiting for... */
+-				tc35815_set_link_modes(dev);
+-
+-				/*
+-				 * Success, at least so far, advance our state
+-				 * engine.
+-				 */
+-				lp->timer_state = lupwait;
+-				restart_timer = 1;
+-			} else {
+-				restart_timer = 1;
+-			}
+-		}
+-		break;
+-
+-	case lupwait:
+-		/*
+-		 * Auto negotiation was successful and we are awaiting a
+-		 * link up status.  I have decided to let this timer run
+-		 * forever until some sort of error is signalled, reporting
+-		 * a message to the user at 10 second intervals.
+-		 */
+-		bmsr = tc_mdio_read(dev, pid, MII_BMSR);
+-		if (bmsr & BMSR_LSTATUS) {
+-			/*
+-			 * Wheee, it's up, display the link mode in use and put
+-			 * the timer to sleep.
+-			 */
+-			tc35815_display_link_mode(dev);
+-			netif_carrier_on(dev);
+-#ifdef WORKAROUND_100HALF_PROMISC
+-			/* delayed promiscuous enabling */
+-			if (dev->flags & IFF_PROMISC)
+-				tc35815_set_multicast_list(dev);
+-#endif
+-#if 1
+-			lp->saved_lpa = tc_mdio_read(dev, pid, MII_LPA);
+-			lp->timer_state = lcheck;
+-			restart_timer = 1;
+-#else
+-			lp->timer_state = asleep;
+-			restart_timer = 0;
+-#endif
+-		} else {
+-			if (lp->timer_ticks >= 10) {
+-				printk(KERN_NOTICE "%s: Auto negotiation successful, link still "
+-				       "not completely up.\n", dev->name);
+-				lp->timer_ticks = 0;
+-				restart_timer = 1;
+-			} else {
+-				restart_timer = 1;
+-			}
+-		}
+-		break;
+-
+-	case ltrywait:
+-		/*
+-		 * Making the timeout here too long can make it take
+-		 * annoyingly long to attempt all of the link mode
+-		 * permutations, but then again this is essentially
+-		 * error recovery code for the most part.
+-		 */
+-		bmsr = tc_mdio_read(dev, pid, MII_BMSR);
+-		bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-		if (lp->timer_ticks == 1) {
+-			/*
+-			 * Re-enable transceiver, we'll re-enable the
+-			 * transceiver next tick, then check link state
+-			 * on the following tick.
+-			 */
+-			restart_timer = 1;
+-			break;
+-		}
+-		if (lp->timer_ticks == 2) {
+-			restart_timer = 1;
+-			break;
+-		}
+-		if (bmsr & BMSR_LSTATUS) {
+-			/* Force mode selection success. */
+-			tc35815_display_forced_link_mode(dev);
+-			netif_carrier_on(dev);
+-			tc35815_set_link_modes(dev);
+-#ifdef WORKAROUND_100HALF_PROMISC
+-			/* delayed promiscuous enabling */
+-			if (dev->flags & IFF_PROMISC)
+-				tc35815_set_multicast_list(dev);
+-#endif
+-#if 1
+-			lp->saved_lpa = tc_mdio_read(dev, pid, MII_LPA);
+-			lp->timer_state = lcheck;
+-			restart_timer = 1;
+-#else
+-			lp->timer_state = asleep;
+-			restart_timer = 0;
+-#endif
+-		} else {
+-			if (lp->timer_ticks >= 4) { /* 6 seconds or so... */
+-				int ret;
+-
+-				ret = tc35815_try_next_permutation(dev);
+-				if (ret == -1) {
+-					/*
+-					 * Aieee, tried them all, reset the
+-					 * chip and try all over again.
+-					 */
+-					printk(KERN_NOTICE "%s: Link down, "
+-					       "cable problem?\n",
+-					       dev->name);
+-
+-					/* Try to restart the adaptor. */
+-					tc35815_restart(dev);
+-					goto out;
+-				}
+-				lp->timer_ticks = 0;
+-				restart_timer = 1;
+-			} else {
+-				restart_timer = 1;
+-			}
+-		}
+-		break;
+-
+-	case lcheck:
+-		bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-		lpa = tc_mdio_read(dev, pid, MII_LPA);
+-		if (bmcr & (BMCR_PDOWN | BMCR_ISOLATE | BMCR_RESET)) {
+-			printk(KERN_ERR "%s: PHY down? (BMCR %x)\n", dev->name,
+-			       bmcr);
+-		} else if ((lp->saved_lpa ^ lpa) &
+-			   (LPA_100FULL|LPA_100HALF|LPA_10FULL|LPA_10HALF)) {
+-			printk(KERN_NOTICE "%s: link status changed"
+-			       " (BMCR %x LPA %x->%x)\n", dev->name,
+-			       bmcr, lp->saved_lpa, lpa);
+-		} else {
+-			/* go on */
+-			restart_timer = 1;
+-			break;
+-		}
+-		/* Try to restart the adaptor. */
+-		tc35815_restart(dev);
+-		goto out;
+-
+-	case asleep:
+-	default:
+-		/* Can't happens.... */
+-		printk(KERN_ERR "%s: Aieee, link timer is asleep but we got "
+-		       "one anyways!\n", dev->name);
+-		restart_timer = 0;
+-		lp->timer_ticks = 0;
+-		lp->timer_state = asleep; /* foo on you */
+-		break;
+-	}
+-
+-	if (restart_timer) {
+-		lp->timer.expires = jiffies + msecs_to_jiffies(1200);
+-		add_timer(&lp->timer);
+-	}
+-out:
+-	spin_unlock_irq(&lp->lock);
+-}
+-
+-static void tc35815_start_auto_negotiation(struct net_device *dev,
+-					   struct ethtool_cmd *ep)
+-{
+-	struct tc35815_local *lp = dev->priv;
+-	int pid = lp->phy_addr;
+-	unsigned short bmsr, bmcr, advertize;
+-	int timeout;
+-
+-	netif_carrier_off(dev);
+-	bmsr = tc_mdio_read(dev, pid, MII_BMSR);
+-	bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-	advertize = tc_mdio_read(dev, pid, MII_ADVERTISE);
+-
+-	if (ep == NULL || ep->autoneg == AUTONEG_ENABLE) {
+-		if (options.speed || options.duplex) {
+-			/* Advertise only specified configuration. */
+-			advertize &= ~(ADVERTISE_10HALF |
+-				       ADVERTISE_10FULL |
+-				       ADVERTISE_100HALF |
+-				       ADVERTISE_100FULL);
+-			if (options.speed != 10) {
+-				if (options.duplex != 1)
+-					advertize |= ADVERTISE_100FULL;
+-				if (options.duplex != 2)
+-					advertize |= ADVERTISE_100HALF;
+-			}
+-			if (options.speed != 100) {
+-				if (options.duplex != 1)
+-					advertize |= ADVERTISE_10FULL;
+-				if (options.duplex != 2)
+-					advertize |= ADVERTISE_10HALF;
+-			}
+-			if (options.speed == 100)
+-				bmcr |= BMCR_SPEED100;
+-			else if (options.speed == 10)
+-				bmcr &= ~BMCR_SPEED100;
+-			if (options.duplex == 2)
+-				bmcr |= BMCR_FULLDPLX;
+-			else if (options.duplex == 1)
+-				bmcr &= ~BMCR_FULLDPLX;
+-		} else {
+-			/* Advertise everything we can support. */
+-			if (bmsr & BMSR_10HALF)
+-				advertize |= ADVERTISE_10HALF;
+-			else
+-				advertize &= ~ADVERTISE_10HALF;
+-			if (bmsr & BMSR_10FULL)
+-				advertize |= ADVERTISE_10FULL;
+-			else
+-				advertize &= ~ADVERTISE_10FULL;
+-			if (bmsr & BMSR_100HALF)
+-				advertize |= ADVERTISE_100HALF;
+-			else
+-				advertize &= ~ADVERTISE_100HALF;
+-			if (bmsr & BMSR_100FULL)
+-				advertize |= ADVERTISE_100FULL;
+-			else
+-				advertize &= ~ADVERTISE_100FULL;
+-		}
+-
+-		tc_mdio_write(dev, pid, MII_ADVERTISE, advertize);
+-
+-		/* Enable Auto-Negotiation, this is usually on already... */
+-		bmcr |= BMCR_ANENABLE;
+-		tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+-
+-		/* Restart it to make sure it is going. */
+-		bmcr |= BMCR_ANRESTART;
+-		tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+-		printk(KERN_DEBUG "%s: ADVERTISE %x BMCR %x\n", dev->name, advertize, bmcr);
+-
+-		/* BMCR_ANRESTART self clears when the process has begun. */
+-		timeout = 64;  /* More than enough. */
+-		while (--timeout) {
+-			bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-			if (!(bmcr & BMCR_ANRESTART))
+-				break; /* got it. */
+-			udelay(10);
+-		}
+-		if (!timeout) {
+-			printk(KERN_ERR "%s: TC35815 would not start auto "
+-			       "negotiation BMCR=0x%04x\n",
+-			       dev->name, bmcr);
+-			printk(KERN_NOTICE "%s: Performing force link "
+-			       "detection.\n", dev->name);
+-			goto force_link;
+-		} else {
+-			printk(KERN_DEBUG "%s: auto negotiation started.\n", dev->name);
+-			lp->timer_state = arbwait;
+-		}
+-	} else {
+-force_link:
+-		/* Force the link up, trying first a particular mode.
+-		 * Either we are here at the request of ethtool or
+-		 * because the Happy Meal would not start to autoneg.
+-		 */
+-
+-		/* Disable auto-negotiation in BMCR, enable the duplex and
+-		 * speed setting, init the timer state machine, and fire it off.
+-		 */
+-		if (ep == NULL || ep->autoneg == AUTONEG_ENABLE) {
+-			bmcr = BMCR_SPEED100;
+-		} else {
+-			if (ep->speed == SPEED_100)
+-				bmcr = BMCR_SPEED100;
+-			else
+-				bmcr = 0;
+-			if (ep->duplex == DUPLEX_FULL)
+-				bmcr |= BMCR_FULLDPLX;
+-		}
+-		tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+-
+-		/* OK, seems we need do disable the transceiver for the first
+-		 * tick to make sure we get an accurate link state at the
+-		 * second tick.
+-		 */
+-		lp->timer_state = ltrywait;
+-	}
+-
+-	del_timer(&lp->timer);
+-	lp->timer_ticks = 0;
+-	lp->timer.expires = jiffies + msecs_to_jiffies(1200);
+-	add_timer(&lp->timer);
+-}
+-
+-static void tc35815_find_phy(struct net_device *dev)
+-{
+-	struct tc35815_local *lp = dev->priv;
+-	int pid = lp->phy_addr;
+-	unsigned short id0;
+-
+-	/* find MII phy */
+-	for (pid = 31; pid >= 0; pid--) {
+-		id0 = tc_mdio_read(dev, pid, MII_BMSR);
+-		if (id0 != 0xffff && id0 != 0x0000 &&
+-		    (id0 & BMSR_RESV) != (0xffff & BMSR_RESV) /* paranoia? */
+-			) {
+-			lp->phy_addr = pid;
+-			break;
+-		}
+-	}
+-	if (pid < 0) {
+-		printk(KERN_ERR "%s: No MII Phy found.\n",
+-		       dev->name);
+-		lp->phy_addr = pid = 0;
+-	}
+-
+-	lp->mii_id[0] = tc_mdio_read(dev, pid, MII_PHYSID1);
+-	lp->mii_id[1] = tc_mdio_read(dev, pid, MII_PHYSID2);
+-	if (netif_msg_hw(lp))
+-		printk(KERN_INFO "%s: PHY(%02x) ID %04x %04x\n", dev->name,
+-		       pid, lp->mii_id[0], lp->mii_id[1]);
+-}
+-
+-static void tc35815_phy_chip_init(struct net_device *dev)
+-{
+-	struct tc35815_local *lp = dev->priv;
+-	int pid = lp->phy_addr;
+-	unsigned short bmcr;
+-	struct ethtool_cmd ecmd, *ep;
+-
+-	/* dis-isolate if needed. */
+-	bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-	if (bmcr & BMCR_ISOLATE) {
+-		int count = 32;
+-		printk(KERN_DEBUG "%s: unisolating...", dev->name);
+-		tc_mdio_write(dev, pid, MII_BMCR, bmcr & ~BMCR_ISOLATE);
+-		while (--count) {
+-			if (!(tc_mdio_read(dev, pid, MII_BMCR) & BMCR_ISOLATE))
+-				break;
+-			udelay(20);
+-		}
+-		printk(" %s.\n", count ? "done" : "failed");
+-	}
+-
+-	if (options.speed && options.duplex) {
+-		ecmd.autoneg = AUTONEG_DISABLE;
+-		ecmd.speed = options.speed == 10 ? SPEED_10 : SPEED_100;
+-		ecmd.duplex = options.duplex == 1 ? DUPLEX_HALF : DUPLEX_FULL;
+-		ep = &ecmd;
+-	} else {
+-		ep = NULL;
+-	}
+-	tc35815_start_auto_negotiation(dev, ep);
++	if (!lp->phy_dev)
++		return -ENODEV;
++	return phy_mii_ioctl(lp->phy_dev, if_mii(rq), cmd);
+ }
+ 
+ static void tc35815_chip_reset(struct net_device *dev)
+@@ -2862,13 +2368,11 @@ static void tc35815_chip_reset(struct net_device *dev)
+ 
+ static void tc35815_chip_init(struct net_device *dev)
+ {
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	struct tc35815_regs __iomem *tr =
+ 		(struct tc35815_regs __iomem *)dev->base_addr;
+ 	unsigned long txctl = TX_CTL_CMD;
+ 
+-	tc35815_phy_chip_init(dev);
+-
+ 	/* load station address to CAM */
+ 	tc35815_set_cam_entry(dev, CAM_ENTRY_SOURCE, dev->dev_addr);
+ 
+@@ -2905,12 +2409,11 @@ static void tc35815_chip_init(struct net_device *dev)
+ 	/* start MAC transmitter */
+ #ifndef NO_CHECK_CARRIER
+ 	/* TX4939 does not have EnLCarr */
+-	if (lp->boardtype == TC35815_TX4939)
++	if (lp->chiptype == TC35815_TX4939)
+ 		txctl &= ~Tx_EnLCarr;
+ #ifdef WORKAROUND_LOSTCAR
+ 	/* WORKAROUND: ignore LostCrS in full duplex operation */
+-	if ((lp->timer_state != asleep && lp->timer_state != lcheck) ||
+-	    lp->fullduplex)
++	if (!lp->phy_dev || !lp->link || lp->duplex == DUPLEX_FULL)
+ 		txctl &= ~Tx_EnLCarr;
+ #endif
+ #endif /* !NO_CHECK_CARRIER */
+@@ -2924,15 +2427,16 @@ static void tc35815_chip_init(struct net_device *dev)
+ static int tc35815_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+-	struct tc35815_local *lp = dev->priv;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 	unsigned long flags;
+ 
+ 	pci_save_state(pdev);
+ 	if (!netif_running(dev))
+ 		return 0;
+ 	netif_device_detach(dev);
++	if (lp->phy_dev)
++		phy_stop(lp->phy_dev);
+ 	spin_lock_irqsave(&lp->lock, flags);
+-	del_timer(&lp->timer);		/* Kill if running	*/
+ 	tc35815_chip_reset(dev);
+ 	spin_unlock_irqrestore(&lp->lock, flags);
+ 	pci_set_power_state(pdev, PCI_D3hot);
+@@ -2942,16 +2446,15 @@ static int tc35815_suspend(struct pci_dev *pdev, pm_message_t state)
+ static int tc35815_resume(struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata(pdev);
+-	struct tc35815_local *lp = dev->priv;
+-	unsigned long flags;
++	struct tc35815_local *lp = netdev_priv(dev);
+ 
+ 	pci_restore_state(pdev);
+ 	if (!netif_running(dev))
+ 		return 0;
+ 	pci_set_power_state(pdev, PCI_D0);
+-	spin_lock_irqsave(&lp->lock, flags);
+ 	tc35815_restart(dev);
+-	spin_unlock_irqrestore(&lp->lock, flags);
++	if (lp->phy_dev)
++		phy_start(lp->phy_dev);
+ 	netif_device_attach(dev);
+ 	return 0;
+ }
+@@ -2972,8 +2475,6 @@ module_param_named(speed, options.speed, int, 0);
+ MODULE_PARM_DESC(speed, "0:auto, 10:10Mbps, 100:100Mbps");
+ module_param_named(duplex, options.duplex, int, 0);
+ MODULE_PARM_DESC(duplex, "0:auto, 1:half, 2:full");
+-module_param_named(doforce, options.doforce, int, 0);
+-MODULE_PARM_DESC(doforce, "try force link mode if auto-negotiation failed");
+ 
+ static int __init tc35815_init_module(void)
+ {
+diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
+index 17585e5..e83b166 100644
+--- a/drivers/net/tehuti.c
++++ b/drivers/net/tehuti.c
+@@ -625,6 +625,12 @@ static void __init bdx_firmware_endianess(void)
+ 		s_firmLoad[i] = CPU_CHIP_SWAP32(s_firmLoad[i]);
+ }
+ 
++static int bdx_range_check(struct bdx_priv *priv, u32 offset)
++{
++	return (offset > (u32) (BDX_REGS_SIZE / priv->nic->port_num)) ?
++		-EINVAL : 0;
++}
++
+ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
+ {
+ 	struct bdx_priv *priv = ndev->priv;
+@@ -643,9 +649,15 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
+ 		DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
+ 	}
+ 
++	if (!capable(CAP_NET_ADMIN))
++		return -EPERM;
++
+ 	switch (data[0]) {
+ 
+ 	case BDX_OP_READ:
++		error = bdx_range_check(priv, data[1]);
++		if (error < 0)
++			return error;
+ 		data[2] = READ_REG(priv, data[1]);
+ 		DBG("read_reg(0x%x)=0x%x (dec %d)\n", data[1], data[2],
+ 		    data[2]);
+@@ -655,6 +667,9 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
+ 		break;
+ 
+ 	case BDX_OP_WRITE:
++		error = bdx_range_check(priv, data[1]);
++		if (error < 0)
++			return error;
+ 		WRITE_REG(priv, data[1], data[2]);
+ 		DBG("write_reg(0x%x, 0x%x)\n", data[1], data[2]);
+ 		break;
+diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
+index 96043c5..e3f74c9 100644
+--- a/drivers/net/tg3.c
++++ b/drivers/net/tg3.c
+@@ -64,8 +64,8 @@
+ 
+ #define DRV_MODULE_NAME		"tg3"
+ #define PFX DRV_MODULE_NAME	": "
+-#define DRV_MODULE_VERSION	"3.90"
+-#define DRV_MODULE_RELDATE	"April 12, 2008"
++#define DRV_MODULE_VERSION	"3.91"
++#define DRV_MODULE_RELDATE	"April 18, 2008"
+ 
+ #define TG3_DEF_MAC_MODE	0
+ #define TG3_DEF_RX_MODE		0
+@@ -4017,6 +4017,8 @@ static int tg3_halt(struct tg3 *, int, int);
+  * Invoked with tp->lock held.
+  */
+ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
++	__releases(tp->lock)
++	__acquires(tp->lock)
+ {
+ 	int err;
+ 
+@@ -4135,11 +4137,21 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
+ 				       u32 last_plus_one, u32 *start,
+ 				       u32 base_flags, u32 mss)
+ {
+-	struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
++	struct sk_buff *new_skb;
+ 	dma_addr_t new_addr = 0;
+ 	u32 entry = *start;
+ 	int i, ret = 0;
+ 
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
++		new_skb = skb_copy(skb, GFP_ATOMIC);
++	else {
++		int more_headroom = 4 - ((unsigned long)skb->data & 3);
++
++		new_skb = skb_copy_expand(skb,
++					  skb_headroom(skb) + more_headroom,
++					  skb_tailroom(skb), GFP_ATOMIC);
++	}
++
+ 	if (!new_skb) {
+ 		ret = -1;
+ 	} else {
+@@ -4462,7 +4474,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
+ 
+ 	would_hit_hwbug = 0;
+ 
+-	if (tg3_4g_overflow_test(mapping, len))
++	if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG)
++		would_hit_hwbug = 1;
++	else if (tg3_4g_overflow_test(mapping, len))
+ 		would_hit_hwbug = 1;
+ 
+ 	tg3_set_txd(tp, entry, mapping, len, base_flags,
+@@ -11339,6 +11353,38 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
+ 		}
+ 	}
+ 
++	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
++		static struct tg3_dev_id {
++			u32	vendor;
++			u32	device;
++		} bridge_chipsets[] = {
++			{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0 },
++			{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1 },
++			{ },
++		};
++		struct tg3_dev_id *pci_id = &bridge_chipsets[0];
++		struct pci_dev *bridge = NULL;
++
++		while (pci_id->vendor != 0) {
++			bridge = pci_get_device(pci_id->vendor,
++						pci_id->device,
++						bridge);
++			if (!bridge) {
++				pci_id++;
++				continue;
++			}
++			if (bridge->subordinate &&
++			    (bridge->subordinate->number <=
++			     tp->pdev->bus->number) &&
++			    (bridge->subordinate->subordinate >=
++			     tp->pdev->bus->number)) {
++				tp->tg3_flags3 |= TG3_FLG3_5701_DMA_BUG;
++				pci_dev_put(bridge);
++				break;
++			}
++		}
++	}
++
+ 	/* The EPB bridge inside 5714, 5715, and 5780 cannot support
+ 	 * DMA addresses > 40-bit. This bridge may have other additional
+ 	 * 57xx devices behind it in some 4-port NIC designs for example.
+diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
+index c1075a7..c688c3a 100644
+--- a/drivers/net/tg3.h
++++ b/drivers/net/tg3.h
+@@ -2476,6 +2476,7 @@ struct tg3 {
+ #define TG3_FLG3_NO_NVRAM_ADDR_TRANS	0x00000001
+ #define TG3_FLG3_ENABLE_APE		0x00000002
+ #define TG3_FLG3_5761_5784_AX_FIXES	0x00000004
++#define TG3_FLG3_5701_DMA_BUG		0x00000008
+ 
+ 	struct timer_list		timer;
+ 	u16				timer_counter;
+diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
+index 6f33f84..6017d52 100644
+--- a/drivers/net/tsi108_eth.c
++++ b/drivers/net/tsi108_eth.c
+@@ -162,6 +162,7 @@ static struct platform_driver tsi_eth_driver = {
+ 	.remove = tsi108_ether_remove,
+ 	.driver	= {
+ 		.name = "tsi-ethernet",
++		.owner = THIS_MODULE,
+ 	},
+ };
+ 
+@@ -1729,3 +1730,4 @@ module_exit(tsi108_ether_exit);
+ MODULE_AUTHOR("Tundra Semiconductor Corporation");
+ MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:tsi-ethernet");
+diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
+index 20ac150..d913405 100644
+--- a/drivers/net/tulip/Kconfig
++++ b/drivers/net/tulip/Kconfig
+@@ -141,7 +141,7 @@ config ULI526X
+ 	  be called uli526x.
+ 	  
+ config PCMCIA_XIRCOM
+-	tristate "Xircom CardBus support (new driver)"
++	tristate "Xircom CardBus support"
+ 	depends on CARDBUS
+ 	---help---
+ 	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
+@@ -152,17 +152,4 @@ config PCMCIA_XIRCOM
+ 	  To compile this driver as a module, choose M here. The module will
+ 	  be called xircom_cb.  If unsure, say N.
+ 
+-config PCMCIA_XIRTULIP
+-	tristate "Xircom Tulip-like CardBus support (old driver)"
+-	depends on CARDBUS && BROKEN_ON_SMP
+-	select CRC32
+-	---help---
+-	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
+-	  It should work with most DEC 21*4*-based chips/ethercards, as well
+-	  as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
+-	  ASIX.
+-
+-	  To compile this driver as a module, choose M here. The module will
+-	  be called xircom_tulip_cb.  If unsure, say N.
+-
+ endif # NET_TULIP
+diff --git a/drivers/net/tulip/Makefile b/drivers/net/tulip/Makefile
+index 451090d..200cbf7 100644
+--- a/drivers/net/tulip/Makefile
++++ b/drivers/net/tulip/Makefile
+@@ -2,7 +2,6 @@
+ # Makefile for the Linux "Tulip" family network device drivers.
+ #
+ 
+-obj-$(CONFIG_PCMCIA_XIRTULIP)	+= xircom_tulip_cb.o
+ obj-$(CONFIG_PCMCIA_XIRCOM)	+= xircom_cb.o
+ obj-$(CONFIG_DM9102)		+= dmfe.o
+ obj-$(CONFIG_WINBOND_840)	+= winbond-840.o
+diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
+index 3f69f53..908422f 100644
+--- a/drivers/net/tulip/tulip.h
++++ b/drivers/net/tulip/tulip.h
+@@ -268,7 +268,12 @@ enum t21143_csr6_bits {
+ #define RX_RING_SIZE	128
+ #define MEDIA_MASK     31
+ 
+-#define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer. */
++/* The receiver on the DC21143 rev 65 can fail to close the last
++ * receive descriptor in certain circumstances (see errata) when
++ * using MWI. This can only occur if the receive buffer ends on
++ * a cache line boundary, so the "+ 4" below ensures it doesn't.
++ */
++#define PKT_BUF_SZ	(1536 + 4)	/* Size of each temporary Rx buffer. */
+ 
+ #define TULIP_MIN_CACHE_LINE	8	/* in units of 32-bit words */
+ 
+diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
+index 82f404b..fa1c1c3 100644
+--- a/drivers/net/tulip/tulip_core.c
++++ b/drivers/net/tulip/tulip_core.c
+@@ -1154,18 +1154,13 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev,
+ 
+ 	tp->csr0 = csr0 = 0;
+ 
+-	/* if we have any cache line size at all, we can do MRM */
+-	csr0 |= MRM;
++	/* if we have any cache line size at all, we can do MRM and MWI */
++	csr0 |= MRM | MWI;
+ 
+-	/* ...and barring hardware bugs, MWI */
+-	if (!(tp->chip_id == DC21143 && tp->revision == 65))
+-		csr0 |= MWI;
+-
+-	/* set or disable MWI in the standard PCI command bit.
+-	 * Check for the case where  mwi is desired but not available
++	/* Enable MWI in the standard PCI command bit.
++	 * Check for the case where MWI is desired but not available
+ 	 */
+-	if (csr0 & MWI)	pci_try_set_mwi(pdev);
+-	else		pci_clear_mwi(pdev);
++	pci_try_set_mwi(pdev);
+ 
+ 	/* read result from hardware (in case bit refused to enable) */
+ 	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+@@ -1401,10 +1396,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
+ #ifdef CONFIG_TULIP_MWI
+ 	if (!force_csr0 && (tp->flags & HAS_PCI_MWI))
+ 		tulip_mwi_config (pdev, dev);
+-#else
+-	/* MWI is broken for DC21143 rev 65... */
+-	if (chip_idx == DC21143 && pdev->revision == 65)
+-		tp->csr0 &= ~MWI;
+ #endif
+ 
+ 	/* Stop the chip's Tx and Rx processes. */
+diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
+index 35d0cfc..5006819 100644
+--- a/drivers/net/tulip/winbond-840.c
++++ b/drivers/net/tulip/winbond-840.c
+@@ -107,8 +107,6 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ /* Time in jiffies before concluding the transmitter is hung. */
+ #define TX_TIMEOUT  (2*HZ)
+ 
+-#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
+-
+ /* Include files, designed to support most kernel versions 2.0.0 and later. */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+@@ -137,6 +135,9 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ 
+ #include "tulip.h"
+ 
++#undef PKT_BUF_SZ			/* tulip.h also defines this */
++#define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer.*/
++
+ /* These identify the driver base version and may not be removed. */
+ static char version[] =
+ KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE "  Donald Becker <becker at scyld.com>\n"
+diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
+deleted file mode 100644
+index c3f8e30..0000000
+--- a/drivers/net/tulip/xircom_tulip_cb.c
++++ /dev/null
+@@ -1,1726 +0,0 @@
+-/* xircom_tulip_cb.c: A Xircom CBE-100 ethernet driver for Linux. */
+-/*
+-	Written/copyright 1994-1999 by Donald Becker.
+-
+-	This software may be used and distributed according to the terms
+-	of the GNU General Public License, incorporated herein by reference.
+-
+-	The author may be reached as becker at scyld.com, or C/O
+-	Scyld Computing Corporation
+-	410 Severn Ave., Suite 210
+-	Annapolis MD 21403
+-
+-*/
+-
+-#define DRV_NAME	"xircom_tulip_cb"
+-#define DRV_VERSION	"0.92"
+-#define DRV_RELDATE	"June 27, 2006"
+-
+-/* A few user-configurable values. */
+-
+-#define xircom_debug debug
+-#ifdef XIRCOM_DEBUG
+-static int xircom_debug = XIRCOM_DEBUG;
+-#else
+-static int xircom_debug = 1;
+-#endif
+-
+-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+-static int max_interrupt_work = 25;
+-
+-#define MAX_UNITS 4
+-/* Used to pass the full-duplex flag, etc. */
+-static int full_duplex[MAX_UNITS];
+-static int options[MAX_UNITS];
+-static int mtu[MAX_UNITS];			/* Jumbo MTU for interfaces. */
+-
+-/* Keep the ring sizes a power of two for efficiency.
+-   Making the Tx ring too large decreases the effectiveness of channel
+-   bonding and packet priority.
+-   There are no ill effects from too-large receive rings. */
+-#define TX_RING_SIZE	16
+-#define RX_RING_SIZE	32
+-
+-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
+-#ifdef __alpha__
+-static int rx_copybreak = 1518;
+-#else
+-static int rx_copybreak = 100;
+-#endif
+-
+-/*
+-  Set the bus performance register.
+-	Typical: Set 16 longword cache alignment, no burst limit.
+-	Cache alignment bits 15:14	     Burst length 13:8
+-		0000	No alignment  0x00000000 unlimited		0800 8 longwords
+-		4000	8  longwords		0100 1 longword		1000 16 longwords
+-		8000	16 longwords		0200 2 longwords	2000 32 longwords
+-		C000	32  longwords		0400 4 longwords
+-	Warning: many older 486 systems are broken and require setting 0x00A04800
+-	   8 longword cache alignment, 8 longword burst.
+-	ToDo: Non-Intel setting could be better.
+-*/
+-
+-#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
+-static int csr0 = 0x01A00000 | 0xE000;
+-#elif defined(__powerpc__)
+-static int csr0 = 0x01B00000 | 0x8000;
+-#elif defined(CONFIG_SPARC)
+-static int csr0 = 0x01B00080 | 0x8000;
+-#elif defined(__i386__)
+-static int csr0 = 0x01A00000 | 0x8000;
+-#else
+-#warning Processor architecture undefined!
+-static int csr0 = 0x00A00000 | 0x4800;
+-#endif
+-
+-/* Operational parameters that usually are not changed. */
+-/* Time in jiffies before concluding the transmitter is hung. */
+-#define TX_TIMEOUT		(4 * HZ)
+-#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
+-#define PKT_SETUP_SZ		192			/* Size of the setup frame */
+-
+-/* PCI registers */
+-#define PCI_POWERMGMT 	0x40
+-
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/kernel.h>
+-#include <linux/pci.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/delay.h>
+-#include <linux/init.h>
+-#include <linux/mii.h>
+-#include <linux/ethtool.h>
+-#include <linux/crc32.h>
+-
+-#include <asm/io.h>
+-#include <asm/processor.h>	/* Processor type for cache alignment. */
+-#include <asm/uaccess.h>
+-
+-
+-/* These identify the driver base version and may not be removed. */
+-static char version[] __devinitdata =
+-KERN_INFO DRV_NAME ".c derived from tulip.c:v0.91 4/14/99 becker at scyld.com\n"
+-KERN_INFO " unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE "\n";
+-
+-MODULE_AUTHOR("Donald Becker <becker at scyld.com>");
+-MODULE_DESCRIPTION("Xircom CBE-100 ethernet driver");
+-MODULE_LICENSE("GPL v2");
+-MODULE_VERSION(DRV_VERSION);
+-
+-module_param(debug, int, 0);
+-module_param(max_interrupt_work, int, 0);
+-module_param(rx_copybreak, int, 0);
+-module_param(csr0, int, 0);
+-
+-module_param_array(options, int, NULL, 0);
+-module_param_array(full_duplex, int, NULL, 0);
+-
+-#define RUN_AT(x) (jiffies + (x))
+-
+-/*
+-				Theory of Operation
+-
+-I. Board Compatibility
+-
+-This device driver was forked from the driver for the DECchip "Tulip",
+-Digital's single-chip ethernet controllers for PCI.  It supports Xircom's
+-almost-Tulip-compatible CBE-100 CardBus adapters.
+-
+-II. Board-specific settings
+-
+-PCI bus devices are configured by the system at boot time, so no jumpers
+-need to be set on the board.  The system BIOS preferably should assign the
+-PCI INTA signal to an otherwise unused system IRQ line.
+-
+-III. Driver operation
+-
+-IIIa. Ring buffers
+-
+-The Xircom can use either ring buffers or lists of Tx and Rx descriptors.
+-This driver uses statically allocated rings of Rx and Tx descriptors, set at
+-compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
+-for the Rx ring buffers at open() time and passes the skb->data field to the
+-Xircom as receive data buffers.  When an incoming frame is less than
+-RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
+-copied to the new skbuff.  When the incoming frame is larger, the skbuff is
+-passed directly up the protocol stack and replaced by a newly allocated
+-skbuff.
+-
+-The RX_COPYBREAK value is chosen to trade-off the memory wasted by
+-using a full-sized skbuff for small frames vs. the copying costs of larger
+-frames.  For small frames the copying cost is negligible (esp. considering
+-that we are pre-loading the cache with immediately useful header
+-information).  For large frames the copying cost is non-trivial, and the
+-larger copy might flush the cache of useful data.  A subtle aspect of this
+-choice is that the Xircom only receives into longword aligned buffers, thus
+-the IP header at offset 14 isn't longword aligned for further processing.
+-Copied frames are put into the new skbuff at an offset of "+2", thus copying
+-has the beneficial effect of aligning the IP header and preloading the
+-cache.
+-
+-IIIC. Synchronization
+-The driver runs as two independent, single-threaded flows of control.  One
+-is the send-packet routine, which enforces single-threaded use by the
+-dev->tbusy flag.  The other thread is the interrupt handler, which is single
+-threaded by the hardware and other software.
+-
+-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
+-flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
+-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
+-the 'tp->tx_full' flag.
+-
+-The interrupt handler has exclusive control over the Rx ring and records stats
+-from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
+-we can't avoid the interrupt overhead by having the Tx routine reap the Tx
+-stats.)	 After reaping the stats, it marks the queue entry as empty by setting
+-the 'base' to zero.	 Iff the 'tp->tx_full' flag is set, it clears both the
+-tx_full and tbusy flags.
+-
+-IV. Notes
+-
+-IVb. References
+-
+-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+-http://www.digital.com  (search for current 21*4* datasheets and "21X4 SROM")
+-http://www.national.com/pf/DP/DP83840A.html
+-
+-IVc. Errata
+-
+-*/
+-
+-/* A full-duplex map for media types. */
+-enum MediaIs {
+-	MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
+-	MediaIs100=16};
+-static const char media_cap[] =
+-{0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20 };
+-
+-/* Offsets to the Command and Status Registers, "CSRs".  All accesses
+-   must be longword instructions and quadword aligned. */
+-enum xircom_offsets {
+-	CSR0=0,    CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
+-	CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
+-	CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x04, };
+-
+-/* The bits in the CSR5 status registers, mostly interrupt sources. */
+-enum status_bits {
+-	LinkChange=0x08000000,
+-	NormalIntr=0x10000, NormalIntrMask=0x00014045,
+-	AbnormalIntr=0x8000, AbnormalIntrMask=0x0a00a5a2,
+-	ReservedIntrMask=0xe0001a18,
+-	EarlyRxIntr=0x4000, BusErrorIntr=0x2000,
+-	EarlyTxIntr=0x400, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
+-	TxFIFOUnderflow=0x20, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
+-};
+-
+-enum csr0_control_bits {
+-	EnableMWI=0x01000000, EnableMRL=0x00800000,
+-	EnableMRM=0x00200000, EqualBusPrio=0x02,
+-	SoftwareReset=0x01,
+-};
+-
+-enum csr6_control_bits {
+-	ReceiveAllBit=0x40000000, AllMultiBit=0x80, PromiscBit=0x40,
+-	HashFilterBit=0x01, FullDuplexBit=0x0200,
+-	TxThresh10=0x400000, TxStoreForw=0x200000,
+-	TxThreshMask=0xc000, TxThreshShift=14,
+-	EnableTx=0x2000, EnableRx=0x02,
+-	ReservedZeroMask=0x8d930134, ReservedOneMask=0x320c0000,
+-	EnableTxRx=(EnableTx | EnableRx),
+-};
+-
+-
+-enum tbl_flag {
+-	HAS_MII=1, HAS_ACPI=2,
+-};
+-static struct xircom_chip_table {
+-	char *chip_name;
+-	int valid_intrs;			/* CSR7 interrupt enable settings */
+-	int flags;
+-} xircom_tbl[] = {
+-  { "Xircom Cardbus Adapter",
+-	LinkChange | NormalIntr | AbnormalIntr | BusErrorIntr |
+-	RxDied | RxNoBuf | RxIntr | TxFIFOUnderflow | TxNoBuf | TxDied | TxIntr,
+-	HAS_MII | HAS_ACPI, },
+-  { NULL, },
+-};
+-/* This matches the table above. */
+-enum chips {
+-	X3201_3,
+-};
+-
+-
+-/* The Xircom Rx and Tx buffer descriptors. */
+-struct xircom_rx_desc {
+-	s32 status;
+-	s32 length;
+-	u32 buffer1, buffer2;
+-};
+-
+-struct xircom_tx_desc {
+-	s32 status;
+-	s32 length;
+-	u32 buffer1, buffer2;				/* We use only buffer 1.  */
+-};
+-
+-enum tx_desc0_status_bits {
+-	Tx0DescOwned=0x80000000, Tx0DescError=0x8000, Tx0NoCarrier=0x0800,
+-	Tx0LateColl=0x0200, Tx0ManyColl=0x0100, Tx0Underflow=0x02,
+-};
+-enum tx_desc1_status_bits {
+-	Tx1ComplIntr=0x80000000, Tx1LastSeg=0x40000000, Tx1FirstSeg=0x20000000,
+-	Tx1SetupPkt=0x08000000, Tx1DisableCRC=0x04000000, Tx1RingWrap=0x02000000,
+-	Tx1ChainDesc=0x01000000, Tx1NoPad=0x800000, Tx1HashSetup=0x400000,
+-	Tx1WholePkt=(Tx1FirstSeg | Tx1LastSeg),
+-};
+-enum rx_desc0_status_bits {
+-	Rx0DescOwned=0x80000000, Rx0DescError=0x8000, Rx0NoSpace=0x4000,
+-	Rx0Runt=0x0800, Rx0McastPkt=0x0400, Rx0FirstSeg=0x0200, Rx0LastSeg=0x0100,
+-	Rx0HugeFrame=0x80, Rx0CRCError=0x02,
+-	Rx0WholePkt=(Rx0FirstSeg | Rx0LastSeg),
+-};
+-enum rx_desc1_status_bits {
+-	Rx1RingWrap=0x02000000, Rx1ChainDesc=0x01000000,
+-};
+-
+-struct xircom_private {
+-	struct xircom_rx_desc rx_ring[RX_RING_SIZE];
+-	struct xircom_tx_desc tx_ring[TX_RING_SIZE];
+-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+-	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+-
+-	/* The X3201-3 requires 4-byte aligned tx bufs */
+-	struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE];
+-
+-	/* The addresses of receive-in-place skbuffs. */
+-	struct sk_buff* rx_skbuff[RX_RING_SIZE];
+-	u16 setup_frame[PKT_SETUP_SZ / sizeof(u16)];	/* Pseudo-Tx frame to init address table. */
+-	int chip_id;
+-	struct net_device_stats stats;
+-	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
+-	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
+-	unsigned int tx_full:1;				/* The Tx queue is full. */
+-	unsigned int speed100:1;
+-	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
+-	unsigned int autoneg:1;
+-	unsigned int default_port:4;		/* Last dev->if_port value. */
+-	unsigned int open:1;
+-	unsigned int csr0;					/* CSR0 setting. */
+-	unsigned int csr6;					/* Current CSR6 control settings. */
+-	u16 to_advertise;					/* NWay capabilities advertised.  */
+-	u16 advertising[4];
+-	signed char phys[4], mii_cnt;		/* MII device addresses. */
+-	int saved_if_port;
+-	struct pci_dev *pdev;
+-	spinlock_t lock;
+-};
+-
+-static int mdio_read(struct net_device *dev, int phy_id, int location);
+-static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
+-static void xircom_up(struct net_device *dev);
+-static void xircom_down(struct net_device *dev);
+-static int xircom_open(struct net_device *dev);
+-static void xircom_tx_timeout(struct net_device *dev);
+-static void xircom_init_ring(struct net_device *dev);
+-static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev);
+-static int xircom_rx(struct net_device *dev);
+-static void xircom_media_change(struct net_device *dev);
+-static irqreturn_t xircom_interrupt(int irq, void *dev_instance);
+-static int xircom_close(struct net_device *dev);
+-static struct net_device_stats *xircom_get_stats(struct net_device *dev);
+-static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+-static void set_rx_mode(struct net_device *dev);
+-static void check_duplex(struct net_device *dev);
+-static const struct ethtool_ops ops;
+-
+-
+-/* The Xircom cards are picky about when certain bits in CSR6 can be
+-   manipulated.  Keith Owens <kaos at ocs.com.au>. */
+-static void outl_CSR6(u32 newcsr6, long ioaddr)
+-{
+-	const int strict_bits =
+-		TxThresh10 | TxStoreForw | TxThreshMask | EnableTxRx | FullDuplexBit;
+-    int csr5, csr5_22_20, csr5_19_17, currcsr6, attempts = 200;
+-    unsigned long flags;
+-    save_flags(flags);
+-    cli();
+-	/* mask out the reserved bits that always read 0 on the Xircom cards */
+-	newcsr6 &= ~ReservedZeroMask;
+-	/* or in the reserved bits that always read 1 */
+-	newcsr6 |= ReservedOneMask;
+-    currcsr6 = inl(ioaddr + CSR6);
+-    if (((newcsr6 & strict_bits) == (currcsr6 & strict_bits)) ||
+-	((currcsr6 & ~EnableTxRx) == 0)) {
+-		outl(newcsr6, ioaddr + CSR6);	/* safe */
+-		restore_flags(flags);
+-		return;
+-    }
+-    /* make sure the transmitter and receiver are stopped first */
+-    currcsr6 &= ~EnableTxRx;
+-    while (1) {
+-		csr5 = inl(ioaddr + CSR5);
+-		if (csr5 == 0xffffffff)
+-			break;  /* cannot read csr5, card removed? */
+-		csr5_22_20 = csr5 & 0x700000;
+-		csr5_19_17 = csr5 & 0x0e0000;
+-		if ((csr5_22_20 == 0 || csr5_22_20 == 0x600000) &&
+-			(csr5_19_17 == 0 || csr5_19_17 == 0x80000 || csr5_19_17 == 0xc0000))
+-			break;  /* both are stopped or suspended */
+-		if (!--attempts) {
+-			printk(KERN_INFO DRV_NAME ": outl_CSR6 too many attempts,"
+-				   "csr5=0x%08x\n", csr5);
+-			outl(newcsr6, ioaddr + CSR6);  /* unsafe but do it anyway */
+-			restore_flags(flags);
+-			return;
+-		}
+-		outl(currcsr6, ioaddr + CSR6);
+-		udelay(1);
+-    }
+-    /* now it is safe to change csr6 */
+-    outl(newcsr6, ioaddr + CSR6);
+-    restore_flags(flags);
+-}
+-
+-
+-static void __devinit read_mac_address(struct net_device *dev)
+-{
+-	long ioaddr = dev->base_addr;
+-	int i, j;
+-	unsigned char tuple, link, data_id, data_count;
+-
+-	/* Xircom has its address stored in the CIS;
+-	 * we access it through the boot rom interface for now
+-	 * this might not work, as the CIS is not parsed but I
+-	 * (danilo) use the offset I found on my card's CIS !!!
+-	 *
+-	 * Doug Ledford: I changed this routine around so that it
+-	 * walks the CIS memory space, parsing the config items, and
+-	 * finds the proper lan_node_id tuple and uses the data
+-	 * stored there.
+-	 */
+-	outl(1 << 12, ioaddr + CSR9); /* enable boot rom access */
+-	for (i = 0x100; i < 0x1f7; i += link+2) {
+-		outl(i, ioaddr + CSR10);
+-		tuple = inl(ioaddr + CSR9) & 0xff;
+-		outl(i + 1, ioaddr + CSR10);
+-		link = inl(ioaddr + CSR9) & 0xff;
+-		outl(i + 2, ioaddr + CSR10);
+-		data_id = inl(ioaddr + CSR9) & 0xff;
+-		outl(i + 3, ioaddr + CSR10);
+-		data_count = inl(ioaddr + CSR9) & 0xff;
+-		if ( (tuple == 0x22) &&
+-			 (data_id == 0x04) && (data_count == 0x06) ) {
+-			/*
+-			 * This is it.  We have the data we want.
+-			 */
+-			for (j = 0; j < 6; j++) {
+-				outl(i + j + 4, ioaddr + CSR10);
+-				dev->dev_addr[j] = inl(ioaddr + CSR9) & 0xff;
+-			}
+-			break;
+-		} else if (link == 0) {
+-			break;
+-		}
+-	}
+-}
+-
+-
+-/*
+- * locate the MII interfaces and initialize them.
+- * we disable full-duplex modes here,
+- * because we don't know how to handle them.
+- */
+-static void find_mii_transceivers(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	int phy, phy_idx;
+-
+-	if (media_cap[tp->default_port] & MediaIsMII) {
+-		u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
+-		tp->to_advertise = media2advert[tp->default_port - 9];
+-	} else
+-		tp->to_advertise =
+-			/*ADVERTISE_100BASE4 | ADVERTISE_100FULL |*/ ADVERTISE_100HALF |
+-			/*ADVERTISE_10FULL |*/ ADVERTISE_10HALF | ADVERTISE_CSMA;
+-
+-	/* Find the connected MII xcvrs.
+-	   Doing this in open() would allow detecting external xcvrs later,
+-	   but takes much time. */
+-	for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) {
+-		int mii_status = mdio_read(dev, phy, MII_BMSR);
+-		if ((mii_status & (BMSR_100BASE4 | BMSR_100HALF | BMSR_10HALF)) == BMSR_100BASE4 ||
+-			((mii_status & BMSR_100BASE4) == 0 &&
+-			 (mii_status & (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | BMSR_10HALF)) != 0)) {
+-			int mii_reg0 = mdio_read(dev, phy, MII_BMCR);
+-			int mii_advert = mdio_read(dev, phy, MII_ADVERTISE);
+-			int reg4 = ((mii_status >> 6) & tp->to_advertise) | ADVERTISE_CSMA;
+-			tp->phys[phy_idx] = phy;
+-			tp->advertising[phy_idx++] = reg4;
+-			printk(KERN_INFO "%s:  MII transceiver #%d "
+-				   "config %4.4x status %4.4x advertising %4.4x.\n",
+-				   dev->name, phy, mii_reg0, mii_status, mii_advert);
+-		}
+-	}
+-	tp->mii_cnt = phy_idx;
+-	if (phy_idx == 0) {
+-		printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
+-			   dev->name);
+-		tp->phys[0] = 0;
+-	}
+-}
+-
+-
+-/*
+- * To quote Arjan van de Ven:
+- *   transceiver_voodoo() enables the external UTP plug thingy.
+- *   it's called voodoo as I stole this code and cannot cross-reference
+- *   it with the specification.
+- * Actually it seems to go like this:
+- * - GPIO2 enables the MII itself so we can talk to it. The MII gets reset
+- *   so any prior MII settings are lost.
+- * - GPIO0 enables the TP port so the MII can talk to the network.
+- * - a software reset will reset both GPIO pins.
+- * I also moved the software reset here, because doing it in xircom_up()
+- * required enabling the GPIO pins each time, which reset the MII each time.
+- * Thus we couldn't control the MII -- which sucks because we don't know
+- * how to handle full-duplex modes so we *must* disable them.
+- */
+-static void transceiver_voodoo(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	long ioaddr = dev->base_addr;
+-
+-	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
+-	outl(SoftwareReset, ioaddr + CSR0);
+-	udelay(2);
+-
+-	/* Deassert reset. */
+-	outl(tp->csr0, ioaddr + CSR0);
+-
+-	/* Reset the xcvr interface and turn on heartbeat. */
+-	outl(0x0008, ioaddr + CSR15);
+-	udelay(5);  /* The delays are Xircom-recommended to give the
+-				 * chipset time to reset the actual hardware
+-				 * on the PCMCIA card
+-				 */
+-	outl(0xa8050000, ioaddr + CSR15);
+-	udelay(5);
+-	outl(0xa00f0000, ioaddr + CSR15);
+-	udelay(5);
+-
+-	outl_CSR6(0, ioaddr);
+-	//outl_CSR6(FullDuplexBit, ioaddr);
+-}
+-
+-
+-static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+-{
+-	struct net_device *dev;
+-	struct xircom_private *tp;
+-	static int board_idx = -1;
+-	int chip_idx = id->driver_data;
+-	long ioaddr;
+-	int i;
+-
+-/* when built into the kernel, we only print version if device is found */
+-#ifndef MODULE
+-	static int printed_version;
+-	if (!printed_version++)
+-		printk(version);
+-#endif
+-
+-	//printk(KERN_INFO "xircom_init_one(%s)\n", pci_name(pdev));
+-
+-	board_idx++;
+-
+-	if (pci_enable_device(pdev))
+-		return -ENODEV;
+-
+-	pci_set_master(pdev);
+-
+-	ioaddr = pci_resource_start(pdev, 0);
+-	dev = alloc_etherdev(sizeof(*tp));
+-	if (!dev) {
+-		printk (KERN_ERR DRV_NAME "%d: cannot alloc etherdev, aborting\n", board_idx);
+-		return -ENOMEM;
+-	}
+-	SET_NETDEV_DEV(dev, &pdev->dev);
+-
+-	dev->base_addr = ioaddr;
+-	dev->irq = pdev->irq;
+-
+-	if (pci_request_regions(pdev, dev->name)) {
+-		printk (KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", board_idx);
+-		goto err_out_free_netdev;
+-	}
+-
+-	/* Bring the chip out of sleep mode.
+-	   Caution: Snooze mode does not work with some boards! */
+-	if (xircom_tbl[chip_idx].flags & HAS_ACPI)
+-		pci_write_config_dword(pdev, PCI_POWERMGMT, 0);
+-
+-	/* Stop the chip's Tx and Rx processes. */
+-	outl_CSR6(inl(ioaddr + CSR6) & ~EnableTxRx, ioaddr);
+-	/* Clear the missed-packet counter. */
+-	(volatile int)inl(ioaddr + CSR8);
+-
+-	tp = netdev_priv(dev);
+-
+-	spin_lock_init(&tp->lock);
+-	tp->pdev = pdev;
+-	tp->chip_id = chip_idx;
+-	/* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. */
+-	/* XXX: is this necessary for Xircom? */
+-	tp->csr0 = csr0 & ~EnableMWI;
+-
+-	pci_set_drvdata(pdev, dev);
+-
+-	/* The lower four bits are the media type. */
+-	if (board_idx >= 0 && board_idx < MAX_UNITS) {
+-		tp->default_port = options[board_idx] & 15;
+-		if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0)
+-			tp->full_duplex = 1;
+-		if (mtu[board_idx] > 0)
+-			dev->mtu = mtu[board_idx];
+-	}
+-	if (dev->mem_start)
+-		tp->default_port = dev->mem_start;
+-	if (tp->default_port) {
+-		if (media_cap[tp->default_port] & MediaAlwaysFD)
+-			tp->full_duplex = 1;
+-	}
+-	if (tp->full_duplex)
+-		tp->autoneg = 0;
+-	else
+-		tp->autoneg = 1;
+-	tp->speed100 = 1;
+-
+-	/* The Xircom-specific entries in the device structure. */
+-	dev->open = &xircom_open;
+-	dev->hard_start_xmit = &xircom_start_xmit;
+-	dev->stop = &xircom_close;
+-	dev->get_stats = &xircom_get_stats;
+-	dev->do_ioctl = &xircom_ioctl;
+-#ifdef HAVE_MULTICAST
+-	dev->set_multicast_list = &set_rx_mode;
+-#endif
+-	dev->tx_timeout = xircom_tx_timeout;
+-	dev->watchdog_timeo = TX_TIMEOUT;
+-	SET_ETHTOOL_OPS(dev, &ops);
+-
+-	transceiver_voodoo(dev);
+-
+-	read_mac_address(dev);
+-
+-	if (register_netdev(dev))
+-		goto err_out_cleardev;
+-
+-	printk(KERN_INFO "%s: %s rev %d at %#3lx,",
+-	       dev->name, xircom_tbl[chip_idx].chip_name, pdev->revision, ioaddr);
+-	for (i = 0; i < 6; i++)
+-		printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
+-	printk(", IRQ %d.\n", dev->irq);
+-
+-	if (xircom_tbl[chip_idx].flags & HAS_MII) {
+-		find_mii_transceivers(dev);
+-		check_duplex(dev);
+-	}
+-
+-	return 0;
+-
+-err_out_cleardev:
+-	pci_set_drvdata(pdev, NULL);
+-	pci_release_regions(pdev);
+-err_out_free_netdev:
+-	free_netdev(dev);
+-	return -ENODEV;
+-}
+-
+-
+-/* MII transceiver control section.
+-   Read and write the MII registers using software-generated serial
+-   MDIO protocol.  See the MII specifications or DP83840A data sheet
+-   for details. */
+-
+-/* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
+-   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+-   "overclocking" issues or future 66Mhz PCI. */
+-#define mdio_delay() inl(mdio_addr)
+-
+-/* Read and write the MII registers using software-generated serial
+-   MDIO protocol.  It is just different enough from the EEPROM protocol
+-   to not share code.  The maxium data clock rate is 2.5 Mhz. */
+-#define MDIO_SHIFT_CLK	0x10000
+-#define MDIO_DATA_WRITE0 0x00000
+-#define MDIO_DATA_WRITE1 0x20000
+-#define MDIO_ENB		0x00000		/* Ignore the 0x02000 databook setting. */
+-#define MDIO_ENB_IN		0x40000
+-#define MDIO_DATA_READ	0x80000
+-
+-static int mdio_read(struct net_device *dev, int phy_id, int location)
+-{
+-	int i;
+-	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+-	int retval = 0;
+-	long ioaddr = dev->base_addr;
+-	long mdio_addr = ioaddr + CSR9;
+-
+-	/* Establish sync by sending at least 32 logic ones. */
+-	for (i = 32; i >= 0; i--) {
+-		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+-		mdio_delay();
+-		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+-		mdio_delay();
+-	}
+-	/* Shift the read command bits out. */
+-	for (i = 15; i >= 0; i--) {
+-		int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+-
+-		outl(MDIO_ENB | dataval, mdio_addr);
+-		mdio_delay();
+-		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+-		mdio_delay();
+-	}
+-	/* Read the two transition, 16 data, and wire-idle bits. */
+-	for (i = 19; i > 0; i--) {
+-		outl(MDIO_ENB_IN, mdio_addr);
+-		mdio_delay();
+-		retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+-		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+-		mdio_delay();
+-	}
+-	return (retval>>1) & 0xffff;
+-}
+-
+-
+-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
+-{
+-	int i;
+-	int cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
+-	long ioaddr = dev->base_addr;
+-	long mdio_addr = ioaddr + CSR9;
+-
+-	/* Establish sync by sending 32 logic ones. */
+-	for (i = 32; i >= 0; i--) {
+-		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+-		mdio_delay();
+-		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+-		mdio_delay();
+-	}
+-	/* Shift the command bits out. */
+-	for (i = 31; i >= 0; i--) {
+-		int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+-		outl(MDIO_ENB | dataval, mdio_addr);
+-		mdio_delay();
+-		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+-		mdio_delay();
+-	}
+-	/* Clear out extra bits. */
+-	for (i = 2; i > 0; i--) {
+-		outl(MDIO_ENB_IN, mdio_addr);
+-		mdio_delay();
+-		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+-		mdio_delay();
+-	}
+-	return;
+-}
+-
+-
+-static void
+-xircom_up(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	long ioaddr = dev->base_addr;
+-	int i;
+-
+-	xircom_init_ring(dev);
+-	/* Clear the tx ring */
+-	for (i = 0; i < TX_RING_SIZE; i++) {
+-		tp->tx_skbuff[i] = NULL;
+-		tp->tx_ring[i].status = 0;
+-	}
+-
+-	if (xircom_debug > 1)
+-		printk(KERN_DEBUG "%s: xircom_up() irq %d.\n", dev->name, dev->irq);
+-
+-	outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3);
+-	outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);
+-
+-	tp->saved_if_port = dev->if_port;
+-	if (dev->if_port == 0)
+-		dev->if_port = tp->default_port;
+-
+-	tp->csr6 = TxThresh10 /*| FullDuplexBit*/;						/* XXX: why 10 and not 100? */
+-
+-	set_rx_mode(dev);
+-
+-	/* Start the chip's Tx to process setup frame. */
+-	outl_CSR6(tp->csr6, ioaddr);
+-	outl_CSR6(tp->csr6 | EnableTx, ioaddr);
+-
+-	/* Acknowledge all outstanding interrupts sources */
+-	outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
+-	/* Enable interrupts by setting the interrupt mask. */
+-	outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+-	/* Enable Rx */
+-	outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+-	/* Rx poll demand */
+-	outl(0, ioaddr + CSR2);
+-
+-	/* Tell the net layer we're ready */
+-	netif_start_queue (dev);
+-
+-	/* Check current media state */
+-	xircom_media_change(dev);
+-
+-	if (xircom_debug > 2) {
+-		printk(KERN_DEBUG "%s: Done xircom_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",
+-			   dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5),
+-			   inl(ioaddr + CSR6));
+-	}
+-}
+-
+-
+-static int
+-xircom_open(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-
+-	if (request_irq(dev->irq, &xircom_interrupt, IRQF_SHARED, dev->name, dev))
+-		return -EAGAIN;
+-
+-	xircom_up(dev);
+-	tp->open = 1;
+-
+-	return 0;
+-}
+-
+-
+-static void xircom_tx_timeout(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	long ioaddr = dev->base_addr;
+-
+-	if (media_cap[dev->if_port] & MediaIsMII) {
+-		/* Do nothing -- the media monitor should handle this. */
+-		if (xircom_debug > 1)
+-			printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
+-				   dev->name);
+-	}
+-
+-#if defined(way_too_many_messages)
+-	if (xircom_debug > 3) {
+-		int i;
+-		for (i = 0; i < RX_RING_SIZE; i++) {
+-			u8 *buf = (u8 *)(tp->rx_ring[i].buffer1);
+-			int j;
+-			printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x  "
+-				   "%2.2x %2.2x %2.2x.\n",
+-				   i, (unsigned int)tp->rx_ring[i].status,
+-				   (unsigned int)tp->rx_ring[i].length,
+-				   (unsigned int)tp->rx_ring[i].buffer1,
+-				   (unsigned int)tp->rx_ring[i].buffer2,
+-				   buf[0], buf[1], buf[2]);
+-			for (j = 0; buf[j] != 0xee && j < 1600; j++)
+-				if (j < 100) printk(" %2.2x", buf[j]);
+-			printk(" j=%d.\n", j);
+-		}
+-		printk(KERN_DEBUG "  Rx ring %8.8x: ", (int)tp->rx_ring);
+-		for (i = 0; i < RX_RING_SIZE; i++)
+-			printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
+-		printk("\n" KERN_DEBUG "  Tx ring %8.8x: ", (int)tp->tx_ring);
+-		for (i = 0; i < TX_RING_SIZE; i++)
+-			printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
+-		printk("\n");
+-	}
+-#endif
+-
+-	/* Stop and restart the chip's Tx/Rx processes . */
+-	outl_CSR6(tp->csr6 | EnableRx, ioaddr);
+-	outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+-	/* Trigger an immediate transmit demand. */
+-	outl(0, ioaddr + CSR1);
+-
+-	dev->trans_start = jiffies;
+-	netif_wake_queue (dev);
+-	tp->stats.tx_errors++;
+-}
+-
+-
+-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+-static void xircom_init_ring(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	int i;
+-
+-	tp->tx_full = 0;
+-	tp->cur_rx = tp->cur_tx = 0;
+-	tp->dirty_rx = tp->dirty_tx = 0;
+-
+-	for (i = 0; i < RX_RING_SIZE; i++) {
+-		tp->rx_ring[i].status = 0;
+-		tp->rx_ring[i].length = PKT_BUF_SZ;
+-		tp->rx_ring[i].buffer2 = virt_to_bus(&tp->rx_ring[i+1]);
+-		tp->rx_skbuff[i] = NULL;
+-	}
+-	/* Mark the last entry as wrapping the ring. */
+-	tp->rx_ring[i-1].length = PKT_BUF_SZ | Rx1RingWrap;
+-	tp->rx_ring[i-1].buffer2 = virt_to_bus(&tp->rx_ring[0]);
+-
+-	for (i = 0; i < RX_RING_SIZE; i++) {
+-		/* Note the receive buffer must be longword aligned.
+-		   dev_alloc_skb() provides 16 byte alignment.  But do *not*
+-		   use skb_reserve() to align the IP header! */
+-		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+-		tp->rx_skbuff[i] = skb;
+-		if (skb == NULL)
+-			break;
+-		skb->dev = dev;			/* Mark as being used by this device. */
+-		tp->rx_ring[i].status = Rx0DescOwned;	/* Owned by Xircom chip */
+-		tp->rx_ring[i].buffer1 = virt_to_bus(skb->data);
+-	}
+-	tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
+-
+-	/* The Tx buffer descriptor is filled in as needed, but we
+-	   do need to clear the ownership bit. */
+-	for (i = 0; i < TX_RING_SIZE; i++) {
+-		tp->tx_skbuff[i] = NULL;
+-		tp->tx_ring[i].status = 0;
+-		tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]);
+-		if (tp->chip_id == X3201_3)
+-			tp->tx_aligned_skbuff[i] = dev_alloc_skb(PKT_BUF_SZ);
+-	}
+-	tp->tx_ring[i-1].buffer2 = virt_to_bus(&tp->tx_ring[0]);
+-}
+-
+-
+-static int
+-xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	int entry;
+-	u32 flag;
+-
+-	/* Caution: the write order is important here, set the base address
+-	   with the "ownership" bits last. */
+-
+-	/* Calculate the next Tx descriptor entry. */
+-	entry = tp->cur_tx % TX_RING_SIZE;
+-
+-	tp->tx_skbuff[entry] = skb;
+-	if (tp->chip_id == X3201_3) {
+-		skb_copy_from_linear_data(skb,
+-					  tp->tx_aligned_skbuff[entry]->data,
+-					  skb->len);
+-		tp->tx_ring[entry].buffer1 = virt_to_bus(tp->tx_aligned_skbuff[entry]->data);
+-	} else
+-		tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data);
+-
+-	if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
+-		flag = Tx1WholePkt; /* No interrupt */
+-	} else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
+-		flag = Tx1WholePkt | Tx1ComplIntr; /* Tx-done intr. */
+-	} else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
+-		flag = Tx1WholePkt; /* No Tx-done intr. */
+-	} else {
+-		/* Leave room for set_rx_mode() to fill entries. */
+-		flag = Tx1WholePkt | Tx1ComplIntr; /* Tx-done intr. */
+-		tp->tx_full = 1;
+-	}
+-	if (entry == TX_RING_SIZE - 1)
+-		flag |= Tx1WholePkt | Tx1ComplIntr | Tx1RingWrap;
+-
+-	tp->tx_ring[entry].length = skb->len | flag;
+-	tp->tx_ring[entry].status = Tx0DescOwned;	/* Pass ownership to the chip. */
+-	tp->cur_tx++;
+-	if (tp->tx_full)
+-		netif_stop_queue (dev);
+-	else
+-		netif_wake_queue (dev);
+-
+-	/* Trigger an immediate transmit demand. */
+-	outl(0, dev->base_addr + CSR1);
+-
+-	dev->trans_start = jiffies;
+-
+-	return 0;
+-}
+-
+-
+-static void xircom_media_change(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	long ioaddr = dev->base_addr;
+-	u16 reg0, reg1, reg4, reg5;
+-	u32 csr6 = inl(ioaddr + CSR6), newcsr6;
+-
+-	/* reset status first */
+-	mdio_read(dev, tp->phys[0], MII_BMCR);
+-	mdio_read(dev, tp->phys[0], MII_BMSR);
+-
+-	reg0 = mdio_read(dev, tp->phys[0], MII_BMCR);
+-	reg1 = mdio_read(dev, tp->phys[0], MII_BMSR);
+-
+-	if (reg1 & BMSR_LSTATUS) {
+-		/* link is up */
+-		if (reg0 & BMCR_ANENABLE) {
+-			/* autonegotiation is enabled */
+-			reg4 = mdio_read(dev, tp->phys[0], MII_ADVERTISE);
+-			reg5 = mdio_read(dev, tp->phys[0], MII_LPA);
+-			if (reg4 & ADVERTISE_100FULL && reg5 & LPA_100FULL) {
+-				tp->speed100 = 1;
+-				tp->full_duplex = 1;
+-			} else if (reg4 & ADVERTISE_100HALF && reg5 & LPA_100HALF) {
+-				tp->speed100 = 1;
+-				tp->full_duplex = 0;
+-			} else if (reg4 & ADVERTISE_10FULL && reg5 & LPA_10FULL) {
+-				tp->speed100 = 0;
+-				tp->full_duplex = 1;
+-			} else {
+-				tp->speed100 = 0;
+-				tp->full_duplex = 0;
+-			}
+-		} else {
+-			/* autonegotiation is disabled */
+-			if (reg0 & BMCR_SPEED100)
+-				tp->speed100 = 1;
+-			else
+-				tp->speed100 = 0;
+-			if (reg0 & BMCR_FULLDPLX)
+-				tp->full_duplex = 1;
+-			else
+-				tp->full_duplex = 0;
+-		}
+-		printk(KERN_DEBUG "%s: Link is up, running at %sMbit %s-duplex\n",
+-		       dev->name,
+-		       tp->speed100 ? "100" : "10",
+-		       tp->full_duplex ? "full" : "half");
+-		netif_carrier_on(dev);
+-		newcsr6 = csr6 & ~FullDuplexBit;
+-		if (tp->full_duplex)
+-			newcsr6 |= FullDuplexBit;
+-		if (newcsr6 != csr6)
+-			outl_CSR6(newcsr6, ioaddr + CSR6);
+-	} else {
+-		printk(KERN_DEBUG "%s: Link is down\n", dev->name);
+-		netif_carrier_off(dev);
+-	}
+-}
+-
+-
+-static void check_duplex(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	u16 reg0;
+-
+-	mdio_write(dev, tp->phys[0], MII_BMCR, BMCR_RESET);
+-	udelay(500);
+-	while (mdio_read(dev, tp->phys[0], MII_BMCR) & BMCR_RESET);
+-
+-	reg0 = mdio_read(dev, tp->phys[0], MII_BMCR);
+-	mdio_write(dev, tp->phys[0], MII_ADVERTISE, tp->advertising[0]);
+-
+-	if (tp->autoneg) {
+-		reg0 &= ~(BMCR_SPEED100 | BMCR_FULLDPLX);
+-		reg0 |= BMCR_ANENABLE | BMCR_ANRESTART;
+-	} else {
+-		reg0 &= ~(BMCR_ANENABLE | BMCR_ANRESTART);
+-		if (tp->speed100)
+-			reg0 |= BMCR_SPEED100;
+-		if (tp->full_duplex)
+-			reg0 |= BMCR_FULLDPLX;
+-		printk(KERN_DEBUG "%s: Link forced to %sMbit %s-duplex\n",
+-		       dev->name,
+-		       tp->speed100 ? "100" : "10",
+-		       tp->full_duplex ? "full" : "half");
+-	}
+-	mdio_write(dev, tp->phys[0], MII_BMCR, reg0);
+-}
+-
+-
+-/* The interrupt handler does all of the Rx thread work and cleans up
+-   after the Tx thread. */
+-static irqreturn_t xircom_interrupt(int irq, void *dev_instance)
+-{
+-	struct net_device *dev = dev_instance;
+-	struct xircom_private *tp = netdev_priv(dev);
+-	long ioaddr = dev->base_addr;
+-	int csr5, work_budget = max_interrupt_work;
+-	int handled = 0;
+-
+-	spin_lock (&tp->lock);
+-
+-	do {
+-		csr5 = inl(ioaddr + CSR5);
+-		/* Acknowledge all of the current interrupt sources ASAP. */
+-		outl(csr5 & 0x0001ffff, ioaddr + CSR5);
+-
+-		if (xircom_debug > 4)
+-			printk(KERN_DEBUG "%s: interrupt  csr5=%#8.8x new csr5=%#8.8x.\n",
+-				   dev->name, csr5, inl(dev->base_addr + CSR5));
+-
+-		if (csr5 == 0xffffffff)
+-			break;	/* all bits set, assume PCMCIA card removed */
+-
+-		if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
+-			break;
+-
+-		handled = 1;
+-
+-		if (csr5 & (RxIntr | RxNoBuf))
+-			work_budget -= xircom_rx(dev);
+-
+-		if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
+-			unsigned int dirty_tx;
+-
+-			for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
+-				 dirty_tx++) {
+-				int entry = dirty_tx % TX_RING_SIZE;
+-				int status = tp->tx_ring[entry].status;
+-
+-				if (status < 0)
+-					break;			/* It still hasn't been Txed */
+-				/* Check for Rx filter setup frames. */
+-				if (tp->tx_skbuff[entry] == NULL)
+-				  continue;
+-
+-				if (status & Tx0DescError) {
+-					/* There was an major error, log it. */
+-#ifndef final_version
+-					if (xircom_debug > 1)
+-						printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
+-							   dev->name, status);
+-#endif
+-					tp->stats.tx_errors++;
+-					if (status & Tx0ManyColl) {
+-						tp->stats.tx_aborted_errors++;
+-					}
+-					if (status & Tx0NoCarrier) tp->stats.tx_carrier_errors++;
+-					if (status & Tx0LateColl) tp->stats.tx_window_errors++;
+-					if (status & Tx0Underflow) tp->stats.tx_fifo_errors++;
+-				} else {
+-					tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
+-					tp->stats.collisions += (status >> 3) & 15;
+-					tp->stats.tx_packets++;
+-				}
+-
+-				/* Free the original skb. */
+-				dev_kfree_skb_irq(tp->tx_skbuff[entry]);
+-				tp->tx_skbuff[entry] = NULL;
+-			}
+-
+-#ifndef final_version
+-			if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {
+-				printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+-					   dev->name, dirty_tx, tp->cur_tx, tp->tx_full);
+-				dirty_tx += TX_RING_SIZE;
+-			}
+-#endif
+-
+-			if (tp->tx_full &&
+-			    tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2)
+-				/* The ring is no longer full */
+-				tp->tx_full = 0;
+-
+-			if (tp->tx_full)
+-				netif_stop_queue (dev);
+-			else
+-				netif_wake_queue (dev);
+-
+-			tp->dirty_tx = dirty_tx;
+-			if (csr5 & TxDied) {
+-				if (xircom_debug > 2)
+-					printk(KERN_WARNING "%s: The transmitter stopped."
+-						   "  CSR5 is %x, CSR6 %x, new CSR6 %x.\n",
+-						   dev->name, csr5, inl(ioaddr + CSR6), tp->csr6);
+-				outl_CSR6(tp->csr6 | EnableRx, ioaddr);
+-				outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+-			}
+-		}
+-
+-		/* Log errors. */
+-		if (csr5 & AbnormalIntr) {	/* Abnormal error summary bit. */
+-			if (csr5 & LinkChange)
+-				xircom_media_change(dev);
+-			if (csr5 & TxFIFOUnderflow) {
+-				if ((tp->csr6 & TxThreshMask) != TxThreshMask)
+-					tp->csr6 += (1 << TxThreshShift);	/* Bump up the Tx threshold */
+-				else
+-					tp->csr6 |= TxStoreForw;  /* Store-n-forward. */
+-				/* Restart the transmit process. */
+-				outl_CSR6(tp->csr6 | EnableRx, ioaddr);
+-				outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+-			}
+-			if (csr5 & RxDied) {		/* Missed a Rx frame. */
+-				tp->stats.rx_errors++;
+-				tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+-				outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+-			}
+-			/* Clear all error sources, included undocumented ones! */
+-			outl(0x0800f7ba, ioaddr + CSR5);
+-		}
+-		if (--work_budget < 0) {
+-			if (xircom_debug > 1)
+-				printk(KERN_WARNING "%s: Too much work during an interrupt, "
+-					   "csr5=0x%8.8x.\n", dev->name, csr5);
+-			/* Acknowledge all interrupt sources. */
+-			outl(0x8001ffff, ioaddr + CSR5);
+-			break;
+-		}
+-	} while (1);
+-
+-	if (xircom_debug > 3)
+-		printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
+-			   dev->name, inl(ioaddr + CSR5));
+-
+-	spin_unlock (&tp->lock);
+-	return IRQ_RETVAL(handled);
+-}
+-
+-
+-static int
+-xircom_rx(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	int entry = tp->cur_rx % RX_RING_SIZE;
+-	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
+-	int work_done = 0;
+-
+-	if (xircom_debug > 4)
+-		printk(KERN_DEBUG " In xircom_rx(), entry %d %8.8x.\n", entry,
+-			   tp->rx_ring[entry].status);
+-	/* If we own the next entry, it's a new packet. Send it up. */
+-	while (tp->rx_ring[entry].status >= 0) {
+-		s32 status = tp->rx_ring[entry].status;
+-
+-		if (xircom_debug > 5)
+-			printk(KERN_DEBUG " In xircom_rx(), entry %d %8.8x.\n", entry,
+-				   tp->rx_ring[entry].status);
+-		if (--rx_work_limit < 0)
+-			break;
+-		if ((status & 0x38008300) != 0x0300) {
+-			if ((status & 0x38000300) != 0x0300) {
+-				/* Ignore earlier buffers. */
+-				if ((status & 0xffff) != 0x7fff) {
+-					if (xircom_debug > 1)
+-						printk(KERN_WARNING "%s: Oversized Ethernet frame "
+-							   "spanned multiple buffers, status %8.8x!\n",
+-							   dev->name, status);
+-					tp->stats.rx_length_errors++;
+-				}
+-			} else if (status & Rx0DescError) {
+-				/* There was a fatal error. */
+-				if (xircom_debug > 2)
+-					printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
+-						   dev->name, status);
+-				tp->stats.rx_errors++; /* end of a packet.*/
+-				if (status & (Rx0Runt | Rx0HugeFrame)) tp->stats.rx_length_errors++;
+-				if (status & Rx0CRCError) tp->stats.rx_crc_errors++;
+-			}
+-		} else {
+-			/* Omit the four octet CRC from the length. */
+-			short pkt_len = ((status >> 16) & 0x7ff) - 4;
+-			struct sk_buff *skb;
+-
+-#ifndef final_version
+-			if (pkt_len > 1518) {
+-				printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
+-					   dev->name, pkt_len, pkt_len);
+-				pkt_len = 1518;
+-				tp->stats.rx_length_errors++;
+-			}
+-#endif
+-			/* Check if the packet is long enough to accept without copying
+-			   to a minimally-sized skbuff. */
+-			if (pkt_len < rx_copybreak
+-				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+-				skb_reserve(skb, 2);	/* 16 byte align the IP header */
+-#if ! defined(__alpha__)
+-				skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
+-								 pkt_len);
+-				skb_put(skb, pkt_len);
+-#else
+-				memcpy(skb_put(skb, pkt_len),
+-					   bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len);
+-#endif
+-				work_done++;
+-			} else { 	/* Pass up the skb already on the Rx ring. */
+-				skb_put(skb = tp->rx_skbuff[entry], pkt_len);
+-				tp->rx_skbuff[entry] = NULL;
+-			}
+-			skb->protocol = eth_type_trans(skb, dev);
+-			netif_rx(skb);
+-			dev->last_rx = jiffies;
+-			tp->stats.rx_packets++;
+-			tp->stats.rx_bytes += pkt_len;
+-		}
+-		entry = (++tp->cur_rx) % RX_RING_SIZE;
+-	}
+-
+-	/* Refill the Rx ring buffers. */
+-	for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
+-		entry = tp->dirty_rx % RX_RING_SIZE;
+-		if (tp->rx_skbuff[entry] == NULL) {
+-			struct sk_buff *skb;
+-			skb = tp->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ);
+-			if (skb == NULL)
+-				break;
+-			skb->dev = dev;			/* Mark as being used by this device. */
+-			tp->rx_ring[entry].buffer1 = virt_to_bus(skb->data);
+-			work_done++;
+-		}
+-		tp->rx_ring[entry].status = Rx0DescOwned;
+-	}
+-
+-	return work_done;
+-}
+-
+-
+-static void
+-xircom_down(struct net_device *dev)
+-{
+-	long ioaddr = dev->base_addr;
+-	struct xircom_private *tp = netdev_priv(dev);
+-
+-	/* Disable interrupts by clearing the interrupt mask. */
+-	outl(0, ioaddr + CSR7);
+-	/* Stop the chip's Tx and Rx processes. */
+-	outl_CSR6(inl(ioaddr + CSR6) & ~EnableTxRx, ioaddr);
+-
+-	if (inl(ioaddr + CSR6) != 0xffffffff)
+-		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+-
+-	dev->if_port = tp->saved_if_port;
+-}
+-
+-
+-static int
+-xircom_close(struct net_device *dev)
+-{
+-	long ioaddr = dev->base_addr;
+-	struct xircom_private *tp = netdev_priv(dev);
+-	int i;
+-
+-	if (xircom_debug > 1)
+-		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
+-			   dev->name, inl(ioaddr + CSR5));
+-
+-	netif_stop_queue(dev);
+-
+-	if (netif_device_present(dev))
+-		xircom_down(dev);
+-
+-	free_irq(dev->irq, dev);
+-
+-	/* Free all the skbuffs in the Rx queue. */
+-	for (i = 0; i < RX_RING_SIZE; i++) {
+-		struct sk_buff *skb = tp->rx_skbuff[i];
+-		tp->rx_skbuff[i] = NULL;
+-		tp->rx_ring[i].status = 0;		/* Not owned by Xircom chip. */
+-		tp->rx_ring[i].length = 0;
+-		tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
+-		if (skb) {
+-			dev_kfree_skb(skb);
+-		}
+-	}
+-	for (i = 0; i < TX_RING_SIZE; i++) {
+-		if (tp->tx_skbuff[i])
+-			dev_kfree_skb(tp->tx_skbuff[i]);
+-		tp->tx_skbuff[i] = NULL;
+-	}
+-
+-	tp->open = 0;
+-	return 0;
+-}
+-
+-
+-static struct net_device_stats *xircom_get_stats(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	long ioaddr = dev->base_addr;
+-
+-	if (netif_device_present(dev))
+-		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+-
+-	return &tp->stats;
+-}
+-
+-static int xircom_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	ecmd->supported =
+-			SUPPORTED_10baseT_Half |
+-			SUPPORTED_10baseT_Full |
+-			SUPPORTED_100baseT_Half |
+-			SUPPORTED_100baseT_Full |
+-			SUPPORTED_Autoneg |
+-			SUPPORTED_MII;
+-
+-	ecmd->advertising = ADVERTISED_MII;
+-	if (tp->advertising[0] & ADVERTISE_10HALF)
+-		ecmd->advertising |= ADVERTISED_10baseT_Half;
+-	if (tp->advertising[0] & ADVERTISE_10FULL)
+-		ecmd->advertising |= ADVERTISED_10baseT_Full;
+-	if (tp->advertising[0] & ADVERTISE_100HALF)
+-		ecmd->advertising |= ADVERTISED_100baseT_Half;
+-	if (tp->advertising[0] & ADVERTISE_100FULL)
+-		ecmd->advertising |= ADVERTISED_100baseT_Full;
+-	if (tp->autoneg) {
+-		ecmd->advertising |= ADVERTISED_Autoneg;
+-		ecmd->autoneg = AUTONEG_ENABLE;
+-	} else
+-		ecmd->autoneg = AUTONEG_DISABLE;
+-
+-	ecmd->port = PORT_MII;
+-	ecmd->transceiver = XCVR_INTERNAL;
+-	ecmd->phy_address = tp->phys[0];
+-	ecmd->speed = tp->speed100 ? SPEED_100 : SPEED_10;
+-	ecmd->duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+-	ecmd->maxtxpkt = TX_RING_SIZE / 2;
+-	ecmd->maxrxpkt = 0;
+-	return 0;
+-}
+-
+-static int xircom_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	u16 autoneg, speed100, full_duplex;
+-
+-	autoneg = (ecmd->autoneg == AUTONEG_ENABLE);
+-	speed100 = (ecmd->speed == SPEED_100);
+-	full_duplex = (ecmd->duplex == DUPLEX_FULL);
+-
+-	tp->autoneg = autoneg;
+-	if (speed100 != tp->speed100 ||
+-	    full_duplex != tp->full_duplex) {
+-		tp->speed100 = speed100;
+-		tp->full_duplex = full_duplex;
+-		/* change advertising bits */
+-		tp->advertising[0] &= ~(ADVERTISE_10HALF |
+-				     ADVERTISE_10FULL |
+-				     ADVERTISE_100HALF |
+-				     ADVERTISE_100FULL |
+-				     ADVERTISE_100BASE4);
+-		if (speed100) {
+-			if (full_duplex)
+-				tp->advertising[0] |= ADVERTISE_100FULL;
+-			else
+-				tp->advertising[0] |= ADVERTISE_100HALF;
+-		} else {
+-			if (full_duplex)
+-				tp->advertising[0] |= ADVERTISE_10FULL;
+-			else
+-				tp->advertising[0] |= ADVERTISE_10HALF;
+-		}
+-	}
+-	check_duplex(dev);
+-	return 0;
+-}
+-
+-static void xircom_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	strcpy(info->driver, DRV_NAME);
+-	strcpy(info->version, DRV_VERSION);
+-	strcpy(info->bus_info, pci_name(tp->pdev));
+-}
+-
+-static const struct ethtool_ops ops = {
+-	.get_settings = xircom_get_settings,
+-	.set_settings = xircom_set_settings,
+-	.get_drvinfo = xircom_get_drvinfo,
+-};
+-
+-/* Provide ioctl() calls to examine the MII xcvr state. */
+-static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	u16 *data = (u16 *)&rq->ifr_ifru;
+-	int phy = tp->phys[0] & 0x1f;
+-	unsigned long flags;
+-
+-	switch(cmd) {
+-	/* Legacy mii-diag interface */
+-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+-		if (tp->mii_cnt)
+-			data[0] = phy;
+-		else
+-			return -ENODEV;
+-		return 0;
+-	case SIOCGMIIREG:		/* Read MII PHY register. */
+-		save_flags(flags);
+-		cli();
+-		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+-		restore_flags(flags);
+-		return 0;
+-	case SIOCSMIIREG:		/* Write MII PHY register. */
+-		if (!capable(CAP_NET_ADMIN))
+-			return -EPERM;
+-		save_flags(flags);
+-		cli();
+-		if (data[0] == tp->phys[0]) {
+-			u16 value = data[2];
+-			switch (data[1]) {
+-			case 0:
+-				if (value & (BMCR_RESET | BMCR_ANENABLE))
+-					/* Autonegotiation. */
+-					tp->autoneg = 1;
+-				else {
+-					tp->full_duplex = (value & BMCR_FULLDPLX) ? 1 : 0;
+-					tp->autoneg = 0;
+-				}
+-				break;
+-			case 4:
+-				tp->advertising[0] = value;
+-				break;
+-			}
+-			check_duplex(dev);
+-		}
+-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+-		restore_flags(flags);
+-		return 0;
+-	default:
+-		return -EOPNOTSUPP;
+-	}
+-
+-	return -EOPNOTSUPP;
+-}
+-
+-/* Set or clear the multicast filter for this adaptor.
+-   Note that we only use exclusion around actually queueing the
+-   new frame, not around filling tp->setup_frame.  This is non-deterministic
+-   when re-entered but still correct. */
+-static void set_rx_mode(struct net_device *dev)
+-{
+-	struct xircom_private *tp = netdev_priv(dev);
+-	struct dev_mc_list *mclist;
+-	long ioaddr = dev->base_addr;
+-	int csr6 = inl(ioaddr + CSR6);
+-	u16 *eaddrs, *setup_frm;
+-	u32 tx_flags;
+-	int i;
+-
+-	tp->csr6 &= ~(AllMultiBit | PromiscBit | HashFilterBit);
+-	csr6 &= ~(AllMultiBit | PromiscBit | HashFilterBit);
+-	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
+-		tp->csr6 |= PromiscBit;
+-		csr6 |= PromiscBit;
+-		goto out;
+-	}
+-
+-	if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) {
+-		/* Too many to filter well -- accept all multicasts. */
+-		tp->csr6 |= AllMultiBit;
+-		csr6 |= AllMultiBit;
+-		goto out;
+-	}
+-
+-	tx_flags = Tx1WholePkt | Tx1SetupPkt | PKT_SETUP_SZ;
+-
+-	/* Note that only the low-address shortword of setup_frame is valid! */
+-	setup_frm = tp->setup_frame;
+-	mclist = dev->mc_list;
+-
+-	/* Fill the first entry with our physical address. */
+-	eaddrs = (u16 *)dev->dev_addr;
+-	*setup_frm = cpu_to_le16(eaddrs[0]); setup_frm += 2;
+-	*setup_frm = cpu_to_le16(eaddrs[1]); setup_frm += 2;
+-	*setup_frm = cpu_to_le16(eaddrs[2]); setup_frm += 2;
+-
+-	if (dev->mc_count > 14) { /* Must use a multicast hash table. */
+-		u32 *hash_table = (u32 *)(tp->setup_frame + 4 * 12);
+-		u32 hash, hash2;
+-
+-		tx_flags |= Tx1HashSetup;
+-		tp->csr6 |= HashFilterBit;
+-		csr6 |= HashFilterBit;
+-
+-		/* Fill the unused 3 entries with the broadcast address.
+-		   At least one entry *must* contain the broadcast address!!!*/
+-		for (i = 0; i < 3; i++) {
+-			*setup_frm = 0xffff; setup_frm += 2;
+-			*setup_frm = 0xffff; setup_frm += 2;
+-			*setup_frm = 0xffff; setup_frm += 2;
+-		}
+-
+-		/* Truly brain-damaged hash filter layout */
+-		/* XXX: not sure if I should take the last or the first 9 bits */
+-		for (i = 0; i < dev->mc_count; i++, mclist = mclist->next) {
+-			u32 *hptr;
+-			hash = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x1ff;
+-			if (hash < 384) {
+-				hash2 = hash + ((hash >> 4) << 4) +
+-					((hash >> 5) << 5);
+-			} else {
+-				hash -= 384;
+-				hash2 = 64 + hash + (hash >> 4) * 80;
+-			}
+-			hptr = &hash_table[hash2 & ~0x1f];
+-			*hptr |= cpu_to_le32(1 << (hash2 & 0x1f));
+-		}
+-	} else {
+-		/* We have <= 14 mcast addresses so we can use Xircom's
+-		   wonderful 16-address perfect filter. */
+-		for (i = 0; i < dev->mc_count; i++, mclist = mclist->next) {
+-			eaddrs = (u16 *)mclist->dmi_addr;
+-			*setup_frm = cpu_to_le16(eaddrs[0]); setup_frm += 2;
+-			*setup_frm = cpu_to_le16(eaddrs[1]); setup_frm += 2;
+-			*setup_frm = cpu_to_le16(eaddrs[2]); setup_frm += 2;
+-		}
+-		/* Fill the unused entries with the broadcast address.
+-		   At least one entry *must* contain the broadcast address!!!*/
+-		for (; i < 15; i++) {
+-			*setup_frm = 0xffff; setup_frm += 2;
+-			*setup_frm = 0xffff; setup_frm += 2;
+-			*setup_frm = 0xffff; setup_frm += 2;
+-		}
+-	}
+-
+-	/* Now add this frame to the Tx list. */
+-	if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
+-		/* Same setup recently queued, we need not add it. */
+-		/* XXX: Huh? All it means is that the Tx list is full...*/
+-	} else {
+-		unsigned long flags;
+-		unsigned int entry;
+-		int dummy = -1;
+-
+-		save_flags(flags); cli();
+-		entry = tp->cur_tx++ % TX_RING_SIZE;
+-
+-		if (entry != 0) {
+-			/* Avoid a chip errata by prefixing a dummy entry. */
+-			tp->tx_skbuff[entry] = NULL;
+-			tp->tx_ring[entry].length =
+-				(entry == TX_RING_SIZE - 1) ? Tx1RingWrap : 0;
+-			tp->tx_ring[entry].buffer1 = 0;
+-			/* race with chip, set Tx0DescOwned later */
+-			dummy = entry;
+-			entry = tp->cur_tx++ % TX_RING_SIZE;
+-		}
+-
+-		tp->tx_skbuff[entry] = NULL;
+-		/* Put the setup frame on the Tx list. */
+-		if (entry == TX_RING_SIZE - 1)
+-			tx_flags |= Tx1RingWrap;		/* Wrap ring. */
+-		tp->tx_ring[entry].length = tx_flags;
+-		tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
+-		tp->tx_ring[entry].status = Tx0DescOwned;
+-		if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
+-			tp->tx_full = 1;
+-			netif_stop_queue (dev);
+-		}
+-		if (dummy >= 0)
+-			tp->tx_ring[dummy].status = Tx0DescOwned;
+-		restore_flags(flags);
+-		/* Trigger an immediate transmit demand. */
+-		outl(0, ioaddr + CSR1);
+-	}
+-
+-out:
+-	outl_CSR6(csr6, ioaddr);
+-}
+-
+-
+-static struct pci_device_id xircom_pci_table[] = {
+-  { 0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, X3201_3 },
+-  {0},
+-};
+-MODULE_DEVICE_TABLE(pci, xircom_pci_table);
+-
+-
+-#ifdef CONFIG_PM
+-static int xircom_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+-	struct net_device *dev = pci_get_drvdata(pdev);
+-	struct xircom_private *tp = netdev_priv(dev);
+-	printk(KERN_INFO "xircom_suspend(%s)\n", dev->name);
+-	if (tp->open)
+-		xircom_down(dev);
+-
+-	pci_save_state(pdev);
+-	pci_disable_device(pdev);
+-	pci_set_power_state(pdev, 3);
+-
+-	return 0;
+-}
+-
+-
+-static int xircom_resume(struct pci_dev *pdev)
+-{
+-	struct net_device *dev = pci_get_drvdata(pdev);
+-	struct xircom_private *tp = netdev_priv(dev);
+-	printk(KERN_INFO "xircom_resume(%s)\n", dev->name);
+-
+-	pci_set_power_state(pdev,0);
+-	pci_enable_device(pdev);
+-	pci_restore_state(pdev);
+-
+-	/* Bring the chip out of sleep mode.
+-	   Caution: Snooze mode does not work with some boards! */
+-	if (xircom_tbl[tp->chip_id].flags & HAS_ACPI)
+-		pci_write_config_dword(tp->pdev, PCI_POWERMGMT, 0);
+-
+-	transceiver_voodoo(dev);
+-	if (xircom_tbl[tp->chip_id].flags & HAS_MII)
+-		check_duplex(dev);
+-
+-	if (tp->open)
+-		xircom_up(dev);
+-	return 0;
+-}
+-#endif /* CONFIG_PM */
+-
+-
+-static void __devexit xircom_remove_one(struct pci_dev *pdev)
+-{
+-	struct net_device *dev = pci_get_drvdata(pdev);
+-
+-	printk(KERN_INFO "xircom_remove_one(%s)\n", dev->name);
+-	unregister_netdev(dev);
+-	pci_release_regions(pdev);
+-	free_netdev(dev);
+-	pci_set_drvdata(pdev, NULL);
+-}
+-
+-
+-static struct pci_driver xircom_driver = {
+-	.name		= DRV_NAME,
+-	.id_table	= xircom_pci_table,
+-	.probe		= xircom_init_one,
+-	.remove		= __devexit_p(xircom_remove_one),
+-#ifdef CONFIG_PM
+-	.suspend	= xircom_suspend,
+-	.resume		= xircom_resume
+-#endif /* CONFIG_PM */
+-};
+-
+-
+-static int __init xircom_init(void)
+-{
+-/* when a module, this is printed whether or not devices are found in probe */
+-#ifdef MODULE
+-	printk(version);
+-#endif
+-	return pci_register_driver(&xircom_driver);
+-}
+-
+-
+-static void __exit xircom_exit(void)
+-{
+-	pci_unregister_driver(&xircom_driver);
+-}
+-
+-module_init(xircom_init)
+-module_exit(xircom_exit)
+-
+-/*
+- * Local variables:
+- *  c-indent-level: 4
+- *  c-basic-offset: 4
+- *  tab-width: 4
+- * End:
+- */
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 5b5d875..0ce07a3 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -62,7 +62,9 @@
+ #include <linux/if_ether.h>
+ #include <linux/if_tun.h>
+ #include <linux/crc32.h>
++#include <linux/nsproxy.h>
+ #include <net/net_namespace.h>
++#include <net/netns/generic.h>
+ 
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+@@ -106,7 +108,11 @@ struct tun_struct {
+ 
+ /* Network device part of the driver */
+ 
+-static LIST_HEAD(tun_dev_list);
++static unsigned int tun_net_id;
++struct tun_net {
++	struct list_head dev_list;
++};
++
+ static const struct ethtool_ops tun_ethtool_ops;
+ 
+ /* Net device open. */
+@@ -471,14 +477,15 @@ static void tun_setup(struct net_device *dev)
+ 	dev->stop = tun_net_close;
+ 	dev->ethtool_ops = &tun_ethtool_ops;
+ 	dev->destructor = free_netdev;
++	dev->features |= NETIF_F_NETNS_LOCAL;
+ }
+ 
+-static struct tun_struct *tun_get_by_name(const char *name)
++static struct tun_struct *tun_get_by_name(struct tun_net *tn, const char *name)
+ {
+ 	struct tun_struct *tun;
+ 
+ 	ASSERT_RTNL();
+-	list_for_each_entry(tun, &tun_dev_list, list) {
++	list_for_each_entry(tun, &tn->dev_list, list) {
+ 		if (!strncmp(tun->dev->name, name, IFNAMSIZ))
+ 		    return tun;
+ 	}
+@@ -486,13 +493,15 @@ static struct tun_struct *tun_get_by_name(const char *name)
+ 	return NULL;
+ }
+ 
+-static int tun_set_iff(struct file *file, struct ifreq *ifr)
++static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
+ {
++	struct tun_net *tn;
+ 	struct tun_struct *tun;
+ 	struct net_device *dev;
+ 	int err;
+ 
+-	tun = tun_get_by_name(ifr->ifr_name);
++	tn = net_generic(net, tun_net_id);
++	tun = tun_get_by_name(tn, ifr->ifr_name);
+ 	if (tun) {
+ 		if (tun->attached)
+ 			return -EBUSY;
+@@ -505,7 +514,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
+ 		     !capable(CAP_NET_ADMIN))
+ 			return -EPERM;
+ 	}
+-	else if (__dev_get_by_name(&init_net, ifr->ifr_name))
++	else if (__dev_get_by_name(net, ifr->ifr_name))
+ 		return -EINVAL;
+ 	else {
+ 		char *name;
+@@ -536,6 +545,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
+ 		if (!dev)
+ 			return -ENOMEM;
+ 
++		dev_net_set(dev, net);
+ 		tun = netdev_priv(dev);
+ 		tun->dev = dev;
+ 		tun->flags = flags;
+@@ -558,7 +568,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
+ 		if (err < 0)
+ 			goto err_free_dev;
+ 
+-		list_add(&tun->list, &tun_dev_list);
++		list_add(&tun->list, &tn->dev_list);
+ 	}
+ 
+ 	DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name);
+@@ -575,6 +585,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
+ 
+ 	file->private_data = tun;
+ 	tun->attached = 1;
++	get_net(dev_net(tun->dev));
+ 
+ 	strcpy(ifr->ifr_name, tun->dev->name);
+ 	return 0;
+@@ -603,7 +614,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
+ 		ifr.ifr_name[IFNAMSIZ-1] = '\0';
+ 
+ 		rtnl_lock();
+-		err = tun_set_iff(file, &ifr);
++		err = tun_set_iff(current->nsproxy->net_ns, file, &ifr);
+ 		rtnl_unlock();
+ 
+ 		if (err)
+@@ -657,16 +668,23 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
+ 		break;
+ 
+ 	case TUNSETLINK:
++	{
++		int ret;
++
+ 		/* Only allow setting the type when the interface is down */
++		rtnl_lock();
+ 		if (tun->dev->flags & IFF_UP) {
+ 			DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
+ 				tun->dev->name);
+-			return -EBUSY;
++			ret = -EBUSY;
+ 		} else {
+ 			tun->dev->type = (int) arg;
+ 			DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
++			ret = 0;
+ 		}
+-		break;
++		rtnl_unlock();
++		return ret;
++	}
+ 
+ #ifdef TUN_DEBUG
+ 	case TUNSETDEBUG:
+@@ -723,7 +741,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
+ 	case SIOCADDMULTI:
+ 		/** Add the specified group to the character device's multicast filter
+ 		 * list. */
++		rtnl_lock();
++		netif_tx_lock_bh(tun->dev);
+ 		add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
++		netif_tx_unlock_bh(tun->dev);
++		rtnl_unlock();
++
+ 		DBG(KERN_DEBUG "%s: add multi: %s\n",
+ 		    tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
+ 		return 0;
+@@ -731,7 +754,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
+ 	case SIOCDELMULTI:
+ 		/** Remove the specified group from the character device's multicast
+ 		 * filter list. */
++		rtnl_lock();
++		netif_tx_lock_bh(tun->dev);
+ 		del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
++		netif_tx_unlock_bh(tun->dev);
++		rtnl_unlock();
++
+ 		DBG(KERN_DEBUG "%s: del multi: %s\n",
+ 		    tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
+ 		return 0;
+@@ -790,6 +818,7 @@ static int tun_chr_close(struct inode *inode, struct file *file)
+ 	/* Detach from net device */
+ 	file->private_data = NULL;
+ 	tun->attached = 0;
++	put_net(dev_net(tun->dev));
+ 
+ 	/* Drop read queue */
+ 	skb_queue_purge(&tun->readq);
+@@ -909,32 +938,76 @@ static const struct ethtool_ops tun_ethtool_ops = {
+ 	.set_rx_csum	= tun_set_rx_csum
+ };
+ 
+-static int __init tun_init(void)
++static int tun_init_net(struct net *net)
+ {
+-	int ret = 0;
++	struct tun_net *tn;
+ 
+-	printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
+-	printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
++	tn = kmalloc(sizeof(*tn), GFP_KERNEL);
++	if (tn == NULL)
++		return -ENOMEM;
+ 
+-	ret = misc_register(&tun_miscdev);
+-	if (ret)
+-		printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
+-	return ret;
++	INIT_LIST_HEAD(&tn->dev_list);
++
++	if (net_assign_generic(net, tun_net_id, tn)) {
++		kfree(tn);
++		return -ENOMEM;
++	}
++
++	return 0;
+ }
+ 
+-static void tun_cleanup(void)
++static void tun_exit_net(struct net *net)
+ {
++	struct tun_net *tn;
+ 	struct tun_struct *tun, *nxt;
+ 
+-	misc_deregister(&tun_miscdev);
++	tn = net_generic(net, tun_net_id);
+ 
+ 	rtnl_lock();
+-	list_for_each_entry_safe(tun, nxt, &tun_dev_list, list) {
++	list_for_each_entry_safe(tun, nxt, &tn->dev_list, list) {
+ 		DBG(KERN_INFO "%s cleaned up\n", tun->dev->name);
+ 		unregister_netdevice(tun->dev);
+ 	}
+ 	rtnl_unlock();
+ 
++	kfree(tn);
++}
++
++static struct pernet_operations tun_net_ops = {
++	.init = tun_init_net,
++	.exit = tun_exit_net,
++};
++
++static int __init tun_init(void)
++{
++	int ret = 0;
++
++	printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
++	printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
++
++	ret = register_pernet_gen_device(&tun_net_id, &tun_net_ops);
++	if (ret) {
++		printk(KERN_ERR "tun: Can't register pernet ops\n");
++		goto err_pernet;
++	}
++
++	ret = misc_register(&tun_miscdev);
++	if (ret) {
++		printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
++		goto err_misc;
++	}
++	return 0;
++
++err_misc:
++	unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
++err_pernet:
++	return ret;
++}
++
++static void tun_cleanup(void)
++{
++	misc_deregister(&tun_miscdev);
++	unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
+ }
+ 
+ module_init(tun_init);
+diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
+index 333961b..c0dd25b 100644
+--- a/drivers/net/typhoon.c
++++ b/drivers/net/typhoon.c
+@@ -2183,7 +2183,6 @@ typhoon_resume(struct pci_dev *pdev)
+ 	}
+ 
+ 	netif_device_attach(dev);
+-	netif_start_queue(dev);
+ 	return 0;
+ 
+ reset:
+diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
+index 0ee4c16..281ce3d 100644
+--- a/drivers/net/ucc_geth.c
++++ b/drivers/net/ucc_geth.c
+@@ -3853,7 +3853,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+ 
+ 	ugeth_vdbg("%s: IN", __FUNCTION__);
+ 
+-	prop = of_get_property(np, "device-id", NULL);
++	prop = of_get_property(np, "cell-index", NULL);
++	if (!prop) {
++		prop = of_get_property(np, "device-id", NULL);
++		if (!prop)
++			return -ENODEV;
++	}
++
+ 	ucc_num = *prop - 1;
+ 	if ((ucc_num < 0) || (ucc_num > 7))
+ 		return -ENODEV;
+@@ -3926,7 +3932,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+ 	ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
+ 	fixed_link = of_get_property(np, "fixed-link", NULL);
+ 	if (fixed_link) {
+-		ug_info->mdio_bus = 0;
++		snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "0");
+ 		ug_info->phy_address = fixed_link[0];
+ 		phy = NULL;
+ 	} else {
+@@ -3954,7 +3960,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+ 		if (err)
+ 			return -1;
+ 
+-		ug_info->mdio_bus = res.start;
++		snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", res.start);
+ 	}
+ 
+ 	/* get the phy interface type, or default to MII */
+diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
+index 4fb95b3..9f8b758 100644
+--- a/drivers/net/ucc_geth.h
++++ b/drivers/net/ucc_geth.h
+@@ -1156,7 +1156,7 @@ struct ucc_geth_info {
+ 	u16 pausePeriod;
+ 	u16 extensionField;
+ 	u8 phy_address;
+-	u32 mdio_bus;
++	char mdio_bus[MII_BUS_ID_SIZE];
+ 	u8 weightfactor[NUM_TX_QUEUES];
+ 	u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
+ 	u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];
+diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
+index c69e654..2af4907 100644
+--- a/drivers/net/ucc_geth_mii.c
++++ b/drivers/net/ucc_geth_mii.c
+@@ -157,7 +157,7 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
+ 	if (err)
+ 		goto reg_map_fail;
+ 
+-	new_bus->id = res.start;
++	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ 
+ 	new_bus->irq = kmalloc(32 * sizeof(int), GFP_KERNEL);
+ 
+@@ -203,9 +203,14 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
+ 		if ((res.start >= tempres.start) &&
+ 		    (res.end <= tempres.end)) {
+ 			/* set this UCC to be the MII master */
+-			const u32 *id = of_get_property(tempnp, "device-id", NULL);
+-			if (id == NULL)
+-				goto bus_register_fail;
++			const u32 *id;
++
++			id = of_get_property(tempnp, "cell-index", NULL);
++			if (!id) {
++				id = of_get_property(tempnp, "device-id", NULL);
++				if (!id)
++					goto bus_register_fail;
++			}
+ 
+ 			ucc_set_qe_mux_mii_mng(*id - 1);
+ 
+diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
+index 01660f6..f7319d3 100644
+--- a/drivers/net/usb/dm9601.c
++++ b/drivers/net/usb/dm9601.c
+@@ -155,7 +155,7 @@ static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
+ 	dm_write_async_helper(dev, reg, value, 0, NULL);
+ }
+ 
+-static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, u16 *value)
++static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
+ {
+ 	int ret, i;
+ 
+@@ -194,7 +194,7 @@ static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, u16 *value)
+ 	return ret;
+ }
+ 
+-static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, u16 value)
++static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 value)
+ {
+ 	int ret, i;
+ 
+@@ -249,7 +249,7 @@ static int dm9601_get_eeprom(struct net_device *net,
+ 			     struct ethtool_eeprom *eeprom, u8 * data)
+ {
+ 	struct usbnet *dev = netdev_priv(net);
+-	u16 *ebuf = (u16 *) data;
++	__le16 *ebuf = (__le16 *) data;
+ 	int i;
+ 
+ 	/* access is 16bit */
+@@ -268,7 +268,7 @@ static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc)
+ {
+ 	struct usbnet *dev = netdev_priv(netdev);
+ 
+-	u16 res;
++	__le16 res;
+ 
+ 	if (phy_id) {
+ 		devdbg(dev, "Only internal phy supported");
+@@ -288,7 +288,7 @@ static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc,
+ 			      int val)
+ {
+ 	struct usbnet *dev = netdev_priv(netdev);
+-	u16 res = cpu_to_le16(val);
++	__le16 res = cpu_to_le16(val);
+ 
+ 	if (phy_id) {
+ 		devdbg(dev, "Only internal phy supported");
+diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
+index 569ad8b..0dcfc03 100644
+--- a/drivers/net/usb/kaweth.c
++++ b/drivers/net/usb/kaweth.c
+@@ -58,7 +58,6 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/wait.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/byteorder.h>
+ 
+ #undef DEBUG
+diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
+index 369c731..21a7785 100644
+--- a/drivers/net/usb/rndis_host.c
++++ b/drivers/net/usb/rndis_host.c
+@@ -218,7 +218,7 @@ EXPORT_SYMBOL_GPL(rndis_command);
+  * ActiveSync 4.1 Windows driver.
+  */
+ static int rndis_query(struct usbnet *dev, struct usb_interface *intf,
+-		void *buf, u32 oid, u32 in_len,
++		void *buf, __le32 oid, u32 in_len,
+ 		void **reply, int *reply_len)
+ {
+ 	int retval;
+@@ -283,7 +283,8 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
+ 		struct rndis_set_c	*set_c;
+ 		struct rndis_halt	*halt;
+ 	} u;
+-	u32			tmp, phym_unspec, *phym;
++	u32			tmp, phym_unspec;
++	__le32			*phym;
+ 	int			reply_len;
+ 	unsigned char		*bp;
+ 
+diff --git a/drivers/net/veth.c b/drivers/net/veth.c
+index e2ad98b..31cd817 100644
+--- a/drivers/net/veth.c
++++ b/drivers/net/veth.c
+@@ -375,7 +375,7 @@ static int veth_newlink(struct net_device *dev,
+ 	else
+ 		snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");
+ 
+-	peer = rtnl_create_link(dev->nd_net, ifname, &veth_link_ops, tbp);
++	peer = rtnl_create_link(dev_net(dev), ifname, &veth_link_ops, tbp);
+ 	if (IS_ERR(peer))
+ 		return PTR_ERR(peer);
+ 
+diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
+index cc0addb..6b8d882 100644
+--- a/drivers/net/via-velocity.c
++++ b/drivers/net/via-velocity.c
+@@ -605,7 +605,6 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
+ static void velocity_init_cam_filter(struct velocity_info *vptr)
+ {
+ 	struct mac_regs __iomem * regs = vptr->mac_regs;
+-	unsigned short vid;
+ 
+ 	/* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
+ 	WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
+@@ -617,29 +616,33 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
+ 	mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
+ 	mac_set_cam_mask(regs, vptr->mCAMmask);
+ 
+-	/* Enable first VCAM */
++	/* Enable VCAMs */
+ 	if (vptr->vlgrp) {
+-		for (vid = 0; vid < VLAN_VID_MASK; vid++) {
+-			if (vlan_group_get_device(vptr->vlgrp, vid)) {
+-				/* If Tagging option is enabled and
+-				   VLAN ID is not zero, then
+-				   turn on MCFG_RTGOPT also */
+-				if (vid != 0)
+-					WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
++		unsigned int vid, i = 0;
++
++		if (!vlan_group_get_device(vptr->vlgrp, 0))
++			WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
+ 
+-				mac_set_vlan_cam(regs, 0, (u8 *) &vid);
++		for (vid = 1; (vid < VLAN_VID_MASK); vid++) {
++			if (vlan_group_get_device(vptr->vlgrp, vid)) {
++				mac_set_vlan_cam(regs, i, (u8 *) &vid);
++				vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
++				if (++i >= VCAM_SIZE)
++					break;
+ 			}
+ 		}
+-		vptr->vCAMmask[0] |= 1;
+ 		mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
+-	} else {
+-		u16 temp = 0;
+-		mac_set_vlan_cam(regs, 0, (u8 *) &temp);
+-		temp = 1;
+-		mac_set_vlan_cam_mask(regs, (u8 *) &temp);
+ 	}
+ }
+ 
++static void velocity_vlan_rx_register(struct net_device *dev,
++				      struct vlan_group *grp)
++{
++	struct velocity_info *vptr = netdev_priv(dev);
++
++	vptr->vlgrp = grp;
++}
++
+ static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+ {
+ 	struct velocity_info *vptr = netdev_priv(dev);
+@@ -959,11 +962,13 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
+ 
+ 	dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid;
+ 	dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid;
++	dev->vlan_rx_register = velocity_vlan_rx_register;
+ 
+ #ifdef  VELOCITY_ZERO_COPY_SUPPORT
+ 	dev->features |= NETIF_F_SG;
+ #endif
+-	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER;
++	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
++		NETIF_F_HW_VLAN_RX;
+ 
+ 	if (vptr->flags & VELOCITY_FLAGS_TX_CSUM)
+ 		dev->features |= NETIF_F_IP_CSUM;
+@@ -1597,8 +1602,13 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
+ 	skb_put(skb, pkt_len - 4);
+ 	skb->protocol = eth_type_trans(skb, vptr->dev);
+ 
++	if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_DETAG)) {
++		vlan_hwaccel_rx(skb, vptr->vlgrp,
++				swab16(le16_to_cpu(rd->rdesc1.PQTAG)));
++	} else
++		netif_rx(skb);
++
+ 	stats->rx_bytes += pkt_len;
+-	netif_rx(skb);
+ 
+ 	return 0;
+ }
+@@ -3460,21 +3470,22 @@ static int velocity_resume(struct pci_dev *pdev)
+ static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
+ {
+ 	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
++	struct net_device *dev = ifa->ifa_dev->dev;
++	struct velocity_info *vptr;
++	unsigned long flags;
+ 
+-	if (ifa) {
+-		struct net_device *dev = ifa->ifa_dev->dev;
+-		struct velocity_info *vptr;
+-		unsigned long flags;
++	if (dev_net(dev) != &init_net)
++		return NOTIFY_DONE;
+ 
+-		spin_lock_irqsave(&velocity_dev_list_lock, flags);
+-		list_for_each_entry(vptr, &velocity_dev_list, list) {
+-			if (vptr->dev == dev) {
+-				velocity_get_ip(vptr);
+-				break;
+-			}
++	spin_lock_irqsave(&velocity_dev_list_lock, flags);
++	list_for_each_entry(vptr, &velocity_dev_list, list) {
++		if (vptr->dev == dev) {
++			velocity_get_ip(vptr);
++			break;
+ 		}
+-		spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
+ 	}
++	spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
++
+ 	return NOTIFY_DONE;
+ }
+ 
+diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
+index c4c8eab..c2cc42f 100644
+--- a/drivers/net/wan/c101.c
++++ b/drivers/net/wan/c101.c
+@@ -402,7 +402,7 @@ static int __init c101_init(void)
+ #ifdef MODULE
+ 		printk(KERN_INFO "c101: no card initialized\n");
+ #endif
+-		return -ENOSYS;	/* no parameters specified, abort */
++		return -EINVAL;	/* no parameters specified, abort */
+ 	}
+ 
+ 	printk(KERN_INFO "%s\n", version);
+@@ -420,11 +420,11 @@ static int __init c101_init(void)
+ 			c101_run(irq, ram);
+ 
+ 		if (*hw == '\x0')
+-			return first_card ? 0 : -ENOSYS;
++			return first_card ? 0 : -EINVAL;
+ 	}while(*hw++ == ':');
+ 
+ 	printk(KERN_ERR "c101: invalid hardware parameters\n");
+-	return first_card ? 0 : -ENOSYS;
++	return first_card ? 0 : -EINVAL;
+ }
+ 
+ 
+diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
+index 1d706ea..45ddfc9 100644
+--- a/drivers/net/wan/cosa.c
++++ b/drivers/net/wan/cosa.c
+@@ -90,6 +90,7 @@
+ #include <linux/ioport.h>
+ #include <linux/netdevice.h>
+ #include <linux/spinlock.h>
++#include <linux/mutex.h>
+ #include <linux/device.h>
+ 
+ #undef COSA_SLOW_IO	/* for testing purposes only */
+@@ -127,7 +128,8 @@ struct channel_data {
+ 	int (*tx_done)(struct channel_data *channel, int size);
+ 
+ 	/* Character device parts */
+-	struct semaphore rsem, wsem;
++	struct mutex rlock;
++	struct semaphore wsem;
+ 	char *rxdata;
+ 	int rxsize;
+ 	wait_queue_head_t txwaitq, rxwaitq;
+@@ -807,7 +809,7 @@ static struct net_device_stats *cosa_net_stats(struct net_device *dev)
+ 
+ static void chardev_channel_init(struct channel_data *chan)
+ {
+-	init_MUTEX(&chan->rsem);
++	mutex_init(&chan->rlock);
+ 	init_MUTEX(&chan->wsem);
+ }
+ 
+@@ -825,12 +827,12 @@ static ssize_t cosa_read(struct file *file,
+ 			cosa->name, cosa->firmware_status);
+ 		return -EPERM;
+ 	}
+-	if (down_interruptible(&chan->rsem))
++	if (mutex_lock_interruptible(&chan->rlock))
+ 		return -ERESTARTSYS;
+ 	
+ 	if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) {
+ 		printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name);
+-		up(&chan->rsem);
++		mutex_unlock(&chan->rlock);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -848,7 +850,7 @@ static ssize_t cosa_read(struct file *file,
+ 			remove_wait_queue(&chan->rxwaitq, &wait);
+ 			current->state = TASK_RUNNING;
+ 			spin_unlock_irqrestore(&cosa->lock, flags);
+-			up(&chan->rsem);
++			mutex_unlock(&chan->rlock);
+ 			return -ERESTARTSYS;
+ 		}
+ 	}
+@@ -857,7 +859,7 @@ static ssize_t cosa_read(struct file *file,
+ 	kbuf = chan->rxdata;
+ 	count = chan->rxsize;
+ 	spin_unlock_irqrestore(&cosa->lock, flags);
+-	up(&chan->rsem);
++	mutex_unlock(&chan->rlock);
+ 
+ 	if (copy_to_user(buf, kbuf, count)) {
+ 		kfree(kbuf);
+diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
+index 96b2324..b142427 100644
+--- a/drivers/net/wan/dlci.c
++++ b/drivers/net/wan/dlci.c
+@@ -517,7 +517,7 @@ static int dlci_dev_event(struct notifier_block *unused,
+ {
+ 	struct net_device *dev = (struct net_device *) ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event == NETDEV_UNREGISTER) {
+diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
+index 39951d0..9a83c9d 100644
+--- a/drivers/net/wan/hdlc.c
++++ b/drivers/net/wan/hdlc.c
+@@ -68,7 +68,7 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
+ {
+ 	struct hdlc_device *hdlc = dev_to_hdlc(dev);
+ 
+-	if (dev->nd_net != &init_net) {
++	if (dev_net(dev) != &init_net) {
+ 		kfree_skb(skb);
+ 		return 0;
+ 	}
+@@ -105,7 +105,7 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event,
+ 	unsigned long flags;
+ 	int on;
+  
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (dev->get_stats != hdlc_get_stats)
+diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
+index c4ab032..520bb0b 100644
+--- a/drivers/net/wan/hdlc_fr.c
++++ b/drivers/net/wan/hdlc_fr.c
+@@ -1090,10 +1090,6 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
+ 	pvc_device *pvc = NULL;
+ 	struct net_device *dev;
+ 	int result, used;
+-	char * prefix = "pvc%d";
+-
+-	if (type == ARPHRD_ETHER)
+-		prefix = "pvceth%d";
+ 
+ 	if ((pvc = add_pvc(frad, dlci)) == NULL) {
+ 		printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
+diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
+index 824df3b..b5860b9 100644
+--- a/drivers/net/wan/lapbether.c
++++ b/drivers/net/wan/lapbether.c
+@@ -91,7 +91,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
+ 	int len, err;
+ 	struct lapbethdev *lapbeth;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto drop;
+ 
+ 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+@@ -393,7 +393,7 @@ static int lapbeth_device_event(struct notifier_block *this,
+ 	struct lapbethdev *lapbeth;
+ 	struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (!dev_is_ethdev(dev))
+diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
+index 61e24b7..29b4b94 100644
+--- a/drivers/net/wan/syncppp.c
++++ b/drivers/net/wan/syncppp.c
+@@ -1444,7 +1444,7 @@ static void sppp_print_bytes (u_char *p, u16 len)
+ 
+ static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev)
+ {
+-	if (dev->nd_net != &init_net) {
++	if (dev_net(dev) != &init_net) {
+ 		kfree_skb(skb);
+ 		return 0;
+ 	}
+diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
+index 714a6ca..fdf5aa8 100644
+--- a/drivers/net/wireless/Kconfig
++++ b/drivers/net/wireless/Kconfig
+@@ -146,12 +146,15 @@ config IPW2100
+           configure your card:
+ 
+           <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
++
++          It is recommended that you compile this driver as a module (M)
++          rather than built-in (Y). This driver requires firmware at device
++          initialization time, and when built-in this typically happens
++          before the filesystem is accessible (hence firmware will be
++          unavailable and initialization will fail). If you do choose to build
++          this driver into your kernel image, you can avoid this problem by
++          including the firmware and a firmware loader in an initramfs.
+  
+-          If you want to compile the driver as a module ( = code which can be
+-          inserted in and removed from the running kernel whenever you want),
+-          say M here and read <file:Documentation/kbuild/modules.txt>.
+-          The module will be called ipw2100.ko.
+-	
+ config IPW2100_MONITOR
+         bool "Enable promiscuous mode"
+         depends on IPW2100
+@@ -201,11 +204,14 @@ config IPW2200
+           configure your card:
+ 
+           <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+- 
+-          If you want to compile the driver as a module ( = code which can be
+-          inserted in and removed from the running kernel whenever you want),
+-          say M here and read <file:Documentation/kbuild/modules.txt>.
+-          The module will be called ipw2200.ko.
++
++          It is recommended that you compile this driver as a module (M)
++          rather than built-in (Y). This driver requires firmware at device
++          initialization time, and when built-in this typically happens
++          before the filesystem is accessible (hence firmware will be
++          unavailable and initialization will fail). If you do choose to build
++          this driver into your kernel image, you can avoid this problem by
++          including the firmware and a firmware loader in an initramfs.
+ 
+ config IPW2200_MONITOR
+         bool "Enable promiscuous mode"
+@@ -265,7 +271,6 @@ config LIBERTAS
+ 	tristate "Marvell 8xxx Libertas WLAN driver support"
+ 	depends on WLAN_80211
+ 	select WIRELESS_EXT
+-	select IEEE80211
+ 	select FW_LOADER
+ 	---help---
+ 	  A library for Marvell Libertas 8xxx devices.
+@@ -278,7 +283,7 @@ config LIBERTAS_USB
+ 
+ config LIBERTAS_CS
+ 	tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
+-	depends on LIBERTAS && PCMCIA && EXPERIMENTAL
++	depends on LIBERTAS && PCMCIA
+ 	select FW_LOADER
+ 	---help---
+ 	  A driver for Marvell Libertas 8385 CompactFlash devices.
+@@ -668,90 +673,10 @@ config ADM8211
+ 
+ 	  Thanks to Infineon-ADMtek for their support of this driver.
+ 
+-config P54_COMMON
+-	tristate "Softmac Prism54 support"
+-	depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL
+-	---help---
+-	  This is common code for isl38xx based cards.
+-	  This module does nothing by itself - the USB/PCI frontends
+-	  also need to be enabled in order to support any devices.
+-
+-	  These devices require softmac firmware which can be found at
+-	  http://prism54.org/
+-
+-	  If you choose to build a module, it'll be called p54common.
+-
+-config P54_USB
+-	tristate "Prism54 USB support"
+-	depends on P54_COMMON && USB
+-	select CRC32
+-	---help---
+-	  This driver is for USB isl38xx based wireless cards.
+-	  These are USB based adapters found in devices such as:
+-
+-	  3COM 3CRWE254G72
+-	  SMC 2862W-G
+-	  Accton 802.11g WN4501 USB
+-	  Siemens Gigaset USB
+-	  Netgear WG121
+-	  Netgear WG111
+-	  Medion 40900, Roper Europe
+-	  Shuttle PN15, Airvast WM168g, IOGear GWU513
+-	  Linksys WUSB54G
+-	  Linksys WUSB54G Portable
+-	  DLink DWL-G120 Spinnaker
+-	  DLink DWL-G122
+-	  Belkin F5D7050 ver 1000
+-	  Cohiba Proto board
+-	  SMC 2862W-G version 2
+-	  U.S. Robotics U5 802.11g Adapter
+-	  FUJITSU E-5400 USB D1700
+-	  Sagem XG703A
+-	  DLink DWL-G120 Cohiba
+-	  Spinnaker Proto board
+-	  Linksys WUSB54AG
+-	  Inventel UR054G
+-	  Spinnaker DUT
+-
+-	  These devices require softmac firmware which can be found at
+-	  http://prism54.org/
+-
+-	  If you choose to build a module, it'll be called p54usb.
+-
+-config P54_PCI
+-	tristate "Prism54 PCI support"
+-	depends on P54_COMMON && PCI
+-	---help---
+-	  This driver is for PCI isl38xx based wireless cards.
+-	  This driver supports most devices that are supported by the
+-	  fullmac prism54 driver plus many devices which are not
+-	  supported by the fullmac driver/firmware.
+-
+-	  This driver requires softmac firmware which can be found at
+-	  http://prism54.org/
+-
+-	  If you choose to build a module, it'll be called p54pci.
+-
+-config ATH5K
+-	tristate "Atheros 5xxx wireless cards support"
+-	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+-	---help---
+-	  This module adds support for wireless adapters based on
+-	  Atheros 5xxx chipset.
+-
+-	  Currently the following chip versions are supported:
+-
+-	  MAC: AR5211 AR5212
+-	  PHY: RF5111/2111 RF5112/2112 RF5413/2413
+-
+-	  This driver uses the kernel's mac80211 subsystem.
+-
+-	  If you choose to build a module, it'll be called ath5k. Say M if
+-	  unsure.
+-
++source "drivers/net/wireless/p54/Kconfig"
++source "drivers/net/wireless/ath5k/Kconfig"
+ source "drivers/net/wireless/iwlwifi/Kconfig"
+ source "drivers/net/wireless/hostap/Kconfig"
+-source "drivers/net/wireless/bcm43xx/Kconfig"
+ source "drivers/net/wireless/b43/Kconfig"
+ source "drivers/net/wireless/b43legacy/Kconfig"
+ source "drivers/net/wireless/zd1211rw/Kconfig"
+diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
+index 091dfe2..c2642bc 100644
+--- a/drivers/net/wireless/Makefile
++++ b/drivers/net/wireless/Makefile
+@@ -35,7 +35,6 @@ obj-$(CONFIG_PCMCIA_ATMEL)      += atmel_cs.o
+ obj-$(CONFIG_PRISM54)		+= prism54/
+ 
+ obj-$(CONFIG_HOSTAP)		+= hostap/
+-obj-$(CONFIG_BCM43XX)		+= bcm43xx/
+ obj-$(CONFIG_B43)		+= b43/
+ obj-$(CONFIG_B43LEGACY)		+= b43legacy/
+ obj-$(CONFIG_ZD1211RW)		+= zd1211rw/
+@@ -57,12 +56,9 @@ obj-$(CONFIG_RTL8187)	+= rtl8187.o
+ 
+ obj-$(CONFIG_ADM8211)	+= adm8211.o
+ 
+-obj-$(CONFIG_IWL3945)	+= iwlwifi/
+-obj-$(CONFIG_IWL4965)	+= iwlwifi/
++obj-$(CONFIG_IWLCORE)	+= iwlwifi/
+ obj-$(CONFIG_RT2X00)	+= rt2x00/
+ 
+-obj-$(CONFIG_P54_COMMON)	+= p54common.o
+-obj-$(CONFIG_P54_USB)		+= p54usb.o
+-obj-$(CONFIG_P54_PCI)		+= p54pci.o
++obj-$(CONFIG_P54_COMMON)	+= p54/
+ 
+ obj-$(CONFIG_ATH5K)	+= ath5k/
+diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
+index 7979618..5c0d2b0 100644
+--- a/drivers/net/wireless/adm8211.c
++++ b/drivers/net/wireless/adm8211.c
+@@ -48,6 +48,32 @@ static struct pci_device_id adm8211_pci_id_table[] __devinitdata = {
+ 	{ 0 }
+ };
+ 
++static struct ieee80211_rate adm8211_rates[] = {
++	{ .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, /* XX ?? */
++};
++
++static const struct ieee80211_channel adm8211_channels[] = {
++	{ .center_freq = 2412},
++	{ .center_freq = 2417},
++	{ .center_freq = 2422},
++	{ .center_freq = 2427},
++	{ .center_freq = 2432},
++	{ .center_freq = 2437},
++	{ .center_freq = 2442},
++	{ .center_freq = 2447},
++	{ .center_freq = 2452},
++	{ .center_freq = 2457},
++	{ .center_freq = 2462},
++	{ .center_freq = 2467},
++	{ .center_freq = 2472},
++	{ .center_freq = 2484},
++};
++
++
+ static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+ {
+ 	struct adm8211_priv *priv = eeprom->data;
+@@ -155,17 +181,17 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev)
+ 	printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n",
+ 	       pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max);
+ 
+-	priv->modes[0].num_channels = chan_range.max - chan_range.min + 1;
+-	priv->modes[0].channels = priv->channels;
++	BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels));
+ 
+-	memcpy(priv->channels, adm8211_channels, sizeof(adm8211_channels));
++	memcpy(priv->channels, adm8211_channels, sizeof(priv->channels));
++	priv->band.channels = priv->channels;
++	priv->band.n_channels = ARRAY_SIZE(adm8211_channels);
++	priv->band.bitrates = adm8211_rates;
++	priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates);
+ 
+ 	for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++)
+-		if (i >= chan_range.min && i <= chan_range.max)
+-			priv->channels[i - 1].flag =
+-				IEEE80211_CHAN_W_SCAN |
+-				IEEE80211_CHAN_W_ACTIVE_SCAN |
+-				IEEE80211_CHAN_W_IBSS;
++		if (i < chan_range.min || i > chan_range.max)
++			priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED;
+ 
+ 	switch (priv->eeprom->specific_bbptype) {
+ 	case ADM8211_BBP_RFMD3000:
+@@ -347,7 +373,6 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
+ 	unsigned int pktlen;
+ 	struct sk_buff *skb, *newskb;
+ 	unsigned int limit = priv->rx_ring_size;
+-	static const u8 rate_tbl[] = {10, 20, 55, 110, 220};
+ 	u8 rssi, rate;
+ 
+ 	while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) {
+@@ -425,12 +450,10 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
+ 			else
+ 				rx_status.ssi = 100 - rssi;
+ 
+-			if (rate <= 4)
+-				rx_status.rate = rate_tbl[rate];
++			rx_status.rate_idx = rate;
+ 
+-			rx_status.channel = priv->channel;
+-			rx_status.freq = adm8211_channels[priv->channel - 1].freq;
+-			rx_status.phymode = MODE_IEEE80211B;
++			rx_status.freq = adm8211_channels[priv->channel - 1].center_freq;
++			rx_status.band = IEEE80211_BAND_2GHZ;
+ 
+ 			ieee80211_rx_irqsafe(dev, skb, &rx_status);
+ 		}
+@@ -465,9 +488,6 @@ do {									   \
+ 	if (stsr & ADM8211_STSR_TCI)
+ 		adm8211_interrupt_tci(dev);
+ 
+-	/*ADM8211_INT(LinkOn);*/
+-	/*ADM8211_INT(LinkOff);*/
+-
+ 	ADM8211_INT(PCF);
+ 	ADM8211_INT(BCNTC);
+ 	ADM8211_INT(GPINT);
+@@ -477,7 +497,6 @@ do {									   \
+ 	ADM8211_INT(SQL);
+ 	ADM8211_INT(WEPTD);
+ 	ADM8211_INT(ATIME);
+-	/*ADM8211_INT(TBTT);*/
+ 	ADM8211_INT(TEIS);
+ 	ADM8211_INT(FBE);
+ 	ADM8211_INT(REIS);
+@@ -485,9 +504,6 @@ do {									   \
+ 	ADM8211_INT(RPS);
+ 	ADM8211_INT(RDU);
+ 	ADM8211_INT(TUF);
+-	/*ADM8211_INT(TRT);*/
+-	/*ADM8211_INT(TLT);*/
+-	/*ADM8211_INT(TDU);*/
+ 	ADM8211_INT(TPS);
+ 
+ 	return IRQ_HANDLED;
+@@ -1054,7 +1070,7 @@ static int adm8211_set_rate(struct ieee80211_hw *dev)
+ 	if (priv->pdev->revision != ADM8211_REV_BA) {
+ 		rate_buf[0] = ARRAY_SIZE(adm8211_rates);
+ 		for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++)
+-			rate_buf[i + 1] = (adm8211_rates[i].rate / 5) | 0x80;
++			rate_buf[i + 1] = (adm8211_rates[i].bitrate / 5) | 0x80;
+ 	} else {
+ 		/* workaround for rev BA specific bug */
+ 		rate_buf[0] = 0x04;
+@@ -1086,7 +1102,7 @@ static void adm8211_hw_init(struct ieee80211_hw *dev)
+ 	u32 reg;
+ 	u8 cline;
+ 
+-	reg = le32_to_cpu(ADM8211_CSR_READ(PAR));
++	reg = ADM8211_CSR_READ(PAR);
+ 	reg |= ADM8211_PAR_MRLE | ADM8211_PAR_MRME;
+ 	reg &= ~(ADM8211_PAR_BAR | ADM8211_PAR_CAL);
+ 
+@@ -1303,9 +1319,10 @@ static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len)
+ static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+ {
+ 	struct adm8211_priv *priv = dev->priv;
++	int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ 
+-	if (conf->channel != priv->channel) {
+-		priv->channel = conf->channel;
++	if (channel != priv->channel) {
++		priv->channel = channel;
+ 		adm8211_rf_set_channel(dev, priv->channel);
+ 	}
+ 
+@@ -1678,13 +1695,9 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ 	int plcp, dur, len, plcp_signal, short_preamble;
+ 	struct ieee80211_hdr *hdr;
+ 
+-	if (control->tx_rate < 0) {
+-		short_preamble = 1;
+-		plcp_signal = -control->tx_rate;
+-	} else {
+-		short_preamble = 0;
+-		plcp_signal = control->tx_rate;
+-	}
++	short_preamble = !!(control->tx_rate->flags &
++					IEEE80211_TXCTL_SHORT_PREAMBLE);
++	plcp_signal = control->tx_rate->bitrate;
+ 
+ 	hdr = (struct ieee80211_hdr *)skb->data;
+ 	fc = le16_to_cpu(hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED;
+@@ -1880,18 +1893,11 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
+ 	SET_IEEE80211_PERM_ADDR(dev, perm_addr);
+ 
+ 	dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
+-	dev->flags = IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
+-	/* IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
++	/* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
+ 
+ 	dev->channel_change_time = 1000;
+ 	dev->max_rssi = 100;	/* FIXME: find better value */
+ 
+-	priv->modes[0].mode = MODE_IEEE80211B;
+-	/* channel info filled in by adm8211_read_eeprom */
+-	memcpy(priv->rates, adm8211_rates, sizeof(adm8211_rates));
+-	priv->modes[0].num_rates = ARRAY_SIZE(adm8211_rates);
+-	priv->modes[0].rates = priv->rates;
+-
+ 	dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */
+ 
+ 	priv->retry_limit = 3;
+@@ -1917,14 +1923,9 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
+ 		goto err_free_desc;
+ 	}
+ 
+-	priv->channel = priv->modes[0].channels[0].chan;
++	priv->channel = 1;
+ 
+-	err = ieee80211_register_hwmode(dev, &priv->modes[0]);
+-	if (err) {
+-		printk(KERN_ERR "%s (adm8211): Can't register hwmode\n",
+-		       pci_name(pdev));
+-		goto err_free_desc;
+-	}
++	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+ 
+ 	err = ieee80211_register_hw(dev);
+ 	if (err) {
+diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h
+index ef326fe..8d7c564 100644
+--- a/drivers/net/wireless/adm8211.h
++++ b/drivers/net/wireless/adm8211.h
+@@ -534,61 +534,6 @@ struct adm8211_eeprom {
+ 	u8	cis_data[0];		/* 0x80, 384 bytes */
+ } __attribute__ ((packed));
+ 
+-static const struct ieee80211_rate adm8211_rates[] = {
+-	{ .rate = 10,
+-	  .val = 10,
+-	  .val2 = -10,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 20,
+-	  .val = 20,
+-	  .val2 = -20,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 55,
+-	  .val = 55,
+-	  .val2 = -55,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 110,
+-	  .val = 110,
+-	  .val2 = -110,
+-	  .flags = IEEE80211_RATE_CCK_2 }
+-};
+-
+-struct ieee80211_chan_range {
+-	u8 min;
+-	u8 max;
+-};
+-
+-static const struct ieee80211_channel adm8211_channels[] = {
+-	{ .chan = 1,
+-	  .freq = 2412},
+-	{ .chan = 2,
+-	  .freq = 2417},
+-	{ .chan = 3,
+-	  .freq = 2422},
+-	{ .chan = 4,
+-	  .freq = 2427},
+-	{ .chan = 5,
+-	  .freq = 2432},
+-	{ .chan = 6,
+-	  .freq = 2437},
+-	{ .chan = 7,
+-	  .freq = 2442},
+-	{ .chan = 8,
+-	  .freq = 2447},
+-	{ .chan = 9,
+-	  .freq = 2452},
+-	{ .chan = 10,
+-	  .freq = 2457},
+-	{ .chan = 11,
+-	  .freq = 2462},
+-	{ .chan = 12,
+-	  .freq = 2467},
+-	{ .chan = 13,
+-	  .freq = 2472},
+-	{ .chan = 14,
+-	  .freq = 2484},
+-};
+-
+ struct adm8211_priv {
+ 	struct pci_dev *pdev;
+ 	spinlock_t lock;
+@@ -603,9 +548,8 @@ struct adm8211_priv {
+ 	unsigned int cur_tx, dirty_tx, cur_rx;
+ 
+ 	struct ieee80211_low_level_stats stats;
+-	struct ieee80211_hw_mode modes[1];
+-	struct ieee80211_channel channels[ARRAY_SIZE(adm8211_channels)];
+-	struct ieee80211_rate rates[ARRAY_SIZE(adm8211_rates)];
++	struct ieee80211_supported_band band;
++	struct ieee80211_channel channels[14];
+ 	int mode;
+ 
+ 	int channel;
+@@ -643,6 +587,11 @@ struct adm8211_priv {
+ 	} transceiver_type;
+ };
+ 
++struct ieee80211_chan_range {
++	u8 min;
++	u8 max;
++};
++
+ static const struct ieee80211_chan_range cranges[] = {
+ 	{1,  11},	/* FCC */
+ 	{1,  11},	/* IC */
+diff --git a/drivers/net/wireless/ath5k/Kconfig b/drivers/net/wireless/ath5k/Kconfig
+new file mode 100644
+index 0000000..f1f2aea
+--- /dev/null
++++ b/drivers/net/wireless/ath5k/Kconfig
+@@ -0,0 +1,37 @@
++config ATH5K
++	tristate "Atheros 5xxx wireless cards support"
++	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
++	---help---
++	  This module adds support for wireless adapters based on
++	  Atheros 5xxx chipset.
++
++	  Currently the following chip versions are supported:
++
++	  MAC: AR5211 AR5212
++	  PHY: RF5111/2111 RF5112/2112 RF5413/2413
++
++	  This driver uses the kernel's mac80211 subsystem.
++
++	  If you choose to build a module, it'll be called ath5k. Say M if
++	  unsure.
++
++config ATH5K_DEBUG
++	bool "Atheros 5xxx debugging"
++	depends on ATH5K
++	---help---
++	  Atheros 5xxx debugging messages.
++
++	  Say Y, if and you will get debug options for ath5k.
++	  To use this, you need to mount debugfs:
++
++	  mkdir /debug/
++	  mount -t debugfs debug /debug/
++
++	  You will get access to files under:
++	  /debug/ath5k/phy0/
++
++	  To enable debug, pass the debug level to the debug module
++	  parameter. For example:
++
++	  modprobe ath5k debug=0x00000400
++
+diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile
+index 321641f..564ecd0 100644
+--- a/drivers/net/wireless/ath5k/Makefile
++++ b/drivers/net/wireless/ath5k/Makefile
+@@ -1,2 +1,6 @@
+-ath5k-objs		= base.o hw.o regdom.o initvals.o phy.o debug.o
+-obj-$(CONFIG_ATH5K)	+= ath5k.o
++ath5k-y				+= base.o
++ath5k-y				+= hw.o
++ath5k-y				+= initvals.o
++ath5k-y				+= phy.o
++ath5k-$(CONFIG_ATH5K_DEBUG)	+= debug.o
++obj-$(CONFIG_ATH5K)		+= ath5k.o
+diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
+index 69dea33..ba35c30 100644
+--- a/drivers/net/wireless/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath5k/ath5k.h
+@@ -30,7 +30,6 @@
+ #include <net/mac80211.h>
+ 
+ #include "hw.h"
+-#include "regdom.h"
+ 
+ /* PCI IDs */
+ #define PCI_DEVICE_ID_ATHEROS_AR5210 		0x0007 /* AR5210 */
+@@ -141,7 +140,9 @@ enum ath5k_radio {
+ 	AR5K_RF5110	= 0,
+ 	AR5K_RF5111	= 1,
+ 	AR5K_RF5112	= 2,
+-	AR5K_RF5413	= 3,
++	AR5K_RF2413	= 3,
++	AR5K_RF5413	= 4,
++	AR5K_RF2425	= 5,
+ };
+ 
+ /*
+@@ -169,12 +170,15 @@ struct ath5k_srev_name {
+ #define AR5K_SREV_VER_AR5212	0x50
+ #define AR5K_SREV_VER_AR5213	0x55
+ #define AR5K_SREV_VER_AR5213A	0x59
+-#define AR5K_SREV_VER_AR2424	0xa0
+-#define AR5K_SREV_VER_AR5424	0xa3
++#define AR5K_SREV_VER_AR2413	0x78
++#define AR5K_SREV_VER_AR2414	0x79
++#define AR5K_SREV_VER_AR2424	0xa0 /* PCI-E */
++#define AR5K_SREV_VER_AR5424	0xa3 /* PCI-E */
+ #define AR5K_SREV_VER_AR5413	0xa4
+ #define AR5K_SREV_VER_AR5414	0xa5
+-#define AR5K_SREV_VER_AR5416	0xc0	/* ? */
+-#define AR5K_SREV_VER_AR5418	0xca
++#define AR5K_SREV_VER_AR5416	0xc0 /* PCI-E */
++#define AR5K_SREV_VER_AR5418	0xca /* PCI-E */
++#define AR5K_SREV_VER_AR2425	0xe2 /* PCI-E */
+ 
+ #define AR5K_SREV_RAD_5110	0x00
+ #define AR5K_SREV_RAD_5111	0x10
+@@ -184,8 +188,9 @@ struct ath5k_srev_name {
+ #define AR5K_SREV_RAD_5112A	0x35
+ #define AR5K_SREV_RAD_2112	0x40
+ #define AR5K_SREV_RAD_2112A	0x45
++#define AR5K_SREV_RAD_SC0	0x56	/* Found on 2413/2414 */
+ #define AR5K_SREV_RAD_SC1	0x63	/* Found on 5413/5414 */
+-#define AR5K_SREV_RAD_SC2	0xa2	/* Found on 2424/5424 */
++#define AR5K_SREV_RAD_SC2	0xa2	/* Found on 2424-5/5424 */
+ #define AR5K_SREV_RAD_5133	0xc0	/* MIMO found on 5418 */
+ 
+ /* IEEE defs */
+@@ -251,26 +256,31 @@ struct ath5k_srev_name {
+  */
+ #define MODULATION_TURBO	0x00000080
+ 
+-enum ath5k_vendor_mode {
+-	MODE_ATHEROS_TURBO = NUM_IEEE80211_MODES+1,
+-	MODE_ATHEROS_TURBOG
++enum ath5k_driver_mode {
++	AR5K_MODE_11A		=	0,
++	AR5K_MODE_11A_TURBO	=	1,
++	AR5K_MODE_11B		=	2,
++	AR5K_MODE_11G		=	3,
++	AR5K_MODE_11G_TURBO	=	4,
++	AR5K_MODE_XR		=	0,
++	AR5K_MODE_MAX		=	5
+ };
+ 
+-/* Number of supported mac80211 enum ieee80211_phymode modes by this driver */
+-#define NUM_DRIVER_MODES	3
+-
+ /* adding this flag to rate_code enables short preamble, see ar5212_reg.h */
+ #define AR5K_SET_SHORT_PREAMBLE 0x04
+ 
+-#define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_CCK_2)
+-#define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
++#define HAS_SHPREAMBLE(_ix) \
++	(rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE)
++#define SHPREAMBLE_FLAG(_ix) \
++	(HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
++
+ 
+ /****************\
+   TX DEFINITIONS
+ \****************/
+ 
+ /*
+- * Tx Descriptor
++ * TX Status
+  */
+ struct ath5k_tx_status {
+ 	u16	ts_seqnum;
+@@ -418,7 +428,7 @@ enum ath5k_dmasize {
+ \****************/
+ 
+ /*
+- * Rx Descriptor
++ * RX Status
+  */
+ struct ath5k_rx_status {
+ 	u16	rs_datalen;
+@@ -440,16 +450,6 @@ struct ath5k_rx_status {
+ #define AR5K_RXKEYIX_INVALID	((u8) - 1)
+ #define AR5K_TXKEYIX_INVALID	((u32) - 1)
+ 
+-struct ath5k_mib_stats {
+-	u32	ackrcv_bad;
+-	u32	rts_bad;
+-	u32	rts_good;
+-	u32	fcs_bad;
+-	u32	beacons;
+-};
+-
+-
+-
+ 
+ /**************************\
+  BEACON TIMERS DEFINITIONS
+@@ -492,29 +492,23 @@ struct ath5k_beacon_state {
+ #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
+ 
+ 
+-
+ /********************\
+   COMMON DEFINITIONS
+ \********************/
+ 
+ /*
+- * Atheros descriptor
++ * Atheros hardware descriptor
++ * This is read and written to by the hardware
+  */
+ struct ath5k_desc {
+-	u32	ds_link;
+-	u32	ds_data;
+-	u32	ds_ctl0;
+-	u32	ds_ctl1;
+-	u32	ds_hw[4];
++	u32	ds_link;	/* physical address of the next descriptor */
++	u32	ds_data;	/* physical address of data buffer (skb) */
+ 
+ 	union {
+-		struct ath5k_rx_status rx;
+-		struct ath5k_tx_status tx;
+-	} ds_us;
+-
+-#define ds_rxstat ds_us.rx
+-#define ds_txstat ds_us.tx
+-
++		struct ath5k_hw_5210_tx_desc	ds_tx5210;
++		struct ath5k_hw_5212_tx_desc	ds_tx5212;
++		struct ath5k_hw_all_rx_desc	ds_rx;
++	} ud;
+ } __packed;
+ 
+ #define AR5K_RXDESC_INTREQ	0x0020
+@@ -560,8 +554,8 @@ struct ath5k_desc {
+  * Used internaly in OpenHAL (ar5211.c/ar5212.c
+  * for reset_tx_queue). Also see struct struct ieee80211_channel.
+  */
+-#define IS_CHAN_XR(_c)	((_c.val & CHANNEL_XR) != 0)
+-#define IS_CHAN_B(_c)	((_c.val & CHANNEL_B) != 0)
++#define IS_CHAN_XR(_c)	((_c.hw_value & CHANNEL_XR) != 0)
++#define IS_CHAN_B(_c)	((_c.hw_value & CHANNEL_B) != 0)
+ 
+ /*
+  * The following structure will be used to map 2GHz channels to
+@@ -584,7 +578,7 @@ struct ath5k_athchan_2ghz {
+ 
+ /**
+  * struct ath5k_rate - rate structure
+- * @valid: is this a valid rate for the current mode
++ * @valid: is this a valid rate for rate control (remove)
+  * @modulation: respective mac80211 modulation
+  * @rate_kbps: rate in kbit/s
+  * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
+@@ -643,47 +637,48 @@ struct ath5k_rate_table {
+ 
+ /*
+  * Rate tables...
++ * TODO: CLEAN THIS !!!
+  */
+ #define AR5K_RATES_11A { 8, {					\
+ 	255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0,	\
+ 	7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255,	\
+ 	255, 255, 255, 255, 255, 255, 255, 255 }, {		\
+-	{ 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 0 },		\
+-	{ 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 0 },		\
+-	{ 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 2 },		\
+-	{ 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 2 },		\
+-	{ 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 4 },		\
+-	{ 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 4 },		\
+-	{ 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 4 },		\
+-	{ 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 4 } }		\
++	{ 1, 0, 6000, 11, 140, 0 },		\
++	{ 1, 0, 9000, 15, 18, 0 },		\
++	{ 1, 0, 12000, 10, 152, 2 },		\
++	{ 1, 0, 18000, 14, 36, 2 },		\
++	{ 1, 0, 24000, 9, 176, 4 },		\
++	{ 1, 0, 36000, 13, 72, 4 },		\
++	{ 1, 0, 48000, 8, 96, 4 },		\
++	{ 1, 0, 54000, 12, 108, 4 } }		\
+ }
+ 
+ #define AR5K_RATES_11B { 4, {						\
+ 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,	\
+ 	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,	\
+ 	3, 2, 1, 0, 255, 255, 255, 255 }, {				\
+-	{ 1, IEEE80211_RATE_CCK, 1000, 27, 130, 0 },	\
+-	{ 1, IEEE80211_RATE_CCK_2, 2000, 26, 132, 1 },	\
+-	{ 1, IEEE80211_RATE_CCK_2, 5500, 25, 139, 1 },	\
+-	{ 1, IEEE80211_RATE_CCK_2, 11000, 24, 150, 1 } }	\
++	{ 1, 0, 1000, 27, 130, 0 },	\
++	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 132, 1 },	\
++	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 139, 1 },	\
++	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 150, 1 } }	\
+ }
+ 
+ #define AR5K_RATES_11G { 12, {					\
+ 	255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4,	\
+ 	11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255,	\
+ 	3, 2, 1, 0, 255, 255, 255, 255 }, {			\
+-	{ 1, IEEE80211_RATE_CCK, 1000, 27, 2, 0 },		\
+-	{ 1, IEEE80211_RATE_CCK_2, 2000, 26, 4, 1 },		\
+-	{ 1, IEEE80211_RATE_CCK_2, 5500, 25, 11, 1 },		\
+-	{ 1, IEEE80211_RATE_CCK_2, 11000, 24, 22, 1 },	\
+-	{ 0, IEEE80211_RATE_OFDM, 6000, 11, 12, 4 },	\
+-	{ 0, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 12000, 10, 24, 6 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 24000, 9, 48, 8 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } }	\
++	{ 1, 0, 1000, 27, 2, 0 },		\
++	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 4, 1 },		\
++	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 11, 1 },		\
++	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 22, 1 },	\
++	{ 0, 0, 6000, 11, 12, 4 },	\
++	{ 0, 0, 9000, 15, 18, 4 },	\
++	{ 1, 0, 12000, 10, 24, 6 },	\
++	{ 1, 0, 18000, 14, 36, 6 },	\
++	{ 1, 0, 24000, 9, 48, 8 },	\
++	{ 1, 0, 36000, 13, 72, 8 },	\
++	{ 1, 0, 48000, 8, 96, 8 },	\
++	{ 1, 0, 54000, 12, 108, 8 } }	\
+ }
+ 
+ #define AR5K_RATES_TURBO { 8, {					\
+@@ -708,14 +703,14 @@ struct ath5k_rate_table {
+ 	{ 1, MODULATION_XR, 1000, 2, 139, 1 },		\
+ 	{ 1, MODULATION_XR, 2000, 6, 150, 2 },		\
+ 	{ 1, MODULATION_XR, 3000, 1, 150, 3 },		\
+-	{ 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 4 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 6 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 8 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 },	\
+-	{ 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } }	\
++	{ 1, 0, 6000, 11, 140, 4 },	\
++	{ 1, 0, 9000, 15, 18, 4 },	\
++	{ 1, 0, 12000, 10, 152, 6 },	\
++	{ 1, 0, 18000, 14, 36, 6 },	\
++	{ 1, 0, 24000, 9, 176, 8 },	\
++	{ 1, 0, 36000, 13, 72, 8 },	\
++	{ 1, 0, 48000, 8, 96, 8 },	\
++	{ 1, 0, 54000, 12, 108, 8 } }	\
+ }
+ 
+ /*
+@@ -890,12 +885,14 @@ enum ath5k_capability_type {
+ 	AR5K_CAP_RFSILENT		= 20,	/* Supports RFsilent */
+ };
+ 
++
++/* XXX: we *may* move cap_range stuff to struct wiphy */
+ struct ath5k_capabilities {
+ 	/*
+ 	 * Supported PHY modes
+ 	 * (ie. CHANNEL_A, CHANNEL_B, ...)
+ 	 */
+-	DECLARE_BITMAP(cap_mode, NUM_DRIVER_MODES);
++	DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
+ 
+ 	/*
+ 	 * Frequency range (without regulation restrictions)
+@@ -908,14 +905,6 @@ struct ath5k_capabilities {
+ 	} cap_range;
+ 
+ 	/*
+-	 * Active regulation domain settings
+-	 */
+-	struct {
+-		enum ath5k_regdom reg_current;
+-		enum ath5k_regdom reg_hw;
+-	} cap_regdomain;
+-
+-	/*
+ 	 * Values stored in the EEPROM (some of them...)
+ 	 */
+ 	struct ath5k_eeprom_info	cap_eeprom;
+@@ -963,6 +952,7 @@ struct ath5k_hw {
+ 	u16			ah_phy_revision;
+ 	u16			ah_radio_5ghz_revision;
+ 	u16			ah_radio_2ghz_revision;
++	u32			ah_phy_spending;
+ 
+ 	enum ath5k_version	ah_version;
+ 	enum ath5k_radio	ah_radio;
+@@ -1038,8 +1028,10 @@ struct ath5k_hw {
+ 	int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ 		unsigned int, unsigned int, unsigned int, unsigned int,
+ 		unsigned int, unsigned int);
+-	int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *);
+-	int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *);
++	int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
++		struct ath5k_tx_status *);
++	int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
++		struct ath5k_rx_status *);
+ };
+ 
+ /*
+@@ -1070,6 +1062,7 @@ extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
+ extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
+ extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
+ extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask);
++extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats);
+ /* EEPROM access functions */
+ extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain);
+ /* Protocol Control Unit Functions */
+@@ -1098,7 +1091,6 @@ extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_be
+ extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
+ extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr);
+ #endif
+-extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics);
+ /* ACK bit rate */
+ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
+ /* ACK/CTS Timeouts */
+@@ -1129,8 +1121,6 @@ extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
+ extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
+ extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
+ extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
+-/* Regulatory Domain/Channels Setup */
+-extern u16 ath5k_get_regdomain(struct ath5k_hw *ah);
+ /* Misc functions */
+ extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
+ 
+diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
+index bef967c..e18305b 100644
+--- a/drivers/net/wireless/ath5k/base.c
++++ b/drivers/net/wireless/ath5k/base.c
+@@ -80,7 +80,7 @@ MODULE_AUTHOR("Nick Kossifidis");
+ MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
+ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
+ MODULE_LICENSE("Dual BSD/GPL");
+-MODULE_VERSION("0.1.1 (EXPERIMENTAL)");
++MODULE_VERSION("0.5.0 (EXPERIMENTAL)");
+ 
+ 
+ /* Known PCI ids */
+@@ -118,12 +118,15 @@ static struct ath5k_srev_name srev_names[] = {
+ 	{ "5212",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR5212 },
+ 	{ "5213",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR5213 },
+ 	{ "5213A",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR5213A },
++	{ "2413",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR2413 },
++	{ "2414",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR2414 },
+ 	{ "2424",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR2424 },
+ 	{ "5424",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR5424 },
+ 	{ "5413",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR5413 },
+ 	{ "5414",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR5414 },
+ 	{ "5416",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR5416 },
+ 	{ "5418",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR5418 },
++	{ "2425",	AR5K_VERSION_VER,	AR5K_SREV_VER_AR2425 },
+ 	{ "xxxxx",	AR5K_VERSION_VER,	AR5K_SREV_UNKNOWN },
+ 	{ "5110",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5110 },
+ 	{ "5111",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5111 },
+@@ -132,6 +135,7 @@ static struct ath5k_srev_name srev_names[] = {
+ 	{ "5112A",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5112A },
+ 	{ "2112",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2112 },
+ 	{ "2112A",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2112A },
++	{ "SChip",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_SC0 },
+ 	{ "SChip",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_SC1 },
+ 	{ "SChip",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_SC2 },
+ 	{ "5133",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5133 },
+@@ -240,6 +244,8 @@ static int 	ath5k_chan_set(struct ath5k_softc *sc,
+ static void	ath5k_setcurmode(struct ath5k_softc *sc,
+ 				unsigned int mode);
+ static void	ath5k_mode_setup(struct ath5k_softc *sc);
++static void	ath5k_set_total_hw_rates(struct ath5k_softc *sc);
++
+ /* Descriptor setup */
+ static int	ath5k_desc_alloc(struct ath5k_softc *sc,
+ 				struct pci_dev *pdev);
+@@ -278,7 +284,8 @@ 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 ath5k_desc *ds,
+-					struct sk_buff *skb);
++					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,
+@@ -511,35 +518,46 @@ ath5k_pci_probe(struct pci_dev *pdev,
+ 					sc->ah->ah_mac_srev,
+ 					sc->ah->ah_phy_revision);
+ 
+-	if(!sc->ah->ah_single_chip){
++	if (!sc->ah->ah_single_chip) {
+ 		/* Single chip radio (!RF5111) */
+-		if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) {
++		if (sc->ah->ah_radio_5ghz_revision &&
++			!sc->ah->ah_radio_2ghz_revision) {
+ 			/* No 5GHz support -> report 2GHz radio */
+-			if(!test_bit(MODE_IEEE80211A, sc->ah->ah_capabilities.cap_mode)){
++			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(MODE_IEEE80211B, sc->ah->ah_capabilities.cap_mode)){
++					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);
++					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);
++					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){
++		/* 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_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_chip_name(AR5K_VERSION_RAD,
++					sc->ah->ah_radio_2ghz_revision),
++					sc->ah->ah_radio_2ghz_revision);
+ 		}
+ 	}
+ 
+@@ -693,11 +711,14 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+ 		goto err;
+ 	}
+ 
++	/* Set *_rates so we can map hw rate index */
++	ath5k_set_total_hw_rates(sc);
++
+ 	/* NB: setup here so ath5k_rate_update is happy */
+-	if (test_bit(MODE_IEEE80211A, ah->ah_modes))
+-		ath5k_setcurmode(sc, MODE_IEEE80211A);
++	if (test_bit(AR5K_MODE_11A, ah->ah_modes))
++		ath5k_setcurmode(sc, AR5K_MODE_11A);
+ 	else
+-		ath5k_setcurmode(sc, MODE_IEEE80211B);
++		ath5k_setcurmode(sc, AR5K_MODE_11B);
+ 
+ 	/*
+ 	 * Allocate tx+rx descriptors and populate the lists.
+@@ -837,12 +858,9 @@ ath5k_copy_rates(struct ieee80211_rate *rates,
+ 		return 0;
+ 
+ 	for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
+-		if (!rt->rates[i].valid)
+-			continue;
+-		rates->rate = rt->rates[i].rate_kbps / 100;
+-		rates->val = rt->rates[i].rate_code;
+-		rates->flags = rt->rates[i].modulation;
+-		rates++;
++		rates[count].bitrate = rt->rates[i].rate_kbps / 100;
++		rates[count].hw_value = rt->rates[i].rate_code;
++		rates[count].flags = rt->rates[i].modulation;
+ 		count++;
+ 		max--;
+ 	}
+@@ -856,43 +874,22 @@ ath5k_copy_channels(struct ath5k_hw *ah,
+ 		unsigned int mode,
+ 		unsigned int max)
+ {
+-	static const struct { unsigned int mode, mask, chan; } map[] = {
+-		[MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A },
+-		[MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T },
+-		[MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B },
+-		[MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G },
+-		[MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG },
+-	};
+-	static const struct ath5k_regchannel chans_2ghz[] =
+-		IEEE80211_CHANNELS_2GHZ;
+-	static const struct ath5k_regchannel chans_5ghz[] =
+-		IEEE80211_CHANNELS_5GHZ;
+-	const struct ath5k_regchannel *chans;
+-	enum ath5k_regdom dmn;
+-	unsigned int i, count, size, chfreq, all, f, ch;
++	unsigned int i, count, size, chfreq, freq, ch;
+ 
+ 	if (!test_bit(mode, ah->ah_modes))
+ 		return 0;
+ 
+-	all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1;
+-
+ 	switch (mode) {
+-	case MODE_IEEE80211A:
+-	case MODE_ATHEROS_TURBO:
++	case AR5K_MODE_11A:
++	case AR5K_MODE_11A_TURBO:
+ 		/* 1..220, but 2GHz frequencies are filtered by check_channel */
+-		size = all ? 220 : ARRAY_SIZE(chans_5ghz);
+-		chans = chans_5ghz;
+-		dmn = ath5k_regdom2flag(ah->ah_regdomain,
+-				IEEE80211_CHANNELS_5GHZ_MIN);
++		size = 220 ;
+ 		chfreq = CHANNEL_5GHZ;
+ 		break;
+-	case MODE_IEEE80211B:
+-	case MODE_IEEE80211G:
+-	case MODE_ATHEROS_TURBOG:
+-		size = all ? 26 : ARRAY_SIZE(chans_2ghz);
+-		chans = chans_2ghz;
+-		dmn = ath5k_regdom2flag(ah->ah_regdomain,
+-				IEEE80211_CHANNELS_2GHZ_MIN);
++	case AR5K_MODE_11B:
++	case AR5K_MODE_11G:
++	case AR5K_MODE_11G_TURBO:
++		size = 26;
+ 		chfreq = CHANNEL_2GHZ;
+ 		break;
+ 	default:
+@@ -901,25 +898,31 @@ ath5k_copy_channels(struct ath5k_hw *ah,
+ 	}
+ 
+ 	for (i = 0, count = 0; i < size && max > 0; i++) {
+-		ch = all ? i + 1 : chans[i].chan;
+-		f = ath5k_ieee2mhz(ch);
+-		/* Check if channel is supported by the chipset */
+-		if (!ath5k_channel_ok(ah, f, chfreq))
+-			continue;
++		ch = i + 1 ;
++		freq = ath5k_ieee2mhz(ch);
+ 
+-		/* Match regulation domain */
+-		if (!all && !(IEEE80211_DMN(chans[i].domain) &
+-							IEEE80211_DMN(dmn)))
++		/* Check if channel is supported by the chipset */
++		if (!ath5k_channel_ok(ah, freq, chfreq))
+ 			continue;
+ 
+-		if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode)
+-			continue;
++		/* Write channel info and increment counter */
++		channels[count].center_freq = freq;
++		channels[count].band = (chfreq == CHANNEL_2GHZ) ?
++			IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
++		switch (mode) {
++		case AR5K_MODE_11A:
++		case AR5K_MODE_11G:
++			channels[count].hw_value = chfreq | CHANNEL_OFDM;
++			break;
++		case AR5K_MODE_11A_TURBO:
++		case AR5K_MODE_11G_TURBO:
++			channels[count].hw_value = chfreq |
++				CHANNEL_OFDM | CHANNEL_TURBO;
++			break;
++		case AR5K_MODE_11B:
++			channels[count].hw_value = CHANNEL_B;
++		}
+ 
+-		/* Write channel and increment counter */
+-		channels->chan = ch;
+-		channels->freq = f;
+-		channels->val = map[mode].chan;
+-		channels++;
+ 		count++;
+ 		max--;
+ 	}
+@@ -927,95 +930,78 @@ ath5k_copy_channels(struct ath5k_hw *ah,
+ 	return count;
+ }
+ 
+-/* Only tries to register modes our EEPROM says it can support */
+-#define REGISTER_MODE(m) do { \
+-	ret = ath5k_register_mode(hw, m); \
+-	if (ret) \
+-		return ret; \
+-} while (0) \
+-
+-static inline int
+-ath5k_register_mode(struct ieee80211_hw *hw, u8 m)
+-{
+-	struct ath5k_softc *sc = hw->priv;
+-	struct ieee80211_hw_mode *modes = sc->modes;
+-	unsigned int i;
+-	int ret;
+-
+-	if (!test_bit(m, sc->ah->ah_capabilities.cap_mode))
+-		return 0;
+-
+-	for (i = 0; i < NUM_DRIVER_MODES; i++) {
+-		if (modes[i].mode != m || !modes[i].num_channels)
+-			continue;
+-		ret = ieee80211_register_hwmode(hw, &modes[i]);
+-		if (ret) {
+-			ATH5K_ERR(sc, "can't register hwmode %u\n", m);
+-			return ret;
+-		}
+-		return 0;
+-	}
+-	BUG();
+-}
+-
+ static int
+ ath5k_getchannels(struct ieee80211_hw *hw)
+ {
+ 	struct ath5k_softc *sc = hw->priv;
+ 	struct ath5k_hw *ah = sc->ah;
+-	struct ieee80211_hw_mode *modes = sc->modes;
+-	unsigned int i, max_r, max_c;
+-	int ret;
++	struct ieee80211_supported_band *sbands = sc->sbands;
++	const struct ath5k_rate_table *hw_rates;
++	unsigned int max_r, max_c, count_r, count_c;
++	int mode2g = AR5K_MODE_11G;
+ 
+-	BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3);
+-
+-	/* The order here does not matter */
+-	modes[0].mode = MODE_IEEE80211G;
+-	modes[1].mode = MODE_IEEE80211B;
+-	modes[2].mode = MODE_IEEE80211A;
++	BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
+ 
+ 	max_r = ARRAY_SIZE(sc->rates);
+ 	max_c = ARRAY_SIZE(sc->channels);
++	count_r = count_c = 0;
+ 
+-	for (i = 0; i < NUM_DRIVER_MODES; i++) {
+-		struct ieee80211_hw_mode *mode = &modes[i];
+-		const struct ath5k_rate_table *hw_rates;
++	/* 2GHz band */
++	if (!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
++		mode2g = AR5K_MODE_11B;
++		if (!test_bit(AR5K_MODE_11B,
++			sc->ah->ah_capabilities.cap_mode))
++			mode2g = -1;
++	}
+ 
+-		if (i == 0) {
+-			modes[0].rates	= sc->rates;
+-			modes->channels	= sc->channels;
+-		} else {
+-			struct ieee80211_hw_mode *prev_mode = &modes[i-1];
+-			int prev_num_r	= prev_mode->num_rates;
+-			int prev_num_c	= prev_mode->num_channels;
+-			mode->rates	= &prev_mode->rates[prev_num_r];
+-			mode->channels	= &prev_mode->channels[prev_num_c];
+-		}
++	if (mode2g > 0) {
++		struct ieee80211_supported_band *sband =
++			&sbands[IEEE80211_BAND_2GHZ];
++
++		sband->bitrates = sc->rates;
++		sband->channels = sc->channels;
++
++		sband->band = IEEE80211_BAND_2GHZ;
++		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
++					mode2g, max_c);
++
++		hw_rates = ath5k_hw_get_rate_table(ah, mode2g);
++		sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
++					hw_rates, max_r);
++
++		count_c = sband->n_channels;
++		count_r = sband->n_bitrates;
++
++		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
++
++		max_r -= count_r;
++		max_c -= count_c;
+ 
+-		hw_rates = ath5k_hw_get_rate_table(ah, mode->mode);
+-		mode->num_rates    = ath5k_copy_rates(mode->rates, hw_rates,
+-			max_r);
+-		mode->num_channels = ath5k_copy_channels(ah, mode->channels,
+-			mode->mode, max_c);
+-		max_r -= mode->num_rates;
+-		max_c -= mode->num_channels;
+ 	}
+ 
+-	/* We try to register all modes this driver supports. We don't bother
+-	 * with MODE_IEEE80211B for AR5212 as MODE_IEEE80211G already accounts
+-	 * for that as per mac80211. Then, REGISTER_MODE() will will actually
+-	 * check the eeprom reading for more reliable capability information.
+-	 * Order matters here as per mac80211's latest preference. This will
+-	 * all hopefullly soon go away. */
++	/* 5GHz band */
+ 
+-	REGISTER_MODE(MODE_IEEE80211G);
+-	if (ah->ah_version != AR5K_AR5212)
+-		REGISTER_MODE(MODE_IEEE80211B);
+-	REGISTER_MODE(MODE_IEEE80211A);
++	if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
++		struct ieee80211_supported_band *sband =
++			&sbands[IEEE80211_BAND_5GHZ];
+ 
+-	ath5k_debug_dump_modes(sc, modes);
++		sband->bitrates = &sc->rates[count_r];
++		sband->channels = &sc->channels[count_c];
+ 
+-	return ret;
++		sband->band = IEEE80211_BAND_5GHZ;
++		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
++					AR5K_MODE_11A, max_c);
++
++		hw_rates = ath5k_hw_get_rate_table(ah, AR5K_MODE_11A);
++		sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
++					hw_rates, max_r);
++
++		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
++	}
++
++	ath5k_debug_dump_bands(sc);
++
++	return 0;
+ }
+ 
+ /*
+@@ -1030,11 +1016,15 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ 	struct ath5k_hw *ah = sc->ah;
+ 	int ret;
+ 
+-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n",
+-		sc->curchan->chan, sc->curchan->freq,
+-		chan->chan, chan->freq);
++	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
++		sc->curchan->center_freq, chan->center_freq);
++
++	if (chan->center_freq != sc->curchan->center_freq ||
++		chan->hw_value != sc->curchan->hw_value) {
++
++		sc->curchan = chan;
++		sc->curband = &sc->sbands[chan->band];
+ 
+-	if (chan->freq != sc->curchan->freq || chan->val != sc->curchan->val) {
+ 		/*
+ 		 * To switch channels clear any pending DMA operations;
+ 		 * wait long enough for the RX fifo to drain, reset the
+@@ -1044,13 +1034,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ 		ath5k_hw_set_intr(ah, 0);	/* disable interrupts */
+ 		ath5k_txq_cleanup(sc);		/* clear pending tx frames */
+ 		ath5k_rx_stop(sc);		/* turn off frame recv */
+-		ret = ath5k_hw_reset(ah, sc->opmode, chan, true);
++		ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
+ 		if (ret) {
+-			ATH5K_ERR(sc, "%s: unable to reset channel %u "
+-				"(%u Mhz)\n", __func__, chan->chan, chan->freq);
++			ATH5K_ERR(sc, "%s: unable to reset channel "
++				"(%u Mhz)\n", __func__, chan->center_freq);
+ 			return ret;
+ 		}
+-		sc->curchan = chan;
++
+ 		ath5k_hw_set_txpower_limit(sc->ah, 0);
+ 
+ 		/*
+@@ -1081,6 +1071,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ 	return 0;
+ }
+ 
++/*
++ * TODO: CLEAN THIS !!!
++ */
+ static void
+ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+ {
+@@ -1121,10 +1114,6 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+ 				continue;
+ 			}
+ 			sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
+-			if (SHPREAMBLE_FLAG(ix) || rt->rates[ix].modulation ==
+-					IEEE80211_RATE_OFDM)
+-				sc->hwmap[i].txflags |=
+-						IEEE80211_RADIOTAP_F_SHORTPRE;
+ 			/* receive frames include FCS */
+ 			sc->hwmap[i].rxflags = sc->hwmap[i].txflags |
+ 					IEEE80211_RADIOTAP_F_FCS;
+@@ -1142,6 +1131,12 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+ 	}
+ 
+ 	sc->curmode = mode;
++
++	if (mode == AR5K_MODE_11A) {
++		sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ];
++	} else {
++		sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ];
++	}
+ }
+ 
+ static void
+@@ -1164,6 +1159,72 @@ ath5k_mode_setup(struct ath5k_softc *sc)
+ 	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
+ }
+ 
++/*
++ * Match the hw provided rate index (through descriptors)
++ * to an index for sc->curband->bitrates, so it can be used
++ * by the stack.
++ *
++ * This one is a little bit tricky but i think i'm right
++ * about this...
++ *
++ * We have 4 rate tables in the following order:
++ * XR (4 rates)
++ * 802.11a (8 rates)
++ * 802.11b (4 rates)
++ * 802.11g (12 rates)
++ * that make the hw rate table.
++ *
++ * Lets take a 5211 for example that supports a and b modes only.
++ * First comes the 802.11a table and then 802.11b (total 12 rates).
++ * When hw returns eg. 11 it points to the last 802.11b rate (11Mbit),
++ * if it returns 2 it points to the second 802.11a rate etc.
++ *
++ * Same goes for 5212 who has xr/a/b/g support (total 28 rates).
++ * First comes the XR table, then 802.11a, 802.11b and 802.11g.
++ * When hw returns eg. 27 it points to the last 802.11g rate (54Mbits) etc
++ */
++static void
++ath5k_set_total_hw_rates(struct ath5k_softc *sc) {
++
++	struct ath5k_hw *ah = sc->ah;
++
++	if (test_bit(AR5K_MODE_11A, ah->ah_modes))
++		sc->a_rates = 8;
++
++	if (test_bit(AR5K_MODE_11B, ah->ah_modes))
++		sc->b_rates = 4;
++
++	if (test_bit(AR5K_MODE_11G, ah->ah_modes))
++		sc->g_rates = 12;
++
++	/* XXX: Need to see what what happens when
++		xr disable bits in eeprom are set */
++	if (ah->ah_version >= AR5K_AR5212)
++		sc->xr_rates = 4;
++
++}
++
++static inline int
++ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) {
++
++	int mac80211_rix;
++
++	if(sc->curband->band == IEEE80211_BAND_2GHZ) {
++		/* We setup a g ratetable for both b/g modes */
++		mac80211_rix =
++			hw_rix - sc->b_rates - sc->a_rates - sc->xr_rates;
++	} else {
++		mac80211_rix = hw_rix - sc->xr_rates;
++	}
++
++	/* Something went wrong, fallback to basic rate for this band */
++	if ((mac80211_rix >= sc->curband->n_bitrates) ||
++		(mac80211_rix <= 0 ))
++		mac80211_rix = 1;
++
++	return mac80211_rix;
++}
++
+ 
+ 
+ 
+@@ -1268,7 +1329,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+ 
+ 	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
+ 		ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
+-		(ctl->power_level * 2), ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0);
++		(sc->power_level * 2), ctl->tx_rate->hw_value,
++		ctl->retry_limit, keyidx, 0, flags, 0, 0);
+ 	if (ret)
+ 		goto err_unmap;
+ 
+@@ -1503,8 +1565,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ 	 */
+ 	spin_lock_bh(&txq->lock);
+ 	list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+-		ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah,
+-					bf->desc));
++		ath5k_debug_printtxbuf(sc, bf);
+ 
+ 		ath5k_txbuf_free(sc, bf);
+ 
+@@ -1629,20 +1690,20 @@ ath5k_rx_stop(struct ath5k_softc *sc)
+ 
+ static unsigned int
+ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
+-		struct sk_buff *skb)
++		struct sk_buff *skb, struct ath5k_rx_status *rs)
+ {
+ 	struct ieee80211_hdr *hdr = (void *)skb->data;
+ 	unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb);
+ 
+-	if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
+-			ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID)
++	if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
++			rs->rs_keyix != AR5K_RXKEYIX_INVALID)
+ 		return RX_FLAG_DECRYPTED;
+ 
+ 	/* Apparently when a default key is used to decrypt the packet
+ 	   the hw does not set the index used to decrypt.  In such cases
+ 	   get the index from the packet. */
+ 	if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) &&
+-			!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
++			!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
+ 			skb->len >= hlen + 4) {
+ 		keyix = skb->data[hlen + 3] >> 6;
+ 
+@@ -1655,28 +1716,62 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
+ 
+ 
+ static void
+-ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
++ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
++		     struct ieee80211_rx_status *rxs)
+ {
++	u64 tsf, bc_tstamp;
+ 	u32 hw_tu;
+ 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+ 
+-	if ((mgmt->frame_control & IEEE80211_FCTL_FTYPE) ==
++	if ((le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_FTYPE) ==
+ 		IEEE80211_FTYPE_MGMT &&
+-	    (mgmt->frame_control & IEEE80211_FCTL_STYPE) ==
++	    (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) ==
+ 		IEEE80211_STYPE_BEACON &&
+-	    mgmt->u.beacon.capab_info & WLAN_CAPABILITY_IBSS &&
++	    le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
+ 	    memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
+ 		/*
+-		 * Received an IBSS beacon with the same BSSID. Hardware might
+-		 * have updated the TSF, check if we need to update timers.
++		 * Received an IBSS beacon with the same BSSID. Hardware *must*
++		 * have updated the local TSF. We have to work around various
++		 * hardware bugs, though...
+ 		 */
+-		hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
+-		if (hw_tu >= sc->nexttbtt) {
+-			ath5k_beacon_update_timers(sc,
+-				mgmt->u.beacon.timestamp);
++		tsf = ath5k_hw_get_tsf64(sc->ah);
++		bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
++		hw_tu = TSF_TO_TU(tsf);
++
++		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
++			"beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
++			(unsigned long long)bc_tstamp,
++			(unsigned long long)rxs->mactime,
++			(unsigned long long)(rxs->mactime - bc_tstamp),
++			(unsigned long long)tsf);
++
++		/*
++		 * Sometimes the HW will give us a wrong tstamp in the rx
++		 * status, causing the timestamp extension to go wrong.
++		 * (This seems to happen especially with beacon frames bigger
++		 * than 78 byte (incl. FCS))
++		 * But we know that the receive timestamp must be later than the
++		 * timestamp of the beacon since HW must have synced to that.
++		 *
++		 * NOTE: here we assume mactime to be after the frame was
++		 * received, not like mac80211 which defines it at the start.
++		 */
++		if (bc_tstamp > rxs->mactime) {
+ 			ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+-				"detected HW merge from received beacon\n");
++				"fixing mactime from %llx to %llx\n",
++				(unsigned long long)rxs->mactime,
++				(unsigned long long)tsf);
++			rxs->mactime = tsf;
+ 		}
++
++		/*
++		 * Local TSF might have moved higher than our beacon timers,
++		 * in that case we have to update them to continue sending
++		 * beacons. This also takes care of synchronizing beacon sending
++		 * times with other stations.
++		 */
++		if (hw_tu >= sc->nexttbtt)
++			ath5k_beacon_update_timers(sc, bc_tstamp);
+ 	}
+ }
+ 
+@@ -1685,12 +1780,11 @@ static void
+ ath5k_tasklet_rx(unsigned long data)
+ {
+ 	struct ieee80211_rx_status rxs = {};
++	struct ath5k_rx_status rs = {};
+ 	struct sk_buff *skb;
+ 	struct ath5k_softc *sc = (void *)data;
+ 	struct ath5k_buf *bf;
+ 	struct ath5k_desc *ds;
+-	u16 len;
+-	u8 stat;
+ 	int ret;
+ 	int hdrlen;
+ 	int pad;
+@@ -1713,7 +1807,7 @@ ath5k_tasklet_rx(unsigned long data)
+ 		if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */
+ 			break;
+ 
+-		ret = sc->ah->ah_proc_rx_desc(sc->ah, ds);
++		ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
+ 		if (unlikely(ret == -EINPROGRESS))
+ 			break;
+ 		else if (unlikely(ret)) {
+@@ -1722,16 +1816,15 @@ ath5k_tasklet_rx(unsigned long data)
+ 			return;
+ 		}
+ 
+-		if (unlikely(ds->ds_rxstat.rs_more)) {
++		if (unlikely(rs.rs_more)) {
+ 			ATH5K_WARN(sc, "unsupported jumbo\n");
+ 			goto next;
+ 		}
+ 
+-		stat = ds->ds_rxstat.rs_status;
+-		if (unlikely(stat)) {
+-			if (stat & AR5K_RXERR_PHY)
++		if (unlikely(rs.rs_status)) {
++			if (rs.rs_status & AR5K_RXERR_PHY)
+ 				goto next;
+-			if (stat & AR5K_RXERR_DECRYPT) {
++			if (rs.rs_status & AR5K_RXERR_DECRYPT) {
+ 				/*
+ 				 * Decrypt error.  If the error occurred
+ 				 * because there was no hardware key, then
+@@ -1742,30 +1835,29 @@ ath5k_tasklet_rx(unsigned long data)
+ 				 *
+ 				 * XXX do key cache faulting
+ 				 */
+-				if (ds->ds_rxstat.rs_keyix ==
+-						AR5K_RXKEYIX_INVALID &&
+-						!(stat & AR5K_RXERR_CRC))
++				if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
++				    !(rs.rs_status & AR5K_RXERR_CRC))
+ 					goto accept;
+ 			}
+-			if (stat & AR5K_RXERR_MIC) {
++			if (rs.rs_status & AR5K_RXERR_MIC) {
+ 				rxs.flag |= RX_FLAG_MMIC_ERROR;
+ 				goto accept;
+ 			}
+ 
+ 			/* let crypto-error packets fall through in MNTR */
+-			if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
++			if ((rs.rs_status &
++				~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
+ 					sc->opmode != IEEE80211_IF_TYPE_MNTR)
+ 				goto next;
+ 		}
+ accept:
+-		len = ds->ds_rxstat.rs_datalen;
+-		pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len,
+-				PCI_DMA_FROMDEVICE);
++		pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr,
++				rs.rs_datalen, PCI_DMA_FROMDEVICE);
+ 		pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
+ 				PCI_DMA_FROMDEVICE);
+ 		bf->skb = NULL;
+ 
+-		skb_put(skb, len);
++		skb_put(skb, rs.rs_datalen);
+ 
+ 		/*
+ 		 * the hardware adds a padding to 4 byte boundaries between
+@@ -1787,13 +1879,23 @@ accept:
+ 		 * 15bit only. that means TSF extension has to be done within
+ 		 * 32768usec (about 32ms). it might be necessary to move this to
+ 		 * the interrupt handler, like it is done in madwifi.
++		 *
++		 * Unfortunately we don't know when the hardware takes the rx
++		 * timestamp (beginning of phy frame, data frame, end of rx?).
++		 * The only thing we know is that it is hardware specific...
++		 * On AR5213 it seems the rx timestamp is at the end of the
++		 * frame, but i'm not sure.
++		 *
++		 * NOTE: mac80211 defines mactime at the beginning of the first
++		 * data symbol. Since we don't have any time references it's
++		 * impossible to comply to that. This affects IBSS merge only
++		 * right now, so it's not too bad...
+ 		 */
+-		rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
++		rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
+ 		rxs.flag |= RX_FLAG_TSFT;
+ 
+-		rxs.freq = sc->curchan->freq;
+-		rxs.channel = sc->curchan->chan;
+-		rxs.phymode = sc->curmode;
++		rxs.freq = sc->curchan->center_freq;
++		rxs.band = sc->curband->band;
+ 
+ 		/*
+ 		 * signal quality:
+@@ -1803,25 +1905,25 @@ accept:
+ 		/* noise floor in dBm, from the last noise calibration */
+ 		rxs.noise = sc->ah->ah_noise_floor;
+ 		/* signal level in dBm */
+-		rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi;
++		rxs.ssi = rxs.noise + rs.rs_rssi;
+ 		/*
+ 		 * "signal" is actually displayed as Link Quality by iwconfig
+ 		 * we provide a percentage based on rssi (assuming max rssi 64)
+ 		 */
+-		rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
++		rxs.signal = rs.rs_rssi * 100 / 64;
+ 
+-		rxs.antenna = ds->ds_rxstat.rs_antenna;
+-		rxs.rate = ds->ds_rxstat.rs_rate;
+-		rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);
++		rxs.antenna = rs.rs_antenna;
++		rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
++		rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
+ 
+ 		ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
+ 
+ 		/* check beacons in IBSS mode */
+ 		if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
+-			ath5k_check_ibss_hw_merge(sc, skb);
++			ath5k_check_ibss_tsf(sc, skb, &rxs);
+ 
+ 		__ieee80211_rx(sc->hw, skb, &rxs);
+-		sc->led_rxrate = ds->ds_rxstat.rs_rate;
++		sc->led_rxrate = rs.rs_rate;
+ 		ath5k_led_event(sc, ATH_LED_RX);
+ next:
+ 		list_move_tail(&bf->list, &sc->rxbuf);
+@@ -1840,6 +1942,7 @@ static void
+ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ {
+ 	struct ieee80211_tx_status txs = {};
++	struct ath5k_tx_status ts = {};
+ 	struct ath5k_buf *bf, *bf0;
+ 	struct ath5k_desc *ds;
+ 	struct sk_buff *skb;
+@@ -1852,7 +1955,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ 		/* TODO only one segment */
+ 		pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
+ 				sc->desc_len, PCI_DMA_FROMDEVICE);
+-		ret = sc->ah->ah_proc_tx_desc(sc->ah, ds);
++		ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+ 		if (unlikely(ret == -EINPROGRESS))
+ 			break;
+ 		else if (unlikely(ret)) {
+@@ -1867,17 +1970,16 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ 				PCI_DMA_TODEVICE);
+ 
+ 		txs.control = bf->ctl;
+-		txs.retry_count = ds->ds_txstat.ts_shortretry +
+-			ds->ds_txstat.ts_longretry / 6;
+-		if (unlikely(ds->ds_txstat.ts_status)) {
++		txs.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
++		if (unlikely(ts.ts_status)) {
+ 			sc->ll_stats.dot11ACKFailureCount++;
+-			if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY)
++			if (ts.ts_status & AR5K_TXERR_XRETRY)
+ 				txs.excessive_retries = 1;
+-			else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT)
++			else if (ts.ts_status & AR5K_TXERR_FILT)
+ 				txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
+ 		} else {
+ 			txs.flags |= IEEE80211_TX_STATUS_ACK;
+-			txs.ack_signal = ds->ds_txstat.ts_rssi;
++			txs.ack_signal = ts.ts_rssi;
+ 		}
+ 
+ 		ieee80211_tx_status(sc->hw, skb, &txs);
+@@ -1958,8 +2060,9 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+ 	ds->ds_data = bf->skbaddr;
+ 	ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
+ 			ieee80211_get_hdrlen_from_skb(skb),
+-			AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1,
+-			AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0);
++			AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
++			ctl->tx_rate->hw_value, 1, AR5K_TXKEYIX_INVALID,
++			antenna, flags, 0, 0);
+ 	if (ret)
+ 		goto err_unmap;
+ 
+@@ -2050,7 +2153,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
+  * beacon timer registers.
+  *
+  * This is called in a variety of situations, e.g. when a beacon is received,
+- * when a HW merge has been detected, but also when an new IBSS is created or
++ * when a TSF update has been detected, but also when an new IBSS is created or
+  * when we otherwise know we have to update the timers, but we keep it in this
+  * function to have it all together in one place.
+  */
+@@ -2150,7 +2253,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
+  * another AP to associate with.
+  *
+  * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
+- * interrupts to detect HW merges only.
++ * interrupts to detect TSF updates only.
+  *
+  * AP mode is missing.
+  */
+@@ -2170,7 +2273,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
+ 		 * hardware send the beacons automatically. We have to load it
+ 		 * only once here.
+ 		 * We use the SWBA interrupt only to keep track of the beacon
+-		 * timers in order to detect HW merges (automatic TSF updates).
++		 * timers in order to detect automatic TSF updates.
+ 		 */
+ 		ath5k_beaconq_config(sc);
+ 
+@@ -2211,7 +2314,8 @@ ath5k_init(struct ath5k_softc *sc)
+ 	 * be followed by initialization of the appropriate bits
+ 	 * and then setup of the interrupt mask.
+ 	 */
+-	sc->curchan = sc->hw->conf.chan;
++	sc->curchan = sc->hw->conf.channel;
++	sc->curband = &sc->sbands[sc->curchan->band];
+ 	ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false);
+ 	if (ret) {
+ 		ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret);
+@@ -2238,7 +2342,8 @@ ath5k_init(struct ath5k_softc *sc)
+ 	 * Enable interrupts.
+ 	 */
+ 	sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
+-		AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL;
++		AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL |
++		AR5K_INT_MIB;
+ 
+ 	ath5k_hw_set_intr(sc->ah, sc->imask);
+ 	/* Set ack to be sent at low bit-rates */
+@@ -2382,8 +2487,8 @@ ath5k_intr(int irq, void *dev_id)
+ 				*
+ 				* In IBSS mode we use this interrupt just to
+ 				* keep track of the next TBTT (target beacon
+-				* transmission time) in order to detect hardware
+-				* merges (TSF updates).
++				* transmission time) in order to detect wether
++				* automatic TSF updates happened.
+ 				*/
+ 				if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ 					 /* XXX: only if VEOL suppported */
+@@ -2418,7 +2523,11 @@ ath5k_intr(int irq, void *dev_id)
+ 			if (status & AR5K_INT_BMISS) {
+ 			}
+ 			if (status & AR5K_INT_MIB) {
+-				/* TODO */
++				/*
++				 * These stats are also used for ANI i think
++				 * so how about updating them more often ?
++				 */
++				ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
+ 			}
+ 		}
+ 	} while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
+@@ -2448,7 +2557,8 @@ ath5k_calibrate(unsigned long data)
+ 	struct ath5k_hw *ah = sc->ah;
+ 
+ 	ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
+-		sc->curchan->chan, sc->curchan->val);
++		ieee80211_frequency_to_channel(sc->curchan->center_freq),
++		sc->curchan->hw_value);
+ 
+ 	if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) {
+ 		/*
+@@ -2460,7 +2570,8 @@ ath5k_calibrate(unsigned long data)
+ 	}
+ 	if (ath5k_hw_phy_calibrate(ah, sc->curchan))
+ 		ATH5K_ERR(sc, "calibration of channel %u failed\n",
+-				sc->curchan->chan);
++			ieee80211_frequency_to_channel(
++				sc->curchan->center_freq));
+ 
+ 	mod_timer(&sc->calib_tim, round_jiffies(jiffies +
+ 			msecs_to_jiffies(ath5k_calinterval * 1000)));
+@@ -2558,7 +2669,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ 		memmove(skb->data, skb->data+pad, hdrlen);
+ 	}
+ 
+-	sc->led_txrate = ctl->tx_rate;
++	sc->led_txrate = ctl->tx_rate->hw_value;
+ 
+ 	spin_lock_irqsave(&sc->txbuflock, flags);
+ 	if (list_empty(&sc->txbuf)) {
+@@ -2597,11 +2708,6 @@ ath5k_reset(struct ieee80211_hw *hw)
+ 	int ret;
+ 
+ 	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
+-	/*
+-	 * Convert to a hw channel description with the flags
+-	 * constrained to reflect the current operating mode.
+-	 */
+-	sc->curchan = hw->conf.chan;
+ 
+ 	ath5k_hw_set_intr(ah, 0);
+ 	ath5k_txq_cleanup(sc);
+@@ -2692,6 +2798,9 @@ end:
+ 	mutex_unlock(&sc->lock);
+ }
+ 
++/*
++ * TODO: Phy disable/diversity etc
++ */
+ static int
+ ath5k_config(struct ieee80211_hw *hw,
+ 			struct ieee80211_conf *conf)
+@@ -2699,9 +2808,9 @@ ath5k_config(struct ieee80211_hw *hw,
+ 	struct ath5k_softc *sc = hw->priv;
+ 
+ 	sc->bintval = conf->beacon_int;
+-	ath5k_setcurmode(sc, conf->phymode);
++	sc->power_level = conf->power_level;
+ 
+-	return ath5k_chan_set(sc, conf->chan);
++	return ath5k_chan_set(sc, conf->channel);
+ }
+ 
+ static int
+@@ -2869,7 +2978,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ 
+ 	switch(key->alg) {
+ 	case ALG_WEP:
+-		break;
++	/* XXX: fix hardware encryption, its not working. For now
++	 * allow software encryption */
++		/* break; */
+ 	case ALG_TKIP:
+ 	case ALG_CCMP:
+ 		return -EOPNOTSUPP;
+@@ -2909,6 +3020,10 @@ ath5k_get_stats(struct ieee80211_hw *hw,
+ 		struct ieee80211_low_level_stats *stats)
+ {
+ 	struct ath5k_softc *sc = hw->priv;
++	struct ath5k_hw *ah = sc->ah;
++
++	/* Force update */
++	ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
+ 
+ 	memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
+ 
+diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h
+index 8287ae7..3a97558 100644
+--- a/drivers/net/wireless/ath5k/base.h
++++ b/drivers/net/wireless/ath5k/base.h
+@@ -83,7 +83,7 @@ struct ath5k_txq {
+ #if CHAN_DEBUG
+ #define ATH_CHAN_MAX	(26+26+26+200+200)
+ #else
+-#define ATH_CHAN_MAX	(14+14+14+252+20)	/* XXX what's the max? */
++#define ATH_CHAN_MAX	(14+14+14+252+20)
+ #endif
+ 
+ /* Software Carrier, keeps track of the driver state
+@@ -95,15 +95,22 @@ struct ath5k_softc {
+ 	struct ieee80211_tx_queue_stats tx_stats;
+ 	struct ieee80211_low_level_stats ll_stats;
+ 	struct ieee80211_hw	*hw;		/* IEEE 802.11 common */
+-	struct ieee80211_hw_mode modes[NUM_DRIVER_MODES];
++	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+ 	struct ieee80211_channel channels[ATH_CHAN_MAX];
+-	struct ieee80211_rate	rates[AR5K_MAX_RATES * NUM_DRIVER_MODES];
++	struct ieee80211_rate	rates[AR5K_MAX_RATES * IEEE80211_NUM_BANDS];
+ 	enum ieee80211_if_types	opmode;
+ 	struct ath5k_hw		*ah;		/* Atheros HW */
+ 
+-#if ATH5K_DEBUG
++	struct ieee80211_supported_band		*curband;
++
++	u8			a_rates;
++	u8			b_rates;
++	u8			g_rates;
++	u8			xr_rates;
++
++#ifdef CONFIG_ATH5K_DEBUG
+ 	struct ath5k_dbg_info	debug;		/* debug info */
+-#endif
++#endif /* CONFIG_ATH5K_DEBUG */
+ 
+ 	struct ath5k_buf	*bufptr;	/* allocated buffer ptr */
+ 	struct ath5k_desc	*desc;		/* TX/RX descriptors */
+@@ -169,6 +176,7 @@ struct ath5k_softc {
+ 	unsigned int		nexttbtt;	/* next beacon time in TU */
+ 
+ 	struct timer_list	calib_tim;	/* calibration timer */
++	int 			power_level;	/* Requested tx power in dbm */
+ };
+ 
+ #define ath5k_hw_hasbssidmask(_ah) \
+diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
+index bb581ef..41d5fa3 100644
+--- a/drivers/net/wireless/ath5k/debug.c
++++ b/drivers/net/wireless/ath5k/debug.c
+@@ -65,7 +65,7 @@ static unsigned int ath5k_debug;
+ module_param_named(debug, ath5k_debug, uint, 0);
+ 
+ 
+-#if ATH5K_DEBUG
++#ifdef CONFIG_ATH5K_DEBUG
+ 
+ #include <linux/seq_file.h>
+ #include "reg.h"
+@@ -200,7 +200,8 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
+ {
+ 	struct ath5k_softc *sc = file->private_data;
+ 	char buf[100];
+-	snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
++	snprintf(buf, sizeof(buf), "0x%016llx\n",
++		 (unsigned long long)ath5k_hw_get_tsf64(sc->ah));
+ 	return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
+ }
+ 
+@@ -271,7 +272,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
+ 
+ 	tsf = ath5k_hw_get_tsf64(sc->ah);
+ 	len += snprintf(buf+len, sizeof(buf)-len,
+-		"TSF\t\t0x%016llx\tTU: %08x\n", tsf, TSF_TO_TU(tsf));
++		"TSF\t\t0x%016llx\tTU: %08x\n",
++		(unsigned long long)tsf, TSF_TO_TU(tsf));
+ 
+ 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ }
+@@ -340,7 +342,7 @@ static struct {
+ 	{ ATH5K_DEBUG_LED,	"led",		"LED mamagement" },
+ 	{ ATH5K_DEBUG_DUMP_RX,	"dumprx",	"print received skb content" },
+ 	{ ATH5K_DEBUG_DUMP_TX,	"dumptx",	"print transmit skb content" },
+-	{ ATH5K_DEBUG_DUMPMODES, "dumpmodes",	"dump modes" },
++	{ ATH5K_DEBUG_DUMPBANDS, "dumpbands",	"dump bands" },
+ 	{ ATH5K_DEBUG_TRACE,	"trace",	"trace function calls" },
+ 	{ ATH5K_DEBUG_ANY,	"all",		"show all debug levels" },
+ };
+@@ -452,43 +454,63 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
+ /* functions used in other places */
+ 
+ void
+-ath5k_debug_dump_modes(struct ath5k_softc *sc, struct ieee80211_hw_mode *modes)
++ath5k_debug_dump_bands(struct ath5k_softc *sc)
+ {
+-	unsigned int m, i;
++	unsigned int b, i;
+ 
+-	if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPMODES)))
++	if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
+ 		return;
+ 
+-	for (m = 0; m < NUM_DRIVER_MODES; m++) {
+-		printk(KERN_DEBUG "Mode %u: channels %d, rates %d\n", m,
+-				modes[m].num_channels, modes[m].num_rates);
++	BUG_ON(!sc->sbands);
++
++	for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
++		struct ieee80211_supported_band *band = &sc->sbands[b];
++		char bname[5];
++		switch (band->band) {
++		case IEEE80211_BAND_2GHZ:
++			strcpy(bname, "2 GHz");
++			break;
++		case IEEE80211_BAND_5GHZ:
++			strcpy(bname, "5 GHz");
++			break;
++		default:
++			printk(KERN_DEBUG "Band not supported: %d\n",
++				band->band);
++			return;
++		}
++		printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
++				band->n_channels, band->n_bitrates);
+ 		printk(KERN_DEBUG " channels:\n");
+-		for (i = 0; i < modes[m].num_channels; i++)
++		for (i = 0; i < band->n_channels; i++)
+ 			printk(KERN_DEBUG "  %3d %d %.4x %.4x\n",
+-					modes[m].channels[i].chan,
+-					modes[m].channels[i].freq,
+-					modes[m].channels[i].val,
+-					modes[m].channels[i].flag);
++					ieee80211_frequency_to_channel(
++						band->channels[i].center_freq),
++					band->channels[i].center_freq,
++					band->channels[i].hw_value,
++					band->channels[i].flags);
+ 		printk(KERN_DEBUG " rates:\n");
+-		for (i = 0; i < modes[m].num_rates; i++)
++		for (i = 0; i < band->n_bitrates; i++)
+ 			printk(KERN_DEBUG "  %4d %.4x %.4x %.4x\n",
+-					modes[m].rates[i].rate,
+-					modes[m].rates[i].val,
+-					modes[m].rates[i].flags,
+-					modes[m].rates[i].val2);
++					band->bitrates[i].bitrate,
++					band->bitrates[i].hw_value,
++					band->bitrates[i].flags,
++					band->bitrates[i].hw_value_short);
+ 	}
+ }
+ 
+ static inline void
+-ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
++ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
++		       struct ath5k_rx_status *rs)
+ {
+ 	struct ath5k_desc *ds = bf->desc;
++	struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
+ 
+ 	printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
+ 		ds, (unsigned long long)bf->daddr,
+-		ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
+-		ds->ds_hw[0], ds->ds_hw[1],
+-		!done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
++		ds->ds_link, ds->ds_data,
++		rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
++		rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
++		!done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
+ }
+ 
+ void
+@@ -496,6 +518,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
+ {
+ 	struct ath5k_desc *ds;
+ 	struct ath5k_buf *bf;
++	struct ath5k_rx_status rs = {};
+ 	int status;
+ 
+ 	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+@@ -507,9 +530,9 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
+ 	spin_lock_bh(&sc->rxbuflock);
+ 	list_for_each_entry(bf, &sc->rxbuf, list) {
+ 		ds = bf->desc;
+-		status = ah->ah_proc_rx_desc(ah, ds);
++		status = ah->ah_proc_rx_desc(ah, ds, &rs);
+ 		if (!status)
+-			ath5k_debug_printrxbuf(bf, status == 0);
++			ath5k_debug_printrxbuf(bf, status == 0, &rs);
+ 	}
+ 	spin_unlock_bh(&sc->rxbuflock);
+ }
+@@ -533,19 +556,24 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc,
+ }
+ 
+ void
+-ath5k_debug_printtxbuf(struct ath5k_softc *sc,
+-			struct ath5k_buf *bf, int done)
++ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ {
+ 	struct ath5k_desc *ds = bf->desc;
++	struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
++	struct ath5k_tx_status ts = {};
++	int done;
+ 
+ 	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+ 		return;
+ 
++	done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
++
+ 	printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
+ 		"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
+-		ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
+-		ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
+-		!done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
++		ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
++		td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
++		td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
++		done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
+ }
+ 
+-#endif /* if ATH5K_DEBUG */
++#endif /* ifdef CONFIG_ATH5K_DEBUG */
+diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h
+index c4fd8c4..2cf8d18 100644
+--- a/drivers/net/wireless/ath5k/debug.h
++++ b/drivers/net/wireless/ath5k/debug.h
+@@ -61,11 +61,6 @@
+ #ifndef _ATH5K_DEBUG_H
+ #define _ATH5K_DEBUG_H
+ 
+-/* set this to 1 for debugging output */
+-#ifndef ATH5K_DEBUG
+-#define ATH5K_DEBUG	0
+-#endif
+-
+ struct ath5k_softc;
+ struct ath5k_hw;
+ struct ieee80211_hw_mode;
+@@ -96,7 +91,7 @@ struct ath5k_dbg_info {
+  * @ATH5K_DEBUG_LED: led management
+  * @ATH5K_DEBUG_DUMP_RX: print received skb content
+  * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
+- * @ATH5K_DEBUG_DUMPMODES: dump modes
++ * @ATH5K_DEBUG_DUMPBANDS: dump bands
+  * @ATH5K_DEBUG_TRACE: trace function calls
+  * @ATH5K_DEBUG_ANY: show at any debug level
+  *
+@@ -118,12 +113,12 @@ enum ath5k_debug_level {
+ 	ATH5K_DEBUG_LED		= 0x00000080,
+ 	ATH5K_DEBUG_DUMP_RX	= 0x00000100,
+ 	ATH5K_DEBUG_DUMP_TX	= 0x00000200,
+-	ATH5K_DEBUG_DUMPMODES	= 0x00000400,
++	ATH5K_DEBUG_DUMPBANDS	= 0x00000400,
+ 	ATH5K_DEBUG_TRACE	= 0x00001000,
+ 	ATH5K_DEBUG_ANY		= 0xffffffff
+ };
+ 
+-#if ATH5K_DEBUG
++#ifdef CONFIG_ATH5K_DEBUG
+ 
+ #define ATH5K_TRACE(_sc) do { \
+ 	if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
+@@ -158,20 +153,20 @@ void
+ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
+ 
+ void
+-ath5k_debug_dump_modes(struct ath5k_softc *sc,
+-			struct ieee80211_hw_mode *modes);
++ath5k_debug_dump_bands(struct ath5k_softc *sc);
+ 
+ void
+ ath5k_debug_dump_skb(struct ath5k_softc *sc,
+ 			struct sk_buff *skb, const char *prefix, int tx);
+ 
+ void
+-ath5k_debug_printtxbuf(struct ath5k_softc *sc,
+-			struct ath5k_buf *bf, int done);
++ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
+ 
+ #else /* no debugging */
+ 
+-#define ATH5K_TRACE(_sc) /* empty */
++#include <linux/compiler.h>
++
++#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc))
+ 
+ static inline void __attribute__ ((format (printf, 3, 4)))
+ ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
+@@ -196,17 +191,15 @@ static inline void
+ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
+ 
+ static inline void
+-ath5k_debug_dump_modes(struct ath5k_softc *sc,
+-			struct ieee80211_hw_mode *modes) {}
++ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
+ 
+ static inline void
+ ath5k_debug_dump_skb(struct ath5k_softc *sc,
+ 			struct sk_buff *skb, const char *prefix, int tx) {}
+ 
+ static inline void
+-ath5k_debug_printtxbuf(struct ath5k_softc *sc,
+-			struct ath5k_buf *bf, int done) {}
++ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
+ 
+-#endif /* if ATH5K_DEBUG */
++#endif /* ifdef CONFIG_ATH5K_DEBUG */
+ 
+ #endif /* ifndef _ATH5K_DEBUG_H */
+diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
+index 0175743..5fb1ae6 100644
+--- a/drivers/net/wireless/ath5k/hw.c
++++ b/drivers/net/wireless/ath5k/hw.c
+@@ -1,4 +1,4 @@
+- /*
++/*
+  * Copyright (c) 2004-2007 Reyk Floeter <reyk at openbsd.org>
+  * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm at gmail.com>
+  * Copyright (c) 2007 Matthew W. S. Bell  <mentor at madwifi.org>
+@@ -48,14 +48,18 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+ static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+ 	unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
+ 	unsigned int);
+-static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
++static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
++					 struct ath5k_tx_status *);
+ static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+ 	unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
+ 	unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
+ 	unsigned int, unsigned int);
+-static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
+-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *);
++static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
++					 struct ath5k_tx_status *);
++static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *,
++					struct ath5k_rx_status *);
++static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *,
++					struct ath5k_rx_status *);
+ static int ath5k_hw_get_capabilities(struct ath5k_hw *);
+ 
+ static int ath5k_eeprom_init(struct ath5k_hw *);
+@@ -81,12 +85,12 @@ static int ath5k_hw_disable_pspoll(struct ath5k_hw *);
+ 
+ static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
+ {
+-	return turbo == true ? (usec * 80) : (usec * 40);
++	return turbo ? (usec * 80) : (usec * 40);
+ }
+ 
+ static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
+ {
+-	return turbo == true ? (clock / 80) : (clock / 40);
++	return turbo ? (clock / 80) : (clock / 40);
+ }
+ 
+ /*
+@@ -100,7 +104,7 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
+ 
+ 	for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
+ 		data = ath5k_hw_reg_read(ah, reg);
+-		if ((is_set == true) && (data & flag))
++		if (is_set && (data & flag))
+ 			break;
+ 		else if ((data & flag) == val)
+ 			break;
+@@ -116,11 +120,69 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
+ \***************************************/
+ 
+ /*
++ * Power On Self Test helper function
++ */
++static int ath5k_hw_post(struct ath5k_hw *ah)
++{
++
++	int i, c;
++	u16 cur_reg;
++	u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)};
++	u32 var_pattern;
++	u32 static_pattern[4] = {
++		0x55555555,	0xaaaaaaaa,
++		0x66666666,	0x99999999
++	};
++	u32 init_val;
++	u32 cur_val;
++
++	for (c = 0; c < 2; c++) {
++
++		cur_reg = regs[c];
++		init_val = ath5k_hw_reg_read(ah, cur_reg);
++
++		for (i = 0; i < 256; i++) {
++			var_pattern = i << 16 | i;
++			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
++			cur_val = ath5k_hw_reg_read(ah, cur_reg);
++
++			if (cur_val != var_pattern) {
++				ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
++				return -EAGAIN;
++			}
++
++			/* Found on ndiswrapper dumps */
++			var_pattern = 0x0039080f;
++			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
++		}
++
++		for (i = 0; i < 4; i++) {
++			var_pattern = static_pattern[i];
++			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
++			cur_val = ath5k_hw_reg_read(ah, cur_reg);
++
++			if (cur_val != var_pattern) {
++				ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
++				return -EAGAIN;
++			}
++
++			/* Found on ndiswrapper dumps */
++			var_pattern = 0x003b080f;
++			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
++		}
++	}
++
++	return 0;
++
++}
++
++/*
+  * Check if the device is supported and initialize the needed structs
+  */
+ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ {
+ 	struct ath5k_hw *ah;
++	struct pci_dev *pdev = sc->pdev;
+ 	u8 mac[ETH_ALEN];
+ 	int ret;
+ 	u32 srev;
+@@ -140,9 +202,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ 	 * HW information
+ 	 */
+ 
+-	/* Get reg domain from eeprom */
+-	ath5k_get_regdomain(ah);
+-
+ 	ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
+ 	ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
+ 	ah->ah_turbo = false;
+@@ -177,9 +236,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ 	}
+ 
+ 	if (ah->ah_version == AR5K_AR5212)
+-		ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status;
++		ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
+ 	else if (ah->ah_version <= AR5K_AR5211)
+-		ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status;
++		ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
+ 
+ 	/* Bring device out of sleep and reset it's units */
+ 	ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
+@@ -203,15 +262,19 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ 				CHANNEL_2GHZ);
+ 
+ 	/* Return on unsuported chips (unsupported eeprom etc) */
+-	if(srev >= AR5K_SREV_VER_AR5416){
++	if ((srev >= AR5K_SREV_VER_AR5416) &&
++	(srev < AR5K_SREV_VER_AR2425)) {
+ 		ATH5K_ERR(sc, "Device not yet supported.\n");
+ 		ret = -ENODEV;
+ 		goto err_free;
++	} else if (srev == AR5K_SREV_VER_AR2425) {
++		ATH5K_WARN(sc, "Support for RF2425 is under development.\n");
+ 	}
+ 
+ 	/* Identify single chip solutions */
+-	if((srev <= AR5K_SREV_VER_AR5414) &&
+-	(srev >= AR5K_SREV_VER_AR2424)) {
++	if (((srev <= AR5K_SREV_VER_AR5414) &&
++	(srev >= AR5K_SREV_VER_AR2413)) ||
++	(srev == AR5K_SREV_VER_AR2425)) {
+ 		ah->ah_single_chip = true;
+ 	} else {
+ 		ah->ah_single_chip = false;
+@@ -226,15 +289,87 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ 		ah->ah_radio = AR5K_RF5110;
+ 	} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
+ 		ah->ah_radio = AR5K_RF5111;
+-	} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
++		ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
++	} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) {
++
+ 		ah->ah_radio = AR5K_RF5112;
+-	} else {
++
++		if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
++			ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
++		} else {
++			ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
++		}
++
++	} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
++		ah->ah_radio = AR5K_RF2413;
++		ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
++	} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) {
+ 		ah->ah_radio = AR5K_RF5413;
++		ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
++	} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) {
++
++		/* AR5424 */
++		if (srev >= AR5K_SREV_VER_AR5424) {
++			ah->ah_radio = AR5K_RF5413;
++			ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424;
++		/* AR2424 */
++		} else {
++			ah->ah_radio = AR5K_RF2413; /* For testing */
++			ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
++		}
++
++	/*
++	 * Register returns 0x4 for radio revision
++	 * so ath5k_hw_radio_revision doesn't parse the value
++	 * correctly. For now we are based on mac's srev to
++	 * identify RF2425 radio.
++	 */
++	} else if (srev == AR5K_SREV_VER_AR2425) {
++		ah->ah_radio = AR5K_RF2425;
++		ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
+ 	}
+ 
+ 	ah->ah_phy = AR5K_PHY(0);
+ 
+ 	/*
++	 * Identify AR5212-based PCI-E cards
++	 * And write some initial settings.
++	 *
++	 * (doing a "strings" on ndis driver
++	 * -ar5211.sys- reveals the following
++	 * pci-e related functions:
++	 *
++	 * pcieClockReq
++	 * pcieRxErrNotify
++	 * pcieL1SKPEnable
++	 * pcieAspm
++	 * pcieDisableAspmOnRfWake
++	 * pciePowerSaveEnable
++	 *
++	 * I guess these point to ClockReq but
++	 * i'm not sure.)
++	 */
++	if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
++		ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080);
++		ath5k_hw_reg_write(ah, 0x24924924, 0x4080);
++		ath5k_hw_reg_write(ah, 0x28000039, 0x4080);
++		ath5k_hw_reg_write(ah, 0x53160824, 0x4080);
++		ath5k_hw_reg_write(ah, 0xe5980579, 0x4080);
++		ath5k_hw_reg_write(ah, 0x001defff, 0x4080);
++		ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080);
++		ath5k_hw_reg_write(ah, 0xbe105554, 0x4080);
++		ath5k_hw_reg_write(ah, 0x000e3007, 0x4080);
++		ath5k_hw_reg_write(ah, 0x00000000, 0x4084);
++	}
++
++	/*
++	 * POST
++	 */
++	ret = ath5k_hw_post(ah);
++	if (ret)
++		goto err_free;
++
++	/*
+ 	 * Get card capabilities, values, ...
+ 	 */
+ 
+@@ -280,7 +415,8 @@ err:
+  */
+ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
+ {
+-	u32 turbo, mode, clock;
++	struct pci_dev *pdev = ah->ah_sc->pdev;
++	u32 turbo, mode, clock, bus_flags;
+ 	int ret;
+ 
+ 	turbo = 0;
+@@ -357,10 +493,16 @@ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
+ 					AR5K_PHY_TURBO);
+ 	}
+ 
+-	/* ...reset chipset and PCI device */
+-	if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah,
+-				AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) {
+-		ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n");
++	/* reseting PCI on PCI-E cards results card to hang
++	 * and always return 0xffff... so we ingore that flag
++	 * for PCI-E cards */
++	bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
++
++	/* Reset chipset */
++	ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
++		AR5K_RESET_CTL_BASEBAND | bus_flags);
++	if (ret) {
++		ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+ 		return -EIO;
+ 	}
+ 
+@@ -405,15 +547,15 @@ const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah,
+ 
+ 	/* Get rate tables */
+ 	switch (mode) {
+-	case MODE_IEEE80211A:
++	case AR5K_MODE_11A:
+ 		return &ath5k_rt_11a;
+-	case MODE_ATHEROS_TURBO:
++	case AR5K_MODE_11A_TURBO:
+ 		return &ath5k_rt_turbo;
+-	case MODE_IEEE80211B:
++	case AR5K_MODE_11B:
+ 		return &ath5k_rt_11b;
+-	case MODE_IEEE80211G:
++	case AR5K_MODE_11G:
+ 		return &ath5k_rt_11g;
+-	case MODE_ATHEROS_TURBOG:
++	case AR5K_MODE_11G_TURBO:
+ 		return &ath5k_rt_xr;
+ 	}
+ 
+@@ -459,15 +601,15 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+ 		ds_coef_exp, ds_coef_man, clock;
+ 
+ 	if (!(ah->ah_version == AR5K_AR5212) ||
+-		!(channel->val & CHANNEL_OFDM))
++		!(channel->hw_value & CHANNEL_OFDM))
+ 		BUG();
+ 
+ 	/* Seems there are two PLLs, one for baseband sampling and one
+ 	 * for tuning. Tuning basebands are 40 MHz or 80MHz when in
+ 	 * turbo. */
+-	clock = channel->val & CHANNEL_TURBO ? 80 : 40;
++	clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
+ 	coef_scaled = ((5 * (clock << 24)) / 2) /
+-	channel->freq;
++	channel->center_freq;
+ 
+ 	for (coef_exp = 31; coef_exp > 0; coef_exp--)
+ 		if ((coef_scaled >> coef_exp) & 0x1)
+@@ -494,8 +636,7 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+  * ath5k_hw_write_rate_duration - set rate duration during hw resets
+  *
+  * @ah: the &struct ath5k_hw
+- * @driver_mode: one of enum ieee80211_phymode or our one of our own
+- *     vendor modes
++ * @mode: one of enum ath5k_driver_mode
+  *
+  * Write the rate duration table for the current mode upon hw reset. This
+  * is a helper for ath5k_hw_reset(). It seems all this is doing is setting
+@@ -506,19 +647,20 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+  *
+  */
+ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
+-       unsigned int driver_mode)
++       unsigned int mode)
+ {
+ 	struct ath5k_softc *sc = ah->ah_sc;
+ 	const struct ath5k_rate_table *rt;
++	struct ieee80211_rate srate = {};
+ 	unsigned int i;
+ 
+ 	/* Get rate table for the current operating mode */
+-	rt = ath5k_hw_get_rate_table(ah,
+-		driver_mode);
++	rt = ath5k_hw_get_rate_table(ah, mode);
+ 
+ 	/* Write rate duration table */
+ 	for (i = 0; i < rt->rate_count; i++) {
+ 		const struct ath5k_rate *rate, *control_rate;
++
+ 		u32 reg;
+ 		u16 tx_time;
+ 
+@@ -528,14 +670,16 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
+ 		/* Set ACK timeout */
+ 		reg = AR5K_RATE_DUR(rate->rate_code);
+ 
++		srate.bitrate = control_rate->rate_kbps/100;
++
+ 		/* An ACK frame consists of 10 bytes. If you add the FCS,
+ 		 * which ieee80211_generic_frame_duration() adds,
+ 		 * its 14 bytes. Note we use the control rate and not the
+ 		 * actual rate for this rate. See mac80211 tx.c
+ 		 * ieee80211_duration() for a brief description of
+ 		 * what rate we should choose to TX ACKs. */
+-		tx_time = ieee80211_generic_frame_duration(sc->hw,
+-			sc->vif, 10, control_rate->rate_kbps/100);
++		tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
++							sc->vif, 10, &srate));
+ 
+ 		ath5k_hw_reg_write(ah, tx_time, reg);
+ 
+@@ -568,8 +712,9 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 	struct ieee80211_channel *channel, bool change_channel)
+ {
+ 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+-	u32 data, s_seq, s_ant, s_led[3];
+-	unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1;
++	struct pci_dev *pdev = ah->ah_sc->pdev;
++	u32 data, s_seq, s_ant, s_led[3], dma_size;
++	unsigned int i, mode, freq, ee_mode, ant[2];
+ 	int ret;
+ 
+ 	ATH5K_TRACE(ah->ah_sc);
+@@ -585,7 +730,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 	 */
+ 	/*DCU/Antenna selection not available on 5210*/
+ 	if (ah->ah_version != AR5K_AR5210) {
+-		if (change_channel == true) {
++		if (change_channel) {
+ 			/* Seq number for queue 0 -do this for all queues ? */
+ 			s_seq = ath5k_hw_reg_read(ah,
+ 					AR5K_QUEUE_DFS_SEQNUM(0));
+@@ -599,12 +744,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 	s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
+ 	s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+ 
+-	if (change_channel == true && ah->ah_rf_banks != NULL)
++	if (change_channel && ah->ah_rf_banks != NULL)
+ 		ath5k_hw_get_rf_gain(ah);
+ 
+ 
+ 	/*Wakeup the device*/
+-	ret = ath5k_hw_nic_wakeup(ah, channel->val, false);
++	ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -620,43 +765,40 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 	if (ah->ah_version != AR5K_AR5210) {
+ 		if (ah->ah_radio != AR5K_RF5111 &&
+ 			ah->ah_radio != AR5K_RF5112 &&
+-			ah->ah_radio != AR5K_RF5413) {
++			ah->ah_radio != AR5K_RF5413 &&
++			ah->ah_radio != AR5K_RF2413 &&
++			ah->ah_radio != AR5K_RF2425) {
+ 			ATH5K_ERR(ah->ah_sc,
+ 				"invalid phy radio: %u\n", ah->ah_radio);
+ 			return -EINVAL;
+ 		}
+ 
+-		switch (channel->val & CHANNEL_MODES) {
++		switch (channel->hw_value & CHANNEL_MODES) {
+ 		case CHANNEL_A:
+-			mode = AR5K_INI_VAL_11A;
++			mode = AR5K_MODE_11A;
+ 			freq = AR5K_INI_RFGAIN_5GHZ;
+ 			ee_mode = AR5K_EEPROM_MODE_11A;
+-			driver_mode = MODE_IEEE80211A;
+ 			break;
+ 		case CHANNEL_G:
+-			mode = AR5K_INI_VAL_11G;
++			mode = AR5K_MODE_11G;
+ 			freq = AR5K_INI_RFGAIN_2GHZ;
+ 			ee_mode = AR5K_EEPROM_MODE_11G;
+-			driver_mode = MODE_IEEE80211G;
+ 			break;
+ 		case CHANNEL_B:
+-			mode = AR5K_INI_VAL_11B;
++			mode = AR5K_MODE_11B;
+ 			freq = AR5K_INI_RFGAIN_2GHZ;
+ 			ee_mode = AR5K_EEPROM_MODE_11B;
+-			driver_mode = MODE_IEEE80211B;
+ 			break;
+ 		case CHANNEL_T:
+-			mode = AR5K_INI_VAL_11A_TURBO;
++			mode = AR5K_MODE_11A_TURBO;
+ 			freq = AR5K_INI_RFGAIN_5GHZ;
+ 			ee_mode = AR5K_EEPROM_MODE_11A;
+-			driver_mode = MODE_ATHEROS_TURBO;
+ 			break;
+ 		/*Is this ok on 5211 too ?*/
+ 		case CHANNEL_TG:
+-			mode = AR5K_INI_VAL_11G_TURBO;
++			mode = AR5K_MODE_11G_TURBO;
+ 			freq = AR5K_INI_RFGAIN_2GHZ;
+ 			ee_mode = AR5K_EEPROM_MODE_11G;
+-			driver_mode = MODE_ATHEROS_TURBOG;
+ 			break;
+ 		case CHANNEL_XR:
+ 			if (ah->ah_version == AR5K_AR5211) {
+@@ -664,14 +806,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 					"XR mode not available on 5211");
+ 				return -EINVAL;
+ 			}
+-			mode = AR5K_INI_VAL_XR;
++			mode = AR5K_MODE_XR;
+ 			freq = AR5K_INI_RFGAIN_5GHZ;
+ 			ee_mode = AR5K_EEPROM_MODE_11A;
+-			driver_mode = MODE_IEEE80211A;
+ 			break;
+ 		default:
+ 			ATH5K_ERR(ah->ah_sc,
+-				"invalid channel: %d\n", channel->freq);
++				"invalid channel: %d\n", channel->center_freq);
+ 			return -EINVAL;
+ 		}
+ 
+@@ -701,15 +842,26 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 		/*
+ 		 * Write some more initial register settings
+ 		 */
+-		if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */
++		if (ah->ah_version == AR5K_AR5212) {
+ 			ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11));
+ 
+-			if (channel->val == CHANNEL_G)
+-				ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */
++			if (channel->hw_value == CHANNEL_G)
++				if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413)
++					ath5k_hw_reg_write(ah, 0x00f80d80,
++						AR5K_PHY(83));
++				else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424)
++					ath5k_hw_reg_write(ah, 0x00380140,
++						AR5K_PHY(83));
++				else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425)
++					ath5k_hw_reg_write(ah, 0x00fc0ec0,
++						AR5K_PHY(83));
++				else /* 2425 */
++					ath5k_hw_reg_write(ah, 0x00fc0fc0,
++						AR5K_PHY(83));
+ 			else
+-				ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83));
++				ath5k_hw_reg_write(ah, 0x00000000,
++					AR5K_PHY(83));
+ 
+-			ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */
+ 			ath5k_hw_reg_write(ah, 0x000009b5, 0xa228);
+ 			ath5k_hw_reg_write(ah, 0x0000000f, 0x8060);
+ 			ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
+@@ -722,7 +874,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 				AR5K_SREV_RAD_5112A) {
+ 			ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
+ 					AR5K_PHY_CCKTXCTL);
+-			if (channel->val & CHANNEL_5GHZ)
++			if (channel->hw_value & CHANNEL_5GHZ)
+ 				data = 0xffb81020;
+ 			else
+ 				data = 0xffb80d20;
+@@ -742,7 +894,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 		 * mac80211 are integrated */
+ 		if (ah->ah_version == AR5K_AR5212 &&
+ 			ah->ah_sc->vif != NULL)
+-			ath5k_hw_write_rate_duration(ah, driver_mode);
++			ath5k_hw_write_rate_duration(ah, mode);
+ 
+ 		/*
+ 		 * Write RF registers
+@@ -758,7 +910,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 
+ 		/* Write OFDM timings on 5212*/
+ 		if (ah->ah_version == AR5K_AR5212 &&
+-			channel->val & CHANNEL_OFDM) {
++			channel->hw_value & CHANNEL_OFDM) {
+ 			ret = ath5k_hw_write_ofdm_timings(ah, channel);
+ 			if (ret)
+ 				return ret;
+@@ -767,7 +919,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 		/*Enable/disable 802.11b mode on 5111
+ 		(enable 2111 frequency converter + CCK)*/
+ 		if (ah->ah_radio == AR5K_RF5111) {
+-			if (driver_mode == MODE_IEEE80211B)
++			if (mode == AR5K_MODE_11B)
+ 				AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
+ 				    AR5K_TXCFG_B_MODE);
+ 			else
+@@ -885,13 +1037,24 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 
+ 	/*
+ 	 * Set Rx/Tx DMA Configuration
+-	 *(passing dma size not available on 5210)
++	 *
++	 * Set maximum DMA size (512) except for PCI-E cards since
++	 * it causes rx overruns and tx errors (tested on 5424 but since
++	 * rx overruns also occur on 5416/5418 with madwifi we set 128
++	 * for all PCI-E cards to be safe).
++	 *
++	 * In dumps this is 128 for allchips.
++	 *
++	 * XXX: need to check 5210 for this
++	 * TODO: Check out tx triger level, it's always 64 on dumps but I
++	 * guess we can tweak it and see how it goes ;-)
+ 	 */
++	dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
+ 	if (ah->ah_version != AR5K_AR5210) {
+-		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR,
+-				AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE);
+-		AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW,
+-				AR5K_DMASIZE_512B);
++		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
++			AR5K_TXCFG_SDMAMR, dma_size);
++		AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
++			AR5K_RXCFG_SDMAMW, dma_size);
+ 	}
+ 
+ 	/*
+@@ -905,7 +1068,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 	if (ah->ah_version != AR5K_AR5210) {
+ 		data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+ 			AR5K_PHY_RX_DELAY_M;
+-		data = (channel->val & CHANNEL_CCK) ?
++		data = (channel->hw_value & CHANNEL_CCK) ?
+ 			((data << 2) / 22) : (data / 10);
+ 
+ 		udelay(100 + data);
+@@ -922,11 +1085,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 	if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ 			AR5K_PHY_AGCCTL_CAL, 0, false)) {
+ 		ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+-			channel->freq);
++			channel->center_freq);
+ 		return -EAGAIN;
+ 	}
+ 
+-	ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
++	ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -934,7 +1097,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 
+ 	/* A and G modes can use QAM modulation which requires enabling
+ 	 * I and Q calibration. Don't bother in B mode. */
+-	if (!(driver_mode == MODE_IEEE80211B)) {
++	if (!(mode == AR5K_MODE_11B)) {
+ 		ah->ah_calibration = true;
+ 		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+ 				AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+@@ -981,6 +1144,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 
+ 	/*
+ 	 * Set the 32MHz reference clock on 5212 phy clock sleep register
++	 *
++	 * TODO: Find out how to switch to external 32Khz clock to save power
+ 	 */
+ 	if (ah->ah_version == AR5K_AR5212) {
+ 		ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
+@@ -988,9 +1153,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ 		ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
+ 		ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
+ 		ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
+-		ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ?
+-			AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112,
+-			AR5K_PHY_SPENDING);
++		ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
++	}
++
++	if (ah->ah_version == AR5K_AR5212) {
++		ath5k_hw_reg_write(ah, 0x000100aa, 0x8118);
++		ath5k_hw_reg_write(ah, 0x00003210, 0x811c);
++		ath5k_hw_reg_write(ah, 0x00000052, 0x8108);
++		if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413)
++			ath5k_hw_reg_write(ah, 0x00000004, 0x8120);
+ 	}
+ 
+ 	/*
+@@ -1065,7 +1236,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
+ 		staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
+ 		/* fallthrough */
+ 	case AR5K_PM_NETWORK_SLEEP:
+-		if (set_chip == true)
++		if (set_chip)
+ 			ath5k_hw_reg_write(ah,
+ 				AR5K_SLEEP_CTL_SLE | sleep_duration,
+ 				AR5K_SLEEP_CTL);
+@@ -1074,7 +1245,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
+ 		break;
+ 
+ 	case AR5K_PM_FULL_SLEEP:
+-		if (set_chip == true)
++		if (set_chip)
+ 			ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
+ 				AR5K_SLEEP_CTL);
+ 
+@@ -1082,7 +1253,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
+ 		break;
+ 
+ 	case AR5K_PM_AWAKE:
+-		if (set_chip == false)
++		if (!set_chip)
+ 			goto commit;
+ 
+ 		ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
+@@ -1389,7 +1560,7 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
+ 	trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
+ 			AR5K_TXCFG_TXFULL);
+ 
+-	if (increase == false) {
++	if (!increase) {
+ 		if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
+ 			goto done;
+ 	} else
+@@ -1592,9 +1763,10 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
+ /*
+  * Write to eeprom - currently disabled, use at your own risk
+  */
++#if 0
+ static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
+ {
+-#if 0
++
+ 	u32 status, timeout;
+ 
+ 	ATH5K_TRACE(ah->ah_sc);
+@@ -1636,10 +1808,11 @@ static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
+ 		}
+ 		udelay(15);
+ 	}
+-#endif
++
+ 	ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!");
+ 	return -EIO;
+ }
++#endif
+ 
+ /*
+  * Translate binary channel representation in EEPROM to frequency
+@@ -2045,50 +2218,6 @@ static int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+ }
+ 
+ /*
+- * Read/Write regulatory domain
+- */
+-static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write,
+-	enum ath5k_regdom *regdomain)
+-{
+-	u16 ee_regdomain;
+-
+-	/* Read current value */
+-	if (write != true) {
+-		ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain;
+-		*regdomain = ath5k_regdom_to_ieee(ee_regdomain);
+-		return true;
+-	}
+-
+-	ee_regdomain = ath5k_regdom_from_ieee(*regdomain);
+-
+-	/* Try to write a new value */
+-	if (ah->ah_capabilities.cap_eeprom.ee_protect &
+-			AR5K_EEPROM_PROTECT_WR_128_191)
+-		return false;
+-	if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0)
+-		return false;
+-
+-	ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
+-
+-	return true;
+-}
+-
+-/*
+- * Use the above to write a new regulatory domain
+- */
+-int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain)
+-{
+-	enum ath5k_regdom ieee_regdomain;
+-
+-	ieee_regdomain = ath5k_regdom_to_ieee(regdomain);
+-
+-	if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true)
+-		return 0;
+-
+-	return -EIO;
+-}
+-
+-/*
+  * Fill the capabilities struct
+  */
+ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
+@@ -2110,8 +2239,8 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
+ 		ah->ah_capabilities.cap_range.range_2ghz_max = 0;
+ 
+ 		/* Set supported modes */
+-		__set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode);
+-		__set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode);
++		__set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
++		__set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
+ 	} else {
+ 		/*
+ 		 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
+@@ -2133,12 +2262,12 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
+ 			ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
+ 
+ 			/* Set supported modes */
+-			__set_bit(MODE_IEEE80211A,
++			__set_bit(AR5K_MODE_11A,
+ 					ah->ah_capabilities.cap_mode);
+-			__set_bit(MODE_ATHEROS_TURBO,
++			__set_bit(AR5K_MODE_11A_TURBO,
+ 					ah->ah_capabilities.cap_mode);
+ 			if (ah->ah_version == AR5K_AR5212)
+-				__set_bit(MODE_ATHEROS_TURBOG,
++				__set_bit(AR5K_MODE_11G_TURBO,
+ 						ah->ah_capabilities.cap_mode);
+ 		}
+ 
+@@ -2150,11 +2279,11 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
+ 			ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
+ 
+ 			if (AR5K_EEPROM_HDR_11B(ee_header))
+-				__set_bit(MODE_IEEE80211B,
++				__set_bit(AR5K_MODE_11B,
+ 						ah->ah_capabilities.cap_mode);
+ 
+ 			if (AR5K_EEPROM_HDR_11G(ee_header))
+-				__set_bit(MODE_IEEE80211G,
++				__set_bit(AR5K_MODE_11G,
+ 						ah->ah_capabilities.cap_mode);
+ 		}
+ 	}
+@@ -2279,8 +2408,8 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
+ 	 * Set simple BSSID mask on 5212
+ 	 */
+ 	if (ah->ah_version == AR5K_AR5212) {
+-		ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0);
+-		ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1);
++		ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
++		ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
+ 	}
+ 
+ 	/*
+@@ -2425,6 +2554,8 @@ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
+ {
+ 	ATH5K_TRACE(ah->ah_sc);
+ 	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
++
++	/* TODO: ANI Support */
+ }
+ 
+ /*
+@@ -2434,6 +2565,8 @@ void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah)
+ {
+ 	ATH5K_TRACE(ah->ah_sc);
+ 	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
++
++	/* TODO: ANI Support */
+ }
+ 
+ /*
+@@ -2828,15 +2961,19 @@ int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
+  * Update mib counters (statistics)
+  */
+ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
+-		struct ath5k_mib_stats *statistics)
++		struct ieee80211_low_level_stats  *stats)
+ {
+ 	ATH5K_TRACE(ah->ah_sc);
++
+ 	/* Read-And-Clear */
+-	statistics->ackrcv_bad += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
+-	statistics->rts_bad += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
+-	statistics->rts_good += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
+-	statistics->fcs_bad += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
+-	statistics->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
++	stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
++	stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
++	stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
++	stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
++
++	/* XXX: Should we use this to track beacon count ?
++	 * -we read it anyway to clear the register */
++	ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
+ 
+ 	/* Reset profile count registers on 5212*/
+ 	if (ah->ah_version == AR5K_AR5212) {
+@@ -2937,8 +3074,16 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
+ 	for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
+ 		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
+ 
+-	/* Set NULL encryption on non-5210*/
+-	if (ah->ah_version != AR5K_AR5210)
++	/*
++	 * 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
++	 */
++	if (ah->ah_version > AR5K_AR5211)
+ 		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ 				AR5K_KEYTABLE_TYPE(entry));
+ 
+@@ -3186,19 +3331,19 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+ 			return 0;
+ 
+ 		/* Set Slot time */
+-		ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ 			AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
+ 			AR5K_SLOT_TIME);
+ 		/* Set ACK_CTS timeout */
+-		ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ 			AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
+ 			AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
+ 		/* Set Transmit Latency */
+-		ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ 			AR5K_INIT_TRANSMIT_LATENCY_TURBO :
+ 			AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
+ 		/* Set IFS0 */
+-		if (ah->ah_turbo == true)
++		if (ah->ah_turbo)
+ 			 ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
+ 				(ah->ah_aifs + tq->tqi_aifs) *
+ 				AR5K_INIT_SLOT_TIME_TURBO) <<
+@@ -3211,16 +3356,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+ 				AR5K_INIT_SIFS, AR5K_IFS0);
+ 
+ 		/* Set IFS1 */
+-		ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ 			AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
+ 			AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
+ 		/* Set PHY register 0x9844 (??) */
+-		ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ 			(ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 :
+ 			(ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C,
+ 			AR5K_PHY(17));
+ 		/* Set Frame Control Register */
+-		ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ 			(AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
+ 			AR5K_PHY_TURBO_SHORT | 0x2020) :
+ 			(AR5K_PHY_FRAME_CTL_INI | 0x1020),
+@@ -3259,7 +3404,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+ 	/*
+ 	 * Calculate and set retry limits
+ 	 */
+-	if (ah->ah_software_retry == true) {
++	if (ah->ah_software_retry) {
+ 		/* XXX Need to test this */
+ 		retry_lg = ah->ah_limit_tx_retries;
+ 		retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
+@@ -3507,10 +3652,10 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 	unsigned int rtscts_rate, unsigned int rtscts_duration)
+ {
+ 	u32 frame_type;
+-	struct ath5k_hw_2w_tx_desc *tx_desc;
++	struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ 	unsigned int frame_len;
+ 
+-	tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
++	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+ 
+ 	/*
+ 	 * Validate input
+@@ -3529,12 +3674,8 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 		return -EINVAL;
+ 	}
+ 
+-	/* Clear status descriptor */
+-	memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status));
+-
+-	/* Initialize control descriptor */
+-	tx_desc->tx_control_0 = 0;
+-	tx_desc->tx_control_1 = 0;
++	/* Clear descriptor */
++	memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
+ 
+ 	/* Setup control descriptor */
+ 
+@@ -3546,7 +3687,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 	if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
+ 		return -EINVAL;
+ 
+-	tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
++	tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+ 
+ 	/* Verify and set buffer length */
+ 
+@@ -3557,7 +3698,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 	if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
+ 		return -EINVAL;
+ 
+-	tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
++	tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+ 
+ 	/*
+ 	 * Verify and set header length
+@@ -3566,7 +3707,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 	if (ah->ah_version == AR5K_AR5210) {
+ 		if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
+ 			return -EINVAL;
+-		tx_desc->tx_control_0 |=
++		tx_ctl->tx_control_0 |=
+ 			AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
+ 	}
+ 
+@@ -3582,19 +3723,19 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 			frame_type = type /*<< 2 ?*/;
+ 		}
+ 
+-		tx_desc->tx_control_0 |=
++		tx_ctl->tx_control_0 |=
+ 			AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
+ 			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+ 	} else {
+-		tx_desc->tx_control_0 |=
++		tx_ctl->tx_control_0 |=
+ 			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
+ 			AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
+-		tx_desc->tx_control_1 |=
++		tx_ctl->tx_control_1 |=
+ 			AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
+ 	}
+ #define _TX_FLAGS(_c, _flag)						\
+ 	if (flags & AR5K_TXDESC_##_flag)				\
+-		tx_desc->tx_control_##_c |=				\
++		tx_ctl->tx_control_##_c |=				\
+ 			AR5K_2W_TX_DESC_CTL##_c##_##_flag
+ 
+ 	_TX_FLAGS(0, CLRDMASK);
+@@ -3609,9 +3750,9 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 	 * WEP crap
+ 	 */
+ 	if (key_index != AR5K_TXKEYIX_INVALID) {
+-		tx_desc->tx_control_0 |=
++		tx_ctl->tx_control_0 |=
+ 			AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+-		tx_desc->tx_control_1 |=
++		tx_ctl->tx_control_1 |=
+ 			AR5K_REG_SM(key_index,
+ 			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+ 	}
+@@ -3621,7 +3762,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 	 */
+ 	if ((ah->ah_version == AR5K_AR5210) &&
+ 			(flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
+-		tx_desc->tx_control_1 |= rtscts_duration &
++		tx_ctl->tx_control_1 |= rtscts_duration &
+ 				AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
+ 
+ 	return 0;
+@@ -3637,13 +3778,11 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ 	unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
+ 	unsigned int rtscts_duration)
+ {
+-	struct ath5k_hw_4w_tx_desc *tx_desc;
+-	struct ath5k_hw_tx_status *tx_status;
++	struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ 	unsigned int frame_len;
+ 
+ 	ATH5K_TRACE(ah->ah_sc);
+-	tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+-	tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
++	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+ 
+ 	/*
+ 	 * Validate input
+@@ -3662,14 +3801,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ 		return -EINVAL;
+ 	}
+ 
+-	/* Clear status descriptor */
+-	memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status));
+-
+-	/* Initialize control descriptor */
+-	tx_desc->tx_control_0 = 0;
+-	tx_desc->tx_control_1 = 0;
+-	tx_desc->tx_control_2 = 0;
+-	tx_desc->tx_control_3 = 0;
++	/* Clear descriptor */
++	memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
+ 
+ 	/* Setup control descriptor */
+ 
+@@ -3681,7 +3814,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ 	if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
+ 		return -EINVAL;
+ 
+-	tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
++	tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+ 
+ 	/* Verify and set buffer length */
+ 
+@@ -3692,20 +3825,20 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ 	if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
+ 		return -EINVAL;
+ 
+-	tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
++	tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+ 
+-	tx_desc->tx_control_0 |=
++	tx_ctl->tx_control_0 |=
+ 		AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
+ 		AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
+-	tx_desc->tx_control_1 |= AR5K_REG_SM(type,
++	tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
+ 					AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
+-	tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
++	tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+ 					AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
+-	tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
++	tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+ 
+ #define _TX_FLAGS(_c, _flag)			\
+ 	if (flags & AR5K_TXDESC_##_flag)	\
+-		tx_desc->tx_control_##_c |=	\
++		tx_ctl->tx_control_##_c |=	\
+ 			AR5K_4W_TX_DESC_CTL##_c##_##_flag
+ 
+ 	_TX_FLAGS(0, CLRDMASK);
+@@ -3721,8 +3854,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ 	 * WEP crap
+ 	 */
+ 	if (key_index != AR5K_TXKEYIX_INVALID) {
+-		tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+-		tx_desc->tx_control_1 |= AR5K_REG_SM(key_index,
++		tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
++		tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
+ 				AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+ 	}
+ 
+@@ -3733,9 +3866,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ 		if ((flags & AR5K_TXDESC_RTSENA) &&
+ 				(flags & AR5K_TXDESC_CTSENA))
+ 			return -EINVAL;
+-		tx_desc->tx_control_2 |= rtscts_duration &
++		tx_ctl->tx_control_2 |= rtscts_duration &
+ 				AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
+-		tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
++		tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+ 				AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
+ 	}
+ 
+@@ -3750,7 +3883,7 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
+ 	unsigned int tx_rate3, u_int tx_tries3)
+ {
+-	struct ath5k_hw_4w_tx_desc *tx_desc;
++	struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ 
+ 	/*
+ 	 * Rates can be 0 as long as the retry count is 0 too.
+@@ -3767,14 +3900,14 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 	}
+ 
+ 	if (ah->ah_version == AR5K_AR5212) {
+-		tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
++		tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+ 
+ #define _XTX_TRIES(_n)							\
+ 	if (tx_tries##_n) {						\
+-		tx_desc->tx_control_2 |=				\
++		tx_ctl->tx_control_2 |=				\
+ 		    AR5K_REG_SM(tx_tries##_n,				\
+ 		    AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n);		\
+-		tx_desc->tx_control_3 |=				\
++		tx_ctl->tx_control_3 |=				\
+ 		    AR5K_REG_SM(tx_rate##_n,				\
+ 		    AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n);		\
+ 	}
+@@ -3795,13 +3928,15 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+  * Proccess the tx status descriptor on 5210/5211
+  */
+ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
+-		struct ath5k_desc *desc)
++		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+ {
++	struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ 	struct ath5k_hw_tx_status *tx_status;
+-	struct ath5k_hw_2w_tx_desc *tx_desc;
+ 
+-	tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
+-	tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0];
++	ATH5K_TRACE(ah->ah_sc);
++
++	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
++	tx_status = &desc->ud.ds_tx5210.tx_stat;
+ 
+ 	/* No frame has been send or error */
+ 	if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
+@@ -3810,32 +3945,32 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
+ 	/*
+ 	 * Get descriptor status
+ 	 */
+-	desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
++	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ 		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+-	desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
++	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ 		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+-	desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
++	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ 		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+-	/*TODO: desc->ds_us.tx.ts_virtcol + test*/
+-	desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
++	/*TODO: ts->ts_virtcol + test*/
++	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ 		AR5K_DESC_TX_STATUS1_SEQ_NUM);
+-	desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
++	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ 		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+-	desc->ds_us.tx.ts_antenna = 1;
+-	desc->ds_us.tx.ts_status = 0;
+-	desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0,
++	ts->ts_antenna = 1;
++	ts->ts_status = 0;
++	ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
+ 		AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+ 
+ 	if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
+ 		if (tx_status->tx_status_0 &
+ 				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+-			desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
++			ts->ts_status |= AR5K_TXERR_XRETRY;
+ 
+ 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+-			desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
++			ts->ts_status |= AR5K_TXERR_FIFO;
+ 
+ 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+-			desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
++			ts->ts_status |= AR5K_TXERR_FILT;
+ 	}
+ 
+ 	return 0;
+@@ -3845,14 +3980,15 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
+  * Proccess a tx descriptor on 5212
+  */
+ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+-		struct ath5k_desc *desc)
++		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+ {
++	struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ 	struct ath5k_hw_tx_status *tx_status;
+-	struct ath5k_hw_4w_tx_desc *tx_desc;
+ 
+ 	ATH5K_TRACE(ah->ah_sc);
+-	tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+-	tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
++
++	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
++	tx_status = &desc->ud.ds_tx5212.tx_stat;
+ 
+ 	/* No frame has been send or error */
+ 	if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
+@@ -3861,42 +3997,42 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+ 	/*
+ 	 * Get descriptor status
+ 	 */
+-	desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
++	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ 		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+-	desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
++	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ 		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+-	desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
++	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ 		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+-	desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
++	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ 		AR5K_DESC_TX_STATUS1_SEQ_NUM);
+-	desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
++	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ 		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+-	desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 &
++	ts->ts_antenna = (tx_status->tx_status_1 &
+ 		AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
+-	desc->ds_us.tx.ts_status = 0;
++	ts->ts_status = 0;
+ 
+ 	switch (AR5K_REG_MS(tx_status->tx_status_1,
+ 			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
+ 	case 0:
+-		desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
++		ts->ts_rate = tx_ctl->tx_control_3 &
+ 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+ 		break;
+ 	case 1:
+-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
++		ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+ 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
+-		desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
++		ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+ 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+ 		break;
+ 	case 2:
+-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
++		ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+ 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
+-		desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
++		ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+ 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
+ 		break;
+ 	case 3:
+-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
++		ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+ 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
+-		desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
++		ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+ 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
+ 		break;
+ 	}
+@@ -3904,13 +4040,13 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+ 	if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
+ 		if (tx_status->tx_status_0 &
+ 				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+-			desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
++			ts->ts_status |= AR5K_TXERR_XRETRY;
+ 
+ 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+-			desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
++			ts->ts_status |= AR5K_TXERR_FIFO;
+ 
+ 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+-			desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
++			ts->ts_status |= AR5K_TXERR_FILT;
+ 	}
+ 
+ 	return 0;
+@@ -3926,31 +4062,27 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ 			u32 size, unsigned int flags)
+ {
+-	struct ath5k_rx_desc *rx_desc;
++	struct ath5k_hw_rx_ctl *rx_ctl;
+ 
+ 	ATH5K_TRACE(ah->ah_sc);
+-	rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0;
++	rx_ctl = &desc->ud.ds_rx.rx_ctl;
+ 
+ 	/*
+-	 *Clear ds_hw
++	 * Clear the descriptor
+ 	 * If we don't clean the status descriptor,
+ 	 * while scanning we get too many results,
+ 	 * most of them virtual, after some secs
+ 	 * of scanning system hangs. M.F.
+ 	*/
+-	memset(desc->ds_hw, 0, sizeof(desc->ds_hw));
+-
+-	/*Initialize rx descriptor*/
+-	rx_desc->rx_control_0 = 0;
+-	rx_desc->rx_control_1 = 0;
++	memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
+ 
+ 	/* Setup descriptor */
+-	rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+-	if (unlikely(rx_desc->rx_control_1 != size))
++	rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
++	if (unlikely(rx_ctl->rx_control_1 != size))
+ 		return -EINVAL;
+ 
+ 	if (flags & AR5K_RXDESC_INTREQ)
+-		rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
++		rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+ 
+ 	return 0;
+ }
+@@ -3958,67 +4090,68 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ /*
+  * Proccess the rx status descriptor on 5210/5211
+  */
+-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
+-		struct ath5k_desc *desc)
++static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
++		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+ {
+-	struct ath5k_hw_old_rx_status *rx_status;
++	struct ath5k_hw_rx_status *rx_status;
+ 
+-	rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0];
++	rx_status = &desc->ud.ds_rx.u.rx_stat;
+ 
+ 	/* No frame received / not ready */
+-	if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE)
++	if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE)
+ 				== 0))
+ 		return -EINPROGRESS;
+ 
+ 	/*
+ 	 * Frame receive status
+ 	 */
+-	desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
+-		AR5K_OLD_RX_DESC_STATUS0_DATA_LEN;
+-	desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+-		AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+-	desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+-		AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE);
+-	desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
+-		AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+-	desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
+-		AR5K_OLD_RX_DESC_STATUS0_MORE;
+-	desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+-		AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+-	desc->ds_us.rx.rs_status = 0;
++	rs->rs_datalen = rx_status->rx_status_0 &
++		AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
++	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
++		AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
++	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
++		AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
++	rs->rs_antenna = rx_status->rx_status_0 &
++		AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
++	rs->rs_more = rx_status->rx_status_0 &
++		AR5K_5210_RX_DESC_STATUS0_MORE;
++	/* TODO: this timestamp is 13 bit, later on we assume 15 bit */
++	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
++		AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
++	rs->rs_status = 0;
+ 
+ 	/*
+ 	 * Key table status
+ 	 */
+-	if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID)
+-		desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+-			AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX);
++	if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
++		rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
++			AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
+ 	else
+-		desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
++		rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+ 
+ 	/*
+ 	 * Receive/descriptor errors
+ 	 */
+-	if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK)
+-			== 0) {
+-		if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR)
+-			desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
++	if ((rx_status->rx_status_1 &
++			AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
++		if (rx_status->rx_status_1 &
++				AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
++			rs->rs_status |= AR5K_RXERR_CRC;
+ 
+ 		if (rx_status->rx_status_1 &
+-				AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN)
+-			desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
++				AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
++			rs->rs_status |= AR5K_RXERR_FIFO;
+ 
+ 		if (rx_status->rx_status_1 &
+-				AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) {
+-			desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
+-			desc->ds_us.rx.rs_phyerr =
+-				AR5K_REG_MS(rx_status->rx_status_1,
+-					AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR);
++				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
++			rs->rs_status |= AR5K_RXERR_PHY;
++			rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
++					   AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
+ 		}
+ 
+ 		if (rx_status->rx_status_1 &
+-				AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+-			desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
++				AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
++			rs->rs_status |= AR5K_RXERR_DECRYPT;
+ 	}
+ 
+ 	return 0;
+@@ -4027,71 +4160,72 @@ static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
+ /*
+  * Proccess the rx status descriptor on 5212
+  */
+-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
+-		struct ath5k_desc *desc)
++static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
++		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+ {
+-	struct ath5k_hw_new_rx_status *rx_status;
++	struct ath5k_hw_rx_status *rx_status;
+ 	struct ath5k_hw_rx_error *rx_err;
+ 
+ 	ATH5K_TRACE(ah->ah_sc);
+-	rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0];
++	rx_status = &desc->ud.ds_rx.u.rx_stat;
+ 
+ 	/* Overlay on error */
+-	rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0];
++	rx_err = &desc->ud.ds_rx.u.rx_err;
+ 
+ 	/* No frame received / not ready */
+-	if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE)
++	if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE)
+ 				== 0))
+ 		return -EINPROGRESS;
+ 
+ 	/*
+ 	 * Frame receive status
+ 	 */
+-	desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
+-		AR5K_NEW_RX_DESC_STATUS0_DATA_LEN;
+-	desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+-		AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+-	desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+-		AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE);
+-	desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
+-		AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+-	desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
+-		AR5K_NEW_RX_DESC_STATUS0_MORE;
+-	desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+-		AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+-	desc->ds_us.rx.rs_status = 0;
++	rs->rs_datalen = rx_status->rx_status_0 &
++		AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
++	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
++		AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
++	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
++		AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
++	rs->rs_antenna = rx_status->rx_status_0 &
++		AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
++	rs->rs_more = rx_status->rx_status_0 &
++		AR5K_5212_RX_DESC_STATUS0_MORE;
++	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
++		AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
++	rs->rs_status = 0;
+ 
+ 	/*
+ 	 * Key table status
+ 	 */
+-	if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID)
+-		desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+-				AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX);
++	if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
++		rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
++				AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
+ 	else
+-		desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
++		rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+ 
+ 	/*
+ 	 * Receive/descriptor errors
+ 	 */
+ 	if ((rx_status->rx_status_1 &
+-			AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
+-		if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR)
+-			desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
++			AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
++		if (rx_status->rx_status_1 &
++				AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
++			rs->rs_status |= AR5K_RXERR_CRC;
+ 
+ 		if (rx_status->rx_status_1 &
+-				AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) {
+-			desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
+-			desc->ds_us.rx.rs_phyerr =
+-				AR5K_REG_MS(rx_err->rx_error_1,
+-					AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
++				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
++			rs->rs_status |= AR5K_RXERR_PHY;
++			rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1,
++					   AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
+ 		}
+ 
+ 		if (rx_status->rx_status_1 &
+-				AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+-			desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
++				AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
++			rs->rs_status |= AR5K_RXERR_DECRYPT;
+ 
+-		if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR)
+-			desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
++		if (rx_status->rx_status_1 &
++				AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
++			rs->rs_status |= AR5K_RXERR_MIC;
+ 	}
+ 
+ 	return 0;
+@@ -4250,35 +4384,6 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
+ }
+ 
+ 
+-/*********************************\
+- Regulatory Domain/Channels Setup
+-\*********************************/
+-
+-u16 ath5k_get_regdomain(struct ath5k_hw *ah)
+-{
+-	u16 regdomain;
+-	enum ath5k_regdom ieee_regdomain;
+-#ifdef COUNTRYCODE
+-	u16 code;
+-#endif
+-
+-	ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain);
+-	ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
+-
+-#ifdef COUNTRYCODE
+-	/*
+-	 * Get the regulation domain by country code. This will ignore
+-	 * the settings found in the EEPROM.
+-	 */
+-	code = ieee80211_name2countrycode(COUNTRYCODE);
+-	ieee_regdomain = ieee80211_countrycode2regdomain(code);
+-#endif
+-
+-	regdomain = ath5k_regdom_from_ieee(ieee_regdomain);
+-	ah->ah_capabilities.cap_regdomain.reg_current = regdomain;
+-
+-	return regdomain;
+-}
+ 
+ 
+ /****************\
+diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/hw.h
+index d9a7c09..64fca8d 100644
+--- a/drivers/net/wireless/ath5k/hw.h
++++ b/drivers/net/wireless/ath5k/hw.h
+@@ -173,7 +173,10 @@ struct ath5k_eeprom_info {
+  * (rX: reserved fields possibily used by future versions of the ar5k chipset)
+  */
+ 
+-struct ath5k_rx_desc {
++/*
++ * common hardware RX control descriptor
++ */
++struct ath5k_hw_rx_ctl {
+ 	u32	rx_control_0; /* RX control word 0 */
+ 
+ #define AR5K_DESC_RX_CTL0			0x00000000
+@@ -185,69 +188,63 @@ struct ath5k_rx_desc {
+ } __packed;
+ 
+ /*
+- * 5210/5211 rx status descriptor
++ * common hardware RX status descriptor
++ * 5210/11 and 5212 differ only in the flags defined below
+  */
+-struct ath5k_hw_old_rx_status {
++struct ath5k_hw_rx_status {
+ 	u32	rx_status_0; /* RX status word 0 */
+-
+-#define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN		0x00000fff
+-#define AR5K_OLD_RX_DESC_STATUS0_MORE			0x00001000
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE		0x00078000
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S		15
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL		0x07f80000
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	19
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA	0x38000000
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	27
+-
+ 	u32	rx_status_1; /* RX status word 1 */
+-
+-#define AR5K_OLD_RX_DESC_STATUS1_DONE			0x00000001
+-#define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
+-#define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR		0x00000004
+-#define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN		0x00000008
+-#define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010
+-#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR		0x000000e0
+-#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S		5
+-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
+-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX		0x00007e00
+-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S		9
+-#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000
+-#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
+-#define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS		0x10000000
+ } __packed;
+ 
++/* 5210/5211 */
++#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN		0x00000fff
++#define AR5K_5210_RX_DESC_STATUS0_MORE			0x00001000
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE		0x00078000
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S	15
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x07f80000
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	19
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA	0x38000000
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	27
++#define AR5K_5210_RX_DESC_STATUS1_DONE			0x00000001
++#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
++#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR		0x00000004
++#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN		0x00000008
++#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010
++#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR		0x000000e0
++#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S		5
++#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
++#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00
++#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S		9
++#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000
++#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
++#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS	0x10000000
++
++/* 5212 */
++#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN		0x00000fff
++#define AR5K_5212_RX_DESC_STATUS0_MORE			0x00001000
++#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR	0x00002000
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE		0x000f8000
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S	15
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x0ff00000
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	20
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA	0xf0000000
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	28
++#define AR5K_5212_RX_DESC_STATUS1_DONE			0x00000001
++#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
++#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR		0x00000004
++#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000008
++#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR		0x00000010
++#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR		0x00000020
++#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
++#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX		0x0000fe00
++#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S		9
++#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x7fff0000
++#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	16
++#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS	0x80000000
++
+ /*
+- * 5212 rx status descriptor
++ * common hardware RX error descriptor
+  */
+-struct ath5k_hw_new_rx_status {
+-	u32	rx_status_0; /* RX status word 0 */
+-
+-#define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN		0x00000fff
+-#define AR5K_NEW_RX_DESC_STATUS0_MORE			0x00001000
+-#define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR	0x00002000
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE		0x000f8000
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S		15
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL		0x0ff00000
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	20
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA	0xf0000000
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	28
+-
+-	u32	rx_status_1; /* RX status word 1 */
+-
+-#define AR5K_NEW_RX_DESC_STATUS1_DONE			0x00000001
+-#define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
+-#define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR		0x00000004
+-#define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000008
+-#define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR		0x00000010
+-#define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR		0x00000020
+-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
+-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX		0x0000fe00
+-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S		9
+-#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x7fff0000
+-#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	16
+-#define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS		0x80000000
+-} __packed;
+-
+ struct ath5k_hw_rx_error {
+ 	u32	rx_error_0; /* RX error word 0 */
+ 
+@@ -268,7 +265,10 @@ struct ath5k_hw_rx_error {
+ #define AR5K_DESC_RX_PHY_ERROR_SERVICE		0xc0
+ #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR	0xe0
+ 
+-struct ath5k_hw_2w_tx_desc {
++/*
++ * 5210/5211 hardware 2-word TX control descriptor
++ */
++struct ath5k_hw_2w_tx_ctl {
+ 	u32	tx_control_0; /* TX control word 0 */
+ 
+ #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
+@@ -314,9 +314,9 @@ struct ath5k_hw_2w_tx_desc {
+ #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS     0x10
+ 
+ /*
+- * 5212 4-word tx control descriptor
++ * 5212 hardware 4-word TX control descriptor
+  */
+-struct ath5k_hw_4w_tx_desc {
++struct ath5k_hw_4w_tx_ctl {
+ 	u32	tx_control_0; /* TX control word 0 */
+ 
+ #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
+@@ -374,7 +374,7 @@ struct ath5k_hw_4w_tx_desc {
+ } __packed;
+ 
+ /*
+- * Common tx status descriptor
++ * Common TX status descriptor
+  */
+ struct ath5k_hw_tx_status {
+ 	u32	tx_status_0; /* TX status word 0 */
+@@ -415,6 +415,34 @@ struct ath5k_hw_tx_status {
+ 
+ 
+ /*
++ * 5210/5211 hardware TX descriptor
++ */
++struct ath5k_hw_5210_tx_desc {
++	struct ath5k_hw_2w_tx_ctl	tx_ctl;
++	struct ath5k_hw_tx_status	tx_stat;
++} __packed;
++
++/*
++ * 5212 hardware TX descriptor
++ */
++struct ath5k_hw_5212_tx_desc {
++	struct ath5k_hw_4w_tx_ctl	tx_ctl;
++	struct ath5k_hw_tx_status	tx_stat;
++} __packed;
++
++/*
++ * common hardware RX descriptor
++ */
++struct ath5k_hw_all_rx_desc {
++	struct ath5k_hw_rx_ctl			rx_ctl;
++	union {
++		struct ath5k_hw_rx_status	rx_stat;
++		struct ath5k_hw_rx_error	rx_err;
++	} u;
++} __packed;
++
++
++/*
+  * AR5K REGISTER ACCESS
+  */
+ 
+diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c
+index 2c22f1d..04c84e9 100644
+--- a/drivers/net/wireless/ath5k/initvals.c
++++ b/drivers/net/wireless/ath5k/initvals.c
+@@ -678,8 +678,8 @@ static const struct ath5k_ini ar5212_ini[] = {
+ 	{ AR5K_PHY(644), 0x00806333 },
+ 	{ AR5K_PHY(645), 0x00106c10 },
+ 	{ AR5K_PHY(646), 0x009c4060 },
+-	/*{ AR5K_PHY(647), 0x1483800a },*/ /* Old value */
+ 	{ AR5K_PHY(647), 0x1483800a },
++	/* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */
+ 	{ AR5K_PHY(648), 0x01831061 },
+ 	{ AR5K_PHY(649), 0x00000400 },
+ 	/*{ AR5K_PHY(650), 0x000001b5 },*/
+@@ -1081,6 +1081,414 @@ static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
+ 		{ 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
+ };
+ 
++/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */
++/* XXX: No dumps for turbog yet, so turbog is the same with g here with some
++ * minor tweaking based on dumps from other chips */
++static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
++	{ AR5K_TXCFG,
++	/*	      b		g	    gTurbo */
++		{ 0x00000015, 0x00000015, 0x00000015 } },
++	{ AR5K_USEC_5211,
++		{ 0x04e01395, 0x12e013ab, 0x098813cf } },
++	{ AR5K_PHY(10),
++		{ 0x05020000, 0x0a020001, 0x0a020001 } },
++	{ AR5K_PHY(13),
++		{ 0x00000e00, 0x00000e00, 0x00000e00 } },
++	{ AR5K_PHY(14),
++		{ 0x0000000a, 0x0000000a, 0x0000000a } },
++	{ AR5K_PHY(18),
++		{ 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
++	{ AR5K_PHY(20),
++		{ 0x0de8b0da, 0x0c98b0da, 0x0c98b0da } },
++	{ AR5K_PHY_SIG,
++		{ 0x7ee80d2e, 0x7ec80d2e, 0x7ec80d2e } },
++	{ AR5K_PHY_AGCCOARSE,
++		{ 0x3137665e, 0x3139605e, 0x3139605e } },
++	{ AR5K_PHY(27),
++		{ 0x050cb081, 0x050cb081, 0x050cb081 } },
++	{ AR5K_PHY_RX_DELAY,
++		{ 0x0000044c, 0x00000898, 0x000007d0 } },
++	{ AR5K_PHY_FRAME_CTL_5211,
++		{ 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
++	{ AR5K_PHY_CCKTXCTL,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(642),
++		{ 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
++	{ AR5K_PHY_GAIN_2GHZ,
++		{ 0x0042c140, 0x0042c140, 0x0042c140 } },
++	{ 0xa21c,
++		{ 0x1863800a, 0x1883800a, 0x1883800a } },
++	{ AR5K_DCU_FP,
++		{ 0x000003e0, 0x000003e0, 0x000003e0 } },
++	{ 0x8060,
++		{ 0x0000000f, 0x0000000f, 0x0000000f } },
++	{ 0x8118,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x811c,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x8120,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x8124,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x8128,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x812c,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x8130,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x8134,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x8138,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x813c,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0x8140,
++		{ 0x800000a8, 0x800000a8, 0x800000a8 } },
++	{ 0x8144,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ AR5K_PHY_AGC,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(11),
++		{ 0x0000a000, 0x0000a000, 0x0000a000 } },
++	{ AR5K_PHY(15),
++		{ 0x00200400, 0x00200400, 0x00200400 } },
++	{ AR5K_PHY(19),
++		{ 0x1284233c, 0x1284233c, 0x1284233c } },
++	{ AR5K_PHY_SCR,
++		{ 0x0000001f, 0x0000001f, 0x0000001f } },
++	{ AR5K_PHY_SLMT,
++		{ 0x00000080, 0x00000080, 0x00000080 } },
++	{ AR5K_PHY_SCAL,
++		{ 0x0000000e, 0x0000000e, 0x0000000e } },
++	{ AR5K_PHY(86),
++		{ 0x000000ff, 0x000000ff, 0x000000ff } },
++	{ AR5K_PHY(96),
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(97),
++		{ 0x02800000, 0x02800000, 0x02800000 } },
++	{ AR5K_PHY(104),
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(120),
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(121),
++		{ 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa } },
++	{ AR5K_PHY(122),
++		{ 0x3c466478, 0x3c466478, 0x3c466478 } },
++	{ AR5K_PHY(123),
++		{ 0x000000aa, 0x000000aa, 0x000000aa } },
++	{ AR5K_PHY_SCLOCK,
++		{ 0x0000000c, 0x0000000c, 0x0000000c } },
++	{ AR5K_PHY_SDELAY,
++		{ 0x000000ff, 0x000000ff, 0x000000ff } },
++	{ AR5K_PHY_SPENDING,
++		{ 0x00000014, 0x00000014, 0x00000014 } },
++	{ 0xa228,
++		{ 0x000009b5, 0x000009b5, 0x000009b5 } },
++	{ 0xa23c,
++		{ 0x93c889af, 0x93c889af, 0x93c889af } },
++	{ 0xa24c,
++		{ 0x00000001, 0x00000001, 0x00000001 } },
++	{ 0xa250,
++		{ 0x0000a000, 0x0000a000, 0x0000a000 } },
++	{ 0xa254,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0xa258,
++		{ 0x0cc75380, 0x0cc75380, 0x0cc75380 } },
++	{ 0xa25c,
++		{ 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01 } },
++	{ 0xa260,
++		{ 0x5f690f01, 0x5f690f01, 0x5f690f01 } },
++	{ 0xa264,
++		{ 0x00418a11, 0x00418a11, 0x00418a11 } },
++	{ 0xa268,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0xa26c,
++		{ 0x0c30c16a, 0x0c30c16a, 0x0c30c16a } },
++	{ 0xa270,
++		{ 0x00820820, 0x00820820, 0x00820820 } },
++	{ 0xa274,
++		{ 0x001b7caa, 0x001b7caa, 0x001b7caa } },
++	{ 0xa278,
++		{ 0x1ce739ce, 0x1ce739ce, 0x1ce739ce } },
++	{ 0xa27c,
++		{ 0x051701ce, 0x051701ce, 0x051701ce } },
++	{ 0xa300,
++		{ 0x18010000, 0x18010000, 0x18010000 } },
++	{ 0xa304,
++		{ 0x30032602, 0x30032602, 0x30032602 } },
++	{ 0xa308,
++		{ 0x48073e06, 0x48073e06, 0x48073e06 } },
++	{ 0xa30c,
++		{ 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
++	{ 0xa310,
++		{ 0x641a600f, 0x641a600f, 0x641a600f } },
++	{ 0xa314,
++		{ 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
++	{ 0xa318,
++		{ 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
++	{ 0xa31c,
++		{ 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
++	{ 0xa320,
++		{ 0x9d4f970f, 0x9d4f970f, 0x9d4f970f } },
++	{ 0xa324,
++		{ 0xa5cfa18f, 0xa5cfa18f, 0xa5cfa18f } },
++	{ 0xa328,
++		{ 0xb55faf1f, 0xb55faf1f, 0xb55faf1f } },
++	{ 0xa32c,
++		{ 0xbddfb99f, 0xbddfb99f, 0xbddfb99f } },
++	{ 0xa330,
++		{ 0xcd7fc73f, 0xcd7fc73f, 0xcd7fc73f } },
++	{ 0xa334,
++		{ 0xd5ffd1bf, 0xd5ffd1bf, 0xd5ffd1bf } },
++	{ 0xa338,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0xa33c,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0xa340,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0xa344,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 0xa348,
++		{ 0x3fffffff, 0x3fffffff, 0x3fffffff } },
++	{ 0xa34c,
++		{ 0x3fffffff, 0x3fffffff, 0x3fffffff } },
++	{ 0xa350,
++		{ 0x3fffffff, 0x3fffffff, 0x3fffffff } },
++	{ 0xa354,
++		{ 0x0003ffff, 0x0003ffff, 0x0003ffff } },
++	{ 0xa358,
++		{ 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f } },
++	{ 0xa35c,
++		{ 0x066c420f, 0x066c420f, 0x066c420f } },
++	{ 0xa360,
++		{ 0x0f282207, 0x0f282207, 0x0f282207 } },
++	{ 0xa364,
++		{ 0x17601685, 0x17601685, 0x17601685 } },
++	{ 0xa368,
++		{ 0x1f801104, 0x1f801104, 0x1f801104 } },
++	{ 0xa36c,
++		{ 0x37a00c03, 0x37a00c03, 0x37a00c03 } },
++	{ 0xa370,
++		{ 0x3fc40883, 0x3fc40883, 0x3fc40883 } },
++	{ 0xa374,
++		{ 0x57c00803, 0x57c00803, 0x57c00803 } },
++	{ 0xa378,
++		{ 0x5fd80682, 0x5fd80682, 0x5fd80682 } },
++	{ 0xa37c,
++		{ 0x7fe00482, 0x7fe00482, 0x7fe00482 } },
++	{ 0xa380,
++		{ 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba } },
++	{ 0xa384,
++		{ 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
++};
++
++/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */
++/* XXX: No dumps for turbog yet, so turbog is the same with g here with some
++ * minor tweaking based on dumps from other chips */
++static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
++	{ AR5K_TXCFG,
++	/*	       g	gTurbo */
++		{ 0x00000015, 0x00000015 } },
++	{ AR5K_USEC_5211,
++		{ 0x12e013ab, 0x098813cf } },
++	{ AR5K_PHY_TURBO,
++		{ 0x00000000, 0x00000003 } },
++	{ AR5K_PHY(10),
++		{ 0x0a020001, 0x0a020001 } },
++	{ AR5K_PHY(13),
++		{ 0x00000e0e, 0x00000e0e } },
++	{ AR5K_PHY(14),
++		{ 0x0000000b, 0x0000000b } },
++	{ AR5K_PHY(17),
++		{ 0x13721422, 0x13721422 } },
++	{ AR5K_PHY(18),
++		{ 0x00199a65, 0x00199a65 } },
++	{ AR5K_PHY(20),
++		{ 0x0c98b0da, 0x0c98b0da } },
++	{ AR5K_PHY_SIG,
++		{ 0x7ec80d2e, 0x7ec80d2e } },
++	{ AR5K_PHY_AGCCOARSE,
++		{ 0x3139605e, 0x3139605e } },
++	{ AR5K_PHY(27),
++		{ 0x050cb081, 0x050cb081 } },
++	{ AR5K_PHY_RX_DELAY,
++		{ 0x00000898, 0x000007d0 } },
++	{ AR5K_PHY_FRAME_CTL_5211,
++		{ 0xf7b81000, 0xf7b81000 } },
++	{ AR5K_PHY_CCKTXCTL,
++		{ 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(642),
++		{ 0xd03e6788, 0xd03e6788 } },
++	{ AR5K_PHY_GAIN_2GHZ,
++		{ 0x0052c140, 0x0052c140 } },
++	{ 0xa21c,
++		{ 0x1883800a, 0x1883800a } },
++	{ 0xa324,
++		{ 0xa7cfa7cf, 0xa7cfa7cf } },
++	{ 0xa328,
++		{ 0xa7cfa7cf, 0xa7cfa7cf } },
++	{ 0xa32c,
++		{ 0xa7cfa7cf, 0xa7cfa7cf } },
++	{ 0xa330,
++		{ 0xa7cfa7cf, 0xa7cfa7cf } },
++	{ 0xa334,
++		{ 0xa7cfa7cf, 0xa7cfa7cf } },
++	{ AR5K_DCU_FP,
++		{ 0x000003e0, 0x000003e0 } },
++	{ 0x8060,
++		{ 0x0000000f, 0x0000000f } },
++	{ 0x809c,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x80a0,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x8118,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x811c,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x8120,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x8124,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x8128,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x812c,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x8130,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x8134,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x8138,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x813c,
++		{ 0x00000000, 0x00000000 } },
++	{ 0x8140,
++		{ 0x800003f9, 0x800003f9 } },
++	{ 0x8144,
++		{ 0x00000000, 0x00000000 } },
++	{ AR5K_PHY_AGC,
++		{ 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(11),
++		{ 0x0000a000, 0x0000a000 } },
++	{ AR5K_PHY(15),
++		{ 0x00200400, 0x00200400 } },
++	{ AR5K_PHY(19),
++		{ 0x1284233c, 0x1284233c } },
++	{ AR5K_PHY_SCR,
++		{ 0x0000001f, 0x0000001f } },
++	{ AR5K_PHY_SLMT,
++		{ 0x00000080, 0x00000080 } },
++	{ AR5K_PHY_SCAL,
++		{ 0x0000000e, 0x0000000e } },
++	{ AR5K_PHY(86),
++		{ 0x00081fff, 0x00081fff } },
++	{ AR5K_PHY(96),
++		{ 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(97),
++		{ 0x02800000, 0x02800000 } },
++	{ AR5K_PHY(104),
++		{ 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(119),
++		{ 0xfebadbe8, 0xfebadbe8 } },
++	{ AR5K_PHY(120),
++		{ 0x00000000, 0x00000000 } },
++	{ AR5K_PHY(121),
++		{ 0xaaaaaaaa, 0xaaaaaaaa } },
++	{ AR5K_PHY(122),
++		{ 0x3c466478, 0x3c466478 } },
++	{ AR5K_PHY(123),
++		{ 0x000000aa, 0x000000aa } },
++	{ AR5K_PHY_SCLOCK,
++		{ 0x0000000c, 0x0000000c } },
++	{ AR5K_PHY_SDELAY,
++		{ 0x000000ff, 0x000000ff } },
++	{ AR5K_PHY_SPENDING,
++		{ 0x00000014, 0x00000014 } },
++	{ 0xa228,
++		{ 0x000009b5, 0x000009b5 } },
++	{ AR5K_PHY_TXPOWER_RATE3,
++		{ 0x20202020, 0x20202020 } },
++	{ AR5K_PHY_TXPOWER_RATE4,
++		{ 0x20202020, 0x20202020 } },
++	{ 0xa23c,
++		{ 0x93c889af, 0x93c889af } },
++	{ 0xa24c,
++		{ 0x00000001, 0x00000001 } },
++	{ 0xa250,
++		{ 0x0000a000, 0x0000a000 } },
++	{ 0xa254,
++		{ 0x00000000, 0x00000000 } },
++	{ 0xa258,
++		{ 0x0cc75380, 0x0cc75380 } },
++	{ 0xa25c,
++		{ 0x0f0f0f01, 0x0f0f0f01 } },
++	{ 0xa260,
++		{ 0x5f690f01, 0x5f690f01 } },
++	{ 0xa264,
++		{ 0x00418a11, 0x00418a11 } },
++	{ 0xa268,
++		{ 0x00000000, 0x00000000 } },
++	{ 0xa26c,
++		{ 0x0c30c166, 0x0c30c166 } },
++	{ 0xa270,
++		{ 0x00820820, 0x00820820 } },
++	{ 0xa274,
++		{ 0x081a3caa, 0x081a3caa } },
++	{ 0xa278,
++		{ 0x1ce739ce, 0x1ce739ce } },
++	{ 0xa27c,
++		{ 0x051701ce, 0x051701ce } },
++	{ 0xa300,
++		{ 0x16010000, 0x16010000 } },
++	{ 0xa304,
++		{ 0x2c032402, 0x2c032402 } },
++	{ 0xa308,
++		{ 0x48433e42, 0x48433e42 } },
++	{ 0xa30c,
++		{ 0x5a0f500b, 0x5a0f500b } },
++	{ 0xa310,
++		{ 0x6c4b624a, 0x6c4b624a } },
++	{ 0xa314,
++		{ 0x7e8b748a, 0x7e8b748a } },
++	{ 0xa318,
++		{ 0x96cf8ccb, 0x96cf8ccb } },
++	{ 0xa31c,
++		{ 0xa34f9d0f, 0xa34f9d0f } },
++	{ 0xa320,
++		{ 0xa7cfa58f, 0xa7cfa58f } },
++	{ 0xa348,
++		{ 0x3fffffff, 0x3fffffff } },
++	{ 0xa34c,
++		{ 0x3fffffff, 0x3fffffff } },
++	{ 0xa350,
++		{ 0x3fffffff, 0x3fffffff } },
++	{ 0xa354,
++		{ 0x0003ffff, 0x0003ffff } },
++	{ 0xa358,
++		{ 0x79a8aa1f, 0x79a8aa1f } },
++	{ 0xa35c,
++		{ 0x066c420f, 0x066c420f } },
++	{ 0xa360,
++		{ 0x0f282207, 0x0f282207 } },
++	{ 0xa364,
++		{ 0x17601685, 0x17601685 } },
++	{ 0xa368,
++		{ 0x1f801104, 0x1f801104 } },
++	{ 0xa36c,
++		{ 0x37a00c03, 0x37a00c03 } },
++	{ 0xa370,
++		{ 0x3fc40883, 0x3fc40883 } },
++	{ 0xa374,
++		{ 0x57c00803, 0x57c00803 } },
++	{ 0xa378,
++		{ 0x5fd80682, 0x5fd80682 } },
++	{ 0xa37c,
++		{ 0x7fe00482, 0x7fe00482 } },
++	{ 0xa380,
++		{ 0x7f3c7bba, 0x7f3c7bba } },
++	{ 0xa384,
++		{ 0xf3307ff0, 0xf3307ff0 } },
++};
++
+ /*
+  * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
+  * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
+@@ -1290,35 +1698,92 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
+ 
+ 		/* Second set of mode-specific settings */
+ 		if (ah->ah_radio == AR5K_RF5111){
++
+ 			ath5k_hw_ini_mode_registers(ah,
+ 					ARRAY_SIZE(ar5212_rf5111_ini_mode_end),
+ 					ar5212_rf5111_ini_mode_end, mode);
++
+ 			/* Baseband gain table */
+ 			ath5k_hw_ini_registers(ah,
+ 					ARRAY_SIZE(rf5111_ini_bbgain),
+ 					rf5111_ini_bbgain, change_channel);
++
+ 		} else if (ah->ah_radio == AR5K_RF5112){
++
+ 			ath5k_hw_ini_mode_registers(ah,
+ 					ARRAY_SIZE(ar5212_rf5112_ini_mode_end),
+ 					ar5212_rf5112_ini_mode_end, mode);
+-			/* Baseband gain table */
++
+ 			ath5k_hw_ini_registers(ah,
+ 					ARRAY_SIZE(rf5112_ini_bbgain),
+ 					rf5112_ini_bbgain, change_channel);
++
+ 		} else if (ah->ah_radio == AR5K_RF5413){
++
+ 			ath5k_hw_ini_mode_registers(ah,
+ 					ARRAY_SIZE(rf5413_ini_mode_end),
+ 					rf5413_ini_mode_end, mode);
++
++			ath5k_hw_ini_registers(ah,
++					ARRAY_SIZE(rf5112_ini_bbgain),
++					rf5112_ini_bbgain, change_channel);
++
++		} else if (ah->ah_radio == AR5K_RF2413) {
++
++			if (mode < 2) {
++				ATH5K_ERR(ah->ah_sc,
++					"unsupported channel mode: %d\n", mode);
++				return -EINVAL;
++			}
++			mode = mode - 2;
++
++			/* Override a setting from ar5212_ini */
++			ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648));
++
++			ath5k_hw_ini_mode_registers(ah,
++					ARRAY_SIZE(rf2413_ini_mode_end),
++					rf2413_ini_mode_end, mode);
++
++			/* Baseband gain table */
++			ath5k_hw_ini_registers(ah,
++					ARRAY_SIZE(rf5112_ini_bbgain),
++					rf5112_ini_bbgain, change_channel);
++
++		} else if (ah->ah_radio == AR5K_RF2425) {
++
++			if (mode < 2) {
++				ATH5K_ERR(ah->ah_sc,
++					"unsupported channel mode: %d\n", mode);
++				return -EINVAL;
++			}
++
++			/* Map b to g */
++			if (mode == 2)
++				mode = 0;
++			else
++				mode = mode - 3;
++
++			/* Override a setting from ar5212_ini */
++			ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648));
++
++			ath5k_hw_ini_mode_registers(ah,
++					ARRAY_SIZE(rf2425_ini_mode_end),
++					rf2425_ini_mode_end, mode);
++
+ 			/* Baseband gain table */
+ 			ath5k_hw_ini_registers(ah,
+ 					ARRAY_SIZE(rf5112_ini_bbgain),
+ 					rf5112_ini_bbgain, change_channel);
++
+ 		}
++
+ 	/* For AR5211 */
+ 	} else if (ah->ah_version == AR5K_AR5211) {
+ 
+-		if(mode > 2){ /* AR5K_INI_VAL_11B */
+-			ATH5K_ERR(ah->ah_sc,"unsupported channel mode: %d\n", mode);
++		/* AR5K_MODE_11B */
++		if (mode > 2) {
++			ATH5K_ERR(ah->ah_sc,
++				"unsupported channel mode: %d\n", mode);
+ 			return -EINVAL;
+ 		}
+ 
+diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c
+index b959417..afd8689 100644
+--- a/drivers/net/wireless/ath5k/phy.c
++++ b/drivers/net/wireless/ath5k/phy.c
+@@ -666,6 +666,153 @@ static const struct ath5k_ini_rf rfregs_5413[] = {
+ 	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+ };
+ 
++/* RF2413/2414 mode-specific init registers */
++static const struct ath5k_ini_rf rfregs_2413[] = {
++	{ 1, AR5K_RF_BUFFER_CONTROL_4,
++	/* 	   mode b      mode g     mode gTurbo */
++		{ 0x00000020, 0x00000020, 0x00000020 } },
++	{ 2, AR5K_RF_BUFFER_CONTROL_3,
++		{ 0x02001408, 0x02001408, 0x02001408 } },
++	{ 3, AR5K_RF_BUFFER_CONTROL_6,
++		{ 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0xf0000000, 0xf0000000, 0xf0000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x03000000, 0x03000000, 0x03000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x40400000, 0x40400000, 0x40400000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x65050000, 0x65050000, 0x65050000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00420000, 0x00420000, 0x00420000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00b50000, 0x00b50000, 0x00b50000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00030000, 0x00030000, 0x00030000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00f70000, 0x00f70000, 0x00f70000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x009d0000, 0x009d0000, 0x009d0000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00220000, 0x00220000, 0x00220000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x04220000, 0x04220000, 0x04220000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00230018, 0x00230018, 0x00230018 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00280050, 0x00280050, 0x00280050 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x005000c3, 0x005000c3, 0x005000c3 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x0004007f, 0x0004007f, 0x0004007f } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000458, 0x00000458, 0x00000458 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x0000c000, 0x0000c000, 0x0000c000 } },
++	{ 6, AR5K_RF_BUFFER_CONTROL_5,
++		{ 0x00400230, 0x00400230, 0x00400230 } },
++	{ 7, AR5K_RF_BUFFER,
++		{ 0x00006400, 0x00006400, 0x00006400 } },
++	{ 7, AR5K_RF_BUFFER,
++		{ 0x00000800, 0x00000800, 0x00000800 } },
++	{ 7, AR5K_RF_BUFFER_CONTROL_2,
++		{ 0x0000000e, 0x0000000e, 0x0000000e } },
++};
++
++/* RF2425 mode-specific init registers */
++static const struct ath5k_ini_rf rfregs_2425[] = {
++	{ 1, AR5K_RF_BUFFER_CONTROL_4,
++	/* 	   mode g     mode gTurbo */
++		{ 0x00000020, 0x00000020 } },
++	{ 2, AR5K_RF_BUFFER_CONTROL_3,
++		{ 0x02001408, 0x02001408 } },
++	{ 3, AR5K_RF_BUFFER_CONTROL_6,
++		{ 0x00e020c0, 0x00e020c0 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x10000000, 0x10000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x002a0000, 0x002a0000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00100000, 0x00100000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00020000, 0x00020000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00730000, 0x00730000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00f80000, 0x00f80000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00e70000, 0x00e70000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00140000, 0x00140000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00910040, 0x00910040 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x0007001a, 0x0007001a } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00410000, 0x00410000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00810060, 0x00810060 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00020803, 0x00020803 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00000000, 0x00000000 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00001660, 0x00001660 } },
++	{ 6, AR5K_RF_BUFFER,
++		{ 0x00001688, 0x00001688 } },
++	{ 6, AR5K_RF_BUFFER_CONTROL_1,
++		{ 0x00000001, 0x00000001 } },
++	{ 7, AR5K_RF_BUFFER,
++		{ 0x00006400, 0x00006400 } },
++	{ 7, AR5K_RF_BUFFER,
++		{ 0x00000800, 0x00000800 } },
++	{ 7, AR5K_RF_BUFFER_CONTROL_2,
++		{ 0x0000000e, 0x0000000e } },
++};
+ 
+ /* Initial RF Gain settings for RF5112 */
+ static const struct ath5k_ini_rfgain rfgain_5112[] = {
+@@ -805,6 +952,74 @@ static const struct ath5k_ini_rfgain rfgain_5413[] = {
+ 	{ AR5K_RF_GAIN(63),	{ 0x000000f9, 0x000000f9 } },
+ };
+ 
++/* Initial RF Gain settings for RF2413 */
++static const struct ath5k_ini_rfgain rfgain_2413[] = {
++	{ AR5K_RF_GAIN(0), { 0x00000000 } },
++	{ AR5K_RF_GAIN(1), { 0x00000040 } },
++	{ AR5K_RF_GAIN(2), { 0x00000080 } },
++	{ AR5K_RF_GAIN(3), { 0x00000181 } },
++	{ AR5K_RF_GAIN(4), { 0x000001c1 } },
++	{ AR5K_RF_GAIN(5), { 0x00000001 } },
++	{ AR5K_RF_GAIN(6), { 0x00000041 } },
++	{ AR5K_RF_GAIN(7), { 0x00000081 } },
++	{ AR5K_RF_GAIN(8), { 0x00000168 } },
++	{ AR5K_RF_GAIN(9), { 0x000001a8 } },
++	{ AR5K_RF_GAIN(10), { 0x000001e8 } },
++	{ AR5K_RF_GAIN(11), { 0x00000028 } },
++	{ AR5K_RF_GAIN(12), { 0x00000068 } },
++	{ AR5K_RF_GAIN(13), { 0x00000189 } },
++	{ AR5K_RF_GAIN(14), { 0x000001c9 } },
++	{ AR5K_RF_GAIN(15), { 0x00000009 } },
++	{ AR5K_RF_GAIN(16), { 0x00000049 } },
++	{ AR5K_RF_GAIN(17), { 0x00000089 } },
++	{ AR5K_RF_GAIN(18), { 0x00000190 } },
++	{ AR5K_RF_GAIN(19), { 0x000001d0 } },
++	{ AR5K_RF_GAIN(20), { 0x00000010 } },
++	{ AR5K_RF_GAIN(21), { 0x00000050 } },
++	{ AR5K_RF_GAIN(22), { 0x00000090 } },
++	{ AR5K_RF_GAIN(23), { 0x00000191 } },
++	{ AR5K_RF_GAIN(24), { 0x000001d1 } },
++	{ AR5K_RF_GAIN(25), { 0x00000011 } },
++	{ AR5K_RF_GAIN(26), { 0x00000051 } },
++	{ AR5K_RF_GAIN(27), { 0x00000091 } },
++	{ AR5K_RF_GAIN(28), { 0x00000178 } },
++	{ AR5K_RF_GAIN(29), { 0x000001b8 } },
++	{ AR5K_RF_GAIN(30), { 0x000001f8 } },
++	{ AR5K_RF_GAIN(31), { 0x00000038 } },
++	{ AR5K_RF_GAIN(32), { 0x00000078 } },
++	{ AR5K_RF_GAIN(33), { 0x00000199 } },
++	{ AR5K_RF_GAIN(34), { 0x000001d9 } },
++	{ AR5K_RF_GAIN(35), { 0x00000019 } },
++	{ AR5K_RF_GAIN(36), { 0x00000059 } },
++	{ AR5K_RF_GAIN(37), { 0x00000099 } },
++	{ AR5K_RF_GAIN(38), { 0x000000d9 } },
++	{ AR5K_RF_GAIN(39), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(40), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(41), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(42), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(43), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(44), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(45), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(46), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(47), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(48), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(49), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(50), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(51), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(52), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(53), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(54), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(55), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(56), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(57), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(58), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(59), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(60), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(61), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(62), { 0x000000f9 } },
++	{ AR5K_RF_GAIN(63), { 0x000000f9 } },
++};
++
+ static const struct ath5k_gain_opt rfgain_opt_5112 = {
+ 	1,
+ 	8,
+@@ -844,14 +1059,14 @@ static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits,
+ 	entry = ((first - 1) / 8) + offset;
+ 	position = (first - 1) % 8;
+ 
+-	if (set == true)
++	if (set)
+ 		data = ath5k_hw_bitswap(reg, bits);
+ 
+ 	for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
+ 		last = (position + left > 8) ? 8 : position + left;
+ 		mask = (((1 << last) - 1) ^ ((1 << position) - 1)) << (col * 8);
+ 
+-		if (set == true) {
++		if (set) {
+ 			rf[entry] &= ~mask;
+ 			rf[entry] |= ((data << position) << (col * 8)) & mask;
+ 			data >>= (8 - position);
+@@ -864,7 +1079,7 @@ static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits,
+ 		left -= 8 - position;
+ 	}
+ 
+-	data = set == true ? 1 : ath5k_hw_bitswap(data, bits);
++	data = set ? 1 : ath5k_hw_bitswap(data, bits);
+ 
+ 	return data;
+ }
+@@ -955,7 +1170,6 @@ static s32 ath5k_hw_rfregs_gain_adjust(struct ath5k_hw *ah)
+ 		go = &rfgain_opt_5111;
+ 		break;
+ 	case AR5K_RF5112:
+-	case AR5K_RF5413: /* ??? */
+ 		go = &rfgain_opt_5112;
+ 		break;
+ 	default:
+@@ -1018,7 +1232,7 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
+ 	int obdb = -1, bank = -1;
+ 	u32 ee_mode;
+ 
+-	AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
++	AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
+ 
+ 	rf = ah->ah_rf_banks;
+ 
+@@ -1038,8 +1252,8 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
+ 	}
+ 
+ 	/* Modify bank 0 */
+-	if (channel->val & CHANNEL_2GHZ) {
+-		if (channel->val & CHANNEL_CCK)
++	if (channel->hw_value & CHANNEL_2GHZ) {
++		if (channel->hw_value & CHANNEL_CCK)
+ 			ee_mode = AR5K_EEPROM_MODE_11B;
+ 		else
+ 			ee_mode = AR5K_EEPROM_MODE_11G;
+@@ -1058,10 +1272,10 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
+ 	} else {
+ 		/* For 11a, Turbo and XR */
+ 		ee_mode = AR5K_EEPROM_MODE_11A;
+-		obdb =	 channel->freq >= 5725 ? 3 :
+-			(channel->freq >= 5500 ? 2 :
+-			(channel->freq >= 5260 ? 1 :
+-			 (channel->freq > 4000 ? 0 : -1)));
++		obdb =	 channel->center_freq >= 5725 ? 3 :
++			(channel->center_freq >= 5500 ? 2 :
++			(channel->center_freq >= 5260 ? 1 :
++			 (channel->center_freq > 4000 ? 0 : -1)));
+ 
+ 		if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ 				ee->ee_pwd_84, 1, 51, 3, true))
+@@ -1119,12 +1333,12 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
+ 	int obdb = -1, bank = -1;
+ 	u32 ee_mode;
+ 
+-	AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
++	AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
+ 
+ 	rf = ah->ah_rf_banks;
+ 
+ 	if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_2112A
+-		&& !test_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode)){
++		&& !test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) {
+ 		rf_ini = rfregs_2112a;
+ 		rf_size = ARRAY_SIZE(rfregs_5112a);
+ 		if (mode < 2) {
+@@ -1156,8 +1370,8 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
+ 	}
+ 
+ 	/* Modify bank 6 */
+-	if (channel->val & CHANNEL_2GHZ) {
+-		if (channel->val & CHANNEL_OFDM)
++	if (channel->hw_value & CHANNEL_2GHZ) {
++		if (channel->hw_value & CHANNEL_OFDM)
+ 			ee_mode = AR5K_EEPROM_MODE_11G;
+ 		else
+ 			ee_mode = AR5K_EEPROM_MODE_11B;
+@@ -1173,10 +1387,13 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
+ 	} else {
+ 		/* For 11a, Turbo and XR */
+ 		ee_mode = AR5K_EEPROM_MODE_11A;
+-		obdb = channel->freq >= 5725 ? 3 :
+-		    (channel->freq >= 5500 ? 2 :
+-			(channel->freq >= 5260 ? 1 :
+-			    (channel->freq > 4000 ? 0 : -1)));
++		obdb = channel->center_freq >= 5725 ? 3 :
++		    (channel->center_freq >= 5500 ? 2 :
++			(channel->center_freq >= 5260 ? 1 :
++			    (channel->center_freq > 4000 ? 0 : -1)));
++
++		if (obdb == -1)
++			return -EINVAL;
+ 
+ 		if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ 				ee->ee_ob[ee_mode][obdb], 3, 279, 0, true))
+@@ -1209,7 +1426,8 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
+ }
+ 
+ /*
+- * Initialize RF5413/5414
++ * Initialize RF5413/5414 and future chips
++ * (until we come up with a better solution)
+  */
+ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
+ 		struct ieee80211_channel *channel, unsigned int mode)
+@@ -1219,12 +1437,47 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
+ 	unsigned int rf_size, i;
+ 	int bank = -1;
+ 
+-	AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
++	AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
+ 
+ 	rf = ah->ah_rf_banks;
+ 
+-	rf_ini = rfregs_5413;
+-	rf_size = ARRAY_SIZE(rfregs_5413);
++	switch (ah->ah_radio) {
++	case AR5K_RF5413:
++		rf_ini = rfregs_5413;
++		rf_size = ARRAY_SIZE(rfregs_5413);
++		break;
++	case AR5K_RF2413:
++		rf_ini = rfregs_2413;
++		rf_size = ARRAY_SIZE(rfregs_2413);
++
++		if (mode < 2) {
++			ATH5K_ERR(ah->ah_sc,
++				"invalid channel mode: %i\n", mode);
++			return -EINVAL;
++		}
++
++		mode = mode - 2;
++		break;
++	case AR5K_RF2425:
++		rf_ini = rfregs_2425;
++		rf_size = ARRAY_SIZE(rfregs_2425);
++
++		if (mode < 2) {
++			ATH5K_ERR(ah->ah_sc,
++				"invalid channel mode: %i\n", mode);
++			return -EINVAL;
++		}
++
++		/* Map b to g */
++		if (mode == 2)
++			mode = 0;
++		else
++			mode = mode - 3;
++
++		break;
++	default:
++		return -EINVAL;
++	}
+ 
+ 	/* Copy values to modify them */
+ 	for (i = 0; i < rf_size; i++) {
+@@ -1283,6 +1536,14 @@ int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ 		ah->ah_rf_banks_size = sizeof(rfregs_5413);
+ 		func = ath5k_hw_rf5413_rfregs;
+ 		break;
++	case AR5K_RF2413:
++		ah->ah_rf_banks_size = sizeof(rfregs_2413);
++		func = ath5k_hw_rf5413_rfregs;
++		break;
++	case AR5K_RF2425:
++		ah->ah_rf_banks_size = sizeof(rfregs_2425);
++		func = ath5k_hw_rf5413_rfregs;
++		break;
+ 	default:
+ 		return -EINVAL;
+ 	}
+@@ -1321,6 +1582,16 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq)
+ 		ath5k_rfg = rfgain_5413;
+ 		size = ARRAY_SIZE(rfgain_5413);
+ 		break;
++	case AR5K_RF2413:
++		ath5k_rfg = rfgain_2413;
++		size = ARRAY_SIZE(rfgain_2413);
++		freq = 0; /* only 2Ghz */
++		break;
++	case AR5K_RF2425:
++		ath5k_rfg = rfgain_2413;
++		size = ARRAY_SIZE(rfgain_2413);
++		freq = 0; /* only 2Ghz */
++		break;
+ 	default:
+ 		return -EINVAL;
+ 	}
+@@ -1395,7 +1666,6 @@ int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah)
+ 		ah->ah_gain.g_active = 1;
+ 		break;
+ 	case AR5K_RF5112:
+-	case AR5K_RF5413: /* ??? */
+ 		ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
+ 		ah->ah_gain.g_step =
+ 		    &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx];
+@@ -1445,9 +1715,10 @@ static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
+ 	 * newer chipsets like the AR5212A who have a completely
+ 	 * different RF/PHY part.
+ 	 */
+-	athchan = (ath5k_hw_bitswap((channel->chan - 24) / 2, 5) << 1) |
+-		(1 << 6) | 0x1;
+-
++	athchan = (ath5k_hw_bitswap(
++			(ieee80211_frequency_to_channel(
++				channel->center_freq) - 24) / 2, 5)
++				<< 1) | (1 << 6) | 0x1;
+ 	return athchan;
+ }
+ 
+@@ -1506,7 +1777,8 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
+ 		struct ieee80211_channel *channel)
+ {
+ 	struct ath5k_athchan_2ghz ath5k_channel_2ghz;
+-	unsigned int ath5k_channel = channel->chan;
++	unsigned int ath5k_channel =
++		ieee80211_frequency_to_channel(channel->center_freq);
+ 	u32 data0, data1, clock;
+ 	int ret;
+ 
+@@ -1515,10 +1787,11 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
+ 	 */
+ 	data0 = data1 = 0;
+ 
+-	if (channel->val & CHANNEL_2GHZ) {
++	if (channel->hw_value & CHANNEL_2GHZ) {
+ 		/* Map 2GHz channel to 5GHz Atheros channel ID */
+-		ret = ath5k_hw_rf5111_chan2athchan(channel->chan,
+-				&ath5k_channel_2ghz);
++		ret = ath5k_hw_rf5111_chan2athchan(
++			ieee80211_frequency_to_channel(channel->center_freq),
++			&ath5k_channel_2ghz);
+ 		if (ret)
+ 			return ret;
+ 
+@@ -1555,7 +1828,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
+ 	u16 c;
+ 
+ 	data = data0 = data1 = data2 = 0;
+-	c = channel->freq;
++	c = channel->center_freq;
+ 
+ 	/*
+ 	 * Set the channel on the RF5112 or newer
+@@ -1599,19 +1872,17 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
+ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
+ {
+ 	int ret;
+-
+ 	/*
+-	 * Check bounds supported by the PHY
+-	 * (don't care about regulation restrictions at this point)
+-	 */
+-	if ((channel->freq < ah->ah_capabilities.cap_range.range_2ghz_min ||
+-	    channel->freq > ah->ah_capabilities.cap_range.range_2ghz_max) &&
+-	    (channel->freq < ah->ah_capabilities.cap_range.range_5ghz_min ||
+-	    channel->freq > ah->ah_capabilities.cap_range.range_5ghz_max)) {
++	 * Check bounds supported by the PHY (we don't care about regultory
++	 * restrictions at this point). Note: hw_value already has the band
++	 * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
++	 * of the band by that */
++	if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
+ 		ATH5K_ERR(ah->ah_sc,
+-			"channel out of supported range (%u MHz)\n",
+-			channel->freq);
+-		return -EINVAL;
++			"channel frequency (%u MHz) out of supported "
++			"band range\n",
++			channel->center_freq);
++			return -EINVAL;
+ 	}
+ 
+ 	/*
+@@ -1632,9 +1903,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
+ 	if (ret)
+ 		return ret;
+ 
+-	ah->ah_current_channel.freq = channel->freq;
+-	ah->ah_current_channel.val = channel->val;
+-	ah->ah_turbo = channel->val == CHANNEL_T ? true : false;
++	ah->ah_current_channel.center_freq = channel->center_freq;
++	ah->ah_current_channel.hw_value = channel->hw_value;
++	ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
+ 
+ 	return 0;
+ }
+@@ -1797,11 +2068,11 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
+ 
+ 	if (ret) {
+ 		ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+-				channel->freq);
++				channel->center_freq);
+ 		return ret;
+ 	}
+ 
+-	ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
++	ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -1825,7 +2096,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
+ 	s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
+ 	ATH5K_TRACE(ah->ah_sc);
+ 
+-	if (ah->ah_calibration == false ||
++	if (!ah->ah_calibration ||
+ 			ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
+ 		goto done;
+ 
+@@ -1848,10 +2119,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
+ 		((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
+ 
+ done:
+-	ath5k_hw_noise_floor_calibration(ah, channel->freq);
++	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+ 
+ 	/* Request RF gain */
+-	if (channel->val & CHANNEL_5GHZ) {
++	if (channel->hw_value & CHANNEL_5GHZ) {
+ 		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max,
+ 			AR5K_PHY_PAPD_PROBE_TXPOWER) |
+ 			AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
+@@ -2015,6 +2286,18 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ 		return -EINVAL;
+ 	}
+ 
++	/*
++	 * RF2413 for some reason can't
++	 * transmit anything if we call
++	 * this funtion, so we skip it
++	 * until we fix txpower.
++	 *
++	 * XXX: Assume same for RF2425
++	 * to be safe.
++	 */
++	if ((ah->ah_radio == AR5K_RF2413) || (ah->ah_radio == AR5K_RF2425))
++		return 0;
++
+ 	/* Reset TX power values */
+ 	memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
+ 	ah->ah_txpower.txp_tpc = tpc;
+@@ -2048,7 +2331,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ 		AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
+ 		AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
+ 
+-	if (ah->ah_txpower.txp_tpc == true)
++	if (ah->ah_txpower.txp_tpc)
+ 		ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
+ 			AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+ 	else
+diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
+index 2f41c83..30629b3 100644
+--- a/drivers/net/wireless/ath5k/reg.h
++++ b/drivers/net/wireless/ath5k/reg.h
+@@ -1923,7 +1923,9 @@ after DFS is enabled */
+ #define AR5K_PHY_SDELAY_32MHZ		0x000000ff
+ #define AR5K_PHY_SPENDING		0x99f8
+ #define AR5K_PHY_SPENDING_RF5111	0x00000018
+-#define AR5K_PHY_SPENDING_RF5112	0x00000014
++#define AR5K_PHY_SPENDING_RF5112	0x00000014 /* <- i 've only seen this on 2425 dumps ! */
++#define AR5K_PHY_SPENDING_RF5112A	0x0000000e /* but since i only have 5112A-based chips */
++#define AR5K_PHY_SPENDING_RF5424	0x00000012 /* to test it might be also for old 5112.  */
+ 
+ /*
+  * Misc PHY/radio registers [5110 - 5111]
+diff --git a/drivers/net/wireless/ath5k/regdom.c b/drivers/net/wireless/ath5k/regdom.c
+deleted file mode 100644
+index e851957..0000000
+--- a/drivers/net/wireless/ath5k/regdom.c
++++ /dev/null
+@@ -1,121 +0,0 @@
+-/*
+- * Copyright (c) 2004, 2005 Reyk Floeter <reyk at vantronix.net>
+- *
+- * Permission to use, copy, modify, and distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- */
+-
+-/*
+- * Basic regulation domain extensions for the IEEE 802.11 stack
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-
+-#include "regdom.h"
+-
+-static const struct ath5k_regdommap {
+-	enum ath5k_regdom dmn;
+-	enum ath5k_regdom dmn5;
+-	enum ath5k_regdom dmn2;
+-} r_map[] = {
+-	{ DMN_DEFAULT,		DMN_DEBUG,	DMN_DEBUG },
+-	{ DMN_NULL_WORLD,	DMN_NULL,	DMN_WORLD },
+-	{ DMN_NULL_ETSIB,	DMN_NULL,	DMN_ETSIB },
+-	{ DMN_NULL_ETSIC,	DMN_NULL,	DMN_ETSIC },
+-	{ DMN_FCC1_FCCA,	DMN_FCC1,	DMN_FCCA },
+-	{ DMN_FCC1_WORLD,	DMN_FCC1,	DMN_WORLD },
+-	{ DMN_FCC2_FCCA,	DMN_FCC2,	DMN_FCCA },
+-	{ DMN_FCC2_WORLD,	DMN_FCC2,	DMN_WORLD },
+-	{ DMN_FCC2_ETSIC,	DMN_FCC2,	DMN_ETSIC },
+-	{ DMN_FRANCE_NULL,	DMN_ETSI3,	DMN_ETSI3 },
+-	{ DMN_FCC3_FCCA,	DMN_FCC3,	DMN_WORLD },
+-	{ DMN_ETSI1_WORLD,	DMN_ETSI1,	DMN_WORLD },
+-	{ DMN_ETSI3_ETSIA,	DMN_ETSI3,	DMN_WORLD },
+-	{ DMN_ETSI2_WORLD,	DMN_ETSI2,	DMN_WORLD },
+-	{ DMN_ETSI3_WORLD,	DMN_ETSI3,	DMN_WORLD },
+-	{ DMN_ETSI4_WORLD,	DMN_ETSI4,	DMN_WORLD },
+-	{ DMN_ETSI4_ETSIC,	DMN_ETSI4,	DMN_ETSIC },
+-	{ DMN_ETSI5_WORLD,	DMN_ETSI5,	DMN_WORLD },
+-	{ DMN_ETSI6_WORLD,	DMN_ETSI6,	DMN_WORLD },
+-	{ DMN_ETSI_NULL,	DMN_ETSI1,	DMN_ETSI1 },
+-	{ DMN_MKK1_MKKA,	DMN_MKK1,	DMN_MKKA },
+-	{ DMN_MKK1_MKKB,	DMN_MKK1,	DMN_MKKA },
+-	{ DMN_APL4_WORLD,	DMN_APL4,	DMN_WORLD },
+-	{ DMN_MKK2_MKKA,	DMN_MKK2,	DMN_MKKA },
+-	{ DMN_APL_NULL,		DMN_APL1,	DMN_NULL },
+-	{ DMN_APL2_WORLD,	DMN_APL2,	DMN_WORLD },
+-	{ DMN_APL2_APLC,	DMN_APL2,	DMN_WORLD },
+-	{ DMN_APL3_WORLD,	DMN_APL3,	DMN_WORLD },
+-	{ DMN_MKK1_FCCA,	DMN_MKK1,	DMN_FCCA },
+-	{ DMN_APL2_APLD,	DMN_APL2,	DMN_APLD },
+-	{ DMN_MKK1_MKKA1,	DMN_MKK1,	DMN_MKKA },
+-	{ DMN_MKK1_MKKA2,	DMN_MKK1,	DMN_MKKA },
+-	{ DMN_APL1_WORLD,	DMN_APL1,	DMN_WORLD },
+-	{ DMN_APL1_FCCA,	DMN_APL1,	DMN_FCCA },
+-	{ DMN_APL1_APLA,	DMN_APL1,	DMN_WORLD },
+-	{ DMN_APL1_ETSIC,	DMN_APL1,	DMN_ETSIC },
+-	{ DMN_APL2_ETSIC,	DMN_APL2,	DMN_ETSIC },
+-	{ DMN_APL5_WORLD,	DMN_APL5,	DMN_WORLD },
+-	{ DMN_WOR0_WORLD,	DMN_WORLD,	DMN_WORLD },
+-	{ DMN_WOR1_WORLD,	DMN_WORLD,	DMN_WORLD },
+-	{ DMN_WOR2_WORLD,	DMN_WORLD,	DMN_WORLD },
+-	{ DMN_WOR3_WORLD,	DMN_WORLD,	DMN_WORLD },
+-	{ DMN_WOR4_WORLD,	DMN_WORLD,	DMN_WORLD },
+-	{ DMN_WOR5_ETSIC,	DMN_WORLD,	DMN_WORLD },
+-	{ DMN_WOR01_WORLD,	DMN_WORLD,	DMN_WORLD },
+-	{ DMN_WOR02_WORLD,	DMN_WORLD,	DMN_WORLD },
+-	{ DMN_EU1_WORLD,	DMN_ETSI1,	DMN_WORLD },
+-	{ DMN_WOR9_WORLD,	DMN_WORLD,	DMN_WORLD },
+-	{ DMN_WORA_WORLD,	DMN_WORLD,	DMN_WORLD },
+-};
+-
+-enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom dmn, u16 mhz)
+-{
+-	unsigned int i;
+-
+-	for (i = 0; i < ARRAY_SIZE(r_map); i++) {
+-		if (r_map[i].dmn == dmn) {
+-			if (mhz >= 2000 && mhz <= 3000)
+-				return r_map[i].dmn2;
+-			if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN &&
+-					mhz <= IEEE80211_CHANNELS_5GHZ_MAX)
+-				return r_map[i].dmn5;
+-		}
+-	}
+-
+-	return DMN_DEBUG;
+-}
+-
+-u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee)
+-{
+-	u32 regdomain = (u32)ieee;
+-
+-	/*
+-	 * Use the default regulation domain if the value is empty
+-	 * or not supported by the net80211 regulation code.
+-	 */
+-	if (ath5k_regdom2flag(regdomain, IEEE80211_CHANNELS_5GHZ_MIN) ==
+-			DMN_DEBUG)
+-		return (u16)AR5K_TUNE_REGDOMAIN;
+-
+-	/* It is supported, just return the value */
+-	return regdomain;
+-}
+-
+-enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain)
+-{
+-	enum ath5k_regdom ieee = (enum ath5k_regdom)regdomain;
+-
+-	return ieee;
+-}
+-
+diff --git a/drivers/net/wireless/ath5k/regdom.h b/drivers/net/wireless/ath5k/regdom.h
+deleted file mode 100644
+index f7d3c66..0000000
+--- a/drivers/net/wireless/ath5k/regdom.h
++++ /dev/null
+@@ -1,500 +0,0 @@
+-/*
+- * Copyright (c) 2004, 2005 Reyk Floeter <reyk at openbsd.org>
+- *
+- * Permission to use, copy, modify, and distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 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 _IEEE80211_REGDOMAIN_H_
+-#define _IEEE80211_REGDOMAIN_H_
+-
+-#include <linux/types.h>
+-
+-/* Default regulation domain if stored value EEPROM value is invalid */
+-#define AR5K_TUNE_REGDOMAIN	DMN_FCC2_FCCA	/* Canada */
+-#define AR5K_TUNE_CTRY		CTRY_DEFAULT
+-
+-
+-enum ath5k_regdom {
+-	DMN_DEFAULT		= 0x00,
+-	DMN_NULL_WORLD		= 0x03,
+-	DMN_NULL_ETSIB		= 0x07,
+-	DMN_NULL_ETSIC		= 0x08,
+-	DMN_FCC1_FCCA		= 0x10,
+-	DMN_FCC1_WORLD		= 0x11,
+-	DMN_FCC2_FCCA		= 0x20,
+-	DMN_FCC2_WORLD		= 0x21,
+-	DMN_FCC2_ETSIC		= 0x22,
+-	DMN_FRANCE_NULL		= 0x31,
+-	DMN_FCC3_FCCA		= 0x3A,
+-	DMN_ETSI1_WORLD		= 0x37,
+-	DMN_ETSI3_ETSIA		= 0x32,
+-	DMN_ETSI2_WORLD		= 0x35,
+-	DMN_ETSI3_WORLD		= 0x36,
+-	DMN_ETSI4_WORLD		= 0x30,
+-	DMN_ETSI4_ETSIC		= 0x38,
+-	DMN_ETSI5_WORLD		= 0x39,
+-	DMN_ETSI6_WORLD		= 0x34,
+-	DMN_ETSI_NULL		= 0x33,
+-	DMN_MKK1_MKKA		= 0x40,
+-	DMN_MKK1_MKKB		= 0x41,
+-	DMN_APL4_WORLD		= 0x42,
+-	DMN_MKK2_MKKA		= 0x43,
+-	DMN_APL_NULL		= 0x44,
+-	DMN_APL2_WORLD		= 0x45,
+-	DMN_APL2_APLC		= 0x46,
+-	DMN_APL3_WORLD		= 0x47,
+-	DMN_MKK1_FCCA		= 0x48,
+-	DMN_APL2_APLD		= 0x49,
+-	DMN_MKK1_MKKA1		= 0x4A,
+-	DMN_MKK1_MKKA2		= 0x4B,
+-	DMN_APL1_WORLD		= 0x52,
+-	DMN_APL1_FCCA		= 0x53,
+-	DMN_APL1_APLA		= 0x54,
+-	DMN_APL1_ETSIC		= 0x55,
+-	DMN_APL2_ETSIC		= 0x56,
+-	DMN_APL5_WORLD		= 0x58,
+-	DMN_WOR0_WORLD		= 0x60,
+-	DMN_WOR1_WORLD		= 0x61,
+-	DMN_WOR2_WORLD		= 0x62,
+-	DMN_WOR3_WORLD		= 0x63,
+-	DMN_WOR4_WORLD		= 0x64,
+-	DMN_WOR5_ETSIC		= 0x65,
+-	DMN_WOR01_WORLD		= 0x66,
+-	DMN_WOR02_WORLD		= 0x67,
+-	DMN_EU1_WORLD		= 0x68,
+-	DMN_WOR9_WORLD		= 0x69,
+-	DMN_WORA_WORLD		= 0x6A,
+-
+-	DMN_APL1		= 0xf0000001,
+-	DMN_APL2		= 0xf0000002,
+-	DMN_APL3		= 0xf0000004,
+-	DMN_APL4		= 0xf0000008,
+-	DMN_APL5		= 0xf0000010,
+-	DMN_ETSI1		= 0xf0000020,
+-	DMN_ETSI2		= 0xf0000040,
+-	DMN_ETSI3		= 0xf0000080,
+-	DMN_ETSI4		= 0xf0000100,
+-	DMN_ETSI5		= 0xf0000200,
+-	DMN_ETSI6		= 0xf0000400,
+-	DMN_ETSIA		= 0xf0000800,
+-	DMN_ETSIB		= 0xf0001000,
+-	DMN_ETSIC		= 0xf0002000,
+-	DMN_FCC1		= 0xf0004000,
+-	DMN_FCC2		= 0xf0008000,
+-	DMN_FCC3		= 0xf0010000,
+-	DMN_FCCA		= 0xf0020000,
+-	DMN_APLD		= 0xf0040000,
+-	DMN_MKK1		= 0xf0080000,
+-	DMN_MKK2		= 0xf0100000,
+-	DMN_MKKA		= 0xf0200000,
+-	DMN_NULL		= 0xf0400000,
+-	DMN_WORLD		= 0xf0800000,
+-	DMN_DEBUG               = 0xf1000000	/* used for debugging */
+-};
+-
+-#define IEEE80211_DMN(_d)	((_d) & ~0xf0000000)
+-
+-enum ath5k_countrycode {
+-	CTRY_DEFAULT            = 0,   /* Default domain (NA) */
+-	CTRY_ALBANIA            = 8,   /* Albania */
+-	CTRY_ALGERIA            = 12,  /* Algeria */
+-	CTRY_ARGENTINA          = 32,  /* Argentina */
+-	CTRY_ARMENIA            = 51,  /* Armenia */
+-	CTRY_AUSTRALIA          = 36,  /* Australia */
+-	CTRY_AUSTRIA            = 40,  /* Austria */
+-	CTRY_AZERBAIJAN         = 31,  /* Azerbaijan */
+-	CTRY_BAHRAIN            = 48,  /* Bahrain */
+-	CTRY_BELARUS            = 112, /* Belarus */
+-	CTRY_BELGIUM            = 56,  /* Belgium */
+-	CTRY_BELIZE             = 84,  /* Belize */
+-	CTRY_BOLIVIA            = 68,  /* Bolivia */
+-	CTRY_BRAZIL             = 76,  /* Brazil */
+-	CTRY_BRUNEI_DARUSSALAM  = 96,  /* Brunei Darussalam */
+-	CTRY_BULGARIA           = 100, /* Bulgaria */
+-	CTRY_CANADA             = 124, /* Canada */
+-	CTRY_CHILE              = 152, /* Chile */
+-	CTRY_CHINA              = 156, /* People's Republic of China */
+-	CTRY_COLOMBIA           = 170, /* Colombia */
+-	CTRY_COSTA_RICA         = 188, /* Costa Rica */
+-	CTRY_CROATIA            = 191, /* Croatia */
+-	CTRY_CYPRUS             = 196, /* Cyprus */
+-	CTRY_CZECH              = 203, /* Czech Republic */
+-	CTRY_DENMARK            = 208, /* Denmark */
+-	CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */
+-	CTRY_ECUADOR            = 218, /* Ecuador */
+-	CTRY_EGYPT              = 818, /* Egypt */
+-	CTRY_EL_SALVADOR        = 222, /* El Salvador */
+-	CTRY_ESTONIA            = 233, /* Estonia */
+-	CTRY_FAEROE_ISLANDS     = 234, /* Faeroe Islands */
+-	CTRY_FINLAND            = 246, /* Finland */
+-	CTRY_FRANCE             = 250, /* France */
+-	CTRY_FRANCE2            = 255, /* France2 */
+-	CTRY_GEORGIA            = 268, /* Georgia */
+-	CTRY_GERMANY            = 276, /* Germany */
+-	CTRY_GREECE             = 300, /* Greece */
+-	CTRY_GUATEMALA          = 320, /* Guatemala */
+-	CTRY_HONDURAS           = 340, /* Honduras */
+-	CTRY_HONG_KONG          = 344, /* Hong Kong S.A.R., P.R.C. */
+-	CTRY_HUNGARY            = 348, /* Hungary */
+-	CTRY_ICELAND            = 352, /* Iceland */
+-	CTRY_INDIA              = 356, /* India */
+-	CTRY_INDONESIA          = 360, /* Indonesia */
+-	CTRY_IRAN               = 364, /* Iran */
+-	CTRY_IRAQ               = 368, /* Iraq */
+-	CTRY_IRELAND            = 372, /* Ireland */
+-	CTRY_ISRAEL             = 376, /* Israel */
+-	CTRY_ITALY              = 380, /* Italy */
+-	CTRY_JAMAICA            = 388, /* Jamaica */
+-	CTRY_JAPAN              = 392, /* Japan */
+-	CTRY_JAPAN1             = 393, /* Japan (JP1) */
+-	CTRY_JAPAN2             = 394, /* Japan (JP0) */
+-	CTRY_JAPAN3             = 395, /* Japan (JP1-1) */
+-	CTRY_JAPAN4             = 396, /* Japan (JE1) */
+-	CTRY_JAPAN5             = 397, /* Japan (JE2) */
+-	CTRY_JORDAN             = 400, /* Jordan */
+-	CTRY_KAZAKHSTAN         = 398, /* Kazakhstan */
+-	CTRY_KENYA              = 404, /* Kenya */
+-	CTRY_KOREA_NORTH        = 408, /* North Korea */
+-	CTRY_KOREA_ROC          = 410, /* South Korea */
+-	CTRY_KOREA_ROC2         = 411, /* South Korea */
+-	CTRY_KUWAIT             = 414, /* Kuwait */
+-	CTRY_LATVIA             = 428, /* Latvia */
+-	CTRY_LEBANON            = 422, /* Lebanon */
+-	CTRY_LIBYA              = 434, /* Libya */
+-	CTRY_LIECHTENSTEIN      = 438, /* Liechtenstein */
+-	CTRY_LITHUANIA          = 440, /* Lithuania */
+-	CTRY_LUXEMBOURG         = 442, /* Luxembourg */
+-	CTRY_MACAU              = 446, /* Macau */
+-	CTRY_MACEDONIA          = 807, /* Republic of Macedonia */
+-	CTRY_MALAYSIA           = 458, /* Malaysia */
+-	CTRY_MEXICO             = 484, /* Mexico */
+-	CTRY_MONACO             = 492, /* Principality of Monaco */
+-	CTRY_MOROCCO            = 504, /* Morocco */
+-	CTRY_NETHERLANDS        = 528, /* Netherlands */
+-	CTRY_NEW_ZEALAND        = 554, /* New Zealand */
+-	CTRY_NICARAGUA          = 558, /* Nicaragua */
+-	CTRY_NORWAY             = 578, /* Norway */
+-	CTRY_OMAN               = 512, /* Oman */
+-	CTRY_PAKISTAN           = 586, /* Islamic Republic of Pakistan */
+-	CTRY_PANAMA             = 591, /* Panama */
+-	CTRY_PARAGUAY           = 600, /* Paraguay */
+-	CTRY_PERU               = 604, /* Peru */
+-	CTRY_PHILIPPINES        = 608, /* Republic of the Philippines */
+-	CTRY_POLAND             = 616, /* Poland */
+-	CTRY_PORTUGAL           = 620, /* Portugal */
+-	CTRY_PUERTO_RICO        = 630, /* Puerto Rico */
+-	CTRY_QATAR              = 634, /* Qatar */
+-	CTRY_ROMANIA            = 642, /* Romania */
+-	CTRY_RUSSIA             = 643, /* Russia */
+-	CTRY_SAUDI_ARABIA       = 682, /* Saudi Arabia */
+-	CTRY_SINGAPORE          = 702, /* Singapore */
+-	CTRY_SLOVAKIA           = 703, /* Slovak Republic */
+-	CTRY_SLOVENIA           = 705, /* Slovenia */
+-	CTRY_SOUTH_AFRICA       = 710, /* South Africa */
+-	CTRY_SPAIN              = 724, /* Spain */
+-	CTRY_SRI_LANKA          = 728, /* Sri Lanka */
+-	CTRY_SWEDEN             = 752, /* Sweden */
+-	CTRY_SWITZERLAND        = 756, /* Switzerland */
+-	CTRY_SYRIA              = 760, /* Syria */
+-	CTRY_TAIWAN             = 158, /* Taiwan */
+-	CTRY_THAILAND           = 764, /* Thailand */
+-	CTRY_TRINIDAD_Y_TOBAGO  = 780, /* Trinidad y Tobago */
+-	CTRY_TUNISIA            = 788, /* Tunisia */
+-	CTRY_TURKEY             = 792, /* Turkey */
+-	CTRY_UAE                = 784, /* U.A.E. */
+-	CTRY_UKRAINE            = 804, /* Ukraine */
+-	CTRY_UNITED_KINGDOM     = 826, /* United Kingdom */
+-	CTRY_UNITED_STATES      = 840, /* United States */
+-	CTRY_URUGUAY            = 858, /* Uruguay */
+-	CTRY_UZBEKISTAN         = 860, /* Uzbekistan */
+-	CTRY_VENEZUELA          = 862, /* Venezuela */
+-	CTRY_VIET_NAM           = 704, /* Viet Nam */
+-	CTRY_YEMEN              = 887, /* Yemen */
+-	CTRY_ZIMBABWE           = 716, /* Zimbabwe */
+-};
+-
+-#define IEEE80211_CHANNELS_2GHZ_MIN	2412	/* 2GHz channel 1 */
+-#define IEEE80211_CHANNELS_2GHZ_MAX	2732	/* 2GHz channel 26 */
+-#define IEEE80211_CHANNELS_5GHZ_MIN	5005	/* 5GHz channel 1 */
+-#define IEEE80211_CHANNELS_5GHZ_MAX	6100	/* 5GHz channel 220 */
+-
+-struct ath5k_regchannel {
+-	u16 chan;
+-	enum ath5k_regdom domain;
+-	u32 mode;
+-};
+-
+-#define IEEE80211_CHANNELS_2GHZ {					\
+-/*2412*/ {   1, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2417*/ {   2, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2422*/ {   3, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2427*/ {   4, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2432*/ {   5, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2437*/ {   6, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2442*/ {   7, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2447*/ {   8, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2452*/ {   9, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2457*/ {  10, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2462*/ {  11, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2467*/ {  12, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2472*/ {  13, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-									\
+-/*2432*/ {   5, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2437*/ {   6, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*2442*/ {   7, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM },			\
+-									\
+-/*2412*/ {   1, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2417*/ {   2, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2422*/ {   3, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2427*/ {   4, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2432*/ {   5, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2437*/ {   6, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*2442*/ {   7, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2447*/ {   8, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2452*/ {   9, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2457*/ {  10, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2462*/ {  11, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2467*/ {  12, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2472*/ {  13, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM },			\
+-									\
+-/*2412*/ {   1, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2417*/ {   2, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2422*/ {   3, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2427*/ {   4, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2432*/ {   5, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2437*/ {   6, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*2442*/ {   7, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2447*/ {   8, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2452*/ {   9, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2457*/ {  10, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2462*/ {  11, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-									\
+-/*2412*/ {   1, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2417*/ {   2, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2422*/ {   3, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2427*/ {   4, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2432*/ {   5, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2437*/ {   6, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2442*/ {   7, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2447*/ {   8, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2452*/ {   9, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2457*/ {  10, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2462*/ {  11, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2467*/ {  12, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2472*/ {  13, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2484*/ {  14, DMN_MKKA, CHANNEL_CCK },				\
+-									\
+-/*2412*/ {   1, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2417*/ {   2, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2422*/ {   3, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2427*/ {   4, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2432*/ {   5, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2437*/ {   6, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*2442*/ {   7, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2447*/ {   8, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2452*/ {   9, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2457*/ {  10, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2462*/ {  11, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2467*/ {  12, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-/*2472*/ {  13, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM },			\
+-}
+-
+-#define IEEE80211_CHANNELS_5GHZ {			\
+-/*5745*/ { 149, DMN_APL1, CHANNEL_OFDM },		\
+-/*5765*/ { 153, DMN_APL1, CHANNEL_OFDM },		\
+-/*5785*/ { 157, DMN_APL1, CHANNEL_OFDM },		\
+-/*5805*/ { 161, DMN_APL1, CHANNEL_OFDM },		\
+-/*5825*/ { 165, DMN_APL1, CHANNEL_OFDM },		\
+-							\
+-/*5745*/ { 149, DMN_APL2, CHANNEL_OFDM },		\
+-/*5765*/ { 153, DMN_APL2, CHANNEL_OFDM },		\
+-/*5785*/ { 157, DMN_APL2, CHANNEL_OFDM },		\
+-/*5805*/ { 161, DMN_APL2, CHANNEL_OFDM },		\
+-							\
+-/*5280*/ {  56, DMN_APL3, CHANNEL_OFDM },		\
+-/*5300*/ {  60, DMN_APL3, CHANNEL_OFDM },		\
+-/*5320*/ {  64, DMN_APL3, CHANNEL_OFDM },		\
+-/*5745*/ { 149, DMN_APL3, CHANNEL_OFDM },		\
+-/*5765*/ { 153, DMN_APL3, CHANNEL_OFDM },		\
+-/*5785*/ { 157, DMN_APL3, CHANNEL_OFDM },		\
+-/*5805*/ { 161, DMN_APL3, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_APL4, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_APL4, CHANNEL_OFDM },		\
+-/*5220*/ {  44, DMN_APL4, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_APL4, CHANNEL_OFDM },		\
+-/*5745*/ { 149, DMN_APL4, CHANNEL_OFDM },		\
+-/*5765*/ { 153, DMN_APL4, CHANNEL_OFDM },		\
+-/*5785*/ { 157, DMN_APL4, CHANNEL_OFDM },		\
+-/*5805*/ { 161, DMN_APL4, CHANNEL_OFDM },		\
+-/*5825*/ { 165, DMN_APL4, CHANNEL_OFDM },		\
+-							\
+-/*5745*/ { 149, DMN_APL5, CHANNEL_OFDM },		\
+-/*5765*/ { 153, DMN_APL5, CHANNEL_OFDM },		\
+-/*5785*/ { 157, DMN_APL5, CHANNEL_OFDM },		\
+-/*5805*/ { 161, DMN_APL5, CHANNEL_OFDM },		\
+-/*5825*/ { 165, DMN_APL5, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5220*/ {  44, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5260*/ {  52, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5280*/ {  56, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5300*/ {  60, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5320*/ {  64, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5500*/ { 100, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5520*/ { 104, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5540*/ { 108, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5560*/ { 112, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5580*/ { 116, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5600*/ { 120, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5620*/ { 124, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5640*/ { 128, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5660*/ { 132, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5680*/ { 136, DMN_ETSI1, CHANNEL_OFDM },		\
+-/*5700*/ { 140, DMN_ETSI1, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_ETSI2, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_ETSI2, CHANNEL_OFDM },		\
+-/*5220*/ {  44, DMN_ETSI2, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_ETSI2, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_ETSI3, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_ETSI3, CHANNEL_OFDM },		\
+-/*5220*/ {  44, DMN_ETSI3, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_ETSI3, CHANNEL_OFDM },		\
+-/*5260*/ {  52, DMN_ETSI3, CHANNEL_OFDM },		\
+-/*5280*/ {  56, DMN_ETSI3, CHANNEL_OFDM },		\
+-/*5300*/ {  60, DMN_ETSI3, CHANNEL_OFDM },		\
+-/*5320*/ {  64, DMN_ETSI3, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_ETSI4, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_ETSI4, CHANNEL_OFDM },		\
+-/*5220*/ {  44, DMN_ETSI4, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_ETSI4, CHANNEL_OFDM },		\
+-/*5260*/ {  52, DMN_ETSI4, CHANNEL_OFDM },		\
+-/*5280*/ {  56, DMN_ETSI4, CHANNEL_OFDM },		\
+-/*5300*/ {  60, DMN_ETSI4, CHANNEL_OFDM },		\
+-/*5320*/ {  64, DMN_ETSI4, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_ETSI5, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_ETSI5, CHANNEL_OFDM },		\
+-/*5220*/ {  44, DMN_ETSI5, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_ETSI5, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5220*/ {  44, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5260*/ {  52, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5280*/ {  56, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5500*/ { 100, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5520*/ { 104, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5540*/ { 108, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5560*/ { 112, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5580*/ { 116, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5600*/ { 120, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5620*/ { 124, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5640*/ { 128, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5660*/ { 132, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5680*/ { 136, DMN_ETSI6, CHANNEL_OFDM },		\
+-/*5700*/ { 140, DMN_ETSI6, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5210*/ {  42, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5220*/ {  44, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5250*/ {  50, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5260*/ {  52, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5280*/ {  56, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5290*/ {  58, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5300*/ {  60, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5320*/ {  64, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5745*/ { 149, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5760*/ { 152, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5765*/ { 153, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5785*/ { 157, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5800*/ { 160, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5805*/ { 161, DMN_FCC1, CHANNEL_OFDM },		\
+-/*5825*/ { 165, DMN_FCC1, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5220*/ {  44, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5260*/ {  52, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5280*/ {  56, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5300*/ {  60, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5320*/ {  64, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5745*/ { 149, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5765*/ { 153, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5785*/ { 157, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5805*/ { 161, DMN_FCC2, CHANNEL_OFDM },		\
+-/*5825*/ { 165, DMN_FCC2, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5210*/ {  42, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5220*/ {  44, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5250*/ {  50, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5260*/ {  52, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5280*/ {  56, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5290*/ {  58, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5300*/ {  60, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5320*/ {  64, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5500*/ { 100, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5520*/ { 104, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5540*/ { 108, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5560*/ { 112, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5580*/ { 116, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5600*/ { 120, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5620*/ { 124, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5640*/ { 128, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5660*/ { 132, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5680*/ { 136, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5700*/ { 140, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5745*/ { 149, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5760*/ { 152, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5765*/ { 153, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5785*/ { 157, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5800*/ { 160, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO },	\
+-/*5805*/ { 161, DMN_FCC3, CHANNEL_OFDM },		\
+-/*5825*/ { 165, DMN_FCC3, CHANNEL_OFDM },		\
+-							\
+-/*5170*/ {  34, DMN_MKK1, CHANNEL_OFDM },		\
+-/*5190*/ {  38, DMN_MKK1, CHANNEL_OFDM },		\
+-/*5210*/ {  42, DMN_MKK1, CHANNEL_OFDM },		\
+-/*5230*/ {  46, DMN_MKK1, CHANNEL_OFDM },		\
+-							\
+-/*5040*/ {   8, DMN_MKK2, CHANNEL_OFDM },		\
+-/*5060*/ {  12, DMN_MKK2, CHANNEL_OFDM },		\
+-/*5080*/ {  16, DMN_MKK2, CHANNEL_OFDM },		\
+-/*5170*/ {  34, DMN_MKK2, CHANNEL_OFDM },		\
+-/*5190*/ {  38, DMN_MKK2, CHANNEL_OFDM },		\
+-/*5210*/ {  42, DMN_MKK2, CHANNEL_OFDM },		\
+-/*5230*/ {  46, DMN_MKK2, CHANNEL_OFDM },		\
+-							\
+-/*5180*/ {  36, DMN_WORLD, CHANNEL_OFDM },		\
+-/*5200*/ {  40, DMN_WORLD, CHANNEL_OFDM },		\
+-/*5220*/ {  44, DMN_WORLD, CHANNEL_OFDM },		\
+-/*5240*/ {  48, DMN_WORLD, CHANNEL_OFDM },		\
+-}
+-
+-enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16);
+-u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee);
+-enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain);
+-
+-#endif
+diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
+index 63ec7a7..ef2da40 100644
+--- a/drivers/net/wireless/atmel.c
++++ b/drivers/net/wireless/atmel.c
+@@ -66,6 +66,7 @@
+ #include <linux/device.h>
+ #include <linux/moduleparam.h>
+ #include <linux/firmware.h>
++#include <linux/jiffies.h>
+ #include <net/ieee80211.h>
+ #include "atmel.h"
+ 
+@@ -516,7 +517,7 @@ struct atmel_private {
+ 		SITE_SURVEY_IN_PROGRESS,
+ 		SITE_SURVEY_COMPLETED
+ 	} site_survey_state;
+-	time_t last_survey;
++	unsigned long last_survey;
+ 
+ 	int station_was_associated, station_is_associated;
+ 	int fast_scan;
+@@ -2283,7 +2284,7 @@ static int atmel_set_scan(struct net_device *dev,
+ 		return -EAGAIN;
+ 
+ 	/* Timeout old surveys. */
+-	if ((jiffies - priv->last_survey) > (20 * HZ))
++	if (time_after(jiffies, priv->last_survey + 20 * HZ))
+ 		priv->site_survey_state = SITE_SURVEY_IDLE;
+ 	priv->last_survey = jiffies;
+ 
+diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
+index 8bc4bc4..f51b2d9 100644
+--- a/drivers/net/wireless/b43/Kconfig
++++ b/drivers/net/wireless/b43/Kconfig
+@@ -62,6 +62,14 @@ config B43_PCMCIA
+ 
+ 	  If unsure, say N.
+ 
++# Data transfers to the device via PIO
++# This is only needed on PCMCIA devices. All others can do DMA properly.
++config B43_PIO
++	bool
++	depends on B43 && (B43_PCMCIA || B43_FORCE_PIO)
++	select SSB_BLOCKIO
++	default y
++
+ config B43_NPHY
+ 	bool "Pre IEEE 802.11n support (BROKEN)"
+ 	depends on B43 && EXPERIMENTAL && BROKEN
+@@ -94,3 +102,13 @@ config B43_DEBUG
+ 
+ 	  Say Y, if you want to find out why the driver does not
+ 	  work for you.
++
++config B43_FORCE_PIO
++	bool "Force usage of PIO instead of DMA"
++	depends on B43 && B43_DEBUG
++	---help---
++	  This will disable DMA and always enable PIO instead.
++
++	  Say N!
++	  This is only for debugging the PIO engine code. You do
++	  _NOT_ want to enable this.
+diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
+index ac1329d..8c52b0b 100644
+--- a/drivers/net/wireless/b43/Makefile
++++ b/drivers/net/wireless/b43/Makefile
+@@ -1,13 +1,14 @@
+ b43-y				+= main.o
+ b43-y				+= tables.o
+-b43-y				+= tables_nphy.o
++b43-$(CONFIG_B43_NPHY)		+= tables_nphy.o
+ b43-y				+= phy.o
+-b43-y				+= nphy.o
++b43-$(CONFIG_B43_NPHY)		+= nphy.o
+ b43-y				+= sysfs.o
+ b43-y				+= xmit.o
+ b43-y				+= lo.o
+ b43-y				+= wa.o
+ b43-y				+= dma.o
++b43-$(CONFIG_B43_PIO)		+= pio.o
+ b43-$(CONFIG_B43_RFKILL)	+= rfkill.o
+ b43-$(CONFIG_B43_LEDS)		+= leds.o
+ b43-$(CONFIG_B43_PCMCIA)	+= pcmcia.o
+diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
+index f13346b..eff2a15 100644
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -75,6 +75,23 @@
+ #define B43_MMIO_DMA64_BASE4		0x300
+ #define B43_MMIO_DMA64_BASE5		0x340
+ 
++/* PIO on core rev < 11 */
++#define B43_MMIO_PIO_BASE0		0x300
++#define B43_MMIO_PIO_BASE1		0x310
++#define B43_MMIO_PIO_BASE2		0x320
++#define B43_MMIO_PIO_BASE3		0x330
++#define B43_MMIO_PIO_BASE4		0x340
++#define B43_MMIO_PIO_BASE5		0x350
++#define B43_MMIO_PIO_BASE6		0x360
++#define B43_MMIO_PIO_BASE7		0x370
++/* PIO on core rev >= 11 */
++#define B43_MMIO_PIO11_BASE0		0x200
++#define B43_MMIO_PIO11_BASE1		0x240
++#define B43_MMIO_PIO11_BASE2		0x280
++#define B43_MMIO_PIO11_BASE3		0x2C0
++#define B43_MMIO_PIO11_BASE4		0x300
++#define B43_MMIO_PIO11_BASE5		0x340
++
+ #define B43_MMIO_PHY_VER		0x3E0
+ #define B43_MMIO_PHY_RADIO		0x3E2
+ #define B43_MMIO_PHY0			0x3E6
+@@ -94,11 +111,14 @@
+ #define B43_MMIO_GPIO_MASK		0x49E
+ #define B43_MMIO_TSF_CFP_START_LOW	0x604
+ #define B43_MMIO_TSF_CFP_START_HIGH	0x606
++#define B43_MMIO_TSF_CFP_PRETBTT	0x612
+ #define B43_MMIO_TSF_0			0x632	/* core rev < 3 only */
+ #define B43_MMIO_TSF_1			0x634	/* core rev < 3 only */
+ #define B43_MMIO_TSF_2			0x636	/* core rev < 3 only */
+ #define B43_MMIO_TSF_3			0x638	/* core rev < 3 only */
+ #define B43_MMIO_RNG			0x65A
++#define B43_MMIO_IFSCTL			0x688 /* Interframe space control */
++#define  B43_MMIO_IFSCTL_USE_EDCF	0x0004
+ #define B43_MMIO_POWERUP_DELAY		0x6A8
+ 
+ /* SPROM boardflags_lo values */
+@@ -144,7 +164,8 @@ enum {
+ #define B43_SHM_SH_PHYTYPE		0x0052	/* PHY type */
+ #define B43_SHM_SH_ANTSWAP		0x005C	/* Antenna swap threshold */
+ #define B43_SHM_SH_HOSTFLO		0x005E	/* Hostflags for ucode options (low) */
+-#define B43_SHM_SH_HOSTFHI		0x0060	/* Hostflags for ucode options (high) */
++#define B43_SHM_SH_HOSTFMI		0x0060	/* Hostflags for ucode options (middle) */
++#define B43_SHM_SH_HOSTFHI		0x0062	/* Hostflags for ucode options (high) */
+ #define B43_SHM_SH_RFATT		0x0064	/* Current radio attenuation value */
+ #define B43_SHM_SH_RADAR		0x0066	/* Radar register */
+ #define B43_SHM_SH_PHYTXNOI		0x006E	/* PHY noise directly after TX (lower 8bit only) */
+@@ -232,31 +253,41 @@ enum {
+ #define B43_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
+ 
+ /* HostFlags. See b43_hf_read/write() */
+-#define B43_HF_ANTDIVHELP		0x00000001	/* ucode antenna div helper */
+-#define B43_HF_SYMW			0x00000002	/* G-PHY SYM workaround */
+-#define B43_HF_RXPULLW			0x00000004	/* RX pullup workaround */
+-#define B43_HF_CCKBOOST			0x00000008	/* 4dB CCK power boost (exclusive with OFDM boost) */
+-#define B43_HF_BTCOEX			0x00000010	/* Bluetooth coexistance */
+-#define B43_HF_GDCW			0x00000020	/* G-PHY DV canceller filter bw workaround */
+-#define B43_HF_OFDMPABOOST		0x00000040	/* Enable PA gain boost for OFDM */
+-#define B43_HF_ACPR			0x00000080	/* Disable for Japan, channel 14 */
+-#define B43_HF_EDCF			0x00000100	/* on if WME and MAC suspended */
+-#define B43_HF_TSSIRPSMW		0x00000200	/* TSSI reset PSM ucode workaround */
+-#define B43_HF_DSCRQ			0x00000400	/* Disable slow clock request in ucode */
+-#define B43_HF_ACIW			0x00000800	/* ACI workaround: shift bits by 2 on PHY CRS */
+-#define B43_HF_2060W			0x00001000	/* 2060 radio workaround */
+-#define B43_HF_RADARW			0x00002000	/* Radar workaround */
+-#define B43_HF_USEDEFKEYS		0x00004000	/* Enable use of default keys */
+-#define B43_HF_BT4PRIOCOEX		0x00010000	/* Bluetooth 2-priority coexistance */
+-#define B43_HF_FWKUP			0x00020000	/* Fast wake-up ucode */
+-#define B43_HF_VCORECALC		0x00040000	/* Force VCO recalculation when powering up synthpu */
+-#define B43_HF_PCISCW			0x00080000	/* PCI slow clock workaround */
+-#define B43_HF_4318TSSI			0x00200000	/* 4318 TSSI */
+-#define B43_HF_FBCMCFIFO		0x00400000	/* Flush bcast/mcast FIFO immediately */
+-#define B43_HF_HWPCTL			0x00800000	/* Enable hardwarre power control */
+-#define B43_HF_BTCOEXALT		0x01000000	/* Bluetooth coexistance in alternate pins */
+-#define B43_HF_TXBTCHECK		0x02000000	/* Bluetooth check during transmission */
+-#define B43_HF_SKCFPUP			0x04000000	/* Skip CFP update */
++#define B43_HF_ANTDIVHELP	0x000000000001ULL /* ucode antenna div helper */
++#define B43_HF_SYMW		0x000000000002ULL /* G-PHY SYM workaround */
++#define B43_HF_RXPULLW		0x000000000004ULL /* RX pullup workaround */
++#define B43_HF_CCKBOOST		0x000000000008ULL /* 4dB CCK power boost (exclusive with OFDM boost) */
++#define B43_HF_BTCOEX		0x000000000010ULL /* Bluetooth coexistance */
++#define B43_HF_GDCW		0x000000000020ULL /* G-PHY DC canceller filter bw workaround */
++#define B43_HF_OFDMPABOOST	0x000000000040ULL /* Enable PA gain boost for OFDM */
++#define B43_HF_ACPR		0x000000000080ULL /* Disable for Japan, channel 14 */
++#define B43_HF_EDCF		0x000000000100ULL /* on if WME and MAC suspended */
++#define B43_HF_TSSIRPSMW	0x000000000200ULL /* TSSI reset PSM ucode workaround */
++#define B43_HF_20IN40IQW	0x000000000200ULL /* 20 in 40 MHz I/Q workaround (rev >= 13 only) */
++#define B43_HF_DSCRQ		0x000000000400ULL /* Disable slow clock request in ucode */
++#define B43_HF_ACIW		0x000000000800ULL /* ACI workaround: shift bits by 2 on PHY CRS */
++#define B43_HF_2060W		0x000000001000ULL /* 2060 radio workaround */
++#define B43_HF_RADARW		0x000000002000ULL /* Radar workaround */
++#define B43_HF_USEDEFKEYS	0x000000004000ULL /* Enable use of default keys */
++#define B43_HF_AFTERBURNER	0x000000008000ULL /* Afterburner enabled */
++#define B43_HF_BT4PRIOCOEX	0x000000010000ULL /* Bluetooth 4-priority coexistance */
++#define B43_HF_FWKUP		0x000000020000ULL /* Fast wake-up ucode */
++#define B43_HF_VCORECALC	0x000000040000ULL /* Force VCO recalculation when powering up synthpu */
++#define B43_HF_PCISCW		0x000000080000ULL /* PCI slow clock workaround */
++#define B43_HF_4318TSSI		0x000000200000ULL /* 4318 TSSI */
++#define B43_HF_FBCMCFIFO	0x000000400000ULL /* Flush bcast/mcast FIFO immediately */
++#define B43_HF_HWPCTL		0x000000800000ULL /* Enable hardwarre power control */
++#define B43_HF_BTCOEXALT	0x000001000000ULL /* Bluetooth coexistance in alternate pins */
++#define B43_HF_TXBTCHECK	0x000002000000ULL /* Bluetooth check during transmission */
++#define B43_HF_SKCFPUP		0x000004000000ULL /* Skip CFP update */
++#define B43_HF_N40W		0x000008000000ULL /* N PHY 40 MHz workaround (rev >= 13 only) */
++#define B43_HF_ANTSEL		0x000020000000ULL /* Antenna selection (for testing antenna div.) */
++#define B43_HF_BT3COEXT		0x000020000000ULL /* Bluetooth 3-wire coexistence (rev >= 13 only) */
++#define B43_HF_BTCANT		0x000040000000ULL /* Bluetooth coexistence (antenna mode) (rev >= 13 only) */
++#define B43_HF_ANTSELEN		0x000100000000ULL /* Antenna selection enabled (rev >= 13 only) */
++#define B43_HF_ANTSELMODE	0x000200000000ULL /* Antenna selection mode (rev >= 13 only) */
++#define B43_HF_MLADVW		0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */
++#define B43_HF_PR45960W		0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */
+ 
+ /* MacFilter offsets. */
+ #define B43_MACFILTER_SELF		0x0000
+@@ -380,7 +411,6 @@ enum {
+ 
+ #define B43_IRQ_ALL			0xFFFFFFFF
+ #define B43_IRQ_MASKTEMPLATE		(B43_IRQ_MAC_SUSPENDED | \
+-					 B43_IRQ_BEACON | \
+ 					 B43_IRQ_TBTT_INDI | \
+ 					 B43_IRQ_ATIM_END | \
+ 					 B43_IRQ_PMQ | \
+@@ -429,7 +459,6 @@ enum {
+ };
+ 
+ struct b43_dmaring;
+-struct b43_pioqueue;
+ 
+ /* The firmware file header */
+ #define B43_FW_TYPE_UCODE	'u'
+@@ -458,20 +487,13 @@ struct b43_iv {
+ } __attribute__((__packed__));
+ 
+ 
+-#define B43_PHYMODE(phytype)		(1 << (phytype))
+-#define B43_PHYMODE_A			B43_PHYMODE(B43_PHYTYPE_A)
+-#define B43_PHYMODE_B			B43_PHYMODE(B43_PHYTYPE_B)
+-#define B43_PHYMODE_G			B43_PHYMODE(B43_PHYTYPE_G)
+-
+ struct b43_phy {
+-	/* Possible PHYMODEs on this PHY */
+-	u8 possible_phymodes;
++	/* Band support flags. */
++	bool supports_2ghz;
++	bool supports_5ghz;
++
+ 	/* GMODE bit enabled? */
+ 	bool gmode;
+-	/* Possible ieee80211 subsystem hwmodes for this PHY.
+-	 * Which mode is selected, depends on thr GMODE enabled bit */
+-#define B43_MAX_PHYHWMODES	2
+-	struct ieee80211_hw_mode hwmodes[B43_MAX_PHYHWMODES];
+ 
+ 	/* Analog Type */
+ 	u8 analog;
+@@ -583,15 +605,27 @@ struct b43_phy {
+ 
+ /* Data structures for DMA transmission, per 80211 core. */
+ struct b43_dma {
+-	struct b43_dmaring *tx_ring0;
+-	struct b43_dmaring *tx_ring1;
+-	struct b43_dmaring *tx_ring2;
+-	struct b43_dmaring *tx_ring3;
+-	struct b43_dmaring *tx_ring4;
+-	struct b43_dmaring *tx_ring5;
+-
+-	struct b43_dmaring *rx_ring0;
+-	struct b43_dmaring *rx_ring3;	/* only available on core.rev < 5 */
++	struct b43_dmaring *tx_ring_AC_BK; /* Background */
++	struct b43_dmaring *tx_ring_AC_BE; /* Best Effort */
++	struct b43_dmaring *tx_ring_AC_VI; /* Video */
++	struct b43_dmaring *tx_ring_AC_VO; /* Voice */
++	struct b43_dmaring *tx_ring_mcast; /* Multicast */
++
++	struct b43_dmaring *rx_ring;
++};
++
++struct b43_pio_txqueue;
++struct b43_pio_rxqueue;
++
++/* Data structures for PIO transmission, per 80211 core. */
++struct b43_pio {
++	struct b43_pio_txqueue *tx_queue_AC_BK; /* Background */
++	struct b43_pio_txqueue *tx_queue_AC_BE; /* Best Effort */
++	struct b43_pio_txqueue *tx_queue_AC_VI; /* Video */
++	struct b43_pio_txqueue *tx_queue_AC_VO; /* Voice */
++	struct b43_pio_txqueue *tx_queue_mcast; /* Multicast */
++
++	struct b43_pio_rxqueue *rx_queue;
+ };
+ 
+ /* Context information for a noise calculation (Link Quality). */
+@@ -617,6 +651,35 @@ struct b43_key {
+ 	u8 algorithm;
+ };
+ 
++/* SHM offsets to the QOS data structures for the 4 different queues. */
++#define B43_QOS_PARAMS(queue)	(B43_SHM_SH_EDCFQ + \
++				 (B43_NR_QOSPARAMS * sizeof(u16) * (queue)))
++#define B43_QOS_BACKGROUND	B43_QOS_PARAMS(0)
++#define B43_QOS_BESTEFFORT	B43_QOS_PARAMS(1)
++#define B43_QOS_VIDEO		B43_QOS_PARAMS(2)
++#define B43_QOS_VOICE		B43_QOS_PARAMS(3)
++
++/* QOS parameter hardware data structure offsets. */
++#define B43_NR_QOSPARAMS	22
++enum {
++	B43_QOSPARAM_TXOP = 0,
++	B43_QOSPARAM_CWMIN,
++	B43_QOSPARAM_CWMAX,
++	B43_QOSPARAM_CWCUR,
++	B43_QOSPARAM_AIFS,
++	B43_QOSPARAM_BSLOTS,
++	B43_QOSPARAM_REGGAP,
++	B43_QOSPARAM_STATUS,
++};
++
++/* QOS parameters for a queue. */
++struct b43_qos_params {
++	/* The QOS parameters */
++	struct ieee80211_tx_queue_params p;
++	/* Does this need to get uploaded to hardware? */
++	bool need_hw_update;
++};
++
+ struct b43_wldev;
+ 
+ /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
+@@ -667,8 +730,16 @@ struct b43_wl {
+ 	/* The beacon we are currently using (AP or IBSS mode).
+ 	 * This beacon stuff is protected by the irq_lock. */
+ 	struct sk_buff *current_beacon;
++	struct ieee80211_tx_control beacon_txctl;
+ 	bool beacon0_uploaded;
+ 	bool beacon1_uploaded;
++	struct work_struct beacon_update_trigger;
++
++	/* The current QOS parameters for the 4 queues.
++	 * This is protected by the irq_lock. */
++	struct b43_qos_params qos_params[4];
++	/* Workqueue for updating QOS parameters in hardware. */
++	struct work_struct qos_update_work;
+ };
+ 
+ /* In-memory representation of a cached microcode file. */
+@@ -727,7 +798,6 @@ struct b43_wldev {
+ 
+ 	bool bad_frames_preempt;	/* Use "Bad Frames Preemption" (default off) */
+ 	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM) */
+-	bool short_preamble;	/* TRUE, if short preamble is enabled. */
+ 	bool short_slot;	/* TRUE, if short slot timing is enabled. */
+ 	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
+ 	bool suspend_in_progress;	/* TRUE, if we are in a suspend/resume cycle */
+@@ -735,8 +805,15 @@ struct b43_wldev {
+ 	/* PHY/Radio device. */
+ 	struct b43_phy phy;
+ 
+-	/* DMA engines. */
+-	struct b43_dma dma;
++	union {
++		/* DMA engines. */
++		struct b43_dma dma;
++		/* PIO engines. */
++		struct b43_pio pio;
++	};
++	/* Use b43_using_pio_transfers() to check whether we are using
++	 * DMA or PIO data transfers. */
++	bool __using_pio_transfers;
+ 
+ 	/* Various statistics about the physical device. */
+ 	struct b43_stats stats;
+@@ -820,6 +897,22 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
+ 	ssb_write32(dev->dev, offset, value);
+ }
+ 
++static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
++{
++#ifdef CONFIG_B43_PIO
++	return dev->__using_pio_transfers;
++#else
++	return 0;
++#endif
++}
++
++#ifdef CONFIG_B43_FORCE_PIO
++# define B43_FORCE_PIO	1
++#else
++# define B43_FORCE_PIO	0
++#endif
++
++
+ /* Message printing */
+ void b43info(struct b43_wl *wl, const char *fmt, ...)
+     __attribute__ ((format(printf, 2, 3)));
+diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
+index 48e9124..6dcbb3c 100644
+--- a/drivers/net/wireless/b43/dma.c
++++ b/drivers/net/wireless/b43/dma.c
+@@ -38,6 +38,7 @@
+ #include <linux/delay.h>
+ #include <linux/skbuff.h>
+ #include <linux/etherdevice.h>
++#include <asm/div64.h>
+ 
+ 
+ /* 32bit DMA ops. */
+@@ -291,52 +292,6 @@ static inline int request_slot(struct b43_dmaring *ring)
+ 	return slot;
+ }
+ 
+-/* Mac80211-queue to b43-ring mapping */
+-static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev,
+-					      int queue_priority)
+-{
+-	struct b43_dmaring *ring;
+-
+-/*FIXME: For now we always run on TX-ring-1 */
+-	return dev->dma.tx_ring1;
+-
+-	/* 0 = highest priority */
+-	switch (queue_priority) {
+-	default:
+-		B43_WARN_ON(1);
+-		/* fallthrough */
+-	case 0:
+-		ring = dev->dma.tx_ring3;
+-		break;
+-	case 1:
+-		ring = dev->dma.tx_ring2;
+-		break;
+-	case 2:
+-		ring = dev->dma.tx_ring1;
+-		break;
+-	case 3:
+-		ring = dev->dma.tx_ring0;
+-		break;
+-	}
+-
+-	return ring;
+-}
+-
+-/* b43-ring to mac80211-queue mapping */
+-static inline int txring_to_priority(struct b43_dmaring *ring)
+-{
+-	static const u8 idx_to_prio[] = { 3, 2, 1, 0, };
+-	unsigned int index;
+-
+-/*FIXME: have only one queue, for now */
+-	return 0;
+-
+-	index = ring->index;
+-	if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio)))
+-		index = 0;
+-	return idx_to_prio[index];
+-}
+-
+ static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx)
+ {
+ 	static const u16 map64[] = {
+@@ -596,7 +551,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
+ 			       struct b43_dmadesc_meta *meta, gfp_t gfp_flags)
+ {
+ 	struct b43_rxhdr_fw4 *rxhdr;
+-	struct b43_hwtxstatus *txstat;
+ 	dma_addr_t dmaaddr;
+ 	struct sk_buff *skb;
+ 
+@@ -632,8 +586,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
+ 
+ 	rxhdr = (struct b43_rxhdr_fw4 *)(skb->data);
+ 	rxhdr->frame_len = 0;
+-	txstat = (struct b43_hwtxstatus *)(skb->data);
+-	txstat->cookie = 0;
+ 
+ 	return 0;
+ }
+@@ -822,6 +774,18 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
+ 	return DMA_30BIT_MASK;
+ }
+ 
++static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask)
++{
++	if (dmamask == DMA_30BIT_MASK)
++		return B43_DMA_30BIT;
++	if (dmamask == DMA_32BIT_MASK)
++		return B43_DMA_32BIT;
++	if (dmamask == DMA_64BIT_MASK)
++		return B43_DMA_64BIT;
++	B43_WARN_ON(1);
++	return B43_DMA_30BIT;
++}
++
+ /* Main initialization function. */
+ static
+ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
+@@ -937,16 +901,52 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
+ 	goto out;
+ }
+ 
++#define divide(a, b)	({	\
++	typeof(a) __a = a;	\
++	do_div(__a, b);		\
++	__a;			\
++  })
++
++#define modulo(a, b)	({	\
++	typeof(a) __a = a;	\
++	do_div(__a, b);		\
++  })
++
+ /* Main cleanup function. */
+-static void b43_destroy_dmaring(struct b43_dmaring *ring)
++static void b43_destroy_dmaring(struct b43_dmaring *ring,
++				const char *ringname)
+ {
+ 	if (!ring)
+ 		return;
+ 
+-	b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n",
+-	       (unsigned int)(ring->type),
+-	       ring->mmio_base,
+-	       (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots);
++#ifdef CONFIG_B43_DEBUG
++	{
++		/* Print some statistics. */
++		u64 failed_packets = ring->nr_failed_tx_packets;
++		u64 succeed_packets = ring->nr_succeed_tx_packets;
++		u64 nr_packets = failed_packets + succeed_packets;
++		u64 permille_failed = 0, average_tries = 0;
++
++		if (nr_packets)
++			permille_failed = divide(failed_packets * 1000, nr_packets);
++		if (nr_packets)
++			average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets);
++
++		b43dbg(ring->dev->wl, "DMA-%u %s: "
++		       "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, "
++		       "Average tries %llu.%02llu\n",
++		       (unsigned int)(ring->type), ringname,
++		       ring->max_used_slots,
++		       ring->nr_slots,
++		       (unsigned long long)failed_packets,
++		       (unsigned long long)nr_packets,
++		       (unsigned long long)divide(permille_failed, 10),
++		       (unsigned long long)modulo(permille_failed, 10),
++		       (unsigned long long)divide(average_tries, 100),
++		       (unsigned long long)modulo(average_tries, 100));
++	}
++#endif /* DEBUG */
++
+ 	/* Device IRQs are disabled prior entering this function,
+ 	 * so no need to take care of concurrency with rx handler stuff.
+ 	 */
+@@ -959,139 +959,129 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring)
+ 	kfree(ring);
+ }
+ 
++#define destroy_ring(dma, ring) do {				\
++	b43_destroy_dmaring((dma)->ring, __stringify(ring));	\
++	(dma)->ring = NULL;					\
++    } while (0)
++
+ void b43_dma_free(struct b43_wldev *dev)
+ {
+-	struct b43_dma *dma = &dev->dma;
++	struct b43_dma *dma;
+ 
+-	b43_destroy_dmaring(dma->rx_ring3);
+-	dma->rx_ring3 = NULL;
+-	b43_destroy_dmaring(dma->rx_ring0);
+-	dma->rx_ring0 = NULL;
+-
+-	b43_destroy_dmaring(dma->tx_ring5);
+-	dma->tx_ring5 = NULL;
+-	b43_destroy_dmaring(dma->tx_ring4);
+-	dma->tx_ring4 = NULL;
+-	b43_destroy_dmaring(dma->tx_ring3);
+-	dma->tx_ring3 = NULL;
+-	b43_destroy_dmaring(dma->tx_ring2);
+-	dma->tx_ring2 = NULL;
+-	b43_destroy_dmaring(dma->tx_ring1);
+-	dma->tx_ring1 = NULL;
+-	b43_destroy_dmaring(dma->tx_ring0);
+-	dma->tx_ring0 = NULL;
++	if (b43_using_pio_transfers(dev))
++		return;
++	dma = &dev->dma;
++
++	destroy_ring(dma, rx_ring);
++	destroy_ring(dma, tx_ring_AC_BK);
++	destroy_ring(dma, tx_ring_AC_BE);
++	destroy_ring(dma, tx_ring_AC_VI);
++	destroy_ring(dma, tx_ring_AC_VO);
++	destroy_ring(dma, tx_ring_mcast);
++}
++
++static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
++{
++	u64 orig_mask = mask;
++	bool fallback = 0;
++	int err;
++
++	/* Try to set the DMA mask. If it fails, try falling back to a
++	 * lower mask, as we can always also support a lower one. */
++	while (1) {
++		err = ssb_dma_set_mask(dev->dev, mask);
++		if (!err)
++			break;
++		if (mask == DMA_64BIT_MASK) {
++			mask = DMA_32BIT_MASK;
++			fallback = 1;
++			continue;
++		}
++		if (mask == DMA_32BIT_MASK) {
++			mask = DMA_30BIT_MASK;
++			fallback = 1;
++			continue;
++		}
++		b43err(dev->wl, "The machine/kernel does not support "
++		       "the required %u-bit DMA mask\n",
++		       (unsigned int)dma_mask_to_engine_type(orig_mask));
++		return -EOPNOTSUPP;
++	}
++	if (fallback) {
++		b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n",
++			(unsigned int)dma_mask_to_engine_type(orig_mask),
++			(unsigned int)dma_mask_to_engine_type(mask));
++	}
++
++	return 0;
+ }
+ 
+ int b43_dma_init(struct b43_wldev *dev)
+ {
+ 	struct b43_dma *dma = &dev->dma;
+-	struct b43_dmaring *ring;
+ 	int err;
+ 	u64 dmamask;
+ 	enum b43_dmatype type;
+ 
+ 	dmamask = supported_dma_mask(dev);
+-	switch (dmamask) {
+-	default:
+-		B43_WARN_ON(1);
+-	case DMA_30BIT_MASK:
+-		type = B43_DMA_30BIT;
+-		break;
+-	case DMA_32BIT_MASK:
+-		type = B43_DMA_32BIT;
+-		break;
+-	case DMA_64BIT_MASK:
+-		type = B43_DMA_64BIT;
+-		break;
+-	}
+-	err = ssb_dma_set_mask(dev->dev, dmamask);
+-	if (err) {
+-		b43err(dev->wl, "The machine/kernel does not support "
+-		       "the required DMA mask (0x%08X%08X)\n",
+-		       (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32),
+-		       (unsigned int)(dmamask & 0x00000000FFFFFFFFULL));
+-		return -EOPNOTSUPP;
+-	}
++	type = dma_mask_to_engine_type(dmamask);
++	err = b43_dma_set_mask(dev, dmamask);
++	if (err)
++		return err;
+ 
+ 	err = -ENOMEM;
+ 	/* setup TX DMA channels. */
+-	ring = b43_setup_dmaring(dev, 0, 1, type);
+-	if (!ring)
++	dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type);
++	if (!dma->tx_ring_AC_BK)
+ 		goto out;
+-	dma->tx_ring0 = ring;
+ 
+-	ring = b43_setup_dmaring(dev, 1, 1, type);
+-	if (!ring)
+-		goto err_destroy_tx0;
+-	dma->tx_ring1 = ring;
++	dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type);
++	if (!dma->tx_ring_AC_BE)
++		goto err_destroy_bk;
+ 
+-	ring = b43_setup_dmaring(dev, 2, 1, type);
+-	if (!ring)
+-		goto err_destroy_tx1;
+-	dma->tx_ring2 = ring;
++	dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type);
++	if (!dma->tx_ring_AC_VI)
++		goto err_destroy_be;
+ 
+-	ring = b43_setup_dmaring(dev, 3, 1, type);
+-	if (!ring)
+-		goto err_destroy_tx2;
+-	dma->tx_ring3 = ring;
++	dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type);
++	if (!dma->tx_ring_AC_VO)
++		goto err_destroy_vi;
+ 
+-	ring = b43_setup_dmaring(dev, 4, 1, type);
+-	if (!ring)
+-		goto err_destroy_tx3;
+-	dma->tx_ring4 = ring;
++	dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type);
++	if (!dma->tx_ring_mcast)
++		goto err_destroy_vo;
+ 
+-	ring = b43_setup_dmaring(dev, 5, 1, type);
+-	if (!ring)
+-		goto err_destroy_tx4;
+-	dma->tx_ring5 = ring;
++	/* setup RX DMA channel. */
++	dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type);
++	if (!dma->rx_ring)
++		goto err_destroy_mcast;
+ 
+-	/* setup RX DMA channels. */
+-	ring = b43_setup_dmaring(dev, 0, 0, type);
+-	if (!ring)
+-		goto err_destroy_tx5;
+-	dma->rx_ring0 = ring;
+-
+-	if (dev->dev->id.revision < 5) {
+-		ring = b43_setup_dmaring(dev, 3, 0, type);
+-		if (!ring)
+-			goto err_destroy_rx0;
+-		dma->rx_ring3 = ring;
+-	}
++	/* No support for the TX status DMA ring. */
++	B43_WARN_ON(dev->dev->id.revision < 5);
+ 
+ 	b43dbg(dev->wl, "%u-bit DMA initialized\n",
+ 	       (unsigned int)type);
+ 	err = 0;
+-      out:
++out:
+ 	return err;
+ 
+-      err_destroy_rx0:
+-	b43_destroy_dmaring(dma->rx_ring0);
+-	dma->rx_ring0 = NULL;
+-      err_destroy_tx5:
+-	b43_destroy_dmaring(dma->tx_ring5);
+-	dma->tx_ring5 = NULL;
+-      err_destroy_tx4:
+-	b43_destroy_dmaring(dma->tx_ring4);
+-	dma->tx_ring4 = NULL;
+-      err_destroy_tx3:
+-	b43_destroy_dmaring(dma->tx_ring3);
+-	dma->tx_ring3 = NULL;
+-      err_destroy_tx2:
+-	b43_destroy_dmaring(dma->tx_ring2);
+-	dma->tx_ring2 = NULL;
+-      err_destroy_tx1:
+-	b43_destroy_dmaring(dma->tx_ring1);
+-	dma->tx_ring1 = NULL;
+-      err_destroy_tx0:
+-	b43_destroy_dmaring(dma->tx_ring0);
+-	dma->tx_ring0 = NULL;
+-	goto out;
++err_destroy_mcast:
++	destroy_ring(dma, tx_ring_mcast);
++err_destroy_vo:
++	destroy_ring(dma, tx_ring_AC_VO);
++err_destroy_vi:
++	destroy_ring(dma, tx_ring_AC_VI);
++err_destroy_be:
++	destroy_ring(dma, tx_ring_AC_BE);
++err_destroy_bk:
++	destroy_ring(dma, tx_ring_AC_BK);
++	return err;
+ }
+ 
+ /* Generate a cookie for the TX header. */
+ static u16 generate_cookie(struct b43_dmaring *ring, int slot)
+ {
+-	u16 cookie = 0x1000;
++	u16 cookie;
+ 
+ 	/* Use the upper 4 bits of the cookie as
+ 	 * DMA controller ID and store the slot number
+@@ -1101,30 +1091,9 @@ static u16 generate_cookie(struct b43_dmaring *ring, int slot)
+ 	 * It can also not be 0xFFFF because that is special
+ 	 * for multicast frames.
+ 	 */
+-	switch (ring->index) {
+-	case 0:
+-		cookie = 0x1000;
+-		break;
+-	case 1:
+-		cookie = 0x2000;
+-		break;
+-	case 2:
+-		cookie = 0x3000;
+-		break;
+-	case 3:
+-		cookie = 0x4000;
+-		break;
+-	case 4:
+-		cookie = 0x5000;
+-		break;
+-	case 5:
+-		cookie = 0x6000;
+-		break;
+-	default:
+-		B43_WARN_ON(1);
+-	}
++	cookie = (((u16)ring->index + 1) << 12);
+ 	B43_WARN_ON(slot & ~0x0FFF);
+-	cookie |= (u16) slot;
++	cookie |= (u16)slot;
+ 
+ 	return cookie;
+ }
+@@ -1138,22 +1107,19 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
+ 
+ 	switch (cookie & 0xF000) {
+ 	case 0x1000:
+-		ring = dma->tx_ring0;
++		ring = dma->tx_ring_AC_BK;
+ 		break;
+ 	case 0x2000:
+-		ring = dma->tx_ring1;
++		ring = dma->tx_ring_AC_BE;
+ 		break;
+ 	case 0x3000:
+-		ring = dma->tx_ring2;
++		ring = dma->tx_ring_AC_VI;
+ 		break;
+ 	case 0x4000:
+-		ring = dma->tx_ring3;
++		ring = dma->tx_ring_AC_VO;
+ 		break;
+ 	case 0x5000:
+-		ring = dma->tx_ring4;
+-		break;
+-	case 0x6000:
+-		ring = dma->tx_ring5;
++		ring = dma->tx_ring_mcast;
+ 		break;
+ 	default:
+ 		B43_WARN_ON(1);
+@@ -1180,7 +1146,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
+ 	size_t hdrsize = b43_txhdr_size(ring->dev);
+ 
+ #define SLOTS_PER_PACKET  2
+-	B43_WARN_ON(skb_shinfo(skb)->nr_frags);
+ 
+ 	old_top_slot = ring->current_slot;
+ 	old_used_slots = ring->used_slots;
+@@ -1285,6 +1250,37 @@ static inline int should_inject_overflow(struct b43_dmaring *ring)
+ 	return 0;
+ }
+ 
++/* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */
++static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev,
++						    u8 queue_prio)
++{
++	struct b43_dmaring *ring;
++
++	if (b43_modparam_qos) {
++		/* 0 = highest priority */
++		switch (queue_prio) {
++		default:
++			B43_WARN_ON(1);
++			/* fallthrough */
++		case 0:
++			ring = dev->dma.tx_ring_AC_VO;
++			break;
++		case 1:
++			ring = dev->dma.tx_ring_AC_VI;
++			break;
++		case 2:
++			ring = dev->dma.tx_ring_AC_BE;
++			break;
++		case 3:
++			ring = dev->dma.tx_ring_AC_BK;
++			break;
++		}
++	} else
++		ring = dev->dma.tx_ring_AC_BE;
++
++	return ring;
++}
++
+ int b43_dma_tx(struct b43_wldev *dev,
+ 	       struct sk_buff *skb, struct ieee80211_tx_control *ctl)
+ {
+@@ -1293,21 +1289,16 @@ int b43_dma_tx(struct b43_wldev *dev,
+ 	int err = 0;
+ 	unsigned long flags;
+ 
+-	if (unlikely(skb->len < 2 + 2 + 6)) {
+-		/* Too short, this can't be a valid frame. */
+-		return -EINVAL;
+-	}
+-
+ 	hdr = (struct ieee80211_hdr *)skb->data;
+ 	if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
+ 		/* The multicast ring will be sent after the DTIM */
+-		ring = dev->dma.tx_ring4;
++		ring = dev->dma.tx_ring_mcast;
+ 		/* Set the more-data bit. Ucode will clear it on
+ 		 * the last frame for us. */
+ 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ 	} else {
+ 		/* Decide by priority where to put this frame. */
+-		ring = priority_to_txring(dev, ctl->queue);
++		ring = select_ring_by_priority(dev, ctl->queue);
+ 	}
+ 
+ 	spin_lock_irqsave(&ring->lock, flags);
+@@ -1322,6 +1313,11 @@ int b43_dma_tx(struct b43_wldev *dev,
+ 	 * That would be a mac80211 bug. */
+ 	B43_WARN_ON(ring->stopped);
+ 
++	/* Assign the queue number to the ring (if not already done before)
++	 * so TX status handling can use it. The queue to ring mapping is
++	 * static, so we don't need to store it per frame. */
++	ring->queue_prio = ctl->queue;
++
+ 	err = dma_tx_fragment(ring, skb, ctl);
+ 	if (unlikely(err == -ENOKEY)) {
+ 		/* Drop this packet, as we don't have the encryption key
+@@ -1338,7 +1334,7 @@ int b43_dma_tx(struct b43_wldev *dev,
+ 	if ((free_slots(ring) < SLOTS_PER_PACKET) ||
+ 	    should_inject_overflow(ring)) {
+ 		/* This TX ring is full. */
+-		ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring));
++		ieee80211_stop_queue(dev->wl->hw, ctl->queue);
+ 		ring->stopped = 1;
+ 		if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
+ 			b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
+@@ -1359,6 +1355,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ 	struct b43_dmadesc_generic *desc;
+ 	struct b43_dmadesc_meta *meta;
+ 	int slot;
++	bool frame_succeed;
+ 
+ 	ring = parse_cookie(dev, status->cookie, &slot);
+ 	if (unlikely(!ring))
+@@ -1385,18 +1382,15 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ 			 * status of the transmission.
+ 			 * Some fields of txstat are already filled in dma_tx().
+ 			 */
+-			if (status->acked) {
+-				meta->txstat.flags |= IEEE80211_TX_STATUS_ACK;
+-			} else {
+-				if (!(meta->txstat.control.flags
+-				      & IEEE80211_TXCTL_NO_ACK))
+-					meta->txstat.excessive_retries = 1;
+-			}
+-			if (status->frame_count == 0) {
+-				/* The frame was not transmitted at all. */
+-				meta->txstat.retry_count = 0;
+-			} else
+-				meta->txstat.retry_count = status->frame_count - 1;
++			frame_succeed = b43_fill_txstatus_report(
++						&(meta->txstat), status);
++#ifdef CONFIG_B43_DEBUG
++			if (frame_succeed)
++				ring->nr_succeed_tx_packets++;
++			else
++				ring->nr_failed_tx_packets++;
++			ring->nr_total_packet_tries += status->frame_count;
++#endif /* DEBUG */
+ 			ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb,
+ 						    &(meta->txstat));
+ 			/* skb is freed by ieee80211_tx_status_irqsafe() */
+@@ -1418,7 +1412,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ 	dev->stats.last_tx = jiffies;
+ 	if (ring->stopped) {
+ 		B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
+-		ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring));
++		ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
+ 		ring->stopped = 0;
+ 		if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
+ 			b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
+@@ -1439,7 +1433,7 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev,
+ 
+ 	for (i = 0; i < nr_queues; i++) {
+ 		data = &(stats->data[i]);
+-		ring = priority_to_txring(dev, i);
++		ring = select_ring_by_priority(dev, i);
+ 
+ 		spin_lock_irqsave(&ring->lock, flags);
+ 		data->len = ring->used_slots / SLOTS_PER_PACKET;
+@@ -1465,25 +1459,6 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
+ 	sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
+ 	skb = meta->skb;
+ 
+-	if (ring->index == 3) {
+-		/* We received an xmit status. */
+-		struct b43_hwtxstatus *hw = (struct b43_hwtxstatus *)skb->data;
+-		int i = 0;
+-
+-		while (hw->cookie == 0) {
+-			if (i > 100)
+-				break;
+-			i++;
+-			udelay(2);
+-			barrier();
+-		}
+-		b43_handle_hwtxstatus(ring->dev, hw);
+-		/* recycle the descriptor buffer. */
+-		sync_descbuffer_for_device(ring, meta->dmaaddr,
+-					   ring->rx_buffersize);
+-
+-		return;
+-	}
+ 	rxhdr = (struct b43_rxhdr_fw4 *)skb->data;
+ 	len = le16_to_cpu(rxhdr->frame_len);
+ 	if (len == 0) {
+@@ -1540,7 +1515,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
+ 	skb_pull(skb, ring->frameoffset);
+ 
+ 	b43_rx(ring->dev, skb, rxhdr);
+-      drop:
++drop:
+ 	return;
+ }
+ 
+@@ -1586,21 +1561,55 @@ static void b43_dma_tx_resume_ring(struct b43_dmaring *ring)
+ void b43_dma_tx_suspend(struct b43_wldev *dev)
+ {
+ 	b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
+-	b43_dma_tx_suspend_ring(dev->dma.tx_ring0);
+-	b43_dma_tx_suspend_ring(dev->dma.tx_ring1);
+-	b43_dma_tx_suspend_ring(dev->dma.tx_ring2);
+-	b43_dma_tx_suspend_ring(dev->dma.tx_ring3);
+-	b43_dma_tx_suspend_ring(dev->dma.tx_ring4);
+-	b43_dma_tx_suspend_ring(dev->dma.tx_ring5);
++	b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BK);
++	b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BE);
++	b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VI);
++	b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VO);
++	b43_dma_tx_suspend_ring(dev->dma.tx_ring_mcast);
+ }
+ 
+ void b43_dma_tx_resume(struct b43_wldev *dev)
+ {
+-	b43_dma_tx_resume_ring(dev->dma.tx_ring5);
+-	b43_dma_tx_resume_ring(dev->dma.tx_ring4);
+-	b43_dma_tx_resume_ring(dev->dma.tx_ring3);
+-	b43_dma_tx_resume_ring(dev->dma.tx_ring2);
+-	b43_dma_tx_resume_ring(dev->dma.tx_ring1);
+-	b43_dma_tx_resume_ring(dev->dma.tx_ring0);
++	b43_dma_tx_resume_ring(dev->dma.tx_ring_mcast);
++	b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VO);
++	b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VI);
++	b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BE);
++	b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK);
+ 	b43_power_saving_ctl_bits(dev, 0);
+ }
++
++#ifdef CONFIG_B43_PIO
++static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
++			   u16 mmio_base, bool enable)
++{
++	u32 ctl;
++
++	if (type == B43_DMA_64BIT) {
++		ctl = b43_read32(dev, mmio_base + B43_DMA64_RXCTL);
++		ctl &= ~B43_DMA64_RXDIRECTFIFO;
++		if (enable)
++			ctl |= B43_DMA64_RXDIRECTFIFO;
++		b43_write32(dev, mmio_base + B43_DMA64_RXCTL, ctl);
++	} else {
++		ctl = b43_read32(dev, mmio_base + B43_DMA32_RXCTL);
++		ctl &= ~B43_DMA32_RXDIRECTFIFO;
++		if (enable)
++			ctl |= B43_DMA32_RXDIRECTFIFO;
++		b43_write32(dev, mmio_base + B43_DMA32_RXCTL, ctl);
++	}
++}
++
++/* Enable/Disable Direct FIFO Receive Mode (PIO) on a RX engine.
++ * This is called from PIO code, so DMA structures are not available. */
++void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
++			    unsigned int engine_index, bool enable)
++{
++	enum b43_dmatype type;
++	u16 mmio_base;
++
++	type = dma_mask_to_engine_type(supported_dma_mask(dev));
++
++	mmio_base = b43_dmacontroller_base(type, engine_index);
++	direct_fifo_rx(dev, type, mmio_base, enable);
++}
++#endif /* CONFIG_B43_PIO */
+diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
+index c0d6b69..20acf88 100644
+--- a/drivers/net/wireless/b43/dma.h
++++ b/drivers/net/wireless/b43/dma.h
+@@ -245,6 +245,9 @@ struct b43_dmaring {
+ 	enum b43_dmatype type;
+ 	/* Boolean. Is this ring stopped at ieee80211 level? */
+ 	bool stopped;
++	/* The QOS priority assigned to this ring. Only used for TX rings.
++	 * This is the mac80211 "queue" value. */
++	u8 queue_prio;
+ 	/* Lock, only used for TX. */
+ 	spinlock_t lock;
+ 	struct b43_wldev *dev;
+@@ -253,7 +256,13 @@ struct b43_dmaring {
+ 	int max_used_slots;
+ 	/* Last time we injected a ring overflow. */
+ 	unsigned long last_injected_overflow;
+-#endif				/* CONFIG_B43_DEBUG */
++	/* Statistics: Number of successfully transmitted packets */
++	u64 nr_succeed_tx_packets;
++	/* Statistics: Number of failed TX packets */
++	u64 nr_failed_tx_packets;
++	/* Statistics: Total number of TX plus all retries. */
++	u64 nr_total_packet_tries;
++#endif /* CONFIG_B43_DEBUG */
+ };
+ 
+ static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset)
+@@ -282,4 +291,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ 
+ void b43_dma_rx(struct b43_dmaring *ring);
+ 
++void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
++			    unsigned int engine_index, bool enable);
++
+ #endif /* B43_DMA_H_ */
+diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
+index 0aac1ff..36a9c42 100644
+--- a/drivers/net/wireless/b43/leds.c
++++ b/drivers/net/wireless/b43/leds.c
+@@ -116,10 +116,7 @@ static void b43_unregister_led(struct b43_led *led)
+ {
+ 	if (!led->dev)
+ 		return;
+-	if (led->dev->suspend_in_progress)
+-		led_classdev_unregister_suspended(&led->led_dev);
+-	else
+-		led_classdev_unregister(&led->led_dev);
++	led_classdev_unregister(&led->led_dev);
+ 	b43_led_turn_off(led->dev, led->index, led->activelow);
+ 	led->dev = NULL;
+ }
+diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
+index c73a75b..4bf8a99 100644
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -46,7 +46,9 @@
+ #include "main.h"
+ #include "debugfs.h"
+ #include "phy.h"
++#include "nphy.h"
+ #include "dma.h"
++#include "pio.h"
+ #include "sysfs.h"
+ #include "xmit.h"
+ #include "lo.h"
+@@ -78,6 +80,15 @@ static int modparam_nohwcrypt;
+ module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
+ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+ 
++int b43_modparam_qos = 1;
++module_param_named(qos, b43_modparam_qos, int, 0444);
++MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
++
++static int modparam_btcoex = 1;
++module_param_named(btcoex, modparam_btcoex, int, 0444);
++MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)");
++
++
+ static const struct ssb_device_id b43_ssb_tbl[] = {
+ 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
+ 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
+@@ -96,25 +107,29 @@ MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
+  * data in there. This data is the same for all devices, so we don't
+  * get concurrency issues */
+ #define RATETAB_ENT(_rateid, _flags) \
+-	{							\
+-		.rate	= B43_RATE_TO_BASE100KBPS(_rateid),	\
+-		.val	= (_rateid),				\
+-		.val2	= (_rateid),				\
+-		.flags	= (_flags),				\
++	{								\
++		.bitrate	= B43_RATE_TO_BASE100KBPS(_rateid),	\
++		.hw_value	= (_rateid),				\
++		.flags		= (_flags),				\
+ 	}
++
++/*
++ * NOTE: When changing this, sync with xmit.c's
++ *	 b43_plcp_get_bitrate_idx_* functions!
++ */
+ static struct ieee80211_rate __b43_ratetable[] = {
+-	RATETAB_ENT(B43_CCK_RATE_1MB, IEEE80211_RATE_CCK),
+-	RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
+-	RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
+-	RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
+-	RATETAB_ENT(B43_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
++	RATETAB_ENT(B43_CCK_RATE_1MB, 0),
++	RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
++	RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
++	RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
++	RATETAB_ENT(B43_OFDM_RATE_6MB, 0),
++	RATETAB_ENT(B43_OFDM_RATE_9MB, 0),
++	RATETAB_ENT(B43_OFDM_RATE_12MB, 0),
++	RATETAB_ENT(B43_OFDM_RATE_18MB, 0),
++	RATETAB_ENT(B43_OFDM_RATE_24MB, 0),
++	RATETAB_ENT(B43_OFDM_RATE_36MB, 0),
++	RATETAB_ENT(B43_OFDM_RATE_48MB, 0),
++	RATETAB_ENT(B43_OFDM_RATE_54MB, 0),
+ };
+ 
+ #define b43_a_ratetable		(__b43_ratetable + 4)
+@@ -124,53 +139,144 @@ static struct ieee80211_rate __b43_ratetable[] = {
+ #define b43_g_ratetable		(__b43_ratetable + 0)
+ #define b43_g_ratetable_size	12
+ 
+-#define CHANTAB_ENT(_chanid, _freq) \
+-	{							\
+-		.chan	= (_chanid),				\
+-		.freq	= (_freq),				\
+-		.val	= (_chanid),				\
+-		.flag	= IEEE80211_CHAN_W_SCAN |		\
+-			  IEEE80211_CHAN_W_ACTIVE_SCAN |	\
+-			  IEEE80211_CHAN_W_IBSS,		\
+-		.power_level	= 0xFF,				\
+-		.antenna_max	= 0xFF,				\
+-	}
++#define CHAN4G(_channel, _freq, _flags) {			\
++	.band			= IEEE80211_BAND_2GHZ,		\
++	.center_freq		= (_freq),			\
++	.hw_value		= (_channel),			\
++	.flags			= (_flags),			\
++	.max_antenna_gain	= 0,				\
++	.max_power		= 30,				\
++}
+ static struct ieee80211_channel b43_2ghz_chantable[] = {
+-	CHANTAB_ENT(1, 2412),
+-	CHANTAB_ENT(2, 2417),
+-	CHANTAB_ENT(3, 2422),
+-	CHANTAB_ENT(4, 2427),
+-	CHANTAB_ENT(5, 2432),
+-	CHANTAB_ENT(6, 2437),
+-	CHANTAB_ENT(7, 2442),
+-	CHANTAB_ENT(8, 2447),
+-	CHANTAB_ENT(9, 2452),
+-	CHANTAB_ENT(10, 2457),
+-	CHANTAB_ENT(11, 2462),
+-	CHANTAB_ENT(12, 2467),
+-	CHANTAB_ENT(13, 2472),
+-	CHANTAB_ENT(14, 2484),
++	CHAN4G(1, 2412, 0),
++	CHAN4G(2, 2417, 0),
++	CHAN4G(3, 2422, 0),
++	CHAN4G(4, 2427, 0),
++	CHAN4G(5, 2432, 0),
++	CHAN4G(6, 2437, 0),
++	CHAN4G(7, 2442, 0),
++	CHAN4G(8, 2447, 0),
++	CHAN4G(9, 2452, 0),
++	CHAN4G(10, 2457, 0),
++	CHAN4G(11, 2462, 0),
++	CHAN4G(12, 2467, 0),
++	CHAN4G(13, 2472, 0),
++	CHAN4G(14, 2484, 0),
+ };
+-#define b43_2ghz_chantable_size	ARRAY_SIZE(b43_2ghz_chantable)
+-
+-#if 0
+-static struct ieee80211_channel b43_5ghz_chantable[] = {
+-	CHANTAB_ENT(36, 5180),
+-	CHANTAB_ENT(40, 5200),
+-	CHANTAB_ENT(44, 5220),
+-	CHANTAB_ENT(48, 5240),
+-	CHANTAB_ENT(52, 5260),
+-	CHANTAB_ENT(56, 5280),
+-	CHANTAB_ENT(60, 5300),
+-	CHANTAB_ENT(64, 5320),
+-	CHANTAB_ENT(149, 5745),
+-	CHANTAB_ENT(153, 5765),
+-	CHANTAB_ENT(157, 5785),
+-	CHANTAB_ENT(161, 5805),
+-	CHANTAB_ENT(165, 5825),
++#undef CHAN4G
++
++#define CHAN5G(_channel, _flags) {				\
++	.band			= IEEE80211_BAND_5GHZ,		\
++	.center_freq		= 5000 + (5 * (_channel)),	\
++	.hw_value		= (_channel),			\
++	.flags			= (_flags),			\
++	.max_antenna_gain	= 0,				\
++	.max_power		= 30,				\
++}
++static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
++	CHAN5G(32, 0),		CHAN5G(34, 0),
++	CHAN5G(36, 0),		CHAN5G(38, 0),
++	CHAN5G(40, 0),		CHAN5G(42, 0),
++	CHAN5G(44, 0),		CHAN5G(46, 0),
++	CHAN5G(48, 0),		CHAN5G(50, 0),
++	CHAN5G(52, 0),		CHAN5G(54, 0),
++	CHAN5G(56, 0),		CHAN5G(58, 0),
++	CHAN5G(60, 0),		CHAN5G(62, 0),
++	CHAN5G(64, 0),		CHAN5G(66, 0),
++	CHAN5G(68, 0),		CHAN5G(70, 0),
++	CHAN5G(72, 0),		CHAN5G(74, 0),
++	CHAN5G(76, 0),		CHAN5G(78, 0),
++	CHAN5G(80, 0),		CHAN5G(82, 0),
++	CHAN5G(84, 0),		CHAN5G(86, 0),
++	CHAN5G(88, 0),		CHAN5G(90, 0),
++	CHAN5G(92, 0),		CHAN5G(94, 0),
++	CHAN5G(96, 0),		CHAN5G(98, 0),
++	CHAN5G(100, 0),		CHAN5G(102, 0),
++	CHAN5G(104, 0),		CHAN5G(106, 0),
++	CHAN5G(108, 0),		CHAN5G(110, 0),
++	CHAN5G(112, 0),		CHAN5G(114, 0),
++	CHAN5G(116, 0),		CHAN5G(118, 0),
++	CHAN5G(120, 0),		CHAN5G(122, 0),
++	CHAN5G(124, 0),		CHAN5G(126, 0),
++	CHAN5G(128, 0),		CHAN5G(130, 0),
++	CHAN5G(132, 0),		CHAN5G(134, 0),
++	CHAN5G(136, 0),		CHAN5G(138, 0),
++	CHAN5G(140, 0),		CHAN5G(142, 0),
++	CHAN5G(144, 0),		CHAN5G(145, 0),
++	CHAN5G(146, 0),		CHAN5G(147, 0),
++	CHAN5G(148, 0),		CHAN5G(149, 0),
++	CHAN5G(150, 0),		CHAN5G(151, 0),
++	CHAN5G(152, 0),		CHAN5G(153, 0),
++	CHAN5G(154, 0),		CHAN5G(155, 0),
++	CHAN5G(156, 0),		CHAN5G(157, 0),
++	CHAN5G(158, 0),		CHAN5G(159, 0),
++	CHAN5G(160, 0),		CHAN5G(161, 0),
++	CHAN5G(162, 0),		CHAN5G(163, 0),
++	CHAN5G(164, 0),		CHAN5G(165, 0),
++	CHAN5G(166, 0),		CHAN5G(168, 0),
++	CHAN5G(170, 0),		CHAN5G(172, 0),
++	CHAN5G(174, 0),		CHAN5G(176, 0),
++	CHAN5G(178, 0),		CHAN5G(180, 0),
++	CHAN5G(182, 0),		CHAN5G(184, 0),
++	CHAN5G(186, 0),		CHAN5G(188, 0),
++	CHAN5G(190, 0),		CHAN5G(192, 0),
++	CHAN5G(194, 0),		CHAN5G(196, 0),
++	CHAN5G(198, 0),		CHAN5G(200, 0),
++	CHAN5G(202, 0),		CHAN5G(204, 0),
++	CHAN5G(206, 0),		CHAN5G(208, 0),
++	CHAN5G(210, 0),		CHAN5G(212, 0),
++	CHAN5G(214, 0),		CHAN5G(216, 0),
++	CHAN5G(218, 0),		CHAN5G(220, 0),
++	CHAN5G(222, 0),		CHAN5G(224, 0),
++	CHAN5G(226, 0),		CHAN5G(228, 0),
++};
++
++static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
++	CHAN5G(34, 0),		CHAN5G(36, 0),
++	CHAN5G(38, 0),		CHAN5G(40, 0),
++	CHAN5G(42, 0),		CHAN5G(44, 0),
++	CHAN5G(46, 0),		CHAN5G(48, 0),
++	CHAN5G(52, 0),		CHAN5G(56, 0),
++	CHAN5G(60, 0),		CHAN5G(64, 0),
++	CHAN5G(100, 0),		CHAN5G(104, 0),
++	CHAN5G(108, 0),		CHAN5G(112, 0),
++	CHAN5G(116, 0),		CHAN5G(120, 0),
++	CHAN5G(124, 0),		CHAN5G(128, 0),
++	CHAN5G(132, 0),		CHAN5G(136, 0),
++	CHAN5G(140, 0),		CHAN5G(149, 0),
++	CHAN5G(153, 0),		CHAN5G(157, 0),
++	CHAN5G(161, 0),		CHAN5G(165, 0),
++	CHAN5G(184, 0),		CHAN5G(188, 0),
++	CHAN5G(192, 0),		CHAN5G(196, 0),
++	CHAN5G(200, 0),		CHAN5G(204, 0),
++	CHAN5G(208, 0),		CHAN5G(212, 0),
++	CHAN5G(216, 0),
++};
++#undef CHAN5G
++
++static struct ieee80211_supported_band b43_band_5GHz_nphy = {
++	.band		= IEEE80211_BAND_5GHZ,
++	.channels	= b43_5ghz_nphy_chantable,
++	.n_channels	= ARRAY_SIZE(b43_5ghz_nphy_chantable),
++	.bitrates	= b43_a_ratetable,
++	.n_bitrates	= b43_a_ratetable_size,
++};
++
++static struct ieee80211_supported_band b43_band_5GHz_aphy = {
++	.band		= IEEE80211_BAND_5GHZ,
++	.channels	= b43_5ghz_aphy_chantable,
++	.n_channels	= ARRAY_SIZE(b43_5ghz_aphy_chantable),
++	.bitrates	= b43_a_ratetable,
++	.n_bitrates	= b43_a_ratetable_size,
++};
++
++static struct ieee80211_supported_band b43_band_2GHz = {
++	.band		= IEEE80211_BAND_2GHZ,
++	.channels	= b43_2ghz_chantable,
++	.n_channels	= ARRAY_SIZE(b43_2ghz_chantable),
++	.bitrates	= b43_g_ratetable,
++	.n_bitrates	= b43_g_ratetable_size,
+ };
+-#define b43_5ghz_chantable_size	ARRAY_SIZE(b43_5ghz_chantable)
+-#endif
+ 
+ static void b43_wireless_core_exit(struct b43_wldev *dev);
+ static int b43_wireless_core_init(struct b43_wldev *dev);
+@@ -370,24 +476,30 @@ out:
+ }
+ 
+ /* Read HostFlags */
+-u32 b43_hf_read(struct b43_wldev * dev)
++u64 b43_hf_read(struct b43_wldev * dev)
+ {
+-	u32 ret;
++	u64 ret;
+ 
+ 	ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI);
+ 	ret <<= 16;
++	ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI);
++	ret <<= 16;
+ 	ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO);
+ 
+ 	return ret;
+ }
+ 
+ /* Write HostFlags */
+-void b43_hf_write(struct b43_wldev *dev, u32 value)
++void b43_hf_write(struct b43_wldev *dev, u64 value)
+ {
+-	b43_shm_write16(dev, B43_SHM_SHARED,
+-			B43_SHM_SH_HOSTFLO, (value & 0x0000FFFF));
+-	b43_shm_write16(dev, B43_SHM_SHARED,
+-			B43_SHM_SH_HOSTFHI, ((value & 0xFFFF0000) >> 16));
++	u16 lo, mi, hi;
++
++	lo = (value & 0x00000000FFFFULL);
++	mi = (value & 0x0000FFFF0000ULL) >> 16;
++	hi = (value & 0xFFFF00000000ULL) >> 32;
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo);
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi);
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
+ }
+ 
+ void b43_tsf_read(struct b43_wldev *dev, u64 * tsf)
+@@ -912,7 +1024,18 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
+ /* Turn the Analog ON/OFF */
+ static void b43_switch_analog(struct b43_wldev *dev, int on)
+ {
+-	b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
++	switch (dev->phy.type) {
++	case B43_PHYTYPE_A:
++	case B43_PHYTYPE_G:
++		b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
++		break;
++	case B43_PHYTYPE_N:
++		b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
++			      on ? 0 : 0x7FFF);
++		break;
++	default:
++		B43_WARN_ON(1);
++	}
+ }
+ 
+ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+@@ -1162,22 +1285,107 @@ static void b43_write_template_common(struct b43_wldev *dev,
+ 			size + sizeof(struct b43_plcp_hdr6));
+ }
+ 
++/* Check if the use of the antenna that ieee80211 told us to
++ * use is possible. This will fall back to DEFAULT.
++ * "antenna_nr" is the antenna identifier we got from ieee80211. */
++u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
++				  u8 antenna_nr)
++{
++	u8 antenna_mask;
++
++	if (antenna_nr == 0) {
++		/* Zero means "use default antenna". That's always OK. */
++		return 0;
++	}
++
++	/* Get the mask of available antennas. */
++	if (dev->phy.gmode)
++		antenna_mask = dev->dev->bus->sprom.ant_available_bg;
++	else
++		antenna_mask = dev->dev->bus->sprom.ant_available_a;
++
++	if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
++		/* This antenna is not available. Fall back to default. */
++		return 0;
++	}
++
++	return antenna_nr;
++}
++
++static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
++{
++	antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
++	switch (antenna) {
++	case 0:		/* default/diversity */
++		return B43_ANTENNA_DEFAULT;
++	case 1:		/* Antenna 0 */
++		return B43_ANTENNA0;
++	case 2:		/* Antenna 1 */
++		return B43_ANTENNA1;
++	case 3:		/* Antenna 2 */
++		return B43_ANTENNA2;
++	case 4:		/* Antenna 3 */
++		return B43_ANTENNA3;
++	default:
++		return B43_ANTENNA_DEFAULT;
++	}
++}
++
++/* Convert a b43 antenna number value to the PHY TX control value. */
++static u16 b43_antenna_to_phyctl(int antenna)
++{
++	switch (antenna) {
++	case B43_ANTENNA0:
++		return B43_TXH_PHY_ANT0;
++	case B43_ANTENNA1:
++		return B43_TXH_PHY_ANT1;
++	case B43_ANTENNA2:
++		return B43_TXH_PHY_ANT2;
++	case B43_ANTENNA3:
++		return B43_TXH_PHY_ANT3;
++	case B43_ANTENNA_AUTO:
++		return B43_TXH_PHY_ANT01AUTO;
++	}
++	B43_WARN_ON(1);
++	return 0;
++}
++
+ static void b43_write_beacon_template(struct b43_wldev *dev,
+ 				      u16 ram_offset,
+-				      u16 shm_size_offset, u8 rate)
++				      u16 shm_size_offset)
+ {
+ 	unsigned int i, len, variable_len;
+ 	const struct ieee80211_mgmt *bcn;
+ 	const u8 *ie;
+ 	bool tim_found = 0;
++	unsigned int rate;
++	u16 ctl;
++	int antenna;
+ 
+ 	bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
+ 	len = min((size_t) dev->wl->current_beacon->len,
+ 		  0x200 - sizeof(struct b43_plcp_hdr6));
++	rate = dev->wl->beacon_txctl.tx_rate->hw_value;
+ 
+ 	b43_write_template_common(dev, (const u8 *)bcn,
+ 				  len, ram_offset, shm_size_offset, rate);
+ 
++	/* Write the PHY TX control parameters. */
++	antenna = b43_antenna_from_ieee80211(dev,
++			dev->wl->beacon_txctl.antenna_sel_tx);
++	antenna = b43_antenna_to_phyctl(antenna);
++	ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
++	/* We can't send beacons with short preamble. Would get PHY errors. */
++	ctl &= ~B43_TXH_PHY_SHORTPRMBL;
++	ctl &= ~B43_TXH_PHY_ANT;
++	ctl &= ~B43_TXH_PHY_ENC;
++	ctl |= antenna;
++	if (b43_is_cck_rate(rate))
++		ctl |= B43_TXH_PHY_ENC_CCK;
++	else
++		ctl |= B43_TXH_PHY_ENC_OFDM;
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
++
+ 	/* Find the position of the TIM and the DTIM_period value
+ 	 * and write them to SHM. */
+ 	ie = bcn->u.beacon.variable;
+@@ -1218,21 +1426,23 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
+ 		b43warn(dev->wl, "Did not find a valid TIM IE in "
+ 			"the beacon template packet. AP or IBSS operation "
+ 			"may be broken.\n");
+-	}
++	} else
++		b43dbg(dev->wl, "Updated beacon template\n");
+ }
+ 
+ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
+-				      u16 shm_offset, u16 size, u8 rate)
++				      u16 shm_offset, u16 size,
++				      struct ieee80211_rate *rate)
+ {
+ 	struct b43_plcp_hdr4 plcp;
+ 	u32 tmp;
+ 	__le16 dur;
+ 
+ 	plcp.data = 0;
+-	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
++	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
+ 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
+ 					       dev->wl->vif, size,
+-					       B43_RATE_TO_BASE100KBPS(rate));
++					       rate);
+ 	/* Write PLCP in two parts and timing for packet transfer */
+ 	tmp = le32_to_cpu(plcp.data);
+ 	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
+@@ -1247,7 +1457,8 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
+  * 3) Stripping TIM
+  */
+ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
+-					  u16 *dest_size, u8 rate)
++					  u16 *dest_size,
++					  struct ieee80211_rate *rate)
+ {
+ 	const u8 *src_data;
+ 	u8 *dest_data;
+@@ -1292,7 +1503,7 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
+ 					 IEEE80211_STYPE_PROBE_RESP);
+ 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
+ 					       dev->wl->vif, *dest_size,
+-					       B43_RATE_TO_BASE100KBPS(rate));
++					       rate);
+ 	hdr->duration_id = dur;
+ 
+ 	return dest_data;
+@@ -1300,7 +1511,8 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
+ 
+ static void b43_write_probe_resp_template(struct b43_wldev *dev,
+ 					  u16 ram_offset,
+-					  u16 shm_size_offset, u8 rate)
++					  u16 shm_size_offset,
++					  struct ieee80211_rate *rate)
+ {
+ 	const u8 *probe_resp_data;
+ 	u16 size;
+@@ -1313,20 +1525,89 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
+ 	/* Looks like PLCP headers plus packet timings are stored for
+ 	 * all possible basic rates
+ 	 */
+-	b43_write_probe_resp_plcp(dev, 0x31A, size, B43_CCK_RATE_1MB);
+-	b43_write_probe_resp_plcp(dev, 0x32C, size, B43_CCK_RATE_2MB);
+-	b43_write_probe_resp_plcp(dev, 0x33E, size, B43_CCK_RATE_5MB);
+-	b43_write_probe_resp_plcp(dev, 0x350, size, B43_CCK_RATE_11MB);
++	b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]);
++	b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]);
++	b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]);
++	b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]);
+ 
+ 	size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));
+ 	b43_write_template_common(dev, probe_resp_data,
+-				  size, ram_offset, shm_size_offset, rate);
++				  size, ram_offset, shm_size_offset,
++				  rate->hw_value);
+ 	kfree(probe_resp_data);
+ }
+ 
++static void handle_irq_beacon(struct b43_wldev *dev)
++{
++	struct b43_wl *wl = dev->wl;
++	u32 cmd, beacon0_valid, beacon1_valid;
++
++	if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
++		return;
++
++	/* This is the bottom half of the asynchronous beacon update. */
++
++	/* Ignore interrupt in the future. */
++	dev->irq_savedstate &= ~B43_IRQ_BEACON;
++
++	cmd = b43_read32(dev, B43_MMIO_MACCMD);
++	beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
++	beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID);
++
++	/* Schedule interrupt manually, if busy. */
++	if (beacon0_valid && beacon1_valid) {
++		b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
++		dev->irq_savedstate |= B43_IRQ_BEACON;
++		return;
++	}
++
++	if (!beacon0_valid) {
++		if (!wl->beacon0_uploaded) {
++			b43_write_beacon_template(dev, 0x68, 0x18);
++			b43_write_probe_resp_template(dev, 0x268, 0x4A,
++						      &__b43_ratetable[3]);
++			wl->beacon0_uploaded = 1;
++		}
++		cmd = b43_read32(dev, B43_MMIO_MACCMD);
++		cmd |= B43_MACCMD_BEACON0_VALID;
++		b43_write32(dev, B43_MMIO_MACCMD, cmd);
++	} else if (!beacon1_valid) {
++		if (!wl->beacon1_uploaded) {
++			b43_write_beacon_template(dev, 0x468, 0x1A);
++			wl->beacon1_uploaded = 1;
++		}
++		cmd = b43_read32(dev, B43_MMIO_MACCMD);
++		cmd |= B43_MACCMD_BEACON1_VALID;
++		b43_write32(dev, B43_MMIO_MACCMD, cmd);
++	}
++}
++
++static void b43_beacon_update_trigger_work(struct work_struct *work)
++{
++	struct b43_wl *wl = container_of(work, struct b43_wl,
++					 beacon_update_trigger);
++	struct b43_wldev *dev;
++
++	mutex_lock(&wl->mutex);
++	dev = wl->current_dev;
++	if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
++		spin_lock_irq(&wl->irq_lock);
++		/* update beacon right away or defer to irq */
++		dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
++		handle_irq_beacon(dev);
++		/* The handler might have updated the IRQ mask. */
++		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK,
++			    dev->irq_savedstate);
++		mmiowb();
++		spin_unlock_irq(&wl->irq_lock);
++	}
++	mutex_unlock(&wl->mutex);
++}
++
+ /* Asynchronously update the packet templates in template RAM.
+  * Locking: Requires wl->irq_lock to be locked. */
+-static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
++static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon,
++				 const struct ieee80211_tx_control *txctl)
+ {
+ 	/* This is the top half of the ansynchronous beacon update.
+ 	 * The bottom half is the beacon IRQ.
+@@ -1337,8 +1618,10 @@ static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
+ 	if (wl->current_beacon)
+ 		dev_kfree_skb_any(wl->current_beacon);
+ 	wl->current_beacon = beacon;
++	memcpy(&wl->beacon_txctl, txctl, sizeof(wl->beacon_txctl));
+ 	wl->beacon0_uploaded = 0;
+ 	wl->beacon1_uploaded = 0;
++	queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
+ }
+ 
+ static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len)
+@@ -1364,44 +1647,14 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
+ {
+ 	b43_time_lock(dev);
+ 	if (dev->dev->id.revision >= 3) {
+-		b43_write32(dev, 0x188, (beacon_int << 16));
++		b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
++		b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
+ 	} else {
+ 		b43_write16(dev, 0x606, (beacon_int >> 6));
+ 		b43_write16(dev, 0x610, beacon_int);
+ 	}
+ 	b43_time_unlock(dev);
+-}
+-
+-static void handle_irq_beacon(struct b43_wldev *dev)
+-{
+-	struct b43_wl *wl = dev->wl;
+-	u32 cmd;
+-
+-	if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
+-		return;
+-
+-	/* This is the bottom half of the asynchronous beacon update. */
+-
+-	cmd = b43_read32(dev, B43_MMIO_MACCMD);
+-	if (!(cmd & B43_MACCMD_BEACON0_VALID)) {
+-		if (!wl->beacon0_uploaded) {
+-			b43_write_beacon_template(dev, 0x68, 0x18,
+-						  B43_CCK_RATE_1MB);
+-			b43_write_probe_resp_template(dev, 0x268, 0x4A,
+-						      B43_CCK_RATE_11MB);
+-			wl->beacon0_uploaded = 1;
+-		}
+-		cmd |= B43_MACCMD_BEACON0_VALID;
+-	}
+-	if (!(cmd & B43_MACCMD_BEACON1_VALID)) {
+-		if (!wl->beacon1_uploaded) {
+-			b43_write_beacon_template(dev, 0x468, 0x1A,
+-						  B43_CCK_RATE_1MB);
+-			wl->beacon1_uploaded = 1;
+-		}
+-		cmd |= B43_MACCMD_BEACON1_VALID;
+-	}
+-	b43_write32(dev, B43_MMIO_MACCMD, cmd);
++	b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
+ }
+ 
+ static void handle_irq_ucode_debug(struct b43_wldev *dev)
+@@ -1483,12 +1736,15 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
+ 		handle_irq_noise(dev);
+ 
+ 	/* Check the DMA reason registers for received data. */
+-	if (dma_reason[0] & B43_DMAIRQ_RX_DONE)
+-		b43_dma_rx(dev->dma.rx_ring0);
+-	if (dma_reason[3] & B43_DMAIRQ_RX_DONE)
+-		b43_dma_rx(dev->dma.rx_ring3);
++	if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
++		if (b43_using_pio_transfers(dev))
++			b43_pio_rx(dev->pio.rx_queue);
++		else
++			b43_dma_rx(dev->dma.rx_ring);
++	}
+ 	B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);
+ 	B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);
++	B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE);
+ 	B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
+ 	B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
+ 
+@@ -2045,7 +2301,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
+ }
+ 
+ /* http://bcm-specs.sipsolutions.net/EnableMac */
+-void b43_mac_enable(struct b43_wldev *dev)
++static void b43_mac_enable(struct b43_wldev *dev)
+ {
+ 	dev->mac_suspended--;
+ 	B43_WARN_ON(dev->mac_suspended < 0);
+@@ -2068,7 +2324,7 @@ void b43_mac_enable(struct b43_wldev *dev)
+ }
+ 
+ /* http://bcm-specs.sipsolutions.net/SuspendMAC */
+-void b43_mac_suspend(struct b43_wldev *dev)
++static void b43_mac_suspend(struct b43_wldev *dev)
+ {
+ 	int i;
+ 	u32 tmp;
+@@ -2091,6 +2347,13 @@ void b43_mac_suspend(struct b43_wldev *dev)
+ 			    & ~B43_MACCTL_ENABLED);
+ 		/* force pci to flush the write */
+ 		b43_read32(dev, B43_MMIO_MACCTL);
++		for (i = 35; i; i--) {
++			tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
++			if (tmp & B43_IRQ_MAC_SUSPENDED)
++				goto out;
++			udelay(10);
++		}
++		/* Hm, it seems this will take some time. Use msleep(). */
+ 		for (i = 40; i; i--) {
+ 			tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
+ 			if (tmp & B43_IRQ_MAC_SUSPENDED)
+@@ -2196,38 +2459,28 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
+ 	}
+ }
+ 
++/* Set the default values for the PHY TX Control Words. */
++static void b43_set_phytxctl_defaults(struct b43_wldev *dev)
++{
++	u16 ctl = 0;
++
++	ctl |= B43_TXH_PHY_ENC_CCK;
++	ctl |= B43_TXH_PHY_ANT01AUTO;
++	ctl |= B43_TXH_PHY_TXPWR;
++
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, ctl);
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, ctl);
++}
++
+ /* Set the TX-Antenna for management frames sent by firmware. */
+ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
+ {
+-	u16 ant = 0;
++	u16 ant;
+ 	u16 tmp;
+ 
+-	switch (antenna) {
+-	case B43_ANTENNA0:
+-		ant |= B43_TXH_PHY_ANT0;
+-		break;
+-	case B43_ANTENNA1:
+-		ant |= B43_TXH_PHY_ANT1;
+-		break;
+-	case B43_ANTENNA2:
+-		ant |= B43_TXH_PHY_ANT2;
+-		break;
+-	case B43_ANTENNA3:
+-		ant |= B43_TXH_PHY_ANT3;
+-		break;
+-	case B43_ANTENNA_AUTO:
+-		ant |= B43_TXH_PHY_ANT01AUTO;
+-		break;
+-	default:
+-		B43_WARN_ON(1);
+-	}
+-
+-	/* FIXME We also need to set the other flags of the PHY control field somewhere. */
++	ant = b43_antenna_to_phyctl(antenna);
+ 
+-	/* For Beacons */
+-	tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
+-	tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
+-	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, tmp);
+ 	/* For ACK/CTS */
+ 	tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL);
+ 	tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
+@@ -2555,10 +2808,10 @@ static int b43_rng_read(struct hwrng *rng, u32 * data)
+ 	return (sizeof(u16));
+ }
+ 
+-static void b43_rng_exit(struct b43_wl *wl, bool suspended)
++static void b43_rng_exit(struct b43_wl *wl)
+ {
+ 	if (wl->rng_initialized)
+-		__hwrng_unregister(&wl->rng, suspended);
++		hwrng_unregister(&wl->rng);
+ }
+ 
+ static int b43_rng_init(struct b43_wl *wl)
+@@ -2589,22 +2842,199 @@ static int b43_op_tx(struct ieee80211_hw *hw,
+ 	struct b43_wldev *dev = wl->current_dev;
+ 	int err = -ENODEV;
+ 
++	if (unlikely(skb->len < 2 + 2 + 6)) {
++		/* Too short, this can't be a valid frame. */
++		return -EINVAL;
++	}
++	B43_WARN_ON(skb_shinfo(skb)->nr_frags);
++
+ 	if (unlikely(!dev))
+ 		goto out;
+ 	if (unlikely(b43_status(dev) < B43_STAT_STARTED))
+ 		goto out;
+-	/* DMA-TX is done without a global lock. */
+-	err = b43_dma_tx(dev, skb, ctl);
++	/* TX is done without a global lock. */
++	if (b43_using_pio_transfers(dev))
++		err = b43_pio_tx(dev, skb, ctl);
++	else
++		err = b43_dma_tx(dev, skb, ctl);
+ out:
+ 	if (unlikely(err))
+ 		return NETDEV_TX_BUSY;
+ 	return NETDEV_TX_OK;
+ }
+ 
++/* Locking: wl->irq_lock */
++static void b43_qos_params_upload(struct b43_wldev *dev,
++				  const struct ieee80211_tx_queue_params *p,
++				  u16 shm_offset)
++{
++	u16 params[B43_NR_QOSPARAMS];
++	int cw_min, cw_max, aifs, bslots, tmp;
++	unsigned int i;
++
++	const u16 aCWmin = 0x0001;
++	const u16 aCWmax = 0x03FF;
++
++	/* Calculate the default values for the parameters, if needed. */
++	switch (shm_offset) {
++	case B43_QOS_VOICE:
++		aifs = (p->aifs == -1) ? 2 : p->aifs;
++		cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 4 - 1) : p->cw_min;
++		cw_max = (p->cw_max == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_max;
++		break;
++	case B43_QOS_VIDEO:
++		aifs = (p->aifs == -1) ? 2 : p->aifs;
++		cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_min;
++		cw_max = (p->cw_max == 0) ? aCWmin : p->cw_max;
++		break;
++	case B43_QOS_BESTEFFORT:
++		aifs = (p->aifs == -1) ? 3 : p->aifs;
++		cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
++		cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
++		break;
++	case B43_QOS_BACKGROUND:
++		aifs = (p->aifs == -1) ? 7 : p->aifs;
++		cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
++		cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
++		break;
++	default:
++		B43_WARN_ON(1);
++		return;
++	}
++	if (cw_min <= 0)
++		cw_min = aCWmin;
++	if (cw_max <= 0)
++		cw_max = aCWmin;
++	bslots = b43_read16(dev, B43_MMIO_RNG) % cw_min;
++
++	memset(&params, 0, sizeof(params));
++
++	params[B43_QOSPARAM_TXOP] = p->txop * 32;
++	params[B43_QOSPARAM_CWMIN] = cw_min;
++	params[B43_QOSPARAM_CWMAX] = cw_max;
++	params[B43_QOSPARAM_CWCUR] = cw_min;
++	params[B43_QOSPARAM_AIFS] = aifs;
++	params[B43_QOSPARAM_BSLOTS] = bslots;
++	params[B43_QOSPARAM_REGGAP] = bslots + aifs;
++
++	for (i = 0; i < ARRAY_SIZE(params); i++) {
++		if (i == B43_QOSPARAM_STATUS) {
++			tmp = b43_shm_read16(dev, B43_SHM_SHARED,
++					     shm_offset + (i * 2));
++			/* Mark the parameters as updated. */
++			tmp |= 0x100;
++			b43_shm_write16(dev, B43_SHM_SHARED,
++					shm_offset + (i * 2),
++					tmp);
++		} else {
++			b43_shm_write16(dev, B43_SHM_SHARED,
++					shm_offset + (i * 2),
++					params[i]);
++		}
++	}
++}
++
++/* Update the QOS parameters in hardware. */
++static void b43_qos_update(struct b43_wldev *dev)
++{
++	struct b43_wl *wl = dev->wl;
++	struct b43_qos_params *params;
++	unsigned long flags;
++	unsigned int i;
++
++	/* Mapping of mac80211 queues to b43 SHM offsets. */
++	static const u16 qos_shm_offsets[] = {
++		[0] = B43_QOS_VOICE,
++		[1] = B43_QOS_VIDEO,
++		[2] = B43_QOS_BESTEFFORT,
++		[3] = B43_QOS_BACKGROUND,
++	};
++	BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params));
++
++	b43_mac_suspend(dev);
++	spin_lock_irqsave(&wl->irq_lock, flags);
++
++	for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
++		params = &(wl->qos_params[i]);
++		if (params->need_hw_update) {
++			b43_qos_params_upload(dev, &(params->p),
++					      qos_shm_offsets[i]);
++			params->need_hw_update = 0;
++		}
++	}
++
++	spin_unlock_irqrestore(&wl->irq_lock, flags);
++	b43_mac_enable(dev);
++}
++
++static void b43_qos_clear(struct b43_wl *wl)
++{
++	struct b43_qos_params *params;
++	unsigned int i;
++
++	for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
++		params = &(wl->qos_params[i]);
++
++		memset(&(params->p), 0, sizeof(params->p));
++		params->p.aifs = -1;
++		params->need_hw_update = 1;
++	}
++}
++
++/* Initialize the core's QOS capabilities */
++static void b43_qos_init(struct b43_wldev *dev)
++{
++	struct b43_wl *wl = dev->wl;
++	unsigned int i;
++
++	/* Upload the current QOS parameters. */
++	for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++)
++		wl->qos_params[i].need_hw_update = 1;
++	b43_qos_update(dev);
++
++	/* Enable QOS support. */
++	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
++	b43_write16(dev, B43_MMIO_IFSCTL,
++		    b43_read16(dev, B43_MMIO_IFSCTL)
++		    | B43_MMIO_IFSCTL_USE_EDCF);
++}
++
++static void b43_qos_update_work(struct work_struct *work)
++{
++	struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work);
++	struct b43_wldev *dev;
++
++	mutex_lock(&wl->mutex);
++	dev = wl->current_dev;
++	if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED)))
++		b43_qos_update(dev);
++	mutex_unlock(&wl->mutex);
++}
++
+ static int b43_op_conf_tx(struct ieee80211_hw *hw,
+-			  int queue,
++			  int _queue,
+ 			  const struct ieee80211_tx_queue_params *params)
+ {
++	struct b43_wl *wl = hw_to_b43_wl(hw);
++	unsigned long flags;
++	unsigned int queue = (unsigned int)_queue;
++	struct b43_qos_params *p;
++
++	if (queue >= ARRAY_SIZE(wl->qos_params)) {
++		/* Queue not available or don't support setting
++		 * params on this queue. Return success to not
++		 * confuse mac80211. */
++		return 0;
++	}
++
++	spin_lock_irqsave(&wl->irq_lock, flags);
++	p = &(wl->qos_params[queue]);
++	memcpy(&(p->p), params, sizeof(p->p));
++	p->need_hw_update = 1;
++	spin_unlock_irqrestore(&wl->irq_lock, flags);
++
++	queue_work(hw->workqueue, &wl->qos_update_work);
++
+ 	return 0;
+ }
+ 
+@@ -2620,7 +3050,10 @@ static int b43_op_get_tx_stats(struct ieee80211_hw *hw,
+ 		goto out;
+ 	spin_lock_irqsave(&wl->irq_lock, flags);
+ 	if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
+-		b43_dma_get_tx_stats(dev, stats);
++		if (b43_using_pio_transfers(dev))
++			b43_pio_get_tx_stats(dev, stats);
++		else
++			b43_dma_get_tx_stats(dev, stats);
+ 		err = 0;
+ 	}
+ 	spin_unlock_irqrestore(&wl->irq_lock, flags);
+@@ -2641,45 +3074,6 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
+ 	return 0;
+ }
+ 
+-static const char *phymode_to_string(unsigned int phymode)
+-{
+-	switch (phymode) {
+-	case B43_PHYMODE_A:
+-		return "A";
+-	case B43_PHYMODE_B:
+-		return "B";
+-	case B43_PHYMODE_G:
+-		return "G";
+-	default:
+-		B43_WARN_ON(1);
+-	}
+-	return "";
+-}
+-
+-static int find_wldev_for_phymode(struct b43_wl *wl,
+-				  unsigned int phymode,
+-				  struct b43_wldev **dev, bool * gmode)
+-{
+-	struct b43_wldev *d;
+-
+-	list_for_each_entry(d, &wl->devlist, list) {
+-		if (d->phy.possible_phymodes & phymode) {
+-			/* Ok, this device supports the PHY-mode.
+-			 * Now figure out how the gmode bit has to be
+-			 * set to support it. */
+-			if (phymode == B43_PHYMODE_A)
+-				*gmode = 0;
+-			else
+-				*gmode = 1;
+-			*dev = d;
+-
+-			return 0;
+-		}
+-	}
+-
+-	return -ESRCH;
+-}
+-
+ static void b43_put_phy_into_reset(struct b43_wldev *dev)
+ {
+ 	struct ssb_device *sdev = dev->dev;
+@@ -2699,28 +3093,64 @@ static void b43_put_phy_into_reset(struct b43_wldev *dev)
+ 	msleep(1);
+ }
+ 
++static const char * band_to_string(enum ieee80211_band band)
++{
++	switch (band) {
++	case IEEE80211_BAND_5GHZ:
++		return "5";
++	case IEEE80211_BAND_2GHZ:
++		return "2.4";
++	default:
++		break;
++	}
++	B43_WARN_ON(1);
++	return "";
++}
++
+ /* Expects wl->mutex locked */
+-static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
++static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
+ {
+-	struct b43_wldev *up_dev;
++	struct b43_wldev *up_dev = NULL;
+ 	struct b43_wldev *down_dev;
++	struct b43_wldev *d;
+ 	int err;
+-	bool gmode = 0;
++	bool gmode;
+ 	int prev_status;
+ 
+-	err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode);
+-	if (err) {
+-		b43err(wl, "Could not find a device for %s-PHY mode\n",
+-		       phymode_to_string(new_mode));
+-		return err;
++	/* Find a device and PHY which supports the band. */
++	list_for_each_entry(d, &wl->devlist, list) {
++		switch (chan->band) {
++		case IEEE80211_BAND_5GHZ:
++			if (d->phy.supports_5ghz) {
++				up_dev = d;
++				gmode = 0;
++			}
++			break;
++		case IEEE80211_BAND_2GHZ:
++			if (d->phy.supports_2ghz) {
++				up_dev = d;
++				gmode = 1;
++			}
++			break;
++		default:
++			B43_WARN_ON(1);
++			return -EINVAL;
++		}
++		if (up_dev)
++			break;
++	}
++	if (!up_dev) {
++		b43err(wl, "Could not find a device for %s-GHz band operation\n",
++		       band_to_string(chan->band));
++		return -ENODEV;
+ 	}
+ 	if ((up_dev == wl->current_dev) &&
+ 	    (!!wl->current_dev->phy.gmode == !!gmode)) {
+ 		/* This device is already running. */
+ 		return 0;
+ 	}
+-	b43dbg(wl, "Reconfiguring PHYmode to %s-PHY\n",
+-	       phymode_to_string(new_mode));
++	b43dbg(wl, "Switching to %s-GHz band\n",
++	       band_to_string(chan->band));
+ 	down_dev = wl->current_dev;
+ 
+ 	prev_status = b43_status(down_dev);
+@@ -2742,8 +3172,8 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
+ 		err = b43_wireless_core_init(up_dev);
+ 		if (err) {
+ 			b43err(wl, "Fatal: Could not initialize device for "
+-			       "newly selected %s-PHY mode\n",
+-			       phymode_to_string(new_mode));
++			       "selected %s-GHz band\n",
++			       band_to_string(chan->band));
+ 			goto init_failure;
+ 		}
+ 	}
+@@ -2751,8 +3181,8 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
+ 		err = b43_wireless_core_start(up_dev);
+ 		if (err) {
+ 			b43err(wl, "Fatal: Coult not start device for "
+-			       "newly selected %s-PHY mode\n",
+-			       phymode_to_string(new_mode));
++			       "selected %s-GHz band\n",
++			       band_to_string(chan->band));
+ 			b43_wireless_core_exit(up_dev);
+ 			goto init_failure;
+ 		}
+@@ -2762,86 +3192,26 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
+ 	wl->current_dev = up_dev;
+ 
+ 	return 0;
+-      init_failure:
++init_failure:
+ 	/* Whoops, failed to init the new core. No core is operating now. */
+ 	wl->current_dev = NULL;
+ 	return err;
+ }
+ 
+-/* Check if the use of the antenna that ieee80211 told us to
+- * use is possible. This will fall back to DEFAULT.
+- * "antenna_nr" is the antenna identifier we got from ieee80211. */
+-u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
+-				  u8 antenna_nr)
+-{
+-	u8 antenna_mask;
+-
+-	if (antenna_nr == 0) {
+-		/* Zero means "use default antenna". That's always OK. */
+-		return 0;
+-	}
+-
+-	/* Get the mask of available antennas. */
+-	if (dev->phy.gmode)
+-		antenna_mask = dev->dev->bus->sprom.ant_available_bg;
+-	else
+-		antenna_mask = dev->dev->bus->sprom.ant_available_a;
+-
+-	if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
+-		/* This antenna is not available. Fall back to default. */
+-		return 0;
+-	}
+-
+-	return antenna_nr;
+-}
+-
+-static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
+-{
+-	antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
+-	switch (antenna) {
+-	case 0:		/* default/diversity */
+-		return B43_ANTENNA_DEFAULT;
+-	case 1:		/* Antenna 0 */
+-		return B43_ANTENNA0;
+-	case 2:		/* Antenna 1 */
+-		return B43_ANTENNA1;
+-	case 3:		/* Antenna 2 */
+-		return B43_ANTENNA2;
+-	case 4:		/* Antenna 3 */
+-		return B43_ANTENNA3;
+-	default:
+-		return B43_ANTENNA_DEFAULT;
+-	}
+-}
+-
+ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+ {
+ 	struct b43_wl *wl = hw_to_b43_wl(hw);
+ 	struct b43_wldev *dev;
+ 	struct b43_phy *phy;
+ 	unsigned long flags;
+-	unsigned int new_phymode = 0xFFFF;
+ 	int antenna;
+ 	int err = 0;
+ 	u32 savedirqs;
+ 
+ 	mutex_lock(&wl->mutex);
+ 
+-	/* Switch the PHY mode (if necessary). */
+-	switch (conf->phymode) {
+-	case MODE_IEEE80211A:
+-		new_phymode = B43_PHYMODE_A;
+-		break;
+-	case MODE_IEEE80211B:
+-		new_phymode = B43_PHYMODE_B;
+-		break;
+-	case MODE_IEEE80211G:
+-		new_phymode = B43_PHYMODE_G;
+-		break;
+-	default:
+-		B43_WARN_ON(1);
+-	}
+-	err = b43_switch_phymode(wl, new_phymode);
++	/* Switch the band (if necessary). This might change the active core. */
++	err = b43_switch_band(wl, conf->channel);
+ 	if (err)
+ 		goto out_unlock_mutex;
+ 	dev = wl->current_dev;
+@@ -2861,8 +3231,8 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+ 
+ 	/* Switch to the requested channel.
+ 	 * The firmware takes care of races with the TX handler. */
+-	if (conf->channel_val != phy->channel)
+-		b43_radio_selectchannel(dev, conf->channel_val, 0);
++	if (conf->channel->hw_value != phy->channel)
++		b43_radio_selectchannel(dev, conf->channel->hw_value, 0);
+ 
+ 	/* Enable/Disable ShortSlot timing. */
+ 	if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
+@@ -3075,8 +3445,10 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
+ 		if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
+ 			B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
+ 			b43_set_ssid(dev, conf->ssid, conf->ssid_len);
+-			if (conf->beacon)
+-				b43_update_templates(wl, conf->beacon);
++			if (conf->beacon) {
++				b43_update_templates(wl, conf->beacon,
++						     conf->beacon_control);
++			}
+ 		}
+ 		b43_write_mac_bssid_templates(dev);
+ 	}
+@@ -3106,6 +3478,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
+ 
+ 	b43_set_status(dev, B43_STAT_INITIALIZED);
+ 
++	b43_pio_stop(dev);
+ 	mutex_unlock(&wl->mutex);
+ 	/* Must unlock as it would otherwise deadlock. No races here.
+ 	 * Cancel the possibly running self-rearming periodic work. */
+@@ -3337,8 +3710,10 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
+ static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
+ {
+ 	struct ssb_sprom *sprom = &dev->dev->bus->sprom;
+-	u32 hf;
++	u64 hf;
+ 
++	if (!modparam_btcoex)
++		return;
+ 	if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST))
+ 		return;
+ 	if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode)
+@@ -3350,11 +3725,13 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
+ 	else
+ 		hf |= B43_HF_BTCOEX;
+ 	b43_hf_write(dev, hf);
+-	//TODO
+ }
+ 
+ static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
+-{				//TODO
++{
++	if (!modparam_btcoex)
++		return;
++	//TODO
+ }
+ 
+ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
+@@ -3400,6 +3777,41 @@ static void b43_set_retry_limits(struct b43_wldev *dev,
+ 			long_retry);
+ }
+ 
++static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
++{
++	u16 pu_delay;
++
++	/* The time value is in microseconds. */
++	if (dev->phy.type == B43_PHYTYPE_A)
++		pu_delay = 3700;
++	else
++		pu_delay = 1050;
++	if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
++		pu_delay = 500;
++	if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
++		pu_delay = max(pu_delay, (u16)2400);
++
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SPUWKUP, pu_delay);
++}
++
++/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
++static void b43_set_pretbtt(struct b43_wldev *dev)
++{
++	u16 pretbtt;
++
++	/* The time value is in microseconds. */
++	if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) {
++		pretbtt = 2;
++	} else {
++		if (dev->phy.type == B43_PHYTYPE_A)
++			pretbtt = 120;
++		else
++			pretbtt = 250;
++	}
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRETBTT, pretbtt);
++	b43_write16(dev, B43_MMIO_TSF_CFP_PRETBTT, pretbtt);
++}
++
+ /* Shutdown a wireless core */
+ /* Locking: wl->mutex */
+ static void b43_wireless_core_exit(struct b43_wldev *dev)
+@@ -3420,9 +3832,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
+ 
+ 	if (!dev->suspend_in_progress) {
+ 		b43_leds_exit(dev);
+-		b43_rng_exit(dev->wl, false);
++		b43_rng_exit(dev->wl);
+ 	}
+ 	b43_dma_free(dev);
++	b43_pio_free(dev);
+ 	b43_chip_exit(dev);
+ 	b43_radio_turn_off(dev, 1);
+ 	b43_switch_analog(dev, 0);
+@@ -3447,7 +3860,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+ 	struct ssb_sprom *sprom = &bus->sprom;
+ 	struct b43_phy *phy = &dev->phy;
+ 	int err;
+-	u32 hf, tmp;
++	u64 hf;
++	u32 tmp;
+ 
+ 	B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
+ 
+@@ -3510,6 +3924,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+ 	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 1);
+ 
+ 	b43_rate_memory_init(dev);
++	b43_set_phytxctl_defaults(dev);
+ 
+ 	/* Minimum Contention Window */
+ 	if (phy->type == B43_PHYTYPE_B) {
+@@ -3520,18 +3935,17 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+ 	/* Maximum Contention Window */
+ 	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
+ 
+-	err = b43_dma_init(dev);
++	if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) {
++		dev->__using_pio_transfers = 1;
++		err = b43_pio_init(dev);
++	} else {
++		dev->__using_pio_transfers = 0;
++		err = b43_dma_init(dev);
++	}
+ 	if (err)
+ 		goto err_chip_exit;
+ 	b43_qos_init(dev);
+-
+-//FIXME
+-#if 1
+-	b43_write16(dev, 0x0612, 0x0050);
+-	b43_shm_write16(dev, B43_SHM_SHARED, 0x0416, 0x0050);
+-	b43_shm_write16(dev, B43_SHM_SHARED, 0x0414, 0x01F4);
+-#endif
+-
++	b43_set_synth_pu_delay(dev, 1);
+ 	b43_bluetooth_coext_enable(dev);
+ 
+ 	ssb_bus_powerup(bus, 1);	/* Enable dynamic PCTL */
+@@ -3591,6 +4005,8 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
+ 
+ 	spin_lock_irqsave(&wl->irq_lock, flags);
+ 	b43_adjust_opmode(dev);
++	b43_set_pretbtt(dev);
++	b43_set_synth_pu_delay(dev, 0);
+ 	b43_upload_card_macaddress(dev);
+ 	spin_unlock_irqrestore(&wl->irq_lock, flags);
+ 
+@@ -3642,6 +4058,7 @@ static int b43_op_start(struct ieee80211_hw *hw)
+ 	memset(wl->mac_addr, 0, ETH_ALEN);
+ 	wl->filter_flags = 0;
+ 	wl->radiotap_enabled = 0;
++	b43_qos_clear(wl);
+ 
+ 	/* First register RFkill.
+ 	 * LEDs that are registered later depend on it. */
+@@ -3683,6 +4100,8 @@ static void b43_op_stop(struct ieee80211_hw *hw)
+ 	struct b43_wldev *dev = wl->current_dev;
+ 
+ 	b43_rfkill_exit(dev);
++	cancel_work_sync(&(wl->qos_update_work));
++	cancel_work_sync(&(wl->beacon_update_trigger));
+ 
+ 	mutex_lock(&wl->mutex);
+ 	if (b43_status(dev) >= B43_STAT_STARTED)
+@@ -3716,16 +4135,17 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
+ 	struct b43_wl *wl = hw_to_b43_wl(hw);
+ 	struct sk_buff *beacon;
+ 	unsigned long flags;
++	struct ieee80211_tx_control txctl;
+ 
+ 	/* We could modify the existing beacon and set the aid bit in
+ 	 * the TIM field, but that would probably require resizing and
+ 	 * moving of data within the beacon template.
+ 	 * Simply request a new beacon and let mac80211 do the hard work. */
+-	beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
++	beacon = ieee80211_beacon_get(hw, wl->vif, &txctl);
+ 	if (unlikely(!beacon))
+ 		return -ENOMEM;
+ 	spin_lock_irqsave(&wl->irq_lock, flags);
+-	b43_update_templates(wl, beacon);
++	b43_update_templates(wl, beacon, &txctl);
+ 	spin_unlock_irqrestore(&wl->irq_lock, flags);
+ 
+ 	return 0;
+@@ -3739,12 +4159,22 @@ static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&wl->irq_lock, flags);
+-	b43_update_templates(wl, beacon);
++	b43_update_templates(wl, beacon, ctl);
+ 	spin_unlock_irqrestore(&wl->irq_lock, flags);
+ 
+ 	return 0;
+ }
+ 
++static void b43_op_sta_notify(struct ieee80211_hw *hw,
++			      struct ieee80211_vif *vif,
++			      enum sta_notify_cmd notify_cmd,
++			      const u8 *addr)
++{
++	struct b43_wl *wl = hw_to_b43_wl(hw);
++
++	B43_WARN_ON(!vif || wl->vif != vif);
++}
++
+ static const struct ieee80211_ops b43_hw_ops = {
+ 	.tx			= b43_op_tx,
+ 	.conf_tx		= b43_op_conf_tx,
+@@ -3761,6 +4191,7 @@ static const struct ieee80211_ops b43_hw_ops = {
+ 	.set_retry_limit	= b43_op_set_retry_limit,
+ 	.set_tim		= b43_op_beacon_set_tim,
+ 	.beacon_update		= b43_op_ibss_beacon_update,
++	.sta_notify		= b43_op_sta_notify,
+ };
+ 
+ /* Hard-reset the chip. Do not call this directly.
+@@ -3804,31 +4235,23 @@ static void b43_chip_reset(struct work_struct *work)
+ 		b43info(wl, "Controller restarted\n");
+ }
+ 
+-static int b43_setup_modes(struct b43_wldev *dev,
++static int b43_setup_bands(struct b43_wldev *dev,
+ 			   bool have_2ghz_phy, bool have_5ghz_phy)
+ {
+ 	struct ieee80211_hw *hw = dev->wl->hw;
+-	struct ieee80211_hw_mode *mode;
+-	struct b43_phy *phy = &dev->phy;
+-	int err;
+ 
+-	/* XXX: This function will go away soon, when mac80211
+-	 *      band stuff is rewritten. So this is just a hack.
+-	 *      For now we always claim GPHY mode, as there is no
+-	 *      support for NPHY and APHY in the device, yet.
+-	 *      This assumption is OK, as any B, N or A PHY will already
+-	 *      have died a horrible sanity check death earlier. */
+-
+-	mode = &phy->hwmodes[0];
+-	mode->mode = MODE_IEEE80211G;
+-	mode->num_channels = b43_2ghz_chantable_size;
+-	mode->channels = b43_2ghz_chantable;
+-	mode->num_rates = b43_g_ratetable_size;
+-	mode->rates = b43_g_ratetable;
+-	err = ieee80211_register_hwmode(hw, mode);
+-	if (err)
+-		return err;
+-	phy->possible_phymodes |= B43_PHYMODE_G;
++	if (have_2ghz_phy)
++		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz;
++	if (dev->phy.type == B43_PHYTYPE_N) {
++		if (have_5ghz_phy)
++			hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy;
++	} else {
++		if (have_5ghz_phy)
++			hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
++	}
++
++	dev->phy.supports_2ghz = have_2ghz_phy;
++	dev->phy.supports_5ghz = have_5ghz_phy;
+ 
+ 	return 0;
+ }
+@@ -3910,7 +4333,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
+ 	err = b43_validate_chipaccess(dev);
+ 	if (err)
+ 		goto err_powerdown;
+-	err = b43_setup_modes(dev, have_2ghz_phy, have_5ghz_phy);
++	err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy);
+ 	if (err)
+ 		goto err_powerdown;
+ 
+@@ -4000,8 +4423,16 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
+ 	return err;
+ }
+ 
++#define IS_PDEV(pdev, _vendor, _device, _subvendor, _subdevice)		( \
++	(pdev->vendor == PCI_VENDOR_ID_##_vendor) &&			\
++	(pdev->device == _device) &&					\
++	(pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) &&	\
++	(pdev->subsystem_device == _subdevice)				)
++
+ static void b43_sprom_fixup(struct ssb_bus *bus)
+ {
++	struct pci_dev *pdev;
++
+ 	/* boardflags workarounds */
+ 	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
+ 	    bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
+@@ -4009,6 +4440,13 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
+ 	if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
+ 	    bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
+ 		bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
++	if (bus->bustype == SSB_BUSTYPE_PCI) {
++		pdev = bus->host_pci;
++		if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) ||
++		    IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) ||
++		    IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013))
++			bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST;
++	}
+ }
+ 
+ static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
+@@ -4040,7 +4478,7 @@ static int b43_wireless_init(struct ssb_device *dev)
+ 	hw->max_signal = 100;
+ 	hw->max_rssi = -110;
+ 	hw->max_noise = -110;
+-	hw->queues = 1;		/* FIXME: hardware has more queues */
++	hw->queues = b43_modparam_qos ? 4 : 1;
+ 	SET_IEEE80211_DEV(hw, dev->dev);
+ 	if (is_valid_ether_addr(sprom->et1mac))
+ 		SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
+@@ -4056,6 +4494,8 @@ static int b43_wireless_init(struct ssb_device *dev)
+ 	spin_lock_init(&wl->shm_lock);
+ 	mutex_init(&wl->mutex);
+ 	INIT_LIST_HEAD(&wl->devlist);
++	INIT_WORK(&wl->qos_update_work, b43_qos_update_work);
++	INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
+ 
+ 	ssb_set_devtypedata(dev, wl);
+ 	b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
+@@ -4173,7 +4613,7 @@ static int b43_resume(struct ssb_device *dev)
+ 		err = b43_wireless_core_start(wldev);
+ 		if (err) {
+ 			b43_leds_exit(wldev);
+-			b43_rng_exit(wldev->wl, true);
++			b43_rng_exit(wldev->wl);
+ 			b43_wireless_core_exit(wldev);
+ 			b43err(wl, "Resume failed at core start\n");
+ 			goto out;
+diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
+index 2d52d9d..5230aec 100644
+--- a/drivers/net/wireless/b43/main.h
++++ b/drivers/net/wireless/b43/main.h
+@@ -38,6 +38,10 @@
+ /* Magic helper macro to pad structures. Ignore those above. It's magic. */
+ #define PAD_BYTES(nr_bytes)		P4D_BYTES( __LINE__ , (nr_bytes))
+ 
++
++extern int b43_modparam_qos;
++
++
+ /* Lightweight function to convert a frequency (in Mhz) to a channel number. */
+ static inline u8 b43_freq_to_channel_5ghz(int freq)
+ {
+@@ -95,16 +99,13 @@ u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
+ void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
+ void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
+ 
+-u32 b43_hf_read(struct b43_wldev *dev);
+-void b43_hf_write(struct b43_wldev *dev, u32 value);
++u64 b43_hf_read(struct b43_wldev *dev);
++void b43_hf_write(struct b43_wldev *dev, u64 value);
+ 
+ void b43_dummy_transmission(struct b43_wldev *dev);
+ 
+ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
+ 
+-void b43_mac_suspend(struct b43_wldev *dev);
+-void b43_mac_enable(struct b43_wldev *dev);
+-
+ void b43_controller_restart(struct b43_wldev *dev, const char *reason);
+ 
+ #define B43_PS_ENABLED	(1 << 0)	/* Force enable hardware power saving */
+diff --git a/drivers/net/wireless/b43/nphy.c b/drivers/net/wireless/b43/nphy.c
+index 705131e..8695eb2 100644
+--- a/drivers/net/wireless/b43/nphy.c
++++ b/drivers/net/wireless/b43/nphy.c
+@@ -240,7 +240,6 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
+ 
+ 	b43_phy_set(dev, B43_NPHY_IQFLIP,
+ 		    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+-	//FIXME the following condition is different in the specs.
+ 	if (1 /* FIXME band is 2.4GHz */) {
+ 		b43_phy_set(dev, B43_NPHY_CLASSCTL,
+ 			    B43_NPHY_CLASSCTL_CCKEN);
+diff --git a/drivers/net/wireless/b43/nphy.h b/drivers/net/wireless/b43/nphy.h
+index 5d95118..faf46b9 100644
+--- a/drivers/net/wireless/b43/nphy.h
++++ b/drivers/net/wireless/b43/nphy.h
+@@ -919,6 +919,10 @@
+ 
+ struct b43_wldev;
+ 
++
++#ifdef CONFIG_B43_NPHY
++/* N-PHY support enabled */
++
+ int b43_phy_initn(struct b43_wldev *dev);
+ 
+ void b43_nphy_radio_turn_on(struct b43_wldev *dev);
+@@ -929,4 +933,40 @@ int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel);
+ void b43_nphy_xmitpower(struct b43_wldev *dev);
+ void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna);
+ 
++
++#else /* CONFIG_B43_NPHY */
++/* N-PHY support disabled */
++
++
++static inline
++int b43_phy_initn(struct b43_wldev *dev)
++{
++	return -EOPNOTSUPP;
++}
++
++static inline
++void b43_nphy_radio_turn_on(struct b43_wldev *dev)
++{
++}
++static inline
++void b43_nphy_radio_turn_off(struct b43_wldev *dev)
++{
++}
++
++static inline
++int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
++{
++	return -ENOSYS;
++}
++
++static inline
++void b43_nphy_xmitpower(struct b43_wldev *dev)
++{
++}
++static inline
++void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
++{
++}
++
++#endif /* CONFIG_B43_NPHY */
+ #endif /* B43_NPHY_H_ */
+diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
+index 371e4a1..b8aa163 100644
+--- a/drivers/net/wireless/b43/pcmcia.c
++++ b/drivers/net/wireless/b43/pcmcia.c
+@@ -43,14 +43,16 @@ MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl);
+ #ifdef CONFIG_PM
+ static int b43_pcmcia_suspend(struct pcmcia_device *dev)
+ {
+-	//TODO
+-	return 0;
++	struct ssb_bus *ssb = dev->priv;
++
++	return ssb_bus_suspend(ssb);
+ }
+ 
+ static int b43_pcmcia_resume(struct pcmcia_device *dev)
+ {
+-	//TODO
+-	return 0;
++	struct ssb_bus *ssb = dev->priv;
++
++	return ssb_bus_resume(ssb);
+ }
+ #else /* CONFIG_PM */
+ # define b43_pcmcia_suspend		NULL
+diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c
+index 575c543..de024dc 100644
+--- a/drivers/net/wireless/b43/phy.c
++++ b/drivers/net/wireless/b43/phy.c
+@@ -2043,7 +2043,7 @@ int b43_phy_init(struct b43_wldev *dev)
+ void b43_set_rx_antenna(struct b43_wldev *dev, int antenna)
+ {
+ 	struct b43_phy *phy = &dev->phy;
+-	u32 hf;
++	u64 hf;
+ 	u16 tmp;
+ 	int autodiv = 0;
+ 
+diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
+new file mode 100644
+index 0000000..fcacafb
+--- /dev/null
++++ b/drivers/net/wireless/b43/pio.c
+@@ -0,0 +1,842 @@
++/*
++
++  Broadcom B43 wireless driver
++
++  PIO data transfer
++
++  Copyright (c) 2005-2008 Michael Buesch <mb at 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 "pio.h"
++#include "dma.h"
++#include "main.h"
++#include "xmit.h"
++
++#include <linux/delay.h>
++
++
++static void b43_pio_rx_work(struct work_struct *work);
++
++
++static u16 generate_cookie(struct b43_pio_txqueue *q,
++			   struct b43_pio_txpacket *pack)
++{
++	u16 cookie;
++
++	/* Use the upper 4 bits of the cookie as
++	 * PIO controller ID and store the packet index number
++	 * in the lower 12 bits.
++	 * Note that the cookie must never be 0, as this
++	 * is a special value used in RX path.
++	 * It can also not be 0xFFFF because that is special
++	 * for multicast frames.
++	 */
++	cookie = (((u16)q->index + 1) << 12);
++	cookie |= pack->index;
++
++	return cookie;
++}
++
++static
++struct b43_pio_txqueue * parse_cookie(struct b43_wldev *dev,
++				      u16 cookie,
++				      struct b43_pio_txpacket **pack)
++{
++	struct b43_pio *pio = &dev->pio;
++	struct b43_pio_txqueue *q = NULL;
++	unsigned int pack_index;
++
++	switch (cookie & 0xF000) {
++	case 0x1000:
++		q = pio->tx_queue_AC_BK;
++		break;
++	case 0x2000:
++		q = pio->tx_queue_AC_BE;
++		break;
++	case 0x3000:
++		q = pio->tx_queue_AC_VI;
++		break;
++	case 0x4000:
++		q = pio->tx_queue_AC_VO;
++		break;
++	case 0x5000:
++		q = pio->tx_queue_mcast;
++		break;
++	}
++	if (B43_WARN_ON(!q))
++		return NULL;
++	pack_index = (cookie & 0x0FFF);
++	if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets)))
++		return NULL;
++	*pack = &q->packets[pack_index];
++
++	return q;
++}
++
++static u16 index_to_pioqueue_base(struct b43_wldev *dev,
++				  unsigned int index)
++{
++	static const u16 bases[] = {
++		B43_MMIO_PIO_BASE0,
++		B43_MMIO_PIO_BASE1,
++		B43_MMIO_PIO_BASE2,
++		B43_MMIO_PIO_BASE3,
++		B43_MMIO_PIO_BASE4,
++		B43_MMIO_PIO_BASE5,
++		B43_MMIO_PIO_BASE6,
++		B43_MMIO_PIO_BASE7,
++	};
++	static const u16 bases_rev11[] = {
++		B43_MMIO_PIO11_BASE0,
++		B43_MMIO_PIO11_BASE1,
++		B43_MMIO_PIO11_BASE2,
++		B43_MMIO_PIO11_BASE3,
++		B43_MMIO_PIO11_BASE4,
++		B43_MMIO_PIO11_BASE5,
++	};
++
++	if (dev->dev->id.revision >= 11) {
++		B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
++		return bases_rev11[index];
++	}
++	B43_WARN_ON(index >= ARRAY_SIZE(bases));
++	return bases[index];
++}
++
++static u16 pio_txqueue_offset(struct b43_wldev *dev)
++{
++	if (dev->dev->id.revision >= 11)
++		return 0x18;
++	return 0;
++}
++
++static u16 pio_rxqueue_offset(struct b43_wldev *dev)
++{
++	if (dev->dev->id.revision >= 11)
++		return 0x38;
++	return 8;
++}
++
++static struct b43_pio_txqueue * b43_setup_pioqueue_tx(struct b43_wldev *dev,
++						      unsigned int index)
++{
++	struct b43_pio_txqueue *q;
++	struct b43_pio_txpacket *p;
++	unsigned int i;
++
++	q = kzalloc(sizeof(*q), GFP_KERNEL);
++	if (!q)
++		return NULL;
++	spin_lock_init(&q->lock);
++	q->dev = dev;
++	q->rev = dev->dev->id.revision;
++	q->mmio_base = index_to_pioqueue_base(dev, index) +
++		       pio_txqueue_offset(dev);
++	q->index = index;
++
++	q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS;
++	if (q->rev >= 8) {
++		q->buffer_size = 1920; //FIXME this constant is wrong.
++	} else {
++		q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE);
++		q->buffer_size -= 80;
++	}
++
++	INIT_LIST_HEAD(&q->packets_list);
++	for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
++		p = &(q->packets[i]);
++		INIT_LIST_HEAD(&p->list);
++		p->index = i;
++		p->queue = q;
++		list_add(&p->list, &q->packets_list);
++	}
++
++	return q;
++}
++
++static struct b43_pio_rxqueue * b43_setup_pioqueue_rx(struct b43_wldev *dev,
++						      unsigned int index)
++{
++	struct b43_pio_rxqueue *q;
++
++	q = kzalloc(sizeof(*q), GFP_KERNEL);
++	if (!q)
++		return NULL;
++	spin_lock_init(&q->lock);
++	q->dev = dev;
++	q->rev = dev->dev->id.revision;
++	q->mmio_base = index_to_pioqueue_base(dev, index) +
++		       pio_rxqueue_offset(dev);
++	INIT_WORK(&q->rx_work, b43_pio_rx_work);
++
++	/* Enable Direct FIFO RX (PIO) on the engine. */
++	b43_dma_direct_fifo_rx(dev, index, 1);
++
++	return q;
++}
++
++static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
++{
++	struct b43_pio_txpacket *pack;
++	unsigned int i;
++
++	for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
++		pack = &(q->packets[i]);
++		if (pack->skb) {
++			dev_kfree_skb_any(pack->skb);
++			pack->skb = NULL;
++		}
++	}
++}
++
++static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q,
++				    const char *name)
++{
++	if (!q)
++		return;
++	b43_pio_cancel_tx_packets(q);
++	kfree(q);
++}
++
++static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q,
++				    const char *name)
++{
++	if (!q)
++		return;
++	kfree(q);
++}
++
++#define destroy_queue_tx(pio, queue) do {				\
++	b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue));	\
++	(pio)->queue = NULL;						\
++  } while (0)
++
++#define destroy_queue_rx(pio, queue) do {				\
++	b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue));	\
++	(pio)->queue = NULL;						\
++  } while (0)
++
++void b43_pio_free(struct b43_wldev *dev)
++{
++	struct b43_pio *pio;
++
++	if (!b43_using_pio_transfers(dev))
++		return;
++	pio = &dev->pio;
++
++	destroy_queue_rx(pio, rx_queue);
++	destroy_queue_tx(pio, tx_queue_mcast);
++	destroy_queue_tx(pio, tx_queue_AC_VO);
++	destroy_queue_tx(pio, tx_queue_AC_VI);
++	destroy_queue_tx(pio, tx_queue_AC_BE);
++	destroy_queue_tx(pio, tx_queue_AC_BK);
++}
++
++void b43_pio_stop(struct b43_wldev *dev)
++{
++	if (!b43_using_pio_transfers(dev))
++		return;
++	cancel_work_sync(&dev->pio.rx_queue->rx_work);
++}
++
++int b43_pio_init(struct b43_wldev *dev)
++{
++	struct b43_pio *pio = &dev->pio;
++	int err = -ENOMEM;
++
++	b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
++		    & ~B43_MACCTL_BE);
++	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0);
++
++	pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0);
++	if (!pio->tx_queue_AC_BK)
++		goto out;
++
++	pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1);
++	if (!pio->tx_queue_AC_BE)
++		goto err_destroy_bk;
++
++	pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2);
++	if (!pio->tx_queue_AC_VI)
++		goto err_destroy_be;
++
++	pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3);
++	if (!pio->tx_queue_AC_VO)
++		goto err_destroy_vi;
++
++	pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4);
++	if (!pio->tx_queue_mcast)
++		goto err_destroy_vo;
++
++	pio->rx_queue = b43_setup_pioqueue_rx(dev, 0);
++	if (!pio->rx_queue)
++		goto err_destroy_mcast;
++
++	b43dbg(dev->wl, "PIO initialized\n");
++	err = 0;
++out:
++	return err;
++
++err_destroy_mcast:
++	destroy_queue_tx(pio, tx_queue_mcast);
++err_destroy_vo:
++	destroy_queue_tx(pio, tx_queue_AC_VO);
++err_destroy_vi:
++	destroy_queue_tx(pio, tx_queue_AC_VI);
++err_destroy_be:
++	destroy_queue_tx(pio, tx_queue_AC_BE);
++err_destroy_bk:
++	destroy_queue_tx(pio, tx_queue_AC_BK);
++	return err;
++}
++
++/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
++static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev,
++							 u8 queue_prio)
++{
++	struct b43_pio_txqueue *q;
++
++	if (b43_modparam_qos) {
++		/* 0 = highest priority */
++		switch (queue_prio) {
++		default:
++			B43_WARN_ON(1);
++			/* fallthrough */
++		case 0:
++			q = dev->pio.tx_queue_AC_VO;
++			break;
++		case 1:
++			q = dev->pio.tx_queue_AC_VI;
++			break;
++		case 2:
++			q = dev->pio.tx_queue_AC_BE;
++			break;
++		case 3:
++			q = dev->pio.tx_queue_AC_BK;
++			break;
++		}
++	} else
++		q = dev->pio.tx_queue_AC_BE;
++
++	return q;
++}
++
++static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
++				u16 ctl,
++				const void *_data,
++				unsigned int data_len)
++{
++	struct b43_wldev *dev = q->dev;
++	const u8 *data = _data;
++
++	ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
++	b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
++
++	ssb_block_write(dev->dev, data, (data_len & ~1),
++			q->mmio_base + B43_PIO_TXDATA,
++			sizeof(u16));
++	if (data_len & 1) {
++		/* Write the last byte. */
++		ctl &= ~B43_PIO_TXCTL_WRITEHI;
++		b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
++		b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
++	}
++
++	return ctl;
++}
++
++static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
++				     const u8 *hdr, unsigned int hdrlen)
++{
++	struct b43_pio_txqueue *q = pack->queue;
++	const char *frame = pack->skb->data;
++	unsigned int frame_len = pack->skb->len;
++	u16 ctl;
++
++	ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
++	ctl |= B43_PIO_TXCTL_FREADY;
++	ctl &= ~B43_PIO_TXCTL_EOF;
++
++	/* Transfer the header data. */
++	ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen);
++	/* Transfer the frame data. */
++	ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
++
++	ctl |= B43_PIO_TXCTL_EOF;
++	b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
++}
++
++static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
++				u32 ctl,
++				const void *_data,
++				unsigned int data_len)
++{
++	struct b43_wldev *dev = q->dev;
++	const u8 *data = _data;
++
++	ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
++	       B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
++	b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
++
++	ssb_block_write(dev->dev, data, (data_len & ~3),
++			q->mmio_base + B43_PIO8_TXDATA,
++			sizeof(u32));
++	if (data_len & 3) {
++		u32 value = 0;
++
++		/* Write the last few bytes. */
++		ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
++			 B43_PIO8_TXCTL_24_31);
++		data = &(data[data_len - 1]);
++		switch (data_len & 3) {
++		case 3:
++			ctl |= B43_PIO8_TXCTL_16_23;
++			value |= (u32)(*data) << 16;
++			data--;
++		case 2:
++			ctl |= B43_PIO8_TXCTL_8_15;
++			value |= (u32)(*data) << 8;
++			data--;
++		case 1:
++			value |= (u32)(*data);
++		}
++		b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
++		b43_piotx_write32(q, B43_PIO8_TXDATA, value);
++	}
++
++	return ctl;
++}
++
++static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
++				     const u8 *hdr, unsigned int hdrlen)
++{
++	struct b43_pio_txqueue *q = pack->queue;
++	const char *frame = pack->skb->data;
++	unsigned int frame_len = pack->skb->len;
++	u32 ctl;
++
++	ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
++	ctl |= B43_PIO8_TXCTL_FREADY;
++	ctl &= ~B43_PIO8_TXCTL_EOF;
++
++	/* Transfer the header data. */
++	ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen);
++	/* Transfer the frame data. */
++	ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
++
++	ctl |= B43_PIO8_TXCTL_EOF;
++	b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
++}
++
++static int pio_tx_frame(struct b43_pio_txqueue *q,
++			struct sk_buff *skb,
++			struct ieee80211_tx_control *ctl)
++{
++	struct b43_pio_txpacket *pack;
++	struct b43_txhdr txhdr;
++	u16 cookie;
++	int err;
++	unsigned int hdrlen;
++
++	B43_WARN_ON(list_empty(&q->packets_list));
++	pack = list_entry(q->packets_list.next,
++			  struct b43_pio_txpacket, list);
++	memset(&pack->txstat, 0, sizeof(pack->txstat));
++	memcpy(&pack->txstat.control, ctl, sizeof(*ctl));
++
++	cookie = generate_cookie(q, pack);
++	hdrlen = b43_txhdr_size(q->dev);
++	err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data,
++				 skb->len, ctl, cookie);
++	if (err)
++		return err;
++
++	if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
++		/* Tell the firmware about the cookie of the last
++		 * mcast frame, so it can clear the more-data bit in it. */
++		b43_shm_write16(q->dev, B43_SHM_SHARED,
++				B43_SHM_SH_MCASTCOOKIE, cookie);
++	}
++
++	pack->skb = skb;
++	if (q->rev >= 8)
++		pio_tx_frame_4byte_queue(pack, (const u8 *)&txhdr, hdrlen);
++	else
++		pio_tx_frame_2byte_queue(pack, (const u8 *)&txhdr, hdrlen);
++
++	/* Remove it from the list of available packet slots.
++	 * It will be put back when we receive the status report. */
++	list_del(&pack->list);
++
++	/* Update the queue statistics. */
++	q->buffer_used += roundup(skb->len + hdrlen, 4);
++	q->free_packet_slots -= 1;
++
++	return 0;
++}
++
++int b43_pio_tx(struct b43_wldev *dev,
++	       struct sk_buff *skb, struct ieee80211_tx_control *ctl)
++{
++	struct b43_pio_txqueue *q;
++	struct ieee80211_hdr *hdr;
++	unsigned long flags;
++	unsigned int hdrlen, total_len;
++	int err = 0;
++
++	hdr = (struct ieee80211_hdr *)skb->data;
++	if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
++		/* The multicast queue will be sent after the DTIM. */
++		q = dev->pio.tx_queue_mcast;
++		/* Set the frame More-Data bit. Ucode will clear it
++		 * for us on the last frame. */
++		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
++	} else {
++		/* Decide by priority where to put this frame. */
++		q = select_queue_by_priority(dev, ctl->queue);
++	}
++
++	spin_lock_irqsave(&q->lock, flags);
++
++	hdrlen = b43_txhdr_size(dev);
++	total_len = roundup(skb->len + hdrlen, 4);
++
++	if (unlikely(total_len > q->buffer_size)) {
++		err = -ENOBUFS;
++		b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
++		goto out_unlock;
++	}
++	if (unlikely(q->free_packet_slots == 0)) {
++		err = -ENOBUFS;
++		b43warn(dev->wl, "PIO: TX packet overflow.\n");
++		goto out_unlock;
++	}
++	B43_WARN_ON(q->buffer_used > q->buffer_size);
++
++	if (total_len > (q->buffer_size - q->buffer_used)) {
++		/* Not enough memory on the queue. */
++		err = -EBUSY;
++		ieee80211_stop_queue(dev->wl->hw, ctl->queue);
++		q->stopped = 1;
++		goto out_unlock;
++	}
++
++	/* Assign the queue number to the ring (if not already done before)
++	 * so TX status handling can use it. The mac80211-queue to b43-queue
++	 * mapping is static, so we don't need to store it per frame. */
++	q->queue_prio = ctl->queue;
++
++	err = pio_tx_frame(q, skb, ctl);
++	if (unlikely(err == -ENOKEY)) {
++		/* Drop this packet, as we don't have the encryption key
++		 * anymore and must not transmit it unencrypted. */
++		dev_kfree_skb_any(skb);
++		err = 0;
++		goto out_unlock;
++	}
++	if (unlikely(err)) {
++		b43err(dev->wl, "PIO transmission failure\n");
++		goto out_unlock;
++	}
++	q->nr_tx_packets++;
++
++	B43_WARN_ON(q->buffer_used > q->buffer_size);
++	if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
++	    (q->free_packet_slots == 0)) {
++		/* The queue is full. */
++		ieee80211_stop_queue(dev->wl->hw, ctl->queue);
++		q->stopped = 1;
++	}
++
++out_unlock:
++	spin_unlock_irqrestore(&q->lock, flags);
++
++	return err;
++}
++
++/* Called with IRQs disabled. */
++void b43_pio_handle_txstatus(struct b43_wldev *dev,
++			     const struct b43_txstatus *status)
++{
++	struct b43_pio_txqueue *q;
++	struct b43_pio_txpacket *pack = NULL;
++	unsigned int total_len;
++
++	q = parse_cookie(dev, status->cookie, &pack);
++	if (unlikely(!q))
++		return;
++	B43_WARN_ON(!pack);
++
++	spin_lock(&q->lock); /* IRQs are already disabled. */
++
++	b43_fill_txstatus_report(&(pack->txstat), status);
++
++	total_len = pack->skb->len + b43_txhdr_size(dev);
++	total_len = roundup(total_len, 4);
++	q->buffer_used -= total_len;
++	q->free_packet_slots += 1;
++
++	ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb,
++				    &(pack->txstat));
++	pack->skb = NULL;
++	list_add(&pack->list, &q->packets_list);
++
++	if (q->stopped) {
++		ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
++		q->stopped = 0;
++	}
++
++	spin_unlock(&q->lock);
++}
++
++void b43_pio_get_tx_stats(struct b43_wldev *dev,
++			  struct ieee80211_tx_queue_stats *stats)
++{
++	const int nr_queues = dev->wl->hw->queues;
++	struct b43_pio_txqueue *q;
++	struct ieee80211_tx_queue_stats_data *data;
++	unsigned long flags;
++	int i;
++
++	for (i = 0; i < nr_queues; i++) {
++		data = &(stats->data[i]);
++		q = select_queue_by_priority(dev, i);
++
++		spin_lock_irqsave(&q->lock, flags);
++		data->len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots;
++		data->limit = B43_PIO_MAX_NR_TXPACKETS;
++		data->count = q->nr_tx_packets;
++		spin_unlock_irqrestore(&q->lock, flags);
++	}
++}
++
++/* Returns whether we should fetch another frame. */
++static bool pio_rx_frame(struct b43_pio_rxqueue *q)
++{
++	struct b43_wldev *dev = q->dev;
++	struct b43_rxhdr_fw4 rxhdr;
++	u16 len;
++	u32 macstat;
++	unsigned int i, padding;
++	struct sk_buff *skb;
++	const char *err_msg = NULL;
++
++	memset(&rxhdr, 0, sizeof(rxhdr));
++
++	/* Check if we have data and wait for it to get ready. */
++	if (q->rev >= 8) {
++		u32 ctl;
++
++		ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
++		if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
++			return 0;
++		b43_piorx_write32(q, B43_PIO8_RXCTL,
++				  B43_PIO8_RXCTL_FRAMERDY);
++		for (i = 0; i < 10; i++) {
++			ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
++			if (ctl & B43_PIO8_RXCTL_DATARDY)
++				goto data_ready;
++			udelay(10);
++		}
++	} else {
++		u16 ctl;
++
++		ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
++		if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
++			return 0;
++		b43_piorx_write16(q, B43_PIO_RXCTL,
++				  B43_PIO_RXCTL_FRAMERDY);
++		for (i = 0; i < 10; i++) {
++			ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
++			if (ctl & B43_PIO_RXCTL_DATARDY)
++				goto data_ready;
++			udelay(10);
++		}
++	}
++	b43dbg(q->dev->wl, "PIO RX timed out\n");
++	return 1;
++data_ready:
++
++	/* Get the preamble (RX header) */
++	if (q->rev >= 8) {
++		ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
++			       q->mmio_base + B43_PIO8_RXDATA,
++			       sizeof(u32));
++	} else {
++		ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
++			       q->mmio_base + B43_PIO_RXDATA,
++			       sizeof(u16));
++	}
++	/* Sanity checks. */
++	len = le16_to_cpu(rxhdr.frame_len);
++	if (unlikely(len > 0x700)) {
++		err_msg = "len > 0x700";
++		goto rx_error;
++	}
++	if (unlikely(len == 0)) {
++		err_msg = "len == 0";
++		goto rx_error;
++	}
++
++	macstat = le32_to_cpu(rxhdr.mac_status);
++	if (macstat & B43_RX_MAC_FCSERR) {
++		if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
++			/* Drop frames with failed FCS. */
++			err_msg = "Frame FCS error";
++			goto rx_error;
++		}
++	}
++
++	/* We always pad 2 bytes, as that's what upstream code expects
++	 * due to the RX-header being 30 bytes. In case the frame is
++	 * unaligned, we pad another 2 bytes. */
++	padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
++	skb = dev_alloc_skb(len + padding + 2);
++	if (unlikely(!skb)) {
++		err_msg = "Out of memory";
++		goto rx_error;
++	}
++	skb_reserve(skb, 2);
++	skb_put(skb, len + padding);
++	if (q->rev >= 8) {
++		ssb_block_read(dev->dev, skb->data + padding, (len & ~3),
++			       q->mmio_base + B43_PIO8_RXDATA,
++			       sizeof(u32));
++		if (len & 3) {
++			u32 value;
++			char *data;
++
++			/* Read the last few bytes. */
++			value = b43_piorx_read32(q, B43_PIO8_RXDATA);
++			data = &(skb->data[len + padding - 1]);
++			switch (len & 3) {
++			case 3:
++				*data = (value >> 16);
++				data--;
++			case 2:
++				*data = (value >> 8);
++				data--;
++			case 1:
++				*data = value;
++			}
++		}
++	} else {
++		ssb_block_read(dev->dev, skb->data + padding, (len & ~1),
++			       q->mmio_base + B43_PIO_RXDATA,
++			       sizeof(u16));
++		if (len & 1) {
++			u16 value;
++
++			/* Read the last byte. */
++			value = b43_piorx_read16(q, B43_PIO_RXDATA);
++			skb->data[len + padding - 1] = value;
++		}
++	}
++
++	b43_rx(q->dev, skb, &rxhdr);
++
++	return 1;
++
++rx_error:
++	if (err_msg)
++		b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
++	b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
++	return 1;
++}
++
++/* RX workqueue. We can sleep, yay! */
++static void b43_pio_rx_work(struct work_struct *work)
++{
++	struct b43_pio_rxqueue *q = container_of(work, struct b43_pio_rxqueue,
++						 rx_work);
++	unsigned int budget = 50;
++	bool stop;
++
++	do {
++		spin_lock_irq(&q->lock);
++		stop = (pio_rx_frame(q) == 0);
++		spin_unlock_irq(&q->lock);
++		cond_resched();
++		if (stop)
++			break;
++	} while (--budget);
++}
++
++/* Called with IRQs disabled. */
++void b43_pio_rx(struct b43_pio_rxqueue *q)
++{
++	/* Due to latency issues we must run the RX path in
++	 * a workqueue to be able to schedule between packets. */
++	queue_work(q->dev->wl->hw->workqueue, &q->rx_work);
++}
++
++static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&q->lock, flags);
++	if (q->rev >= 8) {
++		b43_piotx_write32(q, B43_PIO8_TXCTL,
++				  b43_piotx_read32(q, B43_PIO8_TXCTL)
++				  | B43_PIO8_TXCTL_SUSPREQ);
++	} else {
++		b43_piotx_write16(q, B43_PIO_TXCTL,
++				  b43_piotx_read16(q, B43_PIO_TXCTL)
++				  | B43_PIO_TXCTL_SUSPREQ);
++	}
++	spin_unlock_irqrestore(&q->lock, flags);
++}
++
++static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&q->lock, flags);
++	if (q->rev >= 8) {
++		b43_piotx_write32(q, B43_PIO8_TXCTL,
++				  b43_piotx_read32(q, B43_PIO8_TXCTL)
++				  & ~B43_PIO8_TXCTL_SUSPREQ);
++	} else {
++		b43_piotx_write16(q, B43_PIO_TXCTL,
++				  b43_piotx_read16(q, B43_PIO_TXCTL)
++				  & ~B43_PIO_TXCTL_SUSPREQ);
++	}
++	spin_unlock_irqrestore(&q->lock, flags);
++}
++
++void b43_pio_tx_suspend(struct b43_wldev *dev)
++{
++	b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
++	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK);
++	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE);
++	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI);
++	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO);
++	b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast);
++}
++
++void b43_pio_tx_resume(struct b43_wldev *dev)
++{
++	b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast);
++	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO);
++	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI);
++	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE);
++	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK);
++	b43_power_saving_ctl_bits(dev, 0);
++}
+diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h
+new file mode 100644
+index 0000000..e2ec676
+--- /dev/null
++++ b/drivers/net/wireless/b43/pio.h
+@@ -0,0 +1,220 @@
++#ifndef B43_PIO_H_
++#define B43_PIO_H_
++
++#include "b43.h"
++
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/list.h>
++#include <linux/skbuff.h>
++
++
++/*** Registers for PIO queues up to revision 7. ***/
++/* TX queue. */
++#define B43_PIO_TXCTL			0x00
++#define  B43_PIO_TXCTL_WRITELO		0x0001
++#define  B43_PIO_TXCTL_WRITEHI		0x0002
++#define  B43_PIO_TXCTL_EOF		0x0004
++#define  B43_PIO_TXCTL_FREADY		0x0008
++#define  B43_PIO_TXCTL_FLUSHREQ		0x0020
++#define  B43_PIO_TXCTL_FLUSHPEND	0x0040
++#define  B43_PIO_TXCTL_SUSPREQ		0x0080
++#define  B43_PIO_TXCTL_QSUSP		0x0100
++#define  B43_PIO_TXCTL_COMMCNT		0xFC00
++#define  B43_PIO_TXCTL_COMMCNT_SHIFT	10
++#define B43_PIO_TXDATA			0x02
++#define B43_PIO_TXQBUFSIZE		0x04
++/* RX queue. */
++#define B43_PIO_RXCTL			0x00
++#define  B43_PIO_RXCTL_FRAMERDY		0x0001
++#define  B43_PIO_RXCTL_DATARDY		0x0002
++#define B43_PIO_RXDATA			0x02
++
++/*** Registers for PIO queues revision 8 and later. ***/
++/* TX queue */
++#define B43_PIO8_TXCTL			0x00
++#define  B43_PIO8_TXCTL_0_7		0x00000001
++#define  B43_PIO8_TXCTL_8_15		0x00000002
++#define  B43_PIO8_TXCTL_16_23		0x00000004
++#define  B43_PIO8_TXCTL_24_31		0x00000008
++#define  B43_PIO8_TXCTL_EOF		0x00000010
++#define  B43_PIO8_TXCTL_FREADY		0x00000080
++#define  B43_PIO8_TXCTL_SUSPREQ		0x00000100
++#define  B43_PIO8_TXCTL_QSUSP		0x00000200
++#define  B43_PIO8_TXCTL_FLUSHREQ	0x00000400
++#define  B43_PIO8_TXCTL_FLUSHPEND	0x00000800
++#define B43_PIO8_TXDATA			0x04
++/* RX queue */
++#define B43_PIO8_RXCTL			0x00
++#define  B43_PIO8_RXCTL_FRAMERDY	0x00000001
++#define  B43_PIO8_RXCTL_DATARDY		0x00000002
++#define B43_PIO8_RXDATA			0x04
++
++
++/* The maximum number of TX-packets the HW can handle. */
++#define B43_PIO_MAX_NR_TXPACKETS	32
++
++
++#ifdef CONFIG_B43_PIO
++
++struct b43_pio_txpacket {
++	/* Pointer to the TX queue we belong to. */
++	struct b43_pio_txqueue *queue;
++	/* The TX data packet. */
++	struct sk_buff *skb;
++	/* The status meta data. */
++	struct ieee80211_tx_status txstat;
++	/* Index in the (struct b43_pio_txqueue)->packets array. */
++	u8 index;
++
++	struct list_head list;
++};
++
++struct b43_pio_txqueue {
++	struct b43_wldev *dev;
++	spinlock_t lock;
++	u16 mmio_base;
++
++	/* The device queue buffer size in bytes. */
++	u16 buffer_size;
++	/* The number of used bytes in the device queue buffer. */
++	u16 buffer_used;
++	/* The number of packets that can still get queued.
++	 * This is decremented on queueing a packet and incremented
++	 * after receiving the transmit status. */
++	u16 free_packet_slots;
++
++	/* True, if the mac80211 queue was stopped due to overflow at TX. */
++	bool stopped;
++	/* Our b43 queue index number */
++	u8 index;
++	/* The mac80211 QoS queue priority. */
++	u8 queue_prio;
++
++	/* Buffer for TX packet meta data. */
++	struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS];
++	struct list_head packets_list;
++
++	/* Total number of transmitted packets. */
++	unsigned int nr_tx_packets;
++
++	/* Shortcut to the 802.11 core revision. This is to
++	 * avoid horrible pointer dereferencing in the fastpaths. */
++	u8 rev;
++};
++
++struct b43_pio_rxqueue {
++	struct b43_wldev *dev;
++	spinlock_t lock;
++	u16 mmio_base;
++
++	/* Work to reduce latency issues on RX. */
++	struct work_struct rx_work;
++
++	/* Shortcut to the 802.11 core revision. This is to
++	 * avoid horrible pointer dereferencing in the fastpaths. */
++	u8 rev;
++};
++
++
++static inline u16 b43_piotx_read16(struct b43_pio_txqueue *q, u16 offset)
++{
++	return b43_read16(q->dev, q->mmio_base + offset);
++}
++
++static inline u32 b43_piotx_read32(struct b43_pio_txqueue *q, u16 offset)
++{
++	return b43_read32(q->dev, q->mmio_base + offset);
++}
++
++static inline void b43_piotx_write16(struct b43_pio_txqueue *q,
++				     u16 offset, u16 value)
++{
++	b43_write16(q->dev, q->mmio_base + offset, value);
++}
++
++static inline void b43_piotx_write32(struct b43_pio_txqueue *q,
++				     u16 offset, u32 value)
++{
++	b43_write32(q->dev, q->mmio_base + offset, value);
++}
++
++
++static inline u16 b43_piorx_read16(struct b43_pio_rxqueue *q, u16 offset)
++{
++	return b43_read16(q->dev, q->mmio_base + offset);
++}
++
++static inline u32 b43_piorx_read32(struct b43_pio_rxqueue *q, u16 offset)
++{
++	return b43_read32(q->dev, q->mmio_base + offset);
++}
++
++static inline void b43_piorx_write16(struct b43_pio_rxqueue *q,
++				     u16 offset, u16 value)
++{
++	b43_write16(q->dev, q->mmio_base + offset, value);
++}
++
++static inline void b43_piorx_write32(struct b43_pio_rxqueue *q,
++				     u16 offset, u32 value)
++{
++	b43_write32(q->dev, q->mmio_base + offset, value);
++}
++
++
++int b43_pio_init(struct b43_wldev *dev);
++void b43_pio_stop(struct b43_wldev *dev);
++void b43_pio_free(struct b43_wldev *dev);
++
++int b43_pio_tx(struct b43_wldev *dev,
++	       struct sk_buff *skb, struct ieee80211_tx_control *ctl);
++void b43_pio_handle_txstatus(struct b43_wldev *dev,
++			     const struct b43_txstatus *status);
++void b43_pio_get_tx_stats(struct b43_wldev *dev,
++			  struct ieee80211_tx_queue_stats *stats);
++void b43_pio_rx(struct b43_pio_rxqueue *q);
++
++void b43_pio_tx_suspend(struct b43_wldev *dev);
++void b43_pio_tx_resume(struct b43_wldev *dev);
++
++
++#else /* CONFIG_B43_PIO */
++
++
++static inline int b43_pio_init(struct b43_wldev *dev)
++{
++	return 0;
++}
++static inline void b43_pio_free(struct b43_wldev *dev)
++{
++}
++static inline void b43_pio_stop(struct b43_wldev *dev)
++{
++}
++static inline int b43_pio_tx(struct b43_wldev *dev,
++			     struct sk_buff *skb,
++			     struct ieee80211_tx_control *ctl)
++{
++	return 0;
++}
++static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
++					   const struct b43_txstatus *status)
++{
++}
++static inline void b43_pio_get_tx_stats(struct b43_wldev *dev,
++					struct ieee80211_tx_queue_stats *stats)
++{
++}
++static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
++{
++}
++static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
++{
++}
++static inline void b43_pio_tx_resume(struct b43_wldev *dev)
++{
++}
++
++#endif /* CONFIG_B43_PIO */
++#endif /* B43_PIO_H_ */
+diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
+index f4faff6..275095b 100644
+--- a/drivers/net/wireless/b43/sysfs.c
++++ b/drivers/net/wireless/b43/sysfs.c
+@@ -47,29 +47,6 @@ static int get_integer(const char *buf, size_t count)
+ 	return ret;
+ }
+ 
+-static int get_boolean(const char *buf, size_t count)
+-{
+-	if (count != 0) {
+-		if (buf[0] == '1')
+-			return 1;
+-		if (buf[0] == '0')
+-			return 0;
+-		if (count >= 4 && memcmp(buf, "true", 4) == 0)
+-			return 1;
+-		if (count >= 5 && memcmp(buf, "false", 5) == 0)
+-			return 0;
+-		if (count >= 3 && memcmp(buf, "yes", 3) == 0)
+-			return 1;
+-		if (count >= 2 && memcmp(buf, "no", 2) == 0)
+-			return 0;
+-		if (count >= 2 && memcmp(buf, "on", 2) == 0)
+-			return 1;
+-		if (count >= 3 && memcmp(buf, "off", 3) == 0)
+-			return 0;
+-	}
+-	return -EINVAL;
+-}
+-
+ static ssize_t b43_attr_interfmode_show(struct device *dev,
+ 					struct device_attribute *attr,
+ 					char *buf)
+@@ -155,82 +132,18 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
+ static DEVICE_ATTR(interference, 0644,
+ 		   b43_attr_interfmode_show, b43_attr_interfmode_store);
+ 
+-static ssize_t b43_attr_preamble_show(struct device *dev,
+-				      struct device_attribute *attr, char *buf)
+-{
+-	struct b43_wldev *wldev = dev_to_b43_wldev(dev);
+-	ssize_t count;
+-
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+-	mutex_lock(&wldev->wl->mutex);
+-
+-	if (wldev->short_preamble)
+-		count =
+-		    snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
+-	else
+-		count =
+-		    snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
+-
+-	mutex_unlock(&wldev->wl->mutex);
+-
+-	return count;
+-}
+-
+-static ssize_t b43_attr_preamble_store(struct device *dev,
+-				       struct device_attribute *attr,
+-				       const char *buf, size_t count)
+-{
+-	struct b43_wldev *wldev = dev_to_b43_wldev(dev);
+-	unsigned long flags;
+-	int value;
+-
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+-	value = get_boolean(buf, count);
+-	if (value < 0)
+-		return value;
+-	mutex_lock(&wldev->wl->mutex);
+-	spin_lock_irqsave(&wldev->wl->irq_lock, flags);
+-
+-	wldev->short_preamble = !!value;
+-
+-	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
+-	mutex_unlock(&wldev->wl->mutex);
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(shortpreamble, 0644,
+-		   b43_attr_preamble_show, b43_attr_preamble_store);
+-
+ int b43_sysfs_register(struct b43_wldev *wldev)
+ {
+ 	struct device *dev = wldev->dev->dev;
+-	int err;
+ 
+ 	B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
+ 
+-	err = device_create_file(dev, &dev_attr_interference);
+-	if (err)
+-		goto out;
+-	err = device_create_file(dev, &dev_attr_shortpreamble);
+-	if (err)
+-		goto err_remove_interfmode;
+-
+-      out:
+-	return err;
+-      err_remove_interfmode:
+-	device_remove_file(dev, &dev_attr_interference);
+-	goto out;
++	return device_create_file(dev, &dev_attr_interference);
+ }
+ 
+ void b43_sysfs_unregister(struct b43_wldev *wldev)
+ {
+ 	struct device *dev = wldev->dev->dev;
+ 
+-	device_remove_file(dev, &dev_attr_shortpreamble);
+ 	device_remove_file(dev, &dev_attr_interference);
+ }
+diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c
+index e632125..daa9421 100644
+--- a/drivers/net/wireless/b43/wa.c
++++ b/drivers/net/wireless/b43/wa.c
+@@ -204,42 +204,43 @@ static void b43_wa_rt(struct b43_wldev *dev) /* Rotor table */
+ 		b43_ofdmtab_write32(dev, B43_OFDMTAB_ROTOR, i, b43_tab_rotor[i]);
+ }
+ 
++static void b43_write_null_nst(struct b43_wldev *dev)
++{
++	int i;
++
++	for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
++		b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, 0);
++}
++
++static void b43_write_nst(struct b43_wldev *dev, const u16 *nst)
++{
++	int i;
++
++	for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
++		b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, nst[i]);
++}
++
+ static void b43_wa_nst(struct b43_wldev *dev) /* Noise scale table */
+ {
+ 	struct b43_phy *phy = &dev->phy;
+-	int i;
+ 
+ 	if (phy->type == B43_PHYTYPE_A) {
+ 		if (phy->rev <= 1)
+-			for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+-				b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+-							i, 0);
++			b43_write_null_nst(dev);
+ 		else if (phy->rev == 2)
+-			for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+-				b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+-							i, b43_tab_noisescalea2[i]);
++			b43_write_nst(dev, b43_tab_noisescalea2);
+ 		else if (phy->rev == 3)
+-			for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+-				b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+-							i, b43_tab_noisescalea3[i]);
++			b43_write_nst(dev, b43_tab_noisescalea3);
+ 		else
+-			for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+-				b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+-							i, b43_tab_noisescaleg3[i]);
++			b43_write_nst(dev, b43_tab_noisescaleg3);
+ 	} else {
+ 		if (phy->rev >= 6) {
+ 			if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
+-				for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+-					b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+-						i, b43_tab_noisescaleg3[i]);
++				b43_write_nst(dev, b43_tab_noisescaleg3);
+ 			else
+-				for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+-					b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+-						i, b43_tab_noisescaleg2[i]);
++				b43_write_nst(dev, b43_tab_noisescaleg2);
+ 		} else {
+-			for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+-				b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+-							i, b43_tab_noisescaleg1[i]);
++			b43_write_nst(dev, b43_tab_noisescaleg1);
+ 		}
+ 	}
+ }
+diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
+index 7caa26e..19aefbf 100644
+--- a/drivers/net/wireless/b43/xmit.c
++++ b/drivers/net/wireless/b43/xmit.c
+@@ -30,48 +30,51 @@
+ #include "xmit.h"
+ #include "phy.h"
+ #include "dma.h"
++#include "pio.h"
+ 
+ 
+-/* Extract the bitrate out of a CCK PLCP header. */
+-static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp)
++/* Extract the bitrate index out of a CCK PLCP header. */
++static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
+ {
+ 	switch (plcp->raw[0]) {
+ 	case 0x0A:
+-		return B43_CCK_RATE_1MB;
++		return 0;
+ 	case 0x14:
+-		return B43_CCK_RATE_2MB;
++		return 1;
+ 	case 0x37:
+-		return B43_CCK_RATE_5MB;
++		return 2;
+ 	case 0x6E:
+-		return B43_CCK_RATE_11MB;
++		return 3;
+ 	}
+ 	B43_WARN_ON(1);
+-	return 0;
++	return -1;
+ }
+ 
+-/* Extract the bitrate out of an OFDM PLCP header. */
+-static u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp)
++/* Extract the bitrate index out of an OFDM PLCP header. */
++static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
+ {
++	int base = aphy ? 0 : 4;
++
+ 	switch (plcp->raw[0] & 0xF) {
+ 	case 0xB:
+-		return B43_OFDM_RATE_6MB;
++		return base + 0;
+ 	case 0xF:
+-		return B43_OFDM_RATE_9MB;
++		return base + 1;
+ 	case 0xA:
+-		return B43_OFDM_RATE_12MB;
++		return base + 2;
+ 	case 0xE:
+-		return B43_OFDM_RATE_18MB;
++		return base + 3;
+ 	case 0x9:
+-		return B43_OFDM_RATE_24MB;
++		return base + 4;
+ 	case 0xD:
+-		return B43_OFDM_RATE_36MB;
++		return base + 5;
+ 	case 0x8:
+-		return B43_OFDM_RATE_48MB;
++		return base + 6;
+ 	case 0xC:
+-		return B43_OFDM_RATE_54MB;
++		return base + 7;
+ 	}
+ 	B43_WARN_ON(1);
+-	return 0;
++	return -1;
+ }
+ 
+ u8 b43_plcp_get_ratecode_cck(const u8 bitrate)
+@@ -191,6 +194,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+ 	    (const struct ieee80211_hdr *)fragment_data;
+ 	int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
+ 	u16 fctl = le16_to_cpu(wlhdr->frame_control);
++	struct ieee80211_rate *fbrate;
+ 	u8 rate, rate_fb;
+ 	int rate_ofdm, rate_fb_ofdm;
+ 	unsigned int plcp_fragment_len;
+@@ -200,9 +204,11 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+ 
+ 	memset(txhdr, 0, sizeof(*txhdr));
+ 
+-	rate = txctl->tx_rate;
++	WARN_ON(!txctl->tx_rate);
++	rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB;
+ 	rate_ofdm = b43_is_ofdm_rate(rate);
+-	rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
++	fbrate = txctl->alt_retry_rate ? : txctl->tx_rate;
++	rate_fb = fbrate->hw_value;
+ 	rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
+ 
+ 	if (rate_ofdm)
+@@ -221,11 +227,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+ 		 * use the original dur_id field. */
+ 		txhdr->dur_fb = wlhdr->duration_id;
+ 	} else {
+-		int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb);
+ 		txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
+ 								 txctl->vif,
+ 								 fragment_len,
+-								 fbrate_base100kbps);
++								 fbrate);
+ 	}
+ 
+ 	plcp_fragment_len = fragment_len + FCS_LEN;
+@@ -287,7 +292,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+ 		phy_ctl |= B43_TXH_PHY_ENC_OFDM;
+ 	else
+ 		phy_ctl |= B43_TXH_PHY_ENC_CCK;
+-	if (dev->short_preamble)
++	if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
+ 		phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
+ 
+ 	switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) {
+@@ -332,7 +337,8 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+ 		int rts_rate_ofdm, rts_rate_fb_ofdm;
+ 		struct b43_plcp_hdr6 *plcp;
+ 
+-		rts_rate = txctl->rts_cts_rate;
++		WARN_ON(!txctl->rts_cts_rate);
++		rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
+ 		rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
+ 		rts_rate_fb = b43_calc_fallback_rate(rts_rate);
+ 		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
+@@ -506,7 +512,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
+ 	u16 phystat0, phystat3, chanstat, mactime;
+ 	u32 macstat;
+ 	u16 chanid;
+-	u8 jssi;
++	u16 phytype;
+ 	int padding;
+ 
+ 	memset(&status, 0, sizeof(status));
+@@ -514,10 +520,10 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
+ 	/* Get metadata about the frame from the header. */
+ 	phystat0 = le16_to_cpu(rxhdr->phy_status0);
+ 	phystat3 = le16_to_cpu(rxhdr->phy_status3);
+-	jssi = rxhdr->jssi;
+ 	macstat = le32_to_cpu(rxhdr->mac_status);
+ 	mactime = le16_to_cpu(rxhdr->mac_time);
+ 	chanstat = le16_to_cpu(rxhdr->channel);
++	phytype = chanstat & B43_RX_CHAN_PHYTYPE;
+ 
+ 	if (macstat & B43_RX_MAC_FCSERR)
+ 		dev->wl->ieee_stats.dot11FCSErrorCount++;
+@@ -567,26 +573,40 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
+ 		}
+ 	}
+ 
+-	status.ssi = b43_rssi_postprocess(dev, jssi,
+-					  (phystat0 & B43_RX_PHYST0_OFDM),
+-					  (phystat0 & B43_RX_PHYST0_GAINCTL),
+-					  (phystat3 & B43_RX_PHYST3_TRSTATE));
++	/* Link quality statistics */
+ 	status.noise = dev->stats.link_noise;
+-	/* the next line looks wrong, but is what mac80211 wants */
+-	status.signal = (jssi * 100) / B43_RX_MAX_SSI;
++	if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
++//		s8 rssi = max(rxhdr->power0, rxhdr->power1);
++		//TODO: Find out what the rssi value is (dBm or percentage?)
++		//      and also find out what the maximum possible value is.
++		//      Fill status.ssi and status.signal fields.
++	} else {
++		status.ssi = b43_rssi_postprocess(dev, rxhdr->jssi,
++						  (phystat0 & B43_RX_PHYST0_OFDM),
++						  (phystat0 & B43_RX_PHYST0_GAINCTL),
++						  (phystat3 & B43_RX_PHYST3_TRSTATE));
++		/* the next line looks wrong, but is what mac80211 wants */
++		status.signal = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
++	}
++
+ 	if (phystat0 & B43_RX_PHYST0_OFDM)
+-		status.rate = b43_plcp_get_bitrate_ofdm(plcp);
++		status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
++						phytype == B43_PHYTYPE_A);
+ 	else
+-		status.rate = b43_plcp_get_bitrate_cck(plcp);
++		status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
+ 	status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
+ 
+ 	/*
+-	 * If monitors are present get full 64-bit timestamp. This
+-	 * code assumes we get to process the packet within 16 bits
+-	 * of timestamp, i.e. about 65 milliseconds after the PHY
+-	 * received the first symbol.
++	 * All frames on monitor interfaces and beacons always need a full
++	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
++	 * purposes and beacons for IBSS merging.
++	 * This code assumes we get to process the packet within 16 bits
++	 * of timestamp, i.e. about 65 milliseconds after the PHY received
++	 * the first symbol.
+ 	 */
+-	if (dev->wl->radiotap_enabled) {
++	if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
++	    == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
++	    dev->wl->radiotap_enabled) {
+ 		u16 low_mactime_now;
+ 
+ 		b43_tsf_read(dev, &status.mactime);
+@@ -601,29 +621,28 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
+ 	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
+ 	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
+ 	case B43_PHYTYPE_A:
+-		status.phymode = MODE_IEEE80211A;
++		status.band = IEEE80211_BAND_5GHZ;
+ 		B43_WARN_ON(1);
+ 		/* FIXME: We don't really know which value the "chanid" contains.
+ 		 *        So the following assignment might be wrong. */
+-		status.channel = chanid;
+-		status.freq = b43_channel_to_freq_5ghz(status.channel);
++		status.freq = b43_channel_to_freq_5ghz(chanid);
+ 		break;
+ 	case B43_PHYTYPE_G:
+-		status.phymode = MODE_IEEE80211G;
++		status.band = IEEE80211_BAND_2GHZ;
+ 		/* chanid is the radio channel cookie value as used
+ 		 * to tune the radio. */
+ 		status.freq = chanid + 2400;
+-		status.channel = b43_freq_to_channel_2ghz(status.freq);
+ 		break;
+ 	case B43_PHYTYPE_N:
+-		status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/;
+ 		/* chanid is the SHM channel cookie. Which is the plain
+ 		 * channel number in b43. */
+-		status.channel = chanid;
+-		if (chanstat & B43_RX_CHAN_5GHZ)
+-			status.freq = b43_freq_to_channel_5ghz(status.freq);
+-		else
+-			status.freq = b43_freq_to_channel_2ghz(status.freq);
++		if (chanstat & B43_RX_CHAN_5GHZ) {
++			status.band = IEEE80211_BAND_5GHZ;
++			status.freq = b43_freq_to_channel_5ghz(chanid);
++		} else {
++			status.band = IEEE80211_BAND_2GHZ;
++			status.freq = b43_freq_to_channel_2ghz(chanid);
++		}
+ 		break;
+ 	default:
+ 		B43_WARN_ON(1);
+@@ -657,67 +676,54 @@ void b43_handle_txstatus(struct b43_wldev *dev,
+ 			dev->wl->ieee_stats.dot11RTSSuccessCount++;
+ 	}
+ 
+-	b43_dma_handle_txstatus(dev, status);
++	if (b43_using_pio_transfers(dev))
++		b43_pio_handle_txstatus(dev, status);
++	else
++		b43_dma_handle_txstatus(dev, status);
+ }
+ 
+-/* Handle TX status report as received through DMA/PIO queues */
+-void b43_handle_hwtxstatus(struct b43_wldev *dev,
+-			   const struct b43_hwtxstatus *hw)
++/* Fill out the mac80211 TXstatus report based on the b43-specific
++ * txstatus report data. This returns a boolean whether the frame was
++ * successfully transmitted. */
++bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
++			      const struct b43_txstatus *status)
+ {
+-	struct b43_txstatus status;
+-	u8 tmp;
+-
+-	status.cookie = le16_to_cpu(hw->cookie);
+-	status.seq = le16_to_cpu(hw->seq);
+-	status.phy_stat = hw->phy_stat;
+-	tmp = hw->count;
+-	status.frame_count = (tmp >> 4);
+-	status.rts_count = (tmp & 0x0F);
+-	tmp = hw->flags;
+-	status.supp_reason = ((tmp & 0x1C) >> 2);
+-	status.pm_indicated = !!(tmp & 0x80);
+-	status.intermediate = !!(tmp & 0x40);
+-	status.for_ampdu = !!(tmp & 0x20);
+-	status.acked = !!(tmp & 0x02);
+-
+-	b43_handle_txstatus(dev, &status);
++	bool frame_success = 1;
++
++	if (status->acked) {
++		/* The frame was ACKed. */
++		report->flags |= IEEE80211_TX_STATUS_ACK;
++	} else {
++		/* The frame was not ACKed... */
++		if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) {
++			/* ...but we expected an ACK. */
++			frame_success = 0;
++			report->excessive_retries = 1;
++		}
++	}
++	if (status->frame_count == 0) {
++		/* The frame was not transmitted at all. */
++		report->retry_count = 0;
++	} else
++		report->retry_count = status->frame_count - 1;
++
++	return frame_success;
+ }
+ 
+ /* Stop any TX operation on the device (suspend the hardware queues) */
+ void b43_tx_suspend(struct b43_wldev *dev)
+ {
+-	b43_dma_tx_suspend(dev);
++	if (b43_using_pio_transfers(dev))
++		b43_pio_tx_suspend(dev);
++	else
++		b43_dma_tx_suspend(dev);
+ }
+ 
+ /* Resume any TX operation on the device (resume the hardware queues) */
+ void b43_tx_resume(struct b43_wldev *dev)
+ {
+-	b43_dma_tx_resume(dev);
+-}
+-
+-#if 0
+-static void upload_qos_parms(struct b43_wldev *dev,
+-			     const u16 * parms, u16 offset)
+-{
+-	int i;
+-
+-	for (i = 0; i < B43_NR_QOSPARMS; i++) {
+-		b43_shm_write16(dev, B43_SHM_SHARED,
+-				offset + (i * 2), parms[i]);
+-	}
+-}
+-#endif
+-
+-/* Initialize the QoS parameters */
+-void b43_qos_init(struct b43_wldev *dev)
+-{
+-	/* FIXME: This function must probably be called from the mac80211
+-	 * config callback. */
+-	return;
+-
+-	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
+-	//FIXME kill magic
+-	b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4);
+-
+-	/*TODO: We might need some stack support here to get the values. */
++	if (b43_using_pio_transfers(dev))
++		b43_pio_tx_resume(dev);
++	else
++		b43_dma_tx_resume(dev);
+ }
+diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
+index 4176503..b05f44e 100644
+--- a/drivers/net/wireless/b43/xmit.h
++++ b/drivers/net/wireless/b43/xmit.h
+@@ -207,25 +207,24 @@ enum {
+ 	B43_TXST_SUPP_ABNACK,	/* Afterburner NACK */
+ };
+ 
+-/* Transmit Status as received through DMA/PIO on old chips */
+-struct b43_hwtxstatus {
+-	PAD_BYTES(4);
+-	__le16 cookie;
+-	u8 flags;
+-	u8 count;
+-	 PAD_BYTES(2);
+-	__le16 seq;
+-	u8 phy_stat;
+-	 PAD_BYTES(1);
+-} __attribute__ ((__packed__));
+-
+ /* Receive header for v4 firmware. */
+ struct b43_rxhdr_fw4 {
+ 	__le16 frame_len;	/* Frame length */
+ 	 PAD_BYTES(2);
+ 	__le16 phy_status0;	/* PHY RX Status 0 */
+-	__u8 jssi;		/* PHY RX Status 1: JSSI */
+-	__u8 sig_qual;		/* PHY RX Status 1: Signal Quality */
++	union {
++		/* RSSI for A/B/G-PHYs */
++		struct {
++			__u8 jssi;	/* PHY RX Status 1: JSSI */
++			__u8 sig_qual;	/* PHY RX Status 1: Signal Quality */
++		} __attribute__ ((__packed__));
++
++		/* RSSI for N-PHYs */
++		struct {
++			__s8 power0;	/* PHY RX Status 1: Power 0 */
++			__s8 power1;	/* PHY RX Status 1: Power 1 */
++		} __attribute__ ((__packed__));
++	} __attribute__ ((__packed__));
+ 	__le16 phy_status2;	/* PHY RX Status 2 */
+ 	__le16 phy_status3;	/* PHY RX Status 3 */
+ 	__le32 mac_status;	/* MAC RX status */
+@@ -295,25 +294,12 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr);
+ 
+ void b43_handle_txstatus(struct b43_wldev *dev,
+ 			 const struct b43_txstatus *status);
+-
+-void b43_handle_hwtxstatus(struct b43_wldev *dev,
+-			   const struct b43_hwtxstatus *hw);
++bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
++			      const struct b43_txstatus *status);
+ 
+ void b43_tx_suspend(struct b43_wldev *dev);
+ void b43_tx_resume(struct b43_wldev *dev);
+ 
+-#define B43_NR_QOSPARMS		22
+-enum {
+-	B43_QOSPARM_TXOP = 0,
+-	B43_QOSPARM_CWMIN,
+-	B43_QOSPARM_CWMAX,
+-	B43_QOSPARM_CWCUR,
+-	B43_QOSPARM_AIFS,
+-	B43_QOSPARM_BSLOTS,
+-	B43_QOSPARM_REGGAP,
+-	B43_QOSPARM_STATUS,
+-};
+-void b43_qos_init(struct b43_wldev *dev);
+ 
+ /* Helper functions for converting the key-table index from "firmware-format"
+  * to "raw-format" and back. The firmware API changed for this at some revision.
+diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
+index 93d45b7..ded3cd3 100644
+--- a/drivers/net/wireless/b43legacy/b43legacy.h
++++ b/drivers/net/wireless/b43legacy/b43legacy.h
+@@ -97,6 +97,7 @@
+ #define B43legacy_MMIO_RADIO_HWENABLED_LO	0x49A
+ #define B43legacy_MMIO_GPIO_CONTROL	0x49C
+ #define B43legacy_MMIO_GPIO_MASK		0x49E
++#define B43legacy_MMIO_TSF_CFP_PRETBTT	0x612
+ #define B43legacy_MMIO_TSF_0		0x632 /* core rev < 3 only */
+ #define B43legacy_MMIO_TSF_1		0x634 /* core rev < 3 only */
+ #define B43legacy_MMIO_TSF_2		0x636 /* core rev < 3 only */
+@@ -130,19 +131,27 @@
+ #define B43legacy_SHM_SH_HOSTFHI	0x0060 /* Hostflags ucode opts (high) */
+ /* SHM_SHARED crypto engine */
+ #define B43legacy_SHM_SH_KEYIDXBLOCK	0x05D4 /* Key index/algorithm block */
+-/* SHM_SHARED beacon variables */
++/* SHM_SHARED beacon/AP variables */
++#define B43legacy_SHM_SH_DTIMP		0x0012 /* DTIM period */
++#define B43legacy_SHM_SH_BTL0		0x0018 /* Beacon template length 0 */
++#define B43legacy_SHM_SH_BTL1		0x001A /* Beacon template length 1 */
++#define B43legacy_SHM_SH_BTSFOFF	0x001C /* Beacon TSF offset */
++#define B43legacy_SHM_SH_TIMPOS		0x001E /* TIM position in beacon */
+ #define B43legacy_SHM_SH_BEACPHYCTL	0x0054 /* Beacon PHY TX control word */
+ /* SHM_SHARED ACK/CTS control */
+ #define B43legacy_SHM_SH_ACKCTSPHYCTL	0x0022 /* ACK/CTS PHY control word */
+ /* SHM_SHARED probe response variables */
+-#define B43legacy_SHM_SH_PRPHYCTL	0x0188 /* Probe Resp PHY TX control */
++#define B43legacy_SHM_SH_PRTLEN		0x004A /* Probe Response template length */
+ #define B43legacy_SHM_SH_PRMAXTIME	0x0074 /* Probe Response max time */
++#define B43legacy_SHM_SH_PRPHYCTL	0x0188 /* Probe Resp PHY TX control */
+ /* SHM_SHARED rate tables */
+ /* SHM_SHARED microcode soft registers */
+ #define B43legacy_SHM_SH_UCODEREV	0x0000 /* Microcode revision */
+ #define B43legacy_SHM_SH_UCODEPATCH	0x0002 /* Microcode patchlevel */
+ #define B43legacy_SHM_SH_UCODEDATE	0x0004 /* Microcode date */
+ #define B43legacy_SHM_SH_UCODETIME	0x0006 /* Microcode time */
++#define B43legacy_SHM_SH_SPUWKUP	0x0094 /* pre-wakeup for synth PU in us */
++#define B43legacy_SHM_SH_PRETBTT	0x0096 /* pre-TBTT in us */
+ 
+ #define B43legacy_UCODEFLAGS_OFFSET     0x005E
+ 
+@@ -199,6 +208,13 @@
+ #define B43legacy_MACCTL_TBTTHOLD	0x10000000 /* TBTT Hold */
+ #define B43legacy_MACCTL_GMODE		0x80000000 /* G Mode */
+ 
++/* MAC Command bitfield */
++#define B43legacy_MACCMD_BEACON0_VALID	0x00000001 /* Beacon 0 in template RAM is busy/valid */
++#define B43legacy_MACCMD_BEACON1_VALID	0x00000002 /* Beacon 1 in template RAM is busy/valid */
++#define B43legacy_MACCMD_DFQ_VALID	0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */
++#define B43legacy_MACCMD_CCA		0x00000008 /* Clear channel assessment */
++#define B43legacy_MACCMD_BGNOISE	0x00000010 /* Background noise */
++
+ /* 802.11 core specific TM State Low flags */
+ #define B43legacy_TMSLOW_GMODE		0x20000000 /* G Mode Enable */
+ #define B43legacy_TMSLOW_PLLREFSEL	0x00200000 /* PLL Freq Ref Select */
+@@ -317,15 +333,7 @@ enum {
+ # undef assert
+ #endif
+ #ifdef CONFIG_B43LEGACY_DEBUG
+-# define B43legacy_WARN_ON(expr)					\
+-	do {								\
+-		if (unlikely((expr))) {					\
+-			printk(KERN_INFO PFX "Test (%s) failed at:"	\
+-					      " %s:%d:%s()\n",		\
+-					      #expr, __FILE__,		\
+-					      __LINE__, __FUNCTION__);	\
+-		}							\
+-	} while (0)
++# define B43legacy_WARN_ON(x)	WARN_ON(x)
+ # define B43legacy_BUG_ON(expr)						\
+ 	do {								\
+ 		if (unlikely((expr))) {					\
+@@ -336,7 +344,9 @@ enum {
+ 	} while (0)
+ # define B43legacy_DEBUG	1
+ #else
+-# define B43legacy_WARN_ON(x)	do { /* nothing */ } while (0)
++/* This will evaluate the argument even if debugging is disabled. */
++static inline bool __b43legacy_warn_on_dummy(bool x) { return x; }
++# define B43legacy_WARN_ON(x)	__b43legacy_warn_on_dummy(unlikely(!!(x)))
+ # define B43legacy_BUG_ON(x)	do { /* nothing */ } while (0)
+ # define B43legacy_DEBUG	0
+ #endif
+@@ -392,10 +402,6 @@ struct b43legacy_phy {
+ 	u8 possible_phymodes;
+ 	/* GMODE bit enabled in MACCTL? */
+ 	bool gmode;
+-	/* Possible ieee80211 subsystem hwmodes for this PHY.
+-	 * Which mode is selected, depends on thr GMODE enabled bit */
+-#define B43legacy_MAX_PHYHWMODES	2
+-	struct ieee80211_hw_mode hwmodes[B43legacy_MAX_PHYHWMODES];
+ 
+ 	/* Analog Type */
+ 	u8 analog;
+@@ -598,6 +604,12 @@ struct b43legacy_wl {
+ 	u8 nr_devs;
+ 
+ 	bool radiotap_enabled;
++
++	/* The beacon we are currently using (AP or IBSS mode).
++	 * This beacon stuff is protected by the irq_lock. */
++	struct sk_buff *current_beacon;
++	bool beacon0_uploaded;
++	bool beacon1_uploaded;
+ };
+ 
+ /* Pointers to the firmware data and meta information about it. */
+@@ -649,7 +661,7 @@ struct b43legacy_wldev {
+ 
+ 	bool __using_pio;	/* Using pio rather than dma. */
+ 	bool bad_frames_preempt;/* Use "Bad Frames Preemption". */
+-	bool reg124_set_0x4;	/* Variable to keep track of IRQ. */
++	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM). */
+ 	bool short_preamble;	/* TRUE if using short preamble. */
+ 	bool short_slot;	/* TRUE if using short slot timing. */
+ 	bool radio_hw_enable;	/* State of radio hardware enable bit. */
+@@ -696,9 +708,6 @@ struct b43legacy_wldev {
+ 	u8 max_nr_keys;
+ 	struct b43legacy_key key[58];
+ 
+-	/* Cached beacon template while uploading the template. */
+-	struct sk_buff *cached_beacon;
+-
+ 	/* Firmware data */
+ 	struct b43legacy_firmware fw;
+ 
+diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
+index 0f7a6e7..ef829ee 100644
+--- a/drivers/net/wireless/b43legacy/main.c
++++ b/drivers/net/wireless/b43legacy/main.c
+@@ -95,28 +95,29 @@ MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl);
+  * data in there. This data is the same for all devices, so we don't
+  * get concurrency issues */
+ #define RATETAB_ENT(_rateid, _flags) \
+-	{							\
+-		.rate	= B43legacy_RATE_TO_100KBPS(_rateid),	\
+-		.val	= (_rateid),				\
+-		.val2	= (_rateid),				\
+-		.flags	= (_flags),				\
++	{								\
++		.bitrate	= B43legacy_RATE_TO_100KBPS(_rateid),	\
++		.hw_value	= (_rateid),				\
++		.flags		= (_flags),				\
+ 	}
++/*
++ * NOTE: When changing this, sync with xmit.c's
++ *	 b43legacy_plcp_get_bitrate_idx_* functions!
++ */
+ static struct ieee80211_rate __b43legacy_ratetable[] = {
+-	RATETAB_ENT(B43legacy_CCK_RATE_1MB, IEEE80211_RATE_CCK),
+-	RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
+-	RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
+-	RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
+-	RATETAB_ENT(B43legacy_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43legacy_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43legacy_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43legacy_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43legacy_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43legacy_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43legacy_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
+-	RATETAB_ENT(B43legacy_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
++	RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0),
++	RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
++	RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
++	RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
++	RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0),
++	RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0),
++	RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0),
++	RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0),
++	RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0),
++	RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0),
++	RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0),
++	RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0),
+ };
+-#define b43legacy_a_ratetable		(__b43legacy_ratetable + 4)
+-#define b43legacy_a_ratetable_size	8
+ #define b43legacy_b_ratetable		(__b43legacy_ratetable + 0)
+ #define b43legacy_b_ratetable_size	4
+ #define b43legacy_g_ratetable		(__b43legacy_ratetable + 0)
+@@ -124,14 +125,8 @@ static struct ieee80211_rate __b43legacy_ratetable[] = {
+ 
+ #define CHANTAB_ENT(_chanid, _freq) \
+ 	{							\
+-		.chan	= (_chanid),				\
+-		.freq	= (_freq),				\
+-		.val	= (_chanid),				\
+-		.flag	= IEEE80211_CHAN_W_SCAN |		\
+-			  IEEE80211_CHAN_W_ACTIVE_SCAN |	\
+-			  IEEE80211_CHAN_W_IBSS,		\
+-		.power_level	= 0x0A,				\
+-		.antenna_max	= 0xFF,				\
++		.center_freq	= (_freq),			\
++		.hw_value	= (_chanid),			\
+ 	}
+ static struct ieee80211_channel b43legacy_bg_chantable[] = {
+ 	CHANTAB_ENT(1, 2412),
+@@ -149,7 +144,20 @@ static struct ieee80211_channel b43legacy_bg_chantable[] = {
+ 	CHANTAB_ENT(13, 2472),
+ 	CHANTAB_ENT(14, 2484),
+ };
+-#define b43legacy_bg_chantable_size	ARRAY_SIZE(b43legacy_bg_chantable)
++
++static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = {
++	.channels = b43legacy_bg_chantable,
++	.n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
++	.bitrates = b43legacy_b_ratetable,
++	.n_bitrates = b43legacy_b_ratetable_size,
++};
++
++static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = {
++	.channels = b43legacy_bg_chantable,
++	.n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
++	.bitrates = b43legacy_g_ratetable,
++	.n_bitrates = b43legacy_g_ratetable_size,
++};
+ 
+ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev);
+ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev);
+@@ -797,9 +805,8 @@ static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev)
+ {
+ 	b43legacy_jssi_write(dev, 0x7F7F7F7F);
+ 	b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+-			  b43legacy_read32(dev,
+-			  B43legacy_MMIO_MACCMD)
+-			  | (1 << 4));
++			  b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
++			  | B43legacy_MACCMD_BGNOISE);
+ 	B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
+ 			    dev->phy.channel);
+ }
+@@ -888,18 +895,18 @@ static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev)
+ 		if (1/*FIXME: the last PSpoll frame was sent successfully */)
+ 			b43legacy_power_saving_ctl_bits(dev, -1, -1);
+ 	}
+-	dev->reg124_set_0x4 = 0;
+ 	if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
+-		dev->reg124_set_0x4 = 1;
++		dev->dfq_valid = 1;
+ }
+ 
+ static void handle_irq_atim_end(struct b43legacy_wldev *dev)
+ {
+-	if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
+-		return;
+-	b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+-			  b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
+-			  | 0x4);
++	if (dev->dfq_valid) {
++		b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
++				  b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
++				  | B43legacy_MACCMD_DFQ_VALID);
++		dev->dfq_valid = 0;
++	}
+ }
+ 
+ static void handle_irq_pmq(struct b43legacy_wldev *dev)
+@@ -955,32 +962,77 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
+ 					    u16 ram_offset,
+ 					    u16 shm_size_offset, u8 rate)
+ {
+-	int len;
+-	const u8 *data;
+ 
+-	B43legacy_WARN_ON(!dev->cached_beacon);
+-	len = min((size_t)dev->cached_beacon->len,
++	unsigned int i, len, variable_len;
++	const struct ieee80211_mgmt *bcn;
++	const u8 *ie;
++	bool tim_found = 0;
++
++	bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
++	len = min((size_t)dev->wl->current_beacon->len,
+ 		  0x200 - sizeof(struct b43legacy_plcp_hdr6));
+-	data = (const u8 *)(dev->cached_beacon->data);
+-	b43legacy_write_template_common(dev, data,
+-					len, ram_offset,
++
++	b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset,
+ 					shm_size_offset, rate);
++
++	/* Find the position of the TIM and the DTIM_period value
++	 * and write them to SHM. */
++	ie = bcn->u.beacon.variable;
++	variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
++	for (i = 0; i < variable_len - 2; ) {
++		uint8_t ie_id, ie_len;
++
++		ie_id = ie[i];
++		ie_len = ie[i + 1];
++		if (ie_id == 5) {
++			u16 tim_position;
++			u16 dtim_period;
++			/* This is the TIM Information Element */
++
++			/* Check whether the ie_len is in the beacon data range. */
++			if (variable_len < ie_len + 2 + i)
++				break;
++			/* A valid TIM is at least 4 bytes long. */
++			if (ie_len < 4)
++				break;
++			tim_found = 1;
++
++			tim_position = sizeof(struct b43legacy_plcp_hdr6);
++			tim_position += offsetof(struct ieee80211_mgmt,
++						 u.beacon.variable);
++			tim_position += i;
++
++			dtim_period = ie[i + 3];
++
++			b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
++					B43legacy_SHM_SH_TIMPOS, tim_position);
++			b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
++					B43legacy_SHM_SH_DTIMP, dtim_period);
++			break;
++		}
++		i += ie_len + 2;
++	}
++	if (!tim_found) {
++		b43legacywarn(dev->wl, "Did not find a valid TIM IE in the "
++			      "beacon template packet. AP or IBSS operation "
++			      "may be broken.\n");
++	}
+ }
+ 
+ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
+ 					    u16 shm_offset, u16 size,
+-					    u8 rate)
++					    struct ieee80211_rate *rate)
+ {
+ 	struct b43legacy_plcp_hdr4 plcp;
+ 	u32 tmp;
+ 	__le16 dur;
+ 
+ 	plcp.data = 0;
+-	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
++	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate);
+ 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
+ 					       dev->wl->vif,
+ 					       size,
+-					       B43legacy_RATE_TO_100KBPS(rate));
++					       rate);
+ 	/* Write PLCP in two parts and timing for packet transfer */
+ 	tmp = le32_to_cpu(plcp.data);
+ 	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset,
+@@ -997,45 +1049,44 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
+  * 2) Patching duration field
+  * 3) Stripping TIM
+  */
+-static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
+-					 u16 *dest_size, u8 rate)
++static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
++					       u16 *dest_size,
++					       struct ieee80211_rate *rate)
+ {
+ 	const u8 *src_data;
+ 	u8 *dest_data;
+-	u16 src_size;
+-	u16 elem_size;
+-	u16 src_pos;
+-	u16 dest_pos;
++	u16 src_size, elem_size, src_pos, dest_pos;
+ 	__le16 dur;
+ 	struct ieee80211_hdr *hdr;
++	size_t ie_start;
++
++	src_size = dev->wl->current_beacon->len;
++	src_data = (const u8 *)dev->wl->current_beacon->data;
+ 
+-	B43legacy_WARN_ON(!dev->cached_beacon);
+-	src_size = dev->cached_beacon->len;
+-	src_data = (const u8 *)dev->cached_beacon->data;
++	/* Get the start offset of the variable IEs in the packet. */
++	ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
++	B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt,
++					       u.beacon.variable));
+ 
+-	if (unlikely(src_size < 0x24)) {
+-		b43legacydbg(dev->wl, "b43legacy_generate_probe_resp: "
+-		       "invalid beacon\n");
++	if (B43legacy_WARN_ON(src_size < ie_start))
+ 		return NULL;
+-	}
+ 
+ 	dest_data = kmalloc(src_size, GFP_ATOMIC);
+ 	if (unlikely(!dest_data))
+ 		return NULL;
+ 
+-	/* 0x24 is offset of first variable-len Information-Element
+-	 * in beacon frame.
+-	 */
+-	memcpy(dest_data, src_data, 0x24);
+-	src_pos = 0x24;
+-	dest_pos = 0x24;
+-	for (; src_pos < src_size - 2; src_pos += elem_size) {
++	/* Copy the static data and all Information Elements, except the TIM. */
++	memcpy(dest_data, src_data, ie_start);
++	src_pos = ie_start;
++	dest_pos = ie_start;
++	for ( ; src_pos < src_size - 2; src_pos += elem_size) {
+ 		elem_size = src_data[src_pos + 1] + 2;
+-		if (src_data[src_pos] != 0x05) { /* TIM */
+-			memcpy(dest_data + dest_pos, src_data + src_pos,
+-			       elem_size);
+-			dest_pos += elem_size;
++		if (src_data[src_pos] == 5) {
++			/* This is the TIM. */
++			continue;
+ 		}
++		memcpy(dest_data + dest_pos, src_data + src_pos, elem_size);
++		dest_pos += elem_size;
+ 	}
+ 	*dest_size = dest_pos;
+ 	hdr = (struct ieee80211_hdr *)dest_data;
+@@ -1046,7 +1097,7 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
+ 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
+ 					       dev->wl->vif,
+ 					       *dest_size,
+-					       B43legacy_RATE_TO_100KBPS(rate));
++					       rate);
+ 	hdr->duration_id = dur;
+ 
+ 	return dest_data;
+@@ -1054,13 +1105,13 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
+ 
+ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
+ 						u16 ram_offset,
+-						u16 shm_size_offset, u8 rate)
++						u16 shm_size_offset,
++						struct ieee80211_rate *rate)
+ {
+-	u8 *probe_resp_data;
++	const u8 *probe_resp_data;
+ 	u16 size;
+ 
+-	B43legacy_WARN_ON(!dev->cached_beacon);
+-	size = dev->cached_beacon->len;
++	size = dev->wl->current_beacon->len;
+ 	probe_resp_data = b43legacy_generate_probe_resp(dev, &size, rate);
+ 	if (unlikely(!probe_resp_data))
+ 		return;
+@@ -1069,59 +1120,37 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
+ 	 * all possible basic rates
+ 	 */
+ 	b43legacy_write_probe_resp_plcp(dev, 0x31A, size,
+-					B43legacy_CCK_RATE_1MB);
++					&b43legacy_b_ratetable[0]);
+ 	b43legacy_write_probe_resp_plcp(dev, 0x32C, size,
+-					B43legacy_CCK_RATE_2MB);
++					&b43legacy_b_ratetable[1]);
+ 	b43legacy_write_probe_resp_plcp(dev, 0x33E, size,
+-					B43legacy_CCK_RATE_5MB);
++					&b43legacy_b_ratetable[2]);
+ 	b43legacy_write_probe_resp_plcp(dev, 0x350, size,
+-					B43legacy_CCK_RATE_11MB);
++					&b43legacy_b_ratetable[3]);
+ 
+ 	size = min((size_t)size,
+ 		   0x200 - sizeof(struct b43legacy_plcp_hdr6));
+ 	b43legacy_write_template_common(dev, probe_resp_data,
+ 					size, ram_offset,
+-					shm_size_offset, rate);
++					shm_size_offset, rate->bitrate);
+ 	kfree(probe_resp_data);
+ }
+ 
+-static int b43legacy_refresh_cached_beacon(struct b43legacy_wldev *dev,
+-					   struct sk_buff *beacon)
++/* Asynchronously update the packet templates in template RAM.
++ * Locking: Requires wl->irq_lock to be locked. */
++static void b43legacy_update_templates(struct b43legacy_wl *wl,
++				       struct sk_buff *beacon)
+ {
+-	if (dev->cached_beacon)
+-		kfree_skb(dev->cached_beacon);
+-	dev->cached_beacon = beacon;
++	/* This is the top half of the ansynchronous beacon update. The bottom
++	 * half is the beacon IRQ. Beacon update must be asynchronous to avoid
++	 * sending an invalid beacon. This can happen for example, if the
++	 * firmware transmits a beacon while we are updating it. */
+ 
+-	return 0;
+-}
+-
+-static void b43legacy_update_templates(struct b43legacy_wldev *dev)
+-{
+-	u32 status;
+-
+-	B43legacy_WARN_ON(!dev->cached_beacon);
+-
+-	b43legacy_write_beacon_template(dev, 0x68, 0x18,
+-					B43legacy_CCK_RATE_1MB);
+-	b43legacy_write_beacon_template(dev, 0x468, 0x1A,
+-					B43legacy_CCK_RATE_1MB);
+-	b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
+-					    B43legacy_CCK_RATE_11MB);
+-
+-	status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+-	status |= 0x03;
+-	b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
+-}
+-
+-static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
+-					struct sk_buff *beacon)
+-{
+-	int err;
+-
+-	err = b43legacy_refresh_cached_beacon(dev, beacon);
+-	if (unlikely(err))
+-		return;
+-	b43legacy_update_templates(dev);
++	if (wl->current_beacon)
++		dev_kfree_skb_any(wl->current_beacon);
++	wl->current_beacon = beacon;
++	wl->beacon0_uploaded = 0;
++	wl->beacon1_uploaded = 0;
+ }
+ 
+ static void b43legacy_set_ssid(struct b43legacy_wldev *dev,
+@@ -1162,38 +1191,37 @@ static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
+ 
+ static void handle_irq_beacon(struct b43legacy_wldev *dev)
+ {
+-	u32 status;
++	struct b43legacy_wl *wl = dev->wl;
++	u32 cmd;
+ 
+-	if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
++	if (!b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
+ 		return;
+ 
+-	dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
+-	status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+-
+-	if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
+-		/* ACK beacon IRQ. */
+-		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
+-				  B43legacy_IRQ_BEACON);
+-		dev->irq_savedstate |= B43legacy_IRQ_BEACON;
+-		if (dev->cached_beacon)
+-			kfree_skb(dev->cached_beacon);
+-		dev->cached_beacon = NULL;
+-		return;
+-	}
+-	if (!(status & 0x1)) {
+-		b43legacy_write_beacon_template(dev, 0x68, 0x18,
+-						B43legacy_CCK_RATE_1MB);
+-		status |= 0x1;
+-		b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+-				  status);
+-	}
+-	if (!(status & 0x2)) {
+-		b43legacy_write_beacon_template(dev, 0x468, 0x1A,
+-						B43legacy_CCK_RATE_1MB);
+-		status |= 0x2;
+-		b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+-				  status);
++	/* This is the bottom half of the asynchronous beacon update. */
++
++	cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
++	if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) {
++		if (!wl->beacon0_uploaded) {
++			b43legacy_write_beacon_template(dev, 0x68,
++							B43legacy_SHM_SH_BTL0,
++							B43legacy_CCK_RATE_1MB);
++			b43legacy_write_probe_resp_template(dev, 0x268,
++							    B43legacy_SHM_SH_PRTLEN,
++							    &__b43legacy_ratetable[3]);
++			wl->beacon0_uploaded = 1;
++		}
++		cmd |= B43legacy_MACCMD_BEACON0_VALID;
++	}
++	if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) {
++		if (!wl->beacon1_uploaded) {
++			b43legacy_write_beacon_template(dev, 0x468,
++							B43legacy_SHM_SH_BTL1,
++							B43legacy_CCK_RATE_1MB);
++			wl->beacon1_uploaded = 1;
++		}
++		cmd |= B43legacy_MACCMD_BEACON1_VALID;
+ 	}
++	b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+ }
+ 
+ static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
+@@ -2552,14 +2580,16 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+ 	antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
+ 
+ 	mutex_lock(&wl->mutex);
++	dev = wl->current_dev;
++	phy = &dev->phy;
+ 
+ 	/* Switch the PHY mode (if necessary). */
+-	switch (conf->phymode) {
+-	case MODE_IEEE80211B:
+-		new_phymode = B43legacy_PHYMODE_B;
+-		break;
+-	case MODE_IEEE80211G:
+-		new_phymode = B43legacy_PHYMODE_G;
++	switch (conf->channel->band) {
++	case IEEE80211_BAND_2GHZ:
++		if (phy->type == B43legacy_PHYTYPE_B)
++			new_phymode = B43legacy_PHYMODE_B;
++		else
++			new_phymode = B43legacy_PHYMODE_G;
+ 		break;
+ 	default:
+ 		B43legacy_WARN_ON(1);
+@@ -2567,8 +2597,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+ 	err = b43legacy_switch_phymode(wl, new_phymode);
+ 	if (err)
+ 		goto out_unlock_mutex;
+-	dev = wl->current_dev;
+-	phy = &dev->phy;
+ 
+ 	/* Disable IRQs while reconfiguring the device.
+ 	 * This makes it possible to drop the spinlock throughout
+@@ -2584,8 +2612,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+ 
+ 	/* Switch to the requested channel.
+ 	 * The firmware takes care of races with the TX handler. */
+-	if (conf->channel_val != phy->channel)
+-		b43legacy_radio_selectchannel(dev, conf->channel_val, 0);
++	if (conf->channel->hw_value != phy->channel)
++		b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
+ 
+ 	/* Enable/Disable ShortSlot timing. */
+ 	if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME))
+@@ -2702,7 +2730,7 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
+ 			B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
+ 			b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
+ 			if (conf->beacon)
+-				b43legacy_refresh_templates(dev, conf->beacon);
++				b43legacy_update_templates(wl, conf->beacon);
+ 		}
+ 		b43legacy_write_mac_bssid_templates(dev);
+ 	}
+@@ -2920,7 +2948,7 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
+ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
+ {
+ 	/* Flags */
+-	dev->reg124_set_0x4 = 0;
++	dev->dfq_valid = 0;
+ 
+ 	/* Stats */
+ 	memset(&dev->stats, 0, sizeof(dev->stats));
+@@ -2979,6 +3007,34 @@ static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
+ 	b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
+ }
+ 
++static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
++					  bool idle) {
++	u16 pu_delay = 1050;
++
++	if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
++		pu_delay = 500;
++	if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
++		pu_delay = max(pu_delay, (u16)2400);
++
++	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
++			      B43legacy_SHM_SH_SPUWKUP, pu_delay);
++}
++
++/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
++static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
++{
++	u16 pretbtt;
++
++	/* The time value is in microseconds. */
++	if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
++		pretbtt = 2;
++	else
++		pretbtt = 250;
++	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
++			      B43legacy_SHM_SH_PRETBTT, pretbtt);
++	b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt);
++}
++
+ /* Shutdown a wireless core */
+ /* Locking: wl->mutex */
+ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
+@@ -3015,6 +3071,11 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
+ 		kfree(phy->tssi2dbm);
+ 	kfree(phy->lo_control);
+ 	phy->lo_control = NULL;
++	if (dev->wl->current_beacon) {
++		dev_kfree_skb_any(dev->wl->current_beacon);
++		dev->wl->current_beacon = NULL;
++	}
++
+ 	ssb_device_disable(dev->dev, 0);
+ 	ssb_bus_may_powerdown(dev->dev->bus);
+ }
+@@ -3160,9 +3221,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
+ 	if (err)
+ 		goto err_chip_exit;
+ 
+-	b43legacy_write16(dev, 0x0612, 0x0050);
+-	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0416, 0x0050);
+-	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
++	b43legacy_set_synth_pu_delay(dev, 1);
+ 
+ 	ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
+ 	b43legacy_upload_card_macaddress(dev);
+@@ -3218,6 +3277,8 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
+ 
+ 	spin_lock_irqsave(&wl->irq_lock, flags);
+ 	b43legacy_adjust_opmode(dev);
++	b43legacy_set_pretbtt(dev);
++	b43legacy_set_synth_pu_delay(dev, 0);
+ 	b43legacy_upload_card_macaddress(dev);
+ 	spin_unlock_irqrestore(&wl->irq_lock, flags);
+ 
+@@ -3339,6 +3400,41 @@ out_unlock:
+ 	return err;
+ }
+ 
++static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
++				       int aid, int set)
++{
++	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
++	struct sk_buff *beacon;
++	unsigned long flags;
++
++	/* We could modify the existing beacon and set the aid bit in the TIM
++	 * field, but that would probably require resizing and moving of data
++	 * within the beacon template. Simply request a new beacon and let
++	 * mac80211 do the hard work. */
++	beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
++	if (unlikely(!beacon))
++		return -ENOMEM;
++	spin_lock_irqsave(&wl->irq_lock, flags);
++	b43legacy_update_templates(wl, beacon);
++	spin_unlock_irqrestore(&wl->irq_lock, flags);
++
++	return 0;
++}
++
++static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
++					   struct sk_buff *beacon,
++					   struct ieee80211_tx_control *ctl)
++{
++	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
++	unsigned long flags;
++
++	spin_lock_irqsave(&wl->irq_lock, flags);
++	b43legacy_update_templates(wl, beacon);
++	spin_unlock_irqrestore(&wl->irq_lock, flags);
++
++	return 0;
++}
++
+ static const struct ieee80211_ops b43legacy_hw_ops = {
+ 	.tx			= b43legacy_op_tx,
+ 	.conf_tx		= b43legacy_op_conf_tx,
+@@ -3352,6 +3448,8 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
+ 	.start			= b43legacy_op_start,
+ 	.stop			= b43legacy_op_stop,
+ 	.set_retry_limit	= b43legacy_op_set_retry_limit,
++	.set_tim		= b43legacy_op_beacon_set_tim,
++	.beacon_update		= b43legacy_op_ibss_beacon_update,
+ };
+ 
+ /* Hard-reset the chip. Do not call this directly.
+@@ -3400,48 +3498,19 @@ static int b43legacy_setup_modes(struct b43legacy_wldev *dev,
+ 				 int have_gphy)
+ {
+ 	struct ieee80211_hw *hw = dev->wl->hw;
+-	struct ieee80211_hw_mode *mode;
+ 	struct b43legacy_phy *phy = &dev->phy;
+-	int cnt = 0;
+-	int err;
+ 
+ 	phy->possible_phymodes = 0;
+-	for (; 1; cnt++) {
+-		if (have_bphy) {
+-			B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
+-			mode = &phy->hwmodes[cnt];
+-
+-			mode->mode = MODE_IEEE80211B;
+-			mode->num_channels = b43legacy_bg_chantable_size;
+-			mode->channels = b43legacy_bg_chantable;
+-			mode->num_rates = b43legacy_b_ratetable_size;
+-			mode->rates = b43legacy_b_ratetable;
+-			err = ieee80211_register_hwmode(hw, mode);
+-			if (err)
+-				return err;
+-
+-			phy->possible_phymodes |= B43legacy_PHYMODE_B;
+-			have_bphy = 0;
+-			continue;
+-		}
+-		if (have_gphy) {
+-			B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
+-			mode = &phy->hwmodes[cnt];
+-
+-			mode->mode = MODE_IEEE80211G;
+-			mode->num_channels = b43legacy_bg_chantable_size;
+-			mode->channels = b43legacy_bg_chantable;
+-			mode->num_rates = b43legacy_g_ratetable_size;
+-			mode->rates = b43legacy_g_ratetable;
+-			err = ieee80211_register_hwmode(hw, mode);
+-			if (err)
+-				return err;
+-
+-			phy->possible_phymodes |= B43legacy_PHYMODE_G;
+-			have_gphy = 0;
+-			continue;
+-		}
+-		break;
++	if (have_bphy) {
++		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++			&b43legacy_band_2GHz_BPHY;
++		phy->possible_phymodes |= B43legacy_PHYMODE_B;
++	}
++
++	if (have_gphy) {
++		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++			&b43legacy_band_2GHz_GPHY;
++		phy->possible_phymodes |= B43legacy_PHYMODE_G;
+ 	}
+ 
+ 	return 0;
+diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
+index d84408a..dcad249 100644
+--- a/drivers/net/wireless/b43legacy/xmit.c
++++ b/drivers/net/wireless/b43legacy/xmit.c
+@@ -37,45 +37,48 @@
+ 
+ 
+ /* Extract the bitrate out of a CCK PLCP header. */
+-static u8 b43legacy_plcp_get_bitrate_cck(struct b43legacy_plcp_hdr6 *plcp)
++static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp)
+ {
+ 	switch (plcp->raw[0]) {
+ 	case 0x0A:
+-		return B43legacy_CCK_RATE_1MB;
++		return 0;
+ 	case 0x14:
+-		return B43legacy_CCK_RATE_2MB;
++		return 1;
+ 	case 0x37:
+-		return B43legacy_CCK_RATE_5MB;
++		return 2;
+ 	case 0x6E:
+-		return B43legacy_CCK_RATE_11MB;
++		return 3;
+ 	}
+ 	B43legacy_BUG_ON(1);
+-	return 0;
++	return -1;
+ }
+ 
+ /* Extract the bitrate out of an OFDM PLCP header. */
+-static u8 b43legacy_plcp_get_bitrate_ofdm(struct b43legacy_plcp_hdr6 *plcp)
++static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp,
++					      bool aphy)
+ {
++	int base = aphy ? 0 : 4;
++
+ 	switch (plcp->raw[0] & 0xF) {
+ 	case 0xB:
+-		return B43legacy_OFDM_RATE_6MB;
++		return base + 0;
+ 	case 0xF:
+-		return B43legacy_OFDM_RATE_9MB;
++		return base + 1;
+ 	case 0xA:
+-		return B43legacy_OFDM_RATE_12MB;
++		return base + 2;
+ 	case 0xE:
+-		return B43legacy_OFDM_RATE_18MB;
++		return base + 3;
+ 	case 0x9:
+-		return B43legacy_OFDM_RATE_24MB;
++		return base + 4;
+ 	case 0xD:
+-		return B43legacy_OFDM_RATE_36MB;
++		return base + 5;
+ 	case 0x8:
+-		return B43legacy_OFDM_RATE_48MB;
++		return base + 6;
+ 	case 0xC:
+-		return B43legacy_OFDM_RATE_54MB;
++		return base + 7;
+ 	}
+ 	B43legacy_BUG_ON(1);
+-	return 0;
++	return -1;
+ }
+ 
+ u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate)
+@@ -192,7 +195,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+ 	int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
+ 	u16 fctl;
+ 	u8 rate;
+-	u8 rate_fb;
++	struct ieee80211_rate *rate_fb;
+ 	int rate_ofdm;
+ 	int rate_fb_ofdm;
+ 	unsigned int plcp_fragment_len;
+@@ -204,16 +207,16 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+ 
+ 	memset(txhdr, 0, sizeof(*txhdr));
+ 
+-	rate = txctl->tx_rate;
++	rate = txctl->tx_rate->hw_value;
+ 	rate_ofdm = b43legacy_is_ofdm_rate(rate);
+-	rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
+-	rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb);
++	rate_fb = txctl->alt_retry_rate ? : txctl->tx_rate;
++	rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
+ 
+ 	txhdr->mac_frame_ctl = wlhdr->frame_control;
+ 	memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
+ 
+ 	/* Calculate duration for fallback rate */
+-	if ((rate_fb == rate) ||
++	if ((rate_fb->hw_value == rate) ||
+ 	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
+ 	    (wlhdr->duration_id == cpu_to_le16(0))) {
+ 		/* If the fallback rate equals the normal rate or the
+@@ -221,11 +224,10 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+ 		 * use the original dur_id field. */
+ 		txhdr->dur_fb = wlhdr->duration_id;
+ 	} else {
+-		int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb);
+ 		txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
+ 							 txctl->vif,
+ 							 fragment_len,
+-							 fbrate_base100kbps);
++							 rate_fb);
+ 	}
+ 
+ 	plcp_fragment_len = fragment_len + FCS_LEN;
+@@ -266,7 +268,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+ 				    rate);
+ 	b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
+ 				    (&txhdr->plcp_fb), plcp_fragment_len,
+-				    rate_fb);
++				    rate_fb->hw_value);
+ 
+ 	/* PHY TX Control word */
+ 	if (rate_ofdm)
+@@ -310,7 +312,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+ 		int rts_rate_ofdm;
+ 		int rts_rate_fb_ofdm;
+ 
+-		rts_rate = txctl->rts_cts_rate;
++		rts_rate = txctl->rts_cts_rate->hw_value;
+ 		rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
+ 		rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
+ 		rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
+@@ -536,19 +538,24 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
+ 				      (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
+ 	status.noise = dev->stats.link_noise;
+ 	status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI;
++	/* change to support A PHY */
+ 	if (phystat0 & B43legacy_RX_PHYST0_OFDM)
+-		status.rate = b43legacy_plcp_get_bitrate_ofdm(plcp);
++		status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
+ 	else
+-		status.rate = b43legacy_plcp_get_bitrate_cck(plcp);
++		status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp);
+ 	status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
+ 
+ 	/*
+-	 * If monitors are present get full 64-bit timestamp. This
+-	 * code assumes we get to process the packet within 16 bits
+-	 * of timestamp, i.e. about 65 milliseconds after the PHY
+-	 * received the first symbol.
++	 * All frames on monitor interfaces and beacons always need a full
++	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
++	 * purposes and beacons for IBSS merging.
++	 * This code assumes we get to process the packet within 16 bits
++	 * of timestamp, i.e. about 65 milliseconds after the PHY received
++	 * the first symbol.
+ 	 */
+-	if (dev->wl->radiotap_enabled) {
++	if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
++	    == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
++	    dev->wl->radiotap_enabled) {
+ 		u16 low_mactime_now;
+ 
+ 		b43legacy_tsf_read(dev, &status.mactime);
+@@ -564,14 +571,9 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
+ 		  B43legacy_RX_CHAN_ID_SHIFT;
+ 	switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) {
+ 	case B43legacy_PHYTYPE_B:
+-		status.phymode = MODE_IEEE80211B;
+-		status.freq = chanid + 2400;
+-		status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
+-		break;
+ 	case B43legacy_PHYTYPE_G:
+-		status.phymode = MODE_IEEE80211G;
++		status.band = IEEE80211_BAND_2GHZ;
+ 		status.freq = chanid + 2400;
+-		status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
+ 		break;
+ 	default:
+ 		b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
+diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
+deleted file mode 100644
+index afb8f43..0000000
+--- a/drivers/net/wireless/bcm43xx/Kconfig
++++ /dev/null
+@@ -1,70 +0,0 @@
+-config BCM43XX
+-	tristate "Broadcom BCM43xx wireless support (DEPRECATED)"
+-	depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && WLAN_80211 && (!SSB_B43_PCI_BRIDGE || SSB != y) && EXPERIMENTAL
+-	select WIRELESS_EXT
+-	select FW_LOADER
+-	select HW_RANDOM
+-	---help---
+-	  This is an experimental driver for the Broadcom 43xx wireless
+-	  chip, found in the Apple Airport Extreme and various other
+-	  devices.  This driver is deprecated and will be removed
+-	  from the kernel in the near future.  It has been replaced
+-	  by the b43 and b43legacy drivers.
+-
+-config BCM43XX_DEBUG
+-	bool "Broadcom BCM43xx debugging (RECOMMENDED)"
+-	depends on BCM43XX
+-	default y
+-	---help---
+-	  Broadcom 43xx debugging messages.
+-	  Say Y, because the driver is still very experimental and
+-	  this will help you get it running.
+-
+-config BCM43XX_DMA
+-	bool
+-	depends on BCM43XX
+-
+-config BCM43XX_PIO
+-	bool
+-	depends on BCM43XX
+-
+-choice
+-	prompt "BCM43xx data transfer mode"
+-	depends on BCM43XX
+-	default BCM43XX_DMA_AND_PIO_MODE
+-
+-config BCM43XX_DMA_AND_PIO_MODE
+-	bool "DMA + PIO"
+-	select BCM43XX_DMA
+-	select BCM43XX_PIO
+-	---help---
+-	  Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
+-	  data transfer modes.
+-	  The actually used mode is selectable through the module
+-	  parameter "pio". If the module parameter is pio=0, DMA is used.
+-	  Otherwise PIO is used. DMA is default.
+-
+-	  If unsure, choose this option.
+-
+-config BCM43XX_DMA_MODE
+-	bool "DMA (Direct Memory Access) only"
+-	select BCM43XX_DMA
+-	---help---
+-	  Only include Direct Memory Access (DMA).
+-	  This reduces the size of the driver module, by omitting the PIO code.
+-
+-config BCM43XX_PIO_MODE
+-	bool "PIO (Programmed I/O) only"
+-	select BCM43XX_PIO
+-	---help---
+-	  Only include Programmed I/O (PIO).
+-	  This reduces the size of the driver module, by omitting the DMA code.
+-	  Please note that PIO transfers are slow (compared to DMA).
+-
+-	  Also note that not all devices of the 43xx series support PIO.
+-	  The 4306 (Apple Airport Extreme and others) supports PIO, while
+-	  the 4318 is known to _not_ support PIO.
+-
+-	  Only use PIO, if DMA does not work for you.
+-
+-endchoice
+diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile
+deleted file mode 100644
+index bb5220c..0000000
+--- a/drivers/net/wireless/bcm43xx/Makefile
++++ /dev/null
+@@ -1,12 +0,0 @@
+-obj-$(CONFIG_BCM43XX) += bcm43xx.o
+-bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o
+-
+-bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o
+-bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o
+-
+-bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \
+-		bcm43xx_radio.o bcm43xx_phy.o \
+-		bcm43xx_power.o bcm43xx_wx.o \
+-		bcm43xx_leds.o bcm43xx_ethtool.o \
+-		bcm43xx_xmit.o bcm43xx_sysfs.o \
+-		$(bcm43xx-obj-y)
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
+deleted file mode 100644
+index 2ebd2ed..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
++++ /dev/null
+@@ -1,997 +0,0 @@
+-#ifndef BCM43xx_H_
+-#define BCM43xx_H_
+-
+-#include <linux/hw_random.h>
+-#include <linux/version.h>
+-#include <linux/kernel.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-#include <linux/stringify.h>
+-#include <linux/pci.h>
+-#include <net/ieee80211.h>
+-#include <net/ieee80211softmac.h>
+-#include <asm/atomic.h>
+-#include <asm/io.h>
+-
+-
+-#include "bcm43xx_debugfs.h"
+-#include "bcm43xx_leds.h"
+-
+-
+-#define PFX				KBUILD_MODNAME ": "
+-
+-#define BCM43xx_SWITCH_CORE_MAX_RETRIES	50
+-#define BCM43xx_IRQWAIT_MAX_RETRIES	100
+-
+-#define BCM43xx_IO_SIZE			8192
+-
+-/* Active Core PCI Configuration Register. */
+-#define BCM43xx_PCICFG_ACTIVE_CORE	0x80
+-/* SPROM control register. */
+-#define BCM43xx_PCICFG_SPROMCTL		0x88
+-/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */
+-#define BCM43xx_PCICFG_ICR		0x94
+-
+-/* MMIO offsets */
+-#define BCM43xx_MMIO_DMA0_REASON	0x20
+-#define BCM43xx_MMIO_DMA0_IRQ_MASK	0x24
+-#define BCM43xx_MMIO_DMA1_REASON	0x28
+-#define BCM43xx_MMIO_DMA1_IRQ_MASK	0x2C
+-#define BCM43xx_MMIO_DMA2_REASON	0x30
+-#define BCM43xx_MMIO_DMA2_IRQ_MASK	0x34
+-#define BCM43xx_MMIO_DMA3_REASON	0x38
+-#define BCM43xx_MMIO_DMA3_IRQ_MASK	0x3C
+-#define BCM43xx_MMIO_DMA4_REASON	0x40
+-#define BCM43xx_MMIO_DMA4_IRQ_MASK	0x44
+-#define BCM43xx_MMIO_DMA5_REASON	0x48
+-#define BCM43xx_MMIO_DMA5_IRQ_MASK	0x4C
+-#define BCM43xx_MMIO_STATUS_BITFIELD	0x120
+-#define BCM43xx_MMIO_STATUS2_BITFIELD	0x124
+-#define BCM43xx_MMIO_GEN_IRQ_REASON	0x128
+-#define BCM43xx_MMIO_GEN_IRQ_MASK	0x12C
+-#define BCM43xx_MMIO_RAM_CONTROL	0x130
+-#define BCM43xx_MMIO_RAM_DATA		0x134
+-#define BCM43xx_MMIO_PS_STATUS		0x140
+-#define BCM43xx_MMIO_RADIO_HWENABLED_HI	0x158
+-#define BCM43xx_MMIO_SHM_CONTROL	0x160
+-#define BCM43xx_MMIO_SHM_DATA		0x164
+-#define BCM43xx_MMIO_SHM_DATA_UNALIGNED	0x166
+-#define BCM43xx_MMIO_XMITSTAT_0		0x170
+-#define BCM43xx_MMIO_XMITSTAT_1		0x174
+-#define BCM43xx_MMIO_REV3PLUS_TSF_LOW	0x180 /* core rev >= 3 only */
+-#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH	0x184 /* core rev >= 3 only */
+-
+-/* 32-bit DMA */
+-#define BCM43xx_MMIO_DMA32_BASE0	0x200
+-#define BCM43xx_MMIO_DMA32_BASE1	0x220
+-#define BCM43xx_MMIO_DMA32_BASE2	0x240
+-#define BCM43xx_MMIO_DMA32_BASE3	0x260
+-#define BCM43xx_MMIO_DMA32_BASE4	0x280
+-#define BCM43xx_MMIO_DMA32_BASE5	0x2A0
+-/* 64-bit DMA */
+-#define BCM43xx_MMIO_DMA64_BASE0	0x200
+-#define BCM43xx_MMIO_DMA64_BASE1	0x240
+-#define BCM43xx_MMIO_DMA64_BASE2	0x280
+-#define BCM43xx_MMIO_DMA64_BASE3	0x2C0
+-#define BCM43xx_MMIO_DMA64_BASE4	0x300
+-#define BCM43xx_MMIO_DMA64_BASE5	0x340
+-/* PIO */
+-#define BCM43xx_MMIO_PIO1_BASE		0x300
+-#define BCM43xx_MMIO_PIO2_BASE		0x310
+-#define BCM43xx_MMIO_PIO3_BASE		0x320
+-#define BCM43xx_MMIO_PIO4_BASE		0x330
+-
+-#define BCM43xx_MMIO_PHY_VER		0x3E0
+-#define BCM43xx_MMIO_PHY_RADIO		0x3E2
+-#define BCM43xx_MMIO_ANTENNA		0x3E8
+-#define BCM43xx_MMIO_CHANNEL		0x3F0
+-#define BCM43xx_MMIO_CHANNEL_EXT	0x3F4
+-#define BCM43xx_MMIO_RADIO_CONTROL	0x3F6
+-#define BCM43xx_MMIO_RADIO_DATA_HIGH	0x3F8
+-#define BCM43xx_MMIO_RADIO_DATA_LOW	0x3FA
+-#define BCM43xx_MMIO_PHY_CONTROL	0x3FC
+-#define BCM43xx_MMIO_PHY_DATA		0x3FE
+-#define BCM43xx_MMIO_MACFILTER_CONTROL	0x420
+-#define BCM43xx_MMIO_MACFILTER_DATA	0x422
+-#define BCM43xx_MMIO_RADIO_HWENABLED_LO	0x49A
+-#define BCM43xx_MMIO_GPIO_CONTROL	0x49C
+-#define BCM43xx_MMIO_GPIO_MASK		0x49E
+-#define BCM43xx_MMIO_TSF_0		0x632 /* core rev < 3 only */
+-#define BCM43xx_MMIO_TSF_1		0x634 /* core rev < 3 only */
+-#define BCM43xx_MMIO_TSF_2		0x636 /* core rev < 3 only */
+-#define BCM43xx_MMIO_TSF_3		0x638 /* core rev < 3 only */
+-#define BCM43xx_MMIO_RNG		0x65A
+-#define BCM43xx_MMIO_POWERUP_DELAY	0x6A8
+-
+-/* SPROM offsets. */
+-#define BCM43xx_SPROM_BASE		0x1000
+-#define BCM43xx_SPROM_BOARDFLAGS2	0x1c
+-#define BCM43xx_SPROM_IL0MACADDR	0x24
+-#define BCM43xx_SPROM_ET0MACADDR	0x27
+-#define BCM43xx_SPROM_ET1MACADDR	0x2a
+-#define BCM43xx_SPROM_ETHPHY		0x2d
+-#define BCM43xx_SPROM_BOARDREV		0x2e
+-#define BCM43xx_SPROM_PA0B0		0x2f
+-#define BCM43xx_SPROM_PA0B1		0x30
+-#define BCM43xx_SPROM_PA0B2		0x31
+-#define BCM43xx_SPROM_WL0GPIO0		0x32
+-#define BCM43xx_SPROM_WL0GPIO2		0x33
+-#define BCM43xx_SPROM_MAXPWR		0x34
+-#define BCM43xx_SPROM_PA1B0		0x35
+-#define BCM43xx_SPROM_PA1B1		0x36
+-#define BCM43xx_SPROM_PA1B2		0x37
+-#define BCM43xx_SPROM_IDL_TSSI_TGT	0x38
+-#define BCM43xx_SPROM_BOARDFLAGS	0x39
+-#define BCM43xx_SPROM_ANTENNA_GAIN	0x3a
+-#define BCM43xx_SPROM_VERSION		0x3f
+-
+-/* BCM43xx_SPROM_BOARDFLAGS values */
+-#define BCM43xx_BFL_BTCOEXIST		0x0001 /* implements Bluetooth coexistance */
+-#define BCM43xx_BFL_PACTRL		0x0002 /* GPIO 9 controlling the PA */
+-#define BCM43xx_BFL_AIRLINEMODE		0x0004 /* implements GPIO 13 radio disable indication */
+-#define BCM43xx_BFL_RSSI		0x0008 /* software calculates nrssi slope. */
+-#define BCM43xx_BFL_ENETSPI		0x0010 /* has ephy roboswitch spi */
+-#define BCM43xx_BFL_XTAL_NOSLOW		0x0020 /* no slow clock available */
+-#define BCM43xx_BFL_CCKHIPWR		0x0040 /* can do high power CCK transmission */
+-#define BCM43xx_BFL_ENETADM		0x0080 /* has ADMtek switch */
+-#define BCM43xx_BFL_ENETVLAN		0x0100 /* can do vlan */
+-#define BCM43xx_BFL_AFTERBURNER		0x0200 /* supports Afterburner mode */
+-#define BCM43xx_BFL_NOPCI		0x0400 /* leaves PCI floating */
+-#define BCM43xx_BFL_FEM			0x0800 /* supports the Front End Module */
+-#define BCM43xx_BFL_EXTLNA		0x1000 /* has an external LNA */
+-#define BCM43xx_BFL_HGPA		0x2000 /* had high gain PA */
+-#define BCM43xx_BFL_BTCMOD		0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
+-#define BCM43xx_BFL_ALTIQ		0x8000 /* alternate I/Q settings */
+-
+-/* GPIO register offset, in both ChipCommon and PCI core. */
+-#define BCM43xx_GPIO_CONTROL		0x6c
+-
+-/* SHM Routing */
+-#define BCM43xx_SHM_SHARED		0x0001
+-#define BCM43xx_SHM_WIRELESS		0x0002
+-#define BCM43xx_SHM_PCM			0x0003
+-#define BCM43xx_SHM_HWMAC		0x0004
+-#define BCM43xx_SHM_UCODE		0x0300
+-
+-/* MacFilter offsets. */
+-#define BCM43xx_MACFILTER_SELF		0x0000
+-#define BCM43xx_MACFILTER_ASSOC		0x0003
+-
+-/* Chipcommon registers. */
+-#define BCM43xx_CHIPCOMMON_CAPABILITIES 	0x04
+-#define BCM43xx_CHIPCOMMON_CTL			0x28
+-#define BCM43xx_CHIPCOMMON_PLLONDELAY		0xB0
+-#define BCM43xx_CHIPCOMMON_FREFSELDELAY		0xB4
+-#define BCM43xx_CHIPCOMMON_SLOWCLKCTL		0xB8
+-#define BCM43xx_CHIPCOMMON_SYSCLKCTL		0xC0
+-
+-/* PCI core specific registers. */
+-#define BCM43xx_PCICORE_BCAST_ADDR	0x50
+-#define BCM43xx_PCICORE_BCAST_DATA	0x54
+-#define BCM43xx_PCICORE_SBTOPCI2	0x108
+-
+-/* SBTOPCI2 values. */
+-#define BCM43xx_SBTOPCI2_PREFETCH	0x4
+-#define BCM43xx_SBTOPCI2_BURST		0x8
+-#define BCM43xx_SBTOPCI2_MEMREAD_MULTI	0x20
+-
+-/* PCI-E core registers. */
+-#define BCM43xx_PCIECORE_REG_ADDR      0x0130
+-#define BCM43xx_PCIECORE_REG_DATA      0x0134
+-#define BCM43xx_PCIECORE_MDIO_CTL      0x0128
+-#define BCM43xx_PCIECORE_MDIO_DATA     0x012C
+-
+-/* PCI-E registers. */
+-#define BCM43xx_PCIE_TLP_WORKAROUND    0x0004
+-#define BCM43xx_PCIE_DLLP_LINKCTL      0x0100
+-
+-/* PCI-E MDIO bits. */
+-#define BCM43xx_PCIE_MDIO_ST   0x40000000
+-#define BCM43xx_PCIE_MDIO_WT   0x10000000
+-#define BCM43xx_PCIE_MDIO_DEV  22
+-#define BCM43xx_PCIE_MDIO_REG  18
+-#define BCM43xx_PCIE_MDIO_TA   0x00020000
+-#define BCM43xx_PCIE_MDIO_TC   0x0100
+-
+-/* MDIO devices. */
+-#define BCM43xx_MDIO_SERDES_RX	0x1F
+-
+-/* SERDES RX registers. */
+-#define BCM43xx_SERDES_RXTIMER	0x2
+-#define BCM43xx_SERDES_CDR	0x6
+-#define BCM43xx_SERDES_CDR_BW	0x7
+-
+-/* Chipcommon capabilities. */
+-#define BCM43xx_CAPABILITIES_PCTL		0x00040000
+-#define BCM43xx_CAPABILITIES_PLLMASK		0x00030000
+-#define BCM43xx_CAPABILITIES_PLLSHIFT		16
+-#define BCM43xx_CAPABILITIES_FLASHMASK		0x00000700
+-#define BCM43xx_CAPABILITIES_FLASHSHIFT		8
+-#define BCM43xx_CAPABILITIES_EXTBUSPRESENT	0x00000040
+-#define BCM43xx_CAPABILITIES_UARTGPIO		0x00000020
+-#define BCM43xx_CAPABILITIES_UARTCLOCKMASK	0x00000018
+-#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT	3
+-#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN	0x00000004
+-#define BCM43xx_CAPABILITIES_NRUARTSMASK	0x00000003
+-
+-/* PowerControl */
+-#define BCM43xx_PCTL_IN			0xB0
+-#define BCM43xx_PCTL_OUT		0xB4
+-#define BCM43xx_PCTL_OUTENABLE		0xB8
+-#define BCM43xx_PCTL_XTAL_POWERUP	0x40
+-#define BCM43xx_PCTL_PLL_POWERDOWN	0x80
+-
+-/* PowerControl Clock Modes */
+-#define BCM43xx_PCTL_CLK_FAST		0x00
+-#define BCM43xx_PCTL_CLK_SLOW		0x01
+-#define BCM43xx_PCTL_CLK_DYNAMIC	0x02
+-
+-#define BCM43xx_PCTL_FORCE_SLOW		0x0800
+-#define BCM43xx_PCTL_FORCE_PLL		0x1000
+-#define BCM43xx_PCTL_DYN_XTAL		0x2000
+-
+-/* COREIDs */
+-#define BCM43xx_COREID_CHIPCOMMON	0x800
+-#define BCM43xx_COREID_ILINE20          0x801
+-#define BCM43xx_COREID_SDRAM            0x803
+-#define BCM43xx_COREID_PCI		0x804
+-#define BCM43xx_COREID_MIPS             0x805
+-#define BCM43xx_COREID_ETHERNET         0x806
+-#define BCM43xx_COREID_V90		0x807
+-#define BCM43xx_COREID_USB11_HOSTDEV    0x80a
+-#define BCM43xx_COREID_IPSEC            0x80b
+-#define BCM43xx_COREID_PCMCIA		0x80d
+-#define BCM43xx_COREID_EXT_IF           0x80f
+-#define BCM43xx_COREID_80211		0x812
+-#define BCM43xx_COREID_MIPS_3302        0x816
+-#define BCM43xx_COREID_USB11_HOST       0x817
+-#define BCM43xx_COREID_USB11_DEV        0x818
+-#define BCM43xx_COREID_USB20_HOST       0x819
+-#define BCM43xx_COREID_USB20_DEV        0x81a
+-#define BCM43xx_COREID_SDIO_HOST        0x81b
+-#define BCM43xx_COREID_PCIE		0x820
+-
+-/* Core Information Registers */
+-#define BCM43xx_CIR_BASE		0xf00
+-#define BCM43xx_CIR_SBTPSFLAG		(BCM43xx_CIR_BASE + 0x18)
+-#define BCM43xx_CIR_SBIMSTATE		(BCM43xx_CIR_BASE + 0x90)
+-#define BCM43xx_CIR_SBINTVEC		(BCM43xx_CIR_BASE + 0x94)
+-#define BCM43xx_CIR_SBTMSTATELOW	(BCM43xx_CIR_BASE + 0x98)
+-#define BCM43xx_CIR_SBTMSTATEHIGH	(BCM43xx_CIR_BASE + 0x9c)
+-#define BCM43xx_CIR_SBIMCONFIGLOW	(BCM43xx_CIR_BASE + 0xa8)
+-#define BCM43xx_CIR_SB_ID_HI		(BCM43xx_CIR_BASE + 0xfc)
+-
+-/* Mask to get the Backplane Flag Number from SBTPSFLAG. */
+-#define BCM43xx_BACKPLANE_FLAG_NR_MASK	0x3f
+-
+-/* SBIMCONFIGLOW values/masks. */
+-#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK		0x00000007
+-#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT	0
+-#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK		0x00000070
+-#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT	4
+-#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK		0x00ff0000
+-#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT		16
+-
+-/* sbtmstatelow state flags */
+-#define BCM43xx_SBTMSTATELOW_RESET		0x01
+-#define BCM43xx_SBTMSTATELOW_REJECT		0x02
+-#define BCM43xx_SBTMSTATELOW_CLOCK		0x10000
+-#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK	0x20000
+-#define BCM43xx_SBTMSTATELOW_G_MODE_ENABLE	0x20000000
+-
+-/* sbtmstatehigh state flags */
+-#define BCM43xx_SBTMSTATEHIGH_SERROR		0x00000001
+-#define BCM43xx_SBTMSTATEHIGH_BUSY		0x00000004
+-#define BCM43xx_SBTMSTATEHIGH_TIMEOUT		0x00000020
+-#define BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL	0x00010000
+-#define BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL	0x00020000
+-#define BCM43xx_SBTMSTATEHIGH_COREFLAGS		0x1FFF0000
+-#define BCM43xx_SBTMSTATEHIGH_DMA64BIT		0x10000000
+-#define BCM43xx_SBTMSTATEHIGH_GATEDCLK		0x20000000
+-#define BCM43xx_SBTMSTATEHIGH_BISTFAILED	0x40000000
+-#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE	0x80000000
+-
+-/* sbimstate flags */
+-#define BCM43xx_SBIMSTATE_IB_ERROR		0x20000
+-#define BCM43xx_SBIMSTATE_TIMEOUT		0x40000
+-
+-/* PHYVersioning */
+-#define BCM43xx_PHYTYPE_A		0x00
+-#define BCM43xx_PHYTYPE_B		0x01
+-#define BCM43xx_PHYTYPE_G		0x02
+-
+-/* PHYRegisters */
+-#define BCM43xx_PHY_ILT_A_CTRL		0x0072
+-#define BCM43xx_PHY_ILT_A_DATA1		0x0073
+-#define BCM43xx_PHY_ILT_A_DATA2		0x0074
+-#define BCM43xx_PHY_G_LO_CONTROL	0x0810
+-#define BCM43xx_PHY_ILT_G_CTRL		0x0472
+-#define BCM43xx_PHY_ILT_G_DATA1		0x0473
+-#define BCM43xx_PHY_ILT_G_DATA2		0x0474
+-#define BCM43xx_PHY_A_PCTL		0x007B
+-#define BCM43xx_PHY_G_PCTL		0x0029
+-#define BCM43xx_PHY_A_CRS		0x0029
+-#define BCM43xx_PHY_RADIO_BITFIELD	0x0401
+-#define BCM43xx_PHY_G_CRS		0x0429
+-#define BCM43xx_PHY_NRSSILT_CTRL	0x0803
+-#define BCM43xx_PHY_NRSSILT_DATA	0x0804
+-
+-/* RadioRegisters */
+-#define BCM43xx_RADIOCTL_ID		0x01
+-
+-/* StatusBitField */
+-#define BCM43xx_SBF_MAC_ENABLED		0x00000001
+-#define BCM43xx_SBF_2			0x00000002 /*FIXME: fix name*/
+-#define BCM43xx_SBF_CORE_READY		0x00000004
+-#define BCM43xx_SBF_400			0x00000400 /*FIXME: fix name*/
+-#define BCM43xx_SBF_4000		0x00004000 /*FIXME: fix name*/
+-#define BCM43xx_SBF_8000		0x00008000 /*FIXME: fix name*/
+-#define BCM43xx_SBF_XFER_REG_BYTESWAP	0x00010000
+-#define BCM43xx_SBF_MODE_NOTADHOC	0x00020000
+-#define BCM43xx_SBF_MODE_AP		0x00040000
+-#define BCM43xx_SBF_RADIOREG_LOCK	0x00080000
+-#define BCM43xx_SBF_MODE_MONITOR	0x00400000
+-#define BCM43xx_SBF_MODE_PROMISC	0x01000000
+-#define BCM43xx_SBF_PS1			0x02000000
+-#define BCM43xx_SBF_PS2			0x04000000
+-#define BCM43xx_SBF_NO_SSID_BCAST	0x08000000
+-#define BCM43xx_SBF_TIME_UPDATE		0x10000000
+-#define BCM43xx_SBF_MODE_G		0x80000000
+-
+-/* Microcode */
+-#define BCM43xx_UCODE_REVISION		0x0000
+-#define BCM43xx_UCODE_PATCHLEVEL	0x0002
+-#define BCM43xx_UCODE_DATE		0x0004
+-#define BCM43xx_UCODE_TIME		0x0006
+-#define BCM43xx_UCODE_STATUS		0x0040
+-
+-/* MicrocodeFlagsBitfield (addr + lo-word values?)*/
+-#define BCM43xx_UCODEFLAGS_OFFSET	0x005E
+-
+-#define BCM43xx_UCODEFLAG_AUTODIV	0x0001
+-#define BCM43xx_UCODEFLAG_UNKBGPHY	0x0002
+-#define BCM43xx_UCODEFLAG_UNKBPHY	0x0004
+-#define BCM43xx_UCODEFLAG_UNKGPHY	0x0020
+-#define BCM43xx_UCODEFLAG_UNKPACTRL	0x0040
+-#define BCM43xx_UCODEFLAG_JAPAN		0x0080
+-
+-/* Hardware Radio Enable masks */
+-#define BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16)
+-#define BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
+-
+-/* Generic-Interrupt reasons. */
+-#define BCM43xx_IRQ_READY		(1 << 0)
+-#define BCM43xx_IRQ_BEACON		(1 << 1)
+-#define BCM43xx_IRQ_PS			(1 << 2)
+-#define BCM43xx_IRQ_REG124		(1 << 5)
+-#define BCM43xx_IRQ_PMQ			(1 << 6)
+-#define BCM43xx_IRQ_PIO_WORKAROUND	(1 << 8)
+-#define BCM43xx_IRQ_XMIT_ERROR		(1 << 11)
+-#define BCM43xx_IRQ_RX			(1 << 15)
+-#define BCM43xx_IRQ_SCAN		(1 << 16)
+-#define BCM43xx_IRQ_NOISE		(1 << 18)
+-#define BCM43xx_IRQ_XMIT_STATUS		(1 << 29)
+-
+-#define BCM43xx_IRQ_ALL			0xffffffff
+-#define BCM43xx_IRQ_INITIAL		(BCM43xx_IRQ_PS |		\
+-					 BCM43xx_IRQ_REG124 |		\
+-					 BCM43xx_IRQ_PMQ |		\
+-					 BCM43xx_IRQ_XMIT_ERROR |	\
+-					 BCM43xx_IRQ_RX |		\
+-					 BCM43xx_IRQ_SCAN |		\
+-					 BCM43xx_IRQ_NOISE |		\
+-					 BCM43xx_IRQ_XMIT_STATUS)
+-					 
+-
+-/* Initial default iw_mode */
+-#define BCM43xx_INITIAL_IWMODE			IW_MODE_INFRA
+-
+-/* Bus type PCI. */
+-#define BCM43xx_BUSTYPE_PCI	0
+-/* Bus type Silicone Backplane Bus. */
+-#define BCM43xx_BUSTYPE_SB	1
+-/* Bus type PCMCIA. */
+-#define BCM43xx_BUSTYPE_PCMCIA	2
+-
+-/* Threshold values. */
+-#define BCM43xx_MIN_RTS_THRESHOLD		1U
+-#define BCM43xx_MAX_RTS_THRESHOLD		2304U
+-#define BCM43xx_DEFAULT_RTS_THRESHOLD		BCM43xx_MAX_RTS_THRESHOLD
+-
+-#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT	7
+-#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT	4
+-
+-/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
+-#define RX_RSSI_MAX				60
+-
+-/* Max size of a security key */
+-#define BCM43xx_SEC_KEYSIZE			16
+-/* Security algorithms. */
+-enum {
+-	BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
+-	BCM43xx_SEC_ALGO_WEP,
+-	BCM43xx_SEC_ALGO_UNKNOWN,
+-	BCM43xx_SEC_ALGO_AES,
+-	BCM43xx_SEC_ALGO_WEP104,
+-	BCM43xx_SEC_ALGO_TKIP,
+-};
+-
+-#ifdef assert
+-# undef assert
+-#endif
+-#ifdef CONFIG_BCM43XX_DEBUG
+-#define assert(expr) \
+-	do {									\
+-		if (unlikely(!(expr))) {					\
+-		printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n",	\
+-			#expr, __FILE__, __LINE__, __FUNCTION__);		\
+-		}								\
+-	} while (0)
+-#else
+-#define assert(expr)	do { /* nothing */ } while (0)
+-#endif
+-
+-/* rate limited printk(). */
+-#ifdef printkl
+-# undef printkl
+-#endif
+-#define printkl(f, x...)  do { if (printk_ratelimit()) printk(f ,##x); } while (0)
+-/* rate limited printk() for debugging */
+-#ifdef dprintkl
+-# undef dprintkl
+-#endif
+-#ifdef CONFIG_BCM43XX_DEBUG
+-# define dprintkl		printkl
+-#else
+-# define dprintkl(f, x...)	do { /* nothing */ } while (0)
+-#endif
+-
+-/* Helper macro for if branches.
+- * An if branch marked with this macro is only taken in DEBUG mode.
+- * Example:
+- *	if (DEBUG_ONLY(foo == bar)) {
+- *		do something
+- *	}
+- *	In DEBUG mode, the branch will be taken if (foo == bar).
+- *	In non-DEBUG mode, the branch will never be taken.
+- */
+-#ifdef DEBUG_ONLY
+-# undef DEBUG_ONLY
+-#endif
+-#ifdef CONFIG_BCM43XX_DEBUG
+-# define DEBUG_ONLY(x)	(x)
+-#else
+-# define DEBUG_ONLY(x)	0
+-#endif
+-
+-/* debugging printk() */
+-#ifdef dprintk
+-# undef dprintk
+-#endif
+-#ifdef CONFIG_BCM43XX_DEBUG
+-# define dprintk(f, x...)  do { printk(f ,##x); } while (0)
+-#else
+-# define dprintk(f, x...)  do { /* nothing */ } while (0)
+-#endif
+-
+-
+-struct net_device;
+-struct pci_dev;
+-struct bcm43xx_dmaring;
+-struct bcm43xx_pioqueue;
+-
+-struct bcm43xx_initval {
+-	__be16 offset;
+-	__be16 size;
+-	__be32 value;
+-} __attribute__((__packed__));
+-
+-/* Values for bcm430x_sprominfo.locale */
+-enum {
+-	BCM43xx_LOCALE_WORLD = 0,
+-	BCM43xx_LOCALE_THAILAND,
+-	BCM43xx_LOCALE_ISRAEL,
+-	BCM43xx_LOCALE_JORDAN,
+-	BCM43xx_LOCALE_CHINA,
+-	BCM43xx_LOCALE_JAPAN,
+-	BCM43xx_LOCALE_USA_CANADA_ANZ,
+-	BCM43xx_LOCALE_EUROPE,
+-	BCM43xx_LOCALE_USA_LOW,
+-	BCM43xx_LOCALE_JAPAN_HIGH,
+-	BCM43xx_LOCALE_ALL,
+-	BCM43xx_LOCALE_NONE,
+-};
+-
+-#define BCM43xx_SPROM_SIZE	64 /* in 16-bit words. */
+-struct bcm43xx_sprominfo {
+-	u16 boardflags2;
+-	u8 il0macaddr[6];
+-	u8 et0macaddr[6];
+-	u8 et1macaddr[6];
+-	u8 et0phyaddr:5;
+-	u8 et1phyaddr:5;
+-	u8 boardrev;
+-	u8 locale:4;
+-	u8 antennas_aphy:2;
+-	u8 antennas_bgphy:2;
+-	u16 pa0b0;
+-	u16 pa0b1;
+-	u16 pa0b2;
+-	u8 wl0gpio0;
+-	u8 wl0gpio1;
+-	u8 wl0gpio2;
+-	u8 wl0gpio3;
+-	u8 maxpower_aphy;
+-	u8 maxpower_bgphy;
+-	u16 pa1b0;
+-	u16 pa1b1;
+-	u16 pa1b2;
+-	u8 idle_tssi_tgt_aphy;
+-	u8 idle_tssi_tgt_bgphy;
+-	u16 boardflags;
+-	u16 antennagain_aphy;
+-	u16 antennagain_bgphy;
+-};
+-
+-/* Value pair to measure the LocalOscillator. */
+-struct bcm43xx_lopair {
+-	s8 low;
+-	s8 high;
+-	u8 used:1;
+-};
+-#define BCM43xx_LO_COUNT	(14*4)
+-
+-struct bcm43xx_phyinfo {
+-	/* Hardware Data */
+-	u8 analog;
+-	u8 type;
+-	u8 rev;
+-	u16 antenna_diversity;
+-	u16 savedpctlreg;
+-	u16 minlowsig[2];
+-	u16 minlowsigpos[2];
+-	u8 connected:1,
+-	   calibrated:1,
+-	   is_locked:1, /* used in bcm43xx_phy_{un}lock() */
+-	   dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */
+-	/* LO Measurement Data.
+-	 * Use bcm43xx_get_lopair() to get a value.
+-	 */
+-	struct bcm43xx_lopair *_lo_pairs;
+-
+-	/* TSSI to dBm table in use */
+-	const s8 *tssi2dbm;
+-	/* idle TSSI value */
+-	s8 idle_tssi;
+-
+-	/* Values from bcm43xx_calc_loopback_gain() */
+-	u16 loopback_gain[2];
+-
+-	/* PHY lock for core.rev < 3
+-	 * This lock is only used by bcm43xx_phy_{un}lock()
+-	 */
+-	spinlock_t lock;
+-
+-	/* Firmware. */
+-	const struct firmware *ucode;
+-	const struct firmware *pcm;
+-	const struct firmware *initvals0;
+-	const struct firmware *initvals1;
+-};
+-
+-
+-struct bcm43xx_radioinfo {
+-	u16 manufact;
+-	u16 version;
+-	u8 revision;
+-
+-	/* Desired TX power in dBm Q5.2 */
+-	u16 txpower_desired;
+-	/* TX Power control values. */
+-	union {
+-		/* B/G PHY */
+-		struct {
+-			u16 baseband_atten;
+-			u16 radio_atten;
+-			u16 txctl1;
+-			u16 txctl2;
+-		};
+-		/* A PHY */
+-		struct {
+-			u16 txpwr_offset;
+-		};
+-	};
+-
+-	/* Current Interference Mitigation mode */
+-	int interfmode;
+-	/* Stack of saved values from the Interference Mitigation code.
+-	 * Each value in the stack is layed out as follows:
+-	 * bit 0-11:  offset
+-	 * bit 12-15: register ID
+-	 * bit 16-32: value
+-	 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
+-	 */
+-#define BCM43xx_INTERFSTACK_SIZE	26
+-	u32 interfstack[BCM43xx_INTERFSTACK_SIZE];
+-
+-	/* Saved values from the NRSSI Slope calculation */
+-	s16 nrssi[2];
+-	s32 nrssislope;
+-	/* In memory nrssi lookup table. */
+-	s8 nrssi_lt[64];
+-
+-	/* current channel */
+-	u8 channel;
+-	u8 initial_channel;
+-
+-	u16 lofcal;
+-
+-	u16 initval;
+-
+-	u8 enabled:1;
+-	/* ACI (adjacent channel interference) flags. */
+-	u8 aci_enable:1,
+-	   aci_wlan_automatic:1,
+-	   aci_hw_rssi:1;
+-};
+-
+-/* Data structures for DMA transmission, per 80211 core. */
+-struct bcm43xx_dma {
+-	struct bcm43xx_dmaring *tx_ring0;
+-	struct bcm43xx_dmaring *tx_ring1;
+-	struct bcm43xx_dmaring *tx_ring2;
+-	struct bcm43xx_dmaring *tx_ring3;
+-	struct bcm43xx_dmaring *tx_ring4;
+-	struct bcm43xx_dmaring *tx_ring5;
+-
+-	struct bcm43xx_dmaring *rx_ring0;
+-	struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */
+-};
+-
+-/* Data structures for PIO transmission, per 80211 core. */
+-struct bcm43xx_pio {
+-	struct bcm43xx_pioqueue *queue0;
+-	struct bcm43xx_pioqueue *queue1;
+-	struct bcm43xx_pioqueue *queue2;
+-	struct bcm43xx_pioqueue *queue3;
+-};
+-
+-#define BCM43xx_MAX_80211_CORES		2
+-
+-/* Generic information about a core. */
+-struct bcm43xx_coreinfo {
+-	u8 available:1,
+-	   enabled:1,
+-	   initialized:1;
+-	/** core_rev revision number */
+-	u8 rev;
+-	/** Index number for _switch_core() */
+-	u8 index;
+-	/** core_id ID number */
+-	u16 id;
+-	/** Core-specific data. */
+-	void *priv;
+-};
+-
+-/* Additional information for each 80211 core. */
+-struct bcm43xx_coreinfo_80211 {
+-	/* PHY device. */
+-	struct bcm43xx_phyinfo phy;
+-	/* Radio device. */
+-	struct bcm43xx_radioinfo radio;
+-	union {
+-		/* DMA context. */
+-		struct bcm43xx_dma dma;
+-		/* PIO context. */
+-		struct bcm43xx_pio pio;
+-	};
+-};
+-
+-/* Context information for a noise calculation (Link Quality). */
+-struct bcm43xx_noise_calculation {
+-	struct bcm43xx_coreinfo *core_at_start;
+-	u8 channel_at_start;
+-	u8 calculation_running:1;
+-	u8 nr_samples;
+-	s8 samples[8][4];
+-};
+-
+-struct bcm43xx_stats {
+-	u8 noise;
+-	struct iw_statistics wstats;
+-	/* Store the last TX/RX times here for updating the leds. */
+-	unsigned long last_tx;
+-	unsigned long last_rx;
+-};
+-
+-struct bcm43xx_key {
+-	u8 enabled:1;
+-	u8 algorithm;
+-};
+-
+-/* Driver initialization status. */
+-enum {
+-	BCM43xx_STAT_UNINIT,		/* Uninitialized. */
+-	BCM43xx_STAT_INITIALIZING,	/* init_board() in progress. */
+-	BCM43xx_STAT_INITIALIZED,	/* Fully operational. */
+-	BCM43xx_STAT_SHUTTINGDOWN,	/* free_board() in progress. */
+-	BCM43xx_STAT_RESTARTING,	/* controller_restart() called. */
+-};
+-#define bcm43xx_status(bcm)		atomic_read(&(bcm)->init_status)
+-#define bcm43xx_set_status(bcm, stat)	do {			\
+-		atomic_set(&(bcm)->init_status, (stat));	\
+-		smp_wmb();					\
+-					} while (0)
+-
+-/*    *** THEORY OF LOCKING ***
+- *
+- * We have two different locks in the bcm43xx driver.
+- * => bcm->mutex:    General sleeping mutex. Protects struct bcm43xx_private
+- *                   and the device registers. This mutex does _not_ protect
+- *                   against concurrency from the IRQ handler.
+- * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
+- *
+- * Please note that, if you only take the irq_lock, you are not protected
+- * against concurrency from the periodic work handlers.
+- * Most times you want to take _both_ locks.
+- */
+-
+-struct bcm43xx_private {
+-	struct ieee80211_device *ieee;
+-	struct ieee80211softmac_device *softmac;
+-
+-	struct net_device *net_dev;
+-	struct pci_dev *pci_dev;
+-	unsigned int irq;
+-
+-	void __iomem *mmio_addr;
+-
+-	spinlock_t irq_lock;
+-	struct mutex mutex;
+-
+-	/* Driver initialization status BCM43xx_STAT_*** */
+-	atomic_t init_status;
+-
+-	u16 was_initialized:1,		/* for PCI suspend/resume. */
+-	    __using_pio:1,		/* Internal, use bcm43xx_using_pio(). */
+-	    bad_frames_preempt:1,	/* Use "Bad Frames Preemption" (default off) */
+-	    reg124_set_0x4:1,		/* Some variable to keep track of IRQ stuff. */
+-	    short_preamble:1,		/* TRUE, if short preamble is enabled. */
+-	    firmware_norelease:1,	/* Do not release the firmware. Used on suspend. */
+-	    radio_hw_enable:1;		/* TRUE if radio is hardware enabled */
+-
+-	struct bcm43xx_stats stats;
+-
+-	/* Bus type we are connected to.
+-	 * This is currently always BCM43xx_BUSTYPE_PCI
+-	 */
+-	u8 bustype;
+-	u64 dma_mask;
+-
+-	u16 board_vendor;
+-	u16 board_type;
+-	u16 board_revision;
+-
+-	u16 chip_id;
+-	u8 chip_rev;
+-	u8 chip_package;
+-
+-	struct bcm43xx_sprominfo sprom;
+-#define BCM43xx_NR_LEDS		4
+-	struct bcm43xx_led leds[BCM43xx_NR_LEDS];
+-	spinlock_t leds_lock;
+-
+-	/* The currently active core. */
+-	struct bcm43xx_coreinfo *current_core;
+-	struct bcm43xx_coreinfo *active_80211_core;
+-	/* coreinfo structs for all possible cores follow.
+-	 * Note that a core might not exist.
+-	 * So check the coreinfo flags before using it.
+-	 */
+-	struct bcm43xx_coreinfo core_chipcommon;
+-	struct bcm43xx_coreinfo core_pci;
+-	struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
+-	/* Additional information, specific to the 80211 cores. */
+-	struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
+-	/* Number of available 80211 cores. */
+-	int nr_80211_available;
+-
+-	u32 chipcommon_capabilities;
+-
+-	/* Reason code of the last interrupt. */
+-	u32 irq_reason;
+-	u32 dma_reason[6];
+-	/* saved irq enable/disable state bitfield. */
+-	u32 irq_savedstate;
+-	/* Link Quality calculation context. */
+-	struct bcm43xx_noise_calculation noisecalc;
+-	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
+-	int mac_suspended;
+-
+-	/* Threshold values. */
+-	//TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
+-	u32 rts_threshold;
+-
+-	/* Interrupt Service Routine tasklet (bottom-half) */
+-	struct tasklet_struct isr_tasklet;
+-
+-	/* Periodic tasks */
+-	struct delayed_work periodic_work;
+-	unsigned int periodic_state;
+-
+-	struct work_struct restart_work;
+-
+-	/* Informational stuff. */
+-	char nick[IW_ESSID_MAX_SIZE + 1];
+-
+-	/* encryption/decryption */
+-	u16 security_offset;
+-	struct bcm43xx_key key[54];
+-	u8 default_key_idx;
+-
+-	/* Random Number Generator. */
+-	struct hwrng rng;
+-	char rng_name[20 + 1];
+-
+-	/* Debugging stuff follows. */
+-#ifdef CONFIG_BCM43XX_DEBUG
+-	struct bcm43xx_dfsentry *dfsentry;
+-#endif
+-};
+-
+-
+-static inline
+-struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
+-{
+-	return ieee80211softmac_priv(dev);
+-}
+-
+-struct device;
+-
+-static inline
+-struct bcm43xx_private * dev_to_bcm(struct device *dev)
+-{
+-	struct net_device *net_dev;
+-	struct bcm43xx_private *bcm;
+-
+-	net_dev = dev_get_drvdata(dev);
+-	bcm = bcm43xx_priv(net_dev);
+-
+-	return bcm;
+-}
+-
+-
+-/* Helper function, which returns a boolean.
+- * TRUE, if PIO is used; FALSE, if DMA is used.
+- */
+-#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
+-static inline
+-int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+-{
+-	return bcm->__using_pio;
+-}
+-#elif defined(CONFIG_BCM43XX_DMA)
+-static inline
+-int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+-{
+-	return 0;
+-}
+-#elif defined(CONFIG_BCM43XX_PIO)
+-static inline
+-int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+-{
+-	return 1;
+-}
+-#else
+-# error "Using neither DMA nor PIO? Confused..."
+-#endif
+-
+-/* Helper functions to access data structures private to the 80211 cores.
+- * Note that we _must_ have an 80211 core mapped when calling
+- * any of these functions.
+- */
+-static inline
+-struct bcm43xx_coreinfo_80211 *
+-bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
+-{
+-	assert(bcm->current_core->id == BCM43xx_COREID_80211);
+-	return bcm->current_core->priv;
+-}
+-static inline
+-struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
+-{
+-	assert(bcm43xx_using_pio(bcm));
+-	return &(bcm43xx_current_80211_priv(bcm)->pio);
+-}
+-static inline
+-struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
+-{
+-	assert(!bcm43xx_using_pio(bcm));
+-	return &(bcm43xx_current_80211_priv(bcm)->dma);
+-}
+-static inline
+-struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
+-{
+-	return &(bcm43xx_current_80211_priv(bcm)->phy);
+-}
+-static inline
+-struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
+-{
+-	return &(bcm43xx_current_80211_priv(bcm)->radio);
+-}
+-
+-
+-static inline
+-struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
+-					   u16 radio_attenuation,
+-					   u16 baseband_attenuation)
+-{
+-	return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2));
+-}
+-
+-
+-static inline
+-u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
+-{
+-	return ioread16(bcm->mmio_addr + offset);
+-}
+-
+-static inline
+-void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
+-{
+-	iowrite16(value, bcm->mmio_addr + offset);
+-}
+-
+-static inline
+-u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
+-{
+-	return ioread32(bcm->mmio_addr + offset);
+-}
+-
+-static inline
+-void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
+-{
+-	iowrite32(value, bcm->mmio_addr + offset);
+-}
+-
+-static inline
+-int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value)
+-{
+-	return pci_read_config_word(bcm->pci_dev, offset, value);
+-}
+-
+-static inline
+-int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value)
+-{
+-	return pci_read_config_dword(bcm->pci_dev, offset, value);
+-}
+-
+-static inline
+-int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value)
+-{
+-	return pci_write_config_word(bcm->pci_dev, offset, value);
+-}
+-
+-static inline
+-int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value)
+-{
+-	return pci_write_config_dword(bcm->pci_dev, offset, value);
+-}
+-
+-/** Limit a value between two limits */
+-#ifdef limit_value
+-# undef limit_value
+-#endif
+-#define limit_value(value, min, max)  \
+-	({						\
+-		typeof(value) __value = (value);	\
+-	 	typeof(value) __min = (min);		\
+-	 	typeof(value) __max = (max);		\
+-	 	if (__value < __min)			\
+-	 		__value = __min;		\
+-	 	else if (__value > __max)		\
+-	 		__value = __max;		\
+-	 	__value;				\
+-	})
+-
+-#endif /* BCM43xx_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+deleted file mode 100644
+index 76e9dd8..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
++++ /dev/null
+@@ -1,556 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  debugfs driver debugging code
+-
+-  Copyright (c) 2005 Michael Buesch <mbuesch at freenet.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 <linux/fs.h>
+-#include <linux/debugfs.h>
+-#include <linux/slab.h>
+-#include <linux/netdevice.h>
+-#include <linux/pci.h>
+-#include <asm/io.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_debugfs.h"
+-#include "bcm43xx_dma.h"
+-#include "bcm43xx_pio.h"
+-#include "bcm43xx_xmit.h"
+-
+-#define REALLY_BIG_BUFFER_SIZE	(1024*256)
+-
+-static struct bcm43xx_debugfs fs;
+-static char really_big_buffer[REALLY_BIG_BUFFER_SIZE];
+-static DECLARE_MUTEX(big_buffer_sem);
+-
+-
+-static ssize_t write_file_dummy(struct file *file, const char __user *buf,
+-				size_t count, loff_t *ppos)
+-{
+-	return count;
+-}
+-
+-static int open_file_generic(struct inode *inode, struct file *file)
+-{
+-	file->private_data = inode->i_private;
+-	return 0;
+-}
+-
+-#define fappend(fmt, x...)	pos += snprintf(buf + pos, len - pos, fmt , ##x)
+-
+-static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
+-				 size_t count, loff_t *ppos)
+-{
+-	const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+-	struct bcm43xx_private *bcm = file->private_data;
+-	char *buf = really_big_buffer;
+-	size_t pos = 0;
+-	ssize_t res;
+-	struct net_device *net_dev;
+-	struct pci_dev *pci_dev;
+-	unsigned long flags;
+-	u16 tmp16;
+-	int i;
+-
+-	down(&big_buffer_sem);
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+-		fappend("Board not initialized.\n");
+-		goto out;
+-	}
+-	net_dev = bcm->net_dev;
+-	pci_dev = bcm->pci_dev;
+-
+-	/* This is where the information is written to the "devinfo" file */
+-	fappend("*** %s devinfo ***\n", net_dev->name);
+-	fappend("vendor:           0x%04x   device:           0x%04x\n",
+-		pci_dev->vendor, pci_dev->device);
+-	fappend("subsystem_vendor: 0x%04x   subsystem_device: 0x%04x\n",
+-		pci_dev->subsystem_vendor, pci_dev->subsystem_device);
+-	fappend("IRQ: %d\n", bcm->irq);
+-	fappend("mmio_addr: 0x%p\n", bcm->mmio_addr);
+-	fappend("chip_id: 0x%04x   chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
+-	if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
+-		fappend("Radio disabled by hardware!\n");
+-	if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4)))
+-		fappend("Radio disabled by hardware!\n");
+-	fappend("board_vendor: 0x%04x   board_type: 0x%04x\n", bcm->board_vendor,
+-	        bcm->board_type);
+-
+-	fappend("\nCores:\n");
+-#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, "	\
+-					 "rev: 0x%02x, index: 0x%02x\n",		\
+-					 (info).available				\
+-						? "available" : "nonavailable",		\
+-					 (info).enabled					\
+-						? "enabled" : "disabled",		\
+-					 (info).id, (info).rev, (info).index)
+-	fappend_core("CHIPCOMMON", bcm->core_chipcommon);
+-	fappend_core("PCI", bcm->core_pci);
+-	fappend_core("first 80211", bcm->core_80211[0]);
+-	fappend_core("second 80211", bcm->core_80211[1]);
+-#undef fappend_core
+-	tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+-	fappend("LEDs: ");
+-	for (i = 0; i < BCM43xx_NR_LEDS; i++)
+-		fappend("%d ", !!(tmp16 & (1 << i)));
+-	fappend("\n");
+-
+-out:
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+-	up(&big_buffer_sem);
+-	return res;
+-}
+-
+-static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf,
+-				 size_t count, loff_t *ppos)
+-{
+-	const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+-	char *buf = really_big_buffer;
+-	size_t pos = 0;
+-	ssize_t res;
+-
+-	down(&big_buffer_sem);
+-
+-	/* This is where the information is written to the "driver" file */
+-	fappend(KBUILD_MODNAME " driver\n");
+-	fappend("Compiled at: %s %s\n", __DATE__, __TIME__);
+-
+-	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+-	up(&big_buffer_sem);
+-	return res;
+-}
+-
+-static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
+-				 size_t count, loff_t *ppos)
+-{
+-	const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+-	struct bcm43xx_private *bcm = file->private_data;
+-	char *buf = really_big_buffer;
+-	size_t pos = 0;
+-	ssize_t res;
+-	unsigned long flags;
+-
+-	down(&big_buffer_sem);
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+-		fappend("Board not initialized.\n");
+-		goto out;
+-	}
+-
+-	/* This is where the information is written to the "sprom_dump" file */
+-	fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
+-
+-out:
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+-	up(&big_buffer_sem);
+-	return res;
+-}
+-
+-static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
+-			     size_t count, loff_t *ppos)
+-{
+-	const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+-	struct bcm43xx_private *bcm = file->private_data;
+-	char *buf = really_big_buffer;
+-	size_t pos = 0;
+-	ssize_t res;
+-	unsigned long flags;
+-	u64 tsf;
+-
+-	down(&big_buffer_sem);
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+-		fappend("Board not initialized.\n");
+-		goto out;
+-	}
+-	bcm43xx_tsf_read(bcm, &tsf);
+-	fappend("0x%08x%08x\n",
+-		(unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
+-		(unsigned int)(tsf & 0xFFFFFFFFULL));
+-
+-out:
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+-	up(&big_buffer_sem);
+-	return res;
+-}
+-
+-static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
+-			      size_t count, loff_t *ppos)
+-{
+-	struct bcm43xx_private *bcm = file->private_data;
+-	char *buf = really_big_buffer;
+-	ssize_t buf_size;
+-	ssize_t res;
+-	unsigned long flags;
+-	unsigned long long tsf;
+-
+-	buf_size = min(count, sizeof (really_big_buffer) - 1);
+-	down(&big_buffer_sem);
+-	if (copy_from_user(buf, user_buf, buf_size)) {
+-	        res = -EFAULT;
+-		goto out_up;
+-	}
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+-		printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
+-		res = -EFAULT;
+-		goto out_unlock;
+-	}
+-	if (sscanf(buf, "%lli", &tsf) != 1) {
+-		printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n");
+-		res = -EINVAL;
+-		goto out_unlock;
+-	}
+-	bcm43xx_tsf_write(bcm, tsf);
+-	mmiowb();
+-	res = buf_size;
+-	
+-out_unlock:
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-out_up:
+-	up(&big_buffer_sem);
+-	return res;
+-}
+-
+-static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
+-				size_t count, loff_t *ppos)
+-{
+-	const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+-	struct bcm43xx_private *bcm = file->private_data;
+-	char *buf = really_big_buffer;
+-	size_t pos = 0;
+-	ssize_t res;
+-	unsigned long flags;
+-	struct bcm43xx_dfsentry *e;
+-	struct bcm43xx_xmitstatus *status;
+-	int i, cnt, j = 0;
+-
+-	down(&big_buffer_sem);
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+-	fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
+-		BCM43xx_NR_LOGGED_XMITSTATUS);
+-	e = bcm->dfsentry;
+-	if (e->xmitstatus_printing == 0) {
+-		/* At the beginning, make a copy of all data to avoid
+-		 * concurrency, as this function is called multiple
+-		 * times for big logs. Without copying, the data might
+-		 * change between reads. This would result in total trash.
+-		 */
+-		e->xmitstatus_printing = 1;
+-		e->saved_xmitstatus_ptr = e->xmitstatus_ptr;
+-		e->saved_xmitstatus_cnt = e->xmitstatus_cnt;
+-		memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer,
+-		       BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer)));
+-	}
+-	i = e->saved_xmitstatus_ptr - 1;
+-	if (i < 0)
+-		i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
+-	cnt = e->saved_xmitstatus_cnt;
+-	while (cnt) {
+-		status = e->xmitstatus_print_buffer + i;
+-		fappend("0x%02x:   cookie: 0x%04x,  flags: 0x%02x,  "
+-			"cnt1: 0x%02x,  cnt2: 0x%02x,  seq: 0x%04x,  "
+-			"unk: 0x%04x\n", j,
+-			status->cookie, status->flags,
+-			status->cnt1, status->cnt2, status->seq,
+-			status->unknown);
+-		j++;
+-		cnt--;
+-		i--;
+-		if (i < 0)
+-			i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
+-	}
+-
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (*ppos == pos) {
+-		/* Done. Drop the copied data. */
+-		e->xmitstatus_printing = 0;
+-	}
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-	up(&big_buffer_sem);
+-	return res;
+-}
+-
+-static ssize_t restart_write_file(struct file *file, const char __user *user_buf,
+-				  size_t count, loff_t *ppos)
+-{
+-	struct bcm43xx_private *bcm = file->private_data;
+-	char *buf = really_big_buffer;
+-	ssize_t buf_size;
+-	ssize_t res;
+-	unsigned long flags;
+-
+-	buf_size = min(count, sizeof (really_big_buffer) - 1);
+-	down(&big_buffer_sem);
+-	if (copy_from_user(buf, user_buf, buf_size)) {
+-	        res = -EFAULT;
+-		goto out_up;
+-	}
+-	mutex_lock(&(bcm)->mutex);
+-	spin_lock_irqsave(&(bcm)->irq_lock, flags);
+-	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+-		printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
+-		res = -EFAULT;
+-		goto out_unlock;
+-	}
+-	if (count > 0 && buf[0] == '1') {
+-		bcm43xx_controller_restart(bcm, "manually restarted");
+-		res = count;
+-	} else
+-		res = -EINVAL;
+-
+-out_unlock:
+-	spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
+-	mutex_unlock(&(bcm)->mutex);
+-out_up:
+-	up(&big_buffer_sem);
+-	return res;
+-}
+-
+-#undef fappend
+-
+-
+-static const struct file_operations devinfo_fops = {
+-	.read = devinfo_read_file,
+-	.write = write_file_dummy,
+-	.open = open_file_generic,
+-};
+-
+-static const struct file_operations spromdump_fops = {
+-	.read = spromdump_read_file,
+-	.write = write_file_dummy,
+-	.open = open_file_generic,
+-};
+-
+-static const struct file_operations drvinfo_fops = {
+-	.read = drvinfo_read_file,
+-	.write = write_file_dummy,
+-	.open = open_file_generic,
+-};
+-
+-static const struct file_operations tsf_fops = {
+-	.read = tsf_read_file,
+-	.write = tsf_write_file,
+-	.open = open_file_generic,
+-};
+-
+-static const struct file_operations txstat_fops = {
+-	.read = txstat_read_file,
+-	.write = write_file_dummy,
+-	.open = open_file_generic,
+-};
+-
+-static const struct file_operations restart_fops = {
+-	.write = restart_write_file,
+-	.open = open_file_generic,
+-};
+-
+-
+-void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_dfsentry *e;
+-	char devdir[IFNAMSIZ];
+-
+-	assert(bcm);
+-	e = kzalloc(sizeof(*e), GFP_KERNEL);
+-	if (!e) {
+-		printk(KERN_ERR PFX "out of memory\n");
+-		return;
+-	}
+-	e->bcm = bcm;
+-	e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
+-				       * sizeof(*(e->xmitstatus_buffer)),
+-				       GFP_KERNEL);
+-	if (!e->xmitstatus_buffer) {
+-		printk(KERN_ERR PFX "out of memory\n");
+-		kfree(e);
+-		return;
+-	}
+-	e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
+-					     * sizeof(*(e->xmitstatus_buffer)),
+-					     GFP_KERNEL);
+-	if (!e->xmitstatus_print_buffer) {
+-		printk(KERN_ERR PFX "out of memory\n");
+-		kfree(e);
+-		return;
+-	}
+-
+-
+-	bcm->dfsentry = e;
+-
+-	strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir));
+-	e->subdir = debugfs_create_dir(devdir, fs.root);
+-	e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir,
+-						bcm, &devinfo_fops);
+-	if (!e->dentry_devinfo)
+-		printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir);
+-	e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir,
+-						  bcm, &spromdump_fops);
+-	if (!e->dentry_spromdump)
+-		printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir);
+-	e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir,
+-	                                    bcm, &tsf_fops);
+-	if (!e->dentry_tsf)
+-		printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir);
+-	e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir,
+-						bcm, &txstat_fops);
+-	if (!e->dentry_txstat)
+-		printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
+-	e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir,
+-						bcm, &restart_fops);
+-	if (!e->dentry_restart)
+-		printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir);
+-}
+-
+-void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_dfsentry *e;
+-
+-	if (!bcm)
+-		return;
+-
+-	e = bcm->dfsentry;
+-	assert(e);
+-	debugfs_remove(e->dentry_spromdump);
+-	debugfs_remove(e->dentry_devinfo);
+-	debugfs_remove(e->dentry_tsf);
+-	debugfs_remove(e->dentry_txstat);
+-	debugfs_remove(e->dentry_restart);
+-	debugfs_remove(e->subdir);
+-	kfree(e->xmitstatus_buffer);
+-	kfree(e->xmitstatus_print_buffer);
+-	kfree(e);
+-}
+-
+-void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+-				struct bcm43xx_xmitstatus *status)
+-{
+-	struct bcm43xx_dfsentry *e;
+-	struct bcm43xx_xmitstatus *savedstatus;
+-
+-	/* This is protected by bcm->_lock */
+-	e = bcm->dfsentry;
+-	assert(e);
+-	savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr;
+-	memcpy(savedstatus, status, sizeof(*status));
+-	e->xmitstatus_ptr++;
+-	if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS)
+-		e->xmitstatus_ptr = 0;
+-	if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS)
+-		e->xmitstatus_cnt++;
+-}
+-
+-void bcm43xx_debugfs_init(void)
+-{
+-	memset(&fs, 0, sizeof(fs));
+-	fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+-	if (!fs.root)
+-		printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n");
+-	fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops);
+-	if (!fs.dentry_driverinfo)
+-		printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n");
+-}
+-
+-void bcm43xx_debugfs_exit(void)
+-{
+-	debugfs_remove(fs.dentry_driverinfo);
+-	debugfs_remove(fs.root);
+-}
+-
+-void bcm43xx_printk_dump(const char *data,
+-			 size_t size,
+-			 const char *description)
+-{
+-	size_t i;
+-	char c;
+-
+-	printk(KERN_INFO PFX "Data dump (%s, %zd bytes):",
+-	       description, size);
+-	for (i = 0; i < size; i++) {
+-		c = data[i];
+-		if (i % 8 == 0)
+-			printk("\n" KERN_INFO PFX "0x%08zx:  0x%02x, ", i, c & 0xff);
+-		else
+-			printk("0x%02x, ", c & 0xff);
+-	}
+-	printk("\n");
+-}
+-
+-void bcm43xx_printk_bitdump(const unsigned char *data,
+-			    size_t bytes, int msb_to_lsb,
+-			    const char *description)
+-{
+-	size_t i;
+-	int j;
+-	const unsigned char *d;
+-
+-	printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***",
+-	       description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
+-	for (i = 0; i < bytes; i++) {
+-		d = data + i;
+-		if (i % 8 == 0)
+-			printk("\n" KERN_INFO PFX "0x%08zx:  ", i);
+-		if (msb_to_lsb) {
+-			for (j = 7; j >= 0; j--) {
+-				if (*d & (1 << j))
+-					printk("1");
+-				else
+-					printk("0");
+-			}
+-		} else {
+-			for (j = 0; j < 8; j++) {
+-				if (*d & (1 << j))
+-					printk("1");
+-				else
+-					printk("0");
+-			}
+-		}
+-		printk(" ");
+-	}
+-	printk("\n");
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
+deleted file mode 100644
+index a40d1af..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
++++ /dev/null
+@@ -1,118 +0,0 @@
+-#ifndef BCM43xx_DEBUGFS_H_
+-#define BCM43xx_DEBUGFS_H_
+-
+-struct bcm43xx_private;
+-struct bcm43xx_xmitstatus;
+-
+-#ifdef CONFIG_BCM43XX_DEBUG
+-
+-#include <linux/list.h>
+-#include <asm/semaphore.h>
+-
+-struct dentry;
+-
+-/* limited by the size of the "really_big_buffer" */
+-#define BCM43xx_NR_LOGGED_XMITSTATUS	100
+-
+-struct bcm43xx_dfsentry {
+-	struct dentry *subdir;
+-	struct dentry *dentry_devinfo;
+-	struct dentry *dentry_spromdump;
+-	struct dentry *dentry_tsf;
+-	struct dentry *dentry_txstat;
+-	struct dentry *dentry_restart;
+-
+-	struct bcm43xx_private *bcm;
+-
+-	/* saved xmitstatus. */
+-	struct bcm43xx_xmitstatus *xmitstatus_buffer;
+-	int xmitstatus_ptr;
+-	int xmitstatus_cnt;
+-	/* We need a seperate buffer while printing to avoid
+-	 * concurrency issues. (New xmitstatus can arrive
+-	 * while we are printing).
+-	 */
+-	struct bcm43xx_xmitstatus *xmitstatus_print_buffer;
+-	int saved_xmitstatus_ptr;
+-	int saved_xmitstatus_cnt;
+-	int xmitstatus_printing;
+-};
+-
+-struct bcm43xx_debugfs {
+-	struct dentry *root;
+-	struct dentry *dentry_driverinfo;
+-};
+-
+-void bcm43xx_debugfs_init(void);
+-void bcm43xx_debugfs_exit(void);
+-void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm);
+-void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm);
+-void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+-				struct bcm43xx_xmitstatus *status);
+-
+-/* Debug helper: Dump binary data through printk. */
+-void bcm43xx_printk_dump(const char *data,
+-			 size_t size,
+-			 const char *description);
+-/* Debug helper: Dump bitwise binary data through printk. */
+-void bcm43xx_printk_bitdump(const unsigned char *data,
+-			    size_t bytes, int msb_to_lsb,
+-			    const char *description);
+-#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \
+-	do {									\
+-		bcm43xx_printk_bitdump((const unsigned char *)(pointer),	\
+-				       sizeof(*(pointer)),			\
+-				       (msb_to_lsb),				\
+-				       (description));				\
+-	} while (0)
+-
+-#else /* CONFIG_BCM43XX_DEBUG*/
+-
+-static inline
+-void bcm43xx_debugfs_init(void) { }
+-static inline
+-void bcm43xx_debugfs_exit(void) { }
+-static inline
+-void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { }
+-static inline
+-void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { }
+-static inline
+-void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+-				struct bcm43xx_xmitstatus *status) { }
+-
+-static inline
+-void bcm43xx_printk_dump(const char *data,
+-			 size_t size,
+-			 const char *description)
+-{
+-}
+-static inline
+-void bcm43xx_printk_bitdump(const unsigned char *data,
+-			    size_t bytes, int msb_to_lsb,
+-			    const char *description)
+-{
+-}
+-#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description)  do { /* nothing */ } while (0)
+-
+-#endif /* CONFIG_BCM43XX_DEBUG*/
+-
+-/* Ugly helper macros to make incomplete code more verbose on runtime */
+-#ifdef TODO
+-# undef TODO
+-#endif
+-#define TODO()  \
+-	do {										\
+-		printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n",	\
+-		       __FUNCTION__, __FILE__, __LINE__);				\
+-	} while (0)
+-
+-#ifdef FIXME
+-# undef FIXME
+-#endif
+-#define FIXME()  \
+-	do {										\
+-		printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n",	\
+-		       __FUNCTION__, __FILE__, __LINE__);				\
+-	} while (0)
+-
+-#endif /* BCM43xx_DEBUGFS_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+deleted file mode 100644
+index 1f7731f..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
++++ /dev/null
+@@ -1,1263 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  DMA ringbuffer and descriptor allocation/management
+-
+-  Copyright (c) 2005, 2006 Michael Buesch <mbuesch at freenet.de>
+-
+-  Some code in this file is derived from the b44.c driver
+-  Copyright (C) 2002 David S. Miller
+-  Copyright (C) Pekka Pietikainen
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 "bcm43xx.h"
+-#include "bcm43xx_dma.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_debugfs.h"
+-#include "bcm43xx_power.h"
+-#include "bcm43xx_xmit.h"
+-
+-#include <linux/dma-mapping.h>
+-#include <linux/pci.h>
+-#include <linux/delay.h>
+-#include <linux/skbuff.h>
+-
+-
+-static inline int free_slots(struct bcm43xx_dmaring *ring)
+-{
+-	return (ring->nr_slots - ring->used_slots);
+-}
+-
+-static inline int next_slot(struct bcm43xx_dmaring *ring, int slot)
+-{
+-	assert(slot >= -1 && slot <= ring->nr_slots - 1);
+-	if (slot == ring->nr_slots - 1)
+-		return 0;
+-	return slot + 1;
+-}
+-
+-static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot)
+-{
+-	assert(slot >= 0 && slot <= ring->nr_slots - 1);
+-	if (slot == 0)
+-		return ring->nr_slots - 1;
+-	return slot - 1;
+-}
+-
+-/* Request a slot for usage. */
+-static inline
+-int request_slot(struct bcm43xx_dmaring *ring)
+-{
+-	int slot;
+-
+-	assert(ring->tx);
+-	assert(!ring->suspended);
+-	assert(free_slots(ring) != 0);
+-
+-	slot = next_slot(ring, ring->current_slot);
+-	ring->current_slot = slot;
+-	ring->used_slots++;
+-
+-	/* Check the number of available slots and suspend TX,
+-	 * if we are running low on free slots.
+-	 */
+-	if (unlikely(free_slots(ring) < ring->suspend_mark)) {
+-		netif_stop_queue(ring->bcm->net_dev);
+-		ring->suspended = 1;
+-	}
+-#ifdef CONFIG_BCM43XX_DEBUG
+-	if (ring->used_slots > ring->max_used_slots)
+-		ring->max_used_slots = ring->used_slots;
+-#endif /* CONFIG_BCM43XX_DEBUG*/
+-
+-	return slot;
+-}
+-
+-/* Return a slot to the free slots. */
+-static inline
+-void return_slot(struct bcm43xx_dmaring *ring, int slot)
+-{
+-	assert(ring->tx);
+-
+-	ring->used_slots--;
+-
+-	/* Check if TX is suspended and check if we have
+-	 * enough free slots to resume it again.
+-	 */
+-	if (unlikely(ring->suspended)) {
+-		if (free_slots(ring) >= ring->resume_mark) {
+-			ring->suspended = 0;
+-			netif_wake_queue(ring->bcm->net_dev);
+-		}
+-	}
+-}
+-
+-u16 bcm43xx_dmacontroller_base(int dma64bit, int controller_idx)
+-{
+-	static const u16 map64[] = {
+-		BCM43xx_MMIO_DMA64_BASE0,
+-		BCM43xx_MMIO_DMA64_BASE1,
+-		BCM43xx_MMIO_DMA64_BASE2,
+-		BCM43xx_MMIO_DMA64_BASE3,
+-		BCM43xx_MMIO_DMA64_BASE4,
+-		BCM43xx_MMIO_DMA64_BASE5,
+-	};
+-	static const u16 map32[] = {
+-		BCM43xx_MMIO_DMA32_BASE0,
+-		BCM43xx_MMIO_DMA32_BASE1,
+-		BCM43xx_MMIO_DMA32_BASE2,
+-		BCM43xx_MMIO_DMA32_BASE3,
+-		BCM43xx_MMIO_DMA32_BASE4,
+-		BCM43xx_MMIO_DMA32_BASE5,
+-	};
+-
+-	if (dma64bit) {
+-		assert(controller_idx >= 0 &&
+-		       controller_idx < ARRAY_SIZE(map64));
+-		return map64[controller_idx];
+-	}
+-	assert(controller_idx >= 0 &&
+-	       controller_idx < ARRAY_SIZE(map32));
+-	return map32[controller_idx];
+-}
+-
+-static inline
+-dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
+-			  unsigned char *buf,
+-			  size_t len,
+-			  int tx)
+-{
+-	dma_addr_t dmaaddr;
+-	int direction = PCI_DMA_FROMDEVICE;
+-
+-	if (tx)
+-		direction = PCI_DMA_TODEVICE;
+-
+-	dmaaddr = pci_map_single(ring->bcm->pci_dev,
+-					 buf, len,
+-					 direction);
+-
+-	return dmaaddr;
+-}
+-
+-static inline
+-void unmap_descbuffer(struct bcm43xx_dmaring *ring,
+-		      dma_addr_t addr,
+-		      size_t len,
+-		      int tx)
+-{
+-	if (tx) {
+-		pci_unmap_single(ring->bcm->pci_dev,
+-				 addr, len,
+-				 PCI_DMA_TODEVICE);
+-	} else {
+-		pci_unmap_single(ring->bcm->pci_dev,
+-				 addr, len,
+-				 PCI_DMA_FROMDEVICE);
+-	}
+-}
+-
+-static inline
+-void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
+-			     dma_addr_t addr,
+-			     size_t len)
+-{
+-	assert(!ring->tx);
+-
+-	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+-				    addr, len, PCI_DMA_FROMDEVICE);
+-}
+-
+-static inline
+-void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
+-				dma_addr_t addr,
+-				size_t len)
+-{
+-	assert(!ring->tx);
+-
+-	pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+-				    addr, len, PCI_DMA_TODEVICE);
+-}
+-
+-/* Unmap and free a descriptor buffer. */
+-static inline
+-void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
+-			    struct bcm43xx_dmadesc_meta *meta,
+-			    int irq_context)
+-{
+-	assert(meta->skb);
+-	if (irq_context)
+-		dev_kfree_skb_irq(meta->skb);
+-	else
+-		dev_kfree_skb(meta->skb);
+-	meta->skb = NULL;
+-}
+-
+-static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
+-{
+-	ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
+-					    &(ring->dmabase));
+-	if (!ring->descbase) {
+-		/* Allocation may have failed due to pci_alloc_consistent
+-		   insisting on use of GFP_DMA, which is more restrictive
+-		   than necessary...  */
+-		struct dma_desc *rx_ring;
+-		dma_addr_t rx_ring_dma;
+-
+-		rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
+-		if (!rx_ring)
+-			goto out_err;
+-
+-		rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
+-					     BCM43xx_DMA_RINGMEMSIZE,
+-					     PCI_DMA_BIDIRECTIONAL);
+-
+-		if (pci_dma_mapping_error(rx_ring_dma) ||
+-		    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+-			/* Sigh... */
+-			if (!pci_dma_mapping_error(rx_ring_dma))
+-				pci_unmap_single(ring->bcm->pci_dev,
+-						 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+-						 PCI_DMA_BIDIRECTIONAL);
+-			rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
+-						 rx_ring, BCM43xx_DMA_RINGMEMSIZE,
+-						 PCI_DMA_BIDIRECTIONAL);
+-			if (pci_dma_mapping_error(rx_ring_dma) ||
+-			    rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+-				assert(0);
+-				if (!pci_dma_mapping_error(rx_ring_dma))
+-					pci_unmap_single(ring->bcm->pci_dev,
+-							 rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+-							 PCI_DMA_BIDIRECTIONAL);
+-				goto out_err;
+-			}
+-                }
+-
+-                ring->descbase = rx_ring;
+-                ring->dmabase = rx_ring_dma;
+-	}
+-	memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
+-
+-	return 0;
+-out_err:
+-	printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+-	return -ENOMEM;
+-}
+-
+-static void free_ringmemory(struct bcm43xx_dmaring *ring)
+-{
+-	struct device *dev = &(ring->bcm->pci_dev->dev);
+-
+-	dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
+-			  ring->descbase, ring->dmabase);
+-}
+-
+-/* Reset the RX DMA channel */
+-int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+-				   u16 mmio_base, int dma64)
+-{
+-	int i;
+-	u32 value;
+-	u16 offset;
+-
+-	offset = dma64 ? BCM43xx_DMA64_RXCTL : BCM43xx_DMA32_RXCTL;
+-	bcm43xx_write32(bcm, mmio_base + offset, 0);
+-	for (i = 0; i < 1000; i++) {
+-		offset = dma64 ? BCM43xx_DMA64_RXSTATUS : BCM43xx_DMA32_RXSTATUS;
+-		value = bcm43xx_read32(bcm, mmio_base + offset);
+-		if (dma64) {
+-			value &= BCM43xx_DMA64_RXSTAT;
+-			if (value == BCM43xx_DMA64_RXSTAT_DISABLED) {
+-				i = -1;
+-				break;
+-			}
+-		} else {
+-			value &= BCM43xx_DMA32_RXSTATE;
+-			if (value == BCM43xx_DMA32_RXSTAT_DISABLED) {
+-				i = -1;
+-				break;
+-			}
+-		}
+-		udelay(10);
+-	}
+-	if (i != -1) {
+-		printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n");
+-		return -ENODEV;
+-	}
+-
+-	return 0;
+-}
+-
+-/* Reset the RX DMA channel */
+-int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+-				   u16 mmio_base, int dma64)
+-{
+-	int i;
+-	u32 value;
+-	u16 offset;
+-
+-	for (i = 0; i < 1000; i++) {
+-		offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
+-		value = bcm43xx_read32(bcm, mmio_base + offset);
+-		if (dma64) {
+-			value &= BCM43xx_DMA64_TXSTAT;
+-			if (value == BCM43xx_DMA64_TXSTAT_DISABLED ||
+-			    value == BCM43xx_DMA64_TXSTAT_IDLEWAIT ||
+-			    value == BCM43xx_DMA64_TXSTAT_STOPPED)
+-				break;
+-		} else {
+-			value &= BCM43xx_DMA32_TXSTATE;
+-			if (value == BCM43xx_DMA32_TXSTAT_DISABLED ||
+-			    value == BCM43xx_DMA32_TXSTAT_IDLEWAIT ||
+-			    value == BCM43xx_DMA32_TXSTAT_STOPPED)
+-				break;
+-		}
+-		udelay(10);
+-	}
+-	offset = dma64 ? BCM43xx_DMA64_TXCTL : BCM43xx_DMA32_TXCTL;
+-	bcm43xx_write32(bcm, mmio_base + offset, 0);
+-	for (i = 0; i < 1000; i++) {
+-		offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
+-		value = bcm43xx_read32(bcm, mmio_base + offset);
+-		if (dma64) {
+-			value &= BCM43xx_DMA64_TXSTAT;
+-			if (value == BCM43xx_DMA64_TXSTAT_DISABLED) {
+-				i = -1;
+-				break;
+-			}
+-		} else {
+-			value &= BCM43xx_DMA32_TXSTATE;
+-			if (value == BCM43xx_DMA32_TXSTAT_DISABLED) {
+-				i = -1;
+-				break;
+-			}
+-		}
+-		udelay(10);
+-	}
+-	if (i != -1) {
+-		printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n");
+-		return -ENODEV;
+-	}
+-	/* ensure the reset is completed. */
+-	udelay(300);
+-
+-	return 0;
+-}
+-
+-static void fill_descriptor(struct bcm43xx_dmaring *ring,
+-			    struct bcm43xx_dmadesc_generic *desc,
+-			    dma_addr_t dmaaddr,
+-			    u16 bufsize,
+-			    int start, int end, int irq)
+-{
+-	int slot;
+-
+-	slot = bcm43xx_dma_desc2idx(ring, desc);
+-	assert(slot >= 0 && slot < ring->nr_slots);
+-
+-	if (ring->dma64) {
+-		u32 ctl0 = 0, ctl1 = 0;
+-		u32 addrlo, addrhi;
+-		u32 addrext;
+-
+-		addrlo = (u32)(dmaaddr & 0xFFFFFFFF);
+-		addrhi = (((u64)dmaaddr >> 32) & ~BCM43xx_DMA64_ROUTING);
+-		addrext = (((u64)dmaaddr >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
+-		addrhi |= ring->routing;
+-		if (slot == ring->nr_slots - 1)
+-			ctl0 |= BCM43xx_DMA64_DCTL0_DTABLEEND;
+-		if (start)
+-			ctl0 |= BCM43xx_DMA64_DCTL0_FRAMESTART;
+-		if (end)
+-			ctl0 |= BCM43xx_DMA64_DCTL0_FRAMEEND;
+-		if (irq)
+-			ctl0 |= BCM43xx_DMA64_DCTL0_IRQ;
+-		ctl1 |= (bufsize - ring->frameoffset)
+-			& BCM43xx_DMA64_DCTL1_BYTECNT;
+-		ctl1 |= (addrext << BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT)
+-			& BCM43xx_DMA64_DCTL1_ADDREXT_MASK;
+-
+-		desc->dma64.control0 = cpu_to_le32(ctl0);
+-		desc->dma64.control1 = cpu_to_le32(ctl1);
+-		desc->dma64.address_low = cpu_to_le32(addrlo);
+-		desc->dma64.address_high = cpu_to_le32(addrhi);
+-	} else {
+-		u32 ctl;
+-		u32 addr;
+-		u32 addrext;
+-
+-		addr = (u32)(dmaaddr & ~BCM43xx_DMA32_ROUTING);
+-		addrext = (u32)(dmaaddr & BCM43xx_DMA32_ROUTING)
+-			   >> BCM43xx_DMA32_ROUTING_SHIFT;
+-		addr |= ring->routing;
+-		ctl = (bufsize - ring->frameoffset)
+-		      & BCM43xx_DMA32_DCTL_BYTECNT;
+-		if (slot == ring->nr_slots - 1)
+-			ctl |= BCM43xx_DMA32_DCTL_DTABLEEND;
+-		if (start)
+-			ctl |= BCM43xx_DMA32_DCTL_FRAMESTART;
+-		if (end)
+-			ctl |= BCM43xx_DMA32_DCTL_FRAMEEND;
+-		if (irq)
+-			ctl |= BCM43xx_DMA32_DCTL_IRQ;
+-		ctl |= (addrext << BCM43xx_DMA32_DCTL_ADDREXT_SHIFT)
+-		       & BCM43xx_DMA32_DCTL_ADDREXT_MASK;
+-
+-		desc->dma32.control = cpu_to_le32(ctl);
+-		desc->dma32.address = cpu_to_le32(addr);
+-	}
+-}
+-
+-static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
+-			       struct bcm43xx_dmadesc_generic *desc,
+-			       struct bcm43xx_dmadesc_meta *meta,
+-			       gfp_t gfp_flags)
+-{
+-	struct bcm43xx_rxhdr *rxhdr;
+-	struct bcm43xx_hwxmitstatus *xmitstat;
+-	dma_addr_t dmaaddr;
+-	struct sk_buff *skb;
+-
+-	assert(!ring->tx);
+-
+-	skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
+-	if (unlikely(!skb))
+-		return -ENOMEM;
+-	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+-	/* This hardware bug work-around adapted from the b44 driver.
+-	   The chip may be unable to do PCI DMA to/from anything above 1GB */
+-	if (pci_dma_mapping_error(dmaaddr) ||
+-	    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+-		/* This one has 30-bit addressing... */
+-		if (!pci_dma_mapping_error(dmaaddr))
+-			pci_unmap_single(ring->bcm->pci_dev,
+-					 dmaaddr, ring->rx_buffersize,
+-					 PCI_DMA_FROMDEVICE);
+-		dev_kfree_skb_any(skb);
+-		skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
+-		if (skb == NULL)
+-			return -ENOMEM;
+-		dmaaddr = pci_map_single(ring->bcm->pci_dev,
+-					 skb->data, ring->rx_buffersize,
+-					 PCI_DMA_FROMDEVICE);
+-		if (pci_dma_mapping_error(dmaaddr) ||
+-		    dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+-			assert(0);
+-			dev_kfree_skb_any(skb);
+-			return -ENOMEM;
+-		}
+-	}
+-	meta->skb = skb;
+-	meta->dmaaddr = dmaaddr;
+-	skb->dev = ring->bcm->net_dev;
+-
+-	fill_descriptor(ring, desc, dmaaddr,
+-			ring->rx_buffersize, 0, 0, 0);
+-
+-	rxhdr = (struct bcm43xx_rxhdr *)(skb->data);
+-	rxhdr->frame_length = 0;
+-	rxhdr->flags1 = 0;
+-	xmitstat = (struct bcm43xx_hwxmitstatus *)(skb->data);
+-	xmitstat->cookie = 0;
+-
+-	return 0;
+-}
+-
+-/* Allocate the initial descbuffers.
+- * This is used for an RX ring only.
+- */
+-static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring)
+-{
+-	int i, err = -ENOMEM;
+-	struct bcm43xx_dmadesc_generic *desc;
+-	struct bcm43xx_dmadesc_meta *meta;
+-
+-	for (i = 0; i < ring->nr_slots; i++) {
+-		desc = bcm43xx_dma_idx2desc(ring, i, &meta);
+-
+-		err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
+-		if (err)
+-			goto err_unwind;
+-	}
+-	mb();
+-	ring->used_slots = ring->nr_slots;
+-	err = 0;
+-out:
+-	return err;
+-
+-err_unwind:
+-	for (i--; i >= 0; i--) {
+-		desc = bcm43xx_dma_idx2desc(ring, i, &meta);
+-
+-		unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
+-		dev_kfree_skb(meta->skb);
+-	}
+-	goto out;
+-}
+-
+-/* Do initial setup of the DMA controller.
+- * Reset the controller, write the ring busaddress
+- * and switch the "enable" bit on.
+- */
+-static int dmacontroller_setup(struct bcm43xx_dmaring *ring)
+-{
+-	int err = 0;
+-	u32 value;
+-	u32 addrext;
+-
+-	if (ring->tx) {
+-		if (ring->dma64) {
+-			u64 ringbase = (u64)(ring->dmabase);
+-
+-			addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
+-			value = BCM43xx_DMA64_TXENABLE;
+-			value |= (addrext << BCM43xx_DMA64_TXADDREXT_SHIFT)
+-				& BCM43xx_DMA64_TXADDREXT_MASK;
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, value);
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO,
+-					(ringbase & 0xFFFFFFFF));
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI,
+-					((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
+-					| ring->routing);
+-		} else {
+-			u32 ringbase = (u32)(ring->dmabase);
+-
+-			addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
+-			value = BCM43xx_DMA32_TXENABLE;
+-			value |= (addrext << BCM43xx_DMA32_TXADDREXT_SHIFT)
+-				& BCM43xx_DMA32_TXADDREXT_MASK;
+-			bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, value);
+-			bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING,
+-					(ringbase & ~BCM43xx_DMA32_ROUTING)
+-					| ring->routing);
+-		}
+-	} else {
+-		err = alloc_initial_descbuffers(ring);
+-		if (err)
+-			goto out;
+-		if (ring->dma64) {
+-			u64 ringbase = (u64)(ring->dmabase);
+-
+-			addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
+-			value = (ring->frameoffset << BCM43xx_DMA64_RXFROFF_SHIFT);
+-			value |= BCM43xx_DMA64_RXENABLE;
+-			value |= (addrext << BCM43xx_DMA64_RXADDREXT_SHIFT)
+-				& BCM43xx_DMA64_RXADDREXT_MASK;
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXCTL, value);
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO,
+-					(ringbase & 0xFFFFFFFF));
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI,
+-					((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
+-					| ring->routing);
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, 200);
+-		} else {
+-			u32 ringbase = (u32)(ring->dmabase);
+-
+-			addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
+-			value = (ring->frameoffset << BCM43xx_DMA32_RXFROFF_SHIFT);
+-			value |= BCM43xx_DMA32_RXENABLE;
+-			value |= (addrext << BCM43xx_DMA32_RXADDREXT_SHIFT)
+-				& BCM43xx_DMA32_RXADDREXT_MASK;
+-			bcm43xx_dma_write(ring, BCM43xx_DMA32_RXCTL, value);
+-			bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING,
+-					(ringbase & ~BCM43xx_DMA32_ROUTING)
+-					| ring->routing);
+-			bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, 200);
+-		}
+-	}
+-
+-out:
+-	return err;
+-}
+-
+-/* Shutdown the DMA controller. */
+-static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring)
+-{
+-	if (ring->tx) {
+-		bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base, ring->dma64);
+-		if (ring->dma64) {
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, 0);
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, 0);
+-		} else
+-			bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, 0);
+-	} else {
+-		bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base, ring->dma64);
+-		if (ring->dma64) {
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, 0);
+-			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, 0);
+-		} else
+-			bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, 0);
+-	}
+-}
+-
+-static void free_all_descbuffers(struct bcm43xx_dmaring *ring)
+-{
+-	struct bcm43xx_dmadesc_generic *desc;
+-	struct bcm43xx_dmadesc_meta *meta;
+-	int i;
+-
+-	if (!ring->used_slots)
+-		return;
+-	for (i = 0; i < ring->nr_slots; i++) {
+-		desc = bcm43xx_dma_idx2desc(ring, i, &meta);
+-
+-		if (!meta->skb) {
+-			assert(ring->tx);
+-			continue;
+-		}
+-		if (ring->tx) {
+-			unmap_descbuffer(ring, meta->dmaaddr,
+-					meta->skb->len, 1);
+-		} else {
+-			unmap_descbuffer(ring, meta->dmaaddr,
+-					ring->rx_buffersize, 0);
+-		}
+-		free_descriptor_buffer(ring, meta, 0);
+-	}
+-}
+-
+-/* Main initialization function. */
+-static
+-struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
+-					       int controller_index,
+-					       int for_tx,
+-					       int dma64)
+-{
+-	struct bcm43xx_dmaring *ring;
+-	int err;
+-	int nr_slots;
+-
+-	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+-	if (!ring)
+-		goto out;
+-
+-	nr_slots = BCM43xx_RXRING_SLOTS;
+-	if (for_tx)
+-		nr_slots = BCM43xx_TXRING_SLOTS;
+-
+-	ring->meta = kcalloc(nr_slots, sizeof(struct bcm43xx_dmadesc_meta),
+-			     GFP_KERNEL);
+-	if (!ring->meta)
+-		goto err_kfree_ring;
+-
+-	ring->routing = BCM43xx_DMA32_CLIENTTRANS;
+-	if (dma64)
+-		ring->routing = BCM43xx_DMA64_CLIENTTRANS;
+-
+-	ring->bcm = bcm;
+-	ring->nr_slots = nr_slots;
+-	ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100;
+-	ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100;
+-	assert(ring->suspend_mark < ring->resume_mark);
+-	ring->mmio_base = bcm43xx_dmacontroller_base(dma64, controller_index);
+-	ring->index = controller_index;
+-	ring->dma64 = !!dma64;
+-	if (for_tx) {
+-		ring->tx = 1;
+-		ring->current_slot = -1;
+-	} else {
+-		if (ring->index == 0) {
+-			ring->rx_buffersize = BCM43xx_DMA0_RX_BUFFERSIZE;
+-			ring->frameoffset = BCM43xx_DMA0_RX_FRAMEOFFSET;
+-		} else if (ring->index == 3) {
+-			ring->rx_buffersize = BCM43xx_DMA3_RX_BUFFERSIZE;
+-			ring->frameoffset = BCM43xx_DMA3_RX_FRAMEOFFSET;
+-		} else
+-			assert(0);
+-	}
+-
+-	err = alloc_ringmemory(ring);
+-	if (err)
+-		goto err_kfree_meta;
+-	err = dmacontroller_setup(ring);
+-	if (err)
+-		goto err_free_ringmemory;
+-	return ring;
+-
+-out:
+-	printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
+-	return ring;
+-
+-err_free_ringmemory:
+-	free_ringmemory(ring);
+-err_kfree_meta:
+-	kfree(ring->meta);
+-err_kfree_ring:
+-	kfree(ring);
+-	ring = NULL;
+-	goto out;
+-}
+-
+-/* Main cleanup function. */
+-static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring)
+-{
+-	if (!ring)
+-		return;
+-
+-	dprintk(KERN_INFO PFX "DMA-%s 0x%04X (%s) max used slots: %d/%d\n",
+-		(ring->dma64) ? "64" : "32",
+-		ring->mmio_base,
+-		(ring->tx) ? "TX" : "RX",
+-		ring->max_used_slots, ring->nr_slots);
+-	/* Device IRQs are disabled prior entering this function,
+-	 * so no need to take care of concurrency with rx handler stuff.
+-	 */
+-	dmacontroller_cleanup(ring);
+-	free_all_descbuffers(ring);
+-	free_ringmemory(ring);
+-
+-	kfree(ring->meta);
+-	kfree(ring);
+-}
+-
+-void bcm43xx_dma_free(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_dma *dma;
+-
+-	if (bcm43xx_using_pio(bcm))
+-		return;
+-	dma = bcm43xx_current_dma(bcm);
+-
+-	bcm43xx_destroy_dmaring(dma->rx_ring3);
+-	dma->rx_ring3 = NULL;
+-	bcm43xx_destroy_dmaring(dma->rx_ring0);
+-	dma->rx_ring0 = NULL;
+-
+-	bcm43xx_destroy_dmaring(dma->tx_ring5);
+-	dma->tx_ring5 = NULL;
+-	bcm43xx_destroy_dmaring(dma->tx_ring4);
+-	dma->tx_ring4 = NULL;
+-	bcm43xx_destroy_dmaring(dma->tx_ring3);
+-	dma->tx_ring3 = NULL;
+-	bcm43xx_destroy_dmaring(dma->tx_ring2);
+-	dma->tx_ring2 = NULL;
+-	bcm43xx_destroy_dmaring(dma->tx_ring1);
+-	dma->tx_ring1 = NULL;
+-	bcm43xx_destroy_dmaring(dma->tx_ring0);
+-	dma->tx_ring0 = NULL;
+-}
+-
+-int bcm43xx_dma_init(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
+-	struct bcm43xx_dmaring *ring;
+-	int err = -ENOMEM;
+-	int dma64 = 0;
+-
+-	bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
+-	if (bcm->dma_mask == DMA_64BIT_MASK)
+-		dma64 = 1;
+-	err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
+-	if (err)
+-		goto no_dma;
+-	err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
+-	if (err)
+-		goto no_dma;
+-
+-	/* setup TX DMA channels. */
+-	ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
+-	if (!ring)
+-		goto out;
+-	dma->tx_ring0 = ring;
+-
+-	ring = bcm43xx_setup_dmaring(bcm, 1, 1, dma64);
+-	if (!ring)
+-		goto err_destroy_tx0;
+-	dma->tx_ring1 = ring;
+-
+-	ring = bcm43xx_setup_dmaring(bcm, 2, 1, dma64);
+-	if (!ring)
+-		goto err_destroy_tx1;
+-	dma->tx_ring2 = ring;
+-
+-	ring = bcm43xx_setup_dmaring(bcm, 3, 1, dma64);
+-	if (!ring)
+-		goto err_destroy_tx2;
+-	dma->tx_ring3 = ring;
+-
+-	ring = bcm43xx_setup_dmaring(bcm, 4, 1, dma64);
+-	if (!ring)
+-		goto err_destroy_tx3;
+-	dma->tx_ring4 = ring;
+-
+-	ring = bcm43xx_setup_dmaring(bcm, 5, 1, dma64);
+-	if (!ring)
+-		goto err_destroy_tx4;
+-	dma->tx_ring5 = ring;
+-
+-	/* setup RX DMA channels. */
+-	ring = bcm43xx_setup_dmaring(bcm, 0, 0, dma64);
+-	if (!ring)
+-		goto err_destroy_tx5;
+-	dma->rx_ring0 = ring;
+-
+-	if (bcm->current_core->rev < 5) {
+-		ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64);
+-		if (!ring)
+-			goto err_destroy_rx0;
+-		dma->rx_ring3 = ring;
+-	}
+-
+-	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
+-		(bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
+-		(bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
+-	err = 0;
+-out:
+-	return err;
+-
+-err_destroy_rx0:
+-	bcm43xx_destroy_dmaring(dma->rx_ring0);
+-	dma->rx_ring0 = NULL;
+-err_destroy_tx5:
+-	bcm43xx_destroy_dmaring(dma->tx_ring5);
+-	dma->tx_ring5 = NULL;
+-err_destroy_tx4:
+-	bcm43xx_destroy_dmaring(dma->tx_ring4);
+-	dma->tx_ring4 = NULL;
+-err_destroy_tx3:
+-	bcm43xx_destroy_dmaring(dma->tx_ring3);
+-	dma->tx_ring3 = NULL;
+-err_destroy_tx2:
+-	bcm43xx_destroy_dmaring(dma->tx_ring2);
+-	dma->tx_ring2 = NULL;
+-err_destroy_tx1:
+-	bcm43xx_destroy_dmaring(dma->tx_ring1);
+-	dma->tx_ring1 = NULL;
+-err_destroy_tx0:
+-	bcm43xx_destroy_dmaring(dma->tx_ring0);
+-	dma->tx_ring0 = NULL;
+-no_dma:
+-#ifdef CONFIG_BCM43XX_PIO
+-	printk(KERN_WARNING PFX "DMA not supported on this device."
+-				" Falling back to PIO.\n");
+-	bcm->__using_pio = 1;
+-	return -ENOSYS;
+-#else
+-	printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+-			    "Please recompile the driver with PIO support.\n");
+-	return -ENODEV;
+-#endif /* CONFIG_BCM43XX_PIO */
+-}
+-
+-/* Generate a cookie for the TX header. */
+-static u16 generate_cookie(struct bcm43xx_dmaring *ring,
+-			   int slot)
+-{
+-	u16 cookie = 0x1000;
+-
+-	/* Use the upper 4 bits of the cookie as
+-	 * DMA controller ID and store the slot number
+-	 * in the lower 12 bits.
+-	 * Note that the cookie must never be 0, as this
+-	 * is a special value used in RX path.
+-	 */
+-	switch (ring->index) {
+-	case 0:
+-		cookie = 0xA000;
+-		break;
+-	case 1:
+-		cookie = 0xB000;
+-		break;
+-	case 2:
+-		cookie = 0xC000;
+-		break;
+-	case 3:
+-		cookie = 0xD000;
+-		break;
+-	case 4:
+-		cookie = 0xE000;
+-		break;
+-	case 5:
+-		cookie = 0xF000;
+-		break;
+-	}
+-	assert(((u16)slot & 0xF000) == 0x0000);
+-	cookie |= (u16)slot;
+-
+-	return cookie;
+-}
+-
+-/* Inspect a cookie and find out to which controller/slot it belongs. */
+-static
+-struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm,
+-				      u16 cookie, int *slot)
+-{
+-	struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
+-	struct bcm43xx_dmaring *ring = NULL;
+-
+-	switch (cookie & 0xF000) {
+-	case 0xA000:
+-		ring = dma->tx_ring0;
+-		break;
+-	case 0xB000:
+-		ring = dma->tx_ring1;
+-		break;
+-	case 0xC000:
+-		ring = dma->tx_ring2;
+-		break;
+-	case 0xD000:
+-		ring = dma->tx_ring3;
+-		break;
+-	case 0xE000:
+-		ring = dma->tx_ring4;
+-		break;
+-	case 0xF000:
+-		ring = dma->tx_ring5;
+-		break;
+-	default:
+-		assert(0);
+-	}
+-	*slot = (cookie & 0x0FFF);
+-	assert(*slot >= 0 && *slot < ring->nr_slots);
+-
+-	return ring;
+-}
+-
+-static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring,
+-				  int slot)
+-{
+-	u16 offset;
+-	int descsize;
+-
+-	/* Everything is ready to start. Buffers are DMA mapped and
+-	 * associated with slots.
+-	 * "slot" is the last slot of the new frame we want to transmit.
+-	 * Close your seat belts now, please.
+-	 */
+-	wmb();
+-	slot = next_slot(ring, slot);
+-	offset = (ring->dma64) ? BCM43xx_DMA64_TXINDEX : BCM43xx_DMA32_TXINDEX;
+-	descsize = (ring->dma64) ? sizeof(struct bcm43xx_dmadesc64)
+-		: sizeof(struct bcm43xx_dmadesc32);
+-	bcm43xx_dma_write(ring, offset,
+-			(u32)(slot * descsize));
+-}
+-
+-static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
+-			    struct sk_buff *skb,
+-			    u8 cur_frag)
+-{
+-	int slot;
+-	struct bcm43xx_dmadesc_generic *desc;
+-	struct bcm43xx_dmadesc_meta *meta;
+-	dma_addr_t dmaaddr;
+-	struct sk_buff *bounce_skb;
+-
+-	assert(skb_shinfo(skb)->nr_frags == 0);
+-
+-	slot = request_slot(ring);
+-	desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
+-
+-	/* Add a device specific TX header. */
+-	assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr));
+-	/* Reserve enough headroom for the device tx header. */
+-	__skb_push(skb, sizeof(struct bcm43xx_txhdr));
+-	/* Now calculate and add the tx header.
+-	 * The tx header includes the PLCP header.
+-	 */
+-	bcm43xx_generate_txhdr(ring->bcm,
+-			       (struct bcm43xx_txhdr *)skb->data,
+-			       skb->data + sizeof(struct bcm43xx_txhdr),
+-			       skb->len - sizeof(struct bcm43xx_txhdr),
+-			       (cur_frag == 0),
+-			       generate_cookie(ring, slot));
+-	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+-	if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+-		/* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
+-		if (!dma_mapping_error(dmaaddr))
+-			unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+-		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
+-		if (!bounce_skb)
+-			return;
+-		dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
+-		if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+-			if (!dma_mapping_error(dmaaddr))
+-				unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+-			dev_kfree_skb_any(bounce_skb);
+-			assert(0);
+-			return;
+-		}
+-		skb_copy_from_linear_data(skb, skb_put(bounce_skb, skb->len),
+-					  skb->len);
+-		dev_kfree_skb_any(skb);
+-		skb = bounce_skb;
+-	}
+-
+-	meta->skb = skb;
+-	meta->dmaaddr = dmaaddr;
+-
+-	fill_descriptor(ring, desc, dmaaddr,
+-			skb->len, 1, 1, 1);
+-
+-	/* Now transfer the whole frame. */
+-	dmacontroller_poke_tx(ring, slot);
+-}
+-
+-int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+-		   struct ieee80211_txb *txb)
+-{
+-	/* We just received a packet from the kernel network subsystem.
+-	 * Add headers and DMA map the memory. Poke
+-	 * the device to send the stuff.
+-	 * Note that this is called from atomic context.
+-	 */
+-	struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1;
+-	u8 i;
+-	struct sk_buff *skb;
+-
+-	assert(ring->tx);
+-	if (unlikely(free_slots(ring) < txb->nr_frags)) {
+-		/* The queue should be stopped,
+-		 * if we are low on free slots.
+-		 * If this ever triggers, we have to lower the suspend_mark.
+-		 */
+-		dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n");
+-		return -ENOMEM;
+-	}
+-
+-	for (i = 0; i < txb->nr_frags; i++) {
+-		skb = txb->fragments[i];
+-		/* Take skb from ieee80211_txb_free */
+-		txb->fragments[i] = NULL;
+-		dma_tx_fragment(ring, skb, i);
+-	}
+-	ieee80211_txb_free(txb);
+-
+-	return 0;
+-}
+-
+-void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+-				   struct bcm43xx_xmitstatus *status)
+-{
+-	struct bcm43xx_dmaring *ring;
+-	struct bcm43xx_dmadesc_generic *desc;
+-	struct bcm43xx_dmadesc_meta *meta;
+-	int is_last_fragment;
+-	int slot;
+-	u32 tmp;
+-
+-	ring = parse_cookie(bcm, status->cookie, &slot);
+-	assert(ring);
+-	assert(ring->tx);
+-	while (1) {
+-		assert(slot >= 0 && slot < ring->nr_slots);
+-		desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
+-
+-		if (ring->dma64) {
+-			tmp = le32_to_cpu(desc->dma64.control0);
+-			is_last_fragment = !!(tmp & BCM43xx_DMA64_DCTL0_FRAMEEND);
+-		} else {
+-			tmp = le32_to_cpu(desc->dma32.control);
+-			is_last_fragment = !!(tmp & BCM43xx_DMA32_DCTL_FRAMEEND);
+-		}
+-		unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+-		free_descriptor_buffer(ring, meta, 1);
+-		/* Everything belonging to the slot is unmapped
+-		 * and freed, so we can return it.
+-		 */
+-		return_slot(ring, slot);
+-
+-		if (is_last_fragment)
+-			break;
+-		slot = next_slot(ring, slot);
+-	}
+-	bcm->stats.last_tx = jiffies;
+-}
+-
+-static void dma_rx(struct bcm43xx_dmaring *ring,
+-		   int *slot)
+-{
+-	struct bcm43xx_dmadesc_generic *desc;
+-	struct bcm43xx_dmadesc_meta *meta;
+-	struct bcm43xx_rxhdr *rxhdr;
+-	struct sk_buff *skb;
+-	u16 len;
+-	int err;
+-	dma_addr_t dmaaddr;
+-
+-	desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
+-
+-	sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
+-	skb = meta->skb;
+-
+-	if (ring->index == 3) {
+-		/* We received an xmit status. */
+-		struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
+-		struct bcm43xx_xmitstatus stat;
+-		int i = 0;
+-
+-		stat.cookie = le16_to_cpu(hw->cookie);
+-		while (stat.cookie == 0) {
+-			if (unlikely(++i >= 10000)) {
+-				assert(0);
+-				break;
+-			}
+-			udelay(2);
+-			barrier();
+-			stat.cookie = le16_to_cpu(hw->cookie);
+-		}
+-		stat.flags = hw->flags;
+-		stat.cnt1 = hw->cnt1;
+-		stat.cnt2 = hw->cnt2;
+-		stat.seq = le16_to_cpu(hw->seq);
+-		stat.unknown = le16_to_cpu(hw->unknown);
+-
+-		bcm43xx_debugfs_log_txstat(ring->bcm, &stat);
+-		bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat);
+-		/* recycle the descriptor buffer. */
+-		sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize);
+-
+-		return;
+-	}
+-	rxhdr = (struct bcm43xx_rxhdr *)skb->data;
+-	len = le16_to_cpu(rxhdr->frame_length);
+-	if (len == 0) {
+-		int i = 0;
+-
+-		do {
+-			udelay(2);
+-			barrier();
+-			len = le16_to_cpu(rxhdr->frame_length);
+-		} while (len == 0 && i++ < 5);
+-		if (unlikely(len == 0)) {
+-			/* recycle the descriptor buffer. */
+-			sync_descbuffer_for_device(ring, meta->dmaaddr,
+-						   ring->rx_buffersize);
+-			goto drop;
+-		}
+-	}
+-	if (unlikely(len > ring->rx_buffersize)) {
+-		/* The data did not fit into one descriptor buffer
+-		 * and is split over multiple buffers.
+-		 * This should never happen, as we try to allocate buffers
+-		 * big enough. So simply ignore this packet.
+-		 */
+-		int cnt = 0;
+-		s32 tmp = len;
+-
+-		while (1) {
+-			desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
+-			/* recycle the descriptor buffer. */
+-			sync_descbuffer_for_device(ring, meta->dmaaddr,
+-						   ring->rx_buffersize);
+-			*slot = next_slot(ring, *slot);
+-			cnt++;
+-			tmp -= ring->rx_buffersize;
+-			if (tmp <= 0)
+-				break;
+-		}
+-		printkl(KERN_ERR PFX "DMA RX buffer too small "
+-			"(len: %u, buffer: %u, nr-dropped: %d)\n",
+-			len, ring->rx_buffersize, cnt);
+-		goto drop;
+-	}
+-	len -= IEEE80211_FCS_LEN;
+-
+-	dmaaddr = meta->dmaaddr;
+-	err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
+-	if (unlikely(err)) {
+-		dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n");
+-		sync_descbuffer_for_device(ring, dmaaddr,
+-					   ring->rx_buffersize);
+-		goto drop;
+-	}
+-
+-	unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
+-	skb_put(skb, len + ring->frameoffset);
+-	skb_pull(skb, ring->frameoffset);
+-
+-	err = bcm43xx_rx(ring->bcm, skb, rxhdr);
+-	if (err) {
+-		dev_kfree_skb_irq(skb);
+-		goto drop;
+-	}
+-
+-drop:
+-	return;
+-}
+-
+-void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
+-{
+-	u32 status;
+-	u16 descptr;
+-	int slot, current_slot;
+-#ifdef CONFIG_BCM43XX_DEBUG
+-	int used_slots = 0;
+-#endif
+-
+-	assert(!ring->tx);
+-	if (ring->dma64) {
+-		status = bcm43xx_dma_read(ring, BCM43xx_DMA64_RXSTATUS);
+-		descptr = (status & BCM43xx_DMA64_RXSTATDPTR);
+-		current_slot = descptr / sizeof(struct bcm43xx_dmadesc64);
+-	} else {
+-		status = bcm43xx_dma_read(ring, BCM43xx_DMA32_RXSTATUS);
+-		descptr = (status & BCM43xx_DMA32_RXDPTR);
+-		current_slot = descptr / sizeof(struct bcm43xx_dmadesc32);
+-	}
+-	assert(current_slot >= 0 && current_slot < ring->nr_slots);
+-
+-	slot = ring->current_slot;
+-	for ( ; slot != current_slot; slot = next_slot(ring, slot)) {
+-		dma_rx(ring, &slot);
+-#ifdef CONFIG_BCM43XX_DEBUG
+-		if (++used_slots > ring->max_used_slots)
+-			ring->max_used_slots = used_slots;
+-#endif
+-	}
+-	if (ring->dma64) {
+-		bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX,
+-				(u32)(slot * sizeof(struct bcm43xx_dmadesc64)));
+-	} else {
+-		bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX,
+-				(u32)(slot * sizeof(struct bcm43xx_dmadesc32)));
+-	}
+-	ring->current_slot = slot;
+-}
+-
+-void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+-{
+-	assert(ring->tx);
+-	bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1);
+-	if (ring->dma64) {
+-		bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
+-				bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
+-				| BCM43xx_DMA64_TXSUSPEND);
+-	} else {
+-		bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
+-				bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
+-				| BCM43xx_DMA32_TXSUSPEND);
+-	}
+-}
+-
+-void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+-{
+-	assert(ring->tx);
+-	if (ring->dma64) {
+-		bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
+-				bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
+-				& ~BCM43xx_DMA64_TXSUSPEND);
+-	} else {
+-		bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
+-				bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
+-				& ~BCM43xx_DMA32_TXSUSPEND);
+-	}
+-	bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1);
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+deleted file mode 100644
+index d1105e5..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
++++ /dev/null
+@@ -1,386 +0,0 @@
+-#ifndef BCM43xx_DMA_H_
+-#define BCM43xx_DMA_H_
+-
+-#include <linux/list.h>
+-#include <linux/spinlock.h>
+-#include <linux/workqueue.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/linkage.h>
+-#include <asm/atomic.h>
+-
+-
+-/* DMA-Interrupt reasons. */
+-#define BCM43xx_DMAIRQ_FATALMASK	((1 << 10) | (1 << 11) | (1 << 12) \
+-					 | (1 << 14) | (1 << 15))
+-#define BCM43xx_DMAIRQ_NONFATALMASK	(1 << 13)
+-#define BCM43xx_DMAIRQ_RX_DONE		(1 << 16)
+-
+-
+-/*** 32-bit DMA Engine. ***/
+-
+-/* 32-bit DMA controller registers. */
+-#define BCM43xx_DMA32_TXCTL				0x00
+-#define		BCM43xx_DMA32_TXENABLE			0x00000001
+-#define		BCM43xx_DMA32_TXSUSPEND			0x00000002
+-#define		BCM43xx_DMA32_TXLOOPBACK		0x00000004
+-#define		BCM43xx_DMA32_TXFLUSH			0x00000010
+-#define		BCM43xx_DMA32_TXADDREXT_MASK		0x00030000
+-#define		BCM43xx_DMA32_TXADDREXT_SHIFT		16
+-#define BCM43xx_DMA32_TXRING				0x04
+-#define BCM43xx_DMA32_TXINDEX				0x08
+-#define BCM43xx_DMA32_TXSTATUS				0x0C
+-#define		BCM43xx_DMA32_TXDPTR			0x00000FFF
+-#define		BCM43xx_DMA32_TXSTATE			0x0000F000
+-#define			BCM43xx_DMA32_TXSTAT_DISABLED	0x00000000
+-#define			BCM43xx_DMA32_TXSTAT_ACTIVE	0x00001000
+-#define			BCM43xx_DMA32_TXSTAT_IDLEWAIT	0x00002000
+-#define			BCM43xx_DMA32_TXSTAT_STOPPED	0x00003000
+-#define			BCM43xx_DMA32_TXSTAT_SUSP	0x00004000
+-#define		BCM43xx_DMA32_TXERROR			0x000F0000
+-#define			BCM43xx_DMA32_TXERR_NOERR	0x00000000
+-#define			BCM43xx_DMA32_TXERR_PROT	0x00010000
+-#define			BCM43xx_DMA32_TXERR_UNDERRUN	0x00020000
+-#define			BCM43xx_DMA32_TXERR_BUFREAD	0x00030000
+-#define			BCM43xx_DMA32_TXERR_DESCREAD	0x00040000
+-#define		BCM43xx_DMA32_TXACTIVE			0xFFF00000
+-#define BCM43xx_DMA32_RXCTL				0x10
+-#define		BCM43xx_DMA32_RXENABLE			0x00000001
+-#define		BCM43xx_DMA32_RXFROFF_MASK		0x000000FE
+-#define		BCM43xx_DMA32_RXFROFF_SHIFT		1
+-#define		BCM43xx_DMA32_RXDIRECTFIFO		0x00000100
+-#define		BCM43xx_DMA32_RXADDREXT_MASK		0x00030000
+-#define		BCM43xx_DMA32_RXADDREXT_SHIFT		16
+-#define BCM43xx_DMA32_RXRING				0x14
+-#define BCM43xx_DMA32_RXINDEX				0x18
+-#define BCM43xx_DMA32_RXSTATUS				0x1C
+-#define		BCM43xx_DMA32_RXDPTR			0x00000FFF
+-#define		BCM43xx_DMA32_RXSTATE			0x0000F000
+-#define			BCM43xx_DMA32_RXSTAT_DISABLED	0x00000000
+-#define			BCM43xx_DMA32_RXSTAT_ACTIVE	0x00001000
+-#define			BCM43xx_DMA32_RXSTAT_IDLEWAIT	0x00002000
+-#define			BCM43xx_DMA32_RXSTAT_STOPPED	0x00003000
+-#define		BCM43xx_DMA32_RXERROR			0x000F0000
+-#define			BCM43xx_DMA32_RXERR_NOERR	0x00000000
+-#define			BCM43xx_DMA32_RXERR_PROT	0x00010000
+-#define			BCM43xx_DMA32_RXERR_OVERFLOW	0x00020000
+-#define			BCM43xx_DMA32_RXERR_BUFWRITE	0x00030000
+-#define			BCM43xx_DMA32_RXERR_DESCREAD	0x00040000
+-#define		BCM43xx_DMA32_RXACTIVE			0xFFF00000
+-
+-/* 32-bit DMA descriptor. */
+-struct bcm43xx_dmadesc32 {
+-	__le32 control;
+-	__le32 address;
+-} __attribute__((__packed__));
+-#define BCM43xx_DMA32_DCTL_BYTECNT		0x00001FFF
+-#define BCM43xx_DMA32_DCTL_ADDREXT_MASK		0x00030000
+-#define BCM43xx_DMA32_DCTL_ADDREXT_SHIFT	16
+-#define BCM43xx_DMA32_DCTL_DTABLEEND		0x10000000
+-#define BCM43xx_DMA32_DCTL_IRQ			0x20000000
+-#define BCM43xx_DMA32_DCTL_FRAMEEND		0x40000000
+-#define BCM43xx_DMA32_DCTL_FRAMESTART		0x80000000
+-
+-/* Address field Routing value. */
+-#define BCM43xx_DMA32_ROUTING			0xC0000000
+-#define BCM43xx_DMA32_ROUTING_SHIFT		30
+-#define		BCM43xx_DMA32_NOTRANS		0x00000000
+-#define		BCM43xx_DMA32_CLIENTTRANS	0x40000000
+-
+-
+-
+-/*** 64-bit DMA Engine. ***/
+-
+-/* 64-bit DMA controller registers. */
+-#define BCM43xx_DMA64_TXCTL				0x00
+-#define		BCM43xx_DMA64_TXENABLE			0x00000001
+-#define		BCM43xx_DMA64_TXSUSPEND			0x00000002
+-#define		BCM43xx_DMA64_TXLOOPBACK		0x00000004
+-#define		BCM43xx_DMA64_TXFLUSH			0x00000010
+-#define		BCM43xx_DMA64_TXADDREXT_MASK		0x00030000
+-#define		BCM43xx_DMA64_TXADDREXT_SHIFT		16
+-#define BCM43xx_DMA64_TXINDEX				0x04
+-#define BCM43xx_DMA64_TXRINGLO				0x08
+-#define BCM43xx_DMA64_TXRINGHI				0x0C
+-#define BCM43xx_DMA64_TXSTATUS				0x10
+-#define		BCM43xx_DMA64_TXSTATDPTR		0x00001FFF
+-#define		BCM43xx_DMA64_TXSTAT			0xF0000000
+-#define			BCM43xx_DMA64_TXSTAT_DISABLED	0x00000000
+-#define			BCM43xx_DMA64_TXSTAT_ACTIVE	0x10000000
+-#define			BCM43xx_DMA64_TXSTAT_IDLEWAIT	0x20000000
+-#define			BCM43xx_DMA64_TXSTAT_STOPPED	0x30000000
+-#define			BCM43xx_DMA64_TXSTAT_SUSP	0x40000000
+-#define BCM43xx_DMA64_TXERROR				0x14
+-#define		BCM43xx_DMA64_TXERRDPTR			0x0001FFFF
+-#define		BCM43xx_DMA64_TXERR			0xF0000000
+-#define			BCM43xx_DMA64_TXERR_NOERR	0x00000000
+-#define			BCM43xx_DMA64_TXERR_PROT	0x10000000
+-#define			BCM43xx_DMA64_TXERR_UNDERRUN	0x20000000
+-#define			BCM43xx_DMA64_TXERR_TRANSFER	0x30000000
+-#define			BCM43xx_DMA64_TXERR_DESCREAD	0x40000000
+-#define			BCM43xx_DMA64_TXERR_CORE	0x50000000
+-#define BCM43xx_DMA64_RXCTL				0x20
+-#define		BCM43xx_DMA64_RXENABLE			0x00000001
+-#define		BCM43xx_DMA64_RXFROFF_MASK		0x000000FE
+-#define		BCM43xx_DMA64_RXFROFF_SHIFT		1
+-#define		BCM43xx_DMA64_RXDIRECTFIFO		0x00000100
+-#define		BCM43xx_DMA64_RXADDREXT_MASK		0x00030000
+-#define		BCM43xx_DMA64_RXADDREXT_SHIFT		16
+-#define BCM43xx_DMA64_RXINDEX				0x24
+-#define BCM43xx_DMA64_RXRINGLO				0x28
+-#define BCM43xx_DMA64_RXRINGHI				0x2C
+-#define BCM43xx_DMA64_RXSTATUS				0x30
+-#define		BCM43xx_DMA64_RXSTATDPTR		0x00001FFF
+-#define		BCM43xx_DMA64_RXSTAT			0xF0000000
+-#define			BCM43xx_DMA64_RXSTAT_DISABLED	0x00000000
+-#define			BCM43xx_DMA64_RXSTAT_ACTIVE	0x10000000
+-#define			BCM43xx_DMA64_RXSTAT_IDLEWAIT	0x20000000
+-#define			BCM43xx_DMA64_RXSTAT_STOPPED	0x30000000
+-#define			BCM43xx_DMA64_RXSTAT_SUSP	0x40000000
+-#define BCM43xx_DMA64_RXERROR				0x34
+-#define		BCM43xx_DMA64_RXERRDPTR			0x0001FFFF
+-#define		BCM43xx_DMA64_RXERR			0xF0000000
+-#define			BCM43xx_DMA64_RXERR_NOERR	0x00000000
+-#define			BCM43xx_DMA64_RXERR_PROT	0x10000000
+-#define			BCM43xx_DMA64_RXERR_UNDERRUN	0x20000000
+-#define			BCM43xx_DMA64_RXERR_TRANSFER	0x30000000
+-#define			BCM43xx_DMA64_RXERR_DESCREAD	0x40000000
+-#define			BCM43xx_DMA64_RXERR_CORE	0x50000000
+-
+-/* 64-bit DMA descriptor. */
+-struct bcm43xx_dmadesc64 {
+-	__le32 control0;
+-	__le32 control1;
+-	__le32 address_low;
+-	__le32 address_high;
+-} __attribute__((__packed__));
+-#define BCM43xx_DMA64_DCTL0_DTABLEEND		0x10000000
+-#define BCM43xx_DMA64_DCTL0_IRQ			0x20000000
+-#define BCM43xx_DMA64_DCTL0_FRAMEEND		0x40000000
+-#define BCM43xx_DMA64_DCTL0_FRAMESTART		0x80000000
+-#define BCM43xx_DMA64_DCTL1_BYTECNT		0x00001FFF
+-#define BCM43xx_DMA64_DCTL1_ADDREXT_MASK	0x00030000
+-#define BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT	16
+-
+-/* Address field Routing value. */
+-#define BCM43xx_DMA64_ROUTING			0xC0000000
+-#define BCM43xx_DMA64_ROUTING_SHIFT		30
+-#define		BCM43xx_DMA64_NOTRANS		0x00000000
+-#define		BCM43xx_DMA64_CLIENTTRANS	0x80000000
+-
+-
+-
+-struct bcm43xx_dmadesc_generic {
+-	union {
+-		struct bcm43xx_dmadesc32 dma32;
+-		struct bcm43xx_dmadesc64 dma64;
+-	} __attribute__((__packed__));
+-} __attribute__((__packed__));
+-
+-
+-/* Misc DMA constants */
+-#define BCM43xx_DMA_RINGMEMSIZE		PAGE_SIZE
+-#define BCM43xx_DMA0_RX_FRAMEOFFSET	30
+-#define BCM43xx_DMA3_RX_FRAMEOFFSET	0
+-
+-
+-/* DMA engine tuning knobs */
+-#define BCM43xx_TXRING_SLOTS		512
+-#define BCM43xx_RXRING_SLOTS		64
+-#define BCM43xx_DMA0_RX_BUFFERSIZE	(2304 + 100)
+-#define BCM43xx_DMA3_RX_BUFFERSIZE	16
+-/* Suspend the tx queue, if less than this percent slots are free. */
+-#define BCM43xx_TXSUSPEND_PERCENT	20
+-/* Resume the tx queue, if more than this percent slots are free. */
+-#define BCM43xx_TXRESUME_PERCENT	50
+-
+-
+-
+-#ifdef CONFIG_BCM43XX_DMA
+-
+-
+-struct sk_buff;
+-struct bcm43xx_private;
+-struct bcm43xx_xmitstatus;
+-
+-
+-struct bcm43xx_dmadesc_meta {
+-	/* The kernel DMA-able buffer. */
+-	struct sk_buff *skb;
+-	/* DMA base bus-address of the descriptor buffer. */
+-	dma_addr_t dmaaddr;
+-};
+-
+-struct bcm43xx_dmaring {
+-	/* Kernel virtual base address of the ring memory. */
+-	void *descbase;
+-	/* Meta data about all descriptors. */
+-	struct bcm43xx_dmadesc_meta *meta;
+-	/* DMA Routing value. */
+-	u32 routing;
+-	/* (Unadjusted) DMA base bus-address of the ring memory. */
+-	dma_addr_t dmabase;
+-	/* Number of descriptor slots in the ring. */
+-	int nr_slots;
+-	/* Number of used descriptor slots. */
+-	int used_slots;
+-	/* Currently used slot in the ring. */
+-	int current_slot;
+-	/* Marks to suspend/resume the queue. */
+-	int suspend_mark;
+-	int resume_mark;
+-	/* Frameoffset in octets. */
+-	u32 frameoffset;
+-	/* Descriptor buffer size. */
+-	u16 rx_buffersize;
+-	/* The MMIO base register of the DMA controller. */
+-	u16 mmio_base;
+-	/* DMA controller index number (0-5). */
+-	int index;
+-	/* Boolean. Is this a TX ring? */
+-	u8 tx;
+-	/* Boolean. 64bit DMA if true, 32bit DMA otherwise. */
+-	u8 dma64;
+-	/* Boolean. Are transfers suspended on this ring? */
+-	u8 suspended;
+-	struct bcm43xx_private *bcm;
+-#ifdef CONFIG_BCM43XX_DEBUG
+-	/* Maximum number of used slots. */
+-	int max_used_slots;
+-#endif /* CONFIG_BCM43XX_DEBUG*/
+-};
+-
+-
+-static inline
+-int bcm43xx_dma_desc2idx(struct bcm43xx_dmaring *ring,
+-			 struct bcm43xx_dmadesc_generic *desc)
+-{
+-	if (ring->dma64) {
+-		struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
+-		return (int)(&(desc->dma64) - dd64);
+-	} else {
+-		struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
+-		return (int)(&(desc->dma32) - dd32);
+-	}
+-}
+-
+-static inline
+-struct bcm43xx_dmadesc_generic * bcm43xx_dma_idx2desc(struct bcm43xx_dmaring *ring,
+-						      int slot,
+-						      struct bcm43xx_dmadesc_meta **meta)
+-{
+-	*meta = &(ring->meta[slot]);
+-	if (ring->dma64) {
+-		struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
+-		return (struct bcm43xx_dmadesc_generic *)(&(dd64[slot]));
+-	} else {
+-		struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
+-		return (struct bcm43xx_dmadesc_generic *)(&(dd32[slot]));
+-	}
+-}
+-
+-static inline
+-u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring,
+-		     u16 offset)
+-{
+-	return bcm43xx_read32(ring->bcm, ring->mmio_base + offset);
+-}
+-
+-static inline
+-void bcm43xx_dma_write(struct bcm43xx_dmaring *ring,
+-		       u16 offset, u32 value)
+-{
+-	bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value);
+-}
+-
+-
+-int bcm43xx_dma_init(struct bcm43xx_private *bcm);
+-void bcm43xx_dma_free(struct bcm43xx_private *bcm);
+-
+-int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+-				   u16 dmacontroller_mmio_base,
+-				   int dma64);
+-int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+-				   u16 dmacontroller_mmio_base,
+-				   int dma64);
+-
+-u16 bcm43xx_dmacontroller_base(int dma64bit, int dmacontroller_idx);
+-
+-void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring);
+-void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring);
+-
+-void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+-				   struct bcm43xx_xmitstatus *status);
+-
+-int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+-		   struct ieee80211_txb *txb);
+-void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
+-
+-/* Helper function that returns the dma mask for this device. */
+-static inline
+-u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm)
+-{
+-	int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) &
+-				   BCM43xx_SBTMSTATEHIGH_DMA64BIT;
+-	u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0);
+-	u32 mask = BCM43xx_DMA32_TXADDREXT_MASK;
+-
+-	if (dma64)
+-		return DMA_64BIT_MASK;
+-	bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask);
+-	if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask)
+-		return DMA_32BIT_MASK;
+-	return DMA_30BIT_MASK;
+-}
+-
+-#else /* CONFIG_BCM43XX_DMA */
+-
+-
+-static inline
+-int bcm43xx_dma_init(struct bcm43xx_private *bcm)
+-{
+-	return 0;
+-}
+-static inline
+-void bcm43xx_dma_free(struct bcm43xx_private *bcm)
+-{
+-}
+-static inline
+-int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+-				   u16 dmacontroller_mmio_base,
+-				   int dma64)
+-{
+-	return 0;
+-}
+-static inline
+-int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+-				   u16 dmacontroller_mmio_base,
+-				   int dma64)
+-{
+-	return 0;
+-}
+-static inline
+-int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+-		   struct ieee80211_txb *txb)
+-{
+-	return 0;
+-}
+-static inline
+-void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+-				   struct bcm43xx_xmitstatus *status)
+-{
+-}
+-static inline
+-void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
+-{
+-}
+-static inline
+-void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+-{
+-}
+-static inline
+-void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+-{
+-}
+-
+-#endif /* CONFIG_BCM43XX_DMA */
+-#endif /* BCM43xx_DMA_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
+deleted file mode 100644
+index d2df6a0..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
++++ /dev/null
+@@ -1,50 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  ethtool support
+-
+-  Copyright (c) 2006 Jason Lunz <lunz at falooley.org>
+-
+-  Some code in this file is derived from the 8139too.c driver
+-  Copyright (C) 2002 Jeff Garzik
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 "bcm43xx.h"
+-#include "bcm43xx_ethtool.h"
+-
+-#include <linux/netdevice.h>
+-#include <linux/pci.h>
+-#include <linux/string.h>
+-#include <linux/utsname.h>
+-
+-
+-static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(dev);
+-
+-	strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+-	strncpy(info->version, utsname()->release, sizeof(info->version));
+-	strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN);
+-}
+-
+-const struct ethtool_ops bcm43xx_ethtool_ops = {
+-	.get_drvinfo = bcm43xx_get_drvinfo,
+-	.get_link = ethtool_op_get_link,
+-};
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
+deleted file mode 100644
+index 6f8d42d..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
++++ /dev/null
+@@ -1,8 +0,0 @@
+-#ifndef BCM43xx_ETHTOOL_H_
+-#define BCM43xx_ETHTOOL_H_
+-
+-#include <linux/ethtool.h>
+-
+-extern const struct ethtool_ops bcm43xx_ethtool_ops;
+-
+-#endif /* BCM43xx_ETHTOOL_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
+deleted file mode 100644
+index f2b8dba..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
++++ /dev/null
+@@ -1,352 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 "bcm43xx.h"
+-#include "bcm43xx_ilt.h"
+-#include "bcm43xx_phy.h"
+-
+-
+-/**** Initial Internal Lookup Tables ****/
+-
+-const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = {
+-	0xFEB93FFD, 0xFEC63FFD, /* 0 */
+-	0xFED23FFD, 0xFEDF3FFD,
+-	0xFEEC3FFE, 0xFEF83FFE,
+-	0xFF053FFE, 0xFF113FFE,
+-	0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
+-	0xFF373FFF, 0xFF443FFF,
+-	0xFF503FFF, 0xFF5D3FFF,
+-	0xFF693FFF, 0xFF763FFF,
+-	0xFF824000, 0xFF8F4000, /* 16 */
+-	0xFF9B4000, 0xFFA84000,
+-	0xFFB54000, 0xFFC14000,
+-	0xFFCE4000, 0xFFDA4000,
+-	0xFFE74000, 0xFFF34000, /* 24 */
+-	0x00004000, 0x000D4000,
+-	0x00194000, 0x00264000,
+-	0x00324000, 0x003F4000,
+-	0x004B4000, 0x00584000, /* 32 */
+-	0x00654000, 0x00714000,
+-	0x007E4000, 0x008A3FFF,
+-	0x00973FFF, 0x00A33FFF,
+-	0x00B03FFF, 0x00BC3FFF, /* 40 */
+-	0x00C93FFF, 0x00D63FFF,
+-	0x00E23FFE, 0x00EF3FFE,
+-	0x00FB3FFE, 0x01083FFE,
+-	0x01143FFE, 0x01213FFD, /* 48 */
+-	0x012E3FFD, 0x013A3FFD,
+-	0x01473FFD,
+-};
+-
+-const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = {
+-	0xDB93CB87, 0xD666CF64, /* 0 */
+-	0xD1FDD358, 0xCDA6D826,
+-	0xCA38DD9F, 0xC729E2B4,
+-	0xC469E88E, 0xC26AEE2B,
+-	0xC0DEF46C, 0xC073FA62, /* 8 */
+-	0xC01D00D5, 0xC0760743,
+-	0xC1560D1E, 0xC2E51369,
+-	0xC4ED18FF, 0xC7AC1ED7,
+-	0xCB2823B2, 0xCEFA28D9, /* 16 */
+-	0xD2F62D3F, 0xD7BB3197,
+-	0xDCE53568, 0xE1FE3875,
+-	0xE7D13B35, 0xED663D35,
+-	0xF39B3EC4, 0xF98E3FA7, /* 24 */
+-	0x00004000, 0x06723FA7,
+-	0x0C653EC4, 0x129A3D35,
+-	0x182F3B35, 0x1E023875,
+-	0x231B3568, 0x28453197, /* 32 */
+-	0x2D0A2D3F, 0x310628D9,
+-	0x34D823B2, 0x38541ED7,
+-	0x3B1318FF, 0x3D1B1369,
+-	0x3EAA0D1E, 0x3F8A0743, /* 40 */
+-	0x3FE300D5, 0x3F8DFA62,
+-	0x3F22F46C, 0x3D96EE2B,
+-	0x3B97E88E, 0x38D7E2B4,
+-	0x35C8DD9F, 0x325AD826, /* 48 */
+-	0x2E03D358, 0x299ACF64,
+-	0x246DCB87,
+-};
+-
+-const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = {
+-	0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
+- 	0x0202, 0x0282, 0x0302, 0x0382,
+- 	0x0402, 0x0482, 0x0502, 0x0582,
+- 	0x05E2, 0x0662, 0x06E2, 0x0762,
+- 	0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
+- 	0x09C2, 0x0A22, 0x0AA2, 0x0B02,
+- 	0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
+- 	0x0D42, 0x0DA2, 0x0E02, 0x0E62,
+- 	0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
+- 	0x1062, 0x10C2, 0x1122, 0x1182,
+- 	0x11E2, 0x1242, 0x12A2, 0x12E2,
+- 	0x1342, 0x13A2, 0x1402, 0x1442,
+- 	0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
+- 	0x15E2, 0x1622, 0x1662, 0x16C1,
+- 	0x1701, 0x1741, 0x1781, 0x17E1,
+- 	0x1821, 0x1861, 0x18A1, 0x18E1,
+- 	0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
+- 	0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
+- 	0x1B01, 0x1B41, 0x1B81, 0x1BA1,
+- 	0x1BE1, 0x1C21, 0x1C41, 0x1C81,
+- 	0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
+- 	0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
+- 	0x1E21, 0x1E61, 0x1E81, 0x1EA1,
+- 	0x1EE1, 0x1F01, 0x1F21, 0x1F41,
+- 	0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
+- 	0x2001, 0x2041, 0x2061, 0x2081,
+- 	0x20A1, 0x20C1, 0x20E1, 0x2101,
+- 	0x2121, 0x2141, 0x2161, 0x2181,
+- 	0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
+- 	0x2221, 0x2241, 0x2261, 0x2281,
+- 	0x22A1, 0x22C1, 0x22C1, 0x22E1,
+- 	0x2301, 0x2321, 0x2341, 0x2361,
+- 	0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
+- 	0x23E1, 0x23E1, 0x2401, 0x2421,
+- 	0x2441, 0x2441, 0x2461, 0x2481,
+- 	0x2481, 0x24A1, 0x24C1, 0x24C1,
+- 	0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
+- 	0x2541, 0x2541, 0x2561, 0x2561,
+- 	0x2581, 0x25A1, 0x25A1, 0x25C1,
+- 	0x25C1, 0x25E1, 0x2601, 0x2601,
+- 	0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
+- 	0x2661, 0x2661, 0x2681, 0x2681,
+- 	0x26A1, 0x26A1, 0x26C1, 0x26C1,
+- 	0x26E1, 0x26E1, 0x2701, 0x2701,
+- 	0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
+- 	0x2760, 0x2760, 0x2780, 0x2780,
+- 	0x2780, 0x27A0, 0x27A0, 0x27C0,
+- 	0x27C0, 0x27E0, 0x27E0, 0x27E0,
+- 	0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
+- 	0x2820, 0x2840, 0x2840, 0x2840,
+- 	0x2860, 0x2860, 0x2880, 0x2880,
+- 	0x2880, 0x28A0, 0x28A0, 0x28A0,
+- 	0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
+- 	0x28E0, 0x28E0, 0x2900, 0x2900,
+- 	0x2900, 0x2920, 0x2920, 0x2920,
+- 	0x2940, 0x2940, 0x2940, 0x2960,
+- 	0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
+- 	0x2980, 0x2980, 0x29A0, 0x29A0,
+- 	0x29A0, 0x29A0, 0x29C0, 0x29C0,
+- 	0x29C0, 0x29E0, 0x29E0, 0x29E0,
+- 	0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
+- 	0x2A00, 0x2A20, 0x2A20, 0x2A20,
+- 	0x2A20, 0x2A40, 0x2A40, 0x2A40,
+- 	0x2A40, 0x2A60, 0x2A60, 0x2A60,
+-};
+-
+-const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = {
+-	0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
+-	0x05A9, 0x0669, 0x0709, 0x0789,
+-	0x0829, 0x08A9, 0x0929, 0x0989,
+-	0x0A09, 0x0A69, 0x0AC9, 0x0B29,
+-	0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
+-	0x0D09, 0x0D69, 0x0DA9, 0x0E09,
+-	0x0E69, 0x0EA9, 0x0F09, 0x0F49,
+-	0x0FA9, 0x0FE9, 0x1029, 0x1089,
+-	0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
+-	0x11E9, 0x1229, 0x1289, 0x12C9,
+-	0x1309, 0x1349, 0x1389, 0x13C9,
+-	0x1409, 0x1449, 0x14A9, 0x14E9,
+-	0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
+-	0x1629, 0x1669, 0x16A9, 0x16E8,
+-	0x1728, 0x1768, 0x17A8, 0x17E8,
+-	0x1828, 0x1868, 0x18A8, 0x18E8,
+-	0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
+-	0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
+-	0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
+-	0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
+-	0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
+-	0x1E48, 0x1E88, 0x1EC8, 0x1F08,
+-	0x1F48, 0x1F88, 0x1FE8, 0x2028,
+-	0x2068, 0x20A8, 0x2108, 0x2148,
+-	0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
+-	0x22C8, 0x2308, 0x2348, 0x23A8,
+-	0x23E8, 0x2448, 0x24A8, 0x24E8,
+-	0x2548, 0x25A8, 0x2608, 0x2668,
+-	0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
+-	0x2847, 0x28C7, 0x2947, 0x29A7,
+-	0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
+-	0x2CA7, 0x2D67, 0x2E47, 0x2F67,
+-	0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
+-	0x3806, 0x38A6, 0x3946, 0x39E6,
+-	0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
+-	0x3C45, 0x3CA5, 0x3D05, 0x3D85,
+-	0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
+-	0x3F45, 0x3FA5, 0x4005, 0x4045,
+-	0x40A5, 0x40E5, 0x4145, 0x4185,
+-	0x41E5, 0x4225, 0x4265, 0x42C5,
+-	0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
+-	0x4424, 0x4464, 0x44C4, 0x4504,
+-	0x4544, 0x4584, 0x45C4, 0x4604,
+-	0x4644, 0x46A4, 0x46E4, 0x4724,
+-	0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
+-	0x4864, 0x48A4, 0x48E4, 0x4924,
+-	0x4964, 0x49A4, 0x49E4, 0x4A24,
+-	0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
+-	0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
+-	0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
+-	0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
+-	0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
+-	0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
+-	0x5083, 0x50C3, 0x5103, 0x5143,
+-	0x5183, 0x51E2, 0x5222, 0x5262,
+-	0x52A2, 0x52E2, 0x5342, 0x5382,
+-	0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
+-	0x5502, 0x5542, 0x55A2, 0x55E2,
+-	0x5642, 0x5682, 0x56E2, 0x5722,
+-	0x5782, 0x57E1, 0x5841, 0x58A1,
+-	0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
+-	0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
+-	0x5C61, 0x5D01, 0x5D80, 0x5E20,
+-	0x5EE0, 0x5FA0, 0x6080, 0x61C0,
+-};
+-
+-const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = {
+-	0x0001, 0x0001, 0x0001, 0xFFFE,
+-	0xFFFE, 0x3FFF, 0x1000, 0x0393,
+-};
+-
+-const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = {
+-	0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+-	0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+-};
+-
+-const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = {
+-	0x013C, 0x01F5, 0x031A, 0x0631,
+-	0x0001, 0x0001, 0x0001, 0x0001,
+-};
+-
+-const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = {
+-	0x5484, 0x3C40, 0x0000, 0x0000,
+-	0x0000, 0x0000, 0x0000, 0x0000,
+-};
+-
+-const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+-	0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
+-	0x2F2D, 0x2A2A, 0x2527, 0x1F21,
+-	0x1A1D, 0x1719, 0x1616, 0x1414,
+-	0x1414, 0x1400, 0x1414, 0x1614,
+-	0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
+-	0x2A27, 0x2F2A, 0x332D, 0x3B35,
+-	0x5140, 0x6C62, 0x0077,
+-};
+-
+-const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+-	0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
+-	0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
+-	0x969B, 0x9195, 0x8F8F, 0x8A8A,
+-	0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
+-	0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
+-	0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
+-	0xCBC0, 0xD8D4, 0x00DD,
+-};
+-
+-const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+-	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
+-	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+-	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+-	0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
+-	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
+-	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+-	0xA4A4, 0xA4A4, 0x00A4,
+-};
+-
+-const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = {
+-	0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
+-	0x0067, 0x0063, 0x005E, 0x0059,
+-	0x0054, 0x0050, 0x004B, 0x0046,
+-	0x0042, 0x003D, 0x003D, 0x003D,
+-	0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
+-	0x003D, 0x003D, 0x003D, 0x003D,
+-	0x003D, 0x003D, 0x0000, 0x003D,
+-	0x003D, 0x003D, 0x003D, 0x003D,
+-	0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
+-	0x003D, 0x003D, 0x003D, 0x003D,
+-	0x0042, 0x0046, 0x004B, 0x0050,
+-	0x0054, 0x0059, 0x005E, 0x0063,
+-	0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
+-	0x007A,
+-};
+-
+-const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = {
+-	0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
+-	0x00D6, 0x00D4, 0x00D2, 0x00CF,
+-	0x00CD, 0x00CA, 0x00C7, 0x00C4,
+-	0x00C1, 0x00BE, 0x00BE, 0x00BE,
+-	0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
+-	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+-	0x00BE, 0x00BE, 0x0000, 0x00BE,
+-	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+-	0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
+-	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+-	0x00C1, 0x00C4, 0x00C7, 0x00CA,
+-	0x00CD, 0x00CF, 0x00D2, 0x00D4,
+-	0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
+-	0x00DE,
+-};
+-
+-/**** Helper functions to access the device Internal Lookup Tables ****/
+-
+-void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
+-{
+-	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+-		mmiowb();
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val);
+-	} else {
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+-		mmiowb();
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val);
+-	}
+-}
+-
+-void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val)
+-{
+-	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+-		mmiowb();
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16);
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF);
+-	} else {
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+-		mmiowb();
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16);
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF);
+-	}
+-}
+-
+-u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
+-{
+-	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+-		return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1);
+-	} else {
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+-		return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1);
+-	}
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
+deleted file mode 100644
+index d7eaf5f..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
++++ /dev/null
+@@ -1,33 +0,0 @@
+-#ifndef BCM43xx_ILT_H_
+-#define BCM43xx_ILT_H_
+-
+-#define BCM43xx_ILT_ROTOR_SIZE		53
+-extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE];
+-#define BCM43xx_ILT_RETARD_SIZE		53
+-extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE];
+-#define BCM43xx_ILT_FINEFREQA_SIZE	256
+-extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE];
+-#define BCM43xx_ILT_FINEFREQG_SIZE	256
+-extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE];
+-#define BCM43xx_ILT_NOISEA2_SIZE	8
+-extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE];
+-#define BCM43xx_ILT_NOISEA3_SIZE	8
+-extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE];
+-#define BCM43xx_ILT_NOISEG1_SIZE	8
+-extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE];
+-#define BCM43xx_ILT_NOISEG2_SIZE	8
+-extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE];
+-#define BCM43xx_ILT_NOISESCALEG_SIZE	27
+-extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE];
+-extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE];
+-extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE];
+-#define BCM43xx_ILT_SIGMASQR_SIZE	53
+-extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE];
+-extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE];
+-
+-
+-void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+-void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val);
+-u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
+-
+-#endif /* BCM43xx_ILT_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
+deleted file mode 100644
+index cb51dc5..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
++++ /dev/null
+@@ -1,307 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 "bcm43xx_leds.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx.h"
+-
+-#include <linux/bitops.h>
+-
+-
+-static void bcm43xx_led_changestate(struct bcm43xx_led *led)
+-{
+-	struct bcm43xx_private *bcm = led->bcm;
+-	const int index = bcm43xx_led_index(led);
+-	const u16 mask = (1 << index);
+-	u16 ledctl;
+-
+-	assert(index >= 0 && index < BCM43xx_NR_LEDS);
+-	assert(led->blink_interval);
+-	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+-	ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask);
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+-}
+-
+-static void bcm43xx_led_blink(unsigned long d)
+-{
+-	struct bcm43xx_led *led = (struct bcm43xx_led *)d;
+-	struct bcm43xx_private *bcm = led->bcm;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&bcm->leds_lock, flags);
+-	if (led->blink_interval) {
+-		bcm43xx_led_changestate(led);
+-		mod_timer(&led->blink_timer, jiffies + led->blink_interval);
+-	}
+-	spin_unlock_irqrestore(&bcm->leds_lock, flags);
+-}
+-
+-static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
+-				    unsigned long interval)
+-{
+-	if (led->blink_interval)
+-		return;
+-	led->blink_interval = interval;
+-	bcm43xx_led_changestate(led);
+-	led->blink_timer.expires = jiffies + interval;
+-	add_timer(&led->blink_timer);
+-}
+-
+-static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync)
+-{
+-	struct bcm43xx_private *bcm = led->bcm;
+-	const int index = bcm43xx_led_index(led);
+-	u16 ledctl;
+-
+-	if (!led->blink_interval)
+-		return;
+-	if (unlikely(sync))
+-		del_timer_sync(&led->blink_timer);
+-	else
+-		del_timer(&led->blink_timer);
+-	led->blink_interval = 0;
+-
+-	/* Make sure the LED is turned off. */
+-	assert(index >= 0 && index < BCM43xx_NR_LEDS);
+-	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+-	if (led->activelow)
+-		ledctl |= (1 << index);
+-	else
+-		ledctl &= ~(1 << index);
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+-}
+-
+-static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm,
+-				       struct bcm43xx_led *led,
+-				       int led_index)
+-{
+-	/* This function is called, if the behaviour (and activelow)
+-	 * information for a LED is missing in the SPROM.
+-	 * We hardcode the behaviour values for various devices here.
+-	 * Note that the BCM43xx_LED_TEST_XXX behaviour values can
+-	 * be used to figure out which led is mapped to which index.
+-	 */
+-
+-	switch (led_index) {
+-	case 0:
+-		led->behaviour = BCM43xx_LED_ACTIVITY;
+-		led->activelow = 1;
+-		if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ)
+-			led->behaviour = BCM43xx_LED_RADIO_ALL;
+-		break;
+-	case 1:
+-		led->behaviour = BCM43xx_LED_RADIO_B;
+-		if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK)
+-			led->behaviour = BCM43xx_LED_ASSOC;
+-		break;
+-	case 2:
+-		led->behaviour = BCM43xx_LED_RADIO_A;
+-		break;
+-	case 3:
+-		led->behaviour = BCM43xx_LED_OFF;
+-		break;
+-	default:
+-		assert(0);
+-	}
+-}
+-
+-int bcm43xx_leds_init(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_led *led;
+-	u8 sprom[4];
+-	int i;
+-
+-	sprom[0] = bcm->sprom.wl0gpio0;
+-	sprom[1] = bcm->sprom.wl0gpio1;
+-	sprom[2] = bcm->sprom.wl0gpio2;
+-	sprom[3] = bcm->sprom.wl0gpio3;
+-
+-	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+-		led = &(bcm->leds[i]);
+-		led->bcm = bcm;
+-		setup_timer(&led->blink_timer,
+-			    bcm43xx_led_blink,
+-			    (unsigned long)led);
+-
+-		if (sprom[i] == 0xFF) {
+-			bcm43xx_led_init_hardcoded(bcm, led, i);
+-		} else {
+-			led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR;
+-			led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW);
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-void bcm43xx_leds_exit(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_led *led;
+-	int i;
+-
+-	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+-		led = &(bcm->leds[i]);
+-		bcm43xx_led_blink_stop(led, 1);
+-	}
+-	bcm43xx_leds_switch_all(bcm, 0);
+-}
+-
+-void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
+-{
+-	struct bcm43xx_led *led;
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES;
+-	int i, turn_on;
+-	unsigned long interval = 0;
+-	u16 ledctl;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&bcm->leds_lock, flags);
+-	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+-	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+-		led = &(bcm->leds[i]);
+-
+-		turn_on = 0;
+-		switch (led->behaviour) {
+-		case BCM43xx_LED_INACTIVE:
+-			continue;
+-		case BCM43xx_LED_OFF:
+-		case BCM43xx_LED_BCM4303_3:
+-			break;
+-		case BCM43xx_LED_ON:
+-			turn_on = 1;
+-			break;
+-		case BCM43xx_LED_ACTIVITY:
+-		case BCM43xx_LED_BCM4303_0:
+-			turn_on = activity;
+-			break;
+-		case BCM43xx_LED_RADIO_ALL:
+-			turn_on = radio->enabled && bcm43xx_is_hw_radio_enabled(bcm);
+-			break;
+-		case BCM43xx_LED_RADIO_A:
+-		case BCM43xx_LED_BCM4303_2:
+-			turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) &&
+-				   phy->type == BCM43xx_PHYTYPE_A);
+-			break;
+-		case BCM43xx_LED_RADIO_B:
+-		case BCM43xx_LED_BCM4303_1:
+-			turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) &&
+-				   (phy->type == BCM43xx_PHYTYPE_B ||
+-				    phy->type == BCM43xx_PHYTYPE_G));
+-			break;
+-		case BCM43xx_LED_MODE_BG:
+-			if (phy->type == BCM43xx_PHYTYPE_G && bcm43xx_is_hw_radio_enabled(bcm) &&
+-			    1/*FIXME: using G rates.*/)
+-				turn_on = 1;
+-			break;
+-		case BCM43xx_LED_TRANSFER:
+-			if (transferring)
+-				bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
+-			else
+-				bcm43xx_led_blink_stop(led, 0);
+-			continue;
+-		case BCM43xx_LED_APTRANSFER:
+-			if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
+-				if (transferring) {
+-					interval = BCM43xx_LEDBLINK_FAST;
+-					turn_on = 1;
+-				}
+-			} else {
+-				turn_on = 1;
+-				if (0/*TODO: not assoc*/)
+-					interval = BCM43xx_LEDBLINK_SLOW;
+-				else if (transferring)
+-					interval = BCM43xx_LEDBLINK_FAST;
+-				else
+-					turn_on = 0;
+-			}
+-			if (turn_on)
+-				bcm43xx_led_blink_start(led, interval);
+-			else
+-				bcm43xx_led_blink_stop(led, 0);
+-			continue;
+-		case BCM43xx_LED_WEIRD:
+-			//TODO
+-			break;
+-		case BCM43xx_LED_ASSOC:
+-			if (bcm->softmac->associnfo.associated)
+-				turn_on = 1;
+-			break;
+-#ifdef CONFIG_BCM43XX_DEBUG
+-		case BCM43xx_LED_TEST_BLINKSLOW:
+-			bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW);
+-			continue;
+-		case BCM43xx_LED_TEST_BLINKMEDIUM:
+-			bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
+-			continue;
+-		case BCM43xx_LED_TEST_BLINKFAST:
+-			bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST);
+-			continue;
+-#endif /* CONFIG_BCM43XX_DEBUG */
+-		default:
+-			dprintkl(KERN_INFO PFX "Bad value in leds_update,"
+-				" led->behaviour: 0x%x\n", led->behaviour);
+-		};
+-
+-		if (led->activelow)
+-			turn_on = !turn_on;
+-		if (turn_on)
+-			ledctl |= (1 << i);
+-		else
+-			ledctl &= ~(1 << i);
+-	}
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+-	spin_unlock_irqrestore(&bcm->leds_lock, flags);
+-}
+-
+-void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
+-{
+-	struct bcm43xx_led *led;
+-	u16 ledctl;
+-	int i;
+-	int bit_on;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&bcm->leds_lock, flags);
+-	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+-	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+-		led = &(bcm->leds[i]);
+-		if (led->behaviour == BCM43xx_LED_INACTIVE)
+-			continue;
+-		if (on)
+-			bit_on = led->activelow ? 0 : 1;
+-		else
+-			bit_on = led->activelow ? 1 : 0;
+-		if (bit_on)
+-			ledctl |= (1 << i);
+-		else
+-			ledctl &= ~(1 << i);
+-	}
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+-	spin_unlock_irqrestore(&bcm->leds_lock, flags);
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
+deleted file mode 100644
+index 811e14a..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
++++ /dev/null
+@@ -1,62 +0,0 @@
+-#ifndef BCM43xx_LEDS_H_
+-#define BCM43xx_LEDS_H_
+-
+-#include <linux/types.h>
+-#include <linux/timer.h>
+-
+-
+-struct bcm43xx_led {
+-	u8 behaviour:7;
+-	u8 activelow:1;
+-
+-	struct bcm43xx_private *bcm;
+-	struct timer_list blink_timer;
+-	unsigned long blink_interval;
+-};
+-#define bcm43xx_led_index(led)	((int)((led) - (led)->bcm->leds))
+-
+-/* Delay between state changes when blinking in jiffies */
+-#define BCM43xx_LEDBLINK_SLOW		(HZ / 1)
+-#define BCM43xx_LEDBLINK_MEDIUM		(HZ / 4)
+-#define BCM43xx_LEDBLINK_FAST		(HZ / 8)
+-
+-#define BCM43xx_LED_XFER_THRES		(HZ / 100)
+-
+-#define BCM43xx_LED_BEHAVIOUR		0x7F
+-#define BCM43xx_LED_ACTIVELOW		0x80
+-enum { /* LED behaviour values */
+-	BCM43xx_LED_OFF,
+-	BCM43xx_LED_ON,
+-	BCM43xx_LED_ACTIVITY,
+-	BCM43xx_LED_RADIO_ALL,
+-	BCM43xx_LED_RADIO_A,
+-	BCM43xx_LED_RADIO_B,
+-	BCM43xx_LED_MODE_BG,
+-	BCM43xx_LED_TRANSFER,
+-	BCM43xx_LED_APTRANSFER,
+-	BCM43xx_LED_WEIRD,//FIXME
+-	BCM43xx_LED_ASSOC,
+-	BCM43xx_LED_INACTIVE,
+-
+-	/* Behaviour values for testing.
+-	 * With these values it is easier to figure out
+-	 * the real behaviour of leds, in case the SPROM
+-	 * is missing information.
+-	 */
+-	BCM43xx_LED_TEST_BLINKSLOW,
+-	BCM43xx_LED_TEST_BLINKMEDIUM,
+-	BCM43xx_LED_TEST_BLINKFAST,
+-
+-	/* Misc values for BCM4303 */
+-	BCM43xx_LED_BCM4303_0 = 0x2B,
+-	BCM43xx_LED_BCM4303_1 = 0x78,
+-	BCM43xx_LED_BCM4303_2 = 0x2E,
+-	BCM43xx_LED_BCM4303_3 = 0x19,
+-};
+-
+-int bcm43xx_leds_init(struct bcm43xx_private *bcm);
+-void bcm43xx_leds_exit(struct bcm43xx_private *bcm);
+-void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity);
+-void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on);
+-
+-#endif /* BCM43xx_LEDS_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+deleted file mode 100644
+index b96a325..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
++++ /dev/null
+@@ -1,4281 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-  GNU General Public License for more details.
+-
+-  You should have received a copy of the GNU General Public License
+-  along with this program; see the file COPYING.  If not, write to
+-  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+-  Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/delay.h>
+-#include <linux/init.h>
+-#include <linux/moduleparam.h>
+-#include <linux/if_arp.h>
+-#include <linux/etherdevice.h>
+-#include <linux/version.h>
+-#include <linux/firmware.h>
+-#include <linux/wireless.h>
+-#include <linux/workqueue.h>
+-#include <linux/skbuff.h>
+-#include <linux/dma-mapping.h>
+-#include <net/iw_handler.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_debugfs.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx_phy.h"
+-#include "bcm43xx_dma.h"
+-#include "bcm43xx_pio.h"
+-#include "bcm43xx_power.h"
+-#include "bcm43xx_wx.h"
+-#include "bcm43xx_ethtool.h"
+-#include "bcm43xx_xmit.h"
+-#include "bcm43xx_sysfs.h"
+-
+-
+-MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
+-MODULE_AUTHOR("Martin Langer");
+-MODULE_AUTHOR("Stefano Brivio");
+-MODULE_AUTHOR("Michael Buesch");
+-MODULE_LICENSE("GPL");
+-
+-#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
+-static int modparam_pio;
+-module_param_named(pio, modparam_pio, int, 0444);
+-MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
+-#elif defined(CONFIG_BCM43XX_DMA)
+-# define modparam_pio	0
+-#elif defined(CONFIG_BCM43XX_PIO)
+-# define modparam_pio	1
+-#endif
+-
+-static int modparam_bad_frames_preempt;
+-module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+-MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption");
+-
+-static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT;
+-module_param_named(short_retry, modparam_short_retry, int, 0444);
+-MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
+-
+-static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT;
+-module_param_named(long_retry, modparam_long_retry, int, 0444);
+-MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
+-
+-static int modparam_locale = -1;
+-module_param_named(locale, modparam_locale, int, 0444);
+-MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)");
+-
+-static int modparam_noleds;
+-module_param_named(noleds, modparam_noleds, int, 0444);
+-MODULE_PARM_DESC(noleds, "Turn off all LED activity");
+-
+-static char modparam_fwpostfix[64];
+-module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
+-MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
+-
+-
+-/* If you want to debug with just a single device, enable this,
+- * where the string is the pci device ID (as given by the kernel's
+- * pci_name function) of the device to be used.
+- */
+-//#define DEBUG_SINGLE_DEVICE_ONLY	"0001:11:00.0"
+-
+-/* If you want to enable printing of each MMIO access, enable this. */
+-//#define DEBUG_ENABLE_MMIO_PRINT
+-
+-/* If you want to enable printing of MMIO access within
+- * ucode/pcm upload, initvals write, enable this.
+- */
+-//#define DEBUG_ENABLE_UCODE_MMIO_PRINT
+-
+-/* If you want to enable printing of PCI Config Space access, enable this */
+-//#define DEBUG_ENABLE_PCILOG
+-
+-
+-/* Detailed list maintained at:
+- * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
+- */
+-	static struct pci_device_id bcm43xx_pci_tbl[] = {
+-	/* Broadcom 4303 802.11b */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	/* Broadcom 4307 802.11b */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	/* Broadcom 4311 802.11(a)/b/g */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	/* Broadcom 4312 802.11a/b/g */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	/* Broadcom 4318 802.11b/g */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	/* Broadcom 4319 802.11a/b/g */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	/* Broadcom 4306 802.11b/g */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	/* Broadcom 4306 802.11a */
+-//	{ PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	/* Broadcom 4309 802.11a/b/g */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	/* Broadcom 43XG 802.11b/g */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-	{ 0 },
+-};
+-MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
+-
+-static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val)
+-{
+-	u32 status;
+-
+-	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP))
+-		val = swab32(val);
+-
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset);
+-	mmiowb();
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val);
+-}
+-
+-static inline
+-void bcm43xx_shm_control_word(struct bcm43xx_private *bcm,
+-			      u16 routing, u16 offset)
+-{
+-	u32 control;
+-
+-	/* "offset" is the WORD offset. */
+-
+-	control = routing;
+-	control <<= 16;
+-	control |= offset;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control);
+-}
+-
+-u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
+-		       u16 routing, u16 offset)
+-{
+-	u32 ret;
+-
+-	if (routing == BCM43xx_SHM_SHARED) {
+-		if (offset & 0x0003) {
+-			/* Unaligned access */
+-			bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+-			ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
+-			ret <<= 16;
+-			bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
+-			ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
+-
+-			return ret;
+-		}
+-		offset >>= 2;
+-	}
+-	bcm43xx_shm_control_word(bcm, routing, offset);
+-	ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA);
+-
+-	return ret;
+-}
+-
+-u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
+-		       u16 routing, u16 offset)
+-{
+-	u16 ret;
+-
+-	if (routing == BCM43xx_SHM_SHARED) {
+-		if (offset & 0x0003) {
+-			/* Unaligned access */
+-			bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+-			ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
+-
+-			return ret;
+-		}
+-		offset >>= 2;
+-	}
+-	bcm43xx_shm_control_word(bcm, routing, offset);
+-	ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
+-
+-	return ret;
+-}
+-
+-void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
+-			 u16 routing, u16 offset,
+-			 u32 value)
+-{
+-	if (routing == BCM43xx_SHM_SHARED) {
+-		if (offset & 0x0003) {
+-			/* Unaligned access */
+-			bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+-			mmiowb();
+-			bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
+-					(value >> 16) & 0xffff);
+-			mmiowb();
+-			bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
+-			mmiowb();
+-			bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA,
+-					value & 0xffff);
+-			return;
+-		}
+-		offset >>= 2;
+-	}
+-	bcm43xx_shm_control_word(bcm, routing, offset);
+-	mmiowb();
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value);
+-}
+-
+-void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
+-			 u16 routing, u16 offset,
+-			 u16 value)
+-{
+-	if (routing == BCM43xx_SHM_SHARED) {
+-		if (offset & 0x0003) {
+-			/* Unaligned access */
+-			bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+-			mmiowb();
+-			bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
+-					value);
+-			return;
+-		}
+-		offset >>= 2;
+-	}
+-	bcm43xx_shm_control_word(bcm, routing, offset);
+-	mmiowb();
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value);
+-}
+-
+-void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf)
+-{
+-	/* We need to be careful. As we read the TSF from multiple
+-	 * registers, we should take care of register overflows.
+-	 * In theory, the whole tsf read process should be atomic.
+-	 * We try to be atomic here, by restaring the read process,
+-	 * if any of the high registers changed (overflew).
+-	 */
+-	if (bcm->current_core->rev >= 3) {
+-		u32 low, high, high2;
+-
+-		do {
+-			high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
+-			low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW);
+-			high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
+-		} while (unlikely(high != high2));
+-
+-		*tsf = high;
+-		*tsf <<= 32;
+-		*tsf |= low;
+-	} else {
+-		u64 tmp;
+-		u16 v0, v1, v2, v3;
+-		u16 test1, test2, test3;
+-
+-		do {
+-			v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
+-			v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
+-			v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
+-			v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0);
+-
+-			test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
+-			test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
+-			test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
+-		} while (v3 != test3 || v2 != test2 || v1 != test1);
+-
+-		*tsf = v3;
+-		*tsf <<= 48;
+-		tmp = v2;
+-		tmp <<= 32;
+-		*tsf |= tmp;
+-		tmp = v1;
+-		tmp <<= 16;
+-		*tsf |= tmp;
+-		*tsf |= v0;
+-	}
+-}
+-
+-void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
+-{
+-	u32 status;
+-
+-	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	status |= BCM43xx_SBF_TIME_UPDATE;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+-	mmiowb();
+-
+-	/* Be careful with the in-progress timer.
+-	 * First zero out the low register, so we have a full
+-	 * register-overflow duration to complete the operation.
+-	 */
+-	if (bcm->current_core->rev >= 3) {
+-		u32 lo = (tsf & 0x00000000FFFFFFFFULL);
+-		u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
+-
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0);
+-		mmiowb();
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi);
+-		mmiowb();
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo);
+-	} else {
+-		u16 v0 = (tsf & 0x000000000000FFFFULL);
+-		u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
+-		u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
+-		u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
+-
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0);
+-		mmiowb();
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3);
+-		mmiowb();
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2);
+-		mmiowb();
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1);
+-		mmiowb();
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0);
+-	}
+-
+-	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	status &= ~BCM43xx_SBF_TIME_UPDATE;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+-}
+-
+-static
+-void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
+-			   u16 offset,
+-			   const u8 *mac)
+-{
+-	u16 data;
+-
+-	offset |= 0x0020;
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset);
+-
+-	data = mac[0];
+-	data |= mac[1] << 8;
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+-	data = mac[2];
+-	data |= mac[3] << 8;
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+-	data = mac[4];
+-	data |= mac[5] << 8;
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+-}
+-
+-static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
+-				    u16 offset)
+-{
+-	const u8 zero_addr[ETH_ALEN] = { 0 };
+-
+-	bcm43xx_macfilter_set(bcm, offset, zero_addr);
+-}
+-
+-static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
+-{
+-	const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
+-	const u8 *bssid = (const u8 *)(bcm->ieee->bssid);
+-	u8 mac_bssid[ETH_ALEN * 2];
+-	int i;
+-
+-	memcpy(mac_bssid, mac, ETH_ALEN);
+-	memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
+-
+-	/* Write our MAC address and BSSID to template ram */
+-	for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+-		bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i)));
+-	for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+-		bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i)));
+-	for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+-		bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i)));
+-}
+-
+-//FIXME: Well, we should probably call them from somewhere.
+-#if 0
+-static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time)
+-{
+-	/* slot_time is in usec. */
+-	if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G)
+-		return;
+-	bcm43xx_write16(bcm, 0x684, 510 + slot_time);
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time);
+-}
+-
+-static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_set_slot_time(bcm, 9);
+-}
+-
+-static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_set_slot_time(bcm, 20);
+-}
+-#endif
+-
+-/* FIXME: To get the MAC-filter working, we need to implement the
+- *        following functions (and rename them :)
+- */
+-#if 0
+-static void bcm43xx_disassociate(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_mac_suspend(bcm);
+-	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
+-
+-	bcm43xx_ram_write(bcm, 0x0026, 0x0000);
+-	bcm43xx_ram_write(bcm, 0x0028, 0x0000);
+-	bcm43xx_ram_write(bcm, 0x007E, 0x0000);
+-	bcm43xx_ram_write(bcm, 0x0080, 0x0000);
+-	bcm43xx_ram_write(bcm, 0x047E, 0x0000);
+-	bcm43xx_ram_write(bcm, 0x0480, 0x0000);
+-
+-	if (bcm->current_core->rev < 3) {
+-		bcm43xx_write16(bcm, 0x0610, 0x8000);
+-		bcm43xx_write16(bcm, 0x060E, 0x0000);
+-	} else
+-		bcm43xx_write32(bcm, 0x0188, 0x80000000);
+-
+-	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
+-
+-	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G &&
+-	    ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate))
+-		bcm43xx_short_slot_timing_enable(bcm);
+-
+-	bcm43xx_mac_enable(bcm);
+-}
+-
+-static void bcm43xx_associate(struct bcm43xx_private *bcm,
+-			      const u8 *mac)
+-{
+-	memcpy(bcm->ieee->bssid, mac, ETH_ALEN);
+-
+-	bcm43xx_mac_suspend(bcm);
+-	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac);
+-	bcm43xx_write_mac_bssid_templates(bcm);
+-	bcm43xx_mac_enable(bcm);
+-}
+-#endif
+-
+-/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
+- * Returns the _previously_ enabled IRQ mask.
+- */
+-static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask)
+-{
+-	u32 old_mask;
+-
+-	old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask);
+-
+-	return old_mask;
+-}
+-
+-/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
+- * Returns the _previously_ enabled IRQ mask.
+- */
+-static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask)
+-{
+-	u32 old_mask;
+-
+-	old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
+-
+-	return old_mask;
+-}
+-
+-/* Synchronize IRQ top- and bottom-half.
+- * IRQs must be masked before calling this.
+- * This must not be called with the irq_lock held.
+- */
+-static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
+-{
+-	synchronize_irq(bcm->irq);
+-	tasklet_disable(&bcm->isr_tasklet);
+-}
+-
+-/* Make sure we don't receive more data from the device. */
+-static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
+-		spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-		return -EBUSY;
+-	}
+-	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+-	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	bcm43xx_synchronize_irq(bcm);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u32 radio_id;
+-	u16 manufact;
+-	u16 version;
+-	u8 revision;
+-
+-	if (bcm->chip_id == 0x4317) {
+-		if (bcm->chip_rev == 0x00)
+-			radio_id = 0x3205017F;
+-		else if (bcm->chip_rev == 0x01)
+-			radio_id = 0x4205017F;
+-		else
+-			radio_id = 0x5205017F;
+-	} else {
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
+-		radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH);
+-		radio_id <<= 16;
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
+-		radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
+-	}
+-
+-	manufact = (radio_id & 0x00000FFF);
+-	version = (radio_id & 0x0FFFF000) >> 12;
+-	revision = (radio_id & 0xF0000000) >> 28;
+-
+-	dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n",
+-		radio_id, manufact, version, revision);
+-
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_A:
+-		if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f))
+-			goto err_unsupported_radio;
+-		break;
+-	case BCM43xx_PHYTYPE_B:
+-		if ((version & 0xFFF0) != 0x2050)
+-			goto err_unsupported_radio;
+-		break;
+-	case BCM43xx_PHYTYPE_G:
+-		if (version != 0x2050)
+-			goto err_unsupported_radio;
+-		break;
+-	}
+-
+-	radio->manufact = manufact;
+-	radio->version = version;
+-	radio->revision = revision;
+-
+-	if (phy->type == BCM43xx_PHYTYPE_A)
+-		radio->txpower_desired = bcm->sprom.maxpower_aphy;
+-	else
+-		radio->txpower_desired = bcm->sprom.maxpower_bgphy;
+-
+-	return 0;
+-
+-err_unsupported_radio:
+-	printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n");
+-	return -ENODEV;
+-}
+-
+-static const char * bcm43xx_locale_iso(u8 locale)
+-{
+-	/* ISO 3166-1 country codes.
+-	 * Note that there aren't ISO 3166-1 codes for
+-	 * all or locales. (Not all locales are countries)
+-	 */
+-	switch (locale) {
+-	case BCM43xx_LOCALE_WORLD:
+-	case BCM43xx_LOCALE_ALL:
+-		return "XX";
+-	case BCM43xx_LOCALE_THAILAND:
+-		return "TH";
+-	case BCM43xx_LOCALE_ISRAEL:
+-		return "IL";
+-	case BCM43xx_LOCALE_JORDAN:
+-		return "JO";
+-	case BCM43xx_LOCALE_CHINA:
+-		return "CN";
+-	case BCM43xx_LOCALE_JAPAN:
+-	case BCM43xx_LOCALE_JAPAN_HIGH:
+-		return "JP";
+-	case BCM43xx_LOCALE_USA_CANADA_ANZ:
+-	case BCM43xx_LOCALE_USA_LOW:
+-		return "US";
+-	case BCM43xx_LOCALE_EUROPE:
+-		return "EU";
+-	case BCM43xx_LOCALE_NONE:
+-		return "  ";
+-	}
+-	assert(0);
+-	return "  ";
+-}
+-
+-static const char * bcm43xx_locale_string(u8 locale)
+-{
+-	switch (locale) {
+-	case BCM43xx_LOCALE_WORLD:
+-		return "World";
+-	case BCM43xx_LOCALE_THAILAND:
+-		return "Thailand";
+-	case BCM43xx_LOCALE_ISRAEL:
+-		return "Israel";
+-	case BCM43xx_LOCALE_JORDAN:
+-		return "Jordan";
+-	case BCM43xx_LOCALE_CHINA:
+-		return "China";
+-	case BCM43xx_LOCALE_JAPAN:
+-		return "Japan";
+-	case BCM43xx_LOCALE_USA_CANADA_ANZ:
+-		return "USA/Canada/ANZ";
+-	case BCM43xx_LOCALE_EUROPE:
+-		return "Europe";
+-	case BCM43xx_LOCALE_USA_LOW:
+-		return "USAlow";
+-	case BCM43xx_LOCALE_JAPAN_HIGH:
+-		return "JapanHigh";
+-	case BCM43xx_LOCALE_ALL:
+-		return "All";
+-	case BCM43xx_LOCALE_NONE:
+-		return "None";
+-	}
+-	assert(0);
+-	return "";
+-}
+-
+-static inline u8 bcm43xx_crc8(u8 crc, u8 data)
+-{
+-	static const u8 t[] = {
+-		0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+-		0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+-		0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+-		0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+-		0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+-		0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+-		0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+-		0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+-		0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+-		0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+-		0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+-		0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+-		0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+-		0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+-		0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+-		0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+-		0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+-		0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+-		0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+-		0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+-		0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+-		0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+-		0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+-		0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+-		0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+-		0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+-		0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+-		0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+-		0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+-		0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+-		0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+-		0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
+-	};
+-	return t[crc ^ data];
+-}
+-
+-static u8 bcm43xx_sprom_crc(const u16 *sprom)
+-{
+-	int word;
+-	u8 crc = 0xFF;
+-
+-	for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) {
+-		crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF);
+-		crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8);
+-	}
+-	crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF);
+-	crc ^= 0xFF;
+-
+-	return crc;
+-}
+-
+-int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom)
+-{
+-	int i;
+-	u8 crc, expected_crc;
+-
+-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
+-		sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
+-	/* CRC-8 check. */
+-	crc = bcm43xx_sprom_crc(sprom);
+-	expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
+-	if (crc != expected_crc) {
+-		printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum "
+-					"(0x%02X, expected: 0x%02X)\n",
+-		       crc, expected_crc);
+-		return -EINVAL;
+-	}
+-
+-	return 0;
+-}
+-
+-int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
+-{
+-	int i, err;
+-	u8 crc, expected_crc;
+-	u32 spromctl;
+-
+-	/* CRC-8 validation of the input data. */
+-	crc = bcm43xx_sprom_crc(sprom);
+-	expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
+-	if (crc != expected_crc) {
+-		printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n");
+-		return -EINVAL;
+-	}
+-
+-	printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
+-	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl);
+-	if (err)
+-		goto err_ctlreg;
+-	spromctl |= 0x10; /* SPROM WRITE enable. */
+-	err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+-	if (err)
+-		goto err_ctlreg;
+-	/* We must burn lots of CPU cycles here, but that does not
+-	 * really matter as one does not write the SPROM every other minute...
+-	 */
+-	printk(KERN_INFO PFX "[ 0%%");
+-	mdelay(500);
+-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+-		if (i == 16)
+-			printk("25%%");
+-		else if (i == 32)
+-			printk("50%%");
+-		else if (i == 48)
+-			printk("75%%");
+-		else if (i % 2)
+-			printk(".");
+-		bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]);
+-		mmiowb();
+-		mdelay(20);
+-	}
+-	spromctl &= ~0x10; /* SPROM WRITE enable. */
+-	err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+-	if (err)
+-		goto err_ctlreg;
+-	mdelay(500);
+-	printk("100%% ]\n");
+-	printk(KERN_INFO PFX "SPROM written.\n");
+-	bcm43xx_controller_restart(bcm, "SPROM update");
+-
+-	return 0;
+-err_ctlreg:
+-	printk(KERN_ERR PFX "Could not access SPROM control register.\n");
+-	return -ENODEV;
+-}
+-
+-static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
+-{
+-	u16 value;
+-	u16 *sprom;
+-
+-	sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
+-			GFP_KERNEL);
+-	if (!sprom) {
+-		printk(KERN_ERR PFX "sprom_extract OOM\n");
+-		return -ENOMEM;
+-	}
+-	bcm43xx_sprom_read(bcm, sprom);
+-
+-	/* boardflags2 */
+-	value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
+-	bcm->sprom.boardflags2 = value;
+-
+-	/* il0macaddr */
+-	value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
+-	*(((__be16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
+-	value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
+-	*(((__be16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
+-	value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
+-	*(((__be16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
+-
+-	/* et0macaddr */
+-	value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
+-	*(((__be16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
+-	value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
+-	*(((__be16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
+-	value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
+-	*(((__be16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
+-
+-	/* et1macaddr */
+-	value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
+-	*(((__be16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
+-	value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
+-	*(((__be16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
+-	value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
+-	*(((__be16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
+-
+-	/* ethernet phy settings */
+-	value = sprom[BCM43xx_SPROM_ETHPHY];
+-	bcm->sprom.et0phyaddr = (value & 0x001F);
+-	bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
+-
+-	/* boardrev, antennas, locale */
+-	value = sprom[BCM43xx_SPROM_BOARDREV];
+-	bcm->sprom.boardrev = (value & 0x00FF);
+-	bcm->sprom.locale = (value & 0x0F00) >> 8;
+-	bcm->sprom.antennas_aphy = (value & 0x3000) >> 12;
+-	bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14;
+-	if (modparam_locale != -1) {
+-		if (modparam_locale >= 0 && modparam_locale <= 11) {
+-			bcm->sprom.locale = modparam_locale;
+-			printk(KERN_WARNING PFX "Operating with modified "
+-						"LocaleCode %u (%s)\n",
+-			       bcm->sprom.locale,
+-			       bcm43xx_locale_string(bcm->sprom.locale));
+-		} else {
+-			printk(KERN_WARNING PFX "Module parameter \"locale\" "
+-						"invalid value. (0 - 11)\n");
+-		}
+-	}
+-
+-	/* pa0b* */
+-	value = sprom[BCM43xx_SPROM_PA0B0];
+-	bcm->sprom.pa0b0 = value;
+-	value = sprom[BCM43xx_SPROM_PA0B1];
+-	bcm->sprom.pa0b1 = value;
+-	value = sprom[BCM43xx_SPROM_PA0B2];
+-	bcm->sprom.pa0b2 = value;
+-
+-	/* wl0gpio* */
+-	value = sprom[BCM43xx_SPROM_WL0GPIO0];
+-	if (value == 0x0000)
+-		value = 0xFFFF;
+-	bcm->sprom.wl0gpio0 = value & 0x00FF;
+-	bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8;
+-	value = sprom[BCM43xx_SPROM_WL0GPIO2];
+-	if (value == 0x0000)
+-		value = 0xFFFF;
+-	bcm->sprom.wl0gpio2 = value & 0x00FF;
+-	bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8;
+-
+-	/* maxpower */
+-	value = sprom[BCM43xx_SPROM_MAXPWR];
+-	bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8;
+-	bcm->sprom.maxpower_bgphy = value & 0x00FF;
+-
+-	/* pa1b* */
+-	value = sprom[BCM43xx_SPROM_PA1B0];
+-	bcm->sprom.pa1b0 = value;
+-	value = sprom[BCM43xx_SPROM_PA1B1];
+-	bcm->sprom.pa1b1 = value;
+-	value = sprom[BCM43xx_SPROM_PA1B2];
+-	bcm->sprom.pa1b2 = value;
+-
+-	/* idle tssi target */
+-	value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT];
+-	bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF;
+-	bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8;
+-
+-	/* boardflags */
+-	value = sprom[BCM43xx_SPROM_BOARDFLAGS];
+-	if (value == 0xFFFF)
+-		value = 0x0000;
+-	bcm->sprom.boardflags = value;
+-	/* boardflags workarounds */
+-	if (bcm->board_vendor == PCI_VENDOR_ID_DELL &&
+-	    bcm->chip_id == 0x4301 &&
+-	    bcm->board_revision == 0x74)
+-		bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST;
+-	if (bcm->board_vendor == PCI_VENDOR_ID_APPLE &&
+-	    bcm->board_type == 0x4E &&
+-	    bcm->board_revision > 0x40)
+-		bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL;
+-
+-	/* antenna gain */
+-	value = sprom[BCM43xx_SPROM_ANTENNA_GAIN];
+-	if (value == 0x0000 || value == 0xFFFF)
+-		value = 0x0202;
+-	/* convert values to Q5.2 */
+-	bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4;
+-	bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
+-
+-	kfree(sprom);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
+-{
+-	struct ieee80211_geo *geo;
+-	struct ieee80211_channel *chan;
+-	int have_a = 0, have_bg = 0;
+-	int i;
+-	u8 channel;
+-	struct bcm43xx_phyinfo *phy;
+-	const char *iso_country;
+-	u8 max_bg_channel;
+-
+-	geo = kzalloc(sizeof(*geo), GFP_KERNEL);
+-	if (!geo)
+-		return -ENOMEM;
+-
+-	for (i = 0; i < bcm->nr_80211_available; i++) {
+-		phy = &(bcm->core_80211_ext[i].phy);
+-		switch (phy->type) {
+-		case BCM43xx_PHYTYPE_B:
+-		case BCM43xx_PHYTYPE_G:
+-			have_bg = 1;
+-			break;
+-		case BCM43xx_PHYTYPE_A:
+-			have_a = 1;
+-			break;
+-		default:
+-			assert(0);
+-		}
+-	}
+-	iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
+-
+-/* set the maximum channel based on locale set in sprom or witle locale option */
+-	switch (bcm->sprom.locale) {
+-	case BCM43xx_LOCALE_THAILAND:
+-	case BCM43xx_LOCALE_ISRAEL:
+-	case BCM43xx_LOCALE_JORDAN:
+-	case BCM43xx_LOCALE_USA_CANADA_ANZ:
+-	case BCM43xx_LOCALE_USA_LOW:
+-		max_bg_channel = 11;
+-		break;
+-	case BCM43xx_LOCALE_JAPAN:
+-	case BCM43xx_LOCALE_JAPAN_HIGH:
+-		max_bg_channel = 14;
+-		break;
+-	default:
+-		max_bg_channel = 13;
+-	}
+-
+- 	if (have_a) {
+-		for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
+-		      channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
+-			chan = &geo->a[i++];
+-			chan->freq = bcm43xx_channel_to_freq_a(channel);
+-			chan->channel = channel;
+-		}
+-		geo->a_channels = i;
+-	}
+-	if (have_bg) {
+-		for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
+-		      channel <= max_bg_channel; channel++) {
+-			chan = &geo->bg[i++];
+-			chan->freq = bcm43xx_channel_to_freq_bg(channel);
+-			chan->channel = channel;
+-		}
+-		geo->bg_channels = i;
+-	}
+-	memcpy(geo->name, iso_country, 2);
+-	if (0 /*TODO: Outdoor use only */)
+-		geo->name[2] = 'O';
+-	else if (0 /*TODO: Indoor use only */)
+-		geo->name[2] = 'I';
+-	else
+-		geo->name[2] = ' ';
+-	geo->name[3] = '\0';
+-
+-	ieee80211_set_geo(bcm->ieee, geo);
+-	kfree(geo);
+-
+-	return 0;
+-}
+-
+-/* DummyTransmission function, as documented on 
+- * http://bcm-specs.sipsolutions.net/DummyTransmission
+- */
+-void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	unsigned int i, max_loop;
+-	u16 value = 0;
+-	u32 buffer[5] = {
+-		0x00000000,
+-		0x0000D400,
+-		0x00000000,
+-		0x00000001,
+-		0x00000000,
+-	};
+-
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_A:
+-		max_loop = 0x1E;
+-		buffer[0] = 0xCC010200;
+-		break;
+-	case BCM43xx_PHYTYPE_B:
+-	case BCM43xx_PHYTYPE_G:
+-		max_loop = 0xFA;
+-		buffer[0] = 0x6E840B00; 
+-		break;
+-	default:
+-		assert(0);
+-		return;
+-	}
+-
+-	for (i = 0; i < 5; i++)
+-		bcm43xx_ram_write(bcm, i * 4, buffer[i]);
+-
+-	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+-
+-	bcm43xx_write16(bcm, 0x0568, 0x0000);
+-	bcm43xx_write16(bcm, 0x07C0, 0x0000);
+-	bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0));
+-	bcm43xx_write16(bcm, 0x0508, 0x0000);
+-	bcm43xx_write16(bcm, 0x050A, 0x0000);
+-	bcm43xx_write16(bcm, 0x054C, 0x0000);
+-	bcm43xx_write16(bcm, 0x056A, 0x0014);
+-	bcm43xx_write16(bcm, 0x0568, 0x0826);
+-	bcm43xx_write16(bcm, 0x0500, 0x0000);
+-	bcm43xx_write16(bcm, 0x0502, 0x0030);
+-
+-	if (radio->version == 0x2050 && radio->revision <= 0x5)
+-		bcm43xx_radio_write16(bcm, 0x0051, 0x0017);
+-	for (i = 0x00; i < max_loop; i++) {
+-		value = bcm43xx_read16(bcm, 0x050E);
+-		if (value & 0x0080)
+-			break;
+-		udelay(10);
+-	}
+-	for (i = 0x00; i < 0x0A; i++) {
+-		value = bcm43xx_read16(bcm, 0x050E);
+-		if (value & 0x0400)
+-			break;
+-		udelay(10);
+-	}
+-	for (i = 0x00; i < 0x0A; i++) {
+-		value = bcm43xx_read16(bcm, 0x0690);
+-		if (!(value & 0x0100))
+-			break;
+-		udelay(10);
+-	}
+-	if (radio->version == 0x2050 && radio->revision <= 0x5)
+-		bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
+-}
+-
+-static void key_write(struct bcm43xx_private *bcm,
+-		      u8 index, u8 algorithm, const __le16 *key)
+-{
+-	unsigned int i, basic_wep = 0;
+-	u32 offset;
+-	u16 value;
+- 
+-	/* Write associated key information */
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2),
+-			    ((index << 4) | (algorithm & 0x0F)));
+- 
+-	/* The first 4 WEP keys need extra love */
+-	if (((algorithm == BCM43xx_SEC_ALGO_WEP) ||
+-	    (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4))
+-		basic_wep = 1;
+- 
+-	/* Write key payload, 8 little endian words */
+-	offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE);
+-	for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) {
+-		value = le16_to_cpu(key[i]);
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+-				    offset + (i * 2), value);
+- 
+-		if (!basic_wep)
+-			continue;
+- 
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+-				    offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE,
+-				    value);
+-	}
+-}
+-
+-static void keymac_write(struct bcm43xx_private *bcm,
+-			 u8 index, const __be32 *addr)
+-{
+-	/* for keys 0-3 there is no associated mac address */
+-	if (index < 4)
+-		return;
+-
+-	index -= 4;
+-	if (bcm->current_core->rev >= 5) {
+-		bcm43xx_shm_write32(bcm,
+-				    BCM43xx_SHM_HWMAC,
+-				    index * 2,
+-				    be32_to_cpu(*addr));
+-		bcm43xx_shm_write16(bcm,
+-				    BCM43xx_SHM_HWMAC,
+-				    (index * 2) + 1,
+-				    be16_to_cpu(*((__be16 *)(addr + 1))));
+-	} else {
+-		if (index < 8) {
+-			TODO(); /* Put them in the macaddress filter */
+-		} else {
+-			TODO();
+-			/* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
+-			   Keep in mind to update the count of keymacs in 0x003E as well! */
+-		}
+-	}
+-}
+-
+-static int bcm43xx_key_write(struct bcm43xx_private *bcm,
+-			     u8 index, u8 algorithm,
+-			     const u8 *_key, int key_len,
+-			     const u8 *mac_addr)
+-{
+-	u8 key[BCM43xx_SEC_KEYSIZE] = { 0 };
+-
+-	if (index >= ARRAY_SIZE(bcm->key))
+-		return -EINVAL;
+-	if (key_len > ARRAY_SIZE(key))
+-		return -EINVAL;
+-	if (algorithm < 1 || algorithm > 5)
+-		return -EINVAL;
+-
+-	memcpy(key, _key, key_len);
+-	key_write(bcm, index, algorithm, (const __le16 *)key);
+-	keymac_write(bcm, index, (const __be32 *)mac_addr);
+-
+-	bcm->key[index].algorithm = algorithm;
+-
+-	return 0;
+-}
+-
+-static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
+-{
+-	static const __be32 zero_mac[2] = { 0 };
+-	unsigned int i,j, nr_keys = 54;
+-	u16 offset;
+-
+-	if (bcm->current_core->rev < 5)
+-		nr_keys = 16;
+-	assert(nr_keys <= ARRAY_SIZE(bcm->key));
+-
+-	for (i = 0; i < nr_keys; i++) {
+-		bcm->key[i].enabled = 0;
+-		/* returns for i < 4 immediately */
+-		keymac_write(bcm, i, zero_mac);
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+-				    0x100 + (i * 2), 0x0000);
+-		for (j = 0; j < 8; j++) {
+-			offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE);
+-			bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+-					    offset, 0x0000);
+-		}
+-	}
+-	dprintk(KERN_INFO PFX "Keys cleared\n");
+-}
+-
+-/* Lowlevel core-switch function. This is only to be used in
+- * bcm43xx_switch_core() and bcm43xx_probe_cores()
+- */
+-static int _switch_core(struct bcm43xx_private *bcm, int core)
+-{
+-	int err;
+-	int attempts = 0;
+-	u32 current_core;
+-
+-	assert(core >= 0);
+-	while (1) {
+-		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
+-						 (core * 0x1000) + 0x18000000);
+-		if (unlikely(err))
+-			goto error;
+-		err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
+-						&current_core);
+-		if (unlikely(err))
+-			goto error;
+-		current_core = (current_core - 0x18000000) / 0x1000;
+-		if (current_core == core)
+-			break;
+-
+-		if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES))
+-			goto error;
+-		udelay(10);
+-	}
+-
+-	return 0;
+-error:
+-	printk(KERN_ERR PFX "Failed to switch to core %d\n", core);
+-	return -ENODEV;
+-}
+-
+-int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core)
+-{
+-	int err;
+-
+-	if (unlikely(!new_core))
+-		return 0;
+-	if (!new_core->available)
+-		return -ENODEV;
+-	if (bcm->current_core == new_core)
+-		return 0;
+-	err = _switch_core(bcm, new_core->index);
+-	if (unlikely(err))
+-		goto out;
+-
+-	bcm->current_core = new_core;
+-out:
+-	return err;
+-}
+-
+-static int bcm43xx_core_enabled(struct bcm43xx_private *bcm)
+-{
+-	u32 value;
+-
+-	value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-	value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET
+-		 | BCM43xx_SBTMSTATELOW_REJECT;
+-
+-	return (value == BCM43xx_SBTMSTATELOW_CLOCK);
+-}
+-
+-/* disable current core */
+-static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags)
+-{
+-	u32 sbtmstatelow;
+-	u32 sbtmstatehigh;
+-	int i;
+-
+-	/* fetch sbtmstatelow from core information registers */
+-	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-
+-	/* core is already in reset */
+-	if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET)
+-		goto out;
+-
+-	if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) {
+-		sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+-			       BCM43xx_SBTMSTATELOW_REJECT;
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-
+-		for (i = 0; i < 1000; i++) {
+-			sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-			if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) {
+-				i = -1;
+-				break;
+-			}
+-			udelay(10);
+-		}
+-		if (i != -1) {
+-			printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n");
+-			return -EBUSY;
+-		}
+-
+-		for (i = 0; i < 1000; i++) {
+-			sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+-			if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) {
+-				i = -1;
+-				break;
+-			}
+-			udelay(10);
+-		}
+-		if (i != -1) {
+-			printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n");
+-			return -EBUSY;
+-		}
+-
+-		sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+-			       BCM43xx_SBTMSTATELOW_REJECT |
+-			       BCM43xx_SBTMSTATELOW_RESET |
+-			       BCM43xx_SBTMSTATELOW_CLOCK |
+-			       core_flags;
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-		udelay(10);
+-	}
+-
+-	sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET |
+-		       BCM43xx_SBTMSTATELOW_REJECT |
+-		       core_flags;
+-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-
+-out:
+-	bcm->current_core->enabled = 0;
+-
+-	return 0;
+-}
+-
+-/* enable (reset) current core */
+-static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags)
+-{
+-	u32 sbtmstatelow;
+-	u32 sbtmstatehigh;
+-	u32 sbimstate;
+-	int err;
+-
+-	err = bcm43xx_core_disable(bcm, core_flags);
+-	if (err)
+-		goto out;
+-
+-	sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+-		       BCM43xx_SBTMSTATELOW_RESET |
+-		       BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+-		       core_flags;
+-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-	udelay(1);
+-
+-	sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+-	if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) {
+-		sbtmstatehigh = 0x00000000;
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh);
+-	}
+-
+-	sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE);
+-	if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) {
+-		sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT);
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate);
+-	}
+-
+-	sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+-		       BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+-		       core_flags;
+-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-	udelay(1);
+-
+-	sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags;
+-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-	udelay(1);
+-
+-	bcm->current_core->enabled = 1;
+-	assert(err == 0);
+-out:
+-	return err;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/80211CoreReset */
+-void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
+-{
+-	u32 flags = 0x00040000;
+-
+-	if ((bcm43xx_core_enabled(bcm)) &&
+-	    !bcm43xx_using_pio(bcm)) {
+-	}
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+-		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+-				& ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
+-	} else {
+-		if (connect_phy)
+-			flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
+-		bcm43xx_phy_connect(bcm, connect_phy);
+-		bcm43xx_core_enable(bcm, flags);
+-		bcm43xx_write16(bcm, 0x03E6, 0x0000);
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+-				bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+-				| BCM43xx_SBF_400);
+-	}
+-}
+-
+-static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_radio_turn_off(bcm);
+-	bcm43xx_write16(bcm, 0x03E6, 0x00F4);
+-	bcm43xx_core_disable(bcm, 0);
+-}
+-
+-/* Mark the current 80211 core inactive. */
+-static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm)
+-{
+-	u32 sbtmstatelow;
+-
+-	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+-	bcm43xx_radio_turn_off(bcm);
+-	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-	sbtmstatelow &= 0xDFF5FFFF;
+-	sbtmstatelow |= 0x000A0000;
+-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-	udelay(1);
+-	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-	sbtmstatelow &= 0xFFF5FFFF;
+-	sbtmstatelow |= 0x00080000;
+-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-	udelay(1);
+-}
+-
+-static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
+-{
+-	u32 v0, v1;
+-	u16 tmp;
+-	struct bcm43xx_xmitstatus stat;
+-
+-	while (1) {
+-		v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
+-		if (!v0)
+-			break;
+-		v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
+-
+-		stat.cookie = (v0 >> 16) & 0x0000FFFF;
+-		tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1));
+-		stat.flags = tmp & 0xFF;
+-		stat.cnt1 = (tmp & 0x0F00) >> 8;
+-		stat.cnt2 = (tmp & 0xF000) >> 12;
+-		stat.seq = (u16)(v1 & 0xFFFF);
+-		stat.unknown = (u16)((v1 >> 16) & 0xFF);
+-
+-		bcm43xx_debugfs_log_txstat(bcm, &stat);
+-
+-		if (stat.flags & BCM43xx_TXSTAT_FLAG_AMPDU)
+-			continue;
+-		if (stat.flags & BCM43xx_TXSTAT_FLAG_INTER)
+-			continue;
+-
+-		if (bcm43xx_using_pio(bcm))
+-			bcm43xx_pio_handle_xmitstatus(bcm, &stat);
+-		else
+-			bcm43xx_dma_handle_xmitstatus(bcm, &stat);
+-	}
+-}
+-
+-static void drain_txstatus_queue(struct bcm43xx_private *bcm)
+-{
+-	u32 dummy;
+-
+-	if (bcm->current_core->rev < 5)
+-		return;
+-	/* Read all entries from the microcode TXstatus FIFO
+-	 * and throw them away.
+-	 */
+-	while (1) {
+-		dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
+-		if (!dummy)
+-			break;
+-		dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
+-	}
+-}
+-
+-static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
+-			bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4));
+-	assert(bcm->noisecalc.core_at_start == bcm->current_core);
+-	assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel);
+-}
+-
+-static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm)
+-{
+-	/* Top half of Link Quality calculation. */
+-
+-	if (bcm->noisecalc.calculation_running)
+-		return;
+-	bcm->noisecalc.core_at_start = bcm->current_core;
+-	bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel;
+-	bcm->noisecalc.calculation_running = 1;
+-	bcm->noisecalc.nr_samples = 0;
+-
+-	bcm43xx_generate_noise_sample(bcm);
+-}
+-
+-static void handle_irq_noise(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 tmp;
+-	u8 noise[4];
+-	u8 i, j;
+-	s32 average;
+-
+-	/* Bottom half of Link Quality calculation. */
+-
+-	assert(bcm->noisecalc.calculation_running);
+-	if (bcm->noisecalc.core_at_start != bcm->current_core ||
+-	    bcm->noisecalc.channel_at_start != radio->channel)
+-		goto drop_calculation;
+-	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408);
+-	noise[0] = (tmp & 0x00FF);
+-	noise[1] = (tmp & 0xFF00) >> 8;
+-	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A);
+-	noise[2] = (tmp & 0x00FF);
+-	noise[3] = (tmp & 0xFF00) >> 8;
+-	if (noise[0] == 0x7F || noise[1] == 0x7F ||
+-	    noise[2] == 0x7F || noise[3] == 0x7F)
+-		goto generate_new;
+-
+-	/* Get the noise samples. */
+-	assert(bcm->noisecalc.nr_samples < 8);
+-	i = bcm->noisecalc.nr_samples;
+-	noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+-	noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+-	noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+-	noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+-	bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]];
+-	bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]];
+-	bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]];
+-	bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]];
+-	bcm->noisecalc.nr_samples++;
+-	if (bcm->noisecalc.nr_samples == 8) {
+-		/* Calculate the Link Quality by the noise samples. */
+-		average = 0;
+-		for (i = 0; i < 8; i++) {
+-			for (j = 0; j < 4; j++)
+-				average += bcm->noisecalc.samples[i][j];
+-		}
+-		average /= (8 * 4);
+-		average *= 125;
+-		average += 64;
+-		average /= 128;
+-
+-		tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C);
+-		tmp = (tmp / 128) & 0x1F;
+-		if (tmp >= 8)
+-			average += 2;
+-		else
+-			average -= 25;
+-		if (tmp == 8)
+-			average -= 72;
+-		else
+-			average -= 48;
+-
+-		bcm->stats.noise = average;
+-drop_calculation:
+-		bcm->noisecalc.calculation_running = 0;
+-		return;
+-	}
+-generate_new:
+-	bcm43xx_generate_noise_sample(bcm);
+-}
+-
+-static void handle_irq_ps(struct bcm43xx_private *bcm)
+-{
+-	if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
+-		///TODO: PS TBTT
+-	} else {
+-		if (1/*FIXME: the last PSpoll frame was sent successfully */)
+-			bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+-	}
+-	if (bcm->ieee->iw_mode == IW_MODE_ADHOC)
+-		bcm->reg124_set_0x4 = 1;
+-	//FIXME else set to false?
+-}
+-
+-static void handle_irq_reg124(struct bcm43xx_private *bcm)
+-{
+-	if (!bcm->reg124_set_0x4)
+-		return;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
+-			bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
+-			| 0x4);
+-	//FIXME: reset reg124_set_0x4 to false?
+-}
+-
+-static void handle_irq_pmq(struct bcm43xx_private *bcm)
+-{
+-	u32 tmp;
+-
+-	//TODO: AP mode.
+-
+-	while (1) {
+-		tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS);
+-		if (!(tmp & 0x00000008))
+-			break;
+-	}
+-	/* 16bit write is odd, but correct. */
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002);
+-}
+-
+-static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm,
+-					     u16 ram_offset, u16 shm_size_offset)
+-{
+-	u32 value;
+-	u16 size = 0;
+-
+-	/* Timestamp. */
+-	//FIXME: assumption: The chip sets the timestamp
+-	value = 0;
+-	bcm43xx_ram_write(bcm, ram_offset++, value);
+-	bcm43xx_ram_write(bcm, ram_offset++, value);
+-	size += 8;
+-
+-	/* Beacon Interval / Capability Information */
+-	value = 0x0000;//FIXME: Which interval?
+-	value |= (1 << 0) << 16; /* ESS */
+-	value |= (1 << 2) << 16; /* CF Pollable */	//FIXME?
+-	value |= (1 << 3) << 16; /* CF Poll Request */	//FIXME?
+-	if (!bcm->ieee->open_wep)
+-		value |= (1 << 4) << 16; /* Privacy */
+-	bcm43xx_ram_write(bcm, ram_offset++, value);
+-	size += 4;
+-
+-	/* SSID */
+-	//TODO
+-
+-	/* FH Parameter Set */
+-	//TODO
+-
+-	/* DS Parameter Set */
+-	//TODO
+-
+-	/* CF Parameter Set */
+-	//TODO
+-
+-	/* TIM */
+-	//TODO
+-
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size);
+-}
+-
+-static void handle_irq_beacon(struct bcm43xx_private *bcm)
+-{
+-	u32 status;
+-
+-	bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON;
+-	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
+-
+-	if ((status & 0x1) && (status & 0x2)) {
+-		/* ACK beacon IRQ. */
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
+-				BCM43xx_IRQ_BEACON);
+-		bcm->irq_savedstate |= BCM43xx_IRQ_BEACON;
+-		return;
+-	}
+-	if (!(status & 0x1)) {
+-		bcm43xx_generate_beacon_template(bcm, 0x68, 0x18);
+-		status |= 0x1;
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
+-	}
+-	if (!(status & 0x2)) {
+-		bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A);
+-		status |= 0x2;
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
+-	}
+-}
+-
+-/* Interrupt handler bottom-half */
+-static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
+-{
+-	u32 reason;
+-	u32 dma_reason[6];
+-	u32 merged_dma_reason = 0;
+-	int i, activity = 0;
+-	unsigned long flags;
+-
+-#ifdef CONFIG_BCM43XX_DEBUG
+-	u32 _handled = 0x00000000;
+-# define bcmirq_handled(irq)	do { _handled |= (irq); } while (0)
+-#else
+-# define bcmirq_handled(irq)	do { /* nothing */ } while (0)
+-#endif /* CONFIG_BCM43XX_DEBUG*/
+-
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	reason = bcm->irq_reason;
+-	for (i = 5; i >= 0; i--) {
+-		dma_reason[i] = bcm->dma_reason[i];
+-		merged_dma_reason |= dma_reason[i];
+-	}
+-
+-	if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) {
+-		/* TX error. We get this when Template Ram is written in wrong endianess
+-		 * in dummy_tx(). We also get this if something is wrong with the TX header
+-		 * on DMA or PIO queues.
+-		 * Maybe we get this in other error conditions, too.
+-		 */
+-		printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n");
+-		bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR);
+-	}
+-	if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_FATALMASK)) {
+-		printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: "
+-				     "0x%08X, 0x%08X, 0x%08X, "
+-				     "0x%08X, 0x%08X, 0x%08X\n",
+-		        dma_reason[0], dma_reason[1],
+-			dma_reason[2], dma_reason[3],
+-			dma_reason[4], dma_reason[5]);
+-		bcm43xx_controller_restart(bcm, "DMA error");
+-		mmiowb();
+-		spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-		return;
+-	}
+-	if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_NONFATALMASK)) {
+-		printkl(KERN_ERR PFX "DMA error: "
+-				     "0x%08X, 0x%08X, 0x%08X, "
+-				     "0x%08X, 0x%08X, 0x%08X\n",
+-		        dma_reason[0], dma_reason[1],
+-			dma_reason[2], dma_reason[3],
+-			dma_reason[4], dma_reason[5]);
+-	}
+-
+-	if (reason & BCM43xx_IRQ_PS) {
+-		handle_irq_ps(bcm);
+-		bcmirq_handled(BCM43xx_IRQ_PS);
+-	}
+-
+-	if (reason & BCM43xx_IRQ_REG124) {
+-		handle_irq_reg124(bcm);
+-		bcmirq_handled(BCM43xx_IRQ_REG124);
+-	}
+-
+-	if (reason & BCM43xx_IRQ_BEACON) {
+-		if (bcm->ieee->iw_mode == IW_MODE_MASTER)
+-			handle_irq_beacon(bcm);
+-		bcmirq_handled(BCM43xx_IRQ_BEACON);
+-	}
+-
+-	if (reason & BCM43xx_IRQ_PMQ) {
+-		handle_irq_pmq(bcm);
+-		bcmirq_handled(BCM43xx_IRQ_PMQ);
+-	}
+-
+-	if (reason & BCM43xx_IRQ_SCAN) {
+-		/*TODO*/
+-		//bcmirq_handled(BCM43xx_IRQ_SCAN);
+-	}
+-
+-	if (reason & BCM43xx_IRQ_NOISE) {
+-		handle_irq_noise(bcm);
+-		bcmirq_handled(BCM43xx_IRQ_NOISE);
+-	}
+-
+-	/* Check the DMA reason registers for received data. */
+-	if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
+-		if (bcm43xx_using_pio(bcm))
+-			bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0);
+-		else
+-			bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0);
+-		/* We intentionally don't set "activity" to 1, here. */
+-	}
+-	assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
+-	assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
+-	if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
+-		if (bcm43xx_using_pio(bcm))
+-			bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3);
+-		else
+-			bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring3);
+-		activity = 1;
+-	}
+-	assert(!(dma_reason[4] & BCM43xx_DMAIRQ_RX_DONE));
+-	assert(!(dma_reason[5] & BCM43xx_DMAIRQ_RX_DONE));
+-	bcmirq_handled(BCM43xx_IRQ_RX);
+-
+-	if (reason & BCM43xx_IRQ_XMIT_STATUS) {
+-		handle_irq_transmit_status(bcm);
+-		activity = 1;
+-		//TODO: In AP mode, this also causes sending of powersave responses.
+-		bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS);
+-	}
+-
+-	/* IRQ_PIO_WORKAROUND is handled in the top-half. */
+-	bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND);
+-#ifdef CONFIG_BCM43XX_DEBUG
+-	if (unlikely(reason & ~_handled)) {
+-		printkl(KERN_WARNING PFX
+-			"Unhandled IRQ! Reason: 0x%08x,  Unhandled: 0x%08x,  "
+-			"DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+-			reason, (reason & ~_handled),
+-			dma_reason[0], dma_reason[1],
+-			dma_reason[2], dma_reason[3]);
+-	}
+-#endif
+-#undef bcmirq_handled
+-
+-	if (!modparam_noleds)
+-		bcm43xx_leds_update(bcm, activity);
+-	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+-	mmiowb();
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-}
+-
+-static void pio_irq_workaround(struct bcm43xx_private *bcm,
+-			       u16 base, int queueidx)
+-{
+-	u16 rxctl;
+-
+-	rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL);
+-	if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE)
+-		bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE;
+-	else
+-		bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE;
+-}
+-
+-static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason)
+-{
+-	if (bcm43xx_using_pio(bcm) &&
+-	    (bcm->current_core->rev < 3) &&
+-	    (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
+-		/* Apply a PIO specific workaround to the dma_reasons */
+-		pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0);
+-		pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1);
+-		pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2);
+-		pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3);
+-	}
+-
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason);
+-
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_REASON,
+-			bcm->dma_reason[0]);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
+-			bcm->dma_reason[1]);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
+-			bcm->dma_reason[2]);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
+-			bcm->dma_reason[3]);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
+-			bcm->dma_reason[4]);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_REASON,
+-			bcm->dma_reason[5]);
+-}
+-
+-/* Interrupt handler top-half */
+-static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id)
+-{
+-	irqreturn_t ret = IRQ_HANDLED;
+-	struct bcm43xx_private *bcm = dev_id;
+-	u32 reason;
+-
+-	if (!bcm)
+-		return IRQ_NONE;
+-
+-	spin_lock(&bcm->irq_lock);
+-
+-	reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+-	if (reason == 0xffffffff) {
+-		/* irq not for us (shared irq) */
+-		ret = IRQ_NONE;
+-		goto out;
+-	}
+-	reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+-	if (!reason)
+-		goto out;
+-
+-	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+-	assert(bcm->current_core->id == BCM43xx_COREID_80211);
+-
+-	bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON)
+-			     & 0x0001DC00;
+-	bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
+-			     & 0x0000DC00;
+-	bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
+-			     & 0x0000DC00;
+-	bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
+-			     & 0x0001DC00;
+-	bcm->dma_reason[4] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
+-			     & 0x0000DC00;
+-	bcm->dma_reason[5] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA5_REASON)
+-			     & 0x0000DC00;
+-
+-	bcm43xx_interrupt_ack(bcm, reason);
+-
+-	/* disable all IRQs. They are enabled again in the bottom half. */
+-	bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+-	/* save the reason code and call our bottom half. */
+-	bcm->irq_reason = reason;
+-	tasklet_schedule(&bcm->isr_tasklet);
+-
+-out:
+-	mmiowb();
+-	spin_unlock(&bcm->irq_lock);
+-
+-	return ret;
+-}
+-
+-static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+-	if (bcm->firmware_norelease && !force)
+-		return; /* Suspending or controller reset. */
+-	release_firmware(phy->ucode);
+-	phy->ucode = NULL;
+-	release_firmware(phy->pcm);
+-	phy->pcm = NULL;
+-	release_firmware(phy->initvals0);
+-	phy->initvals0 = NULL;
+-	release_firmware(phy->initvals1);
+-	phy->initvals1 = NULL;
+-}
+-
+-static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u8 rev = bcm->current_core->rev;
+-	int err = 0;
+-	int nr;
+-	char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
+-
+-	if (!phy->ucode) {
+-		snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
+-			 (rev >= 5 ? 5 : rev),
+-			 modparam_fwpostfix);
+-		err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev);
+-		if (err) {
+-			printk(KERN_ERR PFX 
+-			       "Error: Microcode \"%s\" not available or load failed.\n",
+-			        buf);
+-			goto error;
+-		}
+-	}
+-
+-	if (!phy->pcm) {
+-		snprintf(buf, ARRAY_SIZE(buf),
+-			 "bcm43xx_pcm%d%s.fw",
+-			 (rev < 5 ? 4 : 5),
+-			 modparam_fwpostfix);
+-		err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev);
+-		if (err) {
+-			printk(KERN_ERR PFX
+-			       "Error: PCM \"%s\" not available or load failed.\n",
+-			       buf);
+-			goto error;
+-		}
+-	}
+-
+-	if (!phy->initvals0) {
+-		if (rev == 2 || rev == 4) {
+-			switch (phy->type) {
+-			case BCM43xx_PHYTYPE_A:
+-				nr = 3;
+-				break;
+-			case BCM43xx_PHYTYPE_B:
+-			case BCM43xx_PHYTYPE_G:
+-				nr = 1;
+-				break;
+-			default:
+-				goto err_noinitval;
+-			}
+-		
+-		} else if (rev >= 5) {
+-			switch (phy->type) {
+-			case BCM43xx_PHYTYPE_A:
+-				nr = 7;
+-				break;
+-			case BCM43xx_PHYTYPE_B:
+-			case BCM43xx_PHYTYPE_G:
+-				nr = 5;
+-				break;
+-			default:
+-				goto err_noinitval;
+-			}
+-		} else
+-			goto err_noinitval;
+-		snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
+-			 nr, modparam_fwpostfix);
+-
+-		err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev);
+-		if (err) {
+-			printk(KERN_ERR PFX 
+-			       "Error: InitVals \"%s\" not available or load failed.\n",
+-			        buf);
+-			goto error;
+-		}
+-		if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) {
+-			printk(KERN_ERR PFX "InitVals fileformat error.\n");
+-			goto error;
+-		}
+-	}
+-
+-	if (!phy->initvals1) {
+-		if (rev >= 5) {
+-			u32 sbtmstatehigh;
+-
+-			switch (phy->type) {
+-			case BCM43xx_PHYTYPE_A:
+-				sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+-				if (sbtmstatehigh & 0x00010000)
+-					nr = 9;
+-				else
+-					nr = 10;
+-				break;
+-			case BCM43xx_PHYTYPE_B:
+-			case BCM43xx_PHYTYPE_G:
+-					nr = 6;
+-				break;
+-			default:
+-				goto err_noinitval;
+-			}
+-			snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
+-				 nr, modparam_fwpostfix);
+-
+-			err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev);
+-			if (err) {
+-				printk(KERN_ERR PFX 
+-				       "Error: InitVals \"%s\" not available or load failed.\n",
+-			        	buf);
+-				goto error;
+-			}
+-			if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) {
+-				printk(KERN_ERR PFX "InitVals fileformat error.\n");
+-				goto error;
+-			}
+-		}
+-	}
+-
+-out:
+-	return err;
+-error:
+-	bcm43xx_release_firmware(bcm, 1);
+-	goto out;
+-err_noinitval:
+-	printk(KERN_ERR PFX "Error: No InitVals available!\n");
+-	err = -ENOENT;
+-	goto error;
+-}
+-
+-static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	const __be32 *data;
+-	unsigned int i, len;
+-
+-	/* Upload Microcode. */
+-	data = (__be32 *)(phy->ucode->data);
+-	len = phy->ucode->size / sizeof(u32);
+-	bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
+-	for (i = 0; i < len; i++) {
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
+-				be32_to_cpu(data[i]));
+-		udelay(10);
+-	}
+-
+-	/* Upload PCM data. */
+-	data = (__be32 *)(phy->pcm->data);
+-	len = phy->pcm->size / sizeof(u32);
+-	bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
+-	bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
+-	for (i = 0; i < len; i++) {
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
+-				be32_to_cpu(data[i]));
+-		udelay(10);
+-	}
+-}
+-
+-static int bcm43xx_write_initvals(struct bcm43xx_private *bcm,
+-				  const struct bcm43xx_initval *data,
+-				  const unsigned int len)
+-{
+-	u16 offset, size;
+-	u32 value;
+-	unsigned int i;
+-
+-	for (i = 0; i < len; i++) {
+-		offset = be16_to_cpu(data[i].offset);
+-		size = be16_to_cpu(data[i].size);
+-		value = be32_to_cpu(data[i].value);
+-
+-		if (unlikely(offset >= 0x1000))
+-			goto err_format;
+-		if (size == 2) {
+-			if (unlikely(value & 0xFFFF0000))
+-				goto err_format;
+-			bcm43xx_write16(bcm, offset, (u16)value);
+-		} else if (size == 4) {
+-			bcm43xx_write32(bcm, offset, value);
+-		} else
+-			goto err_format;
+-	}
+-
+-	return 0;
+-
+-err_format:
+-	printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. "
+-			    "Please fix your bcm43xx firmware files.\n");
+-	return -EPROTO;
+-}
+-
+-static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	int err;
+-
+-	err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data,
+-				     phy->initvals0->size / sizeof(struct bcm43xx_initval));
+-	if (err)
+-		goto out;
+-	if (phy->initvals1) {
+-		err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data,
+-					     phy->initvals1->size / sizeof(struct bcm43xx_initval));
+-		if (err)
+-			goto out;
+-	}
+-out:
+-	return err;
+-}
+-
+-static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
+-{
+-	int err;
+-
+-	bcm->irq = bcm->pci_dev->irq;
+-	err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
+-			  IRQF_SHARED, KBUILD_MODNAME, bcm);
+-	if (err)
+-		printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
+-
+-	return err;
+-}
+-
+-/* Switch to the core used to write the GPIO register.
+- * This is either the ChipCommon, or the PCI core.
+- */
+-static int switch_to_gpio_core(struct bcm43xx_private *bcm)
+-{
+-	int err;
+-
+-	/* Where to find the GPIO register depends on the chipset.
+-	 * If it has a ChipCommon, its register at offset 0x6c is the GPIO
+-	 * control register. Otherwise the register at offset 0x6c in the
+-	 * PCI core is the GPIO control register.
+-	 */
+-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+-	if (err == -ENODEV) {
+-		err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+-		if (unlikely(err == -ENODEV)) {
+-			printk(KERN_ERR PFX "gpio error: "
+-			       "Neither ChipCommon nor PCI core available!\n");
+-		}
+-	}
+-
+-	return err;
+-}
+-
+-/* Initialize the GPIOs
+- * http://bcm-specs.sipsolutions.net/GPIO
+- */
+-static int bcm43xx_gpio_init(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_coreinfo *old_core;
+-	int err;
+-	u32 mask, set;
+-
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+-			bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+-			& 0xFFFF3FFF);
+-
+-	bcm43xx_leds_switch_all(bcm, 0);
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+-			bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F);
+-
+-	mask = 0x0000001F;
+-	set = 0x0000000F;
+-	if (bcm->chip_id == 0x4301) {
+-		mask |= 0x0060;
+-		set |= 0x0060;
+-	}
+-	if (0 /* FIXME: conditional unknown */) {
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+-				bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
+-				| 0x0100);
+-		mask |= 0x0180;
+-		set |= 0x0180;
+-	}
+-	if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+-				bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
+-				| 0x0200);
+-		mask |= 0x0200;
+-		set |= 0x0200;
+-	}
+-	if (bcm->current_core->rev >= 2)
+-		mask  |= 0x0010; /* FIXME: This is redundant. */
+-
+-	old_core = bcm->current_core;
+-	err = switch_to_gpio_core(bcm);
+-	if (err)
+-		goto out;
+-	bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL,
+-	                (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set);
+-	err = bcm43xx_switch_core(bcm, old_core);
+-out:
+-	return err;
+-}
+-
+-/* Turn off all GPIO stuff. Call this on module unload, for example. */
+-static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_coreinfo *old_core;
+-	int err;
+-
+-	old_core = bcm->current_core;
+-	err = switch_to_gpio_core(bcm);
+-	if (err)
+-		return err;
+-	bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000);
+-	err = bcm43xx_switch_core(bcm, old_core);
+-	assert(err == 0);
+-
+-	return 0;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/EnableMac */
+-void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
+-{
+-	bcm->mac_suspended--;
+-	assert(bcm->mac_suspended >= 0);
+-	if (bcm->mac_suspended == 0) {
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+-		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+-				| BCM43xx_SBF_MAC_ENABLED);
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
+-		bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+-		bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+-		bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+-	}
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/SuspendMAC */
+-void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
+-{
+-	int i;
+-	u32 tmp;
+-
+-	assert(bcm->mac_suspended >= 0);
+-	if (bcm->mac_suspended == 0) {
+-		bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+-		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+-		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+-				& ~BCM43xx_SBF_MAC_ENABLED);
+-		bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+-		for (i = 10000; i; i--) {
+-			tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+-			if (tmp & BCM43xx_IRQ_READY)
+-				goto out;
+-			udelay(1);
+-		}
+-		printkl(KERN_ERR PFX "MAC suspend failed\n");
+-	}
+-out:
+-	bcm->mac_suspended++;
+-}
+-
+-void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
+-			int iw_mode)
+-{
+-	unsigned long flags;
+-	struct net_device *net_dev = bcm->net_dev;
+-	u32 status;
+-	u16 value;
+-
+-	spin_lock_irqsave(&bcm->ieee->lock, flags);
+-	bcm->ieee->iw_mode = iw_mode;
+-	spin_unlock_irqrestore(&bcm->ieee->lock, flags);
+-	if (iw_mode == IW_MODE_MONITOR)
+-		net_dev->type = ARPHRD_IEEE80211;
+-	else
+-		net_dev->type = ARPHRD_ETHER;
+-
+-	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	/* Reset status to infrastructured mode */
+-	status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
+-	status &= ~BCM43xx_SBF_MODE_PROMISC;
+-	status |= BCM43xx_SBF_MODE_NOTADHOC;
+-
+-/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
+-status |= BCM43xx_SBF_MODE_PROMISC;
+-
+-	switch (iw_mode) {
+-	case IW_MODE_MONITOR:
+-		status |= BCM43xx_SBF_MODE_MONITOR;
+-		status |= BCM43xx_SBF_MODE_PROMISC;
+-		break;
+-	case IW_MODE_ADHOC:
+-		status &= ~BCM43xx_SBF_MODE_NOTADHOC;
+-		break;
+-	case IW_MODE_MASTER:
+-		status |= BCM43xx_SBF_MODE_AP;
+-		break;
+-	case IW_MODE_SECOND:
+-	case IW_MODE_REPEAT:
+-		TODO(); /* TODO */
+-		break;
+-	case IW_MODE_INFRA:
+-		/* nothing to be done here... */
+-		break;
+-	default:
+-		dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode);
+-	}
+-	if (net_dev->flags & IFF_PROMISC)
+-		status |= BCM43xx_SBF_MODE_PROMISC;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+-
+-	value = 0x0002;
+-	if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
+-		if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
+-			value = 0x0064;
+-		else
+-			value = 0x0032;
+-	}
+-	bcm43xx_write16(bcm, 0x0612, value);
+-}
+-
+-/* This is the opposite of bcm43xx_chip_init() */
+-static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_radio_turn_off(bcm);
+-	if (!modparam_noleds)
+-		bcm43xx_leds_exit(bcm);
+-	bcm43xx_gpio_cleanup(bcm);
+-	bcm43xx_release_firmware(bcm, 0);
+-}
+-
+-/* Initialize the chip
+- * http://bcm-specs.sipsolutions.net/ChipInit
+- */
+-static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	int err;
+-	int i, tmp;
+-	u32 value32;
+-	u16 value16;
+-
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+-			BCM43xx_SBF_CORE_READY
+-			| BCM43xx_SBF_400);
+-
+-	err = bcm43xx_request_firmware(bcm);
+-	if (err)
+-		goto out;
+-	bcm43xx_upload_microcode(bcm);
+-
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
+-	i = 0;
+-	while (1) {
+-		value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+-		if (value32 == BCM43xx_IRQ_READY)
+-			break;
+-		i++;
+-		if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
+-			printk(KERN_ERR PFX "IRQ_READY timeout\n");
+-			err = -ENODEV;
+-			goto err_release_fw;
+-		}
+-		udelay(10);
+-	}
+-	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+-
+-	value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-				     BCM43xx_UCODE_REVISION);
+-
+-	dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x "
+-		"(20%.2i-%.2i-%.2i  %.2i:%.2i:%.2i)\n", value16,
+-		bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-				   BCM43xx_UCODE_PATCHLEVEL),
+-		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-				    BCM43xx_UCODE_DATE) >> 12) & 0xf,
+-		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-				    BCM43xx_UCODE_DATE) >> 8) & 0xf,
+-		bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-				   BCM43xx_UCODE_DATE) & 0xff,
+-		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-				   BCM43xx_UCODE_TIME) >> 11) & 0x1f,
+-		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-				   BCM43xx_UCODE_TIME) >> 5) & 0x3f,
+-		bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-				   BCM43xx_UCODE_TIME) & 0x1f);
+-
+-	if ( value16 > 0x128 ) {
+-		printk(KERN_ERR PFX
+-			"Firmware: no support for microcode extracted "
+-			"from version 4.x binary drivers.\n");
+-		err = -EOPNOTSUPP;
+-		goto err_release_fw;
+-	}
+-
+-	err = bcm43xx_gpio_init(bcm);
+-	if (err)
+-		goto err_release_fw;
+-
+-	err = bcm43xx_upload_initvals(bcm);
+-	if (err)
+-		goto err_gpio_cleanup;
+-	bcm43xx_radio_turn_on(bcm);
+-	bcm->radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
+-	printk(KERN_INFO PFX "Radio %s by hardware\n",
+-		(bcm->radio_hw_enable == 0) ? "disabled" : "enabled");
+-
+-	bcm43xx_write16(bcm, 0x03E6, 0x0000);
+-	err = bcm43xx_phy_init(bcm);
+-	if (err)
+-		goto err_radio_off;
+-
+-	/* Select initial Interference Mitigation. */
+-	tmp = radio->interfmode;
+-	radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
+-	bcm43xx_radio_set_interference_mitigation(bcm, tmp);
+-
+-	bcm43xx_phy_set_antenna_diversity(bcm);
+-	bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT);
+-	if (phy->type == BCM43xx_PHYTYPE_B) {
+-		value16 = bcm43xx_read16(bcm, 0x005E);
+-		value16 |= 0x0004;
+-		bcm43xx_write16(bcm, 0x005E, value16);
+-	}
+-	bcm43xx_write32(bcm, 0x0100, 0x01000000);
+-	if (bcm->current_core->rev < 5)
+-		bcm43xx_write32(bcm, 0x010C, 0x01000000);
+-
+-	value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+-	value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	value32 |= BCM43xx_SBF_MODE_NOTADHOC;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+-
+-	value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	value32 |= 0x100000;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+-
+-	if (bcm43xx_using_pio(bcm)) {
+-		bcm43xx_write32(bcm, 0x0210, 0x00000100);
+-		bcm43xx_write32(bcm, 0x0230, 0x00000100);
+-		bcm43xx_write32(bcm, 0x0250, 0x00000100);
+-		bcm43xx_write32(bcm, 0x0270, 0x00000100);
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000);
+-	}
+-
+-	/* Probe Response Timeout value */
+-	/* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);
+-
+-	/* Initially set the wireless operation mode. */
+-	bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode);
+-
+-	if (bcm->current_core->rev < 3) {
+-		bcm43xx_write16(bcm, 0x060E, 0x0000);
+-		bcm43xx_write16(bcm, 0x0610, 0x8000);
+-		bcm43xx_write16(bcm, 0x0604, 0x0000);
+-		bcm43xx_write16(bcm, 0x0606, 0x0200);
+-	} else {
+-		bcm43xx_write32(bcm, 0x0188, 0x80000000);
+-		bcm43xx_write32(bcm, 0x018C, 0x02000000);
+-	}
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
+-
+-	value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-	value32 |= 0x00100000;
+-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32);
+-
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm));
+-
+-	assert(err == 0);
+-	dprintk(KERN_INFO PFX "Chip initialized\n");
+-out:
+-	return err;
+-
+-err_radio_off:
+-	bcm43xx_radio_turn_off(bcm);
+-err_gpio_cleanup:
+-	bcm43xx_gpio_cleanup(bcm);
+-err_release_fw:
+-	bcm43xx_release_firmware(bcm, 1);
+-	goto out;
+-}
+-	
+-/* Validate chip access
+- * http://bcm-specs.sipsolutions.net/ValidateChipAccess */
+-static int bcm43xx_validate_chip(struct bcm43xx_private *bcm)
+-{
+-	u32 value;
+-	u32 shm_backup;
+-
+-	shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000);
+-	bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA);
+-	if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA)
+-		goto error;
+-	bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55);
+-	if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55)
+-		goto error;
+-	bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup);
+-
+-	value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	if ((value | 0x80000000) != 0x80000400)
+-		goto error;
+-
+-	value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+-	if (value != 0x00000000)
+-		goto error;
+-
+-	return 0;
+-error:
+-	printk(KERN_ERR PFX "Failed to validate the chipaccess\n");
+-	return -ENODEV;
+-}
+-
+-static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
+-{
+-	/* Initialize a "phyinfo" structure. The structure is already
+-	 * zeroed out.
+-	 * This is called on insmod time to initialize members.
+-	 */
+-	phy->savedpctlreg = 0xFFFF;
+-	spin_lock_init(&phy->lock);
+-}
+-
+-static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
+-{
+-	/* Initialize a "radioinfo" structure. The structure is already
+-	 * zeroed out.
+-	 * This is called on insmod time to initialize members.
+-	 */
+-	radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
+-	radio->channel = 0xFF;
+-	radio->initial_channel = 0xFF;
+-}
+-
+-static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
+-{
+-	int err, i;
+-	int current_core;
+-	u32 core_vendor, core_id, core_rev;
+-	u32 sb_id_hi, chip_id_32 = 0;
+-	u16 pci_device, chip_id_16;
+-	u8 core_count;
+-
+-	memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo));
+-	memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo));
+-	memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo)
+-				    * BCM43xx_MAX_80211_CORES);
+-	memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
+-					* BCM43xx_MAX_80211_CORES);
+-	bcm->nr_80211_available = 0;
+-	bcm->current_core = NULL;
+-	bcm->active_80211_core = NULL;
+-
+-	/* map core 0 */
+-	err = _switch_core(bcm, 0);
+-	if (err)
+-		goto out;
+-
+-	/* fetch sb_id_hi from core information registers */
+-	sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+-
+-	core_id = (sb_id_hi & 0x8FF0) >> 4;
+-	core_rev = (sb_id_hi & 0x7000) >> 8;
+-	core_rev |= (sb_id_hi & 0xF);
+-	core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+-
+-	/* if present, chipcommon is always core 0; read the chipid from it */
+-	if (core_id == BCM43xx_COREID_CHIPCOMMON) {
+-		chip_id_32 = bcm43xx_read32(bcm, 0);
+-		chip_id_16 = chip_id_32 & 0xFFFF;
+-		bcm->core_chipcommon.available = 1;
+-		bcm->core_chipcommon.id = core_id;
+-		bcm->core_chipcommon.rev = core_rev;
+-		bcm->core_chipcommon.index = 0;
+-		/* While we are at it, also read the capabilities. */
+-		bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES);
+-	} else {
+-		/* without a chipCommon, use a hard coded table. */
+-		pci_device = bcm->pci_dev->device;
+-		if (pci_device == 0x4301)
+-			chip_id_16 = 0x4301;
+-		else if ((pci_device >= 0x4305) && (pci_device <= 0x4307))
+-			chip_id_16 = 0x4307;
+-		else if ((pci_device >= 0x4402) && (pci_device <= 0x4403))
+-			chip_id_16 = 0x4402;
+-		else if ((pci_device >= 0x4610) && (pci_device <= 0x4615))
+-			chip_id_16 = 0x4610;
+-		else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
+-			chip_id_16 = 0x4710;
+-		else {
+-			printk(KERN_ERR PFX "Could not determine Chip ID\n");
+-			return -ENODEV;
+-		}
+-	}
+-
+-	/* ChipCommon with Core Rev >=4 encodes number of cores,
+-	 * otherwise consult hardcoded table */
+-	if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
+-		core_count = (chip_id_32 & 0x0F000000) >> 24;
+-	} else {
+-		switch (chip_id_16) {
+-			case 0x4610:
+-			case 0x4704:
+-			case 0x4710:
+-				core_count = 9;
+-				break;
+-			case 0x4310:
+-				core_count = 8;
+-				break;
+-			case 0x5365:
+-				core_count = 7;
+-				break;
+-			case 0x4306:
+-				core_count = 6;
+-				break;
+-			case 0x4301:
+-			case 0x4307:
+-				core_count = 5;
+-				break;
+-			case 0x4402:
+-				core_count = 3;
+-				break;
+-			default:
+-				/* SOL if we get here */
+-				assert(0);
+-				core_count = 1;
+-		}
+-	}
+-
+-	bcm->chip_id = chip_id_16;
+-	bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16;
+-	bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20;
+-
+-	dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n",
+-		bcm->chip_id, bcm->chip_rev);
+-	dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
+-	if (bcm->core_chipcommon.available) {
+-		dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n",
+-			core_id, core_rev, core_vendor);
+-		current_core = 1;
+-	} else
+-		current_core = 0;
+-	for ( ; current_core < core_count; current_core++) {
+-		struct bcm43xx_coreinfo *core;
+-		struct bcm43xx_coreinfo_80211 *ext_80211;
+-
+-		err = _switch_core(bcm, current_core);
+-		if (err)
+-			goto out;
+-		/* Gather information */
+-		/* fetch sb_id_hi from core information registers */
+-		sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+-
+-		/* extract core_id, core_rev, core_vendor */
+-		core_id = (sb_id_hi & 0x8FF0) >> 4;
+-		core_rev = ((sb_id_hi & 0xF) | ((sb_id_hi & 0x7000) >> 8));
+-		core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+-
+-		dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n",
+-			current_core, core_id, core_rev, core_vendor);
+-
+-		core = NULL;
+-		switch (core_id) {
+-		case BCM43xx_COREID_PCI:
+-		case BCM43xx_COREID_PCIE:
+-			core = &bcm->core_pci;
+-			if (core->available) {
+-				printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
+-				continue;
+-			}
+-			break;
+-		case BCM43xx_COREID_80211:
+-			for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+-				core = &(bcm->core_80211[i]);
+-				ext_80211 = &(bcm->core_80211_ext[i]);
+-				if (!core->available)
+-					break;
+-				core = NULL;
+-			}
+-			if (!core) {
+-				printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n",
+-				       BCM43xx_MAX_80211_CORES);
+-				continue;
+-			}
+-			if (i != 0) {
+-				/* More than one 80211 core is only supported
+-				 * by special chips.
+-				 * There are chips with two 80211 cores, but with
+-				 * dangling pins on the second core. Be careful
+-				 * and ignore these cores here.
+-				 */
+-				if (1 /*bcm->pci_dev->device != 0x4324*/ ) {
+-				/* TODO: A PHY */
+-					dprintk(KERN_INFO PFX "Ignoring additional 802.11a core.\n");
+-					continue;
+-				}
+-			}
+-			switch (core_rev) {
+-			case 2:
+-			case 4:
+-			case 5:
+-			case 6:
+-			case 7:
+-			case 9:
+-			case 10:
+-				break;
+-			default:
+-				printk(KERN_WARNING PFX
+-				       "Unsupported 80211 core revision %u\n",
+-				       core_rev);
+-			}
+-			bcm->nr_80211_available++;
+-			core->priv = ext_80211;
+-			bcm43xx_init_struct_phyinfo(&ext_80211->phy);
+-			bcm43xx_init_struct_radioinfo(&ext_80211->radio);
+-			break;
+-		case BCM43xx_COREID_CHIPCOMMON:
+-			printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
+-			break;
+-		}
+-		if (core) {
+-			core->available = 1;
+-			core->id = core_id;
+-			core->rev = core_rev;
+-			core->index = current_core;
+-		}
+-	}
+-
+-	if (!bcm->core_80211[0].available) {
+-		printk(KERN_ERR PFX "Error: No 80211 core found!\n");
+-		err = -ENODEV;
+-		goto out;
+-	}
+-
+-	err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
+-
+-	assert(err == 0);
+-out:
+-	return err;
+-}
+-
+-static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
+-{
+-	const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
+-	u8 *bssid = bcm->ieee->bssid;
+-
+-	switch (bcm->ieee->iw_mode) {
+-	case IW_MODE_ADHOC:
+-		random_ether_addr(bssid);
+-		break;
+-	case IW_MODE_MASTER:
+-	case IW_MODE_INFRA:
+-	case IW_MODE_REPEAT:
+-	case IW_MODE_SECOND:
+-	case IW_MODE_MONITOR:
+-		memcpy(bssid, mac, ETH_ALEN);
+-		break;
+-	default:
+-		assert(0);
+-	}
+-}
+-
+-static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
+-				      u16 rate,
+-				      int is_ofdm)
+-{
+-	u16 offset;
+-
+-	if (is_ofdm) {
+-		offset = 0x480;
+-		offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
+-	}
+-	else {
+-		offset = 0x4C0;
+-		offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
+-	}
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20,
+-			    bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset));
+-}
+-
+-static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm)
+-{
+-	switch (bcm43xx_current_phy(bcm)->type) {
+-	case BCM43xx_PHYTYPE_A:
+-	case BCM43xx_PHYTYPE_G:
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1);
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1);
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1);
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1);
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1);
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1);
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1);
+-	case BCM43xx_PHYTYPE_B:
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0);
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0);
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0);
+-		bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0);
+-		break;
+-	default:
+-		assert(0);
+-	}
+-}
+-
+-static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_chip_cleanup(bcm);
+-	bcm43xx_pio_free(bcm);
+-	bcm43xx_dma_free(bcm);
+-
+-	bcm->current_core->initialized = 0;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/80211Init */
+-static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
+-				      int active_wlcore)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u32 ucodeflags;
+-	int err;
+-	u32 sbimconfiglow;
+-	u8 limit;
+-
+-	if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
+-		sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+-		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+-		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+-		if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
+-			sbimconfiglow |= 0x32;
+-		else
+-			sbimconfiglow |= 0x53;
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
+-	}
+-
+-	bcm43xx_phy_calibrate(bcm);
+-	err = bcm43xx_chip_init(bcm);
+-	if (err)
+-		goto out;
+-
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev);
+-	ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET);
+-
+-	if (0 /*FIXME: which condition has to be used here? */)
+-		ucodeflags |= 0x00000010;
+-
+-	/* HW decryption needs to be set now */
+-	ucodeflags |= 0x40000000;
+-	
+-	if (phy->type == BCM43xx_PHYTYPE_G) {
+-		ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
+-		if (phy->rev == 1)
+-			ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY;
+-		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+-			ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL;
+-	} else if (phy->type == BCM43xx_PHYTYPE_B) {
+-		ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
+-		if (phy->rev >= 2 && radio->version == 0x2050)
+-			ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY;
+-	}
+-
+-	if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+-					     BCM43xx_UCODEFLAGS_OFFSET)) {
+-		bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+-				    BCM43xx_UCODEFLAGS_OFFSET, ucodeflags);
+-	}
+-
+-	/* Short/Long Retry Limit.
+-	 * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
+-	 * the chip-internal counter.
+-	 */
+-	limit = limit_value(modparam_short_retry, 0, 0xF);
+-	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit);
+-	limit = limit_value(modparam_long_retry, 0, 0xF);
+-	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit);
+-
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3);
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2);
+-
+-	bcm43xx_rate_memory_init(bcm);
+-
+-	/* Minimum Contention Window */
+-	if (phy->type == BCM43xx_PHYTYPE_B)
+-		bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f);
+-	else
+-		bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f);
+-	/* Maximum Contention Window */
+-	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
+-
+-	bcm43xx_gen_bssid(bcm);
+-	bcm43xx_write_mac_bssid_templates(bcm);
+-
+-	if (bcm->current_core->rev >= 5)
+-		bcm43xx_write16(bcm, 0x043C, 0x000C);
+-
+-	if (active_wlcore) {
+-		if (bcm43xx_using_pio(bcm)) {
+-			err = bcm43xx_pio_init(bcm);
+-		} else {
+-			err = bcm43xx_dma_init(bcm);
+-			if (err == -ENOSYS)
+-				err = bcm43xx_pio_init(bcm);
+-		}
+-		if (err)
+-			goto err_chip_cleanup;
+-	}
+-	bcm43xx_write16(bcm, 0x0612, 0x0050);
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
+-
+-	if (active_wlcore) {
+-		if (radio->initial_channel != 0xFF)
+-			bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0);
+-	}
+-
+-	/* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
+-	 * We enable it later.
+-	 */
+-	bcm->current_core->initialized = 1;
+-out:
+-	return err;
+-
+-err_chip_cleanup:
+-	bcm43xx_chip_cleanup(bcm);
+-	goto out;
+-}
+-
+-static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
+-{
+-	int err;
+-	u16 pci_status;
+-
+-	err = bcm43xx_pctl_set_crystal(bcm, 1);
+-	if (err)
+-		goto out;
+-	err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
+-	if (err)
+-		goto out;
+-	err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
+-
+-out:
+-	return err;
+-}
+-
+-static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+-	bcm43xx_pctl_set_crystal(bcm, 0);
+-}
+-
+-static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
+-					    u32 address,
+-					    u32 data)
+-{
+-	bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address);
+-	bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data);
+-}
+-
+-static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
+-{
+-	int err = 0;
+-
+-	bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+-
+-	if (bcm->core_chipcommon.available) {
+-		err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+-		if (err)
+-			goto out;
+-
+-		bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+-
+-		/* this function is always called when a PCI core is mapped */
+-		err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+-		if (err)
+-			goto out;
+-	} else
+-		bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+-
+-	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+-
+-out:
+-	return err;
+-}
+-
+-static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address)
+-{
+-	bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+-	return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA);
+-}
+-
+-static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address,
+-				    u32 data)
+-{
+-	bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+-	bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data);
+-}
+-
+-static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg,
+-				    u16 data)
+-{
+-	int i;
+-
+-	bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082);
+-	bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST |
+-			BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) |
+-			(reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA |
+-			data);
+-	udelay(10);
+-
+-	for (i = 0; i < 10; i++) {
+-		if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) &
+-		    BCM43xx_PCIE_MDIO_TC)
+-			break;
+-		msleep(1);
+-	}
+-	bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0);
+-}
+-
+-/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
+- * To enable core 0, pass a core_mask of 1<<0
+- */
+-static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
+-						  u32 core_mask)
+-{
+-	u32 backplane_flag_nr;
+-	u32 value;
+-	struct bcm43xx_coreinfo *old_core;
+-	int err = 0;
+-
+-	value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
+-	backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
+-
+-	old_core = bcm->current_core;
+-	err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+-	if (err)
+-		goto out;
+-
+-	if (bcm->current_core->rev < 6 &&
+-		bcm->current_core->id == BCM43xx_COREID_PCI) {
+-		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
+-		value |= (1 << backplane_flag_nr);
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
+-	} else {
+-		err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value);
+-		if (err) {
+-			printk(KERN_ERR PFX "Error: ICR setup failure!\n");
+-			goto out_switch_back;
+-		}
+-		value |= core_mask << 8;
+-		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value);
+-		if (err) {
+-			printk(KERN_ERR PFX "Error: ICR setup failure!\n");
+-			goto out_switch_back;
+-		}
+-	}
+-
+-	if (bcm->current_core->id == BCM43xx_COREID_PCI) {
+-		value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+-		value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
+-		bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+-
+-		if (bcm->current_core->rev < 5) {
+-			value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+-			value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
+-				 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+-			value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
+-				 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+-			bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
+-			err = bcm43xx_pcicore_commit_settings(bcm);
+-			assert(err == 0);
+-		} else if (bcm->current_core->rev >= 11) {
+-			value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+-			value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI;
+-			bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+-		}
+-	} else {
+-		if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) {
+-			value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND);
+-			value |= 0x8;
+-			bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND,
+-					       value);
+-		}
+-		if (bcm->current_core->rev == 0) {
+-			bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+-						BCM43xx_SERDES_RXTIMER, 0x8128);
+-			bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+-						BCM43xx_SERDES_CDR, 0x0100);
+-			bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+-						BCM43xx_SERDES_CDR_BW, 0x1466);
+-		} else if (bcm->current_core->rev == 1) {
+-			value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL);
+-			value |= 0x40;
+-			bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL,
+-					       value);
+-		}
+-	}
+-out_switch_back:
+-	err = bcm43xx_switch_core(bcm, old_core);
+-out:
+-	return err;
+-}
+-
+-static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+-	if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2)
+-		return;
+-
+-	bcm43xx_mac_suspend(bcm);
+-	bcm43xx_phy_lo_g_measure(bcm);
+-	bcm43xx_mac_enable(bcm);
+-}
+-
+-static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_phy_lo_mark_all_unused(bcm);
+-	if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+-		bcm43xx_mac_suspend(bcm);
+-		bcm43xx_calc_nrssi_slope(bcm);
+-		bcm43xx_mac_enable(bcm);
+-	}
+-}
+-
+-static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
+-{
+-	/* Update device statistics. */
+-	bcm43xx_calculate_link_quality(bcm);
+-}
+-
+-static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
+-	//TODO for APHY (temperature?)
+-}
+-
+-static void bcm43xx_periodic_every1sec(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	int radio_hw_enable;
+-
+-	/* check if radio hardware enabled status changed */
+-	radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
+-	if (unlikely(bcm->radio_hw_enable != radio_hw_enable)) {
+-		bcm->radio_hw_enable = radio_hw_enable;
+-		printk(KERN_INFO PFX "Radio hardware status changed to %s\n",
+-		       (radio_hw_enable == 0) ? "disabled" : "enabled");
+-		bcm43xx_leds_update(bcm, 0);
+-	}
+-	if (phy->type == BCM43xx_PHYTYPE_G) {
+-		//TODO: update_aci_moving_average
+-		if (radio->aci_enable && radio->aci_wlan_automatic) {
+-			bcm43xx_mac_suspend(bcm);
+-			if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
+-				if (0 /*TODO: bunch of conditions*/) {
+-					bcm43xx_radio_set_interference_mitigation(bcm,
+-										  BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
+-				}
+-			} else if (1/*TODO*/) {
+-				/*
+-				if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) {
+-					bcm43xx_radio_set_interference_mitigation(bcm,
+-										  BCM43xx_RADIO_INTERFMODE_NONE);
+-				}
+-				*/
+-			}
+-			bcm43xx_mac_enable(bcm);
+-		} else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN &&
+-			   phy->rev == 1) {
+-			//TODO: implement rev1 workaround
+-		}
+-	}
+-}
+-
+-static void do_periodic_work(struct bcm43xx_private *bcm)
+-{
+-	if (bcm->periodic_state % 120 == 0)
+-		bcm43xx_periodic_every120sec(bcm);
+-	if (bcm->periodic_state % 60 == 0)
+-		bcm43xx_periodic_every60sec(bcm);
+-	if (bcm->periodic_state % 30 == 0)
+-		bcm43xx_periodic_every30sec(bcm);
+-	if (bcm->periodic_state % 15 == 0)
+-		bcm43xx_periodic_every15sec(bcm);
+-	bcm43xx_periodic_every1sec(bcm);
+-
+-	schedule_delayed_work(&bcm->periodic_work, HZ);
+-}
+-
+-static void bcm43xx_periodic_work_handler(struct work_struct *work)
+-{
+-	struct bcm43xx_private *bcm =
+-		container_of(work, struct bcm43xx_private, periodic_work.work);
+-	struct net_device *net_dev = bcm->net_dev;
+-	unsigned long flags;
+-	u32 savedirqs = 0;
+-	unsigned long orig_trans_start = 0;
+-
+-	mutex_lock(&bcm->mutex);
+-	/* keep from doing and rearming periodic work if shutting down */
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT)
+-		goto unlock_mutex;
+-	if (unlikely(bcm->periodic_state % 60 == 0)) {
+-		/* Periodic work will take a long time, so we want it to
+-		 * be preemtible.
+-		 */
+-
+-		netif_tx_lock_bh(net_dev);
+-		/* We must fake a started transmission here, as we are going to
+-		 * disable TX. If we wouldn't fake a TX, it would be possible to
+-		 * trigger the netdev watchdog, if the last real TX is already
+-		 * some time on the past (slightly less than 5secs)
+-		 */
+-		orig_trans_start = net_dev->trans_start;
+-		net_dev->trans_start = jiffies;
+-		netif_stop_queue(net_dev);
+-		netif_tx_unlock_bh(net_dev);
+-
+-		spin_lock_irqsave(&bcm->irq_lock, flags);
+-		bcm43xx_mac_suspend(bcm);
+-		if (bcm43xx_using_pio(bcm))
+-			bcm43xx_pio_freeze_txqueues(bcm);
+-		savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+-		spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-		bcm43xx_synchronize_irq(bcm);
+-	} else {
+-		/* Periodic work should take short time, so we want low
+-		 * locking overhead.
+-		 */
+-		spin_lock_irqsave(&bcm->irq_lock, flags);
+-	}
+-
+-	do_periodic_work(bcm);
+-
+-	if (unlikely(bcm->periodic_state % 60 == 0)) {
+-		spin_lock_irqsave(&bcm->irq_lock, flags);
+-		tasklet_enable(&bcm->isr_tasklet);
+-		bcm43xx_interrupt_enable(bcm, savedirqs);
+-		if (bcm43xx_using_pio(bcm))
+-			bcm43xx_pio_thaw_txqueues(bcm);
+-		bcm43xx_mac_enable(bcm);
+-		netif_wake_queue(bcm->net_dev);
+-		net_dev->trans_start = orig_trans_start;
+-	}
+-	mmiowb();
+-	bcm->periodic_state++;
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-unlock_mutex:
+-	mutex_unlock(&bcm->mutex);
+-}
+-
+-void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
+-{
+-	struct delayed_work *work = &bcm->periodic_work;
+-
+-	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+-	INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
+-	schedule_delayed_work(work, 0);
+-}
+-
+-static void bcm43xx_security_init(struct bcm43xx_private *bcm)
+-{
+-	bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-						  0x0056) * 2;
+-	bcm43xx_clear_keys(bcm);
+-}
+-
+-static int bcm43xx_rng_read(struct hwrng *rng, u32 *data)
+-{
+-	struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&(bcm)->irq_lock, flags);
+-	*data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
+-	spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
+-
+-	return (sizeof(u16));
+-}
+-
+-static void bcm43xx_rng_exit(struct bcm43xx_private *bcm)
+-{
+-	hwrng_unregister(&bcm->rng);
+-}
+-
+-static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
+-{
+-	int err;
+-
+-	snprintf(bcm->rng_name, ARRAY_SIZE(bcm->rng_name),
+-		 "%s_%s", KBUILD_MODNAME, bcm->net_dev->name);
+-	bcm->rng.name = bcm->rng_name;
+-	bcm->rng.data_read = bcm43xx_rng_read;
+-	bcm->rng.priv = (unsigned long)bcm;
+-	err = hwrng_register(&bcm->rng);
+-	if (err)
+-		printk(KERN_ERR PFX "RNG init failed (%d)\n", err);
+-
+-	return err;
+-}
+-
+-void bcm43xx_cancel_work(struct bcm43xx_private *bcm)
+-{
+-	/* The system must be unlocked when this routine is entered.
+-	 * If not, the next 2 steps may deadlock */
+-	cancel_work_sync(&bcm->restart_work);
+-	cancel_delayed_work_sync(&bcm->periodic_work);
+-}
+-
+-static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
+-{
+-	int ret = 0;
+-	int i, err;
+-	struct bcm43xx_coreinfo *core;
+-
+-	bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
+-	for (i = 0; i < bcm->nr_80211_available; i++) {
+-		core = &(bcm->core_80211[i]);
+-		assert(core->available);
+-		if (!core->initialized)
+-			continue;
+-		err = bcm43xx_switch_core(bcm, core);
+-		if (err) {
+-			dprintk(KERN_ERR PFX "shutdown_all_wireless_cores "
+-					     "switch_core failed (%d)\n", err);
+-			ret = err;
+-			continue;
+-		}
+-		bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+-		bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+-		bcm43xx_wireless_core_cleanup(bcm);
+-		if (core == bcm->active_80211_core)
+-			bcm->active_80211_core = NULL;
+-	}
+-	free_irq(bcm->irq, bcm);
+-	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+-
+-	return ret;
+-}
+-
+-/* This is the opposite of bcm43xx_init_board() */
+-static void bcm43xx_free_board(struct bcm43xx_private *bcm)
+-{
+-	bcm43xx_rng_exit(bcm);
+-	bcm43xx_sysfs_unregister(bcm);
+-
+-	mutex_lock(&(bcm)->mutex);
+-	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+-	mutex_unlock(&(bcm)->mutex);
+-
+-	bcm43xx_cancel_work(bcm);
+-
+-	mutex_lock(&(bcm)->mutex);
+-	bcm43xx_shutdown_all_wireless_cores(bcm);
+-	bcm43xx_pctl_set_crystal(bcm, 0);
+-	mutex_unlock(&(bcm)->mutex);
+-}
+-
+-static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy)
+-{
+-	phy->antenna_diversity = 0xFFFF;
+-	memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
+-	memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
+-
+-	/* Flags */
+-	phy->calibrated = 0;
+-	phy->is_locked = 0;
+-
+-	if (phy->_lo_pairs) {
+-		memset(phy->_lo_pairs, 0,
+-		       sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT);
+-	}
+-	memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain));
+-}
+-
+-static void prepare_radiodata_for_init(struct bcm43xx_private *bcm,
+-				       struct bcm43xx_radioinfo *radio)
+-{
+-	int i;
+-
+-	/* Set default attenuation values. */
+-	radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
+-	radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
+-	radio->txctl1 = bcm43xx_default_txctl1(bcm);
+-	radio->txctl2 = 0xFFFF;
+-	radio->txpwr_offset = 0;
+-
+-	/* NRSSI */
+-	radio->nrssislope = 0;
+-	for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++)
+-		radio->nrssi[i] = -1000;
+-	for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++)
+-		radio->nrssi_lt[i] = i;
+-
+-	radio->lofcal = 0xFFFF;
+-	radio->initval = 0xFFFF;
+-
+-	radio->aci_enable = 0;
+-	radio->aci_wlan_automatic = 0;
+-	radio->aci_hw_rssi = 0;
+-}
+-
+-static void prepare_priv_for_init(struct bcm43xx_private *bcm)
+-{
+-	int i;
+-	struct bcm43xx_coreinfo *core;
+-	struct bcm43xx_coreinfo_80211 *wlext;
+-
+-	assert(!bcm->active_80211_core);
+-
+-	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
+-
+-	/* Flags */
+-	bcm->was_initialized = 0;
+-	bcm->reg124_set_0x4 = 0;
+-
+-	/* Stats */
+-	memset(&bcm->stats, 0, sizeof(bcm->stats));
+-
+-	/* Wireless core data */
+-	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+-		core = &(bcm->core_80211[i]);
+-		wlext = core->priv;
+-
+-		if (!core->available)
+-			continue;
+-		assert(wlext == &(bcm->core_80211_ext[i]));
+-
+-		prepare_phydata_for_init(&wlext->phy);
+-		prepare_radiodata_for_init(bcm, &wlext->radio);
+-	}
+-
+-	/* IRQ related flags */
+-	bcm->irq_reason = 0;
+-	memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason));
+-	bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+-
+-	bcm->mac_suspended = 1;
+-
+-	/* Noise calculation context */
+-	memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc));
+-
+-	/* Periodic work context */
+-	bcm->periodic_state = 0;
+-}
+-
+-static int wireless_core_up(struct bcm43xx_private *bcm,
+-			    int active_wlcore)
+-{
+-	int err;
+-
+-	if (!bcm43xx_core_enabled(bcm))
+-		bcm43xx_wireless_core_reset(bcm, 1);
+-	if (!active_wlcore)
+-		bcm43xx_wireless_core_mark_inactive(bcm);
+-	err = bcm43xx_wireless_core_init(bcm, active_wlcore);
+-	if (err)
+-		goto out;
+-	if (!active_wlcore)
+-		bcm43xx_radio_turn_off(bcm);
+-out:
+-	return err;
+-}
+-
+-/* Select and enable the "to be used" wireless core.
+- * Locking: bcm->mutex must be aquired before calling this.
+- *          bcm->irq_lock must not be aquired.
+- */
+-int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
+-				 int phytype)
+-{
+-	int i, err;
+-	struct bcm43xx_coreinfo *active_core = NULL;
+-	struct bcm43xx_coreinfo_80211 *active_wlext = NULL;
+-	struct bcm43xx_coreinfo *core;
+-	struct bcm43xx_coreinfo_80211 *wlext;
+-	int adjust_active_sbtmstatelow = 0;
+-
+-	might_sleep();
+-
+-	if (phytype < 0) {
+-		/* If no phytype is requested, select the first core. */
+-		assert(bcm->core_80211[0].available);
+-		wlext = bcm->core_80211[0].priv;
+-		phytype = wlext->phy.type;
+-	}
+-	/* Find the requested core. */
+-	for (i = 0; i < bcm->nr_80211_available; i++) {
+-		core = &(bcm->core_80211[i]);
+-		wlext = core->priv;
+-		if (wlext->phy.type == phytype) {
+-			active_core = core;
+-			active_wlext = wlext;
+-			break;
+-		}
+-	}
+-	if (!active_core)
+-		return -ESRCH; /* No such PHYTYPE on this board. */
+-
+-	if (bcm->active_80211_core) {
+-		/* We already selected a wl core in the past.
+-		 * So first clean up everything.
+-		 */
+-		dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n");
+-		ieee80211softmac_stop(bcm->net_dev);
+-		bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
+-		err = bcm43xx_disable_interrupts_sync(bcm);
+-		assert(!err);
+-		tasklet_enable(&bcm->isr_tasklet);
+-		err = bcm43xx_shutdown_all_wireless_cores(bcm);
+-		if (err)
+-			goto error;
+-		/* Ok, everything down, continue to re-initialize. */
+-		bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
+-	}
+-
+-	/* Reset all data structures. */
+-	prepare_priv_for_init(bcm);
+-
+-	err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
+-	if (err)
+-		goto error;
+-
+-	/* Mark all unused cores "inactive". */
+-	for (i = 0; i < bcm->nr_80211_available; i++) {
+-		core = &(bcm->core_80211[i]);
+-		wlext = core->priv;
+-
+-		if (core == active_core)
+-			continue;
+-		err = bcm43xx_switch_core(bcm, core);
+-		if (err) {
+-			dprintk(KERN_ERR PFX "Could not switch to inactive "
+-					     "802.11 core (%d)\n", err);
+-			goto error;
+-		}
+-		err = wireless_core_up(bcm, 0);
+-		if (err) {
+-			dprintk(KERN_ERR PFX "core_up for inactive 802.11 core "
+-					     "failed (%d)\n", err);
+-			goto error;
+-		}
+-		adjust_active_sbtmstatelow = 1;
+-	}
+-
+-	/* Now initialize the active 802.11 core. */
+-	err = bcm43xx_switch_core(bcm, active_core);
+-	if (err) {
+-		dprintk(KERN_ERR PFX "Could not switch to active "
+-				     "802.11 core (%d)\n", err);
+-		goto error;
+-	}
+-	if (adjust_active_sbtmstatelow &&
+-	    active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
+-		u32 sbtmstatelow;
+-
+-		sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-		sbtmstatelow |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-	}
+-	err = wireless_core_up(bcm, 1);
+-	if (err) {
+-		dprintk(KERN_ERR PFX "core_up for active 802.11 core "
+-				     "failed (%d)\n", err);
+-		goto error;
+-	}
+-	err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
+-	if (err)
+-		goto error;
+-	bcm->active_80211_core = active_core;
+-
+-	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
+-	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
+-	bcm43xx_security_init(bcm);
+-	drain_txstatus_queue(bcm);
+-	ieee80211softmac_start(bcm->net_dev);
+-
+-	/* Let's go! Be careful after enabling the IRQs.
+-	 * Don't switch cores, for example.
+-	 */
+-	bcm43xx_mac_enable(bcm);
+-	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
+-	err = bcm43xx_initialize_irq(bcm);
+-	if (err)
+-		goto error;
+-	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+-
+-	dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
+-		active_wlext->phy.type);
+-
+-	return 0;
+-
+-error:
+-	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+-	bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+-	return err;
+-}
+-
+-static int bcm43xx_init_board(struct bcm43xx_private *bcm)
+-{
+-	int err;
+-
+-	mutex_lock(&(bcm)->mutex);
+-
+-	tasklet_enable(&bcm->isr_tasklet);
+-	err = bcm43xx_pctl_set_crystal(bcm, 1);
+-	if (err)
+-		goto err_tasklet;
+-	err = bcm43xx_pctl_init(bcm);
+-	if (err)
+-		goto err_crystal_off;
+-	err = bcm43xx_select_wireless_core(bcm, -1);
+-	if (err)
+-		goto err_crystal_off;
+-	err = bcm43xx_sysfs_register(bcm);
+-	if (err)
+-		goto err_wlshutdown;
+-	err = bcm43xx_rng_init(bcm);
+-	if (err)
+-		goto err_sysfs_unreg;
+-	bcm43xx_periodic_tasks_setup(bcm);
+-
+-	/*FIXME: This should be handled by softmac instead. */
+-	schedule_delayed_work(&bcm->softmac->associnfo.work, 0);
+-
+-out:
+-	mutex_unlock(&(bcm)->mutex);
+-
+-	return err;
+-
+-err_sysfs_unreg:
+-	bcm43xx_sysfs_unregister(bcm);
+-err_wlshutdown:
+-	bcm43xx_shutdown_all_wireless_cores(bcm);
+-err_crystal_off:
+-	bcm43xx_pctl_set_crystal(bcm, 0);
+-err_tasklet:
+-	tasklet_disable(&bcm->isr_tasklet);
+-	goto out;
+-}
+-
+-static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
+-{
+-	struct pci_dev *pci_dev = bcm->pci_dev;
+-	int i;
+-
+-	bcm43xx_chipset_detach(bcm);
+-	/* Do _not_ access the chip, after it is detached. */
+-	pci_iounmap(pci_dev, bcm->mmio_addr);
+-	pci_release_regions(pci_dev);
+-	pci_disable_device(pci_dev);
+-
+-	/* Free allocated structures/fields */
+-	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+-		kfree(bcm->core_80211_ext[i].phy._lo_pairs);
+-		if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
+-			kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+-	}
+-}	
+-
+-static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 value;
+-	u8 phy_analog;
+-	u8 phy_type;
+-	u8 phy_rev;
+-	int phy_rev_ok = 1;
+-	void *p;
+-
+-	value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
+-
+-	phy_analog = (value & 0xF000) >> 12;
+-	phy_type = (value & 0x0F00) >> 8;
+-	phy_rev = (value & 0x000F);
+-
+-	dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n",
+-		phy_analog, phy_type, phy_rev);
+-
+-	switch (phy_type) {
+-	case BCM43xx_PHYTYPE_A:
+-		if (phy_rev >= 4)
+-			phy_rev_ok = 0;
+-		/*FIXME: We need to switch the ieee->modulation, etc.. flags,
+-		 *       if we switch 80211 cores after init is done.
+-		 *       As we do not implement on the fly switching between
+-		 *       wireless cores, I will leave this as a future task.
+-		 */
+-		bcm->ieee->modulation = IEEE80211_OFDM_MODULATION;
+-		bcm->ieee->mode = IEEE_A;
+-		bcm->ieee->freq_band = IEEE80211_52GHZ_BAND |
+-				       IEEE80211_24GHZ_BAND;
+-		break;
+-	case BCM43xx_PHYTYPE_B:
+-		if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7)
+-			phy_rev_ok = 0;
+-		bcm->ieee->modulation = IEEE80211_CCK_MODULATION;
+-		bcm->ieee->mode = IEEE_B;
+-		bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
+-		break;
+-	case BCM43xx_PHYTYPE_G:
+-		if (phy_rev > 8)
+-			phy_rev_ok = 0;
+-		bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
+-					IEEE80211_CCK_MODULATION;
+-		bcm->ieee->mode = IEEE_G;
+-		bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
+-		break;
+-	default:
+-		printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n",
+-		       phy_type);
+-		return -ENODEV;
+-	};
+-	bcm->ieee->perfect_rssi = RX_RSSI_MAX;
+-	bcm->ieee->worst_rssi = 0;
+-	if (!phy_rev_ok) {
+-		printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
+-		       phy_rev);
+-	}
+-
+-	phy->analog = phy_analog;
+-	phy->type = phy_type;
+-	phy->rev = phy_rev;
+-	if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
+-		p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT,
+-			    GFP_KERNEL);
+-		if (!p)
+-			return -ENOMEM;
+-		phy->_lo_pairs = p;
+-	}
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
+-{
+-	struct pci_dev *pci_dev = bcm->pci_dev;
+-	struct net_device *net_dev = bcm->net_dev;
+-	int err;
+-	int i;
+-	u32 coremask;
+-
+-	err = pci_enable_device(pci_dev);
+-	if (err) {
+-		printk(KERN_ERR PFX "pci_enable_device() failed\n");
+-		goto out;
+-	}
+-	err = pci_request_regions(pci_dev, KBUILD_MODNAME);
+-	if (err) {
+-		printk(KERN_ERR PFX "pci_request_regions() failed\n");
+-		goto err_pci_disable;
+-	}
+-	/* enable PCI bus-mastering */
+-	pci_set_master(pci_dev);
+-	bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL);
+-	if (!bcm->mmio_addr) {
+-		printk(KERN_ERR PFX "pci_iomap() failed\n");
+-		err = -EIO;
+-		goto err_pci_release;
+-	}
+-	net_dev->base_addr = (unsigned long)bcm->mmio_addr;
+-
+-	err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
+-	                          &bcm->board_vendor);
+-	if (err)
+-		goto err_iounmap;
+-	err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
+-	                          &bcm->board_type);
+-	if (err)
+-		goto err_iounmap;
+-
+-	bcm->board_revision = bcm->pci_dev->revision;
+-
+-	err = bcm43xx_chipset_attach(bcm);
+-	if (err)
+-		goto err_iounmap;
+-	err = bcm43xx_pctl_init(bcm);
+-	if (err)
+-		goto err_chipset_detach;
+-	err = bcm43xx_probe_cores(bcm);
+-	if (err)
+-		goto err_chipset_detach;
+-	
+-	/* Attach all IO cores to the backplane. */
+-	coremask = 0;
+-	for (i = 0; i < bcm->nr_80211_available; i++)
+-		coremask |= (1 << bcm->core_80211[i].index);
+-	//FIXME: Also attach some non80211 cores?
+-	err = bcm43xx_setup_backplane_pci_connection(bcm, coremask);
+-	if (err) {
+-		printk(KERN_ERR PFX "Backplane->PCI connection failed!\n");
+-		goto err_chipset_detach;
+-	}
+-
+-	err = bcm43xx_sprom_extract(bcm);
+-	if (err)
+-		goto err_chipset_detach;
+-	err = bcm43xx_leds_init(bcm);
+-	if (err)
+-		goto err_chipset_detach;
+-
+-	for (i = 0; i < bcm->nr_80211_available; i++) {
+-		err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
+-		assert(err != -ENODEV);
+-		if (err)
+-			goto err_80211_unwind;
+-
+-		/* Enable the selected wireless core.
+-		 * Connect PHY only on the first core.
+-		 */
+-		bcm43xx_wireless_core_reset(bcm, (i == 0));
+-
+-		err = bcm43xx_read_phyinfo(bcm);
+-		if (err && (i == 0))
+-			goto err_80211_unwind;
+-
+-		err = bcm43xx_read_radioinfo(bcm);
+-		if (err && (i == 0))
+-			goto err_80211_unwind;
+-
+-		err = bcm43xx_validate_chip(bcm);
+-		if (err && (i == 0))
+-			goto err_80211_unwind;
+-
+-		bcm43xx_radio_turn_off(bcm);
+-		err = bcm43xx_phy_init_tssi2dbm_table(bcm);
+-		if (err)
+-			goto err_80211_unwind;
+-		bcm43xx_wireless_core_disable(bcm);
+-	}
+-	err = bcm43xx_geo_init(bcm);
+-	if (err)
+-		goto err_80211_unwind;
+-	bcm43xx_pctl_set_crystal(bcm, 0);
+-
+-	/* Set the MAC address in the networking subsystem */
+-	if (is_valid_ether_addr(bcm->sprom.et1macaddr))
+-		memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
+-	else
+-		memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
+-
+-	snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
+-		 "Broadcom %04X", bcm->chip_id);
+-
+-	assert(err == 0);
+-out:
+-	return err;
+-
+-err_80211_unwind:
+-	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+-		kfree(bcm->core_80211_ext[i].phy._lo_pairs);
+-		if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
+-			kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+-	}
+-err_chipset_detach:
+-	bcm43xx_chipset_detach(bcm);
+-err_iounmap:
+-	pci_iounmap(pci_dev, bcm->mmio_addr);
+-err_pci_release:
+-	pci_release_regions(pci_dev);
+-err_pci_disable:
+-	pci_disable_device(pci_dev);
+-	printk(KERN_ERR PFX "Unable to attach board\n");
+-	goto out;
+-}
+-
+-/* Do the Hardware IO operations to send the txb */
+-static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
+-			     struct ieee80211_txb *txb)
+-{
+-	int err = -ENODEV;
+-
+-	if (bcm43xx_using_pio(bcm))
+-		err = bcm43xx_pio_tx(bcm, txb);
+-	else
+-		err = bcm43xx_dma_tx(bcm, txb);
+-	bcm->net_dev->trans_start = jiffies;
+-
+-	return err;
+-}
+-
+-static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
+-				       u8 channel)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	struct bcm43xx_radioinfo *radio;
+-	unsigned long flags;
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+-		bcm43xx_mac_suspend(bcm);
+-		bcm43xx_radio_selectchannel(bcm, channel, 0);
+-		bcm43xx_mac_enable(bcm);
+-	} else {
+-		radio = bcm43xx_current_radio(bcm);
+-		radio->initial_channel = channel;
+-	}
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-}
+-
+-/* set_security() callback in struct ieee80211_device */
+-static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
+-					   struct ieee80211_security *sec)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	struct ieee80211_security *secinfo = &bcm->ieee->sec;
+-	unsigned long flags;
+-	int keyidx;
+-	
+-	dprintk(KERN_INFO PFX "set security called");
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+-	for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
+-		if (sec->flags & (1<<keyidx)) {
+-			secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
+-			secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
+-			memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN);
+-		}
+-	
+-	if (sec->flags & SEC_ACTIVE_KEY) {
+-		secinfo->active_key = sec->active_key;
+-		dprintk(", .active_key = %d", sec->active_key);
+-	}
+-	if (sec->flags & SEC_UNICAST_GROUP) {
+-		secinfo->unicast_uses_group = sec->unicast_uses_group;
+-		dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group);
+-	}
+-	if (sec->flags & SEC_LEVEL) {
+-		secinfo->level = sec->level;
+-		dprintk(", .level = %d", sec->level);
+-	}
+-	if (sec->flags & SEC_ENABLED) {
+-		secinfo->enabled = sec->enabled;
+-		dprintk(", .enabled = %d", sec->enabled);
+-	}
+-	if (sec->flags & SEC_ENCRYPT) {
+-		secinfo->encrypt = sec->encrypt;
+-		dprintk(", .encrypt = %d", sec->encrypt);
+-	}
+-	if (sec->flags & SEC_AUTH_MODE) {
+-		secinfo->auth_mode = sec->auth_mode;
+-		dprintk(", .auth_mode = %d", sec->auth_mode);
+-	}
+-	dprintk("\n");
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
+-	    !bcm->ieee->host_encrypt) {
+-		if (secinfo->enabled) {
+-			/* upload WEP keys to hardware */
+-			char null_address[6] = { 0 };
+-			u8 algorithm = 0;
+-			for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) {
+-				if (!(sec->flags & (1<<keyidx)))
+-					continue;
+-				switch (sec->encode_alg[keyidx]) {
+-					case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break;
+-					case SEC_ALG_WEP:
+-						algorithm = BCM43xx_SEC_ALGO_WEP;
+-						if (secinfo->key_sizes[keyidx] == 13)
+-							algorithm = BCM43xx_SEC_ALGO_WEP104;
+-						break;
+-					case SEC_ALG_TKIP:
+-						FIXME();
+-						algorithm = BCM43xx_SEC_ALGO_TKIP;
+-						break;
+-					case SEC_ALG_CCMP:
+-						FIXME();
+-						algorithm = BCM43xx_SEC_ALGO_AES;
+-						break;
+-					default:
+-						assert(0);
+-						break;
+-				}
+-				bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]);
+-				bcm->key[keyidx].enabled = 1;
+-				bcm->key[keyidx].algorithm = algorithm;
+-			}
+-		} else
+-				bcm43xx_clear_keys(bcm);
+-	}
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-}
+-
+-/* hard_start_xmit() callback in struct ieee80211_device */
+-static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
+-					     struct net_device *net_dev,
+-					     int pri)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int err = -ENODEV;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
+-		err = bcm43xx_tx(bcm, txb);
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-
+-	if (unlikely(err))
+-		return NETDEV_TX_BUSY;
+-	return NETDEV_TX_OK;
+-}
+-
+-static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	bcm43xx_controller_restart(bcm, "TX timeout");
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-}
+-
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-static void bcm43xx_net_poll_controller(struct net_device *net_dev)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
+-		bcm43xx_interrupt_handler(bcm->irq, bcm);
+-	local_irq_restore(flags);
+-}
+-#endif /* CONFIG_NET_POLL_CONTROLLER */
+-
+-static int bcm43xx_net_open(struct net_device *net_dev)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+-	return bcm43xx_init_board(bcm);
+-}
+-
+-static int bcm43xx_net_stop(struct net_device *net_dev)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int err;
+-
+-	ieee80211softmac_stop(net_dev);
+-	err = bcm43xx_disable_interrupts_sync(bcm);
+-	assert(!err);
+-	bcm43xx_free_board(bcm);
+-	bcm43xx_cancel_work(bcm);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_init_private(struct bcm43xx_private *bcm,
+-				struct net_device *net_dev,
+-				struct pci_dev *pci_dev)
+-{
+-	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+-	bcm->ieee = netdev_priv(net_dev);
+-	bcm->softmac = ieee80211_priv(net_dev);
+-	bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
+-
+-	bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+-	bcm->mac_suspended = 1;
+-	bcm->pci_dev = pci_dev;
+-	bcm->net_dev = net_dev;
+-	bcm->bad_frames_preempt = modparam_bad_frames_preempt;
+-	spin_lock_init(&bcm->irq_lock);
+-	spin_lock_init(&bcm->leds_lock);
+-	mutex_init(&bcm->mutex);
+-	tasklet_init(&bcm->isr_tasklet,
+-		     (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
+-		     (unsigned long)bcm);
+-	tasklet_disable_nosync(&bcm->isr_tasklet);
+-	if (modparam_pio)
+-		bcm->__using_pio = 1;
+-	bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
+-
+-	/* default to sw encryption for now */
+-	bcm->ieee->host_build_iv = 0;
+-	bcm->ieee->host_encrypt = 1;
+-	bcm->ieee->host_decrypt = 1;
+-	
+-	bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE;
+-	bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr);
+-	bcm->ieee->set_security = bcm43xx_ieee80211_set_security;
+-	bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit;
+-
+-	return 0;
+-}
+-
+-static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
+-				      const struct pci_device_id *ent)
+-{
+-	struct net_device *net_dev;
+-	struct bcm43xx_private *bcm;
+-	int err;
+-
+-#ifdef DEBUG_SINGLE_DEVICE_ONLY
+-	if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
+-		return -ENODEV;
+-#endif
+-
+-	net_dev = alloc_ieee80211softmac(sizeof(*bcm));
+-	if (!net_dev) {
+-		printk(KERN_ERR PFX
+-		       "could not allocate ieee80211 device %s\n",
+-		       pci_name(pdev));
+-		err = -ENOMEM;
+-		goto out;
+-	}
+-	/* initialize the net_device struct */
+-	SET_NETDEV_DEV(net_dev, &pdev->dev);
+-
+-	net_dev->open = bcm43xx_net_open;
+-	net_dev->stop = bcm43xx_net_stop;
+-	net_dev->tx_timeout = bcm43xx_net_tx_timeout;
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-	net_dev->poll_controller = bcm43xx_net_poll_controller;
+-#endif
+-	net_dev->wireless_handlers = &bcm43xx_wx_handlers_def;
+-	net_dev->irq = pdev->irq;
+-	SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops);
+-
+-	/* initialize the bcm43xx_private struct */
+-	bcm = bcm43xx_priv(net_dev);
+-	memset(bcm, 0, sizeof(*bcm));
+-	err = bcm43xx_init_private(bcm, net_dev, pdev);
+-	if (err)
+-		goto err_free_netdev;
+-
+-	pci_set_drvdata(pdev, net_dev);
+-
+-	err = bcm43xx_attach_board(bcm);
+-	if (err)
+-		goto err_free_netdev;
+-
+-	err = register_netdev(net_dev);
+-	if (err) {
+-		printk(KERN_ERR PFX "Cannot register net device, "
+-		       "aborting.\n");
+-		err = -ENOMEM;
+-		goto err_detach_board;
+-	}
+-
+-	bcm43xx_debugfs_add_device(bcm);
+-
+-	assert(err == 0);
+-out:
+-	return err;
+-
+-err_detach_board:
+-	bcm43xx_detach_board(bcm);
+-err_free_netdev:
+-	free_ieee80211softmac(net_dev);
+-	goto out;
+-}
+-
+-static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
+-{
+-	struct net_device *net_dev = pci_get_drvdata(pdev);
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+-	bcm43xx_debugfs_remove_device(bcm);
+-	unregister_netdev(net_dev);
+-	bcm43xx_detach_board(bcm);
+-	free_ieee80211softmac(net_dev);
+-}
+-
+-/* Hard-reset the chip. Do not call this directly.
+- * Use bcm43xx_controller_restart()
+- */
+-static void bcm43xx_chip_reset(struct work_struct *work)
+-{
+-	struct bcm43xx_private *bcm =
+-		container_of(work, struct bcm43xx_private, restart_work);
+-	struct bcm43xx_phyinfo *phy;
+-	int err = -ENODEV;
+-
+-	bcm43xx_cancel_work(bcm);
+-	mutex_lock(&(bcm)->mutex);
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+-		phy = bcm43xx_current_phy(bcm);
+-		err = bcm43xx_select_wireless_core(bcm, phy->type);
+-		if (!err)
+-			bcm43xx_periodic_tasks_setup(bcm);
+-	}
+-	mutex_unlock(&(bcm)->mutex);
+-
+-	printk(KERN_ERR PFX "Controller restart%s\n",
+-	       (err == 0) ? "ed" : " failed");
+-}
+-
+-/* Hard-reset the chip.
+- * This can be called from interrupt or process context.
+- * bcm->irq_lock must be locked.
+- */
+-void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
+-{
+-	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
+-		return;
+-	printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
+-	INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset);
+-	schedule_work(&bcm->restart_work);
+-}
+-
+-#ifdef CONFIG_PM
+-
+-static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+-	struct net_device *net_dev = pci_get_drvdata(pdev);
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int err;
+-
+-	dprintk(KERN_INFO PFX "Suspending...\n");
+-
+-	netif_device_detach(net_dev);
+-	bcm->was_initialized = 0;
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+-		bcm->was_initialized = 1;
+-		ieee80211softmac_stop(net_dev);
+-		err = bcm43xx_disable_interrupts_sync(bcm);
+-		if (unlikely(err)) {
+-			dprintk(KERN_ERR PFX "Suspend failed.\n");
+-			return -EAGAIN;
+-		}
+-		bcm->firmware_norelease = 1;
+-		bcm43xx_free_board(bcm);
+-		bcm->firmware_norelease = 0;
+-	}
+-	bcm43xx_chipset_detach(bcm);
+-
+-	pci_save_state(pdev);
+-	pci_disable_device(pdev);
+-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+-
+-	dprintk(KERN_INFO PFX "Device suspended.\n");
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_resume(struct pci_dev *pdev)
+-{
+-	struct net_device *net_dev = pci_get_drvdata(pdev);
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int err = 0;
+-
+-	dprintk(KERN_INFO PFX "Resuming...\n");
+-
+-	pci_set_power_state(pdev, 0);
+-	err = pci_enable_device(pdev);
+-	if (err) {
+-		printk(KERN_ERR PFX "Failure with pci_enable_device!\n");
+-		return err;
+-	}
+-	pci_restore_state(pdev);
+-
+-	bcm43xx_chipset_attach(bcm);
+-	if (bcm->was_initialized)
+-		err = bcm43xx_init_board(bcm);
+-	if (err) {
+-		printk(KERN_ERR PFX "Resume failed!\n");
+-		return err;
+-	}
+-	netif_device_attach(net_dev);
+-
+-	dprintk(KERN_INFO PFX "Device resumed.\n");
+-
+-	return 0;
+-}
+-
+-#endif				/* CONFIG_PM */
+-
+-static struct pci_driver bcm43xx_pci_driver = {
+-	.name = KBUILD_MODNAME,
+-	.id_table = bcm43xx_pci_tbl,
+-	.probe = bcm43xx_init_one,
+-	.remove = __devexit_p(bcm43xx_remove_one),
+-#ifdef CONFIG_PM
+-	.suspend = bcm43xx_suspend,
+-	.resume = bcm43xx_resume,
+-#endif				/* CONFIG_PM */
+-};
+-
+-static int __init bcm43xx_init(void)
+-{
+-	printk(KERN_INFO KBUILD_MODNAME " driver\n");
+-	bcm43xx_debugfs_init();
+-	return pci_register_driver(&bcm43xx_pci_driver);
+-}
+-
+-static void __exit bcm43xx_exit(void)
+-{
+-	pci_unregister_driver(&bcm43xx_pci_driver);
+-	bcm43xx_debugfs_exit();
+-}
+-
+-module_init(bcm43xx_init)
+-module_exit(bcm43xx_exit)
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+deleted file mode 100644
+index 14cfbeb..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 BCM43xx_MAIN_H_
+-#define BCM43xx_MAIN_H_
+-
+-#include "bcm43xx.h"
+-
+-#define P4D_BYT3S(magic, nr_bytes)	u8 __p4dding##magic[nr_bytes]
+-#define P4D_BYTES(line, nr_bytes)	P4D_BYT3S(line, nr_bytes)
+-/* Magic helper macro to pad structures. Ignore those above. It's magic. */
+-#define PAD_BYTES(nr_bytes)		P4D_BYTES( __LINE__ , (nr_bytes))
+-
+-
+-/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
+-static inline
+-u8 bcm43xx_freq_to_channel_a(int freq)
+-{
+-	return ((freq - 5000) / 5);
+-}
+-static inline
+-u8 bcm43xx_freq_to_channel_bg(int freq)
+-{
+-	u8 channel;
+-
+-	if (freq == 2484)
+-		channel = 14;
+-	else
+-		channel = (freq - 2407) / 5;
+-
+-	return channel;
+-}
+-static inline
+-u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm,
+-			   int freq)
+-{
+-	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+-		return bcm43xx_freq_to_channel_a(freq);
+-	return bcm43xx_freq_to_channel_bg(freq);
+-}
+-
+-/* Lightweight function to convert a channel number to a frequency (in Mhz). */
+-static inline
+-int bcm43xx_channel_to_freq_a(u8 channel)
+-{
+-	return (5000 + (5 * channel));
+-}
+-static inline
+-int bcm43xx_channel_to_freq_bg(u8 channel)
+-{
+-	int freq;
+-
+-	if (channel == 14)
+-		freq = 2484;
+-	else
+-		freq = 2407 + (5 * channel);
+-
+-	return freq;
+-}
+-static inline
+-int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
+-			    u8 channel)
+-{
+-	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+-		return bcm43xx_channel_to_freq_a(channel);
+-	return bcm43xx_channel_to_freq_bg(channel);
+-}
+-
+-void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
+-void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
+-
+-void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
+-			int iw_mode);
+-
+-u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
+-		       u16 routing, u16 offset);
+-u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
+-		       u16 routing, u16 offset);
+-void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
+-			 u16 routing, u16 offset,
+-			 u32 value);
+-void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
+-			 u16 routing, u16 offset,
+-			 u16 value);
+-
+-void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
+-
+-int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
+-
+-int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
+-				 int phytype);
+-
+-void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
+-
+-void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
+-void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_cancel_work(struct bcm43xx_private *bcm);
+-void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
+-
+-int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
+-int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom);
+-
+-#endif /* BCM43xx_MAIN_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+deleted file mode 100644
+index af3de33..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
++++ /dev/null
+@@ -1,2346 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-  GNU General Public License for more details.
+-
+-  You should have received a copy of the GNU General Public License
+-  along with this program; see the file COPYING.  If not, write to
+-  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+-  Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/delay.h>
+-#include <linux/pci.h>
+-#include <linux/types.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_phy.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx_ilt.h"
+-#include "bcm43xx_power.h"
+-
+-
+-static const s8 bcm43xx_tssi2dbm_b_table[] = {
+-	0x4D, 0x4C, 0x4B, 0x4A,
+-	0x4A, 0x49, 0x48, 0x47,
+-	0x47, 0x46, 0x45, 0x45,
+-	0x44, 0x43, 0x42, 0x42,
+-	0x41, 0x40, 0x3F, 0x3E,
+-	0x3D, 0x3C, 0x3B, 0x3A,
+-	0x39, 0x38, 0x37, 0x36,
+-	0x35, 0x34, 0x32, 0x31,
+-	0x30, 0x2F, 0x2D, 0x2C,
+-	0x2B, 0x29, 0x28, 0x26,
+-	0x25, 0x23, 0x21, 0x1F,
+-	0x1D, 0x1A, 0x17, 0x14,
+-	0x10, 0x0C, 0x06, 0x00,
+-	  -7,   -7,   -7,   -7,
+-	  -7,   -7,   -7,   -7,
+-	  -7,   -7,   -7,   -7,
+-};
+-
+-static const s8 bcm43xx_tssi2dbm_g_table[] = {
+-	 77,  77,  77,  76,
+-	 76,  76,  75,  75,
+-	 74,  74,  73,  73,
+-	 73,  72,  72,  71,
+-	 71,  70,  70,  69,
+-	 68,  68,  67,  67,
+-	 66,  65,  65,  64,
+-	 63,  63,  62,  61,
+-	 60,  59,  58,  57,
+-	 56,  55,  54,  53,
+-	 52,  50,  49,  47,
+-	 45,  43,  40,  37,
+-	 33,  28,  22,  14,
+-	  5,  -7, -20, -20,
+-	-20, -20, -20, -20,
+-	-20, -20, -20, -20,
+-};
+-
+-static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
+-
+-
+-static inline
+-void bcm43xx_voluntary_preempt(void)
+-{
+-	assert(!in_atomic() && !in_irq() &&
+-	       !in_interrupt() && !irqs_disabled());
+-#ifndef CONFIG_PREEMPT
+-	cond_resched();
+-#endif /* CONFIG_PREEMPT */
+-}
+-
+-void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+-	assert(irqs_disabled());
+-	if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) {
+-		phy->is_locked = 0;
+-		return;
+-	}
+-	if (bcm->current_core->rev < 3) {
+-		bcm43xx_mac_suspend(bcm);
+-		spin_lock(&phy->lock);
+-	} else {
+-		if (bcm->ieee->iw_mode != IW_MODE_MASTER)
+-			bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+-	}
+-	phy->is_locked = 1;
+-}
+-
+-void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+-	assert(irqs_disabled());
+-	if (bcm->current_core->rev < 3) {
+-		if (phy->is_locked) {
+-			spin_unlock(&phy->lock);
+-			bcm43xx_mac_enable(bcm);
+-		}
+-	} else {
+-		if (bcm->ieee->iw_mode != IW_MODE_MASTER)
+-			bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+-	}
+-	phy->is_locked = 0;
+-}
+-
+-u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset)
+-{
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
+-	return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA);
+-}
+-
+-void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
+-{
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
+-	mmiowb();
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val);
+-}
+-
+-void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+-	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
+-	if (phy->calibrated)
+-		return;
+-	if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
+-		bcm43xx_wireless_core_reset(bcm, 0);
+-		bcm43xx_phy_initg(bcm);
+-		bcm43xx_wireless_core_reset(bcm, 1);
+-	}
+-	phy->calibrated = 1;
+-}
+-
+-/* Connect the PHY 
+- * http://bcm-specs.sipsolutions.net/SetPHY
+- */
+-int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u32 flags;
+-
+-	if (bcm->current_core->rev < 5)
+-		goto out;
+-
+-	flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+-	if (connect) {
+-		if (!(flags & BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL))
+-			return -ENODEV;
+-		flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-		flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+-	} else {
+-		if (!(flags & BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL))
+-			return -ENODEV;
+-		flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-		flags &= ~BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
+-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+-	}
+-out:
+-	phy->connected = connect;
+-	if (connect)
+-		dprintk(KERN_INFO PFX "PHY connected\n");
+-	else
+-		dprintk(KERN_INFO PFX "PHY disconnected\n");
+-
+-	return 0;
+-}
+-
+-/* intialize B PHY power control
+- * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
+- */
+-static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0;
+-	int must_reset_txpower = 0;
+-
+-	assert(phy->type != BCM43xx_PHYTYPE_A);
+-	if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+-	    (bcm->board_type == 0x0416))
+-		return;
+-
+-	bcm43xx_phy_write(bcm, 0x0028, 0x8018);
+-	bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
+-
+-	if (phy->type == BCM43xx_PHYTYPE_G) {
+-		if (!phy->connected)
+-			return;
+-		bcm43xx_phy_write(bcm, 0x047A, 0xC111);
+-	}
+-	if (phy->savedpctlreg != 0xFFFF)
+-		return;
+-
+-	if (phy->type == BCM43xx_PHYTYPE_B &&
+-	    phy->rev >= 2 &&
+-	    radio->version == 0x2050) {
+-		bcm43xx_radio_write16(bcm, 0x0076,
+-				      bcm43xx_radio_read16(bcm, 0x0076) | 0x0084);
+-	} else {
+-		saved_batt = radio->baseband_atten;
+-		saved_ratt = radio->radio_atten;
+-		saved_txctl1 = radio->txctl1;
+-		if ((radio->revision >= 6) && (radio->revision <= 8)
+-		    && /*FIXME: incomplete specs for 5 < revision < 9 */ 0)
+-			bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0);
+-		else
+-			bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0);
+-		must_reset_txpower = 1;
+-	}
+-	bcm43xx_dummy_transmission(bcm);
+-
+-	phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL);
+-
+-	if (must_reset_txpower)
+-		bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1);
+-	else
+-		bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B);
+-	bcm43xx_radio_clear_tssi(bcm);
+-}
+-
+-static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 offset = 0x0000;
+-
+-	if (phy->rev == 1)
+-		offset = 0x4C00;
+-
+-	bcm43xx_ilt_write(bcm, offset, 0x00FE);
+-	bcm43xx_ilt_write(bcm, offset + 1, 0x000D);
+-	bcm43xx_ilt_write(bcm, offset + 2, 0x0013);
+-	bcm43xx_ilt_write(bcm, offset + 3, 0x0019);
+-
+-	if (phy->rev == 1) {
+-		bcm43xx_ilt_write(bcm, 0x1800, 0x2710);
+-		bcm43xx_ilt_write(bcm, 0x1801, 0x9B83);
+-		bcm43xx_ilt_write(bcm, 0x1802, 0x9B83);
+-		bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D);
+-		bcm43xx_phy_write(bcm, 0x0455, 0x0004);
+-	}
+-
+-	bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700);
+-	bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F);
+-	bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80);
+-	bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300);
+-
+-	bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008);
+-
+-	bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008);
+-	bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600);
+-	bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700);
+-	bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100);
+-
+-	if (phy->rev == 1)
+-		bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007);
+-
+-	bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C);
+-	bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200);
+-	bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C);
+-	bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020);
+-	bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200);
+-	bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E);
+-	bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00);
+-	bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028);
+-	bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00);
+-
+-	if (phy->rev == 1) {
+-		bcm43xx_phy_write(bcm, 0x0430, 0x092B);
+-		bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002);
+-	} else {
+-		bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1);
+-		bcm43xx_phy_write(bcm, 0x041F, 0x287A);
+-		bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004);
+-	}
+-
+-	if (phy->rev > 2) {
+-		bcm43xx_phy_write(bcm, 0x0422, 0x287A);
+-		bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420)
+-				  & 0x0FFF) | 0x3000);
+-	}
+-		
+-	bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080)
+-					| 0x7874);
+-	bcm43xx_phy_write(bcm, 0x048E, 0x1C00);
+-
+-	if (phy->rev == 1) {
+-		bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB)
+-				  & 0xF0FF) | 0x0600);
+-		bcm43xx_phy_write(bcm, 0x048B, 0x005E);
+-		bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C)
+-				  & 0xFF00) | 0x001E);
+-		bcm43xx_phy_write(bcm, 0x048D, 0x0002);
+-	}
+-
+-	bcm43xx_ilt_write(bcm, offset + 0x0800, 0);
+-	bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
+-	bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
+-	bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
+-
+-	if (phy->rev >= 6) {
+-		bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+-				  & 0xFFFC));
+-		bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+-				  & 0xEFFF));
+-	}
+-}
+-
+-static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 i;
+-
+-	assert(phy->type == BCM43xx_PHYTYPE_G);
+-	if (phy->rev == 1) {
+-		bcm43xx_phy_write(bcm, 0x0406, 0x4F19);
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-				  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
+-				  & 0xFC3F) | 0x0340);
+-		bcm43xx_phy_write(bcm, 0x042C, 0x005A);
+-		bcm43xx_phy_write(bcm, 0x0427, 0x001A);
+-
+-		for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]);
+-		for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
+-		for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
+-			bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+-	} else {
+-		/* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
+-		bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
+-
+-		if (phy->rev == 2) {
+-			bcm43xx_phy_write(bcm, 0x04C0, 0x1861);
+-			bcm43xx_phy_write(bcm, 0x04C1, 0x0271);
+-		} else if (phy->rev > 2) {
+-			bcm43xx_phy_write(bcm, 0x04C0, 0x0098);
+-			bcm43xx_phy_write(bcm, 0x04C1, 0x0070);
+-			bcm43xx_phy_write(bcm, 0x04C9, 0x0080);
+-		}
+-		bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800);
+-
+-		for (i = 0; i < 64; i++)
+-			bcm43xx_ilt_write(bcm, 0x4000 + i, i);
+-		for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]);
+-	}
+-	
+-	if (phy->rev <= 2)
+-		for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
+-	else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
+-		for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
+-	else
+-		for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]);
+-	
+-	if (phy->rev == 2)
+-		for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
+-	else if ((phy->rev > 2) && (phy->rev <= 8))
+-		for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
+-	
+-	if (phy->rev == 1) {
+-		for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
+-			bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+-		for (i = 0; i < 4; i++) {
+-			bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
+-			bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
+-			bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020);
+-			bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020);
+-		}
+-		bcm43xx_phy_agcsetup(bcm);
+-
+-		if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+-		    (bcm->board_type == 0x0416) &&
+-		    (bcm->board_revision == 0x0017))
+-			return;
+-
+-		bcm43xx_ilt_write(bcm, 0x5001, 0x0002);
+-		bcm43xx_ilt_write(bcm, 0x5002, 0x0001);
+-	} else {
+-		for (i = 0; i <= 0x2F; i++)
+-			bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820);
+-		bcm43xx_phy_agcsetup(bcm);
+-		bcm43xx_phy_read(bcm, 0x0400); /* dummy read */
+-		bcm43xx_phy_write(bcm, 0x0403, 0x1000);
+-		bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
+-		bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
+-
+-		if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+-		    (bcm->board_type == 0x0416) &&
+-		    (bcm->board_revision == 0x0017))
+-			return;
+-
+-		bcm43xx_ilt_write(bcm, 0x0401, 0x0002);
+-		bcm43xx_ilt_write(bcm, 0x0402, 0x0001);
+-	}
+-}
+-
+-/* Initialize the noisescaletable for APHY */
+-static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	int i;
+-
+-	bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400);
+-	for (i = 0; i < 12; i++) {
+-		if (phy->rev == 2)
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
+-		else
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
+-	}
+-	if (phy->rev == 2)
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700);
+-	else
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300);
+-	for (i = 0; i < 11; i++) {
+-		if (phy->rev == 2)
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
+-		else
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
+-	}
+-	if (phy->rev == 2)
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067);
+-	else
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023);
+-}
+-
+-static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 i;
+-
+-	assert(phy->type == BCM43xx_PHYTYPE_A);
+-	switch (phy->rev) {
+-	case 2:
+-		bcm43xx_phy_write(bcm, 0x008E, 0x3800);
+-		bcm43xx_phy_write(bcm, 0x0035, 0x03FF);
+-		bcm43xx_phy_write(bcm, 0x0036, 0x0400);
+-
+-		bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
+-
+-		bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
+-		bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
+-		bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF);
+-		bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
+-
+-		bcm43xx_phy_write(bcm, 0x0024, 0x4680);
+-		bcm43xx_phy_write(bcm, 0x0020, 0x0003);
+-		bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
+-		bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
+-
+-		bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
+-		bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF);
+-		bcm43xx_phy_write(bcm, 0x008E, 0x58C1);
+-
+-		bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
+-		bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
+-		bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
+-		bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
+-		bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
+-
+-		bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
+-		bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
+-		bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
+-		bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
+-		bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
+-		bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
+-		bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
+-
+-		bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
+-		bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
+-		bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
+-
+-		for (i = 0; i < 16; i++)
+-			bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F);
+-
+-		bcm43xx_ilt_write(bcm, 0x3003, 0x1044);
+-		bcm43xx_ilt_write(bcm, 0x3004, 0x7201);
+-		bcm43xx_ilt_write(bcm, 0x3006, 0x0040);
+-		bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
+-
+-		for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]);
+-		for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
+-		for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
+-			bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+-		bcm43xx_phy_init_noisescaletbl(bcm);
+-		for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
+-			bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+-		break;
+-	case 3:
+-		for (i = 0; i < 64; i++)
+-			bcm43xx_ilt_write(bcm, 0x4000 + i, i);
+-
+-		bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
+-
+-		bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
+-		bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
+-		bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
+-
+-		bcm43xx_phy_write(bcm, 0x0024, 0x4680);
+-		bcm43xx_phy_write(bcm, 0x0020, 0x0003);
+-		bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
+-		bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
+-		bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
+-
+-		bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
+-		for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]);
+-		bcm43xx_phy_init_noisescaletbl(bcm);
+-		for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+-			bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
+-
+-		bcm43xx_phy_write(bcm, 0x0003, 0x1808);
+-
+-		bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
+-		bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
+-		bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
+-		bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
+-		bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
+-
+-		bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
+-		bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
+-		bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
+-		bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
+-		bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
+-		bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
+-		bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
+-
+-		bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
+-		bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
+-		bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
+-
+-		bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
+-		bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
+-		break;
+-	default:
+-		assert(0);
+-	}
+-}
+-
+-/* Initialize APHY. This is also called for the GPHY in some cases. */
+-static void bcm43xx_phy_inita(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 tval;
+-
+-	if (phy->type == BCM43xx_PHYTYPE_A) {
+-		bcm43xx_phy_setupa(bcm);
+-	} else {
+-		bcm43xx_phy_setupg(bcm);
+-		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+-			bcm43xx_phy_write(bcm, 0x046E, 0x03CF);
+-		return;
+-	}
+-
+-	bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
+-	                  (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340);
+-	bcm43xx_phy_write(bcm, 0x0034, 0x0001);
+-
+-	TODO();//TODO: RSSI AGC
+-	bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
+-	                  bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14));
+-	bcm43xx_radio_init2060(bcm);
+-
+-	if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)
+-	    && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) {
+-		if (radio->lofcal == 0xFFFF) {
+-			TODO();//TODO: LOF Cal
+-			bcm43xx_radio_set_tx_iq(bcm);
+-		} else
+-			bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal);
+-	}
+-
+-	bcm43xx_phy_write(bcm, 0x007A, 0xF111);
+-
+-	if (phy->savedpctlreg == 0xFFFF) {
+-		bcm43xx_radio_write16(bcm, 0x0019, 0x0000);
+-		bcm43xx_radio_write16(bcm, 0x0017, 0x0020);
+-
+-		tval = bcm43xx_ilt_read(bcm, 0x3001);
+-		if (phy->rev == 1) {
+-			bcm43xx_ilt_write(bcm, 0x3001,
+-					  (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87)
+-					  | 0x0058);
+-		} else {
+-			bcm43xx_ilt_write(bcm, 0x3001,
+-					  (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3)
+-					  | 0x002C);
+-		}
+-		bcm43xx_dummy_transmission(bcm);
+-		phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL);
+-		bcm43xx_ilt_write(bcm, 0x3001, tval);
+-
+-		bcm43xx_radio_set_txpower_a(bcm, 0x0018);
+-	}
+-	bcm43xx_radio_clear_tssi(bcm);
+-}
+-
+-static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 offset, val;
+-
+-	bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+-	bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+-	bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+-	bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+-	bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
+-	val = 0x3C3D;
+-	for (offset = 0x0089; offset < 0x00A7; offset++) {
+-		bcm43xx_phy_write(bcm, offset, val);
+-		val -= 0x0202;
+-	}
+-	bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
+-	if (radio->channel == 0xFF)
+-		bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+-	else
+-		bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
+-	if (radio->version != 0x2050) {
+-		bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+-		bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+-	}
+-	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+-	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+-	if (radio->version == 0x2050) {
+-		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+-		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+-		bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+-		bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+-		bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
+-		bcm43xx_phy_write(bcm, 0x0038, 0x0677);
+-		bcm43xx_radio_init2050(bcm);
+-	}
+-	bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+-	bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+-	bcm43xx_phy_write(bcm, 0x0032, 0x00CC);
+-	bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
+-	bcm43xx_phy_lo_b_measure(bcm);
+-	bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+-	if (radio->version != 0x2050)
+-		bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000);
+-	bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+-	if (radio->version != 0x2050)
+-		bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+-	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+-	bcm43xx_phy_init_pctl(bcm);
+-}
+-
+-static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 offset, val;
+-
+-	bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+-	bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+-	bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+-	bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+-	bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
+-	val = 0x3C3D;
+-	for (offset = 0x0089; offset < 0x00A7; offset++) {
+-		bcm43xx_phy_write(bcm, offset, val);
+-		val -= 0x0202;
+-	}
+-	bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
+-	if (radio->channel == 0xFF)
+-		bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+-	else
+-		bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
+-	if (radio->version != 0x2050) {
+-		bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+-		bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+-	}
+-	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+-	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+-	if (radio->version == 0x2050) {
+-		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+-		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+-		bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+-		bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+-		bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
+-		bcm43xx_phy_write(bcm, 0x0038, 0x0677);
+-		bcm43xx_radio_init2050(bcm);
+-	}
+-	bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+-	bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+-	if (radio->version == 0x2050)
+-		bcm43xx_phy_write(bcm, 0x0032, 0x00E0);
+-	bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
+-
+-	bcm43xx_phy_lo_b_measure(bcm);
+-
+-	bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+-	if (radio->version == 0x2050)
+-		bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100);
+-	bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+-	if (radio->version == 0x2050)
+-		bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+-	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+-	if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+-		bcm43xx_calc_nrssi_slope(bcm);
+-		bcm43xx_calc_nrssi_threshold(bcm);
+-	}
+-	bcm43xx_phy_init_pctl(bcm);
+-}
+-
+-static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 offset;
+-	u16 value;
+-	u8 old_channel;
+-
+-	if (phy->analog == 1)
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A)
+-				      | 0x0050);
+-	if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
+-	    (bcm->board_type != 0x0416)) {
+-		value = 0x2120;
+-		for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
+-			bcm43xx_phy_write(bcm, offset, value);
+-			value += 0x0202;
+-		}
+-	}
+-	bcm43xx_phy_write(bcm, 0x0035,
+-			  (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF)
+-			  | 0x0700);
+-	if (radio->version == 0x2050)
+-		bcm43xx_phy_write(bcm, 0x0038, 0x0667);
+-
+-	if (phy->connected) {
+-		if (radio->version == 0x2050) {
+-			bcm43xx_radio_write16(bcm, 0x007A,
+-					      bcm43xx_radio_read16(bcm, 0x007A)
+-					      | 0x0020);
+-			bcm43xx_radio_write16(bcm, 0x0051,
+-					      bcm43xx_radio_read16(bcm, 0x0051)
+-					      | 0x0004);
+-		}
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000);
+-
+-		bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
+-		bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+-
+-		bcm43xx_phy_write(bcm, 0x001C, 0x186A);
+-
+-		bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900);
+-		bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064);
+-		bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A);
+-	}
+-
+-	if (bcm->bad_frames_preempt) {
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+-				  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
+-	}
+-
+-	if (phy->analog == 1) {
+-		bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+-		bcm43xx_phy_write(bcm, 0x0021, 0x3763);
+-		bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
+-		bcm43xx_phy_write(bcm, 0x0023, 0x06F9);
+-		bcm43xx_phy_write(bcm, 0x0024, 0x037E);
+-	} else
+-		bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+-	bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+-	bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+-
+-	if (phy->analog == 1)
+-		bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
+-	else
+-		bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+-
+-	if (phy->analog == 0)
+-		bcm43xx_write16(bcm, 0x03E4, 0x3000);
+-
+-	old_channel = radio->channel;
+-	/* Force to channel 7, even if not supported. */
+-	bcm43xx_radio_selectchannel(bcm, 7, 0);
+-
+-	if (radio->version != 0x2050) {
+-		bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+-		bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+-	}
+-
+-	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+-	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+-
+-	if (radio->version == 0x2050) {
+-		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+-		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+-	}
+-
+-	bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+-	bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+-
+-	bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
+-
+-	bcm43xx_radio_selectchannel(bcm, old_channel, 0);
+-
+-	bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+-	bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+-	bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+-
+-	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+-
+-	if (radio->version == 0x2050)
+-		bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
+-
+-	bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004);
+-}
+-
+-static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 offset, val;
+-	u8 old_channel;
+-
+-	bcm43xx_phy_write(bcm, 0x003E, 0x817A);
+-	bcm43xx_radio_write16(bcm, 0x007A,
+-	                      (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
+-	if (radio->revision == 4 ||
+-	     radio->revision == 5) {
+-		bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
+-		bcm43xx_radio_write16(bcm, 0x0052, 0x0070);
+-		bcm43xx_radio_write16(bcm, 0x0053, 0x00B3);
+-		bcm43xx_radio_write16(bcm, 0x0054, 0x009B);
+-		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+-		bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
+-		bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
+-		bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
+-		bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
+-		bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+-				    BCM43xx_UCODEFLAGS_OFFSET,
+-				    (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+-				    BCM43xx_UCODEFLAGS_OFFSET)
+-				    | 0x00000200));
+-	}
+-	if (radio->revision == 8) {
+-		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
+-		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+-		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
+-		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+-		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+-		bcm43xx_radio_write16(bcm, 0x005B, 0x006B);
+-		bcm43xx_radio_write16(bcm, 0x005C, 0x000F);
+-		if (bcm->sprom.boardflags & 0x8000) {
+-			bcm43xx_radio_write16(bcm, 0x005D, 0x00FA);
+-			bcm43xx_radio_write16(bcm, 0x005E, 0x00D8);
+-		} else {
+-			bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
+-			bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
+-		}
+-		bcm43xx_radio_write16(bcm, 0x0073, 0x0003);
+-		bcm43xx_radio_write16(bcm, 0x007D, 0x00A8);
+-		bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
+-		bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
+-	}
+-	val = 0x1E1F;
+-	for (offset = 0x0088; offset < 0x0098; offset++) {
+-		bcm43xx_phy_write(bcm, offset, val);
+-		val -= 0x0202;
+-	}
+-	val = 0x3E3F;
+-	for (offset = 0x0098; offset < 0x00A8; offset++) {
+-		bcm43xx_phy_write(bcm, offset, val);
+-		val -= 0x0202;
+-	}
+-	val = 0x2120;
+-	for (offset = 0x00A8; offset < 0x00C8; offset++) {
+-		bcm43xx_phy_write(bcm, offset, (val & 0x3F3F));
+-		val += 0x0202;
+-	}
+-	if (phy->type == BCM43xx_PHYTYPE_G) {
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-		                      bcm43xx_radio_read16(bcm, 0x007A) | 0x0020);
+-		bcm43xx_radio_write16(bcm, 0x0051,
+-		                      bcm43xx_radio_read16(bcm, 0x0051) | 0x0004);
+-		bcm43xx_phy_write(bcm, 0x0802,
+-		                  bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
+-		bcm43xx_phy_write(bcm, 0x042B,
+-		                  bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+-		bcm43xx_phy_write(bcm, 0x5B, 0x0000);
+-		bcm43xx_phy_write(bcm, 0x5C, 0x0000);
+-	}
+-
+-	old_channel = radio->channel;
+-	if (old_channel >= 8)
+-		bcm43xx_radio_selectchannel(bcm, 1, 0);
+-	else
+-		bcm43xx_radio_selectchannel(bcm, 13, 0);
+-
+-	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+-	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+-	udelay(40);
+-	if (radio->revision < 6 || radio-> revision == 8) {
+-		bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C)
+-				      | 0x0002));
+-		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+-	}
+-	if (radio->revision <= 2) {
+-		bcm43xx_radio_write16(bcm, 0x007C, 0x0020);
+-		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+-		bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+-		bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+-	}
+-	bcm43xx_radio_write16(bcm, 0x007A,
+-	                      (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
+-
+-	bcm43xx_radio_selectchannel(bcm, old_channel, 0);
+-
+-	bcm43xx_phy_write(bcm, 0x0014, 0x0200);
+-	if (radio->revision >= 6)
+-		bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+-	else
+-		bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
+-	bcm43xx_phy_write(bcm, 0x0038, 0x0668);
+-	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+-	if (radio->revision <= 5)
+-		bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D)
+-			          & 0xFF80) | 0x0003);
+-	if (radio->revision <= 2)
+-		bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
+-	
+-	if (phy->analog == 4){
+-		bcm43xx_write16(bcm, 0x03E4, 0x0009);
+-		bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF);
+-	} else {
+-		bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
+-	}
+-	if (phy->type == BCM43xx_PHYTYPE_G)
+-		bcm43xx_write16(bcm, 0x03E6, 0x0);
+-	if (phy->type == BCM43xx_PHYTYPE_B) {
+-		bcm43xx_write16(bcm, 0x03E6, 0x8140);
+-		bcm43xx_phy_write(bcm, 0x0016, 0x0410);
+-		bcm43xx_phy_write(bcm, 0x0017, 0x0820);
+-		bcm43xx_phy_write(bcm, 0x0062, 0x0007);
+-		bcm43xx_radio_init2050(bcm);
+-		bcm43xx_phy_lo_g_measure(bcm);
+-		if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+-			bcm43xx_calc_nrssi_slope(bcm);
+-			bcm43xx_calc_nrssi_threshold(bcm);
+-		}
+-		bcm43xx_phy_init_pctl(bcm);
+-	}
+-}
+-
+-static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 backup_phy[15] = {0};
+-	u16 backup_radio[3];
+-	u16 backup_bband;
+-	u16 i;
+-	u16 loop1_cnt, loop1_done, loop1_omitted;
+-	u16 loop2_done;
+-
+-	backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429);
+-	backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001);
+-	backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811);
+-	backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812);
+-	if (phy->rev != 1) {
+-		backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814);
+-		backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815);
+-	}
+-	backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A);
+-	backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059);
+-	backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058);
+-	backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A);
+-	backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003);
+-	backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F);
+-	backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810);
+-	backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B);
+-	backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015);
+-	bcm43xx_phy_read(bcm, 0x002D); /* dummy read */
+-	backup_bband = radio->baseband_atten;
+-	backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052);
+-	backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043);
+-	backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A);
+-
+-	bcm43xx_phy_write(bcm, 0x0429,
+-			  bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF);
+-	bcm43xx_phy_write(bcm, 0x0001,
+-			  bcm43xx_phy_read(bcm, 0x0001) & 0x8000);
+-	bcm43xx_phy_write(bcm, 0x0811,
+-			  bcm43xx_phy_read(bcm, 0x0811) | 0x0002);
+-	bcm43xx_phy_write(bcm, 0x0812,
+-			  bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD);
+-	bcm43xx_phy_write(bcm, 0x0811,
+-			  bcm43xx_phy_read(bcm, 0x0811) | 0x0001);
+-	bcm43xx_phy_write(bcm, 0x0812,
+-			  bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE);
+-	if (phy->rev != 1) {
+-		bcm43xx_phy_write(bcm, 0x0814,
+-				  bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
+-		bcm43xx_phy_write(bcm, 0x0815,
+-				  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
+-		bcm43xx_phy_write(bcm, 0x0814,
+-				  bcm43xx_phy_read(bcm, 0x0814) | 0x0002);
+-		bcm43xx_phy_write(bcm, 0x0815,
+-				  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD);
+-	}
+-	bcm43xx_phy_write(bcm, 0x0811,
+-			  bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+-	bcm43xx_phy_write(bcm, 0x0812,
+-			  bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
+-
+-	bcm43xx_phy_write(bcm, 0x0811,
+-			  (bcm43xx_phy_read(bcm, 0x0811)
+-			   & 0xFFCF) | 0x0030);
+-	bcm43xx_phy_write(bcm, 0x0812,
+-			  (bcm43xx_phy_read(bcm, 0x0812)
+-			   & 0xFFCF) | 0x0010);
+-
+-	bcm43xx_phy_write(bcm, 0x005A, 0x0780);
+-	bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+-	bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+-	if (phy->analog == 0) {
+-		bcm43xx_phy_write(bcm, 0x0003, 0x0122);
+-	} else {
+-		bcm43xx_phy_write(bcm, 0x000A,
+-				  bcm43xx_phy_read(bcm, 0x000A)
+-				  | 0x2000);
+-	}
+-	if (phy->rev != 1) {
+-		bcm43xx_phy_write(bcm, 0x0814,
+-				  bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
+-		bcm43xx_phy_write(bcm, 0x0815,
+-				  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+-	}
+-	bcm43xx_phy_write(bcm, 0x0003,
+-			  (bcm43xx_phy_read(bcm, 0x0003)
+-			   & 0xFF9F) | 0x0040);
+-	if (radio->version == 0x2050 && radio->revision == 2) {
+-		bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+-		bcm43xx_radio_write16(bcm, 0x0043,
+-				      (bcm43xx_radio_read16(bcm, 0x0043)
+-				       & 0xFFF0) | 0x0009);
+-		loop1_cnt = 9;
+-	} else if (radio->revision == 8) {
+-		bcm43xx_radio_write16(bcm, 0x0043, 0x000F);
+-		loop1_cnt = 15;
+-	} else
+-		loop1_cnt = 0;
+-
+-	bcm43xx_phy_set_baseband_attenuation(bcm, 11);
+-
+-	if (phy->rev >= 3)
+-		bcm43xx_phy_write(bcm, 0x080F, 0xC020);
+-	else
+-		bcm43xx_phy_write(bcm, 0x080F, 0x8020);
+-	bcm43xx_phy_write(bcm, 0x0810, 0x0000);
+-
+-	bcm43xx_phy_write(bcm, 0x002B,
+-			  (bcm43xx_phy_read(bcm, 0x002B)
+-			   & 0xFFC0) | 0x0001);
+-	bcm43xx_phy_write(bcm, 0x002B,
+-			  (bcm43xx_phy_read(bcm, 0x002B)
+-			   & 0xC0FF) | 0x0800);
+-	bcm43xx_phy_write(bcm, 0x0811,
+-			  bcm43xx_phy_read(bcm, 0x0811) | 0x0100);
+-	bcm43xx_phy_write(bcm, 0x0812,
+-			  bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF);
+-	if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) {
+-		if (phy->rev >= 7) {
+-			bcm43xx_phy_write(bcm, 0x0811,
+-					  bcm43xx_phy_read(bcm, 0x0811)
+-					  | 0x0800);
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  bcm43xx_phy_read(bcm, 0x0812)
+-					  | 0x8000);
+-		}
+-	}
+-	bcm43xx_radio_write16(bcm, 0x007A,
+-			      bcm43xx_radio_read16(bcm, 0x007A)
+-			      & 0x00F7);
+-
+-	for (i = 0; i < loop1_cnt; i++) {
+-		bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt);
+-		bcm43xx_phy_write(bcm, 0x0812,
+-				  (bcm43xx_phy_read(bcm, 0x0812)
+-				   & 0xF0FF) | (i << 8));
+-		bcm43xx_phy_write(bcm, 0x0015,
+-				  (bcm43xx_phy_read(bcm, 0x0015)
+-				   & 0x0FFF) | 0xA000);
+-		bcm43xx_phy_write(bcm, 0x0015,
+-				  (bcm43xx_phy_read(bcm, 0x0015)
+-				   & 0x0FFF) | 0xF000);
+-		udelay(20);
+-		if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
+-			break;
+-	}
+-	loop1_done = i;
+-	loop1_omitted = loop1_cnt - loop1_done;
+-
+-	loop2_done = 0;
+-	if (loop1_done >= 8) {
+-		bcm43xx_phy_write(bcm, 0x0812,
+-				  bcm43xx_phy_read(bcm, 0x0812)
+-				  | 0x0030);
+-		for (i = loop1_done - 8; i < 16; i++) {
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  (bcm43xx_phy_read(bcm, 0x0812)
+-					   & 0xF0FF) | (i << 8));
+-			bcm43xx_phy_write(bcm, 0x0015,
+-					  (bcm43xx_phy_read(bcm, 0x0015)
+-					   & 0x0FFF) | 0xA000);
+-			bcm43xx_phy_write(bcm, 0x0015,
+-					  (bcm43xx_phy_read(bcm, 0x0015)
+-					   & 0x0FFF) | 0xF000);
+-			udelay(20);
+-			if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
+-				break;
+-		}
+-	}
+-
+-	if (phy->rev != 1) {
+-		bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]);
+-		bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]);
+-	}
+-	bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]);
+-	bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]);
+-	bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]);
+-	bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]);
+-	bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]);
+-	bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]);
+-	bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]);
+-	bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]);
+-	bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]);
+-
+-	bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband);
+-
+-	bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]);
+-	bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]);
+-	bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]);
+-
+-	bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003);
+-	udelay(10);
+-	bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]);
+-	bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]);
+-	bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]);
+-	bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]);
+-
+-	phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11;
+-	phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2;
+-}
+-
+-static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 tmp;
+-
+-	if (phy->rev == 1)
+-		bcm43xx_phy_initb5(bcm);
+-	else
+-		bcm43xx_phy_initb6(bcm);
+-	if (phy->rev >= 2 || phy->connected)
+-		bcm43xx_phy_inita(bcm);
+-
+-	if (phy->rev >= 2) {
+-		bcm43xx_phy_write(bcm, 0x0814, 0x0000);
+-		bcm43xx_phy_write(bcm, 0x0815, 0x0000);
+-	}
+-	if (phy->rev == 2) {
+-		bcm43xx_phy_write(bcm, 0x0811, 0x0000);
+-		bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
+-	}
+-	if (phy->rev > 5) {
+-		bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+-		bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
+-	}
+-	if (phy->rev >= 2 && phy->connected) {
+-		tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
+-		if (tmp ==3 || tmp == 5) {
+-			bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
+-			bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
+-			if (tmp == 5) {
+-				bcm43xx_phy_write(bcm, 0x04CC,
+-						  (bcm43xx_phy_read(bcm, 0x04CC)
+-						   & 0x00FF) | 0x1F00);
+-			}
+-		}
+-		bcm43xx_phy_write(bcm, 0x047E, 0x0078);
+-	}
+-	if (radio->revision == 8) {
+-		bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
+-		bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
+-	}
+-	if (phy->rev >= 2 && phy->connected)
+-		bcm43xx_calc_loopback_gain(bcm);
+-	if (radio->revision != 8) {
+-		if (radio->initval == 0xFFFF)
+-			radio->initval = bcm43xx_radio_init2050(bcm);
+-		else
+-			bcm43xx_radio_write16(bcm, 0x0078, radio->initval);
+-	}
+-	if (radio->txctl2 == 0xFFFF) {
+-		bcm43xx_phy_lo_g_measure(bcm);
+-	} else {
+-		if (radio->version == 0x2050 && radio->revision == 8) {
+-			bcm43xx_radio_write16(bcm, 0x0052,
+-					      (radio->txctl1 << 4) | radio->txctl2);
+-		} else {
+-			bcm43xx_radio_write16(bcm, 0x0052,
+-					      (bcm43xx_radio_read16(bcm, 0x0052)
+-					       & 0xFFF0) | radio->txctl1);
+-		}
+-		if (phy->rev >= 6) {
+-			bcm43xx_phy_write(bcm, 0x0036,
+-					  (bcm43xx_phy_read(bcm, 0x0036)
+-					   & 0x0FFF) | (radio->txctl2 << 12));
+-		}
+-		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+-			bcm43xx_phy_write(bcm, 0x002E, 0x8075);
+-		else
+-			bcm43xx_phy_write(bcm, 0x002E, 0x807F);
+-		if (phy->rev < 2)
+-			bcm43xx_phy_write(bcm, 0x002F, 0x0101);
+-		else
+-			bcm43xx_phy_write(bcm, 0x002F, 0x0202);
+-	}
+-	if (phy->connected || phy->rev >= 2) {
+-		bcm43xx_phy_lo_adjust(bcm, 0);
+-		bcm43xx_phy_write(bcm, 0x080F, 0x8078);
+-	}
+-
+-	if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+-		/* The specs state to update the NRSSI LT with
+-		 * the value 0x7FFFFFFF here. I think that is some weird
+-		 * compiler optimization in the original driver.
+-		 * Essentially, what we do here is resetting all NRSSI LT
+-		 * entries to -32 (see the limit_value() in nrssi_hw_update())
+-		 */
+-		bcm43xx_nrssi_hw_update(bcm, 0xFFFF);
+-		bcm43xx_calc_nrssi_threshold(bcm);
+-	} else if (phy->connected || phy->rev >= 2) {
+-		if (radio->nrssi[0] == -1000) {
+-			assert(radio->nrssi[1] == -1000);
+-			bcm43xx_calc_nrssi_slope(bcm);
+-		} else {
+-			assert(radio->nrssi[1] != -1000);
+-			bcm43xx_calc_nrssi_threshold(bcm);
+-		}
+-	}
+-	if (radio->revision == 8)
+-		bcm43xx_phy_write(bcm, 0x0805, 0x3230);
+-	bcm43xx_phy_init_pctl(bcm);
+-	if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
+-		bcm43xx_phy_write(bcm, 0x0429,
+-				  bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
+-		bcm43xx_phy_write(bcm, 0x04C3,
+-				  bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF);
+-	}
+-}
+-
+-static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
+-{
+-	int i;
+-	u16 ret = 0;
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	for (i = 0; i < 10; i++){
+-		bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
+-		udelay(1);
+-		bcm43xx_phy_write(bcm, 0x0015, 0xEFA0);
+-		udelay(10);
+-		bcm43xx_phy_write(bcm, 0x0015, 0xFFA0);
+-		udelay(40);
+-		ret += bcm43xx_phy_read(bcm, 0x002C);
+-	}
+-	local_irq_restore(flags);
+-	bcm43xx_voluntary_preempt();
+-
+-	return ret;
+-}
+-
+-void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 regstack[12] = { 0 };
+-	u16 mls;
+-	u16 fval;
+-	int i, j;
+-
+-	regstack[0] = bcm43xx_phy_read(bcm, 0x0015);
+-	regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0;
+-
+-	if (radio->version == 0x2053) {
+-		regstack[2] = bcm43xx_phy_read(bcm, 0x000A);
+-		regstack[3] = bcm43xx_phy_read(bcm, 0x002A);
+-		regstack[4] = bcm43xx_phy_read(bcm, 0x0035);
+-		regstack[5] = bcm43xx_phy_read(bcm, 0x0003);
+-		regstack[6] = bcm43xx_phy_read(bcm, 0x0001);
+-		regstack[7] = bcm43xx_phy_read(bcm, 0x0030);
+-
+-		regstack[8] = bcm43xx_radio_read16(bcm, 0x0043);
+-		regstack[9] = bcm43xx_radio_read16(bcm, 0x007A);
+-		regstack[10] = bcm43xx_read16(bcm, 0x03EC);
+-		regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0;
+-
+-		bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+-		bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
+-		bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F);
+-		bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0);
+-	}
+-	bcm43xx_phy_write(bcm, 0x0015, 0xB000);
+-	bcm43xx_phy_write(bcm, 0x002B, 0x0004);
+-
+-	if (radio->version == 0x2053) {
+-		bcm43xx_phy_write(bcm, 0x002B, 0x0203);
+-		bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+-	}
+-
+-	phy->minlowsig[0] = 0xFFFF;
+-
+-	for (i = 0; i < 4; i++) {
+-		bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
+-		bcm43xx_phy_lo_b_r15_loop(bcm);
+-	}
+-	for (i = 0; i < 10; i++) {
+-		bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
+-		mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
+-		if (mls < phy->minlowsig[0]) {
+-			phy->minlowsig[0] = mls;
+-			phy->minlowsigpos[0] = i;
+-		}
+-	}
+-	bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]);
+-
+-	phy->minlowsig[1] = 0xFFFF;
+-
+-	for (i = -4; i < 5; i += 2) {
+-		for (j = -4; j < 5; j += 2) {
+-			if (j < 0)
+-				fval = (0x0100 * i) + j + 0x0100;
+-			else
+-				fval = (0x0100 * i) + j;
+-			bcm43xx_phy_write(bcm, 0x002F, fval);
+-			mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
+-			if (mls < phy->minlowsig[1]) {
+-				phy->minlowsig[1] = mls;
+-				phy->minlowsigpos[1] = fval;
+-			}
+-		}
+-	}
+-	phy->minlowsigpos[1] += 0x0101;
+-
+-	bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]);
+-	if (radio->version == 0x2053) {
+-		bcm43xx_phy_write(bcm, 0x000A, regstack[2]);
+-		bcm43xx_phy_write(bcm, 0x002A, regstack[3]);
+-		bcm43xx_phy_write(bcm, 0x0035, regstack[4]);
+-		bcm43xx_phy_write(bcm, 0x0003, regstack[5]);
+-		bcm43xx_phy_write(bcm, 0x0001, regstack[6]);
+-		bcm43xx_phy_write(bcm, 0x0030, regstack[7]);
+-
+-		bcm43xx_radio_write16(bcm, 0x0043, regstack[8]);
+-		bcm43xx_radio_write16(bcm, 0x007A, regstack[9]);
+-
+-		bcm43xx_radio_write16(bcm, 0x0052,
+-		                      (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F)
+-				      | regstack[11]);
+-
+-		bcm43xx_write16(bcm, 0x03EC, regstack[10]);
+-	}
+-	bcm43xx_phy_write(bcm, 0x0015, regstack[0]);
+-}
+-
+-static inline
+-u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 ret;
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	if (phy->connected) {
+-		bcm43xx_phy_write(bcm, 0x15, 0xE300);
+-		control <<= 8;
+-		bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0);
+-		udelay(5);
+-		bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2);
+-		udelay(2);
+-		bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3);
+-		udelay(4);
+-		bcm43xx_phy_write(bcm, 0x0015, 0xF300);
+-		udelay(8);
+-	} else {
+-		bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0);
+-		udelay(2);
+-		bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0);
+-		udelay(4);
+-		bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
+-		udelay(8);
+-	}
+-	ret = bcm43xx_phy_read(bcm, 0x002D);
+-	local_irq_restore(flags);
+-	bcm43xx_voluntary_preempt();
+-
+-	return ret;
+-}
+-
+-static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
+-{
+-	int i;
+-	u32 ret = 0;
+-
+-	for (i = 0; i < 8; i++)
+-		ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control);
+-
+-	return ret;
+-}
+-
+-/* Write the LocalOscillator CONTROL */
+-static inline
+-void bcm43xx_lo_write(struct bcm43xx_private *bcm,
+-		      struct bcm43xx_lopair *pair)
+-{
+-	u16 value;
+-
+-	value = (u8)(pair->low);
+-	value |= ((u8)(pair->high)) << 8;
+-
+-#ifdef CONFIG_BCM43XX_DEBUG
+-	/* Sanity check. */
+-	if (pair->low < -8 || pair->low > 8 ||
+-	    pair->high < -8 || pair->high > 8) {
+-		printk(KERN_WARNING PFX
+-		       "WARNING: Writing invalid LOpair "
+-		       "(low: %d, high: %d, index: %lu)\n",
+-		       pair->low, pair->high,
+-		       (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs));
+-		dump_stack();
+-	}
+-#endif
+-
+-	bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value);
+-}
+-
+-static inline
+-struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm,
+-					    u16 baseband_attenuation,
+-					    u16 radio_attenuation,
+-					    u16 tx)
+-{
+-	static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+-	if (baseband_attenuation > 6)
+-		baseband_attenuation = 6;
+-	assert(radio_attenuation < 10);
+-
+-	if (tx == 3) {
+-		return bcm43xx_get_lopair(phy,
+-					  radio_attenuation,
+-					  baseband_attenuation);
+-	}
+-	return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation);
+-}
+-
+-static inline
+-struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+-	return bcm43xx_find_lopair(bcm,
+-				   radio->baseband_atten,
+-				   radio->radio_atten,
+-				   radio->txctl1);
+-}
+-
+-/* Adjust B/G LO */
+-void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed)
+-{
+-	struct bcm43xx_lopair *pair;
+-
+-	if (fixed) {
+-		/* Use fixed values. Only for initialization. */
+-		pair = bcm43xx_find_lopair(bcm, 2, 3, 0);
+-	} else
+-		pair = bcm43xx_current_lopair(bcm);
+-	bcm43xx_lo_write(bcm, pair);
+-}
+-
+-static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 txctl2 = 0, i;
+-	u32 smallest, tmp;
+-
+-	bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+-	udelay(10);
+-	smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
+-	for (i = 0; i < 16; i++) {
+-		bcm43xx_radio_write16(bcm, 0x0052, i);
+-		udelay(10);
+-		tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
+-		if (tmp < smallest) {
+-			smallest = tmp;
+-			txctl2 = i;
+-		}
+-	}
+-	radio->txctl2 = txctl2;
+-}
+-
+-static
+-void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm,
+-			    const struct bcm43xx_lopair *in_pair,
+-			    struct bcm43xx_lopair *out_pair,
+-			    u16 r27)
+-{
+-	static const struct bcm43xx_lopair transitions[8] = {
+-		{ .high =  1,  .low =  1, },
+-		{ .high =  1,  .low =  0, },
+-		{ .high =  1,  .low = -1, },
+-		{ .high =  0,  .low = -1, },
+-		{ .high = -1,  .low = -1, },
+-		{ .high = -1,  .low =  0, },
+-		{ .high = -1,  .low =  1, },
+-		{ .high =  0,  .low =  1, },
+-	};
+-	struct bcm43xx_lopair lowest_transition = {
+-		.high = in_pair->high,
+-		.low = in_pair->low,
+-	};
+-	struct bcm43xx_lopair tmp_pair;
+-	struct bcm43xx_lopair transition;
+-	int i = 12;
+-	int state = 0;
+-	int found_lower;
+-	int j, begin, end;
+-	u32 lowest_deviation;
+-	u32 tmp;
+-
+-	/* Note that in_pair and out_pair can point to the same pair. Be careful. */
+-
+-	bcm43xx_lo_write(bcm, &lowest_transition);
+-	lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
+-	do {
+-		found_lower = 0;
+-		assert(state >= 0 && state <= 8);
+-		if (state == 0) {
+-			begin = 1;
+-			end = 8;
+-		} else if (state % 2 == 0) {
+-			begin = state - 1;
+-			end = state + 1;
+-		} else {
+-			begin = state - 2;
+-			end = state + 2;
+-		}
+-		if (begin < 1)
+-			begin += 8;
+-		if (end > 8)
+-			end -= 8;
+-
+-		j = begin;
+-		tmp_pair.high = lowest_transition.high;
+-		tmp_pair.low = lowest_transition.low;
+-		while (1) {
+-			assert(j >= 1 && j <= 8);
+-			transition.high = tmp_pair.high + transitions[j - 1].high;
+-			transition.low = tmp_pair.low + transitions[j - 1].low;
+-			if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) {
+-				bcm43xx_lo_write(bcm, &transition);
+-				tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
+-				if (tmp < lowest_deviation) {
+-					lowest_deviation = tmp;
+-					state = j;
+-					found_lower = 1;
+-
+-					lowest_transition.high = transition.high;
+-					lowest_transition.low = transition.low;
+-				}
+-			}
+-			if (j == end)
+-				break;
+-			if (j == 8)
+-				j = 1;
+-			else
+-				j++;
+-		}
+-	} while (i-- && found_lower);
+-
+-	out_pair->high = lowest_transition.high;
+-	out_pair->low = lowest_transition.low;
+-}
+-
+-/* Set the baseband attenuation value on chip. */
+-void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
+-					  u16 baseband_attenuation)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 value;
+-
+-	if (phy->analog == 0) {
+-		value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
+-		value |= (baseband_attenuation & 0x000F);
+-		bcm43xx_write16(bcm, 0x03E6, value);
+-		return;
+-	}
+-
+-	if (phy->analog > 1) {
+-		value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
+-		value |= (baseband_attenuation << 2) & 0x003C;
+-	} else {
+-		value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078;
+-		value |= (baseband_attenuation << 3) & 0x0078;
+-	}
+-	bcm43xx_phy_write(bcm, 0x0060, value);
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */
+-void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
+-{
+-	static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
+-	const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING);
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 h, i, oldi = 0, j;
+-	struct bcm43xx_lopair control;
+-	struct bcm43xx_lopair *tmp_control;
+-	u16 tmp;
+-	u16 regstack[16] = { 0 };
+-	u8 oldchannel;
+-
+-	//XXX: What are these?
+-	u8 r27 = 0, r31;
+-
+-	oldchannel = radio->channel;
+-	/* Setup */
+-	if (phy->connected) {
+-		regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
+-		regstack[1] = bcm43xx_phy_read(bcm, 0x0802);
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
+-		bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
+-	}
+-	regstack[3] = bcm43xx_read16(bcm, 0x03E2);
+-	bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000);
+-	regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+-	regstack[5] = bcm43xx_phy_read(bcm, 0x15);
+-	regstack[6] = bcm43xx_phy_read(bcm, 0x2A);
+-	regstack[7] = bcm43xx_phy_read(bcm, 0x35);
+-	regstack[8] = bcm43xx_phy_read(bcm, 0x60);
+-	regstack[9] = bcm43xx_radio_read16(bcm, 0x43);
+-	regstack[10] = bcm43xx_radio_read16(bcm, 0x7A);
+-	regstack[11] = bcm43xx_radio_read16(bcm, 0x52);
+-	if (phy->connected) {
+-		regstack[12] = bcm43xx_phy_read(bcm, 0x0811);
+-		regstack[13] = bcm43xx_phy_read(bcm, 0x0812);
+-		regstack[14] = bcm43xx_phy_read(bcm, 0x0814);
+-		regstack[15] = bcm43xx_phy_read(bcm, 0x0815);
+-	}
+-	bcm43xx_radio_selectchannel(bcm, 6, 0);
+-	if (phy->connected) {
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
+-		bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
+-		bcm43xx_dummy_transmission(bcm);
+-	}
+-	bcm43xx_radio_write16(bcm, 0x0043, 0x0006);
+-
+-	bcm43xx_phy_set_baseband_attenuation(bcm, 2);
+-
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000);
+-	bcm43xx_phy_write(bcm, 0x002E, 0x007F);
+-	bcm43xx_phy_write(bcm, 0x080F, 0x0078);
+-	bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7));
+-	bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0);
+-	bcm43xx_phy_write(bcm, 0x002B, 0x0203);
+-	bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+-	if (phy->connected) {
+-		bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003);
+-		bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC);
+-		bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
+-		bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
+-	}
+-	if (is_initializing)
+-		bcm43xx_phy_lo_g_measure_txctl2(bcm);
+-	bcm43xx_phy_write(bcm, 0x080F, 0x8078);
+-
+-	/* Measure */
+-	control.low = 0;
+-	control.high = 0;
+-	for (h = 0; h < 10; h++) {
+-		/* Loop over each possible RadioAttenuation (0-9) */
+-		i = pairorder[h];
+-		if (is_initializing) {
+-			if (i == 3) {
+-				control.low = 0;
+-				control.high = 0;
+-			} else if (((i % 2 == 1) && (oldi % 2 == 1)) ||
+-				  ((i % 2 == 0) && (oldi % 2 == 0))) {
+-				tmp_control = bcm43xx_get_lopair(phy, oldi, 0);
+-				memcpy(&control, tmp_control, sizeof(control));
+-			} else {
+-				tmp_control = bcm43xx_get_lopair(phy, 3, 0);
+-				memcpy(&control, tmp_control, sizeof(control));
+-			}
+-		}
+-		/* Loop over each possible BasebandAttenuation/2 */
+-		for (j = 0; j < 4; j++) {
+-			if (is_initializing) {
+-				tmp = i * 2 + j;
+-				r27 = 0;
+-				r31 = 0;
+-				if (tmp > 14) {
+-					r31 = 1;
+-					if (tmp > 17)
+-						r27 = 1;
+-					if (tmp > 19)
+-						r27 = 2;
+-				}
+-			} else {
+-				tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+-				if (!tmp_control->used)
+-					continue;
+-				memcpy(&control, tmp_control, sizeof(control));
+-				r27 = 3;
+-				r31 = 0;
+-			}
+-			bcm43xx_radio_write16(bcm, 0x43, i);
+-			bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
+-			udelay(10);
+-			bcm43xx_voluntary_preempt();
+-
+-			bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
+-
+-			tmp = (regstack[10] & 0xFFF0);
+-			if (r31)
+-				tmp |= 0x0008;
+-			bcm43xx_radio_write16(bcm, 0x007A, tmp);
+-
+-			tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+-			bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
+-		}
+-		oldi = i;
+-	}
+-	/* Loop over each possible RadioAttenuation (10-13) */
+-	for (i = 10; i < 14; i++) {
+-		/* Loop over each possible BasebandAttenuation/2 */
+-		for (j = 0; j < 4; j++) {
+-			if (is_initializing) {
+-				tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
+-				memcpy(&control, tmp_control, sizeof(control));
+-				tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger.
+-				r27 = 0;
+-				r31 = 0;
+-				if (tmp > 14) {
+-					r31 = 1;
+-					if (tmp > 17)
+-						r27 = 1;
+-					if (tmp > 19)
+-						r27 = 2;
+-				}
+-			} else {
+-				tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
+-				if (!tmp_control->used)
+-					continue;
+-				memcpy(&control, tmp_control, sizeof(control));
+-				r27 = 3;
+-				r31 = 0;
+-			}
+-			bcm43xx_radio_write16(bcm, 0x43, i - 9);
+-			bcm43xx_radio_write16(bcm, 0x52,
+-					      radio->txctl2
+-					      | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
+-			udelay(10);
+-			bcm43xx_voluntary_preempt();
+-
+-			bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
+-
+-			tmp = (regstack[10] & 0xFFF0);
+-			if (r31)
+-				tmp |= 0x0008;
+-			bcm43xx_radio_write16(bcm, 0x7A, tmp);
+-
+-			tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+-			bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
+-		}
+-	}
+-
+-	/* Restoration */
+-	if (phy->connected) {
+-		bcm43xx_phy_write(bcm, 0x0015, 0xE300);
+-		bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0);
+-		udelay(5);
+-		bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
+-		udelay(2);
+-		bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
+-		bcm43xx_voluntary_preempt();
+-	} else
+-		bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
+-	bcm43xx_phy_lo_adjust(bcm, is_initializing);
+-	bcm43xx_phy_write(bcm, 0x002E, 0x807F);
+-	if (phy->connected)
+-		bcm43xx_phy_write(bcm, 0x002F, 0x0202);
+-	else
+-		bcm43xx_phy_write(bcm, 0x002F, 0x0101);
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]);
+-	bcm43xx_phy_write(bcm, 0x0015, regstack[5]);
+-	bcm43xx_phy_write(bcm, 0x002A, regstack[6]);
+-	bcm43xx_phy_write(bcm, 0x0035, regstack[7]);
+-	bcm43xx_phy_write(bcm, 0x0060, regstack[8]);
+-	bcm43xx_radio_write16(bcm, 0x0043, regstack[9]);
+-	bcm43xx_radio_write16(bcm, 0x007A, regstack[10]);
+-	regstack[11] &= 0x00F0;
+-	regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F);
+-	bcm43xx_radio_write16(bcm, 0x52, regstack[11]);
+-	bcm43xx_write16(bcm, 0x03E2, regstack[3]);
+-	if (phy->connected) {
+-		bcm43xx_phy_write(bcm, 0x0811, regstack[12]);
+-		bcm43xx_phy_write(bcm, 0x0812, regstack[13]);
+-		bcm43xx_phy_write(bcm, 0x0814, regstack[14]);
+-		bcm43xx_phy_write(bcm, 0x0815, regstack[15]);
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]);
+-		bcm43xx_phy_write(bcm, 0x0802, regstack[1]);
+-	}
+-	bcm43xx_radio_selectchannel(bcm, oldchannel, 1);
+-
+-#ifdef CONFIG_BCM43XX_DEBUG
+-	{
+-		/* Sanity check for all lopairs. */
+-		for (i = 0; i < BCM43xx_LO_COUNT; i++) {
+-			tmp_control = phy->_lo_pairs + i;
+-			if (tmp_control->low < -8 || tmp_control->low > 8 ||
+-			    tmp_control->high < -8 || tmp_control->high > 8) {
+-				printk(KERN_WARNING PFX
+-				       "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n",
+-				       tmp_control->low, tmp_control->high, i);
+-			}
+-		}
+-	}
+-#endif /* CONFIG_BCM43XX_DEBUG */
+-}
+-
+-static
+-void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_lopair *pair;
+-
+-	pair = bcm43xx_current_lopair(bcm);
+-	pair->used = 1;
+-}
+-
+-void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_lopair *pair;
+-	int i;
+-
+-	for (i = 0; i < BCM43xx_LO_COUNT; i++) {
+-		pair = phy->_lo_pairs + i;
+-		pair->used = 0;
+-	}
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
+- * This function converts a TSSI value to dBm in Q5.2
+- */
+-static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	s8 dbm = 0;
+-	s32 tmp;
+-
+-	tmp = phy->idle_tssi;
+-	tmp += tssi;
+-	tmp -= phy->savedpctlreg;
+-
+-	switch (phy->type) {
+-		case BCM43xx_PHYTYPE_A:
+-			tmp += 0x80;
+-			tmp = limit_value(tmp, 0x00, 0xFF);
+-			dbm = phy->tssi2dbm[tmp];
+-			TODO(); //TODO: There's a FIXME on the specs
+-			break;
+-		case BCM43xx_PHYTYPE_B:
+-		case BCM43xx_PHYTYPE_G:
+-			tmp = limit_value(tmp, 0x00, 0x3F);
+-			dbm = phy->tssi2dbm[tmp];
+-			break;
+-		default:
+-			assert(0);
+-	}
+-
+-	return dbm;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
+-void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	
+-	if (phy->savedpctlreg == 0xFFFF)
+-		return;
+-	if ((bcm->board_type == 0x0416) &&
+-	    (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM))
+-		return;
+-	
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_A: {
+-
+-		TODO(); //TODO: Nothing for A PHYs yet :-/
+-
+-		break;
+-	}
+-	case BCM43xx_PHYTYPE_B:
+-	case BCM43xx_PHYTYPE_G: {
+-		u16 tmp;
+-		u16 txpower;
+-		s8 v0, v1, v2, v3;
+-		s8 average;
+-		u8 max_pwr;
+-		s16 desired_pwr, estimated_pwr, pwr_adjust;
+-		s16 radio_att_delta, baseband_att_delta;
+-		s16 radio_attenuation, baseband_attenuation;
+-		unsigned long phylock_flags;
+-
+-		tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058);
+-		v0 = (s8)(tmp & 0x00FF);
+-		v1 = (s8)((tmp & 0xFF00) >> 8);
+-		tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A);
+-		v2 = (s8)(tmp & 0x00FF);
+-		v3 = (s8)((tmp & 0xFF00) >> 8);
+-		tmp = 0;
+-
+-		if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
+-			tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070);
+-			v0 = (s8)(tmp & 0x00FF);
+-			v1 = (s8)((tmp & 0xFF00) >> 8);
+-			tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072);
+-			v2 = (s8)(tmp & 0x00FF);
+-			v3 = (s8)((tmp & 0xFF00) >> 8);
+-			if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
+-				return;
+-			v0 = (v0 + 0x20) & 0x3F;
+-			v1 = (v1 + 0x20) & 0x3F;
+-			v2 = (v2 + 0x20) & 0x3F;
+-			v3 = (v3 + 0x20) & 0x3F;
+-			tmp = 1;
+-		}
+-		bcm43xx_radio_clear_tssi(bcm);
+-
+-		average = (v0 + v1 + v2 + v3 + 2) / 4;
+-
+-		if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8))
+-			average -= 13;
+-
+-		estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average);
+-
+-		max_pwr = bcm->sprom.maxpower_bgphy;
+-
+-		if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) &&
+-		    (phy->type == BCM43xx_PHYTYPE_G))
+-			max_pwr -= 0x3;
+-
+-		/*TODO:
+-		max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr)
+-			where REG is the max power as per the regulatory domain
+-		*/
+-
+-		desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr);
+-		/* Check if we need to adjust the current power. */
+-		pwr_adjust = desired_pwr - estimated_pwr;
+-		radio_att_delta = -(pwr_adjust + 7) >> 3;
+-		baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta);
+-		if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
+-			bcm43xx_phy_lo_mark_current_used(bcm);
+-			return;
+-		}
+-
+-		/* Calculate the new attenuation values. */
+-		baseband_attenuation = radio->baseband_atten;
+-		baseband_attenuation += baseband_att_delta;
+-		radio_attenuation = radio->radio_atten;
+-		radio_attenuation += radio_att_delta;
+-
+-		/* Get baseband and radio attenuation values into their permitted ranges.
+-		 * baseband 0-11, radio 0-9.
+-		 * Radio attenuation affects power level 4 times as much as baseband.
+-		 */
+-		if (radio_attenuation < 0) {
+-			baseband_attenuation -= (4 * -radio_attenuation);
+-			radio_attenuation = 0;
+-		} else if (radio_attenuation > 9) {
+-			baseband_attenuation += (4 * (radio_attenuation - 9));
+-			radio_attenuation = 9;
+-		} else {
+-			while (baseband_attenuation < 0 && radio_attenuation > 0) {
+-				baseband_attenuation += 4;
+-				radio_attenuation--;
+-			}
+-			while (baseband_attenuation > 11 && radio_attenuation < 9) {
+-				baseband_attenuation -= 4;
+-				radio_attenuation++;
+-			}
+-		}
+-		baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+-
+-		txpower = radio->txctl1;
+-		if ((radio->version == 0x2050) && (radio->revision == 2)) {
+-			if (radio_attenuation <= 1) {
+-				if (txpower == 0) {
+-					txpower = 3;
+-					radio_attenuation += 2;
+-					baseband_attenuation += 2;
+-				} else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+-					baseband_attenuation += 4 * (radio_attenuation - 2);
+-					radio_attenuation = 2;
+-				}
+-			} else if (radio_attenuation > 4 && txpower != 0) {
+-				txpower = 0;
+-				if (baseband_attenuation < 3) {
+-					radio_attenuation -= 3;
+-					baseband_attenuation += 2;
+-				} else {
+-					radio_attenuation -= 2;
+-					baseband_attenuation -= 2;
+-				}
+-			}
+-		}
+-		radio->txctl1 = txpower;
+-		baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+-		radio_attenuation = limit_value(radio_attenuation, 0, 9);
+-
+-		bcm43xx_phy_lock(bcm, phylock_flags);
+-		bcm43xx_radio_lock(bcm);
+-		bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation,
+-					     radio_attenuation, txpower);
+-		bcm43xx_phy_lo_mark_current_used(bcm);
+-		bcm43xx_radio_unlock(bcm);
+-		bcm43xx_phy_unlock(bcm, phylock_flags);
+-		break;
+-	}
+-	default:
+-		assert(0);
+-	}
+-}
+-
+-static inline
+-s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den)
+-{
+-	if (num < 0)
+-		return num/den;
+-	else
+-		return (num+den/2)/den;
+-}
+-
+-static inline
+-s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
+-{
+-	s32 m1, m2, f = 256, q, delta;
+-	s8 i = 0;
+-	
+-	m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
+-	m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1);
+-	do {
+-		if (i > 15)
+-			return -EINVAL;
+-		q = bcm43xx_tssi2dbm_ad(f * 4096 -
+-					bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048);
+-		delta = abs(q - f);
+-		f = q;
+-		i++;
+-	} while (delta >= 2);
+-	entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128);
+-	return 0;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
+-int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	s16 pab0, pab1, pab2;
+-	u8 idx;
+-	s8 *dyn_tssi2dbm;
+-	
+-	if (phy->type == BCM43xx_PHYTYPE_A) {
+-		pab0 = (s16)(bcm->sprom.pa1b0);
+-		pab1 = (s16)(bcm->sprom.pa1b1);
+-		pab2 = (s16)(bcm->sprom.pa1b2);
+-	} else {
+-		pab0 = (s16)(bcm->sprom.pa0b0);
+-		pab1 = (s16)(bcm->sprom.pa0b1);
+-		pab2 = (s16)(bcm->sprom.pa0b2);
+-	}
+-
+-	if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) {
+-		phy->idle_tssi = 0x34;
+-		phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
+-		return 0;
+-	}
+-
+-	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
+-	    pab0 != -1 && pab1 != -1 && pab2 != -1) {
+-		/* The pabX values are set in SPROM. Use them. */
+-		if (phy->type == BCM43xx_PHYTYPE_A) {
+-			if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 &&
+-			    (s8)bcm->sprom.idle_tssi_tgt_aphy != -1)
+-				phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy);
+-			else
+-				phy->idle_tssi = 62;
+-		} else {
+-			if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 &&
+-			    (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1)
+-				phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy);
+-			else
+-				phy->idle_tssi = 62;
+-		}
+-		dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
+-		if (dyn_tssi2dbm == NULL) {
+-			printk(KERN_ERR PFX "Could not allocate memory "
+-					    "for tssi2dbm table\n");
+-			return -ENOMEM;
+-		}
+-		for (idx = 0; idx < 64; idx++)
+-			if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
+-				phy->tssi2dbm = NULL;
+-				printk(KERN_ERR PFX "Could not generate "
+-						    "tssi2dBm table\n");
+-				kfree(dyn_tssi2dbm);
+-				return -ENODEV;
+-			}
+-		phy->tssi2dbm = dyn_tssi2dbm;
+-		phy->dyn_tssi_tbl = 1;
+-	} else {
+-		/* pabX values not set in SPROM. */
+-		switch (phy->type) {
+-		case BCM43xx_PHYTYPE_A:
+-			/* APHY needs a generated table. */
+-			phy->tssi2dbm = NULL;
+-			printk(KERN_ERR PFX "Could not generate tssi2dBm "
+-					    "table (wrong SPROM info)!\n");
+-			return -ENODEV;
+-		case BCM43xx_PHYTYPE_B:
+-			phy->idle_tssi = 0x34;
+-			phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
+-			break;
+-		case BCM43xx_PHYTYPE_G:
+-			phy->idle_tssi = 0x34;
+-			phy->tssi2dbm = bcm43xx_tssi2dbm_g_table;
+-			break;
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-int bcm43xx_phy_init(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	int err = -ENODEV;
+-
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_A:
+-		if (phy->rev == 2 || phy->rev == 3) {
+-			bcm43xx_phy_inita(bcm);
+-			err = 0;
+-		}
+-		break;
+-	case BCM43xx_PHYTYPE_B:
+-		switch (phy->rev) {
+-		case 2:
+-			bcm43xx_phy_initb2(bcm);
+-			err = 0;
+-			break;
+-		case 4:
+-			bcm43xx_phy_initb4(bcm);
+-			err = 0;
+-			break;
+-		case 5:
+-			bcm43xx_phy_initb5(bcm);
+-			err = 0;
+-			break;
+-		case 6:
+-			bcm43xx_phy_initb6(bcm);
+-			err = 0;
+-			break;
+-		}
+-		break;
+-	case BCM43xx_PHYTYPE_G:
+-		bcm43xx_phy_initg(bcm);
+-		err = 0;
+-		break;
+-	}
+-	if (err)
+-		printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
+-
+-	return err;
+-}
+-
+-void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 antennadiv;
+-	u16 offset;
+-	u16 value;
+-	u32 ucodeflags;
+-
+-	antennadiv = phy->antenna_diversity;
+-
+-	if (antennadiv == 0xFFFF)
+-		antennadiv = 3;
+-	assert(antennadiv <= 3);
+-
+-	ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+-					BCM43xx_UCODEFLAGS_OFFSET);
+-	bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+-			    BCM43xx_UCODEFLAGS_OFFSET,
+-			    ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV);
+-
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_A:
+-	case BCM43xx_PHYTYPE_G:
+-		if (phy->type == BCM43xx_PHYTYPE_A)
+-			offset = 0x0000;
+-		else
+-			offset = 0x0400;
+-
+-		if (antennadiv == 2)
+-			value = (3/*automatic*/ << 7);
+-		else
+-			value = (antennadiv << 7);
+-		bcm43xx_phy_write(bcm, offset + 1,
+-				  (bcm43xx_phy_read(bcm, offset + 1)
+-				   & 0x7E7F) | value);
+-
+-		if (antennadiv >= 2) {
+-			if (antennadiv == 2)
+-				value = (antennadiv << 7);
+-			else
+-				value = (0/*force0*/ << 7);
+-			bcm43xx_phy_write(bcm, offset + 0x2B,
+-					  (bcm43xx_phy_read(bcm, offset + 0x2B)
+-					   & 0xFEFF) | value);
+-		}
+-
+-		if (phy->type == BCM43xx_PHYTYPE_G) {
+-			if (antennadiv >= 2)
+-				bcm43xx_phy_write(bcm, 0x048C,
+-						  bcm43xx_phy_read(bcm, 0x048C)
+-						   | 0x2000);
+-			else
+-				bcm43xx_phy_write(bcm, 0x048C,
+-						  bcm43xx_phy_read(bcm, 0x048C)
+-						   & ~0x2000);
+-			if (phy->rev >= 2) {
+-				bcm43xx_phy_write(bcm, 0x0461,
+-						  bcm43xx_phy_read(bcm, 0x0461)
+-						   | 0x0010);
+-				bcm43xx_phy_write(bcm, 0x04AD,
+-						  (bcm43xx_phy_read(bcm, 0x04AD)
+-						   & 0x00FF) | 0x0015);
+-				if (phy->rev == 2)
+-					bcm43xx_phy_write(bcm, 0x0427, 0x0008);
+-				else
+-					bcm43xx_phy_write(bcm, 0x0427,
+-						(bcm43xx_phy_read(bcm, 0x0427)
+-						 & 0x00FF) | 0x0008);
+-			}
+-			else if (phy->rev >= 6)
+-				bcm43xx_phy_write(bcm, 0x049B, 0x00DC);
+-		} else {
+-			if (phy->rev < 3)
+-				bcm43xx_phy_write(bcm, 0x002B,
+-						  (bcm43xx_phy_read(bcm, 0x002B)
+-						   & 0x00FF) | 0x0024);
+-			else {
+-				bcm43xx_phy_write(bcm, 0x0061,
+-						  bcm43xx_phy_read(bcm, 0x0061)
+-						   | 0x0010);
+-				if (phy->rev == 3) {
+-					bcm43xx_phy_write(bcm, 0x0093, 0x001D);
+-					bcm43xx_phy_write(bcm, 0x0027, 0x0008);
+-				} else {
+-					bcm43xx_phy_write(bcm, 0x0093, 0x003A);
+-					bcm43xx_phy_write(bcm, 0x0027,
+-						(bcm43xx_phy_read(bcm, 0x0027)
+-						 & 0x00FF) | 0x0008);
+-				}
+-			}
+-		}
+-		break;
+-	case BCM43xx_PHYTYPE_B:
+-		if (bcm->current_core->rev == 2)
+-			value = (3/*automatic*/ << 7);
+-		else
+-			value = (antennadiv << 7);
+-		bcm43xx_phy_write(bcm, 0x03E2,
+-				  (bcm43xx_phy_read(bcm, 0x03E2)
+-				   & 0xFE7F) | value);
+-		break;
+-	default:
+-		assert(0);
+-	}
+-
+-	if (antennadiv >= 2) {
+-		ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+-						BCM43xx_UCODEFLAGS_OFFSET);
+-		bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+-				    BCM43xx_UCODEFLAGS_OFFSET,
+-				    ucodeflags | BCM43xx_UCODEFLAG_AUTODIV);
+-	}
+-
+-	phy->antenna_diversity = antennadiv;
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
+deleted file mode 100644
+index 7311836..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
++++ /dev/null
+@@ -1,78 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 BCM43xx_PHY_H_
+-#define BCM43xx_PHY_H_
+-
+-#include <linux/types.h>
+-
+-struct bcm43xx_private;
+-
+-void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm);
+-#define bcm43xx_phy_lock(bcm, flags) \
+-	do {					\
+-		local_irq_save(flags);		\
+-		bcm43xx_raw_phy_lock(bcm);	\
+-	} while (0)
+-void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm);
+-#define bcm43xx_phy_unlock(bcm, flags) \
+-	do {					\
+-		bcm43xx_raw_phy_unlock(bcm);	\
+-		local_irq_restore(flags);	\
+-	} while (0)
+-
+-/* Card uses the loopback gain stuff */
+-#define has_loopback_gain(phy) \
+-        (((phy)->rev > 1) || ((phy)->connected))
+-
+-u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset);
+-void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+-
+-int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm);
+-int bcm43xx_phy_init(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm);
+-void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm);
+-int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect);
+-
+-void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm);
+-void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm);
+-void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm);
+-
+-/* Adjust the LocalOscillator to the saved values.
+- * "fixed" is only set to 1 once in initialization. Set to 0 otherwise.
+- */
+-void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed);
+-void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
+-					  u16 baseband_attenuation);
+-
+-#endif /* BCM43xx_PHY_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+deleted file mode 100644
+index 76ab109..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
++++ /dev/null
+@@ -1,674 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  PIO Transmission
+-
+-  Copyright (c) 2005 Michael Buesch <mbuesch at freenet.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 "bcm43xx.h"
+-#include "bcm43xx_pio.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_xmit.h"
+-#include "bcm43xx_power.h"
+-
+-#include <linux/delay.h>
+-
+-
+-static void tx_start(struct bcm43xx_pioqueue *queue)
+-{
+-	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+-			  BCM43xx_PIO_TXCTL_INIT);
+-}
+-
+-static void tx_octet(struct bcm43xx_pioqueue *queue,
+-		     u8 octet)
+-{
+-	if (queue->need_workarounds) {
+-		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+-				  octet);
+-		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+-				  BCM43xx_PIO_TXCTL_WRITELO);
+-	} else {
+-		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+-				  BCM43xx_PIO_TXCTL_WRITELO);
+-		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+-				  octet);
+-	}
+-}
+-
+-static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
+-			    const u8 *packet,
+-			    unsigned int *pos)
+-{
+-	const u8 *source;
+-	unsigned int i = *pos;
+-	u16 ret;
+-
+-	if (i < sizeof(*txhdr)) {
+-		source = (const u8 *)txhdr;
+-	} else {
+-		source = packet;
+-		i -= sizeof(*txhdr);
+-	}
+-	ret = le16_to_cpu( *((__le16 *)(source + i)) );
+-	*pos += 2;
+-
+-	return ret;
+-}
+-
+-static void tx_data(struct bcm43xx_pioqueue *queue,
+-		    struct bcm43xx_txhdr *txhdr,
+-		    const u8 *packet,
+-		    unsigned int octets)
+-{
+-	u16 data;
+-	unsigned int i = 0;
+-
+-	if (queue->need_workarounds) {
+-		data = tx_get_next_word(txhdr, packet, &i);
+-		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
+-	}
+-	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+-			  BCM43xx_PIO_TXCTL_WRITELO |
+-			  BCM43xx_PIO_TXCTL_WRITEHI);
+-	while (i < octets - 1) {
+-		data = tx_get_next_word(txhdr, packet, &i);
+-		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
+-	}
+-	if (octets % 2)
+-		tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]);
+-}
+-
+-static void tx_complete(struct bcm43xx_pioqueue *queue,
+-			struct sk_buff *skb)
+-{
+-	if (queue->need_workarounds) {
+-		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+-				  skb->data[skb->len - 1]);
+-		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+-				  BCM43xx_PIO_TXCTL_WRITELO |
+-				  BCM43xx_PIO_TXCTL_COMPLETE);
+-	} else {
+-		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+-				  BCM43xx_PIO_TXCTL_COMPLETE);
+-	}
+-}
+-
+-static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
+-			   struct bcm43xx_pio_txpacket *packet)
+-{
+-	u16 cookie = 0x0000;
+-	int packetindex;
+-
+-	/* We use the upper 4 bits for the PIO
+-	 * controller ID and the lower 12 bits
+-	 * for the packet index (in the cache).
+-	 */
+-	switch (queue->mmio_base) {
+-	case BCM43xx_MMIO_PIO1_BASE:
+-		break;
+-	case BCM43xx_MMIO_PIO2_BASE:
+-		cookie = 0x1000;
+-		break;
+-	case BCM43xx_MMIO_PIO3_BASE:
+-		cookie = 0x2000;
+-		break;
+-	case BCM43xx_MMIO_PIO4_BASE:
+-		cookie = 0x3000;
+-		break;
+-	default:
+-		assert(0);
+-	}
+-	packetindex = pio_txpacket_getindex(packet);
+-	assert(((u16)packetindex & 0xF000) == 0x0000);
+-	cookie |= (u16)packetindex;
+-
+-	return cookie;
+-}
+-
+-static
+-struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm,
+-				       u16 cookie,
+-				       struct bcm43xx_pio_txpacket **packet)
+-{
+-	struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
+-	struct bcm43xx_pioqueue *queue = NULL;
+-	int packetindex;
+-
+-	switch (cookie & 0xF000) {
+-	case 0x0000:
+-		queue = pio->queue0;
+-		break;
+-	case 0x1000:
+-		queue = pio->queue1;
+-		break;
+-	case 0x2000:
+-		queue = pio->queue2;
+-		break;
+-	case 0x3000:
+-		queue = pio->queue3;
+-		break;
+-	default:
+-		assert(0);
+-	}
+-	packetindex = (cookie & 0x0FFF);
+-	assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS);
+-	*packet = &(queue->tx_packets_cache[packetindex]);
+-
+-	return queue;
+-}
+-
+-static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
+-				  struct sk_buff *skb,
+-				  struct bcm43xx_pio_txpacket *packet)
+-{
+-	struct bcm43xx_txhdr txhdr;
+-	unsigned int octets;
+-
+-	assert(skb_shinfo(skb)->nr_frags == 0);
+-	bcm43xx_generate_txhdr(queue->bcm,
+-			       &txhdr, skb->data, skb->len,
+-			       (packet->xmitted_frags == 0),
+-			       generate_cookie(queue, packet));
+-
+-	tx_start(queue);
+-	octets = skb->len + sizeof(txhdr);
+-	if (queue->need_workarounds)
+-		octets--;
+-	tx_data(queue, &txhdr, (u8 *)skb->data, octets);
+-	tx_complete(queue, skb);
+-}
+-
+-static void free_txpacket(struct bcm43xx_pio_txpacket *packet,
+-			  int irq_context)
+-{
+-	struct bcm43xx_pioqueue *queue = packet->queue;
+-
+-	ieee80211_txb_free(packet->txb);
+-	list_move(&packet->list, &queue->txfree);
+-	queue->nr_txfree++;
+-
+-	assert(queue->tx_devq_used >= packet->xmitted_octets);
+-	assert(queue->tx_devq_packets >= packet->xmitted_frags);
+-	queue->tx_devq_used -= packet->xmitted_octets;
+-	queue->tx_devq_packets -= packet->xmitted_frags;
+-}
+-
+-static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
+-{
+-	struct bcm43xx_pioqueue *queue = packet->queue;
+-	struct ieee80211_txb *txb = packet->txb;
+-	struct sk_buff *skb;
+-	u16 octets;
+-	int i;
+-
+-	for (i = packet->xmitted_frags; i < txb->nr_frags; i++) {
+-		skb = txb->fragments[i];
+-
+-		octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
+-		assert(queue->tx_devq_size >= octets);
+-		assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS);
+-		assert(queue->tx_devq_used <= queue->tx_devq_size);
+-		/* Check if there is sufficient free space on the device
+-		 * TX queue. If not, return and let the TX tasklet
+-		 * retry later.
+-		 */
+-		if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS)
+-			return -EBUSY;
+-		if (queue->tx_devq_used + octets > queue->tx_devq_size)
+-			return -EBUSY;
+-		/* Now poke the device. */
+-		pio_tx_write_fragment(queue, skb, packet);
+-
+-		/* Account for the packet size.
+-		 * (We must not overflow the device TX queue)
+-		 */
+-		queue->tx_devq_packets++;
+-		queue->tx_devq_used += octets;
+-
+-		assert(packet->xmitted_frags < packet->txb->nr_frags);
+-		packet->xmitted_frags++;
+-		packet->xmitted_octets += octets;
+-	}
+-	list_move_tail(&packet->list, &queue->txrunning);
+-
+-	return 0;
+-}
+-
+-static void tx_tasklet(unsigned long d)
+-{
+-	struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d;
+-	struct bcm43xx_private *bcm = queue->bcm;
+-	unsigned long flags;
+-	struct bcm43xx_pio_txpacket *packet, *tmp_packet;
+-	int err;
+-	u16 txctl;
+-
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+-	if (queue->tx_frozen)
+-		goto out_unlock;
+-	txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
+-	if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
+-		goto out_unlock;
+-
+-	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
+-		assert(packet->xmitted_frags < packet->txb->nr_frags);
+-		if (packet->xmitted_frags == 0) {
+-			int i;
+-			struct sk_buff *skb;
+-
+-			/* Check if the device queue is big
+-			 * enough for every fragment. If not, drop the
+-			 * whole packet.
+-			 */
+-			for (i = 0; i < packet->txb->nr_frags; i++) {
+-				skb = packet->txb->fragments[i];
+-				if (unlikely(skb->len > queue->tx_devq_size)) {
+-					dprintkl(KERN_ERR PFX "PIO TX device queue too small. "
+-							      "Dropping packet.\n");
+-					free_txpacket(packet, 1);
+-					goto next_packet;
+-				}
+-			}
+-		}
+-		/* Try to transmit the packet.
+-		 * This may not completely succeed.
+-		 */
+-		err = pio_tx_packet(packet);
+-		if (err)
+-			break;
+-	next_packet:
+-		continue;
+-	}
+-out_unlock:
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-}
+-
+-static void setup_txqueues(struct bcm43xx_pioqueue *queue)
+-{
+-	struct bcm43xx_pio_txpacket *packet;
+-	int i;
+-
+-	queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS;
+-	for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) {
+-		packet = &(queue->tx_packets_cache[i]);
+-
+-		packet->queue = queue;
+-		INIT_LIST_HEAD(&packet->list);
+-
+-		list_add(&packet->list, &queue->txfree);
+-	}
+-}
+-
+-static
+-struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
+-						 u16 pio_mmio_base)
+-{
+-	struct bcm43xx_pioqueue *queue;
+-	u32 value;
+-	u16 qsize;
+-
+-	queue = kzalloc(sizeof(*queue), GFP_KERNEL);
+-	if (!queue)
+-		goto out;
+-
+-	queue->bcm = bcm;
+-	queue->mmio_base = pio_mmio_base;
+-	queue->need_workarounds = (bcm->current_core->rev < 3);
+-
+-	INIT_LIST_HEAD(&queue->txfree);
+-	INIT_LIST_HEAD(&queue->txqueue);
+-	INIT_LIST_HEAD(&queue->txrunning);
+-	tasklet_init(&queue->txtask, tx_tasklet,
+-		     (unsigned long)queue);
+-
+-	value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
+-
+-	qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
+-	if (qsize == 0) {
+-		printk(KERN_ERR PFX "ERROR: This card does not support PIO "
+-				    "operation mode. Please use DMA mode "
+-				    "(module parameter pio=0).\n");
+-		goto err_freequeue;
+-	}
+-	if (qsize <= BCM43xx_PIO_TXQADJUST) {
+-		printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n",
+-		       qsize);
+-		goto err_freequeue;
+-	}
+-	qsize -= BCM43xx_PIO_TXQADJUST;
+-	queue->tx_devq_size = qsize;
+-
+-	setup_txqueues(queue);
+-
+-out:
+-	return queue;
+-
+-err_freequeue:
+-	kfree(queue);
+-	queue = NULL;
+-	goto out;
+-}
+-
+-static void cancel_transfers(struct bcm43xx_pioqueue *queue)
+-{
+-	struct bcm43xx_pio_txpacket *packet, *tmp_packet;
+-
+-	netif_tx_disable(queue->bcm->net_dev);
+-	tasklet_disable(&queue->txtask);
+-
+-	list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
+-		free_txpacket(packet, 0);
+-	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
+-		free_txpacket(packet, 0);
+-}
+-
+-static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
+-{
+-	if (!queue)
+-		return;
+-
+-	cancel_transfers(queue);
+-	kfree(queue);
+-}
+-
+-void bcm43xx_pio_free(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_pio *pio;
+-
+-	if (!bcm43xx_using_pio(bcm))
+-		return;
+-	pio = bcm43xx_current_pio(bcm);
+-
+-	bcm43xx_destroy_pioqueue(pio->queue3);
+-	pio->queue3 = NULL;
+-	bcm43xx_destroy_pioqueue(pio->queue2);
+-	pio->queue2 = NULL;
+-	bcm43xx_destroy_pioqueue(pio->queue1);
+-	pio->queue1 = NULL;
+-	bcm43xx_destroy_pioqueue(pio->queue0);
+-	pio->queue0 = NULL;
+-}
+-
+-int bcm43xx_pio_init(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
+-	struct bcm43xx_pioqueue *queue;
+-	int err = -ENOMEM;
+-
+-	queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE);
+-	if (!queue)
+-		goto out;
+-	pio->queue0 = queue;
+-
+-	queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE);
+-	if (!queue)
+-		goto err_destroy0;
+-	pio->queue1 = queue;
+-
+-	queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE);
+-	if (!queue)
+-		goto err_destroy1;
+-	pio->queue2 = queue;
+-
+-	queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE);
+-	if (!queue)
+-		goto err_destroy2;
+-	pio->queue3 = queue;
+-
+-	if (bcm->current_core->rev < 3)
+-		bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
+-
+-	dprintk(KERN_INFO PFX "PIO initialized\n");
+-	err = 0;
+-out:
+-	return err;
+-
+-err_destroy2:
+-	bcm43xx_destroy_pioqueue(pio->queue2);
+-	pio->queue2 = NULL;
+-err_destroy1:
+-	bcm43xx_destroy_pioqueue(pio->queue1);
+-	pio->queue1 = NULL;
+-err_destroy0:
+-	bcm43xx_destroy_pioqueue(pio->queue0);
+-	pio->queue0 = NULL;
+-	goto out;
+-}
+-
+-int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+-		   struct ieee80211_txb *txb)
+-{
+-	struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
+-	struct bcm43xx_pio_txpacket *packet;
+-
+-	assert(!queue->tx_suspended);
+-	assert(!list_empty(&queue->txfree));
+-
+-	packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
+-	packet->txb = txb;
+-	packet->xmitted_frags = 0;
+-	packet->xmitted_octets = 0;
+-	list_move_tail(&packet->list, &queue->txqueue);
+-	queue->nr_txfree--;
+-	assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
+-
+-	/* Suspend TX, if we are out of packets in the "free" queue. */
+-	if (list_empty(&queue->txfree)) {
+-		netif_stop_queue(queue->bcm->net_dev);
+-		queue->tx_suspended = 1;
+-	}
+-
+-	tasklet_schedule(&queue->txtask);
+-
+-	return 0;
+-}
+-
+-void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+-				   struct bcm43xx_xmitstatus *status)
+-{
+-	struct bcm43xx_pioqueue *queue;
+-	struct bcm43xx_pio_txpacket *packet;
+-
+-	queue = parse_cookie(bcm, status->cookie, &packet);
+-	assert(queue);
+-
+-	free_txpacket(packet, 1);
+-	if (queue->tx_suspended) {
+-		queue->tx_suspended = 0;
+-		netif_wake_queue(queue->bcm->net_dev);
+-	}
+-	/* If there are packets on the txqueue, poke the tasklet
+-	 * to transmit them.
+-	 */
+-	if (!list_empty(&queue->txqueue))
+-		tasklet_schedule(&queue->txtask);
+-}
+-
+-static void pio_rx_error(struct bcm43xx_pioqueue *queue,
+-			 int clear_buffers,
+-			 const char *error)
+-{
+-	int i;
+-
+-	printkl("PIO RX error: %s\n", error);
+-	bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
+-			  BCM43xx_PIO_RXCTL_READY);
+-	if (clear_buffers) {
+-		assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE);
+-		for (i = 0; i < 15; i++) {
+-			/* Dummy read. */
+-			bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+-		}
+-	}
+-}
+-
+-void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
+-{
+-	__le16 preamble[21] = { 0 };
+-	struct bcm43xx_rxhdr *rxhdr;
+-	u16 tmp, len, rxflags2;
+-	int i, preamble_readwords;
+-	struct sk_buff *skb;
+-
+-	tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
+-	if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE))
+-		return;
+-	bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
+-			  BCM43xx_PIO_RXCTL_DATAAVAILABLE);
+-
+-	for (i = 0; i < 10; i++) {
+-		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
+-		if (tmp & BCM43xx_PIO_RXCTL_READY)
+-			goto data_ready;
+-		udelay(10);
+-	}
+-	dprintkl(KERN_ERR PFX "PIO RX timed out\n");
+-	return;
+-data_ready:
+-
+-	len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+-	if (unlikely(len > 0x700)) {
+-		pio_rx_error(queue, 0, "len > 0x700");
+-		return;
+-	}
+-	if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) {
+-		pio_rx_error(queue, 0, "len == 0");
+-		return;
+-	}
+-	preamble[0] = cpu_to_le16(len);
+-	if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE)
+-		preamble_readwords = 14 / sizeof(u16);
+-	else
+-		preamble_readwords = 18 / sizeof(u16);
+-	for (i = 0; i < preamble_readwords; i++) {
+-		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+-		preamble[i + 1] = cpu_to_le16(tmp);
+-	}
+-	rxhdr = (struct bcm43xx_rxhdr *)preamble;
+-	rxflags2 = le16_to_cpu(rxhdr->flags2);
+-	if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) {
+-		pio_rx_error(queue,
+-			     (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE),
+-			     "invalid frame");
+-		return;
+-	}
+-	if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) {
+-		/* We received an xmit status. */
+-		struct bcm43xx_hwxmitstatus *hw;
+-		struct bcm43xx_xmitstatus stat;
+-
+-		hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1);
+-		stat.cookie = le16_to_cpu(hw->cookie);
+-		stat.flags = hw->flags;
+-		stat.cnt1 = hw->cnt1;
+-		stat.cnt2 = hw->cnt2;
+-		stat.seq = le16_to_cpu(hw->seq);
+-		stat.unknown = le16_to_cpu(hw->unknown);
+-
+-		bcm43xx_debugfs_log_txstat(queue->bcm, &stat);
+-		bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat);
+-
+-		return;
+-	}
+-
+-	skb = dev_alloc_skb(len);
+-	if (unlikely(!skb)) {
+-		pio_rx_error(queue, 1, "OOM");
+-		return;
+-	}
+-	skb_put(skb, len);
+-	for (i = 0; i < len - 1; i += 2) {
+-		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+-		*((__le16 *)(skb->data + i)) = cpu_to_le16(tmp);
+-	}
+-	if (len % 2) {
+-		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+-		skb->data[len - 1] = (tmp & 0x00FF);
+-/* The specs say the following is required, but
+- * it is wrong and corrupts the PLCP. If we don't do
+- * this, the PLCP seems to be correct. So ifdef it out for now.
+- */
+-#if 0
+-		if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
+-			skb->data[2] = (tmp & 0xFF00) >> 8;
+-		else
+-			skb->data[0] = (tmp & 0xFF00) >> 8;
+-#endif
+-	}
+-	skb_trim(skb, len - IEEE80211_FCS_LEN);
+-	bcm43xx_rx(queue->bcm, skb, rxhdr);
+-}
+-
+-void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+-{
+-	bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1);
+-	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+-			  bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+-			  | BCM43xx_PIO_TXCTL_SUSPEND);
+-}
+-
+-void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+-{
+-	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+-			  bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+-			  & ~BCM43xx_PIO_TXCTL_SUSPEND);
+-	bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
+-	if (!list_empty(&queue->txqueue))
+-		tasklet_schedule(&queue->txtask);
+-}
+-
+-void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_pio *pio;
+-
+-	assert(bcm43xx_using_pio(bcm));
+-	pio = bcm43xx_current_pio(bcm);
+-	pio->queue0->tx_frozen = 1;
+-	pio->queue1->tx_frozen = 1;
+-	pio->queue2->tx_frozen = 1;
+-	pio->queue3->tx_frozen = 1;
+-}
+-
+-void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_pio *pio;
+-
+-	assert(bcm43xx_using_pio(bcm));
+-	pio = bcm43xx_current_pio(bcm);
+-	pio->queue0->tx_frozen = 0;
+-	pio->queue1->tx_frozen = 0;
+-	pio->queue2->tx_frozen = 0;
+-	pio->queue3->tx_frozen = 0;
+-	if (!list_empty(&pio->queue0->txqueue))
+-		tasklet_schedule(&pio->queue0->txtask);
+-	if (!list_empty(&pio->queue1->txqueue))
+-		tasklet_schedule(&pio->queue1->txtask);
+-	if (!list_empty(&pio->queue2->txqueue))
+-		tasklet_schedule(&pio->queue2->txtask);
+-	if (!list_empty(&pio->queue3->txqueue))
+-		tasklet_schedule(&pio->queue3->txtask);
+-}
+-
+-
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
+deleted file mode 100644
+index bc78a3c..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
++++ /dev/null
+@@ -1,163 +0,0 @@
+-#ifndef BCM43xx_PIO_H_
+-#define BCM43xx_PIO_H_
+-
+-#include "bcm43xx.h"
+-
+-#include <linux/interrupt.h>
+-#include <linux/list.h>
+-#include <linux/skbuff.h>
+-
+-
+-#define BCM43xx_PIO_TXCTL		0x00
+-#define BCM43xx_PIO_TXDATA		0x02
+-#define BCM43xx_PIO_TXQBUFSIZE		0x04
+-#define BCM43xx_PIO_RXCTL		0x08
+-#define BCM43xx_PIO_RXDATA		0x0A
+-
+-#define BCM43xx_PIO_TXCTL_WRITELO	(1 << 0)
+-#define BCM43xx_PIO_TXCTL_WRITEHI	(1 << 1)
+-#define BCM43xx_PIO_TXCTL_COMPLETE	(1 << 2)
+-#define BCM43xx_PIO_TXCTL_INIT		(1 << 3)
+-#define BCM43xx_PIO_TXCTL_SUSPEND	(1 << 7)
+-
+-#define BCM43xx_PIO_RXCTL_DATAAVAILABLE	(1 << 0)
+-#define BCM43xx_PIO_RXCTL_READY		(1 << 1)
+-
+-/* PIO constants */
+-#define BCM43xx_PIO_MAXTXDEVQPACKETS	31
+-#define BCM43xx_PIO_TXQADJUST		80
+-
+-/* PIO tuning knobs */
+-#define BCM43xx_PIO_MAXTXPACKETS	256
+-
+-
+-
+-#ifdef CONFIG_BCM43XX_PIO
+-
+-
+-struct bcm43xx_pioqueue;
+-struct bcm43xx_xmitstatus;
+-
+-struct bcm43xx_pio_txpacket {
+-	struct bcm43xx_pioqueue *queue;
+-	struct ieee80211_txb *txb;
+-	struct list_head list;
+-
+-	u8 xmitted_frags;
+-	u16 xmitted_octets;
+-};
+-
+-#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache)) 
+-
+-struct bcm43xx_pioqueue {
+-	struct bcm43xx_private *bcm;
+-	u16 mmio_base;
+-
+-	u8 tx_suspended:1,
+-	   tx_frozen:1,
+-	   need_workarounds:1; /* Workarounds needed for core.rev < 3 */
+-
+-	/* Adjusted size of the device internal TX buffer. */
+-	u16 tx_devq_size;
+-	/* Used octets of the device internal TX buffer. */
+-	u16 tx_devq_used;
+-	/* Used packet slots in the device internal TX buffer. */
+-	u8 tx_devq_packets;
+-	/* Packets from the txfree list can
+-	 * be taken on incoming TX requests.
+-	 */
+-	struct list_head txfree;
+-	unsigned int nr_txfree;
+-	/* Packets on the txqueue are queued,
+-	 * but not completely written to the chip, yet.
+-	 */
+-	struct list_head txqueue;
+-	/* Packets on the txrunning queue are completely
+-	 * posted to the device. We are waiting for the txstatus.
+-	 */
+-	struct list_head txrunning;
+-	/* Total number or packets sent.
+-	 * (This counter can obviously wrap).
+-	 */
+-	unsigned int nr_tx_packets;
+-	struct tasklet_struct txtask;
+-	struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS];
+-};
+-
+-static inline
+-u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue,
+-		     u16 offset)
+-{
+-	return bcm43xx_read16(queue->bcm, queue->mmio_base + offset);
+-}
+-
+-static inline
+-void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
+-		       u16 offset, u16 value)
+-{
+-	bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
+-	mmiowb();
+-}
+-
+-
+-int bcm43xx_pio_init(struct bcm43xx_private *bcm);
+-void bcm43xx_pio_free(struct bcm43xx_private *bcm);
+-
+-int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+-		   struct ieee80211_txb *txb);
+-void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+-				   struct bcm43xx_xmitstatus *status);
+-void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
+-
+-/* Suspend a TX queue on hardware level. */
+-void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
+-void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
+-/* Suspend (freeze) the TX tasklet (software level). */
+-void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm);
+-void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm);
+-
+-#else /* CONFIG_BCM43XX_PIO */
+-
+-static inline
+-int bcm43xx_pio_init(struct bcm43xx_private *bcm)
+-{
+-	return 0;
+-}
+-static inline
+-void bcm43xx_pio_free(struct bcm43xx_private *bcm)
+-{
+-}
+-static inline
+-int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+-		   struct ieee80211_txb *txb)
+-{
+-	return 0;
+-}
+-static inline
+-void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+-				   struct bcm43xx_xmitstatus *status)
+-{
+-}
+-static inline
+-void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
+-{
+-}
+-static inline
+-void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+-{
+-}
+-static inline
+-void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+-{
+-}
+-static inline
+-void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+-{
+-}
+-static inline
+-void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+-{
+-}
+-
+-#endif /* CONFIG_BCM43XX_PIO */
+-#endif /* BCM43xx_PIO_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
+deleted file mode 100644
+index 7e774f4..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c
++++ /dev/null
+@@ -1,393 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-  GNU General Public License for more details.
+-
+-  You should have received a copy of the GNU General Public License
+-  along with this program; see the file COPYING.  If not, write to
+-  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+-  Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/delay.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_power.h"
+-#include "bcm43xx_main.h"
+-
+-
+-/* Get the Slow Clock Source */
+-static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
+-{
+-	u32 tmp;
+-	int err;
+-
+-	assert(bcm->current_core == &bcm->core_chipcommon);
+-	if (bcm->current_core->rev < 6) {
+-		if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
+-		    bcm->bustype == BCM43xx_BUSTYPE_SB)
+-			return BCM43xx_PCTL_CLKSRC_XTALOS;
+-		if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
+-			err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
+-			assert(!err);
+-			if (tmp & 0x10)
+-				return BCM43xx_PCTL_CLKSRC_PCI;
+-			return BCM43xx_PCTL_CLKSRC_XTALOS;
+-		}
+-	}
+-	if (bcm->current_core->rev < 10) {
+-		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+-		tmp &= 0x7;
+-		if (tmp == 0)
+-			return BCM43xx_PCTL_CLKSRC_LOPWROS;
+-		if (tmp == 1)
+-			return BCM43xx_PCTL_CLKSRC_XTALOS;
+-		if (tmp == 2)
+-			return BCM43xx_PCTL_CLKSRC_PCI;
+-	}
+-
+-	return BCM43xx_PCTL_CLKSRC_XTALOS;
+-}
+-
+-/* Get max/min slowclock frequency
+- * as described in http://bcm-specs.sipsolutions.net/PowerControl
+- */
+-static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
+-				       int get_max)
+-{
+-	int limit;
+-	int clocksrc;
+-	int divisor;
+-	u32 tmp;
+-
+-	assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
+-	assert(bcm->current_core == &bcm->core_chipcommon);
+-
+-	clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
+-	if (bcm->current_core->rev < 6) {
+-		switch (clocksrc) {
+-		case BCM43xx_PCTL_CLKSRC_PCI:
+-			divisor = 64;
+-			break;
+-		case BCM43xx_PCTL_CLKSRC_XTALOS:
+-			divisor = 32;
+-			break;
+-		default:
+-			assert(0);
+-			divisor = 1;
+-		}
+-	} else if (bcm->current_core->rev < 10) {
+-		switch (clocksrc) {
+-		case BCM43xx_PCTL_CLKSRC_LOPWROS:
+-			divisor = 1;
+-			break;
+-		case BCM43xx_PCTL_CLKSRC_XTALOS:
+-		case BCM43xx_PCTL_CLKSRC_PCI:
+-			tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+-			divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+-			divisor *= 4;
+-			break;
+-		default:
+-			assert(0);
+-			divisor = 1;
+-		}
+-	} else {
+-		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
+-		divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+-		divisor *= 4;
+-	}
+-
+-	switch (clocksrc) {
+-	case BCM43xx_PCTL_CLKSRC_LOPWROS:
+-		if (get_max)
+-			limit = 43000;
+-		else
+-			limit = 25000;
+-		break;
+-	case BCM43xx_PCTL_CLKSRC_XTALOS:
+-		if (get_max)
+-			limit = 20200000;
+-		else
+-			limit = 19800000;
+-		break;
+-	case BCM43xx_PCTL_CLKSRC_PCI:
+-		if (get_max)
+-			limit = 34000000;
+-		else
+-			limit = 25000000;
+-		break;
+-	default:
+-		assert(0);
+-		limit = 0;
+-	}
+-	limit /= divisor;
+-
+-	return limit;
+-}
+-
+-
+-/* init power control
+- * as described in http://bcm-specs.sipsolutions.net/PowerControl
+- */
+-int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
+-{
+-	int err, maxfreq;
+-	struct bcm43xx_coreinfo *old_core;
+-
+-	old_core = bcm->current_core;
+-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+-	if (err == -ENODEV)
+-		return 0;
+-	if (err)
+-		goto out;
+-
+-	if (bcm->chip_id == 0x4321) {
+-		if (bcm->chip_rev == 0)
+-			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4);
+-		if (bcm->chip_rev == 1)
+-			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4);
+-	}
+-
+-	if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) {
+-		if (bcm->current_core->rev >= 10) {
+-			/* Set Idle Power clock rate to 1Mhz */
+-			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL,
+-				       (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL)
+-				       & 0x0000FFFF) | 0x40000);
+-		} else {
+-			maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+-			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
+-				       (maxfreq * 150 + 999999) / 1000000);
+-			bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
+-				       (maxfreq * 15 + 999999) / 1000000);
+-		}
+-	}
+-
+-	err = bcm43xx_switch_core(bcm, old_core);
+-	assert(err == 0);
+-
+-out:
+-	return err;
+-}
+-
+-u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm)
+-{
+-	u16 delay = 0;
+-	int err;
+-	u32 pll_on_delay;
+-	struct bcm43xx_coreinfo *old_core;
+-	int minfreq;
+-
+-	if (bcm->bustype != BCM43xx_BUSTYPE_PCI)
+-		goto out;
+-	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+-		goto out;
+-	old_core = bcm->current_core;
+-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+-	if (err == -ENODEV)
+-		goto out;
+-
+-	minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0);
+-	pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY);
+-	delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
+-
+-	err = bcm43xx_switch_core(bcm, old_core);
+-	assert(err == 0);
+-
+-out:
+-	return delay;
+-}
+-
+-/* set the powercontrol clock
+- * as described in http://bcm-specs.sipsolutions.net/PowerControl
+- */
+-int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode)
+-{
+-	int err;
+-	struct bcm43xx_coreinfo *old_core;
+-	u32 tmp;
+-
+-	old_core = bcm->current_core;
+-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+-	if (err == -ENODEV)
+-		return 0;
+-	if (err)
+-		goto out;
+-	
+-	if (bcm->core_chipcommon.rev < 6) {
+-		if (mode == BCM43xx_PCTL_CLK_FAST) {
+-			err = bcm43xx_pctl_set_crystal(bcm, 1);
+-			if (err)
+-				goto out;
+-		}
+-	} else {
+-		if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) &&
+-			(bcm->core_chipcommon.rev < 10)) {
+-			switch (mode) {
+-			case BCM43xx_PCTL_CLK_FAST:
+-				tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+-				tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL;
+-				bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+-				break;
+-			case BCM43xx_PCTL_CLK_SLOW:
+-				tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+-				tmp |= BCM43xx_PCTL_FORCE_SLOW;
+-				bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+-				break;
+-			case BCM43xx_PCTL_CLK_DYNAMIC:
+-				tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+-				tmp &= ~BCM43xx_PCTL_FORCE_SLOW;
+-				tmp |= BCM43xx_PCTL_FORCE_PLL;
+-				tmp &= ~BCM43xx_PCTL_DYN_XTAL;
+-				bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+-			}
+-		}
+-	}
+-	
+-	err = bcm43xx_switch_core(bcm, old_core);
+-	assert(err == 0);
+-
+-out:
+-	return err;
+-}
+-
+-int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on)
+-{
+-	int err;
+-	u32 in, out, outenable;
+-
+-	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in);
+-	if (err)
+-		goto err_pci;
+-	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out);
+-	if (err)
+-		goto err_pci;
+-	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable);
+-	if (err)
+-		goto err_pci;
+-
+-	outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
+-
+-	if (on) {
+-		if (in & 0x40)
+-			return 0;
+-
+-		out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
+-
+-		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+-		if (err)
+-			goto err_pci;
+-		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
+-		if (err)
+-			goto err_pci;
+-		udelay(1000);
+-
+-		out &= ~BCM43xx_PCTL_PLL_POWERDOWN;
+-		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+-		if (err)
+-			goto err_pci;
+-		udelay(5000);
+-	} else {
+-		if (bcm->current_core->rev < 5)
+-			return 0;
+-		if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW)
+-			return 0;
+-
+-/*		XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time?
+- *		err = bcm43xx_switch_core(bcm, bcm->active_80211_core);
+- *		if (err)
+- *			return err;
+- *		if (((bcm->current_core->rev >= 3) &&
+- *			(bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) ||
+- *		      ((bcm->current_core->rev < 3) &&
+- *			!(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4))))
+- *			return 0;
+- *		err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+- *		if (err)
+- *			return err;
+- */
+-		
+-		err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+-		if (err)
+-			goto out;
+-		out &= ~BCM43xx_PCTL_XTAL_POWERUP;
+-		out |= BCM43xx_PCTL_PLL_POWERDOWN;
+-		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+-		if (err)
+-			goto err_pci;
+-		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
+-		if (err)
+-			goto err_pci;
+-	}
+-
+-out:
+-	return err;
+-
+-err_pci:
+-	printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n");
+-	err = -EBUSY;
+-	goto out;
+-}
+-
+-/* Set the PowerSavingControlBits.
+- * Bitvalues:
+- *   0  => unset the bit
+- *   1  => set the bit
+- *   -1 => calculate the bit
+- */
+-void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
+-				   int bit25, int bit26)
+-{
+-	int i;
+-	u32 status;
+-
+-//FIXME: Force 25 to off and 26 to on for now:
+-bit25 = 0;
+-bit26 = 1;
+-
+-	if (bit25 == -1) {
+-		//TODO: If powersave is not off and FIXME is not set and we are not in adhoc
+-		//	and thus is not an AP and we are associated, set bit 25
+-	}
+-	if (bit26 == -1) {
+-		//TODO: If the device is awake or this is an AP, or we are scanning, or FIXME,
+-		//	or we are associated, or FIXME, or the latest PS-Poll packet sent was
+-		//	successful, set bit26
+-	}
+-	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	if (bit25)
+-		status |= BCM43xx_SBF_PS1;
+-	else
+-		status &= ~BCM43xx_SBF_PS1;
+-	if (bit26)
+-		status |= BCM43xx_SBF_PS2;
+-	else
+-		status &= ~BCM43xx_SBF_PS2;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+-	if (bit26 && bcm->current_core->rev >= 5) {
+-		for (i = 0; i < 100; i++) {
+-			if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4)
+-				break;
+-			udelay(10);
+-		}
+-	}
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
+deleted file mode 100644
+index c966ab3..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 BCM43xx_POWER_H_
+-#define BCM43xx_POWER_H_
+-
+-#include <linux/types.h>
+-
+-/* Clock sources */
+-enum {
+-	/* PCI clock */
+-	BCM43xx_PCTL_CLKSRC_PCI,
+-	/* Crystal slow clock oscillator */
+-	BCM43xx_PCTL_CLKSRC_XTALOS,
+-	/* Low power oscillator */
+-	BCM43xx_PCTL_CLKSRC_LOPWROS,
+-};
+-
+-struct bcm43xx_private;
+-
+-int bcm43xx_pctl_init(struct bcm43xx_private *bcm);
+-int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode);
+-int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on);
+-u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
+-				   int bit25, int bit26);
+-
+-#endif /* BCM43xx_POWER_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
+deleted file mode 100644
+index c605099..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
++++ /dev/null
+@@ -1,2170 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-  GNU General Public License for more details.
+-
+-  You should have received a copy of the GNU General Public License
+-  along with this program; see the file COPYING.  If not, write to
+-  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+-  Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/delay.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_phy.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx_ilt.h"
+-
+-
+-/* Table for bcm43xx_radio_calibrationvalue() */
+-static const u16 rcc_table[16] = {
+-	0x0002, 0x0003, 0x0001, 0x000F,
+-	0x0006, 0x0007, 0x0005, 0x000F,
+-	0x000A, 0x000B, 0x0009, 0x000F,
+-	0x000E, 0x000F, 0x000D, 0x000F,
+-};
+-
+-/* Reverse the bits of a 4bit value.
+- * Example:  1101 is flipped 1011
+- */
+-static u16 flip_4bit(u16 value)
+-{
+-	u16 flipped = 0x0000;
+-
+-	assert((value & ~0x000F) == 0x0000);
+-
+-	flipped |= (value & 0x0001) << 3;
+-	flipped |= (value & 0x0002) << 1;
+-	flipped |= (value & 0x0004) >> 1;
+-	flipped |= (value & 0x0008) >> 3;
+-
+-	return flipped;
+-}
+-
+-/* Get the freq, as it has to be written to the device. */
+-static inline
+-u16 channel2freq_bg(u8 channel)
+-{
+-	/* Frequencies are given as frequencies_bg[index] + 2.4GHz
+-	 * Starting with channel 1
+-	 */
+-	static const u16 frequencies_bg[14] = {
+-		12, 17, 22, 27,
+-		32, 37, 42, 47,
+-		52, 57, 62, 67,
+-		72, 84,
+-	};
+-
+-	assert(channel >= 1 && channel <= 14);
+-
+-	return frequencies_bg[channel - 1];
+-}
+-
+-/* Get the freq, as it has to be written to the device. */
+-static inline
+-u16 channel2freq_a(u8 channel)
+-{
+-	assert(channel <= 200);
+-
+-	return (5000 + 5 * channel);
+-}
+-
+-void bcm43xx_radio_lock(struct bcm43xx_private *bcm)
+-{
+-	u32 status;
+-
+-	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	status |= BCM43xx_SBF_RADIOREG_LOCK;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+-	mmiowb();
+-	udelay(10);
+-}
+-
+-void bcm43xx_radio_unlock(struct bcm43xx_private *bcm)
+-{
+-	u32 status;
+-
+-	bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */
+-	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+-	status &= ~BCM43xx_SBF_RADIOREG_LOCK;
+-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+-	mmiowb();
+-}
+-
+-u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_A:
+-		offset |= 0x0040;
+-		break;
+-	case BCM43xx_PHYTYPE_B:
+-		if (radio->version == 0x2053) {
+-			if (offset < 0x70)
+-				offset += 0x80;
+-			else if (offset < 0x80)
+-				offset += 0x70;
+-		} else if (radio->version == 0x2050) {
+-			offset |= 0x80;
+-		} else
+-			assert(0);
+-		break;
+-	case BCM43xx_PHYTYPE_G:
+-		offset |= 0x80;
+-		break;
+-	}
+-
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
+-	return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
+-}
+-
+-void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val)
+-{
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
+-	mmiowb();
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val);
+-}
+-
+-static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm,
+-				  s16 first, s16 second, s16 third)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 i;
+-	u16 start = 0x08, end = 0x18;
+-	u16 offset = 0x0400;
+-	u16 tmp;
+-
+-	if (phy->rev <= 1) {
+-		offset = 0x5000;
+-		start = 0x10;
+-		end = 0x20;
+-	}
+-
+-	for (i = 0; i < 4; i++)
+-		bcm43xx_ilt_write(bcm, offset + i, first);
+-
+-	for (i = start; i < end; i++)
+-		bcm43xx_ilt_write(bcm, offset + i, second);
+-
+-	if (third != -1) {
+-		tmp = ((u16)third << 14) | ((u16)third << 6);
+-		bcm43xx_phy_write(bcm, 0x04A0,
+-		                  (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp);
+-		bcm43xx_phy_write(bcm, 0x04A1,
+-		                  (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp);
+-		bcm43xx_phy_write(bcm, 0x04A2,
+-		                  (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp);
+-	}
+-	bcm43xx_dummy_transmission(bcm);
+-}
+-
+-static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 i, tmp;
+-	u16 offset = 0x0400;
+-	u16 start = 0x0008, end = 0x0018;
+-
+-	if (phy->rev <= 1) {
+-		offset = 0x5000;
+-		start = 0x0010;
+-		end = 0x0020;
+-	}
+-
+-	for (i = 0; i < 4; i++) {
+-		tmp = (i & 0xFFFC);
+-		tmp |= (i & 0x0001) << 1;
+-		tmp |= (i & 0x0002) >> 1;
+-
+-		bcm43xx_ilt_write(bcm, offset + i, tmp);
+-	}
+-
+-	for (i = start; i < end; i++)
+-		bcm43xx_ilt_write(bcm, offset + i, i - start);
+-
+-	bcm43xx_phy_write(bcm, 0x04A0,
+-	                  (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040);
+-	bcm43xx_phy_write(bcm, 0x04A1,
+-	                  (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040);
+-	bcm43xx_phy_write(bcm, 0x04A2,
+-	                  (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000);
+-	bcm43xx_dummy_transmission(bcm);
+-}
+-
+-/* Synthetic PU workaround */
+-static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	
+-	if (radio->version != 0x2050 || radio->revision >= 6) {
+-		/* We do not need the workaround. */
+-		return;
+-	}
+-
+-	if (channel <= 10) {
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+-				channel2freq_bg(channel + 4));
+-	} else {
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+-				channel2freq_bg(1));
+-	}
+-	udelay(100);
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+-			channel2freq_bg(channel));
+-}
+-
+-u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u8 ret = 0;
+-	u16 saved, rssi, temp;
+-	int i, j = 0;
+-
+-	saved = bcm43xx_phy_read(bcm, 0x0403);
+-	bcm43xx_radio_selectchannel(bcm, channel, 0);
+-	bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5);
+-	if (radio->aci_hw_rssi)
+-		rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F;
+-	else
+-		rssi = saved & 0x3F;
+-	/* clamp temp to signed 5bit */
+-	if (rssi > 32)
+-		rssi -= 64;
+-	for (i = 0;i < 100; i++) {
+-		temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F;
+-		if (temp > 32)
+-			temp -= 64;
+-		if (temp < rssi)
+-			j++;
+-		if (j >= 20)
+-			ret = 1;
+-	}
+-	bcm43xx_phy_write(bcm, 0x0403, saved);
+-
+-	return ret;
+-}
+-
+-u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u8 ret[13];
+-	unsigned int channel = radio->channel;
+-	unsigned int i, j, start, end;
+-	unsigned long phylock_flags;
+-
+-	if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0)))
+-		return 0;
+-
+-	bcm43xx_phy_lock(bcm, phylock_flags);
+-	bcm43xx_radio_lock(bcm);
+-	bcm43xx_phy_write(bcm, 0x0802,
+-	                  bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
+-	bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-	                  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
+-	bcm43xx_set_all_gains(bcm, 3, 8, 1);
+-
+-	start = (channel - 5 > 0) ? channel - 5 : 1;
+-	end = (channel + 5 < 14) ? channel + 5 : 13;
+-
+-	for (i = start; i <= end; i++) {
+-		if (abs(channel - i) > 2)
+-			ret[i-1] = bcm43xx_radio_aci_detect(bcm, i);
+-	}
+-	bcm43xx_radio_selectchannel(bcm, channel, 0);
+-	bcm43xx_phy_write(bcm, 0x0802,
+-	                  (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003);
+-	bcm43xx_phy_write(bcm, 0x0403,
+-	                  bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8);
+-	bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-	                  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
+-	bcm43xx_set_original_gains(bcm);
+-	for (i = 0; i < 13; i++) {
+-		if (!ret[i])
+-			continue;
+-		end = (i + 5 < 13) ? i + 5 : 13;
+-		for (j = i; j < end; j++)
+-			ret[j] = 1;
+-	}
+-	bcm43xx_radio_unlock(bcm);
+-	bcm43xx_phy_unlock(bcm, phylock_flags);
+-
+-	return ret[channel - 1];
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+-void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val)
+-{
+-	bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
+-	mmiowb();
+-	bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val);
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+-s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset)
+-{
+-	u16 val;
+-
+-	bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
+-	val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA);
+-
+-	return (s16)val;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+-void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val)
+-{
+-	u16 i;
+-	s16 tmp;
+-
+-	for (i = 0; i < 64; i++) {
+-		tmp = bcm43xx_nrssi_hw_read(bcm, i);
+-		tmp -= val;
+-		tmp = limit_value(tmp, -32, 31);
+-		bcm43xx_nrssi_hw_write(bcm, i, tmp);
+-	}
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+-void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	s16 i, delta;
+-	s32 tmp;
+-
+-	delta = 0x1F - radio->nrssi[0];
+-	for (i = 0; i < 64; i++) {
+-		tmp = (i - delta) * radio->nrssislope;
+-		tmp /= 0x10000;
+-		tmp += 0x3A;
+-		tmp = limit_value(tmp, 0, 0x3F);
+-		radio->nrssi_lt[i] = tmp;
+-	}
+-}
+-
+-static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	u16 backup[20] = { 0 };
+-	s16 v47F;
+-	u16 i;
+-	u16 saved = 0xFFFF;
+-
+-	backup[0] = bcm43xx_phy_read(bcm, 0x0001);
+-	backup[1] = bcm43xx_phy_read(bcm, 0x0811);
+-	backup[2] = bcm43xx_phy_read(bcm, 0x0812);
+-	backup[3] = bcm43xx_phy_read(bcm, 0x0814);
+-	backup[4] = bcm43xx_phy_read(bcm, 0x0815);
+-	backup[5] = bcm43xx_phy_read(bcm, 0x005A);
+-	backup[6] = bcm43xx_phy_read(bcm, 0x0059);
+-	backup[7] = bcm43xx_phy_read(bcm, 0x0058);
+-	backup[8] = bcm43xx_phy_read(bcm, 0x000A);
+-	backup[9] = bcm43xx_phy_read(bcm, 0x0003);
+-	backup[10] = bcm43xx_radio_read16(bcm, 0x007A);
+-	backup[11] = bcm43xx_radio_read16(bcm, 0x0043);
+-
+-	bcm43xx_phy_write(bcm, 0x0429,
+-			  bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF);
+-	bcm43xx_phy_write(bcm, 0x0001,
+-			  (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000);
+-	bcm43xx_phy_write(bcm, 0x0811,
+-			  bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+-	bcm43xx_phy_write(bcm, 0x0812,
+-			  (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004);
+-	bcm43xx_phy_write(bcm, 0x0802,
+-			  bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2));
+-	if (phy->rev >= 6) {
+-		backup[12] = bcm43xx_phy_read(bcm, 0x002E);
+-		backup[13] = bcm43xx_phy_read(bcm, 0x002F);
+-		backup[14] = bcm43xx_phy_read(bcm, 0x080F);
+-		backup[15] = bcm43xx_phy_read(bcm, 0x0810);
+-		backup[16] = bcm43xx_phy_read(bcm, 0x0801);
+-		backup[17] = bcm43xx_phy_read(bcm, 0x0060);
+-		backup[18] = bcm43xx_phy_read(bcm, 0x0014);
+-		backup[19] = bcm43xx_phy_read(bcm, 0x0478);
+-
+-		bcm43xx_phy_write(bcm, 0x002E, 0);
+-		bcm43xx_phy_write(bcm, 0x002F, 0);
+-		bcm43xx_phy_write(bcm, 0x080F, 0);
+-		bcm43xx_phy_write(bcm, 0x0810, 0);
+-		bcm43xx_phy_write(bcm, 0x0478,
+-				  bcm43xx_phy_read(bcm, 0x0478) | 0x0100);
+-		bcm43xx_phy_write(bcm, 0x0801,
+-				  bcm43xx_phy_read(bcm, 0x0801) | 0x0040);
+-		bcm43xx_phy_write(bcm, 0x0060,
+-				  bcm43xx_phy_read(bcm, 0x0060) | 0x0040);
+-		bcm43xx_phy_write(bcm, 0x0014,
+-				  bcm43xx_phy_read(bcm, 0x0014) | 0x0200);
+-	}
+-	bcm43xx_radio_write16(bcm, 0x007A,
+-			      bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
+-	bcm43xx_radio_write16(bcm, 0x007A,
+-			      bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+-	udelay(30);
+-
+-	v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+-	if (v47F >= 0x20)
+-		v47F -= 0x40;
+-	if (v47F == 31) {
+-		for (i = 7; i >= 4; i--) {
+-			bcm43xx_radio_write16(bcm, 0x007B, i);
+-			udelay(20);
+-			v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+-			if (v47F >= 0x20)
+-				v47F -= 0x40;
+-			if (v47F < 31 && saved == 0xFFFF)
+-				saved = i;
+-		}
+-		if (saved == 0xFFFF)
+-			saved = 4;
+-	} else {
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+-		bcm43xx_phy_write(bcm, 0x0814,
+-				  bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
+-		bcm43xx_phy_write(bcm, 0x0815,
+-				  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
+-		bcm43xx_phy_write(bcm, 0x0811,
+-				  bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+-		bcm43xx_phy_write(bcm, 0x0812,
+-				  bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
+-		bcm43xx_phy_write(bcm, 0x0811,
+-				  bcm43xx_phy_read(bcm, 0x0811) | 0x0030);
+-		bcm43xx_phy_write(bcm, 0x0812,
+-				  bcm43xx_phy_read(bcm, 0x0812) | 0x0030);
+-		bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+-		bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+-		bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+-		if (phy->analog == 0) {
+-			bcm43xx_phy_write(bcm, 0x0003, 0x0122);
+-		} else {
+-			bcm43xx_phy_write(bcm, 0x000A,
+-					  bcm43xx_phy_read(bcm, 0x000A)
+-					  | 0x2000);
+-		}
+-		bcm43xx_phy_write(bcm, 0x0814,
+-				  bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
+-		bcm43xx_phy_write(bcm, 0x0815,
+-				  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+-		bcm43xx_phy_write(bcm, 0x0003,
+-				  (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F)
+-				  | 0x0040);
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
+-		bcm43xx_set_all_gains(bcm, 3, 0, 1);
+-		bcm43xx_radio_write16(bcm, 0x0043,
+-				      (bcm43xx_radio_read16(bcm, 0x0043)
+-				       & 0x00F0) | 0x000F);
+-		udelay(30);
+-		v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+-		if (v47F >= 0x20)
+-			v47F -= 0x40;
+-		if (v47F == -32) {
+-			for (i = 0; i < 4; i++) {
+-				bcm43xx_radio_write16(bcm, 0x007B, i);
+-				udelay(20);
+-				v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+-				if (v47F >= 0x20)
+-					v47F -= 0x40;
+-				if (v47F > -31 && saved == 0xFFFF)
+-					saved = i;
+-			}
+-			if (saved == 0xFFFF)
+-				saved = 3;
+-		} else
+-			saved = 0;
+-	}
+-	bcm43xx_radio_write16(bcm, 0x007B, saved);
+-
+-	if (phy->rev >= 6) {
+-		bcm43xx_phy_write(bcm, 0x002E, backup[12]);
+-		bcm43xx_phy_write(bcm, 0x002F, backup[13]);
+-		bcm43xx_phy_write(bcm, 0x080F, backup[14]);
+-		bcm43xx_phy_write(bcm, 0x0810, backup[15]);
+-	}
+-	bcm43xx_phy_write(bcm, 0x0814, backup[3]);
+-	bcm43xx_phy_write(bcm, 0x0815, backup[4]);
+-	bcm43xx_phy_write(bcm, 0x005A, backup[5]);
+-	bcm43xx_phy_write(bcm, 0x0059, backup[6]);
+-	bcm43xx_phy_write(bcm, 0x0058, backup[7]);
+-	bcm43xx_phy_write(bcm, 0x000A, backup[8]);
+-	bcm43xx_phy_write(bcm, 0x0003, backup[9]);
+-	bcm43xx_radio_write16(bcm, 0x0043, backup[11]);
+-	bcm43xx_radio_write16(bcm, 0x007A, backup[10]);
+-	bcm43xx_phy_write(bcm, 0x0802,
+-			  bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2);
+-	bcm43xx_phy_write(bcm, 0x0429,
+-			  bcm43xx_phy_read(bcm, 0x0429) | 0x8000);
+-	bcm43xx_set_original_gains(bcm);
+-	if (phy->rev >= 6) {
+-		bcm43xx_phy_write(bcm, 0x0801, backup[16]);
+-		bcm43xx_phy_write(bcm, 0x0060, backup[17]);
+-		bcm43xx_phy_write(bcm, 0x0014, backup[18]);
+-		bcm43xx_phy_write(bcm, 0x0478, backup[19]);
+-	}
+-	bcm43xx_phy_write(bcm, 0x0001, backup[0]);
+-	bcm43xx_phy_write(bcm, 0x0812, backup[2]);
+-	bcm43xx_phy_write(bcm, 0x0811, backup[1]);
+-}
+-
+-void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 backup[18] = { 0 };
+-	u16 tmp;
+-	s16 nrssi0, nrssi1;
+-
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_B:
+-		backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
+-		backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
+-		backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
+-		backup[3] = bcm43xx_phy_read(bcm, 0x0030);
+-		backup[4] = bcm43xx_phy_read(bcm, 0x0026);
+-		backup[5] = bcm43xx_phy_read(bcm, 0x0015);
+-		backup[6] = bcm43xx_phy_read(bcm, 0x002A);
+-		backup[7] = bcm43xx_phy_read(bcm, 0x0020);
+-		backup[8] = bcm43xx_phy_read(bcm, 0x005A);
+-		backup[9] = bcm43xx_phy_read(bcm, 0x0059);
+-		backup[10] = bcm43xx_phy_read(bcm, 0x0058);
+-		backup[11] = bcm43xx_read16(bcm, 0x03E2);
+-		backup[12] = bcm43xx_read16(bcm, 0x03E6);
+-		backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+-
+-		tmp  = bcm43xx_radio_read16(bcm, 0x007A);
+-		tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
+-		bcm43xx_radio_write16(bcm, 0x007A, tmp);
+-		bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+-		bcm43xx_write16(bcm, 0x03EC, 0x7F7F);
+-		bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+-		bcm43xx_phy_write(bcm, 0x0015,
+-				  bcm43xx_phy_read(bcm, 0x0015) | 0x0020);
+-		bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+-
+-		nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027);
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+-		if (phy->analog >= 2) {
+-			bcm43xx_write16(bcm, 0x03E6, 0x0040);
+-		} else if (phy->analog == 0) {
+-			bcm43xx_write16(bcm, 0x03E6, 0x0122);
+-		} else {
+-			bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+-					bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000);
+-		}
+-		bcm43xx_phy_write(bcm, 0x0020, 0x3F3F);
+-		bcm43xx_phy_write(bcm, 0x0015, 0xF330);
+-		bcm43xx_radio_write16(bcm, 0x005A, 0x0060);
+-		bcm43xx_radio_write16(bcm, 0x0043,
+-				      bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0);
+-		bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+-		bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+-		bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+-		udelay(20);
+-
+-		nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027);
+-		bcm43xx_phy_write(bcm, 0x0030, backup[3]);
+-		bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
+-		bcm43xx_write16(bcm, 0x03E2, backup[11]);
+-		bcm43xx_phy_write(bcm, 0x0026, backup[4]);
+-		bcm43xx_phy_write(bcm, 0x0015, backup[5]);
+-		bcm43xx_phy_write(bcm, 0x002A, backup[6]);
+-		bcm43xx_synth_pu_workaround(bcm, radio->channel);
+-		if (phy->analog != 0)
+-			bcm43xx_write16(bcm, 0x03F4, backup[13]);
+-
+-		bcm43xx_phy_write(bcm, 0x0020, backup[7]);
+-		bcm43xx_phy_write(bcm, 0x005A, backup[8]);
+-		bcm43xx_phy_write(bcm, 0x0059, backup[9]);
+-		bcm43xx_phy_write(bcm, 0x0058, backup[10]);
+-		bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
+-		bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
+-
+-		if (nrssi0 == nrssi1)
+-			radio->nrssislope = 0x00010000;
+-		else 
+-			radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+-
+-		if (nrssi0 <= -4) {
+-			radio->nrssi[0] = nrssi0;
+-			radio->nrssi[1] = nrssi1;
+-		}
+-		break;
+-	case BCM43xx_PHYTYPE_G:
+-		if (radio->revision >= 9)
+-			return;
+-		if (radio->revision == 8)
+-			bcm43xx_calc_nrssi_offset(bcm);
+-
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-				  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
+-		bcm43xx_phy_write(bcm, 0x0802,
+-				  bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
+-		backup[7] = bcm43xx_read16(bcm, 0x03E2);
+-		bcm43xx_write16(bcm, 0x03E2,
+-				bcm43xx_read16(bcm, 0x03E2) | 0x8000);
+-		backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
+-		backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
+-		backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
+-		backup[3] = bcm43xx_phy_read(bcm, 0x0015);
+-		backup[4] = bcm43xx_phy_read(bcm, 0x005A);
+-		backup[5] = bcm43xx_phy_read(bcm, 0x0059);
+-		backup[6] = bcm43xx_phy_read(bcm, 0x0058);
+-		backup[8] = bcm43xx_read16(bcm, 0x03E6);
+-		backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+-		if (phy->rev >= 3) {
+-			backup[10] = bcm43xx_phy_read(bcm, 0x002E);
+-			backup[11] = bcm43xx_phy_read(bcm, 0x002F);
+-			backup[12] = bcm43xx_phy_read(bcm, 0x080F);
+-			backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL);
+-			backup[14] = bcm43xx_phy_read(bcm, 0x0801);
+-			backup[15] = bcm43xx_phy_read(bcm, 0x0060);
+-			backup[16] = bcm43xx_phy_read(bcm, 0x0014);
+-			backup[17] = bcm43xx_phy_read(bcm, 0x0478);
+-			bcm43xx_phy_write(bcm, 0x002E, 0);
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0);
+-			switch (phy->rev) {
+-			case 4: case 6: case 7:
+-				bcm43xx_phy_write(bcm, 0x0478,
+-						  bcm43xx_phy_read(bcm, 0x0478)
+-						  | 0x0100);
+-				bcm43xx_phy_write(bcm, 0x0801,
+-						  bcm43xx_phy_read(bcm, 0x0801)
+-						  | 0x0040);
+-				break;
+-			case 3: case 5:
+-				bcm43xx_phy_write(bcm, 0x0801,
+-						  bcm43xx_phy_read(bcm, 0x0801)
+-						  & 0xFFBF);
+-				break;
+-			}
+-			bcm43xx_phy_write(bcm, 0x0060,
+-					  bcm43xx_phy_read(bcm, 0x0060)
+-					  | 0x0040);
+-			bcm43xx_phy_write(bcm, 0x0014,
+-					  bcm43xx_phy_read(bcm, 0x0014)
+-					  | 0x0200);
+-		}
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
+-		bcm43xx_set_all_gains(bcm, 0, 8, 0);
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7);
+-		if (phy->rev >= 2) {
+-			bcm43xx_phy_write(bcm, 0x0811,
+-					  (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030);
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010);
+-		}
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+-		udelay(20);
+-
+-		nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+-		if (nrssi0 >= 0x0020)
+-			nrssi0 -= 0x0040;
+-
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+-		if (phy->analog >= 2) {
+-			bcm43xx_phy_write(bcm, 0x0003,
+-					  (bcm43xx_phy_read(bcm, 0x0003)
+-					   & 0xFF9F) | 0x0040);
+-		}
+-
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+-				bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+-				| 0x2000);
+-		bcm43xx_radio_write16(bcm, 0x007A,
+-				      bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
+-		bcm43xx_phy_write(bcm, 0x0015, 0xF330);
+-		if (phy->rev >= 2) {
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020);
+-			bcm43xx_phy_write(bcm, 0x0811,
+-					  (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020);
+-		}
+-
+-		bcm43xx_set_all_gains(bcm, 3, 0, 1);
+-		if (radio->revision == 8) {
+-			bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
+-		} else {
+-			tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F;
+-			bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060);
+-			tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0;
+-			bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009);
+-		}
+-		bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+-		bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+-		bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+-		udelay(20);
+-		nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+-		if (nrssi1 >= 0x0020)
+-			nrssi1 -= 0x0040;
+-		if (nrssi0 == nrssi1)
+-			radio->nrssislope = 0x00010000;
+-		else
+-			radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+-		if (nrssi0 >= -4) {
+-			radio->nrssi[0] = nrssi1;
+-			radio->nrssi[1] = nrssi0;
+-		}
+-		if (phy->rev >= 3) {
+-			bcm43xx_phy_write(bcm, 0x002E, backup[10]);
+-			bcm43xx_phy_write(bcm, 0x002F, backup[11]);
+-			bcm43xx_phy_write(bcm, 0x080F, backup[12]);
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]);
+-		}
+-		if (phy->rev >= 2) {
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF);
+-			bcm43xx_phy_write(bcm, 0x0811,
+-					  bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF);
+-		}
+-
+-		bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
+-		bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
+-		bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
+-		bcm43xx_write16(bcm, 0x03E2, backup[7]);
+-		bcm43xx_write16(bcm, 0x03E6, backup[8]);
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]);
+-		bcm43xx_phy_write(bcm, 0x0015, backup[3]);
+-		bcm43xx_phy_write(bcm, 0x005A, backup[4]);
+-		bcm43xx_phy_write(bcm, 0x0059, backup[5]);
+-		bcm43xx_phy_write(bcm, 0x0058, backup[6]);
+-		bcm43xx_synth_pu_workaround(bcm, radio->channel);
+-		bcm43xx_phy_write(bcm, 0x0802,
+-				  bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002));
+-		bcm43xx_set_original_gains(bcm);
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-				  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
+-		if (phy->rev >= 3) {
+-			bcm43xx_phy_write(bcm, 0x0801, backup[14]);
+-			bcm43xx_phy_write(bcm, 0x0060, backup[15]);
+-			bcm43xx_phy_write(bcm, 0x0014, backup[16]);
+-			bcm43xx_phy_write(bcm, 0x0478, backup[17]);
+-		}
+-		bcm43xx_nrssi_mem_update(bcm);
+-		bcm43xx_calc_nrssi_threshold(bcm);
+-		break;
+-	default:
+-		assert(0);
+-	}
+-}
+-
+-void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	s32 threshold;
+-	s32 a, b;
+-	s16 tmp16;
+-	u16 tmp_u16;
+-
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_B: {
+-		if (radio->version != 0x2050)
+-			return;
+-		if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI))
+-			return;
+-
+-		if (radio->revision >= 6) {
+-			threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32;
+-			threshold += 20 * (radio->nrssi[0] + 1);
+-			threshold /= 40;
+-		} else
+-			threshold = radio->nrssi[1] - 5;
+-
+-		threshold = limit_value(threshold, 0, 0x3E);
+-		bcm43xx_phy_read(bcm, 0x0020); /* dummy read */
+-		bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C);
+-
+-		if (radio->revision >= 6) {
+-			bcm43xx_phy_write(bcm, 0x0087, 0x0E0D);
+-			bcm43xx_phy_write(bcm, 0x0086, 0x0C0B);
+-			bcm43xx_phy_write(bcm, 0x0085, 0x0A09);
+-			bcm43xx_phy_write(bcm, 0x0084, 0x0808);
+-			bcm43xx_phy_write(bcm, 0x0083, 0x0808);
+-			bcm43xx_phy_write(bcm, 0x0082, 0x0604);
+-			bcm43xx_phy_write(bcm, 0x0081, 0x0302);
+-			bcm43xx_phy_write(bcm, 0x0080, 0x0100);
+-		}
+-		break;
+-	}
+-	case BCM43xx_PHYTYPE_G:
+-		if (!phy->connected ||
+-		    !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+-			tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20);
+-			if (tmp16 >= 0x20)
+-				tmp16 -= 0x40;
+-			if (tmp16 < 3) {
+-				bcm43xx_phy_write(bcm, 0x048A,
+-						  (bcm43xx_phy_read(bcm, 0x048A)
+-						   & 0xF000) | 0x09EB);
+-			} else {
+-				bcm43xx_phy_write(bcm, 0x048A,
+-						  (bcm43xx_phy_read(bcm, 0x048A)
+-						   & 0xF000) | 0x0AED);
+-			}
+-		} else {
+-			if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
+-				a = 0xE;
+-				b = 0xA;
+-			} else if (!radio->aci_wlan_automatic && radio->aci_enable) {
+-				a = 0x13;
+-				b = 0x12;
+-			} else {
+-				a = 0xE;
+-				b = 0x11;
+-			}
+-
+-			a = a * (radio->nrssi[1] - radio->nrssi[0]);
+-			a += (radio->nrssi[0] << 6);
+-			if (a < 32)
+-				a += 31;
+-			else
+-				a += 32;
+-			a = a >> 6;
+-			a = limit_value(a, -31, 31);
+-
+-			b = b * (radio->nrssi[1] - radio->nrssi[0]);
+-			b += (radio->nrssi[0] << 6);
+-			if (b < 32)
+-				b += 31;
+-			else
+-				b += 32;
+-			b = b >> 6;
+-			b = limit_value(b, -31, 31);
+-
+-			tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000;
+-			tmp_u16 |= ((u32)b & 0x0000003F);
+-			tmp_u16 |= (((u32)a & 0x0000003F) << 6);
+-			bcm43xx_phy_write(bcm, 0x048A, tmp_u16);
+-		}
+-		break;
+-	default:
+-		assert(0);
+-	}
+-}
+-
+-/* Stack implementation to save/restore values from the
+- * interference mitigation code.
+- * It is save to restore values in random order.
+- */
+-static void _stack_save(u32 *_stackptr, size_t *stackidx,
+-			u8 id, u16 offset, u16 value)
+-{
+-	u32 *stackptr = &(_stackptr[*stackidx]);
+-
+-	assert((offset & 0xE000) == 0x0000);
+-	assert((id & 0xF8) == 0x00);
+-	*stackptr = offset;
+-	*stackptr |= ((u32)id) << 13;
+-	*stackptr |= ((u32)value) << 16;
+-	(*stackidx)++;
+-	assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
+-}
+-
+-static u16 _stack_restore(u32 *stackptr,
+-			  u8 id, u16 offset)
+-{
+-	size_t i;
+-
+-	assert((offset & 0xE000) == 0x0000);
+-	assert((id & 0xF8) == 0x00);
+-	for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
+-		if ((*stackptr & 0x00001FFF) != offset)
+-			continue;
+-		if (((*stackptr & 0x00007000) >> 13) != id)
+-			continue;
+-		return ((*stackptr & 0xFFFF0000) >> 16);
+-	}
+-	assert(0);
+-
+-	return 0;
+-}
+-
+-#define phy_stacksave(offset)					\
+-	do {							\
+-		_stack_save(stack, &stackidx, 0x1, (offset),	\
+-			    bcm43xx_phy_read(bcm, (offset)));	\
+-	} while (0)
+-#define phy_stackrestore(offset)				\
+-	do {							\
+-		bcm43xx_phy_write(bcm, (offset),		\
+-				  _stack_restore(stack, 0x1,	\
+-					  	 (offset)));	\
+-	} while (0)
+-#define radio_stacksave(offset)						\
+-	do {								\
+-		_stack_save(stack, &stackidx, 0x2, (offset),		\
+-			    bcm43xx_radio_read16(bcm, (offset)));	\
+-	} while (0)
+-#define radio_stackrestore(offset)					\
+-	do {								\
+-		bcm43xx_radio_write16(bcm, (offset),			\
+-				      _stack_restore(stack, 0x2,	\
+-						     (offset)));	\
+-	} while (0)
+-#define ilt_stacksave(offset)					\
+-	do {							\
+-		_stack_save(stack, &stackidx, 0x3, (offset),	\
+-			    bcm43xx_ilt_read(bcm, (offset)));	\
+-	} while (0)
+-#define ilt_stackrestore(offset)				\
+-	do {							\
+-		bcm43xx_ilt_write(bcm, (offset),		\
+-				  _stack_restore(stack, 0x3,	\
+-						 (offset)));	\
+-	} while (0)
+-
+-static void
+-bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,
+-					     int mode)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 tmp, flipped;
+-	u32 tmp32;
+-	size_t stackidx = 0;
+-	u32 *stack = radio->interfstack;
+-
+-	switch (mode) {
+-	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+-		if (phy->rev != 1) {
+-			bcm43xx_phy_write(bcm, 0x042B,
+-			                  bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-			                  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000);
+-			break;
+-		}
+-		radio_stacksave(0x0078);
+-		tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);
+-		flipped = flip_4bit(tmp);
+-		if (flipped < 10 && flipped >= 8)
+-			flipped = 7;
+-		else if (flipped >= 10)
+-			flipped -= 3;
+-		flipped = flip_4bit(flipped);
+-		flipped = (flipped << 1) | 0x0020;
+-		bcm43xx_radio_write16(bcm, 0x0078, flipped);
+-
+-		bcm43xx_calc_nrssi_threshold(bcm);
+-
+-		phy_stacksave(0x0406);
+-		bcm43xx_phy_write(bcm, 0x0406, 0x7E28);
+-
+-		bcm43xx_phy_write(bcm, 0x042B,
+-		                  bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+-		                  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);
+-
+-		phy_stacksave(0x04A0);
+-		bcm43xx_phy_write(bcm, 0x04A0,
+-		                  (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);
+-		phy_stacksave(0x04A1);
+-		bcm43xx_phy_write(bcm, 0x04A1,
+-				  (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);
+-		phy_stacksave(0x04A2);
+-		bcm43xx_phy_write(bcm, 0x04A2,
+-				  (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);
+-		phy_stacksave(0x04A8);
+-		bcm43xx_phy_write(bcm, 0x04A8,
+-				  (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803);
+-		phy_stacksave(0x04AB);
+-		bcm43xx_phy_write(bcm, 0x04AB,
+-				  (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605);
+-
+-		phy_stacksave(0x04A7);
+-		bcm43xx_phy_write(bcm, 0x04A7, 0x0002);
+-		phy_stacksave(0x04A3);
+-		bcm43xx_phy_write(bcm, 0x04A3, 0x287A);
+-		phy_stacksave(0x04A9);
+-		bcm43xx_phy_write(bcm, 0x04A9, 0x2027);
+-		phy_stacksave(0x0493);
+-		bcm43xx_phy_write(bcm, 0x0493, 0x32F5);
+-		phy_stacksave(0x04AA);
+-		bcm43xx_phy_write(bcm, 0x04AA, 0x2027);
+-		phy_stacksave(0x04AC);
+-		bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);
+-		break;
+-	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+-		if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800)
+-			break;
+-
+-		radio->aci_enable = 1;
+-
+-		phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);
+-		phy_stacksave(BCM43xx_PHY_G_CRS);
+-		if (phy->rev < 2) {
+-			phy_stacksave(0x0406);
+-		} else {
+-			phy_stacksave(0x04C0);
+-			phy_stacksave(0x04C1);
+-		}
+-		phy_stacksave(0x0033);
+-		phy_stacksave(0x04A7);
+-		phy_stacksave(0x04A3);
+-		phy_stacksave(0x04A9);
+-		phy_stacksave(0x04AA);
+-		phy_stacksave(0x04AC);
+-		phy_stacksave(0x0493);
+-		phy_stacksave(0x04A1);
+-		phy_stacksave(0x04A0);
+-		phy_stacksave(0x04A2);
+-		phy_stacksave(0x048A);
+-		phy_stacksave(0x04A8);
+-		phy_stacksave(0x04AB);
+-		if (phy->rev == 2) {
+-			phy_stacksave(0x04AD);
+-			phy_stacksave(0x04AE);
+-		} else if (phy->rev >= 3) {
+-			phy_stacksave(0x04AD);
+-			phy_stacksave(0x0415);
+-			phy_stacksave(0x0416);
+-			phy_stacksave(0x0417);
+-			ilt_stacksave(0x1A00 + 0x2);
+-			ilt_stacksave(0x1A00 + 0x3);
+-		}
+-		phy_stacksave(0x042B);
+-		phy_stacksave(0x048C);
+-
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+-				  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
+-				  & ~0x1000);
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-				  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
+-				   & 0xFFFC) | 0x0002);
+-
+-		bcm43xx_phy_write(bcm, 0x0033, 0x0800);
+-		bcm43xx_phy_write(bcm, 0x04A3, 0x2027);
+-		bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8);
+-		bcm43xx_phy_write(bcm, 0x0493, 0x287A);
+-		bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8);
+-		bcm43xx_phy_write(bcm, 0x04AC, 0x287A);
+-
+-		bcm43xx_phy_write(bcm, 0x04A0,
+-				  (bcm43xx_phy_read(bcm, 0x04A0)
+-				   & 0xFFC0) | 0x001A);
+-		bcm43xx_phy_write(bcm, 0x04A7, 0x000D);
+-
+-		if (phy->rev < 2) {
+-			bcm43xx_phy_write(bcm, 0x0406, 0xFF0D);
+-		} else if (phy->rev == 2) {
+-			bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF);
+-			bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);
+-		} else {
+-			bcm43xx_phy_write(bcm, 0x04C0, 0x00C1);
+-			bcm43xx_phy_write(bcm, 0x04C1, 0x0059);
+-		}
+-
+-		bcm43xx_phy_write(bcm, 0x04A1,
+-		                  (bcm43xx_phy_read(bcm, 0x04A1)
+-				   & 0xC0FF) | 0x1800);
+-		bcm43xx_phy_write(bcm, 0x04A1,
+-		                  (bcm43xx_phy_read(bcm, 0x04A1)
+-				   & 0xFFC0) | 0x0015);
+-		bcm43xx_phy_write(bcm, 0x04A8,
+-		                  (bcm43xx_phy_read(bcm, 0x04A8)
+-				   & 0xCFFF) | 0x1000);
+-		bcm43xx_phy_write(bcm, 0x04A8,
+-		                  (bcm43xx_phy_read(bcm, 0x04A8)
+-				   & 0xF0FF) | 0x0A00);
+-		bcm43xx_phy_write(bcm, 0x04AB,
+-		                  (bcm43xx_phy_read(bcm, 0x04AB)
+-				   & 0xCFFF) | 0x1000);
+-		bcm43xx_phy_write(bcm, 0x04AB,
+-		                  (bcm43xx_phy_read(bcm, 0x04AB)
+-				   & 0xF0FF) | 0x0800);
+-		bcm43xx_phy_write(bcm, 0x04AB,
+-		                  (bcm43xx_phy_read(bcm, 0x04AB)
+-				   & 0xFFCF) | 0x0010);
+-		bcm43xx_phy_write(bcm, 0x04AB,
+-		                  (bcm43xx_phy_read(bcm, 0x04AB)
+-				   & 0xFFF0) | 0x0005);
+-		bcm43xx_phy_write(bcm, 0x04A8,
+-		                  (bcm43xx_phy_read(bcm, 0x04A8)
+-				   & 0xFFCF) | 0x0010);
+-		bcm43xx_phy_write(bcm, 0x04A8,
+-		                  (bcm43xx_phy_read(bcm, 0x04A8)
+-				   & 0xFFF0) | 0x0006);
+-		bcm43xx_phy_write(bcm, 0x04A2,
+-		                  (bcm43xx_phy_read(bcm, 0x04A2)
+-				   & 0xF0FF) | 0x0800);
+-		bcm43xx_phy_write(bcm, 0x04A0,
+-				  (bcm43xx_phy_read(bcm, 0x04A0)
+-				   & 0xF0FF) | 0x0500);
+-		bcm43xx_phy_write(bcm, 0x04A2,
+-				  (bcm43xx_phy_read(bcm, 0x04A2)
+-				   & 0xFFF0) | 0x000B);
+-
+-		if (phy->rev >= 3) {
+-			bcm43xx_phy_write(bcm, 0x048A,
+-					  bcm43xx_phy_read(bcm, 0x048A)
+-					  & ~0x8000);
+-			bcm43xx_phy_write(bcm, 0x0415,
+-					  (bcm43xx_phy_read(bcm, 0x0415)
+-					   & 0x8000) | 0x36D8);
+-			bcm43xx_phy_write(bcm, 0x0416,
+-					  (bcm43xx_phy_read(bcm, 0x0416)
+-					   & 0x8000) | 0x36D8);
+-			bcm43xx_phy_write(bcm, 0x0417,
+-					  (bcm43xx_phy_read(bcm, 0x0417)
+-					   & 0xFE00) | 0x016D);
+-		} else {
+-			bcm43xx_phy_write(bcm, 0x048A,
+-					  bcm43xx_phy_read(bcm, 0x048A)
+-					  | 0x1000);
+-			bcm43xx_phy_write(bcm, 0x048A,
+-					  (bcm43xx_phy_read(bcm, 0x048A)
+-					   & 0x9FFF) | 0x2000);
+-			tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+-						   BCM43xx_UCODEFLAGS_OFFSET);
+-			if (!(tmp32 & 0x800)) {
+-				tmp32 |= 0x800;
+-				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+-						    BCM43xx_UCODEFLAGS_OFFSET,
+-						    tmp32);
+-			}
+-		}
+-		if (phy->rev >= 2) {
+-			bcm43xx_phy_write(bcm, 0x042B,
+-					  bcm43xx_phy_read(bcm, 0x042B)
+-					  | 0x0800);
+-		}
+-		bcm43xx_phy_write(bcm, 0x048C,
+-				  (bcm43xx_phy_read(bcm, 0x048C)
+-				   & 0xF0FF) | 0x0200);
+-		if (phy->rev == 2) {
+-			bcm43xx_phy_write(bcm, 0x04AE,
+-					  (bcm43xx_phy_read(bcm, 0x04AE)
+-					   & 0xFF00) | 0x007F);
+-			bcm43xx_phy_write(bcm, 0x04AD,
+-					  (bcm43xx_phy_read(bcm, 0x04AD)
+-					   & 0x00FF) | 0x1300);
+-		} else if (phy->rev >= 6) {
+-			bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F);
+-			bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F);
+-			bcm43xx_phy_write(bcm, 0x04AD,
+-					  bcm43xx_phy_read(bcm, 0x04AD)
+-					  & 0x00FF);
+-		}
+-		bcm43xx_calc_nrssi_slope(bcm);
+-		break;
+-	default:
+-		assert(0);
+-	}
+-}
+-
+-static void
+-bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
+-					      int mode)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u32 tmp32;
+-	u32 *stack = radio->interfstack;
+-
+-	switch (mode) {
+-	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+-		if (phy->rev != 1) {
+-			bcm43xx_phy_write(bcm, 0x042B,
+-			                  bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-			                  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
+-			break;
+-		}
+-		phy_stackrestore(0x0078);
+-		bcm43xx_calc_nrssi_threshold(bcm);
+-		phy_stackrestore(0x0406);
+-		bcm43xx_phy_write(bcm, 0x042B,
+-				  bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
+-		if (!bcm->bad_frames_preempt) {
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+-					  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
+-					  & ~(1 << 11));
+-		}
+-		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-				  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
+-		phy_stackrestore(0x04A0);
+-		phy_stackrestore(0x04A1);
+-		phy_stackrestore(0x04A2);
+-		phy_stackrestore(0x04A8);
+-		phy_stackrestore(0x04AB);
+-		phy_stackrestore(0x04A7);
+-		phy_stackrestore(0x04A3);
+-		phy_stackrestore(0x04A9);
+-		phy_stackrestore(0x0493);
+-		phy_stackrestore(0x04AA);
+-		phy_stackrestore(0x04AC);
+-		break;
+-	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+-		if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800))
+-			break;
+-
+-		radio->aci_enable = 0;
+-
+-		phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);
+-		phy_stackrestore(BCM43xx_PHY_G_CRS);
+-		phy_stackrestore(0x0033);
+-		phy_stackrestore(0x04A3);
+-		phy_stackrestore(0x04A9);
+-		phy_stackrestore(0x0493);
+-		phy_stackrestore(0x04AA);
+-		phy_stackrestore(0x04AC);
+-		phy_stackrestore(0x04A0);
+-		phy_stackrestore(0x04A7);
+-		if (phy->rev >= 2) {
+-			phy_stackrestore(0x04C0);
+-			phy_stackrestore(0x04C1);
+-		} else
+-			phy_stackrestore(0x0406);
+-		phy_stackrestore(0x04A1);
+-		phy_stackrestore(0x04AB);
+-		phy_stackrestore(0x04A8);
+-		if (phy->rev == 2) {
+-			phy_stackrestore(0x04AD);
+-			phy_stackrestore(0x04AE);
+-		} else if (phy->rev >= 3) {
+-			phy_stackrestore(0x04AD);
+-			phy_stackrestore(0x0415);
+-			phy_stackrestore(0x0416);
+-			phy_stackrestore(0x0417);
+-			ilt_stackrestore(0x1A00 + 0x2);
+-			ilt_stackrestore(0x1A00 + 0x3);
+-		}
+-		phy_stackrestore(0x04A2);
+-		phy_stackrestore(0x04A8);
+-		phy_stackrestore(0x042B);
+-		phy_stackrestore(0x048C);
+-		tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+-					   BCM43xx_UCODEFLAGS_OFFSET);
+-		if (tmp32 & 0x800) {
+-			tmp32 &= ~0x800;
+-			bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+-					    BCM43xx_UCODEFLAGS_OFFSET,
+-					    tmp32);
+-		}
+-		bcm43xx_calc_nrssi_slope(bcm);
+-		break;
+-	default:
+-		assert(0);
+-	}
+-}
+-
+-#undef phy_stacksave
+-#undef phy_stackrestore
+-#undef radio_stacksave
+-#undef radio_stackrestore
+-#undef ilt_stacksave
+-#undef ilt_stackrestore
+-
+-int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,
+-					      int mode)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	int currentmode;
+-
+-	if ((phy->type != BCM43xx_PHYTYPE_G) ||
+-	    (phy->rev == 0) ||
+-	    (!phy->connected))
+-		return -ENODEV;
+-
+-	radio->aci_wlan_automatic = 0;
+-	switch (mode) {
+-	case BCM43xx_RADIO_INTERFMODE_AUTOWLAN:
+-		radio->aci_wlan_automatic = 1;
+-		if (radio->aci_enable)
+-			mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+-		else
+-			mode = BCM43xx_RADIO_INTERFMODE_NONE;
+-		break;
+-	case BCM43xx_RADIO_INTERFMODE_NONE:
+-	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+-	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+-		break;
+-	default:
+-		return -EINVAL;
+-	}
+-
+-	currentmode = radio->interfmode;
+-	if (currentmode == mode)
+-		return 0;
+-	if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE)
+-		bcm43xx_radio_interference_mitigation_disable(bcm, currentmode);
+-
+-	if (mode == BCM43xx_RADIO_INTERFMODE_NONE) {
+-		radio->aci_enable = 0;
+-		radio->aci_hw_rssi = 0;
+-	} else
+-		bcm43xx_radio_interference_mitigation_enable(bcm, mode);
+-	radio->interfmode = mode;
+-
+-	return 0;
+-}
+-
+-u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm)
+-{
+-	u16 reg, index, ret;
+-
+-	reg = bcm43xx_radio_read16(bcm, 0x0060);
+-	index = (reg & 0x001E) >> 1;
+-	ret = rcc_table[index] << 1;
+-	ret |= (reg & 0x0001);
+-	ret |= 0x0020;
+-
+-	return ret;
+-}
+-
+-#define LPD(L, P, D)    (((L) << 2) | ((P) << 1) | ((D) << 0))
+-static u16 bcm43xx_get_812_value(struct bcm43xx_private *bcm, u8 lpd)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 loop_or = 0;
+-	u16 adj_loopback_gain = phy->loopback_gain[0];
+-	u8 loop;
+-	u16 extern_lna_control;
+-
+-	if (!phy->connected)
+-		return 0;
+-	if (!has_loopback_gain(phy)) {
+-		if (phy->rev < 7 || !(bcm->sprom.boardflags
+-		    & BCM43xx_BFL_EXTLNA)) {
+-			switch (lpd) {
+-			case LPD(0, 1, 1):
+-				return 0x0FB2;
+-			case LPD(0, 0, 1):
+-				return 0x00B2;
+-			case LPD(1, 0, 1):
+-				return 0x30B2;
+-			case LPD(1, 0, 0):
+-				return 0x30B3;
+-			default:
+-				assert(0);
+-			}
+-		} else {
+-			switch (lpd) {
+-			case LPD(0, 1, 1):
+-				return 0x8FB2;
+-			case LPD(0, 0, 1):
+-				return 0x80B2;
+-			case LPD(1, 0, 1):
+-				return 0x20B2;
+-			case LPD(1, 0, 0):
+-				return 0x20B3;
+-			default:
+-				assert(0);
+-			}
+-		}
+-	} else {
+-		if (radio->revision == 8)
+-			adj_loopback_gain += 0x003E;
+-		else
+-			adj_loopback_gain += 0x0026;
+-		if (adj_loopback_gain >= 0x46) {
+-			adj_loopback_gain -= 0x46;
+-			extern_lna_control = 0x3000;
+-		} else if (adj_loopback_gain >= 0x3A) {
+-			adj_loopback_gain -= 0x3A;
+-			extern_lna_control = 0x2000;
+-		} else if (adj_loopback_gain >= 0x2E) {
+-			adj_loopback_gain -= 0x2E;
+-			extern_lna_control = 0x1000;
+-		} else {
+-			adj_loopback_gain -= 0x10;
+-			extern_lna_control = 0x0000;
+-		}
+-		for (loop = 0; loop < 16; loop++) {
+-			u16 tmp = adj_loopback_gain - 6 * loop;
+-			if (tmp < 6)
+-				break;
+-		}
+-
+-		loop_or = (loop << 8) | extern_lna_control;
+-		if (phy->rev >= 7 && bcm->sprom.boardflags
+-		    & BCM43xx_BFL_EXTLNA) {
+-			if (extern_lna_control)
+-				loop_or |= 0x8000;
+-			switch (lpd) {
+-			case LPD(0, 1, 1):
+-				return 0x8F92;
+-			case LPD(0, 0, 1):
+-				return (0x8092 | loop_or);
+-			case LPD(1, 0, 1):
+-				return (0x2092 | loop_or);
+-			case LPD(1, 0, 0):
+-				return (0x2093 | loop_or);
+-			default:
+-				assert(0);
+-			}
+-		} else {
+-			switch (lpd) {
+-			case LPD(0, 1, 1):
+-				return 0x0F92;
+-			case LPD(0, 0, 1):
+-			case LPD(1, 0, 1):
+-				return (0x0092 | loop_or);
+-			case LPD(1, 0, 0):
+-				return (0x0093 | loop_or);
+-			default:
+-				assert(0);
+-			}
+-		}
+-	}
+-	return 0;
+-}
+-
+-u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 backup[21] = { 0 };
+-	u16 ret;
+-	u16 i, j;
+-	u32 tmp1 = 0, tmp2 = 0;
+-
+-	backup[0] = bcm43xx_radio_read16(bcm, 0x0043);
+-	backup[14] = bcm43xx_radio_read16(bcm, 0x0051);
+-	backup[15] = bcm43xx_radio_read16(bcm, 0x0052);
+-	backup[1] = bcm43xx_phy_read(bcm, 0x0015);
+-	backup[16] = bcm43xx_phy_read(bcm, 0x005A);
+-	backup[17] = bcm43xx_phy_read(bcm, 0x0059);
+-	backup[18] = bcm43xx_phy_read(bcm, 0x0058);
+-	if (phy->type == BCM43xx_PHYTYPE_B) {
+-		backup[2] = bcm43xx_phy_read(bcm, 0x0030);
+-		backup[3] = bcm43xx_read16(bcm, 0x03EC);
+-		bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+-		bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
+-	} else {
+-		if (phy->connected) {
+-			backup[4] = bcm43xx_phy_read(bcm, 0x0811);
+-			backup[5] = bcm43xx_phy_read(bcm, 0x0812);
+-			backup[6] = bcm43xx_phy_read(bcm, 0x0814);
+-			backup[7] = bcm43xx_phy_read(bcm, 0x0815);
+-			backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
+-			backup[9] = bcm43xx_phy_read(bcm, 0x0802);
+-			bcm43xx_phy_write(bcm, 0x0814,
+-			                  (bcm43xx_phy_read(bcm, 0x0814)
+-					  | 0x0003));
+-			bcm43xx_phy_write(bcm, 0x0815,
+-			                  (bcm43xx_phy_read(bcm, 0x0815)
+-					  & 0xFFFC));
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+-			                  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
+-					  & 0x7FFF));
+-			bcm43xx_phy_write(bcm, 0x0802,
+-			                  (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC));
+-			if (phy->rev > 1) { /* loopback gain enabled */
+-				backup[19] = bcm43xx_phy_read(bcm, 0x080F);
+-				backup[20] = bcm43xx_phy_read(bcm, 0x0810);
+-				if (phy->rev >= 3)
+-					bcm43xx_phy_write(bcm, 0x080F, 0xC020);
+-				else
+-					bcm43xx_phy_write(bcm, 0x080F, 0x8020);
+-				bcm43xx_phy_write(bcm, 0x0810, 0x0000);
+-			}
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));
+-			if (phy->rev < 7 || !(bcm->sprom.boardflags
+-			    & BCM43xx_BFL_EXTLNA))
+-				bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
+-			else
+-				bcm43xx_phy_write(bcm, 0x0811, 0x09B3);
+-		}
+-	}
+-	bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
+-	                (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000));
+-	backup[10] = bcm43xx_phy_read(bcm, 0x0035);
+-	bcm43xx_phy_write(bcm, 0x0035,
+-	                  (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F));
+-	backup[11] = bcm43xx_read16(bcm, 0x03E6);
+-	backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+-
+-	// Initialization
+-	if (phy->analog == 0) {
+-		bcm43xx_write16(bcm, 0x03E6, 0x0122);
+-	} else {
+-		if (phy->analog >= 2)
+-			bcm43xx_phy_write(bcm, 0x0003,
+-					  (bcm43xx_phy_read(bcm, 0x0003)
+-					  & 0xFFBF) | 0x0040);
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+-		                (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+-				| 0x2000));
+-	}
+-
+-	ret = bcm43xx_radio_calibrationvalue(bcm);
+-
+-	if (phy->type == BCM43xx_PHYTYPE_B)
+-		bcm43xx_radio_write16(bcm, 0x0078, 0x0026);
+-
+-	if (phy->connected)
+-		bcm43xx_phy_write(bcm, 0x0812,
+-				  bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));
+-	bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
+-	bcm43xx_phy_write(bcm, 0x002B, 0x1403);
+-	if (phy->connected)
+-		bcm43xx_phy_write(bcm, 0x0812,
+-				  bcm43xx_get_812_value(bcm, LPD(0, 0, 1)));
+-	bcm43xx_phy_write(bcm, 0x0015, 0xBFA0);
+-	bcm43xx_radio_write16(bcm, 0x0051,
+-	                      (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
+-	if (radio->revision == 8)
+-		bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
+-	else {
+-		bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+-		bcm43xx_radio_write16(bcm, 0x0043,
+-				      (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0)
+-				      | 0x0009);
+-	}
+-	bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+-
+-	for (i = 0; i < 16; i++) {
+-		bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+-		bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+-		bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+-		if (phy->connected)
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
+-		bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+-		udelay(10);
+-		if (phy->connected)
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
+-		bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
+-		udelay(10);
+-		if (phy->connected)
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  bcm43xx_get_812_value(bcm, LPD(1, 0, 0)));
+-		bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
+-		udelay(20);
+-		tmp1 += bcm43xx_phy_read(bcm, 0x002D);
+-		bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+-		if (phy->connected)
+-			bcm43xx_phy_write(bcm, 0x0812,
+-					  bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
+-		bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+-	}
+-
+-	tmp1++;
+-	tmp1 >>= 9;
+-	udelay(10);
+-	bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+-
+-	for (i = 0; i < 16; i++) {
+-		bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020);
+-		backup[13] = bcm43xx_radio_read16(bcm, 0x0078);
+-		udelay(10);
+-		for (j = 0; j < 16; j++) {
+-			bcm43xx_phy_write(bcm, 0x005A, 0x0D80);
+-			bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+-			bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+-			if (phy->connected)
+-				bcm43xx_phy_write(bcm, 0x0812,
+-						  bcm43xx_get_812_value(bcm,
+-						  LPD(1, 0, 1)));
+-			bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+-			udelay(10);
+-			if (phy->connected)
+-				bcm43xx_phy_write(bcm, 0x0812,
+-						  bcm43xx_get_812_value(bcm,
+-						  LPD(1, 0, 1)));
+-			bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
+-			udelay(10);
+-			if (phy->connected)
+-				bcm43xx_phy_write(bcm, 0x0812,
+-						  bcm43xx_get_812_value(bcm,
+-						  LPD(1, 0, 0)));
+-			bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
+-			udelay(10);
+-			tmp2 += bcm43xx_phy_read(bcm, 0x002D);
+-			bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+-			if (phy->connected)
+-				bcm43xx_phy_write(bcm, 0x0812,
+-						  bcm43xx_get_812_value(bcm,
+-						  LPD(1, 0, 1)));
+-			bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+-		}
+-		tmp2++;
+-		tmp2 >>= 8;
+-		if (tmp1 < tmp2)
+-			break;
+-	}
+-
+-	/* Restore the registers */
+-	bcm43xx_phy_write(bcm, 0x0015, backup[1]);
+-	bcm43xx_radio_write16(bcm, 0x0051, backup[14]);
+-	bcm43xx_radio_write16(bcm, 0x0052, backup[15]);
+-	bcm43xx_radio_write16(bcm, 0x0043, backup[0]);
+-	bcm43xx_phy_write(bcm, 0x005A, backup[16]);
+-	bcm43xx_phy_write(bcm, 0x0059, backup[17]);
+-	bcm43xx_phy_write(bcm, 0x0058, backup[18]);
+-	bcm43xx_write16(bcm, 0x03E6, backup[11]);
+-	if (phy->analog != 0)
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
+-	bcm43xx_phy_write(bcm, 0x0035, backup[10]);
+-	bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
+-	if (phy->type == BCM43xx_PHYTYPE_B) {
+-		bcm43xx_phy_write(bcm, 0x0030, backup[2]);
+-		bcm43xx_write16(bcm, 0x03EC, backup[3]);
+-	} else {
+-		if (phy->connected) {
+-			bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
+-					(bcm43xx_read16(bcm,
+-					BCM43xx_MMIO_PHY_RADIO) & 0x7FFF));
+-			bcm43xx_phy_write(bcm, 0x0811, backup[4]);
+-			bcm43xx_phy_write(bcm, 0x0812, backup[5]);
+-			bcm43xx_phy_write(bcm, 0x0814, backup[6]);
+-			bcm43xx_phy_write(bcm, 0x0815, backup[7]);
+-			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]);
+-			bcm43xx_phy_write(bcm, 0x0802, backup[9]);
+-			if (phy->rev > 1) {
+-				bcm43xx_phy_write(bcm, 0x080F, backup[19]);
+-				bcm43xx_phy_write(bcm, 0x0810, backup[20]);
+-			}
+-		}
+-	}
+-	if (i >= 15)
+-		ret = backup[13];
+-
+-	return ret;
+-}
+-
+-void bcm43xx_radio_init2060(struct bcm43xx_private *bcm)
+-{
+-	int err;
+-
+-	bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
+-	bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
+-	bcm43xx_radio_write16(bcm, 0x0009, 0x0040);
+-	bcm43xx_radio_write16(bcm, 0x0005, 0x00AA);
+-	bcm43xx_radio_write16(bcm, 0x0032, 0x008F);
+-	bcm43xx_radio_write16(bcm, 0x0006, 0x008F);
+-	bcm43xx_radio_write16(bcm, 0x0034, 0x008F);
+-	bcm43xx_radio_write16(bcm, 0x002C, 0x0007);
+-	bcm43xx_radio_write16(bcm, 0x0082, 0x0080);
+-	bcm43xx_radio_write16(bcm, 0x0080, 0x0000);
+-	bcm43xx_radio_write16(bcm, 0x003F, 0x00DA);
+-	bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
+-	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010);
+-	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
+-	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
+-	udelay(400);
+-
+-	bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010);
+-	udelay(400);
+-
+-	bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008);
+-	bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010);
+-	bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
+-	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040);
+-	bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040);
+-	bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008);
+-	bcm43xx_phy_write(bcm, 0x0063, 0xDDC6);
+-	bcm43xx_phy_write(bcm, 0x0069, 0x07BE);
+-	bcm43xx_phy_write(bcm, 0x006A, 0x0000);
+-
+-	err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0);
+-	assert(err == 0);
+-	udelay(1000);
+-}
+-
+-static inline
+-u16 freq_r3A_value(u16 frequency)
+-{
+-	u16 value;
+-
+-	if (frequency < 5091)
+-		value = 0x0040;
+-	else if (frequency < 5321)
+-		value = 0x0000;
+-	else if (frequency < 5806)
+-		value = 0x0080;
+-	else
+-		value = 0x0040;
+-
+-	return value;
+-}
+-
+-void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm)
+-{
+-	static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
+-	static const u8 data_low[5]  = { 0x00, 0x01, 0x05, 0x06, 0x0A };
+-	u16 tmp = bcm43xx_radio_read16(bcm, 0x001E);
+-	int i, j;
+-	
+-	for (i = 0; i < 5; i++) {
+-		for (j = 0; j < 5; j++) {
+-			if (tmp == (data_high[i] | data_low[j])) {
+-				bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);
+-				return;
+-			}
+-		}
+-	}
+-}
+-
+-int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
+-				u8 channel,
+-				int synthetic_pu_workaround)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 r8, tmp;
+-	u16 freq;
+-
+-	if (!ieee80211_is_valid_channel(bcm->ieee, channel))
+-		return -EINVAL;
+-	if ((radio->manufact == 0x17F) &&
+-	    (radio->version == 0x2060) &&
+-	    (radio->revision == 1)) {
+-		freq = channel2freq_a(channel);
+-
+-		r8 = bcm43xx_radio_read16(bcm, 0x0008);
+-		bcm43xx_write16(bcm, 0x03F0, freq);
+-		bcm43xx_radio_write16(bcm, 0x0008, r8);
+-
+-		TODO();//TODO: write max channel TX power? to Radio 0x2D
+-		tmp = bcm43xx_radio_read16(bcm, 0x002E);
+-		tmp &= 0x0080;
+-		TODO();//TODO: OR tmp with the Power out estimation for this channel?
+-		bcm43xx_radio_write16(bcm, 0x002E, tmp);
+-
+-		if (freq >= 4920 && freq <= 5500) {
+-			/* 
+-			 * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
+-			 *    = (freq * 0.025862069
+-			 */
+-			r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
+-		}
+-		bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8);
+-		bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8);
+-		bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8);
+-		bcm43xx_radio_write16(bcm, 0x0022,
+-				      (bcm43xx_radio_read16(bcm, 0x0022)
+-				       & 0x000F) | (r8 << 4));
+-		bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4));
+-		bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4));
+-		bcm43xx_radio_write16(bcm, 0x0008,
+-				      (bcm43xx_radio_read16(bcm, 0x0008)
+-				       & 0x00F0) | (r8 << 4));
+-		bcm43xx_radio_write16(bcm, 0x0029,
+-				      (bcm43xx_radio_read16(bcm, 0x0029)
+-				       & 0xFF0F) | 0x00B0);
+-		bcm43xx_radio_write16(bcm, 0x0035, 0x00AA);
+-		bcm43xx_radio_write16(bcm, 0x0036, 0x0085);
+-		bcm43xx_radio_write16(bcm, 0x003A,
+-				      (bcm43xx_radio_read16(bcm, 0x003A)
+-				       & 0xFF20) | freq_r3A_value(freq));
+-		bcm43xx_radio_write16(bcm, 0x003D,
+-				      bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF);
+-		bcm43xx_radio_write16(bcm, 0x0081,
+-				      (bcm43xx_radio_read16(bcm, 0x0081)
+-				       & 0xFF7F) | 0x0080);
+-		bcm43xx_radio_write16(bcm, 0x0035,
+-				      bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF);
+-		bcm43xx_radio_write16(bcm, 0x0035,
+-				      (bcm43xx_radio_read16(bcm, 0x0035)
+-				       & 0xFFEF) | 0x0010);
+-		bcm43xx_radio_set_tx_iq(bcm);
+-		TODO();	//TODO:	TSSI2dbm workaround
+-		bcm43xx_phy_xmitpower(bcm);//FIXME correct?
+-	} else {
+-		if (synthetic_pu_workaround)
+-			bcm43xx_synth_pu_workaround(bcm, channel);
+-
+-		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+-				channel2freq_bg(channel));
+-
+-		if (channel == 14) {
+-			if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) {
+-				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+-						    BCM43xx_UCODEFLAGS_OFFSET,
+-						    bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+-								       BCM43xx_UCODEFLAGS_OFFSET)
+-						    & ~(1 << 7));
+-			} else {
+-				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+-						    BCM43xx_UCODEFLAGS_OFFSET,
+-						    bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+-								       BCM43xx_UCODEFLAGS_OFFSET)
+-						    | (1 << 7));
+-			}
+-			bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+-					bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+-					| (1 << 11));
+-		} else {
+-			bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+-					bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+-					& 0xF7BF);
+-		}
+-	}
+-
+-	radio->channel = channel;
+-	//XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
+-	//     that 2000 usecs might suffice.
+-	udelay(8000);
+-
+-	return 0;
+-}
+-
+-void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val)
+-{
+-	u16 tmp;
+-
+-	val <<= 8;
+-	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF;
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val);
+-	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF;
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val);
+-	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF;
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val);
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
+-static u16 bcm43xx_get_txgain_base_band(u16 txpower)
+-{
+-	u16 ret;
+-
+-	assert(txpower <= 63);
+-
+-	if (txpower >= 54)
+-		ret = 2;
+-	else if (txpower >= 49)
+-		ret = 4;
+-	else if (txpower >= 44)
+-		ret = 5;
+-	else
+-		ret = 6;
+-
+-	return ret;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
+-static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower)
+-{
+-	u16 ret;
+-
+-	assert(txpower <= 63);
+-
+-	if (txpower >= 32)
+-		ret = 0;
+-	else if (txpower >= 25)
+-		ret = 1;
+-	else if (txpower >= 20)
+-		ret = 2;
+-	else if (txpower >= 12)
+-		ret = 3;
+-	else
+-		ret = 4;
+-
+-	return ret;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
+-static u16 bcm43xx_get_txgain_dac(u16 txpower)
+-{
+-	u16 ret;
+-
+-	assert(txpower <= 63);
+-
+-	if (txpower >= 54)
+-		ret = txpower - 53;
+-	else if (txpower >= 49)
+-		ret = txpower - 42;
+-	else if (txpower >= 44)
+-		ret = txpower - 37;
+-	else if (txpower >= 32)
+-		ret = txpower - 32;
+-	else if (txpower >= 25)
+-		ret = txpower - 20;
+-	else if (txpower >= 20)
+-		ret = txpower - 13;
+-	else if (txpower >= 12)
+-		ret = txpower - 8;
+-	else
+-		ret = txpower;
+-
+-	return ret;
+-}
+-
+-void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 pamp, base, dac, ilt;
+-
+-	txpower = limit_value(txpower, 0, 63);
+-
+-	pamp = bcm43xx_get_txgain_freq_power_amp(txpower);
+-	pamp <<= 5;
+-	pamp &= 0x00E0;
+-	bcm43xx_phy_write(bcm, 0x0019, pamp);
+-
+-	base = bcm43xx_get_txgain_base_band(txpower);
+-	base &= 0x000F;
+-	bcm43xx_phy_write(bcm, 0x0017, base | 0x0020);
+-
+-	ilt = bcm43xx_ilt_read(bcm, 0x3001);
+-	ilt &= 0x0007;
+-
+-	dac = bcm43xx_get_txgain_dac(txpower);
+-	dac <<= 3;
+-	dac |= ilt;
+-
+-	bcm43xx_ilt_write(bcm, 0x3001, dac);
+-
+-	radio->txpwr_offset = txpower;
+-
+-	TODO();
+-	//TODO: FuncPlaceholder (Adjust BB loft cancel)
+-}
+-
+-void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
+-                                 u16 baseband_attenuation, u16 radio_attenuation,
+-                                 u16 txpower)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+-	if (baseband_attenuation == 0xFFFF)
+-		baseband_attenuation = radio->baseband_atten;
+-	if (radio_attenuation == 0xFFFF)
+-		radio_attenuation = radio->radio_atten;
+-	if (txpower == 0xFFFF)
+-		txpower = radio->txctl1;
+-	radio->baseband_atten = baseband_attenuation;
+-	radio->radio_atten = radio_attenuation;
+-	radio->txctl1 = txpower;
+-
+-	assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11);
+-	if (radio->revision < 6)
+-		assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9);
+-	else
+-		assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31);
+-	assert(/*txpower >= 0 &&*/ txpower <= 7);
+-
+-	bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation);
+-	bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation);
+-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation);
+-	if (radio->version == 0x2050) {
+-		bcm43xx_radio_write16(bcm, 0x0052,
+-		                      (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070)
+-				       | ((txpower << 4) & 0x0070));
+-	}
+-	//FIXME: The spec is very weird and unclear here.
+-	if (phy->type == BCM43xx_PHYTYPE_G)
+-		bcm43xx_phy_lo_adjust(bcm, 0);
+-}
+-
+-u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+-	if (radio->version == 0x2050 && radio->revision < 6)
+-		return 0;
+-	return 2;
+-}
+-
+-u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	u16 att = 0xFFFF;
+-
+-	if (phy->type == BCM43xx_PHYTYPE_A)
+-		return 0x60;
+-
+-	switch (radio->version) {
+-	case 0x2053:
+-		switch (radio->revision) {
+-		case 1:
+-			att = 6;
+-			break;
+-		}
+-		break;
+-	case 0x2050:
+-		switch (radio->revision) {
+-		case 0:
+-			att = 5;
+-			break;
+-		case 1:
+-			if (phy->type == BCM43xx_PHYTYPE_G) {
+-				if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+-				    bcm->board_type == 0x421 &&
+-				    bcm->board_revision >= 30)
+-					att = 3;
+-				else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+-					 bcm->board_type == 0x416)
+-					att = 3;
+-				else
+-					att = 1;
+-			} else {
+-				if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+-				    bcm->board_type == 0x421 &&
+-				    bcm->board_revision >= 30)
+-					att = 7;
+-				else
+-					att = 6;
+-			}
+-			break;
+-		case 2:
+-			if (phy->type == BCM43xx_PHYTYPE_G) {
+-				if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+-				    bcm->board_type == 0x421 &&
+-				    bcm->board_revision >= 30)
+-					att = 3;
+-				else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+-					 bcm->board_type == 0x416)
+-					att = 5;
+-				else if (bcm->chip_id == 0x4320)
+-					att = 4;
+-				else
+-					att = 3;
+-			} else
+-				att = 6;
+-			break;
+-		case 3:
+-			att = 5;
+-			break;
+-		case 4:
+-		case 5:
+-			att = 1;
+-			break;
+-		case 6:
+-		case 7:
+-			att = 5;
+-			break;
+-		case 8:
+-			att = 0x1A;
+-			break;
+-		case 9:
+-		default:
+-			att = 5;
+-		}
+-	}
+-	if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+-	    bcm->board_type == 0x421) {
+-		if (bcm->board_revision < 0x43)
+-			att = 2;
+-		else if (bcm->board_revision < 0x51)
+-			att = 3;
+-	}
+-	if (att == 0xFFFF)
+-		att = 5;
+-
+-	return att;
+-}
+-
+-u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+-	if (radio->version != 0x2050)
+-		return 0;
+-	if (radio->revision == 1)
+-		return 3;
+-	if (radio->revision < 6)
+-		return 2;
+-	if (radio->revision == 8)
+-		return 1;
+-	return 0;
+-}
+-
+-void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	int err;
+-
+-	if (radio->enabled)
+-		return;
+-
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_A:
+-		bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
+-		bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
+-		bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7);
+-		bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7);
+-		bcm43xx_radio_init2060(bcm);	
+-		break;
+-	case BCM43xx_PHYTYPE_B:
+-	case BCM43xx_PHYTYPE_G:
+-		bcm43xx_phy_write(bcm, 0x0015, 0x8000);
+-		bcm43xx_phy_write(bcm, 0x0015, 0xCC00);
+-		bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000));
+-		err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1);
+-		assert(err == 0);
+-		break;
+-	default:
+-		assert(0);
+-	}
+-	radio->enabled = 1;
+-	dprintk(KERN_INFO PFX "Radio turned on\n");
+-	bcm43xx_leds_update(bcm, 0);
+-}
+-	
+-void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+-	if (phy->type == BCM43xx_PHYTYPE_A) {
+-		bcm43xx_radio_write16(bcm, 0x0004, 0x00FF);
+-		bcm43xx_radio_write16(bcm, 0x0005, 0x00FB);
+-		bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008);
+-		bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008);
+-	}
+-	if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) {
+-		bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C);
+-		bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73);
+-	} else
+-		bcm43xx_phy_write(bcm, 0x0015, 0xAA00);
+-	radio->enabled = 0;
+-	dprintk(KERN_INFO PFX "Radio initialized\n");
+-	bcm43xx_leds_update(bcm, 0);
+-}
+-
+-void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+-	switch (phy->type) {
+-	case BCM43xx_PHYTYPE_A:
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F);
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F);
+-		break;
+-	case BCM43xx_PHYTYPE_B:
+-	case BCM43xx_PHYTYPE_G:
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F);
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F);
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F);
+-		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F);
+-		break;
+-	}
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
+deleted file mode 100644
+index 77a98a5..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
++++ /dev/null
+@@ -1,115 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 BCM43xx_RADIO_H_
+-#define BCM43xx_RADIO_H_
+-
+-#include "bcm43xx.h"
+-
+-
+-#define BCM43xx_RADIO_DEFAULT_CHANNEL_A		36
+-#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG	6
+-
+-/* Force antenna 0. */
+-#define BCM43xx_RADIO_TXANTENNA_0		0
+-/* Force antenna 1. */
+-#define BCM43xx_RADIO_TXANTENNA_1		1
+-/* Use the RX antenna, that was selected for the most recently
+- * received good PLCP header.
+- */
+-#define BCM43xx_RADIO_TXANTENNA_LASTPLCP	3
+-#define BCM43xx_RADIO_TXANTENNA_DEFAULT		BCM43xx_RADIO_TXANTENNA_LASTPLCP
+-
+-#define BCM43xx_RADIO_INTERFMODE_NONE		0
+-#define BCM43xx_RADIO_INTERFMODE_NONWLAN	1
+-#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN	2
+-#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN	3
+-
+-
+-void bcm43xx_radio_lock(struct bcm43xx_private *bcm);
+-void bcm43xx_radio_unlock(struct bcm43xx_private *bcm);
+-
+-u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset);
+-void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val);
+-
+-u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm);
+-void bcm43xx_radio_init2060(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm);
+-void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm);
+-
+-static inline
+-int bcm43xx_is_hw_radio_enabled(struct bcm43xx_private *bcm)
+-{
+-	/* function to return state of hardware enable of radio
+-	 * returns 0 if radio disabled, 1 if radio enabled
+-	 */
+-	if (bcm->current_core->rev >= 3)
+-		return ((bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI)
+-					& BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK)
+-					== 0) ? 1 : 0;
+-	else
+-		return ((bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO)
+-					& BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK)
+-					== 0) ? 0 : 1;
+-}
+-
+-int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel,
+-				int synthetic_pu_workaround);
+-
+-void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower);
+-void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
+-                               u16 baseband_attenuation, u16 attenuation,
+-			       u16 txpower);
+-
+-u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm);
+-u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm);
+-u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val);
+-
+-void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm);
+-
+-u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel);
+-u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm);
+-
+-int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode);
+-
+-void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm);
+-void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm);
+-s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset);
+-void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val);
+-void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val);
+-void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm);
+-u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm);
+-
+-#endif /* BCM43xx_RADIO_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+deleted file mode 100644
+index 8ab5f93..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
++++ /dev/null
+@@ -1,471 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  SYSFS support routines
+-
+-  Copyright (c) 2006 Michael Buesch <mbuesch at freenet.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 "bcm43xx_sysfs.h"
+-#include "bcm43xx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_radio.h"
+-
+-#include <linux/capability.h>
+-
+-
+-#define GENERIC_FILESIZE	64
+-
+-
+-static int get_integer(const char *buf, size_t count)
+-{
+-	char tmp[10 + 1] = { 0 };
+-	int ret = -EINVAL;
+-
+-	if (count == 0)
+-		goto out;
+-	count = min(count, (size_t)10);
+-	memcpy(tmp, buf, count);
+-	ret = simple_strtol(tmp, NULL, 10);
+-out:
+-	return ret;
+-}
+-
+-static int get_boolean(const char *buf, size_t count)
+-{
+-	if (count != 0) {
+-		if (buf[0] == '1')
+-			return 1;
+-		if (buf[0] == '0')
+-			return 0;
+-		if (count >= 4 && memcmp(buf, "true", 4) == 0)
+-			return 1;
+-		if (count >= 5 && memcmp(buf, "false", 5) == 0)
+-			return 0;
+-		if (count >= 3 && memcmp(buf, "yes", 3) == 0)
+-			return 1;
+-		if (count >= 2 && memcmp(buf, "no", 2) == 0)
+-			return 0;
+-		if (count >= 2 && memcmp(buf, "on", 2) == 0)
+-			return 1;
+-		if (count >= 3 && memcmp(buf, "off", 3) == 0)
+-			return 0;
+-	}
+-	return -EINVAL;
+-}
+-
+-static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
+-{
+-	int i, pos = 0;
+-
+-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+-		pos += snprintf(buf + pos, buf_len - pos - 1,
+-				"%04X", swab16(sprom[i]) & 0xFFFF);
+-	}
+-	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
+-
+-	return pos + 1;
+-}
+-
+-static int hex2sprom(u16 *sprom, const char *dump, size_t len)
+-{
+-	char tmp[5] = { 0 };
+-	int cnt = 0;
+-	unsigned long parsed;
+-
+-	if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+-		return -EINVAL;
+-
+-	while (cnt < BCM43xx_SPROM_SIZE) {
+-		memcpy(tmp, dump, 4);
+-		dump += 4;
+-		parsed = simple_strtoul(tmp, NULL, 16);
+-		sprom[cnt++] = swab16((u16)parsed);
+-	}
+-
+-	return 0;
+-}
+-
+-static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
+-				       struct device_attribute *attr,
+-				       char *buf)
+-{
+-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+-	u16 *sprom;
+-	unsigned long flags;
+-	int err;
+-
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+-	assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE);
+-	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+-			GFP_KERNEL);
+-	if (!sprom)
+-		return -ENOMEM;
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	err = bcm43xx_sprom_read(bcm, sprom);
+-	if (!err)
+-		err = sprom2hex(sprom, buf, PAGE_SIZE);
+-	mmiowb();
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-	kfree(sprom);
+-
+-	return err;
+-}
+-
+-static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
+-					struct device_attribute *attr,
+-					const char *buf, size_t count)
+-{
+-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+-	u16 *sprom;
+-	unsigned long flags;
+-	int err;
+-
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+-	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+-			GFP_KERNEL);
+-	if (!sprom)
+-		return -ENOMEM;
+-	err = hex2sprom(sprom, buf, count);
+-	if (err)
+-		goto out_kfree;
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	spin_lock(&bcm->leds_lock);
+-	err = bcm43xx_sprom_write(bcm, sprom);
+-	mmiowb();
+-	spin_unlock(&bcm->leds_lock);
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-out_kfree:
+-	kfree(sprom);
+-
+-	return err ? err : count;
+-
+-}
+-
+-static DEVICE_ATTR(sprom, 0600,
+-		   bcm43xx_attr_sprom_show,
+-		   bcm43xx_attr_sprom_store);
+-
+-static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
+-					    struct device_attribute *attr,
+-					    char *buf)
+-{
+-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+-	ssize_t count = 0;
+-
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+-	mutex_lock(&bcm->mutex);
+-
+-	switch (bcm43xx_current_radio(bcm)->interfmode) {
+-	case BCM43xx_RADIO_INTERFMODE_NONE:
+-		count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n");
+-		break;
+-	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+-		count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n");
+-		break;
+-	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+-		count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n");
+-		break;
+-	default:
+-		assert(0);
+-	}
+-
+-	mutex_unlock(&bcm->mutex);
+-
+-	return count;
+-
+-}
+-
+-static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
+-					     struct device_attribute *attr,
+-					     const char *buf, size_t count)
+-{
+-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+-	unsigned long flags;
+-	int err;
+-	int mode;
+-
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+-	mode = get_integer(buf, count);
+-	switch (mode) {
+-	case 0:
+-		mode = BCM43xx_RADIO_INTERFMODE_NONE;
+-		break;
+-	case 1:
+-		mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
+-		break;
+-	case 2:
+-		mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+-		break;
+-	case 3:
+-		mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
+-		break;
+-	default:
+-		return -EINVAL;
+-	}
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+-	err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
+-	if (err) {
+-		printk(KERN_ERR PFX "Interference Mitigation not "
+-				    "supported by device\n");
+-	}
+-	mmiowb();
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return err ? err : count;
+-}
+-
+-static DEVICE_ATTR(interference, 0644,
+-		   bcm43xx_attr_interfmode_show,
+-		   bcm43xx_attr_interfmode_store);
+-
+-static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
+-					  struct device_attribute *attr,
+-					  char *buf)
+-{
+-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+-	ssize_t count;
+-
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+-	mutex_lock(&bcm->mutex);
+-
+-	if (bcm->short_preamble)
+-		count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
+-	else
+-		count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
+-
+-	mutex_unlock(&bcm->mutex);
+-
+-	return count;
+-}
+-
+-static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
+-					   struct device_attribute *attr,
+-					   const char *buf, size_t count)
+-{
+-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+-	unsigned long flags;
+-	int value;
+-
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+-	value = get_boolean(buf, count);
+-	if (value < 0)
+-		return value;
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+-	bcm->short_preamble = !!value;
+-
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(shortpreamble, 0644,
+-		   bcm43xx_attr_preamble_show,
+-		   bcm43xx_attr_preamble_store);
+-
+-static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
+-					  struct device_attribute *attr,
+-					  const char *buf, size_t count)
+-{
+-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+-	int phytype;
+-	int err = -EINVAL;
+-
+-	if (count < 1)
+-		goto out;
+-	switch (buf[0]) {
+-	case 'a':  case 'A':
+-		phytype = BCM43xx_PHYTYPE_A;
+-		break;
+-	case 'b':  case 'B':
+-		phytype = BCM43xx_PHYTYPE_B;
+-		break;
+-	case 'g':  case 'G':
+-		phytype = BCM43xx_PHYTYPE_G;
+-		break;
+-	default:
+-		goto out;
+-	}
+-
+-	bcm43xx_cancel_work(bcm);
+-	mutex_lock(&(bcm)->mutex);
+-	err = bcm43xx_select_wireless_core(bcm, phytype);
+-	if (!err)
+-		bcm43xx_periodic_tasks_setup(bcm);
+-	mutex_unlock(&(bcm)->mutex);
+-	if (err == -ESRCH)
+-		err = -ENODEV;
+-
+-out:
+-	return err ? err : count;
+-}
+-
+-static ssize_t bcm43xx_attr_phymode_show(struct device *dev,
+-					 struct device_attribute *attr,
+-					 char *buf)
+-{
+-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+-	ssize_t count = 0;
+-
+-	mutex_lock(&(bcm)->mutex);
+-	switch (bcm43xx_current_phy(bcm)->type) {
+-	case BCM43xx_PHYTYPE_A:
+-		snprintf(buf, PAGE_SIZE, "A");
+-		break;
+-	case BCM43xx_PHYTYPE_B:
+-		snprintf(buf, PAGE_SIZE, "B");
+-		break;
+-	case BCM43xx_PHYTYPE_G:
+-		snprintf(buf, PAGE_SIZE, "G");
+-		break;
+-	default:
+-		assert(0);
+-	}
+-	mutex_unlock(&(bcm)->mutex);
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(phymode, 0644,
+-		   bcm43xx_attr_phymode_show,
+-		   bcm43xx_attr_phymode_store);
+-
+-static ssize_t bcm43xx_attr_microcode_show(struct device *dev,
+-					   struct device_attribute *attr,
+-					   char *buf)
+-{
+-	unsigned long flags;
+-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+-	ssize_t count = 0;
+-	u16 status;
+-
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+-	mutex_lock(&(bcm)->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	status = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+-				    BCM43xx_UCODE_STATUS);
+-
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&(bcm)->mutex);
+-	switch (status) {
+-	case 0x0000:
+-		count = snprintf(buf, PAGE_SIZE, "0x%.4x (invalid)\n",
+-				 status);
+-		break;
+-	case 0x0001:
+-		count = snprintf(buf, PAGE_SIZE, "0x%.4x (init)\n",
+-				 status);
+-		break;
+-	case 0x0002:
+-		count = snprintf(buf, PAGE_SIZE, "0x%.4x (active)\n",
+-				 status);
+-		break;
+-	case 0x0003:
+-		count = snprintf(buf, PAGE_SIZE, "0x%.4x (suspended)\n",
+-				 status);
+-		break;
+-	case 0x0004:
+-		count = snprintf(buf, PAGE_SIZE, "0x%.4x (asleep)\n",
+-				 status);
+-		break;
+-	default:
+-		count = snprintf(buf, PAGE_SIZE, "0x%.4x (unknown)\n",
+-				 status);
+-		break;
+-	}
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(microcodestatus, 0444,
+-		   bcm43xx_attr_microcode_show,
+-		   NULL);
+-
+-int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
+-{
+-	struct device *dev = &bcm->pci_dev->dev;
+-	int err;
+-
+-	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+-
+-	err = device_create_file(dev, &dev_attr_sprom);
+-	if (err)
+-		goto out;
+-	err = device_create_file(dev, &dev_attr_interference);
+-	if (err)
+-		goto err_remove_sprom;
+-	err = device_create_file(dev, &dev_attr_shortpreamble);
+-	if (err)
+-		goto err_remove_interfmode;
+-	err = device_create_file(dev, &dev_attr_phymode);
+-	if (err)
+-		goto err_remove_shortpreamble;
+-	err = device_create_file(dev, &dev_attr_microcodestatus);
+-	if (err)
+-		goto err_remove_phymode;
+-
+-out:
+-	return err;
+-err_remove_phymode:
+-	device_remove_file(dev, &dev_attr_phymode);
+-err_remove_shortpreamble:
+-	device_remove_file(dev, &dev_attr_shortpreamble);
+-err_remove_interfmode:
+-	device_remove_file(dev, &dev_attr_interference);
+-err_remove_sprom:
+-	device_remove_file(dev, &dev_attr_sprom);
+-	goto out;
+-}
+-
+-void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
+-{
+-	struct device *dev = &bcm->pci_dev->dev;
+-
+-	device_remove_file(dev, &dev_attr_microcodestatus);
+-	device_remove_file(dev, &dev_attr_phymode);
+-	device_remove_file(dev, &dev_attr_shortpreamble);
+-	device_remove_file(dev, &dev_attr_interference);
+-	device_remove_file(dev, &dev_attr_sprom);
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
+deleted file mode 100644
+index cc701df..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
++++ /dev/null
+@@ -1,9 +0,0 @@
+-#ifndef BCM43xx_SYSFS_H_
+-#define BCM43xx_SYSFS_H_
+-
+-struct bcm43xx_private;
+-
+-int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
+-void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm);
+-
+-#endif /* BCM43xx_SYSFS_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+deleted file mode 100644
+index 6acfdc4..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
++++ /dev/null
+@@ -1,1035 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-  GNU General Public License for more details.
+-
+-  You should have received a copy of the GNU General Public License
+-  along with this program; see the file COPYING.  If not, write to
+-  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+-  Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/wireless.h>
+-#include <net/iw_handler.h>
+-#include <net/ieee80211softmac.h>
+-#include <net/ieee80211softmac_wx.h>
+-#include <linux/capability.h>
+-#include <linux/delay.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_wx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx_phy.h"
+-
+-
+-/* The WIRELESS_EXT version, which is implemented by this driver. */
+-#define BCM43xx_WX_VERSION	18
+-
+-#define MAX_WX_STRING		80
+-
+-static int bcm43xx_wx_get_name(struct net_device *net_dev,
+-                               struct iw_request_info *info,
+-			       union iwreq_data *data,
+-			       char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int i;
+-	struct bcm43xx_phyinfo *phy;
+-	char suffix[7] = { 0 };
+-	int have_a = 0, have_b = 0, have_g = 0;
+-
+-	mutex_lock(&bcm->mutex);
+-	for (i = 0; i < bcm->nr_80211_available; i++) {
+-		phy = &(bcm->core_80211_ext[i].phy);
+-		switch (phy->type) {
+-		case BCM43xx_PHYTYPE_A:
+-			have_a = 1;
+-			break;
+-		case BCM43xx_PHYTYPE_G:
+-			have_g = 1;
+-		case BCM43xx_PHYTYPE_B:
+-			have_b = 1;
+-			break;
+-		default:
+-			assert(0);
+-		}
+-	}
+-	mutex_unlock(&bcm->mutex);
+-
+-	i = 0;
+-	if (have_a) {
+-		suffix[i++] = 'a';
+-		suffix[i++] = '/';
+-	}
+-	if (have_b) {
+-		suffix[i++] = 'b';
+-		suffix[i++] = '/';
+-	}
+-	if (have_g) {
+-		suffix[i++] = 'g';
+-		suffix[i++] = '/';
+-	}
+-	if (i != 0) 
+-		suffix[i - 1] = '\0';
+-
+-	snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
+-				      struct iw_request_info *info,
+-				      union iwreq_data *data,
+-				      char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	unsigned long flags;
+-	u8 channel;
+-	s8 expon;
+-	int freq;
+-	int err = -EINVAL;
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+-	if ((data->freq.e == 0) &&
+-	    (data->freq.m >= 0) && (data->freq.m <= 1000)) {
+-		channel = data->freq.m;
+-		freq = bcm43xx_channel_to_freq(bcm, channel);
+-	} else {
+-		freq = data->freq.m;
+-		expon = 6 - data->freq.e;
+-		while (--expon >= 0)    /* scale down the frequency to MHz */
+-			freq /= 10;
+-		assert(freq > 1000);
+-		channel = bcm43xx_freq_to_channel(bcm, freq);
+-	}
+-	if (!ieee80211_is_valid_channel(bcm->ieee, channel))
+-		goto out_unlock;
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+-		//ieee80211softmac_disassoc(softmac, $REASON);
+-		bcm43xx_mac_suspend(bcm);
+-		err = bcm43xx_radio_selectchannel(bcm, channel, 0);
+-		bcm43xx_mac_enable(bcm);
+-	} else {
+-		bcm43xx_current_radio(bcm)->initial_channel = channel;
+-		err = 0;
+-	}
+-out_unlock:
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return err;
+-}
+-
+-static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
+-				      struct iw_request_info *info,
+-				      union iwreq_data *data,
+-				      char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	struct bcm43xx_radioinfo *radio;
+-	int err = -ENODEV;
+-	u16 channel;
+-
+-	mutex_lock(&bcm->mutex);
+-	radio = bcm43xx_current_radio(bcm);
+-	channel = radio->channel;
+-	if (channel == 0xFF) {
+-		channel = radio->initial_channel;
+-		if (channel == 0xFF)
+-			goto out_unlock;
+-	}
+-	assert(channel > 0 && channel <= 1000);
+-	data->freq.e = 1;
+-	data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
+-	data->freq.flags = 1;
+-
+-	err = 0;
+-out_unlock:
+-	mutex_unlock(&bcm->mutex);
+-
+-	return err;
+-}
+-
+-static int bcm43xx_wx_set_mode(struct net_device *net_dev,
+-			       struct iw_request_info *info,
+-			       union iwreq_data *data,
+-			       char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	unsigned long flags;
+-	int mode;
+-
+-	mode = data->mode;
+-	if (mode == IW_MODE_AUTO)
+-		mode = BCM43xx_INITIAL_IWMODE;
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+-		if (bcm->ieee->iw_mode != mode)
+-			bcm43xx_set_iwmode(bcm, mode);
+-	} else
+-		bcm->ieee->iw_mode = mode;
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_get_mode(struct net_device *net_dev,
+-			       struct iw_request_info *info,
+-			       union iwreq_data *data,
+-			       char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+-	mutex_lock(&bcm->mutex);
+-	data->mode = bcm->ieee->iw_mode;
+-	mutex_unlock(&bcm->mutex);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
+-				      struct iw_request_info *info,
+-				      union iwreq_data *data,
+-				      char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	struct iw_range *range = (struct iw_range *)extra;
+-	const struct ieee80211_geo *geo;
+-	int i, j;
+-	struct bcm43xx_phyinfo *phy;
+-
+-	data->data.length = sizeof(*range);
+-	memset(range, 0, sizeof(*range));
+-
+-	//TODO: What about 802.11b?
+-	/* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
+-	range->throughput = 27 * 1000 * 1000;
+-
+-	range->max_qual.qual = 100;
+-	range->max_qual.level = 146; /* set floor at -110 dBm (146 - 256) */
+-	range->max_qual.noise = 146;
+-	range->max_qual.updated = IW_QUAL_ALL_UPDATED;
+-
+-	range->avg_qual.qual = 50;
+-	range->avg_qual.level = 0;
+-	range->avg_qual.noise = 0;
+-	range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
+-
+-	range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
+-	range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
+-	range->min_frag = MIN_FRAG_THRESHOLD;
+-	range->max_frag = MAX_FRAG_THRESHOLD;
+-
+-	range->encoding_size[0] = 5;
+-	range->encoding_size[1] = 13;
+-	range->num_encoding_sizes = 2;
+-	range->max_encoding_tokens = WEP_KEYS;
+-
+-	range->we_version_compiled = WIRELESS_EXT;
+-	range->we_version_source = BCM43xx_WX_VERSION;
+-
+-	range->enc_capa = IW_ENC_CAPA_WPA |
+-			  IW_ENC_CAPA_WPA2 |
+-			  IW_ENC_CAPA_CIPHER_TKIP |
+-			  IW_ENC_CAPA_CIPHER_CCMP;
+-
+-	mutex_lock(&bcm->mutex);
+-	phy = bcm43xx_current_phy(bcm);
+-
+-	range->num_bitrates = 0;
+-	i = 0;
+-	if (phy->type == BCM43xx_PHYTYPE_A ||
+-	    phy->type == BCM43xx_PHYTYPE_G) {
+-		range->num_bitrates = 8;
+-		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
+-		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
+-		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
+-		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
+-		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
+-		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
+-		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
+-		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
+-	}
+-	if (phy->type == BCM43xx_PHYTYPE_B ||
+-	    phy->type == BCM43xx_PHYTYPE_G) {
+-		range->num_bitrates += 4;
+-		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
+-		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
+-		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
+-		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
+-	}
+-
+-	geo = ieee80211_get_geo(bcm->ieee);
+-	range->num_channels = geo->a_channels + geo->bg_channels;
+-	j = 0;
+-	for (i = 0; i < geo->a_channels; i++) {
+-		if (j == IW_MAX_FREQUENCIES)
+-			break;
+-		range->freq[j].i = j + 1;
+-		range->freq[j].m = geo->a[i].freq * 100000;
+-		range->freq[j].e = 1;
+-		j++;
+-	}
+-	for (i = 0; i < geo->bg_channels; i++) {
+-		if (j == IW_MAX_FREQUENCIES)
+-			break;
+-		range->freq[j].i = j + 1;
+-		range->freq[j].m = geo->bg[i].freq * 100000;
+-		range->freq[j].e = 1;
+-		j++;
+-	}
+-	range->num_frequency = j;
+-
+-	mutex_unlock(&bcm->mutex);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_set_nick(struct net_device *net_dev,
+-			       struct iw_request_info *info,
+-			       union iwreq_data *data,
+-			       char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	size_t len;
+-
+-	mutex_lock(&bcm->mutex);
+-	len =  min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
+-	memcpy(bcm->nick, extra, len);
+-	bcm->nick[len] = '\0';
+-	mutex_unlock(&bcm->mutex);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_get_nick(struct net_device *net_dev,
+-			       struct iw_request_info *info,
+-			       union iwreq_data *data,
+-			       char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	size_t len;
+-
+-	mutex_lock(&bcm->mutex);
+-	len = strlen(bcm->nick);
+-	memcpy(extra, bcm->nick, len);
+-	data->data.length = (__u16)len;
+-	data->data.flags = 1;
+-	mutex_unlock(&bcm->mutex);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_set_rts(struct net_device *net_dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *data,
+-			      char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	unsigned long flags;
+-	int err = -EINVAL;
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (data->rts.disabled) {
+-		bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
+-		err = 0;
+-	} else {
+-		if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
+-		    data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
+-			bcm->rts_threshold = data->rts.value;
+-			err = 0;
+-		}
+-	}
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return err;
+-}
+-
+-static int bcm43xx_wx_get_rts(struct net_device *net_dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *data,
+-			      char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+-	mutex_lock(&bcm->mutex);
+-	data->rts.value = bcm->rts_threshold;
+-	data->rts.fixed = 0;
+-	data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_set_frag(struct net_device *net_dev,
+-			       struct iw_request_info *info,
+-			       union iwreq_data *data,
+-			       char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	unsigned long flags;
+-	int err = -EINVAL;
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (data->frag.disabled) {
+-		bcm->ieee->fts = MAX_FRAG_THRESHOLD;
+-		err = 0;
+-	} else {
+-		if (data->frag.value >= MIN_FRAG_THRESHOLD &&
+-		    data->frag.value <= MAX_FRAG_THRESHOLD) {
+-			bcm->ieee->fts = data->frag.value & ~0x1;
+-			err = 0;
+-		}
+-	}
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return err;
+-}
+-
+-static int bcm43xx_wx_get_frag(struct net_device *net_dev,
+-			       struct iw_request_info *info,
+-			       union iwreq_data *data,
+-			       char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+-	mutex_lock(&bcm->mutex);
+-	data->frag.value = bcm->ieee->fts;
+-	data->frag.fixed = 0;
+-	data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
+-				    struct iw_request_info *info,
+-				    union iwreq_data *data,
+-				    char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	struct bcm43xx_radioinfo *radio;
+-	struct bcm43xx_phyinfo *phy;
+-	unsigned long flags;
+-	int err = -ENODEV;
+-	u16 maxpower;
+-
+-	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
+-		printk(KERN_ERR PFX "TX power not in dBm.\n");
+-		return -EOPNOTSUPP;
+-	}
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
+-		goto out_unlock;
+-	radio = bcm43xx_current_radio(bcm);
+-	phy = bcm43xx_current_phy(bcm);
+-	if (data->txpower.disabled != (!(radio->enabled))) {
+-		if (data->txpower.disabled)
+-			bcm43xx_radio_turn_off(bcm);
+-		else
+-			bcm43xx_radio_turn_on(bcm);
+-	}
+-	if (data->txpower.value > 0) {
+-		/* desired and maxpower dBm values are in Q5.2 */
+-		if (phy->type == BCM43xx_PHYTYPE_A)
+-			maxpower = bcm->sprom.maxpower_aphy;
+-		else
+-			maxpower = bcm->sprom.maxpower_bgphy;
+-		radio->txpower_desired = limit_value(data->txpower.value << 2,
+-						     0, maxpower);
+-		bcm43xx_phy_xmitpower(bcm);
+-	}
+-	err = 0;
+-
+-out_unlock:
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return err;
+-}
+-
+-static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
+-				    struct iw_request_info *info,
+-				    union iwreq_data *data,
+-				    char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	struct bcm43xx_radioinfo *radio;
+-	int err = -ENODEV;
+-
+-	mutex_lock(&bcm->mutex);
+-	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
+-		goto out_unlock;
+-	radio = bcm43xx_current_radio(bcm);
+-	/* desired dBm value is in Q5.2 */
+-	data->txpower.value = radio->txpower_desired >> 2;
+-	data->txpower.fixed = 1;
+-	data->txpower.flags = IW_TXPOW_DBM;
+-	data->txpower.disabled = !(radio->enabled);
+-
+-	err = 0;
+-out_unlock:
+-	mutex_unlock(&bcm->mutex);
+-
+-	return err;
+-}
+-
+-static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
+-				   struct iw_request_info *info,
+-				   union iwreq_data *data,
+-				   char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int err;
+-
+-	err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
+-
+-	return err;
+-}
+-
+-static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
+-                                   struct iw_request_info *info,
+-                                   union iwreq_data *data,
+-                                   char *extra)
+-{
+-        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-        int err;
+-
+-        err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
+-
+-        return err;
+-}
+-
+-static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
+-				   struct iw_request_info *info,
+-				   union iwreq_data *data,
+-				   char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int err;
+-
+-	err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
+-
+-	return err;
+-}
+-
+-static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
+-                                   struct iw_request_info *info,
+-                                   union iwreq_data *data,
+-                                   char *extra)
+-{
+-        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-        int err;
+-
+-        err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
+-
+-        return err;
+-}
+-
+-static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
+-				     struct iw_request_info *info,
+-				     union iwreq_data *data,
+-				     char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	unsigned long flags;
+-	int mode, err = 0;
+-
+-	mode = *((int *)extra);
+-	switch (mode) {
+-	case 0:
+-		mode = BCM43xx_RADIO_INTERFMODE_NONE;
+-		break;
+-	case 1:
+-		mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
+-		break;
+-	case 2:
+-		mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+-		break;
+-	case 3:
+-		mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
+-		break;
+-	default:
+-		printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
+-				    "0 => None,  1 => Non-WLAN,  2 => WLAN,  "
+-				    "3 => Auto-WLAN\n");
+-		return -EINVAL;
+-	}
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+-		err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
+-		if (err) {
+-			printk(KERN_ERR PFX "Interference Mitigation not "
+-					    "supported by device\n");
+-		}
+-	} else {
+-		if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
+-			printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
+-					    "not supported while the interface is down.\n");
+-			err = -ENODEV;
+-		} else
+-			bcm43xx_current_radio(bcm)->interfmode = mode;
+-	}
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return err;
+-}
+-
+-static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
+-				     struct iw_request_info *info,
+-				     union iwreq_data *data,
+-				     char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int mode;
+-
+-	mutex_lock(&bcm->mutex);
+-	mode = bcm43xx_current_radio(bcm)->interfmode;
+-	mutex_unlock(&bcm->mutex);
+-
+-	switch (mode) {
+-	case BCM43xx_RADIO_INTERFMODE_NONE:
+-		strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
+-		break;
+-	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+-		strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
+-		break;
+-	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+-		strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
+-		break;
+-	default:
+-		assert(0);
+-	}
+-	data->data.length = strlen(extra) + 1;
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
+-					struct iw_request_info *info,
+-					union iwreq_data *data,
+-					char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	unsigned long flags;
+-	int on;
+-
+-	on = *((int *)extra);
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	bcm->short_preamble = !!on;
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
+-					struct iw_request_info *info,
+-					union iwreq_data *data,
+-					char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int on;
+-
+-	mutex_lock(&bcm->mutex);
+-	on = bcm->short_preamble;
+-	mutex_unlock(&bcm->mutex);
+-
+-	if (on)
+-		strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
+-	else
+-		strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
+-	data->data.length = strlen(extra) + 1;
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
+-				       struct iw_request_info *info,
+-				       union iwreq_data *data,
+-				       char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	unsigned long flags;
+-	int on;
+-	
+-	on = *((int *)extra);
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	bcm->ieee->host_encrypt = !!on;
+-	bcm->ieee->host_decrypt = !!on;
+-	bcm->ieee->host_build_iv = !on;
+-	bcm->ieee->host_strip_iv_icv = !on;
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
+-				       struct iw_request_info *info,
+-				       union iwreq_data *data,
+-				       char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int on;
+-
+-	mutex_lock(&bcm->mutex);
+-	on = bcm->ieee->host_encrypt;
+-	mutex_unlock(&bcm->mutex);
+-
+-	if (on)
+-		strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
+-	else
+-		strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
+-	data->data.length = strlen(extra + 1);
+-
+-	return 0;
+-}
+-
+-/* Enough buffer to hold a hexdump of the sprom data. */
+-#define SPROM_BUFFERSIZE	512
+-
+-static int sprom2hex(const u16 *sprom, char *dump)
+-{
+-	int i, pos = 0;
+-
+-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+-		pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
+-				"%04X", swab16(sprom[i]) & 0xFFFF);
+-	}
+-
+-	return pos + 1;
+-}
+-
+-static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
+-{
+-	char tmp[5] = { 0 };
+-	int cnt = 0;
+-	unsigned long parsed;
+-
+-	if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+-		return -EINVAL;
+-	while (cnt < BCM43xx_SPROM_SIZE) {
+-		memcpy(tmp, dump, 4);
+-		dump += 4;
+-		parsed = simple_strtoul(tmp, NULL, 16);
+-		sprom[cnt++] = swab16((u16)parsed);
+-	}
+-
+-	return 0;
+-}
+-
+-static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
+-				 struct iw_request_info *info,
+-				 union iwreq_data *data,
+-				 char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int err = -EPERM;
+-	u16 *sprom;
+-	unsigned long flags;
+-
+-	if (!capable(CAP_SYS_RAWIO))
+-		goto out;
+-
+-	err = -ENOMEM;
+-	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+-			GFP_KERNEL);
+-	if (!sprom)
+-		goto out;
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	err = -ENODEV;
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
+-		err = bcm43xx_sprom_read(bcm, sprom);
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-	if (!err)
+-		data->data.length = sprom2hex(sprom, extra);
+-	kfree(sprom);
+-out:
+-	return err;
+-}
+-
+-static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
+-				  struct iw_request_info *info,
+-				  union iwreq_data *data,
+-				  char *extra)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	int err = -EPERM;
+-	u16 *sprom;
+-	unsigned long flags;
+-	char *input;
+-	unsigned int len;
+-
+-	if (!capable(CAP_SYS_RAWIO))
+-		goto out;
+-
+-	err = -ENOMEM;
+-	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+-			GFP_KERNEL);
+-	if (!sprom)
+-		goto out;
+-
+-	len = data->data.length;
+-	extra[len - 1] = '\0';
+-	input = strchr(extra, ':');
+-	if (input) {
+-		input++;
+-		len -= input - extra;
+-	} else
+-		input = extra;
+-	err = hex2sprom(sprom, input, len);
+-	if (err)
+-		goto out_kfree;
+-
+-	mutex_lock(&bcm->mutex);
+-	spin_lock_irqsave(&bcm->irq_lock, flags);
+-	spin_lock(&bcm->leds_lock);
+-	err = -ENODEV;
+-	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
+-		err = bcm43xx_sprom_write(bcm, sprom);
+-	spin_unlock(&bcm->leds_lock);
+-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-	mutex_unlock(&bcm->mutex);
+-out_kfree:
+-	kfree(sprom);
+-out:
+-	return err;
+-}
+-
+-/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
+-
+-static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
+-{
+-	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+-	struct iw_statistics *wstats;
+-	struct ieee80211_network *network = NULL;
+-	static int tmp_level = 0;
+-	static int tmp_qual = 0;
+-	unsigned long flags;
+-
+-	wstats = &bcm->stats.wstats;
+-	if (!mac->associnfo.associated) {
+-		wstats->miss.beacon = 0;
+-//		bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
+-		wstats->discard.retries = 0;
+-//		bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
+-		wstats->discard.nwid = 0;
+-//		bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
+-		wstats->discard.code = 0;
+-//		bcm->ieee->ieee_stats.rx_fragments = 0;  // FIXME: same here
+-		wstats->discard.fragment = 0;
+-		wstats->discard.misc = 0;
+-		wstats->qual.qual = 0;
+-		wstats->qual.level = 0;
+-		wstats->qual.noise = 0;
+-		wstats->qual.updated = 7;
+-		wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+-		return wstats;
+-	}
+-	/* fill in the real statistics when iface associated */
+-	spin_lock_irqsave(&mac->ieee->lock, flags);
+-	list_for_each_entry(network, &mac->ieee->network_list, list) {
+-		if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) {
+-			if (!tmp_level)	{	/* get initial values */
+-				tmp_level = network->stats.signal;
+-				tmp_qual = network->stats.rssi;
+-			} else {		/* smooth results */
+-				tmp_level = (15 * tmp_level + network->stats.signal)/16;
+-				tmp_qual = (15 * tmp_qual + network->stats.rssi)/16;
+-			}
+-			break;
+-		}
+-	}
+-	spin_unlock_irqrestore(&mac->ieee->lock, flags);
+-	wstats->qual.level = tmp_level;
+-	wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX;
+-	wstats->qual.noise = bcm->stats.noise;
+-	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+-	wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
+-	wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
+-	wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
+-	wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
+-	wstats->discard.misc = 0;	// FIXME
+-	wstats->miss.beacon = 0;	// FIXME
+-	return wstats;
+-}
+-
+-
+-#ifdef WX
+-# undef WX
+-#endif
+-#define WX(ioctl)  [(ioctl) - SIOCSIWCOMMIT]
+-static const iw_handler bcm43xx_wx_handlers[] = {
+-	/* Wireless Identification */
+-	WX(SIOCGIWNAME)		= bcm43xx_wx_get_name,
+-	/* Basic operations */
+-	WX(SIOCSIWFREQ)		= bcm43xx_wx_set_channelfreq,
+-	WX(SIOCGIWFREQ)		= bcm43xx_wx_get_channelfreq,
+-	WX(SIOCSIWMODE)		= bcm43xx_wx_set_mode,
+-	WX(SIOCGIWMODE)		= bcm43xx_wx_get_mode,
+-	/* Informative stuff */
+-	WX(SIOCGIWRANGE)	= bcm43xx_wx_get_rangeparams,
+-	/* Access Point manipulation */
+-	WX(SIOCSIWAP)           = ieee80211softmac_wx_set_wap,
+-	WX(SIOCGIWAP)           = ieee80211softmac_wx_get_wap,
+-	WX(SIOCSIWSCAN)		= ieee80211softmac_wx_trigger_scan,
+-	WX(SIOCGIWSCAN)		= ieee80211softmac_wx_get_scan_results,
+-	/* 802.11 specific support */
+-	WX(SIOCSIWESSID)	= ieee80211softmac_wx_set_essid,
+-	WX(SIOCGIWESSID)	= ieee80211softmac_wx_get_essid,
+-	WX(SIOCSIWNICKN)	= bcm43xx_wx_set_nick,
+-	WX(SIOCGIWNICKN)	= bcm43xx_wx_get_nick,
+-	/* Other parameters */
+-	WX(SIOCSIWRATE)		= ieee80211softmac_wx_set_rate,
+-	WX(SIOCGIWRATE)		= ieee80211softmac_wx_get_rate,
+-	WX(SIOCSIWRTS)		= bcm43xx_wx_set_rts,
+-	WX(SIOCGIWRTS)		= bcm43xx_wx_get_rts,
+-	WX(SIOCSIWFRAG)		= bcm43xx_wx_set_frag,
+-	WX(SIOCGIWFRAG)		= bcm43xx_wx_get_frag,
+-	WX(SIOCSIWTXPOW)	= bcm43xx_wx_set_xmitpower,
+-	WX(SIOCGIWTXPOW)	= bcm43xx_wx_get_xmitpower,
+-//TODO	WX(SIOCSIWRETRY)	= bcm43xx_wx_set_retry,
+-//TODO	WX(SIOCGIWRETRY)	= bcm43xx_wx_get_retry,
+-	/* Encoding */
+-	WX(SIOCSIWENCODE)	= bcm43xx_wx_set_encoding,
+-	WX(SIOCGIWENCODE)	= bcm43xx_wx_get_encoding,
+-	WX(SIOCSIWENCODEEXT)	= bcm43xx_wx_set_encodingext,
+-	WX(SIOCGIWENCODEEXT)	= bcm43xx_wx_get_encodingext,
+-	/* Power saving */
+-//TODO	WX(SIOCSIWPOWER)	= bcm43xx_wx_set_power,
+-//TODO	WX(SIOCGIWPOWER)	= bcm43xx_wx_get_power,
+-	WX(SIOCSIWGENIE)	= ieee80211softmac_wx_set_genie,
+-	WX(SIOCGIWGENIE)	= ieee80211softmac_wx_get_genie,
+-	WX(SIOCSIWAUTH)		= ieee80211_wx_set_auth,
+-	WX(SIOCGIWAUTH)		= ieee80211_wx_get_auth,
+-};
+-#undef WX
+-
+-static const iw_handler bcm43xx_priv_wx_handlers[] = {
+-	/* Set Interference Mitigation Mode. */
+-	bcm43xx_wx_set_interfmode,
+-	/* Get Interference Mitigation Mode. */
+-	bcm43xx_wx_get_interfmode,
+-	/* Enable/Disable Short Preamble mode. */
+-	bcm43xx_wx_set_shortpreamble,
+-	/* Get Short Preamble mode. */
+-	bcm43xx_wx_get_shortpreamble,
+-	/* Enable/Disable Software Encryption mode */
+-	bcm43xx_wx_set_swencryption,
+-	/* Get Software Encryption mode */
+-	bcm43xx_wx_get_swencryption,
+-	/* Write SRPROM data. */
+-	bcm43xx_wx_sprom_write,
+-	/* Read SPROM data. */
+-	bcm43xx_wx_sprom_read,
+-};
+-
+-#define PRIV_WX_SET_INTERFMODE		(SIOCIWFIRSTPRIV + 0)
+-#define PRIV_WX_GET_INTERFMODE		(SIOCIWFIRSTPRIV + 1)
+-#define PRIV_WX_SET_SHORTPREAMBLE	(SIOCIWFIRSTPRIV + 2)
+-#define PRIV_WX_GET_SHORTPREAMBLE	(SIOCIWFIRSTPRIV + 3)
+-#define PRIV_WX_SET_SWENCRYPTION	(SIOCIWFIRSTPRIV + 4)
+-#define PRIV_WX_GET_SWENCRYPTION	(SIOCIWFIRSTPRIV + 5)
+-#define PRIV_WX_SPROM_WRITE		(SIOCIWFIRSTPRIV + 6)
+-#define PRIV_WX_SPROM_READ		(SIOCIWFIRSTPRIV + 7)
+-
+-#define PRIV_WX_DUMMY(ioctl)	\
+-	{					\
+-		.cmd		= (ioctl),	\
+-		.name		= "__unused"	\
+-	}
+-
+-static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
+-	{
+-		.cmd		= PRIV_WX_SET_INTERFMODE,
+-		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+-		.name		= "set_interfmode",
+-	},
+-	{
+-		.cmd		= PRIV_WX_GET_INTERFMODE,
+-		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+-		.name		= "get_interfmode",
+-	},
+-	{
+-		.cmd		= PRIV_WX_SET_SHORTPREAMBLE,
+-		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+-		.name		= "set_shortpreamb",
+-	},
+-	{
+-		.cmd		= PRIV_WX_GET_SHORTPREAMBLE,
+-		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+-		.name		= "get_shortpreamb",
+-	},
+-	{
+-		.cmd		= PRIV_WX_SET_SWENCRYPTION,
+-		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+-		.name		= "set_swencrypt",
+-	},
+-	{
+-		.cmd		= PRIV_WX_GET_SWENCRYPTION,
+-		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+-		.name		= "get_swencrypt",
+-	},
+-	{
+-		.cmd		= PRIV_WX_SPROM_WRITE,
+-		.set_args	= IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
+-		.name		= "write_sprom",
+-	},
+-	{
+-		.cmd		= PRIV_WX_SPROM_READ,
+-		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
+-		.name		= "read_sprom",
+-	},
+-};
+-
+-const struct iw_handler_def bcm43xx_wx_handlers_def = {
+-	.standard		= bcm43xx_wx_handlers,
+-	.num_standard		= ARRAY_SIZE(bcm43xx_wx_handlers),
+-	.num_private		= ARRAY_SIZE(bcm43xx_priv_wx_handlers),
+-	.num_private_args	= ARRAY_SIZE(bcm43xx_priv_wx_args),
+-	.private		= bcm43xx_priv_wx_handlers,
+-	.private_args		= bcm43xx_priv_wx_args,
+-	.get_wireless_stats	= bcm43xx_get_wireless_stats,
+-};
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
+deleted file mode 100644
+index 1f29ff3..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  Some parts of the code in this file are derived from the ipw2200
+-  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 BCM43xx_WX_H_
+-#define BCM43xx_WX_H_
+-
+-extern const struct iw_handler_def bcm43xx_wx_handlers_def;
+-
+-#endif /* BCM43xx_WX_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+deleted file mode 100644
+index f79fe11..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
++++ /dev/null
+@@ -1,565 +0,0 @@
+-/*
+-
+-  Broadcom BCM43xx wireless driver
+-
+-  Transmission (TX/RX) related functions.
+-
+-  Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+-                     Stefano Brivio <st3 at riseup.net>
+-                     Michael Buesch <mbuesch at freenet.de>
+-                     Danny van Dyk <kugelfang at gentoo.org>
+-                     Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+-  This program is free software; you can redistribute it and/or modify
+-  it under the terms of the GNU General Public License as published by
+-  the Free Software Foundation; either version 2 of the License, or
+-  (at your option) any later version.
+-
+-  This program is distributed in the hope that it will be useful,
+-  but WITHOUT ANY WARRANTY; without even the implied warranty of
+-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 "bcm43xx_xmit.h"
+-
+-#include <linux/etherdevice.h>
+-
+-
+-/* Extract the bitrate out of a CCK PLCP header. */
+-static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
+-{
+-	switch (plcp->raw[0]) {
+-	case 0x0A:
+-		return IEEE80211_CCK_RATE_1MB;
+-	case 0x14:
+-		return IEEE80211_CCK_RATE_2MB;
+-	case 0x37:
+-		return IEEE80211_CCK_RATE_5MB;
+-	case 0x6E:
+-		return IEEE80211_CCK_RATE_11MB;
+-	}
+-	assert(0);
+-	return 0;
+-}
+-
+-/* Extract the bitrate out of an OFDM PLCP header. */
+-static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
+-{
+-	switch (plcp->raw[0] & 0xF) {
+-	case 0xB:
+-		return IEEE80211_OFDM_RATE_6MB;
+-	case 0xF:
+-		return IEEE80211_OFDM_RATE_9MB;
+-	case 0xA:
+-		return IEEE80211_OFDM_RATE_12MB;
+-	case 0xE:
+-		return IEEE80211_OFDM_RATE_18MB;
+-	case 0x9:
+-		return IEEE80211_OFDM_RATE_24MB;
+-	case 0xD:
+-		return IEEE80211_OFDM_RATE_36MB;
+-	case 0x8:
+-		return IEEE80211_OFDM_RATE_48MB;
+-	case 0xC:
+-		return IEEE80211_OFDM_RATE_54MB;
+-	}
+-	assert(0);
+-	return 0;
+-}
+-
+-u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
+-{
+-	switch (bitrate) {
+-	case IEEE80211_CCK_RATE_1MB:
+-		return 0x0A;
+-	case IEEE80211_CCK_RATE_2MB:
+-		return 0x14;
+-	case IEEE80211_CCK_RATE_5MB:
+-		return 0x37;
+-	case IEEE80211_CCK_RATE_11MB:
+-		return 0x6E;
+-	}
+-	assert(0);
+-	return 0;
+-}
+-
+-u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
+-{
+-	switch (bitrate) {
+-	case IEEE80211_OFDM_RATE_6MB:
+-		return 0xB;
+-	case IEEE80211_OFDM_RATE_9MB:
+-		return 0xF;
+-	case IEEE80211_OFDM_RATE_12MB:
+-		return 0xA;
+-	case IEEE80211_OFDM_RATE_18MB:
+-		return 0xE;
+-	case IEEE80211_OFDM_RATE_24MB:
+-		return 0x9;
+-	case IEEE80211_OFDM_RATE_36MB:
+-		return 0xD;
+-	case IEEE80211_OFDM_RATE_48MB:
+-		return 0x8;
+-	case IEEE80211_OFDM_RATE_54MB:
+-		return 0xC;
+-	}
+-	assert(0);
+-	return 0;
+-}
+-
+-static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
+-				      const u16 octets, const u8 bitrate,
+-				      const int ofdm_modulation)
+-{
+-	__le32 *data = &(plcp->data);
+-	__u8 *raw = plcp->raw;
+-
+-	if (ofdm_modulation) {
+-		u32 val = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
+-		assert(!(octets & 0xF000));
+-		val |= (octets << 5);
+-		*data = cpu_to_le32(val);
+-	} else {
+-		u32 plen;
+-
+-		plen = octets * 16 / bitrate;
+-		if ((octets * 16 % bitrate) > 0) {
+-			plen++;
+-			if ((bitrate == IEEE80211_CCK_RATE_11MB)
+-			    && ((octets * 8 % 11) < 4)) {
+-				raw[1] = 0x84;
+-			} else
+-				raw[1] = 0x04;
+-		} else
+-			raw[1] = 0x04;
+-		*data |= cpu_to_le32(plen << 16);
+-		raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
+-	}
+-}
+-
+-static u8 bcm43xx_calc_fallback_rate(u8 bitrate)
+-{
+-	switch (bitrate) {
+-	case IEEE80211_CCK_RATE_1MB:
+-		return IEEE80211_CCK_RATE_1MB;
+-	case IEEE80211_CCK_RATE_2MB:
+-		return IEEE80211_CCK_RATE_1MB;
+-	case IEEE80211_CCK_RATE_5MB:
+-		return IEEE80211_CCK_RATE_2MB;
+-	case IEEE80211_CCK_RATE_11MB:
+-		return IEEE80211_CCK_RATE_5MB;
+-	case IEEE80211_OFDM_RATE_6MB:
+-		return IEEE80211_CCK_RATE_5MB;
+-	case IEEE80211_OFDM_RATE_9MB:
+-		return IEEE80211_OFDM_RATE_6MB;
+-	case IEEE80211_OFDM_RATE_12MB:
+-		return IEEE80211_OFDM_RATE_9MB;
+-	case IEEE80211_OFDM_RATE_18MB:
+-		return IEEE80211_OFDM_RATE_12MB;
+-	case IEEE80211_OFDM_RATE_24MB:
+-		return IEEE80211_OFDM_RATE_18MB;
+-	case IEEE80211_OFDM_RATE_36MB:
+-		return IEEE80211_OFDM_RATE_24MB;
+-	case IEEE80211_OFDM_RATE_48MB:
+-		return IEEE80211_OFDM_RATE_36MB;
+-	case IEEE80211_OFDM_RATE_54MB:
+-		return IEEE80211_OFDM_RATE_48MB;
+-	}
+-	assert(0);
+-	return 0;
+-}
+-
+-static
+-__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,
+-				u8 bitrate)
+-{
+-	const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);
+-	__le16 duration_id = wireless_header->duration_id;
+-
+-	switch (WLAN_FC_GET_TYPE(frame_ctl)) {
+-	case IEEE80211_FTYPE_DATA:
+-	case IEEE80211_FTYPE_MGMT:
+-		//TODO: Steal the code from ieee80211, once it is completed there.
+-		break;
+-	case IEEE80211_FTYPE_CTL:
+-		/* Use the original duration/id. */
+-		break;
+-	default:
+-		assert(0);
+-	}
+-
+-	return duration_id;
+-}
+-
+-static inline
+-u16 ceiling_div(u16 dividend, u16 divisor)
+-{
+-	return ((dividend + divisor - 1) / divisor);
+-}
+-
+-static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,
+-				 struct bcm43xx_txhdr *txhdr,
+-				 u16 *flags,
+-				 u8 bitrate,
+-				 const struct ieee80211_hdr_4addr *wlhdr)
+-{
+-	u16 fctl;
+-	u16 dur;
+-	u8 fallback_bitrate;
+-	int ofdm_modulation;
+-	int fallback_ofdm_modulation;
+-//	u8 *sa, *da;
+-	u16 flen;
+-
+-//FIXME	sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);
+-//FIXME	da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);
+-	fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
+-	ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
+-	fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
+-
+-	flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,
+-	bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),
+-				  flen, bitrate,
+-				  !ieee80211_is_cck_rate(bitrate));
+-	bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),
+-				  flen, fallback_bitrate,
+-				  !ieee80211_is_cck_rate(fallback_bitrate));
+-	fctl = IEEE80211_FTYPE_CTL;
+-	fctl |= IEEE80211_STYPE_RTS;
+-	dur = le16_to_cpu(wlhdr->duration_id);
+-/*FIXME: should we test for dur==0 here and let it unmodified in this case?
+- *       The following assert checks for this case...
+- */
+-assert(dur);
+-/*FIXME: The duration calculation is not really correct.
+- *       I am not 100% sure which bitrate to use. We use the RTS rate here,
+- *       but this is likely to be wrong.
+- */
+-	if (phy->type == BCM43xx_PHYTYPE_A) {
+-		/* Three times SIFS */
+-		dur += 16 * 3;
+-		/* Add ACK duration. */
+-		dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
+-				   bitrate * 4);
+-		/* Add CTS duration. */
+-		dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
+-				   bitrate * 4);
+-	} else {
+-		/* Three times SIFS */
+-		dur += 10 * 3;
+-		/* Add ACK duration. */
+-		dur += ceiling_div(8 * (14 /*bytes*/) * 10,
+-				   bitrate);
+-		/* Add CTS duration. */
+-		dur += ceiling_div(8 * (14 /*bytes*/) * 10,
+-				   bitrate);
+-	}
+-
+-	txhdr->rts_cts_frame_control = cpu_to_le16(fctl);
+-	txhdr->rts_cts_dur = cpu_to_le16(dur);
+-//printk(BCM43xx_MACFMT "  " BCM43xx_MACFMT "  " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));
+-//printk(BCM43xx_MACFMT "  " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));
+-	memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!
+-//	memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);
+-
+-	*flags |= BCM43xx_TXHDRFLAG_RTSCTS;
+-	*flags |= BCM43xx_TXHDRFLAG_RTS;
+-	if (ofdm_modulation)
+-		*flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;
+-	if (fallback_ofdm_modulation)
+-		*flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;
+-}
+-				 
+-void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
+-			    struct bcm43xx_txhdr *txhdr,
+-			    const unsigned char *fragment_data,
+-			    const unsigned int fragment_len,
+-			    const int is_first_fragment,
+-			    const u16 cookie)
+-{
+-	const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;
+-	const struct ieee80211_security *secinfo = &bcm->ieee->sec;
+-	u8 bitrate;
+-	u8 fallback_bitrate;
+-	int ofdm_modulation;
+-	int fallback_ofdm_modulation;
+-	u16 plcp_fragment_len = fragment_len;
+-	u16 flags = 0;
+-	u16 control = 0;
+-	u16 wsec_rate = 0;
+-	u16 encrypt_frame;
+-	const u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl));
+-	const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT);
+-
+-	/* Now construct the TX header. */
+-	memset(txhdr, 0, sizeof(*txhdr));
+-
+-	bitrate = ieee80211softmac_suggest_txrate(bcm->softmac,
+-		is_multicast_ether_addr(wireless_header->addr1), is_mgt);
+-	ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
+-	fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
+-	fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
+-
+-	/* Set Frame Control from 80211 header. */
+-	txhdr->frame_control = wireless_header->frame_ctl;
+-	/* Copy address1 from 80211 header. */
+-	memcpy(txhdr->mac1, wireless_header->addr1, 6);
+-	/* Set the fallback duration ID. */
+-	txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header,
+-							  fallback_bitrate);
+-	/* Set the cookie (used as driver internal ID for the frame) */
+-	txhdr->cookie = cpu_to_le16(cookie);
+-
+-	/* Hardware appends FCS. */
+-	plcp_fragment_len += IEEE80211_FCS_LEN;
+-
+-	/* Hardware encryption. */
+-	encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
+-	if (encrypt_frame && !bcm->ieee->host_encrypt) {
+-		const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
+-		memcpy(txhdr->wep_iv, hdr->payload, 4);
+-		/* Hardware appends ICV. */
+-		plcp_fragment_len += 4;
+-
+-		wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
+-			     & BCM43xx_TXHDR_WSEC_ALGO_MASK;
+-		wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
+-			     & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
+-	}
+-
+-	/* Generate the PLCP header and the fallback PLCP header. */
+-	bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
+-				  plcp_fragment_len,
+-				  bitrate, ofdm_modulation);
+-	bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
+-				  fallback_bitrate, fallback_ofdm_modulation);
+-
+-	/* Set the CONTROL field */
+-	if (ofdm_modulation)
+-		control |= BCM43xx_TXHDRCTL_OFDM;
+-	if (bcm->short_preamble) //FIXME: could be the other way around, please test
+-		control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
+-	control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
+-		   & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
+-
+-	/* Set the FLAGS field */
+-	if (!is_multicast_ether_addr(wireless_header->addr1) &&
+-	    !is_broadcast_ether_addr(wireless_header->addr1))
+-		flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
+-	if (1 /* FIXME: PS poll?? */)
+-		flags |= 0x10; // FIXME: unknown meaning.
+-	if (fallback_ofdm_modulation)
+-		flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
+-	if (is_first_fragment)
+-		flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
+-
+-	/* Set WSEC/RATE field */
+-	wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
+-		     & BCM43xx_TXHDR_RATE_MASK;
+-
+-	/* Generate the RTS/CTS packet, if required. */
+-	/* FIXME: We should first try with CTS-to-self,
+-	 *        if we are on 80211g. If we get too many
+-	 *        failures (hidden nodes), we should switch back to RTS/CTS.
+-	 */
+-	if (0/*FIXME txctl->use_rts_cts*/) {
+-		bcm43xx_generate_rts(phy, txhdr, &flags,
+-				     0/*FIXME txctl->rts_cts_rate*/,
+-				     wireless_header);
+-	}
+-
+-	txhdr->flags = cpu_to_le16(flags);
+-	txhdr->control = cpu_to_le16(control);
+-	txhdr->wsec_rate = cpu_to_le16(wsec_rate);
+-}
+-
+-static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
+-				   u8 in_rssi, int ofdm,
+-				   int adjust_2053, int adjust_2050)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	s32 tmp;
+-
+-	switch (radio->version) {
+-	case 0x2050:
+-		if (ofdm) {
+-			tmp = in_rssi;
+-			if (tmp > 127)
+-				tmp -= 256;
+-			tmp *= 73;
+-			tmp /= 64;
+-			if (adjust_2050)
+-				tmp += 25;
+-			else
+-				tmp -= 3;
+-		} else {
+-			if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+-				if (in_rssi > 63)
+-					in_rssi = 63;
+-				tmp = radio->nrssi_lt[in_rssi];
+-				tmp = 31 - tmp;
+-				tmp *= -131;
+-				tmp /= 128;
+-				tmp -= 57;
+-			} else {
+-				tmp = in_rssi;
+-				tmp = 31 - tmp;
+-				tmp *= -149;
+-				tmp /= 128;
+-				tmp -= 68;
+-			}
+-			if (phy->type == BCM43xx_PHYTYPE_G &&
+-			    adjust_2050)
+-				tmp += 25;
+-		}
+-		break;
+-	case 0x2060:
+-		if (in_rssi > 127)
+-			tmp = in_rssi - 256;
+-		else
+-			tmp = in_rssi;
+-		break;
+-	default:
+-		tmp = in_rssi;
+-		tmp -= 11;
+-		tmp *= 103;
+-		tmp /= 64;
+-		if (adjust_2053)
+-			tmp -= 109;
+-		else
+-			tmp -= 83;
+-	}
+-
+-	return (s8)tmp;
+-}
+-
+-//TODO
+-#if 0
+-static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
+-					u8 in_rssi)
+-{
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	s8 ret;
+-
+-	if (phy->type == BCM43xx_PHYTYPE_A) {
+-		//TODO: Incomplete specs.
+-		ret = 0;
+-	} else
+-		ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
+-
+-	return ret;
+-}
+-#endif
+-
+-int bcm43xx_rx(struct bcm43xx_private *bcm,
+-	       struct sk_buff *skb,
+-	       struct bcm43xx_rxhdr *rxhdr)
+-{
+-	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-	struct bcm43xx_plcp_hdr4 *plcp;
+-	struct ieee80211_rx_stats stats;
+-	struct ieee80211_hdr_4addr *wlhdr;
+-	u16 frame_ctl;
+-	int is_packet_for_us = 0;
+-	int err = -EINVAL;
+-	const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
+-	const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
+-	const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
+-	const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
+-
+-	if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
+-		plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
+-		/* Skip two unknown bytes and the PLCP header. */
+-		skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
+-	} else {
+-		plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
+-		/* Skip the PLCP header. */
+-		skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
+-	}
+-	/* The SKB contains the PAYLOAD (wireless header + data)
+-	 * at this point. The FCS at the end is stripped.
+-	 */
+-
+-	memset(&stats, 0, sizeof(stats));
+-	stats.mac_time = le16_to_cpu(rxhdr->mactime);
+-	stats.rssi = rxhdr->rssi;
+-	stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
+-					      !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
+-					      !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
+-	stats.noise = bcm->stats.noise;
+-	if (is_ofdm)
+-		stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
+-	else
+-		stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
+-	stats.received_channel = radio->channel;
+-	stats.mask = IEEE80211_STATMASK_SIGNAL |
+-		     IEEE80211_STATMASK_NOISE |
+-		     IEEE80211_STATMASK_RATE |
+-		     IEEE80211_STATMASK_RSSI;
+-	if (phy->type == BCM43xx_PHYTYPE_A)
+-		stats.freq = IEEE80211_52GHZ_BAND;
+-	else
+-		stats.freq = IEEE80211_24GHZ_BAND;
+-	stats.len = skb->len;
+-
+-	bcm->stats.last_rx = jiffies;
+-	if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
+-		err = ieee80211_rx(bcm->ieee, skb, &stats);
+-		return (err == 0) ? -EINVAL : 0;
+-	}
+-
+-	wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
+-
+-	switch (bcm->ieee->iw_mode) {
+-	case IW_MODE_ADHOC:
+-		if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
+-		    memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
+-		    is_broadcast_ether_addr(wlhdr->addr1) ||
+-		    is_multicast_ether_addr(wlhdr->addr1) ||
+-		    bcm->net_dev->flags & IFF_PROMISC)
+-			is_packet_for_us = 1;
+-		break;
+-	case IW_MODE_INFRA:
+-	default:
+-		/* When receiving multicast or broadcast packets, filter out
+-		   the packets we send ourself; we shouldn't see those */
+-		if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
+-		    memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
+-		    (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
+-		     (is_broadcast_ether_addr(wlhdr->addr1) ||
+-		      is_multicast_ether_addr(wlhdr->addr1) ||
+-		      bcm->net_dev->flags & IFF_PROMISC)))
+-			is_packet_for_us = 1;
+-		break;
+-	}
+-
+-	frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
+-	switch (WLAN_FC_GET_TYPE(frame_ctl)) {
+-	case IEEE80211_FTYPE_MGMT:
+-		ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
+-		break;
+-	case IEEE80211_FTYPE_DATA:
+-		if (is_packet_for_us) {
+-			err = ieee80211_rx(bcm->ieee, skb, &stats);
+-			err = (err == 0) ? -EINVAL : 0;
+-		}
+-		break;
+-	case IEEE80211_FTYPE_CTL:
+-		break;
+-	default:
+-		assert(0);
+-		return -EINVAL;
+-	}
+-
+-	return err;
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
+deleted file mode 100644
+index 47c135a..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
++++ /dev/null
+@@ -1,150 +0,0 @@
+-#ifndef BCM43xx_XMIT_H_
+-#define BCM43xx_XMIT_H_
+-
+-#include "bcm43xx_main.h"
+-
+-
+-#define _bcm43xx_declare_plcp_hdr(size) \
+-	struct bcm43xx_plcp_hdr##size {		\
+-		union {				\
+-			__le32 data;		\
+-			__u8 raw[size];		\
+-		} __attribute__((__packed__));	\
+-	} __attribute__((__packed__))
+-
+-/* struct bcm43xx_plcp_hdr4 */
+-_bcm43xx_declare_plcp_hdr(4);
+-/* struct bcm43xx_plcp_hdr6 */
+-_bcm43xx_declare_plcp_hdr(6);
+-
+-#undef _bcm43xx_declare_plcp_hdr
+-
+-/* Device specific TX header. To be prepended to TX frames. */
+-struct bcm43xx_txhdr {
+-	union {
+-		struct {
+-			__le16 flags;
+-			__le16 wsec_rate;
+-			__le16 frame_control;
+-			u16 unknown_zeroed_0;
+-			__le16 control;
+-			u8 wep_iv[10];
+-			u8 unknown_wsec_tkip_data[3]; //FIXME
+-			PAD_BYTES(3);
+-			u8 mac1[6];
+-			u16 unknown_zeroed_1;
+-			struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
+-			__le16 rts_cts_dur_fallback;
+-			struct bcm43xx_plcp_hdr4 fallback_plcp;
+-			__le16 fallback_dur_id;
+-			PAD_BYTES(2);
+-			__le16 cookie;
+-			__le16 unknown_scb_stuff; //FIXME
+-			struct bcm43xx_plcp_hdr6 rts_cts_plcp;
+-			__le16 rts_cts_frame_control;
+-			__le16 rts_cts_dur;
+-			u8 rts_cts_mac1[6];
+-			u8 rts_cts_mac2[6];
+-			PAD_BYTES(2);
+-			struct bcm43xx_plcp_hdr6 plcp;
+-		} __attribute__((__packed__));
+-		u8 raw[82];
+-	} __attribute__((__packed__));
+-} __attribute__((__packed__));
+-
+-/* Values/Masks for the device TX header */
+-#define BCM43xx_TXHDRFLAG_EXPECTACK		0x0001
+-#define BCM43xx_TXHDRFLAG_RTSCTS		0x0002
+-#define BCM43xx_TXHDRFLAG_RTS			0x0004
+-#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT		0x0008
+-#define BCM43xx_TXHDRFLAG_DESTPSMODE		0x0020
+-#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM		0x0080
+-#define BCM43xx_TXHDRFLAG_FALLBACKOFDM		0x0100
+-#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM	0x0200
+-#define BCM43xx_TXHDRFLAG_CTS			0x0400
+-#define BCM43xx_TXHDRFLAG_FRAMEBURST		0x0800
+-
+-#define BCM43xx_TXHDRCTL_OFDM			0x0001
+-#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE		0x0010
+-#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK	0x0030
+-#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT	8
+-
+-#define BCM43xx_TXHDR_RATE_MASK			0x0F00
+-#define BCM43xx_TXHDR_RATE_SHIFT		8
+-#define BCM43xx_TXHDR_RTSRATE_MASK		0xF000
+-#define BCM43xx_TXHDR_RTSRATE_SHIFT		12
+-#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK	0x00F0
+-#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT	4
+-#define BCM43xx_TXHDR_WSEC_ALGO_MASK		0x0003
+-#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT		0
+-
+-void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
+-			    struct bcm43xx_txhdr *txhdr,
+-			    const unsigned char *fragment_data,
+-			    const unsigned int fragment_len,
+-			    const int is_first_fragment,
+-			    const u16 cookie);
+-
+-/* RX header as received from the hardware. */
+-struct bcm43xx_rxhdr {
+-	/* Frame Length. Must be generated explicitly in PIO mode. */
+-	__le16 frame_length;
+-	PAD_BYTES(2);
+-	/* Flags field 1 */
+-	__le16 flags1;
+-	u8 rssi;
+-	u8 signal_quality;
+-	PAD_BYTES(2);
+-	/* Flags field 3 */
+-	__le16 flags3;
+-	/* Flags field 2 */
+-	__le16 flags2;
+-	/* Lower 16bits of the TSF at the time the frame started. */
+-	__le16 mactime;
+-	PAD_BYTES(14);
+-} __attribute__((__packed__));
+-
+-#define BCM43xx_RXHDR_FLAGS1_OFDM		(1 << 0)
+-/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL???	(1 << 3) FIXME */
+-#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE	(1 << 7)
+-#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ	(1 << 14)
+-
+-#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME	(1 << 0)
+-#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME		(1 << 2)
+-/*FIXME: WEP related flags */
+-
+-#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ	(1 << 10)
+-
+-/* Transmit Status as received from the hardware. */
+-struct bcm43xx_hwxmitstatus {
+-	PAD_BYTES(4);
+-	__le16 cookie;
+-	u8 flags;
+-	u8 cnt1:4,
+-	   cnt2:4;
+-	PAD_BYTES(2);
+-	__le16 seq;
+-	__le16 unknown; //FIXME
+-} __attribute__((__packed__));
+-
+-/* Transmit Status in CPU byteorder. */
+-struct bcm43xx_xmitstatus {
+-	u16 cookie;
+-	u8 flags;
+-	u8 cnt1:4,
+-	   cnt2:4;
+-	u16 seq;
+-	u16 unknown; //FIXME
+-};
+-
+-#define BCM43xx_TXSTAT_FLAG_AMPDU	0x10
+-#define BCM43xx_TXSTAT_FLAG_INTER	0x20
+-
+-u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
+-u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
+-
+-int bcm43xx_rx(struct bcm43xx_private *bcm,
+-	       struct sk_buff *skb,
+-	       struct bcm43xx_rxhdr *rxhdr);
+-
+-#endif /* BCM43xx_XMIT_H_ */
+diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
+index 98d6ff6..fa87c5c 100644
+--- a/drivers/net/wireless/ipw2200.c
++++ b/drivers/net/wireless/ipw2200.c
+@@ -4495,9 +4495,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
+ 								       priv->
+ 								       essid_len),
+ 							  print_mac(mac, priv->bssid),
+-							  ntohs(auth->status),
++							  le16_to_cpu(auth->status),
+ 							  ipw_get_status_code
+-							  (ntohs
++							  (le16_to_cpu
+ 							   (auth->status)));
+ 
+ 						priv->status &=
+@@ -4532,9 +4532,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
+ 							  IPW_DL_STATE |
+ 							  IPW_DL_ASSOC,
+ 							  "association failed (0x%04X): %s\n",
+-							  ntohs(resp->status),
++							  le16_to_cpu(resp->status),
+ 							  ipw_get_status_code
+-							  (ntohs
++							  (le16_to_cpu
+ 							   (resp->status)));
+ 					}
+ 
+@@ -4591,8 +4591,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
+ 					IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ 						  IPW_DL_ASSOC,
+ 						  "authentication failed (0x%04X): %s\n",
+-						  ntohs(auth->status),
+-						  ipw_get_status_code(ntohs
++						  le16_to_cpu(auth->status),
++						  ipw_get_status_code(le16_to_cpu
+ 								      (auth->
+ 								       status)));
+ 				}
+@@ -10350,9 +10350,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
+ 					 remaining_bytes,
+ 					 PCI_DMA_TODEVICE));
+ 
+-			tfd->u.data.num_chunks =
+-			    cpu_to_le32(le32_to_cpu(tfd->u.data.num_chunks) +
+-					1);
++			le32_add_cpu(&tfd->u.data.num_chunks, 1);
+ 		}
+ 	}
+ 
+diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
+index fdc187e..cd3295b 100644
+--- a/drivers/net/wireless/ipw2200.h
++++ b/drivers/net/wireless/ipw2200.h
+@@ -385,73 +385,73 @@ struct clx2_queue {
+ 	dma_addr_t dma_addr;		/**< physical addr for BD's */
+ 	int low_mark;		       /**< low watermark, resume queue if free space more than this */
+ 	int high_mark;		       /**< high watermark, stop queue if free space less than this */
+-} __attribute__ ((packed));
++} __attribute__ ((packed)); /* XXX */
+ 
+ struct machdr32 {
+ 	__le16 frame_ctl;
+-	u16 duration;		// watch out for endians!
++	__le16 duration;		// watch out for endians!
+ 	u8 addr1[MACADRR_BYTE_LEN];
+ 	u8 addr2[MACADRR_BYTE_LEN];
+ 	u8 addr3[MACADRR_BYTE_LEN];
+-	u16 seq_ctrl;		// more endians!
++	__le16 seq_ctrl;		// more endians!
+ 	u8 addr4[MACADRR_BYTE_LEN];
+ 	__le16 qos_ctrl;
+ } __attribute__ ((packed));
+ 
+ struct machdr30 {
+ 	__le16 frame_ctl;
+-	u16 duration;		// watch out for endians!
++	__le16 duration;		// watch out for endians!
+ 	u8 addr1[MACADRR_BYTE_LEN];
+ 	u8 addr2[MACADRR_BYTE_LEN];
+ 	u8 addr3[MACADRR_BYTE_LEN];
+-	u16 seq_ctrl;		// more endians!
++	__le16 seq_ctrl;		// more endians!
+ 	u8 addr4[MACADRR_BYTE_LEN];
+ } __attribute__ ((packed));
+ 
+ struct machdr26 {
+ 	__le16 frame_ctl;
+-	u16 duration;		// watch out for endians!
++	__le16 duration;		// watch out for endians!
+ 	u8 addr1[MACADRR_BYTE_LEN];
+ 	u8 addr2[MACADRR_BYTE_LEN];
+ 	u8 addr3[MACADRR_BYTE_LEN];
+-	u16 seq_ctrl;		// more endians!
++	__le16 seq_ctrl;		// more endians!
+ 	__le16 qos_ctrl;
+ } __attribute__ ((packed));
+ 
+ struct machdr24 {
+ 	__le16 frame_ctl;
+-	u16 duration;		// watch out for endians!
++	__le16 duration;		// watch out for endians!
+ 	u8 addr1[MACADRR_BYTE_LEN];
+ 	u8 addr2[MACADRR_BYTE_LEN];
+ 	u8 addr3[MACADRR_BYTE_LEN];
+-	u16 seq_ctrl;		// more endians!
++	__le16 seq_ctrl;		// more endians!
+ } __attribute__ ((packed));
+ 
+ // TX TFD with 32 byte MAC Header
+ struct tx_tfd_32 {
+ 	struct machdr32 mchdr;	// 32
+-	u32 uivplaceholder[2];	// 8
++	__le32 uivplaceholder[2];	// 8
+ } __attribute__ ((packed));
+ 
+ // TX TFD with 30 byte MAC Header
+ struct tx_tfd_30 {
+ 	struct machdr30 mchdr;	// 30
+ 	u8 reserved[2];		// 2
+-	u32 uivplaceholder[2];	// 8
++	__le32 uivplaceholder[2];	// 8
+ } __attribute__ ((packed));
+ 
+ // tx tfd with 26 byte mac header
+ struct tx_tfd_26 {
+ 	struct machdr26 mchdr;	// 26
+ 	u8 reserved1[2];	// 2
+-	u32 uivplaceholder[2];	// 8
++	__le32 uivplaceholder[2];	// 8
+ 	u8 reserved2[4];	// 4
+ } __attribute__ ((packed));
+ 
+ // tx tfd with 24 byte mac header
+ struct tx_tfd_24 {
+ 	struct machdr24 mchdr;	// 24
+-	u32 uivplaceholder[2];	// 8
++	__le32 uivplaceholder[2];	// 8
+ 	u8 reserved[8];		// 8
+ } __attribute__ ((packed));
+ 
+@@ -460,7 +460,7 @@ struct tx_tfd_24 {
+ struct tfd_command {
+ 	u8 index;
+ 	u8 length;
+-	u16 reserved;
++	__le16 reserved;
+ 	u8 payload[0];
+ } __attribute__ ((packed));
+ 
+@@ -562,27 +562,27 @@ struct rate_histogram {
+ struct ipw_cmd_stats {
+ 	u8 cmd_id;
+ 	u8 seq_num;
+-	u16 good_sfd;
+-	u16 bad_plcp;
+-	u16 wrong_bssid;
+-	u16 valid_mpdu;
+-	u16 bad_mac_header;
+-	u16 reserved_frame_types;
+-	u16 rx_ina;
+-	u16 bad_crc32;
+-	u16 invalid_cts;
+-	u16 invalid_acks;
+-	u16 long_distance_ina_fina;
+-	u16 dsp_silence_unreachable;
+-	u16 accumulated_rssi;
+-	u16 rx_ovfl_frame_tossed;
+-	u16 rssi_silence_threshold;
+-	u16 rx_ovfl_frame_supplied;
+-	u16 last_rx_frame_signal;
+-	u16 last_rx_frame_noise;
+-	u16 rx_autodetec_no_ofdm;
+-	u16 rx_autodetec_no_barker;
+-	u16 reserved;
++	__le16 good_sfd;
++	__le16 bad_plcp;
++	__le16 wrong_bssid;
++	__le16 valid_mpdu;
++	__le16 bad_mac_header;
++	__le16 reserved_frame_types;
++	__le16 rx_ina;
++	__le16 bad_crc32;
++	__le16 invalid_cts;
++	__le16 invalid_acks;
++	__le16 long_distance_ina_fina;
++	__le16 dsp_silence_unreachable;
++	__le16 accumulated_rssi;
++	__le16 rx_ovfl_frame_tossed;
++	__le16 rssi_silence_threshold;
++	__le16 rx_ovfl_frame_supplied;
++	__le16 last_rx_frame_signal;
++	__le16 last_rx_frame_noise;
++	__le16 rx_autodetec_no_ofdm;
++	__le16 rx_autodetec_no_barker;
++	__le16 reserved;
+ } __attribute__ ((packed));
+ 
+ struct notif_channel_result {
+@@ -637,7 +637,7 @@ struct notif_association {
+ struct notif_authenticate {
+ 	u8 state;
+ 	struct machdr24 addr;
+-	u16 status;
++	__le16 status;
+ } __attribute__ ((packed));
+ 
+ struct notif_calibration {
+@@ -732,14 +732,14 @@ struct ipw_rx_queue {
+ struct alive_command_responce {
+ 	u8 alive_command;
+ 	u8 sequence_number;
+-	u16 software_revision;
++	__le16 software_revision;
+ 	u8 device_identifier;
+ 	u8 reserved1[5];
+-	u16 reserved2;
+-	u16 reserved3;
+-	u16 clock_settle_time;
+-	u16 powerup_settle_time;
+-	u16 reserved4;
++	__le16 reserved2;
++	__le16 reserved3;
++	__le16 clock_settle_time;
++	__le16 powerup_settle_time;
++	__le16 reserved4;
+ 	u8 time_stamp[5];	/* month, day, year, hours, minutes */
+ 	u8 ucode_valid;
+ } __attribute__ ((packed));
+@@ -878,7 +878,11 @@ static inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan,
+ 
+ struct ipw_associate {
+ 	u8 channel;
++#ifdef __LITTLE_ENDIAN_BITFIELD
+ 	u8 auth_type:4, auth_key:4;
++#else
++	u8 auth_key:4, auth_type:4;
++#endif
+ 	u8 assoc_type;
+ 	u8 reserved;
+ 	__le16 policy_support;
+@@ -918,12 +922,12 @@ struct ipw_frag_threshold {
+ struct ipw_retry_limit {
+ 	u8 short_retry_limit;
+ 	u8 long_retry_limit;
+-	u16 reserved;
++	__le16 reserved;
+ } __attribute__ ((packed));
+ 
+ struct ipw_dino_config {
+-	u32 dino_config_addr;
+-	u16 dino_config_size;
++	__le32 dino_config_addr;
++	__le16 dino_config_size;
+ 	u8 dino_response;
+ 	u8 reserved;
+ } __attribute__ ((packed));
+@@ -998,7 +1002,7 @@ struct ipw_sensitivity_calib {
+  * - \a status contains status;
+  * - \a param filled with status parameters.
+  */
+-struct ipw_cmd {
++struct ipw_cmd {	 /* XXX */
+ 	u32 cmd;   /**< Host command */
+ 	u32 status;/**< Status */
+ 	u32 status_len;
+@@ -1092,7 +1096,7 @@ struct ipw_ibss_seq {
+ 	struct list_head list;
+ };
+ 
+-struct ipw_error_elem {
++struct ipw_error_elem {	 /* XXX */
+ 	u32 desc;
+ 	u32 time;
+ 	u32 blink1;
+@@ -1102,13 +1106,13 @@ struct ipw_error_elem {
+ 	u32 data;
+ };
+ 
+-struct ipw_event {
++struct ipw_event {	 /* XXX */
+ 	u32 event;
+ 	u32 time;
+ 	u32 data;
+ } __attribute__ ((packed));
+ 
+-struct ipw_fw_error {
++struct ipw_fw_error {	 /* XXX */
+ 	unsigned long jiffies;
+ 	u32 status;
+ 	u32 config;
+@@ -1153,7 +1157,7 @@ struct ipw_prom_priv {
+  */
+ struct ipw_rt_hdr {
+ 	struct ieee80211_radiotap_header rt_hdr;
+-	u64 rt_tsf;      /* TSF */
++	u64 rt_tsf;      /* TSF */	/* XXX */
+ 	u8 rt_flags;	/* radiotap packet flags */
+ 	u8 rt_rate;	/* rate in 500kb/s */
+ 	__le16 rt_channel;	/* channel in mhz */
+@@ -1940,8 +1944,8 @@ enum {
+ #define IPW_MEM_FIXED_OVERRIDE          (IPW_SHARED_LOWER_BOUND + 0x41C)
+ 
+ struct ipw_fixed_rate {
+-	u16 tx_rates;
+-	u16 reserved;
++	__le16 tx_rates;
++	__le16 reserved;
+ } __attribute__ ((packed));
+ 
+ #define IPW_INDIRECT_ADDR_MASK (~0x3ul)
+@@ -1951,12 +1955,12 @@ struct host_cmd {
+ 	u8 len;
+ 	u16 reserved;
+ 	u32 *param;
+-} __attribute__ ((packed));
++} __attribute__ ((packed));	/* XXX */
+ 
+ struct cmdlog_host_cmd {
+ 	u8 cmd;
+ 	u8 len;
+-	u16 reserved;
++	__le16 reserved;
+ 	char param[124];
+ } __attribute__ ((packed));
+ 
+diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
+index b54ff71..c4e631d 100644
+--- a/drivers/net/wireless/iwlwifi/Kconfig
++++ b/drivers/net/wireless/iwlwifi/Kconfig
+@@ -1,7 +1,22 @@
++config IWLCORE
++	tristate "Intel Wireless Wifi Core"
++	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
++
++config IWLWIFI_LEDS
++	bool
++	default n
++
++config IWLWIFI_RFKILL
++	boolean "IWLWIFI RF kill support"
++	depends on IWLCORE
++	select RFKILL
++	select RFKILL_INPUT
++
+ config IWL4965
+ 	tristate "Intel Wireless WiFi 4965AGN"
+ 	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+ 	select FW_LOADER
++	select IWLCORE
+ 	---help---
+ 	  Select to build the driver supporting the:
+ 
+@@ -24,21 +39,24 @@ config IWL4965
+ 	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
+ 	  module will be called iwl4965.ko.
+ 
+-config IWL4965_QOS
+-	bool "Enable Wireless QoS in iwl4965 driver"
+-	depends on IWL4965
+-	---help---
+-	  This option will enable wireless quality of service (QoS) for the
+-	  iwl4965 driver.
+-
+ config IWL4965_HT
+ 	bool "Enable 802.11n HT features in iwl4965 driver"
+ 	depends on EXPERIMENTAL
+-	depends on IWL4965 && IWL4965_QOS
++	depends on IWL4965
+ 	---help---
+ 	  This option enables IEEE 802.11n High Throughput features
+ 	  for the iwl4965 driver.
+ 
++config IWL4965_LEDS
++	bool "Enable LEDS features in iwl4965 driver"
++	depends on IWL4965
++	select MAC80211_LEDS
++	select LEDS_CLASS
++	select IWLWIFI_LEDS
++	---help---
++	  This option enables LEDS for the iwlwifi drivers
++
++
+ config IWL4965_SPECTRUM_MEASUREMENT
+ 	bool "Enable Spectrum Measurement in iwl4965 driver"
+ 	depends on IWL4965
+@@ -52,7 +70,7 @@ config IWL4965_SENSITIVITY
+ 	  This option will enable sensitivity calibration for the iwl4965
+ 	  driver.
+ 
+-config IWL4965_DEBUG
++config IWLWIFI_DEBUG
+ 	bool "Enable full debugging output in iwl4965 driver"
+ 	depends on IWL4965
+ 	---help---
+@@ -78,6 +96,12 @@ config IWL4965_DEBUG
+ 	  as the debug information can assist others in helping you resolve
+ 	  any problems you may encounter.
+ 
++config IWLWIFI_DEBUGFS
++        bool "Iwlwifi debugfs support"
++        depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS
++        ---help---
++	  Enable creation of debugfs files for the iwlwifi drivers.
++
+ config IWL3945
+ 	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
+ 	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+@@ -104,19 +128,20 @@ config IWL3945
+ 	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
+ 	  module will be called iwl3945.ko.
+ 
+-config IWL3945_QOS
+-	bool "Enable Wireless QoS in iwl3945 driver"
+-	depends on IWL3945
+-	---help---
+-	  This option will enable wireless quality of service (QoS) for the
+-	  iwl3945 driver.
+-
+ config IWL3945_SPECTRUM_MEASUREMENT
+ 	bool "Enable Spectrum Measurement in iwl3945 drivers"
+ 	depends on IWL3945
+ 	---help---
+ 	  This option will enable spectrum measurement for the iwl3945 driver.
+ 
++config IWL3945_LEDS
++	bool "Enable LEDS features in iwl3945 driver"
++	depends on IWL3945
++	select MAC80211_LEDS
++	select LEDS_CLASS
++	---help---
++	  This option enables LEDS for the iwl3945 driver.
++
+ config IWL3945_DEBUG
+ 	bool "Enable full debugging output in iwl3945 driver"
+ 	depends on IWL3945
+diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
+index 3bbd383..ec6187b 100644
+--- a/drivers/net/wireless/iwlwifi/Makefile
++++ b/drivers/net/wireless/iwlwifi/Makefile
+@@ -1,5 +1,13 @@
++obj-$(CONFIG_IWLCORE)	+= iwlcore.o
++iwlcore-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o
++iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
++iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
++iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
++
+ obj-$(CONFIG_IWL3945)	+= iwl3945.o
+-iwl3945-objs		= iwl3945-base.o iwl-3945.o iwl-3945-rs.o
++iwl3945-objs		:= iwl3945-base.o iwl-3945.o iwl-3945-rs.o
++iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o
+ 
+ obj-$(CONFIG_IWL4965)	+= iwl4965.o
+-iwl4965-objs		= iwl4965-base.o iwl-4965.o iwl-4965-rs.o
++iwl4965-objs		:= iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
+index 46bb2c7..817ece7 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
+@@ -5,7 +5,7 @@
+  *
+  * GPL LICENSE SUMMARY
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 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
+@@ -30,7 +30,7 @@
+  *
+  * BSD LICENSE
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -515,14 +515,20 @@ struct iwl3945_qosparam_cmd {
+ #define STA_CONTROL_MODIFY_MSK		0x01
+ 
+ /* key flags __le16*/
+-#define STA_KEY_FLG_ENCRYPT_MSK	__constant_cpu_to_le16(0x7)
+-#define STA_KEY_FLG_NO_ENC	__constant_cpu_to_le16(0x0)
+-#define STA_KEY_FLG_WEP		__constant_cpu_to_le16(0x1)
+-#define STA_KEY_FLG_CCMP	__constant_cpu_to_le16(0x2)
+-#define STA_KEY_FLG_TKIP	__constant_cpu_to_le16(0x3)
++#define STA_KEY_FLG_ENCRYPT_MSK	__constant_cpu_to_le16(0x0007)
++#define STA_KEY_FLG_NO_ENC	__constant_cpu_to_le16(0x0000)
++#define STA_KEY_FLG_WEP		__constant_cpu_to_le16(0x0001)
++#define STA_KEY_FLG_CCMP	__constant_cpu_to_le16(0x0002)
++#define STA_KEY_FLG_TKIP	__constant_cpu_to_le16(0x0003)
+ 
+ #define STA_KEY_FLG_KEYID_POS	8
+ #define STA_KEY_FLG_INVALID 	__constant_cpu_to_le16(0x0800)
++/* wep key is either from global key (0) or from station info array (1) */
++#define STA_KEY_FLG_WEP_KEY_MAP_MSK  __constant_cpu_to_le16(0x0008)
++
++/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
++#define STA_KEY_FLG_KEY_SIZE_MSK     __constant_cpu_to_le16(0x1000)
++#define STA_KEY_MULTICAST_MSK        __constant_cpu_to_le16(0x4000)
+ 
+ /* Flags indicate whether to modify vs. don't change various station params */
+ #define	STA_MODIFY_KEY_MASK		0x01
+@@ -546,7 +552,8 @@ struct iwl3945_keyinfo {
+ 	u8 tkip_rx_tsc_byte2;	/* TSC[2] for key mix ph1 detection */
+ 	u8 reserved1;
+ 	__le16 tkip_rx_ttak[5];	/* 10-byte unicast TKIP TTAK */
+-	__le16 reserved2;
++	u8 key_offset;
++	u8 reserved2;
+ 	u8 key[16];		/* 16-byte unicast decryption key */
+ } __attribute__ ((packed));
+ 
+@@ -659,26 +666,26 @@ struct iwl3945_rx_frame_hdr {
+ 	u8 payload[0];
+ } __attribute__ ((packed));
+ 
+-#define	RX_RES_STATUS_NO_CRC32_ERROR	__constant_cpu_to_le32(1 << 0)
+-#define	RX_RES_STATUS_NO_RXE_OVERFLOW	__constant_cpu_to_le32(1 << 1)
++#define RX_RES_STATUS_NO_CRC32_ERROR	__constant_cpu_to_le32(1 << 0)
++#define RX_RES_STATUS_NO_RXE_OVERFLOW	__constant_cpu_to_le32(1 << 1)
+ 
+-#define	RX_RES_PHY_FLAGS_BAND_24_MSK	__constant_cpu_to_le16(1 << 0)
+-#define	RX_RES_PHY_FLAGS_MOD_CCK_MSK		__constant_cpu_to_le16(1 << 1)
+-#define	RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	__constant_cpu_to_le16(1 << 2)
+-#define	RX_RES_PHY_FLAGS_NARROW_BAND_MSK	__constant_cpu_to_le16(1 << 3)
+-#define	RX_RES_PHY_FLAGS_ANTENNA_MSK		__constant_cpu_to_le16(0xf0)
++#define RX_RES_PHY_FLAGS_BAND_24_MSK	__constant_cpu_to_le16(1 << 0)
++#define RX_RES_PHY_FLAGS_MOD_CCK_MSK		__constant_cpu_to_le16(1 << 1)
++#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	__constant_cpu_to_le16(1 << 2)
++#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK	__constant_cpu_to_le16(1 << 3)
++#define RX_RES_PHY_FLAGS_ANTENNA_MSK		__constant_cpu_to_le16(0xf0)
+ 
+-#define	RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
+-#define	RX_RES_STATUS_SEC_TYPE_NONE	(0x0 << 8)
+-#define	RX_RES_STATUS_SEC_TYPE_WEP	(0x1 << 8)
+-#define	RX_RES_STATUS_SEC_TYPE_CCMP	(0x2 << 8)
+-#define	RX_RES_STATUS_SEC_TYPE_TKIP	(0x3 << 8)
++#define RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
++#define RX_RES_STATUS_SEC_TYPE_NONE	(0x0 << 8)
++#define RX_RES_STATUS_SEC_TYPE_WEP	(0x1 << 8)
++#define RX_RES_STATUS_SEC_TYPE_CCMP	(0x2 << 8)
++#define RX_RES_STATUS_SEC_TYPE_TKIP	(0x3 << 8)
+ 
+-#define	RX_RES_STATUS_DECRYPT_TYPE_MSK	(0x3 << 11)
+-#define	RX_RES_STATUS_NOT_DECRYPT	(0x0 << 11)
+-#define	RX_RES_STATUS_DECRYPT_OK	(0x3 << 11)
+-#define	RX_RES_STATUS_BAD_ICV_MIC	(0x1 << 11)
+-#define	RX_RES_STATUS_BAD_KEY_TTAK	(0x2 << 11)
++#define RX_RES_STATUS_DECRYPT_TYPE_MSK	(0x3 << 11)
++#define RX_RES_STATUS_NOT_DECRYPT	(0x0 << 11)
++#define RX_RES_STATUS_DECRYPT_OK	(0x3 << 11)
++#define RX_RES_STATUS_BAD_ICV_MIC	(0x1 << 11)
++#define RX_RES_STATUS_BAD_KEY_TTAK	(0x2 << 11)
+ 
+ struct iwl3945_rx_frame_end {
+ 	__le32 status;
+@@ -700,45 +707,6 @@ struct iwl3945_rx_frame {
+ 	struct iwl3945_rx_frame_end end;
+ } __attribute__ ((packed));
+ 
+-/* Fixed (non-configurable) rx data from phy */
+-#define RX_PHY_FLAGS_ANTENNAE_OFFSET		(4)
+-#define RX_PHY_FLAGS_ANTENNAE_MASK		(0x70)
+-#define IWL_AGC_DB_MASK 	(0x3f80)	/* MASK(7,13) */
+-#define IWL_AGC_DB_POS		(7)
+-struct iwl4965_rx_non_cfg_phy {
+-	__le16 ant_selection;	/* ant A bit 4, ant B bit 5, ant C bit 6 */
+-	__le16 agc_info;	/* agc code 0:6, agc dB 7:13, reserved 14:15 */
+-	u8 rssi_info[6];	/* we use even entries, 0/2/4 for A/B/C rssi */
+-	u8 pad[0];
+-} __attribute__ ((packed));
+-
+-/*
+- * REPLY_4965_RX = 0xc3 (response only, not a command)
+- * Used only for legacy (non 11n) frames.
+- */
+-#define RX_RES_PHY_CNT 14
+-struct iwl4965_rx_phy_res {
+-	u8 non_cfg_phy_cnt;     /* non configurable DSP phy data byte count */
+-	u8 cfg_phy_cnt;		/* configurable DSP phy data byte count */
+-	u8 stat_id;		/* configurable DSP phy data set ID */
+-	u8 reserved1;
+-	__le64 timestamp;	/* TSF at on air rise */
+-	__le32 beacon_time_stamp; /* beacon at on-air rise */
+-	__le16 phy_flags;	/* general phy flags: band, modulation, ... */
+-	__le16 channel;		/* channel number */
+-	__le16 non_cfg_phy[RX_RES_PHY_CNT];	/* upto 14 phy entries */
+-	__le32 reserved2;
+-	__le32 rate_n_flags;
+-	__le16 byte_count;		/* frame's byte-count */
+-	__le16 reserved3;
+-} __attribute__ ((packed));
+-
+-struct iwl4965_rx_mpdu_res_start {
+-	__le16 byte_count;
+-	__le16 reserved;
+-} __attribute__ ((packed));
+-
+-
+ /******************************************************************************
+  * (5)
+  * Tx Commands & Responses:
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-core.h b/drivers/net/wireless/iwlwifi/iwl-3945-core.h
+new file mode 100644
+index 0000000..bc12f97
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-core.h
+@@ -0,0 +1,80 @@
++/******************************************************************************
++ *
++ * 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 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:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ *  * Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ *  * Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *  * Neither the name Intel Corporation nor the names of its
++ *    contributors may be used to endorse or promote products derived
++ *    from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *****************************************************************************/
++
++#ifndef __iwl_3945_dev_h__
++#define __iwl_3945_dev_h__
++
++#define IWL_PCI_DEVICE(dev, subdev, cfg) \
++	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
++	.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
++	.driver_data = (kernel_ulong_t)&(cfg)
++
++#define IWL_SKU_G       0x1
++#define IWL_SKU_A       0x2
++
++struct iwl_3945_cfg {
++	const char *name;
++	const char *fw_name;
++	unsigned int sku;
++};
++
++#endif /* __iwl_dev_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
+index f853c6b..f1d002f 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+  *
+  * Portions of this file are derived from the ipw3945 project.
+  *
+@@ -40,6 +40,15 @@ do { if (iwl3945_debug_level & (level)) \
+ do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \
+   printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+ 	 in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
++
++static inline void iwl3945_print_hex_dump(int level, void *p, u32 len)
++{
++	if (!(iwl3945_debug_level & level))
++		return;
++
++	print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
++			p, len, 1);
++}
+ #else
+ static inline void IWL_DEBUG(int level, const char *fmt, ...)
+ {
+@@ -47,7 +56,12 @@ static inline void IWL_DEBUG(int level, const char *fmt, ...)
+ static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
+ {
+ }
+-#endif				/* CONFIG_IWL3945_DEBUG */
++static inline void iwl3945_print_hex_dump(int level, void *p, u32 len)
++{
++}
++#endif	/* CONFIG_IWL3945_DEBUG */
++
++
+ 
+ /*
+  * To use the debug system;
+@@ -143,6 +157,7 @@ static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
+ 	IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+ #define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
+ #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
++#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a)
+ #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
+ #define IWL_DEBUG_QOS(f, a...)   IWL_DEBUG(IWL_DL_QOS, f, ## a)
+ #define IWL_DEBUG_RADIO(f, a...)  IWL_DEBUG(IWL_DL_RADIO, f, ## a)
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+index 571815d..ad612a8 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+@@ -5,7 +5,7 @@
+  *
+  * GPL LICENSE SUMMARY
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 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
+@@ -30,7 +30,7 @@
+  *
+  * BSD LICENSE
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -198,43 +198,27 @@ struct iwl3945_eeprom_temperature_corr {
+  */
+ struct iwl3945_eeprom {
+ 	u8 reserved0[16];
+-#define EEPROM_DEVICE_ID                    (2*0x08)	/* 2 bytes */
+ 	u16 device_id;	/* abs.ofs: 16 */
+ 	u8 reserved1[2];
+-#define EEPROM_PMC                          (2*0x0A)	/* 2 bytes */
+ 	u16 pmc;		/* abs.ofs: 20 */
+ 	u8 reserved2[20];
+-#define EEPROM_MAC_ADDRESS                  (2*0x15)	/* 6  bytes */
+ 	u8 mac_address[6];	/* abs.ofs: 42 */
+ 	u8 reserved3[58];
+-#define EEPROM_BOARD_REVISION               (2*0x35)	/* 2  bytes */
+ 	u16 board_revision;	/* abs.ofs: 106 */
+ 	u8 reserved4[11];
+-#define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1)	/* 9  bytes */
+ 	u8 board_pba_number[9];	/* abs.ofs: 119 */
+ 	u8 reserved5[8];
+-#define EEPROM_VERSION                      (2*0x44)	/* 2  bytes */
+ 	u16 version;		/* abs.ofs: 136 */
+-#define EEPROM_SKU_CAP                      (2*0x45)	/* 1  bytes */
+ 	u8 sku_cap;		/* abs.ofs: 138 */
+-#define EEPROM_LEDS_MODE                    (2*0x45+1)	/* 1  bytes */
+ 	u8 leds_mode;		/* abs.ofs: 139 */
+-#define EEPROM_OEM_MODE                     (2*0x46)	/* 2  bytes */
+ 	u16 oem_mode;
+-#define EEPROM_WOWLAN_MODE                  (2*0x47)	/* 2  bytes */
+ 	u16 wowlan_mode;	/* abs.ofs: 142 */
+-#define EEPROM_LEDS_TIME_INTERVAL           (2*0x48)	/* 2  bytes */
+ 	u16 leds_time_interval;	/* abs.ofs: 144 */
+-#define EEPROM_LEDS_OFF_TIME                (2*0x49)	/* 1  bytes */
+ 	u8 leds_off_time;	/* abs.ofs: 146 */
+-#define EEPROM_LEDS_ON_TIME                 (2*0x49+1)	/* 1  bytes */
+ 	u8 leds_on_time;	/* abs.ofs: 147 */
+-#define EEPROM_ALMGOR_M_VERSION             (2*0x4A)	/* 1  bytes */
+ 	u8 almgor_m_version;	/* abs.ofs: 148 */
+-#define EEPROM_ANTENNA_SWITCH_TYPE          (2*0x4A+1)	/* 1  bytes */
+ 	u8 antenna_switch_type;	/* abs.ofs: 149 */
+ 	u8 reserved6[42];
+-#define EEPROM_REGULATORY_SKU_ID            (2*0x60)	/* 4  bytes */
+ 	u8 sku_id[4];		/* abs.ofs: 192 */
+ 
+ /*
+@@ -249,9 +233,7 @@ struct iwl3945_eeprom {
+  *
+  * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+  */
+-#define EEPROM_REGULATORY_BAND_1            (2*0x62)	/* 2  bytes */
+ 	u16 band_1_count;	/* abs.ofs: 196 */
+-#define EEPROM_REGULATORY_BAND_1_CHANNELS   (2*0x63)	/* 28 bytes */
+ 	struct iwl3945_eeprom_channel band_1_channels[14];  /* abs.ofs: 196 */
+ 
+ /*
+@@ -259,36 +241,28 @@ struct iwl3945_eeprom {
+  * 5.0 GHz channels 7, 8, 11, 12, 16
+  * (4915-5080MHz) (none of these is ever supported)
+  */
+-#define EEPROM_REGULATORY_BAND_2            (2*0x71)	/* 2  bytes */
+ 	u16 band_2_count;	/* abs.ofs: 226 */
+-#define EEPROM_REGULATORY_BAND_2_CHANNELS   (2*0x72)	/* 26 bytes */
+ 	struct iwl3945_eeprom_channel band_2_channels[13];  /* abs.ofs: 228 */
+ 
+ /*
+  * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+  * (5170-5320MHz)
+  */
+-#define EEPROM_REGULATORY_BAND_3            (2*0x7F)	/* 2  bytes */
+ 	u16 band_3_count;	/* abs.ofs: 254 */
+-#define EEPROM_REGULATORY_BAND_3_CHANNELS   (2*0x80)	/* 24 bytes */
+ 	struct iwl3945_eeprom_channel band_3_channels[12];  /* abs.ofs: 256 */
+ 
+ /*
+  * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+  * (5500-5700MHz)
+  */
+-#define EEPROM_REGULATORY_BAND_4            (2*0x8C)	/* 2  bytes */
+ 	u16 band_4_count;	/* abs.ofs: 280 */
+-#define EEPROM_REGULATORY_BAND_4_CHANNELS   (2*0x8D)	/* 22 bytes */
+ 	struct iwl3945_eeprom_channel band_4_channels[11];  /* abs.ofs: 282 */
+ 
+ /*
+  * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+  * (5725-5825MHz)
+  */
+-#define EEPROM_REGULATORY_BAND_5            (2*0x98)	/* 2  bytes */
+ 	u16 band_5_count;	/* abs.ofs: 304 */
+-#define EEPROM_REGULATORY_BAND_5_CHANNELS   (2*0x99)	/* 12 bytes */
+ 	struct iwl3945_eeprom_channel band_5_channels[6];  /* abs.ofs: 306 */
+ 
+ 	u8 reserved9[194];
+@@ -296,15 +270,9 @@ struct iwl3945_eeprom {
+ /*
+  * 3945 Txpower calibration data.
+  */
+-#define EEPROM_TXPOWER_CALIB_GROUP0 0x200
+-#define EEPROM_TXPOWER_CALIB_GROUP1 0x240
+-#define EEPROM_TXPOWER_CALIB_GROUP2 0x280
+-#define EEPROM_TXPOWER_CALIB_GROUP3 0x2c0
+-#define EEPROM_TXPOWER_CALIB_GROUP4 0x300
+ #define IWL_NUM_TX_CALIB_GROUPS 5
+ 	struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
+ /* abs.ofs: 512 */
+-#define EEPROM_CALIB_TEMPERATURE_CORRECT 0x340
+ 	struct iwl3945_eeprom_temperature_corr corrections;  /* abs.ofs: 832 */
+ 	u8 reserved16[172];	/* fill out to full 1024 byte block */
+ } __attribute__ ((packed));
+@@ -321,181 +289,6 @@ struct iwl3945_eeprom {
+ #define PCI_REG_WUM8       0x0E8
+ #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT         (0x80000000)
+ 
+-/*=== CSR (control and status registers) ===*/
+-#define CSR_BASE    (0x000)
+-
+-#define CSR_SW_VER              (CSR_BASE+0x000)
+-#define CSR_HW_IF_CONFIG_REG    (CSR_BASE+0x000) /* hardware interface config */
+-#define CSR_INT_COALESCING      (CSR_BASE+0x004) /* accum ints, 32-usec units */
+-#define CSR_INT                 (CSR_BASE+0x008) /* host interrupt status/ack */
+-#define CSR_INT_MASK            (CSR_BASE+0x00c) /* host interrupt enable */
+-#define CSR_FH_INT_STATUS       (CSR_BASE+0x010) /* busmaster int status/ack*/
+-#define CSR_GPIO_IN             (CSR_BASE+0x018) /* read external chip pins */
+-#define CSR_RESET               (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
+-#define CSR_GP_CNTRL            (CSR_BASE+0x024)
+-
+-/*
+- * Hardware revision info
+- * Bit fields:
+- * 31-8:  Reserved
+- *  7-4:  Type of device:  0x0 = 4965, 0xd = 3945
+- *  3-2:  Revision step:  0 = A, 1 = B, 2 = C, 3 = D
+- *  1-0:  "Dash" value, as in A-1, etc.
+- */
+-#define CSR_HW_REV              (CSR_BASE+0x028)
+-
+-/* EEPROM reads */
+-#define CSR_EEPROM_REG          (CSR_BASE+0x02c)
+-#define CSR_EEPROM_GP           (CSR_BASE+0x030)
+-#define CSR_GP_UCODE		(CSR_BASE+0x044)
+-#define CSR_UCODE_DRV_GP1       (CSR_BASE+0x054)
+-#define CSR_UCODE_DRV_GP1_SET   (CSR_BASE+0x058)
+-#define CSR_UCODE_DRV_GP1_CLR   (CSR_BASE+0x05c)
+-#define CSR_UCODE_DRV_GP2       (CSR_BASE+0x060)
+-#define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
+-
+-/* Analog phase-lock-loop configuration (3945 only)
+- * Set bit 24. */
+-#define CSR_ANA_PLL_CFG         (CSR_BASE+0x20c)
+-
+-/* Bits for CSR_HW_IF_CONFIG_REG */
+-#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB         (0x00000100)
+-#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM         (0x00000200)
+-#define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC            (0x00000400)
+-#define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE         (0x00000800)
+-#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A    (0x00000000)
+-#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B    (0x00001000)
+-#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM     (0x00200000)
+-
+-/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
+- * acknowledged (reset) by host writing "1" to flagged bits. */
+-#define CSR_INT_BIT_FH_RX        (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
+-#define CSR_INT_BIT_HW_ERR       (1 << 29) /* DMA hardware error FH_INT[31] */
+-#define CSR_INT_BIT_DNLD         (1 << 28) /* uCode Download */
+-#define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
+-#define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
+-#define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
+-#define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
+-#define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */
+-#define CSR_INT_BIT_SW_RX        (1 << 3)  /* Rx, command responses, 3945 */
+-#define CSR_INT_BIT_WAKEUP       (1 << 1)  /* NIC controller waking up (pwr mgmt) */
+-#define CSR_INT_BIT_ALIVE        (1 << 0)  /* uCode interrupts once it initializes */
+-
+-#define CSR_INI_SET_MASK	(CSR_INT_BIT_FH_RX   | \
+-				 CSR_INT_BIT_HW_ERR  | \
+-				 CSR_INT_BIT_FH_TX   | \
+-				 CSR_INT_BIT_SW_ERR  | \
+-				 CSR_INT_BIT_RF_KILL | \
+-				 CSR_INT_BIT_SW_RX   | \
+-				 CSR_INT_BIT_WAKEUP  | \
+-				 CSR_INT_BIT_ALIVE)
+-
+-/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
+-#define CSR_FH_INT_BIT_ERR       (1 << 31) /* Error */
+-#define CSR_FH_INT_BIT_HI_PRIOR  (1 << 30) /* High priority Rx, bypass coalescing */
+-#define CSR_FH_INT_BIT_RX_CHNL2  (1 << 18) /* Rx channel 2 (3945 only) */
+-#define CSR_FH_INT_BIT_RX_CHNL1  (1 << 17) /* Rx channel 1 */
+-#define CSR_FH_INT_BIT_RX_CHNL0  (1 << 16) /* Rx channel 0 */
+-#define CSR_FH_INT_BIT_TX_CHNL6  (1 << 6)  /* Tx channel 6 (3945 only) */
+-#define CSR_FH_INT_BIT_TX_CHNL1  (1 << 1)  /* Tx channel 1 */
+-#define CSR_FH_INT_BIT_TX_CHNL0  (1 << 0)  /* Tx channel 0 */
+-
+-#define CSR_FH_INT_RX_MASK	(CSR_FH_INT_BIT_HI_PRIOR | \
+-				 CSR_FH_INT_BIT_RX_CHNL2 | \
+-				 CSR_FH_INT_BIT_RX_CHNL1 | \
+-				 CSR_FH_INT_BIT_RX_CHNL0)
+-
+-#define CSR_FH_INT_TX_MASK	(CSR_FH_INT_BIT_TX_CHNL6 | \
+-				 CSR_FH_INT_BIT_TX_CHNL1 | \
+-				 CSR_FH_INT_BIT_TX_CHNL0)
+-
+-
+-/* RESET */
+-#define CSR_RESET_REG_FLAG_NEVO_RESET                (0x00000001)
+-#define CSR_RESET_REG_FLAG_FORCE_NMI                 (0x00000002)
+-#define CSR_RESET_REG_FLAG_SW_RESET                  (0x00000080)
+-#define CSR_RESET_REG_FLAG_MASTER_DISABLED           (0x00000100)
+-#define CSR_RESET_REG_FLAG_STOP_MASTER               (0x00000200)
+-
+-/* GP (general purpose) CONTROL */
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY        (0x00000001)
+-#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE              (0x00000004)
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ         (0x00000008)
+-#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)
+-
+-#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN           (0x00000001)
+-
+-#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE         (0x07000000)
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE         (0x04000000)
+-#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW          (0x08000000)
+-
+-
+-/* EEPROM REG */
+-#define CSR_EEPROM_REG_READ_VALID_MSK	(0x00000001)
+-#define CSR_EEPROM_REG_BIT_CMD		(0x00000002)
+-
+-/* EEPROM GP */
+-#define CSR_EEPROM_GP_VALID_MSK		(0x00000006)
+-#define CSR_EEPROM_GP_BAD_SIGNATURE	(0x00000000)
+-#define CSR_EEPROM_GP_IF_OWNER_MSK	(0x00000180)
+-
+-/* UCODE DRV GP */
+-#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP             (0x00000001)
+-#define CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)
+-#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)
+-#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)
+-
+-/* GPIO */
+-#define CSR_GPIO_IN_BIT_AUX_POWER                   (0x00000200)
+-#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC                (0x00000000)
+-#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC		CSR_GPIO_IN_BIT_AUX_POWER
+-
+-/* GI Chicken Bits */
+-#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
+-#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)
+-
+-/* CSR_ANA_PLL_CFG */
+-#define CSR_ANA_PLL_CFG_SH		(0x00880300)
+-
+-/*=== HBUS (Host-side Bus) ===*/
+-#define HBUS_BASE	(0x400)
+-
+-/*
+- * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
+- * structures, error log, event log, verifying uCode load).
+- * First write to address register, then read from or write to data register
+- * to complete the job.  Once the address register is set up, accesses to
+- * data registers auto-increment the address by one dword.
+- * Bit usage for address registers (read or write):
+- *  0-31:  memory address within device
+- */
+-#define HBUS_TARG_MEM_RADDR     (HBUS_BASE+0x00c)
+-#define HBUS_TARG_MEM_WADDR     (HBUS_BASE+0x010)
+-#define HBUS_TARG_MEM_WDAT      (HBUS_BASE+0x018)
+-#define HBUS_TARG_MEM_RDAT      (HBUS_BASE+0x01c)
+-
+-/*
+- * Registers for accessing device's internal peripheral registers
+- * (e.g. SCD, BSM, etc.).  First write to address register,
+- * then read from or write to data register to complete the job.
+- * Bit usage for address registers (read or write):
+- *  0-15:  register address (offset) within device
+- * 24-25:  (# bytes - 1) to read or write (e.g. 3 for dword)
+- */
+-#define HBUS_TARG_PRPH_WADDR    (HBUS_BASE+0x044)
+-#define HBUS_TARG_PRPH_RADDR    (HBUS_BASE+0x048)
+-#define HBUS_TARG_PRPH_WDAT     (HBUS_BASE+0x04c)
+-#define HBUS_TARG_PRPH_RDAT     (HBUS_BASE+0x050)
+-
+-/*
+- * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
+- * Indicates index to next TFD that driver will fill (1 past latest filled).
+- * Bit usage:
+- *  0-7:  queue write index
+- * 11-8:  queue selector
+- */
+-#define HBUS_TARG_WRPTR         (HBUS_BASE+0x060)
+-
+ /* SCD (3945 Tx Frame Scheduler) */
+ #define SCD_BASE                        (CSR_BASE + 0x2E00)
+ 
+@@ -663,7 +456,7 @@ struct iwl3945_eeprom {
+ /* Size of uCode instruction memory in bootstrap state machine */
+ #define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE
+ 
+-#define IWL_MAX_NUM_QUEUES	8
++#define IWL39_MAX_NUM_QUEUES	8
+ 
+ static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
+ {
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
+index 75e20d0..0b94751 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+  *
+  * Portions of this file are derived from the ipw3945 project.
+  *
+@@ -59,28 +59,28 @@
+  *
+  */
+ 
+-#define _iwl3945_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
++#define _iwl3945_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
+ #ifdef CONFIG_IWL3945_DEBUG
+-static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *iwl,
++static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *priv,
+ 				 u32 ofs, u32 val)
+ {
+ 	IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
+-	_iwl3945_write32(iwl, ofs, val);
++	_iwl3945_write32(priv, ofs, val);
+ }
+-#define iwl3945_write32(iwl, ofs, val) \
+-	__iwl3945_write32(__FILE__, __LINE__, iwl, ofs, val)
++#define iwl3945_write32(priv, ofs, val) \
++	__iwl3945_write32(__FILE__, __LINE__, priv, ofs, val)
+ #else
+-#define iwl3945_write32(iwl, ofs, val) _iwl3945_write32(iwl, ofs, val)
++#define iwl3945_write32(priv, ofs, val) _iwl3945_write32(priv, ofs, val)
+ #endif
+ 
+-#define _iwl3945_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
++#define _iwl3945_read32(priv, ofs) readl((priv)->hw_base + (ofs))
+ #ifdef CONFIG_IWL3945_DEBUG
+-static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *iwl, u32 ofs)
++static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u32 ofs)
+ {
+ 	IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
+-	return _iwl3945_read32(iwl, ofs);
++	return _iwl3945_read32(priv, ofs);
+ }
+-#define iwl3945_read32(iwl, ofs) __iwl3945_read32(__FILE__, __LINE__, iwl, ofs)
++#define iwl3945_read32(priv, ofs) __iwl3945_read32(__FILE__, __LINE__, priv, ofs)
+ #else
+ #define iwl3945_read32(p, o) _iwl3945_read32(p, o)
+ #endif
+@@ -105,18 +105,13 @@ static inline int __iwl3945_poll_bit(const char *f, u32 l,
+ 				 u32 bits, u32 mask, int timeout)
+ {
+ 	int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout);
+-	if (unlikely(ret  == -ETIMEDOUT))
+-		IWL_DEBUG_IO
+-		    ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
+-		     addr, bits, mask, f, l);
+-	else
+-		IWL_DEBUG_IO
+-		    ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
+-		     addr, bits, mask, ret, f, l);
++	IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
++		      addr, bits, mask,
++		      unlikely(ret  == -ETIMEDOUT)?"timeout":"", f, l);
+ 	return ret;
+ }
+-#define iwl3945_poll_bit(iwl, addr, bits, mask, timeout) \
+-	__iwl3945_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
++#define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \
++	__iwl3945_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout)
+ #else
+ #define iwl3945_poll_bit(p, a, b, m, t) _iwl3945_poll_bit(p, a, b, m, t)
+ #endif
+@@ -321,8 +316,8 @@ static inline int __iwl3945_poll_direct_bit(const char *f, u32 l,
+ 			     "- %s %d\n", addr, mask, ret, f, l);
+ 	return ret;
+ }
+-#define iwl3945_poll_direct_bit(iwl, addr, mask, timeout) \
+-	__iwl3945_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
++#define iwl3945_poll_direct_bit(priv, addr, mask, timeout) \
++	__iwl3945_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
+ #else
+ #define iwl3945_poll_direct_bit _iwl3945_poll_direct_bit
+ #endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+new file mode 100644
+index 0000000..d200d08
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+@@ -0,0 +1,433 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at 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/version.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/wireless.h>
++#include <net/mac80211.h>
++#include <linux/etherdevice.h>
++#include <asm/unaligned.h>
++
++#include "iwl-3945.h"
++#include "iwl-helpers.h"
++
++#define IWL_1MB_RATE (128 * 1024)
++#define IWL_LED_THRESHOLD (16)
++#define IWL_MAX_BLINK_TBL (10)
++
++static const struct {
++	u16 brightness;
++	u8 on_time;
++	u8 of_time;
++} blink_tbl[] =
++{
++	{300, 25, 25},
++	{200, 40, 40},
++	{100, 55, 55},
++	{70, 65, 65},
++	{50, 75, 75},
++	{20, 85, 85},
++	{15, 95, 95 },
++	{10, 110, 110},
++	{5, 130, 130},
++	{0, 167, 167}
++};
++
++static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv,
++				    struct iwl3945_cmd *cmd,
++				    struct sk_buff *skb)
++{
++	return 1;
++}
++
++
++/* Send led command */
++static int iwl_send_led_cmd(struct iwl3945_priv *priv,
++			    struct iwl3945_led_cmd *led_cmd)
++{
++	struct iwl3945_host_cmd cmd = {
++		.id = REPLY_LEDS_CMD,
++		.len = sizeof(struct iwl3945_led_cmd),
++		.data = led_cmd,
++		.meta.flags = CMD_ASYNC,
++		.meta.u.callback = iwl3945_led_cmd_callback
++	};
++
++	return iwl3945_send_cmd(priv, &cmd);
++}
++
++
++/* Set led on command */
++static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id)
++{
++	struct iwl3945_led_cmd led_cmd = {
++		.id = led_id,
++		.on = IWL_LED_SOLID,
++		.off = 0,
++		.interval = IWL_DEF_LED_INTRVL
++	};
++	return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led on command */
++static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id,
++			       enum led_brightness brightness)
++{
++	struct iwl3945_led_cmd led_cmd = {
++		.id = led_id,
++		.on = brightness,
++		.off = brightness,
++		.interval = IWL_DEF_LED_INTRVL
++	};
++	if (brightness == LED_FULL) {
++		led_cmd.on = IWL_LED_SOLID;
++		led_cmd.off = 0;
++	}
++	return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led register off */
++static int iwl3945_led_on_reg(struct iwl3945_priv *priv, int led_id)
++{
++	IWL_DEBUG_LED("led on %d\n", led_id);
++	return iwl3945_led_on(priv, led_id);
++}
++
++/* Set led off command */
++static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id)
++{
++	struct iwl3945_led_cmd led_cmd = {
++		.id = led_id,
++		.on = 0,
++		.off = 0,
++		.interval = IWL_DEF_LED_INTRVL
++	};
++	IWL_DEBUG_LED("led off %d\n", led_id);
++	return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led register off */
++static int iwl3945_led_off_reg(struct iwl3945_priv *priv, int led_id)
++{
++	iwl3945_led_off(priv, led_id);
++	return 0;
++}
++
++/* Set led blink command */
++static int iwl3945_led_not_solid(struct iwl3945_priv *priv, int led_id,
++			       u8 brightness)
++{
++	struct iwl3945_led_cmd led_cmd = {
++		.id = led_id,
++		.on = brightness,
++		.off = brightness,
++		.interval = IWL_DEF_LED_INTRVL
++	};
++
++	return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++
++/*
++ * brightness call back function for Tx/Rx LED
++ */
++static int iwl3945_led_associated(struct iwl3945_priv *priv, int led_id)
++{
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
++	    !test_bit(STATUS_READY, &priv->status))
++		return 0;
++
++
++	/* start counting Tx/Rx bytes */
++	if (!priv->last_blink_time && priv->allow_blinking)
++		priv->last_blink_time = jiffies;
++	return 0;
++}
++
++/*
++ * brightness call back for association and radio
++ */
++static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
++				enum led_brightness brightness)
++{
++	struct iwl3945_led *led = container_of(led_cdev,
++					       struct iwl3945_led, led_dev);
++	struct iwl3945_priv *priv = led->priv;
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	switch (brightness) {
++	case LED_FULL:
++		if (led->type == IWL_LED_TRG_ASSOC) {
++			priv->allow_blinking = 1;
++			IWL_DEBUG_LED("MAC is  associated\n");
++		}
++		if (led->led_on)
++			led->led_on(priv, IWL_LED_LINK);
++		break;
++	case LED_OFF:
++		if (led->type == IWL_LED_TRG_ASSOC) {
++			priv->allow_blinking = 0;
++			IWL_DEBUG_LED("MAC is disassociated\n");
++		}
++		if (led->led_off)
++			led->led_off(priv, IWL_LED_LINK);
++		break;
++	default:
++		if (led->led_pattern)
++			led->led_pattern(priv, IWL_LED_LINK, brightness);
++		break;
++	}
++}
++
++
++
++/*
++ * Register led class with the system
++ */
++static int iwl3945_led_register_led(struct iwl3945_priv *priv,
++				   struct iwl3945_led *led,
++				   enum led_type type, u8 set_led,
++				   const char *name, char *trigger)
++{
++	struct device *device = wiphy_dev(priv->hw->wiphy);
++	int ret;
++
++	led->led_dev.name = name;
++	led->led_dev.brightness_set = iwl3945_led_brightness_set;
++	led->led_dev.default_trigger = trigger;
++
++	ret = led_classdev_register(device, &led->led_dev);
++	if (ret) {
++		IWL_ERROR("Error: failed to register led handler.\n");
++		return ret;
++	}
++
++	led->priv = priv;
++	led->type = type;
++	led->registered = 1;
++
++	if (set_led && led->led_on)
++		led->led_on(priv, IWL_LED_LINK);
++	return 0;
++}
++
++
++/*
++ * calculate blink rate according to last 2 sec Tx/Rx activities
++ */
++static inline u8 get_blink_rate(struct iwl3945_priv *priv)
++{
++	int index;
++	u8 blink_rate;
++
++	if (priv->rxtxpackets < IWL_LED_THRESHOLD)
++		index = 10;
++	else {
++		for (index = 0; index < IWL_MAX_BLINK_TBL; index++) {
++			if (priv->rxtxpackets > (blink_tbl[index].brightness *
++						 IWL_1MB_RATE))
++				break;
++		}
++	}
++	/* if 0 frame is transfered */
++	if ((index == IWL_MAX_BLINK_TBL) || !priv->allow_blinking)
++		blink_rate = IWL_LED_SOLID;
++	else
++		blink_rate = blink_tbl[index].on_time;
++
++	return blink_rate;
++}
++
++static inline int is_rf_kill(struct iwl3945_priv *priv)
++{
++	return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++		test_bit(STATUS_RF_KILL_SW, &priv->status);
++}
++
++/*
++ * this function called from handler. Since setting Led command can
++ * happen very frequent we postpone led command to be called from
++ * REPLY handler so we know ucode is up
++ */
++void iwl3945_led_background(struct iwl3945_priv *priv)
++{
++	u8 blink_rate;
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++		priv->last_blink_time = 0;
++		return;
++	}
++	if (is_rf_kill(priv)) {
++		priv->last_blink_time = 0;
++		return;
++	}
++
++	if (!priv->allow_blinking) {
++		priv->last_blink_time = 0;
++		if (priv->last_blink_rate != IWL_LED_SOLID) {
++			priv->last_blink_rate = IWL_LED_SOLID;
++			iwl3945_led_on(priv, IWL_LED_LINK);
++		}
++		return;
++	}
++	if (!priv->last_blink_time ||
++	    !time_after(jiffies, priv->last_blink_time +
++			msecs_to_jiffies(1000)))
++		return;
++
++	blink_rate = get_blink_rate(priv);
++
++	/* call only if blink rate change */
++	if (blink_rate != priv->last_blink_rate) {
++		if (blink_rate != IWL_LED_SOLID) {
++			priv->last_blink_time = jiffies +
++						msecs_to_jiffies(1000);
++			iwl3945_led_not_solid(priv, IWL_LED_LINK, blink_rate);
++		} else {
++			priv->last_blink_time = 0;
++			iwl3945_led_on(priv, IWL_LED_LINK);
++		}
++	}
++
++	priv->last_blink_rate = blink_rate;
++	priv->rxtxpackets = 0;
++}
++
++
++/* Register all led handler */
++int iwl3945_led_register(struct iwl3945_priv *priv)
++{
++	char *trigger;
++	char name[32];
++	int ret;
++
++	priv->last_blink_rate = 0;
++	priv->rxtxpackets = 0;
++	priv->last_blink_time = 0;
++	priv->allow_blinking = 0;
++
++	trigger = ieee80211_get_radio_led_name(priv->hw);
++	snprintf(name, sizeof(name), "iwl-%s:radio",
++		 wiphy_name(priv->hw->wiphy));
++
++	priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on_reg;
++	priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off_reg;
++	priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
++
++	ret = iwl3945_led_register_led(priv,
++				   &priv->led[IWL_LED_TRG_RADIO],
++				   IWL_LED_TRG_RADIO, 1,
++				   name, trigger);
++	if (ret)
++		goto exit_fail;
++
++	trigger = ieee80211_get_assoc_led_name(priv->hw);
++	snprintf(name, sizeof(name), "iwl-%s:assoc",
++		 wiphy_name(priv->hw->wiphy));
++
++	ret = iwl3945_led_register_led(priv,
++				   &priv->led[IWL_LED_TRG_ASSOC],
++				   IWL_LED_TRG_ASSOC, 0,
++				   name, trigger);
++	/* for assoc always turn led on */
++	priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on_reg;
++	priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on_reg;
++	priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
++
++	if (ret)
++		goto exit_fail;
++
++	trigger = ieee80211_get_rx_led_name(priv->hw);
++	snprintf(name, sizeof(name), "iwl-%s:RX",
++		 wiphy_name(priv->hw->wiphy));
++
++
++	ret = iwl3945_led_register_led(priv,
++				   &priv->led[IWL_LED_TRG_RX],
++				   IWL_LED_TRG_RX, 0,
++				   name, trigger);
++
++	priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated;
++	priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated;
++	priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern;
++
++	if (ret)
++		goto exit_fail;
++
++	trigger = ieee80211_get_tx_led_name(priv->hw);
++	snprintf(name, sizeof(name), "iwl-%s:TX",
++		 wiphy_name(priv->hw->wiphy));
++	ret = iwl3945_led_register_led(priv,
++				   &priv->led[IWL_LED_TRG_TX],
++				   IWL_LED_TRG_TX, 0,
++				   name, trigger);
++	priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated;
++	priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated;
++	priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern;
++
++	if (ret)
++		goto exit_fail;
++
++	return 0;
++
++exit_fail:
++	iwl3945_led_unregister(priv);
++	return ret;
++}
++
++
++/* unregister led class */
++static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led)
++{
++	if (!led->registered)
++		return;
++
++	led_classdev_unregister(&led->led_dev);
++
++	if (set_led)
++		led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++	led->registered = 0;
++}
++
++/* Unregister all led handlers */
++void iwl3945_led_unregister(struct iwl3945_priv *priv)
++{
++	iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
++	iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
++	iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
++	iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
++}
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h
+new file mode 100644
+index 0000000..b1d2f6b
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h
+@@ -0,0 +1,73 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef IWL3945_LEDS_H
++#define IWL3945_LEDS_H
++
++struct iwl3945_priv;
++
++#ifdef CONFIG_IWL3945_LEDS
++#define IWL_LED_SOLID 11
++#define IWL_LED_NAME_LEN 31
++#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000)
++
++#define IWL_LED_ACTIVITY       (0<<1)
++#define IWL_LED_LINK           (1<<1)
++
++enum led_type {
++	IWL_LED_TRG_TX,
++	IWL_LED_TRG_RX,
++	IWL_LED_TRG_ASSOC,
++	IWL_LED_TRG_RADIO,
++	IWL_LED_TRG_MAX,
++};
++
++#include <linux/leds.h>
++
++struct iwl3945_led {
++	struct iwl3945_priv *priv;
++	struct led_classdev led_dev;
++
++	int (*led_on) (struct iwl3945_priv *priv, int led_id);
++	int (*led_off) (struct iwl3945_priv *priv, int led_id);
++	int (*led_pattern) (struct iwl3945_priv *priv, int led_id,
++			    enum led_brightness brightness);
++
++	enum led_type type;
++	unsigned int registered;
++};
++
++extern int iwl3945_led_register(struct iwl3945_priv *priv);
++extern void iwl3945_led_unregister(struct iwl3945_priv *priv);
++extern void iwl3945_led_background(struct iwl3945_priv *priv);
++
++#else
++static inline int iwl3945_led_register(struct iwl3945_priv *priv) { return 0; }
++static inline void iwl3945_led_unregister(struct iwl3945_priv *priv) {}
++static inline void iwl3945_led_background(struct iwl3945_priv *priv) {}
++#endif /* CONFIG_IWL3945_LEDS */
++
++#endif /* IWL3945_LEDS_H */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+index 80d31ae..85c2264 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 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
+@@ -37,7 +37,7 @@
+ 
+ #include <linux/workqueue.h>
+ 
+-#include "../net/mac80211/ieee80211_rate.h"
++#include "../net/mac80211/rate.h"
+ 
+ #include "iwl-3945.h"
+ 
+@@ -100,14 +100,6 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
+ 	{-89, IWL_RATE_6M_INDEX}
+ };
+ 
+-static struct iwl3945_tpt_entry iwl3945_tpt_table_b[] = {
+-	{-86, IWL_RATE_11M_INDEX},
+-	{-88, IWL_RATE_5M_INDEX},
+-	{-90, IWL_RATE_2M_INDEX},
+-	{-92, IWL_RATE_1M_INDEX}
+-
+-};
+-
+ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
+ 	{-60, IWL_RATE_54M_INDEX},
+ 	{-64, IWL_RATE_48M_INDEX},
+@@ -129,7 +121,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
+ #define IWL_RATE_MIN_SUCCESS_TH       8
+ #define IWL_RATE_DECREASE_TH       1920
+ 
+-static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
++static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
+ {
+ 	u32 index = 0;
+ 	u32 table_size = 0;
+@@ -138,21 +130,19 @@ static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
+ 	if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
+ 		rssi = IWL_MIN_RSSI_VAL;
+ 
+-	switch (mode) {
+-	case MODE_IEEE80211G:
++	switch (band) {
++	case IEEE80211_BAND_2GHZ:
+ 		tpt_table = iwl3945_tpt_table_g;
+ 		table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
+ 		break;
+ 
+-	case MODE_IEEE80211A:
++	case IEEE80211_BAND_5GHZ:
+ 		tpt_table = iwl3945_tpt_table_a;
+ 		table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
+ 		break;
+ 
+ 	default:
+-	case MODE_IEEE80211B:
+-		tpt_table = iwl3945_tpt_table_b;
+-		table_size = ARRAY_SIZE(iwl3945_tpt_table_b);
++		BUG();
+ 		break;
+ 	}
+ 
+@@ -168,9 +158,9 @@ static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
+ {
+ 	window->data = 0;
+ 	window->success_counter = 0;
+-	window->success_ratio = IWL_INVALID_VALUE;
++	window->success_ratio = -1;
+ 	window->counter = 0;
+-	window->average_tpt = IWL_INVALID_VALUE;
++	window->average_tpt = IWL_INV_TPT;
+ 	window->stamp = 0;
+ }
+ 
+@@ -340,17 +330,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ 	 * after assoc.. */
+ 
+ 	for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
+-		if (sta->supp_rates & (1 << i)) {
+-			sta->txrate = i;
++		if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) {
++			sta->txrate_idx = i;
+ 			break;
+ 		}
+ 	}
+ 
+-	sta->last_txrate = sta->txrate;
++	sta->last_txrate_idx = sta->txrate_idx;
+ 
+-	/* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */
+-        if (local->hw.conf.phymode == MODE_IEEE80211A)
+-                sta->last_txrate += IWL_FIRST_OFDM_RATE;
++	/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
++	if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
++		sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+ 
+ 	IWL_DEBUG_RATE("leave\n");
+ }
+@@ -429,17 +419,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
+ {
+ 	int next_rate = iwl3945_get_prev_ieee_rate(rate);
+ 
+-	switch (priv->phymode) {
+-	case MODE_IEEE80211A:
++	switch (priv->band) {
++	case IEEE80211_BAND_5GHZ:
+ 		if (rate == IWL_RATE_12M_INDEX)
+ 			next_rate = IWL_RATE_9M_INDEX;
+ 		else if (rate == IWL_RATE_6M_INDEX)
+ 			next_rate = IWL_RATE_6M_INDEX;
+ 		break;
++/* XXX cannot be invoked in current mac80211 so not a regression
+ 	case MODE_IEEE80211B:
+ 		if (rate == IWL_RATE_11M_INDEX_TABLE)
+ 			next_rate = IWL_RATE_5M_INDEX_TABLE;
+ 		break;
++ */
+ 	default:
+ 		break;
+ 	}
+@@ -465,22 +457,25 @@ static void rs_tx_status(void *priv_rate,
+ 	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
+ 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ 	struct iwl3945_rs_sta *rs_sta;
++	struct ieee80211_supported_band *sband;
+ 
+ 	IWL_DEBUG_RATE("enter\n");
+ 
+-	retries = tx_resp->retry_count;
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ 
+-	first_index = tx_resp->control.tx_rate;
++
++	retries = tx_resp->retry_count;
++	first_index = tx_resp->control.tx_rate->hw_value;
+ 	if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
+-		IWL_DEBUG_RATE("leave: Rate out of bounds: %0x for %d\n",
+-			       tx_resp->control.tx_rate, first_index);
++		IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
+ 		return;
+ 	}
+ 
++	rcu_read_lock();
++
+ 	sta = sta_info_get(local, hdr->addr1);
+ 	if (!sta || !sta->rate_ctrl_priv) {
+-		if (sta)
+-			sta_info_put(sta);
++		rcu_read_unlock();
+ 		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
+ 		return;
+ 	}
+@@ -553,7 +548,7 @@ static void rs_tx_status(void *priv_rate,
+ 
+ 	spin_unlock_irqrestore(&rs_sta->lock, flags);
+ 
+-	sta_info_put(sta);
++	rcu_read_unlock();
+ 
+ 	IWL_DEBUG_RATE("leave\n");
+ 
+@@ -561,14 +556,14 @@ static void rs_tx_status(void *priv_rate,
+ }
+ 
+ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
+-				 u8 index, u16 rate_mask, int phymode)
++				 u8 index, u16 rate_mask, enum ieee80211_band band)
+ {
+ 	u8 high = IWL_RATE_INVALID;
+ 	u8 low = IWL_RATE_INVALID;
+ 
+ 	/* 802.11A walks to the next literal adjacent rate in
+ 	 * the rate table */
+-	if (unlikely(phymode == MODE_IEEE80211A)) {
++	if (unlikely(band == IEEE80211_BAND_5GHZ)) {
+ 		int i;
+ 		u32 mask;
+ 
+@@ -639,7 +634,8 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
+  *
+  */
+ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+-			struct ieee80211_hw_mode *mode, struct sk_buff *skb,
++			struct ieee80211_supported_band *sband,
++			struct sk_buff *skb,
+ 			struct rate_selection *sel)
+ {
+ 	u8 low = IWL_RATE_INVALID;
+@@ -648,9 +644,9 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 	int index;
+ 	struct iwl3945_rs_sta *rs_sta;
+ 	struct iwl3945_rate_scale_data *window = NULL;
+-	int current_tpt = IWL_INVALID_VALUE;
+-	int low_tpt = IWL_INVALID_VALUE;
+-	int high_tpt = IWL_INVALID_VALUE;
++	int current_tpt = IWL_INV_TPT;
++	int low_tpt = IWL_INV_TPT;
++	int high_tpt = IWL_INV_TPT;
+ 	u32 fail_count;
+ 	s8 scale_action = 0;
+ 	unsigned long flags;
+@@ -663,6 +659,8 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 
+ 	IWL_DEBUG_RATE("enter\n");
+ 
++	rcu_read_lock();
++
+ 	sta = sta_info_get(local, hdr->addr1);
+ 
+ 	/* Send management frames and broadcast/multicast data using lowest
+@@ -672,16 +670,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 	    is_multicast_ether_addr(hdr->addr1) ||
+ 	    !sta || !sta->rate_ctrl_priv) {
+ 		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
+-		sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+-		if (sta)
+-			sta_info_put(sta);
++		sel->rate = rate_lowest(local, sband, sta);
++		rcu_read_unlock();
+ 		return;
+ 	}
+ 
+-	rate_mask = sta->supp_rates;
+-	index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1);
++	rate_mask = sta->supp_rates[sband->band];
++	index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
+ 
+-	if (priv->phymode == (u8) MODE_IEEE80211A)
++	if (sband->band == IEEE80211_BAND_5GHZ)
+ 		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
+ 
+ 	rs_sta = (void *)sta->rate_ctrl_priv;
+@@ -713,7 +710,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 
+ 	if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
+ 	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
+-		window->average_tpt = IWL_INVALID_VALUE;
++		window->average_tpt = IWL_INV_TPT;
+ 		spin_unlock_irqrestore(&rs_sta->lock, flags);
+ 
+ 		IWL_DEBUG_RATE("Invalid average_tpt on rate %d: "
+@@ -732,7 +729,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 	current_tpt = window->average_tpt;
+ 
+ 	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
+-					 local->hw.conf.phymode);
++					     sband->band);
+ 	low = high_low & 0xff;
+ 	high = (high_low >> 8) & 0xff;
+ 
+@@ -749,19 +746,16 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 	if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
+ 		IWL_DEBUG_RATE("decrease rate because of low success_ratio\n");
+ 		scale_action = -1;
+-	} else if ((low_tpt == IWL_INVALID_VALUE) &&
+-		   (high_tpt == IWL_INVALID_VALUE))
++	} else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
+ 		scale_action = 1;
+-	else if ((low_tpt != IWL_INVALID_VALUE) &&
+-		   (high_tpt != IWL_INVALID_VALUE)
+-		   && (low_tpt < current_tpt)
+-		   && (high_tpt < current_tpt)) {
++	else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
++		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
+ 		IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < "
+ 			       "current_tpt [%d]\n",
+ 			       low_tpt, high_tpt, current_tpt);
+ 		scale_action = 0;
+ 	} else {
+-		if (high_tpt != IWL_INVALID_VALUE) {
++		if (high_tpt != IWL_INV_TPT) {
+ 			if (high_tpt > current_tpt)
+ 				scale_action = 1;
+ 			else {
+@@ -769,7 +763,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 				    ("decrease rate because of high tpt\n");
+ 				scale_action = -1;
+ 			}
+-		} else if (low_tpt != IWL_INVALID_VALUE) {
++		} else if (low_tpt != IWL_INV_TPT) {
+ 			if (low_tpt > current_tpt) {
+ 				IWL_DEBUG_RATE
+ 				    ("decrease rate because of low tpt\n");
+@@ -810,17 +804,17 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 
+  out:
+ 
+-	sta->last_txrate = index;
+-	if (priv->phymode == (u8) MODE_IEEE80211A)
+-		sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE;
++	sta->last_txrate_idx = index;
++	if (sband->band == IEEE80211_BAND_5GHZ)
++		sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
+ 	else
+-		sta->txrate = sta->last_txrate;
++		sta->txrate_idx = sta->last_txrate_idx;
+ 
+-	sta_info_put(sta);
++	rcu_read_unlock();
+ 
+ 	IWL_DEBUG_RATE("leave: %d\n", index);
+ 
+-	sel->rate = &priv->ieee_rates[index];
++	sel->rate = &sband->bitrates[sta->txrate_idx];
+ }
+ 
+ static struct rate_control_ops rs_ops = {
+@@ -848,13 +842,15 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+ 	unsigned long now = jiffies;
+ 	u32 max_time = 0;
+ 
++	rcu_read_lock();
++
+ 	sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
+ 	if (!sta || !sta->rate_ctrl_priv) {
+-		if (sta) {
+-			sta_info_put(sta);
++		if (sta)
+ 			IWL_DEBUG_RATE("leave - no private rate data!\n");
+-		} else
++		else
+ 			IWL_DEBUG_RATE("leave - no station!\n");
++		rcu_read_unlock();
+ 		return sprintf(buf, "station %d not found\n", sta_id);
+ 	}
+ 
+@@ -895,7 +891,7 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+ 		i = j;
+ 	}
+ 	spin_unlock_irqrestore(&rs_sta->lock, flags);
+-	sta_info_put(sta);
++	rcu_read_unlock();
+ 
+ 	/* Display the average rate of all samples taken.
+ 	 *
+@@ -932,11 +928,12 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+ 		return;
+ 	}
+ 
++	rcu_read_lock();
++
+ 	sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
+ 	if (!sta || !sta->rate_ctrl_priv) {
+-		if (sta)
+-			sta_info_put(sta);
+ 		IWL_DEBUG_RATE("leave - no private rate data!\n");
++		rcu_read_unlock();
+ 		return;
+ 	}
+ 
+@@ -945,8 +942,9 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+ 	spin_lock_irqsave(&rs_sta->lock, flags);
+ 
+ 	rs_sta->tgg = 0;
+-	switch (priv->phymode) {
+-	case MODE_IEEE80211G:
++	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) {
+ 			rs_sta->tgg = 1;
+ 			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
+@@ -954,18 +952,15 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+ 			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
+ 		break;
+ 
+-	case MODE_IEEE80211A:
++	case IEEE80211_BAND_5GHZ:
+ 		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
+ 		break;
+-
+-	default:
+-		IWL_WARNING("Invalid phymode.  Defaulting to 802.11b\n");
+-	case MODE_IEEE80211B:
+-		rs_sta->expected_tpt = iwl3945_expected_tpt_b;
++	case IEEE80211_NUM_BANDS:
++		BUG();
+ 		break;
+ 	}
+ 
+-	sta_info_put(sta);
++	rcu_read_unlock();
+ 	spin_unlock_irqrestore(&rs_sta->lock, flags);
+ 
+ 	rssi = priv->last_rx_rssi;
+@@ -974,20 +969,19 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+ 
+ 	IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi);
+ 
+-	rs_sta->start_rate =
+-			iwl3945_get_rate_index_by_rssi(rssi, priv->phymode);
++	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
+ 
+ 	IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
+ 		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
+ 		       iwl3945_rates[rs_sta->start_rate].plcp);
+ }
+ 
+-void iwl3945_rate_control_register(struct ieee80211_hw *hw)
++int iwl3945_rate_control_register(void)
+ {
+-	ieee80211_rate_control_register(&rs_ops);
++	return ieee80211_rate_control_register(&rs_ops);
+ }
+ 
+-void iwl3945_rate_control_unregister(struct ieee80211_hw *hw)
++void iwl3945_rate_control_unregister(void)
+ {
+ 	ieee80211_rate_control_unregister(&rs_ops);
+ }
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
+index d5e9220..f085d33 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 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
+@@ -36,8 +36,8 @@ struct iwl3945_rate_info {
+ 	u8 next_rs;		/* next rate used in rs algo */
+ 	u8 prev_rs_tgg;		/* previous rate used in TGG rs algo */
+ 	u8 next_rs_tgg;		/* next rate used in TGG rs algo */
+-        u8 table_rs_index;	/* index in rate scale table cmd */
+-        u8 prev_table_rs;	/* prev in rate table cmd */
++	u8 table_rs_index;	/* index in rate scale table cmd */
++	u8 prev_table_rs;	/* prev in rate table cmd */
+ };
+ 
+ /*
+@@ -159,7 +159,7 @@ enum {
+ 
+ #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
+ 
+-#define IWL_INVALID_VALUE    -1
++#define IWL_INV_TPT    -1
+ 
+ #define IWL_MIN_RSSI_VAL                 -100
+ #define IWL_MAX_RSSI_VAL                    0
+@@ -202,7 +202,7 @@ extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+  * ieee80211_register_hw
+  *
+  */
+-extern void iwl3945_rate_control_register(struct ieee80211_hw *hw);
++extern int iwl3945_rate_control_register(void);
+ 
+ /**
+  * iwl3945_rate_control_unregister - Unregister the rate control callbacks
+@@ -210,6 +210,6 @@ extern void iwl3945_rate_control_register(struct ieee80211_hw *hw);
+  * This should be called after calling ieee80211_unregister_hw, but before
+  * the driver is unloaded.
+  */
+-extern void iwl3945_rate_control_unregister(struct ieee80211_hw *hw);
++extern void iwl3945_rate_control_unregister(void);
+ 
+ #endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
+index 8d4d91d..598e4ee 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
++++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 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
+@@ -39,6 +39,7 @@
+ #include <asm/unaligned.h>
+ #include <net/mac80211.h>
+ 
++#include "iwl-3945-core.h"
+ #include "iwl-3945.h"
+ #include "iwl-helpers.h"
+ #include "iwl-3945-rs.h"
+@@ -183,6 +184,16 @@ void iwl3945_disable_events(struct iwl3945_priv *priv)
+ 
+ }
+ 
++static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
++{
++	int idx;
++
++	for (idx = 0; idx < IWL_RATE_COUNT; idx++)
++		if (iwl3945_rates[idx].plcp == plcp)
++			return idx;
++	return -1;
++}
++
+ /**
+  * iwl3945_get_antenna_flags - Get antenna flags for RXON command
+  * @priv: eeprom and antenna fields are used to determine antenna flags
+@@ -216,14 +227,126 @@ __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv)
+ 	return 0;		/* "diversity" is default if error */
+ }
+ 
++#ifdef CONFIG_IWL3945_DEBUG
++#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
++
++static const char *iwl3945_get_tx_fail_reason(u32 status)
++{
++	switch (status & TX_STATUS_MSK) {
++	case TX_STATUS_SUCCESS:
++		return "SUCCESS";
++		TX_STATUS_ENTRY(SHORT_LIMIT);
++		TX_STATUS_ENTRY(LONG_LIMIT);
++		TX_STATUS_ENTRY(FIFO_UNDERRUN);
++		TX_STATUS_ENTRY(MGMNT_ABORT);
++		TX_STATUS_ENTRY(NEXT_FRAG);
++		TX_STATUS_ENTRY(LIFE_EXPIRE);
++		TX_STATUS_ENTRY(DEST_PS);
++		TX_STATUS_ENTRY(ABORTED);
++		TX_STATUS_ENTRY(BT_RETRY);
++		TX_STATUS_ENTRY(STA_INVALID);
++		TX_STATUS_ENTRY(FRAG_DROPPED);
++		TX_STATUS_ENTRY(TID_DISABLE);
++		TX_STATUS_ENTRY(FRAME_FLUSHED);
++		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
++		TX_STATUS_ENTRY(TX_LOCKED);
++		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
++	}
++
++	return "UNKNOWN";
++}
++#else
++static inline const char *iwl3945_get_tx_fail_reason(u32 status)
++{
++	return "";
++}
++#endif
++
++
++/**
++ * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
++ *
++ * When FW advances 'R' index, all entries between old and new 'R' index
++ * need to be reclaimed. As result, some free space forms. If there is
++ * enough free space (> low mark), wake the stack that feeds us.
++ */
++static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv,
++				     int txq_id, int index)
++{
++	struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
++	struct iwl3945_queue *q = &txq->q;
++	struct iwl3945_tx_info *tx_info;
++
++	BUG_ON(txq_id == IWL_CMD_QUEUE_NUM);
++
++	for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
++		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
++
++		tx_info = &txq->txb[txq->q.read_ptr];
++		ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0],
++					    &tx_info->status);
++		tx_info->skb[0] = NULL;
++		iwl3945_hw_txq_free_tfd(priv, txq);
++	}
++
++	if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
++			(txq_id != IWL_CMD_QUEUE_NUM) &&
++			priv->mac80211_registered)
++		ieee80211_wake_queue(priv->hw, txq_id);
++}
++
++/**
++ * iwl3945_rx_reply_tx - Handle Tx response
++ */
++static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
++			    struct iwl3945_rx_mem_buffer *rxb)
++{
++	struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
++	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
++	int txq_id = SEQ_TO_QUEUE(sequence);
++	int index = SEQ_TO_INDEX(sequence);
++	struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
++	struct ieee80211_tx_status *tx_status;
++	struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
++	u32  status = le32_to_cpu(tx_resp->status);
++	int rate_idx;
++
++	if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) {
++		IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
++			  "is out of range [0-%d] %d %d\n", txq_id,
++			  index, txq->q.n_bd, txq->q.write_ptr,
++			  txq->q.read_ptr);
++		return;
++	}
++
++	tx_status = &(txq->txb[txq->q.read_ptr].status);
++
++	tx_status->retry_count = tx_resp->failure_frame;
++	/* tx_status->rts_retry_count = tx_resp->failure_rts; */
++	tx_status->flags = ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
++				IEEE80211_TX_STATUS_ACK : 0;
++
++	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
++			txq_id, iwl3945_get_tx_fail_reason(status), status,
++			tx_resp->rate, tx_resp->failure_frame);
++
++	rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
++	tx_status->control.tx_rate = &priv->ieee_rates[rate_idx];
++	IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
++	iwl3945_tx_queue_reclaim(priv, txq_id, index);
++
++	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
++		IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
++}
++
++
++
+ /*****************************************************************************
+  *
+  * Intel PRO/Wireless 3945ABG/BG Network Connection
+  *
+  *  RX handler implementations
+  *
+- *  Used by iwl-base.c
+- *
+  *****************************************************************************/
+ 
+ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb)
+@@ -235,9 +358,161 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_b
+ 
+ 	memcpy(&priv->statistics, pkt->u.raw, sizeof(priv->statistics));
+ 
++	iwl3945_led_background(priv);
++
+ 	priv->last_statistics_time = jiffies;
+ }
+ 
++/******************************************************************************
++ *
++ * Misc. internal state and helper functions
++ *
++ ******************************************************************************/
++#ifdef CONFIG_IWL3945_DEBUG
++
++/**
++ * iwl3945_report_frame - dump frame to syslog during debug sessions
++ *
++ * You may hack this function to show different aspects of received frames,
++ * including selective frame dumps.
++ * group100 parameter selects whether to show 1 out of 100 good frames.
++ */
++static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
++		      struct iwl3945_rx_packet *pkt,
++		      struct ieee80211_hdr *header, int group100)
++{
++	u32 to_us;
++	u32 print_summary = 0;
++	u32 print_dump = 0;	/* set to 1 to dump all frames' contents */
++	u32 hundred = 0;
++	u32 dataframe = 0;
++	u16 fc;
++	u16 seq_ctl;
++	u16 channel;
++	u16 phy_flags;
++	u16 length;
++	u16 status;
++	u16 bcn_tmr;
++	u32 tsf_low;
++	u64 tsf;
++	u8 rssi;
++	u8 agc;
++	u16 sig_avg;
++	u16 noise_diff;
++	struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
++	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
++	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
++	u8 *data = IWL_RX_DATA(pkt);
++
++	/* MAC header */
++	fc = le16_to_cpu(header->frame_control);
++	seq_ctl = le16_to_cpu(header->seq_ctrl);
++
++	/* metadata */
++	channel = le16_to_cpu(rx_hdr->channel);
++	phy_flags = le16_to_cpu(rx_hdr->phy_flags);
++	length = le16_to_cpu(rx_hdr->len);
++
++	/* end-of-frame status and timestamp */
++	status = le32_to_cpu(rx_end->status);
++	bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
++	tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
++	tsf = le64_to_cpu(rx_end->timestamp);
++
++	/* signal statistics */
++	rssi = rx_stats->rssi;
++	agc = rx_stats->agc;
++	sig_avg = le16_to_cpu(rx_stats->sig_avg);
++	noise_diff = le16_to_cpu(rx_stats->noise_diff);
++
++	to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
++
++	/* if data frame is to us and all is good,
++	 *   (optionally) print summary for only 1 out of every 100 */
++	if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
++	    (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
++		dataframe = 1;
++		if (!group100)
++			print_summary = 1;	/* print each frame */
++		else if (priv->framecnt_to_us < 100) {
++			priv->framecnt_to_us++;
++			print_summary = 0;
++		} else {
++			priv->framecnt_to_us = 0;
++			print_summary = 1;
++			hundred = 1;
++		}
++	} else {
++		/* print summary for all other frames */
++		print_summary = 1;
++	}
++
++	if (print_summary) {
++		char *title;
++		u32 rate;
++
++		if (hundred)
++			title = "100Frames";
++		else if (fc & IEEE80211_FCTL_RETRY)
++			title = "Retry";
++		else if (ieee80211_is_assoc_response(fc))
++			title = "AscRsp";
++		else if (ieee80211_is_reassoc_response(fc))
++			title = "RasRsp";
++		else if (ieee80211_is_probe_response(fc)) {
++			title = "PrbRsp";
++			print_dump = 1;	/* dump frame contents */
++		} else if (ieee80211_is_beacon(fc)) {
++			title = "Beacon";
++			print_dump = 1;	/* dump frame contents */
++		} else if (ieee80211_is_atim(fc))
++			title = "ATIM";
++		else if (ieee80211_is_auth(fc))
++			title = "Auth";
++		else if (ieee80211_is_deauth(fc))
++			title = "DeAuth";
++		else if (ieee80211_is_disassoc(fc))
++			title = "DisAssoc";
++		else
++			title = "Frame";
++
++		rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
++		if (rate == -1)
++			rate = 0;
++		else
++			rate = iwl3945_rates[rate].ieee / 2;
++
++		/* print frame summary.
++		 * MAC addresses show just the last byte (for brevity),
++		 *    but you can hack it to show more, if you'd like to. */
++		if (dataframe)
++			IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
++				     "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
++				     title, fc, header->addr1[5],
++				     length, rssi, channel, rate);
++		else {
++			/* src/dst addresses assume managed mode */
++			IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
++				     "src=0x%02x, rssi=%u, tim=%lu usec, "
++				     "phy=0x%02x, chnl=%d\n",
++				     title, fc, header->addr1[5],
++				     header->addr3[5], rssi,
++				     tsf_low - priv->scan_start_tsf,
++				     phy_flags, channel);
++		}
++	}
++	if (print_dump)
++		iwl3945_print_hex_dump(IWL_DL_RX, data, length);
++}
++#else
++static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
++		      struct iwl3945_rx_packet *pkt,
++		      struct ieee80211_hdr *header, int group100)
++{
++}
++#endif
++
++
+ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
+ 				 struct sk_buff *skb,
+ 				 struct iwl3945_rx_frame_hdr *rx_hdr,
+@@ -247,9 +522,9 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
+ 	 * the information provided in the skb from the hardware */
+ 	s8 signal = stats->ssi;
+ 	s8 noise = 0;
+-	int rate = stats->rate;
++	int rate = stats->rate_idx;
+ 	u64 tsf = stats->mactime;
+-	__le16 phy_flags_hw = rx_hdr->phy_flags;
++	__le16 phy_flags_hw = rx_hdr->phy_flags, antenna;
+ 
+ 	struct iwl3945_rt_rx_hdr {
+ 		struct ieee80211_radiotap_header rt_hdr;
+@@ -315,15 +590,14 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
+ 					  IEEE80211_CHAN_2GHZ),
+ 			      &iwl3945_rt->rt_chbitmask);
+ 
+-	rate = iwl3945_rate_index_from_plcp(rate);
+ 	if (rate == -1)
+ 		iwl3945_rt->rt_rate = 0;
+ 	else
+ 		iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
+ 
+ 	/* antenna number */
+-	iwl3945_rt->rt_antenna =
+-		le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
++	antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
++	iwl3945_rt->rt_antenna = le16_to_cpu(antenna) >> 4;
+ 
+ 	/* set the preamble flag if we have it */
+ 	if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+@@ -368,6 +642,10 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
+ 	if (priv->add_radiotap)
+ 		iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats);
+ 
++#ifdef CONFIG_IWL3945_LEDS
++	if (is_data)
++		priv->rxtxpackets += len;
++#endif
+ 	ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
+ 	rxb->skb = NULL;
+ }
+@@ -377,25 +655,28 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
+ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ 				struct iwl3945_rx_mem_buffer *rxb)
+ {
++	struct ieee80211_hdr *header;
++	struct ieee80211_rx_status rx_status;
+ 	struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ 	struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+ 	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+ 	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
+-	struct ieee80211_hdr *header;
++	int snr;
+ 	u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg);
+ 	u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff);
+-	struct ieee80211_rx_status stats = {
+-		.mactime = le64_to_cpu(rx_end->timestamp),
+-		.freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)),
+-		.channel = le16_to_cpu(rx_hdr->channel),
+-		.phymode = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+-		MODE_IEEE80211G : MODE_IEEE80211A,
+-		.antenna = 0,
+-		.rate = rx_hdr->rate,
+-		.flag = 0,
+-	};
+ 	u8 network_packet;
+-	int snr;
++
++	rx_status.antenna = 0;
++	rx_status.flag = 0;
++	rx_status.mactime = le64_to_cpu(rx_end->timestamp);
++	rx_status.freq =
++		ieee80211_frequency_to_channel(le16_to_cpu(rx_hdr->channel));
++	rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
++				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
++
++	rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
++	if (rx_status.band == IEEE80211_BAND_5GHZ)
++		rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
+ 
+ 	if ((unlikely(rx_stats->phy_count > 20))) {
+ 		IWL_DEBUG_DROP
+@@ -411,12 +692,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ 	}
+ 
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
+-		iwl3945_handle_data_packet(priv, 1, rxb, &stats);
++		iwl3945_handle_data_packet(priv, 1, rxb, &rx_status);
+ 		return;
+ 	}
+ 
+ 	/* Convert 3945's rssi indicator to dBm */
+-	stats.ssi = rx_stats->rssi - IWL_RSSI_OFFSET;
++	rx_status.ssi = rx_stats->rssi - IWL_RSSI_OFFSET;
+ 
+ 	/* Set default noise value to -127 */
+ 	if (priv->last_rx_noise == 0)
+@@ -432,51 +713,47 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ 	 *   signal-to-noise ratio (SNR) is (sig_avg / noise_diff).
+ 	 * Convert linear SNR to dB SNR, then subtract that from rssi dBm
+ 	 *   to obtain noise level in dBm.
+-	 * Calculate stats.signal (quality indicator in %) based on SNR. */
++	 * Calculate rx_status.signal (quality indicator in %) based on SNR. */
+ 	if (rx_stats_noise_diff) {
+ 		snr = rx_stats_sig_avg / rx_stats_noise_diff;
+-		stats.noise = stats.ssi - iwl3945_calc_db_from_ratio(snr);
+-		stats.signal = iwl3945_calc_sig_qual(stats.ssi, stats.noise);
++		rx_status.noise = rx_status.ssi -
++					iwl3945_calc_db_from_ratio(snr);
++		rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi,
++							 rx_status.noise);
+ 
+ 	/* If noise info not available, calculate signal quality indicator (%)
+ 	 *   using just the dBm signal level. */
+ 	} else {
+-		stats.noise = priv->last_rx_noise;
+-		stats.signal = iwl3945_calc_sig_qual(stats.ssi, 0);
++		rx_status.noise = priv->last_rx_noise;
++		rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, 0);
+ 	}
+ 
+ 
+ 	IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n",
+-			stats.ssi, stats.noise, stats.signal,
++			rx_status.ssi, rx_status.noise, rx_status.signal,
+ 			rx_stats_sig_avg, rx_stats_noise_diff);
+ 
+-	stats.freq = ieee80211chan2mhz(stats.channel);
+-
+-	/* can be covered by iwl3945_report_frame() in most cases */
+-/*      IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */
+-
+ 	header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
+ 
+ 	network_packet = iwl3945_is_network_packet(priv, header);
+ 
+-#ifdef CONFIG_IWL3945_DEBUG
+-	if (iwl3945_debug_level & IWL_DL_STATS && net_ratelimit())
+-		IWL_DEBUG_STATS
+-		    ("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n",
+-		     network_packet ? '*' : ' ',
+-		     stats.channel, stats.ssi, stats.ssi,
+-		     stats.ssi, stats.rate);
++	IWL_DEBUG_STATS_LIMIT("[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n",
++			      network_packet ? '*' : ' ',
++			      le16_to_cpu(rx_hdr->channel),
++			      rx_status.ssi, rx_status.ssi,
++			      rx_status.ssi, rx_status.rate_idx);
+ 
++#ifdef CONFIG_IWL3945_DEBUG
+ 	if (iwl3945_debug_level & (IWL_DL_RX))
+ 		/* Set "1" to report good data frames in groups of 100 */
+-		iwl3945_report_frame(priv, pkt, header, 1);
++		iwl3945_dbg_report_frame(priv, pkt, header, 1);
+ #endif
+ 
+ 	if (network_packet) {
+ 		priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
+ 		priv->last_tsf = le64_to_cpu(rx_end->timestamp);
+-		priv->last_rx_rssi = stats.ssi;
+-		priv->last_rx_noise = stats.noise;
++		priv->last_rx_rssi = rx_status.ssi;
++		priv->last_rx_noise = rx_status.noise;
+ 	}
+ 
+ 	switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) {
+@@ -563,7 +840,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ 			}
+ 		}
+ 
+-		iwl3945_handle_data_packet(priv, 0, rxb, &stats);
++		iwl3945_handle_data_packet(priv, 0, rxb, &rx_status);
+ 		break;
+ 
+ 	case IEEE80211_FTYPE_CTL:
+@@ -580,7 +857,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ 				       print_mac(mac2, header->addr2),
+ 				       print_mac(mac3, header->addr3));
+ 		else
+-			iwl3945_handle_data_packet(priv, 1, rxb, &stats);
++			iwl3945_handle_data_packet(priv, 1, rxb, &rx_status);
+ 		break;
+ 	}
+ 	}
+@@ -689,7 +966,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
+ 			      struct ieee80211_hdr *hdr, int sta_id, int tx_id)
+ {
+ 	unsigned long flags;
+-	u16 rate_index = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
++	u16 rate_index = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
+ 	u16 rate_mask;
+ 	int rate;
+ 	u8 rts_retry_limit;
+@@ -709,7 +986,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
+ 	priv->stations[sta_id].current_rate.rate_n_flags = rate;
+ 
+ 	if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+-	    (sta_id != IWL3945_BROADCAST_ID) &&
++	    (sta_id != priv->hw_setting.bcast_sta_id) &&
+ 		(sta_id != IWL_MULTICAST_ID))
+ 		priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate;
+ 
+@@ -996,19 +1273,19 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
+ 	if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
+ 		IWL_DEBUG_INFO("RTP type \n");
+ 	else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
+-		IWL_DEBUG_INFO("ALM-MB type\n");
++		IWL_DEBUG_INFO("3945 RADIO-MB type\n");
+ 		iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+-			    CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB);
++			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
+ 	} else {
+-		IWL_DEBUG_INFO("ALM-MM type\n");
++		IWL_DEBUG_INFO("3945 RADIO-MM type\n");
+ 		iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+-			    CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM);
++			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
+ 	}
+ 
+ 	if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) {
+ 		IWL_DEBUG_INFO("SKU OP mode is mrc\n");
+ 		iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+-			    CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC);
++			    CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
+ 	} else
+ 		IWL_DEBUG_INFO("SKU OP mode is basic\n");
+ 
+@@ -1016,24 +1293,24 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
+ 		IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
+ 			       priv->eeprom.board_revision);
+ 		iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+-			    CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
++			    CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+ 	} else {
+ 		IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
+ 			       priv->eeprom.board_revision);
+ 		iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+-			      CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
++			      CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+ 	}
+ 
+ 	if (priv->eeprom.almgor_m_version <= 1) {
+ 		iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+-			    CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
++			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
+ 		IWL_DEBUG_INFO("Card M type A version is 0x%X\n",
+ 			       priv->eeprom.almgor_m_version);
+ 	} else {
+ 		IWL_DEBUG_INFO("Card M type B version is 0x%X\n",
+ 			       priv->eeprom.almgor_m_version);
+ 		iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+-			    CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
++			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
+ 	}
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+@@ -1552,14 +1829,14 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
+ 		.channel = priv->active_rxon.channel,
+ 	};
+ 
+-	txpower.band = (priv->phymode == MODE_IEEE80211A) ? 0 : 1;
++	txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
+ 	ch_info = iwl3945_get_channel_info(priv,
+-				       priv->phymode,
++				       priv->band,
+ 				       le16_to_cpu(priv->active_rxon.channel));
+ 	if (!ch_info) {
+ 		IWL_ERROR
+ 		    ("Failed to get channel info for channel %d [%d]\n",
+-		     le16_to_cpu(priv->active_rxon.channel), priv->phymode);
++		     le16_to_cpu(priv->active_rxon.channel), priv->band);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -2241,8 +2518,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
+ 		table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index;
+ 	}
+ 
+-	switch (priv->phymode) {
+-	case MODE_IEEE80211A:
++	switch (priv->band) {
++	case IEEE80211_BAND_5GHZ:
+ 		IWL_DEBUG_RATE("Select A mode rate scale\n");
+ 		/* If one of the following CCK rates is used,
+ 		 * have it fall back to the 6M OFDM rate */
+@@ -2257,8 +2534,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
+ 		    iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
+ 		break;
+ 
+-	case MODE_IEEE80211B:
+-		IWL_DEBUG_RATE("Select B mode rate scale\n");
++	case IEEE80211_BAND_2GHZ:
++		IWL_DEBUG_RATE("Select B/G mode rate scale\n");
+ 		/* If an OFDM rate is used, have it fall back to the
+ 		 * 1M CCK rates */
+ 		for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
+@@ -2269,7 +2546,7 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
+ 		break;
+ 
+ 	default:
+-		IWL_DEBUG_RATE("Select G mode rate scale\n");
++		WARN_ON(1);
+ 		break;
+ 	}
+ 
+@@ -2303,7 +2580,6 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
+ 		return -ENOMEM;
+ 	}
+ 
+-	priv->hw_setting.ac_queue_count = AC_NUM;
+ 	priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE;
+ 	priv->hw_setting.max_pkt_size = 2342;
+ 	priv->hw_setting.tx_cmd_len = sizeof(struct iwl3945_tx_cmd);
+@@ -2311,6 +2587,8 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
+ 	priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
+ 	priv->hw_setting.max_stations = IWL3945_STATION_COUNT;
+ 	priv->hw_setting.bcast_sta_id = IWL3945_BROADCAST_ID;
++
++	priv->hw_setting.tx_ant_num = 2;
+ 	return 0;
+ }
+ 
+@@ -2323,7 +2601,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
+ 	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 = IWL3945_BROADCAST_ID;
++	tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id;
+ 	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+ 
+ 	frame_size = iwl3945_fill_beacon_frame(priv,
+@@ -2350,6 +2628,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
+ 
+ void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv)
+ {
++	priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
+ 	priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
+ }
+ 
+@@ -2364,9 +2643,25 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv)
+ 	cancel_delayed_work(&priv->thermal_periodic);
+ }
+ 
++static struct iwl_3945_cfg iwl3945_bg_cfg = {
++	.name = "3945BG",
++	.fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
++	.sku = IWL_SKU_G,
++};
++
++static struct iwl_3945_cfg iwl3945_abg_cfg = {
++	.name = "3945ABG",
++	.fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
++	.sku = IWL_SKU_A|IWL_SKU_G,
++};
++
+ struct pci_device_id iwl3945_hw_card_ids[] = {
+-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4222)},
+-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4227)},
++	{IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)},
++	{IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)},
++	{IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)},
++	{IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)},
++	{IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)},
++	{IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)},
+ 	{0}
+ };
+ 
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
+index 1da14f9..45c1c55 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 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
+@@ -40,9 +40,17 @@
+ extern struct pci_device_id iwl3945_hw_card_ids[];
+ 
+ #define DRV_NAME	"iwl3945"
+-#include "iwl-3945-hw.h"
++#include "iwl-csr.h"
+ #include "iwl-prph.h"
++#include "iwl-3945-hw.h"
+ #include "iwl-3945-debug.h"
++#include "iwl-3945-led.h"
++
++/* Change firmware file name, using "-" and incrementing number,
++ *   *only* when uCode interface or architecture changes so that it
++ *   is not compatible with earlier drivers.
++ * This number will also appear in << 8 position of 1st dword of uCode file */
++#define IWL3945_UCODE_API "-1"
+ 
+ /* Default noise level to report when noise measurement is not available.
+  *   This may be because we're:
+@@ -109,6 +117,9 @@ struct iwl3945_queue {
+ 				* space less than this */
+ } __attribute__ ((packed));
+ 
++int iwl3945_queue_space(const struct iwl3945_queue *q);
++int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i);
++
+ #define MAX_NUM_OF_TBS          (20)
+ 
+ /* One for each TFD */
+@@ -195,7 +206,7 @@ struct iwl3945_channel_info {
+ 
+ 	u8 group_index;	  /* 0-4, maps channel to group1/2/3/4/5 */
+ 	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */
+-	u8 phymode;	  /* MODE_IEEE80211{A,B,G} */
++	enum ieee80211_band band;
+ 
+ 	/* Radio/DSP gain settings for each "normal" data Tx rate.
+ 	 * These include, in addition to RF and DSP gain, a few fields for
+@@ -269,8 +280,8 @@ struct iwl3945_frame {
+ 
+ #define SEQ_TO_QUEUE(x)  ((x >> 8) & 0xbf)
+ #define QUEUE_TO_SEQ(x)  ((x & 0xbf) << 8)
+-#define SEQ_TO_INDEX(x) (x & 0xff)
+-#define INDEX_TO_SEQ(x) (x & 0xff)
++#define SEQ_TO_INDEX(x) ((u8)(x & 0xff))
++#define INDEX_TO_SEQ(x) ((u8)(x & 0xff))
+ #define SEQ_HUGE_FRAME  (0x4000)
+ #define SEQ_RX_FRAME    __constant_cpu_to_le16(0x8000)
+ #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+@@ -390,23 +401,24 @@ struct iwl3945_rx_queue {
+ #define MIN_B_CHANNELS  1
+ 
+ #define STATUS_HCMD_ACTIVE	0	/* host command in progress */
+-#define STATUS_INT_ENABLED	1
+-#define STATUS_RF_KILL_HW	2
+-#define STATUS_RF_KILL_SW	3
+-#define STATUS_INIT		4
+-#define STATUS_ALIVE		5
+-#define STATUS_READY		6
+-#define STATUS_TEMPERATURE	7
+-#define STATUS_GEO_CONFIGURED	8
+-#define STATUS_EXIT_PENDING	9
+-#define STATUS_IN_SUSPEND	10
+-#define STATUS_STATISTICS	11
+-#define STATUS_SCANNING		12
+-#define STATUS_SCAN_ABORTING	13
+-#define STATUS_SCAN_HW		14
+-#define STATUS_POWER_PMI	15
+-#define STATUS_FW_ERROR		16
+-#define STATUS_CONF_PENDING	17
++#define STATUS_HCMD_SYNC_ACTIVE	1	/* sync host command in progress */
++#define STATUS_INT_ENABLED	2
++#define STATUS_RF_KILL_HW	3
++#define STATUS_RF_KILL_SW	4
++#define STATUS_INIT		5
++#define STATUS_ALIVE		6
++#define STATUS_READY		7
++#define STATUS_TEMPERATURE	8
++#define STATUS_GEO_CONFIGURED	9
++#define STATUS_EXIT_PENDING	10
++#define STATUS_IN_SUSPEND	11
++#define STATUS_STATISTICS	12
++#define STATUS_SCANNING		13
++#define STATUS_SCAN_ABORTING	14
++#define STATUS_SCAN_HW		15
++#define STATUS_POWER_PMI	16
++#define STATUS_FW_ERROR		17
++#define STATUS_CONF_PENDING	18
+ 
+ #define MAX_TID_COUNT        9
+ 
+@@ -431,8 +443,6 @@ union iwl3945_ht_rate_supp {
+ 	};
+ };
+ 
+-#ifdef CONFIG_IWL3945_QOS
+-
+ union iwl3945_qos_capabity {
+ 	struct {
+ 		u8 edca_count:4;	/* bit 0-3 */
+@@ -460,7 +470,6 @@ struct iwl3945_qos_info {
+ 	union iwl3945_qos_capabity qos_cap;
+ 	struct iwl3945_qosparam_cmd def_qos_parm;
+ };
+-#endif /*CONFIG_IWL3945_QOS */
+ 
+ #define STA_PS_STATUS_WAKE             0
+ #define STA_PS_STATUS_SLEEP            1
+@@ -511,8 +520,8 @@ struct iwl3945_ibss_seq {
+ /**
+  * struct iwl3945_driver_hw_info
+  * @max_txq_num: Max # Tx queues supported
+- * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
+  * @tx_cmd_len: Size of Tx command (but not including frame itself)
++ * @tx_ant_num: Number of TX antennas
+  * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
+  * @rx_buf_size:
+  * @max_pkt_size:
+@@ -524,8 +533,8 @@ struct iwl3945_ibss_seq {
+  */
+ struct iwl3945_driver_hw_info {
+ 	u16 max_txq_num;
+-	u16 ac_queue_count;
+ 	u16 tx_cmd_len;
++	u16 tx_ant_num;
+ 	u16 max_rxq_size;
+ 	u32 rx_buf_size;
+ 	u32 max_pkt_size;
+@@ -561,16 +570,6 @@ extern int iwl3945_is_network_packet(struct iwl3945_priv *priv,
+ 				 struct ieee80211_hdr *header);
+ extern int iwl3945_power_init_handle(struct iwl3945_priv *priv);
+ extern int iwl3945_eeprom_init(struct iwl3945_priv *priv);
+-#ifdef CONFIG_IWL3945_DEBUG
+-extern void iwl3945_report_frame(struct iwl3945_priv *priv,
+-			     struct iwl3945_rx_packet *pkt,
+-			     struct ieee80211_hdr *header, int group100);
+-#else
+-static inline void iwl3945_report_frame(struct iwl3945_priv *priv,
+-				    struct iwl3945_rx_packet *pkt,
+-				    struct ieee80211_hdr *header,
+-				    int group100) {}
+-#endif
+ extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv,
+ 					   struct iwl3945_rx_mem_buffer *rxb,
+ 					   void *data, short len,
+@@ -688,25 +687,28 @@ enum {
+ 
+ #endif
+ 
++#define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES
++
+ struct iwl3945_priv {
+ 
+ 	/* ieee device used by generic ieee processing code */
+ 	struct ieee80211_hw *hw;
+ 	struct ieee80211_channel *ieee_channels;
+ 	struct ieee80211_rate *ieee_rates;
++	struct iwl_3945_cfg *cfg; /* device configuration */
+ 
+ 	/* temporary frame storage list */
+ 	struct list_head free_frames;
+ 	int frames_count;
+ 
+-	u8 phymode;
++	enum ieee80211_band band;
+ 	int alloc_rxb_skb;
+ 	bool add_radiotap;
+ 
+ 	void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv,
+ 				       struct iwl3945_rx_mem_buffer *rxb);
+ 
+-	const struct ieee80211_hw_mode *modes;
++	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+ 
+ #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+ 	/* spectrum measurement report caching */
+@@ -779,13 +781,15 @@ struct iwl3945_priv {
+ 	struct iwl3945_init_alive_resp card_alive_init;
+ 	struct iwl3945_alive_resp card_alive;
+ 
+-#ifdef LED
+-	/* LED related variables */
+-	struct iwl3945_activity_blink activity;
+-	unsigned long led_packets;
+-	int led_state;
++#ifdef CONFIG_IWL3945_LEDS
++	struct iwl3945_led led[IWL_LED_TRG_MAX];
++	unsigned long last_blink_time;
++	u8 last_blink_rate;
++	u8 allow_blinking;
++	unsigned int rxtxpackets;
+ #endif
+ 
++
+ 	u16 active_rate;
+ 	u16 active_rate_basic;
+ 
+@@ -803,7 +807,6 @@ struct iwl3945_priv {
+ 	struct iwl3945_tx_queue txq[IWL_MAX_NUM_QUEUES];
+ 
+ 	unsigned long status;
+-	u32 config;
+ 
+ 	int last_rx_rssi;	/* From Rx packet statisitics */
+ 	int last_rx_noise;	/* From beacon statistics */
+@@ -830,10 +833,9 @@ struct iwl3945_priv {
+ 	struct iwl3945_station_entry stations[IWL_STATION_COUNT];
+ 
+ 	/* Indication if ieee80211_ops->open has been called */
+-	int is_open;
++	u8 is_open;
+ 
+ 	u8 mac80211_registered;
+-	int is_abg;
+ 
+ 	u32 notif_missed_beacons;
+ 
+@@ -852,7 +854,7 @@ struct iwl3945_priv {
+ 	/* eeprom */
+ 	struct iwl3945_eeprom eeprom;
+ 
+-	int iw_mode;
++	enum ieee80211_if_types iw_mode;
+ 
+ 	struct sk_buff *ibss_beacon;
+ 
+@@ -869,9 +871,7 @@ struct iwl3945_priv {
+ 	u16 assoc_capability;
+ 	u8 ps_mode;
+ 
+-#ifdef CONFIG_IWL3945_QOS
+ 	struct iwl3945_qos_info qos_data;
+-#endif /*CONFIG_IWL3945_QOS */
+ 
+ 	struct workqueue_struct *workqueue;
+ 
+@@ -937,13 +937,12 @@ static inline int is_channel_radar(const struct iwl3945_channel_info *ch_info)
+ 
+ static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info)
+ {
+-	return ch_info->phymode == MODE_IEEE80211A;
++	return ch_info->band == IEEE80211_BAND_5GHZ;
+ }
+ 
+ static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info)
+ {
+-	return ((ch_info->phymode == MODE_IEEE80211B) ||
+-		(ch_info->phymode == MODE_IEEE80211G));
++	return ch_info->band == IEEE80211_BAND_2GHZ;
+ }
+ 
+ static inline int is_channel_passive(const struct iwl3945_channel_info *ch)
+@@ -956,18 +955,8 @@ static inline int is_channel_ibss(const struct iwl3945_channel_info *ch)
+ 	return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
+ }
+ 
+-static inline int iwl3945_rate_index_from_plcp(int plcp)
+-{
+-	int i;
+-
+-	for (i = 0; i < IWL_RATE_COUNT; i++)
+-		if (iwl3945_rates[i].plcp == plcp)
+-			return i;
+-	return -1;
+-}
+-
+ extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
+-	const struct iwl3945_priv *priv, int phymode, u16 channel);
++	const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel);
+ 
+ /* Requires full declaration of iwl3945_priv before including */
+ #include "iwl-3945-io.h"
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
+index f3470c8..3bcd107 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
++++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
+@@ -5,7 +5,7 @@
+  *
+  * GPL LICENSE SUMMARY
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 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
+@@ -30,7 +30,7 @@
+  *
+  * BSD LICENSE
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -84,6 +84,9 @@ enum {
+ 	REPLY_REMOVE_STA = 0x19,	/* not used */
+ 	REPLY_REMOVE_ALL_STA = 0x1a,	/* not used */
+ 
++	/* Security */
++	REPLY_WEPKEY = 0x20,
++
+ 	/* RX, TX, LEDs */
+ 	REPLY_TX = 0x1c,
+ 	REPLY_RATE_SCALE = 0x47,	/* 3945 only */
+@@ -139,7 +142,7 @@ enum {
+ 	REPLY_PHY_CALIBRATION_CMD = 0xb0,
+ 	REPLY_RX_PHY_CMD = 0xc0,
+ 	REPLY_RX_MPDU_CMD = 0xc1,
+-	REPLY_4965_RX = 0xc3,
++	REPLY_RX = 0xc3,
+ 	REPLY_COMPRESSED_BA = 0xc5,
+ 	REPLY_MAX = 0xff
+ };
+@@ -151,16 +154,16 @@ enum {
+  *
+  *****************************************************************************/
+ 
+-/* iwl4965_cmd_header flags value */
++/* iwl_cmd_header flags value */
+ #define IWL_CMD_FAILED_MSK 0x40
+ 
+ /**
+- * struct iwl4965_cmd_header
++ * struct iwl_cmd_header
+  *
+  * This header format appears in the beginning of each command sent from the
+  * driver, and each response/notification received from uCode.
+  */
+-struct iwl4965_cmd_header {
++struct iwl_cmd_header {
+ 	u8 cmd;		/* Command ID:  REPLY_RXON, etc. */
+ 	u8 flags;	/* IWL_CMD_* */
+ 	/*
+@@ -194,7 +197,7 @@ struct iwl4965_cmd_header {
+  * 4965 rate_n_flags bit fields
+  *
+  * rate_n_flags format is used in following 4965 commands:
+- *  REPLY_4965_RX (response only)
++ *  REPLY_RX (response only)
+  *  REPLY_TX (both command and response)
+  *  REPLY_TX_LINK_QUALITY_CMD
+  *
+@@ -266,11 +269,10 @@ struct iwl4965_cmd_header {
+  *          10 B active, A inactive
+  *          11 Both active
+  */
+-#define RATE_MCS_ANT_A_POS	14
+-#define RATE_MCS_ANT_B_POS	15
+-#define RATE_MCS_ANT_A_MSK	0x4000
+-#define RATE_MCS_ANT_B_MSK	0x8000
+-#define RATE_MCS_ANT_AB_MSK	0xc000
++#define RATE_MCS_ANT_POS       14
++#define RATE_MCS_ANT_A_MSK     0x04000
++#define RATE_MCS_ANT_B_MSK     0x08000
++#define RATE_MCS_ANT_AB_MSK    0x0C000
+ 
+ 
+ /**
+@@ -727,14 +729,21 @@ struct iwl4965_qosparam_cmd {
+ #define STA_CONTROL_MODIFY_MSK		0x01
+ 
+ /* key flags __le16*/
+-#define STA_KEY_FLG_ENCRYPT_MSK	__constant_cpu_to_le16(0x7)
+-#define STA_KEY_FLG_NO_ENC	__constant_cpu_to_le16(0x0)
+-#define STA_KEY_FLG_WEP		__constant_cpu_to_le16(0x1)
+-#define STA_KEY_FLG_CCMP	__constant_cpu_to_le16(0x2)
+-#define STA_KEY_FLG_TKIP	__constant_cpu_to_le16(0x3)
++#define STA_KEY_FLG_ENCRYPT_MSK	__constant_cpu_to_le16(0x0007)
++#define STA_KEY_FLG_NO_ENC	__constant_cpu_to_le16(0x0000)
++#define STA_KEY_FLG_WEP		__constant_cpu_to_le16(0x0001)
++#define STA_KEY_FLG_CCMP	__constant_cpu_to_le16(0x0002)
++#define STA_KEY_FLG_TKIP	__constant_cpu_to_le16(0x0003)
+ 
+ #define STA_KEY_FLG_KEYID_POS	8
+ #define STA_KEY_FLG_INVALID 	__constant_cpu_to_le16(0x0800)
++/* wep key is either from global key (0) or from station info array (1) */
++#define STA_KEY_FLG_MAP_KEY_MSK	__constant_cpu_to_le16(0x0008)
++
++/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
++#define STA_KEY_FLG_KEY_SIZE_MSK     __constant_cpu_to_le16(0x1000)
++#define STA_KEY_MULTICAST_MSK        __constant_cpu_to_le16(0x4000)
++#define STA_KEY_MAX_NUM		8
+ 
+ /* Flags indicate whether to modify vs. don't change various station params */
+ #define	STA_MODIFY_KEY_MASK		0x01
+@@ -752,7 +761,8 @@ struct iwl4965_keyinfo {
+ 	u8 tkip_rx_tsc_byte2;	/* TSC[2] for key mix ph1 detection */
+ 	u8 reserved1;
+ 	__le16 tkip_rx_ttak[5];	/* 10-byte unicast TKIP TTAK */
+-	__le16 reserved2;
++	u8 key_offset;
++	u8 reserved2;
+ 	u8 key[16];		/* 16-byte unicast decryption key */
+ } __attribute__ ((packed));
+ 
+@@ -842,6 +852,30 @@ struct iwl4965_add_sta_resp {
+ 	u8 status;	/* ADD_STA_* */
+ } __attribute__ ((packed));
+ 
++/*
++ * REPLY_WEP_KEY = 0x20
++ */
++struct iwl_wep_key {
++	u8 key_index;
++	u8 key_offset;
++	u8 reserved1[2];
++	u8 key_size;
++	u8 reserved2[3];
++	u8 key[16];
++} __attribute__ ((packed));
++
++struct iwl_wep_cmd {
++	u8 num_keys;
++	u8 global_key_type;
++	u8 flags;
++	u8 reserved;
++	struct iwl_wep_key key[0];
++} __attribute__ ((packed));
++
++#define WEP_KEY_WEP_TYPE 1
++#define WEP_KEYS_MAX 4
++#define WEP_INVALID_OFFSET 0xff
++#define WEP_KEY_LEN_128 13
+ 
+ /******************************************************************************
+  * (4)
+@@ -868,26 +902,35 @@ struct iwl4965_rx_frame_hdr {
+ 	u8 payload[0];
+ } __attribute__ ((packed));
+ 
+-#define	RX_RES_STATUS_NO_CRC32_ERROR	__constant_cpu_to_le32(1 << 0)
+-#define	RX_RES_STATUS_NO_RXE_OVERFLOW	__constant_cpu_to_le32(1 << 1)
++#define RX_RES_STATUS_NO_CRC32_ERROR	__constant_cpu_to_le32(1 << 0)
++#define RX_RES_STATUS_NO_RXE_OVERFLOW	__constant_cpu_to_le32(1 << 1)
++
++#define RX_RES_PHY_FLAGS_BAND_24_MSK	__constant_cpu_to_le16(1 << 0)
++#define RX_RES_PHY_FLAGS_MOD_CCK_MSK		__constant_cpu_to_le16(1 << 1)
++#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	__constant_cpu_to_le16(1 << 2)
++#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK	__constant_cpu_to_le16(1 << 3)
++#define RX_RES_PHY_FLAGS_ANTENNA_MSK		__constant_cpu_to_le16(0xf0)
++
++#define RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
++#define RX_RES_STATUS_SEC_TYPE_NONE	(0x0 << 8)
++#define RX_RES_STATUS_SEC_TYPE_WEP	(0x1 << 8)
++#define RX_RES_STATUS_SEC_TYPE_CCMP	(0x2 << 8)
++#define RX_RES_STATUS_SEC_TYPE_TKIP	(0x3 << 8)
++#define	RX_RES_STATUS_SEC_TYPE_ERR	(0x7 << 8)
+ 
+-#define	RX_RES_PHY_FLAGS_BAND_24_MSK	__constant_cpu_to_le16(1 << 0)
+-#define	RX_RES_PHY_FLAGS_MOD_CCK_MSK		__constant_cpu_to_le16(1 << 1)
+-#define	RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	__constant_cpu_to_le16(1 << 2)
+-#define	RX_RES_PHY_FLAGS_NARROW_BAND_MSK	__constant_cpu_to_le16(1 << 3)
+-#define	RX_RES_PHY_FLAGS_ANTENNA_MSK		__constant_cpu_to_le16(0xf0)
++#define RX_RES_STATUS_STATION_FOUND	(1<<6)
++#define RX_RES_STATUS_NO_STATION_INFO_MISMATCH	(1<<7)
+ 
+-#define	RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
+-#define	RX_RES_STATUS_SEC_TYPE_NONE	(0x0 << 8)
+-#define	RX_RES_STATUS_SEC_TYPE_WEP	(0x1 << 8)
+-#define	RX_RES_STATUS_SEC_TYPE_CCMP	(0x2 << 8)
+-#define	RX_RES_STATUS_SEC_TYPE_TKIP	(0x3 << 8)
++#define RX_RES_STATUS_DECRYPT_TYPE_MSK	(0x3 << 11)
++#define RX_RES_STATUS_NOT_DECRYPT	(0x0 << 11)
++#define RX_RES_STATUS_DECRYPT_OK	(0x3 << 11)
++#define RX_RES_STATUS_BAD_ICV_MIC	(0x1 << 11)
++#define RX_RES_STATUS_BAD_KEY_TTAK	(0x2 << 11)
+ 
+-#define	RX_RES_STATUS_DECRYPT_TYPE_MSK	(0x3 << 11)
+-#define	RX_RES_STATUS_NOT_DECRYPT	(0x0 << 11)
+-#define	RX_RES_STATUS_DECRYPT_OK	(0x3 << 11)
+-#define	RX_RES_STATUS_BAD_ICV_MIC	(0x1 << 11)
+-#define	RX_RES_STATUS_BAD_KEY_TTAK	(0x2 << 11)
++#define RX_MPDU_RES_STATUS_ICV_OK	(0x20)
++#define RX_MPDU_RES_STATUS_MIC_OK	(0x40)
++#define RX_MPDU_RES_STATUS_TTAK_OK	(1 << 7)
++#define RX_MPDU_RES_STATUS_DEC_DONE_MSK	(0x800)
+ 
+ struct iwl4965_rx_frame_end {
+ 	__le32 status;
+@@ -922,7 +965,7 @@ struct iwl4965_rx_non_cfg_phy {
+ } __attribute__ ((packed));
+ 
+ /*
+- * REPLY_4965_RX = 0xc3 (response only, not a command)
++ * REPLY_RX = 0xc3 (response only, not a command)
+  * Used only for legacy (non 11n) frames.
+  */
+ #define RX_RES_PHY_CNT 14
+@@ -1038,6 +1081,10 @@ struct iwl4965_rx_mpdu_res_start {
+  * MAC header) to DWORD boundary. */
+ #define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
+ 
++/* accelerate aggregation support
++ * 0 - no CCMP encryption; 1 - CCMP encryption */
++#define TX_CMD_FLG_AGG_CCMP_MSK __constant_cpu_to_le32(1 << 22)
++
+ /* HCCA-AP - disable duration overwriting. */
+ #define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25)
+ 
+@@ -1300,6 +1347,25 @@ struct iwl4965_tx_resp {
+ 	__le32 status;	/* TX status (for aggregation status of 1st frame) */
+ } __attribute__ ((packed));
+ 
++struct agg_tx_status {
++	__le16 status;
++	__le16 sequence;
++} __attribute__ ((packed));
++
++struct iwl4965_tx_resp_agg {
++	u8 frame_count;         /* 1 no aggregation, >1 aggregation */
++	u8 reserved1;
++	u8 failure_rts;
++	u8 failure_frame;
++	__le32 rate_n_flags;
++	__le16 wireless_media_time;
++	__le16 reserved3;
++	__le32 pa_power1;
++	__le32 pa_power2;
++	struct agg_tx_status status;    /* TX status (for aggregation status */
++					/* of 1st frame) */
++} __attribute__ ((packed));
++
+ /*
+  * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
+  *
+@@ -1313,9 +1379,8 @@ struct iwl4965_compressed_ba_resp {
+ 	/* Index of recipient (BA-sending) station in uCode's station table */
+ 	u8 sta_id;
+ 	u8 tid;
+-	__le16 ba_seq_ctl;
+-	__le32 ba_bitmap0;
+-	__le32 ba_bitmap1;
++	__le16 seq_ctl;
++	__le64 bitmap;
+ 	__le16 scd_flow;
+ 	__le16 scd_ssn;
+ } __attribute__ ((packed));
+@@ -1348,11 +1413,11 @@ struct iwl4965_txpowertable_cmd {
+ 
+ 
+ /**
+- * struct iwl4965_link_qual_general_params
++ * struct iwl_link_qual_general_params
+  *
+  * Used in REPLY_TX_LINK_QUALITY_CMD
+  */
+-struct iwl4965_link_qual_general_params {
++struct iwl_link_qual_general_params {
+ 	u8 flags;
+ 
+ 	/* No entries at or above this (driver chosen) index contain MIMO */
+@@ -1379,11 +1444,11 @@ struct iwl4965_link_qual_general_params {
+ } __attribute__ ((packed));
+ 
+ /**
+- * struct iwl4965_link_qual_agg_params
++ * struct iwl_link_qual_agg_params
+  *
+  * Used in REPLY_TX_LINK_QUALITY_CMD
+  */
+-struct iwl4965_link_qual_agg_params {
++struct iwl_link_qual_agg_params {
+ 
+ 	/* Maximum number of uSec in aggregation.
+ 	 * Driver should set this to 4000 (4 milliseconds). */
+@@ -1593,14 +1658,14 @@ struct iwl4965_link_qual_agg_params {
+  * legacy), and then repeat the search process.
+  *
+  */
+-struct iwl4965_link_quality_cmd {
++struct iwl_link_quality_cmd {
+ 
+ 	/* Index of destination/recipient station in uCode's station table */
+ 	u8 sta_id;
+ 	u8 reserved1;
+ 	__le16 control;		/* not used */
+-	struct iwl4965_link_qual_general_params general_params;
+-	struct iwl4965_link_qual_agg_params agg_params;
++	struct iwl_link_qual_general_params general_params;
++	struct iwl_link_qual_agg_params agg_params;
+ 
+ 	/*
+ 	 * Rate info; when using rate-scaling, Tx command's initial_rate_index
+@@ -2625,7 +2690,7 @@ struct iwl4965_led_cmd {
+ 
+ struct iwl4965_rx_packet {
+ 	__le32 len;
+-	struct iwl4965_cmd_header hdr;
++	struct iwl_cmd_header hdr;
+ 	union {
+ 		struct iwl4965_alive_resp alive_frame;
+ 		struct iwl4965_rx_frame rx_frame;
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h
+deleted file mode 100644
+index 36696bb..0000000
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h
++++ /dev/null
+@@ -1,152 +0,0 @@
+-/******************************************************************************
+- *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
+- *
+- * Portions of this file are derived from the ipw3945 project.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called LICENSE.
+- *
+- * Contact Information:
+- * James P. Ketrenos <ipw2100-admin at linux.intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+- *****************************************************************************/
+-
+-#ifndef __iwl4965_debug_h__
+-#define __iwl4965_debug_h__
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-extern u32 iwl4965_debug_level;
+-#define IWL_DEBUG(level, fmt, args...) \
+-do { if (iwl4965_debug_level & (level)) \
+-  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+-	 in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+-
+-#define IWL_DEBUG_LIMIT(level, fmt, args...) \
+-do { if ((iwl4965_debug_level & (level)) && net_ratelimit()) \
+-  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+-	 in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+-#else
+-static inline void IWL_DEBUG(int level, const char *fmt, ...)
+-{
+-}
+-static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
+-{
+-}
+-#endif				/* CONFIG_IWL4965_DEBUG */
+-
+-/*
+- * To use the debug system;
+- *
+- * If you are defining a new debug classification, simply add it to the #define
+- * list here in the form of:
+- *
+- * #define IWL_DL_xxxx VALUE
+- *
+- * shifting value to the left one bit from the previous entry.  xxxx should be
+- * the name of the classification (for example, WEP)
+- *
+- * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
+- * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
+- * to send output to that classification.
+- *
+- * To add your debug level to the list of levels seen when you perform
+- *
+- * % cat /proc/net/iwl/debug_level
+- *
+- * you simply need to add your entry to the iwl4965_debug_levels array.
+- *
+- * If you do not see debug_level in /proc/net/iwl then you do not have
+- * CONFIG_IWL4965_DEBUG defined in your kernel configuration
+- *
+- */
+-
+-#define IWL_DL_INFO          (1 << 0)
+-#define IWL_DL_MAC80211      (1 << 1)
+-#define IWL_DL_HOST_COMMAND  (1 << 2)
+-#define IWL_DL_STATE         (1 << 3)
+-
+-#define IWL_DL_RADIO         (1 << 7)
+-#define IWL_DL_POWER         (1 << 8)
+-#define IWL_DL_TEMP          (1 << 9)
+-
+-#define IWL_DL_NOTIF         (1 << 10)
+-#define IWL_DL_SCAN          (1 << 11)
+-#define IWL_DL_ASSOC         (1 << 12)
+-#define IWL_DL_DROP          (1 << 13)
+-
+-#define IWL_DL_TXPOWER       (1 << 14)
+-
+-#define IWL_DL_AP            (1 << 15)
+-
+-#define IWL_DL_FW            (1 << 16)
+-#define IWL_DL_RF_KILL       (1 << 17)
+-#define IWL_DL_FW_ERRORS     (1 << 18)
+-
+-#define IWL_DL_LED           (1 << 19)
+-
+-#define IWL_DL_RATE          (1 << 20)
+-
+-#define IWL_DL_CALIB         (1 << 21)
+-#define IWL_DL_WEP           (1 << 22)
+-#define IWL_DL_TX            (1 << 23)
+-#define IWL_DL_RX            (1 << 24)
+-#define IWL_DL_ISR           (1 << 25)
+-#define IWL_DL_HT            (1 << 26)
+-#define IWL_DL_IO            (1 << 27)
+-#define IWL_DL_11H           (1 << 28)
+-
+-#define IWL_DL_STATS         (1 << 29)
+-#define IWL_DL_TX_REPLY      (1 << 30)
+-#define IWL_DL_QOS           (1 << 31)
+-
+-#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
+-#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
+-#define IWL_DEBUG_INFO(f, a...)    IWL_DEBUG(IWL_DL_INFO, f, ## a)
+-
+-#define IWL_DEBUG_MAC80211(f, a...)     IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
+-#define IWL_DEBUG_TEMP(f, a...)   IWL_DEBUG(IWL_DL_TEMP, f, ## a)
+-#define IWL_DEBUG_SCAN(f, a...)   IWL_DEBUG(IWL_DL_SCAN, f, ## a)
+-#define IWL_DEBUG_RX(f, a...)     IWL_DEBUG(IWL_DL_RX, f, ## a)
+-#define IWL_DEBUG_TX(f, a...)     IWL_DEBUG(IWL_DL_TX, f, ## a)
+-#define IWL_DEBUG_ISR(f, a...)    IWL_DEBUG(IWL_DL_ISR, f, ## a)
+-#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
+-#define IWL_DEBUG_WEP(f, a...)    IWL_DEBUG(IWL_DL_WEP, f, ## a)
+-#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
+-#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
+-#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
+-#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
+-#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
+-#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
+-#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
+-#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
+-#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
+-#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
+-#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
+-#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
+-#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+-#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
+-	IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+-#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
+-#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
+-#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
+-#define IWL_DEBUG_QOS(f, a...)   IWL_DEBUG(IWL_DL_QOS, f, ## a)
+-#define IWL_DEBUG_RADIO(f, a...)  IWL_DEBUG(IWL_DL_RADIO, f, ## a)
+-#define IWL_DEBUG_POWER(f, a...)  IWL_DEBUG(IWL_DL_POWER, f, ## a)
+-#define IWL_DEBUG_11H(f, a...)  IWL_DEBUG(IWL_DL_11H, f, ## a)
+-
+-#endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+index ffe1e9d..1a66b50 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
++++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+@@ -5,7 +5,7 @@
+  *
+  * GPL LICENSE SUMMARY
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 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
+@@ -30,7 +30,7 @@
+  *
+  * BSD LICENSE
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -92,316 +92,6 @@
+ /* RSSI to dBm */
+ #define IWL_RSSI_OFFSET	44
+ 
+-/*
+- * EEPROM related constants, enums, and structures.
+- */
+-
+-/*
+- * EEPROM access time values:
+- *
+- * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
+- *   then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
+- *   CSR_EEPROM_REG_BIT_CMD (0x2).
+- * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
+- * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
+- * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
+- */
+-#define IWL_EEPROM_ACCESS_TIMEOUT	5000 /* uSec */
+-#define IWL_EEPROM_ACCESS_DELAY		10   /* uSec */
+-
+-/*
+- * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
+- *
+- * IBSS and/or AP operation is allowed *only* on those channels with
+- * (VALID && IBSS && ACTIVE && !RADAR).  This restriction is in place because
+- * RADAR detection is not supported by the 4965 driver, but is a
+- * requirement for establishing a new network for legal operation on channels
+- * requiring RADAR detection or restricting ACTIVE scanning.
+- *
+- * NOTE:  "WIDE" flag does not indicate anything about "FAT" 40 MHz channels.
+- *        It only indicates that 20 MHz channel use is supported; FAT channel
+- *        usage is indicated by a separate set of regulatory flags for each
+- *        FAT channel pair.
+- *
+- * NOTE:  Using a channel inappropriately will result in a uCode error!
+- */
+-enum {
+-	EEPROM_CHANNEL_VALID = (1 << 0),	/* usable for this SKU/geo */
+-	EEPROM_CHANNEL_IBSS = (1 << 1),		/* usable as an IBSS channel */
+-	/* Bit 2 Reserved */
+-	EEPROM_CHANNEL_ACTIVE = (1 << 3),	/* active scanning allowed */
+-	EEPROM_CHANNEL_RADAR = (1 << 4),	/* radar detection required */
+-	EEPROM_CHANNEL_WIDE = (1 << 5),		/* 20 MHz channel okay */
+-	EEPROM_CHANNEL_NARROW = (1 << 6),	/* 10 MHz channel (not used) */
+-	EEPROM_CHANNEL_DFS = (1 << 7),	/* dynamic freq selection candidate */
+-};
+-
+-/* SKU Capabilities */
+-#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
+-#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
+-
+-/* *regulatory* channel data format in eeprom, one for each channel.
+- * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */
+-struct iwl4965_eeprom_channel {
+-	u8 flags;		/* EEPROM_CHANNEL_* flags copied from EEPROM */
+-	s8 max_power_avg;	/* max power (dBm) on this chnl, limit 31 */
+-} __attribute__ ((packed));
+-
+-/* 4965 has two radio transmitters (and 3 radio receivers) */
+-#define EEPROM_TX_POWER_TX_CHAINS      (2)
+-
+-/* 4965 has room for up to 8 sets of txpower calibration data */
+-#define EEPROM_TX_POWER_BANDS          (8)
+-
+-/* 4965 factory calibration measures txpower gain settings for
+- * each of 3 target output levels */
+-#define EEPROM_TX_POWER_MEASUREMENTS   (3)
+-
+-/* 4965 driver does not work with txpower calibration version < 5.
+- * Look for this in calib_version member of struct iwl4965_eeprom. */
+-#define EEPROM_TX_POWER_VERSION_NEW    (5)
+-
+-
+-/*
+- * 4965 factory calibration data for one txpower level, on one channel,
+- * measured on one of the 2 tx chains (radio transmitter and associated
+- * antenna).  EEPROM contains:
+- *
+- * 1)  Temperature (degrees Celsius) of device when measurement was made.
+- *
+- * 2)  Gain table index used to achieve the target measurement power.
+- *     This refers to the "well-known" gain tables (see iwl-4965-hw.h).
+- *
+- * 3)  Actual measured output power, in half-dBm ("34" = 17 dBm).
+- *
+- * 4)  RF power amplifier detector level measurement (not used).
+- */
+-struct iwl4965_eeprom_calib_measure {
+-	u8 temperature;		/* Device temperature (Celsius) */
+-	u8 gain_idx;		/* Index into gain table */
+-	u8 actual_pow;		/* Measured RF output power, half-dBm */
+-	s8 pa_det;		/* Power amp detector level (not used) */
+-} __attribute__ ((packed));
+-
+-
+-/*
+- * 4965 measurement set for one channel.  EEPROM contains:
+- *
+- * 1)  Channel number measured
+- *
+- * 2)  Measurements for each of 3 power levels for each of 2 radio transmitters
+- *     (a.k.a. "tx chains") (6 measurements altogether)
+- */
+-struct iwl4965_eeprom_calib_ch_info {
+-	u8 ch_num;
+-	struct iwl4965_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS]
+-		[EEPROM_TX_POWER_MEASUREMENTS];
+-} __attribute__ ((packed));
+-
+-/*
+- * 4965 txpower subband info.
+- *
+- * For each frequency subband, EEPROM contains the following:
+- *
+- * 1)  First and last channels within range of the subband.  "0" values
+- *     indicate that this sample set is not being used.
+- *
+- * 2)  Sample measurement sets for 2 channels close to the range endpoints.
+- */
+-struct iwl4965_eeprom_calib_subband_info {
+-	u8 ch_from;	/* channel number of lowest channel in subband */
+-	u8 ch_to;	/* channel number of highest channel in subband */
+-	struct iwl4965_eeprom_calib_ch_info ch1;
+-	struct iwl4965_eeprom_calib_ch_info ch2;
+-} __attribute__ ((packed));
+-
+-
+-/*
+- * 4965 txpower calibration info.  EEPROM contains:
+- *
+- * 1)  Factory-measured saturation power levels (maximum levels at which
+- *     tx power amplifier can output a signal without too much distortion).
+- *     There is one level for 2.4 GHz band and one for 5 GHz band.  These
+- *     values apply to all channels within each of the bands.
+- *
+- * 2)  Factory-measured power supply voltage level.  This is assumed to be
+- *     constant (i.e. same value applies to all channels/bands) while the
+- *     factory measurements are being made.
+- *
+- * 3)  Up to 8 sets of factory-measured txpower calibration values.
+- *     These are for different frequency ranges, since txpower gain
+- *     characteristics of the analog radio circuitry vary with frequency.
+- *
+- *     Not all sets need to be filled with data;
+- *     struct iwl4965_eeprom_calib_subband_info contains range of channels
+- *     (0 if unused) for each set of data.
+- */
+-struct iwl4965_eeprom_calib_info {
+-	u8 saturation_power24;	/* half-dBm (e.g. "34" = 17 dBm) */
+-	u8 saturation_power52;	/* half-dBm */
+-	s16 voltage;		/* signed */
+-	struct iwl4965_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS];
+-} __attribute__ ((packed));
+-
+-
+-/*
+- * 4965 EEPROM map
+- */
+-struct iwl4965_eeprom {
+-	u8 reserved0[16];
+-#define EEPROM_DEVICE_ID                    (2*0x08)	/* 2 bytes */
+-	u16 device_id;		/* abs.ofs: 16 */
+-	u8 reserved1[2];
+-#define EEPROM_PMC                          (2*0x0A)	/* 2 bytes */
+-	u16 pmc;		/* abs.ofs: 20 */
+-	u8 reserved2[20];
+-#define EEPROM_MAC_ADDRESS                  (2*0x15)	/* 6  bytes */
+-	u8 mac_address[6];	/* abs.ofs: 42 */
+-	u8 reserved3[58];
+-#define EEPROM_BOARD_REVISION               (2*0x35)	/* 2  bytes */
+-	u16 board_revision;	/* abs.ofs: 106 */
+-	u8 reserved4[11];
+-#define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1)	/* 9  bytes */
+-	u8 board_pba_number[9];	/* abs.ofs: 119 */
+-	u8 reserved5[8];
+-#define EEPROM_VERSION                      (2*0x44)	/* 2  bytes */
+-	u16 version;		/* abs.ofs: 136 */
+-#define EEPROM_SKU_CAP                      (2*0x45)	/* 1  bytes */
+-	u8 sku_cap;		/* abs.ofs: 138 */
+-#define EEPROM_LEDS_MODE                    (2*0x45+1)	/* 1  bytes */
+-	u8 leds_mode;		/* abs.ofs: 139 */
+-#define EEPROM_OEM_MODE                     (2*0x46)	/* 2  bytes */
+-	u16 oem_mode;
+-#define EEPROM_WOWLAN_MODE                  (2*0x47)	/* 2  bytes */
+-	u16 wowlan_mode;	/* abs.ofs: 142 */
+-#define EEPROM_LEDS_TIME_INTERVAL           (2*0x48)	/* 2  bytes */
+-	u16 leds_time_interval;	/* abs.ofs: 144 */
+-#define EEPROM_LEDS_OFF_TIME                (2*0x49)	/* 1  bytes */
+-	u8 leds_off_time;	/* abs.ofs: 146 */
+-#define EEPROM_LEDS_ON_TIME                 (2*0x49+1)	/* 1  bytes */
+-	u8 leds_on_time;	/* abs.ofs: 147 */
+-#define EEPROM_ALMGOR_M_VERSION             (2*0x4A)	/* 1  bytes */
+-	u8 almgor_m_version;	/* abs.ofs: 148 */
+-#define EEPROM_ANTENNA_SWITCH_TYPE          (2*0x4A+1)	/* 1  bytes */
+-	u8 antenna_switch_type;	/* abs.ofs: 149 */
+-	u8 reserved6[8];
+-#define EEPROM_4965_BOARD_REVISION          (2*0x4F)	/* 2 bytes */
+-	u16 board_revision_4965;	/* abs.ofs: 158 */
+-	u8 reserved7[13];
+-#define EEPROM_4965_BOARD_PBA               (2*0x56+1)	/* 9 bytes */
+-	u8 board_pba_number_4965[9];	/* abs.ofs: 173 */
+-	u8 reserved8[10];
+-#define EEPROM_REGULATORY_SKU_ID            (2*0x60)	/* 4  bytes */
+-	u8 sku_id[4];		/* abs.ofs: 192 */
+-
+-/*
+- * Per-channel regulatory data.
+- *
+- * Each channel that *might* be supported by 3945 or 4965 has a fixed location
+- * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+- * txpower (MSB).
+- *
+- * Entries immediately below are for 20 MHz channel width.  FAT (40 MHz)
+- * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
+- *
+- * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+- */
+-#define EEPROM_REGULATORY_BAND_1            (2*0x62)	/* 2  bytes */
+-	u16 band_1_count;	/* abs.ofs: 196 */
+-#define EEPROM_REGULATORY_BAND_1_CHANNELS   (2*0x63)	/* 28 bytes */
+-	struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
+-
+-/*
+- * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+- * 5.0 GHz channels 7, 8, 11, 12, 16
+- * (4915-5080MHz) (none of these is ever supported)
+- */
+-#define EEPROM_REGULATORY_BAND_2            (2*0x71)	/* 2  bytes */
+-	u16 band_2_count;	/* abs.ofs: 226 */
+-#define EEPROM_REGULATORY_BAND_2_CHANNELS   (2*0x72)	/* 26 bytes */
+-	struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
+-
+-/*
+- * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+- * (5170-5320MHz)
+- */
+-#define EEPROM_REGULATORY_BAND_3            (2*0x7F)	/* 2  bytes */
+-	u16 band_3_count;	/* abs.ofs: 254 */
+-#define EEPROM_REGULATORY_BAND_3_CHANNELS   (2*0x80)	/* 24 bytes */
+-	struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
+-
+-/*
+- * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+- * (5500-5700MHz)
+- */
+-#define EEPROM_REGULATORY_BAND_4            (2*0x8C)	/* 2  bytes */
+-	u16 band_4_count;	/* abs.ofs: 280 */
+-#define EEPROM_REGULATORY_BAND_4_CHANNELS   (2*0x8D)	/* 22 bytes */
+-	struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
+-
+-/*
+- * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+- * (5725-5825MHz)
+- */
+-#define EEPROM_REGULATORY_BAND_5            (2*0x98)	/* 2  bytes */
+-	u16 band_5_count;	/* abs.ofs: 304 */
+-#define EEPROM_REGULATORY_BAND_5_CHANNELS   (2*0x99)	/* 12 bytes */
+-	struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
+-
+-	u8 reserved10[2];
+-
+-
+-/*
+- * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
+- *
+- * The channel listed is the center of the lower 20 MHz half of the channel.
+- * The overall center frequency is actually 2 channels (10 MHz) above that,
+- * and the upper half of each FAT channel is centered 4 channels (20 MHz) away
+- * from the lower half; e.g. the upper half of FAT channel 1 is channel 5,
+- * and the overall FAT channel width centers on channel 3.
+- *
+- * NOTE:  The RXON command uses 20 MHz channel numbers to specify the
+- *        control channel to which to tune.  RXON also specifies whether the
+- *        control channel is the upper or lower half of a FAT channel.
+- *
+- * NOTE:  4965 does not support FAT channels on 2.4 GHz.
+- */
+-#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0)	/* 14 bytes */
+-	struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */
+-	u8 reserved11[2];
+-
+-/*
+- * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64),
+- * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
+- */
+-#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8)	/* 22 bytes */
+-	struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */
+-	u8 reserved12[6];
+-
+-/*
+- * 4965 driver requires txpower calibration format version 5 or greater.
+- * Driver does not work with txpower calibration version < 5.
+- * This value is simply a 16-bit number, no major/minor versions here.
+- */
+-#define EEPROM_CALIB_VERSION_OFFSET            (2*0xB6)	/* 2 bytes */
+-	u16 calib_version;	/* abs.ofs: 364 */
+-	u8 reserved13[2];
+-	u8 reserved14[96];	/* abs.ofs: 368 */
+-
+-/*
+- * 4965 Txpower calibration data.
+- */
+-#define EEPROM_IWL_CALIB_TXPOWER_OFFSET        (2*0xE8)	/* 48  bytes */
+-	struct iwl4965_eeprom_calib_info calib_info;	/* abs.ofs: 464 */
+-
+-	u8 reserved16[140];	/* fill out to full 1024 byte block */
+-
+-
+-} __attribute__ ((packed));
+-
+-#define IWL_EEPROM_IMAGE_SIZE 1024
+-
+-/* End of EEPROM */
+ 
+ #include "iwl-4965-commands.h"
+ 
+@@ -410,182 +100,6 @@ struct iwl4965_eeprom {
+ #define PCI_REG_WUM8       0x0E8
+ #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT         (0x80000000)
+ 
+-/*=== CSR (control and status registers) ===*/
+-#define CSR_BASE    (0x000)
+-
+-#define CSR_SW_VER              (CSR_BASE+0x000)
+-#define CSR_HW_IF_CONFIG_REG    (CSR_BASE+0x000) /* hardware interface config */
+-#define CSR_INT_COALESCING      (CSR_BASE+0x004) /* accum ints, 32-usec units */
+-#define CSR_INT                 (CSR_BASE+0x008) /* host interrupt status/ack */
+-#define CSR_INT_MASK            (CSR_BASE+0x00c) /* host interrupt enable */
+-#define CSR_FH_INT_STATUS       (CSR_BASE+0x010) /* busmaster int status/ack*/
+-#define CSR_GPIO_IN             (CSR_BASE+0x018) /* read external chip pins */
+-#define CSR_RESET               (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
+-#define CSR_GP_CNTRL            (CSR_BASE+0x024)
+-
+-/*
+- * Hardware revision info
+- * Bit fields:
+- * 31-8:  Reserved
+- *  7-4:  Type of device:  0x0 = 4965, 0xd = 3945
+- *  3-2:  Revision step:  0 = A, 1 = B, 2 = C, 3 = D
+- *  1-0:  "Dash" value, as in A-1, etc.
+- *
+- * NOTE:  Revision step affects calculation of CCK txpower for 4965.
+- */
+-#define CSR_HW_REV              (CSR_BASE+0x028)
+-
+-/* EEPROM reads */
+-#define CSR_EEPROM_REG          (CSR_BASE+0x02c)
+-#define CSR_EEPROM_GP           (CSR_BASE+0x030)
+-#define CSR_GP_UCODE		(CSR_BASE+0x044)
+-#define CSR_UCODE_DRV_GP1       (CSR_BASE+0x054)
+-#define CSR_UCODE_DRV_GP1_SET   (CSR_BASE+0x058)
+-#define CSR_UCODE_DRV_GP1_CLR   (CSR_BASE+0x05c)
+-#define CSR_UCODE_DRV_GP2       (CSR_BASE+0x060)
+-#define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
+-
+-/*
+- * Indicates hardware rev, to determine CCK backoff for txpower calculation.
+- * Bit fields:
+- *  3-2:  0 = A, 1 = B, 2 = C, 3 = D step
+- */
+-#define CSR_HW_REV_WA_REG	(CSR_BASE+0x22C)
+-
+-/* Hardware interface configuration bits */
+-#define CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R	(0x00000010)
+-#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER	(0x00000C00)
+-#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI		(0x00000100)
+-#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI	(0x00000200)
+-#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
+-
+-/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
+- * acknowledged (reset) by host writing "1" to flagged bits. */
+-#define CSR_INT_BIT_FH_RX        (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
+-#define CSR_INT_BIT_HW_ERR       (1 << 29) /* DMA hardware error FH_INT[31] */
+-#define CSR_INT_BIT_DNLD         (1 << 28) /* uCode Download */
+-#define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
+-#define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
+-#define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
+-#define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
+-#define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */
+-#define CSR_INT_BIT_SW_RX        (1 << 3)  /* Rx, command responses, 3945 */
+-#define CSR_INT_BIT_WAKEUP       (1 << 1)  /* NIC controller waking up (pwr mgmt) */
+-#define CSR_INT_BIT_ALIVE        (1 << 0)  /* uCode interrupts once it initializes */
+-
+-#define CSR_INI_SET_MASK	(CSR_INT_BIT_FH_RX   | \
+-				 CSR_INT_BIT_HW_ERR  | \
+-				 CSR_INT_BIT_FH_TX   | \
+-				 CSR_INT_BIT_SW_ERR  | \
+-				 CSR_INT_BIT_RF_KILL | \
+-				 CSR_INT_BIT_SW_RX   | \
+-				 CSR_INT_BIT_WAKEUP  | \
+-				 CSR_INT_BIT_ALIVE)
+-
+-/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
+-#define CSR_FH_INT_BIT_ERR       (1 << 31) /* Error */
+-#define CSR_FH_INT_BIT_HI_PRIOR  (1 << 30) /* High priority Rx, bypass coalescing */
+-#define CSR_FH_INT_BIT_RX_CHNL1  (1 << 17) /* Rx channel 1 */
+-#define CSR_FH_INT_BIT_RX_CHNL0  (1 << 16) /* Rx channel 0 */
+-#define CSR_FH_INT_BIT_TX_CHNL1  (1 << 1)  /* Tx channel 1 */
+-#define CSR_FH_INT_BIT_TX_CHNL0  (1 << 0)  /* Tx channel 0 */
+-
+-#define CSR_FH_INT_RX_MASK	(CSR_FH_INT_BIT_HI_PRIOR | \
+-				 CSR_FH_INT_BIT_RX_CHNL1 | \
+-				 CSR_FH_INT_BIT_RX_CHNL0)
+-
+-#define CSR_FH_INT_TX_MASK	(CSR_FH_INT_BIT_TX_CHNL1 | \
+-				 CSR_FH_INT_BIT_TX_CHNL0)
+-
+-
+-/* RESET */
+-#define CSR_RESET_REG_FLAG_NEVO_RESET                (0x00000001)
+-#define CSR_RESET_REG_FLAG_FORCE_NMI                 (0x00000002)
+-#define CSR_RESET_REG_FLAG_SW_RESET                  (0x00000080)
+-#define CSR_RESET_REG_FLAG_MASTER_DISABLED           (0x00000100)
+-#define CSR_RESET_REG_FLAG_STOP_MASTER               (0x00000200)
+-
+-/* GP (general purpose) CONTROL */
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY        (0x00000001)
+-#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE              (0x00000004)
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ         (0x00000008)
+-#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)
+-
+-#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN           (0x00000001)
+-
+-#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE         (0x07000000)
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE         (0x04000000)
+-#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW          (0x08000000)
+-
+-
+-/* EEPROM REG */
+-#define CSR_EEPROM_REG_READ_VALID_MSK	(0x00000001)
+-#define CSR_EEPROM_REG_BIT_CMD		(0x00000002)
+-
+-/* EEPROM GP */
+-#define CSR_EEPROM_GP_VALID_MSK		(0x00000006)
+-#define CSR_EEPROM_GP_BAD_SIGNATURE	(0x00000000)
+-#define CSR_EEPROM_GP_IF_OWNER_MSK	(0x00000180)
+-
+-/* UCODE DRV GP */
+-#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP             (0x00000001)
+-#define CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)
+-#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)
+-#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)
+-
+-/* GPIO */
+-#define CSR_GPIO_IN_BIT_AUX_POWER                   (0x00000200)
+-#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC                (0x00000000)
+-#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC		CSR_GPIO_IN_BIT_AUX_POWER
+-
+-/* GI Chicken Bits */
+-#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
+-#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)
+-
+-/*=== HBUS (Host-side Bus) ===*/
+-#define HBUS_BASE	(0x400)
+-
+-/*
+- * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
+- * structures, error log, event log, verifying uCode load).
+- * First write to address register, then read from or write to data register
+- * to complete the job.  Once the address register is set up, accesses to
+- * data registers auto-increment the address by one dword.
+- * Bit usage for address registers (read or write):
+- *  0-31:  memory address within device
+- */
+-#define HBUS_TARG_MEM_RADDR     (HBUS_BASE+0x00c)
+-#define HBUS_TARG_MEM_WADDR     (HBUS_BASE+0x010)
+-#define HBUS_TARG_MEM_WDAT      (HBUS_BASE+0x018)
+-#define HBUS_TARG_MEM_RDAT      (HBUS_BASE+0x01c)
+-
+-/*
+- * Registers for accessing device's internal peripheral registers
+- * (e.g. SCD, BSM, etc.).  First write to address register,
+- * then read from or write to data register to complete the job.
+- * Bit usage for address registers (read or write):
+- *  0-15:  register address (offset) within device
+- * 24-25:  (# bytes - 1) to read or write (e.g. 3 for dword)
+- */
+-#define HBUS_TARG_PRPH_WADDR    (HBUS_BASE+0x044)
+-#define HBUS_TARG_PRPH_RADDR    (HBUS_BASE+0x048)
+-#define HBUS_TARG_PRPH_WDAT     (HBUS_BASE+0x04c)
+-#define HBUS_TARG_PRPH_RDAT     (HBUS_BASE+0x050)
+-
+-/*
+- * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
+- * Driver sets this to indicate index to next TFD that driver will fill
+- * (1 past latest filled).
+- * Bit usage:
+- *  0-7:  queue write index (0-255)
+- * 11-8:  queue selector (0-15)
+- */
+-#define HBUS_TARG_WRPTR         (HBUS_BASE+0x060)
+-
+-#define HBUS_TARG_MBX_C         (HBUS_BASE+0x030)
+-
+-#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED         (0x00000004)
+-
+ #define TFD_QUEUE_SIZE_MAX      (256)
+ 
+ #define IWL_NUM_SCAN_RATES         (2)
+@@ -599,9 +113,6 @@ struct iwl4965_eeprom {
+ #define TFD_TX_CMD_SLOTS 256
+ #define TFD_CMD_SLOTS 32
+ 
+-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \
+-			      sizeof(struct iwl4965_cmd_meta))
+-
+ /*
+  * RX related structures and functions
+  */
+@@ -615,16 +126,18 @@ struct iwl4965_eeprom {
+ /* Sizes and addresses for instruction and data memory (SRAM) in
+  * 4965's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
+ #define RTC_INST_LOWER_BOUND			(0x000000)
+-#define KDR_RTC_INST_UPPER_BOUND		(0x018000)
++#define IWL49_RTC_INST_UPPER_BOUND		(0x018000)
+ 
+ #define RTC_DATA_LOWER_BOUND			(0x800000)
+-#define KDR_RTC_DATA_UPPER_BOUND		(0x80A000)
++#define IWL49_RTC_DATA_UPPER_BOUND		(0x80A000)
+ 
+-#define KDR_RTC_INST_SIZE    (KDR_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
+-#define KDR_RTC_DATA_SIZE    (KDR_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
++#define IWL49_RTC_INST_SIZE	\
++			(IWL49_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
++#define IWL49_RTC_DATA_SIZE	\
++			(IWL49_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
+ 
+-#define IWL_MAX_INST_SIZE KDR_RTC_INST_SIZE
+-#define IWL_MAX_DATA_SIZE KDR_RTC_DATA_SIZE
++#define IWL_MAX_INST_SIZE IWL49_RTC_INST_SIZE
++#define IWL_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
+ 
+ /* Size of uCode instruction memory in bootstrap state machine */
+ #define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE
+@@ -632,7 +145,7 @@ struct iwl4965_eeprom {
+ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
+ {
+ 	return (addr >= RTC_DATA_LOWER_BOUND) &&
+-	       (addr < KDR_RTC_DATA_UPPER_BOUND);
++	       (addr < IWL49_RTC_DATA_UPPER_BOUND);
+ }
+ 
+ /********************* START TEMPERATURE *************************************/
+@@ -1872,10 +1385,10 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags)
+  * up to 7 DMA channels (FIFOs).  Each Tx queue is supported by a circular array
+  * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
+  */
+-#define IWL4965_MAX_WIN_SIZE              64
+-#define IWL4965_QUEUE_SIZE               256
+-#define IWL4965_NUM_FIFOS                  7
+-#define IWL_MAX_NUM_QUEUES                16
++#define IWL4965_MAX_WIN_SIZE	64
++#define IWL4965_QUEUE_SIZE	256
++#define IWL4965_NUM_FIFOS	7
++#define IWL4965_MAX_NUM_QUEUES	16
+ 
+ 
+ /**
+@@ -2040,30 +1553,30 @@ struct iwl4965_sched_queue_byte_cnt_tbl {
+  */
+ struct iwl4965_shared {
+ 	struct iwl4965_sched_queue_byte_cnt_tbl
+-	 queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES];
+-	__le32 val0;
++	 queues_byte_cnt_tbls[IWL4965_MAX_NUM_QUEUES];
++	__le32 rb_closed;
+ 
+ 	/* __le32 rb_closed_stts_rb_num:12; */
+ #define IWL_rb_closed_stts_rb_num_POS 0
+ #define IWL_rb_closed_stts_rb_num_LEN 12
+-#define IWL_rb_closed_stts_rb_num_SYM val0
++#define IWL_rb_closed_stts_rb_num_SYM rb_closed
+ 	/* __le32 rsrv1:4; */
+ 	/* __le32 rb_closed_stts_rx_frame_num:12; */
+ #define IWL_rb_closed_stts_rx_frame_num_POS 16
+ #define IWL_rb_closed_stts_rx_frame_num_LEN 12
+-#define IWL_rb_closed_stts_rx_frame_num_SYM val0
++#define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed
+ 	/* __le32 rsrv2:4; */
+ 
+-	__le32 val1;
++	__le32 frm_finished;
+ 	/* __le32 frame_finished_stts_rb_num:12; */
+ #define IWL_frame_finished_stts_rb_num_POS 0
+ #define IWL_frame_finished_stts_rb_num_LEN 12
+-#define IWL_frame_finished_stts_rb_num_SYM val1
++#define IWL_frame_finished_stts_rb_num_SYM frm_finished
+ 	/* __le32 rsrv3:4; */
+ 	/* __le32 frame_finished_stts_rx_frame_num:12; */
+ #define IWL_frame_finished_stts_rx_frame_num_POS 16
+ #define IWL_frame_finished_stts_rx_frame_num_LEN 12
+-#define IWL_frame_finished_stts_rx_frame_num_SYM val1
++#define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished
+ 	/* __le32 rsrv4:4; */
+ 
+ 	__le32 padding1;  /* so that allocation will be aligned to 16B */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-io.h b/drivers/net/wireless/iwlwifi/iwl-4965-io.h
+deleted file mode 100644
+index 34a0b57..0000000
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-io.h
++++ /dev/null
+@@ -1,431 +0,0 @@
+-/******************************************************************************
+- *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
+- *
+- * Portions of this file are derived from the ipw3945 project.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called LICENSE.
+- *
+- * Contact Information:
+- * James P. Ketrenos <ipw2100-admin at linux.intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+- *****************************************************************************/
+-
+-#ifndef __iwl4965_io_h__
+-#define __iwl4965_io_h__
+-
+-#include <linux/io.h>
+-
+-#include "iwl-4965-debug.h"
+-
+-/*
+- * IO, register, and NIC memory access functions
+- *
+- * NOTE on naming convention and macro usage for these
+- *
+- * A single _ prefix before a an access function means that no state
+- * check or debug information is printed when that function is called.
+- *
+- * A double __ prefix before an access function means that state is checked
+- * and the current line number is printed in addition to any other debug output.
+- *
+- * The non-prefixed name is the #define that maps the caller into a
+- * #define that provides the caller's __LINE__ to the double prefix version.
+- *
+- * If you wish to call the function without any debug or state checking,
+- * you should use the single _ prefix version (as is used by dependent IO
+- * routines, for example _iwl4965_read_direct32 calls the non-check version of
+- * _iwl4965_read32.)
+- *
+- * These declarations are *extremely* useful in quickly isolating code deltas
+- * which result in misconfiguring of the hardware I/O.  In combination with
+- * git-bisect and the IO debug level you can quickly determine the specific
+- * commit which breaks the IO sequence to the hardware.
+- *
+- */
+-
+-#define _iwl4965_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *iwl,
+-				 u32 ofs, u32 val)
+-{
+-	IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
+-	_iwl4965_write32(iwl, ofs, val);
+-}
+-#define iwl4965_write32(iwl, ofs, val) \
+-	__iwl4965_write32(__FILE__, __LINE__, iwl, ofs, val)
+-#else
+-#define iwl4965_write32(iwl, ofs, val) _iwl4965_write32(iwl, ofs, val)
+-#endif
+-
+-#define _iwl4965_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *iwl, u32 ofs)
+-{
+-	IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
+-	return _iwl4965_read32(iwl, ofs);
+-}
+-#define iwl4965_read32(iwl, ofs) __iwl4965_read32(__FILE__, __LINE__, iwl, ofs)
+-#else
+-#define iwl4965_read32(p, o) _iwl4965_read32(p, o)
+-#endif
+-
+-static inline int _iwl4965_poll_bit(struct iwl4965_priv *priv, u32 addr,
+-				u32 bits, u32 mask, int timeout)
+-{
+-	int i = 0;
+-
+-	do {
+-		if ((_iwl4965_read32(priv, addr) & mask) == (bits & mask))
+-			return i;
+-		mdelay(10);
+-		i += 10;
+-	} while (i < timeout);
+-
+-	return -ETIMEDOUT;
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline int __iwl4965_poll_bit(const char *f, u32 l,
+-				 struct iwl4965_priv *priv, u32 addr,
+-				 u32 bits, u32 mask, int timeout)
+-{
+-	int ret = _iwl4965_poll_bit(priv, addr, bits, mask, timeout);
+-	if (unlikely(ret  == -ETIMEDOUT))
+-		IWL_DEBUG_IO
+-		    ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
+-		     addr, bits, mask, f, l);
+-	else
+-		IWL_DEBUG_IO
+-		    ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
+-		     addr, bits, mask, ret, f, l);
+-	return ret;
+-}
+-#define iwl4965_poll_bit(iwl, addr, bits, mask, timeout) \
+-	__iwl4965_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
+-#else
+-#define iwl4965_poll_bit(p, a, b, m, t) _iwl4965_poll_bit(p, a, b, m, t)
+-#endif
+-
+-static inline void _iwl4965_set_bit(struct iwl4965_priv *priv, u32 reg, u32 mask)
+-{
+-	_iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) | mask);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_set_bit(const char *f, u32 l,
+-				 struct iwl4965_priv *priv, u32 reg, u32 mask)
+-{
+-	u32 val = _iwl4965_read32(priv, reg) | mask;
+-	IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+-	_iwl4965_write32(priv, reg, val);
+-}
+-#define iwl4965_set_bit(p, r, m) __iwl4965_set_bit(__FILE__, __LINE__, p, r, m)
+-#else
+-#define iwl4965_set_bit(p, r, m) _iwl4965_set_bit(p, r, m)
+-#endif
+-
+-static inline void _iwl4965_clear_bit(struct iwl4965_priv *priv, u32 reg, u32 mask)
+-{
+-	_iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) & ~mask);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_clear_bit(const char *f, u32 l,
+-				   struct iwl4965_priv *priv, u32 reg, u32 mask)
+-{
+-	u32 val = _iwl4965_read32(priv, reg) & ~mask;
+-	IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+-	_iwl4965_write32(priv, reg, val);
+-}
+-#define iwl4965_clear_bit(p, r, m) __iwl4965_clear_bit(__FILE__, __LINE__, p, r, m)
+-#else
+-#define iwl4965_clear_bit(p, r, m) _iwl4965_clear_bit(p, r, m)
+-#endif
+-
+-static inline int _iwl4965_grab_nic_access(struct iwl4965_priv *priv)
+-{
+-	int ret;
+-	u32 gp_ctl;
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-	if (atomic_read(&priv->restrict_refcnt))
+-		return 0;
+-#endif
+-	if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
+-	    test_bit(STATUS_RF_KILL_SW, &priv->status)) {
+-		IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
+-			"wakes up NIC\n");
+-
+-		/* 10 msec allows time for NIC to complete its data save */
+-		gp_ctl = _iwl4965_read32(priv, CSR_GP_CNTRL);
+-		if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
+-			IWL_DEBUG_RF_KILL("Wait for complete power-down, "
+-				"gpctl = 0x%08x\n", gp_ctl);
+-			mdelay(10);
+-		} else
+-			IWL_DEBUG_RF_KILL("power-down complete, "
+-					  "gpctl = 0x%08x\n", gp_ctl);
+-	}
+-
+-	/* this bit wakes up the NIC */
+-	_iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+-	ret = _iwl4965_poll_bit(priv, CSR_GP_CNTRL,
+-			   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+-			   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+-			    CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
+-	if (ret < 0) {
+-		IWL_ERROR("MAC is in deep sleep!\n");
+-		return -EIO;
+-	}
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-	atomic_inc(&priv->restrict_refcnt);
+-#endif
+-	return 0;
+-}
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline int __iwl4965_grab_nic_access(const char *f, u32 l,
+-					       struct iwl4965_priv *priv)
+-{
+-	if (atomic_read(&priv->restrict_refcnt))
+-		IWL_DEBUG_INFO("Grabbing access while already held at "
+-			       "line %d.\n", l);
+-
+-	IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
+-	return _iwl4965_grab_nic_access(priv);
+-}
+-#define iwl4965_grab_nic_access(priv) \
+-	__iwl4965_grab_nic_access(__FILE__, __LINE__, priv)
+-#else
+-#define iwl4965_grab_nic_access(priv) \
+-	_iwl4965_grab_nic_access(priv)
+-#endif
+-
+-static inline void _iwl4965_release_nic_access(struct iwl4965_priv *priv)
+-{
+-#ifdef CONFIG_IWL4965_DEBUG
+-	if (atomic_dec_and_test(&priv->restrict_refcnt))
+-#endif
+-		_iwl4965_clear_bit(priv, CSR_GP_CNTRL,
+-			       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_release_nic_access(const char *f, u32 l,
+-					    struct iwl4965_priv *priv)
+-{
+-	if (atomic_read(&priv->restrict_refcnt) <= 0)
+-		IWL_ERROR("Release unheld nic access at line %d.\n", l);
+-
+-	IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
+-	_iwl4965_release_nic_access(priv);
+-}
+-#define iwl4965_release_nic_access(priv) \
+-	__iwl4965_release_nic_access(__FILE__, __LINE__, priv)
+-#else
+-#define iwl4965_release_nic_access(priv) \
+-	_iwl4965_release_nic_access(priv)
+-#endif
+-
+-static inline u32 _iwl4965_read_direct32(struct iwl4965_priv *priv, u32 reg)
+-{
+-	return _iwl4965_read32(priv, reg);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline u32 __iwl4965_read_direct32(const char *f, u32 l,
+-					struct iwl4965_priv *priv, u32 reg)
+-{
+-	u32 value = _iwl4965_read_direct32(priv, reg);
+-	if (!atomic_read(&priv->restrict_refcnt))
+-		IWL_ERROR("Nic access not held from %s %d\n", f, l);
+-	IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
+-		     f, l);
+-	return value;
+-}
+-#define iwl4965_read_direct32(priv, reg) \
+-	__iwl4965_read_direct32(__FILE__, __LINE__, priv, reg)
+-#else
+-#define iwl4965_read_direct32 _iwl4965_read_direct32
+-#endif
+-
+-static inline void _iwl4965_write_direct32(struct iwl4965_priv *priv,
+-					 u32 reg, u32 value)
+-{
+-	_iwl4965_write32(priv, reg, value);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static void __iwl4965_write_direct32(u32 line,
+-				   struct iwl4965_priv *priv, u32 reg, u32 value)
+-{
+-	if (!atomic_read(&priv->restrict_refcnt))
+-		IWL_ERROR("Nic access not held from line %d\n", line);
+-	_iwl4965_write_direct32(priv, reg, value);
+-}
+-#define iwl4965_write_direct32(priv, reg, value) \
+-	__iwl4965_write_direct32(__LINE__, priv, reg, value)
+-#else
+-#define iwl4965_write_direct32 _iwl4965_write_direct32
+-#endif
+-
+-static inline void iwl4965_write_reg_buf(struct iwl4965_priv *priv,
+-					       u32 reg, u32 len, u32 *values)
+-{
+-	u32 count = sizeof(u32);
+-
+-	if ((priv != NULL) && (values != NULL)) {
+-		for (; 0 < len; len -= count, reg += count, values++)
+-			_iwl4965_write_direct32(priv, reg, *values);
+-	}
+-}
+-
+-static inline int _iwl4965_poll_direct_bit(struct iwl4965_priv *priv,
+-					   u32 addr, u32 mask, int timeout)
+-{
+-	int i = 0;
+-
+-	do {
+-		if ((_iwl4965_read_direct32(priv, addr) & mask) == mask)
+-			return i;
+-		mdelay(10);
+-		i += 10;
+-	} while (i < timeout);
+-
+-	return -ETIMEDOUT;
+-}
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline int __iwl4965_poll_direct_bit(const char *f, u32 l,
+-					    struct iwl4965_priv *priv,
+-					    u32 addr, u32 mask, int timeout)
+-{
+-	int ret  = _iwl4965_poll_direct_bit(priv, addr, mask, timeout);
+-
+-	if (unlikely(ret == -ETIMEDOUT))
+-		IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - "
+-			     "timedout - %s %d\n", addr, mask, f, l);
+-	else
+-		IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
+-			     "- %s %d\n", addr, mask, ret, f, l);
+-	return ret;
+-}
+-#define iwl4965_poll_direct_bit(iwl, addr, mask, timeout) \
+-	__iwl4965_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
+-#else
+-#define iwl4965_poll_direct_bit _iwl4965_poll_direct_bit
+-#endif
+-
+-static inline u32 _iwl4965_read_prph(struct iwl4965_priv *priv, u32 reg)
+-{
+-	_iwl4965_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+-	return _iwl4965_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline u32 __iwl4965_read_prph(u32 line, struct iwl4965_priv *priv, u32 reg)
+-{
+-	if (!atomic_read(&priv->restrict_refcnt))
+-		IWL_ERROR("Nic access not held from line %d\n", line);
+-	return _iwl4965_read_prph(priv, reg);
+-}
+-
+-#define iwl4965_read_prph(priv, reg) \
+-	__iwl4965_read_prph(__LINE__, priv, reg)
+-#else
+-#define iwl4965_read_prph _iwl4965_read_prph
+-#endif
+-
+-static inline void _iwl4965_write_prph(struct iwl4965_priv *priv,
+-					     u32 addr, u32 val)
+-{
+-	_iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
+-			      ((addr & 0x0000FFFF) | (3 << 24)));
+-	_iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_write_prph(u32 line, struct iwl4965_priv *priv,
+-					      u32 addr, u32 val)
+-{
+-	if (!atomic_read(&priv->restrict_refcnt))
+-		IWL_ERROR("Nic access from line %d\n", line);
+-	_iwl4965_write_prph(priv, addr, val);
+-}
+-
+-#define iwl4965_write_prph(priv, addr, val) \
+-	__iwl4965_write_prph(__LINE__, priv, addr, val);
+-#else
+-#define iwl4965_write_prph _iwl4965_write_prph
+-#endif
+-
+-#define _iwl4965_set_bits_prph(priv, reg, mask) \
+-	_iwl4965_write_prph(priv, reg, (_iwl4965_read_prph(priv, reg) | mask))
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_set_bits_prph(u32 line, struct iwl4965_priv *priv,
+-					u32 reg, u32 mask)
+-{
+-	if (!atomic_read(&priv->restrict_refcnt))
+-		IWL_ERROR("Nic access not held from line %d\n", line);
+-
+-	_iwl4965_set_bits_prph(priv, reg, mask);
+-}
+-#define iwl4965_set_bits_prph(priv, reg, mask) \
+-	__iwl4965_set_bits_prph(__LINE__, priv, reg, mask)
+-#else
+-#define iwl4965_set_bits_prph _iwl4965_set_bits_prph
+-#endif
+-
+-#define _iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \
+-	_iwl4965_write_prph(priv, reg, ((_iwl4965_read_prph(priv, reg) & mask) | bits))
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_set_bits_mask_prph(u32 line,
+-		struct iwl4965_priv *priv, u32 reg, u32 bits, u32 mask)
+-{
+-	if (!atomic_read(&priv->restrict_refcnt))
+-		IWL_ERROR("Nic access not held from line %d\n", line);
+-	_iwl4965_set_bits_mask_prph(priv, reg, bits, mask);
+-}
+-#define iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \
+-	__iwl4965_set_bits_mask_prph(__LINE__, priv, reg, bits, mask)
+-#else
+-#define iwl4965_set_bits_mask_prph _iwl4965_set_bits_mask_prph
+-#endif
+-
+-static inline void iwl4965_clear_bits_prph(struct iwl4965_priv
+-						 *priv, u32 reg, u32 mask)
+-{
+-	u32 val = _iwl4965_read_prph(priv, reg);
+-	_iwl4965_write_prph(priv, reg, (val & ~mask));
+-}
+-
+-static inline u32 iwl4965_read_targ_mem(struct iwl4965_priv *priv, u32 addr)
+-{
+-	iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
+-	return iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+-}
+-
+-static inline void iwl4965_write_targ_mem(struct iwl4965_priv *priv, u32 addr, u32 val)
+-{
+-	iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+-	iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
+-}
+-
+-static inline void iwl4965_write_targ_mem_buf(struct iwl4965_priv *priv, u32 addr,
+-					  u32 len, u32 *values)
+-{
+-	iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+-	for (; 0 < len; len -= sizeof(u32), values++)
+-		iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
+-}
+-#endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+index d064622..b608e1c 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
++++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 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
+@@ -36,9 +36,10 @@
+ 
+ #include <linux/workqueue.h>
+ 
+-#include "../net/mac80211/ieee80211_rate.h"
++#include "../net/mac80211/rate.h"
+ 
+ #include "iwl-4965.h"
++#include "iwl-core.h"
+ #include "iwl-helpers.h"
+ 
+ #define RS_NAME "iwl-4965-rs"
+@@ -83,7 +84,7 @@ struct iwl4965_rate_scale_data {
+ /**
+  * struct iwl4965_scale_tbl_info -- tx params and success history for all rates
+  *
+- * There are two of these in struct iwl_rate_scale_priv,
++ * There are two of these in struct iwl4965_lq_sta,
+  * one for "active", and one for "search".
+  */
+ struct iwl4965_scale_tbl_info {
+@@ -98,8 +99,23 @@ struct iwl4965_scale_tbl_info {
+ 	struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
+ };
+ 
++#ifdef CONFIG_IWL4965_HT
++
++struct iwl4965_traffic_load {
++	unsigned long time_stamp;	/* age of the oldest statistics */
++	u32 packet_count[TID_QUEUE_MAX_SIZE];   /* packet count in this time
++						 * slice */
++	u32 total;			/* total num of packets during the
++					 * last TID_MAX_TIME_DIFF */
++	u8 queue_count;			/* number of queues that has
++					 * been used since the last cleanup */
++	u8 head;			/* start of the circular buffer */
++};
++
++#endif /* CONFIG_IWL4965_HT */
++
+ /**
+- * struct iwl_rate_scale_priv -- driver's rate scaling private structure
++ * struct iwl4965_lq_sta -- driver's rate scaling private structure
+  *
+  * Pointer to this gets passed back and forth between driver and mac80211.
+  */
+@@ -124,7 +140,7 @@ struct iwl4965_lq_sta {
+ 	u8 valid_antenna;
+ 	u8 is_green;
+ 	u8 is_dup;
+-	u8 phymode;
++	enum ieee80211_band band;
+ 	u8 ibss_sta_added;
+ 
+ 	/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
+@@ -134,23 +150,30 @@ struct iwl4965_lq_sta {
+ 	u16 active_mimo_rate;
+ 	u16 active_rate_basic;
+ 
+-	struct iwl4965_link_quality_cmd lq;
++	struct iwl_link_quality_cmd lq;
+ 	struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
++#ifdef CONFIG_IWL4965_HT
++	struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT];
++	u8 tx_agg_tid_en;
++#endif
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ 	struct dentry *rs_sta_dbgfs_scale_table_file;
+ 	struct dentry *rs_sta_dbgfs_stats_table_file;
++#ifdef CONFIG_IWL4965_HT
++	struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
++#endif
+ 	struct iwl4965_rate dbg_fixed;
+-	struct iwl4965_priv *drv;
++	struct iwl_priv *drv;
+ #endif
+ };
+ 
+-static void rs_rate_scale_perform(struct iwl4965_priv *priv,
++static void rs_rate_scale_perform(struct iwl_priv *priv,
+ 				   struct net_device *dev,
+ 				   struct ieee80211_hdr *hdr,
+ 				   struct sta_info *sta);
+ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ 			     struct iwl4965_rate *tx_mcs,
+-			     struct iwl4965_link_quality_cmd *tbl);
++			     struct iwl_link_quality_cmd *tbl);
+ 
+ 
+ #ifdef CONFIG_MAC80211_DEBUGFS
+@@ -207,68 +230,150 @@ static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = {
+ 	0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293
+ };
+ 
+-static int iwl4965_lq_sync_callback(struct iwl4965_priv *priv,
+-				struct iwl4965_cmd *cmd, struct sk_buff *skb)
++static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags)
+ {
+-	/*We didn't cache the SKB; let the caller free it */
+-	return 1;
++	return (u8)(rate_n_flags & 0xFF);
+ }
+ 
+-static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags)
++static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
+ {
+-	return (u8)(rate_n_flags & 0xFF);
++	window->data = 0;
++	window->success_counter = 0;
++	window->success_ratio = IWL_INVALID_VALUE;
++	window->counter = 0;
++	window->average_tpt = IWL_INVALID_VALUE;
++	window->stamp = 0;
+ }
+ 
+-static int rs_send_lq_cmd(struct iwl4965_priv *priv,
+-			  struct iwl4965_link_quality_cmd *lq, u8 flags)
++#ifdef CONFIG_IWL4965_HT
++/*
++ *	removes the old data from the statistics. All data that is older than
++ *	TID_MAX_TIME_DIFF, will be deleted.
++ */
++static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
+-	int i;
+-#endif
+-	struct iwl4965_host_cmd cmd = {
+-		.id = REPLY_TX_LINK_QUALITY_CMD,
+-		.len = sizeof(struct iwl4965_link_quality_cmd),
+-		.meta.flags = flags,
+-		.data = lq,
+-	};
+-
+-	if ((lq->sta_id == 0xFF) &&
+-	    (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
+-		return -EINVAL;
++	/* The oldest age we want to keep */
++	u32 oldest_time = curr_time - TID_MAX_TIME_DIFF;
++
++	while (tl->queue_count &&
++	       (tl->time_stamp < oldest_time)) {
++		tl->total -= tl->packet_count[tl->head];
++		tl->packet_count[tl->head] = 0;
++		tl->time_stamp += TID_QUEUE_CELL_SPACING;
++		tl->queue_count--;
++		tl->head++;
++		if (tl->head >= TID_QUEUE_MAX_SIZE)
++			tl->head = 0;
++	}
++}
++
++/*
++ *	increment traffic load value for tid and also remove
++ *	any old values if passed the certain time period
++ */
++static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, u8 tid)
++{
++	u32 curr_time = jiffies_to_msecs(jiffies);
++	u32 time_diff;
++	s32 index;
++	struct iwl4965_traffic_load *tl = NULL;
+ 
+-	if (lq->sta_id == 0xFF)
+-		lq->sta_id = IWL_AP_ID;
++	if (tid >= TID_MAX_LOAD_COUNT)
++		return;
+ 
+-	IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id);
+-	IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n",
+-		       lq->general_params.single_stream_ant_msk,
+-		       lq->general_params.dual_stream_ant_msk);
+-#ifdef CONFIG_IWL4965_DEBUG
+-	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+-		IWL_DEBUG_RATE("lq index %d 0x%X\n",
+-				i, lq->rs_table[i].rate_n_flags);
+-#endif
++	tl = &lq_data->load[tid];
+ 
+-	if (flags & CMD_ASYNC)
+-		cmd.meta.u.callback = iwl4965_lq_sync_callback;
++	curr_time -= curr_time % TID_ROUND_VALUE;
+ 
+-	if (iwl4965_is_associated(priv) && priv->assoc_station_added &&
+-	    priv->lq_mngr.lq_ready)
+-		return  iwl4965_send_cmd(priv, &cmd);
++	/* Happens only for the first packet. Initialize the data */
++	if (!(tl->queue_count)) {
++		tl->total = 1;
++		tl->time_stamp = curr_time;
++		tl->queue_count = 1;
++		tl->head = 0;
++		tl->packet_count[0] = 1;
++		return;
++	}
+ 
+-	return 0;
++	time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
++	index = time_diff / TID_QUEUE_CELL_SPACING;
++
++	/* The history is too long: remove data that is older than */
++	/* TID_MAX_TIME_DIFF */
++	if (index >= TID_QUEUE_MAX_SIZE)
++		rs_tl_rm_old_stats(tl, curr_time);
++
++	index = (tl->head + index) % TID_QUEUE_MAX_SIZE;
++	tl->packet_count[index] = tl->packet_count[index] + 1;
++	tl->total = tl->total + 1;
++
++	if ((index + 1) > tl->queue_count)
++		tl->queue_count = index + 1;
+ }
+ 
+-static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
++/*
++	get the traffic load value for tid
++*/
++static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid)
+ {
+-	window->data = 0;
+-	window->success_counter = 0;
+-	window->success_ratio = IWL_INVALID_VALUE;
+-	window->counter = 0;
+-	window->average_tpt = IWL_INVALID_VALUE;
+-	window->stamp = 0;
++	u32 curr_time = jiffies_to_msecs(jiffies);
++	u32 time_diff;
++	s32 index;
++	struct iwl4965_traffic_load *tl = NULL;
++
++	if (tid >= TID_MAX_LOAD_COUNT)
++		return 0;
++
++	tl = &(lq_data->load[tid]);
++
++	curr_time -= curr_time % TID_ROUND_VALUE;
++
++	if (!(tl->queue_count))
++		return 0;
++
++	time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
++	index = time_diff / TID_QUEUE_CELL_SPACING;
++
++	/* The history is too long: remove data that is older than */
++	/* TID_MAX_TIME_DIFF */
++	if (index >= TID_QUEUE_MAX_SIZE)
++		rs_tl_rm_old_stats(tl, curr_time);
++
++	return tl->total;
++}
++
++static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
++				struct iwl4965_lq_sta *lq_data, u8 tid,
++				struct sta_info *sta)
++{
++	unsigned long state;
++	DECLARE_MAC_BUF(mac);
++
++	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++	state = sta->ampdu_mlme.tid_state_tx[tid];
++	spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++	if (state == HT_AGG_STATE_IDLE &&
++	    rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
++		IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
++				print_mac(mac, sta->addr), tid);
++		ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
++	}
++}
++
++static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
++				struct iwl4965_lq_sta *lq_data,
++				struct sta_info *sta)
++{
++	if ((tid < TID_MAX_LOAD_COUNT))
++		rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
++	else if (tid == IWL_AGG_ALL_TID)
++		for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
++			rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
+ }
+ 
++#endif /* CONFIG_IWLWIFI_HT */
++
+ /**
+  * rs_collect_tx_data - Update the success/failure sliding window
+  *
+@@ -277,7 +382,8 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
+  * packets.
+  */
+ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows,
+-			      int scale_index, s32 tpt, u32 status)
++			      int scale_index, s32 tpt, int retries,
++			      int successes)
+ {
+ 	struct iwl4965_rate_scale_data *window = NULL;
+ 	u64 mask;
+@@ -298,26 +404,33 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows,
+ 	 * subtract "1" from the success counter (this is the main reason
+ 	 * we keep these bitmaps!).
+ 	 */
+-	if (window->counter >= win_size) {
+-		window->counter = win_size - 1;
+-		mask = 1;
+-		mask = (mask << (win_size - 1));
+-		if ((window->data & mask)) {
+-			window->data &= ~mask;
+-			window->success_counter = window->success_counter - 1;
++	while (retries > 0) {
++		if (window->counter >= win_size) {
++			window->counter = win_size - 1;
++			mask = 1;
++			mask = (mask << (win_size - 1));
++			if (window->data & mask) {
++				window->data &= ~mask;
++				window->success_counter =
++					window->success_counter - 1;
++			}
+ 		}
+-	}
+ 
+-	/* Increment frames-attempted counter */
+-	window->counter = window->counter + 1;
++		/* Increment frames-attempted counter */
++		window->counter++;
++
++		/* Shift bitmap by one frame (throw away oldest history),
++		 * OR in "1", and increment "success" if this
++		 * frame was successful. */
++		mask = window->data;
++		window->data = (mask << 1);
++		if (successes > 0) {
++			window->success_counter = window->success_counter + 1;
++			window->data |= 0x1;
++			successes--;
++		}
+ 
+-	/* Shift bitmap by one frame (throw away oldest history),
+-	 * OR in "1", and increment "success" if this frame was successful. */
+-	mask = window->data;
+-	window->data = (mask << 1);
+-	if (status != 0) {
+-		window->success_counter = window->success_counter + 1;
+-		window->data |= 0x1;
++		retries--;
+ 	}
+ 
+ 	/* Calculate current success ratio, avoid divide-by-0! */
+@@ -404,13 +517,14 @@ static void rs_mcs_from_tbl(struct iwl4965_rate *mcs_rate,
+  * fill "search" or "active" tx mode table.
+  */
+ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate,
+-				    int phymode, struct iwl4965_scale_tbl_info *tbl,
++				    enum ieee80211_band band,
++				    struct iwl4965_scale_tbl_info *tbl,
+ 				    int *rate_idx)
+ {
+ 	int index;
+ 	u32 ant_msk;
+ 
+-	index = iwl4965_rate_index_from_plcp(mcs_rate->rate_n_flags);
++	index = iwl4965_hwrate_to_plcp_idx(mcs_rate->rate_n_flags);
+ 
+ 	if (index  == IWL_RATE_INVALID) {
+ 		*rate_idx = -1;
+@@ -429,7 +543,7 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate,
+ 			tbl->lq_type = LQ_NONE;
+ 		else {
+ 
+-			if (phymode == MODE_IEEE80211A)
++			if (band == IEEE80211_BAND_5GHZ)
+ 				tbl->lq_type = LQ_A;
+ 			else
+ 				tbl->lq_type = LQ_G;
+@@ -498,7 +612,7 @@ static inline void rs_toggle_antenna(struct iwl4965_rate *new_rate,
+ 	}
+ }
+ 
+-static inline u8 rs_use_green(struct iwl4965_priv *priv,
++static inline u8 rs_use_green(struct iwl_priv *priv,
+ 			      struct ieee80211_conf *conf)
+ {
+ #ifdef CONFIG_IWL4965_HT
+@@ -607,7 +721,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta,
+ 	if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
+ 		switch_to_legacy = 1;
+ 		scale_index = rs_ht_to_legacy[scale_index];
+-		if (lq_sta->phymode == MODE_IEEE80211A)
++		if (lq_sta->band == IEEE80211_BAND_5GHZ)
+ 			tbl->lq_type = LQ_A;
+ 		else
+ 			tbl->lq_type = LQ_G;
+@@ -625,7 +739,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta,
+ 	/* Mask with station rate restriction */
+ 	if (is_legacy(tbl->lq_type)) {
+ 		/* supp_rates has no CCK bits in A mode */
+-		if (lq_sta->phymode == (u8) MODE_IEEE80211A)
++		if (lq_sta->band == IEEE80211_BAND_5GHZ)
+ 			rate_mask  = (u16)(rate_mask &
+ 			   (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
+ 		else
+@@ -658,11 +772,12 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 	u8 retries;
+ 	int rs_index, index = 0;
+ 	struct iwl4965_lq_sta *lq_sta;
+-	struct iwl4965_link_quality_cmd *table;
++	struct iwl_link_quality_cmd *table;
+ 	struct sta_info *sta;
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
++	struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_hw *hw = local_to_hw(local);
+ 	struct iwl4965_rate_scale_data *window = NULL;
+ 	struct iwl4965_rate_scale_data *search_win = NULL;
+ 	struct iwl4965_rate tx_mcs;
+@@ -677,28 +792,32 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 	if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
+ 		return;
+ 
++	/* This packet was aggregated but doesn't carry rate scale info */
++	if ((tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) &&
++	    !(tx_resp->flags & IEEE80211_TX_STATUS_AMPDU))
++		return;
++
+ 	retries = tx_resp->retry_count;
+ 
+ 	if (retries > 15)
+ 		retries = 15;
+ 
++	rcu_read_lock();
+ 
+ 	sta = sta_info_get(local, hdr->addr1);
+ 
+-	if (!sta || !sta->rate_ctrl_priv) {
+-		if (sta)
+-			sta_info_put(sta);
+-		return;
+-	}
++	if (!sta || !sta->rate_ctrl_priv)
++		goto out;
++
+ 
+ 	lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
+ 
+ 	if (!priv->lq_mngr.lq_ready)
+-		return;
++		goto out;
+ 
+ 	if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ 	    !lq_sta->ibss_sta_added)
+-		return;
++		goto out;
+ 
+ 	table = &lq_sta->lq;
+ 	active_index = lq_sta->active_tbl;
+@@ -719,17 +838,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 	search_win = (struct iwl4965_rate_scale_data *)
+ 	    &(search_tbl->win[0]);
+ 
+-	tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
+-
+-	rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
+-				  &tbl_type, &rs_index);
+-	if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) {
+-		IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n",
+-			     rs_index, tx_mcs.rate_n_flags);
+-		sta_info_put(sta);
+-		return;
+-	}
+-
+ 	/*
+ 	 * Ignore this Tx frame response if its initial rate doesn't match
+ 	 * that of latest Link Quality command.  There may be stragglers
+@@ -738,14 +846,29 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 	 * to check "search" mode, or a prior "search" mode after we've moved
+ 	 * to a new "search" mode (which might become the new "active" mode).
+ 	 */
+-	if (retries &&
+-	    (tx_mcs.rate_n_flags !=
+-				le32_to_cpu(table->rs_table[0].rate_n_flags))) {
+-		IWL_DEBUG_RATE("initial rate does not match 0x%x 0x%x\n",
+-				tx_mcs.rate_n_flags,
+-				le32_to_cpu(table->rs_table[0].rate_n_flags));
+-		sta_info_put(sta);
+-		return;
++	tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[0].rate_n_flags);
++	rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index);
++	if (priv->band == IEEE80211_BAND_5GHZ)
++		rs_index -= IWL_FIRST_OFDM_RATE;
++
++	if ((tx_resp->control.tx_rate == NULL) ||
++	    (tbl_type.is_SGI ^
++		!!(tx_resp->control.flags & IEEE80211_TXCTL_SHORT_GI)) ||
++	    (tbl_type.is_fat ^
++		!!(tx_resp->control.flags & IEEE80211_TXCTL_40_MHZ_WIDTH)) ||
++	    (tbl_type.is_dup ^
++		!!(tx_resp->control.flags & IEEE80211_TXCTL_DUP_DATA)) ||
++	    (tbl_type.antenna_type ^
++		tx_resp->control.antenna_sel_tx) ||
++	    (!!(tx_mcs.rate_n_flags & RATE_MCS_HT_MSK) ^
++		!!(tx_resp->control.flags & IEEE80211_TXCTL_OFDM_HT)) ||
++	    (!!(tx_mcs.rate_n_flags & RATE_MCS_GF_MSK) ^
++		!!(tx_resp->control.flags & IEEE80211_TXCTL_GREEN_FIELD)) ||
++	    (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate !=
++		tx_resp->control.tx_rate->bitrate)) {
++		IWL_DEBUG_RATE("initial rate does not match 0x%x\n",
++				tx_mcs.rate_n_flags);
++		goto out;
+ 	}
+ 
+ 	/* Update frame history window with "failure" for each Tx retry. */
+@@ -754,7 +877,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 		 * Each tx attempt steps one entry deeper in the rate table. */
+ 		tx_mcs.rate_n_flags =
+ 		    le32_to_cpu(table->rs_table[index].rate_n_flags);
+-		rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
++		rs_get_tbl_info_from_mcs(&tx_mcs, priv->band,
+ 					  &tbl_type, &rs_index);
+ 
+ 		/* If type matches "search" table,
+@@ -766,7 +889,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 				tpt = search_tbl->expected_tpt[rs_index];
+ 			else
+ 				tpt = 0;
+-			rs_collect_tx_data(search_win, rs_index, tpt, 0);
++			rs_collect_tx_data(search_win, rs_index, tpt, 1, 0);
+ 
+ 		/* Else if type matches "current/active" table,
+ 		 * add failure to "current/active" history */
+@@ -777,7 +900,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 				tpt = curr_tbl->expected_tpt[rs_index];
+ 			else
+ 				tpt = 0;
+-			rs_collect_tx_data(window, rs_index, tpt, 0);
++			rs_collect_tx_data(window, rs_index, tpt, 1, 0);
+ 		}
+ 
+ 		/* If not searching for a new mode, increment failed counter
+@@ -794,14 +917,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 	 * if Tx was successful first try, use original rate,
+ 	 * else look up the rate that was, finally, successful.
+ 	 */
+-	if (!tx_resp->retry_count)
+-		tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
+-	else
+-		tx_mcs.rate_n_flags =
+-			le32_to_cpu(table->rs_table[index].rate_n_flags);
+-
+-	rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
+-				  &tbl_type, &rs_index);
++	tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags);
++	rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index);
+ 
+ 	/* Update frame history window with "success" if Tx got ACKed ... */
+ 	if (tx_resp->flags & IEEE80211_TX_STATUS_ACK)
+@@ -818,9 +935,13 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 			tpt = search_tbl->expected_tpt[rs_index];
+ 		else
+ 			tpt = 0;
+-		rs_collect_tx_data(search_win,
+-				    rs_index, tpt, status);
+-
++		if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
++			rs_collect_tx_data(search_win, rs_index, tpt,
++					   tx_resp->ampdu_ack_len,
++					   tx_resp->ampdu_ack_map);
++		else
++			rs_collect_tx_data(search_win, rs_index, tpt,
++					   1, status);
+ 	/* Else if type matches "current/active" table,
+ 	 * add final tx status to "current/active" history */
+ 	} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
+@@ -830,21 +951,34 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ 			tpt = curr_tbl->expected_tpt[rs_index];
+ 		else
+ 			tpt = 0;
+-		rs_collect_tx_data(window, rs_index, tpt, status);
++		if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
++			rs_collect_tx_data(window, rs_index, tpt,
++					   tx_resp->ampdu_ack_len,
++					   tx_resp->ampdu_ack_map);
++		else
++			rs_collect_tx_data(window, rs_index, tpt,
++					   1, status);
+ 	}
+ 
+ 	/* If not searching for new mode, increment success/failed counter
+ 	 * ... these help determine when to start searching again */
+ 	if (lq_sta->stay_in_tbl) {
+-		if (status)
+-			lq_sta->total_success++;
+-		else
+-			lq_sta->total_failed++;
++		if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) {
++			lq_sta->total_success += tx_resp->ampdu_ack_map;
++			lq_sta->total_failed +=
++			     (tx_resp->ampdu_ack_len - tx_resp->ampdu_ack_map);
++		} else {
++			if (status)
++				lq_sta->total_success++;
++			else
++				lq_sta->total_failed++;
++		}
+ 	}
+ 
+ 	/* See if there's a better rate or modulation mode to try. */
+ 	rs_rate_scale_perform(priv, dev, hdr, sta);
+-	sta_info_put(sta);
++out:
++	rcu_read_unlock();
+ 	return;
+ }
+ 
+@@ -948,7 +1082,7 @@ static void rs_get_expected_tpt_table(struct iwl4965_lq_sta *lq_sta,
+  * to decrease to match "active" throughput.  When moving from MIMO to SISO,
+  * bit rate will typically need to increase, but not if performance was bad.
+  */
+-static s32 rs_get_best_rate(struct iwl4965_priv *priv,
++static s32 rs_get_best_rate(struct iwl_priv *priv,
+ 			    struct iwl4965_lq_sta *lq_sta,
+ 			    struct iwl4965_scale_tbl_info *tbl,	/* "search" */
+ 			    u16 rate_mask, s8 index, s8 rate)
+@@ -1046,7 +1180,7 @@ static inline u8 rs_is_both_ant_supp(u8 valid_antenna)
+ /*
+  * Set up search table for MIMO
+  */
+-static int rs_switch_to_mimo(struct iwl4965_priv *priv,
++static int rs_switch_to_mimo(struct iwl_priv *priv,
+ 			     struct iwl4965_lq_sta *lq_sta,
+ 			     struct ieee80211_conf *conf,
+ 			     struct sta_info *sta,
+@@ -1105,13 +1239,13 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv,
+ 	return 0;
+ #else
+ 	return -1;
+-#endif				/*CONFIG_IWL4965_HT */
++#endif	/*CONFIG_IWL4965_HT */
+ }
+ 
+ /*
+  * Set up search table for SISO
+  */
+-static int rs_switch_to_siso(struct iwl4965_priv *priv,
++static int rs_switch_to_siso(struct iwl_priv *priv,
+ 			     struct iwl4965_lq_sta *lq_sta,
+ 			     struct ieee80211_conf *conf,
+ 			     struct sta_info *sta,
+@@ -1168,13 +1302,13 @@ static int rs_switch_to_siso(struct iwl4965_priv *priv,
+ #else
+ 	return -1;
+ 
+-#endif				/*CONFIG_IWL4965_HT */
++#endif	/*CONFIG_IWL4965_HT */
+ }
+ 
+ /*
+  * Try to switch to new modulation mode from legacy
+  */
+-static int rs_move_legacy_other(struct iwl4965_priv *priv,
++static int rs_move_legacy_other(struct iwl_priv *priv,
+ 				struct iwl4965_lq_sta *lq_sta,
+ 				struct ieee80211_conf *conf,
+ 				struct sta_info *sta,
+@@ -1272,7 +1406,7 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv,
+ /*
+  * Try to switch to new modulation mode from SISO
+  */
+-static int rs_move_siso_to_other(struct iwl4965_priv *priv,
++static int rs_move_siso_to_other(struct iwl_priv *priv,
+ 				 struct iwl4965_lq_sta *lq_sta,
+ 				 struct ieee80211_conf *conf,
+ 				 struct sta_info *sta,
+@@ -1325,6 +1459,7 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv,
+ 			break;
+ 		case IWL_SISO_SWITCH_GI:
+ 			IWL_DEBUG_HT("LQ: SISO SWITCH TO GI\n");
++
+ 			memcpy(search_tbl, tbl, sz);
+ 			search_tbl->action = 0;
+ 			if (search_tbl->is_SGI)
+@@ -1367,7 +1502,7 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv,
+ /*
+  * Try to switch to new modulation mode from MIMO
+  */
+-static int rs_move_mimo_to_other(struct iwl4965_priv *priv,
++static int rs_move_mimo_to_other(struct iwl_priv *priv,
+ 				 struct iwl4965_lq_sta *lq_sta,
+ 				 struct ieee80211_conf *conf,
+ 				 struct sta_info *sta,
+@@ -1390,6 +1525,7 @@ static int rs_move_mimo_to_other(struct iwl4965_priv *priv,
+ 		case IWL_MIMO_SWITCH_ANTENNA_B:
+ 			IWL_DEBUG_HT("LQ: MIMO SWITCH TO SISO\n");
+ 
++
+ 			/* Set up new search table for SISO */
+ 			memcpy(search_tbl, tbl, sz);
+ 			search_tbl->lq_type = LQ_SISO;
+@@ -1546,7 +1682,7 @@ static void rs_stay_in_table(struct iwl4965_lq_sta *lq_sta)
+ /*
+  * Do rate scaling and search for new modulation mode.
+  */
+-static void rs_rate_scale_perform(struct iwl4965_priv *priv,
++static void rs_rate_scale_perform(struct iwl_priv *priv,
+ 				  struct net_device *dev,
+ 				  struct ieee80211_hdr *hdr,
+ 				  struct sta_info *sta)
+@@ -1574,6 +1710,10 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ 	u8 active_tbl = 0;
+ 	u8 done_search = 0;
+ 	u16 high_low;
++#ifdef CONFIG_IWL4965_HT
++	u8 tid = MAX_TID_COUNT;
++	__le16 *qc;
++#endif
+ 
+ 	IWL_DEBUG_RATE("rate scale calculate new rate for skb\n");
+ 
+@@ -1594,6 +1734,13 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ 	}
+ 	lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
+ 
++#ifdef CONFIG_IWL4965_HT
++	qc = ieee80211_get_qos_ctrl(hdr);
++	if (qc) {
++		tid = (u8)(le16_to_cpu(*qc) & 0xf);
++		rs_tl_add_packet(lq_sta, tid);
++	}
++#endif
+ 	/*
+ 	 * Select rate-scale / modulation-mode table to work with in
+ 	 * the rest of this function:  "search" if searching for better
+@@ -1608,7 +1755,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ 	is_green = lq_sta->is_green;
+ 
+ 	/* current tx rate */
+-	index = sta->last_txrate;
++	index = sta->last_txrate_idx;
+ 
+ 	IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index,
+ 		       tbl->lq_type);
+@@ -1621,7 +1768,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ 
+ 	/* mask with station rate restriction */
+ 	if (is_legacy(tbl->lq_type)) {
+-		if (lq_sta->phymode == (u8) MODE_IEEE80211A)
++		if (lq_sta->band == IEEE80211_BAND_5GHZ)
+ 			/* supp_rates has no CCK bits in A mode */
+ 			rate_scale_index_msk = (u16) (rate_mask &
+ 				(lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
+@@ -1685,7 +1832,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ 		if (update_lq) {
+ 			rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green);
+ 			rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
+-			rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
++			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+ 		}
+ 		goto out;
+ 
+@@ -1727,7 +1874,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ 			tbl = &(lq_sta->lq_info[active_tbl]);
+ 
+ 			/* Revert to "active" rate and throughput info */
+-			index = iwl4965_rate_index_from_plcp(
++			index = iwl4965_hwrate_to_plcp_idx(
+ 				tbl->current_rate.rate_n_flags);
+ 			current_tpt = lq_sta->last_tpt;
+ 
+@@ -1850,7 +1997,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ 	if (update_lq) {
+ 		rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green);
+ 		rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
+-		rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
++		iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+ 	}
+ 
+ 	/* Should we stay with this modulation mode, or search for a new one? */
+@@ -1883,14 +2030,14 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ 				rs_rate_scale_clear_window(&(tbl->win[i]));
+ 
+ 			/* Use new "search" start rate */
+-			index = iwl4965_rate_index_from_plcp(
++			index = iwl4965_hwrate_to_plcp_idx(
+ 					tbl->current_rate.rate_n_flags);
+ 
+ 			IWL_DEBUG_HT("Switch current  mcs: %X index: %d\n",
+ 				     tbl->current_rate.rate_n_flags, index);
+ 			rs_fill_link_cmd(lq_sta, &tbl->current_rate,
+ 					 &lq_sta->lq);
+-			rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
++			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+ 		}
+ 
+ 		/* If the "active" (non-search) mode was legacy,
+@@ -1914,15 +2061,14 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ 		 * mode for a while before next round of mode comparisons. */
+ 		if (lq_sta->enable_counter &&
+ 		    (lq_sta->action_counter >= IWL_ACTION_LIMIT)) {
+-#ifdef CONFIG_IWL4965_HT_AGG
+-			/* If appropriate, set up aggregation! */
+-			if ((lq_sta->last_tpt > TID_AGG_TPT_THREHOLD) &&
+-			    (priv->lq_mngr.agg_ctrl.auto_agg)) {
+-				priv->lq_mngr.agg_ctrl.tid_retry =
+-				    TID_ALL_SPECIFIED;
+-				schedule_work(&priv->agg_work);
++#ifdef CONFIG_IWL4965_HT
++			if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
++			    (lq_sta->tx_agg_tid_en & (1 << tid)) &&
++			    (tid != MAX_TID_COUNT)) {
++				IWL_DEBUG_HT("try to aggregate tid %d\n", tid);
++				rs_tl_turn_on_agg(priv, tid, lq_sta, sta);
+ 			}
+-#endif /*CONFIG_IWL4965_HT_AGG */
++#endif /*CONFIG_IWL4965_HT */
+ 			lq_sta->action_counter = 0;
+ 			rs_set_stay_in_table(0, lq_sta);
+ 		}
+@@ -1942,21 +2088,21 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ out:
+ 	rs_mcs_from_tbl(&tbl->current_rate, tbl, index, is_green);
+ 	i = index;
+-	sta->last_txrate = i;
++	sta->last_txrate_idx = i;
+ 
+-	/* sta->txrate is an index to A mode rates which start
++	/* sta->txrate_idx is an index to A mode rates which start
+ 	 * at IWL_FIRST_OFDM_RATE
+ 	 */
+-	if (lq_sta->phymode == (u8) MODE_IEEE80211A)
+-		sta->txrate = i - IWL_FIRST_OFDM_RATE;
++	if (lq_sta->band == IEEE80211_BAND_5GHZ)
++		sta->txrate_idx = i - IWL_FIRST_OFDM_RATE;
+ 	else
+-		sta->txrate = i;
++		sta->txrate_idx = i;
+ 
+ 	return;
+ }
+ 
+ 
+-static void rs_initialize_lq(struct iwl4965_priv *priv,
++static void rs_initialize_lq(struct iwl_priv *priv,
+ 			     struct ieee80211_conf *conf,
+ 			     struct sta_info *sta)
+ {
+@@ -1972,7 +2118,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
+ 		goto out;
+ 
+ 	lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
+-	i = sta->last_txrate;
++	i = sta->last_txrate_idx;
+ 
+ 	if ((lq_sta->lq.sta_id == 0xff) &&
+ 	    (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
+@@ -1996,7 +2142,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
+ 		mcs_rate.rate_n_flags |= RATE_MCS_CCK_MSK;
+ 
+ 	tbl->antenna_type = ANT_AUX;
+-	rs_get_tbl_info_from_mcs(&mcs_rate, priv->phymode, tbl, &rate_idx);
++	rs_get_tbl_info_from_mcs(&mcs_rate, priv->band, tbl, &rate_idx);
+ 	if (!rs_is_ant_connected(priv->valid_antenna, tbl->antenna_type))
+ 	    rs_toggle_antenna(&mcs_rate, tbl);
+ 
+@@ -2004,13 +2150,14 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
+ 	tbl->current_rate.rate_n_flags = mcs_rate.rate_n_flags;
+ 	rs_get_expected_tpt_table(lq_sta, tbl);
+ 	rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
+-	rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
++	iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+  out:
+ 	return;
+ }
+ 
+ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+-			struct ieee80211_hw_mode *mode, struct sk_buff *skb,
++			struct ieee80211_supported_band *sband,
++			struct sk_buff *skb,
+ 			struct rate_selection *sel)
+ {
+ 
+@@ -2020,11 +2167,13 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ 	struct sta_info *sta;
+ 	u16 fc;
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
++	struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ 	struct iwl4965_lq_sta *lq_sta;
+ 
+ 	IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
+ 
++	rcu_read_lock();
++
+ 	sta = sta_info_get(local, hdr->addr1);
+ 
+ 	/* Send management frames and broadcast/multicast data using lowest
+@@ -2032,14 +2181,12 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 	fc = le16_to_cpu(hdr->frame_control);
+ 	if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
+ 	    !sta || !sta->rate_ctrl_priv) {
+-		sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+-		if (sta)
+-			sta_info_put(sta);
+-		return;
++		sel->rate = rate_lowest(local, sband, sta);
++		goto out;
+ 	}
+ 
+ 	lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
+-	i = sta->last_txrate;
++	i = sta->last_txrate_idx;
+ 
+ 	if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ 	    !lq_sta->ibss_sta_added) {
+@@ -2062,14 +2209,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ 			goto done;
+ 	}
+ 
+- done:
++done:
+ 	if ((i < 0) || (i > IWL_RATE_COUNT)) {
+-		sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+-		return;
++		sel->rate = rate_lowest(local, sband, sta);
++		goto out;
+ 	}
+-	sta_info_put(sta);
+ 
+ 	sel->rate = &priv->ieee_rates[i];
++out:
++	rcu_read_unlock();
+ }
+ 
+ static void *rs_alloc_sta(void *priv, gfp_t gfp)
+@@ -2099,13 +2247,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ {
+ 	int i, j;
+ 	struct ieee80211_conf *conf = &local->hw.conf;
+-	struct ieee80211_hw_mode *mode = local->oper_hw_mode;
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
++	struct ieee80211_supported_band *sband;
++	struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ 	struct iwl4965_lq_sta *lq_sta = priv_sta;
+ 
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
+ 	lq_sta->flush_timer = 0;
+-	lq_sta->supp_rates = sta->supp_rates;
+-	sta->txrate = 3;
++	lq_sta->supp_rates = sta->supp_rates[sband->band];
++	sta->txrate_idx = 3;
+ 	for (j = 0; j < LQ_SIZE; j++)
+ 		for (i = 0; i < IWL_RATE_COUNT; i++)
+ 			rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i]));
+@@ -2140,15 +2290,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ 	}
+ 
+ 	/* Find highest tx rate supported by hardware and destination station */
+-	for (i = 0; i < mode->num_rates; i++) {
+-		if ((sta->supp_rates & BIT(i)) &&
+-		    (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
+-			sta->txrate = i;
+-	}
+-	sta->last_txrate = sta->txrate;
++	for (i = 0; i < sband->n_bitrates; i++)
++		if (sta->supp_rates[sband->band] & BIT(i))
++			sta->txrate_idx = i;
++
++	sta->last_txrate_idx = sta->txrate_idx;
++	/* WTF is with this bogus comment? A doesn't have cck rates */
+ 	/* For MODE_IEEE80211A, cck rates are at end of rate table */
+-	if (local->hw.conf.phymode == MODE_IEEE80211A)
+-		sta->last_txrate += IWL_FIRST_OFDM_RATE;
++	if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
++		sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+ 
+ 	lq_sta->is_dup = 0;
+ 	lq_sta->valid_antenna = priv->valid_antenna;
+@@ -2157,7 +2307,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ 	lq_sta->active_rate = priv->active_rate;
+ 	lq_sta->active_rate &= ~(0x1000);
+ 	lq_sta->active_rate_basic = priv->active_rate_basic;
+-	lq_sta->phymode = priv->phymode;
++	lq_sta->band = priv->band;
+ #ifdef CONFIG_IWL4965_HT
+ 	/*
+ 	 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
+@@ -2180,6 +2330,8 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ 	IWL_DEBUG_HT("SISO RATE 0x%X MIMO RATE 0x%X\n",
+ 		     lq_sta->active_siso_rate,
+ 		     lq_sta->active_mimo_rate);
++	/* as default allow aggregation for all tids */
++	lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
+ #endif /*CONFIG_IWL4965_HT*/
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ 	lq_sta->drv = priv;
+@@ -2193,7 +2345,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ 
+ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ 			    struct iwl4965_rate *tx_mcs,
+-			    struct iwl4965_link_quality_cmd *lq_cmd)
++			    struct iwl_link_quality_cmd *lq_cmd)
+ {
+ 	int index = 0;
+ 	int rate_idx;
+@@ -2207,7 +2359,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ 	rs_dbgfs_set_mcs(lq_sta, tx_mcs, index);
+ 
+ 	/* Interpret rate_n_flags */
+-	rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->phymode,
++	rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->band,
+ 				  &tbl_type, &rate_idx);
+ 
+ 	/* How many times should we repeat the initial rate? */
+@@ -2261,7 +2413,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ 			index++;
+ 		}
+ 
+-		rs_get_tbl_info_from_mcs(&new_rate, lq_sta->phymode, &tbl_type,
++		rs_get_tbl_info_from_mcs(&new_rate, lq_sta->band, &tbl_type,
+ 						&rate_idx);
+ 
+ 		/* Indicate to uCode which entries might be MIMO.
+@@ -2318,17 +2470,11 @@ static void rs_free(void *priv_rate)
+ 
+ static void rs_clear(void *priv_rate)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *) priv_rate;
++	struct iwl_priv *priv = (struct iwl_priv *) priv_rate;
+ 
+ 	IWL_DEBUG_RATE("enter\n");
+ 
+ 	priv->lq_mngr.lq_ready = 0;
+-#ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+-	if (priv->lq_mngr.agg_ctrl.granted_ba)
+-		iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);
+-#endif /*CONFIG_IWL4965_HT_AGG */
+-#endif /* CONFIG_IWL4965_HT */
+ 
+ 	IWL_DEBUG_RATE("leave\n");
+ }
+@@ -2354,7 +2500,7 @@ static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta,
+ {
+ 	u32 base_rate;
+ 
+-	if (lq_sta->phymode == (u8) MODE_IEEE80211A)
++	if (lq_sta->band == IEEE80211_BAND_5GHZ)
+ 		base_rate = 0x800D;
+ 	else
+ 		base_rate = 0x820A;
+@@ -2398,7 +2544,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
+ 
+ 	if (lq_sta->dbg_fixed.rate_n_flags) {
+ 		rs_fill_link_cmd(lq_sta, &lq_sta->dbg_fixed, &lq_sta->lq);
+-		rs_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
++		iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
+ 	}
+ 
+ 	return count;
+@@ -2495,6 +2641,12 @@ static void rs_add_debugfs(void *priv, void *priv_sta,
+ 	lq_sta->rs_sta_dbgfs_stats_table_file =
+ 		debugfs_create_file("rate_stats_table", 0600, dir,
+ 			lq_sta, &rs_sta_dbgfs_stats_table_ops);
++#ifdef CONFIG_IWL4965_HT
++	lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
++		debugfs_create_u8("tx_agg_tid_enable", 0600, dir,
++		&lq_sta->tx_agg_tid_en);
++#endif
++
+ }
+ 
+ static void rs_remove_debugfs(void *priv, void *priv_sta)
+@@ -2502,6 +2654,9 @@ static void rs_remove_debugfs(void *priv, void *priv_sta)
+ 	struct iwl4965_lq_sta *lq_sta = priv_sta;
+ 	debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
+ 	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
++#ifdef CONFIG_IWL4965_HT
++	debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
++#endif
+ }
+ #endif
+ 
+@@ -2525,7 +2680,7 @@ static struct rate_control_ops rs_ops = {
+ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+ {
+ 	struct ieee80211_local *local = hw_to_local(hw);
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	struct iwl4965_lq_sta *lq_sta;
+ 	struct sta_info *sta;
+ 	int cnt = 0, i;
+@@ -2534,13 +2689,15 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+ 	u32 max_time = 0;
+ 	u8 lq_type, antenna;
+ 
++	rcu_read_lock();
++
+ 	sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
+ 	if (!sta || !sta->rate_ctrl_priv) {
+-		if (sta) {
+-			sta_info_put(sta);
++		if (sta)
+ 			IWL_DEBUG_RATE("leave - no private rate data!\n");
+-		} else
++		else
+ 			IWL_DEBUG_RATE("leave - no station!\n");
++		rcu_read_unlock();
+ 		return sprintf(buf, "station %d not found\n", sta_id);
+ 	}
+ 
+@@ -2605,25 +2762,25 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+ 
+ 	cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d "
+ 			 "active_search %d rate index %d\n", lq_type, antenna,
+-			 lq_sta->search_better_tbl, sta->last_txrate);
++			 lq_sta->search_better_tbl, sta->last_txrate_idx);
+ 
+-	sta_info_put(sta);
++	rcu_read_unlock();
+ 	return cnt;
+ }
+ 
+ void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 
+ 	priv->lq_mngr.lq_ready = 1;
+ }
+ 
+-void iwl4965_rate_control_register(struct ieee80211_hw *hw)
++int iwl4965_rate_control_register(void)
+ {
+-	ieee80211_rate_control_register(&rs_ops);
++	return ieee80211_rate_control_register(&rs_ops);
+ }
+ 
+-void iwl4965_rate_control_unregister(struct ieee80211_hw *hw)
++void iwl4965_rate_control_unregister(void)
+ {
+ 	ieee80211_rate_control_unregister(&rs_ops);
+ }
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
+index 55f7073..866e378 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
++++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 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
+@@ -212,6 +212,18 @@ enum {
+ 
+ #define LQ_SIZE		2	/* 2 mode tables:  "Active" and "Search" */
+ 
++/* load per tid defines for A-MPDU activation */
++#define IWL_AGG_TPT_THREHOLD	0
++#define IWL_AGG_LOAD_THRESHOLD	10
++#define IWL_AGG_ALL_TID		0xff
++#define TID_QUEUE_CELL_SPACING	50	/*mS */
++#define TID_QUEUE_MAX_SIZE	20
++#define TID_ROUND_VALUE		5	/* mS */
++#define TID_MAX_LOAD_COUNT	8
++
++#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
++#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
++
+ extern const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT];
+ 
+ enum iwl4965_table_type {
+@@ -247,7 +259,7 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
+ 	return rate;
+ }
+ 
+-extern int iwl4965_rate_index_from_plcp(int plcp);
++extern int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags);
+ 
+ /**
+  * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation
+@@ -276,7 +288,7 @@ extern void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+  * ieee80211_register_hw
+  *
+  */
+-extern void iwl4965_rate_control_register(struct ieee80211_hw *hw);
++extern int iwl4965_rate_control_register(void);
+ 
+ /**
+  * iwl4965_rate_control_unregister - Unregister the rate control callbacks
+@@ -284,6 +296,6 @@ extern void iwl4965_rate_control_register(struct ieee80211_hw *hw);
+  * This should be called after calling ieee80211_unregister_hw, but before
+  * the driver is unloaded.
+  */
+-extern void iwl4965_rate_control_unregister(struct ieee80211_hw *hw);
++extern void iwl4965_rate_control_unregister(void);
+ 
+ #endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
+index 6576757..17f629f 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
++++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 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
+@@ -38,10 +38,21 @@
+ #include <linux/etherdevice.h>
+ #include <asm/unaligned.h>
+ 
++#include "iwl-eeprom.h"
+ #include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-io.h"
+ #include "iwl-helpers.h"
+ 
+-static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv);
++/* module parameters */
++static struct iwl_mod_params iwl4965_mod_params = {
++	.num_of_queues = IWL4965_MAX_NUM_QUEUES,
++	.enable_qos = 1,
++	.amsdu_size_8K = 1,
++	/* the rest are 0 by default */
++};
++
++static void iwl4965_hw_card_show_info(struct iwl_priv *priv);
+ 
+ #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np)    \
+ 	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,      \
+@@ -79,13 +90,277 @@ const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT] = {
+ 	IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
+ };
+ 
++#ifdef CONFIG_IWL4965_HT
++
++static const u16 default_tid_to_tx_fifo[] = {
++	IWL_TX_FIFO_AC1,
++	IWL_TX_FIFO_AC0,
++	IWL_TX_FIFO_AC0,
++	IWL_TX_FIFO_AC1,
++	IWL_TX_FIFO_AC2,
++	IWL_TX_FIFO_AC2,
++	IWL_TX_FIFO_AC3,
++	IWL_TX_FIFO_AC3,
++	IWL_TX_FIFO_NONE,
++	IWL_TX_FIFO_NONE,
++	IWL_TX_FIFO_NONE,
++	IWL_TX_FIFO_NONE,
++	IWL_TX_FIFO_NONE,
++	IWL_TX_FIFO_NONE,
++	IWL_TX_FIFO_NONE,
++	IWL_TX_FIFO_NONE,
++	IWL_TX_FIFO_AC3
++};
++
++#endif	/*CONFIG_IWL4965_HT */
++
++/* check contents of special bootstrap uCode SRAM */
++static int iwl4965_verify_bsm(struct iwl_priv *priv)
++{
++	__le32 *image = priv->ucode_boot.v_addr;
++	u32 len = priv->ucode_boot.len;
++	u32 reg;
++	u32 val;
++
++	IWL_DEBUG_INFO("Begin verify bsm\n");
++
++	/* verify BSM SRAM contents */
++	val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
++	for (reg = BSM_SRAM_LOWER_BOUND;
++	     reg < BSM_SRAM_LOWER_BOUND + len;
++	     reg += sizeof(u32), image++) {
++		val = iwl_read_prph(priv, reg);
++		if (val != le32_to_cpu(*image)) {
++			IWL_ERROR("BSM uCode verification failed at "
++				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
++				  BSM_SRAM_LOWER_BOUND,
++				  reg - BSM_SRAM_LOWER_BOUND, len,
++				  val, le32_to_cpu(*image));
++			return -EIO;
++		}
++	}
++
++	IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
++
++	return 0;
++}
++
++/**
++ * iwl4965_load_bsm - Load bootstrap instructions
++ *
++ * BSM operation:
++ *
++ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
++ * in special SRAM that does not power down during RFKILL.  When powering back
++ * up after power-saving sleeps (or during initial uCode load), the BSM loads
++ * the bootstrap program into the on-board processor, and starts it.
++ *
++ * The bootstrap program loads (via DMA) instructions and data for a new
++ * program from host DRAM locations indicated by the host driver in the
++ * BSM_DRAM_* registers.  Once the new program is loaded, it starts
++ * automatically.
++ *
++ * When initializing the NIC, the host driver points the BSM to the
++ * "initialize" uCode image.  This uCode sets up some internal data, then
++ * notifies host via "initialize alive" that it is complete.
++ *
++ * The host then replaces the BSM_DRAM_* pointer values to point to the
++ * normal runtime uCode instructions and a backup uCode data cache buffer
++ * (filled initially with starting data values for the on-board processor),
++ * then triggers the "initialize" uCode to load and launch the runtime uCode,
++ * which begins normal operation.
++ *
++ * When doing a power-save shutdown, runtime uCode saves data SRAM into
++ * the backup data cache in DRAM before SRAM is powered down.
++ *
++ * When powering back up, the BSM loads the bootstrap program.  This reloads
++ * the runtime uCode instructions and the backup data cache into SRAM,
++ * and re-launches the runtime uCode from where it left off.
++ */
++static int iwl4965_load_bsm(struct iwl_priv *priv)
++{
++	__le32 *image = priv->ucode_boot.v_addr;
++	u32 len = priv->ucode_boot.len;
++	dma_addr_t pinst;
++	dma_addr_t pdata;
++	u32 inst_len;
++	u32 data_len;
++	int i;
++	u32 done;
++	u32 reg_offset;
++	int ret;
++
++	IWL_DEBUG_INFO("Begin load bsm\n");
++
++	/* make sure bootstrap program is no larger than BSM's SRAM size */
++	if (len > IWL_MAX_BSM_SIZE)
++		return -EINVAL;
++
++	/* Tell bootstrap uCode where to find the "Initialize" uCode
++	 *   in host DRAM ... host DRAM physical address bits 35:4 for 4965.
++	 * NOTE:  iwl4965_initialize_alive_start() will replace these values,
++	 *        after the "initialize" uCode has run, to point to
++	 *        runtime/protocol instructions and backup data cache. */
++	pinst = priv->ucode_init.p_addr >> 4;
++	pdata = priv->ucode_init_data.p_addr >> 4;
++	inst_len = priv->ucode_init.len;
++	data_len = priv->ucode_init_data.len;
++
++	ret = iwl_grab_nic_access(priv);
++	if (ret)
++		return ret;
++
++	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
++	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
++	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
++	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
++
++	/* Fill BSM memory with bootstrap instructions */
++	for (reg_offset = BSM_SRAM_LOWER_BOUND;
++	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
++	     reg_offset += sizeof(u32), image++)
++		_iwl_write_prph(priv, reg_offset, le32_to_cpu(*image));
++
++	ret = iwl4965_verify_bsm(priv);
++	if (ret) {
++		iwl_release_nic_access(priv);
++		return ret;
++	}
++
++	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
++	iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
++	iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND);
++	iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
++
++	/* Load bootstrap code into instruction SRAM now,
++	 *   to prepare to load "initialize" uCode */
++	iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
++
++	/* Wait for load of bootstrap uCode to finish */
++	for (i = 0; i < 100; i++) {
++		done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
++		if (!(done & BSM_WR_CTRL_REG_BIT_START))
++			break;
++		udelay(10);
++	}
++	if (i < 100)
++		IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
++	else {
++		IWL_ERROR("BSM write did not complete!\n");
++		return -EIO;
++	}
++
++	/* Enable future boot loads whenever power management unit triggers it
++	 *   (e.g. when powering back up after power-save shutdown) */
++	iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
++
++	iwl_release_nic_access(priv);
++
++	return 0;
++}
++
++static int iwl4965_init_drv(struct iwl_priv *priv)
++{
++	int ret;
++	int i;
++
++	priv->antenna = (enum iwl4965_antenna)priv->cfg->mod_params->antenna;
++	priv->retry_rate = 1;
++	priv->ibss_beacon = NULL;
++
++	spin_lock_init(&priv->lock);
++	spin_lock_init(&priv->power_data.lock);
++	spin_lock_init(&priv->sta_lock);
++	spin_lock_init(&priv->hcmd_lock);
++	spin_lock_init(&priv->lq_mngr.lock);
++
++	priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
++					sizeof(struct iwl4965_shared),
++					&priv->shared_phys);
++
++	if (!priv->shared_virt) {
++		ret = -ENOMEM;
++		goto err;
++	}
++
++	memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared));
++
++
++	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
++		INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
++
++	INIT_LIST_HEAD(&priv->free_frames);
++
++	mutex_init(&priv->mutex);
++
++	/* Clear the driver's (not device's) station table */
++	iwlcore_clear_stations_table(priv);
++
++	priv->data_retry_limit = -1;
++	priv->ieee_channels = NULL;
++	priv->ieee_rates = NULL;
++	priv->band = IEEE80211_BAND_2GHZ;
++
++	priv->iw_mode = IEEE80211_IF_TYPE_STA;
++
++	priv->use_ant_b_for_management_frame = 1; /* start with ant B */
++	priv->valid_antenna = 0x7;	/* assume all 3 connected */
++	priv->ps_mode = IWL_MIMO_PS_NONE;
++
++	/* Choose which receivers/antennas to use */
++	iwl4965_set_rxon_chain(priv);
++
++	iwlcore_reset_qos(priv);
++
++	priv->qos_data.qos_active = 0;
++	priv->qos_data.qos_cap.val = 0;
++
++	iwlcore_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
++
++	priv->rates_mask = IWL_RATES_MASK;
++	/* If power management is turned on, default to AC mode */
++	priv->power_mode = IWL_POWER_AC;
++	priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
++
++	ret = iwl_init_channel_map(priv);
++	if (ret) {
++		IWL_ERROR("initializing regulatory failed: %d\n", ret);
++		goto err;
++	}
++
++	ret = iwl4965_init_geos(priv);
++	if (ret) {
++		IWL_ERROR("initializing geos failed: %d\n", ret);
++		goto err_free_channel_map;
++	}
++
++	ret = ieee80211_register_hw(priv->hw);
++	if (ret) {
++		IWL_ERROR("Failed to register network device (error %d)\n",
++				ret);
++		goto err_free_geos;
++	}
++
++	priv->hw->conf.beacon_int = 100;
++	priv->mac80211_registered = 1;
++
++	return 0;
++
++err_free_geos:
++	iwl4965_free_geos(priv);
++err_free_channel_map:
++	iwl_free_channel_map(priv);
++err:
++	return ret;
++}
++
+ static int is_fat_channel(__le32 rxon_flags)
+ {
+ 	return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) ||
+ 		(rxon_flags & RXON_FLG_CHANNEL_MODE_MIXED_MSK);
+ }
+ 
+-static u8 is_single_stream(struct iwl4965_priv *priv)
++static u8 is_single_stream(struct iwl_priv *priv)
+ {
+ #ifdef CONFIG_IWL4965_HT
+ 	if (!priv->current_ht_config.is_ht ||
+@@ -98,13 +373,71 @@ static u8 is_single_stream(struct iwl4965_priv *priv)
+ 	return 0;
+ }
+ 
++int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags)
++{
++	int idx = 0;
++
++	/* 4965 HT rate format */
++	if (rate_n_flags & RATE_MCS_HT_MSK) {
++		idx = (rate_n_flags & 0xff);
++
++		if (idx >= IWL_RATE_MIMO_6M_PLCP)
++			idx = idx - IWL_RATE_MIMO_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;
++
++	/* 4965 legacy rate format, search for match in table */
++	} else {
++		for (idx = 0; idx < ARRAY_SIZE(iwl4965_rates); idx++)
++			if (iwl4965_rates[idx].plcp == (rate_n_flags & 0xFF))
++				return idx;
++	}
++
++	return -1;
++}
++
++/**
++ * translate ucode response to mac80211 tx status control values
++ */
++void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
++				  struct ieee80211_tx_control *control)
++{
++	int rate_index;
++
++	control->antenna_sel_tx =
++		((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS);
++	if (rate_n_flags & RATE_MCS_HT_MSK)
++		control->flags |= IEEE80211_TXCTL_OFDM_HT;
++	if (rate_n_flags & RATE_MCS_GF_MSK)
++		control->flags |= IEEE80211_TXCTL_GREEN_FIELD;
++	if (rate_n_flags & RATE_MCS_FAT_MSK)
++		control->flags |= IEEE80211_TXCTL_40_MHZ_WIDTH;
++	if (rate_n_flags & RATE_MCS_DUP_MSK)
++		control->flags |= IEEE80211_TXCTL_DUP_DATA;
++	if (rate_n_flags & RATE_MCS_SGI_MSK)
++		control->flags |= IEEE80211_TXCTL_SHORT_GI;
++	/* since iwl4965_hwrate_to_plcp_idx is band indifferent, we always use
++	 * IEEE80211_BAND_2GHZ band as it contains all the rates */
++	rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags);
++	if (rate_index == -1)
++		control->tx_rate = NULL;
++	else
++		control->tx_rate =
++			&priv->bands[IEEE80211_BAND_2GHZ].bitrates[rate_index];
++}
++
+ /*
+  * Determine how many receiver/antenna chains to use.
+  * More provides better reception via diversity.  Fewer saves power.
+  * MIMO (dual stream) requires at least 2, but works better with 3.
+  * This does not determine *which* chains to use, just how many.
+  */
+-static int iwl4965_get_rx_chain_counter(struct iwl4965_priv *priv,
++static int iwl4965_get_rx_chain_counter(struct iwl_priv *priv,
+ 					u8 *idle_state, u8 *rx_state)
+ {
+ 	u8 is_single = is_single_stream(priv);
+@@ -133,32 +466,32 @@ static int iwl4965_get_rx_chain_counter(struct iwl4965_priv *priv,
+ 	return 0;
+ }
+ 
+-int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv)
++int iwl4965_hw_rxq_stop(struct iwl_priv *priv)
+ {
+ 	int rc;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		return rc;
+ 	}
+ 
+ 	/* stop Rx DMA */
+-	iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+-	rc = iwl4965_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
++	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
++	rc = iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
+ 				     (1 << 24), 1000);
+ 	if (rc < 0)
+ 		IWL_ERROR("Can't stop Rx DMA.\n");
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	return 0;
+ }
+ 
+-u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr)
++u8 iwl4965_hw_find_station(struct iwl_priv *priv, const u8 *addr)
+ {
+ 	int i;
+ 	int start = 0;
+@@ -171,10 +504,10 @@ u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr)
+ 		start = IWL_STA_ID;
+ 
+ 	if (is_broadcast_ether_addr(addr))
+-		return IWL4965_BROADCAST_ID;
++		return priv->hw_params.bcast_sta_id;
+ 
+ 	spin_lock_irqsave(&priv->sta_lock, flags);
+-	for (i = start; i < priv->hw_setting.max_stations; i++)
++	for (i = start; i < priv->hw_params.max_stations; i++)
+ 		if ((priv->stations[i].used) &&
+ 		    (!compare_ether_addr
+ 		     (priv->stations[i].sta.sta.addr, addr))) {
+@@ -190,13 +523,13 @@ u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr)
+ 	return ret;
+ }
+ 
+-static int iwl4965_nic_set_pwr_src(struct iwl4965_priv *priv, int pwr_max)
++static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
+ {
+ 	int ret;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	ret = iwl4965_grab_nic_access(priv);
++	ret = iwl_grab_nic_access(priv);
+ 	if (ret) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		return ret;
+@@ -209,92 +542,92 @@ static int iwl4965_nic_set_pwr_src(struct iwl4965_priv *priv, int pwr_max)
+ 					   &val);
+ 
+ 		if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT)
+-			iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
++			iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+ 				APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+ 				~APMG_PS_CTRL_MSK_PWR_SRC);
+ 	} else
+-		iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
++		iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+ 			APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+ 			~APMG_PS_CTRL_MSK_PWR_SRC);
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	return ret;
+ }
+ 
+-static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
++static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
+ {
+-	int rc;
++	int ret;
+ 	unsigned long flags;
+ 	unsigned int rb_size;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	rc = iwl4965_grab_nic_access(priv);
+-	if (rc) {
++	ret = iwl_grab_nic_access(priv);
++	if (ret) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+-		return rc;
++		return ret;
+ 	}
+ 
+-	if (iwl4965_param_amsdu_size_8K)
++	if (priv->cfg->mod_params->amsdu_size_8K)
+ 		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+ 	else
+ 		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+ 
+ 	/* Stop Rx DMA */
+-	iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
++	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+ 
+ 	/* Reset driver's Rx queue write index */
+-	iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
++	iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+ 
+ 	/* Tell device where to find RBD circular buffer in DRAM */
+-	iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+-			     rxq->dma_addr >> 8);
++	iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
++			   rxq->dma_addr >> 8);
+ 
+ 	/* Tell device where in DRAM to update its Rx status */
+-	iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
+-			     (priv->hw_setting.shared_phys +
+-			      offsetof(struct iwl4965_shared, val0)) >> 4);
++	iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
++			   (priv->shared_phys +
++			    offsetof(struct iwl4965_shared, rb_closed)) >> 4);
+ 
+ 	/* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
+-	iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
+-			     FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+-			     FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+-			     rb_size |
+-			     /*0x10 << 4 | */
+-			     (RX_QUEUE_SIZE_LOG <<
++	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
++			   FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
++			   FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
++			   rb_size |
++			     /* 0x10 << 4 | */
++			   (RX_QUEUE_SIZE_LOG <<
+ 			      FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
+ 
+ 	/*
+-	 * iwl4965_write32(priv,CSR_INT_COAL_REG,0);
++	 * iwl_write32(priv,CSR_INT_COAL_REG,0);
+ 	 */
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	return 0;
+ }
+ 
+ /* Tell 4965 where to find the "keep warm" buffer */
+-static int iwl4965_kw_init(struct iwl4965_priv *priv)
++static int iwl4965_kw_init(struct iwl_priv *priv)
+ {
+ 	unsigned long flags;
+ 	int rc;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc)
+ 		goto out;
+ 
+-	iwl4965_write_direct32(priv, IWL_FH_KW_MEM_ADDR_REG,
++	iwl_write_direct32(priv, IWL_FH_KW_MEM_ADDR_REG,
+ 			     priv->kw.dma_addr >> 4);
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ out:
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 	return rc;
+ }
+ 
+-static int iwl4965_kw_alloc(struct iwl4965_priv *priv)
++static int iwl4965_kw_alloc(struct iwl_priv *priv)
+ {
+ 	struct pci_dev *dev = priv->pci_dev;
+ 	struct iwl4965_kw *kw = &priv->kw;
+@@ -307,58 +640,10 @@ static int iwl4965_kw_alloc(struct iwl4965_priv *priv)
+ 	return 0;
+ }
+ 
+-#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
+-			    ? # x " " : "")
+-
+-/**
+- * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv.
+- *
+- * Does not set up a command, or touch hardware.
+- */
+-int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, u16 channel,
+-			      const struct iwl4965_eeprom_channel *eeprom_ch,
+-			      u8 fat_extension_channel)
+-{
+-	struct iwl4965_channel_info *ch_info;
+-
+-	ch_info = (struct iwl4965_channel_info *)
+-			iwl4965_get_channel_info(priv, phymode, channel);
+-
+-	if (!is_channel_valid(ch_info))
+-		return -1;
+-
+-	IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
+-			" %ddBm): Ad-Hoc %ssupported\n",
+-			ch_info->channel,
+-			is_channel_a_band(ch_info) ?
+-			"5.2" : "2.4",
+-			CHECK_AND_PRINT(IBSS),
+-			CHECK_AND_PRINT(ACTIVE),
+-			CHECK_AND_PRINT(RADAR),
+-			CHECK_AND_PRINT(WIDE),
+-			CHECK_AND_PRINT(NARROW),
+-			CHECK_AND_PRINT(DFS),
+-			eeprom_ch->flags,
+-			eeprom_ch->max_power_avg,
+-			((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
+-			 && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
+-			"" : "not ");
+-
+-	ch_info->fat_eeprom = *eeprom_ch;
+-	ch_info->fat_max_power_avg = eeprom_ch->max_power_avg;
+-	ch_info->fat_curr_txpow = eeprom_ch->max_power_avg;
+-	ch_info->fat_min_power = 0;
+-	ch_info->fat_scan_power = eeprom_ch->max_power_avg;
+-	ch_info->fat_flags = eeprom_ch->flags;
+-	ch_info->fat_extension_channel = fat_extension_channel;
+-
+-	return 0;
+-}
+-
+ /**
+  * iwl4965_kw_free - Free the "keep warm" buffer
+  */
+-static void iwl4965_kw_free(struct iwl4965_priv *priv)
++static void iwl4965_kw_free(struct iwl_priv *priv)
+ {
+ 	struct pci_dev *dev = priv->pci_dev;
+ 	struct iwl4965_kw *kw = &priv->kw;
+@@ -376,7 +661,7 @@ static void iwl4965_kw_free(struct iwl4965_priv *priv)
+  * @param priv
+  * @return error code
+  */
+-static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
++static int iwl4965_txq_ctx_reset(struct iwl_priv *priv)
+ {
+ 	int rc = 0;
+ 	int txq_id, slots_num;
+@@ -396,7 +681,7 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (unlikely(rc)) {
+ 		IWL_ERROR("TX reset failed");
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+@@ -404,8 +689,8 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
+ 	}
+ 
+ 	/* Turn off all Tx DMA channels */
+-	iwl4965_write_prph(priv, KDR_SCD_TXFACT, 0);
+-	iwl4965_release_nic_access(priv);
++	iwl_write_prph(priv, IWL49_SCD_TXFACT, 0);
++	iwl_release_nic_access(priv);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	/* Tell 4965 where to find the keep-warm buffer */
+@@ -417,7 +702,7 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
+ 
+ 	/* Alloc and init all (default 16) Tx queues,
+ 	 * including the command queue (#4) */
+-	for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) {
++	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+ 		slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
+ 					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+ 		rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
+@@ -438,7 +723,7 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
+ 	return rc;
+ }
+ 
+-int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
++int iwl4965_hw_nic_init(struct iwl_priv *priv)
+ {
+ 	int rc;
+ 	unsigned long flags;
+@@ -452,11 +737,11 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
+ 	/* nic_init */
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+-	iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS,
++	iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ 		    CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+ 
+-	iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+-	rc = iwl4965_poll_bit(priv, CSR_GP_CNTRL,
++	iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
++	rc = iwl_poll_bit(priv, CSR_GP_CNTRL,
+ 			  CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ 			  CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ 	if (rc < 0) {
+@@ -465,26 +750,25 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
+ 		return rc;
+ 	}
+ 
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		return rc;
+ 	}
+ 
+-	iwl4965_read_prph(priv, APMG_CLK_CTRL_REG);
++	iwl_read_prph(priv, APMG_CLK_CTRL_REG);
+ 
+-	iwl4965_write_prph(priv, APMG_CLK_CTRL_REG,
+-				 APMG_CLK_VAL_DMA_CLK_RQT |
+-				 APMG_CLK_VAL_BSM_CLK_RQT);
+-	iwl4965_read_prph(priv, APMG_CLK_CTRL_REG);
++	iwl_write_prph(priv, APMG_CLK_CTRL_REG,
++			APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
++	iwl_read_prph(priv, APMG_CLK_CTRL_REG);
+ 
+ 	udelay(20);
+ 
+-	iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+-				    APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
++	iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
++				APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+ 
+-	iwl4965_release_nic_access(priv);
+-	iwl4965_write32(priv, CSR_INT_COALESCING, 512 / 32);
++	iwl_release_nic_access(priv);
++	iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	/* Determine HW type */
+@@ -520,25 +804,24 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
+ 
+ 	/* set CSR_HW_CONFIG_REG for uCode use */
+ 
+-	iwl4965_set_bit(priv, CSR_SW_VER, CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R |
+-		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+-		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
++	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
++		    CSR49_HW_IF_CONFIG_REG_BIT_4965_R |
++		    CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI |
++		    CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI);
+ 
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc < 0) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		IWL_DEBUG_INFO("Failed to init the card\n");
+ 		return rc;
+ 	}
+ 
+-	iwl4965_read_prph(priv, APMG_PS_CTRL_REG);
+-	iwl4965_set_bits_prph(priv, APMG_PS_CTRL_REG,
+-				    APMG_PS_CTRL_VAL_RESET_REQ);
++	iwl_read_prph(priv, APMG_PS_CTRL_REG);
++	iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
+ 	udelay(5);
+-	iwl4965_clear_bits_prph(priv, APMG_PS_CTRL_REG,
+-				      APMG_PS_CTRL_VAL_RESET_REQ);
++	iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	iwl4965_hw_card_show_info(priv);
+@@ -582,7 +865,7 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
+ 	return 0;
+ }
+ 
+-int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv)
++int iwl4965_hw_nic_stop_master(struct iwl_priv *priv)
+ {
+ 	int rc = 0;
+ 	u32 reg_val;
+@@ -591,16 +874,16 @@ int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv)
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+ 	/* set stop master bit */
+-	iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
++	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+ 
+-	reg_val = iwl4965_read32(priv, CSR_GP_CNTRL);
++	reg_val = iwl_read32(priv, CSR_GP_CNTRL);
+ 
+ 	if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE ==
+ 	    (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE))
+ 		IWL_DEBUG_INFO("Card in power save, master is already "
+ 			       "stopped\n");
+ 	else {
+-		rc = iwl4965_poll_bit(priv, CSR_RESET,
++		rc = iwl_poll_bit(priv, CSR_RESET,
+ 				  CSR_RESET_REG_FLAG_MASTER_DISABLED,
+ 				  CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
+ 		if (rc < 0) {
+@@ -618,27 +901,26 @@ int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv)
+ /**
+  * iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
+  */
+-void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv)
++void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
+ {
+ 
+ 	int txq_id;
+ 	unsigned long flags;
+ 
+ 	/* Stop each Tx DMA channel, and wait for it to be idle */
+-	for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) {
++	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+ 		spin_lock_irqsave(&priv->lock, flags);
+-		if (iwl4965_grab_nic_access(priv)) {
++		if (iwl_grab_nic_access(priv)) {
+ 			spin_unlock_irqrestore(&priv->lock, flags);
+ 			continue;
+ 		}
+ 
+-		iwl4965_write_direct32(priv,
+-				     IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
+-				     0x0);
+-		iwl4965_poll_direct_bit(priv, IWL_FH_TSSR_TX_STATUS_REG,
+-					IWL_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
+-					(txq_id), 200);
+-		iwl4965_release_nic_access(priv);
++		iwl_write_direct32(priv,
++				   IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0);
++		iwl_poll_direct_bit(priv, IWL_FH_TSSR_TX_STATUS_REG,
++				    IWL_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
++				    (txq_id), 200);
++		iwl_release_nic_access(priv);
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 	}
+ 
+@@ -646,7 +928,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv)
+ 	iwl4965_hw_txq_ctx_free(priv);
+ }
+ 
+-int iwl4965_hw_nic_reset(struct iwl4965_priv *priv)
++int iwl4965_hw_nic_reset(struct iwl_priv *priv)
+ {
+ 	int rc = 0;
+ 	unsigned long flags;
+@@ -655,29 +937,29 @@ int iwl4965_hw_nic_reset(struct iwl4965_priv *priv)
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+-	iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
++	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ 
+ 	udelay(10);
+ 
+-	iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+-	rc = iwl4965_poll_bit(priv, CSR_RESET,
++	iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
++	rc = iwl_poll_bit(priv, CSR_RESET,
+ 			  CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ 			  CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);
+ 
+ 	udelay(10);
+ 
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (!rc) {
+-		iwl4965_write_prph(priv, APMG_CLK_EN_REG,
+-					 APMG_CLK_VAL_DMA_CLK_RQT |
+-					 APMG_CLK_VAL_BSM_CLK_RQT);
++		iwl_write_prph(priv, APMG_CLK_EN_REG,
++				APMG_CLK_VAL_DMA_CLK_RQT |
++				APMG_CLK_VAL_BSM_CLK_RQT);
+ 
+ 		udelay(10);
+ 
+-		iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+-				APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
++		iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
++					APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+ 
+-		iwl4965_release_nic_access(priv);
++		iwl_release_nic_access(priv);
+ 	}
+ 
+ 	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+@@ -694,56 +976,37 @@ int iwl4965_hw_nic_reset(struct iwl4965_priv *priv)
+ /**
+  * iwl4965_bg_statistics_periodic - Timer callback to queue statistics
+  *
+- * This callback is provided in order to queue the statistics_work
+- * in work_queue context (v. softirq)
++ * This callback is provided in order to send a statistics request.
+  *
+  * This timer function is continually reset to execute within
+  * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
+  * was received.  We need to ensure we receive the statistics in order
+- * to update the temperature used for calibrating the TXPOWER.  However,
+- * we can't send the statistics command from softirq context (which
+- * is the context which timers run at) so we have to queue off the
+- * statistics_work to actually send the command to the hardware.
++ * to update the temperature used for calibrating the TXPOWER.
+  */
+ static void iwl4965_bg_statistics_periodic(unsigned long data)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)data;
+-
+-	queue_work(priv->workqueue, &priv->statistics_work);
+-}
+-
+-/**
+- * iwl4965_bg_statistics_work - Send the statistics request to the hardware.
+- *
+- * This is queued by iwl4965_bg_statistics_periodic.
+- */
+-static void iwl4965_bg_statistics_work(struct work_struct *work)
+-{
+-	struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
+-					     statistics_work);
++	struct iwl_priv *priv = (struct iwl_priv *)data;
+ 
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 		return;
+ 
+-	mutex_lock(&priv->mutex);
+-	iwl4965_send_statistics_request(priv);
+-	mutex_unlock(&priv->mutex);
++	iwl_send_statistics_request(priv, CMD_ASYNC);
+ }
+ 
+ #define CT_LIMIT_CONST		259
+ #define TM_CT_KILL_THRESHOLD	110
+ 
+-void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv)
++void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_ct_kill_config cmd;
+ 	u32 R1, R2, R3;
+ 	u32 temp_th;
+ 	u32 crit_temperature;
+ 	unsigned long flags;
+-	int rc = 0;
++	int ret = 0;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ 		    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+@@ -761,9 +1024,9 @@ void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv)
+ 
+ 	crit_temperature = ((temp_th * (R3-R1))/CT_LIMIT_CONST) + R2;
+ 	cmd.critical_temperature_R =  cpu_to_le32(crit_temperature);
+-	rc = iwl4965_send_cmd_pdu(priv,
+-			      REPLY_CT_KILL_CONFIG_CMD, sizeof(cmd), &cmd);
+-	if (rc)
++	ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
++			       sizeof(cmd), &cmd);
++	if (ret)
+ 		IWL_ERROR("REPLY_CT_KILL_CONFIG_CMD failed\n");
+ 	else
+ 		IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded\n");
+@@ -779,7 +1042,7 @@ void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv)
+  *   enough to receive all of our own network traffic, but not so
+  *   high that our DSP gets too busy trying to lock onto non-network
+  *   activity/noise. */
+-static int iwl4965_sens_energy_cck(struct iwl4965_priv *priv,
++static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
+ 				   u32 norm_fa,
+ 				   u32 rx_enable_time,
+ 				   struct statistics_general_data *rx_info)
+@@ -970,7 +1233,7 @@ static int iwl4965_sens_energy_cck(struct iwl4965_priv *priv,
+ }
+ 
+ 
+-static int iwl4965_sens_auto_corr_ofdm(struct iwl4965_priv *priv,
++static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv,
+ 				       u32 norm_fa,
+ 				       u32 rx_enable_time)
+ {
+@@ -1035,25 +1298,25 @@ static int iwl4965_sens_auto_corr_ofdm(struct iwl4965_priv *priv,
+ 	return 0;
+ }
+ 
+-static int iwl4965_sensitivity_callback(struct iwl4965_priv *priv,
+-				    struct iwl4965_cmd *cmd, struct sk_buff *skb)
++static int iwl4965_sensitivity_callback(struct iwl_priv *priv,
++				    struct iwl_cmd *cmd, struct sk_buff *skb)
+ {
+ 	/* We didn't cache the SKB; let the caller free it */
+ 	return 1;
+ }
+ 
+ /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
+-static int iwl4965_sensitivity_write(struct iwl4965_priv *priv, u8 flags)
++static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags)
+ {
+-	int rc = 0;
+ 	struct iwl4965_sensitivity_cmd cmd ;
+ 	struct iwl4965_sensitivity_data *data = NULL;
+-	struct iwl4965_host_cmd cmd_out = {
++	struct iwl_host_cmd cmd_out = {
+ 		.id = SENSITIVITY_CMD,
+ 		.len = sizeof(struct iwl4965_sensitivity_cmd),
+ 		.meta.flags = flags,
+ 		.data = &cmd,
+ 	};
++	int ret;
+ 
+ 	data = &(priv->sensitivity_data);
+ 
+@@ -1111,20 +1374,18 @@ static int iwl4965_sensitivity_write(struct iwl4965_priv *priv, u8 flags)
+ 	memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
+ 	       sizeof(u16)*HD_TABLE_SIZE);
+ 
+-	rc = iwl4965_send_cmd(priv, &cmd_out);
+-	if (!rc) {
+-		IWL_DEBUG_CALIB("SENSITIVITY_CMD succeeded\n");
+-		return rc;
+-	}
++	ret = iwl_send_cmd(priv, &cmd_out);
++	if (ret)
++		IWL_ERROR("SENSITIVITY_CMD failed\n");
+ 
+-	return 0;
++	return ret;
+ }
+ 
+-void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force)
++void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force)
+ {
+-	int rc = 0;
+-	int i;
+ 	struct iwl4965_sensitivity_data *data = NULL;
++	int i;
++	int ret  = 0;
+ 
+ 	IWL_DEBUG_CALIB("Start iwl4965_init_sensitivity\n");
+ 
+@@ -1168,8 +1429,8 @@ void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force)
+ 		memset(&(priv->sensitivity_tbl[0]), 0,
+ 		    sizeof(u16)*HD_TABLE_SIZE);
+ 
+-	rc |= iwl4965_sensitivity_write(priv, flags);
+-	IWL_DEBUG_CALIB("<<return 0x%X\n", rc);
++	ret |= iwl4965_sensitivity_write(priv, flags);
++	IWL_DEBUG_CALIB("<<return 0x%X\n", ret);
+ 
+ 	return;
+ }
+@@ -1178,13 +1439,12 @@ void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force)
+ /* Reset differential Rx gains in NIC to prepare for chain noise calibration.
+  * Called after every association, but this runs only once!
+  *  ... once chain noise is calibrated the first time, it's good forever.  */
+-void iwl4965_chain_noise_reset(struct iwl4965_priv *priv)
++void iwl4965_chain_noise_reset(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_chain_noise_data *data = NULL;
+-	int rc = 0;
+ 
+ 	data = &(priv->chain_noise_data);
+-	if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl4965_is_associated(priv)) {
++	if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
+ 		struct iwl4965_calibration_cmd cmd;
+ 
+ 		memset(&cmd, 0, sizeof(cmd));
+@@ -1192,8 +1452,8 @@ void iwl4965_chain_noise_reset(struct iwl4965_priv *priv)
+ 		cmd.diff_gain_a = 0;
+ 		cmd.diff_gain_b = 0;
+ 		cmd.diff_gain_c = 0;
+-		rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+-				 sizeof(cmd), &cmd);
++		iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
++				 sizeof(cmd), &cmd, NULL);
+ 		msleep(4);
+ 		data->state = IWL_CHAIN_NOISE_ACCUMULATE;
+ 		IWL_DEBUG_CALIB("Run chain_noise_calibrate\n");
+@@ -1207,11 +1467,11 @@ void iwl4965_chain_noise_reset(struct iwl4965_priv *priv)
+  * 1)  Which antennas are connected.
+  * 2)  Differential rx gain settings to balance the 3 receivers.
+  */
+-static void iwl4965_noise_calibration(struct iwl4965_priv *priv,
++static void iwl4965_noise_calibration(struct iwl_priv *priv,
+ 				      struct iwl4965_notif_statistics *stat_resp)
+ {
+ 	struct iwl4965_chain_noise_data *data = NULL;
+-	int rc = 0;
++	int ret = 0;
+ 
+ 	u32 chain_noise_a;
+ 	u32 chain_noise_b;
+@@ -1417,9 +1677,9 @@ static void iwl4965_noise_calibration(struct iwl4965_priv *priv,
+ 			cmd.diff_gain_a = data->delta_gain_code[0];
+ 			cmd.diff_gain_b = data->delta_gain_code[1];
+ 			cmd.diff_gain_c = data->delta_gain_code[2];
+-			rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
++			ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ 					      sizeof(cmd), &cmd);
+-			if (rc)
++			if (ret)
+ 				IWL_DEBUG_CALIB("fail sending cmd "
+ 					     "REPLY_PHY_CALIBRATION_CMD \n");
+ 
+@@ -1440,10 +1700,9 @@ static void iwl4965_noise_calibration(struct iwl4965_priv *priv,
+ 	return;
+ }
+ 
+-static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv,
++static void iwl4965_sensitivity_calibration(struct iwl_priv *priv,
+ 					    struct iwl4965_notif_statistics *resp)
+ {
+-	int rc = 0;
+ 	u32 rx_enable_time;
+ 	u32 fa_cck;
+ 	u32 fa_ofdm;
+@@ -1456,10 +1715,11 @@ static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv,
+ 	struct statistics_rx *statistics = &(resp->rx);
+ 	unsigned long flags;
+ 	struct statistics_general_data statis;
++	int ret;
+ 
+ 	data = &(priv->sensitivity_data);
+ 
+-	if (!iwl4965_is_associated(priv)) {
++	if (!iwl_is_associated(priv)) {
+ 		IWL_DEBUG_CALIB("<< - not associated\n");
+ 		return;
+ 	}
+@@ -1540,14 +1800,14 @@ static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv,
+ 
+ 	iwl4965_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
+ 	iwl4965_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
+-	rc |= iwl4965_sensitivity_write(priv, CMD_ASYNC);
++	ret = iwl4965_sensitivity_write(priv, CMD_ASYNC);
+ 
+ 	return;
+ }
+ 
+ static void iwl4965_bg_sensitivity_work(struct work_struct *work)
+ {
+-	struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
++	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+ 			sensitivity_work);
+ 
+ 	mutex_lock(&priv->mutex);
+@@ -1577,7 +1837,7 @@ static void iwl4965_bg_sensitivity_work(struct work_struct *work)
+ 
+ static void iwl4965_bg_txpower_work(struct work_struct *work)
+ {
+-	struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
++	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+ 			txpower_work);
+ 
+ 	/* If a scan happened to start before we got here
+@@ -1605,11 +1865,11 @@ static void iwl4965_bg_txpower_work(struct work_struct *work)
+ /*
+  * Acquire priv->lock before calling this function !
+  */
+-static void iwl4965_set_wr_ptrs(struct iwl4965_priv *priv, int txq_id, u32 index)
++static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
+ {
+-	iwl4965_write_direct32(priv, HBUS_TARG_WRPTR,
++	iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+ 			     (index & 0xff) | (txq_id << 8));
+-	iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(txq_id), index);
++	iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index);
+ }
+ 
+ /**
+@@ -1619,7 +1879,7 @@ static void iwl4965_set_wr_ptrs(struct iwl4965_priv *priv, int txq_id, u32 index
+  *
+  * NOTE:  Acquire priv->lock before calling this function !
+  */
+-static void iwl4965_tx_queue_set_status(struct iwl4965_priv *priv,
++static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
+ 					struct iwl4965_tx_queue *txq,
+ 					int tx_fifo_id, int scd_retry)
+ {
+@@ -1629,7 +1889,7 @@ static void iwl4965_tx_queue_set_status(struct iwl4965_priv *priv,
+ 	int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
+ 
+ 	/* Set up and activate */
+-	iwl4965_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id),
++	iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
+ 				 (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+ 				 (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) |
+ 				 (scd_retry << SCD_QUEUE_STTS_REG_POS_WSL) |
+@@ -1653,22 +1913,22 @@ static const u16 default_queue_to_tx_fifo[] = {
+ 	IWL_TX_FIFO_HCCA_2
+ };
+ 
+-static inline void iwl4965_txq_ctx_activate(struct iwl4965_priv *priv, int txq_id)
++static inline void iwl4965_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
+ {
+ 	set_bit(txq_id, &priv->txq_ctx_active_msk);
+ }
+ 
+-static inline void iwl4965_txq_ctx_deactivate(struct iwl4965_priv *priv, int txq_id)
++static inline void iwl4965_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
+ {
+ 	clear_bit(txq_id, &priv->txq_ctx_active_msk);
+ }
+ 
+-int iwl4965_alive_notify(struct iwl4965_priv *priv)
++int iwl4965_alive_notify(struct iwl_priv *priv)
+ {
+ 	u32 a;
+ 	int i = 0;
+ 	unsigned long flags;
+-	int rc;
++	int ret;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+@@ -1681,46 +1941,46 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv)
+ 		priv->chain_noise_data.delta_gain_code[i] =
+ 				CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
+ #endif /* CONFIG_IWL4965_SENSITIVITY*/
+-	rc = iwl4965_grab_nic_access(priv);
+-	if (rc) {
++	ret = iwl_grab_nic_access(priv);
++	if (ret) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+-		return rc;
++		return ret;
+ 	}
+ 
+ 	/* Clear 4965's internal Tx Scheduler data base */
+-	priv->scd_base_addr = iwl4965_read_prph(priv, KDR_SCD_SRAM_BASE_ADDR);
++	priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR);
+ 	a = priv->scd_base_addr + SCD_CONTEXT_DATA_OFFSET;
+ 	for (; a < priv->scd_base_addr + SCD_TX_STTS_BITMAP_OFFSET; a += 4)
+-		iwl4965_write_targ_mem(priv, a, 0);
++		iwl_write_targ_mem(priv, a, 0);
+ 	for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4)
+-		iwl4965_write_targ_mem(priv, a, 0);
+-	for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4)
+-		iwl4965_write_targ_mem(priv, a, 0);
++		iwl_write_targ_mem(priv, a, 0);
++	for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4)
++		iwl_write_targ_mem(priv, a, 0);
+ 
+ 	/* Tel 4965 where to find Tx byte count tables */
+-	iwl4965_write_prph(priv, KDR_SCD_DRAM_BASE_ADDR,
+-		(priv->hw_setting.shared_phys +
++	iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
++		(priv->shared_phys +
+ 		 offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10);
+ 
+ 	/* Disable chain mode for all queues */
+-	iwl4965_write_prph(priv, KDR_SCD_QUEUECHAIN_SEL, 0);
++	iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
+ 
+ 	/* Initialize each Tx queue (including the command queue) */
+-	for (i = 0; i < priv->hw_setting.max_txq_num; i++) {
++	for (i = 0; i < priv->hw_params.max_txq_num; i++) {
+ 
+ 		/* TFD circular buffer read/write indexes */
+-		iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(i), 0);
+-		iwl4965_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
++		iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0);
++		iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
+ 
+ 		/* Max Tx Window size for Scheduler-ACK mode */
+-		iwl4965_write_targ_mem(priv, priv->scd_base_addr +
++		iwl_write_targ_mem(priv, priv->scd_base_addr +
+ 					SCD_CONTEXT_QUEUE_OFFSET(i),
+ 					(SCD_WIN_SIZE <<
+ 					SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
+ 					SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+ 
+ 		/* Frame limit */
+-		iwl4965_write_targ_mem(priv, priv->scd_base_addr +
++		iwl_write_targ_mem(priv, priv->scd_base_addr +
+ 					SCD_CONTEXT_QUEUE_OFFSET(i) +
+ 					sizeof(u32),
+ 					(SCD_FRAME_LIMIT <<
+@@ -1728,11 +1988,11 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv)
+ 					SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+ 
+ 	}
+-	iwl4965_write_prph(priv, KDR_SCD_INTERRUPT_MASK,
+-				 (1 << priv->hw_setting.max_txq_num) - 1);
++	iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK,
++				 (1 << priv->hw_params.max_txq_num) - 1);
+ 
+ 	/* Activate all Tx DMA/FIFO channels */
+-	iwl4965_write_prph(priv, KDR_SCD_TXFACT,
++	iwl_write_prph(priv, IWL49_SCD_TXFACT,
+ 				 SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
+ 
+ 	iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+@@ -1744,42 +2004,47 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv)
+ 		iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
+ 	}
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	return 0;
++	/* Ask for statistics now, the uCode will send statistics notification
++	 * periodically after association */
++	iwl_send_statistics_request(priv, CMD_ASYNC);
++	return ret;
+ }
+ 
+ /**
+- * iwl4965_hw_set_hw_setting
++ * iwl4965_hw_set_hw_params
+  *
+  * Called when initializing driver
+  */
+-int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv)
++int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
+ {
+-	/* Allocate area for Tx byte count tables and Rx queue status */
+-	priv->hw_setting.shared_virt =
+-	    pci_alloc_consistent(priv->pci_dev,
+-				 sizeof(struct iwl4965_shared),
+-				 &priv->hw_setting.shared_phys);
+-
+-	if (!priv->hw_setting.shared_virt)
+-		return -1;
+ 
+-	memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared));
++	if ((priv->cfg->mod_params->num_of_queues > IWL4965_MAX_NUM_QUEUES) ||
++	    (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
++		IWL_ERROR("invalid queues_num, should be between %d and %d\n",
++			  IWL_MIN_NUM_QUEUES, IWL4965_MAX_NUM_QUEUES);
++		return -EINVAL;
++	}
+ 
+-	priv->hw_setting.max_txq_num = iwl4965_param_queues_num;
+-	priv->hw_setting.ac_queue_count = AC_NUM;
+-	priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
+-	priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;
+-	priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
+-	if (iwl4965_param_amsdu_size_8K)
+-		priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K;
++	priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
++	priv->hw_params.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
++	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_buf_size = IWL_RX_BUF_SIZE_8K;
+ 	else
+-		priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K;
+-	priv->hw_setting.max_pkt_size = priv->hw_setting.rx_buf_size - 256;
+-	priv->hw_setting.max_stations = IWL4965_STATION_COUNT;
+-	priv->hw_setting.bcast_sta_id = IWL4965_BROADCAST_ID;
++		priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
++	priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
++	priv->hw_params.max_stations = IWL4965_STATION_COUNT;
++	priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
++
++	priv->hw_params.tx_chains_num = 2;
++	priv->hw_params.rx_chains_num = 2;
++	priv->hw_params.valid_tx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX);
++	priv->hw_params.valid_rx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX);
++
+ 	return 0;
+ }
+ 
+@@ -1788,12 +2053,12 @@ int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv)
+  *
+  * Destroy all TX DMA queues and structures
+  */
+-void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv)
++void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv)
+ {
+ 	int txq_id;
+ 
+ 	/* Tx queues */
+-	for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++)
++	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+ 		iwl4965_tx_queue_free(priv, &priv->txq[txq_id]);
+ 
+ 	/* Keep-warm buffer */
+@@ -1806,7 +2071,7 @@ void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv)
+  * Does NOT advance any TFD circular buffer read/write indexes
+  * Does NOT free the TFD itself (which is within circular buffer)
+  */
+-int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
++int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
+ {
+ 	struct iwl4965_tfd_frame *bd_tmp = (struct iwl4965_tfd_frame *)&txq->bd[0];
+ 	struct iwl4965_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
+@@ -1859,7 +2124,7 @@ int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *
+ 	return 0;
+ }
+ 
+-int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power)
++int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
+ {
+ 	IWL_ERROR("TODO: Implement iwl4965_hw_reg_set_txpower!\n");
+ 	return -EINVAL;
+@@ -1914,12 +2179,13 @@ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
+ 	return comp;
+ }
+ 
+-static const struct iwl4965_channel_info *
+-iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, u8 phymode, u16 channel)
++static const struct iwl_channel_info *
++iwl4965_get_channel_txpower_info(struct iwl_priv *priv,
++				 enum ieee80211_band band, u16 channel)
+ {
+-	const struct iwl4965_channel_info *ch_info;
++	const struct iwl_channel_info *ch_info;
+ 
+-	ch_info = iwl4965_get_channel_info(priv, phymode, channel);
++	ch_info = iwl_get_channel_info(priv, band, channel);
+ 
+ 	if (!is_channel_valid(ch_info))
+ 		return NULL;
+@@ -1953,7 +2219,7 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel)
+ 	return -1;
+ }
+ 
+-static u32 iwl4965_get_sub_band(const struct iwl4965_priv *priv, u32 channel)
++static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
+ {
+ 	s32 b = -1;
+ 
+@@ -1989,7 +2255,7 @@ static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
+  * differences in channel frequencies, which is proportional to differences
+  * in channel number.
+  */
+-static int iwl4965_interpolate_chan(struct iwl4965_priv *priv, u32 channel,
++static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
+ 				    struct iwl4965_eeprom_calib_ch_info *chan_info)
+ {
+ 	s32 s = -1;
+@@ -2322,7 +2588,7 @@ static const struct gain_entry gain_table[2][108] = {
+ 	 }
+ };
+ 
+-static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 channel,
++static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
+ 				    u8 is_fat, u8 ctrl_chan_high,
+ 				    struct iwl4965_tx_power_db *tx_power_tbl)
+ {
+@@ -2336,7 +2602,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 chan
+ 	s32 txatten_grp = CALIB_CH_GROUP_MAX;
+ 	int i;
+ 	int c;
+-	const struct iwl4965_channel_info *ch_info = NULL;
++	const struct iwl_channel_info *ch_info = NULL;
+ 	struct iwl4965_eeprom_calib_ch_info ch_eeprom_info;
+ 	const struct iwl4965_eeprom_calib_measure *measurement;
+ 	s16 voltage;
+@@ -2368,7 +2634,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 chan
+ 
+ 	/* Get current (RXON) channel, band, width */
+ 	ch_info =
+-		iwl4965_get_channel_txpower_info(priv, priv->phymode, channel);
++		iwl4965_get_channel_txpower_info(priv, priv->band, channel);
+ 
+ 	IWL_DEBUG_TXPOWER("chan %d band %d is_fat %d\n", channel, band,
+ 			  is_fat);
+@@ -2579,10 +2845,10 @@ static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 chan
+  * Uses the active RXON for channel, band, and characteristics (fat, high)
+  * The power limit is taken from priv->user_txpower_limit.
+  */
+-int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv)
++int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_txpowertable_cmd cmd = { 0 };
+-	int rc = 0;
++	int ret;
+ 	u8 band = 0;
+ 	u8 is_fat = 0;
+ 	u8 ctrl_chan_high = 0;
+@@ -2595,8 +2861,7 @@ int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv)
+ 		return -EAGAIN;
+ 	}
+ 
+-	band = ((priv->phymode == MODE_IEEE80211B) ||
+-		(priv->phymode == MODE_IEEE80211G));
++	band = priv->band == IEEE80211_BAND_2GHZ;
+ 
+ 	is_fat =  is_fat_channel(priv->active_rxon.flags);
+ 
+@@ -2607,29 +2872,70 @@ int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv)
+ 	cmd.band = band;
+ 	cmd.channel = priv->active_rxon.channel;
+ 
+-	rc = iwl4965_fill_txpower_tbl(priv, band,
++	ret = iwl4965_fill_txpower_tbl(priv, band,
+ 				le16_to_cpu(priv->active_rxon.channel),
+ 				is_fat, ctrl_chan_high, &cmd.tx_power);
+-	if (rc)
+-		return rc;
++	if (ret)
++		goto out;
+ 
+-	rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
+-	return rc;
++	ret = iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
++
++out:
++	return ret;
+ }
+ 
+-int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel)
++static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
++{
++	int ret = 0;
++	struct iwl4965_rxon_assoc_cmd rxon_assoc;
++	const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon;
++	const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon;
++
++	if ((rxon1->flags == rxon2->flags) &&
++	    (rxon1->filter_flags == rxon2->filter_flags) &&
++	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
++	    (rxon1->ofdm_ht_single_stream_basic_rates ==
++	     rxon2->ofdm_ht_single_stream_basic_rates) &&
++	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
++	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
++	    (rxon1->rx_chain == rxon2->rx_chain) &&
++	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
++		IWL_DEBUG_INFO("Using current RXON_ASSOC.  Not resending.\n");
++		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.reserved = 0;
++	rxon_assoc.ofdm_ht_single_stream_basic_rates =
++	    priv->staging_rxon.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;
++
++	ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
++				     sizeof(rxon_assoc), &rxon_assoc, NULL);
++	if (ret)
++		return ret;
++
++	return ret;
++}
++
++
++int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
+ {
+ 	int rc;
+ 	u8 band = 0;
+ 	u8 is_fat = 0;
+ 	u8 ctrl_chan_high = 0;
+ 	struct iwl4965_channel_switch_cmd cmd = { 0 };
+-	const struct iwl4965_channel_info *ch_info;
++	const struct iwl_channel_info *ch_info;
+ 
+-	band = ((priv->phymode == MODE_IEEE80211B) ||
+-		(priv->phymode == MODE_IEEE80211G));
++	band = priv->band == IEEE80211_BAND_2GHZ;
+ 
+-	ch_info = iwl4965_get_channel_info(priv, priv->phymode, channel);
++	ch_info = iwl_get_channel_info(priv, priv->band, channel);
+ 
+ 	is_fat = is_fat_channel(priv->staging_rxon.flags);
+ 
+@@ -2655,15 +2961,15 @@ int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel)
+ 		return rc;
+ 	}
+ 
+-	rc = iwl4965_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
++	rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
+ 	return rc;
+ }
+ 
+ #define RTS_HCCA_RETRY_LIMIT		3
+ #define RTS_DFAULT_RETRY_LIMIT		60
+ 
+-void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+-			      struct iwl4965_cmd *cmd,
++void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
++			      struct iwl_cmd *cmd,
+ 			      struct ieee80211_tx_control *ctrl,
+ 			      struct ieee80211_hdr *hdr, int sta_id,
+ 			      int is_hcca)
+@@ -2674,7 +2980,7 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+ 	u16 fc = le16_to_cpu(hdr->frame_control);
+ 	u8 rate_plcp;
+ 	u16 rate_flags = 0;
+-	int rate_idx = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
++	int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
+ 
+ 	rate_plcp = iwl4965_rates[rate_idx].plcp;
+ 
+@@ -2729,19 +3035,18 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+ 	tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
+ }
+ 
+-int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv)
++int iwl4965_hw_get_rx_read(struct iwl_priv *priv)
+ {
+-	struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
+-
+-	return IWL_GET_BITS(*shared_data, rb_closed_stts_rb_num);
++	struct iwl4965_shared *s = priv->shared_virt;
++	return le32_to_cpu(s->rb_closed) & 0xFFF;
+ }
+ 
+-int iwl4965_hw_get_temperature(struct iwl4965_priv *priv)
++int iwl4965_hw_get_temperature(struct iwl_priv *priv)
+ {
+ 	return priv->temperature;
+ }
+ 
+-unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
++unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+ 			  struct iwl4965_frame *frame, u8 rate)
+ {
+ 	struct iwl4965_tx_beacon_cmd *tx_beacon_cmd;
+@@ -2750,7 +3055,7 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
+ 	tx_beacon_cmd = &frame->u.beacon;
+ 	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+ 
+-	tx_beacon_cmd->tx.sta_id = IWL4965_BROADCAST_ID;
++	tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
+ 	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+ 
+ 	frame_size = iwl4965_fill_beacon_frame(priv,
+@@ -2780,35 +3085,35 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
+  * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+  * channels supported in hardware.
+  */
+-int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
++int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
+ {
+ 	int rc;
+ 	unsigned long flags;
+ 	int txq_id = txq->q.id;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		return rc;
+ 	}
+ 
+ 	/* Circular buffer (TFD queue in DRAM) physical base address */
+-	iwl4965_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
++	iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
+ 			     txq->q.dma_addr >> 8);
+ 
+ 	/* Enable DMA channel, using same id as for TFD queue */
+-	iwl4965_write_direct32(
++	iwl_write_direct32(
+ 		priv, IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
+ 		IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ 		IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	return 0;
+ }
+ 
+-int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *ptr,
++int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
+ 				 dma_addr_t addr, u16 len)
+ {
+ 	int index, is_odd;
+@@ -2842,7 +3147,7 @@ int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *ptr,
+ 	return 0;
+ }
+ 
+-static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv)
++static void iwl4965_hw_card_show_info(struct iwl_priv *priv)
+ {
+ 	u16 hw_version = priv->eeprom.board_revision_4965;
+ 
+@@ -2858,17 +3163,15 @@ static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv)
+ #define IWL_TX_DELIMITER_SIZE	4
+ 
+ /**
+- * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array
++ * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+  */
+-int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
+-				   struct iwl4965_tx_queue *txq, u16 byte_cnt)
++static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
++					    struct iwl4965_tx_queue *txq,
++					    u16 byte_cnt)
+ {
+ 	int len;
+ 	int txq_id = txq->q.id;
+-	struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
+-
+-	if (txq->need_update == 0)
+-		return 0;
++	struct iwl4965_shared *shared_data = priv->shared_virt;
+ 
+ 	len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+ 
+@@ -2881,8 +3184,6 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
+ 		IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
+ 			tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr],
+ 			byte_cnt, len);
+-
+-	return 0;
+ }
+ 
+ /**
+@@ -2891,7 +3192,7 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
+  * Selects how many and which Rx receivers/antennas/chains to use.
+  * This should not be used for scan command ... it puts data in wrong place.
+  */
+-void iwl4965_set_rxon_chain(struct iwl4965_priv *priv)
++void iwl4965_set_rxon_chain(struct iwl_priv *priv)
+ {
+ 	u8 is_single = is_single_stream(priv);
+ 	u8 idle_state, rx_state;
+@@ -2922,378 +3223,6 @@ void iwl4965_set_rxon_chain(struct iwl4965_priv *priv)
+ 	IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain);
+ }
+ 
+-#ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+-/*
+-	get the traffic load value for tid
+-*/
+-static u32 iwl4965_tl_get_load(struct iwl4965_priv *priv, u8 tid)
+-{
+-	u32 load = 0;
+-	u32 current_time = jiffies_to_msecs(jiffies);
+-	u32 time_diff;
+-	s32 index;
+-	unsigned long flags;
+-	struct iwl4965_traffic_load *tid_ptr = NULL;
+-
+-	if (tid >= TID_MAX_LOAD_COUNT)
+-		return 0;
+-
+-	tid_ptr = &(priv->lq_mngr.agg_ctrl.traffic_load[tid]);
+-
+-	current_time -= current_time % TID_ROUND_VALUE;
+-
+-	spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-	if (!(tid_ptr->queue_count))
+-		goto out;
+-
+-	time_diff = TIME_WRAP_AROUND(tid_ptr->time_stamp, current_time);
+-	index = time_diff / TID_QUEUE_CELL_SPACING;
+-
+-	if (index >= TID_QUEUE_MAX_SIZE) {
+-		u32 oldest_time = current_time - TID_MAX_TIME_DIFF;
+-
+-		while (tid_ptr->queue_count &&
+-		       (tid_ptr->time_stamp < oldest_time)) {
+-			tid_ptr->total -= tid_ptr->packet_count[tid_ptr->head];
+-			tid_ptr->packet_count[tid_ptr->head] = 0;
+-			tid_ptr->time_stamp += TID_QUEUE_CELL_SPACING;
+-			tid_ptr->queue_count--;
+-			tid_ptr->head++;
+-			if (tid_ptr->head >= TID_QUEUE_MAX_SIZE)
+-				tid_ptr->head = 0;
+-		}
+-	}
+-	load = tid_ptr->total;
+-
+- out:
+-	spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-	return load;
+-}
+-
+-/*
+-	increment traffic load value for tid and also remove
+-	any old values if passed the certian time period
+-*/
+-static void iwl4965_tl_add_packet(struct iwl4965_priv *priv, u8 tid)
+-{
+-	u32 current_time = jiffies_to_msecs(jiffies);
+-	u32 time_diff;
+-	s32 index;
+-	unsigned long flags;
+-	struct iwl4965_traffic_load *tid_ptr = NULL;
+-
+-	if (tid >= TID_MAX_LOAD_COUNT)
+-		return;
+-
+-	tid_ptr = &(priv->lq_mngr.agg_ctrl.traffic_load[tid]);
+-
+-	current_time -= current_time % TID_ROUND_VALUE;
+-
+-	spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-	if (!(tid_ptr->queue_count)) {
+-		tid_ptr->total = 1;
+-		tid_ptr->time_stamp = current_time;
+-		tid_ptr->queue_count = 1;
+-		tid_ptr->head = 0;
+-		tid_ptr->packet_count[0] = 1;
+-		goto out;
+-	}
+-
+-	time_diff = TIME_WRAP_AROUND(tid_ptr->time_stamp, current_time);
+-	index = time_diff / TID_QUEUE_CELL_SPACING;
+-
+-	if (index >= TID_QUEUE_MAX_SIZE) {
+-		u32 oldest_time = current_time - TID_MAX_TIME_DIFF;
+-
+-		while (tid_ptr->queue_count &&
+-		       (tid_ptr->time_stamp < oldest_time)) {
+-			tid_ptr->total -= tid_ptr->packet_count[tid_ptr->head];
+-			tid_ptr->packet_count[tid_ptr->head] = 0;
+-			tid_ptr->time_stamp += TID_QUEUE_CELL_SPACING;
+-			tid_ptr->queue_count--;
+-			tid_ptr->head++;
+-			if (tid_ptr->head >= TID_QUEUE_MAX_SIZE)
+-				tid_ptr->head = 0;
+-		}
+-	}
+-
+-	index = (tid_ptr->head + index) % TID_QUEUE_MAX_SIZE;
+-	tid_ptr->packet_count[index] = tid_ptr->packet_count[index] + 1;
+-	tid_ptr->total = tid_ptr->total + 1;
+-
+-	if ((index + 1) > tid_ptr->queue_count)
+-		tid_ptr->queue_count = index + 1;
+- out:
+-	spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-
+-}
+-
+-#define MMAC_SCHED_MAX_NUMBER_OF_HT_BACK_FLOWS   7
+-enum HT_STATUS {
+-	BA_STATUS_FAILURE = 0,
+-	BA_STATUS_INITIATOR_DELBA,
+-	BA_STATUS_RECIPIENT_DELBA,
+-	BA_STATUS_RENEW_ADDBA_REQUEST,
+-	BA_STATUS_ACTIVE,
+-};
+-
+-/**
+- * iwl4964_tl_ba_avail - Find out if an unused aggregation queue is available
+- */
+-static u8 iwl4964_tl_ba_avail(struct iwl4965_priv *priv)
+-{
+-	int i;
+-	struct iwl4965_lq_mngr *lq;
+-	u8 count = 0;
+-	u16 msk;
+-
+-	lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+-	/* Find out how many agg queues are in use */
+-	for (i = 0; i < TID_MAX_LOAD_COUNT ; i++) {
+-		msk = 1 << i;
+-		if ((lq->agg_ctrl.granted_ba & msk) ||
+-		    (lq->agg_ctrl.wait_for_agg_status & msk))
+-			count++;
+-	}
+-
+-	if (count < MMAC_SCHED_MAX_NUMBER_OF_HT_BACK_FLOWS)
+-		return 1;
+-
+-	return 0;
+-}
+-
+-static void iwl4965_ba_status(struct iwl4965_priv *priv,
+-			      u8 tid, enum HT_STATUS status);
+-
+-static int iwl4965_perform_addba(struct iwl4965_priv *priv, u8 tid, u32 length,
+-				 u32 ba_timeout)
+-{
+-	int rc;
+-
+-	rc = ieee80211_start_BA_session(priv->hw, priv->bssid, tid);
+-	if (rc)
+-		iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE);
+-
+-	return rc;
+-}
+-
+-static int iwl4965_perform_delba(struct iwl4965_priv *priv, u8 tid)
+-{
+-	int rc;
+-
+-	rc = ieee80211_stop_BA_session(priv->hw, priv->bssid, tid);
+-	if (rc)
+-		iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE);
+-
+-	return rc;
+-}
+-
+-static void iwl4965_turn_on_agg_for_tid(struct iwl4965_priv *priv,
+-					struct iwl4965_lq_mngr *lq,
+-					u8 auto_agg, u8 tid)
+-{
+-	u32 tid_msk = (1 << tid);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-/*
+-	if ((auto_agg) && (!lq->enable_counter)){
+-		lq->agg_ctrl.next_retry = 0;
+-		lq->agg_ctrl.tid_retry = 0;
+-		spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-		return;
+-	}
+-*/
+-	if (!(lq->agg_ctrl.granted_ba & tid_msk) &&
+-	    (lq->agg_ctrl.requested_ba & tid_msk)) {
+-		u8 available_queues;
+-		u32 load;
+-
+-		spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-		available_queues = iwl4964_tl_ba_avail(priv);
+-		load = iwl4965_tl_get_load(priv, tid);
+-
+-		spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-		if (!available_queues) {
+-			if (auto_agg)
+-				lq->agg_ctrl.tid_retry |= tid_msk;
+-			else {
+-				lq->agg_ctrl.requested_ba &= ~tid_msk;
+-				lq->agg_ctrl.wait_for_agg_status &= ~tid_msk;
+-			}
+-		} else if ((auto_agg) &&
+-			   ((load <= lq->agg_ctrl.tid_traffic_load_threshold) ||
+-			    ((lq->agg_ctrl.wait_for_agg_status & tid_msk))))
+-			lq->agg_ctrl.tid_retry |= tid_msk;
+-		else {
+-			lq->agg_ctrl.wait_for_agg_status |= tid_msk;
+-			spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-			iwl4965_perform_addba(priv, tid, 0x40,
+-					      lq->agg_ctrl.ba_timeout);
+-			spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-		}
+-	}
+-	spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-}
+-
+-static void iwl4965_turn_on_agg(struct iwl4965_priv *priv, u8 tid)
+-{
+-	struct iwl4965_lq_mngr *lq;
+-	unsigned long flags;
+-
+-	lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+-	if ((tid < TID_MAX_LOAD_COUNT))
+-		iwl4965_turn_on_agg_for_tid(priv, lq, lq->agg_ctrl.auto_agg,
+-					    tid);
+-	else if (tid == TID_ALL_SPECIFIED) {
+-		if (lq->agg_ctrl.requested_ba) {
+-			for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
+-				iwl4965_turn_on_agg_for_tid(priv, lq,
+-					lq->agg_ctrl.auto_agg, tid);
+-		} else {
+-			spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-			lq->agg_ctrl.tid_retry = 0;
+-			lq->agg_ctrl.next_retry = 0;
+-			spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-		}
+-	}
+-
+-}
+-
+-void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid)
+-{
+-	u32 tid_msk;
+-	struct iwl4965_lq_mngr *lq;
+-	unsigned long flags;
+-
+-	lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+-	if ((tid < TID_MAX_LOAD_COUNT)) {
+-		tid_msk = 1 << tid;
+-		spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-		lq->agg_ctrl.wait_for_agg_status |= tid_msk;
+-		lq->agg_ctrl.requested_ba &= ~tid_msk;
+-		spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-		iwl4965_perform_delba(priv, tid);
+-	} else if (tid == TID_ALL_SPECIFIED) {
+-		spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-		for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) {
+-			tid_msk = 1 << tid;
+-			lq->agg_ctrl.wait_for_agg_status |= tid_msk;
+-			spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-			iwl4965_perform_delba(priv, tid);
+-			spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-		}
+-		lq->agg_ctrl.requested_ba = 0;
+-		spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-	}
+-}
+-
+-/**
+- * iwl4965_ba_status - Update driver's link quality mgr with tid's HT status
+- */
+-static void iwl4965_ba_status(struct iwl4965_priv *priv,
+-				u8 tid, enum HT_STATUS status)
+-{
+-	struct iwl4965_lq_mngr *lq;
+-	u32 tid_msk = (1 << tid);
+-	unsigned long flags;
+-
+-	lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+-	if ((tid >= TID_MAX_LOAD_COUNT))
+-		goto out;
+-
+-	spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-	switch (status) {
+-	case BA_STATUS_ACTIVE:
+-		if (!(lq->agg_ctrl.granted_ba & tid_msk))
+-			lq->agg_ctrl.granted_ba |= tid_msk;
+-		break;
+-	default:
+-		if ((lq->agg_ctrl.granted_ba & tid_msk))
+-			lq->agg_ctrl.granted_ba &= ~tid_msk;
+-		break;
+-	}
+-
+-	lq->agg_ctrl.wait_for_agg_status &= ~tid_msk;
+-	if (status != BA_STATUS_ACTIVE) {
+-		if (lq->agg_ctrl.auto_agg) {
+-			lq->agg_ctrl.tid_retry |= tid_msk;
+-			lq->agg_ctrl.next_retry =
+-			    jiffies + msecs_to_jiffies(500);
+-		} else
+-			lq->agg_ctrl.requested_ba &= ~tid_msk;
+-	}
+-	spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- out:
+-	return;
+-}
+-
+-static void iwl4965_bg_agg_work(struct work_struct *work)
+-{
+-	struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
+-					agg_work);
+-
+-	u32 tid;
+-	u32 retry_tid;
+-	u32 tid_msk;
+-	unsigned long flags;
+-	struct iwl4965_lq_mngr *lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+-	spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-	retry_tid = lq->agg_ctrl.tid_retry;
+-	lq->agg_ctrl.tid_retry = 0;
+-	spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-
+-	if (retry_tid == TID_ALL_SPECIFIED)
+-		iwl4965_turn_on_agg(priv, TID_ALL_SPECIFIED);
+-	else {
+-		for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) {
+-			tid_msk = (1 << tid);
+-			if (retry_tid & tid_msk)
+-				iwl4965_turn_on_agg(priv, tid);
+-		}
+-	}
+-
+-	spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-	if (lq->agg_ctrl.tid_retry)
+-		lq->agg_ctrl.next_retry = jiffies + msecs_to_jiffies(500);
+-	spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-	return;
+-}
+-
+-/* TODO: move this functionality to rate scaling */
+-void iwl4965_tl_get_stats(struct iwl4965_priv *priv,
+-		   struct ieee80211_hdr *hdr)
+-{
+-	__le16 *qc = ieee80211_get_qos_ctrl(hdr);
+-
+-	if (qc &&
+-	    (priv->iw_mode != IEEE80211_IF_TYPE_IBSS)) {
+-		u8 tid = 0;
+-		tid = (u8) (le16_to_cpu(*qc) & 0xF);
+-		if (tid < TID_MAX_LOAD_COUNT)
+-			iwl4965_tl_add_packet(priv, tid);
+-	}
+-
+-	if (priv->lq_mngr.agg_ctrl.next_retry &&
+-	    (time_after(priv->lq_mngr.agg_ctrl.next_retry, jiffies))) {
+-		unsigned long flags;
+-
+-		spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-		priv->lq_mngr.agg_ctrl.next_retry = 0;
+-		spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-		schedule_work(&priv->agg_work);
+-	}
+-}
+-
+-#endif /*CONFIG_IWL4965_HT_AGG */
+-#endif /* CONFIG_IWL4965_HT */
+-
+ /**
+  * sign_extend - Sign extend a value using specified bit as sign-bit
+  *
+@@ -3316,7 +3245,7 @@ static s32 sign_extend(u32 oper, int index)
+  *
+  * A return of <0 indicates bogus data in the statistics
+  */
+-int iwl4965_get_temperature(const struct iwl4965_priv *priv)
++int iwl4965_get_temperature(const struct iwl_priv *priv)
+ {
+ 	s32 temperature;
+ 	s32 vt;
+@@ -3384,7 +3313,7 @@ int iwl4965_get_temperature(const struct iwl4965_priv *priv)
+  * Assumes caller will replace priv->last_temperature once calibration
+  * executed.
+  */
+-static int iwl4965_is_temp_calib_needed(struct iwl4965_priv *priv)
++static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
+ {
+ 	int temp_diff;
+ 
+@@ -3417,7 +3346,7 @@ static int iwl4965_is_temp_calib_needed(struct iwl4965_priv *priv)
+ /* Calculate noise level, based on measurements during network silence just
+  *   before arriving beacon.  This measurement can be done only if we know
+  *   exactly when to expect beacons, therefore only when we're associated. */
+-static void iwl4965_rx_calc_noise(struct iwl4965_priv *priv)
++static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
+ {
+ 	struct statistics_rx_non_phy *rx_info
+ 				= &(priv->statistics.rx.general);
+@@ -3454,7 +3383,7 @@ static void iwl4965_rx_calc_noise(struct iwl4965_priv *priv)
+ 			priv->last_rx_noise);
+ }
+ 
+-void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
++void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ 	int change;
+@@ -3488,6 +3417,8 @@ void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_b
+ #endif
+ 	}
+ 
++	iwl_leds_background(priv);
++
+ 	/* If the hardware hasn't reported a change in
+ 	 * temperature then don't bother computing a
+ 	 * calibrated temperature value */
+@@ -3518,7 +3449,7 @@ void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_b
+ 		queue_work(priv->workqueue, &priv->txpower_work);
+ }
+ 
+-static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
++static void iwl4965_add_radiotap(struct iwl_priv *priv,
+ 				 struct sk_buff *skb,
+ 				 struct iwl4965_rx_phy_res *rx_start,
+ 				 struct ieee80211_rx_status *stats,
+@@ -3526,8 +3457,9 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
+ {
+ 	s8 signal = stats->ssi;
+ 	s8 noise = 0;
+-	int rate = stats->rate;
++	int rate = stats->rate_idx;
+ 	u64 tsf = stats->mactime;
++	__le16 antenna;
+ 	__le16 phy_flags_hw = rx_start->phy_flags;
+ 	struct iwl4965_rt_rx_hdr {
+ 		struct ieee80211_radiotap_header rt_hdr;
+@@ -3594,7 +3526,6 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
+ 					  IEEE80211_CHAN_2GHZ),
+ 			      &iwl4965_rt->rt_chbitmask);
+ 
+-	rate = iwl4965_rate_index_from_plcp(rate);
+ 	if (rate == -1)
+ 		iwl4965_rt->rt_rate = 0;
+ 	else
+@@ -3613,8 +3544,8 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
+ 	 * new 802.11n radiotap field "RX chains" that is defined
+ 	 * as a bitmask.
+ 	 */
+-	iwl4965_rt->rt_antenna =
+-		le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
++	antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
++	iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4;
+ 
+ 	/* set the preamble flag if appropriate */
+ 	if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+@@ -3623,7 +3554,74 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
+ 	stats->flag |= RX_FLAG_RADIOTAP;
+ }
+ 
+-static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
++static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len)
++{
++	/* 0 - mgmt, 1 - cnt, 2 - data */
++	int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
++	priv->rx_stats[idx].cnt++;
++	priv->rx_stats[idx].bytes += len;
++}
++
++static u32 iwl4965_translate_rx_status(u32 decrypt_in)
++{
++	u32 decrypt_out = 0;
++
++	if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
++					RX_RES_STATUS_STATION_FOUND)
++		decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
++				RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
++
++	decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
++
++	/* packet was not encrypted */
++	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
++					RX_RES_STATUS_SEC_TYPE_NONE)
++		return decrypt_out;
++
++	/* packet was encrypted with unknown alg */
++	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
++					RX_RES_STATUS_SEC_TYPE_ERR)
++		return decrypt_out;
++
++	/* decryption was not done in HW */
++	if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
++					RX_MPDU_RES_STATUS_DEC_DONE_MSK)
++		return decrypt_out;
++
++	switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
++
++	case RX_RES_STATUS_SEC_TYPE_CCMP:
++		/* alg is CCM: check MIC only */
++		if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
++			/* Bad MIC */
++			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
++		else
++			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
++
++		break;
++
++	case RX_RES_STATUS_SEC_TYPE_TKIP:
++		if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
++			/* Bad TTAK */
++			decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
++			break;
++		}
++		/* fall through if TTAK OK */
++	default:
++		if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
++			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
++		else
++			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
++		break;
++	};
++
++	IWL_DEBUG_RX("decrypt_in:0x%x  decrypt_out = 0x%x\n",
++					decrypt_in, decrypt_out);
++
++	return decrypt_out;
++}
++
++static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
+ 				       int include_phy,
+ 				       struct iwl4965_rx_mem_buffer *rxb,
+ 				       struct ieee80211_rx_status *stats)
+@@ -3636,6 +3634,7 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
+ 	__le32 *rx_end;
+ 	unsigned int skblen;
+ 	u32 ampdu_status;
++	u32 ampdu_status_legacy;
+ 
+ 	if (!include_phy && priv->last_phy_res[0])
+ 		rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
+@@ -3664,7 +3663,7 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
+ 		rx_start->byte_count = amsdu->byte_count;
+ 		rx_end = (__le32 *) (((u8 *) hdr) + len);
+ 	}
+-	if (len > priv->hw_setting.max_pkt_size || len < 16) {
++	if (len > priv->hw_params.max_pkt_size || len < 16) {
+ 		IWL_WARNING("byte count out of range [16,4K] : %d\n", len);
+ 		return;
+ 	}
+@@ -3672,6 +3671,12 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
+ 	ampdu_status = le32_to_cpu(*rx_end);
+ 	skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32);
+ 
++	if (!include_phy) {
++		/* New status scheme, need to translate */
++		ampdu_status_legacy = ampdu_status;
++		ampdu_status = iwl4965_translate_rx_status(ampdu_status);
++	}
++
+ 	/* start from MAC */
+ 	skb_reserve(rxb->skb, (void *)hdr - (void *)pkt);
+ 	skb_put(rxb->skb, len);	/* end where data ends */
+@@ -3686,19 +3691,16 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
+ 	stats->flag = 0;
+ 	hdr = (struct ieee80211_hdr *)rxb->skb->data;
+ 
+-	if (iwl4965_param_hwcrypto)
++	if (!priv->cfg->mod_params->sw_crypto)
+ 		iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats);
+ 
+ 	if (priv->add_radiotap)
+ 		iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status);
+ 
++	iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len);
+ 	ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
+ 	priv->alloc_rxb_skb--;
+ 	rxb->skb = NULL;
+-#ifdef LED
+-	priv->led_packets += len;
+-	iwl4965_setup_activity_timer(priv);
+-#endif
+ }
+ 
+ /* Calc max signal level (dBm) among 3 possible receivers */
+@@ -3737,85 +3739,16 @@ static int iwl4965_calc_rssi(struct iwl4965_rx_phy_res *rx_resp)
+ 
+ #ifdef CONFIG_IWL4965_HT
+ 
+-/* Parsed Information Elements */
+-struct ieee802_11_elems {
+-	u8 *ds_params;
+-	u8 ds_params_len;
+-	u8 *tim;
+-	u8 tim_len;
+-	u8 *ibss_params;
+-	u8 ibss_params_len;
+-	u8 *erp_info;
+-	u8 erp_info_len;
+-	u8 *ht_cap_param;
+-	u8 ht_cap_param_len;
+-	u8 *ht_extra_param;
+-	u8 ht_extra_param_len;
+-};
+-
+-static int parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems)
+-{
+-	size_t left = len;
+-	u8 *pos = start;
+-	int unknown = 0;
+-
+-	memset(elems, 0, sizeof(*elems));
+-
+-	while (left >= 2) {
+-		u8 id, elen;
+-
+-		id = *pos++;
+-		elen = *pos++;
+-		left -= 2;
+-
+-		if (elen > left)
+-			return -1;
+-
+-		switch (id) {
+-		case WLAN_EID_DS_PARAMS:
+-			elems->ds_params = pos;
+-			elems->ds_params_len = elen;
+-			break;
+-		case WLAN_EID_TIM:
+-			elems->tim = pos;
+-			elems->tim_len = elen;
+-			break;
+-		case WLAN_EID_IBSS_PARAMS:
+-			elems->ibss_params = pos;
+-			elems->ibss_params_len = elen;
+-			break;
+-		case WLAN_EID_ERP_INFO:
+-			elems->erp_info = pos;
+-			elems->erp_info_len = elen;
+-			break;
+-		case WLAN_EID_HT_CAPABILITY:
+-			elems->ht_cap_param = pos;
+-			elems->ht_cap_param_len = elen;
+-			break;
+-		case WLAN_EID_HT_EXTRA_INFO:
+-			elems->ht_extra_param = pos;
+-			elems->ht_extra_param_len = elen;
+-			break;
+-		default:
+-			unknown++;
+-			break;
+-		}
+-
+-		left -= elen;
+-		pos += elen;
+-	}
+-
+-	return 0;
+-}
+-
+-void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode)
++void iwl4965_init_ht_hw_capab(struct iwl_priv *priv,
++			      struct ieee80211_ht_info *ht_info,
++			      enum ieee80211_band band)
+ {
+ 	ht_info->cap = 0;
+ 	memset(ht_info->supp_mcs_set, 0, 16);
+ 
+ 	ht_info->ht_supported = 1;
+ 
+-	if (mode == MODE_IEEE80211A) {
++	if (band == IEEE80211_BAND_5GHZ) {
+ 		ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH;
+ 		ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40;
+ 		ht_info->supp_mcs_set[4] = 0x01;
+@@ -3824,10 +3757,9 @@ void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode)
+ 	ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
+ 	ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS &
+ 			     (IWL_MIMO_PS_NONE << 2));
+-	if (iwl4965_param_amsdu_size_8K) {
+-		printk(KERN_DEBUG "iwl4965 in A-MSDU 8K support mode\n");
++
++	if (priv->cfg->mod_params->amsdu_size_8K)
+ 		ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU;
+-	}
+ 
+ 	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
+ 	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
+@@ -3837,7 +3769,7 @@ void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode)
+ }
+ #endif /* CONFIG_IWL4965_HT */
+ 
+-static void iwl4965_sta_modify_ps_wake(struct iwl4965_priv *priv, int sta_id)
++static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
+ {
+ 	unsigned long flags;
+ 
+@@ -3851,7 +3783,7 @@ static void iwl4965_sta_modify_ps_wake(struct iwl4965_priv *priv, int sta_id)
+ 	iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ }
+ 
+-static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *addr)
++static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
+ {
+ 	/* FIXME: need locking over ps_status ??? */
+ 	u8 sta_id = iwl4965_hw_find_station(priv, addr);
+@@ -3868,44 +3800,201 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad
+ 		}
+ 	}
+ }
++#ifdef CONFIG_IWLWIFI_DEBUG
+ 
+-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
++/**
++ * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions
++ *
++ * You may hack this function to show different aspects of received frames,
++ * including selective frame dumps.
++ * group100 parameter selects whether to show 1 out of 100 good frames.
++ *
++ * TODO:  This was originally written for 3945, need to audit for
++ *        proper operation with 4965.
++ */
++static void iwl4965_dbg_report_frame(struct iwl_priv *priv,
++		      struct iwl4965_rx_packet *pkt,
++		      struct ieee80211_hdr *header, int group100)
++{
++	u32 to_us;
++	u32 print_summary = 0;
++	u32 print_dump = 0;	/* set to 1 to dump all frames' contents */
++	u32 hundred = 0;
++	u32 dataframe = 0;
++	u16 fc;
++	u16 seq_ctl;
++	u16 channel;
++	u16 phy_flags;
++	int rate_sym;
++	u16 length;
++	u16 status;
++	u16 bcn_tmr;
++	u32 tsf_low;
++	u64 tsf;
++	u8 rssi;
++	u8 agc;
++	u16 sig_avg;
++	u16 noise_diff;
++	struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
++	struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
++	struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
++	u8 *data = IWL_RX_DATA(pkt);
++
++	if (likely(!(iwl_debug_level & IWL_DL_RX)))
++		return;
+ 
+-/* Called for REPLY_4965_RX (legacy ABG frames), or
++	/* MAC header */
++	fc = le16_to_cpu(header->frame_control);
++	seq_ctl = le16_to_cpu(header->seq_ctrl);
++
++	/* metadata */
++	channel = le16_to_cpu(rx_hdr->channel);
++	phy_flags = le16_to_cpu(rx_hdr->phy_flags);
++	rate_sym = rx_hdr->rate;
++	length = le16_to_cpu(rx_hdr->len);
++
++	/* end-of-frame status and timestamp */
++	status = le32_to_cpu(rx_end->status);
++	bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
++	tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
++	tsf = le64_to_cpu(rx_end->timestamp);
++
++	/* signal statistics */
++	rssi = rx_stats->rssi;
++	agc = rx_stats->agc;
++	sig_avg = le16_to_cpu(rx_stats->sig_avg);
++	noise_diff = le16_to_cpu(rx_stats->noise_diff);
++
++	to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
++
++	/* if data frame is to us and all is good,
++	 *   (optionally) print summary for only 1 out of every 100 */
++	if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
++	    (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
++		dataframe = 1;
++		if (!group100)
++			print_summary = 1;	/* print each frame */
++		else if (priv->framecnt_to_us < 100) {
++			priv->framecnt_to_us++;
++			print_summary = 0;
++		} else {
++			priv->framecnt_to_us = 0;
++			print_summary = 1;
++			hundred = 1;
++		}
++	} else {
++		/* print summary for all other frames */
++		print_summary = 1;
++	}
++
++	if (print_summary) {
++		char *title;
++		int rate_idx;
++		u32 bitrate;
++
++		if (hundred)
++			title = "100Frames";
++		else if (fc & IEEE80211_FCTL_RETRY)
++			title = "Retry";
++		else if (ieee80211_is_assoc_response(fc))
++			title = "AscRsp";
++		else if (ieee80211_is_reassoc_response(fc))
++			title = "RasRsp";
++		else if (ieee80211_is_probe_response(fc)) {
++			title = "PrbRsp";
++			print_dump = 1;	/* dump frame contents */
++		} else if (ieee80211_is_beacon(fc)) {
++			title = "Beacon";
++			print_dump = 1;	/* dump frame contents */
++		} else if (ieee80211_is_atim(fc))
++			title = "ATIM";
++		else if (ieee80211_is_auth(fc))
++			title = "Auth";
++		else if (ieee80211_is_deauth(fc))
++			title = "DeAuth";
++		else if (ieee80211_is_disassoc(fc))
++			title = "DisAssoc";
++		else
++			title = "Frame";
++
++		rate_idx = iwl4965_hwrate_to_plcp_idx(rate_sym);
++		if (unlikely(rate_idx == -1))
++			bitrate = 0;
++		else
++			bitrate = iwl4965_rates[rate_idx].ieee / 2;
++
++		/* print frame summary.
++		 * MAC addresses show just the last byte (for brevity),
++		 *    but you can hack it to show more, if you'd like to. */
++		if (dataframe)
++			IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
++				     "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
++				     title, fc, header->addr1[5],
++				     length, rssi, channel, bitrate);
++		else {
++			/* src/dst addresses assume managed mode */
++			IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
++				     "src=0x%02x, rssi=%u, tim=%lu usec, "
++				     "phy=0x%02x, chnl=%d\n",
++				     title, fc, header->addr1[5],
++				     header->addr3[5], rssi,
++				     tsf_low - priv->scan_start_tsf,
++				     phy_flags, channel);
++		}
++	}
++	if (print_dump)
++		iwl_print_hex_dump(IWL_DL_RX, data, length);
++}
++#else
++static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv,
++					    struct iwl4965_rx_packet *pkt,
++					    struct ieee80211_hdr *header,
++					    int group100)
++{
++}
++#endif
++
++
++
++/* Called for REPLY_RX (legacy ABG frames), or
+  * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
+-static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
+ 				struct iwl4965_rx_mem_buffer *rxb)
+ {
++	struct ieee80211_hdr *header;
++	struct ieee80211_rx_status rx_status;
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ 	/* Use phy data (Rx signal strength, etc.) contained within
+ 	 *   this rx packet for legacy frames,
+ 	 *   or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
+-	int include_phy = (pkt->hdr.cmd == REPLY_4965_RX);
++	int include_phy = (pkt->hdr.cmd == REPLY_RX);
+ 	struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
+ 		(struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) :
+ 		(struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
+ 	__le32 *rx_end;
+ 	unsigned int len = 0;
+-	struct ieee80211_hdr *header;
+ 	u16 fc;
+-	struct ieee80211_rx_status stats = {
+-		.mactime = le64_to_cpu(rx_start->timestamp),
+-		.channel = le16_to_cpu(rx_start->channel),
+-		.phymode =
+-			(rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+-			MODE_IEEE80211G : MODE_IEEE80211A,
+-		.antenna = 0,
+-		.rate = iwl4965_hw_get_rate(rx_start->rate_n_flags),
+-		.flag = 0,
+-	};
+ 	u8 network_packet;
+ 
++	rx_status.mactime = le64_to_cpu(rx_start->timestamp);
++	rx_status.freq =
++		ieee80211_frequency_to_channel(le16_to_cpu(rx_start->channel));
++	rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
++				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
++	rx_status.rate_idx =
++		iwl4965_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags));
++	if (rx_status.band == IEEE80211_BAND_5GHZ)
++		rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
++
++	rx_status.antenna = 0;
++	rx_status.flag = 0;
++
+ 	if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
+-		IWL_DEBUG_DROP
+-			("dsp size out of range [0,20]: "
+-			 "%d/n", rx_start->cfg_phy_cnt);
++		IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n",
++				rx_start->cfg_phy_cnt);
+ 		return;
+ 	}
++
+ 	if (!include_phy) {
+ 		if (priv->last_phy_res[0])
+ 			rx_start = (struct iwl4965_rx_phy_res *)
+@@ -3924,7 +4013,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ 						  + rx_start->cfg_phy_cnt);
+ 
+ 		len = le16_to_cpu(rx_start->byte_count);
+-		rx_end = (__le32 *) (pkt->u.raw + rx_start->cfg_phy_cnt +
++		rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
+ 				  sizeof(struct iwl4965_rx_phy_res) + len);
+ 	} else {
+ 		struct iwl4965_rx_mpdu_res_start *amsdu =
+@@ -3946,43 +4035,38 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ 
+ 	priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
+ 
+-	stats.freq = ieee80211chan2mhz(stats.channel);
+-
+ 	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
+-	stats.ssi = iwl4965_calc_rssi(rx_start);
++	rx_status.ssi = iwl4965_calc_rssi(rx_start);
+ 
+ 	/* Meaningful noise values are available only from beacon statistics,
+ 	 *   which are gathered only when associated, and indicate noise
+ 	 *   only for the associated network channel ...
+ 	 * Ignore these noise values while scanning (other channels) */
+-	if (iwl4965_is_associated(priv) &&
++	if (iwl_is_associated(priv) &&
+ 	    !test_bit(STATUS_SCANNING, &priv->status)) {
+-		stats.noise = priv->last_rx_noise;
+-		stats.signal = iwl4965_calc_sig_qual(stats.ssi, stats.noise);
++		rx_status.noise = priv->last_rx_noise;
++		rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi,
++							 rx_status.noise);
+ 	} else {
+-		stats.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+-		stats.signal = iwl4965_calc_sig_qual(stats.ssi, 0);
++		rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
++		rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, 0);
+ 	}
+ 
+ 	/* Reset beacon noise level if not associated. */
+-	if (!iwl4965_is_associated(priv))
++	if (!iwl_is_associated(priv))
+ 		priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
+-	/* TODO:  Parts of iwl4965_report_frame are broken for 4965 */
+-	if (iwl4965_debug_level & (IWL_DL_RX))
+-		/* Set "1" to report good data frames in groups of 100 */
+-		iwl4965_report_frame(priv, pkt, header, 1);
++	/* Set "1" to report good data frames in groups of 100 */
++	/* FIXME: need to optimze the call: */
++	iwl4965_dbg_report_frame(priv, pkt, header, 1);
+ 
+-	if (iwl4965_debug_level & (IWL_DL_RX | IWL_DL_STATS))
+-	IWL_DEBUG_RX("Rssi %d, noise %d, qual %d, TSF %lu\n",
+-		stats.ssi, stats.noise, stats.signal,
+-		 (long unsigned int)le64_to_cpu(rx_start->timestamp));
+-#endif
++	IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
++			      rx_status.ssi, rx_status.noise, rx_status.signal,
++			      (unsigned long long)rx_status.mactime);
+ 
+ 	network_packet = iwl4965_is_network_packet(priv, header);
+ 	if (network_packet) {
+-		priv->last_rx_rssi = stats.ssi;
++		priv->last_rx_rssi = rx_status.ssi;
+ 		priv->last_beacon_time =  priv->ucode_beacon_time;
+ 		priv->last_tsf = le64_to_cpu(rx_start->timestamp);
+ 	}
+@@ -3990,102 +4074,10 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ 	fc = le16_to_cpu(header->frame_control);
+ 	switch (fc & IEEE80211_FCTL_FTYPE) {
+ 	case IEEE80211_FTYPE_MGMT:
+-
+ 		if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ 			iwl4965_update_ps_mode(priv, fc  & IEEE80211_FCTL_PM,
+ 						header->addr2);
+-		switch (fc & IEEE80211_FCTL_STYPE) {
+-		case IEEE80211_STYPE_PROBE_RESP:
+-		case IEEE80211_STYPE_BEACON:
+-			if ((priv->iw_mode == IEEE80211_IF_TYPE_STA &&
+-			     !compare_ether_addr(header->addr2, priv->bssid)) ||
+-			    (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+-			     !compare_ether_addr(header->addr3, priv->bssid))) {
+-				struct ieee80211_mgmt *mgmt =
+-					(struct ieee80211_mgmt *)header;
+-				u64 timestamp =
+-					le64_to_cpu(mgmt->u.beacon.timestamp);
+-
+-				priv->timestamp0 = timestamp & 0xFFFFFFFF;
+-				priv->timestamp1 =
+-					(timestamp >> 32) & 0xFFFFFFFF;
+-				priv->beacon_int = le16_to_cpu(
+-				    mgmt->u.beacon.beacon_int);
+-				if (priv->call_post_assoc_from_beacon &&
+-				    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
+-					priv->call_post_assoc_from_beacon = 0;
+-					queue_work(priv->workqueue,
+-					    &priv->post_associate.work);
+-				}
+-			}
+-			break;
+-
+-		case IEEE80211_STYPE_ACTION:
+-			break;
+-
+-			/*
+-			 * TODO: Use the new callback function from
+-			 * mac80211 instead of sniffing these packets.
+-			 */
+-		case IEEE80211_STYPE_ASSOC_RESP:
+-		case IEEE80211_STYPE_REASSOC_RESP:
+-			if (network_packet) {
+-#ifdef CONFIG_IWL4965_HT
+-				u8 *pos = NULL;
+-				struct ieee802_11_elems elems;
+-#endif				/*CONFIG_IWL4965_HT */
+-				struct ieee80211_mgmt *mgnt =
+-					(struct ieee80211_mgmt *)header;
+-
+-				/* We have just associated, give some
+-				 * time for the 4-way handshake if
+-				 * any. Don't start scan too early. */
+-				priv->next_scan_jiffies = jiffies +
+-					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
+-
+-				priv->assoc_id = (~((1 << 15) | (1 << 14))
+-					& le16_to_cpu(mgnt->u.assoc_resp.aid));
+-				priv->assoc_capability =
+-					le16_to_cpu(
+-						mgnt->u.assoc_resp.capab_info);
+-#ifdef CONFIG_IWL4965_HT
+-				pos = mgnt->u.assoc_resp.variable;
+-				if (!parse_elems(pos,
+-						 len - (pos - (u8 *) mgnt),
+-						 &elems)) {
+-					if (elems.ht_extra_param &&
+-					    elems.ht_cap_param)
+-						break;
+-				}
+-#endif				/*CONFIG_IWL4965_HT */
+-				/* assoc_id is 0 no association */
+-				if (!priv->assoc_id)
+-					break;
+-				if (priv->beacon_int)
+-					queue_work(priv->workqueue,
+-					    &priv->post_associate.work);
+-				else
+-					priv->call_post_assoc_from_beacon = 1;
+-			}
+-
+-			break;
+-
+-		case IEEE80211_STYPE_PROBE_REQ:
+-			if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+-			    !iwl4965_is_associated(priv)) {
+-				DECLARE_MAC_BUF(mac1);
+-				DECLARE_MAC_BUF(mac2);
+-				DECLARE_MAC_BUF(mac3);
+-
+-				IWL_DEBUG_DROP("Dropping (non network): "
+-					       "%s, %s, %s\n",
+-					       print_mac(mac1, header->addr1),
+-					       print_mac(mac2, header->addr2),
+-					       print_mac(mac3, header->addr3));
+-				return;
+-			}
+-		}
+-		iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &stats);
++		iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status);
+ 		break;
+ 
+ 	case IEEE80211_FTYPE_CTL:
+@@ -4094,7 +4086,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ 		case IEEE80211_STYPE_BACK_REQ:
+ 			IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n");
+ 			iwl4965_handle_data_packet(priv, 0, include_phy,
+-						rxb, &stats);
++						rxb, &rx_status);
+ 			break;
+ 		default:
+ 			break;
+@@ -4124,7 +4116,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ 				       print_mac(mac3, header->addr3));
+ 		else
+ 			iwl4965_handle_data_packet(priv, 1, include_phy, rxb,
+-						   &stats);
++						   &rx_status);
+ 		break;
+ 	}
+ 	default:
+@@ -4135,7 +4127,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ 
+ /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
+  * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
+-static void iwl4965_rx_reply_rx_phy(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
+ 				    struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4143,8 +4135,7 @@ static void iwl4965_rx_reply_rx_phy(struct iwl4965_priv *priv,
+ 	memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
+ 	       sizeof(struct iwl4965_rx_phy_res));
+ }
+-
+-static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
+ 					   struct iwl4965_rx_mem_buffer *rxb)
+ 
+ {
+@@ -4165,31 +4156,12 @@ static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv,
+ 	}
+ #endif /*CONFIG_IWL4965_SENSITIVITY*/
+ }
+-
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+-
+-/**
+- * iwl4965_set_tx_status - Update driver's record of one Tx frame's status
+- *
+- * This will get sent to mac80211.
+- */
+-static void iwl4965_set_tx_status(struct iwl4965_priv *priv, int txq_id, int idx,
+-				  u32 status, u32 retry_count, u32 rate)
+-{
+-	struct ieee80211_tx_status *tx_status =
+-		&(priv->txq[txq_id].txb[idx].status);
+-
+-	tx_status->flags = status ? IEEE80211_TX_STATUS_ACK : 0;
+-	tx_status->retry_count += retry_count;
+-	tx_status->control.tx_rate = rate;
+-}
+-
+ 
+ /**
+  * iwl4965_sta_modify_enable_tid_tx - Enable Tx for this TID in station table
+  */
+-static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv,
++static void iwl4965_sta_modify_enable_tid_tx(struct iwl_priv *priv,
+ 					 int sta_id, int tid)
+ {
+ 	unsigned long flags;
+@@ -4204,24 +4176,24 @@ static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv,
+ 	iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ }
+ 
+-
+ /**
+  * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack
+  *
+  * Go through block-ack's bitmap of ACK'd frames, update driver's record of
+  * ACK vs. not.  This gets sent to mac80211, then to rate scaling algo.
+  */
+-static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv,
++static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+ 						 struct iwl4965_ht_agg *agg,
+ 						 struct iwl4965_compressed_ba_resp*
+ 						 ba_resp)
+ 
+ {
+ 	int i, sh, ack;
+-	u16 ba_seq_ctl = le16_to_cpu(ba_resp->ba_seq_ctl);
+-	u32 bitmap0, bitmap1;
+-	u32 resp_bitmap0 = le32_to_cpu(ba_resp->ba_bitmap0);
+-	u32 resp_bitmap1 = le32_to_cpu(ba_resp->ba_bitmap1);
++	u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
++	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
++	u64 bitmap;
++	int successes = 0;
++	struct ieee80211_tx_status *tx_status;
+ 
+ 	if (unlikely(!agg->wait_for_ba))  {
+ 		IWL_ERROR("Received BA when not expected\n");
+@@ -4230,17 +4202,15 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv,
+ 
+ 	/* Mark that the expected block-ack response arrived */
+ 	agg->wait_for_ba = 0;
+-	IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->ba_seq_ctl);
++	IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
+ 
+ 	/* Calculate shift to align block-ack bits with our Tx window bits */
+-	sh = agg->start_idx - SEQ_TO_INDEX(ba_seq_ctl >> 4);
++	sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4);
+ 	if (sh < 0) /* tbw something is wrong with indices */
+ 		sh += 0x100;
+ 
+ 	/* don't use 64-bit values for now */
+-	bitmap0 = resp_bitmap0 >> sh;
+-	bitmap1 = resp_bitmap1 >> sh;
+-	bitmap0 |= (resp_bitmap1 & ((1 << sh) | ((1 << sh) - 1))) << (32 - sh);
++	bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
+ 
+ 	if (agg->frame_count > (64 - sh)) {
+ 		IWL_DEBUG_TX_REPLY("more frames than bitmap size");
+@@ -4249,23 +4219,113 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv,
+ 
+ 	/* check for success or failure according to the
+ 	 * transmitted bitmap and block-ack bitmap */
+-	bitmap0 &= agg->bitmap0;
+-	bitmap1 &= agg->bitmap1;
++	bitmap &= agg->bitmap;
+ 
+ 	/* For each frame attempted in aggregation,
+ 	 * update driver's record of tx frame's status. */
+ 	for (i = 0; i < agg->frame_count ; i++) {
+-		int idx = (agg->start_idx + i) & 0xff;
+-		ack = bitmap0 & (1 << i);
++		ack = bitmap & (1 << i);
++		successes += !!ack;
+ 		IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
+-			ack? "ACK":"NACK", i, idx, agg->start_idx + i);
+-		iwl4965_set_tx_status(priv, agg->txq_id, idx, ack, 0,
+-			agg->rate_n_flags);
++			ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
++			agg->start_idx + i);
++	}
++
++	tx_status = &priv->txq[scd_flow].txb[agg->start_idx].status;
++	tx_status->flags = IEEE80211_TX_STATUS_ACK;
++	tx_status->flags |= IEEE80211_TX_STATUS_AMPDU;
++	tx_status->ampdu_ack_map = successes;
++	tx_status->ampdu_ack_len = agg->frame_count;
++	iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags,
++				     &tx_status->control);
++
++	IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
+ 
++	return 0;
++}
++
++/**
++ * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
++ */
++static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
++					    u16 txq_id)
++{
++	/* Simply stop the queue, but don't change any configuration;
++	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
++	iwl_write_prph(priv,
++		IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
++		(0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
++		(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
++}
++
++/**
++ * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID
++ * priv->lock must be held by the caller
++ */
++static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id,
++					u16 ssn_idx, u8 tx_fifo)
++{
++	int ret = 0;
++
++	if (IWL_BACK_QUEUE_FIRST_ID > txq_id) {
++		IWL_WARNING("queue number too small: %d, must be > %d\n",
++				txq_id, IWL_BACK_QUEUE_FIRST_ID);
++		return -EINVAL;
+ 	}
+ 
+-	IWL_DEBUG_TX_REPLY("Bitmap %x%x\n", bitmap0, bitmap1);
++	ret = iwl_grab_nic_access(priv);
++	if (ret)
++		return ret;
++
++	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
+ 
++	iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
++
++	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
++	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
++	/* supposes that ssn_idx is valid (!= 0xFFF) */
++	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
++
++	iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
++	iwl4965_txq_ctx_deactivate(priv, txq_id);
++	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
++
++	iwl_release_nic_access(priv);
++
++	return 0;
++}
++
++int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
++					 u8 tid, int txq_id)
++{
++	struct iwl4965_queue *q = &priv->txq[txq_id].q;
++	u8 *addr = priv->stations[sta_id].sta.sta.addr;
++	struct iwl4965_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
++
++	switch (priv->stations[sta_id].tid[tid].agg.state) {
++	case IWL_EMPTYING_HW_QUEUE_DELBA:
++		/* We are reclaiming the last packet of the */
++		/* aggregated HW queue */
++		if (txq_id  == tid_data->agg.txq_id &&
++		    q->read_ptr == q->write_ptr) {
++			u16 ssn = SEQ_TO_SN(tid_data->seq_number);
++			int tx_fifo = default_tid_to_tx_fifo[tid];
++			IWL_DEBUG_HT("HW queue empty: continue DELBA flow\n");
++			iwl4965_tx_queue_agg_disable(priv, txq_id,
++						     ssn, tx_fifo);
++			tid_data->agg.state = IWL_AGG_OFF;
++			ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid);
++		}
++		break;
++	case IWL_EMPTYING_HW_QUEUE_ADDBA:
++		/* We are reclaiming the last packet of the queue */
++		if (tid_data->tfds_in_queue == 0) {
++			IWL_DEBUG_HT("HW queue empty: continue ADDBA flow\n");
++			tid_data->agg.state = IWL_AGG_ON;
++			ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid);
++		}
++		break;
++	}
+ 	return 0;
+ }
+ 
+@@ -4285,7 +4345,7 @@ static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
+  * Handles block-acknowledge notification from device, which reports success
+  * of frames sent via aggregation.
+  */
+-static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
+ 					   struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4293,48 +4353,43 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv,
+ 	int index;
+ 	struct iwl4965_tx_queue *txq = NULL;
+ 	struct iwl4965_ht_agg *agg;
++	DECLARE_MAC_BUF(mac);
+ 
+ 	/* "flow" corresponds to Tx queue */
+-	u16 ba_resp_scd_flow = le16_to_cpu(ba_resp->scd_flow);
++	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+ 
+ 	/* "ssn" is start of block-ack Tx window, corresponds to index
+ 	 * (in Tx queue's circular buffer) of first TFD/frame in window */
+ 	u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
+ 
+-	if (ba_resp_scd_flow >= ARRAY_SIZE(priv->txq)) {
++	if (scd_flow >= priv->hw_params.max_txq_num) {
+ 		IWL_ERROR("BUG_ON scd_flow is bigger than number of queues");
+ 		return;
+ 	}
+ 
+-	txq = &priv->txq[ba_resp_scd_flow];
++	txq = &priv->txq[scd_flow];
+ 	agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
+ 
+ 	/* Find index just before block-ack window */
+ 	index = iwl4965_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
+ 
+ 	/* TODO: Need to get this copy more safely - now good for debug */
+-/*
+-	{
+-	DECLARE_MAC_BUF(mac);
++
+ 	IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, "
+ 			   "sta_id = %d\n",
+ 			   agg->wait_for_ba,
+ 			   print_mac(mac, (u8*) &ba_resp->sta_addr_lo32),
+ 			   ba_resp->sta_id);
+-	IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%X%X, scd_flow = "
++	IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
+ 			   "%d, scd_ssn = %d\n",
+ 			   ba_resp->tid,
+-			   ba_resp->ba_seq_ctl,
+-			   ba_resp->ba_bitmap1,
+-			   ba_resp->ba_bitmap0,
++			   ba_resp->seq_ctl,
++			   (unsigned long long)le64_to_cpu(ba_resp->bitmap),
+ 			   ba_resp->scd_flow,
+ 			   ba_resp->scd_ssn);
+-	IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%X%X \n",
++	IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n",
+ 			   agg->start_idx,
+-			   agg->bitmap1,
+-			   agg->bitmap0);
+-	}
+-*/
++			   (unsigned long long)agg->bitmap);
+ 
+ 	/* Update driver's record of ACK vs. not for each frame in window */
+ 	iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp);
+@@ -4342,29 +4397,23 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv,
+ 	/* Release all TFDs before the SSN, i.e. all TFDs in front of
+ 	 * block-ack window (we assume that they've been successfully
+ 	 * transmitted ... if not, it's too late anyway). */
+-	if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff))
+-		iwl4965_tx_queue_reclaim(priv, ba_resp_scd_flow, index);
+-
+-}
+-
+-
+-/**
+- * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
+- */
+-static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, u16 txq_id)
+-{
+-	/* Simply stop the queue, but don't change any configuration;
+-	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
+-	iwl4965_write_prph(priv,
+-		KDR_SCD_QUEUE_STATUS_BITS(txq_id),
+-		(0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
+-		(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
++	if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
++		int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index);
++		priv->stations[ba_resp->sta_id].
++			tid[ba_resp->tid].tfds_in_queue -= freed;
++		if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
++			priv->mac80211_registered &&
++			agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
++			ieee80211_wake_queue(priv->hw, scd_flow);
++		iwl4965_check_empty_hw_queue(priv, ba_resp->sta_id,
++			ba_resp->tid, scd_flow);
++	}
+ }
+ 
+ /**
+  * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
+  */
+-static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid,
++static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
+ 					u16 txq_id)
+ {
+ 	u32 tbl_dw_addr;
+@@ -4376,25 +4425,26 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid,
+ 	tbl_dw_addr = priv->scd_base_addr +
+ 			SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
+ 
+-	tbl_dw = iwl4965_read_targ_mem(priv, tbl_dw_addr);
++	tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);
+ 
+ 	if (txq_id & 0x1)
+ 		tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
+ 	else
+ 		tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
+ 
+-	iwl4965_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
++	iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
+ 
+ 	return 0;
+ }
+ 
++
+ /**
+  * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
+  *
+  * NOTE:  txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID,
+  *        i.e. it must be one of the higher queues used for aggregation
+  */
+-static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
++static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id,
+ 				       int tx_fifo, int sta_id, int tid,
+ 				       u16 ssn_idx)
+ {
+@@ -4412,7 +4462,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
+ 	iwl4965_sta_modify_enable_tid_tx(priv, sta_id, tid);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		return rc;
+@@ -4425,7 +4475,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
+ 	iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
+ 
+ 	/* Set this queue as a chain-building queue */
+-	iwl4965_set_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id));
++	iwl_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+ 
+ 	/* Place first TFD at index corresponding to start sequence number.
+ 	 * Assumes that ssn_idx is valid (!= 0xFFF) */
+@@ -4434,69 +4484,27 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
+ 	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
+ 
+ 	/* Set up Tx window size and frame limit for this queue */
+-	iwl4965_write_targ_mem(priv,
++	iwl_write_targ_mem(priv,
+ 			priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id),
+ 			(SCD_WIN_SIZE << SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
+ 			SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+ 
+-	iwl4965_write_targ_mem(priv, priv->scd_base_addr +
++	iwl_write_targ_mem(priv, priv->scd_base_addr +
+ 			SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
+ 			(SCD_FRAME_LIMIT << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS)
+ 			& SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+ 
+-	iwl4965_set_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id));
++	iwl_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
+ 
+ 	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
+ 	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
+ 
+-	iwl4965_release_nic_access(priv);
+-	spin_unlock_irqrestore(&priv->lock, flags);
+-
+-	return 0;
+-}
+-
+-/**
+- * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID
+- */
+-static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id,
+-					u16 ssn_idx, u8 tx_fifo)
+-{
+-	unsigned long flags;
+-	int rc;
+-
+-	if (IWL_BACK_QUEUE_FIRST_ID > txq_id) {
+-		IWL_WARNING("queue number too small: %d, must be > %d\n",
+-				txq_id, IWL_BACK_QUEUE_FIRST_ID);
+-		return -EINVAL;
+-	}
+-
+-	spin_lock_irqsave(&priv->lock, flags);
+-	rc = iwl4965_grab_nic_access(priv);
+-	if (rc) {
+-		spin_unlock_irqrestore(&priv->lock, flags);
+-		return rc;
+-	}
+-
+-	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
+-
+-	iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+-
+-	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+-	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+-	/* supposes that ssn_idx is valid (!= 0xFFF) */
+-	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
+-
+-	iwl4965_clear_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id));
+-	iwl4965_txq_ctx_deactivate(priv, txq_id);
+-	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
+-
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	return 0;
+ }
+ 
+-#endif/* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ 
+ /**
+@@ -4513,10 +4521,10 @@ static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id,
+  *       calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
+  *       which requires station table entry to exist).
+  */
+-void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
++void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+ {
+ 	int i, r;
+-	struct iwl4965_link_quality_cmd link_cmd = {
++	struct iwl_link_quality_cmd link_cmd = {
+ 		.reserved1 = 0,
+ 	};
+ 	u16 rate_flags;
+@@ -4525,7 +4533,7 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
+ 	 * all the way down to 1M in IEEE order, and then spin on 1M */
+ 	if (is_ap)
+ 		r = IWL_RATE_54M_INDEX;
+-	else if (priv->phymode == MODE_IEEE80211A)
++	else if (priv->band == IEEE80211_BAND_5GHZ)
+ 		r = IWL_RATE_6M_INDEX;
+ 	else
+ 		r = IWL_RATE_1M_INDEX;
+@@ -4550,24 +4558,25 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
+ 	link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
+ 
+ 	/* Update the rate scaling for control frame Tx to AP */
+-	link_cmd.sta_id = is_ap ? IWL_AP_ID : IWL4965_BROADCAST_ID;
++	link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
+ 
+-	iwl4965_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd),
+-			 &link_cmd);
++	iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
++			       sizeof(link_cmd), &link_cmd, NULL);
+ }
+ 
+ #ifdef CONFIG_IWL4965_HT
+ 
+-static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode,
+-				   u16 channel, u8 extension_chan_offset)
++static u8 iwl4965_is_channel_extension(struct iwl_priv *priv,
++				       enum ieee80211_band band,
++				       u16 channel, u8 extension_chan_offset)
+ {
+-	const struct iwl4965_channel_info *ch_info;
++	const struct iwl_channel_info *ch_info;
+ 
+-	ch_info = iwl4965_get_channel_info(priv, phymode, channel);
++	ch_info = iwl_get_channel_info(priv, band, channel);
+ 	if (!is_channel_valid(ch_info))
+ 		return 0;
+ 
+-	if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO)
++	if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE)
+ 		return 0;
+ 
+ 	if ((ch_info->fat_extension_channel == extension_chan_offset) ||
+@@ -4577,14 +4586,14 @@ static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode,
+ 	return 0;
+ }
+ 
+-static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv,
++static u8 iwl4965_is_fat_tx_allowed(struct iwl_priv *priv,
+ 				struct ieee80211_ht_info *sta_ht_inf)
+ {
+ 	struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
+ 
+ 	if ((!iwl_ht_conf->is_ht) ||
+ 	   (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
+-	   (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO))
++	   (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE))
+ 		return 0;
+ 
+ 	if (sta_ht_inf) {
+@@ -4593,12 +4602,12 @@ static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv,
+ 			return 0;
+ 	}
+ 
+-	return (iwl4965_is_channel_extension(priv, priv->phymode,
++	return (iwl4965_is_channel_extension(priv, priv->band,
+ 					 iwl_ht_conf->control_channel,
+ 					 iwl_ht_conf->extension_chan_offset));
+ }
+ 
+-void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info)
++void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
+ {
+ 	struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+ 	u32 val;
+@@ -4629,9 +4638,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info)
+ 	case IWL_EXT_CHANNEL_OFFSET_BELOW:
+ 		rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+ 		break;
+-	case IWL_EXT_CHANNEL_OFFSET_AUTO:
+-		rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
+-		break;
++	case IWL_EXT_CHANNEL_OFFSET_NONE:
+ 	default:
+ 		rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
+ 		break;
+@@ -4654,7 +4661,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info)
+ 	return;
+ }
+ 
+-void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
++void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
+ 				struct ieee80211_ht_info *sta_ht_inf)
+ {
+ 	__le32 sta_flags;
+@@ -4699,7 +4706,7 @@ void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
+ 	return;
+ }
+ 
+-static void iwl4965_sta_modify_add_ba_tid(struct iwl4965_priv *priv,
++static void iwl4965_sta_modify_add_ba_tid(struct iwl_priv *priv,
+ 					  int sta_id, int tid, u16 ssn)
+ {
+ 	unsigned long flags;
+@@ -4715,7 +4722,7 @@ static void iwl4965_sta_modify_add_ba_tid(struct iwl4965_priv *priv,
+ 	iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ }
+ 
+-static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv,
++static void iwl4965_sta_modify_del_ba_tid(struct iwl_priv *priv,
+ 					  int sta_id, int tid)
+ {
+ 	unsigned long flags;
+@@ -4730,136 +4737,94 @@ static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv,
+ 	iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ }
+ 
+-int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+-			     enum ieee80211_ampdu_mlme_action action,
+-			     const u8 *addr, u16 tid, u16 ssn)
+-{
+-	struct iwl4965_priv *priv = hw->priv;
+-	int sta_id;
+-	DECLARE_MAC_BUF(mac);
+-
+-	IWL_DEBUG_HT("A-MPDU action on da=%s tid=%d ",
+-			print_mac(mac, addr), tid);
+-	sta_id = iwl4965_hw_find_station(priv, addr);
+-	switch (action) {
+-	case IEEE80211_AMPDU_RX_START:
+-		IWL_DEBUG_HT("start Rx\n");
+-		iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, ssn);
+-		break;
+-	case IEEE80211_AMPDU_RX_STOP:
+-		IWL_DEBUG_HT("stop Rx\n");
+-		iwl4965_sta_modify_del_ba_tid(priv, sta_id, tid);
+-		break;
+-	default:
+-		IWL_DEBUG_HT("unknown\n");
+-		return -EINVAL;
+-		break;
+-	}
+-	return 0;
+-}
+-
+-#ifdef CONFIG_IWL4965_HT_AGG
+-
+-static const u16 default_tid_to_tx_fifo[] = {
+-	IWL_TX_FIFO_AC1,
+-	IWL_TX_FIFO_AC0,
+-	IWL_TX_FIFO_AC0,
+-	IWL_TX_FIFO_AC1,
+-	IWL_TX_FIFO_AC2,
+-	IWL_TX_FIFO_AC2,
+-	IWL_TX_FIFO_AC3,
+-	IWL_TX_FIFO_AC3,
+-	IWL_TX_FIFO_NONE,
+-	IWL_TX_FIFO_NONE,
+-	IWL_TX_FIFO_NONE,
+-	IWL_TX_FIFO_NONE,
+-	IWL_TX_FIFO_NONE,
+-	IWL_TX_FIFO_NONE,
+-	IWL_TX_FIFO_NONE,
+-	IWL_TX_FIFO_NONE,
+-	IWL_TX_FIFO_AC3
+-};
+-
+ /*
+  * Find first available (lowest unused) Tx Queue, mark it "active".
+  * Called only when finding queue for aggregation.
+  * Should never return anything < 7, because they should already
+  * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6).
+  */
+-static int iwl4965_txq_ctx_activate_free(struct iwl4965_priv *priv)
++static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv)
+ {
+ 	int txq_id;
+ 
+-	for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++)
++	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+ 		if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk))
+ 			return txq_id;
+ 	return -1;
+ }
+ 
+-int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid,
+-			    u16 *start_seq_num)
++static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da,
++				       u16 tid, u16 *start_seq_num)
+ {
+-
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	int sta_id;
+ 	int tx_fifo;
+ 	int txq_id;
+ 	int ssn = -1;
++	int ret = 0;
+ 	unsigned long flags;
+ 	struct iwl4965_tid_data *tid_data;
+ 	DECLARE_MAC_BUF(mac);
+ 
+-	/* Determine Tx DMA/FIFO channel for this Traffic ID */
+ 	if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
+ 		tx_fifo = default_tid_to_tx_fifo[tid];
+ 	else
+ 		return -EINVAL;
+ 
+-	IWL_WARNING("iwl-AGG iwl4965_mac_ht_tx_agg_start on da=%s"
+-		    " tid=%d\n", print_mac(mac, da), tid);
++	IWL_WARNING("%s on da = %s tid = %d\n",
++			__func__, print_mac(mac, da), tid);
+ 
+-	/* Get index into station table */
+ 	sta_id = iwl4965_hw_find_station(priv, da);
+ 	if (sta_id == IWL_INVALID_STATION)
+ 		return -ENXIO;
+ 
+-	/* Find available Tx queue for aggregation */
++	if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
++		IWL_ERROR("Start AGG when state is not IWL_AGG_OFF !\n");
++		return -ENXIO;
++	}
++
+ 	txq_id = iwl4965_txq_ctx_activate_free(priv);
+ 	if (txq_id == -1)
+ 		return -ENXIO;
+ 
+ 	spin_lock_irqsave(&priv->sta_lock, flags);
+ 	tid_data = &priv->stations[sta_id].tid[tid];
+-
+-	/* Get starting sequence number for 1st frame in block ack window.
+-	 * We'll use least signif byte as 1st frame's index into Tx queue. */
+ 	ssn = SEQ_TO_SN(tid_data->seq_number);
+ 	tid_data->agg.txq_id = txq_id;
+ 	spin_unlock_irqrestore(&priv->sta_lock, flags);
+ 
+ 	*start_seq_num = ssn;
++	ret = iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo,
++					  sta_id, tid, ssn);
++	if (ret)
++		return ret;
+ 
+-	/* Update driver's link quality manager */
+-	iwl4965_ba_status(priv, tid, BA_STATUS_ACTIVE);
+-
+-	/* Set up and enable aggregation for selected Tx queue and FIFO */
+-	return iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo,
+-					   sta_id, tid, ssn);
++	ret = 0;
++	if (tid_data->tfds_in_queue == 0) {
++		printk(KERN_ERR "HW queue is empty\n");
++		tid_data->agg.state = IWL_AGG_ON;
++		ieee80211_start_tx_ba_cb_irqsafe(hw, da, tid);
++	} else {
++		IWL_DEBUG_HT("HW queue is NOT empty: %d packets in HW queue\n",
++				tid_data->tfds_in_queue);
++		tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
++	}
++	return ret;
+ }
+ 
+-
+-int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
+-			   int generator)
++static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da,
++				      u16 tid)
+ {
+ 
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	int tx_fifo_id, txq_id, sta_id, ssn = -1;
+ 	struct iwl4965_tid_data *tid_data;
+-	int rc;
++	int ret, write_ptr, read_ptr;
++	unsigned long flags;
+ 	DECLARE_MAC_BUF(mac);
+ 
+ 	if (!da) {
+-		IWL_ERROR("%s: da = NULL\n", __func__);
++		IWL_ERROR("da = NULL\n");
+ 		return -EINVAL;
+ 	}
+ 
+@@ -4873,31 +4838,82 @@ int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
+ 	if (sta_id == IWL_INVALID_STATION)
+ 		return -ENXIO;
+ 
++	if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON)
++		IWL_WARNING("Stopping AGG while state not IWL_AGG_ON\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;
++	write_ptr = priv->txq[txq_id].q.write_ptr;
++	read_ptr = priv->txq[txq_id].q.read_ptr;
++
++	/* The queue is not empty */
++	if (write_ptr != read_ptr) {
++		IWL_DEBUG_HT("Stopping a non empty AGG HW QUEUE\n");
++		priv->stations[sta_id].tid[tid].agg.state =
++				IWL_EMPTYING_HW_QUEUE_DELBA;
++		return 0;
++	}
+ 
+-	rc = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id);
+-	/* FIXME: need more safe way to handle error condition */
+-	if (rc)
+-		return rc;
++	IWL_DEBUG_HT("HW queue empty\n");;
++	priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	ret = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	if (ret)
++		return ret;
++
++	ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, da, tid);
+ 
+-	iwl4965_ba_status(priv, tid, BA_STATUS_INITIATOR_DELBA);
+ 	IWL_DEBUG_INFO("iwl4965_mac_ht_tx_agg_stop on da=%s tid=%d\n",
+-		       print_mac(mac, da), tid);
++			print_mac(mac, da), tid);
+ 
+ 	return 0;
+ }
+ 
++int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
++			     enum ieee80211_ampdu_mlme_action action,
++			     const u8 *addr, u16 tid, u16 *ssn)
++{
++	struct iwl_priv *priv = hw->priv;
++	int sta_id;
++	DECLARE_MAC_BUF(mac);
++
++	IWL_DEBUG_HT("A-MPDU action on da=%s tid=%d ",
++			print_mac(mac, addr), tid);
++	sta_id = iwl4965_hw_find_station(priv, addr);
++	switch (action) {
++	case IEEE80211_AMPDU_RX_START:
++		IWL_DEBUG_HT("start Rx\n");
++		iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, *ssn);
++		break;
++	case IEEE80211_AMPDU_RX_STOP:
++		IWL_DEBUG_HT("stop Rx\n");
++		iwl4965_sta_modify_del_ba_tid(priv, sta_id, tid);
++		break;
++	case IEEE80211_AMPDU_TX_START:
++		IWL_DEBUG_HT("start Tx\n");
++		return iwl4965_mac_ht_tx_agg_start(hw, addr, tid, ssn);
++	case IEEE80211_AMPDU_TX_STOP:
++		IWL_DEBUG_HT("stop Tx\n");
++		return iwl4965_mac_ht_tx_agg_stop(hw, addr, tid);
++	default:
++		IWL_DEBUG_HT("unknown\n");
++		return -EINVAL;
++		break;
++	}
++	return 0;
++}
+ 
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ 
+ /* Set up 4965-specific Rx frame reply handlers */
+-void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv)
++void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv)
+ {
+ 	/* Legacy Rx frames */
+-	priv->rx_handlers[REPLY_4965_RX] = iwl4965_rx_reply_rx;
++	priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx;
+ 
+ 	/* High-throughput (HT) Rx frames */
+ 	priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
+@@ -4907,71 +4923,85 @@ void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv)
+ 	    iwl4965_rx_missed_beacon_notif;
+ 
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ 	priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ }
+ 
+-void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv)
++void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv)
+ {
+ 	INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
+-	INIT_WORK(&priv->statistics_work, iwl4965_bg_statistics_work);
+ #ifdef CONFIG_IWL4965_SENSITIVITY
+ 	INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work);
+ #endif
+-#ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+-	INIT_WORK(&priv->agg_work, iwl4965_bg_agg_work);
+-#endif /* CONFIG_IWL4965_HT_AGG */
+-#endif /* CONFIG_IWL4965_HT */
+ 	init_timer(&priv->statistics_periodic);
+ 	priv->statistics_periodic.data = (unsigned long)priv;
+ 	priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
+ }
+ 
+-void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv)
++void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv)
+ {
+ 	del_timer_sync(&priv->statistics_periodic);
+ 
+ 	cancel_delayed_work(&priv->init_alive_start);
+ }
+ 
+-struct pci_device_id iwl4965_hw_card_ids[] = {
+-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4229)},
+-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4230)},
+-	{0}
++
++static struct iwl_hcmd_ops iwl4965_hcmd = {
++	.rxon_assoc = iwl4965_send_rxon_assoc,
+ };
+ 
+-/*
+- * The device's EEPROM semaphore prevents conflicts between driver and uCode
+- * when accessing the EEPROM; each access is a series of pulses to/from the
+- * EEPROM chip, not a single event, so even reads could conflict if they
+- * weren't arbitrated by the semaphore.
+- */
+-int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv)
+-{
+-	u16 count;
+-	int rc;
++static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
++	.enqueue_hcmd = iwl4965_enqueue_hcmd,
++};
+ 
+-	for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
+-		/* Request semaphore */
+-		iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+-			CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+-
+-		/* See if we got it */
+-		rc = iwl4965_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 (rc >= 0) {
+-			IWL_DEBUG_IO("Acquired semaphore after %d tries.\n",
+-				count+1);
+-			return rc;
+-		}
+-	}
++static struct iwl_lib_ops iwl4965_lib = {
++	.init_drv = iwl4965_init_drv,
++	.set_hw_params = iwl4965_hw_set_hw_params,
++	.txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
++	.hw_nic_init = iwl4965_hw_nic_init,
++	.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
++	.alive_notify = iwl4965_alive_notify,
++	.load_ucode = iwl4965_load_bsm,
++	.eeprom_ops = {
++		.verify_signature  = iwlcore_eeprom_verify_signature,
++		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
++		.release_semaphore = iwlcore_eeprom_release_semaphore,
++	},
++	.radio_kill_sw = iwl4965_radio_kill_sw,
++};
+ 
+-	return rc;
+-}
++static struct iwl_ops iwl4965_ops = {
++	.lib = &iwl4965_lib,
++	.hcmd = &iwl4965_hcmd,
++	.utils = &iwl4965_hcmd_utils,
++};
++
++struct iwl_cfg iwl4965_agn_cfg = {
++	.name = "4965AGN",
++	.fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode",
++	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
++	.ops = &iwl4965_ops,
++	.mod_params = &iwl4965_mod_params,
++};
++
++module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
++MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
++module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
++MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
++module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
++MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n");
++module_param_named(debug, iwl4965_mod_params.debug, int, 0444);
++MODULE_PARM_DESC(debug, "debug output mask");
++module_param_named(
++	disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444);
++MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
++
++module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444);
++MODULE_PARM_DESC(queues_num, "number of hw queues.");
++
++/* QoS */
++module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444);
++MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
++module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444);
++MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
+ 
+-MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
+index 9cb82be..9ed13cb 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
++++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 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
+@@ -36,13 +36,24 @@
+ #include <linux/kernel.h>
+ #include <net/ieee80211_radiotap.h>
+ 
+-/* Hardware specific file defines the PCI IDs table for that hardware module */
+-extern struct pci_device_id iwl4965_hw_card_ids[];
+-
+ #define DRV_NAME        "iwl4965"
++#include "iwl-rfkill.h"
++#include "iwl-eeprom.h"
+ #include "iwl-4965-hw.h"
++#include "iwl-csr.h"
+ #include "iwl-prph.h"
+-#include "iwl-4965-debug.h"
++#include "iwl-debug.h"
++#include "iwl-led.h"
++
++/* configuration for the iwl4965 */
++extern struct iwl_cfg iwl4965_agn_cfg;
++
++/* Change firmware file name, using "-" and incrementing number,
++ *   *only* when uCode interface or architecture changes so that it
++ *   is not compatible with earlier drivers.
++ * This number will also appear in << 8 position of 1st dword of uCode file */
++#define IWL4965_UCODE_API "-1"
++
+ 
+ /* Default noise level to report when noise measurement is not available.
+  *   This may be because we're:
+@@ -57,11 +68,6 @@ extern struct pci_device_id iwl4965_hw_card_ids[];
+  *   averages within an s8's (used in some apps) range of negative values. */
+ #define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
+ 
+-/* Module parameters accessible from iwl-*.c */
+-extern int iwl4965_param_hwcrypto;
+-extern int iwl4965_param_queues_num;
+-extern int iwl4965_param_amsdu_size_8K;
+-
+ enum iwl4965_antenna {
+ 	IWL_ANTENNA_DIVERSITY,
+ 	IWL_ANTENNA_MAIN,
+@@ -133,7 +139,7 @@ struct iwl4965_tx_info {
+ struct iwl4965_tx_queue {
+ 	struct iwl4965_queue q;
+ 	struct iwl4965_tfd_frame *bd;
+-	struct iwl4965_cmd *cmd;
++	struct iwl_cmd *cmd;
+ 	dma_addr_t dma_addr_cmd;
+ 	struct iwl4965_tx_info *txb;
+ 	int need_update;
+@@ -190,7 +196,7 @@ enum {
+  */
+ #define IWL4965_MAX_RATE (33)
+ 
+-struct iwl4965_channel_info {
++struct iwl_channel_info {
+ 	struct iwl4965_channel_tgd_info tgd;
+ 	struct iwl4965_channel_tgh_info tgh;
+ 	struct iwl4965_eeprom_channel eeprom;	  /* EEPROM regulatory limit */
+@@ -206,7 +212,7 @@ struct iwl4965_channel_info {
+ 
+ 	u8 group_index;	  /* 0-4, maps channel to group1/2/3/4/5 */
+ 	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */
+-	u8 phymode;	  /* MODE_IEEE80211{A,B,G} */
++	enum ieee80211_band band;
+ 
+ 	/* Radio/DSP gain settings for each "normal" data Tx rate.
+ 	 * These include, in addition to RF and DSP gain, a few fields for
+@@ -288,8 +294,8 @@ struct iwl4965_frame {
+ 
+ #define SEQ_TO_QUEUE(x)  ((x >> 8) & 0xbf)
+ #define QUEUE_TO_SEQ(x)  ((x & 0xbf) << 8)
+-#define SEQ_TO_INDEX(x) (x & 0xff)
+-#define INDEX_TO_SEQ(x) (x & 0xff)
++#define SEQ_TO_INDEX(x) ((u8)(x & 0xff))
++#define INDEX_TO_SEQ(x) ((u8)(x & 0xff))
+ #define SEQ_HUGE_FRAME  (0x4000)
+ #define SEQ_RX_FRAME    __constant_cpu_to_le16(0x8000)
+ #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+@@ -305,15 +311,15 @@ enum {
+ 	CMD_WANT_SKB = (1 << 2),
+ };
+ 
+-struct iwl4965_cmd;
+-struct iwl4965_priv;
++struct iwl_cmd;
++struct iwl_priv;
+ 
+-struct iwl4965_cmd_meta {
+-	struct iwl4965_cmd_meta *source;
++struct iwl_cmd_meta {
++	struct iwl_cmd_meta *source;
+ 	union {
+ 		struct sk_buff *skb;
+-		int (*callback)(struct iwl4965_priv *priv,
+-				struct iwl4965_cmd *cmd, struct sk_buff *skb);
++		int (*callback)(struct iwl_priv *priv,
++				struct iwl_cmd *cmd, struct sk_buff *skb);
+ 	} __attribute__ ((packed)) u;
+ 
+ 	/* The CMD_SIZE_HUGE flag bit indicates that the command
+@@ -323,15 +329,15 @@ struct iwl4965_cmd_meta {
+ } __attribute__ ((packed));
+ 
+ /**
+- * struct iwl4965_cmd
++ * struct iwl_cmd
+  *
+  * For allocation of the command and tx queues, this establishes the overall
+  * size of the largest command we send to uCode, except for a scan command
+  * (which is relatively huge; space is allocated separately).
+  */
+-struct iwl4965_cmd {
+-	struct iwl4965_cmd_meta meta;	/* driver data */
+-	struct iwl4965_cmd_header hdr;	/* uCode API */
++struct iwl_cmd {
++	struct iwl_cmd_meta meta;	/* driver data */
++	struct iwl_cmd_header hdr;	/* uCode API */
+ 	union {
+ 		struct iwl4965_addsta_cmd addsta;
+ 		struct iwl4965_led_cmd led;
+@@ -351,15 +357,15 @@ struct iwl4965_cmd {
+ 	} __attribute__ ((packed)) cmd;
+ } __attribute__ ((packed));
+ 
+-struct iwl4965_host_cmd {
++struct iwl_host_cmd {
+ 	u8 id;
+ 	u16 len;
+-	struct iwl4965_cmd_meta meta;
++	struct iwl_cmd_meta meta;
+ 	const void *data;
+ };
+ 
+-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \
+-			      sizeof(struct iwl4965_cmd_meta))
++#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
++			      sizeof(struct iwl_cmd_meta))
+ 
+ /*
+  * RX related structures and functions
+@@ -408,32 +414,12 @@ struct iwl4965_rx_queue {
+ #define MAX_B_CHANNELS  14
+ #define MIN_B_CHANNELS  1
+ 
+-#define STATUS_HCMD_ACTIVE	0	/* host command in progress */
+-#define STATUS_INT_ENABLED	1
+-#define STATUS_RF_KILL_HW	2
+-#define STATUS_RF_KILL_SW	3
+-#define STATUS_INIT		4
+-#define STATUS_ALIVE		5
+-#define STATUS_READY		6
+-#define STATUS_TEMPERATURE	7
+-#define STATUS_GEO_CONFIGURED	8
+-#define STATUS_EXIT_PENDING	9
+-#define STATUS_IN_SUSPEND	10
+-#define STATUS_STATISTICS	11
+-#define STATUS_SCANNING		12
+-#define STATUS_SCAN_ABORTING	13
+-#define STATUS_SCAN_HW		14
+-#define STATUS_POWER_PMI	15
+-#define STATUS_FW_ERROR		16
+-#define STATUS_CONF_PENDING	17
+-
+ #define MAX_TID_COUNT        9
+ 
+ #define IWL_INVALID_RATE     0xFF
+ #define IWL_INVALID_VALUE    -1
+ 
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ /**
+  * struct iwl4965_ht_agg -- aggregation status while waiting for block-ack
+  * @txq_id: Tx queue used for Tx attempt
+@@ -453,25 +439,30 @@ struct iwl4965_ht_agg {
+ 	u16 frame_count;
+ 	u16 wait_for_ba;
+ 	u16 start_idx;
+-	u32 bitmap0;
+-	u32 bitmap1;
++	u64 bitmap;
+ 	u32 rate_n_flags;
++#define IWL_AGG_OFF 0
++#define IWL_AGG_ON 1
++#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
++#define IWL_EMPTYING_HW_QUEUE_DELBA 3
++	u8 state;
+ };
+-#endif /* CONFIG_IWL4965_HT_AGG */
++
+ #endif /* CONFIG_IWL4965_HT */
+ 
+ struct iwl4965_tid_data {
+ 	u16 seq_number;
++	u16 tfds_in_queue;
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ 	struct iwl4965_ht_agg agg;
+-#endif	/* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ };
+ 
+ struct iwl4965_hw_key {
+ 	enum ieee80211_key_alg alg;
+ 	int keylen;
++	u8 keyidx;
++	struct ieee80211_key_conf *conf;
+ 	u8 key[32];
+ };
+ 
+@@ -508,8 +499,6 @@ struct iwl_ht_info {
+ };
+ #endif				/*CONFIG_IWL4965_HT */
+ 
+-#ifdef CONFIG_IWL4965_QOS
+-
+ union iwl4965_qos_capabity {
+ 	struct {
+ 		u8 edca_count:4;	/* bit 0-3 */
+@@ -537,7 +526,6 @@ struct iwl4965_qos_info {
+ 	union iwl4965_qos_capabity qos_cap;
+ 	struct iwl4965_qosparam_cmd def_qos_parm;
+ };
+-#endif /*CONFIG_IWL4965_QOS */
+ 
+ #define STA_PS_STATUS_WAKE             0
+ #define STA_PS_STATUS_SLEEP            1
+@@ -579,30 +567,29 @@ struct iwl4965_ibss_seq {
+ };
+ 
+ /**
+- * struct iwl4965_driver_hw_info
++ * struct iwl_hw_params
+  * @max_txq_num: Max # Tx queues supported
+- * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
+  * @tx_cmd_len: Size of Tx command (but not including frame itself)
++ * @tx_ant_num: Number of TX antennas
+  * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
+  * @rx_buffer_size:
+  * @max_rxq_log: Log-base-2 of max_rxq_size
+  * @max_stations:
+  * @bcast_sta_id:
+- * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status
+- * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status
+  */
+-struct iwl4965_driver_hw_info {
++struct iwl_hw_params {
+ 	u16 max_txq_num;
+-	u16 ac_queue_count;
+ 	u16 tx_cmd_len;
++	u8  tx_chains_num;
++	u8  rx_chains_num;
++	u8  valid_tx_ant;
++	u8  valid_rx_ant;
+ 	u16 max_rxq_size;
++	u16 max_rxq_log;
+ 	u32 rx_buf_size;
+ 	u32 max_pkt_size;
+-	u16 max_rxq_log;
+ 	u8  max_stations;
+ 	u8  bcast_sta_id;
+-	void *shared_virt;
+-	dma_addr_t shared_phys;
+ };
+ 
+ #define HT_SHORT_GI_20MHZ_ONLY          (1 << 0)
+@@ -626,62 +613,49 @@ struct iwl4965_driver_hw_info {
+  *
+  *****************************************************************************/
+ struct iwl4965_addsta_cmd;
+-extern int iwl4965_send_add_station(struct iwl4965_priv *priv,
++extern int iwl4965_send_add_station(struct iwl_priv *priv,
+ 				struct iwl4965_addsta_cmd *sta, u8 flags);
+-extern u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
++extern u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
+ 			  int is_ap, u8 flags, void *ht_data);
+-extern int iwl4965_is_network_packet(struct iwl4965_priv *priv,
++extern int iwl4965_is_network_packet(struct iwl_priv *priv,
+ 				 struct ieee80211_hdr *header);
+-extern int iwl4965_power_init_handle(struct iwl4965_priv *priv);
+-extern int iwl4965_eeprom_init(struct iwl4965_priv *priv);
+-#ifdef CONFIG_IWL4965_DEBUG
+-extern void iwl4965_report_frame(struct iwl4965_priv *priv,
+-			     struct iwl4965_rx_packet *pkt,
+-			     struct ieee80211_hdr *header, int group100);
+-#else
+-static inline void iwl4965_report_frame(struct iwl4965_priv *priv,
+-				    struct iwl4965_rx_packet *pkt,
+-				    struct ieee80211_hdr *header,
+-				    int group100) {}
+-#endif
+-extern void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv,
++extern int iwl4965_power_init_handle(struct iwl_priv *priv);
++extern void iwl4965_handle_data_packet_monitor(struct iwl_priv *priv,
+ 					   struct iwl4965_rx_mem_buffer *rxb,
+ 					   void *data, short len,
+ 					   struct ieee80211_rx_status *stats,
+ 					   u16 phy_flags);
+-extern int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv,
++extern int iwl4965_is_duplicate_packet(struct iwl_priv *priv,
+ 				       struct ieee80211_hdr *header);
+-extern int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv);
+-extern void iwl4965_rx_queue_reset(struct iwl4965_priv *priv,
++extern int iwl4965_rx_queue_alloc(struct iwl_priv *priv);
++extern void iwl4965_rx_queue_reset(struct iwl_priv *priv,
+ 			       struct iwl4965_rx_queue *rxq);
+ extern int iwl4965_calc_db_from_ratio(int sig_ratio);
+ extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm);
+-extern int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
++extern int iwl4965_tx_queue_init(struct iwl_priv *priv,
+ 			     struct iwl4965_tx_queue *txq, int count, u32 id);
+ extern void iwl4965_rx_replenish(void *data);
+-extern void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq);
+-extern int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len,
+-			    const void *data);
+-extern int __must_check iwl4965_send_cmd(struct iwl4965_priv *priv,
+-		struct iwl4965_host_cmd *cmd);
+-extern unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
++extern void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
++extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
+ 					struct ieee80211_hdr *hdr,
+ 					const u8 *dest, int left);
+-extern int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv,
++extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv,
+ 					 struct iwl4965_rx_queue *q);
+-extern int iwl4965_send_statistics_request(struct iwl4965_priv *priv);
+-extern void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
++extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
+ 				   u32 decrypt_res,
+ 				   struct ieee80211_rx_status *stats);
+ extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr);
++int iwl4965_init_geos(struct iwl_priv *priv);
++void iwl4965_free_geos(struct iwl_priv *priv);
+ 
+ extern const u8 iwl4965_broadcast_addr[ETH_ALEN];
++int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+ 
+ /*
+  * Currently used by iwl-3945-rs... look at restructuring so that it doesn't
+  * call this... todo... fix that.
+ */
+-extern u8 iwl4965_sync_station(struct iwl4965_priv *priv, int sta_id,
++extern u8 iwl4965_sync_station(struct iwl_priv *priv, int sta_id,
+ 			   u16 tx_rate, u8 flags);
+ 
+ /******************************************************************************
+@@ -700,36 +674,36 @@ extern u8 iwl4965_sync_station(struct iwl4965_priv *priv, int sta_id,
+  * iwl4965_mac_     <-- mac80211 callback
+  *
+  ****************************************************************************/
+-extern void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_nic_init(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_nic_reset(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *tfd,
++extern void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv);
++extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
++extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
++extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
++extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
++extern int iwl4965_hw_nic_init(struct iwl_priv *priv);
++extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
++extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv);
++extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
++extern int iwl4965_hw_nic_reset(struct iwl_priv *priv);
++extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
+ 					dma_addr_t addr, u16 len);
+-extern int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq);
+-extern int iwl4965_hw_get_temperature(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv,
++extern int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
++extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
++extern int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
+ 				struct iwl4965_tx_queue *txq);
+-extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
++extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+ 				 struct iwl4965_frame *frame, u8 rate);
+-extern int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+-				     struct iwl4965_cmd *cmd,
++extern int iwl4965_hw_get_rx_read(struct iwl_priv *priv);
++extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
++				     struct iwl_cmd *cmd,
+ 				     struct ieee80211_tx_control *ctrl,
+ 				     struct ieee80211_hdr *hdr,
+ 				     int sta_id, int tx_id);
+-extern int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power);
+-extern void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv,
++extern int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv);
++extern int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
++extern void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
+ 				 struct iwl4965_rx_mem_buffer *rxb);
+-extern void iwl4965_disable_events(struct iwl4965_priv *priv);
+-extern int iwl4965_get_temperature(const struct iwl4965_priv *priv);
++extern void iwl4965_disable_events(struct iwl_priv *priv);
++extern int iwl4965_get_temperature(const struct iwl_priv *priv);
+ 
+ /**
+  * iwl4965_hw_find_station - Find station id for a given BSSID
+@@ -739,54 +713,51 @@ extern int iwl4965_get_temperature(const struct iwl4965_priv *priv);
+  * not yet been merged into a single common layer for managing the
+  * station tables.
+  */
+-extern u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *bssid);
++extern u8 iwl4965_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
+ 
+-extern int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel);
+-extern int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index);
+-
+-struct iwl4965_priv;
++extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel);
++extern int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
++extern int iwl4965_queue_space(const struct iwl4965_queue *q);
++struct iwl_priv;
+ 
++extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio);
+ /*
+  * Forward declare iwl-4965.c functions for iwl-base.c
+  */
+-extern int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv);
+-
+-extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
++extern int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
+ 					  struct iwl4965_tx_queue *txq,
+ 					  u16 byte_cnt);
+-extern void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr,
++extern void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr,
+ 				int is_ap);
+-extern void iwl4965_set_rxon_chain(struct iwl4965_priv *priv);
+-extern int iwl4965_alive_notify(struct iwl4965_priv *priv);
+-extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode);
+-extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv);
+-extern void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags,
++extern void iwl4965_set_rxon_chain(struct iwl_priv *priv);
++extern int iwl4965_alive_notify(struct iwl_priv *priv);
++extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode);
++extern void iwl4965_chain_noise_reset(struct iwl_priv *priv);
++extern void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags,
+ 				     u8 force);
+-extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode,
+-				u16 channel,
+-				const struct iwl4965_eeprom_channel *eeprom_ch,
+-				u8 fat_extension_channel);
+-extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv);
++extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv);
++extern void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv,
++					 u32 rate_n_flags,
++					 struct ieee80211_tx_control *control);
+ 
+ #ifdef CONFIG_IWL4965_HT
+-extern void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info,
+-					int mode);
+-extern void iwl4965_set_rxon_ht(struct iwl4965_priv *priv,
+-				struct iwl_ht_info *ht_info);
+-extern void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
++void iwl4965_init_ht_hw_capab(struct iwl_priv *priv,
++			      struct ieee80211_ht_info *ht_info,
++			      enum ieee80211_band band);
++void iwl4965_set_rxon_ht(struct iwl_priv *priv,
++			 struct iwl_ht_info *ht_info);
++void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
+ 				struct ieee80211_ht_info *sta_ht_inf);
+-extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
++int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+ 				    enum ieee80211_ampdu_mlme_action action,
+-				    const u8 *addr, u16 tid, u16 ssn);
+-#ifdef CONFIG_IWL4965_HT_AGG
+-extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da,
+-				   u16 tid, u16 *start_seq_num);
+-extern int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da,
+-				  u16 tid, int generator);
+-extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid);
+-extern void iwl4965_tl_get_stats(struct iwl4965_priv *priv,
+-				struct ieee80211_hdr *hdr);
+-#endif /* CONFIG_IWL4965_HT_AGG */
++				    const u8 *addr, u16 tid, u16 *ssn);
++int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
++					u8 tid, int txq_id);
++#else
++static inline void iwl4965_init_ht_hw_capab(struct iwl_priv *priv,
++					    struct ieee80211_ht_info *ht_info,
++					    enum ieee80211_band band) {}
++
+ #endif /*CONFIG_IWL4965_HT */
+ /* Structures, enum, and defines specific to the 4965 */
+ 
+@@ -798,18 +769,6 @@ struct iwl4965_kw {
+ 	size_t size;
+ };
+ 
+-#define TID_QUEUE_CELL_SPACING 50	/*mS */
+-#define TID_QUEUE_MAX_SIZE     20
+-#define TID_ROUND_VALUE        5	/* mS */
+-#define TID_MAX_LOAD_COUNT     8
+-
+-#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
+-#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
+-
+-#define TID_ALL_ENABLED		0x7f
+-#define TID_ALL_SPECIFIED       0xff
+-#define TID_AGG_TPT_THREHOLD    0x0
+-
+ #define IWL_CHANNEL_WIDTH_20MHZ   0
+ #define IWL_CHANNEL_WIDTH_40MHZ   1
+ 
+@@ -823,48 +782,17 @@ struct iwl4965_kw {
+ #define IWL_OPERATION_MODE_MIXED    2
+ #define IWL_OPERATION_MODE_20MHZ    3
+ 
+-#define IWL_EXT_CHANNEL_OFFSET_AUTO   0
+-#define IWL_EXT_CHANNEL_OFFSET_ABOVE  1
+-#define IWL_EXT_CHANNEL_OFFSET_       2
+-#define IWL_EXT_CHANNEL_OFFSET_BELOW  3
+-#define IWL_EXT_CHANNEL_OFFSET_MAX    4
++#define IWL_EXT_CHANNEL_OFFSET_NONE      0
++#define IWL_EXT_CHANNEL_OFFSET_ABOVE     1
++#define IWL_EXT_CHANNEL_OFFSET_RESERVE1  2
++#define IWL_EXT_CHANNEL_OFFSET_BELOW     3
+ 
+ #define NRG_NUM_PREV_STAT_L     20
+ #define NUM_RX_CHAINS           (3)
+ 
+ #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
+ 
+-struct iwl4965_traffic_load {
+-	unsigned long time_stamp;
+-	u32 packet_count[TID_QUEUE_MAX_SIZE];
+-	u8 queue_count;
+-	u8 head;
+-	u32 total;
+-};
+-
+-#ifdef CONFIG_IWL4965_HT_AGG
+-/**
+- * struct iwl4965_agg_control
+- * @requested_ba: bit map of tids requesting aggregation/block-ack
+- * @granted_ba: bit map of tids granted aggregation/block-ack
+- */
+-struct iwl4965_agg_control {
+-	unsigned long next_retry;
+-	u32 wait_for_agg_status;
+-	u32 tid_retry;
+-	u32 requested_ba;
+-	u32 granted_ba;
+-	u8 auto_agg;
+-	u32 tid_traffic_load_threshold;
+-	u32 ba_timeout;
+-	struct iwl4965_traffic_load traffic_load[TID_MAX_LOAD_COUNT];
+-};
+-#endif				/*CONFIG_IWL4965_HT_AGG */
+-
+ struct iwl4965_lq_mngr {
+-#ifdef CONFIG_IWL4965_HT_AGG
+-	struct iwl4965_agg_control agg_ctrl;
+-#endif
+ 	spinlock_t lock;
+ 	s32 max_window_size;
+ 	s32 *expected_tpt;
+@@ -877,7 +805,6 @@ struct iwl4965_lq_mngr {
+ 	u8 lq_ready;
+ };
+ 
+-
+ /* Sensitivity and chain noise calibration */
+ #define INTERFERENCE_DATA_AVAILABLE	__constant_cpu_to_le32(1)
+ #define INITIALIZATION_VALUE		0xFFFF
+@@ -1014,25 +941,28 @@ enum {
+ 
+ #endif
+ 
+-struct iwl4965_priv {
++#define IWL_MAX_NUM_QUEUES	20 /* FIXME: do dynamic allocation */
++
++struct iwl_priv {
+ 
+ 	/* ieee device used by generic ieee processing code */
+ 	struct ieee80211_hw *hw;
+ 	struct ieee80211_channel *ieee_channels;
+ 	struct ieee80211_rate *ieee_rates;
++	struct iwl_cfg *cfg;
+ 
+ 	/* temporary frame storage list */
+ 	struct list_head free_frames;
+ 	int frames_count;
+ 
+-	u8 phymode;
++	enum ieee80211_band band;
+ 	int alloc_rxb_skb;
+ 	bool add_radiotap;
+ 
+-	void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv,
++	void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
+ 				       struct iwl4965_rx_mem_buffer *rxb);
+ 
+-	const struct ieee80211_hw_mode *modes;
++	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+ 
+ #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
+ 	/* spectrum measurement report caching */
+@@ -1044,7 +974,7 @@ struct iwl4965_priv {
+ 
+ 	/* we allocate array of iwl4965_channel_info for NIC's valid channels.
+ 	 *    Access via channel # using indirect index array */
+-	struct iwl4965_channel_info *channel_info;	/* channel info array */
++	struct iwl_channel_info *channel_info;	/* channel info array */
+ 	u8 channel_count;	/* # of channels */
+ 
+ 	/* each calibration channel group in the EEPROM has a derived
+@@ -1104,18 +1034,21 @@ struct iwl4965_priv {
+ 	 * 4965's initialize alive response contains some calibration data. */
+ 	struct iwl4965_init_alive_resp card_alive_init;
+ 	struct iwl4965_alive_resp card_alive;
++#ifdef CONFIG_IWLWIFI_RFKILL
++	struct iwl_rfkill_mngr rfkill_mngr;
++#endif
+ 
+-#ifdef LED
+-	/* LED related variables */
+-	struct iwl4965_activity_blink activity;
+-	unsigned long led_packets;
+-	int led_state;
++#ifdef CONFIG_IWLWIFI_LEDS
++	struct iwl4965_led led[IWL_LED_TRG_MAX];
++	unsigned long last_blink_time;
++	u8 last_blink_rate;
++	u8 allow_blinking;
++	u64 led_tpt;
+ #endif
+ 
+ 	u16 active_rate;
+ 	u16 active_rate_basic;
+ 
+-	u8 call_post_assoc_from_beacon;
+ 	u8 assoc_station_added;
+ 	u8 use_ant_b_for_management_frame;	/* Tx antenna selection */
+ 	u8 valid_antenna;	/* Bit mask of antennas actually connected */
+@@ -1150,11 +1083,16 @@ struct iwl4965_priv {
+ 	u32 scd_base_addr;	/* scheduler sram base address */
+ 
+ 	unsigned long status;
+-	u32 config;
+ 
+ 	int last_rx_rssi;	/* From Rx packet statisitics */
+ 	int last_rx_noise;	/* From beacon statistics */
+ 
++	/* counts mgmt, ctl, and data packets */
++	struct traffic_stats {
++		u32 cnt;
++		u64 bytes;
++	} tx_stats[3], rx_stats[3];
++
+ 	struct iwl4965_power_mgr power_data;
+ 
+ 	struct iwl4965_notif_statistics statistics;
+@@ -1175,12 +1113,15 @@ struct iwl4965_priv {
+ 	spinlock_t sta_lock;
+ 	int num_stations;
+ 	struct iwl4965_station_entry stations[IWL_STATION_COUNT];
++	struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
++	u8 default_wep_key;
++	u8 key_mapping_key;
++	unsigned long ucode_key_table;
+ 
+ 	/* Indication if ieee80211_ops->open has been called */
+-	int is_open;
++	u8 is_open;
+ 
+ 	u8 mac80211_registered;
+-	int is_abg;
+ 
+ 	u32 notif_missed_beacons;
+ 
+@@ -1199,26 +1140,28 @@ struct iwl4965_priv {
+ 	/* eeprom */
+ 	struct iwl4965_eeprom eeprom;
+ 
+-	int iw_mode;
++	enum ieee80211_if_types iw_mode;
+ 
+ 	struct sk_buff *ibss_beacon;
+ 
+ 	/* Last Rx'd beacon timestamp */
+-	u32 timestamp0;
+-	u32 timestamp1;
++	u64 timestamp;
+ 	u16 beacon_int;
+-	struct iwl4965_driver_hw_info hw_setting;
+ 	struct ieee80211_vif *vif;
+ 
++	struct iwl_hw_params hw_params;
++	/* driver/uCode shared Tx Byte Counts and Rx status */
++	void *shared_virt;
++	/* Physical Pointer to Tx Byte Counts and Rx status */
++	dma_addr_t shared_phys;
++
+ 	/* Current association information needed to configure the
+ 	 * hardware */
+ 	u16 assoc_id;
+ 	u16 assoc_capability;
+ 	u8 ps_mode;
+ 
+-#ifdef CONFIG_IWL4965_QOS
+ 	struct iwl4965_qos_info qos_data;
+-#endif /*CONFIG_IWL4965_QOS */
+ 
+ 	struct workqueue_struct *workqueue;
+ 
+@@ -1253,71 +1196,68 @@ struct iwl4965_priv {
+ 	u32 pm_state[16];
+ #endif
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ 	/* debugging info */
+ 	u32 framecnt_to_us;
+ 	atomic_t restrict_refcnt;
+-#endif
++#ifdef CONFIG_IWLWIFI_DEBUGFS
++	/* debugfs */
++	struct iwl_debugfs *dbgfs;
++#endif /* CONFIG_IWLWIFI_DEBUGFS */
++#endif /* CONFIG_IWLWIFI_DEBUG */
+ 
+ 	struct work_struct txpower_work;
+ #ifdef CONFIG_IWL4965_SENSITIVITY
+ 	struct work_struct sensitivity_work;
+ #endif
+-	struct work_struct statistics_work;
+ 	struct timer_list statistics_periodic;
++}; /*iwl_priv */
+ 
+-#ifdef CONFIG_IWL4965_HT_AGG
+-	struct work_struct agg_work;
+-#endif
+-};				/*iwl4965_priv */
+-
+-static inline int iwl4965_is_associated(struct iwl4965_priv *priv)
++static inline int iwl_is_associated(struct iwl_priv *priv)
+ {
+ 	return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+ }
+ 
+-static inline int is_channel_valid(const struct iwl4965_channel_info *ch_info)
++static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
+ {
+ 	if (ch_info == NULL)
+ 		return 0;
+ 	return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
+ }
+ 
+-static inline int is_channel_narrow(const struct iwl4965_channel_info *ch_info)
++static inline int is_channel_narrow(const struct iwl_channel_info *ch_info)
+ {
+ 	return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0;
+ }
+ 
+-static inline int is_channel_radar(const struct iwl4965_channel_info *ch_info)
++static inline int is_channel_radar(const struct iwl_channel_info *ch_info)
+ {
+ 	return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
+ }
+ 
+-static inline u8 is_channel_a_band(const struct iwl4965_channel_info *ch_info)
++static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info)
+ {
+-	return ch_info->phymode == MODE_IEEE80211A;
++	return ch_info->band == IEEE80211_BAND_5GHZ;
+ }
+ 
+-static inline u8 is_channel_bg_band(const struct iwl4965_channel_info *ch_info)
++static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info)
+ {
+-	return ((ch_info->phymode == MODE_IEEE80211B) ||
+-		(ch_info->phymode == MODE_IEEE80211G));
++	return ch_info->band == IEEE80211_BAND_2GHZ;
+ }
+ 
+-static inline int is_channel_passive(const struct iwl4965_channel_info *ch)
++static inline int is_channel_passive(const struct iwl_channel_info *ch)
+ {
+ 	return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
+ }
+ 
+-static inline int is_channel_ibss(const struct iwl4965_channel_info *ch)
++static inline int is_channel_ibss(const struct iwl_channel_info *ch)
+ {
+ 	return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
+ }
+ 
+-extern const struct iwl4965_channel_info *iwl4965_get_channel_info(
+-	const struct iwl4965_priv *priv, int phymode, u16 channel);
++extern const struct iwl_channel_info *iwl_get_channel_info(
++	const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
+ 
+-/* Requires full declaration of iwl4965_priv before including */
+-#include "iwl-4965-io.h"
++/* Requires full declaration of iwl_priv before including */
+ 
+ #endif				/* __iwl4965_4965_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
+new file mode 100644
+index 0000000..2dfd982
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-core.c
+@@ -0,0 +1,292 @@
++/******************************************************************************
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 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:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *****************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <net/mac80211.h>
++
++struct iwl_priv; /* FIXME: remove */
++#include "iwl-debug.h"
++#include "iwl-eeprom.h"
++#include "iwl-4965.h" /* FIXME: remove */
++#include "iwl-core.h"
++#include "iwl-rfkill.h"
++
++
++MODULE_DESCRIPTION("iwl core");
++MODULE_VERSION(IWLWIFI_VERSION);
++MODULE_AUTHOR(DRV_COPYRIGHT);
++MODULE_LICENSE("GPL");
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++u32 iwl_debug_level;
++EXPORT_SYMBOL(iwl_debug_level);
++#endif
++
++/* This function both allocates and initializes hw and priv. */
++struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
++		struct ieee80211_ops *hw_ops)
++{
++	struct iwl_priv *priv;
++
++	/* mac80211 allocates memory for this device instance, including
++	 *   space for this driver's private structure */
++	struct ieee80211_hw *hw =
++		ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops);
++	if (hw == NULL) {
++		IWL_ERROR("Can not allocate network device\n");
++		goto out;
++	}
++
++	priv = hw->priv;
++	priv->hw = hw;
++
++out:
++	return hw;
++}
++EXPORT_SYMBOL(iwl_alloc_all);
++
++/**
++ * iwlcore_clear_stations_table - Clear the driver's station table
++ *
++ * NOTE:  This does not clear or otherwise alter the device's station table.
++ */
++void iwlcore_clear_stations_table(struct iwl_priv *priv)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++
++	priv->num_stations = 0;
++	memset(priv->stations, 0, sizeof(priv->stations));
++
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++}
++EXPORT_SYMBOL(iwlcore_clear_stations_table);
++
++void iwlcore_reset_qos(struct iwl_priv *priv)
++{
++	u16 cw_min = 15;
++	u16 cw_max = 1023;
++	u8 aifs = 2;
++	u8 is_legacy = 0;
++	unsigned long flags;
++	int i;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->qos_data.qos_active = 0;
++
++	if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
++		if (priv->qos_data.qos_enable)
++			priv->qos_data.qos_active = 1;
++		if (!(priv->active_rate & 0xfff0)) {
++			cw_min = 31;
++			is_legacy = 1;
++		}
++	} else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
++		if (priv->qos_data.qos_enable)
++			priv->qos_data.qos_active = 1;
++	} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
++		cw_min = 31;
++		is_legacy = 1;
++	}
++
++	if (priv->qos_data.qos_active)
++		aifs = 3;
++
++	priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
++	priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
++	priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
++	priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
++	priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
++
++	if (priv->qos_data.qos_active) {
++		i = 1;
++		priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
++		priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
++		priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
++		priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
++		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++
++		i = 2;
++		priv->qos_data.def_qos_parm.ac[i].cw_min =
++			cpu_to_le16((cw_min + 1) / 2 - 1);
++		priv->qos_data.def_qos_parm.ac[i].cw_max =
++			cpu_to_le16(cw_max);
++		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
++		if (is_legacy)
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(6016);
++		else
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(3008);
++		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++
++		i = 3;
++		priv->qos_data.def_qos_parm.ac[i].cw_min =
++			cpu_to_le16((cw_min + 1) / 4 - 1);
++		priv->qos_data.def_qos_parm.ac[i].cw_max =
++			cpu_to_le16((cw_max + 1) / 2 - 1);
++		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
++		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++		if (is_legacy)
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(3264);
++		else
++			priv->qos_data.def_qos_parm.ac[i].edca_txop =
++				cpu_to_le16(1504);
++	} else {
++		for (i = 1; i < 4; i++) {
++			priv->qos_data.def_qos_parm.ac[i].cw_min =
++				cpu_to_le16(cw_min);
++			priv->qos_data.def_qos_parm.ac[i].cw_max =
++				cpu_to_le16(cw_max);
++			priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
++			priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
++			priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++		}
++	}
++	IWL_DEBUG_QOS("set QoS to default \n");
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++}
++EXPORT_SYMBOL(iwlcore_reset_qos);
++
++/**
++ * iwlcore_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
++
++ * 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
++ */
++int iwlcore_set_rxon_channel(struct iwl_priv *priv,
++				enum ieee80211_band band,
++				u16 channel)
++{
++	if (!iwl_get_channel_info(priv, band, channel)) {
++		IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
++			       channel, band);
++		return -EINVAL;
++	}
++
++	if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
++	    (priv->band == band))
++		return 0;
++
++	priv->staging_rxon.channel = cpu_to_le16(channel);
++	if (band == IEEE80211_BAND_5GHZ)
++		priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
++	else
++		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
++
++	priv->band = band;
++
++	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
++
++	return 0;
++}
++EXPORT_SYMBOL(iwlcore_set_rxon_channel);
++
++static void iwlcore_init_hw(struct iwl_priv *priv)
++{
++	struct ieee80211_hw *hw = priv->hw;
++	hw->rate_control_algorithm = "iwl-4965-rs";
++
++	/* Tell mac80211 and its clients (e.g. Wireless Extensions)
++	 *	 the range of signal quality values that we'll provide.
++	 * Negative values for level/noise indicate that we'll provide dBm.
++	 * For WE, at least, non-0 values here *enable* display of values
++	 *	 in app (iwconfig). */
++	hw->max_rssi = -20; /* signal level, negative indicates dBm */
++	hw->max_noise = -20;	/* noise level, negative indicates dBm */
++	hw->max_signal = 100;	/* link quality indication (%) */
++
++	/* Tell mac80211 our Tx characteristics */
++	hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
++
++	/* Default value; 4 EDCA QOS priorities */
++	hw->queues = 4;
++#ifdef CONFIG_IWL4965_HT
++	/* Enhanced value; more queues, to support 11n aggregation */
++	hw->queues = 16;
++#endif /* CONFIG_IWL4965_HT */
++}
++
++int iwl_setup(struct iwl_priv *priv)
++{
++	int ret = 0;
++	iwlcore_init_hw(priv);
++	ret = priv->cfg->ops->lib->init_drv(priv);
++	return ret;
++}
++EXPORT_SYMBOL(iwl_setup);
++
++/* Low level driver call this function to update iwlcore with
++ * driver status.
++ */
++int iwlcore_low_level_notify(struct iwl_priv *priv,
++			      enum iwlcore_card_notify notify)
++{
++	int ret;
++	switch (notify) {
++	case IWLCORE_INIT_EVT:
++		ret = iwl_rfkill_init(priv);
++		if (ret)
++			IWL_ERROR("Unable to initialize RFKILL system. "
++				  "Ignoring error: %d\n", ret);
++		break;
++	case IWLCORE_START_EVT:
++		break;
++	case IWLCORE_STOP_EVT:
++		break;
++	case IWLCORE_REMOVE_EVT:
++		iwl_rfkill_unregister(priv);
++		break;
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL(iwlcore_low_level_notify);
++
++int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
++{
++	u32 stat_flags = 0;
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_STATISTICS_CMD,
++		.meta.flags = flags,
++		.len = sizeof(stat_flags),
++		.data = (u8 *) &stat_flags,
++	};
++	return iwl_send_cmd(priv, &cmd);
++}
++EXPORT_SYMBOL(iwl_send_statistics_request);
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
+new file mode 100644
+index 0000000..7193d97
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-core.h
+@@ -0,0 +1,246 @@
++/******************************************************************************
++ *
++ * 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 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:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 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_core_h__
++#define __iwl_core_h__
++
++/************************
++ * forward declarations *
++ ************************/
++struct iwl_host_cmd;
++struct iwl_cmd;
++
++
++#define IWLWIFI_VERSION "1.2.26k"
++#define DRV_COPYRIGHT	"Copyright(c) 2003-2008 Intel Corporation"
++
++#define IWL_PCI_DEVICE(dev, subdev, cfg) \
++	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
++	.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
++	.driver_data = (kernel_ulong_t)&(cfg)
++
++#define IWL_SKU_G       0x1
++#define IWL_SKU_A       0x2
++#define IWL_SKU_N       0x8
++
++struct iwl_hcmd_ops {
++	int (*rxon_assoc)(struct iwl_priv *priv);
++};
++struct iwl_hcmd_utils_ops {
++	int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
++};
++
++struct iwl_lib_ops {
++	/* iwlwifi driver (priv) init */
++	int (*init_drv)(struct iwl_priv *priv);
++	/* set hw dependant perameters */
++	int (*set_hw_params)(struct iwl_priv *priv);
++
++	void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
++					struct iwl4965_tx_queue *txq,
++					u16 byte_cnt);
++	/* nic init */
++	int (*hw_nic_init)(struct iwl_priv *priv);
++	/* alive notification */
++	int (*alive_notify)(struct iwl_priv *priv);
++	/* check validity of rtc data address */
++	int (*is_valid_rtc_data_addr)(u32 addr);
++	/* 1st ucode load */
++	int (*load_ucode)(struct iwl_priv *priv);
++	/* rfkill */
++	void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio);
++	/* eeprom operations (as defined in iwl-eeprom.h) */
++	struct iwl_eeprom_ops eeprom_ops;
++};
++
++struct iwl_ops {
++	const struct iwl_lib_ops *lib;
++	const struct iwl_hcmd_ops *hcmd;
++	const struct iwl_hcmd_utils_ops *utils;
++};
++
++struct iwl_mod_params {
++	int disable;		/* def: 0 = enable radio */
++	int sw_crypto;		/* def: 0 = using hardware encryption */
++	int debug;		/* def: 0 = minimal debug log messages */
++	int disable_hw_scan;	/* def: 0 = use h/w scan */
++	int num_of_queues;	/* def: HW dependent */
++	int enable_qos;		/* def: 1 = use quality of service */
++	int amsdu_size_8K;	/* def: 1 = enable 8K amsdu size */
++	int antenna;  		/* def: 0 = both antennas (use diversity) */
++};
++
++struct iwl_cfg {
++	const char *name;
++	const char *fw_name;
++	unsigned int sku;
++	const struct iwl_ops *ops;
++	const struct iwl_mod_params *mod_params;
++};
++
++/***************************
++ *   L i b                 *
++ ***************************/
++
++struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
++		struct ieee80211_ops *hw_ops);
++
++void iwlcore_clear_stations_table(struct iwl_priv *priv);
++void iwlcore_reset_qos(struct iwl_priv *priv);
++int iwlcore_set_rxon_channel(struct iwl_priv *priv,
++				enum ieee80211_band band,
++				u16 channel);
++
++int iwl_setup(struct iwl_priv *priv);
++
++/*****************************************************
++ *   S e n d i n g     H o s t     C o m m a n d s   *
++ *****************************************************/
++
++const char *get_cmd_string(u8 cmd);
++int __must_check iwl_send_cmd_sync(struct iwl_priv *priv,
++				   struct iwl_host_cmd *cmd);
++int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
++int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id,
++				  u16 len, const void *data);
++int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
++			   const void *data,
++			   int (*callback)(struct iwl_priv *priv,
++					   struct iwl_cmd *cmd,
++					   struct sk_buff *skb));
++/*************** DRIVER STATUS FUNCTIONS   *****/
++
++#define STATUS_HCMD_ACTIVE	0	/* host command in progress */
++#define STATUS_HCMD_SYNC_ACTIVE	1	/* sync host command in progress */
++#define STATUS_INT_ENABLED	2
++#define STATUS_RF_KILL_HW	3
++#define STATUS_RF_KILL_SW	4
++#define STATUS_INIT		5
++#define STATUS_ALIVE		6
++#define STATUS_READY		7
++#define STATUS_TEMPERATURE	8
++#define STATUS_GEO_CONFIGURED	9
++#define STATUS_EXIT_PENDING	10
++#define STATUS_IN_SUSPEND	11
++#define STATUS_STATISTICS	12
++#define STATUS_SCANNING		13
++#define STATUS_SCAN_ABORTING	14
++#define STATUS_SCAN_HW		15
++#define STATUS_POWER_PMI	16
++#define STATUS_FW_ERROR		17
++#define STATUS_CONF_PENDING	18
++
++
++static inline int iwl_is_ready(struct iwl_priv *priv)
++{
++	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
++	 * set but EXIT_PENDING is not */
++	return test_bit(STATUS_READY, &priv->status) &&
++	       test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
++	       !test_bit(STATUS_EXIT_PENDING, &priv->status);
++}
++
++static inline int iwl_is_alive(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_ALIVE, &priv->status);
++}
++
++static inline int iwl_is_init(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_INIT, &priv->status);
++}
++
++static inline int iwl_is_rfkill(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++	       test_bit(STATUS_RF_KILL_SW, &priv->status);
++}
++
++static inline int iwl_is_ready_rf(struct iwl_priv *priv)
++{
++
++	if (iwl_is_rfkill(priv))
++		return 0;
++
++	return iwl_is_ready(priv);
++}
++
++
++enum iwlcore_card_notify {
++	IWLCORE_INIT_EVT = 0,
++	IWLCORE_START_EVT = 1,
++	IWLCORE_STOP_EVT = 2,
++	IWLCORE_REMOVE_EVT = 3,
++};
++
++int iwlcore_low_level_notify(struct iwl_priv *priv,
++			     enum iwlcore_card_notify notify);
++extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags);
++int iwl_send_lq_cmd(struct iwl_priv *priv,
++		    struct iwl_link_quality_cmd *lq, u8 flags);
++
++static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
++{
++	return priv->cfg->ops->hcmd->rxon_assoc(priv);
++}
++
++#endif /* __iwl_core_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
+new file mode 100644
+index 0000000..1272579
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
+@@ -0,0 +1,265 @@
++/******************************************************************************
++ *
++ * This file is provided under a dual BSD/GPLv2 license.  When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2005 - 2008 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:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 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.
++ *
++ *****************************************************************************/
++/*=== CSR (control and status registers) ===*/
++#define CSR_BASE    (0x000)
++
++#define CSR_HW_IF_CONFIG_REG    (CSR_BASE+0x000) /* hardware interface config */
++#define CSR_INT_COALESCING      (CSR_BASE+0x004) /* accum ints, 32-usec units */
++#define CSR_INT                 (CSR_BASE+0x008) /* host interrupt status/ack */
++#define CSR_INT_MASK            (CSR_BASE+0x00c) /* host interrupt enable */
++#define CSR_FH_INT_STATUS       (CSR_BASE+0x010) /* busmaster int status/ack*/
++#define CSR_GPIO_IN             (CSR_BASE+0x018) /* read external chip pins */
++#define CSR_RESET               (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
++#define CSR_GP_CNTRL            (CSR_BASE+0x024)
++
++/*
++ * Hardware revision info
++ * Bit fields:
++ * 31-8:  Reserved
++ *  7-4:  Type of device:  0x0 = 4965, 0xd = 3945
++ *  3-2:  Revision step:  0 = A, 1 = B, 2 = C, 3 = D
++ *  1-0:  "Dash" value, as in A-1, etc.
++ *
++ * NOTE:  Revision step affects calculation of CCK txpower for 4965.
++ */
++#define CSR_HW_REV              (CSR_BASE+0x028)
++
++/* EEPROM reads */
++#define CSR_EEPROM_REG          (CSR_BASE+0x02c)
++#define CSR_EEPROM_GP           (CSR_BASE+0x030)
++#define CSR_GP_UCODE		(CSR_BASE+0x044)
++#define CSR_UCODE_DRV_GP1       (CSR_BASE+0x054)
++#define CSR_UCODE_DRV_GP1_SET   (CSR_BASE+0x058)
++#define CSR_UCODE_DRV_GP1_CLR   (CSR_BASE+0x05c)
++#define CSR_UCODE_DRV_GP2       (CSR_BASE+0x060)
++#define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
++#define CSR_LED_REG             (CSR_BASE+0x094)
++
++/* Analog phase-lock-loop configuration (3945 only)
++ * Set bit 24. */
++#define CSR_ANA_PLL_CFG         (CSR_BASE+0x20c)
++/*
++ * Indicates hardware rev, to determine CCK backoff for txpower calculation.
++ * Bit fields:
++ *  3-2:  0 = A, 1 = B, 2 = C, 3 = D step
++ */
++#define CSR_HW_REV_WA_REG	(CSR_BASE+0x22C)
++
++/* Bits for CSR_HW_IF_CONFIG_REG */
++#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R	(0x00000010)
++#define CSR49_HW_IF_CONFIG_REG_MSK_BOARD_VER	(0x00000C00)
++#define CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI		(0x00000100)
++#define CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI	(0x00000200)
++
++#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB         (0x00000100)
++#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM         (0x00000200)
++#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC            (0x00000400)
++#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE         (0x00000800)
++#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A    (0x00000000)
++#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B    (0x00001000)
++
++#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM     (0x00200000)
++
++/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
++ * acknowledged (reset) by host writing "1" to flagged bits. */
++#define CSR_INT_BIT_FH_RX        (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
++#define CSR_INT_BIT_HW_ERR       (1 << 29) /* DMA hardware error FH_INT[31] */
++#define CSR_INT_BIT_DNLD         (1 << 28) /* uCode Download */
++#define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
++#define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
++#define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
++#define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
++#define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */
++#define CSR_INT_BIT_SW_RX        (1 << 3)  /* Rx, command responses, 3945 */
++#define CSR_INT_BIT_WAKEUP       (1 << 1)  /* NIC controller waking up (pwr mgmt) */
++#define CSR_INT_BIT_ALIVE        (1 << 0)  /* uCode interrupts once it initializes */
++
++#define CSR_INI_SET_MASK	(CSR_INT_BIT_FH_RX   | \
++				 CSR_INT_BIT_HW_ERR  | \
++				 CSR_INT_BIT_FH_TX   | \
++				 CSR_INT_BIT_SW_ERR  | \
++				 CSR_INT_BIT_RF_KILL | \
++				 CSR_INT_BIT_SW_RX   | \
++				 CSR_INT_BIT_WAKEUP  | \
++				 CSR_INT_BIT_ALIVE)
++
++/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
++#define CSR_FH_INT_BIT_ERR       (1 << 31) /* Error */
++#define CSR_FH_INT_BIT_HI_PRIOR  (1 << 30) /* High priority Rx, bypass coalescing */
++#define CSR39_FH_INT_BIT_RX_CHNL2  (1 << 18) /* Rx channel 2 (3945 only) */
++#define CSR_FH_INT_BIT_RX_CHNL1  (1 << 17) /* Rx channel 1 */
++#define CSR_FH_INT_BIT_RX_CHNL0  (1 << 16) /* Rx channel 0 */
++#define CSR39_FH_INT_BIT_TX_CHNL6  (1 << 6)  /* Tx channel 6 (3945 only) */
++#define CSR_FH_INT_BIT_TX_CHNL1  (1 << 1)  /* Tx channel 1 */
++#define CSR_FH_INT_BIT_TX_CHNL0  (1 << 0)  /* Tx channel 0 */
++
++#define CSR39_FH_INT_RX_MASK	(CSR_FH_INT_BIT_HI_PRIOR | \
++				 CSR39_FH_INT_BIT_RX_CHNL2 | \
++				 CSR_FH_INT_BIT_RX_CHNL1 | \
++				 CSR_FH_INT_BIT_RX_CHNL0)
++
++
++#define CSR39_FH_INT_TX_MASK	(CSR39_FH_INT_BIT_TX_CHNL6 | \
++				 CSR_FH_INT_BIT_TX_CHNL1 | \
++				 CSR_FH_INT_BIT_TX_CHNL0)
++
++#define CSR49_FH_INT_RX_MASK	(CSR_FH_INT_BIT_HI_PRIOR | \
++				 CSR_FH_INT_BIT_RX_CHNL1 | \
++				 CSR_FH_INT_BIT_RX_CHNL0)
++
++#define CSR49_FH_INT_TX_MASK	(CSR_FH_INT_BIT_TX_CHNL1 | \
++				 CSR_FH_INT_BIT_TX_CHNL0)
++
++
++/* RESET */
++#define CSR_RESET_REG_FLAG_NEVO_RESET                (0x00000001)
++#define CSR_RESET_REG_FLAG_FORCE_NMI                 (0x00000002)
++#define CSR_RESET_REG_FLAG_SW_RESET                  (0x00000080)
++#define CSR_RESET_REG_FLAG_MASTER_DISABLED           (0x00000100)
++#define CSR_RESET_REG_FLAG_STOP_MASTER               (0x00000200)
++
++/* GP (general purpose) CONTROL */
++#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY        (0x00000001)
++#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE              (0x00000004)
++#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ         (0x00000008)
++#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)
++
++#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN           (0x00000001)
++
++#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE         (0x07000000)
++#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE         (0x04000000)
++#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW          (0x08000000)
++
++
++/* EEPROM REG */
++#define CSR_EEPROM_REG_READ_VALID_MSK	(0x00000001)
++#define CSR_EEPROM_REG_BIT_CMD		(0x00000002)
++
++/* EEPROM GP */
++#define CSR_EEPROM_GP_VALID_MSK		(0x00000006)
++#define CSR_EEPROM_GP_BAD_SIGNATURE	(0x00000000)
++#define CSR_EEPROM_GP_IF_OWNER_MSK	(0x00000180)
++
++/* UCODE DRV GP */
++#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP             (0x00000001)
++#define CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)
++#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)
++#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)
++
++/* GPIO */
++#define CSR_GPIO_IN_BIT_AUX_POWER                   (0x00000200)
++#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC                (0x00000000)
++#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC		CSR_GPIO_IN_BIT_AUX_POWER
++
++/* GI Chicken Bits */
++#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
++#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)
++
++/* LED */
++#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
++#define CSR_LED_REG_TRUN_ON (0x78)
++#define CSR_LED_REG_TRUN_OFF (0x38)
++
++/*=== HBUS (Host-side Bus) ===*/
++#define HBUS_BASE	(0x400)
++/*
++ * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
++ * structures, error log, event log, verifying uCode load).
++ * First write to address register, then read from or write to data register
++ * to complete the job.  Once the address register is set up, accesses to
++ * data registers auto-increment the address by one dword.
++ * Bit usage for address registers (read or write):
++ *  0-31:  memory address within device
++ */
++#define HBUS_TARG_MEM_RADDR     (HBUS_BASE+0x00c)
++#define HBUS_TARG_MEM_WADDR     (HBUS_BASE+0x010)
++#define HBUS_TARG_MEM_WDAT      (HBUS_BASE+0x018)
++#define HBUS_TARG_MEM_RDAT      (HBUS_BASE+0x01c)
++
++/*
++ * Registers for accessing device's internal peripheral registers
++ * (e.g. SCD, BSM, etc.).  First write to address register,
++ * then read from or write to data register to complete the job.
++ * Bit usage for address registers (read or write):
++ *  0-15:  register address (offset) within device
++ * 24-25:  (# bytes - 1) to read or write (e.g. 3 for dword)
++ */
++#define HBUS_TARG_PRPH_WADDR    (HBUS_BASE+0x044)
++#define HBUS_TARG_PRPH_RADDR    (HBUS_BASE+0x048)
++#define HBUS_TARG_PRPH_WDAT     (HBUS_BASE+0x04c)
++#define HBUS_TARG_PRPH_RDAT     (HBUS_BASE+0x050)
++
++/*
++ * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
++ * Indicates index to next TFD that driver will fill (1 past latest filled).
++ * Bit usage:
++ *  0-7:  queue write index
++ * 11-8:  queue selector
++ */
++#define HBUS_TARG_WRPTR         (HBUS_BASE+0x060)
++#define HBUS_TARG_MBX_C         (HBUS_BASE+0x030)
++
++#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED         (0x00000004)
++
++
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
+new file mode 100644
+index 0000000..c60724c
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
+@@ -0,0 +1,197 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_debug_h__
++#define __iwl_debug_h__
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++extern u32 iwl_debug_level;
++#define IWL_DEBUG(level, fmt, args...) \
++do { if (iwl_debug_level & (level)) \
++  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
++	 in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
++
++#define IWL_DEBUG_LIMIT(level, fmt, args...) \
++do { if ((iwl_debug_level & (level)) && net_ratelimit()) \
++  printk(KERN_ERR DRV_NAME": %c %s " fmt, \
++	 in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
++
++static inline void iwl_print_hex_dump(int level, void *p, u32 len)
++{
++	if (!(iwl_debug_level & level))
++		return;
++
++	print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
++			p, len, 1);
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUGFS
++struct iwl_debugfs {
++	const char *name;
++	struct dentry *dir_drv;
++	struct dentry *dir_data;
++	struct dir_data_files{
++		struct dentry *file_sram;
++		struct dentry *file_stations;
++		struct dentry *file_rx_statistics;
++		struct dentry *file_tx_statistics;
++	} dbgfs_data_files;
++	u32 sram_offset;
++	u32 sram_len;
++};
++
++int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
++void iwl_dbgfs_unregister(struct iwl_priv *priv);
++#endif
++
++#else
++static inline void IWL_DEBUG(int level, const char *fmt, ...)
++{
++}
++static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
++{
++}
++static inline void iwl_print_hex_dump(int level, void *p, u32 len)
++{
++}
++#endif				/* CONFIG_IWLWIFI_DEBUG */
++
++
++
++#ifndef CONFIG_IWLWIFI_DEBUGFS
++static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
++{
++	return 0;
++}
++static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
++{
++}
++#endif				/* CONFIG_IWLWIFI_DEBUGFS */
++
++/*
++ * To use the debug system;
++ *
++ * If you are defining a new debug classification, simply add it to the #define
++ * list here in the form of:
++ *
++ * #define IWL_DL_xxxx VALUE
++ *
++ * shifting value to the left one bit from the previous entry.  xxxx should be
++ * the name of the classification (for example, WEP)
++ *
++ * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
++ * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
++ * to send output to that classification.
++ *
++ * To add your debug level to the list of levels seen when you perform
++ *
++ * % cat /proc/net/iwl/debug_level
++ *
++ * you simply need to add your entry to the iwl_debug_levels array.
++ *
++ * If you do not see debug_level in /proc/net/iwl then you do not have
++ * CONFIG_IWLWIFI_DEBUG defined in your kernel configuration
++ *
++ */
++
++#define IWL_DL_INFO          (1 << 0)
++#define IWL_DL_MAC80211      (1 << 1)
++#define IWL_DL_HOST_COMMAND  (1 << 2)
++#define IWL_DL_STATE         (1 << 3)
++
++#define IWL_DL_RADIO         (1 << 7)
++#define IWL_DL_POWER         (1 << 8)
++#define IWL_DL_TEMP          (1 << 9)
++
++#define IWL_DL_NOTIF         (1 << 10)
++#define IWL_DL_SCAN          (1 << 11)
++#define IWL_DL_ASSOC         (1 << 12)
++#define IWL_DL_DROP          (1 << 13)
++
++#define IWL_DL_TXPOWER       (1 << 14)
++
++#define IWL_DL_AP            (1 << 15)
++
++#define IWL_DL_FW            (1 << 16)
++#define IWL_DL_RF_KILL       (1 << 17)
++#define IWL_DL_FW_ERRORS     (1 << 18)
++
++#define IWL_DL_LED           (1 << 19)
++
++#define IWL_DL_RATE          (1 << 20)
++
++#define IWL_DL_CALIB         (1 << 21)
++#define IWL_DL_WEP           (1 << 22)
++#define IWL_DL_TX            (1 << 23)
++#define IWL_DL_RX            (1 << 24)
++#define IWL_DL_ISR           (1 << 25)
++#define IWL_DL_HT            (1 << 26)
++#define IWL_DL_IO            (1 << 27)
++#define IWL_DL_11H           (1 << 28)
++
++#define IWL_DL_STATS         (1 << 29)
++#define IWL_DL_TX_REPLY      (1 << 30)
++#define IWL_DL_QOS           (1 << 31)
++
++#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
++#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
++#define IWL_DEBUG_INFO(f, a...)    IWL_DEBUG(IWL_DL_INFO, f, ## a)
++
++#define IWL_DEBUG_MAC80211(f, a...)     IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
++#define IWL_DEBUG_TEMP(f, a...)   IWL_DEBUG(IWL_DL_TEMP, f, ## a)
++#define IWL_DEBUG_SCAN(f, a...)   IWL_DEBUG(IWL_DL_SCAN, f, ## a)
++#define IWL_DEBUG_RX(f, a...)     IWL_DEBUG(IWL_DL_RX, f, ## a)
++#define IWL_DEBUG_TX(f, a...)     IWL_DEBUG(IWL_DL_TX, f, ## a)
++#define IWL_DEBUG_ISR(f, a...)    IWL_DEBUG(IWL_DL_ISR, f, ## a)
++#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
++#define IWL_DEBUG_WEP(f, a...)    IWL_DEBUG(IWL_DL_WEP, f, ## a)
++#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
++#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
++#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
++#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
++#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
++#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
++#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
++#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
++#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
++#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
++#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
++#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
++#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
++#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
++	IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
++#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
++#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
++#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a)
++#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
++#define IWL_DEBUG_QOS(f, a...)   IWL_DEBUG(IWL_DL_QOS, f, ## a)
++#define IWL_DEBUG_RADIO(f, a...)  IWL_DEBUG(IWL_DL_RADIO, f, ## a)
++#define IWL_DEBUG_POWER(f, a...)  IWL_DEBUG(IWL_DL_POWER, f, ## a)
++#define IWL_DEBUG_11H(f, a...)  IWL_DEBUG(IWL_DL_11H, f, ## a)
++
++#endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+new file mode 100644
+index 0000000..9a30e1d
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+@@ -0,0 +1,341 @@
++/******************************************************************************
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 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:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *****************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/debugfs.h>
++
++#include <linux/ieee80211.h>
++#include <net/mac80211.h>
++
++
++#include "iwl-4965.h"
++#include "iwl-debug.h"
++#include "iwl-core.h"
++#include "iwl-io.h"
++
++
++/* create and remove of files */
++#define DEBUGFS_ADD_DIR(name, parent) do {                              \
++	dbgfs->dir_##name = debugfs_create_dir(#name, parent);          \
++	if (!(dbgfs->dir_##name))                                       \
++		goto err; 						\
++} while (0)
++
++#define DEBUGFS_ADD_FILE(name, parent) do {                             \
++	dbgfs->dbgfs_##parent##_files.file_##name =                     \
++	debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv,     \
++				&iwl_dbgfs_##name##_ops);               \
++	if (!(dbgfs->dbgfs_##parent##_files.file_##name))               \
++		goto err;                                               \
++} while (0)
++
++#define DEBUGFS_REMOVE(name)  do {              \
++	debugfs_remove(name);                   \
++	name = NULL;                            \
++} while (0);
++
++/* file operation */
++#define DEBUGFS_READ_FUNC(name)                                         \
++static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \
++					char __user *user_buf,          \
++					size_t count, loff_t *ppos);
++
++#define DEBUGFS_WRITE_FUNC(name)                                        \
++static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
++					const char __user *user_buf,    \
++					size_t count, loff_t *ppos);
++
++
++static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
++{
++	file->private_data = inode->i_private;
++	return 0;
++}
++
++#define DEBUGFS_READ_FILE_OPS(name)                                     \
++	DEBUGFS_READ_FUNC(name);                                        \
++static const struct file_operations iwl_dbgfs_##name##_ops = {          \
++	.read = iwl_dbgfs_##name##_read,                       		\
++	.open = iwl_dbgfs_open_file_generic,                    	\
++};
++
++#define DEBUGFS_READ_WRITE_FILE_OPS(name)                               \
++	DEBUGFS_READ_FUNC(name);                                        \
++	DEBUGFS_WRITE_FUNC(name);                                       \
++static const struct file_operations iwl_dbgfs_##name##_ops = {          \
++	.write = iwl_dbgfs_##name##_write,                              \
++	.read = iwl_dbgfs_##name##_read,                                \
++	.open = iwl_dbgfs_open_file_generic,                            \
++};
++
++
++static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
++						char __user *user_buf,
++						size_t count, loff_t *ppos) {
++
++	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
++	char buf[256];
++	int pos = 0;
++	const size_t bufsz = sizeof(buf);
++
++	pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
++						priv->tx_stats[0].cnt);
++	pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
++						priv->tx_stats[1].cnt);
++	pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
++						priv->tx_stats[2].cnt);
++
++	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
++}
++
++static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
++						char __user *user_buf,
++						size_t count, loff_t *ppos) {
++
++	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
++	char buf[256];
++	int pos = 0;
++	const size_t bufsz = sizeof(buf);
++
++	pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
++						priv->rx_stats[0].cnt);
++	pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
++						priv->rx_stats[1].cnt);
++	pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
++						priv->rx_stats[2].cnt);
++
++	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
++}
++
++#define BYTE1_MASK 0x000000ff;
++#define BYTE2_MASK 0x0000ffff;
++#define BYTE3_MASK 0x00ffffff;
++static ssize_t iwl_dbgfs_sram_read(struct file *file,
++					char __user *user_buf,
++					size_t count, loff_t *ppos)
++{
++	u32 val;
++	char buf[1024];
++	ssize_t ret;
++	int i;
++	int pos = 0;
++	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
++	const size_t bufsz = sizeof(buf);
++
++	printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n",
++	priv->dbgfs->sram_offset, priv->dbgfs->sram_len);
++
++	iwl_grab_nic_access(priv);
++	for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
++		val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
++					priv->dbgfs->sram_len - i);
++		if (i < 4) {
++			switch (i) {
++			case 1:
++				val &= BYTE1_MASK;
++				break;
++			case 2:
++				val &= BYTE2_MASK;
++				break;
++			case 3:
++				val &= BYTE3_MASK;
++				break;
++			}
++		}
++		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
++	}
++	pos += scnprintf(buf + pos, bufsz - pos, "\n");
++	iwl_release_nic_access(priv);
++
++	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
++	return ret;
++}
++
++static ssize_t iwl_dbgfs_sram_write(struct file *file,
++					const char __user *user_buf,
++					size_t count, loff_t *ppos)
++{
++	struct iwl_priv *priv = file->private_data;
++	char buf[64];
++	int buf_size;
++	u32 offset, len;
++
++	memset(buf, 0, sizeof(buf));
++	buf_size = min(count, sizeof(buf) -  1);
++	if (copy_from_user(buf, user_buf, buf_size))
++		return -EFAULT;
++
++	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
++		priv->dbgfs->sram_offset = offset;
++		priv->dbgfs->sram_len = len;
++	} else {
++		priv->dbgfs->sram_offset = 0;
++		priv->dbgfs->sram_len = 0;
++	}
++
++	return count;
++}
++
++static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
++					size_t count, loff_t *ppos)
++{
++	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
++	struct iwl4965_station_entry *station;
++	int max_sta = priv->hw_params.max_stations;
++	char *buf;
++	int i, j, pos = 0;
++	ssize_t ret;
++	/* Add 30 for initial string */
++	const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
++	DECLARE_MAC_BUF(mac);
++
++	buf = kmalloc(bufsz, GFP_KERNEL);
++	if(!buf)
++		return -ENOMEM;
++
++	pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
++			priv->num_stations);
++
++	for (i = 0; i < max_sta; i++) {
++		station = &priv->stations[i];
++		if (station->used) {
++			pos += scnprintf(buf + pos, bufsz - pos,
++					"station %d:\ngeneral data:\n", i+1);
++			print_mac(mac, station->sta.sta.addr);
++			pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
++					station->sta.sta.sta_id);
++			pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
++					station->sta.mode);
++			pos += scnprintf(buf + pos, bufsz - pos,
++					"flags: 0x%x\n",
++					station->sta.station_flags_msk);
++			pos += scnprintf(buf + pos, bufsz - pos,
++					"ps_status: %u\n", station->ps_status);
++			pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
++			pos += scnprintf(buf + pos, bufsz - pos,
++					"seq_num\t\ttxq_id");
++#ifdef CONFIG_IWL4965_HT
++			pos += scnprintf(buf + pos, bufsz - pos,
++					"\tframe_count\twait_for_ba\t");
++			pos += scnprintf(buf + pos, bufsz - pos,
++					"start_idx\tbitmap0\t");
++			pos += scnprintf(buf + pos, bufsz - pos,
++					"bitmap1\trate_n_flags");
++#endif
++			pos += scnprintf(buf + pos, bufsz - pos, "\n");
++
++			for (j = 0; j < MAX_TID_COUNT; j++) {
++				pos += scnprintf(buf + pos, bufsz - pos,
++						"[%d]:\t\t%u", j,
++						station->tid[j].seq_number);
++#ifdef CONFIG_IWL4965_HT
++				pos += scnprintf(buf + pos, bufsz - pos,
++						"\t%u\t\t%u\t\t%u\t\t",
++						station->tid[j].agg.txq_id,
++						station->tid[j].agg.frame_count,
++						station->tid[j].agg.wait_for_ba);
++				pos += scnprintf(buf + pos, bufsz - pos,
++						"%u\t%llu\t%u",
++						station->tid[j].agg.start_idx,
++						(unsigned long long)station->tid[j].agg.bitmap,
++						station->tid[j].agg.rate_n_flags);
++#endif
++				pos += scnprintf(buf + pos, bufsz - pos, "\n");
++			}
++			pos += scnprintf(buf + pos, bufsz - pos, "\n");
++		}
++	}
++
++	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
++	kfree(buf);
++	return ret;
++}
++
++
++DEBUGFS_READ_WRITE_FILE_OPS(sram);
++DEBUGFS_READ_FILE_OPS(stations);
++DEBUGFS_READ_FILE_OPS(rx_statistics);
++DEBUGFS_READ_FILE_OPS(tx_statistics);
++
++/*
++ * Create the debugfs files and directories
++ *
++ */
++int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
++{
++	struct iwl_debugfs *dbgfs;
++
++	dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
++	if (!dbgfs) {
++		goto err;
++	}
++
++	priv->dbgfs = dbgfs;
++	dbgfs->name = name;
++	dbgfs->dir_drv = debugfs_create_dir(name, NULL);
++	if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){
++		goto err;
++	}
++
++	DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
++	DEBUGFS_ADD_FILE(sram, data);
++	DEBUGFS_ADD_FILE(stations, data);
++	DEBUGFS_ADD_FILE(rx_statistics, data);
++	DEBUGFS_ADD_FILE(tx_statistics, data);
++
++	return 0;
++
++err:
++	IWL_ERROR("Can't open the debugfs directory\n");
++	iwl_dbgfs_unregister(priv);
++	return -ENOENT;
++}
++EXPORT_SYMBOL(iwl_dbgfs_register);
++
++/**
++ * Remove the debugfs files and directories
++ *
++ */
++void iwl_dbgfs_unregister(struct iwl_priv *priv)
++{
++	if (!(priv->dbgfs))
++		return;
++
++	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
++	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
++	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
++	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
++	DEBUGFS_REMOVE(priv->dbgfs->dir_data);
++	DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
++	kfree(priv->dbgfs);
++	priv->dbgfs = NULL;
++}
++EXPORT_SYMBOL(iwl_dbgfs_unregister);
++
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+new file mode 100644
+index 0000000..a07d5dc
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+@@ -0,0 +1,561 @@
++/******************************************************************************
++ *
++ * This file is provided under a dual BSD/GPLv2 license.  When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 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:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 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/version.h>
++#include <linux/init.h>
++
++#include <net/mac80211.h>
++
++#include "iwl-4965-commands.h"
++#include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-debug.h"
++#include "iwl-eeprom.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.
++ *
++ *********************************************************************/
++
++/* 2.4 GHz */
++const u8 iwl_eeprom_band_1[14] = {
++	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
++};
++
++/* 5.2 GHz bands */
++static const u8 iwl_eeprom_band_2[] = {	/* 4915-5080MHz */
++	183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
++};
++
++static const u8 iwl_eeprom_band_3[] = {	/* 5170-5320MHz */
++	34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
++};
++
++static const u8 iwl_eeprom_band_4[] = {	/* 5500-5700MHz */
++	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
++};
++
++static const u8 iwl_eeprom_band_5[] = {	/* 5725-5825MHz */
++	145, 149, 153, 157, 161, 165
++};
++
++static const u8 iwl_eeprom_band_6[] = {       /* 2.4 FAT channel */
++	1, 2, 3, 4, 5, 6, 7
++};
++
++static const u8 iwl_eeprom_band_7[] = {       /* 5.2 FAT channel */
++	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
++};
++
++/******************************************************************************
++ *
++ * EEPROM related functions
++ *
++******************************************************************************/
++
++int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
++{
++	u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
++	if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
++		IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
++		return -ENOENT;
++	}
++	return 0;
++}
++EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
++
++/*
++ * 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("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);
++
++
++/**
++ * iwl_eeprom_init - read EEPROM contents
++ *
++ * Load the EEPROM contents from adapter into priv->eeprom
++ *
++ * NOTE:  This routine uses the non-debug IO access functions.
++ */
++int iwl_eeprom_init(struct iwl_priv *priv)
++{
++	u16 *e = (u16 *)&priv->eeprom;
++	u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
++	u32 r;
++	int sz = sizeof(priv->eeprom);
++	int ret;
++	int i;
++	u16 addr;
++
++	/* The EEPROM structure has several padding buffers within it
++	 * and when adding new EEPROM maps is subject to programmer errors
++	 * which may be very difficult to identify without explicitly
++	 * checking the resulting size of the eeprom map. */
++	BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
++
++	if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
++		IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
++		return -ENOENT;
++	}
++
++	/* Make sure driver (instead of uCode) is allowed to read EEPROM */
++	ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv);
++	if (ret < 0) {
++		IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
++		return -ENOENT;
++	}
++
++	/* eeprom is an array of 16bit values */
++	for (addr = 0; addr < sz; addr += sizeof(u16)) {
++		_iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
++		_iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
++
++		for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
++					i += IWL_EEPROM_ACCESS_DELAY) {
++			r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
++			if (r & CSR_EEPROM_REG_READ_VALID_MSK)
++				break;
++			udelay(IWL_EEPROM_ACCESS_DELAY);
++		}
++
++		if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
++			IWL_ERROR("Time out reading EEPROM[%d]", addr);
++			ret = -ETIMEDOUT;
++			goto done;
++		}
++		e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
++	}
++	ret = 0;
++
++done:
++	priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
++	return ret;
++}
++EXPORT_SYMBOL(iwl_eeprom_init);
++
++
++void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
++{
++	memcpy(mac, priv->eeprom.mac_address, 6);
++}
++EXPORT_SYMBOL(iwl_eeprom_get_mac);
++
++static void iwl_init_band_reference(const struct iwl_priv *priv,
++				    int band,
++				    int *eeprom_ch_count,
++				    const struct iwl4965_eeprom_channel
++				    **eeprom_ch_info,
++				    const u8 **eeprom_ch_index)
++{
++	switch (band) {
++	case 1:		/* 2.4GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
++		*eeprom_ch_info = priv->eeprom.band_1_channels;
++		*eeprom_ch_index = iwl_eeprom_band_1;
++		break;
++	case 2:		/* 4.9GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
++		*eeprom_ch_info = priv->eeprom.band_2_channels;
++		*eeprom_ch_index = iwl_eeprom_band_2;
++		break;
++	case 3:		/* 5.2GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
++		*eeprom_ch_info = priv->eeprom.band_3_channels;
++		*eeprom_ch_index = iwl_eeprom_band_3;
++		break;
++	case 4:		/* 5.5GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
++		*eeprom_ch_info = priv->eeprom.band_4_channels;
++		*eeprom_ch_index = iwl_eeprom_band_4;
++		break;
++	case 5:		/* 5.7GHz band */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
++		*eeprom_ch_info = priv->eeprom.band_5_channels;
++		*eeprom_ch_index = iwl_eeprom_band_5;
++		break;
++	case 6:		/* 2.4GHz FAT channels */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
++		*eeprom_ch_info = priv->eeprom.band_24_channels;
++		*eeprom_ch_index = iwl_eeprom_band_6;
++		break;
++	case 7:		/* 5 GHz FAT channels */
++		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
++		*eeprom_ch_info = priv->eeprom.band_52_channels;
++		*eeprom_ch_index = iwl_eeprom_band_7;
++		break;
++	default:
++		BUG();
++		return;
++	}
++}
++
++#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
++			    ? # x " " : "")
++
++/**
++ * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv.
++ *
++ * Does not set up a command, or touch hardware.
++ */
++static int iwl4965_set_fat_chan_info(struct iwl_priv *priv,
++			      enum ieee80211_band band, u16 channel,
++			      const struct iwl4965_eeprom_channel *eeprom_ch,
++			      u8 fat_extension_channel)
++{
++	struct iwl_channel_info *ch_info;
++
++	ch_info = (struct iwl_channel_info *)
++			iwl_get_channel_info(priv, band, channel);
++
++	if (!is_channel_valid(ch_info))
++		return -1;
++
++	IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
++			" %ddBm): Ad-Hoc %ssupported\n",
++			ch_info->channel,
++			is_channel_a_band(ch_info) ?
++			"5.2" : "2.4",
++			CHECK_AND_PRINT(IBSS),
++			CHECK_AND_PRINT(ACTIVE),
++			CHECK_AND_PRINT(RADAR),
++			CHECK_AND_PRINT(WIDE),
++			CHECK_AND_PRINT(NARROW),
++			CHECK_AND_PRINT(DFS),
++			eeprom_ch->flags,
++			eeprom_ch->max_power_avg,
++			((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
++			 && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
++			"" : "not ");
++
++	ch_info->fat_eeprom = *eeprom_ch;
++	ch_info->fat_max_power_avg = eeprom_ch->max_power_avg;
++	ch_info->fat_curr_txpow = eeprom_ch->max_power_avg;
++	ch_info->fat_min_power = 0;
++	ch_info->fat_scan_power = eeprom_ch->max_power_avg;
++	ch_info->fat_flags = eeprom_ch->flags;
++	ch_info->fat_extension_channel = fat_extension_channel;
++
++	return 0;
++}
++
++#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
++			    ? # x " " : "")
++
++/**
++ * iwl_init_channel_map - Set up driver's info for all possible channels
++ */
++int iwl_init_channel_map(struct iwl_priv *priv)
++{
++	int eeprom_ch_count = 0;
++	const u8 *eeprom_ch_index = NULL;
++	const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL;
++	int band, ch;
++	struct iwl_channel_info *ch_info;
++
++	if (priv->channel_count) {
++		IWL_DEBUG_INFO("Channel map already initialized.\n");
++		return 0;
++	}
++
++	if (priv->eeprom.version < 0x2f) {
++		IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
++			    priv->eeprom.version);
++		return -EINVAL;
++	}
++
++	IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
++
++	priv->channel_count =
++	    ARRAY_SIZE(iwl_eeprom_band_1) +
++	    ARRAY_SIZE(iwl_eeprom_band_2) +
++	    ARRAY_SIZE(iwl_eeprom_band_3) +
++	    ARRAY_SIZE(iwl_eeprom_band_4) +
++	    ARRAY_SIZE(iwl_eeprom_band_5);
++
++	IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
++
++	priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
++				     priv->channel_count, GFP_KERNEL);
++	if (!priv->channel_info) {
++		IWL_ERROR("Could not allocate channel_info\n");
++		priv->channel_count = 0;
++		return -ENOMEM;
++	}
++
++	ch_info = priv->channel_info;
++
++	/* Loop through the 5 EEPROM bands adding them in order to the
++	 * channel map we maintain (that contains additional information than
++	 * what just in the EEPROM) */
++	for (band = 1; band <= 5; band++) {
++
++		iwl_init_band_reference(priv, band, &eeprom_ch_count,
++					&eeprom_ch_info, &eeprom_ch_index);
++
++		/* Loop through each band adding each of the channels */
++		for (ch = 0; ch < eeprom_ch_count; ch++) {
++			ch_info->channel = eeprom_ch_index[ch];
++			ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
++			    IEEE80211_BAND_5GHZ;
++
++			/* permanently store EEPROM's channel regulatory flags
++			 *   and max power in channel info database. */
++			ch_info->eeprom = eeprom_ch_info[ch];
++
++			/* Copy the run-time flags so they are there even on
++			 * invalid channels */
++			ch_info->flags = eeprom_ch_info[ch].flags;
++
++			if (!(is_channel_valid(ch_info))) {
++				IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
++					       "No traffic\n",
++					       ch_info->channel,
++					       ch_info->flags,
++					       is_channel_a_band(ch_info) ?
++					       "5.2" : "2.4");
++				ch_info++;
++				continue;
++			}
++
++			/* Initialize regulatory-based run-time data */
++			ch_info->max_power_avg = ch_info->curr_txpow =
++			    eeprom_ch_info[ch].max_power_avg;
++			ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
++			ch_info->min_power = 0;
++
++			IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x"
++				       " %ddBm): Ad-Hoc %ssupported\n",
++				       ch_info->channel,
++				       is_channel_a_band(ch_info) ?
++				       "5.2" : "2.4",
++				       CHECK_AND_PRINT_I(VALID),
++				       CHECK_AND_PRINT_I(IBSS),
++				       CHECK_AND_PRINT_I(ACTIVE),
++				       CHECK_AND_PRINT_I(RADAR),
++				       CHECK_AND_PRINT_I(WIDE),
++				       CHECK_AND_PRINT_I(NARROW),
++				       CHECK_AND_PRINT_I(DFS),
++				       eeprom_ch_info[ch].flags,
++				       eeprom_ch_info[ch].max_power_avg,
++				       ((eeprom_ch_info[ch].
++					 flags & EEPROM_CHANNEL_IBSS)
++					&& !(eeprom_ch_info[ch].
++					     flags & EEPROM_CHANNEL_RADAR))
++				       ? "" : "not ");
++
++			/* Set the user_txpower_limit to the highest power
++			 * supported by any channel */
++			if (eeprom_ch_info[ch].max_power_avg >
++			    priv->user_txpower_limit)
++				priv->user_txpower_limit =
++				    eeprom_ch_info[ch].max_power_avg;
++
++			ch_info++;
++		}
++	}
++
++	/* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
++	for (band = 6; band <= 7; band++) {
++		enum ieee80211_band ieeeband;
++		u8 fat_extension_chan;
++
++		iwl_init_band_reference(priv, band, &eeprom_ch_count,
++					&eeprom_ch_info, &eeprom_ch_index);
++
++		/* EEPROM band 6 is 2.4, band 7 is 5 GHz */
++		ieeeband =
++			(band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
++
++		/* Loop through each band adding each of the channels */
++		for (ch = 0; ch < eeprom_ch_count; ch++) {
++
++			if ((band == 6) &&
++			    ((eeprom_ch_index[ch] == 5) ||
++			    (eeprom_ch_index[ch] == 6) ||
++			    (eeprom_ch_index[ch] == 7)))
++			       fat_extension_chan = HT_IE_EXT_CHANNEL_MAX;
++			else
++				fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
++
++			/* Set up driver's info for lower half */
++			iwl4965_set_fat_chan_info(priv, ieeeband,
++						  eeprom_ch_index[ch],
++						  &(eeprom_ch_info[ch]),
++						  fat_extension_chan);
++
++			/* Set up driver's info for upper half */
++			iwl4965_set_fat_chan_info(priv, ieeeband,
++						  (eeprom_ch_index[ch] + 4),
++						  &(eeprom_ch_info[ch]),
++						  HT_IE_EXT_CHANNEL_BELOW);
++		}
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL(iwl_init_channel_map);
++
++/*
++ * iwl_free_channel_map - undo allocations in iwl4965_init_channel_map
++ */
++void iwl_free_channel_map(struct iwl_priv *priv)
++{
++	kfree(priv->channel_info);
++	priv->channel_count = 0;
++}
++EXPORT_SYMBOL(iwl_free_channel_map);
++
++/**
++ * iwl_get_channel_info - Find driver's private channel info
++ *
++ * Based on band and channel number.
++ */
++const struct iwl_channel_info *iwl_get_channel_info(
++		const struct iwl_priv *priv,
++		enum ieee80211_band band, u16 channel)
++{
++	int i;
++
++	switch (band) {
++	case IEEE80211_BAND_5GHZ:
++		for (i = 14; i < priv->channel_count; i++) {
++			if (priv->channel_info[i].channel == channel)
++				return &priv->channel_info[i];
++		}
++		break;
++	case IEEE80211_BAND_2GHZ:
++		if (channel >= 1 && channel <= 14)
++			return &priv->channel_info[channel - 1];
++		break;
++	default:
++		BUG();
++	}
++
++	return NULL;
++}
++EXPORT_SYMBOL(iwl_get_channel_info);
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+new file mode 100644
+index 0000000..bd0a042
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+@@ -0,0 +1,375 @@
++/******************************************************************************
++ *
++ * 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 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:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 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_eeprom_h__
++#define __iwl_eeprom_h__
++
++struct iwl_priv;
++
++/*
++ * EEPROM access time values:
++ *
++ * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
++ *   then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
++ *   CSR_EEPROM_REG_BIT_CMD (0x2).
++ * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
++ * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
++ * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
++ */
++#define IWL_EEPROM_ACCESS_TIMEOUT	5000 /* uSec */
++#define IWL_EEPROM_ACCESS_DELAY		10   /* uSec */
++
++#define IWL_EEPROM_SEM_TIMEOUT 		10   /* milliseconds */
++#define IWL_EEPROM_SEM_RETRY_LIMIT	1000 /* number of attempts (not time) */
++
++
++/*
++ * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
++ *
++ * IBSS and/or AP operation is allowed *only* on those channels with
++ * (VALID && IBSS && ACTIVE && !RADAR).  This restriction is in place because
++ * RADAR detection is not supported by the 4965 driver, but is a
++ * requirement for establishing a new network for legal operation on channels
++ * requiring RADAR detection or restricting ACTIVE scanning.
++ *
++ * NOTE:  "WIDE" flag does not indicate anything about "FAT" 40 MHz channels.
++ *        It only indicates that 20 MHz channel use is supported; FAT channel
++ *        usage is indicated by a separate set of regulatory flags for each
++ *        FAT channel pair.
++ *
++ * NOTE:  Using a channel inappropriately will result in a uCode error!
++ */
++#define IWL_NUM_TX_CALIB_GROUPS 5
++enum {
++	EEPROM_CHANNEL_VALID = (1 << 0),	/* usable for this SKU/geo */
++	EEPROM_CHANNEL_IBSS = (1 << 1),		/* usable as an IBSS channel */
++	/* Bit 2 Reserved */
++	EEPROM_CHANNEL_ACTIVE = (1 << 3),	/* active scanning allowed */
++	EEPROM_CHANNEL_RADAR = (1 << 4),	/* radar detection required */
++	EEPROM_CHANNEL_WIDE = (1 << 5),		/* 20 MHz channel okay */
++	EEPROM_CHANNEL_NARROW = (1 << 6),	/* 10 MHz channel (not used) */
++	EEPROM_CHANNEL_DFS = (1 << 7),	/* dynamic freq selection candidate */
++};
++
++/* SKU Capabilities */
++#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
++#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
++
++/* *regulatory* channel data format in eeprom, one for each channel.
++ * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */
++struct iwl4965_eeprom_channel {
++	u8 flags;		/* EEPROM_CHANNEL_* flags copied from EEPROM */
++	s8 max_power_avg;	/* max power (dBm) on this chnl, limit 31 */
++} __attribute__ ((packed));
++
++/* 4965 has two radio transmitters (and 3 radio receivers) */
++#define EEPROM_TX_POWER_TX_CHAINS      (2)
++
++/* 4965 has room for up to 8 sets of txpower calibration data */
++#define EEPROM_TX_POWER_BANDS          (8)
++
++/* 4965 factory calibration measures txpower gain settings for
++ * each of 3 target output levels */
++#define EEPROM_TX_POWER_MEASUREMENTS   (3)
++
++#define EEPROM_4965_TX_POWER_VERSION        (2)
++
++/* 4965 driver does not work with txpower calibration version < 5.
++ * Look for this in calib_version member of struct iwl4965_eeprom. */
++#define EEPROM_TX_POWER_VERSION_NEW    (5)
++
++/* 2.4 GHz */
++extern const u8 iwl_eeprom_band_1[14];
++
++/*
++ * 4965 factory calibration data for one txpower level, on one channel,
++ * measured on one of the 2 tx chains (radio transmitter and associated
++ * antenna).  EEPROM contains:
++ *
++ * 1)  Temperature (degrees Celsius) of device when measurement was made.
++ *
++ * 2)  Gain table index used to achieve the target measurement power.
++ *     This refers to the "well-known" gain tables (see iwl-4965-hw.h).
++ *
++ * 3)  Actual measured output power, in half-dBm ("34" = 17 dBm).
++ *
++ * 4)  RF power amplifier detector level measurement (not used).
++ */
++struct iwl4965_eeprom_calib_measure {
++	u8 temperature;		/* Device temperature (Celsius) */
++	u8 gain_idx;		/* Index into gain table */
++	u8 actual_pow;		/* Measured RF output power, half-dBm */
++	s8 pa_det;		/* Power amp detector level (not used) */
++} __attribute__ ((packed));
++
++
++/*
++ * 4965 measurement set for one channel.  EEPROM contains:
++ *
++ * 1)  Channel number measured
++ *
++ * 2)  Measurements for each of 3 power levels for each of 2 radio transmitters
++ *     (a.k.a. "tx chains") (6 measurements altogether)
++ */
++struct iwl4965_eeprom_calib_ch_info {
++	u8 ch_num;
++	struct iwl4965_eeprom_calib_measure
++		measurements[EEPROM_TX_POWER_TX_CHAINS]
++			[EEPROM_TX_POWER_MEASUREMENTS];
++} __attribute__ ((packed));
++
++/*
++ * 4965 txpower subband info.
++ *
++ * For each frequency subband, EEPROM contains the following:
++ *
++ * 1)  First and last channels within range of the subband.  "0" values
++ *     indicate that this sample set is not being used.
++ *
++ * 2)  Sample measurement sets for 2 channels close to the range endpoints.
++ */
++struct iwl4965_eeprom_calib_subband_info {
++	u8 ch_from;	/* channel number of lowest channel in subband */
++	u8 ch_to;	/* channel number of highest channel in subband */
++	struct iwl4965_eeprom_calib_ch_info ch1;
++	struct iwl4965_eeprom_calib_ch_info ch2;
++} __attribute__ ((packed));
++
++
++/*
++ * 4965 txpower calibration info.  EEPROM contains:
++ *
++ * 1)  Factory-measured saturation power levels (maximum levels at which
++ *     tx power amplifier can output a signal without too much distortion).
++ *     There is one level for 2.4 GHz band and one for 5 GHz band.  These
++ *     values apply to all channels within each of the bands.
++ *
++ * 2)  Factory-measured power supply voltage level.  This is assumed to be
++ *     constant (i.e. same value applies to all channels/bands) while the
++ *     factory measurements are being made.
++ *
++ * 3)  Up to 8 sets of factory-measured txpower calibration values.
++ *     These are for different frequency ranges, since txpower gain
++ *     characteristics of the analog radio circuitry vary with frequency.
++ *
++ *     Not all sets need to be filled with data;
++ *     struct iwl4965_eeprom_calib_subband_info contains range of channels
++ *     (0 if unused) for each set of data.
++ */
++struct iwl4965_eeprom_calib_info {
++	u8 saturation_power24;	/* half-dBm (e.g. "34" = 17 dBm) */
++	u8 saturation_power52;	/* half-dBm */
++	s16 voltage;		/* signed */
++	struct iwl4965_eeprom_calib_subband_info
++		band_info[EEPROM_TX_POWER_BANDS];
++} __attribute__ ((packed));
++
++
++
++/*
++ * 4965 EEPROM map
++ */
++struct iwl4965_eeprom {
++	u8 reserved0[16];
++	u16 device_id;		/* abs.ofs: 16 */
++	u8 reserved1[2];
++	u16 pmc;		/* abs.ofs: 20 */
++	u8 reserved2[20];
++	u8 mac_address[6];	/* abs.ofs: 42 */
++	u8 reserved3[58];
++	u16 board_revision;	/* abs.ofs: 106 */
++	u8 reserved4[11];
++	u8 board_pba_number[9];	/* abs.ofs: 119 */
++	u8 reserved5[8];
++	u16 version;		/* abs.ofs: 136 */
++	u8 sku_cap;		/* abs.ofs: 138 */
++	u8 leds_mode;		/* abs.ofs: 139 */
++	u16 oem_mode;
++	u16 wowlan_mode;	/* abs.ofs: 142 */
++	u16 leds_time_interval;	/* abs.ofs: 144 */
++	u8 leds_off_time;	/* abs.ofs: 146 */
++	u8 leds_on_time;	/* abs.ofs: 147 */
++	u8 almgor_m_version;	/* abs.ofs: 148 */
++	u8 antenna_switch_type;	/* abs.ofs: 149 */
++	u8 reserved6[8];
++	u16 board_revision_4965;	/* abs.ofs: 158 */
++	u8 reserved7[13];
++	u8 board_pba_number_4965[9];	/* abs.ofs: 173 */
++	u8 reserved8[10];
++	u8 sku_id[4];		/* abs.ofs: 192 */
++
++/*
++ * Per-channel regulatory data.
++ *
++ * Each channel that *might* be supported by 3945 or 4965 has a fixed location
++ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
++ * txpower (MSB).
++ *
++ * Entries immediately below are for 20 MHz channel width.  FAT (40 MHz)
++ * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
++ *
++ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
++ */
++	u16 band_1_count;	/* abs.ofs: 196 */
++	struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
++
++/*
++ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
++ * 5.0 GHz channels 7, 8, 11, 12, 16
++ * (4915-5080MHz) (none of these is ever supported)
++ */
++	u16 band_2_count;	/* abs.ofs: 226 */
++	struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
++
++/*
++ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
++ * (5170-5320MHz)
++ */
++	u16 band_3_count;	/* abs.ofs: 254 */
++	struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
++
++/*
++ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
++ * (5500-5700MHz)
++ */
++	u16 band_4_count;	/* abs.ofs: 280 */
++	struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
++
++/*
++ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
++ * (5725-5825MHz)
++ */
++	u16 band_5_count;	/* abs.ofs: 304 */
++	struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
++
++	u8 reserved10[2];
++
++
++/*
++ * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
++ *
++ * The channel listed is the center of the lower 20 MHz half of the channel.
++ * The overall center frequency is actually 2 channels (10 MHz) above that,
++ * and the upper half of each FAT channel is centered 4 channels (20 MHz) away
++ * from the lower half; e.g. the upper half of FAT channel 1 is channel 5,
++ * and the overall FAT channel width centers on channel 3.
++ *
++ * NOTE:  The RXON command uses 20 MHz channel numbers to specify the
++ *        control channel to which to tune.  RXON also specifies whether the
++ *        control channel is the upper or lower half of a FAT channel.
++ *
++ * NOTE:  4965 does not support FAT channels on 2.4 GHz.
++ */
++	struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */
++	u8 reserved11[2];
++
++/*
++ * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64),
++ * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
++ */
++	struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */
++	u8 reserved12[6];
++
++/*
++ * 4965 driver requires txpower calibration format version 5 or greater.
++ * Driver does not work with txpower calibration version < 5.
++ * This value is simply a 16-bit number, no major/minor versions here.
++ */
++	u16 calib_version;	/* abs.ofs: 364 */
++	u8 reserved13[2];
++	u8 reserved14[96];	/* abs.ofs: 368 */
++
++/*
++ * 4965 Txpower calibration data.
++ */
++	struct iwl4965_eeprom_calib_info calib_info;	/* abs.ofs: 464 */
++
++	u8 reserved16[140];	/* fill out to full 1024 byte block */
++
++
++} __attribute__ ((packed));
++
++#define IWL_EEPROM_IMAGE_SIZE 1024
++
++/* End of EEPROM */
++
++struct iwl_eeprom_ops {
++	int (*verify_signature) (struct iwl_priv *priv);
++	int (*acquire_semaphore) (struct iwl_priv *priv);
++	void (*release_semaphore) (struct iwl_priv *priv);
++};
++
++
++void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
++int iwl_eeprom_init(struct iwl_priv *priv);
++
++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);
++
++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(
++		const struct iwl_priv *priv,
++		enum ieee80211_band band, u16 channel);
++
++#endif  /* __iwl_eeprom_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+new file mode 100644
+index 0000000..fdb27f1
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+@@ -0,0 +1,278 @@
++/******************************************************************************
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 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:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *****************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <net/mac80211.h>
++
++#include "iwl-4965.h" /* FIXME: remove */
++#include "iwl-debug.h"
++#include "iwl-eeprom.h"
++#include "iwl-core.h"
++
++
++#define IWL_CMD(x) case x : return #x
++
++const char *get_cmd_string(u8 cmd)
++{
++	switch (cmd) {
++		IWL_CMD(REPLY_ALIVE);
++		IWL_CMD(REPLY_ERROR);
++		IWL_CMD(REPLY_RXON);
++		IWL_CMD(REPLY_RXON_ASSOC);
++		IWL_CMD(REPLY_QOS_PARAM);
++		IWL_CMD(REPLY_RXON_TIMING);
++		IWL_CMD(REPLY_ADD_STA);
++		IWL_CMD(REPLY_REMOVE_STA);
++		IWL_CMD(REPLY_REMOVE_ALL_STA);
++		IWL_CMD(REPLY_WEPKEY);
++		IWL_CMD(REPLY_TX);
++		IWL_CMD(REPLY_RATE_SCALE);
++		IWL_CMD(REPLY_LEDS_CMD);
++		IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
++		IWL_CMD(RADAR_NOTIFICATION);
++		IWL_CMD(REPLY_QUIET_CMD);
++		IWL_CMD(REPLY_CHANNEL_SWITCH);
++		IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
++		IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
++		IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
++		IWL_CMD(POWER_TABLE_CMD);
++		IWL_CMD(PM_SLEEP_NOTIFICATION);
++		IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
++		IWL_CMD(REPLY_SCAN_CMD);
++		IWL_CMD(REPLY_SCAN_ABORT_CMD);
++		IWL_CMD(SCAN_START_NOTIFICATION);
++		IWL_CMD(SCAN_RESULTS_NOTIFICATION);
++		IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
++		IWL_CMD(BEACON_NOTIFICATION);
++		IWL_CMD(REPLY_TX_BEACON);
++		IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
++		IWL_CMD(QUIET_NOTIFICATION);
++		IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
++		IWL_CMD(MEASURE_ABORT_NOTIFICATION);
++		IWL_CMD(REPLY_BT_CONFIG);
++		IWL_CMD(REPLY_STATISTICS_CMD);
++		IWL_CMD(STATISTICS_NOTIFICATION);
++		IWL_CMD(REPLY_CARD_STATE_CMD);
++		IWL_CMD(CARD_STATE_NOTIFICATION);
++		IWL_CMD(MISSED_BEACONS_NOTIFICATION);
++		IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
++		IWL_CMD(SENSITIVITY_CMD);
++		IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
++		IWL_CMD(REPLY_RX_PHY_CMD);
++		IWL_CMD(REPLY_RX_MPDU_CMD);
++		IWL_CMD(REPLY_RX);
++		IWL_CMD(REPLY_COMPRESSED_BA);
++	default:
++		return "UNKNOWN";
++
++	}
++}
++EXPORT_SYMBOL(get_cmd_string);
++
++#define HOST_COMPLETE_TIMEOUT (HZ / 2)
++
++static int iwl_generic_cmd_callback(struct iwl_priv *priv,
++				    struct iwl_cmd *cmd, struct sk_buff *skb)
++{
++	struct iwl4965_rx_packet *pkt = NULL;
++
++	if (!skb) {
++		IWL_ERROR("Error: Response NULL in %s.\n",
++				get_cmd_string(cmd->hdr.cmd));
++		return 1;
++	}
++
++	pkt = (struct iwl4965_rx_packet *)skb->data;
++	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
++		IWL_ERROR("Bad return from %s (0x%08X)\n",
++			get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
++		return 1;
++	}
++
++	IWL_DEBUG_HC("back from %s (0x%08X)\n",
++			get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
++
++	/* Let iwl_tx_complete free the response skb */
++	return 1;
++}
++
++static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++	int ret;
++
++	BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
++
++	/* An asynchronous command can not expect an SKB to be set. */
++	BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
++
++	/* Assign a generic callback if one is not provided */
++	if (!cmd->meta.u.callback)
++		cmd->meta.u.callback = iwl_generic_cmd_callback;
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return -EBUSY;
++
++	ret = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd);
++	if (ret < 0) {
++		IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
++			  get_cmd_string(cmd->id), ret);
++		return ret;
++	}
++	return 0;
++}
++
++int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++	int cmd_idx;
++	int ret;
++
++	BUG_ON(cmd->meta.flags & CMD_ASYNC);
++
++	 /* A synchronous command can not have a callback set. */
++	BUG_ON(cmd->meta.u.callback != NULL);
++
++	if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
++		IWL_ERROR("Error sending %s: Already sending a host command\n",
++			  get_cmd_string(cmd->id));
++		ret = -EBUSY;
++		goto out;
++	}
++
++	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
++
++	if (cmd->meta.flags & CMD_WANT_SKB)
++		cmd->meta.source = &cmd->meta;
++
++	cmd_idx = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd);
++	if (cmd_idx < 0) {
++		ret = cmd_idx;
++		IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
++			  get_cmd_string(cmd->id), ret);
++		goto out;
++	}
++
++	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
++			!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
++			HOST_COMPLETE_TIMEOUT);
++	if (!ret) {
++		if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
++			IWL_ERROR("Error sending %s: time out after %dms.\n",
++				  get_cmd_string(cmd->id),
++				  jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
++
++			clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
++			ret = -ETIMEDOUT;
++			goto cancel;
++		}
++	}
++
++	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
++		IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
++			       get_cmd_string(cmd->id));
++		ret = -ECANCELED;
++		goto fail;
++	}
++	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
++		IWL_DEBUG_INFO("Command %s failed: FW Error\n",
++			       get_cmd_string(cmd->id));
++		ret = -EIO;
++		goto fail;
++	}
++	if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
++		IWL_ERROR("Error: Response NULL in '%s'\n",
++			  get_cmd_string(cmd->id));
++		ret = -EIO;
++		goto out;
++	}
++
++	ret = 0;
++	goto out;
++
++cancel:
++	if (cmd->meta.flags & CMD_WANT_SKB) {
++		struct iwl_cmd *qcmd;
++
++		/* Cancel the CMD_WANT_SKB flag for the cmd in the
++		 * TX cmd queue. Otherwise in case the cmd comes
++		 * in later, it will possibly set an invalid
++		 * address (cmd->meta.source). */
++		qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
++		qcmd->meta.flags &= ~CMD_WANT_SKB;
++	}
++fail:
++	if (cmd->meta.u.skb) {
++		dev_kfree_skb_any(cmd->meta.u.skb);
++		cmd->meta.u.skb = NULL;
++	}
++out:
++	clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
++	return ret;
++}
++EXPORT_SYMBOL(iwl_send_cmd_sync);
++
++int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++	if (cmd->meta.flags & CMD_ASYNC)
++		return iwl_send_cmd_async(priv, cmd);
++
++	return iwl_send_cmd_sync(priv, cmd);
++}
++EXPORT_SYMBOL(iwl_send_cmd);
++
++int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
++{
++	struct iwl_host_cmd cmd = {
++		.id = id,
++		.len = len,
++		.data = data,
++	};
++
++	return iwl_send_cmd_sync(priv, &cmd);
++}
++EXPORT_SYMBOL(iwl_send_cmd_pdu);
++
++int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
++			   u8 id, u16 len, const void *data,
++			   int (*callback)(struct iwl_priv *priv,
++					   struct iwl_cmd *cmd,
++					   struct sk_buff *skb))
++{
++	struct iwl_host_cmd cmd = {
++		.id = id,
++		.len = len,
++		.data = data,
++	};
++
++	cmd.meta.flags |= CMD_ASYNC;
++	cmd.meta.u.callback = callback;
++
++	return iwl_send_cmd_async(priv, &cmd);
++}
++EXPORT_SYMBOL(iwl_send_cmd_pdu_async);
+diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
+index 8993cca..a443472 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
++++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 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.
+@@ -254,6 +254,26 @@ static inline u8 iwl_get_dma_hi_address(dma_addr_t addr)
+ 	return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0;
+ }
+ 
++/**
++ * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
++ * @index -- current index
++ * @n_bd -- total number of entries in queue (must be power of 2)
++ */
++static inline int iwl_queue_inc_wrap(int index, int n_bd)
++{
++	return ++index & (n_bd - 1);
++}
++
++/**
++ * iwl_queue_dec_wrap - decrement queue index, wrap back to end
++ * @index -- current index
++ * @n_bd -- total number of entries in queue (must be power of 2)
++ */
++static inline int iwl_queue_dec_wrap(int index, int n_bd)
++{
++	return --index & (n_bd - 1);
++}
++
+ /* TODO: Move fw_desc functions to iwl-pci.ko */
+ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
+ 				    struct fw_desc *desc)
+diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
+new file mode 100644
+index 0000000..5bc3df4
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-io.h
+@@ -0,0 +1,429 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_io_h__
++#define __iwl_io_h__
++
++#include <linux/io.h>
++
++#include "iwl-debug.h"
++
++/*
++ * IO, register, and NIC memory access functions
++ *
++ * NOTE on naming convention and macro usage for these
++ *
++ * A single _ prefix before a an access function means that no state
++ * check or debug information is printed when that function is called.
++ *
++ * A double __ prefix before an access function means that state is checked
++ * and the current line number and caller function name are printed in addition
++ * to any other debug output.
++ *
++ * The non-prefixed name is the #define that maps the caller into a
++ * #define that provides the caller's name and __LINE__ to the double
++ * prefix version.
++ *
++ * If you wish to call the function without any debug or state checking,
++ * you should use the single _ prefix version (as is used by dependent IO
++ * routines, for example _iwl_read_direct32 calls the non-check version of
++ * _iwl_read32.)
++ *
++ * These declarations are *extremely* useful in quickly isolating code deltas
++ * which result in misconfiguring of the hardware I/O.  In combination with
++ * git-bisect and the IO debug level you can quickly determine the specific
++ * commit which breaks the IO sequence to the hardware.
++ *
++ */
++
++#define _iwl_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv,
++				 u32 ofs, u32 val)
++{
++	IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
++	_iwl_write32(priv, ofs, val);
++}
++#define iwl_write32(priv, ofs, val) \
++	__iwl_write32(__FILE__, __LINE__, priv, ofs, val)
++#else
++#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val)
++#endif
++
++#define _iwl_read32(priv, ofs) readl((priv)->hw_base + (ofs))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs)
++{
++	IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
++	return _iwl_read32(priv, ofs);
++}
++#define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs)
++#else
++#define iwl_read32(p, o) _iwl_read32(p, o)
++#endif
++
++static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
++				u32 bits, u32 mask, int timeout)
++{
++	int i = 0;
++
++	do {
++		if ((_iwl_read32(priv, addr) & mask) == (bits & mask))
++			return i;
++		mdelay(10);
++		i += 10;
++	} while (i < timeout);
++
++	return -ETIMEDOUT;
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline int __iwl_poll_bit(const char *f, u32 l,
++				 struct iwl_priv *priv, u32 addr,
++				 u32 bits, u32 mask, int timeout)
++{
++	int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout);
++	IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
++		     addr, bits, mask,
++		     unlikely(ret  == -ETIMEDOUT)?"timeout":"", f, l);
++	return ret;
++}
++#define iwl_poll_bit(priv, addr, bits, mask, timeout) \
++	__iwl_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout)
++#else
++#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t)
++#endif
++
++static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
++{
++	_iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_set_bit(const char *f, u32 l,
++				 struct iwl_priv *priv, u32 reg, u32 mask)
++{
++	u32 val = _iwl_read32(priv, reg) | mask;
++	IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
++	_iwl_write32(priv, reg, val);
++}
++#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m)
++#else
++#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m)
++#endif
++
++static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
++{
++	_iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_clear_bit(const char *f, u32 l,
++				   struct iwl_priv *priv, u32 reg, u32 mask)
++{
++	u32 val = _iwl_read32(priv, reg) & ~mask;
++	IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
++	_iwl_write32(priv, reg, val);
++}
++#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m)
++#else
++#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m)
++#endif
++
++static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
++{
++	int ret;
++	u32 gp_ctl;
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (atomic_read(&priv->restrict_refcnt))
++		return 0;
++#endif
++	if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++	    test_bit(STATUS_RF_KILL_SW, &priv->status)) {
++		IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
++			"wakes up NIC\n");
++
++		/* 10 msec allows time for NIC to complete its data save */
++		gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL);
++		if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
++			IWL_DEBUG_RF_KILL("Wait for complete power-down, "
++				"gpctl = 0x%08x\n", gp_ctl);
++			mdelay(10);
++		} else
++			IWL_DEBUG_RF_KILL("power-down complete, "
++					  "gpctl = 0x%08x\n", gp_ctl);
++	}
++
++	/* this bit wakes up the NIC */
++	_iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++	ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
++			   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
++			   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
++			    CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
++	if (ret < 0) {
++		IWL_ERROR("MAC is in deep sleep!\n");
++		return -EIO;
++	}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	atomic_inc(&priv->restrict_refcnt);
++#endif
++	return 0;
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline int __iwl_grab_nic_access(const char *f, u32 l,
++					       struct iwl_priv *priv)
++{
++	if (atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Grabbing access while already held %s %d.\n", f, l);
++
++	IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
++	return _iwl_grab_nic_access(priv);
++}
++#define iwl_grab_nic_access(priv) \
++	__iwl_grab_nic_access(__FILE__, __LINE__, priv)
++#else
++#define iwl_grab_nic_access(priv) \
++	_iwl_grab_nic_access(priv)
++#endif
++
++static inline void _iwl_release_nic_access(struct iwl_priv *priv)
++{
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (atomic_dec_and_test(&priv->restrict_refcnt))
++#endif
++		_iwl_clear_bit(priv, CSR_GP_CNTRL,
++			       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_release_nic_access(const char *f, u32 l,
++					    struct iwl_priv *priv)
++{
++	if (atomic_read(&priv->restrict_refcnt) <= 0)
++		IWL_ERROR("Release unheld nic access at line %s %d.\n", f, l);
++
++	IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
++	_iwl_release_nic_access(priv);
++}
++#define iwl_release_nic_access(priv) \
++	__iwl_release_nic_access(__FILE__, __LINE__, priv)
++#else
++#define iwl_release_nic_access(priv) \
++	_iwl_release_nic_access(priv)
++#endif
++
++static inline u32 _iwl_read_direct32(struct iwl_priv *priv, u32 reg)
++{
++	return _iwl_read32(priv, reg);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline u32 __iwl_read_direct32(const char *f, u32 l,
++					struct iwl_priv *priv, u32 reg)
++{
++	u32 value = _iwl_read_direct32(priv, reg);
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Nic access not held from %s %d\n", f, l);
++	IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
++		     f, l);
++	return value;
++}
++#define iwl_read_direct32(priv, reg) \
++	__iwl_read_direct32(__FILE__, __LINE__, priv, reg)
++#else
++#define iwl_read_direct32 _iwl_read_direct32
++#endif
++
++static inline void _iwl_write_direct32(struct iwl_priv *priv,
++					 u32 reg, u32 value)
++{
++	_iwl_write32(priv, reg, value);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static void __iwl_write_direct32(const char *f , u32 line,
++				   struct iwl_priv *priv, u32 reg, u32 value)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++	_iwl_write_direct32(priv, reg, value);
++}
++#define iwl_write_direct32(priv, reg, value) \
++	__iwl_write_direct32(__func__, __LINE__, priv, reg, value)
++#else
++#define iwl_write_direct32 _iwl_write_direct32
++#endif
++
++static inline void iwl_write_reg_buf(struct iwl_priv *priv,
++					       u32 reg, u32 len, u32 *values)
++{
++	u32 count = sizeof(u32);
++
++	if ((priv != NULL) && (values != NULL)) {
++		for (; 0 < len; len -= count, reg += count, values++)
++			_iwl_write_direct32(priv, reg, *values);
++	}
++}
++
++static inline int _iwl_poll_direct_bit(struct iwl_priv *priv,
++					   u32 addr, u32 mask, int timeout)
++{
++	int i = 0;
++
++	do {
++		if ((_iwl_read_direct32(priv, addr) & mask) == mask)
++			return i;
++		mdelay(10);
++		i += 10;
++	} while (i < timeout);
++
++	return -ETIMEDOUT;
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline int __iwl_poll_direct_bit(const char *f, u32 l,
++					    struct iwl_priv *priv,
++					    u32 addr, u32 mask, int timeout)
++{
++	int ret  = _iwl_poll_direct_bit(priv, addr, mask, timeout);
++
++	if (unlikely(ret == -ETIMEDOUT))
++		IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - "
++			     "timedout - %s %d\n", addr, mask, f, l);
++	else
++		IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
++			     "- %s %d\n", addr, mask, ret, f, l);
++	return ret;
++}
++#define iwl_poll_direct_bit(priv, addr, mask, timeout) \
++	__iwl_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
++#else
++#define iwl_poll_direct_bit _iwl_poll_direct_bit
++#endif
++
++static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg)
++{
++	_iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
++	return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline u32 __iwl_read_prph(const char *f, u32 line,
++				  struct iwl_priv *priv, u32 reg)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++	return _iwl_read_prph(priv, reg);
++}
++
++#define iwl_read_prph(priv, reg) \
++	__iwl_read_prph(__func__, __LINE__, priv, reg)
++#else
++#define iwl_read_prph _iwl_read_prph
++#endif
++
++static inline void _iwl_write_prph(struct iwl_priv *priv,
++					     u32 addr, u32 val)
++{
++	_iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
++			      ((addr & 0x0000FFFF) | (3 << 24)));
++	_iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_write_prph(const char *f, u32 line,
++				    struct iwl_priv *priv, u32 addr, u32 val)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++	_iwl_write_prph(priv, addr, val);
++}
++
++#define iwl_write_prph(priv, addr, val) \
++	__iwl_write_prph(__func__, __LINE__, priv, addr, val);
++#else
++#define iwl_write_prph _iwl_write_prph
++#endif
++
++#define _iwl_set_bits_prph(priv, reg, mask) \
++	_iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_set_bits_prph(const char *f, u32 line,
++				       struct iwl_priv *priv,
++				       u32 reg, u32 mask)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++
++	_iwl_set_bits_prph(priv, reg, mask);
++}
++#define iwl_set_bits_prph(priv, reg, mask) \
++	__iwl_set_bits_prph(__func__, __LINE__, priv, reg, mask)
++#else
++#define iwl_set_bits_prph _iwl_set_bits_prph
++#endif
++
++#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \
++	_iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits))
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_set_bits_mask_prph(const char *f, u32 line,
++		struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
++{
++	if (!atomic_read(&priv->restrict_refcnt))
++		IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++	_iwl_set_bits_mask_prph(priv, reg, bits, mask);
++}
++#define iwl_set_bits_mask_prph(priv, reg, bits, mask) \
++	__iwl_set_bits_mask_prph(__func__, __LINE__, priv, reg, bits, mask)
++#else
++#define iwl_set_bits_mask_prph _iwl_set_bits_mask_prph
++#endif
++
++static inline void iwl_clear_bits_prph(struct iwl_priv
++						 *priv, u32 reg, u32 mask)
++{
++	u32 val = _iwl_read_prph(priv, reg);
++	_iwl_write_prph(priv, reg, (val & ~mask));
++}
++
++static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
++{
++	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
++	return iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
++}
++
++static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
++{
++	iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
++	iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
++}
++
++static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
++					  u32 len, u32 *values)
++{
++	iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
++	for (; 0 < len; len -= sizeof(u32), values++)
++		iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
++}
++#endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
+new file mode 100644
+index 0000000..03fdf5b
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-led.c
+@@ -0,0 +1,449 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at 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/version.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/wireless.h>
++#include <net/mac80211.h>
++#include <linux/etherdevice.h>
++#include <asm/unaligned.h>
++
++#include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-io.h"
++#include "iwl-helpers.h"
++
++#define IWL_1MB_RATE (128 * 1024)
++#define IWL_LED_THRESHOLD (16)
++#define IWL_MAX_BLINK_TBL (10)
++
++static const struct {
++	u16 tpt;
++	u8 on_time;
++	u8 of_time;
++} blink_tbl[] =
++{
++	{300, 25, 25},
++	{200, 40, 40},
++	{100, 55, 55},
++	{70, 65, 65},
++	{50, 75, 75},
++	{20, 85, 85},
++	{15, 95, 95 },
++	{10, 110, 110},
++	{5, 130, 130},
++	{0, 167, 167}
++};
++
++static int iwl_led_cmd_callback(struct iwl_priv *priv,
++				struct iwl_cmd *cmd, struct sk_buff *skb)
++{
++	return 1;
++}
++
++
++/* Send led command */
++static int iwl_send_led_cmd(struct iwl_priv *priv,
++			    struct iwl4965_led_cmd *led_cmd)
++{
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_LEDS_CMD,
++		.len = sizeof(struct iwl4965_led_cmd),
++		.data = led_cmd,
++		.meta.flags = CMD_ASYNC,
++		.meta.u.callback = iwl_led_cmd_callback
++	};
++	u32 reg;
++
++	reg = iwl_read32(priv, CSR_LED_REG);
++	if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
++		iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
++
++	return iwl_send_cmd(priv, &cmd);
++}
++
++
++/* Set led on command */
++static int iwl4965_led_on(struct iwl_priv *priv, int led_id)
++{
++	struct iwl4965_led_cmd led_cmd = {
++		.id = led_id,
++		.on = IWL_LED_SOLID,
++		.off = 0,
++		.interval = IWL_DEF_LED_INTRVL
++	};
++	return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led on command */
++static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id,
++			       enum led_brightness brightness)
++{
++	struct iwl4965_led_cmd led_cmd = {
++		.id = led_id,
++		.on = brightness,
++		.off = brightness,
++		.interval = IWL_DEF_LED_INTRVL
++	};
++	if (brightness == LED_FULL) {
++		led_cmd.on = IWL_LED_SOLID;
++		led_cmd.off = 0;
++	}
++	return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led register off */
++static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id)
++{
++	IWL_DEBUG_LED("led on %d\n", led_id);
++	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
++	return 0;
++}
++
++#if 0
++/* Set led off command */
++int iwl4965_led_off(struct iwl_priv *priv, int led_id)
++{
++	struct iwl4965_led_cmd led_cmd = {
++		.id = led_id,
++		.on = 0,
++		.off = 0,
++		.interval = IWL_DEF_LED_INTRVL
++	};
++	IWL_DEBUG_LED("led off %d\n", led_id);
++	return iwl_send_led_cmd(priv, &led_cmd);
++}
++#endif
++
++
++/* Set led register off */
++static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id)
++{
++	IWL_DEBUG_LED("radio off\n");
++	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
++	return 0;
++}
++
++/* Set led blink command */
++static int iwl4965_led_not_solid(struct iwl_priv *priv, int led_id,
++			       u8 brightness)
++{
++	struct iwl4965_led_cmd led_cmd = {
++		.id = led_id,
++		.on = brightness,
++		.off = brightness,
++		.interval = IWL_DEF_LED_INTRVL
++	};
++
++	return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++
++/*
++ * brightness call back function for Tx/Rx LED
++ */
++static int iwl4965_led_associated(struct iwl_priv *priv, int led_id)
++{
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
++	    !test_bit(STATUS_READY, &priv->status))
++		return 0;
++
++
++	/* start counting Tx/Rx bytes */
++	if (!priv->last_blink_time && priv->allow_blinking)
++		priv->last_blink_time = jiffies;
++	return 0;
++}
++
++/*
++ * brightness call back for association and radio
++ */
++static void iwl4965_led_brightness_set(struct led_classdev *led_cdev,
++				       enum led_brightness brightness)
++{
++	struct iwl4965_led *led = container_of(led_cdev,
++					       struct iwl4965_led, led_dev);
++	struct iwl_priv *priv = led->priv;
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return;
++
++	switch (brightness) {
++	case LED_FULL:
++		if (led->type == IWL_LED_TRG_ASSOC)
++			priv->allow_blinking = 1;
++
++		if (led->led_on)
++			led->led_on(priv, IWL_LED_LINK);
++		break;
++	case LED_OFF:
++		if (led->type == IWL_LED_TRG_ASSOC)
++			priv->allow_blinking = 0;
++
++		if (led->led_off)
++			led->led_off(priv, IWL_LED_LINK);
++		break;
++	default:
++		if (led->led_pattern)
++			led->led_pattern(priv, IWL_LED_LINK, brightness);
++		break;
++	}
++}
++
++
++
++/*
++ * Register led class with the system
++ */
++static int iwl_leds_register_led(struct iwl_priv *priv,
++				   struct iwl4965_led *led,
++				   enum led_type type, u8 set_led,
++				   const char *name, char *trigger)
++{
++	struct device *device = wiphy_dev(priv->hw->wiphy);
++	int ret;
++
++	led->led_dev.name = name;
++	led->led_dev.brightness_set = iwl4965_led_brightness_set;
++	led->led_dev.default_trigger = trigger;
++
++	led->priv = priv;
++	led->type = type;
++
++	ret = led_classdev_register(device, &led->led_dev);
++	if (ret) {
++		IWL_ERROR("Error: failed to register led handler.\n");
++		return ret;
++	}
++
++	led->registered = 1;
++
++	if (set_led && led->led_on)
++		led->led_on(priv, IWL_LED_LINK);
++
++	return 0;
++}
++
++
++/*
++ * calculate blink rate according to last 2 sec Tx/Rx activities
++ */
++static inline u8 get_blink_rate(struct iwl_priv *priv)
++{
++	int i;
++	u8 blink_rate;
++	u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes;
++	s64 tpt = current_tpt - priv->led_tpt;
++
++	if (tpt < 0) /* wrapparound */
++		tpt = -tpt;
++
++	priv->led_tpt = current_tpt;
++
++	if (tpt < IWL_LED_THRESHOLD) {
++		i = IWL_MAX_BLINK_TBL;
++	} else {
++		for (i = 0; i < IWL_MAX_BLINK_TBL; i++)
++			if (tpt  > (blink_tbl[i].tpt * IWL_1MB_RATE))
++				break;
++	}
++	/* if 0 frame is transfered */
++	if ((i == IWL_MAX_BLINK_TBL) || !priv->allow_blinking)
++		blink_rate = IWL_LED_SOLID;
++	else
++		blink_rate = blink_tbl[i].on_time;
++
++	return blink_rate;
++}
++
++static inline int is_rf_kill(struct iwl_priv *priv)
++{
++	return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++		test_bit(STATUS_RF_KILL_SW, &priv->status);
++}
++
++/*
++ * this function called from handler. Since setting Led command can
++ * happen very frequent we postpone led command to be called from
++ * REPLY handler so we know ucode is up
++ */
++void iwl_leds_background(struct iwl_priv *priv)
++{
++	u8 blink_rate;
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++		priv->last_blink_time = 0;
++		return;
++	}
++	if (is_rf_kill(priv)) {
++		priv->last_blink_time = 0;
++		return;
++	}
++
++	if (!priv->allow_blinking) {
++		priv->last_blink_time = 0;
++		if (priv->last_blink_rate != IWL_LED_SOLID) {
++			priv->last_blink_rate = IWL_LED_SOLID;
++			iwl4965_led_on(priv, IWL_LED_LINK);
++		}
++		return;
++	}
++	if (!priv->last_blink_time ||
++	    !time_after(jiffies, priv->last_blink_time +
++			msecs_to_jiffies(1000)))
++		return;
++
++	blink_rate = get_blink_rate(priv);
++
++	/* call only if blink rate change */
++	if (blink_rate != priv->last_blink_rate) {
++		if (blink_rate != IWL_LED_SOLID) {
++			priv->last_blink_time = jiffies +
++						msecs_to_jiffies(1000);
++			iwl4965_led_not_solid(priv, IWL_LED_LINK, blink_rate);
++		} else {
++			priv->last_blink_time = 0;
++			iwl4965_led_on(priv, IWL_LED_LINK);
++		}
++	}
++
++	priv->last_blink_rate = blink_rate;
++}
++EXPORT_SYMBOL(iwl_leds_background);
++
++/* Register all led handler */
++int iwl_leds_register(struct iwl_priv *priv)
++{
++	char *trigger;
++	char name[32];
++	int ret;
++
++	priv->last_blink_rate = 0;
++	priv->led_tpt = 0;
++	priv->last_blink_time = 0;
++	priv->allow_blinking = 0;
++
++	trigger = ieee80211_get_radio_led_name(priv->hw);
++	snprintf(name, sizeof(name), "iwl-%s:radio",
++		 wiphy_name(priv->hw->wiphy));
++
++	priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg;
++	priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg;
++	priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
++
++	ret = iwl_leds_register_led(priv,
++				   &priv->led[IWL_LED_TRG_RADIO],
++				   IWL_LED_TRG_RADIO, 1,
++				   name, trigger);
++	if (ret)
++		goto exit_fail;
++
++	trigger = ieee80211_get_assoc_led_name(priv->hw);
++	snprintf(name, sizeof(name), "iwl-%s:assoc",
++		 wiphy_name(priv->hw->wiphy));
++
++	ret = iwl_leds_register_led(priv,
++				   &priv->led[IWL_LED_TRG_ASSOC],
++				   IWL_LED_TRG_ASSOC, 0,
++				   name, trigger);
++	/* for assoc always turn led on */
++	priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg;
++	priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg;
++	priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
++
++	if (ret)
++		goto exit_fail;
++
++	trigger = ieee80211_get_rx_led_name(priv->hw);
++	snprintf(name, sizeof(name), "iwl-%s:RX",
++		 wiphy_name(priv->hw->wiphy));
++
++
++	ret = iwl_leds_register_led(priv,
++				   &priv->led[IWL_LED_TRG_RX],
++				   IWL_LED_TRG_RX, 0,
++				   name, trigger);
++
++	priv->led[IWL_LED_TRG_RX].led_on = iwl4965_led_associated;
++	priv->led[IWL_LED_TRG_RX].led_off = iwl4965_led_associated;
++	priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern;
++
++	if (ret)
++		goto exit_fail;
++
++	trigger = ieee80211_get_tx_led_name(priv->hw);
++	snprintf(name, sizeof(name), "iwl-%s:TX",
++		 wiphy_name(priv->hw->wiphy));
++	ret = iwl_leds_register_led(priv,
++				   &priv->led[IWL_LED_TRG_TX],
++				   IWL_LED_TRG_TX, 0,
++				   name, trigger);
++	priv->led[IWL_LED_TRG_TX].led_on = iwl4965_led_associated;
++	priv->led[IWL_LED_TRG_TX].led_off = iwl4965_led_associated;
++	priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern;
++
++	if (ret)
++		goto exit_fail;
++
++	return 0;
++
++exit_fail:
++	iwl_leds_unregister(priv);
++	return ret;
++}
++EXPORT_SYMBOL(iwl_leds_register);
++
++/* unregister led class */
++static void iwl_leds_unregister_led(struct iwl4965_led *led, u8 set_led)
++{
++	if (!led->registered)
++		return;
++
++	led_classdev_unregister(&led->led_dev);
++
++	if (set_led)
++		led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++	led->registered = 0;
++}
++
++/* Unregister all led handlers */
++void iwl_leds_unregister(struct iwl_priv *priv)
++{
++	iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
++	iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
++	iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
++	iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
++}
++EXPORT_SYMBOL(iwl_leds_unregister);
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h
+new file mode 100644
+index 0000000..5bb0412
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-led.h
+@@ -0,0 +1,82 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_leds_h__
++#define __iwl_leds_h__
++
++
++struct iwl_priv;
++
++#ifdef CONFIG_IWLWIFI_LEDS
++#include <linux/leds.h>
++
++#define IWL_LED_SOLID 11
++#define IWL_LED_NAME_LEN 31
++#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000)
++
++#define IWL_LED_ACTIVITY       (0<<1)
++#define IWL_LED_LINK           (1<<1)
++
++enum led_type {
++	IWL_LED_TRG_TX,
++	IWL_LED_TRG_RX,
++	IWL_LED_TRG_ASSOC,
++	IWL_LED_TRG_RADIO,
++	IWL_LED_TRG_MAX,
++};
++
++
++struct iwl4965_led {
++	struct iwl_priv *priv;
++	struct led_classdev led_dev;
++
++	int (*led_on) (struct iwl_priv *priv, int led_id);
++	int (*led_off) (struct iwl_priv *priv, int led_id);
++	int (*led_pattern) (struct iwl_priv *priv, int led_id,
++			    enum led_brightness brightness);
++
++	enum led_type type;
++	unsigned int registered;
++};
++
++int iwl_leds_register(struct iwl_priv *priv);
++void iwl_leds_unregister(struct iwl_priv *priv);
++void iwl_leds_background(struct iwl_priv *priv);
++
++#else
++static inline int iwl_leds_register(struct iwl_priv *priv)
++{
++	return 0;
++}
++static inline void iwl_leds_unregister(struct iwl_priv *priv)
++{
++}
++static inline void iwl_leds_background(struct iwl_priv *priv)
++{
++}
++
++#endif /* CONFIG_IWLWIFI_LEDS */
++#endif /* __iwl_leds_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
+index 4ba1216..c9cf8ee 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
++++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
+@@ -5,7 +5,7 @@
+  *
+  * GPL LICENSE SUMMARY
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 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
+@@ -30,7 +30,7 @@
+  *
+  * BSD LICENSE
+  *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -243,44 +243,48 @@
+  * 4965 Tx Scheduler registers.
+  * Details are documented in iwl-4965-hw.h
+  */
+-#define KDR_SCD_BASE		(PRPH_BASE + 0xa02c00)
++#define IWL49_SCD_BASE		(PRPH_BASE + 0xa02c00)
+ 
+-#define KDR_SCD_SRAM_BASE_ADDR         (KDR_SCD_BASE + 0x0)
+-#define KDR_SCD_EMPTY_BITS             (KDR_SCD_BASE + 0x4)
+-#define KDR_SCD_DRAM_BASE_ADDR         (KDR_SCD_BASE + 0x10)
+-#define KDR_SCD_AIT                    (KDR_SCD_BASE + 0x18)
+-#define KDR_SCD_TXFACT                 (KDR_SCD_BASE + 0x1c)
+-#define KDR_SCD_QUEUE_WRPTR(x)         (KDR_SCD_BASE + 0x24 + (x) * 4)
+-#define KDR_SCD_QUEUE_RDPTR(x)         (KDR_SCD_BASE + 0x64 + (x) * 4)
+-#define KDR_SCD_SETQUEUENUM            (KDR_SCD_BASE + 0xa4)
+-#define KDR_SCD_SET_TXSTAT_TXED        (KDR_SCD_BASE + 0xa8)
+-#define KDR_SCD_SET_TXSTAT_DONE        (KDR_SCD_BASE + 0xac)
+-#define KDR_SCD_SET_TXSTAT_NOT_SCHD    (KDR_SCD_BASE + 0xb0)
+-#define KDR_SCD_DECREASE_CREDIT        (KDR_SCD_BASE + 0xb4)
+-#define KDR_SCD_DECREASE_SCREDIT       (KDR_SCD_BASE + 0xb8)
+-#define KDR_SCD_LOAD_CREDIT            (KDR_SCD_BASE + 0xbc)
+-#define KDR_SCD_LOAD_SCREDIT           (KDR_SCD_BASE + 0xc0)
+-#define KDR_SCD_BAR                    (KDR_SCD_BASE + 0xc4)
+-#define KDR_SCD_BAR_DW0                (KDR_SCD_BASE + 0xc8)
+-#define KDR_SCD_BAR_DW1                (KDR_SCD_BASE + 0xcc)
+-#define KDR_SCD_QUEUECHAIN_SEL         (KDR_SCD_BASE + 0xd0)
+-#define KDR_SCD_QUERY_REQ              (KDR_SCD_BASE + 0xd8)
+-#define KDR_SCD_QUERY_RES              (KDR_SCD_BASE + 0xdc)
+-#define KDR_SCD_PENDING_FRAMES         (KDR_SCD_BASE + 0xe0)
+-#define KDR_SCD_INTERRUPT_MASK         (KDR_SCD_BASE + 0xe4)
+-#define KDR_SCD_INTERRUPT_THRESHOLD    (KDR_SCD_BASE + 0xe8)
+-#define KDR_SCD_QUERY_MIN_FRAME_SIZE   (KDR_SCD_BASE + 0x100)
+-#define KDR_SCD_QUEUE_STATUS_BITS(x)   (KDR_SCD_BASE + 0x104 + (x) * 4)
++#define IWL49_SCD_SRAM_BASE_ADDR         (IWL49_SCD_BASE + 0x0)
++#define IWL49_SCD_EMPTY_BITS             (IWL49_SCD_BASE + 0x4)
++#define IWL49_SCD_DRAM_BASE_ADDR         (IWL49_SCD_BASE + 0x10)
++#define IWL49_SCD_AIT                    (IWL49_SCD_BASE + 0x18)
++#define IWL49_SCD_TXFACT                 (IWL49_SCD_BASE + 0x1c)
++#define IWL49_SCD_QUEUE_WRPTR(x)         (IWL49_SCD_BASE + 0x24 + (x) * 4)
++#define IWL49_SCD_QUEUE_RDPTR(x)         (IWL49_SCD_BASE + 0x64 + (x) * 4)
++#define IWL49_SCD_SETQUEUENUM            (IWL49_SCD_BASE + 0xa4)
++#define IWL49_SCD_SET_TXSTAT_TXED        (IWL49_SCD_BASE + 0xa8)
++#define IWL49_SCD_SET_TXSTAT_DONE        (IWL49_SCD_BASE + 0xac)
++#define IWL49_SCD_SET_TXSTAT_NOT_SCHD    (IWL49_SCD_BASE + 0xb0)
++#define IWL49_SCD_DECREASE_CREDIT        (IWL49_SCD_BASE + 0xb4)
++#define IWL49_SCD_DECREASE_SCREDIT       (IWL49_SCD_BASE + 0xb8)
++#define IWL49_SCD_LOAD_CREDIT            (IWL49_SCD_BASE + 0xbc)
++#define IWL49_SCD_LOAD_SCREDIT           (IWL49_SCD_BASE + 0xc0)
++#define IWL49_SCD_BAR                    (IWL49_SCD_BASE + 0xc4)
++#define IWL49_SCD_BAR_DW0                (IWL49_SCD_BASE + 0xc8)
++#define IWL49_SCD_BAR_DW1                (IWL49_SCD_BASE + 0xcc)
++#define IWL49_SCD_QUEUECHAIN_SEL         (IWL49_SCD_BASE + 0xd0)
++#define IWL49_SCD_QUERY_REQ              (IWL49_SCD_BASE + 0xd8)
++#define IWL49_SCD_QUERY_RES              (IWL49_SCD_BASE + 0xdc)
++#define IWL49_SCD_PENDING_FRAMES         (IWL49_SCD_BASE + 0xe0)
++#define IWL49_SCD_INTERRUPT_MASK         (IWL49_SCD_BASE + 0xe4)
++#define IWL49_SCD_INTERRUPT_THRESHOLD    (IWL49_SCD_BASE + 0xe8)
++#define IWL49_SCD_QUERY_MIN_FRAME_SIZE   (IWL49_SCD_BASE + 0x100)
++#define IWL49_SCD_QUEUE_STATUS_BITS(x)   (IWL49_SCD_BASE + 0x104 + (x) * 4)
+ 
+ /* SP SCD */
+-#define SHL_SCD_BASE			(PRPH_BASE + 0xa02c00)
++#define IWL50_SCD_BASE			(PRPH_BASE + 0xa02c00)
+ 
+-#define SHL_SCD_AIT                    (SHL_SCD_BASE + 0x0c)
+-#define SHL_SCD_TXFACT                 (SHL_SCD_BASE + 0x10)
+-#define SHL_SCD_QUEUE_WRPTR(x)         (SHL_SCD_BASE + 0x18 + (x) * 4)
+-#define SHL_SCD_QUEUE_RDPTR(x)         (SHL_SCD_BASE + 0x68 + (x) * 4)
+-#define SHL_SCD_QUEUECHAIN_SEL         (SHL_SCD_BASE + 0xe8)
+-#define SHL_SCD_AGGR_SEL	       (SHL_SCD_BASE + 0x248)
+-#define SHL_SCD_INTERRUPT_MASK         (SHL_SCD_BASE + 0x108)
++#define IWL50_SCD_SRAM_BASE_ADDR         (IWL50_SCD_BASE + 0x0)
++#define IWL50_SCD_DRAM_BASE_ADDR	 (IWL50_SCD_BASE + 0x8)
++#define IWL50_SCD_AIT                    (IWL50_SCD_BASE + 0x0c)
++#define IWL50_SCD_TXFACT                 (IWL50_SCD_BASE + 0x10)
++#define IWL50_SCD_ACTIVE		 (IWL50_SCD_BASE + 0x14)
++#define IWL50_SCD_QUEUE_WRPTR(x)         (IWL50_SCD_BASE + 0x18 + (x) * 4)
++#define IWL50_SCD_QUEUE_RDPTR(x)         (IWL50_SCD_BASE + 0x68 + (x) * 4)
++#define IWL50_SCD_QUEUECHAIN_SEL         (IWL50_SCD_BASE + 0xe8)
++#define IWL50_SCD_AGGR_SEL	     	 (IWL50_SCD_BASE + 0x248)
++#define IWL50_SCD_INTERRUPT_MASK         (IWL50_SCD_BASE + 0x108)
++#define IWL50_SCD_QUEUE_STATUS_BITS(x)   (IWL50_SCD_BASE + 0x10c + (x) * 4)
+ 
+ #endif				/* __iwl_prph_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+new file mode 100644
+index 0000000..5980a56
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+@@ -0,0 +1,173 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 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:
++ * James P. Ketrenos <ipw2100-admin at 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/version.h>
++#include <linux/init.h>
++
++#include <net/mac80211.h>
++
++#include "iwl-eeprom.h"
++#include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-helpers.h"
++
++
++/* software rf-kill from user */
++static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
++{
++	struct iwl_priv *priv = data;
++	int err = 0;
++
++	if (!priv->rfkill_mngr.rfkill)
++		return 0;
++
++	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++		return 0;
++
++	IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
++	mutex_lock(&priv->mutex);
++
++	switch (state) {
++	case RFKILL_STATE_ON:
++		priv->cfg->ops->lib->radio_kill_sw(priv, 0);
++		/* if HW rf-kill is set dont allow ON state */
++		if (iwl_is_rfkill(priv))
++			err = -EBUSY;
++		break;
++	case RFKILL_STATE_OFF:
++		priv->cfg->ops->lib->radio_kill_sw(priv, 1);
++		if (!iwl_is_rfkill(priv))
++			err = -EBUSY;
++		break;
++	}
++	mutex_unlock(&priv->mutex);
++
++	return err;
++}
++
++int iwl_rfkill_init(struct iwl_priv *priv)
++{
++	struct device *device = wiphy_dev(priv->hw->wiphy);
++	int ret = 0;
++
++	BUG_ON(device == NULL);
++
++	IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
++	priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
++	if (!priv->rfkill_mngr.rfkill) {
++		IWL_ERROR("Unable to allocate rfkill device.\n");
++		ret = -ENOMEM;
++		goto error;
++	}
++
++	priv->rfkill_mngr.rfkill->name = priv->cfg->name;
++	priv->rfkill_mngr.rfkill->data = priv;
++	priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
++	priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
++	priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
++
++	priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
++	priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
++
++	priv->rfkill_mngr.input_dev = input_allocate_device();
++	if (!priv->rfkill_mngr.input_dev) {
++		IWL_ERROR("Unable to allocate rfkill input device.\n");
++		ret = -ENOMEM;
++		goto freed_rfkill;
++	}
++
++	priv->rfkill_mngr.input_dev->name = priv->cfg->name;
++	priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy);
++	priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST;
++	priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor;
++	priv->rfkill_mngr.input_dev->dev.parent = device;
++	priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY);
++	set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit);
++
++	ret = rfkill_register(priv->rfkill_mngr.rfkill);
++	if (ret) {
++		IWL_ERROR("Unable to register rfkill: %d\n", ret);
++		goto free_input_dev;
++	}
++
++	ret = input_register_device(priv->rfkill_mngr.input_dev);
++	if (ret) {
++		IWL_ERROR("Unable to register rfkill input device: %d\n", ret);
++		goto unregister_rfkill;
++	}
++
++	IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
++	return ret;
++
++unregister_rfkill:
++	rfkill_unregister(priv->rfkill_mngr.rfkill);
++	priv->rfkill_mngr.rfkill = NULL;
++
++free_input_dev:
++	input_free_device(priv->rfkill_mngr.input_dev);
++	priv->rfkill_mngr.input_dev = NULL;
++
++freed_rfkill:
++	if (priv->rfkill_mngr.rfkill != NULL)
++		rfkill_free(priv->rfkill_mngr.rfkill);
++	priv->rfkill_mngr.rfkill = NULL;
++
++error:
++	IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
++	return ret;
++}
++EXPORT_SYMBOL(iwl_rfkill_init);
++
++void iwl_rfkill_unregister(struct iwl_priv *priv)
++{
++
++	if (priv->rfkill_mngr.input_dev)
++		input_unregister_device(priv->rfkill_mngr.input_dev);
++
++	if (priv->rfkill_mngr.rfkill)
++		rfkill_unregister(priv->rfkill_mngr.rfkill);
++
++	priv->rfkill_mngr.input_dev = NULL;
++	priv->rfkill_mngr.rfkill = NULL;
++}
++EXPORT_SYMBOL(iwl_rfkill_unregister);
++
++/* set rf-kill to the right state. */
++void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
++{
++
++	if (!priv->rfkill_mngr.rfkill)
++		return;
++
++	if (!iwl_is_rfkill(priv))
++		priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
++	else
++		priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
++}
++EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
+diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
+new file mode 100644
+index 0000000..a7f04b8
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
+@@ -0,0 +1,54 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2007 - 2008 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:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *****************************************************************************/
++#ifndef __iwl_rf_kill_h__
++#define __iwl_rf_kill_h__
++
++struct iwl_priv;
++
++#include <linux/rfkill.h>
++#include <linux/input.h>
++
++
++#ifdef CONFIG_IWLWIFI_RFKILL
++struct iwl_rfkill_mngr {
++	struct rfkill *rfkill;
++	struct input_dev *input_dev;
++};
++
++void iwl_rfkill_set_hw_state(struct iwl_priv *priv);
++void iwl_rfkill_unregister(struct iwl_priv *priv);
++int iwl_rfkill_init(struct iwl_priv *priv);
++#else
++static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {}
++static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {}
++static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; }
++#endif
++
++
++
++#endif  /* __iwl_rf_kill_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h
+index b576ff2..a40a217 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h
++++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+  *
+  * Portions of this file are derived from the ieee80211 subsystem header files.
+  *
+diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
+new file mode 100644
+index 0000000..e4fdfaa
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
+@@ -0,0 +1,355 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 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:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#include <net/mac80211.h>
++
++#include "iwl-eeprom.h"
++#include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-sta.h"
++#include "iwl-io.h"
++#include "iwl-helpers.h"
++#include "iwl-4965.h"
++#include "iwl-sta.h"
++
++int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
++{
++	int i;
++
++	for (i = 0; i < STA_KEY_MAX_NUM; i++)
++		if (!test_and_set_bit(i, &priv->ucode_key_table))
++			return i;
++
++	return -1;
++}
++
++int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 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 = REPLY_WEPKEY,
++		.data = wep_cmd,
++		.meta.flags = CMD_ASYNC,
++	};
++
++	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_remove_default_wep_key(struct iwl_priv *priv,
++			       struct ieee80211_key_conf *keyconf)
++{
++	int ret;
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++
++	if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table))
++		IWL_ERROR("index %d not used in uCode key table.\n",
++			  keyconf->keyidx);
++
++	priv->default_wep_key--;
++	memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
++	ret = iwl_send_static_wepkey_cmd(priv, 1);
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++	return ret;
++}
++
++int iwl_set_default_wep_key(struct iwl_priv *priv,
++			    struct ieee80211_key_conf *keyconf)
++{
++	int ret;
++	unsigned long flags;
++
++	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
++	keyconf->hw_key_idx = keyconf->keyidx;
++	priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++	priv->default_wep_key++;
++
++	if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table))
++		IWL_ERROR("index %d already used in uCode key table.\n",
++			keyconf->keyidx);
++
++	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);
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++	return ret;
++}
++
++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;
++	int ret;
++
++	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
++	keyconf->hw_key_idx = keyconf->keyidx;
++
++	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);
++
++	priv->stations[sta_id].sta.key.key_offset =
++				 iwl_get_free_ucode_key_index(priv);
++	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;
++
++	ret = iwl4965_send_add_station(priv,
++		&priv->stations[sta_id].sta, CMD_ASYNC);
++
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++	return ret;
++}
++
++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;
++
++	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;
++	keyconf->hw_key_idx = keyconf->keyidx;
++
++	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);
++
++	priv->stations[sta_id].sta.key.key_offset =
++				iwl_get_free_ucode_key_index(priv);
++	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;
++
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++	IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
++	return iwl4965_send_add_station(priv,
++				&priv->stations[sta_id].sta, CMD_ASYNC);
++}
++
++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;
++
++	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
++	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
++	keyconf->hw_key_idx = keyconf->keyidx;
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++
++	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
++	priv->stations[sta_id].keyinfo.conf = keyconf;
++	priv->stations[sta_id].keyinfo.keylen = 16;
++	priv->stations[sta_id].sta.key.key_offset =
++				 iwl_get_free_ucode_key_index(priv);
++
++	/* 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;
++}
++
++int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id)
++{
++	unsigned long flags;
++
++	priv->key_mapping_key = 0;
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++	if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
++		&priv->ucode_key_table))
++		IWL_ERROR("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 iwl4965_hw_key));
++	memset(&priv->stations[sta_id].sta.key, 0,
++					sizeof(struct iwl4965_keyinfo));
++	priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
++	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
++	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++	IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
++	return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
++}
++
++int iwl_set_dynamic_key(struct iwl_priv *priv,
++				struct ieee80211_key_conf *key, u8 sta_id)
++{
++	int ret;
++
++	priv->key_mapping_key = 1;
++
++	switch (key->alg) {
++	case ALG_CCMP:
++		ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id);
++		break;
++	case ALG_TKIP:
++		ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id);
++		break;
++	case ALG_WEP:
++		ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id);
++		break;
++	default:
++		IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static void iwl_dump_lq_cmd(struct iwl_priv *priv,
++			   struct iwl_link_quality_cmd *lq)
++{
++	int i;
++	IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id);
++	IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n",
++		       lq->general_params.single_stream_ant_msk,
++		       lq->general_params.dual_stream_ant_msk);
++
++	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
++		IWL_DEBUG_RATE("lq index %d 0x%X\n",
++			       i, lq->rs_table[i].rate_n_flags);
++}
++#else
++static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
++				   struct iwl_link_quality_cmd *lq)
++{
++}
++#endif
++
++int iwl_send_lq_cmd(struct iwl_priv *priv,
++		    struct iwl_link_quality_cmd *lq, u8 flags)
++{
++	struct iwl_host_cmd cmd = {
++		.id = REPLY_TX_LINK_QUALITY_CMD,
++		.len = sizeof(struct iwl_link_quality_cmd),
++		.meta.flags = flags,
++		.data = lq,
++	};
++
++	if ((lq->sta_id == 0xFF) &&
++	    (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
++		return -EINVAL;
++
++	if (lq->sta_id == 0xFF)
++		lq->sta_id = IWL_AP_ID;
++
++	iwl_dump_lq_cmd(priv,lq);
++
++	if (iwl_is_associated(priv) && priv->assoc_station_added &&
++	    priv->lq_mngr.lq_ready)
++		return  iwl_send_cmd(priv, &cmd);
++
++	return 0;
++}
++EXPORT_SYMBOL(iwl_send_lq_cmd);
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
+new file mode 100644
+index 0000000..44f272e
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
+@@ -0,0 +1,49 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 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:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++#ifndef __iwl_sta_h__
++#define __iwl_sta_h__
++
++#include <net/mac80211.h>
++
++#include "iwl-eeprom.h"
++#include "iwl-core.h"
++#include "iwl-4965.h"
++#include "iwl-io.h"
++#include "iwl-helpers.h"
++
++int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
++int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty);
++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_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id);
++int iwl_set_dynamic_key(struct iwl_priv *priv,
++				struct ieee80211_key_conf *key, u8 sta_id);
++#endif /* __iwl_sta_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
+index cbaeaf1..a1a0b3c 100644
+--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 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.
+@@ -46,6 +46,7 @@
+ 
+ #include <asm/div64.h>
+ 
++#include "iwl-3945-core.h"
+ #include "iwl-3945.h"
+ #include "iwl-helpers.h"
+ 
+@@ -69,7 +70,7 @@ static int iwl3945_param_disable;  /* def: 0 = enable radio */
+ static int iwl3945_param_antenna;  /* def: 0 = both antennas (use diversity) */
+ int iwl3945_param_hwcrypto;        /* def: 0 = use software encryption */
+ static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
+-int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
++int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
+ 
+ /*
+  * module name, copyright, version, etc.
+@@ -91,15 +92,10 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
+ #define VS
+ #endif
+ 
+-#define IWLWIFI_VERSION "1.2.23k" VD VS
+-#define DRV_COPYRIGHT	"Copyright(c) 2003-2007 Intel Corporation"
++#define IWLWIFI_VERSION "1.2.26k" VD VS
++#define DRV_COPYRIGHT	"Copyright(c) 2003-2008 Intel Corporation"
+ #define DRV_VERSION     IWLWIFI_VERSION
+ 
+-/* Change firmware file name, using "-" and incrementing number,
+- *   *only* when uCode interface or architecture changes so that it
+- *   is not compatible with earlier drivers.
+- * This number will also appear in << 8 position of 1st dword of uCode file */
+-#define IWL3945_UCODE_API "-1"
+ 
+ MODULE_DESCRIPTION(DRV_DESCRIPTION);
+ MODULE_VERSION(DRV_VERSION);
+@@ -116,16 +112,10 @@ static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
+ 	return NULL;
+ }
+ 
+-static const struct ieee80211_hw_mode *iwl3945_get_hw_mode(
+-		struct iwl3945_priv *priv, int mode)
++static const struct ieee80211_supported_band *iwl3945_get_band(
++		struct iwl3945_priv *priv, enum ieee80211_band band)
+ {
+-	int i;
+-
+-	for (i = 0; i < 3; i++)
+-		if (priv->modes[i].mode == mode)
+-			return &priv->modes[i];
+-
+-	return NULL;
++	return priv->hw->wiphy->bands[band];
+ }
+ 
+ static int iwl3945_is_empty_essid(const char *essid, int essid_len)
+@@ -168,17 +158,6 @@ static const char *iwl3945_escape_essid(const char *essid, u8 essid_len)
+ 	return escaped;
+ }
+ 
+-static void iwl3945_print_hex_dump(int level, void *p, u32 len)
+-{
+-#ifdef CONFIG_IWL3945_DEBUG
+-	if (!(iwl3945_debug_level & level))
+-		return;
+-
+-	print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
+-			p, len, 1);
+-#endif
+-}
+-
+ /*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
+  * DMA services
+  *
+@@ -204,7 +183,7 @@ static void iwl3945_print_hex_dump(int level, void *p, u32 len)
+  * (#0-3) for data tx via EDCA.  An additional 2 HCCA queues are unused.
+  ***************************************************/
+ 
+-static int iwl3945_queue_space(const struct iwl3945_queue *q)
++int iwl3945_queue_space(const struct iwl3945_queue *q)
+ {
+ 	int s = q->read_ptr - q->write_ptr;
+ 
+@@ -220,33 +199,14 @@ static int iwl3945_queue_space(const struct iwl3945_queue *q)
+ 	return s;
+ }
+ 
+-/**
+- * iwl3945_queue_inc_wrap - increment queue index, wrap back to beginning
+- * @index -- current index
+- * @n_bd -- total number of entries in queue (must be power of 2)
+- */
+-static inline int iwl3945_queue_inc_wrap(int index, int n_bd)
+-{
+-	return ++index & (n_bd - 1);
+-}
+-
+-/**
+- * iwl3945_queue_dec_wrap - increment queue index, wrap back to end
+- * @index -- current index
+- * @n_bd -- total number of entries in queue (must be power of 2)
+- */
+-static inline int iwl3945_queue_dec_wrap(int index, int n_bd)
+-{
+-	return --index & (n_bd - 1);
+-}
+-
+-static inline int x2_queue_used(const struct iwl3945_queue *q, int i)
++int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i)
+ {
+ 	return q->write_ptr > q->read_ptr ?
+ 		(i >= q->read_ptr && i < q->write_ptr) :
+ 		!(i < q->read_ptr && i >= q->write_ptr);
+ }
+ 
++
+ static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge)
+ {
+ 	/* This is for scan command, the big buffer at end of command array */
+@@ -267,8 +227,8 @@ static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q
+ 	q->n_window = slots_num;
+ 	q->id = id;
+ 
+-	/* count must be power-of-two size, otherwise iwl3945_queue_inc_wrap
+-	 * and iwl3945_queue_dec_wrap are broken. */
++	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
++	 * and iwl_queue_dec_wrap are broken. */
+ 	BUG_ON(!is_power_of_2(count));
+ 
+ 	/* slots_num must be power-of-two size, otherwise
+@@ -368,7 +328,7 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
+ 	txq->need_update = 0;
+ 
+ 	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+-	 * iwl3945_queue_inc_wrap and iwl3945_queue_dec_wrap are broken. */
++	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+ 	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+ 
+ 	/* Initialize queue high/low-water, head/tail indexes */
+@@ -399,7 +359,7 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t
+ 
+ 	/* first, empty all BD's */
+ 	for (; q->write_ptr != q->read_ptr;
+-	     q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd))
++	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
+ 		iwl3945_hw_txq_free_tfd(priv, txq);
+ 
+ 	len = sizeof(struct iwl3945_cmd) * q->n_window;
+@@ -547,7 +507,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
+ 	station->sta.sta.sta_id = index;
+ 	station->sta.station_flags = 0;
+ 
+-	if (priv->phymode == MODE_IEEE80211A)
++	if (priv->band == IEEE80211_BAND_5GHZ)
+ 		rate = IWL_RATE_6M_PLCP;
+ 	else
+ 		rate =	IWL_RATE_1M_PLCP;
+@@ -738,7 +698,7 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c
+ 	txq->need_update = 1;
+ 
+ 	/* Increment and update queue's write index */
+-	q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
++	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ 	ret = iwl3945_tx_queue_update_write_ptr(priv, txq);
+ 
+ 	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+@@ -773,17 +733,17 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_
+ {
+ 	int cmd_idx;
+ 	int ret;
+-	static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
+ 
+ 	BUG_ON(cmd->meta.flags & CMD_ASYNC);
+ 
+ 	 /* A synchronous command can not have a callback set. */
+ 	BUG_ON(cmd->meta.u.callback != NULL);
+ 
+-	if (atomic_xchg(&entry, 1)) {
++	if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
+ 		IWL_ERROR("Error sending %s: Already sending a host command\n",
+ 			  get_cmd_string(cmd->id));
+-		return -EBUSY;
++		ret = -EBUSY;
++		goto out;
+ 	}
+ 
+ 	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+@@ -853,7 +813,7 @@ fail:
+ 		cmd->meta.u.skb = NULL;
+ 	}
+ out:
+-	atomic_set(&entry, 0);
++	clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
+ 	return ret;
+ }
+ 
+@@ -894,35 +854,37 @@ int iwl3945_send_statistics_request(struct iwl3945_priv *priv)
+ 
+ /**
+  * iwl3945_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
++ * @band: 2.4 or 5 GHz band
++ * @channel: Any channel valid for the requested band
+ 
+- * In addition to setting the staging RXON, priv->phymode is also set.
++ * In addition to setting the staging RXON, priv->band 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 band
+  */
+-static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, u8 phymode, u16 channel)
++static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv,
++				    enum ieee80211_band band,
++				    u16 channel)
+ {
+-	if (!iwl3945_get_channel_info(priv, phymode, channel)) {
++	if (!iwl3945_get_channel_info(priv, band, channel)) {
+ 		IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
+-			       channel, phymode);
++			       channel, band);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
+-	    (priv->phymode == phymode))
++	    (priv->band == band))
+ 		return 0;
+ 
+ 	priv->staging_rxon.channel = cpu_to_le16(channel);
+-	if (phymode == MODE_IEEE80211A)
++	if (band == IEEE80211_BAND_5GHZ)
+ 		priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
+ 	else
+ 		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
+ 
+-	priv->phymode = phymode;
++	priv->band = band;
+ 
+-	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
++	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
+ 
+ 	return 0;
+ }
+@@ -1210,8 +1172,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
+ 			return -EIO;
+ 		}
+ 
+-	/* Init the hardware's rate fallback order based on the
+-	 * phymode */
++	/* Init the hardware's rate fallback order based on the band */
+ 	rc = iwl3945_init_hw_rate_table(priv);
+ 	if (rc) {
+ 		IWL_ERROR("Error setting HW rate table: %02X\n", rc);
+@@ -1635,151 +1596,6 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
+ 	return 0;
+ }
+ 
+-/******************************************************************************
+- *
+- * Misc. internal state and helper functions
+- *
+- ******************************************************************************/
+-#ifdef CONFIG_IWL3945_DEBUG
+-
+-/**
+- * iwl3945_report_frame - dump frame to syslog during debug sessions
+- *
+- * You may hack this function to show different aspects of received frames,
+- * including selective frame dumps.
+- * group100 parameter selects whether to show 1 out of 100 good frames.
+- */
+-void iwl3945_report_frame(struct iwl3945_priv *priv,
+-		      struct iwl3945_rx_packet *pkt,
+-		      struct ieee80211_hdr *header, int group100)
+-{
+-	u32 to_us;
+-	u32 print_summary = 0;
+-	u32 print_dump = 0;	/* set to 1 to dump all frames' contents */
+-	u32 hundred = 0;
+-	u32 dataframe = 0;
+-	u16 fc;
+-	u16 seq_ctl;
+-	u16 channel;
+-	u16 phy_flags;
+-	int rate_sym;
+-	u16 length;
+-	u16 status;
+-	u16 bcn_tmr;
+-	u32 tsf_low;
+-	u64 tsf;
+-	u8 rssi;
+-	u8 agc;
+-	u16 sig_avg;
+-	u16 noise_diff;
+-	struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+-	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+-	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
+-	u8 *data = IWL_RX_DATA(pkt);
+-
+-	/* MAC header */
+-	fc = le16_to_cpu(header->frame_control);
+-	seq_ctl = le16_to_cpu(header->seq_ctrl);
+-
+-	/* metadata */
+-	channel = le16_to_cpu(rx_hdr->channel);
+-	phy_flags = le16_to_cpu(rx_hdr->phy_flags);
+-	rate_sym = rx_hdr->rate;
+-	length = le16_to_cpu(rx_hdr->len);
+-
+-	/* end-of-frame status and timestamp */
+-	status = le32_to_cpu(rx_end->status);
+-	bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
+-	tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
+-	tsf = le64_to_cpu(rx_end->timestamp);
+-
+-	/* signal statistics */
+-	rssi = rx_stats->rssi;
+-	agc = rx_stats->agc;
+-	sig_avg = le16_to_cpu(rx_stats->sig_avg);
+-	noise_diff = le16_to_cpu(rx_stats->noise_diff);
+-
+-	to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
+-
+-	/* if data frame is to us and all is good,
+-	 *   (optionally) print summary for only 1 out of every 100 */
+-	if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
+-	    (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
+-		dataframe = 1;
+-		if (!group100)
+-			print_summary = 1;	/* print each frame */
+-		else if (priv->framecnt_to_us < 100) {
+-			priv->framecnt_to_us++;
+-			print_summary = 0;
+-		} else {
+-			priv->framecnt_to_us = 0;
+-			print_summary = 1;
+-			hundred = 1;
+-		}
+-	} else {
+-		/* print summary for all other frames */
+-		print_summary = 1;
+-	}
+-
+-	if (print_summary) {
+-		char *title;
+-		u32 rate;
+-
+-		if (hundred)
+-			title = "100Frames";
+-		else if (fc & IEEE80211_FCTL_RETRY)
+-			title = "Retry";
+-		else if (ieee80211_is_assoc_response(fc))
+-			title = "AscRsp";
+-		else if (ieee80211_is_reassoc_response(fc))
+-			title = "RasRsp";
+-		else if (ieee80211_is_probe_response(fc)) {
+-			title = "PrbRsp";
+-			print_dump = 1;	/* dump frame contents */
+-		} else if (ieee80211_is_beacon(fc)) {
+-			title = "Beacon";
+-			print_dump = 1;	/* dump frame contents */
+-		} else if (ieee80211_is_atim(fc))
+-			title = "ATIM";
+-		else if (ieee80211_is_auth(fc))
+-			title = "Auth";
+-		else if (ieee80211_is_deauth(fc))
+-			title = "DeAuth";
+-		else if (ieee80211_is_disassoc(fc))
+-			title = "DisAssoc";
+-		else
+-			title = "Frame";
+-
+-		rate = iwl3945_rate_index_from_plcp(rate_sym);
+-		if (rate == -1)
+-			rate = 0;
+-		else
+-			rate = iwl3945_rates[rate].ieee / 2;
+-
+-		/* print frame summary.
+-		 * MAC addresses show just the last byte (for brevity),
+-		 *    but you can hack it to show more, if you'd like to. */
+-		if (dataframe)
+-			IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
+-				     "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
+-				     title, fc, header->addr1[5],
+-				     length, rssi, channel, rate);
+-		else {
+-			/* src/dst addresses assume managed mode */
+-			IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
+-				     "src=0x%02x, rssi=%u, tim=%lu usec, "
+-				     "phy=0x%02x, chnl=%d\n",
+-				     title, fc, header->addr1[5],
+-				     header->addr3[5], rssi,
+-				     tsf_low - priv->scan_start_tsf,
+-				     phy_flags, channel);
+-		}
+-	}
+-	if (print_dump)
+-		iwl3945_print_hex_dump(IWL_DL_RX, data, length);
+-}
+-#endif
+-
+ static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv)
+ {
+ 	if (priv->hw_setting.shared_virt)
+@@ -1915,7 +1731,6 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
+ /*
+  * QoS  support
+ */
+-#ifdef CONFIG_IWL3945_QOS
+ static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv,
+ 				       struct iwl3945_qosparam_cmd *qos)
+ {
+@@ -2044,7 +1859,6 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
+ 	}
+ }
+ 
+-#endif /* CONFIG_IWL3945_QOS */
+ /*
+  * Power management (not Tx power!) functions
+  */
+@@ -2244,39 +2058,13 @@ int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *h
+ 			return !compare_ether_addr(header->addr2, priv->bssid);
+ 		/* packets to our adapter go through */
+ 		return !compare_ether_addr(header->addr1, priv->mac_addr);
++	default:
++		return 1;
+ 	}
+ 
+ 	return 1;
+ }
+ 
+-#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
+-
+-static const char *iwl3945_get_tx_fail_reason(u32 status)
+-{
+-	switch (status & TX_STATUS_MSK) {
+-	case TX_STATUS_SUCCESS:
+-		return "SUCCESS";
+-		TX_STATUS_ENTRY(SHORT_LIMIT);
+-		TX_STATUS_ENTRY(LONG_LIMIT);
+-		TX_STATUS_ENTRY(FIFO_UNDERRUN);
+-		TX_STATUS_ENTRY(MGMNT_ABORT);
+-		TX_STATUS_ENTRY(NEXT_FRAG);
+-		TX_STATUS_ENTRY(LIFE_EXPIRE);
+-		TX_STATUS_ENTRY(DEST_PS);
+-		TX_STATUS_ENTRY(ABORTED);
+-		TX_STATUS_ENTRY(BT_RETRY);
+-		TX_STATUS_ENTRY(STA_INVALID);
+-		TX_STATUS_ENTRY(FRAG_DROPPED);
+-		TX_STATUS_ENTRY(TID_DISABLE);
+-		TX_STATUS_ENTRY(FRAME_FLUSHED);
+-		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
+-		TX_STATUS_ENTRY(TX_LOCKED);
+-		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
+-	}
+-
+-	return "UNKNOWN";
+-}
+-
+ /**
+  * iwl3945_scan_cancel - Cancel any currently executing HW scan
+  *
+@@ -2461,9 +2249,10 @@ static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt)
+ 	return 0;
+ }
+ 
+-static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode)
++static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
++					  enum ieee80211_band band)
+ {
+-	if (phymode == MODE_IEEE80211A) {
++	if (band == IEEE80211_BAND_5GHZ) {
+ 		priv->staging_rxon.flags &=
+ 		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
+ 		      | RXON_FLG_CCK_MSK);
+@@ -2515,6 +2304,9 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+ 		priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
+ 		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
+ 		break;
++	default:
++		IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
++		break;
+ 	}
+ 
+ #if 0
+@@ -2526,7 +2318,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+ 		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ #endif
+ 
+-	ch_info = iwl3945_get_channel_info(priv, priv->phymode,
++	ch_info = iwl3945_get_channel_info(priv, priv->band,
+ 				       le16_to_cpu(priv->staging_rxon.channel));
+ 
+ 	if (!ch_info)
+@@ -2542,11 +2334,11 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+ 
+ 	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
+ 	if (is_channel_a_band(ch_info))
+-		priv->phymode = MODE_IEEE80211A;
++		priv->band = IEEE80211_BAND_5GHZ;
+ 	else
+-		priv->phymode = MODE_IEEE80211G;
++		priv->band = IEEE80211_BAND_2GHZ;
+ 
+-	iwl3945_set_flags_for_phymode(priv, priv->phymode);
++	iwl3945_set_flags_for_phymode(priv, priv->band);
+ 
+ 	priv->staging_rxon.ofdm_basic_rates =
+ 	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+@@ -2560,7 +2352,7 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
+ 		const struct iwl3945_channel_info *ch_info;
+ 
+ 		ch_info = iwl3945_get_channel_info(priv,
+-			priv->phymode,
++			priv->band,
+ 			le16_to_cpu(priv->staging_rxon.channel));
+ 
+ 		if (!ch_info || !is_channel_ibss(ch_info)) {
+@@ -2694,8 +2486,12 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
+ 			cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
+ 		else
+ 			cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
+-	} else
++	} else {
+ 		cmd->cmd.tx.timeout.pm_frame_timeout = 0;
++#ifdef CONFIG_IWL3945_LEDS
++		priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len);
++#endif
++	}
+ 
+ 	cmd->cmd.tx.driver_txop = 0;
+ 	cmd->cmd.tx.tx_flags = tx_flags;
+@@ -2792,7 +2588,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
+ 		goto drop_unlock;
+ 	}
+ 
+-	if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
++	if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
+ 		IWL_ERROR("ERROR: No TX rate available.\n");
+ 		goto drop_unlock;
+ 	}
+@@ -2963,7 +2759,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
+ 			   ieee80211_get_hdrlen(fc));
+ 
+ 	/* Tell device the write index *just past* this latest filled TFD */
+-	q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
++	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ 	rc = iwl3945_tx_queue_update_write_ptr(priv, txq);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+@@ -2992,12 +2788,12 @@ drop:
+ 
+ static void iwl3945_set_rate(struct iwl3945_priv *priv)
+ {
+-	const struct ieee80211_hw_mode *hw = NULL;
++	const struct ieee80211_supported_band *sband = NULL;
+ 	struct ieee80211_rate *rate;
+ 	int i;
+ 
+-	hw = iwl3945_get_hw_mode(priv, priv->phymode);
+-	if (!hw) {
++	sband = iwl3945_get_band(priv, priv->band);
++	if (!sband) {
+ 		IWL_ERROR("Failed to set rate: unable to get hw mode\n");
+ 		return;
+ 	}
+@@ -3005,24 +2801,17 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv)
+ 	priv->active_rate = 0;
+ 	priv->active_rate_basic = 0;
+ 
+-	IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
+-		       hw->mode == MODE_IEEE80211A ?
+-		       'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
+-
+-	for (i = 0; i < hw->num_rates; i++) {
+-		rate = &(hw->rates[i]);
+-		if ((rate->val < IWL_RATE_COUNT) &&
+-		    (rate->flags & IEEE80211_RATE_SUPPORTED)) {
+-			IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
+-				       rate->val, iwl3945_rates[rate->val].plcp,
+-				       (rate->flags & IEEE80211_RATE_BASIC) ?
+-				       "*" : "");
+-			priv->active_rate |= (1 << rate->val);
+-			if (rate->flags & IEEE80211_RATE_BASIC)
+-				priv->active_rate_basic |= (1 << rate->val);
+-		} else
+-			IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
+-				       rate->val, iwl3945_rates[rate->val].plcp);
++	IWL_DEBUG_RATE("Setting rates for %s GHz\n",
++		       sband->band == IEEE80211_BAND_2GHZ ? "2.4" : "5");
++
++	for (i = 0; i < sband->n_bitrates; i++) {
++		rate = &sband->bitrates[i];
++		if ((rate->hw_value < IWL_RATE_COUNT) &&
++		    !(rate->flags & IEEE80211_CHAN_DISABLED)) {
++			IWL_DEBUG_RATE("Adding rate index %d (plcp %d)\n",
++				       rate->hw_value, iwl3945_rates[rate->hw_value].plcp);
++			priv->active_rate |= (1 << rate->hw_value);
++		}
+ 	}
+ 
+ 	IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
+@@ -3330,127 +3119,6 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv,
+ }
+ #endif
+ 
+-static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv,
+-				 struct iwl3945_tx_info *tx_sta)
+-{
+-
+-	tx_sta->status.ack_signal = 0;
+-	tx_sta->status.excessive_retries = 0;
+-	tx_sta->status.queue_length = 0;
+-	tx_sta->status.queue_number = 0;
+-
+-	if (in_interrupt())
+-		ieee80211_tx_status_irqsafe(priv->hw,
+-					    tx_sta->skb[0], &(tx_sta->status));
+-	else
+-		ieee80211_tx_status(priv->hw,
+-				    tx_sta->skb[0], &(tx_sta->status));
+-
+-	tx_sta->skb[0] = NULL;
+-}
+-
+-/**
+- * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
+- *
+- * When FW advances 'R' index, all entries between old and new 'R' index
+- * need to be reclaimed. As result, some free space forms. If there is
+- * enough free space (> low mark), wake the stack that feeds us.
+- */
+-static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index)
+-{
+-	struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
+-	struct iwl3945_queue *q = &txq->q;
+-	int nfreed = 0;
+-
+-	if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) {
+-		IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
+-			  "is out of range [0-%d] %d %d.\n", txq_id,
+-			  index, q->n_bd, q->write_ptr, q->read_ptr);
+-		return 0;
+-	}
+-
+-	for (index = iwl3945_queue_inc_wrap(index, q->n_bd);
+-		q->read_ptr != index;
+-		q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+-		if (txq_id != IWL_CMD_QUEUE_NUM) {
+-			iwl3945_txstatus_to_ieee(priv,
+-					&(txq->txb[txq->q.read_ptr]));
+-			iwl3945_hw_txq_free_tfd(priv, txq);
+-		} else if (nfreed > 1) {
+-			IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
+-					q->write_ptr, q->read_ptr);
+-			queue_work(priv->workqueue, &priv->restart);
+-		}
+-		nfreed++;
+-	}
+-
+-	if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
+-			(txq_id != IWL_CMD_QUEUE_NUM) &&
+-			priv->mac80211_registered)
+-		ieee80211_wake_queue(priv->hw, txq_id);
+-
+-
+-	return nfreed;
+-}
+-
+-static int iwl3945_is_tx_success(u32 status)
+-{
+-	return (status & 0xFF) == 0x1;
+-}
+-
+-/******************************************************************************
+- *
+- * Generic RX handler implementations
+- *
+- ******************************************************************************/
+-/**
+- * iwl3945_rx_reply_tx - Handle Tx response
+- */
+-static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
+-			    struct iwl3945_rx_mem_buffer *rxb)
+-{
+-	struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+-	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+-	int txq_id = SEQ_TO_QUEUE(sequence);
+-	int index = SEQ_TO_INDEX(sequence);
+-	struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
+-	struct ieee80211_tx_status *tx_status;
+-	struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+-	u32  status = le32_to_cpu(tx_resp->status);
+-
+-	if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
+-		IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
+-			  "is out of range [0-%d] %d %d\n", txq_id,
+-			  index, txq->q.n_bd, txq->q.write_ptr,
+-			  txq->q.read_ptr);
+-		return;
+-	}
+-
+-	tx_status = &(txq->txb[txq->q.read_ptr].status);
+-
+-	tx_status->retry_count = tx_resp->failure_frame;
+-	tx_status->queue_number = status;
+-	tx_status->queue_length = tx_resp->bt_kill_count;
+-	tx_status->queue_length |= tx_resp->failure_rts;
+-
+-	tx_status->flags =
+-	    iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
+-
+-	tx_status->control.tx_rate = iwl3945_rate_index_from_plcp(tx_resp->rate);
+-
+-	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
+-			txq_id, iwl3945_get_tx_fail_reason(status), status,
+-			tx_resp->rate, tx_resp->failure_frame);
+-
+-	IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
+-	if (index != -1)
+-		iwl3945_tx_queue_reclaim(priv, txq_id, index);
+-
+-	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
+-		IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
+-}
+-
+-
+ static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv,
+ 			       struct iwl3945_rx_mem_buffer *rxb)
+ {
+@@ -3797,13 +3465,44 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv)
+ 	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
+ 	    iwl3945_rx_scan_complete_notif;
+ 	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
+-	priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
+ 
+ 	/* Set up hardware specific Rx handlers */
+ 	iwl3945_hw_rx_handler_setup(priv);
+ }
+ 
+ /**
++ * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries
++ * When FW advances 'R' index, all entries between old and new 'R' index
++ * need to be reclaimed.
++ */
++static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv,
++				      int txq_id, int index)
++{
++	struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
++	struct iwl3945_queue *q = &txq->q;
++	int nfreed = 0;
++
++	if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) {
++		IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
++			  "is out of range [0-%d] %d %d.\n", txq_id,
++			  index, q->n_bd, q->write_ptr, q->read_ptr);
++		return;
++	}
++
++	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)) {
++		if (nfreed > 1) {
++			IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
++					q->write_ptr, q->read_ptr);
++			queue_work(priv->workqueue, &priv->restart);
++			break;
++		}
++		nfreed++;
++	}
++}
++
++
++/**
+  * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+  * @rxb: Rx buffer to reclaim
+  *
+@@ -3822,12 +3521,6 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
+ 	int cmd_index;
+ 	struct iwl3945_cmd *cmd;
+ 
+-	/* 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 (txq_id != IWL_CMD_QUEUE_NUM)
+-		IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
+-			  txq_id, pkt->hdr.cmd);
+ 	BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
+ 
+ 	cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
+@@ -3841,7 +3534,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
+ 		   !cmd->meta.u.callback(priv, cmd, rxb->skb))
+ 		rxb->skb = NULL;
+ 
+-	iwl3945_tx_queue_reclaim(priv, txq_id, index);
++	iwl3945_cmd_queue_reclaim(priv, txq_id, index);
+ 
+ 	if (!(cmd->meta.flags & CMD_ASYNC)) {
+ 		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+@@ -4460,6 +4153,16 @@ static void iwl3945_enable_interrupts(struct iwl3945_priv *priv)
+ 	iwl3945_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
+ }
+ 
++
++/* call this function to flush any scheduled tasklet */
++static inline void iwl_synchronize_irq(struct iwl3945_priv *priv)
++{
++	/* wait to make sure we flush pedding tasklet*/
++	synchronize_irq(priv->pci_dev->irq);
++	tasklet_kill(&priv->irq_tasklet);
++}
++
++
+ static inline void iwl3945_disable_interrupts(struct iwl3945_priv *priv)
+ {
+ 	clear_bit(STATUS_INT_ENABLED, &priv->status);
+@@ -4521,8 +4224,7 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv)
+ 
+ 	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ 		IWL_ERROR("Start IWL Error Log Dump:\n");
+-		IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n",
+-			  priv->status, priv->config, count);
++		IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
+ 	}
+ 
+ 	IWL_ERROR("Desc       Time       asrtPC  blink2 "
+@@ -4742,9 +4444,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
+ 	 * atomic, make sure that inta covers all the interrupts that
+ 	 * we've discovered, even if FH interrupt came in just after
+ 	 * reading CSR_INT. */
+-	if (inta_fh & CSR_FH_INT_RX_MASK)
++	if (inta_fh & CSR39_FH_INT_RX_MASK)
+ 		inta |= CSR_INT_BIT_FH_RX;
+-	if (inta_fh & CSR_FH_INT_TX_MASK)
++	if (inta_fh & CSR39_FH_INT_TX_MASK)
+ 		inta |= CSR_INT_BIT_FH_TX;
+ 
+ 	/* Now service all interrupt bits discovered above. */
+@@ -4792,7 +4494,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
+ 		/* Queue restart only if RF_KILL switch was set to "kill"
+ 		 *   when we loaded driver, and is now set to "enable".
+ 		 * After we're Alive, RF_KILL gets handled by
+-		 *   iwl_rx_card_state_notif() */
++		 *   iwl3945_rx_card_state_notif() */
+ 		if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
+ 			clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ 			queue_work(priv->workqueue, &priv->restart);
+@@ -4860,7 +4562,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
+ 	}
+ 
+ 	/* Re-enable all interrupts */
+-	iwl3945_enable_interrupts(priv);
++	/* only Re-enable if disabled by irq */
++	if (test_bit(STATUS_INT_ENABLED, &priv->status))
++		iwl3945_enable_interrupts(priv);
+ 
+ #ifdef CONFIG_IWL3945_DEBUG
+ 	if (iwl3945_debug_level & (IWL_DL_ISR)) {
+@@ -4924,7 +4628,9 @@ unplugged:
+ 
+  none:
+ 	/* re-enable interrupts here since we don't have anything to service. */
+-	iwl3945_enable_interrupts(priv);
++	/* only Re-enable if disabled by irq */
++	if (test_bit(STATUS_INT_ENABLED, &priv->status))
++		iwl3945_enable_interrupts(priv);
+ 	spin_unlock(&priv->lock);
+ 	return IRQ_NONE;
+ }
+@@ -5026,24 +4732,24 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban
+  * Based on band and channel number.
+  */
+ const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv,
+-						    int phymode, u16 channel)
++						    enum ieee80211_band band, u16 channel)
+ {
+ 	int i;
+ 
+-	switch (phymode) {
+-	case MODE_IEEE80211A:
++	switch (band) {
++	case IEEE80211_BAND_5GHZ:
+ 		for (i = 14; i < priv->channel_count; i++) {
+ 			if (priv->channel_info[i].channel == channel)
+ 				return &priv->channel_info[i];
+ 		}
+ 		break;
+ 
+-	case MODE_IEEE80211B:
+-	case MODE_IEEE80211G:
++	case IEEE80211_BAND_2GHZ:
+ 		if (channel >= 1 && channel <= 14)
+ 			return &priv->channel_info[channel - 1];
+ 		break;
+-
++	case IEEE80211_NUM_BANDS:
++		WARN_ON(1);
+ 	}
+ 
+ 	return NULL;
+@@ -5106,8 +4812,8 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
+ 		/* Loop through each band adding each of the channels */
+ 		for (ch = 0; ch < eeprom_ch_count; ch++) {
+ 			ch_info->channel = eeprom_ch_index[ch];
+-			ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
+-			    MODE_IEEE80211A;
++			ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
++			    IEEE80211_BAND_5GHZ;
+ 
+ 			/* permanently store EEPROM's channel regulatory flags
+ 			 *   and max power in channel info database. */
+@@ -5134,11 +4840,12 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
+ 			ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
+ 			ch_info->min_power = 0;
+ 
+-			IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
++			IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x"
+ 				       " %ddBm): Ad-Hoc %ssupported\n",
+ 				       ch_info->channel,
+ 				       is_channel_a_band(ch_info) ?
+ 				       "5.2" : "2.4",
++				       CHECK_AND_PRINT(VALID),
+ 				       CHECK_AND_PRINT(IBSS),
+ 				       CHECK_AND_PRINT(ACTIVE),
+ 				       CHECK_AND_PRINT(RADAR),
+@@ -5203,18 +4910,20 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
+ #define IWL_PASSIVE_DWELL_BASE      (100)
+ #define IWL_CHANNEL_TUNE_TIME       5
+ 
+-static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, int phymode)
++static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
++						enum ieee80211_band band)
+ {
+-	if (phymode == MODE_IEEE80211A)
++	if (band == IEEE80211_BAND_5GHZ)
+ 		return IWL_ACTIVE_DWELL_TIME_52;
+ 	else
+ 		return IWL_ACTIVE_DWELL_TIME_24;
+ }
+ 
+-static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode)
++static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
++					  enum ieee80211_band band)
+ {
+-	u16 active = iwl3945_get_active_dwell_time(priv, phymode);
+-	u16 passive = (phymode != MODE_IEEE80211A) ?
++	u16 active = iwl3945_get_active_dwell_time(priv, band);
++	u16 passive = (band == IEEE80211_BAND_2GHZ) ?
+ 	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
+ 	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
+ 
+@@ -5234,28 +4943,32 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode
+ 	return passive;
+ }
+ 
+-static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
++static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
++					 enum ieee80211_band band,
+ 				     u8 is_active, u8 direct_mask,
+ 				     struct iwl3945_scan_channel *scan_ch)
+ {
+ 	const struct ieee80211_channel *channels = NULL;
+-	const struct ieee80211_hw_mode *hw_mode;
++	const struct ieee80211_supported_band *sband;
+ 	const struct iwl3945_channel_info *ch_info;
+ 	u16 passive_dwell = 0;
+ 	u16 active_dwell = 0;
+ 	int added, i;
+ 
+-	hw_mode = iwl3945_get_hw_mode(priv, phymode);
+-	if (!hw_mode)
++	sband = iwl3945_get_band(priv, band);
++	if (!sband)
+ 		return 0;
+ 
+-	channels = hw_mode->channels;
++	channels = sband->channels;
+ 
+-	active_dwell = iwl3945_get_active_dwell_time(priv, phymode);
+-	passive_dwell = iwl3945_get_passive_dwell_time(priv, phymode);
++	active_dwell = iwl3945_get_active_dwell_time(priv, band);
++	passive_dwell = iwl3945_get_passive_dwell_time(priv, band);
+ 
+-	for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
+-		if (channels[i].chan ==
++	for (i = 0, added = 0; i < sband->n_channels; i++) {
++		if (channels[i].flags & IEEE80211_CHAN_DISABLED)
++			continue;
++
++		if (channels[i].hw_value ==
+ 		    le16_to_cpu(priv->active_rxon.channel)) {
+ 			if (iwl3945_is_associated(priv)) {
+ 				IWL_DEBUG_SCAN
+@@ -5266,9 +4979,9 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
+ 		} else if (priv->only_active_channel)
+ 			continue;
+ 
+-		scan_ch->channel = channels[i].chan;
++		scan_ch->channel = channels[i].hw_value;
+ 
+-		ch_info = iwl3945_get_channel_info(priv, phymode, scan_ch->channel);
++		ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel);
+ 		if (!is_channel_valid(ch_info)) {
+ 			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
+ 				       scan_ch->channel);
+@@ -5276,7 +4989,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
+ 		}
+ 
+ 		if (!is_active || is_channel_passive(ch_info) ||
+-		    !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
++		    (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
+ 			scan_ch->type = 0;	/* passive */
+ 		else
+ 			scan_ch->type = 1;	/* active */
+@@ -5295,7 +5008,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
+ 		/* scan_pwr_info->tpc.dsp_atten; */
+ 
+ 		/*scan_pwr_info->tpc.tx_gain; */
+-		if (phymode == MODE_IEEE80211A)
++		if (band == IEEE80211_BAND_5GHZ)
+ 			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+ 		else {
+ 			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+@@ -5319,41 +5032,23 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
+ 	return added;
+ }
+ 
+-static void iwl3945_reset_channel_flag(struct iwl3945_priv *priv)
+-{
+-	int i, j;
+-	for (i = 0; i < 3; i++) {
+-		struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
+-		for (j = 0; j < hw_mode->num_channels; j++)
+-			hw_mode->channels[j].flag = hw_mode->channels[j].val;
+-	}
+-}
+-
+ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
+ 			      struct ieee80211_rate *rates)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < IWL_RATE_COUNT; i++) {
+-		rates[i].rate = iwl3945_rates[i].ieee * 5;
+-		rates[i].val = i; /* Rate scaling will work on indexes */
+-		rates[i].val2 = i;
+-		rates[i].flags = IEEE80211_RATE_SUPPORTED;
+-		/* Only OFDM have the bits-per-symbol set */
+-		if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
+-			rates[i].flags |= IEEE80211_RATE_OFDM;
+-		else {
++		rates[i].bitrate = iwl3945_rates[i].ieee * 5;
++		rates[i].hw_value = i; /* Rate scaling will work on indexes */
++		rates[i].hw_value_short = i;
++		rates[i].flags = 0;
++		if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
+ 			/*
+-			 * If CCK 1M then set rate flag to CCK else CCK_2
+-			 * which is CCK | PREAMBLE2
++			 * If CCK != 1M then set short preamble rate flag.
+ 			 */
+ 			rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
+-				IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
++				0 : IEEE80211_RATE_SHORT_PREAMBLE;
+ 		}
+-
+-		/* Set up which ones are basic rates... */
+-		if (IWL_BASIC_RATES_MASK & (1 << i))
+-			rates[i].flags |= IEEE80211_RATE_BASIC;
+ 	}
+ }
+ 
+@@ -5363,143 +5058,117 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
+ static int iwl3945_init_geos(struct iwl3945_priv *priv)
+ {
+ 	struct iwl3945_channel_info *ch;
+-	struct ieee80211_hw_mode *modes;
++	struct ieee80211_supported_band *sband;
+ 	struct ieee80211_channel *channels;
+ 	struct ieee80211_channel *geo_ch;
+ 	struct ieee80211_rate *rates;
+ 	int i = 0;
+-	enum {
+-		A = 0,
+-		B = 1,
+-		G = 2,
+-	};
+-	int mode_count = 3;
+ 
+-	if (priv->modes) {
++	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
++	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
+ 		IWL_DEBUG_INFO("Geography modes already initialized.\n");
+ 		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+ 		return 0;
+ 	}
+ 
+-	modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
+-			GFP_KERNEL);
+-	if (!modes)
+-		return -ENOMEM;
+-
+ 	channels = kzalloc(sizeof(struct ieee80211_channel) *
+ 			   priv->channel_count, GFP_KERNEL);
+-	if (!channels) {
+-		kfree(modes);
++	if (!channels)
+ 		return -ENOMEM;
+-	}
+ 
+-	rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
++	rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)),
+ 			GFP_KERNEL);
+ 	if (!rates) {
+-		kfree(modes);
+ 		kfree(channels);
+ 		return -ENOMEM;
+ 	}
+ 
+-	/* 0 = 802.11a
+-	 * 1 = 802.11b
+-	 * 2 = 802.11g
+-	 */
+-
+ 	/* 5.2GHz channels start after the 2.4GHz channels */
+-	modes[A].mode = MODE_IEEE80211A;
+-	modes[A].channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
+-	modes[A].rates = &rates[4];
+-	modes[A].num_rates = 8;	/* just OFDM */
+-	modes[A].num_channels = 0;
+-
+-	modes[B].mode = MODE_IEEE80211B;
+-	modes[B].channels = channels;
+-	modes[B].rates = rates;
+-	modes[B].num_rates = 4;	/* just CCK */
+-	modes[B].num_channels = 0;
+-
+-	modes[G].mode = MODE_IEEE80211G;
+-	modes[G].channels = channels;
+-	modes[G].rates = rates;
+-	modes[G].num_rates = 12;	/* OFDM & CCK */
+-	modes[G].num_channels = 0;
++	sband = &priv->bands[IEEE80211_BAND_5GHZ];
++	sband->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
++	/* just OFDM */
++	sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
++	sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
++
++	sband = &priv->bands[IEEE80211_BAND_2GHZ];
++	sband->channels = channels;
++	/* OFDM & CCK */
++	sband->bitrates = rates;
++	sband->n_bitrates = IWL_RATE_COUNT;
+ 
+ 	priv->ieee_channels = channels;
+ 	priv->ieee_rates = rates;
+ 
+ 	iwl3945_init_hw_rates(priv, rates);
+ 
+-	for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
++	for (i = 0;  i < priv->channel_count; i++) {
+ 		ch = &priv->channel_info[i];
+ 
+-		if (!is_channel_valid(ch)) {
+-			IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- "
+-				    "skipping.\n",
+-				    ch->channel, is_channel_a_band(ch) ?
+-				    "5.2" : "2.4");
++		/* FIXME: might be removed if scan is OK*/
++		if (!is_channel_valid(ch))
+ 			continue;
+-		}
+ 
+ 		if (is_channel_a_band(ch))
+-			geo_ch = &modes[A].channels[modes[A].num_channels++];
+-		else {
+-			geo_ch = &modes[B].channels[modes[B].num_channels++];
+-			modes[G].num_channels++;
+-		}
++			sband =  &priv->bands[IEEE80211_BAND_5GHZ];
++		else
++			sband =  &priv->bands[IEEE80211_BAND_2GHZ];
+ 
+-		geo_ch->freq = ieee80211chan2mhz(ch->channel);
+-		geo_ch->chan = ch->channel;
+-		geo_ch->power_level = ch->max_power_avg;
+-		geo_ch->antenna_max = 0xff;
++		geo_ch = &sband->channels[sband->n_channels++];
++
++		geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel);
++		geo_ch->max_power = ch->max_power_avg;
++		geo_ch->max_antenna_gain = 0xff;
++		geo_ch->hw_value = ch->channel;
+ 
+ 		if (is_channel_valid(ch)) {
+-			geo_ch->flag = IEEE80211_CHAN_W_SCAN;
+-			if (ch->flags & EEPROM_CHANNEL_IBSS)
+-				geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
++			if (!(ch->flags & EEPROM_CHANNEL_IBSS))
++				geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
+ 
+-			if (ch->flags & EEPROM_CHANNEL_ACTIVE)
+-				geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
++			if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
++				geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+ 
+ 			if (ch->flags & EEPROM_CHANNEL_RADAR)
+-				geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
++				geo_ch->flags |= IEEE80211_CHAN_RADAR;
+ 
+ 			if (ch->max_power_avg > priv->max_channel_txpower_limit)
+ 				priv->max_channel_txpower_limit =
+ 				    ch->max_power_avg;
++		} else {
++			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
+ 		}
+ 
+-		geo_ch->val = geo_ch->flag;
++		/* Save flags for reg domain usage */
++		geo_ch->orig_flags = geo_ch->flags;
++
++		IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n",
++				ch->channel, geo_ch->center_freq,
++				is_channel_a_band(ch) ?  "5.2" : "2.4",
++				geo_ch->flags & IEEE80211_CHAN_DISABLED ?
++				"restricted" : "valid",
++				 geo_ch->flags);
+ 	}
+ 
+-	if ((modes[A].num_channels == 0) && priv->is_abg) {
++	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
++	     priv->cfg->sku & IWL_SKU_A) {
+ 		printk(KERN_INFO DRV_NAME
+ 		       ": Incorrectly detected BG card as ABG.  Please send "
+ 		       "your PCI ID 0x%04X:0x%04X to maintainer.\n",
+ 		       priv->pci_dev->device, priv->pci_dev->subsystem_device);
+-		priv->is_abg = 0;
++		 priv->cfg->sku &= ~IWL_SKU_A;
+ 	}
+ 
+ 	printk(KERN_INFO DRV_NAME
+ 	       ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
+-	       modes[G].num_channels, modes[A].num_channels);
++	       priv->bands[IEEE80211_BAND_2GHZ].n_channels,
++	       priv->bands[IEEE80211_BAND_5GHZ].n_channels);
+ 
+-	/*
+-	 * NOTE:  We register these in preference of order -- the
+-	 * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
+-	 * a phymode based on rates or AP capabilities but seems to
+-	 * configure it purely on if the channel being configured
+-	 * is supported by a mode -- and the first match is taken
+-	 */
++	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
++		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++			&priv->bands[IEEE80211_BAND_2GHZ];
++	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
++		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
++			&priv->bands[IEEE80211_BAND_5GHZ];
+ 
+-	if (modes[G].num_channels)
+-		ieee80211_register_hwmode(priv->hw, &modes[G]);
+-	if (modes[B].num_channels)
+-		ieee80211_register_hwmode(priv->hw, &modes[B]);
+-	if (modes[A].num_channels)
+-		ieee80211_register_hwmode(priv->hw, &modes[A]);
+-
+-	priv->modes = modes;
+ 	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+ 
+ 	return 0;
+@@ -5510,7 +5179,6 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
+  */
+ static void iwl3945_free_geos(struct iwl3945_priv *priv)
+ {
+-	kfree(priv->modes);
+ 	kfree(priv->ieee_channels);
+ 	kfree(priv->ieee_rates);
+ 	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+@@ -5837,7 +5505,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
+ 	int ret = 0;
+ 	const struct firmware *ucode_raw;
+ 	/* firmware file name contains uCode/driver compatibility version */
+-	const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode";
++	const char *name = priv->cfg->fw_name;
+ 	u8 *src;
+ 	size_t len;
+ 	u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
+@@ -6209,6 +5877,8 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
+ 
+ 	iwl3945_reg_txpower_periodic(priv);
+ 
++	iwl3945_led_register(priv);
++
+ 	IWL_DEBUG_INFO("ALIVE processing complete.\n");
+ 	set_bit(STATUS_READY, &priv->status);
+ 	wake_up_interruptible(&priv->wait_command_queue);
+@@ -6216,6 +5886,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
+ 	if (priv->error_recovering)
+ 		iwl3945_error_recovery(priv);
+ 
++	ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
+ 	return;
+ 
+  restart:
+@@ -6237,6 +5908,7 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
+ 	if (!exit_pending)
+ 		set_bit(STATUS_EXIT_PENDING, &priv->status);
+ 
++	iwl3945_led_unregister(priv);
+ 	iwl3945_clear_stations_table(priv);
+ 
+ 	/* Unblock any waiting calls */
+@@ -6251,7 +5923,10 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
+ 	iwl3945_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+ 
+ 	/* tell the device to stop sending interrupts */
++	spin_lock_irqsave(&priv->lock, flags);
+ 	iwl3945_disable_interrupts(priv);
++	spin_unlock_irqrestore(&priv->lock, flags);
++	iwl_synchronize_irq(priv);
+ 
+ 	if (priv->mac80211_registered)
+ 		ieee80211_stop_queues(priv->hw);
+@@ -6519,7 +6194,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
+ 	struct iwl3945_scan_cmd *scan;
+ 	struct ieee80211_conf *conf = NULL;
+ 	u8 direct_mask;
+-	int phymode;
++	enum ieee80211_band band;
+ 
+ 	conf = ieee80211_get_hw_conf(priv->hw);
+ 
+@@ -6651,13 +6326,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
+ 		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;
+-		phymode = MODE_IEEE80211G;
++		band = IEEE80211_BAND_2GHZ;
+ 		break;
+ 
+ 	case 1:
+ 		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
+ 		scan->good_CRC_th = IWL_GOOD_CRC_TH;
+-		phymode = MODE_IEEE80211A;
++		band = IEEE80211_BAND_5GHZ;
+ 		break;
+ 
+ 	default:
+@@ -6671,18 +6346,23 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
+ 		scan->filter_flags = RXON_FILTER_PROMISC_MSK;
+ 
+-	if (direct_mask)
++	if (direct_mask) {
+ 		IWL_DEBUG_SCAN
+ 		    ("Initiating direct scan for %s.\n",
+ 		     iwl3945_escape_essid(priv->essid, priv->essid_len));
+-	else
++		scan->channel_count =
++			iwl3945_get_channels_for_scan(
++				priv, band, 1, /* active */
++				direct_mask,
++				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++	} else {
+ 		IWL_DEBUG_SCAN("Initiating indirect scan.\n");
+-
+-	scan->channel_count =
+-		iwl3945_get_channels_for_scan(
+-			priv, phymode, 1, /* active */
+-			direct_mask,
+-			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++		scan->channel_count =
++			iwl3945_get_channels_for_scan(
++				priv, band, 0, /* passive */
++				direct_mask,
++				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++	}
+ 
+ 	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+ 	    scan->channel_count * sizeof(struct iwl3945_scan_channel);
+@@ -6825,7 +6505,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
+ 		iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
+ 		iwl3945_add_station(priv, priv->bssid, 0, 0);
+ 		iwl3945_sync_sta(priv, IWL_STA_ID,
+-				 (priv->phymode == MODE_IEEE80211A)?
++				 (priv->band == IEEE80211_BAND_5GHZ) ?
+ 				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
+ 				 CMD_ASYNC);
+ 		iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
+@@ -6841,9 +6521,8 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
+ 
+ 	iwl3945_sequence_reset(priv);
+ 
+-#ifdef CONFIG_IWL3945_QOS
+ 	iwl3945_activate_qos(priv, 0);
+-#endif /* CONFIG_IWL3945_QOS */
++
+ 	/* we have just associated, don't start scan too early */
+ 	priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
+ 	mutex_unlock(&priv->mutex);
+@@ -7020,7 +6699,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ 	}
+ 
+ 	IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+-		     ctl->tx_rate);
++		     ctl->tx_rate->bitrate);
+ 
+ 	if (iwl3945_tx_skb(priv, skb, ctl))
+ 		dev_kfree_skb_any(skb);
+@@ -7079,7 +6758,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ 	int ret = 0;
+ 
+ 	mutex_lock(&priv->mutex);
+-	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
++	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
+ 
+ 	priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+ 
+@@ -7099,19 +6778,20 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+-	ch_info = iwl3945_get_channel_info(priv, conf->phymode, conf->channel);
++	ch_info = iwl3945_get_channel_info(priv, conf->channel->band,
++					   conf->channel->hw_value);
+ 	if (!is_channel_valid(ch_info)) {
+ 		IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
+-			       conf->channel, conf->phymode);
++			       conf->channel->hw_value, conf->channel->band);
+ 		IWL_DEBUG_MAC80211("leave - invalid channel\n");
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		ret = -EINVAL;
+ 		goto out;
+ 	}
+ 
+-	iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel);
++	iwl3945_set_rxon_channel(priv, conf->channel->band, conf->channel->hw_value);
+ 
+-	iwl3945_set_flags_for_phymode(priv, conf->phymode);
++	iwl3945_set_flags_for_phymode(priv, conf->channel->band);
+ 
+ 	/* The list of supported rates and rate mask can be different
+ 	 * for each phymode; since the phymode may have changed, reset
+@@ -7225,6 +6905,11 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
+ 	if (conf == NULL)
+ 		return -EIO;
+ 
++	if (priv->vif != vif) {
++		IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
++		return 0;
++	}
++
+ 	/* XXX: this MUST use conf->mac_addr */
+ 
+ 	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
+@@ -7249,17 +6934,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
+ 	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
+ 	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
+  */
+-	if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
+-		IWL_DEBUG_MAC80211("leave - scanning\n");
+-		mutex_unlock(&priv->mutex);
+-		return 0;
+-	}
+-
+-	if (priv->vif != vif) {
+-		IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
+-		mutex_unlock(&priv->mutex);
+-		return 0;
+-	}
+ 
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ 		if (!conf->bssid) {
+@@ -7487,10 +7161,8 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ 			   const struct ieee80211_tx_queue_params *params)
+ {
+ 	struct iwl3945_priv *priv = hw->priv;
+-#ifdef CONFIG_IWL3945_QOS
+ 	unsigned long flags;
+ 	int q;
+-#endif /* CONFIG_IWL3945_QOS */
+ 
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+@@ -7504,7 +7176,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ 		return 0;
+ 	}
+ 
+-#ifdef CONFIG_IWL3945_QOS
+ 	if (!priv->qos_data.qos_enable) {
+ 		priv->qos_data.qos_active = 0;
+ 		IWL_DEBUG_MAC80211("leave - qos not enabled\n");
+@@ -7518,7 +7189,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ 	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->burst_time * 100));
++			cpu_to_le16((params->txop * 32));
+ 
+ 	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+ 	priv->qos_data.qos_active = 1;
+@@ -7533,8 +7204,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ 
+ 	mutex_unlock(&priv->mutex);
+ 
+-#endif /*CONFIG_IWL3945_QOS */
+-
+ 	IWL_DEBUG_MAC80211("leave\n");
+ 	return 0;
+ }
+@@ -7599,9 +7268,8 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
+ 	mutex_lock(&priv->mutex);
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+-#ifdef CONFIG_IWL3945_QOS
+ 	iwl3945_reset_qos(priv);
+-#endif
++
+ 	cancel_delayed_work(&priv->post_associate);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+@@ -7689,9 +7357,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
+ 	IWL_DEBUG_MAC80211("leave\n");
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-#ifdef CONFIG_IWL3945_QOS
+ 	iwl3945_reset_qos(priv);
+-#endif
+ 
+ 	queue_work(priv->workqueue, &priv->post_associate.work);
+ 
+@@ -7892,65 +7558,6 @@ static ssize_t store_filter_flags(struct device *d,
+ static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
+ 		   store_filter_flags);
+ 
+-static ssize_t show_tune(struct device *d,
+-			 struct device_attribute *attr, char *buf)
+-{
+-	struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+-
+-	return sprintf(buf, "0x%04X\n",
+-		       (priv->phymode << 8) |
+-			le16_to_cpu(priv->active_rxon.channel));
+-}
+-
+-static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode);
+-
+-static ssize_t store_tune(struct device *d,
+-			  struct device_attribute *attr,
+-			  const char *buf, size_t count)
+-{
+-	struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+-	char *p = (char *)buf;
+-	u16 tune = simple_strtoul(p, &p, 0);
+-	u8 phymode = (tune >> 8) & 0xff;
+-	u16 channel = tune & 0xff;
+-
+-	IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
+-
+-	mutex_lock(&priv->mutex);
+-	if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
+-	    (priv->phymode != phymode)) {
+-		const struct iwl3945_channel_info *ch_info;
+-
+-		ch_info = iwl3945_get_channel_info(priv, phymode, channel);
+-		if (!ch_info) {
+-			IWL_WARNING("Requested invalid phymode/channel "
+-				    "combination: %d %d\n", phymode, channel);
+-			mutex_unlock(&priv->mutex);
+-			return -EINVAL;
+-		}
+-
+-		/* Cancel any currently running scans... */
+-		if (iwl3945_scan_cancel_timeout(priv, 100))
+-			IWL_WARNING("Could not cancel scan.\n");
+-		else {
+-			IWL_DEBUG_INFO("Committing phymode and "
+-				       "rxon.channel = %d %d\n",
+-				       phymode, channel);
+-
+-			iwl3945_set_rxon_channel(priv, phymode, channel);
+-			iwl3945_set_flags_for_phymode(priv, phymode);
+-
+-			iwl3945_set_rate(priv);
+-			iwl3945_commit_rxon(priv);
+-		}
+-	}
+-	mutex_unlock(&priv->mutex);
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
+-
+ #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+ 
+ static ssize_t show_measurement(struct device *d,
+@@ -8024,31 +7631,6 @@ static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
+ 		   show_measurement, store_measurement);
+ #endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */
+ 
+-static ssize_t show_rate(struct device *d,
+-			 struct device_attribute *attr, char *buf)
+-{
+-	struct iwl3945_priv *priv = dev_get_drvdata(d);
+-	unsigned long flags;
+-	int i;
+-
+-	spin_lock_irqsave(&priv->sta_lock, flags);
+-	if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
+-		i = priv->stations[IWL_AP_ID].current_rate.s.rate;
+-	else
+-		i = priv->stations[IWL_STA_ID].current_rate.s.rate;
+-	spin_unlock_irqrestore(&priv->sta_lock, flags);
+-
+-	i = iwl3945_rate_index_from_plcp(i);
+-	if (i == -1)
+-		return sprintf(buf, "0\n");
+-
+-	return sprintf(buf, "%d%s\n",
+-		       (iwl3945_rates[i].ieee >> 1),
+-		       (iwl3945_rates[i].ieee & 0x1) ? ".5" : "");
+-}
+-
+-static DEVICE_ATTR(rate, S_IRUSR, show_rate, NULL);
+-
+ static ssize_t store_retry_rate(struct device *d,
+ 				struct device_attribute *attr,
+ 				const char *buf, size_t count)
+@@ -8165,73 +7747,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
+ static ssize_t show_channels(struct device *d,
+ 			     struct device_attribute *attr, char *buf)
+ {
+-	struct iwl3945_priv *priv = dev_get_drvdata(d);
+-	int len = 0, i;
+-	struct ieee80211_channel *channels = NULL;
+-	const struct ieee80211_hw_mode *hw_mode = NULL;
+-	int count = 0;
+-
+-	if (!iwl3945_is_ready(priv))
+-		return -EAGAIN;
+-
+-	hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211G);
+-	if (!hw_mode)
+-		hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211B);
+-	if (hw_mode) {
+-		channels = hw_mode->channels;
+-		count = hw_mode->num_channels;
+-	}
+-
+-	len +=
+-	    sprintf(&buf[len],
+-		    "Displaying %d channels in 2.4GHz band "
+-		    "(802.11bg):\n", count);
+-
+-	for (i = 0; i < count; i++)
+-		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+-			       channels[i].chan,
+-			       channels[i].power_level,
+-			       channels[i].
+-			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
+-			       " (IEEE 802.11h required)" : "",
+-			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
+-				|| (channels[i].
+-				    flag &
+-				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
+-			       ", IBSS",
+-			       channels[i].
+-			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
+-			       "active/passive" : "passive only");
+-
+-	hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211A);
+-	if (hw_mode) {
+-		channels = hw_mode->channels;
+-		count = hw_mode->num_channels;
+-	} else {
+-		channels = NULL;
+-		count = 0;
+-	}
+-
+-	len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
+-		       "(802.11a):\n", count);
+-
+-	for (i = 0; i < count; i++)
+-		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+-			       channels[i].chan,
+-			       channels[i].power_level,
+-			       channels[i].
+-			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
+-			       " (IEEE 802.11h required)" : "",
+-			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
+-				|| (channels[i].
+-				    flag &
+-				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
+-			       ", IBSS",
+-			       channels[i].
+-			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
+-			       "active/passive" : "passive only");
+-
+-	return len;
++	/* all this shit doesn't belong into sysfs anyway */
++	return 0;
+ }
+ 
+ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
+@@ -8404,14 +7921,12 @@ static struct attribute *iwl3945_sysfs_entries[] = {
+ 	&dev_attr_measurement.attr,
+ #endif
+ 	&dev_attr_power_level.attr,
+-	&dev_attr_rate.attr,
+ 	&dev_attr_retry_rate.attr,
+ 	&dev_attr_rf_kill.attr,
+ 	&dev_attr_rs_window.attr,
+ 	&dev_attr_statistics.attr,
+ 	&dev_attr_status.attr,
+ 	&dev_attr_temperature.attr,
+-	&dev_attr_tune.attr,
+ 	&dev_attr_tx_power.attr,
+ 
+ 	NULL
+@@ -8444,10 +7959,11 @@ static struct ieee80211_ops iwl3945_hw_ops = {
+ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	int err = 0;
+-	u32 pci_id;
+ 	struct iwl3945_priv *priv;
+ 	struct ieee80211_hw *hw;
++	struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
+ 	int i;
++	unsigned long flags;
+ 	DECLARE_MAC_BUF(mac);
+ 
+ 	/* Disabling hardware scan means that mac80211 will perform scans
+@@ -8457,10 +7973,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 		iwl3945_hw_ops.hw_scan = NULL;
+ 	}
+ 
+-	if ((iwl3945_param_queues_num > IWL_MAX_NUM_QUEUES) ||
++	if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) ||
+ 	    (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) {
+ 		IWL_ERROR("invalid queues_num, should be between %d and %d\n",
+-			  IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
++			  IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
+ 		err = -EINVAL;
+ 		goto out;
+ 	}
+@@ -8482,6 +7998,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 	priv->hw = hw;
+ 
+ 	priv->pci_dev = pdev;
++	priv->cfg = cfg;
+ 
+ 	/* Select antenna (may be helpful if only one antenna is connected) */
+ 	priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna;
+@@ -8532,7 +8049,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 	priv->data_retry_limit = -1;
+ 	priv->ieee_channels = NULL;
+ 	priv->ieee_rates = NULL;
+-	priv->phymode = -1;
++	priv->band = IEEE80211_BAND_2GHZ;
+ 
+ 	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ 	if (!err)
+@@ -8571,32 +8088,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 
+ 	priv->iw_mode = IEEE80211_IF_TYPE_STA;
+ 
+-	pci_id =
+-	    (priv->pci_dev->device << 16) | priv->pci_dev->subsystem_device;
+-
+-	switch (pci_id) {
+-	case 0x42221005:	/* 0x4222 0x8086 0x1005 is BG SKU */
+-	case 0x42221034:	/* 0x4222 0x8086 0x1034 is BG SKU */
+-	case 0x42271014:	/* 0x4227 0x8086 0x1014 is BG SKU */
+-	case 0x42221044:	/* 0x4222 0x8086 0x1044 is BG SKU */
+-		priv->is_abg = 0;
+-		break;
+-
+-	/*
+-	 * Rest are assumed ABG SKU -- if this is not the
+-	 * case then the card will get the wrong 'Detected'
+-	 * line in the kernel log however the code that
+-	 * initializes the GEO table will detect no A-band
+-	 * channels and remove the is_abg mask.
+-	 */
+-	default:
+-		priv->is_abg = 1;
+-		break;
+-	}
+-
+ 	printk(KERN_INFO DRV_NAME
+-	       ": Detected Intel PRO/Wireless 3945%sBG Network Connection\n",
+-	       priv->is_abg ? "A" : "");
++		": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+ 
+ 	/* Device-specific setup */
+ 	if (iwl3945_hw_set_hw_setting(priv)) {
+@@ -8604,7 +8097,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 		goto out_iounmap;
+ 	}
+ 
+-#ifdef CONFIG_IWL3945_QOS
+ 	if (iwl3945_param_qos_enable)
+ 		priv->qos_data.qos_enable = 1;
+ 
+@@ -8612,9 +8104,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 
+ 	priv->qos_data.qos_active = 0;
+ 	priv->qos_data.qos_cap.val = 0;
+-#endif /* CONFIG_IWL3945_QOS */
+ 
+-	iwl3945_set_rxon_channel(priv, MODE_IEEE80211G, 6);
++	iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
+ 	iwl3945_setup_deferred_work(priv);
+ 	iwl3945_setup_rx_handlers(priv);
+ 
+@@ -8623,7 +8114,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 	priv->power_mode = IWL_POWER_AC;
+ 	priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
+ 
++	spin_lock_irqsave(&priv->lock, flags);
+ 	iwl3945_disable_interrupts(priv);
++	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+ 	if (err) {
+@@ -8665,9 +8158,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 		IWL_ERROR("initializing geos failed: %d\n", err);
+ 		goto out_free_channel_map;
+ 	}
+-	iwl3945_reset_channel_flag(priv);
+ 
+-	iwl3945_rate_control_register(priv->hw);
+ 	err = ieee80211_register_hw(priv->hw);
+ 	if (err) {
+ 		IWL_ERROR("Failed to register network device (error %d)\n", err);
+@@ -8711,6 +8202,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
+ 	struct iwl3945_priv *priv = pci_get_drvdata(pdev);
+ 	struct list_head *p, *q;
+ 	int i;
++	unsigned long flags;
+ 
+ 	if (!priv)
+ 		return;
+@@ -8721,6 +8213,15 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
+ 
+ 	iwl3945_down(priv);
+ 
++	/* make sure we flush any pending irq or
++	 * tasklet for the driver
++	 */
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl3945_disable_interrupts(priv);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	iwl_synchronize_irq(priv);
++
+ 	/* Free MAC hash list for ADHOC */
+ 	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
+ 		list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
+@@ -8742,7 +8243,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
+ 
+ 	if (priv->mac80211_registered) {
+ 		ieee80211_unregister_hw(priv->hw);
+-		iwl3945_rate_control_unregister(priv->hw);
+ 	}
+ 
+ 	/*netif_stop_queue(dev); */
+@@ -8823,21 +8323,35 @@ static int __init iwl3945_init(void)
+ 	int ret;
+ 	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ 	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
++
++	ret = iwl3945_rate_control_register();
++	if (ret) {
++		IWL_ERROR("Unable to register rate control algorithm: %d\n", ret);
++		return ret;
++	}
++
+ 	ret = pci_register_driver(&iwl3945_driver);
+ 	if (ret) {
+ 		IWL_ERROR("Unable to initialize PCI module\n");
+-		return ret;
++		goto error_register;
+ 	}
+ #ifdef CONFIG_IWL3945_DEBUG
+ 	ret = driver_create_file(&iwl3945_driver.driver, &driver_attr_debug_level);
+ 	if (ret) {
+ 		IWL_ERROR("Unable to create driver sysfs file\n");
+-		pci_unregister_driver(&iwl3945_driver);
+-		return ret;
++		goto error_debug;
+ 	}
+ #endif
+ 
+ 	return ret;
++
++#ifdef CONFIG_IWL3945_DEBUG
++error_debug:
++	pci_unregister_driver(&iwl3945_driver);
++#endif
++error_register:
++	iwl3945_rate_control_unregister();
++	return ret;
+ }
+ 
+ static void __exit iwl3945_exit(void)
+@@ -8846,6 +8360,7 @@ static void __exit iwl3945_exit(void)
+ 	driver_remove_file(&iwl3945_driver.driver, &driver_attr_debug_level);
+ #endif
+ 	pci_unregister_driver(&iwl3945_driver);
++	iwl3945_rate_control_unregister();
+ }
+ 
+ module_param_named(antenna, iwl3945_param_antenna, int, 0444);
+diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
+index 60ec29e..d0bbcaa 100644
+--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
++++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+  *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 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.
+@@ -45,14 +45,14 @@
+ 
+ #include <asm/div64.h>
+ 
++#include "iwl-eeprom.h"
+ #include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-io.h"
+ #include "iwl-helpers.h"
++#include "iwl-sta.h"
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
+-u32 iwl4965_debug_level;
+-#endif
+-
+-static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
++static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
+ 				  struct iwl4965_tx_queue *txq);
+ 
+ /******************************************************************************
+@@ -61,16 +61,6 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
+  *
+  ******************************************************************************/
+ 
+-/* module parameters */
+-static int iwl4965_param_disable_hw_scan; /* def: 0 = use 4965's h/w scan */
+-static int iwl4965_param_debug;    /* def: 0 = minimal debug log messages */
+-static int iwl4965_param_disable;  /* def: enable radio */
+-static int iwl4965_param_antenna;  /* def: 0 = both antennas (use diversity) */
+-int iwl4965_param_hwcrypto;        /* def: using software encryption */
+-static int iwl4965_param_qos_enable = 1; /* def: 1 = use quality of service */
+-int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 16 Tx queues */
+-int iwl4965_param_amsdu_size_8K;   /* def: enable 8K amsdu size */
+-
+ /*
+  * module name, copyright, version, etc.
+  * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
+@@ -78,7 +68,7 @@ int iwl4965_param_amsdu_size_8K;   /* def: enable 8K amsdu size */
+ 
+ #define DRV_DESCRIPTION	"Intel(R) Wireless WiFi Link 4965AGN driver for Linux"
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ #define VD "d"
+ #else
+ #define VD
+@@ -90,15 +80,8 @@ int iwl4965_param_amsdu_size_8K;   /* def: enable 8K amsdu size */
+ #define VS
+ #endif
+ 
+-#define IWLWIFI_VERSION "1.2.23k" VD VS
+-#define DRV_COPYRIGHT	"Copyright(c) 2003-2007 Intel Corporation"
+-#define DRV_VERSION     IWLWIFI_VERSION
++#define DRV_VERSION     IWLWIFI_VERSION VD VS
+ 
+-/* Change firmware file name, using "-" and incrementing number,
+- *   *only* when uCode interface or architecture changes so that it
+- *   is not compatible with earlier drivers.
+- * This number will also appear in << 8 position of 1st dword of uCode file */
+-#define IWL4965_UCODE_API "-1"
+ 
+ MODULE_DESCRIPTION(DRV_DESCRIPTION);
+ MODULE_VERSION(DRV_VERSION);
+@@ -115,16 +98,10 @@ __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
+ 	return NULL;
+ }
+ 
+-static const struct ieee80211_hw_mode *iwl4965_get_hw_mode(
+-		struct iwl4965_priv *priv, int mode)
++static const struct ieee80211_supported_band *iwl4965_get_hw_mode(
++		struct iwl_priv *priv, enum ieee80211_band band)
+ {
+-	int i;
+-
+-	for (i = 0; i < 3; i++)
+-		if (priv->modes[i].mode == mode)
+-			return &priv->modes[i];
+-
+-	return NULL;
++	return priv->hw->wiphy->bands[band];
+ }
+ 
+ static int iwl4965_is_empty_essid(const char *essid, int essid_len)
+@@ -167,17 +144,6 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
+ 	return escaped;
+ }
+ 
+-static void iwl4965_print_hex_dump(int level, void *p, u32 len)
+-{
+-#ifdef CONFIG_IWL4965_DEBUG
+-	if (!(iwl4965_debug_level & level))
+-		return;
+-
+-	print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
+-			p, len, 1);
+-#endif
+-}
+-
+ /*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
+  * DMA services
+  *
+@@ -205,7 +171,7 @@ static void iwl4965_print_hex_dump(int level, void *p, u32 len)
+  * See more detailed info in iwl-4965-hw.h.
+  ***************************************************/
+ 
+-static int iwl4965_queue_space(const struct iwl4965_queue *q)
++int iwl4965_queue_space(const struct iwl4965_queue *q)
+ {
+ 	int s = q->read_ptr - q->write_ptr;
+ 
+@@ -221,25 +187,6 @@ static int iwl4965_queue_space(const struct iwl4965_queue *q)
+ 	return s;
+ }
+ 
+-/**
+- * iwl4965_queue_inc_wrap - increment queue index, wrap back to beginning
+- * @index -- current index
+- * @n_bd -- total number of entries in queue (must be power of 2)
+- */
+-static inline int iwl4965_queue_inc_wrap(int index, int n_bd)
+-{
+-	return ++index & (n_bd - 1);
+-}
+-
+-/**
+- * iwl4965_queue_dec_wrap - decrement queue index, wrap back to end
+- * @index -- current index
+- * @n_bd -- total number of entries in queue (must be power of 2)
+- */
+-static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
+-{
+-	return --index & (n_bd - 1);
+-}
+ 
+ static inline int x2_queue_used(const struct iwl4965_queue *q, int i)
+ {
+@@ -261,15 +208,15 @@ static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge)
+ /**
+  * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes
+  */
+-static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q,
++static int iwl4965_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q,
+ 			  int count, int slots_num, u32 id)
+ {
+ 	q->n_bd = count;
+ 	q->n_window = slots_num;
+ 	q->id = id;
+ 
+-	/* count must be power-of-two size, otherwise iwl4965_queue_inc_wrap
+-	 * and iwl4965_queue_dec_wrap are broken. */
++	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
++	 * and iwl_queue_dec_wrap are broken. */
+ 	BUG_ON(!is_power_of_2(count));
+ 
+ 	/* slots_num must be power-of-two size, otherwise
+@@ -292,7 +239,7 @@ static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q
+ /**
+  * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
+  */
+-static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv,
++static int iwl4965_tx_queue_alloc(struct iwl_priv *priv,
+ 			      struct iwl4965_tx_queue *txq, u32 id)
+ {
+ 	struct pci_dev *dev = priv->pci_dev;
+@@ -337,7 +284,7 @@ static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv,
+ /**
+  * iwl4965_tx_queue_init - Allocate and initialize one tx/cmd queue
+  */
+-int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
++int iwl4965_tx_queue_init(struct iwl_priv *priv,
+ 		      struct iwl4965_tx_queue *txq, int slots_num, u32 txq_id)
+ {
+ 	struct pci_dev *dev = priv->pci_dev;
+@@ -352,7 +299,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
+ 	 * For normal Tx queues (all other queues), no super-size command
+ 	 * space is needed.
+ 	 */
+-	len = sizeof(struct iwl4965_cmd) * slots_num;
++	len = sizeof(struct iwl_cmd) * slots_num;
+ 	if (txq_id == IWL_CMD_QUEUE_NUM)
+ 		len +=  IWL_MAX_SCAN_SIZE;
+ 	txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
+@@ -369,7 +316,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
+ 	txq->need_update = 0;
+ 
+ 	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+-	 * iwl4965_queue_inc_wrap and iwl4965_queue_dec_wrap are broken. */
++	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+ 	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+ 
+ 	/* Initialize queue's high/low-water marks, and head/tail indexes */
+@@ -389,7 +336,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
+  * Free all buffers.
+  * 0-fill, but do not free "txq" descriptor structure.
+  */
+-void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
++void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
+ {
+ 	struct iwl4965_queue *q = &txq->q;
+ 	struct pci_dev *dev = priv->pci_dev;
+@@ -400,10 +347,10 @@ void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *t
+ 
+ 	/* first, empty all BD's */
+ 	for (; q->write_ptr != q->read_ptr;
+-	     q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd))
++	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
+ 		iwl4965_hw_txq_free_tfd(priv, txq);
+ 
+-	len = sizeof(struct iwl4965_cmd) * q->n_window;
++	len = sizeof(struct iwl_cmd) * q->n_window;
+ 	if (q->id == IWL_CMD_QUEUE_NUM)
+ 		len += IWL_MAX_SCAN_SIZE;
+ 
+@@ -440,7 +387,7 @@ const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+  *
+  * NOTE:  This does not remove station from device's station table.
+  */
+-static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
++static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+ {
+ 	int index = IWL_INVALID_STATION;
+ 	int i;
+@@ -451,9 +398,9 @@ static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int
+ 	if (is_ap)
+ 		index = IWL_AP_ID;
+ 	else if (is_broadcast_ether_addr(addr))
+-		index = priv->hw_setting.bcast_sta_id;
++		index = priv->hw_params.bcast_sta_id;
+ 	else
+-		for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++)
++		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
+ 			if (priv->stations[i].used &&
+ 			    !compare_ether_addr(priv->stations[i].sta.sta.addr,
+ 						addr)) {
+@@ -478,26 +425,9 @@ out:
+ #endif
+ 
+ /**
+- * iwl4965_clear_stations_table - Clear the driver's station table
+- *
+- * NOTE:  This does not clear or otherwise alter the device's station table.
+- */
+-static void iwl4965_clear_stations_table(struct iwl4965_priv *priv)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&priv->sta_lock, flags);
+-
+-	priv->num_stations = 0;
+-	memset(priv->stations, 0, sizeof(priv->stations));
+-
+-	spin_unlock_irqrestore(&priv->sta_lock, flags);
+-}
+-
+-/**
+  * iwl4965_add_station_flags - Add station to tables in driver and device
+  */
+-u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
++u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
+ 				int is_ap, u8 flags, void *ht_data)
+ {
+ 	int i;
+@@ -510,9 +440,9 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
+ 	if (is_ap)
+ 		index = IWL_AP_ID;
+ 	else if (is_broadcast_ether_addr(addr))
+-		index = priv->hw_setting.bcast_sta_id;
++		index = priv->hw_params.bcast_sta_id;
+ 	else
+-		for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) {
++		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
+ 			if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+ 						addr)) {
+ 				index = i;
+@@ -553,7 +483,7 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
+ 
+ #ifdef CONFIG_IWL4965_HT
+ 	/* BCAST station and IBSS stations do not work in HT mode */
+-	if (index != priv->hw_setting.bcast_sta_id &&
++	if (index != priv->hw_params.bcast_sta_id &&
+ 	    priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
+ 		iwl4965_set_ht_add_station(priv, index,
+ 				 (struct ieee80211_ht_info *) ht_data);
+@@ -567,103 +497,10 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
+ 
+ }
+ 
+-/*************** DRIVER STATUS FUNCTIONS   *****/
+-
+-static inline int iwl4965_is_ready(struct iwl4965_priv *priv)
+-{
+-	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
+-	 * set but EXIT_PENDING is not */
+-	return test_bit(STATUS_READY, &priv->status) &&
+-	       test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
+-	       !test_bit(STATUS_EXIT_PENDING, &priv->status);
+-}
+-
+-static inline int iwl4965_is_alive(struct iwl4965_priv *priv)
+-{
+-	return test_bit(STATUS_ALIVE, &priv->status);
+-}
+-
+-static inline int iwl4965_is_init(struct iwl4965_priv *priv)
+-{
+-	return test_bit(STATUS_INIT, &priv->status);
+-}
+-
+-static inline int iwl4965_is_rfkill(struct iwl4965_priv *priv)
+-{
+-	return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
+-	       test_bit(STATUS_RF_KILL_SW, &priv->status);
+-}
+-
+-static inline int iwl4965_is_ready_rf(struct iwl4965_priv *priv)
+-{
+-
+-	if (iwl4965_is_rfkill(priv))
+-		return 0;
+ 
+-	return iwl4965_is_ready(priv);
+-}
+ 
+ /*************** HOST COMMAND QUEUE FUNCTIONS   *****/
+ 
+-#define IWL_CMD(x) case x : return #x
+-
+-static const char *get_cmd_string(u8 cmd)
+-{
+-	switch (cmd) {
+-		IWL_CMD(REPLY_ALIVE);
+-		IWL_CMD(REPLY_ERROR);
+-		IWL_CMD(REPLY_RXON);
+-		IWL_CMD(REPLY_RXON_ASSOC);
+-		IWL_CMD(REPLY_QOS_PARAM);
+-		IWL_CMD(REPLY_RXON_TIMING);
+-		IWL_CMD(REPLY_ADD_STA);
+-		IWL_CMD(REPLY_REMOVE_STA);
+-		IWL_CMD(REPLY_REMOVE_ALL_STA);
+-		IWL_CMD(REPLY_TX);
+-		IWL_CMD(REPLY_RATE_SCALE);
+-		IWL_CMD(REPLY_LEDS_CMD);
+-		IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
+-		IWL_CMD(RADAR_NOTIFICATION);
+-		IWL_CMD(REPLY_QUIET_CMD);
+-		IWL_CMD(REPLY_CHANNEL_SWITCH);
+-		IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
+-		IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
+-		IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
+-		IWL_CMD(POWER_TABLE_CMD);
+-		IWL_CMD(PM_SLEEP_NOTIFICATION);
+-		IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
+-		IWL_CMD(REPLY_SCAN_CMD);
+-		IWL_CMD(REPLY_SCAN_ABORT_CMD);
+-		IWL_CMD(SCAN_START_NOTIFICATION);
+-		IWL_CMD(SCAN_RESULTS_NOTIFICATION);
+-		IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
+-		IWL_CMD(BEACON_NOTIFICATION);
+-		IWL_CMD(REPLY_TX_BEACON);
+-		IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
+-		IWL_CMD(QUIET_NOTIFICATION);
+-		IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
+-		IWL_CMD(MEASURE_ABORT_NOTIFICATION);
+-		IWL_CMD(REPLY_BT_CONFIG);
+-		IWL_CMD(REPLY_STATISTICS_CMD);
+-		IWL_CMD(STATISTICS_NOTIFICATION);
+-		IWL_CMD(REPLY_CARD_STATE_CMD);
+-		IWL_CMD(CARD_STATE_NOTIFICATION);
+-		IWL_CMD(MISSED_BEACONS_NOTIFICATION);
+-		IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
+-		IWL_CMD(SENSITIVITY_CMD);
+-		IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
+-		IWL_CMD(REPLY_RX_PHY_CMD);
+-		IWL_CMD(REPLY_RX_MPDU_CMD);
+-		IWL_CMD(REPLY_4965_RX);
+-		IWL_CMD(REPLY_COMPRESSED_BA);
+-	default:
+-		return "UNKNOWN";
+-
+-	}
+-}
+-
+-#define HOST_COMPLETE_TIMEOUT (HZ / 2)
+-
+ /**
+  * iwl4965_enqueue_hcmd - enqueue a uCode command
+  * @priv: device private data point
+@@ -673,13 +510,13 @@ static const char *get_cmd_string(u8 cmd)
+  * failed. On success, it turns the index (> 0) of command in the
+  * command queue.
+  */
+-static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
++int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+ {
+ 	struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+ 	struct iwl4965_queue *q = &txq->q;
+ 	struct iwl4965_tfd_frame *tfd;
+ 	u32 *control_flags;
+-	struct iwl4965_cmd *out_cmd;
++	struct iwl_cmd *out_cmd;
+ 	u32 idx;
+ 	u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
+ 	dma_addr_t phys_addr;
+@@ -692,7 +529,7 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c
+ 	BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
+ 	       !(cmd->meta.flags & CMD_SIZE_HUGE));
+ 
+-	if (iwl4965_is_rfkill(priv)) {
++	if (iwl_is_rfkill(priv)) {
+ 		IWL_DEBUG_INFO("Not sending command - RF KILL");
+ 		return -EIO;
+ 	}
+@@ -726,7 +563,7 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c
+ 		out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
+ 
+ 	phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
+-			offsetof(struct iwl4965_cmd, hdr);
++			offsetof(struct iwl_cmd, hdr);
+ 	iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
+ 
+ 	IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
+@@ -738,161 +575,25 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c
+ 	txq->need_update = 1;
+ 
+ 	/* Set up entry in queue's byte count circular buffer */
+-	ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0);
++	priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
+ 
+ 	/* Increment and update queue's write index */
+-	q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
+-	iwl4965_tx_queue_update_write_ptr(priv, txq);
++	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
++	ret = iwl4965_tx_queue_update_write_ptr(priv, txq);
+ 
+ 	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+ 	return ret ? ret : idx;
+ }
+ 
+-static int iwl4965_send_cmd_async(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
++static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
+ {
+-	int ret;
+-
+-	BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
+-
+-	/* An asynchronous command can not expect an SKB to be set. */
+-	BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
+-
+-	/* An asynchronous command MUST have a callback. */
+-	BUG_ON(!cmd->meta.u.callback);
+-
+-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+-		return -EBUSY;
+-
+-	ret = iwl4965_enqueue_hcmd(priv, cmd);
+-	if (ret < 0) {
+-		IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n",
+-			  get_cmd_string(cmd->id), ret);
+-		return ret;
+-	}
+-	return 0;
+-}
+-
+-static int iwl4965_send_cmd_sync(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
+-{
+-	int cmd_idx;
+-	int ret;
+-	static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
+-
+-	BUG_ON(cmd->meta.flags & CMD_ASYNC);
+-
+-	 /* A synchronous command can not have a callback set. */
+-	BUG_ON(cmd->meta.u.callback != NULL);
+-
+-	if (atomic_xchg(&entry, 1)) {
+-		IWL_ERROR("Error sending %s: Already sending a host command\n",
+-			  get_cmd_string(cmd->id));
+-		return -EBUSY;
+-	}
+-
+-	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+-
+-	if (cmd->meta.flags & CMD_WANT_SKB)
+-		cmd->meta.source = &cmd->meta;
+-
+-	cmd_idx = iwl4965_enqueue_hcmd(priv, cmd);
+-	if (cmd_idx < 0) {
+-		ret = cmd_idx;
+-		IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n",
+-			  get_cmd_string(cmd->id), ret);
+-		goto out;
+-	}
+-
+-	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+-			!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
+-			HOST_COMPLETE_TIMEOUT);
+-	if (!ret) {
+-		if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
+-			IWL_ERROR("Error sending %s: time out after %dms.\n",
+-				  get_cmd_string(cmd->id),
+-				  jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+-
+-			clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+-			ret = -ETIMEDOUT;
+-			goto cancel;
+-		}
+-	}
+-
+-	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
+-		IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
+-			       get_cmd_string(cmd->id));
+-		ret = -ECANCELED;
+-		goto fail;
+-	}
+-	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
+-		IWL_DEBUG_INFO("Command %s failed: FW Error\n",
+-			       get_cmd_string(cmd->id));
+-		ret = -EIO;
+-		goto fail;
+-	}
+-	if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
+-		IWL_ERROR("Error: Response NULL in '%s'\n",
+-			  get_cmd_string(cmd->id));
+-		ret = -EIO;
+-		goto out;
+-	}
+-
+-	ret = 0;
+-	goto out;
+-
+-cancel:
+-	if (cmd->meta.flags & CMD_WANT_SKB) {
+-		struct iwl4965_cmd *qcmd;
+-
+-		/* Cancel the CMD_WANT_SKB flag for the cmd in the
+-		 * TX cmd queue. Otherwise in case the cmd comes
+-		 * in later, it will possibly set an invalid
+-		 * address (cmd->meta.source). */
+-		qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
+-		qcmd->meta.flags &= ~CMD_WANT_SKB;
+-	}
+-fail:
+-	if (cmd->meta.u.skb) {
+-		dev_kfree_skb_any(cmd->meta.u.skb);
+-		cmd->meta.u.skb = NULL;
+-	}
+-out:
+-	atomic_set(&entry, 0);
+-	return ret;
+-}
+-
+-int iwl4965_send_cmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
+-{
+-	if (cmd->meta.flags & CMD_ASYNC)
+-		return iwl4965_send_cmd_async(priv, cmd);
+-
+-	return iwl4965_send_cmd_sync(priv, cmd);
+-}
+-
+-int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len, const void *data)
+-{
+-	struct iwl4965_host_cmd cmd = {
+-		.id = id,
+-		.len = len,
+-		.data = data,
+-	};
+-
+-	return iwl4965_send_cmd_sync(priv, &cmd);
+-}
+-
+-static int __must_check iwl4965_send_cmd_u32(struct iwl4965_priv *priv, u8 id, u32 val)
+-{
+-	struct iwl4965_host_cmd cmd = {
+-		.id = id,
+-		.len = sizeof(val),
+-		.data = &val,
+-	};
++	struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+ 
+-	return iwl4965_send_cmd_sync(priv, &cmd);
+-}
++	if (hw_decrypt)
++		rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
++	else
++		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
+ 
+-int iwl4965_send_statistics_request(struct iwl4965_priv *priv)
+-{
+-	return iwl4965_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
+ }
+ 
+ /**
+@@ -901,7 +602,7 @@ int iwl4965_send_statistics_request(struct iwl4965_priv *priv)
+  * there is only one AP station with id= IWL_AP_ID
+  * NOTE: mutex must be held before calling this fnction
+  */
+-static int iwl4965_rxon_add_station(struct iwl4965_priv *priv,
++static int iwl4965_rxon_add_station(struct iwl_priv *priv,
+ 				const u8 *addr, int is_ap)
+ {
+ 	u8 sta_id;
+@@ -928,42 +629,6 @@ static int iwl4965_rxon_add_station(struct iwl4965_priv *priv,
+ }
+ 
+ /**
+- * iwl4965_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
+-
+- * 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
+- */
+-static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, u8 phymode,
+-				 u16 channel)
+-{
+-	if (!iwl4965_get_channel_info(priv, phymode, channel)) {
+-		IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
+-			       channel, phymode);
+-		return -EINVAL;
+-	}
+-
+-	if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
+-	    (priv->phymode == phymode))
+-		return 0;
+-
+-	priv->staging_rxon.channel = cpu_to_le16(channel);
+-	if (phymode == MODE_IEEE80211A)
+-		priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
+-	else
+-		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
+-
+-	priv->phymode = phymode;
+-
+-	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
+-
+-	return 0;
+-}
+-
+-/**
+  * iwl4965_check_rxon_cmd - validate RXON structure is valid
+  *
+  * NOTE:  This is really only useful during development and can eventually
+@@ -1044,7 +709,7 @@ static int iwl4965_check_rxon_cmd(struct iwl4965_rxon_cmd *rxon)
+  * 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.
+  */
+-static int iwl4965_full_rxon_required(struct iwl4965_priv *priv)
++static int iwl4965_full_rxon_required(struct iwl_priv *priv)
+ {
+ 
+ 	/* These items are only settable from the full RXON command */
+@@ -1084,60 +749,6 @@ static int iwl4965_full_rxon_required(struct iwl4965_priv *priv)
+ 	return 0;
+ }
+ 
+-static int iwl4965_send_rxon_assoc(struct iwl4965_priv *priv)
+-{
+-	int rc = 0;
+-	struct iwl4965_rx_packet *res = NULL;
+-	struct iwl4965_rxon_assoc_cmd rxon_assoc;
+-	struct iwl4965_host_cmd cmd = {
+-		.id = REPLY_RXON_ASSOC,
+-		.len = sizeof(rxon_assoc),
+-		.meta.flags = CMD_WANT_SKB,
+-		.data = &rxon_assoc,
+-	};
+-	const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon;
+-	const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon;
+-
+-	if ((rxon1->flags == rxon2->flags) &&
+-	    (rxon1->filter_flags == rxon2->filter_flags) &&
+-	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
+-	    (rxon1->ofdm_ht_single_stream_basic_rates ==
+-	     rxon2->ofdm_ht_single_stream_basic_rates) &&
+-	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
+-	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
+-	    (rxon1->rx_chain == rxon2->rx_chain) &&
+-	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
+-		IWL_DEBUG_INFO("Using current RXON_ASSOC.  Not resending.\n");
+-		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.reserved = 0;
+-	rxon_assoc.ofdm_ht_single_stream_basic_rates =
+-	    priv->staging_rxon.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;
+-
+-	rc = iwl4965_send_cmd_sync(priv, &cmd);
+-	if (rc)
+-		return rc;
+-
+-	res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
+-	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+-		IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
+-		rc = -EIO;
+-	}
+-
+-	priv->alloc_rxb_skb--;
+-	dev_kfree_skb_any(cmd.meta.u.skb);
+-
+-	return rc;
+-}
+-
+ /**
+  * iwl4965_commit_rxon - commit staging_rxon to hardware
+  *
+@@ -1146,14 +757,14 @@ static int iwl4965_send_rxon_assoc(struct iwl4965_priv *priv)
+  * function correctly transitions out of the RXON_ASSOC_MSK state if
+  * a HW tune is required based on the RXON structure changes.
+  */
+-static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
++static int iwl4965_commit_rxon(struct iwl_priv *priv)
+ {
+ 	/* cast away the const for active_rxon in this function */
+ 	struct iwl4965_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+ 	DECLARE_MAC_BUF(mac);
+ 	int rc = 0;
+ 
+-	if (!iwl4965_is_alive(priv))
++	if (!iwl_is_alive(priv))
+ 		return -1;
+ 
+ 	/* always get timestamp with Rx frame */
+@@ -1169,7 +780,7 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+ 	 * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
+ 	 * and other flags for the current radio configuration. */
+ 	if (!iwl4965_full_rxon_required(priv)) {
+-		rc = iwl4965_send_rxon_assoc(priv);
++		rc = iwl_send_rxon_assoc(priv);
+ 		if (rc) {
+ 			IWL_ERROR("Error setting RXON_ASSOC "
+ 				  "configuration (%d).\n", rc);
+@@ -1196,12 +807,12 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+ 	 * 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 (iwl4965_is_associated(priv) &&
++	if (iwl_is_associated(priv) &&
+ 	    (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
+ 		IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
+ 		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ 
+-		rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON,
++		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+ 				      sizeof(struct iwl4965_rxon_cmd),
+ 				      &priv->active_rxon);
+ 
+@@ -1224,15 +835,16 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+ 		       le16_to_cpu(priv->staging_rxon.channel),
+ 		       print_mac(mac, priv->staging_rxon.bssid_addr));
+ 
++	iwl4965_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto);
+ 	/* Apply the new configuration */
+-	rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON,
++	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+ 			      sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon);
+ 	if (rc) {
+ 		IWL_ERROR("Error setting new configuration (%d).\n", rc);
+ 		return rc;
+ 	}
+ 
+-	iwl4965_clear_stations_table(priv);
++	iwlcore_clear_stations_table(priv);
+ 
+ #ifdef CONFIG_IWL4965_SENSITIVITY
+ 	if (!priv->error_recovering)
+@@ -1261,7 +873,7 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+ 
+ 	/* If we have set the ASSOC_MSK and we are in BSS mode then
+ 	 * add the IWL_AP_ID to the station rate table */
+-	if (iwl4965_is_associated(priv) &&
++	if (iwl_is_associated(priv) &&
+ 	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
+ 		if (iwl4965_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
+ 		    == IWL_INVALID_STATION) {
+@@ -1269,12 +881,15 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+ 			return -EIO;
+ 		}
+ 		priv->assoc_station_added = 1;
++		if (priv->default_wep_key &&
++		    iwl_send_static_wepkey_cmd(priv, 0))
++			IWL_ERROR("Could not send WEP static key.\n");
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-static int iwl4965_send_bt_config(struct iwl4965_priv *priv)
++static int iwl4965_send_bt_config(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_bt_cmd bt_cmd = {
+ 		.flags = 3,
+@@ -1284,15 +899,15 @@ static int iwl4965_send_bt_config(struct iwl4965_priv *priv)
+ 		.kill_cts_mask = 0,
+ 	};
+ 
+-	return iwl4965_send_cmd_pdu(priv, REPLY_BT_CONFIG,
++	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+ 				sizeof(struct iwl4965_bt_cmd), &bt_cmd);
+ }
+ 
+-static int iwl4965_send_scan_abort(struct iwl4965_priv *priv)
++static int iwl4965_send_scan_abort(struct iwl_priv *priv)
+ {
+ 	int rc = 0;
+ 	struct iwl4965_rx_packet *res;
+-	struct iwl4965_host_cmd cmd = {
++	struct iwl_host_cmd cmd = {
+ 		.id = REPLY_SCAN_ABORT_CMD,
+ 		.meta.flags = CMD_WANT_SKB,
+ 	};
+@@ -1305,7 +920,7 @@ static int iwl4965_send_scan_abort(struct iwl4965_priv *priv)
+ 		return 0;
+ 	}
+ 
+-	rc = iwl4965_send_cmd_sync(priv, &cmd);
++	rc = iwl_send_cmd_sync(priv, &cmd);
+ 	if (rc) {
+ 		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+ 		return rc;
+@@ -1329,8 +944,8 @@ static int iwl4965_send_scan_abort(struct iwl4965_priv *priv)
+ 	return rc;
+ }
+ 
+-static int iwl4965_card_state_sync_callback(struct iwl4965_priv *priv,
+-					struct iwl4965_cmd *cmd,
++static int iwl4965_card_state_sync_callback(struct iwl_priv *priv,
++					struct iwl_cmd *cmd,
+ 					struct sk_buff *skb)
+ {
+ 	return 1;
+@@ -1346,9 +961,9 @@ static int iwl4965_card_state_sync_callback(struct iwl4965_priv *priv,
+  * When in the 'halt' state, the card is shut down and must be fully
+  * restarted to come back on.
+  */
+-static int iwl4965_send_card_state(struct iwl4965_priv *priv, u32 flags, u8 meta_flag)
++static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
+ {
+-	struct iwl4965_host_cmd cmd = {
++	struct iwl_host_cmd cmd = {
+ 		.id = REPLY_CARD_STATE_CMD,
+ 		.len = sizeof(u32),
+ 		.data = &flags,
+@@ -1358,11 +973,11 @@ static int iwl4965_send_card_state(struct iwl4965_priv *priv, u32 flags, u8 meta
+ 	if (meta_flag & CMD_ASYNC)
+ 		cmd.meta.u.callback = iwl4965_card_state_sync_callback;
+ 
+-	return iwl4965_send_cmd(priv, &cmd);
++	return iwl_send_cmd(priv, &cmd);
+ }
+ 
+-static int iwl4965_add_sta_sync_callback(struct iwl4965_priv *priv,
+-				     struct iwl4965_cmd *cmd, struct sk_buff *skb)
++static int iwl4965_add_sta_sync_callback(struct iwl_priv *priv,
++				     struct iwl_cmd *cmd, struct sk_buff *skb)
+ {
+ 	struct iwl4965_rx_packet *res = NULL;
+ 
+@@ -1389,12 +1004,12 @@ static int iwl4965_add_sta_sync_callback(struct iwl4965_priv *priv,
+ 	return 1;
+ }
+ 
+-int iwl4965_send_add_station(struct iwl4965_priv *priv,
++int iwl4965_send_add_station(struct iwl_priv *priv,
+ 			 struct iwl4965_addsta_cmd *sta, u8 flags)
+ {
+ 	struct iwl4965_rx_packet *res = NULL;
+ 	int rc = 0;
+-	struct iwl4965_host_cmd cmd = {
++	struct iwl_host_cmd cmd = {
+ 		.id = REPLY_ADD_STA,
+ 		.len = sizeof(struct iwl4965_addsta_cmd),
+ 		.meta.flags = flags,
+@@ -1406,7 +1021,7 @@ int iwl4965_send_add_station(struct iwl4965_priv *priv,
+ 	else
+ 		cmd.meta.flags |= CMD_WANT_SKB;
+ 
+-	rc = iwl4965_send_cmd(priv, &cmd);
++	rc = iwl_send_cmd(priv, &cmd);
+ 
+ 	if (rc || (flags & CMD_ASYNC))
+ 		return rc;
+@@ -1436,62 +1051,7 @@ int iwl4965_send_add_station(struct iwl4965_priv *priv,
+ 	return rc;
+ }
+ 
+-static int iwl4965_update_sta_key_info(struct iwl4965_priv *priv,
+-				   struct ieee80211_key_conf *keyconf,
+-				   u8 sta_id)
+-{
+-	unsigned long flags;
+-	__le16 key_flags = 0;
+-
+-	switch (keyconf->alg) {
+-	case ALG_CCMP:
+-		key_flags |= STA_KEY_FLG_CCMP;
+-		key_flags |= cpu_to_le16(
+-				keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+-		key_flags &= ~STA_KEY_FLG_INVALID;
+-		break;
+-	case ALG_TKIP:
+-	case ALG_WEP:
+-	default:
+-		return -EINVAL;
+-	}
+-	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);
+-	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;
+-
+-	spin_unlock_irqrestore(&priv->sta_lock, flags);
+-
+-	IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
+-	iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+-	return 0;
+-}
+-
+-static int iwl4965_clear_sta_key_info(struct iwl4965_priv *priv, u8 sta_id)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&priv->sta_lock, flags);
+-	memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key));
+-	memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo));
+-	priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
+-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+-	spin_unlock_irqrestore(&priv->sta_lock, flags);
+-
+-	IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
+-	iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+-	return 0;
+-}
+-
+-static void iwl4965_clear_free_frames(struct iwl4965_priv *priv)
++static void iwl4965_clear_free_frames(struct iwl_priv *priv)
+ {
+ 	struct list_head *element;
+ 
+@@ -1512,7 +1072,7 @@ static void iwl4965_clear_free_frames(struct iwl4965_priv *priv)
+ 	}
+ }
+ 
+-static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl4965_priv *priv)
++static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_frame *frame;
+ 	struct list_head *element;
+@@ -1532,18 +1092,18 @@ static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl4965_priv *priv)
+ 	return list_entry(element, struct iwl4965_frame, list);
+ }
+ 
+-static void iwl4965_free_frame(struct iwl4965_priv *priv, struct iwl4965_frame *frame)
++static void iwl4965_free_frame(struct iwl_priv *priv, struct iwl4965_frame *frame)
+ {
+ 	memset(frame, 0, sizeof(*frame));
+ 	list_add(&frame->list, &priv->free_frames);
+ }
+ 
+-unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
++unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
+ 				struct ieee80211_hdr *hdr,
+ 				const u8 *dest, int left)
+ {
+ 
+-	if (!iwl4965_is_associated(priv) || !priv->ibss_beacon ||
++	if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
+ 	    ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
+ 	     (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
+ 		return 0;
+@@ -1556,34 +1116,6 @@ unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
+ 	return priv->ibss_beacon->len;
+ }
+ 
+-int iwl4965_rate_index_from_plcp(int plcp)
+-{
+-	int i = 0;
+-
+-	/* 4965 HT rate format */
+-	if (plcp & RATE_MCS_HT_MSK) {
+-		i = (plcp & 0xff);
+-
+-		if (i >= IWL_RATE_MIMO_6M_PLCP)
+-			i = i - IWL_RATE_MIMO_6M_PLCP;
+-
+-		i += IWL_FIRST_OFDM_RATE;
+-		/* skip 9M not supported in ht*/
+-		if (i >= IWL_RATE_9M_INDEX)
+-			i += 1;
+-		if ((i >= IWL_FIRST_OFDM_RATE) &&
+-		    (i <= IWL_LAST_OFDM_RATE))
+-			return i;
+-
+-	/* 4965 legacy rate format, search for match in table */
+-	} else {
+-		for (i = 0; i < ARRAY_SIZE(iwl4965_rates); i++)
+-			if (iwl4965_rates[i].plcp == (plcp &0xFF))
+-				return i;
+-	}
+-	return -1;
+-}
+-
+ static u8 iwl4965_rate_get_lowest_plcp(int rate_mask)
+ {
+ 	u8 i;
+@@ -1597,7 +1129,7 @@ static u8 iwl4965_rate_get_lowest_plcp(int rate_mask)
+ 	return IWL_RATE_INVALID;
+ }
+ 
+-static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv)
++static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_frame *frame;
+ 	unsigned int frame_size;
+@@ -1625,7 +1157,7 @@ static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv)
+ 
+ 	frame_size = iwl4965_hw_get_beacon_cmd(priv, frame, rate);
+ 
+-	rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
++	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
+ 			      &frame->u.cmd[0]);
+ 
+ 	iwl4965_free_frame(priv, frame);
+@@ -1635,238 +1167,17 @@ static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv)
+ 
+ /******************************************************************************
+  *
+- * EEPROM related functions
+- *
+- ******************************************************************************/
+-
+-static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac)
+-{
+-	memcpy(mac, priv->eeprom.mac_address, 6);
+-}
+-
+-static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv)
+-{
+-	iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+-		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+-}
+-
+-/**
+- * iwl4965_eeprom_init - read EEPROM contents
+- *
+- * Load the EEPROM contents from adapter into priv->eeprom
+- *
+- * NOTE:  This routine uses the non-debug IO access functions.
+- */
+-int iwl4965_eeprom_init(struct iwl4965_priv *priv)
+-{
+-	u16 *e = (u16 *)&priv->eeprom;
+-	u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP);
+-	u32 r;
+-	int sz = sizeof(priv->eeprom);
+-	int rc;
+-	int i;
+-	u16 addr;
+-
+-	/* The EEPROM structure has several padding buffers within it
+-	 * and when adding new EEPROM maps is subject to programmer errors
+-	 * which may be very difficult to identify without explicitly
+-	 * checking the resulting size of the eeprom map. */
+-	BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
+-
+-	if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
+-		IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
+-		return -ENOENT;
+-	}
+-
+-	/* Make sure driver (instead of uCode) is allowed to read EEPROM */
+-	rc = iwl4965_eeprom_acquire_semaphore(priv);
+-	if (rc < 0) {
+-		IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
+-		return -ENOENT;
+-	}
+-
+-	/* eeprom is an array of 16bit values */
+-	for (addr = 0; addr < sz; addr += sizeof(u16)) {
+-		_iwl4965_write32(priv, CSR_EEPROM_REG, addr << 1);
+-		_iwl4965_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
+-
+-		for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
+-					i += IWL_EEPROM_ACCESS_DELAY) {
+-			r = _iwl4965_read_direct32(priv, CSR_EEPROM_REG);
+-			if (r & CSR_EEPROM_REG_READ_VALID_MSK)
+-				break;
+-			udelay(IWL_EEPROM_ACCESS_DELAY);
+-		}
+-
+-		if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
+-			IWL_ERROR("Time out reading EEPROM[%d]", addr);
+-			rc = -ETIMEDOUT;
+-			goto done;
+-		}
+-		e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
+-	}
+-	rc = 0;
+-
+-done:
+-	iwl4965_eeprom_release_semaphore(priv);
+-	return rc;
+-}
+-
+-/******************************************************************************
+- *
+  * Misc. internal state and helper functions
+  *
+  ******************************************************************************/
+-#ifdef CONFIG_IWL4965_DEBUG
+-
+-/**
+- * iwl4965_report_frame - dump frame to syslog during debug sessions
+- *
+- * You may hack this function to show different aspects of received frames,
+- * including selective frame dumps.
+- * group100 parameter selects whether to show 1 out of 100 good frames.
+- *
+- * TODO:  This was originally written for 3945, need to audit for
+- *        proper operation with 4965.
+- */
+-void iwl4965_report_frame(struct iwl4965_priv *priv,
+-		      struct iwl4965_rx_packet *pkt,
+-		      struct ieee80211_hdr *header, int group100)
+-{
+-	u32 to_us;
+-	u32 print_summary = 0;
+-	u32 print_dump = 0;	/* set to 1 to dump all frames' contents */
+-	u32 hundred = 0;
+-	u32 dataframe = 0;
+-	u16 fc;
+-	u16 seq_ctl;
+-	u16 channel;
+-	u16 phy_flags;
+-	int rate_sym;
+-	u16 length;
+-	u16 status;
+-	u16 bcn_tmr;
+-	u32 tsf_low;
+-	u64 tsf;
+-	u8 rssi;
+-	u8 agc;
+-	u16 sig_avg;
+-	u16 noise_diff;
+-	struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+-	struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+-	struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
+-	u8 *data = IWL_RX_DATA(pkt);
+-
+-	/* MAC header */
+-	fc = le16_to_cpu(header->frame_control);
+-	seq_ctl = le16_to_cpu(header->seq_ctrl);
+-
+-	/* metadata */
+-	channel = le16_to_cpu(rx_hdr->channel);
+-	phy_flags = le16_to_cpu(rx_hdr->phy_flags);
+-	rate_sym = rx_hdr->rate;
+-	length = le16_to_cpu(rx_hdr->len);
+-
+-	/* end-of-frame status and timestamp */
+-	status = le32_to_cpu(rx_end->status);
+-	bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
+-	tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
+-	tsf = le64_to_cpu(rx_end->timestamp);
+-
+-	/* signal statistics */
+-	rssi = rx_stats->rssi;
+-	agc = rx_stats->agc;
+-	sig_avg = le16_to_cpu(rx_stats->sig_avg);
+-	noise_diff = le16_to_cpu(rx_stats->noise_diff);
+-
+-	to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
+-
+-	/* if data frame is to us and all is good,
+-	 *   (optionally) print summary for only 1 out of every 100 */
+-	if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
+-	    (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
+-		dataframe = 1;
+-		if (!group100)
+-			print_summary = 1;	/* print each frame */
+-		else if (priv->framecnt_to_us < 100) {
+-			priv->framecnt_to_us++;
+-			print_summary = 0;
+-		} else {
+-			priv->framecnt_to_us = 0;
+-			print_summary = 1;
+-			hundred = 1;
+-		}
+-	} else {
+-		/* print summary for all other frames */
+-		print_summary = 1;
+-	}
+-
+-	if (print_summary) {
+-		char *title;
+-		u32 rate;
+-
+-		if (hundred)
+-			title = "100Frames";
+-		else if (fc & IEEE80211_FCTL_RETRY)
+-			title = "Retry";
+-		else if (ieee80211_is_assoc_response(fc))
+-			title = "AscRsp";
+-		else if (ieee80211_is_reassoc_response(fc))
+-			title = "RasRsp";
+-		else if (ieee80211_is_probe_response(fc)) {
+-			title = "PrbRsp";
+-			print_dump = 1;	/* dump frame contents */
+-		} else if (ieee80211_is_beacon(fc)) {
+-			title = "Beacon";
+-			print_dump = 1;	/* dump frame contents */
+-		} else if (ieee80211_is_atim(fc))
+-			title = "ATIM";
+-		else if (ieee80211_is_auth(fc))
+-			title = "Auth";
+-		else if (ieee80211_is_deauth(fc))
+-			title = "DeAuth";
+-		else if (ieee80211_is_disassoc(fc))
+-			title = "DisAssoc";
+-		else
+-			title = "Frame";
+ 
+-		rate = iwl4965_rate_index_from_plcp(rate_sym);
+-		if (rate == -1)
+-			rate = 0;
+-		else
+-			rate = iwl4965_rates[rate].ieee / 2;
+-
+-		/* print frame summary.
+-		 * MAC addresses show just the last byte (for brevity),
+-		 *    but you can hack it to show more, if you'd like to. */
+-		if (dataframe)
+-			IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
+-				     "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
+-				     title, fc, header->addr1[5],
+-				     length, rssi, channel, rate);
+-		else {
+-			/* src/dst addresses assume managed mode */
+-			IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
+-				     "src=0x%02x, rssi=%u, tim=%lu usec, "
+-				     "phy=0x%02x, chnl=%d\n",
+-				     title, fc, header->addr1[5],
+-				     header->addr3[5], rssi,
+-				     tsf_low - priv->scan_start_tsf,
+-				     phy_flags, channel);
+-		}
+-	}
+-	if (print_dump)
+-		iwl4965_print_hex_dump(IWL_DL_RX, data, length);
+-}
+-#endif
+-
+-static void iwl4965_unset_hw_setting(struct iwl4965_priv *priv)
++static void iwl4965_unset_hw_params(struct iwl_priv *priv)
+ {
+-	if (priv->hw_setting.shared_virt)
++	if (priv->shared_virt)
+ 		pci_free_consistent(priv->pci_dev,
+ 				    sizeof(struct iwl4965_shared),
+-				    priv->hw_setting.shared_virt,
+-				    priv->hw_setting.shared_phys);
++				    priv->shared_virt,
++				    priv->shared_phys);
+ }
+ 
+ /**
+@@ -1898,24 +1209,20 @@ static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate,
+ 	return ret_rates;
+ }
+ 
+-#ifdef CONFIG_IWL4965_HT
+-void static iwl4965_set_ht_capab(struct ieee80211_hw *hw,
+-			     struct ieee80211_ht_cap *ht_cap,
+-			     u8 use_current_config);
+-#endif
+-
+ /**
+  * iwl4965_fill_probe_req - fill in all required fields and IE for probe request
+  */
+-static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv,
+-			      struct ieee80211_mgmt *frame,
+-			      int left, int is_direct)
++static u16 iwl4965_fill_probe_req(struct iwl_priv *priv,
++				  enum ieee80211_band band,
++				  struct ieee80211_mgmt *frame,
++				  int left, int is_direct)
+ {
+ 	int len = 0;
+ 	u8 *pos = NULL;
+ 	u16 active_rates, ret_rates, cck_rates, active_rate_basic;
+ #ifdef CONFIG_IWL4965_HT
+-	struct ieee80211_hw_mode *mode;
++	const struct ieee80211_supported_band *sband =
++						iwl4965_get_hw_mode(priv, band);
+ #endif /* CONFIG_IWL4965_HT */
+ 
+ 	/* Make sure there is enough space for the probe request,
+@@ -2000,13 +1307,18 @@ static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv,
+ 		len += 2 + *pos;
+ 
+ #ifdef CONFIG_IWL4965_HT
+-	mode = priv->hw->conf.mode;
+-	if (mode->ht_info.ht_supported) {
++	if (sband && sband->ht_info.ht_supported) {
++		struct ieee80211_ht_cap *ht_cap;
+ 		pos += (*pos) + 1;
+ 		*pos++ = WLAN_EID_HT_CAPABILITY;
+ 		*pos++ = sizeof(struct ieee80211_ht_cap);
+-		iwl4965_set_ht_capab(priv->hw,
+-				(struct ieee80211_ht_cap *)pos, 0);
++		ht_cap = (struct ieee80211_ht_cap *)pos;
++		ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap);
++		memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16);
++		ht_cap->ampdu_params_info =(sband->ht_info.ampdu_factor &
++					    IEEE80211_HT_CAP_AMPDU_FACTOR) |
++					    ((sband->ht_info.ampdu_density << 2) &
++					    IEEE80211_HT_CAP_AMPDU_DENSITY);
+ 		len += 2 + sizeof(struct ieee80211_ht_cap);
+ 	}
+ #endif  /*CONFIG_IWL4965_HT */
+@@ -2018,103 +1330,15 @@ static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv,
+ /*
+  * QoS  support
+ */
+-#ifdef CONFIG_IWL4965_QOS
+-static int iwl4965_send_qos_params_command(struct iwl4965_priv *priv,
++static int iwl4965_send_qos_params_command(struct iwl_priv *priv,
+ 				       struct iwl4965_qosparam_cmd *qos)
+ {
+ 
+-	return iwl4965_send_cmd_pdu(priv, REPLY_QOS_PARAM,
++	return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
+ 				sizeof(struct iwl4965_qosparam_cmd), qos);
+ }
+ 
+-static void iwl4965_reset_qos(struct iwl4965_priv *priv)
+-{
+-	u16 cw_min = 15;
+-	u16 cw_max = 1023;
+-	u8 aifs = 2;
+-	u8 is_legacy = 0;
+-	unsigned long flags;
+-	int i;
+-
+-	spin_lock_irqsave(&priv->lock, flags);
+-	priv->qos_data.qos_active = 0;
+-
+-	if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
+-		if (priv->qos_data.qos_enable)
+-			priv->qos_data.qos_active = 1;
+-		if (!(priv->active_rate & 0xfff0)) {
+-			cw_min = 31;
+-			is_legacy = 1;
+-		}
+-	} else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+-		if (priv->qos_data.qos_enable)
+-			priv->qos_data.qos_active = 1;
+-	} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
+-		cw_min = 31;
+-		is_legacy = 1;
+-	}
+-
+-	if (priv->qos_data.qos_active)
+-		aifs = 3;
+-
+-	priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
+-	priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
+-	priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
+-	priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
+-	priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
+-
+-	if (priv->qos_data.qos_active) {
+-		i = 1;
+-		priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
+-		priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
+-		priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
+-		priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
+-		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+-
+-		i = 2;
+-		priv->qos_data.def_qos_parm.ac[i].cw_min =
+-			cpu_to_le16((cw_min + 1) / 2 - 1);
+-		priv->qos_data.def_qos_parm.ac[i].cw_max =
+-			cpu_to_le16(cw_max);
+-		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
+-		if (is_legacy)
+-			priv->qos_data.def_qos_parm.ac[i].edca_txop =
+-				cpu_to_le16(6016);
+-		else
+-			priv->qos_data.def_qos_parm.ac[i].edca_txop =
+-				cpu_to_le16(3008);
+-		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+-
+-		i = 3;
+-		priv->qos_data.def_qos_parm.ac[i].cw_min =
+-			cpu_to_le16((cw_min + 1) / 4 - 1);
+-		priv->qos_data.def_qos_parm.ac[i].cw_max =
+-			cpu_to_le16((cw_max + 1) / 2 - 1);
+-		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
+-		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+-		if (is_legacy)
+-			priv->qos_data.def_qos_parm.ac[i].edca_txop =
+-				cpu_to_le16(3264);
+-		else
+-			priv->qos_data.def_qos_parm.ac[i].edca_txop =
+-				cpu_to_le16(1504);
+-	} else {
+-		for (i = 1; i < 4; i++) {
+-			priv->qos_data.def_qos_parm.ac[i].cw_min =
+-				cpu_to_le16(cw_min);
+-			priv->qos_data.def_qos_parm.ac[i].cw_max =
+-				cpu_to_le16(cw_max);
+-			priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
+-			priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
+-			priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+-		}
+-	}
+-	IWL_DEBUG_QOS("set QoS to default \n");
+-
+-	spin_unlock_irqrestore(&priv->lock, flags);
+-}
+-
+-static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force)
++static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
+ {
+ 	unsigned long flags;
+ 
+@@ -2142,7 +1366,7 @@ static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force)
+ 
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	if (force || iwl4965_is_associated(priv)) {
++	if (force || iwl_is_associated(priv)) {
+ 		IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+ 				priv->qos_data.qos_active,
+ 				priv->qos_data.def_qos_parm.qos_flags);
+@@ -2152,7 +1376,6 @@ static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force)
+ 	}
+ }
+ 
+-#endif /* CONFIG_IWL4965_QOS */
+ /*
+  * Power management (not Tx power!) functions
+  */
+@@ -2193,7 +1416,7 @@ static struct iwl4965_power_vec_entry range_1[IWL_POWER_AC] = {
+ 		 SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
+ };
+ 
+-int iwl4965_power_init_handle(struct iwl4965_priv *priv)
++int iwl4965_power_init_handle(struct iwl_priv *priv)
+ {
+ 	int rc = 0, i;
+ 	struct iwl4965_power_mgr *pow_data;
+@@ -2232,7 +1455,7 @@ int iwl4965_power_init_handle(struct iwl4965_priv *priv)
+ 	return rc;
+ }
+ 
+-static int iwl4965_update_power_cmd(struct iwl4965_priv *priv,
++static int iwl4965_update_power_cmd(struct iwl_priv *priv,
+ 				struct iwl4965_powertable_cmd *cmd, u32 mode)
+ {
+ 	int rc = 0, i;
+@@ -2296,7 +1519,7 @@ static int iwl4965_update_power_cmd(struct iwl4965_priv *priv,
+ 	return rc;
+ }
+ 
+-static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode)
++static int iwl4965_send_power_mode(struct iwl_priv *priv, u32 mode)
+ {
+ 	u32 uninitialized_var(final_mode);
+ 	int rc;
+@@ -2321,7 +1544,7 @@ static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode)
+ 
+ 	iwl4965_update_power_cmd(priv, &cmd, final_mode);
+ 
+-	rc = iwl4965_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
++	rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
+ 
+ 	if (final_mode == IWL_POWER_MODE_CAM)
+ 		clear_bit(STATUS_POWER_PMI, &priv->status);
+@@ -2331,7 +1554,7 @@ static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode)
+ 	return rc;
+ }
+ 
+-int iwl4965_is_network_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header)
++int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
+ {
+ 	/* Filter incoming packets to determine if they are targeted toward
+ 	 * this network, discarding packets coming from ourselves */
+@@ -2354,6 +1577,8 @@ int iwl4965_is_network_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *h
+ 			return !compare_ether_addr(header->addr2, priv->bssid);
+ 		/* packets to our adapter go through */
+ 		return !compare_ether_addr(header->addr1, priv->mac_addr);
++	default:
++		break;
+ 	}
+ 
+ 	return 1;
+@@ -2392,7 +1617,7 @@ static const char *iwl4965_get_tx_fail_reason(u32 status)
+  *
+  * NOTE: priv->mutex is not required before calling this function
+  */
+-static int iwl4965_scan_cancel(struct iwl4965_priv *priv)
++static int iwl4965_scan_cancel(struct iwl_priv *priv)
+ {
+ 	if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
+ 		clear_bit(STATUS_SCANNING, &priv->status);
+@@ -2420,7 +1645,7 @@ static int iwl4965_scan_cancel(struct iwl4965_priv *priv)
+  *
+  * NOTE: priv->mutex must be held before calling this function
+  */
+-static int iwl4965_scan_cancel_timeout(struct iwl4965_priv *priv, unsigned long ms)
++static int iwl4965_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
+ {
+ 	unsigned long now = jiffies;
+ 	int ret;
+@@ -2439,7 +1664,7 @@ static int iwl4965_scan_cancel_timeout(struct iwl4965_priv *priv, unsigned long
+ 	return ret;
+ }
+ 
+-static void iwl4965_sequence_reset(struct iwl4965_priv *priv)
++static void iwl4965_sequence_reset(struct iwl_priv *priv)
+ {
+ 	/* Reset ieee stats */
+ 
+@@ -2469,7 +1694,7 @@ static __le16 iwl4965_adjust_beacon_interval(u16 beacon_val)
+ 	return cpu_to_le16(new_val);
+ }
+ 
+-static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv)
++static void iwl4965_setup_rxon_timing(struct iwl_priv *priv)
+ {
+ 	u64 interval_tm_unit;
+ 	u64 tsf, result;
+@@ -2480,13 +1705,13 @@ static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv)
+ 	conf = ieee80211_get_hw_conf(priv->hw);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp1);
+-	priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0);
++	priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp >> 32);
++	priv->rxon_timing.timestamp.dw[0] =
++				cpu_to_le32(priv->timestamp & 0xFFFFFFFF);
+ 
+ 	priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
+ 
+-	tsf = priv->timestamp1;
+-	tsf = ((tsf << 32) | priv->timestamp0);
++	tsf = priv->timestamp;
+ 
+ 	beacon_int = priv->beacon_int;
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+@@ -2525,14 +1750,14 @@ static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv)
+ 		le16_to_cpu(priv->rxon_timing.atim_window));
+ }
+ 
+-static int iwl4965_scan_initiate(struct iwl4965_priv *priv)
++static int iwl4965_scan_initiate(struct iwl_priv *priv)
+ {
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ 		IWL_ERROR("APs don't scan.\n");
+ 		return 0;
+ 	}
+ 
+-	if (!iwl4965_is_ready_rf(priv)) {
++	if (!iwl_is_ready_rf(priv)) {
+ 		IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
+ 		return -EIO;
+ 	}
+@@ -2559,27 +1784,17 @@ static int iwl4965_scan_initiate(struct iwl4965_priv *priv)
+ 	return 0;
+ }
+ 
+-static int iwl4965_set_rxon_hwcrypto(struct iwl4965_priv *priv, int hw_decrypt)
+-{
+-	struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+ 
+-	if (hw_decrypt)
+-		rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
+-	else
+-		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
+-
+-	return 0;
+-}
+-
+-static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode)
++static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv,
++					  enum ieee80211_band band)
+ {
+-	if (phymode == MODE_IEEE80211A) {
++	if (band == IEEE80211_BAND_5GHZ) {
+ 		priv->staging_rxon.flags &=
+ 		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
+ 		      | RXON_FLG_CCK_MSK);
+ 		priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ 	} else {
+-		/* Copied from iwl4965_bg_post_associate() */
++		/* Copied from iwl4965_post_associate() */
+ 		if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+ 			priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ 		else
+@@ -2597,9 +1812,9 @@ static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode)
+ /*
+  * initialize rxon structure with default values from eeprom
+  */
+-static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
++static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
+ {
+-	const struct iwl4965_channel_info *ch_info;
++	const struct iwl_channel_info *ch_info;
+ 
+ 	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
+ 
+@@ -2625,6 +1840,9 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
+ 		priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
+ 		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
+ 		break;
++	default:
++		IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
++		break;
+ 	}
+ 
+ #if 0
+@@ -2636,7 +1854,7 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
+ 		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ #endif
+ 
+-	ch_info = iwl4965_get_channel_info(priv, priv->phymode,
++	ch_info = iwl_get_channel_info(priv, priv->band,
+ 				       le16_to_cpu(priv->staging_rxon.channel));
+ 
+ 	if (!ch_info)
+@@ -2651,12 +1869,9 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
+ 		ch_info = &priv->channel_info[0];
+ 
+ 	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
+-	if (is_channel_a_band(ch_info))
+-		priv->phymode = MODE_IEEE80211A;
+-	else
+-		priv->phymode = MODE_IEEE80211G;
++	priv->band = ch_info->band;
+ 
+-	iwl4965_set_flags_for_phymode(priv, priv->phymode);
++	iwl4965_set_flags_for_phymode(priv, priv->band);
+ 
+ 	priv->staging_rxon.ofdm_basic_rates =
+ 	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+@@ -2672,13 +1887,13 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
+ 	iwl4965_set_rxon_chain(priv);
+ }
+ 
+-static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode)
++static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
+ {
+ 	if (mode == IEEE80211_IF_TYPE_IBSS) {
+-		const struct iwl4965_channel_info *ch_info;
++		const struct iwl_channel_info *ch_info;
+ 
+-		ch_info = iwl4965_get_channel_info(priv,
+-			priv->phymode,
++		ch_info = iwl_get_channel_info(priv,
++			priv->band,
+ 			le16_to_cpu(priv->staging_rxon.channel));
+ 
+ 		if (!ch_info || !is_channel_ibss(ch_info)) {
+@@ -2693,10 +1908,10 @@ static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode)
+ 	iwl4965_connection_init_rx_config(priv);
+ 	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
+ 
+-	iwl4965_clear_stations_table(priv);
++	iwlcore_clear_stations_table(priv);
+ 
+ 	/* dont commit rxon if rf-kill is on*/
+-	if (!iwl4965_is_ready_rf(priv))
++	if (!iwl_is_ready_rf(priv))
+ 		return -EAGAIN;
+ 
+ 	cancel_delayed_work(&priv->scan_check);
+@@ -2711,44 +1926,58 @@ static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode)
+ 	return 0;
+ }
+ 
+-static void iwl4965_build_tx_cmd_hwcrypto(struct iwl4965_priv *priv,
++static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
+ 				      struct ieee80211_tx_control *ctl,
+-				      struct iwl4965_cmd *cmd,
++				      struct iwl_cmd *cmd,
+ 				      struct sk_buff *skb_frag,
+-				      int last_frag)
++				      int sta_id)
+ {
+-	struct iwl4965_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
++	struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
++	struct iwl_wep_key *wepkey;
++	int keyidx = 0;
++
++	BUG_ON(ctl->key_idx > 3);
+ 
+ 	switch (keyinfo->alg) {
+ 	case ALG_CCMP:
+ 		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
+ 		memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
++		if (ctl->flags & IEEE80211_TXCTL_AMPDU)
++			cmd->cmd.tx.tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
+ 		IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
+ 		break;
+ 
+ 	case ALG_TKIP:
+-#if 0
+ 		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
+-
+-		if (last_frag)
+-			memcpy(cmd->cmd.tx.tkip_mic.byte, skb_frag->tail - 8,
+-			       8);
+-		else
+-			memset(cmd->cmd.tx.tkip_mic.byte, 0, 8);
+-#endif
++		ieee80211_get_tkip_key(keyinfo->conf, skb_frag,
++			IEEE80211_TKIP_P2_KEY, cmd->cmd.tx.key);
++		IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
+ 		break;
+ 
+ 	case ALG_WEP:
+-		cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP |
+-			(ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
+-
+-		if (keyinfo->keylen == 13)
+-			cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
++		wepkey = &priv->wep_keys[ctl->key_idx];
++		cmd->cmd.tx.sec_ctl = 0;
++		if (priv->default_wep_key) {
++			/* the WEP key was sent as static */
++			keyidx = ctl->key_idx;
++			memcpy(&cmd->cmd.tx.key[3], wepkey->key,
++							wepkey->key_size);
++			if (wepkey->key_size == WEP_KEY_LEN_128)
++				cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
++		} else {
++			/* the WEP key was sent as dynamic */
++			keyidx = keyinfo->keyidx;
++			memcpy(&cmd->cmd.tx.key[3], keyinfo->key,
++							keyinfo->keylen);
++			if (keyinfo->keylen == WEP_KEY_LEN_128)
++				cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
++		}
+ 
+-		memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
++		cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
++			(keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
+ 
+ 		IWL_DEBUG_TX("Configuring packet for WEP encryption "
+-			     "with key %d\n", ctl->key_idx);
++			     "with key %d\n", keyidx);
+ 		break;
+ 
+ 	default:
+@@ -2760,8 +1989,8 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl4965_priv *priv,
+ /*
+  * handle build REPLY_TX command notification.
+  */
+-static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv,
+-				  struct iwl4965_cmd *cmd,
++static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv,
++				  struct iwl_cmd *cmd,
+ 				  struct ieee80211_tx_control *ctrl,
+ 				  struct ieee80211_hdr *hdr,
+ 				  int is_unicast, u8 std_id)
+@@ -2816,20 +2045,27 @@ static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv,
+ 			cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
+ 		else
+ 			cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
+-	} else
++	} else {
+ 		cmd->cmd.tx.timeout.pm_frame_timeout = 0;
++	}
+ 
+ 	cmd->cmd.tx.driver_txop = 0;
+ 	cmd->cmd.tx.tx_flags = tx_flags;
+ 	cmd->cmd.tx.next_frame_len = 0;
+ }
+-
++static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
++{
++	/* 0 - mgmt, 1 - cnt, 2 - data */
++	int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
++	priv->tx_stats[idx].cnt++;
++	priv->tx_stats[idx].bytes += len;
++}
+ /**
+  * iwl4965_get_sta_id - Find station's index within station table
+  *
+  * If new IBSS station, create new entry in station table
+  */
+-static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
++static int iwl4965_get_sta_id(struct iwl_priv *priv,
+ 				struct ieee80211_hdr *hdr)
+ {
+ 	int sta_id;
+@@ -2839,7 +2075,7 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
+ 	/* If this frame is broadcast or management, use broadcast station id */
+ 	if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
+ 	    is_multicast_ether_addr(hdr->addr1))
+-		return priv->hw_setting.bcast_sta_id;
++		return priv->hw_params.bcast_sta_id;
+ 
+ 	switch (priv->iw_mode) {
+ 
+@@ -2853,7 +2089,7 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
+ 		sta_id = iwl4965_hw_find_station(priv, hdr->addr1);
+ 		if (sta_id != IWL_INVALID_STATION)
+ 			return sta_id;
+-		return priv->hw_setting.bcast_sta_id;
++		return priv->hw_params.bcast_sta_id;
+ 
+ 	/* If this frame is going out to an IBSS network, find the station,
+ 	 * or create a new station table entry */
+@@ -2872,19 +2108,19 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
+ 		IWL_DEBUG_DROP("Station %s not in station map. "
+ 			       "Defaulting to broadcast...\n",
+ 			       print_mac(mac, hdr->addr1));
+-		iwl4965_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
+-		return priv->hw_setting.bcast_sta_id;
++		iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
++		return priv->hw_params.bcast_sta_id;
+ 
+ 	default:
+ 		IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
+-		return priv->hw_setting.bcast_sta_id;
++		return priv->hw_params.bcast_sta_id;
+ 	}
+ }
+ 
+ /*
+  * start REPLY_TX command process
+  */
+-static int iwl4965_tx_skb(struct iwl4965_priv *priv,
++static int iwl4965_tx_skb(struct iwl_priv *priv,
+ 		      struct sk_buff *skb, struct ieee80211_tx_control *ctl)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+@@ -2896,7 +2132,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 	dma_addr_t phys_addr;
+ 	dma_addr_t txcmd_phys;
+ 	dma_addr_t scratch_phys;
+-	struct iwl4965_cmd *out_cmd = NULL;
++	struct iwl_cmd *out_cmd = NULL;
+ 	u16 len, idx, len_org;
+ 	u8 id, hdr_len, unicast;
+ 	u8 sta_id;
+@@ -2908,7 +2144,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 	int rc;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	if (iwl4965_is_rfkill(priv)) {
++	if (iwl_is_rfkill(priv)) {
+ 		IWL_DEBUG_DROP("Dropping - RF KILL\n");
+ 		goto drop_unlock;
+ 	}
+@@ -2918,7 +2154,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 		goto drop_unlock;
+ 	}
+ 
+-	if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
++	if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
+ 		IWL_ERROR("ERROR: No TX rate available.\n");
+ 		goto drop_unlock;
+ 	}
+@@ -2928,7 +2164,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 
+ 	fc = le16_to_cpu(hdr->frame_control);
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ 	if (ieee80211_is_auth(fc))
+ 		IWL_DEBUG_TX("Sending AUTH frame\n");
+ 	else if (ieee80211_is_assoc_request(fc))
+@@ -2939,10 +2175,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 
+ 	/* drop all data frame if we are not associated */
+ 	if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+-	   (!iwl4965_is_associated(priv) ||
++	   (!iwl_is_associated(priv) ||
+ 	    ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) ||
+ 	    !priv->assoc_station_added)) {
+-		IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n");
++		IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
+ 		goto drop_unlock;
+ 	}
+ 
+@@ -2972,11 +2208,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 				__constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
+ 		seq_number += 0x10;
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ 		/* aggregation is on for this <sta,tid> */
+-		if (ctl->flags & IEEE80211_TXCTL_HT_MPDU_AGG)
++		if (ctl->flags & IEEE80211_TXCTL_AMPDU)
+ 			txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
+-#endif /* CONFIG_IWL4965_HT_AGG */
++		priv->stations[sta_id].tid[tid].tfds_in_queue++;
+ #endif /* CONFIG_IWL4965_HT */
+ 	}
+ 
+@@ -3025,8 +2260,8 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 	 * of the MAC header (device reads on dword boundaries).
+ 	 * We'll tell device about this padding later.
+ 	 */
+-	len = priv->hw_setting.tx_cmd_len +
+-		sizeof(struct iwl4965_cmd_header) + hdr_len;
++	len = priv->hw_params.tx_cmd_len +
++		sizeof(struct iwl_cmd_header) + hdr_len;
+ 
+ 	len_org = len;
+ 	len = (len + 3) & ~3;
+@@ -3038,15 +2273,15 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 
+ 	/* Physical address of this Tx command's header (not MAC header!),
+ 	 * within command buffer array. */
+-	txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl4965_cmd) * idx +
+-		     offsetof(struct iwl4965_cmd, hdr);
++	txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
++		     offsetof(struct iwl_cmd, hdr);
+ 
+ 	/* Add buffer containing Tx command and MAC(!) header to TFD's
+ 	 * first entry */
+ 	iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
+ 
+ 	if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
+-		iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
++		iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, sta_id);
+ 
+ 	/* Set up TFD's 2nd entry to point directly to remainder of skb,
+ 	 * if any (802.11 null frames have no payload). */
+@@ -3071,19 +2306,13 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 	/* set is_hcca to 0; it probably will never be implemented */
+ 	iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
+ 
+-	scratch_phys = txcmd_phys + sizeof(struct iwl4965_cmd_header) +
++	iwl_update_tx_stats(priv, fc, len);
++
++	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
+ 		offsetof(struct iwl4965_tx_cmd, scratch);
+ 	out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys);
+ 	out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);
+ 
+-#ifdef CONFIG_IWL4965_HT_AGG
+-#ifdef CONFIG_IWL4965_HT
+-	/* TODO: move this functionality to rate scaling */
+-	iwl4965_tl_get_stats(priv, hdr);
+-#endif /* CONFIG_IWL4965_HT_AGG */
+-#endif /*CONFIG_IWL4965_HT */
+-
+-
+ 	if (!ieee80211_get_morefrag(hdr)) {
+ 		txq->need_update = 1;
+ 		if (qc) {
+@@ -3095,17 +2324,17 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ 		txq->need_update = 0;
+ 	}
+ 
+-	iwl4965_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
++	iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
+ 			   sizeof(out_cmd->cmd.tx));
+ 
+-	iwl4965_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
++	iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
+ 			   ieee80211_get_hdrlen(fc));
+ 
+ 	/* Set up entry for this TFD in Tx byte-count array */
+-	iwl4965_tx_queue_update_wr_ptr(priv, txq, len);
++	priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len);
+ 
+ 	/* Tell device the write index *just past* this latest filled TFD */
+-	q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
++	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ 	rc = iwl4965_tx_queue_update_write_ptr(priv, txq);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+@@ -3132,13 +2361,13 @@ drop:
+ 	return -1;
+ }
+ 
+-static void iwl4965_set_rate(struct iwl4965_priv *priv)
++static void iwl4965_set_rate(struct iwl_priv *priv)
+ {
+-	const struct ieee80211_hw_mode *hw = NULL;
++	const struct ieee80211_supported_band *hw = NULL;
+ 	struct ieee80211_rate *rate;
+ 	int i;
+ 
+-	hw = iwl4965_get_hw_mode(priv, priv->phymode);
++	hw = iwl4965_get_hw_mode(priv, priv->band);
+ 	if (!hw) {
+ 		IWL_ERROR("Failed to set rate: unable to get hw mode\n");
+ 		return;
+@@ -3147,24 +2376,10 @@ static void iwl4965_set_rate(struct iwl4965_priv *priv)
+ 	priv->active_rate = 0;
+ 	priv->active_rate_basic = 0;
+ 
+-	IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
+-		       hw->mode == MODE_IEEE80211A ?
+-		       'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
+-
+-	for (i = 0; i < hw->num_rates; i++) {
+-		rate = &(hw->rates[i]);
+-		if ((rate->val < IWL_RATE_COUNT) &&
+-		    (rate->flags & IEEE80211_RATE_SUPPORTED)) {
+-			IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
+-				       rate->val, iwl4965_rates[rate->val].plcp,
+-				       (rate->flags & IEEE80211_RATE_BASIC) ?
+-				       "*" : "");
+-			priv->active_rate |= (1 << rate->val);
+-			if (rate->flags & IEEE80211_RATE_BASIC)
+-				priv->active_rate_basic |= (1 << rate->val);
+-		} else
+-			IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
+-				       rate->val, iwl4965_rates[rate->val].plcp);
++	for (i = 0; i < hw->n_bitrates; i++) {
++		rate = &(hw->bitrates[i]);
++		if (rate->hw_value < IWL_RATE_COUNT)
++			priv->active_rate |= (1 << rate->hw_value);
+ 	}
+ 
+ 	IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
+@@ -3193,7 +2408,7 @@ static void iwl4965_set_rate(struct iwl4965_priv *priv)
+ 		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+ }
+ 
+-static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
++void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
+ {
+ 	unsigned long flags;
+ 
+@@ -3208,17 +2423,26 @@ static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
+ 		/* FIXME: This is a workaround for AP */
+ 		if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ 			spin_lock_irqsave(&priv->lock, flags);
+-			iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
++			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ 				    CSR_UCODE_SW_BIT_RFKILL);
+ 			spin_unlock_irqrestore(&priv->lock, flags);
+-			iwl4965_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
++			/* call the host command only if no hw rf-kill set */
++			if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
++			    iwl_is_ready(priv))
++				iwl4965_send_card_state(priv,
++							CARD_STATE_CMD_DISABLE,
++							0);
+ 			set_bit(STATUS_RF_KILL_SW, &priv->status);
++
++			/* make sure mac80211 stop sending Tx frame */
++			if (priv->mac80211_registered)
++				ieee80211_stop_queues(priv->hw);
+ 		}
+ 		return;
+ 	}
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ 
+ 	clear_bit(STATUS_RF_KILL_SW, &priv->status);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+@@ -3227,9 +2451,9 @@ static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
+ 	msleep(10);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
+-	if (!iwl4965_grab_nic_access(priv))
+-		iwl4965_release_nic_access(priv);
++	iwl_read32(priv, CSR_UCODE_DRV_GP1);
++	if (!iwl_grab_nic_access(priv))
++		iwl_release_nic_access(priv);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
+@@ -3242,7 +2466,7 @@ static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
+ 	return;
+ }
+ 
+-void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
++void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
+ 			    u32 decrypt_res, struct ieee80211_rx_status *stats)
+ {
+ 	u16 fc =
+@@ -3257,6 +2481,12 @@ void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
+ 	IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
+ 	switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
+ 	case RX_RES_STATUS_SEC_TYPE_TKIP:
++		/* The uCode has got a bad phase 1 Key, pushes the packet.
++		 * Decryption will be done in SW. */
++		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
++		    RX_RES_STATUS_BAD_KEY_TTAK)
++			break;
++
+ 		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+ 		    RX_RES_STATUS_BAD_ICV_MIC)
+ 			stats->flag |= RX_FLAG_MMIC_ERROR;
+@@ -3277,7 +2507,7 @@ void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
+ 
+ #define IWL_PACKET_RETRY_TIME HZ
+ 
+-int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header)
++int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
+ {
+ 	u16 sc = le16_to_cpu(header->seq_ctrl);
+ 	u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
+@@ -3394,13 +2624,13 @@ static __le32 iwl4965_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
+ 	return cpu_to_le32(res);
+ }
+ 
+-static int iwl4965_get_measurement(struct iwl4965_priv *priv,
++static int iwl4965_get_measurement(struct iwl_priv *priv,
+ 			       struct ieee80211_measurement_params *params,
+ 			       u8 type)
+ {
+ 	struct iwl4965_spectrum_cmd spectrum;
+ 	struct iwl4965_rx_packet *res;
+-	struct iwl4965_host_cmd cmd = {
++	struct iwl_host_cmd cmd = {
+ 		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
+ 		.data = (void *)&spectrum,
+ 		.meta.flags = CMD_WANT_SKB,
+@@ -3410,7 +2640,7 @@ static int iwl4965_get_measurement(struct iwl4965_priv *priv,
+ 	int spectrum_resp_status;
+ 	int duration = le16_to_cpu(params->duration);
+ 
+-	if (iwl4965_is_associated(priv))
++	if (iwl_is_associated(priv))
+ 		add_time =
+ 		    iwl4965_usecs_to_beacons(
+ 			le64_to_cpu(params->start_time) - priv->last_tsf,
+@@ -3425,7 +2655,7 @@ static int iwl4965_get_measurement(struct iwl4965_priv *priv,
+ 	cmd.len = sizeof(spectrum);
+ 	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
+ 
+-	if (iwl4965_is_associated(priv))
++	if (iwl_is_associated(priv))
+ 		spectrum.start_time =
+ 		    iwl4965_add_beacon_time(priv->last_beacon_time,
+ 				add_time,
+@@ -3440,7 +2670,7 @@ static int iwl4965_get_measurement(struct iwl4965_priv *priv,
+ 		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
+ 		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
+ 
+-	rc = iwl4965_send_cmd_sync(priv, &cmd);
++	rc = iwl_send_cmd_sync(priv, &cmd);
+ 	if (rc)
+ 		return rc;
+ 
+@@ -3474,7 +2704,7 @@ static int iwl4965_get_measurement(struct iwl4965_priv *priv,
+ }
+ #endif
+ 
+-static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv,
++static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
+ 				 struct iwl4965_tx_info *tx_sta)
+ {
+ 
+@@ -3500,7 +2730,7 @@ static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv,
+  * need to be reclaimed. As result, some free space forms.  If there is
+  * enough free space (> low mark), wake the stack that feeds us.
+  */
+-int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
++int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+ {
+ 	struct iwl4965_tx_queue *txq = &priv->txq[txq_id];
+ 	struct iwl4965_queue *q = &txq->q;
+@@ -3513,9 +2743,9 @@ int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
+ 		return 0;
+ 	}
+ 
+-	for (index = iwl4965_queue_inc_wrap(index, q->n_bd);
++	for (index = iwl_queue_inc_wrap(index, q->n_bd);
+ 		q->read_ptr != index;
+-		q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd)) {
++		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+ 		if (txq_id != IWL_CMD_QUEUE_NUM) {
+ 			iwl4965_txstatus_to_ieee(priv,
+ 					&(txq->txb[txq->q.read_ptr]));
+@@ -3528,10 +2758,10 @@ int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
+ 		nfreed++;
+ 	}
+ 
+-	if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
++/*	if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
+ 			(txq_id != IWL_CMD_QUEUE_NUM) &&
+ 			priv->mac80211_registered)
+-		ieee80211_wake_queue(priv->hw, txq_id);
++		ieee80211_wake_queue(priv->hw, txq_id); */
+ 
+ 
+ 	return nfreed;
+@@ -3550,9 +2780,8 @@ static int iwl4965_is_tx_success(u32 status)
+  *
+  ******************************************************************************/
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ 
+-static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv,
++static inline int iwl4965_get_ra_sta_id(struct iwl_priv *priv,
+ 				    struct ieee80211_hdr *hdr)
+ {
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
+@@ -3564,7 +2793,7 @@ static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv,
+ }
+ 
+ static struct ieee80211_hdr *iwl4965_tx_queue_get_hdr(
+-	struct iwl4965_priv *priv, int txq_id, int idx)
++	struct iwl_priv *priv, int txq_id, int idx)
+ {
+ 	if (priv->txq[txq_id].txb[idx].skb[0])
+ 		return (struct ieee80211_hdr *)priv->txq[txq_id].
+@@ -3583,13 +2812,13 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
+ /**
+  * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
+  */
+-static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
++static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
+ 				      struct iwl4965_ht_agg *agg,
+-				      struct iwl4965_tx_resp *tx_resp,
++				      struct iwl4965_tx_resp_agg *tx_resp,
+ 				      u16 start_idx)
+ {
+-	u32 status;
+-	__le32 *frame_status = &tx_resp->status;
++	u16 status;
++	struct agg_tx_status *frame_status = &tx_resp->status;
+ 	struct ieee80211_tx_status *tx_status = NULL;
+ 	struct ieee80211_hdr *hdr = NULL;
+ 	int i, sh;
+@@ -3602,30 +2831,30 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
+ 	agg->frame_count = tx_resp->frame_count;
+ 	agg->start_idx = start_idx;
+ 	agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+-	agg->bitmap0 = agg->bitmap1 = 0;
++	agg->bitmap = 0;
+ 
+ 	/* # frames attempted by Tx command */
+ 	if (agg->frame_count == 1) {
+ 		/* Only one frame was attempted; no block-ack will arrive */
+-		struct iwl4965_tx_queue *txq ;
+-		status = le32_to_cpu(frame_status[0]);
++		status = le16_to_cpu(frame_status[0].status);
++		seq  = le16_to_cpu(frame_status[0].sequence);
++		idx = SEQ_TO_INDEX(seq);
++		txq_id = SEQ_TO_QUEUE(seq);
+ 
+-		txq_id = agg->txq_id;
+-		txq = &priv->txq[txq_id];
+ 		/* FIXME: code repetition */
+-		IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d \n",
+-				   agg->frame_count, agg->start_idx);
++		IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
++				   agg->frame_count, agg->start_idx, idx);
+ 
+-		tx_status = &(priv->txq[txq_id].txb[txq->q.read_ptr].status);
++		tx_status = &(priv->txq[txq_id].txb[idx].status);
+ 		tx_status->retry_count = tx_resp->failure_frame;
+ 		tx_status->queue_number = status & 0xff;
+-		tx_status->queue_length = tx_resp->bt_kill_count;
+-		tx_status->queue_length |= tx_resp->failure_rts;
+-
++		tx_status->queue_length = tx_resp->failure_rts;
++		tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
+ 		tx_status->flags = iwl4965_is_tx_success(status)?
+ 			IEEE80211_TX_STATUS_ACK : 0;
+-		tx_status->control.tx_rate =
+-				iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags);
++		iwl4965_hwrate_to_tx_control(priv,
++					     le32_to_cpu(tx_resp->rate_n_flags),
++					     &tx_status->control);
+ 		/* FIXME: code repetition end */
+ 
+ 		IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
+@@ -3642,8 +2871,8 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
+ 		/* Construct bit-map of pending frames within Tx window */
+ 		for (i = 0; i < agg->frame_count; i++) {
+ 			u16 sc;
+-			status = le32_to_cpu(frame_status[i]);
+-			seq  = status >> 16;
++			status = le16_to_cpu(frame_status[i].status);
++			seq  = le16_to_cpu(frame_status[i].sequence);
+ 			idx = SEQ_TO_INDEX(seq);
+ 			txq_id = SEQ_TO_QUEUE(seq);
+ 
+@@ -3687,13 +2916,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
+ 					   start, (u32)(bitmap & 0xFFFFFFFF));
+ 		}
+ 
+-		agg->bitmap0 = bitmap & 0xFFFFFFFF;
+-		agg->bitmap1 = bitmap >> 32;
++		agg->bitmap = bitmap;
+ 		agg->start_idx = start;
+ 		agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+-		IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%x\n",
++		IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
+ 				   agg->frame_count, agg->start_idx,
+-				   agg->bitmap0);
++				   (unsigned long long)agg->bitmap);
+ 
+ 		if (bitmap)
+ 			agg->wait_for_ba = 1;
+@@ -3701,12 +2929,11 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
+ 	return 0;
+ }
+ #endif
+-#endif
+ 
+ /**
+  * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
+  */
+-static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
+ 			    struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3718,9 +2945,9 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ 	struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+ 	u32  status = le32_to_cpu(tx_resp->status);
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+-	int tid, sta_id;
+-#endif
++	int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
++	struct ieee80211_hdr *hdr;
++	__le16 *qc;
+ #endif
+ 
+ 	if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
+@@ -3732,44 +2959,51 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ 	}
+ 
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
++	hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index);
++	qc = ieee80211_get_qos_ctrl(hdr);
++
++	if (qc)
++		tid = le16_to_cpu(*qc) & 0xf;
++
++	sta_id = iwl4965_get_ra_sta_id(priv, hdr);
++	if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
++		IWL_ERROR("Station not known\n");
++		return;
++	}
++
+ 	if (txq->sched_retry) {
+ 		const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
+-		struct ieee80211_hdr *hdr =
+-			iwl4965_tx_queue_get_hdr(priv, txq_id, index);
+ 		struct iwl4965_ht_agg *agg = NULL;
+-		__le16 *qc = ieee80211_get_qos_ctrl(hdr);
+ 
+-		if (qc == NULL) {
+-			IWL_ERROR("BUG_ON qc is null!!!!\n");
++		if (!qc)
+ 			return;
+-		}
+-
+-		tid = le16_to_cpu(*qc) & 0xf;
+-
+-		sta_id = iwl4965_get_ra_sta_id(priv, hdr);
+-		if (unlikely(sta_id == IWL_INVALID_STATION)) {
+-			IWL_ERROR("Station not known for\n");
+-			return;
+-		}
+ 
+ 		agg = &priv->stations[sta_id].tid[tid].agg;
+ 
+-		iwl4965_tx_status_reply_tx(priv, agg, tx_resp, index);
++		iwl4965_tx_status_reply_tx(priv, agg,
++				(struct iwl4965_tx_resp_agg *)tx_resp, index);
+ 
+ 		if ((tx_resp->frame_count == 1) &&
+ 		    !iwl4965_is_tx_success(status)) {
+ 			/* TODO: send BAR */
+ 		}
+ 
+-		if ((txq->q.read_ptr != (scd_ssn & 0xff))) {
+-			index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
++		if (txq->q.read_ptr != (scd_ssn & 0xff)) {
++			int freed;
++			index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
+ 			IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
+ 					   "%d index %d\n", scd_ssn , index);
+-			iwl4965_tx_queue_reclaim(priv, txq_id, index);
++			freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
++			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
++
++			if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
++			    txq_id >= 0 && priv->mac80211_registered &&
++			    agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
++				ieee80211_wake_queue(priv->hw, txq_id);
++
++			iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
+ 		}
+ 	} else {
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ 	tx_status = &(txq->txb[txq->q.read_ptr].status);
+ 
+@@ -3777,12 +3011,10 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ 	tx_status->queue_number = status;
+ 	tx_status->queue_length = tx_resp->bt_kill_count;
+ 	tx_status->queue_length |= tx_resp->failure_rts;
+-
+ 	tx_status->flags =
+ 	    iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
+-
+-	tx_status->control.tx_rate =
+-		iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags);
++	iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
++				     &tx_status->control);
+ 
+ 	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
+ 		     "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status),
+@@ -3790,12 +3022,21 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ 		     tx_resp->failure_frame);
+ 
+ 	IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
+-	if (index != -1)
+-		iwl4965_tx_queue_reclaim(priv, txq_id, index);
++	if (index != -1) {
++		int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
++#ifdef CONFIG_IWL4965_HT
++		if (tid != MAX_TID_COUNT)
++			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
++		if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
++			(txq_id >= 0) &&
++			priv->mac80211_registered)
++			ieee80211_wake_queue(priv->hw, txq_id);
++		if (tid != MAX_TID_COUNT)
++			iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
++#endif
++	}
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ 	}
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ 
+ 	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
+@@ -3803,7 +3044,7 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ }
+ 
+ 
+-static void iwl4965_rx_reply_alive(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
+ 			       struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3839,7 +3080,7 @@ static void iwl4965_rx_reply_alive(struct iwl4965_priv *priv,
+ 		IWL_WARNING("uCode did not respond OK.\n");
+ }
+ 
+-static void iwl4965_rx_reply_add_sta(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_add_sta(struct iwl_priv *priv,
+ 				 struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3848,7 +3089,7 @@ static void iwl4965_rx_reply_add_sta(struct iwl4965_priv *priv,
+ 	return;
+ }
+ 
+-static void iwl4965_rx_reply_error(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_error(struct iwl_priv *priv,
+ 			       struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3864,7 +3105,7 @@ static void iwl4965_rx_reply_error(struct iwl4965_priv *priv,
+ 
+ #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
+ 
+-static void iwl4965_rx_csa(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
++static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ 	struct iwl4965_rxon_cmd *rxon = (void *)&priv->active_rxon;
+@@ -3875,7 +3116,7 @@ static void iwl4965_rx_csa(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buff
+ 	priv->staging_rxon.channel = csa->channel;
+ }
+ 
+-static void iwl4965_rx_spectrum_measure_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
+ 					  struct iwl4965_rx_mem_buffer *rxb)
+ {
+ #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
+@@ -3893,10 +3134,10 @@ static void iwl4965_rx_spectrum_measure_notif(struct iwl4965_priv *priv,
+ #endif
+ }
+ 
+-static void iwl4965_rx_pm_sleep_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
+ 				  struct iwl4965_rx_mem_buffer *rxb)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ 	struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif);
+ 	IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
+@@ -3904,20 +3145,20 @@ static void iwl4965_rx_pm_sleep_notif(struct iwl4965_priv *priv,
+ #endif
+ }
+ 
+-static void iwl4965_rx_pm_debug_statistics_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+ 					     struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ 	IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
+ 			"notification for %s:\n",
+ 			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
+-	iwl4965_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
++	iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+ }
+ 
+ static void iwl4965_bg_beacon_update(struct work_struct *work)
+ {
+-	struct iwl4965_priv *priv =
+-		container_of(work, struct iwl4965_priv, beacon_update);
++	struct iwl_priv *priv =
++		container_of(work, struct iwl_priv, beacon_update);
+ 	struct sk_buff *beacon;
+ 
+ 	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
+@@ -3939,10 +3180,10 @@ static void iwl4965_bg_beacon_update(struct work_struct *work)
+ 	iwl4965_send_beacon_cmd(priv);
+ }
+ 
+-static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
+ 				struct iwl4965_rx_mem_buffer *rxb)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ 	struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status);
+ 	u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+@@ -3962,10 +3203,10 @@ static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv,
+ }
+ 
+ /* Service response to REPLY_SCAN_CMD (0x80) */
+-static void iwl4965_rx_reply_scan(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_scan(struct iwl_priv *priv,
+ 			      struct iwl4965_rx_mem_buffer *rxb)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ 	struct iwl4965_scanreq_notification *notif =
+ 	    (struct iwl4965_scanreq_notification *)pkt->u.raw;
+@@ -3975,7 +3216,7 @@ static void iwl4965_rx_reply_scan(struct iwl4965_priv *priv,
+ }
+ 
+ /* Service SCAN_START_NOTIFICATION (0x82) */
+-static void iwl4965_rx_scan_start_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv,
+ 				    struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3992,7 +3233,7 @@ static void iwl4965_rx_scan_start_notif(struct iwl4965_priv *priv,
+ }
+ 
+ /* Service SCAN_RESULTS_NOTIFICATION (0x83) */
+-static void iwl4965_rx_scan_results_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv,
+ 				      struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4017,7 +3258,7 @@ static void iwl4965_rx_scan_results_notif(struct iwl4965_priv *priv,
+ }
+ 
+ /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
+-static void iwl4965_rx_scan_complete_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv,
+ 				       struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4075,7 +3316,7 @@ reschedule:
+ 
+ /* Handle notification from uCode that card's power state is changing
+  * due to software, hardware, or critical temperature RFKILL */
+-static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
+ 				    struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4089,35 +3330,35 @@ static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv,
+ 	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
+ 		     RF_CARD_DISABLED)) {
+ 
+-		iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
++		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ 			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+ 
+-		if (!iwl4965_grab_nic_access(priv)) {
+-			iwl4965_write_direct32(
++		if (!iwl_grab_nic_access(priv)) {
++			iwl_write_direct32(
+ 				priv, HBUS_TARG_MBX_C,
+ 				HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+ 
+-			iwl4965_release_nic_access(priv);
++			iwl_release_nic_access(priv);
+ 		}
+ 
+ 		if (!(flags & RXON_CARD_DISABLED)) {
+-			iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ 				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+-			if (!iwl4965_grab_nic_access(priv)) {
+-				iwl4965_write_direct32(
++			if (!iwl_grab_nic_access(priv)) {
++				iwl_write_direct32(
+ 					priv, HBUS_TARG_MBX_C,
+ 					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+ 
+-				iwl4965_release_nic_access(priv);
++				iwl_release_nic_access(priv);
+ 			}
+ 		}
+ 
+ 		if (flags & RF_CARD_DISABLED) {
+-			iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
++			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ 				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+-			iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
+-			if (!iwl4965_grab_nic_access(priv))
+-				iwl4965_release_nic_access(priv);
++			iwl_read32(priv, CSR_UCODE_DRV_GP1);
++			if (!iwl_grab_nic_access(priv))
++				iwl_release_nic_access(priv);
+ 		}
+ 	}
+ 
+@@ -4153,7 +3394,7 @@ static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv,
+  * This function chains into the hardware specific files for them to setup
+  * any hardware specific handlers as well.
+  */
+-static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv)
++static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
+ {
+ 	priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
+ 	priv->rx_handlers[REPLY_ADD_STA] = iwl4965_rx_reply_add_sta;
+@@ -4195,7 +3436,7 @@ static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv)
+  * will be executed.  The attached skb (if present) will only be freed
+  * if the callback returns 1
+  */
+-static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv,
++static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
+ 				struct iwl4965_rx_mem_buffer *rxb)
+ {
+ 	struct iwl4965_rx_packet *pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
+@@ -4204,7 +3445,7 @@ static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv,
+ 	int index = SEQ_TO_INDEX(sequence);
+ 	int huge = sequence & SEQ_HUGE_FRAME;
+ 	int cmd_index;
+-	struct iwl4965_cmd *cmd;
++	struct iwl_cmd *cmd;
+ 
+ 	/* 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
+@@ -4318,7 +3559,7 @@ static int iwl4965_rx_queue_space(const struct iwl4965_rx_queue *q)
+ /**
+  * iwl4965_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+  */
+-int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_rx_queue *q)
++int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_queue *q)
+ {
+ 	u32 reg = 0;
+ 	int rc = 0;
+@@ -4331,27 +3572,27 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_
+ 
+ 	/* If power-saving is in use, make sure device is awake */
+ 	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+-		reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
++		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ 
+ 		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+-			iwl4965_set_bit(priv, CSR_GP_CNTRL,
++			iwl_set_bit(priv, CSR_GP_CNTRL,
+ 				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ 			goto exit_unlock;
+ 		}
+ 
+-		rc = iwl4965_grab_nic_access(priv);
++		rc = iwl_grab_nic_access(priv);
+ 		if (rc)
+ 			goto exit_unlock;
+ 
+ 		/* Device expects a multiple of 8 */
+-		iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
++		iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
+ 				     q->write & ~0x7);
+-		iwl4965_release_nic_access(priv);
++		iwl_release_nic_access(priv);
+ 
+ 	/* Else device is assumed to be awake */
+ 	} else
+ 		/* Device expects a multiple of 8 */
+-		iwl4965_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
++		iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
+ 
+ 
+ 	q->need_update = 0;
+@@ -4364,7 +3605,7 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_
+ /**
+  * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+  */
+-static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv,
++static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl_priv *priv,
+ 					  dma_addr_t dma_addr)
+ {
+ 	return cpu_to_le32((u32)(dma_addr >> 8));
+@@ -4382,7 +3623,7 @@ static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv,
+  * also updates the memory address in the firmware to reference the new
+  * target buffer.
+  */
+-static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv)
++static int iwl4965_rx_queue_restock(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_rx_queue *rxq = &priv->rxq;
+ 	struct list_head *element;
+@@ -4434,7 +3675,7 @@ static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv)
+  * Also restock the Rx queue via iwl4965_rx_queue_restock.
+  * This is called as a scheduled work item (except for during initialization)
+  */
+-static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
++static void iwl4965_rx_allocate(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_rx_queue *rxq = &priv->rxq;
+ 	struct list_head *element;
+@@ -4447,7 +3688,7 @@ static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
+ 
+ 		/* Alloc a new receive buffer */
+ 		rxb->skb =
+-		    alloc_skb(priv->hw_setting.rx_buf_size,
++		    alloc_skb(priv->hw_params.rx_buf_size,
+ 				__GFP_NOWARN | GFP_ATOMIC);
+ 		if (!rxb->skb) {
+ 			if (net_ratelimit())
+@@ -4464,7 +3705,7 @@ static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
+ 		/* Get physical address of RB/SKB */
+ 		rxb->dma_addr =
+ 		    pci_map_single(priv->pci_dev, rxb->skb->data,
+-			   priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE);
++			   priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE);
+ 		list_add_tail(&rxb->list, &rxq->rx_free);
+ 		rxq->free_count++;
+ 	}
+@@ -4476,7 +3717,7 @@ static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
+ */
+ static void __iwl4965_rx_replenish(void *data)
+ {
+-	struct iwl4965_priv *priv = data;
++	struct iwl_priv *priv = data;
+ 
+ 	iwl4965_rx_allocate(priv);
+ 	iwl4965_rx_queue_restock(priv);
+@@ -4485,7 +3726,7 @@ static void __iwl4965_rx_replenish(void *data)
+ 
+ void iwl4965_rx_replenish(void *data)
+ {
+-	struct iwl4965_priv *priv = data;
++	struct iwl_priv *priv = data;
+ 	unsigned long flags;
+ 
+ 	iwl4965_rx_allocate(priv);
+@@ -4500,14 +3741,14 @@ void iwl4965_rx_replenish(void *data)
+  * This free routine walks the list of POOL entries and if SKB is set to
+  * non NULL it is unmapped and freed
+  */
+-static void iwl4965_rx_queue_free(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
++static void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
+ {
+ 	int i;
+ 	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+ 		if (rxq->pool[i].skb != NULL) {
+ 			pci_unmap_single(priv->pci_dev,
+ 					 rxq->pool[i].dma_addr,
+-					 priv->hw_setting.rx_buf_size,
++					 priv->hw_params.rx_buf_size,
+ 					 PCI_DMA_FROMDEVICE);
+ 			dev_kfree_skb(rxq->pool[i].skb);
+ 		}
+@@ -4518,7 +3759,7 @@ static void iwl4965_rx_queue_free(struct iwl4965_priv *priv, struct iwl4965_rx_q
+ 	rxq->bd = NULL;
+ }
+ 
+-int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv)
++int iwl4965_rx_queue_alloc(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_rx_queue *rxq = &priv->rxq;
+ 	struct pci_dev *dev = priv->pci_dev;
+@@ -4545,7 +3786,7 @@ int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv)
+ 	return 0;
+ }
+ 
+-void iwl4965_rx_queue_reset(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
++void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
+ {
+ 	unsigned long flags;
+ 	int i;
+@@ -4559,7 +3800,7 @@ void iwl4965_rx_queue_reset(struct iwl4965_priv *priv, struct iwl4965_rx_queue *
+ 		if (rxq->pool[i].skb != NULL) {
+ 			pci_unmap_single(priv->pci_dev,
+ 					 rxq->pool[i].dma_addr,
+-					 priv->hw_setting.rx_buf_size,
++					 priv->hw_params.rx_buf_size,
+ 					 PCI_DMA_FROMDEVICE);
+ 			priv->alloc_rxb_skb--;
+ 			dev_kfree_skb(rxq->pool[i].skb);
+@@ -4660,7 +3901,7 @@ int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
+  * the appropriate handlers, including command responses,
+  * frame-received notifications, and other notifications.
+  */
+-static void iwl4965_rx_handle(struct iwl4965_priv *priv)
++static void iwl4965_rx_handle(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_rx_mem_buffer *rxb;
+ 	struct iwl4965_rx_packet *pkt;
+@@ -4694,7 +3935,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+ 		rxq->queue[i] = NULL;
+ 
+ 		pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
+-					    priv->hw_setting.rx_buf_size,
++					    priv->hw_params.rx_buf_size,
+ 					    PCI_DMA_FROMDEVICE);
+ 		pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
+ 
+@@ -4706,7 +3947,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+ 		 *   but apparently a few don't get set; catch them here. */
+ 		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+ 			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
+-			(pkt->hdr.cmd != REPLY_4965_RX) &&
++			(pkt->hdr.cmd != REPLY_RX) &&
+ 			(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
+ 			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+ 			(pkt->hdr.cmd != REPLY_TX);
+@@ -4729,7 +3970,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+ 
+ 		if (reclaim) {
+ 			/* Invoke any callbacks, transfer the skb to caller, and
+-			 * fire off the (possibly) blocking iwl4965_send_cmd()
++			 * fire off the (possibly) blocking iwl_send_cmd()
+ 			 * as we reclaim the driver command queue */
+ 			if (rxb && rxb->skb)
+ 				iwl4965_tx_cmd_complete(priv, rxb);
+@@ -4747,7 +3988,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+ 		}
+ 
+ 		pci_unmap_single(priv->pci_dev, rxb->dma_addr,
+-				 priv->hw_setting.rx_buf_size,
++				 priv->hw_params.rx_buf_size,
+ 				 PCI_DMA_FROMDEVICE);
+ 		spin_lock_irqsave(&rxq->lock, flags);
+ 		list_add_tail(&rxb->list, &priv->rxq.rx_used);
+@@ -4773,7 +4014,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+ /**
+  * iwl4965_tx_queue_update_write_ptr - Send new write index to hardware
+  */
+-static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
++static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
+ 				  struct iwl4965_tx_queue *txq)
+ {
+ 	u32 reg = 0;
+@@ -4788,27 +4029,27 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
+ 		/* wake up nic if it's powered down ...
+ 		 * uCode will wake up, and interrupt us again, so next
+ 		 * time we'll skip this part. */
+-		reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
++		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ 
+ 		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+ 			IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
+-			iwl4965_set_bit(priv, CSR_GP_CNTRL,
++			iwl_set_bit(priv, CSR_GP_CNTRL,
+ 				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ 			return rc;
+ 		}
+ 
+ 		/* restore this queue's parameters in nic hardware. */
+-		rc = iwl4965_grab_nic_access(priv);
++		rc = iwl_grab_nic_access(priv);
+ 		if (rc)
+ 			return rc;
+-		iwl4965_write_direct32(priv, HBUS_TARG_WRPTR,
++		iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+ 				     txq->q.write_ptr | (txq_id << 8));
+-		iwl4965_release_nic_access(priv);
++		iwl_release_nic_access(priv);
+ 
+ 	/* else not in power-save mode, uCode will never sleep when we're
+ 	 * trying to tx (during RFKILL, we're not trying to tx). */
+ 	} else
+-		iwl4965_write32(priv, HBUS_TARG_WRPTR,
++		iwl_write32(priv, HBUS_TARG_WRPTR,
+ 			    txq->q.write_ptr | (txq_id << 8));
+ 
+ 	txq->need_update = 0;
+@@ -4816,13 +4057,13 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
+ 	return rc;
+ }
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon)
+ {
+ 	DECLARE_MAC_BUF(mac);
+ 
+ 	IWL_DEBUG_RADIO("RX CONFIG:\n");
+-	iwl4965_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
++	iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+ 	IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
+ 	IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
+ 	IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
+@@ -4839,24 +4080,32 @@ static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon)
+ }
+ #endif
+ 
+-static void iwl4965_enable_interrupts(struct iwl4965_priv *priv)
++static void iwl4965_enable_interrupts(struct iwl_priv *priv)
+ {
+ 	IWL_DEBUG_ISR("Enabling interrupts\n");
+ 	set_bit(STATUS_INT_ENABLED, &priv->status);
+-	iwl4965_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
++	iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
++}
++
++/* call this function to flush any scheduled tasklet */
++static inline void iwl_synchronize_irq(struct iwl_priv *priv)
++{
++	/* wait to make sure we flush pedding tasklet*/
++	synchronize_irq(priv->pci_dev->irq);
++	tasklet_kill(&priv->irq_tasklet);
+ }
+ 
+-static inline void iwl4965_disable_interrupts(struct iwl4965_priv *priv)
++static inline void iwl4965_disable_interrupts(struct iwl_priv *priv)
+ {
+ 	clear_bit(STATUS_INT_ENABLED, &priv->status);
+ 
+ 	/* disable interrupts from uCode/NIC to host */
+-	iwl4965_write32(priv, CSR_INT_MASK, 0x00000000);
++	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+ 
+ 	/* acknowledge/clear/reset any interrupts still pending
+ 	 * from uCode or flow handler (Rx/Tx DMA) */
+-	iwl4965_write32(priv, CSR_INT, 0xffffffff);
+-	iwl4965_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
++	iwl_write32(priv, CSR_INT, 0xffffffff);
++	iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
+ 	IWL_DEBUG_ISR("Disabled interrupts\n");
+ }
+ 
+@@ -4883,7 +4132,7 @@ static const char *desc_lookup(int i)
+ #define ERROR_START_OFFSET  (1 * sizeof(u32))
+ #define ERROR_ELEM_SIZE     (7 * sizeof(u32))
+ 
+-static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
++static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
+ {
+ 	u32 data2, line;
+ 	u32 desc, time, count, base, data1;
+@@ -4892,34 +4141,33 @@ static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
+ 
+ 	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+ 
+-	if (!iwl4965_hw_valid_rtc_data_addr(base)) {
++	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ 		IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
+ 		return;
+ 	}
+ 
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc) {
+ 		IWL_WARNING("Can not read from adapter at this time.\n");
+ 		return;
+ 	}
+ 
+-	count = iwl4965_read_targ_mem(priv, base);
++	count = iwl_read_targ_mem(priv, base);
+ 
+ 	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ 		IWL_ERROR("Start IWL Error Log Dump:\n");
+-		IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n",
+-			  priv->status, priv->config, count);
++		IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
+ 	}
+ 
+-	desc = iwl4965_read_targ_mem(priv, base + 1 * sizeof(u32));
+-	blink1 = iwl4965_read_targ_mem(priv, base + 3 * sizeof(u32));
+-	blink2 = iwl4965_read_targ_mem(priv, base + 4 * sizeof(u32));
+-	ilink1 = iwl4965_read_targ_mem(priv, base + 5 * sizeof(u32));
+-	ilink2 = iwl4965_read_targ_mem(priv, base + 6 * sizeof(u32));
+-	data1 = iwl4965_read_targ_mem(priv, base + 7 * sizeof(u32));
+-	data2 = iwl4965_read_targ_mem(priv, base + 8 * sizeof(u32));
+-	line = iwl4965_read_targ_mem(priv, base + 9 * sizeof(u32));
+-	time = iwl4965_read_targ_mem(priv, base + 11 * sizeof(u32));
++	desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
++	blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
++	blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
++	ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
++	ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
++	data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
++	data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
++	line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
++	time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
+ 
+ 	IWL_ERROR("Desc               Time       "
+ 		  "data1      data2      line\n");
+@@ -4929,7 +4177,7 @@ static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
+ 	IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
+ 		  ilink1, ilink2);
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ }
+ 
+ #define EVENT_START_OFFSET  (4 * sizeof(u32))
+@@ -4937,9 +4185,9 @@ static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
+ /**
+  * iwl4965_print_event_log - Dump error event log to syslog
+  *
+- * NOTE: Must be called with iwl4965_grab_nic_access() already obtained!
++ * NOTE: Must be called with iwl_grab_nic_access() already obtained!
+  */
+-static void iwl4965_print_event_log(struct iwl4965_priv *priv, u32 start_idx,
++static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ 				u32 num_events, u32 mode)
+ {
+ 	u32 i;
+@@ -4963,21 +4211,21 @@ static void iwl4965_print_event_log(struct iwl4965_priv *priv, u32 start_idx,
+ 	/* "time" is actually "data" for mode 0 (no timestamp).
+ 	 * place event id # at far right for easier visual parsing. */
+ 	for (i = 0; i < num_events; i++) {
+-		ev = iwl4965_read_targ_mem(priv, ptr);
++		ev = iwl_read_targ_mem(priv, ptr);
+ 		ptr += sizeof(u32);
+-		time = iwl4965_read_targ_mem(priv, ptr);
++		time = iwl_read_targ_mem(priv, ptr);
+ 		ptr += sizeof(u32);
+ 		if (mode == 0)
+ 			IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
+ 		else {
+-			data = iwl4965_read_targ_mem(priv, ptr);
++			data = iwl_read_targ_mem(priv, ptr);
+ 			ptr += sizeof(u32);
+ 			IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
+ 		}
+ 	}
+ }
+ 
+-static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv)
++static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
+ {
+ 	int rc;
+ 	u32 base;       /* SRAM byte address of event log header */
+@@ -4988,29 +4236,29 @@ static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv)
+ 	u32 size;       /* # entries that we'll print */
+ 
+ 	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+-	if (!iwl4965_hw_valid_rtc_data_addr(base)) {
++	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ 		IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
+ 		return;
+ 	}
+ 
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc) {
+ 		IWL_WARNING("Can not read from adapter at this time.\n");
+ 		return;
+ 	}
+ 
+ 	/* event log header */
+-	capacity = iwl4965_read_targ_mem(priv, base);
+-	mode = iwl4965_read_targ_mem(priv, base + (1 * sizeof(u32)));
+-	num_wraps = iwl4965_read_targ_mem(priv, base + (2 * sizeof(u32)));
+-	next_entry = iwl4965_read_targ_mem(priv, base + (3 * sizeof(u32)));
++	capacity = iwl_read_targ_mem(priv, base);
++	mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
++	num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
++	next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
+ 
+ 	size = num_wraps ? capacity : next_entry;
+ 
+ 	/* bail out if nothing in log */
+ 	if (size == 0) {
+ 		IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
+-		iwl4965_release_nic_access(priv);
++		iwl_release_nic_access(priv);
+ 		return;
+ 	}
+ 
+@@ -5026,13 +4274,13 @@ static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv)
+ 	/* (then/else) start at top of log */
+ 	iwl4965_print_event_log(priv, 0, next_entry, mode);
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ }
+ 
+ /**
+  * iwl4965_irq_handle_error - called for HW or SW error interrupt from card
+  */
+-static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
++static void iwl4965_irq_handle_error(struct iwl_priv *priv)
+ {
+ 	/* Set the FW error flag -- cleared on iwl4965_down */
+ 	set_bit(STATUS_FW_ERROR, &priv->status);
+@@ -5040,8 +4288,8 @@ static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
+ 	/* Cancel currently queued command. */
+ 	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
+-	if (iwl4965_debug_level & IWL_DL_FW_ERRORS) {
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & IWL_DL_FW_ERRORS) {
+ 		iwl4965_dump_nic_error_log(priv);
+ 		iwl4965_dump_nic_event_log(priv);
+ 		iwl4965_print_rx_config_cmd(&priv->staging_rxon);
+@@ -5058,7 +4306,7 @@ static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
+ 		IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
+ 			  "Restarting adapter due to uCode error.\n");
+ 
+-		if (iwl4965_is_associated(priv)) {
++		if (iwl_is_associated(priv)) {
+ 			memcpy(&priv->recovery_rxon, &priv->active_rxon,
+ 			       sizeof(priv->recovery_rxon));
+ 			priv->error_recovering = 1;
+@@ -5067,7 +4315,7 @@ static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
+ 	}
+ }
+ 
+-static void iwl4965_error_recovery(struct iwl4965_priv *priv)
++static void iwl4965_error_recovery(struct iwl_priv *priv)
+ {
+ 	unsigned long flags;
+ 
+@@ -5084,12 +4332,12 @@ static void iwl4965_error_recovery(struct iwl4965_priv *priv)
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ 
+-static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
++static void iwl4965_irq_tasklet(struct iwl_priv *priv)
+ {
+ 	u32 inta, handled = 0;
+ 	u32 inta_fh;
+ 	unsigned long flags;
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ 	u32 inta_mask;
+ #endif
+ 
+@@ -5098,19 +4346,19 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ 	/* Ack/clear/reset pending uCode interrupts.
+ 	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
+ 	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
+-	inta = iwl4965_read32(priv, CSR_INT);
+-	iwl4965_write32(priv, CSR_INT, inta);
++	inta = iwl_read32(priv, CSR_INT);
++	iwl_write32(priv, CSR_INT, inta);
+ 
+ 	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
+ 	 * Any new interrupts that happen after this, either while we're
+ 	 * in this tasklet, or later, will show up in next ISR/tasklet. */
+-	inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
+-	iwl4965_write32(priv, CSR_FH_INT_STATUS, inta_fh);
++	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
++	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
+-	if (iwl4965_debug_level & IWL_DL_ISR) {
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & IWL_DL_ISR) {
+ 		/* just for debug */
+-		inta_mask = iwl4965_read32(priv, CSR_INT_MASK);
++		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+ 		IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+ 			      inta, inta_mask, inta_fh);
+ 	}
+@@ -5120,9 +4368,9 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ 	 * atomic, make sure that inta covers all the interrupts that
+ 	 * we've discovered, even if FH interrupt came in just after
+ 	 * reading CSR_INT. */
+-	if (inta_fh & CSR_FH_INT_RX_MASK)
++	if (inta_fh & CSR49_FH_INT_RX_MASK)
+ 		inta |= CSR_INT_BIT_FH_RX;
+-	if (inta_fh & CSR_FH_INT_TX_MASK)
++	if (inta_fh & CSR49_FH_INT_TX_MASK)
+ 		inta |= CSR_INT_BIT_FH_TX;
+ 
+ 	/* Now service all interrupt bits discovered above. */
+@@ -5141,8 +4389,8 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ 		return;
+ 	}
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
+-	if (iwl4965_debug_level & (IWL_DL_ISR)) {
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & (IWL_DL_ISR)) {
+ 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
+ 		if (inta & CSR_INT_BIT_SCD)
+ 			IWL_DEBUG_ISR("Scheduler finished to transmit "
+@@ -5159,7 +4407,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ 	/* HW RF KILL switch toggled */
+ 	if (inta & CSR_INT_BIT_RF_KILL) {
+ 		int hw_rf_kill = 0;
+-		if (!(iwl4965_read32(priv, CSR_GP_CNTRL) &
++		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+ 				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+ 			hw_rf_kill = 1;
+ 
+@@ -5170,7 +4418,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ 		/* Queue restart only if RF_KILL switch was set to "kill"
+ 		 *   when we loaded driver, and is now set to "enable".
+ 		 * After we're Alive, RF_KILL gets handled by
+-		 *   iwl_rx_card_state_notif() */
++		 *   iwl4965_rx_card_state_notif() */
+ 		if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
+ 			clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ 			queue_work(priv->workqueue, &priv->restart);
+@@ -5230,13 +4478,15 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ 	}
+ 
+ 	/* Re-enable all interrupts */
+-	iwl4965_enable_interrupts(priv);
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-	if (iwl4965_debug_level & (IWL_DL_ISR)) {
+-		inta = iwl4965_read32(priv, CSR_INT);
+-		inta_mask = iwl4965_read32(priv, CSR_INT_MASK);
+-		inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
++	/* only Re-enable if diabled by irq */
++	if (test_bit(STATUS_INT_ENABLED, &priv->status))
++		iwl4965_enable_interrupts(priv);
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	if (iwl_debug_level & (IWL_DL_ISR)) {
++		inta = iwl_read32(priv, CSR_INT);
++		inta_mask = iwl_read32(priv, CSR_INT_MASK);
++		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+ 		IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
+ 			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
+ 	}
+@@ -5246,7 +4496,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ 
+ static irqreturn_t iwl4965_isr(int irq, void *data)
+ {
+-	struct iwl4965_priv *priv = data;
++	struct iwl_priv *priv = data;
+ 	u32 inta, inta_mask;
+ 	u32 inta_fh;
+ 	if (!priv)
+@@ -5258,12 +4508,12 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
+ 	 *    back-to-back ISRs and sporadic interrupts from our NIC.
+ 	 * If we have something to service, the tasklet will re-enable ints.
+ 	 * If we *don't* have something, we'll re-enable before leaving here. */
+-	inta_mask = iwl4965_read32(priv, CSR_INT_MASK);  /* just for debug */
+-	iwl4965_write32(priv, CSR_INT_MASK, 0x00000000);
++	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
++	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+ 
+ 	/* Discover which interrupts are active/pending */
+-	inta = iwl4965_read32(priv, CSR_INT);
+-	inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
++	inta = iwl_read32(priv, CSR_INT);
++	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+ 
+ 	/* Ignore interrupt if there's nothing in NIC to service.
+ 	 * This may be due to IRQ shared with another device,
+@@ -5295,313 +4545,13 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
+ 
+  none:
+ 	/* re-enable interrupts here since we don't have anything to service. */
+-	iwl4965_enable_interrupts(priv);
++	/* only Re-enable if diabled by irq */
++	if (test_bit(STATUS_INT_ENABLED, &priv->status))
++		iwl4965_enable_interrupts(priv);
+ 	spin_unlock(&priv->lock);
+ 	return IRQ_NONE;
+ }
+ 
+-/************************** EEPROM BANDS ****************************
+- *
+- * The iwl4965_eeprom_band definitions below provide the mapping from the
+- * EEPROM contents to the specific channel number supported for each
+- * band.
+- *
+- * For example, iwl4965_priv->eeprom.band_3_channels[4] from the band_3
+- * definition below maps to physical channel 42 in the 5.2GHz spectrum.
+- * The specific geography and calibration information for that channel
+- * is contained in the eeprom map itself.
+- *
+- * During init, we copy the eeprom information and channel map
+- * information into priv->channel_info_24/52 and priv->channel_map_24/52
+- *
+- * channel_map_24/52 provides the index in the channel_info array for a
+- * given channel.  We have to have two separate maps as there is channel
+- * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
+- * band_2
+- *
+- * A value of 0xff stored in the channel_map indicates that the channel
+- * is not supported by the hardware at all.
+- *
+- * A value of 0xfe in the channel_map indicates that the channel is not
+- * valid for Tx with the current hardware.  This means that
+- * while the system can tune and receive on a given channel, it may not
+- * be able to associate or transmit any frames on that
+- * channel.  There is no corresponding channel information for that
+- * entry.
+- *
+- *********************************************************************/
+-
+-/* 2.4 GHz */
+-static const u8 iwl4965_eeprom_band_1[14] = {
+-	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+-};
+-
+-/* 5.2 GHz bands */
+-static const u8 iwl4965_eeprom_band_2[] = {	/* 4915-5080MHz */
+-	183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
+-};
+-
+-static const u8 iwl4965_eeprom_band_3[] = {	/* 5170-5320MHz */
+-	34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+-};
+-
+-static const u8 iwl4965_eeprom_band_4[] = {	/* 5500-5700MHz */
+-	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+-};
+-
+-static const u8 iwl4965_eeprom_band_5[] = {	/* 5725-5825MHz */
+-	145, 149, 153, 157, 161, 165
+-};
+-
+-static u8 iwl4965_eeprom_band_6[] = {       /* 2.4 FAT channel */
+-	1, 2, 3, 4, 5, 6, 7
+-};
+-
+-static u8 iwl4965_eeprom_band_7[] = {       /* 5.2 FAT channel */
+-	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
+-};
+-
+-static void iwl4965_init_band_reference(const struct iwl4965_priv *priv,
+-				    int band,
+-				    int *eeprom_ch_count,
+-				    const struct iwl4965_eeprom_channel
+-				    **eeprom_ch_info,
+-				    const u8 **eeprom_ch_index)
+-{
+-	switch (band) {
+-	case 1:		/* 2.4GHz band */
+-		*eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_1);
+-		*eeprom_ch_info = priv->eeprom.band_1_channels;
+-		*eeprom_ch_index = iwl4965_eeprom_band_1;
+-		break;
+-	case 2:		/* 4.9GHz band */
+-		*eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_2);
+-		*eeprom_ch_info = priv->eeprom.band_2_channels;
+-		*eeprom_ch_index = iwl4965_eeprom_band_2;
+-		break;
+-	case 3:		/* 5.2GHz band */
+-		*eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_3);
+-		*eeprom_ch_info = priv->eeprom.band_3_channels;
+-		*eeprom_ch_index = iwl4965_eeprom_band_3;
+-		break;
+-	case 4:		/* 5.5GHz band */
+-		*eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_4);
+-		*eeprom_ch_info = priv->eeprom.band_4_channels;
+-		*eeprom_ch_index = iwl4965_eeprom_band_4;
+-		break;
+-	case 5:		/* 5.7GHz band */
+-		*eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_5);
+-		*eeprom_ch_info = priv->eeprom.band_5_channels;
+-		*eeprom_ch_index = iwl4965_eeprom_band_5;
+-		break;
+-	case 6:		/* 2.4GHz FAT channels */
+-		*eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_6);
+-		*eeprom_ch_info = priv->eeprom.band_24_channels;
+-		*eeprom_ch_index = iwl4965_eeprom_band_6;
+-		break;
+-	case 7:		/* 5 GHz FAT channels */
+-		*eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_7);
+-		*eeprom_ch_info = priv->eeprom.band_52_channels;
+-		*eeprom_ch_index = iwl4965_eeprom_band_7;
+-		break;
+-	default:
+-		BUG();
+-		return;
+-	}
+-}
+-
+-/**
+- * iwl4965_get_channel_info - Find driver's private channel info
+- *
+- * Based on band and channel number.
+- */
+-const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv,
+-						    int phymode, u16 channel)
+-{
+-	int i;
+-
+-	switch (phymode) {
+-	case MODE_IEEE80211A:
+-		for (i = 14; i < priv->channel_count; i++) {
+-			if (priv->channel_info[i].channel == channel)
+-				return &priv->channel_info[i];
+-		}
+-		break;
+-
+-	case MODE_IEEE80211B:
+-	case MODE_IEEE80211G:
+-		if (channel >= 1 && channel <= 14)
+-			return &priv->channel_info[channel - 1];
+-		break;
+-
+-	}
+-
+-	return NULL;
+-}
+-
+-#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
+-			    ? # x " " : "")
+-
+-/**
+- * iwl4965_init_channel_map - Set up driver's info for all possible channels
+- */
+-static int iwl4965_init_channel_map(struct iwl4965_priv *priv)
+-{
+-	int eeprom_ch_count = 0;
+-	const u8 *eeprom_ch_index = NULL;
+-	const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL;
+-	int band, ch;
+-	struct iwl4965_channel_info *ch_info;
+-
+-	if (priv->channel_count) {
+-		IWL_DEBUG_INFO("Channel map already initialized.\n");
+-		return 0;
+-	}
+-
+-	if (priv->eeprom.version < 0x2f) {
+-		IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
+-			    priv->eeprom.version);
+-		return -EINVAL;
+-	}
+-
+-	IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
+-
+-	priv->channel_count =
+-	    ARRAY_SIZE(iwl4965_eeprom_band_1) +
+-	    ARRAY_SIZE(iwl4965_eeprom_band_2) +
+-	    ARRAY_SIZE(iwl4965_eeprom_band_3) +
+-	    ARRAY_SIZE(iwl4965_eeprom_band_4) +
+-	    ARRAY_SIZE(iwl4965_eeprom_band_5);
+-
+-	IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
+-
+-	priv->channel_info = kzalloc(sizeof(struct iwl4965_channel_info) *
+-				     priv->channel_count, GFP_KERNEL);
+-	if (!priv->channel_info) {
+-		IWL_ERROR("Could not allocate channel_info\n");
+-		priv->channel_count = 0;
+-		return -ENOMEM;
+-	}
+-
+-	ch_info = priv->channel_info;
+-
+-	/* Loop through the 5 EEPROM bands adding them in order to the
+-	 * channel map we maintain (that contains additional information than
+-	 * what just in the EEPROM) */
+-	for (band = 1; band <= 5; band++) {
+-
+-		iwl4965_init_band_reference(priv, band, &eeprom_ch_count,
+-					&eeprom_ch_info, &eeprom_ch_index);
+-
+-		/* Loop through each band adding each of the channels */
+-		for (ch = 0; ch < eeprom_ch_count; ch++) {
+-			ch_info->channel = eeprom_ch_index[ch];
+-			ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
+-			    MODE_IEEE80211A;
+-
+-			/* permanently store EEPROM's channel regulatory flags
+-			 *   and max power in channel info database. */
+-			ch_info->eeprom = eeprom_ch_info[ch];
+-
+-			/* Copy the run-time flags so they are there even on
+-			 * invalid channels */
+-			ch_info->flags = eeprom_ch_info[ch].flags;
+-
+-			if (!(is_channel_valid(ch_info))) {
+-				IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
+-					       "No traffic\n",
+-					       ch_info->channel,
+-					       ch_info->flags,
+-					       is_channel_a_band(ch_info) ?
+-					       "5.2" : "2.4");
+-				ch_info++;
+-				continue;
+-			}
+-
+-			/* Initialize regulatory-based run-time data */
+-			ch_info->max_power_avg = ch_info->curr_txpow =
+-			    eeprom_ch_info[ch].max_power_avg;
+-			ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
+-			ch_info->min_power = 0;
+-
+-			IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
+-				       " %ddBm): Ad-Hoc %ssupported\n",
+-				       ch_info->channel,
+-				       is_channel_a_band(ch_info) ?
+-				       "5.2" : "2.4",
+-				       CHECK_AND_PRINT(IBSS),
+-				       CHECK_AND_PRINT(ACTIVE),
+-				       CHECK_AND_PRINT(RADAR),
+-				       CHECK_AND_PRINT(WIDE),
+-				       CHECK_AND_PRINT(NARROW),
+-				       CHECK_AND_PRINT(DFS),
+-				       eeprom_ch_info[ch].flags,
+-				       eeprom_ch_info[ch].max_power_avg,
+-				       ((eeprom_ch_info[ch].
+-					 flags & EEPROM_CHANNEL_IBSS)
+-					&& !(eeprom_ch_info[ch].
+-					     flags & EEPROM_CHANNEL_RADAR))
+-				       ? "" : "not ");
+-
+-			/* Set the user_txpower_limit to the highest power
+-			 * supported by any channel */
+-			if (eeprom_ch_info[ch].max_power_avg >
+-			    priv->user_txpower_limit)
+-				priv->user_txpower_limit =
+-				    eeprom_ch_info[ch].max_power_avg;
+-
+-			ch_info++;
+-		}
+-	}
+-
+-	/* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
+-	for (band = 6; band <= 7; band++) {
+-		int phymode;
+-		u8 fat_extension_chan;
+-
+-		iwl4965_init_band_reference(priv, band, &eeprom_ch_count,
+-					&eeprom_ch_info, &eeprom_ch_index);
+-
+-		/* EEPROM band 6 is 2.4, band 7 is 5 GHz */
+-		phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A;
+-
+-		/* Loop through each band adding each of the channels */
+-		for (ch = 0; ch < eeprom_ch_count; ch++) {
+-
+-			if ((band == 6) &&
+-			    ((eeprom_ch_index[ch] == 5) ||
+-			    (eeprom_ch_index[ch] == 6) ||
+-			    (eeprom_ch_index[ch] == 7)))
+-			       fat_extension_chan = HT_IE_EXT_CHANNEL_MAX;
+-			else
+-				fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
+-
+-			/* Set up driver's info for lower half */
+-			iwl4965_set_fat_chan_info(priv, phymode,
+-						  eeprom_ch_index[ch],
+-						  &(eeprom_ch_info[ch]),
+-						  fat_extension_chan);
+-
+-			/* Set up driver's info for upper half */
+-			iwl4965_set_fat_chan_info(priv, phymode,
+-						  (eeprom_ch_index[ch] + 4),
+-						  &(eeprom_ch_info[ch]),
+-						  HT_IE_EXT_CHANNEL_BELOW);
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-/*
+- * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map
+- */
+-static void iwl4965_free_channel_map(struct iwl4965_priv *priv)
+-{
+-	kfree(priv->channel_info);
+-	priv->channel_count = 0;
+-}
+-
+ /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
+  * sending probe req.  This should be set long enough to hear probe responses
+  * from more than one AP.  */
+@@ -5625,22 +4575,24 @@ static void iwl4965_free_channel_map(struct iwl4965_priv *priv)
+ #define IWL_PASSIVE_DWELL_BASE      (100)
+ #define IWL_CHANNEL_TUNE_TIME       5
+ 
+-static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, int phymode)
++static inline u16 iwl4965_get_active_dwell_time(struct iwl_priv *priv,
++						enum ieee80211_band band)
+ {
+-	if (phymode == MODE_IEEE80211A)
++	if (band == IEEE80211_BAND_5GHZ)
+ 		return IWL_ACTIVE_DWELL_TIME_52;
+ 	else
+ 		return IWL_ACTIVE_DWELL_TIME_24;
+ }
+ 
+-static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode)
++static u16 iwl4965_get_passive_dwell_time(struct iwl_priv *priv,
++					  enum ieee80211_band band)
+ {
+-	u16 active = iwl4965_get_active_dwell_time(priv, phymode);
+-	u16 passive = (phymode != MODE_IEEE80211A) ?
++	u16 active = iwl4965_get_active_dwell_time(priv, band);
++	u16 passive = (band != IEEE80211_BAND_5GHZ) ?
+ 	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
+ 	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
+ 
+-	if (iwl4965_is_associated(priv)) {
++	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) */
+@@ -5656,30 +4608,34 @@ static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode
+ 	return passive;
+ }
+ 
+-static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
++static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
++					 enum ieee80211_band band,
+ 				     u8 is_active, u8 direct_mask,
+ 				     struct iwl4965_scan_channel *scan_ch)
+ {
+ 	const struct ieee80211_channel *channels = NULL;
+-	const struct ieee80211_hw_mode *hw_mode;
+-	const struct iwl4965_channel_info *ch_info;
++	const struct ieee80211_supported_band *sband;
++	const struct iwl_channel_info *ch_info;
+ 	u16 passive_dwell = 0;
+ 	u16 active_dwell = 0;
+ 	int added, i;
+ 
+-	hw_mode = iwl4965_get_hw_mode(priv, phymode);
+-	if (!hw_mode)
++	sband = iwl4965_get_hw_mode(priv, band);
++	if (!sband)
+ 		return 0;
+ 
+-	channels = hw_mode->channels;
++	channels = sband->channels;
++
++	active_dwell = iwl4965_get_active_dwell_time(priv, band);
++	passive_dwell = iwl4965_get_passive_dwell_time(priv, band);
+ 
+-	active_dwell = iwl4965_get_active_dwell_time(priv, phymode);
+-	passive_dwell = iwl4965_get_passive_dwell_time(priv, phymode);
++	for (i = 0, added = 0; i < sband->n_channels; i++) {
++		if (channels[i].flags & IEEE80211_CHAN_DISABLED)
++			continue;
+ 
+-	for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
+-		if (channels[i].chan ==
++		if (ieee80211_frequency_to_channel(channels[i].center_freq) ==
+ 		    le16_to_cpu(priv->active_rxon.channel)) {
+-			if (iwl4965_is_associated(priv)) {
++			if (iwl_is_associated(priv)) {
+ 				IWL_DEBUG_SCAN
+ 				    ("Skipping current channel %d\n",
+ 				     le16_to_cpu(priv->active_rxon.channel));
+@@ -5688,9 +4644,9 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
+ 		} else if (priv->only_active_channel)
+ 			continue;
+ 
+-		scan_ch->channel = channels[i].chan;
++		scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq);
+ 
+-		ch_info = iwl4965_get_channel_info(priv, phymode,
++		ch_info = iwl_get_channel_info(priv, band,
+ 					 scan_ch->channel);
+ 		if (!is_channel_valid(ch_info)) {
+ 			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
+@@ -5699,7 +4655,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
+ 		}
+ 
+ 		if (!is_active || is_channel_passive(ch_info) ||
+-		    !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
++		    (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
+ 			scan_ch->type = 0;	/* passive */
+ 		else
+ 			scan_ch->type = 1;	/* active */
+@@ -5718,7 +4674,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
+ 		/* scan_pwr_info->tpc.dsp_atten; */
+ 
+ 		/*scan_pwr_info->tpc.tx_gain; */
+-		if (phymode == MODE_IEEE80211A)
++		if (band == IEEE80211_BAND_5GHZ)
+ 			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+ 		else {
+ 			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+@@ -5742,194 +4698,148 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
+ 	return added;
+ }
+ 
+-static void iwl4965_reset_channel_flag(struct iwl4965_priv *priv)
+-{
+-	int i, j;
+-	for (i = 0; i < 3; i++) {
+-		struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
+-		for (j = 0; j < hw_mode->num_channels; j++)
+-			hw_mode->channels[j].flag = hw_mode->channels[j].val;
+-	}
+-}
+-
+-static void iwl4965_init_hw_rates(struct iwl4965_priv *priv,
++static void iwl4965_init_hw_rates(struct iwl_priv *priv,
+ 			      struct ieee80211_rate *rates)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < IWL_RATE_COUNT; i++) {
+-		rates[i].rate = iwl4965_rates[i].ieee * 5;
+-		rates[i].val = i; /* Rate scaling will work on indexes */
+-		rates[i].val2 = i;
+-		rates[i].flags = IEEE80211_RATE_SUPPORTED;
+-		/* Only OFDM have the bits-per-symbol set */
+-		if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
+-			rates[i].flags |= IEEE80211_RATE_OFDM;
+-		else {
++		rates[i].bitrate = iwl4965_rates[i].ieee * 5;
++		rates[i].hw_value = i; /* Rate scaling will work on indexes */
++		rates[i].hw_value_short = i;
++		rates[i].flags = 0;
++		if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
+ 			/*
+-			 * If CCK 1M then set rate flag to CCK else CCK_2
+-			 * which is CCK | PREAMBLE2
++			 * If CCK != 1M then set short preamble rate flag.
+ 			 */
+-			rates[i].flags |= (iwl4965_rates[i].plcp == 10) ?
+-				IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
++			rates[i].flags |=
++				(iwl4965_rates[i].plcp == IWL_RATE_1M_PLCP) ?
++					0 : IEEE80211_RATE_SHORT_PREAMBLE;
+ 		}
+-
+-		/* Set up which ones are basic rates... */
+-		if (IWL_BASIC_RATES_MASK & (1 << i))
+-			rates[i].flags |= IEEE80211_RATE_BASIC;
+ 	}
+ }
+ 
+ /**
+  * iwl4965_init_geos - Initialize mac80211's geo/channel info based from eeprom
+  */
+-static int iwl4965_init_geos(struct iwl4965_priv *priv)
++int iwl4965_init_geos(struct iwl_priv *priv)
+ {
+-	struct iwl4965_channel_info *ch;
+-	struct ieee80211_hw_mode *modes;
++	struct iwl_channel_info *ch;
++	struct ieee80211_supported_band *sband;
+ 	struct ieee80211_channel *channels;
+ 	struct ieee80211_channel *geo_ch;
+ 	struct ieee80211_rate *rates;
+ 	int i = 0;
+-	enum {
+-		A = 0,
+-		B = 1,
+-		G = 2,
+-	};
+-	int mode_count = 3;
+ 
+-	if (priv->modes) {
++	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
++	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
+ 		IWL_DEBUG_INFO("Geography modes already initialized.\n");
+ 		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+ 		return 0;
+ 	}
+ 
+-	modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
+-			GFP_KERNEL);
+-	if (!modes)
+-		return -ENOMEM;
+-
+ 	channels = kzalloc(sizeof(struct ieee80211_channel) *
+ 			   priv->channel_count, GFP_KERNEL);
+-	if (!channels) {
+-		kfree(modes);
++	if (!channels)
+ 		return -ENOMEM;
+-	}
+ 
+-	rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
++	rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)),
+ 			GFP_KERNEL);
+ 	if (!rates) {
+-		kfree(modes);
+ 		kfree(channels);
+ 		return -ENOMEM;
+ 	}
+ 
+-	/* 0 = 802.11a
+-	 * 1 = 802.11b
+-	 * 2 = 802.11g
+-	 */
+-
+ 	/* 5.2GHz channels start after the 2.4GHz channels */
+-	modes[A].mode = MODE_IEEE80211A;
+-	modes[A].channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)];
+-	modes[A].rates = rates;
+-	modes[A].num_rates = 8;	/* just OFDM */
+-	modes[A].rates = &rates[4];
+-	modes[A].num_channels = 0;
+-#ifdef CONFIG_IWL4965_HT
+-	iwl4965_init_ht_hw_capab(&modes[A].ht_info, MODE_IEEE80211A);
+-#endif
++	sband = &priv->bands[IEEE80211_BAND_5GHZ];
++	sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
++	/* just OFDM */
++	sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
++	sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
+ 
+-	modes[B].mode = MODE_IEEE80211B;
+-	modes[B].channels = channels;
+-	modes[B].rates = rates;
+-	modes[B].num_rates = 4;	/* just CCK */
+-	modes[B].num_channels = 0;
+-
+-	modes[G].mode = MODE_IEEE80211G;
+-	modes[G].channels = channels;
+-	modes[G].rates = rates;
+-	modes[G].num_rates = 12;	/* OFDM & CCK */
+-	modes[G].num_channels = 0;
+-#ifdef CONFIG_IWL4965_HT
+-	iwl4965_init_ht_hw_capab(&modes[G].ht_info, MODE_IEEE80211G);
+-#endif
++	iwl4965_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_5GHZ);
++
++	sband = &priv->bands[IEEE80211_BAND_2GHZ];
++	sband->channels = channels;
++	/* OFDM & CCK */
++	sband->bitrates = rates;
++	sband->n_bitrates = IWL_RATE_COUNT;
++
++	iwl4965_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_2GHZ);
+ 
+ 	priv->ieee_channels = channels;
+ 	priv->ieee_rates = rates;
+ 
+ 	iwl4965_init_hw_rates(priv, rates);
+ 
+-	for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
++	for (i = 0;  i < priv->channel_count; i++) {
+ 		ch = &priv->channel_info[i];
+ 
+-		if (!is_channel_valid(ch)) {
+-			IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- "
+-				    "skipping.\n",
+-				    ch->channel, is_channel_a_band(ch) ?
+-				    "5.2" : "2.4");
++		/* FIXME: might be removed if scan is OK */
++		if (!is_channel_valid(ch))
+ 			continue;
+-		}
+ 
+-		if (is_channel_a_band(ch)) {
+-			geo_ch = &modes[A].channels[modes[A].num_channels++];
+-		} else {
+-			geo_ch = &modes[B].channels[modes[B].num_channels++];
+-			modes[G].num_channels++;
+-		}
++		if (is_channel_a_band(ch))
++			sband =  &priv->bands[IEEE80211_BAND_5GHZ];
++		else
++			sband =  &priv->bands[IEEE80211_BAND_2GHZ];
+ 
+-		geo_ch->freq = ieee80211chan2mhz(ch->channel);
+-		geo_ch->chan = ch->channel;
+-		geo_ch->power_level = ch->max_power_avg;
+-		geo_ch->antenna_max = 0xff;
++		geo_ch = &sband->channels[sband->n_channels++];
++
++		geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel);
++		geo_ch->max_power = ch->max_power_avg;
++		geo_ch->max_antenna_gain = 0xff;
++		geo_ch->hw_value = ch->channel;
+ 
+ 		if (is_channel_valid(ch)) {
+-			geo_ch->flag = IEEE80211_CHAN_W_SCAN;
+-			if (ch->flags & EEPROM_CHANNEL_IBSS)
+-				geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
++			if (!(ch->flags & EEPROM_CHANNEL_IBSS))
++				geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
+ 
+-			if (ch->flags & EEPROM_CHANNEL_ACTIVE)
+-				geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
++			if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
++				geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+ 
+ 			if (ch->flags & EEPROM_CHANNEL_RADAR)
+-				geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
++				geo_ch->flags |= IEEE80211_CHAN_RADAR;
+ 
+ 			if (ch->max_power_avg > priv->max_channel_txpower_limit)
+ 				priv->max_channel_txpower_limit =
+ 				    ch->max_power_avg;
++		} else {
++			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
+ 		}
+ 
+-		geo_ch->val = geo_ch->flag;
++		/* Save flags for reg domain usage */
++		geo_ch->orig_flags = geo_ch->flags;
++
++		IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n",
++				ch->channel, geo_ch->center_freq,
++				is_channel_a_band(ch) ?  "5.2" : "2.4",
++				geo_ch->flags & IEEE80211_CHAN_DISABLED ?
++				"restricted" : "valid",
++				 geo_ch->flags);
+ 	}
+ 
+-	if ((modes[A].num_channels == 0) && priv->is_abg) {
++	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
++	     priv->cfg->sku & IWL_SKU_A) {
+ 		printk(KERN_INFO DRV_NAME
+ 		       ": Incorrectly detected BG card as ABG.  Please send "
+ 		       "your PCI ID 0x%04X:0x%04X to maintainer.\n",
+ 		       priv->pci_dev->device, priv->pci_dev->subsystem_device);
+-		priv->is_abg = 0;
++		priv->cfg->sku &= ~IWL_SKU_A;
+ 	}
+ 
+ 	printk(KERN_INFO DRV_NAME
+ 	       ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
+-	       modes[G].num_channels, modes[A].num_channels);
++	       priv->bands[IEEE80211_BAND_2GHZ].n_channels,
++	       priv->bands[IEEE80211_BAND_5GHZ].n_channels);
+ 
+-	/*
+-	 * NOTE:  We register these in preference of order -- the
+-	 * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
+-	 * a phymode based on rates or AP capabilities but seems to
+-	 * configure it purely on if the channel being configured
+-	 * is supported by a mode -- and the first match is taken
+-	 */
++	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
++		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++			&priv->bands[IEEE80211_BAND_2GHZ];
++	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
++		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
++			&priv->bands[IEEE80211_BAND_5GHZ];
+ 
+-	if (modes[G].num_channels)
+-		ieee80211_register_hwmode(priv->hw, &modes[G]);
+-	if (modes[B].num_channels)
+-		ieee80211_register_hwmode(priv->hw, &modes[B]);
+-	if (modes[A].num_channels)
+-		ieee80211_register_hwmode(priv->hw, &modes[A]);
+-
+-	priv->modes = modes;
+ 	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+ 
+ 	return 0;
+@@ -5938,9 +4848,8 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv)
+ /*
+  * iwl4965_free_geos - undo allocations in iwl4965_init_geos
+  */
+-static void iwl4965_free_geos(struct iwl4965_priv *priv)
++void iwl4965_free_geos(struct iwl_priv *priv)
+ {
+-	kfree(priv->modes);
+ 	kfree(priv->ieee_channels);
+ 	kfree(priv->ieee_rates);
+ 	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+@@ -5952,7 +4861,7 @@ static void iwl4965_free_geos(struct iwl4965_priv *priv)
+  *
+  ******************************************************************************/
+ 
+-static void iwl4965_dealloc_ucode_pci(struct iwl4965_priv *priv)
++static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
+ {
+ 	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
+ 	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
+@@ -5966,7 +4875,7 @@ static void iwl4965_dealloc_ucode_pci(struct iwl4965_priv *priv)
+  * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host,
+  *     looking at all data.
+  */
+-static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
++static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image,
+ 				 u32 len)
+ {
+ 	u32 val;
+@@ -5976,18 +4885,18 @@ static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
+ 
+ 	IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
+ 
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc)
+ 		return rc;
+ 
+-	iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
++	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
+ 
+ 	errcnt = 0;
+ 	for (; len > 0; len -= sizeof(u32), image++) {
+ 		/* read data comes through single port, auto-incr addr */
+ 		/* NOTE: Use the debugless read so we don't flood kernel log
+ 		 * if IWL_DL_IO is set */
+-		val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
++		val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+ 		if (val != le32_to_cpu(*image)) {
+ 			IWL_ERROR("uCode INST section is invalid at "
+ 				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
+@@ -5999,7 +4908,7 @@ static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
+ 		}
+ 	}
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 
+ 	if (!errcnt)
+ 		IWL_DEBUG_INFO
+@@ -6014,7 +4923,7 @@ static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
+  *   using sample data 100 bytes apart.  If these sample points are good,
+  *   it's a pretty good bet that everything between them is good, too.
+  */
+-static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image, u32 len)
++static int iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
+ {
+ 	u32 val;
+ 	int rc = 0;
+@@ -6023,7 +4932,7 @@ static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image,
+ 
+ 	IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
+ 
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc)
+ 		return rc;
+ 
+@@ -6031,9 +4940,9 @@ static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image,
+ 		/* read data comes through single port, auto-incr addr */
+ 		/* NOTE: Use the debugless read so we don't flood kernel log
+ 		 * if IWL_DL_IO is set */
+-		iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR,
++		iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+ 			i + RTC_INST_LOWER_BOUND);
+-		val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
++		val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+ 		if (val != le32_to_cpu(*image)) {
+ #if 0 /* Enable this if you want to see details */
+ 			IWL_ERROR("uCode INST section is invalid at "
+@@ -6047,7 +4956,7 @@ static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image,
+ 		}
+ 	}
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 
+ 	return rc;
+ }
+@@ -6057,7 +4966,7 @@ static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image,
+  * iwl4965_verify_ucode - determine which instruction image is in SRAM,
+  *    and verify its contents
+  */
+-static int iwl4965_verify_ucode(struct iwl4965_priv *priv)
++static int iwl4965_verify_ucode(struct iwl_priv *priv)
+ {
+ 	__le32 *image;
+ 	u32 len;
+@@ -6102,160 +5011,10 @@ static int iwl4965_verify_ucode(struct iwl4965_priv *priv)
+ 	return rc;
+ }
+ 
+-
+-/* check contents of special bootstrap uCode SRAM */
+-static int iwl4965_verify_bsm(struct iwl4965_priv *priv)
+-{
+-	__le32 *image = priv->ucode_boot.v_addr;
+-	u32 len = priv->ucode_boot.len;
+-	u32 reg;
+-	u32 val;
+-
+-	IWL_DEBUG_INFO("Begin verify bsm\n");
+-
+-	/* verify BSM SRAM contents */
+-	val = iwl4965_read_prph(priv, BSM_WR_DWCOUNT_REG);
+-	for (reg = BSM_SRAM_LOWER_BOUND;
+-	     reg < BSM_SRAM_LOWER_BOUND + len;
+-	     reg += sizeof(u32), image ++) {
+-		val = iwl4965_read_prph(priv, reg);
+-		if (val != le32_to_cpu(*image)) {
+-			IWL_ERROR("BSM uCode verification failed at "
+-				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
+-				  BSM_SRAM_LOWER_BOUND,
+-				  reg - BSM_SRAM_LOWER_BOUND, len,
+-				  val, le32_to_cpu(*image));
+-			return -EIO;
+-		}
+-	}
+-
+-	IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
+-
+-	return 0;
+-}
+-
+-/**
+- * iwl4965_load_bsm - Load bootstrap instructions
+- *
+- * BSM operation:
+- *
+- * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+- * in special SRAM that does not power down during RFKILL.  When powering back
+- * up after power-saving sleeps (or during initial uCode load), the BSM loads
+- * the bootstrap program into the on-board processor, and starts it.
+- *
+- * The bootstrap program loads (via DMA) instructions and data for a new
+- * program from host DRAM locations indicated by the host driver in the
+- * BSM_DRAM_* registers.  Once the new program is loaded, it starts
+- * automatically.
+- *
+- * When initializing the NIC, the host driver points the BSM to the
+- * "initialize" uCode image.  This uCode sets up some internal data, then
+- * notifies host via "initialize alive" that it is complete.
+- *
+- * The host then replaces the BSM_DRAM_* pointer values to point to the
+- * normal runtime uCode instructions and a backup uCode data cache buffer
+- * (filled initially with starting data values for the on-board processor),
+- * then triggers the "initialize" uCode to load and launch the runtime uCode,
+- * which begins normal operation.
+- *
+- * When doing a power-save shutdown, runtime uCode saves data SRAM into
+- * the backup data cache in DRAM before SRAM is powered down.
+- *
+- * When powering back up, the BSM loads the bootstrap program.  This reloads
+- * the runtime uCode instructions and the backup data cache into SRAM,
+- * and re-launches the runtime uCode from where it left off.
+- */
+-static int iwl4965_load_bsm(struct iwl4965_priv *priv)
+-{
+-	__le32 *image = priv->ucode_boot.v_addr;
+-	u32 len = priv->ucode_boot.len;
+-	dma_addr_t pinst;
+-	dma_addr_t pdata;
+-	u32 inst_len;
+-	u32 data_len;
+-	int rc;
+-	int i;
+-	u32 done;
+-	u32 reg_offset;
+-
+-	IWL_DEBUG_INFO("Begin load bsm\n");
+-
+-	/* make sure bootstrap program is no larger than BSM's SRAM size */
+-	if (len > IWL_MAX_BSM_SIZE)
+-		return -EINVAL;
+-
+-	/* Tell bootstrap uCode where to find the "Initialize" uCode
+-	 *   in host DRAM ... host DRAM physical address bits 35:4 for 4965.
+-	 * NOTE:  iwl4965_initialize_alive_start() will replace these values,
+-	 *        after the "initialize" uCode has run, to point to
+-	 *        runtime/protocol instructions and backup data cache. */
+-	pinst = priv->ucode_init.p_addr >> 4;
+-	pdata = priv->ucode_init_data.p_addr >> 4;
+-	inst_len = priv->ucode_init.len;
+-	data_len = priv->ucode_init_data.len;
+-
+-	rc = iwl4965_grab_nic_access(priv);
+-	if (rc)
+-		return rc;
+-
+-	iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+-	iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+-	iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+-	iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+-
+-	/* Fill BSM memory with bootstrap instructions */
+-	for (reg_offset = BSM_SRAM_LOWER_BOUND;
+-	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
+-	     reg_offset += sizeof(u32), image++)
+-		_iwl4965_write_prph(priv, reg_offset,
+-					  le32_to_cpu(*image));
+-
+-	rc = iwl4965_verify_bsm(priv);
+-	if (rc) {
+-		iwl4965_release_nic_access(priv);
+-		return rc;
+-	}
+-
+-	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+-	iwl4965_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+-	iwl4965_write_prph(priv, BSM_WR_MEM_DST_REG,
+-				 RTC_INST_LOWER_BOUND);
+-	iwl4965_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+-
+-	/* Load bootstrap code into instruction SRAM now,
+-	 *   to prepare to load "initialize" uCode */
+-	iwl4965_write_prph(priv, BSM_WR_CTRL_REG,
+-		BSM_WR_CTRL_REG_BIT_START);
+-
+-	/* Wait for load of bootstrap uCode to finish */
+-	for (i = 0; i < 100; i++) {
+-		done = iwl4965_read_prph(priv, BSM_WR_CTRL_REG);
+-		if (!(done & BSM_WR_CTRL_REG_BIT_START))
+-			break;
+-		udelay(10);
+-	}
+-	if (i < 100)
+-		IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
+-	else {
+-		IWL_ERROR("BSM write did not complete!\n");
+-		return -EIO;
+-	}
+-
+-	/* Enable future boot loads whenever power management unit triggers it
+-	 *   (e.g. when powering back up after power-save shutdown) */
+-	iwl4965_write_prph(priv, BSM_WR_CTRL_REG,
+-		BSM_WR_CTRL_REG_BIT_START_EN);
+-
+-	iwl4965_release_nic_access(priv);
+-
+-	return 0;
+-}
+-
+-static void iwl4965_nic_start(struct iwl4965_priv *priv)
++static void iwl4965_nic_start(struct iwl_priv *priv)
+ {
+ 	/* Remove all resets to allow NIC to operate */
+-	iwl4965_write32(priv, CSR_RESET, 0);
++	iwl_write32(priv, CSR_RESET, 0);
+ }
+ 
+ 
+@@ -6264,12 +5023,12 @@ static void iwl4965_nic_start(struct iwl4965_priv *priv)
+  *
+  * Copy into buffers for card to fetch via bus-mastering
+  */
+-static int iwl4965_read_ucode(struct iwl4965_priv *priv)
++static int iwl4965_read_ucode(struct iwl_priv *priv)
+ {
+ 	struct iwl4965_ucode *ucode;
+ 	int ret;
+ 	const struct firmware *ucode_raw;
+-	const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode";
++	const char *name = priv->cfg->fw_name;
+ 	u8 *src;
+ 	size_t len;
+ 	u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
+@@ -6465,7 +5224,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv)
+  * We need to replace them to load runtime uCode inst and data,
+  * and to save runtime data when powering down.
+  */
+-static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv)
++static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
+ {
+ 	dma_addr_t pinst;
+ 	dma_addr_t pdata;
+@@ -6477,24 +5236,24 @@ static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv)
+ 	pdata = priv->ucode_data_backup.p_addr >> 4;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	rc = iwl4965_grab_nic_access(priv);
++	rc = iwl_grab_nic_access(priv);
+ 	if (rc) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		return rc;
+ 	}
+ 
+ 	/* Tell bootstrap uCode where to find image to load */
+-	iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+-	iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+-	iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
++	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
++	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
++	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+ 				 priv->ucode_data.len);
+ 
+ 	/* Inst bytecount must be last to set up, bit 31 signals uCode
+ 	 *   that all new ptr/size info is in place */
+-	iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
++	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
+ 				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
+ 
+-	iwl4965_release_nic_access(priv);
++	iwl_release_nic_access(priv);
+ 
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+@@ -6514,7 +5273,7 @@ static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv)
+  *
+  * Tell "initialize" uCode to go ahead and load the runtime uCode.
+ */
+-static void iwl4965_init_alive_start(struct iwl4965_priv *priv)
++static void iwl4965_init_alive_start(struct iwl_priv *priv)
+ {
+ 	/* Check alive response for "valid" sign from uCode */
+ 	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
+@@ -6559,9 +5318,9 @@ static void iwl4965_init_alive_start(struct iwl4965_priv *priv)
+  *                   from protocol/runtime uCode (initialization uCode's
+  *                   Alive gets handled by iwl4965_init_alive_start()).
+  */
+-static void iwl4965_alive_start(struct iwl4965_priv *priv)
++static void iwl4965_alive_start(struct iwl_priv *priv)
+ {
+-	int rc = 0;
++	int ret = 0;
+ 
+ 	IWL_DEBUG_INFO("Runtime Alive received.\n");
+ 
+@@ -6582,12 +5341,12 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+ 		goto restart;
+ 	}
+ 
+-	iwl4965_clear_stations_table(priv);
++	iwlcore_clear_stations_table(priv);
+ 
+-	rc = iwl4965_alive_notify(priv);
+-	if (rc) {
++	ret = priv->cfg->ops->lib->alive_notify(priv);
++	if (ret) {
+ 		IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
+-			    rc);
++			    ret);
+ 		goto restart;
+ 	}
+ 
+@@ -6597,7 +5356,7 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+ 	/* Clear out the uCode error bit if it is set */
+ 	clear_bit(STATUS_FW_ERROR, &priv->status);
+ 
+-	if (iwl4965_is_rfkill(priv))
++	if (iwl_is_rfkill(priv))
+ 		return;
+ 
+ 	ieee80211_start_queues(priv->hw);
+@@ -6607,7 +5366,7 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+ 
+ 	iwl4965_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
+ 
+-	if (iwl4965_is_associated(priv)) {
++	if (iwl_is_associated(priv)) {
+ 		struct iwl4965_rxon_cmd *active_rxon =
+ 				(struct iwl4965_rxon_cmd *)(&priv->active_rxon);
+ 
+@@ -6631,6 +5390,8 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+ 
+ 	iwl4965_rf_kill_ct_config(priv);
+ 
++	iwl_leds_register(priv);
++
+ 	IWL_DEBUG_INFO("ALIVE processing complete.\n");
+ 	set_bit(STATUS_READY, &priv->status);
+ 	wake_up_interruptible(&priv->wait_command_queue);
+@@ -6638,15 +5399,17 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+ 	if (priv->error_recovering)
+ 		iwl4965_error_recovery(priv);
+ 
++	iwlcore_low_level_notify(priv, IWLCORE_START_EVT);
++	ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
+ 	return;
+ 
+  restart:
+ 	queue_work(priv->workqueue, &priv->restart);
+ }
+ 
+-static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv);
++static void iwl4965_cancel_deferred_work(struct iwl_priv *priv);
+ 
+-static void __iwl4965_down(struct iwl4965_priv *priv)
++static void __iwl4965_down(struct iwl_priv *priv)
+ {
+ 	unsigned long flags;
+ 	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
+@@ -6659,7 +5422,11 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ 	if (!exit_pending)
+ 		set_bit(STATUS_EXIT_PENDING, &priv->status);
+ 
+-	iwl4965_clear_stations_table(priv);
++	iwl_leds_unregister(priv);
++
++	iwlcore_low_level_notify(priv, IWLCORE_STOP_EVT);
++
++	iwlcore_clear_stations_table(priv);
+ 
+ 	/* Unblock any waiting calls */
+ 	wake_up_interruptible_all(&priv->wait_command_queue);
+@@ -6670,17 +5437,20 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ 		clear_bit(STATUS_EXIT_PENDING, &priv->status);
+ 
+ 	/* stop and reset the on-board processor */
+-	iwl4965_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
++	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+ 
+ 	/* tell the device to stop sending interrupts */
++	spin_lock_irqsave(&priv->lock, flags);
+ 	iwl4965_disable_interrupts(priv);
++	spin_unlock_irqrestore(&priv->lock, flags);
++	iwl_synchronize_irq(priv);
+ 
+ 	if (priv->mac80211_registered)
+ 		ieee80211_stop_queues(priv->hw);
+ 
+ 	/* If we have not previously called iwl4965_init() then
+ 	 * clear all bits but the RF Kill and SUSPEND bits and return */
+-	if (!iwl4965_is_init(priv)) {
++	if (!iwl_is_init(priv)) {
+ 		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
+ 					STATUS_RF_KILL_HW |
+ 			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
+@@ -6706,7 +5476,7 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ 				STATUS_FW_ERROR;
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	iwl4965_clear_bit(priv, CSR_GP_CNTRL,
++	iwl_clear_bit(priv, CSR_GP_CNTRL,
+ 			 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+@@ -6714,17 +5484,17 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ 	iwl4965_hw_rxq_stop(priv);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	if (!iwl4965_grab_nic_access(priv)) {
+-		iwl4965_write_prph(priv, APMG_CLK_DIS_REG,
++	if (!iwl_grab_nic_access(priv)) {
++		iwl_write_prph(priv, APMG_CLK_DIS_REG,
+ 					 APMG_CLK_VAL_DMA_CLK_RQT);
+-		iwl4965_release_nic_access(priv);
++		iwl_release_nic_access(priv);
+ 	}
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	udelay(5);
+ 
+ 	iwl4965_hw_nic_stop_master(priv);
+-	iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
++	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ 	iwl4965_hw_nic_reset(priv);
+ 
+  exit:
+@@ -6738,7 +5508,7 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ 	iwl4965_clear_free_frames(priv);
+ }
+ 
+-static void iwl4965_down(struct iwl4965_priv *priv)
++static void iwl4965_down(struct iwl_priv *priv)
+ {
+ 	mutex_lock(&priv->mutex);
+ 	__iwl4965_down(priv);
+@@ -6749,9 +5519,10 @@ static void iwl4965_down(struct iwl4965_priv *priv)
+ 
+ #define MAX_HW_RESTARTS 5
+ 
+-static int __iwl4965_up(struct iwl4965_priv *priv)
++static int __iwl4965_up(struct iwl_priv *priv)
+ {
+-	int rc, i;
++	int i;
++	int ret;
+ 
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+ 		IWL_WARNING("Exit pending; will not bring the NIC up\n");
+@@ -6761,6 +5532,7 @@ static int __iwl4965_up(struct iwl4965_priv *priv)
+ 	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
+ 		IWL_WARNING("Radio disabled by SW RF kill (module "
+ 			    "parameter)\n");
++		iwl_rfkill_set_hw_state(priv);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -6770,37 +5542,39 @@ static int __iwl4965_up(struct iwl4965_priv *priv)
+ 	}
+ 
+ 	/* If platform's RF_KILL switch is NOT set to KILL */
+-	if (iwl4965_read32(priv, CSR_GP_CNTRL) &
++	if (iwl_read32(priv, CSR_GP_CNTRL) &
+ 				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+ 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ 	else {
+ 		set_bit(STATUS_RF_KILL_HW, &priv->status);
+ 		if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
++			iwl_rfkill_set_hw_state(priv);
+ 			IWL_WARNING("Radio disabled by HW RF Kill switch\n");
+ 			return -ENODEV;
+ 		}
+ 	}
+ 
+-	iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF);
++	iwl_rfkill_set_hw_state(priv);
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+ 
+-	rc = iwl4965_hw_nic_init(priv);
+-	if (rc) {
+-		IWL_ERROR("Unable to int nic\n");
+-		return rc;
++	ret = priv->cfg->ops->lib->hw_nic_init(priv);
++	if (ret) {
++		IWL_ERROR("Unable to init nic\n");
++		return ret;
+ 	}
+ 
+ 	/* make sure rfkill handshake bits are cleared */
+-	iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+-	iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ 		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+ 
+ 	/* clear (again), then enable host interrupts */
+-	iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF);
++	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+ 	iwl4965_enable_interrupts(priv);
+ 
+ 	/* really make sure rfkill handshake bits are cleared */
+-	iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+-	iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ 
+ 	/* Copy original ucode data image from disk into backup cache.
+ 	 * This will be used to initialize the on-board processor's
+@@ -6814,15 +5588,15 @@ static int __iwl4965_up(struct iwl4965_priv *priv)
+ 
+ 	for (i = 0; i < MAX_HW_RESTARTS; i++) {
+ 
+-		iwl4965_clear_stations_table(priv);
++		iwlcore_clear_stations_table(priv);
+ 
+ 		/* load bootstrap state machine,
+ 		 * load bootstrap program into processor's memory,
+ 		 * prepare to load the "initialize" uCode */
+-		rc = iwl4965_load_bsm(priv);
++		ret = priv->cfg->ops->lib->load_ucode(priv);
+ 
+-		if (rc) {
+-			IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
++		if (ret) {
++			IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret);
+ 			continue;
+ 		}
+ 
+@@ -6852,8 +5626,8 @@ static int __iwl4965_up(struct iwl4965_priv *priv)
+ 
+ static void iwl4965_bg_init_alive_start(struct work_struct *data)
+ {
+-	struct iwl4965_priv *priv =
+-	    container_of(data, struct iwl4965_priv, init_alive_start.work);
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, init_alive_start.work);
+ 
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 		return;
+@@ -6865,8 +5639,8 @@ static void iwl4965_bg_init_alive_start(struct work_struct *data)
+ 
+ static void iwl4965_bg_alive_start(struct work_struct *data)
+ {
+-	struct iwl4965_priv *priv =
+-	    container_of(data, struct iwl4965_priv, alive_start.work);
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, alive_start.work);
+ 
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 		return;
+@@ -6878,7 +5652,7 @@ static void iwl4965_bg_alive_start(struct work_struct *data)
+ 
+ static void iwl4965_bg_rf_kill(struct work_struct *work)
+ {
+-	struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, rf_kill);
++	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
+ 
+ 	wake_up_interruptible(&priv->wait_command_queue);
+ 
+@@ -6887,13 +5661,16 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
+ 
+ 	mutex_lock(&priv->mutex);
+ 
+-	if (!iwl4965_is_rfkill(priv)) {
++	if (!iwl_is_rfkill(priv)) {
+ 		IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
+ 			  "HW and/or SW RF Kill no longer active, restarting "
+ 			  "device\n");
+ 		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 			queue_work(priv->workqueue, &priv->restart);
+ 	} else {
++		/* make sure mac80211 stop sending Tx frame */
++		if (priv->mac80211_registered)
++			ieee80211_stop_queues(priv->hw);
+ 
+ 		if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
+ 			IWL_DEBUG_RF_KILL("Can not turn radio back on - "
+@@ -6903,6 +5680,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
+ 				    "Kill switch must be turned off for "
+ 				    "wireless networking to work.\n");
+ 	}
++	iwl_rfkill_set_hw_state(priv);
++
+ 	mutex_unlock(&priv->mutex);
+ }
+ 
+@@ -6910,8 +5689,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
+ 
+ static void iwl4965_bg_scan_check(struct work_struct *data)
+ {
+-	struct iwl4965_priv *priv =
+-	    container_of(data, struct iwl4965_priv, scan_check.work);
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, scan_check.work);
+ 
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 		return;
+@@ -6931,24 +5710,25 @@ static void iwl4965_bg_scan_check(struct work_struct *data)
+ 
+ static void iwl4965_bg_request_scan(struct work_struct *data)
+ {
+-	struct iwl4965_priv *priv =
+-	    container_of(data, struct iwl4965_priv, request_scan);
+-	struct iwl4965_host_cmd cmd = {
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, request_scan);
++	struct iwl_host_cmd cmd = {
+ 		.id = REPLY_SCAN_CMD,
+ 		.len = sizeof(struct iwl4965_scan_cmd),
+ 		.meta.flags = CMD_SIZE_HUGE,
+ 	};
+-	int rc = 0;
+ 	struct iwl4965_scan_cmd *scan;
+ 	struct ieee80211_conf *conf = NULL;
++	u16 cmd_len;
++	enum ieee80211_band band;
+ 	u8 direct_mask;
+-	int phymode;
++	int ret = 0;
+ 
+ 	conf = ieee80211_get_hw_conf(priv->hw);
+ 
+ 	mutex_lock(&priv->mutex);
+ 
+-	if (!iwl4965_is_ready(priv)) {
++	if (!iwl_is_ready(priv)) {
+ 		IWL_WARNING("request scan called when driver not ready.\n");
+ 		goto done;
+ 	}
+@@ -6963,7 +5743,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+ 		IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. "
+ 			       "Ignoring second request.\n");
+-		rc = -EIO;
++		ret = -EIO;
+ 		goto done;
+ 	}
+ 
+@@ -6977,7 +5757,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 		goto done;
+ 	}
+ 
+-	if (iwl4965_is_rfkill(priv)) {
++	if (iwl_is_rfkill(priv)) {
+ 		IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
+ 		goto done;
+ 	}
+@@ -6996,7 +5776,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 		priv->scan = kmalloc(sizeof(struct iwl4965_scan_cmd) +
+ 				     IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+ 		if (!priv->scan) {
+-			rc = -ENOMEM;
++			ret = -ENOMEM;
+ 			goto done;
+ 		}
+ 	}
+@@ -7006,7 +5786,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
+ 	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
+ 
+-	if (iwl4965_is_associated(priv)) {
++	if (iwl_is_associated(priv)) {
+ 		u16 interval = 0;
+ 		u32 extra;
+ 		u32 suspend_time = 100;
+@@ -7043,26 +5823,19 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 		memcpy(scan->direct_scan[0].ssid,
+ 		       priv->direct_ssid, priv->direct_ssid_len);
+ 		direct_mask = 1;
+-	} else if (!iwl4965_is_associated(priv) && priv->essid_len) {
++	} else if (!iwl_is_associated(priv) && priv->essid_len) {
+ 		scan->direct_scan[0].id = WLAN_EID_SSID;
+ 		scan->direct_scan[0].len = priv->essid_len;
+ 		memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
+ 		direct_mask = 1;
+-	} else
++	} else {
+ 		direct_mask = 0;
++	}
+ 
+-	/* 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.len = cpu_to_le16(
+-		iwl4965_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
+-			IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
+ 	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+-	scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
++	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
+ 	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+ 
+-	/* flags + rate selection */
+-
+-	scan->tx_cmd.tx_flags |= cpu_to_le32(0x200);
+ 
+ 	switch (priv->scan_bands) {
+ 	case 2:
+@@ -7072,7 +5845,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 				RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
+ 
+ 		scan->good_CRC_th = 0;
+-		phymode = MODE_IEEE80211G;
++		band = IEEE80211_BAND_2GHZ;
+ 		break;
+ 
+ 	case 1:
+@@ -7080,7 +5853,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 				iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
+ 				RATE_MCS_ANT_B_MSK);
+ 		scan->good_CRC_th = IWL_GOOD_CRC_TH;
+-		phymode = MODE_IEEE80211A;
++		band = IEEE80211_BAND_5GHZ;
+ 		break;
+ 
+ 	default:
+@@ -7088,6 +5861,13 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 		goto done;
+ 	}
+ 
++	/* We don't build a direct scan probe request; the uCode will do
++	 * that based on the direct_mask added to each channel entry */
++	cmd_len = iwl4965_fill_probe_req(priv, band,
++					(struct ieee80211_mgmt *)scan->data,
++					IWL_MAX_SCAN_SIZE - sizeof(*scan), 0);
++
++	scan->tx_cmd.len = cpu_to_le16(cmd_len);
+ 	/* select Rx chains */
+ 
+ 	/* Force use of chains B and C (0x6) for scan Rx.
+@@ -7101,18 +5881,23 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
+ 		scan->filter_flags = RXON_FILTER_PROMISC_MSK;
+ 
+-	if (direct_mask)
++	if (direct_mask) {
+ 		IWL_DEBUG_SCAN
+ 		    ("Initiating direct scan for %s.\n",
+ 		     iwl4965_escape_essid(priv->essid, priv->essid_len));
+-	else
++		scan->channel_count =
++			iwl4965_get_channels_for_scan(
++				priv, band, 1, /* active */
++				direct_mask,
++				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++	} else {
+ 		IWL_DEBUG_SCAN("Initiating indirect scan.\n");
+-
+-	scan->channel_count =
+-		iwl4965_get_channels_for_scan(
+-			priv, phymode, 1, /* active */
+-			direct_mask,
+-			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++		scan->channel_count =
++			iwl4965_get_channels_for_scan(
++				priv, band, 0, /* passive */
++				direct_mask,
++				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++	}
+ 
+ 	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+ 	    scan->channel_count * sizeof(struct iwl4965_scan_channel);
+@@ -7120,8 +5905,8 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 	scan->len = cpu_to_le16(cmd.len);
+ 
+ 	set_bit(STATUS_SCAN_HW, &priv->status);
+-	rc = iwl4965_send_cmd_sync(priv, &cmd);
+-	if (rc)
++	ret = iwl_send_cmd_sync(priv, &cmd);
++	if (ret)
+ 		goto done;
+ 
+ 	queue_delayed_work(priv->workqueue, &priv->scan_check,
+@@ -7138,7 +5923,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ 
+ static void iwl4965_bg_up(struct work_struct *data)
+ {
+-	struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, up);
++	struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
+ 
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 		return;
+@@ -7150,7 +5935,7 @@ static void iwl4965_bg_up(struct work_struct *data)
+ 
+ static void iwl4965_bg_restart(struct work_struct *data)
+ {
+-	struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, restart);
++	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
+ 
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 		return;
+@@ -7161,8 +5946,8 @@ static void iwl4965_bg_restart(struct work_struct *data)
+ 
+ static void iwl4965_bg_rx_replenish(struct work_struct *data)
+ {
+-	struct iwl4965_priv *priv =
+-	    container_of(data, struct iwl4965_priv, rx_replenish);
++	struct iwl_priv *priv =
++	    container_of(data, struct iwl_priv, rx_replenish);
+ 
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 		return;
+@@ -7174,13 +5959,10 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data)
+ 
+ #define IWL_DELAY_NEXT_SCAN (HZ*2)
+ 
+-static void iwl4965_bg_post_associate(struct work_struct *data)
++static void iwl4965_post_associate(struct iwl_priv *priv)
+ {
+-	struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv,
+-					     post_associate.work);
+-
+-	int rc = 0;
+ 	struct ieee80211_conf *conf = NULL;
++	int ret = 0;
+ 	DECLARE_MAC_BUF(mac);
+ 
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+@@ -7196,12 +5978,10 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 		return;
+ 
+-	mutex_lock(&priv->mutex);
+ 
+-	if (!priv->vif || !priv->is_open) {
+-		mutex_unlock(&priv->mutex);
++	if (!priv->vif || !priv->is_open)
+ 		return;
+-	}
++
+ 	iwl4965_scan_cancel_timeout(priv, 200);
+ 
+ 	conf = ieee80211_get_hw_conf(priv->hw);
+@@ -7211,9 +5991,9 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
+ 
+ 	memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
+ 	iwl4965_setup_rxon_timing(priv);
+-	rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING,
++	ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+ 			      sizeof(priv->rxon_timing), &priv->rxon_timing);
+-	if (rc)
++	if (ret)
+ 		IWL_WARNING("REPLY_RXON_TIMING failed - "
+ 			    "Attempting to continue.\n");
+ 
+@@ -7255,7 +6035,7 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
+ 	case IEEE80211_IF_TYPE_IBSS:
+ 
+ 		/* clear out the station table */
+-		iwl4965_clear_stations_table(priv);
++		iwlcore_clear_stations_table(priv);
+ 
+ 		iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
+ 		iwl4965_rxon_add_station(priv, priv->bssid, 0);
+@@ -7281,19 +6061,29 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+ 		priv->assoc_station_added = 1;
+ 
+-#ifdef CONFIG_IWL4965_QOS
+ 	iwl4965_activate_qos(priv, 0);
+-#endif /* CONFIG_IWL4965_QOS */
++
+ 	/* we have just associated, don't start scan too early */
+ 	priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
++}
++
++
++static void iwl4965_bg_post_associate(struct work_struct *data)
++{
++	struct iwl_priv *priv = container_of(data, struct iwl_priv,
++					     post_associate.work);
++
++	mutex_lock(&priv->mutex);
++	iwl4965_post_associate(priv);
+ 	mutex_unlock(&priv->mutex);
++
+ }
+ 
+ static void iwl4965_bg_abort_scan(struct work_struct *work)
+ {
+-	struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, abort_scan);
++	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
+ 
+-	if (!iwl4965_is_ready(priv))
++	if (!iwl_is_ready(priv))
+ 		return;
+ 
+ 	mutex_lock(&priv->mutex);
+@@ -7308,8 +6098,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ 
+ static void iwl4965_bg_scan_completed(struct work_struct *work)
+ {
+-	struct iwl4965_priv *priv =
+-	    container_of(work, struct iwl4965_priv, scan_completed);
++	struct iwl_priv *priv =
++	    container_of(work, struct iwl_priv, scan_completed);
+ 
+ 	IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
+ 
+@@ -7338,7 +6128,7 @@ static void iwl4965_bg_scan_completed(struct work_struct *work)
+ 
+ static int iwl4965_mac_start(struct ieee80211_hw *hw)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	int ret;
+ 
+ 	IWL_DEBUG_MAC80211("enter\n");
+@@ -7415,7 +6205,7 @@ out_disable_msi:
+ 
+ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+@@ -7426,7 +6216,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
+ 
+ 	priv->is_open = 0;
+ 
+-	if (iwl4965_is_ready_rf(priv)) {
++	if (iwl_is_ready_rf(priv)) {
+ 		/* stop mac, cancel any scan request and clear
+ 		 * RXON_FILTER_ASSOC_MSK BIT
+ 		 */
+@@ -7450,7 +6240,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
+ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ 		      struct ieee80211_tx_control *ctl)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+@@ -7460,7 +6250,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ 	}
+ 
+ 	IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+-		     ctl->tx_rate);
++		     ctl->tx_rate->bitrate);
+ 
+ 	if (iwl4965_tx_skb(priv, skb, ctl))
+ 		dev_kfree_skb_any(skb);
+@@ -7472,7 +6262,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
+ 				 struct ieee80211_if_init_conf *conf)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	unsigned long flags;
+ 	DECLARE_MAC_BUF(mac);
+ 
+@@ -7495,7 +6285,7 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
+ 		memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
+ 	}
+ 
+-	if (iwl4965_is_ready(priv))
++	if (iwl_is_ready(priv))
+ 		iwl4965_set_mode(priv, conf->type);
+ 
+ 	mutex_unlock(&priv->mutex);
+@@ -7513,23 +6303,23 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
+  */
+ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
+-	const struct iwl4965_channel_info *ch_info;
++	struct iwl_priv *priv = hw->priv;
++	const struct iwl_channel_info *ch_info;
+ 	unsigned long flags;
+ 	int ret = 0;
+ 
+ 	mutex_lock(&priv->mutex);
+-	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
++	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
+ 
+ 	priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+ 
+-	if (!iwl4965_is_ready(priv)) {
++	if (!iwl_is_ready(priv)) {
+ 		IWL_DEBUG_MAC80211("leave - not ready\n");
+ 		ret = -EIO;
+ 		goto out;
+ 	}
+ 
+-	if (unlikely(!iwl4965_param_disable_hw_scan &&
++	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
+ 		     test_bit(STATUS_SCANNING, &priv->status))) {
+ 		IWL_DEBUG_MAC80211("leave - scanning\n");
+ 		set_bit(STATUS_CONF_PENDING, &priv->status);
+@@ -7539,10 +6329,9 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+-	ch_info = iwl4965_get_channel_info(priv, conf->phymode, conf->channel);
++	ch_info = iwl_get_channel_info(priv, conf->channel->band,
++			ieee80211_frequency_to_channel(conf->channel->center_freq));
+ 	if (!is_channel_valid(ch_info)) {
+-		IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
+-			       conf->channel, conf->phymode);
+ 		IWL_DEBUG_MAC80211("leave - invalid channel\n");
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		ret = -EINVAL;
+@@ -7550,10 +6339,10 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ 	}
+ 
+ #ifdef CONFIG_IWL4965_HT
+-	/* if we are switching fron ht to 2.4 clear flags
++	/* 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) != conf->channel)
++	if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel->hw_value)
+ #ifdef IEEE80211_CONF_CHANNEL_SWITCH
+ 	    && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH)
+ #endif
+@@ -7561,12 +6350,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ 		priv->staging_rxon.flags = 0;
+ #endif /* CONFIG_IWL4965_HT */
+ 
+-	iwl4965_set_rxon_channel(priv, conf->phymode, conf->channel);
++	iwlcore_set_rxon_channel(priv, conf->channel->band,
++		ieee80211_frequency_to_channel(conf->channel->center_freq));
+ 
+-	iwl4965_set_flags_for_phymode(priv, conf->phymode);
++	iwl4965_set_flags_for_phymode(priv, conf->channel->band);
+ 
+ 	/* The list of supported rates and rate mask can be different
+-	 * for each phymode; since the phymode may have changed, reset
++	 * for each band; since the band may have changed, reset
+ 	 * the rate mask to what mac80211 lists */
+ 	iwl4965_set_rate(priv);
+ 
+@@ -7579,14 +6369,15 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ 	}
+ #endif
+ 
+-	iwl4965_radio_kill_sw(priv, !conf->radio_enabled);
++	if (priv->cfg->ops->lib->radio_kill_sw)
++		priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled);
+ 
+ 	if (!conf->radio_enabled) {
+ 		IWL_DEBUG_MAC80211("leave - radio disabled\n");
+ 		goto out;
+ 	}
+ 
+-	if (iwl4965_is_rfkill(priv)) {
++	if (iwl_is_rfkill(priv)) {
+ 		IWL_DEBUG_MAC80211("leave - RF kill\n");
+ 		ret = -EIO;
+ 		goto out;
+@@ -7608,9 +6399,9 @@ out:
+ 	return ret;
+ }
+ 
+-static void iwl4965_config_ap(struct iwl4965_priv *priv)
++static void iwl4965_config_ap(struct iwl_priv *priv)
+ {
+-	int rc = 0;
++	int ret = 0;
+ 
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ 		return;
+@@ -7625,9 +6416,9 @@ static void iwl4965_config_ap(struct iwl4965_priv *priv)
+ 		/* RXON Timing */
+ 		memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
+ 		iwl4965_setup_rxon_timing(priv);
+-		rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING,
++		ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+ 				sizeof(priv->rxon_timing), &priv->rxon_timing);
+-		if (rc)
++		if (ret)
+ 			IWL_WARNING("REPLY_RXON_TIMING failed - "
+ 					"Attempting to continue.\n");
+ 
+@@ -7658,9 +6449,7 @@ static void iwl4965_config_ap(struct iwl4965_priv *priv)
+ 		/* restore RXON assoc */
+ 		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ 		iwl4965_commit_rxon(priv);
+-#ifdef CONFIG_IWL4965_QOS
+ 		iwl4965_activate_qos(priv, 1);
+-#endif
+ 		iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
+ 	}
+ 	iwl4965_send_beacon_cmd(priv);
+@@ -7674,7 +6463,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ 					struct ieee80211_vif *vif,
+ 				    struct ieee80211_if_conf *conf)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	DECLARE_MAC_BUF(mac);
+ 	unsigned long flags;
+ 	int rc;
+@@ -7682,6 +6471,11 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ 	if (conf == NULL)
+ 		return -EIO;
+ 
++	if (priv->vif != vif) {
++		IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
++		return 0;
++	}
++
+ 	if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
+ 	    (!conf->beacon || !conf->ssid_len)) {
+ 		IWL_DEBUG_MAC80211
+@@ -7689,7 +6483,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ 		return 0;
+ 	}
+ 
+-	if (!iwl4965_is_alive(priv))
++	if (!iwl_is_alive(priv))
+ 		return -EAGAIN;
+ 
+ 	mutex_lock(&priv->mutex);
+@@ -7704,17 +6498,6 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ 	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
+ 	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
+  */
+-	if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
+-		IWL_DEBUG_MAC80211("leave - scanning\n");
+-		mutex_unlock(&priv->mutex);
+-		return 0;
+-	}
+-
+-	if (priv->vif != vif) {
+-		IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
+-		mutex_unlock(&priv->mutex);
+-		return 0;
+-	}
+ 
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ 		if (!conf->bssid) {
+@@ -7729,7 +6512,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ 		priv->ibss_beacon = conf->beacon;
+ 	}
+ 
+-	if (iwl4965_is_rfkill(priv))
++	if (iwl_is_rfkill(priv))
+ 		goto done;
+ 
+ 	if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
+@@ -7797,13 +6580,13 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw,
+ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
+ 				     struct ieee80211_if_init_conf *conf)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+ 	mutex_lock(&priv->mutex);
+ 
+-	if (iwl4965_is_ready_rf(priv)) {
++	if (iwl_is_ready_rf(priv)) {
+ 		iwl4965_scan_cancel_timeout(priv, 100);
+ 		cancel_delayed_work(&priv->post_associate);
+ 		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+@@ -7821,14 +6604,77 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
+ 
+ }
+ 
++
++#ifdef CONFIG_IWL4965_HT
++static void iwl4965_ht_conf(struct iwl_priv *priv,
++			    struct ieee80211_bss_conf *bss_conf)
++{
++	struct ieee80211_ht_info *ht_conf = bss_conf->ht_conf;
++	struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
++	struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
++
++	IWL_DEBUG_MAC80211("enter: \n");
++
++	iwl_conf->is_ht = bss_conf->assoc_ht;
++
++	if (!iwl_conf->is_ht)
++		return;
++
++	priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
++
++	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
++		iwl_conf->sgf |= 0x1;
++	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
++		iwl_conf->sgf |= 0x2;
++
++	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
++	iwl_conf->max_amsdu_size =
++		!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
++
++	iwl_conf->supported_chan_width =
++		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
++	iwl_conf->extension_chan_offset =
++		ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
++	/* If no above or below channel supplied disable FAT channel */
++	if (iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_ABOVE &&
++	    iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_BELOW)
++		iwl_conf->supported_chan_width = 0;
++
++	iwl_conf->tx_mimo_ps_mode =
++		(u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
++	memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
++
++	iwl_conf->control_channel = ht_bss_conf->primary_channel;
++	iwl_conf->tx_chan_width =
++		!!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
++	iwl_conf->ht_protection =
++		ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
++	iwl_conf->non_GF_STA_present =
++		!!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
++
++	IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel);
++	IWL_DEBUG_MAC80211("leave\n");
++}
++#else
++static inline void iwl4965_ht_conf(struct iwl_priv *priv,
++				   struct ieee80211_bss_conf *bss_conf)
++{
++}
++#endif
++
++#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
+ 				     struct ieee80211_vif *vif,
+ 				     struct ieee80211_bss_conf *bss_conf,
+ 				     u32 changes)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
++
++	IWL_DEBUG_MAC80211("changes = 0x%X\n", changes);
+ 
+ 	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
++		IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n",
++				   bss_conf->use_short_preamble);
+ 		if (bss_conf->use_short_preamble)
+ 			priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ 		else
+@@ -7836,35 +6682,58 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
+ 	}
+ 
+ 	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
+-		if (bss_conf->use_cts_prot && (priv->phymode != MODE_IEEE80211A))
++		IWL_DEBUG_MAC80211("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;
+ 		else
+ 			priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+ 	}
+ 
++	if (changes & BSS_CHANGED_HT) {
++		IWL_DEBUG_MAC80211("HT %d\n", bss_conf->assoc_ht);
++		iwl4965_ht_conf(priv, bss_conf);
++		iwl4965_set_rxon_chain(priv);
++	}
++
+ 	if (changes & BSS_CHANGED_ASSOC) {
+-		/*
+-		 * TODO:
+-		 * do stuff instead of sniffing assoc resp
+-		 */
++		IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc);
++		/* This should never happen as this function should
++		 * never be called from interrupt context. */
++		if (WARN_ON_ONCE(in_interrupt()))
++			return;
++		if (bss_conf->assoc) {
++			priv->assoc_id = bss_conf->aid;
++			priv->beacon_int = bss_conf->beacon_int;
++			priv->timestamp = bss_conf->timestamp;
++			priv->assoc_capability = bss_conf->assoc_capability;
++			priv->next_scan_jiffies = jiffies +
++					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
++			mutex_lock(&priv->mutex);
++			iwl4965_post_associate(priv);
++			mutex_unlock(&priv->mutex);
++		} else {
++			priv->assoc_id = 0;
++			IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc);
++		}
++	} else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
++			IWL_DEBUG_MAC80211("Associated Changes %d\n", changes);
++			iwl_send_rxon_assoc(priv);
+ 	}
+ 
+-	if (iwl4965_is_associated(priv))
+-		iwl4965_send_rxon_assoc(priv);
+ }
+ 
+ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
+ {
+ 	int rc = 0;
+ 	unsigned long flags;
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+ 	mutex_lock(&priv->mutex);
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+-	if (!iwl4965_is_ready_rf(priv)) {
++	if (!iwl_is_ready_rf(priv)) {
+ 		rc = -EIO;
+ 		IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
+ 		goto out_unlock;
+@@ -7910,18 +6779,67 @@ out_unlock:
+ 	return rc;
+ }
+ 
++static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
++			struct ieee80211_key_conf *keyconf, const u8 *addr,
++			u32 iv32, u16 *phase1key)
++{
++	struct iwl_priv *priv = hw->priv;
++	u8 sta_id = IWL_INVALID_STATION;
++	unsigned long flags;
++	__le16 key_flags = 0;
++	int i;
++	DECLARE_MAC_BUF(mac);
++
++	IWL_DEBUG_MAC80211("enter\n");
++
++	sta_id = iwl4965_hw_find_station(priv, addr);
++	if (sta_id == IWL_INVALID_STATION) {
++		IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
++				   print_mac(mac, addr));
++		return;
++	}
++
++	iwl4965_scan_cancel_timeout(priv, 100);
++
++	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;
++
++	spin_lock_irqsave(&priv->sta_lock, flags);
++
++	priv->stations[sta_id].sta.key.key_flags = key_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;
++
++	iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
++
++	spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++	IWL_DEBUG_MAC80211("leave\n");
++}
++
+ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ 			   const u8 *local_addr, const u8 *addr,
+ 			   struct ieee80211_key_conf *key)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	DECLARE_MAC_BUF(mac);
+-	int rc = 0;
+-	u8 sta_id;
++	int ret = 0;
++	u8 sta_id = IWL_INVALID_STATION;
++	u8 is_default_wep_key = 0;
+ 
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+-	if (!iwl4965_param_hwcrypto) {
++	if (priv->cfg->mod_params->sw_crypto) {
+ 		IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
+ 		return -EOPNOTSUPP;
+ 	}
+@@ -7935,53 +6853,61 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ 		IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
+ 				   print_mac(mac, addr));
+ 		return -EINVAL;
++
+ 	}
+ 
+ 	mutex_lock(&priv->mutex);
+-
+ 	iwl4965_scan_cancel_timeout(priv, 100);
++	mutex_unlock(&priv->mutex);
++
++	/* If we are getting WEP group key and we didn't receive any key mapping
++	 * so far, we are in legacy wep mode (group key only), otherwise we are
++	 * in 1X mode.
++	 * In legacy wep mode, we use another host command to the uCode */
++	if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id &&
++		priv->iw_mode != IEEE80211_IF_TYPE_AP) {
++		if (cmd == SET_KEY)
++			is_default_wep_key = !priv->key_mapping_key;
++		else
++			is_default_wep_key = priv->default_wep_key;
++	}
+ 
+ 	switch (cmd) {
+-	case  SET_KEY:
+-		rc = iwl4965_update_sta_key_info(priv, key, sta_id);
+-		if (!rc) {
+-			iwl4965_set_rxon_hwcrypto(priv, 1);
+-			iwl4965_commit_rxon(priv);
+-			key->hw_key_idx = sta_id;
+-			IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n");
+-			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+-		}
++	case SET_KEY:
++		if (is_default_wep_key)
++			ret = iwl_set_default_wep_key(priv, key);
++		else
++			ret = iwl_set_dynamic_key(priv, key, sta_id);
++
++		IWL_DEBUG_MAC80211("enable hwcrypto key\n");
+ 		break;
+ 	case DISABLE_KEY:
+-		rc = iwl4965_clear_sta_key_info(priv, sta_id);
+-		if (!rc) {
+-			iwl4965_set_rxon_hwcrypto(priv, 0);
+-			iwl4965_commit_rxon(priv);
+-			IWL_DEBUG_MAC80211("disable hwcrypto key\n");
+-		}
++		if (is_default_wep_key)
++			ret = iwl_remove_default_wep_key(priv, key);
++		else
++			ret = iwl_remove_dynamic_key(priv, sta_id);
++
++		IWL_DEBUG_MAC80211("disable hwcrypto key\n");
+ 		break;
+ 	default:
+-		rc = -EINVAL;
++		ret = -EINVAL;
+ 	}
+ 
+ 	IWL_DEBUG_MAC80211("leave\n");
+-	mutex_unlock(&priv->mutex);
+ 
+-	return rc;
++	return ret;
+ }
+ 
+ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ 			   const struct ieee80211_tx_queue_params *params)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
+-#ifdef CONFIG_IWL4965_QOS
++	struct iwl_priv *priv = hw->priv;
+ 	unsigned long flags;
+ 	int q;
+-#endif /* CONFIG_IWL4965_QOS */
+ 
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+-	if (!iwl4965_is_ready_rf(priv)) {
++	if (!iwl_is_ready_rf(priv)) {
+ 		IWL_DEBUG_MAC80211("leave - RF not ready\n");
+ 		return -EIO;
+ 	}
+@@ -7991,7 +6917,6 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ 		return 0;
+ 	}
+ 
+-#ifdef CONFIG_IWL4965_QOS
+ 	if (!priv->qos_data.qos_enable) {
+ 		priv->qos_data.qos_active = 0;
+ 		IWL_DEBUG_MAC80211("leave - qos not enabled\n");
+@@ -8005,7 +6930,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ 	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->burst_time * 100));
++			cpu_to_le16((params->txop * 32));
+ 
+ 	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+ 	priv->qos_data.qos_active = 1;
+@@ -8015,13 +6940,11 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ 	mutex_lock(&priv->mutex);
+ 	if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ 		iwl4965_activate_qos(priv, 1);
+-	else if (priv->assoc_id && iwl4965_is_associated(priv))
++	else if (priv->assoc_id && iwl_is_associated(priv))
+ 		iwl4965_activate_qos(priv, 0);
+ 
+ 	mutex_unlock(&priv->mutex);
+ 
+-#endif /*CONFIG_IWL4965_QOS */
+-
+ 	IWL_DEBUG_MAC80211("leave\n");
+ 	return 0;
+ }
+@@ -8029,7 +6952,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
+ 				struct ieee80211_tx_queue_stats *stats)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	int i, avail;
+ 	struct iwl4965_tx_queue *txq;
+ 	struct iwl4965_queue *q;
+@@ -8037,7 +6960,7 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
+ 
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+-	if (!iwl4965_is_ready_rf(priv)) {
++	if (!iwl_is_ready_rf(priv)) {
+ 		IWL_DEBUG_MAC80211("leave - RF not ready\n");
+ 		return -EIO;
+ 	}
+@@ -8080,7 +7003,7 @@ static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw)
+ 
+ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	unsigned long flags;
+ 
+ 	mutex_lock(&priv->mutex);
+@@ -8091,30 +7014,15 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+-#ifdef CONFIG_IWL4965_HT_AGG
+-/*	if (priv->lq_mngr.agg_ctrl.granted_ba)
+-		iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);*/
+-
+-	memset(&(priv->lq_mngr.agg_ctrl), 0, sizeof(struct iwl4965_agg_control));
+-	priv->lq_mngr.agg_ctrl.tid_traffic_load_threshold = 10;
+-	priv->lq_mngr.agg_ctrl.ba_timeout = 5000;
+-	priv->lq_mngr.agg_ctrl.auto_agg = 1;
+-
+-	if (priv->lq_mngr.agg_ctrl.auto_agg)
+-		priv->lq_mngr.agg_ctrl.requested_ba = TID_ALL_ENABLED;
+-#endif /*CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ 
+-#ifdef CONFIG_IWL4965_QOS
+-	iwl4965_reset_qos(priv);
+-#endif
++	iwlcore_reset_qos(priv);
+ 
+ 	cancel_delayed_work(&priv->post_associate);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	priv->assoc_id = 0;
+ 	priv->assoc_capability = 0;
+-	priv->call_post_assoc_from_beacon = 0;
+ 	priv->assoc_station_added = 0;
+ 
+ 	/* new association get rid of ibss beacon skb */
+@@ -8124,14 +7032,13 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+ 	priv->ibss_beacon = NULL;
+ 
+ 	priv->beacon_int = priv->hw->conf.beacon_int;
+-	priv->timestamp1 = 0;
+-	priv->timestamp0 = 0;
++	priv->timestamp = 0;
+ 	if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
+ 		priv->beacon_int = 0;
+ 
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	if (!iwl4965_is_ready_rf(priv)) {
++	if (!iwl_is_ready_rf(priv)) {
+ 		IWL_DEBUG_MAC80211("leave - not ready\n");
+ 		mutex_unlock(&priv->mutex);
+ 		return;
+@@ -8166,13 +7073,13 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+ 				 struct ieee80211_tx_control *control)
+ {
+-	struct iwl4965_priv *priv = hw->priv;
++	struct iwl_priv *priv = hw->priv;
+ 	unsigned long flags;
+ 
+ 	mutex_lock(&priv->mutex);
+ 	IWL_DEBUG_MAC80211("enter\n");
+ 
+-	if (!iwl4965_is_ready_rf(priv)) {
++	if (!iwl_is_ready_rf(priv)) {
+ 		IWL_DEBUG_MAC80211("leave - RF not ready\n");
+ 		mutex_unlock(&priv->mutex);
+ 		return -EIO;
+@@ -8196,9 +7103,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
+ 	IWL_DEBUG_MAC80211("leave\n");
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-#ifdef CONFIG_IWL4965_QOS
+-	iwl4965_reset_qos(priv);
+-#endif
++	iwlcore_reset_qos(priv);
+ 
+ 	queue_work(priv->workqueue, &priv->post_associate.work);
+ 
+@@ -8207,111 +7112,13 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_IWL4965_HT
+-
+-static void iwl4965_ht_info_fill(struct ieee80211_conf *conf,
+-				 struct iwl4965_priv *priv)
+-{
+-	struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
+-	struct ieee80211_ht_info *ht_conf = &conf->ht_conf;
+-	struct ieee80211_ht_bss_info *ht_bss_conf = &conf->ht_bss_conf;
+-
+-	IWL_DEBUG_MAC80211("enter: \n");
+-
+-	if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) {
+-		iwl_conf->is_ht = 0;
+-		return;
+-	}
+-
+-	iwl_conf->is_ht = 1;
+-	priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
+-
+-	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
+-		iwl_conf->sgf |= 0x1;
+-	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
+-		iwl_conf->sgf |= 0x2;
+-
+-	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
+-	iwl_conf->max_amsdu_size =
+-		!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
+-	iwl_conf->supported_chan_width =
+-		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
+-	iwl_conf->tx_mimo_ps_mode =
+-		(u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
+-	memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
+-
+-	iwl_conf->control_channel = ht_bss_conf->primary_channel;
+-	iwl_conf->extension_chan_offset =
+-		ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
+-	iwl_conf->tx_chan_width =
+-		!!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
+-	iwl_conf->ht_protection =
+-		ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
+-	iwl_conf->non_GF_STA_present =
+-		!!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
+-
+-	IWL_DEBUG_MAC80211("control channel %d\n",
+-		iwl_conf->control_channel);
+-	IWL_DEBUG_MAC80211("leave\n");
+-}
+-
+-static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw,
+-			       struct ieee80211_conf *conf)
+-{
+-	struct iwl4965_priv *priv = hw->priv;
+-
+-	IWL_DEBUG_MAC80211("enter: \n");
+-
+-	iwl4965_ht_info_fill(conf, priv);
+-	iwl4965_set_rxon_chain(priv);
+-
+-	if (priv && priv->assoc_id &&
+-	    (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
+-		unsigned long flags;
+-
+-		spin_lock_irqsave(&priv->lock, flags);
+-		if (priv->beacon_int)
+-			queue_work(priv->workqueue, &priv->post_associate.work);
+-		else
+-			priv->call_post_assoc_from_beacon = 1;
+-		spin_unlock_irqrestore(&priv->lock, flags);
+-	}
+-
+-	IWL_DEBUG_MAC80211("leave:\n");
+-	return 0;
+-}
+-
+-static void iwl4965_set_ht_capab(struct ieee80211_hw *hw,
+-			struct ieee80211_ht_cap *ht_cap,
+-			u8 use_current_config)
+-{
+-	struct ieee80211_conf *conf = &hw->conf;
+-	struct ieee80211_hw_mode *mode = conf->mode;
+-
+-	if (use_current_config) {
+-		ht_cap->cap_info = cpu_to_le16(conf->ht_conf.cap);
+-		memcpy(ht_cap->supp_mcs_set,
+-				conf->ht_conf.supp_mcs_set, 16);
+-	} else {
+-		ht_cap->cap_info = cpu_to_le16(mode->ht_info.cap);
+-		memcpy(ht_cap->supp_mcs_set,
+-				mode->ht_info.supp_mcs_set, 16);
+-	}
+-	ht_cap->ampdu_params_info =
+-		(mode->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) |
+-		((mode->ht_info.ampdu_density << 2) &
+-					IEEE80211_HT_CAP_AMPDU_DENSITY);
+-}
+-
+-#endif /*CONFIG_IWL4965_HT*/
+-
+ /*****************************************************************************
+  *
+  * sysfs attributes
+  *
+  *****************************************************************************/
+ 
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ 
+ /*
+  * The following adds a new attribute to the sysfs representation
+@@ -8323,7 +7130,7 @@ static void iwl4965_set_ht_capab(struct ieee80211_hw *hw,
+ 
+ static ssize_t show_debug_level(struct device_driver *d, char *buf)
+ {
+-	return sprintf(buf, "0x%08X\n", iwl4965_debug_level);
++	return sprintf(buf, "0x%08X\n", iwl_debug_level);
+ }
+ static ssize_t store_debug_level(struct device_driver *d,
+ 				 const char *buf, size_t count)
+@@ -8336,7 +7143,7 @@ static ssize_t store_debug_level(struct device_driver *d,
+ 		printk(KERN_INFO DRV_NAME
+ 		       ": %s is not in hex or decimal form.\n", buf);
+ 	else
+-		iwl4965_debug_level = val;
++		iwl_debug_level = val;
+ 
+ 	return strnlen(buf, count);
+ }
+@@ -8344,45 +7151,15 @@ static ssize_t store_debug_level(struct device_driver *d,
+ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
+ 		   show_debug_level, store_debug_level);
+ 
+-#endif /* CONFIG_IWL4965_DEBUG */
+-
+-static ssize_t show_rf_kill(struct device *d,
+-			    struct device_attribute *attr, char *buf)
+-{
+-	/*
+-	 * 0 - RF kill not enabled
+-	 * 1 - SW based RF kill active (sysfs)
+-	 * 2 - HW based RF kill active
+-	 * 3 - Both HW and SW based RF kill active
+-	 */
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
+-	int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
+-		  (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
+-
+-	return sprintf(buf, "%i\n", val);
+-}
+-
+-static ssize_t store_rf_kill(struct device *d,
+-			     struct device_attribute *attr,
+-			     const char *buf, size_t count)
+-{
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++#endif /* CONFIG_IWLWIFI_DEBUG */
+ 
+-	mutex_lock(&priv->mutex);
+-	iwl4965_radio_kill_sw(priv, buf[0] == '1');
+-	mutex_unlock(&priv->mutex);
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
+ 
+ static ssize_t show_temperature(struct device *d,
+ 				struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ 
+-	if (!iwl4965_is_alive(priv))
++	if (!iwl_is_alive(priv))
+ 		return -EAGAIN;
+ 
+ 	return sprintf(buf, "%d\n", iwl4965_hw_get_temperature(priv));
+@@ -8394,7 +7171,7 @@ static ssize_t show_rs_window(struct device *d,
+ 			      struct device_attribute *attr,
+ 			      char *buf)
+ {
+-	struct iwl4965_priv *priv = d->driver_data;
++	struct iwl_priv *priv = d->driver_data;
+ 	return iwl4965_fill_rs_info(priv->hw, buf, IWL_AP_ID);
+ }
+ static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
+@@ -8402,7 +7179,7 @@ static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
+ static ssize_t show_tx_power(struct device *d,
+ 			     struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ 	return sprintf(buf, "%d\n", priv->user_txpower_limit);
+ }
+ 
+@@ -8410,7 +7187,7 @@ static ssize_t store_tx_power(struct device *d,
+ 			      struct device_attribute *attr,
+ 			      const char *buf, size_t count)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ 	char *p = (char *)buf;
+ 	u32 val;
+ 
+@@ -8429,7 +7206,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
+ static ssize_t show_flags(struct device *d,
+ 			  struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ 
+ 	return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
+ }
+@@ -8438,7 +7215,7 @@ static ssize_t store_flags(struct device *d,
+ 			   struct device_attribute *attr,
+ 			   const char *buf, size_t count)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ 	u32 flags = simple_strtoul(buf, NULL, 0);
+ 
+ 	mutex_lock(&priv->mutex);
+@@ -8463,7 +7240,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
+ static ssize_t show_filter_flags(struct device *d,
+ 				 struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ 
+ 	return sprintf(buf, "0x%04X\n",
+ 		le32_to_cpu(priv->active_rxon.filter_flags));
+@@ -8473,7 +7250,7 @@ static ssize_t store_filter_flags(struct device *d,
+ 				  struct device_attribute *attr,
+ 				  const char *buf, size_t count)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ 	u32 filter_flags = simple_strtoul(buf, NULL, 0);
+ 
+ 	mutex_lock(&priv->mutex);
+@@ -8497,71 +7274,12 @@ static ssize_t store_filter_flags(struct device *d,
+ static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
+ 		   store_filter_flags);
+ 
+-static ssize_t show_tune(struct device *d,
+-			 struct device_attribute *attr, char *buf)
+-{
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
+-
+-	return sprintf(buf, "0x%04X\n",
+-		       (priv->phymode << 8) |
+-			le16_to_cpu(priv->active_rxon.channel));
+-}
+-
+-static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode);
+-
+-static ssize_t store_tune(struct device *d,
+-			  struct device_attribute *attr,
+-			  const char *buf, size_t count)
+-{
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
+-	char *p = (char *)buf;
+-	u16 tune = simple_strtoul(p, &p, 0);
+-	u8 phymode = (tune >> 8) & 0xff;
+-	u16 channel = tune & 0xff;
+-
+-	IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
+-
+-	mutex_lock(&priv->mutex);
+-	if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
+-	    (priv->phymode != phymode)) {
+-		const struct iwl4965_channel_info *ch_info;
+-
+-		ch_info = iwl4965_get_channel_info(priv, phymode, channel);
+-		if (!ch_info) {
+-			IWL_WARNING("Requested invalid phymode/channel "
+-				    "combination: %d %d\n", phymode, channel);
+-			mutex_unlock(&priv->mutex);
+-			return -EINVAL;
+-		}
+-
+-		/* Cancel any currently running scans... */
+-		if (iwl4965_scan_cancel_timeout(priv, 100))
+-			IWL_WARNING("Could not cancel scan.\n");
+-		else {
+-			IWL_DEBUG_INFO("Committing phymode and "
+-				       "rxon.channel = %d %d\n",
+-				       phymode, channel);
+-
+-			iwl4965_set_rxon_channel(priv, phymode, channel);
+-			iwl4965_set_flags_for_phymode(priv, phymode);
+-
+-			iwl4965_set_rate(priv);
+-			iwl4965_commit_rxon(priv);
+-		}
+-	}
+-	mutex_unlock(&priv->mutex);
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
+-
+ #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
+ 
+ static ssize_t show_measurement(struct device *d,
+ 				struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
++	struct iwl_priv *priv = dev_get_drvdata(d);
+ 	struct iwl4965_spectrum_notification measure_report;
+ 	u32 size = sizeof(measure_report), len = 0, ofs = 0;
+ 	u8 *data = (u8 *) & measure_report;
+@@ -8594,7 +7312,7 @@ static ssize_t store_measurement(struct device *d,
+ 				 struct device_attribute *attr,
+ 				 const char *buf, size_t count)
+ {
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
++	struct iwl_priv *priv = dev_get_drvdata(d);
+ 	struct ieee80211_measurement_params params = {
+ 		.channel = le16_to_cpu(priv->active_rxon.channel),
+ 		.start_time = cpu_to_le64(priv->last_tsf),
+@@ -8633,7 +7351,7 @@ static ssize_t store_retry_rate(struct device *d,
+ 				struct device_attribute *attr,
+ 				const char *buf, size_t count)
+ {
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
++	struct iwl_priv *priv = dev_get_drvdata(d);
+ 
+ 	priv->retry_rate = simple_strtoul(buf, NULL, 0);
+ 	if (priv->retry_rate <= 0)
+@@ -8645,7 +7363,7 @@ static ssize_t store_retry_rate(struct device *d,
+ static ssize_t show_retry_rate(struct device *d,
+ 			       struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
++	struct iwl_priv *priv = dev_get_drvdata(d);
+ 	return sprintf(buf, "%d", priv->retry_rate);
+ }
+ 
+@@ -8656,14 +7374,14 @@ static ssize_t store_power_level(struct device *d,
+ 				 struct device_attribute *attr,
+ 				 const char *buf, size_t count)
+ {
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
++	struct iwl_priv *priv = dev_get_drvdata(d);
+ 	int rc;
+ 	int mode;
+ 
+ 	mode = simple_strtoul(buf, NULL, 0);
+ 	mutex_lock(&priv->mutex);
+ 
+-	if (!iwl4965_is_ready(priv)) {
++	if (!iwl_is_ready(priv)) {
+ 		rc = -EAGAIN;
+ 		goto out;
+ 	}
+@@ -8710,7 +7428,7 @@ static const s32 period_duration[] = {
+ static ssize_t show_power_level(struct device *d,
+ 				struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
++	struct iwl_priv *priv = dev_get_drvdata(d);
+ 	int level = IWL_POWER_LEVEL(priv->power_mode);
+ 	char *p = buf;
+ 
+@@ -8745,73 +7463,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
+ static ssize_t show_channels(struct device *d,
+ 			     struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
+-	int len = 0, i;
+-	struct ieee80211_channel *channels = NULL;
+-	const struct ieee80211_hw_mode *hw_mode = NULL;
+-	int count = 0;
+-
+-	if (!iwl4965_is_ready(priv))
+-		return -EAGAIN;
+-
+-	hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211G);
+-	if (!hw_mode)
+-		hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211B);
+-	if (hw_mode) {
+-		channels = hw_mode->channels;
+-		count = hw_mode->num_channels;
+-	}
+-
+-	len +=
+-	    sprintf(&buf[len],
+-		    "Displaying %d channels in 2.4GHz band "
+-		    "(802.11bg):\n", count);
+-
+-	for (i = 0; i < count; i++)
+-		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+-			       channels[i].chan,
+-			       channels[i].power_level,
+-			       channels[i].
+-			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
+-			       " (IEEE 802.11h required)" : "",
+-			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
+-				|| (channels[i].
+-				    flag &
+-				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
+-			       ", IBSS",
+-			       channels[i].
+-			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
+-			       "active/passive" : "passive only");
+-
+-	hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211A);
+-	if (hw_mode) {
+-		channels = hw_mode->channels;
+-		count = hw_mode->num_channels;
+-	} else {
+-		channels = NULL;
+-		count = 0;
+-	}
+-
+-	len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
+-		       "(802.11a):\n", count);
+-
+-	for (i = 0; i < count; i++)
+-		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+-			       channels[i].chan,
+-			       channels[i].power_level,
+-			       channels[i].
+-			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
+-			       " (IEEE 802.11h required)" : "",
+-			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
+-				|| (channels[i].
+-				    flag &
+-				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
+-			       ", IBSS",
+-			       channels[i].
+-			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
+-			       "active/passive" : "passive only");
+-
+-	return len;
++	/* all this shit doesn't belong into sysfs anyway */
++	return 0;
+ }
+ 
+ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
+@@ -8819,17 +7472,17 @@ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
+ static ssize_t show_statistics(struct device *d,
+ 			       struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
++	struct iwl_priv *priv = dev_get_drvdata(d);
+ 	u32 size = sizeof(struct iwl4965_notif_statistics);
+ 	u32 len = 0, ofs = 0;
+ 	u8 *data = (u8 *) & priv->statistics;
+ 	int rc = 0;
+ 
+-	if (!iwl4965_is_alive(priv))
++	if (!iwl_is_alive(priv))
+ 		return -EAGAIN;
+ 
+ 	mutex_lock(&priv->mutex);
+-	rc = iwl4965_send_statistics_request(priv);
++	rc = iwl_send_statistics_request(priv, 0);
+ 	mutex_unlock(&priv->mutex);
+ 
+ 	if (rc) {
+@@ -8857,9 +7510,9 @@ static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
+ static ssize_t show_antenna(struct device *d,
+ 			    struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
++	struct iwl_priv *priv = dev_get_drvdata(d);
+ 
+-	if (!iwl4965_is_alive(priv))
++	if (!iwl_is_alive(priv))
+ 		return -EAGAIN;
+ 
+ 	return sprintf(buf, "%d\n", priv->antenna);
+@@ -8870,7 +7523,7 @@ static ssize_t store_antenna(struct device *d,
+ 			     const char *buf, size_t count)
+ {
+ 	int ant;
+-	struct iwl4965_priv *priv = dev_get_drvdata(d);
++	struct iwl_priv *priv = dev_get_drvdata(d);
+ 
+ 	if (count == 0)
+ 		return 0;
+@@ -8895,8 +7548,8 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
+ static ssize_t show_status(struct device *d,
+ 			   struct device_attribute *attr, char *buf)
+ {
+-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
+-	if (!iwl4965_is_alive(priv))
++	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++	if (!iwl_is_alive(priv))
+ 		return -EAGAIN;
+ 	return sprintf(buf, "0x%08x\n", (int)priv->status);
+ }
+@@ -8910,7 +7563,7 @@ static ssize_t dump_error_log(struct device *d,
+ 	char *p = (char *)buf;
+ 
+ 	if (p[0] == '1')
+-		iwl4965_dump_nic_error_log((struct iwl4965_priv *)d->driver_data);
++		iwl4965_dump_nic_error_log((struct iwl_priv *)d->driver_data);
+ 
+ 	return strnlen(buf, count);
+ }
+@@ -8924,7 +7577,7 @@ static ssize_t dump_event_log(struct device *d,
+ 	char *p = (char *)buf;
+ 
+ 	if (p[0] == '1')
+-		iwl4965_dump_nic_event_log((struct iwl4965_priv *)d->driver_data);
++		iwl4965_dump_nic_event_log((struct iwl_priv *)d->driver_data);
+ 
+ 	return strnlen(buf, count);
+ }
+@@ -8937,7 +7590,7 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
+  *
+  *****************************************************************************/
+ 
+-static void iwl4965_setup_deferred_work(struct iwl4965_priv *priv)
++static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
+ {
+ 	priv->workqueue = create_workqueue(DRV_NAME);
+ 
+@@ -8962,7 +7615,7 @@ static void iwl4965_setup_deferred_work(struct iwl4965_priv *priv)
+ 		     iwl4965_irq_tasklet, (unsigned long)priv);
+ }
+ 
+-static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv)
++static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
+ {
+ 	iwl4965_hw_cancel_deferred_work(priv);
+ 
+@@ -8985,12 +7638,10 @@ static struct attribute *iwl4965_sysfs_entries[] = {
+ #endif
+ 	&dev_attr_power_level.attr,
+ 	&dev_attr_retry_rate.attr,
+-	&dev_attr_rf_kill.attr,
+ 	&dev_attr_rs_window.attr,
+ 	&dev_attr_statistics.attr,
+ 	&dev_attr_status.attr,
+ 	&dev_attr_temperature.attr,
+-	&dev_attr_tune.attr,
+ 	&dev_attr_tx_power.attr,
+ 
+ 	NULL
+@@ -9011,6 +7662,7 @@ static struct ieee80211_ops iwl4965_hw_ops = {
+ 	.config_interface = iwl4965_mac_config_interface,
+ 	.configure_filter = iwl4965_configure_filter,
+ 	.set_key = iwl4965_mac_set_key,
++	.update_tkip_key = iwl4965_mac_update_tkip_key,
+ 	.get_stats = iwl4965_mac_get_stats,
+ 	.get_tx_stats = iwl4965_mac_get_tx_stats,
+ 	.conf_tx = iwl4965_mac_conf_tx,
+@@ -9019,12 +7671,7 @@ static struct ieee80211_ops iwl4965_hw_ops = {
+ 	.beacon_update = iwl4965_mac_beacon_update,
+ 	.bss_info_changed = iwl4965_bss_info_changed,
+ #ifdef CONFIG_IWL4965_HT
+-	.conf_ht = iwl4965_mac_conf_ht,
+ 	.ampdu_action = iwl4965_mac_ampdu_action,
+-#ifdef CONFIG_IWL4965_HT_AGG
+-	.ht_tx_agg_start = iwl4965_mac_ht_tx_agg_start,
+-	.ht_tx_agg_stop = iwl4965_mac_ht_tx_agg_stop,
+-#endif  /* CONFIG_IWL4965_HT_AGG */
+ #endif  /* CONFIG_IWL4965_HT */
+ 	.hw_scan = iwl4965_mac_hw_scan
+ };
+@@ -9032,85 +7679,45 @@ static struct ieee80211_ops iwl4965_hw_ops = {
+ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ 	int err = 0;
+-	struct iwl4965_priv *priv;
++	struct iwl_priv *priv;
+ 	struct ieee80211_hw *hw;
+-	int i;
++	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
++	unsigned long flags;
+ 	DECLARE_MAC_BUF(mac);
+ 
++	/************************
++	 * 1. Allocating HW data
++	 ************************/
++
+ 	/* Disabling hardware scan means that mac80211 will perform scans
+ 	 * "the hard way", rather than using device's scan. */
+-	if (iwl4965_param_disable_hw_scan) {
++	if (cfg->mod_params->disable_hw_scan) {
+ 		IWL_DEBUG_INFO("Disabling hw_scan\n");
+ 		iwl4965_hw_ops.hw_scan = NULL;
+ 	}
+ 
+-	if ((iwl4965_param_queues_num > IWL_MAX_NUM_QUEUES) ||
+-	    (iwl4965_param_queues_num < IWL_MIN_NUM_QUEUES)) {
+-		IWL_ERROR("invalid queues_num, should be between %d and %d\n",
+-			  IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
+-		err = -EINVAL;
+-		goto out;
+-	}
+-
+-	/* mac80211 allocates memory for this device instance, including
+-	 *   space for this driver's private structure */
+-	hw = ieee80211_alloc_hw(sizeof(struct iwl4965_priv), &iwl4965_hw_ops);
+-	if (hw == NULL) {
+-		IWL_ERROR("Can not allocate network device\n");
++	hw = iwl_alloc_all(cfg, &iwl4965_hw_ops);
++	if (!hw) {
+ 		err = -ENOMEM;
+ 		goto out;
+ 	}
+-	SET_IEEE80211_DEV(hw, &pdev->dev);
++	priv = hw->priv;
++	/* At this point both hw and priv are allocated. */
+ 
+-	hw->rate_control_algorithm = "iwl-4965-rs";
++	SET_IEEE80211_DEV(hw, &pdev->dev);
+ 
+ 	IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
+-	priv = hw->priv;
+-	priv->hw = hw;
+-
++	priv->cfg = cfg;
+ 	priv->pci_dev = pdev;
+-	priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna;
+-#ifdef CONFIG_IWL4965_DEBUG
+-	iwl4965_debug_level = iwl4965_param_debug;
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++	iwl_debug_level = priv->cfg->mod_params->debug;
+ 	atomic_set(&priv->restrict_refcnt, 0);
+ #endif
+-	priv->retry_rate = 1;
+-
+-	priv->ibss_beacon = NULL;
+-
+-	/* Tell mac80211 and its clients (e.g. Wireless Extensions)
+-	 *   the range of signal quality values that we'll provide.
+-	 * Negative values for level/noise indicate that we'll provide dBm.
+-	 * For WE, at least, non-0 values here *enable* display of values
+-	 *   in app (iwconfig). */
+-	hw->max_rssi = -20;	/* signal level, negative indicates dBm */
+-	hw->max_noise = -20;	/* noise level, negative indicates dBm */
+-	hw->max_signal = 100;	/* link quality indication (%) */
+ 
+-	/* Tell mac80211 our Tx characteristics */
+-	hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+-
+-	/* Default value; 4 EDCA QOS priorities */
+-	hw->queues = 4;
+-#ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+-	/* Enhanced value; more queues, to support 11n aggregation */
+-	hw->queues = 16;
+-#endif /* CONFIG_IWL4965_HT_AGG */
+-#endif /* CONFIG_IWL4965_HT */
+-
+-	spin_lock_init(&priv->lock);
+-	spin_lock_init(&priv->power_data.lock);
+-	spin_lock_init(&priv->sta_lock);
+-	spin_lock_init(&priv->hcmd_lock);
+-	spin_lock_init(&priv->lq_mngr.lock);
+-
+-	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
+-		INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
+-
+-	INIT_LIST_HEAD(&priv->free_frames);
+-
+-	mutex_init(&priv->mutex);
++	/**************************
++	 * 2. Initializing PCI bus
++	 **************************/
+ 	if (pci_enable_device(pdev)) {
+ 		err = -ENODEV;
+ 		goto out_ieee80211_free_hw;
+@@ -9118,31 +7725,28 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 
+ 	pci_set_master(pdev);
+ 
+-	/* Clear the driver's (not device's) station table */
+-	iwl4965_clear_stations_table(priv);
+-
+-	priv->data_retry_limit = -1;
+-	priv->ieee_channels = NULL;
+-	priv->ieee_rates = NULL;
+-	priv->phymode = -1;
+-
+ 	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ 	if (!err)
+ 		err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+-	if (err) {
+-		printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
+-		goto out_pci_disable_device;
++		if (err) {
++			printk(KERN_WARNING DRV_NAME
++				": No suitable DMA available.\n");
++			goto out_pci_disable_device;
+ 	}
+ 
+-	pci_set_drvdata(pdev, priv);
+ 	err = pci_request_regions(pdev, DRV_NAME);
+ 	if (err)
+ 		goto out_pci_disable_device;
+ 
++	pci_set_drvdata(pdev, priv);
++
+ 	/* We disable the RETRY_TIMEOUT register (0x41) to keep
+ 	 * PCI Tx retries from interfering with C3 CPU state */
+ 	pci_write_config_byte(pdev, 0x41, 0x00);
+ 
++	/***********************
++	 * 3. Read REV register
++	 ***********************/
+ 	priv->hw_base = pci_iomap(pdev, 0, 0);
+ 	if (!priv->hw_base) {
+ 		err = -ENODEV;
+@@ -9150,132 +7754,112 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 	}
+ 
+ 	IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n",
+-			(unsigned long long) pci_resource_len(pdev, 0));
++		(unsigned long long) pci_resource_len(pdev, 0));
+ 	IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
+ 
+-	/* Initialize module parameter values here */
++	printk(KERN_INFO DRV_NAME
++		": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+ 
+-	/* Disable radio (SW RF KILL) via parameter when loading driver */
+-	if (iwl4965_param_disable) {
+-		set_bit(STATUS_RF_KILL_SW, &priv->status);
+-		IWL_DEBUG_INFO("Radio disabled.\n");
++	/*****************
++	 * 4. Read EEPROM
++	 *****************/
++	/* nic init */
++	iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
++		CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
++
++	iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
++	err = iwl_poll_bit(priv, CSR_GP_CNTRL,
++		CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
++		CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
++	if (err < 0) {
++		IWL_DEBUG_INFO("Failed to init the card\n");
++		goto out_iounmap;
+ 	}
++	/* Read the EEPROM */
++	err = iwl_eeprom_init(priv);
++	if (err) {
++		IWL_ERROR("Unable to init EEPROM\n");
++		goto out_iounmap;
++	}
++	/* MAC Address location in EEPROM same for 3945/4965 */
++	iwl_eeprom_get_mac(priv, priv->mac_addr);
++	IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
++	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+ 
+-	priv->iw_mode = IEEE80211_IF_TYPE_STA;
+-
+-	priv->ps_mode = 0;
+-	priv->use_ant_b_for_management_frame = 1; /* start with ant B */
+-	priv->valid_antenna = 0x7;	/* assume all 3 connected */
+-	priv->ps_mode = IWL_MIMO_PS_NONE;
+-
+-	/* Choose which receivers/antennas to use */
+-	iwl4965_set_rxon_chain(priv);
+-
+-	printk(KERN_INFO DRV_NAME
+-	       ": Detected Intel Wireless WiFi Link 4965AGN\n");
+-
++	/************************
++	 * 5. Setup HW constants
++	 ************************/
+ 	/* Device-specific setup */
+-	if (iwl4965_hw_set_hw_setting(priv)) {
+-		IWL_ERROR("failed to set hw settings\n");
++	if (priv->cfg->ops->lib->set_hw_params(priv)) {
++		IWL_ERROR("failed to set hw parameters\n");
+ 		goto out_iounmap;
+ 	}
+ 
+-#ifdef CONFIG_IWL4965_QOS
+-	if (iwl4965_param_qos_enable)
+-		priv->qos_data.qos_enable = 1;
++	/*******************
++	 * 6. Setup hw/priv
++	 *******************/
+ 
+-	iwl4965_reset_qos(priv);
++	err = iwl_setup(priv);
++	if (err)
++		goto out_unset_hw_params;
++	/* At this point both hw and priv are initialized. */
+ 
+-	priv->qos_data.qos_active = 0;
+-	priv->qos_data.qos_cap.val = 0;
+-#endif /* CONFIG_IWL4965_QOS */
++	/**********************************
++	 * 7. Initialize module parameters
++	 **********************************/
+ 
+-	iwl4965_set_rxon_channel(priv, MODE_IEEE80211G, 6);
+-	iwl4965_setup_deferred_work(priv);
+-	iwl4965_setup_rx_handlers(priv);
++	/* Disable radio (SW RF KILL) via parameter when loading driver */
++	if (priv->cfg->mod_params->disable) {
++		set_bit(STATUS_RF_KILL_SW, &priv->status);
++		IWL_DEBUG_INFO("Radio disabled.\n");
++	}
+ 
+-	priv->rates_mask = IWL_RATES_MASK;
+-	/* If power management is turned on, default to AC mode */
+-	priv->power_mode = IWL_POWER_AC;
+-	priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
++	if (priv->cfg->mod_params->enable_qos)
++		priv->qos_data.qos_enable = 1;
+ 
++	/********************
++	 * 8. Setup services
++	 ********************/
++	spin_lock_irqsave(&priv->lock, flags);
+ 	iwl4965_disable_interrupts(priv);
++	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+ 	if (err) {
+ 		IWL_ERROR("failed to create sysfs device attributes\n");
+-		goto out_release_irq;
+-	}
+-
+-	/* nic init */
+-	iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+-                    CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+-
+-        iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+-        err = iwl4965_poll_bit(priv, CSR_GP_CNTRL,
+-                          CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+-                          CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+-        if (err < 0) {
+-                IWL_DEBUG_INFO("Failed to init the card\n");
+-		goto out_remove_sysfs;
+-        }
+-	/* Read the EEPROM */
+-	err = iwl4965_eeprom_init(priv);
+-	if (err) {
+-		IWL_ERROR("Unable to init EEPROM\n");
+-		goto out_remove_sysfs;
++		goto out_unset_hw_params;
+ 	}
+-	/* MAC Address location in EEPROM same for 3945/4965 */
+-	get_eeprom_mac(priv, priv->mac_addr);
+-	IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
+-	SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+ 
+-	err = iwl4965_init_channel_map(priv);
++	err = iwl_dbgfs_register(priv, DRV_NAME);
+ 	if (err) {
+-		IWL_ERROR("initializing regulatory failed: %d\n", err);
++		IWL_ERROR("failed to create debugfs files\n");
+ 		goto out_remove_sysfs;
+ 	}
+ 
+-	err = iwl4965_init_geos(priv);
+-	if (err) {
+-		IWL_ERROR("initializing geos failed: %d\n", err);
+-		goto out_free_channel_map;
+-	}
+-	iwl4965_reset_channel_flag(priv);
+-
+-	iwl4965_rate_control_register(priv->hw);
+-	err = ieee80211_register_hw(priv->hw);
+-	if (err) {
+-		IWL_ERROR("Failed to register network device (error %d)\n", err);
+-		goto out_free_geos;
+-	}
++	iwl4965_setup_deferred_work(priv);
++	iwl4965_setup_rx_handlers(priv);
+ 
+-	priv->hw->conf.beacon_int = 100;
+-	priv->mac80211_registered = 1;
++	/********************
++	 * 9. Conclude
++	 ********************/
+ 	pci_save_state(pdev);
+ 	pci_disable_device(pdev);
+ 
++	/* notify iwlcore to init */
++	iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT);
+ 	return 0;
+ 
+- out_free_geos:
+-	iwl4965_free_geos(priv);
+- out_free_channel_map:
+-	iwl4965_free_channel_map(priv);
+  out_remove_sysfs:
+ 	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+-
+- out_release_irq:
+-	destroy_workqueue(priv->workqueue);
+-	priv->workqueue = NULL;
+-	iwl4965_unset_hw_setting(priv);
+-
++ out_unset_hw_params:
++	iwl4965_unset_hw_params(priv);
+  out_iounmap:
+ 	pci_iounmap(pdev, priv->hw_base);
+  out_pci_release_regions:
+ 	pci_release_regions(pdev);
++	pci_set_drvdata(pdev, NULL);
+  out_pci_disable_device:
+ 	pci_disable_device(pdev);
+-	pci_set_drvdata(pdev, NULL);
+  out_ieee80211_free_hw:
+ 	ieee80211_free_hw(priv->hw);
+  out:
+@@ -9284,19 +7868,34 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 
+ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ {
+-	struct iwl4965_priv *priv = pci_get_drvdata(pdev);
++	struct iwl_priv *priv = pci_get_drvdata(pdev);
+ 	struct list_head *p, *q;
+ 	int i;
++	unsigned long flags;
+ 
+ 	if (!priv)
+ 		return;
+ 
+ 	IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n");
+ 
++	if (priv->mac80211_registered) {
++		ieee80211_unregister_hw(priv->hw);
++		priv->mac80211_registered = 0;
++	}
++
+ 	set_bit(STATUS_EXIT_PENDING, &priv->status);
+ 
+ 	iwl4965_down(priv);
+ 
++	/* make sure we flush any pending irq or
++	 * tasklet for the driver
++	 */
++	spin_lock_irqsave(&priv->lock, flags);
++	iwl4965_disable_interrupts(priv);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	iwl_synchronize_irq(priv);
++
+ 	/* Free MAC hash list for ADHOC */
+ 	for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
+ 		list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
+@@ -9305,6 +7904,8 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ 		}
+ 	}
+ 
++	iwlcore_low_level_notify(priv, IWLCORE_REMOVE_EVT);
++	iwl_dbgfs_unregister(priv);
+ 	sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+ 
+ 	iwl4965_dealloc_ucode_pci(priv);
+@@ -9313,13 +7914,9 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ 		iwl4965_rx_queue_free(priv, &priv->rxq);
+ 	iwl4965_hw_txq_ctx_free(priv);
+ 
+-	iwl4965_unset_hw_setting(priv);
+-	iwl4965_clear_stations_table(priv);
++	iwl4965_unset_hw_params(priv);
++	iwlcore_clear_stations_table(priv);
+ 
+-	if (priv->mac80211_registered) {
+-		ieee80211_unregister_hw(priv->hw);
+-		iwl4965_rate_control_unregister(priv->hw);
+-	}
+ 
+ 	/*netif_stop_queue(dev); */
+ 	flush_workqueue(priv->workqueue);
+@@ -9335,7 +7932,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ 	pci_disable_device(pdev);
+ 	pci_set_drvdata(pdev, NULL);
+ 
+-	iwl4965_free_channel_map(priv);
++	iwl_free_channel_map(priv);
+ 	iwl4965_free_geos(priv);
+ 
+ 	if (priv->ibss_beacon)
+@@ -9348,7 +7945,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ 
+ static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+-	struct iwl4965_priv *priv = pci_get_drvdata(pdev);
++	struct iwl_priv *priv = pci_get_drvdata(pdev);
+ 
+ 	if (priv->is_open) {
+ 		set_bit(STATUS_IN_SUSPEND, &priv->status);
+@@ -9363,7 +7960,7 @@ static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+ 
+ static int iwl4965_pci_resume(struct pci_dev *pdev)
+ {
+-	struct iwl4965_priv *priv = pci_get_drvdata(pdev);
++	struct iwl_priv *priv = pci_get_drvdata(pdev);
+ 
+ 	pci_set_power_state(pdev, PCI_D0);
+ 
+@@ -9382,9 +7979,17 @@ static int iwl4965_pci_resume(struct pci_dev *pdev)
+  *
+  *****************************************************************************/
+ 
+-static struct pci_driver iwl4965_driver = {
++/* Hardware specific file defines the PCI IDs table for that hardware module */
++static struct pci_device_id iwl_hw_card_ids[] = {
++	{IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
++	{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
++	{0}
++};
++MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
++
++static struct pci_driver iwl_driver = {
+ 	.name = DRV_NAME,
+-	.id_table = iwl4965_hw_card_ids,
++	.id_table = iwl_hw_card_ids,
+ 	.probe = iwl4965_pci_probe,
+ 	.remove = __devexit_p(iwl4965_pci_remove),
+ #ifdef CONFIG_PM
+@@ -9399,51 +8004,45 @@ static int __init iwl4965_init(void)
+ 	int ret;
+ 	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ 	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+-	ret = pci_register_driver(&iwl4965_driver);
++
++	ret = iwl4965_rate_control_register();
+ 	if (ret) {
+-		IWL_ERROR("Unable to initialize PCI module\n");
++		IWL_ERROR("Unable to register rate control algorithm: %d\n", ret);
+ 		return ret;
+ 	}
+-#ifdef CONFIG_IWL4965_DEBUG
+-	ret = driver_create_file(&iwl4965_driver.driver, &driver_attr_debug_level);
++
++	ret = pci_register_driver(&iwl_driver);
++	if (ret) {
++		IWL_ERROR("Unable to initialize PCI module\n");
++		goto error_register;
++	}
++#ifdef CONFIG_IWLWIFI_DEBUG
++	ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
+ 	if (ret) {
+ 		IWL_ERROR("Unable to create driver sysfs file\n");
+-		pci_unregister_driver(&iwl4965_driver);
+-		return ret;
++		goto error_debug;
+ 	}
+ #endif
+ 
+ 	return ret;
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++error_debug:
++	pci_unregister_driver(&iwl_driver);
++#endif
++error_register:
++	iwl4965_rate_control_unregister();
++	return ret;
+ }
+ 
+ static void __exit iwl4965_exit(void)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
+-	driver_remove_file(&iwl4965_driver.driver, &driver_attr_debug_level);
++#ifdef CONFIG_IWLWIFI_DEBUG
++	driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
+ #endif
+-	pci_unregister_driver(&iwl4965_driver);
+-}
+-
+-module_param_named(antenna, iwl4965_param_antenna, int, 0444);
+-MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
+-module_param_named(disable, iwl4965_param_disable, int, 0444);
+-MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
+-module_param_named(hwcrypto, iwl4965_param_hwcrypto, int, 0444);
+-MODULE_PARM_DESC(hwcrypto,
+-		 "using hardware crypto engine (default 0 [software])\n");
+-module_param_named(debug, iwl4965_param_debug, int, 0444);
+-MODULE_PARM_DESC(debug, "debug output mask");
+-module_param_named(disable_hw_scan, iwl4965_param_disable_hw_scan, int, 0444);
+-MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
+-
+-module_param_named(queues_num, iwl4965_param_queues_num, int, 0444);
+-MODULE_PARM_DESC(queues_num, "number of hw queues.");
+-
+-/* QoS */
+-module_param_named(qos_enable, iwl4965_param_qos_enable, int, 0444);
+-MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
+-module_param_named(amsdu_size_8K, iwl4965_param_amsdu_size_8K, int, 0444);
+-MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
++	pci_unregister_driver(&iwl_driver);
++	iwl4965_rate_control_unregister();
++}
+ 
+ module_exit(iwl4965_exit);
+ module_init(iwl4965_init);
+diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c
+index 5e10ce0..4bc46a6 100644
+--- a/drivers/net/wireless/libertas/11d.c
++++ b/drivers/net/wireless/libertas/11d.c
+@@ -79,7 +79,7 @@ static u8 *lbs_code_2_region(u8 code)
+  *  @param nrchan   number of channels
+  *  @return 	      the nrchan-th chan number
+ */
+-static u8 lbs_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 *chan)
++static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan)
+ /*find the nrchan-th chan after the firstchan*/
+ {
+ 	u8 i;
+@@ -134,7 +134,7 @@ static u8 lbs_channel_known_11d(u8 chan,
+ 	return 0;
+ }
+ 
+-u32 lbs_chan_2_freq(u8 chan, u8 band)
++u32 lbs_chan_2_freq(u8 chan)
+ {
+ 	struct chan_freq_power *cf;
+ 	u16 i;
+@@ -264,7 +264,7 @@ static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_ch
+  *  @param chan                 chan
+  *  @return 	                TRUE;FALSE
+ */
+-static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan)
++static u8 lbs_region_chan_supported_11d(u8 region, u8 chan)
+ {
+ 	struct chan_freq_power *cfp;
+ 	int cfp_no;
+@@ -273,7 +273,7 @@ static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan)
+ 
+ 	lbs_deb_enter(LBS_DEB_11D);
+ 
+-	cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
++	cfp = lbs_get_region_cfp_table(region, &cfp_no);
+ 	if (cfp == NULL)
+ 		return 0;
+ 
+@@ -367,7 +367,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
+ 		for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
+ 			/*step4: channel is supported? */
+ 
+-			if (!lbs_get_chan_11d(band, firstchan, i, &curchan)) {
++			if (!lbs_get_chan_11d(firstchan, i, &curchan)) {
+ 				/* Chan is not found in UN table */
+ 				lbs_deb_11d("chan is not supported: %d \n", i);
+ 				break;
+@@ -375,8 +375,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
+ 
+ 			lastchan = curchan;
+ 
+-			if (lbs_region_chan_supported_11d
+-			    (region, band, curchan)) {
++			if (lbs_region_chan_supported_11d(region, curchan)) {
+ 				/*step5: Check if curchan is supported by mrvl in region */
+ 				parsed_region_chan->chanpwr[idx].chan = curchan;
+ 				parsed_region_chan->chanpwr[idx].pwr =
+@@ -554,8 +553,7 @@ done:
+  *  @param resp    pointer to command response buffer
+  *  @return 	   0; -1
+  */
+-int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
+-				 struct cmd_ds_command *resp)
++int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
+ {
+ 	struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
+ 	struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
+diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h
+index 811eea2..4f4f47f 100644
+--- a/drivers/net/wireless/libertas/11d.h
++++ b/drivers/net/wireless/libertas/11d.h
+@@ -83,7 +83,7 @@ struct lbs_private;
+ u8 lbs_get_scan_type_11d(u8 chan,
+ 			  struct parsed_region_chan_11d *parsed_region_chan);
+ 
+-u32 lbs_chan_2_freq(u8 chan, u8 band);
++u32 lbs_chan_2_freq(u8 chan);
+ 
+ void lbs_init_11d(struct lbs_private *priv);
+ 
+@@ -93,8 +93,7 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
+ 				 struct cmd_ds_command *cmd, u16 cmdno,
+ 				 u16 cmdOption);
+ 
+-int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
+-				 struct cmd_ds_command *resp);
++int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
+ 
+ struct bss_descriptor;
+ int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
+diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
+index 0e27876..f0724e3 100644
+--- a/drivers/net/wireless/libertas/Makefile
++++ b/drivers/net/wireless/libertas/Makefile
+@@ -1,7 +1,7 @@
+ libertas-objs := main.o wext.o \
+ 		rx.o tx.o cmd.o 	  \
+ 		cmdresp.o scan.o	  \
+-		join.o 11d.o 		  \
++		11d.o 		  \
+ 		debugfs.o	  \
+ 		ethtool.o assoc.o
+ 
+diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
+index 6a24ed6..c9c3640 100644
+--- a/drivers/net/wireless/libertas/assoc.c
++++ b/drivers/net/wireless/libertas/assoc.c
+@@ -1,14 +1,11 @@
+ /* Copyright (C) 2006, Red Hat, Inc. */
+ 
+-#include <linux/bitops.h>
+-#include <net/ieee80211.h>
+ #include <linux/etherdevice.h>
+ 
+ #include "assoc.h"
+-#include "join.h"
+ #include "decl.h"
+-#include "hostcmd.h"
+ #include "host.h"
++#include "scan.h"
+ #include "cmd.h"
+ 
+ 
+@@ -17,6 +14,428 @@ static const u8 bssid_any[ETH_ALEN]  __attribute__ ((aligned (2))) =
+ static const u8 bssid_off[ETH_ALEN]  __attribute__ ((aligned (2))) =
+ 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ 
++/* The firmware needs certain bits masked out of the beacon-derviced capability
++ * field when associating/joining to BSSs.
++ */
++#define CAPINFO_MASK	(~(0xda00))
++
++
++
++/**
++ *  @brief Associate to a specific BSS discovered in a scan
++ *
++ *  @param priv      A pointer to struct lbs_private structure
++ *  @param pbssdesc  Pointer to the BSS descriptor to associate with.
++ *
++ *  @return          0-success, otherwise fail
++ */
++static int lbs_associate(struct lbs_private *priv,
++	struct assoc_request *assoc_req)
++{
++	int ret;
++
++	lbs_deb_enter(LBS_DEB_ASSOC);
++
++	ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
++				    0, CMD_OPTION_WAITFORRSP,
++				    0, assoc_req->bss.bssid);
++
++	if (ret)
++		goto done;
++
++	/* set preamble to firmware */
++	if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
++	    (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
++		priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
++	else
++		priv->preamble = CMD_TYPE_LONG_PREAMBLE;
++
++	lbs_set_radio_control(priv);
++
++	ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
++				    0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
++
++done:
++	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
++	return ret;
++}
++
++/**
++ *  @brief Join an adhoc network found in a previous scan
++ *
++ *  @param priv         A pointer to struct lbs_private structure
++ *  @param pbssdesc     Pointer to a BSS descriptor found in a previous scan
++ *                      to attempt to join
++ *
++ *  @return             0--success, -1--fail
++ */
++static int lbs_join_adhoc_network(struct lbs_private *priv,
++	struct assoc_request *assoc_req)
++{
++	struct bss_descriptor *bss = &assoc_req->bss;
++	int ret = 0;
++
++	lbs_deb_join("current SSID '%s', ssid length %u\n",
++		escape_essid(priv->curbssparams.ssid,
++		priv->curbssparams.ssid_len),
++		priv->curbssparams.ssid_len);
++	lbs_deb_join("requested ssid '%s', ssid length %u\n",
++		escape_essid(bss->ssid, bss->ssid_len),
++		bss->ssid_len);
++
++	/* check if the requested SSID is already joined */
++	if (priv->curbssparams.ssid_len &&
++	    !lbs_ssid_cmp(priv->curbssparams.ssid,
++			priv->curbssparams.ssid_len,
++			bss->ssid, bss->ssid_len) &&
++	    (priv->mode == IW_MODE_ADHOC) &&
++	    (priv->connect_status == LBS_CONNECTED)) {
++		union iwreq_data wrqu;
++
++		lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
++			"current, not attempting to re-join");
++
++		/* Send the re-association event though, because the association
++		 * request really was successful, even if just a null-op.
++		 */
++		memset(&wrqu, 0, sizeof(wrqu));
++		memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
++		       ETH_ALEN);
++		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++		wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
++		goto out;
++	}
++
++	/* Use shortpreamble only when both creator and card supports
++	   short preamble */
++	if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) ||
++	    !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
++		lbs_deb_join("AdhocJoin: Long preamble\n");
++		priv->preamble = CMD_TYPE_LONG_PREAMBLE;
++	} else {
++		lbs_deb_join("AdhocJoin: Short preamble\n");
++		priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
++	}
++
++	lbs_set_radio_control(priv);
++
++	lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
++	lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
++
++	priv->adhoccreate = 0;
++
++	ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
++				    0, CMD_OPTION_WAITFORRSP,
++				    OID_802_11_SSID, assoc_req);
++
++out:
++	return ret;
++}
++
++/**
++ *  @brief Start an Adhoc Network
++ *
++ *  @param priv         A pointer to struct lbs_private structure
++ *  @param adhocssid    The ssid of the Adhoc Network
++ *  @return             0--success, -1--fail
++ */
++static int lbs_start_adhoc_network(struct lbs_private *priv,
++	struct assoc_request *assoc_req)
++{
++	int ret = 0;
++
++	priv->adhoccreate = 1;
++
++	if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
++		lbs_deb_join("AdhocStart: Short preamble\n");
++		priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
++	} else {
++		lbs_deb_join("AdhocStart: Long preamble\n");
++		priv->preamble = CMD_TYPE_LONG_PREAMBLE;
++	}
++
++	lbs_set_radio_control(priv);
++
++	lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
++	lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
++
++	ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
++				    0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
++
++	return ret;
++}
++
++int lbs_stop_adhoc_network(struct lbs_private *priv)
++{
++	return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
++				     0, CMD_OPTION_WAITFORRSP, 0, NULL);
++}
++
++static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
++					struct bss_descriptor *match_bss)
++{
++	if (!secinfo->wep_enabled  && !secinfo->WPAenabled
++	    && !secinfo->WPA2enabled
++	    && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
++	    && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
++	    && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
++		return 1;
++	else
++		return 0;
++}
++
++static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
++				       struct bss_descriptor *match_bss)
++{
++	if (secinfo->wep_enabled && !secinfo->WPAenabled
++	    && !secinfo->WPA2enabled
++	    && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
++		return 1;
++	else
++		return 0;
++}
++
++static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
++				struct bss_descriptor *match_bss)
++{
++	if (!secinfo->wep_enabled && secinfo->WPAenabled
++	    && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
++	    /* privacy bit may NOT be set in some APs like LinkSys WRT54G
++	    && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
++	   )
++		return 1;
++	else
++		return 0;
++}
++
++static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
++				 struct bss_descriptor *match_bss)
++{
++	if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
++	    (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
++	    /* privacy bit may NOT be set in some APs like LinkSys WRT54G
++	    (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
++	   )
++		return 1;
++	else
++		return 0;
++}
++
++static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
++					struct bss_descriptor *match_bss)
++{
++	if (!secinfo->wep_enabled && !secinfo->WPAenabled
++	    && !secinfo->WPA2enabled
++	    && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
++	    && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
++	    && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
++		return 1;
++	else
++		return 0;
++}
++
++/**
++ *  @brief Check if a scanned network compatible with the driver settings
++ *
++ *   WEP     WPA     WPA2    ad-hoc  encrypt                      Network
++ * enabled enabled  enabled   AES     mode   privacy  WPA  WPA2  Compatible
++ *    0       0        0       0      NONE      0      0    0   yes No security
++ *    1       0        0       0      NONE      1      0    0   yes Static WEP
++ *    0       1        0       0       x        1x     1    x   yes WPA
++ *    0       0        1       0       x        1x     x    1   yes WPA2
++ *    0       0        0       1      NONE      1      0    0   yes Ad-hoc AES
++ *    0       0        0       0     !=NONE     1      0    0   yes Dynamic WEP
++ *
++ *
++ *  @param priv A pointer to struct lbs_private
++ *  @param index   Index in scantable to check against current driver settings
++ *  @param mode    Network mode: Infrastructure or IBSS
++ *
++ *  @return        Index in scantable, or error code if negative
++ */
++static int is_network_compatible(struct lbs_private *priv,
++				 struct bss_descriptor *bss, uint8_t mode)
++{
++	int matched = 0;
++
++	lbs_deb_enter(LBS_DEB_SCAN);
++
++	if (bss->mode != mode)
++		goto done;
++
++	matched = match_bss_no_security(&priv->secinfo, bss);
++	if (matched)
++		goto done;
++	matched = match_bss_static_wep(&priv->secinfo, bss);
++	if (matched)
++		goto done;
++	matched = match_bss_wpa(&priv->secinfo, bss);
++	if (matched) {
++		lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
++			     "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
++			     "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
++			     priv->secinfo.wep_enabled ? "e" : "d",
++			     priv->secinfo.WPAenabled ? "e" : "d",
++			     priv->secinfo.WPA2enabled ? "e" : "d",
++			     (bss->capability & WLAN_CAPABILITY_PRIVACY));
++		goto done;
++	}
++	matched = match_bss_wpa2(&priv->secinfo, bss);
++	if (matched) {
++		lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
++			     "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
++			     "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
++			     priv->secinfo.wep_enabled ? "e" : "d",
++			     priv->secinfo.WPAenabled ? "e" : "d",
++			     priv->secinfo.WPA2enabled ? "e" : "d",
++			     (bss->capability & WLAN_CAPABILITY_PRIVACY));
++		goto done;
++	}
++	matched = match_bss_dynamic_wep(&priv->secinfo, bss);
++	if (matched) {
++		lbs_deb_scan("is_network_compatible() dynamic WEP: "
++			     "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
++			     bss->wpa_ie[0], bss->rsn_ie[0],
++			     (bss->capability & WLAN_CAPABILITY_PRIVACY));
++		goto done;
++	}
++
++	/* bss security settings don't match those configured on card */
++	lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
++		     "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
++		     bss->wpa_ie[0], bss->rsn_ie[0],
++		     priv->secinfo.wep_enabled ? "e" : "d",
++		     priv->secinfo.WPAenabled ? "e" : "d",
++		     priv->secinfo.WPA2enabled ? "e" : "d",
++		     (bss->capability & WLAN_CAPABILITY_PRIVACY));
++
++done:
++	lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
++	return matched;
++}
++
++/**
++ *  @brief This function finds a specific compatible BSSID in the scan list
++ *
++ *  Used in association code
++ *
++ *  @param priv  A pointer to struct lbs_private
++ *  @param bssid    BSSID to find in the scan list
++ *  @param mode     Network mode: Infrastructure or IBSS
++ *
++ *  @return         index in BSSID list, or error return code (< 0)
++ */
++static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
++					      uint8_t *bssid, uint8_t mode)
++{
++	struct bss_descriptor *iter_bss;
++	struct bss_descriptor *found_bss = NULL;
++
++	lbs_deb_enter(LBS_DEB_SCAN);
++
++	if (!bssid)
++		goto out;
++
++	lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
++
++	/* Look through the scan table for a compatible match.  The loop will
++	 *   continue past a matched bssid that is not compatible in case there
++	 *   is an AP with multiple SSIDs assigned to the same BSSID
++	 */
++	mutex_lock(&priv->lock);
++	list_for_each_entry(iter_bss, &priv->network_list, list) {
++		if (compare_ether_addr(iter_bss->bssid, bssid))
++			continue; /* bssid doesn't match */
++		switch (mode) {
++		case IW_MODE_INFRA:
++		case IW_MODE_ADHOC:
++			if (!is_network_compatible(priv, iter_bss, mode))
++				break;
++			found_bss = iter_bss;
++			break;
++		default:
++			found_bss = iter_bss;
++			break;
++		}
++	}
++	mutex_unlock(&priv->lock);
++
++out:
++	lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
++	return found_bss;
++}
++
++/**
++ *  @brief This function finds ssid in ssid list.
++ *
++ *  Used in association code
++ *
++ *  @param priv  A pointer to struct lbs_private
++ *  @param ssid     SSID to find in the list
++ *  @param bssid    BSSID to qualify the SSID selection (if provided)
++ *  @param mode     Network mode: Infrastructure or IBSS
++ *
++ *  @return         index in BSSID list
++ */
++static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
++					     uint8_t *ssid, uint8_t ssid_len,
++					     uint8_t *bssid, uint8_t mode,
++					     int channel)
++{
++	u32 bestrssi = 0;
++	struct bss_descriptor *iter_bss = NULL;
++	struct bss_descriptor *found_bss = NULL;
++	struct bss_descriptor *tmp_oldest = NULL;
++
++	lbs_deb_enter(LBS_DEB_SCAN);
++
++	mutex_lock(&priv->lock);
++
++	list_for_each_entry(iter_bss, &priv->network_list, list) {
++		if (!tmp_oldest ||
++		    (iter_bss->last_scanned < tmp_oldest->last_scanned))
++			tmp_oldest = iter_bss;
++
++		if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
++				 ssid, ssid_len) != 0)
++			continue; /* ssid doesn't match */
++		if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
++			continue; /* bssid doesn't match */
++		if ((channel > 0) && (iter_bss->channel != channel))
++			continue; /* channel doesn't match */
++
++		switch (mode) {
++		case IW_MODE_INFRA:
++		case IW_MODE_ADHOC:
++			if (!is_network_compatible(priv, iter_bss, mode))
++				break;
++
++			if (bssid) {
++				/* Found requested BSSID */
++				found_bss = iter_bss;
++				goto out;
++			}
++
++			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
++				bestrssi = SCAN_RSSI(iter_bss->rssi);
++				found_bss = iter_bss;
++			}
++			break;
++		case IW_MODE_AUTO:
++		default:
++			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
++				bestrssi = SCAN_RSSI(iter_bss->rssi);
++				found_bss = iter_bss;
++			}
++			break;
++		}
++	}
++
++out:
++	mutex_unlock(&priv->lock);
++	lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
++	return found_bss;
++}
+ 
+ static int assoc_helper_essid(struct lbs_private *priv,
+                               struct assoc_request * assoc_req)
+@@ -38,7 +457,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
+ 	              escape_essid(assoc_req->ssid, assoc_req->ssid_len));
+ 	if (assoc_req->mode == IW_MODE_INFRA) {
+ 		lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
+-			assoc_req->ssid_len, 0);
++			assoc_req->ssid_len);
+ 
+ 		bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
+ 				assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
+@@ -53,7 +472,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
+ 		 *   scan data will cause us to join a non-existant adhoc network
+ 		 */
+ 		lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
+-			assoc_req->ssid_len, 1);
++			assoc_req->ssid_len);
+ 
+ 		/* Search for the requested SSID in the scan table */
+ 		bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
+@@ -164,34 +583,6 @@ done:
+ 	return ret;
+ }
+ 
+-
+-int lbs_update_channel(struct lbs_private *priv)
+-{
+-	int ret;
+-
+-	/* the channel in f/w could be out of sync; get the current channel */
+-	lbs_deb_enter(LBS_DEB_ASSOC);
+-
+-	ret = lbs_get_channel(priv);
+-	if (ret > 0) {
+-		priv->curbssparams.channel = ret;
+-		ret = 0;
+-	}
+-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+-	return ret;
+-}
+-
+-void lbs_sync_channel(struct work_struct *work)
+-{
+-	struct lbs_private *priv = container_of(work, struct lbs_private,
+-		sync_channel);
+-
+-	lbs_deb_enter(LBS_DEB_ASSOC);
+-	if (lbs_update_channel(priv))
+-		lbs_pr_info("Channel synchronization failed.");
+-	lbs_deb_leave(LBS_DEB_ASSOC);
+-}
+-
+ static int assoc_helper_channel(struct lbs_private *priv,
+                                 struct assoc_request * assoc_req)
+ {
+@@ -279,13 +670,11 @@ static int assoc_helper_wep_keys(struct lbs_private *priv,
+ 
+ 	/* enable/disable the MAC's WEP packet filter */
+ 	if (assoc_req->secinfo.wep_enabled)
+-		priv->currentpacketfilter |= CMD_ACT_MAC_WEP_ENABLE;
++		priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
+ 	else
+-		priv->currentpacketfilter &= ~CMD_ACT_MAC_WEP_ENABLE;
++		priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
+ 
+-	ret = lbs_set_mac_packet_filter(priv);
+-	if (ret)
+-		goto out;
++	lbs_set_mac_control(priv);
+ 
+ 	mutex_lock(&priv->lock);
+ 
+@@ -315,9 +704,7 @@ static int assoc_helper_secinfo(struct lbs_private *priv,
+ 	memcpy(&priv->secinfo, &assoc_req->secinfo,
+ 		sizeof(struct lbs_802_11_security));
+ 
+-	ret = lbs_set_mac_packet_filter(priv);
+-	if (ret)
+-		goto out;
++	lbs_set_mac_control(priv);
+ 
+ 	/* If RSN is already enabled, don't try to enable it again, since
+ 	 * ENABLE_RSN resets internal state machines and will clobber the
+@@ -360,11 +747,7 @@ static int assoc_helper_wpa_keys(struct lbs_private *priv,
+ 
+ 	if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
+ 		clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
+-		ret = lbs_prepare_and_send_command(priv,
+-					CMD_802_11_KEY_MATERIAL,
+-					CMD_ACT_SET,
+-					CMD_OPTION_WAITFORRSP,
+-					0, assoc_req);
++		ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
+ 		assoc_req->flags = flags;
+ 	}
+ 
+@@ -374,11 +757,7 @@ static int assoc_helper_wpa_keys(struct lbs_private *priv,
+ 	if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
+ 		clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
+ 
+-		ret = lbs_prepare_and_send_command(priv,
+-					CMD_802_11_KEY_MATERIAL,
+-					CMD_ACT_SET,
+-					CMD_OPTION_WAITFORRSP,
+-					0, assoc_req);
++		ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
+ 		assoc_req->flags = flags;
+ 	}
+ 
+@@ -413,11 +792,10 @@ static int should_deauth_infrastructure(struct lbs_private *priv,
+ {
+ 	int ret = 0;
+ 
+-	lbs_deb_enter(LBS_DEB_ASSOC);
+-
+ 	if (priv->connect_status != LBS_CONNECTED)
+ 		return 0;
+ 
++	lbs_deb_enter(LBS_DEB_ASSOC);
+ 	if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
+ 		lbs_deb_assoc("Deauthenticating due to new SSID\n");
+ 		ret = 1;
+@@ -456,7 +834,7 @@ static int should_deauth_infrastructure(struct lbs_private *priv,
+ 
+ out:
+ 	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+-	return 0;
++	return ret;
+ }
+ 
+ 
+@@ -489,6 +867,91 @@ static int should_stop_adhoc(struct lbs_private *priv,
+ }
+ 
+ 
++/**
++ *  @brief This function finds the best SSID in the Scan List
++ *
++ *  Search the scan table for the best SSID that also matches the current
++ *   adapter network preference (infrastructure or adhoc)
++ *
++ *  @param priv  A pointer to struct lbs_private
++ *
++ *  @return         index in BSSID list
++ */
++static struct bss_descriptor *lbs_find_best_ssid_in_list(
++	struct lbs_private *priv, uint8_t mode)
++{
++	uint8_t bestrssi = 0;
++	struct bss_descriptor *iter_bss;
++	struct bss_descriptor *best_bss = NULL;
++
++	lbs_deb_enter(LBS_DEB_SCAN);
++
++	mutex_lock(&priv->lock);
++
++	list_for_each_entry(iter_bss, &priv->network_list, list) {
++		switch (mode) {
++		case IW_MODE_INFRA:
++		case IW_MODE_ADHOC:
++			if (!is_network_compatible(priv, iter_bss, mode))
++				break;
++			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
++				break;
++			bestrssi = SCAN_RSSI(iter_bss->rssi);
++			best_bss = iter_bss;
++			break;
++		case IW_MODE_AUTO:
++		default:
++			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
++				break;
++			bestrssi = SCAN_RSSI(iter_bss->rssi);
++			best_bss = iter_bss;
++			break;
++		}
++	}
++
++	mutex_unlock(&priv->lock);
++	lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
++	return best_bss;
++}
++
++/**
++ *  @brief Find the best AP
++ *
++ *  Used from association worker.
++ *
++ *  @param priv         A pointer to struct lbs_private structure
++ *  @param pSSID        A pointer to AP's ssid
++ *
++ *  @return             0--success, otherwise--fail
++ */
++static int lbs_find_best_network_ssid(struct lbs_private *priv,
++	uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode,
++	uint8_t *out_mode)
++{
++	int ret = -1;
++	struct bss_descriptor *found;
++
++	lbs_deb_enter(LBS_DEB_SCAN);
++
++	priv->scan_ssid_len = 0;
++	lbs_scan_networks(priv, 1);
++	if (priv->surpriseremoved)
++		goto out;
++
++	found = lbs_find_best_ssid_in_list(priv, preferred_mode);
++	if (found && (found->ssid_len > 0)) {
++		memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
++		*out_ssid_len = found->ssid_len;
++		*out_mode = found->mode;
++		ret = 0;
++	}
++
++out:
++	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
++	return ret;
++}
++
++
+ void lbs_association_worker(struct work_struct *work)
+ {
+ 	struct lbs_private *priv = container_of(work, struct lbs_private,
+@@ -643,17 +1106,11 @@ void lbs_association_worker(struct work_struct *work)
+ 		}
+ 
+ 		if (success) {
+-			lbs_deb_assoc("ASSOC: associated to '%s', %s\n",
+-				escape_essid(priv->curbssparams.ssid,
+-				             priv->curbssparams.ssid_len),
++			lbs_deb_assoc("associated to %s\n",
+ 				print_mac(mac, priv->curbssparams.bssid));
+ 			lbs_prepare_and_send_command(priv,
+ 				CMD_802_11_RSSI,
+ 				0, CMD_OPTION_WAITFORRSP, 0, NULL);
+-
+-			lbs_prepare_and_send_command(priv,
+-				CMD_802_11_GET_LOG,
+-				0, CMD_OPTION_WAITFORRSP, 0, NULL);
+ 		} else {
+ 			ret = -1;
+ 		}
+@@ -752,3 +1209,705 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
+ 	lbs_deb_leave(LBS_DEB_ASSOC);
+ 	return assoc_req;
+ }
++
++
++/**
++ *  @brief This function finds common rates between rate1 and card rates.
++ *
++ * It will fill common rates in rate1 as output if found.
++ *
++ * NOTE: Setting the MSB of the basic rates need to be taken
++ *   care, either before or after calling this function
++ *
++ *  @param priv     A pointer to struct lbs_private structure
++ *  @param rate1       the buffer which keeps input and output
++ *  @param rate1_size  the size of rate1 buffer; new size of buffer on return
++ *
++ *  @return            0 or -1
++ */
++static int get_common_rates(struct lbs_private *priv,
++	u8 *rates,
++	u16 *rates_size)
++{
++	u8 *card_rates = lbs_bg_rates;
++	size_t num_card_rates = sizeof(lbs_bg_rates);
++	int ret = 0, i, j;
++	u8 tmp[30];
++	size_t tmp_size = 0;
++
++	/* For each rate in card_rates that exists in rate1, copy to tmp */
++	for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
++		for (j = 0; rates[j] && (j < *rates_size); j++) {
++			if (rates[j] == card_rates[i])
++				tmp[tmp_size++] = card_rates[i];
++		}
++	}
++
++	lbs_deb_hex(LBS_DEB_JOIN, "AP rates    ", rates, *rates_size);
++	lbs_deb_hex(LBS_DEB_JOIN, "card rates  ", card_rates, num_card_rates);
++	lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
++	lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
++
++	if (!priv->auto_rate) {
++		for (i = 0; i < tmp_size; i++) {
++			if (tmp[i] == priv->cur_rate)
++				goto done;
++		}
++		lbs_pr_alert("Previously set fixed data rate %#x isn't "
++		       "compatible with the network.\n", priv->cur_rate);
++		ret = -1;
++		goto done;
++	}
++	ret = 0;
++
++done:
++	memset(rates, 0, *rates_size);
++	*rates_size = min_t(int, tmp_size, *rates_size);
++	memcpy(rates, tmp, *rates_size);
++	return ret;
++}
++
++
++/**
++ *  @brief Sets the MSB on basic rates as the firmware requires
++ *
++ * Scan through an array and set the MSB for basic data rates.
++ *
++ *  @param rates     buffer of data rates
++ *  @param len       size of buffer
++ */
++static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
++{
++	int i;
++
++	for (i = 0; i < len; i++) {
++		if (rates[i] == 0x02 || rates[i] == 0x04 ||
++		    rates[i] == 0x0b || rates[i] == 0x16)
++			rates[i] |= 0x80;
++	}
++}
++
++/**
++ *  @brief Send Deauthentication Request
++ *
++ *  @param priv      A pointer to struct lbs_private structure
++ *  @return          0--success, -1--fail
++ */
++int lbs_send_deauthentication(struct lbs_private *priv)
++{
++	return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
++				     0, CMD_OPTION_WAITFORRSP, 0, NULL);
++}
++
++/**
++ *  @brief This function prepares command of authenticate.
++ *
++ *  @param priv      A pointer to struct lbs_private structure
++ *  @param cmd       A pointer to cmd_ds_command structure
++ *  @param pdata_buf Void cast of pointer to a BSSID to authenticate with
++ *
++ *  @return         0 or -1
++ */
++int lbs_cmd_80211_authenticate(struct lbs_private *priv,
++				 struct cmd_ds_command *cmd,
++				 void *pdata_buf)
++{
++	struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
++	int ret = -1;
++	u8 *bssid = pdata_buf;
++	DECLARE_MAC_BUF(mac);
++
++	lbs_deb_enter(LBS_DEB_JOIN);
++
++	cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
++	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
++			+ S_DS_GEN);
++
++	/* translate auth mode to 802.11 defined wire value */
++	switch (priv->secinfo.auth_mode) {
++	case IW_AUTH_ALG_OPEN_SYSTEM:
++		pauthenticate->authtype = 0x00;
++		break;
++	case IW_AUTH_ALG_SHARED_KEY:
++		pauthenticate->authtype = 0x01;
++		break;
++	case IW_AUTH_ALG_LEAP:
++		pauthenticate->authtype = 0x80;
++		break;
++	default:
++		lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
++			priv->secinfo.auth_mode);
++		goto out;
++	}
++
++	memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
++
++	lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
++		print_mac(mac, bssid), pauthenticate->authtype);
++	ret = 0;
++
++out:
++	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
++	return ret;
++}
++
++int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
++				   struct cmd_ds_command *cmd)
++{
++	struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
++
++	lbs_deb_enter(LBS_DEB_JOIN);
++
++	cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
++	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
++			     S_DS_GEN);
++
++	/* set AP MAC address */
++	memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
++
++	/* Reason code 3 = Station is leaving */
++#define REASON_CODE_STA_LEAVING 3
++	dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
++
++	lbs_deb_leave(LBS_DEB_JOIN);
++	return 0;
++}
++
++int lbs_cmd_80211_associate(struct lbs_private *priv,
++			      struct cmd_ds_command *cmd, void *pdata_buf)
++{
++	struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
++	int ret = 0;
++	struct assoc_request *assoc_req = pdata_buf;
++	struct bss_descriptor *bss = &assoc_req->bss;
++	u8 *pos;
++	u16 tmpcap, tmplen;
++	struct mrvlietypes_ssidparamset *ssid;
++	struct mrvlietypes_phyparamset *phy;
++	struct mrvlietypes_ssparamset *ss;
++	struct mrvlietypes_ratesparamset *rates;
++	struct mrvlietypes_rsnparamset *rsn;
++
++	lbs_deb_enter(LBS_DEB_ASSOC);
++
++	pos = (u8 *) passo;
++
++	if (!priv) {
++		ret = -1;
++		goto done;
++	}
++
++	cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
++
++	memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
++	pos += sizeof(passo->peerstaaddr);
++
++	/* set the listen interval */
++	passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
++
++	pos += sizeof(passo->capability);
++	pos += sizeof(passo->listeninterval);
++	pos += sizeof(passo->bcnperiod);
++	pos += sizeof(passo->dtimperiod);
++
++	ssid = (struct mrvlietypes_ssidparamset *) pos;
++	ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
++	tmplen = bss->ssid_len;
++	ssid->header.len = cpu_to_le16(tmplen);
++	memcpy(ssid->ssid, bss->ssid, tmplen);
++	pos += sizeof(ssid->header) + tmplen;
++
++	phy = (struct mrvlietypes_phyparamset *) pos;
++	phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
++	tmplen = sizeof(phy->fh_ds.dsparamset);
++	phy->header.len = cpu_to_le16(tmplen);
++	memcpy(&phy->fh_ds.dsparamset,
++	       &bss->phyparamset.dsparamset.currentchan,
++	       tmplen);
++	pos += sizeof(phy->header) + tmplen;
++
++	ss = (struct mrvlietypes_ssparamset *) pos;
++	ss->header.type = cpu_to_le16(TLV_TYPE_CF);
++	tmplen = sizeof(ss->cf_ibss.cfparamset);
++	ss->header.len = cpu_to_le16(tmplen);
++	pos += sizeof(ss->header) + tmplen;
++
++	rates = (struct mrvlietypes_ratesparamset *) pos;
++	rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
++	memcpy(&rates->rates, &bss->rates, MAX_RATES);
++	tmplen = MAX_RATES;
++	if (get_common_rates(priv, rates->rates, &tmplen)) {
++		ret = -1;
++		goto done;
++	}
++	pos += sizeof(rates->header) + tmplen;
++	rates->header.len = cpu_to_le16(tmplen);
++	lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
++
++	/* Copy the infra. association rates into Current BSS state structure */
++	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
++	memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
++
++	/* Set MSB on basic rates as the firmware requires, but _after_
++	 * copying to current bss rates.
++	 */
++	lbs_set_basic_rate_flags(rates->rates, tmplen);
++
++	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
++		rsn = (struct mrvlietypes_rsnparamset *) pos;
++		/* WPA_IE or WPA2_IE */
++		rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
++		tmplen = (u16) assoc_req->wpa_ie[1];
++		rsn->header.len = cpu_to_le16(tmplen);
++		memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
++		lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
++			sizeof(rsn->header) + tmplen);
++		pos += sizeof(rsn->header) + tmplen;
++	}
++
++	/* update curbssparams */
++	priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
++
++	if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
++		ret = -1;
++		goto done;
++	}
++
++	cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
++
++	/* set the capability info */
++	tmpcap = (bss->capability & CAPINFO_MASK);
++	if (bss->mode == IW_MODE_INFRA)
++		tmpcap |= WLAN_CAPABILITY_ESS;
++	passo->capability = cpu_to_le16(tmpcap);
++	lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
++
++done:
++	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
++	return ret;
++}
++
++int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
++				 struct cmd_ds_command *cmd, void *pdata_buf)
++{
++	struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
++	int ret = 0;
++	int cmdappendsize = 0;
++	struct assoc_request *assoc_req = pdata_buf;
++	u16 tmpcap = 0;
++	size_t ratesize = 0;
++
++	lbs_deb_enter(LBS_DEB_JOIN);
++
++	if (!priv) {
++		ret = -1;
++		goto done;
++	}
++
++	cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
++
++	/*
++	 * Fill in the parameters for 2 data structures:
++	 *   1. cmd_ds_802_11_ad_hoc_start command
++	 *   2. priv->scantable[i]
++	 *
++	 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
++	 *   probe delay, and cap info.
++	 *
++	 * Firmware will fill up beacon period, DTIM, Basic rates
++	 *   and operational rates.
++	 */
++
++	memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
++	memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
++
++	lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
++		escape_essid(assoc_req->ssid, assoc_req->ssid_len),
++		assoc_req->ssid_len);
++
++	/* set the BSS type */
++	adhs->bsstype = CMD_BSS_TYPE_IBSS;
++	priv->mode = IW_MODE_ADHOC;
++	if (priv->beacon_period == 0)
++		priv->beacon_period = MRVDRV_BEACON_INTERVAL;
++	adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
++
++	/* set Physical param set */
++#define DS_PARA_IE_ID   3
++#define DS_PARA_IE_LEN  1
++
++	adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
++	adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
++
++	WARN_ON(!assoc_req->channel);
++
++	lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
++		     assoc_req->channel);
++
++	adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
++
++	/* set IBSS param set */
++#define IBSS_PARA_IE_ID   6
++#define IBSS_PARA_IE_LEN  2
++
++	adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
++	adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
++	adhs->ssparamset.ibssparamset.atimwindow = 0;
++
++	/* set capability info */
++	tmpcap = WLAN_CAPABILITY_IBSS;
++	if (assoc_req->secinfo.wep_enabled) {
++		lbs_deb_join("ADHOC_S_CMD: WEP enabled, "
++			"setting privacy on\n");
++		tmpcap |= WLAN_CAPABILITY_PRIVACY;
++	} else {
++		lbs_deb_join("ADHOC_S_CMD: WEP disabled, "
++			"setting privacy off\n");
++	}
++	adhs->capability = cpu_to_le16(tmpcap);
++
++	/* probedelay */
++	adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
++
++	memset(adhs->rates, 0, sizeof(adhs->rates));
++	ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
++	memcpy(adhs->rates, lbs_bg_rates, ratesize);
++
++	/* Copy the ad-hoc creating rates into Current BSS state structure */
++	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
++	memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
++
++	/* Set MSB on basic rates as the firmware requires, but _after_
++	 * copying to current bss rates.
++	 */
++	lbs_set_basic_rate_flags(adhs->rates, ratesize);
++
++	lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
++	       adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
++
++	lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
++
++	if (lbs_create_dnld_countryinfo_11d(priv)) {
++		lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
++		ret = -1;
++		goto done;
++	}
++
++	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
++				S_DS_GEN + cmdappendsize);
++
++	ret = 0;
++done:
++	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
++	return ret;
++}
++
++int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd)
++{
++	cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
++	cmd->size = cpu_to_le16(S_DS_GEN);
++
++	return 0;
++}
++
++int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
++				struct cmd_ds_command *cmd, void *pdata_buf)
++{
++	struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
++	struct assoc_request *assoc_req = pdata_buf;
++	struct bss_descriptor *bss = &assoc_req->bss;
++	int cmdappendsize = 0;
++	int ret = 0;
++	u16 ratesize = 0;
++	DECLARE_MAC_BUF(mac);
++
++	lbs_deb_enter(LBS_DEB_JOIN);
++
++	cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
++
++	join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
++	join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
++
++	memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
++	memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
++
++	memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
++	       sizeof(union ieeetypes_phyparamset));
++
++	memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
++	       sizeof(union IEEEtypes_ssparamset));
++
++	join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
++	lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
++	       bss->capability, CAPINFO_MASK);
++
++	/* information on BSSID descriptor passed to FW */
++	lbs_deb_join(
++	       "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
++	       print_mac(mac, join_cmd->bss.bssid),
++	       join_cmd->bss.ssid);
++
++	/* failtimeout */
++	join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
++
++	/* probedelay */
++	join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
++
++	priv->curbssparams.channel = bss->channel;
++
++	/* Copy Data rates from the rates recorded in scan response */
++	memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
++	ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
++	memcpy(join_cmd->bss.rates, bss->rates, ratesize);
++	if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
++		lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
++		ret = -1;
++		goto done;
++	}
++
++	/* Copy the ad-hoc creating rates into Current BSS state structure */
++	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
++	memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
++
++	/* Set MSB on basic rates as the firmware requires, but _after_
++	 * copying to current bss rates.
++	 */
++	lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
++
++	join_cmd->bss.ssparamset.ibssparamset.atimwindow =
++	    cpu_to_le16(bss->atimwindow);
++
++	if (assoc_req->secinfo.wep_enabled) {
++		u16 tmp = le16_to_cpu(join_cmd->bss.capability);
++		tmp |= WLAN_CAPABILITY_PRIVACY;
++		join_cmd->bss.capability = cpu_to_le16(tmp);
++	}
++
++	if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
++		/* wake up first */
++		__le32 Localpsmode;
++
++		Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
++		ret = lbs_prepare_and_send_command(priv,
++					    CMD_802_11_PS_MODE,
++					    CMD_ACT_SET,
++					    0, 0, &Localpsmode);
++
++		if (ret) {
++			ret = -1;
++			goto done;
++		}
++	}
++
++	if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
++		ret = -1;
++		goto done;
++	}
++
++	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
++				S_DS_GEN + cmdappendsize);
++
++done:
++	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
++	return ret;
++}
++
++int lbs_ret_80211_associate(struct lbs_private *priv,
++			      struct cmd_ds_command *resp)
++{
++	int ret = 0;
++	union iwreq_data wrqu;
++	struct ieeetypes_assocrsp *passocrsp;
++	struct bss_descriptor *bss;
++	u16 status_code;
++
++	lbs_deb_enter(LBS_DEB_ASSOC);
++
++	if (!priv->in_progress_assoc_req) {
++		lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
++		ret = -1;
++		goto done;
++	}
++	bss = &priv->in_progress_assoc_req->bss;
++
++	passocrsp = (struct ieeetypes_assocrsp *) &resp->params;
++
++	/*
++	 * Older FW versions map the IEEE 802.11 Status Code in the association
++	 * response to the following values returned in passocrsp->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)
++	 */
++
++	status_code = le16_to_cpu(passocrsp->statuscode);
++	switch (status_code) {
++	case 0x00:
++		break;
++	case 0x01:
++		lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
++		break;
++	case 0x02:
++		lbs_deb_assoc("ASSOC_RESP: internal timer "
++			"expired while waiting for the AP\n");
++		break;
++	case 0x03:
++		lbs_deb_assoc("ASSOC_RESP: association "
++			"refused by AP\n");
++		break;
++	case 0x04:
++		lbs_deb_assoc("ASSOC_RESP: authentication "
++			"refused by AP\n");
++		break;
++	default:
++		lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
++			" unknown\n", status_code);
++		break;
++	}
++
++	if (status_code) {
++		lbs_mac_event_disconnected(priv);
++		ret = -1;
++		goto done;
++	}
++
++	lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
++		le16_to_cpu(resp->size) - S_DS_GEN);
++
++	/* Send a Media Connected event, according to the Spec */
++	priv->connect_status = LBS_CONNECTED;
++
++	/* Update current SSID and BSSID */
++	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
++	priv->curbssparams.ssid_len = bss->ssid_len;
++	memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
++
++	priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
++	priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
++
++	memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
++	memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
++	priv->nextSNRNF = 0;
++	priv->numSNRNF = 0;
++
++	netif_carrier_on(priv->dev);
++	if (!priv->tx_pending_len)
++		netif_wake_queue(priv->dev);
++
++	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
++	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
++
++done:
++	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
++	return ret;
++}
++
++int lbs_ret_80211_disassociate(struct lbs_private *priv)
++{
++	lbs_deb_enter(LBS_DEB_JOIN);
++
++	lbs_mac_event_disconnected(priv);
++
++	lbs_deb_leave(LBS_DEB_JOIN);
++	return 0;
++}
++
++int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
++				 struct cmd_ds_command *resp)
++{
++	int ret = 0;
++	u16 command = le16_to_cpu(resp->command);
++	u16 result = le16_to_cpu(resp->result);
++	struct cmd_ds_802_11_ad_hoc_result *padhocresult;
++	union iwreq_data wrqu;
++	struct bss_descriptor *bss;
++	DECLARE_MAC_BUF(mac);
++
++	lbs_deb_enter(LBS_DEB_JOIN);
++
++	padhocresult = &resp->params.result;
++
++	lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
++	lbs_deb_join("ADHOC_RESP: command = %x\n", command);
++	lbs_deb_join("ADHOC_RESP: result = %x\n", result);
++
++	if (!priv->in_progress_assoc_req) {
++		lbs_deb_join("ADHOC_RESP: no in-progress association "
++			"request\n");
++		ret = -1;
++		goto done;
++	}
++	bss = &priv->in_progress_assoc_req->bss;
++
++	/*
++	 * Join result code 0 --> SUCCESS
++	 */
++	if (result) {
++		lbs_deb_join("ADHOC_RESP: failed\n");
++		if (priv->connect_status == LBS_CONNECTED)
++			lbs_mac_event_disconnected(priv);
++		ret = -1;
++		goto done;
++	}
++
++	/*
++	 * Now the join cmd should be successful
++	 * If BSSID has changed use SSID to compare instead of BSSID
++	 */
++	lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
++		escape_essid(bss->ssid, bss->ssid_len));
++
++	/* Send a Media Connected event, according to the Spec */
++	priv->connect_status = LBS_CONNECTED;
++
++	if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
++		/* Update the created network descriptor with the new BSSID */
++		memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
++	}
++
++	/* Set the BSSID from the joined/started descriptor */
++	memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
++
++	/* Set the new SSID to current SSID */
++	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
++	priv->curbssparams.ssid_len = bss->ssid_len;
++
++	netif_carrier_on(priv->dev);
++	if (!priv->tx_pending_len)
++		netif_wake_queue(priv->dev);
++
++	memset(&wrqu, 0, sizeof(wrqu));
++	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
++	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
++
++	lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
++	lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
++	lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
++		     print_mac(mac, padhocresult->bssid));
++
++done:
++	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
++	return ret;
++}
++
++int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv)
++{
++	lbs_deb_enter(LBS_DEB_JOIN);
++
++	lbs_mac_event_disconnected(priv);
++
++	lbs_deb_leave(LBS_DEB_JOIN);
++	return 0;
++}
+diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
+index 08372bb..c516fbe 100644
+--- a/drivers/net/wireless/libertas/assoc.h
++++ b/drivers/net/wireless/libertas/assoc.h
+@@ -7,6 +7,33 @@
+ 
+ void lbs_association_worker(struct work_struct *work);
+ struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
+-void lbs_sync_channel(struct work_struct *work);
++
++struct cmd_ds_command;
++int lbs_cmd_80211_authenticate(struct lbs_private *priv,
++					struct cmd_ds_command *cmd,
++					void *pdata_buf);
++int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
++				       struct cmd_ds_command *cmd,
++				       void *pdata_buf);
++int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd);
++int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
++					struct cmd_ds_command *cmd,
++					void *pdata_buf);
++int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
++					  struct cmd_ds_command *cmd);
++int lbs_cmd_80211_associate(struct lbs_private *priv,
++				     struct cmd_ds_command *cmd,
++				     void *pdata_buf);
++
++int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
++					struct cmd_ds_command *resp);
++int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv);
++int lbs_ret_80211_disassociate(struct lbs_private *priv);
++int lbs_ret_80211_associate(struct lbs_private *priv,
++				     struct cmd_ds_command *resp);
++
++int lbs_stop_adhoc_network(struct lbs_private *priv);
++
++int lbs_send_deauthentication(struct lbs_private *priv);
+ 
+ #endif /* _LBS_ASSOC_H */
+diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
+index b3c1acb..6328b95 100644
+--- a/drivers/net/wireless/libertas/cmd.c
++++ b/drivers/net/wireless/libertas/cmd.c
+@@ -4,19 +4,57 @@
+   */
+ 
+ #include <net/iw_handler.h>
++#include <linux/kfifo.h>
+ #include "host.h"
+ #include "hostcmd.h"
+ #include "decl.h"
+ #include "defs.h"
+ #include "dev.h"
+-#include "join.h"
++#include "assoc.h"
+ #include "wext.h"
+ #include "cmd.h"
+ 
+ static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
+-static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
+-		    struct cmd_ctrl_node *ptempnode,
+-		    void *pdata_buf);
++
++
++/**
++ *  @brief Simple callback that copies response back into command
++ *
++ *  @param priv    	A pointer to struct lbs_private structure
++ *  @param extra  	A pointer to the original command structure for which
++ *                      'resp' is a response
++ *  @param resp         A pointer to the command response
++ *
++ *  @return 	   	0 on success, error on failure
++ */
++int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
++		     struct cmd_header *resp)
++{
++	struct cmd_header *buf = (void *)extra;
++	uint16_t copy_len;
++
++	copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
++	memcpy(buf, resp, copy_len);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
++
++/**
++ *  @brief Simple callback that ignores the result. Use this if
++ *  you just want to send a command to the hardware, but don't
++ *  care for the result.
++ *
++ *  @param priv         ignored
++ *  @param extra        ignored
++ *  @param resp         ignored
++ *
++ *  @return 	   	0 for success
++ */
++static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,
++		     struct cmd_header *resp)
++{
++	return 0;
++}
+ 
+ 
+ /**
+@@ -143,8 +181,7 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria)
+ }
+ EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
+ 
+-static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv,
+-				   struct cmd_ds_command *cmd,
++static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
+ 				   u16 cmd_action)
+ {
+ 	struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
+@@ -259,6 +296,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
+ 
+ 	lbs_deb_enter(LBS_DEB_CMD);
+ 
++	memset(&cmd, 0, sizeof(cmd));
+ 	cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
+ 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ 
+@@ -322,7 +360,9 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+ 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ 	cmd.action = cpu_to_le16(cmd_action);
+ 
+-	if (cmd_action == CMD_ACT_SET) {
++	if (cmd_action == CMD_ACT_GET)
++		cmd.enable = 0;
++	else {
+ 		if (*enable)
+ 			cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
+ 		else
+@@ -338,81 +378,108 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+ 	return ret;
+ }
+ 
+-static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
+-                            struct enc_key * pkey)
++static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
++                            struct enc_key *key)
+ {
+ 	lbs_deb_enter(LBS_DEB_CMD);
+ 
+-	if (pkey->flags & KEY_INFO_WPA_ENABLED) {
+-		pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
+-	}
+-	if (pkey->flags & KEY_INFO_WPA_UNICAST) {
+-		pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
+-	}
+-	if (pkey->flags & KEY_INFO_WPA_MCAST) {
+-		pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
+-	}
++	if (key->flags & KEY_INFO_WPA_ENABLED)
++		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
++	if (key->flags & KEY_INFO_WPA_UNICAST)
++		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
++	if (key->flags & KEY_INFO_WPA_MCAST)
++		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
+ 
+-	pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
+-	pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
+-	pkeyparamset->keylen = cpu_to_le16(pkey->len);
+-	memcpy(pkeyparamset->key, pkey->key, pkey->len);
+-	pkeyparamset->length = cpu_to_le16(  sizeof(pkeyparamset->keytypeid)
+-	                                        + sizeof(pkeyparamset->keyinfo)
+-	                                        + sizeof(pkeyparamset->keylen)
+-	                                        + sizeof(pkeyparamset->key));
++	keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
++	keyparam->keytypeid = cpu_to_le16(key->type);
++	keyparam->keylen = cpu_to_le16(key->len);
++	memcpy(keyparam->key, key->key, key->len);
++
++	/* Length field doesn't include the {type,length} header */
++	keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
+ 	lbs_deb_leave(LBS_DEB_CMD);
+ }
+ 
+-static int lbs_cmd_802_11_key_material(struct lbs_private *priv,
+-					struct cmd_ds_command *cmd,
+-					u16 cmd_action,
+-					u32 cmd_oid, void *pdata_buf)
++int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
++				struct assoc_request *assoc)
+ {
+-	struct cmd_ds_802_11_key_material *pkeymaterial =
+-	    &cmd->params.keymaterial;
+-	struct assoc_request * assoc_req = pdata_buf;
++	struct cmd_ds_802_11_key_material cmd;
+ 	int ret = 0;
+ 	int index = 0;
+ 
+ 	lbs_deb_enter(LBS_DEB_CMD);
+ 
+-	cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL);
+-	pkeymaterial->action = cpu_to_le16(cmd_action);
++	cmd.action = cpu_to_le16(cmd_action);
++	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ 
+ 	if (cmd_action == CMD_ACT_GET) {
+-		cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
+-		ret = 0;
+-		goto done;
+-	}
++		cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2);
++	} else {
++		memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
+ 
+-	memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
++		if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
++			set_one_wpa_key(&cmd.keyParamSet[index],
++					&assoc->wpa_unicast_key);
++			index++;
++		}
+ 
+-	if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
+-		set_one_wpa_key(&pkeymaterial->keyParamSet[index],
+-		                &assoc_req->wpa_unicast_key);
+-		index++;
+-	}
++		if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
++			set_one_wpa_key(&cmd.keyParamSet[index],
++					&assoc->wpa_mcast_key);
++			index++;
++		}
+ 
+-	if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
+-		set_one_wpa_key(&pkeymaterial->keyParamSet[index],
+-		                &assoc_req->wpa_mcast_key);
+-		index++;
++		/* The common header and as many keys as we included */
++		cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
++						    keyParamSet[index]));
+ 	}
++	ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
++	/* Copy the returned key to driver private data */
++	if (!ret && cmd_action == CMD_ACT_GET) {
++		void *buf_ptr = cmd.keyParamSet;
++		void *resp_end = &(&cmd)[1];
++
++		while (buf_ptr < resp_end) {
++			struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
++			struct enc_key *key;
++			uint16_t param_set_len = le16_to_cpu(keyparam->length);
++			uint16_t key_len = le16_to_cpu(keyparam->keylen);
++			uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
++			uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
++			void *end;
++
++			end = (void *)keyparam + sizeof(keyparam->type)
++				+ sizeof(keyparam->length) + param_set_len;
++
++			/* Make sure we don't access past the end of the IEs */
++			if (end > resp_end)
++				break;
++
++			if (key_flags & KEY_INFO_WPA_UNICAST)
++				key = &priv->wpa_unicast_key;
++			else if (key_flags & KEY_INFO_WPA_MCAST)
++				key = &priv->wpa_mcast_key;
++			else
++				break;
+ 
+-	cmd->size = cpu_to_le16(  S_DS_GEN
+-	                        + sizeof (pkeymaterial->action)
+-	                        + (index * sizeof(struct MrvlIEtype_keyParamSet)));
++			/* Copy returned key into driver */
++			memset(key, 0, sizeof(struct enc_key));
++			if (key_len > sizeof(key->key))
++				break;
++			key->type = key_type;
++			key->flags = key_flags;
++			key->len = key_len;
++			memcpy(key->key, keyparam->key, key->len);
+ 
+-	ret = 0;
++			buf_ptr = end + 1;
++		}
++	}
+ 
+-done:
+ 	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ 	return ret;
+ }
+ 
+-static int lbs_cmd_802_11_reset(struct lbs_private *priv,
+-				 struct cmd_ds_command *cmd, int cmd_action)
++static int lbs_cmd_802_11_reset(struct cmd_ds_command *cmd, int cmd_action)
+ {
+ 	struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
+ 
+@@ -426,30 +493,6 @@ static int lbs_cmd_802_11_reset(struct lbs_private *priv,
+ 	return 0;
+ }
+ 
+-static int lbs_cmd_802_11_get_log(struct lbs_private *priv,
+-				   struct cmd_ds_command *cmd)
+-{
+-	lbs_deb_enter(LBS_DEB_CMD);
+-	cmd->command = cpu_to_le16(CMD_802_11_GET_LOG);
+-	cmd->size =
+-		cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN);
+-
+-	lbs_deb_leave(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+-static int lbs_cmd_802_11_get_stat(struct lbs_private *priv,
+-				    struct cmd_ds_command *cmd)
+-{
+-	lbs_deb_enter(LBS_DEB_CMD);
+-	cmd->command = cpu_to_le16(CMD_802_11_GET_STAT);
+-	cmd->size =
+-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
+-
+-	lbs_deb_leave(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+ static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
+ 				    struct cmd_ds_command *cmd,
+ 				    int cmd_action,
+@@ -570,8 +613,7 @@ static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
+ 	return 0;
+ }
+ 
+-static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv,
+-				       struct cmd_ds_command *cmd,
++static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd,
+ 				       u16 cmd_action, void *pdata_buf)
+ {
+ 
+@@ -614,8 +656,7 @@ static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv,
+ 	return 0;
+ }
+ 
+-static int lbs_cmd_802_11_monitor_mode(struct lbs_private *priv,
+-				      struct cmd_ds_command *cmd,
++static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
+ 				      u16 cmd_action, void *pdata_buf)
+ {
+ 	struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
+@@ -773,6 +814,7 @@ int lbs_get_channel(struct lbs_private *priv)
+ 
+ 	lbs_deb_enter(LBS_DEB_CMD);
+ 
++	memset(&cmd, 0, sizeof(cmd));
+ 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ 	cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
+ 
+@@ -788,6 +830,22 @@ out:
+ 	return ret;
+ }
+ 
++int lbs_update_channel(struct lbs_private *priv)
++{
++	int ret;
++
++	/* the channel in f/w could be out of sync; get the current channel */
++	lbs_deb_enter(LBS_DEB_ASSOC);
++
++	ret = lbs_get_channel(priv);
++	if (ret > 0) {
++		priv->curbssparams.channel = ret;
++		ret = 0;
++	}
++	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
++	return ret;
++}
++
+ /**
+  *  @brief Set the radio channel
+  *
+@@ -804,6 +862,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
+ 
+ 	lbs_deb_enter(LBS_DEB_CMD);
+ 
++	memset(&cmd, 0, sizeof(cmd));
+ 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ 	cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
+ 	cmd.channel = cpu_to_le16(channel);
+@@ -842,8 +901,7 @@ static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
+ 	return 0;
+ }
+ 
+-static int lbs_cmd_reg_access(struct lbs_private *priv,
+-			       struct cmd_ds_command *cmdptr,
++static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
+ 			       u8 cmd_action, void *pdata_buf)
+ {
+ 	struct lbs_offset_value *offval;
+@@ -917,53 +975,7 @@ static int lbs_cmd_reg_access(struct lbs_private *priv,
+ 	return 0;
+ }
+ 
+-static int lbs_cmd_802_11_mac_address(struct lbs_private *priv,
+-				       struct cmd_ds_command *cmd,
+-				       u16 cmd_action)
+-{
+-
+-	lbs_deb_enter(LBS_DEB_CMD);
+-	cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
+-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
+-			     S_DS_GEN);
+-	cmd->result = 0;
+-
+-	cmd->params.macadd.action = cpu_to_le16(cmd_action);
+-
+-	if (cmd_action == CMD_ACT_SET) {
+-		memcpy(cmd->params.macadd.macadd,
+-		       priv->current_addr, ETH_ALEN);
+-		lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", priv->current_addr, 6);
+-	}
+-
+-	lbs_deb_leave(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+-static int lbs_cmd_802_11_eeprom_access(struct lbs_private *priv,
+-					 struct cmd_ds_command *cmd,
+-					 int cmd_action, void *pdata_buf)
+-{
+-	struct lbs_ioctl_regrdwr *ea = pdata_buf;
+-
+-	lbs_deb_enter(LBS_DEB_CMD);
+-
+-	cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS);
+-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
+-				S_DS_GEN);
+-	cmd->result = 0;
+-
+-	cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
+-	cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset);
+-	cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB);
+-	cmd->params.rdeeprom.value = 0;
+-
+-	lbs_deb_leave(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+-static int lbs_cmd_bt_access(struct lbs_private *priv,
+-			       struct cmd_ds_command *cmd,
++static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
+ 			       u16 cmd_action, void *pdata_buf)
+ {
+ 	struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
+@@ -1000,8 +1012,7 @@ static int lbs_cmd_bt_access(struct lbs_private *priv,
+ 	return 0;
+ }
+ 
+-static int lbs_cmd_fwt_access(struct lbs_private *priv,
+-			       struct cmd_ds_command *cmd,
++static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
+ 			       u16 cmd_action, void *pdata_buf)
+ {
+ 	struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
+@@ -1153,9 +1164,9 @@ static void lbs_submit_command(struct lbs_private *priv,
+ 	    command == CMD_802_11_AUTHENTICATE)
+ 		timeo = 10 * HZ;
+ 
+-	lbs_deb_host("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n",
+-		     command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies);
+-	lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
++	lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
++		     command, le16_to_cpu(cmd->seqnum), cmdsize);
++	lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
+ 
+ 	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
+ 
+@@ -1164,9 +1175,7 @@ static void lbs_submit_command(struct lbs_private *priv,
+ 		/* Let the timer kick in and retry, and potentially reset
+ 		   the whole thing if the condition persists */
+ 		timeo = HZ;
+-	} else
+-		lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n",
+-			    command, jiffies);
++	}
+ 
+ 	/* Setup the timer after transmit command */
+ 	mod_timer(&priv->command_timer, jiffies + timeo);
+@@ -1174,24 +1183,6 @@ static void lbs_submit_command(struct lbs_private *priv,
+ 	lbs_deb_leave(LBS_DEB_HOST);
+ }
+ 
+-static int lbs_cmd_mac_control(struct lbs_private *priv,
+-				struct cmd_ds_command *cmd)
+-{
+-	struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
+-
+-	lbs_deb_enter(LBS_DEB_CMD);
+-
+-	cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
+-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
+-	mac->action = cpu_to_le16(priv->currentpacketfilter);
+-
+-	lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
+-		    le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
+-
+-	lbs_deb_leave(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+ /**
+  *  This function inserts command node to cmdfreeq
+  *  after cleans it. Requires priv->driver_lock held.
+@@ -1234,7 +1225,7 @@ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ 	cmd->cmdwaitqwoken = 1;
+ 	wake_up_interruptible(&cmd->cmdwait_q);
+ 
+-	if (!cmd->callback)
++	if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
+ 		__lbs_cleanup_and_insert_cmd(priv, cmd);
+ 	priv->cur_cmd = NULL;
+ }
+@@ -1278,18 +1269,20 @@ int lbs_set_radio_control(struct lbs_private *priv)
+ 	return ret;
+ }
+ 
+-int lbs_set_mac_packet_filter(struct lbs_private *priv)
++void lbs_set_mac_control(struct lbs_private *priv)
+ {
+-	int ret = 0;
++	struct cmd_ds_mac_control cmd;
+ 
+ 	lbs_deb_enter(LBS_DEB_CMD);
+ 
+-	/* Send MAC control command to station */
+-	ret = lbs_prepare_and_send_command(priv,
+-				    CMD_MAC_CONTROL, 0, 0, 0, NULL);
++	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
++	cmd.action = cpu_to_le16(priv->mac_control);
++	cmd.reserved = 0;
+ 
+-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+-	return ret;
++	lbs_cmd_async(priv, CMD_MAC_CONTROL,
++		&cmd.hdr, sizeof(cmd));
++
++	lbs_deb_leave(LBS_DEB_CMD);
+ }
+ 
+ /**
+@@ -1338,7 +1331,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ 		goto done;
+ 	}
+ 
+-	lbs_set_cmd_ctrl_node(priv, cmdnode, pdata_buf);
++	cmdnode->callback = NULL;
++	cmdnode->callback_arg = (unsigned long)pdata_buf;
+ 
+ 	cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
+ 
+@@ -1353,15 +1347,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ 
+ 	switch (cmd_no) {
+ 	case CMD_802_11_PS_MODE:
+-		ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
+-		break;
+-
+-	case CMD_802_11_SCAN:
+-		ret = lbs_cmd_80211_scan(priv, cmdptr, pdata_buf);
+-		break;
+-
+-	case CMD_MAC_CONTROL:
+-		ret = lbs_cmd_mac_control(priv, cmdptr);
++		ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
+ 		break;
+ 
+ 	case CMD_802_11_ASSOCIATE:
+@@ -1376,25 +1362,15 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ 	case CMD_802_11_AD_HOC_START:
+ 		ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
+ 		break;
+-	case CMD_CODE_DNLD:
+-		break;
+ 
+ 	case CMD_802_11_RESET:
+-		ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action);
+-		break;
+-
+-	case CMD_802_11_GET_LOG:
+-		ret = lbs_cmd_802_11_get_log(priv, cmdptr);
++		ret = lbs_cmd_802_11_reset(cmdptr, cmd_action);
+ 		break;
+ 
+ 	case CMD_802_11_AUTHENTICATE:
+ 		ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
+ 		break;
+ 
+-	case CMD_802_11_GET_STAT:
+-		ret = lbs_cmd_802_11_get_stat(priv, cmdptr);
+-		break;
+-
+ 	case CMD_802_11_SNMP_MIB:
+ 		ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
+ 					       cmd_action, cmd_oid, pdata_buf);
+@@ -1403,12 +1379,12 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ 	case CMD_MAC_REG_ACCESS:
+ 	case CMD_BBP_REG_ACCESS:
+ 	case CMD_RF_REG_ACCESS:
+-		ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
++		ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
+ 		break;
+ 
+ 	case CMD_802_11_RF_TX_POWER:
+-		ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr,
+-						  cmd_action, pdata_buf);
++		ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
++						 cmd_action, pdata_buf);
+ 		break;
+ 
+ 	case CMD_802_11_RATE_ADAPT_RATESET:
+@@ -1421,7 +1397,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ 		break;
+ 
+ 	case CMD_802_11_MONITOR_MODE:
+-		ret = lbs_cmd_802_11_monitor_mode(priv, cmdptr,
++		ret = lbs_cmd_802_11_monitor_mode(cmdptr,
+ 				          cmd_action, pdata_buf);
+ 		break;
+ 
+@@ -1434,26 +1410,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ 		break;
+ 
+ 	case CMD_802_11_AD_HOC_STOP:
+-		ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr);
+-		break;
+-
+-	case CMD_802_11_KEY_MATERIAL:
+-		ret = lbs_cmd_802_11_key_material(priv, cmdptr, cmd_action,
+-				cmd_oid, pdata_buf);
+-		break;
+-
+-	case CMD_802_11_PAIRWISE_TSC:
+-		break;
+-	case CMD_802_11_GROUP_TSC:
+-		break;
+-
+-	case CMD_802_11_MAC_ADDRESS:
+-		ret = lbs_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
+-		break;
+-
+-	case CMD_802_11_EEPROM_ACCESS:
+-		ret = lbs_cmd_802_11_eeprom_access(priv, cmdptr,
+-						    cmd_action, pdata_buf);
++		ret = lbs_cmd_80211_ad_hoc_stop(cmdptr);
+ 		break;
+ 
+ 	case CMD_802_11_SET_AFC:
+@@ -1509,22 +1466,12 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ 			break;
+ 		}
+ 
+-	case CMD_802_11_PWR_CFG:
+-		cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
+-		cmdptr->size =
+-		    cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) +
+-				     S_DS_GEN);
+-		memmove(&cmdptr->params.pwrcfg, pdata_buf,
+-			sizeof(struct cmd_ds_802_11_pwr_cfg));
+-
+-		ret = 0;
+-		break;
+ 	case CMD_BT_ACCESS:
+-		ret = lbs_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
++		ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
+ 		break;
+ 
+ 	case CMD_FWT_ACCESS:
+-		ret = lbs_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
++		ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
+ 		break;
+ 
+ 	case CMD_GET_TSF:
+@@ -1697,36 +1644,6 @@ static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
+ }
+ 
+ /**
+- *  @brief This function cleans command node.
+- *
+- *  @param ptempnode	A pointer to cmdCtrlNode structure
+- *  @return 		n/a
+- */
+-
+-/**
+- *  @brief This function initializes the command node.
+- *
+- *  @param priv		A pointer to struct lbs_private structure
+- *  @param ptempnode	A pointer to cmd_ctrl_node structure
+- *  @param pdata_buf	A pointer to informaion buffer
+- *  @return 		0 or -1
+- */
+-static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
+-				  struct cmd_ctrl_node *ptempnode,
+-				  void *pdata_buf)
+-{
+-	lbs_deb_enter(LBS_DEB_HOST);
+-
+-	if (!ptempnode)
+-		return;
+-
+-	ptempnode->callback = NULL;
+-	ptempnode->callback_arg = (unsigned long)pdata_buf;
+-
+-	lbs_deb_leave(LBS_DEB_HOST);
+-}
+-
+-/**
+  *  @brief This function executes next command in command
+  *  pending queue. It will put fimware back to PS mode
+  *  if applicable.
+@@ -1741,9 +1658,9 @@ int lbs_execute_next_command(struct lbs_private *priv)
+ 	unsigned long flags;
+ 	int ret = 0;
+ 
+-	// Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
+-	// only caller to us is lbs_thread() and we get even when a
+-	// data packet is received
++	/* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
++	 * only caller to us is lbs_thread() and we get even when a
++	 * data packet is received */
+ 	lbs_deb_enter(LBS_DEB_THREAD);
+ 
+ 	spin_lock_irqsave(&priv->driver_lock, flags);
+@@ -1907,44 +1824,32 @@ void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
+ 	lbs_deb_leave(LBS_DEB_WEXT);
+ }
+ 
+-static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size)
++static void lbs_send_confirmsleep(struct lbs_private *priv)
+ {
+ 	unsigned long flags;
+-	int ret = 0;
++	int ret;
+ 
+ 	lbs_deb_enter(LBS_DEB_HOST);
++	lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
++		sizeof(confirm_sleep));
+ 
+-	lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
+-	       size);
+-
+-	lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
+-
+-	ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
++	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
++		sizeof(confirm_sleep));
++	if (ret) {
++		lbs_pr_alert("confirm_sleep failed\n");
++		goto out;
++	}
+ 
+ 	spin_lock_irqsave(&priv->driver_lock, flags);
+-	if (priv->intcounter || priv->currenttxskb)
+-		lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
+-		       priv->intcounter, priv->currenttxskb);
+-	spin_unlock_irqrestore(&priv->driver_lock, flags);
+ 
+-	if (ret) {
+-		lbs_pr_alert(
+-		       "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
+-	} else {
+-		spin_lock_irqsave(&priv->driver_lock, flags);
+-		if (!priv->intcounter) {
+-			priv->psstate = PS_STATE_SLEEP;
+-		} else {
+-			lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
+-			       priv->intcounter);
+-		}
+-		spin_unlock_irqrestore(&priv->driver_lock, flags);
++	/* If nothing to do, go back to sleep (?) */
++	if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx])
++		priv->psstate = PS_STATE_SLEEP;
+ 
+-		lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
+-	}
++	spin_unlock_irqrestore(&priv->driver_lock, flags);
+ 
+-	lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
+-	return ret;
++out:
++	lbs_deb_leave(LBS_DEB_HOST);
+ }
+ 
+ void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
+@@ -1992,10 +1897,10 @@ void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
+  *  @param psmode  	Power Saving mode
+  *  @return 	   	n/a
+  */
+-void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
++void lbs_ps_confirm_sleep(struct lbs_private *priv)
+ {
+ 	unsigned long flags =0;
+-	u8 allowed = 1;
++	int allowed = 1;
+ 
+ 	lbs_deb_enter(LBS_DEB_HOST);
+ 
+@@ -2005,20 +1910,22 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
+ 	}
+ 
+ 	spin_lock_irqsave(&priv->driver_lock, flags);
++	/* In-progress command? */
+ 	if (priv->cur_cmd) {
+ 		allowed = 0;
+ 		lbs_deb_host("cur_cmd was set\n");
+ 	}
+-	if (priv->intcounter > 0) {
++
++	/* Pending events or command responses? */
++	if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
+ 		allowed = 0;
+-		lbs_deb_host("intcounter %d\n", priv->intcounter);
++		lbs_deb_host("pending events or command responses\n");
+ 	}
+ 	spin_unlock_irqrestore(&priv->driver_lock, flags);
+ 
+ 	if (allowed) {
+ 		lbs_deb_host("sending lbs_ps_confirm_sleep\n");
+-		sendconfirmsleep(priv, (u8 *) & priv->lbs_ps_confirm_sleep,
+-				 sizeof(struct PS_CMD_ConfirmSleep));
++		lbs_send_confirmsleep(priv);
+ 	} else {
+ 		lbs_deb_host("sleep confirm has been delayed\n");
+ 	}
+@@ -2027,39 +1934,10 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
+ }
+ 
+ 
+-/**
+- *  @brief Simple callback that copies response back into command
+- *
+- *  @param priv    	A pointer to struct lbs_private structure
+- *  @param extra  	A pointer to the original command structure for which
+- *                      'resp' is a response
+- *  @param resp         A pointer to the command response
+- *
+- *  @return 	   	0 on success, error on failure
+- */
+-int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
+-		     struct cmd_header *resp)
+-{
+-	struct cmd_header *buf = (void *)extra;
+-	uint16_t copy_len;
+-
+-	lbs_deb_enter(LBS_DEB_CMD);
+-
+-	copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
+-	lbs_deb_cmd("Copying back %u bytes; command response was %u bytes, "
+-		    "copy back buffer was %u bytes\n", copy_len,
+-		    le16_to_cpu(resp->size), le16_to_cpu(buf->size));
+-	memcpy(buf, resp, copy_len);
+-
+-	lbs_deb_leave(LBS_DEB_CMD);
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
+-
+-struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
+-				      struct cmd_header *in_cmd, int in_cmd_size,
+-				      int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+-				      unsigned long callback_arg)
++static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
++	uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
++	int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
++	unsigned long callback_arg)
+ {
+ 	struct cmd_ctrl_node *cmdnode;
+ 
+@@ -2096,9 +1974,6 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command
+ 
+ 	lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
+ 
+-	/* here was the big old switch() statement, which is now obsolete,
+-	 * because the caller of lbs_cmd() sets up all of *cmd for us. */
+-
+ 	cmdnode->cmdwaitqwoken = 0;
+ 	lbs_queue_cmd(priv, cmdnode);
+ 	wake_up_interruptible(&priv->waitq);
+@@ -2108,6 +1983,15 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command
+ 	return cmdnode;
+ }
+ 
++void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
++	struct cmd_header *in_cmd, int in_cmd_size)
++{
++	lbs_deb_enter(LBS_DEB_CMD);
++	__lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
++		lbs_cmd_async_callback, 0);
++	lbs_deb_leave(LBS_DEB_CMD);
++}
++
+ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
+ 	      struct cmd_header *in_cmd, int in_cmd_size,
+ 	      int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
+index b9ab85c..3dfc2d4 100644
+--- a/drivers/net/wireless/libertas/cmd.h
++++ b/drivers/net/wireless/libertas/cmd.h
+@@ -18,12 +18,9 @@
+ #define lbs_cmd_with_response(priv, cmdnr, cmd)	\
+ 	lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
+ 
+-/* __lbs_cmd() will free the cmdnode and return success/failure.
+-   __lbs_cmd_async() requires that the callback free the cmdnode */
+-struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
+-				      struct cmd_header *in_cmd, int in_cmd_size,
+-				      int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+-				      unsigned long callback_arg);
++void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
++	struct cmd_header *in_cmd, int in_cmd_size);
++
+ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
+ 	      struct cmd_header *in_cmd, int in_cmd_size,
+ 	      int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+@@ -57,5 +54,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
+ 			   struct assoc_request *assoc);
+ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+ 			      uint16_t *enable);
++int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
++				struct assoc_request *assoc);
+ 
+ #endif /* _LBS_CMD_H */
+diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
+index f0ef708..5abecb7 100644
+--- a/drivers/net/wireless/libertas/cmdresp.c
++++ b/drivers/net/wireless/libertas/cmdresp.c
+@@ -12,7 +12,7 @@
+ #include "decl.h"
+ #include "defs.h"
+ #include "dev.h"
+-#include "join.h"
++#include "assoc.h"
+ #include "wext.h"
+ 
+ /**
+@@ -74,7 +74,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
+ 		lbs_deb_cmd("disconnected, so exit PS mode\n");
+ 		lbs_ps_wakeup(priv, 0);
+ 	}
+-	lbs_deb_leave(LBS_DEB_CMD);
++	lbs_deb_leave(LBS_DEB_ASSOC);
+ }
+ 
+ /**
+@@ -146,22 +146,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
+ 	return ret;
+ }
+ 
+-static int lbs_ret_802_11_stat(struct lbs_private *priv,
+-				struct cmd_ds_command *resp)
+-{
+-	lbs_deb_enter(LBS_DEB_CMD);
+-/*	currently priv->wlan802_11Stat is unused
+-
+-	struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
+-
+-	// TODO Convert it to Big endian befor copy
+-	memcpy(&priv->wlan802_11Stat,
+-	       p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
+-*/
+-	lbs_deb_leave(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
+ 				    struct cmd_ds_command *resp)
+ {
+@@ -204,74 +188,6 @@ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
+ 	return 0;
+ }
+ 
+-static int lbs_ret_802_11_key_material(struct lbs_private *priv,
+-					struct cmd_ds_command *resp)
+-{
+-	struct cmd_ds_802_11_key_material *pkeymaterial =
+-	    &resp->params.keymaterial;
+-	u16 action = le16_to_cpu(pkeymaterial->action);
+-
+-	lbs_deb_enter(LBS_DEB_CMD);
+-
+-	/* Copy the returned key to driver private data */
+-	if (action == CMD_ACT_GET) {
+-		u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
+-		u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
+-
+-		while (buf_ptr < resp_end) {
+-			struct MrvlIEtype_keyParamSet * pkeyparamset =
+-			    (struct MrvlIEtype_keyParamSet *) buf_ptr;
+-			struct enc_key * pkey;
+-			u16 param_set_len = le16_to_cpu(pkeyparamset->length);
+-			u16 key_len = le16_to_cpu(pkeyparamset->keylen);
+-			u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
+-			u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
+-			u8 * end;
+-
+-			end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
+-			                          + sizeof (pkeyparamset->length)
+-			                          + param_set_len;
+-			/* Make sure we don't access past the end of the IEs */
+-			if (end > resp_end)
+-				break;
+-
+-			if (key_flags & KEY_INFO_WPA_UNICAST)
+-				pkey = &priv->wpa_unicast_key;
+-			else if (key_flags & KEY_INFO_WPA_MCAST)
+-				pkey = &priv->wpa_mcast_key;
+-			else
+-				break;
+-
+-			/* Copy returned key into driver */
+-			memset(pkey, 0, sizeof(struct enc_key));
+-			if (key_len > sizeof(pkey->key))
+-				break;
+-			pkey->type = key_type;
+-			pkey->flags = key_flags;
+-			pkey->len = key_len;
+-			memcpy(pkey->key, pkeyparamset->key, pkey->len);
+-
+-			buf_ptr = end + 1;
+-		}
+-	}
+-
+-	lbs_deb_enter(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+-static int lbs_ret_802_11_mac_address(struct lbs_private *priv,
+-				       struct cmd_ds_command *resp)
+-{
+-	struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
+-
+-	lbs_deb_enter(LBS_DEB_CMD);
+-
+-	memcpy(priv->current_addr, macadd->macadd, ETH_ALEN);
+-
+-	lbs_deb_enter(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+ static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
+ 				       struct cmd_ds_command *resp)
+ {
+@@ -333,45 +249,6 @@ static int lbs_ret_802_11_rssi(struct lbs_private *priv,
+ 	return 0;
+ }
+ 
+-static int lbs_ret_802_11_eeprom_access(struct lbs_private *priv,
+-				  struct cmd_ds_command *resp)
+-{
+-	struct lbs_ioctl_regrdwr *pbuf;
+-	pbuf = (struct lbs_ioctl_regrdwr *) priv->prdeeprom;
+-
+-	lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
+-	       le16_to_cpu(resp->params.rdeeprom.bytecount));
+-	if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
+-		pbuf->NOB = 0;
+-		lbs_deb_cmd("EEPROM read length too big\n");
+-		return -1;
+-	}
+-	pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
+-	if (pbuf->NOB > 0) {
+-
+-		memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
+-		       le16_to_cpu(resp->params.rdeeprom.bytecount));
+-		lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value,
+-			le16_to_cpu(resp->params.rdeeprom.bytecount));
+-	}
+-	lbs_deb_leave(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+-static int lbs_ret_get_log(struct lbs_private *priv,
+-			    struct cmd_ds_command *resp)
+-{
+-	struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
+-
+-	lbs_deb_enter(LBS_DEB_CMD);
+-
+-	/* Stored little-endian */
+-	memcpy(&priv->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
+-
+-	lbs_deb_leave(LBS_DEB_CMD);
+-	return 0;
+-}
+-
+ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
+ 					struct cmd_ds_command *resp)
+ {
+@@ -390,7 +267,6 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
+ }
+ 
+ static inline int handle_cmd_response(struct lbs_private *priv,
+-				      unsigned long dummy,
+ 				      struct cmd_header *cmd_response)
+ {
+ 	struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
+@@ -407,14 +283,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ 		ret = lbs_ret_reg_access(priv, respcmd, resp);
+ 		break;
+ 
+-	case CMD_RET(CMD_802_11_SCAN):
+-		ret = lbs_ret_80211_scan(priv, resp);
+-		break;
+-
+-	case CMD_RET(CMD_802_11_GET_LOG):
+-		ret = lbs_ret_get_log(priv, resp);
+-		break;
+-
+ 	case CMD_RET_802_11_ASSOCIATE:
+ 	case CMD_RET(CMD_802_11_ASSOCIATE):
+ 	case CMD_RET(CMD_802_11_REASSOCIATE):
+@@ -423,7 +291,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ 
+ 	case CMD_RET(CMD_802_11_DISASSOCIATE):
+ 	case CMD_RET(CMD_802_11_DEAUTHENTICATE):
+-		ret = lbs_ret_80211_disassociate(priv, resp);
++		ret = lbs_ret_80211_disassociate(priv);
+ 		break;
+ 
+ 	case CMD_RET(CMD_802_11_AD_HOC_START):
+@@ -431,10 +299,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ 		ret = lbs_ret_80211_ad_hoc_start(priv, resp);
+ 		break;
+ 
+-	case CMD_RET(CMD_802_11_GET_STAT):
+-		ret = lbs_ret_802_11_stat(priv, resp);
+-		break;
+-
+ 	case CMD_RET(CMD_802_11_SNMP_MIB):
+ 		ret = lbs_ret_802_11_snmp_mib(priv, resp);
+ 		break;
+@@ -453,7 +317,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ 		break;
+ 
+ 	case CMD_RET(CMD_MAC_MULTICAST_ADR):
+-	case CMD_RET(CMD_MAC_CONTROL):
+ 	case CMD_RET(CMD_802_11_RESET):
+ 	case CMD_RET(CMD_802_11_AUTHENTICATE):
+ 	case CMD_RET(CMD_802_11_BEACON_STOP):
+@@ -467,24 +330,12 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ 		ret = lbs_ret_802_11_rssi(priv, resp);
+ 		break;
+ 
+-	case CMD_RET(CMD_802_11_MAC_ADDRESS):
+-		ret = lbs_ret_802_11_mac_address(priv, resp);
+-		break;
+-
+ 	case CMD_RET(CMD_802_11_AD_HOC_STOP):
+-		ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
+-		break;
+-
+-	case CMD_RET(CMD_802_11_KEY_MATERIAL):
+-		ret = lbs_ret_802_11_key_material(priv, resp);
+-		break;
+-
+-	case CMD_RET(CMD_802_11_EEPROM_ACCESS):
+-		ret = lbs_ret_802_11_eeprom_access(priv, resp);
++		ret = lbs_ret_80211_ad_hoc_stop(priv);
+ 		break;
+ 
+ 	case CMD_RET(CMD_802_11D_DOMAIN_INFO):
+-		ret = lbs_ret_802_11d_domain_info(priv, resp);
++		ret = lbs_ret_802_11d_domain_info(resp);
+ 		break;
+ 
+ 	case CMD_RET(CMD_802_11_TPC_CFG):
+@@ -500,14 +351,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ 		spin_unlock_irqrestore(&priv->driver_lock, flags);
+ 		break;
+ 
+-	case CMD_RET(CMD_802_11_PWR_CFG):
+-		spin_lock_irqsave(&priv->driver_lock, flags);
+-		memmove((void *)priv->cur_cmd->callback_arg, &resp->params.pwrcfg,
+-			sizeof(struct cmd_ds_802_11_pwr_cfg));
+-		spin_unlock_irqrestore(&priv->driver_lock, flags);
+-
+-		break;
+-
+ 	case CMD_RET(CMD_GET_TSF):
+ 		spin_lock_irqsave(&priv->driver_lock, flags);
+ 		memcpy((void *)priv->cur_cmd->callback_arg,
+@@ -541,7 +384,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ 	return ret;
+ }
+ 
+-int lbs_process_rx_command(struct lbs_private *priv)
++int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
+ {
+ 	uint16_t respcmd, curcmd;
+ 	struct cmd_header *resp;
+@@ -561,14 +404,14 @@ int lbs_process_rx_command(struct lbs_private *priv)
+ 		goto done;
+ 	}
+ 
+-	resp = (void *)priv->upld_buf;
++	resp = (void *)data;
+ 	curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
+ 	respcmd = le16_to_cpu(resp->command);
+ 	result = le16_to_cpu(resp->result);
+ 
+-	lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
+-		     respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
+-	lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
++	lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n",
++		     respcmd, le16_to_cpu(resp->seqnum), len);
++	lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len);
+ 
+ 	if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
+ 		lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
+@@ -687,7 +530,7 @@ int lbs_process_rx_command(struct lbs_private *priv)
+ 		ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
+ 				resp);
+ 	} else
+-		ret = handle_cmd_response(priv, 0, resp);
++		ret = handle_cmd_response(priv, resp);
+ 
+ 	spin_lock_irqsave(&priv->driver_lock, flags);
+ 
+@@ -705,21 +548,20 @@ done:
+ 
+ static int lbs_send_confirmwake(struct lbs_private *priv)
+ {
+-	struct cmd_header *cmd = &priv->lbs_ps_confirm_wake;
++	struct cmd_header cmd;
+ 	int ret = 0;
+ 
+ 	lbs_deb_enter(LBS_DEB_HOST);
+ 
+-	cmd->command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
+-	cmd->size = cpu_to_le16(sizeof(*cmd));
+-	cmd->seqnum = cpu_to_le16(++priv->seqnum);
+-	cmd->result = 0;
+-
+-	lbs_deb_host("SEND_WAKEC_CMD: before download\n");
++	cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
++	cmd.size = cpu_to_le16(sizeof(cmd));
++	cmd.seqnum = cpu_to_le16(++priv->seqnum);
++	cmd.result = 0;
+ 
+-	lbs_deb_hex(LBS_DEB_HOST, "wake confirm command", (void *)cmd, sizeof(*cmd));
++	lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
++		sizeof(cmd));
+ 
+-	ret = priv->hw_host_to_card(priv, MVMS_CMD, (void *)cmd, sizeof(*cmd));
++	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
+ 	if (ret)
+ 		lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
+ 
+@@ -727,22 +569,15 @@ static int lbs_send_confirmwake(struct lbs_private *priv)
+ 	return ret;
+ }
+ 
+-int lbs_process_event(struct lbs_private *priv)
++int lbs_process_event(struct lbs_private *priv, u32 event)
+ {
+ 	int ret = 0;
+-	u32 eventcause;
+ 
+ 	lbs_deb_enter(LBS_DEB_CMD);
+ 
+-	spin_lock_irq(&priv->driver_lock);
+-	eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT;
+-	spin_unlock_irq(&priv->driver_lock);
+-
+-	lbs_deb_cmd("event cause %d\n", eventcause);
+-
+-	switch (eventcause) {
++	switch (event) {
+ 	case MACREG_INT_CODE_LINK_SENSED:
+-		lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
++		lbs_deb_cmd("EVENT: link sensed\n");
+ 		break;
+ 
+ 	case MACREG_INT_CODE_DEAUTHENTICATED:
+@@ -761,7 +596,7 @@ int lbs_process_event(struct lbs_private *priv)
+ 		break;
+ 
+ 	case MACREG_INT_CODE_PS_SLEEP:
+-		lbs_deb_cmd("EVENT: sleep\n");
++		lbs_deb_cmd("EVENT: ps sleep\n");
+ 
+ 		/* handle unexpected PS SLEEP event */
+ 		if (priv->psstate == PS_STATE_FULL_POWER) {
+@@ -771,17 +606,17 @@ int lbs_process_event(struct lbs_private *priv)
+ 		}
+ 		priv->psstate = PS_STATE_PRE_SLEEP;
+ 
+-		lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
++		lbs_ps_confirm_sleep(priv);
+ 
+ 		break;
+ 
+ 	case MACREG_INT_CODE_HOST_AWAKE:
+-		lbs_deb_cmd("EVENT: HOST_AWAKE\n");
++		lbs_deb_cmd("EVENT: host awake\n");
+ 		lbs_send_confirmwake(priv);
+ 		break;
+ 
+ 	case MACREG_INT_CODE_PS_AWAKE:
+-		lbs_deb_cmd("EVENT: awake\n");
++		lbs_deb_cmd("EVENT: ps awake\n");
+ 		/* handle unexpected PS AWAKE event */
+ 		if (priv->psstate == PS_STATE_FULL_POWER) {
+ 			lbs_deb_cmd(
+@@ -812,14 +647,16 @@ int lbs_process_event(struct lbs_private *priv)
+ 		lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
+ 		handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
+ 		break;
++
+ 	case MACREG_INT_CODE_MIB_CHANGED:
++		lbs_deb_cmd("EVENT: MIB CHANGED\n");
++		break;
+ 	case MACREG_INT_CODE_INIT_DONE:
++		lbs_deb_cmd("EVENT: INIT DONE\n");
+ 		break;
+-
+ 	case MACREG_INT_CODE_ADHOC_BCN_LOST:
+ 		lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
+ 		break;
+-
+ 	case MACREG_INT_CODE_RSSI_LOW:
+ 		lbs_pr_alert("EVENT: rssi low\n");
+ 		break;
+@@ -854,14 +691,10 @@ int lbs_process_event(struct lbs_private *priv)
+ 		break;
+ 
+ 	default:
+-		lbs_pr_alert("EVENT: unknown event id %d\n", eventcause);
++		lbs_pr_alert("EVENT: unknown event id %d\n", event);
+ 		break;
+ 	}
+ 
+-	spin_lock_irq(&priv->driver_lock);
+-	priv->eventcause = 0;
+-	spin_unlock_irq(&priv->driver_lock);
+-
+ 	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ 	return ret;
+ }
+diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
+index fd67b77..ad2fabc 100644
+--- a/drivers/net/wireless/libertas/debugfs.c
++++ b/drivers/net/wireless/libertas/debugfs.c
+@@ -19,7 +19,7 @@ static char *szStates[] = {
+ };
+ 
+ #ifdef PROC_DEBUG
+-static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev);
++static void lbs_debug_init(struct lbs_private *priv);
+ #endif
+ 
+ static int open_file_generic(struct inode *inode, struct file *file)
+@@ -78,7 +78,7 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
+ 		u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
+ 
+ 		pos += snprintf(buf+pos, len-pos,
+-			"%02u| %03d | %04ld | %s |",
++			"%02u| %03d | %04d | %s |",
+ 			numscansdone, iter_bss->channel, iter_bss->rssi,
+ 			print_mac(mac, iter_bss->bssid));
+ 		pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
+@@ -164,173 +164,6 @@ out_unlock:
+ 	return ret;
+ }
+ 
+-static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
+-				  size_t count, loff_t *ppos)
+-{
+-	struct lbs_private *priv = file->private_data;
+-	ssize_t res, buf_size;
+-	union iwreq_data wrqu;
+-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
+-	char *buf = (char *)addr;
+-
+-	buf_size = min(count, len - 1);
+-	if (copy_from_user(buf, userbuf, buf_size)) {
+-		res = -EFAULT;
+-		goto out_unlock;
+-	}
+-
+-	lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
+-
+-	memset(&wrqu, 0, sizeof(union iwreq_data));
+-	wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+-
+-out_unlock:
+-	free_page(addr);
+-	return count;
+-}
+-
+-static void lbs_parse_bssid(char *buf, size_t count,
+-	struct lbs_ioctl_user_scan_cfg *scan_cfg)
+-{
+-	char *hold;
+-	unsigned int mac[ETH_ALEN];
+-
+-	hold = strstr(buf, "bssid=");
+-	if (!hold)
+-		return;
+-	hold += 6;
+-	sscanf(hold, "%02x:%02x:%02x:%02x:%02x:%02x",
+-	       mac, mac+1, mac+2, mac+3, mac+4, mac+5);
+-	memcpy(scan_cfg->bssid, mac, ETH_ALEN);
+-}
+-
+-static void lbs_parse_ssid(char *buf, size_t count,
+-	struct lbs_ioctl_user_scan_cfg *scan_cfg)
+-{
+-	char *hold, *end;
+-	ssize_t size;
+-
+-	hold = strstr(buf, "ssid=");
+-	if (!hold)
+-		return;
+-	hold += 5;
+-	end = strchr(hold, ' ');
+-	if (!end)
+-		end = buf + count - 1;
+-
+-	size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
+-	strncpy(scan_cfg->ssid, hold, size);
+-
+-	return;
+-}
+-
+-static int lbs_parse_clear(char *buf, size_t count, const char *tag)
+-{
+-	char *hold;
+-	int val;
+-
+-	hold = strstr(buf, tag);
+-	if (!hold)
+-		return 0;
+-	hold += strlen(tag);
+-	sscanf(hold, "%d", &val);
+-
+-	if (val != 0)
+-		val = 1;
+-
+-	return val;
+-}
+-
+-static int lbs_parse_dur(char *buf, size_t count,
+-	struct lbs_ioctl_user_scan_cfg *scan_cfg)
+-{
+-	char *hold;
+-	int val;
+-
+-	hold = strstr(buf, "dur=");
+-	if (!hold)
+-		return 0;
+-	hold += 4;
+-	sscanf(hold, "%d", &val);
+-
+-	return val;
+-}
+-
+-static void lbs_parse_type(char *buf, size_t count,
+-	struct lbs_ioctl_user_scan_cfg *scan_cfg)
+-{
+-	char *hold;
+-	int val;
+-
+-	hold = strstr(buf, "type=");
+-	if (!hold)
+-		return;
+-	hold += 5;
+-	sscanf(hold, "%d", &val);
+-
+-	/* type=1,2 or 3 */
+-	if (val < 1 || val > 3)
+-		return;
+-
+-	scan_cfg->bsstype = val;
+-
+-	return;
+-}
+-
+-static ssize_t lbs_setuserscan(struct file *file,
+-				    const char __user *userbuf,
+-				    size_t count, loff_t *ppos)
+-{
+-	struct lbs_private *priv = file->private_data;
+-	ssize_t res, buf_size;
+-	struct lbs_ioctl_user_scan_cfg *scan_cfg;
+-	union iwreq_data wrqu;
+-	int dur;
+-	char *buf = (char *)get_zeroed_page(GFP_KERNEL);
+-
+-	if (!buf)
+-		return -ENOMEM;
+-
+-	buf_size = min(count, len - 1);
+-	if (copy_from_user(buf, userbuf, buf_size)) {
+-		res = -EFAULT;
+-		goto out_buf;
+-	}
+-
+-	scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL);
+-	if (!scan_cfg) {
+-		res = -ENOMEM;
+-		goto out_buf;
+-	}
+-	res = count;
+-
+-	scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY;
+-
+-	dur = lbs_parse_dur(buf, count, scan_cfg);
+-	lbs_parse_bssid(buf, count, scan_cfg);
+-	scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid=");
+-	lbs_parse_ssid(buf, count, scan_cfg);
+-	scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid=");
+-	lbs_parse_type(buf, count, scan_cfg);
+-
+-	lbs_scan_networks(priv, scan_cfg, 1);
+-	wait_event_interruptible(priv->cmd_pending,
+-				 priv->surpriseremoved || !priv->last_scanned_channel);
+-
+-	if (priv->surpriseremoved)
+-		goto out_scan_cfg;
+-
+-	memset(&wrqu, 0x00, sizeof(union iwreq_data));
+-	wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+-
+- out_scan_cfg:
+-	kfree(scan_cfg);
+- out_buf:
+-	free_page((unsigned long)buf);
+-	return res;
+-}
+-
+-
+ /*
+  * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
+  * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
+@@ -857,8 +690,6 @@ static struct lbs_debugfs_files debugfs_files[] = {
+ 					write_file_dummy), },
+ 	{ "sleepparams", 0644, FOPS(lbs_sleepparams_read,
+ 				lbs_sleepparams_write), },
+-	{ "extscan", 0600, FOPS(NULL, lbs_extscan), },
+-	{ "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), },
+ };
+ 
+ static struct lbs_debugfs_files debugfs_events_files[] = {
+@@ -947,7 +778,7 @@ void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
+ 	}
+ 
+ #ifdef PROC_DEBUG
+-	lbs_debug_init(priv, dev);
++	lbs_debug_init(priv);
+ #endif
+ exit:
+ 	return;
+@@ -993,7 +824,6 @@ struct debug_data {
+ /* To debug any member of struct lbs_private, simply add one line here.
+  */
+ static struct debug_data items[] = {
+-	{"intcounter", item_size(intcounter), item_addr(intcounter)},
+ 	{"psmode", item_size(psmode), item_addr(psmode)},
+ 	{"psstate", item_size(psstate), item_addr(psstate)},
+ };
+@@ -1121,7 +951,7 @@ static struct file_operations lbs_debug_fops = {
+  *  @param dev     pointer net_device
+  *  @return 	   N/A
+  */
+-static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev)
++static void lbs_debug_init(struct lbs_private *priv)
+ {
+ 	int i;
+ 
+diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
+index 4e22341..b652fa3 100644
+--- a/drivers/net/wireless/libertas/decl.h
++++ b/drivers/net/wireless/libertas/decl.h
+@@ -17,9 +17,9 @@ struct net_device;
+ struct cmd_ctrl_node;
+ struct cmd_ds_command;
+ 
+-int lbs_set_mac_packet_filter(struct lbs_private *priv);
++void lbs_set_mac_control(struct lbs_private *priv);
+ 
+-void lbs_send_tx_feedback(struct lbs_private *priv);
++void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
+ 
+ int lbs_free_cmd_buffer(struct lbs_private *priv);
+ 
+@@ -30,17 +30,16 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ 
+ int lbs_allocate_cmd_buffer(struct lbs_private *priv);
+ int lbs_execute_next_command(struct lbs_private *priv);
+-int lbs_process_event(struct lbs_private *priv);
+-void lbs_interrupt(struct lbs_private *priv);
++int lbs_process_event(struct lbs_private *priv, u32 event);
++void lbs_queue_event(struct lbs_private *priv, u32 event);
++void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
++
+ int lbs_set_radio_control(struct lbs_private *priv);
+ u32 lbs_fw_index_to_data_rate(u8 index);
+ u8 lbs_data_rate_to_fw_index(u32 rate);
+-void lbs_get_fwversion(struct lbs_private *priv,
+-	char *fwversion,
+-	int maxlen);
+ 
+ /** The proc fs interface */
+-int lbs_process_rx_command(struct lbs_private *priv);
++int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
+ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ 			  int result);
+ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
+@@ -49,7 +48,7 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
+ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
+ 
+ void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
+-void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode);
++void lbs_ps_confirm_sleep(struct lbs_private *priv);
+ void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
+ 
+ struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
+@@ -63,7 +62,6 @@ void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str);
+ 
+ /* main.c */
+ struct chan_freq_power *lbs_get_region_cfp_table(u8 region,
+-	u8 band,
+ 	int *cfp_no);
+ struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
+ int lbs_remove_card(struct lbs_private *priv);
+@@ -72,4 +70,9 @@ int lbs_stop_card(struct lbs_private *priv);
+ void lbs_host_to_card_done(struct lbs_private *priv);
+ 
+ int lbs_update_channel(struct lbs_private *priv);
++
++#ifndef CONFIG_IEEE80211
++const char *escape_essid(const char *essid, u8 essid_len);
++#endif
++
+ #endif
+diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
+index 3053cc2..d395201 100644
+--- a/drivers/net/wireless/libertas/defs.h
++++ b/drivers/net/wireless/libertas/defs.h
+@@ -53,14 +53,14 @@ do { if ((lbs_debug & (grp)) == (grp)) \
+ #endif
+ 
+ #define lbs_deb_enter(grp) \
+-  LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s():%d\n", __FUNCTION__, __LINE__);
++  LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
+ #define lbs_deb_enter_args(grp, fmt, args...) \
+-  LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt "):%d\n", __FUNCTION__, ## args, __LINE__);
++  LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
+ #define lbs_deb_leave(grp) \
+-  LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d\n", __FUNCTION__, __LINE__);
++  LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__);
+ #define lbs_deb_leave_args(grp, fmt, args...) \
+-  LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d, " fmt "\n", \
+-  __FUNCTION__, __LINE__, ##args);
++  LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
++  __func__, ##args);
+ #define lbs_deb_main(fmt, args...)      LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args)
+ #define lbs_deb_net(fmt, args...)       LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args)
+ #define lbs_deb_mesh(fmt, args...)      LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args)
+@@ -177,8 +177,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
+ #define MRVDRV_CMD_UPLD_RDY		0x0008
+ #define MRVDRV_CARDEVENT		0x0010
+ 
+-#define SBI_EVENT_CAUSE_SHIFT		3
+-
+ /** TxPD status */
+ 
+ /*	Station firmware use TxPD status field to report final Tx transmit
+diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
+index 5a69f2b..0d9edb9 100644
+--- a/drivers/net/wireless/libertas/dev.h
++++ b/drivers/net/wireless/libertas/dev.h
+@@ -10,9 +10,10 @@
+ #include <linux/wireless.h>
+ #include <linux/ethtool.h>
+ #include <linux/debugfs.h>
++#include <net/ieee80211.h>
+ 
+ #include "defs.h"
+-#include "scan.h"
++#include "hostcmd.h"
+ 
+ extern struct ethtool_ops lbs_ethtool_ops;
+ 
+@@ -128,10 +129,6 @@ struct lbs_private {
+ 	u32 bbp_offset;
+ 	u32 rf_offset;
+ 
+-	/** Upload length */
+-	u32 upld_len;
+-	/* Upload buffer */
+-	u8 upld_buf[LBS_UPLD_SIZE];
+ 	/* Download sent:
+ 	   bit0 1/0=data_sent/data_tx_done,
+ 	   bit1 1/0=cmd_sent/cmd_tx_done,
+@@ -143,27 +140,27 @@ struct lbs_private {
+ 	wait_queue_head_t waitq;
+ 	struct workqueue_struct *work_thread;
+ 
++	/** Scanning */
+ 	struct delayed_work scan_work;
+ 	struct delayed_work assoc_work;
+ 	struct work_struct sync_channel;
++	/* remember which channel was scanned last, != 0 if currently scanning */
++	int scan_channel;
++	u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
++	u8 scan_ssid_len;
+ 
+ 	/** Hardware access */
+ 	int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
+-	int (*hw_get_int_status) (struct lbs_private *priv, u8 *);
+-	int (*hw_read_event_cause) (struct lbs_private *);
+ 
+ 	/* Wake On LAN */
+ 	uint32_t wol_criteria;
+ 	uint8_t wol_gpio;
+ 	uint8_t wol_gap;
+ 
+-	/* was struct lbs_adapter from here... */
+-
+ 	/** Wlan adapter data structure*/
+ 	/** STATUS variables */
+ 	u32 fwrelease;
+ 	u32 fwcapinfo;
+-	/* protected with big lock */
+ 
+ 	struct mutex lock;
+ 
+@@ -175,7 +172,6 @@ struct lbs_private {
+ 
+ 	/** command-related variables */
+ 	u16 seqnum;
+-	/* protected by big lock */
+ 
+ 	struct cmd_ctrl_node *cmd_array;
+ 	/** Current command */
+@@ -188,12 +184,17 @@ struct lbs_private {
+ 	struct list_head cmdpendingq;
+ 
+ 	wait_queue_head_t cmd_pending;
+-	/* command related variables protected by priv->driver_lock */
+ 
+-	/** Async and Sync Event variables */
+-	u32 intcounter;
+-	u32 eventcause;
+-	u8 nodename[16];	/* nickname */
++	/* Command responses sent from the hardware to the driver */
++	u8 resp_idx;
++	u8 resp_buf[2][LBS_UPLD_SIZE];
++	u32 resp_len[2];
++
++	/* Events sent from hardware to driver */
++	struct kfifo *event_fifo;
++
++	/* nickname */
++	u8 nodename[16];
+ 
+ 	/** spin locks */
+ 	spinlock_t driver_lock;
+@@ -203,8 +204,6 @@ struct lbs_private {
+ 	int nr_retries;
+ 	int cmd_timed_out;
+ 
+-	u8 hisregcpy;
+-
+ 	/** current ssid/bssid related parameters*/
+ 	struct current_bss_params curbssparams;
+ 
+@@ -247,7 +246,7 @@ struct lbs_private {
+ 	struct sk_buff *currenttxskb;
+ 
+ 	/** NIC Operation characteristics */
+-	u16 currentpacketfilter;
++	u16 mac_control;
+ 	u32 connect_status;
+ 	u32 mesh_connect_status;
+ 	u16 regioncode;
+@@ -262,9 +261,6 @@ struct lbs_private {
+ 	char ps_supported;
+ 	u8 needtowakeup;
+ 
+-	struct PS_CMD_ConfirmSleep lbs_ps_confirm_sleep;
+-	struct cmd_header lbs_ps_confirm_wake;
+-
+ 	struct assoc_request * pending_assoc_req;
+ 	struct assoc_request * in_progress_assoc_req;
+ 
+@@ -315,16 +311,52 @@ struct lbs_private {
+ 	u32 enable11d;
+ 
+ 	/**	MISCELLANEOUS */
+-	u8 *prdeeprom;
+ 	struct lbs_offset_value offsetvalue;
+ 
+-	struct cmd_ds_802_11_get_log logmsg;
+-
+ 	u32 monitormode;
+-	int last_scanned_channel;
+ 	u8 fw_ready;
+ };
+ 
++extern struct cmd_confirm_sleep confirm_sleep;
++
++/**
++ *  @brief Structure used to store information for each beacon/probe response
++ */
++struct bss_descriptor {
++	u8 bssid[ETH_ALEN];
++
++	u8 ssid[IW_ESSID_MAX_SIZE + 1];
++	u8 ssid_len;
++
++	u16 capability;
++	u32 rssi;
++	u32 channel;
++	u16 beaconperiod;
++	u32 atimwindow;
++
++	/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
++	u8 mode;
++
++	/* zero-terminated array of supported data rates */
++	u8 rates[MAX_RATES + 1];
++
++	unsigned long last_scanned;
++
++	union ieeetypes_phyparamset phyparamset;
++	union IEEEtypes_ssparamset ssparamset;
++
++	struct ieeetypes_countryinfofullset countryinfo;
++
++	u8 wpa_ie[MAX_WPA_IE_LEN];
++	size_t wpa_ie_len;
++	u8 rsn_ie[MAX_WPA_IE_LEN];
++	size_t rsn_ie_len;
++
++	u8 mesh;
++
++	struct list_head list;
++};
++
+ /** Association request
+  *
+  * Encapsulates all the options that describe a specific assocation request
+diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
+index 21e6f98..dcfdb40 100644
+--- a/drivers/net/wireless/libertas/ethtool.c
++++ b/drivers/net/wireless/libertas/ethtool.c
+@@ -6,7 +6,6 @@
+ #include "decl.h"
+ #include "defs.h"
+ #include "dev.h"
+-#include "join.h"
+ #include "wext.h"
+ #include "cmd.h"
+ 
+@@ -25,13 +24,14 @@ static void lbs_ethtool_get_drvinfo(struct net_device *dev,
+ 					 struct ethtool_drvinfo *info)
+ {
+ 	struct lbs_private *priv = (struct lbs_private *) dev->priv;
+-	char fwver[32];
+-
+-	lbs_get_fwversion(priv, fwver, sizeof(fwver) - 1);
+ 
++	snprintf(info->fw_version, 32, "%u.%u.%u.p%u",
++		priv->fwrelease >> 24 & 0xff,
++		priv->fwrelease >> 16 & 0xff,
++		priv->fwrelease >>  8 & 0xff,
++		priv->fwrelease       & 0xff);
+ 	strcpy(info->driver, "libertas");
+ 	strcpy(info->version, lbs_driver_version);
+-	strcpy(info->fw_version, fwver);
+ }
+ 
+ /* All 8388 parts have 16KiB EEPROM size at the time of writing.
+@@ -48,61 +48,28 @@ static int lbs_ethtool_get_eeprom(struct net_device *dev,
+                                   struct ethtool_eeprom *eeprom, u8 * bytes)
+ {
+ 	struct lbs_private *priv = (struct lbs_private *) dev->priv;
+-	struct lbs_ioctl_regrdwr regctrl;
+-	char *ptr;
++	struct cmd_ds_802_11_eeprom_access cmd;
+ 	int ret;
+ 
+-	regctrl.action = 0;
+-	regctrl.offset = eeprom->offset;
+-	regctrl.NOB = eeprom->len;
+-
+-	if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN)
+-		return -EINVAL;
+-
+-//      mutex_lock(&priv->mutex);
+-
+-	priv->prdeeprom = kmalloc(eeprom->len+sizeof(regctrl), GFP_KERNEL);
+-	if (!priv->prdeeprom)
+-		return -ENOMEM;
+-	memcpy(priv->prdeeprom, &regctrl, sizeof(regctrl));
+-
+-	/* +14 is for action, offset, and NOB in
+-	 * response */
+-	lbs_deb_ethtool("action:%d offset: %x NOB: %02x\n",
+-	       regctrl.action, regctrl.offset, regctrl.NOB);
++	lbs_deb_enter(LBS_DEB_ETHTOOL);
+ 
+-	ret = lbs_prepare_and_send_command(priv,
+-				    CMD_802_11_EEPROM_ACCESS,
+-				    regctrl.action,
+-				    CMD_OPTION_WAITFORRSP, 0,
+-				    &regctrl);
+-
+-	if (ret) {
+-		if (priv->prdeeprom)
+-			kfree(priv->prdeeprom);
+-		goto done;
++	if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
++	    eeprom->len > LBS_EEPROM_READ_LEN) {
++		ret = -EINVAL;
++		goto out;
+ 	}
+ 
+-	mdelay(10);
+-
+-	ptr = (char *)priv->prdeeprom;
+-
+-	/* skip the command header, but include the "value" u32 variable */
+-	ptr = ptr + sizeof(struct lbs_ioctl_regrdwr) - 4;
+-
+-	/*
+-	 * Return the result back to the user
+-	 */
+-	memcpy(bytes, ptr, eeprom->len);
+-
+-	if (priv->prdeeprom)
+-		kfree(priv->prdeeprom);
+-//	mutex_unlock(&priv->mutex);
+-
+-	ret = 0;
+-
+-done:
+-	lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret);
++	cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) -
++		LBS_EEPROM_READ_LEN + eeprom->len);
++	cmd.action = cpu_to_le16(CMD_ACT_GET);
++	cmd.offset = cpu_to_le16(eeprom->offset);
++	cmd.len    = cpu_to_le16(eeprom->len);
++	ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd);
++	if (!ret)
++		memcpy(bytes, cmd.value, eeprom->len);
++
++out:
++	lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret);
+         return ret;
+ }
+ 
+diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
+index 1aa0407..3915c31 100644
+--- a/drivers/net/wireless/libertas/host.h
++++ b/drivers/net/wireless/libertas/host.h
+@@ -33,7 +33,6 @@
+ #define CMD_RET_802_11_ASSOCIATE		0x8012
+ 
+ /* Command codes */
+-#define CMD_CODE_DNLD				0x0002
+ #define CMD_GET_HW_SPEC				0x0003
+ #define	CMD_EEPROM_UPDATE			0x0004
+ #define CMD_802_11_RESET			0x0005
+@@ -68,8 +67,6 @@
+ #define CMD_802_11_AD_HOC_JOIN			0x002c
+ #define CMD_802_11_QUERY_TKIP_REPLY_CNTRS	0x002e
+ #define CMD_802_11_ENABLE_RSN			0x002f
+-#define CMD_802_11_PAIRWISE_TSC			0x0036
+-#define CMD_802_11_GROUP_TSC			0x0037
+ #define CMD_802_11_SET_AFC			0x003c
+ #define CMD_802_11_GET_AFC			0x003d
+ #define CMD_802_11_AD_HOC_STOP			0x0040
+@@ -87,7 +84,6 @@
+ #define CMD_802_11_INACTIVITY_TIMEOUT		0x0067
+ #define CMD_802_11_SLEEP_PERIOD			0x0068
+ #define CMD_802_11_TPC_CFG			0x0072
+-#define CMD_802_11_PWR_CFG			0x0073
+ #define CMD_802_11_FW_WAKE_METHOD		0x0074
+ #define CMD_802_11_SUBSCRIBE_EVENT		0x0075
+ #define CMD_802_11_RATE_ADAPT_RATESET		0x0076
+diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
+index d35b015..f29bc5b 100644
+--- a/drivers/net/wireless/libertas/hostcmd.h
++++ b/drivers/net/wireless/libertas/hostcmd.h
+@@ -174,9 +174,11 @@ struct cmd_ds_802_11_subscribe_event {
+  * Define data structure for CMD_802_11_SCAN
+  */
+ struct cmd_ds_802_11_scan {
+-	u8 bsstype;
+-	u8 bssid[ETH_ALEN];
+-	u8 tlvbuffer[1];
++	struct cmd_header hdr;
++
++	uint8_t bsstype;
++	uint8_t bssid[ETH_ALEN];
++	uint8_t tlvbuffer[0];
+ #if 0
+ 	mrvlietypes_ssidparamset_t ssidParamSet;
+ 	mrvlietypes_chanlistparamset_t ChanListParamSet;
+@@ -185,12 +187,16 @@ struct cmd_ds_802_11_scan {
+ };
+ 
+ struct cmd_ds_802_11_scan_rsp {
++	struct cmd_header hdr;
++
+ 	__le16 bssdescriptsize;
+-	u8 nr_sets;
+-	u8 bssdesc_and_tlvbuffer[1];
++	uint8_t nr_sets;
++	uint8_t bssdesc_and_tlvbuffer[0];
+ };
+ 
+ struct cmd_ds_802_11_get_log {
++	struct cmd_header hdr;
++
+ 	__le32 mcasttxframe;
+ 	__le32 failed;
+ 	__le32 retry;
+@@ -207,8 +213,9 @@ struct cmd_ds_802_11_get_log {
+ };
+ 
+ struct cmd_ds_mac_control {
++	struct cmd_header hdr;
+ 	__le16 action;
+-	__le16 reserved;
++	u16 reserved;
+ };
+ 
+ struct cmd_ds_mac_multicast_adr {
+@@ -420,6 +427,8 @@ struct cmd_ds_802_11_rssi_rsp {
+ };
+ 
+ struct cmd_ds_802_11_mac_address {
++	struct cmd_header hdr;
++
+ 	__le16 action;
+ 	u8 macadd[ETH_ALEN];
+ };
+@@ -471,14 +480,11 @@ struct cmd_ds_802_11_ps_mode {
+ 	__le16 locallisteninterval;
+ };
+ 
+-struct PS_CMD_ConfirmSleep {
+-	__le16 command;
+-	__le16 size;
+-	__le16 seqnum;
+-	__le16 result;
++struct cmd_confirm_sleep {
++	struct cmd_header hdr;
+ 
+ 	__le16 action;
+-	__le16 reserved1;
++	__le16 nullpktinterval;
+ 	__le16 multipledtim;
+ 	__le16 reserved;
+ 	__le16 locallisteninterval;
+@@ -572,17 +578,20 @@ struct cmd_ds_host_sleep {
+ } __attribute__ ((packed));
+ 
+ struct cmd_ds_802_11_key_material {
++	struct cmd_header hdr;
++
+ 	__le16 action;
+ 	struct MrvlIEtype_keyParamSet keyParamSet[2];
+ } __attribute__ ((packed));
+ 
+ struct cmd_ds_802_11_eeprom_access {
++	struct cmd_header hdr;
+ 	__le16 action;
+-
+-	/* multiple 4 */
+ 	__le16 offset;
+-	__le16 bytecount;
+-	u8 value;
++	__le16 len;
++	/* firmware says it returns a maximum of 20 bytes */
++#define LBS_EEPROM_READ_LEN 20
++	u8 value[LBS_EEPROM_READ_LEN];
+ } __attribute__ ((packed));
+ 
+ struct cmd_ds_802_11_tpc_cfg {
+@@ -600,14 +609,6 @@ struct cmd_ds_802_11_led_ctrl {
+ 	u8 data[256];
+ } __attribute__ ((packed));
+ 
+-struct cmd_ds_802_11_pwr_cfg {
+-	__le16 action;
+-	u8 enable;
+-	s8 PA_P0;
+-	s8 PA_P1;
+-	s8 PA_P2;
+-} __attribute__ ((packed));
+-
+ struct cmd_ds_802_11_afc {
+ 	__le16 afc_auto;
+ 	union {
+@@ -689,15 +690,11 @@ struct cmd_ds_command {
+ 	/* command Body */
+ 	union {
+ 		struct cmd_ds_802_11_ps_mode psmode;
+-		struct cmd_ds_802_11_scan scan;
+-		struct cmd_ds_802_11_scan_rsp scanresp;
+-		struct cmd_ds_mac_control macctrl;
+ 		struct cmd_ds_802_11_associate associate;
+ 		struct cmd_ds_802_11_deauthenticate deauth;
+ 		struct cmd_ds_802_11_ad_hoc_start ads;
+ 		struct cmd_ds_802_11_reset reset;
+ 		struct cmd_ds_802_11_ad_hoc_result result;
+-		struct cmd_ds_802_11_get_log glog;
+ 		struct cmd_ds_802_11_authenticate auth;
+ 		struct cmd_ds_802_11_get_stat gstat;
+ 		struct cmd_ds_802_3_get_stat gstat_8023;
+@@ -711,18 +708,14 @@ struct cmd_ds_command {
+ 		struct cmd_ds_802_11_rssi rssi;
+ 		struct cmd_ds_802_11_rssi_rsp rssirsp;
+ 		struct cmd_ds_802_11_disassociate dassociate;
+-		struct cmd_ds_802_11_mac_address macadd;
+-		struct cmd_ds_802_11_key_material keymaterial;
+ 		struct cmd_ds_mac_reg_access macreg;
+ 		struct cmd_ds_bbp_reg_access bbpreg;
+ 		struct cmd_ds_rf_reg_access rfreg;
+-		struct cmd_ds_802_11_eeprom_access rdeeprom;
+ 
+ 		struct cmd_ds_802_11d_domain_info domaininfo;
+ 		struct cmd_ds_802_11d_domain_info domaininforesp;
+ 
+ 		struct cmd_ds_802_11_tpc_cfg tpccfg;
+-		struct cmd_ds_802_11_pwr_cfg pwrcfg;
+ 		struct cmd_ds_802_11_afc afc;
+ 		struct cmd_ds_802_11_led_ctrl ledgpio;
+ 
+diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
+index 038c66a..54280e2 100644
+--- a/drivers/net/wireless/libertas/if_cs.c
++++ b/drivers/net/wireless/libertas/if_cs.c
+@@ -83,14 +83,14 @@ static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg)
+ {
+ 	unsigned int val = ioread8(card->iobase + reg);
+ 	if (debug_output)
+-		printk(KERN_INFO "##inb %08x<%02x\n", reg, val);
++		printk(KERN_INFO "inb %08x<%02x\n", reg, val);
+ 	return val;
+ }
+ static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg)
+ {
+ 	unsigned int val = ioread16(card->iobase + reg);
+ 	if (debug_output)
+-		printk(KERN_INFO "##inw %08x<%04x\n", reg, val);
++		printk(KERN_INFO "inw %08x<%04x\n", reg, val);
+ 	return val;
+ }
+ static inline void if_cs_read16_rep(
+@@ -100,7 +100,7 @@ static inline void if_cs_read16_rep(
+ 	unsigned long count)
+ {
+ 	if (debug_output)
+-		printk(KERN_INFO "##insw %08x<(0x%lx words)\n",
++		printk(KERN_INFO "insw %08x<(0x%lx words)\n",
+ 			reg, count);
+ 	ioread16_rep(card->iobase + reg, buf, count);
+ }
+@@ -108,14 +108,14 @@ static inline void if_cs_read16_rep(
+ static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val)
+ {
+ 	if (debug_output)
+-		printk(KERN_INFO "##outb %08x>%02x\n", reg, val);
++		printk(KERN_INFO "outb %08x>%02x\n", reg, val);
+ 	iowrite8(val, card->iobase + reg);
+ }
+ 
+ static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val)
+ {
+ 	if (debug_output)
+-		printk(KERN_INFO "##outw %08x>%04x\n", reg, val);
++		printk(KERN_INFO "outw %08x>%04x\n", reg, val);
+ 	iowrite16(val, card->iobase + reg);
+ }
+ 
+@@ -126,7 +126,7 @@ static inline void if_cs_write16_rep(
+ 	unsigned long count)
+ {
+ 	if (debug_output)
+-		printk(KERN_INFO "##outsw %08x>(0x%lx words)\n",
++		printk(KERN_INFO "outsw %08x>(0x%lx words)\n",
+ 			reg, count);
+ 	iowrite16_rep(card->iobase + reg, buf, count);
+ }
+@@ -199,17 +199,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
+ #define IF_CS_C_S_CARDEVENT		0x0010
+ #define IF_CS_C_S_MASK			0x001f
+ #define IF_CS_C_S_STATUS_MASK		0x7f00
+-/* The following definitions should be the same as the MRVDRV_ ones */
+-
+-#if MRVDRV_CMD_DNLD_RDY != IF_CS_C_S_CMD_DNLD_RDY
+-#error MRVDRV_CMD_DNLD_RDY and IF_CS_C_S_CMD_DNLD_RDY not in sync
+-#endif
+-#if MRVDRV_CMD_UPLD_RDY != IF_CS_C_S_CMD_UPLD_RDY
+-#error MRVDRV_CMD_UPLD_RDY and IF_CS_C_S_CMD_UPLD_RDY not in sync
+-#endif
+-#if MRVDRV_CARDEVENT != IF_CS_C_S_CARDEVENT
+-#error MRVDRV_CARDEVENT and IF_CS_C_S_CARDEVENT not in sync
+-#endif
+ 
+ #define IF_CS_C_INT_CAUSE		0x00000022
+ #define	IF_CS_C_IC_MASK			0x001f
+@@ -226,55 +215,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
+ 
+ 
+ /********************************************************************/
+-/* Interrupts                                                       */
+-/********************************************************************/
+-
+-static inline void if_cs_enable_ints(struct if_cs_card *card)
+-{
+-	lbs_deb_enter(LBS_DEB_CS);
+-	if_cs_write16(card, IF_CS_H_INT_MASK, 0);
+-}
+-
+-static inline void if_cs_disable_ints(struct if_cs_card *card)
+-{
+-	lbs_deb_enter(LBS_DEB_CS);
+-	if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
+-}
+-
+-static irqreturn_t if_cs_interrupt(int irq, void *data)
+-{
+-	struct if_cs_card *card = data;
+-	u16 int_cause;
+-
+-	lbs_deb_enter(LBS_DEB_CS);
+-
+-	int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
+-	if (int_cause == 0x0) {
+-		/* Not for us */
+-		return IRQ_NONE;
+-
+-	} else if (int_cause == 0xffff) {
+-		/* Read in junk, the card has probably been removed */
+-		card->priv->surpriseremoved = 1;
+-		return IRQ_HANDLED;
+-	} else {
+-		if (int_cause & IF_CS_H_IC_TX_OVER)
+-			lbs_host_to_card_done(card->priv);
+-
+-		/* clear interrupt */
+-		if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK);
+-	}
+-	spin_lock(&card->priv->driver_lock);
+-	lbs_interrupt(card->priv);
+-	spin_unlock(&card->priv->driver_lock);
+-
+-	return IRQ_HANDLED;
+-}
+-
+-
+-
+-
+-/********************************************************************/
+ /* I/O                                                              */
+ /********************************************************************/
+ 
+@@ -351,6 +291,7 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
+  */
+ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
+ {
++	unsigned long flags;
+ 	int ret = -1;
+ 	u16 val;
+ 
+@@ -378,6 +319,12 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
+ 	 * bytes */
+ 	*len -= 8;
+ 	ret = 0;
++
++	/* Clear this flag again */
++	spin_lock_irqsave(&priv->driver_lock, flags);
++	priv->dnld_sent = DNLD_RES_RECEIVED;
++	spin_unlock_irqrestore(&priv->driver_lock, flags);
++
+ out:
+ 	lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len);
+ 	return ret;
+@@ -396,11 +343,9 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
+ 	if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
+ 		lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len);
+ 		priv->stats.rx_dropped++;
+-		printk(KERN_INFO "##HS %s:%d TODO\n", __FUNCTION__, __LINE__);
+ 		goto dat_err;
+ 	}
+ 
+-	//TODO: skb = dev_alloc_skb(len+ETH_FRAME_LEN+MRVDRV_SNAP_HEADER_LEN+EXTRA_LEN);
+ 	skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2);
+ 	if (!skb)
+ 		goto out;
+@@ -425,6 +370,96 @@ out:
+ 
+ 
+ /********************************************************************/
++/* Interrupts                                                       */
++/********************************************************************/
++
++static inline void if_cs_enable_ints(struct if_cs_card *card)
++{
++	lbs_deb_enter(LBS_DEB_CS);
++	if_cs_write16(card, IF_CS_H_INT_MASK, 0);
++}
++
++static inline void if_cs_disable_ints(struct if_cs_card *card)
++{
++	lbs_deb_enter(LBS_DEB_CS);
++	if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
++}
++
++
++static irqreturn_t if_cs_interrupt(int irq, void *data)
++{
++	struct if_cs_card *card = data;
++	struct lbs_private *priv = card->priv;
++	u16 cause;
++
++	lbs_deb_enter(LBS_DEB_CS);
++
++	cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
++	if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK);
++
++	lbs_deb_cs("cause 0x%04x\n", cause);
++	if (cause == 0) {
++		/* Not for us */
++		return IRQ_NONE;
++	}
++
++	if (cause == 0xffff) {
++		/* Read in junk, the card has probably been removed */
++		card->priv->surpriseremoved = 1;
++		return IRQ_HANDLED;
++	}
++
++	/* TODO: I'm not sure what the best ordering is */
++
++	cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
++
++	if (cause & IF_CS_C_S_RX_UPLD_RDY) {
++		struct sk_buff *skb;
++		lbs_deb_cs("rx packet\n");
++		skb = if_cs_receive_data(priv);
++		if (skb)
++			lbs_process_rxed_packet(priv, skb);
++	}
++
++	if (cause & IF_CS_H_IC_TX_OVER) {
++		lbs_deb_cs("tx over\n");
++		lbs_host_to_card_done(priv);
++	}
++
++	if (cause & IF_CS_C_S_CMD_UPLD_RDY) {
++		unsigned long flags;
++		u8 i;
++
++		lbs_deb_cs("cmd upload ready\n");
++		spin_lock_irqsave(&priv->driver_lock, flags);
++		i = (priv->resp_idx == 0) ? 1 : 0;
++		spin_unlock_irqrestore(&priv->driver_lock, flags);
++
++		BUG_ON(priv->resp_len[i]);
++		if_cs_receive_cmdres(priv, priv->resp_buf[i],
++			&priv->resp_len[i]);
++
++		spin_lock_irqsave(&priv->driver_lock, flags);
++		lbs_notify_command_response(priv, i);
++		spin_unlock_irqrestore(&priv->driver_lock, flags);
++	}
++
++	if (cause & IF_CS_H_IC_HOST_EVENT) {
++		u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS)
++			& IF_CS_C_S_STATUS_MASK;
++		if_cs_write16(priv->card, IF_CS_H_INT_CAUSE,
++			IF_CS_H_IC_HOST_EVENT);
++		lbs_deb_cs("eventcause 0x%04x\n", event);
++		lbs_queue_event(priv, event >> 8 & 0xff);
++	}
++
++	return IRQ_HANDLED;
++}
++
++
++
++
++/********************************************************************/
+ /* Firmware                                                         */
+ /********************************************************************/
+ 
+@@ -476,8 +511,6 @@ static int if_cs_prog_helper(struct if_cs_card *card)
+ 
+ 		if (remain < count)
+ 			count = remain;
+-		/* printk(KERN_INFO "//HS %d loading %d of %d bytes\n",
+-			__LINE__, sent, fw->size); */
+ 
+ 		/* "write the number of bytes to be sent to the I/O Command
+ 		 * write length register" */
+@@ -544,18 +577,12 @@ static int if_cs_prog_real(struct if_cs_card *card)
+ 
+ 	ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK);
+ 	if (ret < 0) {
+-		int i;
+ 		lbs_pr_err("helper firmware doesn't answer\n");
+-		for (i = 0; i < 0x50; i += 2)
+-			printk(KERN_INFO "## HS %02x: %04x\n",
+-				i, if_cs_read16(card, i));
+ 		goto err_release;
+ 	}
+ 
+ 	for (sent = 0; sent < fw->size; sent += len) {
+ 		len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW);
+-		/* printk(KERN_INFO "//HS %d loading %d of %d bytes\n",
+-			__LINE__, sent, fw->size); */
+ 		if (len & 1) {
+ 			retry++;
+ 			lbs_pr_info("odd, need to retry this firmware block\n");
+@@ -642,64 +669,6 @@ static int if_cs_host_to_card(struct lbs_private *priv,
+ }
+ 
+ 
+-static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg)
+-{
+-	struct if_cs_card *card = (struct if_cs_card *)priv->card;
+-	int ret = 0;
+-	u16 int_cause;
+-	*ireg = 0;
+-
+-	lbs_deb_enter(LBS_DEB_CS);
+-
+-	if (priv->surpriseremoved)
+-		goto out;
+-
+-	int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK;
+-	if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause);
+-
+-	*ireg = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
+-
+-	if (!*ireg)
+-		goto sbi_get_int_status_exit;
+-
+-sbi_get_int_status_exit:
+-
+-	/* is there a data packet for us? */
+-	if (*ireg & IF_CS_C_S_RX_UPLD_RDY) {
+-		struct sk_buff *skb = if_cs_receive_data(priv);
+-		lbs_process_rxed_packet(priv, skb);
+-		*ireg &= ~IF_CS_C_S_RX_UPLD_RDY;
+-	}
+-
+-	if (*ireg & IF_CS_C_S_TX_DNLD_RDY) {
+-		priv->dnld_sent = DNLD_RES_RECEIVED;
+-	}
+-
+-	/* Card has a command result for us */
+-	if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) {
+-		ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len);
+-		if (ret < 0)
+-			lbs_pr_err("could not receive cmd from card\n");
+-	}
+-
+-out:
+-	lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy);
+-	return ret;
+-}
+-
+-
+-static int if_cs_read_event_cause(struct lbs_private *priv)
+-{
+-	lbs_deb_enter(LBS_DEB_CS);
+-
+-	priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5;
+-	if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT);
+-
+-	return 0;
+-}
+-
+-
+-
+ /********************************************************************/
+ /* Card Services                                                    */
+ /********************************************************************/
+@@ -852,13 +821,10 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
+ 		goto out2;
+ 	}
+ 
+-	/* Store pointers to our call-back functions */
++	/* Finish setting up fields in lbs_private */
+ 	card->priv = priv;
+ 	priv->card = card;
+-	priv->hw_host_to_card     = if_cs_host_to_card;
+-	priv->hw_get_int_status   = if_cs_get_int_status;
+-	priv->hw_read_event_cause = if_cs_read_event_cause;
+-
++	priv->hw_host_to_card = if_cs_host_to_card;
+ 	priv->fw_ready = 1;
+ 
+ 	/* Now actually get the IRQ */
+@@ -880,6 +846,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
+ 		goto out3;
+ 	}
+ 
++	/* The firmware for the CF card supports powersave */
++	priv->ps_supported = 1;
++
+ 	ret = 0;
+ 	goto out;
+ 
+diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
+index eed7320..51f664b 100644
+--- a/drivers/net/wireless/libertas/if_sdio.c
++++ b/drivers/net/wireless/libertas/if_sdio.c
+@@ -91,8 +91,6 @@ struct if_sdio_card {
+ 	const char		*firmware;
+ 
+ 	u8			buffer[65536];
+-	u8			int_cause;
+-	u32			event;
+ 
+ 	spinlock_t		lock;
+ 	struct if_sdio_packet	*packets;
+@@ -129,13 +127,13 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
+ static int if_sdio_handle_cmd(struct if_sdio_card *card,
+ 		u8 *buffer, unsigned size)
+ {
++	struct lbs_private *priv = card->priv;
+ 	int ret;
+ 	unsigned long flags;
++	u8 i;
+ 
+ 	lbs_deb_enter(LBS_DEB_SDIO);
+ 
+-	spin_lock_irqsave(&card->priv->driver_lock, flags);
+-
+ 	if (size > LBS_CMD_BUFFER_SIZE) {
+ 		lbs_deb_sdio("response packet too large (%d bytes)\n",
+ 			(int)size);
+@@ -143,20 +141,20 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
+ 		goto out;
+ 	}
+ 
+-	memcpy(card->priv->upld_buf, buffer, size);
+-	card->priv->upld_len = size;
++	spin_lock_irqsave(&priv->driver_lock, flags);
+ 
+-	card->int_cause |= MRVDRV_CMD_UPLD_RDY;
++	i = (priv->resp_idx == 0) ? 1 : 0;
++	BUG_ON(priv->resp_len[i]);
++	priv->resp_len[i] = size;
++	memcpy(priv->resp_buf[i], buffer, size);
++	lbs_notify_command_response(priv, i);
+ 
+-	lbs_interrupt(card->priv);
++	spin_unlock_irqrestore(&card->priv->driver_lock, flags);
+ 
+ 	ret = 0;
+ 
+ out:
+-	spin_unlock_irqrestore(&card->priv->driver_lock, flags);
+-
+ 	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+-
+ 	return ret;
+ }
+ 
+@@ -202,7 +200,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
+ 		u8 *buffer, unsigned size)
+ {
+ 	int ret;
+-	unsigned long flags;
+ 	u32 event;
+ 
+ 	lbs_deb_enter(LBS_DEB_SDIO);
+@@ -222,18 +219,9 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
+ 		event |= buffer[2] << 16;
+ 		event |= buffer[1] << 8;
+ 		event |= buffer[0] << 0;
+-		event <<= SBI_EVENT_CAUSE_SHIFT;
+ 	}
+ 
+-	spin_lock_irqsave(&card->priv->driver_lock, flags);
+-
+-	card->event = event;
+-	card->int_cause |= MRVDRV_CARDEVENT;
+-
+-	lbs_interrupt(card->priv);
+-
+-	spin_unlock_irqrestore(&card->priv->driver_lock, flags);
+-
++	lbs_queue_event(card->priv, event & 0xFF);
+ 	ret = 0;
+ 
+ out:
+@@ -770,37 +758,6 @@ out:
+ 	return ret;
+ }
+ 
+-static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg)
+-{
+-	struct if_sdio_card *card;
+-
+-	lbs_deb_enter(LBS_DEB_SDIO);
+-
+-	card = priv->card;
+-
+-	*ireg = card->int_cause;
+-	card->int_cause = 0;
+-
+-	lbs_deb_leave(LBS_DEB_SDIO);
+-
+-	return 0;
+-}
+-
+-static int if_sdio_read_event_cause(struct lbs_private *priv)
+-{
+-	struct if_sdio_card *card;
+-
+-	lbs_deb_enter(LBS_DEB_SDIO);
+-
+-	card = priv->card;
+-
+-	priv->eventcause = card->event;
+-
+-	lbs_deb_leave(LBS_DEB_SDIO);
+-
+-	return 0;
+-}
+-
+ /*******************************************************************/
+ /* SDIO callbacks                                                  */
+ /*******************************************************************/
+@@ -953,8 +910,6 @@ static int if_sdio_probe(struct sdio_func *func,
+ 
+ 	priv->card = card;
+ 	priv->hw_host_to_card = if_sdio_host_to_card;
+-	priv->hw_get_int_status = if_sdio_get_int_status;
+-	priv->hw_read_event_cause = if_sdio_read_event_cause;
+ 
+ 	priv->fw_ready = 1;
+ 
+diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
+index 75aed9d..8032df7 100644
+--- a/drivers/net/wireless/libertas/if_usb.c
++++ b/drivers/net/wireless/libertas/if_usb.c
+@@ -38,8 +38,6 @@ static void if_usb_receive_fwload(struct urb *urb);
+ static int if_usb_prog_firmware(struct if_usb_card *cardp);
+ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
+ 			       uint8_t *payload, uint16_t nb);
+-static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *);
+-static int if_usb_read_event_cause(struct lbs_private *);
+ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
+ 			uint16_t nb);
+ static void if_usb_free(struct if_usb_card *cardp);
+@@ -233,8 +231,6 @@ static int if_usb_probe(struct usb_interface *intf,
+ 	cardp->priv->fw_ready = 1;
+ 
+ 	priv->hw_host_to_card = if_usb_host_to_card;
+-	priv->hw_get_int_status = if_usb_get_int_status;
+-	priv->hw_read_event_cause = if_usb_read_event_cause;
+ 	cardp->boot2_version = udev->descriptor.bcdDevice;
+ 
+ 	if_usb_submit_rx_urb(cardp);
+@@ -582,7 +578,6 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
+ 	skb_pull(skb, MESSAGE_HEADER_LEN);
+ 
+ 	lbs_process_rxed_packet(priv, skb);
+-	priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
+ }
+ 
+ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
+@@ -590,6 +585,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
+ 				      struct if_usb_card *cardp,
+ 				      struct lbs_private *priv)
+ {
++	u8 i;
++
+ 	if (recvlength > LBS_CMD_BUFFER_SIZE) {
+ 		lbs_deb_usbd(&cardp->udev->dev,
+ 			     "The receive buffer is too large\n");
+@@ -601,12 +598,15 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
+ 		BUG();
+ 
+ 	spin_lock(&priv->driver_lock);
+-	cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY;
+-	priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
+-	memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len);
+ 
++	i = (priv->resp_idx == 0) ? 1 : 0;
++	BUG_ON(priv->resp_len[i]);
++	priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN);
++	memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN,
++		priv->resp_len[i]);
+ 	kfree_skb(skb);
+-	lbs_interrupt(priv);
++	lbs_notify_command_response(priv, i);
++
+ 	spin_unlock(&priv->driver_lock);
+ 
+ 	lbs_deb_usbd(&cardp->udev->dev,
+@@ -629,6 +629,7 @@ static void if_usb_receive(struct urb *urb)
+ 	uint8_t *recvbuff = NULL;
+ 	uint32_t recvtype = 0;
+ 	__le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
++	uint32_t event;
+ 
+ 	lbs_deb_enter(LBS_DEB_USB);
+ 
+@@ -660,26 +661,20 @@ static void if_usb_receive(struct urb *urb)
+ 		break;
+ 
+ 	case CMD_TYPE_INDICATION:
+-		/* Event cause handling */
+-		spin_lock(&priv->driver_lock);
++		/* Event handling */
++		event = le32_to_cpu(pkt[1]);
++		lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event);
++		kfree_skb(skb);
+ 
+-		cardp->usb_event_cause = le32_to_cpu(pkt[1]);
++		/* Icky undocumented magic special case */
++		if (event & 0xffff0000) {
++			u32 trycount = (event & 0xffff0000) >> 16;
+ 
+-		lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n",
+-			     cardp->usb_event_cause);
++			lbs_send_tx_feedback(priv, trycount);
++		} else
++			lbs_queue_event(priv, event & 0xFF);
++		break;
+ 
+-		/* Icky undocumented magic special case */
+-		if (cardp->usb_event_cause & 0xffff0000) {
+-			lbs_send_tx_feedback(priv);
+-			spin_unlock(&priv->driver_lock);
+-			break;
+-		}
+-		cardp->usb_event_cause <<= 3;
+-		cardp->usb_int_cause |= MRVDRV_CARDEVENT;
+-		kfree_skb(skb);
+-		lbs_interrupt(priv);
+-		spin_unlock(&priv->driver_lock);
+-		goto rx_exit;
+ 	default:
+ 		lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n",
+ 			     recvtype);
+@@ -722,30 +717,6 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
+ 	return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN);
+ }
+ 
+-/* called with priv->driver_lock held */
+-static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg)
+-{
+-	struct if_usb_card *cardp = priv->card;
+-
+-	*ireg = cardp->usb_int_cause;
+-	cardp->usb_int_cause = 0;
+-
+-	lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg);
+-
+-	return 0;
+-}
+-
+-static int if_usb_read_event_cause(struct lbs_private *priv)
+-{
+-	struct if_usb_card *cardp = priv->card;
+-
+-	priv->eventcause = cardp->usb_event_cause;
+-	/* Re-submit rx urb here to avoid event lost issue */
+-	if_usb_submit_rx_urb(cardp);
+-
+-	return 0;
+-}
+-
+ /**
+  *  @brief This function issues Boot command to the Boot2 code
+  *  @param ivalue   1:Boot from FW by USB-Download
+diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
+index e4829a3..5771a83 100644
+--- a/drivers/net/wireless/libertas/if_usb.h
++++ b/drivers/net/wireless/libertas/if_usb.h
+@@ -46,8 +46,6 @@ struct if_usb_card {
+ 	struct lbs_private *priv;
+ 
+ 	struct sk_buff *rx_skb;
+-	uint32_t usb_event_cause;
+-	uint8_t usb_int_cause;
+ 
+ 	uint8_t ep_in;
+ 	uint8_t ep_out;
+diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
+deleted file mode 100644
+index 2d45080..0000000
+--- a/drivers/net/wireless/libertas/join.c
++++ /dev/null
+@@ -1,895 +0,0 @@
+-/**
+-  *  Functions implementing wlan infrastructure and adhoc join routines,
+-  *  IOCTL handlers as well as command preperation and response routines
+-  *  for sending adhoc start, adhoc join, and association commands
+-  *  to the firmware.
+-  */
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/wireless.h>
+-#include <linux/etherdevice.h>
+-
+-#include <net/iw_handler.h>
+-
+-#include "host.h"
+-#include "decl.h"
+-#include "join.h"
+-#include "dev.h"
+-#include "assoc.h"
+-
+-/* The firmware needs certain bits masked out of the beacon-derviced capability
+- * field when associating/joining to BSSs.
+- */
+-#define CAPINFO_MASK	(~(0xda00))
+-
+-/**
+- *  @brief This function finds common rates between rate1 and card rates.
+- *
+- * It will fill common rates in rate1 as output if found.
+- *
+- * NOTE: Setting the MSB of the basic rates need to be taken
+- *   care, either before or after calling this function
+- *
+- *  @param priv     A pointer to struct lbs_private structure
+- *  @param rate1       the buffer which keeps input and output
+- *  @param rate1_size  the size of rate1 buffer; new size of buffer on return
+- *
+- *  @return            0 or -1
+- */
+-static int get_common_rates(struct lbs_private *priv,
+-	u8 *rates,
+-	u16 *rates_size)
+-{
+-	u8 *card_rates = lbs_bg_rates;
+-	size_t num_card_rates = sizeof(lbs_bg_rates);
+-	int ret = 0, i, j;
+-	u8 tmp[30];
+-	size_t tmp_size = 0;
+-
+-	/* For each rate in card_rates that exists in rate1, copy to tmp */
+-	for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
+-		for (j = 0; rates[j] && (j < *rates_size); j++) {
+-			if (rates[j] == card_rates[i])
+-				tmp[tmp_size++] = card_rates[i];
+-		}
+-	}
+-
+-	lbs_deb_hex(LBS_DEB_JOIN, "AP rates    ", rates, *rates_size);
+-	lbs_deb_hex(LBS_DEB_JOIN, "card rates  ", card_rates, num_card_rates);
+-	lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
+-	lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
+-
+-	if (!priv->auto_rate) {
+-		for (i = 0; i < tmp_size; i++) {
+-			if (tmp[i] == priv->cur_rate)
+-				goto done;
+-		}
+-		lbs_pr_alert("Previously set fixed data rate %#x isn't "
+-		       "compatible with the network.\n", priv->cur_rate);
+-		ret = -1;
+-		goto done;
+-	}
+-	ret = 0;
+-
+-done:
+-	memset(rates, 0, *rates_size);
+-	*rates_size = min_t(int, tmp_size, *rates_size);
+-	memcpy(rates, tmp, *rates_size);
+-	return ret;
+-}
+-
+-
+-/**
+- *  @brief Sets the MSB on basic rates as the firmware requires
+- *
+- * Scan through an array and set the MSB for basic data rates.
+- *
+- *  @param rates     buffer of data rates
+- *  @param len       size of buffer
+- */
+-static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
+-{
+-	int i;
+-
+-	for (i = 0; i < len; i++) {
+-		if (rates[i] == 0x02 || rates[i] == 0x04 ||
+-		    rates[i] == 0x0b || rates[i] == 0x16)
+-			rates[i] |= 0x80;
+-	}
+-}
+-
+-/**
+- *  @brief Unsets the MSB on basic rates
+- *
+- * Scan through an array and unset the MSB for basic data rates.
+- *
+- *  @param rates     buffer of data rates
+- *  @param len       size of buffer
+- */
+-void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
+-{
+-	int i;
+-
+-	for (i = 0; i < len; i++)
+-		rates[i] &= 0x7f;
+-}
+-
+-
+-/**
+- *  @brief Associate to a specific BSS discovered in a scan
+- *
+- *  @param priv      A pointer to struct lbs_private structure
+- *  @param pbssdesc  Pointer to the BSS descriptor to associate with.
+- *
+- *  @return          0-success, otherwise fail
+- */
+-int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req)
+-{
+-	int ret;
+-
+-	lbs_deb_enter(LBS_DEB_ASSOC);
+-
+-	ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
+-				    0, CMD_OPTION_WAITFORRSP,
+-				    0, assoc_req->bss.bssid);
+-
+-	if (ret)
+-		goto done;
+-
+-	/* set preamble to firmware */
+-	if (   (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+-	    && (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
+-		priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
+-	else
+-		priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+-
+-	lbs_set_radio_control(priv);
+-
+-	ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
+-				    0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
+-
+-done:
+-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+-	return ret;
+-}
+-
+-/**
+- *  @brief Start an Adhoc Network
+- *
+- *  @param priv         A pointer to struct lbs_private structure
+- *  @param adhocssid    The ssid of the Adhoc Network
+- *  @return             0--success, -1--fail
+- */
+-int lbs_start_adhoc_network(struct lbs_private *priv,
+-	struct assoc_request *assoc_req)
+-{
+-	int ret = 0;
+-
+-	priv->adhoccreate = 1;
+-
+-	if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
+-		lbs_deb_join("AdhocStart: Short preamble\n");
+-		priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
+-	} else {
+-		lbs_deb_join("AdhocStart: Long preamble\n");
+-		priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+-	}
+-
+-	lbs_set_radio_control(priv);
+-
+-	lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
+-	lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
+-
+-	ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
+-				    0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
+-
+-	return ret;
+-}
+-
+-/**
+- *  @brief Join an adhoc network found in a previous scan
+- *
+- *  @param priv         A pointer to struct lbs_private structure
+- *  @param pbssdesc     Pointer to a BSS descriptor found in a previous scan
+- *                      to attempt to join
+- *
+- *  @return             0--success, -1--fail
+- */
+-int lbs_join_adhoc_network(struct lbs_private *priv,
+-	struct assoc_request *assoc_req)
+-{
+-	struct bss_descriptor * bss = &assoc_req->bss;
+-	int ret = 0;
+-
+-	lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
+-	             __func__,
+-	             escape_essid(priv->curbssparams.ssid,
+-	                          priv->curbssparams.ssid_len),
+-	             priv->curbssparams.ssid_len);
+-	lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
+-	             __func__, escape_essid(bss->ssid, bss->ssid_len),
+-	             bss->ssid_len);
+-
+-	/* check if the requested SSID is already joined */
+-	if (   priv->curbssparams.ssid_len
+-	    && !lbs_ssid_cmp(priv->curbssparams.ssid,
+-	                          priv->curbssparams.ssid_len,
+-	                          bss->ssid, bss->ssid_len)
+-	    && (priv->mode == IW_MODE_ADHOC)
+-	    && (priv->connect_status == LBS_CONNECTED)) {
+-		union iwreq_data wrqu;
+-
+-		lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
+-		             "current, not attempting to re-join");
+-
+-		/* Send the re-association event though, because the association
+-		 * request really was successful, even if just a null-op.
+-		 */
+-		memset(&wrqu, 0, sizeof(wrqu));
+-		memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
+-		       ETH_ALEN);
+-		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+-		wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+-		goto out;
+-	}
+-
+-	/* Use shortpreamble only when both creator and card supports
+-	   short preamble */
+-	if (   !(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+-	    || !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
+-		lbs_deb_join("AdhocJoin: Long preamble\n");
+-		priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+-	} else {
+-		lbs_deb_join("AdhocJoin: Short preamble\n");
+-		priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
+-	}
+-
+-	lbs_set_radio_control(priv);
+-
+-	lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
+-	lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
+-
+-	priv->adhoccreate = 0;
+-
+-	ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
+-				    0, CMD_OPTION_WAITFORRSP,
+-				    OID_802_11_SSID, assoc_req);
+-
+-out:
+-	return ret;
+-}
+-
+-int lbs_stop_adhoc_network(struct lbs_private *priv)
+-{
+-	return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
+-				     0, CMD_OPTION_WAITFORRSP, 0, NULL);
+-}
+-
+-/**
+- *  @brief Send Deauthentication Request
+- *
+- *  @param priv      A pointer to struct lbs_private structure
+- *  @return          0--success, -1--fail
+- */
+-int lbs_send_deauthentication(struct lbs_private *priv)
+-{
+-	return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
+-				     0, CMD_OPTION_WAITFORRSP, 0, NULL);
+-}
+-
+-/**
+- *  @brief This function prepares command of authenticate.
+- *
+- *  @param priv      A pointer to struct lbs_private structure
+- *  @param cmd       A pointer to cmd_ds_command structure
+- *  @param pdata_buf Void cast of pointer to a BSSID to authenticate with
+- *
+- *  @return         0 or -1
+- */
+-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
+-				 struct cmd_ds_command *cmd,
+-				 void *pdata_buf)
+-{
+-	struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
+-	int ret = -1;
+-	u8 *bssid = pdata_buf;
+-	DECLARE_MAC_BUF(mac);
+-
+-	lbs_deb_enter(LBS_DEB_JOIN);
+-
+-	cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
+-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
+-	                        + S_DS_GEN);
+-
+-	/* translate auth mode to 802.11 defined wire value */
+-	switch (priv->secinfo.auth_mode) {
+-	case IW_AUTH_ALG_OPEN_SYSTEM:
+-		pauthenticate->authtype = 0x00;
+-		break;
+-	case IW_AUTH_ALG_SHARED_KEY:
+-		pauthenticate->authtype = 0x01;
+-		break;
+-	case IW_AUTH_ALG_LEAP:
+-		pauthenticate->authtype = 0x80;
+-		break;
+-	default:
+-		lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
+-		             priv->secinfo.auth_mode);
+-		goto out;
+-	}
+-
+-	memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
+-
+-	lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
+-	             print_mac(mac, bssid), pauthenticate->authtype);
+-	ret = 0;
+-
+-out:
+-	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+-	return ret;
+-}
+-
+-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
+-				   struct cmd_ds_command *cmd)
+-{
+-	struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
+-
+-	lbs_deb_enter(LBS_DEB_JOIN);
+-
+-	cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
+-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
+-			     S_DS_GEN);
+-
+-	/* set AP MAC address */
+-	memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
+-
+-	/* Reason code 3 = Station is leaving */
+-#define REASON_CODE_STA_LEAVING 3
+-	dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
+-
+-	lbs_deb_leave(LBS_DEB_JOIN);
+-	return 0;
+-}
+-
+-int lbs_cmd_80211_associate(struct lbs_private *priv,
+-			      struct cmd_ds_command *cmd, void *pdata_buf)
+-{
+-	struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
+-	int ret = 0;
+-	struct assoc_request * assoc_req = pdata_buf;
+-	struct bss_descriptor * bss = &assoc_req->bss;
+-	u8 *pos;
+-	u16 tmpcap, tmplen;
+-	struct mrvlietypes_ssidparamset *ssid;
+-	struct mrvlietypes_phyparamset *phy;
+-	struct mrvlietypes_ssparamset *ss;
+-	struct mrvlietypes_ratesparamset *rates;
+-	struct mrvlietypes_rsnparamset *rsn;
+-
+-	lbs_deb_enter(LBS_DEB_ASSOC);
+-
+-	pos = (u8 *) passo;
+-
+-	if (!priv) {
+-		ret = -1;
+-		goto done;
+-	}
+-
+-	cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
+-
+-	memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
+-	pos += sizeof(passo->peerstaaddr);
+-
+-	/* set the listen interval */
+-	passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
+-
+-	pos += sizeof(passo->capability);
+-	pos += sizeof(passo->listeninterval);
+-	pos += sizeof(passo->bcnperiod);
+-	pos += sizeof(passo->dtimperiod);
+-
+-	ssid = (struct mrvlietypes_ssidparamset *) pos;
+-	ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
+-	tmplen = bss->ssid_len;
+-	ssid->header.len = cpu_to_le16(tmplen);
+-	memcpy(ssid->ssid, bss->ssid, tmplen);
+-	pos += sizeof(ssid->header) + tmplen;
+-
+-	phy = (struct mrvlietypes_phyparamset *) pos;
+-	phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
+-	tmplen = sizeof(phy->fh_ds.dsparamset);
+-	phy->header.len = cpu_to_le16(tmplen);
+-	memcpy(&phy->fh_ds.dsparamset,
+-	       &bss->phyparamset.dsparamset.currentchan,
+-	       tmplen);
+-	pos += sizeof(phy->header) + tmplen;
+-
+-	ss = (struct mrvlietypes_ssparamset *) pos;
+-	ss->header.type = cpu_to_le16(TLV_TYPE_CF);
+-	tmplen = sizeof(ss->cf_ibss.cfparamset);
+-	ss->header.len = cpu_to_le16(tmplen);
+-	pos += sizeof(ss->header) + tmplen;
+-
+-	rates = (struct mrvlietypes_ratesparamset *) pos;
+-	rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
+-	memcpy(&rates->rates, &bss->rates, MAX_RATES);
+-	tmplen = MAX_RATES;
+-	if (get_common_rates(priv, rates->rates, &tmplen)) {
+-		ret = -1;
+-		goto done;
+-	}
+-	pos += sizeof(rates->header) + tmplen;
+-	rates->header.len = cpu_to_le16(tmplen);
+-	lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
+-
+-	/* Copy the infra. association rates into Current BSS state structure */
+-	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+-	memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
+-
+-	/* Set MSB on basic rates as the firmware requires, but _after_
+-	 * copying to current bss rates.
+-	 */
+-	lbs_set_basic_rate_flags(rates->rates, tmplen);
+-
+-	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
+-		rsn = (struct mrvlietypes_rsnparamset *) pos;
+-		/* WPA_IE or WPA2_IE */
+-		rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
+-		tmplen = (u16) assoc_req->wpa_ie[1];
+-		rsn->header.len = cpu_to_le16(tmplen);
+-		memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
+-		lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
+-			sizeof(rsn->header) + tmplen);
+-		pos += sizeof(rsn->header) + tmplen;
+-	}
+-
+-	/* update curbssparams */
+-	priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
+-
+-	if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
+-		ret = -1;
+-		goto done;
+-	}
+-
+-	cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
+-
+-	/* set the capability info */
+-	tmpcap = (bss->capability & CAPINFO_MASK);
+-	if (bss->mode == IW_MODE_INFRA)
+-		tmpcap |= WLAN_CAPABILITY_ESS;
+-	passo->capability = cpu_to_le16(tmpcap);
+-	lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
+-
+-done:
+-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+-	return ret;
+-}
+-
+-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
+-				 struct cmd_ds_command *cmd, void *pdata_buf)
+-{
+-	struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
+-	int ret = 0;
+-	int cmdappendsize = 0;
+-	struct assoc_request * assoc_req = pdata_buf;
+-	u16 tmpcap = 0;
+-	size_t ratesize = 0;
+-
+-	lbs_deb_enter(LBS_DEB_JOIN);
+-
+-	if (!priv) {
+-		ret = -1;
+-		goto done;
+-	}
+-
+-	cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
+-
+-	/*
+-	 * Fill in the parameters for 2 data structures:
+-	 *   1. cmd_ds_802_11_ad_hoc_start command
+-	 *   2. priv->scantable[i]
+-	 *
+-	 * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
+-	 *   probe delay, and cap info.
+-	 *
+-	 * Firmware will fill up beacon period, DTIM, Basic rates
+-	 *   and operational rates.
+-	 */
+-
+-	memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
+-	memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
+-
+-	lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
+-	             escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+-	             assoc_req->ssid_len);
+-
+-	/* set the BSS type */
+-	adhs->bsstype = CMD_BSS_TYPE_IBSS;
+-	priv->mode = IW_MODE_ADHOC;
+-	if (priv->beacon_period == 0)
+-		priv->beacon_period = MRVDRV_BEACON_INTERVAL;
+-	adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
+-
+-	/* set Physical param set */
+-#define DS_PARA_IE_ID   3
+-#define DS_PARA_IE_LEN  1
+-
+-	adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
+-	adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
+-
+-	WARN_ON(!assoc_req->channel);
+-
+-	lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
+-		     assoc_req->channel);
+-
+-	adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
+-
+-	/* set IBSS param set */
+-#define IBSS_PARA_IE_ID   6
+-#define IBSS_PARA_IE_LEN  2
+-
+-	adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
+-	adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
+-	adhs->ssparamset.ibssparamset.atimwindow = 0;
+-
+-	/* set capability info */
+-	tmpcap = WLAN_CAPABILITY_IBSS;
+-	if (assoc_req->secinfo.wep_enabled) {
+-		lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
+-		tmpcap |= WLAN_CAPABILITY_PRIVACY;
+-	} else {
+-		lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
+-	}
+-	adhs->capability = cpu_to_le16(tmpcap);
+-
+-	/* probedelay */
+-	adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
+-
+-	memset(adhs->rates, 0, sizeof(adhs->rates));
+-	ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
+-	memcpy(adhs->rates, lbs_bg_rates, ratesize);
+-
+-	/* Copy the ad-hoc creating rates into Current BSS state structure */
+-	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+-	memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
+-
+-	/* Set MSB on basic rates as the firmware requires, but _after_
+-	 * copying to current bss rates.
+-	 */
+-	lbs_set_basic_rate_flags(adhs->rates, ratesize);
+-
+-	lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
+-	       adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
+-
+-	lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
+-
+-	if (lbs_create_dnld_countryinfo_11d(priv)) {
+-		lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
+-		ret = -1;
+-		goto done;
+-	}
+-
+-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
+-				S_DS_GEN + cmdappendsize);
+-
+-	ret = 0;
+-done:
+-	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+-	return ret;
+-}
+-
+-int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
+-				struct cmd_ds_command *cmd)
+-{
+-	cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
+-	cmd->size = cpu_to_le16(S_DS_GEN);
+-
+-	return 0;
+-}
+-
+-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
+-				struct cmd_ds_command *cmd, void *pdata_buf)
+-{
+-	struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
+-	struct assoc_request * assoc_req = pdata_buf;
+-	struct bss_descriptor *bss = &assoc_req->bss;
+-	int cmdappendsize = 0;
+-	int ret = 0;
+-	u16 ratesize = 0;
+-	DECLARE_MAC_BUF(mac);
+-
+-	lbs_deb_enter(LBS_DEB_JOIN);
+-
+-	cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
+-
+-	join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
+-	join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
+-
+-	memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
+-	memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
+-
+-	memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
+-	       sizeof(union ieeetypes_phyparamset));
+-
+-	memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
+-	       sizeof(union IEEEtypes_ssparamset));
+-
+-	join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
+-	lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
+-	       bss->capability, CAPINFO_MASK);
+-
+-	/* information on BSSID descriptor passed to FW */
+-	lbs_deb_join(
+-	       "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
+-	       print_mac(mac, join_cmd->bss.bssid),
+-	       join_cmd->bss.ssid);
+-
+-	/* failtimeout */
+-	join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
+-
+-	/* probedelay */
+-	join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
+-
+-	priv->curbssparams.channel = bss->channel;
+-
+-	/* Copy Data rates from the rates recorded in scan response */
+-	memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
+-	ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
+-	memcpy(join_cmd->bss.rates, bss->rates, ratesize);
+-	if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
+-		lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
+-		ret = -1;
+-		goto done;
+-	}
+-
+-	/* Copy the ad-hoc creating rates into Current BSS state structure */
+-	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+-	memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
+-
+-	/* Set MSB on basic rates as the firmware requires, but _after_
+-	 * copying to current bss rates.
+-	 */
+-	lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
+-
+-	join_cmd->bss.ssparamset.ibssparamset.atimwindow =
+-	    cpu_to_le16(bss->atimwindow);
+-
+-	if (assoc_req->secinfo.wep_enabled) {
+-		u16 tmp = le16_to_cpu(join_cmd->bss.capability);
+-		tmp |= WLAN_CAPABILITY_PRIVACY;
+-		join_cmd->bss.capability = cpu_to_le16(tmp);
+-	}
+-
+-	if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
+-		/* wake up first */
+-		__le32 Localpsmode;
+-
+-		Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
+-		ret = lbs_prepare_and_send_command(priv,
+-					    CMD_802_11_PS_MODE,
+-					    CMD_ACT_SET,
+-					    0, 0, &Localpsmode);
+-
+-		if (ret) {
+-			ret = -1;
+-			goto done;
+-		}
+-	}
+-
+-	if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
+-		ret = -1;
+-		goto done;
+-	}
+-
+-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
+-				S_DS_GEN + cmdappendsize);
+-
+-done:
+-	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+-	return ret;
+-}
+-
+-int lbs_ret_80211_associate(struct lbs_private *priv,
+-			      struct cmd_ds_command *resp)
+-{
+-	int ret = 0;
+-	union iwreq_data wrqu;
+-	struct ieeetypes_assocrsp *passocrsp;
+-	struct bss_descriptor * bss;
+-	u16 status_code;
+-
+-	lbs_deb_enter(LBS_DEB_ASSOC);
+-
+-	if (!priv->in_progress_assoc_req) {
+-		lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
+-		ret = -1;
+-		goto done;
+-	}
+-	bss = &priv->in_progress_assoc_req->bss;
+-
+-	passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
+-
+-	/*
+-	 * Older FW versions map the IEEE 802.11 Status Code in the association
+-	 * response to the following values returned in passocrsp->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)
+-	 */
+-
+-	status_code = le16_to_cpu(passocrsp->statuscode);
+-	switch (status_code) {
+-	case 0x00:
+-		break;
+-	case 0x01:
+-		lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
+-		break;
+-	case 0x02:
+-		lbs_deb_assoc("ASSOC_RESP: internal timer "
+-			"expired while waiting for the AP\n");
+-		break;
+-	case 0x03:
+-		lbs_deb_assoc("ASSOC_RESP: association "
+-			"refused by AP\n");
+-		break;
+-	case 0x04:
+-		lbs_deb_assoc("ASSOC_RESP: authentication "
+-			"refused by AP\n");
+-		break;
+-	default:
+-		lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
+-			" unknown\n", status_code);
+-		break;
+-	}
+-
+-	if (status_code) {
+-		lbs_mac_event_disconnected(priv);
+-		ret = -1;
+-		goto done;
+-	}
+-
+-	lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
+-		le16_to_cpu(resp->size) - S_DS_GEN);
+-
+-	/* Send a Media Connected event, according to the Spec */
+-	priv->connect_status = LBS_CONNECTED;
+-
+-	/* Update current SSID and BSSID */
+-	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+-	priv->curbssparams.ssid_len = bss->ssid_len;
+-	memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
+-
+-	lbs_deb_assoc("ASSOC_RESP: currentpacketfilter is 0x%x\n",
+-		priv->currentpacketfilter);
+-
+-	priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
+-	priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
+-
+-	memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
+-	memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
+-	priv->nextSNRNF = 0;
+-	priv->numSNRNF = 0;
+-
+-	netif_carrier_on(priv->dev);
+-	if (!priv->tx_pending_len)
+-		netif_wake_queue(priv->dev);
+-
+-	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
+-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+-
+-done:
+-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+-	return ret;
+-}
+-
+-int lbs_ret_80211_disassociate(struct lbs_private *priv,
+-				 struct cmd_ds_command *resp)
+-{
+-	lbs_deb_enter(LBS_DEB_JOIN);
+-
+-	lbs_mac_event_disconnected(priv);
+-
+-	lbs_deb_leave(LBS_DEB_JOIN);
+-	return 0;
+-}
+-
+-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
+-				 struct cmd_ds_command *resp)
+-{
+-	int ret = 0;
+-	u16 command = le16_to_cpu(resp->command);
+-	u16 result = le16_to_cpu(resp->result);
+-	struct cmd_ds_802_11_ad_hoc_result *padhocresult;
+-	union iwreq_data wrqu;
+-	struct bss_descriptor *bss;
+-	DECLARE_MAC_BUF(mac);
+-
+-	lbs_deb_enter(LBS_DEB_JOIN);
+-
+-	padhocresult = &resp->params.result;
+-
+-	lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
+-	lbs_deb_join("ADHOC_RESP: command = %x\n", command);
+-	lbs_deb_join("ADHOC_RESP: result = %x\n", result);
+-
+-	if (!priv->in_progress_assoc_req) {
+-		lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
+-		ret = -1;
+-		goto done;
+-	}
+-	bss = &priv->in_progress_assoc_req->bss;
+-
+-	/*
+-	 * Join result code 0 --> SUCCESS
+-	 */
+-	if (result) {
+-		lbs_deb_join("ADHOC_RESP: failed\n");
+-		if (priv->connect_status == LBS_CONNECTED) {
+-			lbs_mac_event_disconnected(priv);
+-		}
+-		ret = -1;
+-		goto done;
+-	}
+-
+-	/*
+-	 * Now the join cmd should be successful
+-	 * If BSSID has changed use SSID to compare instead of BSSID
+-	 */
+-	lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
+-	             escape_essid(bss->ssid, bss->ssid_len));
+-
+-	/* Send a Media Connected event, according to the Spec */
+-	priv->connect_status = LBS_CONNECTED;
+-
+-	if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
+-		/* Update the created network descriptor with the new BSSID */
+-		memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
+-	}
+-
+-	/* Set the BSSID from the joined/started descriptor */
+-	memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
+-
+-	/* Set the new SSID to current SSID */
+-	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+-	priv->curbssparams.ssid_len = bss->ssid_len;
+-
+-	netif_carrier_on(priv->dev);
+-	if (!priv->tx_pending_len)
+-		netif_wake_queue(priv->dev);
+-
+-	memset(&wrqu, 0, sizeof(wrqu));
+-	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
+-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+-
+-	lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
+-	lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
+-	lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
+-		     print_mac(mac, padhocresult->bssid));
+-
+-done:
+-	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+-	return ret;
+-}
+-
+-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
+-				struct cmd_ds_command *resp)
+-{
+-	lbs_deb_enter(LBS_DEB_JOIN);
+-
+-	lbs_mac_event_disconnected(priv);
+-
+-	lbs_deb_leave(LBS_DEB_JOIN);
+-	return 0;
+-}
+diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h
+deleted file mode 100644
+index c617d07..0000000
+--- a/drivers/net/wireless/libertas/join.h
++++ /dev/null
+@@ -1,53 +0,0 @@
+-/**
+-  * Interface for the wlan infrastructure and adhoc join routines
+-  *
+-  * Driver interface functions and type declarations for the join module
+-  *   implemented in join.c.  Process all start/join requests for
+-  *   both adhoc and infrastructure networks
+-  */
+-#ifndef _LBS_JOIN_H
+-#define _LBS_JOIN_H
+-
+-#include "defs.h"
+-#include "dev.h"
+-
+-struct cmd_ds_command;
+-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
+-					struct cmd_ds_command *cmd,
+-					void *pdata_buf);
+-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
+-				       struct cmd_ds_command *cmd,
+-				       void *pdata_buf);
+-int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
+-				       struct cmd_ds_command *cmd);
+-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
+-					struct cmd_ds_command *cmd,
+-					void *pdata_buf);
+-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
+-					  struct cmd_ds_command *cmd);
+-int lbs_cmd_80211_associate(struct lbs_private *priv,
+-				     struct cmd_ds_command *cmd,
+-				     void *pdata_buf);
+-
+-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
+-					struct cmd_ds_command *resp);
+-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
+-				       struct cmd_ds_command *resp);
+-int lbs_ret_80211_disassociate(struct lbs_private *priv,
+-					struct cmd_ds_command *resp);
+-int lbs_ret_80211_associate(struct lbs_private *priv,
+-				     struct cmd_ds_command *resp);
+-
+-int lbs_start_adhoc_network(struct lbs_private *priv,
+-			     struct assoc_request * assoc_req);
+-int lbs_join_adhoc_network(struct lbs_private *priv,
+-				struct assoc_request * assoc_req);
+-int lbs_stop_adhoc_network(struct lbs_private *priv);
+-
+-int lbs_send_deauthentication(struct lbs_private *priv);
+-
+-int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req);
+-
+-void lbs_unset_basic_rate_flags(u8 *rates, size_t len);
+-
+-#endif
+diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
+index 4d4e2f3..406f54d 100644
+--- a/drivers/net/wireless/libertas/main.c
++++ b/drivers/net/wireless/libertas/main.c
+@@ -10,6 +10,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/if_arp.h>
+ #include <linux/kthread.h>
++#include <linux/kfifo.h>
+ 
+ #include <net/iw_handler.h>
+ #include <net/ieee80211.h>
+@@ -19,8 +20,8 @@
+ #include "dev.h"
+ #include "wext.h"
+ #include "debugfs.h"
++#include "scan.h"
+ #include "assoc.h"
+-#include "join.h"
+ #include "cmd.h"
+ 
+ #define DRIVER_RELEASE_VERSION "323.p0"
+@@ -37,6 +38,11 @@ EXPORT_SYMBOL_GPL(lbs_debug);
+ module_param_named(libertas_debug, lbs_debug, int, 0644);
+ 
+ 
++/* This global structure is used to send the confirm_sleep command as
++ * fast as possible down to the firmware. */
++struct cmd_confirm_sleep confirm_sleep;
++
++
+ #define LBS_TX_PWR_DEFAULT		20	/*100mW */
+ #define LBS_TX_PWR_US_DEFAULT		20	/*100mW */
+ #define LBS_TX_PWR_JP_DEFAULT		16	/*50mW */
+@@ -277,10 +283,10 @@ static ssize_t lbs_rtap_set(struct device *dev,
+ 	struct lbs_private *priv = to_net_dev(dev)->priv;
+ 
+ 	sscanf(buf, "%x", &monitor_mode);
+-	if (monitor_mode != LBS_MONITOR_OFF) {
+-		if(priv->monitormode == monitor_mode)
++	if (monitor_mode) {
++		if (priv->monitormode == monitor_mode)
+ 			return strlen(buf);
+-		if (priv->monitormode == LBS_MONITOR_OFF) {
++		if (!priv->monitormode) {
+ 			if (priv->infra_open || priv->mesh_open)
+ 				return -EBUSY;
+ 			if (priv->mode == IW_MODE_INFRA)
+@@ -293,9 +299,9 @@ static ssize_t lbs_rtap_set(struct device *dev,
+ 	}
+ 
+ 	else {
+-		if (priv->monitormode == LBS_MONITOR_OFF)
++		if (!priv->monitormode)
+ 			return strlen(buf);
+-		priv->monitormode = LBS_MONITOR_OFF;
++		priv->monitormode = 0;
+ 		lbs_remove_rtap(priv);
+ 
+ 		if (priv->currenttxskb) {
+@@ -392,7 +398,7 @@ static int lbs_dev_open(struct net_device *dev)
+ 
+ 	spin_lock_irq(&priv->driver_lock);
+ 
+-	if (priv->monitormode != LBS_MONITOR_OFF) {
++	if (priv->monitormode) {
+ 		ret = -EBUSY;
+ 		goto out;
+ 	}
+@@ -475,10 +481,9 @@ static void lbs_tx_timeout(struct net_device *dev)
+ 
+ 	dev->trans_start = jiffies;
+ 
+-	if (priv->currenttxskb) {
+-		priv->eventcause = 0x01000000;
+-		lbs_send_tx_feedback(priv);
+-	}
++	if (priv->currenttxskb)
++		lbs_send_tx_feedback(priv, 0);
++
+ 	/* XX: Shouldn't we also call into the hw-specific driver
+ 	   to kick it somehow? */
+ 	lbs_host_to_card_done(priv);
+@@ -531,34 +536,27 @@ static int lbs_set_mac_address(struct net_device *dev, void *addr)
+ 	int ret = 0;
+ 	struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ 	struct sockaddr *phwaddr = addr;
++	struct cmd_ds_802_11_mac_address cmd;
+ 
+ 	lbs_deb_enter(LBS_DEB_NET);
+ 
+ 	/* In case it was called from the mesh device */
+-	dev = priv->dev ;
+-
+-	memset(priv->current_addr, 0, ETH_ALEN);
+-
+-	/* dev->dev_addr is 8 bytes */
+-	lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN);
+-
+-	lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN);
+-	memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
++	dev = priv->dev;
+ 
+-	ret = lbs_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS,
+-				    CMD_ACT_SET,
+-				    CMD_OPTION_WAITFORRSP, 0, NULL);
++	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
++	cmd.action = cpu_to_le16(CMD_ACT_SET);
++	memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN);
+ 
++	ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
+ 	if (ret) {
+ 		lbs_deb_net("set MAC address failed\n");
+-		ret = -1;
+ 		goto done;
+ 	}
+ 
+-	lbs_deb_hex(LBS_DEB_NET, "priv->macaddr", priv->current_addr, ETH_ALEN);
+-	memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
++	memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
++	memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
+ 	if (priv->mesh_dev)
+-		memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
++		memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
+ 
+ done:
+ 	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+@@ -581,45 +579,45 @@ static int lbs_copy_multicast_address(struct lbs_private *priv,
+ static void lbs_set_multicast_list(struct net_device *dev)
+ {
+ 	struct lbs_private *priv = dev->priv;
+-	int oldpacketfilter;
++	int old_mac_control;
+ 	DECLARE_MAC_BUF(mac);
+ 
+ 	lbs_deb_enter(LBS_DEB_NET);
+ 
+-	oldpacketfilter = priv->currentpacketfilter;
++	old_mac_control = priv->mac_control;
+ 
+ 	if (dev->flags & IFF_PROMISC) {
+ 		lbs_deb_net("enable promiscuous mode\n");
+-		priv->currentpacketfilter |=
++		priv->mac_control |=
+ 		    CMD_ACT_MAC_PROMISCUOUS_ENABLE;
+-		priv->currentpacketfilter &=
++		priv->mac_control &=
+ 		    ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE |
+ 		      CMD_ACT_MAC_MULTICAST_ENABLE);
+ 	} else {
+ 		/* Multicast */
+-		priv->currentpacketfilter &=
++		priv->mac_control &=
+ 		    ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
+ 
+ 		if (dev->flags & IFF_ALLMULTI || dev->mc_count >
+ 		    MRVDRV_MAX_MULTICAST_LIST_SIZE) {
+ 			lbs_deb_net( "enabling all multicast\n");
+-			priv->currentpacketfilter |=
++			priv->mac_control |=
+ 			    CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
+-			priv->currentpacketfilter &=
++			priv->mac_control &=
+ 			    ~CMD_ACT_MAC_MULTICAST_ENABLE;
+ 		} else {
+-			priv->currentpacketfilter &=
++			priv->mac_control &=
+ 			    ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
+ 
+ 			if (!dev->mc_count) {
+ 				lbs_deb_net("no multicast addresses, "
+ 				       "disabling multicast\n");
+-				priv->currentpacketfilter &=
++				priv->mac_control &=
+ 				    ~CMD_ACT_MAC_MULTICAST_ENABLE;
+ 			} else {
+ 				int i;
+ 
+-				priv->currentpacketfilter |=
++				priv->mac_control |=
+ 				    CMD_ACT_MAC_MULTICAST_ENABLE;
+ 
+ 				priv->nr_of_multicastmacaddr =
+@@ -642,9 +640,8 @@ static void lbs_set_multicast_list(struct net_device *dev)
+ 		}
+ 	}
+ 
+-	if (priv->currentpacketfilter != oldpacketfilter) {
+-		lbs_set_mac_packet_filter(priv);
+-	}
++	if (priv->mac_control != old_mac_control)
++		lbs_set_mac_control(priv);
+ 
+ 	lbs_deb_leave(LBS_DEB_NET);
+ }
+@@ -662,7 +659,6 @@ static int lbs_thread(void *data)
+ 	struct net_device *dev = data;
+ 	struct lbs_private *priv = dev->priv;
+ 	wait_queue_t wait;
+-	u8 ireg = 0;
+ 
+ 	lbs_deb_enter(LBS_DEB_THREAD);
+ 
+@@ -670,9 +666,10 @@ static int lbs_thread(void *data)
+ 
+ 	for (;;) {
+ 		int shouldsleep;
++		u8 resp_idx;
+ 
+-		lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+-				priv->intcounter, priv->currenttxskb, priv->dnld_sent);
++		lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n",
++				priv->currenttxskb, priv->dnld_sent);
+ 
+ 		add_wait_queue(&priv->waitq, &wait);
+ 		set_current_state(TASK_INTERRUPTIBLE);
+@@ -684,8 +681,6 @@ static int lbs_thread(void *data)
+ 			shouldsleep = 1;	/* We need to wait until we're _told_ to die */
+ 		else if (priv->psstate == PS_STATE_SLEEP)
+ 			shouldsleep = 1;	/* Sleep mode. Nothing we can do till it wakes */
+-		else if (priv->intcounter)
+-			shouldsleep = 0;	/* Interrupt pending. Deal with it now */
+ 		else if (priv->cmd_timed_out)
+ 			shouldsleep = 0;	/* Command timed out. Recover */
+ 		else if (!priv->fw_ready)
+@@ -698,29 +693,34 @@ static int lbs_thread(void *data)
+ 			shouldsleep = 1;	/* Can't send a command; one already running */
+ 		else if (!list_empty(&priv->cmdpendingq))
+ 			shouldsleep = 0;	/* We have a command to send */
++		else if (__kfifo_len(priv->event_fifo))
++			shouldsleep = 0;	/* We have an event to process */
++		else if (priv->resp_len[priv->resp_idx])
++			shouldsleep = 0;	/* We have a command response */
+ 		else
+ 			shouldsleep = 1;	/* No command */
+ 
+ 		if (shouldsleep) {
+-			lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
+-				       priv->connect_status, priv->intcounter,
+-				       priv->psmode, priv->psstate);
++			lbs_deb_thread("sleeping, connect_status %d, "
++				"ps_mode %d, ps_state %d\n",
++				priv->connect_status,
++				priv->psmode, priv->psstate);
+ 			spin_unlock_irq(&priv->driver_lock);
+ 			schedule();
+ 		} else
+ 			spin_unlock_irq(&priv->driver_lock);
+ 
+-		lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+-			       priv->intcounter, priv->currenttxskb, priv->dnld_sent);
++		lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n",
++			       priv->currenttxskb, priv->dnld_sent);
+ 
+ 		set_current_state(TASK_RUNNING);
+ 		remove_wait_queue(&priv->waitq, &wait);
+ 
+-		lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+-			       priv->intcounter, priv->currenttxskb, priv->dnld_sent);
++		lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n",
++			       priv->currenttxskb, priv->dnld_sent);
+ 
+ 		if (kthread_should_stop()) {
+-			lbs_deb_thread("main-thread: break from main thread\n");
++			lbs_deb_thread("break from main thread\n");
+ 			break;
+ 		}
+ 
+@@ -729,35 +729,23 @@ static int lbs_thread(void *data)
+ 			continue;
+ 		}
+ 
+-		spin_lock_irq(&priv->driver_lock);
+-
+-		if (priv->intcounter) {
+-			u8 int_status;
+-
+-			priv->intcounter = 0;
+-			int_status = priv->hw_get_int_status(priv, &ireg);
+-
+-			if (int_status) {
+-				lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n");
+-				spin_unlock_irq(&priv->driver_lock);
+-				continue;
+-			}
+-			priv->hisregcpy |= ireg;
+-		}
+-
+-		lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+-			       priv->intcounter, priv->currenttxskb, priv->dnld_sent);
++		lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n",
++		       priv->currenttxskb, priv->dnld_sent);
+ 
+-		/* command response? */
+-		if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) {
+-			lbs_deb_thread("main-thread: cmd response ready\n");
+-
+-			priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
++		spin_lock_irq(&priv->driver_lock);
++		/* Process any pending command response */
++		resp_idx = priv->resp_idx;
++		if (priv->resp_len[resp_idx]) {
+ 			spin_unlock_irq(&priv->driver_lock);
+-			lbs_process_rx_command(priv);
++			lbs_process_command_response(priv,
++				priv->resp_buf[resp_idx],
++				priv->resp_len[resp_idx]);
+ 			spin_lock_irq(&priv->driver_lock);
++			priv->resp_len[resp_idx] = 0;
+ 		}
++		spin_unlock_irq(&priv->driver_lock);
+ 
++		/* command timeout stuff */
+ 		if (priv->cmd_timed_out && priv->cur_cmd) {
+ 			struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
+ 
+@@ -778,21 +766,18 @@ static int lbs_thread(void *data)
+ 		}
+ 		priv->cmd_timed_out = 0;
+ 
+-		/* Any Card Event */
+-		if (priv->hisregcpy & MRVDRV_CARDEVENT) {
+-			lbs_deb_thread("main-thread: Card Event Activity\n");
+-
+-			priv->hisregcpy &= ~MRVDRV_CARDEVENT;
++		/* Process hardware events, e.g. card removed, link lost */
++		spin_lock_irq(&priv->driver_lock);
++		while (__kfifo_len(priv->event_fifo)) {
++			u32 event;
+ 
+-			if (priv->hw_read_event_cause(priv)) {
+-				lbs_pr_alert("main-thread: hw_read_event_cause failed\n");
+-				spin_unlock_irq(&priv->driver_lock);
+-				continue;
+-			}
+-			spin_unlock_irq(&priv->driver_lock);
+-			lbs_process_event(priv);
+-		} else
++			__kfifo_get(priv->event_fifo, (unsigned char *) &event,
++				sizeof(event));
+ 			spin_unlock_irq(&priv->driver_lock);
++			lbs_process_event(priv, event);
++			spin_lock_irq(&priv->driver_lock);
++		}
++		spin_unlock_irq(&priv->driver_lock);
+ 
+ 		if (!priv->fw_ready)
+ 			continue;
+@@ -801,10 +786,12 @@ static int lbs_thread(void *data)
+ 		if (priv->psstate == PS_STATE_PRE_SLEEP &&
+ 		    !priv->dnld_sent && !priv->cur_cmd) {
+ 			if (priv->connect_status == LBS_CONNECTED) {
+-				lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n",
+-					       priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd);
++				lbs_deb_thread("pre-sleep, currenttxskb %p, "
++					"dnld_sent %d, cur_cmd %p\n",
++					priv->currenttxskb, priv->dnld_sent,
++					priv->cur_cmd);
+ 
+-				lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
++				lbs_ps_confirm_sleep(priv);
+ 			} else {
+ 				/* workaround for firmware sending
+ 				 * deauth/linkloss event immediately
+@@ -812,7 +799,8 @@ static int lbs_thread(void *data)
+ 				 * after firmware fixes it
+ 				 */
+ 				priv->psstate = PS_STATE_AWAKE;
+-				lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n");
++				lbs_pr_alert("ignore PS_SleepConfirm in "
++					"non-connected state\n");
+ 			}
+ 		}
+ 
+@@ -945,7 +933,7 @@ static int lbs_setup_firmware(struct lbs_private *priv)
+ 		goto done;
+ 	}
+ 
+-	lbs_set_mac_packet_filter(priv);
++	lbs_set_mac_control(priv);
+ 
+ 	ret = lbs_get_data_rate(priv);
+ 	if (ret < 0) {
+@@ -985,6 +973,18 @@ out:
+ 	lbs_deb_leave(LBS_DEB_CMD);
+ }
+ 
++static void lbs_sync_channel_worker(struct work_struct *work)
++{
++	struct lbs_private *priv = container_of(work, struct lbs_private,
++		sync_channel);
++
++	lbs_deb_enter(LBS_DEB_MAIN);
++	if (lbs_update_channel(priv))
++		lbs_pr_info("Channel synchronization failed.");
++	lbs_deb_leave(LBS_DEB_MAIN);
++}
++
++
+ static int lbs_init_adapter(struct lbs_private *priv)
+ {
+ 	size_t bufsize;
+@@ -1009,14 +1009,6 @@ static int lbs_init_adapter(struct lbs_private *priv)
+ 			      &priv->network_free_list);
+ 	}
+ 
+-	priv->lbs_ps_confirm_sleep.seqnum = cpu_to_le16(++priv->seqnum);
+-	priv->lbs_ps_confirm_sleep.command =
+-	    cpu_to_le16(CMD_802_11_PS_MODE);
+-	priv->lbs_ps_confirm_sleep.size =
+-	    cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
+-	priv->lbs_ps_confirm_sleep.action =
+-	    cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
+-
+ 	memset(priv->current_addr, 0xff, ETH_ALEN);
+ 
+ 	priv->connect_status = LBS_DISCONNECTED;
+@@ -1024,7 +1016,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
+ 	priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+ 	priv->mode = IW_MODE_INFRA;
+ 	priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
+-	priv->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
++	priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
+ 	priv->radioon = RADIO_ON;
+ 	priv->auto_rate = 1;
+ 	priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
+@@ -1045,7 +1037,18 @@ static int lbs_init_adapter(struct lbs_private *priv)
+ 	/* Allocate the command buffers */
+ 	if (lbs_allocate_cmd_buffer(priv)) {
+ 		lbs_pr_err("Out of memory allocating command buffers\n");
+-		ret = -1;
++		ret = -ENOMEM;
++		goto out;
++	}
++	priv->resp_idx = 0;
++	priv->resp_len[0] = priv->resp_len[1] = 0;
++
++	/* Create the event FIFO */
++	priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL);
++	if (IS_ERR(priv->event_fifo)) {
++		lbs_pr_err("Out of memory allocating event FIFO buffer\n");
++		ret = -ENOMEM;
++		goto out;
+ 	}
+ 
+ out:
+@@ -1059,6 +1062,8 @@ static void lbs_free_adapter(struct lbs_private *priv)
+ 	lbs_deb_enter(LBS_DEB_MAIN);
+ 
+ 	lbs_free_cmd_buffer(priv);
++	if (priv->event_fifo)
++		kfifo_free(priv->event_fifo);
+ 	del_timer(&priv->command_timer);
+ 	kfree(priv->networks);
+ 	priv->networks = NULL;
+@@ -1128,7 +1133,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
+ 	priv->work_thread = create_singlethread_workqueue("lbs_worker");
+ 	INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
+ 	INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
+-	INIT_WORK(&priv->sync_channel, lbs_sync_channel);
++	INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
+ 
+ 	sprintf(priv->mesh_ssid, "mesh");
+ 	priv->mesh_ssid_len = 4;
+@@ -1380,7 +1385,7 @@ static void lbs_remove_mesh(struct lbs_private *priv)
+  *  @param cfp_no  A pointer to CFP number
+  *  @return 	   A pointer to CFP
+  */
+-struct chan_freq_power *lbs_get_region_cfp_table(u8 region, u8 band, int *cfp_no)
++struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
+ {
+ 	int i, end;
+ 
+@@ -1414,7 +1419,7 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
+ 
+ 	memset(priv->region_channel, 0, sizeof(priv->region_channel));
+ 
+-	cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
++	cfp = lbs_get_region_cfp_table(region, &cfp_no);
+ 	if (cfp != NULL) {
+ 		priv->region_channel[i].nrcfp = cfp_no;
+ 		priv->region_channel[i].CFP = cfp;
+@@ -1433,31 +1438,49 @@ out:
+ 	return ret;
+ }
+ 
+-/**
+- *  @brief This function handles the interrupt. it will change PS
+- *  state if applicable. it will wake up main_thread to handle
+- *  the interrupt event as well.
+- *
+- *  @param dev     A pointer to net_device structure
+- *  @return 	   n/a
+- */
+-void lbs_interrupt(struct lbs_private *priv)
++void lbs_queue_event(struct lbs_private *priv, u32 event)
++{
++	unsigned long flags;
++
++	lbs_deb_enter(LBS_DEB_THREAD);
++	spin_lock_irqsave(&priv->driver_lock, flags);
++
++	if (priv->psstate == PS_STATE_SLEEP)
++		priv->psstate = PS_STATE_AWAKE;
++
++	__kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32));
++
++	wake_up_interruptible(&priv->waitq);
++
++	spin_unlock_irqrestore(&priv->driver_lock, flags);
++	lbs_deb_leave(LBS_DEB_THREAD);
++}
++EXPORT_SYMBOL_GPL(lbs_queue_event);
++
++void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
+ {
+ 	lbs_deb_enter(LBS_DEB_THREAD);
+ 
+-	lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter);
+-	priv->intcounter++;
+ 	if (priv->psstate == PS_STATE_SLEEP)
+ 		priv->psstate = PS_STATE_AWAKE;
++
++	/* Swap buffers by flipping the response index */
++	BUG_ON(resp_idx > 1);
++	priv->resp_idx = resp_idx;
++
+ 	wake_up_interruptible(&priv->waitq);
+ 
+ 	lbs_deb_leave(LBS_DEB_THREAD);
+ }
+-EXPORT_SYMBOL_GPL(lbs_interrupt);
++EXPORT_SYMBOL_GPL(lbs_notify_command_response);
+ 
+ static int __init lbs_init_module(void)
+ {
+ 	lbs_deb_enter(LBS_DEB_MAIN);
++	memset(&confirm_sleep, 0, sizeof(confirm_sleep));
++	confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
++	confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
++	confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
+ 	lbs_debugfs_init();
+ 	lbs_deb_leave(LBS_DEB_MAIN);
+ 	return 0;
+@@ -1554,6 +1577,32 @@ out:
+ 	return ret;
+ }
+ 
++#ifndef CONFIG_IEEE80211
++const char *escape_essid(const char *essid, u8 essid_len)
++{
++	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
++	const char *s = essid;
++	char *d = escaped;
++
++	if (ieee80211_is_empty_essid(essid, essid_len)) {
++		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
++		return escaped;
++	}
++
++	essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
++	while (essid_len--) {
++		if (*s == '\0') {
++			*d++ = '\\';
++			*d++ = '0';
++			s++;
++		} else {
++			*d++ = *s++;
++		}
++	}
++	*d = '\0';
++	return escaped;
++}
++#endif
+ 
+ module_init(lbs_init_module);
+ module_exit(lbs_exit_module);
+diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
+index 149557a..05af731 100644
+--- a/drivers/net/wireless/libertas/rx.c
++++ b/drivers/net/wireless/libertas/rx.c
+@@ -145,17 +145,17 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
+ 	struct net_device *dev = priv->dev;
+ 	struct rxpackethdr *p_rx_pkt;
+ 	struct rxpd *p_rx_pd;
+-
+ 	int hdrchop;
+ 	struct ethhdr *p_ethhdr;
+-
+ 	const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+ 
+ 	lbs_deb_enter(LBS_DEB_RX);
+ 
++	BUG_ON(!skb);
++
+ 	skb->ip_summed = CHECKSUM_NONE;
+ 
+-	if (priv->monitormode != LBS_MONITOR_OFF)
++	if (priv->monitormode)
+ 		return process_rxed_802_11_packet(priv, skb);
+ 
+ 	p_rx_pkt = (struct rxpackethdr *) skb->data;
+diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
+index 69f94c9..e72c97a 100644
+--- a/drivers/net/wireless/libertas/scan.c
++++ b/drivers/net/wireless/libertas/scan.c
+@@ -4,22 +4,14 @@
+   * IOCTL handlers as well as command preperation and response routines
+   *  for sending scan commands to the firmware.
+   */
+-#include <linux/ctype.h>
+-#include <linux/if.h>
+-#include <linux/netdevice.h>
+-#include <linux/wireless.h>
+ #include <linux/etherdevice.h>
+-
+-#include <net/ieee80211.h>
+-#include <net/iw_handler.h>
+-
+ #include <asm/unaligned.h>
+ 
+ #include "host.h"
+ #include "decl.h"
+ #include "dev.h"
+ #include "scan.h"
+-#include "join.h"
++#include "cmd.h"
+ 
+ //! Approximate amount of data needed to pass a scan result back to iwlist
+ #define MAX_SCAN_CELL_SIZE  (IW_EV_ADDR_LEN             \
+@@ -39,10 +31,9 @@
+ //! Memory needed to store a max number/size SSID TLV for a firmware scan
+ #define SSID_TLV_MAX_SIZE  (1 * sizeof(struct mrvlietypes_ssidparamset))
+ 
+-//! Maximum memory needed for a lbs_scan_cmd_config with all TLVs at max
+-#define MAX_SCAN_CFG_ALLOC (sizeof(struct lbs_scan_cmd_config)  \
+-                            + CHAN_TLV_MAX_SIZE                 \
+-                            + SSID_TLV_MAX_SIZE)
++//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
++#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan)	\
++                            + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE)
+ 
+ //! The maximum number of channels the firmware can scan per command
+ #define MRVDRV_MAX_CHANNELS_PER_SCAN   14
+@@ -61,11 +52,8 @@
+ //! Scan time specified in the channel TLV for each channel for active scans
+ #define MRVDRV_ACTIVE_SCAN_CHAN_TIME   100
+ 
+-static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+-static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+-
+-
+-
++static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
++			      struct cmd_header *resp);
+ 
+ /*********************************************************************/
+ /*                                                                   */
+@@ -73,7 +61,24 @@ static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ /*                                                                   */
+ /*********************************************************************/
+ 
+-static inline void clear_bss_descriptor (struct bss_descriptor * bss)
++/**
++ *  @brief Unsets the MSB on basic rates
++ *
++ * Scan through an array and unset the MSB for basic data rates.
++ *
++ *  @param rates     buffer of data rates
++ *  @param len       size of buffer
++ */
++static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
++{
++	int i;
++
++	for (i = 0; i < len; i++)
++		rates[i] &= 0x7f;
++}
++
++
++static inline void clear_bss_descriptor(struct bss_descriptor *bss)
+ {
+ 	/* Don't blow away ->list, just BSS data */
+ 	memset(bss, 0, offsetof(struct bss_descriptor, list));
+@@ -87,7 +92,8 @@ static inline void clear_bss_descriptor (struct bss_descriptor * bss)
+  *
+  *  @return         0: ssid is same, otherwise is different
+  */
+-int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
++int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
++		 uint8_t ssid2_len)
+ {
+ 	if (ssid1_len != ssid2_len)
+ 		return -1;
+@@ -95,76 +101,6 @@ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
+ 	return memcmp(ssid1, ssid2, ssid1_len);
+ }
+ 
+-static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
+-			struct bss_descriptor * match_bss)
+-{
+-	if (   !secinfo->wep_enabled
+-	    && !secinfo->WPAenabled
+-	    && !secinfo->WPA2enabled
+-	    && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
+-	    && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
+-	    && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
+-			struct bss_descriptor * match_bss)
+-{
+-	if ( secinfo->wep_enabled
+-	   && !secinfo->WPAenabled
+-	   && !secinfo->WPA2enabled
+-	   && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
+-			struct bss_descriptor * match_bss)
+-{
+-	if (  !secinfo->wep_enabled
+-	   && secinfo->WPAenabled
+-	   && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
+-	   /* privacy bit may NOT be set in some APs like LinkSys WRT54G
+-	      && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+-	    */
+-	   ) {
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
+-			struct bss_descriptor * match_bss)
+-{
+-	if (  !secinfo->wep_enabled
+-	   && secinfo->WPA2enabled
+-	   && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
+-	   /* privacy bit may NOT be set in some APs like LinkSys WRT54G
+-	      && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+-	    */
+-	   ) {
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
+-			struct bss_descriptor * match_bss)
+-{
+-	if (  !secinfo->wep_enabled
+-	   && !secinfo->WPAenabled
+-	   && !secinfo->WPA2enabled
+-	   && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
+-	   && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
+-	   && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+ static inline int is_same_network(struct bss_descriptor *src,
+ 				  struct bss_descriptor *dst)
+ {
+@@ -177,83 +113,6 @@ static inline int is_same_network(struct bss_descriptor *src,
+ 		!memcmp(src->ssid, dst->ssid, src->ssid_len));
+ }
+ 
+-/**
+- *  @brief Check if a scanned network compatible with the driver settings
+- *
+- *   WEP     WPA     WPA2    ad-hoc  encrypt                      Network
+- * enabled enabled  enabled   AES     mode   privacy  WPA  WPA2  Compatible
+- *    0       0        0       0      NONE      0      0    0   yes No security
+- *    1       0        0       0      NONE      1      0    0   yes Static WEP
+- *    0       1        0       0       x        1x     1    x   yes WPA
+- *    0       0        1       0       x        1x     x    1   yes WPA2
+- *    0       0        0       1      NONE      1      0    0   yes Ad-hoc AES
+- *    0       0        0       0     !=NONE     1      0    0   yes Dynamic WEP
+- *
+- *
+- *  @param priv A pointer to struct lbs_private
+- *  @param index   Index in scantable to check against current driver settings
+- *  @param mode    Network mode: Infrastructure or IBSS
+- *
+- *  @return        Index in scantable, or error code if negative
+- */
+-static int is_network_compatible(struct lbs_private *priv,
+-		struct bss_descriptor * bss, u8 mode)
+-{
+-	int matched = 0;
+-
+-	lbs_deb_enter(LBS_DEB_SCAN);
+-
+-	if (bss->mode != mode)
+-		goto done;
+-
+-	if ((matched = match_bss_no_security(&priv->secinfo, bss))) {
+-		goto done;
+-	} else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) {
+-		goto done;
+-	} else if ((matched = match_bss_wpa(&priv->secinfo, bss))) {
+-		lbs_deb_scan(
+-		       "is_network_compatible() WPA: wpa_ie 0x%x "
+-		       "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
+-		       "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
+-		       priv->secinfo.wep_enabled ? "e" : "d",
+-		       priv->secinfo.WPAenabled ? "e" : "d",
+-		       priv->secinfo.WPA2enabled ? "e" : "d",
+-		       (bss->capability & WLAN_CAPABILITY_PRIVACY));
+-		goto done;
+-	} else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) {
+-		lbs_deb_scan(
+-		       "is_network_compatible() WPA2: wpa_ie 0x%x "
+-		       "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
+-		       "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
+-		       priv->secinfo.wep_enabled ? "e" : "d",
+-		       priv->secinfo.WPAenabled ? "e" : "d",
+-		       priv->secinfo.WPA2enabled ? "e" : "d",
+-		       (bss->capability & WLAN_CAPABILITY_PRIVACY));
+-		goto done;
+-	} else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) {
+-		lbs_deb_scan(
+-		       "is_network_compatible() dynamic WEP: "
+-		       "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
+-		       bss->wpa_ie[0], bss->rsn_ie[0],
+-		       (bss->capability & WLAN_CAPABILITY_PRIVACY));
+-		goto done;
+-	}
+-
+-	/* bss security settings don't match those configured on card */
+-	lbs_deb_scan(
+-	       "is_network_compatible() FAILED: wpa_ie 0x%x "
+-	       "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
+-	       bss->wpa_ie[0], bss->rsn_ie[0],
+-	       priv->secinfo.wep_enabled ? "e" : "d",
+-	       priv->secinfo.WPAenabled ? "e" : "d",
+-	       priv->secinfo.WPA2enabled ? "e" : "d",
+-	       (bss->capability & WLAN_CAPABILITY_PRIVACY));
+-
+-done:
+-	lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
+-	return matched;
+-}
+-
+ 
+ 
+ 
+@@ -263,17 +122,6 @@ done:
+ /*                                                                   */
+ /*********************************************************************/
+ 
+-void lbs_scan_worker(struct work_struct *work)
+-{
+-	struct lbs_private *priv =
+-		container_of(work, struct lbs_private, scan_work.work);
+-
+-	lbs_deb_enter(LBS_DEB_SCAN);
+-	lbs_scan_networks(priv, NULL, 0);
+-	lbs_deb_leave(LBS_DEB_SCAN);
+-}
+-
+-
+ /**
+  *  @brief Create a channel list for the driver to scan based on region info
+  *
+@@ -285,25 +133,18 @@ void lbs_scan_worker(struct work_struct *work)
+  *
+  *  @param priv          A pointer to struct lbs_private structure
+  *  @param scanchanlist  Output parameter: resulting channel list to scan
+- *  @param filteredscan  Flag indicating whether or not a BSSID or SSID filter
+- *                       is being sent in the command to firmware.  Used to
+- *                       increase the number of channels sent in a scan
+- *                       command and to disable the firmware channel scan
+- *                       filter.
+  *
+  *  @return              void
+  */
+ static int lbs_scan_create_channel_list(struct lbs_private *priv,
+-					  struct chanscanparamset * scanchanlist,
+-					  u8 filteredscan)
++					struct chanscanparamset *scanchanlist)
+ {
+-
+ 	struct region_channel *scanregion;
+ 	struct chan_freq_power *cfp;
+ 	int rgnidx;
+ 	int chanidx;
+ 	int nextchan;
+-	u8 scantype;
++	uint8_t scantype;
+ 
+ 	chanidx = 0;
+ 
+@@ -314,9 +155,8 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
+ 	scantype = CMD_SCAN_TYPE_ACTIVE;
+ 
+ 	for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
+-		if (priv->enable11d &&
+-		    (priv->connect_status != LBS_CONNECTED) &&
+-		    (priv->mesh_connect_status != LBS_CONNECTED)) {
++		if (priv->enable11d && (priv->connect_status != LBS_CONNECTED)
++		    && (priv->mesh_connect_status != LBS_CONNECTED)) {
+ 			/* Scan all the supported chan for the first scan */
+ 			if (!priv->universal_channel[rgnidx].valid)
+ 				continue;
+@@ -331,51 +171,32 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
+ 			scanregion = &priv->region_channel[rgnidx];
+ 		}
+ 
+-		for (nextchan = 0;
+-		     nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
++		for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
++			struct chanscanparamset *chan = &scanchanlist[chanidx];
+ 
+ 			cfp = scanregion->CFP + nextchan;
+ 
+-			if (priv->enable11d) {
+-				scantype =
+-				    lbs_get_scan_type_11d(cfp->channel,
+-							   &priv->
+-							   parsed_region_chan);
+-			}
++			if (priv->enable11d)
++				scantype = lbs_get_scan_type_11d(cfp->channel,
++								 &priv->parsed_region_chan);
+ 
+-			switch (scanregion->band) {
+-			case BAND_B:
+-			case BAND_G:
+-			default:
+-				scanchanlist[chanidx].radiotype =
+-				    CMD_SCAN_RADIO_TYPE_BG;
+-				break;
+-			}
++			if (scanregion->band == BAND_B || scanregion->band == BAND_G)
++				chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
+ 
+ 			if (scantype == CMD_SCAN_TYPE_PASSIVE) {
+-				scanchanlist[chanidx].maxscantime =
+-				    cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
+-				scanchanlist[chanidx].chanscanmode.passivescan =
+-				    1;
++				chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
++				chan->chanscanmode.passivescan = 1;
+ 			} else {
+-				scanchanlist[chanidx].maxscantime =
+-				    cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
+-				scanchanlist[chanidx].chanscanmode.passivescan =
+-				    0;
++				chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
++				chan->chanscanmode.passivescan = 0;
+ 			}
+ 
+-			scanchanlist[chanidx].channumber = cfp->channel;
+-
+-			if (filteredscan) {
+-				scanchanlist[chanidx].chanscanmode.
+-				    disablechanfilt = 1;
+-			}
++			chan->channumber = cfp->channel;
+ 		}
+ 	}
+ 	return chanidx;
+ }
+ 
+-
+ /*
+  * Add SSID TLV of the form:
+  *
+@@ -383,18 +204,16 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
+  * length          06 00
+  * ssid            4d 4e 54 45 53 54
+  */
+-static int lbs_scan_add_ssid_tlv(u8 *tlv,
+-	const struct lbs_ioctl_user_scan_cfg *user_cfg)
++static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
+ {
+-	struct mrvlietypes_ssidparamset *ssid_tlv =
+-		(struct mrvlietypes_ssidparamset *)tlv;
++	struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv;
++
+ 	ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
+-	ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len);
+-	memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len);
+-	return sizeof(ssid_tlv->header) + user_cfg->ssid_len;
++	ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
++	memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
++	return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
+ }
+ 
+-
+ /*
+  * Add CHANLIST TLV of the form
+  *
+@@ -420,13 +239,12 @@ static int lbs_scan_add_ssid_tlv(u8 *tlv,
+  * channel 13      00 0d 00 00 00 64 00
+  *
+  */
+-static int lbs_scan_add_chanlist_tlv(u8 *tlv,
+-	struct chanscanparamset *chan_list,
+-	int chan_count)
++static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
++				     struct chanscanparamset *chan_list,
++				     int chan_count)
+ {
+-	size_t size = sizeof(struct chanscanparamset) * chan_count;
+-	struct mrvlietypes_chanlistparamset *chan_tlv =
+-		(struct mrvlietypes_chanlistparamset *) tlv;
++	size_t size = sizeof(struct chanscanparamset) *chan_count;
++	struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv;
+ 
+ 	chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
+ 	memcpy(chan_tlv->chanscanparam, chan_list, size);
+@@ -434,7 +252,6 @@ static int lbs_scan_add_chanlist_tlv(u8 *tlv,
+ 	return sizeof(chan_tlv->header) + size;
+ }
+ 
+-
+ /*
+  * Add RATES TLV of the form
+  *
+@@ -445,11 +262,10 @@ static int lbs_scan_add_chanlist_tlv(u8 *tlv,
+  * The rates are in lbs_bg_rates[], but for the 802.11b
+  * rates the high bit isn't set.
+  */
+-static int lbs_scan_add_rates_tlv(u8 *tlv)
++static int lbs_scan_add_rates_tlv(uint8_t *tlv)
+ {
+ 	int i;
+-	struct mrvlietypes_ratesparamset *rate_tlv =
+-		(struct mrvlietypes_ratesparamset *) tlv;
++	struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv;
+ 
+ 	rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
+ 	tlv += sizeof(rate_tlv->header);
+@@ -470,82 +286,74 @@ static int lbs_scan_add_rates_tlv(u8 *tlv)
+ 	return sizeof(rate_tlv->header) + i;
+ }
+ 
+-
+ /*
+  * Generate the CMD_802_11_SCAN command with the proper tlv
+  * for a bunch of channels.
+  */
+-static int lbs_do_scan(struct lbs_private *priv,
+-	u8 bsstype,
+-	struct chanscanparamset *chan_list,
+-	int chan_count,
+-	const struct lbs_ioctl_user_scan_cfg *user_cfg)
++static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
++		       struct chanscanparamset *chan_list, int chan_count)
+ {
+ 	int ret = -ENOMEM;
+-	struct lbs_scan_cmd_config *scan_cmd;
+-	u8 *tlv;    /* pointer into our current, growing TLV storage area */
++	struct cmd_ds_802_11_scan *scan_cmd;
++	uint8_t *tlv;	/* pointer into our current, growing TLV storage area */
+ 
+-	lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, "
+-		"chan_count %d",
+-		bsstype, chan_list[0].channumber, chan_count);
++	lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d",
++			   bsstype, chan_list[0].channumber, chan_count);
+ 
+ 	/* create the fixed part for scan command */
+ 	scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
+ 	if (scan_cmd == NULL)
+ 		goto out;
++
+ 	tlv = scan_cmd->tlvbuffer;
+-	if (user_cfg)
+-		memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN);
++	/* TODO: do we need to scan for a specific BSSID?
++	memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
+ 	scan_cmd->bsstype = bsstype;
+ 
+ 	/* add TLVs */
+-	if (user_cfg && user_cfg->ssid_len)
+-		tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg);
++	if (priv->scan_ssid_len)
++		tlv += lbs_scan_add_ssid_tlv(priv, tlv);
+ 	if (chan_list && chan_count)
+ 		tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
+ 	tlv += lbs_scan_add_rates_tlv(tlv);
+ 
+ 	/* This is the final data we are about to send */
+-	scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer;
+-	lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6);
++	scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd);
++	lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
++		    sizeof(*scan_cmd));
+ 	lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
+-		scan_cmd->tlvbufferlen);
++		    tlv - scan_cmd->tlvbuffer);
++
++	ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
++			le16_to_cpu(scan_cmd->hdr.size),
++			lbs_ret_80211_scan, 0);
+ 
+-	ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0,
+-		CMD_OPTION_WAITFORRSP, 0, scan_cmd);
+ out:
+ 	kfree(scan_cmd);
+ 	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+ 	return ret;
+ }
+ 
+-
+ /**
+  *  @brief Internal function used to start a scan based on an input config
+  *
+- *  Also used from debugfs
+- *
+  *  Use the input user scan configuration information when provided in
+  *    order to send the appropriate scan commands to firmware to populate or
+  *    update the internal driver scan table
+  *
+  *  @param priv          A pointer to struct lbs_private structure
+- *  @param puserscanin   Pointer to the input configuration for the requested
+- *                       scan.
++ *  @param full_scan     Do a full-scan (blocking)
+  *
+  *  @return              0 or < 0 if error
+  */
+-int lbs_scan_networks(struct lbs_private *priv,
+-	const struct lbs_ioctl_user_scan_cfg *user_cfg,
+-                       int full_scan)
++int lbs_scan_networks(struct lbs_private *priv, int full_scan)
+ {
+ 	int ret = -ENOMEM;
+ 	struct chanscanparamset *chan_list;
+ 	struct chanscanparamset *curr_chans;
+ 	int chan_count;
+-	u8 bsstype = CMD_BSS_TYPE_ANY;
++	uint8_t bsstype = CMD_BSS_TYPE_ANY;
+ 	int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
+-	int filteredscan = 0;
+ 	union iwreq_data wrqu;
+ #ifdef CONFIG_LIBERTAS_DEBUG
+ 	struct bss_descriptor *iter;
+@@ -553,8 +361,7 @@ int lbs_scan_networks(struct lbs_private *priv,
+ 	DECLARE_MAC_BUF(mac);
+ #endif
+ 
+-	lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d",
+-		full_scan);
++	lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
+ 
+ 	/* Cancel any partial outstanding partial scans if this scan
+ 	 * is a full scan.
+@@ -562,30 +369,27 @@ int lbs_scan_networks(struct lbs_private *priv,
+ 	if (full_scan && delayed_work_pending(&priv->scan_work))
+ 		cancel_delayed_work(&priv->scan_work);
+ 
+-	/* Determine same scan parameters */
++	/* User-specified bsstype or channel list
++	TODO: this can be implemented if some user-space application
++	need the feature. Formerly, it was accessible from debugfs,
++	but then nowhere used.
+ 	if (user_cfg) {
+ 		if (user_cfg->bsstype)
+-			bsstype = user_cfg->bsstype;
+-		if (compare_ether_addr(user_cfg->bssid, &zeromac[0]) != 0) {
+-			numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN;
+-			filteredscan = 1;
+-		}
+-	}
+-	lbs_deb_scan("numchannels %d, bsstype %d, "
+-		"filteredscan %d\n",
+-		numchannels, bsstype, filteredscan);
++		bsstype = user_cfg->bsstype;
++	} */
++
++	lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
+ 
+ 	/* Create list of channels to scan */
+ 	chan_list = kzalloc(sizeof(struct chanscanparamset) *
+-				LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
++			    LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
+ 	if (!chan_list) {
+ 		lbs_pr_alert("SCAN: chan_list empty\n");
+ 		goto out;
+ 	}
+ 
+ 	/* We want to scan all channels */
+-	chan_count = lbs_scan_create_channel_list(priv, chan_list,
+-		filteredscan);
++	chan_count = lbs_scan_create_channel_list(priv, chan_list);
+ 
+ 	netif_stop_queue(priv->dev);
+ 	netif_carrier_off(priv->dev);
+@@ -595,13 +399,13 @@ int lbs_scan_networks(struct lbs_private *priv,
+ 	}
+ 
+ 	/* Prepare to continue an interrupted scan */
+-	lbs_deb_scan("chan_count %d, last_scanned_channel %d\n",
+-		     chan_count, priv->last_scanned_channel);
++	lbs_deb_scan("chan_count %d, scan_channel %d\n",
++		     chan_count, priv->scan_channel);
+ 	curr_chans = chan_list;
+ 	/* advance channel list by already-scanned-channels */
+-	if (priv->last_scanned_channel > 0) {
+-		curr_chans += priv->last_scanned_channel;
+-		chan_count -= priv->last_scanned_channel;
++	if (priv->scan_channel > 0) {
++		curr_chans += priv->scan_channel;
++		chan_count -= priv->scan_channel;
+ 	}
+ 
+ 	/* Send scan command(s)
+@@ -612,9 +416,9 @@ int lbs_scan_networks(struct lbs_private *priv,
+ 	while (chan_count) {
+ 		int to_scan = min(numchannels, chan_count);
+ 		lbs_deb_scan("scanning %d of %d channels\n",
+-			to_scan, chan_count);
++			     to_scan, chan_count);
+ 		ret = lbs_do_scan(priv, bsstype, curr_chans,
+-			to_scan, user_cfg);
++				  to_scan);
+ 		if (ret) {
+ 			lbs_pr_err("SCAN_CMD failed\n");
+ 			goto out2;
+@@ -623,17 +427,16 @@ int lbs_scan_networks(struct lbs_private *priv,
+ 		chan_count -= to_scan;
+ 
+ 		/* somehow schedule the next part of the scan */
+-		if (chan_count &&
+-		    !full_scan &&
++		if (chan_count && !full_scan &&
+ 		    !priv->surpriseremoved) {
+ 			/* -1 marks just that we're currently scanning */
+-			if (priv->last_scanned_channel < 0)
+-				priv->last_scanned_channel = to_scan;
++			if (priv->scan_channel < 0)
++				priv->scan_channel = to_scan;
+ 			else
+-				priv->last_scanned_channel += to_scan;
++				priv->scan_channel += to_scan;
+ 			cancel_delayed_work(&priv->scan_work);
+ 			queue_delayed_work(priv->work_thread, &priv->scan_work,
+-				msecs_to_jiffies(300));
++					   msecs_to_jiffies(300));
+ 			/* skip over GIWSCAN event */
+ 			goto out;
+ 		}
+@@ -648,13 +451,13 @@ int lbs_scan_networks(struct lbs_private *priv,
+ 	lbs_deb_scan("scan table:\n");
+ 	list_for_each_entry(iter, &priv->network_list, list)
+ 		lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n",
+-		       i++, print_mac(mac, iter->bssid), (s32) iter->rssi,
+-		       escape_essid(iter->ssid, iter->ssid_len));
++			     i++, print_mac(mac, iter->bssid), iter->rssi,
++			     escape_essid(iter->ssid, iter->ssid_len));
+ 	mutex_unlock(&priv->lock);
+ #endif
+ 
+ out2:
+-	priv->last_scanned_channel = 0;
++	priv->scan_channel = 0;
+ 
+ out:
+ 	if (priv->connect_status == LBS_CONNECTED) {
+@@ -673,7 +476,15 @@ out:
+ 	return ret;
+ }
+ 
++void lbs_scan_worker(struct work_struct *work)
++{
++	struct lbs_private *priv =
++		container_of(work, struct lbs_private, scan_work.work);
+ 
++	lbs_deb_enter(LBS_DEB_SCAN);
++	lbs_scan_networks(priv, 0);
++	lbs_deb_leave(LBS_DEB_SCAN);
++}
+ 
+ 
+ /*********************************************************************/
+@@ -694,7 +505,7 @@ out:
+  *  @return             0 or -1
+  */
+ static int lbs_process_bss(struct bss_descriptor *bss,
+-				u8 ** pbeaconinfo, int *bytesleft)
++			   uint8_t **pbeaconinfo, int *bytesleft)
+ {
+ 	struct ieeetypes_fhparamset *pFH;
+ 	struct ieeetypes_dsparamset *pDS;
+@@ -702,9 +513,9 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ 	struct ieeetypes_ibssparamset *pibss;
+ 	DECLARE_MAC_BUF(mac);
+ 	struct ieeetypes_countryinfoset *pcountryinfo;
+-	u8 *pos, *end, *p;
+-	u8 n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
+-	u16 beaconsize = 0;
++	uint8_t *pos, *end, *p;
++	uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
++	uint16_t beaconsize = 0;
+ 	int ret;
+ 
+ 	lbs_deb_enter(LBS_DEB_SCAN);
+@@ -776,12 +587,11 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ 
+ 	/* process variable IE */
+ 	while (pos <= end - 2) {
+-		struct ieee80211_info_element * elem =
+-			(struct ieee80211_info_element *) pos;
++		struct ieee80211_info_element * elem = (void *)pos;
+ 
+ 		if (pos + elem->len > end) {
+ 			lbs_deb_scan("process_bss: error in processing IE, "
+-			       "bytes left < IE length\n");
++				     "bytes left < IE length\n");
+ 			break;
+ 		}
+ 
+@@ -795,7 +605,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ 			break;
+ 
+ 		case MFIE_TYPE_RATES:
+-			n_basic_rates = min_t(u8, MAX_RATES, elem->len);
++			n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len);
+ 			memcpy(bss->rates, elem->data, n_basic_rates);
+ 			got_basic_rates = 1;
+ 			lbs_deb_scan("got RATES IE\n");
+@@ -836,19 +646,16 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ 			lbs_deb_scan("got COUNTRY IE\n");
+ 			if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
+ 			    || pcountryinfo->len > 254) {
+-				lbs_deb_scan("process_bss: 11D- Err "
+-				       "CountryInfo len %d, min %zd, max 254\n",
+-				       pcountryinfo->len,
+-				       sizeof(pcountryinfo->countrycode));
++				lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n",
++					     pcountryinfo->len, sizeof(pcountryinfo->countrycode));
+ 				ret = -1;
+ 				goto done;
+ 			}
+ 
+-			memcpy(&bss->countryinfo,
+-			       pcountryinfo, pcountryinfo->len + 2);
++			memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2);
+ 			lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
+-				(u8 *) pcountryinfo,
+-				(u32) (pcountryinfo->len + 2));
++				    (uint8_t *) pcountryinfo,
++				    (int) (pcountryinfo->len + 2));
+ 			break;
+ 
+ 		case MFIE_TYPE_RATES_EX:
+@@ -872,26 +679,19 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ 
+ 		case MFIE_TYPE_GENERIC:
+ 			if (elem->len >= 4 &&
+-			    elem->data[0] == 0x00 &&
+-			    elem->data[1] == 0x50 &&
+-			    elem->data[2] == 0xf2 &&
+-			    elem->data[3] == 0x01) {
+-				bss->wpa_ie_len = min(elem->len + 2,
+-				                      MAX_WPA_IE_LEN);
++			    elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
++			    elem->data[2] == 0xf2 && elem->data[3] == 0x01) {
++				bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
+ 				memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);
+ 				lbs_deb_scan("got WPA IE\n");
+-				lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
+-				            elem->len);
++				lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len);
+ 			} else if (elem->len >= MARVELL_MESH_IE_LENGTH &&
+-			    elem->data[0] == 0x00 &&
+-			    elem->data[1] == 0x50 &&
+-			    elem->data[2] == 0x43 &&
+-			    elem->data[3] == 0x04) {
++				   elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
++				   elem->data[2] == 0x43 && elem->data[3] == 0x04) {
+ 				lbs_deb_scan("got mesh IE\n");
+ 				bss->mesh = 1;
+ 			} else {
+-				lbs_deb_scan("got generiec IE: "
+-					"%02x:%02x:%02x:%02x, len %d\n",
++				lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
+ 					elem->data[0], elem->data[1],
+ 					elem->data[2], elem->data[3],
+ 					elem->len);
+@@ -903,12 +703,12 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ 			bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
+ 			memcpy(bss->rsn_ie, elem, bss->rsn_ie_len);
+ 			lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
+-				bss->rsn_ie, elem->len);
++				    bss->rsn_ie, elem->len);
+ 			break;
+ 
+ 		default:
+ 			lbs_deb_scan("got IE 0x%04x, len %d\n",
+-				elem->id, elem->len);
++				     elem->id, elem->len);
+ 			break;
+ 		}
+ 
+@@ -927,213 +727,6 @@ done:
+ }
+ 
+ /**
+- *  @brief This function finds a specific compatible BSSID in the scan list
+- *
+- *  Used in association code
+- *
+- *  @param priv  A pointer to struct lbs_private
+- *  @param bssid    BSSID to find in the scan list
+- *  @param mode     Network mode: Infrastructure or IBSS
+- *
+- *  @return         index in BSSID list, or error return code (< 0)
+- */
+-struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
+-		u8 * bssid, u8 mode)
+-{
+-	struct bss_descriptor * iter_bss;
+-	struct bss_descriptor * found_bss = NULL;
+-
+-	lbs_deb_enter(LBS_DEB_SCAN);
+-
+-	if (!bssid)
+-		goto out;
+-
+-	lbs_deb_hex(LBS_DEB_SCAN, "looking for",
+-		bssid, ETH_ALEN);
+-
+-	/* Look through the scan table for a compatible match.  The loop will
+-	 *   continue past a matched bssid that is not compatible in case there
+-	 *   is an AP with multiple SSIDs assigned to the same BSSID
+-	 */
+-	mutex_lock(&priv->lock);
+-	list_for_each_entry (iter_bss, &priv->network_list, list) {
+-		if (compare_ether_addr(iter_bss->bssid, bssid))
+-			continue; /* bssid doesn't match */
+-		switch (mode) {
+-		case IW_MODE_INFRA:
+-		case IW_MODE_ADHOC:
+-			if (!is_network_compatible(priv, iter_bss, mode))
+-				break;
+-			found_bss = iter_bss;
+-			break;
+-		default:
+-			found_bss = iter_bss;
+-			break;
+-		}
+-	}
+-	mutex_unlock(&priv->lock);
+-
+-out:
+-	lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
+-	return found_bss;
+-}
+-
+-/**
+- *  @brief This function finds ssid in ssid list.
+- *
+- *  Used in association code
+- *
+- *  @param priv  A pointer to struct lbs_private
+- *  @param ssid     SSID to find in the list
+- *  @param bssid    BSSID to qualify the SSID selection (if provided)
+- *  @param mode     Network mode: Infrastructure or IBSS
+- *
+- *  @return         index in BSSID list
+- */
+-struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
+-		   u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,
+-		   int channel)
+-{
+-	u8 bestrssi = 0;
+-	struct bss_descriptor * iter_bss = NULL;
+-	struct bss_descriptor * found_bss = NULL;
+-	struct bss_descriptor * tmp_oldest = NULL;
+-
+-	lbs_deb_enter(LBS_DEB_SCAN);
+-
+-	mutex_lock(&priv->lock);
+-
+-	list_for_each_entry (iter_bss, &priv->network_list, list) {
+-		if (   !tmp_oldest
+-		    || (iter_bss->last_scanned < tmp_oldest->last_scanned))
+-			tmp_oldest = iter_bss;
+-
+-		if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
+-		                      ssid, ssid_len) != 0)
+-			continue; /* ssid doesn't match */
+-		if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
+-			continue; /* bssid doesn't match */
+-		if ((channel > 0) && (iter_bss->channel != channel))
+-			continue; /* channel doesn't match */
+-
+-		switch (mode) {
+-		case IW_MODE_INFRA:
+-		case IW_MODE_ADHOC:
+-			if (!is_network_compatible(priv, iter_bss, mode))
+-				break;
+-
+-			if (bssid) {
+-				/* Found requested BSSID */
+-				found_bss = iter_bss;
+-				goto out;
+-			}
+-
+-			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
+-				bestrssi = SCAN_RSSI(iter_bss->rssi);
+-				found_bss = iter_bss;
+-			}
+-			break;
+-		case IW_MODE_AUTO:
+-		default:
+-			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
+-				bestrssi = SCAN_RSSI(iter_bss->rssi);
+-				found_bss = iter_bss;
+-			}
+-			break;
+-		}
+-	}
+-
+-out:
+-	mutex_unlock(&priv->lock);
+-	lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
+-	return found_bss;
+-}
+-
+-/**
+- *  @brief This function finds the best SSID in the Scan List
+- *
+- *  Search the scan table for the best SSID that also matches the current
+- *   adapter network preference (infrastructure or adhoc)
+- *
+- *  @param priv  A pointer to struct lbs_private
+- *
+- *  @return         index in BSSID list
+- */
+-static struct bss_descriptor *lbs_find_best_ssid_in_list(
+-	struct lbs_private *priv,
+-	u8 mode)
+-{
+-	u8 bestrssi = 0;
+-	struct bss_descriptor * iter_bss;
+-	struct bss_descriptor * best_bss = NULL;
+-
+-	lbs_deb_enter(LBS_DEB_SCAN);
+-
+-	mutex_lock(&priv->lock);
+-
+-	list_for_each_entry (iter_bss, &priv->network_list, list) {
+-		switch (mode) {
+-		case IW_MODE_INFRA:
+-		case IW_MODE_ADHOC:
+-			if (!is_network_compatible(priv, iter_bss, mode))
+-				break;
+-			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
+-				break;
+-			bestrssi = SCAN_RSSI(iter_bss->rssi);
+-			best_bss = iter_bss;
+-			break;
+-		case IW_MODE_AUTO:
+-		default:
+-			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
+-				break;
+-			bestrssi = SCAN_RSSI(iter_bss->rssi);
+-			best_bss = iter_bss;
+-			break;
+-		}
+-	}
+-
+-	mutex_unlock(&priv->lock);
+-	lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
+-	return best_bss;
+-}
+-
+-/**
+- *  @brief Find the AP with specific ssid in the scan list
+- *
+- *  Used from association worker.
+- *
+- *  @param priv         A pointer to struct lbs_private structure
+- *  @param pSSID        A pointer to AP's ssid
+- *
+- *  @return             0--success, otherwise--fail
+- */
+-int lbs_find_best_network_ssid(struct lbs_private *priv,
+-		u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode)
+-{
+-	int ret = -1;
+-	struct bss_descriptor * found;
+-
+-	lbs_deb_enter(LBS_DEB_SCAN);
+-
+-	lbs_scan_networks(priv, NULL, 1);
+-	if (priv->surpriseremoved)
+-		goto out;
+-
+-	found = lbs_find_best_ssid_in_list(priv, preferred_mode);
+-	if (found && (found->ssid_len > 0)) {
+-		memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
+-		*out_ssid_len = found->ssid_len;
+-		*out_mode = found->mode;
+-		ret = 0;
+-	}
+-
+-out:
+-	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+-	return ret;
+-}
+-
+-
+-/**
+  *  @brief Send a scan command for all available channels filtered on a spec
+  *
+  *  Used in association code and from debugfs
+@@ -1141,29 +734,24 @@ out:
+  *  @param priv             A pointer to struct lbs_private structure
+  *  @param ssid             A pointer to the SSID to scan for
+  *  @param ssid_len         Length of the SSID
+- *  @param clear_ssid       Should existing scan results with this SSID
+- *                          be cleared?
+  *
+  *  @return                0-success, otherwise fail
+  */
+-int lbs_send_specific_ssid_scan(struct lbs_private *priv,
+-			u8 *ssid, u8 ssid_len, u8 clear_ssid)
++int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
++				uint8_t ssid_len)
+ {
+-	struct lbs_ioctl_user_scan_cfg scancfg;
+ 	int ret = 0;
+ 
+-	lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d",
+-		escape_essid(ssid, ssid_len), clear_ssid);
++	lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
++			   escape_essid(ssid, ssid_len));
+ 
+ 	if (!ssid_len)
+ 		goto out;
+ 
+-	memset(&scancfg, 0x00, sizeof(scancfg));
+-	memcpy(scancfg.ssid, ssid, ssid_len);
+-	scancfg.ssid_len = ssid_len;
+-	scancfg.clear_ssid = clear_ssid;
++	memcpy(priv->scan_ssid, ssid, ssid_len);
++	priv->scan_ssid_len = ssid_len;
+ 
+-	lbs_scan_networks(priv, &scancfg, 1);
++	lbs_scan_networks(priv, 1);
+ 	if (priv->surpriseremoved) {
+ 		ret = -1;
+ 		goto out;
+@@ -1187,17 +775,17 @@ out:
+ #define MAX_CUSTOM_LEN 64
+ 
+ static inline char *lbs_translate_scan(struct lbs_private *priv,
+-					char *start, char *stop,
+-					struct bss_descriptor *bss)
++				       char *start, char *stop,
++				       struct bss_descriptor *bss)
+ {
+ 	struct chan_freq_power *cfp;
+ 	char *current_val;	/* For rates */
+ 	struct iw_event iwe;	/* Temporary buffer */
+ 	int j;
+-#define PERFECT_RSSI ((u8)50)
+-#define WORST_RSSI   ((u8)0)
+-#define RSSI_DIFF    ((u8)(PERFECT_RSSI - WORST_RSSI))
+-	u8 rssi;
++#define PERFECT_RSSI ((uint8_t)50)
++#define WORST_RSSI   ((uint8_t)0)
++#define RSSI_DIFF    ((uint8_t)(PERFECT_RSSI - WORST_RSSI))
++	uint8_t rssi;
+ 
+ 	lbs_deb_enter(LBS_DEB_SCAN);
+ 
+@@ -1217,7 +805,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
+ 	/* SSID */
+ 	iwe.cmd = SIOCGIWESSID;
+ 	iwe.u.data.flags = 1;
+-	iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE);
++	iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE);
+ 	start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
+ 
+ 	/* Mode */
+@@ -1238,28 +826,26 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
+ 
+ 	rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
+ 	iwe.u.qual.qual =
+-	    (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
+-	     (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
+-	    (RSSI_DIFF * RSSI_DIFF);
++		(100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
++		 (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
++		(RSSI_DIFF * RSSI_DIFF);
+ 	if (iwe.u.qual.qual > 100)
+ 		iwe.u.qual.qual = 100;
+ 
+ 	if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
+ 		iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
+ 	} else {
+-		iwe.u.qual.noise =
+-		    CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
++		iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
+ 	}
+ 
+ 	/* Locally created ad-hoc BSSs won't have beacons if this is the
+ 	 * only station in the adhoc network; so get signal strength
+ 	 * from receive statistics.
+ 	 */
+-	if ((priv->mode == IW_MODE_ADHOC)
+-	    && priv->adhoccreate
++	if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate
+ 	    && !lbs_ssid_cmp(priv->curbssparams.ssid,
+-	                          priv->curbssparams.ssid_len,
+-	                          bss->ssid, bss->ssid_len)) {
++			     priv->curbssparams.ssid_len,
++			     bss->ssid, bss->ssid_len)) {
+ 		int snr, nf;
+ 		snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+ 		nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+@@ -1290,14 +876,13 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
+ 		current_val = iwe_stream_add_value(start, current_val,
+ 					 stop, &iwe, IW_EV_PARAM_LEN);
+ 	}
+-	if ((bss->mode == IW_MODE_ADHOC)
++	if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
+ 	    && !lbs_ssid_cmp(priv->curbssparams.ssid,
+-	                          priv->curbssparams.ssid_len,
+-	                          bss->ssid, bss->ssid_len)
+-	    && priv->adhoccreate) {
++			     priv->curbssparams.ssid_len,
++			     bss->ssid, bss->ssid_len)) {
+ 		iwe.u.bitrate.value = 22 * 500000;
+ 		current_val = iwe_stream_add_value(start, current_val,
+-					 stop, &iwe, IW_EV_PARAM_LEN);
++						   stop, &iwe, IW_EV_PARAM_LEN);
+ 	}
+ 	/* Check if we added any event */
+ 	if((current_val - start) > IW_EV_LCP_LEN)
+@@ -1326,8 +911,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
+ 		char *p = custom;
+ 
+ 		iwe.cmd = IWEVCUSTOM;
+-		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+-		              "mesh-type: olpc");
++		p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
+ 		iwe.u.data.length = p - custom;
+ 		if (iwe.u.data.length)
+ 			start = iwe_stream_add_point(start, stop, &iwe, custom);
+@@ -1350,39 +934,49 @@ out:
+  *  @return             0 --success, otherwise fail
+  */
+ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
+-		  struct iw_param *wrqu, char *extra)
++		 union iwreq_data *wrqu, char *extra)
+ {
+ 	struct lbs_private *priv = dev->priv;
++	int ret = 0;
+ 
+-	lbs_deb_enter(LBS_DEB_SCAN);
++	lbs_deb_enter(LBS_DEB_WEXT);
+ 
+-	if (!netif_running(dev))
+-		return -ENETDOWN;
++	if (!netif_running(dev)) {
++		ret = -ENETDOWN;
++		goto out;
++	}
+ 
+ 	/* mac80211 does this:
+ 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->type != IEEE80211_IF_TYPE_xxx)
+-		return -EOPNOTSUPP;
++	if (sdata->type != IEEE80211_IF_TYPE_xxx) {
++		ret = -EOPNOTSUPP;
++		goto out;
++	}
++	*/
+ 
+ 	if (wrqu->data.length == sizeof(struct iw_scan_req) &&
+ 	    wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+-		req = (struct iw_scan_req *)extra;
+-			ssid = req->essid;
+-		ssid_len = req->essid_len;
++		struct iw_scan_req *req = (struct iw_scan_req *)extra;
++		priv->scan_ssid_len = req->essid_len;
++		memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
++		lbs_deb_wext("set_scan, essid '%s'\n",
++			escape_essid(priv->scan_ssid, priv->scan_ssid_len));
++	} else {
++		priv->scan_ssid_len = 0;
+ 	}
+-	*/
+ 
+ 	if (!delayed_work_pending(&priv->scan_work))
+ 		queue_delayed_work(priv->work_thread, &priv->scan_work,
+-			msecs_to_jiffies(50));
++				   msecs_to_jiffies(50));
+ 	/* set marker that currently a scan is taking place */
+-	priv->last_scanned_channel = -1;
++	priv->scan_channel = -1;
+ 
+ 	if (priv->surpriseremoved)
+-		return -EIO;
++		ret = -EIO;
+ 
+-	lbs_deb_leave(LBS_DEB_SCAN);
+-	return 0;
++out:
++	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
++	return ret;
+ }
+ 
+ 
+@@ -1397,31 +991,30 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
+  *  @return             0 --success, otherwise fail
+  */
+ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+-		  struct iw_point *dwrq, char *extra)
++		 struct iw_point *dwrq, char *extra)
+ {
+ #define SCAN_ITEM_SIZE 128
+ 	struct lbs_private *priv = dev->priv;
+ 	int err = 0;
+ 	char *ev = extra;
+ 	char *stop = ev + dwrq->length;
+-	struct bss_descriptor * iter_bss;
+-	struct bss_descriptor * safe;
++	struct bss_descriptor *iter_bss;
++	struct bss_descriptor *safe;
+ 
+-	lbs_deb_enter(LBS_DEB_SCAN);
++	lbs_deb_enter(LBS_DEB_WEXT);
+ 
+ 	/* iwlist should wait until the current scan is finished */
+-	if (priv->last_scanned_channel)
++	if (priv->scan_channel)
+ 		return -EAGAIN;
+ 
+ 	/* Update RSSI if current BSS is a locally created ad-hoc BSS */
+-	if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
++	if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate)
+ 		lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+-					CMD_OPTION_WAITFORRSP, 0, NULL);
+-	}
++					     CMD_OPTION_WAITFORRSP, 0, NULL);
+ 
+ 	mutex_lock(&priv->lock);
+ 	list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
+-		char * next_ev;
++		char *next_ev;
+ 		unsigned long stale_time;
+ 
+ 		if (stop - ev < SCAN_ITEM_SIZE) {
+@@ -1436,8 +1029,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+ 		/* Prune old an old scan result */
+ 		stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
+ 		if (time_after(jiffies, stale_time)) {
+-			list_move_tail (&iter_bss->list,
+-			                &priv->network_free_list);
++			list_move_tail(&iter_bss->list, &priv->network_free_list);
+ 			clear_bss_descriptor(iter_bss);
+ 			continue;
+ 		}
+@@ -1453,7 +1045,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+ 	dwrq->length = (ev - extra);
+ 	dwrq->flags = 0;
+ 
+-	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err);
++	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
+ 	return err;
+ }
+ 
+@@ -1468,44 +1060,6 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+ 
+ 
+ /**
+- *  @brief Prepare a scan command to be sent to the firmware
+- *
+- *  Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...)
+- *  from cmd.c
+- *
+- *  Sends a fixed length data part (specifying the BSS type and BSSID filters)
+- *  as well as a variable number/length of TLVs to the firmware.
+- *
+- *  @param priv       A pointer to struct lbs_private structure
+- *  @param cmd        A pointer to cmd_ds_command structure to be sent to
+- *                    firmware with the cmd_DS_801_11_SCAN structure
+- *  @param pdata_buf  Void pointer cast of a lbs_scan_cmd_config struct used
+- *                    to set the fields/TLVs for the command sent to firmware
+- *
+- *  @return           0 or -1
+- */
+-int lbs_cmd_80211_scan(struct lbs_private *priv,
+-	struct cmd_ds_command *cmd, void *pdata_buf)
+-{
+-	struct cmd_ds_802_11_scan *pscan = &cmd->params.scan;
+-	struct lbs_scan_cmd_config *pscancfg = pdata_buf;
+-
+-	lbs_deb_enter(LBS_DEB_SCAN);
+-
+-	/* Set fixed field variables in scan command */
+-	pscan->bsstype = pscancfg->bsstype;
+-	memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN);
+-	memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen);
+-
+-	/* size is equal to the sizeof(fixed portions) + the TLV len + header */
+-	cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN
+-				+ pscancfg->tlvbufferlen + S_DS_GEN);
+-
+-	lbs_deb_leave(LBS_DEB_SCAN);
+-	return 0;
+-}
+-
+-/**
+  *  @brief This function handles the command response of scan
+  *
+  *  Called from handle_cmd_response() in cmdrespc.
+@@ -1531,13 +1085,14 @@ int lbs_cmd_80211_scan(struct lbs_private *priv,
+  *
+  *  @return        0 or -1
+  */
+-int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
++static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
++			      struct cmd_header *resp)
+ {
+-	struct cmd_ds_802_11_scan_rsp *pscan;
+-	struct bss_descriptor * iter_bss;
+-	struct bss_descriptor * safe;
+-	u8 *pbssinfo;
+-	u16 scanrespsize;
++	struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
++	struct bss_descriptor *iter_bss;
++	struct bss_descriptor *safe;
++	uint8_t *bssinfo;
++	uint16_t scanrespsize;
+ 	int bytesleft;
+ 	int idx;
+ 	int tlvbufsize;
+@@ -1554,48 +1109,45 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
+ 		clear_bss_descriptor(iter_bss);
+ 	}
+ 
+-	pscan = &resp->params.scanresp;
+-
+-	if (pscan->nr_sets > MAX_NETWORK_COUNT) {
+-		lbs_deb_scan(
+-		       "SCAN_RESP: too many scan results (%d, max %d)!!\n",
+-		       pscan->nr_sets, MAX_NETWORK_COUNT);
++	if (scanresp->nr_sets > MAX_NETWORK_COUNT) {
++		lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n",
++			     scanresp->nr_sets, MAX_NETWORK_COUNT);
+ 		ret = -1;
+ 		goto done;
+ 	}
+ 
+-	bytesleft = le16_to_cpu(pscan->bssdescriptsize);
++	bytesleft = le16_to_cpu(scanresp->bssdescriptsize);
+ 	lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
+ 
+ 	scanrespsize = le16_to_cpu(resp->size);
+-	lbs_deb_scan("SCAN_RESP: scan results %d\n", pscan->nr_sets);
++	lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets);
+ 
+-	pbssinfo = pscan->bssdesc_and_tlvbuffer;
++	bssinfo = scanresp->bssdesc_and_tlvbuffer;
+ 
+ 	/* The size of the TLV buffer is equal to the entire command response
+ 	 *   size (scanrespsize) minus the fixed fields (sizeof()'s), the
+ 	 *   BSS Descriptions (bssdescriptsize as bytesLef) and the command
+ 	 *   response header (S_DS_GEN)
+ 	 */
+-	tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize)
+-				     + sizeof(pscan->nr_sets)
++	tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
++				     + sizeof(scanresp->nr_sets)
+ 				     + S_DS_GEN);
+ 
+ 	/*
+-	 *  Process each scan response returned (pscan->nr_sets).  Save
++	 *  Process each scan response returned (scanresp->nr_sets). Save
+ 	 *    the information in the newbssentry and then insert into the
+ 	 *    driver scan table either as an update to an existing entry
+ 	 *    or as an addition at the end of the table
+ 	 */
+-	for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) {
++	for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) {
+ 		struct bss_descriptor new;
+-		struct bss_descriptor * found = NULL;
+-		struct bss_descriptor * oldest = NULL;
++		struct bss_descriptor *found = NULL;
++		struct bss_descriptor *oldest = NULL;
+ 		DECLARE_MAC_BUF(mac);
+ 
+ 		/* Process the data fields and IEs returned for this BSS */
+ 		memset(&new, 0, sizeof (struct bss_descriptor));
+-		if (lbs_process_bss(&new, &pbssinfo, &bytesleft) != 0) {
++		if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) {
+ 			/* error parsing the scan response, skipped */
+ 			lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
+ 			continue;
+@@ -1630,8 +1182,7 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
+ 			continue;
+ 		}
+ 
+-		lbs_deb_scan("SCAN_RESP: BSSID %s\n",
+-			     print_mac(mac, new.bssid));
++		lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid));
+ 
+ 		/* Copy the locally created newbssentry to the scan table */
+ 		memcpy(found, &new, offsetof(struct bss_descriptor, list));
+diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
+index 319f70d..9e07b04 100644
+--- a/drivers/net/wireless/libertas/scan.h
++++ b/drivers/net/wireless/libertas/scan.h
+@@ -7,198 +7,22 @@
+ #ifndef _LBS_SCAN_H
+ #define _LBS_SCAN_H
+ 
+-#include <net/ieee80211.h>
+-#include "hostcmd.h"
+-
+ /**
+  *  @brief Maximum number of channels that can be sent in a setuserscan ioctl
+- *
+- *  @sa lbs_ioctl_user_scan_cfg
+  */
+ #define LBS_IOCTL_USER_SCAN_CHAN_MAX  50
+ 
+-//! Infrastructure BSS scan type in lbs_scan_cmd_config
+-#define LBS_SCAN_BSS_TYPE_BSS         1
+-
+-//! Adhoc BSS scan type in lbs_scan_cmd_config
+-#define LBS_SCAN_BSS_TYPE_IBSS        2
+-
+-//! Adhoc or Infrastructure BSS scan type in lbs_scan_cmd_config, no filter
+-#define LBS_SCAN_BSS_TYPE_ANY         3
+-
+-/**
+- * @brief Structure used internally in the wlan driver to configure a scan.
+- *
+- * Sent to the command processing module to configure the firmware
+- *   scan command prepared by lbs_cmd_80211_scan.
+- *
+- * @sa lbs_scan_networks
+- *
+- */
+-struct lbs_scan_cmd_config {
+-    /**
+-     *  @brief BSS type to be sent in the firmware command
+-     *
+-     *  Field can be used to restrict the types of networks returned in the
+-     *    scan.  valid settings are:
+-     *
+-     *   - LBS_SCAN_BSS_TYPE_BSS  (infrastructure)
+-     *   - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
+-     *   - LBS_SCAN_BSS_TYPE_ANY  (unrestricted, adhoc and infrastructure)
+-     */
+-	u8 bsstype;
+-
+-    /**
+-     *  @brief Specific BSSID used to filter scan results in the firmware
+-     */
+-	u8 bssid[ETH_ALEN];
+-
+-    /**
+-     *  @brief length of TLVs sent in command starting at tlvBuffer
+-     */
+-	int tlvbufferlen;
+-
+-    /**
+-     *  @brief SSID TLV(s) and ChanList TLVs to be sent in the firmware command
+-     *
+-     *  @sa TLV_TYPE_CHANLIST, mrvlietypes_chanlistparamset_t
+-     *  @sa TLV_TYPE_SSID, mrvlietypes_ssidparamset_t
+-     */
+-	u8 tlvbuffer[1];	//!< SSID TLV(s) and ChanList TLVs are stored here
+-};
+-
+-/**
+- *  @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg
+- *
+- *  Multiple instances of this structure are included in the IOCTL command
+- *   to configure a instance of a scan on the specific channel.
+- */
+-struct lbs_ioctl_user_scan_chan {
+-	u8 channumber;		//!< channel Number to scan
+-	u8 radiotype;		//!< Radio type: 'B/G' band = 0, 'A' band = 1
+-	u8 scantype;		//!< Scan type: Active = 0, Passive = 1
+-	u16 scantime;		//!< Scan duration in milliseconds; if 0 default used
+-};
+-
+-/**
+- *  @brief IOCTL input structure to configure an immediate scan cmd to firmware
+- *
+- *  Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl.  Specifies
+- *   a number of parameters to be used in general for the scan as well
+- *   as a channel list (lbs_ioctl_user_scan_chan) for each scan period
+- *   desired.
+- *
+- *  @sa lbs_set_user_scan_ioctl
+- */
+-struct lbs_ioctl_user_scan_cfg {
+-    /**
+-     *  @brief BSS type to be sent in the firmware command
+-     *
+-     *  Field can be used to restrict the types of networks returned in the
+-     *    scan.  valid settings are:
+-     *
+-     *   - LBS_SCAN_BSS_TYPE_BSS  (infrastructure)
+-     *   - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
+-     *   - LBS_SCAN_BSS_TYPE_ANY  (unrestricted, adhoc and infrastructure)
+-     */
+-	u8 bsstype;
+-
+-	/**
+-	 *  @brief BSSID filter sent in the firmware command to limit the results
+-	 */
+-	u8 bssid[ETH_ALEN];
+-
+-	/* Clear existing scan results matching this BSSID */
+-	u8 clear_bssid;
+-
+-	/**
+-	 *  @brief SSID filter sent in the firmware command to limit the results
+-	 */
+-	char ssid[IW_ESSID_MAX_SIZE];
+-	u8 ssid_len;
+-
+-	/* Clear existing scan results matching this SSID */
+-	u8 clear_ssid;
+-};
+-
+-/**
+- *  @brief Structure used to store information for each beacon/probe response
+- */
+-struct bss_descriptor {
+-	u8 bssid[ETH_ALEN];
+-
+-	u8 ssid[IW_ESSID_MAX_SIZE + 1];
+-	u8 ssid_len;
+-
+-	u16 capability;
+-
+-	/* receive signal strength in dBm */
+-	long rssi;
+-
+-	u32 channel;
+-
+-	u16 beaconperiod;
+-
+-	u32 atimwindow;
+-
+-	/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
+-	u8 mode;
+-
+-	/* zero-terminated array of supported data rates */
+-	u8 rates[MAX_RATES + 1];
+-
+-	unsigned long last_scanned;
+-
+-	union ieeetypes_phyparamset phyparamset;
+-	union IEEEtypes_ssparamset ssparamset;
+-
+-	struct ieeetypes_countryinfofullset countryinfo;
+-
+-	u8 wpa_ie[MAX_WPA_IE_LEN];
+-	size_t wpa_ie_len;
+-	u8 rsn_ie[MAX_WPA_IE_LEN];
+-	size_t rsn_ie_len;
+-
+-	u8 mesh;
+-
+-	struct list_head list;
+-};
+-
+ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
+ 
+-struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
+-		u8 *ssid, u8 ssid_len, u8 *bssid, u8 mode,
+-		int channel);
+-
+-struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
+-	u8 *bssid, u8 mode);
+-
+-int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid,
+-			u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
+-
+ int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
+-				u8 ssid_len, u8 clear_ssid);
++				u8 ssid_len);
+ 
+-int lbs_cmd_80211_scan(struct lbs_private *priv,
+-				struct cmd_ds_command *cmd,
+-				void *pdata_buf);
+-
+-int lbs_ret_80211_scan(struct lbs_private *priv,
+-				struct cmd_ds_command *resp);
+-
+-int lbs_scan_networks(struct lbs_private *priv,
+-	const struct lbs_ioctl_user_scan_cfg *puserscanin,
+-                int full_scan);
+-
+-struct ifreq;
+-
+-struct iw_point;
+-struct iw_param;
+-struct iw_request_info;
+ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+ 			 struct iw_point *dwrq, char *extra);
+ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
+-			 struct iw_param *vwrq, char *extra);
++			 union iwreq_data *wrqu, char *extra);
++
++int lbs_scan_networks(struct lbs_private *priv, int full_scan);
+ 
+ void lbs_scan_worker(struct work_struct *work);
+ 
+diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
+index 00d95f7..a4972fe 100644
+--- a/drivers/net/wireless/libertas/tx.c
++++ b/drivers/net/wireless/libertas/tx.c
+@@ -151,7 +151,7 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 	dev->trans_start = jiffies;
+ 
+-	if (priv->monitormode != LBS_MONITOR_OFF) {
++	if (priv->monitormode) {
+ 		/* Keep the skb to echo it back once Tx feedback is
+ 		   received from FW */
+ 		skb_orphan(skb);
+@@ -179,32 +179,17 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+  *
+  *  @returns void
+  */
+-void lbs_send_tx_feedback(struct lbs_private *priv)
++void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
+ {
+ 	struct tx_radiotap_hdr *radiotap_hdr;
+-	u32 status = priv->eventcause;
+-	int txfail;
+-	int try_count;
+ 
+-	if (priv->monitormode == LBS_MONITOR_OFF ||
+-	    priv->currenttxskb == NULL)
++	if (!priv->monitormode || priv->currenttxskb == NULL)
+ 		return;
+ 
+ 	radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
+ 
+-	txfail = (status >> 24);
+-
+-#if 0
+-	/* The version of roofnet that we've tested does not use this yet
+-	 * But it may be used in the future.
+-	 */
+-	if (txfail)
+-		radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL;
+-#endif
+-	try_count = (status >> 16) & 0xff;
+-	radiotap_hdr->data_retries = (try_count) ?
+-	    (1 + priv->txretrycount - try_count) : 0;
+-
++	radiotap_hdr->data_retries = try_count ?
++		(1 + priv->txretrycount - try_count) : 0;
+ 
+ 	priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
+ 						      priv->rtap_net_dev);
+diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
+index f0d5795..4031be4 100644
+--- a/drivers/net/wireless/libertas/types.h
++++ b/drivers/net/wireless/libertas/types.h
+@@ -239,4 +239,17 @@ struct mrvlietypes_ledgpio {
+ 	struct led_pin ledpin[1];
+ } __attribute__ ((packed));
+ 
++struct led_bhv {
++	uint8_t	firmwarestate;
++	uint8_t	led;
++	uint8_t	ledstate;
++	uint8_t	ledarg;
++} __attribute__ ((packed));
++
++
++struct mrvlietypes_ledbhv {
++	struct mrvlietypesheader header;
++	struct led_bhv ledbhv[1];
++} __attribute__ ((packed));
++
+ #endif
+diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
+index e8bfc26..0973d01 100644
+--- a/drivers/net/wireless/libertas/wext.c
++++ b/drivers/net/wireless/libertas/wext.c
+@@ -16,8 +16,8 @@
+ #include "decl.h"
+ #include "defs.h"
+ #include "dev.h"
+-#include "join.h"
+ #include "wext.h"
++#include "scan.h"
+ #include "assoc.h"
+ #include "cmd.h"
+ 
+@@ -579,6 +579,9 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
+ 	       range->num_bitrates);
+ 
+ 	range->num_frequency = 0;
++
++	range->scan_capa = IW_SCAN_CAPA_ESSID;
++
+ 	if (priv->enable11d &&
+ 	    (priv->connect_status == LBS_CONNECTED ||
+ 	    priv->mesh_connect_status == LBS_CONNECTED)) {
+@@ -602,7 +605,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
+ 			lbs_deb_wext("chan_no %d\n", chan_no);
+ 			range->freq[range->num_frequency].i = (long)chan_no;
+ 			range->freq[range->num_frequency].m =
+-			    (long)lbs_chan_2_freq(chan_no, band) * 100000;
++			    (long)lbs_chan_2_freq(chan_no) * 100000;
+ 			range->freq[range->num_frequency].e = 1;
+ 			range->num_frequency++;
+ 		}
+@@ -653,13 +656,10 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
+ 	range->num_encoding_sizes = 2;
+ 	range->max_encoding_tokens = 4;
+ 
+-	range->min_pmp = 1000000;
+-	range->max_pmp = 120000000;
+-	range->min_pmt = 1000;
+-	range->max_pmt = 1000000;
+-	range->pmp_flags = IW_POWER_PERIOD;
+-	range->pmt_flags = IW_POWER_TIMEOUT;
+-	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
++	/*
++	 * Right now we support only "iwconfig ethX power on|off"
++	 */
++	range->pm_capa = IW_POWER_ON;
+ 
+ 	/*
+ 	 * Minimum version we recommend
+@@ -781,21 +781,14 @@ static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
+ 			  struct iw_param *vwrq, char *extra)
+ {
+ 	struct lbs_private *priv = dev->priv;
+-	int mode;
+ 
+ 	lbs_deb_enter(LBS_DEB_WEXT);
+ 
+-	mode = priv->psmode;
+-
+-	if ((vwrq->disabled = (mode == LBS802_11POWERMODECAM))
+-	    || priv->connect_status == LBS_DISCONNECTED)
+-	{
+-		goto out;
+-	}
+-
+ 	vwrq->value = 0;
++	vwrq->flags = 0;
++	vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM
++		|| priv->connect_status == LBS_DISCONNECTED;
+ 
+-out:
+ 	lbs_deb_leave(LBS_DEB_WEXT);
+ 	return 0;
+ }
+@@ -817,6 +810,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
+ 	int stats_valid = 0;
+ 	u8 rssi;
+ 	u32 tx_retries;
++	struct cmd_ds_802_11_get_log log;
+ 
+ 	lbs_deb_enter(LBS_DEB_WEXT);
+ 
+@@ -860,7 +854,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
+ 	/* Quality by TX errors */
+ 	priv->wstats.discard.retries = priv->stats.tx_errors;
+ 
+-	tx_retries = le32_to_cpu(priv->logmsg.retry);
++	memset(&log, 0, sizeof(log));
++	log.hdr.size = cpu_to_le16(sizeof(log));
++	lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
++
++	tx_retries = le32_to_cpu(log.retry);
+ 
+ 	if (tx_retries > 75)
+ 		tx_qual = (90 - tx_retries) * POOR / 15;
+@@ -876,10 +874,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
+ 		    (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
+ 	quality = min(quality, tx_qual);
+ 
+-	priv->wstats.discard.code = le32_to_cpu(priv->logmsg.wepundecryptable);
+-	priv->wstats.discard.fragment = le32_to_cpu(priv->logmsg.rxfrag);
++	priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable);
+ 	priv->wstats.discard.retries = tx_retries;
+-	priv->wstats.discard.misc = le32_to_cpu(priv->logmsg.ackfailure);
++	priv->wstats.discard.misc = le32_to_cpu(log.ackfailure);
+ 
+ 	/* Calculate quality */
+ 	priv->wstats.qual.qual = min_t(u8, quality, 100);
+@@ -889,8 +886,6 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
+ 	/* update stats asynchronously for future calls */
+ 	lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+ 					0, 0, NULL);
+-	lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
+-					0, 0, NULL);
+ out:
+ 	if (!stats_valid) {
+ 		priv->wstats.miss.beacon = 0;
+@@ -2065,23 +2060,6 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
+ 	return ret;
+ }
+ 
+-void lbs_get_fwversion(struct lbs_private *priv, char *fwversion, int maxlen)
+-{
+-	char fwver[32];
+-
+-	mutex_lock(&priv->lock);
+-
+-	sprintf(fwver, "%u.%u.%u.p%u",
+-		priv->fwrelease >> 24 & 0xff,
+-		priv->fwrelease >> 16 & 0xff,
+-		priv->fwrelease >>  8 & 0xff,
+-		priv->fwrelease       & 0xff);
+-
+-	mutex_unlock(&priv->lock);
+-	snprintf(fwversion, maxlen, fwver);
+-}
+-
+-
+ /*
+  * iwconfig settable callbacks
+  */
+diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
+index a563d9a..4c08db4 100644
+--- a/drivers/net/wireless/libertas/wext.h
++++ b/drivers/net/wireless/libertas/wext.h
+@@ -4,19 +4,6 @@
+ #ifndef	_LBS_WEXT_H_
+ #define	_LBS_WEXT_H_
+ 
+-/** lbs_ioctl_regrdwr */
+-struct lbs_ioctl_regrdwr {
+-	/** Which register to access */
+-	u16 whichreg;
+-	/** Read or Write */
+-	u16 action;
+-	u32 offset;
+-	u16 NOB;
+-	u32 value;
+-};
+-
+-#define LBS_MONITOR_OFF			0
+-
+ extern struct iw_handler_def lbs_handler_def;
+ extern struct iw_handler_def mesh_handler_def;
+ 
+diff --git a/drivers/net/wireless/net2280.h b/drivers/net/wireless/net2280.h
+deleted file mode 100644
+index 120eb83..0000000
+--- a/drivers/net/wireless/net2280.h
++++ /dev/null
+@@ -1,452 +0,0 @@
+-#ifndef NET2280_H
+-#define NET2280_H
+-/*
+- * NetChip 2280 high/full speed USB device controller.
+- * Unlike many such controllers, this one talks PCI.
+- */
+-
+-/*
+- * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+- * Copyright (C) 2003 David Brownell
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+- */
+-
+-/*-------------------------------------------------------------------------*/
+-
+-/* NET2280 MEMORY MAPPED REGISTERS
+- *
+- * The register layout came from the chip documentation, and the bit
+- * number definitions were extracted from chip specification.
+- *
+- * Use the shift operator ('<<') to build bit masks, with readl/writel
+- * to access the registers through PCI.
+- */
+-
+-/* main registers, BAR0 + 0x0000 */
+-struct net2280_regs {
+-	// offset 0x0000
+-	__le32                  devinit;
+-#define     LOCAL_CLOCK_FREQUENCY                               8
+-#define     FORCE_PCI_RESET                                     7
+-#define     PCI_ID                                              6
+-#define     PCI_ENABLE                                          5
+-#define     FIFO_SOFT_RESET                                     4
+-#define     CFG_SOFT_RESET                                      3
+-#define     PCI_SOFT_RESET                                      2
+-#define     USB_SOFT_RESET                                      1
+-#define     M8051_RESET                                         0
+-	__le32                  eectl;
+-#define     EEPROM_ADDRESS_WIDTH                                23
+-#define     EEPROM_CHIP_SELECT_ACTIVE                           22
+-#define     EEPROM_PRESENT                                      21
+-#define     EEPROM_VALID                                        20
+-#define     EEPROM_BUSY                                         19
+-#define     EEPROM_CHIP_SELECT_ENABLE                           18
+-#define     EEPROM_BYTE_READ_START                              17
+-#define     EEPROM_BYTE_WRITE_START                             16
+-#define     EEPROM_READ_DATA                                    8
+-#define     EEPROM_WRITE_DATA                                   0
+-	__le32                  eeclkfreq;
+-	u32                     _unused0;
+-	// offset 0x0010
+-
+-	__le32                  pciirqenb0;	/* interrupt PCI master ... */
+-#define     SETUP_PACKET_INTERRUPT_ENABLE                       7
+-#define     ENDPOINT_F_INTERRUPT_ENABLE                         6
+-#define     ENDPOINT_E_INTERRUPT_ENABLE                         5
+-#define     ENDPOINT_D_INTERRUPT_ENABLE                         4
+-#define     ENDPOINT_C_INTERRUPT_ENABLE                         3
+-#define     ENDPOINT_B_INTERRUPT_ENABLE                         2
+-#define     ENDPOINT_A_INTERRUPT_ENABLE                         1
+-#define     ENDPOINT_0_INTERRUPT_ENABLE                         0
+-	__le32                  pciirqenb1;
+-#define     PCI_INTERRUPT_ENABLE                                31
+-#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
+-#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
+-#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
+-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
+-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
+-#define     PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE          18
+-#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
+-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
+-#define     GPIO_INTERRUPT_ENABLE                               13
+-#define     DMA_D_INTERRUPT_ENABLE                              12
+-#define     DMA_C_INTERRUPT_ENABLE                              11
+-#define     DMA_B_INTERRUPT_ENABLE                              10
+-#define     DMA_A_INTERRUPT_ENABLE                              9
+-#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
+-#define     VBUS_INTERRUPT_ENABLE                               7
+-#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
+-#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
+-#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
+-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
+-#define     RESUME_INTERRUPT_ENABLE                             1
+-#define     SOF_INTERRUPT_ENABLE                                0
+-	__le32                  cpu_irqenb0;	/* ... or onboard 8051 */
+-#define     SETUP_PACKET_INTERRUPT_ENABLE                       7
+-#define     ENDPOINT_F_INTERRUPT_ENABLE                         6
+-#define     ENDPOINT_E_INTERRUPT_ENABLE                         5
+-#define     ENDPOINT_D_INTERRUPT_ENABLE                         4
+-#define     ENDPOINT_C_INTERRUPT_ENABLE                         3
+-#define     ENDPOINT_B_INTERRUPT_ENABLE                         2
+-#define     ENDPOINT_A_INTERRUPT_ENABLE                         1
+-#define     ENDPOINT_0_INTERRUPT_ENABLE                         0
+-	__le32                  cpu_irqenb1;
+-#define     CPU_INTERRUPT_ENABLE                                31
+-#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
+-#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
+-#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
+-#define     PCI_INTA_INTERRUPT_ENABLE                           24
+-#define     PCI_PME_INTERRUPT_ENABLE                            23
+-#define     PCI_SERR_INTERRUPT_ENABLE                           22
+-#define     PCI_PERR_INTERRUPT_ENABLE                           21
+-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
+-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
+-#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
+-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
+-#define     GPIO_INTERRUPT_ENABLE                               13
+-#define     DMA_D_INTERRUPT_ENABLE                              12
+-#define     DMA_C_INTERRUPT_ENABLE                              11
+-#define     DMA_B_INTERRUPT_ENABLE                              10
+-#define     DMA_A_INTERRUPT_ENABLE                              9
+-#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
+-#define     VBUS_INTERRUPT_ENABLE                               7
+-#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
+-#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
+-#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
+-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
+-#define     RESUME_INTERRUPT_ENABLE                             1
+-#define     SOF_INTERRUPT_ENABLE                                0
+-
+-	// offset 0x0020
+-	u32                     _unused1;
+-	__le32                  usbirqenb1;
+-#define     USB_INTERRUPT_ENABLE                                31
+-#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
+-#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
+-#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
+-#define     PCI_INTA_INTERRUPT_ENABLE                           24
+-#define     PCI_PME_INTERRUPT_ENABLE                            23
+-#define     PCI_SERR_INTERRUPT_ENABLE                           22
+-#define     PCI_PERR_INTERRUPT_ENABLE                           21
+-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
+-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
+-#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
+-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
+-#define     GPIO_INTERRUPT_ENABLE                               13
+-#define     DMA_D_INTERRUPT_ENABLE                              12
+-#define     DMA_C_INTERRUPT_ENABLE                              11
+-#define     DMA_B_INTERRUPT_ENABLE                              10
+-#define     DMA_A_INTERRUPT_ENABLE                              9
+-#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
+-#define     VBUS_INTERRUPT_ENABLE                               7
+-#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
+-#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
+-#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
+-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
+-#define     RESUME_INTERRUPT_ENABLE                             1
+-#define     SOF_INTERRUPT_ENABLE                                0
+-	__le32                  irqstat0;
+-#define     INTA_ASSERTED                                       12
+-#define     SETUP_PACKET_INTERRUPT                              7
+-#define     ENDPOINT_F_INTERRUPT                                6
+-#define     ENDPOINT_E_INTERRUPT                                5
+-#define     ENDPOINT_D_INTERRUPT                                4
+-#define     ENDPOINT_C_INTERRUPT                                3
+-#define     ENDPOINT_B_INTERRUPT                                2
+-#define     ENDPOINT_A_INTERRUPT                                1
+-#define     ENDPOINT_0_INTERRUPT                                0
+-	__le32                  irqstat1;
+-#define     POWER_STATE_CHANGE_INTERRUPT                        27
+-#define     PCI_ARBITER_TIMEOUT_INTERRUPT                       26
+-#define     PCI_PARITY_ERROR_INTERRUPT                          25
+-#define     PCI_INTA_INTERRUPT                                  24
+-#define     PCI_PME_INTERRUPT                                   23
+-#define     PCI_SERR_INTERRUPT                                  22
+-#define     PCI_PERR_INTERRUPT                                  21
+-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT                 20
+-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT                 19
+-#define     PCI_RETRY_ABORT_INTERRUPT                           17
+-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT                     16
+-#define     GPIO_INTERRUPT                                      13
+-#define     DMA_D_INTERRUPT                                     12
+-#define     DMA_C_INTERRUPT                                     11
+-#define     DMA_B_INTERRUPT                                     10
+-#define     DMA_A_INTERRUPT                                     9
+-#define     EEPROM_DONE_INTERRUPT                               8
+-#define     VBUS_INTERRUPT                                      7
+-#define     CONTROL_STATUS_INTERRUPT                            6
+-#define     ROOT_PORT_RESET_INTERRUPT                           4
+-#define     SUSPEND_REQUEST_INTERRUPT                           3
+-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT                    2
+-#define     RESUME_INTERRUPT                                    1
+-#define     SOF_INTERRUPT                                       0
+-	// offset 0x0030
+-	__le32                  idxaddr;
+-	__le32                  idxdata;
+-	__le32                  fifoctl;
+-#define     PCI_BASE2_RANGE                                     16
+-#define     IGNORE_FIFO_AVAILABILITY                            3
+-#define     PCI_BASE2_SELECT                                    2
+-#define     FIFO_CONFIGURATION_SELECT                           0
+-	u32                     _unused2;
+-	// offset 0x0040
+-	__le32                  memaddr;
+-#define     START                                               28
+-#define     DIRECTION                                           27
+-#define     FIFO_DIAGNOSTIC_SELECT                              24
+-#define     MEMORY_ADDRESS                                      0
+-	__le32                  memdata0;
+-	__le32                  memdata1;
+-	u32                     _unused3;
+-	// offset 0x0050
+-	__le32                  gpioctl;
+-#define     GPIO3_LED_SELECT                                    12
+-#define     GPIO3_INTERRUPT_ENABLE                              11
+-#define     GPIO2_INTERRUPT_ENABLE                              10
+-#define     GPIO1_INTERRUPT_ENABLE                              9
+-#define     GPIO0_INTERRUPT_ENABLE                              8
+-#define     GPIO3_OUTPUT_ENABLE                                 7
+-#define     GPIO2_OUTPUT_ENABLE                                 6
+-#define     GPIO1_OUTPUT_ENABLE                                 5
+-#define     GPIO0_OUTPUT_ENABLE                                 4
+-#define     GPIO3_DATA                                          3
+-#define     GPIO2_DATA                                          2
+-#define     GPIO1_DATA                                          1
+-#define     GPIO0_DATA                                          0
+-	__le32                  gpiostat;
+-#define     GPIO3_INTERRUPT                                     3
+-#define     GPIO2_INTERRUPT                                     2
+-#define     GPIO1_INTERRUPT                                     1
+-#define     GPIO0_INTERRUPT                                     0
+-} __attribute__ ((packed));
+-
+-/* usb control, BAR0 + 0x0080 */
+-struct net2280_usb_regs {
+-	// offset 0x0080
+-	__le32                  stdrsp;
+-#define     STALL_UNSUPPORTED_REQUESTS                          31
+-#define     SET_TEST_MODE                                       16
+-#define     GET_OTHER_SPEED_CONFIGURATION                       15
+-#define     GET_DEVICE_QUALIFIER                                14
+-#define     SET_ADDRESS                                         13
+-#define     ENDPOINT_SET_CLEAR_HALT                             12
+-#define     DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP               11
+-#define     GET_STRING_DESCRIPTOR_2                             10
+-#define     GET_STRING_DESCRIPTOR_1                             9
+-#define     GET_STRING_DESCRIPTOR_0                             8
+-#define     GET_SET_INTERFACE                                   6
+-#define     GET_SET_CONFIGURATION                               5
+-#define     GET_CONFIGURATION_DESCRIPTOR                        4
+-#define     GET_DEVICE_DESCRIPTOR                               3
+-#define     GET_ENDPOINT_STATUS                                 2
+-#define     GET_INTERFACE_STATUS                                1
+-#define     GET_DEVICE_STATUS                                   0
+-	__le32                  prodvendid;
+-#define     PRODUCT_ID                                          16
+-#define     VENDOR_ID                                           0
+-	__le32                  relnum;
+-	__le32                  usbctl;
+-#define     SERIAL_NUMBER_INDEX                                 16
+-#define     PRODUCT_ID_STRING_ENABLE                            13
+-#define     VENDOR_ID_STRING_ENABLE                             12
+-#define     USB_ROOT_PORT_WAKEUP_ENABLE                         11
+-#define     VBUS_PIN                                            10
+-#define     TIMED_DISCONNECT                                    9
+-#define     SUSPEND_IMMEDIATELY                                 7
+-#define     SELF_POWERED_USB_DEVICE                             6
+-#define     REMOTE_WAKEUP_SUPPORT                               5
+-#define     PME_POLARITY                                        4
+-#define     USB_DETECT_ENABLE                                   3
+-#define     PME_WAKEUP_ENABLE                                   2
+-#define     DEVICE_REMOTE_WAKEUP_ENABLE                         1
+-#define     SELF_POWERED_STATUS                                 0
+-	// offset 0x0090
+-	__le32                  usbstat;
+-#define     HIGH_SPEED                                          7
+-#define     FULL_SPEED                                          6
+-#define     GENERATE_RESUME                                     5
+-#define     GENERATE_DEVICE_REMOTE_WAKEUP                       4
+-	__le32                  xcvrdiag;
+-#define     FORCE_HIGH_SPEED_MODE                               31
+-#define     FORCE_FULL_SPEED_MODE                               30
+-#define     USB_TEST_MODE                                       24
+-#define     LINE_STATE                                          16
+-#define     TRANSCEIVER_OPERATION_MODE                          2
+-#define     TRANSCEIVER_SELECT                                  1
+-#define     TERMINATION_SELECT                                  0
+-	__le32                  setup0123;
+-	__le32                  setup4567;
+-	// offset 0x0090
+-	u32                     _unused0;
+-	__le32                  ouraddr;
+-#define     FORCE_IMMEDIATE                                     7
+-#define     OUR_USB_ADDRESS                                     0
+-	__le32                  ourconfig;
+-} __attribute__ ((packed));
+-
+-/* pci control, BAR0 + 0x0100 */
+-struct net2280_pci_regs {
+-	// offset 0x0100
+-	__le32                  pcimstctl;
+-#define     PCI_ARBITER_PARK_SELECT                             13
+-#define     PCI_MULTI LEVEL_ARBITER                             12
+-#define     PCI_RETRY_ABORT_ENABLE                              11
+-#define     DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE              10
+-#define     DMA_READ_MULTIPLE_ENABLE                            9
+-#define     DMA_READ_LINE_ENABLE                                8
+-#define     PCI_MASTER_COMMAND_SELECT                           6
+-#define         MEM_READ_OR_WRITE                                   0
+-#define         IO_READ_OR_WRITE                                    1
+-#define         CFG_READ_OR_WRITE                                   2
+-#define     PCI_MASTER_START                                    5
+-#define     PCI_MASTER_READ_WRITE                               4
+-#define         PCI_MASTER_WRITE                                    0
+-#define         PCI_MASTER_READ                                     1
+-#define     PCI_MASTER_BYTE_WRITE_ENABLES                       0
+-	__le32                  pcimstaddr;
+-	__le32                  pcimstdata;
+-	__le32                  pcimststat;
+-#define     PCI_ARBITER_CLEAR                                   2
+-#define     PCI_EXTERNAL_ARBITER                                1
+-#define     PCI_HOST_MODE                                       0
+-} __attribute__ ((packed));
+-
+-/* dma control, BAR0 + 0x0180 ... array of four structs like this,
+- * for channels 0..3.  see also struct net2280_dma:  descriptor
+- * that can be loaded into some of these registers.
+- */
+-struct net2280_dma_regs {	/* [11.7] */
+-	// offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
+-	__le32                  dmactl;
+-#define     DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE            25
+-#define     DMA_CLEAR_COUNT_ENABLE                              21
+-#define     DESCRIPTOR_POLLING_RATE                             19
+-#define         POLL_CONTINUOUS                                     0
+-#define         POLL_1_USEC                                         1
+-#define         POLL_100_USEC                                       2
+-#define         POLL_1_MSEC                                         3
+-#define     DMA_VALID_BIT_POLLING_ENABLE                        18
+-#define     DMA_VALID_BIT_ENABLE                                17
+-#define     DMA_SCATTER_GATHER_ENABLE                           16
+-#define     DMA_OUT_AUTO_START_ENABLE                           4
+-#define     DMA_PREEMPT_ENABLE                                  3
+-#define     DMA_FIFO_VALIDATE                                   2
+-#define     DMA_ENABLE                                          1
+-#define     DMA_ADDRESS_HOLD                                    0
+-	__le32                  dmastat;
+-#define     DMA_SCATTER_GATHER_DONE_INTERRUPT                   25
+-#define     DMA_TRANSACTION_DONE_INTERRUPT                      24
+-#define     DMA_ABORT                                           1
+-#define     DMA_START                                           0
+-	u32                     _unused0[2];
+-	// offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
+-	__le32                  dmacount;
+-#define     VALID_BIT                                           31
+-#define     DMA_DIRECTION                                       30
+-#define     DMA_DONE_INTERRUPT_ENABLE                           29
+-#define     END_OF_CHAIN                                        28
+-#define         DMA_BYTE_COUNT_MASK                                 ((1<<24)-1)
+-#define     DMA_BYTE_COUNT                                      0
+-	__le32                  dmaaddr;
+-	__le32                  dmadesc;
+-	u32                     _unused1;
+-} __attribute__ ((packed));
+-
+-/* dedicated endpoint registers, BAR0 + 0x0200 */
+-
+-struct net2280_dep_regs {	/* [11.8] */
+-	// offset 0x0200, 0x0210, 0x220, 0x230, 0x240
+-	__le32                  dep_cfg;
+-	// offset 0x0204, 0x0214, 0x224, 0x234, 0x244
+-	__le32                  dep_rsp;
+-	u32                     _unused[2];
+-} __attribute__ ((packed));
+-
+-/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
+- * like this, for ep0 then the configurable endpoints A..F
+- * ep0 reserved for control; E and F have only 64 bytes of fifo
+- */
+-struct net2280_ep_regs {	/* [11.9] */
+-	// offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
+-	__le32                  ep_cfg;
+-#define     ENDPOINT_BYTE_COUNT                                 16
+-#define     ENDPOINT_ENABLE                                     10
+-#define     ENDPOINT_TYPE                                       8
+-#define     ENDPOINT_DIRECTION                                  7
+-#define     ENDPOINT_NUMBER                                     0
+-	__le32                  ep_rsp;
+-#define     SET_NAK_OUT_PACKETS                                 15
+-#define     SET_EP_HIDE_STATUS_PHASE                            14
+-#define     SET_EP_FORCE_CRC_ERROR                              13
+-#define     SET_INTERRUPT_MODE                                  12
+-#define     SET_CONTROL_STATUS_PHASE_HANDSHAKE                  11
+-#define     SET_NAK_OUT_PACKETS_MODE                            10
+-#define     SET_ENDPOINT_TOGGLE                                 9
+-#define     SET_ENDPOINT_HALT                                   8
+-#define     CLEAR_NAK_OUT_PACKETS                               7
+-#define     CLEAR_EP_HIDE_STATUS_PHASE                          6
+-#define     CLEAR_EP_FORCE_CRC_ERROR                            5
+-#define     CLEAR_INTERRUPT_MODE                                4
+-#define     CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE                3
+-#define     CLEAR_NAK_OUT_PACKETS_MODE                          2
+-#define     CLEAR_ENDPOINT_TOGGLE                               1
+-#define     CLEAR_ENDPOINT_HALT                                 0
+-	__le32                  ep_irqenb;
+-#define     SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE              6
+-#define     SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE           5
+-#define     DATA_PACKET_RECEIVED_INTERRUPT_ENABLE               3
+-#define     DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE            2
+-#define     DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE                1
+-#define     DATA_IN_TOKEN_INTERRUPT_ENABLE                      0
+-	__le32                  ep_stat;
+-#define     FIFO_VALID_COUNT                                    24
+-#define     HIGH_BANDWIDTH_OUT_TRANSACTION_PID                  22
+-#define     TIMEOUT                                             21
+-#define     USB_STALL_SENT                                      20
+-#define     USB_IN_NAK_SENT                                     19
+-#define     USB_IN_ACK_RCVD                                     18
+-#define     USB_OUT_PING_NAK_SENT                               17
+-#define     USB_OUT_ACK_SENT                                    16
+-#define     FIFO_OVERFLOW                                       13
+-#define     FIFO_UNDERFLOW                                      12
+-#define     FIFO_FULL                                           11
+-#define     FIFO_EMPTY                                          10
+-#define     FIFO_FLUSH                                          9
+-#define     SHORT_PACKET_OUT_DONE_INTERRUPT                     6
+-#define     SHORT_PACKET_TRANSFERRED_INTERRUPT                  5
+-#define     NAK_OUT_PACKETS                                     4
+-#define     DATA_PACKET_RECEIVED_INTERRUPT                      3
+-#define     DATA_PACKET_TRANSMITTED_INTERRUPT                   2
+-#define     DATA_OUT_PING_TOKEN_INTERRUPT                       1
+-#define     DATA_IN_TOKEN_INTERRUPT                             0
+-	// offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
+-	__le32                  ep_avail;
+-	__le32                  ep_data;
+-	u32                     _unused0[2];
+-} __attribute__ ((packed));
+-
+-struct net2280_reg_write {
+-	__le16 port;
+-	__le32 addr;
+-	__le32 val;
+-} __attribute__ ((packed));
+-
+-struct net2280_reg_read {
+-	__le16 port;
+-	__le32 addr;
+-} __attribute__ ((packed));
+-#endif /* NET2280_H */
+diff --git a/drivers/net/wireless/p54.h b/drivers/net/wireless/p54.h
+deleted file mode 100644
+index 744c866..0000000
+--- a/drivers/net/wireless/p54.h
++++ /dev/null
+@@ -1,81 +0,0 @@
+-#ifndef PRISM54_H
+-#define PRISM54_H
+-
+-/*
+- * Shared defines for all mac80211 Prism54 code
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-enum control_frame_types {
+-	P54_CONTROL_TYPE_FILTER_SET = 0,
+-	P54_CONTROL_TYPE_CHANNEL_CHANGE,
+-	P54_CONTROL_TYPE_FREQDONE,
+-	P54_CONTROL_TYPE_DCFINIT,
+-	P54_CONTROL_TYPE_FREEQUEUE = 7,
+-	P54_CONTROL_TYPE_TXDONE,
+-	P54_CONTROL_TYPE_PING,
+-	P54_CONTROL_TYPE_STAT_READBACK,
+-	P54_CONTROL_TYPE_BBP,
+-	P54_CONTROL_TYPE_EEPROM_READBACK,
+-	P54_CONTROL_TYPE_LED
+-};
+-
+-struct p54_control_hdr {
+-	__le16 magic1;
+-	__le16 len;
+-	__le32 req_id;
+-	__le16 type;	/* enum control_frame_types */
+-	u8 retry1;
+-	u8 retry2;
+-	u8 data[0];
+-} __attribute__ ((packed));
+-
+-#define EEPROM_READBACK_LEN (sizeof(struct p54_control_hdr) + 4 /* p54_eeprom_lm86 */)
+-#define MAX_RX_SIZE (IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct p54_control_hdr) + 20 /* length of struct p54_rx_hdr */ + 16 )
+-
+-#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
+-
+-struct p54_common {
+-	u32 rx_start;
+-	u32 rx_end;
+-	struct sk_buff_head tx_queue;
+-	void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data,
+-		   size_t len, int free_on_tx);
+-	int (*open)(struct ieee80211_hw *dev);
+-	void (*stop)(struct ieee80211_hw *dev);
+-	int mode;
+-	u8 mac_addr[ETH_ALEN];
+-	u8 bssid[ETH_ALEN];
+-	struct pda_iq_autocal_entry *iq_autocal;
+-	unsigned int iq_autocal_len;
+-	struct pda_channel_output_limit *output_limit;
+-	unsigned int output_limit_len;
+-	struct pda_pa_curve_data *curve_data;
+-	__le16 rxhw;
+-	u8 version;
+-	unsigned int tx_hdr_len;
+-	void *cached_vdcf;
+-	unsigned int fw_var;
+-	/* FIXME: this channels/modes/rates stuff sucks */
+-	struct ieee80211_channel channels[14];
+-	struct ieee80211_rate rates[12];
+-	struct ieee80211_hw_mode modes[2];
+-	struct ieee80211_tx_queue_stats tx_stats;
+-};
+-
+-int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
+-void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
+-int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
+-void p54_fill_eeprom_readback(struct p54_control_hdr *hdr);
+-struct ieee80211_hw *p54_init_common(size_t priv_data_len);
+-void p54_free_common(struct ieee80211_hw *dev);
+-
+-#endif /* PRISM54_H */
+diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig
+new file mode 100644
+index 0000000..d3469d0
+--- /dev/null
++++ b/drivers/net/wireless/p54/Kconfig
+@@ -0,0 +1,63 @@
++config P54_COMMON
++	tristate "Softmac Prism54 support"
++	depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL
++	---help---
++	  This is common code for isl38xx based cards.
++	  This module does nothing by itself - the USB/PCI frontends
++	  also need to be enabled in order to support any devices.
++
++	  These devices require softmac firmware which can be found at
++	  http://prism54.org/
++
++	  If you choose to build a module, it'll be called p54common.
++
++config P54_USB
++	tristate "Prism54 USB support"
++	depends on P54_COMMON && USB
++	select CRC32
++	---help---
++	  This driver is for USB isl38xx based wireless cards.
++	  These are USB based adapters found in devices such as:
++
++	  3COM 3CRWE254G72
++	  SMC 2862W-G
++	  Accton 802.11g WN4501 USB
++	  Siemens Gigaset USB
++	  Netgear WG121
++	  Netgear WG111
++	  Medion 40900, Roper Europe
++	  Shuttle PN15, Airvast WM168g, IOGear GWU513
++	  Linksys WUSB54G
++	  Linksys WUSB54G Portable
++	  DLink DWL-G120 Spinnaker
++	  DLink DWL-G122
++	  Belkin F5D7050 ver 1000
++	  Cohiba Proto board
++	  SMC 2862W-G version 2
++	  U.S. Robotics U5 802.11g Adapter
++	  FUJITSU E-5400 USB D1700
++	  Sagem XG703A
++	  DLink DWL-G120 Cohiba
++	  Spinnaker Proto board
++	  Linksys WUSB54AG
++	  Inventel UR054G
++	  Spinnaker DUT
++
++	  These devices require softmac firmware which can be found at
++	  http://prism54.org/
++
++	  If you choose to build a module, it'll be called p54usb.
++
++config P54_PCI
++	tristate "Prism54 PCI support"
++	depends on P54_COMMON && PCI
++	---help---
++	  This driver is for PCI isl38xx based wireless cards.
++	  This driver supports most devices that are supported by the
++	  fullmac prism54 driver plus many devices which are not
++	  supported by the fullmac driver/firmware.
++
++	  This driver requires softmac firmware which can be found at
++	  http://prism54.org/
++
++	  If you choose to build a module, it'll be called p54pci.
+diff --git a/drivers/net/wireless/p54/Makefile b/drivers/net/wireless/p54/Makefile
+new file mode 100644
+index 0000000..4fa9ce7
+--- /dev/null
++++ b/drivers/net/wireless/p54/Makefile
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_P54_COMMON)	+= p54common.o
++obj-$(CONFIG_P54_USB)		+= p54usb.o
++obj-$(CONFIG_P54_PCI)		+= p54pci.o
+diff --git a/drivers/net/wireless/p54/net2280.h b/drivers/net/wireless/p54/net2280.h
+new file mode 100644
+index 0000000..4915d9d
+--- /dev/null
++++ b/drivers/net/wireless/p54/net2280.h
+@@ -0,0 +1,452 @@
++#ifndef NET2280_H
++#define NET2280_H
++/*
++ * NetChip 2280 high/full speed USB device controller.
++ * Unlike many such controllers, this one talks PCI.
++ */
++
++/*
++ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
++ * Copyright (C) 2003 David Brownell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/*-------------------------------------------------------------------------*/
++
++/* NET2280 MEMORY MAPPED REGISTERS
++ *
++ * The register layout came from the chip documentation, and the bit
++ * number definitions were extracted from chip specification.
++ *
++ * Use the shift operator ('<<') to build bit masks, with readl/writel
++ * to access the registers through PCI.
++ */
++
++/* main registers, BAR0 + 0x0000 */
++struct net2280_regs {
++	/* offset 0x0000 */
++	__le32			devinit;
++#define LOCAL_CLOCK_FREQUENCY					8
++#define FORCE_PCI_RESET						7
++#define PCI_ID							6
++#define PCI_ENABLE						5
++#define FIFO_SOFT_RESET						4
++#define CFG_SOFT_RESET						3
++#define PCI_SOFT_RESET						2
++#define USB_SOFT_RESET						1
++#define M8051_RESET						0
++	__le32			eectl;
++#define EEPROM_ADDRESS_WIDTH					23
++#define EEPROM_CHIP_SELECT_ACTIVE				22
++#define EEPROM_PRESENT						21
++#define EEPROM_VALID						20
++#define EEPROM_BUSY						19
++#define EEPROM_CHIP_SELECT_ENABLE				18
++#define EEPROM_BYTE_READ_START					17
++#define EEPROM_BYTE_WRITE_START					16
++#define EEPROM_READ_DATA					8
++#define EEPROM_WRITE_DATA					0
++	__le32			eeclkfreq;
++	u32			_unused0;
++	/* offset 0x0010 */
++
++	__le32			pciirqenb0;	/* interrupt PCI master ... */
++#define SETUP_PACKET_INTERRUPT_ENABLE				7
++#define ENDPOINT_F_INTERRUPT_ENABLE				6
++#define ENDPOINT_E_INTERRUPT_ENABLE				5
++#define ENDPOINT_D_INTERRUPT_ENABLE				4
++#define ENDPOINT_C_INTERRUPT_ENABLE				3
++#define ENDPOINT_B_INTERRUPT_ENABLE				2
++#define ENDPOINT_A_INTERRUPT_ENABLE				1
++#define ENDPOINT_0_INTERRUPT_ENABLE				0
++	__le32			pciirqenb1;
++#define PCI_INTERRUPT_ENABLE					31
++#define POWER_STATE_CHANGE_INTERRUPT_ENABLE			27
++#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE			26
++#define PCI_PARITY_ERROR_INTERRUPT_ENABLE			25
++#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE		20
++#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE		19
++#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE		18
++#define PCI_RETRY_ABORT_INTERRUPT_ENABLE			17
++#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE			16
++#define GPIO_INTERRUPT_ENABLE					13
++#define DMA_D_INTERRUPT_ENABLE					12
++#define DMA_C_INTERRUPT_ENABLE					11
++#define DMA_B_INTERRUPT_ENABLE					10
++#define DMA_A_INTERRUPT_ENABLE					9
++#define EEPROM_DONE_INTERRUPT_ENABLE				8
++#define VBUS_INTERRUPT_ENABLE					7
++#define CONTROL_STATUS_INTERRUPT_ENABLE				6
++#define ROOT_PORT_RESET_INTERRUPT_ENABLE			4
++#define SUSPEND_REQUEST_INTERRUPT_ENABLE			3
++#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE			2
++#define RESUME_INTERRUPT_ENABLE					1
++#define SOF_INTERRUPT_ENABLE					0
++	__le32                  cpu_irqenb0;	/* ... or onboard 8051 */
++#define SETUP_PACKET_INTERRUPT_ENABLE				7
++#define ENDPOINT_F_INTERRUPT_ENABLE				6
++#define ENDPOINT_E_INTERRUPT_ENABLE				5
++#define ENDPOINT_D_INTERRUPT_ENABLE				4
++#define ENDPOINT_C_INTERRUPT_ENABLE				3
++#define ENDPOINT_B_INTERRUPT_ENABLE				2
++#define ENDPOINT_A_INTERRUPT_ENABLE				1
++#define ENDPOINT_0_INTERRUPT_ENABLE				0
++	__le32                  cpu_irqenb1;
++#define CPU_INTERRUPT_ENABLE					31
++#define POWER_STATE_CHANGE_INTERRUPT_ENABLE			27
++#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE			26
++#define PCI_PARITY_ERROR_INTERRUPT_ENABLE			25
++#define PCI_INTA_INTERRUPT_ENABLE				24
++#define PCI_PME_INTERRUPT_ENABLE				23
++#define PCI_SERR_INTERRUPT_ENABLE				22
++#define PCI_PERR_INTERRUPT_ENABLE				21
++#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE		20
++#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE		19
++#define PCI_RETRY_ABORT_INTERRUPT_ENABLE			17
++#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE			16
++#define GPIO_INTERRUPT_ENABLE					13
++#define DMA_D_INTERRUPT_ENABLE					12
++#define DMA_C_INTERRUPT_ENABLE					11
++#define DMA_B_INTERRUPT_ENABLE					10
++#define DMA_A_INTERRUPT_ENABLE					9
++#define EEPROM_DONE_INTERRUPT_ENABLE				8
++#define VBUS_INTERRUPT_ENABLE					7
++#define CONTROL_STATUS_INTERRUPT_ENABLE				6
++#define ROOT_PORT_RESET_INTERRUPT_ENABLE			4
++#define SUSPEND_REQUEST_INTERRUPT_ENABLE			3
++#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE			2
++#define RESUME_INTERRUPT_ENABLE					1
++#define SOF_INTERRUPT_ENABLE					0
++
++	/* offset 0x0020 */
++	u32			_unused1;
++	__le32			usbirqenb1;
++#define USB_INTERRUPT_ENABLE					31
++#define POWER_STATE_CHANGE_INTERRUPT_ENABLE			27
++#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE			26
++#define PCI_PARITY_ERROR_INTERRUPT_ENABLE			25
++#define PCI_INTA_INTERRUPT_ENABLE				24
++#define PCI_PME_INTERRUPT_ENABLE				23
++#define PCI_SERR_INTERRUPT_ENABLE				22
++#define PCI_PERR_INTERRUPT_ENABLE				21
++#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE		20
++#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE		19
++#define PCI_RETRY_ABORT_INTERRUPT_ENABLE			17
++#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE			16
++#define GPIO_INTERRUPT_ENABLE					13
++#define DMA_D_INTERRUPT_ENABLE					12
++#define DMA_C_INTERRUPT_ENABLE					11
++#define DMA_B_INTERRUPT_ENABLE					10
++#define DMA_A_INTERRUPT_ENABLE					9
++#define EEPROM_DONE_INTERRUPT_ENABLE				8
++#define VBUS_INTERRUPT_ENABLE					7
++#define CONTROL_STATUS_INTERRUPT_ENABLE				6
++#define ROOT_PORT_RESET_INTERRUPT_ENABLE			4
++#define SUSPEND_REQUEST_INTERRUPT_ENABLE			3
++#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE			2
++#define RESUME_INTERRUPT_ENABLE					1
++#define SOF_INTERRUPT_ENABLE					0
++	__le32			irqstat0;
++#define INTA_ASSERTED						12
++#define SETUP_PACKET_INTERRUPT					7
++#define ENDPOINT_F_INTERRUPT					6
++#define ENDPOINT_E_INTERRUPT					5
++#define ENDPOINT_D_INTERRUPT					4
++#define ENDPOINT_C_INTERRUPT					3
++#define ENDPOINT_B_INTERRUPT					2
++#define ENDPOINT_A_INTERRUPT					1
++#define ENDPOINT_0_INTERRUPT					0
++	__le32			irqstat1;
++#define POWER_STATE_CHANGE_INTERRUPT				27
++#define PCI_ARBITER_TIMEOUT_INTERRUPT				26
++#define PCI_PARITY_ERROR_INTERRUPT				25
++#define PCI_INTA_INTERRUPT					24
++#define PCI_PME_INTERRUPT					23
++#define PCI_SERR_INTERRUPT					22
++#define PCI_PERR_INTERRUPT					21
++#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT			20
++#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT			19
++#define PCI_RETRY_ABORT_INTERRUPT				17
++#define PCI_MASTER_CYCLE_DONE_INTERRUPT				16
++#define GPIO_INTERRUPT						13
++#define DMA_D_INTERRUPT						12
++#define DMA_C_INTERRUPT						11
++#define DMA_B_INTERRUPT						10
++#define DMA_A_INTERRUPT						9
++#define EEPROM_DONE_INTERRUPT					8
++#define VBUS_INTERRUPT						7
++#define CONTROL_STATUS_INTERRUPT				6
++#define ROOT_PORT_RESET_INTERRUPT				4
++#define SUSPEND_REQUEST_INTERRUPT				3
++#define SUSPEND_REQUEST_CHANGE_INTERRUPT			2
++#define RESUME_INTERRUPT					1
++#define SOF_INTERRUPT						0
++	/* offset 0x0030 */
++	__le32			idxaddr;
++	__le32			idxdata;
++	__le32			fifoctl;
++#define PCI_BASE2_RANGE						16
++#define IGNORE_FIFO_AVAILABILITY				3
++#define PCI_BASE2_SELECT					2
++#define FIFO_CONFIGURATION_SELECT				0
++	u32			_unused2;
++	/* offset 0x0040 */
++	__le32			memaddr;
++#define START							28
++#define DIRECTION						27
++#define FIFO_DIAGNOSTIC_SELECT					24
++#define MEMORY_ADDRESS						0
++	__le32			memdata0;
++	__le32			memdata1;
++	u32			_unused3;
++	/* offset 0x0050 */
++	__le32			gpioctl;
++#define GPIO3_LED_SELECT					12
++#define GPIO3_INTERRUPT_ENABLE					11
++#define GPIO2_INTERRUPT_ENABLE					10
++#define GPIO1_INTERRUPT_ENABLE					9
++#define GPIO0_INTERRUPT_ENABLE					8
++#define GPIO3_OUTPUT_ENABLE					7
++#define GPIO2_OUTPUT_ENABLE					6
++#define GPIO1_OUTPUT_ENABLE					5
++#define GPIO0_OUTPUT_ENABLE					4
++#define GPIO3_DATA						3
++#define GPIO2_DATA						2
++#define GPIO1_DATA						1
++#define GPIO0_DATA						0
++	__le32			gpiostat;
++#define GPIO3_INTERRUPT						3
++#define GPIO2_INTERRUPT						2
++#define GPIO1_INTERRUPT						1
++#define GPIO0_INTERRUPT						0
++} __attribute__ ((packed));
++
++/* usb control, BAR0 + 0x0080 */
++struct net2280_usb_regs {
++	/* offset 0x0080 */
++	__le32			stdrsp;
++#define STALL_UNSUPPORTED_REQUESTS				31
++#define SET_TEST_MODE						16
++#define GET_OTHER_SPEED_CONFIGURATION				15
++#define GET_DEVICE_QUALIFIER					14
++#define SET_ADDRESS						13
++#define ENDPOINT_SET_CLEAR_HALT					12
++#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP			11
++#define GET_STRING_DESCRIPTOR_2					10
++#define GET_STRING_DESCRIPTOR_1					9
++#define GET_STRING_DESCRIPTOR_0					8
++#define GET_SET_INTERFACE					6
++#define GET_SET_CONFIGURATION					5
++#define GET_CONFIGURATION_DESCRIPTOR				4
++#define GET_DEVICE_DESCRIPTOR					3
++#define GET_ENDPOINT_STATUS					2
++#define GET_INTERFACE_STATUS					1
++#define GET_DEVICE_STATUS					0
++	__le32			prodvendid;
++#define     PRODUCT_ID						16
++#define     VENDOR_ID						0
++	__le32			relnum;
++	__le32			usbctl;
++#define SERIAL_NUMBER_INDEX					16
++#define PRODUCT_ID_STRING_ENABLE				13
++#define VENDOR_ID_STRING_ENABLE					12
++#define USB_ROOT_PORT_WAKEUP_ENABLE				11
++#define VBUS_PIN						10
++#define TIMED_DISCONNECT					9
++#define SUSPEND_IMMEDIATELY					7
++#define SELF_POWERED_USB_DEVICE					6
++#define REMOTE_WAKEUP_SUPPORT					5
++#define PME_POLARITY						4
++#define USB_DETECT_ENABLE					3
++#define PME_WAKEUP_ENABLE					2
++#define DEVICE_REMOTE_WAKEUP_ENABLE				1
++#define SELF_POWERED_STATUS					0
++	/* offset 0x0090 */
++	__le32			usbstat;
++#define HIGH_SPEED						7
++#define FULL_SPEED						6
++#define GENERATE_RESUME						5
++#define GENERATE_DEVICE_REMOTE_WAKEUP				4
++	__le32			xcvrdiag;
++#define FORCE_HIGH_SPEED_MODE					31
++#define FORCE_FULL_SPEED_MODE					30
++#define USB_TEST_MODE						24
++#define LINE_STATE						16
++#define TRANSCEIVER_OPERATION_MODE				2
++#define TRANSCEIVER_SELECT					1
++#define TERMINATION_SELECT					0
++	__le32			setup0123;
++	__le32			setup4567;
++	/* offset 0x0090 */
++	u32			_unused0;
++	__le32			ouraddr;
++#define FORCE_IMMEDIATE						7
++#define OUR_USB_ADDRESS						0
++	__le32			ourconfig;
++} __attribute__ ((packed));
++
++/* pci control, BAR0 + 0x0100 */
++struct net2280_pci_regs {
++	/* offset 0x0100 */
++	__le32			pcimstctl;
++#define PCI_ARBITER_PARK_SELECT					13
++#define PCI_MULTI LEVEL_ARBITER					12
++#define PCI_RETRY_ABORT_ENABLE					11
++#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE			10
++#define DMA_READ_MULTIPLE_ENABLE				9
++#define DMA_READ_LINE_ENABLE					8
++#define PCI_MASTER_COMMAND_SELECT				6
++#define		MEM_READ_OR_WRITE				0
++#define		IO_READ_OR_WRITE				1
++#define		CFG_READ_OR_WRITE				2
++#define PCI_MASTER_START					5
++#define PCI_MASTER_READ_WRITE					4
++#define		PCI_MASTER_WRITE				0
++#define		PCI_MASTER_READ					1
++#define PCI_MASTER_BYTE_WRITE_ENABLES				0
++	__le32			pcimstaddr;
++	__le32			pcimstdata;
++	__le32			pcimststat;
++#define PCI_ARBITER_CLEAR					2
++#define PCI_EXTERNAL_ARBITER					1
++#define PCI_HOST_MODE						0
++} __attribute__ ((packed));
++
++/* dma control, BAR0 + 0x0180 ... array of four structs like this,
++ * for channels 0..3.  see also struct net2280_dma:  descriptor
++ * that can be loaded into some of these registers.
++ */
++struct net2280_dma_regs {	/* [11.7] */
++	/* offset 0x0180, 0x01a0, 0x01c0, 0x01e0, */
++	__le32			dmactl;
++#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE		25
++#define DMA_CLEAR_COUNT_ENABLE					21
++#define DESCRIPTOR_POLLING_RATE					19
++#define		POLL_CONTINUOUS					0
++#define		POLL_1_USEC					1
++#define		POLL_100_USEC					2
++#define		POLL_1_MSEC					3
++#define DMA_VALID_BIT_POLLING_ENABLE				18
++#define DMA_VALID_BIT_ENABLE					17
++#define DMA_SCATTER_GATHER_ENABLE				16
++#define DMA_OUT_AUTO_START_ENABLE				4
++#define DMA_PREEMPT_ENABLE					3
++#define DMA_FIFO_VALIDATE					2
++#define DMA_ENABLE						1
++#define DMA_ADDRESS_HOLD					0
++	__le32			dmastat;
++#define DMA_SCATTER_GATHER_DONE_INTERRUPT			25
++#define DMA_TRANSACTION_DONE_INTERRUPT				24
++#define DMA_ABORT						1
++#define DMA_START						0
++	u32			_unused0[2];
++	/* offset 0x0190, 0x01b0, 0x01d0, 0x01f0, */
++	__le32                  dmacount;
++#define VALID_BIT						31
++#define DMA_DIRECTION						30
++#define DMA_DONE_INTERRUPT_ENABLE				29
++#define END_OF_CHAIN						28
++#define DMA_BYTE_COUNT_MASK					((1<<24)-1)
++#define DMA_BYTE_COUNT						0
++	__le32			dmaaddr;
++	__le32			dmadesc;
++	u32			_unused1;
++} __attribute__ ((packed));
++
++/* dedicated endpoint registers, BAR0 + 0x0200 */
++
++struct net2280_dep_regs {	/* [11.8] */
++	/* offset 0x0200, 0x0210, 0x220, 0x230, 0x240 */
++	__le32			dep_cfg;
++	/* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */
++	__le32			dep_rsp;
++	u32			_unused[2];
++} __attribute__ ((packed));
++
++/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
++ * like this, for ep0 then the configurable endpoints A..F
++ * ep0 reserved for control; E and F have only 64 bytes of fifo
++ */
++struct net2280_ep_regs {	/* [11.9] */
++	/* offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 */
++	__le32			ep_cfg;
++#define ENDPOINT_BYTE_COUNT					16
++#define ENDPOINT_ENABLE						10
++#define ENDPOINT_TYPE						8
++#define ENDPOINT_DIRECTION					7
++#define ENDPOINT_NUMBER						0
++	__le32			ep_rsp;
++#define SET_NAK_OUT_PACKETS					15
++#define SET_EP_HIDE_STATUS_PHASE				14
++#define SET_EP_FORCE_CRC_ERROR					13
++#define SET_INTERRUPT_MODE					12
++#define SET_CONTROL_STATUS_PHASE_HANDSHAKE			11
++#define SET_NAK_OUT_PACKETS_MODE				10
++#define SET_ENDPOINT_TOGGLE					9
++#define SET_ENDPOINT_HALT					8
++#define CLEAR_NAK_OUT_PACKETS					7
++#define CLEAR_EP_HIDE_STATUS_PHASE				6
++#define CLEAR_EP_FORCE_CRC_ERROR				5
++#define CLEAR_INTERRUPT_MODE					4
++#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE			3
++#define CLEAR_NAK_OUT_PACKETS_MODE				2
++#define CLEAR_ENDPOINT_TOGGLE					1
++#define CLEAR_ENDPOINT_HALT					0
++	__le32			ep_irqenb;
++#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE			6
++#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE		5
++#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE			3
++#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE		2
++#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE			1
++#define DATA_IN_TOKEN_INTERRUPT_ENABLE				0
++	__le32			ep_stat;
++#define FIFO_VALID_COUNT					24
++#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID			22
++#define TIMEOUT							21
++#define USB_STALL_SENT						20
++#define USB_IN_NAK_SENT						19
++#define USB_IN_ACK_RCVD						18
++#define USB_OUT_PING_NAK_SENT					17
++#define USB_OUT_ACK_SENT					16
++#define FIFO_OVERFLOW						13
++#define FIFO_UNDERFLOW						12
++#define FIFO_FULL						11
++#define FIFO_EMPTY						10
++#define FIFO_FLUSH						9
++#define SHORT_PACKET_OUT_DONE_INTERRUPT				6
++#define SHORT_PACKET_TRANSFERRED_INTERRUPT			5
++#define NAK_OUT_PACKETS						4
++#define DATA_PACKET_RECEIVED_INTERRUPT				3
++#define DATA_PACKET_TRANSMITTED_INTERRUPT			2
++#define DATA_OUT_PING_TOKEN_INTERRUPT				1
++#define DATA_IN_TOKEN_INTERRUPT					0
++	/* offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 */
++	__le32			ep_avail;
++	__le32			ep_data;
++	u32			_unused0[2];
++} __attribute__ ((packed));
++
++struct net2280_reg_write {
++	__le16 port;
++	__le32 addr;
++	__le32 val;
++} __attribute__ ((packed));
++
++struct net2280_reg_read {
++	__le16 port;
++	__le32 addr;
++} __attribute__ ((packed));
++#endif /* NET2280_H */
+diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
+new file mode 100644
+index 0000000..06d2c67
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54.h
+@@ -0,0 +1,77 @@
++#ifndef PRISM54_H
++#define PRISM54_H
++
++/*
++ * Shared defines for all mac80211 Prism54 code
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++enum control_frame_types {
++	P54_CONTROL_TYPE_FILTER_SET = 0,
++	P54_CONTROL_TYPE_CHANNEL_CHANGE,
++	P54_CONTROL_TYPE_FREQDONE,
++	P54_CONTROL_TYPE_DCFINIT,
++	P54_CONTROL_TYPE_FREEQUEUE = 7,
++	P54_CONTROL_TYPE_TXDONE,
++	P54_CONTROL_TYPE_PING,
++	P54_CONTROL_TYPE_STAT_READBACK,
++	P54_CONTROL_TYPE_BBP,
++	P54_CONTROL_TYPE_EEPROM_READBACK,
++	P54_CONTROL_TYPE_LED
++};
++
++struct p54_control_hdr {
++	__le16 magic1;
++	__le16 len;
++	__le32 req_id;
++	__le16 type;	/* enum control_frame_types */
++	u8 retry1;
++	u8 retry2;
++	u8 data[0];
++} __attribute__ ((packed));
++
++#define EEPROM_READBACK_LEN (sizeof(struct p54_control_hdr) + 4 /* p54_eeprom_lm86 */)
++#define MAX_RX_SIZE (IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct p54_control_hdr) + 20 /* length of struct p54_rx_hdr */ + 16 )
++
++#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
++
++struct p54_common {
++	u32 rx_start;
++	u32 rx_end;
++	struct sk_buff_head tx_queue;
++	void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data,
++		   size_t len, int free_on_tx);
++	int (*open)(struct ieee80211_hw *dev);
++	void (*stop)(struct ieee80211_hw *dev);
++	int mode;
++	u8 mac_addr[ETH_ALEN];
++	u8 bssid[ETH_ALEN];
++	struct pda_iq_autocal_entry *iq_autocal;
++	unsigned int iq_autocal_len;
++	struct pda_channel_output_limit *output_limit;
++	unsigned int output_limit_len;
++	struct pda_pa_curve_data *curve_data;
++	__le16 rxhw;
++	u8 version;
++	unsigned int tx_hdr_len;
++	void *cached_vdcf;
++	unsigned int fw_var;
++	struct ieee80211_tx_queue_stats tx_stats;
++};
++
++int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
++void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
++int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
++void p54_fill_eeprom_readback(struct p54_control_hdr *hdr);
++struct ieee80211_hw *p54_init_common(size_t priv_data_len);
++void p54_free_common(struct ieee80211_hw *dev);
++
++#endif /* PRISM54_H */
+diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
+new file mode 100644
+index 0000000..63f9bad
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54common.c
+@@ -0,0 +1,1051 @@
++
++/*
++ * Common code for mac80211 Prism54 drivers
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ * Copyright (c) 2007, Christian Lamparter <chunkeey at web.de>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it 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/firmware.h>
++#include <linux/etherdevice.h>
++
++#include <net/mac80211.h>
++
++#include "p54.h"
++#include "p54common.h"
++
++MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
++MODULE_DESCRIPTION("Softmac Prism54 common code");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("prism54common");
++
++static struct ieee80211_rate p54_rates[] = {
++	{ .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 60, .hw_value = 4, },
++	{ .bitrate = 90, .hw_value = 5, },
++	{ .bitrate = 120, .hw_value = 6, },
++	{ .bitrate = 180, .hw_value = 7, },
++	{ .bitrate = 240, .hw_value = 8, },
++	{ .bitrate = 360, .hw_value = 9, },
++	{ .bitrate = 480, .hw_value = 10, },
++	{ .bitrate = 540, .hw_value = 11, },
++};
++
++static struct ieee80211_channel p54_channels[] = {
++	{ .center_freq = 2412, .hw_value = 1, },
++	{ .center_freq = 2417, .hw_value = 2, },
++	{ .center_freq = 2422, .hw_value = 3, },
++	{ .center_freq = 2427, .hw_value = 4, },
++	{ .center_freq = 2432, .hw_value = 5, },
++	{ .center_freq = 2437, .hw_value = 6, },
++	{ .center_freq = 2442, .hw_value = 7, },
++	{ .center_freq = 2447, .hw_value = 8, },
++	{ .center_freq = 2452, .hw_value = 9, },
++	{ .center_freq = 2457, .hw_value = 10, },
++	{ .center_freq = 2462, .hw_value = 11, },
++	{ .center_freq = 2467, .hw_value = 12, },
++	{ .center_freq = 2472, .hw_value = 13, },
++	{ .center_freq = 2484, .hw_value = 14, },
++};
++
++static struct ieee80211_supported_band band_2GHz = {
++	.channels = p54_channels,
++	.n_channels = ARRAY_SIZE(p54_channels),
++	.bitrates = p54_rates,
++	.n_bitrates = ARRAY_SIZE(p54_rates),
++};
++
++
++void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
++{
++	struct p54_common *priv = dev->priv;
++	struct bootrec_exp_if *exp_if;
++	struct bootrec *bootrec;
++	u32 *data = (u32 *)fw->data;
++	u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
++	u8 *fw_version = NULL;
++	size_t len;
++	int i;
++
++	if (priv->rx_start)
++		return;
++
++	while (data < end_data && *data)
++		data++;
++
++	while (data < end_data && !*data)
++		data++;
++
++	bootrec = (struct bootrec *) data;
++
++	while (bootrec->data <= end_data &&
++	       (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
++		u32 code = le32_to_cpu(bootrec->code);
++		switch (code) {
++		case BR_CODE_COMPONENT_ID:
++			switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
++			case FW_FMAC:
++				printk(KERN_INFO "p54: FreeMAC firmware\n");
++				break;
++			case FW_LM20:
++				printk(KERN_INFO "p54: LM20 firmware\n");
++				break;
++			case FW_LM86:
++				printk(KERN_INFO "p54: LM86 firmware\n");
++				break;
++			case FW_LM87:
++				printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
++				break;
++			default:
++				printk(KERN_INFO "p54: unknown firmware\n");
++				break;
++			}
++			break;
++		case BR_CODE_COMPONENT_VERSION:
++			/* 24 bytes should be enough for all firmwares */
++			if (strnlen((unsigned char*)bootrec->data, 24) < 24)
++				fw_version = (unsigned char*)bootrec->data;
++			break;
++		case BR_CODE_DESCR:
++			priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
++			/* FIXME add sanity checking */
++			priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
++			break;
++		case BR_CODE_EXPOSED_IF:
++			exp_if = (struct bootrec_exp_if *) bootrec->data;
++			for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
++				if (exp_if[i].if_id == cpu_to_le16(0x1a))
++					priv->fw_var = le16_to_cpu(exp_if[i].variant);
++			break;
++		case BR_CODE_DEPENDENT_IF:
++			break;
++		case BR_CODE_END_OF_BRA:
++		case LEGACY_BR_CODE_END_OF_BRA:
++			end_data = NULL;
++			break;
++		default:
++			break;
++		}
++		bootrec = (struct bootrec *)&bootrec->data[len];
++	}
++
++	if (fw_version)
++		printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
++			fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
++
++	if (priv->fw_var >= 0x300) {
++		/* Firmware supports QoS, use it! */
++		priv->tx_stats.data[0].limit = 3;
++		priv->tx_stats.data[1].limit = 4;
++		priv->tx_stats.data[2].limit = 3;
++		priv->tx_stats.data[3].limit = 1;
++		dev->queues = 4;
++	}
++}
++EXPORT_SYMBOL_GPL(p54_parse_firmware);
++
++static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
++				    struct pda_pa_curve_data *curve_data)
++{
++	struct p54_common *priv = dev->priv;
++	struct pda_pa_curve_data_sample_rev1 *rev1;
++	struct pda_pa_curve_data_sample_rev0 *rev0;
++	size_t cd_len = sizeof(*curve_data) +
++		(curve_data->points_per_channel*sizeof(*rev1) + 2) *
++		 curve_data->channels;
++	unsigned int i, j;
++	void *source, *target;
++
++	priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
++	if (!priv->curve_data)
++		return -ENOMEM;
++
++	memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
++	source = curve_data->data;
++	target = priv->curve_data->data;
++	for (i = 0; i < curve_data->channels; i++) {
++		__le16 *freq = source;
++		source += sizeof(__le16);
++		*((__le16 *)target) = *freq;
++		target += sizeof(__le16);
++		for (j = 0; j < curve_data->points_per_channel; j++) {
++			rev1 = target;
++			rev0 = source;
++
++			rev1->rf_power = rev0->rf_power;
++			rev1->pa_detector = rev0->pa_detector;
++			rev1->data_64qam = rev0->pcv;
++			/* "invent" the points for the other modulations */
++#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
++			rev1->data_16qam = SUB(rev0->pcv, 12);
++			rev1->data_qpsk  = SUB(rev1->data_16qam, 12);
++			rev1->data_bpsk  = SUB(rev1->data_qpsk, 12);
++			rev1->data_barker= SUB(rev1->data_bpsk, 14);
++#undef SUB
++			target += sizeof(*rev1);
++			source += sizeof(*rev0);
++		}
++	}
++
++	return 0;
++}
++
++int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
++{
++	struct p54_common *priv = dev->priv;
++	struct eeprom_pda_wrap *wrap = NULL;
++	struct pda_entry *entry;
++	unsigned int data_len, entry_len;
++	void *tmp;
++	int err;
++	u8 *end = (u8 *)eeprom + len;
++
++	wrap = (struct eeprom_pda_wrap *) eeprom;
++	entry = (void *)wrap->data + le16_to_cpu(wrap->len);
++
++	/* verify that at least the entry length/code fits */
++	while ((u8 *)entry <= end - sizeof(*entry)) {
++		entry_len = le16_to_cpu(entry->len);
++		data_len = ((entry_len - 1) << 1);
++
++		/* abort if entry exceeds whole structure */
++		if ((u8 *)entry + sizeof(*entry) + data_len > end)
++			break;
++
++		switch (le16_to_cpu(entry->code)) {
++		case PDR_MAC_ADDRESS:
++			SET_IEEE80211_PERM_ADDR(dev, entry->data);
++			break;
++		case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
++			if (data_len < 2) {
++				err = -EINVAL;
++				goto err;
++			}
++
++			if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) {
++				err = -EINVAL;
++				goto err;
++			}
++
++			priv->output_limit = kmalloc(entry->data[1] *
++				sizeof(*priv->output_limit), GFP_KERNEL);
++
++			if (!priv->output_limit) {
++				err = -ENOMEM;
++				goto err;
++			}
++
++			memcpy(priv->output_limit, &entry->data[2],
++			       entry->data[1]*sizeof(*priv->output_limit));
++			priv->output_limit_len = entry->data[1];
++			break;
++		case PDR_PRISM_PA_CAL_CURVE_DATA:
++			if (data_len < sizeof(struct pda_pa_curve_data)) {
++				err = -EINVAL;
++				goto err;
++			}
++
++			if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) {
++				priv->curve_data = kmalloc(data_len, GFP_KERNEL);
++				if (!priv->curve_data) {
++					err = -ENOMEM;
++					goto err;
++				}
++
++				memcpy(priv->curve_data, entry->data, data_len);
++			} else {
++				err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data);
++				if (err)
++					goto err;
++			}
++
++			break;
++		case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
++			priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
++			if (!priv->iq_autocal) {
++				err = -ENOMEM;
++				goto err;
++			}
++
++			memcpy(priv->iq_autocal, entry->data, data_len);
++			priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
++			break;
++		case PDR_INTERFACE_LIST:
++			tmp = entry->data;
++			while ((u8 *)tmp < entry->data + data_len) {
++				struct bootrec_exp_if *exp_if = tmp;
++				if (le16_to_cpu(exp_if->if_id) == 0xF)
++					priv->rxhw = exp_if->variant & cpu_to_le16(0x07);
++				tmp += sizeof(struct bootrec_exp_if);
++			}
++			break;
++		case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
++			priv->version = *(u8 *)(entry->data + 1);
++			break;
++		case PDR_END:
++			/* make it overrun */
++			entry_len = len;
++			break;
++		default:
++			printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n",
++				le16_to_cpu(entry->code));
++			break;
++		}
++
++		entry = (void *)entry + (entry_len + 1)*2;
++	}
++
++	if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) {
++		printk(KERN_ERR "p54: not all required entries found in eeprom!\n");
++		err = -EINVAL;
++		goto err;
++	}
++
++	return 0;
++
++  err:
++	if (priv->iq_autocal) {
++		kfree(priv->iq_autocal);
++		priv->iq_autocal = NULL;
++	}
++
++	if (priv->output_limit) {
++		kfree(priv->output_limit);
++		priv->output_limit = NULL;
++	}
++
++	if (priv->curve_data) {
++		kfree(priv->curve_data);
++		priv->curve_data = NULL;
++	}
++
++	printk(KERN_ERR "p54: eeprom parse failed!\n");
++	return err;
++}
++EXPORT_SYMBOL_GPL(p54_parse_eeprom);
++
++void p54_fill_eeprom_readback(struct p54_control_hdr *hdr)
++{
++	struct p54_eeprom_lm86 *eeprom_hdr;
++
++	hdr->magic1 = cpu_to_le16(0x8000);
++	hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000);
++	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
++	hdr->retry1 = hdr->retry2 = 0;
++	eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
++	eeprom_hdr->offset = 0x0;
++	eeprom_hdr->len = cpu_to_le16(0x2000);
++}
++EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback);
++
++static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
++{
++	struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
++	struct ieee80211_rx_status rx_status = {0};
++	u16 freq = le16_to_cpu(hdr->freq);
++
++	rx_status.ssi = hdr->rssi;
++	/* XX correct? */
++	rx_status.rate_idx = hdr->rate & 0xf;
++	rx_status.freq = freq;
++	rx_status.band = IEEE80211_BAND_2GHZ;
++	rx_status.antenna = hdr->antenna;
++	rx_status.mactime = le64_to_cpu(hdr->timestamp);
++	rx_status.flag |= RX_FLAG_TSFT;
++
++	skb_pull(skb, sizeof(*hdr));
++	skb_trim(skb, le16_to_cpu(hdr->len));
++
++	ieee80211_rx_irqsafe(dev, skb, &rx_status);
++}
++
++static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
++{
++	struct p54_common *priv = dev->priv;
++	int i;
++
++	/* ieee80211_start_queues is great if all queues are really empty.
++	 * But, what if some are full? */
++
++	for (i = 0; i < dev->queues; i++)
++		if (priv->tx_stats.data[i].len < priv->tx_stats.data[i].limit)
++			ieee80211_wake_queue(dev, i);
++}
++
++static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
++{
++	struct p54_common *priv = dev->priv;
++	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
++	struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
++	struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
++	u32 addr = le32_to_cpu(hdr->req_id) - 0x70;
++	struct memrecord *range = NULL;
++	u32 freed = 0;
++	u32 last_addr = priv->rx_start;
++
++	while (entry != (struct sk_buff *)&priv->tx_queue) {
++		range = (struct memrecord *)&entry->cb;
++		if (range->start_addr == addr) {
++			struct ieee80211_tx_status status;
++			struct p54_control_hdr *entry_hdr;
++			struct p54_tx_control_allocdata *entry_data;
++			int pad = 0;
++
++			if (entry->next != (struct sk_buff *)&priv->tx_queue)
++				freed = ((struct memrecord *)&entry->next->cb)->start_addr - last_addr;
++			else
++				freed = priv->rx_end - last_addr;
++
++			last_addr = range->end_addr;
++			__skb_unlink(entry, &priv->tx_queue);
++			if (!range->control) {
++				kfree_skb(entry);
++				break;
++			}
++			memset(&status, 0, sizeof(status));
++			memcpy(&status.control, range->control,
++			       sizeof(status.control));
++			kfree(range->control);
++			priv->tx_stats.data[status.control.queue].len--;
++
++			entry_hdr = (struct p54_control_hdr *) entry->data;
++			entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
++			if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
++				pad = entry_data->align[0];
++
++			if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
++				if (!(payload->status & 0x01))
++					status.flags |= IEEE80211_TX_STATUS_ACK;
++				else
++					status.excessive_retries = 1;
++			}
++			status.retry_count = payload->retries - 1;
++			status.ack_signal = le16_to_cpu(payload->ack_rssi);
++			skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
++			ieee80211_tx_status_irqsafe(dev, entry, &status);
++			break;
++		} else
++			last_addr = range->end_addr;
++		entry = entry->next;
++	}
++
++	if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
++	    sizeof(struct p54_control_hdr))
++		p54_wake_free_queues(dev);
++}
++
++static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
++{
++	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
++
++	switch (le16_to_cpu(hdr->type)) {
++	case P54_CONTROL_TYPE_TXDONE:
++		p54_rx_frame_sent(dev, skb);
++		break;
++	case P54_CONTROL_TYPE_BBP:
++		break;
++	default:
++		printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
++		       wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
++		break;
++	}
++}
++
++/* returns zero if skb can be reused */
++int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
++{
++	u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
++	switch (type) {
++	case 0x00:
++	case 0x01:
++		p54_rx_data(dev, skb);
++		return -1;
++	case 0x4d:
++		/* TODO: do something better... but then again, I've never seen this happen */
++		printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n",
++		       wiphy_name(dev->wiphy));
++		break;
++	case 0x80:
++		p54_rx_control(dev, skb);
++		break;
++	default:
++		printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n",
++		       wiphy_name(dev->wiphy), type);
++		break;
++	}
++	return 0;
++}
++EXPORT_SYMBOL_GPL(p54_rx);
++
++/*
++ * So, the firmware is somewhat stupid and doesn't know what places in its
++ * memory incoming data should go to. By poking around in the firmware, we
++ * can find some unused memory to upload our packets to. However, data that we
++ * want the card to TX needs to stay intact until the card has told us that
++ * it is done with it. This function finds empty places we can upload to and
++ * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
++ * allocated areas.
++ */
++static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
++			       struct p54_control_hdr *data, u32 len,
++			       struct ieee80211_tx_control *control)
++{
++	struct p54_common *priv = dev->priv;
++	struct sk_buff *entry = priv->tx_queue.next;
++	struct sk_buff *target_skb = NULL;
++	struct memrecord *range;
++	u32 last_addr = priv->rx_start;
++	u32 largest_hole = 0;
++	u32 target_addr = priv->rx_start;
++	unsigned long flags;
++	unsigned int left;
++	len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */
++
++	spin_lock_irqsave(&priv->tx_queue.lock, flags);
++	left = skb_queue_len(&priv->tx_queue);
++	while (left--) {
++		u32 hole_size;
++		range = (struct memrecord *)&entry->cb;
++		hole_size = range->start_addr - last_addr;
++		if (!target_skb && hole_size >= len) {
++			target_skb = entry->prev;
++			hole_size -= len;
++			target_addr = last_addr;
++		}
++		largest_hole = max(largest_hole, hole_size);
++		last_addr = range->end_addr;
++		entry = entry->next;
++	}
++	if (!target_skb && priv->rx_end - last_addr >= len) {
++		target_skb = priv->tx_queue.prev;
++		largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
++		if (!skb_queue_empty(&priv->tx_queue)) {
++			range = (struct memrecord *)&target_skb->cb;
++			target_addr = range->end_addr;
++		}
++	} else
++		largest_hole = max(largest_hole, priv->rx_end - last_addr);
++
++	if (skb) {
++		range = (struct memrecord *)&skb->cb;
++		range->start_addr = target_addr;
++		range->end_addr = target_addr + len;
++		range->control = control;
++		__skb_queue_after(&priv->tx_queue, target_skb, skb);
++		if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
++				   sizeof(struct p54_control_hdr))
++			ieee80211_stop_queues(dev);
++	}
++	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
++
++	data->req_id = cpu_to_le32(target_addr + 0x70);
++}
++
++static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
++		  struct ieee80211_tx_control *control)
++{
++	struct ieee80211_tx_queue_stats_data *current_queue;
++	struct p54_common *priv = dev->priv;
++	struct p54_control_hdr *hdr;
++	struct p54_tx_control_allocdata *txhdr;
++	struct ieee80211_tx_control *control_copy;
++	size_t padding, len;
++	u8 rate;
++
++	current_queue = &priv->tx_stats.data[control->queue];
++	if (unlikely(current_queue->len > current_queue->limit))
++		return NETDEV_TX_BUSY;
++	current_queue->len++;
++	current_queue->count++;
++	if (current_queue->len == current_queue->limit)
++		ieee80211_stop_queue(dev, control->queue);
++
++	padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
++	len = skb->len;
++
++	control_copy = kmalloc(sizeof(*control), GFP_ATOMIC);
++	if (control_copy)
++		memcpy(control_copy, control, sizeof(*control));
++
++	txhdr = (struct p54_tx_control_allocdata *)
++			skb_push(skb, sizeof(*txhdr) + padding);
++	hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));
++
++	if (padding)
++		hdr->magic1 = cpu_to_le16(0x4010);
++	else
++		hdr->magic1 = cpu_to_le16(0x0010);
++	hdr->len = cpu_to_le16(len);
++	hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1);
++	hdr->retry1 = hdr->retry2 = control->retry_limit;
++	p54_assign_address(dev, skb, hdr, skb->len, control_copy);
++
++	memset(txhdr->wep_key, 0x0, 16);
++	txhdr->padding = 0;
++	txhdr->padding2 = 0;
++
++	/* TODO: add support for alternate retry TX rates */
++	rate = control->tx_rate->hw_value;
++	if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
++		rate |= 0x10;
++	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
++		rate |= 0x40;
++	else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
++		rate |= 0x20;
++	memset(txhdr->rateset, rate, 8);
++	txhdr->wep_key_present = 0;
++	txhdr->wep_key_len = 0;
++	txhdr->frame_type = cpu_to_le32(control->queue + 4);
++	txhdr->magic4 = 0;
++	txhdr->antenna = (control->antenna_sel_tx == 0) ?
++		2 : control->antenna_sel_tx - 1;
++	txhdr->output_power = 0x7f; // HW Maximum
++	txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ?
++		0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23));
++	if (padding)
++		txhdr->align[0] = padding;
++
++	priv->tx(dev, hdr, skb->len, 0);
++	return 0;
++}
++
++static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
++			  const u8 *dst, const u8 *src, u8 antenna,
++			  u32 magic3, u32 magic8, u32 magic9)
++{
++	struct p54_common *priv = dev->priv;
++	struct p54_control_hdr *hdr;
++	struct p54_tx_control_filter *filter;
++
++	hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
++		      priv->tx_hdr_len, GFP_ATOMIC);
++	if (!hdr)
++		return -ENOMEM;
++
++	hdr = (void *)hdr + priv->tx_hdr_len;
++
++	filter = (struct p54_tx_control_filter *) hdr->data;
++	hdr->magic1 = cpu_to_le16(0x8001);
++	hdr->len = cpu_to_le16(sizeof(*filter));
++	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL);
++	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
++
++	filter->filter_type = cpu_to_le16(filter_type);
++	memcpy(filter->dst, dst, ETH_ALEN);
++	if (!src)
++		memset(filter->src, ~0, ETH_ALEN);
++	else
++		memcpy(filter->src, src, ETH_ALEN);
++	filter->antenna = antenna;
++	filter->magic3 = cpu_to_le32(magic3);
++	filter->rx_addr = cpu_to_le32(priv->rx_end);
++	filter->max_rx = cpu_to_le16(0x0620);	/* FIXME: for usb ver 1.. maybe */
++	filter->rxhw = priv->rxhw;
++	filter->magic8 = cpu_to_le16(magic8);
++	filter->magic9 = cpu_to_le16(magic9);
++
++	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1);
++	return 0;
++}
++
++static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
++{
++	struct p54_common *priv = dev->priv;
++	struct p54_control_hdr *hdr;
++	struct p54_tx_control_channel *chan;
++	unsigned int i;
++	size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
++			     sizeof(*chan->curve_data) *
++			     priv->curve_data->points_per_channel;
++	void *entry;
++
++	hdr = kzalloc(sizeof(*hdr) + payload_len +
++		      priv->tx_hdr_len, GFP_KERNEL);
++	if (!hdr)
++		return -ENOMEM;
++
++	hdr = (void *)hdr + priv->tx_hdr_len;
++
++	chan = (struct p54_tx_control_channel *) hdr->data;
++
++	hdr->magic1 = cpu_to_le16(0x8001);
++	hdr->len = cpu_to_le16(sizeof(*chan));
++	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
++	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL);
++
++	chan->magic1 = cpu_to_le16(0x1);
++	chan->magic2 = cpu_to_le16(0x0);
++
++	for (i = 0; i < priv->iq_autocal_len; i++) {
++		if (priv->iq_autocal[i].freq != freq)
++			continue;
++
++		memcpy(&chan->iq_autocal, &priv->iq_autocal[i],
++		       sizeof(*priv->iq_autocal));
++		break;
++	}
++	if (i == priv->iq_autocal_len)
++		goto err;
++
++	for (i = 0; i < priv->output_limit_len; i++) {
++		if (priv->output_limit[i].freq != freq)
++			continue;
++
++		chan->val_barker = 0x38;
++		chan->val_bpsk = priv->output_limit[i].val_bpsk;
++		chan->val_qpsk = priv->output_limit[i].val_qpsk;
++		chan->val_16qam = priv->output_limit[i].val_16qam;
++		chan->val_64qam = priv->output_limit[i].val_64qam;
++		break;
++	}
++	if (i == priv->output_limit_len)
++		goto err;
++
++	chan->pa_points_per_curve = priv->curve_data->points_per_channel;
++
++	entry = priv->curve_data->data;
++	for (i = 0; i < priv->curve_data->channels; i++) {
++		if (*((__le16 *)entry) != freq) {
++			entry += sizeof(__le16);
++			entry += sizeof(struct pda_pa_curve_data_sample_rev1) *
++				 chan->pa_points_per_curve;
++			continue;
++		}
++
++		entry += sizeof(__le16);
++		memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
++		       chan->pa_points_per_curve);
++		break;
++	}
++
++	memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4);
++
++	priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1);
++	return 0;
++
++ err:
++	printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
++	kfree(hdr);
++	return -EINVAL;
++}
++
++static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
++{
++	struct p54_common *priv = dev->priv;
++	struct p54_control_hdr *hdr;
++	struct p54_tx_control_led *led;
++
++	hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
++		      priv->tx_hdr_len, GFP_KERNEL);
++	if (!hdr)
++		return -ENOMEM;
++
++	hdr = (void *)hdr + priv->tx_hdr_len;
++	hdr->magic1 = cpu_to_le16(0x8001);
++	hdr->len = cpu_to_le16(sizeof(*led));
++	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
++	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL);
++
++	led = (struct p54_tx_control_led *) hdr->data;
++	led->mode = cpu_to_le16(mode);
++	led->led_permanent = cpu_to_le16(link);
++	led->led_temporary = cpu_to_le16(act);
++	led->duration = cpu_to_le16(1000);
++
++	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);
++
++	return 0;
++}
++
++#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop)	\
++do {	 							\
++	queue.aifs = cpu_to_le16(ai_fs);			\
++	queue.cwmin = cpu_to_le16(cw_min);			\
++	queue.cwmax = cpu_to_le16(cw_max);			\
++	queue.txop = cpu_to_le16(_txop);			\
++} while(0)
++
++static void p54_init_vdcf(struct ieee80211_hw *dev)
++{
++	struct p54_common *priv = dev->priv;
++	struct p54_control_hdr *hdr;
++	struct p54_tx_control_vdcf *vdcf;
++
++	/* all USB V1 adapters need a extra headroom */
++	hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
++	hdr->magic1 = cpu_to_le16(0x8001);
++	hdr->len = cpu_to_le16(sizeof(*vdcf));
++	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
++	hdr->req_id = cpu_to_le32(priv->rx_start);
++
++	vdcf = (struct p54_tx_control_vdcf *) hdr->data;
++
++	P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47);
++	P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94);
++	P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0);
++	P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0);
++}
++
++static void p54_set_vdcf(struct ieee80211_hw *dev)
++{
++	struct p54_common *priv = dev->priv;
++	struct p54_control_hdr *hdr;
++	struct p54_tx_control_vdcf *vdcf;
++
++	hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
++
++	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL);
++
++	vdcf = (struct p54_tx_control_vdcf *) hdr->data;
++
++	if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
++		vdcf->slottime = 9;
++		vdcf->magic1 = 0x00;
++		vdcf->magic2 = 0x10;
++	} else {
++		vdcf->slottime = 20;
++		vdcf->magic1 = 0x0a;
++		vdcf->magic2 = 0x06;
++	}
++
++	/* (see prism54/isl_oid.h for further details) */
++	vdcf->frameburst = cpu_to_le16(0);
++
++	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
++}
++
++static int p54_start(struct ieee80211_hw *dev)
++{
++	struct p54_common *priv = dev->priv;
++	int err;
++
++	err = priv->open(dev);
++	if (!err)
++		priv->mode = IEEE80211_IF_TYPE_MNTR;
++
++	return err;
++}
++
++static void p54_stop(struct ieee80211_hw *dev)
++{
++	struct p54_common *priv = dev->priv;
++	struct sk_buff *skb;
++	while ((skb = skb_dequeue(&priv->tx_queue))) {
++		struct memrecord *range = (struct memrecord *)&skb->cb;
++		if (range->control)
++			kfree(range->control);
++		kfree_skb(skb);
++	}
++	priv->stop(dev);
++	priv->mode = IEEE80211_IF_TYPE_INVALID;
++}
++
++static int p54_add_interface(struct ieee80211_hw *dev,
++			     struct ieee80211_if_init_conf *conf)
++{
++	struct p54_common *priv = dev->priv;
++
++	if (priv->mode != IEEE80211_IF_TYPE_MNTR)
++		return -EOPNOTSUPP;
++
++	switch (conf->type) {
++	case IEEE80211_IF_TYPE_STA:
++		priv->mode = conf->type;
++		break;
++	default:
++		return -EOPNOTSUPP;
++	}
++
++	memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
++
++	p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642);
++	p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642);
++
++	switch (conf->type) {
++	case IEEE80211_IF_TYPE_STA:
++		p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0);
++		break;
++	default:
++		BUG();	/* impossible */
++		break;
++	}
++
++	p54_set_leds(dev, 1, 0, 0);
++
++	return 0;
++}
++
++static void p54_remove_interface(struct ieee80211_hw *dev,
++				 struct ieee80211_if_init_conf *conf)
++{
++	struct p54_common *priv = dev->priv;
++	priv->mode = IEEE80211_IF_TYPE_MNTR;
++	memset(priv->mac_addr, 0, ETH_ALEN);
++	p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0);
++}
++
++static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
++{
++	int ret;
++
++	ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
++	p54_set_vdcf(dev);
++	return ret;
++}
++
++static int p54_config_interface(struct ieee80211_hw *dev,
++				struct ieee80211_vif *vif,
++				struct ieee80211_if_conf *conf)
++{
++	struct p54_common *priv = dev->priv;
++
++	p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
++	p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
++	p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
++	memcpy(priv->bssid, conf->bssid, ETH_ALEN);
++	return 0;
++}
++
++static void p54_configure_filter(struct ieee80211_hw *dev,
++				 unsigned int changed_flags,
++				 unsigned int *total_flags,
++				 int mc_count, struct dev_mc_list *mclist)
++{
++	struct p54_common *priv = dev->priv;
++
++	*total_flags &= FIF_BCN_PRBRESP_PROMISC;
++
++	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
++		if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
++			p54_set_filter(dev, 0, priv->mac_addr,
++				       NULL, 2, 0, 0, 0);
++		else
++			p54_set_filter(dev, 0, priv->mac_addr,
++				       priv->bssid, 2, 0, 0, 0);
++	}
++}
++
++static int p54_conf_tx(struct ieee80211_hw *dev, int queue,
++		       const struct ieee80211_tx_queue_params *params)
++{
++	struct p54_common *priv = dev->priv;
++	struct p54_tx_control_vdcf *vdcf;
++
++	vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *)
++		((void *)priv->cached_vdcf + priv->tx_hdr_len))->data);
++
++	if ((params) && !((queue < 0) || (queue > 4))) {
++		P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
++			params->cw_min, params->cw_max, params->txop);
++	} else
++		return -EINVAL;
++
++	p54_set_vdcf(dev);
++
++	return 0;
++}
++
++static int p54_get_stats(struct ieee80211_hw *dev,
++			 struct ieee80211_low_level_stats *stats)
++{
++	/* TODO */
++	return 0;
++}
++
++static int p54_get_tx_stats(struct ieee80211_hw *dev,
++			    struct ieee80211_tx_queue_stats *stats)
++{
++	struct p54_common *priv = dev->priv;
++	unsigned int i;
++
++	for (i = 0; i < dev->queues; i++)
++		memcpy(&stats->data[i], &priv->tx_stats.data[i],
++			sizeof(stats->data[i]));
++
++	return 0;
++}
++
++static const struct ieee80211_ops p54_ops = {
++	.tx			= p54_tx,
++	.start			= p54_start,
++	.stop			= p54_stop,
++	.add_interface		= p54_add_interface,
++	.remove_interface	= p54_remove_interface,
++	.config			= p54_config,
++	.config_interface	= p54_config_interface,
++	.configure_filter	= p54_configure_filter,
++	.conf_tx		= p54_conf_tx,
++	.get_stats		= p54_get_stats,
++	.get_tx_stats		= p54_get_tx_stats
++};
++
++struct ieee80211_hw *p54_init_common(size_t priv_data_len)
++{
++	struct ieee80211_hw *dev;
++	struct p54_common *priv;
++
++	dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
++	if (!dev)
++		return NULL;
++
++	priv = dev->priv;
++	priv->mode = IEEE80211_IF_TYPE_INVALID;
++	skb_queue_head_init(&priv->tx_queue);
++	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
++	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
++		    IEEE80211_HW_RX_INCLUDES_FCS;
++	dev->channel_change_time = 1000;	/* TODO: find actual value */
++	dev->max_rssi = 127;
++
++	priv->tx_stats.data[0].limit = 5;
++	dev->queues = 1;
++
++	dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
++				 sizeof(struct p54_tx_control_allocdata);
++
++        priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) +
++              priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL);
++
++	if (!priv->cached_vdcf) {
++		ieee80211_free_hw(dev);
++		return NULL;
++	}
++
++	p54_init_vdcf(dev);
++
++	return dev;
++}
++EXPORT_SYMBOL_GPL(p54_init_common);
++
++void p54_free_common(struct ieee80211_hw *dev)
++{
++	struct p54_common *priv = dev->priv;
++	kfree(priv->iq_autocal);
++	kfree(priv->output_limit);
++	kfree(priv->curve_data);
++	kfree(priv->cached_vdcf);
++}
++EXPORT_SYMBOL_GPL(p54_free_common);
++
++static int __init p54_init(void)
++{
++	return 0;
++}
++
++static void __exit p54_exit(void)
++{
++}
++
++module_init(p54_init);
++module_exit(p54_exit);
+diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
+new file mode 100644
+index 0000000..c15b56e
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54common.h
+@@ -0,0 +1,254 @@
++#ifndef PRISM54COMMON_H
++#define PRISM54COMMON_H
++
++/*
++ * Common code specific definitions for mac80211 Prism54 drivers
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ * Copyright (c) 2007, Christian Lamparter <chunkeey at web.de>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++struct bootrec {
++	__le32 code;
++	__le32 len;
++	u32 data[0];
++} __attribute__((packed));
++
++struct bootrec_exp_if {
++	__le16 role;
++	__le16 if_id;
++	__le16 variant;
++	__le16 btm_compat;
++	__le16 top_compat;
++} __attribute__((packed));
++
++#define BR_CODE_MIN			0x80000000
++#define BR_CODE_COMPONENT_ID		0x80000001
++#define BR_CODE_COMPONENT_VERSION	0x80000002
++#define BR_CODE_DEPENDENT_IF		0x80000003
++#define BR_CODE_EXPOSED_IF		0x80000004
++#define BR_CODE_DESCR			0x80000101
++#define BR_CODE_MAX			0x8FFFFFFF
++#define BR_CODE_END_OF_BRA		0xFF0000FF
++#define LEGACY_BR_CODE_END_OF_BRA	0xFFFFFFFF
++
++#define FW_FMAC 0x464d4143
++#define FW_LM86 0x4c4d3836
++#define FW_LM87 0x4c4d3837
++#define FW_LM20 0x4c4d3230
++
++/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
++
++struct pda_entry {
++	__le16 len;	/* includes both code and data */
++	__le16 code;
++	u8 data[0];
++} __attribute__ ((packed));
++
++struct eeprom_pda_wrap {
++	__le32 magic;
++	__le16 pad;
++	__le16 len;
++	__le32 arm_opcode;
++	u8 data[0];
++} __attribute__ ((packed));
++
++struct pda_iq_autocal_entry {
++        __le16 freq;
++        __le16 iq_param[4];
++} __attribute__ ((packed));
++
++struct pda_channel_output_limit {
++	__le16 freq;
++	u8 val_bpsk;
++	u8 val_qpsk;
++	u8 val_16qam;
++	u8 val_64qam;
++	u8 rate_set_mask;
++	u8 rate_set_size;
++} __attribute__ ((packed));
++
++struct pda_pa_curve_data_sample_rev0 {
++	u8 rf_power;
++	u8 pa_detector;
++	u8 pcv;
++} __attribute__ ((packed));
++
++struct pda_pa_curve_data_sample_rev1 {
++	u8 rf_power;
++	u8 pa_detector;
++	u8 data_barker;
++	u8 data_bpsk;
++	u8 data_qpsk;
++	u8 data_16qam;
++	u8 data_64qam;
++	u8 padding;
++} __attribute__ ((packed));
++
++struct pda_pa_curve_data {
++	u8 cal_method_rev;
++	u8 channels;
++	u8 points_per_channel;
++	u8 padding;
++	u8 data[0];
++} __attribute__ ((packed));
++
++/*
++ * this defines the PDR codes used to build PDAs as defined in document
++ * number 553155. The current implementation mirrors version 1.1 of the
++ * document and lists only PDRs supported by the ARM platform.
++ */
++
++/* common and choice range (0x0000 - 0x0fff) */
++#define PDR_END					0x0000
++#define PDR_MANUFACTURING_PART_NUMBER		0x0001
++#define PDR_PDA_VERSION				0x0002
++#define PDR_NIC_SERIAL_NUMBER			0x0003
++
++#define PDR_MAC_ADDRESS				0x0101
++#define PDR_REGULATORY_DOMAIN_LIST		0x0103
++#define PDR_TEMPERATURE_TYPE			0x0107
++
++#define PDR_PRISM_PCI_IDENTIFIER		0x0402
++
++/* ARM range (0x1000 - 0x1fff) */
++#define PDR_COUNTRY_INFORMATION			0x1000
++#define PDR_INTERFACE_LIST			0x1001
++#define PDR_HARDWARE_PLATFORM_COMPONENT_ID	0x1002
++#define PDR_OEM_NAME				0x1003
++#define PDR_PRODUCT_NAME			0x1004
++#define PDR_UTF8_OEM_NAME			0x1005
++#define PDR_UTF8_PRODUCT_NAME			0x1006
++#define PDR_COUNTRY_LIST			0x1007
++#define PDR_DEFAULT_COUNTRY			0x1008
++
++#define PDR_ANTENNA_GAIN			0x1100
++
++#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA	0x1901
++#define PDR_RSSI_LINEAR_APPROXIMATION		0x1902
++#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS	0x1903
++#define PDR_PRISM_PA_CAL_CURVE_DATA		0x1904
++#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND	0x1905
++#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION		0x1906
++#define PDR_REGULATORY_POWER_LIMITS		0x1907
++#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED	0x1908
++#define PDR_RADIATED_TRANSMISSION_CORRECTION	0x1909
++#define PDR_PRISM_TX_IQ_CALIBRATION		0x190a
++
++/* reserved range (0x2000 - 0x7fff) */
++
++/* customer range (0x8000 - 0xffff) */
++#define PDR_BASEBAND_REGISTERS			0x8000
++#define PDR_PER_CHANNEL_BASEBAND_REGISTERS	0x8001
++
++/* stored in skb->cb */
++struct memrecord {
++	u32 start_addr;
++	u32 end_addr;
++	struct ieee80211_tx_control *control;
++};
++
++struct p54_eeprom_lm86 {
++	__le16 offset;
++	__le16 len;
++	u8 data[0];
++} __attribute__ ((packed));
++
++struct p54_rx_hdr {
++	__le16 magic;
++	__le16 len;
++	__le16 freq;
++	u8 antenna;
++	u8 rate;
++	u8 rssi;
++	u8 quality;
++	u16 unknown2;
++	__le64 timestamp;
++	u8 data[0];
++} __attribute__ ((packed));
++
++struct p54_frame_sent_hdr {
++	u8 status;
++	u8 retries;
++	__le16 ack_rssi;
++	__le16 seq;
++	u16 rate;
++} __attribute__ ((packed));
++
++struct p54_tx_control_allocdata {
++	u8 rateset[8];
++	u16 padding;
++	u8 wep_key_present;
++	u8 wep_key_len;
++	u8 wep_key[16];
++	__le32 frame_type;
++	u32 padding2;
++	__le16 magic4;
++	u8 antenna;
++	u8 output_power;
++	__le32 magic5;
++	u8 align[0];
++} __attribute__ ((packed));
++
++struct p54_tx_control_filter {
++	__le16 filter_type;
++	u8 dst[ETH_ALEN];
++	u8 src[ETH_ALEN];
++	u8 antenna;
++	u8 debug;
++	__le32 magic3;
++	u8 rates[8];	// FIXME: what's this for?
++	__le32 rx_addr;
++	__le16 max_rx;
++	__le16 rxhw;
++	__le16 magic8;
++	__le16 magic9;
++} __attribute__ ((packed));
++
++struct p54_tx_control_channel {
++	__le16 magic1;
++	__le16 magic2;
++	u8 padding1[20];
++	struct pda_iq_autocal_entry iq_autocal;
++	u8 pa_points_per_curve;
++	u8 val_barker;
++	u8 val_bpsk;
++	u8 val_qpsk;
++	u8 val_16qam;
++	u8 val_64qam;
++	struct pda_pa_curve_data_sample_rev1 curve_data[0];
++	/* additional padding/data after curve_data */
++} __attribute__ ((packed));
++
++struct p54_tx_control_led {
++	__le16 mode;
++	__le16 led_temporary;
++	__le16 led_permanent;
++	__le16 duration;
++} __attribute__ ((packed));
++
++struct p54_tx_vdcf_queues {
++	__le16 aifs;
++	__le16 cwmin;
++	__le16 cwmax;
++	__le16 txop;
++} __attribute__ ((packed));
++
++struct p54_tx_control_vdcf {
++	u8 padding;
++	u8 slottime;
++	u8 magic1;
++	u8 magic2;
++	struct p54_tx_vdcf_queues queue[8];
++	u8 pad2[4];
++	__le16 frameburst;
++} __attribute__ ((packed));
++
++#endif /* PRISM54COMMON_H */
+diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
+new file mode 100644
+index 0000000..fa52772
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54pci.c
+@@ -0,0 +1,697 @@
++
++/*
++ * Linux device driver for PCI based Prism54
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note at m4x.org>, et al.
++ *
++ * This program is free software; you can redistribute it 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/pci.h>
++#include <linux/firmware.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/completion.h>
++#include <net/mac80211.h>
++
++#include "p54.h"
++#include "p54pci.h"
++
++MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
++MODULE_DESCRIPTION("Prism54 PCI wireless driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("prism54pci");
++
++static struct pci_device_id p54p_table[] __devinitdata = {
++	/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
++	{ PCI_DEVICE(0x1260, 0x3890) },
++	/* 3COM 3CRWE154G72 Wireless LAN adapter */
++	{ PCI_DEVICE(0x10b7, 0x6001) },
++	/* Intersil PRISM Indigo Wireless LAN adapter */
++	{ PCI_DEVICE(0x1260, 0x3877) },
++	/* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
++	{ PCI_DEVICE(0x1260, 0x3886) },
++	{ },
++};
++
++MODULE_DEVICE_TABLE(pci, p54p_table);
++
++static int p54p_upload_firmware(struct ieee80211_hw *dev)
++{
++	struct p54p_priv *priv = dev->priv;
++	const struct firmware *fw_entry = NULL;
++	__le32 reg;
++	int err;
++	__le32 *data;
++	u32 remains, left, device_addr;
++
++	P54P_WRITE(int_enable, cpu_to_le32(0));
++	P54P_READ(int_enable);
++	udelay(10);
++
++	reg = P54P_READ(ctrl_stat);
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
++	P54P_WRITE(ctrl_stat, reg);
++	P54P_READ(ctrl_stat);
++	udelay(10);
++
++	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
++	P54P_WRITE(ctrl_stat, reg);
++	wmb();
++	udelay(10);
++
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++	P54P_WRITE(ctrl_stat, reg);
++	wmb();
++
++	mdelay(50);
++
++	err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
++	if (err) {
++		printk(KERN_ERR "%s (prism54pci): cannot find firmware "
++		       "(isl3886)\n", pci_name(priv->pdev));
++		return err;
++	}
++
++	p54_parse_firmware(dev, fw_entry);
++
++	data = (__le32 *) fw_entry->data;
++	remains = fw_entry->size;
++	device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
++	while (remains) {
++		u32 i = 0;
++		left = min((u32)0x1000, remains);
++		P54P_WRITE(direct_mem_base, cpu_to_le32(device_addr));
++		P54P_READ(int_enable);
++
++		device_addr += 0x1000;
++		while (i < left) {
++			P54P_WRITE(direct_mem_win[i], *data++);
++			i += sizeof(u32);
++		}
++
++		remains -= left;
++		P54P_READ(int_enable);
++	}
++
++	release_firmware(fw_entry);
++
++	reg = P54P_READ(ctrl_stat);
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
++	P54P_WRITE(ctrl_stat, reg);
++	P54P_READ(ctrl_stat);
++	udelay(10);
++
++	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
++	P54P_WRITE(ctrl_stat, reg);
++	wmb();
++	udelay(10);
++
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++	P54P_WRITE(ctrl_stat, reg);
++	wmb();
++	udelay(10);
++
++	return 0;
++}
++
++static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id)
++{
++	struct p54p_priv *priv = (struct p54p_priv *) dev_id;
++	__le32 reg;
++
++	reg = P54P_READ(int_ident);
++	P54P_WRITE(int_ack, reg);
++
++	if (reg & P54P_READ(int_enable))
++		complete(&priv->boot_comp);
++
++	return IRQ_HANDLED;
++}
++
++static int p54p_read_eeprom(struct ieee80211_hw *dev)
++{
++	struct p54p_priv *priv = dev->priv;
++	struct p54p_ring_control *ring_control = priv->ring_control;
++	int err;
++	struct p54_control_hdr *hdr;
++	void *eeprom;
++	dma_addr_t rx_mapping, tx_mapping;
++	u16 alen;
++
++	init_completion(&priv->boot_comp);
++	err = request_irq(priv->pdev->irq, &p54p_simple_interrupt,
++			  IRQF_SHARED, "prism54pci", priv);
++	if (err) {
++		printk(KERN_ERR "%s (prism54pci): failed to register IRQ handler\n",
++		       pci_name(priv->pdev));
++		return err;
++	}
++
++	eeprom = kmalloc(0x2010 + EEPROM_READBACK_LEN, GFP_KERNEL);
++	if (!eeprom) {
++		printk(KERN_ERR "%s (prism54pci): no memory for eeprom!\n",
++		       pci_name(priv->pdev));
++		err = -ENOMEM;
++		goto out;
++	}
++
++	memset(ring_control, 0, sizeof(*ring_control));
++	P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
++	P54P_READ(ring_control_base);
++	udelay(10);
++
++	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
++	P54P_READ(int_enable);
++	udelay(10);
++
++	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
++
++	if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
++		printk(KERN_ERR "%s (prism54pci): Cannot boot firmware!\n",
++		       pci_name(priv->pdev));
++		err = -EINVAL;
++		goto out;
++	}
++
++	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
++	P54P_READ(int_enable);
++
++	hdr = eeprom + 0x2010;
++	p54_fill_eeprom_readback(hdr);
++	hdr->req_id = cpu_to_le32(priv->common.rx_start);
++
++	rx_mapping = pci_map_single(priv->pdev, eeprom,
++				    0x2010, PCI_DMA_FROMDEVICE);
++	tx_mapping = pci_map_single(priv->pdev, (void *)hdr,
++				    EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
++
++	ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping);
++	ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010);
++	ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping);
++	ring_control->tx_data[0].device_addr = hdr->req_id;
++	ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN);
++
++	ring_control->host_idx[2] = cpu_to_le32(1);
++	ring_control->host_idx[1] = cpu_to_le32(1);
++
++	wmb();
++	mdelay(100);
++	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
++
++	wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
++	wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
++
++	pci_unmap_single(priv->pdev, tx_mapping,
++			 EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
++	pci_unmap_single(priv->pdev, rx_mapping,
++			 0x2010, PCI_DMA_FROMDEVICE);
++
++	alen = le16_to_cpu(ring_control->rx_mgmt[0].len);
++	if (le32_to_cpu(ring_control->device_idx[2]) != 1 ||
++	    alen < 0x10) {
++		printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n",
++		       pci_name(priv->pdev));
++		err = -EINVAL;
++		goto out;
++	}
++
++	p54_parse_eeprom(dev, (u8 *)eeprom + 0x10, alen - 0x10);
++
++ out:
++	kfree(eeprom);
++	P54P_WRITE(int_enable, cpu_to_le32(0));
++	P54P_READ(int_enable);
++	udelay(10);
++	free_irq(priv->pdev->irq, priv);
++	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
++	return err;
++}
++
++static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
++{
++	struct p54p_priv *priv = dev->priv;
++	struct p54p_ring_control *ring_control = priv->ring_control;
++	u32 limit, host_idx, idx;
++
++	host_idx = le32_to_cpu(ring_control->host_idx[0]);
++	limit = host_idx;
++	limit -= le32_to_cpu(ring_control->device_idx[0]);
++	limit = ARRAY_SIZE(ring_control->rx_data) - limit;
++
++	idx = host_idx % ARRAY_SIZE(ring_control->rx_data);
++	while (limit-- > 1) {
++		struct p54p_desc *desc = &ring_control->rx_data[idx];
++
++		if (!desc->host_addr) {
++			struct sk_buff *skb;
++			dma_addr_t mapping;
++			skb = dev_alloc_skb(MAX_RX_SIZE);
++			if (!skb)
++				break;
++
++			mapping = pci_map_single(priv->pdev,
++						 skb_tail_pointer(skb),
++						 MAX_RX_SIZE,
++						 PCI_DMA_FROMDEVICE);
++			desc->host_addr = cpu_to_le32(mapping);
++			desc->device_addr = 0;	// FIXME: necessary?
++			desc->len = cpu_to_le16(MAX_RX_SIZE);
++			desc->flags = 0;
++			priv->rx_buf[idx] = skb;
++		}
++
++		idx++;
++		host_idx++;
++		idx %= ARRAY_SIZE(ring_control->rx_data);
++	}
++
++	wmb();
++	ring_control->host_idx[0] = cpu_to_le32(host_idx);
++}
++
++static irqreturn_t p54p_interrupt(int irq, void *dev_id)
++{
++	struct ieee80211_hw *dev = dev_id;
++	struct p54p_priv *priv = dev->priv;
++	struct p54p_ring_control *ring_control = priv->ring_control;
++	__le32 reg;
++
++	spin_lock(&priv->lock);
++	reg = P54P_READ(int_ident);
++	if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
++		spin_unlock(&priv->lock);
++		return IRQ_HANDLED;
++	}
++
++	P54P_WRITE(int_ack, reg);
++
++	reg &= P54P_READ(int_enable);
++
++	if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
++		struct p54p_desc *desc;
++		u32 idx, i;
++		i = priv->tx_idx;
++		i %= ARRAY_SIZE(ring_control->tx_data);
++		priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
++		idx %= ARRAY_SIZE(ring_control->tx_data);
++
++		while (i != idx) {
++			desc = &ring_control->tx_data[i];
++			if (priv->tx_buf[i]) {
++				kfree(priv->tx_buf[i]);
++				priv->tx_buf[i] = NULL;
++			}
++
++			pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
++					 le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
++
++			desc->host_addr = 0;
++			desc->device_addr = 0;
++			desc->len = 0;
++			desc->flags = 0;
++
++			i++;
++			i %= ARRAY_SIZE(ring_control->tx_data);
++		}
++
++		i = priv->rx_idx;
++		i %= ARRAY_SIZE(ring_control->rx_data);
++		priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
++		idx %= ARRAY_SIZE(ring_control->rx_data);
++		while (i != idx) {
++			u16 len;
++			struct sk_buff *skb;
++			desc = &ring_control->rx_data[i];
++			len = le16_to_cpu(desc->len);
++			skb = priv->rx_buf[i];
++
++			skb_put(skb, len);
++
++			if (p54_rx(dev, skb)) {
++				pci_unmap_single(priv->pdev,
++						 le32_to_cpu(desc->host_addr),
++						 MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
++
++				priv->rx_buf[i] = NULL;
++				desc->host_addr = 0;
++			} else {
++				skb_trim(skb, 0);
++				desc->len = cpu_to_le16(MAX_RX_SIZE);
++			}
++
++			i++;
++			i %= ARRAY_SIZE(ring_control->rx_data);
++		}
++
++		p54p_refill_rx_ring(dev);
++
++		wmb();
++		P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
++	} else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
++		complete(&priv->boot_comp);
++
++	spin_unlock(&priv->lock);
++
++	return reg ? IRQ_HANDLED : IRQ_NONE;
++}
++
++static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
++		    size_t len, int free_on_tx)
++{
++	struct p54p_priv *priv = dev->priv;
++	struct p54p_ring_control *ring_control = priv->ring_control;
++	unsigned long flags;
++	struct p54p_desc *desc;
++	dma_addr_t mapping;
++	u32 device_idx, idx, i;
++
++	spin_lock_irqsave(&priv->lock, flags);
++
++	device_idx = le32_to_cpu(ring_control->device_idx[1]);
++	idx = le32_to_cpu(ring_control->host_idx[1]);
++	i = idx % ARRAY_SIZE(ring_control->tx_data);
++
++	mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
++	desc = &ring_control->tx_data[i];
++	desc->host_addr = cpu_to_le32(mapping);
++	desc->device_addr = data->req_id;
++	desc->len = cpu_to_le16(len);
++	desc->flags = 0;
++
++	wmb();
++	ring_control->host_idx[1] = cpu_to_le32(idx + 1);
++
++	if (free_on_tx)
++		priv->tx_buf[i] = data;
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
++	P54P_READ(dev_int);
++
++	/* FIXME: unlikely to happen because the device usually runs out of
++	   memory before we fill the ring up, but we can make it impossible */
++	if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
++		printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
++}
++
++static int p54p_open(struct ieee80211_hw *dev)
++{
++	struct p54p_priv *priv = dev->priv;
++	int err;
++
++	init_completion(&priv->boot_comp);
++	err = request_irq(priv->pdev->irq, &p54p_interrupt,
++			  IRQF_SHARED, "prism54pci", dev);
++	if (err) {
++		printk(KERN_ERR "%s: failed to register IRQ handler\n",
++		       wiphy_name(dev->wiphy));
++		return err;
++	}
++
++	memset(priv->ring_control, 0, sizeof(*priv->ring_control));
++	priv->rx_idx = priv->tx_idx = 0;
++	p54p_refill_rx_ring(dev);
++
++	p54p_upload_firmware(dev);
++
++	P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
++	P54P_READ(ring_control_base);
++	wmb();
++	udelay(10);
++
++	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
++	P54P_READ(int_enable);
++	wmb();
++	udelay(10);
++
++	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
++	P54P_READ(dev_int);
++
++	if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
++		printk(KERN_ERR "%s: Cannot boot firmware!\n",
++		       wiphy_name(dev->wiphy));
++		free_irq(priv->pdev->irq, dev);
++		return -ETIMEDOUT;
++	}
++
++	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
++	P54P_READ(int_enable);
++	wmb();
++	udelay(10);
++
++	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
++	P54P_READ(dev_int);
++	wmb();
++	udelay(10);
++
++	return 0;
++}
++
++static void p54p_stop(struct ieee80211_hw *dev)
++{
++	struct p54p_priv *priv = dev->priv;
++	struct p54p_ring_control *ring_control = priv->ring_control;
++	unsigned int i;
++	struct p54p_desc *desc;
++
++	P54P_WRITE(int_enable, cpu_to_le32(0));
++	P54P_READ(int_enable);
++	udelay(10);
++
++	free_irq(priv->pdev->irq, dev);
++
++	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
++
++	for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) {
++		desc = &ring_control->rx_data[i];
++		if (desc->host_addr)
++			pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
++					 MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
++		kfree_skb(priv->rx_buf[i]);
++		priv->rx_buf[i] = NULL;
++	}
++
++	for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) {
++		desc = &ring_control->tx_data[i];
++		if (desc->host_addr)
++			pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
++					 le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
++
++		kfree(priv->tx_buf[i]);
++		priv->tx_buf[i] = NULL;
++	}
++
++	memset(ring_control, 0, sizeof(ring_control));
++}
++
++static int __devinit p54p_probe(struct pci_dev *pdev,
++				const struct pci_device_id *id)
++{
++	struct p54p_priv *priv;
++	struct ieee80211_hw *dev;
++	unsigned long mem_addr, mem_len;
++	int err;
++	DECLARE_MAC_BUF(mac);
++
++	err = pci_enable_device(pdev);
++	if (err) {
++		printk(KERN_ERR "%s (prism54pci): Cannot enable new PCI device\n",
++		       pci_name(pdev));
++		return err;
++	}
++
++	mem_addr = pci_resource_start(pdev, 0);
++	mem_len = pci_resource_len(pdev, 0);
++	if (mem_len < sizeof(struct p54p_csr)) {
++		printk(KERN_ERR "%s (prism54pci): Too short PCI resources\n",
++		       pci_name(pdev));
++		pci_disable_device(pdev);
++		return err;
++	}
++
++	err = pci_request_regions(pdev, "prism54pci");
++	if (err) {
++		printk(KERN_ERR "%s (prism54pci): Cannot obtain PCI resources\n",
++		       pci_name(pdev));
++		return err;
++	}
++
++	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
++	    pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
++		printk(KERN_ERR "%s (prism54pci): No suitable DMA available\n",
++		       pci_name(pdev));
++		goto err_free_reg;
++	}
++
++	pci_set_master(pdev);
++	pci_try_set_mwi(pdev);
++
++	pci_write_config_byte(pdev, 0x40, 0);
++	pci_write_config_byte(pdev, 0x41, 0);
++
++	dev = p54_init_common(sizeof(*priv));
++	if (!dev) {
++		printk(KERN_ERR "%s (prism54pci): ieee80211 alloc failed\n",
++		       pci_name(pdev));
++		err = -ENOMEM;
++		goto err_free_reg;
++	}
++
++	priv = dev->priv;
++	priv->pdev = pdev;
++
++	SET_IEEE80211_DEV(dev, &pdev->dev);
++	pci_set_drvdata(pdev, dev);
++
++	priv->map = ioremap(mem_addr, mem_len);
++	if (!priv->map) {
++		printk(KERN_ERR "%s (prism54pci): Cannot map device memory\n",
++		       pci_name(pdev));
++		err = -EINVAL;	// TODO: use a better error code?
++		goto err_free_dev;
++	}
++
++	priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control),
++						  &priv->ring_control_dma);
++	if (!priv->ring_control) {
++		printk(KERN_ERR "%s (prism54pci): Cannot allocate rings\n",
++		       pci_name(pdev));
++		err = -ENOMEM;
++		goto err_iounmap;
++	}
++	memset(priv->ring_control, 0, sizeof(*priv->ring_control));
++
++	err = p54p_upload_firmware(dev);
++	if (err)
++		goto err_free_desc;
++
++	err = p54p_read_eeprom(dev);
++	if (err)
++		goto err_free_desc;
++
++	priv->common.open = p54p_open;
++	priv->common.stop = p54p_stop;
++	priv->common.tx = p54p_tx;
++
++	spin_lock_init(&priv->lock);
++
++	err = ieee80211_register_hw(dev);
++	if (err) {
++		printk(KERN_ERR "%s (prism54pci): Cannot register netdevice\n",
++		       pci_name(pdev));
++		goto err_free_common;
++	}
++
++	printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
++	       wiphy_name(dev->wiphy),
++	       print_mac(mac, dev->wiphy->perm_addr),
++	       priv->common.version);
++
++	return 0;
++
++ err_free_common:
++	p54_free_common(dev);
++
++ err_free_desc:
++	pci_free_consistent(pdev, sizeof(*priv->ring_control),
++			    priv->ring_control, priv->ring_control_dma);
++
++ err_iounmap:
++	iounmap(priv->map);
++
++ err_free_dev:
++	pci_set_drvdata(pdev, NULL);
++	ieee80211_free_hw(dev);
++
++ err_free_reg:
++	pci_release_regions(pdev);
++	pci_disable_device(pdev);
++	return err;
++}
++
++static void __devexit p54p_remove(struct pci_dev *pdev)
++{
++	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
++	struct p54p_priv *priv;
++
++	if (!dev)
++		return;
++
++	ieee80211_unregister_hw(dev);
++	priv = dev->priv;
++	pci_free_consistent(pdev, sizeof(*priv->ring_control),
++			    priv->ring_control, priv->ring_control_dma);
++	p54_free_common(dev);
++	iounmap(priv->map);
++	pci_release_regions(pdev);
++	pci_disable_device(pdev);
++	ieee80211_free_hw(dev);
++}
++
++#ifdef CONFIG_PM
++static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
++	struct p54p_priv *priv = dev->priv;
++
++	if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
++		ieee80211_stop_queues(dev);
++		p54p_stop(dev);
++	}
++
++	pci_save_state(pdev);
++	pci_set_power_state(pdev, pci_choose_state(pdev, state));
++	return 0;
++}
++
++static int p54p_resume(struct pci_dev *pdev)
++{
++	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
++	struct p54p_priv *priv = dev->priv;
++
++	pci_set_power_state(pdev, PCI_D0);
++	pci_restore_state(pdev);
++
++	if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
++		p54p_open(dev);
++		ieee80211_start_queues(dev);
++	}
++
++	return 0;
++}
++#endif /* CONFIG_PM */
++
++static struct pci_driver p54p_driver = {
++	.name		= "prism54pci",
++	.id_table	= p54p_table,
++	.probe		= p54p_probe,
++	.remove		= __devexit_p(p54p_remove),
++#ifdef CONFIG_PM
++	.suspend	= p54p_suspend,
++	.resume		= p54p_resume,
++#endif /* CONFIG_PM */
++};
++
++static int __init p54p_init(void)
++{
++	return pci_register_driver(&p54p_driver);
++}
++
++static void __exit p54p_exit(void)
++{
++	pci_unregister_driver(&p54p_driver);
++}
++
++module_init(p54p_init);
++module_exit(p54p_exit);
+diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
+new file mode 100644
+index 0000000..5bedd7a
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54pci.h
+@@ -0,0 +1,106 @@
++#ifndef PRISM54PCI_H
++#define PRISM54PCI_H
++
++/*
++ * Defines for PCI based mac80211 Prism54 driver
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* Device Interrupt register bits */
++#define ISL38XX_DEV_INT_RESET                   0x0001
++#define ISL38XX_DEV_INT_UPDATE                  0x0002
++#define ISL38XX_DEV_INT_WAKEUP                  0x0008
++#define ISL38XX_DEV_INT_SLEEP                   0x0010
++#define ISL38XX_DEV_INT_ABORT                   0x0020
++/* these two only used in USB */
++#define ISL38XX_DEV_INT_DATA                    0x0040
++#define ISL38XX_DEV_INT_MGMT                    0x0080
++
++#define ISL38XX_DEV_INT_PCIUART_CTS             0x4000
++#define ISL38XX_DEV_INT_PCIUART_DR              0x8000
++
++/* Interrupt Identification/Acknowledge/Enable register bits */
++#define ISL38XX_INT_IDENT_UPDATE		0x0002
++#define ISL38XX_INT_IDENT_INIT			0x0004
++#define ISL38XX_INT_IDENT_WAKEUP		0x0008
++#define ISL38XX_INT_IDENT_SLEEP			0x0010
++#define ISL38XX_INT_IDENT_PCIUART_CTS		0x4000
++#define ISL38XX_INT_IDENT_PCIUART_DR		0x8000
++
++/* Control/Status register bits */
++#define ISL38XX_CTRL_STAT_SLEEPMODE		0x00000200
++#define ISL38XX_CTRL_STAT_CLKRUN		0x00800000
++#define ISL38XX_CTRL_STAT_RESET			0x10000000
++#define ISL38XX_CTRL_STAT_RAMBOOT		0x20000000
++#define ISL38XX_CTRL_STAT_STARTHALTED		0x40000000
++#define ISL38XX_CTRL_STAT_HOST_OVERRIDE		0x80000000
++
++struct p54p_csr {
++	__le32 dev_int;
++	u8 unused_1[12];
++	__le32 int_ident;
++	__le32 int_ack;
++	__le32 int_enable;
++	u8 unused_2[4];
++	union {
++		__le32 ring_control_base;
++		__le32 gen_purp_com[2];
++	};
++	u8 unused_3[8];
++	__le32 direct_mem_base;
++	u8 unused_4[44];
++	__le32 dma_addr;
++	__le32 dma_len;
++	__le32 dma_ctrl;
++	u8 unused_5[12];
++	__le32 ctrl_stat;
++	u8 unused_6[1924];
++	u8 cardbus_cis[0x800];
++	u8 direct_mem_win[0x1000];
++} __attribute__ ((packed));
++
++/* usb backend only needs the register defines above */
++#ifndef PRISM54USB_H
++struct p54p_desc {
++	__le32 host_addr;
++	__le32 device_addr;
++	__le16 len;
++	__le16 flags;
++} __attribute__ ((packed));
++
++struct p54p_ring_control {
++	__le32 host_idx[4];
++	__le32 device_idx[4];
++	struct p54p_desc rx_data[8];
++	struct p54p_desc tx_data[32];
++	struct p54p_desc rx_mgmt[4];
++	struct p54p_desc tx_mgmt[4];
++} __attribute__ ((packed));
++
++#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r)
++#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r)
++
++struct p54p_priv {
++	struct p54_common common;
++	struct pci_dev *pdev;
++	struct p54p_csr __iomem *map;
++
++	spinlock_t lock;
++	struct p54p_ring_control *ring_control;
++	dma_addr_t ring_control_dma;
++	u32 rx_idx, tx_idx;
++	struct sk_buff *rx_buf[8];
++	void *tx_buf[32];
++	struct completion boot_comp;
++};
++
++#endif /* PRISM54USB_H */
++#endif /* PRISM54PCI_H */
+diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
+new file mode 100644
+index 0000000..98ddbb3
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54usb.c
+@@ -0,0 +1,910 @@
++
++/*
++ * Linux device driver for USB based Prism54
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it 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/usb.h>
++#include <linux/pci.h>
++#include <linux/firmware.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/crc32.h>
++#include <net/mac80211.h>
++
++#include "p54.h"
++#include "p54usb.h"
++
++MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
++MODULE_DESCRIPTION("Prism54 USB wireless driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("prism54usb");
++
++static struct usb_device_id p54u_table[] __devinitdata = {
++	/* Version 1 devices (pci chip + net2280) */
++	{USB_DEVICE(0x0506, 0x0a11)},	/* 3COM 3CRWE254G72 */
++	{USB_DEVICE(0x0707, 0xee06)},	/* SMC 2862W-G */
++	{USB_DEVICE(0x083a, 0x4501)},	/* Accton 802.11g WN4501 USB */
++	{USB_DEVICE(0x083a, 0x4502)},	/* Siemens Gigaset USB Adapter */
++	{USB_DEVICE(0x083a, 0x5501)},	/* Phillips CPWUA054 */
++	{USB_DEVICE(0x0846, 0x4200)},	/* Netgear WG121 */
++	{USB_DEVICE(0x0846, 0x4210)},	/* Netgear WG121 the second ? */
++	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */
++	{USB_DEVICE(0x0cde, 0x0006)},	/* Medion 40900, Roper Europe */
++	{USB_DEVICE(0x124a, 0x4023)},	/* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
++	{USB_DEVICE(0x1915, 0x2234)},	/* Linksys WUSB54G OEM */
++	{USB_DEVICE(0x1915, 0x2235)},	/* Linksys WUSB54G Portable OEM */
++	{USB_DEVICE(0x2001, 0x3701)},	/* DLink DWL-G120 Spinnaker */
++	{USB_DEVICE(0x2001, 0x3703)},	/* DLink DWL-G122 */
++	{USB_DEVICE(0x5041, 0x2234)},	/* Linksys WUSB54G */
++	{USB_DEVICE(0x5041, 0x2235)},	/* Linksys WUSB54G Portable */
++
++	/* Version 2 devices (3887) */
++	{USB_DEVICE(0x050d, 0x7050)},	/* Belkin F5D7050 ver 1000 */
++	{USB_DEVICE(0x0572, 0x2000)},	/* Cohiba Proto board */
++	{USB_DEVICE(0x0572, 0x2002)},	/* Cohiba Proto board */
++	{USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
++	{USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
++	{USB_DEVICE(0x0846, 0x4240)},	/* Netgear WG111 (v2) */
++	{USB_DEVICE(0x0915, 0x2000)},	/* Cohiba Proto board */
++	{USB_DEVICE(0x0915, 0x2002)},	/* Cohiba Proto board */
++	{USB_DEVICE(0x0baf, 0x0118)},   /* U.S. Robotics U5 802.11g Adapter*/
++	{USB_DEVICE(0x0bf8, 0x1009)},   /* FUJITSU E-5400 USB D1700*/
++	{USB_DEVICE(0x0cde, 0x0006)},   /* Medion MD40900 */
++	{USB_DEVICE(0x0cde, 0x0008)},	/* Sagem XG703A */
++	{USB_DEVICE(0x0d8e, 0x3762)},	/* DLink DWL-G120 Cohiba */
++	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */
++	{USB_DEVICE(0x124a, 0x4025)},	/* IOGear GWU513 (GW3887IK chip) */
++	{USB_DEVICE(0x13b1, 0x000a)},	/* Linksys WUSB54G ver 2 */
++	{USB_DEVICE(0x13B1, 0x000C)},	/* Linksys WUSB54AG */
++	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */
++	{USB_DEVICE(0x2001, 0x3704)},	/* DLink DWL-G122 rev A2 */
++	{USB_DEVICE(0x413c, 0x8102)},	/* Spinnaker DUT */
++	{USB_DEVICE(0x413c, 0x8104)},	/* Cohiba Proto board */
++	{}
++};
++
++MODULE_DEVICE_TABLE(usb, p54u_table);
++
++static void p54u_rx_cb(struct urb *urb)
++{
++	struct sk_buff *skb = (struct sk_buff *) urb->context;
++	struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
++	struct ieee80211_hw *dev = info->dev;
++	struct p54u_priv *priv = dev->priv;
++
++	if (unlikely(urb->status)) {
++		info->urb = NULL;
++		usb_free_urb(urb);
++		return;
++	}
++
++	skb_unlink(skb, &priv->rx_queue);
++	skb_put(skb, urb->actual_length);
++	if (!priv->hw_type)
++		skb_pull(skb, sizeof(struct net2280_tx_hdr));
++
++	if (p54_rx(dev, skb)) {
++		skb = dev_alloc_skb(MAX_RX_SIZE);
++		if (unlikely(!skb)) {
++			usb_free_urb(urb);
++			/* TODO check rx queue length and refill *somewhere* */
++			return;
++		}
++
++		info = (struct p54u_rx_info *) skb->cb;
++		info->urb = urb;
++		info->dev = dev;
++		urb->transfer_buffer = skb_tail_pointer(skb);
++		urb->context = skb;
++		skb_queue_tail(&priv->rx_queue, skb);
++	} else {
++		skb_trim(skb, 0);
++		skb_queue_tail(&priv->rx_queue, skb);
++	}
++
++	usb_submit_urb(urb, GFP_ATOMIC);
++}
++
++static void p54u_tx_cb(struct urb *urb)
++{
++	usb_free_urb(urb);
++}
++
++static void p54u_tx_free_cb(struct urb *urb)
++{
++	kfree(urb->transfer_buffer);
++	usb_free_urb(urb);
++}
++
++static int p54u_init_urbs(struct ieee80211_hw *dev)
++{
++	struct p54u_priv *priv = dev->priv;
++	struct urb *entry;
++	struct sk_buff *skb;
++	struct p54u_rx_info *info;
++
++	while (skb_queue_len(&priv->rx_queue) < 32) {
++		skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL);
++		if (!skb)
++			break;
++		entry = usb_alloc_urb(0, GFP_KERNEL);
++		if (!entry) {
++			kfree_skb(skb);
++			break;
++		}
++		usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb);
++		info = (struct p54u_rx_info *) skb->cb;
++		info->urb = entry;
++		info->dev = dev;
++		skb_queue_tail(&priv->rx_queue, skb);
++		usb_submit_urb(entry, GFP_KERNEL);
++	}
++
++	return 0;
++}
++
++static void p54u_free_urbs(struct ieee80211_hw *dev)
++{
++	struct p54u_priv *priv = dev->priv;
++	struct p54u_rx_info *info;
++	struct sk_buff *skb;
++
++	while ((skb = skb_dequeue(&priv->rx_queue))) {
++		info = (struct p54u_rx_info *) skb->cb;
++		if (!info->urb)
++			continue;
++
++		usb_kill_urb(info->urb);
++		kfree_skb(skb);
++	}
++}
++
++static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
++			 size_t len, int free_on_tx)
++{
++	struct p54u_priv *priv = dev->priv;
++	struct urb *addr_urb, *data_urb;
++
++	addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
++	if (!addr_urb)
++		return;
++
++	data_urb = usb_alloc_urb(0, GFP_ATOMIC);
++	if (!data_urb) {
++		usb_free_urb(addr_urb);
++		return;
++	}
++
++	usb_fill_bulk_urb(addr_urb, priv->udev,
++		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
++		sizeof(data->req_id), p54u_tx_cb, dev);
++	usb_fill_bulk_urb(data_urb, priv->udev,
++		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
++		free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
++
++	usb_submit_urb(addr_urb, GFP_ATOMIC);
++	usb_submit_urb(data_urb, GFP_ATOMIC);
++}
++
++static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
++			    size_t len, int free_on_tx)
++{
++	struct p54u_priv *priv = dev->priv;
++	struct urb *int_urb, *data_urb;
++	struct net2280_tx_hdr *hdr;
++	struct net2280_reg_write *reg;
++
++	reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
++	if (!reg)
++		return;
++
++	int_urb = usb_alloc_urb(0, GFP_ATOMIC);
++	if (!int_urb) {
++		kfree(reg);
++		return;
++	}
++
++	data_urb = usb_alloc_urb(0, GFP_ATOMIC);
++	if (!data_urb) {
++		kfree(reg);
++		usb_free_urb(int_urb);
++		return;
++	}
++
++	reg->port = cpu_to_le16(NET2280_DEV_U32);
++	reg->addr = cpu_to_le32(P54U_DEV_BASE);
++	reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
++
++	len += sizeof(*data);
++	hdr = (void *)data - sizeof(*hdr);
++	memset(hdr, 0, sizeof(*hdr));
++	hdr->device_addr = data->req_id;
++	hdr->len = cpu_to_le16(len);
++
++	usb_fill_bulk_urb(int_urb, priv->udev,
++		usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
++		p54u_tx_free_cb, dev);
++	usb_submit_urb(int_urb, GFP_ATOMIC);
++
++	usb_fill_bulk_urb(data_urb, priv->udev,
++		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
++		free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
++	usb_submit_urb(data_urb, GFP_ATOMIC);
++}
++
++static int p54u_write(struct p54u_priv *priv,
++		      struct net2280_reg_write *buf,
++		      enum net2280_op_type type,
++		      __le32 addr, __le32 val)
++{
++	unsigned int ep;
++	int alen;
++
++	if (type & 0x0800)
++		ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
++	else
++		ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
++
++	buf->port = cpu_to_le16(type);
++	buf->addr = addr;
++	buf->val = val;
++
++	return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
++}
++
++static int p54u_read(struct p54u_priv *priv, void *buf,
++		     enum net2280_op_type type,
++		     __le32 addr, __le32 *val)
++{
++	struct net2280_reg_read *read = buf;
++	__le32 *reg = buf;
++	unsigned int ep;
++	int alen, err;
++
++	if (type & 0x0800)
++		ep = P54U_PIPE_DEV;
++	else
++		ep = P54U_PIPE_BRG;
++
++	read->port = cpu_to_le16(type);
++	read->addr = addr;
++
++	err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
++			   read, sizeof(*read), &alen, 1000);
++	if (err)
++		return err;
++
++	err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
++			   reg, sizeof(*reg), &alen, 1000);
++	if (err)
++		return err;
++
++	*val = *reg;
++	return 0;
++}
++
++static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
++			 void *data, size_t len)
++{
++	int alen;
++	return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
++			    data, len, &alen, 2000);
++}
++
++static int p54u_read_eeprom(struct ieee80211_hw *dev)
++{
++	struct p54u_priv *priv = dev->priv;
++	void *buf;
++	struct p54_control_hdr *hdr;
++	int err, alen;
++	size_t offset = priv->hw_type ? 0x10 : 0x20;
++
++	buf = kmalloc(0x2020, GFP_KERNEL);
++	if (!buf) {
++		printk(KERN_ERR "prism54usb: cannot allocate memory for "
++		       "eeprom readback!\n");
++		return -ENOMEM;
++	}
++
++	if (priv->hw_type) {
++		*((u32 *) buf) = priv->common.rx_start;
++		err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
++		if (err) {
++			printk(KERN_ERR "prism54usb: addr send failed\n");
++			goto fail;
++		}
++	} else {
++		struct net2280_reg_write *reg = buf;
++		reg->port = cpu_to_le16(NET2280_DEV_U32);
++		reg->addr = cpu_to_le32(P54U_DEV_BASE);
++		reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
++		err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg));
++		if (err) {
++			printk(KERN_ERR "prism54usb: dev_int send failed\n");
++			goto fail;
++		}
++	}
++
++	hdr = buf + priv->common.tx_hdr_len;
++	p54_fill_eeprom_readback(hdr);
++	hdr->req_id = cpu_to_le32(priv->common.rx_start);
++	if (priv->common.tx_hdr_len) {
++		struct net2280_tx_hdr *tx_hdr = buf;
++		tx_hdr->device_addr = hdr->req_id;
++		tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN);
++	}
++
++	/* we can just pretend to send 0x2000 bytes of nothing in the headers */
++	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf,
++			    EEPROM_READBACK_LEN + priv->common.tx_hdr_len);
++	if (err) {
++		printk(KERN_ERR "prism54usb: eeprom req send failed\n");
++		goto fail;
++	}
++
++	err = usb_bulk_msg(priv->udev,
++			   usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
++			   buf, 0x2020, &alen, 1000);
++	if (!err && alen > offset) {
++		p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset);
++	} else {
++		printk(KERN_ERR "prism54usb: eeprom read failed!\n");
++		err = -EINVAL;
++		goto fail;
++	}
++
++ fail:
++	kfree(buf);
++	return err;
++}
++
++static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
++{
++	static char start_string[] = "~~~~<\r";
++	struct p54u_priv *priv = dev->priv;
++	const struct firmware *fw_entry = NULL;
++	int err, alen;
++	u8 carry = 0;
++	u8 *buf, *tmp, *data;
++	unsigned int left, remains, block_size;
++	struct x2_header *hdr;
++	unsigned long timeout;
++
++	tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
++	if (!buf) {
++		printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n");
++		err = -ENOMEM;
++		goto err_bufalloc;
++	}
++
++	memcpy(buf, start_string, 4);
++	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
++	if (err) {
++		printk(KERN_ERR "p54usb: reset failed! (%d)\n", err);
++		goto err_reset;
++	}
++
++	err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
++	if (err) {
++		printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
++		goto err_req_fw_failed;
++	}
++
++	p54_parse_firmware(dev, fw_entry);
++
++	left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
++	strcpy(buf, start_string);
++	left -= strlen(start_string);
++	tmp += strlen(start_string);
++
++	data = fw_entry->data;
++	remains = fw_entry->size;
++
++	hdr = (struct x2_header *)(buf + strlen(start_string));
++	memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
++	hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
++	hdr->fw_length = cpu_to_le32(fw_entry->size);
++	hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
++					 sizeof(u32)*2));
++	left -= sizeof(*hdr);
++	tmp += sizeof(*hdr);
++
++	while (remains) {
++		while (left--) {
++			if (carry) {
++				*tmp++ = carry;
++				carry = 0;
++				remains--;
++				continue;
++			}
++			switch (*data) {
++			case '~':
++				*tmp++ = '}';
++				carry = '^';
++				break;
++			case '}':
++				*tmp++ = '}';
++				carry = ']';
++				break;
++			default:
++				*tmp++ = *data;
++				remains--;
++				break;
++			}
++			data++;
++		}
++
++		err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
++		if (err) {
++			printk(KERN_ERR "prism54usb: firmware upload failed!\n");
++			goto err_upload_failed;
++		}
++
++		tmp = buf;
++		left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
++	}
++
++	*((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
++	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
++	if (err) {
++		printk(KERN_ERR "prism54usb: firmware upload failed!\n");
++		goto err_upload_failed;
++	}
++
++	timeout = jiffies + msecs_to_jiffies(1000);
++	while (!(err = usb_bulk_msg(priv->udev,
++		usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
++		if (alen > 2 && !memcmp(buf, "OK", 2))
++			break;
++
++		if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
++			printk(KERN_INFO "prism54usb: firmware upload failed!\n");
++			err = -EINVAL;
++			break;
++		}
++
++		if (time_after(jiffies, timeout)) {
++			printk(KERN_ERR "prism54usb: firmware boot timed out!\n");
++			err = -ETIMEDOUT;
++			break;
++		}
++	}
++	if (err)
++		goto err_upload_failed;
++
++	buf[0] = 'g';
++	buf[1] = '\r';
++	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
++	if (err) {
++		printk(KERN_ERR "prism54usb: firmware boot failed!\n");
++		goto err_upload_failed;
++	}
++
++	timeout = jiffies + msecs_to_jiffies(1000);
++	while (!(err = usb_bulk_msg(priv->udev,
++		usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
++		if (alen > 0 && buf[0] == 'g')
++			break;
++
++		if (time_after(jiffies, timeout)) {
++			err = -ETIMEDOUT;
++			break;
++		}
++	}
++	if (err)
++		goto err_upload_failed;
++
++  err_upload_failed:
++	release_firmware(fw_entry);
++  err_req_fw_failed:
++  err_reset:
++	kfree(buf);
++  err_bufalloc:
++	return err;
++}
++
++static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
++{
++	struct p54u_priv *priv = dev->priv;
++	const struct firmware *fw_entry = NULL;
++	const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
++	int err, alen;
++	void *buf;
++	__le32 reg;
++	unsigned int remains, offset;
++	u8 *data;
++
++	buf = kmalloc(512, GFP_KERNEL);
++	if (!buf) {
++		printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n");
++		return -ENOMEM;
++	}
++
++	err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
++	if (err) {
++		printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
++		kfree(buf);
++		return err;
++	}
++
++	p54_parse_firmware(dev, fw_entry);
++
++#define P54U_WRITE(type, addr, data) \
++	do {\
++		err = p54u_write(priv, buf, type,\
++				 cpu_to_le32((u32)(unsigned long)addr), data);\
++		if (err) \
++			goto fail;\
++	} while (0)
++
++#define P54U_READ(type, addr) \
++	do {\
++		err = p54u_read(priv, buf, type,\
++				cpu_to_le32((u32)(unsigned long)addr), &reg);\
++		if (err)\
++			goto fail;\
++	} while (0)
++
++	/* power down net2280 bridge */
++	P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
++	reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
++	reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
++	P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
++
++	mdelay(100);
++
++	/* power up bridge */
++	reg |= cpu_to_le32(P54U_BRG_POWER_UP);
++	reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
++	P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
++
++	mdelay(100);
++
++	P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
++		   cpu_to_le32(NET2280_CLK_30Mhz |
++			       NET2280_PCI_ENABLE |
++			       NET2280_PCI_SOFT_RESET));
++
++	mdelay(20);
++
++	P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
++		   cpu_to_le32(PCI_COMMAND_MEMORY |
++			       PCI_COMMAND_MASTER));
++
++	P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
++		   cpu_to_le32(NET2280_BASE));
++
++	P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
++	reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
++	P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
++
++	// TODO: we really need this?
++	P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
++
++	P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
++		   cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
++	P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
++		   cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
++
++	P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
++		   cpu_to_le32(NET2280_BASE2));
++
++	/* finally done setting up the bridge */
++
++	P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
++		   cpu_to_le32(PCI_COMMAND_MEMORY |
++			       PCI_COMMAND_MASTER));
++
++	P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
++	P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
++		   cpu_to_le32(P54U_DEV_BASE));
++
++	P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
++	P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
++		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
++
++	/* do romboot */
++	P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
++
++	P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
++	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++	mdelay(20);
++
++	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
++	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++	mdelay(20);
++
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++	mdelay(100);
++
++	P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
++	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
++
++	/* finally, we can upload firmware now! */
++	remains = fw_entry->size;
++	data = fw_entry->data;
++	offset = ISL38XX_DEV_FIRMWARE_ADDR;
++
++	while (remains) {
++		unsigned int block_len = min(remains, (unsigned int)512);
++		memcpy(buf, data, block_len);
++
++		err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
++		if (err) {
++			printk(KERN_ERR "prism54usb: firmware block upload "
++			       "failed\n");
++			goto fail;
++		}
++
++		P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
++			   cpu_to_le32(0xc0000f00));
++
++		P54U_WRITE(NET2280_DEV_U32,
++			   0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
++		P54U_WRITE(NET2280_DEV_U32,
++			   0x0020 | (unsigned long)&devreg->direct_mem_win,
++			   cpu_to_le32(1));
++
++		P54U_WRITE(NET2280_DEV_U32,
++			   0x0024 | (unsigned long)&devreg->direct_mem_win,
++			   cpu_to_le32(block_len));
++		P54U_WRITE(NET2280_DEV_U32,
++			   0x0028 | (unsigned long)&devreg->direct_mem_win,
++			   cpu_to_le32(offset));
++
++		P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
++			   cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
++		P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
++			   cpu_to_le32(block_len >> 2));
++		P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
++			   cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
++
++		mdelay(10);
++
++		P54U_READ(NET2280_DEV_U32,
++			  0x002C | (unsigned long)&devreg->direct_mem_win);
++		if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
++		    !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
++			printk(KERN_ERR "prism54usb: firmware DMA transfer "
++			       "failed\n");
++			goto fail;
++		}
++
++		P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
++			   cpu_to_le32(NET2280_FIFO_FLUSH));
++
++		remains -= block_len;
++		data += block_len;
++		offset += block_len;
++	}
++
++	/* do ramboot */
++	P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
++	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
++	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++	mdelay(20);
++
++	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
++	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++	mdelay(100);
++
++	P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
++	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
++
++	/* start up the firmware */
++	P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
++		   cpu_to_le32(ISL38XX_INT_IDENT_INIT));
++
++	P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
++		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
++
++	P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
++		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
++			       NET2280_USB_INTERRUPT_ENABLE));
++
++	P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
++		   cpu_to_le32(ISL38XX_DEV_INT_RESET));
++
++	err = usb_interrupt_msg(priv->udev,
++				usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
++				buf, sizeof(__le32), &alen, 1000);
++	if (err || alen != sizeof(__le32))
++		goto fail;
++
++	P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
++	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
++
++	if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
++		err = -EINVAL;
++
++	P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
++	P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
++		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
++
++#undef P54U_WRITE
++#undef P54U_READ
++
++ fail:
++	release_firmware(fw_entry);
++	kfree(buf);
++	return err;
++}
++
++static int p54u_open(struct ieee80211_hw *dev)
++{
++	struct p54u_priv *priv = dev->priv;
++	int err;
++
++	err = p54u_init_urbs(dev);
++	if (err) {
++		return err;
++	}
++
++	priv->common.open = p54u_init_urbs;
++
++	return 0;
++}
++
++static void p54u_stop(struct ieee80211_hw *dev)
++{
++	/* TODO: figure out how to reliably stop the 3887 and net2280 so
++	   the hardware is still usable next time we want to start it.
++	   until then, we just stop listening to the hardware.. */
++	p54u_free_urbs(dev);
++	return;
++}
++
++static int __devinit p54u_probe(struct usb_interface *intf,
++				const struct usb_device_id *id)
++{
++	struct usb_device *udev = interface_to_usbdev(intf);
++	struct ieee80211_hw *dev;
++	struct p54u_priv *priv;
++	int err;
++	unsigned int i, recognized_pipes;
++	DECLARE_MAC_BUF(mac);
++
++	dev = p54_init_common(sizeof(*priv));
++	if (!dev) {
++		printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n");
++		return -ENOMEM;
++	}
++
++	priv = dev->priv;
++
++	SET_IEEE80211_DEV(dev, &intf->dev);
++	usb_set_intfdata(intf, dev);
++	priv->udev = udev;
++
++	usb_get_dev(udev);
++
++	/* really lazy and simple way of figuring out if we're a 3887 */
++	/* TODO: should just stick the identification in the device table */
++	i = intf->altsetting->desc.bNumEndpoints;
++	recognized_pipes = 0;
++	while (i--) {
++		switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
++		case P54U_PIPE_DATA:
++		case P54U_PIPE_MGMT:
++		case P54U_PIPE_BRG:
++		case P54U_PIPE_DEV:
++		case P54U_PIPE_DATA | USB_DIR_IN:
++		case P54U_PIPE_MGMT | USB_DIR_IN:
++		case P54U_PIPE_BRG | USB_DIR_IN:
++		case P54U_PIPE_DEV | USB_DIR_IN:
++		case P54U_PIPE_INT | USB_DIR_IN:
++			recognized_pipes++;
++		}
++	}
++	priv->common.open = p54u_open;
++
++	if (recognized_pipes < P54U_PIPE_NUMBER) {
++		priv->hw_type = P54U_3887;
++		priv->common.tx = p54u_tx_3887;
++	} else {
++		dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
++		priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
++		priv->common.tx = p54u_tx_net2280;
++	}
++	priv->common.stop = p54u_stop;
++
++	if (priv->hw_type)
++		err = p54u_upload_firmware_3887(dev);
++	else
++		err = p54u_upload_firmware_net2280(dev);
++	if (err)
++		goto err_free_dev;
++
++	err = p54u_read_eeprom(dev);
++	if (err)
++		goto err_free_dev;
++
++	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
++		u8 perm_addr[ETH_ALEN];
++
++		printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n");
++		random_ether_addr(perm_addr);
++		SET_IEEE80211_PERM_ADDR(dev, perm_addr);
++	}
++
++	skb_queue_head_init(&priv->rx_queue);
++
++	err = ieee80211_register_hw(dev);
++	if (err) {
++		printk(KERN_ERR "prism54usb: Cannot register netdevice\n");
++		goto err_free_dev;
++	}
++
++	printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
++	       wiphy_name(dev->wiphy),
++	       print_mac(mac, dev->wiphy->perm_addr),
++	       priv->common.version);
++
++	return 0;
++
++ err_free_dev:
++	ieee80211_free_hw(dev);
++	usb_set_intfdata(intf, NULL);
++	usb_put_dev(udev);
++	return err;
++}
++
++static void __devexit p54u_disconnect(struct usb_interface *intf)
++{
++	struct ieee80211_hw *dev = usb_get_intfdata(intf);
++	struct p54u_priv *priv;
++
++	if (!dev)
++		return;
++
++	ieee80211_unregister_hw(dev);
++
++	priv = dev->priv;
++	usb_put_dev(interface_to_usbdev(intf));
++	p54_free_common(dev);
++	ieee80211_free_hw(dev);
++}
++
++static struct usb_driver p54u_driver = {
++	.name	= "prism54usb",
++	.id_table = p54u_table,
++	.probe = p54u_probe,
++	.disconnect = p54u_disconnect,
++};
++
++static int __init p54u_init(void)
++{
++	return usb_register(&p54u_driver);
++}
++
++static void __exit p54u_exit(void)
++{
++	usb_deregister(&p54u_driver);
++}
++
++module_init(p54u_init);
++module_exit(p54u_exit);
+diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
+new file mode 100644
+index 0000000..d1896b3
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54usb.h
+@@ -0,0 +1,133 @@
++#ifndef PRISM54USB_H
++#define PRISM54USB_H
++
++/*
++ * Defines for USB based mac80211 Prism54 driver
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* for isl3886 register definitions used on ver 1 devices */
++#include "p54pci.h"
++#include "net2280.h"
++
++/* pci */
++#define NET2280_BASE		0x10000000
++#define NET2280_BASE2		0x20000000
++
++/* gpio */
++#define P54U_BRG_POWER_UP	(1 << GPIO0_DATA)
++#define P54U_BRG_POWER_DOWN	(1 << GPIO1_DATA)
++
++/* devinit */
++#define NET2280_CLK_4Mhz	(15 << LOCAL_CLOCK_FREQUENCY)
++#define NET2280_CLK_30Mhz	(2 << LOCAL_CLOCK_FREQUENCY)
++#define NET2280_CLK_60Mhz	(1 << LOCAL_CLOCK_FREQUENCY)
++#define NET2280_CLK_STOP	(0 << LOCAL_CLOCK_FREQUENCY)
++#define NET2280_PCI_ENABLE	(1 << PCI_ENABLE)
++#define NET2280_PCI_SOFT_RESET	(1 << PCI_SOFT_RESET)
++
++/* endpoints */
++#define NET2280_CLEAR_NAK_OUT_PACKETS_MODE	(1 << CLEAR_NAK_OUT_PACKETS_MODE)
++#define NET2280_FIFO_FLUSH			(1 << FIFO_FLUSH)
++
++/* irq */
++#define NET2280_USB_INTERRUPT_ENABLE		(1 << USB_INTERRUPT_ENABLE)
++#define NET2280_PCI_INTA_INTERRUPT		(1 << PCI_INTA_INTERRUPT)
++#define NET2280_PCI_INTA_INTERRUPT_ENABLE	(1 << PCI_INTA_INTERRUPT_ENABLE)
++
++/* registers */
++#define NET2280_DEVINIT		0x00
++#define NET2280_USBIRQENB1	0x24
++#define NET2280_IRQSTAT1	0x2c
++#define NET2280_FIFOCTL         0x38
++#define NET2280_GPIOCTL		0x50
++#define NET2280_RELNUM		0x88
++#define NET2280_EPA_RSP		0x324
++#define NET2280_EPA_STAT	0x32c
++#define NET2280_EPB_STAT	0x34c
++#define NET2280_EPC_RSP		0x364
++#define NET2280_EPC_STAT	0x36c
++#define NET2280_EPD_STAT	0x38c
++
++#define NET2280_EPA_CFG     0x320
++#define NET2280_EPB_CFG     0x340
++#define NET2280_EPC_CFG     0x360
++#define NET2280_EPD_CFG     0x380
++#define NET2280_EPE_CFG     0x3A0
++#define NET2280_EPF_CFG     0x3C0
++#define P54U_DEV_BASE 0x40000000
++
++struct net2280_tx_hdr {
++	__le32 device_addr;
++	__le16 len;
++	__le16 follower;	/* ? */
++	u8 padding[8];
++} __attribute__((packed));
++
++/* Some flags for the isl hardware registers controlling DMA inside the
++ * chip */
++#define ISL38XX_DMA_STATUS_DONE			0x00000001
++#define ISL38XX_DMA_STATUS_READY		0x00000002
++#define NET2280_EPA_FIFO_PCI_ADDR		0x20000000
++#define ISL38XX_DMA_MASTER_CONTROL_TRIGGER	0x00000004
++
++enum net2280_op_type {
++	NET2280_BRG_U32		= 0x001F,
++	NET2280_BRG_CFG_U32	= 0x000F,
++	NET2280_BRG_CFG_U16	= 0x0003,
++	NET2280_DEV_U32		= 0x080F,
++	NET2280_DEV_CFG_U32	= 0x088F,
++	NET2280_DEV_CFG_U16	= 0x0883
++};
++
++#define P54U_FW_BLOCK 2048
++
++#define X2_SIGNATURE "x2  "
++#define X2_SIGNATURE_SIZE 4
++
++struct x2_header {
++	u8 signature[X2_SIGNATURE_SIZE];
++	__le32 fw_load_addr;
++	__le32 fw_length;
++	__le32 crc;
++} __attribute__((packed));
++
++/* pipes 3 and 4 are not used by the driver */
++#define P54U_PIPE_NUMBER 9
++
++enum p54u_pipe_addr {
++        P54U_PIPE_DATA = 0x01,
++        P54U_PIPE_MGMT = 0x02,
++        P54U_PIPE_3 = 0x03,
++        P54U_PIPE_4 = 0x04,
++        P54U_PIPE_BRG = 0x0d,
++        P54U_PIPE_DEV = 0x0e,
++        P54U_PIPE_INT = 0x0f
++};
++
++struct p54u_rx_info {
++	struct urb *urb;
++	struct ieee80211_hw *dev;
++};
++
++struct p54u_priv {
++	struct p54_common common;
++	struct usb_device *udev;
++	enum {
++		P54U_NET2280 = 0,
++		P54U_3887
++	} hw_type;
++
++	spinlock_t lock;
++	struct sk_buff_head rx_queue;
++};
++
++#endif /* PRISM54USB_H */
+diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c
+deleted file mode 100644
+index d191e05..0000000
+--- a/drivers/net/wireless/p54common.c
++++ /dev/null
+@@ -1,1025 +0,0 @@
+-
+-/*
+- * Common code for mac80211 Prism54 drivers
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- * Copyright (c) 2007, Christian Lamparter <chunkeey at web.de>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it 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/firmware.h>
+-#include <linux/etherdevice.h>
+-
+-#include <net/mac80211.h>
+-
+-#include "p54.h"
+-#include "p54common.h"
+-
+-MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
+-MODULE_DESCRIPTION("Softmac Prism54 common code");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("prism54common");
+-
+-void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct bootrec_exp_if *exp_if;
+-	struct bootrec *bootrec;
+-	u32 *data = (u32 *)fw->data;
+-	u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
+-	u8 *fw_version = NULL;
+-	size_t len;
+-	int i;
+-
+-	if (priv->rx_start)
+-		return;
+-
+-	while (data < end_data && *data)
+-		data++;
+-
+-	while (data < end_data && !*data)
+-		data++;
+-
+-	bootrec = (struct bootrec *) data;
+-
+-	while (bootrec->data <= end_data &&
+-	       (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
+-		u32 code = le32_to_cpu(bootrec->code);
+-		switch (code) {
+-		case BR_CODE_COMPONENT_ID:
+-			switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
+-			case FW_FMAC:
+-				printk(KERN_INFO "p54: FreeMAC firmware\n");
+-				break;
+-			case FW_LM20:
+-				printk(KERN_INFO "p54: LM20 firmware\n");
+-				break;
+-			case FW_LM86:
+-				printk(KERN_INFO "p54: LM86 firmware\n");
+-				break;
+-			case FW_LM87:
+-				printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
+-				break;
+-			default:
+-				printk(KERN_INFO "p54: unknown firmware\n");
+-				break;
+-			}
+-			break;
+-		case BR_CODE_COMPONENT_VERSION:
+-			/* 24 bytes should be enough for all firmwares */
+-			if (strnlen((unsigned char*)bootrec->data, 24) < 24)
+-				fw_version = (unsigned char*)bootrec->data;
+-			break;
+-		case BR_CODE_DESCR:
+-			priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
+-			/* FIXME add sanity checking */
+-			priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
+-			break;
+-		case BR_CODE_EXPOSED_IF:
+-			exp_if = (struct bootrec_exp_if *) bootrec->data;
+-			for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
+-				if (exp_if[i].if_id == cpu_to_le16(0x1a))
+-					priv->fw_var = le16_to_cpu(exp_if[i].variant);
+-			break;
+-		case BR_CODE_DEPENDENT_IF:
+-			break;
+-		case BR_CODE_END_OF_BRA:
+-		case LEGACY_BR_CODE_END_OF_BRA:
+-			end_data = NULL;
+-			break;
+-		default:
+-			break;
+-		}
+-		bootrec = (struct bootrec *)&bootrec->data[len];
+-	}
+-
+-	if (fw_version)
+-		printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
+-			fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
+-
+-	if (priv->fw_var >= 0x300) {
+-		/* Firmware supports QoS, use it! */
+-		priv->tx_stats.data[0].limit = 3;
+-		priv->tx_stats.data[1].limit = 4;
+-		priv->tx_stats.data[2].limit = 3;
+-		priv->tx_stats.data[3].limit = 1;
+-		dev->queues = 4;
+-	}
+-}
+-EXPORT_SYMBOL_GPL(p54_parse_firmware);
+-
+-static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
+-				    struct pda_pa_curve_data *curve_data)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct pda_pa_curve_data_sample_rev1 *rev1;
+-	struct pda_pa_curve_data_sample_rev0 *rev0;
+-	size_t cd_len = sizeof(*curve_data) +
+-		(curve_data->points_per_channel*sizeof(*rev1) + 2) *
+-		 curve_data->channels;
+-	unsigned int i, j;
+-	void *source, *target;
+-
+-	priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
+-	if (!priv->curve_data)
+-		return -ENOMEM;
+-
+-	memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
+-	source = curve_data->data;
+-	target = priv->curve_data->data;
+-	for (i = 0; i < curve_data->channels; i++) {
+-		__le16 *freq = source;
+-		source += sizeof(__le16);
+-		*((__le16 *)target) = *freq;
+-		target += sizeof(__le16);
+-		for (j = 0; j < curve_data->points_per_channel; j++) {
+-			rev1 = target;
+-			rev0 = source;
+-
+-			rev1->rf_power = rev0->rf_power;
+-			rev1->pa_detector = rev0->pa_detector;
+-			rev1->data_64qam = rev0->pcv;
+-			/* "invent" the points for the other modulations */
+-#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
+-			rev1->data_16qam = SUB(rev0->pcv, 12);
+-			rev1->data_qpsk  = SUB(rev1->data_16qam, 12);
+-			rev1->data_bpsk  = SUB(rev1->data_qpsk, 12);
+-			rev1->data_barker= SUB(rev1->data_bpsk, 14);
+-#undef SUB
+-			target += sizeof(*rev1);
+-			source += sizeof(*rev0);
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct eeprom_pda_wrap *wrap = NULL;
+-	struct pda_entry *entry;
+-	unsigned int data_len, entry_len;
+-	void *tmp;
+-	int err;
+-	u8 *end = (u8 *)eeprom + len;
+-
+-	wrap = (struct eeprom_pda_wrap *) eeprom;
+-	entry = (void *)wrap->data + le16_to_cpu(wrap->len);
+-
+-	/* verify that at least the entry length/code fits */
+-	while ((u8 *)entry <= end - sizeof(*entry)) {
+-		entry_len = le16_to_cpu(entry->len);
+-		data_len = ((entry_len - 1) << 1);
+-
+-		/* abort if entry exceeds whole structure */
+-		if ((u8 *)entry + sizeof(*entry) + data_len > end)
+-			break;
+-
+-		switch (le16_to_cpu(entry->code)) {
+-		case PDR_MAC_ADDRESS:
+-			SET_IEEE80211_PERM_ADDR(dev, entry->data);
+-			break;
+-		case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
+-			if (data_len < 2) {
+-				err = -EINVAL;
+-				goto err;
+-			}
+-
+-			if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) {
+-				err = -EINVAL;
+-				goto err;
+-			}
+-
+-			priv->output_limit = kmalloc(entry->data[1] *
+-				sizeof(*priv->output_limit), GFP_KERNEL);
+-
+-			if (!priv->output_limit) {
+-				err = -ENOMEM;
+-				goto err;
+-			}
+-
+-			memcpy(priv->output_limit, &entry->data[2],
+-			       entry->data[1]*sizeof(*priv->output_limit));
+-			priv->output_limit_len = entry->data[1];
+-			break;
+-		case PDR_PRISM_PA_CAL_CURVE_DATA:
+-			if (data_len < sizeof(struct pda_pa_curve_data)) {
+-				err = -EINVAL;
+-				goto err;
+-			}
+-
+-			if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) {
+-				priv->curve_data = kmalloc(data_len, GFP_KERNEL);
+-				if (!priv->curve_data) {
+-					err = -ENOMEM;
+-					goto err;
+-				}
+-
+-				memcpy(priv->curve_data, entry->data, data_len);
+-			} else {
+-				err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data);
+-				if (err)
+-					goto err;
+-			}
+-
+-			break;
+-		case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
+-			priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
+-			if (!priv->iq_autocal) {
+-				err = -ENOMEM;
+-				goto err;
+-			}
+-
+-			memcpy(priv->iq_autocal, entry->data, data_len);
+-			priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
+-			break;
+-		case PDR_INTERFACE_LIST:
+-			tmp = entry->data;
+-			while ((u8 *)tmp < entry->data + data_len) {
+-				struct bootrec_exp_if *exp_if = tmp;
+-				if (le16_to_cpu(exp_if->if_id) == 0xF)
+-					priv->rxhw = exp_if->variant & cpu_to_le16(0x07);
+-				tmp += sizeof(struct bootrec_exp_if);
+-			}
+-			break;
+-		case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
+-			priv->version = *(u8 *)(entry->data + 1);
+-			break;
+-		case PDR_END:
+-			/* make it overrun */
+-			entry_len = len;
+-			break;
+-		}
+-
+-		entry = (void *)entry + (entry_len + 1)*2;
+-	}
+-
+-	if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) {
+-		printk(KERN_ERR "p54: not all required entries found in eeprom!\n");
+-		err = -EINVAL;
+-		goto err;
+-	}
+-
+-	return 0;
+-
+-  err:
+-	if (priv->iq_autocal) {
+-		kfree(priv->iq_autocal);
+-		priv->iq_autocal = NULL;
+-	}
+-
+-	if (priv->output_limit) {
+-		kfree(priv->output_limit);
+-		priv->output_limit = NULL;
+-	}
+-
+-	if (priv->curve_data) {
+-		kfree(priv->curve_data);
+-		priv->curve_data = NULL;
+-	}
+-
+-	printk(KERN_ERR "p54: eeprom parse failed!\n");
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(p54_parse_eeprom);
+-
+-void p54_fill_eeprom_readback(struct p54_control_hdr *hdr)
+-{
+-	struct p54_eeprom_lm86 *eeprom_hdr;
+-
+-	hdr->magic1 = cpu_to_le16(0x8000);
+-	hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000);
+-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
+-	hdr->retry1 = hdr->retry2 = 0;
+-	eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
+-	eeprom_hdr->offset = 0x0;
+-	eeprom_hdr->len = cpu_to_le16(0x2000);
+-}
+-EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback);
+-
+-static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
+-{
+-	struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
+-	struct ieee80211_rx_status rx_status = {0};
+-	u16 freq = le16_to_cpu(hdr->freq);
+-
+-	rx_status.ssi = hdr->rssi;
+-	rx_status.rate = hdr->rate & 0x1f; /* report short preambles & CCK too */
+-	rx_status.channel = freq == 2484 ? 14 : (freq - 2407)/5;
+-	rx_status.freq = freq;
+-	rx_status.phymode = MODE_IEEE80211G;
+-	rx_status.antenna = hdr->antenna;
+-	rx_status.mactime = le64_to_cpu(hdr->timestamp);
+-	rx_status.flag |= RX_FLAG_TSFT;
+-
+-	skb_pull(skb, sizeof(*hdr));
+-	skb_trim(skb, le16_to_cpu(hdr->len));
+-
+-	ieee80211_rx_irqsafe(dev, skb, &rx_status);
+-}
+-
+-static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
+-{
+-	struct p54_common *priv = dev->priv;
+-	int i;
+-
+-	/* ieee80211_start_queues is great if all queues are really empty.
+-	 * But, what if some are full? */
+-
+-	for (i = 0; i < dev->queues; i++)
+-		if (priv->tx_stats.data[i].len < priv->tx_stats.data[i].limit)
+-			ieee80211_wake_queue(dev, i);
+-}
+-
+-static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+-	struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
+-	struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
+-	u32 addr = le32_to_cpu(hdr->req_id) - 0x70;
+-	struct memrecord *range = NULL;
+-	u32 freed = 0;
+-	u32 last_addr = priv->rx_start;
+-
+-	while (entry != (struct sk_buff *)&priv->tx_queue) {
+-		range = (struct memrecord *)&entry->cb;
+-		if (range->start_addr == addr) {
+-			struct ieee80211_tx_status status = {{0}};
+-			struct p54_control_hdr *entry_hdr;
+-			struct p54_tx_control_allocdata *entry_data;
+-			int pad = 0;
+-
+-			if (entry->next != (struct sk_buff *)&priv->tx_queue)
+-				freed = ((struct memrecord *)&entry->next->cb)->start_addr - last_addr;
+-			else
+-				freed = priv->rx_end - last_addr;
+-
+-			last_addr = range->end_addr;
+-			__skb_unlink(entry, &priv->tx_queue);
+-			if (!range->control) {
+-				kfree_skb(entry);
+-				break;
+-			}
+-			memcpy(&status.control, range->control,
+-			       sizeof(status.control));
+-			kfree(range->control);
+-			priv->tx_stats.data[status.control.queue].len--;
+-
+-			entry_hdr = (struct p54_control_hdr *) entry->data;
+-			entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
+-			if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
+-				pad = entry_data->align[0];
+-
+-			if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
+-				if (!(payload->status & 0x01))
+-					status.flags |= IEEE80211_TX_STATUS_ACK;
+-				else
+-					status.excessive_retries = 1;
+-			}
+-			status.retry_count = payload->retries - 1;
+-			status.ack_signal = le16_to_cpu(payload->ack_rssi);
+-			skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
+-			ieee80211_tx_status_irqsafe(dev, entry, &status);
+-			break;
+-		} else
+-			last_addr = range->end_addr;
+-		entry = entry->next;
+-	}
+-
+-	if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
+-	    sizeof(struct p54_control_hdr))
+-		p54_wake_free_queues(dev);
+-}
+-
+-static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
+-{
+-	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+-
+-	switch (le16_to_cpu(hdr->type)) {
+-	case P54_CONTROL_TYPE_TXDONE:
+-		p54_rx_frame_sent(dev, skb);
+-		break;
+-	case P54_CONTROL_TYPE_BBP:
+-		break;
+-	default:
+-		printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
+-		       wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
+-		break;
+-	}
+-}
+-
+-/* returns zero if skb can be reused */
+-int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
+-{
+-	u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
+-	switch (type) {
+-	case 0x00:
+-	case 0x01:
+-		p54_rx_data(dev, skb);
+-		return -1;
+-	case 0x4d:
+-		/* TODO: do something better... but then again, I've never seen this happen */
+-		printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n",
+-		       wiphy_name(dev->wiphy));
+-		break;
+-	case 0x80:
+-		p54_rx_control(dev, skb);
+-		break;
+-	default:
+-		printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n",
+-		       wiphy_name(dev->wiphy), type);
+-		break;
+-	}
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(p54_rx);
+-
+-/*
+- * So, the firmware is somewhat stupid and doesn't know what places in its
+- * memory incoming data should go to. By poking around in the firmware, we
+- * can find some unused memory to upload our packets to. However, data that we
+- * want the card to TX needs to stay intact until the card has told us that
+- * it is done with it. This function finds empty places we can upload to and
+- * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
+- * allocated areas.
+- */
+-static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
+-			       struct p54_control_hdr *data, u32 len,
+-			       struct ieee80211_tx_control *control)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct sk_buff *entry = priv->tx_queue.next;
+-	struct sk_buff *target_skb = NULL;
+-	struct memrecord *range;
+-	u32 last_addr = priv->rx_start;
+-	u32 largest_hole = 0;
+-	u32 target_addr = priv->rx_start;
+-	unsigned long flags;
+-	unsigned int left;
+-	len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */
+-
+-	spin_lock_irqsave(&priv->tx_queue.lock, flags);
+-	left = skb_queue_len(&priv->tx_queue);
+-	while (left--) {
+-		u32 hole_size;
+-		range = (struct memrecord *)&entry->cb;
+-		hole_size = range->start_addr - last_addr;
+-		if (!target_skb && hole_size >= len) {
+-			target_skb = entry->prev;
+-			hole_size -= len;
+-			target_addr = last_addr;
+-		}
+-		largest_hole = max(largest_hole, hole_size);
+-		last_addr = range->end_addr;
+-		entry = entry->next;
+-	}
+-	if (!target_skb && priv->rx_end - last_addr >= len) {
+-		target_skb = priv->tx_queue.prev;
+-		largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
+-		if (!skb_queue_empty(&priv->tx_queue)) {
+-			range = (struct memrecord *)&target_skb->cb;
+-			target_addr = range->end_addr;
+-		}
+-	} else
+-		largest_hole = max(largest_hole, priv->rx_end - last_addr);
+-
+-	if (skb) {
+-		range = (struct memrecord *)&skb->cb;
+-		range->start_addr = target_addr;
+-		range->end_addr = target_addr + len;
+-		range->control = control;
+-		__skb_queue_after(&priv->tx_queue, target_skb, skb);
+-		if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
+-				   sizeof(struct p54_control_hdr))
+-			ieee80211_stop_queues(dev);
+-	}
+-	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+-
+-	data->req_id = cpu_to_le32(target_addr + 0x70);
+-}
+-
+-static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+-		  struct ieee80211_tx_control *control)
+-{
+-	struct ieee80211_tx_queue_stats_data *current_queue;
+-	struct p54_common *priv = dev->priv;
+-	struct p54_control_hdr *hdr;
+-	struct p54_tx_control_allocdata *txhdr;
+-	struct ieee80211_tx_control *control_copy;
+-	size_t padding, len;
+-	u8 rate;
+-
+-	current_queue = &priv->tx_stats.data[control->queue];
+-	if (unlikely(current_queue->len > current_queue->limit))
+-		return NETDEV_TX_BUSY;
+-	current_queue->len++;
+-	current_queue->count++;
+-	if (current_queue->len == current_queue->limit)
+-		ieee80211_stop_queue(dev, control->queue);
+-
+-	padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
+-	len = skb->len;
+-
+-	control_copy = kmalloc(sizeof(*control), GFP_ATOMIC);
+-	if (control_copy)
+-		memcpy(control_copy, control, sizeof(*control));
+-
+-	txhdr = (struct p54_tx_control_allocdata *)
+-			skb_push(skb, sizeof(*txhdr) + padding);
+-	hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));
+-
+-	if (padding)
+-		hdr->magic1 = cpu_to_le16(0x4010);
+-	else
+-		hdr->magic1 = cpu_to_le16(0x0010);
+-	hdr->len = cpu_to_le16(len);
+-	hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1);
+-	hdr->retry1 = hdr->retry2 = control->retry_limit;
+-	p54_assign_address(dev, skb, hdr, skb->len, control_copy);
+-
+-	memset(txhdr->wep_key, 0x0, 16);
+-	txhdr->padding = 0;
+-	txhdr->padding2 = 0;
+-
+-	/* TODO: add support for alternate retry TX rates */
+-	rate = control->tx_rate;
+-	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
+-		rate |= 0x40;
+-	else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+-		rate |= 0x20;
+-	memset(txhdr->rateset, rate, 8);
+-	txhdr->wep_key_present = 0;
+-	txhdr->wep_key_len = 0;
+-	txhdr->frame_type = cpu_to_le32(control->queue + 4);
+-	txhdr->magic4 = 0;
+-	txhdr->antenna = (control->antenna_sel_tx == 0) ?
+-		2 : control->antenna_sel_tx - 1;
+-	txhdr->output_power = 0x7f; // HW Maximum
+-	txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ?
+-		0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23));
+-	if (padding)
+-		txhdr->align[0] = padding;
+-
+-	priv->tx(dev, hdr, skb->len, 0);
+-	return 0;
+-}
+-
+-static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
+-			  const u8 *dst, const u8 *src, u8 antenna,
+-			  u32 magic3, u32 magic8, u32 magic9)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct p54_control_hdr *hdr;
+-	struct p54_tx_control_filter *filter;
+-
+-	hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
+-		      priv->tx_hdr_len, GFP_ATOMIC);
+-	if (!hdr)
+-		return -ENOMEM;
+-
+-	hdr = (void *)hdr + priv->tx_hdr_len;
+-
+-	filter = (struct p54_tx_control_filter *) hdr->data;
+-	hdr->magic1 = cpu_to_le16(0x8001);
+-	hdr->len = cpu_to_le16(sizeof(*filter));
+-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL);
+-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
+-
+-	filter->filter_type = cpu_to_le16(filter_type);
+-	memcpy(filter->dst, dst, ETH_ALEN);
+-	if (!src)
+-		memset(filter->src, ~0, ETH_ALEN);
+-	else
+-		memcpy(filter->src, src, ETH_ALEN);
+-	filter->antenna = antenna;
+-	filter->magic3 = cpu_to_le32(magic3);
+-	filter->rx_addr = cpu_to_le32(priv->rx_end);
+-	filter->max_rx = cpu_to_le16(0x0620);	/* FIXME: for usb ver 1.. maybe */
+-	filter->rxhw = priv->rxhw;
+-	filter->magic8 = cpu_to_le16(magic8);
+-	filter->magic9 = cpu_to_le16(magic9);
+-
+-	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1);
+-	return 0;
+-}
+-
+-static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct p54_control_hdr *hdr;
+-	struct p54_tx_control_channel *chan;
+-	unsigned int i;
+-	size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
+-			     sizeof(*chan->curve_data) *
+-			     priv->curve_data->points_per_channel;
+-	void *entry;
+-
+-	hdr = kzalloc(sizeof(*hdr) + payload_len +
+-		      priv->tx_hdr_len, GFP_KERNEL);
+-	if (!hdr)
+-		return -ENOMEM;
+-
+-	hdr = (void *)hdr + priv->tx_hdr_len;
+-
+-	chan = (struct p54_tx_control_channel *) hdr->data;
+-
+-	hdr->magic1 = cpu_to_le16(0x8001);
+-	hdr->len = cpu_to_le16(sizeof(*chan));
+-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
+-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL);
+-
+-	chan->magic1 = cpu_to_le16(0x1);
+-	chan->magic2 = cpu_to_le16(0x0);
+-
+-	for (i = 0; i < priv->iq_autocal_len; i++) {
+-		if (priv->iq_autocal[i].freq != freq)
+-			continue;
+-
+-		memcpy(&chan->iq_autocal, &priv->iq_autocal[i],
+-		       sizeof(*priv->iq_autocal));
+-		break;
+-	}
+-	if (i == priv->iq_autocal_len)
+-		goto err;
+-
+-	for (i = 0; i < priv->output_limit_len; i++) {
+-		if (priv->output_limit[i].freq != freq)
+-			continue;
+-
+-		chan->val_barker = 0x38;
+-		chan->val_bpsk = priv->output_limit[i].val_bpsk;
+-		chan->val_qpsk = priv->output_limit[i].val_qpsk;
+-		chan->val_16qam = priv->output_limit[i].val_16qam;
+-		chan->val_64qam = priv->output_limit[i].val_64qam;
+-		break;
+-	}
+-	if (i == priv->output_limit_len)
+-		goto err;
+-
+-	chan->pa_points_per_curve = priv->curve_data->points_per_channel;
+-
+-	entry = priv->curve_data->data;
+-	for (i = 0; i < priv->curve_data->channels; i++) {
+-		if (*((__le16 *)entry) != freq) {
+-			entry += sizeof(__le16);
+-			entry += sizeof(struct pda_pa_curve_data_sample_rev1) *
+-				 chan->pa_points_per_curve;
+-			continue;
+-		}
+-
+-		entry += sizeof(__le16);
+-		memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
+-		       chan->pa_points_per_curve);
+-		break;
+-	}
+-
+-	memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4);
+-
+-	priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1);
+-	return 0;
+-
+- err:
+-	printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
+-	kfree(hdr);
+-	return -EINVAL;
+-}
+-
+-static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct p54_control_hdr *hdr;
+-	struct p54_tx_control_led *led;
+-
+-	hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
+-		      priv->tx_hdr_len, GFP_KERNEL);
+-	if (!hdr)
+-		return -ENOMEM;
+-
+-	hdr = (void *)hdr + priv->tx_hdr_len;
+-	hdr->magic1 = cpu_to_le16(0x8001);
+-	hdr->len = cpu_to_le16(sizeof(*led));
+-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
+-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL);
+-
+-	led = (struct p54_tx_control_led *) hdr->data;
+-	led->mode = cpu_to_le16(mode);
+-	led->led_permanent = cpu_to_le16(link);
+-	led->led_temporary = cpu_to_le16(act);
+-	led->duration = cpu_to_le16(1000);
+-
+-	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);
+-
+-	return 0;
+-}
+-
+-#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, burst)	\
+-do {	 							\
+-	queue.aifs = cpu_to_le16(ai_fs);			\
+-	queue.cwmin = cpu_to_le16(cw_min);			\
+-	queue.cwmax = cpu_to_le16(cw_max);			\
+-	queue.txop = (burst == 0) ? 				\
+-		0 : cpu_to_le16((burst * 100) / 32 + 1);	\
+-} while(0)
+-
+-static void p54_init_vdcf(struct ieee80211_hw *dev)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct p54_control_hdr *hdr;
+-	struct p54_tx_control_vdcf *vdcf;
+-
+-	/* all USB V1 adapters need a extra headroom */
+-	hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
+-	hdr->magic1 = cpu_to_le16(0x8001);
+-	hdr->len = cpu_to_le16(sizeof(*vdcf));
+-	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
+-	hdr->req_id = cpu_to_le32(priv->rx_start);
+-
+-	vdcf = (struct p54_tx_control_vdcf *) hdr->data;
+-
+-	P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 0x000f);
+-	P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 0x001e);
+-	P54_SET_QUEUE(vdcf->queue[2], 0x0002, 0x000f, 0x03ff, 0x0014);
+-	P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0x0000);
+-}
+-
+-static void p54_set_vdcf(struct ieee80211_hw *dev)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct p54_control_hdr *hdr;
+-	struct p54_tx_control_vdcf *vdcf;
+-
+-	hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
+-
+-	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL);
+-
+-	vdcf = (struct p54_tx_control_vdcf *) hdr->data;
+-
+-	if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+-		vdcf->slottime = 9;
+-		vdcf->magic1 = 0x00;
+-		vdcf->magic2 = 0x10;
+-	} else {
+-		vdcf->slottime = 20;
+-		vdcf->magic1 = 0x0a;
+-		vdcf->magic2 = 0x06;
+-	}
+-
+-	/* (see prism54/isl_oid.h for further details) */
+-	vdcf->frameburst = cpu_to_le16(0);
+-
+-	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
+-}
+-
+-static int p54_start(struct ieee80211_hw *dev)
+-{
+-	struct p54_common *priv = dev->priv;
+-	int err;
+-
+-	err = priv->open(dev);
+-	if (!err)
+-		priv->mode = IEEE80211_IF_TYPE_MNTR;
+-
+-	return err;
+-}
+-
+-static void p54_stop(struct ieee80211_hw *dev)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct sk_buff *skb;
+-	while ((skb = skb_dequeue(&priv->tx_queue))) {
+-		struct memrecord *range = (struct memrecord *)&skb->cb;
+-		if (range->control)
+-			kfree(range->control);
+-		kfree_skb(skb);
+-	}
+-	priv->stop(dev);
+-	priv->mode = IEEE80211_IF_TYPE_INVALID;
+-}
+-
+-static int p54_add_interface(struct ieee80211_hw *dev,
+-			     struct ieee80211_if_init_conf *conf)
+-{
+-	struct p54_common *priv = dev->priv;
+-
+-	if (priv->mode != IEEE80211_IF_TYPE_MNTR)
+-		return -EOPNOTSUPP;
+-
+-	switch (conf->type) {
+-	case IEEE80211_IF_TYPE_STA:
+-		priv->mode = conf->type;
+-		break;
+-	default:
+-		return -EOPNOTSUPP;
+-	}
+-
+-	memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
+-
+-	p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642);
+-	p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642);
+-
+-	switch (conf->type) {
+-	case IEEE80211_IF_TYPE_STA:
+-		p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0);
+-		break;
+-	default:
+-		BUG();	/* impossible */
+-		break;
+-	}
+-
+-	p54_set_leds(dev, 1, 0, 0);
+-
+-	return 0;
+-}
+-
+-static void p54_remove_interface(struct ieee80211_hw *dev,
+-				 struct ieee80211_if_init_conf *conf)
+-{
+-	struct p54_common *priv = dev->priv;
+-	priv->mode = IEEE80211_IF_TYPE_MNTR;
+-	memset(priv->mac_addr, 0, ETH_ALEN);
+-	p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0);
+-}
+-
+-static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+-{
+-	int ret;
+-
+-	ret = p54_set_freq(dev, cpu_to_le16(conf->freq));
+-	p54_set_vdcf(dev);
+-	return ret;
+-}
+-
+-static int p54_config_interface(struct ieee80211_hw *dev,
+-				struct ieee80211_vif *vif,
+-				struct ieee80211_if_conf *conf)
+-{
+-	struct p54_common *priv = dev->priv;
+-
+-	p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
+-	p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
+-	p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
+-	memcpy(priv->bssid, conf->bssid, ETH_ALEN);
+-	return 0;
+-}
+-
+-static void p54_configure_filter(struct ieee80211_hw *dev,
+-				 unsigned int changed_flags,
+-				 unsigned int *total_flags,
+-				 int mc_count, struct dev_mc_list *mclist)
+-{
+-	struct p54_common *priv = dev->priv;
+-
+-	*total_flags &= FIF_BCN_PRBRESP_PROMISC;
+-
+-	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
+-		if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+-			p54_set_filter(dev, 0, priv->mac_addr,
+-				       NULL, 2, 0, 0, 0);
+-		else
+-			p54_set_filter(dev, 0, priv->mac_addr,
+-				       priv->bssid, 2, 0, 0, 0);
+-	}
+-}
+-
+-static int p54_conf_tx(struct ieee80211_hw *dev, int queue,
+-		       const struct ieee80211_tx_queue_params *params)
+-{
+-	struct p54_common *priv = dev->priv;
+-	struct p54_tx_control_vdcf *vdcf;
+-
+-	vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *)
+-		((void *)priv->cached_vdcf + priv->tx_hdr_len))->data);
+-
+-	if ((params) && !((queue < 0) || (queue > 4))) {
+-		P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
+-			params->cw_min, params->cw_max, params->burst_time);
+-	} else
+-		return -EINVAL;
+-
+-	p54_set_vdcf(dev);
+-
+-	return 0;
+-}
+-
+-static int p54_get_stats(struct ieee80211_hw *dev,
+-			 struct ieee80211_low_level_stats *stats)
+-{
+-	/* TODO */
+-	return 0;
+-}
+-
+-static int p54_get_tx_stats(struct ieee80211_hw *dev,
+-			    struct ieee80211_tx_queue_stats *stats)
+-{
+-	struct p54_common *priv = dev->priv;
+-	unsigned int i;
+-
+-	for (i = 0; i < dev->queues; i++)
+-		memcpy(&stats->data[i], &priv->tx_stats.data[i],
+-			sizeof(stats->data[i]));
+-
+-	return 0;
+-}
+-
+-static const struct ieee80211_ops p54_ops = {
+-	.tx			= p54_tx,
+-	.start			= p54_start,
+-	.stop			= p54_stop,
+-	.add_interface		= p54_add_interface,
+-	.remove_interface	= p54_remove_interface,
+-	.config			= p54_config,
+-	.config_interface	= p54_config_interface,
+-	.configure_filter	= p54_configure_filter,
+-	.conf_tx		= p54_conf_tx,
+-	.get_stats		= p54_get_stats,
+-	.get_tx_stats		= p54_get_tx_stats
+-};
+-
+-struct ieee80211_hw *p54_init_common(size_t priv_data_len)
+-{
+-	struct ieee80211_hw *dev;
+-	struct p54_common *priv;
+-	int i;
+-
+-	dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
+-	if (!dev)
+-		return NULL;
+-
+-	priv = dev->priv;
+-	priv->mode = IEEE80211_IF_TYPE_INVALID;
+-	skb_queue_head_init(&priv->tx_queue);
+-	memcpy(priv->channels, p54_channels, sizeof(p54_channels));
+-	memcpy(priv->rates, p54_rates, sizeof(p54_rates));
+-	priv->modes[1].mode = MODE_IEEE80211B;
+-	priv->modes[1].num_rates = 4;
+-	priv->modes[1].rates = priv->rates;
+-	priv->modes[1].num_channels = ARRAY_SIZE(p54_channels);
+-	priv->modes[1].channels = priv->channels;
+-	priv->modes[0].mode = MODE_IEEE80211G;
+-	priv->modes[0].num_rates = ARRAY_SIZE(p54_rates);
+-	priv->modes[0].rates = priv->rates;
+-	priv->modes[0].num_channels = ARRAY_SIZE(p54_channels);
+-	priv->modes[0].channels = priv->channels;
+-	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
+-		    IEEE80211_HW_RX_INCLUDES_FCS;
+-	dev->channel_change_time = 1000;	/* TODO: find actual value */
+-	dev->max_rssi = 127;
+-
+-	priv->tx_stats.data[0].limit = 5;
+-	dev->queues = 1;
+-
+-	dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
+-				 sizeof(struct p54_tx_control_allocdata);
+-
+-        priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) +
+-              priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL);
+-
+-	if (!priv->cached_vdcf) {
+-		ieee80211_free_hw(dev);
+-		return NULL;
+-	}
+-
+-	p54_init_vdcf(dev);
+-
+-	for (i = 0; i < 2; i++) {
+-		if (ieee80211_register_hwmode(dev, &priv->modes[i])) {
+-			kfree(priv->cached_vdcf);
+-			ieee80211_free_hw(dev);
+-			return NULL;
+-		}
+-	}
+-
+-	return dev;
+-}
+-EXPORT_SYMBOL_GPL(p54_init_common);
+-
+-void p54_free_common(struct ieee80211_hw *dev)
+-{
+-	struct p54_common *priv = dev->priv;
+-	kfree(priv->iq_autocal);
+-	kfree(priv->output_limit);
+-	kfree(priv->curve_data);
+-	kfree(priv->cached_vdcf);
+-}
+-EXPORT_SYMBOL_GPL(p54_free_common);
+-
+-static int __init p54_init(void)
+-{
+-	return 0;
+-}
+-
+-static void __exit p54_exit(void)
+-{
+-}
+-
+-module_init(p54_init);
+-module_exit(p54_exit);
+diff --git a/drivers/net/wireless/p54common.h b/drivers/net/wireless/p54common.h
+deleted file mode 100644
+index b67ff34..0000000
+--- a/drivers/net/wireless/p54common.h
++++ /dev/null
+@@ -1,329 +0,0 @@
+-#ifndef PRISM54COMMON_H
+-#define PRISM54COMMON_H
+-
+-/*
+- * Common code specific definitions for mac80211 Prism54 drivers
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- * Copyright (c) 2007, Christian Lamparter <chunkeey at web.de>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-struct bootrec {
+-	__le32 code;
+-	__le32 len;
+-	u32 data[0];
+-} __attribute__((packed));
+-
+-struct bootrec_exp_if {
+-	__le16 role;
+-	__le16 if_id;
+-	__le16 variant;
+-	__le16 btm_compat;
+-	__le16 top_compat;
+-} __attribute__((packed));
+-
+-#define BR_CODE_MIN			0x80000000
+-#define BR_CODE_COMPONENT_ID		0x80000001
+-#define BR_CODE_COMPONENT_VERSION	0x80000002
+-#define BR_CODE_DEPENDENT_IF		0x80000003
+-#define BR_CODE_EXPOSED_IF		0x80000004
+-#define BR_CODE_DESCR			0x80000101
+-#define BR_CODE_MAX			0x8FFFFFFF
+-#define BR_CODE_END_OF_BRA		0xFF0000FF
+-#define LEGACY_BR_CODE_END_OF_BRA	0xFFFFFFFF
+-
+-#define FW_FMAC 0x464d4143
+-#define FW_LM86 0x4c4d3836
+-#define FW_LM87 0x4c4d3837
+-#define FW_LM20 0x4c4d3230
+-
+-/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
+-
+-struct pda_entry {
+-	__le16 len;	/* includes both code and data */
+-	__le16 code;
+-	u8 data[0];
+-} __attribute__ ((packed));
+-
+-struct eeprom_pda_wrap {
+-	__le32 magic;
+-	__le16 pad;
+-	__le16 len;
+-	__le32 arm_opcode;
+-	u8 data[0];
+-} __attribute__ ((packed));
+-
+-struct pda_iq_autocal_entry {
+-        __le16 freq;
+-        __le16 iq_param[4];
+-} __attribute__ ((packed));
+-
+-struct pda_channel_output_limit {
+-	__le16 freq;
+-	u8 val_bpsk;
+-	u8 val_qpsk;
+-	u8 val_16qam;
+-	u8 val_64qam;
+-	u8 rate_set_mask;
+-	u8 rate_set_size;
+-} __attribute__ ((packed));
+-
+-struct pda_pa_curve_data_sample_rev0 {
+-	u8 rf_power;
+-	u8 pa_detector;
+-	u8 pcv;
+-} __attribute__ ((packed));
+-
+-struct pda_pa_curve_data_sample_rev1 {
+-	u8 rf_power;
+-	u8 pa_detector;
+-	u8 data_barker;
+-	u8 data_bpsk;
+-	u8 data_qpsk;
+-	u8 data_16qam;
+-	u8 data_64qam;
+-	u8 padding;
+-} __attribute__ ((packed));
+-
+-struct pda_pa_curve_data {
+-	u8 cal_method_rev;
+-	u8 channels;
+-	u8 points_per_channel;
+-	u8 padding;
+-	u8 data[0];
+-} __attribute__ ((packed));
+-
+-/*
+- * this defines the PDR codes used to build PDAs as defined in document
+- * number 553155. The current implementation mirrors version 1.1 of the
+- * document and lists only PDRs supported by the ARM platform.
+- */
+-
+-/* common and choice range (0x0000 - 0x0fff) */
+-#define PDR_END					0x0000
+-#define PDR_MANUFACTURING_PART_NUMBER		0x0001
+-#define PDR_PDA_VERSION				0x0002
+-#define PDR_NIC_SERIAL_NUMBER			0x0003
+-
+-#define PDR_MAC_ADDRESS				0x0101
+-#define PDR_REGULATORY_DOMAIN_LIST		0x0103
+-#define PDR_TEMPERATURE_TYPE			0x0107
+-
+-#define PDR_PRISM_PCI_IDENTIFIER		0x0402
+-
+-/* ARM range (0x1000 - 0x1fff) */
+-#define PDR_COUNTRY_INFORMATION			0x1000
+-#define PDR_INTERFACE_LIST			0x1001
+-#define PDR_HARDWARE_PLATFORM_COMPONENT_ID	0x1002
+-#define PDR_OEM_NAME				0x1003
+-#define PDR_PRODUCT_NAME			0x1004
+-#define PDR_UTF8_OEM_NAME			0x1005
+-#define PDR_UTF8_PRODUCT_NAME			0x1006
+-#define PDR_COUNTRY_LIST			0x1007
+-#define PDR_DEFAULT_COUNTRY			0x1008
+-
+-#define PDR_ANTENNA_GAIN			0x1100
+-
+-#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA	0x1901
+-#define PDR_RSSI_LINEAR_APPROXIMATION		0x1902
+-#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS	0x1903
+-#define PDR_PRISM_PA_CAL_CURVE_DATA		0x1904
+-#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND	0x1905
+-#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION		0x1906
+-#define PDR_REGULATORY_POWER_LIMITS		0x1907
+-#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED	0x1908
+-#define PDR_RADIATED_TRANSMISSION_CORRECTION	0x1909
+-#define PDR_PRISM_TX_IQ_CALIBRATION		0x190a
+-
+-/* reserved range (0x2000 - 0x7fff) */
+-
+-/* customer range (0x8000 - 0xffff) */
+-#define PDR_BASEBAND_REGISTERS			0x8000
+-#define PDR_PER_CHANNEL_BASEBAND_REGISTERS	0x8001
+-
+-/* stored in skb->cb */
+-struct memrecord {
+-	u32 start_addr;
+-	u32 end_addr;
+-	struct ieee80211_tx_control *control;
+-};
+-
+-struct p54_eeprom_lm86 {
+-	__le16 offset;
+-	__le16 len;
+-	u8 data[0];
+-} __attribute__ ((packed));
+-
+-struct p54_rx_hdr {
+-	__le16 magic;
+-	__le16 len;
+-	__le16 freq;
+-	u8 antenna;
+-	u8 rate;
+-	u8 rssi;
+-	u8 quality;
+-	u16 unknown2;
+-	__le64 timestamp;
+-	u8 data[0];
+-} __attribute__ ((packed));
+-
+-struct p54_frame_sent_hdr {
+-	u8 status;
+-	u8 retries;
+-	__le16 ack_rssi;
+-	__le16 seq;
+-	u16 rate;
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_allocdata {
+-	u8 rateset[8];
+-	u16 padding;
+-	u8 wep_key_present;
+-	u8 wep_key_len;
+-	u8 wep_key[16];
+-	__le32 frame_type;
+-	u32 padding2;
+-	__le16 magic4;
+-	u8 antenna;
+-	u8 output_power;
+-	__le32 magic5;
+-	u8 align[0];
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_filter {
+-	__le16 filter_type;
+-	u8 dst[ETH_ALEN];
+-	u8 src[ETH_ALEN];
+-	u8 antenna;
+-	u8 debug;
+-	__le32 magic3;
+-	u8 rates[8];	// FIXME: what's this for?
+-	__le32 rx_addr;
+-	__le16 max_rx;
+-	__le16 rxhw;
+-	__le16 magic8;
+-	__le16 magic9;
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_channel {
+-	__le16 magic1;
+-	__le16 magic2;
+-	u8 padding1[20];
+-	struct pda_iq_autocal_entry iq_autocal;
+-	u8 pa_points_per_curve;
+-	u8 val_barker;
+-	u8 val_bpsk;
+-	u8 val_qpsk;
+-	u8 val_16qam;
+-	u8 val_64qam;
+-	struct pda_pa_curve_data_sample_rev1 curve_data[0];
+-	/* additional padding/data after curve_data */
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_led {
+-	__le16 mode;
+-	__le16 led_temporary;
+-	__le16 led_permanent;
+-	__le16 duration;
+-} __attribute__ ((packed));
+-
+-struct p54_tx_vdcf_queues {
+-	__le16 aifs;
+-	__le16 cwmin;
+-	__le16 cwmax;
+-	__le16 txop;
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_vdcf {
+-	u8 padding;
+-	u8 slottime;
+-	u8 magic1;
+-	u8 magic2;
+-	struct p54_tx_vdcf_queues queue[8];
+-	u8 pad2[4];
+-	__le16 frameburst;
+-} __attribute__ ((packed));
+-
+-static const struct ieee80211_rate p54_rates[] = {
+-	{ .rate = 10,
+-	  .val = 0,
+-	  .val2 = 0x10,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 20,
+-	  .val = 1,
+-	  .val2 = 0x11,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 55,
+-	  .val = 2,
+-	  .val2 = 0x12,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 110,
+-	  .val = 3,
+-	  .val2 = 0x13,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 60,
+-	  .val = 4,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 90,
+-	  .val = 5,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 120,
+-	  .val = 6,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 180,
+-	  .val = 7,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 240,
+-	  .val = 8,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 360,
+-	  .val = 9,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 480,
+-	  .val = 10,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 540,
+-	  .val = 11,
+-	  .flags = IEEE80211_RATE_OFDM },
+-};
+-
+-// TODO: just generate this..
+-static const struct ieee80211_channel p54_channels[] = {
+-	{ .chan = 1,
+-	  .freq = 2412},
+-	{ .chan = 2,
+-	  .freq = 2417},
+-	{ .chan = 3,
+-	  .freq = 2422},
+-	{ .chan = 4,
+-	  .freq = 2427},
+-	{ .chan = 5,
+-	  .freq = 2432},
+-	{ .chan = 6,
+-	  .freq = 2437},
+-	{ .chan = 7,
+-	  .freq = 2442},
+-	{ .chan = 8,
+-	  .freq = 2447},
+-	{ .chan = 9,
+-	  .freq = 2452},
+-	{ .chan = 10,
+-	  .freq = 2457},
+-	{ .chan = 11,
+-	  .freq = 2462},
+-	{ .chan = 12,
+-	  .freq = 2467},
+-	{ .chan = 13,
+-	  .freq = 2472},
+-	{ .chan = 14,
+-	  .freq = 2484}
+-};
+-
+-#endif /* PRISM54COMMON_H */
+diff --git a/drivers/net/wireless/p54pci.c b/drivers/net/wireless/p54pci.c
+deleted file mode 100644
+index fa52772..0000000
+--- a/drivers/net/wireless/p54pci.c
++++ /dev/null
+@@ -1,697 +0,0 @@
+-
+-/*
+- * Linux device driver for PCI based Prism54
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note at m4x.org>, et al.
+- *
+- * This program is free software; you can redistribute it 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/pci.h>
+-#include <linux/firmware.h>
+-#include <linux/etherdevice.h>
+-#include <linux/delay.h>
+-#include <linux/completion.h>
+-#include <net/mac80211.h>
+-
+-#include "p54.h"
+-#include "p54pci.h"
+-
+-MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
+-MODULE_DESCRIPTION("Prism54 PCI wireless driver");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("prism54pci");
+-
+-static struct pci_device_id p54p_table[] __devinitdata = {
+-	/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
+-	{ PCI_DEVICE(0x1260, 0x3890) },
+-	/* 3COM 3CRWE154G72 Wireless LAN adapter */
+-	{ PCI_DEVICE(0x10b7, 0x6001) },
+-	/* Intersil PRISM Indigo Wireless LAN adapter */
+-	{ PCI_DEVICE(0x1260, 0x3877) },
+-	/* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
+-	{ PCI_DEVICE(0x1260, 0x3886) },
+-	{ },
+-};
+-
+-MODULE_DEVICE_TABLE(pci, p54p_table);
+-
+-static int p54p_upload_firmware(struct ieee80211_hw *dev)
+-{
+-	struct p54p_priv *priv = dev->priv;
+-	const struct firmware *fw_entry = NULL;
+-	__le32 reg;
+-	int err;
+-	__le32 *data;
+-	u32 remains, left, device_addr;
+-
+-	P54P_WRITE(int_enable, cpu_to_le32(0));
+-	P54P_READ(int_enable);
+-	udelay(10);
+-
+-	reg = P54P_READ(ctrl_stat);
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
+-	P54P_WRITE(ctrl_stat, reg);
+-	P54P_READ(ctrl_stat);
+-	udelay(10);
+-
+-	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
+-	P54P_WRITE(ctrl_stat, reg);
+-	wmb();
+-	udelay(10);
+-
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+-	P54P_WRITE(ctrl_stat, reg);
+-	wmb();
+-
+-	mdelay(50);
+-
+-	err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
+-	if (err) {
+-		printk(KERN_ERR "%s (prism54pci): cannot find firmware "
+-		       "(isl3886)\n", pci_name(priv->pdev));
+-		return err;
+-	}
+-
+-	p54_parse_firmware(dev, fw_entry);
+-
+-	data = (__le32 *) fw_entry->data;
+-	remains = fw_entry->size;
+-	device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
+-	while (remains) {
+-		u32 i = 0;
+-		left = min((u32)0x1000, remains);
+-		P54P_WRITE(direct_mem_base, cpu_to_le32(device_addr));
+-		P54P_READ(int_enable);
+-
+-		device_addr += 0x1000;
+-		while (i < left) {
+-			P54P_WRITE(direct_mem_win[i], *data++);
+-			i += sizeof(u32);
+-		}
+-
+-		remains -= left;
+-		P54P_READ(int_enable);
+-	}
+-
+-	release_firmware(fw_entry);
+-
+-	reg = P54P_READ(ctrl_stat);
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+-	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
+-	P54P_WRITE(ctrl_stat, reg);
+-	P54P_READ(ctrl_stat);
+-	udelay(10);
+-
+-	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
+-	P54P_WRITE(ctrl_stat, reg);
+-	wmb();
+-	udelay(10);
+-
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+-	P54P_WRITE(ctrl_stat, reg);
+-	wmb();
+-	udelay(10);
+-
+-	return 0;
+-}
+-
+-static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id)
+-{
+-	struct p54p_priv *priv = (struct p54p_priv *) dev_id;
+-	__le32 reg;
+-
+-	reg = P54P_READ(int_ident);
+-	P54P_WRITE(int_ack, reg);
+-
+-	if (reg & P54P_READ(int_enable))
+-		complete(&priv->boot_comp);
+-
+-	return IRQ_HANDLED;
+-}
+-
+-static int p54p_read_eeprom(struct ieee80211_hw *dev)
+-{
+-	struct p54p_priv *priv = dev->priv;
+-	struct p54p_ring_control *ring_control = priv->ring_control;
+-	int err;
+-	struct p54_control_hdr *hdr;
+-	void *eeprom;
+-	dma_addr_t rx_mapping, tx_mapping;
+-	u16 alen;
+-
+-	init_completion(&priv->boot_comp);
+-	err = request_irq(priv->pdev->irq, &p54p_simple_interrupt,
+-			  IRQF_SHARED, "prism54pci", priv);
+-	if (err) {
+-		printk(KERN_ERR "%s (prism54pci): failed to register IRQ handler\n",
+-		       pci_name(priv->pdev));
+-		return err;
+-	}
+-
+-	eeprom = kmalloc(0x2010 + EEPROM_READBACK_LEN, GFP_KERNEL);
+-	if (!eeprom) {
+-		printk(KERN_ERR "%s (prism54pci): no memory for eeprom!\n",
+-		       pci_name(priv->pdev));
+-		err = -ENOMEM;
+-		goto out;
+-	}
+-
+-	memset(ring_control, 0, sizeof(*ring_control));
+-	P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
+-	P54P_READ(ring_control_base);
+-	udelay(10);
+-
+-	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
+-	P54P_READ(int_enable);
+-	udelay(10);
+-
+-	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
+-
+-	if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
+-		printk(KERN_ERR "%s (prism54pci): Cannot boot firmware!\n",
+-		       pci_name(priv->pdev));
+-		err = -EINVAL;
+-		goto out;
+-	}
+-
+-	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
+-	P54P_READ(int_enable);
+-
+-	hdr = eeprom + 0x2010;
+-	p54_fill_eeprom_readback(hdr);
+-	hdr->req_id = cpu_to_le32(priv->common.rx_start);
+-
+-	rx_mapping = pci_map_single(priv->pdev, eeprom,
+-				    0x2010, PCI_DMA_FROMDEVICE);
+-	tx_mapping = pci_map_single(priv->pdev, (void *)hdr,
+-				    EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
+-
+-	ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping);
+-	ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010);
+-	ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping);
+-	ring_control->tx_data[0].device_addr = hdr->req_id;
+-	ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN);
+-
+-	ring_control->host_idx[2] = cpu_to_le32(1);
+-	ring_control->host_idx[1] = cpu_to_le32(1);
+-
+-	wmb();
+-	mdelay(100);
+-	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+-
+-	wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
+-	wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
+-
+-	pci_unmap_single(priv->pdev, tx_mapping,
+-			 EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
+-	pci_unmap_single(priv->pdev, rx_mapping,
+-			 0x2010, PCI_DMA_FROMDEVICE);
+-
+-	alen = le16_to_cpu(ring_control->rx_mgmt[0].len);
+-	if (le32_to_cpu(ring_control->device_idx[2]) != 1 ||
+-	    alen < 0x10) {
+-		printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n",
+-		       pci_name(priv->pdev));
+-		err = -EINVAL;
+-		goto out;
+-	}
+-
+-	p54_parse_eeprom(dev, (u8 *)eeprom + 0x10, alen - 0x10);
+-
+- out:
+-	kfree(eeprom);
+-	P54P_WRITE(int_enable, cpu_to_le32(0));
+-	P54P_READ(int_enable);
+-	udelay(10);
+-	free_irq(priv->pdev->irq, priv);
+-	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
+-	return err;
+-}
+-
+-static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
+-{
+-	struct p54p_priv *priv = dev->priv;
+-	struct p54p_ring_control *ring_control = priv->ring_control;
+-	u32 limit, host_idx, idx;
+-
+-	host_idx = le32_to_cpu(ring_control->host_idx[0]);
+-	limit = host_idx;
+-	limit -= le32_to_cpu(ring_control->device_idx[0]);
+-	limit = ARRAY_SIZE(ring_control->rx_data) - limit;
+-
+-	idx = host_idx % ARRAY_SIZE(ring_control->rx_data);
+-	while (limit-- > 1) {
+-		struct p54p_desc *desc = &ring_control->rx_data[idx];
+-
+-		if (!desc->host_addr) {
+-			struct sk_buff *skb;
+-			dma_addr_t mapping;
+-			skb = dev_alloc_skb(MAX_RX_SIZE);
+-			if (!skb)
+-				break;
+-
+-			mapping = pci_map_single(priv->pdev,
+-						 skb_tail_pointer(skb),
+-						 MAX_RX_SIZE,
+-						 PCI_DMA_FROMDEVICE);
+-			desc->host_addr = cpu_to_le32(mapping);
+-			desc->device_addr = 0;	// FIXME: necessary?
+-			desc->len = cpu_to_le16(MAX_RX_SIZE);
+-			desc->flags = 0;
+-			priv->rx_buf[idx] = skb;
+-		}
+-
+-		idx++;
+-		host_idx++;
+-		idx %= ARRAY_SIZE(ring_control->rx_data);
+-	}
+-
+-	wmb();
+-	ring_control->host_idx[0] = cpu_to_le32(host_idx);
+-}
+-
+-static irqreturn_t p54p_interrupt(int irq, void *dev_id)
+-{
+-	struct ieee80211_hw *dev = dev_id;
+-	struct p54p_priv *priv = dev->priv;
+-	struct p54p_ring_control *ring_control = priv->ring_control;
+-	__le32 reg;
+-
+-	spin_lock(&priv->lock);
+-	reg = P54P_READ(int_ident);
+-	if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
+-		spin_unlock(&priv->lock);
+-		return IRQ_HANDLED;
+-	}
+-
+-	P54P_WRITE(int_ack, reg);
+-
+-	reg &= P54P_READ(int_enable);
+-
+-	if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
+-		struct p54p_desc *desc;
+-		u32 idx, i;
+-		i = priv->tx_idx;
+-		i %= ARRAY_SIZE(ring_control->tx_data);
+-		priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
+-		idx %= ARRAY_SIZE(ring_control->tx_data);
+-
+-		while (i != idx) {
+-			desc = &ring_control->tx_data[i];
+-			if (priv->tx_buf[i]) {
+-				kfree(priv->tx_buf[i]);
+-				priv->tx_buf[i] = NULL;
+-			}
+-
+-			pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
+-					 le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
+-
+-			desc->host_addr = 0;
+-			desc->device_addr = 0;
+-			desc->len = 0;
+-			desc->flags = 0;
+-
+-			i++;
+-			i %= ARRAY_SIZE(ring_control->tx_data);
+-		}
+-
+-		i = priv->rx_idx;
+-		i %= ARRAY_SIZE(ring_control->rx_data);
+-		priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
+-		idx %= ARRAY_SIZE(ring_control->rx_data);
+-		while (i != idx) {
+-			u16 len;
+-			struct sk_buff *skb;
+-			desc = &ring_control->rx_data[i];
+-			len = le16_to_cpu(desc->len);
+-			skb = priv->rx_buf[i];
+-
+-			skb_put(skb, len);
+-
+-			if (p54_rx(dev, skb)) {
+-				pci_unmap_single(priv->pdev,
+-						 le32_to_cpu(desc->host_addr),
+-						 MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+-
+-				priv->rx_buf[i] = NULL;
+-				desc->host_addr = 0;
+-			} else {
+-				skb_trim(skb, 0);
+-				desc->len = cpu_to_le16(MAX_RX_SIZE);
+-			}
+-
+-			i++;
+-			i %= ARRAY_SIZE(ring_control->rx_data);
+-		}
+-
+-		p54p_refill_rx_ring(dev);
+-
+-		wmb();
+-		P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+-	} else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
+-		complete(&priv->boot_comp);
+-
+-	spin_unlock(&priv->lock);
+-
+-	return reg ? IRQ_HANDLED : IRQ_NONE;
+-}
+-
+-static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
+-		    size_t len, int free_on_tx)
+-{
+-	struct p54p_priv *priv = dev->priv;
+-	struct p54p_ring_control *ring_control = priv->ring_control;
+-	unsigned long flags;
+-	struct p54p_desc *desc;
+-	dma_addr_t mapping;
+-	u32 device_idx, idx, i;
+-
+-	spin_lock_irqsave(&priv->lock, flags);
+-
+-	device_idx = le32_to_cpu(ring_control->device_idx[1]);
+-	idx = le32_to_cpu(ring_control->host_idx[1]);
+-	i = idx % ARRAY_SIZE(ring_control->tx_data);
+-
+-	mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
+-	desc = &ring_control->tx_data[i];
+-	desc->host_addr = cpu_to_le32(mapping);
+-	desc->device_addr = data->req_id;
+-	desc->len = cpu_to_le16(len);
+-	desc->flags = 0;
+-
+-	wmb();
+-	ring_control->host_idx[1] = cpu_to_le32(idx + 1);
+-
+-	if (free_on_tx)
+-		priv->tx_buf[i] = data;
+-
+-	spin_unlock_irqrestore(&priv->lock, flags);
+-
+-	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+-	P54P_READ(dev_int);
+-
+-	/* FIXME: unlikely to happen because the device usually runs out of
+-	   memory before we fill the ring up, but we can make it impossible */
+-	if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
+-		printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
+-}
+-
+-static int p54p_open(struct ieee80211_hw *dev)
+-{
+-	struct p54p_priv *priv = dev->priv;
+-	int err;
+-
+-	init_completion(&priv->boot_comp);
+-	err = request_irq(priv->pdev->irq, &p54p_interrupt,
+-			  IRQF_SHARED, "prism54pci", dev);
+-	if (err) {
+-		printk(KERN_ERR "%s: failed to register IRQ handler\n",
+-		       wiphy_name(dev->wiphy));
+-		return err;
+-	}
+-
+-	memset(priv->ring_control, 0, sizeof(*priv->ring_control));
+-	priv->rx_idx = priv->tx_idx = 0;
+-	p54p_refill_rx_ring(dev);
+-
+-	p54p_upload_firmware(dev);
+-
+-	P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
+-	P54P_READ(ring_control_base);
+-	wmb();
+-	udelay(10);
+-
+-	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
+-	P54P_READ(int_enable);
+-	wmb();
+-	udelay(10);
+-
+-	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
+-	P54P_READ(dev_int);
+-
+-	if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
+-		printk(KERN_ERR "%s: Cannot boot firmware!\n",
+-		       wiphy_name(dev->wiphy));
+-		free_irq(priv->pdev->irq, dev);
+-		return -ETIMEDOUT;
+-	}
+-
+-	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
+-	P54P_READ(int_enable);
+-	wmb();
+-	udelay(10);
+-
+-	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+-	P54P_READ(dev_int);
+-	wmb();
+-	udelay(10);
+-
+-	return 0;
+-}
+-
+-static void p54p_stop(struct ieee80211_hw *dev)
+-{
+-	struct p54p_priv *priv = dev->priv;
+-	struct p54p_ring_control *ring_control = priv->ring_control;
+-	unsigned int i;
+-	struct p54p_desc *desc;
+-
+-	P54P_WRITE(int_enable, cpu_to_le32(0));
+-	P54P_READ(int_enable);
+-	udelay(10);
+-
+-	free_irq(priv->pdev->irq, dev);
+-
+-	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
+-
+-	for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) {
+-		desc = &ring_control->rx_data[i];
+-		if (desc->host_addr)
+-			pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
+-					 MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+-		kfree_skb(priv->rx_buf[i]);
+-		priv->rx_buf[i] = NULL;
+-	}
+-
+-	for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) {
+-		desc = &ring_control->tx_data[i];
+-		if (desc->host_addr)
+-			pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
+-					 le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
+-
+-		kfree(priv->tx_buf[i]);
+-		priv->tx_buf[i] = NULL;
+-	}
+-
+-	memset(ring_control, 0, sizeof(ring_control));
+-}
+-
+-static int __devinit p54p_probe(struct pci_dev *pdev,
+-				const struct pci_device_id *id)
+-{
+-	struct p54p_priv *priv;
+-	struct ieee80211_hw *dev;
+-	unsigned long mem_addr, mem_len;
+-	int err;
+-	DECLARE_MAC_BUF(mac);
+-
+-	err = pci_enable_device(pdev);
+-	if (err) {
+-		printk(KERN_ERR "%s (prism54pci): Cannot enable new PCI device\n",
+-		       pci_name(pdev));
+-		return err;
+-	}
+-
+-	mem_addr = pci_resource_start(pdev, 0);
+-	mem_len = pci_resource_len(pdev, 0);
+-	if (mem_len < sizeof(struct p54p_csr)) {
+-		printk(KERN_ERR "%s (prism54pci): Too short PCI resources\n",
+-		       pci_name(pdev));
+-		pci_disable_device(pdev);
+-		return err;
+-	}
+-
+-	err = pci_request_regions(pdev, "prism54pci");
+-	if (err) {
+-		printk(KERN_ERR "%s (prism54pci): Cannot obtain PCI resources\n",
+-		       pci_name(pdev));
+-		return err;
+-	}
+-
+-	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
+-	    pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+-		printk(KERN_ERR "%s (prism54pci): No suitable DMA available\n",
+-		       pci_name(pdev));
+-		goto err_free_reg;
+-	}
+-
+-	pci_set_master(pdev);
+-	pci_try_set_mwi(pdev);
+-
+-	pci_write_config_byte(pdev, 0x40, 0);
+-	pci_write_config_byte(pdev, 0x41, 0);
+-
+-	dev = p54_init_common(sizeof(*priv));
+-	if (!dev) {
+-		printk(KERN_ERR "%s (prism54pci): ieee80211 alloc failed\n",
+-		       pci_name(pdev));
+-		err = -ENOMEM;
+-		goto err_free_reg;
+-	}
+-
+-	priv = dev->priv;
+-	priv->pdev = pdev;
+-
+-	SET_IEEE80211_DEV(dev, &pdev->dev);
+-	pci_set_drvdata(pdev, dev);
+-
+-	priv->map = ioremap(mem_addr, mem_len);
+-	if (!priv->map) {
+-		printk(KERN_ERR "%s (prism54pci): Cannot map device memory\n",
+-		       pci_name(pdev));
+-		err = -EINVAL;	// TODO: use a better error code?
+-		goto err_free_dev;
+-	}
+-
+-	priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control),
+-						  &priv->ring_control_dma);
+-	if (!priv->ring_control) {
+-		printk(KERN_ERR "%s (prism54pci): Cannot allocate rings\n",
+-		       pci_name(pdev));
+-		err = -ENOMEM;
+-		goto err_iounmap;
+-	}
+-	memset(priv->ring_control, 0, sizeof(*priv->ring_control));
+-
+-	err = p54p_upload_firmware(dev);
+-	if (err)
+-		goto err_free_desc;
+-
+-	err = p54p_read_eeprom(dev);
+-	if (err)
+-		goto err_free_desc;
+-
+-	priv->common.open = p54p_open;
+-	priv->common.stop = p54p_stop;
+-	priv->common.tx = p54p_tx;
+-
+-	spin_lock_init(&priv->lock);
+-
+-	err = ieee80211_register_hw(dev);
+-	if (err) {
+-		printk(KERN_ERR "%s (prism54pci): Cannot register netdevice\n",
+-		       pci_name(pdev));
+-		goto err_free_common;
+-	}
+-
+-	printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
+-	       wiphy_name(dev->wiphy),
+-	       print_mac(mac, dev->wiphy->perm_addr),
+-	       priv->common.version);
+-
+-	return 0;
+-
+- err_free_common:
+-	p54_free_common(dev);
+-
+- err_free_desc:
+-	pci_free_consistent(pdev, sizeof(*priv->ring_control),
+-			    priv->ring_control, priv->ring_control_dma);
+-
+- err_iounmap:
+-	iounmap(priv->map);
+-
+- err_free_dev:
+-	pci_set_drvdata(pdev, NULL);
+-	ieee80211_free_hw(dev);
+-
+- err_free_reg:
+-	pci_release_regions(pdev);
+-	pci_disable_device(pdev);
+-	return err;
+-}
+-
+-static void __devexit p54p_remove(struct pci_dev *pdev)
+-{
+-	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+-	struct p54p_priv *priv;
+-
+-	if (!dev)
+-		return;
+-
+-	ieee80211_unregister_hw(dev);
+-	priv = dev->priv;
+-	pci_free_consistent(pdev, sizeof(*priv->ring_control),
+-			    priv->ring_control, priv->ring_control_dma);
+-	p54_free_common(dev);
+-	iounmap(priv->map);
+-	pci_release_regions(pdev);
+-	pci_disable_device(pdev);
+-	ieee80211_free_hw(dev);
+-}
+-
+-#ifdef CONFIG_PM
+-static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+-	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+-	struct p54p_priv *priv = dev->priv;
+-
+-	if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
+-		ieee80211_stop_queues(dev);
+-		p54p_stop(dev);
+-	}
+-
+-	pci_save_state(pdev);
+-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+-	return 0;
+-}
+-
+-static int p54p_resume(struct pci_dev *pdev)
+-{
+-	struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+-	struct p54p_priv *priv = dev->priv;
+-
+-	pci_set_power_state(pdev, PCI_D0);
+-	pci_restore_state(pdev);
+-
+-	if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
+-		p54p_open(dev);
+-		ieee80211_start_queues(dev);
+-	}
+-
+-	return 0;
+-}
+-#endif /* CONFIG_PM */
+-
+-static struct pci_driver p54p_driver = {
+-	.name		= "prism54pci",
+-	.id_table	= p54p_table,
+-	.probe		= p54p_probe,
+-	.remove		= __devexit_p(p54p_remove),
+-#ifdef CONFIG_PM
+-	.suspend	= p54p_suspend,
+-	.resume		= p54p_resume,
+-#endif /* CONFIG_PM */
+-};
+-
+-static int __init p54p_init(void)
+-{
+-	return pci_register_driver(&p54p_driver);
+-}
+-
+-static void __exit p54p_exit(void)
+-{
+-	pci_unregister_driver(&p54p_driver);
+-}
+-
+-module_init(p54p_init);
+-module_exit(p54p_exit);
+diff --git a/drivers/net/wireless/p54pci.h b/drivers/net/wireless/p54pci.h
+deleted file mode 100644
+index 5bedd7a..0000000
+--- a/drivers/net/wireless/p54pci.h
++++ /dev/null
+@@ -1,106 +0,0 @@
+-#ifndef PRISM54PCI_H
+-#define PRISM54PCI_H
+-
+-/*
+- * Defines for PCI based mac80211 Prism54 driver
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/* Device Interrupt register bits */
+-#define ISL38XX_DEV_INT_RESET                   0x0001
+-#define ISL38XX_DEV_INT_UPDATE                  0x0002
+-#define ISL38XX_DEV_INT_WAKEUP                  0x0008
+-#define ISL38XX_DEV_INT_SLEEP                   0x0010
+-#define ISL38XX_DEV_INT_ABORT                   0x0020
+-/* these two only used in USB */
+-#define ISL38XX_DEV_INT_DATA                    0x0040
+-#define ISL38XX_DEV_INT_MGMT                    0x0080
+-
+-#define ISL38XX_DEV_INT_PCIUART_CTS             0x4000
+-#define ISL38XX_DEV_INT_PCIUART_DR              0x8000
+-
+-/* Interrupt Identification/Acknowledge/Enable register bits */
+-#define ISL38XX_INT_IDENT_UPDATE		0x0002
+-#define ISL38XX_INT_IDENT_INIT			0x0004
+-#define ISL38XX_INT_IDENT_WAKEUP		0x0008
+-#define ISL38XX_INT_IDENT_SLEEP			0x0010
+-#define ISL38XX_INT_IDENT_PCIUART_CTS		0x4000
+-#define ISL38XX_INT_IDENT_PCIUART_DR		0x8000
+-
+-/* Control/Status register bits */
+-#define ISL38XX_CTRL_STAT_SLEEPMODE		0x00000200
+-#define ISL38XX_CTRL_STAT_CLKRUN		0x00800000
+-#define ISL38XX_CTRL_STAT_RESET			0x10000000
+-#define ISL38XX_CTRL_STAT_RAMBOOT		0x20000000
+-#define ISL38XX_CTRL_STAT_STARTHALTED		0x40000000
+-#define ISL38XX_CTRL_STAT_HOST_OVERRIDE		0x80000000
+-
+-struct p54p_csr {
+-	__le32 dev_int;
+-	u8 unused_1[12];
+-	__le32 int_ident;
+-	__le32 int_ack;
+-	__le32 int_enable;
+-	u8 unused_2[4];
+-	union {
+-		__le32 ring_control_base;
+-		__le32 gen_purp_com[2];
+-	};
+-	u8 unused_3[8];
+-	__le32 direct_mem_base;
+-	u8 unused_4[44];
+-	__le32 dma_addr;
+-	__le32 dma_len;
+-	__le32 dma_ctrl;
+-	u8 unused_5[12];
+-	__le32 ctrl_stat;
+-	u8 unused_6[1924];
+-	u8 cardbus_cis[0x800];
+-	u8 direct_mem_win[0x1000];
+-} __attribute__ ((packed));
+-
+-/* usb backend only needs the register defines above */
+-#ifndef PRISM54USB_H
+-struct p54p_desc {
+-	__le32 host_addr;
+-	__le32 device_addr;
+-	__le16 len;
+-	__le16 flags;
+-} __attribute__ ((packed));
+-
+-struct p54p_ring_control {
+-	__le32 host_idx[4];
+-	__le32 device_idx[4];
+-	struct p54p_desc rx_data[8];
+-	struct p54p_desc tx_data[32];
+-	struct p54p_desc rx_mgmt[4];
+-	struct p54p_desc tx_mgmt[4];
+-} __attribute__ ((packed));
+-
+-#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r)
+-#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r)
+-
+-struct p54p_priv {
+-	struct p54_common common;
+-	struct pci_dev *pdev;
+-	struct p54p_csr __iomem *map;
+-
+-	spinlock_t lock;
+-	struct p54p_ring_control *ring_control;
+-	dma_addr_t ring_control_dma;
+-	u32 rx_idx, tx_idx;
+-	struct sk_buff *rx_buf[8];
+-	void *tx_buf[32];
+-	struct completion boot_comp;
+-};
+-
+-#endif /* PRISM54USB_H */
+-#endif /* PRISM54PCI_H */
+diff --git a/drivers/net/wireless/p54usb.c b/drivers/net/wireless/p54usb.c
+deleted file mode 100644
+index 98ddbb3..0000000
+--- a/drivers/net/wireless/p54usb.c
++++ /dev/null
+@@ -1,910 +0,0 @@
+-
+-/*
+- * Linux device driver for USB based Prism54
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it 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/usb.h>
+-#include <linux/pci.h>
+-#include <linux/firmware.h>
+-#include <linux/etherdevice.h>
+-#include <linux/delay.h>
+-#include <linux/crc32.h>
+-#include <net/mac80211.h>
+-
+-#include "p54.h"
+-#include "p54usb.h"
+-
+-MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
+-MODULE_DESCRIPTION("Prism54 USB wireless driver");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("prism54usb");
+-
+-static struct usb_device_id p54u_table[] __devinitdata = {
+-	/* Version 1 devices (pci chip + net2280) */
+-	{USB_DEVICE(0x0506, 0x0a11)},	/* 3COM 3CRWE254G72 */
+-	{USB_DEVICE(0x0707, 0xee06)},	/* SMC 2862W-G */
+-	{USB_DEVICE(0x083a, 0x4501)},	/* Accton 802.11g WN4501 USB */
+-	{USB_DEVICE(0x083a, 0x4502)},	/* Siemens Gigaset USB Adapter */
+-	{USB_DEVICE(0x083a, 0x5501)},	/* Phillips CPWUA054 */
+-	{USB_DEVICE(0x0846, 0x4200)},	/* Netgear WG121 */
+-	{USB_DEVICE(0x0846, 0x4210)},	/* Netgear WG121 the second ? */
+-	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */
+-	{USB_DEVICE(0x0cde, 0x0006)},	/* Medion 40900, Roper Europe */
+-	{USB_DEVICE(0x124a, 0x4023)},	/* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
+-	{USB_DEVICE(0x1915, 0x2234)},	/* Linksys WUSB54G OEM */
+-	{USB_DEVICE(0x1915, 0x2235)},	/* Linksys WUSB54G Portable OEM */
+-	{USB_DEVICE(0x2001, 0x3701)},	/* DLink DWL-G120 Spinnaker */
+-	{USB_DEVICE(0x2001, 0x3703)},	/* DLink DWL-G122 */
+-	{USB_DEVICE(0x5041, 0x2234)},	/* Linksys WUSB54G */
+-	{USB_DEVICE(0x5041, 0x2235)},	/* Linksys WUSB54G Portable */
+-
+-	/* Version 2 devices (3887) */
+-	{USB_DEVICE(0x050d, 0x7050)},	/* Belkin F5D7050 ver 1000 */
+-	{USB_DEVICE(0x0572, 0x2000)},	/* Cohiba Proto board */
+-	{USB_DEVICE(0x0572, 0x2002)},	/* Cohiba Proto board */
+-	{USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
+-	{USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
+-	{USB_DEVICE(0x0846, 0x4240)},	/* Netgear WG111 (v2) */
+-	{USB_DEVICE(0x0915, 0x2000)},	/* Cohiba Proto board */
+-	{USB_DEVICE(0x0915, 0x2002)},	/* Cohiba Proto board */
+-	{USB_DEVICE(0x0baf, 0x0118)},   /* U.S. Robotics U5 802.11g Adapter*/
+-	{USB_DEVICE(0x0bf8, 0x1009)},   /* FUJITSU E-5400 USB D1700*/
+-	{USB_DEVICE(0x0cde, 0x0006)},   /* Medion MD40900 */
+-	{USB_DEVICE(0x0cde, 0x0008)},	/* Sagem XG703A */
+-	{USB_DEVICE(0x0d8e, 0x3762)},	/* DLink DWL-G120 Cohiba */
+-	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */
+-	{USB_DEVICE(0x124a, 0x4025)},	/* IOGear GWU513 (GW3887IK chip) */
+-	{USB_DEVICE(0x13b1, 0x000a)},	/* Linksys WUSB54G ver 2 */
+-	{USB_DEVICE(0x13B1, 0x000C)},	/* Linksys WUSB54AG */
+-	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */
+-	{USB_DEVICE(0x2001, 0x3704)},	/* DLink DWL-G122 rev A2 */
+-	{USB_DEVICE(0x413c, 0x8102)},	/* Spinnaker DUT */
+-	{USB_DEVICE(0x413c, 0x8104)},	/* Cohiba Proto board */
+-	{}
+-};
+-
+-MODULE_DEVICE_TABLE(usb, p54u_table);
+-
+-static void p54u_rx_cb(struct urb *urb)
+-{
+-	struct sk_buff *skb = (struct sk_buff *) urb->context;
+-	struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
+-	struct ieee80211_hw *dev = info->dev;
+-	struct p54u_priv *priv = dev->priv;
+-
+-	if (unlikely(urb->status)) {
+-		info->urb = NULL;
+-		usb_free_urb(urb);
+-		return;
+-	}
+-
+-	skb_unlink(skb, &priv->rx_queue);
+-	skb_put(skb, urb->actual_length);
+-	if (!priv->hw_type)
+-		skb_pull(skb, sizeof(struct net2280_tx_hdr));
+-
+-	if (p54_rx(dev, skb)) {
+-		skb = dev_alloc_skb(MAX_RX_SIZE);
+-		if (unlikely(!skb)) {
+-			usb_free_urb(urb);
+-			/* TODO check rx queue length and refill *somewhere* */
+-			return;
+-		}
+-
+-		info = (struct p54u_rx_info *) skb->cb;
+-		info->urb = urb;
+-		info->dev = dev;
+-		urb->transfer_buffer = skb_tail_pointer(skb);
+-		urb->context = skb;
+-		skb_queue_tail(&priv->rx_queue, skb);
+-	} else {
+-		skb_trim(skb, 0);
+-		skb_queue_tail(&priv->rx_queue, skb);
+-	}
+-
+-	usb_submit_urb(urb, GFP_ATOMIC);
+-}
+-
+-static void p54u_tx_cb(struct urb *urb)
+-{
+-	usb_free_urb(urb);
+-}
+-
+-static void p54u_tx_free_cb(struct urb *urb)
+-{
+-	kfree(urb->transfer_buffer);
+-	usb_free_urb(urb);
+-}
+-
+-static int p54u_init_urbs(struct ieee80211_hw *dev)
+-{
+-	struct p54u_priv *priv = dev->priv;
+-	struct urb *entry;
+-	struct sk_buff *skb;
+-	struct p54u_rx_info *info;
+-
+-	while (skb_queue_len(&priv->rx_queue) < 32) {
+-		skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL);
+-		if (!skb)
+-			break;
+-		entry = usb_alloc_urb(0, GFP_KERNEL);
+-		if (!entry) {
+-			kfree_skb(skb);
+-			break;
+-		}
+-		usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb);
+-		info = (struct p54u_rx_info *) skb->cb;
+-		info->urb = entry;
+-		info->dev = dev;
+-		skb_queue_tail(&priv->rx_queue, skb);
+-		usb_submit_urb(entry, GFP_KERNEL);
+-	}
+-
+-	return 0;
+-}
+-
+-static void p54u_free_urbs(struct ieee80211_hw *dev)
+-{
+-	struct p54u_priv *priv = dev->priv;
+-	struct p54u_rx_info *info;
+-	struct sk_buff *skb;
+-
+-	while ((skb = skb_dequeue(&priv->rx_queue))) {
+-		info = (struct p54u_rx_info *) skb->cb;
+-		if (!info->urb)
+-			continue;
+-
+-		usb_kill_urb(info->urb);
+-		kfree_skb(skb);
+-	}
+-}
+-
+-static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
+-			 size_t len, int free_on_tx)
+-{
+-	struct p54u_priv *priv = dev->priv;
+-	struct urb *addr_urb, *data_urb;
+-
+-	addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
+-	if (!addr_urb)
+-		return;
+-
+-	data_urb = usb_alloc_urb(0, GFP_ATOMIC);
+-	if (!data_urb) {
+-		usb_free_urb(addr_urb);
+-		return;
+-	}
+-
+-	usb_fill_bulk_urb(addr_urb, priv->udev,
+-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
+-		sizeof(data->req_id), p54u_tx_cb, dev);
+-	usb_fill_bulk_urb(data_urb, priv->udev,
+-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
+-		free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+-
+-	usb_submit_urb(addr_urb, GFP_ATOMIC);
+-	usb_submit_urb(data_urb, GFP_ATOMIC);
+-}
+-
+-static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
+-			    size_t len, int free_on_tx)
+-{
+-	struct p54u_priv *priv = dev->priv;
+-	struct urb *int_urb, *data_urb;
+-	struct net2280_tx_hdr *hdr;
+-	struct net2280_reg_write *reg;
+-
+-	reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
+-	if (!reg)
+-		return;
+-
+-	int_urb = usb_alloc_urb(0, GFP_ATOMIC);
+-	if (!int_urb) {
+-		kfree(reg);
+-		return;
+-	}
+-
+-	data_urb = usb_alloc_urb(0, GFP_ATOMIC);
+-	if (!data_urb) {
+-		kfree(reg);
+-		usb_free_urb(int_urb);
+-		return;
+-	}
+-
+-	reg->port = cpu_to_le16(NET2280_DEV_U32);
+-	reg->addr = cpu_to_le32(P54U_DEV_BASE);
+-	reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
+-
+-	len += sizeof(*data);
+-	hdr = (void *)data - sizeof(*hdr);
+-	memset(hdr, 0, sizeof(*hdr));
+-	hdr->device_addr = data->req_id;
+-	hdr->len = cpu_to_le16(len);
+-
+-	usb_fill_bulk_urb(int_urb, priv->udev,
+-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
+-		p54u_tx_free_cb, dev);
+-	usb_submit_urb(int_urb, GFP_ATOMIC);
+-
+-	usb_fill_bulk_urb(data_urb, priv->udev,
+-		usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
+-		free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+-	usb_submit_urb(data_urb, GFP_ATOMIC);
+-}
+-
+-static int p54u_write(struct p54u_priv *priv,
+-		      struct net2280_reg_write *buf,
+-		      enum net2280_op_type type,
+-		      __le32 addr, __le32 val)
+-{
+-	unsigned int ep;
+-	int alen;
+-
+-	if (type & 0x0800)
+-		ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
+-	else
+-		ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
+-
+-	buf->port = cpu_to_le16(type);
+-	buf->addr = addr;
+-	buf->val = val;
+-
+-	return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
+-}
+-
+-static int p54u_read(struct p54u_priv *priv, void *buf,
+-		     enum net2280_op_type type,
+-		     __le32 addr, __le32 *val)
+-{
+-	struct net2280_reg_read *read = buf;
+-	__le32 *reg = buf;
+-	unsigned int ep;
+-	int alen, err;
+-
+-	if (type & 0x0800)
+-		ep = P54U_PIPE_DEV;
+-	else
+-		ep = P54U_PIPE_BRG;
+-
+-	read->port = cpu_to_le16(type);
+-	read->addr = addr;
+-
+-	err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
+-			   read, sizeof(*read), &alen, 1000);
+-	if (err)
+-		return err;
+-
+-	err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
+-			   reg, sizeof(*reg), &alen, 1000);
+-	if (err)
+-		return err;
+-
+-	*val = *reg;
+-	return 0;
+-}
+-
+-static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
+-			 void *data, size_t len)
+-{
+-	int alen;
+-	return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
+-			    data, len, &alen, 2000);
+-}
+-
+-static int p54u_read_eeprom(struct ieee80211_hw *dev)
+-{
+-	struct p54u_priv *priv = dev->priv;
+-	void *buf;
+-	struct p54_control_hdr *hdr;
+-	int err, alen;
+-	size_t offset = priv->hw_type ? 0x10 : 0x20;
+-
+-	buf = kmalloc(0x2020, GFP_KERNEL);
+-	if (!buf) {
+-		printk(KERN_ERR "prism54usb: cannot allocate memory for "
+-		       "eeprom readback!\n");
+-		return -ENOMEM;
+-	}
+-
+-	if (priv->hw_type) {
+-		*((u32 *) buf) = priv->common.rx_start;
+-		err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
+-		if (err) {
+-			printk(KERN_ERR "prism54usb: addr send failed\n");
+-			goto fail;
+-		}
+-	} else {
+-		struct net2280_reg_write *reg = buf;
+-		reg->port = cpu_to_le16(NET2280_DEV_U32);
+-		reg->addr = cpu_to_le32(P54U_DEV_BASE);
+-		reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
+-		err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg));
+-		if (err) {
+-			printk(KERN_ERR "prism54usb: dev_int send failed\n");
+-			goto fail;
+-		}
+-	}
+-
+-	hdr = buf + priv->common.tx_hdr_len;
+-	p54_fill_eeprom_readback(hdr);
+-	hdr->req_id = cpu_to_le32(priv->common.rx_start);
+-	if (priv->common.tx_hdr_len) {
+-		struct net2280_tx_hdr *tx_hdr = buf;
+-		tx_hdr->device_addr = hdr->req_id;
+-		tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN);
+-	}
+-
+-	/* we can just pretend to send 0x2000 bytes of nothing in the headers */
+-	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf,
+-			    EEPROM_READBACK_LEN + priv->common.tx_hdr_len);
+-	if (err) {
+-		printk(KERN_ERR "prism54usb: eeprom req send failed\n");
+-		goto fail;
+-	}
+-
+-	err = usb_bulk_msg(priv->udev,
+-			   usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
+-			   buf, 0x2020, &alen, 1000);
+-	if (!err && alen > offset) {
+-		p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset);
+-	} else {
+-		printk(KERN_ERR "prism54usb: eeprom read failed!\n");
+-		err = -EINVAL;
+-		goto fail;
+-	}
+-
+- fail:
+-	kfree(buf);
+-	return err;
+-}
+-
+-static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
+-{
+-	static char start_string[] = "~~~~<\r";
+-	struct p54u_priv *priv = dev->priv;
+-	const struct firmware *fw_entry = NULL;
+-	int err, alen;
+-	u8 carry = 0;
+-	u8 *buf, *tmp, *data;
+-	unsigned int left, remains, block_size;
+-	struct x2_header *hdr;
+-	unsigned long timeout;
+-
+-	tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
+-	if (!buf) {
+-		printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n");
+-		err = -ENOMEM;
+-		goto err_bufalloc;
+-	}
+-
+-	memcpy(buf, start_string, 4);
+-	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
+-	if (err) {
+-		printk(KERN_ERR "p54usb: reset failed! (%d)\n", err);
+-		goto err_reset;
+-	}
+-
+-	err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
+-	if (err) {
+-		printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
+-		goto err_req_fw_failed;
+-	}
+-
+-	p54_parse_firmware(dev, fw_entry);
+-
+-	left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
+-	strcpy(buf, start_string);
+-	left -= strlen(start_string);
+-	tmp += strlen(start_string);
+-
+-	data = fw_entry->data;
+-	remains = fw_entry->size;
+-
+-	hdr = (struct x2_header *)(buf + strlen(start_string));
+-	memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
+-	hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
+-	hdr->fw_length = cpu_to_le32(fw_entry->size);
+-	hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
+-					 sizeof(u32)*2));
+-	left -= sizeof(*hdr);
+-	tmp += sizeof(*hdr);
+-
+-	while (remains) {
+-		while (left--) {
+-			if (carry) {
+-				*tmp++ = carry;
+-				carry = 0;
+-				remains--;
+-				continue;
+-			}
+-			switch (*data) {
+-			case '~':
+-				*tmp++ = '}';
+-				carry = '^';
+-				break;
+-			case '}':
+-				*tmp++ = '}';
+-				carry = ']';
+-				break;
+-			default:
+-				*tmp++ = *data;
+-				remains--;
+-				break;
+-			}
+-			data++;
+-		}
+-
+-		err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
+-		if (err) {
+-			printk(KERN_ERR "prism54usb: firmware upload failed!\n");
+-			goto err_upload_failed;
+-		}
+-
+-		tmp = buf;
+-		left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
+-	}
+-
+-	*((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
+-	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
+-	if (err) {
+-		printk(KERN_ERR "prism54usb: firmware upload failed!\n");
+-		goto err_upload_failed;
+-	}
+-
+-	timeout = jiffies + msecs_to_jiffies(1000);
+-	while (!(err = usb_bulk_msg(priv->udev,
+-		usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
+-		if (alen > 2 && !memcmp(buf, "OK", 2))
+-			break;
+-
+-		if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
+-			printk(KERN_INFO "prism54usb: firmware upload failed!\n");
+-			err = -EINVAL;
+-			break;
+-		}
+-
+-		if (time_after(jiffies, timeout)) {
+-			printk(KERN_ERR "prism54usb: firmware boot timed out!\n");
+-			err = -ETIMEDOUT;
+-			break;
+-		}
+-	}
+-	if (err)
+-		goto err_upload_failed;
+-
+-	buf[0] = 'g';
+-	buf[1] = '\r';
+-	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
+-	if (err) {
+-		printk(KERN_ERR "prism54usb: firmware boot failed!\n");
+-		goto err_upload_failed;
+-	}
+-
+-	timeout = jiffies + msecs_to_jiffies(1000);
+-	while (!(err = usb_bulk_msg(priv->udev,
+-		usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
+-		if (alen > 0 && buf[0] == 'g')
+-			break;
+-
+-		if (time_after(jiffies, timeout)) {
+-			err = -ETIMEDOUT;
+-			break;
+-		}
+-	}
+-	if (err)
+-		goto err_upload_failed;
+-
+-  err_upload_failed:
+-	release_firmware(fw_entry);
+-  err_req_fw_failed:
+-  err_reset:
+-	kfree(buf);
+-  err_bufalloc:
+-	return err;
+-}
+-
+-static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
+-{
+-	struct p54u_priv *priv = dev->priv;
+-	const struct firmware *fw_entry = NULL;
+-	const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
+-	int err, alen;
+-	void *buf;
+-	__le32 reg;
+-	unsigned int remains, offset;
+-	u8 *data;
+-
+-	buf = kmalloc(512, GFP_KERNEL);
+-	if (!buf) {
+-		printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n");
+-		return -ENOMEM;
+-	}
+-
+-	err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
+-	if (err) {
+-		printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
+-		kfree(buf);
+-		return err;
+-	}
+-
+-	p54_parse_firmware(dev, fw_entry);
+-
+-#define P54U_WRITE(type, addr, data) \
+-	do {\
+-		err = p54u_write(priv, buf, type,\
+-				 cpu_to_le32((u32)(unsigned long)addr), data);\
+-		if (err) \
+-			goto fail;\
+-	} while (0)
+-
+-#define P54U_READ(type, addr) \
+-	do {\
+-		err = p54u_read(priv, buf, type,\
+-				cpu_to_le32((u32)(unsigned long)addr), &reg);\
+-		if (err)\
+-			goto fail;\
+-	} while (0)
+-
+-	/* power down net2280 bridge */
+-	P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
+-	reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
+-	reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
+-
+-	mdelay(100);
+-
+-	/* power up bridge */
+-	reg |= cpu_to_le32(P54U_BRG_POWER_UP);
+-	reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
+-
+-	mdelay(100);
+-
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
+-		   cpu_to_le32(NET2280_CLK_30Mhz |
+-			       NET2280_PCI_ENABLE |
+-			       NET2280_PCI_SOFT_RESET));
+-
+-	mdelay(20);
+-
+-	P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
+-		   cpu_to_le32(PCI_COMMAND_MEMORY |
+-			       PCI_COMMAND_MASTER));
+-
+-	P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
+-		   cpu_to_le32(NET2280_BASE));
+-
+-	P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
+-	reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
+-	P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
+-
+-	// TODO: we really need this?
+-	P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
+-
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
+-		   cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
+-		   cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
+-
+-	P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
+-		   cpu_to_le32(NET2280_BASE2));
+-
+-	/* finally done setting up the bridge */
+-
+-	P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
+-		   cpu_to_le32(PCI_COMMAND_MEMORY |
+-			       PCI_COMMAND_MASTER));
+-
+-	P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
+-	P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
+-		   cpu_to_le32(P54U_DEV_BASE));
+-
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
+-		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
+-
+-	/* do romboot */
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
+-
+-	P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+-	mdelay(20);
+-
+-	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+-	mdelay(20);
+-
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+-	mdelay(100);
+-
+-	P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
+-
+-	/* finally, we can upload firmware now! */
+-	remains = fw_entry->size;
+-	data = fw_entry->data;
+-	offset = ISL38XX_DEV_FIRMWARE_ADDR;
+-
+-	while (remains) {
+-		unsigned int block_len = min(remains, (unsigned int)512);
+-		memcpy(buf, data, block_len);
+-
+-		err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
+-		if (err) {
+-			printk(KERN_ERR "prism54usb: firmware block upload "
+-			       "failed\n");
+-			goto fail;
+-		}
+-
+-		P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
+-			   cpu_to_le32(0xc0000f00));
+-
+-		P54U_WRITE(NET2280_DEV_U32,
+-			   0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
+-		P54U_WRITE(NET2280_DEV_U32,
+-			   0x0020 | (unsigned long)&devreg->direct_mem_win,
+-			   cpu_to_le32(1));
+-
+-		P54U_WRITE(NET2280_DEV_U32,
+-			   0x0024 | (unsigned long)&devreg->direct_mem_win,
+-			   cpu_to_le32(block_len));
+-		P54U_WRITE(NET2280_DEV_U32,
+-			   0x0028 | (unsigned long)&devreg->direct_mem_win,
+-			   cpu_to_le32(offset));
+-
+-		P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
+-			   cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
+-		P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
+-			   cpu_to_le32(block_len >> 2));
+-		P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
+-			   cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
+-
+-		mdelay(10);
+-
+-		P54U_READ(NET2280_DEV_U32,
+-			  0x002C | (unsigned long)&devreg->direct_mem_win);
+-		if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
+-		    !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
+-			printk(KERN_ERR "prism54usb: firmware DMA transfer "
+-			       "failed\n");
+-			goto fail;
+-		}
+-
+-		P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
+-			   cpu_to_le32(NET2280_FIFO_FLUSH));
+-
+-		remains -= block_len;
+-		data += block_len;
+-		offset += block_len;
+-	}
+-
+-	/* do ramboot */
+-	P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
+-	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+-	mdelay(20);
+-
+-	reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+-	reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+-	mdelay(100);
+-
+-	P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
+-
+-	/* start up the firmware */
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
+-		   cpu_to_le32(ISL38XX_INT_IDENT_INIT));
+-
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
+-		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
+-
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
+-		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
+-			       NET2280_USB_INTERRUPT_ENABLE));
+-
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
+-		   cpu_to_le32(ISL38XX_DEV_INT_RESET));
+-
+-	err = usb_interrupt_msg(priv->udev,
+-				usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
+-				buf, sizeof(__le32), &alen, 1000);
+-	if (err || alen != sizeof(__le32))
+-		goto fail;
+-
+-	P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
+-	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
+-
+-	if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
+-		err = -EINVAL;
+-
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
+-	P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
+-		   cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
+-
+-#undef P54U_WRITE
+-#undef P54U_READ
+-
+- fail:
+-	release_firmware(fw_entry);
+-	kfree(buf);
+-	return err;
+-}
+-
+-static int p54u_open(struct ieee80211_hw *dev)
+-{
+-	struct p54u_priv *priv = dev->priv;
+-	int err;
+-
+-	err = p54u_init_urbs(dev);
+-	if (err) {
+-		return err;
+-	}
+-
+-	priv->common.open = p54u_init_urbs;
+-
+-	return 0;
+-}
+-
+-static void p54u_stop(struct ieee80211_hw *dev)
+-{
+-	/* TODO: figure out how to reliably stop the 3887 and net2280 so
+-	   the hardware is still usable next time we want to start it.
+-	   until then, we just stop listening to the hardware.. */
+-	p54u_free_urbs(dev);
+-	return;
+-}
+-
+-static int __devinit p54u_probe(struct usb_interface *intf,
+-				const struct usb_device_id *id)
+-{
+-	struct usb_device *udev = interface_to_usbdev(intf);
+-	struct ieee80211_hw *dev;
+-	struct p54u_priv *priv;
+-	int err;
+-	unsigned int i, recognized_pipes;
+-	DECLARE_MAC_BUF(mac);
+-
+-	dev = p54_init_common(sizeof(*priv));
+-	if (!dev) {
+-		printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n");
+-		return -ENOMEM;
+-	}
+-
+-	priv = dev->priv;
+-
+-	SET_IEEE80211_DEV(dev, &intf->dev);
+-	usb_set_intfdata(intf, dev);
+-	priv->udev = udev;
+-
+-	usb_get_dev(udev);
+-
+-	/* really lazy and simple way of figuring out if we're a 3887 */
+-	/* TODO: should just stick the identification in the device table */
+-	i = intf->altsetting->desc.bNumEndpoints;
+-	recognized_pipes = 0;
+-	while (i--) {
+-		switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
+-		case P54U_PIPE_DATA:
+-		case P54U_PIPE_MGMT:
+-		case P54U_PIPE_BRG:
+-		case P54U_PIPE_DEV:
+-		case P54U_PIPE_DATA | USB_DIR_IN:
+-		case P54U_PIPE_MGMT | USB_DIR_IN:
+-		case P54U_PIPE_BRG | USB_DIR_IN:
+-		case P54U_PIPE_DEV | USB_DIR_IN:
+-		case P54U_PIPE_INT | USB_DIR_IN:
+-			recognized_pipes++;
+-		}
+-	}
+-	priv->common.open = p54u_open;
+-
+-	if (recognized_pipes < P54U_PIPE_NUMBER) {
+-		priv->hw_type = P54U_3887;
+-		priv->common.tx = p54u_tx_3887;
+-	} else {
+-		dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
+-		priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
+-		priv->common.tx = p54u_tx_net2280;
+-	}
+-	priv->common.stop = p54u_stop;
+-
+-	if (priv->hw_type)
+-		err = p54u_upload_firmware_3887(dev);
+-	else
+-		err = p54u_upload_firmware_net2280(dev);
+-	if (err)
+-		goto err_free_dev;
+-
+-	err = p54u_read_eeprom(dev);
+-	if (err)
+-		goto err_free_dev;
+-
+-	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+-		u8 perm_addr[ETH_ALEN];
+-
+-		printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n");
+-		random_ether_addr(perm_addr);
+-		SET_IEEE80211_PERM_ADDR(dev, perm_addr);
+-	}
+-
+-	skb_queue_head_init(&priv->rx_queue);
+-
+-	err = ieee80211_register_hw(dev);
+-	if (err) {
+-		printk(KERN_ERR "prism54usb: Cannot register netdevice\n");
+-		goto err_free_dev;
+-	}
+-
+-	printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
+-	       wiphy_name(dev->wiphy),
+-	       print_mac(mac, dev->wiphy->perm_addr),
+-	       priv->common.version);
+-
+-	return 0;
+-
+- err_free_dev:
+-	ieee80211_free_hw(dev);
+-	usb_set_intfdata(intf, NULL);
+-	usb_put_dev(udev);
+-	return err;
+-}
+-
+-static void __devexit p54u_disconnect(struct usb_interface *intf)
+-{
+-	struct ieee80211_hw *dev = usb_get_intfdata(intf);
+-	struct p54u_priv *priv;
+-
+-	if (!dev)
+-		return;
+-
+-	ieee80211_unregister_hw(dev);
+-
+-	priv = dev->priv;
+-	usb_put_dev(interface_to_usbdev(intf));
+-	p54_free_common(dev);
+-	ieee80211_free_hw(dev);
+-}
+-
+-static struct usb_driver p54u_driver = {
+-	.name	= "prism54usb",
+-	.id_table = p54u_table,
+-	.probe = p54u_probe,
+-	.disconnect = p54u_disconnect,
+-};
+-
+-static int __init p54u_init(void)
+-{
+-	return usb_register(&p54u_driver);
+-}
+-
+-static void __exit p54u_exit(void)
+-{
+-	usb_deregister(&p54u_driver);
+-}
+-
+-module_init(p54u_init);
+-module_exit(p54u_exit);
+diff --git a/drivers/net/wireless/p54usb.h b/drivers/net/wireless/p54usb.h
+deleted file mode 100644
+index d1896b3..0000000
+--- a/drivers/net/wireless/p54usb.h
++++ /dev/null
+@@ -1,133 +0,0 @@
+-#ifndef PRISM54USB_H
+-#define PRISM54USB_H
+-
+-/*
+- * Defines for USB based mac80211 Prism54 driver
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/* for isl3886 register definitions used on ver 1 devices */
+-#include "p54pci.h"
+-#include "net2280.h"
+-
+-/* pci */
+-#define NET2280_BASE		0x10000000
+-#define NET2280_BASE2		0x20000000
+-
+-/* gpio */
+-#define P54U_BRG_POWER_UP	(1 << GPIO0_DATA)
+-#define P54U_BRG_POWER_DOWN	(1 << GPIO1_DATA)
+-
+-/* devinit */
+-#define NET2280_CLK_4Mhz	(15 << LOCAL_CLOCK_FREQUENCY)
+-#define NET2280_CLK_30Mhz	(2 << LOCAL_CLOCK_FREQUENCY)
+-#define NET2280_CLK_60Mhz	(1 << LOCAL_CLOCK_FREQUENCY)
+-#define NET2280_CLK_STOP	(0 << LOCAL_CLOCK_FREQUENCY)
+-#define NET2280_PCI_ENABLE	(1 << PCI_ENABLE)
+-#define NET2280_PCI_SOFT_RESET	(1 << PCI_SOFT_RESET)
+-
+-/* endpoints */
+-#define NET2280_CLEAR_NAK_OUT_PACKETS_MODE	(1 << CLEAR_NAK_OUT_PACKETS_MODE)
+-#define NET2280_FIFO_FLUSH			(1 << FIFO_FLUSH)
+-
+-/* irq */
+-#define NET2280_USB_INTERRUPT_ENABLE		(1 << USB_INTERRUPT_ENABLE)
+-#define NET2280_PCI_INTA_INTERRUPT		(1 << PCI_INTA_INTERRUPT)
+-#define NET2280_PCI_INTA_INTERRUPT_ENABLE	(1 << PCI_INTA_INTERRUPT_ENABLE)
+-
+-/* registers */
+-#define NET2280_DEVINIT		0x00
+-#define NET2280_USBIRQENB1	0x24
+-#define NET2280_IRQSTAT1	0x2c
+-#define NET2280_FIFOCTL         0x38
+-#define NET2280_GPIOCTL		0x50
+-#define NET2280_RELNUM		0x88
+-#define NET2280_EPA_RSP		0x324
+-#define NET2280_EPA_STAT	0x32c
+-#define NET2280_EPB_STAT	0x34c
+-#define NET2280_EPC_RSP		0x364
+-#define NET2280_EPC_STAT	0x36c
+-#define NET2280_EPD_STAT	0x38c
+-
+-#define NET2280_EPA_CFG     0x320
+-#define NET2280_EPB_CFG     0x340
+-#define NET2280_EPC_CFG     0x360
+-#define NET2280_EPD_CFG     0x380
+-#define NET2280_EPE_CFG     0x3A0
+-#define NET2280_EPF_CFG     0x3C0
+-#define P54U_DEV_BASE 0x40000000
+-
+-struct net2280_tx_hdr {
+-	__le32 device_addr;
+-	__le16 len;
+-	__le16 follower;	/* ? */
+-	u8 padding[8];
+-} __attribute__((packed));
+-
+-/* Some flags for the isl hardware registers controlling DMA inside the
+- * chip */
+-#define ISL38XX_DMA_STATUS_DONE			0x00000001
+-#define ISL38XX_DMA_STATUS_READY		0x00000002
+-#define NET2280_EPA_FIFO_PCI_ADDR		0x20000000
+-#define ISL38XX_DMA_MASTER_CONTROL_TRIGGER	0x00000004
+-
+-enum net2280_op_type {
+-	NET2280_BRG_U32		= 0x001F,
+-	NET2280_BRG_CFG_U32	= 0x000F,
+-	NET2280_BRG_CFG_U16	= 0x0003,
+-	NET2280_DEV_U32		= 0x080F,
+-	NET2280_DEV_CFG_U32	= 0x088F,
+-	NET2280_DEV_CFG_U16	= 0x0883
+-};
+-
+-#define P54U_FW_BLOCK 2048
+-
+-#define X2_SIGNATURE "x2  "
+-#define X2_SIGNATURE_SIZE 4
+-
+-struct x2_header {
+-	u8 signature[X2_SIGNATURE_SIZE];
+-	__le32 fw_load_addr;
+-	__le32 fw_length;
+-	__le32 crc;
+-} __attribute__((packed));
+-
+-/* pipes 3 and 4 are not used by the driver */
+-#define P54U_PIPE_NUMBER 9
+-
+-enum p54u_pipe_addr {
+-        P54U_PIPE_DATA = 0x01,
+-        P54U_PIPE_MGMT = 0x02,
+-        P54U_PIPE_3 = 0x03,
+-        P54U_PIPE_4 = 0x04,
+-        P54U_PIPE_BRG = 0x0d,
+-        P54U_PIPE_DEV = 0x0e,
+-        P54U_PIPE_INT = 0x0f
+-};
+-
+-struct p54u_rx_info {
+-	struct urb *urb;
+-	struct ieee80211_hw *dev;
+-};
+-
+-struct p54u_priv {
+-	struct p54_common common;
+-	struct usb_device *udev;
+-	enum {
+-		P54U_NET2280 = 0,
+-		P54U_3887
+-	} hw_type;
+-
+-	spinlock_t lock;
+-	struct sk_buff_head rx_queue;
+-};
+-
+-#endif /* PRISM54USB_H */
+diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
+index 1b595a6..5b375b2 100644
+--- a/drivers/net/wireless/prism54/isl_ioctl.c
++++ b/drivers/net/wireless/prism54/isl_ioctl.c
+@@ -165,7 +165,7 @@ prism54_update_stats(struct work_struct *work)
+ 	struct obj_bss bss, *bss2;
+ 	union oid_res_t r;
+ 
+-	down(&priv->stats_sem);
++	mutex_lock(&priv->stats_lock);
+ 
+ /* Noise floor.
+  * I'm not sure if the unit is dBm.
+@@ -207,7 +207,7 @@ prism54_update_stats(struct work_struct *work)
+ 	mgt_get_request(priv, DOT11_OID_MPDUTXFAILED, 0, NULL, &r);
+ 	priv->local_iwstatistics.discard.retries = r.u;
+ 
+-	up(&priv->stats_sem);
++	mutex_unlock(&priv->stats_lock);
+ 
+ 	return;
+ }
+@@ -218,12 +218,12 @@ prism54_get_wireless_stats(struct net_device *ndev)
+ 	islpci_private *priv = netdev_priv(ndev);
+ 
+ 	/* If the stats are being updated return old data */
+-	if (down_trylock(&priv->stats_sem) == 0) {
++	if (mutex_trylock(&priv->stats_lock)) {
+ 		memcpy(&priv->iwstatistics, &priv->local_iwstatistics,
+ 		       sizeof (struct iw_statistics));
+ 		/* They won't be marked updated for the next time */
+ 		priv->local_iwstatistics.qual.updated = 0;
+-		up(&priv->stats_sem);
++		mutex_unlock(&priv->stats_lock);
+ 	} else
+ 		priv->iwstatistics.qual.updated = 0;
+ 
+@@ -1186,7 +1186,7 @@ prism54_get_encode(struct net_device *ndev, struct iw_request_info *info,
+ 	rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
+ 	devindex = r.u;
+ 	/* Now get the key, return it */
+-	if ((index < 0) || (index > 3))
++	if (index == -1 || index > 3)
+ 		/* no index provided, use the current one */
+ 		index = devindex;
+ 	rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r);
+@@ -1780,7 +1780,7 @@ prism54_set_raw(struct net_device *ndev, struct iw_request_info *info,
+ void
+ prism54_acl_init(struct islpci_acl *acl)
+ {
+-	sema_init(&acl->sem, 1);
++	mutex_init(&acl->lock);
+ 	INIT_LIST_HEAD(&acl->mac_list);
+ 	acl->size = 0;
+ 	acl->policy = MAC_POLICY_OPEN;
+@@ -1792,10 +1792,10 @@ prism54_clear_mac(struct islpci_acl *acl)
+ 	struct list_head *ptr, *next;
+ 	struct mac_entry *entry;
+ 
+-	down(&acl->sem);
++	mutex_lock(&acl->lock);
+ 
+ 	if (acl->size == 0) {
+-		up(&acl->sem);
++		mutex_unlock(&acl->lock);
+ 		return;
+ 	}
+ 
+@@ -1806,7 +1806,7 @@ prism54_clear_mac(struct islpci_acl *acl)
+ 		kfree(entry);
+ 	}
+ 	acl->size = 0;
+-	up(&acl->sem);
++	mutex_unlock(&acl->lock);
+ }
+ 
+ void
+@@ -1833,13 +1833,13 @@ prism54_add_mac(struct net_device *ndev, struct iw_request_info *info,
+ 
+ 	memcpy(entry->addr, addr->sa_data, ETH_ALEN);
+ 
+-	if (down_interruptible(&acl->sem)) {
++	if (mutex_lock_interruptible(&acl->lock)) {
+ 		kfree(entry);
+ 		return -ERESTARTSYS;
+ 	}
+ 	list_add_tail(&entry->_list, &acl->mac_list);
+ 	acl->size++;
+-	up(&acl->sem);
++	mutex_unlock(&acl->lock);
+ 
+ 	return 0;
+ }
+@@ -1856,18 +1856,18 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
+ 	if (addr->sa_family != ARPHRD_ETHER)
+ 		return -EOPNOTSUPP;
+ 
+-	if (down_interruptible(&acl->sem))
++	if (mutex_lock_interruptible(&acl->lock))
+ 		return -ERESTARTSYS;
+ 	list_for_each_entry(entry, &acl->mac_list, _list) {
+ 		if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
+ 			list_del(&entry->_list);
+ 			acl->size--;
+ 			kfree(entry);
+-			up(&acl->sem);
++			mutex_unlock(&acl->lock);
+ 			return 0;
+ 		}
+ 	}
+-	up(&acl->sem);
++	mutex_unlock(&acl->lock);
+ 	return -EINVAL;
+ }
+ 
+@@ -1882,7 +1882,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
+ 
+ 	dwrq->length = 0;
+ 
+-	if (down_interruptible(&acl->sem))
++	if (mutex_lock_interruptible(&acl->lock))
+ 		return -ERESTARTSYS;
+ 
+ 	list_for_each_entry(entry, &acl->mac_list, _list) {
+@@ -1891,7 +1891,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
+ 		dwrq->length++;
+ 		dst++;
+ 	}
+-	up(&acl->sem);
++	mutex_unlock(&acl->lock);
+ 	return 0;
+ }
+ 
+@@ -1955,11 +1955,11 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac)
+ 	struct mac_entry *entry;
+ 	int res = 0;
+ 
+-	if (down_interruptible(&acl->sem))
++	if (mutex_lock_interruptible(&acl->lock))
+ 		return -ERESTARTSYS;
+ 
+ 	if (acl->policy == MAC_POLICY_OPEN) {
+-		up(&acl->sem);
++		mutex_unlock(&acl->lock);
+ 		return 1;
+ 	}
+ 
+@@ -1970,7 +1970,7 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac)
+ 		}
+ 	}
+ 	res = (acl->policy == MAC_POLICY_ACCEPT) ? !res : res;
+-	up(&acl->sem);
++	mutex_unlock(&acl->lock);
+ 
+ 	return res;
+ }
+@@ -2081,6 +2081,7 @@ link_changed(struct net_device *ndev, u32 bitrate)
+ 	islpci_private *priv = netdev_priv(ndev);
+ 
+ 	if (bitrate) {
++		netif_carrier_on(ndev);
+ 		if (priv->iw_mode == IW_MODE_INFRA) {
+ 			union iwreq_data uwrq;
+ 			prism54_get_wap(ndev, NULL, (struct sockaddr *) &uwrq,
+@@ -2089,8 +2090,10 @@ link_changed(struct net_device *ndev, u32 bitrate)
+ 		} else
+ 			send_simple_event(netdev_priv(ndev),
+ 					  "Link established");
+-	} else
++	} else {
++		netif_carrier_off(ndev);
+ 		send_simple_event(netdev_priv(ndev), "Link lost");
++	}
+ }
+ 
+ /* Beacon/ProbeResp payload header */
+@@ -2114,7 +2117,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
+ 	if (wpa_ie_len > MAX_WPA_IE_LEN)
+ 		wpa_ie_len = MAX_WPA_IE_LEN;
+ 
+-	down(&priv->wpa_sem);
++	mutex_lock(&priv->wpa_lock);
+ 
+ 	/* try to use existing entry */
+ 	list_for_each(ptr, &priv->bss_wpa_list) {
+@@ -2165,7 +2168,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
+ 		kfree(bss);
+ 	}
+ 
+-	up(&priv->wpa_sem);
++	mutex_unlock(&priv->wpa_lock);
+ }
+ 
+ static size_t
+@@ -2175,7 +2178,7 @@ prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
+ 	struct islpci_bss_wpa_ie *bss = NULL;
+ 	size_t len = 0;
+ 
+-	down(&priv->wpa_sem);
++	mutex_lock(&priv->wpa_lock);
+ 
+ 	list_for_each(ptr, &priv->bss_wpa_list) {
+ 		bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
+@@ -2187,7 +2190,7 @@ prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
+ 		len = bss->wpa_ie_len;
+ 		memcpy(wpa_ie, bss->wpa_ie, len);
+ 	}
+-	up(&priv->wpa_sem);
++	mutex_unlock(&priv->wpa_lock);
+ 
+ 	return len;
+ }
+@@ -2196,7 +2199,7 @@ void
+ prism54_wpa_bss_ie_init(islpci_private *priv)
+ {
+ 	INIT_LIST_HEAD(&priv->bss_wpa_list);
+-	sema_init(&priv->wpa_sem, 1);
++	mutex_init(&priv->wpa_lock);
+ }
+ 
+ void
+diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
+index dbb538c..04c2638 100644
+--- a/drivers/net/wireless/prism54/islpci_dev.c
++++ b/drivers/net/wireless/prism54/islpci_dev.c
+@@ -387,7 +387,9 @@ islpci_open(struct net_device *ndev)
+ 	}
+ 
+ 	netif_start_queue(ndev);
+-/*      netif_mark_up( ndev ); */
++
++	/* Turn off carrier unless we know we have associated */
++	netif_carrier_off(ndev);
+ 
+ 	return 0;
+ }
+@@ -864,7 +866,7 @@ islpci_setup(struct pci_dev *pdev)
+ 	mutex_init(&priv->mgmt_lock);
+ 	priv->mgmt_received = NULL;
+ 	init_waitqueue_head(&priv->mgmt_wqueue);
+-	sema_init(&priv->stats_sem, 1);
++	mutex_init(&priv->stats_lock);
+ 	spin_lock_init(&priv->slock);
+ 
+ 	/* init state machine with off#1 state */
+diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
+index 4e0182c..8e55a5f 100644
+--- a/drivers/net/wireless/prism54/islpci_dev.h
++++ b/drivers/net/wireless/prism54/islpci_dev.h
+@@ -55,7 +55,7 @@ struct islpci_acl {
+    enum { MAC_POLICY_OPEN=0, MAC_POLICY_ACCEPT=1, MAC_POLICY_REJECT=2 } policy;
+    struct list_head mac_list;  /* a list of mac_entry */
+    int size;   /* size of queue */
+-   struct semaphore sem;   /* accessed in ioctls and trap_work */
++   struct mutex lock;   /* accessed in ioctls and trap_work */
+ };
+ 
+ struct islpci_membuf {
+@@ -88,7 +88,7 @@ typedef struct {
+ 
+ 	/* Take care of the wireless stats */
+ 	struct work_struct stats_work;
+-	struct semaphore stats_sem;
++	struct mutex stats_lock;
+ 	/* remember when we last updated the stats */
+ 	unsigned long stats_timestamp;
+ 	/* The first is accessed under semaphore locking.
+@@ -178,7 +178,7 @@ typedef struct {
+ 	int wpa; /* WPA mode enabled */
+ 	struct list_head bss_wpa_list;
+ 	int num_bss_wpa;
+-	struct semaphore wpa_sem;
++	struct mutex wpa_lock;
+ 	u8 wpa_ie[MAX_WPA_IE_LEN];
+ 	size_t wpa_ie_len;
+ 
+diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
+index f3858ee..963960d 100644
+--- a/drivers/net/wireless/ray_cs.c
++++ b/drivers/net/wireless/ray_cs.c
+@@ -34,6 +34,7 @@
+ #include <linux/kernel.h>
+ #include <linux/proc_fs.h>
+ #include <linux/ptrace.h>
++#include <linux/seq_file.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/timer.h>
+@@ -2582,7 +2583,7 @@ static char *nettype[] = {"Adhoc", "Infra "};
+ static char *framing[] = {"Encapsulation", "Translation"}
+ ;
+ /*===========================================================================*/
+-static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
++static int ray_cs_proc_show(struct seq_file *m, void *v)
+ {
+ /* Print current values which are not available via other means
+  * eg ifconfig 
+@@ -2606,83 +2607,93 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
+     if (!local)
+     	return 0;
+ 
+-    len = 0;
+-
+-    len += sprintf(buf + len, "Raylink Wireless LAN driver status\n");
+-    len += sprintf(buf + len, "%s\n", rcsid);
++    seq_puts(m, "Raylink Wireless LAN driver status\n");
++    seq_printf(m, "%s\n", rcsid);
+     /* build 4 does not report version, and field is 0x55 after memtest */
+-    len += sprintf(buf + len, "Firmware version     = ");
++    seq_puts(m, "Firmware version     = ");
+     if (local->fw_ver == 0x55)
+-        len += sprintf(buf + len, "4 - Use dump_cis for more details\n");
++        seq_puts(m, "4 - Use dump_cis for more details\n");
+     else
+-        len += sprintf(buf + len, "%2d.%02d.%02d\n",
++        seq_printf(m, "%2d.%02d.%02d\n",
+                    local->fw_ver, local->fw_bld, local->fw_var);
+ 
+     for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i];
+     c[32] = 0;
+-    len += sprintf(buf + len, "%s network ESSID = \"%s\"\n", 
++    seq_printf(m, "%s network ESSID = \"%s\"\n",
+                    nettype[local->sparm.b5.a_network_type], c);
+ 
+     p = local->bss_id;
+-    len += sprintf(buf + len, "BSSID                = %s\n",
++    seq_printf(m, "BSSID                = %s\n",
+                    print_mac(mac, p));
+ 
+-    len += sprintf(buf + len, "Country code         = %d\n", 
++    seq_printf(m, "Country code         = %d\n",
+                    local->sparm.b5.a_curr_country_code);
+ 
+     i = local->card_status;
+     if (i < 0) i = 10;
+     if (i > 16) i = 10;
+-    len += sprintf(buf + len, "Card status          = %s\n", card_status[i]);
++    seq_printf(m, "Card status          = %s\n", card_status[i]);
+ 
+-    len += sprintf(buf + len, "Framing mode         = %s\n",framing[translate]);
++    seq_printf(m, "Framing mode         = %s\n",framing[translate]);
+ 
+-    len += sprintf(buf + len, "Last pkt signal lvl  = %d\n", local->last_rsl);
++    seq_printf(m, "Last pkt signal lvl  = %d\n", local->last_rsl);
+ 
+     if (local->beacon_rxed) {
+ 	/* Pull some fields out of last beacon received */
+-	len += sprintf(buf + len, "Beacon Interval      = %d Kus\n", 
++	seq_printf(m, "Beacon Interval      = %d Kus\n",
+ 		       local->last_bcn.beacon_intvl[0]
+ 		       + 256 * local->last_bcn.beacon_intvl[1]);
+     
+     p = local->last_bcn.elements;
+     if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2;
+     else {
+-        len += sprintf(buf + len, "Parse beacon failed at essid element id = %d\n",p[0]);
+-        return len;
++        seq_printf(m, "Parse beacon failed at essid element id = %d\n",p[0]);
++        return 0;
+     }
+ 
+     if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) {
+-        len += sprintf(buf + len, "Supported rate codes = ");
++        seq_puts(m, "Supported rate codes = ");
+         for (i=2; i<p[1] + 2; i++) 
+-            len += sprintf(buf + len, "0x%02x ", p[i]);
+-        len += sprintf(buf + len, "\n");
++            seq_printf(m, "0x%02x ", p[i]);
++        seq_putc(m, '\n');
+         p += p[1] + 2;
+     }
+     else {
+-        len += sprintf(buf + len, "Parse beacon failed at rates element\n");
+-        return len;
++        seq_puts(m, "Parse beacon failed at rates element\n");
++        return 0;
+     }
+ 
+ 	if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) {
+ 	    pfh = (struct freq_hop_element *)p;
+-	    len += sprintf(buf + len, "Hop dwell            = %d Kus\n",
++	    seq_printf(m, "Hop dwell            = %d Kus\n",
+ 			   pfh->dwell_time[0] + 256 * pfh->dwell_time[1]);
+-	    len += sprintf(buf + len, "Hop set              = %d \n", pfh->hop_set);
+-	    len += sprintf(buf + len, "Hop pattern          = %d \n", pfh->hop_pattern);
+-	    len += sprintf(buf + len, "Hop index            = %d \n", pfh->hop_index);
++	    seq_printf(m, "Hop set              = %d \n", pfh->hop_set);
++	    seq_printf(m, "Hop pattern          = %d \n", pfh->hop_pattern);
++	    seq_printf(m, "Hop index            = %d \n", pfh->hop_index);
+ 	    p += p[1] + 2;
+ 	}
+ 	else {
+-	    len += sprintf(buf + len, "Parse beacon failed at FH param element\n");
+-	    return len;
++	    seq_puts(m, "Parse beacon failed at FH param element\n");
++	    return 0;
+ 	}
+     } else {
+-	len += sprintf(buf + len, "No beacons received\n");
++	seq_puts(m, "No beacons received\n");
+     }
+-    return len;
++    return 0;
+ }
+ 
++static int ray_cs_proc_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, ray_cs_proc_show, NULL);
++}
++
++static const struct file_operations ray_cs_proc_fops = {
++	.owner		= THIS_MODULE,
++	.open		= ray_cs_proc_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
+ #endif
+ /*===========================================================================*/
+ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
+@@ -2815,7 +2826,7 @@ static int __init init_ray_cs(void)
+ #ifdef CONFIG_PROC_FS
+     proc_mkdir("driver/ray_cs", NULL);
+ 
+-    create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_read);
++    proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops);
+     raycs_write("driver/ray_cs/essid", write_essid, NULL);
+     raycs_write("driver/ray_cs/net_type", write_int, &net_type);
+     raycs_write("driver/ray_cs/translate", write_int, &translate);
+diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
+index 10b776c..d0b1fb1 100644
+--- a/drivers/net/wireless/rndis_wlan.c
++++ b/drivers/net/wireless/rndis_wlan.c
+@@ -154,128 +154,121 @@ MODULE_PARM_DESC(workaround_interval,
+ #define NDIS_802_11_LENGTH_RATES 8
+ #define NDIS_802_11_LENGTH_RATES_EX 16
+ 
+-struct NDIS_802_11_SSID {
+-	__le32 SsidLength;
+-	u8 Ssid[NDIS_802_11_LENGTH_SSID];
+-} __attribute__((packed));
+-
+-enum NDIS_802_11_NETWORK_TYPE {
+-	Ndis802_11FH,
+-	Ndis802_11DS,
+-	Ndis802_11OFDM5,
+-	Ndis802_11OFDM24,
+-	Ndis802_11NetworkTypeMax
++enum ndis_80211_net_type {
++	ndis_80211_type_freq_hop,
++	ndis_80211_type_direct_seq,
++	ndis_80211_type_ofdm_a,
++	ndis_80211_type_ofdm_g
+ };
+ 
+-struct NDIS_802_11_CONFIGURATION_FH {
+-	__le32 Length;
+-	__le32 HopPattern;
+-	__le32 HopSet;
+-	__le32 DwellTime;
+-} __attribute__((packed));
+-
+-struct NDIS_802_11_CONFIGURATION {
+-	__le32 Length;
+-	__le32 BeaconPeriod;
+-	__le32 ATIMWindow;
+-	__le32 DSConfig;
+-	struct NDIS_802_11_CONFIGURATION_FH FHConfig;
+-} __attribute__((packed));
+-
+-enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
+-	Ndis802_11IBSS,
+-	Ndis802_11Infrastructure,
+-	Ndis802_11AutoUnknown,
+-	Ndis802_11InfrastructureMax
++enum ndis_80211_net_infra {
++	ndis_80211_infra_adhoc,
++	ndis_80211_infra_infra,
++	ndis_80211_infra_auto_unknown
+ };
+ 
+-enum NDIS_802_11_AUTHENTICATION_MODE {
+-	Ndis802_11AuthModeOpen,
+-	Ndis802_11AuthModeShared,
+-	Ndis802_11AuthModeAutoSwitch,
+-	Ndis802_11AuthModeWPA,
+-	Ndis802_11AuthModeWPAPSK,
+-	Ndis802_11AuthModeWPANone,
+-	Ndis802_11AuthModeWPA2,
+-	Ndis802_11AuthModeWPA2PSK,
+-	Ndis802_11AuthModeMax
++enum ndis_80211_auth_mode {
++	ndis_80211_auth_open,
++	ndis_80211_auth_shared,
++	ndis_80211_auth_auto_switch,
++	ndis_80211_auth_wpa,
++	ndis_80211_auth_wpa_psk,
++	ndis_80211_auth_wpa_none,
++	ndis_80211_auth_wpa2,
++	ndis_80211_auth_wpa2_psk
+ };
+ 
+-enum NDIS_802_11_ENCRYPTION_STATUS {
+-	Ndis802_11WEPEnabled,
+-	Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
+-	Ndis802_11WEPDisabled,
+-	Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
+-	Ndis802_11WEPKeyAbsent,
+-	Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
+-	Ndis802_11WEPNotSupported,
+-	Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
+-	Ndis802_11Encryption2Enabled,
+-	Ndis802_11Encryption2KeyAbsent,
+-	Ndis802_11Encryption3Enabled,
+-	Ndis802_11Encryption3KeyAbsent
++enum ndis_80211_encr_status {
++	ndis_80211_encr_wep_enabled,
++	ndis_80211_encr_disabled,
++	ndis_80211_encr_wep_key_absent,
++	ndis_80211_encr_not_supported,
++	ndis_80211_encr_tkip_enabled,
++	ndis_80211_encr_tkip_key_absent,
++	ndis_80211_encr_ccmp_enabled,
++	ndis_80211_encr_ccmp_key_absent
+ };
+ 
+-enum NDIS_802_11_PRIVACY_FILTER {
+-	Ndis802_11PrivFilterAcceptAll,
+-	Ndis802_11PrivFilter8021xWEP
++enum ndis_80211_priv_filter {
++	ndis_80211_priv_accept_all,
++	ndis_80211_priv_8021x_wep
+ };
+ 
+-struct NDIS_WLAN_BSSID_EX {
+-	__le32 Length;
+-	u8 MacAddress[6];
+-	u8 Padding[2];
+-	struct NDIS_802_11_SSID Ssid;
+-	__le32 Privacy;
+-	__le32 Rssi;
+-	__le32 NetworkTypeInUse;
+-	struct NDIS_802_11_CONFIGURATION Configuration;
+-	__le32 InfrastructureMode;
+-	u8 SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
+-	__le32 IELength;
+-	u8 IEs[0];
++struct ndis_80211_ssid {
++	__le32 length;
++	u8 essid[NDIS_802_11_LENGTH_SSID];
+ } __attribute__((packed));
+ 
+-struct NDIS_802_11_BSSID_LIST_EX {
+-	__le32 NumberOfItems;
+-	struct NDIS_WLAN_BSSID_EX Bssid[0];
++struct ndis_80211_conf_freq_hop {
++	__le32 length;
++	__le32 hop_pattern;
++	__le32 hop_set;
++	__le32 dwell_time;
+ } __attribute__((packed));
+ 
+-struct NDIS_802_11_FIXED_IEs {
+-	u8 Timestamp[8];
+-	__le16 BeaconInterval;
+-	__le16 Capabilities;
++struct ndis_80211_conf {
++	__le32 length;
++	__le32 beacon_period;
++	__le32 atim_window;
++	__le32 ds_config;
++	struct ndis_80211_conf_freq_hop fh_config;
+ } __attribute__((packed));
+ 
+-struct NDIS_802_11_WEP {
+-	__le32 Length;
+-	__le32 KeyIndex;
+-	__le32 KeyLength;
+-	u8 KeyMaterial[32];
++struct ndis_80211_bssid_ex {
++	__le32 length;
++	u8 mac[6];
++	u8 padding[2];
++	struct ndis_80211_ssid ssid;
++	__le32 privacy;
++	__le32 rssi;
++	__le32 net_type;
++	struct ndis_80211_conf config;
++	__le32 net_infra;
++	u8 rates[NDIS_802_11_LENGTH_RATES_EX];
++	__le32 ie_length;
++	u8 ies[0];
+ } __attribute__((packed));
+ 
+-struct NDIS_802_11_KEY {
+-	__le32 Length;
+-	__le32 KeyIndex;
+-	__le32 KeyLength;
+-	u8 Bssid[6];
+-	u8 Padding[6];
+-	u8 KeyRSC[8];
+-	u8 KeyMaterial[32];
++struct ndis_80211_bssid_list_ex {
++	__le32 num_items;
++	struct ndis_80211_bssid_ex bssid[0];
+ } __attribute__((packed));
+ 
+-struct NDIS_802_11_REMOVE_KEY {
+-	__le32 Length;
+-	__le32 KeyIndex;
+-	u8 Bssid[6];
++struct ndis_80211_fixed_ies {
++	u8 timestamp[8];
++	__le16 beacon_interval;
++	__le16 capabilities;
+ } __attribute__((packed));
+ 
+-struct RNDIS_CONFIG_PARAMETER_INFOBUFFER {
+-	__le32 ParameterNameOffset;
+-	__le32 ParameterNameLength;
+-	__le32 ParameterType;
+-	__le32 ParameterValueOffset;
+-	__le32 ParameterValueLength;
++struct ndis_80211_wep_key {
++	__le32 size;
++	__le32 index;
++	__le32 length;
++	u8 material[32];
++} __attribute__((packed));
++
++struct ndis_80211_key {
++	__le32 size;
++	__le32 index;
++	__le32 length;
++	u8 bssid[6];
++	u8 padding[6];
++	u8 rsc[8];
++	u8 material[32];
++} __attribute__((packed));
++
++struct ndis_80211_remove_key {
++	__le32 size;
++	__le32 index;
++	u8 bssid[6];
++} __attribute__((packed));
++
++struct ndis_config_param {
++	__le32 name_offs;
++	__le32 name_length;
++	__le32 type;
++	__le32 value_offs;
++	__le32 value_length;
+ } __attribute__((packed));
+ 
+ /* these have to match what is in wpa_supplicant */
+@@ -334,7 +327,7 @@ struct rndis_wext_private {
+ 	/* hardware state */
+ 	int radio_on;
+ 	int infra_mode;
+-	struct NDIS_802_11_SSID essid;
++	struct ndis_80211_ssid essid;
+ 
+ 	/* encryption stuff */
+ 	int  encr_tx_key_index;
+@@ -484,7 +477,7 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
+ static int rndis_set_config_parameter(struct usbnet *dev, char *param,
+ 						int value_type, void *value)
+ {
+-	struct RNDIS_CONFIG_PARAMETER_INFOBUFFER *infobuf;
++	struct ndis_config_param *infobuf;
+ 	int value_len, info_len, param_len, ret, i;
+ 	__le16 *unibuf;
+ 	__le32 *dst_value;
+@@ -519,12 +512,11 @@ static int rndis_set_config_parameter(struct usbnet *dev, char *param,
+ 		devdbg(dev, "setting config parameter: %s, value: %d",
+ 						param, *(u32 *)value);
+ 
+-	infobuf->ParameterNameOffset = cpu_to_le32(sizeof(*infobuf));
+-	infobuf->ParameterNameLength = cpu_to_le32(param_len);
+-	infobuf->ParameterType = cpu_to_le32(value_type);
+-	infobuf->ParameterValueOffset = cpu_to_le32(sizeof(*infobuf) +
+-								param_len);
+-	infobuf->ParameterValueLength = cpu_to_le32(value_len);
++	infobuf->name_offs = cpu_to_le32(sizeof(*infobuf));
++	infobuf->name_length = cpu_to_le32(param_len);
++	infobuf->type = cpu_to_le32(value_type);
++	infobuf->value_offs = cpu_to_le32(sizeof(*infobuf) + param_len);
++	infobuf->value_length = cpu_to_le32(value_len);
+ 
+ 	/* simple string to unicode string conversion */
+ 	unibuf = (void *)infobuf + sizeof(*infobuf);
+@@ -630,7 +622,7 @@ static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
+ static int
+ add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index);
+ 
+-static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
++static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
+ {
+ 	int ret, len;
+ 
+@@ -638,14 +630,14 @@ static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
+ 	ret = rndis_query_oid(usbdev, OID_802_11_SSID, ssid, &len);
+ 
+ 	if (ret != 0)
+-		ssid->SsidLength = 0;
++		ssid->length = 0;
+ 
+ #ifdef DEBUG
+ 	{
+ 		unsigned char tmp[NDIS_802_11_LENGTH_SSID + 1];
+ 
+-		memcpy(tmp, ssid->Ssid, le32_to_cpu(ssid->SsidLength));
+-		tmp[le32_to_cpu(ssid->SsidLength)] = 0;
++		memcpy(tmp, ssid->essid, le32_to_cpu(ssid->length));
++		tmp[le32_to_cpu(ssid->length)] = 0;
+ 		devdbg(usbdev, "get_essid: '%s', ret: %d", tmp, ret);
+ 	}
+ #endif
+@@ -653,7 +645,7 @@ static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
+ }
+ 
+ 
+-static int set_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
++static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
+ {
+ 	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+ 	int ret;
+@@ -697,7 +689,7 @@ static int is_associated(struct usbnet *usbdev)
+ static int disassociate(struct usbnet *usbdev, int reset_ssid)
+ {
+ 	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+-	struct NDIS_802_11_SSID ssid;
++	struct ndis_80211_ssid ssid;
+ 	int i, ret = 0;
+ 
+ 	if (priv->radio_on) {
+@@ -714,12 +706,12 @@ static int disassociate(struct usbnet *usbdev, int reset_ssid)
+ 	/* disassociate causes radio to be turned off; if reset_ssid
+ 	 * is given, set random ssid to enable radio */
+ 	if (reset_ssid) {
+-		ssid.SsidLength = cpu_to_le32(sizeof(ssid.Ssid));
+-		get_random_bytes(&ssid.Ssid[2], sizeof(ssid.Ssid)-2);
+-		ssid.Ssid[0] = 0x1;
+-		ssid.Ssid[1] = 0xff;
+-		for (i = 2; i < sizeof(ssid.Ssid); i++)
+-			ssid.Ssid[i] = 0x1 + (ssid.Ssid[i] * 0xfe / 0xff);
++		ssid.length = cpu_to_le32(sizeof(ssid.essid));
++		get_random_bytes(&ssid.essid[2], sizeof(ssid.essid)-2);
++		ssid.essid[0] = 0x1;
++		ssid.essid[1] = 0xff;
++		for (i = 2; i < sizeof(ssid.essid); i++)
++			ssid.essid[i] = 0x1 + (ssid.essid[i] * 0xfe / 0xff);
+ 		ret = set_essid(usbdev, &ssid);
+ 	}
+ 	return ret;
+@@ -737,23 +729,23 @@ static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
+ 
+ 	if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
+ 		if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
+-			auth_mode = Ndis802_11AuthModeWPA2;
++			auth_mode = ndis_80211_auth_wpa2;
+ 		else
+-			auth_mode = Ndis802_11AuthModeWPA2PSK;
++			auth_mode = ndis_80211_auth_wpa2_psk;
+ 	} else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
+ 		if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
+-			auth_mode = Ndis802_11AuthModeWPA;
++			auth_mode = ndis_80211_auth_wpa;
+ 		else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK)
+-			auth_mode = Ndis802_11AuthModeWPAPSK;
++			auth_mode = ndis_80211_auth_wpa_psk;
+ 		else
+-			auth_mode = Ndis802_11AuthModeWPANone;
++			auth_mode = ndis_80211_auth_wpa_none;
+ 	} else if (authalg & IW_AUTH_ALG_SHARED_KEY) {
+ 		if (authalg & IW_AUTH_ALG_OPEN_SYSTEM)
+-			auth_mode = Ndis802_11AuthModeAutoSwitch;
++			auth_mode = ndis_80211_auth_auto_switch;
+ 		else
+-			auth_mode = Ndis802_11AuthModeShared;
++			auth_mode = ndis_80211_auth_shared;
+ 	} else
+-		auth_mode = Ndis802_11AuthModeOpen;
++		auth_mode = ndis_80211_auth_open;
+ 
+ 	tmp = cpu_to_le32(auth_mode);
+ 	ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp,
+@@ -778,9 +770,9 @@ static int set_priv_filter(struct usbnet *usbdev)
+ 
+ 	if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
+ 	    priv->wpa_version & IW_AUTH_WPA_VERSION_WPA)
+-		tmp = cpu_to_le32(Ndis802_11PrivFilter8021xWEP);
++		tmp = cpu_to_le32(ndis_80211_priv_8021x_wep);
+ 	else
+-		tmp = cpu_to_le32(Ndis802_11PrivFilterAcceptAll);
++		tmp = cpu_to_le32(ndis_80211_priv_accept_all);
+ 
+ 	return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp,
+ 								sizeof(tmp));
+@@ -798,18 +790,18 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
+ 		groupwise);
+ 
+ 	if (pairwise & IW_AUTH_CIPHER_CCMP)
+-		encr_mode = Ndis802_11Encryption3Enabled;
++		encr_mode = ndis_80211_encr_ccmp_enabled;
+ 	else if (pairwise & IW_AUTH_CIPHER_TKIP)
+-		encr_mode = Ndis802_11Encryption2Enabled;
++		encr_mode = ndis_80211_encr_tkip_enabled;
+ 	else if (pairwise &
+ 		 (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
+-		encr_mode = Ndis802_11Encryption1Enabled;
++		encr_mode = ndis_80211_encr_wep_enabled;
+ 	else if (groupwise & IW_AUTH_CIPHER_CCMP)
+-		encr_mode = Ndis802_11Encryption3Enabled;
++		encr_mode = ndis_80211_encr_ccmp_enabled;
+ 	else if (groupwise & IW_AUTH_CIPHER_TKIP)
+-		encr_mode = Ndis802_11Encryption2Enabled;
++		encr_mode = ndis_80211_encr_tkip_enabled;
+ 	else
+-		encr_mode = Ndis802_11EncryptionDisabled;
++		encr_mode = ndis_80211_encr_disabled;
+ 
+ 	tmp = cpu_to_le32(encr_mode);
+ 	ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp,
+@@ -877,7 +869,7 @@ static void set_default_iw_params(struct usbnet *usbdev)
+ 	priv->wpa_keymgmt = 0;
+ 	priv->wpa_version = 0;
+ 
+-	set_infra_mode(usbdev, Ndis802_11Infrastructure);
++	set_infra_mode(usbdev, ndis_80211_infra_infra);
+ 	set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
+ 				IW_AUTH_ALG_OPEN_SYSTEM);
+ 	set_priv_filter(usbdev);
+@@ -899,7 +891,7 @@ static int deauthenticate(struct usbnet *usbdev)
+ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
+ {
+ 	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+-	struct NDIS_802_11_WEP ndis_key;
++	struct ndis_80211_wep_key ndis_key;
+ 	int ret;
+ 
+ 	if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4)
+@@ -907,13 +899,13 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
+ 
+ 	memset(&ndis_key, 0, sizeof(ndis_key));
+ 
+-	ndis_key.Length = cpu_to_le32(sizeof(ndis_key));
+-	ndis_key.KeyLength = cpu_to_le32(key_len);
+-	ndis_key.KeyIndex = cpu_to_le32(index);
+-	memcpy(&ndis_key.KeyMaterial, key, key_len);
++	ndis_key.size = cpu_to_le32(sizeof(ndis_key));
++	ndis_key.length = cpu_to_le32(key_len);
++	ndis_key.index = cpu_to_le32(index);
++	memcpy(&ndis_key.material, key, key_len);
+ 
+ 	if (index == priv->encr_tx_key_index) {
+-		ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
++		ndis_key.index |= cpu_to_le32(1 << 31);
+ 		ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
+ 						IW_AUTH_CIPHER_NONE);
+ 		if (ret)
+@@ -940,7 +932,7 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
+ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
+ {
+ 	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+-	struct NDIS_802_11_REMOVE_KEY remove_key;
++	struct ndis_80211_remove_key remove_key;
+ 	__le32 keyindex;
+ 	int ret;
+ 
+@@ -954,17 +946,17 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
+ 	    priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP ||
+ 	    priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP ||
+ 	    priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) {
+-		remove_key.Length = cpu_to_le32(sizeof(remove_key));
+-		remove_key.KeyIndex = cpu_to_le32(index);
++		remove_key.size = cpu_to_le32(sizeof(remove_key));
++		remove_key.index = cpu_to_le32(index);
+ 		if (bssid) {
+ 			/* pairwise key */
+ 			if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
+-				remove_key.KeyIndex |= cpu_to_le32(1 << 30);
+-			memcpy(remove_key.Bssid, bssid,
+-					sizeof(remove_key.Bssid));
++				remove_key.index |= cpu_to_le32(1 << 30);
++			memcpy(remove_key.bssid, bssid,
++					sizeof(remove_key.bssid));
+ 		} else
+-			memset(remove_key.Bssid, 0xff,
+-						sizeof(remove_key.Bssid));
++			memset(remove_key.bssid, 0xff,
++						sizeof(remove_key.bssid));
+ 
+ 		ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_KEY, &remove_key,
+ 							sizeof(remove_key));
+@@ -1184,7 +1176,7 @@ static int rndis_iw_get_name(struct net_device *dev,
+ static int rndis_iw_set_essid(struct net_device *dev,
+     struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
+ {
+-	struct NDIS_802_11_SSID ssid;
++	struct ndis_80211_ssid ssid;
+ 	int length = wrqu->essid.length;
+ 	struct usbnet *usbdev = dev->priv;
+ 
+@@ -1194,11 +1186,11 @@ static int rndis_iw_set_essid(struct net_device *dev,
+ 	if (length > NDIS_802_11_LENGTH_SSID)
+ 		length = NDIS_802_11_LENGTH_SSID;
+ 
+-	ssid.SsidLength = cpu_to_le32(length);
++	ssid.length = cpu_to_le32(length);
+ 	if (length > 0)
+-		memcpy(ssid.Ssid, essid, length);
++		memcpy(ssid.essid, essid, length);
+ 	else
+-		memset(ssid.Ssid, 0, NDIS_802_11_LENGTH_SSID);
++		memset(ssid.essid, 0, NDIS_802_11_LENGTH_SSID);
+ 
+ 	set_assoc_params(usbdev);
+ 
+@@ -1212,16 +1204,16 @@ static int rndis_iw_set_essid(struct net_device *dev,
+ static int rndis_iw_get_essid(struct net_device *dev,
+     struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
+ {
+-	struct NDIS_802_11_SSID ssid;
++	struct ndis_80211_ssid ssid;
+ 	struct usbnet *usbdev = dev->priv;
+ 	int ret;
+ 
+ 	ret = get_essid(usbdev, &ssid);
+ 
+-	if (ret == 0 && le32_to_cpu(ssid.SsidLength) > 0) {
++	if (ret == 0 && le32_to_cpu(ssid.length) > 0) {
+ 		wrqu->essid.flags = 1;
+-		wrqu->essid.length = le32_to_cpu(ssid.SsidLength);
+-		memcpy(essid, ssid.Ssid, wrqu->essid.length);
++		wrqu->essid.length = le32_to_cpu(ssid.length);
++		memcpy(essid, ssid.essid, wrqu->essid.length);
+ 		essid[wrqu->essid.length] = 0;
+ 	} else {
+ 		memset(essid, 0, sizeof(NDIS_802_11_LENGTH_SSID));
+@@ -1398,13 +1390,13 @@ static int rndis_iw_get_mode(struct net_device *dev,
+ 	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+ 
+ 	switch (priv->infra_mode) {
+-	case Ndis802_11IBSS:
++	case ndis_80211_infra_adhoc:
+ 		wrqu->mode = IW_MODE_ADHOC;
+ 		break;
+-	case Ndis802_11Infrastructure:
++	case ndis_80211_infra_infra:
+ 		wrqu->mode = IW_MODE_INFRA;
+ 		break;
+-	/*case Ndis802_11AutoUnknown:*/
++	/*case ndis_80211_infra_auto_unknown:*/
+ 	default:
+ 		wrqu->mode = IW_MODE_AUTO;
+ 		break;
+@@ -1424,14 +1416,14 @@ static int rndis_iw_set_mode(struct net_device *dev,
+ 
+ 	switch (wrqu->mode) {
+ 	case IW_MODE_ADHOC:
+-		mode = Ndis802_11IBSS;
++		mode = ndis_80211_infra_adhoc;
+ 		break;
+ 	case IW_MODE_INFRA:
+-		mode = Ndis802_11Infrastructure;
++		mode = ndis_80211_infra_infra;
+ 		break;
+ 	/*case IW_MODE_AUTO:*/
+ 	default:
+-		mode = Ndis802_11AutoUnknown;
++		mode = ndis_80211_infra_auto_unknown;
+ 		break;
+ 	}
+ 
+@@ -1507,7 +1499,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
+ 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ 	struct usbnet *usbdev = dev->priv;
+ 	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+-	struct NDIS_802_11_KEY ndis_key;
++	struct ndis_80211_key ndis_key;
+ 	int keyidx, ret;
+ 	u8 *addr;
+ 
+@@ -1532,54 +1524,54 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
+ 	    ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
+ 		return remove_key(usbdev, keyidx, NULL);
+ 
+-	if (ext->key_len > sizeof(ndis_key.KeyMaterial))
++	if (ext->key_len > sizeof(ndis_key.material))
+ 		return -1;
+ 
+ 	memset(&ndis_key, 0, sizeof(ndis_key));
+ 
+-	ndis_key.Length = cpu_to_le32(sizeof(ndis_key) -
+-				sizeof(ndis_key.KeyMaterial) + ext->key_len);
+-	ndis_key.KeyLength = cpu_to_le32(ext->key_len);
+-	ndis_key.KeyIndex = cpu_to_le32(keyidx);
++	ndis_key.size = cpu_to_le32(sizeof(ndis_key) -
++				sizeof(ndis_key.material) + ext->key_len);
++	ndis_key.length = cpu_to_le32(ext->key_len);
++	ndis_key.index = cpu_to_le32(keyidx);
+ 
+ 	if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+-		memcpy(ndis_key.KeyRSC, ext->rx_seq, 6);
+-		ndis_key.KeyIndex |= cpu_to_le32(1 << 29);
++		memcpy(ndis_key.rsc, ext->rx_seq, 6);
++		ndis_key.index |= cpu_to_le32(1 << 29);
+ 	}
+ 
+ 	addr = ext->addr.sa_data;
+ 	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ 		/* group key */
+-		if (priv->infra_mode == Ndis802_11IBSS)
+-			memset(ndis_key.Bssid, 0xff, ETH_ALEN);
++		if (priv->infra_mode == ndis_80211_infra_adhoc)
++			memset(ndis_key.bssid, 0xff, ETH_ALEN);
+ 		else
+-			get_bssid(usbdev, ndis_key.Bssid);
++			get_bssid(usbdev, ndis_key.bssid);
+ 	} else {
+ 		/* pairwise key */
+-		ndis_key.KeyIndex |= cpu_to_le32(1 << 30);
+-		memcpy(ndis_key.Bssid, addr, ETH_ALEN);
++		ndis_key.index |= cpu_to_le32(1 << 30);
++		memcpy(ndis_key.bssid, addr, ETH_ALEN);
+ 	}
+ 
+ 	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+-		ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
++		ndis_key.index |= cpu_to_le32(1 << 31);
+ 
+ 	if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
+ 		/* wpa_supplicant gives us the Michael MIC RX/TX keys in
+ 		 * different order than NDIS spec, so swap the order here. */
+-		memcpy(ndis_key.KeyMaterial, ext->key, 16);
+-		memcpy(ndis_key.KeyMaterial + 16, ext->key + 24, 8);
+-		memcpy(ndis_key.KeyMaterial + 24, ext->key + 16, 8);
++		memcpy(ndis_key.material, ext->key, 16);
++		memcpy(ndis_key.material + 16, ext->key + 24, 8);
++		memcpy(ndis_key.material + 24, ext->key + 16, 8);
+ 	} else
+-		memcpy(ndis_key.KeyMaterial, ext->key, ext->key_len);
++		memcpy(ndis_key.material, ext->key, ext->key_len);
+ 
+ 	ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
+-					le32_to_cpu(ndis_key.Length));
++					le32_to_cpu(ndis_key.size));
+ 	devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret);
+ 	if (ret != 0)
+ 		return ret;
+ 
+ 	priv->encr_key_len[keyidx] = ext->key_len;
+-	memcpy(&priv->encr_keys[keyidx], ndis_key.KeyMaterial, ext->key_len);
++	memcpy(&priv->encr_keys[keyidx], ndis_key.material, ext->key_len);
+ 	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ 		priv->encr_tx_key_index = keyidx;
+ 
+@@ -1611,7 +1603,7 @@ static int rndis_iw_set_scan(struct net_device *dev,
+ 
+ 
+ static char *rndis_translate_scan(struct net_device *dev,
+-    char *cev, char *end_buf, struct NDIS_WLAN_BSSID_EX *bssid)
++    char *cev, char *end_buf, struct ndis_80211_bssid_ex *bssid)
+ {
+ #ifdef DEBUG
+ 	struct usbnet *usbdev = dev->priv;
+@@ -1624,60 +1616,55 @@ static char *rndis_translate_scan(struct net_device *dev,
+ 	unsigned char sbuf[32];
+ 	DECLARE_MAC_BUF(mac);
+ 
+-	bssid_len = le32_to_cpu(bssid->Length);
++	bssid_len = le32_to_cpu(bssid->length);
+ 
+-	devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->MacAddress));
++	devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->mac));
+ 	iwe.cmd = SIOCGIWAP;
+ 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+-	memcpy(iwe.u.ap_addr.sa_data, bssid->MacAddress, ETH_ALEN);
++	memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN);
+ 	cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
+ 
+-	devdbg(usbdev, "SSID(%d) %s",
+-		le32_to_cpu(bssid->Ssid.SsidLength),
+-		bssid->Ssid.Ssid);
++	devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length),
++						bssid->ssid.essid);
+ 	iwe.cmd = SIOCGIWESSID;
+-	iwe.u.essid.length = le32_to_cpu(bssid->Ssid.SsidLength);
++	iwe.u.essid.length = le32_to_cpu(bssid->ssid.length);
+ 	iwe.u.essid.flags = 1;
+-	cev = iwe_stream_add_point(cev, end_buf, &iwe,
+-						bssid->Ssid.Ssid);
++	cev = iwe_stream_add_point(cev, end_buf, &iwe, bssid->ssid.essid);
+ 
+-	devdbg(usbdev, "MODE %d",
+-			le32_to_cpu(bssid->InfrastructureMode));
++	devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra));
+ 	iwe.cmd = SIOCGIWMODE;
+-	switch (le32_to_cpu(bssid->InfrastructureMode)) {
+-	case Ndis802_11IBSS:
++	switch (le32_to_cpu(bssid->net_infra)) {
++	case ndis_80211_infra_adhoc:
+ 		iwe.u.mode = IW_MODE_ADHOC;
+ 		break;
+-	case Ndis802_11Infrastructure:
++	case ndis_80211_infra_infra:
+ 		iwe.u.mode = IW_MODE_INFRA;
+ 		break;
+-	/*case Ndis802_11AutoUnknown:*/
++	/*case ndis_80211_infra_auto_unknown:*/
+ 	default:
+ 		iwe.u.mode = IW_MODE_AUTO;
+ 		break;
+ 	}
+ 	cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
+ 
+-	devdbg(usbdev, "FREQ %d kHz",
+-		le32_to_cpu(bssid->Configuration.DSConfig));
++	devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config));
+ 	iwe.cmd = SIOCGIWFREQ;
+-	dsconfig_to_freq(le32_to_cpu(bssid->Configuration.DSConfig),
+-								&iwe.u.freq);
++	dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq);
+ 	cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
+ 
+-	devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->Rssi));
++	devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi));
+ 	iwe.cmd = IWEVQUAL;
+-	iwe.u.qual.qual  = level_to_qual(le32_to_cpu(bssid->Rssi));
+-	iwe.u.qual.level = le32_to_cpu(bssid->Rssi);
++	iwe.u.qual.qual  = level_to_qual(le32_to_cpu(bssid->rssi));
++	iwe.u.qual.level = le32_to_cpu(bssid->rssi);
+ 	iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
+ 			| IW_QUAL_LEVEL_UPDATED
+ 			| IW_QUAL_NOISE_INVALID;
+ 	cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
+ 
+-	devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->Privacy));
++	devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy));
+ 	iwe.cmd = SIOCGIWENCODE;
+ 	iwe.u.data.length = 0;
+-	if (le32_to_cpu(bssid->Privacy) == Ndis802_11PrivFilterAcceptAll)
++	if (le32_to_cpu(bssid->privacy) == ndis_80211_priv_accept_all)
+ 		iwe.u.data.flags = IW_ENCODE_DISABLED;
+ 	else
+ 		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+@@ -1687,10 +1674,10 @@ static char *rndis_translate_scan(struct net_device *dev,
+ 	devdbg(usbdev, "RATES:");
+ 	current_val = cev + IW_EV_LCP_LEN;
+ 	iwe.cmd = SIOCGIWRATE;
+-	for (i = 0; i < sizeof(bssid->SupportedRates); i++) {
+-		if (bssid->SupportedRates[i] & 0x7f) {
++	for (i = 0; i < sizeof(bssid->rates); i++) {
++		if (bssid->rates[i] & 0x7f) {
+ 			iwe.u.bitrate.value =
+-				((bssid->SupportedRates[i] & 0x7f) *
++				((bssid->rates[i] & 0x7f) *
+ 				500000);
+ 			devdbg(usbdev, " %d", iwe.u.bitrate.value);
+ 			current_val = iwe_stream_add_value(cev,
+@@ -1702,24 +1689,24 @@ static char *rndis_translate_scan(struct net_device *dev,
+ 	if ((current_val - cev) > IW_EV_LCP_LEN)
+ 		cev = current_val;
+ 
+-	beacon = le32_to_cpu(bssid->Configuration.BeaconPeriod);
++	beacon = le32_to_cpu(bssid->config.beacon_period);
+ 	devdbg(usbdev, "BCN_INT %d", beacon);
+ 	iwe.cmd = IWEVCUSTOM;
+ 	snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon);
+ 	iwe.u.data.length = strlen(sbuf);
+ 	cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
+ 
+-	atim = le32_to_cpu(bssid->Configuration.ATIMWindow);
++	atim = le32_to_cpu(bssid->config.atim_window);
+ 	devdbg(usbdev, "ATIM %d", atim);
+ 	iwe.cmd = IWEVCUSTOM;
+ 	snprintf(sbuf, sizeof(sbuf), "atim=%u", atim);
+ 	iwe.u.data.length = strlen(sbuf);
+ 	cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
+ 
+-	ie = (void *)(bssid->IEs + sizeof(struct NDIS_802_11_FIXED_IEs));
++	ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies));
+ 	ie_len = min(bssid_len - (int)sizeof(*bssid),
+-					(int)le32_to_cpu(bssid->IELength));
+-	ie_len -= sizeof(struct NDIS_802_11_FIXED_IEs);
++					(int)le32_to_cpu(bssid->ie_length));
++	ie_len -= sizeof(struct ndis_80211_fixed_ies);
+ 	while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) {
+ 		if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 &&
+ 				memcmp(ie->data, "\x00\x50\xf2\x01", 4) == 0) ||
+@@ -1746,8 +1733,8 @@ static int rndis_iw_get_scan(struct net_device *dev,
+ 	struct usbnet *usbdev = dev->priv;
+ 	void *buf = NULL;
+ 	char *cev = extra;
+-	struct NDIS_802_11_BSSID_LIST_EX *bssid_list;
+-	struct NDIS_WLAN_BSSID_EX *bssid;
++	struct ndis_80211_bssid_list_ex *bssid_list;
++	struct ndis_80211_bssid_ex *bssid;
+ 	int ret = -EINVAL, len, count, bssid_len;
+ 
+ 	devdbg(usbdev, "SIOCGIWSCAN");
+@@ -1765,16 +1752,16 @@ static int rndis_iw_get_scan(struct net_device *dev,
+ 		goto out;
+ 
+ 	bssid_list = buf;
+-	bssid = bssid_list->Bssid;
+-	bssid_len = le32_to_cpu(bssid->Length);
+-	count = le32_to_cpu(bssid_list->NumberOfItems);
++	bssid = bssid_list->bssid;
++	bssid_len = le32_to_cpu(bssid->length);
++	count = le32_to_cpu(bssid_list->num_items);
+ 	devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count);
+ 
+ 	while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
+ 		cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA,
+ 									bssid);
+ 		bssid = (void *)bssid + bssid_len;
+-		bssid_len = le32_to_cpu(bssid->Length);
++		bssid_len = le32_to_cpu(bssid->length);
+ 		count--;
+ 	}
+ 
+@@ -1948,7 +1935,7 @@ static int rndis_iw_set_freq(struct net_device *dev,
+     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+ {
+ 	struct usbnet *usbdev = dev->priv;
+-	struct NDIS_802_11_CONFIGURATION config;
++	struct ndis_80211_conf config;
+ 	unsigned int dsconfig;
+ 	int len, ret;
+ 
+@@ -1967,7 +1954,7 @@ static int rndis_iw_set_freq(struct net_device *dev,
+ 		return 0;
+ 	}
+ 
+-	config.DSConfig = cpu_to_le32(dsconfig);
++	config.ds_config = cpu_to_le32(dsconfig);
+ 
+ 	devdbg(usbdev, "SIOCSIWFREQ: %d * 10^%d", wrqu->freq.m, wrqu->freq.e);
+ 	return rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config,
+@@ -1979,13 +1966,13 @@ static int rndis_iw_get_freq(struct net_device *dev,
+     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+ {
+ 	struct usbnet *usbdev = dev->priv;
+-	struct NDIS_802_11_CONFIGURATION config;
++	struct ndis_80211_conf config;
+ 	int len, ret;
+ 
+ 	len = sizeof(config);
+ 	ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
+ 	if (ret == 0)
+-		dsconfig_to_freq(le32_to_cpu(config.DSConfig), &wrqu->freq);
++		dsconfig_to_freq(le32_to_cpu(config.ds_config), &wrqu->freq);
+ 
+ 	devdbg(usbdev, "SIOCGIWFREQ: %d", wrqu->freq.m);
+ 	return ret;
+@@ -2266,14 +2253,14 @@ static int rndis_wext_get_caps(struct usbnet *dev)
+ 			n = 8;
+ 		for (i = 0; i < n; i++) {
+ 			switch (le32_to_cpu(networks_supported.items[i])) {
+-			case Ndis802_11FH:
+-			case Ndis802_11DS:
++			case ndis_80211_type_freq_hop:
++			case ndis_80211_type_direct_seq:
+ 				priv->caps |= CAP_MODE_80211B;
+ 				break;
+-			case Ndis802_11OFDM5:
++			case ndis_80211_type_ofdm_a:
+ 				priv->caps |= CAP_MODE_80211A;
+ 				break;
+-			case Ndis802_11OFDM24:
++			case ndis_80211_type_ofdm_g:
+ 				priv->caps |= CAP_MODE_80211G;
+ 				break;
+ 			}
+@@ -2415,7 +2402,6 @@ static int bcm4320_early_init(struct usbnet *dev)
+ 	priv->param_power_output = modparam_power_output;
+ 	priv->param_roamtrigger  = modparam_roamtrigger;
+ 	priv->param_roamdelta    = modparam_roamdelta;
+-	priv->param_workaround_interval = modparam_workaround_interval;
+ 
+ 	priv->param_country[0] = toupper(priv->param_country[0]);
+ 	priv->param_country[1] = toupper(priv->param_country[1]);
+@@ -2438,8 +2424,10 @@ static int bcm4320_early_init(struct usbnet *dev)
+ 	else if (priv->param_roamdelta > 2)
+ 		priv->param_roamdelta = 2;
+ 
+-	if (priv->param_workaround_interval < 0)
++	if (modparam_workaround_interval < 0)
+ 		priv->param_workaround_interval = 500;
++	else
++		priv->param_workaround_interval = modparam_workaround_interval;
+ 
+ 	rndis_set_config_parameter_str(dev, "Country", priv->param_country);
+ 	rndis_set_config_parameter_str(dev, "FrameBursting",
+diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
+index da05b1f..ab1029e 100644
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -5,30 +5,28 @@ config RT2X00
+ 	  This will enable the experimental support for the Ralink drivers,
+ 	  developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
+ 
+-	  These drivers will make use of the Devicescape ieee80211 stack.
++	  These drivers will make use of the mac80211 stack.
+ 
+ 	  When building one of the individual drivers, the rt2x00 library
+ 	  will also be created. That library (when the driver is built as
+ 	  a module) will be called "rt2x00lib.ko".
+ 
++if RT2X00
++
+ config RT2X00_LIB
+ 	tristate
+-	depends on RT2X00
+ 
+ config RT2X00_LIB_PCI
+ 	tristate
+-	depends on RT2X00
+ 	select RT2X00_LIB
+ 
+ config RT2X00_LIB_USB
+ 	tristate
+-	depends on RT2X00
+ 	select RT2X00_LIB
+ 
+ config RT2X00_LIB_FIRMWARE
+ 	boolean
+ 	depends on RT2X00_LIB
+-	select CRC_ITU_T
+ 	select FW_LOADER
+ 
+ config RT2X00_LIB_RFKILL
+@@ -37,9 +35,13 @@ config RT2X00_LIB_RFKILL
+ 	select RFKILL
+ 	select INPUT_POLLDEV
+ 
++config RT2X00_LIB_LEDS
++	boolean
++	depends on RT2X00_LIB
++
+ config RT2400PCI
+ 	tristate "Ralink rt2400 pci/pcmcia support"
+-	depends on RT2X00 && PCI
++	depends on PCI
+ 	select RT2X00_LIB_PCI
+ 	select EEPROM_93CX6
+ 	---help---
+@@ -56,9 +58,17 @@ config RT2400PCI_RFKILL
+ 	  hardware button to control the radio state.
+ 	  This feature depends on the RF switch subsystem rfkill.
+ 
++config RT2400PCI_LEDS
++	bool "RT2400 leds support"
++	depends on RT2400PCI
++	select LEDS_CLASS
++	select RT2X00_LIB_LEDS
++	---help---
++	  This adds support for led triggers provided my mac80211.
++
+ config RT2500PCI
+ 	tristate "Ralink rt2500 pci/pcmcia support"
+-	depends on RT2X00 && PCI
++	depends on PCI
+ 	select RT2X00_LIB_PCI
+ 	select EEPROM_93CX6
+ 	---help---
+@@ -75,11 +85,20 @@ config RT2500PCI_RFKILL
+ 	  hardware button to control the radio state.
+ 	  This feature depends on the RF switch subsystem rfkill.
+ 
++config RT2500PCI_LEDS
++	bool "RT2500 leds support"
++	depends on RT2500PCI
++	select LEDS_CLASS
++	select RT2X00_LIB_LEDS
++	---help---
++	  This adds support for led triggers provided my mac80211.
++
+ config RT61PCI
+ 	tristate "Ralink rt61 pci/pcmcia support"
+-	depends on RT2X00 && PCI
++	depends on PCI
+ 	select RT2X00_LIB_PCI
+ 	select RT2X00_LIB_FIRMWARE
++	select CRC_ITU_T
+ 	select EEPROM_93CX6
+ 	---help---
+ 	  This is an experimental driver for the Ralink rt61 wireless chip.
+@@ -95,25 +114,50 @@ config RT61PCI_RFKILL
+ 	  hardware button to control the radio state.
+ 	  This feature depends on the RF switch subsystem rfkill.
+ 
++config RT61PCI_LEDS
++	bool "RT61 leds support"
++	depends on RT61PCI
++	select LEDS_CLASS
++	select RT2X00_LIB_LEDS
++	---help---
++	  This adds support for led triggers provided my mac80211.
++
+ config RT2500USB
+ 	tristate "Ralink rt2500 usb support"
+-	depends on RT2X00 && USB
++	depends on USB
+ 	select RT2X00_LIB_USB
+ 	---help---
+ 	  This is an experimental driver for the Ralink rt2500 wireless chip.
+ 
+ 	  When compiled as a module, this driver will be called "rt2500usb.ko".
+ 
++config RT2500USB_LEDS
++	bool "RT2500 leds support"
++	depends on RT2500USB
++	select LEDS_CLASS
++	select RT2X00_LIB_LEDS
++	---help---
++	  This adds support for led triggers provided my mac80211.
++
+ config RT73USB
+ 	tristate "Ralink rt73 usb support"
+-	depends on RT2X00 && USB
++	depends on USB
+ 	select RT2X00_LIB_USB
+ 	select RT2X00_LIB_FIRMWARE
++	select CRC_ITU_T
+ 	---help---
+ 	  This is an experimental driver for the Ralink rt73 wireless chip.
+ 
+ 	  When compiled as a module, this driver will be called "rt73usb.ko".
+ 
++config RT73USB_LEDS
++	bool "RT73 leds support"
++	depends on RT73USB
++	select LEDS_CLASS
++	select RT2X00_LIB_LEDS
++	---help---
++	  This adds support for led triggers provided my mac80211.
++
+ config RT2X00_LIB_DEBUGFS
+ 	bool "Ralink debugfs support"
+ 	depends on RT2X00_LIB && MAC80211_DEBUGFS
+@@ -128,3 +172,4 @@ config RT2X00_DEBUG
+ 	---help---
+ 	  Enable debugging output for all rt2x00 modules
+ 
++endif
+diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
+index 30d654a..1087dbc 100644
+--- a/drivers/net/wireless/rt2x00/Makefile
++++ b/drivers/net/wireless/rt2x00/Makefile
+@@ -1,22 +1,17 @@
+-rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o
++rt2x00lib-y				+= rt2x00dev.o
++rt2x00lib-y				+= rt2x00mac.o
++rt2x00lib-y				+= rt2x00config.o
++rt2x00lib-y				+= rt2x00queue.o
++rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS)	+= rt2x00debug.o
++rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL)	+= rt2x00rfkill.o
++rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)	+= rt2x00firmware.o
++rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)	+= rt2x00leds.o
+ 
+-ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y)
+-	rt2x00lib-objs += rt2x00debug.o
+-endif
+-
+-ifeq ($(CONFIG_RT2X00_LIB_RFKILL),y)
+-	rt2x00lib-objs += rt2x00rfkill.o
+-endif
+-
+-ifeq ($(CONFIG_RT2X00_LIB_FIRMWARE),y)
+-	rt2x00lib-objs += rt2x00firmware.o
+-endif
+-
+-obj-$(CONFIG_RT2X00_LIB)	+= rt2x00lib.o
+-obj-$(CONFIG_RT2X00_LIB_PCI)	+= rt2x00pci.o
+-obj-$(CONFIG_RT2X00_LIB_USB)	+= rt2x00usb.o
+-obj-$(CONFIG_RT2400PCI)		+= rt2400pci.o
+-obj-$(CONFIG_RT2500PCI)		+= rt2500pci.o
+-obj-$(CONFIG_RT61PCI)		+= rt61pci.o
+-obj-$(CONFIG_RT2500USB)		+= rt2500usb.o
+-obj-$(CONFIG_RT73USB)		+= rt73usb.o
++obj-$(CONFIG_RT2X00_LIB)		+= rt2x00lib.o
++obj-$(CONFIG_RT2X00_LIB_PCI)		+= rt2x00pci.o
++obj-$(CONFIG_RT2X00_LIB_USB)		+= rt2x00usb.o
++obj-$(CONFIG_RT2400PCI)			+= rt2400pci.o
++obj-$(CONFIG_RT2500PCI)			+= rt2500pci.o
++obj-$(CONFIG_RT61PCI)			+= rt61pci.o
++obj-$(CONFIG_RT2500USB)			+= rt2500usb.o
++obj-$(CONFIG_RT73USB)			+= rt73usb.o
+diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
+index c69f85e..b41187a 100644
+--- a/drivers/net/wireless/rt2x00/rt2400pci.c
++++ b/drivers/net/wireless/rt2x00/rt2400pci.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -243,53 +243,109 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+ #define rt2400pci_rfkill_poll	NULL
+ #endif /* CONFIG_RT2400PCI_RFKILL */
+ 
+-/*
+- * Configuration handlers.
+- */
+-static void rt2400pci_config_mac_addr(struct rt2x00_dev *rt2x00dev,
+-				      __le32 *mac)
++#ifdef CONFIG_RT2400PCI_LEDS
++static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
++				     enum led_brightness brightness)
+ {
+-	rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac,
+-				      (2 * sizeof(__le32)));
++	struct rt2x00_led *led =
++	    container_of(led_cdev, struct rt2x00_led, led_dev);
++	unsigned int enabled = brightness != LED_OFF;
++	u32 reg;
++
++	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
++
++	if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
++		rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
++	else if (led->type == LED_TYPE_ACTIVITY)
++		rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
++
++	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ }
+ 
+-static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev,
+-				   __le32 *bssid)
++static int rt2400pci_blink_set(struct led_classdev *led_cdev,
++			       unsigned long *delay_on,
++			       unsigned long *delay_off)
+ {
+-	rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid,
+-				      (2 * sizeof(__le32)));
++	struct rt2x00_led *led =
++	    container_of(led_cdev, struct rt2x00_led, led_dev);
++	u32 reg;
++
++	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
++	rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
++	rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
++	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
++
++	return 0;
+ }
++#endif /* CONFIG_RT2400PCI_LEDS */
+ 
+-static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+-				  const int tsf_sync)
++/*
++ * Configuration handlers.
++ */
++static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
++				    const unsigned int filter_flags)
+ {
+ 	u32 reg;
+ 
+-	rt2x00pci_register_write(rt2x00dev, CSR14, 0);
+-
+ 	/*
+-	 * Enable beacon config
++	 * Start configuration steps.
++	 * Note that the version error will always be dropped
++	 * since there is no filter for it at this time.
+ 	 */
+-	rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
+-	rt2x00_set_field32(&reg, BCNCSR1_PRELOAD,
+-			   PREAMBLE + get_duration(IEEE80211_HEADER, 20));
+-	rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
++	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
++	rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
++			   !(filter_flags & FIF_FCSFAIL));
++	rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
++			   !(filter_flags & FIF_PLCPFAIL));
++	rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
++			   !(filter_flags & FIF_CONTROL));
++	rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
++			   !(filter_flags & FIF_PROMISC_IN_BSS));
++	rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
++			   !(filter_flags & FIF_PROMISC_IN_BSS) &&
++			   !rt2x00dev->intf_ap_count);
++	rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
++	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
++}
+ 
+-	/*
+-	 * Enable synchronisation.
+-	 */
+-	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+-	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
+-	rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
+-	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+-	rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
+-	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
++				  struct rt2x00_intf *intf,
++				  struct rt2x00intf_conf *conf,
++				  const unsigned int flags)
++{
++	unsigned int bcn_preload;
++	u32 reg;
++
++	if (flags & CONFIG_UPDATE_TYPE) {
++		/*
++		 * Enable beacon config
++		 */
++		bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
++		rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
++		rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
++		rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
++
++		/*
++		 * Enable synchronisation.
++		 */
++		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
++		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
++		rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
++		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
++		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++	}
++
++	if (flags & CONFIG_UPDATE_MAC)
++		rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
++					      conf->mac, sizeof(conf->mac));
++
++	if (flags & CONFIG_UPDATE_BSSID)
++		rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
++					      conf->bssid, sizeof(conf->bssid));
+ }
+ 
+-static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+-				      const int short_preamble,
+-				      const int ack_timeout,
+-				      const int ack_consume_time)
++static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
++				 struct rt2x00lib_erp *erp)
+ {
+ 	int preamble_mask;
+ 	u32 reg;
+@@ -297,11 +353,13 @@ static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+ 	/*
+ 	 * When short preamble is enabled, we should set bit 0x08
+ 	 */
+-	preamble_mask = short_preamble << 3;
++	preamble_mask = erp->short_preamble << 3;
+ 
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+-	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, ack_timeout);
+-	rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, ack_consume_time);
++	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT,
++			   erp->ack_timeout);
++	rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME,
++			   erp->ack_consume_time);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+ 
+ 	rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+@@ -397,6 +455,13 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	u8 r1;
+ 	u8 r4;
+ 
++	/*
++	 * We should never come here because rt2x00lib is supposed
++	 * to catch this and send us the correct antenna explicitely.
++	 */
++	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++	       ant->tx == ANTENNA_SW_DIVERSITY);
++
+ 	rt2400pci_bbp_read(rt2x00dev, 4, &r4);
+ 	rt2400pci_bbp_read(rt2x00dev, 1, &r1);
+ 
+@@ -410,14 +475,8 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	case ANTENNA_A:
+ 		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
+ 		break;
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
+ 		break;
+ 	}
+@@ -432,14 +491,8 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	case ANTENNA_A:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
+ 		break;
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+ 		break;
+ 	}
+@@ -481,8 +534,8 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
+-			     const unsigned int flags,
+-			     struct rt2x00lib_conf *libconf)
++			     struct rt2x00lib_conf *libconf,
++			     const unsigned int flags)
+ {
+ 	if (flags & CONFIG_UPDATE_PHYMODE)
+ 		rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates);
+@@ -498,45 +551,17 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
+-				struct ieee80211_tx_queue_params *params)
++				const int cw_min, const int cw_max)
+ {
+ 	u32 reg;
+ 
+ 	rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+-	rt2x00_set_field32(&reg, CSR11_CWMIN, params->cw_min);
+-	rt2x00_set_field32(&reg, CSR11_CWMAX, params->cw_max);
++	rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
++	rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
+ 	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ }
+ 
+ /*
+- * LED functions.
+- */
+-static void rt2400pci_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	u32 reg;
+-
+-	rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
+-
+-	rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
+-	rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
+-	rt2x00_set_field32(&reg, LEDCSR_LINK,
+-			   (rt2x00dev->led_mode != LED_MODE_ASUS));
+-	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY,
+-			   (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
+-	rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
+-}
+-
+-static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	u32 reg;
+-
+-	rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
+-	rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
+-	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
+-	rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
+-}
+-
+-/*
+  * Link tuning
+  */
+ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -593,90 +618,94 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+  * Initialization functions.
+  */
+ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+-				   struct data_entry *entry)
++				   struct queue_entry *entry)
+ {
+-	__le32 *rxd = entry->priv;
++	struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ 	u32 word;
+ 
+-	rt2x00_desc_read(rxd, 2, &word);
+-	rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+-	rt2x00_desc_write(rxd, 2, word);
++	rt2x00_desc_read(priv_rx->desc, 2, &word);
++	rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
++			   entry->queue->data_size);
++	rt2x00_desc_write(priv_rx->desc, 2, word);
+ 
+-	rt2x00_desc_read(rxd, 1, &word);
+-	rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+-	rt2x00_desc_write(rxd, 1, word);
++	rt2x00_desc_read(priv_rx->desc, 1, &word);
++	rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
++	rt2x00_desc_write(priv_rx->desc, 1, word);
+ 
+-	rt2x00_desc_read(rxd, 0, &word);
++	rt2x00_desc_read(priv_rx->desc, 0, &word);
+ 	rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+-	rt2x00_desc_write(rxd, 0, word);
++	rt2x00_desc_write(priv_rx->desc, 0, word);
+ }
+ 
+ static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+-				   struct data_entry *entry)
++				   struct queue_entry *entry)
+ {
+-	__le32 *txd = entry->priv;
++	struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
+ 	u32 word;
+ 
+-	rt2x00_desc_read(txd, 1, &word);
+-	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+-	rt2x00_desc_write(txd, 1, word);
++	rt2x00_desc_read(priv_tx->desc, 1, &word);
++	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
++	rt2x00_desc_write(priv_tx->desc, 1, word);
+ 
+-	rt2x00_desc_read(txd, 2, &word);
+-	rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+-	rt2x00_desc_write(txd, 2, word);
++	rt2x00_desc_read(priv_tx->desc, 2, &word);
++	rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH,
++			   entry->queue->data_size);
++	rt2x00_desc_write(priv_tx->desc, 2, word);
+ 
+-	rt2x00_desc_read(txd, 0, &word);
++	rt2x00_desc_read(priv_tx->desc, 0, &word);
+ 	rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ 	rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+-	rt2x00_desc_write(txd, 0, word);
++	rt2x00_desc_write(priv_tx->desc, 0, word);
+ }
+ 
+-static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev)
++static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
+ {
++	struct queue_entry_priv_pci_rx *priv_rx;
++	struct queue_entry_priv_pci_tx *priv_tx;
+ 	u32 reg;
+ 
+ 	/*
+ 	 * Initialize registers.
+ 	 */
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
+-	rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
+-	rt2x00_set_field32(&reg, TXCSR2_NUM_TXD,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
+-	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM,
+-			   rt2x00dev->bcn[1].stats.limit);
+-	rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
++	rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
++	rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
++	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
++	rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
+ 
++	priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
+ 	rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
+ 
++	priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
+ 	rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
+ 
++	priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
+ 	rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
+-			   rt2x00dev->bcn[1].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
+ 
++	priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
+ 	rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
+-			   rt2x00dev->bcn[0].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
+ 
+ 	rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
+ 	rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
+-	rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
++	rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
+ 	rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
+ 
++	priv_rx = rt2x00dev->rx->entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
+-	rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
+-			   rt2x00dev->rx->data_dma);
++	rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
+ 
+ 	return 0;
+@@ -795,19 +824,15 @@ continue_csr_init:
+ 	rt2400pci_bbp_write(rt2x00dev, 30, 0x21);
+ 	rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
+ 
+-	DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ 		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ 
+ 		if (eeprom != 0xffff && eeprom != 0x0000) {
+ 			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ 			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+-			DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+-			      reg_id, value);
+ 			rt2400pci_bbp_write(rt2x00dev, reg_id, value);
+ 		}
+ 	}
+-	DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+ 
+ 	return 0;
+ }
+@@ -859,7 +884,7 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Initialize all registers.
+ 	 */
+-	if (rt2400pci_init_rings(rt2x00dev) ||
++	if (rt2400pci_init_queues(rt2x00dev) ||
+ 	    rt2400pci_init_registers(rt2x00dev) ||
+ 	    rt2400pci_init_bbp(rt2x00dev)) {
+ 		ERROR(rt2x00dev, "Register initialization failed.\n");
+@@ -871,11 +896,6 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ 	 */
+ 	rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
+ 
+-	/*
+-	 * Enable LED
+-	 */
+-	rt2400pci_enable_led(rt2x00dev);
+-
+ 	return 0;
+ }
+ 
+@@ -883,11 +903,6 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+ 	u32 reg;
+ 
+-	/*
+-	 * Disable LED
+-	 */
+-	rt2400pci_disable_led(rt2x00dev);
+-
+ 	rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
+ 
+ 	/*
+@@ -986,10 +1001,10 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+  */
+ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 				    struct sk_buff *skb,
+-				    struct txdata_entry_desc *desc,
++				    struct txentry_desc *txdesc,
+ 				    struct ieee80211_tx_control *control)
+ {
+-	struct skb_desc *skbdesc = get_skb_desc(skb);
++	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ 	__le32 *txd = skbdesc->desc;
+ 	u32 word;
+ 
+@@ -1001,19 +1016,19 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 	rt2x00_desc_write(txd, 2, word);
+ 
+ 	rt2x00_desc_read(txd, 3, &word);
+-	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
++	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
+ 	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
+ 	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
+-	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
++	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
+ 	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
+ 	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
+ 	rt2x00_desc_write(txd, 3, word);
+ 
+ 	rt2x00_desc_read(txd, 4, &word);
+-	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, desc->length_low);
++	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->length_low);
+ 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
+ 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
+-	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, desc->length_high);
++	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, txdesc->length_high);
+ 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
+ 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
+ 	rt2x00_desc_write(txd, 4, word);
+@@ -1022,14 +1037,14 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 	rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
+ 	rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+ 	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+-			   test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_ACK,
+-			   test_bit(ENTRY_TXD_ACK, &desc->flags));
++			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+-			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_RTS,
+-			   test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags));
+-	rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++			   test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
++	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+ 			   !!(control->flags &
+ 			      IEEE80211_TXCTL_LONG_RETRY_LIMIT));
+@@ -1040,13 +1055,15 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+  * TX data initialization
+  */
+ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+-				    unsigned int queue)
++				    const unsigned int queue)
+ {
+ 	u32 reg;
+ 
+-	if (queue == IEEE80211_TX_QUEUE_BEACON) {
++	if (queue == RT2X00_BCN_QUEUE_BEACON) {
+ 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ 		if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
++			rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
++			rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+ 			rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+ 			rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ 		}
+@@ -1059,56 +1076,62 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ 	rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
+ 			   (queue == IEEE80211_TX_QUEUE_DATA1));
+ 	rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
+-			   (queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
++			   (queue == RT2X00_BCN_QUEUE_ATIM));
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ }
+ 
+ /*
+  * RX control handlers
+  */
+-static void rt2400pci_fill_rxdone(struct data_entry *entry,
+-				  struct rxdata_entry_desc *desc)
++static void rt2400pci_fill_rxdone(struct queue_entry *entry,
++				  struct rxdone_entry_desc *rxdesc)
+ {
+-	__le32 *rxd = entry->priv;
++	struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ 	u32 word0;
+ 	u32 word2;
++	u32 word3;
+ 
+-	rt2x00_desc_read(rxd, 0, &word0);
+-	rt2x00_desc_read(rxd, 2, &word2);
++	rt2x00_desc_read(priv_rx->desc, 0, &word0);
++	rt2x00_desc_read(priv_rx->desc, 2, &word2);
++	rt2x00_desc_read(priv_rx->desc, 3, &word3);
+ 
+-	desc->flags = 0;
++	rxdesc->flags = 0;
+ 	if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+-		desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ 	if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+-		desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
++		rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+ 
+ 	/*
+ 	 * Obtain the status about this packet.
++	 * The signal is the PLCP value, and needs to be stripped
++	 * of the preamble bit (0x08).
+ 	 */
+-	desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
+-	desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
+-	    entry->ring->rt2x00dev->rssi_offset;
+-	desc->ofdm = 0;
+-	desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+-	desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++	rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08;
++	rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) -
++	    entry->queue->rt2x00dev->rssi_offset;
++	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++	rxdesc->dev_flags = RXDONE_SIGNAL_PLCP;
++	if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++		rxdesc->dev_flags |= RXDONE_MY_BSS;
+ }
+ 
+ /*
+  * Interrupt functions.
+  */
+-static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
++static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
++			     const enum ieee80211_tx_queue queue_idx)
+ {
+-	struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
+-	struct data_entry *entry;
+-	__le32 *txd;
++	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
++	struct queue_entry_priv_pci_tx *priv_tx;
++	struct queue_entry *entry;
++	struct txdone_entry_desc txdesc;
+ 	u32 word;
+-	int tx_status;
+-	int retry;
+ 
+-	while (!rt2x00_ring_empty(ring)) {
+-		entry = rt2x00_get_data_entry_done(ring);
+-		txd = entry->priv;
+-		rt2x00_desc_read(txd, 0, &word);
++	while (!rt2x00queue_empty(queue)) {
++		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
++		priv_tx = entry->priv_data;
++		rt2x00_desc_read(priv_tx->desc, 0, &word);
+ 
+ 		if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ 		    !rt2x00_get_field32(word, TXD_W0_VALID))
+@@ -1117,10 +1140,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
+ 		/*
+ 		 * Obtain the status about this packet.
+ 		 */
+-		tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
+-		retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
++		txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
++		txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
+ 
+-		rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
++		rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
+ 	}
+ }
+ 
+@@ -1164,7 +1187,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
+ 	 * 3 - Atim ring transmit done interrupt.
+ 	 */
+ 	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
+-		rt2400pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
++		rt2400pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
+ 
+ 	/*
+ 	 * 4 - Priority ring transmit done interrupt.
+@@ -1272,8 +1295,27 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Store led mode, for correct led behaviour.
+ 	 */
+-	rt2x00dev->led_mode =
+-	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++#ifdef CONFIG_RT2400PCI_LEDS
++	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++
++	rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++	rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++	rt2x00dev->led_radio.led_dev.brightness_set =
++	    rt2400pci_brightness_set;
++	rt2x00dev->led_radio.led_dev.blink_set =
++	    rt2400pci_blink_set;
++	rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++	if (value == LED_MODE_TXRX_ACTIVITY) {
++		rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++		rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
++		rt2x00dev->led_qual.led_dev.brightness_set =
++		    rt2400pci_brightness_set;
++		rt2x00dev->led_qual.led_dev.blink_set =
++		    rt2400pci_blink_set;
++		rt2x00dev->led_qual.flags = LED_INITIALIZED;
++	}
++#endif /* CONFIG_RT2400PCI_LEDS */
+ 
+ 	/*
+ 	 * Detect if this device has an hardware controlled radio.
+@@ -1343,8 +1385,8 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Initialize hw_mode information.
+ 	 */
+-	spec->num_modes = 1;
+-	spec->num_rates = 4;
++	spec->supported_bands = SUPPORT_BAND_2GHZ;
++	spec->supported_rates = SUPPORT_RATE_CCK;
+ 	spec->tx_power_a = NULL;
+ 	spec->tx_power_bg = txpower;
+ 	spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -1374,9 +1416,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ 	rt2400pci_probe_hw_mode(rt2x00dev);
+ 
+ 	/*
+-	 * This device requires the beacon ring
++	 * This device requires the atim queue
+ 	 */
+-	__set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
++	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
+ 
+ 	/*
+ 	 * Set the rssi offset.
+@@ -1389,64 +1431,6 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+  * IEEE80211 stack callback functions.
+  */
+-static void rt2400pci_configure_filter(struct ieee80211_hw *hw,
+-				       unsigned int changed_flags,
+-				       unsigned int *total_flags,
+-				       int mc_count,
+-				       struct dev_addr_list *mc_list)
+-{
+-	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	u32 reg;
+-
+-	/*
+-	 * Mask off any flags we are going to ignore from
+-	 * the total_flags field.
+-	 */
+-	*total_flags &=
+-	    FIF_ALLMULTI |
+-	    FIF_FCSFAIL |
+-	    FIF_PLCPFAIL |
+-	    FIF_CONTROL |
+-	    FIF_OTHER_BSS |
+-	    FIF_PROMISC_IN_BSS;
+-
+-	/*
+-	 * Apply some rules to the filters:
+-	 * - Some filters imply different filters to be set.
+-	 * - Some things we can't filter out at all.
+-	 */
+-	*total_flags |= FIF_ALLMULTI;
+-	if (*total_flags & FIF_OTHER_BSS ||
+-	    *total_flags & FIF_PROMISC_IN_BSS)
+-		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+-	/*
+-	 * Check if there is any work left for us.
+-	 */
+-	if (rt2x00dev->packet_filter == *total_flags)
+-		return;
+-	rt2x00dev->packet_filter = *total_flags;
+-
+-	/*
+-	 * Start configuration steps.
+-	 * Note that the version error will always be dropped
+-	 * since there is no filter for it at this time.
+-	 */
+-	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
+-			   !(*total_flags & FIF_FCSFAIL));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
+-			   !(*total_flags & FIF_PLCPFAIL));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
+-			   !(*total_flags & FIF_CONTROL));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
+-	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+-}
+-
+ static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw,
+ 				     u32 short_retry, u32 long_retry)
+ {
+@@ -1481,7 +1465,8 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw,
+ 	/*
+ 	 * Write configuration to register.
+ 	 */
+-	rt2400pci_config_cw(rt2x00dev, &rt2x00dev->tx->tx_params);
++	rt2400pci_config_cw(rt2x00dev,
++			    rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max);
+ 
+ 	return 0;
+ }
+@@ -1500,12 +1485,58 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw)
+ 	return tsf;
+ }
+ 
+-static void rt2400pci_reset_tsf(struct ieee80211_hw *hw)
++static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
++				   struct ieee80211_tx_control *control)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
++	struct rt2x00_intf *intf = vif_to_intf(control->vif);
++	struct queue_entry_priv_pci_tx *priv_tx;
++	struct skb_frame_desc *skbdesc;
++	u32 reg;
++
++	if (unlikely(!intf->beacon))
++		return -ENOBUFS;
++	priv_tx = intf->beacon->priv_data;
+ 
+-	rt2x00pci_register_write(rt2x00dev, CSR16, 0);
+-	rt2x00pci_register_write(rt2x00dev, CSR17, 0);
++	/*
++	 * Fill in skb descriptor
++	 */
++	skbdesc = get_skb_frame_desc(skb);
++	memset(skbdesc, 0, sizeof(*skbdesc));
++	skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++	skbdesc->data = skb->data;
++	skbdesc->data_len = skb->len;
++	skbdesc->desc = priv_tx->desc;
++	skbdesc->desc_len = intf->beacon->queue->desc_size;
++	skbdesc->entry = intf->beacon;
++
++	/*
++	 * Disable beaconing while we are reloading the beacon data,
++	 * otherwise we might be sending out invalid data.
++	 */
++	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
++	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
++	rt2x00_set_field32(&reg, CSR14_TBCN, 0);
++	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
++	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++
++	/*
++	 * mac80211 doesn't provide the control->queue variable
++	 * for beacons. Set our own queue identification so
++	 * it can be used during descriptor initialization.
++	 */
++	control->queue = RT2X00_BCN_QUEUE_BEACON;
++	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
++
++	/*
++	 * Enable beacon generation.
++	 * Write entire beacon with descriptor to register,
++	 * and kick the beacon generator.
++	 */
++	memcpy(priv_tx->data, skb->data, skb->len);
++	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
++
++	return 0;
+ }
+ 
+ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
+@@ -1525,15 +1556,14 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
+ 	.remove_interface	= rt2x00mac_remove_interface,
+ 	.config			= rt2x00mac_config,
+ 	.config_interface	= rt2x00mac_config_interface,
+-	.configure_filter	= rt2400pci_configure_filter,
++	.configure_filter	= rt2x00mac_configure_filter,
+ 	.get_stats		= rt2x00mac_get_stats,
+ 	.set_retry_limit	= rt2400pci_set_retry_limit,
+ 	.bss_info_changed	= rt2x00mac_bss_info_changed,
+ 	.conf_tx		= rt2400pci_conf_tx,
+ 	.get_tx_stats		= rt2x00mac_get_tx_stats,
+ 	.get_tsf		= rt2400pci_get_tsf,
+-	.reset_tsf		= rt2400pci_reset_tsf,
+-	.beacon_update		= rt2x00pci_beacon_update,
++	.beacon_update		= rt2400pci_beacon_update,
+ 	.tx_last_beacon		= rt2400pci_tx_last_beacon,
+ };
+ 
+@@ -1553,19 +1583,50 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
+ 	.write_tx_data		= rt2x00pci_write_tx_data,
+ 	.kick_tx_queue		= rt2400pci_kick_tx_queue,
+ 	.fill_rxdone		= rt2400pci_fill_rxdone,
+-	.config_mac_addr	= rt2400pci_config_mac_addr,
+-	.config_bssid		= rt2400pci_config_bssid,
+-	.config_type		= rt2400pci_config_type,
+-	.config_preamble	= rt2400pci_config_preamble,
++	.config_filter		= rt2400pci_config_filter,
++	.config_intf		= rt2400pci_config_intf,
++	.config_erp		= rt2400pci_config_erp,
+ 	.config			= rt2400pci_config,
+ };
+ 
++static const struct data_queue_desc rt2400pci_queue_rx = {
++	.entry_num		= RX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= RXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_rx),
++};
++
++static const struct data_queue_desc rt2400pci_queue_tx = {
++	.entry_num		= TX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt2400pci_queue_bcn = {
++	.entry_num		= BEACON_ENTRIES,
++	.data_size		= MGMT_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt2400pci_queue_atim = {
++	.entry_num		= ATIM_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_tx),
++};
++
+ static const struct rt2x00_ops rt2400pci_ops = {
+ 	.name		= KBUILD_MODNAME,
+-	.rxd_size	= RXD_DESC_SIZE,
+-	.txd_size	= TXD_DESC_SIZE,
++	.max_sta_intf	= 1,
++	.max_ap_intf	= 1,
+ 	.eeprom_size	= EEPROM_SIZE,
+ 	.rf_size	= RF_SIZE,
++	.rx		= &rt2400pci_queue_rx,
++	.tx		= &rt2400pci_queue_tx,
++	.bcn		= &rt2400pci_queue_bcn,
++	.atim		= &rt2400pci_queue_atim,
+ 	.lib		= &rt2400pci_rt2x00_ops,
+ 	.hw		= &rt2400pci_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
+index 369aac6..a5210f9 100644
+--- a/drivers/net/wireless/rt2x00/rt2400pci.h
++++ b/drivers/net/wireless/rt2x00/rt2400pci.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -899,13 +899,13 @@
+  * Word2
+  */
+ #define RXD_W2_BUFFER_LENGTH		FIELD32(0x0000ffff)
+-#define RXD_W2_SIGNAL			FIELD32(0x00ff0000)
+-#define RXD_W2_RSSI			FIELD32(0xff000000)
++#define RXD_W2_BBR0			FIELD32(0x00ff0000)
++#define RXD_W2_SIGNAL			FIELD32(0xff000000)
+ 
+ /*
+  * Word3
+  */
+-#define RXD_W3_BBR2			FIELD32(0x000000ff)
++#define RXD_W3_RSSI			FIELD32(0x000000ff)
+ #define RXD_W3_BBR3			FIELD32(0x0000ff00)
+ #define RXD_W3_BBR4			FIELD32(0x00ff0000)
+ #define RXD_W3_BBR5			FIELD32(0xff000000)
+@@ -923,13 +923,13 @@
+ #define RXD_W7_RESERVED			FIELD32(0xffffffff)
+ 
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+  * NOTE: Logics in rt2400pci for txpower are reversed
+  * compared to the other rt2x00 drivers. A higher txpower
+  * value means that the txpower must be lowered. This is
+  * important when converting the value coming from the
+- * dscape stack to the rt2400 acceptable value.
++ * mac80211 stack to the rt2400 acceptable value.
+  */
+ #define MIN_TXPOWER	31
+ #define MAX_TXPOWER	62
+diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
+index 91e87b5..5ade097 100644
+--- a/drivers/net/wireless/rt2x00/rt2500pci.c
++++ b/drivers/net/wireless/rt2x00/rt2500pci.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -243,57 +243,116 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+ #define rt2500pci_rfkill_poll	NULL
+ #endif /* CONFIG_RT2500PCI_RFKILL */
+ 
+-/*
+- * Configuration handlers.
+- */
+-static void rt2500pci_config_mac_addr(struct rt2x00_dev *rt2x00dev,
+-				      __le32 *mac)
++#ifdef CONFIG_RT2500PCI_LEDS
++static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
++				     enum led_brightness brightness)
+ {
+-	rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac,
+-				      (2 * sizeof(__le32)));
++	struct rt2x00_led *led =
++	    container_of(led_cdev, struct rt2x00_led, led_dev);
++	unsigned int enabled = brightness != LED_OFF;
++	u32 reg;
++
++	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
++
++	if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
++		rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
++	else if (led->type == LED_TYPE_ACTIVITY)
++		rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
++
++	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ }
+ 
+-static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev,
+-				   __le32 *bssid)
++static int rt2500pci_blink_set(struct led_classdev *led_cdev,
++			       unsigned long *delay_on,
++			       unsigned long *delay_off)
+ {
+-	rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid,
+-				      (2 * sizeof(__le32)));
++	struct rt2x00_led *led =
++	    container_of(led_cdev, struct rt2x00_led, led_dev);
++	u32 reg;
++
++	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
++	rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
++	rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
++	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
++
++	return 0;
+ }
++#endif /* CONFIG_RT2500PCI_LEDS */
+ 
+-static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+-				  const int tsf_sync)
++/*
++ * Configuration handlers.
++ */
++static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
++				    const unsigned int filter_flags)
+ {
+ 	u32 reg;
+ 
+-	rt2x00pci_register_write(rt2x00dev, CSR14, 0);
+-
+ 	/*
+-	 * Enable beacon config
++	 * Start configuration steps.
++	 * Note that the version error will always be dropped
++	 * and broadcast frames will always be accepted since
++	 * there is no filter for it at this time.
+ 	 */
+-	rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
+-	rt2x00_set_field32(&reg, BCNCSR1_PRELOAD,
+-			   PREAMBLE + get_duration(IEEE80211_HEADER, 20));
+-	rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN,
+-			   rt2x00lib_get_ring(rt2x00dev,
+-					      IEEE80211_TX_QUEUE_BEACON)
+-			   ->tx_params.cw_min);
+-	rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
++	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
++	rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
++			   !(filter_flags & FIF_FCSFAIL));
++	rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
++			   !(filter_flags & FIF_PLCPFAIL));
++	rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
++			   !(filter_flags & FIF_CONTROL));
++	rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
++			   !(filter_flags & FIF_PROMISC_IN_BSS));
++	rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
++			   !(filter_flags & FIF_PROMISC_IN_BSS) &&
++			   !rt2x00dev->intf_ap_count);
++	rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
++	rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
++			   !(filter_flags & FIF_ALLMULTI));
++	rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
++	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
++}
+ 
+-	/*
+-	 * Enable synchronisation.
+-	 */
+-	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+-	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
+-	rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
+-	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+-	rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
+-	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
++				  struct rt2x00_intf *intf,
++				  struct rt2x00intf_conf *conf,
++				  const unsigned int flags)
++{
++	struct data_queue *queue =
++	    rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
++	unsigned int bcn_preload;
++	u32 reg;
++
++	if (flags & CONFIG_UPDATE_TYPE) {
++		/*
++		 * Enable beacon config
++		 */
++		bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
++		rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
++		rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
++		rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
++		rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
++
++		/*
++		 * Enable synchronisation.
++		 */
++		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
++		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
++		rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
++		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
++		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++	}
++
++	if (flags & CONFIG_UPDATE_MAC)
++		rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
++					      conf->mac, sizeof(conf->mac));
++
++	if (flags & CONFIG_UPDATE_BSSID)
++		rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
++					      conf->bssid, sizeof(conf->bssid));
+ }
+ 
+-static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+-				      const int short_preamble,
+-				      const int ack_timeout,
+-				      const int ack_consume_time)
++static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
++				 struct rt2x00lib_erp *erp)
+ {
+ 	int preamble_mask;
+ 	u32 reg;
+@@ -301,11 +360,13 @@ static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+ 	/*
+ 	 * When short preamble is enabled, we should set bit 0x08
+ 	 */
+-	preamble_mask = short_preamble << 3;
++	preamble_mask = erp->short_preamble << 3;
+ 
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+-	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, ack_timeout);
+-	rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, ack_consume_time);
++	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT,
++			   erp->ack_timeout);
++	rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME,
++			   erp->ack_consume_time);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+ 
+ 	rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+@@ -425,6 +486,13 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	u8 r14;
+ 	u8 r2;
+ 
++	/*
++	 * We should never come here because rt2x00lib is supposed
++	 * to catch this and send us the correct antenna explicitely.
++	 */
++	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++	       ant->tx == ANTENNA_SW_DIVERSITY);
++
+ 	rt2x00pci_register_read(rt2x00dev, BBPCSR1, &reg);
+ 	rt2500pci_bbp_read(rt2x00dev, 14, &r14);
+ 	rt2500pci_bbp_read(rt2x00dev, 2, &r2);
+@@ -438,15 +506,8 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 		rt2x00_set_field32(&reg, BBPCSR1_CCK, 0);
+ 		rt2x00_set_field32(&reg, BBPCSR1_OFDM, 0);
+ 		break;
+-	case ANTENNA_HW_DIVERSITY:
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
+ 		rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
+ 		rt2x00_set_field32(&reg, BBPCSR1_OFDM, 2);
+@@ -460,15 +521,8 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	case ANTENNA_A:
+ 		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
+ 		break;
+-	case ANTENNA_HW_DIVERSITY:
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
+ 		break;
+ 	}
+@@ -530,8 +584,8 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
+-			     const unsigned int flags,
+-			     struct rt2x00lib_conf *libconf)
++			     struct rt2x00lib_conf *libconf,
++			     const unsigned int flags)
+ {
+ 	if (flags & CONFIG_UPDATE_PHYMODE)
+ 		rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates);
+@@ -548,34 +602,6 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ /*
+- * LED functions.
+- */
+-static void rt2500pci_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	u32 reg;
+-
+-	rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
+-
+-	rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
+-	rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
+-	rt2x00_set_field32(&reg, LEDCSR_LINK,
+-			   (rt2x00dev->led_mode != LED_MODE_ASUS));
+-	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY,
+-			   (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
+-	rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
+-}
+-
+-static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	u32 reg;
+-
+-	rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
+-	rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
+-	rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
+-	rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
+-}
+-
+-/*
+  * Link tuning
+  */
+ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -610,9 +636,10 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * To prevent collisions with MAC ASIC on chipsets
+ 	 * up to version C the link tuning should halt after 20
+-	 * seconds.
++	 * seconds while being associated.
+ 	 */
+ 	if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
++	    rt2x00dev->intf_associated &&
+ 	    rt2x00dev->link.count > 20)
+ 		return;
+ 
+@@ -620,9 +647,12 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 
+ 	/*
+ 	 * Chipset versions C and lower should directly continue
+-	 * to the dynamic CCA tuning.
++	 * to the dynamic CCA tuning. Chipset version D and higher
++	 * should go straight to dynamic CCA tuning when they
++	 * are not associated.
+ 	 */
+-	if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D)
++	if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D ||
++	    !rt2x00dev->intf_associated)
+ 		goto dynamic_cca_tune;
+ 
+ 	/*
+@@ -684,82 +714,84 @@ dynamic_cca_tune:
+  * Initialization functions.
+  */
+ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+-				   struct data_entry *entry)
++				   struct queue_entry *entry)
+ {
+-	__le32 *rxd = entry->priv;
++	struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ 	u32 word;
+ 
+-	rt2x00_desc_read(rxd, 1, &word);
+-	rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+-	rt2x00_desc_write(rxd, 1, word);
++	rt2x00_desc_read(priv_rx->desc, 1, &word);
++	rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
++	rt2x00_desc_write(priv_rx->desc, 1, word);
+ 
+-	rt2x00_desc_read(rxd, 0, &word);
++	rt2x00_desc_read(priv_rx->desc, 0, &word);
+ 	rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+-	rt2x00_desc_write(rxd, 0, word);
++	rt2x00_desc_write(priv_rx->desc, 0, word);
+ }
+ 
+ static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+-				   struct data_entry *entry)
++				   struct queue_entry *entry)
+ {
+-	__le32 *txd = entry->priv;
++	struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
+ 	u32 word;
+ 
+-	rt2x00_desc_read(txd, 1, &word);
+-	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+-	rt2x00_desc_write(txd, 1, word);
++	rt2x00_desc_read(priv_tx->desc, 1, &word);
++	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
++	rt2x00_desc_write(priv_tx->desc, 1, word);
+ 
+-	rt2x00_desc_read(txd, 0, &word);
++	rt2x00_desc_read(priv_tx->desc, 0, &word);
+ 	rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ 	rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+-	rt2x00_desc_write(txd, 0, word);
++	rt2x00_desc_write(priv_tx->desc, 0, word);
+ }
+ 
+-static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev)
++static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
+ {
++	struct queue_entry_priv_pci_rx *priv_rx;
++	struct queue_entry_priv_pci_tx *priv_tx;
+ 	u32 reg;
+ 
+ 	/*
+ 	 * Initialize registers.
+ 	 */
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
+-	rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
+-	rt2x00_set_field32(&reg, TXCSR2_NUM_TXD,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
+-	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM,
+-			   rt2x00dev->bcn[1].stats.limit);
+-	rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
++	rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
++	rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
++	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
++	rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
+ 
++	priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
+ 	rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
+ 
++	priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
+ 	rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
+ 
++	priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
+ 	rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
+-			   rt2x00dev->bcn[1].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
+ 
++	priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
+ 	rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
+-			   rt2x00dev->bcn[0].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
+ 
+ 	rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
+ 	rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
+-	rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
++	rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
+ 	rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
+ 
++	priv_rx = rt2x00dev->rx->entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
+-	rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
+-			   rt2x00dev->rx->data_dma);
++	rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
+ 
+ 	return 0;
+@@ -947,19 +979,15 @@ continue_csr_init:
+ 	rt2500pci_bbp_write(rt2x00dev, 61, 0x6d);
+ 	rt2500pci_bbp_write(rt2x00dev, 62, 0x10);
+ 
+-	DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ 		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ 
+ 		if (eeprom != 0xffff && eeprom != 0x0000) {
+ 			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ 			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+-			DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+-			      reg_id, value);
+ 			rt2500pci_bbp_write(rt2x00dev, reg_id, value);
+ 		}
+ 	}
+-	DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+ 
+ 	return 0;
+ }
+@@ -1011,7 +1039,7 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Initialize all registers.
+ 	 */
+-	if (rt2500pci_init_rings(rt2x00dev) ||
++	if (rt2500pci_init_queues(rt2x00dev) ||
+ 	    rt2500pci_init_registers(rt2x00dev) ||
+ 	    rt2500pci_init_bbp(rt2x00dev)) {
+ 		ERROR(rt2x00dev, "Register initialization failed.\n");
+@@ -1023,11 +1051,6 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ 	 */
+ 	rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
+ 
+-	/*
+-	 * Enable LED
+-	 */
+-	rt2500pci_enable_led(rt2x00dev);
+-
+ 	return 0;
+ }
+ 
+@@ -1035,11 +1058,6 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+ 	u32 reg;
+ 
+-	/*
+-	 * Disable LED
+-	 */
+-	rt2500pci_disable_led(rt2x00dev);
+-
+ 	rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
+ 
+ 	/*
+@@ -1138,10 +1156,10 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+  */
+ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 				    struct sk_buff *skb,
+-				    struct txdata_entry_desc *desc,
++				    struct txentry_desc *txdesc,
+ 				    struct ieee80211_tx_control *control)
+ {
+-	struct skb_desc *skbdesc = get_skb_desc(skb);
++	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ 	__le32 *txd = skbdesc->desc;
+ 	u32 word;
+ 
+@@ -1150,36 +1168,36 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 	 */
+ 	rt2x00_desc_read(txd, 2, &word);
+ 	rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
+-	rt2x00_set_field32(&word, TXD_W2_AIFS, desc->aifs);
+-	rt2x00_set_field32(&word, TXD_W2_CWMIN, desc->cw_min);
+-	rt2x00_set_field32(&word, TXD_W2_CWMAX, desc->cw_max);
++	rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs);
++	rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min);
++	rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max);
+ 	rt2x00_desc_write(txd, 2, word);
+ 
+ 	rt2x00_desc_read(txd, 3, &word);
+-	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
+-	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
+-	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, desc->length_low);
+-	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, desc->length_high);
++	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
++	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
++	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low);
++	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high);
+ 	rt2x00_desc_write(txd, 3, word);
+ 
+ 	rt2x00_desc_read(txd, 10, &word);
+ 	rt2x00_set_field32(&word, TXD_W10_RTS,
+-			   test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags));
++			   test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
+ 	rt2x00_desc_write(txd, 10, word);
+ 
+ 	rt2x00_desc_read(txd, 0, &word);
+ 	rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
+ 	rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+ 	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+-			   test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_ACK,
+-			   test_bit(ENTRY_TXD_ACK, &desc->flags));
++			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+-			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_OFDM,
+-			   test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
++			   test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
+-	rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+ 			   !!(control->flags &
+ 			      IEEE80211_TXCTL_LONG_RETRY_LIMIT));
+@@ -1192,13 +1210,15 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+  * TX data initialization
+  */
+ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+-				    unsigned int queue)
++				    const unsigned int queue)
+ {
+ 	u32 reg;
+ 
+-	if (queue == IEEE80211_TX_QUEUE_BEACON) {
++	if (queue == RT2X00_BCN_QUEUE_BEACON) {
+ 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ 		if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
++			rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
++			rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+ 			rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+ 			rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ 		}
+@@ -1211,53 +1231,63 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ 	rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
+ 			   (queue == IEEE80211_TX_QUEUE_DATA1));
+ 	rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
+-			   (queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
++			   (queue == RT2X00_BCN_QUEUE_ATIM));
+ 	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ }
+ 
+ /*
+  * RX control handlers
+  */
+-static void rt2500pci_fill_rxdone(struct data_entry *entry,
+-				  struct rxdata_entry_desc *desc)
++static void rt2500pci_fill_rxdone(struct queue_entry *entry,
++				  struct rxdone_entry_desc *rxdesc)
+ {
+-	__le32 *rxd = entry->priv;
++	struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ 	u32 word0;
+ 	u32 word2;
+ 
+-	rt2x00_desc_read(rxd, 0, &word0);
+-	rt2x00_desc_read(rxd, 2, &word2);
++	rt2x00_desc_read(priv_rx->desc, 0, &word0);
++	rt2x00_desc_read(priv_rx->desc, 2, &word2);
+ 
+-	desc->flags = 0;
++	rxdesc->flags = 0;
+ 	if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+-		desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ 	if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+-		desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+-
+-	desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
+-	desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
+-	    entry->ring->rt2x00dev->rssi_offset;
+-	desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+-	desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+-	desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++		rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
++
++	/*
++	 * Obtain the status about this packet.
++	 * When frame was received with an OFDM bitrate,
++	 * the signal is the PLCP value. If it was received with
++	 * a CCK bitrate the signal is the rate in 100kbit/s.
++	 */
++	rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
++	rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
++	    entry->queue->rt2x00dev->rssi_offset;
++	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++	rxdesc->dev_flags = 0;
++	if (rt2x00_get_field32(word0, RXD_W0_OFDM))
++		rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
++	if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++		rxdesc->dev_flags |= RXDONE_MY_BSS;
+ }
+ 
+ /*
+  * Interrupt functions.
+  */
+-static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
++static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
++			     const enum ieee80211_tx_queue queue_idx)
+ {
+-	struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
+-	struct data_entry *entry;
+-	__le32 *txd;
++	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
++	struct queue_entry_priv_pci_tx *priv_tx;
++	struct queue_entry *entry;
++	struct txdone_entry_desc txdesc;
+ 	u32 word;
+-	int tx_status;
+-	int retry;
+ 
+-	while (!rt2x00_ring_empty(ring)) {
+-		entry = rt2x00_get_data_entry_done(ring);
+-		txd = entry->priv;
+-		rt2x00_desc_read(txd, 0, &word);
++	while (!rt2x00queue_empty(queue)) {
++		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
++		priv_tx = entry->priv_data;
++		rt2x00_desc_read(priv_tx->desc, 0, &word);
+ 
+ 		if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ 		    !rt2x00_get_field32(word, TXD_W0_VALID))
+@@ -1266,10 +1296,10 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
+ 		/*
+ 		 * Obtain the status about this packet.
+ 		 */
+-		tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
+-		retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
++		txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
++		txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
+ 
+-		rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
++		rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
+ 	}
+ }
+ 
+@@ -1313,7 +1343,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
+ 	 * 3 - Atim ring transmit done interrupt.
+ 	 */
+ 	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
+-		rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
++		rt2500pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
+ 
+ 	/*
+ 	 * 4 - Priority ring transmit done interrupt.
+@@ -1442,8 +1472,27 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Store led mode, for correct led behaviour.
+ 	 */
+-	rt2x00dev->led_mode =
+-	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++#ifdef CONFIG_RT2500PCI_LEDS
++	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++
++	rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++	rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++	rt2x00dev->led_radio.led_dev.brightness_set =
++	    rt2500pci_brightness_set;
++	rt2x00dev->led_radio.led_dev.blink_set =
++	    rt2500pci_blink_set;
++	rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++	if (value == LED_MODE_TXRX_ACTIVITY) {
++		rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++		rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
++		rt2x00dev->led_qual.led_dev.brightness_set =
++		    rt2500pci_brightness_set;
++		rt2x00dev->led_qual.led_dev.blink_set =
++		    rt2500pci_blink_set;
++		rt2x00dev->led_qual.flags = LED_INITIALIZED;
++	}
++#endif /* CONFIG_RT2500PCI_LEDS */
+ 
+ 	/*
+ 	 * Detect if this device has an hardware controlled radio.
+@@ -1656,8 +1705,8 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Initialize hw_mode information.
+ 	 */
+-	spec->num_modes = 2;
+-	spec->num_rates = 12;
++	spec->supported_bands = SUPPORT_BAND_2GHZ;
++	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+ 	spec->tx_power_a = NULL;
+ 	spec->tx_power_bg = txpower;
+ 	spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -1678,9 +1727,9 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
+ 		spec->channels = rf_vals_bg_2525e;
+ 	} else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
++		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ 		spec->num_channels = ARRAY_SIZE(rf_vals_5222);
+ 		spec->channels = rf_vals_5222;
+-		spec->num_modes = 3;
+ 	}
+ }
+ 
+@@ -1705,9 +1754,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ 	rt2500pci_probe_hw_mode(rt2x00dev);
+ 
+ 	/*
+-	 * This device requires the beacon ring
++	 * This device requires the atim queue
+ 	 */
+-	__set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
++	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
+ 
+ 	/*
+ 	 * Set the rssi offset.
+@@ -1720,69 +1769,6 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+  * IEEE80211 stack callback functions.
+  */
+-static void rt2500pci_configure_filter(struct ieee80211_hw *hw,
+-				       unsigned int changed_flags,
+-				       unsigned int *total_flags,
+-				       int mc_count,
+-				       struct dev_addr_list *mc_list)
+-{
+-	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	u32 reg;
+-
+-	/*
+-	 * Mask off any flags we are going to ignore from
+-	 * the total_flags field.
+-	 */
+-	*total_flags &=
+-	    FIF_ALLMULTI |
+-	    FIF_FCSFAIL |
+-	    FIF_PLCPFAIL |
+-	    FIF_CONTROL |
+-	    FIF_OTHER_BSS |
+-	    FIF_PROMISC_IN_BSS;
+-
+-	/*
+-	 * Apply some rules to the filters:
+-	 * - Some filters imply different filters to be set.
+-	 * - Some things we can't filter out at all.
+-	 */
+-	if (mc_count)
+-		*total_flags |= FIF_ALLMULTI;
+-	if (*total_flags & FIF_OTHER_BSS ||
+-	    *total_flags & FIF_PROMISC_IN_BSS)
+-		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+-	/*
+-	 * Check if there is any work left for us.
+-	 */
+-	if (rt2x00dev->packet_filter == *total_flags)
+-		return;
+-	rt2x00dev->packet_filter = *total_flags;
+-
+-	/*
+-	 * Start configuration steps.
+-	 * Note that the version error will always be dropped
+-	 * and broadcast frames will always be accepted since
+-	 * there is no filter for it at this time.
+-	 */
+-	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
+-			   !(*total_flags & FIF_FCSFAIL));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
+-			   !(*total_flags & FIF_PLCPFAIL));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
+-			   !(*total_flags & FIF_CONTROL));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
+-			   !(*total_flags & FIF_ALLMULTI));
+-	rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
+-	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+-}
+-
+ static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw,
+ 				     u32 short_retry, u32 long_retry)
+ {
+@@ -1811,12 +1797,59 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
+ 	return tsf;
+ }
+ 
+-static void rt2500pci_reset_tsf(struct ieee80211_hw *hw)
++static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
++				   struct ieee80211_tx_control *control)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
++	struct rt2x00_intf *intf = vif_to_intf(control->vif);
++	struct queue_entry_priv_pci_tx *priv_tx;
++	struct skb_frame_desc *skbdesc;
++	u32 reg;
+ 
+-	rt2x00pci_register_write(rt2x00dev, CSR16, 0);
+-	rt2x00pci_register_write(rt2x00dev, CSR17, 0);
++	if (unlikely(!intf->beacon))
++		return -ENOBUFS;
++
++	priv_tx = intf->beacon->priv_data;
++
++	/*
++	 * Fill in skb descriptor
++	 */
++	skbdesc = get_skb_frame_desc(skb);
++	memset(skbdesc, 0, sizeof(*skbdesc));
++	skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++	skbdesc->data = skb->data;
++	skbdesc->data_len = skb->len;
++	skbdesc->desc = priv_tx->desc;
++	skbdesc->desc_len = intf->beacon->queue->desc_size;
++	skbdesc->entry = intf->beacon;
++
++	/*
++	 * Disable beaconing while we are reloading the beacon data,
++	 * otherwise we might be sending out invalid data.
++	 */
++	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
++	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
++	rt2x00_set_field32(&reg, CSR14_TBCN, 0);
++	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
++	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++
++	/*
++	 * mac80211 doesn't provide the control->queue variable
++	 * for beacons. Set our own queue identification so
++	 * it can be used during descriptor initialization.
++	 */
++	control->queue = RT2X00_BCN_QUEUE_BEACON;
++	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
++
++	/*
++	 * Enable beacon generation.
++	 * Write entire beacon with descriptor to register,
++	 * and kick the beacon generator.
++	 */
++	memcpy(priv_tx->data, skb->data, skb->len);
++	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
++
++	return 0;
+ }
+ 
+ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
+@@ -1836,15 +1869,14 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
+ 	.remove_interface	= rt2x00mac_remove_interface,
+ 	.config			= rt2x00mac_config,
+ 	.config_interface	= rt2x00mac_config_interface,
+-	.configure_filter	= rt2500pci_configure_filter,
++	.configure_filter	= rt2x00mac_configure_filter,
+ 	.get_stats		= rt2x00mac_get_stats,
+ 	.set_retry_limit	= rt2500pci_set_retry_limit,
+ 	.bss_info_changed	= rt2x00mac_bss_info_changed,
+ 	.conf_tx		= rt2x00mac_conf_tx,
+ 	.get_tx_stats		= rt2x00mac_get_tx_stats,
+ 	.get_tsf		= rt2500pci_get_tsf,
+-	.reset_tsf		= rt2500pci_reset_tsf,
+-	.beacon_update		= rt2x00pci_beacon_update,
++	.beacon_update		= rt2500pci_beacon_update,
+ 	.tx_last_beacon		= rt2500pci_tx_last_beacon,
+ };
+ 
+@@ -1864,19 +1896,50 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
+ 	.write_tx_data		= rt2x00pci_write_tx_data,
+ 	.kick_tx_queue		= rt2500pci_kick_tx_queue,
+ 	.fill_rxdone		= rt2500pci_fill_rxdone,
+-	.config_mac_addr	= rt2500pci_config_mac_addr,
+-	.config_bssid		= rt2500pci_config_bssid,
+-	.config_type		= rt2500pci_config_type,
+-	.config_preamble	= rt2500pci_config_preamble,
++	.config_filter		= rt2500pci_config_filter,
++	.config_intf		= rt2500pci_config_intf,
++	.config_erp		= rt2500pci_config_erp,
+ 	.config			= rt2500pci_config,
+ };
+ 
++static const struct data_queue_desc rt2500pci_queue_rx = {
++	.entry_num		= RX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= RXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_rx),
++};
++
++static const struct data_queue_desc rt2500pci_queue_tx = {
++	.entry_num		= TX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt2500pci_queue_bcn = {
++	.entry_num		= BEACON_ENTRIES,
++	.data_size		= MGMT_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt2500pci_queue_atim = {
++	.entry_num		= ATIM_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_tx),
++};
++
+ static const struct rt2x00_ops rt2500pci_ops = {
+ 	.name		= KBUILD_MODNAME,
+-	.rxd_size	= RXD_DESC_SIZE,
+-	.txd_size	= TXD_DESC_SIZE,
++	.max_sta_intf	= 1,
++	.max_ap_intf	= 1,
+ 	.eeprom_size	= EEPROM_SIZE,
+ 	.rf_size	= RF_SIZE,
++	.rx		= &rt2500pci_queue_rx,
++	.tx		= &rt2500pci_queue_tx,
++	.bcn		= &rt2500pci_queue_bcn,
++	.atim		= &rt2500pci_queue_atim,
+ 	.lib		= &rt2500pci_rt2x00_ops,
+ 	.hw		= &rt2500pci_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h
+index 92ba090..1389955 100644
+--- a/drivers/net/wireless/rt2x00/rt2500pci.h
++++ b/drivers/net/wireless/rt2x00/rt2500pci.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -1213,8 +1213,8 @@
+ #define RXD_W10_DROP			FIELD32(0x00000001)
+ 
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+  */
+ #define MIN_TXPOWER	0
+ #define MAX_TXPOWER	31
+diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
+index 638c3d2..6bb07b3 100644
+--- a/drivers/net/wireless/rt2x00/rt2500usb.c
++++ b/drivers/net/wireless/rt2x00/rt2500usb.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -282,97 +282,136 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = {
+ };
+ #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+ 
+-/*
+- * Configuration handlers.
+- */
+-static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev,
+-				      __le32 *mac)
++#ifdef CONFIG_RT2500USB_LEDS
++static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
++				     enum led_brightness brightness)
+ {
+-	rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
+-				      (3 * sizeof(__le16)));
+-}
++	struct rt2x00_led *led =
++	    container_of(led_cdev, struct rt2x00_led, led_dev);
++	unsigned int enabled = brightness != LED_OFF;
++	u16 reg;
+ 
+-static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev,
+-				   __le32 *bssid)
+-{
+-	rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, bssid,
+-				      (3 * sizeof(__le16)));
++	rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, &reg);
++
++	if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
++		rt2x00_set_field16(&reg, MAC_CSR20_LINK, enabled);
++	else if (led->type == LED_TYPE_ACTIVITY)
++		rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, enabled);
++
++	rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg);
+ }
+ 
+-static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+-				  const int tsf_sync)
++static int rt2500usb_blink_set(struct led_classdev *led_cdev,
++			       unsigned long *delay_on,
++			       unsigned long *delay_off)
+ {
++	struct rt2x00_led *led =
++	    container_of(led_cdev, struct rt2x00_led, led_dev);
+ 	u16 reg;
+ 
+-	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
++	rt2500usb_register_read(led->rt2x00dev, MAC_CSR21, &reg);
++	rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, *delay_on);
++	rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, *delay_off);
++	rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg);
+ 
+-	/*
+-	 * Enable beacon config
+-	 */
+-	rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
+-	rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET,
+-			   (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6);
+-	if (type == IEEE80211_IF_TYPE_STA)
+-		rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 0);
+-	else
+-		rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 2);
+-	rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
++	return 0;
++}
++#endif /* CONFIG_RT2500USB_LEDS */
++
++/*
++ * Configuration handlers.
++ */
++static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
++				    const unsigned int filter_flags)
++{
++	u16 reg;
+ 
+ 	/*
+-	 * Enable synchronisation.
++	 * Start configuration steps.
++	 * Note that the version error will always be dropped
++	 * and broadcast frames will always be accepted since
++	 * there is no filter for it at this time.
+ 	 */
+-	rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+-	rt2x00_set_field16(&reg, TXRX_CSR18_OFFSET, 0);
+-	rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
+-
+-	rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+-	rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
+-	rt2x00_set_field16(&reg, TXRX_CSR19_TBCN,
+-			   (tsf_sync == TSF_SYNC_BEACON));
+-	rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
+-	rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, tsf_sync);
+-	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
++	rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
++	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
++			   !(filter_flags & FIF_FCSFAIL));
++	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
++			   !(filter_flags & FIF_PLCPFAIL));
++	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
++			   !(filter_flags & FIF_CONTROL));
++	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
++			   !(filter_flags & FIF_PROMISC_IN_BSS));
++	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
++			   !(filter_flags & FIF_PROMISC_IN_BSS) &&
++			   !rt2x00dev->intf_ap_count);
++	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
++	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
++			   !(filter_flags & FIF_ALLMULTI));
++	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
++	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+ }
+ 
+-static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
+-				      const int short_preamble,
+-				      const int ack_timeout,
+-				      const int ack_consume_time)
++static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
++				  struct rt2x00_intf *intf,
++				  struct rt2x00intf_conf *conf,
++				  const unsigned int flags)
+ {
++	unsigned int bcn_preload;
+ 	u16 reg;
+ 
+-	/*
+-	 * When in atomic context, reschedule and let rt2x00lib
+-	 * call this function again.
+-	 */
+-	if (in_atomic()) {
+-		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
+-		return;
++	if (flags & CONFIG_UPDATE_TYPE) {
++		/*
++		 * Enable beacon config
++		 */
++		bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
++		rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
++		rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
++		rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
++				   2 * (conf->type != IEEE80211_IF_TYPE_STA));
++		rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
++
++		/*
++		 * Enable synchronisation.
++		 */
++		rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
++		rt2x00_set_field16(&reg, TXRX_CSR18_OFFSET, 0);
++		rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
++
++		rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
++		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
++		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
++		rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
++		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+ 	}
+ 
++	if (flags & CONFIG_UPDATE_MAC)
++		rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac,
++					      (3 * sizeof(__le16)));
++
++	if (flags & CONFIG_UPDATE_BSSID)
++		rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid,
++					      (3 * sizeof(__le16)));
++}
++
++static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
++				 struct rt2x00lib_erp *erp)
++{
++	u16 reg;
++
+ 	rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
+-	rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, ack_timeout);
++	rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout);
+ 	rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
+ 
+ 	rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
+ 	rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
+-			   !!short_preamble);
++			   !!erp->short_preamble);
+ 	rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
+ }
+ 
+ static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
+-				     const int phymode,
+ 				     const int basic_rate_mask)
+ {
+ 	rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask);
+-
+-	if (phymode == HWMODE_B) {
+-		rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b);
+-		rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040);
+-	} else {
+-		rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0005);
+-		rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x016c);
+-	}
+ }
+ 
+ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
+@@ -424,6 +463,13 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	u16 csr5;
+ 	u16 csr6;
+ 
++	/*
++	 * We should never come here because rt2x00lib is supposed
++	 * to catch this and send us the correct antenna explicitely.
++	 */
++	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++	       ant->tx == ANTENNA_SW_DIVERSITY);
++
+ 	rt2500usb_bbp_read(rt2x00dev, 2, &r2);
+ 	rt2500usb_bbp_read(rt2x00dev, 14, &r14);
+ 	rt2500usb_register_read(rt2x00dev, PHY_CSR5, &csr5);
+@@ -443,14 +489,8 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 		rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0);
+ 		rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0);
+ 		break;
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
+ 		rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2);
+ 		rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2);
+@@ -467,14 +507,8 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	case ANTENNA_A:
+ 		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
+ 		break;
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
+ 		break;
+ 	}
+@@ -510,6 +544,8 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
+ 	u16 reg;
+ 
+ 	rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time);
++	rt2500usb_register_write(rt2x00dev, MAC_CSR11, libconf->sifs);
++	rt2500usb_register_write(rt2x00dev, MAC_CSR12, libconf->eifs);
+ 
+ 	rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+ 	rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
+@@ -518,12 +554,11 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
+-			     const unsigned int flags,
+-			     struct rt2x00lib_conf *libconf)
++			     struct rt2x00lib_conf *libconf,
++			     const unsigned int flags)
+ {
+ 	if (flags & CONFIG_UPDATE_PHYMODE)
+-		rt2500usb_config_phymode(rt2x00dev, libconf->phymode,
+-					 libconf->basic_rates);
++		rt2500usb_config_phymode(rt2x00dev, libconf->basic_rates);
+ 	if (flags & CONFIG_UPDATE_CHANNEL)
+ 		rt2500usb_config_channel(rt2x00dev, &libconf->rf,
+ 					 libconf->conf->power_level);
+@@ -537,36 +572,6 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ /*
+- * LED functions.
+- */
+-static void rt2500usb_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	u16 reg;
+-
+-	rt2500usb_register_read(rt2x00dev, MAC_CSR21, &reg);
+-	rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, 70);
+-	rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, 30);
+-	rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg);
+-
+-	rt2500usb_register_read(rt2x00dev, MAC_CSR20, &reg);
+-	rt2x00_set_field16(&reg, MAC_CSR20_LINK,
+-			   (rt2x00dev->led_mode != LED_MODE_ASUS));
+-	rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY,
+-			   (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
+-	rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
+-}
+-
+-static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	u16 reg;
+-
+-	rt2500usb_register_read(rt2x00dev, MAC_CSR20, &reg);
+-	rt2x00_set_field16(&reg, MAC_CSR20_LINK, 0);
+-	rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 0);
+-	rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
+-}
+-
+-/*
+  * Link tuning
+  */
+ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -626,6 +631,24 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 	u8 low_bound;
+ 
+ 	/*
++	 * Read current r17 value, as well as the sensitivity values
++	 * for the r17 register.
++	 */
++	rt2500usb_bbp_read(rt2x00dev, 17, &r17);
++	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
++
++	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
++	up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
++	low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER);
++
++	/*
++	 * If we are not associated, we should go straight to the
++	 * dynamic CCA tuning.
++	 */
++	if (!rt2x00dev->intf_associated)
++		goto dynamic_cca_tune;
++
++	/*
+ 	 * Determine the BBP tuning threshold and correctly
+ 	 * set BBP 24, 25 and 61.
+ 	 */
+@@ -651,13 +674,6 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 	rt2500usb_bbp_write(rt2x00dev, 61, r61);
+ 
+ 	/*
+-	 * Read current r17 value, as well as the sensitivity values
+-	 * for the r17 register.
+-	 */
+-	rt2500usb_bbp_read(rt2x00dev, 17, &r17);
+-	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
+-
+-	/*
+ 	 * A too low RSSI will cause too much false CCA which will
+ 	 * then corrupt the R17 tuning. To remidy this the tuning should
+ 	 * be stopped (While making sure the R17 value will not exceed limits)
+@@ -692,14 +708,9 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 	 * Leave short or middle distance condition, restore r17
+ 	 * to the dynamic tuning range.
+ 	 */
+-	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
+-	vgc_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
+-
+ 	low_bound = 0x32;
+-	if (rssi >= -77)
+-		up_bound = vgc_bound;
+-	else
+-		up_bound = vgc_bound - (-77 - rssi);
++	if (rssi < -77)
++		up_bound -= (-77 - rssi);
+ 
+ 	if (up_bound < low_bound)
+ 		up_bound = low_bound;
+@@ -707,7 +718,16 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 	if (r17 > up_bound) {
+ 		rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
+ 		rt2x00dev->link.vgc_level = up_bound;
+-	} else if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
++		return;
++	}
++
++dynamic_cca_tune:
++
++	/*
++	 * R17 is inside the dynamic tuning range,
++	 * start tuning the link based on the false cca counter.
++	 */
++	if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
+ 		rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
+ 		rt2x00dev->link.vgc_level = r17;
+ 	} else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
+@@ -878,19 +898,15 @@ continue_csr_init:
+ 	rt2500usb_bbp_write(rt2x00dev, 62, 0x10);
+ 	rt2500usb_bbp_write(rt2x00dev, 75, 0xff);
+ 
+-	DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ 		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ 
+ 		if (eeprom != 0xffff && eeprom != 0x0000) {
+ 			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ 			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+-			DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+-			      reg_id, value);
+ 			rt2500usb_bbp_write(rt2x00dev, reg_id, value);
+ 		}
+ 	}
+-	DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+ 
+ 	return 0;
+ }
+@@ -920,21 +936,11 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
+ 		return -EIO;
+ 	}
+ 
+-	/*
+-	 * Enable LED
+-	 */
+-	rt2500usb_enable_led(rt2x00dev);
+-
+ 	return 0;
+ }
+ 
+ static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+-	/*
+-	 * Disable LED
+-	 */
+-	rt2500usb_disable_led(rt2x00dev);
+-
+ 	rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121);
+ 	rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121);
+ 
+@@ -1027,10 +1033,10 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
+  */
+ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 				    struct sk_buff *skb,
+-				    struct txdata_entry_desc *desc,
++				    struct txentry_desc *txdesc,
+ 				    struct ieee80211_tx_control *control)
+ {
+-	struct skb_desc *skbdesc = get_skb_desc(skb);
++	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ 	__le32 *txd = skbdesc->desc;
+ 	u32 word;
+ 
+@@ -1039,31 +1045,31 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 	 */
+ 	rt2x00_desc_read(txd, 1, &word);
+ 	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+-	rt2x00_set_field32(&word, TXD_W1_AIFS, desc->aifs);
+-	rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
+-	rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
++	rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
++	rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
++	rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
+ 	rt2x00_desc_write(txd, 1, word);
+ 
+ 	rt2x00_desc_read(txd, 2, &word);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+ 	rt2x00_desc_write(txd, 2, word);
+ 
+ 	rt2x00_desc_read(txd, 0, &word);
+ 	rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, control->retry_limit);
+ 	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+-			   test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_ACK,
+-			   test_bit(ENTRY_TXD_ACK, &desc->flags));
++			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+-			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_OFDM,
+-			   test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
++			   test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
+ 			   !!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT));
+-	rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ 	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
+ 	rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
+ 	rt2x00_desc_write(txd, 0, word);
+@@ -1088,15 +1094,17 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
+  * TX data initialization
+  */
+ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+-				    unsigned int queue)
++				    const unsigned int queue)
+ {
+ 	u16 reg;
+ 
+-	if (queue != IEEE80211_TX_QUEUE_BEACON)
++	if (queue != RT2X00_BCN_QUEUE_BEACON)
+ 		return;
+ 
+ 	rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+ 	if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) {
++		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
++		rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
+ 		rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
+ 		/*
+ 		 * Beacon generation will fail initially.
+@@ -1114,42 +1122,68 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ /*
+  * RX control handlers
+  */
+-static void rt2500usb_fill_rxdone(struct data_entry *entry,
+-				  struct rxdata_entry_desc *desc)
++static void rt2500usb_fill_rxdone(struct queue_entry *entry,
++				  struct rxdone_entry_desc *rxdesc)
+ {
+-	struct skb_desc *skbdesc = get_skb_desc(entry->skb);
+-	struct urb *urb = entry->priv;
+-	__le32 *rxd = (__le32 *)(entry->skb->data +
+-				 (urb->actual_length - entry->ring->desc_size));
++	struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data;
++	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
++	__le32 *rxd =
++	    (__le32 *)(entry->skb->data +
++		       (priv_rx->urb->actual_length - entry->queue->desc_size));
++	unsigned int offset = entry->queue->desc_size + 2;
+ 	u32 word0;
+ 	u32 word1;
+ 
++	/*
++	 * Copy descriptor to the available headroom inside the skbuffer.
++	 */
++	skb_push(entry->skb, offset);
++	memcpy(entry->skb->data, rxd, entry->queue->desc_size);
++	rxd = (__le32 *)entry->skb->data;
++
++	/*
++	 * The descriptor is now aligned to 4 bytes and thus it is
++	 * now safe to read it on all architectures.
++	 */
+ 	rt2x00_desc_read(rxd, 0, &word0);
+ 	rt2x00_desc_read(rxd, 1, &word1);
+ 
+-	desc->flags = 0;
++	rxdesc->flags = 0;
+ 	if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+-		desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ 	if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+-		desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
++		rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+ 
+ 	/*
+ 	 * Obtain the status about this packet.
++	 * When frame was received with an OFDM bitrate,
++	 * the signal is the PLCP value. If it was received with
++	 * a CCK bitrate the signal is the rate in 100kbit/s.
++	 */
++	rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
++	rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
++	    entry->queue->rt2x00dev->rssi_offset;
++	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++	rxdesc->dev_flags = 0;
++	if (rt2x00_get_field32(word0, RXD_W0_OFDM))
++		rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
++	if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++		rxdesc->dev_flags |= RXDONE_MY_BSS;
++
++	/*
++	 * Adjust the skb memory window to the frame boundaries.
+ 	 */
+-	desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+-	desc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
+-	    entry->ring->rt2x00dev->rssi_offset;
+-	desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+-	desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+-	desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++	skb_pull(entry->skb, offset);
++	skb_trim(entry->skb, rxdesc->size);
+ 
+ 	/*
+ 	 * Set descriptor and data pointer.
+ 	 */
+-	skbdesc->desc = entry->skb->data + desc->size;
+-	skbdesc->desc_len = entry->ring->desc_size;
+ 	skbdesc->data = entry->skb->data;
+-	skbdesc->data_len = desc->size;
++	skbdesc->data_len = rxdesc->size;
++	skbdesc->desc = rxd;
++	skbdesc->desc_len = entry->queue->desc_size;
+ }
+ 
+ /*
+@@ -1157,10 +1191,10 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry,
+  */
+ static void rt2500usb_beacondone(struct urb *urb)
+ {
+-	struct data_entry *entry = (struct data_entry *)urb->context;
+-	struct data_ring *ring = entry->ring;
++	struct queue_entry *entry = (struct queue_entry *)urb->context;
++	struct queue_entry_priv_usb_bcn *priv_bcn = entry->priv_data;
+ 
+-	if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags))
++	if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
+ 		return;
+ 
+ 	/*
+@@ -1169,18 +1203,11 @@ static void rt2500usb_beacondone(struct urb *urb)
+ 	 * Otherwise we should free the sk_buffer, the device
+ 	 * should be doing the rest of the work now.
+ 	 */
+-	if (ring->index == 1) {
+-		rt2x00_ring_index_done_inc(ring);
+-		entry = rt2x00_get_data_entry(ring);
+-		usb_submit_urb(entry->priv, GFP_ATOMIC);
+-		rt2x00_ring_index_inc(ring);
+-	} else if (ring->index_done == 1) {
+-		entry = rt2x00_get_data_entry_done(ring);
+-		if (entry->skb) {
+-			dev_kfree_skb(entry->skb);
+-			entry->skb = NULL;
+-		}
+-		rt2x00_ring_index_done_inc(ring);
++	if (priv_bcn->guardian_urb == urb) {
++		usb_submit_urb(priv_bcn->urb, GFP_ATOMIC);
++	} else if (priv_bcn->urb == urb) {
++		dev_kfree_skb(entry->skb);
++		entry->skb = NULL;
+ 	}
+ }
+ 
+@@ -1191,6 +1218,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ {
+ 	u16 word;
+ 	u8 *mac;
++	u8 bbp;
+ 
+ 	rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
+ 
+@@ -1245,9 +1273,17 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ 		EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word);
+ 	}
+ 
++	/*
++	 * Switch lower vgc bound to current BBP R17 value,
++	 * lower the value a bit for better quality.
++	 */
++	rt2500usb_bbp_read(rt2x00dev, 17, &bbp);
++	bbp -= 6;
++
+ 	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word);
+ 	if (word == 0xffff) {
+ 		rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
++		rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
+ 		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
+ 		EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
+ 	}
+@@ -1258,6 +1294,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ 		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
+ 		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
+ 		EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
++	} else {
++		rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
++		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
+ 	}
+ 
+ 	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
+@@ -1342,8 +1381,27 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Store led mode, for correct led behaviour.
+ 	 */
+-	rt2x00dev->led_mode =
+-	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++#ifdef CONFIG_RT2500USB_LEDS
++	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++
++	rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++	rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++	rt2x00dev->led_radio.led_dev.brightness_set =
++	    rt2500usb_brightness_set;
++	rt2x00dev->led_radio.led_dev.blink_set =
++	    rt2500usb_blink_set;
++	rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++	if (value == LED_MODE_TXRX_ACTIVITY) {
++		rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++		rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
++		rt2x00dev->led_qual.led_dev.brightness_set =
++		    rt2500usb_brightness_set;
++		rt2x00dev->led_qual.led_dev.blink_set =
++		    rt2500usb_blink_set;
++		rt2x00dev->led_qual.flags = LED_INITIALIZED;
++	}
++#endif /* CONFIG_RT2500USB_LEDS */
+ 
+ 	/*
+ 	 * Check if the BBP tuning should be disabled.
+@@ -1550,8 +1608,8 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Initialize hw_mode information.
+ 	 */
+-	spec->num_modes = 2;
+-	spec->num_rates = 12;
++	spec->supported_bands = SUPPORT_BAND_2GHZ;
++	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+ 	spec->tx_power_a = NULL;
+ 	spec->tx_power_bg = txpower;
+ 	spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -1572,9 +1630,9 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
+ 		spec->channels = rf_vals_bg_2525e;
+ 	} else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
++		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ 		spec->num_channels = ARRAY_SIZE(rf_vals_5222);
+ 		spec->channels = rf_vals_5222;
+-		spec->num_modes = 3;
+ 	}
+ }
+ 
+@@ -1599,9 +1657,11 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+ 	rt2500usb_probe_hw_mode(rt2x00dev);
+ 
+ 	/*
+-	 * This device requires the beacon ring
++	 * This device requires the atim queue
+ 	 */
+-	__set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
++	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
++	__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
++	__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+ 
+ 	/*
+ 	 * Set the rssi offset.
+@@ -1614,125 +1674,58 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+  * IEEE80211 stack callback functions.
+  */
+-static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
+-				       unsigned int changed_flags,
+-				       unsigned int *total_flags,
+-				       int mc_count,
+-				       struct dev_addr_list *mc_list)
+-{
+-	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	u16 reg;
+-
+-	/*
+-	 * Mask off any flags we are going to ignore from
+-	 * the total_flags field.
+-	 */
+-	*total_flags &=
+-	    FIF_ALLMULTI |
+-	    FIF_FCSFAIL |
+-	    FIF_PLCPFAIL |
+-	    FIF_CONTROL |
+-	    FIF_OTHER_BSS |
+-	    FIF_PROMISC_IN_BSS;
+-
+-	/*
+-	 * Apply some rules to the filters:
+-	 * - Some filters imply different filters to be set.
+-	 * - Some things we can't filter out at all.
+-	 */
+-	if (mc_count)
+-		*total_flags |= FIF_ALLMULTI;
+-	if (*total_flags & FIF_OTHER_BSS ||
+-	    *total_flags & FIF_PROMISC_IN_BSS)
+-		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+-	/*
+-	 * Check if there is any work left for us.
+-	 */
+-	if (rt2x00dev->packet_filter == *total_flags)
+-		return;
+-	rt2x00dev->packet_filter = *total_flags;
+-
+-	/*
+-	 * When in atomic context, reschedule and let rt2x00lib
+-	 * call this function again.
+-	 */
+-	if (in_atomic()) {
+-		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+-		return;
+-	}
+-
+-	/*
+-	 * Start configuration steps.
+-	 * Note that the version error will always be dropped
+-	 * and broadcast frames will always be accepted since
+-	 * there is no filter for it at this time.
+-	 */
+-	rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+-	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
+-			   !(*total_flags & FIF_FCSFAIL));
+-	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
+-			   !(*total_flags & FIF_PLCPFAIL));
+-	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
+-			   !(*total_flags & FIF_CONTROL));
+-	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
+-	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
+-			   !(*total_flags & FIF_ALLMULTI));
+-	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
+-	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+-}
+-
+ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
+ 				   struct sk_buff *skb,
+ 				   struct ieee80211_tx_control *control)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	struct usb_device *usb_dev =
+-	    interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+-	struct skb_desc *desc;
+-	struct data_ring *ring;
+-	struct data_entry *beacon;
+-	struct data_entry *guardian;
++	struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
++	struct rt2x00_intf *intf = vif_to_intf(control->vif);
++	struct queue_entry_priv_usb_bcn *priv_bcn;
++	struct skb_frame_desc *skbdesc;
+ 	int pipe = usb_sndbulkpipe(usb_dev, 1);
+ 	int length;
++	u16 reg;
++
++	if (unlikely(!intf->beacon))
++		return -ENOBUFS;
++
++	priv_bcn = intf->beacon->priv_data;
+ 
+ 	/*
+-	 * Just in case the ieee80211 doesn't set this,
+-	 * but we need this queue set for the descriptor
+-	 * initialization.
++	 * Add the descriptor in front of the skb.
+ 	 */
+-	control->queue = IEEE80211_TX_QUEUE_BEACON;
+-	ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
++	skb_push(skb, intf->beacon->queue->desc_size);
++	memset(skb->data, 0, intf->beacon->queue->desc_size);
+ 
+ 	/*
+-	 * Obtain 2 entries, one for the guardian byte,
+-	 * the second for the actual beacon.
++	 * Fill in skb descriptor
+ 	 */
+-	guardian = rt2x00_get_data_entry(ring);
+-	rt2x00_ring_index_inc(ring);
+-	beacon = rt2x00_get_data_entry(ring);
++	skbdesc = get_skb_frame_desc(skb);
++	memset(skbdesc, 0, sizeof(*skbdesc));
++	skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++	skbdesc->data = skb->data + intf->beacon->queue->desc_size;
++	skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
++	skbdesc->desc = skb->data;
++	skbdesc->desc_len = intf->beacon->queue->desc_size;
++	skbdesc->entry = intf->beacon;
+ 
+ 	/*
+-	 * Add the descriptor in front of the skb.
++	 * Disable beaconing while we are reloading the beacon data,
++	 * otherwise we might be sending out invalid data.
+ 	 */
+-	skb_push(skb, ring->desc_size);
+-	memset(skb->data, 0, ring->desc_size);
++	rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
++	rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
++	rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
++	rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
++	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+ 
+ 	/*
+-	 * Fill in skb descriptor
++	 * mac80211 doesn't provide the control->queue variable
++	 * for beacons. Set our own queue identification so
++	 * it can be used during descriptor initialization.
+ 	 */
+-	desc = get_skb_desc(skb);
+-	desc->desc_len = ring->desc_size;
+-	desc->data_len = skb->len - ring->desc_size;
+-	desc->desc = skb->data;
+-	desc->data = skb->data + ring->desc_size;
+-	desc->ring = ring;
+-	desc->entry = beacon;
+-
++	control->queue = RT2X00_BCN_QUEUE_BEACON;
+ 	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+ 
+ 	/*
+@@ -1742,27 +1735,29 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
+ 	 */
+ 	length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
+ 
+-	usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
+-			  skb->data, length, rt2500usb_beacondone, beacon);
++	usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe,
++			  skb->data, length, rt2500usb_beacondone,
++			  intf->beacon);
+ 
+ 	/*
+ 	 * Second we need to create the guardian byte.
+ 	 * We only need a single byte, so lets recycle
+ 	 * the 'flags' field we are not using for beacons.
+ 	 */
+-	guardian->flags = 0;
+-	usb_fill_bulk_urb(guardian->priv, usb_dev, pipe,
+-			  &guardian->flags, 1, rt2500usb_beacondone, guardian);
++	priv_bcn->guardian_data = 0;
++	usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe,
++			  &priv_bcn->guardian_data, 1, rt2500usb_beacondone,
++			  intf->beacon);
+ 
+ 	/*
+ 	 * Send out the guardian byte.
+ 	 */
+-	usb_submit_urb(guardian->priv, GFP_ATOMIC);
++	usb_submit_urb(priv_bcn->guardian_urb, GFP_ATOMIC);
+ 
+ 	/*
+ 	 * Enable beacon generation.
+ 	 */
+-	rt2500usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
++	rt2500usb_kick_tx_queue(rt2x00dev, control->queue);
+ 
+ 	return 0;
+ }
+@@ -1775,7 +1770,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
+ 	.remove_interface	= rt2x00mac_remove_interface,
+ 	.config			= rt2x00mac_config,
+ 	.config_interface	= rt2x00mac_config_interface,
+-	.configure_filter	= rt2500usb_configure_filter,
++	.configure_filter	= rt2x00mac_configure_filter,
+ 	.get_stats		= rt2x00mac_get_stats,
+ 	.bss_info_changed	= rt2x00mac_bss_info_changed,
+ 	.conf_tx		= rt2x00mac_conf_tx,
+@@ -1798,19 +1793,50 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
+ 	.get_tx_data_len	= rt2500usb_get_tx_data_len,
+ 	.kick_tx_queue		= rt2500usb_kick_tx_queue,
+ 	.fill_rxdone		= rt2500usb_fill_rxdone,
+-	.config_mac_addr	= rt2500usb_config_mac_addr,
+-	.config_bssid		= rt2500usb_config_bssid,
+-	.config_type		= rt2500usb_config_type,
+-	.config_preamble	= rt2500usb_config_preamble,
++	.config_filter		= rt2500usb_config_filter,
++	.config_intf		= rt2500usb_config_intf,
++	.config_erp		= rt2500usb_config_erp,
+ 	.config			= rt2500usb_config,
+ };
+ 
++static const struct data_queue_desc rt2500usb_queue_rx = {
++	.entry_num		= RX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= RXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_usb_rx),
++};
++
++static const struct data_queue_desc rt2500usb_queue_tx = {
++	.entry_num		= TX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_usb_tx),
++};
++
++static const struct data_queue_desc rt2500usb_queue_bcn = {
++	.entry_num		= BEACON_ENTRIES,
++	.data_size		= MGMT_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_usb_bcn),
++};
++
++static const struct data_queue_desc rt2500usb_queue_atim = {
++	.entry_num		= ATIM_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_usb_tx),
++};
++
+ static const struct rt2x00_ops rt2500usb_ops = {
+ 	.name		= KBUILD_MODNAME,
+-	.rxd_size	= RXD_DESC_SIZE,
+-	.txd_size	= TXD_DESC_SIZE,
++	.max_sta_intf	= 1,
++	.max_ap_intf	= 1,
+ 	.eeprom_size	= EEPROM_SIZE,
+ 	.rf_size	= RF_SIZE,
++	.rx		= &rt2500usb_queue_rx,
++	.tx		= &rt2500usb_queue_tx,
++	.bcn		= &rt2500usb_queue_bcn,
++	.atim		= &rt2500usb_queue_atim,
+ 	.lib		= &rt2500usb_rt2x00_ops,
+ 	.hw		= &rt2500usb_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
+index 9e04337..a37a068 100644
+--- a/drivers/net/wireless/rt2x00/rt2500usb.h
++++ b/drivers/net/wireless/rt2x00/rt2500usb.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -135,7 +135,7 @@
+  * Misc MAC_CSR registers.
+  * MAC_CSR9: Timer control.
+  * MAC_CSR10: Slot time.
+- * MAC_CSR11: IFS.
++ * MAC_CSR11: SIFS.
+  * MAC_CSR12: EIFS.
+  * MAC_CSR13: Power mode0.
+  * MAC_CSR14: Power mode1.
+@@ -686,6 +686,7 @@
+  */
+ #define EEPROM_BBPTUNE_VGC		0x0034
+ #define EEPROM_BBPTUNE_VGCUPPER		FIELD16(0x00ff)
++#define EEPROM_BBPTUNE_VGCLOWER		FIELD16(0xff00)
+ 
+ /*
+  * EEPROM BBP R17 Tuning.
+@@ -786,8 +787,8 @@
+ #define RXD_W3_EIV			FIELD32(0xffffffff)
+ 
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+  */
+ #define MIN_TXPOWER	0
+ #define MAX_TXPOWER	31
+diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
+index 6c72542..57bdc15 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -27,23 +27,24 @@
+ #define RT2X00_H
+ 
+ #include <linux/bitops.h>
+-#include <linux/prefetch.h>
+ #include <linux/skbuff.h>
+ #include <linux/workqueue.h>
+ #include <linux/firmware.h>
++#include <linux/leds.h>
+ #include <linux/mutex.h>
+ #include <linux/etherdevice.h>
+ 
+ #include <net/mac80211.h>
+ 
+ #include "rt2x00debug.h"
++#include "rt2x00leds.h"
+ #include "rt2x00reg.h"
+-#include "rt2x00ring.h"
++#include "rt2x00queue.h"
+ 
+ /*
+  * Module information.
+  */
+-#define DRV_VERSION	"2.0.14"
++#define DRV_VERSION	"2.1.4"
+ #define DRV_PROJECT	"http://rt2x00.serialmonkey.com"
+ 
+ /*
+@@ -91,26 +92,6 @@
+ 	DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args)
+ 
+ /*
+- * Ring sizes.
+- * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes.
+- * DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings.
+- * MGMT_FRAME_SIZE is used for the BEACON ring.
+- */
+-#define DATA_FRAME_SIZE	2432
+-#define MGMT_FRAME_SIZE	256
+-
+-/*
+- * Number of entries in a packet ring.
+- * PCI devices only need 1 Beacon entry,
+- * but USB devices require a second because they
+- * have to send a Guardian byte first.
+- */
+-#define RX_ENTRIES	12
+-#define TX_ENTRIES	12
+-#define ATIM_ENTRIES	1
+-#define BEACON_ENTRIES	2
+-
+-/*
+  * Standard timing and size defines.
+  * These values should follow the ieee80211 specifications.
+  */
+@@ -364,20 +345,22 @@ static inline int rt2x00_update_ant_rssi(struct link *link, int rssi)
+ 
+ /*
+  * Interface structure
+- * Configuration details about the current interface.
++ * Per interface configuration details, this structure
++ * is allocated as the private data for ieee80211_vif.
+  */
+-struct interface {
++struct rt2x00_intf {
+ 	/*
+-	 * Interface identification. The value is assigned
+-	 * to us by the 80211 stack, and is used to request
+-	 * new beacons.
++	 * All fields within the rt2x00_intf structure
++	 * must be protected with a spinlock.
+ 	 */
+-	struct ieee80211_vif *id;
++	spinlock_t lock;
+ 
+ 	/*
+-	 * Current working type (IEEE80211_IF_TYPE_*).
++	 * BSS configuration. Copied from the structure
++	 * passed to us through the bss_info_changed()
++	 * callback funtion.
+ 	 */
+-	int type;
++	struct ieee80211_bss_conf conf;
+ 
+ 	/*
+ 	 * MAC of the device.
+@@ -388,42 +371,60 @@ struct interface {
+ 	 * BBSID of the AP to associate with.
+ 	 */
+ 	u8 bssid[ETH_ALEN];
+-};
+ 
+-static inline int is_interface_present(struct interface *intf)
+-{
+-	return !!intf->id;
+-}
++	/*
++	 * Entry in the beacon queue which belongs to
++	 * this interface. Each interface has its own
++	 * dedicated beacon entry.
++	 */
++	struct queue_entry *beacon;
++
++	/*
++	 * Actions that needed rescheduling.
++	 */
++	unsigned int delayed_flags;
++#define DELAYED_UPDATE_BEACON		0x00000001
++#define DELAYED_CONFIG_ERP		0x00000002
++#define DELAYED_LED_ASSOC		0x00000004
++};
+ 
+-static inline int is_interface_type(struct interface *intf, int type)
++static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
+ {
+-	return intf->type == type;
++	return (struct rt2x00_intf *)vif->drv_priv;
+ }
+ 
+-/*
++/**
++ * struct hw_mode_spec: Hardware specifications structure
++ *
+  * Details about the supported modes, rates and channels
+  * of a particular chipset. This is used by rt2x00lib
+  * to build the ieee80211_hw_mode array for mac80211.
++ *
++ * @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz).
++ * @supported_rates: Rate types which are supported (CCK, OFDM).
++ * @num_channels: Number of supported channels. This is used as array size
++ *	for @tx_power_a, @tx_power_bg and @channels.
++ * channels: Device/chipset specific channel values (See &struct rf_channel).
++ * @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
++ * @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
++ * @tx_power_default: Default TX power value to use when either
++ *	@tx_power_a or @tx_power_bg is missing.
+  */
+ struct hw_mode_spec {
+-	/*
+-	 * Number of modes, rates and channels.
+-	 */
+-	int num_modes;
+-	int num_rates;
+-	int num_channels;
++	unsigned int supported_bands;
++#define SUPPORT_BAND_2GHZ	0x00000001
++#define SUPPORT_BAND_5GHZ	0x00000002
++
++	unsigned int supported_rates;
++#define SUPPORT_RATE_CCK	0x00000001
++#define SUPPORT_RATE_OFDM	0x00000002
++
++	unsigned int num_channels;
++	const struct rf_channel *channels;
+ 
+-	/*
+-	 * txpower values.
+-	 */
+ 	const u8 *tx_power_a;
+ 	const u8 *tx_power_bg;
+ 	u8 tx_power_default;
+-
+-	/*
+-	 * Device/chipset specific value.
+-	 */
+-	const struct rf_channel *channels;
+ };
+ 
+ /*
+@@ -439,10 +440,10 @@ struct rt2x00lib_conf {
+ 
+ 	struct antenna_setup ant;
+ 
+-	int phymode;
++	enum ieee80211_band band;
+ 
+-	int basic_rates;
+-	int slot_time;
++	u32 basic_rates;
++	u32 slot_time;
+ 
+ 	short sifs;
+ 	short pifs;
+@@ -451,6 +452,47 @@ struct rt2x00lib_conf {
+ };
+ 
+ /*
++ * Configuration structure for erp settings.
++ */
++struct rt2x00lib_erp {
++	int short_preamble;
++
++	int ack_timeout;
++	int ack_consume_time;
++};
++
++/*
++ * Configuration structure wrapper around the
++ * rt2x00 interface configuration handler.
++ */
++struct rt2x00intf_conf {
++	/*
++	 * Interface type
++	 */
++	enum ieee80211_if_types type;
++
++	/*
++	 * TSF sync value, this is dependant on the operation type.
++	 */
++	enum tsf_sync sync;
++
++	/*
++	 * The MAC and BSSID addressess are simple array of bytes,
++	 * these arrays are little endian, so when sending the addressess
++	 * to the drivers, copy the it into a endian-signed variable.
++	 *
++	 * Note that all devices (except rt2500usb) have 32 bits
++	 * register word sizes. This means that whatever variable we
++	 * pass _must_ be a multiple of 32 bits. Otherwise the device
++	 * might not accept what we are sending to it.
++	 * This will also make it easier for the driver to write
++	 * the data to the device.
++	 */
++	__le32 mac[2];
++	__le32 bssid[2];
++};
++
++/*
+  * rt2x00lib callback functions.
+  */
+ struct rt2x00lib_ops {
+@@ -464,6 +506,7 @@ struct rt2x00lib_ops {
+ 	 */
+ 	int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
+ 	char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev);
++	u16 (*get_firmware_crc) (void *data, const size_t len);
+ 	int (*load_firmware) (struct rt2x00_dev *rt2x00dev, void *data,
+ 			      const size_t len);
+ 
+@@ -474,12 +517,12 @@ struct rt2x00lib_ops {
+ 	void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
+ 
+ 	/*
+-	 * Ring initialization handlers
++	 * queue initialization handlers
+ 	 */
+ 	void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
+-			      struct data_entry *entry);
++			      struct queue_entry *entry);
+ 	void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
+-			      struct data_entry *entry);
++			      struct queue_entry *entry);
+ 
+ 	/*
+ 	 * Radio control handlers.
+@@ -497,35 +540,40 @@ struct rt2x00lib_ops {
+ 	 */
+ 	void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
+ 			       struct sk_buff *skb,
+-			       struct txdata_entry_desc *desc,
++			       struct txentry_desc *txdesc,
+ 			       struct ieee80211_tx_control *control);
+ 	int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
+-			      struct data_ring *ring, struct sk_buff *skb,
++			      struct data_queue *queue, struct sk_buff *skb,
+ 			      struct ieee80211_tx_control *control);
+ 	int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
+ 				struct sk_buff *skb);
+ 	void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
+-			       unsigned int queue);
++			       const unsigned int queue);
+ 
+ 	/*
+ 	 * RX control handlers
+ 	 */
+-	void (*fill_rxdone) (struct data_entry *entry,
+-			     struct rxdata_entry_desc *desc);
++	void (*fill_rxdone) (struct queue_entry *entry,
++			     struct rxdone_entry_desc *rxdesc);
+ 
+ 	/*
+ 	 * Configuration handlers.
+ 	 */
+-	void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac);
+-	void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid);
+-	void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type,
+-							   const int tsf_sync);
+-	void (*config_preamble) (struct rt2x00_dev *rt2x00dev,
+-				 const int short_preamble,
+-				 const int ack_timeout,
+-				 const int ack_consume_time);
+-	void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags,
+-			struct rt2x00lib_conf *libconf);
++	void (*config_filter) (struct rt2x00_dev *rt2x00dev,
++			       const unsigned int filter_flags);
++	void (*config_intf) (struct rt2x00_dev *rt2x00dev,
++			     struct rt2x00_intf *intf,
++			     struct rt2x00intf_conf *conf,
++			     const unsigned int flags);
++#define CONFIG_UPDATE_TYPE		( 1 << 1 )
++#define CONFIG_UPDATE_MAC		( 1 << 2 )
++#define CONFIG_UPDATE_BSSID		( 1 << 3 )
++
++	void (*config_erp) (struct rt2x00_dev *rt2x00dev,
++			    struct rt2x00lib_erp *erp);
++	void (*config) (struct rt2x00_dev *rt2x00dev,
++			struct rt2x00lib_conf *libconf,
++			const unsigned int flags);
+ #define CONFIG_UPDATE_PHYMODE		( 1 << 1 )
+ #define CONFIG_UPDATE_CHANNEL		( 1 << 2 )
+ #define CONFIG_UPDATE_TXPOWER		( 1 << 3 )
+@@ -540,10 +588,14 @@ struct rt2x00lib_ops {
+  */
+ struct rt2x00_ops {
+ 	const char *name;
+-	const unsigned int rxd_size;
+-	const unsigned int txd_size;
++	const unsigned int max_sta_intf;
++	const unsigned int max_ap_intf;
+ 	const unsigned int eeprom_size;
+ 	const unsigned int rf_size;
++	const struct data_queue_desc *rx;
++	const struct data_queue_desc *tx;
++	const struct data_queue_desc *bcn;
++	const struct data_queue_desc *atim;
+ 	const struct rt2x00lib_ops *lib;
+ 	const struct ieee80211_ops *hw;
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+@@ -569,8 +621,11 @@ enum rt2x00_flags {
+ 	/*
+ 	 * Driver features
+ 	 */
++	DRIVER_SUPPORT_MIXED_INTERFACES,
+ 	DRIVER_REQUIRE_FIRMWARE,
+-	DRIVER_REQUIRE_BEACON_RING,
++	DRIVER_REQUIRE_BEACON_GUARD,
++	DRIVER_REQUIRE_ATIM_QUEUE,
++	DRIVER_REQUIRE_SCHEDULED,
+ 
+ 	/*
+ 	 * Driver configuration
+@@ -582,7 +637,6 @@ enum rt2x00_flags {
+ 	CONFIG_EXTERNAL_LNA_BG,
+ 	CONFIG_DOUBLE_ANTENNA,
+ 	CONFIG_DISABLE_LINK_TUNING,
+-	CONFIG_SHORT_PREAMBLE,
+ };
+ 
+ /*
+@@ -597,8 +651,10 @@ struct rt2x00_dev {
+ 	 * macro's should be used for correct typecasting.
+ 	 */
+ 	void *dev;
+-#define rt2x00dev_pci(__dev)	( (struct pci_dev*)(__dev)->dev )
+-#define rt2x00dev_usb(__dev)	( (struct usb_interface*)(__dev)->dev )
++#define rt2x00dev_pci(__dev)	( (struct pci_dev *)(__dev)->dev )
++#define rt2x00dev_usb(__dev)	( (struct usb_interface *)(__dev)->dev )
++#define rt2x00dev_usb_dev(__dev)\
++	( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) )
+ 
+ 	/*
+ 	 * Callback functions.
+@@ -609,18 +665,15 @@ struct rt2x00_dev {
+ 	 * IEEE80211 control structure.
+ 	 */
+ 	struct ieee80211_hw *hw;
+-	struct ieee80211_hw_mode *hwmodes;
+-	unsigned int curr_hwmode;
+-#define HWMODE_B	0
+-#define HWMODE_G	1
+-#define HWMODE_A	2
++	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
++	enum ieee80211_band curr_band;
+ 
+ 	/*
+ 	 * rfkill structure for RF state switching support.
+ 	 * This will only be compiled in when required.
+ 	 */
+ #ifdef CONFIG_RT2X00_LIB_RFKILL
+-unsigned long rfkill_state;
++	unsigned long rfkill_state;
+ #define RFKILL_STATE_ALLOCATED		1
+ #define RFKILL_STATE_REGISTERED		2
+ 	struct rfkill *rfkill;
+@@ -636,6 +689,17 @@ unsigned long rfkill_state;
+ #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+ 
+ 	/*
++	 * LED structure for changing the LED status
++	 * by mac8011 or the kernel.
++	 */
++#ifdef CONFIG_RT2X00_LIB_LEDS
++	struct rt2x00_led led_radio;
++	struct rt2x00_led led_assoc;
++	struct rt2x00_led led_qual;
++	u16 led_mcu_reg;
++#endif /* CONFIG_RT2X00_LIB_LEDS */
++
++	/*
+ 	 * Device flags.
+ 	 * In these flags the current status and some
+ 	 * of the device capabilities are stored.
+@@ -661,11 +725,13 @@ unsigned long rfkill_state;
+ 
+ 	/*
+ 	 * Register pointers
+-	 * csr_addr: Base register address. (PCI)
+-	 * csr_cache: CSR cache for usb_control_msg. (USB)
++	 * csr.base: CSR base register address. (PCI)
++	 * csr.cache: CSR cache for usb_control_msg. (USB)
+ 	 */
+-	void __iomem *csr_addr;
+-	void *csr_cache;
++	union csr {
++		void __iomem *base;
++		void *cache;
++	} csr;
+ 
+ 	/*
+ 	 * Mutex to protect register accesses on USB devices.
+@@ -687,9 +753,14 @@ unsigned long rfkill_state;
+ 	unsigned int packet_filter;
+ 
+ 	/*
+-	 * Interface configuration.
++	 * Interface details:
++	 *  - Open ap interface count.
++	 *  - Open sta interface count.
++	 *  - Association count.
+ 	 */
+-	struct interface interface;
++	unsigned int intf_ap_count;
++	unsigned int intf_sta_count;
++	unsigned int intf_associated;
+ 
+ 	/*
+ 	 * Link quality
+@@ -722,16 +793,6 @@ unsigned long rfkill_state;
+ 	u16 tx_power;
+ 
+ 	/*
+-	 * LED register (for rt61pci & rt73usb).
+-	 */
+-	u16 led_reg;
+-
+-	/*
+-	 * Led mode (LED_MODE_*)
+-	 */
+-	u8 led_mode;
+-
+-	/*
+ 	 * Rssi <-> Dbm offset
+ 	 */
+ 	u8 rssi_offset;
+@@ -755,19 +816,18 @@ unsigned long rfkill_state;
+ 	/*
+ 	 * Scheduled work.
+ 	 */
+-	struct work_struct beacon_work;
++	struct work_struct intf_work;
+ 	struct work_struct filter_work;
+-	struct work_struct config_work;
+ 
+ 	/*
+-	 * Data ring arrays for RX, TX and Beacon.
+-	 * The Beacon array also contains the Atim ring
++	 * Data queue arrays for RX, TX and Beacon.
++	 * The Beacon array also contains the Atim queue
+ 	 * if that is supported by the device.
+ 	 */
+-	int data_rings;
+-	struct data_ring *rx;
+-	struct data_ring *tx;
+-	struct data_ring *bcn;
++	int data_queues;
++	struct data_queue *rx;
++	struct data_queue *tx;
++	struct data_queue *bcn;
+ 
+ 	/*
+ 	 * Firmware image.
+@@ -776,37 +836,6 @@ unsigned long rfkill_state;
+ };
+ 
+ /*
+- * For-each loop for the ring array.
+- * All rings have been allocated as a single array,
+- * this means we can create a very simply loop macro
+- * that is capable of looping through all rings.
+- * ring_end(), txring_end() and ring_loop() are helper macro's which
+- * should not be used directly. Instead the following should be used:
+- * ring_for_each() - Loops through all rings (RX, TX, Beacon & Atim)
+- * txring_for_each() - Loops through TX data rings (TX only)
+- * txringall_for_each() - Loops through all TX rings (TX, Beacon & Atim)
+- */
+-#define ring_end(__dev) \
+-	&(__dev)->rx[(__dev)->data_rings]
+-
+-#define txring_end(__dev) \
+-	&(__dev)->tx[(__dev)->hw->queues]
+-
+-#define ring_loop(__entry, __start, __end)			\
+-	for ((__entry) = (__start);				\
+-	     prefetch(&(__entry)[1]), (__entry) != (__end);	\
+-	     (__entry) = &(__entry)[1])
+-
+-#define ring_for_each(__dev, __entry) \
+-	ring_loop(__entry, (__dev)->rx, ring_end(__dev))
+-
+-#define txring_for_each(__dev, __entry) \
+-	ring_loop(__entry, (__dev)->tx, txring_end(__dev))
+-
+-#define txringall_for_each(__dev, __entry) \
+-	ring_loop(__entry, (__dev)->tx, ring_end(__dev))
+-
+-/*
+  * Generic RF access.
+  * The RF is being accessed by word index.
+  */
+@@ -898,20 +927,43 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate)
+ 	return ((size * 8 * 10) % rate);
+ }
+ 
+-/*
+- * Library functions.
++/**
++ * rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue
++ * @rt2x00dev: Pointer to &struct rt2x00_dev.
++ * @queue: mac80211/rt2x00 queue index
++ *	(see &enum ieee80211_tx_queue and &enum rt2x00_bcn_queue).
++ */
++struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
++					 const unsigned int queue);
++
++/**
++ * rt2x00queue_get_entry - Get queue entry where the given index points to.
++ * @rt2x00dev: Pointer to &struct rt2x00_dev.
++ * @index: Index identifier for obtaining the correct index.
++ */
++struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
++					  enum queue_index index);
++
++/**
++ * rt2x00queue_index_inc - Index incrementation function
++ * @queue: Queue (&struct data_queue) to perform the action on.
++ * @action: Index type (&enum queue_index) to perform the action on.
++ *
++ * This function will increase the requested index on the queue,
++ * it will grab the appropriate locks and handle queue overflow events by
++ * resetting the index to the start of the queue.
+  */
+-struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
+-				     const unsigned int queue);
++void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
++
+ 
+ /*
+  * Interrupt context handlers.
+  */
+ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
+-void rt2x00lib_txdone(struct data_entry *entry,
+-		      const int status, const int retry);
+-void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
+-		      struct rxdata_entry_desc *desc);
++void rt2x00lib_txdone(struct queue_entry *entry,
++		      struct txdone_entry_desc *txdesc);
++void rt2x00lib_rxdone(struct queue_entry *entry,
++		      struct rxdone_entry_desc *rxdesc);
+ 
+ /*
+  * TX descriptor initializer
+@@ -935,6 +987,10 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ 			       struct ieee80211_vif *vif,
+ 			       struct ieee80211_if_conf *conf);
++void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
++				unsigned int changed_flags,
++				unsigned int *total_flags,
++				int mc_count, struct dev_addr_list *mc_list);
+ int rt2x00mac_get_stats(struct ieee80211_hw *hw,
+ 			struct ieee80211_low_level_stats *stats);
+ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
+diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
+index 07adc57..a9930a0 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00config.c
++++ b/drivers/net/wireless/rt2x00/rt2x00config.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -29,64 +29,78 @@
+ #include "rt2x00.h"
+ #include "rt2x00lib.h"
+ 
+-
+-/*
+- * The MAC and BSSID addressess are simple array of bytes,
+- * these arrays are little endian, so when sending the addressess
+- * to the drivers, copy the it into a endian-signed variable.
+- *
+- * Note that all devices (except rt2500usb) have 32 bits
+- * register word sizes. This means that whatever variable we
+- * pass _must_ be a multiple of 32 bits. Otherwise the device
+- * might not accept what we are sending to it.
+- * This will also make it easier for the driver to write
+- * the data to the device.
+- *
+- * Also note that when NULL is passed as address the
+- * we will send 00:00:00:00:00 to the device to clear the address.
+- * This will prevent the device being confused when it wants
+- * to ACK frames or consideres itself associated.
+- */
+-void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac)
+-{
+-	__le32 reg[2];
+-
+-	memset(&reg, 0, sizeof(reg));
+-	if (mac)
+-		memcpy(&reg, mac, ETH_ALEN);
+-
+-	rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, &reg[0]);
+-}
+-
+-void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
++void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
++			   struct rt2x00_intf *intf,
++			   enum ieee80211_if_types type,
++			   u8 *mac, u8 *bssid)
+ {
+-	__le32 reg[2];
++	struct rt2x00intf_conf conf;
++	unsigned int flags = 0;
+ 
+-	memset(&reg, 0, sizeof(reg));
+-	if (bssid)
+-		memcpy(&reg, bssid, ETH_ALEN);
+-
+-	rt2x00dev->ops->lib->config_bssid(rt2x00dev, &reg[0]);
+-}
+-
+-void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type)
+-{
+-	int tsf_sync;
++	conf.type = type;
+ 
+ 	switch (type) {
+ 	case IEEE80211_IF_TYPE_IBSS:
+ 	case IEEE80211_IF_TYPE_AP:
+-		tsf_sync = TSF_SYNC_BEACON;
++		conf.sync = TSF_SYNC_BEACON;
+ 		break;
+ 	case IEEE80211_IF_TYPE_STA:
+-		tsf_sync = TSF_SYNC_INFRA;
++		conf.sync = TSF_SYNC_INFRA;
+ 		break;
+ 	default:
+-		tsf_sync = TSF_SYNC_NONE;
++		conf.sync = TSF_SYNC_NONE;
+ 		break;
+ 	}
+ 
+-	rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync);
++	/*
++	 * Note that when NULL is passed as address we will send
++	 * 00:00:00:00:00 to the device to clear the address.
++	 * This will prevent the device being confused when it wants
++	 * to ACK frames or consideres itself associated.
++	 */
++	memset(&conf.mac, 0, sizeof(conf.mac));
++	if (mac)
++		memcpy(&conf.mac, mac, ETH_ALEN);
++
++	memset(&conf.bssid, 0, sizeof(conf.bssid));
++	if (bssid)
++		memcpy(&conf.bssid, bssid, ETH_ALEN);
++
++	flags |= CONFIG_UPDATE_TYPE;
++	if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
++		flags |= CONFIG_UPDATE_MAC;
++	if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
++		flags |= CONFIG_UPDATE_BSSID;
++
++	rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
++}
++
++void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
++			  struct rt2x00_intf *intf,
++			  struct ieee80211_bss_conf *bss_conf)
++{
++	struct rt2x00lib_erp erp;
++
++	memset(&erp, 0, sizeof(erp));
++
++	erp.short_preamble = bss_conf->use_short_preamble;
++	erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10);
++	erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10);
++
++	if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME)
++		erp.ack_timeout += SHORT_DIFS;
++	else
++		erp.ack_timeout += DIFS;
++
++	if (bss_conf->use_short_preamble) {
++		erp.ack_timeout += SHORT_PREAMBLE;
++		erp.ack_consume_time += SHORT_PREAMBLE;
++	} else {
++		erp.ack_timeout += PREAMBLE;
++		erp.ack_consume_time += PREAMBLE;
++	}
++
++	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
+ }
+ 
+ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+@@ -113,7 +127,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	 * The latter is required since we need to recalibrate the
+ 	 * noise-sensitivity ratio for the new setup.
+ 	 */
+-	rt2x00dev->ops->lib->config(rt2x00dev, CONFIG_UPDATE_ANTENNA, &libconf);
++	rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA);
+ 	rt2x00lib_reset_link_tuner(rt2x00dev);
+ 
+ 	rt2x00dev->link.ant.active.rx = libconf.ant.rx;
+@@ -123,12 +137,26 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
+ }
+ 
++static u32 rt2x00lib_get_basic_rates(struct ieee80211_supported_band *band)
++{
++	const struct rt2x00_rate *rate;
++	unsigned int i;
++	u32 mask = 0;
++
++	for (i = 0; i < band->n_bitrates; i++) {
++		rate = rt2x00_get_rate(band->bitrates[i].hw_value);
++		if (rate->flags & DEV_RATE_BASIC)
++			mask |= rate->ratemask;
++	}
++
++	return mask;
++}
++
+ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+ 		      struct ieee80211_conf *conf, const int force_config)
+ {
+ 	struct rt2x00lib_conf libconf;
+-	struct ieee80211_hw_mode *mode;
+-	struct ieee80211_rate *rate;
++	struct ieee80211_supported_band *band;
+ 	struct antenna_setup *default_ant = &rt2x00dev->default_ant;
+ 	struct antenna_setup *active_ant = &rt2x00dev->link.ant.active;
+ 	int flags = 0;
+@@ -147,9 +175,9 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+ 	 * Check which configuration options have been
+ 	 * updated and should be send to the device.
+ 	 */
+-	if (rt2x00dev->rx_status.phymode != conf->phymode)
++	if (rt2x00dev->rx_status.band != conf->channel->band)
+ 		flags |= CONFIG_UPDATE_PHYMODE;
+-	if (rt2x00dev->rx_status.channel != conf->channel)
++	if (rt2x00dev->rx_status.freq != conf->channel->center_freq)
+ 		flags |= CONFIG_UPDATE_CHANNEL;
+ 	if (rt2x00dev->tx_power != conf->power_level)
+ 		flags |= CONFIG_UPDATE_TXPOWER;
+@@ -204,33 +232,15 @@ config:
+ 	memset(&libconf, 0, sizeof(libconf));
+ 
+ 	if (flags & CONFIG_UPDATE_PHYMODE) {
+-		switch (conf->phymode) {
+-		case MODE_IEEE80211A:
+-			libconf.phymode = HWMODE_A;
+-			break;
+-		case MODE_IEEE80211B:
+-			libconf.phymode = HWMODE_B;
+-			break;
+-		case MODE_IEEE80211G:
+-			libconf.phymode = HWMODE_G;
+-			break;
+-		default:
+-			ERROR(rt2x00dev,
+-			      "Attempt to configure unsupported mode (%d)"
+-			      "Defaulting to 802.11b", conf->phymode);
+-			libconf.phymode = HWMODE_B;
+-		}
+-
+-		mode = &rt2x00dev->hwmodes[libconf.phymode];
+-		rate = &mode->rates[mode->num_rates - 1];
+-
+-		libconf.basic_rates =
+-		    DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK;
++		band = &rt2x00dev->bands[conf->channel->band];
++
++		libconf.band = conf->channel->band;
++		libconf.basic_rates = rt2x00lib_get_basic_rates(band);
+ 	}
+ 
+ 	if (flags & CONFIG_UPDATE_CHANNEL) {
+ 		memcpy(&libconf.rf,
+-		       &rt2x00dev->spec.channels[conf->channel_val],
++		       &rt2x00dev->spec.channels[conf->channel->hw_value],
+ 		       sizeof(libconf.rf));
+ 	}
+ 
+@@ -266,7 +276,7 @@ config:
+ 	/*
+ 	 * Start configuration.
+ 	 */
+-	rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf);
++	rt2x00dev->ops->lib->config(rt2x00dev, &libconf, flags);
+ 
+ 	/*
+ 	 * Some configuration changes affect the link quality
+@@ -276,12 +286,11 @@ config:
+ 		rt2x00lib_reset_link_tuner(rt2x00dev);
+ 
+ 	if (flags & CONFIG_UPDATE_PHYMODE) {
+-		rt2x00dev->curr_hwmode = libconf.phymode;
+-		rt2x00dev->rx_status.phymode = conf->phymode;
++		rt2x00dev->curr_band = conf->channel->band;
++		rt2x00dev->rx_status.band = conf->channel->band;
+ 	}
+ 
+-	rt2x00dev->rx_status.freq = conf->freq;
+-	rt2x00dev->rx_status.channel = conf->channel;
++	rt2x00dev->rx_status.freq = conf->channel->center_freq;
+ 	rt2x00dev->tx_power = conf->power_level;
+ 
+ 	if (flags & CONFIG_UPDATE_ANTENNA) {
+diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
+index b44a9f4..bfab3b8 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
++++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -33,7 +33,7 @@
+ #include "rt2x00lib.h"
+ #include "rt2x00dump.h"
+ 
+-#define PRINT_LINE_LEN_MAX 32
++#define MAX_LINE_LENGTH 64
+ 
+ struct rt2x00debug_intf {
+ 	/*
+@@ -60,8 +60,9 @@ struct rt2x00debug_intf {
+ 	 *     - eeprom offset/value files
+ 	 *     - bbp offset/value files
+ 	 *     - rf offset/value files
+-	 *   - frame dump folder
++	 *   - queue folder
+ 	 *     - frame dump file
++	 *     - queue stats file
+ 	 */
+ 	struct dentry *driver_folder;
+ 	struct dentry *driver_entry;
+@@ -76,8 +77,9 @@ struct rt2x00debug_intf {
+ 	struct dentry *bbp_val_entry;
+ 	struct dentry *rf_off_entry;
+ 	struct dentry *rf_val_entry;
+-	struct dentry *frame_folder;
+-	struct dentry *frame_dump_entry;
++	struct dentry *queue_folder;
++	struct dentry *queue_frame_dump_entry;
++	struct dentry *queue_stats_entry;
+ 
+ 	/*
+ 	 * The frame dump file only allows a single reader,
+@@ -116,7 +118,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+ 			    struct sk_buff *skb)
+ {
+ 	struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+-	struct skb_desc *desc = get_skb_desc(skb);
++	struct skb_frame_desc *desc = get_skb_frame_desc(skb);
+ 	struct sk_buff *skbcopy;
+ 	struct rt2x00dump_hdr *dump_hdr;
+ 	struct timeval timestamp;
+@@ -147,7 +149,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+ 	dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
+ 	dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
+ 	dump_hdr->type = cpu_to_le16(desc->frame_type);
+-	dump_hdr->ring_index = desc->ring->queue_idx;
++	dump_hdr->queue_index = desc->entry->queue->qid;
+ 	dump_hdr->entry_index = desc->entry->entry_idx;
+ 	dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
+ 	dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
+@@ -186,7 +188,7 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
+ 	return 0;
+ }
+ 
+-static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
++static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file)
+ {
+ 	struct rt2x00debug_intf *intf = inode->i_private;
+ 	int retval;
+@@ -203,7 +205,7 @@ static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
+ 	return 0;
+ }
+ 
+-static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
++static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file)
+ {
+ 	struct rt2x00debug_intf *intf = inode->i_private;
+ 
+@@ -214,10 +216,10 @@ static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
+ 	return rt2x00debug_file_release(inode, file);
+ }
+ 
+-static ssize_t rt2x00debug_read_ring_dump(struct file *file,
+-					  char __user *buf,
+-					  size_t length,
+-					  loff_t *offset)
++static ssize_t rt2x00debug_read_queue_dump(struct file *file,
++					   char __user *buf,
++					   size_t length,
++					   loff_t *offset)
+ {
+ 	struct rt2x00debug_intf *intf = file->private_data;
+ 	struct sk_buff *skb;
+@@ -248,8 +250,8 @@ exit:
+ 	return status;
+ }
+ 
+-static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
+-					       poll_table *wait)
++static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
++					        poll_table *wait)
+ {
+ 	struct rt2x00debug_intf *intf = file->private_data;
+ 
+@@ -261,12 +263,68 @@ static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
+ 	return 0;
+ }
+ 
+-static const struct file_operations rt2x00debug_fop_ring_dump = {
++static const struct file_operations rt2x00debug_fop_queue_dump = {
+ 	.owner		= THIS_MODULE,
+-	.read		= rt2x00debug_read_ring_dump,
+-	.poll		= rt2x00debug_poll_ring_dump,
+-	.open		= rt2x00debug_open_ring_dump,
+-	.release	= rt2x00debug_release_ring_dump,
++	.read		= rt2x00debug_read_queue_dump,
++	.poll		= rt2x00debug_poll_queue_dump,
++	.open		= rt2x00debug_open_queue_dump,
++	.release	= rt2x00debug_release_queue_dump,
++};
++
++static ssize_t rt2x00debug_read_queue_stats(struct file *file,
++					    char __user *buf,
++					    size_t length,
++					    loff_t *offset)
++{
++	struct rt2x00debug_intf *intf = file->private_data;
++	struct data_queue *queue;
++	unsigned long irqflags;
++	unsigned int lines = 1 + intf->rt2x00dev->data_queues;
++	size_t size;
++	char *data;
++	char *temp;
++
++	if (*offset)
++		return 0;
++
++	data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
++	temp = data +
++	    sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n");
++
++	queue_for_each(intf->rt2x00dev, queue) {
++		spin_lock_irqsave(&queue->lock, irqflags);
++
++		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]);
++
++		spin_unlock_irqrestore(&queue->lock, irqflags);
++	}
++
++	size = strlen(data);
++	size = min(size, length);
++
++	if (copy_to_user(buf, data, size)) {
++		kfree(data);
++		return -EFAULT;
++	}
++
++	kfree(data);
++
++	*offset += size;
++	return size;
++}
++
++static const struct file_operations rt2x00debug_fop_queue_stats = {
++	.owner		= THIS_MODULE,
++	.read		= rt2x00debug_read_queue_stats,
++	.open		= rt2x00debug_file_open,
++	.release	= rt2x00debug_file_release,
+ };
+ 
+ #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)	\
+@@ -386,7 +444,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,
+ {
+ 	char *data;
+ 
+-	data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
++	data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL);
+ 	if (!data)
+ 		return NULL;
+ 
+@@ -409,7 +467,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
+ 	const struct rt2x00debug *debug = intf->debug;
+ 	char *data;
+ 
+-	data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
++	data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL);
+ 	if (!data)
+ 		return NULL;
+ 
+@@ -496,20 +554,24 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
+ 
+ #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
+ 
+-	intf->frame_folder =
+-	    debugfs_create_dir("frame", intf->driver_folder);
+-	if (IS_ERR(intf->frame_folder))
++	intf->queue_folder =
++	    debugfs_create_dir("queue", intf->driver_folder);
++	if (IS_ERR(intf->queue_folder))
+ 		goto exit;
+ 
+-	intf->frame_dump_entry =
+-	    debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
+-				intf, &rt2x00debug_fop_ring_dump);
+-	if (IS_ERR(intf->frame_dump_entry))
++	intf->queue_frame_dump_entry =
++	    debugfs_create_file("dump", S_IRUGO, intf->queue_folder,
++				intf, &rt2x00debug_fop_queue_dump);
++	if (IS_ERR(intf->queue_frame_dump_entry))
+ 		goto exit;
+ 
+ 	skb_queue_head_init(&intf->frame_dump_skbqueue);
+ 	init_waitqueue_head(&intf->frame_dump_waitqueue);
+ 
++	intf->queue_stats_entry =
++	    debugfs_create_file("queue", S_IRUGO, intf->queue_folder,
++				intf, &rt2x00debug_fop_queue_stats);
++
+ 	return;
+ 
+ exit:
+@@ -528,8 +590,9 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
+ 
+ 	skb_queue_purge(&intf->frame_dump_skbqueue);
+ 
+-	debugfs_remove(intf->frame_dump_entry);
+-	debugfs_remove(intf->frame_folder);
++	debugfs_remove(intf->queue_stats_entry);
++	debugfs_remove(intf->queue_frame_dump_entry);
++	debugfs_remove(intf->queue_folder);
+ 	debugfs_remove(intf->rf_val_entry);
+ 	debugfs_remove(intf->rf_off_entry);
+ 	debugfs_remove(intf->bbp_val_entry);
+diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h
+index d37efbd..c4ce895 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00debug.h
++++ b/drivers/net/wireless/rt2x00/rt2x00debug.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
+index e873a39..f8fe7a1 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -31,34 +31,6 @@
+ #include "rt2x00dump.h"
+ 
+ /*
+- * Ring handler.
+- */
+-struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
+-				     const unsigned int queue)
+-{
+-	int beacon = test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
+-
+-	/*
+-	 * Check if we are requesting a reqular TX ring,
+-	 * or if we are requesting a Beacon or Atim ring.
+-	 * For Atim rings, we should check if it is supported.
+-	 */
+-	if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
+-		return &rt2x00dev->tx[queue];
+-
+-	if (!rt2x00dev->bcn || !beacon)
+-		return NULL;
+-
+-	if (queue == IEEE80211_TX_QUEUE_BEACON)
+-		return &rt2x00dev->bcn[0];
+-	else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
+-		return &rt2x00dev->bcn[1];
+-
+-	return NULL;
+-}
+-EXPORT_SYMBOL_GPL(rt2x00lib_get_ring);
+-
+-/*
+  * Link tuning handlers
+  */
+ void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
+@@ -113,46 +85,6 @@ static void rt2x00lib_stop_link_tuner(struct rt2x00_dev *rt2x00dev)
+ }
+ 
+ /*
+- * Ring initialization
+- */
+-static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev)
+-{
+-	struct data_ring *ring = rt2x00dev->rx;
+-	unsigned int i;
+-
+-	if (!rt2x00dev->ops->lib->init_rxentry)
+-		return;
+-
+-	if (ring->data_addr)
+-		memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+-
+-	for (i = 0; i < ring->stats.limit; i++)
+-		rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]);
+-
+-	rt2x00_ring_index_clear(ring);
+-}
+-
+-static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev)
+-{
+-	struct data_ring *ring;
+-	unsigned int i;
+-
+-	if (!rt2x00dev->ops->lib->init_txentry)
+-		return;
+-
+-	txringall_for_each(rt2x00dev, ring) {
+-		if (ring->data_addr)
+-			memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+-
+-		for (i = 0; i < ring->stats.limit; i++)
+-			rt2x00dev->ops->lib->init_txentry(rt2x00dev,
+-							  &ring->entry[i]);
+-
+-		rt2x00_ring_index_clear(ring);
+-	}
+-}
+-
+-/*
+  * Radio control handlers.
+  */
+ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
+@@ -168,19 +100,21 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
+ 		return 0;
+ 
+ 	/*
+-	 * Initialize all data rings.
++	 * Initialize all data queues.
+ 	 */
+-	rt2x00lib_init_rxrings(rt2x00dev);
+-	rt2x00lib_init_txrings(rt2x00dev);
++	rt2x00queue_init_rx(rt2x00dev);
++	rt2x00queue_init_tx(rt2x00dev);
+ 
+ 	/*
+ 	 * Enable radio.
+ 	 */
+-	status = rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+-						       STATE_RADIO_ON);
++	status =
++	    rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_ON);
+ 	if (status)
+ 		return status;
+ 
++	rt2x00leds_led_radio(rt2x00dev, true);
++
+ 	__set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags);
+ 
+ 	/*
+@@ -204,12 +138,10 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Stop all scheduled work.
+ 	 */
+-	if (work_pending(&rt2x00dev->beacon_work))
+-		cancel_work_sync(&rt2x00dev->beacon_work);
++	if (work_pending(&rt2x00dev->intf_work))
++		cancel_work_sync(&rt2x00dev->intf_work);
+ 	if (work_pending(&rt2x00dev->filter_work))
+ 		cancel_work_sync(&rt2x00dev->filter_work);
+-	if (work_pending(&rt2x00dev->config_work))
+-		cancel_work_sync(&rt2x00dev->config_work);
+ 
+ 	/*
+ 	 * Stop the TX queues.
+@@ -225,6 +157,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
+ 	 * Disable radio.
+ 	 */
+ 	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF);
++	rt2x00leds_led_radio(rt2x00dev, false);
+ }
+ 
+ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
+@@ -241,7 +174,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
+ 	 * When we are enabling the RX, we should also start the link tuner.
+ 	 */
+ 	if (state == STATE_RADIO_RX_ON &&
+-	    is_interface_present(&rt2x00dev->interface))
++	    (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count))
+ 		rt2x00lib_start_link_tuner(rt2x00dev);
+ }
+ 
+@@ -449,6 +382,11 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
+ 	rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual);
+ 
+ 	/*
++	 * Send a signal to the led to update the led signal strength.
++	 */
++	rt2x00leds_led_quality(rt2x00dev, rt2x00dev->link.qual.avg_rssi);
++
++	/*
+ 	 * Evaluate antenna setup, make this the last step since this could
+ 	 * possibly reset some statistics.
+ 	 */
+@@ -466,59 +404,76 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
+ {
+ 	struct rt2x00_dev *rt2x00dev =
+ 	    container_of(work, struct rt2x00_dev, filter_work);
+-	unsigned int filter = rt2x00dev->packet_filter;
++
++	rt2x00dev->ops->lib->config_filter(rt2x00dev, rt2x00dev->packet_filter);
++}
++
++static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
++					  struct ieee80211_vif *vif)
++{
++	struct rt2x00_dev *rt2x00dev = data;
++	struct rt2x00_intf *intf = vif_to_intf(vif);
++	struct sk_buff *skb;
++	struct ieee80211_tx_control control;
++	struct ieee80211_bss_conf conf;
++	int delayed_flags;
+ 
+ 	/*
+-	 * Since we had stored the filter inside interface.filter,
+-	 * we should now clear that field. Otherwise the driver will
+-	 * assume nothing has changed (*total_flags will be compared
+-	 * to interface.filter to determine if any action is required).
++	 * Copy all data we need during this action under the protection
++	 * of a spinlock. Otherwise race conditions might occur which results
++	 * into an invalid configuration.
+ 	 */
+-	rt2x00dev->packet_filter = 0;
++	spin_lock(&intf->lock);
++
++	memcpy(&conf, &intf->conf, sizeof(conf));
++	delayed_flags = intf->delayed_flags;
++	intf->delayed_flags = 0;
+ 
+-	rt2x00dev->ops->hw->configure_filter(rt2x00dev->hw,
+-					     filter, &filter, 0, NULL);
++	spin_unlock(&intf->lock);
++
++	if (delayed_flags & DELAYED_UPDATE_BEACON) {
++		skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
++		if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
++							     skb, &control))
++			dev_kfree_skb(skb);
++	}
++
++	if (delayed_flags & DELAYED_CONFIG_ERP)
++		rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf);
++
++	if (delayed_flags & DELAYED_LED_ASSOC)
++		rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
+ }
+ 
+-static void rt2x00lib_configuration_scheduled(struct work_struct *work)
++static void rt2x00lib_intf_scheduled(struct work_struct *work)
+ {
+ 	struct rt2x00_dev *rt2x00dev =
+-	    container_of(work, struct rt2x00_dev, config_work);
+-	struct ieee80211_bss_conf bss_conf;
+-
+-	bss_conf.use_short_preamble =
+-		test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
++	    container_of(work, struct rt2x00_dev, intf_work);
+ 
+ 	/*
+-	 * FIXME: shouldn't invoke it this way because all other contents
+-	 *	  of bss_conf is invalid.
++	 * Iterate over each interface and perform the
++	 * requested configurations.
+ 	 */
+-	rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id,
+-				   &bss_conf, BSS_CHANGED_ERP_PREAMBLE);
++	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
++					    rt2x00lib_intf_scheduled_iter,
++					    rt2x00dev);
+ }
+ 
+ /*
+  * Interrupt context handlers.
+  */
+-static void rt2x00lib_beacondone_scheduled(struct work_struct *work)
++static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
++				      struct ieee80211_vif *vif)
+ {
+-	struct rt2x00_dev *rt2x00dev =
+-	    container_of(work, struct rt2x00_dev, beacon_work);
+-	struct data_ring *ring =
+-	    rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
+-	struct data_entry *entry = rt2x00_get_data_entry(ring);
+-	struct sk_buff *skb;
++	struct rt2x00_intf *intf = vif_to_intf(vif);
+ 
+-	skb = ieee80211_beacon_get(rt2x00dev->hw,
+-				   rt2x00dev->interface.id,
+-				   &entry->tx_status.control);
+-	if (!skb)
++	if (vif->type != IEEE80211_IF_TYPE_AP &&
++	    vif->type != IEEE80211_IF_TYPE_IBSS)
+ 		return;
+ 
+-	rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
+-					  &entry->tx_status.control);
+-
+-	dev_kfree_skb(skb);
++	spin_lock(&intf->lock);
++	intf->delayed_flags |= DELAYED_UPDATE_BEACON;
++	spin_unlock(&intf->lock);
+ }
+ 
+ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
+@@ -526,116 +481,140 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
+ 	if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ 		return;
+ 
+-	queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work);
++	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
++					    rt2x00lib_beacondone_iter,
++					    rt2x00dev);
++
++	queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
+ 
+-void rt2x00lib_txdone(struct data_entry *entry,
+-		      const int status, const int retry)
++void rt2x00lib_txdone(struct queue_entry *entry,
++		      struct txdone_entry_desc *txdesc)
+ {
+-	struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
+-	struct ieee80211_tx_status *tx_status = &entry->tx_status;
+-	struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats;
+-	int success = !!(status == TX_SUCCESS || status == TX_SUCCESS_RETRY);
+-	int fail = !!(status == TX_FAIL_RETRY || status == TX_FAIL_INVALID ||
+-		      status == TX_FAIL_OTHER);
++	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
++	struct skb_frame_desc *skbdesc;
++	struct ieee80211_tx_status tx_status;
++	int success = !!(txdesc->status == TX_SUCCESS ||
++			 txdesc->status == TX_SUCCESS_RETRY);
++	int fail = !!(txdesc->status == TX_FAIL_RETRY ||
++		      txdesc->status == TX_FAIL_INVALID ||
++		      txdesc->status == TX_FAIL_OTHER);
+ 
+ 	/*
+ 	 * Update TX statistics.
+ 	 */
+-	tx_status->flags = 0;
+-	tx_status->ack_signal = 0;
+-	tx_status->excessive_retries = (status == TX_FAIL_RETRY);
+-	tx_status->retry_count = retry;
+ 	rt2x00dev->link.qual.tx_success += success;
+-	rt2x00dev->link.qual.tx_failed += retry + fail;
++	rt2x00dev->link.qual.tx_failed += txdesc->retry + fail;
++
++	/*
++	 * Initialize TX status
++	 */
++	tx_status.flags = 0;
++	tx_status.ack_signal = 0;
++	tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY);
++	tx_status.retry_count = txdesc->retry;
++	memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control));
+ 
+-	if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) {
++	if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
+ 		if (success)
+-			tx_status->flags |= IEEE80211_TX_STATUS_ACK;
++			tx_status.flags |= IEEE80211_TX_STATUS_ACK;
+ 		else
+-			stats->dot11ACKFailureCount++;
++			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
+ 	}
+ 
+-	tx_status->queue_length = entry->ring->stats.limit;
+-	tx_status->queue_number = tx_status->control.queue;
++	tx_status.queue_length = entry->queue->limit;
++	tx_status.queue_number = tx_status.control.queue;
+ 
+-	if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
++	if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+ 		if (success)
+-			stats->dot11RTSSuccessCount++;
++			rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
+ 		else
+-			stats->dot11RTSFailureCount++;
++			rt2x00dev->low_level_stats.dot11RTSFailureCount++;
+ 	}
+ 
+ 	/*
+-	 * Send the tx_status to mac80211 & debugfs.
+-	 * mac80211 will clean up the skb structure.
++	 * Send the tx_status to debugfs. Only send the status report
++	 * to mac80211 when the frame originated from there. If this was
++	 * a extra frame coming through a mac80211 library call (RTS/CTS)
++	 * then we should not send the status report back.
++	 * If send to mac80211, mac80211 will clean up the skb structure,
++	 * otherwise we have to do it ourself.
+ 	 */
+-	get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
++	skbdesc = get_skb_frame_desc(entry->skb);
++	skbdesc->frame_type = DUMP_FRAME_TXDONE;
++
+ 	rt2x00debug_dump_frame(rt2x00dev, entry->skb);
+-	ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
++
++	if (!(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED))
++		ieee80211_tx_status_irqsafe(rt2x00dev->hw,
++					    entry->skb, &tx_status);
++	else
++		dev_kfree_skb(entry->skb);
+ 	entry->skb = NULL;
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
+ 
+-void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
+-		      struct rxdata_entry_desc *desc)
++void rt2x00lib_rxdone(struct queue_entry *entry,
++		      struct rxdone_entry_desc *rxdesc)
+ {
+-	struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
++	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ 	struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
+-	struct ieee80211_hw_mode *mode;
+-	struct ieee80211_rate *rate;
++	struct ieee80211_supported_band *sband;
+ 	struct ieee80211_hdr *hdr;
++	const struct rt2x00_rate *rate;
+ 	unsigned int i;
+-	int val = 0;
++	int idx = -1;
+ 	u16 fc;
+ 
+ 	/*
+ 	 * Update RX statistics.
+ 	 */
+-	mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
+-	for (i = 0; i < mode->num_rates; i++) {
+-		rate = &mode->rates[i];
++	sband = &rt2x00dev->bands[rt2x00dev->curr_band];
++	for (i = 0; i < sband->n_bitrates; i++) {
++		rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
+ 
+-		/*
+-		 * When frame was received with an OFDM bitrate,
+-		 * the signal is the PLCP value. If it was received with
+-		 * a CCK bitrate the signal is the rate in 0.5kbit/s.
+-		 */
+-		if (!desc->ofdm)
+-			val = DEVICE_GET_RATE_FIELD(rate->val, RATE);
+-		else
+-			val = DEVICE_GET_RATE_FIELD(rate->val, PLCP);
+-
+-		if (val == desc->signal) {
+-			val = rate->val;
++		if (((rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) &&
++		     (rate->plcp == rxdesc->signal)) ||
++		    (!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) &&
++		      (rate->bitrate == rxdesc->signal))) {
++			idx = i;
+ 			break;
+ 		}
+ 	}
+ 
++	if (idx < 0) {
++		WARNING(rt2x00dev, "Frame received with unrecognized signal,"
++			"signal=0x%.2x, plcp=%d.\n", rxdesc->signal,
++			!!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP));
++		idx = 0;
++	}
++
+ 	/*
+ 	 * Only update link status if this is a beacon frame carrying our bssid.
+ 	 */
+-	hdr = (struct ieee80211_hdr*)skb->data;
++	hdr = (struct ieee80211_hdr *)entry->skb->data;
+ 	fc = le16_to_cpu(hdr->frame_control);
+-	if (is_beacon(fc) && desc->my_bss)
+-		rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi);
++	if (is_beacon(fc) && (rxdesc->dev_flags & RXDONE_MY_BSS))
++		rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi);
+ 
+ 	rt2x00dev->link.qual.rx_success++;
+ 
+-	rx_status->rate = val;
++	rx_status->rate_idx = idx;
+ 	rx_status->signal =
+-	    rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi);
+-	rx_status->ssi = desc->rssi;
+-	rx_status->flag = desc->flags;
++	    rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi);
++	rx_status->ssi = rxdesc->rssi;
++	rx_status->flag = rxdesc->flags;
+ 	rx_status->antenna = rt2x00dev->link.ant.active.rx;
+ 
+ 	/*
+-	 * Send frame to mac80211 & debugfs
++	 * Send frame to mac80211 & debugfs.
++	 * mac80211 will clean up the skb structure.
+ 	 */
+-	get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
+-	rt2x00debug_dump_frame(rt2x00dev, skb);
+-	ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
++	get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_RXDONE;
++	rt2x00debug_dump_frame(rt2x00dev, entry->skb);
++	ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
++	entry->skb = NULL;
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
+ 
+@@ -646,83 +625,69 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 			     struct sk_buff *skb,
+ 			     struct ieee80211_tx_control *control)
+ {
+-	struct txdata_entry_desc desc;
+-	struct skb_desc *skbdesc = get_skb_desc(skb);
+-	struct ieee80211_hdr *ieee80211hdr = skbdesc->data;
++	struct txentry_desc txdesc;
++	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skbdesc->data;
++	const struct rt2x00_rate *rate;
+ 	int tx_rate;
+-	int bitrate;
+ 	int length;
+ 	int duration;
+ 	int residual;
+ 	u16 frame_control;
+ 	u16 seq_ctrl;
+ 
+-	memset(&desc, 0, sizeof(desc));
++	memset(&txdesc, 0, sizeof(txdesc));
+ 
+-	desc.cw_min = skbdesc->ring->tx_params.cw_min;
+-	desc.cw_max = skbdesc->ring->tx_params.cw_max;
+-	desc.aifs = skbdesc->ring->tx_params.aifs;
+-
+-	/*
+-	 * Identify queue
+-	 */
+-	if (control->queue < rt2x00dev->hw->queues)
+-		desc.queue = control->queue;
+-	else if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
+-		 control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
+-		desc.queue = QUEUE_MGMT;
+-	else
+-		desc.queue = QUEUE_OTHER;
++	txdesc.queue = skbdesc->entry->queue->qid;
++	txdesc.cw_min = skbdesc->entry->queue->cw_min;
++	txdesc.cw_max = skbdesc->entry->queue->cw_max;
++	txdesc.aifs = skbdesc->entry->queue->aifs;
+ 
+ 	/*
+ 	 * Read required fields from ieee80211 header.
+ 	 */
+-	frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+-	seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl);
++	frame_control = le16_to_cpu(hdr->frame_control);
++	seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
+ 
+-	tx_rate = control->tx_rate;
++	tx_rate = control->tx_rate->hw_value;
+ 
+ 	/*
+ 	 * Check whether this frame is to be acked
+ 	 */
+ 	if (!(control->flags & IEEE80211_TXCTL_NO_ACK))
+-		__set_bit(ENTRY_TXD_ACK, &desc.flags);
++		__set_bit(ENTRY_TXD_ACK, &txdesc.flags);
+ 
+ 	/*
+ 	 * Check if this is a RTS/CTS frame
+ 	 */
+ 	if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) {
+-		__set_bit(ENTRY_TXD_BURST, &desc.flags);
++		__set_bit(ENTRY_TXD_BURST, &txdesc.flags);
+ 		if (is_rts_frame(frame_control)) {
+-			__set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags);
+-			__set_bit(ENTRY_TXD_ACK, &desc.flags);
++			__set_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags);
++			__set_bit(ENTRY_TXD_ACK, &txdesc.flags);
+ 		} else
+-			__clear_bit(ENTRY_TXD_ACK, &desc.flags);
++			__clear_bit(ENTRY_TXD_ACK, &txdesc.flags);
+ 		if (control->rts_cts_rate)
+-			tx_rate = control->rts_cts_rate;
++			tx_rate = control->rts_cts_rate->hw_value;
+ 	}
+ 
+-	/*
+-	 * Check for OFDM
+-	 */
+-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK)
+-		__set_bit(ENTRY_TXD_OFDM_RATE, &desc.flags);
++	rate = rt2x00_get_rate(tx_rate);
+ 
+ 	/*
+ 	 * Check if more fragments are pending
+ 	 */
+-	if (ieee80211_get_morefrag(ieee80211hdr)) {
+-		__set_bit(ENTRY_TXD_BURST, &desc.flags);
+-		__set_bit(ENTRY_TXD_MORE_FRAG, &desc.flags);
++	if (ieee80211_get_morefrag(hdr)) {
++		__set_bit(ENTRY_TXD_BURST, &txdesc.flags);
++		__set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags);
+ 	}
+ 
+ 	/*
+ 	 * Beacons and probe responses require the tsf timestamp
+ 	 * to be inserted into the frame.
+ 	 */
+-	if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
++	if (control->queue == RT2X00_BCN_QUEUE_BEACON ||
+ 	    is_probe_resp(frame_control))
+-		__set_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc.flags);
++		__set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc.flags);
+ 
+ 	/*
+ 	 * Determine with what IFS priority this frame should be send.
+@@ -730,30 +695,30 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 	 * or this fragment came after RTS/CTS.
+ 	 */
+ 	if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 ||
+-	    test_bit(ENTRY_TXD_RTS_FRAME, &desc.flags))
+-		desc.ifs = IFS_SIFS;
++	    test_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags))
++		txdesc.ifs = IFS_SIFS;
+ 	else
+-		desc.ifs = IFS_BACKOFF;
++		txdesc.ifs = IFS_BACKOFF;
+ 
+ 	/*
+ 	 * PLCP setup
+ 	 * Length calculation depends on OFDM/CCK rate.
+ 	 */
+-	desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
+-	desc.service = 0x04;
++	txdesc.signal = rate->plcp;
++	txdesc.service = 0x04;
+ 
+ 	length = skbdesc->data_len + FCS_LEN;
+-	if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) {
+-		desc.length_high = (length >> 6) & 0x3f;
+-		desc.length_low = length & 0x3f;
+-	} else {
+-		bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
++	if (rate->flags & DEV_RATE_OFDM) {
++		__set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags);
+ 
++		txdesc.length_high = (length >> 6) & 0x3f;
++		txdesc.length_low = length & 0x3f;
++	} else {
+ 		/*
+ 		 * Convert length to microseconds.
+ 		 */
+-		residual = get_duration_res(length, bitrate);
+-		duration = get_duration(length, bitrate);
++		residual = get_duration_res(length, rate->bitrate);
++		duration = get_duration(length, rate->bitrate);
+ 
+ 		if (residual != 0) {
+ 			duration++;
+@@ -761,28 +726,27 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 			/*
+ 			 * Check if we need to set the Length Extension
+ 			 */
+-			if (bitrate == 110 && residual <= 30)
+-				desc.service |= 0x80;
++			if (rate->bitrate == 110 && residual <= 30)
++				txdesc.service |= 0x80;
+ 		}
+ 
+-		desc.length_high = (duration >> 8) & 0xff;
+-		desc.length_low = duration & 0xff;
++		txdesc.length_high = (duration >> 8) & 0xff;
++		txdesc.length_low = duration & 0xff;
+ 
+ 		/*
+ 		 * When preamble is enabled we should set the
+ 		 * preamble bit for the signal.
+ 		 */
+-		if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
+-			desc.signal |= 0x08;
++		if (rt2x00_get_rate_preamble(tx_rate))
++			txdesc.signal |= 0x08;
+ 	}
+ 
+-	rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control);
++	rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &txdesc, control);
+ 
+ 	/*
+-	 * Update ring entry.
++	 * Update queue entry.
+ 	 */
+ 	skbdesc->entry->skb = skb;
+-	memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
+ 
+ 	/*
+ 	 * The frame has been completely initialized and ready
+@@ -798,133 +762,167 @@ EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);
+ /*
+  * Driver initialization handlers.
+  */
++const struct rt2x00_rate rt2x00_supported_rates[12] = {
++	{
++		.flags = DEV_RATE_CCK | DEV_RATE_BASIC,
++		.bitrate = 10,
++		.ratemask = BIT(0),
++		.plcp = 0x00,
++	},
++	{
++		.flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
++		.bitrate = 20,
++		.ratemask = BIT(1),
++		.plcp = 0x01,
++	},
++	{
++		.flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
++		.bitrate = 55,
++		.ratemask = BIT(2),
++		.plcp = 0x02,
++	},
++	{
++		.flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
++		.bitrate = 110,
++		.ratemask = BIT(3),
++		.plcp = 0x03,
++	},
++	{
++		.flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
++		.bitrate = 60,
++		.ratemask = BIT(4),
++		.plcp = 0x0b,
++	},
++	{
++		.flags = DEV_RATE_OFDM,
++		.bitrate = 90,
++		.ratemask = BIT(5),
++		.plcp = 0x0f,
++	},
++	{
++		.flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
++		.bitrate = 120,
++		.ratemask = BIT(6),
++		.plcp = 0x0a,
++	},
++	{
++		.flags = DEV_RATE_OFDM,
++		.bitrate = 180,
++		.ratemask = BIT(7),
++		.plcp = 0x0e,
++	},
++	{
++		.flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
++		.bitrate = 240,
++		.ratemask = BIT(8),
++		.plcp = 0x09,
++	},
++	{
++		.flags = DEV_RATE_OFDM,
++		.bitrate = 360,
++		.ratemask = BIT(9),
++		.plcp = 0x0d,
++	},
++	{
++		.flags = DEV_RATE_OFDM,
++		.bitrate = 480,
++		.ratemask = BIT(10),
++		.plcp = 0x08,
++	},
++	{
++		.flags = DEV_RATE_OFDM,
++		.bitrate = 540,
++		.ratemask = BIT(11),
++		.plcp = 0x0c,
++	},
++};
++
+ static void rt2x00lib_channel(struct ieee80211_channel *entry,
+ 			      const int channel, const int tx_power,
+ 			      const int value)
+ {
+-	entry->chan = channel;
+-	if (channel <= 14)
+-		entry->freq = 2407 + (5 * channel);
+-	else
+-		entry->freq = 5000 + (5 * channel);
+-	entry->val = value;
+-	entry->flag =
+-	    IEEE80211_CHAN_W_IBSS |
+-	    IEEE80211_CHAN_W_ACTIVE_SCAN |
+-	    IEEE80211_CHAN_W_SCAN;
+-	entry->power_level = tx_power;
+-	entry->antenna_max = 0xff;
++	entry->center_freq = ieee80211_channel_to_frequency(channel);
++	entry->hw_value = value;
++	entry->max_power = tx_power;
++	entry->max_antenna_gain = 0xff;
+ }
+ 
+ static void rt2x00lib_rate(struct ieee80211_rate *entry,
+-			   const int rate, const int mask,
+-			   const int plcp, const int flags)
++			   const u16 index, const struct rt2x00_rate *rate)
+ {
+-	entry->rate = rate;
+-	entry->val =
+-	    DEVICE_SET_RATE_FIELD(rate, RATE) |
+-	    DEVICE_SET_RATE_FIELD(mask, RATEMASK) |
+-	    DEVICE_SET_RATE_FIELD(plcp, PLCP);
+-	entry->flags = flags;
+-	entry->val2 = entry->val;
+-	if (entry->flags & IEEE80211_RATE_PREAMBLE2)
+-		entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);
+-	entry->min_rssi_ack = 0;
+-	entry->min_rssi_ack_delta = 0;
++	entry->flags = 0;
++	entry->bitrate = rate->bitrate;
++	entry->hw_value = rt2x00_create_rate_hw_value(index, 0);
++	entry->hw_value_short = entry->hw_value;
++
++	if (rate->flags & DEV_RATE_SHORT_PREAMBLE) {
++		entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
++		entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1);
++	}
+ }
+ 
+ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
+ 				    struct hw_mode_spec *spec)
+ {
+ 	struct ieee80211_hw *hw = rt2x00dev->hw;
+-	struct ieee80211_hw_mode *hwmodes;
+ 	struct ieee80211_channel *channels;
+ 	struct ieee80211_rate *rates;
++	unsigned int num_rates;
+ 	unsigned int i;
+ 	unsigned char tx_power;
+ 
+-	hwmodes = kzalloc(sizeof(*hwmodes) * spec->num_modes, GFP_KERNEL);
+-	if (!hwmodes)
+-		goto exit;
++	num_rates = 0;
++	if (spec->supported_rates & SUPPORT_RATE_CCK)
++		num_rates += 4;
++	if (spec->supported_rates & SUPPORT_RATE_OFDM)
++		num_rates += 8;
+ 
+ 	channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL);
+ 	if (!channels)
+-		goto exit_free_modes;
++		return -ENOMEM;
+ 
+-	rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL);
++	rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL);
+ 	if (!rates)
+ 		goto exit_free_channels;
+ 
+ 	/*
+ 	 * Initialize Rate list.
+ 	 */
+-	rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB,
+-		       0x00, IEEE80211_RATE_CCK);
+-	rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB,
+-		       0x01, IEEE80211_RATE_CCK_2);
+-	rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB,
+-		       0x02, IEEE80211_RATE_CCK_2);
+-	rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB,
+-		       0x03, IEEE80211_RATE_CCK_2);
+-
+-	if (spec->num_rates > 4) {
+-		rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB,
+-			       0x0b, IEEE80211_RATE_OFDM);
+-		rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB,
+-			       0x0f, IEEE80211_RATE_OFDM);
+-		rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB,
+-			       0x0a, IEEE80211_RATE_OFDM);
+-		rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB,
+-			       0x0e, IEEE80211_RATE_OFDM);
+-		rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB,
+-			       0x09, IEEE80211_RATE_OFDM);
+-		rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB,
+-			       0x0d, IEEE80211_RATE_OFDM);
+-		rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB,
+-			       0x08, IEEE80211_RATE_OFDM);
+-		rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB,
+-			       0x0c, IEEE80211_RATE_OFDM);
+-	}
++	for (i = 0; i < num_rates; i++)
++		rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i));
+ 
+ 	/*
+ 	 * Initialize Channel list.
+ 	 */
+ 	for (i = 0; i < spec->num_channels; i++) {
+-		if (spec->channels[i].channel <= 14)
+-			tx_power = spec->tx_power_bg[i];
+-		else if (spec->tx_power_a)
+-			tx_power = spec->tx_power_a[i];
+-		else
+-			tx_power = spec->tx_power_default;
++		if (spec->channels[i].channel <= 14) {
++			if (spec->tx_power_bg)
++				tx_power = spec->tx_power_bg[i];
++			else
++				tx_power = spec->tx_power_default;
++		} else {
++			if (spec->tx_power_a)
++				tx_power = spec->tx_power_a[i];
++			else
++				tx_power = spec->tx_power_default;
++		}
+ 
+ 		rt2x00lib_channel(&channels[i],
+ 				  spec->channels[i].channel, tx_power, i);
+ 	}
+ 
+ 	/*
+-	 * Intitialize 802.11b
+-	 * Rates: CCK.
+-	 * Channels: OFDM.
+-	 */
+-	if (spec->num_modes > HWMODE_B) {
+-		hwmodes[HWMODE_B].mode = MODE_IEEE80211B;
+-		hwmodes[HWMODE_B].num_channels = 14;
+-		hwmodes[HWMODE_B].num_rates = 4;
+-		hwmodes[HWMODE_B].channels = channels;
+-		hwmodes[HWMODE_B].rates = rates;
+-	}
+-
+-	/*
+-	 * Intitialize 802.11g
++	 * Intitialize 802.11b, 802.11g
+ 	 * Rates: CCK, OFDM.
+-	 * Channels: OFDM.
+-	 */
+-	if (spec->num_modes > HWMODE_G) {
+-		hwmodes[HWMODE_G].mode = MODE_IEEE80211G;
+-		hwmodes[HWMODE_G].num_channels = 14;
+-		hwmodes[HWMODE_G].num_rates = spec->num_rates;
+-		hwmodes[HWMODE_G].channels = channels;
+-		hwmodes[HWMODE_G].rates = rates;
++	 * Channels: 2.4 GHz
++	 */
++	if (spec->supported_bands & SUPPORT_BAND_2GHZ) {
++		rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14;
++		rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates;
++		rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels;
++		rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
++		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++		    &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
+ 	}
+ 
+ 	/*
+@@ -932,40 +930,21 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
+ 	 * Rates: OFDM.
+ 	 * Channels: OFDM, UNII, HiperLAN2.
+ 	 */
+-	if (spec->num_modes > HWMODE_A) {
+-		hwmodes[HWMODE_A].mode = MODE_IEEE80211A;
+-		hwmodes[HWMODE_A].num_channels = spec->num_channels - 14;
+-		hwmodes[HWMODE_A].num_rates = spec->num_rates - 4;
+-		hwmodes[HWMODE_A].channels = &channels[14];
+-		hwmodes[HWMODE_A].rates = &rates[4];
++	if (spec->supported_bands & SUPPORT_BAND_5GHZ) {
++		rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels =
++		    spec->num_channels - 14;
++		rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates =
++		    num_rates - 4;
++		rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14];
++		rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
++		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
++		    &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
+ 	}
+ 
+-	if (spec->num_modes > HWMODE_G &&
+-	    ieee80211_register_hwmode(hw, &hwmodes[HWMODE_G]))
+-		goto exit_free_rates;
+-
+-	if (spec->num_modes > HWMODE_B &&
+-	    ieee80211_register_hwmode(hw, &hwmodes[HWMODE_B]))
+-		goto exit_free_rates;
+-
+-	if (spec->num_modes > HWMODE_A &&
+-	    ieee80211_register_hwmode(hw, &hwmodes[HWMODE_A]))
+-		goto exit_free_rates;
+-
+-	rt2x00dev->hwmodes = hwmodes;
+-
+ 	return 0;
+ 
+-exit_free_rates:
+-	kfree(rates);
+-
+-exit_free_channels:
++ exit_free_channels:
+ 	kfree(channels);
+-
+-exit_free_modes:
+-	kfree(hwmodes);
+-
+-exit:
+ 	ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n");
+ 	return -ENOMEM;
+ }
+@@ -975,11 +954,11 @@ static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
+ 	if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))
+ 		ieee80211_unregister_hw(rt2x00dev->hw);
+ 
+-	if (likely(rt2x00dev->hwmodes)) {
+-		kfree(rt2x00dev->hwmodes->channels);
+-		kfree(rt2x00dev->hwmodes->rates);
+-		kfree(rt2x00dev->hwmodes);
+-		rt2x00dev->hwmodes = NULL;
++	if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
++		kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
++		kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates);
++		rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
++		rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+ 	}
+ }
+ 
+@@ -1012,86 +991,6 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+  * Initialization/uninitialization handlers.
+  */
+-static int rt2x00lib_alloc_entries(struct data_ring *ring,
+-				   const u16 max_entries, const u16 data_size,
+-				   const u16 desc_size)
+-{
+-	struct data_entry *entry;
+-	unsigned int i;
+-
+-	ring->stats.limit = max_entries;
+-	ring->data_size = data_size;
+-	ring->desc_size = desc_size;
+-
+-	/*
+-	 * Allocate all ring entries.
+-	 */
+-	entry = kzalloc(ring->stats.limit * sizeof(*entry), GFP_KERNEL);
+-	if (!entry)
+-		return -ENOMEM;
+-
+-	for (i = 0; i < ring->stats.limit; i++) {
+-		entry[i].flags = 0;
+-		entry[i].ring = ring;
+-		entry[i].skb = NULL;
+-		entry[i].entry_idx = i;
+-	}
+-
+-	ring->entry = entry;
+-
+-	return 0;
+-}
+-
+-static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev)
+-{
+-	struct data_ring *ring;
+-
+-	/*
+-	 * Allocate the RX ring.
+-	 */
+-	if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE,
+-				    rt2x00dev->ops->rxd_size))
+-		return -ENOMEM;
+-
+-	/*
+-	 * First allocate the TX rings.
+-	 */
+-	txring_for_each(rt2x00dev, ring) {
+-		if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE,
+-					    rt2x00dev->ops->txd_size))
+-			return -ENOMEM;
+-	}
+-
+-	if (!test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
+-		return 0;
+-
+-	/*
+-	 * Allocate the BEACON ring.
+-	 */
+-	if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES,
+-				    MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size))
+-		return -ENOMEM;
+-
+-	/*
+-	 * Allocate the Atim ring.
+-	 */
+-	if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], ATIM_ENTRIES,
+-				    DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))
+-		return -ENOMEM;
+-
+-	return 0;
+-}
+-
+-static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev)
+-{
+-	struct data_ring *ring;
+-
+-	ring_for_each(rt2x00dev, ring) {
+-		kfree(ring->entry);
+-		ring->entry = NULL;
+-	}
+-}
+-
+ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
+ {
+ 	if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
+@@ -1108,9 +1007,9 @@ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
+ 	rt2x00dev->ops->lib->uninitialize(rt2x00dev);
+ 
+ 	/*
+-	 * Free allocated ring entries.
++	 * Free allocated queue entries.
+ 	 */
+-	rt2x00lib_free_ring_entries(rt2x00dev);
++	rt2x00queue_uninitialize(rt2x00dev);
+ }
+ 
+ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
+@@ -1121,13 +1020,11 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
+ 		return 0;
+ 
+ 	/*
+-	 * Allocate all ring entries.
++	 * Allocate all queue entries.
+ 	 */
+-	status = rt2x00lib_alloc_ring_entries(rt2x00dev);
+-	if (status) {
+-		ERROR(rt2x00dev, "Ring entries allocation failed.\n");
++	status = rt2x00queue_initialize(rt2x00dev);
++	if (status)
+ 		return status;
+-	}
+ 
+ 	/*
+ 	 * Initialize the device.
+@@ -1146,7 +1043,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
+ 	return 0;
+ 
+ exit:
+-	rt2x00lib_free_ring_entries(rt2x00dev);
++	rt2x00lib_uninitialize(rt2x00dev);
+ 
+ 	return status;
+ }
+@@ -1162,11 +1059,9 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
+ 	 * If this is the first interface which is added,
+ 	 * we should load the firmware now.
+ 	 */
+-	if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
+-		retval = rt2x00lib_load_firmware(rt2x00dev);
+-		if (retval)
+-			return retval;
+-	}
++	retval = rt2x00lib_load_firmware(rt2x00dev);
++	if (retval)
++		return retval;
+ 
+ 	/*
+ 	 * Initialize the device.
+@@ -1184,6 +1079,10 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
+ 		return retval;
+ 	}
+ 
++	rt2x00dev->intf_ap_count = 0;
++	rt2x00dev->intf_sta_count = 0;
++	rt2x00dev->intf_associated = 0;
++
+ 	__set_bit(DEVICE_STARTED, &rt2x00dev->flags);
+ 
+ 	return 0;
+@@ -1200,74 +1099,25 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
+ 	 */
+ 	rt2x00lib_disable_radio(rt2x00dev);
+ 
++	rt2x00dev->intf_ap_count = 0;
++	rt2x00dev->intf_sta_count = 0;
++	rt2x00dev->intf_associated = 0;
++
+ 	__clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
+ }
+ 
+ /*
+  * driver allocation handlers.
+  */
+-static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev)
++int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
+ {
+-	struct data_ring *ring;
+-	unsigned int index;
+-
+-	/*
+-	 * We need the following rings:
+-	 * RX: 1
+-	 * TX: hw->queues
+-	 * Beacon: 1 (if required)
+-	 * Atim: 1 (if required)
+-	 */
+-	rt2x00dev->data_rings = 1 + rt2x00dev->hw->queues +
+-	    (2 * test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags));
+-
+-	ring = kzalloc(rt2x00dev->data_rings * sizeof(*ring), GFP_KERNEL);
+-	if (!ring) {
+-		ERROR(rt2x00dev, "Ring allocation failed.\n");
+-		return -ENOMEM;
+-	}
+-
+-	/*
+-	 * Initialize pointers
+-	 */
+-	rt2x00dev->rx = ring;
+-	rt2x00dev->tx = &rt2x00dev->rx[1];
+-	if (test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
+-		rt2x00dev->bcn = &rt2x00dev->tx[rt2x00dev->hw->queues];
++	int retval = -ENOMEM;
+ 
+ 	/*
+-	 * Initialize ring parameters.
+-	 * RX: queue_idx = 0
+-	 * TX: queue_idx = IEEE80211_TX_QUEUE_DATA0 + index
+-	 * TX: cw_min: 2^5 = 32.
+-	 * TX: cw_max: 2^10 = 1024.
++	 * Make room for rt2x00_intf inside the per-interface
++	 * structure ieee80211_vif.
+ 	 */
+-	rt2x00dev->rx->rt2x00dev = rt2x00dev;
+-	rt2x00dev->rx->queue_idx = 0;
+-
+-	index = IEEE80211_TX_QUEUE_DATA0;
+-	txring_for_each(rt2x00dev, ring) {
+-		ring->rt2x00dev = rt2x00dev;
+-		ring->queue_idx = index++;
+-		ring->tx_params.aifs = 2;
+-		ring->tx_params.cw_min = 5;
+-		ring->tx_params.cw_max = 10;
+-	}
+-
+-	return 0;
+-}
+-
+-static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev)
+-{
+-	kfree(rt2x00dev->rx);
+-	rt2x00dev->rx = NULL;
+-	rt2x00dev->tx = NULL;
+-	rt2x00dev->bcn = NULL;
+-}
+-
+-int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
+-{
+-	int retval = -ENOMEM;
++	rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
+ 
+ 	/*
+ 	 * Let the driver probe the device to detect the capabilities.
+@@ -1281,20 +1131,14 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Initialize configuration work.
+ 	 */
+-	INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled);
++	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
+ 	INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
+-	INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled);
+ 	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
+ 
+ 	/*
+-	 * Reset current working type.
+-	 */
+-	rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID;
+-
+-	/*
+-	 * Allocate ring array.
++	 * Allocate queue array.
+ 	 */
+-	retval = rt2x00lib_alloc_rings(rt2x00dev);
++	retval = rt2x00queue_allocate(rt2x00dev);
+ 	if (retval)
+ 		goto exit;
+ 
+@@ -1310,6 +1154,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Register extra components.
+ 	 */
++	rt2x00leds_register(rt2x00dev);
+ 	rt2x00rfkill_allocate(rt2x00dev);
+ 	rt2x00debug_register(rt2x00dev);
+ 
+@@ -1343,6 +1188,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
+ 	 */
+ 	rt2x00debug_deregister(rt2x00dev);
+ 	rt2x00rfkill_free(rt2x00dev);
++	rt2x00leds_unregister(rt2x00dev);
+ 
+ 	/*
+ 	 * Free ieee80211_hw memory.
+@@ -1355,9 +1201,9 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
+ 	rt2x00lib_free_firmware(rt2x00dev);
+ 
+ 	/*
+-	 * Free ring structures.
++	 * Free queue structures.
+ 	 */
+-	rt2x00lib_free_rings(rt2x00dev);
++	rt2x00queue_free(rt2x00dev);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
+ 
+@@ -1388,6 +1234,7 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
+ 	/*
+ 	 * Suspend/disable extra components.
+ 	 */
++	rt2x00leds_suspend(rt2x00dev);
+ 	rt2x00rfkill_suspend(rt2x00dev);
+ 	rt2x00debug_deregister(rt2x00dev);
+ 
+@@ -1412,9 +1259,30 @@ exit:
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
+ 
++static void rt2x00lib_resume_intf(void *data, u8 *mac,
++				  struct ieee80211_vif *vif)
++{
++	struct rt2x00_dev *rt2x00dev = data;
++	struct rt2x00_intf *intf = vif_to_intf(vif);
++
++	spin_lock(&intf->lock);
++
++	rt2x00lib_config_intf(rt2x00dev, intf,
++			      vif->type, intf->mac, intf->bssid);
++
++
++	/*
++	 * Master or Ad-hoc mode require a new beacon update.
++	 */
++	if (vif->type == IEEE80211_IF_TYPE_AP ||
++	    vif->type == IEEE80211_IF_TYPE_IBSS)
++		intf->delayed_flags |= DELAYED_UPDATE_BEACON;
++
++	spin_unlock(&intf->lock);
++}
++
+ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
+ {
+-	struct interface *intf = &rt2x00dev->interface;
+ 	int retval;
+ 
+ 	NOTICE(rt2x00dev, "Waking up.\n");
+@@ -1424,6 +1292,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
+ 	 */
+ 	rt2x00debug_register(rt2x00dev);
+ 	rt2x00rfkill_resume(rt2x00dev);
++	rt2x00leds_resume(rt2x00dev);
+ 
+ 	/*
+ 	 * Only continue if mac80211 had open interfaces.
+@@ -1445,9 +1314,12 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
+ 	if (!rt2x00dev->hw->conf.radio_enabled)
+ 		rt2x00lib_disable_radio(rt2x00dev);
+ 
+-	rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
+-	rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
+-	rt2x00lib_config_type(rt2x00dev, intf->type);
++	/*
++	 * Iterator over each active interface to
++	 * reconfigure the hardware.
++	 */
++	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
++					    rt2x00lib_resume_intf, rt2x00dev);
+ 
+ 	/*
+ 	 * We are ready again to receive requests from mac80211.
+@@ -1463,12 +1335,11 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
+ 	ieee80211_start_queues(rt2x00dev->hw);
+ 
+ 	/*
+-	 * When in Master or Ad-hoc mode,
+-	 * restart Beacon transmitting by faking a beacondone event.
++	 * During interface iteration we might have changed the
++	 * delayed_flags, time to handles the event by calling
++	 * the work handler directly.
+ 	 */
+-	if (intf->type == IEEE80211_IF_TYPE_AP ||
+-	    intf->type == IEEE80211_IF_TYPE_IBSS)
+-		rt2x00lib_beacondone(rt2x00dev);
++	rt2x00lib_intf_scheduled(&rt2x00dev->intf_work);
+ 
+ 	return 0;
+ 
+diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h
+index 99f3f36..7169c22 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00dump.h
++++ b/drivers/net/wireless/rt2x00/rt2x00dump.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -93,8 +93,8 @@ enum rt2x00_dump_type {
+  * @chip_rf: RF chipset
+  * @chip_rev: Chipset revision
+  * @type: The frame type (&rt2x00_dump_type)
+- * @ring_index: The index number of the data ring.
+- * @entry_index: The index number of the entry inside the data ring.
++ * @queue_index: The index number of the data queue.
++ * @entry_index: The index number of the entry inside the data queue.
+  * @timestamp_sec: Timestamp - seconds
+  * @timestamp_usec: Timestamp - microseconds
+  */
+@@ -111,7 +111,7 @@ struct rt2x00dump_hdr {
+ 	__le32 chip_rev;
+ 
+ 	__le16 type;
+-	__u8 ring_index;
++	__u8 queue_index;
+ 	__u8 entry_index;
+ 
+ 	__le32 timestamp_sec;
+diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
+index 0a475e4..b971bc6 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
++++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -23,7 +23,6 @@
+ 	Abstract: rt2x00 firmware loading routines.
+  */
+ 
+-#include <linux/crc-itu-t.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ 
+@@ -37,7 +36,6 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
+ 	char *fw_name;
+ 	int retval;
+ 	u16 crc;
+-	u16 tmp;
+ 
+ 	/*
+ 	 * Read correct firmware from harddisk.
+@@ -63,18 +61,9 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
+ 		return -ENOENT;
+ 	}
+ 
+-	/*
+-	 * Validate the firmware using 16 bit CRC.
+-	 * The last 2 bytes of the firmware are the CRC
+-	 * so substract those 2 bytes from the CRC checksum,
+-	 * and set those 2 bytes to 0 when calculating CRC.
+-	 */
+-	tmp = 0;
+-	crc = crc_itu_t(0, fw->data, fw->size - 2);
+-	crc = crc_itu_t(crc, (u8 *)&tmp, 2);
+-
++	crc = rt2x00dev->ops->lib->get_firmware_crc(fw->data, fw->size);
+ 	if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
+-		ERROR(rt2x00dev, "Firmware CRC error.\n");
++		ERROR(rt2x00dev, "Firmware checksum error.\n");
+ 		retval = -ENOENT;
+ 		goto exit;
+ 	}
+@@ -96,6 +85,9 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
+ {
+ 	int retval;
+ 
++	if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
++		return 0;
++
+ 	if (!rt2x00dev->fw) {
+ 		retval = rt2x00lib_request_firmware(rt2x00dev);
+ 		if (retval)
+@@ -116,4 +108,3 @@ void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
+ 	release_firmware(rt2x00dev->fw);
+ 	rt2x00dev->fw = NULL;
+ }
+-
+diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
+new file mode 100644
+index 0000000..40c1f5c
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
+@@ -0,0 +1,219 @@
++/*
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
++	<http://rt2x00.serialmonkey.com>
++
++	This program is free software; you can redistribute it and/or modify
++	it under the terms of the GNU General Public License as published by
++	the Free Software Foundation; either version 2 of the License, or
++	(at your option) any later version.
++
++	This program is distributed in the hope that it will be useful,
++	but WITHOUT ANY WARRANTY; without even the implied warranty of
++	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++	GNU General Public License for more details.
++
++	You should have received a copy of the GNU General Public License
++	along with this program; if not, write to the
++	Free Software Foundation, Inc.,
++	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++	Module: rt2x00lib
++	Abstract: rt2x00 led specific routines.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include "rt2x00.h"
++#include "rt2x00lib.h"
++
++void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
++{
++	struct rt2x00_led *led = &rt2x00dev->led_qual;
++	unsigned int brightness;
++
++	if ((led->type != LED_TYPE_QUALITY) || !(led->flags & LED_REGISTERED))
++		return;
++
++	/*
++	 * Led handling requires a positive value for the rssi,
++	 * to do that correctly we need to add the correction.
++	 */
++	rssi += rt2x00dev->rssi_offset;
++
++	/*
++	 * Get the rssi level, this is used to convert the rssi
++	 * to a LED value inside the range LED_OFF - LED_FULL.
++	 */
++	if (rssi <= 30)
++		rssi = 0;
++	else if (rssi <= 39)
++		rssi = 1;
++	else if (rssi <= 49)
++		rssi = 2;
++	else if (rssi <= 53)
++		rssi = 3;
++	else if (rssi <= 63)
++		rssi = 4;
++	else
++		rssi = 5;
++
++	/*
++	 * Note that we must _not_ send LED_OFF since the driver
++	 * is going to calculate the value and might use it in a
++	 * division.
++	 */
++	brightness = ((LED_FULL / 6) * rssi) + 1;
++	if (brightness != led->led_dev.brightness) {
++		led->led_dev.brightness_set(&led->led_dev, brightness);
++		led->led_dev.brightness = brightness;
++	}
++}
++
++void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
++{
++	struct rt2x00_led *led = &rt2x00dev->led_assoc;
++	unsigned int brightness;
++
++	if ((led->type != LED_TYPE_ASSOC) || !(led->flags & LED_REGISTERED))
++		return;
++
++	brightness = enabled ? LED_FULL : LED_OFF;
++	if (brightness != led->led_dev.brightness) {
++		led->led_dev.brightness_set(&led->led_dev, brightness);
++		led->led_dev.brightness = brightness;
++	}
++}
++
++void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled)
++{
++	struct rt2x00_led *led = &rt2x00dev->led_radio;
++	unsigned int brightness;
++
++	if ((led->type != LED_TYPE_RADIO) || !(led->flags & LED_REGISTERED))
++		return;
++
++	brightness = enabled ? LED_FULL : LED_OFF;
++	if (brightness != led->led_dev.brightness) {
++		led->led_dev.brightness_set(&led->led_dev, brightness);
++		led->led_dev.brightness = brightness;
++	}
++}
++
++static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
++				   struct rt2x00_led *led,
++				   const char *name)
++{
++	struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
++	int retval;
++
++	led->led_dev.name = name;
++
++	retval = led_classdev_register(device, &led->led_dev);
++	if (retval) {
++		ERROR(rt2x00dev, "Failed to register led handler.\n");
++		return retval;
++	}
++
++	led->flags |= LED_REGISTERED;
++
++	return 0;
++}
++
++void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
++{
++	char dev_name[16];
++	char name[32];
++	int retval;
++	unsigned long on_period;
++	unsigned long off_period;
++
++	snprintf(dev_name, sizeof(dev_name), "%s-%s",
++		 rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy));
++
++	if (rt2x00dev->led_radio.flags & LED_INITIALIZED) {
++		snprintf(name, sizeof(name), "%s:radio", dev_name);
++
++		retval = rt2x00leds_register_led(rt2x00dev,
++						 &rt2x00dev->led_radio,
++						 name);
++		if (retval)
++			goto exit_fail;
++	}
++
++	if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) {
++		snprintf(name, sizeof(name), "%s:assoc", dev_name);
++
++		retval = rt2x00leds_register_led(rt2x00dev,
++						 &rt2x00dev->led_assoc,
++						 name);
++		if (retval)
++			goto exit_fail;
++	}
++
++	if (rt2x00dev->led_qual.flags & LED_INITIALIZED) {
++		snprintf(name, sizeof(name), "%s:quality", dev_name);
++
++		retval = rt2x00leds_register_led(rt2x00dev,
++						 &rt2x00dev->led_qual,
++						 name);
++		if (retval)
++			goto exit_fail;
++	}
++
++	/*
++	 * Initialize blink time to default value:
++	 * On period: 70ms
++	 * Off period: 30ms
++	 */
++	if (rt2x00dev->led_radio.led_dev.blink_set) {
++		on_period = 70;
++		off_period = 30;
++		rt2x00dev->led_radio.led_dev.blink_set(
++		    &rt2x00dev->led_radio.led_dev, &on_period, &off_period);
++	}
++
++	return;
++
++exit_fail:
++	rt2x00leds_unregister(rt2x00dev);
++}
++
++static void rt2x00leds_unregister_led(struct rt2x00_led *led)
++{
++	led_classdev_unregister(&led->led_dev);
++	led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++	led->flags &= ~LED_REGISTERED;
++}
++
++void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
++{
++	if (rt2x00dev->led_qual.flags & LED_REGISTERED)
++		rt2x00leds_unregister_led(&rt2x00dev->led_qual);
++	if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
++		rt2x00leds_unregister_led(&rt2x00dev->led_assoc);
++	if (rt2x00dev->led_radio.flags & LED_REGISTERED)
++		rt2x00leds_unregister_led(&rt2x00dev->led_radio);
++}
++
++void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
++{
++	if (rt2x00dev->led_qual.flags & LED_REGISTERED)
++		led_classdev_suspend(&rt2x00dev->led_qual.led_dev);
++	if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
++		led_classdev_suspend(&rt2x00dev->led_assoc.led_dev);
++	if (rt2x00dev->led_radio.flags & LED_REGISTERED)
++		led_classdev_suspend(&rt2x00dev->led_radio.led_dev);
++}
++
++void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
++{
++	if (rt2x00dev->led_radio.flags & LED_REGISTERED)
++		led_classdev_resume(&rt2x00dev->led_radio.led_dev);
++	if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
++		led_classdev_resume(&rt2x00dev->led_assoc.led_dev);
++	if (rt2x00dev->led_qual.flags & LED_REGISTERED)
++		led_classdev_resume(&rt2x00dev->led_qual.led_dev);
++}
+diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h
+new file mode 100644
+index 0000000..9df4a49
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00leds.h
+@@ -0,0 +1,50 @@
++/*
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
++	<http://rt2x00.serialmonkey.com>
++
++	This program is free software; you can redistribute it and/or modify
++	it under the terms of the GNU General Public License as published by
++	the Free Software Foundation; either version 2 of the License, or
++	(at your option) any later version.
++
++	This program is distributed in the hope that it will be useful,
++	but WITHOUT ANY WARRANTY; without even the implied warranty of
++	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++	GNU General Public License for more details.
++
++	You should have received a copy of the GNU General Public License
++	along with this program; if not, write to the
++	Free Software Foundation, Inc.,
++	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++	Module: rt2x00lib
++	Abstract: rt2x00 led datastructures and routines
++ */
++
++#ifndef RT2X00LEDS_H
++#define RT2X00LEDS_H
++
++enum led_type {
++	LED_TYPE_RADIO,
++	LED_TYPE_ASSOC,
++	LED_TYPE_ACTIVITY,
++	LED_TYPE_QUALITY,
++};
++
++#ifdef CONFIG_RT2X00_LIB_LEDS
++
++struct rt2x00_led {
++	struct rt2x00_dev *rt2x00dev;
++	struct led_classdev led_dev;
++
++	enum led_type type;
++	unsigned int flags;
++#define LED_INITIALIZED		( 1 << 0 )
++#define LED_REGISTERED		( 1 << 1 )
++};
++
++#endif /* CONFIG_RT2X00_LIB_LEDS */
++
++#endif /* RT2X00LEDS_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
+index ce58c65..5be32ff 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
++++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -34,6 +34,40 @@
+ #define RFKILL_POLL_INTERVAL	( 1000 )
+ 
+ /*
++ * rt2x00_rate: Per rate device information
++ */
++struct rt2x00_rate {
++	unsigned short flags;
++#define DEV_RATE_CCK			0x0001
++#define DEV_RATE_OFDM			0x0002
++#define DEV_RATE_SHORT_PREAMBLE		0x0004
++#define DEV_RATE_BASIC			0x0008
++
++	unsigned short bitrate; /* In 100kbit/s */
++	unsigned short ratemask;
++
++	unsigned short plcp;
++};
++
++extern const struct rt2x00_rate rt2x00_supported_rates[12];
++
++static inline u16 rt2x00_create_rate_hw_value(const u16 index,
++					      const u16 short_preamble)
++{
++	return (short_preamble << 8) | (index & 0xff);
++}
++
++static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
++{
++	return &rt2x00_supported_rates[hw_value & 0xff];
++}
++
++static inline int rt2x00_get_rate_preamble(const u16 hw_value)
++{
++	return (hw_value & 0xff00);
++}
++
++/*
+  * Radio control handlers.
+  */
+ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
+@@ -50,15 +84,29 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
+ /*
+  * Configuration handlers.
+  */
+-void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac);
+-void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid);
+-void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type);
++void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
++			   struct rt2x00_intf *intf,
++			   enum ieee80211_if_types type,
++			   u8 *mac, u8 *bssid);
++void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
++			  struct rt2x00_intf *intf,
++			  struct ieee80211_bss_conf *conf);
+ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 			      enum antenna rx, enum antenna tx);
+ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+ 		      struct ieee80211_conf *conf, const int force_config);
+ 
+ /*
++ * Queue handlers.
++ */
++void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev);
++void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev);
++int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev);
++void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
++int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
++void rt2x00queue_free(struct rt2x00_dev *rt2x00dev);
++
++/*
+  * Firmware handlers.
+  */
+ #ifdef CONFIG_RT2X00_LIB_FIRMWARE
+@@ -132,4 +180,48 @@ static inline void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev)
+ }
+ #endif /* CONFIG_RT2X00_LIB_RFKILL */
+ 
++/*
++ * LED handlers
++ */
++#ifdef CONFIG_RT2X00_LIB_LEDS
++void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi);
++void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled);
++void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled);
++void rt2x00leds_register(struct rt2x00_dev *rt2x00dev);
++void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev);
++void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev);
++void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev);
++#else
++static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev,
++					  int rssi)
++{
++}
++
++static inline void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev,
++					bool enabled)
++{
++}
++
++static inline void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev,
++					bool enabled)
++{
++}
++
++static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
++{
++}
++
++static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
++{
++}
++
++static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
++{
++}
++
++static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
++{
++}
++#endif /* CONFIG_RT2X00_LIB_LEDS */
++
+ #endif /* RT2X00LIB_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
+index e3f15e5..c206b50 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
++++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -30,10 +30,11 @@
+ #include "rt2x00lib.h"
+ 
+ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
+-				struct data_ring *ring,
++				struct data_queue *queue,
+ 				struct sk_buff *frag_skb,
+ 				struct ieee80211_tx_control *control)
+ {
++	struct skb_frame_desc *skbdesc;
+ 	struct sk_buff *skb;
+ 	int size;
+ 
+@@ -52,15 +53,22 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
+ 	skb_put(skb, size);
+ 
+ 	if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+-		ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id,
++		ieee80211_ctstoself_get(rt2x00dev->hw, control->vif,
+ 					frag_skb->data, frag_skb->len, control,
+ 					(struct ieee80211_cts *)(skb->data));
+ 	else
+-		ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id,
++		ieee80211_rts_get(rt2x00dev->hw, control->vif,
+ 				  frag_skb->data, frag_skb->len, control,
+ 				  (struct ieee80211_rts *)(skb->data));
+ 
+-	if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
++	/*
++	 * Initialize skb descriptor
++	 */
++	skbdesc = get_skb_frame_desc(skb);
++	memset(skbdesc, 0, sizeof(*skbdesc));
++	skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++
++	if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
+ 		WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
+ 		return NETDEV_TX_BUSY;
+ 	}
+@@ -73,7 +81,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+ 	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
+-	struct data_ring *ring;
++	struct data_queue *queue;
++	struct skb_frame_desc *skbdesc;
+ 	u16 frame_control;
+ 
+ 	/*
+@@ -88,10 +97,14 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ 	}
+ 
+ 	/*
+-	 * Determine which ring to put packet on.
++	 * Determine which queue to put packet on.
+ 	 */
+-	ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+-	if (unlikely(!ring)) {
++	if (control->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM &&
++	    test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
++		queue = rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
++	else
++		queue = rt2x00queue_get_queue(rt2x00dev, control->queue);
++	if (unlikely(!queue)) {
+ 		ERROR(rt2x00dev,
+ 		      "Attempt to send packet over invalid queue %d.\n"
+ 		      "Please file bug report to %s.\n",
+@@ -110,23 +123,29 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ 	if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
+ 	    (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
+ 			       IEEE80211_TXCTL_USE_CTS_PROTECT))) {
+-		if (rt2x00_ring_free(ring) <= 1) {
++		if (rt2x00queue_available(queue) <= 1) {
+ 			ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ 			return NETDEV_TX_BUSY;
+ 		}
+ 
+-		if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control)) {
++		if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb, control)) {
+ 			ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ 			return NETDEV_TX_BUSY;
+ 		}
+ 	}
+ 
+-	if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
++	/*
++	 * Initialize skb descriptor
++	 */
++	skbdesc = get_skb_frame_desc(skb);
++	memset(skbdesc, 0, sizeof(*skbdesc));
++
++	if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
+ 		ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ 		return NETDEV_TX_BUSY;
+ 	}
+ 
+-	if (rt2x00_ring_full(ring))
++	if (rt2x00queue_full(queue))
+ 		ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ 
+ 	if (rt2x00dev->ops->lib->kick_tx_queue)
+@@ -162,27 +181,67 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
+ 			    struct ieee80211_if_init_conf *conf)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	struct interface *intf = &rt2x00dev->interface;
+-
+-	/* FIXME: Beaconing is broken in rt2x00. */
+-	if (conf->type == IEEE80211_IF_TYPE_IBSS ||
+-	    conf->type == IEEE80211_IF_TYPE_AP) {
+-		ERROR(rt2x00dev,
+-		      "rt2x00 does not support Adhoc or Master mode");
+-		return -EOPNOTSUPP;
+-	}
++	struct rt2x00_intf *intf = vif_to_intf(conf->vif);
++	struct data_queue *queue =
++	    rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
++	struct queue_entry *entry = NULL;
++	unsigned int i;
+ 
+ 	/*
+-	 * Don't allow interfaces to be added while
+-	 * either the device has disappeared or when
+-	 * another interface is already present.
++	 * Don't allow interfaces to be added
++	 * the device has disappeared.
+ 	 */
+ 	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
+-	    is_interface_present(intf))
++	    !test_bit(DEVICE_STARTED, &rt2x00dev->flags))
++		return -ENODEV;
++
++	/*
++	 * When we don't support mixed interfaces (a combination
++	 * of sta and ap virtual interfaces) then we can only
++	 * add this interface when the rival interface count is 0.
++	 */
++	if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) &&
++	    ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) ||
++	     (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count)))
++		return -ENOBUFS;
++
++	/*
++	 * Check if we exceeded the maximum amount of supported interfaces.
++	 */
++	if ((conf->type == IEEE80211_IF_TYPE_AP &&
++	     rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) ||
++	    (conf->type != IEEE80211_IF_TYPE_AP &&
++	     rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf))
+ 		return -ENOBUFS;
+ 
+-	intf->id = conf->vif;
+-	intf->type = conf->type;
++	/*
++	 * Loop through all beacon queues to find a free
++	 * entry. Since there are as much beacon entries
++	 * as the maximum interfaces, this search shouldn't
++	 * fail.
++	 */
++	for (i = 0; i < queue->limit; i++) {
++		entry = &queue->entries[i];
++		if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
++			break;
++	}
++
++	if (unlikely(i == queue->limit))
++		return -ENOBUFS;
++
++	/*
++	 * We are now absolutely sure the interface can be created,
++	 * increase interface count and start initialization.
++	 */
++
++	if (conf->type == IEEE80211_IF_TYPE_AP)
++		rt2x00dev->intf_ap_count++;
++	else
++		rt2x00dev->intf_sta_count++;
++
++	spin_lock_init(&intf->lock);
++	intf->beacon = entry;
++
+ 	if (conf->type == IEEE80211_IF_TYPE_AP)
+ 		memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
+ 	memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
+@@ -192,8 +251,14 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
+ 	 * has been initialized. Otherwise the device can reset
+ 	 * the MAC registers.
+ 	 */
+-	rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
+-	rt2x00lib_config_type(rt2x00dev, conf->type);
++	rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL);
++
++	/*
++	 * Some filters depend on the current working mode. We can force
++	 * an update during the next configure_filter() run by mac80211 by
++	 * resetting the current packet_filter state.
++	 */
++	rt2x00dev->packet_filter = 0;
+ 
+ 	return 0;
+ }
+@@ -203,7 +268,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
+ 				struct ieee80211_if_init_conf *conf)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	struct interface *intf = &rt2x00dev->interface;
++	struct rt2x00_intf *intf = vif_to_intf(conf->vif);
+ 
+ 	/*
+ 	 * Don't allow interfaces to be remove while
+@@ -211,21 +276,27 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
+ 	 * no interface is present.
+ 	 */
+ 	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
+-	    !is_interface_present(intf))
++	    (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) ||
++	    (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count))
+ 		return;
+ 
+-	intf->id = 0;
+-	intf->type = IEEE80211_IF_TYPE_INVALID;
+-	memset(&intf->bssid, 0x00, ETH_ALEN);
+-	memset(&intf->mac, 0x00, ETH_ALEN);
++	if (conf->type == IEEE80211_IF_TYPE_AP)
++		rt2x00dev->intf_ap_count--;
++	else
++		rt2x00dev->intf_sta_count--;
++
++	/*
++	 * Release beacon entry so it is available for
++	 * new interfaces again.
++	 */
++	__clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
+ 
+ 	/*
+ 	 * Make sure the bssid and mac address registers
+ 	 * are cleared to prevent false ACKing of frames.
+ 	 */
+-	rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
+-	rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
+-	rt2x00lib_config_type(rt2x00dev, intf->type);
++	rt2x00lib_config_intf(rt2x00dev, intf,
++			      IEEE80211_IF_TYPE_INVALID, NULL, NULL);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
+ 
+@@ -270,7 +341,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ 			       struct ieee80211_if_conf *conf)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	struct interface *intf = &rt2x00dev->interface;
++	struct rt2x00_intf *intf = vif_to_intf(vif);
+ 	int status;
+ 
+ 	/*
+@@ -280,12 +351,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ 	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
+ 		return 0;
+ 
+-	/*
+-	 * If the given type does not match the configured type,
+-	 * there has been a problem.
+-	 */
+-	if (conf->type != intf->type)
+-		return -EINVAL;
++	spin_lock(&intf->lock);
+ 
+ 	/*
+ 	 * If the interface does not work in master mode,
+@@ -294,7 +360,16 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ 	 */
+ 	if (conf->type != IEEE80211_IF_TYPE_AP)
+ 		memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
+-	rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
++
++	spin_unlock(&intf->lock);
++
++	/*
++	 * Call rt2x00_config_intf() outside of the spinlock context since
++	 * the call will sleep for USB drivers. By using the ieee80211_if_conf
++	 * values as arguments we make keep access to rt2x00_intf thread safe
++	 * even without the lock.
++	 */
++	rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid);
+ 
+ 	/*
+ 	 * We only need to initialize the beacon when master mode is enabled.
+@@ -312,6 +387,50 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ }
+ EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);
+ 
++void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
++				unsigned int changed_flags,
++				unsigned int *total_flags,
++				int mc_count, struct dev_addr_list *mc_list)
++{
++	struct rt2x00_dev *rt2x00dev = hw->priv;
++
++	/*
++	 * Mask off any flags we are going to ignore
++	 * from the total_flags field.
++	 */
++	*total_flags &=
++	    FIF_ALLMULTI |
++	    FIF_FCSFAIL |
++	    FIF_PLCPFAIL |
++	    FIF_CONTROL |
++	    FIF_OTHER_BSS |
++	    FIF_PROMISC_IN_BSS;
++
++	/*
++	 * Apply some rules to the filters:
++	 * - Some filters imply different filters to be set.
++	 * - Some things we can't filter out at all.
++	 * - Multicast filter seems to kill broadcast traffic so never use it.
++	 */
++	*total_flags |= FIF_ALLMULTI;
++	if (*total_flags & FIF_OTHER_BSS ||
++	    *total_flags & FIF_PROMISC_IN_BSS)
++		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
++
++	/*
++	 * Check if there is any work left for us.
++	 */
++	if (rt2x00dev->packet_filter == *total_flags)
++		return;
++	rt2x00dev->packet_filter = *total_flags;
++
++	if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
++		rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
++	else
++		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
++}
++EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
++
+ int rt2x00mac_get_stats(struct ieee80211_hw *hw,
+ 			struct ieee80211_low_level_stats *stats)
+ {
+@@ -334,9 +453,11 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+ 	unsigned int i;
+ 
+-	for (i = 0; i < hw->queues; i++)
+-		memcpy(&stats->data[i], &rt2x00dev->tx[i].stats,
+-		       sizeof(rt2x00dev->tx[i].stats));
++	for (i = 0; i < hw->queues; i++) {
++		stats->data[i].len = rt2x00dev->tx[i].length;
++		stats->data[i].limit = rt2x00dev->tx[i].limit;
++		stats->data[i].count = rt2x00dev->tx[i].count;
++	}
+ 
+ 	return 0;
+ }
+@@ -348,71 +469,83 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
+ 				u32 changes)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	int short_preamble;
+-	int ack_timeout;
+-	int ack_consume_time;
+-	int difs;
+-	int preamble;
++	struct rt2x00_intf *intf = vif_to_intf(vif);
++	unsigned int delayed = 0;
+ 
+ 	/*
+-	 * We only support changing preamble mode.
++	 * When the association status has changed we must reset the link
++	 * tuner counter. This is because some drivers determine if they
++	 * should perform link tuning based on the number of seconds
++	 * while associated or not associated.
+ 	 */
+-	if (!(changes & BSS_CHANGED_ERP_PREAMBLE))
+-		return;
+-
+-	short_preamble = bss_conf->use_short_preamble;
+-	preamble = bss_conf->use_short_preamble ?
+-				SHORT_PREAMBLE : PREAMBLE;
++	if (changes & BSS_CHANGED_ASSOC) {
++		rt2x00dev->link.count = 0;
+ 
+-	difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
+-		SHORT_DIFS : DIFS;
+-	ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10);
++		if (bss_conf->assoc)
++			rt2x00dev->intf_associated++;
++		else
++			rt2x00dev->intf_associated--;
+ 
+-	ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
++		if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
++			rt2x00leds_led_assoc(rt2x00dev,
++					     !!rt2x00dev->intf_associated);
++		else
++			delayed |= DELAYED_LED_ASSOC;
++	}
+ 
+-	if (short_preamble)
+-		__set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+-	else
+-		__clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
++	/*
++	 * When the erp information has changed, we should perform
++	 * additional configuration steps. For all other changes we are done.
++	 */
++	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
++		if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
++			rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
++		else
++			delayed |= DELAYED_CONFIG_ERP;
++	}
+ 
+-	rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble,
+-					     ack_timeout, ack_consume_time);
++	spin_lock(&intf->lock);
++	memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
++	if (delayed) {
++		intf->delayed_flags |= delayed;
++		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
++	}
++	spin_unlock(&intf->lock);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
+ 
+-int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
++int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue_idx,
+ 		      const struct ieee80211_tx_queue_params *params)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	struct data_ring *ring;
++	struct data_queue *queue;
+ 
+-	ring = rt2x00lib_get_ring(rt2x00dev, queue);
+-	if (unlikely(!ring))
++	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
++	if (unlikely(!queue))
+ 		return -EINVAL;
+ 
+ 	/*
+ 	 * The passed variables are stored as real value ((2^n)-1).
+ 	 * Ralink registers require to know the bit number 'n'.
+ 	 */
+-	if (params->cw_min)
+-		ring->tx_params.cw_min = fls(params->cw_min);
++	if (params->cw_min > 0)
++		queue->cw_min = fls(params->cw_min);
+ 	else
+-		ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
++		queue->cw_min = 5; /* cw_min: 2^5 = 32. */
+ 
+-	if (params->cw_max)
+-		ring->tx_params.cw_max = fls(params->cw_max);
++	if (params->cw_max > 0)
++		queue->cw_max = fls(params->cw_max);
+ 	else
+-		ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
++		queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
+ 
+-	if (params->aifs)
+-		ring->tx_params.aifs = params->aifs;
++	if (params->aifs >= 0)
++		queue->aifs = params->aifs;
+ 	else
+-		ring->tx_params.aifs = 2;
++		queue->aifs = 2;
+ 
+ 	INFO(rt2x00dev,
+-	     "Configured TX ring %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
+-	     queue, ring->tx_params.cw_min, ring->tx_params.cw_max,
+-	     ring->tx_params.aifs);
++	     "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
++	     queue_idx, queue->cw_min, queue->cw_max, queue->aifs);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
+index 804a998..7867ec6 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -32,64 +32,21 @@
+ #include "rt2x00pci.h"
+ 
+ /*
+- * Beacon handlers.
+- */
+-int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+-			    struct ieee80211_tx_control *control)
+-{
+-	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	struct skb_desc *desc;
+-	struct data_ring *ring;
+-	struct data_entry *entry;
+-
+-	/*
+-	 * Just in case mac80211 doesn't set this correctly,
+-	 * but we need this queue set for the descriptor
+-	 * initialization.
+-	 */
+-	control->queue = IEEE80211_TX_QUEUE_BEACON;
+-	ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+-	entry = rt2x00_get_data_entry(ring);
+-
+-	/*
+-	 * Fill in skb descriptor
+-	 */
+-	desc = get_skb_desc(skb);
+-	desc->desc_len = ring->desc_size;
+-	desc->data_len = skb->len;
+-	desc->desc = entry->priv;
+-	desc->data = skb->data;
+-	desc->ring = ring;
+-	desc->entry = entry;
+-
+-	memcpy(entry->data_addr, skb->data, skb->len);
+-	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+-
+-	/*
+-	 * Enable beacon generation.
+-	 */
+-	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update);
+-
+-/*
+  * TX data handlers.
+  */
+ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
+-			    struct data_ring *ring, struct sk_buff *skb,
++			    struct data_queue *queue, struct sk_buff *skb,
+ 			    struct ieee80211_tx_control *control)
+ {
+-	struct data_entry *entry = rt2x00_get_data_entry(ring);
+-	__le32 *txd = entry->priv;
+-	struct skb_desc *desc;
++	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
++	struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
++	struct skb_frame_desc *skbdesc;
+ 	u32 word;
+ 
+-	if (rt2x00_ring_full(ring))
++	if (rt2x00queue_full(queue))
+ 		return -EINVAL;
+ 
+-	rt2x00_desc_read(txd, 0, &word);
++	rt2x00_desc_read(priv_tx->desc, 0, &word);
+ 
+ 	if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) ||
+ 	    rt2x00_get_field32(word, TXD_ENTRY_VALID)) {
+@@ -103,18 +60,18 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ 	/*
+ 	 * Fill in skb descriptor
+ 	 */
+-	desc = get_skb_desc(skb);
+-	desc->desc_len = ring->desc_size;
+-	desc->data_len = skb->len;
+-	desc->desc = entry->priv;
+-	desc->data = skb->data;
+-	desc->ring = ring;
+-	desc->entry = entry;
+-
+-	memcpy(entry->data_addr, skb->data, skb->len);
++	skbdesc = get_skb_frame_desc(skb);
++	skbdesc->data = skb->data;
++	skbdesc->data_len = skb->len;
++	skbdesc->desc = priv_tx->desc;
++	skbdesc->desc_len = queue->desc_size;
++	skbdesc->entry = entry;
++
++	memcpy(&priv_tx->control, control, sizeof(priv_tx->control));
++	memcpy(priv_tx->data, skb->data, skb->len);
+ 	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+ 
+-	rt2x00_ring_index_inc(ring);
++	rt2x00queue_index_inc(queue, Q_INDEX);
+ 
+ 	return 0;
+ }
+@@ -125,29 +82,28 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
+  */
+ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+ {
+-	struct data_ring *ring = rt2x00dev->rx;
+-	struct data_entry *entry;
+-	struct sk_buff *skb;
++	struct data_queue *queue = rt2x00dev->rx;
++	struct queue_entry *entry;
++	struct queue_entry_priv_pci_rx *priv_rx;
+ 	struct ieee80211_hdr *hdr;
+-	struct skb_desc *skbdesc;
+-	struct rxdata_entry_desc desc;
++	struct skb_frame_desc *skbdesc;
++	struct rxdone_entry_desc rxdesc;
+ 	int header_size;
+-	__le32 *rxd;
+ 	int align;
+ 	u32 word;
+ 
+ 	while (1) {
+-		entry = rt2x00_get_data_entry(ring);
+-		rxd = entry->priv;
+-		rt2x00_desc_read(rxd, 0, &word);
++		entry = rt2x00queue_get_entry(queue, Q_INDEX);
++		priv_rx = entry->priv_data;
++		rt2x00_desc_read(priv_rx->desc, 0, &word);
+ 
+ 		if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
+ 			break;
+ 
+-		memset(&desc, 0, sizeof(desc));
+-		rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
++		memset(&rxdesc, 0, sizeof(rxdesc));
++		rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
+ 
+-		hdr = (struct ieee80211_hdr *)entry->data_addr;
++		hdr = (struct ieee80211_hdr *)priv_rx->data;
+ 		header_size =
+ 		    ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+ 
+@@ -161,66 +117,68 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+ 		 * Allocate the sk_buffer, initialize it and copy
+ 		 * all data into it.
+ 		 */
+-		skb = dev_alloc_skb(desc.size + align);
+-		if (!skb)
++		entry->skb = dev_alloc_skb(rxdesc.size + align);
++		if (!entry->skb)
+ 			return;
+ 
+-		skb_reserve(skb, align);
+-		memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
++		skb_reserve(entry->skb, align);
++		memcpy(skb_put(entry->skb, rxdesc.size),
++		       priv_rx->data, rxdesc.size);
+ 
+ 		/*
+ 		 * Fill in skb descriptor
+ 		 */
+-		skbdesc = get_skb_desc(skb);
+-		skbdesc->desc_len = entry->ring->desc_size;
+-		skbdesc->data_len = skb->len;
+-		skbdesc->desc = entry->priv;
+-		skbdesc->data = skb->data;
+-		skbdesc->ring = ring;
++		skbdesc = get_skb_frame_desc(entry->skb);
++		memset(skbdesc, 0, sizeof(*skbdesc));
++		skbdesc->data = entry->skb->data;
++		skbdesc->data_len = entry->skb->len;
++		skbdesc->desc = priv_rx->desc;
++		skbdesc->desc_len = queue->desc_size;
+ 		skbdesc->entry = entry;
+ 
+ 		/*
+ 		 * Send the frame to rt2x00lib for further processing.
+ 		 */
+-		rt2x00lib_rxdone(entry, skb, &desc);
++		rt2x00lib_rxdone(entry, &rxdesc);
+ 
+-		if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
++		if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) {
+ 			rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1);
+-			rt2x00_desc_write(rxd, 0, word);
++			rt2x00_desc_write(priv_rx->desc, 0, word);
+ 		}
+ 
+-		rt2x00_ring_index_inc(ring);
++		rt2x00queue_index_inc(queue, Q_INDEX);
+ 	}
+ }
+ EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
+ 
+-void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
+-		      const int tx_status, const int retry)
++void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
++		      struct txdone_entry_desc *txdesc)
+ {
++	struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
+ 	u32 word;
+ 
+-	rt2x00lib_txdone(entry, tx_status, retry);
++	txdesc->control = &priv_tx->control;
++	rt2x00lib_txdone(entry, txdesc);
+ 
+ 	/*
+ 	 * Make this entry available for reuse.
+ 	 */
+ 	entry->flags = 0;
+ 
+-	rt2x00_desc_read(entry->priv, 0, &word);
++	rt2x00_desc_read(priv_tx->desc, 0, &word);
+ 	rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0);
+ 	rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0);
+-	rt2x00_desc_write(entry->priv, 0, word);
++	rt2x00_desc_write(priv_tx->desc, 0, word);
+ 
+-	rt2x00_ring_index_done_inc(entry->ring);
++	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+ 
+ 	/*
+-	 * If the data ring was full before the txdone handler
++	 * If the data queue was full before the txdone handler
+ 	 * we must make sure the packet queue in the mac80211 stack
+ 	 * is reenabled when the txdone handler has finished.
+ 	 */
+-	if (!rt2x00_ring_full(entry->ring))
+-		ieee80211_wake_queue(rt2x00dev->hw,
+-				     entry->tx_status.control.queue);
++	if (!rt2x00queue_full(entry->queue))
++		ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue);
+ 
+ }
+ EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
+@@ -228,73 +186,122 @@ EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
+ /*
+  * Device initialization handlers.
+  */
+-#define priv_offset(__ring, __i)				\
+-({								\
+-	ring->data_addr + (i * ring->desc_size);		\
++#define desc_size(__queue)			\
++({						\
++	 ((__queue)->limit * (__queue)->desc_size);\
++})
++
++#define data_size(__queue)			\
++({						\
++	 ((__queue)->limit * (__queue)->data_size);\
+ })
+ 
+-#define data_addr_offset(__ring, __i)				\
+-({								\
+-	(__ring)->data_addr +					\
+-	    ((__ring)->stats.limit * (__ring)->desc_size) +	\
+-	    ((__i) * (__ring)->data_size);			\
++#define dma_size(__queue)			\
++({						\
++	data_size(__queue) + desc_size(__queue);\
+ })
+ 
+-#define data_dma_offset(__ring, __i)				\
+-({								\
+-	(__ring)->data_dma +					\
+-	    ((__ring)->stats.limit * (__ring)->desc_size) +	\
+-	    ((__i) * (__ring)->data_size);			\
++#define desc_offset(__queue, __base, __i)	\
++({						\
++	(__base) + data_size(__queue) + 	\
++	    ((__i) * (__queue)->desc_size);	\
+ })
+ 
+-static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev,
+-			       struct data_ring *ring)
++#define data_offset(__queue, __base, __i)	\
++({						\
++	(__base) +				\
++	    ((__i) * (__queue)->data_size);	\
++})
++
++static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
++				     struct data_queue *queue)
+ {
++	struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
++	struct queue_entry_priv_pci_rx *priv_rx;
++	struct queue_entry_priv_pci_tx *priv_tx;
++	void *addr;
++	dma_addr_t dma;
++	void *desc_addr;
++	dma_addr_t desc_dma;
++	void *data_addr;
++	dma_addr_t data_dma;
+ 	unsigned int i;
+ 
+ 	/*
+ 	 * Allocate DMA memory for descriptor and buffer.
+ 	 */
+-	ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev),
+-					       rt2x00_get_ring_size(ring),
+-					       &ring->data_dma);
+-	if (!ring->data_addr)
++	addr = pci_alloc_consistent(pci_dev, dma_size(queue), &dma);
++	if (!addr)
+ 		return -ENOMEM;
+ 
++	memset(addr, 0, dma_size(queue));
++
+ 	/*
+-	 * Initialize all ring entries to contain valid
+-	 * addresses.
++	 * Initialize all queue entries to contain valid addresses.
+ 	 */
+-	for (i = 0; i < ring->stats.limit; i++) {
+-		ring->entry[i].priv = priv_offset(ring, i);
+-		ring->entry[i].data_addr = data_addr_offset(ring, i);
+-		ring->entry[i].data_dma = data_dma_offset(ring, i);
++	for (i = 0; i < queue->limit; i++) {
++		desc_addr = desc_offset(queue, addr, i);
++		desc_dma = desc_offset(queue, dma, i);
++		data_addr = data_offset(queue, addr, i);
++		data_dma = data_offset(queue, dma, i);
++
++		if (queue->qid == QID_RX) {
++			priv_rx = queue->entries[i].priv_data;
++			priv_rx->desc = desc_addr;
++			priv_rx->desc_dma = desc_dma;
++			priv_rx->data = data_addr;
++			priv_rx->data_dma = data_dma;
++		} else {
++			priv_tx = queue->entries[i].priv_data;
++			priv_tx->desc = desc_addr;
++			priv_tx->desc_dma = desc_dma;
++			priv_tx->data = data_addr;
++			priv_tx->data_dma = data_dma;
++		}
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev,
+-			       struct data_ring *ring)
++static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
++				     struct data_queue *queue)
+ {
+-	if (ring->data_addr)
+-		pci_free_consistent(rt2x00dev_pci(rt2x00dev),
+-				    rt2x00_get_ring_size(ring),
+-				    ring->data_addr, ring->data_dma);
+-	ring->data_addr = NULL;
++	struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
++	struct queue_entry_priv_pci_rx *priv_rx;
++	struct queue_entry_priv_pci_tx *priv_tx;
++	void *data_addr;
++	dma_addr_t data_dma;
++
++	if (queue->qid == QID_RX) {
++		priv_rx = queue->entries[0].priv_data;
++		data_addr = priv_rx->data;
++		data_dma = priv_rx->data_dma;
++
++		priv_rx->data = NULL;
++	} else {
++		priv_tx = queue->entries[0].priv_data;
++		data_addr = priv_tx->data;
++		data_dma = priv_tx->data_dma;
++
++		priv_tx->data = NULL;
++	}
++
++	if (data_addr)
++		pci_free_consistent(pci_dev, dma_size(queue),
++				    data_addr, data_dma);
+ }
+ 
+ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
+ {
+ 	struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
+-	struct data_ring *ring;
++	struct data_queue *queue;
+ 	int status;
+ 
+ 	/*
+ 	 * Allocate DMA
+ 	 */
+-	ring_for_each(rt2x00dev, ring) {
+-		status = rt2x00pci_alloc_dma(rt2x00dev, ring);
++	queue_for_each(rt2x00dev, queue) {
++		status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
+ 		if (status)
+ 			goto exit;
+ 	}
+@@ -321,7 +328,7 @@ EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
+ 
+ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
+ {
+-	struct data_ring *ring;
++	struct data_queue *queue;
+ 
+ 	/*
+ 	 * Free irq line.
+@@ -331,8 +338,8 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Free DMA
+ 	 */
+-	ring_for_each(rt2x00dev, ring)
+-		rt2x00pci_free_dma(rt2x00dev, ring);
++	queue_for_each(rt2x00dev, queue)
++		rt2x00pci_free_queue_dma(rt2x00dev, queue);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
+ 
+@@ -347,9 +354,9 @@ static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
+ 	kfree(rt2x00dev->eeprom);
+ 	rt2x00dev->eeprom = NULL;
+ 
+-	if (rt2x00dev->csr_addr) {
+-		iounmap(rt2x00dev->csr_addr);
+-		rt2x00dev->csr_addr = NULL;
++	if (rt2x00dev->csr.base) {
++		iounmap(rt2x00dev->csr.base);
++		rt2x00dev->csr.base = NULL;
+ 	}
+ }
+ 
+@@ -357,9 +364,9 @@ static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
+ {
+ 	struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
+ 
+-	rt2x00dev->csr_addr = ioremap(pci_resource_start(pci_dev, 0),
++	rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0),
+ 				      pci_resource_len(pci_dev, 0));
+-	if (!rt2x00dev->csr_addr)
++	if (!rt2x00dev->csr.base)
+ 		goto exit;
+ 
+ 	rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
+@@ -530,5 +537,5 @@ EXPORT_SYMBOL_GPL(rt2x00pci_resume);
+  */
+ MODULE_AUTHOR(DRV_PROJECT);
+ MODULE_VERSION(DRV_VERSION);
+-MODULE_DESCRIPTION("rt2x00 library");
++MODULE_DESCRIPTION("rt2x00 pci library");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
+index 2d1eb81..9d1cdb9 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
++++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -61,7 +61,7 @@ static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
+ 					   const unsigned long offset,
+ 					   u32 *value)
+ {
+-	*value = readl(rt2x00dev->csr_addr + offset);
++	*value = readl(rt2x00dev->csr.base + offset);
+ }
+ 
+ static inline void
+@@ -69,14 +69,14 @@ rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
+ 			     const unsigned long offset,
+ 			     void *value, const u16 length)
+ {
+-	memcpy_fromio(value, rt2x00dev->csr_addr + offset, length);
++	memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
+ }
+ 
+ static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
+ 					    const unsigned long offset,
+ 					    u32 value)
+ {
+-	writel(value, rt2x00dev->csr_addr + offset);
++	writel(value, rt2x00dev->csr.base + offset);
+ }
+ 
+ static inline void
+@@ -84,28 +84,63 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+ 			      const unsigned long offset,
+ 			      void *value, const u16 length)
+ {
+-	memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
++	memcpy_toio(rt2x00dev->csr.base + offset, value, length);
+ }
+ 
+ /*
+- * Beacon handlers.
+- */
+-int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+-			    struct ieee80211_tx_control *control);
+-
+-/*
+  * TX data handlers.
+  */
+ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
+-			    struct data_ring *ring, struct sk_buff *skb,
++			    struct data_queue *queue, struct sk_buff *skb,
+ 			    struct ieee80211_tx_control *control);
+ 
+-/*
+- * RX/TX data handlers.
++/**
++ * struct queue_entry_priv_pci_rx: Per RX entry PCI specific information
++ *
++ * @desc: Pointer to device descriptor.
++ * @data: Pointer to device's entry memory.
++ * @dma: DMA pointer to &data.
++ */
++struct queue_entry_priv_pci_rx {
++	__le32 *desc;
++	dma_addr_t desc_dma;
++
++	void *data;
++	dma_addr_t data_dma;
++};
++
++/**
++ * struct queue_entry_priv_pci_tx: Per TX entry PCI specific information
++ *
++ * @desc: Pointer to device descriptor
++ * @data: Pointer to device's entry memory.
++ * @dma: DMA pointer to &data.
++ * @control: mac80211 control structure used to transmit data.
++ */
++struct queue_entry_priv_pci_tx {
++	__le32 *desc;
++	dma_addr_t desc_dma;
++
++	void *data;
++	dma_addr_t data_dma;
++
++	struct ieee80211_tx_control control;
++};
++
++/**
++ * rt2x00pci_rxdone - Handle RX done events
++ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+  */
+ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+-void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
+-		      const int tx_status, const int retry);
++
++/**
++ * rt2x00pci_txdone - Handle TX done events
++ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
++ * @entry: Entry which has completed the transmission of a frame.
++ * @desc: TX done descriptor
++ */
++void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
++		      struct txdone_entry_desc *desc);
+ 
+ /*
+  * Device initialization handlers.
+diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
+new file mode 100644
+index 0000000..659e9f4
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -0,0 +1,304 @@
++/*
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
++	<http://rt2x00.serialmonkey.com>
++
++	This program is free software; you can redistribute it and/or modify
++	it under the terms of the GNU General Public License as published by
++	the Free Software Foundation; either version 2 of the License, or
++	(at your option) any later version.
++
++	This program is distributed in the hope that it will be useful,
++	but WITHOUT ANY WARRANTY; without even the implied warranty of
++	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++	GNU General Public License for more details.
++
++	You should have received a copy of the GNU General Public License
++	along with this program; if not, write to the
++	Free Software Foundation, Inc.,
++	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++	Module: rt2x00lib
++	Abstract: rt2x00 queue specific routines.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include "rt2x00.h"
++#include "rt2x00lib.h"
++
++struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
++					 const unsigned int queue)
++{
++	int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
++
++	if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
++		return &rt2x00dev->tx[queue];
++
++	if (!rt2x00dev->bcn)
++		return NULL;
++
++	if (queue == RT2X00_BCN_QUEUE_BEACON)
++		return &rt2x00dev->bcn[0];
++	else if (queue == RT2X00_BCN_QUEUE_ATIM && atim)
++		return &rt2x00dev->bcn[1];
++
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(rt2x00queue_get_queue);
++
++struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
++					  enum queue_index index)
++{
++	struct queue_entry *entry;
++	unsigned long irqflags;
++
++	if (unlikely(index >= Q_INDEX_MAX)) {
++		ERROR(queue->rt2x00dev,
++		      "Entry requested from invalid index type (%d)\n", index);
++		return NULL;
++	}
++
++	spin_lock_irqsave(&queue->lock, irqflags);
++
++	entry = &queue->entries[queue->index[index]];
++
++	spin_unlock_irqrestore(&queue->lock, irqflags);
++
++	return entry;
++}
++EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
++
++void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
++{
++	unsigned long irqflags;
++
++	if (unlikely(index >= Q_INDEX_MAX)) {
++		ERROR(queue->rt2x00dev,
++		      "Index change on invalid index type (%d)\n", index);
++		return;
++	}
++
++	spin_lock_irqsave(&queue->lock, irqflags);
++
++	queue->index[index]++;
++	if (queue->index[index] >= queue->limit)
++		queue->index[index] = 0;
++
++	if (index == Q_INDEX) {
++		queue->length++;
++	} else if (index == Q_INDEX_DONE) {
++		queue->length--;
++		queue->count ++;
++	}
++
++	spin_unlock_irqrestore(&queue->lock, irqflags);
++}
++EXPORT_SYMBOL_GPL(rt2x00queue_index_inc);
++
++static void rt2x00queue_reset(struct data_queue *queue)
++{
++	unsigned long irqflags;
++
++	spin_lock_irqsave(&queue->lock, irqflags);
++
++	queue->count = 0;
++	queue->length = 0;
++	memset(queue->index, 0, sizeof(queue->index));
++
++	spin_unlock_irqrestore(&queue->lock, irqflags);
++}
++
++void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev)
++{
++	struct data_queue *queue = rt2x00dev->rx;
++	unsigned int i;
++
++	rt2x00queue_reset(queue);
++
++	if (!rt2x00dev->ops->lib->init_rxentry)
++		return;
++
++	for (i = 0; i < queue->limit; i++)
++		rt2x00dev->ops->lib->init_rxentry(rt2x00dev,
++						  &queue->entries[i]);
++}
++
++void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev)
++{
++	struct data_queue *queue;
++	unsigned int i;
++
++	txall_queue_for_each(rt2x00dev, queue) {
++		rt2x00queue_reset(queue);
++
++		if (!rt2x00dev->ops->lib->init_txentry)
++			continue;
++
++		for (i = 0; i < queue->limit; i++)
++			rt2x00dev->ops->lib->init_txentry(rt2x00dev,
++							  &queue->entries[i]);
++	}
++}
++
++static int rt2x00queue_alloc_entries(struct data_queue *queue,
++				     const struct data_queue_desc *qdesc)
++{
++	struct queue_entry *entries;
++	unsigned int entry_size;
++	unsigned int i;
++
++	rt2x00queue_reset(queue);
++
++	queue->limit = qdesc->entry_num;
++	queue->data_size = qdesc->data_size;
++	queue->desc_size = qdesc->desc_size;
++
++	/*
++	 * Allocate all queue entries.
++	 */
++	entry_size = sizeof(*entries) + qdesc->priv_size;
++	entries = kzalloc(queue->limit * entry_size, GFP_KERNEL);
++	if (!entries)
++		return -ENOMEM;
++
++#define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \
++	( ((char *)(__base)) + ((__limit) * (__esize)) + \
++	    ((__index) * (__psize)) )
++
++	for (i = 0; i < queue->limit; i++) {
++		entries[i].flags = 0;
++		entries[i].queue = queue;
++		entries[i].skb = NULL;
++		entries[i].entry_idx = i;
++		entries[i].priv_data =
++		    QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit,
++					    sizeof(*entries), qdesc->priv_size);
++	}
++
++#undef QUEUE_ENTRY_PRIV_OFFSET
++
++	queue->entries = entries;
++
++	return 0;
++}
++
++int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
++{
++	struct data_queue *queue;
++	int status;
++
++
++	status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx);
++	if (status)
++		goto exit;
++
++	tx_queue_for_each(rt2x00dev, queue) {
++		status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx);
++		if (status)
++			goto exit;
++	}
++
++	status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn);
++	if (status)
++		goto exit;
++
++	if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
++		return 0;
++
++	status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1],
++					   rt2x00dev->ops->atim);
++	if (status)
++		goto exit;
++
++	return 0;
++
++exit:
++	ERROR(rt2x00dev, "Queue entries allocation failed.\n");
++
++	rt2x00queue_uninitialize(rt2x00dev);
++
++	return status;
++}
++
++void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)
++{
++	struct data_queue *queue;
++
++	queue_for_each(rt2x00dev, queue) {
++		kfree(queue->entries);
++		queue->entries = NULL;
++	}
++}
++
++static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
++			     struct data_queue *queue, enum data_queue_qid qid)
++{
++	spin_lock_init(&queue->lock);
++
++	queue->rt2x00dev = rt2x00dev;
++	queue->qid = qid;
++	queue->aifs = 2;
++	queue->cw_min = 5;
++	queue->cw_max = 10;
++}
++
++int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
++{
++	struct data_queue *queue;
++	enum data_queue_qid qid;
++	unsigned int req_atim =
++	    !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
++
++	/*
++	 * We need the following queues:
++	 * RX: 1
++	 * TX: hw->queues
++	 * Beacon: 1
++	 * Atim: 1 (if required)
++	 */
++	rt2x00dev->data_queues = 2 + rt2x00dev->hw->queues + req_atim;
++
++	queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL);
++	if (!queue) {
++		ERROR(rt2x00dev, "Queue allocation failed.\n");
++		return -ENOMEM;
++	}
++
++	/*
++	 * Initialize pointers
++	 */
++	rt2x00dev->rx = queue;
++	rt2x00dev->tx = &queue[1];
++	rt2x00dev->bcn = &queue[1 + rt2x00dev->hw->queues];
++
++	/*
++	 * Initialize queue parameters.
++	 * RX: qid = QID_RX
++	 * TX: qid = QID_AC_BE + index
++	 * TX: cw_min: 2^5 = 32.
++	 * TX: cw_max: 2^10 = 1024.
++	 * BCN & Atim: qid = QID_MGMT
++	 */
++	rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX);
++
++	qid = QID_AC_BE;
++	tx_queue_for_each(rt2x00dev, queue)
++		rt2x00queue_init(rt2x00dev, queue, qid++);
++
++	rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_MGMT);
++	if (req_atim)
++		rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_MGMT);
++
++	return 0;
++}
++
++void rt2x00queue_free(struct rt2x00_dev *rt2x00dev)
++{
++	kfree(rt2x00dev->rx);
++	rt2x00dev->rx = NULL;
++	rt2x00dev->tx = NULL;
++	rt2x00dev->bcn = NULL;
++}
+diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
+new file mode 100644
+index 0000000..7027c9f
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
+@@ -0,0 +1,468 @@
++/*
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
++	<http://rt2x00.serialmonkey.com>
++
++	This program is free software; you can redistribute it and/or modify
++	it under the terms of the GNU General Public License as published by
++	the Free Software Foundation; either version 2 of the License, or
++	(at your option) any later version.
++
++	This program is distributed in the hope that it will be useful,
++	but WITHOUT ANY WARRANTY; without even the implied warranty of
++	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++	GNU General Public License for more details.
++
++	You should have received a copy of the GNU General Public License
++	along with this program; if not, write to the
++	Free Software Foundation, Inc.,
++	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++	Module: rt2x00
++	Abstract: rt2x00 queue datastructures and routines
++ */
++
++#ifndef RT2X00QUEUE_H
++#define RT2X00QUEUE_H
++
++#include <linux/prefetch.h>
++
++/**
++ * DOC: Entrie frame size
++ *
++ * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes,
++ * for USB devices this restriction does not apply, but the value of
++ * 2432 makes sense since it is big enough to contain the maximum fragment
++ * size according to the ieee802.11 specs.
++ */
++#define DATA_FRAME_SIZE	2432
++#define MGMT_FRAME_SIZE	256
++
++/**
++ * DOC: Number of entries per queue
++ *
++ * After research it was concluded that 12 entries in a RX and TX
++ * queue would be sufficient. Although this is almost one third of
++ * the amount the legacy driver allocated, the queues aren't getting
++ * filled to the maximum even when working with the maximum rate.
++ */
++#define RX_ENTRIES	12
++#define TX_ENTRIES	12
++#define BEACON_ENTRIES	1
++#define ATIM_ENTRIES	1
++
++/**
++ * enum data_queue_qid: Queue identification
++ */
++enum data_queue_qid {
++	QID_AC_BE = 0,
++	QID_AC_BK = 1,
++	QID_AC_VI = 2,
++	QID_AC_VO = 3,
++	QID_HCCA = 4,
++	QID_MGMT = 13,
++	QID_RX = 14,
++	QID_OTHER = 15,
++};
++
++/**
++ * enum rt2x00_bcn_queue: Beacon queue index
++ *
++ * Start counting with a high offset, this because this enumeration
++ * supplements &enum ieee80211_tx_queue and we should prevent value
++ * conflicts.
++ *
++ * @RT2X00_BCN_QUEUE_BEACON: Beacon queue
++ * @RT2X00_BCN_QUEUE_ATIM: Atim queue (sends frame after beacon)
++ */
++enum rt2x00_bcn_queue {
++	RT2X00_BCN_QUEUE_BEACON = 100,
++	RT2X00_BCN_QUEUE_ATIM = 101,
++};
++
++/**
++ * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc
++ *
++ * @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver
++ *	and should not be reported back to mac80211 during txdone.
++ */
++enum skb_frame_desc_flags {
++	FRAME_DESC_DRIVER_GENERATED = 1 << 0,
++};
++
++/**
++ * struct skb_frame_desc: Descriptor information for the skb buffer
++ *
++ * This structure is placed over the skb->cb array, this means that
++ * this structure should not exceed the size of that array (48 bytes).
++ *
++ * @flags: Frame flags, see &enum skb_frame_desc_flags.
++ * @frame_type: Frame type, see &enum rt2x00_dump_type.
++ * @data: Pointer to data part of frame (Start of ieee80211 header).
++ * @desc: Pointer to descriptor part of the frame.
++ *	Note that this pointer could point to something outside
++ *	of the scope of the skb->data pointer.
++ * @data_len: Length of the frame data.
++ * @desc_len: Length of the frame descriptor.
++
++ * @entry: The entry to which this sk buffer belongs.
++ */
++struct skb_frame_desc {
++	unsigned int flags;
++
++	unsigned int frame_type;
++
++	void *data;
++	void *desc;
++
++	unsigned int data_len;
++	unsigned int desc_len;
++
++	struct queue_entry *entry;
++};
++
++static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
++{
++	BUILD_BUG_ON(sizeof(struct skb_frame_desc) > sizeof(skb->cb));
++	return (struct skb_frame_desc *)&skb->cb[0];
++}
++
++/**
++ * enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc
++ *
++ * @RXDONE_SIGNAL_PLCP: Does the signal field contain the plcp value,
++ *	or does it contain the bitrate itself.
++ * @RXDONE_MY_BSS: Does this frame originate from device's BSS.
++ */
++enum rxdone_entry_desc_flags {
++	RXDONE_SIGNAL_PLCP = 1 << 0,
++	RXDONE_MY_BSS = 1 << 1,
++};
++
++/**
++ * struct rxdone_entry_desc: RX Entry descriptor
++ *
++ * Summary of information that has been read from the RX frame descriptor.
++ *
++ * @signal: Signal of the received frame.
++ * @rssi: RSSI of the received frame.
++ * @size: Data size of the received frame.
++ * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
++ * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
++
++ */
++struct rxdone_entry_desc {
++	int signal;
++	int rssi;
++	int size;
++	int flags;
++	int dev_flags;
++};
++
++/**
++ * struct txdone_entry_desc: TX done entry descriptor
++ *
++ * Summary of information that has been read from the TX frame descriptor
++ * after the device is done with transmission.
++ *
++ * @control: Control structure which was used to transmit the frame.
++ * @status: TX status (See &enum tx_status).
++ * @retry: Retry count.
++ */
++struct txdone_entry_desc {
++	struct ieee80211_tx_control *control;
++	int status;
++	int retry;
++};
++
++/**
++ * enum txentry_desc_flags: Status flags for TX entry descriptor
++ *
++ * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame.
++ * @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate.
++ * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment.
++ * @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted.
++ * @ENTRY_TXD_BURST: This frame belongs to the same burst event.
++ * @ENTRY_TXD_ACK: An ACK is required for this frame.
++ */
++enum txentry_desc_flags {
++	ENTRY_TXD_RTS_FRAME,
++	ENTRY_TXD_OFDM_RATE,
++	ENTRY_TXD_MORE_FRAG,
++	ENTRY_TXD_REQ_TIMESTAMP,
++	ENTRY_TXD_BURST,
++	ENTRY_TXD_ACK,
++};
++
++/**
++ * struct txentry_desc: TX Entry descriptor
++ *
++ * 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).
++ * @length_high: PLCP length high word.
++ * @length_low: PLCP length low word.
++ * @signal: PLCP signal.
++ * @service: PLCP service.
++ * @aifs: AIFS value.
++ * @ifs: IFS value.
++ * @cw_min: cwmin value.
++ * @cw_max: cwmax value.
++ */
++struct txentry_desc {
++	unsigned long flags;
++
++	enum data_queue_qid queue;
++
++	u16 length_high;
++	u16 length_low;
++	u16 signal;
++	u16 service;
++
++	int aifs;
++	int ifs;
++	int cw_min;
++	int cw_max;
++};
++
++/**
++ * enum queue_entry_flags: Status flags for queue entry
++ *
++ * @ENTRY_BCN_ASSIGNED: This entry has been assigned to an interface.
++ *	As long as this bit is set, this entry may only be touched
++ *	through the interface structure.
++ * @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.
++ */
++
++enum queue_entry_flags {
++	ENTRY_BCN_ASSIGNED,
++	ENTRY_OWNER_DEVICE_DATA,
++	ENTRY_OWNER_DEVICE_CRYPTO,
++};
++
++/**
++ * struct queue_entry: Entry inside the &struct data_queue
++ *
++ * @flags: Entry flags, see &enum queue_entry_flags.
++ * @queue: The data queue (&struct data_queue) to which this entry belongs.
++ * @skb: The buffer which is currently being transmitted (for TX queue),
++ *	or used to directly recieve data in (for RX queue).
++ * @entry_idx: The entry index number.
++ * @priv_data: Private data belonging to this queue entry. The pointer
++ *	points to data specific to a particular driver and queue type.
++ */
++struct queue_entry {
++	unsigned long flags;
++
++	struct data_queue *queue;
++
++	struct sk_buff *skb;
++
++	unsigned int entry_idx;
++
++	void *priv_data;
++};
++
++/**
++ * enum queue_index: Queue index type
++ *
++ * @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_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_DONE,
++	Q_INDEX_CRYPTO,
++	Q_INDEX_MAX,
++};
++
++/**
++ * struct data_queue: Data queue
++ *
++ * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to.
++ * @entries: Base address of the &struct queue_entry which are
++ *	part of this queue.
++ * @qid: The queue identification, see &enum data_queue_qid.
++ * @lock: Spinlock to protect index handling. Whenever @index, @index_done or
++ *	@index_crypt needs to be changed this lock should be grabbed to prevent
++ *	index corruption due to concurrency.
++ * @count: Number of frames handled in the queue.
++ * @limit: Maximum number of entries in the queue.
++ * @length: Number of frames in queue.
++ * @index: Index pointers to entry positions in the queue,
++ *	use &enum queue_index to get a specific index field.
++ * @aifs: The aifs value for outgoing frames (field ignored in RX queue).
++ * @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
++ * @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
++ * @data_size: Maximum data size for the frames in this queue.
++ * @desc_size: Hardware descriptor size for the data in this queue.
++ */
++struct data_queue {
++	struct rt2x00_dev *rt2x00dev;
++	struct queue_entry *entries;
++
++	enum data_queue_qid qid;
++
++	spinlock_t lock;
++	unsigned int count;
++	unsigned short limit;
++	unsigned short length;
++	unsigned short index[Q_INDEX_MAX];
++
++	unsigned short aifs;
++	unsigned short cw_min;
++	unsigned short cw_max;
++
++	unsigned short data_size;
++	unsigned short desc_size;
++};
++
++/**
++ * struct data_queue_desc: Data queue description
++ *
++ * The information in this structure is used by drivers
++ * to inform rt2x00lib about the creation of the data queue.
++ *
++ * @entry_num: Maximum number of entries for a queue.
++ * @data_size: Maximum data size for the frames in this queue.
++ * @desc_size: Hardware descriptor size for the data in this queue.
++ * @priv_size: Size of per-queue_entry private data.
++ */
++struct data_queue_desc {
++	unsigned short entry_num;
++	unsigned short data_size;
++	unsigned short desc_size;
++	unsigned short priv_size;
++};
++
++/**
++ * queue_end - Return pointer to the last queue (HELPER MACRO).
++ * @__dev: Pointer to &struct rt2x00_dev
++ *
++ * Using the base rx pointer and the maximum number of available queues,
++ * this macro will return the address of 1 position beyond  the end of the
++ * queues array.
++ */
++#define queue_end(__dev) \
++	&(__dev)->rx[(__dev)->data_queues]
++
++/**
++ * tx_queue_end - Return pointer to the last TX queue (HELPER MACRO).
++ * @__dev: Pointer to &struct rt2x00_dev
++ *
++ * Using the base tx pointer and the maximum number of available TX
++ * queues, this macro will return the address of 1 position beyond
++ * the end of the TX queue array.
++ */
++#define tx_queue_end(__dev) \
++	&(__dev)->tx[(__dev)->hw->queues]
++
++/**
++ * queue_loop - Loop through the queues within a specific range (HELPER MACRO).
++ * @__entry: Pointer where the current queue entry will be stored in.
++ * @__start: Start queue pointer.
++ * @__end: End queue pointer.
++ *
++ * This macro will loop through all queues between &__start and &__end.
++ */
++#define queue_loop(__entry, __start, __end)			\
++	for ((__entry) = (__start);				\
++	     prefetch(&(__entry)[1]), (__entry) != (__end);	\
++	     (__entry) = &(__entry)[1])
++
++/**
++ * queue_for_each - Loop through all queues
++ * @__dev: Pointer to &struct rt2x00_dev
++ * @__entry: Pointer where the current queue entry will be stored in.
++ *
++ * This macro will loop through all available queues.
++ */
++#define queue_for_each(__dev, __entry) \
++	queue_loop(__entry, (__dev)->rx, queue_end(__dev))
++
++/**
++ * tx_queue_for_each - Loop through the TX queues
++ * @__dev: Pointer to &struct rt2x00_dev
++ * @__entry: Pointer where the current queue entry will be stored in.
++ *
++ * This macro will loop through all TX related queues excluding
++ * the Beacon and Atim queues.
++ */
++#define tx_queue_for_each(__dev, __entry) \
++	queue_loop(__entry, (__dev)->tx, tx_queue_end(__dev))
++
++/**
++ * txall_queue_for_each - Loop through all TX related queues
++ * @__dev: Pointer to &struct rt2x00_dev
++ * @__entry: Pointer where the current queue entry will be stored in.
++ *
++ * This macro will loop through all TX related queues including
++ * the Beacon and Atim queues.
++ */
++#define txall_queue_for_each(__dev, __entry) \
++	queue_loop(__entry, (__dev)->tx, queue_end(__dev))
++
++/**
++ * rt2x00queue_empty - Check if the queue is empty.
++ * @queue: Queue to check if empty.
++ */
++static inline int rt2x00queue_empty(struct data_queue *queue)
++{
++	return queue->length == 0;
++}
++
++/**
++ * rt2x00queue_full - Check if the queue is full.
++ * @queue: Queue to check if full.
++ */
++static inline int rt2x00queue_full(struct data_queue *queue)
++{
++	return queue->length == queue->limit;
++}
++
++/**
++ * rt2x00queue_free - Check the number of available entries in queue.
++ * @queue: Queue to check.
++ */
++static inline int rt2x00queue_available(struct data_queue *queue)
++{
++	return queue->limit - queue->length;
++}
++
++/**
++ * rt2x00_desc_read - Read a word from the hardware descriptor.
++ * @desc: Base descriptor address
++ * @word: Word index from where the descriptor should be read.
++ * @value: Address where the descriptor value should be written into.
++ */
++static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value)
++{
++	*value = le32_to_cpu(desc[word]);
++}
++
++/**
++ * rt2x00_desc_write - wrote a word to the hardware descriptor.
++ * @desc: Base descriptor address
++ * @word: Word index from where the descriptor should be written.
++ * @value: Value that should be written into the descriptor.
++ */
++static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value)
++{
++	desc[word] = cpu_to_le32(value);
++}
++
++#endif /* RT2X00QUEUE_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
+index b1915dc..0325bed 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
++++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -29,7 +29,7 @@
+ /*
+  * TX result flags.
+  */
+-enum TX_STATUS {
++enum tx_status {
+ 	TX_SUCCESS = 0,
+ 	TX_SUCCESS_RETRY = 1,
+ 	TX_FAIL_RETRY = 2,
+@@ -220,75 +220,4 @@ static inline u8 rt2x00_get_field8(const u8 reg,
+ 	return (reg & field.bit_mask) >> field.bit_offset;
+ }
+ 
+-/*
+- * Device specific rate value.
+- * We will have to create the device specific rate value
+- * passed to the ieee80211 kernel. We need to make it a consist of
+- * multiple fields because we want to store more then 1 device specific
+- * values inside the value.
+- *	1 - rate, stored as 100 kbit/s.
+- *	2 - preamble, short_preamble enabled flag.
+- *	3 - MASK_RATE, which rates are enabled in this mode, this mask
+- *	corresponds with the TX register format for the current device.
+- *	4 - plcp, 802.11b rates are device specific,
+- *	802.11g rates are set according to the ieee802.11a-1999 p.14.
+- * The bit to enable preamble is set in a seperate define.
+- */
+-#define DEV_RATE	FIELD32(0x000007ff)
+-#define DEV_PREAMBLE	FIELD32(0x00000800)
+-#define DEV_RATEMASK	FIELD32(0x00fff000)
+-#define DEV_PLCP	FIELD32(0xff000000)
+-
+-/*
+- * Bitfields
+- */
+-#define DEV_RATEBIT_1MB		( 1 << 0 )
+-#define DEV_RATEBIT_2MB		( 1 << 1 )
+-#define DEV_RATEBIT_5_5MB	( 1 << 2 )
+-#define DEV_RATEBIT_11MB	( 1 << 3 )
+-#define DEV_RATEBIT_6MB		( 1 << 4 )
+-#define DEV_RATEBIT_9MB		( 1 << 5 )
+-#define DEV_RATEBIT_12MB	( 1 << 6 )
+-#define DEV_RATEBIT_18MB	( 1 << 7 )
+-#define DEV_RATEBIT_24MB	( 1 << 8 )
+-#define DEV_RATEBIT_36MB	( 1 << 9 )
+-#define DEV_RATEBIT_48MB	( 1 << 10 )
+-#define DEV_RATEBIT_54MB	( 1 << 11 )
+-
+-/*
+- * Bitmasks for DEV_RATEMASK
+- */
+-#define DEV_RATEMASK_1MB	( (DEV_RATEBIT_1MB << 1) -1 )
+-#define DEV_RATEMASK_2MB	( (DEV_RATEBIT_2MB << 1) -1 )
+-#define DEV_RATEMASK_5_5MB	( (DEV_RATEBIT_5_5MB << 1) -1 )
+-#define DEV_RATEMASK_11MB	( (DEV_RATEBIT_11MB << 1) -1 )
+-#define DEV_RATEMASK_6MB	( (DEV_RATEBIT_6MB << 1) -1 )
+-#define DEV_RATEMASK_9MB	( (DEV_RATEBIT_9MB << 1) -1 )
+-#define DEV_RATEMASK_12MB	( (DEV_RATEBIT_12MB << 1) -1 )
+-#define DEV_RATEMASK_18MB	( (DEV_RATEBIT_18MB << 1) -1 )
+-#define DEV_RATEMASK_24MB	( (DEV_RATEBIT_24MB << 1) -1 )
+-#define DEV_RATEMASK_36MB	( (DEV_RATEBIT_36MB << 1) -1 )
+-#define DEV_RATEMASK_48MB	( (DEV_RATEBIT_48MB << 1) -1 )
+-#define DEV_RATEMASK_54MB	( (DEV_RATEBIT_54MB << 1) -1 )
+-
+-/*
+- * Bitmask groups of bitrates
+- */
+-#define DEV_BASIC_RATEMASK \
+-	( DEV_RATEMASK_11MB | \
+-	  DEV_RATEBIT_6MB | DEV_RATEBIT_12MB | DEV_RATEBIT_24MB )
+-
+-#define DEV_CCK_RATEMASK	( DEV_RATEMASK_11MB )
+-#define DEV_OFDM_RATEMASK	( DEV_RATEMASK_54MB & ~DEV_CCK_RATEMASK )
+-
+-/*
+- * Macro's to set and get specific fields from the device specific val and val2
+- * fields inside the ieee80211_rate entry.
+- */
+-#define DEVICE_SET_RATE_FIELD(__value, __mask) \
+-	(int)( ((__value) << DEV_##__mask.bit_offset) & DEV_##__mask.bit_mask )
+-
+-#define DEVICE_GET_RATE_FIELD(__value, __mask) \
+-	(int)( ((__value) & DEV_##__mask.bit_mask) >> DEV_##__mask.bit_offset )
+-
+ #endif /* RT2X00REG_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+index f955775..fcef988 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c
++++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h
+deleted file mode 100644
+index 1caa6d6..0000000
+--- a/drivers/net/wireless/rt2x00/rt2x00ring.h
++++ /dev/null
+@@ -1,290 +0,0 @@
+-/*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+-	<http://rt2x00.serialmonkey.com>
+-
+-	This program is free software; you can redistribute it and/or modify
+-	it under the terms of the GNU General Public License as published by
+-	the Free Software Foundation; either version 2 of the License, or
+-	(at your option) any later version.
+-
+-	This program is distributed in the hope that it will be useful,
+-	but WITHOUT ANY WARRANTY; without even the implied warranty of
+-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-	GNU General Public License for more details.
+-
+-	You should have received a copy of the GNU General Public License
+-	along with this program; if not, write to the
+-	Free Software Foundation, Inc.,
+-	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-/*
+-	Module: rt2x00
+-	Abstract: rt2x00 ring datastructures and routines
+- */
+-
+-#ifndef RT2X00RING_H
+-#define RT2X00RING_H
+-
+-/*
+- * skb_desc
+- * Descriptor information for the skb buffer
+- */
+-struct skb_desc {
+-	unsigned int frame_type;
+-
+-	unsigned int desc_len;
+-	unsigned int data_len;
+-
+-	void *desc;
+-	void *data;
+-
+-	struct data_ring *ring;
+-	struct data_entry *entry;
+-};
+-
+-static inline struct skb_desc* get_skb_desc(struct sk_buff *skb)
+-{
+-	return (struct skb_desc*)&skb->cb[0];
+-}
+-
+-/*
+- * rxdata_entry_desc
+- * Summary of information that has been read from the
+- * RX frame descriptor.
+- */
+-struct rxdata_entry_desc {
+-	int signal;
+-	int rssi;
+-	int ofdm;
+-	int size;
+-	int flags;
+-	int my_bss;
+-};
+-
+-/*
+- * txdata_entry_desc
+- * Summary of information that should be written into the
+- * descriptor for sending a TX frame.
+- */
+-struct txdata_entry_desc {
+-	unsigned long flags;
+-#define ENTRY_TXDONE		1
+-#define ENTRY_TXD_RTS_FRAME	2
+-#define ENTRY_TXD_OFDM_RATE	3
+-#define ENTRY_TXD_MORE_FRAG	4
+-#define ENTRY_TXD_REQ_TIMESTAMP	5
+-#define ENTRY_TXD_BURST		6
+-#define ENTRY_TXD_ACK		7
+-
+-/*
+- * Queue ID. ID's 0-4 are data TX rings
+- */
+-	int queue;
+-#define QUEUE_MGMT		13
+-#define QUEUE_RX		14
+-#define QUEUE_OTHER		15
+-
+-	/*
+-	 * PLCP values.
+-	 */
+-	u16 length_high;
+-	u16 length_low;
+-	u16 signal;
+-	u16 service;
+-
+-	/*
+-	 * Timing information
+-	 */
+-	int aifs;
+-	int ifs;
+-	int cw_min;
+-	int cw_max;
+-};
+-
+-/*
+- * data_entry
+- * The data ring is a list of data entries.
+- * Each entry holds a reference to the descriptor
+- * and the data buffer. For TX rings the reference to the
+- * sk_buff of the packet being transmitted is also stored here.
+- */
+-struct data_entry {
+-	/*
+-	 * Status flags
+-	 */
+-	unsigned long flags;
+-#define ENTRY_OWNER_NIC		1
+-
+-	/*
+-	 * Ring we belong to.
+-	 */
+-	struct data_ring *ring;
+-
+-	/*
+-	 * sk_buff for the packet which is being transmitted
+-	 * in this entry (Only used with TX related rings).
+-	 */
+-	struct sk_buff *skb;
+-
+-	/*
+-	 * Store a ieee80211_tx_status structure in each
+-	 * ring entry, this will optimize the txdone
+-	 * handler.
+-	 */
+-	struct ieee80211_tx_status tx_status;
+-
+-	/*
+-	 * private pointer specific to driver.
+-	 */
+-	void *priv;
+-
+-	/*
+-	 * Data address for this entry.
+-	 */
+-	void *data_addr;
+-	dma_addr_t data_dma;
+-
+-	/*
+-	 * Entry identification number (index).
+-	 */
+-	unsigned int entry_idx;
+-};
+-
+-/*
+- * data_ring
+- * Data rings are used by the device to send and receive packets.
+- * The data_addr is the base address of the data memory.
+- * To determine at which point in the ring we are,
+- * have to use the rt2x00_ring_index_*() functions.
+- */
+-struct data_ring {
+-	/*
+-	 * Pointer to main rt2x00dev structure where this
+-	 * ring belongs to.
+-	 */
+-	struct rt2x00_dev *rt2x00dev;
+-
+-	/*
+-	 * Base address for the device specific data entries.
+-	 */
+-	struct data_entry *entry;
+-
+-	/*
+-	 * TX queue statistic info.
+-	 */
+-	struct ieee80211_tx_queue_stats_data stats;
+-
+-	/*
+-	 * TX Queue parameters.
+-	 */
+-	struct ieee80211_tx_queue_params tx_params;
+-
+-	/*
+-	 * Base address for data ring.
+-	 */
+-	dma_addr_t data_dma;
+-	void *data_addr;
+-
+-	/*
+-	 * Queue identification number:
+-	 * RX: 0
+-	 * TX: IEEE80211_TX_*
+-	 */
+-	unsigned int queue_idx;
+-
+-	/*
+-	 * Index variables.
+-	 */
+-	u16 index;
+-	u16 index_done;
+-
+-	/*
+-	 * Size of packet and descriptor in bytes.
+-	 */
+-	u16 data_size;
+-	u16 desc_size;
+-};
+-
+-/*
+- * Handlers to determine the address of the current device specific
+- * data entry, where either index or index_done points to.
+- */
+-static inline struct data_entry *rt2x00_get_data_entry(struct data_ring *ring)
+-{
+-	return &ring->entry[ring->index];
+-}
+-
+-static inline struct data_entry *rt2x00_get_data_entry_done(struct data_ring
+-							    *ring)
+-{
+-	return &ring->entry[ring->index_done];
+-}
+-
+-/*
+- * Total ring memory
+- */
+-static inline int rt2x00_get_ring_size(struct data_ring *ring)
+-{
+-	return ring->stats.limit * (ring->desc_size + ring->data_size);
+-}
+-
+-/*
+- * Ring index manipulation functions.
+- */
+-static inline void rt2x00_ring_index_inc(struct data_ring *ring)
+-{
+-	ring->index++;
+-	if (ring->index >= ring->stats.limit)
+-		ring->index = 0;
+-	ring->stats.len++;
+-}
+-
+-static inline void rt2x00_ring_index_done_inc(struct data_ring *ring)
+-{
+-	ring->index_done++;
+-	if (ring->index_done >= ring->stats.limit)
+-		ring->index_done = 0;
+-	ring->stats.len--;
+-	ring->stats.count++;
+-}
+-
+-static inline void rt2x00_ring_index_clear(struct data_ring *ring)
+-{
+-	ring->index = 0;
+-	ring->index_done = 0;
+-	ring->stats.len = 0;
+-	ring->stats.count = 0;
+-}
+-
+-static inline int rt2x00_ring_empty(struct data_ring *ring)
+-{
+-	return ring->stats.len == 0;
+-}
+-
+-static inline int rt2x00_ring_full(struct data_ring *ring)
+-{
+-	return ring->stats.len == ring->stats.limit;
+-}
+-
+-static inline int rt2x00_ring_free(struct data_ring *ring)
+-{
+-	return ring->stats.limit - ring->stats.len;
+-}
+-
+-/*
+- * TX/RX Descriptor access functions.
+- */
+-static inline void rt2x00_desc_read(__le32 *desc,
+-				    const u8 word, u32 *value)
+-{
+-	*value = le32_to_cpu(desc[word]);
+-}
+-
+-static inline void rt2x00_desc_write(__le32 *desc,
+-				     const u8 word, const u32 value)
+-{
+-	desc[word] = cpu_to_le32(value);
+-}
+-
+-#endif /* RT2X00RING_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
+index 84e9bdb..5a33167 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
++++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -40,8 +40,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
+ 			     void *buffer, const u16 buffer_length,
+ 			     const int timeout)
+ {
+-	struct usb_device *usb_dev =
+-	    interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
++	struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
+ 	int status;
+ 	unsigned int i;
+ 	unsigned int pipe =
+@@ -85,20 +84,20 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
+ 	/*
+ 	 * Check for Cache availability.
+ 	 */
+-	if (unlikely(!rt2x00dev->csr_cache || buffer_length > CSR_CACHE_SIZE)) {
++	if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
+ 		ERROR(rt2x00dev, "CSR cache not available.\n");
+ 		return -ENOMEM;
+ 	}
+ 
+ 	if (requesttype == USB_VENDOR_REQUEST_OUT)
+-		memcpy(rt2x00dev->csr_cache, buffer, buffer_length);
++		memcpy(rt2x00dev->csr.cache, buffer, buffer_length);
+ 
+ 	status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
+-					  offset, 0, rt2x00dev->csr_cache,
++					  offset, 0, rt2x00dev->csr.cache,
+ 					  buffer_length, timeout);
+ 
+ 	if (!status && requesttype == USB_VENDOR_REQUEST_IN)
+-		memcpy(buffer, rt2x00dev->csr_cache, buffer_length);
++		memcpy(buffer, rt2x00dev->csr.cache, buffer_length);
+ 
+ 	return status;
+ }
+@@ -128,15 +127,15 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
+  */
+ static void rt2x00usb_interrupt_txdone(struct urb *urb)
+ {
+-	struct data_entry *entry = (struct data_entry *)urb->context;
+-	struct data_ring *ring = entry->ring;
+-	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
++	struct queue_entry *entry = (struct queue_entry *)urb->context;
++	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
++	struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data;
++	struct txdone_entry_desc txdesc;
+ 	__le32 *txd = (__le32 *)entry->skb->data;
+ 	u32 word;
+-	int tx_status;
+ 
+ 	if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
+-	    !__test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
++	    !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ 		return;
+ 
+ 	rt2x00_desc_read(txd, 0, &word);
+@@ -144,45 +143,46 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
+ 	/*
+ 	 * Remove the descriptor data from the buffer.
+ 	 */
+-	skb_pull(entry->skb, ring->desc_size);
++	skb_pull(entry->skb, entry->queue->desc_size);
+ 
+ 	/*
+ 	 * Obtain the status about this packet.
+ 	 */
+-	tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
++	txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
++	txdesc.retry = 0;
++	txdesc.control = &priv_tx->control;
+ 
+-	rt2x00lib_txdone(entry, tx_status, 0);
++	rt2x00lib_txdone(entry, &txdesc);
+ 
+ 	/*
+ 	 * Make this entry available for reuse.
+ 	 */
+ 	entry->flags = 0;
+-	rt2x00_ring_index_done_inc(entry->ring);
++	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+ 
+ 	/*
+-	 * If the data ring was full before the txdone handler
++	 * If the data queue was full before the txdone handler
+ 	 * we must make sure the packet queue in the mac80211 stack
+ 	 * is reenabled when the txdone handler has finished.
+ 	 */
+-	if (!rt2x00_ring_full(ring))
+-		ieee80211_wake_queue(rt2x00dev->hw,
+-				     entry->tx_status.control.queue);
++	if (!rt2x00queue_full(entry->queue))
++		ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue);
+ }
+ 
+ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+-			    struct data_ring *ring, struct sk_buff *skb,
++			    struct data_queue *queue, struct sk_buff *skb,
+ 			    struct ieee80211_tx_control *control)
+ {
+-	struct usb_device *usb_dev =
+-	    interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+-	struct data_entry *entry = rt2x00_get_data_entry(ring);
+-	struct skb_desc *desc;
++	struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
++	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
++	struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data;
++	struct skb_frame_desc *skbdesc;
+ 	u32 length;
+ 
+-	if (rt2x00_ring_full(ring))
++	if (rt2x00queue_full(queue))
+ 		return -EINVAL;
+ 
+-	if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) {
++	if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
+ 		ERROR(rt2x00dev,
+ 		      "Arrived at non-free entry in the non-full queue %d.\n"
+ 		      "Please file bug report to %s.\n",
+@@ -193,20 +193,20 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ 	/*
+ 	 * Add the descriptor in front of the skb.
+ 	 */
+-	skb_push(skb, ring->desc_size);
+-	memset(skb->data, 0, ring->desc_size);
++	skb_push(skb, queue->desc_size);
++	memset(skb->data, 0, queue->desc_size);
+ 
+ 	/*
+ 	 * Fill in skb descriptor
+ 	 */
+-	desc = get_skb_desc(skb);
+-	desc->desc_len = ring->desc_size;
+-	desc->data_len = skb->len - ring->desc_size;
+-	desc->desc = skb->data;
+-	desc->data = skb->data + ring->desc_size;
+-	desc->ring = ring;
+-	desc->entry = entry;
++	skbdesc = get_skb_frame_desc(skb);
++	skbdesc->data = skb->data + queue->desc_size;
++	skbdesc->data_len = skb->len - queue->desc_size;
++	skbdesc->desc = skb->data;
++	skbdesc->desc_len = queue->desc_size;
++	skbdesc->entry = entry;
+ 
++	memcpy(&priv_tx->control, control, sizeof(priv_tx->control));
+ 	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+ 
+ 	/*
+@@ -219,12 +219,12 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ 	/*
+ 	 * Initialize URB and send the frame to the device.
+ 	 */
+-	__set_bit(ENTRY_OWNER_NIC, &entry->flags);
+-	usb_fill_bulk_urb(entry->priv, usb_dev, usb_sndbulkpipe(usb_dev, 1),
++	__set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
++	usb_fill_bulk_urb(priv_tx->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1),
+ 			  skb->data, length, rt2x00usb_interrupt_txdone, entry);
+-	usb_submit_urb(entry->priv, GFP_ATOMIC);
++	usb_submit_urb(priv_tx->urb, GFP_ATOMIC);
+ 
+-	rt2x00_ring_index_inc(ring);
++	rt2x00queue_index_inc(queue, Q_INDEX);
+ 
+ 	return 0;
+ }
+@@ -233,20 +233,42 @@ EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
+ /*
+  * RX data handlers.
+  */
++static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue)
++{
++	struct sk_buff *skb;
++	unsigned int frame_size;
++
++	/*
++	 * As alignment we use 2 and not NET_IP_ALIGN because we need
++	 * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
++	 * can be 0 on some hardware). We use these 2 bytes for frame
++	 * alignment later, we assume that the chance that
++	 * header_size % 4 == 2 is bigger then header_size % 2 == 0
++	 * and thus optimize alignment by reserving the 2 bytes in
++	 * advance.
++	 */
++	frame_size = queue->data_size + queue->desc_size;
++	skb = dev_alloc_skb(queue->desc_size + frame_size + 2);
++	if (!skb)
++		return NULL;
++
++	skb_reserve(skb, queue->desc_size + 2);
++	skb_put(skb, frame_size);
++
++	return skb;
++}
++
+ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
+ {
+-	struct data_entry *entry = (struct data_entry *)urb->context;
+-	struct data_ring *ring = entry->ring;
+-	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
++	struct queue_entry *entry = (struct queue_entry *)urb->context;
++	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ 	struct sk_buff *skb;
+-	struct ieee80211_hdr *hdr;
+-	struct skb_desc *skbdesc;
+-	struct rxdata_entry_desc desc;
++	struct skb_frame_desc *skbdesc;
++	struct rxdone_entry_desc rxdesc;
+ 	int header_size;
+-	int frame_size;
+ 
+ 	if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
+-	    !test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
++	    !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ 		return;
+ 
+ 	/*
+@@ -254,67 +276,45 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
+ 	 * to be actually valid, or if the urb is signaling
+ 	 * a problem.
+ 	 */
+-	if (urb->actual_length < entry->ring->desc_size || urb->status)
++	if (urb->actual_length < entry->queue->desc_size || urb->status)
+ 		goto skip_entry;
+ 
+ 	/*
+ 	 * Fill in skb descriptor
+ 	 */
+-	skbdesc = get_skb_desc(entry->skb);
+-	skbdesc->ring = ring;
++	skbdesc = get_skb_frame_desc(entry->skb);
++	memset(skbdesc, 0, sizeof(*skbdesc));
+ 	skbdesc->entry = entry;
+ 
+-	memset(&desc, 0, sizeof(desc));
+-	rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
+-
+-	/*
+-	 * Allocate a new sk buffer to replace the current one.
+-	 * If allocation fails, we should drop the current frame
+-	 * so we can recycle the existing sk buffer for the new frame.
+-	 * As alignment we use 2 and not NET_IP_ALIGN because we need
+-	 * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
+-	 * can be 0 on some hardware). We use these 2 bytes for frame
+-	 * alignment later, we assume that the chance that
+-	 * header_size % 4 == 2 is bigger then header_size % 2 == 0
+-	 * and thus optimize alignment by reserving the 2 bytes in
+-	 * advance.
+-	 */
+-	frame_size = entry->ring->data_size + entry->ring->desc_size;
+-	skb = dev_alloc_skb(frame_size + 2);
+-	if (!skb)
+-		goto skip_entry;
+-
+-	skb_reserve(skb, 2);
+-	skb_put(skb, frame_size);
++	memset(&rxdesc, 0, sizeof(rxdesc));
++	rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
+ 
+ 	/*
+ 	 * The data behind the ieee80211 header must be
+ 	 * aligned on a 4 byte boundary.
+ 	 */
+-	hdr = (struct ieee80211_hdr *)entry->skb->data;
+-	header_size =
+-	    ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+-
++	header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
+ 	if (header_size % 4 == 0) {
+ 		skb_push(entry->skb, 2);
+-		memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
++		memmove(entry->skb->data, entry->skb->data + 2,
++			entry->skb->len - 2);
++		skbdesc->data = entry->skb->data;
++		skb_trim(entry->skb,entry->skb->len - 2);
+ 	}
+ 
+ 	/*
+-	 * Trim the entire buffer down to only contain the valid frame data
+-	 * excluding the device descriptor. The position of the descriptor
+-	 * varies. This means that we should check where the descriptor is
+-	 * and decide if we need to pull the data pointer to exclude the
+-	 * device descriptor.
++	 * Allocate a new sk buffer to replace the current one.
++	 * If allocation fails, we should drop the current frame
++	 * so we can recycle the existing sk buffer for the new frame.
+ 	 */
+-	if (skbdesc->data > skbdesc->desc)
+-		skb_pull(entry->skb, skbdesc->desc_len);
+-	skb_trim(entry->skb, desc.size);
++	skb = rt2x00usb_alloc_rxskb(entry->queue);
++	if (!skb)
++		goto skip_entry;
+ 
+ 	/*
+ 	 * Send the frame to rt2x00lib for further processing.
+ 	 */
+-	rt2x00lib_rxdone(entry, entry->skb, &desc);
++	rt2x00lib_rxdone(entry, &rxdesc);
+ 
+ 	/*
+ 	 * Replace current entry's skb with the newly allocated one,
+@@ -325,12 +325,12 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
+ 	urb->transfer_buffer_length = entry->skb->len;
+ 
+ skip_entry:
+-	if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
+-		__set_bit(ENTRY_OWNER_NIC, &entry->flags);
++	if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) {
++		__set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ 		usb_submit_urb(urb, GFP_ATOMIC);
+ 	}
+ 
+-	rt2x00_ring_index_inc(ring);
++	rt2x00queue_index_inc(entry->queue, Q_INDEX);
+ }
+ 
+ /*
+@@ -338,18 +338,44 @@ skip_entry:
+  */
+ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+-	struct data_ring *ring;
++	struct queue_entry_priv_usb_rx *priv_rx;
++	struct queue_entry_priv_usb_tx *priv_tx;
++	struct queue_entry_priv_usb_bcn *priv_bcn;
++	struct data_queue *queue;
+ 	unsigned int i;
+ 
+ 	rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000,
+ 				    REGISTER_TIMEOUT);
+ 
+ 	/*
+-	 * Cancel all rings.
++	 * Cancel all queues.
+ 	 */
+-	ring_for_each(rt2x00dev, ring) {
+-		for (i = 0; i < ring->stats.limit; i++)
+-			usb_kill_urb(ring->entry[i].priv);
++	for (i = 0; i < rt2x00dev->rx->limit; i++) {
++		priv_rx = rt2x00dev->rx->entries[i].priv_data;
++		usb_kill_urb(priv_rx->urb);
++	}
++
++	tx_queue_for_each(rt2x00dev, queue) {
++		for (i = 0; i < queue->limit; i++) {
++			priv_tx = queue->entries[i].priv_data;
++			usb_kill_urb(priv_tx->urb);
++		}
++	}
++
++	for (i = 0; i < rt2x00dev->bcn->limit; i++) {
++		priv_bcn = rt2x00dev->bcn->entries[i].priv_data;
++		usb_kill_urb(priv_bcn->urb);
++
++		if (priv_bcn->guardian_urb)
++			usb_kill_urb(priv_bcn->guardian_urb);
++	}
++
++	if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
++		return;
++
++	for (i = 0; i < rt2x00dev->bcn[1].limit; i++) {
++		priv_tx = rt2x00dev->bcn[1].entries[i].priv_data;
++		usb_kill_urb(priv_tx->urb);
+ 	}
+ }
+ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
+@@ -358,64 +384,108 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
+  * Device initialization handlers.
+  */
+ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+-			    struct data_entry *entry)
++			    struct queue_entry *entry)
+ {
+-	struct usb_device *usb_dev =
+-	     interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
++	struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
++	struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data;
+ 
+-	usb_fill_bulk_urb(entry->priv, usb_dev,
++	usb_fill_bulk_urb(priv_rx->urb, usb_dev,
+ 			  usb_rcvbulkpipe(usb_dev, 1),
+ 			  entry->skb->data, entry->skb->len,
+ 			  rt2x00usb_interrupt_rxdone, entry);
+ 
+-	__set_bit(ENTRY_OWNER_NIC, &entry->flags);
+-	usb_submit_urb(entry->priv, GFP_ATOMIC);
++	__set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
++	usb_submit_urb(priv_rx->urb, GFP_ATOMIC);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
+ 
+ void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+-			    struct data_entry *entry)
++			    struct queue_entry *entry)
+ {
+ 	entry->flags = 0;
+ }
+ EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry);
+ 
+ static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
+-			       struct data_ring *ring)
++			       struct data_queue *queue)
+ {
++	struct queue_entry_priv_usb_rx *priv_rx;
++	struct queue_entry_priv_usb_tx *priv_tx;
++	struct queue_entry_priv_usb_bcn *priv_bcn;
++	struct urb *urb;
++	unsigned int guardian =
++	    test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
+ 	unsigned int i;
+ 
+ 	/*
+ 	 * Allocate the URB's
+ 	 */
+-	for (i = 0; i < ring->stats.limit; i++) {
+-		ring->entry[i].priv = usb_alloc_urb(0, GFP_KERNEL);
+-		if (!ring->entry[i].priv)
++	for (i = 0; i < queue->limit; i++) {
++		urb = usb_alloc_urb(0, GFP_KERNEL);
++		if (!urb)
+ 			return -ENOMEM;
++
++		if (queue->qid == QID_RX) {
++			priv_rx = queue->entries[i].priv_data;
++			priv_rx->urb = urb;
++		} else if (queue->qid == QID_MGMT && guardian) {
++			priv_bcn = queue->entries[i].priv_data;
++			priv_bcn->urb = urb;
++
++			urb = usb_alloc_urb(0, GFP_KERNEL);
++			if (!urb)
++				return -ENOMEM;
++
++			priv_bcn->guardian_urb = urb;
++		} else {
++			priv_tx = queue->entries[i].priv_data;
++			priv_tx->urb = urb;
++		}
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
+-			       struct data_ring *ring)
++			       struct data_queue *queue)
+ {
++	struct queue_entry_priv_usb_rx *priv_rx;
++	struct queue_entry_priv_usb_tx *priv_tx;
++	struct queue_entry_priv_usb_bcn *priv_bcn;
++	struct urb *urb;
++	unsigned int guardian =
++	    test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
+ 	unsigned int i;
+ 
+-	if (!ring->entry)
++	if (!queue->entries)
+ 		return;
+ 
+-	for (i = 0; i < ring->stats.limit; i++) {
+-		usb_kill_urb(ring->entry[i].priv);
+-		usb_free_urb(ring->entry[i].priv);
+-		if (ring->entry[i].skb)
+-			kfree_skb(ring->entry[i].skb);
++	for (i = 0; i < queue->limit; i++) {
++		if (queue->qid == QID_RX) {
++			priv_rx = queue->entries[i].priv_data;
++			urb = priv_rx->urb;
++		} else if (queue->qid == QID_MGMT && guardian) {
++			priv_bcn = queue->entries[i].priv_data;
++
++			usb_kill_urb(priv_bcn->guardian_urb);
++			usb_free_urb(priv_bcn->guardian_urb);
++
++			urb = priv_bcn->urb;
++		} else {
++			priv_tx = queue->entries[i].priv_data;
++			urb = priv_tx->urb;
++		}
++
++		usb_kill_urb(urb);
++		usb_free_urb(urb);
++		if (queue->entries[i].skb)
++			kfree_skb(queue->entries[i].skb);
+ 	}
+ }
+ 
+ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
+ {
+-	struct data_ring *ring;
++	struct data_queue *queue;
+ 	struct sk_buff *skb;
+ 	unsigned int entry_size;
+ 	unsigned int i;
+@@ -424,25 +494,22 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Allocate DMA
+ 	 */
+-	ring_for_each(rt2x00dev, ring) {
+-		status = rt2x00usb_alloc_urb(rt2x00dev, ring);
++	queue_for_each(rt2x00dev, queue) {
++		status = rt2x00usb_alloc_urb(rt2x00dev, queue);
+ 		if (status)
+ 			goto exit;
+ 	}
+ 
+ 	/*
+-	 * For the RX ring, skb's should be allocated.
++	 * For the RX queue, skb's should be allocated.
+ 	 */
+ 	entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size;
+-	for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
+-		skb = dev_alloc_skb(NET_IP_ALIGN + entry_size);
++	for (i = 0; i < rt2x00dev->rx->limit; i++) {
++		skb = rt2x00usb_alloc_rxskb(rt2x00dev->rx);
+ 		if (!skb)
+ 			goto exit;
+ 
+-		skb_reserve(skb, NET_IP_ALIGN);
+-		skb_put(skb, entry_size);
+-
+-		rt2x00dev->rx->entry[i].skb = skb;
++		rt2x00dev->rx->entries[i].skb = skb;
+ 	}
+ 
+ 	return 0;
+@@ -456,10 +523,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_initialize);
+ 
+ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
+ {
+-	struct data_ring *ring;
++	struct data_queue *queue;
+ 
+-	ring_for_each(rt2x00dev, ring)
+-		rt2x00usb_free_urb(rt2x00dev, ring);
++	queue_for_each(rt2x00dev, queue)
++		rt2x00usb_free_urb(rt2x00dev, queue);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
+ 
+@@ -474,14 +541,14 @@ static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev)
+ 	kfree(rt2x00dev->eeprom);
+ 	rt2x00dev->eeprom = NULL;
+ 
+-	kfree(rt2x00dev->csr_cache);
+-	rt2x00dev->csr_cache = NULL;
++	kfree(rt2x00dev->csr.cache);
++	rt2x00dev->csr.cache = NULL;
+ }
+ 
+ static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
+ {
+-	rt2x00dev->csr_cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
+-	if (!rt2x00dev->csr_cache)
++	rt2x00dev->csr.cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
++	if (!rt2x00dev->csr.cache)
+ 		goto exit;
+ 
+ 	rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
+@@ -627,9 +694,9 @@ EXPORT_SYMBOL_GPL(rt2x00usb_resume);
+ #endif /* CONFIG_PM */
+ 
+ /*
+- * rt2x00pci module information.
++ * rt2x00usb module information.
+  */
+ MODULE_AUTHOR(DRV_PROJECT);
+ MODULE_VERSION(DRV_VERSION);
+-MODULE_DESCRIPTION("rt2x00 library");
++MODULE_DESCRIPTION("rt2x00 usb library");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
+index e40df40..11e5518 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
++++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -60,34 +60,47 @@
+ #define USB_VENDOR_REQUEST_IN	( USB_DIR_IN | USB_VENDOR_REQUEST )
+ #define USB_VENDOR_REQUEST_OUT	( USB_DIR_OUT | USB_VENDOR_REQUEST )
+ 
+-/*
+- * USB vendor commands.
+- */
+-#define USB_DEVICE_MODE		0x01
+-#define USB_SINGLE_WRITE	0x02
+-#define USB_SINGLE_READ		0x03
+-#define USB_MULTI_WRITE		0x06
+-#define USB_MULTI_READ		0x07
+-#define USB_EEPROM_WRITE	0x08
+-#define USB_EEPROM_READ		0x09
+-#define USB_LED_CONTROL		0x0a	/* RT73USB */
+-#define USB_RX_CONTROL		0x0c
++/**
++ * enum rt2x00usb_vendor_request: USB vendor commands.
++ */
++enum rt2x00usb_vendor_request {
++	USB_DEVICE_MODE = 1,
++	USB_SINGLE_WRITE = 2,
++	USB_SINGLE_READ = 3,
++	USB_MULTI_WRITE = 6,
++	USB_MULTI_READ = 7,
++	USB_EEPROM_WRITE = 8,
++	USB_EEPROM_READ = 9,
++	USB_LED_CONTROL = 10, /* RT73USB */
++	USB_RX_CONTROL = 12,
++};
+ 
+-/*
+- * Device modes offset
++/**
++ * enum rt2x00usb_mode_offset: Device modes offset.
+  */
+-#define USB_MODE_RESET		0x01
+-#define USB_MODE_UNPLUG		0x02
+-#define USB_MODE_FUNCTION	0x03
+-#define USB_MODE_TEST		0x04
+-#define USB_MODE_SLEEP		0x07	/* RT73USB */
+-#define USB_MODE_FIRMWARE	0x08	/* RT73USB */
+-#define USB_MODE_WAKEUP		0x09	/* RT73USB */
++enum rt2x00usb_mode_offset {
++	USB_MODE_RESET = 1,
++	USB_MODE_UNPLUG = 2,
++	USB_MODE_FUNCTION = 3,
++	USB_MODE_TEST = 4,
++	USB_MODE_SLEEP = 7,	/* RT73USB */
++	USB_MODE_FIRMWARE = 8,	/* RT73USB */
++	USB_MODE_WAKEUP = 9,	/* RT73USB */
++};
+ 
+-/*
+- * Used to read/write from/to the device.
++/**
++ * rt2x00usb_vendor_request - Send register command to device
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
++ * @requesttype: Request type &USB_VENDOR_REQUEST_*
++ * @offset: Register offset to perform action on
++ * @value: Value to write to device
++ * @buffer: Buffer where information will be read/written to by device
++ * @buffer_length: Size of &buffer
++ * @timeout: Operation timeout
++ *
+  * This is the main function to communicate with the device,
+- * the buffer argument _must_ either be NULL or point to
++ * the &buffer argument _must_ either be NULL or point to
+  * a buffer allocated by kmalloc. Failure to do so can lead
+  * to unexpected behavior depending on the architecture.
+  */
+@@ -97,13 +110,21 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
+ 			     void *buffer, const u16 buffer_length,
+ 			     const int timeout);
+ 
+-/*
+- * Used to read/write from/to the device.
++/**
++ * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
++ * @requesttype: Request type &USB_VENDOR_REQUEST_*
++ * @offset: Register offset to perform action on
++ * @buffer: Buffer where information will be read/written to by device
++ * @buffer_length: Size of &buffer
++ * @timeout: Operation timeout
++ *
+  * This function will use a previously with kmalloc allocated cache
+  * to communicate with the device. The contents of the buffer pointer
+  * will be copied to this cache when writing, or read from the cache
+  * when reading.
+- * Buffers send to rt2x00usb_vendor_request _must_ be allocated with
++ * Buffers send to &rt2x00usb_vendor_request _must_ be allocated with
+  * kmalloc. Hence the reason for using a previously allocated cache
+  * which has been allocated properly.
+  */
+@@ -112,15 +133,32 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
+ 				  const u16 offset, void *buffer,
+ 				  const u16 buffer_length, const int timeout);
+ 
+-/*
+- * A version of rt2x00usb_vendor_request_buff which must be called
+- * if the usb_cache_mutex is already held. */
++/**
++ * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
++ * @requesttype: Request type &USB_VENDOR_REQUEST_*
++ * @offset: Register offset to perform action on
++ * @buffer: Buffer where information will be read/written to by device
++ * @buffer_length: Size of &buffer
++ * @timeout: Operation timeout
++ *
++ * A version of &rt2x00usb_vendor_request_buff which must be called
++ * if the usb_cache_mutex is already held.
++ */
+ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
+ 				   const u8 request, const u8 requesttype,
+ 				   const u16 offset, void *buffer,
+ 				   const u16 buffer_length, const int timeout);
+ 
+-/*
++/**
++ * rt2x00usb_vendor_request_sw - Send single register command to device
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
++ * @offset: Register offset to perform action on
++ * @value: Value to write to device
++ * @timeout: Operation timeout
++ *
+  * Simple wrapper around rt2x00usb_vendor_request to write a single
+  * command to the device. Since we don't use the buffer argument we
+  * don't have to worry about kmalloc here.
+@@ -136,7 +174,12 @@ static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev,
+ 					value, NULL, 0, timeout);
+ }
+ 
+-/*
++/**
++ * rt2x00usb_eeprom_read - Read eeprom from device
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @eeprom: Pointer to eeprom array to store the information in
++ * @length: Number of bytes to read from the eeprom
++ *
+  * Simple wrapper around rt2x00usb_vendor_request to read the eeprom
+  * from the device. Note that the eeprom argument _must_ be allocated using
+  * kmalloc for correct handling inside the kernel USB layer.
+@@ -147,8 +190,8 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
+ 	int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16));
+ 
+ 	return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
+-					USB_VENDOR_REQUEST_IN, 0x0000,
+-					0x0000, eeprom, lenght, timeout);
++					USB_VENDOR_REQUEST_IN, 0, 0,
++					eeprom, lenght, timeout);
+ }
+ 
+ /*
+@@ -160,16 +203,58 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
+  * TX data handlers.
+  */
+ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+-			    struct data_ring *ring, struct sk_buff *skb,
++			    struct data_queue *queue, struct sk_buff *skb,
+ 			    struct ieee80211_tx_control *control);
+ 
++/**
++ * struct queue_entry_priv_usb_rx: Per RX entry USB specific information
++ *
++ * @urb: Urb structure used for device communication.
++ */
++struct queue_entry_priv_usb_rx {
++	struct urb *urb;
++};
++
++/**
++ * struct queue_entry_priv_usb_tx: Per TX entry USB specific information
++ *
++ * @urb: Urb structure used for device communication.
++ * @control: mac80211 control structure used to transmit data.
++ */
++struct queue_entry_priv_usb_tx {
++	struct urb *urb;
++
++	struct ieee80211_tx_control control;
++};
++
++/**
++ * struct queue_entry_priv_usb_tx: Per TX entry USB specific information
++ *
++ * The first section should match &struct queue_entry_priv_usb_tx exactly.
++ * rt2500usb can use this structure to send a guardian byte when working
++ * with beacons.
++ *
++ * @urb: Urb structure used for device communication.
++ * @control: mac80211 control structure used to transmit data.
++ * @guardian_data: Set to 0, used for sending the guardian data.
++ * @guardian_urb: Urb structure used to send the guardian data.
++ */
++struct queue_entry_priv_usb_bcn {
++	struct urb *urb;
++
++	struct ieee80211_tx_control control;
++
++	unsigned int guardian_data;
++	struct urb *guardian_urb;
++};
++
+ /*
+  * Device initialization handlers.
+  */
+ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+-			    struct data_entry *entry);
++			    struct queue_entry *entry);
+ void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+-			    struct data_entry *entry);
++			    struct queue_entry *entry);
+ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
+ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
+ 
+diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
+index ad2e7d5..468a31c 100644
+--- a/drivers/net/wireless/rt2x00/rt61pci.c
++++ b/drivers/net/wireless/rt2x00/rt61pci.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -24,6 +24,7 @@
+ 	Supported chipsets: RT2561, RT2561s, RT2661.
+  */
+ 
++#include <linux/crc-itu-t.h>
+ #include <linux/delay.h>
+ #include <linux/etherdevice.h>
+ #include <linux/init.h>
+@@ -155,6 +156,12 @@ rf_write:
+ 	rt2x00_rf_write(rt2x00dev, word, value);
+ }
+ 
++#ifdef CONFIG_RT61PCI_LEDS
++/*
++ * This function is only called from rt61pci_led_brightness()
++ * make gcc happy by placing this function inside the
++ * same ifdef statement as the caller.
++ */
+ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
+ 				const u8 command, const u8 token,
+ 				const u8 arg0, const u8 arg1)
+@@ -181,6 +188,7 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
+ 	rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
+ 	rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
+ }
++#endif /* CONFIG_RT61PCI_LEDS */
+ 
+ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
+ {
+@@ -262,82 +270,162 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+ 	u32 reg;
+ 
+ 	rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+-	return rt2x00_get_field32(reg, MAC_CSR13_BIT5);;
++	return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
+ }
+ #else
+ #define rt61pci_rfkill_poll	NULL
+ #endif /* CONFIG_RT61PCI_RFKILL */
+ 
+-/*
+- * Configuration handlers.
+- */
+-static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
++#ifdef CONFIG_RT61PCI_LEDS
++static void rt61pci_brightness_set(struct led_classdev *led_cdev,
++				   enum led_brightness brightness)
+ {
+-	u32 tmp;
+-
+-	tmp = le32_to_cpu(mac[1]);
+-	rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
+-	mac[1] = cpu_to_le32(tmp);
+-
+-	rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
+-				      (2 * sizeof(__le32)));
++	struct rt2x00_led *led =
++	    container_of(led_cdev, struct rt2x00_led, led_dev);
++	unsigned int enabled = brightness != LED_OFF;
++	unsigned int a_mode =
++	    (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
++	unsigned int bg_mode =
++	    (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
++
++	if (led->type == LED_TYPE_RADIO) {
++		rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++				   MCU_LEDCS_RADIO_STATUS, enabled);
++
++		rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
++				    (led->rt2x00dev->led_mcu_reg & 0xff),
++				    ((led->rt2x00dev->led_mcu_reg >> 8)));
++	} else if (led->type == LED_TYPE_ASSOC) {
++		rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++				   MCU_LEDCS_LINK_BG_STATUS, bg_mode);
++		rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++				   MCU_LEDCS_LINK_A_STATUS, a_mode);
++
++		rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
++				    (led->rt2x00dev->led_mcu_reg & 0xff),
++				    ((led->rt2x00dev->led_mcu_reg >> 8)));
++	} else if (led->type == LED_TYPE_QUALITY) {
++		/*
++		 * The brightness is divided into 6 levels (0 - 5),
++		 * this means we need to convert the brightness
++		 * argument into the matching level within that range.
++		 */
++		rt61pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
++				    brightness / (LED_FULL / 6), 0);
++	}
+ }
+ 
+-static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
++static int rt61pci_blink_set(struct led_classdev *led_cdev,
++			     unsigned long *delay_on,
++			     unsigned long *delay_off)
+ {
+-	u32 tmp;
++	struct rt2x00_led *led =
++	    container_of(led_cdev, struct rt2x00_led, led_dev);
++	u32 reg;
+ 
+-	tmp = le32_to_cpu(bssid[1]);
+-	rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
+-	bssid[1] = cpu_to_le32(tmp);
++	rt2x00pci_register_read(led->rt2x00dev, MAC_CSR14, &reg);
++	rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
++	rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
++	rt2x00pci_register_write(led->rt2x00dev, MAC_CSR14, reg);
+ 
+-	rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
+-				      (2 * sizeof(__le32)));
++	return 0;
+ }
++#endif /* CONFIG_RT61PCI_LEDS */
+ 
+-static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+-				const int tsf_sync)
++/*
++ * Configuration handlers.
++ */
++static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
++				  const unsigned int filter_flags)
+ {
+ 	u32 reg;
+ 
+ 	/*
+-	 * Clear current synchronisation setup.
+-	 * For the Beacon base registers we only need to clear
+-	 * the first byte since that byte contains the VALID and OWNER
+-	 * bits which (when set to 0) will invalidate the entire beacon.
++	 * Start configuration steps.
++	 * Note that the version error will always be dropped
++	 * and broadcast frames will always be accepted since
++	 * there is no filter for it at this time.
+ 	 */
+-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0);
+-	rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+-	rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+-	rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+-	rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
++	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
++			   !(filter_flags & FIF_FCSFAIL));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
++			   !(filter_flags & FIF_PLCPFAIL));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
++			   !(filter_flags & FIF_CONTROL));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
++			   !(filter_flags & FIF_PROMISC_IN_BSS));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
++			   !(filter_flags & FIF_PROMISC_IN_BSS) &&
++			   !rt2x00dev->intf_ap_count);
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
++			   !(filter_flags & FIF_ALLMULTI));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
++			   !(filter_flags & FIF_CONTROL));
++	rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
++}
+ 
+-	/*
+-	 * Enable synchronisation.
+-	 */
+-	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+-	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
+-	rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
+-			  (tsf_sync == TSF_SYNC_BEACON));
+-	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+-	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
+-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
++static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
++				struct rt2x00_intf *intf,
++				struct rt2x00intf_conf *conf,
++				const unsigned int flags)
++{
++	unsigned int beacon_base;
++	u32 reg;
++
++	if (flags & CONFIG_UPDATE_TYPE) {
++		/*
++		 * Clear current synchronisation setup.
++		 * For the Beacon base registers we only need to clear
++		 * the first byte since that byte contains the VALID and OWNER
++		 * bits which (when set to 0) will invalidate the entire beacon.
++		 */
++		beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
++		rt2x00pci_register_write(rt2x00dev, beacon_base, 0);
++
++		/*
++		 * Enable synchronisation.
++		 */
++		rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
++		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
++		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
++		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
++		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
++	}
++
++	if (flags & CONFIG_UPDATE_MAC) {
++		reg = le32_to_cpu(conf->mac[1]);
++		rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
++		conf->mac[1] = cpu_to_le32(reg);
++
++		rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2,
++					      conf->mac, sizeof(conf->mac));
++	}
++
++	if (flags & CONFIG_UPDATE_BSSID) {
++		reg = le32_to_cpu(conf->bssid[1]);
++		rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
++		conf->bssid[1] = cpu_to_le32(reg);
++
++		rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4,
++					      conf->bssid, sizeof(conf->bssid));
++	}
+ }
+ 
+-static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+-				    const int short_preamble,
+-				    const int ack_timeout,
+-				    const int ack_consume_time)
++static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
++			       struct rt2x00lib_erp *erp)
+ {
+ 	u32 reg;
+ 
+ 	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+-	rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
++	rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
+ 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ 
+ 	rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ 	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+-			   !!short_preamble);
++			   !!erp->short_preamble);
+ 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+ }
+ 
+@@ -427,27 +515,21 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
+ 	case ANTENNA_HW_DIVERSITY:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
+-				  (rt2x00dev->curr_hwmode != HWMODE_A));
++				  (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ));
+ 		break;
+ 	case ANTENNA_A:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+-		if (rt2x00dev->curr_hwmode == HWMODE_A)
++		if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+ 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ 		else
+ 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ 		break;
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+-		if (rt2x00dev->curr_hwmode == HWMODE_A)
++		if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+ 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ 		else
+ 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+@@ -486,14 +568,8 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ 		rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ 		break;
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ 		rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ 		break;
+@@ -531,10 +607,6 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
+ 	rt61pci_bbp_read(rt2x00dev, 4, &r4);
+ 	rt61pci_bbp_read(rt2x00dev, 77, &r77);
+ 
+-	/* FIXME: Antenna selection for the rf 2529 is very confusing in the
+-	 * legacy driver. The code below should be ok for non-diversity setups.
+-	 */
+-
+ 	/*
+ 	 * Configure the RX antenna.
+ 	 */
+@@ -544,15 +616,14 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
+ 		rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ 		rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
+ 		break;
+-	case ANTENNA_SW_DIVERSITY:
+ 	case ANTENNA_HW_DIVERSITY:
+ 		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
++		 * FIXME: Antenna selection for the rf 2529 is very confusing
++		 * in the legacy driver. Just default to antenna B until the
++		 * legacy code can be properly translated into rt2x00 code.
+ 		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ 		rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ 		rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
+@@ -603,7 +674,14 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	unsigned int i;
+ 	u32 reg;
+ 
+-	if (rt2x00dev->curr_hwmode == HWMODE_A) {
++	/*
++	 * We should never come here because rt2x00lib is supposed
++	 * to catch this and send us the correct antenna explicitely.
++	 */
++	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++	       ant->tx == ANTENNA_SW_DIVERSITY);
++
++	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+ 		sel = antenna_sel_a;
+ 		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+ 	} else {
+@@ -617,10 +695,9 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	rt2x00pci_register_read(rt2x00dev, PHY_CSR0, &reg);
+ 
+ 	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
+-			   (rt2x00dev->curr_hwmode == HWMODE_B ||
+-			    rt2x00dev->curr_hwmode == HWMODE_G));
++			   rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
+ 	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
+-			   (rt2x00dev->curr_hwmode == HWMODE_A));
++			   rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+ 
+ 	rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
+ 
+@@ -667,8 +744,8 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
+-			   const unsigned int flags,
+-			   struct rt2x00lib_conf *libconf)
++			   struct rt2x00lib_conf *libconf,
++			   const unsigned int flags)
+ {
+ 	if (flags & CONFIG_UPDATE_PHYMODE)
+ 		rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
+@@ -684,78 +761,6 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ /*
+- * LED functions.
+- */
+-static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	u32 reg;
+-	u8 arg0;
+-	u8 arg1;
+-
+-	rt2x00pci_register_read(rt2x00dev, MAC_CSR14, &reg);
+-	rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
+-	rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
+-	rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg);
+-
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
+-			   (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
+-			   (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
+-
+-	arg0 = rt2x00dev->led_reg & 0xff;
+-	arg1 = (rt2x00dev->led_reg >> 8) & 0xff;
+-
+-	rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
+-}
+-
+-static void rt61pci_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	u16 led_reg;
+-	u8 arg0;
+-	u8 arg1;
+-
+-	led_reg = rt2x00dev->led_reg;
+-	rt2x00_set_field16(&led_reg, MCU_LEDCS_RADIO_STATUS, 0);
+-	rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
+-	rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
+-
+-	arg0 = led_reg & 0xff;
+-	arg1 = (led_reg >> 8) & 0xff;
+-
+-	rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
+-}
+-
+-static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
+-{
+-	u8 led;
+-
+-	if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
+-		return;
+-
+-	/*
+-	 * Led handling requires a positive value for the rssi,
+-	 * to do that correctly we need to add the correction.
+-	 */
+-	rssi += rt2x00dev->rssi_offset;
+-
+-	if (rssi <= 30)
+-		led = 0;
+-	else if (rssi <= 39)
+-		led = 1;
+-	else if (rssi <= 49)
+-		led = 2;
+-	else if (rssi <= 53)
+-		led = 3;
+-	else if (rssi <= 63)
+-		led = 4;
+-	else
+-		led = 5;
+-
+-	rt61pci_mcu_request(rt2x00dev, MCU_LED_STRENGTH, 0xff, led, 0);
+-}
+-
+-/*
+  * Link tuning
+  */
+ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -789,17 +794,12 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 	u8 up_bound;
+ 	u8 low_bound;
+ 
+-	/*
+-	 * Update Led strength
+-	 */
+-	rt61pci_activity_led(rt2x00dev, rssi);
+-
+ 	rt61pci_bbp_read(rt2x00dev, 17, &r17);
+ 
+ 	/*
+ 	 * Determine r17 bounds.
+ 	 */
+-	if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
++	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ 		low_bound = 0x28;
+ 		up_bound = 0x48;
+ 		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+@@ -816,6 +816,13 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 	}
+ 
+ 	/*
++	 * If we are not associated, we should go straight to the
++	 * dynamic CCA tuning.
++	 */
++	if (!rt2x00dev->intf_associated)
++		goto dynamic_cca_tune;
++
++	/*
+ 	 * Special big-R17 for very short distance
+ 	 */
+ 	if (rssi >= -35) {
+@@ -866,6 +873,8 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 		return;
+ 	}
+ 
++dynamic_cca_tune:
++
+ 	/*
+ 	 * r17 does not yet exceed upper limit, continue and base
+ 	 * the r17 tuning on the false CCA count.
+@@ -882,7 +891,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ }
+ 
+ /*
+- * Firmware name function.
++ * Firmware functions
+  */
+ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -906,9 +915,23 @@ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ 	return fw_name;
+ }
+ 
+-/*
+- * Initialization functions.
+- */
++static u16 rt61pci_get_firmware_crc(void *data, const size_t len)
++{
++	u16 crc;
++
++	/*
++	 * Use the crc itu-t algorithm.
++	 * The last 2 bytes in the firmware array are the crc checksum itself,
++	 * this means that we should never pass those 2 bytes to the crc
++	 * algorithm.
++	 */
++	crc = crc_itu_t(0, data, len - 2);
++	crc = crc_itu_t_byte(crc, 0);
++	crc = crc_itu_t_byte(crc, 0);
++
++	return crc;
++}
++
+ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ 				 const size_t len)
+ {
+@@ -989,50 +1012,55 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ 	return 0;
+ }
+ 
++/*
++ * Initialization functions.
++ */
+ static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+-				 struct data_entry *entry)
++				 struct queue_entry *entry)
+ {
+-	__le32 *rxd = entry->priv;
++	struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ 	u32 word;
+ 
+-	rt2x00_desc_read(rxd, 5, &word);
++	rt2x00_desc_read(priv_rx->desc, 5, &word);
+ 	rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
+-			   entry->data_dma);
+-	rt2x00_desc_write(rxd, 5, word);
++			   priv_rx->data_dma);
++	rt2x00_desc_write(priv_rx->desc, 5, word);
+ 
+-	rt2x00_desc_read(rxd, 0, &word);
++	rt2x00_desc_read(priv_rx->desc, 0, &word);
+ 	rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+-	rt2x00_desc_write(rxd, 0, word);
++	rt2x00_desc_write(priv_rx->desc, 0, word);
+ }
+ 
+ static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+-				 struct data_entry *entry)
++				 struct queue_entry *entry)
+ {
+-	__le32 *txd = entry->priv;
++	struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
+ 	u32 word;
+ 
+-	rt2x00_desc_read(txd, 1, &word);
++	rt2x00_desc_read(priv_tx->desc, 1, &word);
+ 	rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
+-	rt2x00_desc_write(txd, 1, word);
++	rt2x00_desc_write(priv_tx->desc, 1, word);
+ 
+-	rt2x00_desc_read(txd, 5, &word);
+-	rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx);
++	rt2x00_desc_read(priv_tx->desc, 5, &word);
++	rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
+ 	rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
+-	rt2x00_desc_write(txd, 5, word);
++	rt2x00_desc_write(priv_tx->desc, 5, word);
+ 
+-	rt2x00_desc_read(txd, 6, &word);
++	rt2x00_desc_read(priv_tx->desc, 6, &word);
+ 	rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
+-			   entry->data_dma);
+-	rt2x00_desc_write(txd, 6, word);
++			   priv_tx->data_dma);
++	rt2x00_desc_write(priv_tx->desc, 6, word);
+ 
+-	rt2x00_desc_read(txd, 0, &word);
++	rt2x00_desc_read(priv_tx->desc, 0, &word);
+ 	rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ 	rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+-	rt2x00_desc_write(txd, 0, word);
++	rt2x00_desc_write(priv_tx->desc, 0, word);
+ }
+ 
+-static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
++static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
+ {
++	struct queue_entry_priv_pci_rx *priv_rx;
++	struct queue_entry_priv_pci_tx *priv_tx;
+ 	u32 reg;
+ 
+ 	/*
+@@ -1040,59 +1068,55 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
+ 	 */
+ 	rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, &reg);
+ 	rt2x00_set_field32(&reg, TX_RING_CSR0_AC0_RING_SIZE,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
++			   rt2x00dev->tx[0].limit);
+ 	rt2x00_set_field32(&reg, TX_RING_CSR0_AC1_RING_SIZE,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
++			   rt2x00dev->tx[1].limit);
+ 	rt2x00_set_field32(&reg, TX_RING_CSR0_AC2_RING_SIZE,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit);
++			   rt2x00dev->tx[2].limit);
+ 	rt2x00_set_field32(&reg, TX_RING_CSR0_AC3_RING_SIZE,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit);
++			   rt2x00dev->tx[3].limit);
+ 	rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg);
+ 
+ 	rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, &reg);
+-	rt2x00_set_field32(&reg, TX_RING_CSR1_MGMT_RING_SIZE,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit);
+ 	rt2x00_set_field32(&reg, TX_RING_CSR1_TXD_SIZE,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size /
+-			   4);
++			   rt2x00dev->tx[0].desc_size / 4);
+ 	rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
+ 
++	priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
+ 	rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
+ 
++	priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
+ 	rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
+ 
++	priv_tx = rt2x00dev->tx[2].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
+ 	rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
+ 
++	priv_tx = rt2x00dev->tx[3].entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
+ 	rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma);
++			   priv_tx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
+ 
+-	rt2x00pci_register_read(rt2x00dev, MGMT_BASE_CSR, &reg);
+-	rt2x00_set_field32(&reg, MGMT_BASE_CSR_RING_REGISTER,
+-			   rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma);
+-	rt2x00pci_register_write(rt2x00dev, MGMT_BASE_CSR, reg);
+-
+ 	rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, &reg);
+-	rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE,
+-			   rt2x00dev->rx->stats.limit);
++	rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
+ 	rt2x00_set_field32(&reg, RX_RING_CSR_RXD_SIZE,
+ 			   rt2x00dev->rx->desc_size / 4);
+ 	rt2x00_set_field32(&reg, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
+ 	rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg);
+ 
++	priv_rx = rt2x00dev->rx->entries[0].priv_data;
+ 	rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, &reg);
+ 	rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
+-			   rt2x00dev->rx->data_dma);
++			   priv_rx->desc_dma);
+ 	rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
+ 
+ 	rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
+@@ -1100,7 +1124,6 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
+ 	rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC1, 2);
+ 	rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC2, 2);
+ 	rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC3, 2);
+-	rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_MGMT, 0);
+ 	rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
+ 
+ 	rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
+@@ -1108,7 +1131,6 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
+ 	rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
+ 	rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
+ 	rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
+-	rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 1);
+ 	rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
+ 
+ 	rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+@@ -1224,6 +1246,17 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
+ 	rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
+ 
+ 	/*
++	 * Clear all beacons
++	 * For the Beacon base registers we only need to clear
++	 * the first byte since that byte contains the VALID and OWNER
++	 * bits which (when set to 0) will invalidate the entire beacon.
++	 */
++	rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
++	rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
++	rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
++	rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
++
++	/*
+ 	 * We must clear the error counters.
+ 	 * These registers are cleared on read,
+ 	 * so we may pass a useless variable to store the value.
+@@ -1296,19 +1329,15 @@ continue_csr_init:
+ 	rt61pci_bbp_write(rt2x00dev, 102, 0x16);
+ 	rt61pci_bbp_write(rt2x00dev, 107, 0x04);
+ 
+-	DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ 		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ 
+ 		if (eeprom != 0xffff && eeprom != 0x0000) {
+ 			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ 			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+-			DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+-			      reg_id, value);
+ 			rt61pci_bbp_write(rt2x00dev, reg_id, value);
+ 		}
+ 	}
+-	DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+ 
+ 	return 0;
+ }
+@@ -1375,7 +1404,7 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Initialize all registers.
+ 	 */
+-	if (rt61pci_init_rings(rt2x00dev) ||
++	if (rt61pci_init_queues(rt2x00dev) ||
+ 	    rt61pci_init_registers(rt2x00dev) ||
+ 	    rt61pci_init_bbp(rt2x00dev)) {
+ 		ERROR(rt2x00dev, "Register initialization failed.\n");
+@@ -1394,11 +1423,6 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ 	rt2x00_set_field32(&reg, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
+ 	rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg);
+ 
+-	/*
+-	 * Enable LED
+-	 */
+-	rt61pci_enable_led(rt2x00dev);
+-
+ 	return 0;
+ }
+ 
+@@ -1406,11 +1430,6 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+ 	u32 reg;
+ 
+-	/*
+-	 * Disable LED
+-	 */
+-	rt61pci_disable_led(rt2x00dev);
+-
+ 	rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+ 
+ 	/*
+@@ -1426,7 +1445,6 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+ 	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
+ 	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
+ 	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
+-	rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_MGMT, 1);
+ 	rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ 
+ 	/*
+@@ -1508,10 +1526,10 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+  */
+ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 				    struct sk_buff *skb,
+-				    struct txdata_entry_desc *desc,
++				    struct txentry_desc *txdesc,
+ 				    struct ieee80211_tx_control *control)
+ {
+-	struct skb_desc *skbdesc = get_skb_desc(skb);
++	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ 	__le32 *txd = skbdesc->desc;
+ 	u32 word;
+ 
+@@ -1519,50 +1537,52 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 	 * Start writing the descriptor words.
+ 	 */
+ 	rt2x00_desc_read(txd, 1, &word);
+-	rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
+-	rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
+-	rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
+-	rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
++	rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
++	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);
+ 	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+ 	rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
+ 	rt2x00_desc_write(txd, 1, word);
+ 
+ 	rt2x00_desc_read(txd, 2, &word);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+ 	rt2x00_desc_write(txd, 2, word);
+ 
+ 	rt2x00_desc_read(txd, 5, &word);
+ 	rt2x00_set_field32(&word, TXD_W5_TX_POWER,
+-			   TXPOWER_TO_DEV(control->power_level));
++			   TXPOWER_TO_DEV(rt2x00dev->tx_power));
+ 	rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
+ 	rt2x00_desc_write(txd, 5, word);
+ 
+-	rt2x00_desc_read(txd, 11, &word);
+-	rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
+-	rt2x00_desc_write(txd, 11, word);
++	if (skbdesc->desc_len > TXINFO_SIZE) {
++		rt2x00_desc_read(txd, 11, &word);
++		rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
++		rt2x00_desc_write(txd, 11, word);
++	}
+ 
+ 	rt2x00_desc_read(txd, 0, &word);
+ 	rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
+ 	rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+ 	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+-			   test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_ACK,
+-			   test_bit(ENTRY_TXD_ACK, &desc->flags));
++			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+-			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_OFDM,
+-			   test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
+-	rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++			   test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
++	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+ 			   !!(control->flags &
+ 			      IEEE80211_TXCTL_LONG_RETRY_LIMIT));
+ 	rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
+ 	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
+ 	rt2x00_set_field32(&word, TXD_W0_BURST,
+-			   test_bit(ENTRY_TXD_BURST, &desc->flags));
++			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+ 	rt2x00_desc_write(txd, 0, word);
+ }
+@@ -1571,11 +1591,11 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+  * TX data initialization
+  */
+ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+-				  unsigned int queue)
++				  const unsigned int queue)
+ {
+ 	u32 reg;
+ 
+-	if (queue == IEEE80211_TX_QUEUE_BEACON) {
++	if (queue == RT2X00_BCN_QUEUE_BEACON) {
+ 		/*
+ 		 * For Wi-Fi faily generated beacons between participating
+ 		 * stations. Set TBTT phase adaptive adjustment step to 8us.
+@@ -1584,6 +1604,8 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ 
+ 		rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ 		if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
++			rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
++			rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+ 			rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+ 			rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ 		}
+@@ -1599,8 +1621,6 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ 			   (queue == IEEE80211_TX_QUEUE_DATA2));
+ 	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3,
+ 			   (queue == IEEE80211_TX_QUEUE_DATA3));
+-	rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_MGMT,
+-			   (queue == IEEE80211_TX_QUEUE_DATA4));
+ 	rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ }
+ 
+@@ -1628,7 +1648,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+ 		return 0;
+ 	}
+ 
+-	if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
++	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ 		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+ 			offset += 14;
+ 
+@@ -1648,28 +1668,35 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+ 	return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
+ }
+ 
+-static void rt61pci_fill_rxdone(struct data_entry *entry,
+-			        struct rxdata_entry_desc *desc)
++static void rt61pci_fill_rxdone(struct queue_entry *entry,
++			        struct rxdone_entry_desc *rxdesc)
+ {
+-	__le32 *rxd = entry->priv;
++	struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ 	u32 word0;
+ 	u32 word1;
+ 
+-	rt2x00_desc_read(rxd, 0, &word0);
+-	rt2x00_desc_read(rxd, 1, &word1);
++	rt2x00_desc_read(priv_rx->desc, 0, &word0);
++	rt2x00_desc_read(priv_rx->desc, 1, &word1);
+ 
+-	desc->flags = 0;
++	rxdesc->flags = 0;
+ 	if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+-		desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ 
+ 	/*
+ 	 * Obtain the status about this packet.
+-	 */
+-	desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+-	desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
+-	desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+-	desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+-	desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++	 * When frame was received with an OFDM bitrate,
++	 * the signal is the PLCP value. If it was received with
++	 * a CCK bitrate the signal is the rate in 100kbit/s.
++	 */
++	rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
++	rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1);
++	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++	rxdesc->dev_flags = 0;
++	if (rt2x00_get_field32(word0, RXD_W0_OFDM))
++		rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
++	if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++		rxdesc->dev_flags |= RXDONE_MY_BSS;
+ }
+ 
+ /*
+@@ -1677,17 +1704,16 @@ static void rt61pci_fill_rxdone(struct data_entry *entry,
+  */
+ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
+ {
+-	struct data_ring *ring;
+-	struct data_entry *entry;
+-	struct data_entry *entry_done;
+-	__le32 *txd;
++	struct data_queue *queue;
++	struct queue_entry *entry;
++	struct queue_entry *entry_done;
++	struct queue_entry_priv_pci_tx *priv_tx;
++	struct txdone_entry_desc txdesc;
+ 	u32 word;
+ 	u32 reg;
+ 	u32 old_reg;
+ 	int type;
+ 	int index;
+-	int tx_status;
+-	int retry;
+ 
+ 	/*
+ 	 * During each loop we will compare the freshly read
+@@ -1710,11 +1736,11 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
+ 
+ 		/*
+ 		 * Skip this entry when it contains an invalid
+-		 * ring identication number.
++		 * queue identication number.
+ 		 */
+ 		type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
+-		ring = rt2x00lib_get_ring(rt2x00dev, type);
+-		if (unlikely(!ring))
++		queue = rt2x00queue_get_queue(rt2x00dev, type);
++		if (unlikely(!queue))
+ 			continue;
+ 
+ 		/*
+@@ -1722,36 +1748,40 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
+ 		 * index number.
+ 		 */
+ 		index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE);
+-		if (unlikely(index >= ring->stats.limit))
++		if (unlikely(index >= queue->limit))
+ 			continue;
+ 
+-		entry = &ring->entry[index];
+-		txd = entry->priv;
+-		rt2x00_desc_read(txd, 0, &word);
++		entry = &queue->entries[index];
++		priv_tx = entry->priv_data;
++		rt2x00_desc_read(priv_tx->desc, 0, &word);
+ 
+ 		if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ 		    !rt2x00_get_field32(word, TXD_W0_VALID))
+ 			return;
+ 
+-		entry_done = rt2x00_get_data_entry_done(ring);
++		entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ 		while (entry != entry_done) {
+-			/* Catch up. Just report any entries we missed as
+-			 * failed. */
++			/* Catch up.
++			 * Just report any entries we missed as failed.
++			 */
+ 			WARNING(rt2x00dev,
+-				"TX status report missed for entry %p\n",
+-				entry_done);
+-			rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER,
+-					 0);
+-			entry_done = rt2x00_get_data_entry_done(ring);
++				"TX status report missed for entry %d\n",
++				entry_done->entry_idx);
++
++			txdesc.status = TX_FAIL_OTHER;
++			txdesc.retry = 0;
++
++			rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
++			entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ 		}
+ 
+ 		/*
+ 		 * Obtain the status about this packet.
+ 		 */
+-		tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
+-		retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
++		txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
++		txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
+ 
+-		rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
++		rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
+ 	}
+ }
+ 
+@@ -1906,7 +1936,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ 		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+ 		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+ 		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+-		EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
++		EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+ 	} else {
+ 		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
+ 		if (value < -10 || value > 10)
+@@ -2035,35 +2065,61 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ 	 * If the eeprom value is invalid,
+ 	 * switch to default led mode.
+ 	 */
++#ifdef CONFIG_RT61PCI_LEDS
+ 	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
++	value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
++
++	rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++	rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++	rt2x00dev->led_radio.led_dev.brightness_set =
++	    rt61pci_brightness_set;
++	rt2x00dev->led_radio.led_dev.blink_set =
++	    rt61pci_blink_set;
++	rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++	rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
++	rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
++	rt2x00dev->led_assoc.led_dev.brightness_set =
++	    rt61pci_brightness_set;
++	rt2x00dev->led_assoc.led_dev.blink_set =
++	    rt61pci_blink_set;
++	rt2x00dev->led_assoc.flags = LED_INITIALIZED;
++
++	if (value == LED_MODE_SIGNAL_STRENGTH) {
++		rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++		rt2x00dev->led_radio.type = LED_TYPE_QUALITY;
++		rt2x00dev->led_qual.led_dev.brightness_set =
++		    rt61pci_brightness_set;
++		rt2x00dev->led_qual.led_dev.blink_set =
++		    rt61pci_blink_set;
++		rt2x00dev->led_qual.flags = LED_INITIALIZED;
++	}
+ 
+-	rt2x00dev->led_mode = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
+-
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
+-			   rt2x00dev->led_mode);
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_0));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_1));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_2));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_3));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_4));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
+ 			   rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_RDY_G));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_RDY_A));
++#endif /* CONFIG_RT61PCI_LEDS */
+ 
+ 	return 0;
+ }
+@@ -2197,7 +2253,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 	rt2x00dev->hw->extra_tx_headroom = 0;
+ 	rt2x00dev->hw->max_signal = MAX_SIGNAL;
+ 	rt2x00dev->hw->max_rssi = MAX_RX_SSI;
+-	rt2x00dev->hw->queues = 5;
++	rt2x00dev->hw->queues = 4;
+ 
+ 	SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
+ 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+@@ -2214,8 +2270,8 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Initialize hw_mode information.
+ 	 */
+-	spec->num_modes = 2;
+-	spec->num_rates = 12;
++	spec->supported_bands = SUPPORT_BAND_2GHZ;
++	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+ 	spec->tx_power_a = NULL;
+ 	spec->tx_power_bg = txpower;
+ 	spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -2230,7 +2286,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 
+ 	if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ 	    rt2x00_rf(&rt2x00dev->chip, RF5325)) {
+-		spec->num_modes = 3;
++		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ 		spec->num_channels = ARRAY_SIZE(rf_vals_seq);
+ 
+ 		txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
+@@ -2262,7 +2318,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ 	rt61pci_probe_hw_mode(rt2x00dev);
+ 
+ 	/*
+-	 * This device requires firmware
++	 * This device requires firmware.
+ 	 */
+ 	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
+ 
+@@ -2277,70 +2333,6 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+  * IEEE80211 stack callback functions.
+  */
+-static void rt61pci_configure_filter(struct ieee80211_hw *hw,
+-				     unsigned int changed_flags,
+-				     unsigned int *total_flags,
+-				     int mc_count,
+-				     struct dev_addr_list *mc_list)
+-{
+-	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	u32 reg;
+-
+-	/*
+-	 * Mask off any flags we are going to ignore from
+-	 * the total_flags field.
+-	 */
+-	*total_flags &=
+-	    FIF_ALLMULTI |
+-	    FIF_FCSFAIL |
+-	    FIF_PLCPFAIL |
+-	    FIF_CONTROL |
+-	    FIF_OTHER_BSS |
+-	    FIF_PROMISC_IN_BSS;
+-
+-	/*
+-	 * Apply some rules to the filters:
+-	 * - Some filters imply different filters to be set.
+-	 * - Some things we can't filter out at all.
+-	 * - Multicast filter seems to kill broadcast traffic so never use it.
+-	 */
+-	*total_flags |= FIF_ALLMULTI;
+-	if (*total_flags & FIF_OTHER_BSS ||
+-	    *total_flags & FIF_PROMISC_IN_BSS)
+-		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+-	/*
+-	 * Check if there is any work left for us.
+-	 */
+-	if (rt2x00dev->packet_filter == *total_flags)
+-		return;
+-	rt2x00dev->packet_filter = *total_flags;
+-
+-	/*
+-	 * Start configuration steps.
+-	 * Note that the version error will always be dropped
+-	 * and broadcast frames will always be accepted since
+-	 * there is no filter for it at this time.
+-	 */
+-	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
+-			   !(*total_flags & FIF_FCSFAIL));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
+-			   !(*total_flags & FIF_PLCPFAIL));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
+-			   !(*total_flags & FIF_CONTROL));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
+-			   !(*total_flags & FIF_ALLMULTI));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BORADCAST, 0);
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
+-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+-}
+-
+ static int rt61pci_set_retry_limit(struct ieee80211_hw *hw,
+ 				   u32 short_retry, u32 long_retry)
+ {
+@@ -2369,66 +2361,72 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
+ 	return tsf;
+ }
+ 
+-static void rt61pci_reset_tsf(struct ieee80211_hw *hw)
+-{
+-	struct rt2x00_dev *rt2x00dev = hw->priv;
+-
+-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR12, 0);
+-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR13, 0);
+-}
+-
+ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+ 			  struct ieee80211_tx_control *control)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	struct skb_desc *desc;
+-	struct data_ring *ring;
+-	struct data_entry *entry;
++	struct rt2x00_intf *intf = vif_to_intf(control->vif);
++	struct skb_frame_desc *skbdesc;
++	unsigned int beacon_base;
++	u32 reg;
+ 
+-	/*
+-	 * Just in case the ieee80211 doesn't set this,
+-	 * but we need this queue set for the descriptor
+-	 * initialization.
+-	 */
+-	control->queue = IEEE80211_TX_QUEUE_BEACON;
+-	ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+-	entry = rt2x00_get_data_entry(ring);
++	if (unlikely(!intf->beacon))
++		return -ENOBUFS;
+ 
+ 	/*
+ 	 * We need to append the descriptor in front of the
+ 	 * beacon frame.
+ 	 */
+-	if (skb_headroom(skb) < TXD_DESC_SIZE) {
+-		if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC))
++	if (skb_headroom(skb) < intf->beacon->queue->desc_size) {
++		if (pskb_expand_head(skb, intf->beacon->queue->desc_size,
++				     0, GFP_ATOMIC))
+ 			return -ENOMEM;
+ 	}
+ 
+ 	/*
+ 	 * Add the descriptor in front of the skb.
+ 	 */
+-	skb_push(skb, ring->desc_size);
+-	memset(skb->data, 0, ring->desc_size);
++	skb_push(skb, intf->beacon->queue->desc_size);
++	memset(skb->data, 0, intf->beacon->queue->desc_size);
+ 
+ 	/*
+ 	 * Fill in skb descriptor
+ 	 */
+-	desc = get_skb_desc(skb);
+-	desc->desc_len = ring->desc_size;
+-	desc->data_len = skb->len - ring->desc_size;
+-	desc->desc = skb->data;
+-	desc->data = skb->data + ring->desc_size;
+-	desc->ring = ring;
+-	desc->entry = entry;
++	skbdesc = get_skb_frame_desc(skb);
++	memset(skbdesc, 0, sizeof(*skbdesc));
++	skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++	skbdesc->data = skb->data + intf->beacon->queue->desc_size;
++	skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
++	skbdesc->desc = skb->data;
++	skbdesc->desc_len = intf->beacon->queue->desc_size;
++	skbdesc->entry = intf->beacon;
++
++	/*
++	 * Disable beaconing while we are reloading the beacon data,
++	 * otherwise we might be sending out invalid data.
++	 */
++	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
++	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
++	rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
++	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
++	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ 
++	/*
++	 * mac80211 doesn't provide the control->queue variable
++	 * for beacons. Set our own queue identification so
++	 * it can be used during descriptor initialization.
++	 */
++	control->queue = RT2X00_BCN_QUEUE_BEACON;
+ 	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+ 
+ 	/*
+ 	 * Write entire beacon with descriptor to register,
+ 	 * and kick the beacon generator.
+ 	 */
+-	rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0,
++	beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
++	rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
+ 				      skb->data, skb->len);
+-	rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
++	rt61pci_kick_tx_queue(rt2x00dev, control->queue);
+ 
+ 	return 0;
+ }
+@@ -2441,14 +2439,13 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
+ 	.remove_interface	= rt2x00mac_remove_interface,
+ 	.config			= rt2x00mac_config,
+ 	.config_interface	= rt2x00mac_config_interface,
+-	.configure_filter	= rt61pci_configure_filter,
++	.configure_filter	= rt2x00mac_configure_filter,
+ 	.get_stats		= rt2x00mac_get_stats,
+ 	.set_retry_limit	= rt61pci_set_retry_limit,
+ 	.bss_info_changed	= rt2x00mac_bss_info_changed,
+ 	.conf_tx		= rt2x00mac_conf_tx,
+ 	.get_tx_stats		= rt2x00mac_get_tx_stats,
+ 	.get_tsf		= rt61pci_get_tsf,
+-	.reset_tsf		= rt61pci_reset_tsf,
+ 	.beacon_update		= rt61pci_beacon_update,
+ };
+ 
+@@ -2456,6 +2453,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
+ 	.irq_handler		= rt61pci_interrupt,
+ 	.probe_hw		= rt61pci_probe_hw,
+ 	.get_firmware_name	= rt61pci_get_firmware_name,
++	.get_firmware_crc	= rt61pci_get_firmware_crc,
+ 	.load_firmware		= rt61pci_load_firmware,
+ 	.initialize		= rt2x00pci_initialize,
+ 	.uninitialize		= rt2x00pci_uninitialize,
+@@ -2470,19 +2468,42 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
+ 	.write_tx_data		= rt2x00pci_write_tx_data,
+ 	.kick_tx_queue		= rt61pci_kick_tx_queue,
+ 	.fill_rxdone		= rt61pci_fill_rxdone,
+-	.config_mac_addr	= rt61pci_config_mac_addr,
+-	.config_bssid		= rt61pci_config_bssid,
+-	.config_type		= rt61pci_config_type,
+-	.config_preamble	= rt61pci_config_preamble,
++	.config_filter		= rt61pci_config_filter,
++	.config_intf		= rt61pci_config_intf,
++	.config_erp		= rt61pci_config_erp,
+ 	.config			= rt61pci_config,
+ };
+ 
++static const struct data_queue_desc rt61pci_queue_rx = {
++	.entry_num		= RX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= RXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_rx),
++};
++
++static const struct data_queue_desc rt61pci_queue_tx = {
++	.entry_num		= TX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt61pci_queue_bcn = {
++	.entry_num		= 4 * BEACON_ENTRIES,
++	.data_size		= MGMT_FRAME_SIZE,
++	.desc_size		= TXINFO_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_pci_tx),
++};
++
+ static const struct rt2x00_ops rt61pci_ops = {
+ 	.name		= KBUILD_MODNAME,
+-	.rxd_size	= RXD_DESC_SIZE,
+-	.txd_size	= TXD_DESC_SIZE,
++	.max_sta_intf	= 1,
++	.max_ap_intf	= 4,
+ 	.eeprom_size	= EEPROM_SIZE,
+ 	.rf_size	= RF_SIZE,
++	.rx		= &rt61pci_queue_rx,
++	.tx		= &rt61pci_queue_tx,
++	.bcn		= &rt61pci_queue_bcn,
+ 	.lib		= &rt61pci_rt2x00_ops,
+ 	.hw		= &rt61pci_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
+index 4c6524e..3511bba 100644
+--- a/drivers/net/wireless/rt2x00/rt61pci.h
++++ b/drivers/net/wireless/rt2x00/rt61pci.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -161,7 +161,9 @@ struct hw_pairwise_ta_entry {
+ #define HW_BEACON_BASE1			0x2d00
+ #define HW_BEACON_BASE2			0x2e00
+ #define HW_BEACON_BASE3			0x2f00
+-#define HW_BEACON_OFFSET		0x0100
++
++#define HW_BEACON_OFFSET(__index) \
++	( HW_BEACON_BASE0 + (__index * 0x0100) )
+ 
+ /*
+  * HOST-MCU shared memory.
+@@ -234,6 +236,11 @@ struct hw_pairwise_ta_entry {
+ 
+ /*
+  * MAC_CSR3: STA MAC register 1.
++ * UNICAST_TO_ME_MASK:
++ *	Used to mask off bits from byte 5 of the MAC address
++ *	to determine the UNICAST_TO_ME bit for RX frames.
++ *	The full mask is complemented by BSS_ID_MASK:
++ *		MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
+  */
+ #define MAC_CSR3			0x300c
+ #define MAC_CSR3_BYTE4			FIELD32(0x000000ff)
+@@ -251,7 +258,14 @@ struct hw_pairwise_ta_entry {
+ 
+ /*
+  * MAC_CSR5: BSSID register 1.
+- * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID.
++ * BSS_ID_MASK:
++ *	This mask is used to mask off bits 0 and 1 of byte 5 of the
++ *	BSSID. This will make sure that those bits will be ignored
++ *	when determining the MY_BSS of RX frames.
++ *		0: 1-BSSID mode (BSS index = 0)
++ *		1: 2-BSSID mode (BSS index: Byte5, bit 0)
++ *		2: 2-BSSID mode (BSS index: byte5, bit 1)
++ *		3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
+  */
+ #define MAC_CSR5			0x3014
+ #define MAC_CSR5_BYTE4			FIELD32(0x000000ff)
+@@ -391,7 +405,7 @@ struct hw_pairwise_ta_entry {
+ #define TXRX_CSR0_DROP_TO_DS		FIELD32(0x00200000)
+ #define TXRX_CSR0_DROP_VERSION_ERROR	FIELD32(0x00400000)
+ #define TXRX_CSR0_DROP_MULTICAST	FIELD32(0x00800000)
+-#define TXRX_CSR0_DROP_BORADCAST	FIELD32(0x01000000)
++#define TXRX_CSR0_DROP_BROADCAST	FIELD32(0x01000000)
+ #define TXRX_CSR0_DROP_ACK_CTS		FIELD32(0x02000000)
+ #define TXRX_CSR0_TX_WITHOUT_WAITING	FIELD32(0x04000000)
+ 
+@@ -866,7 +880,7 @@ struct hw_pairwise_ta_entry {
+ #define TX_CNTL_CSR_ABORT_TX_MGMT	FIELD32(0x00100000)
+ 
+ /*
+- * LOAD_TX_RING_CSR: Load RX de
++ * LOAD_TX_RING_CSR: Load RX desriptor
+  */
+ #define LOAD_TX_RING_CSR		0x3434
+ #define LOAD_TX_RING_CSR_LOAD_TXD_AC0	FIELD32(0x00000001)
+@@ -1116,10 +1130,10 @@ struct hw_pairwise_ta_entry {
+ #define EEPROM_MAC_ADDR_0		0x0002
+ #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
+ #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+-#define EEPROM_MAC_ADDR1		0x0004
++#define EEPROM_MAC_ADDR1		0x0003
+ #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
+ #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+-#define EEPROM_MAC_ADDR_2		0x0006
++#define EEPROM_MAC_ADDR_2		0x0004
+ #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
+ #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
+ 
+@@ -1247,6 +1261,7 @@ struct hw_pairwise_ta_entry {
+  * DMA descriptor defines.
+  */
+ #define TXD_DESC_SIZE			( 16 * sizeof(__le32) )
++#define TXINFO_SIZE			( 6 * sizeof(__le32) )
+ #define RXD_DESC_SIZE			( 16 * sizeof(__le32) )
+ 
+ /*
+@@ -1440,8 +1455,8 @@ struct hw_pairwise_ta_entry {
+ #define RXD_W15_RESERVED		FIELD32(0xffffffff)
+ 
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+  */
+ #define MIN_TXPOWER	0
+ #define MAX_TXPOWER	31
+diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
+index 3909cf4..a9efe25 100644
+--- a/drivers/net/wireless/rt2x00/rt73usb.c
++++ b/drivers/net/wireless/rt2x00/rt73usb.c
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -24,6 +24,7 @@
+ 	Supported chipsets: rt2571W & rt2671.
+  */
+ 
++#include <linux/crc-itu-t.h>
+ #include <linux/delay.h>
+ #include <linux/etherdevice.h>
+ #include <linux/init.h>
+@@ -278,85 +279,158 @@ static const struct rt2x00debug rt73usb_rt2x00debug = {
+ };
+ #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+ 
+-/*
+- * Configuration handlers.
+- */
+-static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
++#ifdef CONFIG_RT73USB_LEDS
++static void rt73usb_brightness_set(struct led_classdev *led_cdev,
++				   enum led_brightness brightness)
+ {
+-	u32 tmp;
+-
+-	tmp = le32_to_cpu(mac[1]);
+-	rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
+-	mac[1] = cpu_to_le32(tmp);
+-
+-	rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
+-				    (2 * sizeof(__le32)));
++	struct rt2x00_led *led =
++	   container_of(led_cdev, struct rt2x00_led, led_dev);
++	unsigned int enabled = brightness != LED_OFF;
++	unsigned int a_mode =
++	    (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
++	unsigned int bg_mode =
++	    (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
++
++	if (led->type == LED_TYPE_RADIO) {
++		rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++				   MCU_LEDCS_RADIO_STATUS, enabled);
++
++		rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
++					    0, led->rt2x00dev->led_mcu_reg,
++					    REGISTER_TIMEOUT);
++	} else if (led->type == LED_TYPE_ASSOC) {
++		rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++				   MCU_LEDCS_LINK_BG_STATUS, bg_mode);
++		rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++				   MCU_LEDCS_LINK_A_STATUS, a_mode);
++
++		rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
++					    0, led->rt2x00dev->led_mcu_reg,
++					    REGISTER_TIMEOUT);
++	} else if (led->type == LED_TYPE_QUALITY) {
++		/*
++		 * The brightness is divided into 6 levels (0 - 5),
++		 * this means we need to convert the brightness
++		 * argument into the matching level within that range.
++		 */
++		rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
++					    brightness / (LED_FULL / 6),
++					    led->rt2x00dev->led_mcu_reg,
++					    REGISTER_TIMEOUT);
++	}
+ }
+ 
+-static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
++static int rt73usb_blink_set(struct led_classdev *led_cdev,
++			     unsigned long *delay_on,
++			     unsigned long *delay_off)
+ {
+-	u32 tmp;
++	struct rt2x00_led *led =
++	    container_of(led_cdev, struct rt2x00_led, led_dev);
++	u32 reg;
+ 
+-	tmp = le32_to_cpu(bssid[1]);
+-	rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
+-	bssid[1] = cpu_to_le32(tmp);
++	rt73usb_register_read(led->rt2x00dev, MAC_CSR14, &reg);
++	rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
++	rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
++	rt73usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
+ 
+-	rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
+-				    (2 * sizeof(__le32)));
++	return 0;
+ }
++#endif /* CONFIG_RT73USB_LEDS */
+ 
+-static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+-				const int tsf_sync)
++/*
++ * Configuration handlers.
++ */
++static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
++				  const unsigned int filter_flags)
+ {
+ 	u32 reg;
+ 
+ 	/*
+-	 * Clear current synchronisation setup.
+-	 * For the Beacon base registers we only need to clear
+-	 * the first byte since that byte contains the VALID and OWNER
+-	 * bits which (when set to 0) will invalidate the entire beacon.
+-	 */
+-	rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0);
+-	rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+-	rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+-	rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+-	rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+-
+-	/*
+-	 * Enable synchronisation.
++	 * Start configuration steps.
++	 * Note that the version error will always be dropped
++	 * and broadcast frames will always be accepted since
++	 * there is no filter for it at this time.
+ 	 */
+-	rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+-	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
+-	rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
+-			   (tsf_sync == TSF_SYNC_BEACON));
+-	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+-	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
+-	rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
++	rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
++			   !(filter_flags & FIF_FCSFAIL));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
++			   !(filter_flags & FIF_PLCPFAIL));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
++			   !(filter_flags & FIF_CONTROL));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
++			   !(filter_flags & FIF_PROMISC_IN_BSS));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
++			   !(filter_flags & FIF_PROMISC_IN_BSS) &&
++			   !rt2x00dev->intf_ap_count);
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
++			   !(filter_flags & FIF_ALLMULTI));
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
++	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
++			   !(filter_flags & FIF_CONTROL));
++	rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+ }
+ 
+-static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
+-				      const int short_preamble,
+-				      const int ack_timeout,
+-				      const int ack_consume_time)
++static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
++				struct rt2x00_intf *intf,
++				struct rt2x00intf_conf *conf,
++				const unsigned int flags)
+ {
++	unsigned int beacon_base;
+ 	u32 reg;
+ 
+-	/*
+-	 * When in atomic context, reschedule and let rt2x00lib
+-	 * call this function again.
+-	 */
+-	if (in_atomic()) {
+-		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
+-		return;
++	if (flags & CONFIG_UPDATE_TYPE) {
++		/*
++		 * Clear current synchronisation setup.
++		 * For the Beacon base registers we only need to clear
++		 * the first byte since that byte contains the VALID and OWNER
++		 * bits which (when set to 0) will invalidate the entire beacon.
++		 */
++		beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
++		rt73usb_register_write(rt2x00dev, beacon_base, 0);
++
++		/*
++		 * Enable synchronisation.
++		 */
++		rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
++		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
++		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
++		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
++		rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ 	}
+ 
++	if (flags & CONFIG_UPDATE_MAC) {
++		reg = le32_to_cpu(conf->mac[1]);
++		rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
++		conf->mac[1] = cpu_to_le32(reg);
++
++		rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2,
++					    conf->mac, sizeof(conf->mac));
++	}
++
++	if (flags & CONFIG_UPDATE_BSSID) {
++		reg = le32_to_cpu(conf->bssid[1]);
++		rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
++		conf->bssid[1] = cpu_to_le32(reg);
++
++		rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4,
++					    conf->bssid, sizeof(conf->bssid));
++	}
++}
++
++static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
++			       struct rt2x00lib_erp *erp)
++{
++	u32 reg;
++
+ 	rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+-	rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
++	rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
+ 	rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+ 
+ 	rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ 	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+-			   !!short_preamble);
++			   !!erp->short_preamble);
+ 	rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+ }
+ 
+@@ -442,28 +516,22 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
+ 	case ANTENNA_HW_DIVERSITY:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
+ 		temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
+-		       && (rt2x00dev->curr_hwmode != HWMODE_A);
++		       && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
+ 		break;
+ 	case ANTENNA_A:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+-		if (rt2x00dev->curr_hwmode == HWMODE_A)
++		if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+ 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ 		else
+ 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ 		break;
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+-		if (rt2x00dev->curr_hwmode == HWMODE_A)
++		if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+ 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ 		else
+ 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+@@ -501,14 +569,8 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
+ 		rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ 		break;
+-	case ANTENNA_SW_DIVERSITY:
+-		/*
+-		 * NOTE: We should never come here because rt2x00lib is
+-		 * supposed to catch this and send us the correct antenna
+-		 * explicitely. However we are nog going to bug about this.
+-		 * Instead, just default to antenna B.
+-		 */
+ 	case ANTENNA_B:
++	default:
+ 		rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ 		break;
+@@ -558,7 +620,14 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	unsigned int i;
+ 	u32 reg;
+ 
+-	if (rt2x00dev->curr_hwmode == HWMODE_A) {
++	/*
++	 * We should never come here because rt2x00lib is supposed
++	 * to catch this and send us the correct antenna explicitely.
++	 */
++	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++	       ant->tx == ANTENNA_SW_DIVERSITY);
++
++	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+ 		sel = antenna_sel_a;
+ 		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+ 	} else {
+@@ -572,10 +641,9 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ 	rt73usb_register_read(rt2x00dev, PHY_CSR0, &reg);
+ 
+ 	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
+-			   (rt2x00dev->curr_hwmode == HWMODE_B ||
+-			    rt2x00dev->curr_hwmode == HWMODE_G));
++			   (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
+ 	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
+-			   (rt2x00dev->curr_hwmode == HWMODE_A));
++			   (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
+ 
+ 	rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
+ 
+@@ -617,8 +685,8 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
+-			   const unsigned int flags,
+-			   struct rt2x00lib_conf *libconf)
++			   struct rt2x00lib_conf *libconf,
++			   const unsigned int flags)
+ {
+ 	if (flags & CONFIG_UPDATE_PHYMODE)
+ 		rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
+@@ -634,68 +702,6 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
+ }
+ 
+ /*
+- * LED functions.
+- */
+-static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	u32 reg;
+-
+-	rt73usb_register_read(rt2x00dev, MAC_CSR14, &reg);
+-	rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
+-	rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
+-	rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
+-
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
+-			   (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
+-			   (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
+-
+-	rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
+-				    rt2x00dev->led_reg, REGISTER_TIMEOUT);
+-}
+-
+-static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 0);
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
+-
+-	rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
+-				    rt2x00dev->led_reg, REGISTER_TIMEOUT);
+-}
+-
+-static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
+-{
+-	u32 led;
+-
+-	if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
+-		return;
+-
+-	/*
+-	 * Led handling requires a positive value for the rssi,
+-	 * to do that correctly we need to add the correction.
+-	 */
+-	rssi += rt2x00dev->rssi_offset;
+-
+-	if (rssi <= 30)
+-		led = 0;
+-	else if (rssi <= 39)
+-		led = 1;
+-	else if (rssi <= 49)
+-		led = 2;
+-	else if (rssi <= 53)
+-		led = 3;
+-	else if (rssi <= 63)
+-		led = 4;
+-	else
+-		led = 5;
+-
+-	rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led,
+-				    rt2x00dev->led_reg, REGISTER_TIMEOUT);
+-}
+-
+-/*
+  * Link tuning
+  */
+ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -729,17 +735,12 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 	u8 up_bound;
+ 	u8 low_bound;
+ 
+-	/*
+-	 * Update Led strength
+-	 */
+-	rt73usb_activity_led(rt2x00dev, rssi);
+-
+ 	rt73usb_bbp_read(rt2x00dev, 17, &r17);
+ 
+ 	/*
+ 	 * Determine r17 bounds.
+ 	 */
+-	if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
++	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ 		low_bound = 0x28;
+ 		up_bound = 0x48;
+ 
+@@ -766,6 +767,13 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 	}
+ 
+ 	/*
++	 * If we are not associated, we should go straight to the
++	 * dynamic CCA tuning.
++	 */
++	if (!rt2x00dev->intf_associated)
++		goto dynamic_cca_tune;
++
++	/*
+ 	 * Special big-R17 for very short distance
+ 	 */
+ 	if (rssi > -35) {
+@@ -815,6 +823,8 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ 		return;
+ 	}
+ 
++dynamic_cca_tune:
++
+ 	/*
+ 	 * r17 does not yet exceed upper limit, continue and base
+ 	 * the r17 tuning on the false CCA count.
+@@ -833,16 +843,30 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ }
+ 
+ /*
+- * Firmware name function.
++ * Firmware functions
+  */
+ static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ {
+ 	return FIRMWARE_RT2571;
+ }
+ 
+-/*
+- * Initialization functions.
+- */
++static u16 rt73usb_get_firmware_crc(void *data, const size_t len)
++{
++	u16 crc;
++
++	/*
++	 * Use the crc itu-t algorithm.
++	 * The last 2 bytes in the firmware array are the crc checksum itself,
++	 * this means that we should never pass those 2 bytes to the crc
++	 * algorithm.
++	 */
++	crc = crc_itu_t(0, data, len - 2);
++	crc = crc_itu_t_byte(crc, 0);
++	crc = crc_itu_t_byte(crc, 0);
++
++	return crc;
++}
++
+ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ 				 const size_t len)
+ {
+@@ -889,7 +913,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ 
+ 		rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
+ 					 USB_VENDOR_REQUEST_OUT,
+-					 FIRMWARE_IMAGE_BASE + i, 0x0000,
++					 FIRMWARE_IMAGE_BASE + i, 0,
+ 					 cache, buflen, timeout);
+ 
+ 		ptr += buflen;
+@@ -902,18 +926,19 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ 	 * we need to specify a long timeout time.
+ 	 */
+ 	status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
+-					     0x0000, USB_MODE_FIRMWARE,
++					     0, USB_MODE_FIRMWARE,
+ 					     REGISTER_TIMEOUT_FIRMWARE);
+ 	if (status < 0) {
+ 		ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
+ 		return status;
+ 	}
+ 
+-	rt73usb_disable_led(rt2x00dev);
+-
+ 	return 0;
+ }
+ 
++/*
++ * Initialization functions.
++ */
+ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
+ {
+ 	u32 reg;
+@@ -1021,6 +1046,17 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
+ 	rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
+ 
+ 	/*
++	 * Clear all beacons
++	 * For the Beacon base registers we only need to clear
++	 * the first byte since that byte contains the VALID and OWNER
++	 * bits which (when set to 0) will invalidate the entire beacon.
++	 */
++	rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
++	rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
++	rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
++	rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
++
++	/*
+ 	 * We must clear the error counters.
+ 	 * These registers are cleared on read,
+ 	 * so we may pass a useless variable to store the value.
+@@ -1094,19 +1130,15 @@ continue_csr_init:
+ 	rt73usb_bbp_write(rt2x00dev, 102, 0x16);
+ 	rt73usb_bbp_write(rt2x00dev, 107, 0x04);
+ 
+-	DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ 		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+ 
+ 		if (eeprom != 0xffff && eeprom != 0x0000) {
+ 			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ 			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+-			DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+-			      reg_id, value);
+ 			rt73usb_bbp_write(rt2x00dev, reg_id, value);
+ 		}
+ 	}
+-	DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+ 
+ 	return 0;
+ }
+@@ -1136,21 +1168,11 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
+ 		return -EIO;
+ 	}
+ 
+-	/*
+-	 * Enable LED
+-	 */
+-	rt73usb_enable_led(rt2x00dev);
+-
+ 	return 0;
+ }
+ 
+ static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+-	/*
+-	 * Disable LED
+-	 */
+-	rt73usb_disable_led(rt2x00dev);
+-
+ 	rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+ 
+ 	/*
+@@ -1234,10 +1256,10 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
+  */
+ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 				    struct sk_buff *skb,
+-				    struct txdata_entry_desc *desc,
++				    struct txentry_desc *txdesc,
+ 				    struct ieee80211_tx_control *control)
+ {
+-	struct skb_desc *skbdesc = get_skb_desc(skb);
++	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ 	__le32 *txd = skbdesc->desc;
+ 	u32 word;
+ 
+@@ -1245,47 +1267,47 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ 	 * Start writing the descriptor words.
+ 	 */
+ 	rt2x00_desc_read(txd, 1, &word);
+-	rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
+-	rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
+-	rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
+-	rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
++	rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
++	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);
+ 	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+ 	rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
+ 	rt2x00_desc_write(txd, 1, word);
+ 
+ 	rt2x00_desc_read(txd, 2, &word);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
+-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
++	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+ 	rt2x00_desc_write(txd, 2, word);
+ 
+ 	rt2x00_desc_read(txd, 5, &word);
+ 	rt2x00_set_field32(&word, TXD_W5_TX_POWER,
+-			   TXPOWER_TO_DEV(control->power_level));
++			   TXPOWER_TO_DEV(rt2x00dev->tx_power));
+ 	rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
+ 	rt2x00_desc_write(txd, 5, word);
+ 
+ 	rt2x00_desc_read(txd, 0, &word);
+ 	rt2x00_set_field32(&word, TXD_W0_BURST,
+-			   test_bit(ENTRY_TXD_BURST, &desc->flags));
++			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+ 	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+-			   test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_ACK,
+-			   test_bit(ENTRY_TXD_ACK, &desc->flags));
++			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+-			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_OFDM,
+-			   test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
+-	rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++			   test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
++	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+ 			   !!(control->flags &
+ 			      IEEE80211_TXCTL_LONG_RETRY_LIMIT));
+ 	rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
+ 	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
+ 	rt2x00_set_field32(&word, TXD_W0_BURST2,
+-			   test_bit(ENTRY_TXD_BURST, &desc->flags));
++			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+ 	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+ 	rt2x00_desc_write(txd, 0, word);
+ }
+@@ -1309,11 +1331,11 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
+  * TX data initialization
+  */
+ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+-				  unsigned int queue)
++				  const unsigned int queue)
+ {
+ 	u32 reg;
+ 
+-	if (queue != IEEE80211_TX_QUEUE_BEACON)
++	if (queue != RT2X00_BCN_QUEUE_BEACON)
+ 		return;
+ 
+ 	/*
+@@ -1324,6 +1346,8 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ 
+ 	rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ 	if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
++		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
++		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+ 		rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+ 		rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ 	}
+@@ -1353,7 +1377,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+ 		return 0;
+ 	}
+ 
+-	if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
++	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ 		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+ 			if (lna == 3 || lna == 2)
+ 				offset += 10;
+@@ -1377,37 +1401,62 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+ 	return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
+ }
+ 
+-static void rt73usb_fill_rxdone(struct data_entry *entry,
+-			        struct rxdata_entry_desc *desc)
++static void rt73usb_fill_rxdone(struct queue_entry *entry,
++			        struct rxdone_entry_desc *rxdesc)
+ {
+-	struct skb_desc *skbdesc = get_skb_desc(entry->skb);
++	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ 	__le32 *rxd = (__le32 *)entry->skb->data;
++	unsigned int offset = entry->queue->desc_size + 2;
+ 	u32 word0;
+ 	u32 word1;
+ 
++	/*
++	 * Copy descriptor to the available headroom inside the skbuffer.
++	 */
++	skb_push(entry->skb, offset);
++	memcpy(entry->skb->data, rxd, entry->queue->desc_size);
++	rxd = (__le32 *)entry->skb->data;
++
++	/*
++	 * The descriptor is now aligned to 4 bytes and thus it is
++	 * now safe to read it on all architectures.
++	 */
+ 	rt2x00_desc_read(rxd, 0, &word0);
+ 	rt2x00_desc_read(rxd, 1, &word1);
+ 
+-	desc->flags = 0;
++	rxdesc->flags = 0;
+ 	if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+-		desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ 
+ 	/*
+ 	 * Obtain the status about this packet.
++	 * When frame was received with an OFDM bitrate,
++	 * the signal is the PLCP value. If it was received with
++	 * a CCK bitrate the signal is the rate in 100kbit/s.
+ 	 */
+-	desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+-	desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
+-	desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+-	desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+-	desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++	rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
++	rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
++	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++	rxdesc->dev_flags = 0;
++	if (rt2x00_get_field32(word0, RXD_W0_OFDM))
++		rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
++	if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++		rxdesc->dev_flags |= RXDONE_MY_BSS;
++
++	/*
++	 * Adjust the skb memory window to the frame boundaries.
++	 */
++	skb_pull(entry->skb, offset + entry->queue->desc_size);
++	skb_trim(entry->skb, rxdesc->size);
+ 
+ 	/*
+ 	 * Set descriptor and data pointer.
+ 	 */
+-	skbdesc->desc = entry->skb->data;
+-	skbdesc->desc_len = entry->ring->desc_size;
+-	skbdesc->data = entry->skb->data + entry->ring->desc_size;
+-	skbdesc->data_len = desc->size;
++	skbdesc->data = entry->skb->data;
++	skbdesc->data_len = rxdesc->size;
++	skbdesc->desc = rxd;
++	skbdesc->desc_len = entry->queue->desc_size;
+ }
+ 
+ /*
+@@ -1499,7 +1548,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ 		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+ 		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+ 		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+-		EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
++		EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+ 	} else {
+ 		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
+ 		if (value < -10 || value > 10)
+@@ -1577,33 +1626,60 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Store led settings, for correct led behaviour.
+ 	 */
++#ifdef CONFIG_RT73USB_LEDS
+ 	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
+ 
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
+-			   rt2x00dev->led_mode);
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
++	rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++	rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++	rt2x00dev->led_radio.led_dev.brightness_set =
++	    rt73usb_brightness_set;
++	rt2x00dev->led_radio.led_dev.blink_set =
++	    rt73usb_blink_set;
++	rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++	rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
++	rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
++	rt2x00dev->led_assoc.led_dev.brightness_set =
++	    rt73usb_brightness_set;
++	rt2x00dev->led_assoc.led_dev.blink_set =
++	    rt73usb_blink_set;
++	rt2x00dev->led_assoc.flags = LED_INITIALIZED;
++
++	if (value == LED_MODE_SIGNAL_STRENGTH) {
++		rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++		rt2x00dev->led_radio.type = LED_TYPE_QUALITY;
++		rt2x00dev->led_qual.led_dev.brightness_set =
++		    rt73usb_brightness_set;
++		rt2x00dev->led_qual.led_dev.blink_set =
++		    rt73usb_blink_set;
++		rt2x00dev->led_qual.flags = LED_INITIALIZED;
++	}
++
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_0));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_1));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_2));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_3));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_GPIO_4));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
+ 			   rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_RDY_G));
+-	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
++	rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
+ 			   rt2x00_get_field16(eeprom,
+ 					      EEPROM_LED_POLARITY_RDY_A));
++#endif /* CONFIG_RT73USB_LEDS */
+ 
+ 	return 0;
+ }
+@@ -1759,7 +1835,7 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 	rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
+ 	rt2x00dev->hw->max_signal = MAX_SIGNAL;
+ 	rt2x00dev->hw->max_rssi = MAX_RX_SSI;
+-	rt2x00dev->hw->queues = 5;
++	rt2x00dev->hw->queues = 4;
+ 
+ 	SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
+ 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+@@ -1776,8 +1852,8 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 	/*
+ 	 * Initialize hw_mode information.
+ 	 */
+-	spec->num_modes = 2;
+-	spec->num_rates = 12;
++	spec->supported_bands = SUPPORT_BAND_2GHZ;
++	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+ 	spec->tx_power_a = NULL;
+ 	spec->tx_power_bg = txpower;
+ 	spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -1786,20 +1862,20 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ 		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
+ 		spec->channels = rf_vals_bg_2528;
+ 	} else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) {
++		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ 		spec->num_channels = ARRAY_SIZE(rf_vals_5226);
+ 		spec->channels = rf_vals_5226;
+ 	} else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) {
+ 		spec->num_channels = 14;
+ 		spec->channels = rf_vals_5225_2527;
+ 	} else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) {
++		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ 		spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
+ 		spec->channels = rf_vals_5225_2527;
+ 	}
+ 
+ 	if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ 	    rt2x00_rf(&rt2x00dev->chip, RF5226)) {
+-		spec->num_modes = 3;
+-
+ 		txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
+ 		for (i = 0; i < 14; i++)
+ 			txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
+@@ -1829,9 +1905,10 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+ 	rt73usb_probe_hw_mode(rt2x00dev);
+ 
+ 	/*
+-	 * This device requires firmware
++	 * This device requires firmware.
+ 	 */
+ 	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
++	__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+ 
+ 	/*
+ 	 * Set the rssi offset.
+@@ -1844,79 +1921,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+  * IEEE80211 stack callback functions.
+  */
+-static void rt73usb_configure_filter(struct ieee80211_hw *hw,
+-				     unsigned int changed_flags,
+-				     unsigned int *total_flags,
+-				     int mc_count,
+-				     struct dev_addr_list *mc_list)
+-{
+-	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	u32 reg;
+-
+-	/*
+-	 * Mask off any flags we are going to ignore from
+-	 * the total_flags field.
+-	 */
+-	*total_flags &=
+-	    FIF_ALLMULTI |
+-	    FIF_FCSFAIL |
+-	    FIF_PLCPFAIL |
+-	    FIF_CONTROL |
+-	    FIF_OTHER_BSS |
+-	    FIF_PROMISC_IN_BSS;
+-
+-	/*
+-	 * Apply some rules to the filters:
+-	 * - Some filters imply different filters to be set.
+-	 * - Some things we can't filter out at all.
+-	 * - Multicast filter seems to kill broadcast traffic so never use it.
+-	 */
+-	*total_flags |= FIF_ALLMULTI;
+-	if (*total_flags & FIF_OTHER_BSS ||
+-	    *total_flags & FIF_PROMISC_IN_BSS)
+-		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+-	/*
+-	 * Check if there is any work left for us.
+-	 */
+-	if (rt2x00dev->packet_filter == *total_flags)
+-		return;
+-	rt2x00dev->packet_filter = *total_flags;
+-
+-	/*
+-	 * When in atomic context, reschedule and let rt2x00lib
+-	 * call this function again.
+-	 */
+-	if (in_atomic()) {
+-		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+-		return;
+-	}
+-
+-	/*
+-	 * Start configuration steps.
+-	 * Note that the version error will always be dropped
+-	 * and broadcast frames will always be accepted since
+-	 * there is no filter for it at this time.
+-	 */
+-	rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
+-			   !(*total_flags & FIF_FCSFAIL));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
+-			   !(*total_flags & FIF_PLCPFAIL));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
+-			   !(*total_flags & FIF_CONTROL));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
+-			   !(*total_flags & FIF_PROMISC_IN_BSS));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
+-			   !(*total_flags & FIF_ALLMULTI));
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
+-	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
+-	rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+-}
+-
+ static int rt73usb_set_retry_limit(struct ieee80211_hw *hw,
+ 				   u32 short_retry, u32 long_retry)
+ {
+@@ -1955,61 +1959,65 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
+ #define rt73usb_get_tsf	NULL
+ #endif
+ 
+-static void rt73usb_reset_tsf(struct ieee80211_hw *hw)
+-{
+-	struct rt2x00_dev *rt2x00dev = hw->priv;
+-
+-	rt73usb_register_write(rt2x00dev, TXRX_CSR12, 0);
+-	rt73usb_register_write(rt2x00dev, TXRX_CSR13, 0);
+-}
+-
+ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+-			  struct ieee80211_tx_control *control)
++				 struct ieee80211_tx_control *control)
+ {
+ 	struct rt2x00_dev *rt2x00dev = hw->priv;
+-	struct skb_desc *desc;
+-	struct data_ring *ring;
+-	struct data_entry *entry;
+-	int timeout;
++	struct rt2x00_intf *intf = vif_to_intf(control->vif);
++	struct skb_frame_desc *skbdesc;
++	unsigned int beacon_base;
++	unsigned int timeout;
++	u32 reg;
+ 
+-	/*
+-	 * Just in case the ieee80211 doesn't set this,
+-	 * but we need this queue set for the descriptor
+-	 * initialization.
+-	 */
+-	control->queue = IEEE80211_TX_QUEUE_BEACON;
+-	ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+-	entry = rt2x00_get_data_entry(ring);
++	if (unlikely(!intf->beacon))
++		return -ENOBUFS;
+ 
+ 	/*
+ 	 * Add the descriptor in front of the skb.
+ 	 */
+-	skb_push(skb, ring->desc_size);
+-	memset(skb->data, 0, ring->desc_size);
++	skb_push(skb, intf->beacon->queue->desc_size);
++	memset(skb->data, 0, intf->beacon->queue->desc_size);
+ 
+ 	/*
+ 	 * Fill in skb descriptor
+ 	 */
+-	desc = get_skb_desc(skb);
+-	desc->desc_len = ring->desc_size;
+-	desc->data_len = skb->len - ring->desc_size;
+-	desc->desc = skb->data;
+-	desc->data = skb->data + ring->desc_size;
+-	desc->ring = ring;
+-	desc->entry = entry;
++	skbdesc = get_skb_frame_desc(skb);
++	memset(skbdesc, 0, sizeof(*skbdesc));
++	skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++	skbdesc->data = skb->data + intf->beacon->queue->desc_size;
++	skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
++	skbdesc->desc = skb->data;
++	skbdesc->desc_len = intf->beacon->queue->desc_size;
++	skbdesc->entry = intf->beacon;
+ 
++	/*
++	 * Disable beaconing while we are reloading the beacon data,
++	 * otherwise we might be sending out invalid data.
++	 */
++	rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
++	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
++	rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
++	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
++	rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
++
++	/*
++	 * mac80211 doesn't provide the control->queue variable
++	 * for beacons. Set our own queue identification so
++	 * it can be used during descriptor initialization.
++	 */
++	control->queue = RT2X00_BCN_QUEUE_BEACON;
+ 	rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+ 
+ 	/*
+ 	 * Write entire beacon with descriptor to register,
+ 	 * and kick the beacon generator.
+ 	 */
++	beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
+ 	timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32));
+ 	rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
+-				 USB_VENDOR_REQUEST_OUT,
+-				 HW_BEACON_BASE0, 0x0000,
++				 USB_VENDOR_REQUEST_OUT, beacon_base, 0,
+ 				 skb->data, skb->len, timeout);
+-	rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
++	rt73usb_kick_tx_queue(rt2x00dev, control->queue);
+ 
+ 	return 0;
+ }
+@@ -2022,20 +2030,20 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
+ 	.remove_interface	= rt2x00mac_remove_interface,
+ 	.config			= rt2x00mac_config,
+ 	.config_interface	= rt2x00mac_config_interface,
+-	.configure_filter	= rt73usb_configure_filter,
++	.configure_filter	= rt2x00mac_configure_filter,
+ 	.get_stats		= rt2x00mac_get_stats,
+ 	.set_retry_limit	= rt73usb_set_retry_limit,
+ 	.bss_info_changed	= rt2x00mac_bss_info_changed,
+ 	.conf_tx		= rt2x00mac_conf_tx,
+ 	.get_tx_stats		= rt2x00mac_get_tx_stats,
+ 	.get_tsf		= rt73usb_get_tsf,
+-	.reset_tsf		= rt73usb_reset_tsf,
+ 	.beacon_update		= rt73usb_beacon_update,
+ };
+ 
+ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
+ 	.probe_hw		= rt73usb_probe_hw,
+ 	.get_firmware_name	= rt73usb_get_firmware_name,
++	.get_firmware_crc	= rt73usb_get_firmware_crc,
+ 	.load_firmware		= rt73usb_load_firmware,
+ 	.initialize		= rt2x00usb_initialize,
+ 	.uninitialize		= rt2x00usb_uninitialize,
+@@ -2050,19 +2058,42 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
+ 	.get_tx_data_len	= rt73usb_get_tx_data_len,
+ 	.kick_tx_queue		= rt73usb_kick_tx_queue,
+ 	.fill_rxdone		= rt73usb_fill_rxdone,
+-	.config_mac_addr	= rt73usb_config_mac_addr,
+-	.config_bssid		= rt73usb_config_bssid,
+-	.config_type		= rt73usb_config_type,
+-	.config_preamble	= rt73usb_config_preamble,
++	.config_filter		= rt73usb_config_filter,
++	.config_intf		= rt73usb_config_intf,
++	.config_erp		= rt73usb_config_erp,
+ 	.config			= rt73usb_config,
+ };
+ 
++static const struct data_queue_desc rt73usb_queue_rx = {
++	.entry_num		= RX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= RXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_usb_rx),
++};
++
++static const struct data_queue_desc rt73usb_queue_tx = {
++	.entry_num		= TX_ENTRIES,
++	.data_size		= DATA_FRAME_SIZE,
++	.desc_size		= TXD_DESC_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_usb_tx),
++};
++
++static const struct data_queue_desc rt73usb_queue_bcn = {
++	.entry_num		= 4 * BEACON_ENTRIES,
++	.data_size		= MGMT_FRAME_SIZE,
++	.desc_size		= TXINFO_SIZE,
++	.priv_size		= sizeof(struct queue_entry_priv_usb_tx),
++};
++
+ static const struct rt2x00_ops rt73usb_ops = {
+ 	.name		= KBUILD_MODNAME,
+-	.rxd_size	= RXD_DESC_SIZE,
+-	.txd_size	= TXD_DESC_SIZE,
++	.max_sta_intf	= 1,
++	.max_ap_intf	= 4,
+ 	.eeprom_size	= EEPROM_SIZE,
+ 	.rf_size	= RF_SIZE,
++	.rx		= &rt73usb_queue_rx,
++	.tx		= &rt73usb_queue_tx,
++	.bcn		= &rt73usb_queue_bcn,
+ 	.lib		= &rt73usb_rt2x00_ops,
+ 	.hw		= &rt73usb_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
+index d49dcaa..06d6874 100644
+--- a/drivers/net/wireless/rt2x00/rt73usb.h
++++ b/drivers/net/wireless/rt2x00/rt73usb.h
+@@ -1,5 +1,5 @@
+ /*
+-	Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++	Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ 	<http://rt2x00.serialmonkey.com>
+ 
+ 	This program is free software; you can redistribute it and/or modify
+@@ -114,6 +114,9 @@ struct hw_pairwise_ta_entry {
+ #define HW_BEACON_BASE2			0x2600
+ #define HW_BEACON_BASE3			0x2700
+ 
++#define HW_BEACON_OFFSET(__index) \
++	( HW_BEACON_BASE0 + (__index * 0x0100) )
++
+ /*
+  * MAC Control/Status Registers(CSR).
+  * Some values are set in TU, whereas 1 TU == 1024 us.
+@@ -146,6 +149,11 @@ struct hw_pairwise_ta_entry {
+ 
+ /*
+  * MAC_CSR3: STA MAC register 1.
++ * UNICAST_TO_ME_MASK:
++ *	Used to mask off bits from byte 5 of the MAC address
++ *	to determine the UNICAST_TO_ME bit for RX frames.
++ *	The full mask is complemented by BSS_ID_MASK:
++ *		MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
+  */
+ #define MAC_CSR3			0x300c
+ #define MAC_CSR3_BYTE4			FIELD32(0x000000ff)
+@@ -163,7 +171,14 @@ struct hw_pairwise_ta_entry {
+ 
+ /*
+  * MAC_CSR5: BSSID register 1.
+- * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID.
++ * BSS_ID_MASK:
++ *	This mask is used to mask off bits 0 and 1 of byte 5 of the
++ *	BSSID. This will make sure that those bits will be ignored
++ *	when determining the MY_BSS of RX frames.
++ *		0: 1-BSSID mode (BSS index = 0)
++ *		1: 2-BSSID mode (BSS index: Byte5, bit 0)
++ *		2: 2-BSSID mode (BSS index: byte5, bit 1)
++ *		3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
+  */
+ #define MAC_CSR5			0x3014
+ #define MAC_CSR5_BYTE4			FIELD32(0x000000ff)
+@@ -867,6 +882,7 @@ struct hw_pairwise_ta_entry {
+  * DMA descriptor defines.
+  */
+ #define TXD_DESC_SIZE			( 6 * sizeof(__le32) )
++#define TXINFO_SIZE			( 6 * sizeof(__le32) )
+ #define RXD_DESC_SIZE			( 6 * sizeof(__le32) )
+ 
+ /*
+@@ -1007,8 +1023,8 @@ struct hw_pairwise_ta_entry {
+ #define RXD_W5_RESERVED			FIELD32(0xffffffff)
+ 
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+  */
+ #define MIN_TXPOWER	0
+ #define MAX_TXPOWER	31
+diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl8180.h
+index 2cbfe3c..082a11f 100644
+--- a/drivers/net/wireless/rtl8180.h
++++ b/drivers/net/wireless/rtl8180.h
+@@ -102,7 +102,7 @@ struct rtl8180_priv {
+ 	struct rtl8180_tx_ring tx_ring[4];
+ 	struct ieee80211_channel channels[14];
+ 	struct ieee80211_rate rates[12];
+-	struct ieee80211_hw_mode modes[2];
++	struct ieee80211_supported_band band;
+ 	struct pci_dev *pdev;
+ 	u32 rx_conf;
+ 
+diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
+index 5e9a8ac..c181f23 100644
+--- a/drivers/net/wireless/rtl8180_dev.c
++++ b/drivers/net/wireless/rtl8180_dev.c
+@@ -49,6 +49,41 @@ static struct pci_device_id rtl8180_table[] __devinitdata = {
+ 
+ MODULE_DEVICE_TABLE(pci, rtl8180_table);
+ 
++static const struct ieee80211_rate rtl818x_rates[] = {
++	{ .bitrate = 10, .hw_value = 0, },
++	{ .bitrate = 20, .hw_value = 1, },
++	{ .bitrate = 55, .hw_value = 2, },
++	{ .bitrate = 110, .hw_value = 3, },
++	{ .bitrate = 60, .hw_value = 4, },
++	{ .bitrate = 90, .hw_value = 5, },
++	{ .bitrate = 120, .hw_value = 6, },
++	{ .bitrate = 180, .hw_value = 7, },
++	{ .bitrate = 240, .hw_value = 8, },
++	{ .bitrate = 360, .hw_value = 9, },
++	{ .bitrate = 480, .hw_value = 10, },
++	{ .bitrate = 540, .hw_value = 11, },
++};
++
++static const struct ieee80211_channel rtl818x_channels[] = {
++	{ .center_freq = 2412 },
++	{ .center_freq = 2417 },
++	{ .center_freq = 2422 },
++	{ .center_freq = 2427 },
++	{ .center_freq = 2432 },
++	{ .center_freq = 2437 },
++	{ .center_freq = 2442 },
++	{ .center_freq = 2447 },
++	{ .center_freq = 2452 },
++	{ .center_freq = 2457 },
++	{ .center_freq = 2462 },
++	{ .center_freq = 2467 },
++	{ .center_freq = 2472 },
++	{ .center_freq = 2484 },
++};
++
++
++
++
+ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+ {
+ 	struct rtl8180_priv *priv = dev->priv;
+@@ -99,10 +134,10 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
+ 			/* TODO: improve signal/rssi reporting */
+ 			rx_status.signal = flags2 & 0xFF;
+ 			rx_status.ssi = (flags2 >> 8) & 0x7F;
+-			rx_status.rate = (flags >> 20) & 0xF;
+-			rx_status.freq = dev->conf.freq;
+-			rx_status.channel = dev->conf.channel;
+-			rx_status.phymode = dev->conf.phymode;
++			/* XXX: is this correct? */
++			rx_status.rate_idx = (flags >> 20) & 0xF;
++			rx_status.freq = dev->conf.channel->center_freq;
++			rx_status.band = dev->conf.channel->band;
+ 			rx_status.mactime = le64_to_cpu(entry->tsft);
+ 			rx_status.flag |= RX_FLAG_TSFT;
+ 			if (flags & RTL8180_RX_DESC_FLAG_CRC32_ERR)
+@@ -222,18 +257,25 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ 	mapping = pci_map_single(priv->pdev, skb->data,
+ 				 skb->len, PCI_DMA_TODEVICE);
+ 
++	BUG_ON(!control->tx_rate);
++
+ 	tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS |
+-		   RTL8180_TX_DESC_FLAG_LS | (control->tx_rate << 24) |
+-		   (control->rts_cts_rate << 19) | skb->len;
++		   RTL8180_TX_DESC_FLAG_LS |
++		   (control->tx_rate->hw_value << 24) | skb->len;
+ 
+ 	if (priv->r8185)
+ 		tx_flags |= RTL8180_TX_DESC_FLAG_DMA |
+ 			    RTL8180_TX_DESC_FLAG_NO_ENC;
+ 
+-	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
++	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
++		BUG_ON(!control->rts_cts_rate);
+ 		tx_flags |= RTL8180_TX_DESC_FLAG_RTS;
+-	else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
++		tx_flags |= control->rts_cts_rate->hw_value << 19;
++	} else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
++		BUG_ON(!control->rts_cts_rate);
+ 		tx_flags |= RTL8180_TX_DESC_FLAG_CTS;
++		tx_flags |= control->rts_cts_rate->hw_value << 19;
++	}
+ 
+ 	*((struct ieee80211_tx_control **) skb->cb) =
+ 		kmemdup(control, sizeof(*control), GFP_ATOMIC);
+@@ -246,9 +288,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ 		unsigned int remainder;
+ 
+ 		plcp_len = DIV_ROUND_UP(16 * (skb->len + 4),
+-					(control->rate->rate * 2) / 10);
++					(control->tx_rate->bitrate * 2) / 10);
+ 		remainder = (16 * (skb->len + 4)) %
+-			    ((control->rate->rate * 2) / 10);
++			    ((control->tx_rate->bitrate * 2) / 10);
+ 		if (remainder > 0 && remainder <= 6)
+ 			plcp_len |= 1 << 15;
+ 	}
+@@ -261,8 +303,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ 	entry->plcp_len = cpu_to_le16(plcp_len);
+ 	entry->tx_buf = cpu_to_le32(mapping);
+ 	entry->frame_len = cpu_to_le32(skb->len);
+-	entry->flags2 = control->alt_retry_rate != -1 ?
+-			control->alt_retry_rate << 4 : 0;
++	entry->flags2 = control->alt_retry_rate != NULL ?
++			control->alt_retry_rate->bitrate << 4 : 0;
+ 	entry->retry_limit = control->retry_limit;
+ 	entry->flags = cpu_to_le32(tx_flags);
+ 	__skb_queue_tail(&ring->queue, skb);
+@@ -646,9 +688,9 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev,
+ 
+ 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ 	rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0],
+-			  cpu_to_le32(*(u32 *)conf->mac_addr));
++			  le32_to_cpu(*(__le32 *)conf->mac_addr));
+ 	rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4],
+-			  cpu_to_le16(*(u16 *)(conf->mac_addr + 4)));
++			  le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));
+ 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+ 
+ 	return 0;
+@@ -838,19 +880,19 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
+ 		goto err_free_dev;
+ 	}
+ 
++	BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
++	BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
++
+ 	memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+ 	memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+-	priv->modes[0].mode = MODE_IEEE80211G;
+-	priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+-	priv->modes[0].rates = priv->rates;
+-	priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+-	priv->modes[0].channels = priv->channels;
+-	priv->modes[1].mode = MODE_IEEE80211B;
+-	priv->modes[1].num_rates = 4;
+-	priv->modes[1].rates = priv->rates;
+-	priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+-	priv->modes[1].channels = priv->channels;
+-	priv->mode = IEEE80211_IF_TYPE_INVALID;
++
++	priv->band.band = IEEE80211_BAND_2GHZ;
++	priv->band.channels = priv->channels;
++	priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
++	priv->band.bitrates = priv->rates;
++	priv->band.n_bitrates = 4;
++	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
++
+ 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ 		     IEEE80211_HW_RX_INCLUDES_FCS;
+ 	dev->queues = 1;
+@@ -879,15 +921,10 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
+ 
+ 	priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;
+ 	if (priv->r8185) {
+-		if ((err = ieee80211_register_hwmode(dev, &priv->modes[0])))
+-			goto err_iounmap;
+-
++		priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
+ 		pci_try_set_mwi(pdev);
+ 	}
+ 
+-	if ((err = ieee80211_register_hwmode(dev, &priv->modes[1])))
+-		goto err_iounmap;
+-
+ 	eeprom.data = dev;
+ 	eeprom.register_read = rtl8180_eeprom_register_read;
+ 	eeprom.register_write = rtl8180_eeprom_register_write;
+@@ -950,8 +987,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
+ 	for (i = 0; i < 14; i += 2) {
+ 		u16 txpwr;
+ 		eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr);
+-		priv->channels[i].val = txpwr & 0xFF;
+-		priv->channels[i + 1].val = txpwr >> 8;
++		priv->channels[i].hw_value = txpwr & 0xFF;
++		priv->channels[i + 1].hw_value = txpwr >> 8;
+ 	}
+ 
+ 	/* OFDM TX power */
+@@ -959,8 +996,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
+ 		for (i = 0; i < 14; i += 2) {
+ 			u16 txpwr;
+ 			eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr);
+-			priv->channels[i].val |= (txpwr & 0xFF) << 8;
+-			priv->channels[i + 1].val |= txpwr & 0xFF00;
++			priv->channels[i].hw_value |= (txpwr & 0xFF) << 8;
++			priv->channels[i + 1].hw_value |= txpwr & 0xFF00;
+ 		}
+ 	}
+ 
+diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl8180_grf5101.c
+index 8293e19..5d47935 100644
+--- a/drivers/net/wireless/rtl8180_grf5101.c
++++ b/drivers/net/wireless/rtl8180_grf5101.c
+@@ -73,8 +73,9 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
+ 				   struct ieee80211_conf *conf)
+ {
+ 	struct rtl8180_priv *priv = dev->priv;
+-	u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
+-	u32 chan = conf->channel - 1;
++	int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
++	u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
++	u32 chan = channel - 1;
+ 
+ 	/* set TX power */
+ 	write_grf5101(dev, 0x15, 0x0);
+diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c
+index 98fe9fd..a34dfd3 100644
+--- a/drivers/net/wireless/rtl8180_max2820.c
++++ b/drivers/net/wireless/rtl8180_max2820.c
+@@ -78,8 +78,9 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev,
+ 				   struct ieee80211_conf *conf)
+ {
+ 	struct rtl8180_priv *priv = dev->priv;
+-	unsigned int chan_idx = conf ? conf->channel - 1 : 0;
+-	u32 txpw = priv->channels[chan_idx].val & 0xFF;
++	int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
++	unsigned int chan_idx = channel - 1;
++	u32 txpw = priv->channels[chan_idx].hw_value & 0xFF;
+ 	u32 chan = max2820_chan[chan_idx];
+ 
+ 	/* While philips SA2400 drive the PA bias from
+diff --git a/drivers/net/wireless/rtl8180_rtl8225.c b/drivers/net/wireless/rtl8180_rtl8225.c
+index ef3832b..cd22781 100644
+--- a/drivers/net/wireless/rtl8180_rtl8225.c
++++ b/drivers/net/wireless/rtl8180_rtl8225.c
+@@ -261,8 +261,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+ 	u32 reg;
+ 	int i;
+ 
+-	cck_power = priv->channels[channel - 1].val & 0xFF;
+-	ofdm_power = priv->channels[channel - 1].val >> 8;
++	cck_power = priv->channels[channel - 1].hw_value & 0xFF;
++	ofdm_power = priv->channels[channel - 1].hw_value >> 8;
+ 
+ 	cck_power = min(cck_power, (u8)35);
+ 	ofdm_power = min(ofdm_power, (u8)35);
+@@ -476,8 +476,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+ 	const u8 *tmp;
+ 	int i;
+ 
+-	cck_power = priv->channels[channel - 1].val & 0xFF;
+-	ofdm_power = priv->channels[channel - 1].val >> 8;
++	cck_power = priv->channels[channel - 1].hw_value & 0xFF;
++	ofdm_power = priv->channels[channel - 1].hw_value >> 8;
+ 
+ 	if (channel == 14)
+ 		tmp = rtl8225z2_tx_power_cck_ch14;
+@@ -716,13 +716,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
+ 				   struct ieee80211_conf *conf)
+ {
+ 	struct rtl8180_priv *priv = dev->priv;
++	int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ 
+ 	if (priv->rf->init == rtl8225_rf_init)
+-		rtl8225_rf_set_tx_power(dev, conf->channel);
++		rtl8225_rf_set_tx_power(dev, chan);
+ 	else
+-		rtl8225z2_rf_set_tx_power(dev, conf->channel);
++		rtl8225z2_rf_set_tx_power(dev, chan);
+ 
+-	rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
++	rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
+ 	msleep(10);
+ 
+ 	if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl8180_sa2400.c
+index e08ace7..0311b4e 100644
+--- a/drivers/net/wireless/rtl8180_sa2400.c
++++ b/drivers/net/wireless/rtl8180_sa2400.c
+@@ -80,8 +80,9 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
+ 				  struct ieee80211_conf *conf)
+ {
+ 	struct rtl8180_priv *priv = dev->priv;
+-	u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
+-	u32 chan = sa2400_chan[conf->channel - 1];
++	int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
++	u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
++	u32 chan = sa2400_chan[channel - 1];
+ 
+ 	write_sa2400(dev, 7, txpw);
+ 
+diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
+index 8680a0b..076d88b 100644
+--- a/drivers/net/wireless/rtl8187.h
++++ b/drivers/net/wireless/rtl8187.h
+@@ -71,7 +71,7 @@ struct rtl8187_priv {
+ 	/* rtl8187 specific */
+ 	struct ieee80211_channel channels[14];
+ 	struct ieee80211_rate rates[12];
+-	struct ieee80211_hw_mode modes[2];
++	struct ieee80211_supported_band band;
+ 	struct usb_device *udev;
+ 	u32 rx_conf;
+ 	u16 txpwr_base;
+diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
+index 133b3f3..d5787b3 100644
+--- a/drivers/net/wireless/rtl8187_dev.c
++++ b/drivers/net/wireless/rtl8187_dev.c
+@@ -45,6 +45,38 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
+ 
+ MODULE_DEVICE_TABLE(usb, rtl8187_table);
+ 
++static const struct ieee80211_rate rtl818x_rates[] = {
++	{ .bitrate = 10, .hw_value = 0, },
++	{ .bitrate = 20, .hw_value = 1, },
++	{ .bitrate = 55, .hw_value = 2, },
++	{ .bitrate = 110, .hw_value = 3, },
++	{ .bitrate = 60, .hw_value = 4, },
++	{ .bitrate = 90, .hw_value = 5, },
++	{ .bitrate = 120, .hw_value = 6, },
++	{ .bitrate = 180, .hw_value = 7, },
++	{ .bitrate = 240, .hw_value = 8, },
++	{ .bitrate = 360, .hw_value = 9, },
++	{ .bitrate = 480, .hw_value = 10, },
++	{ .bitrate = 540, .hw_value = 11, },
++};
++
++static const struct ieee80211_channel rtl818x_channels[] = {
++	{ .center_freq = 2412 },
++	{ .center_freq = 2417 },
++	{ .center_freq = 2422 },
++	{ .center_freq = 2427 },
++	{ .center_freq = 2432 },
++	{ .center_freq = 2437 },
++	{ .center_freq = 2442 },
++	{ .center_freq = 2447 },
++	{ .center_freq = 2452 },
++	{ .center_freq = 2457 },
++	{ .center_freq = 2462 },
++	{ .center_freq = 2467 },
++	{ .center_freq = 2472 },
++	{ .center_freq = 2484 },
++};
++
+ static void rtl8187_iowrite_async_cb(struct urb *urb)
+ {
+ 	kfree(urb->context);
+@@ -146,17 +178,23 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ 
+ 	flags = skb->len;
+ 	flags |= RTL8187_TX_FLAG_NO_ENCRYPT;
+-	flags |= control->rts_cts_rate << 19;
+-	flags |= control->tx_rate << 24;
++
++	BUG_ON(!control->tx_rate);
++
++	flags |= control->tx_rate->hw_value << 24;
+ 	if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data))
+ 		flags |= RTL8187_TX_FLAG_MORE_FRAG;
+ 	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
++		BUG_ON(!control->rts_cts_rate);
+ 		flags |= RTL8187_TX_FLAG_RTS;
++		flags |= control->rts_cts_rate->hw_value << 19;
+ 		rts_dur = ieee80211_rts_duration(dev, priv->vif,
+ 						 skb->len, control);
+-	}
+-	if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
++	} else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
++		BUG_ON(!control->rts_cts_rate);
+ 		flags |= RTL8187_TX_FLAG_CTS;
++		flags |= control->rts_cts_rate->hw_value << 19;
++	}
+ 
+ 	hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ 	hdr->flags = cpu_to_le32(flags);
+@@ -225,10 +263,9 @@ static void rtl8187_rx_cb(struct urb *urb)
+ 	rx_status.antenna = (hdr->signal >> 7) & 1;
+ 	rx_status.signal = 64 - min(hdr->noise, (u8)64);
+ 	rx_status.ssi = signal;
+-	rx_status.rate = rate;
+-	rx_status.freq = dev->conf.freq;
+-	rx_status.channel = dev->conf.channel;
+-	rx_status.phymode = dev->conf.phymode;
++	rx_status.rate_idx = rate;
++	rx_status.freq = dev->conf.channel->center_freq;
++	rx_status.band = dev->conf.channel->band;
+ 	rx_status.mactime = le64_to_cpu(hdr->mac_time);
+ 	rx_status.flag |= RX_FLAG_TSFT;
+ 	if (flags & (1 << 13))
+@@ -685,19 +722,22 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
+ 	usb_get_dev(udev);
+ 
+ 	skb_queue_head_init(&priv->rx_queue);
++
++	BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
++	BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
++
+ 	memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+ 	memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+ 	priv->map = (struct rtl818x_csr *)0xFF00;
+-	priv->modes[0].mode = MODE_IEEE80211G;
+-	priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+-	priv->modes[0].rates = priv->rates;
+-	priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+-	priv->modes[0].channels = priv->channels;
+-	priv->modes[1].mode = MODE_IEEE80211B;
+-	priv->modes[1].num_rates = 4;
+-	priv->modes[1].rates = priv->rates;
+-	priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+-	priv->modes[1].channels = priv->channels;
++
++	priv->band.band = IEEE80211_BAND_2GHZ;
++	priv->band.channels = priv->channels;
++	priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
++	priv->band.bitrates = priv->rates;
++	priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
++	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
++
++
+ 	priv->mode = IEEE80211_IF_TYPE_MNTR;
+ 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ 		     IEEE80211_HW_RX_INCLUDES_FCS;
+@@ -706,10 +746,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
+ 	dev->max_rssi = 65;
+ 	dev->max_signal = 64;
+ 
+-	for (i = 0; i < 2; i++)
+-		if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
+-			goto err_free_dev;
+-
+ 	eeprom.data = dev;
+ 	eeprom.register_read = rtl8187_eeprom_register_read;
+ 	eeprom.register_write = rtl8187_eeprom_register_write;
+@@ -733,20 +769,20 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
+ 	for (i = 0; i < 3; i++) {
+ 		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
+ 				  &txpwr);
+-		(*channel++).val = txpwr & 0xFF;
+-		(*channel++).val = txpwr >> 8;
++		(*channel++).hw_value = txpwr & 0xFF;
++		(*channel++).hw_value = txpwr >> 8;
+ 	}
+ 	for (i = 0; i < 2; i++) {
+ 		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
+ 				  &txpwr);
+-		(*channel++).val = txpwr & 0xFF;
+-		(*channel++).val = txpwr >> 8;
++		(*channel++).hw_value = txpwr & 0xFF;
++		(*channel++).hw_value = txpwr >> 8;
+ 	}
+ 	for (i = 0; i < 2; i++) {
+ 		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
+ 				  &txpwr);
+-		(*channel++).val = txpwr & 0xFF;
+-		(*channel++).val = txpwr >> 8;
++		(*channel++).hw_value = txpwr & 0xFF;
++		(*channel++).hw_value = txpwr >> 8;
+ 	}
+ 
+ 	eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
+diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
+index b713de1..9146387 100644
+--- a/drivers/net/wireless/rtl8187_rtl8225.c
++++ b/drivers/net/wireless/rtl8187_rtl8225.c
+@@ -283,8 +283,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+ 	u32 reg;
+ 	int i;
+ 
+-	cck_power = priv->channels[channel - 1].val & 0xF;
+-	ofdm_power = priv->channels[channel - 1].val >> 4;
++	cck_power = priv->channels[channel - 1].hw_value & 0xF;
++	ofdm_power = priv->channels[channel - 1].hw_value >> 4;
+ 
+ 	cck_power = min(cck_power, (u8)11);
+ 	ofdm_power = min(ofdm_power, (u8)35);
+@@ -500,8 +500,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+ 	u32 reg;
+ 	int i;
+ 
+-	cck_power = priv->channels[channel - 1].val & 0xF;
+-	ofdm_power = priv->channels[channel - 1].val >> 4;
++	cck_power = priv->channels[channel - 1].hw_value & 0xF;
++	ofdm_power = priv->channels[channel - 1].hw_value >> 4;
+ 
+ 	cck_power = min(cck_power, (u8)15);
+ 	cck_power += priv->txpwr_base & 0xF;
+@@ -735,13 +735,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
+ 				   struct ieee80211_conf *conf)
+ {
+ 	struct rtl8187_priv *priv = dev->priv;
++	int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ 
+ 	if (priv->rf->init == rtl8225_rf_init)
+-		rtl8225_rf_set_tx_power(dev, conf->channel);
++		rtl8225_rf_set_tx_power(dev, chan);
+ 	else
+-		rtl8225z2_rf_set_tx_power(dev, conf->channel);
++		rtl8225z2_rf_set_tx_power(dev, chan);
+ 
+-	rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
++	rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
+ 	msleep(10);
+ }
+ 
+diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
+index 1e7d6f8..4f7d38f 100644
+--- a/drivers/net/wireless/rtl818x.h
++++ b/drivers/net/wireless/rtl818x.h
+@@ -175,74 +175,4 @@ struct rtl818x_rf_ops {
+ 	void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
+ };
+ 
+-static const struct ieee80211_rate rtl818x_rates[] = {
+-	{ .rate = 10,
+-	  .val = 0,
+-	  .flags = IEEE80211_RATE_CCK },
+-	{ .rate = 20,
+-	  .val = 1,
+-	  .flags = IEEE80211_RATE_CCK },
+-	{ .rate = 55,
+-	  .val = 2,
+-	  .flags = IEEE80211_RATE_CCK },
+-	{ .rate = 110,
+-	  .val = 3,
+-	  .flags = IEEE80211_RATE_CCK },
+-	{ .rate = 60,
+-	  .val = 4,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 90,
+-	  .val = 5,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 120,
+-	  .val = 6,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 180,
+-	  .val = 7,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 240,
+-	  .val = 8,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 360,
+-	  .val = 9,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 480,
+-	  .val = 10,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 540,
+-	  .val = 11,
+-	  .flags = IEEE80211_RATE_OFDM },
+-};
+-
+-static const struct ieee80211_channel rtl818x_channels[] = {
+-	{ .chan = 1,
+-	  .freq = 2412},
+-	{ .chan = 2,
+-	  .freq = 2417},
+-	{ .chan = 3,
+-	  .freq = 2422},
+-	{ .chan = 4,
+-	  .freq = 2427},
+-	{ .chan = 5,
+-	  .freq = 2432},
+-	{ .chan = 6,
+-	  .freq = 2437},
+-	{ .chan = 7,
+-	  .freq = 2442},
+-	{ .chan = 8,
+-	  .freq = 2447},
+-	{ .chan = 9,
+-	  .freq = 2452},
+-	{ .chan = 10,
+-	  .freq = 2457},
+-	{ .chan = 11,
+-	  .freq = 2462},
+-	{ .chan = 12,
+-	  .freq = 2467},
+-	{ .chan = 13,
+-	  .freq = 2472},
+-	{ .chan = 14,
+-	  .freq = 2484}
+-};
+-
+ #endif /* RTL818X_H */
+diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
+index 88efe1b..bced3fe 100644
+--- a/drivers/net/wireless/strip.c
++++ b/drivers/net/wireless/strip.c
+@@ -962,12 +962,12 @@ static char *time_delta(char buffer[], long time)
+ /* get Nth element of the linked list */
+ static struct strip *strip_get_idx(loff_t pos) 
+ {
+-	struct list_head *l;
++	struct strip *str;
+ 	int i = 0;
+ 
+-	list_for_each_rcu(l, &strip_list) {
++	list_for_each_entry_rcu(str, &strip_list, list) {
+ 		if (pos == i)
+-			return list_entry(l, struct strip, list);
++			return str;
+ 		++i;
+ 	}
+ 	return NULL;
+diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
+index 06eea6a..baf7401 100644
+--- a/drivers/net/wireless/wavelan_cs.c
++++ b/drivers/net/wireless/wavelan_cs.c
+@@ -102,7 +102,7 @@ hacr_write(u_long	base,
+  * Write to card's Host Adapter Command Register. Include a delay for
+  * those times when it is needed.
+  */
+-static inline void
++static void
+ hacr_write_slow(u_long	base,
+ 		u_char	hacr)
+ {
+@@ -255,7 +255,7 @@ update_psa_checksum(struct net_device *	dev)
+ /*
+  * Write 1 byte to the MMC.
+  */
+-static inline void
++static void
+ mmc_out(u_long		base,
+ 	u_short		o,
+ 	u_char		d)
+@@ -275,7 +275,7 @@ mmc_out(u_long		base,
+  * Routine to write bytes to the Modem Management Controller.
+  * We start by the end because it is the way it should be !
+  */
+-static inline void
++static void
+ mmc_write(u_long	base,
+ 	  u_char	o,
+ 	  u_char *	b,
+@@ -293,7 +293,7 @@ mmc_write(u_long	base,
+  * Read 1 byte from the MMC.
+  * Optimised version for 1 byte, avoid using memory...
+  */
+-static inline u_char
++static u_char
+ mmc_in(u_long	base,
+        u_short	o)
+ {
+@@ -318,7 +318,7 @@ mmc_in(u_long	base,
+  * (code has just been moved in the above function)
+  * We start by the end because it is the way it should be !
+  */
+-static inline void
++static void
+ mmc_read(u_long		base,
+ 	 u_char		o,
+ 	 u_char *	b,
+@@ -350,9 +350,8 @@ mmc_encr(u_long		base)	/* i/o port of the card */
+ /*------------------------------------------------------------------*/
+ /*
+  * Wait for the frequency EEprom to complete a command...
+- * I hope this one will be optimally inlined...
+  */
+-static inline void
++static void
+ fee_wait(u_long		base,	/* i/o port of the card */
+ 	 int		delay,	/* Base delay to wait for */
+ 	 int		number)	/* Number of time to wait */
+@@ -738,9 +737,9 @@ static void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
+ }
+ 
+ /* Called when a WavePoint beacon is received */
+-static inline void wl_roam_gather(struct net_device *  dev,
+-				  u_char *  hdr,   /* Beacon header */
+-				  u_char *  stats) /* SNR, Signal quality 
++static void wl_roam_gather(struct net_device *  dev,
++			   u_char *  hdr,   /* Beacon header */
++			   u_char *  stats) /* SNR, Signal quality
+ 						      of packet */
+ {
+   wavepoint_beacon *beacon= (wavepoint_beacon *)hdr; /* Rcvd. Beacon */
+@@ -794,7 +793,7 @@ out:
+ static inline int WAVELAN_BEACON(unsigned char *data)
+ {
+   wavepoint_beacon *beacon= (wavepoint_beacon *)data;
+-  static wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00};
++  static const wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00};
+   
+   if(memcmp(beacon,&beacon_template,9)==0)
+     return 1;
+@@ -980,7 +979,7 @@ read_ringbuf(struct net_device *	dev,
+  * wavelan_interrupt is not an option...), so you may experience
+  * some delay sometime...
+  */
+-static inline void
++static void
+ wv_82593_reconfig(struct net_device *	dev)
+ {
+   net_local *		lp = netdev_priv(dev);
+@@ -1233,7 +1232,7 @@ wv_local_show(struct net_device *	dev)
+ /*
+  * Dump packet header (and content if necessary) on the screen
+  */
+-static inline void
++static void
+ wv_packet_info(u_char *		p,		/* Packet to dump */
+ 	       int		length,		/* Length of the packet */
+ 	       char *		msg1,		/* Name of the device */
+@@ -1272,7 +1271,7 @@ wv_packet_info(u_char *		p,		/* Packet to dump */
+  * This is the information which is displayed by the driver at startup
+  * There  is a lot of flag to configure it at your will...
+  */
+-static inline void
++static void
+ wv_init_info(struct net_device *	dev)
+ {
+   unsigned int	base = dev->base_addr;
+@@ -1509,7 +1508,7 @@ wavelan_set_mac_address(struct net_device *	dev,
+  * Frequency setting (for hardware able of it)
+  * It's a bit complicated and you don't really want to look into it...
+  */
+-static inline int
++static int
+ wv_set_frequency(u_long		base,	/* i/o port of the card */
+ 		 iw_freq *	frequency)
+ {
+@@ -1706,7 +1705,7 @@ wv_set_frequency(u_long		base,	/* i/o port of the card */
+ /*
+  * Give the list of available frequencies
+  */
+-static inline int
++static int
+ wv_frequency_list(u_long	base,	/* i/o port of the card */
+ 		  iw_freq *	list,	/* List of frequency to fill */
+ 		  int		max)	/* Maximum number of frequencies */
+@@ -2759,7 +2758,7 @@ wavelan_get_wireless_stats(struct net_device *	dev)
+  * frame pointer and verify that the frame seem correct
+  * (called by wv_packet_rcv())
+  */
+-static inline int
++static int
+ wv_start_of_frame(struct net_device *	dev,
+ 		  int		rfp,	/* end of frame */
+ 		  int		wrap)	/* start of buffer */
+@@ -2821,7 +2820,7 @@ wv_start_of_frame(struct net_device *	dev,
+  * Note: if any errors occur, the packet is "dropped on the floor"
+  * (called by wv_packet_rcv())
+  */
+-static inline void
++static void
+ wv_packet_read(struct net_device *		dev,
+ 	       int		fd_p,
+ 	       int		sksize)
+@@ -2922,7 +2921,7 @@ wv_packet_read(struct net_device *		dev,
+  * (called by wavelan_interrupt())
+  * Note : the spinlock is already grabbed for us and irq are disabled.
+  */
+-static inline void
++static void
+ wv_packet_rcv(struct net_device *	dev)
+ {
+   unsigned int	base = dev->base_addr;
+@@ -3056,7 +3055,7 @@ wv_packet_rcv(struct net_device *	dev)
+  * the transmit.
+  * (called in wavelan_packet_xmit())
+  */
+-static inline void
++static void
+ wv_packet_write(struct net_device *	dev,
+ 		void *		buf,
+ 		short		length)
+@@ -3180,7 +3179,7 @@ wavelan_packet_xmit(struct sk_buff *	skb,
+  * Routine to initialize the Modem Management Controller.
+  * (called by wv_hw_config())
+  */
+-static inline int
++static int
+ wv_mmc_init(struct net_device *	dev)
+ {
+   unsigned int	base = dev->base_addr;
+@@ -3699,7 +3698,7 @@ wv_82593_config(struct net_device *	dev)
+  * wavelan.
+  * (called by wv_config())
+  */
+-static inline int
++static int
+ wv_pcmcia_reset(struct net_device *	dev)
+ {
+   int		i;
+@@ -3864,7 +3863,7 @@ wv_hw_config(struct net_device *	dev)
+  *	2. Start the LAN controller's receive unit
+  * (called by wavelan_event(), wavelan_watchdog() and wavelan_open())
+  */
+-static inline void
++static void
+ wv_hw_reset(struct net_device *	dev)
+ {
+   net_local *	lp = netdev_priv(dev);
+@@ -3895,7 +3894,7 @@ wv_hw_reset(struct net_device *	dev)
+  * device available to the system.
+  * (called by wavelan_event())
+  */
+-static inline int
++static int
+ wv_pcmcia_config(struct pcmcia_device *	link)
+ {
+   struct net_device *	dev = (struct net_device *) link->priv;
+diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
+index 33dd970..628192d 100644
+--- a/drivers/net/wireless/wavelan_cs.p.h
++++ b/drivers/net/wireless/wavelan_cs.p.h
+@@ -637,7 +637,7 @@ struct net_local
+ /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
+ static inline u_char		/* data */
+ 	hasr_read(u_long);	/* Read the host interface : base address */
+-static inline void
++static void
+ 	hacr_write(u_long,	/* Write to host interface : base address */
+ 		   u_char),	/* data */
+ 	hacr_write_slow(u_long,
+@@ -651,7 +651,7 @@ static void
+ 		  int,		/* Offset in psa */
+ 		  u_char *,	/* Buffer in memory */
+ 		  int);		/* Length of buffer */
+-static inline void
++static void
+ 	mmc_out(u_long,		/* Write 1 byte to the Modem Manag Control */
+ 		u_short,
+ 		u_char),
+@@ -659,10 +659,10 @@ static inline void
+ 		  u_char,
+ 		  u_char *,
+ 		  int);
+-static inline u_char		/* Read 1 byte from the MMC */
++static u_char			/* Read 1 byte from the MMC */
+ 	mmc_in(u_long,
+ 	       u_short);
+-static inline void
++static void
+ 	mmc_read(u_long,	/* Read n bytes from the MMC */
+ 		 u_char,
+ 		 u_char *,
+@@ -688,10 +688,10 @@ static int
+ 		     int,
+ 		     char *,
+ 		     int);
+-static inline void
++static void
+ 	wv_82593_reconfig(struct net_device *);	/* Reconfigure the controller */
+ /* ------------------- DEBUG & INFO SUBROUTINES ------------------- */
+-static inline void
++static void
+ 	wv_init_info(struct net_device *);	/* display startup info */
+ /* ------------------- IOCTL, STATS & RECONFIG ------------------- */
+ static en_stats	*
+@@ -699,17 +699,17 @@ static en_stats	*
+ static iw_stats *
+ 	wavelan_get_wireless_stats(struct net_device *);
+ /* ----------------------- PACKET RECEPTION ----------------------- */
+-static inline int
++static int
+ 	wv_start_of_frame(struct net_device *,	/* Seek beggining of current frame */
+ 			  int,	/* end of frame */
+ 			  int);	/* start of buffer */
+-static inline void
++static void
+ 	wv_packet_read(struct net_device *,	/* Read a packet from a frame */
+ 		       int,
+ 		       int),
+ 	wv_packet_rcv(struct net_device *);	/* Read all packets waiting */
+ /* --------------------- PACKET TRANSMISSION --------------------- */
+-static inline void
++static void
+ 	wv_packet_write(struct net_device *,	/* Write a packet to the Tx buffer */
+ 			void *,
+ 			short);
+@@ -717,20 +717,20 @@ static int
+ 	wavelan_packet_xmit(struct sk_buff *,	/* Send a packet */
+ 			    struct net_device *);
+ /* -------------------- HARDWARE CONFIGURATION -------------------- */
+-static inline int
++static int
+ 	wv_mmc_init(struct net_device *);	/* Initialize the modem */
+ static int
+ 	wv_ru_stop(struct net_device *),	/* Stop the i82593 receiver unit */
+ 	wv_ru_start(struct net_device *);	/* Start the i82593 receiver unit */
+ static int
+ 	wv_82593_config(struct net_device *);	/* Configure the i82593 */
+-static inline int
++static int
+ 	wv_pcmcia_reset(struct net_device *);	/* Reset the pcmcia interface */
+ static int
+ 	wv_hw_config(struct net_device *);	/* Reset & configure the whole hardware */
+-static inline void
++static void
+ 	wv_hw_reset(struct net_device *);	/* Same, + start receiver unit */
+-static inline int
++static int
+ 	wv_pcmcia_config(struct pcmcia_device *);	/* Configure the pcmcia interface */
+ static void
+ 	wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */
+diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
+index 99e5b03..0acb5c3 100644
+--- a/drivers/net/wireless/zd1211rw/zd_chip.c
++++ b/drivers/net/wireless/zd1211rw/zd_chip.c
+@@ -771,10 +771,10 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip)
+ {
+ 	static const struct zd_ioreq32 ioreqs[] = {
+ 		{ CR_ZD1211B_RETRY_MAX,		0x02020202 },
+-		{ CR_ZD1211B_TX_PWR_CTL4,	0x007f003f },
+-		{ CR_ZD1211B_TX_PWR_CTL3,	0x007f003f },
+-		{ CR_ZD1211B_TX_PWR_CTL2,       0x003f001f },
+-		{ CR_ZD1211B_TX_PWR_CTL1,       0x001f000f },
++		{ CR_ZD1211B_CWIN_MAX_MIN_AC0,	0x007f003f },
++		{ CR_ZD1211B_CWIN_MAX_MIN_AC1,	0x007f003f },
++		{ CR_ZD1211B_CWIN_MAX_MIN_AC2,  0x003f001f },
++		{ CR_ZD1211B_CWIN_MAX_MIN_AC3,  0x001f000f },
+ 		{ CR_ZD1211B_AIFS_CTL1,		0x00280028 },
+ 		{ CR_ZD1211B_AIFS_CTL2,		0x008C003C },
+ 		{ CR_ZD1211B_TXOP,		0x01800824 },
+@@ -809,6 +809,7 @@ static int hw_init_hmac(struct zd_chip *chip)
+ 		{ CR_AFTER_PNP,			0x1 },
+ 		{ CR_WEP_PROTECT,		0x114 },
+ 		{ CR_IFS_VALUE,			IFS_VALUE_DEFAULT },
++		{ CR_CAM_MODE,			MODE_AP_WDS},
+ 	};
+ 
+ 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
+@@ -986,7 +987,7 @@ static int print_fw_version(struct zd_chip *chip)
+ 	return 0;
+ }
+ 
+-static int set_mandatory_rates(struct zd_chip *chip, int mode)
++static int set_mandatory_rates(struct zd_chip *chip, int gmode)
+ {
+ 	u32 rates;
+ 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
+@@ -994,17 +995,12 @@ static int set_mandatory_rates(struct zd_chip *chip, int mode)
+ 	 * that the device is supporting. Until further notice we should try
+ 	 * to support 802.11g also for full speed USB.
+ 	 */
+-	switch (mode) {
+-	case MODE_IEEE80211B:
++	if (!gmode)
+ 		rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
+-		break;
+-	case MODE_IEEE80211G:
++	else
+ 		rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
+ 			CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
+-		break;
+-	default:
+-		return -EINVAL;
+-	}
++
+ 	return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
+ }
+ 
+@@ -1108,7 +1104,7 @@ int zd_chip_init_hw(struct zd_chip *chip)
+ 	 * It might be discussed, whether we should suppport pure b mode for
+ 	 * full speed USB.
+ 	 */
+-	r = set_mandatory_rates(chip, MODE_IEEE80211G);
++	r = set_mandatory_rates(chip, 1);
+ 	if (r)
+ 		goto out;
+ 	/* Disabling interrupts is certainly a smart thing here.
+diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
+index 009c037..f8c061a 100644
+--- a/drivers/net/wireless/zd1211rw/zd_chip.h
++++ b/drivers/net/wireless/zd1211rw/zd_chip.h
+@@ -489,6 +489,7 @@ enum {
+ 
+ #define CR_RX_OFFSET			CTL_REG(0x065c)
+ 
++#define CR_BCN_LENGTH			CTL_REG(0x0664)
+ #define CR_PHY_DELAY			CTL_REG(0x066C)
+ #define CR_BCN_FIFO			CTL_REG(0x0670)
+ #define CR_SNIFFER_ON			CTL_REG(0x0674)
+@@ -545,6 +546,8 @@ enum {
+ #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
+ 	RX_FILTER_CFEND | RX_FILTER_CFACK)
+ 
++#define BCN_MODE_IBSS			0x2000000
++
+ /* Monitor mode sets filter to 0xfffff */
+ 
+ #define CR_ACK_TIMEOUT_EXT		CTL_REG(0x0690)
+@@ -578,6 +581,11 @@ enum {
+ 
+ /* CAM: Continuous Access Mode (power management) */
+ #define CR_CAM_MODE			CTL_REG(0x0700)
++#define MODE_IBSS			0x0
++#define MODE_AP				0x1
++#define MODE_STA			0x2
++#define MODE_AP_WDS			0x3
++
+ #define CR_CAM_ROLL_TB_LOW		CTL_REG(0x0704)
+ #define CR_CAM_ROLL_TB_HIGH		CTL_REG(0x0708)
+ #define CR_CAM_ADDRESS			CTL_REG(0x070C)
+@@ -625,11 +633,10 @@ enum {
+ #define CR_S_MD				CTL_REG(0x0830)
+ 
+ #define CR_USB_DEBUG_PORT		CTL_REG(0x0888)
+-
+-#define CR_ZD1211B_TX_PWR_CTL1		CTL_REG(0x0b00)
+-#define CR_ZD1211B_TX_PWR_CTL2		CTL_REG(0x0b04)
+-#define CR_ZD1211B_TX_PWR_CTL3		CTL_REG(0x0b08)
+-#define CR_ZD1211B_TX_PWR_CTL4		CTL_REG(0x0b0c)
++#define CR_ZD1211B_CWIN_MAX_MIN_AC0	CTL_REG(0x0b00)
++#define CR_ZD1211B_CWIN_MAX_MIN_AC1	CTL_REG(0x0b04)
++#define CR_ZD1211B_CWIN_MAX_MIN_AC2	CTL_REG(0x0b08)
++#define CR_ZD1211B_CWIN_MAX_MIN_AC3	CTL_REG(0x0b0c)
+ #define CR_ZD1211B_AIFS_CTL1		CTL_REG(0x0b10)
+ #define CR_ZD1211B_AIFS_CTL2		CTL_REG(0x0b14)
+ #define CR_ZD1211B_TXOP			CTL_REG(0x0b20)
+diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
+index 7c277ec..d8dc41e 100644
+--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c
++++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
+@@ -65,16 +65,14 @@ static const struct channel_range *zd_channel_range(u8 regdomain)
+ 
+ static void unmask_bg_channels(struct ieee80211_hw *hw,
+ 	const struct channel_range *range,
+-	struct ieee80211_hw_mode *mode)
++	struct ieee80211_supported_band *sband)
+ {
+ 	u8 channel;
+ 
+ 	for (channel = range->start; channel < range->end; channel++) {
+ 		struct ieee80211_channel *chan =
+-			&mode->channels[CHAN_TO_IDX(channel)];
+-		chan->flag |= IEEE80211_CHAN_W_SCAN |
+-			IEEE80211_CHAN_W_ACTIVE_SCAN |
+-			IEEE80211_CHAN_W_IBSS;
++			&sband->channels[CHAN_TO_IDX(channel)];
++		chan->flags = 0;
+ 	}
+ }
+ 
+@@ -97,7 +95,6 @@ void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain)
+ 		range = zd_channel_range(ZD_REGDOMAIN_FCC);
+ 	}
+ 
+-	unmask_bg_channels(hw, range, &mac->modes[0]);
+-	unmask_bg_channels(hw, range, &mac->modes[1]);
++	unmask_bg_channels(hw, range, &mac->band);
+ }
+ 
+diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
+index 76ef2d8..69c45ca 100644
+--- a/drivers/net/wireless/zd1211rw/zd_mac.c
++++ b/drivers/net/wireless/zd1211rw/zd_mac.c
+@@ -34,76 +34,61 @@
+ 
+ /* This table contains the hardware specific values for the modulation rates. */
+ static const struct ieee80211_rate zd_rates[] = {
+-	{ .rate = 10,
+-	  .val = ZD_CCK_RATE_1M,
+-	  .flags = IEEE80211_RATE_CCK },
+-	{ .rate = 20,
+-	  .val = ZD_CCK_RATE_2M,
+-	  .val2 = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 55,
+-	  .val = ZD_CCK_RATE_5_5M,
+-	  .val2 = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 110,
+-	  .val = ZD_CCK_RATE_11M,
+-	  .val2 = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
+-	  .flags = IEEE80211_RATE_CCK_2 },
+-	{ .rate = 60,
+-	  .val = ZD_OFDM_RATE_6M,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 90,
+-	  .val = ZD_OFDM_RATE_9M,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 120,
+-	  .val = ZD_OFDM_RATE_12M,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 180,
+-	  .val = ZD_OFDM_RATE_18M,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 240,
+-	  .val = ZD_OFDM_RATE_24M,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 360,
+-	  .val = ZD_OFDM_RATE_36M,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 480,
+-	  .val = ZD_OFDM_RATE_48M,
+-	  .flags = IEEE80211_RATE_OFDM },
+-	{ .rate = 540,
+-	  .val = ZD_OFDM_RATE_54M,
+-	  .flags = IEEE80211_RATE_OFDM },
++	{ .bitrate = 10,
++	  .hw_value = ZD_CCK_RATE_1M, },
++	{ .bitrate = 20,
++	  .hw_value = ZD_CCK_RATE_2M,
++	  .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
++	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 55,
++	  .hw_value = ZD_CCK_RATE_5_5M,
++	  .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
++	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 110,
++	  .hw_value = ZD_CCK_RATE_11M,
++	  .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
++	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++	{ .bitrate = 60,
++	  .hw_value = ZD_OFDM_RATE_6M,
++	  .flags = 0 },
++	{ .bitrate = 90,
++	  .hw_value = ZD_OFDM_RATE_9M,
++	  .flags = 0 },
++	{ .bitrate = 120,
++	  .hw_value = ZD_OFDM_RATE_12M,
++	  .flags = 0 },
++	{ .bitrate = 180,
++	  .hw_value = ZD_OFDM_RATE_18M,
++	  .flags = 0 },
++	{ .bitrate = 240,
++	  .hw_value = ZD_OFDM_RATE_24M,
++	  .flags = 0 },
++	{ .bitrate = 360,
++	  .hw_value = ZD_OFDM_RATE_36M,
++	  .flags = 0 },
++	{ .bitrate = 480,
++	  .hw_value = ZD_OFDM_RATE_48M,
++	  .flags = 0 },
++	{ .bitrate = 540,
++	  .hw_value = ZD_OFDM_RATE_54M,
++	  .flags = 0 },
+ };
+ 
+ static const struct ieee80211_channel zd_channels[] = {
+-	{ .chan = 1,
+-	  .freq = 2412},
+-	{ .chan = 2,
+-	  .freq = 2417},
+-	{ .chan = 3,
+-	  .freq = 2422},
+-	{ .chan = 4,
+-	  .freq = 2427},
+-	{ .chan = 5,
+-	  .freq = 2432},
+-	{ .chan = 6,
+-	  .freq = 2437},
+-	{ .chan = 7,
+-	  .freq = 2442},
+-	{ .chan = 8,
+-	  .freq = 2447},
+-	{ .chan = 9,
+-	  .freq = 2452},
+-	{ .chan = 10,
+-	  .freq = 2457},
+-	{ .chan = 11,
+-	  .freq = 2462},
+-	{ .chan = 12,
+-	  .freq = 2467},
+-	{ .chan = 13,
+-	  .freq = 2472},
+-	{ .chan = 14,
+-	  .freq = 2484}
++	{ .center_freq = 2412, .hw_value = 1 },
++	{ .center_freq = 2417, .hw_value = 2 },
++	{ .center_freq = 2422, .hw_value = 3 },
++	{ .center_freq = 2427, .hw_value = 4 },
++	{ .center_freq = 2432, .hw_value = 5 },
++	{ .center_freq = 2437, .hw_value = 6 },
++	{ .center_freq = 2442, .hw_value = 7 },
++	{ .center_freq = 2447, .hw_value = 8 },
++	{ .center_freq = 2452, .hw_value = 9 },
++	{ .center_freq = 2457, .hw_value = 10 },
++	{ .center_freq = 2462, .hw_value = 11 },
++	{ .center_freq = 2467, .hw_value = 12 },
++	{ .center_freq = 2472, .hw_value = 13 },
++	{ .center_freq = 2484, .hw_value = 14 },
+ };
+ 
+ static void housekeeping_init(struct zd_mac *mac);
+@@ -490,6 +475,46 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
+ 	/* FIXME: Management frame? */
+ }
+ 
++void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
++{
++	struct zd_mac *mac = zd_hw_mac(hw);
++	u32 tmp, j = 0;
++	/* 4 more bytes for tail CRC */
++	u32 full_len = beacon->len + 4;
++	zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
++	zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
++	while (tmp & 0x2) {
++		zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
++		if ((++j % 100) == 0) {
++			printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
++			if (j >= 500)  {
++				printk(KERN_ERR "Giving up beacon config.\n");
++				return;
++			}
++		}
++		msleep(1);
++	}
++
++	zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
++	if (zd_chip_is_zd1211b(&mac->chip))
++		zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
++
++	for (j = 0 ; j < beacon->len; j++)
++		zd_iowrite32(&mac->chip, CR_BCN_FIFO,
++				*((u8 *)(beacon->data + j)));
++
++	for (j = 0; j < 4; j++)
++		zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
++
++	zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
++	/* 802.11b/g 2.4G CCK 1Mb
++	 * 802.11a, not yet implemented, uses different values (see GPL vendor
++	 * driver)
++	 */
++	zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
++			(full_len << 19));
++}
++
+ static int fill_ctrlset(struct zd_mac *mac,
+ 			struct sk_buff *skb,
+ 			struct ieee80211_tx_control *control)
+@@ -503,7 +528,9 @@ static int fill_ctrlset(struct zd_mac *mac,
+ 
+ 	ZD_ASSERT(frag_len <= 0xffff);
+ 
+-	cs->modulation = control->tx_rate;
++	cs->modulation = control->tx_rate->hw_value;
++	if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
++		cs->modulation = control->tx_rate->hw_value_short;
+ 
+ 	cs->tx_length = cpu_to_le16(frag_len);
+ 
+@@ -631,6 +658,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
+ 	int bad_frame = 0;
+ 	u16 fc;
+ 	bool is_qos, is_4addr, need_padding;
++	int i;
++	u8 rate;
+ 
+ 	if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
+ 	             FCS_LEN + sizeof(struct rx_status))
+@@ -660,14 +689,19 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
+ 		}
+ 	}
+ 
+-	stats.channel = _zd_chip_get_channel(&mac->chip);
+-	stats.freq = zd_channels[stats.channel - 1].freq;
+-	stats.phymode = MODE_IEEE80211G;
++	stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
++	stats.band = IEEE80211_BAND_2GHZ;
+ 	stats.ssi = status->signal_strength;
+ 	stats.signal = zd_rx_qual_percent(buffer,
+ 		                          length - sizeof(struct rx_status),
+ 		                          status);
+-	stats.rate = zd_rx_rate(buffer, status);
++
++	rate = zd_rx_rate(buffer, status);
++
++	/* todo: return index in the big switches in zd_rx_rate instead */
++	for (i = 0; i < mac->band.n_bitrates; i++)
++		if (rate == mac->band.bitrates[i].hw_value)
++			stats.rate_idx = i;
+ 
+ 	length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
+ 	buffer += ZD_PLCP_HEADER_SIZE;
+@@ -715,6 +749,7 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
+ 
+ 	switch (conf->type) {
+ 	case IEEE80211_IF_TYPE_MNTR:
++	case IEEE80211_IF_TYPE_MESH_POINT:
+ 	case IEEE80211_IF_TYPE_STA:
+ 		mac->type = conf->type;
+ 		break;
+@@ -736,7 +771,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
+ static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+ {
+ 	struct zd_mac *mac = zd_hw_mac(hw);
+-	return zd_chip_set_channel(&mac->chip, conf->channel);
++	return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
+ }
+ 
+ static int zd_op_config_interface(struct ieee80211_hw *hw,
+@@ -744,15 +779,43 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
+ 				   struct ieee80211_if_conf *conf)
+ {
+ 	struct zd_mac *mac = zd_hw_mac(hw);
++	int associated;
++
++	if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) {
++		associated = true;
++		if (conf->beacon) {
++			zd_mac_config_beacon(hw, conf->beacon);
++			kfree_skb(conf->beacon);
++			zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
++					hw->conf.beacon_int);
++		}
++	} else
++		associated = is_valid_ether_addr(conf->bssid);
+ 
+ 	spin_lock_irq(&mac->lock);
+-	mac->associated = is_valid_ether_addr(conf->bssid);
++	mac->associated = associated;
+ 	spin_unlock_irq(&mac->lock);
+ 
+ 	/* TODO: do hardware bssid filtering */
+ 	return 0;
+ }
+ 
++void zd_process_intr(struct work_struct *work)
++{
++	u16 int_status;
++	struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
++
++	int_status = le16_to_cpu(*(u16 *)(mac->intr_buffer+4));
++	if (int_status & INT_CFG_NEXT_BCN) {
++		if (net_ratelimit())
++			dev_dbg_f(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
++	} else
++		dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
++
++	zd_chip_enable_hwint(&mac->chip);
++}
++
++
+ static void set_multicast_hash_handler(struct work_struct *work)
+ {
+ 	struct zd_mac *mac =
+@@ -780,7 +843,7 @@ static void set_rx_filter_handler(struct work_struct *work)
+ 
+ #define SUPPORTED_FIF_FLAGS \
+ 	(FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
+-	FIF_OTHER_BSS)
++	FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
+ static void zd_op_configure_filter(struct ieee80211_hw *hw,
+ 			unsigned int changed_flags,
+ 			unsigned int *new_flags,
+@@ -894,7 +957,6 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
+ {
+ 	struct zd_mac *mac;
+ 	struct ieee80211_hw *hw;
+-	int i;
+ 
+ 	hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops);
+ 	if (!hw) {
+@@ -912,19 +974,15 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
+ 
+ 	memcpy(mac->channels, zd_channels, sizeof(zd_channels));
+ 	memcpy(mac->rates, zd_rates, sizeof(zd_rates));
+-	mac->modes[0].mode = MODE_IEEE80211G;
+-	mac->modes[0].num_rates = ARRAY_SIZE(zd_rates);
+-	mac->modes[0].rates = mac->rates;
+-	mac->modes[0].num_channels = ARRAY_SIZE(zd_channels);
+-	mac->modes[0].channels = mac->channels;
+-	mac->modes[1].mode = MODE_IEEE80211B;
+-	mac->modes[1].num_rates = 4;
+-	mac->modes[1].rates = mac->rates;
+-	mac->modes[1].num_channels = ARRAY_SIZE(zd_channels);
+-	mac->modes[1].channels = mac->channels;
++	mac->band.n_bitrates = ARRAY_SIZE(zd_rates);
++	mac->band.bitrates = mac->rates;
++	mac->band.n_channels = ARRAY_SIZE(zd_channels);
++	mac->band.channels = mac->channels;
++
++	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
+ 
+ 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+-		     IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
++		    IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+ 	hw->max_rssi = 100;
+ 	hw->max_signal = 100;
+ 
+@@ -933,19 +991,12 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
+ 
+ 	skb_queue_head_init(&mac->ack_wait_queue);
+ 
+-	for (i = 0; i < 2; i++) {
+-		if (ieee80211_register_hwmode(hw, &mac->modes[i])) {
+-			dev_dbg_f(&intf->dev, "cannot register hwmode\n");
+-			ieee80211_free_hw(hw);
+-			return NULL;
+-		}
+-	}
+-
+ 	zd_chip_init(&mac->chip, hw, intf);
+ 	housekeeping_init(mac);
+ 	INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
+ 	INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
+ 	INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler);
++	INIT_WORK(&mac->process_intr, zd_process_intr);
+ 
+ 	SET_IEEE80211_DEV(hw, &intf->dev);
+ 	return hw;
+diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
+index 2dde108..7117024 100644
+--- a/drivers/net/wireless/zd1211rw/zd_mac.h
++++ b/drivers/net/wireless/zd1211rw/zd_mac.h
+@@ -172,12 +172,15 @@ struct zd_tx_skb_control_block {
+ struct zd_mac {
+ 	struct zd_chip chip;
+ 	spinlock_t lock;
++	spinlock_t intr_lock;
+ 	struct ieee80211_hw *hw;
+ 	struct housekeeping housekeeping;
+ 	struct work_struct set_multicast_hash_work;
+ 	struct work_struct set_rts_cts_work;
+ 	struct work_struct set_rx_filter_work;
++	struct work_struct process_intr;
+ 	struct zd_mc_hash multicast_hash;
++	u8 intr_buffer[USB_MAX_EP_INT_BUFFER];
+ 	u8 regdomain;
+ 	u8 default_regdomain;
+ 	int type;
+@@ -185,7 +188,7 @@ struct zd_mac {
+ 	struct sk_buff_head ack_wait_queue;
+ 	struct ieee80211_channel channels[14];
+ 	struct ieee80211_rate rates[12];
+-	struct ieee80211_hw_mode modes[2];
++	struct ieee80211_supported_band band;
+ 
+ 	/* Short preamble (used for RTS/CTS) */
+ 	unsigned int short_preamble:1;
+diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
+index 7942b15..e34675c 100644
+--- a/drivers/net/wireless/zd1211rw/zd_usb.c
++++ b/drivers/net/wireless/zd1211rw/zd_usb.c
+@@ -97,6 +97,7 @@ MODULE_DEVICE_TABLE(usb, usb_ids);
+ #define FW_ZD1211B_PREFIX	"zd1211/zd1211b_"
+ 
+ /* USB device initialization */
++static void int_urb_complete(struct urb *urb);
+ 
+ static int request_fw_file(
+ 	const struct firmware **fw, const char *name, struct device *device)
+@@ -336,11 +337,18 @@ static inline void handle_regs_int(struct urb *urb)
+ 	struct zd_usb *usb = urb->context;
+ 	struct zd_usb_interrupt *intr = &usb->intr;
+ 	int len;
++	u16 int_num;
+ 
+ 	ZD_ASSERT(in_interrupt());
+ 	spin_lock(&intr->lock);
+ 
+-	if (intr->read_regs_enabled) {
++	int_num = le16_to_cpu(*(u16 *)(urb->transfer_buffer+2));
++	if (int_num == CR_INTERRUPT) {
++		struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context));
++		memcpy(&mac->intr_buffer, urb->transfer_buffer,
++				USB_MAX_EP_INT_BUFFER);
++		schedule_work(&mac->process_intr);
++	} else if (intr->read_regs_enabled) {
+ 		intr->read_regs.length = len = urb->actual_length;
+ 
+ 		if (len > sizeof(intr->read_regs.buffer))
+@@ -351,7 +359,6 @@ static inline void handle_regs_int(struct urb *urb)
+ 		goto out;
+ 	}
+ 
+-	dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n");
+ out:
+ 	spin_unlock(&intr->lock);
+ }
+diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
+index 7483d45..e62018a 100644
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -1809,3 +1809,5 @@ module_exit(netif_exit);
+ 
+ MODULE_DESCRIPTION("Xen virtual network device frontend");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("xen:vif");
++MODULE_ALIAS("xennet");
+diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
+index fe6ff3e..2464072 100644
+--- a/drivers/net/yellowfin.c
++++ b/drivers/net/yellowfin.c
+@@ -770,14 +770,14 @@ static void yellowfin_init_ring(struct net_device *dev)
+ 		/* Branch on Tx error. */
+ 		yp->tx_ring[j].dbdma_cmd = cpu_to_le32(CMD_STOP);
+ 		yp->tx_ring[j].branch_addr = cpu_to_le32(yp->tx_ring_dma +
+-			(j+1)*sizeof(struct yellowfin_desc);
++			(j+1)*sizeof(struct yellowfin_desc));
+ 		j++;
+ 		if (yp->flags & FullTxStatus) {
+ 			yp->tx_ring[j].dbdma_cmd =
+ 				cpu_to_le32(CMD_TXSTATUS | sizeof(*yp->tx_status));
+ 			yp->tx_ring[j].request_cnt = sizeof(*yp->tx_status);
+ 			yp->tx_ring[j].addr = cpu_to_le32(yp->tx_status_dma +
+-				i*sizeof(struct tx_status_words);
++				i*sizeof(struct tx_status_words));
+ 		} else {
+ 			/* Symbios chips write only tx_errs word. */
+ 			yp->tx_ring[j].dbdma_cmd =
+diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
+index c03072b..3a7a11a 100644
+--- a/drivers/of/Kconfig
++++ b/drivers/of/Kconfig
+@@ -1,3 +1,15 @@
+ config OF_DEVICE
+ 	def_bool y
+ 	depends on OF && (SPARC || PPC_OF)
++
++config OF_GPIO
++	def_bool y
++	depends on OF && PPC_OF && HAVE_GPIO_LIB
++	help
++	  OpenFirmware GPIO accessors
++
++config OF_I2C
++	def_tristate I2C
++	depends on PPC_OF && I2C
++	help
++	  OpenFirmware I2C accessors
+diff --git a/drivers/of/Makefile b/drivers/of/Makefile
+index ab9be5d..548772e 100644
+--- a/drivers/of/Makefile
++++ b/drivers/of/Makefile
+@@ -1,2 +1,4 @@
+ obj-y = base.o
+ obj-$(CONFIG_OF_DEVICE) += device.o platform.o
++obj-$(CONFIG_OF_GPIO)   += gpio.o
++obj-$(CONFIG_OF_I2C)	+= of_i2c.o
+diff --git a/drivers/of/base.c b/drivers/of/base.c
+index 80c9dec..9bd7c4a 100644
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -117,6 +117,32 @@ int of_device_is_compatible(const struct device_node *device,
+ EXPORT_SYMBOL(of_device_is_compatible);
+ 
+ /**
++ *  of_device_is_available - check if a device is available for use
++ *
++ *  @device: Node to check for availability
++ *
++ *  Returns 1 if the status property is absent or set to "okay" or "ok",
++ *  0 otherwise
++ */
++int of_device_is_available(const struct device_node *device)
++{
++	const char *status;
++	int statlen;
++
++	status = of_get_property(device, "status", &statlen);
++	if (status == NULL)
++		return 1;
++
++	if (statlen > 0) {
++		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
++			return 1;
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL(of_device_is_available);
++
++/**
+  *	of_get_parent - Get a node's parent if any
+  *	@node:	Node to get parent
+  *
+diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
+new file mode 100644
+index 0000000..000681e
+--- /dev/null
++++ b/drivers/of/gpio.c
+@@ -0,0 +1,242 @@
++/*
++ * OF helpers for the GPIO API
++ *
++ * Copyright (c) 2007-2008  MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at 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/kernel.h>
++#include <linux/errno.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_gpio.h>
++#include <asm/prom.h>
++
++/**
++ * of_get_gpio - Get a GPIO number from the device tree to use with GPIO API
++ * @np:		device node to get GPIO from
++ * @index:	index of the GPIO
++ *
++ * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
++ * value on the error condition.
++ */
++int of_get_gpio(struct device_node *np, int index)
++{
++	int ret = -EINVAL;
++	struct device_node *gc;
++	struct of_gpio_chip *of_gc = NULL;
++	int size;
++	const u32 *gpios;
++	u32 nr_cells;
++	int i;
++	const void *gpio_spec;
++	const u32 *gpio_cells;
++	int gpio_index = 0;
++
++	gpios = of_get_property(np, "gpios", &size);
++	if (!gpios) {
++		ret = -ENOENT;
++		goto err0;
++	}
++	nr_cells = size / sizeof(u32);
++
++	for (i = 0; i < nr_cells; gpio_index++) {
++		const phandle *gpio_phandle;
++
++		gpio_phandle = gpios + i;
++		gpio_spec = gpio_phandle + 1;
++
++		/* one cell hole in the gpios = <>; */
++		if (!*gpio_phandle) {
++			if (gpio_index == index)
++				return -ENOENT;
++			i++;
++			continue;
++		}
++
++		gc = of_find_node_by_phandle(*gpio_phandle);
++		if (!gc) {
++			pr_debug("%s: could not find phandle for gpios\n",
++				 np->full_name);
++			goto err0;
++		}
++
++		of_gc = gc->data;
++		if (!of_gc) {
++			pr_debug("%s: gpio controller %s isn't registered\n",
++				 np->full_name, gc->full_name);
++			goto err1;
++		}
++
++		gpio_cells = of_get_property(gc, "#gpio-cells", &size);
++		if (!gpio_cells || size != sizeof(*gpio_cells) ||
++				*gpio_cells != of_gc->gpio_cells) {
++			pr_debug("%s: wrong #gpio-cells for %s\n",
++				 np->full_name, gc->full_name);
++			goto err1;
++		}
++
++		/* Next phandle is at phandle cells + #gpio-cells */
++		i += sizeof(*gpio_phandle) / sizeof(u32) + *gpio_cells;
++		if (i >= nr_cells + 1) {
++			pr_debug("%s: insufficient gpio-spec length\n",
++				 np->full_name);
++			goto err1;
++		}
++
++		if (gpio_index == index)
++			break;
++
++		of_gc = NULL;
++		of_node_put(gc);
++	}
++
++	if (!of_gc) {
++		ret = -ENOENT;
++		goto err0;
++	}
++
++	ret = of_gc->xlate(of_gc, np, gpio_spec);
++	if (ret < 0)
++		goto err1;
++
++	ret += of_gc->gc.base;
++err1:
++	of_node_put(gc);
++err0:
++	pr_debug("%s exited with status %d\n", __func__, ret);
++	return ret;
++}
++EXPORT_SYMBOL(of_get_gpio);
++
++/**
++ * of_gpio_simple_xlate - translate gpio_spec to the GPIO number
++ * @of_gc:	pointer to the of_gpio_chip structure
++ * @np:		device node of the GPIO chip
++ * @gpio_spec:	gpio specifier as found in the device tree
++ *
++ * This is simple translation function, suitable for the most 1:1 mapped
++ * gpio chips. This function performs only one sanity check: whether gpio
++ * is less than ngpios (that is specified in the gpio_chip).
++ */
++int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np,
++			 const void *gpio_spec)
++{
++	const u32 *gpio = gpio_spec;
++
++	if (*gpio > of_gc->gc.ngpio)
++		return -EINVAL;
++
++	return *gpio;
++}
++EXPORT_SYMBOL(of_gpio_simple_xlate);
++
++/* Should be sufficient for now, later we'll use dynamic bases. */
++#if defined(CONFIG_PPC32) || defined(CONFIG_SPARC32)
++#define GPIOS_PER_CHIP 32
++#else
++#define GPIOS_PER_CHIP 64
++#endif
++
++static int of_get_gpiochip_base(struct device_node *np)
++{
++	struct device_node *gc = NULL;
++	int gpiochip_base = 0;
++
++	while ((gc = of_find_all_nodes(gc))) {
++		if (!of_get_property(gc, "gpio-controller", NULL))
++			continue;
++
++		if (gc != np) {
++			gpiochip_base += GPIOS_PER_CHIP;
++			continue;
++		}
++
++		of_node_put(gc);
++
++		if (gpiochip_base >= ARCH_NR_GPIOS)
++			return -ENOSPC;
++
++		return gpiochip_base;
++	}
++
++	return -ENOENT;
++}
++
++/**
++ * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank)
++ * @np:		device node of the GPIO chip
++ * @mm_gc:	pointer to the of_mm_gpio_chip allocated structure
++ *
++ * To use this function you should allocate and fill mm_gc with:
++ *
++ * 1) In the gpio_chip structure:
++ *    - all the callbacks
++ *
++ * 2) In the of_gpio_chip structure:
++ *    - gpio_cells
++ *    - xlate callback (optional)
++ *
++ * 3) In the of_mm_gpio_chip structure:
++ *    - save_regs callback (optional)
++ *
++ * If succeeded, this function will map bank's memory and will
++ * do all necessary work for you. Then you'll able to use .regs
++ * to manage GPIOs from the callbacks.
++ */
++int of_mm_gpiochip_add(struct device_node *np,
++		       struct of_mm_gpio_chip *mm_gc)
++{
++	int ret = -ENOMEM;
++	struct of_gpio_chip *of_gc = &mm_gc->of_gc;
++	struct gpio_chip *gc = &of_gc->gc;
++
++	gc->label = kstrdup(np->full_name, GFP_KERNEL);
++	if (!gc->label)
++		goto err0;
++
++	mm_gc->regs = of_iomap(np, 0);
++	if (!mm_gc->regs)
++		goto err1;
++
++	gc->base = of_get_gpiochip_base(np);
++	if (gc->base < 0) {
++		ret = gc->base;
++		goto err1;
++	}
++
++	if (!of_gc->xlate)
++		of_gc->xlate = of_gpio_simple_xlate;
++
++	if (mm_gc->save_regs)
++		mm_gc->save_regs(mm_gc);
++
++	np->data = of_gc;
++
++	ret = gpiochip_add(gc);
++	if (ret)
++		goto err2;
++
++	/* We don't want to lose the node and its ->data */
++	of_node_get(np);
++
++	pr_debug("%s: registered as generic GPIO chip, base is %d\n",
++		 np->full_name, gc->base);
++	return 0;
++err2:
++	np->data = NULL;
++	iounmap(mm_gc->regs);
++err1:
++	kfree(gc->label);
++err0:
++	pr_err("%s: GPIO chip registration failed with status %d\n",
++	       np->full_name, ret);
++	return ret;
++}
++EXPORT_SYMBOL(of_mm_gpiochip_add);
+diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
+new file mode 100644
+index 0000000..715a444
+--- /dev/null
++++ b/drivers/of/of_i2c.c
+@@ -0,0 +1,118 @@
++/*
++ * OF helpers for the I2C API
++ *
++ * Copyright (c) 2008 Jochen Friedrich <jochen at scram.de>
++ *
++ * Based on a previous patch from Jon Smirl <jonsmirl at gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/i2c.h>
++#include <linux/of.h>
++#include <linux/module.h>
++
++struct i2c_driver_device {
++	char    *of_device;
++	char    *i2c_type;
++};
++
++static struct i2c_driver_device i2c_devices[] = {
++	{ "dallas,ds1374", "rtc-ds1374" },
++};
++
++static int of_find_i2c_driver(struct device_node *node,
++			      struct i2c_board_info *info)
++{
++	int i, cplen;
++	const char *compatible;
++	const char *p;
++
++	/* 1. search for exception list entry */
++	for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
++		if (!of_device_is_compatible(node, i2c_devices[i].of_device))
++			continue;
++		if (strlcpy(info->type, i2c_devices[i].i2c_type,
++			    I2C_NAME_SIZE) >= I2C_NAME_SIZE)
++			return -ENOMEM;
++
++		return 0;
++	}
++
++	compatible = of_get_property(node, "compatible", &cplen);
++	if (!compatible)
++		return -ENODEV;
++
++	/* 2. search for linux,<i2c-type> entry */
++	p = compatible;
++	while (cplen > 0) {
++		if (!strncmp(p, "linux,", 6)) {
++			p += 6;
++			if (strlcpy(info->type, p,
++				    I2C_NAME_SIZE) >= I2C_NAME_SIZE)
++				return -ENOMEM;
++			return 0;
++		}
++
++		i = strlen(p) + 1;
++		p += i;
++		cplen -= i;
++	}
++
++	/* 3. take fist compatible entry and strip manufacturer */
++	p = strchr(compatible, ',');
++	if (!p)
++		return -ENODEV;
++	p++;
++	if (strlcpy(info->type, p, I2C_NAME_SIZE) >= I2C_NAME_SIZE)
++		return -ENOMEM;
++	return 0;
++}
++
++void of_register_i2c_devices(struct i2c_adapter *adap,
++			     struct device_node *adap_node)
++{
++	void *result;
++	struct device_node *node;
++
++	for_each_child_of_node(adap_node, node) {
++		struct i2c_board_info info = {};
++		const u32 *addr;
++		int len;
++
++		addr = of_get_property(node, "reg", &len);
++		if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
++			printk(KERN_ERR
++			       "of-i2c: invalid i2c device entry\n");
++			continue;
++		}
++
++		info.irq = irq_of_parse_and_map(node, 0);
++		if (info.irq == NO_IRQ)
++			info.irq = -1;
++
++		if (of_find_i2c_driver(node, &info) < 0) {
++			irq_dispose_mapping(info.irq);
++			continue;
++		}
++
++		info.addr = *addr;
++
++		request_module(info.type);
++
++		result = i2c_new_device(adap, &info);
++		if (result == NULL) {
++			printk(KERN_ERR
++			       "of-i2c: Failed to load driver for %s\n",
++			       info.type);
++			irq_dispose_mapping(info.irq);
++			continue;
++		}
++	}
++}
++EXPORT_SYMBOL(of_register_i2c_devices);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
+index 03c763c..d9c6322 100644
+--- a/drivers/parisc/dino.c
++++ b/drivers/parisc/dino.c
+@@ -496,7 +496,6 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr)
+ 		list_for_each_safe(ln, tmp_ln, &bus->devices) {
+ 			struct pci_dev *dev = pci_dev_b(ln);
+ 
+-			list_del(&dev->global_list);
+ 			list_del(&dev->bus_list);
+ 		}
+ 			
+diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
+index b7bcdcc..209b4a4 100644
+--- a/drivers/parport/Kconfig
++++ b/drivers/parport/Kconfig
+@@ -36,7 +36,7 @@ if PARPORT
+ config PARPORT_PC
+ 	tristate "PC-style hardware"
+ 	depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && \
+-		(!M68K || ISA) && !MN10300
++		(!M68K || ISA) && !MN10300 && !AVR32
+ 	---help---
+ 	  You should say Y here if you have a PC-style parallel port. All
+ 	  IBM PC compatible computers and some Alphas have PC-style
+diff --git a/drivers/pci/access.c b/drivers/pci/access.c
+index fc405f0..ec8f700 100644
+--- a/drivers/pci/access.c
++++ b/drivers/pci/access.c
+@@ -1,3 +1,4 @@
++#include <linux/delay.h>
+ #include <linux/pci.h>
+ #include <linux/module.h>
+ #include <linux/sched.h>
+@@ -126,6 +127,171 @@ PCI_USER_WRITE_CONFIG(byte, u8)
+ PCI_USER_WRITE_CONFIG(word, u16)
+ PCI_USER_WRITE_CONFIG(dword, u32)
+ 
++/* VPD access through PCI 2.2+ VPD capability */
++
++#define PCI_VPD_PCI22_SIZE (PCI_VPD_ADDR_MASK + 1)
++
++struct pci_vpd_pci22 {
++	struct pci_vpd base;
++	spinlock_t lock; /* controls access to hardware and the flags */
++	u8	cap;
++	bool	busy;
++	bool	flag; /* value of F bit to wait for */
++};
++
++/* Wait for last operation to complete */
++static int pci_vpd_pci22_wait(struct pci_dev *dev)
++{
++	struct pci_vpd_pci22 *vpd =
++		container_of(dev->vpd, struct pci_vpd_pci22, base);
++	u16 flag, status;
++	int wait;
++	int ret;
++
++	if (!vpd->busy)
++		return 0;
++
++	flag = vpd->flag ? PCI_VPD_ADDR_F : 0;
++	wait = vpd->flag ? 10 : 1000; /* read: 100 us; write: 10 ms */
++	for (;;) {
++		ret = pci_user_read_config_word(dev,
++						vpd->cap + PCI_VPD_ADDR,
++						&status);
++		if (ret < 0)
++			return ret;
++		if ((status & PCI_VPD_ADDR_F) == flag) {
++			vpd->busy = false;
++			return 0;
++		}
++		if (wait-- == 0)
++			return -ETIMEDOUT;
++		udelay(10);
++	}
++}
++
++static int pci_vpd_pci22_read(struct pci_dev *dev, int pos, int size,
++			      char *buf)
++{
++	struct pci_vpd_pci22 *vpd =
++		container_of(dev->vpd, struct pci_vpd_pci22, base);
++	u32 val;
++	int ret;
++	int begin, end, i;
++
++	if (pos < 0 || pos > PCI_VPD_PCI22_SIZE ||
++	    size > PCI_VPD_PCI22_SIZE  - pos)
++		return -EINVAL;
++	if (size == 0)
++		return 0;
++
++	spin_lock_irq(&vpd->lock);
++	ret = pci_vpd_pci22_wait(dev);
++	if (ret < 0)
++		goto out;
++	ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
++					 pos & ~3);
++	if (ret < 0)
++		goto out;
++	vpd->busy = true;
++	vpd->flag = 1;
++	ret = pci_vpd_pci22_wait(dev);
++	if (ret < 0)
++		goto out;
++	ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA,
++					 &val);
++out:
++	spin_unlock_irq(&vpd->lock);
++	if (ret < 0)
++		return ret;
++
++	/* Convert to bytes */
++	begin = pos & 3;
++	end = min(4, begin + size);
++	for (i = 0; i < end; ++i) {
++		if (i >= begin)
++			*buf++ = val;
++		val >>= 8;
++	}
++	return end - begin;
++}
++
++static int pci_vpd_pci22_write(struct pci_dev *dev, int pos, int size,
++			       const char *buf)
++{
++	struct pci_vpd_pci22 *vpd =
++		container_of(dev->vpd, struct pci_vpd_pci22, base);
++	u32 val;
++	int ret;
++
++	if (pos < 0 || pos > PCI_VPD_PCI22_SIZE || pos & 3 ||
++	    size > PCI_VPD_PCI22_SIZE - pos || size < 4)
++		return -EINVAL;
++
++	val = (u8) *buf++;
++	val |= ((u8) *buf++) << 8;
++	val |= ((u8) *buf++) << 16;
++	val |= ((u32)(u8) *buf++) << 24;
++
++	spin_lock_irq(&vpd->lock);
++	ret = pci_vpd_pci22_wait(dev);
++	if (ret < 0)
++		goto out;
++	ret = pci_user_write_config_dword(dev, vpd->cap + PCI_VPD_DATA,
++					  val);
++	if (ret < 0)
++		goto out;
++	ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
++					 pos | PCI_VPD_ADDR_F);
++	if (ret < 0)
++		goto out;
++	vpd->busy = true;
++	vpd->flag = 0;
++	ret = pci_vpd_pci22_wait(dev);
++out:
++	spin_unlock_irq(&vpd->lock);
++	if (ret < 0)
++		return ret;
++
++	return 4;
++}
++
++static int pci_vpd_pci22_get_size(struct pci_dev *dev)
++{
++	return PCI_VPD_PCI22_SIZE;
++}
++
++static void pci_vpd_pci22_release(struct pci_dev *dev)
++{
++	kfree(container_of(dev->vpd, struct pci_vpd_pci22, base));
++}
++
++static struct pci_vpd_ops pci_vpd_pci22_ops = {
++	.read = pci_vpd_pci22_read,
++	.write = pci_vpd_pci22_write,
++	.get_size = pci_vpd_pci22_get_size,
++	.release = pci_vpd_pci22_release,
++};
++
++int pci_vpd_pci22_init(struct pci_dev *dev)
++{
++	struct pci_vpd_pci22 *vpd;
++	u8 cap;
++
++	cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
++	if (!cap)
++		return -ENODEV;
++	vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
++	if (!vpd)
++		return -ENOMEM;
++
++	vpd->base.ops = &pci_vpd_pci22_ops;
++	spin_lock_init(&vpd->lock);
++	vpd->cap = cap;
++	vpd->busy = false;
++	dev->vpd = &vpd->base;
++	return 0;
++}
++
+ /**
+  * pci_block_user_cfg_access - Block userspace PCI config reads/writes
+  * @dev:	pci device struct
+diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
+index d708358..529d9d7 100644
+--- a/drivers/pci/bus.c
++++ b/drivers/pci/bus.c
+@@ -84,10 +84,7 @@ int pci_bus_add_device(struct pci_dev *dev)
+ 	if (retval)
+ 		return retval;
+ 
+-	down_write(&pci_bus_sem);
+-	list_add_tail(&dev->global_list, &pci_devices);
+-	up_write(&pci_bus_sem);
+-
++	dev->is_added = 1;
+ 	pci_proc_attach_device(dev);
+ 	pci_create_sysfs_dev_files(dev);
+ 	return 0;
+@@ -112,11 +109,8 @@ void pci_bus_add_devices(struct pci_bus *bus)
+ 	int retval;
+ 
+ 	list_for_each_entry(dev, &bus->devices, bus_list) {
+-		/*
+-		 * Skip already-present devices (which are on the
+-		 * global device list.)
+-		 */
+-		if (!list_empty(&dev->global_list))
++		/* Skip already-added devices */
++		if (dev->is_added)
+ 			continue;
+ 		retval = pci_bus_add_device(dev);
+ 		if (retval)
+@@ -124,8 +118,7 @@ void pci_bus_add_devices(struct pci_bus *bus)
+ 	}
+ 
+ 	list_for_each_entry(dev, &bus->devices, bus_list) {
+-
+-		BUG_ON(list_empty(&dev->global_list));
++		BUG_ON(!dev->is_added);
+ 
+ 		/*
+ 		 * If there is an unattached subordinate bus, attach
+diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
+index 2cdd832..eacfb13 100644
+--- a/drivers/pci/hotplug/Kconfig
++++ b/drivers/pci/hotplug/Kconfig
+@@ -63,7 +63,7 @@ config HOTPLUG_PCI_COMPAQ_NVRAM
+ 
+ config HOTPLUG_PCI_IBM
+ 	tristate "IBM PCI Hotplug driver"
+-	depends on X86_IO_APIC && X86 && PCI_BIOS && PCI_LEGACY
++	depends on X86_IO_APIC && X86 && PCI_BIOS
+ 	help
+ 	  Say Y here if you have a motherboard with a IBM PCI Hotplug
+ 	  controller.
+@@ -119,7 +119,7 @@ config HOTPLUG_PCI_CPCI_ZT5550
+ 
+ config HOTPLUG_PCI_CPCI_GENERIC
+ 	tristate "Generic port I/O CompactPCI Hotplug driver"
+-	depends on HOTPLUG_PCI_CPCI && X86 && PCI_LEGACY
++	depends on HOTPLUG_PCI_CPCI && X86
+ 	help
+ 	  Say Y here if you have a CompactPCI system card that exposes the #ENUM
+ 	  hotswap signal as a bit in a system register that can be read through
+diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
+index 270a33c..f8c187a 100644
+--- a/drivers/pci/hotplug/acpi_pcihp.c
++++ b/drivers/pci/hotplug/acpi_pcihp.c
+@@ -36,7 +36,7 @@
+ 
+ #define MY_NAME	"acpi_pcihp"
+ 
+-#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
++#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0)
+ #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+ #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+ #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+@@ -71,7 +71,7 @@ decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+ 	default:
+ 		printk(KERN_WARNING
+ 		       "%s: Type 0 Revision %d record not supported\n",
+-		       __FUNCTION__, revision);
++		       __func__, revision);
+ 		return AE_ERROR;
+ 	}
+ 	return AE_OK;
+@@ -100,7 +100,7 @@ decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+ 	default:
+ 		printk(KERN_WARNING
+ 		       "%s: Type 1 Revision %d record not supported\n",
+-		       __FUNCTION__, revision);
++		       __func__, revision);
+ 		return AE_ERROR;
+ 	}
+ 	return AE_OK;
+@@ -142,7 +142,7 @@ decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+ 	default:
+ 		printk(KERN_WARNING
+ 		       "%s: Type 2 Revision %d record not supported\n",
+-		       __FUNCTION__, revision);
++		       __func__, revision);
+ 		return AE_ERROR;
+ 	}
+ 	return AE_OK;
+@@ -203,7 +203,7 @@ acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
+ 			break;
+ 		default:
+ 			printk(KERN_ERR "%s: Type %d record not supported\n",
+-			       __FUNCTION__, type);
++			       __func__, type);
+ 			status = AE_ERROR;
+ 			goto exit;
+ 		}
+@@ -235,7 +235,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+ 		ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
+ 		if (!ret_buf.pointer) {
+ 			printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
+-				__FUNCTION__, (char *)string.pointer);
++				__func__, (char *)string.pointer);
+ 			kfree(string.pointer);
+ 			return AE_NO_MEMORY;
+ 		}
+@@ -245,7 +245,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+ 			break;
+ 	default:
+ 		if (ACPI_FAILURE(status)) {
+-			pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
++			pr_debug("%s:%s _HPP fail=0x%x\n", __func__,
+ 				(char *)string.pointer, status);
+ 			kfree(string.pointer);
+ 			return status;
+@@ -254,7 +254,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+ 
+ 	ext_obj = (union acpi_object *) ret_buf.pointer;
+ 	if (ext_obj->type != ACPI_TYPE_PACKAGE) {
+-		printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
++		printk(KERN_ERR "%s:%s _HPP obj not a package\n", __func__,
+ 				(char *)string.pointer);
+ 		status = AE_ERROR;
+ 		goto free_and_return;
+@@ -270,7 +270,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+ 			break;
+ 		default:
+ 			printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
+-				__FUNCTION__, (char *)string.pointer);
++				__func__, (char *)string.pointer);
+ 			status = AE_ERROR;
+ 			goto free_and_return;
+ 		}
+@@ -311,12 +311,12 @@ acpi_status acpi_run_oshp(acpi_handle handle)
+ 	if (ACPI_FAILURE(status))
+ 		if (status != AE_NOT_FOUND)
+ 			printk(KERN_ERR "%s:%s OSHP fails=0x%x\n",
+-			       __FUNCTION__, (char *)string.pointer, status);
++			       __func__, (char *)string.pointer, status);
+ 		else
+ 			dbg("%s:%s OSHP not found\n",
+-			    __FUNCTION__, (char *)string.pointer);
++			    __func__, (char *)string.pointer);
+ 	else
+-		pr_debug("%s:%s OSHP passes\n", __FUNCTION__,
++		pr_debug("%s:%s OSHP passes\n", __func__,
+ 			(char *)string.pointer);
+ 
+ 	kfree(string.pointer);
+diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
+index 9279d5b..7af68ba 100644
+--- a/drivers/pci/hotplug/acpiphp_core.c
++++ b/drivers/pci/hotplug/acpiphp_core.c
+@@ -138,7 +138,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	/* enable the specified slot */
+ 	return acpiphp_enable_slot(slot->acpi_slot);
+@@ -156,7 +156,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	/* disable the specified slot */
+ 	retval = acpiphp_disable_slot(slot->acpi_slot);
+@@ -179,7 +179,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
+  {
+ 	int retval = -ENODEV;
+ 
+- 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ 	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+  
+ 	if (attention_info && try_module_get(attention_info->owner)) {
+ 		retval = attention_info->set_attn(hotplug_slot, status);
+@@ -202,7 +202,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = acpiphp_get_power_status(slot->acpi_slot);
+ 
+@@ -224,7 +224,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ {
+ 	int retval = -EINVAL;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	if (attention_info && try_module_get(attention_info->owner)) {
+ 		retval = attention_info->get_attn(hotplug_slot, value);
+@@ -247,7 +247,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = acpiphp_get_latch_status(slot->acpi_slot);
+ 
+@@ -267,7 +267,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = acpiphp_get_adapter_status(slot->acpi_slot);
+ 
+@@ -284,7 +284,7 @@ static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = acpiphp_get_address(slot->acpi_slot);
+ 
+@@ -318,7 +318,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	kfree(slot->hotplug_slot);
+ 	kfree(slot);
+diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
+index 5e50008..648596d 100644
+--- a/drivers/pci/hotplug/acpiphp_glue.c
++++ b/drivers/pci/hotplug/acpiphp_glue.c
+@@ -352,7 +352,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
+ 		/* use default numbers */
+ 		printk(KERN_WARNING
+ 		       "%s: Could not get hotplug parameters. Use defaults\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		bridge->hpp.t0 = &bridge->hpp.type0_data;
+ 		bridge->hpp.t0->revision = 0;
+ 		bridge->hpp.t0->cache_line_size = 0x10;
+@@ -534,7 +534,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
+ 
+ 	status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp);
+ 	if (ACPI_FAILURE(status)) {
+-		dbg("%s: _ADR evaluation failure\n", __FUNCTION__);
++		dbg("%s: _ADR evaluation failure\n", __func__);
+ 		return AE_OK;
+ 	}
+ 
+@@ -578,7 +578,7 @@ static int add_bridge(acpi_handle handle)
+ 	if (ACPI_SUCCESS(status)) {
+ 		status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
+ 		if (ACPI_FAILURE(status)) {
+-			dbg("%s: _STA evaluation failure\n", __FUNCTION__);
++			dbg("%s: _STA evaluation failure\n", __func__);
+ 			return 0;
+ 		}
+ 		if ((tmp & ACPI_STA_FUNCTIONING) == 0)
+@@ -928,10 +928,10 @@ static int power_on_slot(struct acpiphp_slot *slot)
+ 		func = list_entry(l, struct acpiphp_func, sibling);
+ 
+ 		if (func->flags & FUNC_HAS_PS0) {
+-			dbg("%s: executing _PS0\n", __FUNCTION__);
++			dbg("%s: executing _PS0\n", __func__);
+ 			status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
+ 			if (ACPI_FAILURE(status)) {
+-				warn("%s: _PS0 failed\n", __FUNCTION__);
++				warn("%s: _PS0 failed\n", __func__);
+ 				retval = -1;
+ 				goto err_exit;
+ 			} else
+@@ -966,7 +966,7 @@ static int power_off_slot(struct acpiphp_slot *slot)
+ 		if (func->flags & FUNC_HAS_PS3) {
+ 			status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
+ 			if (ACPI_FAILURE(status)) {
+-				warn("%s: _PS3 failed\n", __FUNCTION__);
++				warn("%s: _PS3 failed\n", __func__);
+ 				retval = -1;
+ 				goto err_exit;
+ 			} else
+@@ -1300,7 +1300,7 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot)
+ 
+ 			status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
+ 			if (ACPI_FAILURE(status)) {
+-				warn("%s: _EJ0 failed\n", __FUNCTION__);
++				warn("%s: _EJ0 failed\n", __func__);
+ 				return -1;
+ 			} else
+ 				break;
+@@ -1349,7 +1349,7 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
+ 		}
+ 	}
+ 
+-	dbg("%s: %d enabled, %d disabled\n", __FUNCTION__, enabled, disabled);
++	dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled);
+ 
+  err_exit:
+ 	return retval;
+@@ -1527,7 +1527,7 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+ 	if (bridge) {
+ 		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+ 		dbg("%s: re-enumerating slots under %s\n",
+-			__FUNCTION__, objname);
++			__func__, objname);
+ 		acpiphp_check_bridge(bridge);
+ 	}
+ 	return AE_OK ;
+@@ -1572,10 +1572,10 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
+ 	switch (type) {
+ 	case ACPI_NOTIFY_BUS_CHECK:
+ 		/* bus re-enumerate */
+-		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
++		dbg("%s: Bus check notify on %s\n", __func__, objname);
+ 		if (bridge) {
+ 			dbg("%s: re-enumerating slots under %s\n",
+-				__FUNCTION__, objname);
++				__func__, objname);
+ 			acpiphp_check_bridge(bridge);
+ 		}
+ 		if (num_sub_bridges)
+@@ -1585,18 +1585,18 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
+ 
+ 	case ACPI_NOTIFY_DEVICE_CHECK:
+ 		/* device check */
+-		dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
++		dbg("%s: Device check notify on %s\n", __func__, objname);
+ 		acpiphp_check_bridge(bridge);
+ 		break;
+ 
+ 	case ACPI_NOTIFY_DEVICE_WAKE:
+ 		/* wake event */
+-		dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
++		dbg("%s: Device wake notify on %s\n", __func__, objname);
+ 		break;
+ 
+ 	case ACPI_NOTIFY_EJECT_REQUEST:
+ 		/* request device eject */
+-		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
++		dbg("%s: Device eject notify on %s\n", __func__, objname);
+ 		if ((bridge->type != BRIDGE_TYPE_HOST) &&
+ 		    (bridge->flags & BRIDGE_HAS_EJ0)) {
+ 			struct acpiphp_slot *slot;
+@@ -1649,24 +1649,24 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
+ 	switch (type) {
+ 	case ACPI_NOTIFY_BUS_CHECK:
+ 		/* bus re-enumerate */
+-		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
++		dbg("%s: Bus check notify on %s\n", __func__, objname);
+ 		acpiphp_enable_slot(func->slot);
+ 		break;
+ 
+ 	case ACPI_NOTIFY_DEVICE_CHECK:
+ 		/* device check : re-enumerate from parent bus */
+-		dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
++		dbg("%s: Device check notify on %s\n", __func__, objname);
+ 		acpiphp_check_bridge(func->slot->bridge);
+ 		break;
+ 
+ 	case ACPI_NOTIFY_DEVICE_WAKE:
+ 		/* wake event */
+-		dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
++		dbg("%s: Device wake notify on %s\n", __func__, objname);
+ 		break;
+ 
+ 	case ACPI_NOTIFY_EJECT_REQUEST:
+ 		/* request device eject */
+-		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
++		dbg("%s: Device eject notify on %s\n", __func__, objname);
+ 		if (!(acpiphp_disable_slot(func->slot)))
+ 			acpiphp_eject_slot(func->slot);
+ 		break;
+@@ -1796,7 +1796,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
+ 		if (retval)
+ 			power_off_slot(slot);
+ 	} else {
+-		dbg("%s: Slot status is not ACPI_STA_ALL\n", __FUNCTION__);
++		dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__);
+ 		power_off_slot(slot);
+ 	}
+ 
+diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
+index b0a22b9..ede9051 100644
+--- a/drivers/pci/hotplug/acpiphp_ibm.c
++++ b/drivers/pci/hotplug/acpiphp_ibm.c
+@@ -186,7 +186,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
+ 
+ 	ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot));
+ 
+-	dbg("%s: set slot %d (%d) attention status to %d\n", __FUNCTION__,
++	dbg("%s: set slot %d (%d) attention status to %d\n", __func__,
+ 			ibm_slot->slot.slot_num, ibm_slot->slot.slot_id,
+ 			(status ? 1 : 0));
+ 
+@@ -231,7 +231,7 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
+ 	else
+ 		*status = 0;
+ 
+-	dbg("%s: get slot %d (%d) attention status is %d\n", __FUNCTION__,
++	dbg("%s: get slot %d (%d) attention status is %d\n", __func__,
+ 			ibm_slot->slot.slot_num, ibm_slot->slot.slot_id,
+ 			*status);
+ 
+@@ -263,10 +263,10 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
+ 	u8 subevent = event & 0xf0;
+ 	struct notification *note = context;
+ 
+-	dbg("%s: Received notification %02x\n", __FUNCTION__, event);
++	dbg("%s: Received notification %02x\n", __func__, event);
+ 
+ 	if (subevent == 0x80) {
+-		dbg("%s: generationg bus event\n", __FUNCTION__);
++		dbg("%s: generationg bus event\n", __func__);
+ 		acpi_bus_generate_proc_event(note->device, note->event, detail);
+ 		acpi_bus_generate_netlink_event(note->device->pnp.device_class,
+ 						  note->device->dev.bus_id,
+@@ -299,7 +299,7 @@ static int ibm_get_table_from_acpi(char **bufp)
+ 
+ 	status = acpi_evaluate_object(ibm_acpi_handle, "APCI", NULL, &buffer);
+ 	if (ACPI_FAILURE(status)) {
+-		err("%s:  APCI evaluation failed\n", __FUNCTION__);
++		err("%s:  APCI evaluation failed\n", __func__);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -307,13 +307,13 @@ static int ibm_get_table_from_acpi(char **bufp)
+ 	if (!(package) ||
+ 			(package->type != ACPI_TYPE_PACKAGE) ||
+ 			!(package->package.elements)) {
+-		err("%s:  Invalid APCI object\n", __FUNCTION__);
++		err("%s:  Invalid APCI object\n", __func__);
+ 		goto read_table_done;
+ 	}
+ 
+ 	for(size = 0, i = 0; i < package->package.count; i++) {
+ 		if (package->package.elements[i].type != ACPI_TYPE_BUFFER) {
+-			err("%s:  Invalid APCI element %d\n", __FUNCTION__, i);
++			err("%s:  Invalid APCI element %d\n", __func__, i);
+ 			goto read_table_done;
+ 		}
+ 		size += package->package.elements[i].buffer.length;
+@@ -324,7 +324,7 @@ static int ibm_get_table_from_acpi(char **bufp)
+ 
+ 	lbuf = kzalloc(size, GFP_KERNEL);
+ 	dbg("%s: element count: %i, ASL table size: %i, &table = 0x%p\n",
+-			__FUNCTION__, package->package.count, size, lbuf);
++			__func__, package->package.count, size, lbuf);
+ 
+ 	if (lbuf) {
+ 		*bufp = lbuf;
+@@ -368,7 +368,7 @@ static ssize_t ibm_read_apci_table(struct kobject *kobj,
+ 	int bytes_read = -EINVAL;
+ 	char *table = NULL;
+ 	
+-	dbg("%s: pos = %d, size = %zd\n", __FUNCTION__, (int)pos, size);
++	dbg("%s: pos = %d, size = %zd\n", __func__, (int)pos, size);
+ 
+ 	if (pos == 0) {
+ 		bytes_read = ibm_get_table_from_acpi(&table);
+@@ -402,7 +402,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
+ 	status = acpi_get_object_info(handle, &info_buffer);
+ 	if (ACPI_FAILURE(status)) {
+ 		err("%s:  Failed to get device information status=0x%x\n",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		return retval;
+ 	}
+ 	info = info_buffer.pointer;
+@@ -432,18 +432,18 @@ static int __init ibm_acpiphp_init(void)
+ 	struct acpi_device *device;
+ 	struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
+ 
+-	dbg("%s\n", __FUNCTION__);
++	dbg("%s\n", __func__);
+ 
+ 	if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ 			ACPI_UINT32_MAX, ibm_find_acpi_device,
+ 			&ibm_acpi_handle, NULL) != FOUND_APCI) {
+-		err("%s: acpi_walk_namespace failed\n", __FUNCTION__);
++		err("%s: acpi_walk_namespace failed\n", __func__);
+ 		retval = -ENODEV;
+ 		goto init_return;
+ 	}
+-	dbg("%s: found IBM aPCI device\n", __FUNCTION__);
++	dbg("%s: found IBM aPCI device\n", __func__);
+ 	if (acpi_bus_get_device(ibm_acpi_handle, &device)) {
+-		err("%s: acpi_bus_get_device failed\n", __FUNCTION__);
++		err("%s: acpi_bus_get_device failed\n", __func__);
+ 		retval = -ENODEV;
+ 		goto init_return;
+ 	}
+@@ -458,7 +458,7 @@ static int __init ibm_acpiphp_init(void)
+ 			&ibm_note);
+ 	if (ACPI_FAILURE(status)) {
+ 		err("%s: Failed to register notification handler\n",
+-				__FUNCTION__);
++				__func__);
+ 		retval = -EBUSY;
+ 		goto init_cleanup;
+ 	}
+@@ -479,17 +479,17 @@ static void __exit ibm_acpiphp_exit(void)
+ 	acpi_status status;
+ 	struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
+ 
+-	dbg("%s\n", __FUNCTION__);
++	dbg("%s\n", __func__);
+ 
+ 	if (acpiphp_unregister_attention(&ibm_attention_info))
+-		err("%s: attention info deregistration failed", __FUNCTION__);
++		err("%s: attention info deregistration failed", __func__);
+ 
+ 	status = acpi_remove_notify_handler(
+ 			   ibm_acpi_handle,
+ 			   ACPI_DEVICE_NOTIFY,
+ 			   ibm_handle_events);
+ 	if (ACPI_FAILURE(status))
+-		err("%s: Notification handler removal failed\n", __FUNCTION__);
++		err("%s: Notification handler removal failed\n", __func__);
+ 	/* remove the /sys entries */
+ 	sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr);
+ }
+diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
+index ed4d44e..d8a6b80 100644
+--- a/drivers/pci/hotplug/cpci_hotplug_core.c
++++ b/drivers/pci/hotplug/cpci_hotplug_core.c
+@@ -108,7 +108,7 @@ enable_slot(struct hotplug_slot *hotplug_slot)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s", __func__, hotplug_slot->name);
+ 
+ 	if (controller->ops->set_power)
+ 		retval = controller->ops->set_power(slot, 1);
+@@ -121,25 +121,25 @@ disable_slot(struct hotplug_slot *hotplug_slot)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s", __func__, hotplug_slot->name);
+ 
+ 	down_write(&list_rwsem);
+ 
+ 	/* Unconfigure device */
+ 	dbg("%s - unconfiguring slot %s",
+-	    __FUNCTION__, slot->hotplug_slot->name);
++	    __func__, slot->hotplug_slot->name);
+ 	if ((retval = cpci_unconfigure_slot(slot))) {
+ 		err("%s - could not unconfigure slot %s",
+-		    __FUNCTION__, slot->hotplug_slot->name);
++		    __func__, slot->hotplug_slot->name);
+ 		goto disable_error;
+ 	}
+ 	dbg("%s - finished unconfiguring slot %s",
+-	    __FUNCTION__, slot->hotplug_slot->name);
++	    __func__, slot->hotplug_slot->name);
+ 
+ 	/* Clear EXT (by setting it) */
+ 	if (cpci_clear_ext(slot)) {
+ 		err("%s - could not clear EXT for slot %s",
+-		    __FUNCTION__, slot->hotplug_slot->name);
++		    __func__, slot->hotplug_slot->name);
+ 		retval = -ENODEV;
+ 		goto disable_error;
+ 	}
+@@ -372,7 +372,7 @@ init_slots(int clear_ins)
+ 	struct slot *slot;
+ 	struct pci_dev* dev;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 	down_read(&list_rwsem);
+ 	if (!slots) {
+ 		up_read(&list_rwsem);
+@@ -380,10 +380,10 @@ init_slots(int clear_ins)
+ 	}
+ 	list_for_each_entry(slot, &slot_list, slot_list) {
+ 		dbg("%s - looking at slot %s",
+-		    __FUNCTION__, slot->hotplug_slot->name);
++		    __func__, slot->hotplug_slot->name);
+ 		if (clear_ins && cpci_check_and_clear_ins(slot))
+ 			dbg("%s - cleared INS for slot %s",
+-			    __FUNCTION__, slot->hotplug_slot->name);
++			    __func__, slot->hotplug_slot->name);
+ 		dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0));
+ 		if (dev) {
+ 			if (update_adapter_status(slot->hotplug_slot, 1))
+@@ -394,7 +394,7 @@ init_slots(int clear_ins)
+ 		}
+ 	}
+ 	up_read(&list_rwsem);
+-	dbg("%s - exit", __FUNCTION__);
++	dbg("%s - exit", __func__);
+ 	return 0;
+ }
+ 
+@@ -415,7 +415,7 @@ check_slots(void)
+ 	extracted = inserted = 0;
+ 	list_for_each_entry(slot, &slot_list, slot_list) {
+ 		dbg("%s - looking at slot %s",
+-		    __FUNCTION__, slot->hotplug_slot->name);
++		    __func__, slot->hotplug_slot->name);
+ 		if (cpci_check_and_clear_ins(slot)) {
+ 			/*
+ 			 * Some broken hardware (e.g. PLX 9054AB) asserts
+@@ -430,28 +430,28 @@ check_slots(void)
+ 
+ 			/* Process insertion */
+ 			dbg("%s - slot %s inserted",
+-			    __FUNCTION__, slot->hotplug_slot->name);
++			    __func__, slot->hotplug_slot->name);
+ 
+ 			/* GSM, debug */
+ 			hs_csr = cpci_get_hs_csr(slot);
+ 			dbg("%s - slot %s HS_CSR (1) = %04x",
+-			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
++			    __func__, slot->hotplug_slot->name, hs_csr);
+ 
+ 			/* Configure device */
+ 			dbg("%s - configuring slot %s",
+-			    __FUNCTION__, slot->hotplug_slot->name);
++			    __func__, slot->hotplug_slot->name);
+ 			if (cpci_configure_slot(slot)) {
+ 				err("%s - could not configure slot %s",
+-				    __FUNCTION__, slot->hotplug_slot->name);
++				    __func__, slot->hotplug_slot->name);
+ 				continue;
+ 			}
+ 			dbg("%s - finished configuring slot %s",
+-			    __FUNCTION__, slot->hotplug_slot->name);
++			    __func__, slot->hotplug_slot->name);
+ 
+ 			/* GSM, debug */
+ 			hs_csr = cpci_get_hs_csr(slot);
+ 			dbg("%s - slot %s HS_CSR (2) = %04x",
+-			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
++			    __func__, slot->hotplug_slot->name, hs_csr);
+ 
+ 			if (update_latch_status(slot->hotplug_slot, 1))
+ 				warn("failure to update latch file");
+@@ -464,18 +464,18 @@ check_slots(void)
+ 			/* GSM, debug */
+ 			hs_csr = cpci_get_hs_csr(slot);
+ 			dbg("%s - slot %s HS_CSR (3) = %04x",
+-			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
++			    __func__, slot->hotplug_slot->name, hs_csr);
+ 
+ 			inserted++;
+ 		} else if (cpci_check_ext(slot)) {
+ 			/* Process extraction request */
+ 			dbg("%s - slot %s extracted",
+-			    __FUNCTION__, slot->hotplug_slot->name);
++			    __func__, slot->hotplug_slot->name);
+ 
+ 			/* GSM, debug */
+ 			hs_csr = cpci_get_hs_csr(slot);
+ 			dbg("%s - slot %s HS_CSR = %04x",
+-			    __FUNCTION__, slot->hotplug_slot->name, hs_csr);
++			    __func__, slot->hotplug_slot->name, hs_csr);
+ 
+ 			if (!slot->extracting) {
+ 				if (update_latch_status(slot->hotplug_slot, 0)) {
+@@ -519,7 +519,7 @@ event_thread(void *data)
+ {
+ 	int rc;
+ 
+-	dbg("%s - event thread started", __FUNCTION__);
++	dbg("%s - event thread started", __func__);
+ 	while (1) {
+ 		dbg("event thread sleeping");
+ 		set_current_state(TASK_INTERRUPTIBLE);
+@@ -532,7 +532,7 @@ event_thread(void *data)
+ 				/* Give userspace a chance to handle extraction */
+ 				msleep(500);
+ 			} else if (rc < 0) {
+-				dbg("%s - error checking slots", __FUNCTION__);
++				dbg("%s - error checking slots", __func__);
+ 				thread_finished = 1;
+ 				goto out;
+ 			}
+@@ -541,7 +541,7 @@ event_thread(void *data)
+ 			break;
+ 
+ 		/* Re-enable ENUM# interrupt */
+-		dbg("%s - re-enabling irq", __FUNCTION__);
++		dbg("%s - re-enabling irq", __func__);
+ 		controller->ops->enable_irq();
+ 	}
+  out:
+@@ -564,7 +564,7 @@ poll_thread(void *data)
+ 					/* Give userspace a chance to handle extraction */
+ 					msleep(500);
+ 				} else if (rc < 0) {
+-					dbg("%s - error checking slots", __FUNCTION__);
++					dbg("%s - error checking slots", __func__);
+ 					thread_finished = 1;
+ 					goto out;
+ 				}
+@@ -621,7 +621,7 @@ cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
+ 			status = -ENODEV;
+ 		}
+ 		dbg("%s - acquired controller irq %d",
+-		    __FUNCTION__, new_controller->irq);
++		    __func__, new_controller->irq);
+ 	}
+ 	if (!status)
+ 		controller = new_controller;
+@@ -673,7 +673,7 @@ cpci_hp_start(void)
+ 	static int first = 1;
+ 	int status;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 	if (!controller)
+ 		return -ENODEV;
+ 
+@@ -693,14 +693,14 @@ cpci_hp_start(void)
+ 	status = cpci_start_thread();
+ 	if (status)
+ 		return status;
+-	dbg("%s - thread started", __FUNCTION__);
++	dbg("%s - thread started", __func__);
+ 
+ 	if (controller->irq) {
+ 		/* Start enum interrupt processing */
+-		dbg("%s - enabling irq", __FUNCTION__);
++		dbg("%s - enabling irq", __func__);
+ 		controller->ops->enable_irq();
+ 	}
+-	dbg("%s - exit", __FUNCTION__);
++	dbg("%s - exit", __func__);
+ 	return 0;
+ }
+ 
+@@ -711,7 +711,7 @@ cpci_hp_stop(void)
+ 		return -ENODEV;
+ 	if (controller->irq) {
+ 		/* Stop enum interrupt processing */
+-		dbg("%s - disabling irq", __FUNCTION__);
++		dbg("%s - disabling irq", __func__);
+ 		controller->ops->disable_irq();
+ 	}
+ 	cpci_stop_thread();
+diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
+index b3515fc..df82b95 100644
+--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
++++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
+@@ -255,7 +255,7 @@ int __ref cpci_configure_slot(struct slot *slot)
+ 	struct pci_bus *parent;
+ 	int fn;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	if (slot->dev == NULL) {
+ 		dbg("pci_dev null, finding %02x:%02x:%x",
+@@ -273,7 +273,7 @@ int __ref cpci_configure_slot(struct slot *slot)
+ 		 * we will only call this case when lookup fails.
+ 		 */
+ 		n = pci_scan_slot(slot->bus, slot->devfn);
+-		dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
++		dbg("%s: pci_scan_slot returned %d", __func__, n);
+ 		slot->dev = pci_get_slot(slot->bus, slot->devfn);
+ 		if (slot->dev == NULL) {
+ 			err("Could not find PCI device for slot %02x", slot->number);
+@@ -322,7 +322,7 @@ int __ref cpci_configure_slot(struct slot *slot)
+ 	pci_bus_add_devices(parent);
+ 	pci_enable_bridges(parent);
+ 
+-	dbg("%s - exit", __FUNCTION__);
++	dbg("%s - exit", __func__);
+ 	return 0;
+ }
+ 
+@@ -331,7 +331,7 @@ int cpci_unconfigure_slot(struct slot* slot)
+ 	int i;
+ 	struct pci_dev *dev;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 	if (!slot->dev) {
+ 		err("No device for slot %02x\n", slot->number);
+ 		return -ENODEV;
+@@ -348,6 +348,6 @@ int cpci_unconfigure_slot(struct slot* slot)
+ 	pci_dev_put(slot->dev);
+ 	slot->dev = NULL;
+ 
+-	dbg("%s - exit", __FUNCTION__);
++	dbg("%s - exit", __func__);
+ 	return 0;
+ }
+diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c
+index f3852a6..148fb46 100644
+--- a/drivers/pci/hotplug/cpcihp_generic.c
++++ b/drivers/pci/hotplug/cpcihp_generic.c
+@@ -154,12 +154,18 @@ static int __init cpcihp_generic_init(void)
+ 	if(!r)
+ 		return -EBUSY;
+ 
+-	dev = pci_find_slot(bridge_busnr, PCI_DEVFN(bridge_slot, 0));
++	bus = pci_find_bus(0, bridge_busnr);
++	if (!bus) {
++		err("Invalid bus number %d", bridge_busnr);
++		return -EINVAL;
++	}
++	dev = pci_get_slot(bus, PCI_DEVFN(bridge_slot, 0));
+ 	if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+ 		err("Invalid bridge device %s", bridge);
+ 		return -EINVAL;
+ 	}
+ 	bus = dev->subordinate;
++	pci_dev_put(dev);
+ 
+ 	memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller));
+ 	generic_hpc_ops.query_enum = query_enum;
+diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
+index 298ad7f..b1decfa 100644
+--- a/drivers/pci/hotplug/cpqphp.h
++++ b/drivers/pci/hotplug/cpqphp.h
+@@ -674,7 +674,7 @@ static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slo
+ 
+ 	hp_slot = slot->device - ctrl->slot_device_offset;
+ 	dbg("%s: slot->device = %d, ctrl->slot_device_offset = %d \n",
+-	    __FUNCTION__, slot->device, ctrl->slot_device_offset);
++	    __func__, slot->device, ctrl->slot_device_offset);
+ 
+ 	status = (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot));
+ 
+@@ -709,7 +709,7 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
+         DECLARE_WAITQUEUE(wait, current);
+ 	int retval = 0;
+ 
+-	dbg("%s - start\n", __FUNCTION__);
++	dbg("%s - start\n", __func__);
+ 	add_wait_queue(&ctrl->queue, &wait);
+ 	/* Sleep for up to 1 second to wait for the LED to change. */
+ 	msleep_interruptible(1000);
+@@ -717,7 +717,7 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
+ 	if (signal_pending(current))
+ 		retval =  -EINTR;
+ 
+-	dbg("%s - end\n", __FUNCTION__);
++	dbg("%s - end\n", __func__);
+ 	return retval;
+ }
+ 
+diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
+index 7417887..36b115b 100644
+--- a/drivers/pci/hotplug/cpqphp_core.c
++++ b/drivers/pci/hotplug/cpqphp_core.c
+@@ -315,7 +315,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	kfree(slot->hotplug_slot->info);
+ 	kfree(slot->hotplug_slot->name);
+@@ -338,7 +338,7 @@ static int ctrl_slot_setup(struct controller *ctrl,
+ 	void __iomem *slot_entry= NULL;
+ 	int result = -ENOMEM;
+ 
+-	dbg("%s\n", __FUNCTION__);
++	dbg("%s\n", __func__);
+ 
+ 	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+ 
+@@ -513,7 +513,7 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
+ 
+ 	u8 tbus, tdevice, tslot, bridgeSlot;
+ 
+-	dbg("%s: %p, %d, %d, %p\n", __FUNCTION__, bus, bus_num, dev_num, slot);
++	dbg("%s: %p, %d, %d, %p\n", __func__, bus, bus_num, dev_num, slot);
+ 
+ 	bridgeSlot = 0xFF;
+ 
+@@ -636,7 +636,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+ 	u8 device;
+ 	u8 function;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+ 		return -ENODEV;
+@@ -663,7 +663,7 @@ static int process_SI(struct hotplug_slot *hotplug_slot)
+ 	u8 device;
+ 	u8 function;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+ 		return -ENODEV;
+@@ -695,7 +695,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot)
+ 	u8 device;
+ 	u8 function;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+ 		return -ENODEV;
+@@ -708,7 +708,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot)
+ 	if (!slot_func)
+ 		return -ENODEV;
+ 
+-	dbg("In %s, slot_func = %p, ctrl = %p\n", __FUNCTION__, slot_func, ctrl);
++	dbg("In %s, slot_func = %p, ctrl = %p\n", __func__, slot_func, ctrl);
+ 	return cpqhp_process_SS(ctrl, slot_func);
+ }
+ 
+@@ -718,7 +718,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	struct controller *ctrl = slot->ctrl;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	return cpqhp_hardware_test(ctrl, value);	
+ }
+@@ -729,7 +729,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	struct controller *ctrl = slot->ctrl;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = get_slot_enabled(ctrl, slot);
+ 	return 0;
+@@ -740,7 +740,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	struct controller *ctrl = slot->ctrl;
+ 	
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = cpq_get_attention_status(ctrl, slot);
+ 	return 0;
+@@ -751,7 +751,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	struct controller *ctrl = slot->ctrl;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = cpq_get_latch_status(ctrl, slot);
+ 
+@@ -763,7 +763,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	struct controller *ctrl = slot->ctrl;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = get_presence_status(ctrl, slot);
+ 
+@@ -775,7 +775,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
+ 	struct slot *slot = hotplug_slot->private;
+ 	struct controller *ctrl = slot->ctrl;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = ctrl->speed_capability;
+ 
+@@ -787,7 +787,7 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
+ 	struct slot *slot = hotplug_slot->private;
+ 	struct controller *ctrl = slot->ctrl;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = ctrl->speed;
+ 
+@@ -841,7 +841,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		// TODO: This code can be made to support non-Compaq or Intel subsystem IDs
+ 		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
+ 		if (rc) {
+-			err("%s : pci_read_config_word failed\n", __FUNCTION__);
++			err("%s : pci_read_config_word failed\n", __func__);
+ 			goto err_disable_device;
+ 		}
+ 		dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
+@@ -853,14 +853,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 		ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
+ 		if (!ctrl) {
+-			err("%s : out of memory\n", __FUNCTION__);
++			err("%s : out of memory\n", __func__);
+ 			rc = -ENOMEM;
+ 			goto err_disable_device;
+ 		}
+ 
+ 		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
+ 		if (rc) {
+-			err("%s : pci_read_config_word failed\n", __FUNCTION__);
++			err("%s : pci_read_config_word failed\n", __func__);
+ 			goto err_free_ctrl;
+ 		}
+ 
+@@ -1142,7 +1142,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK));
+ 	if (rc) {
+ 		err("%s: unable to save PCI configuration data, error %d\n",
+-				__FUNCTION__, rc);
++				__func__, rc);
+ 		goto err_iounmap;
+ 	}
+ 
+@@ -1180,7 +1180,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	if (rc) {
+ 		err(msg_initialization_err, 6);
+ 		err("%s: unable to save PCI configuration data, error %d\n",
+-			__FUNCTION__, rc);
++			__func__, rc);
+ 		goto err_iounmap;
+ 	}
+ 	
+diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
+index 4018420..ef041ca 100644
+--- a/drivers/pci/hotplug/cpqphp_ctrl.c
++++ b/drivers/pci/hotplug/cpqphp_ctrl.c
+@@ -737,12 +737,12 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
+ 
+ 	for (node = *head; node; node = node->next) {
+ 		dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",
+-		    __FUNCTION__, size, node, node->base, node->length);
++		    __func__, size, node, node->base, node->length);
+ 		if (node->length < size)
+ 			continue;
+ 
+ 		if (node->base & (size - 1)) {
+-			dbg("%s: not aligned\n", __FUNCTION__);
++			dbg("%s: not aligned\n", __func__);
+ 			/* this one isn't base aligned properly
+ 			 * so we'll make a new entry and split it up */
+ 			temp_dword = (node->base | (size-1)) + 1;
+@@ -767,7 +767,7 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
+ 
+ 		/* Don't need to check if too small since we already did */
+ 		if (node->length > size) {
+-			dbg("%s: too big\n", __FUNCTION__);
++			dbg("%s: too big\n", __func__);
+ 			/* this one is longer than we need
+ 			 * so we'll make a new entry and split it up */
+ 			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
+@@ -784,7 +784,7 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
+ 			node->next = split_node;
+ 		}  /* End of too big on top end */
+ 
+-		dbg("%s: got one!!!\n", __FUNCTION__);
++		dbg("%s: got one!!!\n", __func__);
+ 		/* If we got here, then it is the right size
+ 		 * Now take it out of the list */
+ 		if (*head == node) {
+@@ -819,7 +819,7 @@ int cpqhp_resource_sort_and_combine(struct pci_resource **head)
+ 	struct pci_resource *node2;
+ 	int out_of_order = 1;
+ 
+-	dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
++	dbg("%s: head = %p, *head = %p\n", __func__, head, *head);
+ 
+ 	if (!(*head))
+ 		return 1;
+@@ -907,7 +907,7 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)
+ 		/* Read to clear posted writes */
+ 		misc = readw(ctrl->hpc_reg + MISC);
+ 
+-		dbg ("%s - waking up\n", __FUNCTION__);
++		dbg ("%s - waking up\n", __func__);
+ 		wake_up_interruptible(&ctrl->queue);
+ 	}
+ 
+@@ -1421,7 +1421,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
+ 
+ 	hp_slot = func->device - ctrl->slot_device_offset;
+ 	dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
+-	    __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
++	    __func__, func->device, ctrl->slot_device_offset, hp_slot);
+ 
+ 	mutex_lock(&ctrl->crit_sect);
+ 
+@@ -1466,55 +1466,55 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
+ 
+ 	/* turn on board and blink green LED */
+ 
+-	dbg("%s: before down\n", __FUNCTION__);
++	dbg("%s: before down\n", __func__);
+ 	mutex_lock(&ctrl->crit_sect);
+-	dbg("%s: after down\n", __FUNCTION__);
++	dbg("%s: after down\n", __func__);
+ 
+-	dbg("%s: before slot_enable\n", __FUNCTION__);
++	dbg("%s: before slot_enable\n", __func__);
+ 	slot_enable (ctrl, hp_slot);
+ 
+-	dbg("%s: before green_LED_blink\n", __FUNCTION__);
++	dbg("%s: before green_LED_blink\n", __func__);
+ 	green_LED_blink (ctrl, hp_slot);
+ 
+-	dbg("%s: before amber_LED_blink\n", __FUNCTION__);
++	dbg("%s: before amber_LED_blink\n", __func__);
+ 	amber_LED_off (ctrl, hp_slot);
+ 
+-	dbg("%s: before set_SOGO\n", __FUNCTION__);
++	dbg("%s: before set_SOGO\n", __func__);
+ 	set_SOGO(ctrl);
+ 
+ 	/* Wait for SOBS to be unset */
+-	dbg("%s: before wait_for_ctrl_irq\n", __FUNCTION__);
++	dbg("%s: before wait_for_ctrl_irq\n", __func__);
+ 	wait_for_ctrl_irq (ctrl);
+-	dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__);
++	dbg("%s: after wait_for_ctrl_irq\n", __func__);
+ 
+-	dbg("%s: before up\n", __FUNCTION__);
++	dbg("%s: before up\n", __func__);
+ 	mutex_unlock(&ctrl->crit_sect);
+-	dbg("%s: after up\n", __FUNCTION__);
++	dbg("%s: after up\n", __func__);
+ 
+ 	/* Wait for ~1 second because of hot plug spec */
+-	dbg("%s: before long_delay\n", __FUNCTION__);
++	dbg("%s: before long_delay\n", __func__);
+ 	long_delay(1*HZ);
+-	dbg("%s: after long_delay\n", __FUNCTION__);
++	dbg("%s: after long_delay\n", __func__);
+ 
+-	dbg("%s: func status = %x\n", __FUNCTION__, func->status);
++	dbg("%s: func status = %x\n", __func__, func->status);
+ 	/* Check for a power fault */
+ 	if (func->status == 0xFF) {
+ 		/* power fault occurred, but it was benign */
+ 		temp_register = 0xFFFFFFFF;
+-		dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
++		dbg("%s: temp register set to %x by power fault\n", __func__, temp_register);
+ 		rc = POWER_FAILURE;
+ 		func->status = 0;
+ 	} else {
+ 		/* Get vendor/device ID u32 */
+ 		ctrl->pci_bus->number = func->bus;
+ 		rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register);
+-		dbg("%s: pci_read_config_dword returns %d\n", __FUNCTION__, rc);
+-		dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
++		dbg("%s: pci_read_config_dword returns %d\n", __func__, rc);
++		dbg("%s: temp_register is %x\n", __func__, temp_register);
+ 
+ 		if (rc != 0) {
+ 			/* Something's wrong here */
+ 			temp_register = 0xFFFFFFFF;
+-			dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
++			dbg("%s: temp register set to %x by error\n", __func__, temp_register);
+ 		}
+ 		/* Preset return code.  It will be changed later if things go okay. */
+ 		rc = NO_ADAPTER_PRESENT;
+@@ -1530,7 +1530,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
+ 
+ 		rc = configure_new_device(ctrl, func, 0, &res_lists);
+ 
+-		dbg("%s: back from configure_new_device\n", __FUNCTION__);
++		dbg("%s: back from configure_new_device\n", __func__);
+ 		ctrl->io_head = res_lists.io_head;
+ 		ctrl->mem_head = res_lists.mem_head;
+ 		ctrl->p_mem_head = res_lists.p_mem_head;
+@@ -1566,7 +1566,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
+ 
+ 		/* next, we will instantiate the linux pci_dev structures (with
+ 		 * appropriate driver notification, if already present) */
+-		dbg("%s: configure linux pci_dev structure\n", __FUNCTION__);
++		dbg("%s: configure linux pci_dev structure\n", __func__);
+ 		index = 0;
+ 		do {
+ 			new_slot = cpqhp_slot_find(ctrl->bus, func->device, index++);
+@@ -1628,7 +1628,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control
+ 	device = func->device;
+ 
+ 	hp_slot = func->device - ctrl->slot_device_offset;
+-	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
++	dbg("In %s, hp_slot = %d\n", __func__, hp_slot);
+ 
+ 	/* When we get here, it is safe to change base address registers.
+ 	 * We will attempt to save the base address register lengths */
+@@ -1928,7 +1928,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
+ 		func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
+ 		dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl);
+ 		if (!func) {
+-			dbg("Error! func NULL in %s\n", __FUNCTION__);
++			dbg("Error! func NULL in %s\n", __func__);
+ 			return ;
+ 		}
+ 
+@@ -1950,7 +1950,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
+ 		func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
+ 		dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl);
+ 		if (!func) {
+-			dbg("Error! func NULL in %s\n", __FUNCTION__);
++			dbg("Error! func NULL in %s\n", __func__);
+ 			return ;
+ 		}
+ 
+@@ -2058,7 +2058,7 @@ int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func)
+ 	}
+ 
+ 	if (rc) {
+-		dbg("%s: rc = %d\n", __FUNCTION__, rc);
++		dbg("%s: rc = %d\n", __func__, rc);
+ 	}
+ 
+ 	if (p_slot)
+@@ -2269,12 +2269,12 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func
+ 
+ 	new_slot = func;
+ 
+-	dbg("%s\n", __FUNCTION__);
++	dbg("%s\n", __func__);
+ 	/* Check for Multi-function device */
+ 	ctrl->pci_bus->number = func->bus;
+ 	rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
+ 	if (rc) {
+-		dbg("%s: rc = %d\n", __FUNCTION__, rc);
++		dbg("%s: rc = %d\n", __func__, rc);
+ 		return rc;
+ 	}
+ 
+diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c
+index ae5e974..cb17488 100644
+--- a/drivers/pci/hotplug/cpqphp_nvram.c
++++ b/drivers/pci/hotplug/cpqphp_nvram.c
+@@ -160,7 +160,7 @@ static int check_for_compaq_ROM (void __iomem *rom_start)
+ 	    (temp6 == 'Q')) {
+ 		result = 1;
+ 	}
+-	dbg ("%s - returned %d\n", __FUNCTION__, result);
++	dbg ("%s - returned %d\n", __func__, result);
+ 	return result;
+ }
+ 
+diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
+index 3f6cd20..0902193 100644
+--- a/drivers/pci/hotplug/cpqphp_pci.c
++++ b/drivers/pci/hotplug/cpqphp_pci.c
+@@ -120,7 +120,7 @@ int cpqhp_unconfigure_device(struct pci_func* func)
+ {
+ 	int j;
+ 	
+-	dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function);
++	dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function);
+ 
+ 	for (j=0; j<8 ; j++) {
+ 		struct pci_dev* temp = pci_find_slot(func->bus, PCI_DEVFN(func->device, j));
+@@ -170,11 +170,11 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
+ 		fakedev->bus = fakebus;
+ 		fakebus->number = bus_num;
+ 		dbg("%s: dev %d, bus %d, pin %d, num %d\n",
+-		    __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
++		    __func__, dev_num, bus_num, int_pin, irq_num);
+ 		rc = pcibios_set_irq_routing(fakedev, int_pin - 0x0a, irq_num);
+ 		kfree(fakedev);
+ 		kfree(fakebus);
+-		dbg("%s: rc %d\n", __FUNCTION__, rc);
++		dbg("%s: rc %d\n", __func__, rc);
+ 		if (!rc)
+ 			return !rc;
+ 
+@@ -1423,7 +1423,7 @@ int cpqhp_return_board_resources(struct pci_func * func, struct resource_lists *
+ 	int rc = 0;
+ 	struct pci_resource *node;
+ 	struct pci_resource *t_node;
+-	dbg("%s\n", __FUNCTION__);
++	dbg("%s\n", __func__);
+ 
+ 	if (!func)
+ 		return 1;
+diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
+index 94b6401..7e9a827 100644
+--- a/drivers/pci/hotplug/fakephp.c
++++ b/drivers/pci/hotplug/fakephp.c
+@@ -293,7 +293,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ 	/* mis-use enable_slot for rescanning of the pci bus */
+ 	cancel_work_sync(&pci_rescan_work);
+ 	queue_work(dummyphp_wq, &pci_rescan_work);
+-	return -ENODEV;
++	return 0;
+ }
+ 
+ /* find the hotplug_slot for the pci_dev */
+@@ -320,7 +320,7 @@ static int disable_slot(struct hotplug_slot *slot)
+ 		return -ENODEV;
+ 	dslot = slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, slot->name);
+ 
+ 	/* don't disable bridged devices just yet, we can't handle them easily... */
+ 	if (dslot->dev->subordinate) {
+diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
+index 87b6b8b..c892daa 100644
+--- a/drivers/pci/hotplug/ibmphp_core.c
++++ b/drivers/pci/hotplug/ibmphp_core.c
+@@ -148,8 +148,10 @@ int ibmphp_init_devno(struct slot **cur_slot)
+ 	len = (rtable->size - sizeof(struct irq_routing_table)) /
+ 			sizeof(struct irq_info);
+ 
+-	if (!len)
++	if (!len) {
++		kfree(rtable);
+ 		return -1;
++	}
+ 	for (loop = 0; loop < len; loop++) {
+ 		if ((*cur_slot)->number == rtable->slots[loop].slot) {
+ 		if ((*cur_slot)->bus == rtable->slots[loop].bus) {
+@@ -187,11 +189,13 @@ int ibmphp_init_devno(struct slot **cur_slot)
+ 				debug("rtable->slots[loop].irq[3].link = %x\n",
+ 					rtable->slots[loop].irq[3].link);
+ 				debug("end of init_devno\n");
++				kfree(rtable);
+ 				return 0;
+ 			}
+ 		}
+ 	}
+ 
++	kfree(rtable);
+ 	return -1;
+ }
+ 
+@@ -395,7 +399,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ 	struct slot *pslot;
+ 	u8 mode = 0;
+ 
+-	debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
++	debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__,
+ 		hotplug_slot, value);
+ 
+ 	ibmphp_lock_operations();
+@@ -425,7 +429,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ 	}
+ 
+ 	ibmphp_unlock_operations();
+-	debug("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
++	debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value);
+ 	return rc;
+ }
+ 
+@@ -435,7 +439,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ 	struct slot *pslot;
+ 	u8 mode = 0;
+ 
+-	debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
++	debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__,
+ 		hotplug_slot, value);
+ 
+ 	ibmphp_lock_operations();
+@@ -471,7 +475,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ 	}
+ 
+ 	ibmphp_unlock_operations();
+-	debug("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
++	debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value);
+ 	return rc;
+ }
+ 
+@@ -741,13 +745,13 @@ static void free_slots(void)
+ 	struct list_head * tmp;
+ 	struct list_head * next;
+ 
+-	debug("%s -- enter\n", __FUNCTION__);
++	debug("%s -- enter\n", __func__);
+ 
+ 	list_for_each_safe(tmp, next, &ibmphp_slot_head) {
+ 		slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
+ 		pci_hp_deregister(slot_cur->hotplug_slot);
+ 	}
+-	debug("%s -- exit\n", __FUNCTION__);
++	debug("%s -- exit\n", __func__);
+ }
+ 
+ static void ibm_unconfigure_device(struct pci_func *func)
+@@ -755,7 +759,7 @@ static void ibm_unconfigure_device(struct pci_func *func)
+ 	struct pci_dev *temp;
+ 	u8 j;
+ 
+-	debug("inside %s\n", __FUNCTION__);
++	debug("inside %s\n", __func__);
+ 	debug("func->device = %x, func->function = %x\n",
+ 					func->device, func->function);
+ 	debug("func->device << 3 | 0x0  = %x\n", func->device << 3 | 0x0);
+@@ -786,13 +790,13 @@ static u8 bus_structure_fixup(u8 busno)
+ 
+ 	bus = kmalloc(sizeof(*bus), GFP_KERNEL);
+ 	if (!bus) {
+-		err("%s - out of memory\n", __FUNCTION__);
++		err("%s - out of memory\n", __func__);
+ 		return 1;
+ 	}
+ 	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ 	if (!dev) {
+ 		kfree(bus);
+-		err("%s - out of memory\n", __FUNCTION__);
++		err("%s - out of memory\n", __func__);
+ 		return 1;
+ 	}
+ 
+@@ -803,7 +807,7 @@ static u8 bus_structure_fixup(u8 busno)
+ 		if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&
+ 					(l != 0x0000) && (l != 0xffff)) {
+ 			debug("%s - Inside bus_struture_fixup()\n",
+-							__FUNCTION__);
++							__func__);
+ 			pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
+ 			break;
+ 		}
+@@ -900,7 +904,7 @@ static int set_bus(struct slot * slot_cur)
+ 	        { },
+ 	};	
+ 
+-	debug("%s - entry slot # %d\n", __FUNCTION__, slot_cur->number);
++	debug("%s - entry slot # %d\n", __func__, slot_cur->number);
+ 	if (SET_BUS_STATUS(slot_cur->ctrl) && is_bus_empty(slot_cur)) {
+ 		rc = slot_update(&slot_cur);
+ 		if (rc)
+@@ -975,7 +979,7 @@ static int set_bus(struct slot * slot_cur)
+ 	/* This is for x440, once Brandon fixes the firmware, 
+ 	will not need this delay */
+ 	msleep(1000);
+-	debug("%s -Exit\n", __FUNCTION__);
++	debug("%s -Exit\n", __func__);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
+index bbccde9..dca7efc 100644
+--- a/drivers/pci/hotplug/ibmphp_ebda.c
++++ b/drivers/pci/hotplug/ibmphp_ebda.c
+@@ -127,18 +127,18 @@ static void __init print_bus_info (void)
+ 	
+ 	list_for_each (ptr1, &bus_info_head) {
+ 		ptr = list_entry (ptr1, struct bus_info, bus_info_list);
+-		debug ("%s - slot_min = %x\n", __FUNCTION__, ptr->slot_min);
+-		debug ("%s - slot_max = %x\n", __FUNCTION__, ptr->slot_max);
+-		debug ("%s - slot_count = %x\n", __FUNCTION__, ptr->slot_count);
+-		debug ("%s - bus# = %x\n", __FUNCTION__, ptr->busno);
+-		debug ("%s - current_speed = %x\n", __FUNCTION__, ptr->current_speed);
+-		debug ("%s - controller_id = %x\n", __FUNCTION__, ptr->controller_id);
++		debug ("%s - slot_min = %x\n", __func__, ptr->slot_min);
++		debug ("%s - slot_max = %x\n", __func__, ptr->slot_max);
++		debug ("%s - slot_count = %x\n", __func__, ptr->slot_count);
++		debug ("%s - bus# = %x\n", __func__, ptr->busno);
++		debug ("%s - current_speed = %x\n", __func__, ptr->current_speed);
++		debug ("%s - controller_id = %x\n", __func__, ptr->controller_id);
+ 		
+-		debug ("%s - slots_at_33_conv = %x\n", __FUNCTION__, ptr->slots_at_33_conv);
+-		debug ("%s - slots_at_66_conv = %x\n", __FUNCTION__, ptr->slots_at_66_conv);
+-		debug ("%s - slots_at_66_pcix = %x\n", __FUNCTION__, ptr->slots_at_66_pcix);
+-		debug ("%s - slots_at_100_pcix = %x\n", __FUNCTION__, ptr->slots_at_100_pcix);
+-		debug ("%s - slots_at_133_pcix = %x\n", __FUNCTION__, ptr->slots_at_133_pcix);
++		debug ("%s - slots_at_33_conv = %x\n", __func__, ptr->slots_at_33_conv);
++		debug ("%s - slots_at_66_conv = %x\n", __func__, ptr->slots_at_66_conv);
++		debug ("%s - slots_at_66_pcix = %x\n", __func__, ptr->slots_at_66_pcix);
++		debug ("%s - slots_at_100_pcix = %x\n", __func__, ptr->slots_at_100_pcix);
++		debug ("%s - slots_at_133_pcix = %x\n", __func__, ptr->slots_at_133_pcix);
+ 
+ 	}
+ }
+@@ -150,12 +150,12 @@ static void print_lo_info (void)
+ 	debug ("print_lo_info ----\n");	
+ 	list_for_each (ptr1, &rio_lo_head) {
+ 		ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
+-		debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id);
+-		debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type);
+-		debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id);
+-		debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num);
+-		debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex);
+-		debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num);
++		debug ("%s - rio_node_id = %x\n", __func__, ptr->rio_node_id);
++		debug ("%s - rio_type = %x\n", __func__, ptr->rio_type);
++		debug ("%s - owner_id = %x\n", __func__, ptr->owner_id);
++		debug ("%s - first_slot_num = %x\n", __func__, ptr->first_slot_num);
++		debug ("%s - wpindex = %x\n", __func__, ptr->wpindex);
++		debug ("%s - chassis_num = %x\n", __func__, ptr->chassis_num);
+ 
+ 	}
+ }
+@@ -164,15 +164,15 @@ static void print_vg_info (void)
+ {
+ 	struct rio_detail *ptr;
+ 	struct list_head *ptr1;
+-	debug ("%s ---\n", __FUNCTION__);
++	debug ("%s ---\n", __func__);
+ 	list_for_each (ptr1, &rio_vg_head) {
+ 		ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
+-		debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id);
+-		debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type);
+-		debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id);
+-		debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num);
+-		debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex);
+-		debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num);
++		debug ("%s - rio_node_id = %x\n", __func__, ptr->rio_node_id);
++		debug ("%s - rio_type = %x\n", __func__, ptr->rio_type);
++		debug ("%s - owner_id = %x\n", __func__, ptr->owner_id);
++		debug ("%s - first_slot_num = %x\n", __func__, ptr->first_slot_num);
++		debug ("%s - wpindex = %x\n", __func__, ptr->wpindex);
++		debug ("%s - chassis_num = %x\n", __func__, ptr->chassis_num);
+ 
+ 	}
+ }
+@@ -185,7 +185,7 @@ static void __init print_ebda_pci_rsrc (void)
+ 	list_for_each (ptr1, &ibmphp_ebda_pci_rsrc_head) {
+ 		ptr = list_entry (ptr1, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
+ 		debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", 
+-			__FUNCTION__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr);
++			__func__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr);
+ 	}
+ }
+ 
+@@ -196,7 +196,7 @@ static void __init print_ibm_slot (void)
+ 
+ 	list_for_each (ptr1, &ibmphp_slot_head) {
+ 		ptr = list_entry (ptr1, struct slot, ibm_slot_list);
+-		debug ("%s - slot_number: %x\n", __FUNCTION__, ptr->number); 
++		debug ("%s - slot_number: %x\n", __func__, ptr->number);
+ 	}
+ }
+ 
+@@ -204,13 +204,13 @@ static void __init print_opt_vg (void)
+ {
+ 	struct opt_rio *ptr;
+ 	struct list_head *ptr1;
+-	debug ("%s ---\n", __FUNCTION__);
++	debug ("%s ---\n", __func__);
+ 	list_for_each (ptr1, &opt_vg_head) {
+ 		ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
+-		debug ("%s - rio_type %x\n", __FUNCTION__, ptr->rio_type); 
+-		debug ("%s - chassis_num: %x\n", __FUNCTION__, ptr->chassis_num); 
+-		debug ("%s - first_slot_num: %x\n", __FUNCTION__, ptr->first_slot_num); 
+-		debug ("%s - middle_num: %x\n", __FUNCTION__, ptr->middle_num); 
++		debug ("%s - rio_type %x\n", __func__, ptr->rio_type);
++		debug ("%s - chassis_num: %x\n", __func__, ptr->chassis_num);
++		debug ("%s - first_slot_num: %x\n", __func__, ptr->first_slot_num);
++		debug ("%s - middle_num: %x\n", __func__, ptr->middle_num);
+ 	}
+ }
+ 
+@@ -225,35 +225,35 @@ static void __init print_ebda_hpc (void)
+ 		hpc_ptr = list_entry (ptr1, struct controller, ebda_hpc_list); 
+ 
+ 		for (index = 0; index < hpc_ptr->slot_count; index++) {
+-			debug ("%s - physical slot#: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_num);
+-			debug ("%s - pci bus# of the slot: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_bus_num);
+-			debug ("%s - index into ctlr addr: %x\n", __FUNCTION__, hpc_ptr->slots[index].ctl_index);
+-			debug ("%s - cap of the slot: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_cap);
++			debug ("%s - physical slot#: %x\n", __func__, hpc_ptr->slots[index].slot_num);
++			debug ("%s - pci bus# of the slot: %x\n", __func__, hpc_ptr->slots[index].slot_bus_num);
++			debug ("%s - index into ctlr addr: %x\n", __func__, hpc_ptr->slots[index].ctl_index);
++			debug ("%s - cap of the slot: %x\n", __func__, hpc_ptr->slots[index].slot_cap);
+ 		}
+ 
+ 		for (index = 0; index < hpc_ptr->bus_count; index++) {
+-			debug ("%s - bus# of each bus controlled by this ctlr: %x\n", __FUNCTION__, hpc_ptr->buses[index].bus_num);
++			debug ("%s - bus# of each bus controlled by this ctlr: %x\n", __func__, hpc_ptr->buses[index].bus_num);
+ 		}
+ 
+-		debug ("%s - type of hpc: %x\n", __FUNCTION__, hpc_ptr->ctlr_type);
++		debug ("%s - type of hpc: %x\n", __func__, hpc_ptr->ctlr_type);
+ 		switch (hpc_ptr->ctlr_type) {
+ 		case 1:
+-			debug ("%s - bus: %x\n", __FUNCTION__, hpc_ptr->u.pci_ctlr.bus);
+-			debug ("%s - dev_fun: %x\n", __FUNCTION__, hpc_ptr->u.pci_ctlr.dev_fun);
+-			debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
++			debug ("%s - bus: %x\n", __func__, hpc_ptr->u.pci_ctlr.bus);
++			debug ("%s - dev_fun: %x\n", __func__, hpc_ptr->u.pci_ctlr.dev_fun);
++			debug ("%s - irq: %x\n", __func__, hpc_ptr->irq);
+ 			break;
+ 
+ 		case 0:
+-			debug ("%s - io_start: %x\n", __FUNCTION__, hpc_ptr->u.isa_ctlr.io_start);
+-			debug ("%s - io_end: %x\n", __FUNCTION__, hpc_ptr->u.isa_ctlr.io_end);
+-			debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
++			debug ("%s - io_start: %x\n", __func__, hpc_ptr->u.isa_ctlr.io_start);
++			debug ("%s - io_end: %x\n", __func__, hpc_ptr->u.isa_ctlr.io_end);
++			debug ("%s - irq: %x\n", __func__, hpc_ptr->irq);
+ 			break;
+ 
+ 		case 2:
+ 		case 4:
+-			debug ("%s - wpegbbar: %lx\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.wpegbbar);
+-			debug ("%s - i2c_addr: %x\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.i2c_addr);
+-			debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
++			debug ("%s - wpegbbar: %lx\n", __func__, hpc_ptr->u.wpeg_ctlr.wpegbbar);
++			debug ("%s - i2c_addr: %x\n", __func__, hpc_ptr->u.wpeg_ctlr.i2c_addr);
++			debug ("%s - irq: %x\n", __func__, hpc_ptr->irq);
+ 			break;
+ 		}
+ 	}
+diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
+index c31e7bf..83f337c 100644
+--- a/drivers/pci/hotplug/ibmphp_hpc.c
++++ b/drivers/pci/hotplug/ibmphp_hpc.c
+@@ -129,14 +129,14 @@ static int hpc_wait_ctlr_notworking (int, struct controller *, void __iomem *, u
+ *---------------------------------------------------------------------*/
+ void __init ibmphp_hpc_initvars (void)
+ {
+-	debug ("%s - Entry\n", __FUNCTION__);
++	debug ("%s - Entry\n", __func__);
+ 
+ 	mutex_init(&sem_hpcaccess);
+ 	init_MUTEX (&semOperations);
+ 	init_MUTEX_LOCKED (&sem_exit);
+ 	to_debug = 0;
+ 
+-	debug ("%s - Exit\n", __FUNCTION__);
++	debug ("%s - Exit\n", __func__);
+ }
+ 
+ /*----------------------------------------------------------------------
+@@ -154,7 +154,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ 	unsigned long ultemp;
+ 	unsigned long data;	// actual data HILO format
+ 
+-	debug_polling ("%s - Entry WPGBbar[%p] index[%x] \n", __FUNCTION__, WPGBbar, index);
++	debug_polling ("%s - Entry WPGBbar[%p] index[%x] \n", __func__, WPGBbar, index);
+ 
+ 	//--------------------------------------------------------------------
+ 	// READ - step 1
+@@ -213,7 +213,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ 		i--;
+ 	}
+ 	if (i == 0) {
+-		debug ("%s - Error : WPG timeout\n", __FUNCTION__);
++		debug ("%s - Error : WPG timeout\n", __func__);
+ 		return HPC_ERROR;
+ 	}
+ 	//--------------------------------------------------------------------
+@@ -241,7 +241,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ 
+ 	status = (u8) data;
+ 
+-	debug_polling ("%s - Exit index[%x] status[%x]\n", __FUNCTION__, index, status);
++	debug_polling ("%s - Exit index[%x] status[%x]\n", __func__, index, status);
+ 
+ 	return (status);
+ }
+@@ -262,7 +262,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ 	unsigned long data;	// actual data HILO format
+ 	int i;
+ 
+-	debug_polling ("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n", __FUNCTION__, WPGBbar, index, cmd);
++	debug_polling ("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n", __func__, WPGBbar, index, cmd);
+ 
+ 	rc = 0;
+ 	//--------------------------------------------------------------------
+@@ -324,7 +324,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ 		i--;
+ 	}
+ 	if (i == 0) {
+-		debug ("%s - Exit Error:WPG timeout\n", __FUNCTION__);
++		debug ("%s - Exit Error:WPG timeout\n", __func__);
+ 		rc = HPC_ERROR;
+ 	}
+ 
+@@ -345,7 +345,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ 		rc = HPC_ERROR;
+ 	}
+ 
+-	debug_polling ("%s Exit rc[%x]\n", __FUNCTION__, rc);
++	debug_polling ("%s Exit rc[%x]\n", __func__, rc);
+ 	return (rc);
+ }
+ 
+@@ -541,12 +541,12 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+ 	int rc = 0;
+ 	int busindex;
+ 
+-	debug_polling ("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n", __FUNCTION__, pslot, cmd, pstatus);
++	debug_polling ("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n", __func__, pslot, cmd, pstatus);
+ 
+ 	if ((pslot == NULL)
+ 	    || ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) {
+ 		rc = -EINVAL;
+-		err ("%s - Error invalid pointer, rc[%d]\n", __FUNCTION__, rc);
++		err ("%s - Error invalid pointer, rc[%d]\n", __func__, rc);
+ 		return rc;
+ 	}
+ 
+@@ -554,7 +554,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+ 		busindex = ibmphp_get_bus_index (pslot->bus);
+ 		if (busindex < 0) {
+ 			rc = -EINVAL;
+-			err ("%s - Exit Error:invalid bus, rc[%d]\n", __FUNCTION__, rc);
++			err ("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
+ 			return rc;
+ 		} else
+ 			index = (u8) busindex;
+@@ -565,7 +565,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+ 
+ 	if (index == HPC_ERROR) {
+ 		rc = -EINVAL;
+-		err ("%s - Exit Error:invalid index, rc[%d]\n", __FUNCTION__, rc);
++		err ("%s - Exit Error:invalid index, rc[%d]\n", __func__, rc);
+ 		return rc;
+ 	}
+ 
+@@ -641,7 +641,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+ 						    ctrl_read (ctlr_ptr, wpg_bbar,
+ 								index + WPG_1ST_EXTSLOT_INDEX);
+ 				} else {
+-					err ("%s - Error ctrl_read failed\n", __FUNCTION__);
++					err ("%s - Error ctrl_read failed\n", __func__);
+ 					rc = -EINVAL;
+ 					break;
+ 				}
+@@ -662,7 +662,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+ 	
+ 	free_hpc_access ();
+ 
+-	debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
++	debug_polling ("%s - Exit rc[%d]\n", __func__, rc);
+ 	return rc;
+ }
+ 
+@@ -681,10 +681,10 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ 	int rc = 0;
+ 	int timeout;
+ 
+-	debug_polling ("%s - Entry pslot[%p] cmd[%x]\n", __FUNCTION__, pslot, cmd);
++	debug_polling ("%s - Entry pslot[%p] cmd[%x]\n", __func__, pslot, cmd);
+ 	if (pslot == NULL) {
+ 		rc = -EINVAL;
+-		err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc);
++		err ("%s - Error Exit rc[%d]\n", __func__, rc);
+ 		return rc;
+ 	}
+ 
+@@ -694,7 +694,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ 		busindex = ibmphp_get_bus_index (pslot->bus);
+ 		if (busindex < 0) {
+ 			rc = -EINVAL;
+-			err ("%s - Exit Error:invalid bus, rc[%d]\n", __FUNCTION__, rc);
++			err ("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
+ 			return rc;
+ 		} else
+ 			index = (u8) busindex;
+@@ -705,7 +705,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ 
+ 	if (index == HPC_ERROR) {
+ 		rc = -EINVAL;
+-		err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc);
++		err ("%s - Error Exit rc[%d]\n", __func__, rc);
+ 		return rc;
+ 	}
+ 
+@@ -719,7 +719,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ 	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) {
+ 		wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
+ 
+-		debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __FUNCTION__,
++		debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __func__,
+ 		ctlr_ptr->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar,
+ 		ctlr_ptr->u.wpeg_ctlr.i2c_addr);
+ 	}
+@@ -750,7 +750,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ 				msleep(1000);
+ 				if (timeout < 1) {
+ 					done = 1;
+-					err ("%s - Error command complete timeout\n", __FUNCTION__);
++					err ("%s - Error command complete timeout\n", __func__);
+ 					rc = -EFAULT;
+ 				} else
+ 					timeout--;
+@@ -765,7 +765,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ 		iounmap (wpg_bbar);
+ 	free_hpc_access ();
+ 
+-	debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
++	debug_polling ("%s - Exit rc[%d]\n", __func__, rc);
+ 	return rc;
+ }
+ 
+@@ -803,10 +803,10 @@ void ibmphp_lock_operations (void)
+ *---------------------------------------------------------------------*/
+ void ibmphp_unlock_operations (void)
+ {
+-	debug ("%s - Entry\n", __FUNCTION__);
++	debug ("%s - Entry\n", __func__);
+ 	up (&semOperations);
+ 	to_debug = 0;
+-	debug ("%s - Exit\n", __FUNCTION__);
++	debug ("%s - Exit\n", __func__);
+ }
+ 
+ /*----------------------------------------------------------------------
+@@ -827,7 +827,7 @@ static int poll_hpc(void *data)
+ 	int poll_count = 0;
+ 	u8 ctrl_count = 0x00;
+ 
+-	debug ("%s - Entry\n", __FUNCTION__);
++	debug ("%s - Entry\n", __func__);
+ 
+ 	while (!kthread_should_stop()) {
+ 		/* try to get the lock to do some kind of hardware access */
+@@ -907,7 +907,7 @@ static int poll_hpc(void *data)
+ 		msleep(100);
+ 	}
+ 	up (&sem_exit);
+-	debug ("%s - Exit\n", __FUNCTION__);
++	debug ("%s - Exit\n", __func__);
+ 	return 0;
+ }
+ 
+@@ -999,7 +999,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
+ 		ibmphp_update_slot_info (pslot);
+ 	}
+ 
+-	debug ("%s - Exit rc[%d] disable[%x] update[%x]\n", __FUNCTION__, rc, disable, update);
++	debug ("%s - Exit rc[%d] disable[%x] update[%x]\n", __func__, rc, disable, update);
+ 
+ 	return rc;
+ }
+@@ -1021,7 +1021,7 @@ static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
+ 	u8 mask;
+ 	int rc = 0;
+ 
+-	debug ("%s - Entry old[%x], new[%x]\n", __FUNCTION__, old, new);
++	debug ("%s - Entry old[%x], new[%x]\n", __func__, old, new);
+ 	// bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots
+ 
+ 	for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) {
+@@ -1031,15 +1031,15 @@ static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
+ 			if (pslot) {
+ 				memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
+ 				rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
+-				debug ("%s - call process_changeinstatus for slot[%d]\n", __FUNCTION__, i);
++				debug ("%s - call process_changeinstatus for slot[%d]\n", __func__, i);
+ 				process_changeinstatus (pslot, &myslot);
+ 			} else {
+ 				rc = -EINVAL;
+-				err ("%s - Error bad pointer for slot[%d]\n", __FUNCTION__, i);
++				err ("%s - Error bad pointer for slot[%d]\n", __func__, i);
+ 			}
+ 		}
+ 	}
+-	debug ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
++	debug ("%s - Exit rc[%d]\n", __func__, rc);
+ 	return rc;
+ }
+ 
+@@ -1050,11 +1050,11 @@ static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
+ *---------------------------------------------------------------------*/
+ int __init ibmphp_hpc_start_poll_thread (void)
+ {
+-	debug ("%s - Entry\n", __FUNCTION__);
++	debug ("%s - Entry\n", __func__);
+ 
+ 	ibmphp_poll_thread = kthread_run(poll_hpc, NULL, "hpc_poll");
+ 	if (IS_ERR(ibmphp_poll_thread)) {
+-		err ("%s - Error, thread not started\n", __FUNCTION__);
++		err ("%s - Error, thread not started\n", __func__);
+ 		return PTR_ERR(ibmphp_poll_thread);
+ 	}
+ 	return 0;
+@@ -1067,7 +1067,7 @@ int __init ibmphp_hpc_start_poll_thread (void)
+ *---------------------------------------------------------------------*/
+ void __exit ibmphp_hpc_stop_poll_thread (void)
+ {
+-	debug ("%s - Entry\n", __FUNCTION__);
++	debug ("%s - Entry\n", __func__);
+ 
+ 	kthread_stop(ibmphp_poll_thread);
+ 	debug ("before locking operations \n");
+@@ -1088,7 +1088,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void)
+ 	up (&sem_exit);
+ 	debug ("after sem exit up\n");
+ 
+-	debug ("%s - Exit\n", __FUNCTION__);
++	debug ("%s - Exit\n", __func__);
+ }
+ 
+ /*----------------------------------------------------------------------
+diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
+index d8f05d7..7b09e16 100644
+--- a/drivers/pci/hotplug/ibmphp_pci.c
++++ b/drivers/pci/hotplug/ibmphp_pci.c
+@@ -364,7 +364,7 @@ static int configure_device (struct pci_func *func)
+ 	struct resource_node *pfmem[6];
+ 	unsigned int devfn;
+ 
+-	debug ("%s - inside\n", __FUNCTION__);
++	debug ("%s - inside\n", __func__);
+ 
+ 	devfn = PCI_DEVFN(func->device, func->function);
+ 	ibmphp_pci_bus->number = func->busno;
+@@ -595,7 +595,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
+ 	u8 irq;
+ 	int retval;
+ 
+-	debug ("%s - enter\n", __FUNCTION__);
++	debug ("%s - enter\n", __func__);
+ 
+ 	devfn = PCI_DEVFN(func->function, func->device);
+ 	ibmphp_pci_bus->number = func->busno;
+@@ -1234,7 +1234,7 @@ static int unconfigure_boot_device (u8 busno, u8 device, u8 function)
+ 	u32 tmp_address;
+ 	unsigned int devfn;
+ 
+-	debug ("%s - enter\n", __FUNCTION__);
++	debug ("%s - enter\n", __func__);
+ 
+ 	bus = ibmphp_find_res_bus (busno);
+ 	if (!bus) {
+@@ -1351,7 +1351,7 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function)
+ 	bus_no = (int) busno;
+ 	debug ("busno is %x\n", busno);
+ 	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number);
+-	debug ("%s - busno = %x, primary_number = %x\n", __FUNCTION__, busno, pri_number);
++	debug ("%s - busno = %x, primary_number = %x\n", __func__, busno, pri_number);
+ 
+ 	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
+ 	debug ("sec_number is %x\n", sec_number);
+@@ -1437,7 +1437,7 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function)
+ 			}
+ 		}	/* end of mem */
+ 	}	/* end of for */
+-	debug ("%s - exiting, returning success\n", __FUNCTION__);
++	debug ("%s - exiting, returning success\n", __func__);
+ 	return 0;
+ }
+ 
+@@ -1453,7 +1453,7 @@ static int unconfigure_boot_card (struct slot *slot_cur)
+ 	unsigned int devfn;
+ 	u8 valid_device = 0x00; /* To see if we are ever able to find valid device and read it */
+ 
+-	debug ("%s - enter\n", __FUNCTION__);
++	debug ("%s - enter\n", __func__);
+ 
+ 	device = slot_cur->device;
+ 	busno = slot_cur->bus;
+@@ -1470,7 +1470,7 @@ static int unconfigure_boot_card (struct slot *slot_cur)
+ 			/* found correct device!!! */
+ 			++valid_device;
+ 
+-			debug ("%s - found correct device\n", __FUNCTION__);
++			debug ("%s - found correct device\n", __func__);
+ 
+ 			/* header: x x x x x x x x
+ 			 *         | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge
+@@ -1573,7 +1573,7 @@ int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end)
+ 	struct pci_func *cur_func = NULL;
+ 	struct pci_func *temp_func;
+ 
+-	debug ("%s - enter\n", __FUNCTION__);
++	debug ("%s - enter\n", __func__);
+ 
+ 	if (!the_end) {
+ 		/* Need to unconfigure the card */
+@@ -1624,7 +1624,7 @@ int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end)
+ 
+ 	sl->func = NULL;
+ 	*slot_cur = sl;
+-	debug ("%s - exit\n", __FUNCTION__);
++	debug ("%s - exit\n", __func__);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c
+index 5636b1a..ec73294 100644
+--- a/drivers/pci/hotplug/ibmphp_res.c
++++ b/drivers/pci/hotplug/ibmphp_res.c
+@@ -563,7 +563,7 @@ static void fix_resources (struct bus_node *bus_cur)
+ 	struct range_node *range;
+ 	struct resource_node *res;
+ 
+-	debug ("%s - bus_cur->busno = %d\n", __FUNCTION__, bus_cur->busno);
++	debug ("%s - bus_cur->busno = %d\n", __func__, bus_cur->busno);
+ 
+ 	if (bus_cur->needIOUpdate) {
+ 		res = bus_cur->firstIO;
+@@ -599,7 +599,7 @@ int ibmphp_add_resource (struct resource_node *res)
+ 	struct range_node *range_cur = NULL;
+ 	struct resource_node *res_start = NULL;
+ 
+-	debug ("%s - enter\n", __FUNCTION__);
++	debug ("%s - enter\n", __func__);
+ 
+ 	if (!res) {
+ 		err ("NULL passed to add\n");
+@@ -762,7 +762,7 @@ int ibmphp_add_resource (struct resource_node *res)
+ 		}
+ 	}
+ 
+-	debug ("%s - exit\n", __FUNCTION__);
++	debug ("%s - exit\n", __func__);
+ 	return 0;
+ }
+ 
+@@ -1001,7 +1001,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
+ 		return -EINVAL;
+ 	}
+ 
+-	debug ("%s - enter\n", __FUNCTION__);
++	debug ("%s - enter\n", __func__);
+ 	debug ("bus_cur->busno is %d\n", bus_cur->busno);
+ 
+ 	/* This is a quick fix to not mess up with the code very much.  i.e.,
+@@ -1029,7 +1029,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
+ 
+ 	while (res_cur) {
+ 		range = find_range (bus_cur, res_cur);
+-		debug ("%s - rangeno = %d\n", __FUNCTION__, res_cur->rangeno);
++		debug ("%s - rangeno = %d\n", __func__, res_cur->rangeno);
+ 
+ 		if (!range) {
+ 			err ("no range for the device exists... bailing out...\n");
+@@ -1942,7 +1942,7 @@ static int __init update_bridge_ranges (struct bus_node **bus)
+ 		return -ENODEV;
+ 	ibmphp_pci_bus->number = bus_cur->busno;
+ 
+-	debug ("inside %s\n", __FUNCTION__);
++	debug ("inside %s\n", __func__);
+ 	debug ("bus_cur->busno = %x\n", bus_cur->busno);
+ 
+ 	for (device = 0; device < 32; device++) {
+diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
+index dd59a05..925ba16 100644
+--- a/drivers/pci/hotplug/pci_hotplug_core.c
++++ b/drivers/pci/hotplug/pci_hotplug_core.c
+@@ -43,7 +43,7 @@
+ 
+ #define MY_NAME	"pci_hotplug"
+ 
+-#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
++#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0)
+ #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+ #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+ #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
+index ca656b2..f14267e 100644
+--- a/drivers/pci/hotplug/pciehp.h
++++ b/drivers/pci/hotplug/pciehp.h
+@@ -168,7 +168,7 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
+ 			return slot;
+ 	}
+ 
+-	err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
++	err("%s: slot (device=0x%x) not found\n", __func__, device);
+ 	return NULL;
+ }
+ 
+diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
+index 5fa4ba0..aee19f0 100644
+--- a/drivers/pci/hotplug/pciehp_core.c
++++ b/drivers/pci/hotplug/pciehp_core.c
+@@ -184,7 +184,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	kfree(slot->hotplug_slot->info);
+ 	kfree(slot->hotplug_slot);
+@@ -301,7 +301,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	hotplug_slot->info->attention_status = status;
+ 
+@@ -316,7 +316,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	return pciehp_sysfs_enable_slot(slot);
+ }
+@@ -326,7 +326,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	return pciehp_sysfs_disable_slot(slot);
+ }
+@@ -336,7 +336,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_power_status(slot, value);
+ 	if (retval < 0)
+@@ -350,7 +350,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_attention_status(slot, value);
+ 	if (retval < 0)
+@@ -364,7 +364,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_latch_status(slot, value);
+ 	if (retval < 0)
+@@ -378,7 +378,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_adapter_status(slot, value);
+ 	if (retval < 0)
+@@ -392,7 +392,7 @@ static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
+ 
+@@ -404,7 +404,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_max_bus_speed(slot, value);
+ 	if (retval < 0)
+@@ -418,7 +418,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
+ 	if (retval < 0)
+@@ -437,7 +437,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
+ 
+ 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+ 	if (!ctrl) {
+-		err("%s : out of memory\n", __FUNCTION__);
++		err("%s : out of memory\n", __func__);
+ 		goto err_out_none;
+ 	}
+ 	INIT_LIST_HEAD(&ctrl->slot_list);
+@@ -454,7 +454,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
+ 	pci_set_drvdata(pdev, ctrl);
+ 
+ 	dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
+-	    __FUNCTION__, pdev->bus->number, PCI_SLOT(pdev->devfn),
++	    __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+ 	    PCI_FUNC(pdev->devfn), pdev->irq);
+ 
+ 	/* Setup the slot information structures */
+@@ -503,13 +503,13 @@ static void pciehp_remove (struct pcie_device *dev)
+ #ifdef CONFIG_PM
+ static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
+ {
+-	printk("%s ENTRY\n", __FUNCTION__);
++	printk("%s ENTRY\n", __func__);
+ 	return 0;
+ }
+ 
+ static int pciehp_resume (struct pcie_device *dev)
+ {
+-	printk("%s ENTRY\n", __FUNCTION__);
++	printk("%s ENTRY\n", __func__);
+ 	if (pciehp_force) {
+ 		struct pci_dev *pdev = dev->port;
+ 		struct controller *ctrl = pci_get_drvdata(pdev);
+@@ -563,7 +563,7 @@ static int __init pcied_init(void)
+  	dbg("pcie_port_service_register = %d\n", retval);
+   	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+  	if (retval)
+-		dbg("%s: Failure to register service\n", __FUNCTION__);
++		dbg("%s: Failure to register service\n", __func__);
+ 	return retval;
+ }
+ 
+diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
+index b23061c..0c481f7 100644
+--- a/drivers/pci/hotplug/pciehp_ctrl.c
++++ b/drivers/pci/hotplug/pciehp_ctrl.c
+@@ -181,7 +181,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
+ 	if (POWER_CTRL(ctrl->ctrlcap)) {
+ 		if (pslot->hpc_ops->power_off_slot(pslot)) {
+ 			err("%s: Issue of Slot Power Off command failed\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			return;
+ 		}
+ 	}
+@@ -192,7 +192,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
+ 	if (ATTN_LED(ctrl->ctrlcap)) {
+ 		if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
+ 			err("%s: Issue of Set Attention Led command failed\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			return;
+ 		}
+ 	}
+@@ -211,7 +211,7 @@ static int board_added(struct slot *p_slot)
+ 	struct controller *ctrl = p_slot->ctrl;
+ 
+ 	dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
+-			__FUNCTION__, p_slot->device,
++			__func__, p_slot->device,
+ 			ctrl->slot_device_offset, p_slot->hp_slot);
+ 
+ 	if (POWER_CTRL(ctrl->ctrlcap)) {
+@@ -230,14 +230,14 @@ static int board_added(struct slot *p_slot)
+ 	/* Check link training status */
+ 	retval = p_slot->hpc_ops->check_lnk_status(ctrl);
+ 	if (retval) {
+-		err("%s: Failed to check link status\n", __FUNCTION__);
++		err("%s: Failed to check link status\n", __func__);
+ 		set_slot_off(ctrl, p_slot);
+ 		return retval;
+ 	}
+ 
+ 	/* Check for a power fault */
+ 	if (p_slot->hpc_ops->query_power_fault(p_slot)) {
+-		dbg("%s: power fault detected\n", __FUNCTION__);
++		dbg("%s: power fault detected\n", __func__);
+ 		retval = POWER_FAILURE;
+ 		goto err_exit;
+ 	}
+@@ -277,14 +277,14 @@ static int remove_board(struct slot *p_slot)
+ 	if (retval)
+ 		return retval;
+ 
+-	dbg("In %s, hp_slot = %d\n", __FUNCTION__, p_slot->hp_slot);
++	dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
+ 
+ 	if (POWER_CTRL(ctrl->ctrlcap)) {
+ 		/* power off slot */
+ 		retval = p_slot->hpc_ops->power_off_slot(p_slot);
+ 		if (retval) {
+ 			err("%s: Issue of Slot Disable command failed\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			return retval;
+ 		}
+ 	}
+@@ -319,7 +319,7 @@ static void pciehp_power_thread(struct work_struct *work)
+ 	case POWEROFF_STATE:
+ 		mutex_unlock(&p_slot->lock);
+ 		dbg("%s: disabling bus:device(%x:%x)\n",
+-		    __FUNCTION__, p_slot->bus, p_slot->device);
++		    __func__, p_slot->bus, p_slot->device);
+ 		pciehp_disable_slot(p_slot);
+ 		mutex_lock(&p_slot->lock);
+ 		p_slot->state = STATIC_STATE;
+@@ -347,7 +347,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
+ 
+ 	info = kmalloc(sizeof(*info), GFP_KERNEL);
+ 	if (!info) {
+-		err("%s: Cannot allocate memory\n", __FUNCTION__);
++		err("%s: Cannot allocate memory\n", __func__);
+ 		return;
+ 	}
+ 	info->p_slot = p_slot;
+@@ -424,7 +424,7 @@ static void handle_button_press_event(struct slot *p_slot)
+ 		 * expires to cancel hot-add or hot-remove
+ 		 */
+ 		info("Button cancel on Slot(%s)\n", p_slot->name);
+-		dbg("%s: button cancel\n", __FUNCTION__);
++		dbg("%s: button cancel\n", __func__);
+ 		cancel_delayed_work(&p_slot->work);
+ 		if (p_slot->state == BLINKINGOFF_STATE) {
+ 			if (PWR_LED(ctrl->ctrlcap))
+@@ -465,7 +465,7 @@ static void handle_surprise_event(struct slot *p_slot)
+ 
+ 	info = kmalloc(sizeof(*info), GFP_KERNEL);
+ 	if (!info) {
+-		err("%s: Cannot allocate memory\n", __FUNCTION__);
++		err("%s: Cannot allocate memory\n", __func__);
+ 		return;
+ 	}
+ 	info->p_slot = p_slot;
+@@ -526,7 +526,7 @@ int pciehp_enable_slot(struct slot *p_slot)
+ 
+ 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+ 	if (rc || !getstatus) {
+-		info("%s: no adapter on slot(%s)\n", __FUNCTION__,
++		info("%s: no adapter on slot(%s)\n", __func__,
+ 		     p_slot->name);
+ 		mutex_unlock(&p_slot->ctrl->crit_sect);
+ 		return -ENODEV;
+@@ -534,7 +534,7 @@ int pciehp_enable_slot(struct slot *p_slot)
+ 	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
+ 		rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+ 		if (rc || getstatus) {
+-			info("%s: latch open on slot(%s)\n", __FUNCTION__,
++			info("%s: latch open on slot(%s)\n", __func__,
+ 			     p_slot->name);
+ 			mutex_unlock(&p_slot->ctrl->crit_sect);
+ 			return -ENODEV;
+@@ -544,7 +544,7 @@ int pciehp_enable_slot(struct slot *p_slot)
+ 	if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
+ 		rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+ 		if (rc || getstatus) {
+-			info("%s: already enabled on slot(%s)\n", __FUNCTION__,
++			info("%s: already enabled on slot(%s)\n", __func__,
+ 			     p_slot->name);
+ 			mutex_unlock(&p_slot->ctrl->crit_sect);
+ 			return -EINVAL;
+@@ -579,7 +579,7 @@ int pciehp_disable_slot(struct slot *p_slot)
+ 	if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
+ 		ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+ 		if (ret || !getstatus) {
+-			info("%s: no adapter on slot(%s)\n", __FUNCTION__,
++			info("%s: no adapter on slot(%s)\n", __func__,
+ 			     p_slot->name);
+ 			mutex_unlock(&p_slot->ctrl->crit_sect);
+ 			return -ENODEV;
+@@ -589,7 +589,7 @@ int pciehp_disable_slot(struct slot *p_slot)
+ 	if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
+ 		ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+ 		if (ret || getstatus) {
+-			info("%s: latch open on slot(%s)\n", __FUNCTION__,
++			info("%s: latch open on slot(%s)\n", __func__,
+ 			     p_slot->name);
+ 			mutex_unlock(&p_slot->ctrl->crit_sect);
+ 			return -ENODEV;
+@@ -599,7 +599,7 @@ int pciehp_disable_slot(struct slot *p_slot)
+ 	if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
+ 		ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+ 		if (ret || !getstatus) {
+-			info("%s: already disabled slot(%s)\n", __FUNCTION__,
++			info("%s: already disabled slot(%s)\n", __func__,
+ 			     p_slot->name);
+ 			mutex_unlock(&p_slot->ctrl->crit_sect);
+ 			return -EINVAL;
+diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
+index 698975a..b4bbd07 100644
+--- a/drivers/pci/hotplug/pciehp_hpc.c
++++ b/drivers/pci/hotplug/pciehp_hpc.c
+@@ -258,7 +258,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+ 
+ 	retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (retval) {
+-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ 		goto out;
+ 	}
+ 
+@@ -267,13 +267,13 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+ 		   proceed forward to issue the next command according
+ 		   to spec.  Just print out the error message */
+ 		dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
+-		    __FUNCTION__);
++		    __func__);
+ 	}
+ 
+ 	spin_lock_irqsave(&ctrl->lock, flags);
+ 	retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ 	if (retval) {
+-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTCTRL register\n", __func__);
+ 		goto out_spin_unlock;
+ 	}
+ 
+@@ -283,7 +283,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+ 	ctrl->cmd_busy = 1;
+ 	retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
+ 	if (retval)
+-		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
++		err("%s: Cannot write to SLOTCTRL register\n", __func__);
+ 
+  out_spin_unlock:
+ 	spin_unlock_irqrestore(&ctrl->lock, flags);
+@@ -305,14 +305,14 @@ static int hpc_check_lnk_status(struct controller *ctrl)
+ 
+ 	retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
+ 	if (retval) {
+-		err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read LNKSTATUS register\n", __func__);
+ 		return retval;
+ 	}
+ 
+-	dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status);
++	dbg("%s: lnk_status = %x\n", __func__, lnk_status);
+ 	if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) ||
+ 		!(lnk_status & NEG_LINK_WD)) {
+-		err("%s : Link Training Error occurs \n", __FUNCTION__);
++		err("%s : Link Training Error occurs \n", __func__);
+ 		retval = -1;
+ 		return retval;
+ 	}
+@@ -329,12 +329,12 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
+ 
+ 	retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ 	if (retval) {
+-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTCTRL register\n", __func__);
+ 		return retval;
+ 	}
+ 
+ 	dbg("%s: SLOTCTRL %x, value read %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
++	    __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+ 
+ 	atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
+ 
+@@ -368,11 +368,11 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
+ 
+ 	retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ 	if (retval) {
+-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTCTRL register\n", __func__);
+ 		return retval;
+ 	}
+ 	dbg("%s: SLOTCTRL %x value read %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
++	    __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+ 
+ 	pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
+ 
+@@ -399,7 +399,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
+ 
+ 	retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (retval) {
+-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ 		return retval;
+ 	}
+ 
+@@ -417,7 +417,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
+ 
+ 	retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (retval) {
+-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ 		return retval;
+ 	}
+ 	card_state = (u8)((slot_status & PRSN_STATE) >> 6);
+@@ -435,7 +435,7 @@ static int hpc_query_power_fault(struct slot *slot)
+ 
+ 	retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (retval) {
+-		err("%s: Cannot check for power fault\n", __FUNCTION__);
++		err("%s: Cannot check for power fault\n", __func__);
+ 		return retval;
+ 	}
+ 	pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
+@@ -451,7 +451,7 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
+ 
+ 	retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (retval) {
+-		err("%s : Cannot check EMI status\n", __FUNCTION__);
++		err("%s : Cannot check EMI status\n", __func__);
+ 		return retval;
+ 	}
+ 	*status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT;
+@@ -506,7 +506,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
+ 
+ 	rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ 	dbg("%s: SLOTCTRL %x write cmd %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ 
+ 	return rc;
+ }
+@@ -527,7 +527,7 @@ static void hpc_set_green_led_on(struct slot *slot)
+ 	pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ 
+ 	dbg("%s: SLOTCTRL %x write cmd %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ }
+ 
+ static void hpc_set_green_led_off(struct slot *slot)
+@@ -545,7 +545,7 @@ static void hpc_set_green_led_off(struct slot *slot)
+ 
+ 	pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ 	dbg("%s: SLOTCTRL %x write cmd %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ }
+ 
+ static void hpc_set_green_led_blink(struct slot *slot)
+@@ -564,7 +564,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
+ 	pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ 
+ 	dbg("%s: SLOTCTRL %x write cmd %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ }
+ 
+ static void hpc_release_ctlr(struct controller *ctrl)
+@@ -590,12 +590,12 @@ static int hpc_power_on_slot(struct slot * slot)
+ 	u16 slot_status;
+ 	int retval = 0;
+ 
+-	dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
++	dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
+ 
+ 	/* Clear sticky power-fault bit from previous power failures */
+ 	retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (retval) {
+-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ 		return retval;
+ 	}
+ 	slot_status &= PWR_FAULT_DETECTED;
+@@ -603,7 +603,7 @@ static int hpc_power_on_slot(struct slot * slot)
+ 		retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status);
+ 		if (retval) {
+ 			err("%s: Cannot write to SLOTSTATUS register\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			return retval;
+ 		}
+ 	}
+@@ -627,11 +627,11 @@ static int hpc_power_on_slot(struct slot * slot)
+ 	retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ 
+ 	if (retval) {
+-		err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
++		err("%s: Write %x command failed!\n", __func__, slot_cmd);
+ 		return -1;
+ 	}
+ 	dbg("%s: SLOTCTRL %x write cmd %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ 
+ 	return retval;
+ }
+@@ -677,7 +677,7 @@ static int hpc_power_off_slot(struct slot * slot)
+ 	int retval = 0;
+ 	int changed;
+ 
+-	dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
++	dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
+ 
+ 	/*
+ 	 * Set Bad DLLP Mask bit in Correctable Error Mask
+@@ -710,12 +710,12 @@ static int hpc_power_off_slot(struct slot * slot)
+ 
+ 	retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ 	if (retval) {
+-		err("%s: Write command failed!\n", __FUNCTION__);
++		err("%s: Write command failed!\n", __func__);
+ 		retval = -1;
+ 		goto out;
+ 	}
+ 	dbg("%s: SLOTCTRL %x write cmd %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++	    __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ 
+ 	/*
+ 	 * After turning power off, we must wait for at least 1 second
+@@ -741,7 +741,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ 
+ 	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ 		return IRQ_NONE;
+ 	}
+ 
+@@ -754,26 +754,26 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ 	if ( !intr_loc )
+ 		return IRQ_NONE;
+ 
+-	dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
++	dbg("%s: intr_loc %x\n", __func__, intr_loc);
+ 	/* Mask Hot-plug Interrupt Enable */
+ 	if (!pciehp_poll_mode) {
+ 		spin_lock_irqsave(&ctrl->lock, flags);
+ 		rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ 		if (rc) {
+ 			err("%s: Cannot read SLOT_CTRL register\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			spin_unlock_irqrestore(&ctrl->lock, flags);
+ 			return IRQ_NONE;
+ 		}
+ 
+ 		dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n",
+-		    __FUNCTION__, temp_word);
++		    __func__, temp_word);
+ 		temp_word = (temp_word & ~HP_INTR_ENABLE &
+ 			     ~CMD_CMPL_INTR_ENABLE) | 0x00;
+ 		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ 		if (rc) {
+ 			err("%s: Cannot write to SLOTCTRL register\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			spin_unlock_irqrestore(&ctrl->lock, flags);
+ 			return IRQ_NONE;
+ 		}
+@@ -782,18 +782,18 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ 		rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 		if (rc) {
+ 			err("%s: Cannot read SLOT_STATUS register\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			return IRQ_NONE;
+ 		}
+ 		dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
+-		    __FUNCTION__, slot_status);
++		    __func__, slot_status);
+ 
+ 		/* Clear command complete interrupt caused by this write */
+ 		temp_word = 0x1f;
+ 		rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ 		if (rc) {
+ 			err("%s: Cannot write to SLOTSTATUS register\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			return IRQ_NONE;
+ 		}
+ 	}
+@@ -822,7 +822,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ 	temp_word = 0x1F;
+ 	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ 	if (rc) {
+-		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+ 		return IRQ_NONE;
+ 	}
+ 	/* Unmask Hot-plug Interrupt Enable */
+@@ -831,18 +831,18 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ 		rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ 		if (rc) {
+ 			err("%s: Cannot read SLOTCTRL register\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			spin_unlock_irqrestore(&ctrl->lock, flags);
+ 			return IRQ_NONE;
+ 		}
+ 
+-		dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
++		dbg("%s: Unmask Hot-plug Interrupt Enable\n", __func__);
+ 		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+ 
+ 		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ 		if (rc) {
+ 			err("%s: Cannot write to SLOTCTRL register\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			spin_unlock_irqrestore(&ctrl->lock, flags);
+ 			return IRQ_NONE;
+ 		}
+@@ -851,7 +851,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ 		rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 		if (rc) {
+ 			err("%s: Cannot read SLOT_STATUS register\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			return IRQ_NONE;
+ 		}
+ 
+@@ -860,11 +860,11 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ 		rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ 		if (rc) {
+ 			err("%s: Cannot write to SLOTSTATUS failed\n",
+-			    __FUNCTION__);
++			    __func__);
+ 			return IRQ_NONE;
+ 		}
+ 		dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
+-		    __FUNCTION__, temp_word);
++		    __func__, temp_word);
+ 	}
+ 
+ 	return IRQ_HANDLED;
+@@ -879,7 +879,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
+ 
+ 	retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
+ 	if (retval) {
+-		err("%s: Cannot read LNKCAP register\n", __FUNCTION__);
++		err("%s: Cannot read LNKCAP register\n", __func__);
+ 		return retval;
+ 	}
+ 
+@@ -908,7 +908,7 @@ static int hpc_get_max_lnk_width(struct slot *slot,
+ 
+ 	retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
+ 	if (retval) {
+-		err("%s: Cannot read LNKCAP register\n", __FUNCTION__);
++		err("%s: Cannot read LNKCAP register\n", __func__);
+ 		return retval;
+ 	}
+ 
+@@ -957,7 +957,7 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
+ 
+ 	retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
+ 	if (retval) {
+-		err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read LNKSTATUS register\n", __func__);
+ 		return retval;
+ 	}
+ 
+@@ -986,7 +986,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
+ 
+ 	retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
+ 	if (retval) {
+-		err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read LNKSTATUS register\n", __func__);
+ 		return retval;
+ 	}
+ 
+@@ -1130,38 +1130,38 @@ static int pcie_init_hardware_part1(struct controller *ctrl,
+ 
+ 	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTCAP register\n", __func__);
+ 		return -1;
+ 	}
+ 
+ 	/* Mask Hot-plug Interrupt Enable */
+ 	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTCTRL register\n", __func__);
+ 		return -1;
+ 	}
+ 
+ 	dbg("%s: SLOTCTRL %x value read %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
++	    __func__, ctrl->cap_base + SLOTCTRL, temp_word);
+ 	temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
+ 		0x00;
+ 
+ 	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ 	if (rc) {
+-		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
++		err("%s: Cannot write to SLOTCTRL register\n", __func__);
+ 		return -1;
+ 	}
+ 
+ 	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ 		return -1;
+ 	}
+ 
+ 	temp_word = 0x1F; /* Clear all events */
+ 	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ 	if (rc) {
+-		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+ 		return -1;
+ 	}
+ 	return 0;
+@@ -1177,7 +1177,7 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+ 
+ 	rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTCTRL register\n", __func__);
+ 		goto abort;
+ 	}
+ 
+@@ -1185,7 +1185,7 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+ 
+ 	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTCAP register\n", __func__);
+ 		goto abort;
+ 	}
+ 
+@@ -1212,19 +1212,19 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+ 	 */
+ 	rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ 	if (rc) {
+-		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
++		err("%s: Cannot write to SLOTCTRL register\n", __func__);
+ 		goto abort;
+ 	}
+ 	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ 		goto abort_disable_intr;
+ 	}
+ 
+ 	temp_word =  0x1F; /* Clear all events */
+ 	rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ 	if (rc) {
+-		err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+ 		goto abort_disable_intr;
+ 	}
+ 
+@@ -1247,7 +1247,7 @@ abort_disable_intr:
+ 		rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ 	}
+ 	if (rc)
+-		err("%s : disabling interrupts failed\n", __FUNCTION__);
++		err("%s : disabling interrupts failed\n", __func__);
+ abort:
+ 	return -1;
+ }
+@@ -1265,62 +1265,62 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+ 	ctrl->pci_dev = pdev;	/* save pci_dev in context */
+ 
+ 	dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
+-			__FUNCTION__, pdev->vendor, pdev->device);
++			__func__, pdev->vendor, pdev->device);
+ 
+ 	cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ 	if (cap_base == 0) {
+-		dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
++		dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __func__);
+ 		goto abort;
+ 	}
+ 
+ 	ctrl->cap_base = cap_base;
+ 
+-	dbg("%s: pcie_cap_base %x\n", __FUNCTION__, cap_base);
++	dbg("%s: pcie_cap_base %x\n", __func__, cap_base);
+ 
+ 	rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
+ 	if (rc) {
+-		err("%s: Cannot read CAPREG register\n", __FUNCTION__);
++		err("%s: Cannot read CAPREG register\n", __func__);
+ 		goto abort;
+ 	}
+ 	dbg("%s: CAPREG offset %x cap_reg %x\n",
+-	    __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
++	    __func__, ctrl->cap_base + CAPREG, cap_reg);
+ 
+ 	if (((cap_reg & SLOT_IMPL) == 0) ||
+ 	    (((cap_reg & DEV_PORT_TYPE) != 0x0040)
+ 		&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
+ 		dbg("%s : This is not a root port or the port is not "
+-		    "connected to a slot\n", __FUNCTION__);
++		    "connected to a slot\n", __func__);
+ 		goto abort;
+ 	}
+ 
+ 	rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTCAP register\n", __func__);
+ 		goto abort;
+ 	}
+ 	dbg("%s: SLOTCAP offset %x slot_cap %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
++	    __func__, ctrl->cap_base + SLOTCAP, slot_cap);
+ 
+ 	if (!(slot_cap & HP_CAP)) {
+-		dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
++		dbg("%s : This slot is not hot-plug capable\n", __func__);
+ 		goto abort;
+ 	}
+ 	/* For debugging purpose */
+ 	rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ 		goto abort;
+ 	}
+ 	dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
++	    __func__, ctrl->cap_base + SLOTSTATUS, slot_status);
+ 
+ 	rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ 	if (rc) {
+-		err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++		err("%s: Cannot read SLOTCTRL register\n", __func__);
+ 		goto abort;
+ 	}
+ 	dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
+-	    __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
++	    __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+ 
+ 	for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
+ 		if (pci_resource_len(pdev, rc) > 0)
+@@ -1358,7 +1358,7 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+ 		rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
+ 				 MY_NAME, (void *)ctrl);
+ 		dbg("%s: request_irq %d for hpc%d (returns %d)\n",
+-		    __FUNCTION__, ctrl->pci_dev->irq,
++		    __func__, ctrl->pci_dev->irq,
+ 		    atomic_read(&pciehp_num_controllers), rc);
+ 		if (rc) {
+ 			err("Can't get irq %d for the hotplug controller\n",
+diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
+index 9372a84..6040dcc 100644
+--- a/drivers/pci/hotplug/pciehp_pci.c
++++ b/drivers/pci/hotplug/pciehp_pci.c
+@@ -40,7 +40,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
+ 
+ 	if (hpp->revision > 1) {
+ 		printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n",
+-		       __FUNCTION__, hpp->revision);
++		       __func__, hpp->revision);
+ 		return;
+ 	}
+ 
+@@ -82,7 +82,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
+ 
+ 	if (hpp->revision > 1) {
+ 		printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n",
+-		       __FUNCTION__, hpp->revision);
++		       __func__, hpp->revision);
+ 		return;
+ 	}
+ 
+@@ -150,7 +150,7 @@ static void program_fw_provided_values(struct pci_dev *dev)
+ 
+ 	if (pciehp_get_hp_params_from_firmware(dev, &hpp)) {
+ 		printk(KERN_WARNING "%s: Could not get hotplug parameters\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return;
+ 	}
+ 
+@@ -245,7 +245,7 @@ int pciehp_unconfigure_device(struct slot *p_slot)
+ 	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ 	u16 command;
+ 
+-	dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
++	dbg("%s: bus/dev = %x/%x\n", __func__, p_slot->bus,
+ 				p_slot->device);
+ 	ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
+ 	if (ret)
+diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
+index 50bcd3f..e3dd6cf 100644
+--- a/drivers/pci/hotplug/pcihp_skeleton.c
++++ b/drivers/pci/hotplug/pcihp_skeleton.c
+@@ -98,7 +98,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	/*
+ 	 * Fill in code here to enable the specified slot
+@@ -112,7 +112,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	/*
+ 	 * Fill in code here to disable the specified slot
+@@ -126,7 +126,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	switch (status) {
+ 		case 0:
+@@ -151,7 +151,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	switch (value) {
+ 		case 0:
+@@ -170,7 +170,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	/*
+ 	 * Fill in logic to get the current power status of the specific
+@@ -185,7 +185,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	/*
+ 	 * Fill in logic to get the current attention status of the specific
+@@ -200,7 +200,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	/*
+ 	 * Fill in logic to get the current latch status of the specific
+@@ -215,7 +215,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = hotplug_slot->private;
+ 	int retval = 0;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	/*
+ 	 * Fill in logic to get the current adapter status of the specific
+@@ -229,7 +229,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 	kfree(slot->hotplug_slot->info);
+ 	kfree(slot->hotplug_slot);
+ 	kfree(slot);
+diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
+index 191954b..9c2a22f 100644
+--- a/drivers/pci/hotplug/rpadlpar_core.c
++++ b/drivers/pci/hotplug/rpadlpar_core.c
+@@ -147,7 +147,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
+ 	dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
+ 	if (!dev) {
+ 		printk(KERN_ERR "%s: failed to create pci dev for %s\n",
+-				__FUNCTION__, dn->full_name);
++				__func__, dn->full_name);
+ 		return;
+ 	}
+ 
+@@ -183,21 +183,21 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
+ 	dev = dlpar_find_new_dev(phb->bus, dn);
+ 
+ 	if (!dev) {
+-		printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__,
++		printk(KERN_ERR "%s: unable to add bus %s\n", __func__,
+ 			drc_name);
+ 		return -EIO;
+ 	}
+ 
+ 	if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+ 		printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n",
+-			__FUNCTION__, dev->hdr_type, drc_name);
++			__func__, dev->hdr_type, drc_name);
+ 		return -EIO;
+ 	}
+ 
+ 	/* Add hotplug slot */
+ 	if (rpaphp_add_slot(dn)) {
+ 		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+-			__FUNCTION__, drc_name);
++			__func__, drc_name);
+ 		return -EIO;
+ 	}
+ 	return 0;
+@@ -239,7 +239,7 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
+ 		if (rpaphp_deregister_slot(slot)) {
+ 			printk(KERN_ERR
+ 				"%s: unable to remove hotplug slot %s\n",
+-				__FUNCTION__, drc_name);
++				__func__, drc_name);
+ 			return -EIO;
+ 		}
+ 	}
+@@ -270,7 +270,7 @@ static int dlpar_add_phb(char *drc_name, struct device_node *dn)
+ 
+ 	if (rpaphp_add_slot(dn)) {
+ 		printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+-			__FUNCTION__, drc_name);
++			__func__, drc_name);
+ 		return -EIO;
+ 	}
+ 	return 0;
+@@ -284,7 +284,7 @@ static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
+ 	if (!vio_register_device_node(dn)) {
+ 		printk(KERN_ERR
+ 			"%s: failed to register vio node %s\n",
+-			__FUNCTION__, drc_name);
++			__func__, drc_name);
+ 		return -EIO;
+ 	}
+ 	return 0;
+@@ -384,7 +384,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
+ 		if (rpaphp_deregister_slot(slot)) {
+ 			printk(KERN_ERR
+ 				"%s: unable to remove hotplug slot %s\n",
+-				__FUNCTION__, drc_name);
++				__func__, drc_name);
+ 			return -EIO;
+ 		}
+ 	} else
+@@ -392,7 +392,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
+ 
+ 	if (pcibios_unmap_io_space(bus)) {
+ 		printk(KERN_ERR "%s: failed to unmap bus range\n",
+-			__FUNCTION__);
++			__func__);
+ 		return -ERANGE;
+ 	}
+ 
+@@ -458,7 +458,7 @@ int __init rpadlpar_io_init(void)
+ 
+ 	if (!is_dlpar_capable()) {
+ 		printk(KERN_WARNING "%s: partition not DLPAR capable\n",
+-			__FUNCTION__);
++			__func__);
+ 		return -EPERM;
+ 	}
+ 
+diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
+index 58f1a99..1f84f40 100644
+--- a/drivers/pci/hotplug/rpaphp_core.c
++++ b/drivers/pci/hotplug/rpaphp_core.c
+@@ -317,7 +317,7 @@ int rpaphp_add_slot(struct device_node *dn)
+ 	if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
+ 		return 0;
+ 
+-	dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name);
++	dbg("Entry %s: dn->full_name=%s\n", __func__, dn->full_name);
+ 
+ 	/* register PCI devices */
+ 	name = (char *) &names[1];
+@@ -343,7 +343,7 @@ int rpaphp_add_slot(struct device_node *dn)
+ 		name += strlen(name) + 1;
+ 		type += strlen(type) + 1;
+ 	}
+-	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
++	dbg("%s - Exit: rc[%d]\n", __func__, retval);
+ 
+ 	/* XXX FIXME: reports a failure only if last entry in loop failed */
+ 	return retval;
+@@ -404,7 +404,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ 	} else if (state == EMPTY) {
+ 		slot->state = EMPTY;
+ 	} else {
+-		err("%s: slot[%s] is in invalid state\n", __FUNCTION__, slot->name);
++		err("%s: slot[%s] is in invalid state\n", __func__, slot->name);
+ 		slot->state = NOT_VALID;
+ 		return -EINVAL;
+ 	}
+diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
+index 6571e9b..5acfd4f 100644
+--- a/drivers/pci/hotplug/rpaphp_pci.c
++++ b/drivers/pci/hotplug/rpaphp_pci.c
+@@ -42,7 +42,7 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
+ 	if (rc < 0) {
+ 		if (rc == -EFAULT || rc == -EEXIST) {
+ 			dbg("%s: slot must be power up to get sensor-state\n",
+-			    __FUNCTION__);
++			    __func__);
+ 
+ 			/* some slots have to be powered up 
+ 			 * before get-sensor will succeed.
+@@ -51,15 +51,15 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
+ 						  &setlevel);
+ 			if (rc < 0) {
+ 				dbg("%s: power on slot[%s] failed rc=%d.\n",
+-				    __FUNCTION__, slot->name, rc);
++				    __func__, slot->name, rc);
+ 			} else {
+ 				rc = rtas_get_sensor(DR_ENTITY_SENSE,
+ 						     slot->index, state);
+ 			}
+ 		} else if (rc == -ENODEV)
+-			info("%s: slot is unusable\n", __FUNCTION__);
++			info("%s: slot is unusable\n", __func__);
+ 		else
+-			err("%s failed to get sensor state\n", __FUNCTION__);
++			err("%s failed to get sensor state\n", __func__);
+ 	}
+ 	return rc;
+ }
+@@ -95,7 +95,7 @@ int rpaphp_enable_slot(struct slot *slot)
+ 
+ 	bus = pcibios_find_pci_bus(slot->dn);
+ 	if (!bus) {
+-		err("%s: no pci_bus for dn %s\n", __FUNCTION__, slot->dn->full_name);
++		err("%s: no pci_bus for dn %s\n", __func__, slot->dn->full_name);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -111,7 +111,7 @@ int rpaphp_enable_slot(struct slot *slot)
+ 		/* non-empty slot has to have child */
+ 		if (!slot->dn->child) {
+ 			err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
+-			    __FUNCTION__, slot->name);
++			    __func__, slot->name);
+ 			return -EINVAL;
+ 		}
+ 
+@@ -125,7 +125,7 @@ int rpaphp_enable_slot(struct slot *slot)
+ 
+ 		if (debug) {
+ 			struct pci_dev *dev;
+-			dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->dn->full_name);
++			dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name);
+ 			list_for_each_entry (dev, &bus->devices, bus_list)
+ 				dbg("\t%s\n", pci_name(dev));
+ 		}
+diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
+index 8ad3deb..56197b6 100644
+--- a/drivers/pci/hotplug/rpaphp_slot.c
++++ b/drivers/pci/hotplug/rpaphp_slot.c
+@@ -131,7 +131,7 @@ int rpaphp_deregister_slot(struct slot *slot)
+ 	struct hotplug_slot *php_slot = slot->hotplug_slot;
+ 
+ 	 dbg("%s - Entry: deregistering slot=%s\n",
+-		__FUNCTION__, slot->name);
++		__func__, slot->name);
+ 
+ 	list_del(&slot->rpaphp_slot_list);
+ 	
+@@ -142,7 +142,7 @@ int rpaphp_deregister_slot(struct slot *slot)
+ 	if (retval)
+ 		err("Problem unregistering a slot %s\n", slot->name);
+ 
+-	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
++	dbg("%s - Exit: rc[%d]\n", __func__, retval);
+ 	return retval;
+ }
+ EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
+@@ -153,7 +153,7 @@ int rpaphp_register_slot(struct slot *slot)
+ 	int retval;
+ 
+ 	dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", 
+-		__FUNCTION__, slot->dn->full_name, slot->index, slot->name, 
++		__func__, slot->dn->full_name, slot->index, slot->name,
+ 		slot->power_domain, slot->type);
+ 
+ 	/* should not try to register the same slot twice */
+diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
+index ef07c36..2fe37cd 100644
+--- a/drivers/pci/hotplug/sgi_hotplug.c
++++ b/drivers/pci/hotplug/sgi_hotplug.c
+@@ -367,7 +367,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
+ 		ret = acpi_load_table((struct acpi_table_header *)ssdt);
+ 		if (ACPI_FAILURE(ret)) {
+ 			printk(KERN_ERR "%s: acpi_load_table failed (0x%x)\n",
+-			       __FUNCTION__, ret);
++			       __func__, ret);
+ 			/* try to continue on */
+ 		}
+ 	}
+@@ -459,7 +459,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
+ 				if (ACPI_FAILURE(ret)) {
+ 					printk(KERN_ERR "%s: acpi_bus_add "
+ 					       "failed (0x%x) for slot %d "
+-					       "func %d\n", __FUNCTION__,
++					       "func %d\n", __func__,
+ 					       ret, (int)(adr>>16),
+ 					       (int)(adr&0xffff));
+ 					/* try to continue on */
+@@ -570,7 +570,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
+ 		if (ACPI_FAILURE(ret)) {
+ 			printk(KERN_ERR "%s: acpi_unload_table_id "
+ 			       "failed (0x%x) for id %d\n",
+-			       __FUNCTION__, ret, ssdt_id);
++			       __func__, ret, ssdt_id);
+ 			/* try to continue on */
+ 		}
+ 	}
+@@ -689,7 +689,7 @@ static int sn_pci_hotplug_init(void)
+ 
+ 	if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) {
+ 		printk(KERN_ERR "%s: PROM version does not support hotplug.\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return -EPERM;
+ 	}
+ 
+diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
+index 37ed088..f66e8d6 100644
+--- a/drivers/pci/hotplug/shpchp.h
++++ b/drivers/pci/hotplug/shpchp.h
+@@ -234,7 +234,7 @@ static inline struct slot *shpchp_find_slot(struct controller *ctrl, u8 device)
+ 			return slot;
+ 	}
+ 
+-	err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
++	err("%s: slot (device=0x%x) not found\n", __func__, device);
+ 	return NULL;
+ }
+ 
+@@ -268,7 +268,7 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
+ 	pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, &pcix_bridge_errors_reg);
+ 	perr_set = pcix_bridge_errors_reg & PERR_OBSERVED_MASK;
+ 	if (perr_set) {
+-		dbg ("%s  W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__FUNCTION__ , perr_set);
++		dbg ("%s  W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__func__ , perr_set);
+ 
+ 		pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, perr_set);
+ 	}
+@@ -277,7 +277,7 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
+ 	pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, &pcix_mem_base_reg);
+ 	rse_set = pcix_mem_base_reg & RSE_MASK;
+ 	if (rse_set) {
+-		dbg ("%s  W1C: Memory_Base_Limit[ RSE ]\n",__FUNCTION__ );
++		dbg ("%s  W1C: Memory_Base_Limit[ RSE ]\n",__func__ );
+ 
+ 		pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set);
+ 	}
+diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
+index 80dec97..43816d4 100644
+--- a/drivers/pci/hotplug/shpchp_core.c
++++ b/drivers/pci/hotplug/shpchp_core.c
+@@ -91,7 +91,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = hotplug_slot->private;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	kfree(slot->hotplug_slot->info);
+ 	kfree(slot->hotplug_slot);
+@@ -195,7 +195,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+ {
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	hotplug_slot->info->attention_status = status;
+ 	slot->hpc_ops->set_attention_status(slot, status);
+@@ -207,7 +207,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	return shpchp_sysfs_enable_slot(slot);
+ }
+@@ -216,7 +216,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
+ {
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	return shpchp_sysfs_disable_slot(slot);
+ }
+@@ -226,7 +226,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_power_status(slot, value);
+ 	if (retval < 0)
+@@ -240,7 +240,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_attention_status(slot, value);
+ 	if (retval < 0)
+@@ -254,7 +254,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_latch_status(slot, value);
+ 	if (retval < 0)
+@@ -268,7 +268,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_adapter_status(slot, value);
+ 	if (retval < 0)
+@@ -282,7 +282,7 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 	struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	*value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
+ 
+@@ -294,7 +294,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_max_bus_speed(slot, value);
+ 	if (retval < 0)
+@@ -308,7 +308,7 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
+ 	struct slot *slot = get_slot(hotplug_slot);
+ 	int retval;
+ 
+-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ 
+ 	retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
+ 	if (retval < 0)
+@@ -338,7 +338,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+ 	if (!ctrl) {
+-		err("%s : out of memory\n", __FUNCTION__);
++		err("%s : out of memory\n", __func__);
+ 		goto err_out_none;
+ 	}
+ 	INIT_LIST_HEAD(&ctrl->slot_list);
+@@ -402,7 +402,7 @@ static int __init shpcd_init(void)
+ 	int retval = 0;
+ 
+ 	retval = pci_register_driver(&shpc_driver);
+-	dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
++	dbg("%s: pci_register_driver = %d\n", __func__, retval);
+ 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ 	return retval;
+ }
+diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
+index eb5cac6..dfb5393 100644
+--- a/drivers/pci/hotplug/shpchp_ctrl.c
++++ b/drivers/pci/hotplug/shpchp_ctrl.c
+@@ -91,7 +91,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
+ 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+ 	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+-	dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
++	dbg("%s: Card present %x Power status %x\n", __func__,
+ 		p_slot->presence_save, p_slot->pwr_save);
+ 
+ 	if (getstatus) {
+@@ -191,10 +191,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
+ {
+ 	int rc = 0;
+ 
+-	dbg("%s: change to speed %d\n", __FUNCTION__, speed);
++	dbg("%s: change to speed %d\n", __func__, speed);
+ 	if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) {
+ 		err("%s: Issue of set bus speed mode command failed\n",
+-		    __FUNCTION__);
++		    __func__);
+ 		return WRONG_BUS_FREQUENCY;
+ 	}
+ 	return rc;
+@@ -213,7 +213,7 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
+ 	if (flag) {
+ 		if (asp < bsp) {
+ 			err("%s: speed of bus %x and adapter %x mismatch\n",
+-			    __FUNCTION__, bsp, asp);
++			    __func__, bsp, asp);
+ 			rc = WRONG_BUS_FREQUENCY;
+ 		}
+ 		return rc;
+@@ -247,13 +247,13 @@ static int board_added(struct slot *p_slot)
+ 	hp_slot = p_slot->device - ctrl->slot_device_offset;
+ 
+ 	dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
+-			__FUNCTION__, p_slot->device,
++			__func__, p_slot->device,
+ 			ctrl->slot_device_offset, hp_slot);
+ 
+ 	/* Power on slot without connecting to bus */
+ 	rc = p_slot->hpc_ops->power_on_slot(p_slot);
+ 	if (rc) {
+-		err("%s: Failed to power on slot\n", __FUNCTION__);
++		err("%s: Failed to power on slot\n", __func__);
+ 		return -1;
+ 	}
+ 
+@@ -262,13 +262,13 @@ static int board_added(struct slot *p_slot)
+ 			return WRONG_BUS_FREQUENCY;
+ 
+ 		if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
+-			err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
++			err("%s: Issue of set bus speed mode command failed\n", __func__);
+ 			return WRONG_BUS_FREQUENCY;
+ 		}
+ 
+ 		/* turn on board, blink green LED, turn off Amber LED */
+ 		if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
+-			err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
++			err("%s: Issue of Slot Enable command failed\n", __func__);
+ 			return rc;
+ 		}
+ 	}
+@@ -276,19 +276,19 @@ static int board_added(struct slot *p_slot)
+ 	rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp);
+ 	if (rc) {
+ 		err("%s: Can't get adapter speed or bus mode mismatch\n",
+-		    __FUNCTION__);
++		    __func__);
+ 		return WRONG_BUS_FREQUENCY;
+ 	}
+ 
+ 	rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp);
+ 	if (rc) {
+-		err("%s: Can't get bus operation speed\n", __FUNCTION__);
++		err("%s: Can't get bus operation speed\n", __func__);
+ 		return WRONG_BUS_FREQUENCY;
+ 	}
+ 
+ 	rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp);
+ 	if (rc) {
+-		err("%s: Can't get max bus operation speed\n", __FUNCTION__);
++		err("%s: Can't get max bus operation speed\n", __func__);
+ 		msp = bsp;
+ 	}
+ 
+@@ -297,7 +297,7 @@ static int board_added(struct slot *p_slot)
+ 		slots_not_empty = 1;
+ 
+ 	dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, "
+-	    "max_bus_speed %d\n", __FUNCTION__, slots_not_empty, asp,
++	    "max_bus_speed %d\n", __func__, slots_not_empty, asp,
+ 	    bsp, msp);
+ 
+ 	rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp);
+@@ -306,18 +306,18 @@ static int board_added(struct slot *p_slot)
+ 
+ 	/* turn on board, blink green LED, turn off Amber LED */
+ 	if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
+-		err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
++		err("%s: Issue of Slot Enable command failed\n", __func__);
+ 		return rc;
+ 	}
+ 
+ 	/* Wait for ~1 second */
+ 	msleep(1000);
+ 
+-	dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
++	dbg("%s: slot status = %x\n", __func__, p_slot->status);
+ 	/* Check for a power fault */
+ 	if (p_slot->status == 0xFF) {
+ 		/* power fault occurred, but it was benign */
+-		dbg("%s: power fault\n", __FUNCTION__);
++		dbg("%s: power fault\n", __func__);
+ 		rc = POWER_FAILURE;
+ 		p_slot->status = 0;
+ 		goto err_exit;
+@@ -341,7 +341,7 @@ err_exit:
+ 	/* turn off slot, turn on Amber LED, turn off Green LED */
+ 	rc = p_slot->hpc_ops->slot_disable(p_slot);
+ 	if (rc) {
+-		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
++		err("%s: Issue of Slot Disable command failed\n", __func__);
+ 		return rc;
+ 	}
+ 
+@@ -365,7 +365,7 @@ static int remove_board(struct slot *p_slot)
+ 	hp_slot = p_slot->device - ctrl->slot_device_offset;
+ 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+ 
+-	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
++	dbg("In %s, hp_slot = %d\n", __func__, hp_slot);
+ 
+ 	/* Change status to shutdown */
+ 	if (p_slot->is_a_board)
+@@ -374,13 +374,13 @@ static int remove_board(struct slot *p_slot)
+ 	/* turn off slot, turn on Amber LED, turn off Green LED */
+ 	rc = p_slot->hpc_ops->slot_disable(p_slot);
+ 	if (rc) {
+-		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
++		err("%s: Issue of Slot Disable command failed\n", __func__);
+ 		return rc;
+ 	}
+ 
+ 	rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
+ 	if (rc) {
+-		err("%s: Issue of Set Attention command failed\n", __FUNCTION__);
++		err("%s: Issue of Set Attention command failed\n", __func__);
+ 		return rc;
+ 	}
+ 
+@@ -439,7 +439,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work)
+ 
+ 	info = kmalloc(sizeof(*info), GFP_KERNEL);
+ 	if (!info) {
+-		err("%s: Cannot allocate memory\n", __FUNCTION__);
++		err("%s: Cannot allocate memory\n", __func__);
+ 		return;
+ 	}
+ 	info->p_slot = p_slot;
+@@ -513,7 +513,7 @@ static void handle_button_press_event(struct slot *p_slot)
+ 		 * expires to cancel hot-add or hot-remove
+ 		 */
+ 		info("Button cancel on Slot(%s)\n", p_slot->name);
+-		dbg("%s: button cancel\n", __FUNCTION__);
++		dbg("%s: button cancel\n", __func__);
+ 		cancel_delayed_work(&p_slot->work);
+ 		if (p_slot->state == BLINKINGOFF_STATE)
+ 			p_slot->hpc_ops->green_led_on(p_slot);
+@@ -551,7 +551,7 @@ static void interrupt_event_handler(struct work_struct *work)
+ 		handle_button_press_event(p_slot);
+ 		break;
+ 	case INT_POWER_FAULT:
+-		dbg("%s: power fault\n", __FUNCTION__);
++		dbg("%s: power fault\n", __func__);
+ 		p_slot->hpc_ops->set_attention_status(p_slot, 1);
+ 		p_slot->hpc_ops->green_led_off(p_slot);
+ 		break;
+@@ -593,7 +593,7 @@ static int shpchp_enable_slot (struct slot *p_slot)
+ 	/* We have to save the presence info for these slots */
+ 	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ 	p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
+-	dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
++	dbg("%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save);
+ 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+ 
+ 	if(((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) ||
+diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
+index e8aa138..7d770b2 100644
+--- a/drivers/pci/hotplug/shpchp_hpc.c
++++ b/drivers/pci/hotplug/shpchp_hpc.c
+@@ -321,14 +321,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
+ 	if (!shpc_poll_ctrl_busy(ctrl)) {
+ 		/* After 1 sec and and the controller is still busy */
+ 		err("%s : Controller is still busy after 1 sec.\n",
+-		    __FUNCTION__);
++		    __func__);
+ 		retval = -EBUSY;
+ 		goto out;
+ 	}
+ 
+ 	++t_slot;
+ 	temp_word =  (t_slot << 8) | (cmd & 0xFF);
+-	dbg("%s: t_slot %x cmd %x\n", __FUNCTION__, t_slot, cmd);
++	dbg("%s: t_slot %x cmd %x\n", __func__, t_slot, cmd);
+ 
+ 	/* To make sure the Controller Busy bit is 0 before we send out the
+ 	 * command.
+@@ -345,7 +345,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
+ 	cmd_status = hpc_check_cmd_status(slot->ctrl);
+ 	if (cmd_status) {
+ 		err("%s: Failed to issued command 0x%x (error code = %d)\n",
+-		    __FUNCTION__, cmd, cmd_status);
++		    __func__, cmd, cmd_status);
+ 		retval = -EIO;
+ 	}
+  out:
+@@ -364,15 +364,15 @@ static int hpc_check_cmd_status(struct controller *ctrl)
+ 		break;
+ 	case 1:
+ 		retval = SWITCH_OPEN;
+-		err("%s: Switch opened!\n", __FUNCTION__);
++		err("%s: Switch opened!\n", __func__);
+ 		break;
+ 	case 2:
+ 		retval = INVALID_CMD;
+-		err("%s: Invalid HPC command!\n", __FUNCTION__);
++		err("%s: Invalid HPC command!\n", __func__);
+ 		break;
+ 	case 4:
+ 		retval = INVALID_SPEED_MODE;
+-		err("%s: Invalid bus speed/mode!\n", __FUNCTION__);
++		err("%s: Invalid bus speed/mode!\n", __func__);
+ 		break;
+ 	default:
+ 		retval = cmd_status;
+@@ -484,7 +484,7 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
+ 	}
+ 
+ 	dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
+-	    __FUNCTION__, slot_reg, pcix_cap, m66_cap);
++	    __func__, slot_reg, pcix_cap, m66_cap);
+ 
+ 	switch (pcix_cap) {
+ 	case 0x0:
+@@ -629,7 +629,7 @@ static int hpc_power_on_slot(struct slot * slot)
+ 
+ 	retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR);
+ 	if (retval)
+-		err("%s: Write command failed!\n", __FUNCTION__);
++		err("%s: Write command failed!\n", __func__);
+ 
+ 	return retval;
+ }
+@@ -642,7 +642,7 @@ static int hpc_slot_enable(struct slot * slot)
+ 	retval = shpc_write_cmd(slot, slot->hp_slot,
+ 			SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF);
+ 	if (retval)
+-		err("%s: Write command failed!\n", __FUNCTION__);
++		err("%s: Write command failed!\n", __func__);
+ 
+ 	return retval;
+ }
+@@ -655,7 +655,7 @@ static int hpc_slot_disable(struct slot * slot)
+ 	retval = shpc_write_cmd(slot, slot->hp_slot,
+ 			SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON);
+ 	if (retval)
+-		err("%s: Write command failed!\n", __FUNCTION__);
++		err("%s: Write command failed!\n", __func__);
+ 
+ 	return retval;
+ }
+@@ -719,7 +719,7 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
+ 
+ 	retval = shpc_write_cmd(slot, 0, cmd);
+ 	if (retval)
+-		err("%s: Write command failed!\n", __FUNCTION__);
++		err("%s: Write command failed!\n", __func__);
+ 
+ 	return retval;
+ }
+@@ -735,7 +735,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
+ 	if (!intr_loc)
+ 		return IRQ_NONE;
+ 
+-	dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc);
++	dbg("%s: intr_loc = %x\n",__func__, intr_loc);
+ 
+ 	if(!shpchp_poll_mode) {
+ 		/*
+@@ -748,7 +748,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
+ 		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
+ 
+ 		intr_loc2 = shpc_readl(ctrl, INTR_LOC);
+-		dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2);
++		dbg("%s: intr_loc2 = %x\n",__func__, intr_loc2);
+ 	}
+ 
+ 	if (intr_loc & CMD_INTR_PENDING) {
+@@ -774,7 +774,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
+ 
+ 		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
+ 		dbg("%s: Slot %x with intr, slot register = %x\n",
+-		    __FUNCTION__, hp_slot, slot_reg);
++		    __func__, hp_slot, slot_reg);
+ 
+ 		if (slot_reg & MRL_CHANGE_DETECTED)
+ 			shpchp_handle_switch_change(hp_slot, ctrl);
+@@ -958,33 +958,33 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ 	} else {
+ 		ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
+ 		if (!ctrl->cap_offset) {
+-			err("%s : cap_offset == 0\n", __FUNCTION__);
++			err("%s : cap_offset == 0\n", __func__);
+ 			goto abort;
+ 		}
+-		dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
++		dbg("%s: cap_offset = %x\n", __func__, ctrl->cap_offset);
+ 
+ 		rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
+ 		if (rc) {
+-			err("%s: cannot read base_offset\n", __FUNCTION__);
++			err("%s: cannot read base_offset\n", __func__);
+ 			goto abort;
+ 		}
+ 
+ 		rc = shpc_indirect_read(ctrl, 3, &tempdword);
+ 		if (rc) {
+-			err("%s: cannot read slot config\n", __FUNCTION__);
++			err("%s: cannot read slot config\n", __func__);
+ 			goto abort;
+ 		}
+ 		num_slots = tempdword & SLOT_NUM;
+-		dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
++		dbg("%s: num_slots (indirect) %x\n", __func__, num_slots);
+ 
+ 		for (i = 0; i < 9 + num_slots; i++) {
+ 			rc = shpc_indirect_read(ctrl, i, &tempdword);
+ 			if (rc) {
+ 				err("%s: cannot read creg (index = %d)\n",
+-				    __FUNCTION__, i);
++				    __func__, i);
+ 				goto abort;
+ 			}
+-			dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
++			dbg("%s: offset %d: value %x\n", __func__,i,
+ 					tempdword);
+ 		}
+ 
+@@ -998,25 +998,25 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ 
+ 	rc = pci_enable_device(pdev);
+ 	if (rc) {
+-		err("%s: pci_enable_device failed\n", __FUNCTION__);
++		err("%s: pci_enable_device failed\n", __func__);
+ 		goto abort;
+ 	}
+ 
+ 	if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
+-		err("%s: cannot reserve MMIO region\n", __FUNCTION__);
++		err("%s: cannot reserve MMIO region\n", __func__);
+ 		rc = -1;
+ 		goto abort;
+ 	}
+ 
+ 	ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
+ 	if (!ctrl->creg) {
+-		err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
++		err("%s: cannot remap MMIO region %lx @ %lx\n", __func__,
+ 		    ctrl->mmio_size, ctrl->mmio_base);
+ 		release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
+ 		rc = -1;
+ 		goto abort;
+ 	}
+-	dbg("%s: ctrl->creg %p\n", __FUNCTION__, ctrl->creg);
++	dbg("%s: ctrl->creg %p\n", __func__, ctrl->creg);
+ 
+ 	mutex_init(&ctrl->crit_sect);
+ 	mutex_init(&ctrl->cmd_lock);
+@@ -1035,20 +1035,20 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ 
+ 	/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
+ 	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
+-	dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
++	dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword);
+ 	tempdword |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
+ 		      COMMAND_INTR_MASK | ARBITER_SERR_MASK);
+ 	tempdword &= ~SERR_INTR_RSVDZ_MASK;
+ 	shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
+ 	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
+-	dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
++	dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword);
+ 
+ 	/* Mask the MRL sensor SERR Mask of individual slot in
+ 	 * Slot SERR-INT Mask & clear all the existing event if any
+ 	 */
+ 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
+ 		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
+-		dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
++		dbg("%s: Default Logical Slot Register %d value %x\n", __func__,
+ 			hp_slot, slot_reg);
+ 		slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+ 			     BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+@@ -1073,7 +1073,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ 		rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
+ 				 MY_NAME, (void *)ctrl);
+ 		dbg("%s: request_irq %d for hpc%d (returns %d)\n",
+-		    __FUNCTION__, ctrl->pci_dev->irq,
++		    __func__, ctrl->pci_dev->irq,
+ 		    atomic_read(&shpchp_num_controllers), rc);
+ 		if (rc) {
+ 			err("Can't get irq %d for the hotplug controller\n",
+@@ -1081,7 +1081,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ 			goto abort_iounmap;
+ 		}
+ 	}
+-	dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__,
++	dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__,
+ 			pdev->bus->number, PCI_SLOT(pdev->devfn),
+ 			PCI_FUNC(pdev->devfn), pdev->irq);
+ 	get_hp_hw_control_from_firmware(pdev);
+@@ -1103,7 +1103,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ 	 */
+ 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
+ 		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
+-		dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
++		dbg("%s: Default Logical Slot Register %d value %x\n", __func__,
+ 			hp_slot, slot_reg);
+ 		slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+ 			      BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+@@ -1117,7 +1117,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ 			       SERR_INTR_RSVDZ_MASK);
+ 		shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
+ 		tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
+-		dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
++		dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword);
+ 	}
+ 
+ 	return 0;
+diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
+index a69a215..3fc4ec0 100644
+--- a/drivers/pci/hotplug/shpchp_pci.c
++++ b/drivers/pci/hotplug/shpchp_pci.c
+@@ -51,7 +51,7 @@ static void program_fw_provided_values(struct pci_dev *dev)
+ 	    !hpp.t0 || (hpp.t0->revision > 1)) {
+ 		printk(KERN_WARNING
+ 		       "%s: Could not get hotplug parameters. Use defaults\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		hpp.t0 = &hpp.type0_data;
+ 		hpp.t0->revision = 0;
+ 		hpp.t0->cache_line_size = 8;
+@@ -169,7 +169,7 @@ int shpchp_unconfigure_device(struct slot *p_slot)
+ 	u8 bctl = 0;
+ 	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ 
+-	dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device);
++	dbg("%s: bus/dev = %x/%x\n", __func__, p_slot->bus, p_slot->device);
+ 
+ 	for (j=0; j<8 ; j++) {
+ 		struct pci_dev* temp = pci_get_slot(parent,
+diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
+index 4cb949f..1fd8bb7 100644
+--- a/drivers/pci/intel-iommu.c
++++ b/drivers/pci/intel-iommu.c
+@@ -22,6 +22,7 @@
+ 
+ #include <linux/init.h>
+ #include <linux/bitmap.h>
++#include <linux/debugfs.h>
+ #include <linux/slab.h>
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
+@@ -31,6 +32,7 @@
+ #include <linux/dmar.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/mempool.h>
++#include <linux/timer.h>
+ #include "iova.h"
+ #include "intel-iommu.h"
+ #include <asm/proto.h> /* force_iommu in this header in x86-64*/
+@@ -51,11 +53,37 @@
+ 
+ #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
+ 
++
++static void flush_unmaps_timeout(unsigned long data);
++
++DEFINE_TIMER(unmap_timer,  flush_unmaps_timeout, 0, 0);
++
++static struct intel_iommu *g_iommus;
++
++#define HIGH_WATER_MARK 250
++struct deferred_flush_tables {
++	int next;
++	struct iova *iova[HIGH_WATER_MARK];
++	struct dmar_domain *domain[HIGH_WATER_MARK];
++};
++
++static struct deferred_flush_tables *deferred_flush;
++
++/* bitmap for indexing intel_iommus */
++static int g_num_of_iommus;
++
++static DEFINE_SPINLOCK(async_umap_flush_lock);
++static LIST_HEAD(unmaps_to_do);
++
++static int timer_on;
++static long list_size;
++
+ static void domain_remove_dev_info(struct dmar_domain *domain);
+ 
+ static int dmar_disabled;
+ static int __initdata dmar_map_gfx = 1;
+ static int dmar_forcedac;
++static int intel_iommu_strict;
+ 
+ #define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
+ static DEFINE_SPINLOCK(device_domain_lock);
+@@ -74,9 +102,13 @@ static int __init intel_iommu_setup(char *str)
+ 			printk(KERN_INFO
+ 				"Intel-IOMMU: disable GFX device mapping\n");
+ 		} else if (!strncmp(str, "forcedac", 8)) {
+-			printk (KERN_INFO
++			printk(KERN_INFO
+ 				"Intel-IOMMU: Forcing DAC for PCI devices\n");
+ 			dmar_forcedac = 1;
++		} else if (!strncmp(str, "strict", 6)) {
++			printk(KERN_INFO
++				"Intel-IOMMU: disable batched IOTLB flush\n");
++			intel_iommu_strict = 1;
+ 		}
+ 
+ 		str += strcspn(str, ",");
+@@ -966,17 +998,13 @@ static int iommu_init_domains(struct intel_iommu *iommu)
+ 		set_bit(0, iommu->domain_ids);
+ 	return 0;
+ }
+-
+-static struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
++static struct intel_iommu *alloc_iommu(struct intel_iommu *iommu,
++					struct dmar_drhd_unit *drhd)
+ {
+-	struct intel_iommu *iommu;
+ 	int ret;
+ 	int map_size;
+ 	u32 ver;
+ 
+-	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+-	if (!iommu)
+-		return NULL;
+ 	iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K);
+ 	if (!iommu->reg) {
+ 		printk(KERN_ERR "IOMMU: can't map the region\n");
+@@ -1404,7 +1432,7 @@ static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
+ 	int index;
+ 
+ 	while (dev) {
+-		for (index = 0; index < cnt; index ++)
++		for (index = 0; index < cnt; index++)
+ 			if (dev == devices[index])
+ 				return 1;
+ 
+@@ -1669,7 +1697,7 @@ int __init init_dmars(void)
+ 	struct dmar_rmrr_unit *rmrr;
+ 	struct pci_dev *pdev;
+ 	struct intel_iommu *iommu;
+-	int ret, unit = 0;
++	int i, ret, unit = 0;
+ 
+ 	/*
+ 	 * for each drhd
+@@ -1680,7 +1708,34 @@ int __init init_dmars(void)
+ 	for_each_drhd_unit(drhd) {
+ 		if (drhd->ignored)
+ 			continue;
+-		iommu = alloc_iommu(drhd);
++		g_num_of_iommus++;
++		/*
++		 * lock not needed as this is only incremented in the single
++		 * threaded kernel __init code path all other access are read
++		 * only
++		 */
++	}
++
++	g_iommus = kzalloc(g_num_of_iommus * sizeof(*iommu), GFP_KERNEL);
++	if (!g_iommus) {
++		ret = -ENOMEM;
++		goto error;
++	}
++
++	deferred_flush = kzalloc(g_num_of_iommus *
++		sizeof(struct deferred_flush_tables), GFP_KERNEL);
++	if (!deferred_flush) {
++		kfree(g_iommus);
++		ret = -ENOMEM;
++		goto error;
++	}
++
++	i = 0;
++	for_each_drhd_unit(drhd) {
++		if (drhd->ignored)
++			continue;
++		iommu = alloc_iommu(&g_iommus[i], drhd);
++		i++;
+ 		if (!iommu) {
+ 			ret = -ENOMEM;
+ 			goto error;
+@@ -1713,7 +1768,6 @@ int __init init_dmars(void)
+ 	 * endfor
+ 	 */
+ 	for_each_rmrr_units(rmrr) {
+-		int i;
+ 		for (i = 0; i < rmrr->devices_cnt; i++) {
+ 			pdev = rmrr->devices[i];
+ 			/* some BIOS lists non-exist devices in DMAR table */
+@@ -1769,6 +1823,7 @@ error:
+ 		iommu = drhd->iommu;
+ 		free_iommu(iommu);
+ 	}
++	kfree(g_iommus);
+ 	return ret;
+ }
+ 
+@@ -1850,32 +1905,31 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
+ 	return domain;
+ }
+ 
+-static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
+-	size_t size, int dir)
++static dma_addr_t
++intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
+ {
+ 	struct pci_dev *pdev = to_pci_dev(hwdev);
+-	int ret;
+ 	struct dmar_domain *domain;
+-	unsigned long start_addr;
++	unsigned long start_paddr;
+ 	struct iova *iova;
+ 	int prot = 0;
++	int ret;
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
+-		return virt_to_bus(addr);
++		return paddr;
+ 
+ 	domain = get_valid_domain_for_dev(pdev);
+ 	if (!domain)
+ 		return 0;
+ 
+-	addr = (void *)virt_to_phys(addr);
+-	size = aligned_size((u64)addr, size);
++	size = aligned_size((u64)paddr, size);
+ 
+ 	iova = __intel_alloc_iova(hwdev, domain, size);
+ 	if (!iova)
+ 		goto error;
+ 
+-	start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
++	start_paddr = iova->pfn_lo << PAGE_SHIFT_4K;
+ 
+ 	/*
+ 	 * Check if DMAR supports zero-length reads on write only
+@@ -1887,36 +1941,89 @@ static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
+ 	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
+ 		prot |= DMA_PTE_WRITE;
+ 	/*
+-	 * addr - (addr + size) might be partial page, we should map the whole
++	 * paddr - (paddr + size) might be partial page, we should map the whole
+ 	 * page.  Note: if two part of one page are separately mapped, we
+-	 * might have two guest_addr mapping to the same host addr, but this
++	 * might have two guest_addr mapping to the same host paddr, but this
+ 	 * is not a big problem
+ 	 */
+-	ret = domain_page_mapping(domain, start_addr,
+-		((u64)addr) & PAGE_MASK_4K, size, prot);
++	ret = domain_page_mapping(domain, start_paddr,
++		((u64)paddr) & PAGE_MASK_4K, size, prot);
+ 	if (ret)
+ 		goto error;
+ 
+ 	pr_debug("Device %s request: %lx@%llx mapping: %lx@%llx, dir %d\n",
+-		pci_name(pdev), size, (u64)addr,
+-		size, (u64)start_addr, dir);
++		pci_name(pdev), size, (u64)paddr,
++		size, (u64)start_paddr, dir);
+ 
+ 	/* it's a non-present to present mapping */
+ 	ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
+-			start_addr, size >> PAGE_SHIFT_4K, 1);
++			start_paddr, size >> PAGE_SHIFT_4K, 1);
+ 	if (ret)
+ 		iommu_flush_write_buffer(domain->iommu);
+ 
+-	return (start_addr + ((u64)addr & (~PAGE_MASK_4K)));
++	return (start_paddr + ((u64)paddr & (~PAGE_MASK_4K)));
+ 
+ error:
+ 	if (iova)
+ 		__free_iova(&domain->iovad, iova);
+ 	printk(KERN_ERR"Device %s request: %lx@%llx dir %d --- failed\n",
+-		pci_name(pdev), size, (u64)addr, dir);
++		pci_name(pdev), size, (u64)paddr, dir);
+ 	return 0;
+ }
+ 
++static void flush_unmaps(void)
++{
++	int i, j;
++
++	timer_on = 0;
++
++	/* just flush them all */
++	for (i = 0; i < g_num_of_iommus; i++) {
++		if (deferred_flush[i].next) {
++			iommu_flush_iotlb_global(&g_iommus[i], 0);
++			for (j = 0; j < deferred_flush[i].next; j++) {
++				__free_iova(&deferred_flush[i].domain[j]->iovad,
++						deferred_flush[i].iova[j]);
++			}
++			deferred_flush[i].next = 0;
++		}
++	}
++
++	list_size = 0;
++}
++
++static void flush_unmaps_timeout(unsigned long data)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&async_umap_flush_lock, flags);
++	flush_unmaps();
++	spin_unlock_irqrestore(&async_umap_flush_lock, flags);
++}
++
++static void add_unmap(struct dmar_domain *dom, struct iova *iova)
++{
++	unsigned long flags;
++	int next, iommu_id;
++
++	spin_lock_irqsave(&async_umap_flush_lock, flags);
++	if (list_size == HIGH_WATER_MARK)
++		flush_unmaps();
++
++	iommu_id = dom->iommu - g_iommus;
++	next = deferred_flush[iommu_id].next;
++	deferred_flush[iommu_id].domain[next] = dom;
++	deferred_flush[iommu_id].iova[next] = iova;
++	deferred_flush[iommu_id].next++;
++
++	if (!timer_on) {
++		mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
++		timer_on = 1;
++	}
++	list_size++;
++	spin_unlock_irqrestore(&async_umap_flush_lock, flags);
++}
++
+ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
+ 	size_t size, int dir)
+ {
+@@ -1944,13 +2051,19 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
+ 	dma_pte_clear_range(domain, start_addr, start_addr + size);
+ 	/* free page tables */
+ 	dma_pte_free_pagetable(domain, start_addr, start_addr + size);
+-
+-	if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
+-			size >> PAGE_SHIFT_4K, 0))
+-		iommu_flush_write_buffer(domain->iommu);
+-
+-	/* free iova */
+-	__free_iova(&domain->iovad, iova);
++	if (intel_iommu_strict) {
++		if (iommu_flush_iotlb_psi(domain->iommu,
++			domain->id, start_addr, size >> PAGE_SHIFT_4K, 0))
++			iommu_flush_write_buffer(domain->iommu);
++		/* free iova */
++		__free_iova(&domain->iovad, iova);
++	} else {
++		add_unmap(domain, iova);
++		/*
++		 * queue up the release of the unmap to save the 1/6th of the
++		 * cpu used up by the iotlb flush operation...
++		 */
++	}
+ }
+ 
+ static void * intel_alloc_coherent(struct device *hwdev, size_t size,
+@@ -1968,7 +2081,7 @@ static void * intel_alloc_coherent(struct device *hwdev, size_t size,
+ 		return NULL;
+ 	memset(vaddr, 0, size);
+ 
+-	*dma_handle = intel_map_single(hwdev, vaddr, size, DMA_BIDIRECTIONAL);
++	*dma_handle = intel_map_single(hwdev, virt_to_bus(vaddr), size, DMA_BIDIRECTIONAL);
+ 	if (*dma_handle)
+ 		return vaddr;
+ 	free_pages((unsigned long)vaddr, order);
+@@ -2289,6 +2402,7 @@ int __init intel_iommu_init(void)
+ 	printk(KERN_INFO
+ 	"PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
+ 
++	init_timer(&unmap_timer);
+ 	force_iommu = 1;
+ 	dma_ops = &intel_dma_ops;
+ 	return 0;
+diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c
+index dbcdd6b..3ef4ac0 100644
+--- a/drivers/pci/iova.c
++++ b/drivers/pci/iova.c
+@@ -73,10 +73,11 @@ iova_get_pad_size(int size, unsigned int limit_pfn)
+ 	return pad_size;
+ }
+ 
+-static int __alloc_iova_range(struct iova_domain *iovad, unsigned long size,
+-		unsigned long limit_pfn, struct iova *new, bool size_aligned)
++static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
++		unsigned long size, unsigned long limit_pfn,
++			struct iova *new, bool size_aligned)
+ {
+-	struct rb_node *curr = NULL;
++	struct rb_node *prev, *curr = NULL;
+ 	unsigned long flags;
+ 	unsigned long saved_pfn;
+ 	unsigned int pad_size = 0;
+@@ -85,8 +86,10 @@ static int __alloc_iova_range(struct iova_domain *iovad, unsigned long size,
+ 	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+ 	saved_pfn = limit_pfn;
+ 	curr = __get_cached_rbnode(iovad, &limit_pfn);
++	prev = curr;
+ 	while (curr) {
+ 		struct iova *curr_iova = container_of(curr, struct iova, node);
++
+ 		if (limit_pfn < curr_iova->pfn_lo)
+ 			goto move_left;
+ 		else if (limit_pfn < curr_iova->pfn_hi)
+@@ -100,6 +103,7 @@ static int __alloc_iova_range(struct iova_domain *iovad, unsigned long size,
+ adjust_limit_pfn:
+ 		limit_pfn = curr_iova->pfn_lo - 1;
+ move_left:
++		prev = curr;
+ 		curr = rb_prev(curr);
+ 	}
+ 
+@@ -116,7 +120,33 @@ move_left:
+ 	new->pfn_lo = limit_pfn - (size + pad_size) + 1;
+ 	new->pfn_hi = new->pfn_lo + size - 1;
+ 
++	/* Insert the new_iova into domain rbtree by holding writer lock */
++	/* Add new node and rebalance tree. */
++	{
++		struct rb_node **entry = &((prev)), *parent = NULL;
++		/* Figure out where to put new node */
++		while (*entry) {
++			struct iova *this = container_of(*entry,
++							struct iova, node);
++			parent = *entry;
++
++			if (new->pfn_lo < this->pfn_lo)
++				entry = &((*entry)->rb_left);
++			else if (new->pfn_lo > this->pfn_lo)
++				entry = &((*entry)->rb_right);
++			else
++				BUG(); /* this should not happen */
++		}
++
++		/* Add new node and rebalance tree. */
++		rb_link_node(&new->node, parent, entry);
++		rb_insert_color(&new->node, &iovad->rbroot);
++	}
++	__cached_rbnode_insert_update(iovad, saved_pfn, new);
++
+ 	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
++
++
+ 	return 0;
+ }
+ 
+@@ -172,23 +202,15 @@ alloc_iova(struct iova_domain *iovad, unsigned long size,
+ 		size = __roundup_pow_of_two(size);
+ 
+ 	spin_lock_irqsave(&iovad->iova_alloc_lock, flags);
+-	ret = __alloc_iova_range(iovad, size, limit_pfn, new_iova,
+-			size_aligned);
++	ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn,
++			new_iova, size_aligned);
+ 
++	spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+ 	if (ret) {
+-		spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+ 		free_iova_mem(new_iova);
+ 		return NULL;
+ 	}
+ 
+-	/* Insert the new_iova into domain rbtree by holding writer lock */
+-	spin_lock(&iovad->iova_rbtree_lock);
+-	iova_insert_rbtree(&iovad->rbroot, new_iova);
+-	__cached_rbnode_insert_update(iovad, limit_pfn, new_iova);
+-	spin_unlock(&iovad->iova_rbtree_lock);
+-
+-	spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+-
+ 	return new_iova;
+ }
+ 
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index e571c72..e8d94fa 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -182,15 +182,18 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
+ 	struct mempolicy *oldpol;
+ 	cpumask_t oldmask = current->cpus_allowed;
+ 	int node = pcibus_to_node(dev->bus);
+-	if (node >= 0 && node_online(node))
+-	    set_cpus_allowed(current, node_to_cpumask(node));
++
++	if (node >= 0) {
++		node_to_cpumask_ptr(nodecpumask, node);
++		set_cpus_allowed_ptr(current, nodecpumask);
++	}
+ 	/* And set default memory allocation policy */
+ 	oldpol = current->mempolicy;
+ 	current->mempolicy = NULL;	/* fall back to system default policy */
+ #endif
+ 	error = drv->probe(dev, id);
+ #ifdef CONFIG_NUMA
+-	set_cpus_allowed(current, oldmask);
++	set_cpus_allowed_ptr(current, &oldmask);
+ 	current->mempolicy = oldpol;
+ #endif
+ 	return error;
+diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
+index 8dcf145..271d41c 100644
+--- a/drivers/pci/pci-sysfs.c
++++ b/drivers/pci/pci-sysfs.c
+@@ -21,6 +21,7 @@
+ #include <linux/topology.h>
+ #include <linux/mm.h>
+ #include <linux/capability.h>
++#include <linux/pci-aspm.h>
+ #include "pci.h"
+ 
+ static int sysfs_initialized;	/* = 0 */
+@@ -73,8 +74,23 @@ static ssize_t local_cpus_show(struct device *dev,
+ 
+ 	mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
+ 	len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
+-	strcat(buf,"\n"); 
+-	return 1+len;
++	buf[len++] = '\n';
++	buf[len] = '\0';
++	return len;
++}
++
++
++static ssize_t local_cpulist_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	cpumask_t mask;
++	int len;
++
++	mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
++	len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask);
++	buf[len++] = '\n';
++	buf[len] = '\0';
++	return len;
+ }
+ 
+ /* show resources */
+@@ -201,6 +217,7 @@ struct device_attribute pci_dev_attrs[] = {
+ 	__ATTR_RO(class),
+ 	__ATTR_RO(irq),
+ 	__ATTR_RO(local_cpus),
++	__ATTR_RO(local_cpulist),
+ 	__ATTR_RO(modalias),
+ #ifdef CONFIG_NUMA
+ 	__ATTR_RO(numa_node),
+@@ -342,6 +359,58 @@ pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+ 	return count;
+ }
+ 
++static ssize_t
++pci_read_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
++	     char *buf, loff_t off, size_t count)
++{
++	struct pci_dev *dev =
++		to_pci_dev(container_of(kobj, struct device, kobj));
++	int end;
++	int ret;
++
++	if (off > bin_attr->size)
++		count = 0;
++	else if (count > bin_attr->size - off)
++		count = bin_attr->size - off;
++	end = off + count;
++
++	while (off < end) {
++		ret = dev->vpd->ops->read(dev, off, end - off, buf);
++		if (ret < 0)
++			return ret;
++		buf += ret;
++		off += ret;
++	}
++
++	return count;
++}
++
++static ssize_t
++pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
++	      char *buf, loff_t off, size_t count)
++{
++	struct pci_dev *dev =
++		to_pci_dev(container_of(kobj, struct device, kobj));
++	int end;
++	int ret;
++
++	if (off > bin_attr->size)
++		count = 0;
++	else if (count > bin_attr->size - off)
++		count = bin_attr->size - off;
++	end = off + count;
++
++	while (off < end) {
++		ret = dev->vpd->ops->write(dev, off, end - off, buf);
++		if (ret < 0)
++			return ret;
++		buf += ret;
++		off += ret;
++	}
++
++	return count;
++}
++
+ #ifdef HAVE_PCI_LEGACY
+ /**
+  * pci_read_legacy_io - read byte(s) from legacy I/O port space
+@@ -610,7 +679,7 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
+ 
+ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
+ {
+-	struct bin_attribute *rom_attr = NULL;
++	struct bin_attribute *attr = NULL;
+ 	int retval;
+ 
+ 	if (!sysfs_initialized)
+@@ -623,22 +692,41 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
+ 	if (retval)
+ 		goto err;
+ 
++	/* If the device has VPD, try to expose it in sysfs. */
++	if (pdev->vpd) {
++		attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
++		if (attr) {
++			pdev->vpd->attr = attr;
++			attr->size = pdev->vpd->ops->get_size(pdev);
++			attr->attr.name = "vpd";
++			attr->attr.mode = S_IRUGO | S_IWUSR;
++			attr->read = pci_read_vpd;
++			attr->write = pci_write_vpd;
++			retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
++			if (retval)
++				goto err_vpd;
++		} else {
++			retval = -ENOMEM;
++			goto err_config_file;
++		}
++	}
++
+ 	retval = pci_create_resource_files(pdev);
+ 	if (retval)
+-		goto err_bin_file;
++		goto err_vpd_file;
+ 
+ 	/* If the device has a ROM, try to expose it in sysfs. */
+ 	if (pci_resource_len(pdev, PCI_ROM_RESOURCE) ||
+ 	    (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
+-		rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
+-		if (rom_attr) {
+-			pdev->rom_attr = rom_attr;
+-			rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+-			rom_attr->attr.name = "rom";
+-			rom_attr->attr.mode = S_IRUSR;
+-			rom_attr->read = pci_read_rom;
+-			rom_attr->write = pci_write_rom;
+-			retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
++		attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
++		if (attr) {
++			pdev->rom_attr = attr;
++			attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
++			attr->attr.name = "rom";
++			attr->attr.mode = S_IRUSR;
++			attr->read = pci_read_rom;
++			attr->write = pci_write_rom;
++			retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
+ 			if (retval)
+ 				goto err_rom;
+ 		} else {
+@@ -650,16 +738,24 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
+ 	if (pcibios_add_platform_entries(pdev))
+ 		goto err_rom_file;
+ 
++	pcie_aspm_create_sysfs_dev_files(pdev);
++
+ 	return 0;
+ 
+ err_rom_file:
+ 	if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+-		sysfs_remove_bin_file(&pdev->dev.kobj, rom_attr);
++		sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
+ err_rom:
+-	kfree(rom_attr);
++	kfree(pdev->rom_attr);
+ err_resource_files:
+ 	pci_remove_resource_files(pdev);
+-err_bin_file:
++err_vpd_file:
++	if (pdev->vpd) {
++		sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
++err_vpd:
++		kfree(pdev->vpd->attr);
++	}
++err_config_file:
+ 	if (pdev->cfg_size < 4096)
+ 		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
+ 	else
+@@ -679,6 +775,12 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
+ 	if (!sysfs_initialized)
+ 		return;
+ 
++	pcie_aspm_remove_sysfs_dev_files(pdev);
++
++	if (pdev->vpd) {
++		sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
++		kfree(pdev->vpd->attr);
++	}
+ 	if (pdev->cfg_size < 4096)
+ 		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
+ 	else
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index a4445b7..e4548ab 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -18,6 +18,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/string.h>
+ #include <linux/log2.h>
++#include <linux/pci-aspm.h>
+ #include <asm/dma.h>	/* isa_dma_bridge_buggy */
+ #include "pci.h"
+ 
+@@ -424,7 +425,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
+ 	 */
+ 	if (state != PCI_D0 && dev->current_state > state) {
+ 		printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n",
+-			__FUNCTION__, pci_name(dev), state, dev->current_state);
++			__func__, pci_name(dev), state, dev->current_state);
+ 		return -EINVAL;
+ 	} else if (dev->current_state == state)
+ 		return 0;        /* we're already there */
+@@ -501,6 +502,9 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
+ 	if (need_restore)
+ 		pci_restore_bars(dev);
+ 
++	if (dev->bus->self)
++		pcie_aspm_pm_state_change(dev->bus->self);
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
+index eabeb1f..0a497c1 100644
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -18,6 +18,25 @@ extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
+ extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
+ extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
+ 
++struct pci_vpd_ops {
++	int (*read)(struct pci_dev *dev, int pos, int size, char *buf);
++	int (*write)(struct pci_dev *dev, int pos, int size, const char *buf);
++	int (*get_size)(struct pci_dev *dev);
++	void (*release)(struct pci_dev *dev);
++};
++
++struct pci_vpd {
++	struct pci_vpd_ops *ops;
++	struct bin_attribute *attr; /* descriptor for sysfs VPD entry */
++};
++
++extern int pci_vpd_pci22_init(struct pci_dev *dev);
++static inline void pci_vpd_release(struct pci_dev *dev)
++{
++	if (dev->vpd)
++		dev->vpd->ops->release(dev);
++}
++
+ /* PCI /proc functions */
+ #ifdef CONFIG_PROC_FS
+ extern int pci_proc_attach_device(struct pci_dev *dev);
+diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
+index 287a931..25b04fb 100644
+--- a/drivers/pci/pcie/Kconfig
++++ b/drivers/pci/pcie/Kconfig
+@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE
+ 	  When in doubt, say N.
+ 
+ source "drivers/pci/pcie/aer/Kconfig"
++
++#
++# PCI Express ASPM
++#
++config PCIEASPM
++	bool "PCI Express ASPM support(Experimental)"
++	depends on PCI && EXPERIMENTAL && PCIEPORTBUS
++	default y
++	help
++	  This enables PCI Express ASPM (Active State Power Management) and
++	  Clock Power Management. ASPM supports state L0/L0s/L1.
++
++	  When in doubt, say N.
++config PCIEASPM_DEBUG
++	bool "Debug PCI Express ASPM"
++	depends on PCIEASPM
++	default n
++	help
++	  This enables PCI Express ASPM debug support. It will add per-device
++	  interface to control ASPM.
+diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
+index e00fb99..11f6bb1 100644
+--- a/drivers/pci/pcie/Makefile
++++ b/drivers/pci/pcie/Makefile
+@@ -2,6 +2,9 @@
+ # Makefile for PCI-Express PORT Driver
+ #
+ 
++# Build PCI Express ASPM if needed
++obj-$(CONFIG_PCIEASPM)		+= aspm.o
++
+ pcieportdrv-y			:= portdrv_core.o portdrv_pci.o portdrv_bus.o
+ 
+ obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o
+diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
+index 7a62f7d..07c3bdb 100644
+--- a/drivers/pci/pcie/aer/aerdrv.c
++++ b/drivers/pci/pcie/aer/aerdrv.c
+@@ -220,7 +220,7 @@ static int __devinit aer_probe (struct pcie_device *dev,
+ 	/* Alloc rpc data structure */
+ 	if (!(rpc = aer_alloc_rpc(dev))) {
+ 		printk(KERN_DEBUG "%s: Alloc rpc fails on PCIE device[%s]\n",
+-			__FUNCTION__, device->bus_id);
++			__func__, device->bus_id);
+ 		aer_remove(dev);
+ 		return -ENOMEM;
+ 	}
+@@ -229,7 +229,7 @@ static int __devinit aer_probe (struct pcie_device *dev,
+ 	if ((status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv",
+ 				dev))) {
+ 		printk(KERN_DEBUG "%s: Request ISR fails on PCIE device[%s]\n",
+-			__FUNCTION__, device->bus_id);
++			__func__, device->bus_id);
+ 		aer_remove(dev);
+ 		return status;
+ 	}
+diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
+index 8c199ae..96ac540 100644
+--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
++++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
+@@ -33,8 +33,11 @@ int aer_osc_setup(struct pcie_device *pciedev)
+ 	struct pci_dev *pdev = pciedev->port;
+ 	acpi_handle handle = 0;
+ 
++	if (acpi_pci_disabled)
++		return -1;
++
+ 	/* Find root host bridge */
+-	while (pdev->bus && pdev->bus->self)
++	while (pdev->bus->self)
+ 		pdev = pdev->bus->self;
+ 	handle = acpi_get_pci_rootbridge_handle(
+ 		pci_domain_nr(pdev->bus), pdev->bus->number);
+diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
+index 3c0d8d1..aaa8239 100644
+--- a/drivers/pci/pcie/aer/aerdrv_core.c
++++ b/drivers/pci/pcie/aer/aerdrv_core.c
+@@ -117,6 +117,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
+ 	return 0;
+ }
+ 
++#if 0
+ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
+ {
+ 	int pos;
+@@ -131,6 +132,7 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
+ 
+ 	return 0;
+ }
++#endif  /*  0  */
+ 
+ static int find_device_iter(struct device *device, void *data)
+ {
+@@ -689,7 +691,7 @@ static void aer_isr_one_error(struct pcie_device *p_device,
+ 			e_info.flags |= AER_MULTI_ERROR_VALID_FLAG;
+ 		if (!(s_device = find_source_device(p_device->port, id))) {
+ 			printk(KERN_DEBUG "%s->can't find device of ID%04x\n",
+-				__FUNCTION__, id);
++				__func__, id);
+ 			continue;
+ 		}
+ 		if (get_device_error_info(to_pci_dev(s_device), &e_info) ==
+@@ -757,5 +759,4 @@ EXPORT_SYMBOL_GPL(pci_find_aer_capability);
+ EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
+ EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
+ EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
+-EXPORT_SYMBOL_GPL(pci_cleanup_aer_correct_error_status);
+ 
+diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
+new file mode 100644
+index 0000000..61fedb2
+--- /dev/null
++++ b/drivers/pci/pcie/aspm.c
+@@ -0,0 +1,811 @@
++/*
++ * File:	drivers/pci/pcie/aspm.c
++ * Enabling PCIE link L0s/L1 state and Clock Power Management
++ *
++ * Copyright (C) 2007 Intel
++ * Copyright (C) Zhang Yanmin (yanmin.zhang at intel.com)
++ * Copyright (C) Shaohua Li (shaohua.li at intel.com)
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/pci.h>
++#include <linux/pci_regs.h>
++#include <linux/errno.h>
++#include <linux/pm.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/pci-aspm.h>
++#include "../pci.h"
++
++#ifdef MODULE_PARAM_PREFIX
++#undef MODULE_PARAM_PREFIX
++#endif
++#define MODULE_PARAM_PREFIX "pcie_aspm."
++
++struct endpoint_state {
++	unsigned int l0s_acceptable_latency;
++	unsigned int l1_acceptable_latency;
++};
++
++struct pcie_link_state {
++	struct list_head sibiling;
++	struct pci_dev *pdev;
++
++	/* ASPM state */
++	unsigned int support_state;
++	unsigned int enabled_state;
++	unsigned int bios_aspm_state;
++	/* upstream component */
++	unsigned int l0s_upper_latency;
++	unsigned int l1_upper_latency;
++	/* downstream component */
++	unsigned int l0s_down_latency;
++	unsigned int l1_down_latency;
++	/* Clock PM state*/
++	unsigned int clk_pm_capable;
++	unsigned int clk_pm_enabled;
++	unsigned int bios_clk_state;
++
++	/*
++	 * A pcie downstream port only has one slot under it, so at most there
++	 * are 8 functions
++	 */
++	struct endpoint_state endpoints[8];
++};
++
++static int aspm_disabled;
++static DEFINE_MUTEX(aspm_lock);
++static LIST_HEAD(link_list);
++
++#define POLICY_DEFAULT 0	/* BIOS default setting */
++#define POLICY_PERFORMANCE 1	/* high performance */
++#define POLICY_POWERSAVE 2	/* high power saving */
++static int aspm_policy;
++static const char *policy_str[] = {
++	[POLICY_DEFAULT] = "default",
++	[POLICY_PERFORMANCE] = "performance",
++	[POLICY_POWERSAVE] = "powersave"
++};
++
++static int policy_to_aspm_state(struct pci_dev *pdev)
++{
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	switch (aspm_policy) {
++	case POLICY_PERFORMANCE:
++		/* Disable ASPM and Clock PM */
++		return 0;
++	case POLICY_POWERSAVE:
++		/* Enable ASPM L0s/L1 */
++		return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
++	case POLICY_DEFAULT:
++		return link_state->bios_aspm_state;
++	}
++	return 0;
++}
++
++static int policy_to_clkpm_state(struct pci_dev *pdev)
++{
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	switch (aspm_policy) {
++	case POLICY_PERFORMANCE:
++		/* Disable ASPM and Clock PM */
++		return 0;
++	case POLICY_POWERSAVE:
++		/* Disable Clock PM */
++		return 1;
++	case POLICY_DEFAULT:
++		return link_state->bios_clk_state;
++	}
++	return 0;
++}
++
++static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
++{
++	struct pci_dev *child_dev;
++	int pos;
++	u16 reg16;
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++		if (!pos)
++			return;
++		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
++		if (enable)
++			reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
++		else
++			reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
++		pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
++	}
++	link_state->clk_pm_enabled = !!enable;
++}
++
++static void pcie_check_clock_pm(struct pci_dev *pdev)
++{
++	int pos;
++	u32 reg32;
++	u16 reg16;
++	int capable = 1, enabled = 1;
++	struct pci_dev *child_dev;
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	/* All functions should have the same cap and state, take the worst */
++	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++		if (!pos)
++			return;
++		pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, &reg32);
++		if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
++			capable = 0;
++			enabled = 0;
++			break;
++		}
++		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
++		if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
++			enabled = 0;
++	}
++	link_state->clk_pm_capable = capable;
++	link_state->clk_pm_enabled = enabled;
++	link_state->bios_clk_state = enabled;
++	pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
++}
++
++/*
++ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
++ *   could use common clock. If they are, configure them to use the
++ *   common clock. That will reduce the ASPM state exit latency.
++ */
++static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
++{
++	int pos, child_pos;
++	u16 reg16 = 0;
++	struct pci_dev *child_dev;
++	int same_clock = 1;
++
++	/*
++	 * all functions of a slot should have the same Slot Clock
++	 * Configuration, so just check one function
++	 * */
++	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
++		bus_list);
++	BUG_ON(!child_dev->is_pcie);
++
++	/* Check downstream component if bit Slot Clock Configuration is 1 */
++	child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++	pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, &reg16);
++	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
++		same_clock = 0;
++
++	/* Check upstream component if bit Slot Clock Configuration is 1 */
++	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
++	pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
++	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
++		same_clock = 0;
++
++	/* Configure downstream component, all functions */
++	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++		child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++		pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
++			&reg16);
++		if (same_clock)
++			reg16 |= PCI_EXP_LNKCTL_CCC;
++		else
++			reg16 &= ~PCI_EXP_LNKCTL_CCC;
++		pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
++			reg16);
++	}
++
++	/* Configure upstream component */
++	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
++	if (same_clock)
++		reg16 |= PCI_EXP_LNKCTL_CCC;
++	else
++		reg16 &= ~PCI_EXP_LNKCTL_CCC;
++	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
++
++	/* retrain link */
++	reg16 |= PCI_EXP_LNKCTL_RL;
++	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
++
++	/* Wait for link training end */
++	while (1) {
++		pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
++		if (!(reg16 & PCI_EXP_LNKSTA_LT))
++			break;
++		cpu_relax();
++	}
++}
++
++/*
++ * calc_L0S_latency: Convert L0s latency encoding to ns
++ */
++static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
++{
++	unsigned int ns = 64;
++
++	if (latency_encoding == 0x7) {
++		if (ac)
++			ns = -1U;
++		else
++			ns = 5*1000; /* > 4us */
++	} else
++		ns *= (1 << latency_encoding);
++	return ns;
++}
++
++/*
++ * calc_L1_latency: Convert L1 latency encoding to ns
++ */
++static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
++{
++	unsigned int ns = 1000;
++
++	if (latency_encoding == 0x7) {
++		if (ac)
++			ns = -1U;
++		else
++			ns = 65*1000; /* > 64us */
++	} else
++		ns *= (1 << latency_encoding);
++	return ns;
++}
++
++static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
++	unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
++{
++	int pos;
++	u16 reg16;
++	u32 reg32;
++	unsigned int latency;
++
++	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
++	pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
++	*state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
++	if (*state != PCIE_LINK_STATE_L0S &&
++		*state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
++		*state = 0;
++	if (*state == 0)
++		return;
++
++	latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
++	*l0s = calc_L0S_latency(latency, 0);
++	if (*state & PCIE_LINK_STATE_L1) {
++		latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
++		*l1 = calc_L1_latency(latency, 0);
++	}
++	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
++	*enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
++}
++
++static void pcie_aspm_cap_init(struct pci_dev *pdev)
++{
++	struct pci_dev *child_dev;
++	u32 state, tmp;
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	/* upstream component states */
++	pcie_aspm_get_cap_device(pdev, &link_state->support_state,
++		&link_state->l0s_upper_latency,
++		&link_state->l1_upper_latency,
++		&link_state->enabled_state);
++	/* downstream component states, all functions have the same setting */
++	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
++		bus_list);
++	pcie_aspm_get_cap_device(child_dev, &state,
++		&link_state->l0s_down_latency,
++		&link_state->l1_down_latency,
++		&tmp);
++	link_state->support_state &= state;
++	if (!link_state->support_state)
++		return;
++	link_state->enabled_state &= link_state->support_state;
++	link_state->bios_aspm_state = link_state->enabled_state;
++
++	/* ENDPOINT states*/
++	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++		int pos;
++		u32 reg32;
++		unsigned int latency;
++		struct endpoint_state *ep_state =
++			&link_state->endpoints[PCI_FUNC(child_dev->devfn)];
++
++		if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
++			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
++			continue;
++
++		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++		pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, &reg32);
++		latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
++		latency = calc_L0S_latency(latency, 1);
++		ep_state->l0s_acceptable_latency = latency;
++		if (link_state->support_state & PCIE_LINK_STATE_L1) {
++			latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
++			latency = calc_L1_latency(latency, 1);
++			ep_state->l1_acceptable_latency = latency;
++		}
++	}
++}
++
++static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
++	unsigned int state)
++{
++	struct pci_dev *parent_dev, *tmp_dev;
++	unsigned int latency, l1_latency = 0;
++	struct pcie_link_state *link_state;
++	struct endpoint_state *ep_state;
++
++	parent_dev = pdev->bus->self;
++	link_state = parent_dev->link_state;
++	state &= link_state->support_state;
++	if (state == 0)
++		return 0;
++	ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
++
++	/*
++	 * Check latency for endpoint device.
++	 * TBD: The latency from the endpoint to root complex vary per
++	 * switch's upstream link state above the device. Here we just do a
++	 * simple check which assumes all links above the device can be in L1
++	 * state, that is we just consider the worst case. If switch's upstream
++	 * link can't be put into L0S/L1, then our check is too strictly.
++	 */
++	tmp_dev = pdev;
++	while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
++		parent_dev = tmp_dev->bus->self;
++		link_state = parent_dev->link_state;
++		if (state & PCIE_LINK_STATE_L0S) {
++			latency = max_t(unsigned int,
++					link_state->l0s_upper_latency,
++					link_state->l0s_down_latency);
++			if (latency > ep_state->l0s_acceptable_latency)
++				state &= ~PCIE_LINK_STATE_L0S;
++		}
++		if (state & PCIE_LINK_STATE_L1) {
++			latency = max_t(unsigned int,
++					link_state->l1_upper_latency,
++					link_state->l1_down_latency);
++			if (latency + l1_latency >
++					ep_state->l1_acceptable_latency)
++				state &= ~PCIE_LINK_STATE_L1;
++		}
++		if (!parent_dev->bus->self) /* parent_dev is a root port */
++			break;
++		else {
++			/*
++			 * parent_dev is the downstream port of a switch, make
++			 * tmp_dev the upstream port of the switch
++			 */
++			tmp_dev = parent_dev->bus->self;
++			/*
++			 * every switch on the path to root complex need 1 more
++			 * microsecond for L1. Spec doesn't mention L0S.
++			 */
++			if (state & PCIE_LINK_STATE_L1)
++				l1_latency += 1000;
++		}
++	}
++	return state;
++}
++
++static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
++	unsigned int state)
++{
++	struct pci_dev *child_dev;
++
++	/* If no child, disable the link */
++	if (list_empty(&pdev->subordinate->devices))
++		return 0;
++	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
++			/*
++			 * If downstream component of a link is pci bridge, we
++			 * disable ASPM for now for the link
++			 * */
++			state = 0;
++			break;
++		}
++		if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
++			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
++			continue;
++		/* Device not in D0 doesn't need check latency */
++		if (child_dev->current_state == PCI_D1 ||
++			child_dev->current_state == PCI_D2 ||
++			child_dev->current_state == PCI_D3hot ||
++			child_dev->current_state == PCI_D3cold)
++			continue;
++		state = __pcie_aspm_check_state_one(child_dev, state);
++	}
++	return state;
++}
++
++static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
++{
++	u16 reg16;
++	int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
++
++	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
++	reg16 &= ~0x3;
++	reg16 |= state;
++	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
++}
++
++static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
++{
++	struct pci_dev *child_dev;
++	int valid = 1;
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	/*
++	 * if the downstream component has pci bridge function, don't do ASPM
++	 * now
++	 */
++	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
++			valid = 0;
++			break;
++		}
++	}
++	if (!valid)
++		return;
++
++	/*
++	 * spec 2.0 suggests all functions should be configured the same
++	 * setting for ASPM. Enabling ASPM L1 should be done in upstream
++	 * component first and then downstream, and vice versa for disabling
++	 * ASPM L1. Spec doesn't mention L0S.
++	 */
++	if (state & PCIE_LINK_STATE_L1)
++		__pcie_aspm_config_one_dev(pdev, state);
++
++	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
++		__pcie_aspm_config_one_dev(child_dev, state);
++
++	if (!(state & PCIE_LINK_STATE_L1))
++		__pcie_aspm_config_one_dev(pdev, state);
++
++	link_state->enabled_state = state;
++}
++
++static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
++	unsigned int state)
++{
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	if (link_state->support_state == 0)
++		return;
++	state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
++
++	/* state 0 means disabling aspm */
++	state = pcie_aspm_check_state(pdev, state);
++	if (link_state->enabled_state == state)
++		return;
++	__pcie_aspm_config_link(pdev, state);
++}
++
++/*
++ * pcie_aspm_configure_link_state: enable/disable PCI express link state
++ * @pdev: the root port or switch downstream port
++ */
++static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
++	unsigned int state)
++{
++	down_read(&pci_bus_sem);
++	mutex_lock(&aspm_lock);
++	__pcie_aspm_configure_link_state(pdev, state);
++	mutex_unlock(&aspm_lock);
++	up_read(&pci_bus_sem);
++}
++
++static void free_link_state(struct pci_dev *pdev)
++{
++	kfree(pdev->link_state);
++	pdev->link_state = NULL;
++}
++
++/*
++ * pcie_aspm_init_link_state: Initiate PCI express link state.
++ * It is called after the pcie and its children devices are scaned.
++ * @pdev: the root port or switch downstream port
++ */
++void pcie_aspm_init_link_state(struct pci_dev *pdev)
++{
++	unsigned int state;
++	struct pcie_link_state *link_state;
++	int error = 0;
++
++	if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
++		return;
++	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
++		return;
++	down_read(&pci_bus_sem);
++	if (list_empty(&pdev->subordinate->devices))
++		goto out;
++
++	mutex_lock(&aspm_lock);
++
++	link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
++	if (!link_state)
++		goto unlock_out;
++	pdev->link_state = link_state;
++
++	pcie_aspm_configure_common_clock(pdev);
++
++	pcie_aspm_cap_init(pdev);
++
++	/* config link state to avoid BIOS error */
++	state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
++	__pcie_aspm_config_link(pdev, state);
++
++	pcie_check_clock_pm(pdev);
++
++	link_state->pdev = pdev;
++	list_add(&link_state->sibiling, &link_list);
++
++unlock_out:
++	if (error)
++		free_link_state(pdev);
++	mutex_unlock(&aspm_lock);
++out:
++	up_read(&pci_bus_sem);
++}
++
++/* @pdev: the endpoint device */
++void pcie_aspm_exit_link_state(struct pci_dev *pdev)
++{
++	struct pci_dev *parent = pdev->bus->self;
++	struct pcie_link_state *link_state = parent->link_state;
++
++	if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
++		return;
++	if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++		parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
++		return;
++	down_read(&pci_bus_sem);
++	mutex_lock(&aspm_lock);
++
++	/*
++	 * All PCIe functions are in one slot, remove one function will remove
++	 * the the whole slot, so just wait
++	 */
++	if (!list_empty(&parent->subordinate->devices))
++		goto out;
++
++	/* All functions are removed, so just disable ASPM for the link */
++	__pcie_aspm_config_one_dev(parent, 0);
++	list_del(&link_state->sibiling);
++	/* Clock PM is for endpoint device */
++
++	free_link_state(parent);
++out:
++	mutex_unlock(&aspm_lock);
++	up_read(&pci_bus_sem);
++}
++
++/* @pdev: the root port or switch downstream port */
++void pcie_aspm_pm_state_change(struct pci_dev *pdev)
++{
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
++		return;
++	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
++		return;
++	/*
++	 * devices changed PM state, we should recheck if latency meets all
++	 * functions' requirement
++	 */
++	pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
++}
++
++/*
++ * pci_disable_link_state - disable pci device's link state, so the link will
++ * never enter specific states
++ */
++void pci_disable_link_state(struct pci_dev *pdev, int state)
++{
++	struct pci_dev *parent = pdev->bus->self;
++	struct pcie_link_state *link_state;
++
++	if (aspm_disabled || !pdev->is_pcie)
++		return;
++	if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
++	    pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
++		parent = pdev;
++	if (!parent || !parent->link_state)
++		return;
++
++	down_read(&pci_bus_sem);
++	mutex_lock(&aspm_lock);
++	link_state = parent->link_state;
++	link_state->support_state &=
++		~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
++	if (state & PCIE_LINK_STATE_CLKPM)
++		link_state->clk_pm_capable = 0;
++
++	__pcie_aspm_configure_link_state(parent, link_state->enabled_state);
++	if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
++		pcie_set_clock_pm(parent, 0);
++	mutex_unlock(&aspm_lock);
++	up_read(&pci_bus_sem);
++}
++EXPORT_SYMBOL(pci_disable_link_state);
++
++static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
++{
++	int i;
++	struct pci_dev *pdev;
++	struct pcie_link_state *link_state;
++
++	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
++		if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
++			break;
++	if (i >= ARRAY_SIZE(policy_str))
++		return -EINVAL;
++	if (i == aspm_policy)
++		return 0;
++
++	down_read(&pci_bus_sem);
++	mutex_lock(&aspm_lock);
++	aspm_policy = i;
++	list_for_each_entry(link_state, &link_list, sibiling) {
++		pdev = link_state->pdev;
++		__pcie_aspm_configure_link_state(pdev,
++			policy_to_aspm_state(pdev));
++		if (link_state->clk_pm_capable &&
++		    link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
++			pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
++
++	}
++	mutex_unlock(&aspm_lock);
++	up_read(&pci_bus_sem);
++	return 0;
++}
++
++static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
++{
++	int i, cnt = 0;
++	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
++		if (i == aspm_policy)
++			cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
++		else
++			cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
++	return cnt;
++}
++
++module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
++	NULL, 0644);
++
++#ifdef CONFIG_PCIEASPM_DEBUG
++static ssize_t link_state_show(struct device *dev,
++		struct device_attribute *attr,
++		char *buf)
++{
++	struct pci_dev *pci_device = to_pci_dev(dev);
++	struct pcie_link_state *link_state = pci_device->link_state;
++
++	return sprintf(buf, "%d\n", link_state->enabled_state);
++}
++
++static ssize_t link_state_store(struct device *dev,
++		struct device_attribute *attr,
++		const char *buf,
++		size_t n)
++{
++	struct pci_dev *pci_device = to_pci_dev(dev);
++	int state;
++
++	if (n < 1)
++		return -EINVAL;
++	state = buf[0]-'0';
++	if (state >= 0 && state <= 3) {
++		/* setup link aspm state */
++		pcie_aspm_configure_link_state(pci_device, state);
++		return n;
++	}
++
++	return -EINVAL;
++}
++
++static ssize_t clk_ctl_show(struct device *dev,
++		struct device_attribute *attr,
++		char *buf)
++{
++	struct pci_dev *pci_device = to_pci_dev(dev);
++	struct pcie_link_state *link_state = pci_device->link_state;
++
++	return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
++}
++
++static ssize_t clk_ctl_store(struct device *dev,
++		struct device_attribute *attr,
++		const char *buf,
++		size_t n)
++{
++	struct pci_dev *pci_device = to_pci_dev(dev);
++	int state;
++
++	if (n < 1)
++		return -EINVAL;
++	state = buf[0]-'0';
++
++	down_read(&pci_bus_sem);
++	mutex_lock(&aspm_lock);
++	pcie_set_clock_pm(pci_device, !!state);
++	mutex_unlock(&aspm_lock);
++	up_read(&pci_bus_sem);
++
++	return n;
++}
++
++static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
++static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);
++
++static char power_group[] = "power";
++void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
++{
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
++		return;
++
++	if (link_state->support_state)
++		sysfs_add_file_to_group(&pdev->dev.kobj,
++			&dev_attr_link_state.attr, power_group);
++	if (link_state->clk_pm_capable)
++		sysfs_add_file_to_group(&pdev->dev.kobj,
++			&dev_attr_clk_ctl.attr, power_group);
++}
++
++void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
++{
++	struct pcie_link_state *link_state = pdev->link_state;
++
++	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
++		return;
++
++	if (link_state->support_state)
++		sysfs_remove_file_from_group(&pdev->dev.kobj,
++			&dev_attr_link_state.attr, power_group);
++	if (link_state->clk_pm_capable)
++		sysfs_remove_file_from_group(&pdev->dev.kobj,
++			&dev_attr_clk_ctl.attr, power_group);
++}
++#endif
++
++static int __init pcie_aspm_disable(char *str)
++{
++	aspm_disabled = 1;
++	return 1;
++}
++
++__setup("pcie_noaspm", pcie_aspm_disable);
++
++#ifdef CONFIG_ACPI
++#include <acpi/acpi_bus.h>
++#include <linux/pci-acpi.h>
++static void pcie_aspm_platform_init(void)
++{
++	pcie_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
++		OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
++}
++#else
++static inline void pcie_aspm_platform_init(void) { }
++#endif
++
++static int __init pcie_aspm_init(void)
++{
++	if (aspm_disabled)
++		return 0;
++	pcie_aspm_platform_init();
++	return 0;
++}
++
++fs_initcall(pcie_aspm_init);
+diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
+index 23d9eb0..fb0abfa 100644
+--- a/drivers/pci/pcie/portdrv_core.c
++++ b/drivers/pci/pcie/portdrv_core.c
+@@ -150,7 +150,7 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
+ 	if (pos) {
+ 		struct msix_entry msix_entries[PCIE_PORT_DEVICE_MAXSERVICES] = 
+ 			{{0, 0}, {0, 1}, {0, 2}, {0, 3}};
+-		printk("%s Found MSIX capability\n", __FUNCTION__);
++		printk("%s Found MSIX capability\n", __func__);
+ 		status = pci_enable_msix(dev, msix_entries, nvec);
+ 		if (!status) {
+ 			int j = 0;
+@@ -165,7 +165,7 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
+ 	if (status) {
+ 		pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ 		if (pos) {
+-			printk("%s Found MSI capability\n", __FUNCTION__);
++			printk("%s Found MSI capability\n", __func__);
+ 			status = pci_enable_msi(dev);
+ 			if (!status) {
+ 				interrupt_mode = PCIE_PORT_MSI_MODE;
+diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
+index 26057f9..51d1632 100644
+--- a/drivers/pci/pcie/portdrv_pci.c
++++ b/drivers/pci/pcie/portdrv_pci.c
+@@ -93,7 +93,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
+         if (!dev->irq && dev->pin) {
+ 		printk(KERN_WARNING 
+ 		"%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n", 
+-		__FUNCTION__, dev->vendor, dev->device);
++		__func__, dev->vendor, dev->device);
+ 	}
+ 	if (pcie_port_device_register(dev)) {
+ 		pci_disable_device(dev);
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 2db2e4b..f991359 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -9,6 +9,7 @@
+ #include <linux/slab.h>
+ #include <linux/module.h>
+ #include <linux/cpumask.h>
++#include <linux/pci-aspm.h>
+ #include "pci.h"
+ 
+ #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
+@@ -20,18 +21,27 @@
+ LIST_HEAD(pci_root_buses);
+ EXPORT_SYMBOL(pci_root_buses);
+ 
+-LIST_HEAD(pci_devices);
++
++static int find_anything(struct device *dev, void *data)
++{
++	return 1;
++}
+ 
+ /*
+  * Some device drivers need know if pci is initiated.
+  * Basically, we think pci is not initiated when there
+- * is no device in list of pci_devices.
++ * is no device to be found on the pci_bus_type.
+  */
+ int no_pci_devices(void)
+ {
+-	return list_empty(&pci_devices);
+-}
++	struct device *dev;
++	int no_devices;
+ 
++	dev = bus_find_device(&pci_bus_type, NULL, NULL, find_anything);
++	no_devices = (dev == NULL);
++	put_device(dev);
++	return no_devices;
++}
+ EXPORT_SYMBOL(no_pci_devices);
+ 
+ #ifdef HAVE_PCI_LEGACY
+@@ -82,6 +92,7 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
+  * PCI Bus Class Devices
+  */
+ static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
++					int type,
+ 					struct device_attribute *attr,
+ 					char *buf)
+ {
+@@ -89,12 +100,30 @@ static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
+ 	cpumask_t cpumask;
+ 
+ 	cpumask = pcibus_to_cpumask(to_pci_bus(dev));
+-	ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
+-	if (ret < PAGE_SIZE)
+-		buf[ret++] = '\n';
++	ret = type?
++		cpulist_scnprintf(buf, PAGE_SIZE-2, cpumask):
++		cpumask_scnprintf(buf, PAGE_SIZE-2, cpumask);
++	buf[ret++] = '\n';
++	buf[ret] = '\0';
+ 	return ret;
+ }
+-DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
++
++static ssize_t inline pci_bus_show_cpumaskaffinity(struct device *dev,
++					struct device_attribute *attr,
++					char *buf)
++{
++	return pci_bus_show_cpuaffinity(dev, 0, attr, buf);
++}
++
++static ssize_t inline pci_bus_show_cpulistaffinity(struct device *dev,
++					struct device_attribute *attr,
++					char *buf)
++{
++	return pci_bus_show_cpuaffinity(dev, 1, attr, buf);
++}
++
++DEVICE_ATTR(cpuaffinity,     S_IRUGO, pci_bus_show_cpumaskaffinity, NULL);
++DEVICE_ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL);
+ 
+ /*
+  * PCI Bus Class
+@@ -225,7 +254,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
+ 			res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
+ 		}
+ 		res->end = res->start + (unsigned long) sz;
+-		res->flags |= pci_calc_resource_flags(l);
++		res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
+ 		if (is_64bit_memory(l)) {
+ 			u32 szhi, lhi;
+ 
+@@ -278,7 +307,8 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
+ 			if (sz) {
+ 				res->flags = (l & IORESOURCE_ROM_ENABLE) |
+ 				  IORESOURCE_MEM | IORESOURCE_PREFETCH |
+-				  IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
++				  IORESOURCE_READONLY | IORESOURCE_CACHEABLE |
++				  IORESOURCE_SIZEALIGN;
+ 				res->start = l & PCI_ROM_ADDRESS_MASK;
+ 				res->end = res->start + (unsigned long) sz;
+ 			}
+@@ -388,8 +418,8 @@ static struct pci_bus * pci_alloc_bus(void)
+ 	return b;
+ }
+ 
+-static struct pci_bus * __devinit
+-pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
++static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
++					   struct pci_dev *bridge, int busnr)
+ {
+ 	struct pci_bus *child;
+ 	int i;
+@@ -622,7 +652,9 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
+ 		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
+ 	}
+ 
+-	sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
++	sprintf(child->name,
++		(is_cardbus ? "PCI CardBus %04x:%02x" : "PCI Bus %04x:%02x"),
++		pci_domain_nr(bus), child->number);
+ 
+ 	/* Has only triggered on CardBus, fixup is in yenta_socket */
+ 	while (bus->parent) {
+@@ -782,6 +814,7 @@ static void pci_release_dev(struct device *dev)
+ 	struct pci_dev *pci_dev;
+ 
+ 	pci_dev = to_pci_dev(dev);
++	pci_vpd_release(pci_dev);
+ 	kfree(pci_dev);
+ }
+ 
+@@ -849,7 +882,6 @@ struct pci_dev *alloc_pci_dev(void)
+ 	if (!dev)
+ 		return NULL;
+ 
+-	INIT_LIST_HEAD(&dev->global_list);
+ 	INIT_LIST_HEAD(&dev->bus_list);
+ 
+ 	pci_msi_init_pci_dev(dev);
+@@ -862,8 +894,7 @@ EXPORT_SYMBOL(alloc_pci_dev);
+  * Read the config data for a PCI device, sanity-check it
+  * and fill in the dev structure...
+  */
+-static struct pci_dev * __devinit
+-pci_scan_device(struct pci_bus *bus, int devfn)
++static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
+ {
+ 	struct pci_dev *dev;
+ 	u32 l;
+@@ -922,6 +953,8 @@ pci_scan_device(struct pci_bus *bus, int devfn)
+ 		return NULL;
+ 	}
+ 
++	pci_vpd_pci22_init(dev);
++
+ 	return dev;
+ }
+ 
+@@ -946,7 +979,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
+ 	 * Add the device to our list of discovered devices
+ 	 * and the bus list for fixup functions, etc.
+ 	 */
+-	INIT_LIST_HEAD(&dev->global_list);
+ 	down_write(&pci_bus_sem);
+ 	list_add_tail(&dev->bus_list, &bus->devices);
+ 	up_write(&pci_bus_sem);
+@@ -973,7 +1005,7 @@ EXPORT_SYMBOL(pci_scan_single_device);
+  *
+  * Scan a PCI slot on the specified PCI bus for devices, adding
+  * discovered devices to the @bus->devices list.  New devices
+- * will have an empty dev->global_list head.
++ * will not have is_added set.
+  */
+ int pci_scan_slot(struct pci_bus *bus, int devfn)
+ {
+@@ -1005,6 +1037,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
+ 				break;
+ 		}
+ 	}
++
++	if (bus->self)
++		pcie_aspm_init_link_state(bus->self);
++
+ 	return nr;
+ }
+ 
+@@ -1175,7 +1211,7 @@ static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head
+ 	list_move_tail(&a->dev.knode_bus.n_node, list);
+ }
+ 
+-static void __init pci_sort_breadthfirst_klist(void)
++void __init pci_sort_breadthfirst(void)
+ {
+ 	LIST_HEAD(sorted_devices);
+ 	struct list_head *pos, *tmp;
+@@ -1196,36 +1232,3 @@ static void __init pci_sort_breadthfirst_klist(void)
+ 	list_splice(&sorted_devices, &device_klist->k_list);
+ 	spin_unlock(&device_klist->k_lock);
+ }
+-
+-static void __init pci_insertion_sort_devices(struct pci_dev *a, struct list_head *list)
+-{
+-	struct pci_dev *b;
+-
+-	list_for_each_entry(b, list, global_list) {
+-		if (pci_sort_bf_cmp(a, b) <= 0) {
+-			list_move_tail(&a->global_list, &b->global_list);
+-			return;
+-		}
+-	}
+-	list_move_tail(&a->global_list, list);
+-}
+-
+-static void __init pci_sort_breadthfirst_devices(void)
+-{
+-	LIST_HEAD(sorted_devices);
+-	struct pci_dev *dev, *tmp;
+-
+-	down_write(&pci_bus_sem);
+-	list_for_each_entry_safe(dev, tmp, &pci_devices, global_list) {
+-		pci_insertion_sort_devices(dev, &sorted_devices);
+-	}
+-	list_splice(&sorted_devices, &pci_devices);
+-	up_write(&pci_bus_sem);
+-}
+-
+-void __init pci_sort_breadthfirst(void)
+-{
+-	pci_sort_breadthfirst_devices();
+-	pci_sort_breadthfirst_klist();
+-}
+-
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index e887aa4..afd914e 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -1502,8 +1502,8 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_f
+ 		if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
+  		    (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
+ #ifdef DEBUG
+-			dev_dbg(&dev->dev, "calling quirk 0x%p", f->hook);
+-			print_fn_descriptor_symbol(": %s()\n",
++			dev_dbg(&dev->dev, "calling ");
++			print_fn_descriptor_symbol("%s()\n",
+ 				(unsigned long) f->hook);
+ #endif
+ 			f->hook(dev);
+@@ -1648,13 +1648,24 @@ static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
+ 			/* Turn off PCI Bus Parking */
+ 			pci_write_config_byte(dev, 0x76, b ^ 0x40);
+ 
++			dev_info(&dev->dev,
++				"Disabling VIA CX700 PCI parking\n");
++		}
++	}
++
++	if (pci_read_config_byte(dev, 0x72, &b) == 0) {
++		if (b != 0) {
+ 			/* Turn off PCI Master read caching */
+ 			pci_write_config_byte(dev, 0x72, 0x0);
++
++			/* Set PCI Master Bus time-out to "1x16 PCLK" */
+ 			pci_write_config_byte(dev, 0x75, 0x1);
++
++			/* Disable "Read FIFO Timer" */
+ 			pci_write_config_byte(dev, 0x77, 0x0);
+ 
+ 			dev_info(&dev->dev,
+-				"Disabling VIA CX700 PCI parking/caching\n");
++				"Disabling VIA CX700 PCI caching\n");
+ 		}
+ 	}
+ }
+diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
+index 9684e1b..bdc2a44 100644
+--- a/drivers/pci/remove.c
++++ b/drivers/pci/remove.c
+@@ -1,5 +1,6 @@
+ #include <linux/pci.h>
+ #include <linux/module.h>
++#include <linux/pci-aspm.h>
+ #include "pci.h"
+ 
+ static void pci_free_resources(struct pci_dev *dev)
+@@ -18,18 +19,15 @@ static void pci_free_resources(struct pci_dev *dev)
+ 
+ static void pci_stop_dev(struct pci_dev *dev)
+ {
+-	if (!dev->global_list.next)
+-		return;
+-
+-	if (!list_empty(&dev->global_list)) {
++	if (dev->is_added) {
+ 		pci_proc_detach_device(dev);
+ 		pci_remove_sysfs_dev_files(dev);
+ 		device_unregister(&dev->dev);
+-		down_write(&pci_bus_sem);
+-		list_del(&dev->global_list);
+-		dev->global_list.next = dev->global_list.prev = NULL;
+-		up_write(&pci_bus_sem);
++		dev->is_added = 0;
+ 	}
++
++	if (dev->bus->self)
++		pcie_aspm_exit_link_state(dev);
+ }
+ 
+ static void pci_destroy_dev(struct pci_dev *dev)
+diff --git a/drivers/pci/search.c b/drivers/pci/search.c
+index 8541034..217814f 100644
+--- a/drivers/pci/search.c
++++ b/drivers/pci/search.c
+@@ -114,31 +114,63 @@ pci_find_next_bus(const struct pci_bus *from)
+ }
+ 
+ #ifdef CONFIG_PCI_LEGACY
+-
+ /**
+  * pci_find_slot - locate PCI device from a given PCI slot
+  * @bus: number of PCI bus on which desired PCI device resides
+- * @devfn: encodes number of PCI slot in which the desired PCI 
+- * device resides and the logical device number within that slot 
++ * @devfn: encodes number of PCI slot in which the desired PCI
++ * device resides and the logical device number within that slot
+  * in case of multi-function devices.
+  *
+- * Given a PCI bus and slot/function number, the desired PCI device 
++ * Given a PCI bus and slot/function number, the desired PCI device
+  * is located in system global list of PCI devices.  If the device
+- * is found, a pointer to its data structure is returned.  If no 
++ * is found, a pointer to its data structure is returned.  If no
+  * device is found, %NULL is returned.
++ *
++ * NOTE: Do not use this function any more; use pci_get_slot() instead, as
++ * the PCI device returned by this function can disappear at any moment in
++ * time.
+  */
+-struct pci_dev *
+-pci_find_slot(unsigned int bus, unsigned int devfn)
++struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
+ {
+ 	struct pci_dev *dev = NULL;
+ 
+-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+-		if (dev->bus->number == bus && dev->devfn == devfn)
++	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
++		if (dev->bus->number == bus && dev->devfn == devfn) {
++			pci_dev_put(dev);
+ 			return dev;
++		}
+ 	}
+ 	return NULL;
+ }
++EXPORT_SYMBOL(pci_find_slot);
++
++/**
++ * pci_find_device - begin or continue searching for a PCI device by vendor/device id
++ * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
++ * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
++ * @from: Previous PCI device found in search, or %NULL for new search.
++ *
++ * Iterates through the list of known PCI devices.  If a PCI device is found
++ * with a matching @vendor and @device, a pointer to its device structure is
++ * returned.  Otherwise, %NULL is returned.
++ * A new search is initiated by passing %NULL as the @from argument.
++ * Otherwise if @from is not %NULL, searches continue from next device
++ * on the global list.
++ *
++ * NOTE: Do not use this function any more; use pci_get_device() instead, as
++ * the PCI device returned by this function can disappear at any moment in
++ * time.
++ */
++struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
++				const struct pci_dev *from)
++{
++	struct pci_dev *pdev;
+ 
++	pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
++	pci_dev_put(pdev);
++	return pdev;
++}
++EXPORT_SYMBOL(pci_find_device);
+ #endif /* CONFIG_PCI_LEGACY */
+ 
+ /**
+@@ -204,86 +236,52 @@ struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
+ 	return NULL;
+ }
+ 
+-#ifdef CONFIG_PCI_LEGACY
+-/**
+- * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
+- * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
+- * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
+- * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
+- * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
+- * @from: Previous PCI device found in search, or %NULL for new search.
+- *
+- * Iterates through the list of known PCI devices.  If a PCI device is
+- * found with a matching @vendor, @device, @ss_vendor and @ss_device, a
+- * pointer to its device structure is returned.  Otherwise, %NULL is returned.
+- * A new search is initiated by passing %NULL as the @from argument.
+- * Otherwise if @from is not %NULL, searches continue from next device
+- * on the global list.
+- *
+- * NOTE: Do not use this function any more; use pci_get_subsys() instead, as
+- * the PCI device returned by this function can disappear at any moment in
+- * time.
+- */
+-static struct pci_dev * pci_find_subsys(unsigned int vendor,
+-				        unsigned int device,
+-					unsigned int ss_vendor,
+-					unsigned int ss_device,
+-					const struct pci_dev *from)
++static int match_pci_dev_by_id(struct device *dev, void *data)
+ {
+-	struct list_head *n;
+-	struct pci_dev *dev;
+-
+-	WARN_ON(in_interrupt());
++	struct pci_dev *pdev = to_pci_dev(dev);
++	struct pci_device_id *id = data;
+ 
+-	/*
+-	 * pci_find_subsys() can be called on the ide_setup() path, super-early
+-	 * in boot.  But the down_read() will enable local interrupts, which
+-	 * can cause some machines to crash.  So here we detect and flag that
+-	 * situation and bail out early.
+-	 */
+-	if (unlikely(no_pci_devices()))
+-		return NULL;
+-	down_read(&pci_bus_sem);
+-	n = from ? from->global_list.next : pci_devices.next;
+-
+-	while (n && (n != &pci_devices)) {
+-		dev = pci_dev_g(n);
+-		if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
+-		    (device == PCI_ANY_ID || dev->device == device) &&
+-		    (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
+-		    (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
+-			goto exit;
+-		n = n->next;
+-	}
+-	dev = NULL;
+-exit:
+-	up_read(&pci_bus_sem);
+-	return dev;
++	if (pci_match_one_device(id, pdev))
++		return 1;
++	return 0;
+ }
+ 
+-/**
+- * pci_find_device - begin or continue searching for a PCI device by vendor/device id
+- * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
+- * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
++/*
++ * pci_get_dev_by_id - begin or continue searching for a PCI device by id
++ * @id: pointer to struct pci_device_id to match for the device
+  * @from: Previous PCI device found in search, or %NULL for new search.
+  *
+  * Iterates through the list of known PCI devices.  If a PCI device is found
+- * with a matching @vendor and @device, a pointer to its device structure is
+- * returned.  Otherwise, %NULL is returned.
+- * A new search is initiated by passing %NULL as the @from argument.
+- * Otherwise if @from is not %NULL, searches continue from next device
+- * on the global list.
+- * 
+- * NOTE: Do not use this function any more; use pci_get_device() instead, as
+- * the PCI device returned by this function can disappear at any moment in
+- * time.
++ * with a matching id a pointer to its device structure is returned, and the
++ * reference count to the device is incremented.  Otherwise, %NULL is returned.
++ * A new search is initiated by passing %NULL as the @from argument.  Otherwise
++ * if @from is not %NULL, searches continue from next device on the global
++ * list.  The reference count for @from is always decremented if it is not
++ * %NULL.
++ *
++ * This is an internal function for use by the other search functions in
++ * this file.
+  */
+-struct pci_dev *
+-pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
++static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
++					 const struct pci_dev *from)
+ {
+-	return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
++	struct device *dev;
++	struct device *dev_start = NULL;
++	struct pci_dev *pdev = NULL;
++
++	WARN_ON(in_interrupt());
++	if (from) {
++		/* FIXME
++		 * take the cast off, when bus_find_device is made const.
++		 */
++		dev_start = (struct device *)&from->dev;
++	}
++	dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
++			      match_pci_dev_by_id);
++	if (dev)
++		pdev = to_pci_dev(dev);
++	return pdev;
+ }
+-#endif /* CONFIG_PCI_LEGACY */
+ 
+ /**
+  * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
+@@ -301,42 +299,34 @@ pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *
+  * searches continue from next device on the global list.
+  * The reference count for @from is always decremented if it is not %NULL.
+  */
+-struct pci_dev * 
+-pci_get_subsys(unsigned int vendor, unsigned int device,
+-	       unsigned int ss_vendor, unsigned int ss_device,
+-	       struct pci_dev *from)
++struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
++			       unsigned int ss_vendor, unsigned int ss_device,
++			       const struct pci_dev *from)
+ {
+-	struct list_head *n;
+-	struct pci_dev *dev;
+-
+-	WARN_ON(in_interrupt());
++	struct pci_dev *pdev;
++	struct pci_device_id *id;
+ 
+ 	/*
+-	 * pci_get_subsys() can potentially be called by drivers super-early
+-	 * in boot.  But the down_read() will enable local interrupts, which
+-	 * can cause some machines to crash.  So here we detect and flag that
+-	 * situation and bail out early.
++	 * pci_find_subsys() can be called on the ide_setup() path,
++	 * super-early in boot.  But the down_read() will enable local
++	 * interrupts, which can cause some machines to crash.  So here we
++	 * detect and flag that situation and bail out early.
+ 	 */
+ 	if (unlikely(no_pci_devices()))
+ 		return NULL;
+-	down_read(&pci_bus_sem);
+-	n = from ? from->global_list.next : pci_devices.next;
+-
+-	while (n && (n != &pci_devices)) {
+-		dev = pci_dev_g(n);
+-		if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
+-		    (device == PCI_ANY_ID || dev->device == device) &&
+-		    (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
+-		    (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
+-			goto exit;
+-		n = n->next;
+-	}
+-	dev = NULL;
+-exit:
+-	dev = pci_dev_get(dev);
+-	up_read(&pci_bus_sem);
+-	pci_dev_put(from);
+-	return dev;
++
++	id = kzalloc(sizeof(*id), GFP_KERNEL);
++	if (!id)
++		return NULL;
++	id->vendor = vendor;
++	id->device = device;
++	id->subvendor = ss_vendor;
++	id->subdevice = ss_device;
++
++	pdev = pci_get_dev_by_id(id, from);
++	kfree(id);
++
++	return pdev;
+ }
+ 
+ /**
+@@ -360,46 +350,6 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
+ }
+ 
+ /**
+- * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id
+- * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
+- * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
+- * @from: Previous PCI device found in search, or %NULL for new search.
+- *
+- * Iterates through the list of known PCI devices in the reverse order of
+- * pci_get_device.
+- * If a PCI device is found with a matching @vendor and @device, the reference
+- * count to the  device is incremented and a pointer to its device structure
+- * is returned Otherwise, %NULL is returned.  A new search is initiated by
+- * passing %NULL as the @from argument.  Otherwise if @from is not %NULL,
+- * searches continue from next device on the global list.  The reference
+- * count for @from is always decremented if it is not %NULL.
+- */
+-struct pci_dev *
+-pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from)
+-{
+-	struct list_head *n;
+-	struct pci_dev *dev;
+-
+-	WARN_ON(in_interrupt());
+-	down_read(&pci_bus_sem);
+-	n = from ? from->global_list.prev : pci_devices.prev;
+-
+-	while (n && (n != &pci_devices)) {
+-		dev = pci_dev_g(n);
+-		if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
+-		    (device == PCI_ANY_ID || dev->device == device))
+-			goto exit;
+-		n = n->prev;
+-	}
+-	dev = NULL;
+-exit:
+-	dev = pci_dev_get(dev);
+-	up_read(&pci_bus_sem);
+-	pci_dev_put(from);
+-	return dev;
+-}
+-
+-/**
+  * pci_get_class - begin or continue searching for a PCI device by class
+  * @class: search for a PCI device with this class designation
+  * @from: Previous PCI device found in search, or %NULL for new search.
+@@ -415,46 +365,21 @@ exit:
+  */
+ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
+ {
+-	struct list_head *n;
+ 	struct pci_dev *dev;
++	struct pci_device_id *id;
+ 
+-	WARN_ON(in_interrupt());
+-	down_read(&pci_bus_sem);
+-	n = from ? from->global_list.next : pci_devices.next;
++	id = kzalloc(sizeof(*id), GFP_KERNEL);
++	if (!id)
++		return NULL;
++	id->vendor = id->device = id->subvendor = id->subdevice = PCI_ANY_ID;
++	id->class_mask = PCI_ANY_ID;
++	id->class = class;
+ 
+-	while (n && (n != &pci_devices)) {
+-		dev = pci_dev_g(n);
+-		if (dev->class == class)
+-			goto exit;
+-		n = n->next;
+-	}
+-	dev = NULL;
+-exit:
+-	dev = pci_dev_get(dev);
+-	up_read(&pci_bus_sem);
+-	pci_dev_put(from);
++	dev = pci_get_dev_by_id(id, from);
++	kfree(id);
+ 	return dev;
+ }
+ 
+-const struct pci_device_id *pci_find_present(const struct pci_device_id *ids)
+-{
+-	struct pci_dev *dev;
+-	const struct pci_device_id *found = NULL;
+-
+-	WARN_ON(in_interrupt());
+-	down_read(&pci_bus_sem);
+-	while (ids->vendor || ids->subvendor || ids->class_mask) {
+-		list_for_each_entry(dev, &pci_devices, global_list) {
+-			if ((found = pci_match_one_device(ids, dev)) != NULL)
+-				goto exit;
+-		}
+-		ids++;
+-	}
+-exit:
+-	up_read(&pci_bus_sem);
+-	return found;
+-}
+-
+ /**
+  * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
+  * @ids: A pointer to a null terminated list of struct pci_device_id structures
+@@ -468,23 +393,27 @@ exit:
+  */
+ int pci_dev_present(const struct pci_device_id *ids)
+ {
+-	return pci_find_present(ids) == NULL ? 0 : 1;
+-}
++	struct pci_dev *found = NULL;
+ 
++	WARN_ON(in_interrupt());
++	while (ids->vendor || ids->subvendor || ids->class_mask) {
++		found = pci_get_dev_by_id(ids, NULL);
++		if (found)
++			goto exit;
++		ids++;
++	}
++exit:
++	if (found)
++		return 1;
++	return 0;
++}
+ EXPORT_SYMBOL(pci_dev_present);
+-EXPORT_SYMBOL(pci_find_present);
+-
+-#ifdef CONFIG_PCI_LEGACY
+-EXPORT_SYMBOL(pci_find_device);
+-EXPORT_SYMBOL(pci_find_slot);
+-#endif /* CONFIG_PCI_LEGACY */
+ 
+ /* For boot time work */
+ EXPORT_SYMBOL(pci_find_bus);
+ EXPORT_SYMBOL(pci_find_next_bus);
+ /* For everyone */
+ EXPORT_SYMBOL(pci_get_device);
+-EXPORT_SYMBOL(pci_get_device_reverse);
+ EXPORT_SYMBOL(pci_get_subsys);
+ EXPORT_SYMBOL(pci_get_slot);
+ EXPORT_SYMBOL(pci_get_bus_and_slot);
+diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
+index f7cb8e0..8ddb918 100644
+--- a/drivers/pci/setup-bus.c
++++ b/drivers/pci/setup-bus.c
+@@ -65,6 +65,7 @@ static void pbus_assign_resources_sorted(struct pci_bus *bus)
+ 		res = list->res;
+ 		idx = res - &list->dev->resource[0];
+ 		if (pci_assign_resource(list->dev, idx)) {
++			/* FIXME: get rid of this */
+ 			res->start = 0;
+ 			res->end = 0;
+ 			res->flags = 0;
+@@ -144,8 +145,7 @@ EXPORT_SYMBOL(pci_setup_cardbus);
+    config space writes, so it's quite possible that an I/O window of
+    the bridge will have some undesirable address (e.g. 0) after the
+    first write. Ditto 64-bit prefetchable MMIO.  */
+-static void __devinit
+-pci_setup_bridge(struct pci_bus *bus)
++static void pci_setup_bridge(struct pci_bus *bus)
+ {
+ 	struct pci_dev *bridge = bus->self;
+ 	struct pci_bus_region region;
+@@ -327,6 +327,7 @@ static void pbus_size_io(struct pci_bus *bus)
+ 	/* Alignment of the IO window is always 4K */
+ 	b_res->start = 4096;
+ 	b_res->end = b_res->start + size - 1;
++	b_res->flags |= IORESOURCE_STARTALIGN;
+ }
+ 
+ /* Calculate the size of the bus and minimal alignment which
+@@ -401,11 +402,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
+ 	}
+ 	b_res->start = min_align;
+ 	b_res->end = size + min_align - 1;
++	b_res->flags |= IORESOURCE_STARTALIGN;
+ 	return 1;
+ }
+ 
+-static void __devinit
+-pci_bus_size_cardbus(struct pci_bus *bus)
++static void pci_bus_size_cardbus(struct pci_bus *bus)
+ {
+ 	struct pci_dev *bridge = bus->self;
+ 	struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
+@@ -415,13 +416,13 @@ pci_bus_size_cardbus(struct pci_bus *bus)
+ 	 * Reserve some resources for CardBus.  We reserve
+ 	 * a fixed amount of bus space for CardBus bridges.
+ 	 */
+-	b_res[0].start = pci_cardbus_io_size;
+-	b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
+-	b_res[0].flags |= IORESOURCE_IO;
++	b_res[0].start = 0;
++	b_res[0].end = pci_cardbus_io_size - 1;
++	b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
+ 
+-	b_res[1].start = pci_cardbus_io_size;
+-	b_res[1].end = b_res[1].start + pci_cardbus_io_size - 1;
+-	b_res[1].flags |= IORESOURCE_IO;
++	b_res[1].start = 0;
++	b_res[1].end = pci_cardbus_io_size - 1;
++	b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
+ 
+ 	/*
+ 	 * Check whether prefetchable memory is supported
+@@ -440,17 +441,17 @@ pci_bus_size_cardbus(struct pci_bus *bus)
+ 	 * twice the size.
+ 	 */
+ 	if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
+-		b_res[2].start = pci_cardbus_mem_size;
+-		b_res[2].end = b_res[2].start + pci_cardbus_mem_size - 1;
+-		b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
++		b_res[2].start = 0;
++		b_res[2].end = pci_cardbus_mem_size - 1;
++		b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN;
+ 
+-		b_res[3].start = pci_cardbus_mem_size;
+-		b_res[3].end = b_res[3].start + pci_cardbus_mem_size - 1;
+-		b_res[3].flags |= IORESOURCE_MEM;
++		b_res[3].start = 0;
++		b_res[3].end = pci_cardbus_mem_size - 1;
++		b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
+ 	} else {
+-		b_res[3].start = pci_cardbus_mem_size * 2;
+-		b_res[3].end = b_res[3].start + pci_cardbus_mem_size * 2 - 1;
+-		b_res[3].flags |= IORESOURCE_MEM;
++		b_res[3].start = 0;
++		b_res[3].end = pci_cardbus_mem_size * 2 - 1;
++		b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
+ 	}
+ }
+ 
+diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
+index 4be7ccf..7d35cdf 100644
+--- a/drivers/pci/setup-res.c
++++ b/drivers/pci/setup-res.c
+@@ -137,10 +137,16 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
+ 
+ 	size = res->end - res->start + 1;
+ 	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+-	/* The bridge resources are special, as their
+-	   size != alignment. Sizing routines return
+-	   required alignment in the "start" field. */
+-	align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
++
++	align = resource_alignment(res);
++	if (!align) {
++		printk(KERN_ERR "PCI: Cannot allocate resource (bogus "
++			"alignment) %d [%llx:%llx] (flags %lx) of %s\n",
++			resno, (unsigned long long)res->start,
++			(unsigned long long)res->end, res->flags,
++			pci_name(dev));
++		return -EINVAL;
++	}
+ 
+ 	/* First, try exact prefetching match.. */
+ 	ret = pci_bus_alloc_resource(bus, res, size, align, min,
+@@ -164,14 +170,16 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
+ 			res->flags & IORESOURCE_IO ? "I/O" : "mem",
+ 			resno, (unsigned long long)size,
+ 			(unsigned long long)res->start, pci_name(dev));
+-	} else if (resno < PCI_BRIDGE_RESOURCES) {
+-		pci_update_resource(dev, res, resno);
++	} else {
++		res->flags &= ~IORESOURCE_STARTALIGN;
++		if (resno < PCI_BRIDGE_RESOURCES)
++			pci_update_resource(dev, res, resno);
+ 	}
+ 
+ 	return ret;
+ }
+ 
+-#ifdef CONFIG_EMBEDDED
++#if 0
+ int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
+ {
+ 	struct pci_bus *bus = dev->bus;
+@@ -226,29 +234,25 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
+ 		if (r->flags & IORESOURCE_PCI_FIXED)
+ 			continue;
+ 
+-		r_align = r->end - r->start;
+-		
+ 		if (!(r->flags) || r->parent)
+ 			continue;
++
++		r_align = resource_alignment(r);
+ 		if (!r_align) {
+-			printk(KERN_WARNING "PCI: Ignore bogus resource %d "
+-				"[%llx:%llx] of %s\n",
++			printk(KERN_WARNING "PCI: bogus alignment of resource "
++				"%d [%llx:%llx] (flags %lx) of %s\n",
+ 				i, (unsigned long long)r->start,
+-				(unsigned long long)r->end, pci_name(dev));
++				(unsigned long long)r->end, r->flags,
++				pci_name(dev));
+ 			continue;
+ 		}
+-		r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start;
+ 		for (list = head; ; list = list->next) {
+ 			resource_size_t align = 0;
+ 			struct resource_list *ln = list->next;
+-			int idx;
+ 
+-			if (ln) {
+-				idx = ln->res - &ln->dev->resource[0];
+-				align = (idx < PCI_BRIDGE_RESOURCES) ?
+-					ln->res->end - ln->res->start + 1 :
+-					ln->res->start;
+-			}
++			if (ln)
++				align = resource_alignment(ln->res);
++
+ 			if (r_align > align) {
+ 				tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+ 				if (!tmp)
+@@ -263,3 +267,46 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
+ 		}
+ 	}
+ }
++
++int pci_enable_resources(struct pci_dev *dev, int mask)
++{
++	u16 cmd, old_cmd;
++	int i;
++	struct resource *r;
++
++	pci_read_config_word(dev, PCI_COMMAND, &cmd);
++	old_cmd = cmd;
++
++	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
++		if (!(mask & (1 << i)))
++			continue;
++
++		r = &dev->resource[i];
++
++		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
++			continue;
++		if ((i == PCI_ROM_RESOURCE) &&
++				(!(r->flags & IORESOURCE_ROM_ENABLE)))
++			continue;
++
++		if (!r->parent) {
++			dev_err(&dev->dev, "device not available because of "
++				"BAR %d [%llx:%llx] collisions\n", i,
++				(unsigned long long) r->start,
++				(unsigned long long) r->end);
++			return -EINVAL;
++		}
++
++		if (r->flags & IORESOURCE_IO)
++			cmd |= PCI_COMMAND_IO;
++		if (r->flags & IORESOURCE_MEM)
++			cmd |= PCI_COMMAND_MEMORY;
++	}
++
++	if (cmd != old_cmd) {
++		dev_info(&dev->dev, "enabling device (%04x -> %04x)\n",
++			 old_cmd, cmd);
++		pci_write_config_word(dev, PCI_COMMAND, cmd);
++	}
++	return 0;
++}
+diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
+index 8b22281..8d88526 100644
+--- a/drivers/pcmcia/Kconfig
++++ b/drivers/pcmcia/Kconfig
+@@ -220,6 +220,7 @@ config PCMCIA_SA1111
+ config PCMCIA_PXA2XX
+ 	tristate "PXA2xx support"
+ 	depends on ARM && ARCH_PXA && PCMCIA
++	depends on ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL || MACH_ARMCORE
+ 	help
+ 	  Say Y here to include support for the PXA2xx PCMCIA controller
+ 
+diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
+index fbf2f3a..e7ab060 100644
+--- a/drivers/pcmcia/pxa2xx_cm_x270.c
++++ b/drivers/pcmcia/pxa2xx_cm_x270.c
+@@ -20,6 +20,7 @@
+ #include <asm/hardware.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/cm-x270.h>
+ 
+ #include "soc_common.h"
+diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
+index 2dcd196..98cbc9f 100644
+--- a/drivers/pnp/pnpacpi/rsparser.c
++++ b/drivers/pnp/pnpacpi/rsparser.c
+@@ -84,10 +84,12 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
+ 	while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
+ 	       i < PNP_MAX_IRQ)
+ 		i++;
+-	if (i >= PNP_MAX_IRQ && !warned) {
+-		printk(KERN_WARNING "pnpacpi: exceeded the max number of IRQ "
+-				"resources: %d \n", PNP_MAX_IRQ);
+-		warned = 1;
++	if (i >= PNP_MAX_IRQ) {
++		if (!warned) {
++			printk(KERN_WARNING "pnpacpi: exceeded the max number"
++				" of IRQ resources: %d\n", PNP_MAX_IRQ);
++			warned = 1;
++		}
+ 		return;
+ 	}
+ 	/*
+diff --git a/drivers/ps3/ps3-sys-manager.c b/drivers/ps3/ps3-sys-manager.c
+index d4f6f96..7605453 100644
+--- a/drivers/ps3/ps3-sys-manager.c
++++ b/drivers/ps3/ps3-sys-manager.c
+@@ -24,6 +24,7 @@
+ #include <linux/reboot.h>
+ 
+ #include <asm/firmware.h>
++#include <asm/lv1call.h>
+ #include <asm/ps3.h>
+ 
+ #include "vuart.h"
+@@ -187,6 +188,7 @@ enum ps3_sys_manager_next_op {
+  * controller, and bluetooth controller.
+  * @PS3_SM_WAKE_RTC:
+  * @PS3_SM_WAKE_RTC_ERROR:
++ * @PS3_SM_WAKE_W_O_L: Ether or wireless LAN.
+  * @PS3_SM_WAKE_P_O_R: Power on reset.
+  *
+  * Additional wakeup sources when specifying PS3_SM_NEXT_OP_SYS_SHUTDOWN.
+@@ -200,10 +202,19 @@ enum ps3_sys_manager_wake_source {
+ 	PS3_SM_WAKE_DEFAULT   = 0,
+ 	PS3_SM_WAKE_RTC       = 0x00000040,
+ 	PS3_SM_WAKE_RTC_ERROR = 0x00000080,
++	PS3_SM_WAKE_W_O_L     = 0x00000400,
+ 	PS3_SM_WAKE_P_O_R     = 0x80000000,
+ };
+ 
+ /**
++ * user_wake_sources - User specified wakeup sources.
++ *
++ * Logical OR of enum ps3_sys_manager_wake_source types.
++ */
++
++static u32 user_wake_sources = PS3_SM_WAKE_DEFAULT;
++
++/**
+  * enum ps3_sys_manager_cmd - Command from system manager to guest.
+  *
+  * The guest completes the actions needed, then acks or naks the command via
+@@ -581,6 +592,23 @@ fail_id:
+ 	return -EIO;
+ }
+ 
++static void ps3_sys_manager_fin(struct ps3_system_bus_device *dev)
++{
++	ps3_sys_manager_send_request_shutdown(dev);
++
++	pr_emerg("System Halted, OK to turn off power\n");
++
++	while (ps3_sys_manager_handle_msg(dev)) {
++		/* pause until next DEC interrupt */
++		lv1_pause(0);
++	}
++
++	while (1) {
++		/* pause, ignoring DEC interrupt */
++		lv1_pause(1);
++	}
++}
++
+ /**
+  * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
+  *
+@@ -601,13 +629,9 @@ static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
+ 	ps3_vuart_cancel_async(dev);
+ 
+ 	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
+-		PS3_SM_WAKE_DEFAULT);
+-	ps3_sys_manager_send_request_shutdown(dev);
+-
+-	pr_emerg("System Halted, OK to turn off power\n");
++		user_wake_sources);
+ 
+-	while (1)
+-		ps3_sys_manager_handle_msg(dev);
++	ps3_sys_manager_fin(dev);
+ }
+ 
+ /**
+@@ -638,14 +662,42 @@ static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
+ 
+ 	ps3_sys_manager_send_attr(dev, 0);
+ 	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_REBOOT,
+-		PS3_SM_WAKE_DEFAULT);
+-	ps3_sys_manager_send_request_shutdown(dev);
++		user_wake_sources);
+ 
+-	pr_emerg("System Halted, OK to turn off power\n");
++	ps3_sys_manager_fin(dev);
++}
++
++/**
++ * ps3_sys_manager_get_wol - Get wake-on-lan setting.
++ */
++
++int ps3_sys_manager_get_wol(void)
++{
++	pr_debug("%s:%d\n", __func__, __LINE__);
++
++	return (user_wake_sources & PS3_SM_WAKE_W_O_L) != 0;
++}
++EXPORT_SYMBOL_GPL(ps3_sys_manager_get_wol);
++
++/**
++ * ps3_sys_manager_set_wol - Set wake-on-lan setting.
++ */
++
++void ps3_sys_manager_set_wol(int state)
++{
++	static DEFINE_MUTEX(mutex);
++
++	mutex_lock(&mutex);
++
++	pr_debug("%s:%d: %d\n", __func__, __LINE__, state);
+ 
+-	while (1)
+-		ps3_sys_manager_handle_msg(dev);
++	if (state)
++		user_wake_sources |= PS3_SM_WAKE_W_O_L;
++	else
++		user_wake_sources &= ~PS3_SM_WAKE_W_O_L;
++	mutex_unlock(&mutex);
+ }
++EXPORT_SYMBOL_GPL(ps3_sys_manager_set_wol);
+ 
+ /**
+  * ps3_sys_manager_work - Asynchronous read handler.
+diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c
+index 31648f7..4742258 100644
+--- a/drivers/ps3/sys-manager-core.c
++++ b/drivers/ps3/sys-manager-core.c
+@@ -19,6 +19,7 @@
+  */
+ 
+ #include <linux/kernel.h>
++#include <asm/lv1call.h>
+ #include <asm/ps3.h>
+ 
+ /**
+@@ -50,10 +51,7 @@ void ps3_sys_manager_power_off(void)
+ 	if (ps3_sys_manager_ops.power_off)
+ 		ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev);
+ 
+-	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+-	local_irq_disable();
+-	while (1)
+-		(void)0;
++	ps3_sys_manager_halt();
+ }
+ 
+ void ps3_sys_manager_restart(void)
+@@ -61,8 +59,14 @@ void ps3_sys_manager_restart(void)
+ 	if (ps3_sys_manager_ops.restart)
+ 		ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev);
+ 
+-	printk(KERN_EMERG "System Halted, OK to turn off power\n");
++	ps3_sys_manager_halt();
++}
++
++void ps3_sys_manager_halt(void)
++{
++	pr_emerg("System Halted, OK to turn off power\n");
+ 	local_irq_disable();
+ 	while (1)
+-		(void)0;
++		lv1_pause(1);
+ }
++
+diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
+index 9e9caa5..c594b34 100644
+--- a/drivers/rtc/rtc-sh.c
++++ b/drivers/rtc/rtc-sh.c
+@@ -1,8 +1,9 @@
+ /*
+  * SuperH On-Chip RTC Support
+  *
+- * Copyright (C) 2006, 2007  Paul Mundt
++ * Copyright (C) 2006, 2007, 2008  Paul Mundt
+  * Copyright (C) 2006  Jamie Lenehan
++ * Copyright (C) 2008  Angelo Castello
+  *
+  * Based on the old arch/sh/kernel/cpu/rtc.c by:
+  *
+@@ -26,7 +27,7 @@
+ #include <asm/rtc.h>
+ 
+ #define DRV_NAME	"sh-rtc"
+-#define DRV_VERSION	"0.1.6"
++#define DRV_VERSION	"0.2.0"
+ 
+ #define RTC_REG(r)	((r) * rtc_reg_size)
+ 
+@@ -63,6 +64,13 @@
+ /* ALARM Bits - or with BCD encoded value */
+ #define AR_ENB		0x80	/* Enable for alarm cmp   */
+ 
++/* Period Bits */
++#define PF_HP		0x100	/* Enable Half Period to support 8,32,128Hz */
++#define PF_COUNT	0x200	/* Half periodic counter */
++#define PF_OXS		0x400	/* Periodic One x Second */
++#define PF_KOU		0x800	/* Kernel or User periodic request 1=kernel */
++#define PF_MASK		0xf00
++
+ /* RCR1 Bits */
+ #define RCR1_CF		0x80	/* Carry Flag             */
+ #define RCR1_CIE	0x10	/* Carry Interrupt Enable */
+@@ -84,33 +92,24 @@ struct sh_rtc {
+ 	unsigned int alarm_irq, periodic_irq, carry_irq;
+ 	struct rtc_device *rtc_dev;
+ 	spinlock_t lock;
+-	int rearm_aie;
+ 	unsigned long capabilities;	/* See asm-sh/rtc.h for cap bits */
++	unsigned short periodic_freq;
+ };
+ 
+ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
+ {
+-	struct platform_device *pdev = to_platform_device(dev_id);
+-	struct sh_rtc *rtc = platform_get_drvdata(pdev);
+-	unsigned int tmp, events = 0;
++	struct sh_rtc *rtc = dev_id;
++	unsigned int tmp;
+ 
+ 	spin_lock(&rtc->lock);
+ 
+ 	tmp = readb(rtc->regbase + RCR1);
+ 	tmp &= ~RCR1_CF;
+-
+-	if (rtc->rearm_aie) {
+-		if (tmp & RCR1_AF)
+-			tmp &= ~RCR1_AF;	/* try to clear AF again */
+-		else {
+-			tmp |= RCR1_AIE;	/* AF has cleared, rearm IRQ */
+-			rtc->rearm_aie = 0;
+-		}
+-	}
+-
+ 	writeb(tmp, rtc->regbase + RCR1);
+ 
+-	rtc_update_irq(rtc->rtc_dev, 1, events);
++	/* Users have requested One x Second IRQ */
++	if (rtc->periodic_freq & PF_OXS)
++		rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
+ 
+ 	spin_unlock(&rtc->lock);
+ 
+@@ -119,47 +118,48 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
+ 
+ static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
+ {
+-	struct platform_device *pdev = to_platform_device(dev_id);
+-	struct sh_rtc *rtc = platform_get_drvdata(pdev);
+-	unsigned int tmp, events = 0;
++	struct sh_rtc *rtc = dev_id;
++	unsigned int tmp;
+ 
+ 	spin_lock(&rtc->lock);
+ 
+ 	tmp = readb(rtc->regbase + RCR1);
+-
+-	/*
+-	 * If AF is set then the alarm has triggered. If we clear AF while
+-	 * the alarm time still matches the RTC time then AF will
+-	 * immediately be set again, and if AIE is enabled then the alarm
+-	 * interrupt will immediately be retrigger. So we clear AIE here
+-	 * and use rtc->rearm_aie so that the carry interrupt will keep
+-	 * trying to clear AF and once it stays cleared it'll re-enable
+-	 * AIE.
+-	 */
+-	if (tmp & RCR1_AF) {
+-		events |= RTC_AF | RTC_IRQF;
+-
+-		tmp &= ~(RCR1_AF|RCR1_AIE);
+-
++	tmp &= ~(RCR1_AF | RCR1_AIE);
+ 		writeb(tmp, rtc->regbase + RCR1);
+ 
+-		rtc->rearm_aie = 1;
+-
+-		rtc_update_irq(rtc->rtc_dev, 1, events);
+-	}
++	rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+ 
+ 	spin_unlock(&rtc->lock);
++
+ 	return IRQ_HANDLED;
+ }
+ 
+ static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
+ {
+-	struct platform_device *pdev = to_platform_device(dev_id);
+-	struct sh_rtc *rtc = platform_get_drvdata(pdev);
++	struct sh_rtc *rtc = dev_id;
++	struct rtc_device *rtc_dev = rtc->rtc_dev;
++	unsigned int tmp;
+ 
+ 	spin_lock(&rtc->lock);
+ 
+-	rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
++	tmp = readb(rtc->regbase + RCR2);
++	tmp &= ~RCR2_PEF;
++	writeb(tmp, rtc->regbase + RCR2);
++
++	/* Half period enabled than one skipped and the next notified */
++	if ((rtc->periodic_freq & PF_HP) && (rtc->periodic_freq & PF_COUNT))
++		rtc->periodic_freq &= ~PF_COUNT;
++	else {
++		if (rtc->periodic_freq & PF_HP)
++			rtc->periodic_freq |= PF_COUNT;
++		if (rtc->periodic_freq & PF_KOU) {
++			spin_lock(&rtc_dev->irq_task_lock);
++			if (rtc_dev->irq_task)
++				rtc_dev->irq_task->func(rtc_dev->irq_task->private_data);
++			spin_unlock(&rtc_dev->irq_task_lock);
++		} else
++			rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
++	}
+ 
+ 	spin_unlock(&rtc->lock);
+ 
+@@ -176,8 +176,8 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
+ 	tmp = readb(rtc->regbase + RCR2);
+ 
+ 	if (enable) {
+-		tmp &= ~RCR2_PESMASK;
+-		tmp |= RCR2_PEF | (2 << 4);
++		tmp &= ~RCR2_PEF;	/* Clear PES bit */
++		tmp |= (rtc->periodic_freq & ~PF_HP);	/* Set PES2-0 */
+ 	} else
+ 		tmp &= ~(RCR2_PESMASK | RCR2_PEF);
+ 
+@@ -186,82 +186,81 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
+ 	spin_unlock_irq(&rtc->lock);
+ }
+ 
+-static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
++static inline int sh_rtc_setfreq(struct device *dev, unsigned int freq)
+ {
+ 	struct sh_rtc *rtc = dev_get_drvdata(dev);
+-	unsigned int tmp;
++	int tmp, ret = 0;
+ 
+ 	spin_lock_irq(&rtc->lock);
++	tmp = rtc->periodic_freq & PF_MASK;
+ 
+-	tmp = readb(rtc->regbase + RCR1);
+-
+-	if (!enable) {
+-		tmp &= ~RCR1_AIE;
+-		rtc->rearm_aie = 0;
+-	} else if (rtc->rearm_aie == 0)
+-		tmp |= RCR1_AIE;
++	switch (freq) {
++	case 0:
++		rtc->periodic_freq = 0x00;
++		break;
++	case 1:
++		rtc->periodic_freq = 0x60;
++		break;
++	case 2:
++		rtc->periodic_freq = 0x50;
++		break;
++	case 4:
++		rtc->periodic_freq = 0x40;
++		break;
++	case 8:
++		rtc->periodic_freq = 0x30 | PF_HP;
++		break;
++	case 16:
++		rtc->periodic_freq = 0x30;
++		break;
++	case 32:
++		rtc->periodic_freq = 0x20 | PF_HP;
++		break;
++	case 64:
++		rtc->periodic_freq = 0x20;
++		break;
++	case 128:
++		rtc->periodic_freq = 0x10 | PF_HP;
++		break;
++	case 256:
++		rtc->periodic_freq = 0x10;
++		break;
++	default:
++		ret = -ENOTSUPP;
++	}
+ 
+-	writeb(tmp, rtc->regbase + RCR1);
++	if (ret == 0) {
++		rtc->periodic_freq |= tmp;
++		rtc->rtc_dev->irq_freq = freq;
++	}
+ 
+ 	spin_unlock_irq(&rtc->lock);
++	return ret;
+ }
+ 
+-static int sh_rtc_open(struct device *dev)
++static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
+ {
+ 	struct sh_rtc *rtc = dev_get_drvdata(dev);
+ 	unsigned int tmp;
+-	int ret;
+-
+-	tmp = readb(rtc->regbase + RCR1);
+-	tmp &= ~RCR1_CF;
+-	tmp |= RCR1_CIE;
+-	writeb(tmp, rtc->regbase + RCR1);
+ 
+-	ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED,
+-			  "sh-rtc period", dev);
+-	if (unlikely(ret)) {
+-		dev_err(dev, "request period IRQ failed with %d, IRQ %d\n",
+-			ret, rtc->periodic_irq);
+-		return ret;
+-	}
+-
+-	ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED,
+-			  "sh-rtc carry", dev);
+-	if (unlikely(ret)) {
+-		dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n",
+-			ret, rtc->carry_irq);
+-		free_irq(rtc->periodic_irq, dev);
+-		goto err_bad_carry;
+-	}
++	spin_lock_irq(&rtc->lock);
+ 
+-	ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED,
+-			  "sh-rtc alarm", dev);
+-	if (unlikely(ret)) {
+-		dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
+-			ret, rtc->alarm_irq);
+-		goto err_bad_alarm;
+-	}
++	tmp = readb(rtc->regbase + RCR1);
+ 
+-	return 0;
++	if (!enable)
++		tmp &= ~RCR1_AIE;
++	else
++		tmp |= RCR1_AIE;
+ 
+-err_bad_alarm:
+-	free_irq(rtc->carry_irq, dev);
+-err_bad_carry:
+-	free_irq(rtc->periodic_irq, dev);
++	writeb(tmp, rtc->regbase + RCR1);
+ 
+-	return ret;
++	spin_unlock_irq(&rtc->lock);
+ }
+ 
+ static void sh_rtc_release(struct device *dev)
+ {
+-	struct sh_rtc *rtc = dev_get_drvdata(dev);
+-
+ 	sh_rtc_setpie(dev, 0);
+ 	sh_rtc_setaie(dev, 0);
+-
+-	free_irq(rtc->periodic_irq, dev);
+-	free_irq(rtc->carry_irq, dev);
+-	free_irq(rtc->alarm_irq, dev);
+ }
+ 
+ static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
+@@ -270,31 +269,44 @@ static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
+ 	unsigned int tmp;
+ 
+ 	tmp = readb(rtc->regbase + RCR1);
+-	seq_printf(seq, "carry_IRQ\t: %s\n",
+-		   (tmp & RCR1_CIE) ? "yes" : "no");
++	seq_printf(seq, "carry_IRQ\t: %s\n", (tmp & RCR1_CIE) ? "yes" : "no");
+ 
+ 	tmp = readb(rtc->regbase + RCR2);
+ 	seq_printf(seq, "periodic_IRQ\t: %s\n",
+-		   (tmp & RCR2_PEF) ? "yes" : "no");
++		   (tmp & RCR2_PESMASK) ? "yes" : "no");
+ 
+ 	return 0;
+ }
+ 
+ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+ {
+-	unsigned int ret = -ENOIOCTLCMD;
++	struct sh_rtc *rtc = dev_get_drvdata(dev);
++	unsigned int ret = 0;
+ 
+ 	switch (cmd) {
+ 	case RTC_PIE_OFF:
+ 	case RTC_PIE_ON:
+ 		sh_rtc_setpie(dev, cmd == RTC_PIE_ON);
+-		ret = 0;
+ 		break;
+ 	case RTC_AIE_OFF:
+ 	case RTC_AIE_ON:
+ 		sh_rtc_setaie(dev, cmd == RTC_AIE_ON);
+-		ret = 0;
+ 		break;
++	case RTC_UIE_OFF:
++		rtc->periodic_freq &= ~PF_OXS;
++		break;
++	case RTC_UIE_ON:
++		rtc->periodic_freq |= PF_OXS;
++		break;
++	case RTC_IRQP_READ:
++		ret = put_user(rtc->rtc_dev->irq_freq,
++			       (unsigned long __user *)arg);
++		break;
++	case RTC_IRQP_SET:
++		ret = sh_rtc_setfreq(dev, arg);
++		break;
++	default:
++		ret = -ENOIOCTLCMD;
+ 	}
+ 
+ 	return ret;
+@@ -421,7 +433,7 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+ {
+ 	struct platform_device *pdev = to_platform_device(dev);
+ 	struct sh_rtc *rtc = platform_get_drvdata(pdev);
+-	struct rtc_time* tm = &wkalrm->time;
++	struct rtc_time *tm = &wkalrm->time;
+ 
+ 	spin_lock_irq(&rtc->lock);
+ 
+@@ -452,7 +464,7 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
+ 		writeb(BIN2BCD(value) | AR_ENB,  rtc->regbase + reg_off);
+ }
+ 
+-static int sh_rtc_check_alarm(struct rtc_time* tm)
++static int sh_rtc_check_alarm(struct rtc_time *tm)
+ {
+ 	/*
+ 	 * The original rtc says anything > 0xc0 is "don't care" or "match
+@@ -503,11 +515,9 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+ 
+ 	/* disable alarm interrupt and clear the alarm flag */
+ 	rcr1 = readb(rtc->regbase + RCR1);
+-	rcr1 &= ~(RCR1_AF|RCR1_AIE);
++	rcr1 &= ~(RCR1_AF | RCR1_AIE);
+ 	writeb(rcr1, rtc->regbase + RCR1);
+ 
+-	rtc->rearm_aie = 0;
+-
+ 	/* set alarm time */
+ 	sh_rtc_write_alarm_value(rtc, tm->tm_sec,  RSECAR);
+ 	sh_rtc_write_alarm_value(rtc, tm->tm_min,  RMINAR);
+@@ -529,14 +539,34 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+ 	return 0;
+ }
+ 
++static int sh_rtc_irq_set_state(struct device *dev, int enabled)
++{
++	struct platform_device *pdev = to_platform_device(dev);
++	struct sh_rtc *rtc = platform_get_drvdata(pdev);
++
++	if (enabled) {
++		rtc->periodic_freq |= PF_KOU;
++		return sh_rtc_ioctl(dev, RTC_PIE_ON, 0);
++	} else {
++		rtc->periodic_freq &= ~PF_KOU;
++		return sh_rtc_ioctl(dev, RTC_PIE_OFF, 0);
++	}
++}
++
++static int sh_rtc_irq_set_freq(struct device *dev, int freq)
++{
++	return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq);
++}
++
+ static struct rtc_class_ops sh_rtc_ops = {
+-	.open		= sh_rtc_open,
+ 	.release	= sh_rtc_release,
+ 	.ioctl		= sh_rtc_ioctl,
+ 	.read_time	= sh_rtc_read_time,
+ 	.set_time	= sh_rtc_set_time,
+ 	.read_alarm	= sh_rtc_read_alarm,
+ 	.set_alarm	= sh_rtc_set_alarm,
++	.irq_set_state	= sh_rtc_irq_set_state,
++	.irq_set_freq	= sh_rtc_irq_set_freq,
+ 	.proc		= sh_rtc_proc,
+ };
+ 
+@@ -544,6 +574,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
+ {
+ 	struct sh_rtc *rtc;
+ 	struct resource *res;
++	unsigned int tmp;
+ 	int ret = -ENOENT;
+ 
+ 	rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
+@@ -552,6 +583,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
+ 
+ 	spin_lock_init(&rtc->lock);
+ 
++	/* get periodic/carry/alarm irqs */
+ 	rtc->periodic_irq = platform_get_irq(pdev, 0);
+ 	if (unlikely(rtc->periodic_irq < 0)) {
+ 		dev_err(&pdev->dev, "No IRQ for period\n");
+@@ -608,8 +640,48 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
+ 		rtc->capabilities |= pinfo->capabilities;
+ 	}
+ 
++	rtc->rtc_dev->max_user_freq = 256;
++	rtc->rtc_dev->irq_freq = 1;
++	rtc->periodic_freq = 0x60;
++
+ 	platform_set_drvdata(pdev, rtc);
+ 
++	/* register periodic/carry/alarm irqs */
++	ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED,
++			  "sh-rtc period", rtc);
++	if (unlikely(ret)) {
++		dev_err(&pdev->dev,
++			"request period IRQ failed with %d, IRQ %d\n", ret,
++			rtc->periodic_irq);
++		goto err_badmap;
++	}
++
++	ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED,
++			  "sh-rtc carry", rtc);
++	if (unlikely(ret)) {
++		dev_err(&pdev->dev,
++			"request carry IRQ failed with %d, IRQ %d\n", ret,
++			rtc->carry_irq);
++		free_irq(rtc->periodic_irq, rtc);
++		goto err_badmap;
++	}
++
++	ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED,
++			  "sh-rtc alarm", rtc);
++	if (unlikely(ret)) {
++		dev_err(&pdev->dev,
++			"request alarm IRQ failed with %d, IRQ %d\n", ret,
++			rtc->alarm_irq);
++		free_irq(rtc->carry_irq, rtc);
++		free_irq(rtc->periodic_irq, rtc);
++		goto err_badmap;
++	}
++
++	tmp = readb(rtc->regbase + RCR1);
++	tmp &= ~RCR1_CF;
++	tmp |= RCR1_CIE;
++	writeb(tmp, rtc->regbase + RCR1);
++
+ 	return 0;
+ 
+ err_badmap:
+@@ -630,6 +702,10 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
+ 	sh_rtc_setpie(&pdev->dev, 0);
+ 	sh_rtc_setaie(&pdev->dev, 0);
+ 
++	free_irq(rtc->carry_irq, rtc);
++	free_irq(rtc->periodic_irq, rtc);
++	free_irq(rtc->alarm_irq, rtc);
++
+ 	release_resource(rtc->res);
+ 
+ 	platform_set_drvdata(pdev, NULL);
+@@ -662,6 +738,8 @@ module_exit(sh_rtc_exit);
+ 
+ MODULE_DESCRIPTION("SuperH on-chip RTC driver");
+ MODULE_VERSION(DRV_VERSION);
+-MODULE_AUTHOR("Paul Mundt <lethal at linux-sh.org>, Jamie Lenehan <lenehan at twibble.org>");
++MODULE_AUTHOR("Paul Mundt <lethal at linux-sh.org>, "
++	      "Jamie Lenehan <lenehan at twibble.org>, "
++	      "Angelo Castello <angelo.castello at st.com>");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
+index e879b21..0788319 100644
+--- a/drivers/s390/block/Kconfig
++++ b/drivers/s390/block/Kconfig
+@@ -20,6 +20,7 @@ config DCSSBLK
+ config DASD
+ 	tristate "Support for DASD devices"
+ 	depends on CCW && BLOCK
++	select IOSCHED_DEADLINE
+ 	help
+ 	  Enable this option if you want to access DASDs directly utilizing
+ 	  S/390s channel subsystem commands. This is necessary for running
+diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
+index ccf46c9..ac6d4d3 100644
+--- a/drivers/s390/block/dasd.c
++++ b/drivers/s390/block/dasd.c
+@@ -980,12 +980,12 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
+ 			break;
+ 		case -ETIMEDOUT:
+ 			printk(KERN_WARNING"%s(%s): request timed out\n",
+-			       __FUNCTION__, cdev->dev.bus_id);
++			       __func__, cdev->dev.bus_id);
+ 			//FIXME - dasd uses own timeout interface...
+ 			break;
+ 		default:
+ 			printk(KERN_WARNING"%s(%s): unknown error %ld\n",
+-			       __FUNCTION__, cdev->dev.bus_id, PTR_ERR(irb));
++			       __func__, cdev->dev.bus_id, PTR_ERR(irb));
+ 		}
+ 		return;
+ 	}
+@@ -1956,6 +1956,7 @@ static int dasd_alloc_queue(struct dasd_block *block)
+ 	block->request_queue->queuedata = block;
+ 
+ 	elevator_exit(block->request_queue->elevator);
++	block->request_queue->elevator = NULL;
+ 	rc = elevator_init(block->request_queue, "deadline");
+ 	if (rc) {
+ 		blk_cleanup_queue(block->request_queue);
+@@ -2298,9 +2299,8 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
+ 	 * in the other openers.
+ 	 */
+ 	if (device->block) {
+-		struct dasd_block *block = device->block;
+-		max_count = block->bdev ? 0 : -1;
+-		open_count = (int) atomic_read(&block->open_count);
++		max_count = device->block->bdev ? 0 : -1;
++		open_count = atomic_read(&device->block->open_count);
+ 		if (open_count > max_count) {
+ 			if (open_count > 0)
+ 				printk(KERN_WARNING "Can't offline dasd "
+diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
+index b19db20..e6700df 100644
+--- a/drivers/s390/block/dasd_3990_erp.c
++++ b/drivers/s390/block/dasd_3990_erp.c
+@@ -1996,6 +1996,36 @@ dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense)
+ }				/* end dasd_3990_erp_compound */
+ 
+ /*
++ *DASD_3990_ERP_HANDLE_SIM
++ *
++ *DESCRIPTION
++ *  inspects the SIM SENSE data and starts an appropriate action
++ *
++ * PARAMETER
++ *   sense	   sense data of the actual error
++ *
++ * RETURN VALUES
++ *   none
++ */
++void
++dasd_3990_erp_handle_sim(struct dasd_device *device, char *sense)
++{
++	/* print message according to log or message to operator mode */
++	if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) {
++
++		/* print SIM SRC from RefCode */
++		DEV_MESSAGE(KERN_ERR, device, "SIM - SRC: "
++			    "%02x%02x%02x%02x", sense[22],
++			    sense[23], sense[11], sense[12]);
++	} else if (sense[24] & DASD_SIM_LOG) {
++		/* print SIM SRC Refcode */
++		DEV_MESSAGE(KERN_WARNING, device, "SIM - SRC: "
++			    "%02x%02x%02x%02x", sense[22],
++			    sense[23], sense[11], sense[12]);
++	}
++}
++
++/*
+  * DASD_3990_ERP_INSPECT_32
+  *
+  * DESCRIPTION
+@@ -2018,6 +2048,10 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
+ 
+ 	erp->function = dasd_3990_erp_inspect_32;
+ 
++	/* check for SIM sense data */
++	if ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)
++		dasd_3990_erp_handle_sim(device, sense);
++
+ 	if (sense[25] & DASD_SENSE_BIT_0) {
+ 
+ 		/* compound program action codes (byte25 bit 0 == '1') */
+diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
+index 3a40bee..2d8df0b 100644
+--- a/drivers/s390/block/dasd_alias.c
++++ b/drivers/s390/block/dasd_alias.c
+@@ -745,6 +745,19 @@ static void flush_all_alias_devices_on_lcu(struct alias_lcu *lcu)
+ 	spin_unlock_irqrestore(&lcu->lock, flags);
+ }
+ 
++static void __stop_device_on_lcu(struct dasd_device *device,
++				 struct dasd_device *pos)
++{
++	/* If pos == device then device is already locked! */
++	if (pos == device) {
++		pos->stopped |= DASD_STOPPED_SU;
++		return;
++	}
++	spin_lock(get_ccwdev_lock(pos->cdev));
++	pos->stopped |= DASD_STOPPED_SU;
++	spin_unlock(get_ccwdev_lock(pos->cdev));
++}
++
+ /*
+  * This function is called in interrupt context, so the
+  * cdev lock for device is already locked!
+@@ -755,35 +768,15 @@ static void _stop_all_devices_on_lcu(struct alias_lcu *lcu,
+ 	struct alias_pav_group *pavgroup;
+ 	struct dasd_device *pos;
+ 
+-	list_for_each_entry(pos, &lcu->active_devices, alias_list) {
+-		if (pos != device)
+-			spin_lock(get_ccwdev_lock(pos->cdev));
+-		pos->stopped |= DASD_STOPPED_SU;
+-		if (pos != device)
+-			spin_unlock(get_ccwdev_lock(pos->cdev));
+-	}
+-	list_for_each_entry(pos, &lcu->inactive_devices, alias_list) {
+-		if (pos != device)
+-			spin_lock(get_ccwdev_lock(pos->cdev));
+-		pos->stopped |= DASD_STOPPED_SU;
+-		if (pos != device)
+-			spin_unlock(get_ccwdev_lock(pos->cdev));
+-	}
++	list_for_each_entry(pos, &lcu->active_devices, alias_list)
++		__stop_device_on_lcu(device, pos);
++	list_for_each_entry(pos, &lcu->inactive_devices, alias_list)
++		__stop_device_on_lcu(device, pos);
+ 	list_for_each_entry(pavgroup, &lcu->grouplist, group) {
+-		list_for_each_entry(pos, &pavgroup->baselist, alias_list) {
+-			if (pos != device)
+-				spin_lock(get_ccwdev_lock(pos->cdev));
+-			pos->stopped |= DASD_STOPPED_SU;
+-			if (pos != device)
+-				spin_unlock(get_ccwdev_lock(pos->cdev));
+-		}
+-		list_for_each_entry(pos, &pavgroup->aliaslist, alias_list) {
+-			if (pos != device)
+-				spin_lock(get_ccwdev_lock(pos->cdev));
+-			pos->stopped |= DASD_STOPPED_SU;
+-			if (pos != device)
+-				spin_unlock(get_ccwdev_lock(pos->cdev));
+-		}
++		list_for_each_entry(pos, &pavgroup->baselist, alias_list)
++			__stop_device_on_lcu(device, pos);
++		list_for_each_entry(pos, &pavgroup->aliaslist, alias_list)
++			__stop_device_on_lcu(device, pos);
+ 	}
+ }
+ 
+diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
+index 61f1693..a0edae0 100644
+--- a/drivers/s390/block/dasd_eckd.c
++++ b/drivers/s390/block/dasd_eckd.c
+@@ -1415,6 +1415,13 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
+ 		return;
+ 	}
+ 
++
++	/* service information message SIM */
++	if ((irb->ecw[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE) {
++		dasd_3990_erp_handle_sim(device, irb->ecw);
++		return;
++	}
++
+ 	/* just report other unsolicited interrupts */
+ 	DEV_MESSAGE(KERN_DEBUG, device, "%s",
+ 		    "unsolicited interrupt received");
+diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
+index d13ea05..1166115 100644
+--- a/drivers/s390/block/dasd_fba.c
++++ b/drivers/s390/block/dasd_fba.c
+@@ -125,7 +125,8 @@ dasd_fba_check_characteristics(struct dasd_device *device)
+ 
+ 	private = (struct dasd_fba_private *) device->private;
+ 	if (private == NULL) {
+-		private = kzalloc(sizeof(struct dasd_fba_private), GFP_KERNEL);
++		private = kzalloc(sizeof(struct dasd_fba_private),
++				  GFP_KERNEL | GFP_DMA);
+ 		if (private == NULL) {
+ 			DEV_MESSAGE(KERN_WARNING, device, "%s",
+ 				    "memory allocation failed for private "
+diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
+index 44b2984..6c624bf 100644
+--- a/drivers/s390/block/dasd_int.h
++++ b/drivers/s390/block/dasd_int.h
+@@ -72,6 +72,11 @@ struct dasd_block;
+ #define DASD_SENSE_BIT_2 0x20
+ #define DASD_SENSE_BIT_3 0x10
+ 
++/* BIT DEFINITIONS FOR SIM SENSE */
++#define DASD_SIM_SENSE 0x0F
++#define DASD_SIM_MSG_TO_OP 0x03
++#define DASD_SIM_LOG 0x0C
++
+ /*
+  * SECTION: MACROs for klogd and s390 debug feature (dbf)
+  */
+@@ -621,6 +626,7 @@ void dasd_log_sense(struct dasd_ccw_req *, struct irb *);
+ 
+ /* externals in dasd_3990_erp.c */
+ struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *);
++void dasd_3990_erp_handle_sim(struct dasd_device *, char *);
+ 
+ /* externals in dasd_eer.c */
+ #ifdef CONFIG_DASD_EER
+diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
+index e6c94db..04787ea 100644
+--- a/drivers/s390/block/dcssblk.c
++++ b/drivers/s390/block/dcssblk.c
+@@ -142,57 +142,6 @@ dcssblk_get_device_by_name(char *name)
+ 	return NULL;
+ }
+ 
+-/*
+- * print appropriate error message for segment_load()/segment_type()
+- * return code
+- */
+-static void
+-dcssblk_segment_warn(int rc, char* seg_name)
+-{
+-	switch (rc) {
+-	case -ENOENT:
+-		PRINT_WARN("cannot load/query segment %s, does not exist\n",
+-			   seg_name);
+-		break;
+-	case -ENOSYS:
+-		PRINT_WARN("cannot load/query segment %s, not running on VM\n",
+-			   seg_name);
+-		break;
+-	case -EIO:
+-		PRINT_WARN("cannot load/query segment %s, hardware error\n",
+-			   seg_name);
+-		break;
+-	case -ENOTSUPP:
+-		PRINT_WARN("cannot load/query segment %s, is a multi-part "
+-			   "segment\n", seg_name);
+-		break;
+-	case -ENOSPC:
+-		PRINT_WARN("cannot load/query segment %s, overlaps with "
+-			   "storage\n", seg_name);
+-		break;
+-	case -EBUSY:
+-		PRINT_WARN("cannot load/query segment %s, overlaps with "
+-			   "already loaded dcss\n", seg_name);
+-		break;
+-	case -EPERM:
+-		PRINT_WARN("cannot load/query segment %s, already loaded in "
+-			   "incompatible mode\n", seg_name);
+-		break;
+-	case -ENOMEM:
+-		PRINT_WARN("cannot load/query segment %s, out of memory\n",
+-			   seg_name);
+-		break;
+-	case -ERANGE:
+-		PRINT_WARN("cannot load/query segment %s, exceeds kernel "
+-			   "mapping range\n", seg_name);
+-		break;
+-	default:
+-		PRINT_WARN("cannot load/query segment %s, return value %i\n",
+-			   seg_name, rc);
+-		break;
+-	}
+-}
+-
+ static void dcssblk_unregister_callback(struct device *dev)
+ {
+ 	device_unregister(dev);
+@@ -423,7 +372,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
+ 	rc = segment_load(local_buf, SEGMENT_SHARED,
+ 				&dev_info->start, &dev_info->end);
+ 	if (rc < 0) {
+-		dcssblk_segment_warn(rc, dev_info->segment_name);
++		segment_warning(rc, dev_info->segment_name);
+ 		goto dealloc_gendisk;
+ 	}
+ 	seg_byte_size = (dev_info->end - dev_info->start + 1);
+diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
+index 67009bf..1e1f506 100644
+--- a/drivers/s390/char/monreader.c
++++ b/drivers/s390/char/monreader.c
+@@ -111,56 +111,6 @@ static void dcss_mkname(char *ascii_name, char *ebcdic_name)
+ 	ASCEBC(ebcdic_name, 8);
+ }
+ 
+-/*
+- * print appropriate error message for segment_load()/segment_type()
+- * return code
+- */
+-static void mon_segment_warn(int rc, char* seg_name)
+-{
+-	switch (rc) {
+-	case -ENOENT:
+-		P_WARNING("cannot load/query segment %s, does not exist\n",
+-			  seg_name);
+-		break;
+-	case -ENOSYS:
+-		P_WARNING("cannot load/query segment %s, not running on VM\n",
+-			  seg_name);
+-		break;
+-	case -EIO:
+-		P_WARNING("cannot load/query segment %s, hardware error\n",
+-			  seg_name);
+-		break;
+-	case -ENOTSUPP:
+-		P_WARNING("cannot load/query segment %s, is a multi-part "
+-			  "segment\n", seg_name);
+-		break;
+-	case -ENOSPC:
+-		P_WARNING("cannot load/query segment %s, overlaps with "
+-			  "storage\n", seg_name);
+-		break;
+-	case -EBUSY:
+-		P_WARNING("cannot load/query segment %s, overlaps with "
+-			  "already loaded dcss\n", seg_name);
+-		break;
+-	case -EPERM:
+-		P_WARNING("cannot load/query segment %s, already loaded in "
+-			  "incompatible mode\n", seg_name);
+-		break;
+-	case -ENOMEM:
+-		P_WARNING("cannot load/query segment %s, out of memory\n",
+-			  seg_name);
+-		break;
+-	case -ERANGE:
+-		P_WARNING("cannot load/query segment %s, exceeds kernel "
+-			  "mapping range\n", seg_name);
+-		break;
+-	default:
+-		P_WARNING("cannot load/query segment %s, return value %i\n",
+-			  seg_name, rc);
+-		break;
+-	}
+-}
+-
+ static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
+ {
+ 	return *(u32 *) &monmsg->msg.rmmsg;
+@@ -585,7 +535,7 @@ static int __init mon_init(void)
+ 
+ 	rc = segment_type(mon_dcss_name);
+ 	if (rc < 0) {
+-		mon_segment_warn(rc, mon_dcss_name);
++		segment_warning(rc, mon_dcss_name);
+ 		goto out_iucv;
+ 	}
+ 	if (rc != SEG_TYPE_SC) {
+@@ -598,7 +548,7 @@ static int __init mon_init(void)
+ 	rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
+ 			  &mon_dcss_start, &mon_dcss_end);
+ 	if (rc < 0) {
+-		mon_segment_warn(rc, mon_dcss_name);
++		segment_warning(rc, mon_dcss_name);
+ 		rc = -EINVAL;
+ 		goto out_iucv;
+ 	}
+diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
+index 2e616e3..e3b3d39 100644
+--- a/drivers/s390/char/sclp_tty.c
++++ b/drivers/s390/char/sclp_tty.c
+@@ -332,7 +332,7 @@ sclp_tty_write_string(const unsigned char *str, int count)
+ 		if (sclp_ttybuf == NULL) {
+ 			while (list_empty(&sclp_tty_pages)) {
+ 				spin_unlock_irqrestore(&sclp_tty_lock, flags);
+-				if (in_atomic())
++				if (in_interrupt())
+ 					sclp_sync_wait();
+ 				else
+ 					wait_event(sclp_tty_waitq,
+diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
+index f7b258d..ed50759 100644
+--- a/drivers/s390/char/sclp_vt220.c
++++ b/drivers/s390/char/sclp_vt220.c
+@@ -383,7 +383,7 @@ sclp_vt220_timeout(unsigned long data)
+  */
+ static int
+ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
+-		   int convertlf)
++		   int convertlf, int may_schedule)
+ {
+ 	unsigned long flags;
+ 	void *page;
+@@ -398,9 +398,8 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
+ 		/* Create a sclp output buffer if none exists yet */
+ 		if (sclp_vt220_current_request == NULL) {
+ 			while (list_empty(&sclp_vt220_empty)) {
+-				spin_unlock_irqrestore(&sclp_vt220_lock,
+-						       flags);
+-				if (in_atomic())
++				spin_unlock_irqrestore(&sclp_vt220_lock, flags);
++				if (in_interrupt() || !may_schedule)
+ 					sclp_sync_wait();
+ 				else
+ 					wait_event(sclp_vt220_waitq,
+@@ -450,7 +449,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
+ static int
+ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
+ {
+-	return __sclp_vt220_write(buf, count, 1, 0);
++	return __sclp_vt220_write(buf, count, 1, 0, 1);
+ }
+ 
+ #define SCLP_VT220_SESSION_ENDED	0x01
+@@ -529,7 +528,7 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp)
+ static void
+ sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+-	__sclp_vt220_write(&ch, 1, 0, 0);
++	__sclp_vt220_write(&ch, 1, 0, 0, 1);
+ }
+ 
+ /*
+@@ -746,7 +745,7 @@ __initcall(sclp_vt220_tty_init);
+ static void
+ sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
+ {
+-	__sclp_vt220_write((const unsigned char *) buf, count, 1, 1);
++	__sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0);
+ }
+ 
+ static struct tty_driver *
+diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
+index 5b47e9c..874adf3 100644
+--- a/drivers/s390/char/tape_34xx.c
++++ b/drivers/s390/char/tape_34xx.c
+@@ -394,7 +394,7 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
+ 			return tape_34xx_erp_failed(request, -ENOSPC);
+ 		default:
+ 			PRINT_ERR("Invalid op in %s:%i\n",
+-				  __FUNCTION__, __LINE__);
++				  __func__, __LINE__);
+ 			return tape_34xx_erp_failed(request, 0);
+ 		}
+ 	}
+diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
+index b830a8c..ebe8406 100644
+--- a/drivers/s390/char/tape_char.c
++++ b/drivers/s390/char/tape_char.c
+@@ -83,9 +83,9 @@ tapechar_setup_device(struct tape_device * device)
+ void
+ tapechar_cleanup_device(struct tape_device *device)
+ {
+-	unregister_tape_dev(device->rt);
++	unregister_tape_dev(&device->cdev->dev, device->rt);
+ 	device->rt = NULL;
+-	unregister_tape_dev(device->nt);
++	unregister_tape_dev(&device->cdev->dev, device->nt);
+ 	device->nt = NULL;
+ }
+ 
+diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
+index aa7f166..6dfdb7c 100644
+--- a/drivers/s390/char/tape_class.c
++++ b/drivers/s390/char/tape_class.c
+@@ -99,11 +99,10 @@ fail_with_tcd:
+ }
+ EXPORT_SYMBOL(register_tape_dev);
+ 
+-void unregister_tape_dev(struct tape_class_device *tcd)
++void unregister_tape_dev(struct device *device, struct tape_class_device *tcd)
+ {
+ 	if (tcd != NULL && !IS_ERR(tcd)) {
+-		sysfs_remove_link(&tcd->class_device->kobj,
+-				  tcd->mode_name);
++		sysfs_remove_link(&device->kobj, tcd->mode_name);
+ 		device_destroy(tape_class, tcd->char_device->dev);
+ 		cdev_del(tcd->char_device);
+ 		kfree(tcd);
+diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
+index e2b5ac9..707b7f4 100644
+--- a/drivers/s390/char/tape_class.h
++++ b/drivers/s390/char/tape_class.h
+@@ -56,6 +56,6 @@ struct tape_class_device *register_tape_dev(
+ 	char *			device_name,
+ 	char *			node_name
+ );
+-void unregister_tape_dev(struct tape_class_device *tcd);
++void unregister_tape_dev(struct device *device, struct tape_class_device *tcd);
+ 
+ #endif /* __TAPE_CLASS_H__ */
+diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
+index 7689b50..83ae9a8 100644
+--- a/drivers/s390/char/vmur.c
++++ b/drivers/s390/char/vmur.c
+@@ -100,7 +100,8 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
+ 	urd->reclen = cdev->id.driver_info;
+ 	ccw_device_get_id(cdev, &urd->dev_id);
+ 	mutex_init(&urd->io_mutex);
+-	mutex_init(&urd->open_mutex);
++	init_waitqueue_head(&urd->wait);
++	spin_lock_init(&urd->open_lock);
+ 	atomic_set(&urd->ref_count,  1);
+ 	urd->cdev = cdev;
+ 	get_device(&cdev->dev);
+@@ -678,17 +679,21 @@ static int ur_open(struct inode *inode, struct file *file)
+ 	if (!urd)
+ 		return -ENXIO;
+ 
+-	if (file->f_flags & O_NONBLOCK) {
+-		if (!mutex_trylock(&urd->open_mutex)) {
++	spin_lock(&urd->open_lock);
++	while (urd->open_flag) {
++		spin_unlock(&urd->open_lock);
++		if (file->f_flags & O_NONBLOCK) {
+ 			rc = -EBUSY;
+ 			goto fail_put;
+ 		}
+-	} else {
+-		if (mutex_lock_interruptible(&urd->open_mutex)) {
++		if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) {
+ 			rc = -ERESTARTSYS;
+ 			goto fail_put;
+ 		}
++		spin_lock(&urd->open_lock);
+ 	}
++	urd->open_flag++;
++	spin_unlock(&urd->open_lock);
+ 
+ 	TRACE("ur_open\n");
+ 
+@@ -720,7 +725,9 @@ static int ur_open(struct inode *inode, struct file *file)
+ fail_urfile_free:
+ 	urfile_free(urf);
+ fail_unlock:
+-	mutex_unlock(&urd->open_mutex);
++	spin_lock(&urd->open_lock);
++	urd->open_flag--;
++	spin_unlock(&urd->open_lock);
+ fail_put:
+ 	urdev_put(urd);
+ 	return rc;
+@@ -731,7 +738,10 @@ static int ur_release(struct inode *inode, struct file *file)
+ 	struct urfile *urf = file->private_data;
+ 
+ 	TRACE("ur_release\n");
+-	mutex_unlock(&urf->urd->open_mutex);
++	spin_lock(&urf->urd->open_lock);
++	urf->urd->open_flag--;
++	spin_unlock(&urf->urd->open_lock);
++	wake_up_interruptible(&urf->urd->wait);
+ 	urdev_put(urf->urd);
+ 	urfile_free(urf);
+ 	return 0;
+diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h
+index fa95964..fa320ad 100644
+--- a/drivers/s390/char/vmur.h
++++ b/drivers/s390/char/vmur.h
+@@ -62,7 +62,6 @@ struct file_control_block {
+ struct urdev {
+ 	struct ccw_device *cdev;	/* Backpointer to ccw device */
+ 	struct mutex io_mutex;		/* Serialises device IO */
+-	struct mutex open_mutex;	/* Serialises access to device */
+ 	struct completion *io_done;	/* do_ur_io waits; irq completes */
+ 	struct device *device;
+ 	struct cdev *char_device;
+@@ -71,6 +70,9 @@ struct urdev {
+ 	int class;			/* VM device class */
+ 	int io_request_rc;		/* return code from I/O request */
+ 	atomic_t ref_count;		/* reference counter */
++	wait_queue_head_t wait;		/* wait queue to serialize open */
++	int open_flag;			/* "urdev is open" flag */
++	spinlock_t open_lock;		/* serialize critical sections */
+ };
+ 
+ /*
+diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
+index 6f40fac..19f8389 100644
+--- a/drivers/s390/char/vmwatchdog.c
++++ b/drivers/s390/char/vmwatchdog.c
+@@ -96,7 +96,7 @@ static int vmwdt_keepalive(void)
+ 
+ 	if (ret) {
+ 		printk(KERN_WARNING "%s: problem setting interval %d, "
+-			"cmd %s\n", __FUNCTION__, vmwdt_interval,
++			"cmd %s\n", __func__, vmwdt_interval,
+ 			vmwdt_cmd);
+ 	}
+ 	return ret;
+@@ -107,7 +107,7 @@ static int vmwdt_disable(void)
+ 	int ret = __diag288(wdt_cancel, 0, "", 0);
+ 	if (ret) {
+ 		printk(KERN_WARNING "%s: problem disabling watchdog\n",
+-			__FUNCTION__);
++			__func__);
+ 	}
+ 	return ret;
+ }
+diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
+index f523501..bbbd14e 100644
+--- a/drivers/s390/char/zcore.c
++++ b/drivers/s390/char/zcore.c
+@@ -224,7 +224,7 @@ static int __init init_cpu_info(enum arch_id arch)
+ 
+ 	sa = kmalloc(sizeof(*sa), GFP_KERNEL);
+ 	if (!sa) {
+-		ERROR_MSG("kmalloc failed: %s: %i\n",__FUNCTION__, __LINE__);
++		ERROR_MSG("kmalloc failed: %s: %i\n",__func__, __LINE__);
+ 		return -ENOMEM;
+ 	}
+ 	if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) {
+diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
+index 03914fa..fe1ad17 100644
+--- a/drivers/s390/cio/ccwgroup.c
++++ b/drivers/s390/cio/ccwgroup.c
+@@ -16,7 +16,6 @@
+ #include <linux/ctype.h>
+ #include <linux/dcache.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/ccwdev.h>
+ #include <asm/ccwgroup.h>
+ 
+diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
+index 007aaeb..5de8690 100644
+--- a/drivers/s390/cio/chsc.c
++++ b/drivers/s390/cio/chsc.c
+@@ -217,6 +217,8 @@ void chsc_chp_offline(struct chp_id chpid)
+ 
+ 	if (chp_get_status(chpid) <= 0)
+ 		return;
++	/* Wait until previous actions have settled. */
++	css_wait_for_slow_path();
+ 	for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &chpid);
+ }
+ 
+@@ -303,7 +305,8 @@ static void s390_process_res_acc (struct res_acc_data *res_data)
+ 		sprintf(dbf_txt, "fla%x", res_data->fla);
+ 		CIO_TRACE_EVENT( 2, dbf_txt);
+ 	}
+-
++	/* Wait until previous actions have settled. */
++	css_wait_for_slow_path();
+ 	/*
+ 	 * I/O resources may have become accessible.
+ 	 * Scan through all subchannels that may be concerned and
+@@ -561,9 +564,12 @@ void chsc_chp_online(struct chp_id chpid)
+ 	sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id);
+ 	CIO_TRACE_EVENT(2, dbf_txt);
+ 
+-	if (chp_get_status(chpid) != 0)
++	if (chp_get_status(chpid) != 0) {
++		/* Wait until previous actions have settled. */
++		css_wait_for_slow_path();
+ 		for_each_subchannel_staged(__chp_add, __chp_add_new_sch,
+ 					   &chpid);
++	}
+ }
+ 
+ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
+@@ -650,6 +656,8 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)
+  */
+ int chsc_chp_vary(struct chp_id chpid, int on)
+ {
++	/* Wait until previous actions have settled. */
++	css_wait_for_slow_path();
+ 	/*
+ 	 * Redo PathVerification on the devices the chpid connects to
+ 	 */
+@@ -758,7 +766,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
+ 	if (!secm_area)
+ 		return -ENOMEM;
+ 
+-	mutex_lock(&css->mutex);
+ 	if (enable && !css->cm_enabled) {
+ 		css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ 		css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+@@ -766,7 +773,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
+ 			free_page((unsigned long)css->cub_addr1);
+ 			free_page((unsigned long)css->cub_addr2);
+ 			free_page((unsigned long)secm_area);
+-			mutex_unlock(&css->mutex);
+ 			return -ENOMEM;
+ 		}
+ 	}
+@@ -787,7 +793,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
+ 		free_page((unsigned long)css->cub_addr1);
+ 		free_page((unsigned long)css->cub_addr2);
+ 	}
+-	mutex_unlock(&css->mutex);
+ 	free_page((unsigned long)secm_area);
+ 	return ret;
+ }
+diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
+index 60590a1..23ffcc4 100644
+--- a/drivers/s390/cio/cio.c
++++ b/drivers/s390/cio/cio.c
+@@ -24,6 +24,7 @@
+ #include <asm/ipl.h>
+ #include <asm/chpid.h>
+ #include <asm/airq.h>
++#include <asm/cpu.h>
+ #include "cio.h"
+ #include "css.h"
+ #include "chsc.h"
+@@ -649,13 +650,10 @@ do_IRQ (struct pt_regs *regs)
+ 
+ 	old_regs = set_irq_regs(regs);
+ 	irq_enter();
+-	asm volatile ("mc 0,0");
+-	if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
+-		/**
+-		 * Make sure that the i/o interrupt did not "overtake"
+-		 * the last HZ timer interrupt.
+-		 */
+-		account_ticks(S390_lowcore.int_clock);
++	s390_idle_check();
++	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
++		/* Serve timer interrupts first. */
++		clock_comparator_work();
+ 	/*
+ 	 * Get interrupt information from lowcore
+ 	 */
+@@ -672,10 +670,14 @@ do_IRQ (struct pt_regs *regs)
+ 			continue;
+ 		}
+ 		sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
+-		if (sch)
+-			spin_lock(sch->lock);
++		if (!sch) {
++			/* Clear pending interrupt condition. */
++			tsch(tpi_info->schid, irb);
++			continue;
++		}
++		spin_lock(sch->lock);
+ 		/* Store interrupt response block to lowcore. */
+-		if (tsch (tpi_info->schid, irb) == 0 && sch) {
++		if (tsch(tpi_info->schid, irb) == 0) {
+ 			/* Keep subchannel information word up to date. */
+ 			memcpy (&sch->schib.scsw, &irb->scsw,
+ 				sizeof (irb->scsw));
+@@ -683,8 +685,7 @@ do_IRQ (struct pt_regs *regs)
+ 			if (sch->driver && sch->driver->irq)
+ 				sch->driver->irq(sch);
+ 		}
+-		if (sch)
+-			spin_unlock(sch->lock);
++		spin_unlock(sch->lock);
+ 		/*
+ 		 * Are more interrupts pending?
+ 		 * If so, the tpi instruction will update the lowcore
+@@ -710,8 +711,9 @@ void *cio_get_console_priv(void)
+ /*
+  * busy wait for the next interrupt on the console
+  */
+-void
+-wait_cons_dev (void)
++void wait_cons_dev(void)
++	__releases(console_subchannel.lock)
++	__acquires(console_subchannel.lock)
+ {
+ 	unsigned long cr6      __attribute__ ((aligned (8)));
+ 	unsigned long save_cr6 __attribute__ ((aligned (8)));
+diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
+index 52afa4c..08f2235 100644
+--- a/drivers/s390/cio/cio.h
++++ b/drivers/s390/cio/cio.h
+@@ -100,6 +100,7 @@ extern int cio_modify (struct subchannel *);
+ 
+ int cio_create_sch_lock(struct subchannel *);
+ void do_adapter_IO(void);
++void do_IRQ(struct pt_regs *);
+ 
+ /* Use with care. */
+ #ifdef CONFIG_CCW_CONSOLE
+diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
+index 3b45bbe..c1afab5 100644
+--- a/drivers/s390/cio/css.c
++++ b/drivers/s390/cio/css.c
+@@ -533,6 +533,12 @@ void css_schedule_eval_all(void)
+ 	spin_unlock_irqrestore(&slow_subchannel_lock, flags);
+ }
+ 
++void css_wait_for_slow_path(void)
++{
++	flush_workqueue(ccw_device_notify_work);
++	flush_workqueue(slow_path_wq);
++}
++
+ /* Reprobe subchannel if unregistered. */
+ static int reprobe_subchannel(struct subchannel_id schid, void *data)
+ {
+@@ -683,10 +689,14 @@ css_cm_enable_show(struct device *dev, struct device_attribute *attr,
+ 		   char *buf)
+ {
+ 	struct channel_subsystem *css = to_css(dev);
++	int ret;
+ 
+ 	if (!css)
+ 		return 0;
+-	return sprintf(buf, "%x\n", css->cm_enabled);
++	mutex_lock(&css->mutex);
++	ret = sprintf(buf, "%x\n", css->cm_enabled);
++	mutex_unlock(&css->mutex);
++	return ret;
+ }
+ 
+ static ssize_t
+@@ -696,6 +706,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
+ 	struct channel_subsystem *css = to_css(dev);
+ 	int ret;
+ 
++	mutex_lock(&css->mutex);
+ 	switch (buf[0]) {
+ 	case '0':
+ 		ret = css->cm_enabled ? chsc_secm(css, 0) : 0;
+@@ -706,6 +717,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
+ 	default:
+ 		ret = -EINVAL;
+ 	}
++	mutex_unlock(&css->mutex);
+ 	return ret < 0 ? ret : count;
+ }
+ 
+@@ -752,9 +764,11 @@ static int css_reboot_event(struct notifier_block *this,
+ 		struct channel_subsystem *css;
+ 
+ 		css = channel_subsystems[i];
++		mutex_lock(&css->mutex);
+ 		if (css->cm_enabled)
+ 			if (chsc_secm(css, 0))
+ 				ret = NOTIFY_BAD;
++		mutex_unlock(&css->mutex);
+ 	}
+ 
+ 	return ret;
+diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
+index b705545..e191351 100644
+--- a/drivers/s390/cio/css.h
++++ b/drivers/s390/cio/css.h
+@@ -144,6 +144,7 @@ struct schib;
+ int css_sch_is_valid(struct schib *);
+ 
+ extern struct workqueue_struct *slow_path_wq;
++void css_wait_for_slow_path(void);
+ 
+ extern struct attribute_group *subch_attr_groups[];
+ #endif
+diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
+index fec004f..e0c7adb 100644
+--- a/drivers/s390/cio/device.c
++++ b/drivers/s390/cio/device.c
+@@ -577,7 +577,6 @@ static DEVICE_ATTR(devtype, 0444, devtype_show, NULL);
+ static DEVICE_ATTR(cutype, 0444, cutype_show, NULL);
+ static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
+ static DEVICE_ATTR(online, 0644, online_show, online_store);
+-extern struct device_attribute dev_attr_cmb_enable;
+ static DEVICE_ATTR(availability, 0444, available_show, NULL);
+ 
+ static struct attribute * subch_attrs[] = {
+diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
+index d40a2ff..cb08092 100644
+--- a/drivers/s390/cio/device.h
++++ b/drivers/s390/cio/device.h
+@@ -127,4 +127,5 @@ extern struct bus_type ccw_bus_type;
+ void retry_set_schib(struct ccw_device *cdev);
+ void cmf_retry_copy_block(struct ccw_device *);
+ int cmf_reenable(struct ccw_device *);
++extern struct device_attribute dev_attr_cmb_enable;
+ #endif
+diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
+index 49b58eb..a1718a0 100644
+--- a/drivers/s390/cio/device_ops.c
++++ b/drivers/s390/cio/device_ops.c
+@@ -193,8 +193,15 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
+ 			return -EACCES;
+ 	}
+ 	ret = cio_start_key (sch, cpa, lpm, key);
+-	if (ret == 0)
++	switch (ret) {
++	case 0:
+ 		cdev->private->intparm = intparm;
++		break;
++	case -EACCES:
++	case -ENODEV:
++		dev_fsm_event(cdev, DEV_EVENT_VERIFY);
++		break;
++	}
+ 	return ret;
+ }
+ 
+diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
+index ebe0848..4a38993 100644
+--- a/drivers/s390/cio/device_status.c
++++ b/drivers/s390/cio/device_status.c
+@@ -62,7 +62,7 @@ ccw_device_path_notoper(struct ccw_device *cdev)
+ 	stsch (sch->schid, &sch->schib);
+ 
+ 	CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are "
+-		      "not operational \n", __FUNCTION__,
++		      "not operational \n", __func__,
+ 		      sch->schid.ssid, sch->schid.sch_no,
+ 		      sch->schib.pmcw.pnom);
+ 
+@@ -312,6 +312,7 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
+ {
+ 	struct subchannel *sch;
+ 	struct ccw1 *sense_ccw;
++	int rc;
+ 
+ 	sch = to_subchannel(cdev->dev.parent);
+ 
+@@ -337,7 +338,10 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
+ 	/* Reset internal retry indication. */
+ 	cdev->private->flags.intretry = 0;
+ 
+-	return cio_start(sch, sense_ccw, 0xff);
++	rc = cio_start(sch, sense_ccw, 0xff);
++	if (rc == -ENODEV || rc == -EACCES)
++		dev_fsm_event(cdev, DEV_EVENT_VERIFY);
++	return rc;
+ }
+ 
+ /*
+diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
+index 2b5bfb7..10aa1e7 100644
+--- a/drivers/s390/cio/qdio.c
++++ b/drivers/s390/cio/qdio.c
+@@ -38,11 +38,11 @@
+ #include <linux/proc_fs.h>
+ #include <linux/timer.h>
+ #include <linux/mempool.h>
++#include <linux/semaphore.h>
+ 
+ #include <asm/ccwdev.h>
+ #include <asm/io.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <asm/timex.h>
+ 
+ #include <asm/debug.h>
+@@ -1399,7 +1399,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
+ 	 * q->dev_st_chg_ind is the indicator, be it shared or not.
+ 	 * only clear it, if indicator is non-shared
+ 	 */
+-	if (!spare_ind_was_set)
++	if (q->dev_st_chg_ind != &spare_indicator)
+ 		tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);
+ 
+ 	if (q->hydra_gives_outbound_pcis) {
+@@ -2217,9 +2217,78 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
+ 	return cc;
+ }
+ 
++static int
++qdio_get_ssqd_information(struct subchannel_id *schid,
++			  struct qdio_chsc_ssqd **ssqd_area)
++{
++	int result;
++
++	QDIO_DBF_TEXT0(0, setup, "getssqd");
++	*ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
++	if (!ssqd_area) {
++		QDIO_PRINT_WARN("Could not get memory for chsc on sch x%x.\n",
++				schid->sch_no);
++		return -ENOMEM;
++	}
++
++	(*ssqd_area)->request = (struct chsc_header) {
++		.length = 0x0010,
++		.code	= 0x0024,
++	};
++	(*ssqd_area)->first_sch = schid->sch_no;
++	(*ssqd_area)->last_sch = schid->sch_no;
++	(*ssqd_area)->ssid = schid->ssid;
++	result = chsc(*ssqd_area);
++
++	if (result) {
++		QDIO_PRINT_WARN("CHSC returned cc %i on sch 0.%x.%x.\n",
++				result, schid->ssid, schid->sch_no);
++		goto out;
++	}
++
++	if ((*ssqd_area)->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
++		QDIO_PRINT_WARN("CHSC response is 0x%x on sch 0.%x.%x.\n",
++				(*ssqd_area)->response.code,
++				schid->ssid, schid->sch_no);
++		goto out;
++	}
++	if (!((*ssqd_area)->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
++	    !((*ssqd_area)->flags & CHSC_FLAG_VALIDITY) ||
++	    ((*ssqd_area)->sch != schid->sch_no)) {
++		QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
++				"using all SIGAs.\n",
++				schid->ssid, schid->sch_no);
++		goto out;
++	}
++	return 0;
++out:
++	return -EINVAL;
++}
++
++int
++qdio_get_ssqd_pct(struct ccw_device *cdev)
++{
++	struct qdio_chsc_ssqd *ssqd_area;
++	struct subchannel_id schid;
++	char dbf_text[15];
++	int rc;
++	int pct = 0;
++
++	QDIO_DBF_TEXT0(0, setup, "getpct");
++	schid = ccw_device_get_subchannel_id(cdev);
++	rc = qdio_get_ssqd_information(&schid, &ssqd_area);
++	if (!rc)
++		pct = (int)ssqd_area->pct;
++	if (rc != -ENOMEM)
++		mempool_free(ssqd_area, qdio_mempool_scssc);
++	sprintf(dbf_text, "pct: %d", pct);
++	QDIO_DBF_TEXT2(0, setup, dbf_text);
++	return pct;
++}
++EXPORT_SYMBOL(qdio_get_ssqd_pct);
++
+ static void
+-qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
+-			    unsigned long token)
++qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned long token)
+ {
+ 	struct qdio_q *q;
+ 	int i;
+@@ -2227,7 +2296,7 @@ qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
+ 	char dbf_text[15];
+ 
+ 	/*check if QEBSM is disabled */
+-	if (!(irq_ptr->is_qebsm) || !(qdioac & 0x01)) {
++	if (!(irq_ptr->is_qebsm) || !(irq_ptr->qdioac & 0x01)) {
+ 		irq_ptr->is_qebsm  = 0;
+ 		irq_ptr->sch_token = 0;
+ 		irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+@@ -2256,102 +2325,27 @@ qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
+ }
+ 
+ static void
+-qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
++qdio_get_ssqd_siga(struct qdio_irq *irq_ptr)
+ {
+-	int result;
+-	unsigned char qdioac;
+-	struct {
+-		struct chsc_header request;
+-		u16 reserved1:10;
+-		u16 ssid:2;
+-		u16 fmt:4;
+-		u16 first_sch;
+-		u16 reserved2;
+-		u16 last_sch;
+-		u32 reserved3;
+-		struct chsc_header response;
+-		u32 reserved4;
+-		u8  flags;
+-		u8  reserved5;
+-		u16 sch;
+-		u8  qfmt;
+-		u8  parm;
+-		u8  qdioac1;
+-		u8  sch_class;
+-		u8  reserved7;
+-		u8  icnt;
+-		u8  reserved8;
+-		u8  ocnt;
+-		u8 reserved9;
+-		u8 mbccnt;
+-		u16 qdioac2;
+-		u64 sch_token;
+-	} *ssqd_area;
++	int rc;
++	struct qdio_chsc_ssqd *ssqd_area;
+ 
+ 	QDIO_DBF_TEXT0(0,setup,"getssqd");
+-	qdioac = 0;
+-	ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
+-	if (!ssqd_area) {
+-	        QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
+-				"SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
++	irq_ptr->qdioac = 0;
++	rc = qdio_get_ssqd_information(&irq_ptr->schid, &ssqd_area);
++	if (rc) {
++		QDIO_PRINT_WARN("using all SIGAs for sch x%x.n",
++			irq_ptr->schid.sch_no);
+ 		irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+ 				  CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
+ 				  CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ 		irq_ptr->is_qebsm = 0;
+-		irq_ptr->sch_token = 0;
+-		irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+-		return;
+-	}
+-
+-	ssqd_area->request = (struct chsc_header) {
+-		.length = 0x0010,
+-		.code   = 0x0024,
+-	};
+-	ssqd_area->first_sch = irq_ptr->schid.sch_no;
+-	ssqd_area->last_sch = irq_ptr->schid.sch_no;
+-	ssqd_area->ssid = irq_ptr->schid.ssid;
+-	result = chsc(ssqd_area);
+-
+-	if (result) {
+-		QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
+-				"SIGAs for sch 0.%x.%x.\n", result,
+-				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
+-		qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+-			CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
+-			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+-		irq_ptr->is_qebsm  = 0;
+-		goto out;
+-	}
++	} else
++		irq_ptr->qdioac = ssqd_area->qdioac1;
+ 
+-	if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
+-		QDIO_PRINT_WARN("response upon checking SIGA needs " \
+-				"is 0x%x. Using all SIGAs for sch 0.%x.%x.\n",
+-				ssqd_area->response.code,
+-				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
+-		qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+-			CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
+-			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+-		irq_ptr->is_qebsm  = 0;
+-		goto out;
+-	}
+-	if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
+-	    !(ssqd_area->flags & CHSC_FLAG_VALIDITY) ||
+-	    (ssqd_area->sch != irq_ptr->schid.sch_no)) {
+-		QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
+-				"using all SIGAs.\n",
+-				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
+-		qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+-			CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
+-			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */
+-		irq_ptr->is_qebsm  = 0;
+-		goto out;
+-	}
+-	qdioac = ssqd_area->qdioac1;
+-out:
+-	qdio_check_subchannel_qebsm(irq_ptr, qdioac,
+-				    ssqd_area->sch_token);
+-	mempool_free(ssqd_area, qdio_mempool_scssc);
+-	irq_ptr->qdioac = qdioac;
++	qdio_check_subchannel_qebsm(irq_ptr, ssqd_area->sch_token);
++	if (rc != -ENOMEM)
++		mempool_free(ssqd_area, qdio_mempool_scssc);
+ }
+ 
+ static unsigned int
+@@ -3227,7 +3221,7 @@ qdio_establish(struct qdio_initialize *init_data)
+ 		return -EIO;
+ 	}
+ 
+-	qdio_get_ssqd_information(irq_ptr);
++	qdio_get_ssqd_siga(irq_ptr);
+ 	/* if this gets set once, we're running under VM and can omit SVSes */
+ 	if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY)
+ 		omit_svs=1;
+diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
+index da8a272..c3df6b2 100644
+--- a/drivers/s390/cio/qdio.h
++++ b/drivers/s390/cio/qdio.h
+@@ -406,6 +406,34 @@ do_clear_global_summary(void)
+ #define CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS 0x08
+ #define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
+ 
++struct qdio_chsc_ssqd {
++	struct chsc_header request;
++	u16 reserved1:10;
++	u16 ssid:2;
++	u16 fmt:4;
++	u16 first_sch;
++	u16 reserved2;
++	u16 last_sch;
++	u32 reserved3;
++	struct chsc_header response;
++	u32 reserved4;
++	u8  flags;
++	u8  reserved5;
++	u16 sch;
++	u8  qfmt;
++	u8  parm;
++	u8  qdioac1;
++	u8  sch_class;
++	u8  pct;
++	u8  icnt;
++	u8  reserved7;
++	u8  ocnt;
++	u8  reserved8;
++	u8  mbccnt;
++	u16 qdioac2;
++	u64 sch_token;
++};
++
+ struct qdio_perf_stats {
+ #ifdef CONFIG_64BIT
+ 	atomic64_t tl_runs;
+diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
+index 7b0b819..a1ab3e3 100644
+--- a/drivers/s390/crypto/ap_bus.c
++++ b/drivers/s390/crypto/ap_bus.c
+@@ -45,7 +45,7 @@ static int ap_poll_thread_start(void);
+ static void ap_poll_thread_stop(void);
+ static void ap_request_timeout(unsigned long);
+ 
+-/**
++/*
+  * Module description.
+  */
+ MODULE_AUTHOR("IBM Corporation");
+@@ -53,7 +53,7 @@ MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
+ 		   "Copyright 2006 IBM Corporation");
+ MODULE_LICENSE("GPL");
+ 
+-/**
++/*
+  * Module parameter
+  */
+ int ap_domain_index = -1;	/* Adjunct Processor Domain Index */
+@@ -69,7 +69,7 @@ static struct device *ap_root_device = NULL;
+ static DEFINE_SPINLOCK(ap_device_lock);
+ static LIST_HEAD(ap_device_list);
+ 
+-/**
++/*
+  * Workqueue & timer for bus rescan.
+  */
+ static struct workqueue_struct *ap_work_queue;
+@@ -77,7 +77,7 @@ static struct timer_list ap_config_timer;
+ static int ap_config_time = AP_CONFIG_TIME;
+ static DECLARE_WORK(ap_config_work, ap_scan_bus);
+ 
+-/**
++/*
+  * Tasklet & timer for AP request polling.
+  */
+ static struct timer_list ap_poll_timer = TIMER_INITIALIZER(ap_poll_timeout,0,0);
+@@ -88,9 +88,9 @@ static struct task_struct *ap_poll_kthread = NULL;
+ static DEFINE_MUTEX(ap_poll_thread_mutex);
+ 
+ /**
+- * Test if ap instructions are available.
++ * ap_intructions_available() - Test if AP instructions are available.
+  *
+- * Returns 0 if the ap instructions are installed.
++ * Returns 0 if the AP instructions are installed.
+  */
+ static inline int ap_instructions_available(void)
+ {
+@@ -108,12 +108,12 @@ static inline int ap_instructions_available(void)
+ }
+ 
+ /**
+- * Test adjunct processor queue.
+- * @qid: the ap queue number
+- * @queue_depth: pointer to queue depth value
+- * @device_type: pointer to device type value
++ * ap_test_queue(): Test adjunct processor queue.
++ * @qid: The AP queue number
++ * @queue_depth: Pointer to queue depth value
++ * @device_type: Pointer to device type value
+  *
+- * Returns ap queue status structure.
++ * Returns AP queue status structure.
+  */
+ static inline struct ap_queue_status
+ ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+@@ -130,10 +130,10 @@ ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+ }
+ 
+ /**
+- * Reset adjunct processor queue.
+- * @qid: the ap queue number
++ * ap_reset_queue(): Reset adjunct processor queue.
++ * @qid: The AP queue number
+  *
+- * Returns ap queue status structure.
++ * Returns AP queue status structure.
+  */
+ static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
+ {
+@@ -148,16 +148,14 @@ static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
+ }
+ 
+ /**
+- * Send message to adjunct processor queue.
+- * @qid: the ap queue number
+- * @psmid: the program supplied message identifier
+- * @msg: the message text
+- * @length: the message length
+- *
+- * Returns ap queue status structure.
++ * __ap_send(): Send message to adjunct processor queue.
++ * @qid: The AP queue number
++ * @psmid: The program supplied message identifier
++ * @msg: The message text
++ * @length: The message length
+  *
++ * Returns AP queue status structure.
+  * Condition code 1 on NQAP can't happen because the L bit is 1.
+- *
+  * Condition code 2 on NQAP also means the send is incomplete,
+  * because a segment boundary was reached. The NQAP is repeated.
+  */
+@@ -198,23 +196,20 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
+ }
+ EXPORT_SYMBOL(ap_send);
+ 
+-/*
+- * Receive message from adjunct processor queue.
+- * @qid: the ap queue number
+- * @psmid: pointer to program supplied message identifier
+- * @msg: the message text
+- * @length: the message length
+- *
+- * Returns ap queue status structure.
++/**
++ * __ap_recv(): Receive message from adjunct processor queue.
++ * @qid: The AP queue number
++ * @psmid: Pointer to program supplied message identifier
++ * @msg: The message text
++ * @length: The message length
+  *
++ * Returns AP queue status structure.
+  * Condition code 1 on DQAP means the receive has taken place
+  * but only partially.	The response is incomplete, hence the
+  * DQAP is repeated.
+- *
+  * Condition code 2 on DQAP also means the receive is incomplete,
+  * this time because a segment boundary was reached. Again, the
+  * DQAP is repeated.
+- *
+  * Note that gpr2 is used by the DQAP instruction to keep track of
+  * any 'residual' length, in case the instruction gets interrupted.
+  * Hence it gets zeroed before the instruction.
+@@ -263,11 +258,12 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
+ EXPORT_SYMBOL(ap_recv);
+ 
+ /**
+- * Check if an AP queue is available. The test is repeated for
+- * AP_MAX_RESET times.
+- * @qid: the ap queue number
+- * @queue_depth: pointer to queue depth value
+- * @device_type: pointer to device type value
++ * ap_query_queue(): Check if an AP queue is available.
++ * @qid: The AP queue number
++ * @queue_depth: Pointer to queue depth value
++ * @device_type: Pointer to device type value
++ *
++ * The test is repeated for AP_MAX_RESET times.
+  */
+ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+ {
+@@ -308,8 +304,10 @@ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+ }
+ 
+ /**
++ * ap_init_queue(): Reset an AP queue.
++ * @qid: The AP queue number
++ *
+  * Reset an AP queue and wait for it to become available again.
+- * @qid: the ap queue number
+  */
+ static int ap_init_queue(ap_qid_t qid)
+ {
+@@ -346,7 +344,10 @@ static int ap_init_queue(ap_qid_t qid)
+ }
+ 
+ /**
+- * Arm request timeout if a AP device was idle and a new request is submitted.
++ * ap_increase_queue_count(): Arm request timeout.
++ * @ap_dev: Pointer to an AP device.
++ *
++ * Arm request timeout if an AP device was idle and a new request is submitted.
+  */
+ static void ap_increase_queue_count(struct ap_device *ap_dev)
+ {
+@@ -360,7 +361,10 @@ static void ap_increase_queue_count(struct ap_device *ap_dev)
+ }
+ 
+ /**
+- * AP device is still alive, re-schedule request timeout if there are still
++ * ap_decrease_queue_count(): Decrease queue count.
++ * @ap_dev: Pointer to an AP device.
++ *
++ * If AP device is still alive, re-schedule request timeout if there are still
+  * pending requests.
+  */
+ static void ap_decrease_queue_count(struct ap_device *ap_dev)
+@@ -371,7 +375,7 @@ static void ap_decrease_queue_count(struct ap_device *ap_dev)
+ 	if (ap_dev->queue_count > 0)
+ 		mod_timer(&ap_dev->timeout, jiffies + timeout);
+ 	else
+-		/**
++		/*
+ 		 * The timeout timer should to be disabled now - since
+ 		 * del_timer_sync() is very expensive, we just tell via the
+ 		 * reset flag to ignore the pending timeout timer.
+@@ -379,7 +383,7 @@ static void ap_decrease_queue_count(struct ap_device *ap_dev)
+ 		ap_dev->reset = AP_RESET_IGNORE;
+ }
+ 
+-/**
++/*
+  * AP device related attributes.
+  */
+ static ssize_t ap_hwtype_show(struct device *dev,
+@@ -433,6 +437,10 @@ static struct attribute_group ap_dev_attr_group = {
+ };
+ 
+ /**
++ * ap_bus_match()
++ * @dev: Pointer to device
++ * @drv: Pointer to device_driver
++ *
+  * AP bus driver registration/unregistration.
+  */
+ static int ap_bus_match(struct device *dev, struct device_driver *drv)
+@@ -441,7 +449,7 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv)
+ 	struct ap_driver *ap_drv = to_ap_drv(drv);
+ 	struct ap_device_id *id;
+ 
+-	/**
++	/*
+ 	 * Compare device type of the device with the list of
+ 	 * supported types of the device_driver.
+ 	 */
+@@ -455,8 +463,12 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv)
+ }
+ 
+ /**
+- * uevent function for AP devices. It sets up a single environment
+- * variable DEV_TYPE which contains the hardware device type.
++ * ap_uevent(): Uevent function for AP devices.
++ * @dev: Pointer to device
++ * @env: Pointer to kobj_uevent_env
++ *
++ * It sets up a single environment variable DEV_TYPE which contains the
++ * hardware device type.
+  */
+ static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
+ {
+@@ -500,8 +512,10 @@ static int ap_device_probe(struct device *dev)
+ }
+ 
+ /**
++ * __ap_flush_queue(): Flush requests.
++ * @ap_dev: Pointer to the AP device
++ *
+  * Flush all requests from the request/pending queue of an AP device.
+- * @ap_dev: pointer to the AP device.
+  */
+ static void __ap_flush_queue(struct ap_device *ap_dev)
+ {
+@@ -565,7 +579,7 @@ void ap_driver_unregister(struct ap_driver *ap_drv)
+ }
+ EXPORT_SYMBOL(ap_driver_unregister);
+ 
+-/**
++/*
+  * AP bus attributes.
+  */
+ static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
+@@ -630,14 +644,16 @@ static struct bus_attribute *const ap_bus_attrs[] = {
+ };
+ 
+ /**
+- * Pick one of the 16 ap domains.
++ * ap_select_domain(): Select an AP domain.
++ *
++ * Pick one of the 16 AP domains.
+  */
+ static int ap_select_domain(void)
+ {
+ 	int queue_depth, device_type, count, max_count, best_domain;
+ 	int rc, i, j;
+ 
+-	/**
++	/*
+ 	 * We want to use a single domain. Either the one specified with
+ 	 * the "domain=" parameter or the domain with the maximum number
+ 	 * of devices.
+@@ -669,8 +685,10 @@ static int ap_select_domain(void)
+ }
+ 
+ /**
+- * Find the device type if query queue returned a device type of 0.
++ * ap_probe_device_type(): Find the device type of an AP.
+  * @ap_dev: pointer to the AP device.
++ *
++ * Find the device type if query queue returned a device type of 0.
+  */
+ static int ap_probe_device_type(struct ap_device *ap_dev)
+ {
+@@ -764,7 +782,11 @@ out:
+ }
+ 
+ /**
+- * Scan the ap bus for new devices.
++ * __ap_scan_bus(): Scan the AP bus.
++ * @dev: Pointer to device
++ * @data: Pointer to data
++ *
++ * Scan the AP bus for new devices.
+  */
+ static int __ap_scan_bus(struct device *dev, void *data)
+ {
+@@ -867,6 +889,8 @@ ap_config_timeout(unsigned long ptr)
+ }
+ 
+ /**
++ * ap_schedule_poll_timer(): Schedule poll timer.
++ *
+  * Set up the timer to run the poll tasklet
+  */
+ static inline void ap_schedule_poll_timer(void)
+@@ -877,10 +901,11 @@ static inline void ap_schedule_poll_timer(void)
+ }
+ 
+ /**
+- * Receive pending reply messages from an AP device.
++ * ap_poll_read(): Receive pending reply messages from an AP device.
+  * @ap_dev: pointer to the AP device
+  * @flags: pointer to control flags, bit 2^0 is set if another poll is
+  *	   required, bit 2^1 is set if the poll timer needs to get armed
++ *
+  * Returns 0 if the device is still present, -ENODEV if not.
+  */
+ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
+@@ -925,10 +950,11 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
+ }
+ 
+ /**
+- * Send messages from the request queue to an AP device.
++ * ap_poll_write(): Send messages from the request queue to an AP device.
+  * @ap_dev: pointer to the AP device
+  * @flags: pointer to control flags, bit 2^0 is set if another poll is
+  *	   required, bit 2^1 is set if the poll timer needs to get armed
++ *
+  * Returns 0 if the device is still present, -ENODEV if not.
+  */
+ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
+@@ -968,11 +994,13 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
+ }
+ 
+ /**
+- * Poll AP device for pending replies and send new messages. If either
+- * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
++ * ap_poll_queue(): Poll AP device for pending replies and send new messages.
+  * @ap_dev: pointer to the bus device
+  * @flags: pointer to control flags, bit 2^0 is set if another poll is
+  *	   required, bit 2^1 is set if the poll timer needs to get armed
++ *
++ * Poll AP device for pending replies and send new messages. If either
++ * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
+  * Returns 0.
+  */
+ static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
+@@ -986,9 +1014,11 @@ static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
+ }
+ 
+ /**
+- * Queue a message to a device.
++ * __ap_queue_message(): Queue a message to a device.
+  * @ap_dev: pointer to the AP device
+  * @ap_msg: the message to be queued
++ *
++ * Queue a message to a device. Returns 0 if successful.
+  */
+ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+ {
+@@ -1055,12 +1085,14 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+ EXPORT_SYMBOL(ap_queue_message);
+ 
+ /**
++ * ap_cancel_message(): Cancel a crypto request.
++ * @ap_dev: The AP device that has the message queued
++ * @ap_msg: The message that is to be removed
++ *
+  * Cancel a crypto request. This is done by removing the request
+- * from the devive pendingq or requestq queue. Note that the
++ * from the device pending or request queue. Note that the
+  * request stays on the AP queue. When it finishes the message
+  * reply will be discarded because the psmid can't be found.
+- * @ap_dev: AP device that has the message queued
+- * @ap_msg: the message that is to be removed
+  */
+ void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+ {
+@@ -1082,7 +1114,10 @@ void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+ EXPORT_SYMBOL(ap_cancel_message);
+ 
+ /**
+- * AP receive polling for finished AP requests
++ * ap_poll_timeout(): AP receive polling for finished AP requests.
++ * @unused: Unused variable.
++ *
++ * Schedules the AP tasklet.
+  */
+ static void ap_poll_timeout(unsigned long unused)
+ {
+@@ -1090,6 +1125,9 @@ static void ap_poll_timeout(unsigned long unused)
+ }
+ 
+ /**
++ * ap_reset(): Reset a not responding AP device.
++ * @ap_dev: Pointer to the AP device
++ *
+  * Reset a not responding AP device and move all requests from the
+  * pending queue to the request queue.
+  */
+@@ -1108,11 +1146,6 @@ static void ap_reset(struct ap_device *ap_dev)
+ 		ap_dev->unregistered = 1;
+ }
+ 
+-/**
+- * Poll all AP devices on the bus in a round robin fashion. Continue
+- * polling until bit 2^0 of the control flags is not set. If bit 2^1
+- * of the control flags has been set arm the poll timer.
+- */
+ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
+ {
+ 	spin_lock(&ap_dev->lock);
+@@ -1126,6 +1159,14 @@ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
+ 	return 0;
+ }
+ 
++/**
++ * ap_poll_all(): Poll all AP devices.
++ * @dummy: Unused variable
++ *
++ * Poll all AP devices on the bus in a round robin fashion. Continue
++ * polling until bit 2^0 of the control flags is not set. If bit 2^1
++ * of the control flags has been set arm the poll timer.
++ */
+ static void ap_poll_all(unsigned long dummy)
+ {
+ 	unsigned long flags;
+@@ -1144,6 +1185,9 @@ static void ap_poll_all(unsigned long dummy)
+ }
+ 
+ /**
++ * ap_poll_thread(): Thread that polls for finished requests.
++ * @data: Unused pointer
++ *
+  * AP bus poll thread. The purpose of this thread is to poll for
+  * finished requests in a loop if there is a "free" cpu - that is
+  * a cpu that doesn't have anything better to do. The polling stops
+@@ -1213,7 +1257,10 @@ static void ap_poll_thread_stop(void)
+ }
+ 
+ /**
+- * Handling of request timeouts
++ * ap_request_timeout(): Handling of request timeouts
++ * @data: Holds the AP device.
++ *
++ * Handles request timeouts.
+  */
+ static void ap_request_timeout(unsigned long data)
+ {
+@@ -1246,7 +1293,9 @@ static struct reset_call ap_reset_call = {
+ };
+ 
+ /**
+- * The module initialization code.
++ * ap_module_init(): The module initialization code.
++ *
++ * Initializes the module.
+  */
+ int __init ap_module_init(void)
+ {
+@@ -1288,7 +1337,7 @@ int __init ap_module_init(void)
+ 	if (ap_select_domain() == 0)
+ 		ap_scan_bus(NULL);
+ 
+-	/* Setup the ap bus rescan timer. */
++	/* Setup the AP bus rescan timer. */
+ 	init_timer(&ap_config_timer);
+ 	ap_config_timer.function = ap_config_timeout;
+ 	ap_config_timer.data = 0;
+@@ -1325,7 +1374,9 @@ static int __ap_match_all(struct device *dev, void *data)
+ }
+ 
+ /**
+- * The module termination code
++ * ap_modules_exit(): The module termination code
++ *
++ * Terminates the module.
+  */
+ void ap_module_exit(void)
+ {
+diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
+index 87c2d64..c1e1200 100644
+--- a/drivers/s390/crypto/ap_bus.h
++++ b/drivers/s390/crypto/ap_bus.h
+@@ -50,6 +50,15 @@ typedef unsigned int ap_qid_t;
+ #define AP_QID_QUEUE(_qid) ((_qid) & 15)
+ 
+ /**
++ * structy ap_queue_status - Holds the AP queue status.
++ * @queue_empty: Shows if queue is empty
++ * @replies_waiting: Waiting replies
++ * @queue_full: Is 1 if the queue is full
++ * @pad: A 4 bit pad
++ * @int_enabled: Shows if interrupts are enabled for the AP
++ * @response_conde: Holds the 8 bit response code
++ * @pad2: A 16 bit pad
++ *
+  * The ap queue status word is returned by all three AP functions
+  * (PQAP, NQAP and DQAP).  There's a set of flags in the first
+  * byte, followed by a 1 byte response code.
+@@ -75,7 +84,7 @@ struct ap_queue_status {
+ #define AP_RESPONSE_NO_FIRST_PART	0x13
+ #define AP_RESPONSE_MESSAGE_TOO_BIG	0x15
+ 
+-/**
++/*
+  * Known device types
+  */
+ #define AP_DEVICE_TYPE_PCICC	3
+@@ -84,7 +93,7 @@ struct ap_queue_status {
+ #define AP_DEVICE_TYPE_CEX2A	6
+ #define AP_DEVICE_TYPE_CEX2C	7
+ 
+-/**
++/*
+  * AP reset flag states
+  */
+ #define AP_RESET_IGNORE	0	/* request timeout will be ignored */
+@@ -152,7 +161,7 @@ struct ap_message {
+ 	.dev_type=(dt),					\
+ 	.match_flags=AP_DEVICE_ID_MATCH_DEVICE_TYPE,
+ 
+-/**
++/*
+  * Note: don't use ap_send/ap_recv after using ap_queue_message
+  * for the first time. Otherwise the ap message queue will get
+  * confused.
+diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
+index e3625a4..4d36e80 100644
+--- a/drivers/s390/crypto/zcrypt_api.c
++++ b/drivers/s390/crypto/zcrypt_api.c
+@@ -36,10 +36,11 @@
+ #include <linux/compat.h>
+ #include <asm/atomic.h>
+ #include <asm/uaccess.h>
++#include <linux/hw_random.h>
+ 
+ #include "zcrypt_api.h"
+ 
+-/**
++/*
+  * Module description.
+  */
+ MODULE_AUTHOR("IBM Corporation");
+@@ -52,7 +53,10 @@ static LIST_HEAD(zcrypt_device_list);
+ static int zcrypt_device_count = 0;
+ static atomic_t zcrypt_open_count = ATOMIC_INIT(0);
+ 
+-/**
++static int zcrypt_rng_device_add(void);
++static void zcrypt_rng_device_remove(void);
++
++/*
+  * Device attributes common for all crypto devices.
+  */
+ static ssize_t zcrypt_type_show(struct device *dev,
+@@ -99,6 +103,9 @@ static struct attribute_group zcrypt_device_attr_group = {
+ };
+ 
+ /**
++ * __zcrypt_increase_preference(): Increase preference of a crypto device.
++ * @zdev: Pointer the crypto device
++ *
+  * Move the device towards the head of the device list.
+  * Need to be called while holding the zcrypt device list lock.
+  * Note: cards with speed_rating of 0 are kept at the end of the list.
+@@ -125,6 +132,9 @@ static void __zcrypt_increase_preference(struct zcrypt_device *zdev)
+ }
+ 
+ /**
++ * __zcrypt_decrease_preference(): Decrease preference of a crypto device.
++ * @zdev: Pointer to a crypto device.
++ *
+  * Move the device towards the tail of the device list.
+  * Need to be called while holding the zcrypt device list lock.
+  * Note: cards with speed_rating of 0 are kept at the end of the list.
+@@ -198,7 +208,10 @@ void zcrypt_device_free(struct zcrypt_device *zdev)
+ EXPORT_SYMBOL(zcrypt_device_free);
+ 
+ /**
+- * Register a crypto device.
++ * zcrypt_device_register() - Register a crypto device.
++ * @zdev: Pointer to a crypto device
++ *
++ * Register a crypto device. Returns 0 if successful.
+  */
+ int zcrypt_device_register(struct zcrypt_device *zdev)
+ {
+@@ -216,16 +229,37 @@ int zcrypt_device_register(struct zcrypt_device *zdev)
+ 	__zcrypt_increase_preference(zdev);
+ 	zcrypt_device_count++;
+ 	spin_unlock_bh(&zcrypt_device_lock);
++	if (zdev->ops->rng) {
++		rc = zcrypt_rng_device_add();
++		if (rc)
++			goto out_unregister;
++	}
++	return 0;
++
++out_unregister:
++	spin_lock_bh(&zcrypt_device_lock);
++	zcrypt_device_count--;
++	list_del_init(&zdev->list);
++	spin_unlock_bh(&zcrypt_device_lock);
++	sysfs_remove_group(&zdev->ap_dev->device.kobj,
++			   &zcrypt_device_attr_group);
++	put_device(&zdev->ap_dev->device);
++	zcrypt_device_put(zdev);
+ out:
+ 	return rc;
+ }
+ EXPORT_SYMBOL(zcrypt_device_register);
+ 
+ /**
++ * zcrypt_device_unregister(): Unregister a crypto device.
++ * @zdev: Pointer to crypto device
++ *
+  * Unregister a crypto device.
+  */
+ void zcrypt_device_unregister(struct zcrypt_device *zdev)
+ {
++	if (zdev->ops->rng)
++		zcrypt_rng_device_remove();
+ 	spin_lock_bh(&zcrypt_device_lock);
+ 	zcrypt_device_count--;
+ 	list_del_init(&zdev->list);
+@@ -238,7 +272,9 @@ void zcrypt_device_unregister(struct zcrypt_device *zdev)
+ EXPORT_SYMBOL(zcrypt_device_unregister);
+ 
+ /**
+- * zcrypt_read is not be supported beyond zcrypt 1.3.1
++ * zcrypt_read (): Not supported beyond zcrypt 1.3.1.
++ *
++ * This function is not supported beyond zcrypt 1.3.1.
+  */
+ static ssize_t zcrypt_read(struct file *filp, char __user *buf,
+ 			   size_t count, loff_t *f_pos)
+@@ -247,6 +283,8 @@ static ssize_t zcrypt_read(struct file *filp, char __user *buf,
+ }
+ 
+ /**
++ * zcrypt_write(): Not allowed.
++ *
+  * Write is is not allowed
+  */
+ static ssize_t zcrypt_write(struct file *filp, const char __user *buf,
+@@ -256,7 +294,9 @@ static ssize_t zcrypt_write(struct file *filp, const char __user *buf,
+ }
+ 
+ /**
+- * Device open/close functions to count number of users.
++ * zcrypt_open(): Count number of users.
++ *
++ * Device open function to count number of users.
+  */
+ static int zcrypt_open(struct inode *inode, struct file *filp)
+ {
+@@ -264,13 +304,18 @@ static int zcrypt_open(struct inode *inode, struct file *filp)
+ 	return 0;
+ }
+ 
++/**
++ * zcrypt_release(): Count number of users.
++ *
++ * Device close function to count number of users.
++ */
+ static int zcrypt_release(struct inode *inode, struct file *filp)
+ {
+ 	atomic_dec(&zcrypt_open_count);
+ 	return 0;
+ }
+ 
+-/**
++/*
+  * zcrypt ioctls.
+  */
+ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
+@@ -280,7 +325,7 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
+ 
+ 	if (mex->outputdatalength < mex->inputdatalength)
+ 		return -EINVAL;
+-	/**
++	/*
+ 	 * As long as outputdatalength is big enough, we can set the
+ 	 * outputdatalength equal to the inputdatalength, since that is the
+ 	 * number of bytes we will copy in any case
+@@ -326,7 +371,7 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
+ 	if (crt->outputdatalength < crt->inputdatalength ||
+ 	    (crt->inputdatalength & 1))
+ 		return -EINVAL;
+-	/**
++	/*
+ 	 * As long as outputdatalength is big enough, we can set the
+ 	 * outputdatalength equal to the inputdatalength, since that is the
+ 	 * number of bytes we will copy in any case
+@@ -343,7 +388,7 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
+ 		    zdev->max_mod_size < crt->inputdatalength)
+ 			continue;
+ 		if (zdev->short_crt && crt->inputdatalength > 240) {
+-			/**
++			/*
+ 			 * Check inputdata for leading zeros for cards
+ 			 * that can't handle np_prime, bp_key, or
+ 			 * u_mult_inv > 128 bytes.
+@@ -359,7 +404,7 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
+ 				    copy_from_user(&z3, crt->u_mult_inv, len))
+ 					return -EFAULT;
+ 				copied = 1;
+-				/**
++				/*
+ 				 * We have to restart device lookup -
+ 				 * the device list may have changed by now.
+ 				 */
+@@ -427,6 +472,37 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
+ 	return -ENODEV;
+ }
+ 
++static long zcrypt_rng(char *buffer)
++{
++	struct zcrypt_device *zdev;
++	int rc;
++
++	spin_lock_bh(&zcrypt_device_lock);
++	list_for_each_entry(zdev, &zcrypt_device_list, list) {
++		if (!zdev->online || !zdev->ops->rng)
++			continue;
++		zcrypt_device_get(zdev);
++		get_device(&zdev->ap_dev->device);
++		zdev->request_count++;
++		__zcrypt_decrease_preference(zdev);
++		if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
++			spin_unlock_bh(&zcrypt_device_lock);
++			rc = zdev->ops->rng(zdev, buffer);
++			spin_lock_bh(&zcrypt_device_lock);
++			module_put(zdev->ap_dev->drv->driver.owner);
++		} else
++			rc = -EAGAIN;
++		zdev->request_count--;
++		__zcrypt_increase_preference(zdev);
++		put_device(&zdev->ap_dev->device);
++		zcrypt_device_put(zdev);
++		spin_unlock_bh(&zcrypt_device_lock);
++		return rc;
++	}
++	spin_unlock_bh(&zcrypt_device_lock);
++	return -ENODEV;
++}
++
+ static void zcrypt_status_mask(char status[AP_DEVICES])
+ {
+ 	struct zcrypt_device *zdev;
+@@ -514,6 +590,8 @@ static int zcrypt_count_type(int type)
+ }
+ 
+ /**
++ * zcrypt_ica_status(): Old, depracted combi status call.
++ *
+  * Old, deprecated combi status call.
+  */
+ static long zcrypt_ica_status(struct file *filp, unsigned long arg)
+@@ -615,7 +693,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
+ 				(int __user *) arg);
+ 	case Z90STAT_DOMAIN_INDEX:
+ 		return put_user(ap_domain_index, (int __user *) arg);
+-	/**
++	/*
+ 	 * Deprecated ioctls. Don't add another device count ioctl,
+ 	 * you can count them yourself in the user space with the
+ 	 * output of the Z90STAT_STATUS_MASK ioctl.
+@@ -653,7 +731,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
+ }
+ 
+ #ifdef CONFIG_COMPAT
+-/**
++/*
+  * ioctl32 conversion routines
+  */
+ struct compat_ica_rsa_modexpo {
+@@ -804,7 +882,7 @@ static long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd,
+ }
+ #endif
+ 
+-/**
++/*
+  * Misc device file operations.
+  */
+ static const struct file_operations zcrypt_fops = {
+@@ -819,7 +897,7 @@ static const struct file_operations zcrypt_fops = {
+ 	.release	= zcrypt_release
+ };
+ 
+-/**
++/*
+  * Misc device.
+  */
+ static struct miscdevice zcrypt_misc_device = {
+@@ -828,7 +906,7 @@ static struct miscdevice zcrypt_misc_device = {
+ 	.fops	    = &zcrypt_fops,
+ };
+ 
+-/**
++/*
+  * Deprecated /proc entry support.
+  */
+ static struct proc_dir_entry *zcrypt_entry;
+@@ -1022,7 +1100,7 @@ static int zcrypt_status_write(struct file *file, const char __user *buffer,
+ 	}
+ 
+ 	for (j = 0; j < 64 && *ptr; ptr++) {
+-		/**
++		/*
+ 		 * '0' for no device, '1' for PCICA, '2' for PCICC,
+ 		 * '3' for PCIXCC_MCL2, '4' for PCIXCC_MCL3,
+ 		 * '5' for CEX2C and '6' for CEX2A'
+@@ -1041,7 +1119,76 @@ out:
+ 	return count;
+ }
+ 
++static int zcrypt_rng_device_count;
++static u32 *zcrypt_rng_buffer;
++static int zcrypt_rng_buffer_index;
++static DEFINE_MUTEX(zcrypt_rng_mutex);
++
++static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data)
++{
++	int rc;
++
++	/*
++	 * We don't need locking here because the RNG API guarantees serialized
++	 * read method calls.
++	 */
++	if (zcrypt_rng_buffer_index == 0) {
++		rc = zcrypt_rng((char *) zcrypt_rng_buffer);
++		if (rc < 0)
++			return -EIO;
++		zcrypt_rng_buffer_index = rc / sizeof *data;
++	}
++	*data = zcrypt_rng_buffer[--zcrypt_rng_buffer_index];
++	return sizeof *data;
++}
++
++static struct hwrng zcrypt_rng_dev = {
++	.name		= "zcrypt",
++	.data_read	= zcrypt_rng_data_read,
++};
++
++static int zcrypt_rng_device_add(void)
++{
++	int rc = 0;
++
++	mutex_lock(&zcrypt_rng_mutex);
++	if (zcrypt_rng_device_count == 0) {
++		zcrypt_rng_buffer = (u32 *) get_zeroed_page(GFP_KERNEL);
++		if (!zcrypt_rng_buffer) {
++			rc = -ENOMEM;
++			goto out;
++		}
++		zcrypt_rng_buffer_index = 0;
++		rc = hwrng_register(&zcrypt_rng_dev);
++		if (rc)
++			goto out_free;
++		zcrypt_rng_device_count = 1;
++	} else
++		zcrypt_rng_device_count++;
++	mutex_unlock(&zcrypt_rng_mutex);
++	return 0;
++
++out_free:
++	free_page((unsigned long) zcrypt_rng_buffer);
++out:
++	mutex_unlock(&zcrypt_rng_mutex);
++	return rc;
++}
++
++static void zcrypt_rng_device_remove(void)
++{
++	mutex_lock(&zcrypt_rng_mutex);
++	zcrypt_rng_device_count--;
++	if (zcrypt_rng_device_count == 0) {
++		hwrng_unregister(&zcrypt_rng_dev);
++		free_page((unsigned long) zcrypt_rng_buffer);
++	}
++	mutex_unlock(&zcrypt_rng_mutex);
++}
++
+ /**
++ * zcrypt_api_init(): Module initialization.
++ *
+  * The module initialization code.
+  */
+ int __init zcrypt_api_init(void)
+@@ -1076,6 +1223,8 @@ out:
+ }
+ 
+ /**
++ * zcrypt_api_exit(): Module termination.
++ *
+  * The module termination code.
+  */
+ void zcrypt_api_exit(void)
+diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
+index de4877e..5c6e222 100644
+--- a/drivers/s390/crypto/zcrypt_api.h
++++ b/drivers/s390/crypto/zcrypt_api.h
+@@ -43,17 +43,17 @@
+ #define DEV_NAME	"zcrypt"
+ 
+ #define PRINTK(fmt, args...) \
+-	printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
++	printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __func__ , ## args)
+ #define PRINTKN(fmt, args...) \
+ 	printk(KERN_DEBUG DEV_NAME ": " fmt, ## args)
+ #define PRINTKW(fmt, args...) \
+-	printk(KERN_WARNING DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
++	printk(KERN_WARNING DEV_NAME ": %s -> " fmt, __func__ , ## args)
+ #define PRINTKC(fmt, args...) \
+-	printk(KERN_CRIT DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
++	printk(KERN_CRIT DEV_NAME ": %s -> " fmt, __func__ , ## args)
+ 
+ #ifdef ZCRYPT_DEBUG
+ #define PDEBUG(fmt, args...) \
+-	printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
++	printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __func__ , ## args)
+ #else
+ #define PDEBUG(fmt, args...) do {} while (0)
+ #endif
+@@ -100,6 +100,13 @@ struct ica_z90_status {
+ #define ZCRYPT_CEX2C		5
+ #define ZCRYPT_CEX2A		6
+ 
++/**
++ * Large random numbers are pulled in 4096 byte chunks from the crypto cards
++ * and stored in a page. Be carefull when increasing this buffer due to size
++ * limitations for AP requests.
++ */
++#define ZCRYPT_RNG_BUFFER_SIZE	4096
++
+ struct zcrypt_device;
+ 
+ struct zcrypt_ops {
+@@ -107,6 +114,7 @@ struct zcrypt_ops {
+ 	long (*rsa_modexpo_crt)(struct zcrypt_device *,
+ 				struct ica_rsa_modexpo_crt *);
+ 	long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *);
++	long (*rng)(struct zcrypt_device *, char *);
+ };
+ 
+ struct zcrypt_device {
+diff --git a/drivers/s390/crypto/zcrypt_cca_key.h b/drivers/s390/crypto/zcrypt_cca_key.h
+index 8dbcf0e..ed82f2f 100644
+--- a/drivers/s390/crypto/zcrypt_cca_key.h
++++ b/drivers/s390/crypto/zcrypt_cca_key.h
+@@ -174,7 +174,7 @@ static inline int zcrypt_type6_mex_key_de(struct ica_rsa_modexpo *mex,
+ 	key->pvtMeHdr = static_pvt_me_hdr;
+ 	key->pvtMeSec = static_pvt_me_sec;
+ 	key->pubMeSec = static_pub_me_sec;
+-	/**
++	/*
+ 	 * In a private key, the modulus doesn't appear in the public
+ 	 * section. So, an arbitrary public exponent of 0x010001 will be
+ 	 * used.
+@@ -338,7 +338,7 @@ static inline int zcrypt_type6_crt_key(struct ica_rsa_modexpo_crt *crt,
+ 	pub = (struct cca_public_sec *)(key->key_parts + key_len);
+ 	*pub = static_cca_pub_sec;
+ 	pub->modulus_bit_len = 8 * crt->inputdatalength;
+-	/**
++	/*
+ 	 * In a private key, the modulus doesn't appear in the public
+ 	 * section. So, an arbitrary public exponent of 0x010001 will be
+ 	 * used.
+diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h
+index 2cb616b..3e27fe7 100644
+--- a/drivers/s390/crypto/zcrypt_error.h
++++ b/drivers/s390/crypto/zcrypt_error.h
+@@ -108,7 +108,7 @@ static inline int convert_error(struct zcrypt_device *zdev,
+ 		return -EINVAL;
+ 	case REP82_ERROR_MESSAGE_TYPE:
+ 	//   REP88_ERROR_MESSAGE_TYPE		// '20' CEX2A
+-		/**
++		/*
+ 		 * To sent a message of the wrong type is a bug in the
+ 		 * device driver. Warn about it, disable the device
+ 		 * and then repeat the request.
+diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
+index d6d59bf..17ea56c 100644
+--- a/drivers/s390/crypto/zcrypt_pcicc.c
++++ b/drivers/s390/crypto/zcrypt_pcicc.c
+@@ -42,7 +42,7 @@
+ #define PCICC_MAX_MOD_SIZE_OLD	128	/* 1024 bits */
+ #define PCICC_MAX_MOD_SIZE	256	/* 2048 bits */
+ 
+-/**
++/*
+  * PCICC cards need a speed rating of 0. This keeps them at the end of
+  * the zcrypt device list (see zcrypt_api.c). PCICC cards are only
+  * used if no other cards are present because they are slow and can only
+@@ -388,7 +388,7 @@ static int convert_type86(struct zcrypt_device *zdev,
+ 	reply_len = le16_to_cpu(msg->length) - 2;
+ 	if (reply_len > outputdatalength)
+ 		return -EINVAL;
+-	/**
++	/*
+ 	 * For all encipher requests, the length of the ciphertext (reply_len)
+ 	 * will always equal the modulus length. For MEX decipher requests
+ 	 * the output needs to get padded. Minimum pad size is 10.
+diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
+index 70b9ddc..0bc9b31 100644
+--- a/drivers/s390/crypto/zcrypt_pcixcc.c
++++ b/drivers/s390/crypto/zcrypt_pcixcc.c
+@@ -356,6 +356,55 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
+ }
+ 
+ /**
++ * Prepare a type6 CPRB message for random number generation
++ *
++ * @ap_dev: AP device pointer
++ * @ap_msg: pointer to AP message
++ */
++static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
++			       struct ap_message *ap_msg,
++			       unsigned random_number_length)
++{
++	struct {
++		struct type6_hdr hdr;
++		struct CPRBX cprbx;
++		char function_code[2];
++		short int rule_length;
++		char rule[8];
++		short int verb_length;
++		short int key_length;
++	} __attribute__((packed)) *msg = ap_msg->message;
++	static struct type6_hdr static_type6_hdrX = {
++		.type		= 0x06,
++		.offset1	= 0x00000058,
++		.agent_id	= {'C', 'A'},
++		.function_code	= {'R', 'L'},
++		.ToCardLen1	= sizeof *msg - sizeof(msg->hdr),
++		.FromCardLen1	= sizeof *msg - sizeof(msg->hdr),
++	};
++	static struct CPRBX static_cprbx = {
++		.cprb_len	= 0x00dc,
++		.cprb_ver_id	= 0x02,
++		.func_id	= {0x54, 0x32},
++		.req_parml	= sizeof *msg - sizeof(msg->hdr) -
++				  sizeof(msg->cprbx),
++		.rpl_msgbl	= sizeof *msg - sizeof(msg->hdr),
++	};
++
++	msg->hdr = static_type6_hdrX;
++	msg->hdr.FromCardLen2 = random_number_length,
++	msg->cprbx = static_cprbx;
++	msg->cprbx.rpl_datal = random_number_length,
++	msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
++	memcpy(msg->function_code, msg->hdr.function_code, 0x02);
++	msg->rule_length = 0x0a;
++	memcpy(msg->rule, "RANDOM  ", 8);
++	msg->verb_length = 0x02;
++	msg->key_length = 0x02;
++	ap_msg->length = sizeof *msg;
++}
++
++/**
+  * Copy results from a type 86 ICA reply message back to user space.
+  *
+  * @zdev: crypto device pointer
+@@ -452,7 +501,7 @@ static int convert_type86_ica(struct zcrypt_device *zdev,
+ 	reply_len = msg->length - 2;
+ 	if (reply_len > outputdatalength)
+ 		return -EINVAL;
+-	/**
++	/*
+ 	 * For all encipher requests, the length of the ciphertext (reply_len)
+ 	 * will always equal the modulus length. For MEX decipher requests
+ 	 * the output needs to get padded. Minimum pad size is 10.
+@@ -509,6 +558,26 @@ static int convert_type86_xcrb(struct zcrypt_device *zdev,
+ 	return 0;
+ }
+ 
++static int convert_type86_rng(struct zcrypt_device *zdev,
++			  struct ap_message *reply,
++			  char *buffer)
++{
++	struct {
++		struct type86_hdr hdr;
++		struct type86_fmt2_ext fmt2;
++		struct CPRBX cprbx;
++	} __attribute__((packed)) *msg = reply->message;
++	char *data = reply->message;
++
++	if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) {
++		PDEBUG("RNG response error on PCIXCC/CEX2C rc=%hu/rs=%hu\n",
++		       rc, rs);
++		return -EINVAL;
++	}
++	memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
++	return msg->fmt2.count2;
++}
++
+ static int convert_response_ica(struct zcrypt_device *zdev,
+ 			    struct ap_message *reply,
+ 			    char __user *outputdata,
+@@ -567,6 +636,31 @@ static int convert_response_xcrb(struct zcrypt_device *zdev,
+ 	}
+ }
+ 
++static int convert_response_rng(struct zcrypt_device *zdev,
++				 struct ap_message *reply,
++				 char *data)
++{
++	struct type86x_reply *msg = reply->message;
++
++	switch (msg->hdr.type) {
++	case TYPE82_RSP_CODE:
++	case TYPE88_RSP_CODE:
++		return -EINVAL;
++	case TYPE86_RSP_CODE:
++		if (msg->hdr.reply_code)
++			return -EINVAL;
++		if (msg->cprbx.cprb_ver_id == 0x02)
++			return convert_type86_rng(zdev, reply, data);
++		/* no break, incorrect cprb version is an unknown response */
++	default: /* Unknown response type, this should NEVER EVER happen */
++		PRINTK("Unrecognized Message Header: %08x%08x\n",
++		       *(unsigned int *) reply->message,
++		       *(unsigned int *) (reply->message+4));
++		zdev->online = 0;
++		return -EAGAIN;	/* repeat the request on a different device. */
++	}
++}
++
+ /**
+  * This function is called from the AP bus code after a crypto request
+  * "msg" has finished with the reply message "reply".
+@@ -736,6 +830,42 @@ out_free:
+ }
+ 
+ /**
++ * The request distributor calls this function if it picked the PCIXCC/CEX2C
++ * device to generate random data.
++ * @zdev: pointer to zcrypt_device structure that identifies the
++ *	  PCIXCC/CEX2C device to the request distributor
++ * @buffer: pointer to a memory page to return random data
++ */
++
++static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev,
++				    char *buffer)
++{
++	struct ap_message ap_msg;
++	struct response_type resp_type = {
++		.type = PCIXCC_RESPONSE_TYPE_XCRB,
++	};
++	int rc;
++
++	ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
++	if (!ap_msg.message)
++		return -ENOMEM;
++	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
++				atomic_inc_return(&zcrypt_step);
++	ap_msg.private = &resp_type;
++	rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
++	init_completion(&resp_type.work);
++	ap_queue_message(zdev->ap_dev, &ap_msg);
++	rc = wait_for_completion_interruptible(&resp_type.work);
++	if (rc == 0)
++		rc = convert_response_rng(zdev, &ap_msg, buffer);
++	else
++		/* Signal pending. */
++		ap_cancel_message(zdev->ap_dev, &ap_msg);
++	kfree(ap_msg.message);
++	return rc;
++}
++
++/**
+  * The crypto operations for a PCIXCC/CEX2C card.
+  */
+ static struct zcrypt_ops zcrypt_pcixcc_ops = {
+@@ -744,6 +874,13 @@ static struct zcrypt_ops zcrypt_pcixcc_ops = {
+ 	.send_cprb = zcrypt_pcixcc_send_cprb,
+ };
+ 
++static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = {
++	.rsa_modexpo = zcrypt_pcixcc_modexpo,
++	.rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
++	.send_cprb = zcrypt_pcixcc_send_cprb,
++	.rng = zcrypt_pcixcc_rng,
++};
++
+ /**
+  * Micro-code detection function. Its sends a message to a pcixcc card
+  * to find out the microcode level.
+@@ -859,6 +996,58 @@ out_free:
+ }
+ 
+ /**
++ * Large random number detection function. Its sends a message to a pcixcc
++ * card to find out if large random numbers are supported.
++ * @ap_dev: pointer to the AP device.
++ *
++ * Returns 1 if large random numbers are supported, 0 if not and < 0 on error.
++ */
++static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev)
++{
++	struct ap_message ap_msg;
++	unsigned long long psmid;
++	struct {
++		struct type86_hdr hdr;
++		struct type86_fmt2_ext fmt2;
++		struct CPRBX cprbx;
++	} __attribute__((packed)) *reply;
++	int rc, i;
++
++	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
++	if (!ap_msg.message)
++		return -ENOMEM;
++
++	rng_type6CPRB_msgX(ap_dev, &ap_msg, 4);
++	rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message,
++		     ap_msg.length);
++	if (rc)
++		goto out_free;
++
++	/* Wait for the test message to complete. */
++	for (i = 0; i < 2 * HZ; i++) {
++		msleep(1000 / HZ);
++		rc = ap_recv(ap_dev->qid, &psmid, ap_msg.message, 4096);
++		if (rc == 0 && psmid == 0x0102030405060708ULL)
++			break;
++	}
++
++	if (i >= 2 * HZ) {
++		/* Got no answer. */
++		rc = -ENODEV;
++		goto out_free;
++	}
++
++	reply = ap_msg.message;
++	if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
++		rc = 1;
++	else
++		rc = 0;
++out_free:
++	free_page((unsigned long) ap_msg.message);
++	return rc;
++}
++
++/**
+  * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
+  * since the bus_match already checked the hardware type. The PCIXCC
+  * cards come in two flavours: micro code level 2 and micro code level 3.
+@@ -874,7 +1063,6 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
+ 	if (!zdev)
+ 		return -ENOMEM;
+ 	zdev->ap_dev = ap_dev;
+-	zdev->ops = &zcrypt_pcixcc_ops;
+ 	zdev->online = 1;
+ 	if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
+ 		rc = zcrypt_pcixcc_mcl(ap_dev);
+@@ -901,6 +1089,15 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
+ 		zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
+ 		zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
+ 	}
++	rc = zcrypt_pcixcc_rng_supported(ap_dev);
++	if (rc < 0) {
++		zcrypt_device_free(zdev);
++		return rc;
++	}
++	if (rc)
++		zdev->ops = &zcrypt_pcixcc_with_rng_ops;
++	else
++		zdev->ops = &zcrypt_pcixcc_ops;
+ 	ap_dev->reply = &zdev->reply;
+ 	ap_dev->private = zdev;
+ 	rc = zcrypt_device_register(zdev);
+diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
+index eada69d..a7745c8 100644
+--- a/drivers/s390/net/Kconfig
++++ b/drivers/s390/net/Kconfig
+@@ -5,22 +5,25 @@ config LCS
+ 	tristate "Lan Channel Station Interface"
+ 	depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI)
+ 	help
+-	   Select this option if you want to use LCS networking  on IBM S/390
+-  	   or zSeries. This device driver supports Token Ring (IEEE 802.5),
+-  	   FDDI (IEEE 802.7) and Ethernet. 
+-	   This option is also available as a module which will be
+-	   called lcs.ko. If you do not know what it is, it's safe to say "Y".
++	   Select this option if you want to use LCS networking on IBM System z.
++	   This device driver supports Token Ring (IEEE 802.5),
++	   FDDI (IEEE 802.7) and Ethernet.
++	   To compile as a module, choose M. The module name is lcs.ko.
++	   If you do not know what it is, it's safe to choose Y.
+ 
+-config CTC
+-	tristate "CTC device support"
++config CTCM
++	tristate "CTC and MPC SNA device support"
+ 	depends on CCW && NETDEVICES
+ 	help
+-	  Select this option if you want to use channel-to-channel networking
+-	  on IBM S/390 or zSeries. This device driver supports real CTC
+-	  coupling using ESCON. It also supports virtual CTCs when running
+-	  under VM. It will use the channel device configuration if this is
+-	  available.  This option is also available as a module which will be
+-	  called ctc.ko.  If you do not know what it is, it's safe to say "Y".
++	  Select this option if you want to use channel-to-channel
++	  point-to-point networking on IBM System z.
++	  This device driver supports real CTC coupling using ESCON.
++	  It also supports virtual CTCs when running under VM.
++	  This driver also supports channel-to-channel MPC SNA devices.
++	  MPC is an SNA protocol device used by Communication Server for Linux.
++	  To compile as a module, choose M. The module name is ctcm.ko.
++	  To compile into the kernel, choose Y.
++	  If you do not need any channel-to-channel connection, choose N.
+ 
+ config NETIUCV
+ 	tristate "IUCV network device support (VM only)"
+@@ -29,9 +32,9 @@ config NETIUCV
+ 	  Select this option if you want to use inter-user communication
+ 	  vehicle networking under VM or VIF. It enables a fast communication
+ 	  link between VM guests. Using ifconfig a point-to-point connection
+-	  can be established to the Linux for zSeries and S7390 system
+-	  running on the other VM guest. This option is also available
+-	  as a module which will be called netiucv.ko. If unsure, say "Y".
++	  can be established to the Linux on IBM System z
++	  running on the other VM guest. To compile as a module, choose M.
++	  The module name is netiucv.ko. If unsure, choose Y.
+ 
+ config SMSGIUCV
+ 	tristate "IUCV special message support (VM only)"
+@@ -47,43 +50,46 @@ config CLAW
+ 	  This driver supports channel attached CLAW devices.
+ 	  CLAW is Common Link Access for Workstation.  Common devices
+           that use CLAW are RS/6000s, Cisco Routers (CIP) and 3172 devices.
+-	  To compile as a module choose M here:  The module will be called
+-	  claw.ko to compile into the kernel choose Y
++	  To compile as a module, choose M. The module name is claw.ko.
++	  To compile into the kernel, choose Y.
+ 
+ config QETH
+ 	tristate "Gigabit Ethernet device support"
+ 	depends on CCW && NETDEVICES && IP_MULTICAST && QDIO
+ 	help
+-	  This driver supports the IBM S/390 and zSeries OSA Express adapters
++	  This driver supports the IBM System z OSA Express adapters
+ 	  in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN
+ 	  interfaces in QDIO and HIPER mode.
+ 	
+-	  For details please refer to the documentation provided by IBM at   
+-	  <http://www10.software.ibm.com/developerworks/opensource/linux390>
++	  For details please refer to the documentation provided by IBM at
++	  <http://www.ibm.com/developerworks/linux/linux390>
+ 
+-	  To compile this driver as a module, choose M here: the
+-	  module will be called qeth.ko.
++	  To compile this driver as a module, choose M.
++	  The module name is qeth.ko.
+ 
++config QETH_L2
++        tristate "qeth layer 2 device support"
++        depends on QETH
++        help
++          Select this option to be able to run qeth devices in layer 2 mode.
++          To compile as a module, choose M. The module name is qeth_l2.ko.
++          If unsure, choose y.
+ 
+-comment "Gigabit Ethernet default settings"
+-	depends on QETH
++config QETH_L3
++        tristate "qeth layer 3 device support"
++        depends on QETH
++        help
++          Select this option to be able to run qeth devices in layer 3 mode.
++          To compile as a module choose M. The module name is qeth_l3.ko.
++          If unsure, choose Y.
+ 
+ config QETH_IPV6
+-	bool "IPv6 support for gigabit ethernet"
+-	depends on (QETH = IPV6) || (QETH && IPV6 = 'y')
+-	help
+-	  If CONFIG_QETH is switched on, this option will include IPv6
+-	  support in the qeth device driver.
+-	
+-config QETH_VLAN
+-	bool "VLAN support for gigabit ethernet"
+-	depends on (QETH = VLAN_8021Q) || (QETH && VLAN_8021Q = 'y')
+-	help
+-	  If CONFIG_QETH is switched on, this option will include IEEE
+-	  802.1q VLAN support in the qeth device driver.
++        bool
++        depends on (QETH_L3 = IPV6) || (QETH_L3 && IPV6 = 'y')
++        default y
+ 
+ config CCWGROUP
+- 	tristate
+-	default (LCS || CTC || QETH)
++	tristate
++	default (LCS || CTCM || QETH)
+ 
+ endmenu
+diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
+index bbe3ab2..6382c04 100644
+--- a/drivers/s390/net/Makefile
++++ b/drivers/s390/net/Makefile
+@@ -2,13 +2,15 @@
+ # S/390 network devices
+ #
+ 
+-ctc-objs := ctcmain.o ctcdbug.o
+-
++ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o
++obj-$(CONFIG_CTCM) += ctcm.o fsm.o cu3088.o
+ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
+ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
+-obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
+ obj-$(CONFIG_LCS) += lcs.o cu3088.o
+ obj-$(CONFIG_CLAW) += claw.o cu3088.o
+-qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o 
+-qeth-$(CONFIG_PROC_FS) += qeth_proc.o
++qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o qeth_core_offl.o
+ obj-$(CONFIG_QETH) += qeth.o
++qeth_l2-y += qeth_l2_main.o
++obj-$(CONFIG_QETH_L2) += qeth_l2.o
++qeth_l3-y += qeth_l3_main.o qeth_l3_sys.o
++obj-$(CONFIG_QETH_L3) += qeth_l3.o
+diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
+index d8a5c22..04a1d7b 100644
+--- a/drivers/s390/net/claw.c
++++ b/drivers/s390/net/claw.c
+@@ -299,7 +299,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+ 	struct claw_privbk *privptr=NULL;
+ 
+ #ifdef FUNCTRACE
+-	printk(KERN_INFO "%s Enter\n",__FUNCTION__);
++	printk(KERN_INFO "%s Enter\n",__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"probe");
+ 	if (!get_device(&cgdev->dev))
+@@ -313,7 +313,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+ 		probe_error(cgdev);
+ 		put_device(&cgdev->dev);
+ 		printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
+-			cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
++			cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
+ 		CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+ 		return -ENOMEM;
+ 	}
+@@ -323,7 +323,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+                 probe_error(cgdev);
+ 		put_device(&cgdev->dev);
+ 		printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
+-			cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
++			cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
+ 		CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+                 return -ENOMEM;
+         }
+@@ -340,7 +340,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+ 		probe_error(cgdev);
+ 		put_device(&cgdev->dev);
+ 		printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
+-			cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
++			cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
+ 		CLAW_DBF_TEXT_(2,setup,"probex%d",rc);
+ 		return rc;
+ 	}
+@@ -351,7 +351,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+ 	cgdev->dev.driver_data = privptr;
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "claw:%s exit on line %d, "
+-		"rc = 0\n",__FUNCTION__,__LINE__);
++		"rc = 0\n",__func__,__LINE__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"prbext 0");
+ 
+@@ -371,7 +371,7 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
+         struct chbk *p_ch;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s enter\n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"claw_tx");
+         p_ch=&privptr->channel[WRITE];
+@@ -381,7 +381,7 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
+                 privptr->stats.tx_dropped++;
+ #ifdef FUNCTRACE
+                 printk(KERN_INFO "%s: %s() exit on line %d, rc = EIO\n",
+-			dev->name,__FUNCTION__, __LINE__);
++			dev->name,__func__, __LINE__);
+ #endif
+ 		CLAW_DBF_TEXT_(2,trace,"clawtx%d",-EIO);
+                 return -EIO;
+@@ -398,7 +398,7 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
+         spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s exit on line %d, rc = %d\n",
+-		dev->name, __FUNCTION__, __LINE__, rc);
++		dev->name, __func__, __LINE__, rc);
+ #endif
+ 	CLAW_DBF_TEXT_(4,trace,"clawtx%d",rc);
+         return rc;
+@@ -460,7 +460,7 @@ claw_pack_skb(struct claw_privbk *privptr)
+ #ifdef IOTRACE
+ 		printk(KERN_INFO "%s: %s() Packed %d len %d\n",
+ 			p_env->ndev->name,
+-			__FUNCTION__,pkt_cnt,new_skb->len);
++			__func__,pkt_cnt,new_skb->len);
+ #endif
+ 	}
+ 	CLAW_DBF_TEXT(4,trace,"PackSKBx");
+@@ -478,7 +478,7 @@ claw_change_mtu(struct net_device *dev, int new_mtu)
+ 	struct claw_privbk  *privptr=dev->priv;
+ 	int buff_size;
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
+ #endif
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "variable dev =\n");
+@@ -491,14 +491,14 @@ claw_change_mtu(struct net_device *dev, int new_mtu)
+ #ifdef FUNCTRACE
+                 printk(KERN_INFO "%s:%s Exit on line %d, rc=EINVAL\n",
+ 		dev->name,
+-		__FUNCTION__, __LINE__);
++		__func__, __LINE__);
+ #endif
+                 return -EINVAL;
+         }
+         dev->mtu = new_mtu;
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d\n",dev->name,
+-	__FUNCTION__, __LINE__);
++	__func__, __LINE__);
+ #endif
+         return 0;
+ }  /*   end of claw_change_mtu */
+@@ -522,7 +522,7 @@ claw_open(struct net_device *dev)
+         struct ccwbk *p_buf;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"open");
+ 	if (!dev || (dev->name[0] == 0x00)) {
+@@ -537,7 +537,7 @@ claw_open(struct net_device *dev)
+         	if (rc) {
+                 	printk(KERN_INFO "%s:%s Exit on line %d, rc=ENOMEM\n",
+ 			dev->name,
+-			__FUNCTION__, __LINE__);
++			__func__, __LINE__);
+ 			CLAW_DBF_TEXT(2,trace,"openmem");
+                 	return -ENOMEM;
+         	}
+@@ -661,7 +661,7 @@ claw_open(struct net_device *dev)
+                 claw_clear_busy(dev);
+ #ifdef FUNCTRACE
+                 printk(KERN_INFO "%s:%s Exit on line %d, rc=EIO\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 		CLAW_DBF_TEXT(2,trace,"open EIO");
+                 return -EIO;
+@@ -673,7 +673,7 @@ claw_open(struct net_device *dev)
+ 
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d, rc=0\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"openok");
+         return 0;
+@@ -696,7 +696,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ 
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s enter  \n",__FUNCTION__);
++	printk(KERN_INFO "%s enter  \n",__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"clawirq");
+         /* Bypass all 'unsolicited interrupts' */
+@@ -706,7 +706,7 @@ claw_irq_handler(struct ccw_device *cdev,
+                         cdev->dev.bus_id,irb->scsw.cstat, irb->scsw.dstat);
+ #ifdef FUNCTRACE
+                 printk(KERN_INFO "claw: %s() "
+-			"exit on line %d\n",__FUNCTION__,__LINE__);
++			"exit on line %d\n",__func__,__LINE__);
+ #endif
+ 		CLAW_DBF_TEXT(2,trace,"badirq");
+                 return;
+@@ -752,7 +752,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+ 		printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 		CLAW_DBF_TEXT(2,trace,"chanchk");
+                 /* return; */
+@@ -777,7 +777,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ 	     		(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ #ifdef FUNCTRACE
+                                 printk(KERN_INFO "%s:%s Exit on line %d\n",
+-					dev->name,__FUNCTION__,__LINE__);
++					dev->name,__func__,__LINE__);
+ #endif
+                                 return;
+                         }
+@@ -788,7 +788,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+                         printk(KERN_INFO "%s:%s Exit on line %d\n",
+-				dev->name,__FUNCTION__,__LINE__);
++				dev->name,__func__,__LINE__);
+ #endif
+ 			CLAW_DBF_TEXT(4,trace,"stop");
+                         return;
+@@ -804,7 +804,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ 	     		(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ #ifdef FUNCTRACE
+ 				printk(KERN_INFO "%s:%s Exit on line %d\n",
+-					dev->name,__FUNCTION__,__LINE__);
++					dev->name,__func__,__LINE__);
+ #endif
+ 				CLAW_DBF_TEXT(4,trace,"haltio");
+                                 return;
+@@ -838,7 +838,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+                         printk(KERN_INFO "%s:%s Exit on line %d\n",
+-				dev->name,__FUNCTION__,__LINE__);
++				dev->name,__func__,__LINE__);
+ #endif
+ 			CLAW_DBF_TEXT(4,trace,"haltio");
+                         return;
+@@ -858,7 +858,7 @@ claw_irq_handler(struct ccw_device *cdev,
+                                 }
+ #ifdef FUNCTRACE
+ 				printk(KERN_INFO "%s:%s Exit on line %d\n",
+-					dev->name,__FUNCTION__,__LINE__);
++					dev->name,__func__,__LINE__);
+ #endif
+ 					CLAW_DBF_TEXT(4,trace,"notrdy");
+                                         return;
+@@ -874,7 +874,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ 				}
+ #ifdef FUNCTRACE
+ 				printk(KERN_INFO "%s:%s Exit on line %d\n",
+-					dev->name,__FUNCTION__,__LINE__);
++					dev->name,__func__,__LINE__);
+ #endif
+ 				CLAW_DBF_TEXT(4,trace,"PCI_read");
+                                 return;
+@@ -885,7 +885,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ 	     		 (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ #ifdef FUNCTRACE
+ 				printk(KERN_INFO "%s:%s Exit on line %d\n",
+-					dev->name,__FUNCTION__,__LINE__);
++					dev->name,__func__,__LINE__);
+ #endif
+ 				CLAW_DBF_TEXT(4,trace,"SPend_rd");
+                                 return;
+@@ -906,7 +906,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+ 			printk(KERN_INFO "%s:%s Exit on line %d\n",
+-				dev->name,__FUNCTION__,__LINE__);
++				dev->name,__func__,__LINE__);
+ #endif
+ 			CLAW_DBF_TEXT(4,trace,"RdIRQXit");
+                         return;
+@@ -929,7 +929,7 @@ claw_irq_handler(struct ccw_device *cdev,
+                                 }
+ #ifdef FUNCTRACE
+ 				printk(KERN_INFO "%s:%s Exit on line %d\n",
+-					dev->name,__FUNCTION__,__LINE__);
++					dev->name,__func__,__LINE__);
+ #endif
+ 				CLAW_DBF_TEXT(4,trace,"rstrtwrt");
+                                 return;
+@@ -946,7 +946,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ 	     		(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ #ifdef FUNCTRACE
+ 				printk(KERN_INFO "%s:%s Exit on line %d\n",
+-					dev->name,__FUNCTION__,__LINE__);
++					dev->name,__func__,__LINE__);
+ #endif
+ 				CLAW_DBF_TEXT(4,trace,"writeUE");
+                                 return;
+@@ -969,7 +969,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+ 			printk(KERN_INFO "%s:%s Exit on line %d\n",
+-				dev->name,__FUNCTION__,__LINE__);
++				dev->name,__func__,__LINE__);
+ #endif
+ 			CLAW_DBF_TEXT(4,trace,"StWtExit");
+                         return;
+@@ -978,7 +978,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ 				"state=%d\n",dev->name,p_ch->claw_state);
+ #ifdef FUNCTRACE
+ 			printk(KERN_INFO "%s:%s Exit on line %d\n",
+-				dev->name,__FUNCTION__,__LINE__);
++				dev->name,__func__,__LINE__);
+ #endif
+ 			CLAW_DBF_TEXT(2,trace,"badIRQ");
+                         return;
+@@ -1001,7 +1001,7 @@ claw_irq_tasklet ( unsigned long data )
+ 	p_ch = (struct chbk *) data;
+         dev = (struct net_device *)p_ch->ndev;
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
+ #endif
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: variable p_ch =\n",dev->name);
+@@ -1021,7 +1021,7 @@ claw_irq_tasklet ( unsigned long data )
+ 	CLAW_DBF_TEXT(4,trace,"TskletXt");
+ #ifdef FUNCTRACE
+ 	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+         return;
+ }       /*    end of claw_irq_bh    */
+@@ -1048,7 +1048,7 @@ claw_release(struct net_device *dev)
+         if (!privptr)
+                 return 0;
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"release");
+ #ifdef DEBUGMSG
+@@ -1090,7 +1090,7 @@ claw_release(struct net_device *dev)
+ 	if(privptr->buffs_alloc != 1) {
+ #ifdef FUNCTRACE
+ 	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 		CLAW_DBF_TEXT(4,trace,"none2fre");
+ 		return 0;
+@@ -1171,7 +1171,7 @@ claw_release(struct net_device *dev)
+         }
+ #ifdef FUNCTRACE
+ 	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"rlsexit");
+         return 0;
+@@ -1192,7 +1192,7 @@ claw_write_retry ( struct chbk *p_ch )
+ 
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+         printk(KERN_INFO "claw: variable p_ch =\n");
+         dumpit((char *) p_ch, sizeof(struct chbk));
+ #endif
+@@ -1200,20 +1200,20 @@ claw_write_retry ( struct chbk *p_ch )
+         if (p_ch->claw_state == CLAW_STOP) {
+ #ifdef FUNCTRACE
+ 		printk(KERN_INFO "%s:%s Exit on line %d\n",
+-			dev->name,__FUNCTION__,__LINE__);
++			dev->name,__func__,__LINE__);
+ #endif
+         	return;
+         }
+ #ifdef DEBUGMSG
+         printk( KERN_INFO "%s:%s  state-%02x\n" ,
+ 		dev->name,
+-		__FUNCTION__,
++		__func__,
+ 		p_ch->claw_state);
+ #endif
+ 	claw_strt_out_IO( dev );
+ #ifdef FUNCTRACE
+ 	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"rtry_xit");
+         return;
+@@ -1235,7 +1235,7 @@ claw_write_next ( struct chbk * p_ch )
+ 	int	rc;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter  \n",p_ch->ndev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter  \n",p_ch->ndev->name,__func__);
+         printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
+         dumpit((char *) p_ch, sizeof(struct chbk));
+ #endif
+@@ -1262,7 +1262,7 @@ claw_write_next ( struct chbk * p_ch )
+ 
+ #ifdef FUNCTRACE
+ 	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+         return;
+ }      /* end of claw_write_next      */
+@@ -1276,7 +1276,7 @@ static void
+ claw_timer ( struct chbk * p_ch )
+ {
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__func__);
+         printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
+         dumpit((char *) p_ch, sizeof(struct chbk));
+ #endif
+@@ -1285,7 +1285,7 @@ claw_timer ( struct chbk * p_ch )
+         wake_up(&p_ch->wait);
+ #ifdef FUNCTRACE
+ 	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		p_ch->ndev->name,__FUNCTION__,__LINE__);
++		p_ch->ndev->name,__func__,__LINE__);
+ #endif
+         return;
+ }      /* end of claw_timer  */
+@@ -1312,7 +1312,7 @@ pages_to_order_of_mag(int num_of_pages)
+ 	int	order_of_mag=1;		/* assume 2 pages */
+ 	int	nump=2;
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s Enter pages = %d \n",__FUNCTION__,num_of_pages);
++	printk(KERN_INFO "%s Enter pages = %d \n",__func__,num_of_pages);
+ #endif
+ 	CLAW_DBF_TEXT_(5,trace,"pages%d",num_of_pages);
+ 	if (num_of_pages == 1)   {return 0; }  /* magnitude of 0 = 1 page */
+@@ -1327,7 +1327,7 @@ pages_to_order_of_mag(int num_of_pages)
+ 	if (order_of_mag > 9) { order_of_mag = 9; }  /* I know it's paranoid */
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s Exit on line %d, order = %d\n",
+-	__FUNCTION__,__LINE__, order_of_mag);
++	__func__,__LINE__, order_of_mag);
+ #endif
+ 	CLAW_DBF_TEXT_(5,trace,"mag%d",order_of_mag);
+ 	return order_of_mag;
+@@ -1349,7 +1349,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+         struct ccwbk*  p_buf;
+ #endif
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
+ #endif
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "dev\n");
+@@ -1369,7 +1369,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+         if ( p_first==NULL) {
+ #ifdef FUNCTRACE
+ 		printk(KERN_INFO "%s:%s Exit on line %d\n",
+-			dev->name,__FUNCTION__,__LINE__);
++			dev->name,__func__,__LINE__);
+ #endif
+ 		CLAW_DBF_TEXT(4,trace,"addexit");
+                 return 0;
+@@ -1400,9 +1400,9 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+         if ( privptr-> p_read_active_first ==NULL ) {
+ #ifdef DEBUGMSG
+                 printk(KERN_INFO "%s:%s p_read_active_first == NULL \n",
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+                 printk(KERN_INFO "%s:%s Read active first/last changed \n",
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+ #endif
+                 privptr-> p_read_active_first= p_first;  /*    set new first */
+                 privptr-> p_read_active_last = p_last;   /*    set new last  */
+@@ -1411,7 +1411,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+ 
+ #ifdef DEBUGMSG
+                 printk(KERN_INFO "%s:%s Read in progress \n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+ #endif
+                 /* set up TIC ccw  */
+                 temp_ccw.cda= (__u32)__pa(&p_first->read);
+@@ -1450,15 +1450,15 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+                 privptr->p_read_active_last=p_last;
+         } /* end of if ( privptr-> p_read_active_first ==NULL)  */
+ #ifdef IOTRACE
+-        printk(KERN_INFO "%s:%s  dump p_last CCW BK \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s  dump p_last CCW BK \n",dev->name,__func__);
+         dumpit((char *)p_last, sizeof(struct ccwbk));
+-        printk(KERN_INFO "%s:%s  dump p_end CCW BK \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s  dump p_end CCW BK \n",dev->name,__func__);
+         dumpit((char *)p_end, sizeof(struct endccw));
+ 
+-        printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__func__);
+         dumpit((char *)p_first, sizeof(struct ccwbk));
+         printk(KERN_INFO "%s:%s Dump Active CCW chain \n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+         p_buf=privptr->p_read_active_first;
+         while (p_buf!=NULL) {
+                 dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -1467,7 +1467,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+ #endif
+ #ifdef FUNCTRACE
+ 	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"addexit");
+         return 0;
+@@ -1483,7 +1483,7 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
+ {
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s: %s() > enter  \n",
+-		cdev->dev.bus_id,__FUNCTION__);
++		cdev->dev.bus_id,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"ccwret");
+ #ifdef DEBUGMSG
+@@ -1516,7 +1516,7 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
+         }
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s: %s() > exit on line %d\n",
+-		cdev->dev.bus_id,__FUNCTION__,__LINE__);
++		cdev->dev.bus_id,__func__,__LINE__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"ccwret");
+ }    /*    end of ccw_check_return_code   */
+@@ -1531,7 +1531,7 @@ ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
+ 	struct net_device *dev = p_ch->ndev;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s: %s() > enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
+ #endif
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: variable dev =\n",dev->name);
+@@ -1578,7 +1578,7 @@ ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
+ 
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s: %s() exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ }   /*    end of ccw_check_unit_check    */
+ 
+@@ -1706,7 +1706,7 @@ find_link(struct net_device *dev, char *host_name, char *ws_name )
+ 	int    rc=0;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s > enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s > enter  \n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"findlink");
+ #ifdef DEBUGMSG
+@@ -1739,7 +1739,7 @@ find_link(struct net_device *dev, char *host_name, char *ws_name )
+ 
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+         return 0;
+ }    /*    end of find_link    */
+@@ -1773,7 +1773,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+         struct ccwbk                   *p_buf;
+ #endif
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s: %s() > enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"hw_tx");
+ #ifdef DEBUGMSG
+@@ -1787,7 +1787,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+         p_ch=(struct chbk *)&privptr->channel[WRITE];
+ 	p_env =privptr->p_env;
+ #ifdef IOTRACE
+-        printk(KERN_INFO "%s: %s() dump sk_buff  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s: %s() dump sk_buff  \n",dev->name,__func__);
+         dumpit((char *)skb ,sizeof(struct sk_buff));
+ #endif
+ 	claw_free_wrt_buf(dev);	/* Clean up free chain if posible */
+@@ -1877,7 +1877,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+         while (len_of_data > 0) {
+ #ifdef DEBUGMSG
+                 printk(KERN_INFO "%s: %s() length-of-data is %ld \n",
+-			dev->name ,__FUNCTION__,len_of_data);
++			dev->name ,__func__,len_of_data);
+                 dumpit((char *)pDataAddress ,64);
+ #endif
+                 p_this_ccw=privptr->p_write_free_chain;  /* get a block */
+@@ -1913,7 +1913,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+                 p_last_ccw=p_this_ccw;      /* save new last block */
+ #ifdef IOTRACE
+ 		printk(KERN_INFO "%s: %s() > CCW and Buffer %ld bytes long \n",
+-			dev->name,__FUNCTION__,bytesInThisBuffer);
++			dev->name,__func__,bytesInThisBuffer);
+                 dumpit((char *)p_this_ccw, sizeof(struct ccwbk));
+                 dumpit((char *)p_this_ccw->p_buffer, 64);
+ #endif
+@@ -1998,7 +1998,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+ 
+ #ifdef IOTRACE
+         printk(KERN_INFO "%s: %s() >  Dump Active CCW chain \n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+         p_buf=privptr->p_write_active_first;
+         while (p_buf!=NULL) {
+                 dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -2018,7 +2018,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+         /*      if write free count is zero , set NOBUFFER       */
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s() > free_count is %d\n",
+-		dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		(int) privptr->write_free_count );
+ #endif
+ 	if (privptr->write_free_count==0) {
+@@ -2029,7 +2029,7 @@ Done2:
+ Done:
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s: %s() > exit on line %d, rc = %d \n",
+-		dev->name,__FUNCTION__,__LINE__, rc);
++		dev->name,__func__,__LINE__, rc);
+ #endif
+ 	return(rc);
+ }    /*    end of claw_hw_tx    */
+@@ -2063,7 +2063,7 @@ init_ccw_bk(struct net_device *dev)
+         addr_t   real_TIC_address;
+         int i,j;
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s: %s() enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s: %s() enter  \n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"init_ccw");
+ #ifdef DEBUGMSG
+@@ -2097,15 +2097,15 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s() "
+ 		"ccw_blocks_required=%d\n",
+-		dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		ccw_blocks_required);
+         printk(KERN_INFO "%s: %s() "
+ 		"PAGE_SIZE=0x%x\n",
+-		dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		(unsigned int)PAGE_SIZE);
+         printk(KERN_INFO "%s: %s() > "
+ 		"PAGE_MASK=0x%x\n",
+-		dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		(unsigned int)PAGE_MASK);
+ #endif
+         /*
+@@ -2117,10 +2117,10 @@ init_ccw_bk(struct net_device *dev)
+ 
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s() > ccw_blocks_perpage=%d\n",
+-		dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		ccw_blocks_perpage);
+         printk(KERN_INFO "%s: %s() > ccw_pages_required=%d\n",
+-		dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		ccw_pages_required);
+ #endif
+         /*
+@@ -2156,29 +2156,29 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+         if (privptr->p_env->read_size < PAGE_SIZE) {
+             printk(KERN_INFO "%s: %s() reads_perpage=%d\n",
+-	    	dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		claw_reads_perpage);
+         }
+         else {
+             printk(KERN_INFO "%s: %s() pages_perread=%d\n",
+-	    	dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		privptr->p_buff_pages_perread);
+         }
+         printk(KERN_INFO "%s: %s() read_pages=%d\n",
+-		dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		claw_read_pages);
+         if (privptr->p_env->write_size < PAGE_SIZE) {
+             printk(KERN_INFO "%s: %s() writes_perpage=%d\n",
+-	    	dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		claw_writes_perpage);
+         }
+         else {
+             printk(KERN_INFO "%s: %s() pages_perwrite=%d\n",
+-	    	dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		privptr->p_buff_pages_perwrite);
+         }
+         printk(KERN_INFO "%s: %s() write_pages=%d\n",
+-		dev->name,__FUNCTION__,
++		dev->name,__func__,
+ 		claw_write_pages);
+ #endif
+ 
+@@ -2194,12 +2194,12 @@ init_ccw_bk(struct net_device *dev)
+                         printk(KERN_INFO "%s: %s()  "
+ 				"__get_free_pages for CCWs failed : "
+ 				"pages is %d\n",
+-                                dev->name,__FUNCTION__,
++				dev->name,__func__,
+ 				ccw_pages_required );
+ #ifdef FUNCTRACE
+                         printk(KERN_INFO "%s: %s() > "
+ 				"exit on line %d, rc = ENOMEM\n",
+-				dev->name,__FUNCTION__,
++				dev->name,__func__,
+ 				 __LINE__);
+ #endif
+                         return -ENOMEM;
+@@ -2218,7 +2218,7 @@ init_ccw_bk(struct net_device *dev)
+         /*                              Initialize ending CCW block       */
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s() begin initialize ending CCW blocks\n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+ #endif
+ 
+         p_endccw=privptr->p_end_ccw;
+@@ -2276,7 +2276,7 @@ init_ccw_bk(struct net_device *dev)
+ 
+ #ifdef IOTRACE
+         printk(KERN_INFO "%s: %s() dump claw ending CCW BK \n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+         dumpit((char *)p_endccw, sizeof(struct endccw));
+ #endif
+ 
+@@ -2287,7 +2287,7 @@ init_ccw_bk(struct net_device *dev)
+ 
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s()  Begin build a chain of CCW buffer \n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+ #endif
+         p_buff=privptr->p_buff_ccw;
+ 
+@@ -2306,7 +2306,7 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s() "
+ 		"End build a chain of CCW buffer \n",
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+         p_buf=p_free_chain;
+         while (p_buf!=NULL) {
+                 dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -2321,7 +2321,7 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s() "
+ 		"Begin initialize ClawSignalBlock \n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+ #endif
+         if (privptr->p_claw_signal_blk==NULL) {
+                 privptr->p_claw_signal_blk=p_free_chain;
+@@ -2334,7 +2334,7 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s() >  End initialize "
+ 	 	"ClawSignalBlock\n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+         dumpit((char *)privptr->p_claw_signal_blk, sizeof(struct ccwbk));
+ #endif
+ 
+@@ -2349,14 +2349,14 @@ init_ccw_bk(struct net_device *dev)
+                 if (privptr->p_buff_write==NULL) {
+                         printk(KERN_INFO "%s: %s() __get_free_pages for write"
+ 				" bufs failed : get is for %d pages\n",
+-                                dev->name,__FUNCTION__,claw_write_pages );
++				dev->name,__func__,claw_write_pages );
+                         free_pages((unsigned long)privptr->p_buff_ccw,
+ 			   (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
+                         privptr->p_buff_ccw=NULL;
+ #ifdef FUNCTRACE
+                         printk(KERN_INFO "%s: %s() > exit on line %d,"
+ 			 	"rc = ENOMEM\n",
+-				dev->name,__FUNCTION__,__LINE__);
++				dev->name,__func__,__LINE__);
+ #endif
+                         return -ENOMEM;
+                 }
+@@ -2369,7 +2369,7 @@ init_ccw_bk(struct net_device *dev)
+ 			ccw_pages_required * PAGE_SIZE);
+ #ifdef DEBUGMSG
+                 printk(KERN_INFO "%s: %s() Begin build claw write free "
+-			"chain \n",dev->name,__FUNCTION__);
++			"chain \n",dev->name,__func__);
+ #endif
+                 privptr->p_write_free_chain=NULL;
+ 
+@@ -2409,14 +2409,14 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef IOTRACE
+                    printk(KERN_INFO "%s:%s __get_free_pages "
+ 		    "for writes buf: get for %d pages\n",
+-		    dev->name,__FUNCTION__,
++		    dev->name,__func__,
+ 		    privptr->p_buff_pages_perwrite);
+ #endif
+                    if (p_buff==NULL) {
+ 			printk(KERN_INFO "%s:%s __get_free_pages "
+ 			 	"for writes buf failed : get is for %d pages\n",
+ 				dev->name,
+-				__FUNCTION__,
++				__func__,
+ 				privptr->p_buff_pages_perwrite );
+                         free_pages((unsigned long)privptr->p_buff_ccw,
+ 			      (int)pages_to_order_of_mag(
+@@ -2433,7 +2433,7 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef FUNCTRACE
+                         printk(KERN_INFO "%s: %s exit on line %d, rc = ENOMEM\n",
+ 			dev->name,
+-			__FUNCTION__,
++			__func__,
+ 			__LINE__);
+ #endif
+                         return -ENOMEM;
+@@ -2466,7 +2466,7 @@ init_ccw_bk(struct net_device *dev)
+ 
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s:%s  End build claw write free chain \n",
+-	dev->name,__FUNCTION__);
++	dev->name,__func__);
+         p_buf=privptr->p_write_free_chain;
+         while (p_buf!=NULL) {
+                 dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -2485,7 +2485,7 @@ init_ccw_bk(struct net_device *dev)
+                         printk(KERN_INFO "%s: %s() "
+ 			 	"__get_free_pages for read buf failed : "
+ 			 	"get is for %d pages\n",
+-                                dev->name,__FUNCTION__,claw_read_pages );
++				dev->name,__func__,claw_read_pages );
+                         free_pages((unsigned long)privptr->p_buff_ccw,
+ 				(int)pages_to_order_of_mag(
+ 					privptr->p_buff_ccw_num));
+@@ -2497,7 +2497,7 @@ init_ccw_bk(struct net_device *dev)
+                         privptr->p_buff_write=NULL;
+ #ifdef FUNCTRACE
+                         printk(KERN_INFO "%s: %s() > exit on line %d, rc ="
+-				" ENOMEM\n",dev->name,__FUNCTION__,__LINE__);
++				" ENOMEM\n",dev->name,__func__,__LINE__);
+ #endif
+                         return -ENOMEM;
+                 }
+@@ -2509,7 +2509,7 @@ init_ccw_bk(struct net_device *dev)
+                 */
+ #ifdef DEBUGMSG
+                 printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+ #endif
+                 p_buff=privptr->p_buff_read;
+                 for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
+@@ -2590,7 +2590,7 @@ init_ccw_bk(struct net_device *dev)
+ 
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+ #endif
+                 for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
+                         p_buff = (void *)__get_free_pages(__GFP_DMA,
+@@ -2598,7 +2598,7 @@ init_ccw_bk(struct net_device *dev)
+                         if (p_buff==NULL) {
+                                 printk(KERN_INFO "%s: %s() __get_free_pages for read "
+ 					"buf failed : get is for %d pages\n",
+-					dev->name,__FUNCTION__,
++					dev->name,__func__,
+                                         privptr->p_buff_pages_perread );
+                                 free_pages((unsigned long)privptr->p_buff_ccw,
+ 					(int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
+@@ -2622,7 +2622,7 @@ init_ccw_bk(struct net_device *dev)
+                                 privptr->p_buff_write=NULL;
+ #ifdef FUNCTRACE
+                                 printk(KERN_INFO "%s: %s() exit on line %d, rc = ENOMEM\n",
+-					dev->name,__FUNCTION__,
++					dev->name,__func__,
+ 					__LINE__);
+ #endif
+                                 return -ENOMEM;
+@@ -2695,7 +2695,7 @@ init_ccw_bk(struct net_device *dev)
+         }       /*  pBuffread = NULL */
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s: %s() >  End build claw read free chain \n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+         p_buf=p_first_CCWB;
+         while (p_buf!=NULL) {
+                 dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -2707,7 +2707,7 @@ init_ccw_bk(struct net_device *dev)
+ 	privptr->buffs_alloc = 1;
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s: %s() exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+         return 0;
+ }    /*    end of init_ccw_bk */
+@@ -2723,11 +2723,11 @@ probe_error( struct ccwgroup_device *cgdev)
+ {
+   struct claw_privbk *privptr;
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s enter  \n",__FUNCTION__);
++	printk(KERN_INFO "%s enter  \n",__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"proberr");
+ #ifdef DEBUGMSG
+-        printk(KERN_INFO "%s variable cgdev =\n",__FUNCTION__);
++	printk(KERN_INFO "%s variable cgdev =\n",__func__);
+         dumpit((char *) cgdev, sizeof(struct ccwgroup_device));
+ #endif
+         privptr=(struct claw_privbk *)cgdev->dev.driver_data;
+@@ -2741,7 +2741,7 @@ probe_error( struct ccwgroup_device *cgdev)
+         }
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s > exit on line %d\n",
+-		 __FUNCTION__,__LINE__);
++		 __func__,__LINE__);
+ #endif
+ 
+         return;
+@@ -2772,7 +2772,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
+         struct chbk *p_ch = NULL;
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s: %s() > enter  \n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"clw_cntl");
+ #ifdef DEBUGMSG
+@@ -2794,7 +2794,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
+ #ifdef FUNCTRACE
+                 printk(KERN_INFO "%s: %s() > "
+ 			"exit on line %d, rc=0\n",
+-			dev->name,__FUNCTION__,__LINE__);
++			dev->name,__func__,__LINE__);
+ #endif
+                 return 0;
+         }
+@@ -3057,7 +3057,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
+ 
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s: %s() exit on line %d, rc = 0\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 
+         return 0;
+@@ -3080,7 +3080,7 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
+         struct sk_buff 			*skb;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s > enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s > enter  \n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"sndcntl");
+ #ifdef DEBUGMSG
+@@ -3143,10 +3143,10 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
+         skb = dev_alloc_skb(sizeof(struct clawctl));
+         if (!skb) {
+                 printk(  "%s:%s low on mem, returning...\n",
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+ #ifdef DEBUG
+                 printk(KERN_INFO "%s:%s Exit, rc = ENOMEM\n",
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+ #endif
+                 return -ENOMEM;
+         }
+@@ -3162,7 +3162,7 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
+         	claw_hw_tx(skb, dev, 0);
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 
+         return 0;
+@@ -3180,7 +3180,7 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
+         struct clawctl 	   *p_ctl;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"snd_conn");
+ #ifdef  DEBUGMSG
+@@ -3193,7 +3193,7 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
+         if ( privptr->system_validate_comp==0x00 ) {
+ #ifdef FUNCTRACE
+                 printk(KERN_INFO "%s:%s Exit on line %d, rc = 1\n",
+-			dev->name,__FUNCTION__,__LINE__);
++			dev->name,__func__,__LINE__);
+ #endif
+                 return rc;
+         }
+@@ -3209,7 +3209,7 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
+        			HOST_APPL_NAME, privptr->p_env->api_type);
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+-		dev->name,__FUNCTION__,__LINE__, rc);
++		dev->name,__func__,__LINE__, rc);
+ #endif
+         return rc;
+ 
+@@ -3228,7 +3228,7 @@ claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl)
+         struct conncmd *  p_connect;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"snd_dsc");
+ #ifdef  DEBUGMSG
+@@ -3244,7 +3244,7 @@ claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl)
+                 p_connect->host_name, p_connect->WS_name);
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+-		dev->name,__FUNCTION__, __LINE__, rc);
++		dev->name,__func__, __LINE__, rc);
+ #endif
+         return rc;
+ }     /*   end of claw_snd_disc    */
+@@ -3265,7 +3265,7 @@ claw_snd_sys_validate_rsp(struct net_device *dev,
+ 
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Enter\n",
+-		dev->name,__FUNCTION__);
++		dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"chkresp");
+ #ifdef DEBUGMSG
+@@ -3285,7 +3285,7 @@ claw_snd_sys_validate_rsp(struct net_device *dev,
+ 		p_env->adapter_name  );
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+-		dev->name,__FUNCTION__,__LINE__, rc);
++		dev->name,__func__,__LINE__, rc);
+ #endif
+         return rc;
+ }     /*    end of claw_snd_sys_validate_rsp    */
+@@ -3301,7 +3301,7 @@ claw_strt_conn_req(struct net_device *dev )
+         int rc;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"conn_req");
+ #ifdef DEBUGMSG
+@@ -3311,7 +3311,7 @@ claw_strt_conn_req(struct net_device *dev )
+         rc=claw_snd_conn_req(dev, 1);
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+-		dev->name,__FUNCTION__,__LINE__, rc);
++		dev->name,__func__,__LINE__, rc);
+ #endif
+         return rc;
+ }    /*   end of claw_strt_conn_req   */
+@@ -3327,13 +3327,13 @@ net_device_stats *claw_stats(struct net_device *dev)
+ {
+         struct claw_privbk *privptr;
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"stats");
+         privptr = dev->priv;
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+         return &privptr->stats;
+ }     /*   end of claw_stats   */
+@@ -3366,7 +3366,7 @@ unpack_read(struct net_device *dev )
+ 	int     p=0;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s enter  \n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"unpkread");
+         p_first_ccw=NULL;
+@@ -3408,7 +3408,7 @@ unpack_read(struct net_device *dev )
+                 if ((p_this_ccw->header.opcode & MORE_to_COME_FLAG)!=0) {
+ #ifdef DEBUGMSG
+                         printk(KERN_INFO "%s: %s > More_to_come is ON\n",
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+ #endif
+                         mtc_this_frm=1;
+                         if (p_this_ccw->header.length!=
+@@ -3435,7 +3435,7 @@ unpack_read(struct net_device *dev )
+ #ifdef DEBUGMSG
+                         printk(KERN_INFO "%s:%s goto next "
+ 				"frame from MoretoComeSkip \n",
+-				dev->name,__FUNCTION__);
++				dev->name,__func__);
+ #endif
+                         goto NextFrame;
+                 }
+@@ -3445,7 +3445,7 @@ unpack_read(struct net_device *dev )
+ #ifdef DEBUGMSG
+                         printk(KERN_INFO "%s:%s goto next "
+ 				"frame from claw_process_control \n",
+-				dev->name,__FUNCTION__);
++				dev->name,__func__);
+ #endif
+ 			CLAW_DBF_TEXT(4,trace,"UnpkCntl");
+                         goto NextFrame;
+@@ -3468,7 +3468,7 @@ unpack_next:
+                 if (privptr->mtc_logical_link<0) {
+ #ifdef DEBUGMSG
+                 printk(KERN_INFO "%s: %s mtc_logical_link < 0  \n",
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+ #endif
+ 
+                 /*
+@@ -3487,7 +3487,7 @@ unpack_next:
+                         printk(KERN_INFO "%s: %s > goto next "
+ 				"frame from MoretoComeSkip \n",
+ 				dev->name,
+-				__FUNCTION__);
++				__func__);
+                         printk(KERN_INFO "      bytes_to_mov %d > (MAX_ENVELOPE_"
+ 				"SIZE-privptr->mtc_offset %d)\n",
+ 				bytes_to_mov,(MAX_ENVELOPE_SIZE- privptr->mtc_offset));
+@@ -3505,13 +3505,13 @@ unpack_next:
+ 		}
+ #ifdef DEBUGMSG
+                 printk(KERN_INFO "%s: %s() received data \n",
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+ 		if (p_env->packing == DO_PACKED)
+ 			dumpit((char *)p_packd+sizeof(struct clawph),32);
+ 		else
+ 	                dumpit((char *)p_this_ccw->p_buffer, 32);
+ 		printk(KERN_INFO "%s: %s() bytelength %d \n",
+-			dev->name,__FUNCTION__,bytes_to_mov);
++			dev->name,__func__,bytes_to_mov);
+ #endif
+                 if (mtc_this_frm==0) {
+                         len_of_data=privptr->mtc_offset+bytes_to_mov;
+@@ -3530,13 +3530,13 @@ unpack_next:
+ #ifdef DEBUGMSG
+                                 printk(KERN_INFO "%s: %s() netif_"
+ 					"rx(skb) completed \n",
+-					dev->name,__FUNCTION__);
++					dev->name,__func__);
+ #endif
+                         }
+                         else {
+                                 privptr->stats.rx_dropped++;
+                                 printk(KERN_WARNING "%s: %s() low on memory\n",
+-				dev->name,__FUNCTION__);
++				dev->name,__func__);
+                         }
+                         privptr->mtc_offset=0;
+                         privptr->mtc_logical_link=-1;
+@@ -3575,10 +3575,10 @@ NextFrame:
+ 
+ #ifdef IOTRACE
+         printk(KERN_INFO "%s:%s processed frame is %d \n",
+-		dev->name,__FUNCTION__,i);
++		dev->name,__func__,i);
+         printk(KERN_INFO "%s:%s  F:%lx L:%lx\n",
+ 		dev->name,
+-		__FUNCTION__,
++		__func__,
+ 		(unsigned long)p_first_ccw,
+ 		(unsigned long)p_last_ccw);
+ #endif
+@@ -3588,7 +3588,7 @@ NextFrame:
+         claw_strt_read(dev, LOCK_YES);
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s: %s exit on line %d\n",
+-		dev->name, __FUNCTION__, __LINE__);
++		dev->name, __func__, __LINE__);
+ #endif
+         return;
+ }     /*  end of unpack_read   */
+@@ -3610,7 +3610,7 @@ claw_strt_read (struct net_device *dev, int lock )
+         p_ch=&privptr->channel[READ];
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter  \n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
+         printk(KERN_INFO "%s: variable lock = %d, dev =\n",dev->name, lock);
+         dumpit((char *) dev, sizeof(struct net_device));
+ #endif
+@@ -3626,7 +3626,7 @@ claw_strt_read (struct net_device *dev, int lock )
+         }
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s:%s state-%02x\n" ,
+-		dev->name,__FUNCTION__, p_ch->claw_state);
++		dev->name,__func__, p_ch->claw_state);
+ #endif
+         if (lock==LOCK_YES) {
+                 spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
+@@ -3634,7 +3634,7 @@ claw_strt_read (struct net_device *dev, int lock )
+         if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
+ #ifdef DEBUGMSG
+                 printk(KERN_INFO "%s: HOT READ started in %s\n" ,
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+                 p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
+                 dumpit((char *)&p_clawh->flag , 1);
+ #endif
+@@ -3650,7 +3650,7 @@ claw_strt_read (struct net_device *dev, int lock )
+ 	else {
+ #ifdef DEBUGMSG
+ 		printk(KERN_INFO "%s: No READ started by %s() In progress\n" ,
+-			dev->name,__FUNCTION__);
++			dev->name,__func__);
+ #endif
+ 		CLAW_DBF_TEXT(2,trace,"ReadAct");
+ 	}
+@@ -3660,7 +3660,7 @@ claw_strt_read (struct net_device *dev, int lock )
+         }
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 	CLAW_DBF_TEXT(4,trace,"StRdExit");
+         return;
+@@ -3681,7 +3681,7 @@ claw_strt_out_IO( struct net_device *dev )
+         struct ccwbk   	*p_first_ccw;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ 	if (!dev) {
+ 		return;
+@@ -3691,7 +3691,7 @@ claw_strt_out_IO( struct net_device *dev )
+ 
+ #ifdef DEBUGMSG
+         printk(KERN_INFO "%s:%s state-%02x\n" ,
+-		dev->name,__FUNCTION__,p_ch->claw_state);
++		dev->name,__func__,p_ch->claw_state);
+ #endif
+         CLAW_DBF_TEXT(4,trace,"strt_io");
+         p_first_ccw=privptr->p_write_active_first;
+@@ -3701,14 +3701,14 @@ claw_strt_out_IO( struct net_device *dev )
+         if (p_first_ccw == NULL) {
+ #ifdef FUNCTRACE
+                 printk(KERN_INFO "%s:%s Exit on line %d\n",
+-			dev->name,__FUNCTION__,__LINE__);
++			dev->name,__func__,__LINE__);
+ #endif
+                 return;
+         }
+         if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
+                 parm = (unsigned long) p_ch;
+ #ifdef DEBUGMSG
+-                printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__FUNCTION__);
++		printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__func__);
+                 dumpit((char *)p_first_ccw, sizeof(struct ccwbk));
+ #endif
+ 		CLAW_DBF_TEXT(2,trace,"StWrtIO");
+@@ -3721,7 +3721,7 @@ claw_strt_out_IO( struct net_device *dev )
+         dev->trans_start = jiffies;
+ #ifdef FUNCTRACE
+ 	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-		dev->name,__FUNCTION__,__LINE__);
++		dev->name,__func__,__LINE__);
+ #endif
+ 
+         return;
+@@ -3745,7 +3745,7 @@ claw_free_wrt_buf( struct net_device *dev )
+         struct ccwbk*p_buf;
+ #endif
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+         printk(KERN_INFO "%s: free count = %d  variable dev =\n",
+ 		dev->name,privptr->write_free_count);
+ #endif
+@@ -3798,7 +3798,7 @@ claw_free_wrt_buf( struct net_device *dev )
+                 privptr->p_write_active_last=NULL;
+ #ifdef DEBUGMSG
+                 printk(KERN_INFO "%s:%s p_write_"
+-			"active_first==NULL\n",dev->name,__FUNCTION__);
++			"active_first==NULL\n",dev->name,__func__);
+ #endif
+         }
+ #ifdef IOTRACE
+@@ -3819,7 +3819,7 @@ claw_free_wrt_buf( struct net_device *dev )
+ 	CLAW_DBF_TEXT_(4,trace,"FWC=%d",privptr->write_free_count);
+ #ifdef FUNCTRACE
+         printk(KERN_INFO "%s:%s Exit on line %d free_count =%d\n",
+-		dev->name,__FUNCTION__, __LINE__,privptr->write_free_count);
++		dev->name,__func__, __LINE__,privptr->write_free_count);
+ #endif
+         return;
+ }
+@@ -3833,7 +3833,7 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
+ {
+ 	struct claw_privbk *privptr;
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"free_dev");
+ 
+@@ -3854,7 +3854,7 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"feee_ok");
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Exit\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
+ #endif
+ }
+ 
+@@ -3867,13 +3867,13 @@ static void
+ claw_init_netdevice(struct net_device * dev)
+ {
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"init_dev");
+ 	CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
+ 	if (!dev) {
+         printk(KERN_WARNING "claw:%s BAD Device exit line %d\n",
+-		__FUNCTION__,__LINE__);
++		__func__,__LINE__);
+ 		CLAW_DBF_TEXT(2,setup,"baddev");
+ 		return;
+ 	}
+@@ -3889,7 +3889,7 @@ claw_init_netdevice(struct net_device * dev)
+ 	dev->tx_queue_len = 1300;
+ 	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Exit\n",dev->name,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
+ #endif
+ 	CLAW_DBF_TEXT(2,setup,"initok");
+ 	return;
+@@ -3909,7 +3909,7 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
+ 	struct ccw_dev_id dev_id;
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__FUNCTION__);
++	printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__func__);
+ #endif
+ 	CLAW_DBF_TEXT_(2,setup,"%s",cdev->dev.bus_id);
+ 	privptr->channel[i].flag  = i+1;   /* Read is 1 Write is 2 */
+@@ -3920,16 +3920,16 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
+ 	p_ch->devno = dev_id.devno;
+ 	if ((p_ch->irb = kzalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
+ 		printk(KERN_WARNING "%s Out of memory in %s for irb\n",
+-			p_ch->id,__FUNCTION__);
++			p_ch->id,__func__);
+ #ifdef FUNCTRACE
+         	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-			p_ch->id,__FUNCTION__,__LINE__);
++			p_ch->id,__func__,__LINE__);
+ #endif
+ 		return -ENOMEM;
+ 	}
+ #ifdef FUNCTRACE
+         	printk(KERN_INFO "%s:%s Exit on line %d\n",
+-			cdev->dev.bus_id,__FUNCTION__,__LINE__);
++			cdev->dev.bus_id,__func__,__LINE__);
+ #endif
+ 	return 0;
+ }
+@@ -3952,7 +3952,7 @@ claw_new_device(struct ccwgroup_device *cgdev)
+ 	int ret;
+ 	struct ccw_dev_id dev_id;
+ 
+-	pr_debug("%s() called\n", __FUNCTION__);
++	pr_debug("%s() called\n", __func__);
+ 	printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
+ 	CLAW_DBF_TEXT(2,setup,"new_dev");
+ 	privptr = cgdev->dev.driver_data;
+@@ -3990,7 +3990,7 @@ claw_new_device(struct ccwgroup_device *cgdev)
+ 	}
+ 	dev = alloc_netdev(0,"claw%d",claw_init_netdevice);
+ 	if (!dev) {
+-		printk(KERN_WARNING "%s:alloc_netdev failed\n",__FUNCTION__);
++		printk(KERN_WARNING "%s:alloc_netdev failed\n",__func__);
+ 		goto out;
+ 	}
+ 	dev->priv = privptr;
+@@ -4065,7 +4065,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev)
+ 	struct net_device *ndev;
+ 	int	ret;
+ 
+-	pr_debug("%s() called\n", __FUNCTION__);
++	pr_debug("%s() called\n", __func__);
+ 	CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ 	priv = cgdev->dev.driver_data;
+ 	if (!priv)
+@@ -4095,15 +4095,15 @@ claw_remove_device(struct ccwgroup_device *cgdev)
+ {
+ 	struct claw_privbk *priv;
+ 
+-	pr_debug("%s() called\n", __FUNCTION__);
++	pr_debug("%s() called\n", __func__);
+ 	CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ 	priv = cgdev->dev.driver_data;
+ 	if (!priv) {
+-		printk(KERN_WARNING "claw: %s() no Priv exiting\n",__FUNCTION__);
++		printk(KERN_WARNING "claw: %s() no Priv exiting\n",__func__);
+ 		return;
+ 	}
+ 	printk(KERN_INFO "claw: %s() called %s will be removed.\n",
+-			__FUNCTION__,cgdev->cdev[0]->dev.bus_id);
++			__func__,cgdev->cdev[0]->dev.bus_id);
+ 	if (cgdev->state == CCWGROUP_ONLINE)
+ 		claw_shutdown_device(cgdev);
+ 	claw_remove_files(&cgdev->dev);
+@@ -4346,7 +4346,7 @@ static struct attribute_group claw_attr_group = {
+ static int
+ claw_add_files(struct device *dev)
+ {
+-	pr_debug("%s() called\n", __FUNCTION__);
++	pr_debug("%s() called\n", __func__);
+ 	CLAW_DBF_TEXT(2,setup,"add_file");
+ 	return sysfs_create_group(&dev->kobj, &claw_attr_group);
+ }
+@@ -4354,7 +4354,7 @@ claw_add_files(struct device *dev)
+ static void
+ claw_remove_files(struct device *dev)
+ {
+-	pr_debug("%s() called\n", __FUNCTION__);
++	pr_debug("%s() called\n", __func__);
+ 	CLAW_DBF_TEXT(2,setup,"rem_file");
+ 	sysfs_remove_group(&dev->kobj, &claw_attr_group);
+ }
+@@ -4385,12 +4385,12 @@ claw_init(void)
+ 	printk(KERN_INFO "claw: starting driver\n");
+ 
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "claw: %s() enter \n",__FUNCTION__);
++	printk(KERN_INFO "claw: %s() enter \n",__func__);
+ #endif
+ 	ret = claw_register_debug_facility();
+ 	if (ret) {
+ 		printk(KERN_WARNING "claw: %s() debug_register failed %d\n",
+-			__FUNCTION__,ret);
++			__func__,ret);
+ 		return ret;
+ 	}
+ 	CLAW_DBF_TEXT(2,setup,"init_mod");
+@@ -4398,10 +4398,10 @@ claw_init(void)
+ 	if (ret) {
+ 		claw_unregister_debug_facility();
+ 		printk(KERN_WARNING "claw; %s() cu3088 register failed %d\n",
+-			__FUNCTION__,ret);
++			__func__,ret);
+ 	}
+ #ifdef FUNCTRACE
+-        printk(KERN_INFO "claw: %s() exit \n",__FUNCTION__);
++	printk(KERN_INFO "claw: %s() exit \n",__func__);
+ #endif
+ 	return ret;
+ }
+diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c
+deleted file mode 100644
+index e6e72de..0000000
+--- a/drivers/s390/net/ctcdbug.c
++++ /dev/null
+@@ -1,80 +0,0 @@
+-/*
+- *
+- * linux/drivers/s390/net/ctcdbug.c
+- *
+- * CTC / ESCON network driver - s390 dbf exploit.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- *    Author(s): Original Code written by
+- *			  Peter Tiedemann (ptiedem at de.ibm.com)
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include "ctcdbug.h"
+-
+-/**
+- * Debug Facility Stuff
+- */
+-debug_info_t *ctc_dbf_setup = NULL;
+-debug_info_t *ctc_dbf_data = NULL;
+-debug_info_t *ctc_dbf_trace = NULL;
+-
+-DEFINE_PER_CPU(char[256], ctc_dbf_txt_buf);
+-
+-void
+-ctc_unregister_dbf_views(void)
+-{
+-	if (ctc_dbf_setup)
+-		debug_unregister(ctc_dbf_setup);
+-	if (ctc_dbf_data)
+-		debug_unregister(ctc_dbf_data);
+-	if (ctc_dbf_trace)
+-		debug_unregister(ctc_dbf_trace);
+-}
+-int
+-ctc_register_dbf_views(void)
+-{
+-	ctc_dbf_setup = debug_register(CTC_DBF_SETUP_NAME,
+-					CTC_DBF_SETUP_PAGES,
+-					CTC_DBF_SETUP_NR_AREAS,
+-					CTC_DBF_SETUP_LEN);
+-	ctc_dbf_data = debug_register(CTC_DBF_DATA_NAME,
+-				       CTC_DBF_DATA_PAGES,
+-				       CTC_DBF_DATA_NR_AREAS,
+-				       CTC_DBF_DATA_LEN);
+-	ctc_dbf_trace = debug_register(CTC_DBF_TRACE_NAME,
+-					CTC_DBF_TRACE_PAGES,
+-					CTC_DBF_TRACE_NR_AREAS,
+-					CTC_DBF_TRACE_LEN);
+-
+-	if ((ctc_dbf_setup == NULL) || (ctc_dbf_data == NULL) ||
+-	    (ctc_dbf_trace == NULL)) {
+-		ctc_unregister_dbf_views();
+-		return -ENOMEM;
+-	}
+-	debug_register_view(ctc_dbf_setup, &debug_hex_ascii_view);
+-	debug_set_level(ctc_dbf_setup, CTC_DBF_SETUP_LEVEL);
+-
+-	debug_register_view(ctc_dbf_data, &debug_hex_ascii_view);
+-	debug_set_level(ctc_dbf_data, CTC_DBF_DATA_LEVEL);
+-
+-	debug_register_view(ctc_dbf_trace, &debug_hex_ascii_view);
+-	debug_set_level(ctc_dbf_trace, CTC_DBF_TRACE_LEVEL);
+-
+-	return 0;
+-}
+-
+diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
+deleted file mode 100644
+index 413925e..0000000
+--- a/drivers/s390/net/ctcdbug.h
++++ /dev/null
+@@ -1,125 +0,0 @@
+-/*
+- *
+- * linux/drivers/s390/net/ctcdbug.h
+- *
+- * CTC / ESCON network driver - s390 dbf exploit.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- *    Author(s): Original Code written by
+- *			  Peter Tiedemann (ptiedem at de.ibm.com)
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-#ifndef _CTCDBUG_H_
+-#define _CTCDBUG_H_
+-
+-#include <asm/debug.h>
+-#include "ctcmain.h"
+-/**
+- * Debug Facility stuff
+- */
+-#define CTC_DBF_SETUP_NAME "ctc_setup"
+-#define CTC_DBF_SETUP_LEN 16
+-#define CTC_DBF_SETUP_PAGES 8
+-#define CTC_DBF_SETUP_NR_AREAS 1
+-#define CTC_DBF_SETUP_LEVEL 3
+-
+-#define CTC_DBF_DATA_NAME "ctc_data"
+-#define CTC_DBF_DATA_LEN 128
+-#define CTC_DBF_DATA_PAGES 8
+-#define CTC_DBF_DATA_NR_AREAS 1
+-#define CTC_DBF_DATA_LEVEL 3
+-
+-#define CTC_DBF_TRACE_NAME "ctc_trace"
+-#define CTC_DBF_TRACE_LEN 16
+-#define CTC_DBF_TRACE_PAGES 4
+-#define CTC_DBF_TRACE_NR_AREAS 2
+-#define CTC_DBF_TRACE_LEVEL 3
+-
+-#define DBF_TEXT(name,level,text) \
+-	do { \
+-		debug_text_event(ctc_dbf_##name,level,text); \
+-	} while (0)
+-
+-#define DBF_HEX(name,level,addr,len) \
+-	do { \
+-		debug_event(ctc_dbf_##name,level,(void*)(addr),len); \
+-	} while (0)
+-
+-DECLARE_PER_CPU(char[256], ctc_dbf_txt_buf);
+-extern debug_info_t *ctc_dbf_setup;
+-extern debug_info_t *ctc_dbf_data;
+-extern debug_info_t *ctc_dbf_trace;
+-
+-
+-#define DBF_TEXT_(name,level,text...)				\
+-	do {								\
+-		char* ctc_dbf_txt_buf = get_cpu_var(ctc_dbf_txt_buf);	\
+-		sprintf(ctc_dbf_txt_buf, text);			  	\
+-		debug_text_event(ctc_dbf_##name,level,ctc_dbf_txt_buf);	\
+-		put_cpu_var(ctc_dbf_txt_buf);				\
+-	} while (0)
+-
+-#define DBF_SPRINTF(name,level,text...) \
+-	do { \
+-		debug_sprintf_event(ctc_dbf_trace, level, ##text ); \
+-		debug_sprintf_event(ctc_dbf_trace, level, text ); \
+-	} while (0)
+-
+-
+-int ctc_register_dbf_views(void);
+-
+-void ctc_unregister_dbf_views(void);
+-
+-/**
+- * some more debug stuff
+- */
+-
+-#define HEXDUMP16(importance,header,ptr) \
+-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+-		   *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
+-		   *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
+-		   *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
+-		   *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
+-		   *(((char*)ptr)+12),*(((char*)ptr)+13), \
+-		   *(((char*)ptr)+14),*(((char*)ptr)+15)); \
+-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+-		   *(((char*)ptr)+16),*(((char*)ptr)+17), \
+-		   *(((char*)ptr)+18),*(((char*)ptr)+19), \
+-		   *(((char*)ptr)+20),*(((char*)ptr)+21), \
+-		   *(((char*)ptr)+22),*(((char*)ptr)+23), \
+-		   *(((char*)ptr)+24),*(((char*)ptr)+25), \
+-		   *(((char*)ptr)+26),*(((char*)ptr)+27), \
+-		   *(((char*)ptr)+28),*(((char*)ptr)+29), \
+-		   *(((char*)ptr)+30),*(((char*)ptr)+31));
+-
+-static inline void
+-hex_dump(unsigned char *buf, size_t len)
+-{
+-	size_t i;
+-
+-	for (i = 0; i < len; i++) {
+-		if (i && !(i % 16))
+-			printk("\n");
+-		printk("%02x ", *(buf + i));
+-	}
+-	printk("\n");
+-}
+-
+-
+-#endif
+diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c
+new file mode 100644
+index 0000000..8eb25d0
+--- /dev/null
++++ b/drivers/s390/net/ctcm_dbug.c
+@@ -0,0 +1,67 @@
++/*
++ *	drivers/s390/net/ctcm_dbug.c
++ *
++ *	Copyright IBM Corp. 2001, 2007
++ *	Authors:	Peter Tiedemann (ptiedem at de.ibm.com)
++ *
++ */
++
++#include <linux/stddef.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/ctype.h>
++#include <linux/sysctl.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/debugfs.h>
++#include "ctcm_dbug.h"
++
++/*
++ * Debug Facility Stuff
++ */
++
++DEFINE_PER_CPU(char[256], ctcm_dbf_txt_buf);
++
++struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS] = {
++	[CTCM_DBF_SETUP]	= {"ctc_setup", 8, 1, 64, 5, NULL},
++	[CTCM_DBF_ERROR]	= {"ctc_error", 8, 1, 64, 3, NULL},
++	[CTCM_DBF_TRACE]	= {"ctc_trace", 8, 1, 64, 3, NULL},
++	[CTCM_DBF_MPC_SETUP]	= {"mpc_setup", 8, 1, 64, 5, NULL},
++	[CTCM_DBF_MPC_ERROR]	= {"mpc_error", 8, 1, 64, 3, NULL},
++	[CTCM_DBF_MPC_TRACE]	= {"mpc_trace", 8, 1, 64, 3, NULL},
++};
++
++void ctcm_unregister_dbf_views(void)
++{
++	int x;
++	for (x = 0; x < CTCM_DBF_INFOS; x++) {
++		debug_unregister(ctcm_dbf[x].id);
++		ctcm_dbf[x].id = NULL;
++	}
++}
++
++int ctcm_register_dbf_views(void)
++{
++	int x;
++	for (x = 0; x < CTCM_DBF_INFOS; x++) {
++		/* register the areas */
++		ctcm_dbf[x].id = debug_register(ctcm_dbf[x].name,
++						ctcm_dbf[x].pages,
++						ctcm_dbf[x].areas,
++						ctcm_dbf[x].len);
++		if (ctcm_dbf[x].id == NULL) {
++			ctcm_unregister_dbf_views();
++			return -ENOMEM;
++		}
++
++		/* register a view */
++		debug_register_view(ctcm_dbf[x].id, &debug_hex_ascii_view);
++		/* set a passing level */
++		debug_set_level(ctcm_dbf[x].id, ctcm_dbf[x].level);
++	}
++
++	return 0;
++}
++
+diff --git a/drivers/s390/net/ctcm_dbug.h b/drivers/s390/net/ctcm_dbug.h
+new file mode 100644
+index 0000000..fdff34f
+--- /dev/null
++++ b/drivers/s390/net/ctcm_dbug.h
+@@ -0,0 +1,158 @@
++/*
++ *	drivers/s390/net/ctcm_dbug.h
++ *
++ *	Copyright IBM Corp. 2001, 2007
++ *	Authors:	Peter Tiedemann (ptiedem at de.ibm.com)
++ *
++ */
++
++#ifndef _CTCM_DBUG_H_
++#define _CTCM_DBUG_H_
++
++/*
++ * Debug Facility stuff
++ */
++
++#include <asm/debug.h>
++
++#ifdef DEBUG
++ #define do_debug 1
++#else
++ #define do_debug 0
++#endif
++#ifdef DEBUGDATA
++ #define do_debug_data 1
++#else
++ #define do_debug_data 0
++#endif
++#ifdef DEBUGCCW
++ #define do_debug_ccw 1
++#else
++ #define do_debug_ccw 0
++#endif
++
++/* define dbf debug levels similar to kernel msg levels */
++#define	CTC_DBF_ALWAYS	0	/* always print this 			*/
++#define	CTC_DBF_EMERG	0	/* system is unusable			*/
++#define	CTC_DBF_ALERT	1	/* action must be taken immediately	*/
++#define	CTC_DBF_CRIT	2	/* critical conditions			*/
++#define	CTC_DBF_ERROR	3	/* error conditions			*/
++#define	CTC_DBF_WARN	4	/* warning conditions			*/
++#define	CTC_DBF_NOTICE	5	/* normal but significant condition	*/
++#define	CTC_DBF_INFO	5	/* informational			*/
++#define	CTC_DBF_DEBUG	6	/* debug-level messages			*/
++
++DECLARE_PER_CPU(char[256], ctcm_dbf_txt_buf);
++
++enum ctcm_dbf_names {
++	CTCM_DBF_SETUP,
++	CTCM_DBF_ERROR,
++	CTCM_DBF_TRACE,
++	CTCM_DBF_MPC_SETUP,
++	CTCM_DBF_MPC_ERROR,
++	CTCM_DBF_MPC_TRACE,
++	CTCM_DBF_INFOS	/* must be last element */
++};
++
++struct ctcm_dbf_info {
++	char name[DEBUG_MAX_NAME_LEN];
++	int pages;
++	int areas;
++	int len;
++	int level;
++	debug_info_t *id;
++};
++
++extern struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS];
++
++int ctcm_register_dbf_views(void);
++void ctcm_unregister_dbf_views(void);
++
++static inline const char *strtail(const char *s, int n)
++{
++	int l = strlen(s);
++	return (l > n) ? s + (l - n) : s;
++}
++
++/* sort out levels early to avoid unnecessary sprintfs */
++static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
++{
++	return (dbf_grp->level >= level);
++}
++
++#define CTCM_FUNTAIL strtail((char *)__func__, 16)
++
++#define CTCM_DBF_TEXT(name, level, text) \
++	do { \
++		debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, level, text); \
++	} while (0)
++
++#define CTCM_DBF_HEX(name, level, addr, len) \
++	do { \
++		debug_event(ctcm_dbf[CTCM_DBF_##name].id, \
++					level, (void *)(addr), len); \
++	} while (0)
++
++#define CTCM_DBF_TEXT_(name, level, text...) \
++	do { \
++		if (ctcm_dbf_passes(ctcm_dbf[CTCM_DBF_##name].id, level)) { \
++			char *ctcm_dbf_txt_buf = \
++					 get_cpu_var(ctcm_dbf_txt_buf); \
++			sprintf(ctcm_dbf_txt_buf, text); \
++			debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, \
++					level, ctcm_dbf_txt_buf); \
++			put_cpu_var(ctcm_dbf_txt_buf); \
++		} \
++	} while (0)
++
++/*
++ * cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
++ * dev : netdevice with valid name field.
++ * text: any text string.
++ */
++#define CTCM_DBF_DEV_NAME(cat, dev, text) \
++	do { \
++		CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) : %s", \
++			CTCM_FUNTAIL, dev->name, text); \
++	} while (0)
++
++#define MPC_DBF_DEV_NAME(cat, dev, text) \
++	do { \
++		CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) : %s", \
++			CTCM_FUNTAIL, dev->name, text); \
++	} while (0)
++
++#define CTCMY_DBF_DEV_NAME(cat, dev, text) \
++	do { \
++		if (IS_MPCDEV(dev)) \
++			MPC_DBF_DEV_NAME(cat, dev, text); \
++		else \
++			CTCM_DBF_DEV_NAME(cat, dev, text); \
++	} while (0)
++
++/*
++ * cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
++ * dev : netdevice.
++ * text: any text string.
++ */
++#define CTCM_DBF_DEV(cat, dev, text) \
++	do { \
++		CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) : %s", \
++			CTCM_FUNTAIL, dev, text); \
++	} while (0)
++
++#define MPC_DBF_DEV(cat, dev, text) \
++	do { \
++		CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) : %s", \
++			CTCM_FUNTAIL, dev, text); \
++	} while (0)
++
++#define CTCMY_DBF_DEV(cat, dev, text) \
++	do { \
++		if (IS_MPCDEV(dev)) \
++			MPC_DBF_DEV(cat, dev, text); \
++		else \
++			CTCM_DBF_DEV(cat, dev, text); \
++	} while (0)
++
++#endif
+diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c
+new file mode 100644
+index 0000000..2a106f3
+--- /dev/null
++++ b/drivers/s390/net/ctcm_fsms.c
+@@ -0,0 +1,2347 @@
++/*
++ * drivers/s390/net/ctcm_fsms.c
++ *
++ * Copyright IBM Corp. 2001, 2007
++ * Authors:	Fritz Elfert (felfert at millenux.com)
++ * 		Peter Tiedemann (ptiedem at de.ibm.com)
++ *	MPC additions :
++ *		Belinda Thompson (belindat at us.ibm.com)
++ *		Andy Richter (richtera at us.ibm.com)
++ */
++
++#undef DEBUG
++#undef DEBUGDATA
++#undef DEBUGCCW
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/bitops.h>
++
++#include <linux/signal.h>
++#include <linux/string.h>
++
++#include <linux/ip.h>
++#include <linux/if_arp.h>
++#include <linux/tcp.h>
++#include <linux/skbuff.h>
++#include <linux/ctype.h>
++#include <net/dst.h>
++
++#include <linux/io.h>
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++#include <linux/uaccess.h>
++
++#include <asm/idals.h>
++
++#include "fsm.h"
++#include "cu3088.h"
++
++#include "ctcm_dbug.h"
++#include "ctcm_main.h"
++#include "ctcm_fsms.h"
++
++const char *dev_state_names[] = {
++	[DEV_STATE_STOPPED]		= "Stopped",
++	[DEV_STATE_STARTWAIT_RXTX]	= "StartWait RXTX",
++	[DEV_STATE_STARTWAIT_RX]	= "StartWait RX",
++	[DEV_STATE_STARTWAIT_TX]	= "StartWait TX",
++	[DEV_STATE_STOPWAIT_RXTX]	= "StopWait RXTX",
++	[DEV_STATE_STOPWAIT_RX]		= "StopWait RX",
++	[DEV_STATE_STOPWAIT_TX]		= "StopWait TX",
++	[DEV_STATE_RUNNING]		= "Running",
++};
++
++const char *dev_event_names[] = {
++	[DEV_EVENT_START]	= "Start",
++	[DEV_EVENT_STOP]	= "Stop",
++	[DEV_EVENT_RXUP]	= "RX up",
++	[DEV_EVENT_TXUP]	= "TX up",
++	[DEV_EVENT_RXDOWN]	= "RX down",
++	[DEV_EVENT_TXDOWN]	= "TX down",
++	[DEV_EVENT_RESTART]	= "Restart",
++};
++
++const char *ctc_ch_event_names[] = {
++	[CTC_EVENT_IO_SUCCESS]	= "ccw_device success",
++	[CTC_EVENT_IO_EBUSY]	= "ccw_device busy",
++	[CTC_EVENT_IO_ENODEV]	= "ccw_device enodev",
++	[CTC_EVENT_IO_UNKNOWN]	= "ccw_device unknown",
++	[CTC_EVENT_ATTNBUSY]	= "Status ATTN & BUSY",
++	[CTC_EVENT_ATTN]	= "Status ATTN",
++	[CTC_EVENT_BUSY]	= "Status BUSY",
++	[CTC_EVENT_UC_RCRESET]	= "Unit check remote reset",
++	[CTC_EVENT_UC_RSRESET]	= "Unit check remote system reset",
++	[CTC_EVENT_UC_TXTIMEOUT] = "Unit check TX timeout",
++	[CTC_EVENT_UC_TXPARITY]	= "Unit check TX parity",
++	[CTC_EVENT_UC_HWFAIL]	= "Unit check Hardware failure",
++	[CTC_EVENT_UC_RXPARITY]	= "Unit check RX parity",
++	[CTC_EVENT_UC_ZERO]	= "Unit check ZERO",
++	[CTC_EVENT_UC_UNKNOWN]	= "Unit check Unknown",
++	[CTC_EVENT_SC_UNKNOWN]	= "SubChannel check Unknown",
++	[CTC_EVENT_MC_FAIL]	= "Machine check failure",
++	[CTC_EVENT_MC_GOOD]	= "Machine check operational",
++	[CTC_EVENT_IRQ]		= "IRQ normal",
++	[CTC_EVENT_FINSTAT]	= "IRQ final",
++	[CTC_EVENT_TIMER]	= "Timer",
++	[CTC_EVENT_START]	= "Start",
++	[CTC_EVENT_STOP]	= "Stop",
++	/*
++	* additional MPC events
++	*/
++	[CTC_EVENT_SEND_XID]	= "XID Exchange",
++	[CTC_EVENT_RSWEEP_TIMER] = "MPC Group Sweep Timer",
++};
++
++const char *ctc_ch_state_names[] = {
++	[CTC_STATE_IDLE]	= "Idle",
++	[CTC_STATE_STOPPED]	= "Stopped",
++	[CTC_STATE_STARTWAIT]	= "StartWait",
++	[CTC_STATE_STARTRETRY]	= "StartRetry",
++	[CTC_STATE_SETUPWAIT]	= "SetupWait",
++	[CTC_STATE_RXINIT]	= "RX init",
++	[CTC_STATE_TXINIT]	= "TX init",
++	[CTC_STATE_RX]		= "RX",
++	[CTC_STATE_TX]		= "TX",
++	[CTC_STATE_RXIDLE]	= "RX idle",
++	[CTC_STATE_TXIDLE]	= "TX idle",
++	[CTC_STATE_RXERR]	= "RX error",
++	[CTC_STATE_TXERR]	= "TX error",
++	[CTC_STATE_TERM]	= "Terminating",
++	[CTC_STATE_DTERM]	= "Restarting",
++	[CTC_STATE_NOTOP]	= "Not operational",
++	/*
++	* additional MPC states
++	*/
++	[CH_XID0_PENDING]	= "Pending XID0 Start",
++	[CH_XID0_INPROGRESS]	= "In XID0 Negotiations ",
++	[CH_XID7_PENDING]	= "Pending XID7 P1 Start",
++	[CH_XID7_PENDING1]	= "Active XID7 P1 Exchange ",
++	[CH_XID7_PENDING2]	= "Pending XID7 P2 Start ",
++	[CH_XID7_PENDING3]	= "Active XID7 P2 Exchange ",
++	[CH_XID7_PENDING4]	= "XID7 Complete - Pending READY ",
++};
++
++static void ctcm_action_nop(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- static ctcm actions for channel statemachine -----
++ *
++*/
++static void chx_txdone(fsm_instance *fi, int event, void *arg);
++static void chx_rx(fsm_instance *fi, int event, void *arg);
++static void chx_rxidle(fsm_instance *fi, int event, void *arg);
++static void chx_firstio(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_start(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- static ctcmpc actions for ctcmpc channel statemachine -----
++ *
++*/
++static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg);
++static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg);
++static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg);
++/* shared :
++static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_start(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg);
++*/
++static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg);
++static void ctcmpc_chx_attnbusy(fsm_instance *, int, void *);
++static void ctcmpc_chx_resend(fsm_instance *, int, void *);
++static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg);
++
++/**
++ * Check return code of a preceeding ccw_device call, halt_IO etc...
++ *
++ * ch	:	The channel, the error belongs to.
++ * Returns the error code (!= 0) to inspect.
++ */
++void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg)
++{
++	CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
++			"ccw error %s (%s): %04x\n", ch->id, msg, rc);
++	switch (rc) {
++	case -EBUSY:
++		ctcm_pr_warn("%s (%s): Busy !\n", ch->id, msg);
++		fsm_event(ch->fsm, CTC_EVENT_IO_EBUSY, ch);
++		break;
++	case -ENODEV:
++		ctcm_pr_emerg("%s (%s): Invalid device called for IO\n",
++			     ch->id, msg);
++		fsm_event(ch->fsm, CTC_EVENT_IO_ENODEV, ch);
++		break;
++	default:
++		ctcm_pr_emerg("%s (%s): Unknown error in do_IO %04x\n",
++			     ch->id, msg, rc);
++		fsm_event(ch->fsm, CTC_EVENT_IO_UNKNOWN, ch);
++	}
++}
++
++void ctcm_purge_skb_queue(struct sk_buff_head *q)
++{
++	struct sk_buff *skb;
++
++	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++
++	while ((skb = skb_dequeue(q))) {
++		atomic_dec(&skb->users);
++		dev_kfree_skb_any(skb);
++	}
++}
++
++/**
++ * NOP action for statemachines
++ */
++static void ctcm_action_nop(fsm_instance *fi, int event, void *arg)
++{
++}
++
++/*
++ * Actions for channel - statemachines.
++ */
++
++/**
++ * Normal data has been send. Free the corresponding
++ * skb (it's in io_queue), reset dev->tbusy and
++ * revert to idle state.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void chx_txdone(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++	struct sk_buff *skb;
++	int first = 1;
++	int i;
++	unsigned long duration;
++	struct timespec done_stamp = current_kernel_time(); /* xtime */
++
++	duration =
++	    (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
++	    (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
++	if (duration > ch->prof.tx_time)
++		ch->prof.tx_time = duration;
++
++	if (ch->irb->scsw.count != 0)
++		ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
++			     dev->name, ch->irb->scsw.count);
++	fsm_deltimer(&ch->timer);
++	while ((skb = skb_dequeue(&ch->io_queue))) {
++		priv->stats.tx_packets++;
++		priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
++		if (first) {
++			priv->stats.tx_bytes += 2;
++			first = 0;
++		}
++		atomic_dec(&skb->users);
++		dev_kfree_skb_irq(skb);
++	}
++	spin_lock(&ch->collect_lock);
++	clear_normalized_cda(&ch->ccw[4]);
++	if (ch->collect_len > 0) {
++		int rc;
++
++		if (ctcm_checkalloc_buffer(ch)) {
++			spin_unlock(&ch->collect_lock);
++			return;
++		}
++		ch->trans_skb->data = ch->trans_skb_data;
++		skb_reset_tail_pointer(ch->trans_skb);
++		ch->trans_skb->len = 0;
++		if (ch->prof.maxmulti < (ch->collect_len + 2))
++			ch->prof.maxmulti = ch->collect_len + 2;
++		if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
++			ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
++		*((__u16 *)skb_put(ch->trans_skb, 2)) = ch->collect_len + 2;
++		i = 0;
++		while ((skb = skb_dequeue(&ch->collect_queue))) {
++			skb_copy_from_linear_data(skb,
++				skb_put(ch->trans_skb, skb->len), skb->len);
++			priv->stats.tx_packets++;
++			priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
++			atomic_dec(&skb->users);
++			dev_kfree_skb_irq(skb);
++			i++;
++		}
++		ch->collect_len = 0;
++		spin_unlock(&ch->collect_lock);
++		ch->ccw[1].count = ch->trans_skb->len;
++		fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++		ch->prof.send_stamp = current_kernel_time(); /* xtime */
++		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++						(unsigned long)ch, 0xff, 0);
++		ch->prof.doios_multi++;
++		if (rc != 0) {
++			priv->stats.tx_dropped += i;
++			priv->stats.tx_errors += i;
++			fsm_deltimer(&ch->timer);
++			ctcm_ccw_check_rc(ch, rc, "chained TX");
++		}
++	} else {
++		spin_unlock(&ch->collect_lock);
++		fsm_newstate(fi, CTC_STATE_TXIDLE);
++	}
++	ctcm_clear_busy_do(dev);
++}
++
++/**
++ * Initial data is sent.
++ * Notify device statemachine that we are up and
++ * running.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
++	fsm_deltimer(&ch->timer);
++	fsm_newstate(fi, CTC_STATE_TXIDLE);
++	fsm_event(priv->fsm, DEV_EVENT_TXUP, ch->netdev);
++}
++
++/**
++ * Got normal data, check for sanity, queue it up, allocate new buffer
++ * trigger bottom half, and initiate next read.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void chx_rx(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++	int len = ch->max_bufsize - ch->irb->scsw.count;
++	struct sk_buff *skb = ch->trans_skb;
++	__u16 block_len = *((__u16 *)skb->data);
++	int check_len;
++	int rc;
++
++	fsm_deltimer(&ch->timer);
++	if (len < 8) {
++		ctcm_pr_debug("%s: got packet with length %d < 8\n",
++			     dev->name, len);
++		priv->stats.rx_dropped++;
++		priv->stats.rx_length_errors++;
++						goto again;
++	}
++	if (len > ch->max_bufsize) {
++		ctcm_pr_debug("%s: got packet with length %d > %d\n",
++			     dev->name, len, ch->max_bufsize);
++		priv->stats.rx_dropped++;
++		priv->stats.rx_length_errors++;
++						goto again;
++	}
++
++	/*
++	 * VM TCP seems to have a bug sending 2 trailing bytes of garbage.
++	 */
++	switch (ch->protocol) {
++	case CTCM_PROTO_S390:
++	case CTCM_PROTO_OS390:
++		check_len = block_len + 2;
++		break;
++	default:
++		check_len = block_len;
++		break;
++	}
++	if ((len < block_len) || (len > check_len)) {
++		ctcm_pr_debug("%s: got block length %d != rx length %d\n",
++			     dev->name, block_len, len);
++		if (do_debug)
++			ctcmpc_dump_skb(skb, 0);
++
++		*((__u16 *)skb->data) = len;
++		priv->stats.rx_dropped++;
++		priv->stats.rx_length_errors++;
++						goto again;
++	}
++	block_len -= 2;
++	if (block_len > 0) {
++		*((__u16 *)skb->data) = block_len;
++		ctcm_unpack_skb(ch, skb);
++	}
++ again:
++	skb->data = ch->trans_skb_data;
++	skb_reset_tail_pointer(skb);
++	skb->len = 0;
++	if (ctcm_checkalloc_buffer(ch))
++		return;
++	ch->ccw[1].count = ch->max_bufsize;
++	rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++					(unsigned long)ch, 0xff, 0);
++	if (rc != 0)
++		ctcm_ccw_check_rc(ch, rc, "normal RX");
++}
++
++/**
++ * Initialize connection by sending a __u16 of value 0.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void chx_firstio(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	int rc;
++
++	CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
++
++	if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
++		ctcm_pr_debug("%s: remote side issued READ?, init.\n", ch->id);
++	fsm_deltimer(&ch->timer);
++	if (ctcm_checkalloc_buffer(ch))
++		return;
++	if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&
++	    (ch->protocol == CTCM_PROTO_OS390)) {
++		/* OS/390 resp. z/OS */
++		if (CHANNEL_DIRECTION(ch->flags) == READ) {
++			*((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;
++			fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC,
++				     CTC_EVENT_TIMER, ch);
++			chx_rxidle(fi, event, arg);
++		} else {
++			struct net_device *dev = ch->netdev;
++			struct ctcm_priv *priv = dev->priv;
++			fsm_newstate(fi, CTC_STATE_TXIDLE);
++			fsm_event(priv->fsm, DEV_EVENT_TXUP, dev);
++		}
++		return;
++	}
++
++	/*
++	 * Don't setup a timer for receiving the initial RX frame
++	 * if in compatibility mode, since VM TCP delays the initial
++	 * frame until it has some data to send.
++	 */
++	if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||
++	    (ch->protocol != CTCM_PROTO_S390))
++		fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++
++	*((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;
++	ch->ccw[1].count = 2;	/* Transfer only length */
++
++	fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
++		     ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
++	rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++					(unsigned long)ch, 0xff, 0);
++	if (rc != 0) {
++		fsm_deltimer(&ch->timer);
++		fsm_newstate(fi, CTC_STATE_SETUPWAIT);
++		ctcm_ccw_check_rc(ch, rc, "init IO");
++	}
++	/*
++	 * If in compatibility mode since we don't setup a timer, we
++	 * also signal RX channel up immediately. This enables us
++	 * to send packets early which in turn usually triggers some
++	 * reply from VM TCP which brings up the RX channel to it's
++	 * final state.
++	 */
++	if ((CHANNEL_DIRECTION(ch->flags) == READ) &&
++	    (ch->protocol == CTCM_PROTO_S390)) {
++		struct net_device *dev = ch->netdev;
++		struct ctcm_priv *priv = dev->priv;
++		fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
++	}
++}
++
++/**
++ * Got initial data, check it. If OK,
++ * notify device statemachine that we are up and
++ * running.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void chx_rxidle(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++	__u16 buflen;
++	int rc;
++
++	CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
++	fsm_deltimer(&ch->timer);
++	buflen = *((__u16 *)ch->trans_skb->data);
++	if (do_debug)
++		ctcm_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
++
++	if (buflen >= CTCM_INITIAL_BLOCKLEN) {
++		if (ctcm_checkalloc_buffer(ch))
++			return;
++		ch->ccw[1].count = ch->max_bufsize;
++		fsm_newstate(fi, CTC_STATE_RXIDLE);
++		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++						(unsigned long)ch, 0xff, 0);
++		if (rc != 0) {
++			fsm_newstate(fi, CTC_STATE_RXINIT);
++			ctcm_ccw_check_rc(ch, rc, "initial RX");
++		} else
++			fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
++	} else {
++		if (do_debug)
++			ctcm_pr_debug("%s: Initial RX count %d not %d\n",
++				dev->name, buflen, CTCM_INITIAL_BLOCKLEN);
++		chx_firstio(fi, event, arg);
++	}
++}
++
++/**
++ * Set channel into extended mode.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	int rc;
++	unsigned long saveflags = 0;
++	int timeout = CTCM_TIME_5_SEC;
++
++	fsm_deltimer(&ch->timer);
++	if (IS_MPC(ch)) {
++		timeout = 1500;
++		if (do_debug)
++			ctcm_pr_debug("ctcm enter: %s(): cp=%i ch=0x%p id=%s\n",
++				__FUNCTION__, smp_processor_id(), ch, ch->id);
++	}
++	fsm_addtimer(&ch->timer, timeout, CTC_EVENT_TIMER, ch);
++	fsm_newstate(fi, CTC_STATE_SETUPWAIT);
++	if (do_debug_ccw && IS_MPC(ch))
++		ctcmpc_dumpit((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);
++
++	if (event == CTC_EVENT_TIMER)	/* only for timer not yet locked */
++		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++			/* Such conditional locking is undeterministic in
++			 * static view. => ignore sparse warnings here. */
++
++	rc = ccw_device_start(ch->cdev, &ch->ccw[6],
++					(unsigned long)ch, 0xff, 0);
++	if (event == CTC_EVENT_TIMER)	/* see above comments */
++		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++	if (rc != 0) {
++		fsm_deltimer(&ch->timer);
++		fsm_newstate(fi, CTC_STATE_STARTWAIT);
++		ctcm_ccw_check_rc(ch, rc, "set Mode");
++	} else
++		ch->retry = 0;
++}
++
++/**
++ * Setup channel.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	int rc;
++	struct net_device *dev;
++	unsigned long saveflags;
++
++	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
++	if (ch == NULL) {
++		ctcm_pr_warn("chx_start ch=NULL\n");
++		return;
++	}
++	if (ch->netdev == NULL) {
++		ctcm_pr_warn("chx_start dev=NULL, id=%s\n", ch->id);
++		return;
++	}
++	dev = ch->netdev;
++
++	if (do_debug)
++		ctcm_pr_debug("%s: %s channel start\n", dev->name,
++			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++
++	if (ch->trans_skb != NULL) {
++		clear_normalized_cda(&ch->ccw[1]);
++		dev_kfree_skb(ch->trans_skb);
++		ch->trans_skb = NULL;
++	}
++	if (CHANNEL_DIRECTION(ch->flags) == READ) {
++		ch->ccw[1].cmd_code = CCW_CMD_READ;
++		ch->ccw[1].flags = CCW_FLAG_SLI;
++		ch->ccw[1].count = 0;
++	} else {
++		ch->ccw[1].cmd_code = CCW_CMD_WRITE;
++		ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[1].count = 0;
++	}
++	if (ctcm_checkalloc_buffer(ch)) {
++		ctcm_pr_notice("%s: %s trans_skb allocation delayed "
++				"until first transfer\n", dev->name,
++			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++	}
++
++	ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
++	ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++	ch->ccw[0].count = 0;
++	ch->ccw[0].cda = 0;
++	ch->ccw[2].cmd_code = CCW_CMD_NOOP;	/* jointed CE + DE */
++	ch->ccw[2].flags = CCW_FLAG_SLI;
++	ch->ccw[2].count = 0;
++	ch->ccw[2].cda = 0;
++	memcpy(&ch->ccw[3], &ch->ccw[0], sizeof(struct ccw1) * 3);
++	ch->ccw[4].cda = 0;
++	ch->ccw[4].flags &= ~CCW_FLAG_IDA;
++
++	fsm_newstate(fi, CTC_STATE_STARTWAIT);
++	fsm_addtimer(&ch->timer, 1000, CTC_EVENT_TIMER, ch);
++	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++	rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
++	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++	if (rc != 0) {
++		if (rc != -EBUSY)
++			fsm_deltimer(&ch->timer);
++		ctcm_ccw_check_rc(ch, rc, "initial HaltIO");
++	}
++}
++
++/**
++ * Shutdown a channel.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	unsigned long saveflags = 0;
++	int rc;
++	int oldstate;
++
++	CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
++	fsm_deltimer(&ch->timer);
++	if (IS_MPC(ch))
++		fsm_deltimer(&ch->sweep_timer);
++
++	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++
++	if (event == CTC_EVENT_STOP)	/* only for STOP not yet locked */
++		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++			/* Such conditional locking is undeterministic in
++			 * static view. => ignore sparse warnings here. */
++	oldstate = fsm_getstate(fi);
++	fsm_newstate(fi, CTC_STATE_TERM);
++	rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
++
++	if (event == CTC_EVENT_STOP)
++		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++			/* see remark above about conditional locking */
++
++	if (rc != 0 && rc != -EBUSY) {
++		fsm_deltimer(&ch->timer);
++		if (event != CTC_EVENT_STOP) {
++			fsm_newstate(fi, oldstate);
++			ctcm_ccw_check_rc(ch, rc, (char *)__FUNCTION__);
++		}
++	}
++}
++
++/**
++ * Cleanup helper for chx_fail and chx_stopped
++ * cleanup channels queue and notify interface statemachine.
++ *
++ * fi		An instance of a channel statemachine.
++ * state	The next state (depending on caller).
++ * ch		The channel to operate on.
++ */
++static void ctcm_chx_cleanup(fsm_instance *fi, int state,
++		struct channel *ch)
++{
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++
++	fsm_deltimer(&ch->timer);
++	if (IS_MPC(ch))
++		fsm_deltimer(&ch->sweep_timer);
++
++	fsm_newstate(fi, state);
++	if (state == CTC_STATE_STOPPED && ch->trans_skb != NULL) {
++		clear_normalized_cda(&ch->ccw[1]);
++		dev_kfree_skb_any(ch->trans_skb);
++		ch->trans_skb = NULL;
++	}
++
++	ch->th_seg = 0x00;
++	ch->th_seq_num = 0x00;
++	if (CHANNEL_DIRECTION(ch->flags) == READ) {
++		skb_queue_purge(&ch->io_queue);
++		fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++	} else {
++		ctcm_purge_skb_queue(&ch->io_queue);
++		if (IS_MPC(ch))
++			ctcm_purge_skb_queue(&ch->sweep_queue);
++		spin_lock(&ch->collect_lock);
++		ctcm_purge_skb_queue(&ch->collect_queue);
++		ch->collect_len = 0;
++		spin_unlock(&ch->collect_lock);
++		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++	}
++}
++
++/**
++ * A channel has successfully been halted.
++ * Cleanup it's queue and notify interface statemachine.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg)
++{
++	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++	ctcm_chx_cleanup(fi, CTC_STATE_STOPPED, arg);
++}
++
++/**
++ * A stop command from device statemachine arrived and we are in
++ * not operational mode. Set state to stopped.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg)
++{
++	fsm_newstate(fi, CTC_STATE_STOPPED);
++}
++
++/**
++ * A machine check for no path, not operational status or gone device has
++ * happened.
++ * Cleanup queue and notify interface statemachine.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg)
++{
++	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++	ctcm_chx_cleanup(fi, CTC_STATE_NOTOP, arg);
++}
++
++/**
++ * Handle error during setup of channel.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++
++	/*
++	 * Special case: Got UC_RCRESET on setmode.
++	 * This means that remote side isn't setup. In this case
++	 * simply retry after some 10 secs...
++	 */
++	if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&
++	    ((event == CTC_EVENT_UC_RCRESET) ||
++	     (event == CTC_EVENT_UC_RSRESET))) {
++		fsm_newstate(fi, CTC_STATE_STARTRETRY);
++		fsm_deltimer(&ch->timer);
++		fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++		if (!IS_MPC(ch) && (CHANNEL_DIRECTION(ch->flags) == READ)) {
++			int rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
++			if (rc != 0)
++				ctcm_ccw_check_rc(ch, rc,
++					"HaltIO in chx_setuperr");
++		}
++		return;
++	}
++
++	CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
++		"%s : %s error during %s channel setup state=%s\n",
++		dev->name, ctc_ch_event_names[event],
++		(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
++		fsm_getstate_str(fi));
++
++	if (CHANNEL_DIRECTION(ch->flags) == READ) {
++		fsm_newstate(fi, CTC_STATE_RXERR);
++		fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++	} else {
++		fsm_newstate(fi, CTC_STATE_TXERR);
++		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++	}
++}
++
++/**
++ * Restart a channel after an error.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	unsigned long saveflags = 0;
++	int oldstate;
++	int rc;
++
++	CTCM_DBF_TEXT(TRACE, CTC_DBF_NOTICE, __FUNCTION__);
++	fsm_deltimer(&ch->timer);
++	ctcm_pr_debug("%s: %s channel restart\n", dev->name,
++		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++	oldstate = fsm_getstate(fi);
++	fsm_newstate(fi, CTC_STATE_STARTWAIT);
++	if (event == CTC_EVENT_TIMER)	/* only for timer not yet locked */
++		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++			/* Such conditional locking is a known problem for
++			 * sparse because its undeterministic in static view.
++			 * Warnings should be ignored here. */
++	rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
++	if (event == CTC_EVENT_TIMER)
++		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++	if (rc != 0) {
++		if (rc != -EBUSY) {
++		    fsm_deltimer(&ch->timer);
++		    fsm_newstate(fi, oldstate);
++		}
++		ctcm_ccw_check_rc(ch, rc, "HaltIO in ctcm_chx_restart");
++	}
++}
++
++/**
++ * Handle error during RX initial handshake (exchange of
++ * 0-length block header)
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
++	if (event == CTC_EVENT_TIMER) {
++		if (!IS_MPCDEV(dev))
++			/* TODO : check if MPC deletes timer somewhere */
++			fsm_deltimer(&ch->timer);
++		ctcm_pr_debug("%s: Timeout during RX init handshake\n",
++				dev->name);
++		if (ch->retry++ < 3)
++			ctcm_chx_restart(fi, event, arg);
++		else {
++			fsm_newstate(fi, CTC_STATE_RXERR);
++			fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++		}
++	} else
++		ctcm_pr_warn("%s: Error during RX init handshake\n", dev->name);
++}
++
++/**
++ * Notify device statemachine if we gave up initialization
++ * of RX channel.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
++	fsm_newstate(fi, CTC_STATE_RXERR);
++	ctcm_pr_warn("%s: RX busy. Initialization failed\n", dev->name);
++	fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++}
++
++/**
++ * Handle RX Unit check remote reset (remote disconnected)
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct channel *ch2;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCM_DBF_DEV_NAME(TRACE, dev, "Got remote disconnect, re-initializing");
++	fsm_deltimer(&ch->timer);
++	if (do_debug)
++		ctcm_pr_debug("%s: Got remote disconnect, "
++				"re-initializing ...\n", dev->name);
++	/*
++	 * Notify device statemachine
++	 */
++	fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++	fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++
++	fsm_newstate(fi, CTC_STATE_DTERM);
++	ch2 = priv->channel[WRITE];
++	fsm_newstate(ch2->fsm, CTC_STATE_DTERM);
++
++	ccw_device_halt(ch->cdev, (unsigned long)ch);
++	ccw_device_halt(ch2->cdev, (unsigned long)ch2);
++}
++
++/**
++ * Handle error during TX channel initialization.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++
++	if (event == CTC_EVENT_TIMER) {
++		fsm_deltimer(&ch->timer);
++		CTCM_DBF_DEV_NAME(ERROR, dev,
++				"Timeout during TX init handshake");
++		if (ch->retry++ < 3)
++			ctcm_chx_restart(fi, event, arg);
++		else {
++			fsm_newstate(fi, CTC_STATE_TXERR);
++			fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++		}
++	} else {
++		CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
++			"%s : %s error during channel setup state=%s",
++			dev->name, ctc_ch_event_names[event],
++			fsm_getstate_str(fi));
++
++		ctcm_pr_warn("%s: Error during TX init handshake\n", dev->name);
++	}
++}
++
++/**
++ * Handle TX timeout by retrying operation.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++	struct sk_buff *skb;
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++			__FUNCTION__, smp_processor_id(), ch, ch->id);
++
++	fsm_deltimer(&ch->timer);
++	if (ch->retry++ > 3) {
++		struct mpc_group *gptr = priv->mpcg;
++		ctcm_pr_debug("%s: TX retry failed, restarting channel\n",
++			     dev->name);
++		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++		/* call restart if not MPC or if MPC and mpcg fsm is ready.
++			use gptr as mpc indicator */
++		if (!(gptr && (fsm_getstate(gptr->fsm) != MPCG_STATE_READY)))
++			ctcm_chx_restart(fi, event, arg);
++				goto done;
++	}
++
++	ctcm_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
++	skb = skb_peek(&ch->io_queue);
++	if (skb) {
++		int rc = 0;
++		unsigned long saveflags = 0;
++		clear_normalized_cda(&ch->ccw[4]);
++		ch->ccw[4].count = skb->len;
++		if (set_normalized_cda(&ch->ccw[4], skb->data)) {
++			ctcm_pr_debug("%s: IDAL alloc failed, chan restart\n",
++						dev->name);
++			fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++			ctcm_chx_restart(fi, event, arg);
++				goto done;
++		}
++		fsm_addtimer(&ch->timer, 1000, CTC_EVENT_TIMER, ch);
++		if (event == CTC_EVENT_TIMER) /* for TIMER not yet locked */
++			spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++			/* Such conditional locking is a known problem for
++			 * sparse because its undeterministic in static view.
++			 * Warnings should be ignored here. */
++		if (do_debug_ccw)
++			ctcmpc_dumpit((char *)&ch->ccw[3],
++					sizeof(struct ccw1) * 3);
++
++		rc = ccw_device_start(ch->cdev, &ch->ccw[3],
++						(unsigned long)ch, 0xff, 0);
++		if (event == CTC_EVENT_TIMER)
++			spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev),
++					saveflags);
++		if (rc != 0) {
++			fsm_deltimer(&ch->timer);
++			ctcm_ccw_check_rc(ch, rc, "TX in chx_txretry");
++			ctcm_purge_skb_queue(&ch->io_queue);
++		}
++	}
++done:
++	return;
++}
++
++/**
++ * Handle fatal errors during an I/O command.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++	fsm_deltimer(&ch->timer);
++	ctcm_pr_warn("%s %s : unrecoverable channel error\n",
++			CTC_DRIVER_NAME, dev->name);
++	if (IS_MPC(ch)) {
++		priv->stats.tx_dropped++;
++		priv->stats.tx_errors++;
++	}
++
++	if (CHANNEL_DIRECTION(ch->flags) == READ) {
++		ctcm_pr_debug("%s: RX I/O error\n", dev->name);
++		fsm_newstate(fi, CTC_STATE_RXERR);
++		fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++	} else {
++		ctcm_pr_debug("%s: TX I/O error\n", dev->name);
++		fsm_newstate(fi, CTC_STATE_TXERR);
++		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++	}
++}
++
++/*
++ * The ctcm statemachine for a channel.
++ */
++const fsm_node ch_fsm[] = {
++	{ CTC_STATE_STOPPED,	CTC_EVENT_STOP,		ctcm_action_nop  },
++	{ CTC_STATE_STOPPED,	CTC_EVENT_START,	ctcm_chx_start  },
++	{ CTC_STATE_STOPPED,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
++	{ CTC_STATE_STOPPED,	CTC_EVENT_MC_FAIL,	ctcm_action_nop  },
++
++	{ CTC_STATE_NOTOP,	CTC_EVENT_STOP,		ctcm_chx_stop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_MC_FAIL,	ctcm_action_nop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_MC_GOOD,	ctcm_chx_start  },
++
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_TIMER,	ctcm_chx_setuperr  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_STARTRETRY,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_STARTRETRY,	CTC_EVENT_TIMER,	ctcm_chx_setmode  },
++	{ CTC_STATE_STARTRETRY,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
++	{ CTC_STATE_STARTRETRY,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_FINSTAT,	chx_firstio  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_TIMER,	ctcm_chx_setmode  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_RXINIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_FINSTAT,	chx_rxidle  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_rxiniterr  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_rxiniterr  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_TIMER,	ctcm_chx_rxiniterr  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_ATTNBUSY,	ctcm_chx_rxinitfail  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_ZERO,	chx_firstio  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_FINSTAT,	chx_rx  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_RCRESET,	ctcm_chx_rxdisc  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_ZERO,	chx_rx  },
++
++	{ CTC_STATE_TXINIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_FINSTAT,	ctcm_chx_txidle  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_txiniterr  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_txiniterr  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_TIMER,	ctcm_chx_txiniterr  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_FINSTAT,	chx_firstio  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_TERM,	CTC_EVENT_STOP,		ctcm_action_nop  },
++	{ CTC_STATE_TERM,	CTC_EVENT_START,	ctcm_chx_restart  },
++	{ CTC_STATE_TERM,	CTC_EVENT_FINSTAT,	ctcm_chx_stopped  },
++	{ CTC_STATE_TERM,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
++	{ CTC_STATE_TERM,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
++	{ CTC_STATE_TERM,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_DTERM,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_START,	ctcm_chx_restart  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_TX,		CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TX,		CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_TX,		CTC_EVENT_FINSTAT,	chx_txdone  },
++	{ CTC_STATE_TX,		CTC_EVENT_UC_RCRESET,	ctcm_chx_txretry  },
++	{ CTC_STATE_TX,		CTC_EVENT_UC_RSRESET,	ctcm_chx_txretry  },
++	{ CTC_STATE_TX,		CTC_EVENT_TIMER,	ctcm_chx_txretry  },
++	{ CTC_STATE_TX,		CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_TX,		CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_RXERR,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TXERR,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TXERR,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_RXERR,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++};
++
++int ch_fsm_len = ARRAY_SIZE(ch_fsm);
++
++/*
++ * MPC actions for mpc channel statemachine
++ * handling of MPC protocol requires extra
++ * statemachine and actions which are prefixed ctcmpc_ .
++ * The ctc_ch_states and ctc_ch_state_names,
++ * ctc_ch_events and ctc_ch_event_names share the ctcm definitions
++ * which are expanded by some elements.
++ */
++
++/*
++ * Actions for mpc channel statemachine.
++ */
++
++/**
++ * Normal data has been send. Free the corresponding
++ * skb (it's in io_queue), reset dev->tbusy and
++ * revert to idle state.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
++{
++	struct channel		*ch = arg;
++	struct net_device	*dev = ch->netdev;
++	struct ctcm_priv	*priv = dev->priv;
++	struct mpc_group	*grp = priv->mpcg;
++	struct sk_buff		*skb;
++	int		first = 1;
++	int		i;
++	struct timespec done_stamp;
++	__u32		data_space;
++	unsigned long	duration;
++	struct sk_buff	*peekskb;
++	int		rc;
++	struct th_header *header;
++	struct pdu	*p_header;
++
++	if (do_debug)
++		ctcm_pr_debug("%s cp:%i enter:  %s()\n",
++			dev->name, smp_processor_id(), __FUNCTION__);
++
++	done_stamp = current_kernel_time(); /* xtime */
++	duration = (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000
++		+ (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
++	if (duration > ch->prof.tx_time)
++		ch->prof.tx_time = duration;
++
++	if (ch->irb->scsw.count != 0)
++		ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
++				dev->name, ch->irb->scsw.count);
++	fsm_deltimer(&ch->timer);
++	while ((skb = skb_dequeue(&ch->io_queue))) {
++		priv->stats.tx_packets++;
++		priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
++		if (first) {
++			priv->stats.tx_bytes += 2;
++			first = 0;
++		}
++		atomic_dec(&skb->users);
++		dev_kfree_skb_irq(skb);
++	}
++	spin_lock(&ch->collect_lock);
++	clear_normalized_cda(&ch->ccw[4]);
++
++	if ((ch->collect_len <= 0) || (grp->in_sweep != 0)) {
++		spin_unlock(&ch->collect_lock);
++		fsm_newstate(fi, CTC_STATE_TXIDLE);
++				goto done;
++	}
++
++	if (ctcm_checkalloc_buffer(ch)) {
++		spin_unlock(&ch->collect_lock);
++				goto done;
++	}
++	ch->trans_skb->data = ch->trans_skb_data;
++	skb_reset_tail_pointer(ch->trans_skb);
++	ch->trans_skb->len = 0;
++	if (ch->prof.maxmulti < (ch->collect_len + TH_HEADER_LENGTH))
++		ch->prof.maxmulti = ch->collect_len + TH_HEADER_LENGTH;
++	if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
++		ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
++	i = 0;
++
++	if (do_debug_data)
++		ctcm_pr_debug("ctcmpc: %s() building "
++			       "trans_skb from collect_q \n", __FUNCTION__);
++
++	data_space = grp->group_max_buflen - TH_HEADER_LENGTH;
++
++	if (do_debug_data)
++		ctcm_pr_debug("ctcmpc: %s() building trans_skb from collect_q"
++		       " data_space:%04x\n", __FUNCTION__, data_space);
++	p_header = NULL;
++	while ((skb = skb_dequeue(&ch->collect_queue))) {
++		memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
++		p_header = (struct pdu *)
++			(skb_tail_pointer(ch->trans_skb) - skb->len);
++		p_header->pdu_flag = 0x00;
++		if (skb->protocol == ntohs(ETH_P_SNAP))
++			p_header->pdu_flag |= 0x60;
++		else
++			p_header->pdu_flag |= 0x20;
++
++		if (do_debug_data) {
++			ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
++				       __FUNCTION__, ch->trans_skb->len);
++			ctcm_pr_debug("ctcmpc: %s() pdu header and data"
++				       " for up to 32 bytes sent to vtam\n",
++				       __FUNCTION__);
++			ctcmpc_dumpit((char *)p_header,
++						min_t(int, skb->len, 32));
++		}
++		ch->collect_len -= skb->len;
++		data_space -= skb->len;
++		priv->stats.tx_packets++;
++		priv->stats.tx_bytes += skb->len;
++		atomic_dec(&skb->users);
++		dev_kfree_skb_any(skb);
++		peekskb = skb_peek(&ch->collect_queue);
++		if (peekskb->len > data_space)
++			break;
++		i++;
++	}
++	/* p_header points to the last one we handled */
++	if (p_header)
++		p_header->pdu_flag |= PDU_LAST;	/*Say it's the last one*/
++	header = kzalloc(TH_HEADER_LENGTH, gfp_type());
++
++	if (!header) {
++		printk(KERN_WARNING "ctcmpc: OUT OF MEMORY IN %s()"
++		       ": Data Lost \n", __FUNCTION__);
++		spin_unlock(&ch->collect_lock);
++		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++		goto done;
++	}
++
++	header->th_ch_flag = TH_HAS_PDU;  /* Normal data */
++	ch->th_seq_num++;
++	header->th_seq_num = ch->th_seq_num;
++
++	if (do_debug_data)
++		ctcm_pr_debug("%s: ToVTAM_th_seq= %08x\n" ,
++					__FUNCTION__, ch->th_seq_num);
++
++	memcpy(skb_push(ch->trans_skb, TH_HEADER_LENGTH), header,
++		TH_HEADER_LENGTH);	/* put the TH on the packet */
++
++	kfree(header);
++
++	if (do_debug_data) {
++		ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
++		       __FUNCTION__, ch->trans_skb->len);
++
++		ctcm_pr_debug("ctcmpc: %s() up-to-50 bytes of trans_skb "
++			"data to vtam from collect_q\n", __FUNCTION__);
++		ctcmpc_dumpit((char *)ch->trans_skb->data,
++				min_t(int, ch->trans_skb->len, 50));
++	}
++
++	spin_unlock(&ch->collect_lock);
++	clear_normalized_cda(&ch->ccw[1]);
++	if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
++		dev_kfree_skb_any(ch->trans_skb);
++		ch->trans_skb = NULL;
++		printk(KERN_WARNING
++		       "ctcmpc: %s()CCW failure - data lost\n",
++		       __FUNCTION__);
++		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++		return;
++	}
++	ch->ccw[1].count = ch->trans_skb->len;
++	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++	ch->prof.send_stamp = current_kernel_time(); /* xtime */
++	if (do_debug_ccw)
++		ctcmpc_dumpit((char *)&ch->ccw[0], sizeof(struct ccw1) * 3);
++	rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++					(unsigned long)ch, 0xff, 0);
++	ch->prof.doios_multi++;
++	if (rc != 0) {
++		priv->stats.tx_dropped += i;
++		priv->stats.tx_errors += i;
++		fsm_deltimer(&ch->timer);
++		ctcm_ccw_check_rc(ch, rc, "chained TX");
++	}
++done:
++	ctcm_clear_busy(dev);
++	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
++	return;
++}
++
++/**
++ * Got normal data, check for sanity, queue it up, allocate new buffer
++ * trigger bottom half, and initiate next read.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
++{
++	struct channel		*ch = arg;
++	struct net_device	*dev = ch->netdev;
++	struct ctcm_priv	*priv = dev->priv;
++	struct mpc_group	*grp = priv->mpcg;
++	struct sk_buff		*skb = ch->trans_skb;
++	struct sk_buff		*new_skb;
++	unsigned long	saveflags = 0;	/* avoids compiler warning */
++	int len	= ch->max_bufsize - ch->irb->scsw.count;
++
++	if (do_debug_data) {
++		CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx %s cp:%i %s\n",
++				dev->name, smp_processor_id(), ch->id);
++		CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx: maxbuf: %04x "
++				"len: %04x\n", ch->max_bufsize, len);
++	}
++	fsm_deltimer(&ch->timer);
++
++	if (skb == NULL) {
++		ctcm_pr_debug("ctcmpc exit:  %s() TRANS_SKB = NULL \n",
++			       __FUNCTION__);
++					goto again;
++	}
++
++	if (len < TH_HEADER_LENGTH) {
++		ctcm_pr_info("%s: got packet with invalid length %d\n",
++				dev->name, len);
++		priv->stats.rx_dropped++;
++		priv->stats.rx_length_errors++;
++	} else {
++		/* must have valid th header or game over */
++		__u32	block_len = len;
++		len = TH_HEADER_LENGTH + XID2_LENGTH + 4;
++		new_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC);
++
++		if (new_skb == NULL) {
++			printk(KERN_INFO "ctcmpc:%s() NEW_SKB = NULL\n",
++			       __FUNCTION__);
++			printk(KERN_WARNING "ctcmpc: %s() MEMORY ALLOC FAILED"
++			       " - DATA LOST - MPC FAILED\n",
++			       __FUNCTION__);
++			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++					goto again;
++		}
++		switch (fsm_getstate(grp->fsm)) {
++		case MPCG_STATE_RESET:
++		case MPCG_STATE_INOP:
++			dev_kfree_skb_any(new_skb);
++			break;
++		case MPCG_STATE_FLOWC:
++		case MPCG_STATE_READY:
++			memcpy(skb_put(new_skb, block_len),
++					       skb->data, block_len);
++			skb_queue_tail(&ch->io_queue, new_skb);
++			tasklet_schedule(&ch->ch_tasklet);
++			break;
++		default:
++			memcpy(skb_put(new_skb, len), skb->data, len);
++			skb_queue_tail(&ch->io_queue, new_skb);
++			tasklet_hi_schedule(&ch->ch_tasklet);
++			break;
++		}
++	}
++
++again:
++	switch (fsm_getstate(grp->fsm)) {
++	int rc, dolock;
++	case MPCG_STATE_FLOWC:
++	case MPCG_STATE_READY:
++		if (ctcm_checkalloc_buffer(ch))
++			break;
++		ch->trans_skb->data = ch->trans_skb_data;
++		skb_reset_tail_pointer(ch->trans_skb);
++		ch->trans_skb->len = 0;
++		ch->ccw[1].count = ch->max_bufsize;
++			if (do_debug_ccw)
++			ctcmpc_dumpit((char *)&ch->ccw[0],
++					sizeof(struct ccw1) * 3);
++		dolock = !in_irq();
++		if (dolock)
++			spin_lock_irqsave(
++				get_ccwdev_lock(ch->cdev), saveflags);
++		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++						(unsigned long)ch, 0xff, 0);
++		if (dolock) /* see remark about conditional locking */
++			spin_unlock_irqrestore(
++				get_ccwdev_lock(ch->cdev), saveflags);
++		if (rc != 0)
++			ctcm_ccw_check_rc(ch, rc, "normal RX");
++	default:
++		break;
++	}
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
++				dev->name, __FUNCTION__, ch, ch->id);
++
++}
++
++/**
++ * Initialize connection by sending a __u16 of value 0.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)
++{
++	struct channel		*ch = arg;
++	struct net_device	*dev = ch->netdev;
++	struct ctcm_priv	*priv = dev->priv;
++
++	if (do_debug) {
++		struct mpc_group *gptr = priv->mpcg;
++		ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
++				__FUNCTION__, ch, ch->id);
++		ctcm_pr_debug("%s() %s chstate:%i grpstate:%i chprotocol:%i\n",
++				__FUNCTION__, ch->id, fsm_getstate(fi),
++				fsm_getstate(gptr->fsm), ch->protocol);
++	}
++	if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
++		MPC_DBF_DEV_NAME(TRACE, dev, "remote side issued READ? ");
++
++	fsm_deltimer(&ch->timer);
++	if (ctcm_checkalloc_buffer(ch))
++				goto done;
++
++	switch (fsm_getstate(fi)) {
++	case CTC_STATE_STARTRETRY:
++	case CTC_STATE_SETUPWAIT:
++		if (CHANNEL_DIRECTION(ch->flags) == READ) {
++			ctcmpc_chx_rxidle(fi, event, arg);
++		} else {
++			fsm_newstate(fi, CTC_STATE_TXIDLE);
++			fsm_event(priv->fsm, DEV_EVENT_TXUP, dev);
++		}
++				goto done;
++	default:
++		break;
++	};
++
++	fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
++		     ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
++
++done:
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++			__FUNCTION__, ch, ch->id);
++	return;
++}
++
++/**
++ * Got initial data, check it. If OK,
++ * notify device statemachine that we are up and
++ * running.
++ *
++ * fi		An instance of a channel statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from channel * upon call.
++ */
++void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)
++{
++	struct channel *ch = arg;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv  *priv = dev->priv;
++	struct mpc_group  *grp = priv->mpcg;
++	int rc;
++	unsigned long saveflags = 0;	/* avoids compiler warning */
++
++	fsm_deltimer(&ch->timer);
++	ctcm_pr_debug("%s cp:%i enter:  %s()\n",
++		       dev->name, smp_processor_id(), __FUNCTION__);
++	if (do_debug)
++		ctcm_pr_debug("%s() %s chstate:%i grpstate:%i\n",
++			__FUNCTION__, ch->id,
++			fsm_getstate(fi), fsm_getstate(grp->fsm));
++
++	fsm_newstate(fi, CTC_STATE_RXIDLE);
++	/* XID processing complete */
++
++	switch (fsm_getstate(grp->fsm)) {
++	case MPCG_STATE_FLOWC:
++	case MPCG_STATE_READY:
++		if (ctcm_checkalloc_buffer(ch))
++				goto done;
++		ch->trans_skb->data = ch->trans_skb_data;
++		skb_reset_tail_pointer(ch->trans_skb);
++		ch->trans_skb->len = 0;
++		ch->ccw[1].count = ch->max_bufsize;
++		if (do_debug_ccw)
++			ctcmpc_dumpit((char *)&ch->ccw[0],
++						sizeof(struct ccw1) * 3);
++		if (event == CTC_EVENT_START)
++			/* see remark about conditional locking */
++			spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++						(unsigned long)ch, 0xff, 0);
++		if (event == CTC_EVENT_START)
++			spin_unlock_irqrestore(
++					get_ccwdev_lock(ch->cdev), saveflags);
++		if (rc != 0) {
++			fsm_newstate(fi, CTC_STATE_RXINIT);
++			ctcm_ccw_check_rc(ch, rc, "initial RX");
++				goto done;
++		}
++		break;
++	default:
++		break;
++	}
++
++	fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
++done:
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit: %s  %s()\n",
++					dev->name, __FUNCTION__);
++	return;
++}
++
++/*
++ * ctcmpc channel FSM action
++ * called from several points in ctcmpc_ch_fsm
++ * ctcmpc only
++ */
++static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg)
++{
++	struct channel	  *ch     = arg;
++	struct net_device *dev    = ch->netdev;
++	struct ctcm_priv  *priv   = dev->priv;
++	struct mpc_group  *grp = priv->mpcg;
++
++	if (do_debug) {
++		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s"
++				"GrpState:%s ChState:%s\n",
++				__FUNCTION__, smp_processor_id(), ch, ch->id,
++		fsm_getstate_str(grp->fsm),
++		fsm_getstate_str(ch->fsm));
++	}
++
++	switch (fsm_getstate(grp->fsm)) {
++	case MPCG_STATE_XID2INITW:
++		/* ok..start yside xid exchanges */
++		if (!ch->in_mpcgroup)
++			break;
++		if (fsm_getstate(ch->fsm) ==  CH_XID0_PENDING) {
++			fsm_deltimer(&grp->timer);
++			fsm_addtimer(&grp->timer,
++				MPC_XID_TIMEOUT_VALUE,
++				MPCG_EVENT_TIMER, dev);
++			fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
++
++		} else if (fsm_getstate(ch->fsm) < CH_XID7_PENDING1)
++			/* attn rcvd before xid0 processed via bh */
++			fsm_newstate(ch->fsm, CH_XID7_PENDING1);
++		break;
++	case MPCG_STATE_XID2INITX:
++	case MPCG_STATE_XID0IOWAIT:
++	case MPCG_STATE_XID0IOWAIX:
++		/* attn rcvd before xid0 processed on ch
++		but mid-xid0 processing for group    */
++		if (fsm_getstate(ch->fsm) < CH_XID7_PENDING1)
++			fsm_newstate(ch->fsm, CH_XID7_PENDING1);
++		break;
++	case MPCG_STATE_XID7INITW:
++	case MPCG_STATE_XID7INITX:
++	case MPCG_STATE_XID7INITI:
++	case MPCG_STATE_XID7INITZ:
++		switch (fsm_getstate(ch->fsm)) {
++		case CH_XID7_PENDING:
++			fsm_newstate(ch->fsm, CH_XID7_PENDING1);
++			break;
++		case CH_XID7_PENDING2:
++			fsm_newstate(ch->fsm, CH_XID7_PENDING3);
++			break;
++		}
++		fsm_event(grp->fsm, MPCG_EVENT_XID7DONE, dev);
++		break;
++	}
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit : %s(): cp=%i ch=0x%p id=%s\n",
++			__FUNCTION__, smp_processor_id(), ch, ch->id);
++	return;
++
++}
++
++/*
++ * ctcmpc channel FSM action
++ * called from one point in ctcmpc_ch_fsm
++ * ctcmpc only
++ */
++static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
++{
++	struct channel	  *ch     = arg;
++	struct net_device *dev    = ch->netdev;
++	struct ctcm_priv  *priv   = dev->priv;
++	struct mpc_group  *grp    = priv->mpcg;
++
++	ctcm_pr_debug("ctcmpc enter: %s  %s() %s  \nGrpState:%s ChState:%s\n",
++		       dev->name,
++		       __FUNCTION__, ch->id,
++		       fsm_getstate_str(grp->fsm),
++		       fsm_getstate_str(ch->fsm));
++
++	fsm_deltimer(&ch->timer);
++
++	switch (fsm_getstate(grp->fsm)) {
++	case MPCG_STATE_XID0IOWAIT:
++		/* vtam wants to be primary.start yside xid exchanges*/
++		/* only receive one attn-busy at a time so must not  */
++		/* change state each time			     */
++		grp->changed_side = 1;
++		fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
++		break;
++	case MPCG_STATE_XID2INITW:
++		if (grp->changed_side == 1) {
++			grp->changed_side = 2;
++			break;
++		}
++		/* process began via call to establish_conn	 */
++		/* so must report failure instead of reverting	 */
++		/* back to ready-for-xid passive state		 */
++		if (grp->estconnfunc)
++				goto done;
++		/* this attnbusy is NOT the result of xside xid  */
++		/* collisions so yside must have been triggered  */
++		/* by an ATTN that was not intended to start XID */
++		/* processing. Revert back to ready-for-xid and  */
++		/* wait for ATTN interrupt to signal xid start	 */
++		if (fsm_getstate(ch->fsm) == CH_XID0_INPROGRESS) {
++			fsm_newstate(ch->fsm, CH_XID0_PENDING) ;
++			fsm_deltimer(&grp->timer);
++				goto done;
++		}
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++				goto done;
++	case MPCG_STATE_XID2INITX:
++		/* XID2 was received before ATTN Busy for second
++		   channel.Send yside xid for second channel.
++		*/
++		if (grp->changed_side == 1) {
++			grp->changed_side = 2;
++			break;
++		}
++	case MPCG_STATE_XID0IOWAIX:
++	case MPCG_STATE_XID7INITW:
++	case MPCG_STATE_XID7INITX:
++	case MPCG_STATE_XID7INITI:
++	case MPCG_STATE_XID7INITZ:
++	default:
++		/* multiple attn-busy indicates too out-of-sync      */
++		/* and they are certainly not being received as part */
++		/* of valid mpc group negotiations..		     */
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++				goto done;
++	}
++
++	if (grp->changed_side == 1) {
++		fsm_deltimer(&grp->timer);
++		fsm_addtimer(&grp->timer, MPC_XID_TIMEOUT_VALUE,
++			     MPCG_EVENT_TIMER, dev);
++	}
++	if (ch->in_mpcgroup)
++		fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
++	else
++		printk(KERN_WARNING "ctcmpc: %s() Not all channels have"
++			" been added to group\n", __FUNCTION__);
++
++done:
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit : %s()%s ch=0x%p id=%s\n",
++				__FUNCTION__, dev->name, ch, ch->id);
++
++	return;
++
++}
++
++/*
++ * ctcmpc channel FSM action
++ * called from several points in ctcmpc_ch_fsm
++ * ctcmpc only
++ */
++static void ctcmpc_chx_resend(fsm_instance *fsm, int event, void *arg)
++{
++	struct channel	   *ch	   = arg;
++	struct net_device  *dev    = ch->netdev;
++	struct ctcm_priv   *priv   = dev->priv;
++	struct mpc_group   *grp    = priv->mpcg;
++
++	ctcm_pr_debug("ctcmpc enter: %s  %s() %s  \nGrpState:%s ChState:%s\n",
++		       dev->name, __FUNCTION__, ch->id,
++		       fsm_getstate_str(grp->fsm),
++		       fsm_getstate_str(ch->fsm));
++
++	fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
++
++	return;
++}
++
++/*
++ * ctcmpc channel FSM action
++ * called from several points in ctcmpc_ch_fsm
++ * ctcmpc only
++ */
++static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
++{
++	struct channel *ach = arg;
++	struct net_device *dev = ach->netdev;
++	struct ctcm_priv *priv = dev->priv;
++	struct mpc_group *grp = priv->mpcg;
++	struct channel *wch = priv->channel[WRITE];
++	struct channel *rch = priv->channel[READ];
++	struct sk_buff *skb;
++	struct th_sweep *header;
++	int rc = 0;
++	unsigned long saveflags = 0;
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++			__FUNCTION__, smp_processor_id(), ach, ach->id);
++
++	if (grp->in_sweep == 0)
++				goto done;
++
++	if (do_debug_data) {
++		ctcm_pr_debug("ctcmpc: %s() 1: ToVTAM_th_seq= %08x\n" ,
++			       __FUNCTION__, wch->th_seq_num);
++		ctcm_pr_debug("ctcmpc: %s() 1: FromVTAM_th_seq= %08x\n" ,
++				__FUNCTION__, rch->th_seq_num);
++	}
++
++	if (fsm_getstate(wch->fsm) != CTC_STATE_TXIDLE) {
++		/* give the previous IO time to complete */
++		fsm_addtimer(&wch->sweep_timer,
++			200, CTC_EVENT_RSWEEP_TIMER, wch);
++				goto done;
++	}
++
++	skb = skb_dequeue(&wch->sweep_queue);
++	if (!skb)
++				goto done;
++
++	if (set_normalized_cda(&wch->ccw[4], skb->data)) {
++		grp->in_sweep = 0;
++		ctcm_clear_busy_do(dev);
++		dev_kfree_skb_any(skb);
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++				goto done;
++	} else {
++		atomic_inc(&skb->users);
++		skb_queue_tail(&wch->io_queue, skb);
++	}
++
++	/* send out the sweep */
++	wch->ccw[4].count = skb->len;
++
++	header = (struct th_sweep *)skb->data;
++	switch (header->th.th_ch_flag) {
++	case TH_SWEEP_REQ:
++		grp->sweep_req_pend_num--;
++		break;
++	case TH_SWEEP_RESP:
++		grp->sweep_rsp_pend_num--;
++		break;
++	}
++
++	header->sw.th_last_seq = wch->th_seq_num;
++
++	if (do_debug_ccw)
++		ctcmpc_dumpit((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);
++
++	ctcm_pr_debug("ctcmpc: %s() sweep packet\n", __FUNCTION__);
++	ctcmpc_dumpit((char *)header, TH_SWEEP_LENGTH);
++
++	fsm_addtimer(&wch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, wch);
++	fsm_newstate(wch->fsm, CTC_STATE_TX);
++
++	spin_lock_irqsave(get_ccwdev_lock(wch->cdev), saveflags);
++	wch->prof.send_stamp = current_kernel_time(); /* xtime */
++	rc = ccw_device_start(wch->cdev, &wch->ccw[3],
++					(unsigned long) wch, 0xff, 0);
++	spin_unlock_irqrestore(get_ccwdev_lock(wch->cdev), saveflags);
++
++	if ((grp->sweep_req_pend_num == 0) &&
++	   (grp->sweep_rsp_pend_num == 0)) {
++		grp->in_sweep = 0;
++		rch->th_seq_num = 0x00;
++		wch->th_seq_num = 0x00;
++		ctcm_clear_busy_do(dev);
++	}
++
++	if (do_debug_data) {
++		ctcm_pr_debug("ctcmpc: %s()2: ToVTAM_th_seq= %08x\n" ,
++			       __FUNCTION__, wch->th_seq_num);
++		ctcm_pr_debug("ctcmpc: %s()2: FromVTAM_th_seq= %08x\n" ,
++			       __FUNCTION__, rch->th_seq_num);
++	}
++
++	if (rc != 0)
++		ctcm_ccw_check_rc(wch, rc, "send sweep");
++
++done:
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit:  %s() %s\n", __FUNCTION__, ach->id);
++	return;
++}
++
++
++/*
++ * The ctcmpc statemachine for a channel.
++ */
++
++const fsm_node ctcmpc_ch_fsm[] = {
++	{ CTC_STATE_STOPPED,	CTC_EVENT_STOP,		ctcm_action_nop  },
++	{ CTC_STATE_STOPPED,	CTC_EVENT_START,	ctcm_chx_start  },
++	{ CTC_STATE_STOPPED,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_STOPPED,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
++	{ CTC_STATE_STOPPED,	CTC_EVENT_MC_FAIL,	ctcm_action_nop  },
++
++	{ CTC_STATE_NOTOP,	CTC_EVENT_STOP,		ctcm_chx_stop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_MC_FAIL,	ctcm_action_nop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_MC_GOOD,	ctcm_chx_start  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_UC_RCRESET,	ctcm_chx_stop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_UC_RSRESET,	ctcm_chx_stop  },
++	{ CTC_STATE_NOTOP,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_TIMER,	ctcm_chx_setuperr  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_STARTWAIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_STARTRETRY,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_STARTRETRY,	CTC_EVENT_TIMER,	ctcm_chx_setmode  },
++	{ CTC_STATE_STARTRETRY,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
++	{ CTC_STATE_STARTRETRY,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_STARTRETRY,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_FINSTAT,	ctcmpc_chx_firstio  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_TIMER,	ctcm_chx_setmode  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_SETUPWAIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CTC_STATE_RXINIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rxidle  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_rxiniterr  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_rxiniterr  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_TIMER,	ctcm_chx_rxiniterr  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_ATTNBUSY,	ctcm_chx_rxinitfail  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_firstio  },
++	{ CTC_STATE_RXINIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++
++	{ CH_XID0_PENDING,	CTC_EVENT_FINSTAT,	ctcm_action_nop  },
++	{ CH_XID0_PENDING,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
++	{ CH_XID0_PENDING,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CH_XID0_PENDING,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CH_XID0_PENDING,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CH_XID0_PENDING,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CH_XID0_PENDING,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
++	{ CH_XID0_PENDING,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CH_XID0_PENDING,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CH_XID0_PENDING,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
++
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_ATTNBUSY,	ctcmpc_chx_attnbusy  },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
++	{ CH_XID0_INPROGRESS,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
++
++	{ CH_XID7_PENDING,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
++	{ CH_XID7_PENDING,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CH_XID7_PENDING,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CH_XID7_PENDING,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CH_XID7_PENDING,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
++	{ CH_XID7_PENDING,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
++
++	{ CH_XID7_PENDING1,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
++	{ CH_XID7_PENDING1,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
++
++	{ CH_XID7_PENDING2,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
++	{ CH_XID7_PENDING2,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
++
++	{ CH_XID7_PENDING3,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
++	{ CH_XID7_PENDING3,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
++
++	{ CH_XID7_PENDING4,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_ATTN,		ctcmpc_chx_attn  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_UC_RCRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_UC_RSRESET,	ctcm_chx_setuperr  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_ATTNBUSY,	ctcm_chx_iofatal  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_TIMER,	ctcmpc_chx_resend  },
++	{ CH_XID7_PENDING4,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
++
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_FINSTAT,	ctcmpc_chx_rx  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_RCRESET,	ctcm_chx_rxdisc  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_RSRESET,	ctcm_chx_fail  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_RXIDLE,	CTC_EVENT_UC_ZERO,	ctcmpc_chx_rx  },
++
++	{ CTC_STATE_TXINIT,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_FINSTAT,	ctcm_chx_txidle  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_UC_RCRESET,	ctcm_chx_txiniterr  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_UC_RSRESET,	ctcm_chx_txiniterr  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_TIMER,	ctcm_chx_txiniterr  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_TXINIT,	CTC_EVENT_RSWEEP_TIMER,	ctcmpc_chx_send_sweep },
++
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_FINSTAT,	ctcmpc_chx_firstio  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_UC_RCRESET,	ctcm_chx_fail  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_UC_RSRESET,	ctcm_chx_fail  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_TXIDLE,	CTC_EVENT_RSWEEP_TIMER,	ctcmpc_chx_send_sweep },
++
++	{ CTC_STATE_TERM,	CTC_EVENT_STOP,		ctcm_action_nop  },
++	{ CTC_STATE_TERM,	CTC_EVENT_START,	ctcm_chx_restart  },
++	{ CTC_STATE_TERM,	CTC_EVENT_FINSTAT,	ctcm_chx_stopped  },
++	{ CTC_STATE_TERM,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
++	{ CTC_STATE_TERM,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
++	{ CTC_STATE_TERM,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_TERM,	CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
++	{ CTC_STATE_TERM,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++
++	{ CTC_STATE_DTERM,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_START,	ctcm_chx_restart  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_FINSTAT,	ctcm_chx_setmode  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_UC_RCRESET,	ctcm_action_nop  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_UC_RSRESET,	ctcm_action_nop  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_DTERM,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++
++	{ CTC_STATE_TX,		CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TX,		CTC_EVENT_START,	ctcm_action_nop  },
++	{ CTC_STATE_TX,		CTC_EVENT_FINSTAT,	ctcmpc_chx_txdone  },
++	{ CTC_STATE_TX,		CTC_EVENT_UC_RCRESET,	ctcm_chx_fail  },
++	{ CTC_STATE_TX,		CTC_EVENT_UC_RSRESET,	ctcm_chx_fail  },
++	{ CTC_STATE_TX,		CTC_EVENT_TIMER,	ctcm_chx_txretry  },
++	{ CTC_STATE_TX,		CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_TX,		CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_TX,		CTC_EVENT_RSWEEP_TIMER,	ctcmpc_chx_send_sweep },
++	{ CTC_STATE_TX,		CTC_EVENT_IO_EBUSY,	ctcm_chx_fail  },
++
++	{ CTC_STATE_RXERR,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TXERR,	CTC_EVENT_STOP,		ctcm_chx_haltio  },
++	{ CTC_STATE_TXERR,	CTC_EVENT_IO_ENODEV,	ctcm_chx_iofatal  },
++	{ CTC_STATE_TXERR,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++	{ CTC_STATE_RXERR,	CTC_EVENT_MC_FAIL,	ctcm_chx_fail  },
++};
++
++int mpc_ch_fsm_len = ARRAY_SIZE(ctcmpc_ch_fsm);
++
++/*
++ * Actions for interface - statemachine.
++ */
++
++/**
++ * Startup channels by sending CTC_EVENT_START to each channel.
++ *
++ * fi		An instance of an interface statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from struct net_device * upon call.
++ */
++static void dev_action_start(fsm_instance *fi, int event, void *arg)
++{
++	struct net_device *dev = arg;
++	struct ctcm_priv *priv = dev->priv;
++	int direction;
++
++	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++
++	fsm_deltimer(&priv->restart_timer);
++	fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
++	if (IS_MPC(priv))
++		priv->mpcg->channels_terminating = 0;
++	for (direction = READ; direction <= WRITE; direction++) {
++		struct channel *ch = priv->channel[direction];
++		fsm_event(ch->fsm, CTC_EVENT_START, ch);
++	}
++}
++
++/**
++ * Shutdown channels by sending CTC_EVENT_STOP to each channel.
++ *
++ * fi		An instance of an interface statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from struct net_device * upon call.
++ */
++static void dev_action_stop(fsm_instance *fi, int event, void *arg)
++{
++	int direction;
++	struct net_device *dev = arg;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++
++	fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
++	for (direction = READ; direction <= WRITE; direction++) {
++		struct channel *ch = priv->channel[direction];
++		fsm_event(ch->fsm, CTC_EVENT_STOP, ch);
++		ch->th_seq_num = 0x00;
++	if (do_debug)
++		ctcm_pr_debug("ctcm: %s() CH_th_seq= %08x\n",
++				__FUNCTION__, ch->th_seq_num);
++	}
++	if (IS_MPC(priv))
++		fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);
++}
++
++static void dev_action_restart(fsm_instance *fi, int event, void *arg)
++{
++	int restart_timer;
++	struct net_device *dev = arg;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCMY_DBF_DEV_NAME(TRACE, dev, "");
++
++	if (IS_MPC(priv)) {
++		ctcm_pr_info("ctcm: %s Restarting Device and "
++		       "MPC Group in 5 seconds\n",
++		       dev->name);
++		restart_timer = CTCM_TIME_1_SEC;
++	} else {
++		ctcm_pr_info("%s: Restarting\n", dev->name);
++		restart_timer = CTCM_TIME_5_SEC;
++	}
++
++	dev_action_stop(fi, event, arg);
++	fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
++	if (IS_MPC(priv))
++		fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);
++
++	/* going back into start sequence too quickly can	  */
++	/* result in the other side becoming unreachable   due	  */
++	/* to sense reported when IO is aborted			  */
++	fsm_addtimer(&priv->restart_timer, restart_timer,
++			DEV_EVENT_START, dev);
++}
++
++/**
++ * Called from channel statemachine
++ * when a channel is up and running.
++ *
++ * fi		An instance of an interface statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from struct net_device * upon call.
++ */
++static void dev_action_chup(fsm_instance *fi, int event, void *arg)
++{
++	struct net_device *dev = arg;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++
++	switch (fsm_getstate(fi)) {
++	case DEV_STATE_STARTWAIT_RXTX:
++		if (event == DEV_EVENT_RXUP)
++			fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
++		else
++			fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
++		break;
++	case DEV_STATE_STARTWAIT_RX:
++		if (event == DEV_EVENT_RXUP) {
++			fsm_newstate(fi, DEV_STATE_RUNNING);
++			ctcm_pr_info("%s: connected with remote side\n",
++				    dev->name);
++			ctcm_clear_busy(dev);
++		}
++		break;
++	case DEV_STATE_STARTWAIT_TX:
++		if (event == DEV_EVENT_TXUP) {
++			fsm_newstate(fi, DEV_STATE_RUNNING);
++			ctcm_pr_info("%s: connected with remote side\n",
++				    dev->name);
++			ctcm_clear_busy(dev);
++		}
++		break;
++	case DEV_STATE_STOPWAIT_TX:
++		if (event == DEV_EVENT_RXUP)
++			fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
++		break;
++	case DEV_STATE_STOPWAIT_RX:
++		if (event == DEV_EVENT_TXUP)
++			fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
++		break;
++	}
++
++	if (IS_MPC(priv)) {
++		if (event == DEV_EVENT_RXUP)
++			mpc_channel_action(priv->channel[READ],
++				READ, MPC_CHANNEL_ADD);
++		else
++			mpc_channel_action(priv->channel[WRITE],
++				WRITE, MPC_CHANNEL_ADD);
++	}
++}
++
++/**
++ * Called from device statemachine
++ * when a channel has been shutdown.
++ *
++ * fi		An instance of an interface statemachine.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from struct net_device * upon call.
++ */
++static void dev_action_chdown(fsm_instance *fi, int event, void *arg)
++{
++
++	struct net_device *dev = arg;
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++
++	switch (fsm_getstate(fi)) {
++	case DEV_STATE_RUNNING:
++		if (event == DEV_EVENT_TXDOWN)
++			fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
++		else
++			fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
++		break;
++	case DEV_STATE_STARTWAIT_RX:
++		if (event == DEV_EVENT_TXDOWN)
++			fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
++		break;
++	case DEV_STATE_STARTWAIT_TX:
++		if (event == DEV_EVENT_RXDOWN)
++			fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
++		break;
++	case DEV_STATE_STOPWAIT_RXTX:
++		if (event == DEV_EVENT_TXDOWN)
++			fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);
++		else
++			fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);
++		break;
++	case DEV_STATE_STOPWAIT_RX:
++		if (event == DEV_EVENT_RXDOWN)
++			fsm_newstate(fi, DEV_STATE_STOPPED);
++		break;
++	case DEV_STATE_STOPWAIT_TX:
++		if (event == DEV_EVENT_TXDOWN)
++			fsm_newstate(fi, DEV_STATE_STOPPED);
++		break;
++	}
++	if (IS_MPC(priv)) {
++		if (event == DEV_EVENT_RXDOWN)
++			mpc_channel_action(priv->channel[READ],
++				READ, MPC_CHANNEL_REMOVE);
++		else
++			mpc_channel_action(priv->channel[WRITE],
++				WRITE, MPC_CHANNEL_REMOVE);
++	}
++}
++
++const fsm_node dev_fsm[] = {
++	{ DEV_STATE_STOPPED,        DEV_EVENT_START,   dev_action_start   },
++	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_START,   dev_action_start   },
++	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_TXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RESTART, dev_action_restart },
++	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_START,   dev_action_start   },
++	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXUP,    dev_action_chup    },
++	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_TXUP,    dev_action_chup    },
++	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RESTART, dev_action_restart },
++	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_START,   dev_action_start   },
++	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RXUP,    dev_action_chup    },
++	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXUP,    dev_action_chup    },
++	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RESTART, dev_action_restart },
++	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP,    dev_action_stop    },
++	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP,    dev_action_chup    },
++	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP,    dev_action_chup    },
++	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
++	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_STOP,    dev_action_stop    },
++	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXUP,    dev_action_chup    },
++	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_TXUP,    dev_action_chup    },
++	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RESTART, dev_action_restart },
++	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_STOP,    dev_action_stop    },
++	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RXUP,    dev_action_chup    },
++	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXUP,    dev_action_chup    },
++	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RESTART, dev_action_restart },
++	{ DEV_STATE_RUNNING,        DEV_EVENT_STOP,    dev_action_stop    },
++	{ DEV_STATE_RUNNING,        DEV_EVENT_RXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_RUNNING,        DEV_EVENT_TXDOWN,  dev_action_chdown  },
++	{ DEV_STATE_RUNNING,        DEV_EVENT_TXUP,    ctcm_action_nop    },
++	{ DEV_STATE_RUNNING,        DEV_EVENT_RXUP,    ctcm_action_nop    },
++	{ DEV_STATE_RUNNING,        DEV_EVENT_RESTART, dev_action_restart },
++};
++
++int dev_fsm_len = ARRAY_SIZE(dev_fsm);
++
++/* --- This is the END my friend --- */
++
+diff --git a/drivers/s390/net/ctcm_fsms.h b/drivers/s390/net/ctcm_fsms.h
+new file mode 100644
+index 0000000..2326aba
+--- /dev/null
++++ b/drivers/s390/net/ctcm_fsms.h
+@@ -0,0 +1,359 @@
++/*
++ * drivers/s390/net/ctcm_fsms.h
++ *
++ * Copyright IBM Corp. 2001, 2007
++ * Authors: 	Fritz Elfert (felfert at millenux.com)
++ * 		Peter Tiedemann (ptiedem at de.ibm.com)
++ * 	MPC additions :
++ *		Belinda Thompson (belindat at us.ibm.com)
++ *		Andy Richter (richtera at us.ibm.com)
++ */
++#ifndef _CTCM_FSMS_H_
++#define _CTCM_FSMS_H_
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/bitops.h>
++
++#include <linux/signal.h>
++#include <linux/string.h>
++
++#include <linux/ip.h>
++#include <linux/if_arp.h>
++#include <linux/tcp.h>
++#include <linux/skbuff.h>
++#include <linux/ctype.h>
++#include <net/dst.h>
++
++#include <linux/io.h>
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++#include <linux/uaccess.h>
++
++#include <asm/idals.h>
++
++#include "fsm.h"
++#include "cu3088.h"
++#include "ctcm_main.h"
++
++/*
++ * Definitions for the channel statemachine(s) for ctc and ctcmpc
++ *
++ * To allow better kerntyping, prefix-less definitions for channel states
++ * and channel events have been replaced :
++ * ch_event... -> ctc_ch_event...
++ * CH_EVENT... -> CTC_EVENT...
++ * ch_state... -> ctc_ch_state...
++ * CH_STATE... -> CTC_STATE...
++ */
++/*
++ * Events of the channel statemachine(s) for ctc and ctcmpc
++ */
++enum ctc_ch_events {
++	/*
++	 * Events, representing return code of
++	 * I/O operations (ccw_device_start, ccw_device_halt et al.)
++	 */
++	CTC_EVENT_IO_SUCCESS,
++	CTC_EVENT_IO_EBUSY,
++	CTC_EVENT_IO_ENODEV,
++	CTC_EVENT_IO_UNKNOWN,
++
++	CTC_EVENT_ATTNBUSY,
++	CTC_EVENT_ATTN,
++	CTC_EVENT_BUSY,
++	/*
++	 * Events, representing unit-check
++	 */
++	CTC_EVENT_UC_RCRESET,
++	CTC_EVENT_UC_RSRESET,
++	CTC_EVENT_UC_TXTIMEOUT,
++	CTC_EVENT_UC_TXPARITY,
++	CTC_EVENT_UC_HWFAIL,
++	CTC_EVENT_UC_RXPARITY,
++	CTC_EVENT_UC_ZERO,
++	CTC_EVENT_UC_UNKNOWN,
++	/*
++	 * Events, representing subchannel-check
++	 */
++	CTC_EVENT_SC_UNKNOWN,
++	/*
++	 * Events, representing machine checks
++	 */
++	CTC_EVENT_MC_FAIL,
++	CTC_EVENT_MC_GOOD,
++	/*
++	 * Event, representing normal IRQ
++	 */
++	CTC_EVENT_IRQ,
++	CTC_EVENT_FINSTAT,
++	/*
++	 * Event, representing timer expiry.
++	 */
++	CTC_EVENT_TIMER,
++	/*
++	 * Events, representing commands from upper levels.
++	 */
++	CTC_EVENT_START,
++	CTC_EVENT_STOP,
++	CTC_NR_EVENTS,
++	/*
++	 * additional MPC events
++	 */
++	CTC_EVENT_SEND_XID = CTC_NR_EVENTS,
++	CTC_EVENT_RSWEEP_TIMER,
++	/*
++	 * MUST be always the last element!!
++	 */
++	CTC_MPC_NR_EVENTS,
++};
++
++/*
++ * States of the channel statemachine(s) for ctc and ctcmpc.
++ */
++enum ctc_ch_states {
++	/*
++	 * Channel not assigned to any device,
++	 * initial state, direction invalid
++	 */
++	CTC_STATE_IDLE,
++	/*
++	 * Channel assigned but not operating
++	 */
++	CTC_STATE_STOPPED,
++	CTC_STATE_STARTWAIT,
++	CTC_STATE_STARTRETRY,
++	CTC_STATE_SETUPWAIT,
++	CTC_STATE_RXINIT,
++	CTC_STATE_TXINIT,
++	CTC_STATE_RX,
++	CTC_STATE_TX,
++	CTC_STATE_RXIDLE,
++	CTC_STATE_TXIDLE,
++	CTC_STATE_RXERR,
++	CTC_STATE_TXERR,
++	CTC_STATE_TERM,
++	CTC_STATE_DTERM,
++	CTC_STATE_NOTOP,
++	CTC_NR_STATES,     /* MUST be the last element of non-expanded states */
++	/*
++	 * additional MPC states
++	 */
++	CH_XID0_PENDING = CTC_NR_STATES,
++	CH_XID0_INPROGRESS,
++	CH_XID7_PENDING,
++	CH_XID7_PENDING1,
++	CH_XID7_PENDING2,
++	CH_XID7_PENDING3,
++	CH_XID7_PENDING4,
++	CTC_MPC_NR_STATES, /* MUST be the last element of expanded mpc states */
++};
++
++extern const char *ctc_ch_event_names[];
++
++extern const char *ctc_ch_state_names[];
++
++void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg);
++void ctcm_purge_skb_queue(struct sk_buff_head *q);
++void fsm_action_nop(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- non-static actions for ctcm channel statemachine -----
++ *
++ */
++void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- FSM (state/event/action) of the ctcm channel statemachine -----
++ */
++extern const fsm_node ch_fsm[];
++extern int ch_fsm_len;
++
++
++/*
++ * ----- non-static actions for ctcmpc channel statemachine ----
++ *
++ */
++/* shared :
++void ctcm_chx_txidle(fsm_instance * fi, int event, void *arg);
++ */
++void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- FSM (state/event/action) of the ctcmpc channel statemachine -----
++ */
++extern const fsm_node ctcmpc_ch_fsm[];
++extern int mpc_ch_fsm_len;
++
++/*
++ * Definitions for the device interface statemachine for ctc and mpc
++ */
++
++/*
++ * States of the device interface statemachine.
++ */
++enum dev_states {
++	DEV_STATE_STOPPED,
++	DEV_STATE_STARTWAIT_RXTX,
++	DEV_STATE_STARTWAIT_RX,
++	DEV_STATE_STARTWAIT_TX,
++	DEV_STATE_STOPWAIT_RXTX,
++	DEV_STATE_STOPWAIT_RX,
++	DEV_STATE_STOPWAIT_TX,
++	DEV_STATE_RUNNING,
++	/*
++	 * MUST be always the last element!!
++	 */
++	CTCM_NR_DEV_STATES
++};
++
++extern const char *dev_state_names[];
++
++/*
++ * Events of the device interface statemachine.
++ * ctcm and ctcmpc
++ */
++enum dev_events {
++	DEV_EVENT_START,
++	DEV_EVENT_STOP,
++	DEV_EVENT_RXUP,
++	DEV_EVENT_TXUP,
++	DEV_EVENT_RXDOWN,
++	DEV_EVENT_TXDOWN,
++	DEV_EVENT_RESTART,
++	/*
++	 * MUST be always the last element!!
++	 */
++	CTCM_NR_DEV_EVENTS
++};
++
++extern const char *dev_event_names[];
++
++/*
++ * Actions for the device interface statemachine.
++ * ctc and ctcmpc
++ */
++/*
++static void dev_action_start(fsm_instance * fi, int event, void *arg);
++static void dev_action_stop(fsm_instance * fi, int event, void *arg);
++static void dev_action_restart(fsm_instance *fi, int event, void *arg);
++static void dev_action_chup(fsm_instance * fi, int event, void *arg);
++static void dev_action_chdown(fsm_instance * fi, int event, void *arg);
++*/
++
++/*
++ * The (state/event/action) fsm table of the device interface statemachine.
++ * ctcm and ctcmpc
++ */
++extern const fsm_node dev_fsm[];
++extern int dev_fsm_len;
++
++
++/*
++ * Definitions for the MPC Group statemachine
++ */
++
++/*
++ * MPC Group Station FSM States
++
++State Name		When In This State
++======================	=======================================
++MPCG_STATE_RESET	Initial State When Driver Loaded
++			We receive and send NOTHING
++
++MPCG_STATE_INOP         INOP Received.
++			Group level non-recoverable error
++
++MPCG_STATE_READY	XID exchanges for at least 1 write and
++			1 read channel have completed.
++			Group is ready for data transfer.
++
++States from ctc_mpc_alloc_channel
++==============================================================
++MPCG_STATE_XID2INITW	Awaiting XID2(0) Initiation
++			      ATTN from other side will start
++			      XID negotiations.
++			      Y-side protocol only.
++
++MPCG_STATE_XID2INITX	XID2(0) negotiations are in progress.
++			      At least 1, but not all, XID2(0)'s
++			      have been received from partner.
++
++MPCG_STATE_XID7INITW	XID2(0) complete
++			      No XID2(7)'s have yet been received.
++			      XID2(7) negotiations pending.
++
++MPCG_STATE_XID7INITX	XID2(7) negotiations in progress.
++			      At least 1, but not all, XID2(7)'s
++			      have been received from partner.
++
++MPCG_STATE_XID7INITF	XID2(7) negotiations complete.
++			      Transitioning to READY.
++
++MPCG_STATE_READY	      Ready for Data Transfer.
++
++
++States from ctc_mpc_establish_connectivity call
++==============================================================
++MPCG_STATE_XID0IOWAIT	Initiating XID2(0) negotiations.
++			      X-side protocol only.
++			      ATTN-BUSY from other side will convert
++			      this to Y-side protocol and the
++			      ctc_mpc_alloc_channel flow will begin.
++
++MPCG_STATE_XID0IOWAIX	XID2(0) negotiations are in progress.
++			      At least 1, but not all, XID2(0)'s
++			      have been received from partner.
++
++MPCG_STATE_XID7INITI	XID2(0) complete
++			      No XID2(7)'s have yet been received.
++			      XID2(7) negotiations pending.
++
++MPCG_STATE_XID7INITZ	XID2(7) negotiations in progress.
++			      At least 1, but not all, XID2(7)'s
++			      have been received from partner.
++
++MPCG_STATE_XID7INITF	XID2(7) negotiations complete.
++			      Transitioning to READY.
++
++MPCG_STATE_READY	      Ready for Data Transfer.
++
++*/
++
++enum mpcg_events {
++	MPCG_EVENT_INOP,
++	MPCG_EVENT_DISCONC,
++	MPCG_EVENT_XID0DO,
++	MPCG_EVENT_XID2,
++	MPCG_EVENT_XID2DONE,
++	MPCG_EVENT_XID7DONE,
++	MPCG_EVENT_TIMER,
++	MPCG_EVENT_DOIO,
++	MPCG_NR_EVENTS,
++};
++
++enum mpcg_states {
++	MPCG_STATE_RESET,
++	MPCG_STATE_INOP,
++	MPCG_STATE_XID2INITW,
++	MPCG_STATE_XID2INITX,
++	MPCG_STATE_XID7INITW,
++	MPCG_STATE_XID7INITX,
++	MPCG_STATE_XID0IOWAIT,
++	MPCG_STATE_XID0IOWAIX,
++	MPCG_STATE_XID7INITI,
++	MPCG_STATE_XID7INITZ,
++	MPCG_STATE_XID7INITF,
++	MPCG_STATE_FLOWC,
++	MPCG_STATE_READY,
++	MPCG_NR_STATES,
++};
++
++#endif
++/* --- This is the END my friend --- */
+diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
+new file mode 100644
+index 0000000..d52843d
+--- /dev/null
++++ b/drivers/s390/net/ctcm_main.c
+@@ -0,0 +1,1772 @@
++/*
++ * drivers/s390/net/ctcm_main.c
++ *
++ * Copyright IBM Corp. 2001, 2007
++ * Author(s):
++ *	Original CTC driver(s):
++ *		Fritz Elfert (felfert at millenux.com)
++ *		Dieter Wellerdiek (wel at de.ibm.com)
++ *		Martin Schwidefsky (schwidefsky at de.ibm.com)
++ *		Denis Joseph Barrow (barrow_dj at yahoo.com)
++ *		Jochen Roehrig (roehrig at de.ibm.com)
++ *		Cornelia Huck <cornelia.huck at de.ibm.com>
++ *	MPC additions:
++ *		Belinda Thompson (belindat at us.ibm.com)
++ *		Andy Richter (richtera at us.ibm.com)
++ *	Revived by:
++ *		Peter Tiedemann (ptiedem at de.ibm.com)
++ */
++
++#undef DEBUG
++#undef DEBUGDATA
++#undef DEBUGCCW
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/bitops.h>
++
++#include <linux/signal.h>
++#include <linux/string.h>
++
++#include <linux/ip.h>
++#include <linux/if_arp.h>
++#include <linux/tcp.h>
++#include <linux/skbuff.h>
++#include <linux/ctype.h>
++#include <net/dst.h>
++
++#include <linux/io.h>
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++#include <linux/uaccess.h>
++
++#include <asm/idals.h>
++
++#include "cu3088.h"
++#include "ctcm_fsms.h"
++#include "ctcm_main.h"
++
++/* Some common global variables */
++
++/*
++ * Linked list of all detected channels.
++ */
++struct channel *channels;
++
++/**
++ * Unpack a just received skb and hand it over to
++ * upper layers.
++ *
++ *  ch		The channel where this skb has been received.
++ *  pskb	The received skb.
++ */
++void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
++{
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++	__u16 len = *((__u16 *) pskb->data);
++
++	skb_put(pskb, 2 + LL_HEADER_LENGTH);
++	skb_pull(pskb, 2);
++	pskb->dev = dev;
++	pskb->ip_summed = CHECKSUM_UNNECESSARY;
++	while (len > 0) {
++		struct sk_buff *skb;
++		int skblen;
++		struct ll_header *header = (struct ll_header *)pskb->data;
++
++		skb_pull(pskb, LL_HEADER_LENGTH);
++		if ((ch->protocol == CTCM_PROTO_S390) &&
++		    (header->type != ETH_P_IP)) {
++
++			if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
++				/*
++				 * Check packet type only if we stick strictly
++				 * to S/390's protocol of OS390. This only
++				 * supports IP. Otherwise allow any packet
++				 * type.
++				 */
++				ctcm_pr_warn("%s Illegal packet type 0x%04x "
++						"received, dropping\n",
++						dev->name, header->type);
++				ch->logflags |= LOG_FLAG_ILLEGALPKT;
++			}
++
++			priv->stats.rx_dropped++;
++			priv->stats.rx_frame_errors++;
++			return;
++		}
++		pskb->protocol = ntohs(header->type);
++		if (header->length <= LL_HEADER_LENGTH) {
++			if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
++				ctcm_pr_warn(
++					"%s Illegal packet size %d "
++					"received (MTU=%d blocklen=%d), "
++					"dropping\n", dev->name, header->length,
++					dev->mtu, len);
++				ch->logflags |= LOG_FLAG_ILLEGALSIZE;
++			}
++
++			priv->stats.rx_dropped++;
++			priv->stats.rx_length_errors++;
++			return;
++		}
++		header->length -= LL_HEADER_LENGTH;
++		len -= LL_HEADER_LENGTH;
++		if ((header->length > skb_tailroom(pskb)) ||
++			(header->length > len)) {
++			if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
++				ctcm_pr_warn(
++					"%s Illegal packet size %d (beyond the"
++					" end of received data), dropping\n",
++					dev->name, header->length);
++				ch->logflags |= LOG_FLAG_OVERRUN;
++			}
++
++			priv->stats.rx_dropped++;
++			priv->stats.rx_length_errors++;
++			return;
++		}
++		skb_put(pskb, header->length);
++		skb_reset_mac_header(pskb);
++		len -= header->length;
++		skb = dev_alloc_skb(pskb->len);
++		if (!skb) {
++			if (!(ch->logflags & LOG_FLAG_NOMEM)) {
++				ctcm_pr_warn(
++					"%s Out of memory in ctcm_unpack_skb\n",
++					dev->name);
++				ch->logflags |= LOG_FLAG_NOMEM;
++			}
++			priv->stats.rx_dropped++;
++			return;
++		}
++		skb_copy_from_linear_data(pskb, skb_put(skb, pskb->len),
++					  pskb->len);
++		skb_reset_mac_header(skb);
++		skb->dev = pskb->dev;
++		skb->protocol = pskb->protocol;
++		pskb->ip_summed = CHECKSUM_UNNECESSARY;
++		skblen = skb->len;
++		/*
++		 * reset logflags
++		 */
++		ch->logflags = 0;
++		priv->stats.rx_packets++;
++		priv->stats.rx_bytes += skblen;
++		netif_rx_ni(skb);
++		dev->last_rx = jiffies;
++		if (len > 0) {
++			skb_pull(pskb, header->length);
++			if (skb_tailroom(pskb) < LL_HEADER_LENGTH) {
++				if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
++					CTCM_DBF_DEV_NAME(TRACE, dev,
++						"Overrun in ctcm_unpack_skb");
++					ch->logflags |= LOG_FLAG_OVERRUN;
++				}
++				return;
++			}
++			skb_put(pskb, LL_HEADER_LENGTH);
++		}
++	}
++}
++
++/**
++ * Release a specific channel in the channel list.
++ *
++ *  ch		Pointer to channel struct to be released.
++ */
++static void channel_free(struct channel *ch)
++{
++	CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
++	ch->flags &= ~CHANNEL_FLAGS_INUSE;
++	fsm_newstate(ch->fsm, CTC_STATE_IDLE);
++}
++
++/**
++ * Remove a specific channel in the channel list.
++ *
++ *  ch		Pointer to channel struct to be released.
++ */
++static void channel_remove(struct channel *ch)
++{
++	struct channel **c = &channels;
++	char chid[CTCM_ID_SIZE+1];
++	int ok = 0;
++
++	if (ch == NULL)
++		return;
++	else
++		strncpy(chid, ch->id, CTCM_ID_SIZE);
++
++	channel_free(ch);
++	while (*c) {
++		if (*c == ch) {
++			*c = ch->next;
++			fsm_deltimer(&ch->timer);
++			if (IS_MPC(ch))
++				fsm_deltimer(&ch->sweep_timer);
++
++			kfree_fsm(ch->fsm);
++			clear_normalized_cda(&ch->ccw[4]);
++			if (ch->trans_skb != NULL) {
++				clear_normalized_cda(&ch->ccw[1]);
++				dev_kfree_skb_any(ch->trans_skb);
++			}
++			if (IS_MPC(ch)) {
++				tasklet_kill(&ch->ch_tasklet);
++				tasklet_kill(&ch->ch_disc_tasklet);
++				kfree(ch->discontact_th);
++			}
++			kfree(ch->ccw);
++			kfree(ch->irb);
++			kfree(ch);
++			ok = 1;
++			break;
++		}
++		c = &((*c)->next);
++	}
++
++	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s) %s", CTCM_FUNTAIL,
++			chid, ok ? "OK" : "failed");
++}
++
++/**
++ * Get a specific channel from the channel list.
++ *
++ *  type	Type of channel we are interested in.
++ *  id		Id of channel we are interested in.
++ *  direction	Direction we want to use this channel for.
++ *
++ * returns Pointer to a channel or NULL if no matching channel available.
++ */
++static struct channel *channel_get(enum channel_types type,
++					char *id, int direction)
++{
++	struct channel *ch = channels;
++
++	if (do_debug) {
++		char buf[64];
++		sprintf(buf, "%s(%d, %s, %d)\n",
++				CTCM_FUNTAIL, type, id, direction);
++		CTCM_DBF_TEXT(TRACE, CTC_DBF_INFO, buf);
++	}
++	while (ch && (strncmp(ch->id, id, CTCM_ID_SIZE) || (ch->type != type)))
++		ch = ch->next;
++	if (!ch) {
++		char buf[64];
++		sprintf(buf, "%s(%d, %s, %d) not found in channel list\n",
++				CTCM_FUNTAIL, type, id, direction);
++		CTCM_DBF_TEXT(ERROR, CTC_DBF_ERROR, buf);
++	} else {
++		if (ch->flags & CHANNEL_FLAGS_INUSE)
++			ch = NULL;
++		else {
++			ch->flags |= CHANNEL_FLAGS_INUSE;
++			ch->flags &= ~CHANNEL_FLAGS_RWMASK;
++			ch->flags |= (direction == WRITE)
++			    ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ;
++			fsm_newstate(ch->fsm, CTC_STATE_STOPPED);
++		}
++	}
++	return ch;
++}
++
++static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
++{
++	if (!IS_ERR(irb))
++		return 0;
++
++	CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN, "irb error %ld on device %s\n",
++			PTR_ERR(irb), cdev->dev.bus_id);
++
++	switch (PTR_ERR(irb)) {
++	case -EIO:
++		ctcm_pr_warn("i/o-error on device %s\n", cdev->dev.bus_id);
++		break;
++	case -ETIMEDOUT:
++		ctcm_pr_warn("timeout on device %s\n", cdev->dev.bus_id);
++		break;
++	default:
++		ctcm_pr_warn("unknown error %ld on device %s\n",
++				PTR_ERR(irb), cdev->dev.bus_id);
++	}
++	return PTR_ERR(irb);
++}
++
++
++/**
++ * Check sense of a unit check.
++ *
++ *  ch		The channel, the sense code belongs to.
++ *  sense	The sense code to inspect.
++ */
++static inline void ccw_unit_check(struct channel *ch, unsigned char sense)
++{
++	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
++	if (sense & SNS0_INTERVENTION_REQ) {
++		if (sense & 0x01) {
++			ctcm_pr_debug("%s: Interface disc. or Sel. reset "
++					"(remote)\n", ch->id);
++			fsm_event(ch->fsm, CTC_EVENT_UC_RCRESET, ch);
++		} else {
++			ctcm_pr_debug("%s: System reset (remote)\n", ch->id);
++			fsm_event(ch->fsm, CTC_EVENT_UC_RSRESET, ch);
++		}
++	} else if (sense & SNS0_EQUIPMENT_CHECK) {
++		if (sense & SNS0_BUS_OUT_CHECK) {
++			ctcm_pr_warn("%s: Hardware malfunction (remote)\n",
++				ch->id);
++			fsm_event(ch->fsm, CTC_EVENT_UC_HWFAIL, ch);
++		} else {
++			ctcm_pr_warn("%s: Read-data parity error (remote)\n",
++				ch->id);
++			fsm_event(ch->fsm, CTC_EVENT_UC_RXPARITY, ch);
++		}
++	} else if (sense & SNS0_BUS_OUT_CHECK) {
++		if (sense & 0x04) {
++			ctcm_pr_warn("%s: Data-streaming timeout)\n", ch->id);
++			fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch);
++		} else {
++			ctcm_pr_warn("%s: Data-transfer parity error\n",
++					ch->id);
++			fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch);
++		}
++	} else if (sense & SNS0_CMD_REJECT) {
++		ctcm_pr_warn("%s: Command reject\n", ch->id);
++	} else if (sense == 0) {
++		ctcm_pr_debug("%s: Unit check ZERO\n", ch->id);
++		fsm_event(ch->fsm, CTC_EVENT_UC_ZERO, ch);
++	} else {
++		ctcm_pr_warn("%s: Unit Check with sense code: %02x\n",
++			    ch->id, sense);
++		fsm_event(ch->fsm, CTC_EVENT_UC_UNKNOWN, ch);
++	}
++}
++
++int ctcm_ch_alloc_buffer(struct channel *ch)
++{
++	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
++
++	clear_normalized_cda(&ch->ccw[1]);
++	ch->trans_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC | GFP_DMA);
++	if (ch->trans_skb == NULL) {
++		ctcm_pr_warn("%s: Couldn't alloc %s trans_skb\n",
++			ch->id,
++			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++		return -ENOMEM;
++	}
++
++	ch->ccw[1].count = ch->max_bufsize;
++	if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
++		dev_kfree_skb(ch->trans_skb);
++		ch->trans_skb = NULL;
++		ctcm_pr_warn("%s: set_normalized_cda for %s "
++			"trans_skb failed, dropping packets\n",
++			ch->id,
++			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++		return -ENOMEM;
++	}
++
++	ch->ccw[1].count = 0;
++	ch->trans_skb_data = ch->trans_skb->data;
++	ch->flags &= ~CHANNEL_FLAGS_BUFSIZE_CHANGED;
++	return 0;
++}
++
++/*
++ * Interface API for upper network layers
++ */
++
++/**
++ * Open an interface.
++ * Called from generic network layer when ifconfig up is run.
++ *
++ *  dev		Pointer to interface struct.
++ *
++ * returns 0 on success, -ERRNO on failure. (Never fails.)
++ */
++int ctcm_open(struct net_device *dev)
++{
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++	if (!IS_MPC(priv))
++		fsm_event(priv->fsm,	DEV_EVENT_START, dev);
++	return 0;
++}
++
++/**
++ * Close an interface.
++ * Called from generic network layer when ifconfig down is run.
++ *
++ *  dev		Pointer to interface struct.
++ *
++ * returns 0 on success, -ERRNO on failure. (Never fails.)
++ */
++int ctcm_close(struct net_device *dev)
++{
++	struct ctcm_priv *priv = dev->priv;
++
++	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++	if (!IS_MPC(priv))
++		fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
++	return 0;
++}
++
++
++/**
++ * Transmit a packet.
++ * This is a helper function for ctcm_tx().
++ *
++ *  ch		Channel to be used for sending.
++ *  skb		Pointer to struct sk_buff of packet to send.
++ *            The linklevel header has already been set up
++ *            by ctcm_tx().
++ *
++ * returns 0 on success, -ERRNO on failure. (Never fails.)
++ */
++static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
++{
++	unsigned long saveflags;
++	struct ll_header header;
++	int rc = 0;
++	__u16 block_len;
++	int ccw_idx;
++	struct sk_buff *nskb;
++	unsigned long hi;
++
++	/* we need to acquire the lock for testing the state
++	 * otherwise we can have an IRQ changing the state to
++	 * TXIDLE after the test but before acquiring the lock.
++	 */
++	spin_lock_irqsave(&ch->collect_lock, saveflags);
++	if (fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) {
++		int l = skb->len + LL_HEADER_LENGTH;
++
++		if (ch->collect_len + l > ch->max_bufsize - 2) {
++			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++			return -EBUSY;
++		} else {
++			atomic_inc(&skb->users);
++			header.length = l;
++			header.type = skb->protocol;
++			header.unused = 0;
++			memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
++			       LL_HEADER_LENGTH);
++			skb_queue_tail(&ch->collect_queue, skb);
++			ch->collect_len += l;
++		}
++		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++				goto done;
++	}
++	spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++	/*
++	 * Protect skb against beeing free'd by upper
++	 * layers.
++	 */
++	atomic_inc(&skb->users);
++	ch->prof.txlen += skb->len;
++	header.length = skb->len + LL_HEADER_LENGTH;
++	header.type = skb->protocol;
++	header.unused = 0;
++	memcpy(skb_push(skb, LL_HEADER_LENGTH), &header, LL_HEADER_LENGTH);
++	block_len = skb->len + 2;
++	*((__u16 *)skb_push(skb, 2)) = block_len;
++
++	/*
++	 * IDAL support in CTCM is broken, so we have to
++	 * care about skb's above 2G ourselves.
++	 */
++	hi = ((unsigned long)skb_tail_pointer(skb) + LL_HEADER_LENGTH) >> 31;
++	if (hi) {
++		nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
++		if (!nskb) {
++			atomic_dec(&skb->users);
++			skb_pull(skb, LL_HEADER_LENGTH + 2);
++			ctcm_clear_busy(ch->netdev);
++			return -ENOMEM;
++		} else {
++			memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
++			atomic_inc(&nskb->users);
++			atomic_dec(&skb->users);
++			dev_kfree_skb_irq(skb);
++			skb = nskb;
++		}
++	}
++
++	ch->ccw[4].count = block_len;
++	if (set_normalized_cda(&ch->ccw[4], skb->data)) {
++		/*
++		 * idal allocation failed, try via copying to
++		 * trans_skb. trans_skb usually has a pre-allocated
++		 * idal.
++		 */
++		if (ctcm_checkalloc_buffer(ch)) {
++			/*
++			 * Remove our header. It gets added
++			 * again on retransmit.
++			 */
++			atomic_dec(&skb->users);
++			skb_pull(skb, LL_HEADER_LENGTH + 2);
++			ctcm_clear_busy(ch->netdev);
++			return -EBUSY;
++		}
++
++		skb_reset_tail_pointer(ch->trans_skb);
++		ch->trans_skb->len = 0;
++		ch->ccw[1].count = skb->len;
++		skb_copy_from_linear_data(skb,
++				skb_put(ch->trans_skb, skb->len), skb->len);
++		atomic_dec(&skb->users);
++		dev_kfree_skb_irq(skb);
++		ccw_idx = 0;
++	} else {
++		skb_queue_tail(&ch->io_queue, skb);
++		ccw_idx = 3;
++	}
++	ch->retry = 0;
++	fsm_newstate(ch->fsm, CTC_STATE_TX);
++	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++	ch->prof.send_stamp = current_kernel_time(); /* xtime */
++	rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
++					(unsigned long)ch, 0xff, 0);
++	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++	if (ccw_idx == 3)
++		ch->prof.doios_single++;
++	if (rc != 0) {
++		fsm_deltimer(&ch->timer);
++		ctcm_ccw_check_rc(ch, rc, "single skb TX");
++		if (ccw_idx == 3)
++			skb_dequeue_tail(&ch->io_queue);
++		/*
++		 * Remove our header. It gets added
++		 * again on retransmit.
++		 */
++		skb_pull(skb, LL_HEADER_LENGTH + 2);
++	} else if (ccw_idx == 0) {
++		struct net_device *dev = ch->netdev;
++		struct ctcm_priv *priv = dev->priv;
++		priv->stats.tx_packets++;
++		priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
++	}
++done:
++	ctcm_clear_busy(ch->netdev);
++	return rc;
++}
++
++static void ctcmpc_send_sweep_req(struct channel *rch)
++{
++	struct net_device *dev = rch->netdev;
++	struct ctcm_priv *priv;
++	struct mpc_group *grp;
++	struct th_sweep *header;
++	struct sk_buff *sweep_skb;
++	struct channel *ch;
++	int rc = 0;
++
++	priv = dev->priv;
++	grp = priv->mpcg;
++	ch = priv->channel[WRITE];
++
++	if (do_debug)
++		MPC_DBF_DEV_NAME(TRACE, dev, ch->id);
++
++	/* sweep processing is not complete until response and request */
++	/* has completed for all read channels in group		       */
++	if (grp->in_sweep == 0) {
++		grp->in_sweep = 1;
++		grp->sweep_rsp_pend_num = grp->active_channels[READ];
++		grp->sweep_req_pend_num = grp->active_channels[READ];
++	}
++
++	sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
++
++	if (sweep_skb == NULL)	{
++		printk(KERN_INFO "Couldn't alloc sweep_skb\n");
++		rc = -ENOMEM;
++					goto done;
++	}
++
++	header = kmalloc(TH_SWEEP_LENGTH, gfp_type());
++
++	if (!header) {
++		dev_kfree_skb_any(sweep_skb);
++		rc = -ENOMEM;
++					goto done;
++	}
++
++	header->th.th_seg	= 0x00 ;
++	header->th.th_ch_flag	= TH_SWEEP_REQ;  /* 0x0f */
++	header->th.th_blk_flag	= 0x00;
++	header->th.th_is_xid	= 0x00;
++	header->th.th_seq_num	= 0x00;
++	header->sw.th_last_seq	= ch->th_seq_num;
++
++	memcpy(skb_put(sweep_skb, TH_SWEEP_LENGTH), header, TH_SWEEP_LENGTH);
++
++	kfree(header);
++
++	dev->trans_start = jiffies;
++	skb_queue_tail(&ch->sweep_queue, sweep_skb);
++
++	fsm_addtimer(&ch->sweep_timer, 100, CTC_EVENT_RSWEEP_TIMER, ch);
++
++	return;
++
++done:
++	if (rc != 0) {
++		grp->in_sweep = 0;
++		ctcm_clear_busy(dev);
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++	}
++
++	return;
++}
++
++/*
++ * MPC mode version of transmit_skb
++ */
++static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
++{
++	struct pdu *p_header;
++	struct net_device *dev = ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++	struct mpc_group *grp = priv->mpcg;
++	struct th_header *header;
++	struct sk_buff *nskb;
++	int rc = 0;
++	int ccw_idx;
++	unsigned long hi;
++	unsigned long saveflags = 0;	/* avoids compiler warning */
++	__u16 block_len;
++
++	if (do_debug)
++		ctcm_pr_debug(
++			"ctcm enter: %s(): %s cp=%i ch=0x%p id=%s state=%s\n",
++			__FUNCTION__, dev->name, smp_processor_id(), ch,
++			ch->id, fsm_getstate_str(ch->fsm));
++
++	if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
++		spin_lock_irqsave(&ch->collect_lock, saveflags);
++		atomic_inc(&skb->users);
++		p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
++
++		if (!p_header) {
++			printk(KERN_WARNING "ctcm: OUT OF MEMORY IN %s():"
++			       " Data Lost \n", __FUNCTION__);
++
++			atomic_dec(&skb->users);
++			dev_kfree_skb_any(skb);
++			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++					goto done;
++		}
++
++		p_header->pdu_offset = skb->len;
++		p_header->pdu_proto = 0x01;
++		p_header->pdu_flag = 0x00;
++		if (skb->protocol == ntohs(ETH_P_SNAP)) {
++			p_header->pdu_flag |= PDU_FIRST | PDU_CNTL;
++		} else {
++			p_header->pdu_flag |= PDU_FIRST;
++		}
++		p_header->pdu_seq = 0;
++		memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header,
++		       PDU_HEADER_LENGTH);
++
++		if (do_debug_data) {
++			ctcm_pr_debug("ctcm: %s() Putting on collect_q"
++			       " - skb len: %04x \n", __FUNCTION__, skb->len);
++			ctcm_pr_debug("ctcm: %s() pdu header and data"
++			       " for up to 32 bytes\n", __FUNCTION__);
++			ctcmpc_dump32((char *)skb->data, skb->len);
++		}
++
++		skb_queue_tail(&ch->collect_queue, skb);
++		ch->collect_len += skb->len;
++		kfree(p_header);
++
++		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++			goto done;
++	}
++
++	/*
++	 * Protect skb against beeing free'd by upper
++	 * layers.
++	 */
++	atomic_inc(&skb->users);
++
++	block_len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++	/*
++	 * IDAL support in CTCM is broken, so we have to
++	 * care about skb's above 2G ourselves.
++	 */
++	hi = ((unsigned long)skb->tail + TH_HEADER_LENGTH) >> 31;
++	if (hi) {
++		nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
++		if (!nskb) {
++			printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
++				"-  Data Lost \n", __FUNCTION__);
++			atomic_dec(&skb->users);
++			dev_kfree_skb_any(skb);
++			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++				goto done;
++		} else {
++			memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
++			atomic_inc(&nskb->users);
++			atomic_dec(&skb->users);
++			dev_kfree_skb_irq(skb);
++			skb = nskb;
++		}
++	}
++
++	p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
++
++	if (!p_header) {
++		printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
++		       ": Data Lost \n", __FUNCTION__);
++
++		atomic_dec(&skb->users);
++		dev_kfree_skb_any(skb);
++		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++				goto done;
++	}
++
++	p_header->pdu_offset = skb->len;
++	p_header->pdu_proto = 0x01;
++	p_header->pdu_flag = 0x00;
++	p_header->pdu_seq = 0;
++	if (skb->protocol == ntohs(ETH_P_SNAP)) {
++		p_header->pdu_flag |= PDU_FIRST | PDU_CNTL;
++	} else {
++		p_header->pdu_flag |= PDU_FIRST;
++	}
++	memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header, PDU_HEADER_LENGTH);
++
++	kfree(p_header);
++
++	if (ch->collect_len > 0) {
++		spin_lock_irqsave(&ch->collect_lock, saveflags);
++		skb_queue_tail(&ch->collect_queue, skb);
++		ch->collect_len += skb->len;
++		skb = skb_dequeue(&ch->collect_queue);
++		ch->collect_len -= skb->len;
++		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++	}
++
++	p_header = (struct pdu *)skb->data;
++	p_header->pdu_flag |= PDU_LAST;
++
++	ch->prof.txlen += skb->len - PDU_HEADER_LENGTH;
++
++	header = kmalloc(TH_HEADER_LENGTH, gfp_type());
++
++	if (!header) {
++		printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY: Data Lost \n",
++				__FUNCTION__);
++		atomic_dec(&skb->users);
++		dev_kfree_skb_any(skb);
++		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++				goto done;
++	}
++
++	header->th_seg = 0x00;
++	header->th_ch_flag = TH_HAS_PDU;  /* Normal data */
++	header->th_blk_flag = 0x00;
++	header->th_is_xid = 0x00;          /* Just data here */
++	ch->th_seq_num++;
++	header->th_seq_num = ch->th_seq_num;
++
++	if (do_debug_data)
++		ctcm_pr_debug("ctcm: %s() ToVTAM_th_seq= %08x\n" ,
++		       __FUNCTION__, ch->th_seq_num);
++
++	/* put the TH on the packet */
++	memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH);
++
++	kfree(header);
++
++	if (do_debug_data) {
++		ctcm_pr_debug("ctcm: %s(): skb len: %04x \n",
++				__FUNCTION__, skb->len);
++		ctcm_pr_debug("ctcm: %s(): pdu header and data for up to 32 "
++				"bytes sent to vtam\n", __FUNCTION__);
++		ctcmpc_dump32((char *)skb->data, skb->len);
++	}
++
++	ch->ccw[4].count = skb->len;
++	if (set_normalized_cda(&ch->ccw[4], skb->data)) {
++		/*
++		 * idal allocation failed, try via copying to
++		 * trans_skb. trans_skb usually has a pre-allocated
++		 * idal.
++		 */
++		if (ctcm_checkalloc_buffer(ch)) {
++			/*
++			 * Remove our header. It gets added
++			 * again on retransmit.
++			 */
++			atomic_dec(&skb->users);
++			dev_kfree_skb_any(skb);
++			printk(KERN_WARNING "ctcm: %s()OUT OF MEMORY:"
++					" Data Lost \n", __FUNCTION__);
++			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++				goto done;
++		}
++
++		skb_reset_tail_pointer(ch->trans_skb);
++		ch->trans_skb->len = 0;
++		ch->ccw[1].count = skb->len;
++		memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
++		atomic_dec(&skb->users);
++		dev_kfree_skb_irq(skb);
++		ccw_idx = 0;
++		if (do_debug_data) {
++			ctcm_pr_debug("ctcm: %s() TRANS skb len: %d \n",
++			       __FUNCTION__, ch->trans_skb->len);
++			ctcm_pr_debug("ctcm: %s up to 32 bytes of data"
++				" sent to vtam\n", __FUNCTION__);
++			ctcmpc_dump32((char *)ch->trans_skb->data,
++					ch->trans_skb->len);
++		}
++	} else {
++		skb_queue_tail(&ch->io_queue, skb);
++		ccw_idx = 3;
++	}
++	ch->retry = 0;
++	fsm_newstate(ch->fsm, CTC_STATE_TX);
++	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++
++	if (do_debug_ccw)
++		ctcmpc_dumpit((char *)&ch->ccw[ccw_idx],
++					sizeof(struct ccw1) * 3);
++
++	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++	ch->prof.send_stamp = current_kernel_time(); /* xtime */
++	rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
++					(unsigned long)ch, 0xff, 0);
++	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++	if (ccw_idx == 3)
++		ch->prof.doios_single++;
++	if (rc != 0) {
++		fsm_deltimer(&ch->timer);
++		ctcm_ccw_check_rc(ch, rc, "single skb TX");
++		if (ccw_idx == 3)
++			skb_dequeue_tail(&ch->io_queue);
++	} else if (ccw_idx == 0) {
++		priv->stats.tx_packets++;
++		priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
++	}
++	if (ch->th_seq_num > 0xf0000000)	/* Chose 4Billion at random. */
++		ctcmpc_send_sweep_req(ch);
++
++done:
++	if (do_debug)
++		ctcm_pr_debug("ctcm exit: %s  %s()\n", dev->name, __FUNCTION__);
++	return 0;
++}
++
++/**
++ * Start transmission of a packet.
++ * Called from generic network device layer.
++ *
++ *  skb		Pointer to buffer containing the packet.
++ *  dev		Pointer to interface struct.
++ *
++ * returns 0 if packet consumed, !0 if packet rejected.
++ *         Note: If we return !0, then the packet is free'd by
++ *               the generic network layer.
++ */
++/* first merge version - leaving both functions separated */
++static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
++{
++	int rc = 0;
++	struct ctcm_priv *priv;
++
++	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
++	priv = dev->priv;
++
++	if (skb == NULL) {
++		ctcm_pr_warn("%s: NULL sk_buff passed\n", dev->name);
++		priv->stats.tx_dropped++;
++		return 0;
++	}
++	if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
++		ctcm_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
++			    dev->name, LL_HEADER_LENGTH + 2);
++		dev_kfree_skb(skb);
++		priv->stats.tx_dropped++;
++		return 0;
++	}
++
++	/*
++	 * If channels are not running, try to restart them
++	 * and throw away packet.
++	 */
++	if (fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) {
++		fsm_event(priv->fsm, DEV_EVENT_START, dev);
++		dev_kfree_skb(skb);
++		priv->stats.tx_dropped++;
++		priv->stats.tx_errors++;
++		priv->stats.tx_carrier_errors++;
++		return 0;
++	}
++
++	if (ctcm_test_and_set_busy(dev))
++		return -EBUSY;
++
++	dev->trans_start = jiffies;
++	if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0)
++		rc = 1;
++	return rc;
++}
++
++/* unmerged MPC variant of ctcm_tx */
++static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
++{
++	int len = 0;
++	struct ctcm_priv *priv = NULL;
++	struct mpc_group *grp  = NULL;
++	struct sk_buff *newskb = NULL;
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc enter: %s(): skb:%0lx\n",
++			__FUNCTION__, (unsigned long)skb);
++
++	CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
++			"ctcmpc enter: %s(): skb:%0lx\n",
++			__FUNCTION__, (unsigned long)skb);
++
++	priv = dev->priv;
++	grp  = priv->mpcg;
++	/*
++	 * Some sanity checks ...
++	 */
++	if (skb == NULL) {
++		ctcm_pr_warn("ctcmpc: %s: NULL sk_buff passed\n", dev->name);
++		priv->stats.tx_dropped++;
++					goto done;
++	}
++	if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) {
++		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_WARN,
++			"%s: Got sk_buff with head room < %ld bytes\n",
++			dev->name, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
++
++		if (do_debug_data)
++			ctcmpc_dump32((char *)skb->data, skb->len);
++
++		len =  skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++		newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA);
++
++		if (!newskb) {
++			printk(KERN_WARNING "ctcmpc: %s() OUT OF MEMORY-"
++			       "Data Lost\n",
++			       __FUNCTION__);
++
++			dev_kfree_skb_any(skb);
++			priv->stats.tx_dropped++;
++			priv->stats.tx_errors++;
++			priv->stats.tx_carrier_errors++;
++			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++					goto done;
++		}
++		newskb->protocol = skb->protocol;
++		skb_reserve(newskb, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
++		memcpy(skb_put(newskb, skb->len), skb->data, skb->len);
++		dev_kfree_skb_any(skb);
++		skb = newskb;
++	}
++
++	/*
++	 * If channels are not running,
++	 * notify anybody about a link failure and throw
++	 * away packet.
++	 */
++	if ((fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) ||
++	   (fsm_getstate(grp->fsm) <  MPCG_STATE_XID2INITW)) {
++		dev_kfree_skb_any(skb);
++		printk(KERN_INFO "ctcmpc: %s() DATA RCVD - MPC GROUP "
++		       "NOT ACTIVE - DROPPED\n",
++		       __FUNCTION__);
++		priv->stats.tx_dropped++;
++		priv->stats.tx_errors++;
++		priv->stats.tx_carrier_errors++;
++					goto done;
++	}
++
++	if (ctcm_test_and_set_busy(dev)) {
++		printk(KERN_WARNING "%s:DEVICE ERR - UNRECOVERABLE DATA LOSS\n",
++		       __FUNCTION__);
++		dev_kfree_skb_any(skb);
++		priv->stats.tx_dropped++;
++		priv->stats.tx_errors++;
++		priv->stats.tx_carrier_errors++;
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++					goto done;
++	}
++
++	dev->trans_start = jiffies;
++	if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) {
++		printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
++		       ": Data Lost \n",
++		       __FUNCTION__);
++		printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
++		       " - UNRECOVERABLE DATA LOSS\n",
++		       __FUNCTION__);
++		dev_kfree_skb_any(skb);
++		priv->stats.tx_dropped++;
++		priv->stats.tx_errors++;
++		priv->stats.tx_carrier_errors++;
++		ctcm_clear_busy(dev);
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++					goto done;
++	}
++	ctcm_clear_busy(dev);
++done:
++	if (do_debug)
++		MPC_DBF_DEV_NAME(TRACE, dev, "exit");
++
++	return 0;	/* handle freeing of skb here */
++}
++
++
++/**
++ * Sets MTU of an interface.
++ *
++ *  dev		Pointer to interface struct.
++ *  new_mtu	The new MTU to use for this interface.
++ *
++ * returns 0 on success, -EINVAL if MTU is out of valid range.
++ *         (valid range is 576 .. 65527). If VM is on the
++ *         remote side, maximum MTU is 32760, however this is
++ *         not checked here.
++ */
++static int ctcm_change_mtu(struct net_device *dev, int new_mtu)
++{
++	struct ctcm_priv *priv;
++	int max_bufsize;
++
++	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++
++	if (new_mtu < 576 || new_mtu > 65527)
++		return -EINVAL;
++
++	priv = dev->priv;
++	max_bufsize = priv->channel[READ]->max_bufsize;
++
++	if (IS_MPC(priv)) {
++		if (new_mtu > max_bufsize - TH_HEADER_LENGTH)
++			return -EINVAL;
++		dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++	} else {
++		if (new_mtu > max_bufsize - LL_HEADER_LENGTH - 2)
++			return -EINVAL;
++		dev->hard_header_len = LL_HEADER_LENGTH + 2;
++	}
++	dev->mtu = new_mtu;
++	return 0;
++}
++
++/**
++ * Returns interface statistics of a device.
++ *
++ *  dev		Pointer to interface struct.
++ *
++ * returns Pointer to stats struct of this interface.
++ */
++static struct net_device_stats *ctcm_stats(struct net_device *dev)
++{
++	return &((struct ctcm_priv *)dev->priv)->stats;
++}
++
++
++static void ctcm_netdev_unregister(struct net_device *dev)
++{
++	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++	if (!dev)
++		return;
++	unregister_netdev(dev);
++}
++
++static int ctcm_netdev_register(struct net_device *dev)
++{
++	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++	return register_netdev(dev);
++}
++
++static void ctcm_free_netdevice(struct net_device *dev)
++{
++	struct ctcm_priv *priv;
++	struct mpc_group *grp;
++
++	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++
++	if (!dev)
++		return;
++	priv = dev->priv;
++	if (priv) {
++		grp = priv->mpcg;
++		if (grp) {
++			if (grp->fsm)
++				kfree_fsm(grp->fsm);
++			if (grp->xid_skb)
++				dev_kfree_skb(grp->xid_skb);
++			if (grp->rcvd_xid_skb)
++				dev_kfree_skb(grp->rcvd_xid_skb);
++			tasklet_kill(&grp->mpc_tasklet2);
++			kfree(grp);
++			priv->mpcg = NULL;
++		}
++		if (priv->fsm) {
++			kfree_fsm(priv->fsm);
++			priv->fsm = NULL;
++		}
++		kfree(priv->xid);
++		priv->xid = NULL;
++	/*
++	 * Note: kfree(priv); is done in "opposite" function of
++	 * allocator function probe_device which is remove_device.
++	 */
++	}
++#ifdef MODULE
++	free_netdev(dev);
++#endif
++}
++
++struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
++
++void static ctcm_dev_setup(struct net_device *dev)
++{
++	dev->open = ctcm_open;
++	dev->stop = ctcm_close;
++	dev->get_stats = ctcm_stats;
++	dev->change_mtu = ctcm_change_mtu;
++	dev->type = ARPHRD_SLIP;
++	dev->tx_queue_len = 100;
++	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
++}
++
++/*
++ * Initialize everything of the net device except the name and the
++ * channel structs.
++ */
++static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
++{
++	struct net_device *dev;
++	struct mpc_group *grp;
++	if (!priv)
++		return NULL;
++
++	if (IS_MPC(priv))
++		dev = alloc_netdev(0, MPC_DEVICE_GENE, ctcm_dev_setup);
++	else
++		dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup);
++
++	if (!dev) {
++		ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
++		return NULL;
++	}
++	dev->priv = priv;
++	priv->fsm = init_fsm("ctcmdev", dev_state_names, dev_event_names,
++				CTCM_NR_DEV_STATES, CTCM_NR_DEV_EVENTS,
++				dev_fsm, dev_fsm_len, GFP_KERNEL);
++	if (priv->fsm == NULL) {
++		CTCMY_DBF_DEV(SETUP, dev, "init_fsm error");
++		kfree(dev);
++		return NULL;
++	}
++	fsm_newstate(priv->fsm, DEV_STATE_STOPPED);
++	fsm_settimer(priv->fsm, &priv->restart_timer);
++
++	if (IS_MPC(priv)) {
++		/*  MPC Group Initializations  */
++		grp = ctcmpc_init_mpc_group(priv);
++		if (grp == NULL) {
++			MPC_DBF_DEV(SETUP, dev, "init_mpc_group error");
++			kfree(dev);
++			return NULL;
++		}
++		tasklet_init(&grp->mpc_tasklet2,
++				mpc_group_ready, (unsigned long)dev);
++		dev->mtu = MPC_BUFSIZE_DEFAULT -
++				TH_HEADER_LENGTH - PDU_HEADER_LENGTH;
++
++		dev->hard_start_xmit = ctcmpc_tx;
++		dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++		priv->buffer_size = MPC_BUFSIZE_DEFAULT;
++	} else {
++		dev->mtu = CTCM_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
++		dev->hard_start_xmit = ctcm_tx;
++		dev->hard_header_len = LL_HEADER_LENGTH + 2;
++	}
++
++	CTCMY_DBF_DEV(SETUP, dev, "finished");
++	return dev;
++}
++
++/**
++ * Main IRQ handler.
++ *
++ *  cdev	The ccw_device the interrupt is for.
++ *  intparm	interruption parameter.
++ *  irb		interruption response block.
++ */
++static void ctcm_irq_handler(struct ccw_device *cdev,
++				unsigned long intparm, struct irb *irb)
++{
++	struct channel		*ch;
++	struct net_device	*dev;
++	struct ctcm_priv	*priv;
++	struct ccwgroup_device	*cgdev;
++
++	CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __FUNCTION__);
++	if (ctcm_check_irb_error(cdev, irb))
++		return;
++
++	cgdev = dev_get_drvdata(&cdev->dev);
++
++	/* Check for unsolicited interrupts. */
++	if (cgdev == NULL) {
++		ctcm_pr_warn("ctcm: Got unsolicited irq: %s c-%02x d-%02x\n",
++			    cdev->dev.bus_id, irb->scsw.cstat,
++			    irb->scsw.dstat);
++		return;
++	}
++
++	priv = dev_get_drvdata(&cgdev->dev);
++
++	/* Try to extract channel from driver data. */
++	if (priv->channel[READ]->cdev == cdev)
++		ch = priv->channel[READ];
++	else if (priv->channel[WRITE]->cdev == cdev)
++		ch = priv->channel[WRITE];
++	else {
++		ctcm_pr_err("ctcm: Can't determine channel for interrupt, "
++			   "device %s\n", cdev->dev.bus_id);
++		return;
++	}
++
++	dev = (struct net_device *)(ch->netdev);
++	if (dev == NULL) {
++		ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n",
++				__FUNCTION__, cdev->dev.bus_id, ch);
++		return;
++	}
++
++	if (do_debug)
++		ctcm_pr_debug("%s: interrupt for device: %s "
++				"received c-%02x d-%02x\n",
++				dev->name,
++				ch->id,
++				irb->scsw.cstat,
++				irb->scsw.dstat);
++
++	/* Copy interruption response block. */
++	memcpy(ch->irb, irb, sizeof(struct irb));
++
++	/* Check for good subchannel return code, otherwise error message */
++	if (irb->scsw.cstat) {
++		fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch);
++		ctcm_pr_warn("%s: subchannel check for dev: %s - %02x %02x\n",
++			    dev->name, ch->id, irb->scsw.cstat,
++			    irb->scsw.dstat);
++		return;
++	}
++
++	/* Check the reason-code of a unit check */
++	if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
++		ccw_unit_check(ch, irb->ecw[0]);
++		return;
++	}
++	if (irb->scsw.dstat & DEV_STAT_BUSY) {
++		if (irb->scsw.dstat & DEV_STAT_ATTENTION)
++			fsm_event(ch->fsm, CTC_EVENT_ATTNBUSY, ch);
++		else
++			fsm_event(ch->fsm, CTC_EVENT_BUSY, ch);
++		return;
++	}
++	if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
++		fsm_event(ch->fsm, CTC_EVENT_ATTN, ch);
++		return;
++	}
++	if ((irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
++	    (irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
++	    (irb->scsw.stctl ==
++	     (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))
++		fsm_event(ch->fsm, CTC_EVENT_FINSTAT, ch);
++	else
++		fsm_event(ch->fsm, CTC_EVENT_IRQ, ch);
++
++}
++
++/**
++ * Add ctcm specific attributes.
++ * Add ctcm private data.
++ *
++ *  cgdev	pointer to ccwgroup_device just added
++ *
++ * returns 0 on success, !0 on failure.
++ */
++static int ctcm_probe_device(struct ccwgroup_device *cgdev)
++{
++	struct ctcm_priv *priv;
++	int rc;
++
++	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s %p", __FUNCTION__, cgdev);
++
++	if (!get_device(&cgdev->dev))
++		return -ENODEV;
++
++	priv = kzalloc(sizeof(struct ctcm_priv), GFP_KERNEL);
++	if (!priv) {
++		ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
++		put_device(&cgdev->dev);
++		return -ENOMEM;
++	}
++
++	rc = ctcm_add_files(&cgdev->dev);
++	if (rc) {
++		kfree(priv);
++		put_device(&cgdev->dev);
++		return rc;
++	}
++	priv->buffer_size = CTCM_BUFSIZE_DEFAULT;
++	cgdev->cdev[0]->handler = ctcm_irq_handler;
++	cgdev->cdev[1]->handler = ctcm_irq_handler;
++	dev_set_drvdata(&cgdev->dev, priv);
++
++	return 0;
++}
++
++/**
++ * Add a new channel to the list of channels.
++ * Keeps the channel list sorted.
++ *
++ *  cdev	The ccw_device to be added.
++ *  type	The type class of the new channel.
++ *  priv	Points to the private data of the ccwgroup_device.
++ *
++ * returns 0 on success, !0 on error.
++ */
++static int add_channel(struct ccw_device *cdev, enum channel_types type,
++				struct ctcm_priv *priv)
++{
++	struct channel **c = &channels;
++	struct channel *ch;
++	int ccw_num;
++	int rc = 0;
++
++	CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
++	ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
++	if (ch == NULL)
++					goto nomem_return;
++
++	ch->protocol = priv->protocol;
++	if (IS_MPC(priv)) {
++		ch->discontact_th = (struct th_header *)
++				kzalloc(TH_HEADER_LENGTH, gfp_type());
++		if (ch->discontact_th == NULL)
++					goto nomem_return;
++
++		ch->discontact_th->th_blk_flag = TH_DISCONTACT;
++		tasklet_init(&ch->ch_disc_tasklet,
++			mpc_action_send_discontact, (unsigned long)ch);
++
++		tasklet_init(&ch->ch_tasklet, ctcmpc_bh, (unsigned long)ch);
++		ch->max_bufsize = (MPC_BUFSIZE_DEFAULT - 35);
++		ccw_num = 17;
++	} else
++		ccw_num = 8;
++
++	ch->ccw = (struct ccw1 *)
++		kzalloc(ccw_num * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
++	if (ch->ccw == NULL)
++					goto nomem_return;
++
++	ch->cdev = cdev;
++	snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", cdev->dev.bus_id);
++	ch->type = type;
++
++	/**
++	 * "static" ccws are used in the following way:
++	 *
++	 * ccw[0..2] (Channel program for generic I/O):
++	 *           0: prepare
++	 *           1: read or write (depending on direction) with fixed
++	 *              buffer (idal allocated once when buffer is allocated)
++	 *           2: nop
++	 * ccw[3..5] (Channel program for direct write of packets)
++	 *           3: prepare
++	 *           4: write (idal allocated on every write).
++	 *           5: nop
++	 * ccw[6..7] (Channel program for initial channel setup):
++	 *           6: set extended mode
++	 *           7: nop
++	 *
++	 * ch->ccw[0..5] are initialized in ch_action_start because
++	 * the channel's direction is yet unknown here.
++	 *
++	 * ccws used for xid2 negotiations
++	 *  ch-ccw[8-14] need to be used for the XID exchange either
++	 *    X side XID2 Processing
++	 *       8:  write control
++	 *       9:  write th
++	 *	     10: write XID
++	 *	     11: read th from secondary
++	 *	     12: read XID   from secondary
++	 *	     13: read 4 byte ID
++	 *	     14: nop
++	 *    Y side XID Processing
++	 *	     8:  sense
++	 *       9:  read th
++	 *	     10: read XID
++	 *	     11: write th
++	 *	     12: write XID
++	 *	     13: write 4 byte ID
++	 *	     14: nop
++	 *
++	 *  ccws used for double noop due to VM timing issues
++	 *  which result in unrecoverable Busy on channel
++	 *       15: nop
++	 *       16: nop
++	 */
++	ch->ccw[6].cmd_code	= CCW_CMD_SET_EXTENDED;
++	ch->ccw[6].flags	= CCW_FLAG_SLI;
++
++	ch->ccw[7].cmd_code	= CCW_CMD_NOOP;
++	ch->ccw[7].flags	= CCW_FLAG_SLI;
++
++	if (IS_MPC(priv)) {
++		ch->ccw[15].cmd_code = CCW_CMD_WRITE;
++		ch->ccw[15].flags    = CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[15].count    = TH_HEADER_LENGTH;
++		ch->ccw[15].cda      = virt_to_phys(ch->discontact_th);
++
++		ch->ccw[16].cmd_code = CCW_CMD_NOOP;
++		ch->ccw[16].flags    = CCW_FLAG_SLI;
++
++		ch->fsm = init_fsm(ch->id, ctc_ch_state_names,
++				ctc_ch_event_names, CTC_MPC_NR_STATES,
++				CTC_MPC_NR_EVENTS, ctcmpc_ch_fsm,
++				mpc_ch_fsm_len, GFP_KERNEL);
++	} else {
++		ch->fsm = init_fsm(ch->id, ctc_ch_state_names,
++				ctc_ch_event_names, CTC_NR_STATES,
++				CTC_NR_EVENTS, ch_fsm,
++				ch_fsm_len, GFP_KERNEL);
++	}
++	if (ch->fsm == NULL)
++				goto free_return;
++
++	fsm_newstate(ch->fsm, CTC_STATE_IDLE);
++
++	ch->irb = kzalloc(sizeof(struct irb), GFP_KERNEL);
++	if (ch->irb == NULL)
++				goto nomem_return;
++
++	while (*c && ctcm_less_than((*c)->id, ch->id))
++		c = &(*c)->next;
++
++	if (*c && (!strncmp((*c)->id, ch->id, CTCM_ID_SIZE))) {
++		CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
++				"%s (%s) already in list, using old entry",
++				__FUNCTION__, (*c)->id);
++
++				goto free_return;
++	}
++
++	spin_lock_init(&ch->collect_lock);
++
++	fsm_settimer(ch->fsm, &ch->timer);
++	skb_queue_head_init(&ch->io_queue);
++	skb_queue_head_init(&ch->collect_queue);
++
++	if (IS_MPC(priv)) {
++		fsm_settimer(ch->fsm, &ch->sweep_timer);
++		skb_queue_head_init(&ch->sweep_queue);
++	}
++	ch->next = *c;
++	*c = ch;
++	return 0;
++
++nomem_return:
++	ctcm_pr_warn("ctcm: Out of memory in %s\n", __FUNCTION__);
++	rc = -ENOMEM;
++
++free_return:	/* note that all channel pointers are 0 or valid */
++	kfree(ch->ccw);		/* TODO: check that again */
++	kfree(ch->discontact_th);
++	kfree_fsm(ch->fsm);
++	kfree(ch->irb);
++	kfree(ch);
++	return rc;
++}
++
++/*
++ * Return type of a detected device.
++ */
++static enum channel_types get_channel_type(struct ccw_device_id *id)
++{
++	enum channel_types type;
++	type = (enum channel_types)id->driver_info;
++
++	if (type == channel_type_ficon)
++		type = channel_type_escon;
++
++	return type;
++}
++
++/**
++ *
++ * Setup an interface.
++ *
++ *  cgdev	Device to be setup.
++ *
++ * returns 0 on success, !0 on failure.
++ */
++static int ctcm_new_device(struct ccwgroup_device *cgdev)
++{
++	char read_id[CTCM_ID_SIZE];
++	char write_id[CTCM_ID_SIZE];
++	int direction;
++	enum channel_types type;
++	struct ctcm_priv *priv;
++	struct net_device *dev;
++	int ret;
++
++	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++
++	priv = dev_get_drvdata(&cgdev->dev);
++	if (!priv)
++		return -ENODEV;
++
++	type = get_channel_type(&cgdev->cdev[0]->id);
++
++	snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
++	snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
++
++	ret = add_channel(cgdev->cdev[0], type, priv);
++	if (ret)
++		return ret;
++	ret = add_channel(cgdev->cdev[1], type, priv);
++	if (ret)
++		return ret;
++
++	ret = ccw_device_set_online(cgdev->cdev[0]);
++	if (ret != 0) {
++		CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
++				"ccw_device_set_online (cdev[0]) failed ");
++		ctcm_pr_warn("ccw_device_set_online (cdev[0]) failed "
++				"with ret = %d\n", ret);
++	}
++
++	ret = ccw_device_set_online(cgdev->cdev[1]);
++	if (ret != 0) {
++		CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
++				"ccw_device_set_online (cdev[1]) failed ");
++		ctcm_pr_warn("ccw_device_set_online (cdev[1]) failed "
++				"with ret = %d\n", ret);
++	}
++
++	dev = ctcm_init_netdevice(priv);
++
++	if (dev == NULL) {
++		ctcm_pr_warn("ctcm_init_netdevice failed\n");
++					goto out;
++	}
++
++	for (direction = READ; direction <= WRITE; direction++) {
++		priv->channel[direction] =
++		    channel_get(type, direction == READ ? read_id : write_id,
++				direction);
++		if (priv->channel[direction] == NULL) {
++			if (direction == WRITE)
++				channel_free(priv->channel[READ]);
++			ctcm_free_netdevice(dev);
++					goto out;
++		}
++		priv->channel[direction]->netdev = dev;
++		priv->channel[direction]->protocol = priv->protocol;
++		priv->channel[direction]->max_bufsize = priv->buffer_size;
++	}
++	/* sysfs magic */
++	SET_NETDEV_DEV(dev, &cgdev->dev);
++
++	if (ctcm_netdev_register(dev) != 0) {
++		ctcm_free_netdevice(dev);
++					goto out;
++	}
++
++	if (ctcm_add_attributes(&cgdev->dev)) {
++		ctcm_netdev_unregister(dev);
++/*		dev->priv = NULL;	why that ????	*/
++		ctcm_free_netdevice(dev);
++					goto out;
++	}
++
++	strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
++
++	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
++			"setup(%s) ok : r/w = %s / %s, proto : %d",
++			dev->name, priv->channel[READ]->id,
++			priv->channel[WRITE]->id, priv->protocol);
++
++	return 0;
++out:
++	ccw_device_set_offline(cgdev->cdev[1]);
++	ccw_device_set_offline(cgdev->cdev[0]);
++
++	return -ENODEV;
++}
++
++/**
++ * Shutdown an interface.
++ *
++ *  cgdev	Device to be shut down.
++ *
++ * returns 0 on success, !0 on failure.
++ */
++static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
++{
++	struct ctcm_priv *priv;
++	struct net_device *dev;
++
++	priv = dev_get_drvdata(&cgdev->dev);
++	if (!priv)
++		return -ENODEV;
++
++	if (priv->channel[READ]) {
++		dev = priv->channel[READ]->netdev;
++		CTCM_DBF_DEV(SETUP, dev, "");
++		/* Close the device */
++		ctcm_close(dev);
++		dev->flags &= ~IFF_RUNNING;
++		ctcm_remove_attributes(&cgdev->dev);
++		channel_free(priv->channel[READ]);
++	} else
++		dev = NULL;
++
++	if (priv->channel[WRITE])
++		channel_free(priv->channel[WRITE]);
++
++	if (dev) {
++		ctcm_netdev_unregister(dev);
++/*		dev->priv = NULL;	why that ???	*/
++		ctcm_free_netdevice(dev);
++	}
++
++	if (priv->fsm)
++		kfree_fsm(priv->fsm);
++
++	ccw_device_set_offline(cgdev->cdev[1]);
++	ccw_device_set_offline(cgdev->cdev[0]);
++
++	if (priv->channel[READ])
++		channel_remove(priv->channel[READ]);
++	if (priv->channel[WRITE])
++		channel_remove(priv->channel[WRITE]);
++	priv->channel[READ] = priv->channel[WRITE] = NULL;
++
++	return 0;
++
++}
++
++
++static void ctcm_remove_device(struct ccwgroup_device *cgdev)
++{
++	struct ctcm_priv *priv;
++
++	CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, __FUNCTION__);
++
++	priv = dev_get_drvdata(&cgdev->dev);
++	if (!priv)
++		return;
++	if (cgdev->state == CCWGROUP_ONLINE)
++		ctcm_shutdown_device(cgdev);
++	ctcm_remove_files(&cgdev->dev);
++	dev_set_drvdata(&cgdev->dev, NULL);
++	kfree(priv);
++	put_device(&cgdev->dev);
++}
++
++static struct ccwgroup_driver ctcm_group_driver = {
++	.owner       = THIS_MODULE,
++	.name        = CTC_DRIVER_NAME,
++	.max_slaves  = 2,
++	.driver_id   = 0xC3E3C3D4,	/* CTCM */
++	.probe       = ctcm_probe_device,
++	.remove      = ctcm_remove_device,
++	.set_online  = ctcm_new_device,
++	.set_offline = ctcm_shutdown_device,
++};
++
++
++/*
++ * Module related routines
++ */
++
++/*
++ * Prepare to be unloaded. Free IRQ's and release all resources.
++ * This is called just before this module is unloaded. It is
++ * not called, if the usage count is !0, so we don't need to check
++ * for that.
++ */
++static void __exit ctcm_exit(void)
++{
++	unregister_cu3088_discipline(&ctcm_group_driver);
++	ctcm_unregister_dbf_views();
++	ctcm_pr_info("CTCM driver unloaded\n");
++}
++
++/*
++ * Print Banner.
++ */
++static void print_banner(void)
++{
++	printk(KERN_INFO "CTCM driver initialized\n");
++}
++
++/**
++ * Initialize module.
++ * This is called just after the module is loaded.
++ *
++ * returns 0 on success, !0 on error.
++ */
++static int __init ctcm_init(void)
++{
++	int ret;
++
++	channels = NULL;
++
++	ret = ctcm_register_dbf_views();
++	if (ret) {
++		ctcm_pr_crit("ctcm_init failed with ctcm_register_dbf_views "
++				"rc = %d\n", ret);
++		return ret;
++	}
++	ret = register_cu3088_discipline(&ctcm_group_driver);
++	if (ret) {
++		ctcm_unregister_dbf_views();
++		ctcm_pr_crit("ctcm_init failed with register_cu3088_discipline "
++				"(rc = %d)\n", ret);
++		return ret;
++	}
++	print_banner();
++	return ret;
++}
++
++module_init(ctcm_init);
++module_exit(ctcm_exit);
++
++MODULE_AUTHOR("Peter Tiedemann <ptiedem at de.ibm.com>");
++MODULE_DESCRIPTION("Network driver for S/390 CTC + CTCMPC (SNA)");
++MODULE_LICENSE("GPL");
++
+diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h
+new file mode 100644
+index 0000000..95b0c0b
+--- /dev/null
++++ b/drivers/s390/net/ctcm_main.h
+@@ -0,0 +1,287 @@
++/*
++ *	drivers/s390/net/ctcm_main.h
++ *
++ *	Copyright IBM Corp. 2001, 2007
++ *	Authors:	Fritz Elfert (felfert at millenux.com)
++ *			Peter Tiedemann (ptiedem at de.ibm.com)
++ */
++
++#ifndef _CTCM_MAIN_H_
++#define _CTCM_MAIN_H_
++
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++
++#include "fsm.h"
++#include "cu3088.h"
++#include "ctcm_dbug.h"
++#include "ctcm_mpc.h"
++
++#define CTC_DRIVER_NAME	"ctcm"
++#define CTC_DEVICE_NAME	"ctc"
++#define CTC_DEVICE_GENE	"ctc%d"
++#define MPC_DEVICE_NAME	"mpc"
++#define MPC_DEVICE_GENE	"mpc%d"
++
++#define CHANNEL_FLAGS_READ	0
++#define CHANNEL_FLAGS_WRITE	1
++#define CHANNEL_FLAGS_INUSE	2
++#define CHANNEL_FLAGS_BUFSIZE_CHANGED	4
++#define CHANNEL_FLAGS_FAILED	8
++#define CHANNEL_FLAGS_WAITIRQ	16
++#define CHANNEL_FLAGS_RWMASK	1
++#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
++
++#define LOG_FLAG_ILLEGALPKT	1
++#define LOG_FLAG_ILLEGALSIZE	2
++#define LOG_FLAG_OVERRUN	4
++#define LOG_FLAG_NOMEM		8
++
++#define ctcm_pr_debug(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
++#define ctcm_pr_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
++#define ctcm_pr_notice(fmt, arg...) printk(KERN_NOTICE fmt, ##arg)
++#define ctcm_pr_warn(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
++#define ctcm_pr_emerg(fmt, arg...) printk(KERN_EMERG fmt, ##arg)
++#define ctcm_pr_err(fmt, arg...) printk(KERN_ERR fmt, ##arg)
++#define ctcm_pr_crit(fmt, arg...) printk(KERN_CRIT fmt, ##arg)
++
++/*
++ * CCW commands, used in this driver.
++ */
++#define CCW_CMD_WRITE		0x01
++#define CCW_CMD_READ		0x02
++#define CCW_CMD_NOOP		0x03
++#define CCW_CMD_TIC             0x08
++#define CCW_CMD_SENSE_CMD	0x14
++#define CCW_CMD_WRITE_CTL	0x17
++#define CCW_CMD_SET_EXTENDED	0xc3
++#define CCW_CMD_PREPARE		0xe3
++
++#define CTCM_PROTO_S390		0
++#define CTCM_PROTO_LINUX	1
++#define CTCM_PROTO_LINUX_TTY	2
++#define CTCM_PROTO_OS390	3
++#define CTCM_PROTO_MPC		4
++#define CTCM_PROTO_MAX		4
++
++#define CTCM_BUFSIZE_LIMIT	65535
++#define CTCM_BUFSIZE_DEFAULT	32768
++#define MPC_BUFSIZE_DEFAULT	CTCM_BUFSIZE_LIMIT
++
++#define CTCM_TIME_1_SEC		1000
++#define CTCM_TIME_5_SEC		5000
++#define CTCM_TIME_10_SEC	10000
++
++#define CTCM_INITIAL_BLOCKLEN	2
++
++#define READ			0
++#define WRITE			1
++
++#define CTCM_ID_SIZE		BUS_ID_SIZE+3
++
++struct ctcm_profile {
++	unsigned long maxmulti;
++	unsigned long maxcqueue;
++	unsigned long doios_single;
++	unsigned long doios_multi;
++	unsigned long txlen;
++	unsigned long tx_time;
++	struct timespec send_stamp;
++};
++
++/*
++ * Definition of one channel
++ */
++struct channel {
++	struct channel *next;
++	char id[CTCM_ID_SIZE];
++	struct ccw_device *cdev;
++	/*
++	 * Type of this channel.
++	 * CTC/A or Escon for valid channels.
++	 */
++	enum channel_types type;
++	/*
++	 * Misc. flags. See CHANNEL_FLAGS_... below
++	 */
++	__u32 flags;
++	__u16 protocol;		/* protocol of this channel (4 = MPC) */
++	/*
++	 * I/O and irq related stuff
++	 */
++	struct ccw1 *ccw;
++	struct irb *irb;
++	/*
++	 * RX/TX buffer size
++	 */
++	int max_bufsize;
++	struct sk_buff *trans_skb;	/* transmit/receive buffer */
++	struct sk_buff_head io_queue;	/* universal I/O queue */
++	struct tasklet_struct ch_tasklet;	/* MPC ONLY */
++	/*
++	 * TX queue for collecting skb's during busy.
++	 */
++	struct sk_buff_head collect_queue;
++	/*
++	 * Amount of data in collect_queue.
++	 */
++	int collect_len;
++	/*
++	 * spinlock for collect_queue and collect_len
++	 */
++	spinlock_t collect_lock;
++	/*
++	 * Timer for detecting unresposive
++	 * I/O operations.
++	 */
++	fsm_timer timer;
++	/* MPC ONLY section begin */
++	__u32	th_seq_num;	/* SNA TH seq number */
++	__u8	th_seg;
++	__u32	pdu_seq;
++	struct sk_buff		*xid_skb;
++	char			*xid_skb_data;
++	struct th_header	*xid_th;
++	struct xid2		*xid;
++	char			*xid_id;
++	struct th_header	*rcvd_xid_th;
++	struct xid2		*rcvd_xid;
++	char			*rcvd_xid_id;
++	__u8			in_mpcgroup;
++	fsm_timer		sweep_timer;
++	struct sk_buff_head	sweep_queue;
++	struct th_header	*discontact_th;
++	struct tasklet_struct	ch_disc_tasklet;
++	/* MPC ONLY section end */
++
++	int retry;		/* retry counter for misc. operations */
++	fsm_instance *fsm;	/* finite state machine of this channel */
++	struct net_device *netdev;	/* corresponding net_device */
++	struct ctcm_profile prof;
++	unsigned char *trans_skb_data;
++	__u16 logflags;
++};
++
++struct ctcm_priv {
++	struct net_device_stats	stats;
++	unsigned long	tbusy;
++
++	/* The MPC group struct of this interface */
++	struct	mpc_group	*mpcg;	/* MPC only */
++	struct	xid2		*xid;	/* MPC only */
++
++	/* The finite state machine of this interface */
++	fsm_instance *fsm;
++
++	/* The protocol of this device */
++	__u16 protocol;
++
++	/* Timer for restarting after I/O Errors */
++	fsm_timer	restart_timer;
++
++	int buffer_size;	/* ctc only */
++
++	struct channel *channel[2];
++};
++
++int ctcm_open(struct net_device *dev);
++int ctcm_close(struct net_device *dev);
++
++/*
++ * prototypes for non-static sysfs functions
++ */
++int ctcm_add_attributes(struct device *dev);
++void ctcm_remove_attributes(struct device *dev);
++int ctcm_add_files(struct device *dev);
++void ctcm_remove_files(struct device *dev);
++
++/*
++ * Compatibility macros for busy handling
++ * of network devices.
++ */
++static inline void ctcm_clear_busy_do(struct net_device *dev)
++{
++	clear_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy));
++	netif_wake_queue(dev);
++}
++
++static inline void ctcm_clear_busy(struct net_device *dev)
++{
++	struct mpc_group *grp;
++	grp = ((struct ctcm_priv *)dev->priv)->mpcg;
++
++	if (!(grp && grp->in_sweep))
++		ctcm_clear_busy_do(dev);
++}
++
++
++static inline int ctcm_test_and_set_busy(struct net_device *dev)
++{
++	netif_stop_queue(dev);
++	return test_and_set_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy));
++}
++
++extern int loglevel;
++extern struct channel *channels;
++
++void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb);
++
++/*
++ * Functions related to setup and device detection.
++ */
++
++static inline int ctcm_less_than(char *id1, char *id2)
++{
++	unsigned long dev1, dev2;
++
++	id1 = id1 + 5;
++	id2 = id2 + 5;
++
++	dev1 = simple_strtoul(id1, &id1, 16);
++	dev2 = simple_strtoul(id2, &id2, 16);
++
++	return (dev1 < dev2);
++}
++
++int ctcm_ch_alloc_buffer(struct channel *ch);
++
++static inline int ctcm_checkalloc_buffer(struct channel *ch)
++{
++	if (ch->trans_skb == NULL)
++		return ctcm_ch_alloc_buffer(ch);
++	if (ch->flags & CHANNEL_FLAGS_BUFSIZE_CHANGED) {
++		dev_kfree_skb(ch->trans_skb);
++		return ctcm_ch_alloc_buffer(ch);
++	}
++	return 0;
++}
++
++struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
++
++/* test if protocol attribute (of struct ctcm_priv or struct channel)
++ * has MPC protocol setting. Type is not checked
++ */
++#define IS_MPC(p) ((p)->protocol == CTCM_PROTO_MPC)
++
++/* test if struct ctcm_priv of struct net_device has MPC protocol setting */
++#define IS_MPCDEV(d) IS_MPC((struct ctcm_priv *)d->priv)
++
++static inline gfp_t gfp_type(void)
++{
++	return in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
++}
++
++/*
++ * Definition of our link level header.
++ */
++struct ll_header {
++	__u16 length;
++	__u16 type;
++	__u16 unused;
++};
++#define LL_HEADER_LENGTH (sizeof(struct ll_header))
++
++#endif
+diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
+new file mode 100644
+index 0000000..044adde
+--- /dev/null
++++ b/drivers/s390/net/ctcm_mpc.c
+@@ -0,0 +1,2472 @@
++/*
++ *	drivers/s390/net/ctcm_mpc.c
++ *
++ *	Copyright IBM Corp. 2004, 2007
++ *	Authors:	Belinda Thompson (belindat at us.ibm.com)
++ *			Andy Richter (richtera at us.ibm.com)
++ *			Peter Tiedemann (ptiedem at de.ibm.com)
++ */
++
++/*
++	This module exports functions to be used by CCS:
++	EXPORT_SYMBOL(ctc_mpc_alloc_channel);
++	EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
++	EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
++	EXPORT_SYMBOL(ctc_mpc_flow_control);
++*/
++
++#undef DEBUG
++#undef DEBUGDATA
++#undef DEBUGCCW
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/sched.h>
++
++#include <linux/signal.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++
++#include <linux/ip.h>
++#include <linux/if_arp.h>
++#include <linux/tcp.h>
++#include <linux/skbuff.h>
++#include <linux/ctype.h>
++#include <linux/netdevice.h>
++#include <net/dst.h>
++
++#include <linux/io.h>		/* instead of <asm/io.h> ok ? */
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++#include <linux/bitops.h>	/* instead of <asm/bitops.h> ok ? */
++#include <linux/uaccess.h>	/* instead of <asm/uaccess.h> ok ? */
++#include <linux/wait.h>
++#include <linux/moduleparam.h>
++#include <asm/idals.h>
++
++#include "cu3088.h"
++#include "ctcm_mpc.h"
++#include "ctcm_main.h"
++#include "ctcm_fsms.h"
++
++static const struct xid2 init_xid = {
++	.xid2_type_id	=	XID_FM2,
++	.xid2_len	=	0x45,
++	.xid2_adj_id	=	0,
++	.xid2_rlen	=	0x31,
++	.xid2_resv1	=	0,
++	.xid2_flag1	=	0,
++	.xid2_fmtt	=	0,
++	.xid2_flag4	=	0x80,
++	.xid2_resv2	=	0,
++	.xid2_tgnum	=	0,
++	.xid2_sender_id	=	0,
++	.xid2_flag2	=	0,
++	.xid2_option	=	XID2_0,
++	.xid2_resv3	=	"\x00",
++	.xid2_resv4	=	0,
++	.xid2_dlc_type	=	XID2_READ_SIDE,
++	.xid2_resv5	=	0,
++	.xid2_mpc_flag	=	0,
++	.xid2_resv6	=	0,
++	.xid2_buf_len	=	(MPC_BUFSIZE_DEFAULT - 35),
++};
++
++static const struct th_header thnorm = {
++	.th_seg		=	0x00,
++	.th_ch_flag	=	TH_IS_XID,
++	.th_blk_flag	=	TH_DATA_IS_XID,
++	.th_is_xid	=	0x01,
++	.th_seq_num	=	0x00000000,
++};
++
++static const struct th_header thdummy = {
++	.th_seg		=	0x00,
++	.th_ch_flag	=	0x00,
++	.th_blk_flag	=	TH_DATA_IS_XID,
++	.th_is_xid	=	0x01,
++	.th_seq_num	=	0x00000000,
++};
++
++/*
++ * Definition of one MPC group
++ */
++
++/*
++ * Compatibility macros for busy handling
++ * of network devices.
++ */
++
++static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb);
++
++/*
++ * MPC Group state machine actions (static prototypes)
++ */
++static void mpc_action_nop(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg);
++static void mpc_action_timeout(fsm_instance *fi, int event, void *arg);
++static int  mpc_validate_xid(struct mpcg_info *mpcginfo);
++static void mpc_action_yside_xid(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_xside_xid(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg);
++
++#ifdef DEBUGDATA
++/*-------------------------------------------------------------------*
++* Dump buffer format						     *
++*								     *
++*--------------------------------------------------------------------*/
++void ctcmpc_dumpit(char *buf, int len)
++{
++	__u32	ct, sw, rm, dup;
++	char	*ptr, *rptr;
++	char	tbuf[82], tdup[82];
++	#if (UTS_MACHINE == s390x)
++	char	addr[22];
++	#else
++	char	addr[12];
++	#endif
++	char	boff[12];
++	char	bhex[82], duphex[82];
++	char	basc[40];
++
++	sw  = 0;
++	rptr = ptr = buf;
++	rm  = 16;
++	duphex[0] = 0x00;
++	dup = 0;
++
++	for (ct = 0; ct < len; ct++, ptr++, rptr++) {
++		if (sw == 0) {
++			#if (UTS_MACHINE == s390x)
++			sprintf(addr, "%16.16lx", (unsigned long)rptr);
++			#else
++			sprintf(addr, "%8.8X", (__u32)rptr);
++			#endif
++
++			sprintf(boff, "%4.4X", (__u32)ct);
++			bhex[0] = '\0';
++			basc[0] = '\0';
++		}
++		if ((sw == 4) || (sw == 12))
++			strcat(bhex, " ");
++		if (sw == 8)
++			strcat(bhex, "	");
++
++		#if (UTS_MACHINE == s390x)
++		sprintf(tbuf, "%2.2lX", (unsigned long)*ptr);
++		#else
++		sprintf(tbuf, "%2.2X", (__u32)*ptr);
++		#endif
++
++		tbuf[2] = '\0';
++		strcat(bhex, tbuf);
++		if ((0 != isprint(*ptr)) && (*ptr >= 0x20))
++			basc[sw] = *ptr;
++		else
++			basc[sw] = '.';
++
++		basc[sw+1] = '\0';
++		sw++;
++		rm--;
++		if (sw == 16) {
++			if ((strcmp(duphex, bhex)) != 0) {
++				if (dup != 0) {
++					sprintf(tdup, "Duplicate as above "
++						"to %s", addr);
++					printk(KERN_INFO "		  "
++						"     --- %s ---\n", tdup);
++				}
++				printk(KERN_INFO "   %s (+%s) : %s  [%s]\n",
++					addr, boff, bhex, basc);
++				dup = 0;
++				strcpy(duphex, bhex);
++			} else
++				dup++;
++
++			sw = 0;
++			rm = 16;
++		}
++	}  /* endfor */
++
++	if (sw != 0) {
++		for ( ; rm > 0; rm--, sw++) {
++			if ((sw == 4) || (sw == 12))
++				strcat(bhex, " ");
++			if (sw == 8)
++				strcat(bhex, "	");
++			strcat(bhex, "	");
++			strcat(basc, " ");
++		}
++		if (dup != 0) {
++			sprintf(tdup, "Duplicate as above to %s", addr);
++			printk(KERN_INFO "		  "
++				"     --- %s ---\n", tdup);
++		}
++		printk(KERN_INFO "   %s (+%s) : %s  [%s]\n",
++			addr, boff, bhex, basc);
++	} else {
++		if (dup >= 1) {
++			sprintf(tdup, "Duplicate as above to %s", addr);
++			printk(KERN_INFO "		  "
++				"     --- %s ---\n", tdup);
++		}
++		if (dup != 0) {
++			printk(KERN_INFO "   %s (+%s) : %s  [%s]\n",
++				addr, boff, bhex, basc);
++		}
++	}
++
++	return;
++
++}   /*	 end of ctcmpc_dumpit  */
++#endif
++
++#ifdef DEBUGDATA
++/*
++ * Dump header and first 16 bytes of an sk_buff for debugging purposes.
++ *
++ * skb		The sk_buff to dump.
++ * offset	Offset relative to skb-data, where to start the dump.
++ */
++void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
++{
++	unsigned char *p = skb->data;
++	struct th_header *header;
++	struct pdu *pheader;
++	int bl = skb->len;
++	int i;
++
++	if (p == NULL)
++		return;
++
++	p += offset;
++	header = (struct th_header *)p;
++
++	printk(KERN_INFO "dump:\n");
++	printk(KERN_INFO "skb len=%d \n", skb->len);
++	if (skb->len > 2) {
++		switch (header->th_ch_flag) {
++		case TH_HAS_PDU:
++			break;
++		case 0x00:
++		case TH_IS_XID:
++			if ((header->th_blk_flag == TH_DATA_IS_XID) &&
++			   (header->th_is_xid == 0x01))
++				goto dumpth;
++		case TH_SWEEP_REQ:
++				goto dumpth;
++		case TH_SWEEP_RESP:
++				goto dumpth;
++		default:
++			break;
++		}
++
++		pheader = (struct pdu *)p;
++		printk(KERN_INFO "pdu->offset: %d hex: %04x\n",
++		       pheader->pdu_offset, pheader->pdu_offset);
++		printk(KERN_INFO "pdu->flag  : %02x\n", pheader->pdu_flag);
++		printk(KERN_INFO "pdu->proto : %02x\n", pheader->pdu_proto);
++		printk(KERN_INFO "pdu->seq   : %02x\n", pheader->pdu_seq);
++					goto dumpdata;
++
++dumpth:
++		printk(KERN_INFO "th->seg     : %02x\n", header->th_seg);
++		printk(KERN_INFO "th->ch      : %02x\n", header->th_ch_flag);
++		printk(KERN_INFO "th->blk_flag: %02x\n", header->th_blk_flag);
++		printk(KERN_INFO "th->type    : %s\n",
++		       (header->th_is_xid) ? "DATA" : "XID");
++		printk(KERN_INFO "th->seqnum  : %04x\n", header->th_seq_num);
++
++	}
++dumpdata:
++	if (bl > 32)
++		bl = 32;
++	printk(KERN_INFO "data: ");
++	for (i = 0; i < bl; i++)
++		printk(KERN_INFO "%02x%s", *p++, (i % 16) ? " " : "\n<7>");
++	printk(KERN_INFO "\n");
++}
++#endif
++
++/*
++ * ctc_mpc_alloc_channel
++ *	(exported interface)
++ *
++ * Device Initialization :
++ *	ACTPATH  driven IO operations
++ */
++int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
++{
++	char device[20];
++	struct net_device *dev;
++	struct mpc_group *grp;
++	struct ctcm_priv *priv;
++
++	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
++
++	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
++	dev = __dev_get_by_name(&init_net, device);
++
++	if (dev == NULL) {
++		printk(KERN_INFO "ctc_mpc_alloc_channel %s dev=NULL\n", device);
++		return 1;
++	}
++
++	priv = dev->priv;
++	grp = priv->mpcg;
++	if (!grp)
++		return 1;
++
++	grp->allochanfunc = callback;
++	grp->port_num = port_num;
++	grp->port_persist = 1;
++
++	ctcm_pr_debug("ctcmpc: %s called for device %s state=%s\n",
++		       __FUNCTION__,
++		       dev->name,
++		       fsm_getstate_str(grp->fsm));
++
++	switch (fsm_getstate(grp->fsm)) {
++	case MPCG_STATE_INOP:
++		/* Group is in the process of terminating */
++		grp->alloc_called = 1;
++		break;
++	case MPCG_STATE_RESET:
++		/* MPC Group will transition to state		  */
++		/* MPCG_STATE_XID2INITW iff the minimum number	  */
++		/* of 1 read and 1 write channel have successfully*/
++		/* activated					  */
++		/*fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);*/
++		if (callback)
++			grp->send_qllc_disc = 1;
++	case MPCG_STATE_XID0IOWAIT:
++		fsm_deltimer(&grp->timer);
++		grp->outstanding_xid2 = 0;
++		grp->outstanding_xid7 = 0;
++		grp->outstanding_xid7_p2 = 0;
++		grp->saved_xid2 = NULL;
++		if (callback)
++			ctcm_open(dev);
++		fsm_event(priv->fsm, DEV_EVENT_START, dev);
++		break;
++	case MPCG_STATE_READY:
++		/* XID exchanges completed after PORT was activated */
++		/* Link station already active			    */
++		/* Maybe timing issue...retry callback		    */
++		grp->allocchan_callback_retries++;
++		if (grp->allocchan_callback_retries < 4) {
++			if (grp->allochanfunc)
++				grp->allochanfunc(grp->port_num,
++					      grp->group_max_buflen);
++		} else {
++			/* there are problems...bail out	    */
++			/* there may be a state mismatch so restart */
++			grp->port_persist = 1;
++			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++			grp->allocchan_callback_retries = 0;
++		}
++		break;
++	default:
++		return 0;
++
++	}
++
++	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
++	return 0;
++}
++EXPORT_SYMBOL(ctc_mpc_alloc_channel);
++
++/*
++ * ctc_mpc_establish_connectivity
++ *	(exported interface)
++ */
++void ctc_mpc_establish_connectivity(int port_num,
++				void (*callback)(int, int, int))
++{
++	char device[20];
++	struct net_device *dev;
++	struct mpc_group *grp;
++	struct ctcm_priv *priv;
++	struct channel *rch, *wch;
++
++	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
++
++	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
++	dev = __dev_get_by_name(&init_net, device);
++
++	if (dev == NULL) {
++		printk(KERN_INFO "ctc_mpc_establish_connectivity "
++				"%s dev=NULL\n", device);
++		return;
++	}
++	priv = dev->priv;
++	rch = priv->channel[READ];
++	wch = priv->channel[WRITE];
++
++	grp = priv->mpcg;
++
++	ctcm_pr_debug("ctcmpc: %s() called for device %s state=%s\n",
++			__FUNCTION__, dev->name,
++			fsm_getstate_str(grp->fsm));
++
++	grp->estconnfunc = callback;
++	grp->port_num = port_num;
++
++	switch (fsm_getstate(grp->fsm)) {
++	case MPCG_STATE_READY:
++		/* XID exchanges completed after PORT was activated */
++		/* Link station already active			    */
++		/* Maybe timing issue...retry callback		    */
++		fsm_deltimer(&grp->timer);
++		grp->estconn_callback_retries++;
++		if (grp->estconn_callback_retries < 4) {
++			if (grp->estconnfunc) {
++				grp->estconnfunc(grp->port_num, 0,
++						grp->group_max_buflen);
++				grp->estconnfunc = NULL;
++			}
++		} else {
++			/* there are problems...bail out	 */
++			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++			grp->estconn_callback_retries = 0;
++		}
++		break;
++	case MPCG_STATE_INOP:
++	case MPCG_STATE_RESET:
++		/* MPC Group is not ready to start XID - min num of */
++		/* 1 read and 1 write channel have not been acquired*/
++		printk(KERN_WARNING "ctcmpc: %s() REJECTED ACTIVE XID Req"
++			"uest - Channel Pair is not Active\n", __FUNCTION__);
++		if (grp->estconnfunc) {
++			grp->estconnfunc(grp->port_num, -1, 0);
++			grp->estconnfunc = NULL;
++		}
++		break;
++	case MPCG_STATE_XID2INITW:
++		/* alloc channel was called but no XID exchange    */
++		/* has occurred. initiate xside XID exchange	   */
++		/* make sure yside XID0 processing has not started */
++		if ((fsm_getstate(rch->fsm) > CH_XID0_PENDING) ||
++			(fsm_getstate(wch->fsm) > CH_XID0_PENDING)) {
++			printk(KERN_WARNING "mpc: %s() ABORT ACTIVE XID"
++			       " Request- PASSIVE XID in process\n"
++			       , __FUNCTION__);
++			break;
++		}
++		grp->send_qllc_disc = 1;
++		fsm_newstate(grp->fsm, MPCG_STATE_XID0IOWAIT);
++		fsm_deltimer(&grp->timer);
++		fsm_addtimer(&grp->timer, MPC_XID_TIMEOUT_VALUE,
++						MPCG_EVENT_TIMER, dev);
++		grp->outstanding_xid7 = 0;
++		grp->outstanding_xid7_p2 = 0;
++		grp->saved_xid2 = NULL;
++		if ((rch->in_mpcgroup) &&
++				(fsm_getstate(rch->fsm) == CH_XID0_PENDING))
++			fsm_event(grp->fsm, MPCG_EVENT_XID0DO, rch);
++		else {
++			printk(KERN_WARNING "mpc: %s() Unable to start"
++			       " ACTIVE XID0 on read channel\n",
++			       __FUNCTION__);
++			if (grp->estconnfunc) {
++				grp->estconnfunc(grp->port_num, -1, 0);
++				grp->estconnfunc = NULL;
++			}
++			fsm_deltimer(&grp->timer);
++				goto done;
++		}
++		if ((wch->in_mpcgroup) &&
++				(fsm_getstate(wch->fsm) == CH_XID0_PENDING))
++			fsm_event(grp->fsm, MPCG_EVENT_XID0DO, wch);
++		else {
++			printk(KERN_WARNING "mpc: %s() Unable to start"
++				" ACTIVE XID0 on write channel\n",
++					__FUNCTION__);
++			if (grp->estconnfunc) {
++				grp->estconnfunc(grp->port_num, -1, 0);
++				grp->estconnfunc = NULL;
++			}
++			fsm_deltimer(&grp->timer);
++				goto done;
++			}
++		break;
++	case MPCG_STATE_XID0IOWAIT:
++		/* already in active XID negotiations */
++	default:
++		break;
++	}
++
++done:
++	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
++	return;
++}
++EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
++
++/*
++ * ctc_mpc_dealloc_ch
++ *	(exported interface)
++ */
++void ctc_mpc_dealloc_ch(int port_num)
++{
++	struct net_device *dev;
++	char device[20];
++	struct ctcm_priv *priv;
++	struct mpc_group *grp;
++
++	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
++	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
++	dev = __dev_get_by_name(&init_net, device);
++
++	if (dev == NULL) {
++		printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
++					goto done;
++	}
++
++	ctcm_pr_debug("ctcmpc:%s %s() called for device %s refcount=%d\n",
++			dev->name, __FUNCTION__,
++			dev->name, atomic_read(&dev->refcnt));
++
++	priv = dev->priv;
++	if (priv == NULL) {
++		printk(KERN_INFO "%s() %s priv=NULL\n",
++				__FUNCTION__, device);
++					goto done;
++	}
++	fsm_deltimer(&priv->restart_timer);
++
++	grp = priv->mpcg;
++	if (grp == NULL) {
++		printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
++					goto done;
++	}
++	grp->channels_terminating = 0;
++
++	fsm_deltimer(&grp->timer);
++
++	grp->allochanfunc = NULL;
++	grp->estconnfunc = NULL;
++	grp->port_persist = 0;
++	grp->send_qllc_disc = 0;
++	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++
++	ctcm_close(dev);
++done:
++	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
++	return;
++}
++EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
++
++/*
++ * ctc_mpc_flow_control
++ *	(exported interface)
++ */
++void ctc_mpc_flow_control(int port_num, int flowc)
++{
++	char device[20];
++	struct ctcm_priv *priv;
++	struct mpc_group *grp;
++	struct net_device *dev;
++	struct channel *rch;
++	int mpcg_state;
++
++	ctcm_pr_debug("ctcmpc enter:	%s() %i\n", __FUNCTION__, flowc);
++
++	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
++	dev = __dev_get_by_name(&init_net, device);
++
++	if (dev == NULL) {
++		printk(KERN_INFO "ctc_mpc_flow_control %s dev=NULL\n", device);
++		return;
++	}
++
++	ctcm_pr_debug("ctcmpc: %s %s called \n", dev->name, __FUNCTION__);
++
++	priv  = dev->priv;
++	if (priv == NULL) {
++		printk(KERN_INFO "ctcmpc:%s() %s priv=NULL\n",
++		       __FUNCTION__, device);
++		return;
++	}
++	grp = priv->mpcg;
++	rch = priv->channel[READ];
++
++	mpcg_state = fsm_getstate(grp->fsm);
++	switch (flowc) {
++	case 1:
++		if (mpcg_state == MPCG_STATE_FLOWC)
++			break;
++		if (mpcg_state == MPCG_STATE_READY) {
++			if (grp->flow_off_called == 1)
++				grp->flow_off_called = 0;
++			else
++				fsm_newstate(grp->fsm, MPCG_STATE_FLOWC);
++			break;
++		}
++		break;
++	case 0:
++		if (mpcg_state == MPCG_STATE_FLOWC) {
++			fsm_newstate(grp->fsm, MPCG_STATE_READY);
++			/* ensure any data that has accumulated */
++			/* on the io_queue will now be sen t	*/
++			tasklet_schedule(&rch->ch_tasklet);
++		}
++		/* possible race condition			*/
++		if (mpcg_state == MPCG_STATE_READY) {
++			grp->flow_off_called = 1;
++			break;
++		}
++		break;
++	}
++
++	ctcm_pr_debug("ctcmpc exit:  %s() %i\n", __FUNCTION__, flowc);
++}
++EXPORT_SYMBOL(ctc_mpc_flow_control);
++
++static int mpc_send_qllc_discontact(struct net_device *);
++
++/*
++ * helper function of ctcmpc_unpack_skb
++*/
++static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo)
++{
++	struct channel	  *rch = mpcginfo->ch;
++	struct net_device *dev = rch->netdev;
++	struct ctcm_priv   *priv = dev->priv;
++	struct mpc_group  *grp = priv->mpcg;
++	struct channel	  *ch = priv->channel[WRITE];
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
++			__FUNCTION__, ch, ch->id);
++
++	if (do_debug_data)
++		ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
++
++	grp->sweep_rsp_pend_num--;
++
++	if ((grp->sweep_req_pend_num == 0) &&
++			(grp->sweep_rsp_pend_num == 0)) {
++		fsm_deltimer(&ch->sweep_timer);
++		grp->in_sweep = 0;
++		rch->th_seq_num = 0x00;
++		ch->th_seq_num = 0x00;
++		ctcm_clear_busy_do(dev);
++	}
++
++	kfree(mpcginfo);
++
++	return;
++
++}
++
++/*
++ * helper function of mpc_rcvd_sweep_req
++ * which is a helper of ctcmpc_unpack_skb
++ */
++static void ctcmpc_send_sweep_resp(struct channel *rch)
++{
++	struct net_device *dev = rch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++	struct mpc_group *grp = priv->mpcg;
++	int rc = 0;
++	struct th_sweep *header;
++	struct sk_buff *sweep_skb;
++	struct channel *ch  = priv->channel[WRITE];
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++			__FUNCTION__, rch, rch->id);
++
++	sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
++				    GFP_ATOMIC|GFP_DMA);
++	if (sweep_skb == NULL) {
++		printk(KERN_INFO "Couldn't alloc sweep_skb\n");
++		rc = -ENOMEM;
++				goto done;
++	}
++
++	header = (struct th_sweep *)
++			kmalloc(sizeof(struct th_sweep), gfp_type());
++
++	if (!header) {
++		dev_kfree_skb_any(sweep_skb);
++		rc = -ENOMEM;
++				goto done;
++	}
++
++	header->th.th_seg	= 0x00 ;
++	header->th.th_ch_flag	= TH_SWEEP_RESP;
++	header->th.th_blk_flag	= 0x00;
++	header->th.th_is_xid	= 0x00;
++	header->th.th_seq_num	= 0x00;
++	header->sw.th_last_seq	= ch->th_seq_num;
++
++	memcpy(skb_put(sweep_skb, TH_SWEEP_LENGTH), header, TH_SWEEP_LENGTH);
++
++	kfree(header);
++
++	dev->trans_start = jiffies;
++	skb_queue_tail(&ch->sweep_queue, sweep_skb);
++
++	fsm_addtimer(&ch->sweep_timer, 100, CTC_EVENT_RSWEEP_TIMER, ch);
++
++	return;
++
++done:
++	if (rc != 0) {
++		grp->in_sweep = 0;
++		ctcm_clear_busy_do(dev);
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++	}
++
++	return;
++}
++
++/*
++ * helper function of ctcmpc_unpack_skb
++ */
++static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo)
++{
++	struct channel	  *rch     = mpcginfo->ch;
++	struct net_device *dev     = rch->netdev;
++	struct ctcm_priv  *priv = dev->priv;
++	struct mpc_group  *grp  = priv->mpcg;
++	struct channel	  *ch	   = priv->channel[WRITE];
++
++	if (do_debug)
++		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
++			" %s(): ch=0x%p id=%s\n", __FUNCTION__, ch, ch->id);
++
++	if (grp->in_sweep == 0) {
++		grp->in_sweep = 1;
++		ctcm_test_and_set_busy(dev);
++		grp->sweep_req_pend_num = grp->active_channels[READ];
++		grp->sweep_rsp_pend_num = grp->active_channels[READ];
++	}
++
++	if (do_debug_data)
++		ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
++
++	grp->sweep_req_pend_num--;
++	ctcmpc_send_sweep_resp(ch);
++	kfree(mpcginfo);
++	return;
++}
++
++/*
++  * MPC Group Station FSM definitions
++ */
++static const char *mpcg_event_names[] = {
++	[MPCG_EVENT_INOP]	= "INOP Condition",
++	[MPCG_EVENT_DISCONC]	= "Discontact Received",
++	[MPCG_EVENT_XID0DO]	= "Channel Active - Start XID",
++	[MPCG_EVENT_XID2]	= "XID2 Received",
++	[MPCG_EVENT_XID2DONE]	= "XID0 Complete",
++	[MPCG_EVENT_XID7DONE]	= "XID7 Complete",
++	[MPCG_EVENT_TIMER]	= "XID Setup Timer",
++	[MPCG_EVENT_DOIO]	= "XID DoIO",
++};
++
++static const char *mpcg_state_names[] = {
++	[MPCG_STATE_RESET]	= "Reset",
++	[MPCG_STATE_INOP]	= "INOP",
++	[MPCG_STATE_XID2INITW]	= "Passive XID- XID0 Pending Start",
++	[MPCG_STATE_XID2INITX]	= "Passive XID- XID0 Pending Complete",
++	[MPCG_STATE_XID7INITW]	= "Passive XID- XID7 Pending P1 Start",
++	[MPCG_STATE_XID7INITX]	= "Passive XID- XID7 Pending P2 Complete",
++	[MPCG_STATE_XID0IOWAIT]	= "Active  XID- XID0 Pending Start",
++	[MPCG_STATE_XID0IOWAIX]	= "Active  XID- XID0 Pending Complete",
++	[MPCG_STATE_XID7INITI]	= "Active  XID- XID7 Pending Start",
++	[MPCG_STATE_XID7INITZ]	= "Active  XID- XID7 Pending Complete ",
++	[MPCG_STATE_XID7INITF]	= "XID        - XID7 Complete ",
++	[MPCG_STATE_FLOWC]	= "FLOW CONTROL ON",
++	[MPCG_STATE_READY]	= "READY",
++};
++
++/*
++ * The MPC Group Station FSM
++ *   22 events
++ */
++static const fsm_node mpcg_fsm[] = {
++	{ MPCG_STATE_RESET,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_INOP,	MPCG_EVENT_INOP,	mpc_action_nop        },
++	{ MPCG_STATE_FLOWC,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++
++	{ MPCG_STATE_READY,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
++	{ MPCG_STATE_READY,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++
++	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_XID0DO,	mpc_action_doxid0     },
++	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid0  },
++	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
++	{ MPCG_STATE_XID2INITW,	MPCG_EVENT_DOIO,	mpc_action_yside_xid  },
++
++	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_XID0DO,	mpc_action_doxid0     },
++	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid0  },
++	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
++	{ MPCG_STATE_XID2INITX,	MPCG_EVENT_DOIO,	mpc_action_yside_xid  },
++
++	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_XID2DONE,	mpc_action_doxid7     },
++	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
++	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid7  },
++	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
++	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_XID7DONE,	mpc_action_doxid7     },
++	{ MPCG_STATE_XID7INITW,	MPCG_EVENT_DOIO,	mpc_action_yside_xid  },
++
++	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
++	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid7  },
++	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_XID7DONE,	mpc_action_doxid7     },
++	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
++	{ MPCG_STATE_XID7INITX,	MPCG_EVENT_DOIO,	mpc_action_yside_xid  },
++
++	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_XID0DO,	mpc_action_doxid0     },
++	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_DISCONC,	mpc_action_discontact },
++	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_XID2,	mpc_action_rcvd_xid0  },
++	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_TIMER,	mpc_action_timeout    },
++	{ MPCG_STATE_XID0IOWAIT, MPCG_EVENT_DOIO,	mpc_action_xside_xid  },
++
++	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_XID0DO,	mpc_action_doxid0     },
++	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_DISCONC,	mpc_action_discontact },
++	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_XID2,	mpc_action_rcvd_xid0  },
++	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_TIMER,	mpc_action_timeout    },
++	{ MPCG_STATE_XID0IOWAIX, MPCG_EVENT_DOIO,	mpc_action_xside_xid  },
++
++	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_XID2DONE,	mpc_action_doxid7     },
++	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid7  },
++	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
++	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
++	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_XID7DONE,	mpc_action_doxid7     },
++	{ MPCG_STATE_XID7INITI,	MPCG_EVENT_DOIO,	mpc_action_xside_xid  },
++
++	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_XID2,	mpc_action_rcvd_xid7  },
++	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_XID7DONE,	mpc_action_doxid7     },
++	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_DISCONC,	mpc_action_discontact },
++	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_TIMER,	mpc_action_timeout    },
++	{ MPCG_STATE_XID7INITZ,	MPCG_EVENT_DOIO,	mpc_action_xside_xid  },
++
++	{ MPCG_STATE_XID7INITF,	MPCG_EVENT_INOP,	mpc_action_go_inop    },
++	{ MPCG_STATE_XID7INITF,	MPCG_EVENT_XID7DONE,	mpc_action_go_ready   },
++};
++
++static int mpcg_fsm_len = ARRAY_SIZE(mpcg_fsm);
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
++{
++	struct net_device *dev = arg;
++	struct ctcm_priv *priv = NULL;
++	struct mpc_group *grp = NULL;
++
++	if (dev == NULL) {
++		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++		return;
++	}
++
++	ctcm_pr_debug("ctcmpc enter: %s  %s()\n", dev->name, __FUNCTION__);
++
++	priv = dev->priv;
++	if (priv == NULL) {
++		printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
++		return;
++	}
++
++	grp = priv->mpcg;
++	if (grp == NULL) {
++		printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
++		return;
++	}
++
++	fsm_deltimer(&grp->timer);
++
++	if (grp->saved_xid2->xid2_flag2 == 0x40) {
++		priv->xid->xid2_flag2 = 0x00;
++		if (grp->estconnfunc) {
++			grp->estconnfunc(grp->port_num, 1,
++					grp->group_max_buflen);
++			grp->estconnfunc = NULL;
++		} else if (grp->allochanfunc)
++			grp->send_qllc_disc = 1;
++					goto done;
++	}
++
++	grp->port_persist = 1;
++	grp->out_of_sequence = 0;
++	grp->estconn_called = 0;
++
++	tasklet_hi_schedule(&grp->mpc_tasklet2);
++
++	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
++	return;
++
++done:
++	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++
++
++	ctcm_pr_info("ctcmpc: %s()failure occurred\n", __FUNCTION__);
++}
++
++/*
++ * helper of ctcm_init_netdevice
++ * CTCM_PROTO_MPC only
++ */
++void mpc_group_ready(unsigned long adev)
++{
++	struct net_device *dev = (struct net_device *)adev;
++	struct ctcm_priv *priv = NULL;
++	struct mpc_group  *grp = NULL;
++	struct channel *ch = NULL;
++
++
++	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
++
++	if (dev == NULL) {
++		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++		return;
++	}
++
++	priv = dev->priv;
++	if (priv == NULL) {
++		printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
++		return;
++	}
++
++	grp = priv->mpcg;
++	if (grp == NULL) {
++		printk(KERN_INFO "ctcmpc:%s() grp=NULL\n", __FUNCTION__);
++		return;
++	}
++
++	printk(KERN_NOTICE "ctcmpc: %s GROUP TRANSITIONED TO READY"
++	       "  maxbuf:%d\n",
++	       dev->name, grp->group_max_buflen);
++
++	fsm_newstate(grp->fsm, MPCG_STATE_READY);
++
++	/* Put up a read on the channel */
++	ch = priv->channel[READ];
++	ch->pdu_seq = 0;
++	if (do_debug_data)
++		ctcm_pr_debug("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
++			__FUNCTION__, ch->pdu_seq);
++
++	ctcmpc_chx_rxidle(ch->fsm, CTC_EVENT_START, ch);
++	/* Put the write channel in idle state */
++	ch = priv->channel[WRITE];
++	if (ch->collect_len > 0) {
++		spin_lock(&ch->collect_lock);
++		ctcm_purge_skb_queue(&ch->collect_queue);
++		ch->collect_len = 0;
++		spin_unlock(&ch->collect_lock);
++	}
++	ctcm_chx_txidle(ch->fsm, CTC_EVENT_START, ch);
++
++	ctcm_clear_busy(dev);
++
++	if (grp->estconnfunc) {
++		grp->estconnfunc(grp->port_num, 0,
++				    grp->group_max_buflen);
++		grp->estconnfunc = NULL;
++	} else
++		if (grp->allochanfunc)
++		grp->allochanfunc(grp->port_num,
++				     grp->group_max_buflen);
++
++	grp->send_qllc_disc = 1;
++	grp->changed_side = 0;
++
++	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
++	return;
++
++}
++
++/*
++ * Increment the MPC Group Active Channel Counts
++ * helper of dev_action (called from channel fsm)
++ */
++int mpc_channel_action(struct channel *ch, int direction, int action)
++{
++	struct net_device  *dev     = ch->netdev;
++	struct ctcm_priv    *priv;
++	struct mpc_group   *grp  = NULL;
++	int	    rc = 0;
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
++			__FUNCTION__, ch, ch->id);
++
++	if (dev == NULL) {
++		printk(KERN_INFO "ctcmpc_channel_action %i dev=NULL\n",
++		       action);
++		rc = 1;
++					goto done;
++	}
++
++	priv = dev->priv;
++	if (priv == NULL) {
++		printk(KERN_INFO
++		       "ctcmpc_channel_action%i priv=NULL, dev=%s\n",
++		       action, dev->name);
++		rc = 2;
++					goto done;
++	}
++
++	grp = priv->mpcg;
++
++	if (grp == NULL) {
++		printk(KERN_INFO "ctcmpc: %s()%i mpcgroup=NULL, dev=%s\n",
++		       __FUNCTION__, action, dev->name);
++		rc = 3;
++					goto done;
++	}
++
++	ctcm_pr_info(
++		      "ctcmpc: %s() %i(): Grp:%s total_channel_paths=%i "
++		      "active_channels read=%i, write=%i\n",
++		      __FUNCTION__,
++		      action,
++		      fsm_getstate_str(grp->fsm),
++		      grp->num_channel_paths,
++		      grp->active_channels[READ],
++		      grp->active_channels[WRITE]);
++
++	if ((action == MPC_CHANNEL_ADD) && (ch->in_mpcgroup == 0)) {
++		grp->num_channel_paths++;
++		grp->active_channels[direction]++;
++		grp->outstanding_xid2++;
++		ch->in_mpcgroup = 1;
++
++		if (ch->xid_skb != NULL)
++			dev_kfree_skb_any(ch->xid_skb);
++
++		ch->xid_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
++					GFP_ATOMIC | GFP_DMA);
++		if (ch->xid_skb == NULL) {
++			printk(KERN_INFO "ctcmpc: %s()"
++			       "Couldn't alloc ch xid_skb\n", __FUNCTION__);
++			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++			return 1;
++		}
++		ch->xid_skb_data = ch->xid_skb->data;
++		ch->xid_th = (struct th_header *)ch->xid_skb->data;
++		skb_put(ch->xid_skb, TH_HEADER_LENGTH);
++		ch->xid = (struct xid2 *)skb_tail_pointer(ch->xid_skb);
++		skb_put(ch->xid_skb, XID2_LENGTH);
++		ch->xid_id = skb_tail_pointer(ch->xid_skb);
++		ch->xid_skb->data = ch->xid_skb_data;
++		skb_reset_tail_pointer(ch->xid_skb);
++		ch->xid_skb->len = 0;
++
++		memcpy(skb_put(ch->xid_skb, grp->xid_skb->len),
++				grp->xid_skb->data,
++				grp->xid_skb->len);
++
++		ch->xid->xid2_dlc_type = ((CHANNEL_DIRECTION(ch->flags) == READ)
++				? XID2_READ_SIDE : XID2_WRITE_SIDE);
++
++		if (CHANNEL_DIRECTION(ch->flags) == WRITE)
++			ch->xid->xid2_buf_len = 0x00;
++
++		ch->xid_skb->data = ch->xid_skb_data;
++		skb_reset_tail_pointer(ch->xid_skb);
++		ch->xid_skb->len = 0;
++
++		fsm_newstate(ch->fsm, CH_XID0_PENDING);
++
++		if ((grp->active_channels[READ]  > 0) &&
++		    (grp->active_channels[WRITE] > 0) &&
++			(fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
++			fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
++			printk(KERN_NOTICE "ctcmpc: %s MPC GROUP "
++					"CHANNELS ACTIVE\n", dev->name);
++		}
++	} else if ((action == MPC_CHANNEL_REMOVE) &&
++			(ch->in_mpcgroup == 1)) {
++		ch->in_mpcgroup = 0;
++		grp->num_channel_paths--;
++		grp->active_channels[direction]--;
++
++		if (ch->xid_skb != NULL)
++			dev_kfree_skb_any(ch->xid_skb);
++		ch->xid_skb = NULL;
++
++		if (grp->channels_terminating)
++					goto done;
++
++		if (((grp->active_channels[READ] == 0) &&
++					(grp->active_channels[WRITE] > 0))
++			|| ((grp->active_channels[WRITE] == 0) &&
++					(grp->active_channels[READ] > 0)))
++			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++	}
++
++done:
++
++	if (do_debug) {
++		ctcm_pr_debug(
++		       "ctcmpc: %s() %i Grp:%s ttl_chan_paths=%i "
++		       "active_chans read=%i, write=%i\n",
++		       __FUNCTION__,
++		       action,
++		       fsm_getstate_str(grp->fsm),
++		       grp->num_channel_paths,
++		       grp->active_channels[READ],
++		       grp->active_channels[WRITE]);
++
++		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++				__FUNCTION__, ch, ch->id);
++	}
++	return rc;
++
++}
++
++/**
++ * Unpack a just received skb and hand it over to
++ * upper layers.
++ * special MPC version of unpack_skb.
++ *
++ * ch		The channel where this skb has been received.
++ * pskb		The received skb.
++ */
++static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
++{
++	struct net_device *dev	= ch->netdev;
++	struct ctcm_priv *priv = dev->priv;
++	struct mpc_group *grp = priv->mpcg;
++	struct pdu *curr_pdu;
++	struct mpcg_info *mpcginfo;
++	struct th_header *header = NULL;
++	struct th_sweep *sweep = NULL;
++	int pdu_last_seen = 0;
++	__u32 new_len;
++	struct sk_buff *skb;
++	int skblen;
++	int sendrc = 0;
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc enter: %s() %s cp:%i ch:%s\n",
++		       __FUNCTION__, dev->name, smp_processor_id(), ch->id);
++
++	header = (struct th_header *)pskb->data;
++	if ((header->th_seg == 0) &&
++		(header->th_ch_flag == 0) &&
++		(header->th_blk_flag == 0) &&
++		(header->th_seq_num == 0))
++		/* nothing for us */	goto done;
++
++	if (do_debug_data) {
++		ctcm_pr_debug("ctcmpc: %s() th_header\n", __FUNCTION__);
++		ctcmpc_dumpit((char *)header, TH_HEADER_LENGTH);
++		ctcm_pr_debug("ctcmpc: %s() pskb len: %04x \n",
++		       __FUNCTION__, pskb->len);
++	}
++
++	pskb->dev = dev;
++	pskb->ip_summed = CHECKSUM_UNNECESSARY;
++	skb_pull(pskb, TH_HEADER_LENGTH);
++
++	if (likely(header->th_ch_flag == TH_HAS_PDU)) {
++		if (do_debug_data)
++			ctcm_pr_debug("ctcmpc: %s() came into th_has_pdu\n",
++			       __FUNCTION__);
++		if ((fsm_getstate(grp->fsm) == MPCG_STATE_FLOWC) ||
++		   ((fsm_getstate(grp->fsm) == MPCG_STATE_READY) &&
++		    (header->th_seq_num != ch->th_seq_num + 1) &&
++		    (ch->th_seq_num != 0))) {
++			/* This is NOT the next segment		*
++			 * we are not the correct race winner	*
++			 * go away and let someone else win	*
++			 * BUT..this only applies if xid negot	*
++			 * is done				*
++			*/
++			grp->out_of_sequence += 1;
++			__skb_push(pskb, TH_HEADER_LENGTH);
++			skb_queue_tail(&ch->io_queue, pskb);
++			if (do_debug_data)
++				ctcm_pr_debug("ctcmpc: %s() th_seq_num "
++				       "expect:%08x got:%08x\n", __FUNCTION__,
++				       ch->th_seq_num + 1, header->th_seq_num);
++
++			return;
++		}
++		grp->out_of_sequence = 0;
++		ch->th_seq_num = header->th_seq_num;
++
++		if (do_debug_data)
++			ctcm_pr_debug("ctcmpc: %s() FromVTAM_th_seq=%08x\n",
++			       __FUNCTION__, ch->th_seq_num);
++
++		if (unlikely(fsm_getstate(grp->fsm) != MPCG_STATE_READY))
++					goto done;
++		pdu_last_seen = 0;
++		while ((pskb->len > 0) && !pdu_last_seen) {
++			curr_pdu = (struct pdu *)pskb->data;
++			if (do_debug_data) {
++				ctcm_pr_debug("ctcm: %s() pdu_header\n",
++				       __FUNCTION__);
++				ctcmpc_dumpit((char *)pskb->data,
++						PDU_HEADER_LENGTH);
++				ctcm_pr_debug("ctcm: %s() pskb len: %04x \n",
++				       __FUNCTION__, pskb->len);
++			}
++			skb_pull(pskb, PDU_HEADER_LENGTH);
++
++			if (curr_pdu->pdu_flag & PDU_LAST)
++				pdu_last_seen = 1;
++			if (curr_pdu->pdu_flag & PDU_CNTL)
++				pskb->protocol = htons(ETH_P_SNAP);
++			else
++				pskb->protocol = htons(ETH_P_SNA_DIX);
++
++			if ((pskb->len <= 0) || (pskb->len > ch->max_bufsize)) {
++				printk(KERN_INFO
++				       "%s Illegal packet size %d "
++				       "received "
++				       "dropping\n", dev->name,
++				       pskb->len);
++				priv->stats.rx_dropped++;
++				priv->stats.rx_length_errors++;
++					goto done;
++			}
++			skb_reset_mac_header(pskb);
++			new_len = curr_pdu->pdu_offset;
++			if (do_debug_data)
++				ctcm_pr_debug("ctcmpc: %s() new_len: %04x \n",
++				       __FUNCTION__, new_len);
++			if ((new_len == 0) || (new_len > pskb->len)) {
++				/* should never happen		    */
++				/* pskb len must be hosed...bail out */
++				printk(KERN_INFO
++				       "ctcmpc: %s(): invalid pdu"
++				       " offset of %04x - data may be"
++				       "lost\n", __FUNCTION__, new_len);
++						goto done;
++			}
++			skb = __dev_alloc_skb(new_len+4, GFP_ATOMIC);
++
++			if (!skb) {
++				printk(KERN_INFO
++				       "ctcm: %s Out of memory in "
++				       "%s()- request-len:%04x \n",
++				       dev->name,
++				       __FUNCTION__,
++				       new_len+4);
++				priv->stats.rx_dropped++;
++				fsm_event(grp->fsm,
++					  MPCG_EVENT_INOP, dev);
++						goto done;
++			}
++
++			memcpy(skb_put(skb, new_len),
++					pskb->data, new_len);
++
++			skb_reset_mac_header(skb);
++			skb->dev = pskb->dev;
++			skb->protocol = pskb->protocol;
++			skb->ip_summed = CHECKSUM_UNNECESSARY;
++			*((__u32 *) skb_push(skb, 4)) = ch->pdu_seq;
++			ch->pdu_seq++;
++
++			if (do_debug_data)
++				ctcm_pr_debug("%s: ToDCM_pdu_seq= %08x\n",
++				       __FUNCTION__, ch->pdu_seq);
++
++			ctcm_pr_debug("ctcm: %s() skb:%0lx "
++				"skb len: %d \n", __FUNCTION__,
++			       (unsigned long)skb, skb->len);
++			if (do_debug_data) {
++				ctcm_pr_debug("ctcmpc: %s() up to 32 bytes"
++					       " of pdu_data sent\n",
++					       __FUNCTION__);
++				ctcmpc_dump32((char *)skb->data, skb->len);
++			}
++
++			skblen = skb->len;
++			sendrc = netif_rx(skb);
++			priv->stats.rx_packets++;
++			priv->stats.rx_bytes += skblen;
++			skb_pull(pskb, new_len); /* point to next PDU */
++		}
++	} else {
++		mpcginfo = (struct mpcg_info *)
++				kmalloc(sizeof(struct mpcg_info), gfp_type());
++		if (mpcginfo == NULL)
++					goto done;
++
++		mpcginfo->ch = ch;
++		mpcginfo->th = header;
++		mpcginfo->skb = pskb;
++		ctcm_pr_debug("ctcmpc: %s() Not PDU - may be control pkt\n",
++			       __FUNCTION__);
++		/*  it's a sweep?   */
++		sweep = (struct th_sweep *)pskb->data;
++		mpcginfo->sweep = sweep;
++		if (header->th_ch_flag == TH_SWEEP_REQ)
++			mpc_rcvd_sweep_req(mpcginfo);
++		else if (header->th_ch_flag == TH_SWEEP_RESP)
++			mpc_rcvd_sweep_resp(mpcginfo);
++		else if (header->th_blk_flag == TH_DATA_IS_XID) {
++			struct xid2 *thisxid = (struct xid2 *)pskb->data;
++			skb_pull(pskb, XID2_LENGTH);
++			mpcginfo->xid = thisxid;
++			fsm_event(grp->fsm, MPCG_EVENT_XID2, mpcginfo);
++		} else if (header->th_blk_flag == TH_DISCONTACT)
++			fsm_event(grp->fsm, MPCG_EVENT_DISCONC, mpcginfo);
++		else if (header->th_seq_num != 0) {
++			printk(KERN_INFO "%s unexpected packet"
++					" expected control pkt\n", dev->name);
++			priv->stats.rx_dropped++;
++			/* mpcginfo only used for non-data transfers */
++			kfree(mpcginfo);
++			if (do_debug_data)
++				ctcmpc_dump_skb(pskb, -8);
++		}
++	}
++done:
++
++	dev_kfree_skb_any(pskb);
++	if (sendrc == NET_RX_DROP) {
++		printk(KERN_WARNING "%s %s() NETWORK BACKLOG EXCEEDED"
++		       " - PACKET DROPPED\n", dev->name, __FUNCTION__);
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++	}
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
++				dev->name, __FUNCTION__, ch, ch->id);
++}
++
++/**
++ * tasklet helper for mpc's skb unpacking.
++ *
++ * ch		The channel to work on.
++ * Allow flow control back pressure to occur here.
++ * Throttling back channel can result in excessive
++ * channel inactivity and system deact of channel
++ */
++void ctcmpc_bh(unsigned long thischan)
++{
++	struct channel	  *ch	    = (struct channel *)thischan;
++	struct sk_buff	  *skb;
++	struct net_device *dev	    = ch->netdev;
++	struct ctcm_priv  *priv  = dev->priv;
++	struct mpc_group  *grp   = priv->mpcg;
++
++	if (do_debug)
++		ctcm_pr_debug("%s cp:%i enter:  %s() %s\n",
++		       dev->name, smp_processor_id(), __FUNCTION__, ch->id);
++	/* caller has requested driver to throttle back */
++	while ((fsm_getstate(grp->fsm) != MPCG_STATE_FLOWC) &&
++			(skb = skb_dequeue(&ch->io_queue))) {
++		ctcmpc_unpack_skb(ch, skb);
++		if (grp->out_of_sequence > 20) {
++			/* assume data loss has occurred if */
++			/* missing seq_num for extended     */
++			/* period of time		    */
++			grp->out_of_sequence = 0;
++			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++			break;
++		}
++		if (skb == skb_peek(&ch->io_queue))
++			break;
++	}
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
++			dev->name, __FUNCTION__, ch,  ch->id);
++	return;
++}
++
++/*
++ *  MPC Group Initializations
++ */
++struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
++{
++	struct mpc_group *grp;
++
++	CTCM_DBF_TEXT(MPC_SETUP, 3, __FUNCTION__);
++
++	grp = kzalloc(sizeof(struct mpc_group), GFP_KERNEL);
++	if (grp == NULL)
++		return NULL;
++
++	grp->fsm =
++		init_fsm("mpcg", mpcg_state_names, mpcg_event_names,
++				 MPCG_NR_STATES, MPCG_NR_EVENTS, mpcg_fsm,
++				 mpcg_fsm_len, GFP_KERNEL);
++	if (grp->fsm == NULL) {
++		kfree(grp);
++		return NULL;
++	}
++
++	fsm_newstate(grp->fsm, MPCG_STATE_RESET);
++	fsm_settimer(grp->fsm, &grp->timer);
++
++	grp->xid_skb =
++		 __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC | GFP_DMA);
++	if (grp->xid_skb == NULL) {
++		printk(KERN_INFO "Couldn't alloc MPCgroup xid_skb\n");
++		kfree_fsm(grp->fsm);
++		kfree(grp);
++		return NULL;
++	}
++	/*  base xid for all channels in group  */
++	grp->xid_skb_data = grp->xid_skb->data;
++	grp->xid_th = (struct th_header *)grp->xid_skb->data;
++	memcpy(skb_put(grp->xid_skb, TH_HEADER_LENGTH),
++			&thnorm, TH_HEADER_LENGTH);
++
++	grp->xid = (struct xid2 *) skb_tail_pointer(grp->xid_skb);
++	memcpy(skb_put(grp->xid_skb, XID2_LENGTH), &init_xid, XID2_LENGTH);
++	grp->xid->xid2_adj_id = jiffies | 0xfff00000;
++	grp->xid->xid2_sender_id = jiffies;
++
++	grp->xid_id = skb_tail_pointer(grp->xid_skb);
++	memcpy(skb_put(grp->xid_skb, 4), "VTAM", 4);
++
++	grp->rcvd_xid_skb =
++		__dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
++	if (grp->rcvd_xid_skb == NULL) {
++		printk(KERN_INFO "Couldn't alloc MPCgroup rcvd_xid_skb\n");
++		kfree_fsm(grp->fsm);
++		dev_kfree_skb(grp->xid_skb);
++		kfree(grp);
++		return NULL;
++	}
++	grp->rcvd_xid_data = grp->rcvd_xid_skb->data;
++	grp->rcvd_xid_th = (struct th_header *)grp->rcvd_xid_skb->data;
++	memcpy(skb_put(grp->rcvd_xid_skb, TH_HEADER_LENGTH),
++			&thnorm, TH_HEADER_LENGTH);
++	grp->saved_xid2 = NULL;
++	priv->xid = grp->xid;
++	priv->mpcg = grp;
++	return grp;
++}
++
++/*
++ * The MPC Group Station FSM
++ */
++
++/*
++ * MPC Group Station FSM actions
++ * CTCM_PROTO_MPC only
++ */
++
++/**
++ * NOP action for statemachines
++ */
++static void mpc_action_nop(fsm_instance *fi, int event, void *arg)
++{
++}
++
++/*
++ * invoked when the device transitions to dev_stopped
++ * MPC will stop each individual channel if a single XID failure
++ * occurs, or will intitiate all channels be stopped if a GROUP
++ * level failure occurs.
++ */
++static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
++{
++	struct net_device  *dev = arg;
++	struct ctcm_priv    *priv;
++	struct mpc_group *grp;
++	int rc = 0;
++	struct channel *wch, *rch;
++
++	if (dev == NULL) {
++		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++		return;
++	}
++
++	ctcm_pr_debug("ctcmpc enter: %s  %s()\n", dev->name, __FUNCTION__);
++
++	priv  = dev->priv;
++	grp =  priv->mpcg;
++	grp->flow_off_called = 0;
++
++	fsm_deltimer(&grp->timer);
++
++	if (grp->channels_terminating)
++					goto done;
++
++	grp->channels_terminating = 1;
++
++	grp->saved_state = fsm_getstate(grp->fsm);
++	fsm_newstate(grp->fsm, MPCG_STATE_INOP);
++	if (grp->saved_state > MPCG_STATE_XID7INITF)
++		printk(KERN_NOTICE "%s:MPC GROUP INOPERATIVE\n", dev->name);
++	if ((grp->saved_state != MPCG_STATE_RESET) ||
++		/* dealloc_channel has been called */
++		((grp->saved_state == MPCG_STATE_RESET) &&
++				(grp->port_persist == 0)))
++		fsm_deltimer(&priv->restart_timer);
++
++	wch = priv->channel[WRITE];
++	rch = priv->channel[READ];
++
++	switch (grp->saved_state) {
++	case MPCG_STATE_RESET:
++	case MPCG_STATE_INOP:
++	case MPCG_STATE_XID2INITW:
++	case MPCG_STATE_XID0IOWAIT:
++	case MPCG_STATE_XID2INITX:
++	case MPCG_STATE_XID7INITW:
++	case MPCG_STATE_XID7INITX:
++	case MPCG_STATE_XID0IOWAIX:
++	case MPCG_STATE_XID7INITI:
++	case MPCG_STATE_XID7INITZ:
++	case MPCG_STATE_XID7INITF:
++		break;
++	case MPCG_STATE_FLOWC:
++	case MPCG_STATE_READY:
++	default:
++		tasklet_hi_schedule(&wch->ch_disc_tasklet);
++	}
++
++	grp->xid2_tgnum = 0;
++	grp->group_max_buflen = 0;  /*min of all received */
++	grp->outstanding_xid2 = 0;
++	grp->outstanding_xid7 = 0;
++	grp->outstanding_xid7_p2 = 0;
++	grp->saved_xid2 = NULL;
++	grp->xidnogood = 0;
++	grp->changed_side = 0;
++
++	grp->rcvd_xid_skb->data = grp->rcvd_xid_data;
++	skb_reset_tail_pointer(grp->rcvd_xid_skb);
++	grp->rcvd_xid_skb->len = 0;
++	grp->rcvd_xid_th = (struct th_header *)grp->rcvd_xid_skb->data;
++	memcpy(skb_put(grp->rcvd_xid_skb, TH_HEADER_LENGTH), &thnorm,
++	       TH_HEADER_LENGTH);
++
++	if (grp->send_qllc_disc == 1) {
++		grp->send_qllc_disc = 0;
++		rc = mpc_send_qllc_discontact(dev);
++	}
++
++	/* DO NOT issue DEV_EVENT_STOP directly out of this code */
++	/* This can result in INOP of VTAM PU due to halting of  */
++	/* outstanding IO which causes a sense to be returned	 */
++	/* Only about 3 senses are allowed and then IOS/VTAM will*/
++	/* ebcome unreachable without manual intervention	 */
++	if ((grp->port_persist == 1)	|| (grp->alloc_called)) {
++		grp->alloc_called = 0;
++		fsm_deltimer(&priv->restart_timer);
++		fsm_addtimer(&priv->restart_timer,
++			     500,
++			     DEV_EVENT_RESTART,
++			     dev);
++		fsm_newstate(grp->fsm, MPCG_STATE_RESET);
++		if (grp->saved_state > MPCG_STATE_XID7INITF)
++			printk(KERN_NOTICE "%s:MPC GROUP RECOVERY SCHEDULED\n",
++			       dev->name);
++	} else {
++		fsm_deltimer(&priv->restart_timer);
++		fsm_addtimer(&priv->restart_timer, 500, DEV_EVENT_STOP, dev);
++		fsm_newstate(grp->fsm, MPCG_STATE_RESET);
++		printk(KERN_NOTICE "%s:MPC GROUP RECOVERY NOT ATTEMPTED\n",
++		       dev->name);
++	}
++
++done:
++	ctcm_pr_debug("ctcmpc exit:%s  %s()\n", dev->name, __FUNCTION__);
++	return;
++}
++
++/**
++ * Handle mpc group  action timeout.
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ *
++ * fi		An instance of an mpc_group fsm.
++ * event	The event, just happened.
++ * arg		Generic pointer, casted from net_device * upon call.
++ */
++static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
++{
++	struct net_device *dev = arg;
++	struct ctcm_priv *priv;
++	struct mpc_group *grp;
++	struct channel *wch;
++	struct channel *rch;
++
++	CTCM_DBF_TEXT(MPC_TRACE, 6, __FUNCTION__);
++
++	if (dev == NULL) {
++		CTCM_DBF_TEXT_(MPC_ERROR, 4, "%s: dev=NULL\n", __FUNCTION__);
++		return;
++	}
++
++	priv = dev->priv;
++	grp = priv->mpcg;
++	wch = priv->channel[WRITE];
++	rch = priv->channel[READ];
++
++	switch (fsm_getstate(grp->fsm)) {
++	case MPCG_STATE_XID2INITW:
++		/* Unless there is outstanding IO on the  */
++		/* channel just return and wait for ATTN  */
++		/* interrupt to begin XID negotiations	  */
++		if ((fsm_getstate(rch->fsm) == CH_XID0_PENDING) &&
++		   (fsm_getstate(wch->fsm) == CH_XID0_PENDING))
++			break;
++	default:
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++	}
++
++	CTCM_DBF_TEXT_(MPC_TRACE, 6, "%s: dev=%s exit",
++					__FUNCTION__, dev->name);
++	return;
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++void mpc_action_discontact(fsm_instance *fi, int event, void *arg)
++{
++	struct mpcg_info   *mpcginfo   = arg;
++	struct channel	   *ch	       = mpcginfo->ch;
++	struct net_device  *dev        = ch->netdev;
++	struct ctcm_priv   *priv    = dev->priv;
++	struct mpc_group   *grp     = priv->mpcg;
++
++	if (ch == NULL)	{
++		printk(KERN_INFO "%s() ch=NULL\n", __FUNCTION__);
++		return;
++	}
++	if (ch->netdev == NULL)	{
++		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++		return;
++	}
++
++	ctcm_pr_debug("ctcmpc enter: %s  %s()\n", dev->name, __FUNCTION__);
++
++	grp->send_qllc_disc = 1;
++	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++
++	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
++	return;
++}
++
++/*
++ * MPC Group Station - not part of FSM
++ * CTCM_PROTO_MPC only
++ * called from add_channel in ctcm_main.c
++ */
++void mpc_action_send_discontact(unsigned long thischan)
++{
++	struct channel	   *ch;
++	struct net_device  *dev;
++	struct ctcm_priv    *priv;
++	struct mpc_group   *grp;
++	int rc = 0;
++	unsigned long	  saveflags;
++
++	ch = (struct channel *)thischan;
++	dev = ch->netdev;
++	priv = dev->priv;
++	grp = priv->mpcg;
++
++	ctcm_pr_info("ctcmpc: %s cp:%i enter: %s() GrpState:%s ChState:%s\n",
++		       dev->name,
++		       smp_processor_id(),
++		       __FUNCTION__,
++		       fsm_getstate_str(grp->fsm),
++		       fsm_getstate_str(ch->fsm));
++	saveflags = 0;	/* avoids compiler warning with
++			   spin_unlock_irqrestore */
++
++	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++	rc = ccw_device_start(ch->cdev, &ch->ccw[15],
++					(unsigned long)ch, 0xff, 0);
++	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++
++	if (rc != 0) {
++		ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
++			       __FUNCTION__,
++			       ch->id);
++		ctcm_ccw_check_rc(ch, rc, "send discontact");
++		/* Not checking return code value here */
++		/* Making best effort to notify partner*/
++		/* that MPC Group is going down        */
++	}
++
++	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
++	return;
++}
++
++
++/*
++ * helper function of mpc FSM
++ * CTCM_PROTO_MPC only
++ * mpc_action_rcvd_xid7
++*/
++static int mpc_validate_xid(struct mpcg_info *mpcginfo)
++{
++	struct channel	   *ch	    = mpcginfo->ch;
++	struct net_device  *dev     = ch->netdev;
++	struct ctcm_priv   *priv = dev->priv;
++	struct mpc_group   *grp  = priv->mpcg;
++	struct xid2	   *xid     = mpcginfo->xid;
++	int	failed	= 0;
++	int	rc	= 0;
++	__u64	our_id, their_id = 0;
++	int	len;
++
++	len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++
++	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
++
++	if (mpcginfo->xid == NULL) {
++		printk(KERN_INFO "%s() xid=NULL\n", __FUNCTION__);
++		rc = 1;
++					goto done;
++	}
++
++	ctcm_pr_debug("ctcmpc :  %s  xid received()\n", __FUNCTION__);
++	ctcmpc_dumpit((char *)mpcginfo->xid, XID2_LENGTH);
++
++	/*the received direction should be the opposite of ours  */
++	if (((CHANNEL_DIRECTION(ch->flags) == READ) ? XID2_WRITE_SIDE :
++				XID2_READ_SIDE) != xid->xid2_dlc_type) {
++		failed = 1;
++		printk(KERN_INFO "ctcmpc:%s() XID REJECTED - READ-WRITE CH "
++			"Pairing Invalid \n", __FUNCTION__);
++	}
++
++	if (xid->xid2_dlc_type == XID2_READ_SIDE) {
++		ctcm_pr_debug("ctcmpc: %s(): grpmaxbuf:%d xid2buflen:%d\n",
++				__FUNCTION__, grp->group_max_buflen,
++				xid->xid2_buf_len);
++
++		if (grp->group_max_buflen == 0 ||
++			grp->group_max_buflen > xid->xid2_buf_len - len)
++			grp->group_max_buflen = xid->xid2_buf_len - len;
++	}
++
++
++	if (grp->saved_xid2 == NULL)	{
++		grp->saved_xid2 =
++			(struct xid2 *)skb_tail_pointer(grp->rcvd_xid_skb);
++
++		memcpy(skb_put(grp->rcvd_xid_skb,
++					XID2_LENGTH), xid, XID2_LENGTH);
++		grp->rcvd_xid_skb->data = grp->rcvd_xid_data;
++
++		skb_reset_tail_pointer(grp->rcvd_xid_skb);
++		grp->rcvd_xid_skb->len = 0;
++
++		/* convert two 32 bit numbers into 1 64 bit for id compare */
++		our_id = (__u64)priv->xid->xid2_adj_id;
++		our_id = our_id << 32;
++		our_id = our_id + priv->xid->xid2_sender_id;
++		their_id = (__u64)xid->xid2_adj_id;
++		their_id = their_id << 32;
++		their_id = their_id + xid->xid2_sender_id;
++		/* lower id assume the xside role */
++		if (our_id < their_id) {
++			grp->roll = XSIDE;
++			ctcm_pr_debug("ctcmpc :%s() WE HAVE LOW ID-"
++				       "TAKE XSIDE\n", __FUNCTION__);
++		} else {
++			grp->roll = YSIDE;
++			ctcm_pr_debug("ctcmpc :%s() WE HAVE HIGH ID-"
++				       "TAKE YSIDE\n", __FUNCTION__);
++		}
++
++	} else {
++		if (xid->xid2_flag4 != grp->saved_xid2->xid2_flag4) {
++			failed = 1;
++			printk(KERN_INFO "%s XID REJECTED - XID Flag Byte4\n",
++			       __FUNCTION__);
++		}
++		if (xid->xid2_flag2 == 0x40) {
++			failed = 1;
++			printk(KERN_INFO "%s XID REJECTED - XID NOGOOD\n",
++			       __FUNCTION__);
++		}
++		if (xid->xid2_adj_id != grp->saved_xid2->xid2_adj_id) {
++			failed = 1;
++			printk(KERN_INFO "%s XID REJECTED - "
++				"Adjacent Station ID Mismatch\n",
++				__FUNCTION__);
++		}
++		if (xid->xid2_sender_id != grp->saved_xid2->xid2_sender_id) {
++			failed = 1;
++			printk(KERN_INFO "%s XID REJECTED - "
++				"Sender Address Mismatch\n", __FUNCTION__);
++
++		}
++	}
++
++	if (failed) {
++		ctcm_pr_info("ctcmpc	   :  %s() failed\n", __FUNCTION__);
++		priv->xid->xid2_flag2 = 0x40;
++		grp->saved_xid2->xid2_flag2 = 0x40;
++		rc = 1;
++	}
++
++done:
++
++	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
++	return rc;
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
++{
++	struct channel *ch = arg;
++	struct ctcm_priv *priv;
++	struct mpc_group *grp = NULL;
++	struct net_device *dev = NULL;
++	int rc = 0;
++	int gotlock = 0;
++	unsigned long saveflags = 0;	/* avoids compiler warning with
++			   spin_unlock_irqrestore */
++
++	if (ch == NULL)	{
++		printk(KERN_INFO "%s ch=NULL\n", __FUNCTION__);
++					goto done;
++	}
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++			__FUNCTION__, smp_processor_id(), ch, ch->id);
++
++	dev = ch->netdev;
++	if (dev == NULL) {
++		printk(KERN_INFO "%s dev=NULL\n", __FUNCTION__);
++					goto done;
++	}
++
++	priv = dev->priv;
++	if (priv == NULL) {
++		printk(KERN_INFO "%s priv=NULL\n", __FUNCTION__);
++					goto done;
++	}
++
++	grp = priv->mpcg;
++	if (grp == NULL) {
++		printk(KERN_INFO "%s grp=NULL\n", __FUNCTION__);
++					goto done;
++	}
++
++	if (ctcm_checkalloc_buffer(ch))
++					goto done;
++
++	/* skb data-buffer referencing: */
++
++	ch->trans_skb->data = ch->trans_skb_data;
++	skb_reset_tail_pointer(ch->trans_skb);
++	ch->trans_skb->len = 0;
++	/* result of the previous 3 statements is NOT always
++	 * already set after ctcm_checkalloc_buffer
++	 * because of possible reuse of the trans_skb
++	 */
++	memset(ch->trans_skb->data, 0, 16);
++	ch->rcvd_xid_th =  (struct th_header *)ch->trans_skb_data;
++	/* check is main purpose here: */
++	skb_put(ch->trans_skb, TH_HEADER_LENGTH);
++	ch->rcvd_xid = (struct xid2 *)skb_tail_pointer(ch->trans_skb);
++	/* check is main purpose here: */
++	skb_put(ch->trans_skb, XID2_LENGTH);
++	ch->rcvd_xid_id = skb_tail_pointer(ch->trans_skb);
++	/* cleanup back to startpoint */
++	ch->trans_skb->data = ch->trans_skb_data;
++	skb_reset_tail_pointer(ch->trans_skb);
++	ch->trans_skb->len = 0;
++
++	/* non-checking rewrite of above skb data-buffer referencing: */
++	/*
++	memset(ch->trans_skb->data, 0, 16);
++	ch->rcvd_xid_th =  (struct th_header *)ch->trans_skb_data;
++	ch->rcvd_xid = (struct xid2 *)(ch->trans_skb_data + TH_HEADER_LENGTH);
++	ch->rcvd_xid_id = ch->trans_skb_data + TH_HEADER_LENGTH + XID2_LENGTH;
++	 */
++
++	ch->ccw[8].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++	ch->ccw[8].count	= 0;
++	ch->ccw[8].cda		= 0x00;
++
++	if (side == XSIDE) {
++		/* mpc_action_xside_xid */
++		if (ch->xid_th == NULL) {
++			printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
++					goto done;
++		}
++		ch->ccw[9].cmd_code	= CCW_CMD_WRITE;
++		ch->ccw[9].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[9].count	= TH_HEADER_LENGTH;
++		ch->ccw[9].cda		= virt_to_phys(ch->xid_th);
++
++		if (ch->xid == NULL) {
++			printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
++					goto done;
++		}
++
++		ch->ccw[10].cmd_code	= CCW_CMD_WRITE;
++		ch->ccw[10].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[10].count	= XID2_LENGTH;
++		ch->ccw[10].cda		= virt_to_phys(ch->xid);
++
++		ch->ccw[11].cmd_code	= CCW_CMD_READ;
++		ch->ccw[11].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[11].count	= TH_HEADER_LENGTH;
++		ch->ccw[11].cda		= virt_to_phys(ch->rcvd_xid_th);
++
++		ch->ccw[12].cmd_code	= CCW_CMD_READ;
++		ch->ccw[12].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[12].count	= XID2_LENGTH;
++		ch->ccw[12].cda		= virt_to_phys(ch->rcvd_xid);
++
++		ch->ccw[13].cmd_code	= CCW_CMD_READ;
++		ch->ccw[13].cda		= virt_to_phys(ch->rcvd_xid_id);
++
++	} else { /* side == YSIDE : mpc_action_yside_xid */
++		ch->ccw[9].cmd_code	= CCW_CMD_READ;
++		ch->ccw[9].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[9].count	= TH_HEADER_LENGTH;
++		ch->ccw[9].cda		= virt_to_phys(ch->rcvd_xid_th);
++
++		ch->ccw[10].cmd_code	= CCW_CMD_READ;
++		ch->ccw[10].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[10].count	= XID2_LENGTH;
++		ch->ccw[10].cda		= virt_to_phys(ch->rcvd_xid);
++
++		if (ch->xid_th == NULL)	{
++			printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
++					goto done;
++		}
++		ch->ccw[11].cmd_code	= CCW_CMD_WRITE;
++		ch->ccw[11].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[11].count	= TH_HEADER_LENGTH;
++		ch->ccw[11].cda		= virt_to_phys(ch->xid_th);
++
++		if (ch->xid == NULL) {
++			printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
++					goto done;
++		}
++		ch->ccw[12].cmd_code	= CCW_CMD_WRITE;
++		ch->ccw[12].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++		ch->ccw[12].count	= XID2_LENGTH;
++		ch->ccw[12].cda		= virt_to_phys(ch->xid);
++
++		if (ch->xid_id == NULL)	{
++			printk(KERN_INFO "%s ch->xid_id=NULL\n", __FUNCTION__);
++					goto done;
++		}
++		ch->ccw[13].cmd_code	= CCW_CMD_WRITE;
++		ch->ccw[13].cda		= virt_to_phys(ch->xid_id);
++
++	}
++	ch->ccw[13].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
++	ch->ccw[13].count	= 4;
++
++	ch->ccw[14].cmd_code	= CCW_CMD_NOOP;
++	ch->ccw[14].flags	= CCW_FLAG_SLI;
++	ch->ccw[14].count	= 0;
++	ch->ccw[14].cda		= 0;
++
++	if (do_debug_ccw)
++		ctcmpc_dumpit((char *)&ch->ccw[8], sizeof(struct ccw1) * 7);
++
++	ctcmpc_dumpit((char *)ch->xid_th, TH_HEADER_LENGTH);
++	ctcmpc_dumpit((char *)ch->xid, XID2_LENGTH);
++	ctcmpc_dumpit((char *)ch->xid_id, 4);
++	if (!in_irq()) {
++			 /* Such conditional locking is a known problem for
++			  * sparse because its static undeterministic.
++			  * Warnings should be ignored here. */
++		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++		gotlock = 1;
++	}
++
++	fsm_addtimer(&ch->timer, 5000 , CTC_EVENT_TIMER, ch);
++	rc = ccw_device_start(ch->cdev, &ch->ccw[8],
++				(unsigned long)ch, 0xff, 0);
++
++	if (gotlock)	/* see remark above about conditional locking */
++		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++
++	if (rc != 0) {
++		ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
++				__FUNCTION__, ch->id);
++		ctcm_ccw_check_rc(ch, rc,
++				(side == XSIDE) ? "x-side XID" : "y-side XID");
++	}
++
++done:
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++				__FUNCTION__, ch, ch->id);
++	return;
++
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_xside_xid(fsm_instance *fsm, int event, void *arg)
++{
++	mpc_action_side_xid(fsm, arg, XSIDE);
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_yside_xid(fsm_instance *fsm, int event, void *arg)
++{
++	mpc_action_side_xid(fsm, arg, YSIDE);
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg)
++{
++	struct channel	   *ch = arg;
++	struct ctcm_priv    *priv;
++	struct mpc_group   *grp     = NULL;
++	struct net_device *dev = NULL;
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++			__FUNCTION__, smp_processor_id(), ch, ch->id);
++
++	if (ch == NULL) {
++		printk(KERN_WARNING "%s ch=NULL\n", __FUNCTION__);
++					goto done;
++	}
++
++	dev = ch->netdev;
++	if (dev == NULL) {
++		printk(KERN_WARNING "%s dev=NULL\n", __FUNCTION__);
++					goto done;
++	}
++
++	priv = dev->priv;
++	if (priv == NULL) {
++		printk(KERN_WARNING "%s priv=NULL\n", __FUNCTION__);
++					goto done;
++	}
++
++	grp = priv->mpcg;
++	if (grp == NULL) {
++		printk(KERN_WARNING "%s grp=NULL\n", __FUNCTION__);
++					goto done;
++	}
++
++	if (ch->xid == NULL) {
++		printk(KERN_WARNING "%s ch-xid=NULL\n", __FUNCTION__);
++					goto done;
++	}
++
++	fsm_newstate(ch->fsm, CH_XID0_INPROGRESS);
++
++	ch->xid->xid2_option =	XID2_0;
++
++	switch (fsm_getstate(grp->fsm)) {
++	case MPCG_STATE_XID2INITW:
++	case MPCG_STATE_XID2INITX:
++		ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
++		break;
++	case MPCG_STATE_XID0IOWAIT:
++	case MPCG_STATE_XID0IOWAIX:
++		ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
++		break;
++	}
++
++	fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
++
++done:
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++			__FUNCTION__, ch, ch->id);
++	return;
++
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++*/
++static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
++{
++	struct net_device *dev = arg;
++	struct ctcm_priv   *priv = NULL;
++	struct mpc_group  *grp = NULL;
++	int direction;
++	int rc = 0;
++	int send = 0;
++
++	ctcm_pr_debug("ctcmpc enter:	%s() \n", __FUNCTION__);
++
++	if (dev == NULL) {
++		printk(KERN_INFO "%s dev=NULL \n", __FUNCTION__);
++		rc = 1;
++					goto done;
++	}
++
++	priv = dev->priv;
++	if (priv == NULL) {
++		printk(KERN_INFO "%s priv=NULL \n", __FUNCTION__);
++		rc = 1;
++					goto done;
++	}
++
++	grp = priv->mpcg;
++	if (grp == NULL) {
++		printk(KERN_INFO "%s grp=NULL \n", __FUNCTION__);
++		rc = 1;
++					goto done;
++	}
++
++	for (direction = READ; direction <= WRITE; direction++)	{
++		struct channel *ch = priv->channel[direction];
++		struct xid2 *thisxid = ch->xid;
++		ch->xid_skb->data = ch->xid_skb_data;
++		skb_reset_tail_pointer(ch->xid_skb);
++		ch->xid_skb->len = 0;
++		thisxid->xid2_option = XID2_7;
++		send = 0;
++
++		/* xid7 phase 1 */
++		if (grp->outstanding_xid7_p2 > 0) {
++			if (grp->roll == YSIDE) {
++				if (fsm_getstate(ch->fsm) == CH_XID7_PENDING1) {
++					fsm_newstate(ch->fsm, CH_XID7_PENDING2);
++					ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
++					memcpy(skb_put(ch->xid_skb,
++							TH_HEADER_LENGTH),
++					       &thdummy, TH_HEADER_LENGTH);
++					send = 1;
++				}
++			} else if (fsm_getstate(ch->fsm) < CH_XID7_PENDING2) {
++					fsm_newstate(ch->fsm, CH_XID7_PENDING2);
++					ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
++					memcpy(skb_put(ch->xid_skb,
++						       TH_HEADER_LENGTH),
++					       &thnorm, TH_HEADER_LENGTH);
++					send = 1;
++			}
++		} else {
++			/* xid7 phase 2 */
++			if (grp->roll == YSIDE) {
++				if (fsm_getstate(ch->fsm) < CH_XID7_PENDING4) {
++					fsm_newstate(ch->fsm, CH_XID7_PENDING4);
++					memcpy(skb_put(ch->xid_skb,
++						       TH_HEADER_LENGTH),
++					       &thnorm, TH_HEADER_LENGTH);
++					ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
++					send = 1;
++				}
++			} else if (fsm_getstate(ch->fsm) == CH_XID7_PENDING3) {
++				fsm_newstate(ch->fsm, CH_XID7_PENDING4);
++				ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
++				memcpy(skb_put(ch->xid_skb, TH_HEADER_LENGTH),
++						&thdummy, TH_HEADER_LENGTH);
++				send = 1;
++			}
++		}
++
++		if (send)
++			fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
++	}
++
++done:
++
++	if (rc != 0)
++		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++
++	return;
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg)
++{
++
++	struct mpcg_info   *mpcginfo   = arg;
++	struct channel	   *ch	       = mpcginfo->ch;
++	struct net_device  *dev        = ch->netdev;
++	struct ctcm_priv   *priv;
++	struct mpc_group   *grp;
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++			__FUNCTION__, smp_processor_id(), ch, ch->id);
++
++	priv = dev->priv;
++	grp = priv->mpcg;
++
++	ctcm_pr_debug("ctcmpc in:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
++		       __FUNCTION__, ch->id,
++		       grp->outstanding_xid2,
++		       grp->outstanding_xid7,
++		       grp->outstanding_xid7_p2);
++
++	if (fsm_getstate(ch->fsm) < CH_XID7_PENDING)
++		fsm_newstate(ch->fsm, CH_XID7_PENDING);
++
++	grp->outstanding_xid2--;
++	grp->outstanding_xid7++;
++	grp->outstanding_xid7_p2++;
++
++	/* must change state before validating xid to */
++	/* properly handle interim interrupts received*/
++	switch (fsm_getstate(grp->fsm)) {
++	case MPCG_STATE_XID2INITW:
++		fsm_newstate(grp->fsm, MPCG_STATE_XID2INITX);
++		mpc_validate_xid(mpcginfo);
++		break;
++	case MPCG_STATE_XID0IOWAIT:
++		fsm_newstate(grp->fsm, MPCG_STATE_XID0IOWAIX);
++		mpc_validate_xid(mpcginfo);
++		break;
++	case MPCG_STATE_XID2INITX:
++		if (grp->outstanding_xid2 == 0) {
++			fsm_newstate(grp->fsm, MPCG_STATE_XID7INITW);
++			mpc_validate_xid(mpcginfo);
++			fsm_event(grp->fsm, MPCG_EVENT_XID2DONE, dev);
++		}
++		break;
++	case MPCG_STATE_XID0IOWAIX:
++		if (grp->outstanding_xid2 == 0) {
++			fsm_newstate(grp->fsm, MPCG_STATE_XID7INITI);
++			mpc_validate_xid(mpcginfo);
++			fsm_event(grp->fsm, MPCG_EVENT_XID2DONE, dev);
++		}
++		break;
++	}
++	kfree(mpcginfo);
++
++	if (do_debug) {
++		ctcm_pr_debug("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
++				__FUNCTION__, ch->id,
++				grp->outstanding_xid2,
++				grp->outstanding_xid7,
++				grp->outstanding_xid7_p2);
++		ctcm_pr_debug("ctcmpc:%s() %s grpstate: %s chanstate: %s \n",
++				__FUNCTION__, ch->id,
++				fsm_getstate_str(grp->fsm),
++				fsm_getstate_str(ch->fsm));
++	}
++	return;
++
++}
++
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
++{
++	struct mpcg_info   *mpcginfo   = arg;
++	struct channel	   *ch	       = mpcginfo->ch;
++	struct net_device  *dev        = ch->netdev;
++	struct ctcm_priv   *priv    = dev->priv;
++	struct mpc_group   *grp     = priv->mpcg;
++
++	if (do_debug) {
++		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++				__FUNCTION__, smp_processor_id(), ch, ch->id);
++
++		ctcm_pr_debug("ctcmpc:  outstanding_xid7: %i, "
++				" outstanding_xid7_p2: %i\n",
++				grp->outstanding_xid7,
++				grp->outstanding_xid7_p2);
++	}
++
++	grp->outstanding_xid7--;
++	ch->xid_skb->data = ch->xid_skb_data;
++	skb_reset_tail_pointer(ch->xid_skb);
++	ch->xid_skb->len = 0;
++
++	switch (fsm_getstate(grp->fsm)) {
++	case MPCG_STATE_XID7INITI:
++		fsm_newstate(grp->fsm, MPCG_STATE_XID7INITZ);
++		mpc_validate_xid(mpcginfo);
++		break;
++	case MPCG_STATE_XID7INITW:
++		fsm_newstate(grp->fsm, MPCG_STATE_XID7INITX);
++		mpc_validate_xid(mpcginfo);
++		break;
++	case MPCG_STATE_XID7INITZ:
++	case MPCG_STATE_XID7INITX:
++		if (grp->outstanding_xid7 == 0) {
++			if (grp->outstanding_xid7_p2 > 0) {
++				grp->outstanding_xid7 =
++					grp->outstanding_xid7_p2;
++				grp->outstanding_xid7_p2 = 0;
++			} else
++				fsm_newstate(grp->fsm, MPCG_STATE_XID7INITF);
++
++			mpc_validate_xid(mpcginfo);
++			fsm_event(grp->fsm, MPCG_EVENT_XID7DONE, dev);
++			break;
++		}
++		mpc_validate_xid(mpcginfo);
++		break;
++	}
++
++	kfree(mpcginfo);
++
++	if (do_debug)
++		ctcm_pr_debug("ctcmpc exit: %s(): cp=%i ch=0x%p id=%s\n",
++			__FUNCTION__, smp_processor_id(), ch, ch->id);
++	return;
++
++}
++
++/*
++ * mpc_action helper of an MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static int mpc_send_qllc_discontact(struct net_device *dev)
++{
++	int	rc	= 0;
++	__u32	new_len	= 0;
++	struct sk_buff   *skb;
++	struct qllc      *qllcptr;
++	struct ctcm_priv *priv;
++	struct mpc_group *grp;
++
++	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
++
++	if (dev == NULL) {
++		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++		rc = 1;
++					goto done;
++	}
++
++	priv = dev->priv;
++	if (priv == NULL) {
++		printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
++		rc = 1;
++					goto done;
++	}
++
++	grp = priv->mpcg;
++	if (grp == NULL) {
++		printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
++		rc = 1;
++					goto done;
++	}
++	ctcm_pr_info("ctcmpc: %s() GROUP STATE: %s\n", __FUNCTION__,
++			mpcg_state_names[grp->saved_state]);
++
++	switch (grp->saved_state) {
++	/*
++	 * establish conn callback function is
++	 * preferred method to report failure
++	 */
++	case MPCG_STATE_XID0IOWAIT:
++	case MPCG_STATE_XID0IOWAIX:
++	case MPCG_STATE_XID7INITI:
++	case MPCG_STATE_XID7INITZ:
++	case MPCG_STATE_XID2INITW:
++	case MPCG_STATE_XID2INITX:
++	case MPCG_STATE_XID7INITW:
++	case MPCG_STATE_XID7INITX:
++		if (grp->estconnfunc) {
++			grp->estconnfunc(grp->port_num, -1, 0);
++			grp->estconnfunc = NULL;
++			break;
++		}
++	case MPCG_STATE_FLOWC:
++	case MPCG_STATE_READY:
++		grp->send_qllc_disc = 2;
++		new_len = sizeof(struct qllc);
++		qllcptr = kzalloc(new_len, gfp_type() | GFP_DMA);
++		if (qllcptr == NULL) {
++			printk(KERN_INFO
++			       "ctcmpc: Out of memory in %s()\n",
++			       dev->name);
++			rc = 1;
++				goto done;
++		}
++
++		qllcptr->qllc_address = 0xcc;
++		qllcptr->qllc_commands = 0x03;
++
++		skb = __dev_alloc_skb(new_len, GFP_ATOMIC);
++
++		if (skb == NULL) {
++			printk(KERN_INFO "%s Out of memory in mpc_send_qllc\n",
++			       dev->name);
++			priv->stats.rx_dropped++;
++			rc = 1;
++			kfree(qllcptr);
++				goto done;
++		}
++
++		memcpy(skb_put(skb, new_len), qllcptr, new_len);
++		kfree(qllcptr);
++
++		if (skb_headroom(skb) < 4) {
++			printk(KERN_INFO "ctcmpc: %s() Unable to"
++			       " build discontact for %s\n",
++			       __FUNCTION__, dev->name);
++			rc = 1;
++			dev_kfree_skb_any(skb);
++				goto done;
++		}
++
++		*((__u32 *)skb_push(skb, 4)) = priv->channel[READ]->pdu_seq;
++		priv->channel[READ]->pdu_seq++;
++		if (do_debug_data)
++			ctcm_pr_debug("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
++				__FUNCTION__, priv->channel[READ]->pdu_seq);
++
++		/* receipt of CC03 resets anticipated sequence number on
++		      receiving side */
++		priv->channel[READ]->pdu_seq = 0x00;
++		skb_reset_mac_header(skb);
++		skb->dev = dev;
++		skb->protocol = htons(ETH_P_SNAP);
++		skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++		ctcmpc_dumpit((char *)skb->data, (sizeof(struct qllc) + 4));
++
++		netif_rx(skb);
++		break;
++	default:
++		break;
++
++	}
++
++done:
++	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
++	return rc;
++}
++/* --- This is the END my friend --- */
++
+diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
+new file mode 100644
+index 0000000..f996860
+--- /dev/null
++++ b/drivers/s390/net/ctcm_mpc.h
+@@ -0,0 +1,239 @@
++/*
++ * drivers/s390/net/ctcm_mpc.h
++ *
++ * Copyright IBM Corp. 2007
++ * Authors:	Peter Tiedemann (ptiedem at de.ibm.com)
++ *
++ * 	MPC additions:
++ *		Belinda Thompson (belindat at us.ibm.com)
++ *		Andy Richter (richtera at us.ibm.com)
++ */
++
++#ifndef _CTC_MPC_H_
++#define _CTC_MPC_H_
++
++#include <linux/skbuff.h>
++#include "fsm.h"
++
++/*
++ * MPC external interface
++ * Note that ctc_mpc_xyz are called with a lock on ................
++ */
++
++/*  port_number is the mpc device 0, 1, 2 etc mpc2 is port_number 2 */
++
++/*  passive open  Just wait for XID2 exchange */
++extern int ctc_mpc_alloc_channel(int port,
++		void (*callback)(int port_num, int max_write_size));
++/* active open  Alloc then send XID2 */
++extern void ctc_mpc_establish_connectivity(int port,
++		void (*callback)(int port_num, int rc, int max_write_size));
++
++extern void ctc_mpc_dealloc_ch(int port);
++extern void ctc_mpc_flow_control(int port, int flowc);
++
++/*
++ * other MPC Group prototypes and structures
++ */
++
++#define ETH_P_SNA_DIX	0x80D5
++
++/*
++ * Declaration of an XID2
++ *
++ */
++#define ALLZEROS 0x0000000000000000
++
++#define XID_FM2		0x20
++#define XID2_0		0x00
++#define XID2_7		0x07
++#define XID2_WRITE_SIDE 0x04
++#define XID2_READ_SIDE	0x05
++
++struct xid2 {
++	__u8	xid2_type_id;
++	__u8	xid2_len;
++	__u32	xid2_adj_id;
++	__u8	xid2_rlen;
++	__u8	xid2_resv1;
++	__u8	xid2_flag1;
++	__u8	xid2_fmtt;
++	__u8	xid2_flag4;
++	__u16	xid2_resv2;
++	__u8	xid2_tgnum;
++	__u32	xid2_sender_id;
++	__u8	xid2_flag2;
++	__u8	xid2_option;
++	char  xid2_resv3[8];
++	__u16	xid2_resv4;
++	__u8	xid2_dlc_type;
++	__u16	xid2_resv5;
++	__u8	xid2_mpc_flag;
++	__u8	xid2_resv6;
++	__u16	xid2_buf_len;
++	char xid2_buffer[255 - (13 * sizeof(__u8) +
++				2 * sizeof(__u32) +
++				4 * sizeof(__u16) +
++				8 * sizeof(char))];
++} __attribute__ ((packed));
++
++#define XID2_LENGTH  (sizeof(struct xid2))
++
++struct th_header {
++	__u8	th_seg;
++	__u8	th_ch_flag;
++#define TH_HAS_PDU	0xf0
++#define TH_IS_XID	0x01
++#define TH_SWEEP_REQ	0xfe
++#define TH_SWEEP_RESP	0xff
++	__u8	th_blk_flag;
++#define TH_DATA_IS_XID	0x80
++#define TH_RETRY	0x40
++#define TH_DISCONTACT	0xc0
++#define TH_SEG_BLK	0x20
++#define TH_LAST_SEG	0x10
++#define TH_PDU_PART	0x08
++	__u8	th_is_xid;	/* is 0x01 if this is XID  */
++	__u32	th_seq_num;
++} __attribute__ ((packed));
++
++struct th_addon {
++	__u32	th_last_seq;
++	__u32	th_resvd;
++} __attribute__ ((packed));
++
++struct th_sweep {
++	struct th_header th;
++	struct th_addon sw;
++} __attribute__ ((packed));
++
++#define TH_HEADER_LENGTH (sizeof(struct th_header))
++#define TH_SWEEP_LENGTH (sizeof(struct th_sweep))
++
++#define PDU_LAST	0x80
++#define PDU_CNTL	0x40
++#define PDU_FIRST	0x20
++
++struct pdu {
++	__u32	pdu_offset;
++	__u8	pdu_flag;
++	__u8	pdu_proto;   /*  0x01 is APPN SNA  */
++	__u16	pdu_seq;
++} __attribute__ ((packed));
++
++#define PDU_HEADER_LENGTH  (sizeof(struct pdu))
++
++struct qllc {
++	__u8	qllc_address;
++#define QLLC_REQ	0xFF
++#define QLLC_RESP	0x00
++	__u8	qllc_commands;
++#define QLLC_DISCONNECT 0x53
++#define QLLC_UNSEQACK	0x73
++#define QLLC_SETMODE	0x93
++#define QLLC_EXCHID	0xBF
++} __attribute__ ((packed));
++
++
++/*
++ * Definition of one MPC group
++ */
++
++#define MAX_MPCGCHAN		10
++#define MPC_XID_TIMEOUT_VALUE	10000
++#define MPC_CHANNEL_ADD		0
++#define MPC_CHANNEL_REMOVE	1
++#define MPC_CHANNEL_ATTN	2
++#define XSIDE	1
++#define YSIDE	0
++
++struct mpcg_info {
++	struct sk_buff	*skb;
++	struct channel	*ch;
++	struct xid2	*xid;
++	struct th_sweep	*sweep;
++	struct th_header *th;
++};
++
++struct mpc_group {
++	struct tasklet_struct mpc_tasklet;
++	struct tasklet_struct mpc_tasklet2;
++	int	changed_side;
++	int	saved_state;
++	int	channels_terminating;
++	int	out_of_sequence;
++	int	flow_off_called;
++	int	port_num;
++	int	port_persist;
++	int	alloc_called;
++	__u32	xid2_adj_id;
++	__u8	xid2_tgnum;
++	__u32	xid2_sender_id;
++	int	num_channel_paths;
++	int	active_channels[2];
++	__u16	group_max_buflen;
++	int	outstanding_xid2;
++	int	outstanding_xid7;
++	int	outstanding_xid7_p2;
++	int	sweep_req_pend_num;
++	int	sweep_rsp_pend_num;
++	struct sk_buff	*xid_skb;
++	char		*xid_skb_data;
++	struct th_header *xid_th;
++	struct xid2	*xid;
++	char		*xid_id;
++	struct th_header *rcvd_xid_th;
++	struct sk_buff	*rcvd_xid_skb;
++	char		*rcvd_xid_data;
++	__u8		in_sweep;
++	__u8		roll;
++	struct xid2	*saved_xid2;
++	void 		(*allochanfunc)(int, int);
++	int		allocchan_callback_retries;
++	void 		(*estconnfunc)(int, int, int);
++	int		estconn_callback_retries;
++	int		estconn_called;
++	int		xidnogood;
++	int		send_qllc_disc;
++	fsm_timer	timer;
++	fsm_instance	*fsm; /* group xid fsm */
++};
++
++#ifdef DEBUGDATA
++void ctcmpc_dumpit(char *buf, int len);
++#else
++static inline void ctcmpc_dumpit(char *buf, int len)
++{
++}
++#endif
++
++#ifdef DEBUGDATA
++/*
++ * Dump header and first 16 bytes of an sk_buff for debugging purposes.
++ *
++ * skb	 The struct sk_buff to dump.
++ * offset Offset relative to skb-data, where to start the dump.
++ */
++void ctcmpc_dump_skb(struct sk_buff *skb, int offset);
++#else
++static inline void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
++{}
++#endif
++
++static inline void ctcmpc_dump32(char *buf, int len)
++{
++	if (len < 32)
++		ctcmpc_dumpit(buf, len);
++	else
++		ctcmpc_dumpit(buf, 32);
++}
++
++int ctcmpc_open(struct net_device *);
++void ctcm_ccw_check_rc(struct channel *, int, char *);
++void mpc_group_ready(unsigned long adev);
++int mpc_channel_action(struct channel *ch, int direction, int action);
++void mpc_action_send_discontact(unsigned long thischan);
++void mpc_action_discontact(fsm_instance *fi, int event, void *arg);
++void ctcmpc_bh(unsigned long thischan);
++#endif
++/* --- This is the END my friend --- */
+diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c
+new file mode 100644
+index 0000000..bb2d137
+--- /dev/null
++++ b/drivers/s390/net/ctcm_sysfs.c
+@@ -0,0 +1,210 @@
++/*
++ * drivers/s390/net/ctcm_sysfs.c
++ *
++ * Copyright IBM Corp. 2007, 2007
++ * Authors:	Peter Tiedemann (ptiedem at de.ibm.com)
++ *
++ */
++
++#undef DEBUG
++#undef DEBUGDATA
++#undef DEBUGCCW
++
++#include <linux/sysfs.h>
++#include "ctcm_main.h"
++
++/*
++ * sysfs attributes
++ */
++
++static ssize_t ctcm_buffer_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct ctcm_priv *priv = dev_get_drvdata(dev);
++
++	if (!priv)
++		return -ENODEV;
++	return sprintf(buf, "%d\n", priv->buffer_size);
++}
++
++static ssize_t ctcm_buffer_write(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct net_device *ndev;
++	int bs1;
++	struct ctcm_priv *priv = dev_get_drvdata(dev);
++
++	if (!(priv && priv->channel[READ] &&
++			(ndev = priv->channel[READ]->netdev))) {
++		CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev");
++		return -ENODEV;
++	}
++
++	sscanf(buf, "%u", &bs1);
++	if (bs1 > CTCM_BUFSIZE_LIMIT)
++					goto einval;
++	if (bs1 < (576 + LL_HEADER_LENGTH + 2))
++					goto einval;
++	priv->buffer_size = bs1;	/* just to overwrite the default */
++
++	if ((ndev->flags & IFF_RUNNING) &&
++	    (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
++					goto einval;
++
++	priv->channel[READ]->max_bufsize = bs1;
++	priv->channel[WRITE]->max_bufsize = bs1;
++	if (!(ndev->flags & IFF_RUNNING))
++		ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
++	priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
++	priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
++
++	CTCM_DBF_DEV(SETUP, ndev, buf);
++	return count;
++
++einval:
++	CTCM_DBF_DEV(SETUP, ndev, "buff_err");
++	return -EINVAL;
++}
++
++static void ctcm_print_statistics(struct ctcm_priv *priv)
++{
++	char *sbuf;
++	char *p;
++
++	if (!priv)
++		return;
++	sbuf = kmalloc(2048, GFP_KERNEL);
++	if (sbuf == NULL)
++		return;
++	p = sbuf;
++
++	p += sprintf(p, "  Device FSM state: %s\n",
++		     fsm_getstate_str(priv->fsm));
++	p += sprintf(p, "  RX channel FSM state: %s\n",
++		     fsm_getstate_str(priv->channel[READ]->fsm));
++	p += sprintf(p, "  TX channel FSM state: %s\n",
++		     fsm_getstate_str(priv->channel[WRITE]->fsm));
++	p += sprintf(p, "  Max. TX buffer used: %ld\n",
++		     priv->channel[WRITE]->prof.maxmulti);
++	p += sprintf(p, "  Max. chained SKBs: %ld\n",
++		     priv->channel[WRITE]->prof.maxcqueue);
++	p += sprintf(p, "  TX single write ops: %ld\n",
++		     priv->channel[WRITE]->prof.doios_single);
++	p += sprintf(p, "  TX multi write ops: %ld\n",
++		     priv->channel[WRITE]->prof.doios_multi);
++	p += sprintf(p, "  Netto bytes written: %ld\n",
++		     priv->channel[WRITE]->prof.txlen);
++	p += sprintf(p, "  Max. TX IO-time: %ld\n",
++		     priv->channel[WRITE]->prof.tx_time);
++
++	printk(KERN_INFO "Statistics for %s:\n%s",
++				priv->channel[WRITE]->netdev->name, sbuf);
++	kfree(sbuf);
++	return;
++}
++
++static ssize_t stats_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct ctcm_priv *priv = dev_get_drvdata(dev);
++	if (!priv)
++		return -ENODEV;
++	ctcm_print_statistics(priv);
++	return sprintf(buf, "0\n");
++}
++
++static ssize_t stats_write(struct device *dev, struct device_attribute *attr,
++				const char *buf, size_t count)
++{
++	struct ctcm_priv *priv = dev_get_drvdata(dev);
++	if (!priv)
++		return -ENODEV;
++	/* Reset statistics */
++	memset(&priv->channel[WRITE]->prof, 0,
++				sizeof(priv->channel[WRITE]->prof));
++	return count;
++}
++
++static ssize_t ctcm_proto_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct ctcm_priv *priv = dev_get_drvdata(dev);
++	if (!priv)
++		return -ENODEV;
++
++	return sprintf(buf, "%d\n", priv->protocol);
++}
++
++static ssize_t ctcm_proto_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	int value;
++	struct ctcm_priv *priv = dev_get_drvdata(dev);
++
++	if (!priv)
++		return -ENODEV;
++	sscanf(buf, "%u", &value);
++	if (!((value == CTCM_PROTO_S390)  ||
++	      (value == CTCM_PROTO_LINUX) ||
++	      (value == CTCM_PROTO_MPC) ||
++	      (value == CTCM_PROTO_OS390)))
++		return -EINVAL;
++	priv->protocol = value;
++	CTCM_DBF_DEV(SETUP, dev, buf);
++
++	return count;
++}
++
++static ssize_t ctcm_type_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct ccwgroup_device *cgdev;
++
++	cgdev = to_ccwgroupdev(dev);
++	if (!cgdev)
++		return -ENODEV;
++
++	return sprintf(buf, "%s\n",
++			cu3088_type[cgdev->cdev[0]->id.driver_info]);
++}
++
++static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write);
++static DEVICE_ATTR(protocol, 0644, ctcm_proto_show, ctcm_proto_store);
++static DEVICE_ATTR(type, 0444, ctcm_type_show, NULL);
++static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
++
++static struct attribute *ctcm_attr[] = {
++	&dev_attr_protocol.attr,
++	&dev_attr_type.attr,
++	&dev_attr_buffer.attr,
++	NULL,
++};
++
++static struct attribute_group ctcm_attr_group = {
++	.attrs = ctcm_attr,
++};
++
++int ctcm_add_attributes(struct device *dev)
++{
++	int rc;
++
++	rc = device_create_file(dev, &dev_attr_stats);
++
++	return rc;
++}
++
++void ctcm_remove_attributes(struct device *dev)
++{
++	device_remove_file(dev, &dev_attr_stats);
++}
++
++int ctcm_add_files(struct device *dev)
++{
++	return sysfs_create_group(&dev->kobj, &ctcm_attr_group);
++}
++
++void ctcm_remove_files(struct device *dev)
++{
++	sysfs_remove_group(&dev->kobj, &ctcm_attr_group);
++}
++
+diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
+deleted file mode 100644
+index 77a5031..0000000
+--- a/drivers/s390/net/ctcmain.c
++++ /dev/null
+@@ -1,3062 +0,0 @@
+-/*
+- * CTC / ESCON network driver
+- *
+- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+- * Author(s): Fritz Elfert (elfert at de.ibm.com, felfert at millenux.com)
+- * Fixes by : Jochen Röhrig (roehrig at de.ibm.com)
+- *            Arnaldo Carvalho de Melo <acme at conectiva.com.br>
+-	      Peter Tiedemann (ptiedem at de.ibm.com)
+- * Driver Model stuff by : Cornelia Huck <cornelia.huck at de.ibm.com>
+- *
+- * Documentation used:
+- *  - Principles of Operation (IBM doc#: SA22-7201-06)
+- *  - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
+- *  - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
+- *  - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
+- *  - ESCON I/O Interface (IBM doc#: SA22-7202-029
+- *
+- * and the source of the original CTC driver by:
+- *  Dieter Wellerdiek (wel at de.ibm.com)
+- *  Martin Schwidefsky (schwidefsky at de.ibm.com)
+- *  Denis Joseph Barrow (djbarrow at de.ibm.com,barrow_dj at yahoo.com)
+- *  Jochen Röhrig (roehrig at de.ibm.com)
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-#undef DEBUG
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
+-#include <linux/errno.h>
+-#include <linux/types.h>
+-#include <linux/interrupt.h>
+-#include <linux/timer.h>
+-#include <linux/bitops.h>
+-
+-#include <linux/signal.h>
+-#include <linux/string.h>
+-
+-#include <linux/ip.h>
+-#include <linux/if_arp.h>
+-#include <linux/tcp.h>
+-#include <linux/skbuff.h>
+-#include <linux/ctype.h>
+-#include <net/dst.h>
+-
+-#include <asm/io.h>
+-#include <asm/ccwdev.h>
+-#include <asm/ccwgroup.h>
+-#include <asm/uaccess.h>
+-
+-#include <asm/idals.h>
+-
+-#include "fsm.h"
+-#include "cu3088.h"
+-
+-#include "ctcdbug.h"
+-#include "ctcmain.h"
+-
+-MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert at millenux.com)");
+-MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");
+-MODULE_LICENSE("GPL");
+-/**
+- * States of the interface statemachine.
+- */
+-enum dev_states {
+-	DEV_STATE_STOPPED,
+-	DEV_STATE_STARTWAIT_RXTX,
+-	DEV_STATE_STARTWAIT_RX,
+-	DEV_STATE_STARTWAIT_TX,
+-	DEV_STATE_STOPWAIT_RXTX,
+-	DEV_STATE_STOPWAIT_RX,
+-	DEV_STATE_STOPWAIT_TX,
+-	DEV_STATE_RUNNING,
+-	/**
+-	 * MUST be always the last element!!
+-	 */
+-	CTC_NR_DEV_STATES
+-};
+-
+-static const char *dev_state_names[] = {
+-	"Stopped",
+-	"StartWait RXTX",
+-	"StartWait RX",
+-	"StartWait TX",
+-	"StopWait RXTX",
+-	"StopWait RX",
+-	"StopWait TX",
+-	"Running",
+-};
+-
+-/**
+- * Events of the interface statemachine.
+- */
+-enum dev_events {
+-	DEV_EVENT_START,
+-	DEV_EVENT_STOP,
+-	DEV_EVENT_RXUP,
+-	DEV_EVENT_TXUP,
+-	DEV_EVENT_RXDOWN,
+-	DEV_EVENT_TXDOWN,
+-	DEV_EVENT_RESTART,
+-	/**
+-	 * MUST be always the last element!!
+-	 */
+-	CTC_NR_DEV_EVENTS
+-};
+-
+-static const char *dev_event_names[] = {
+-	"Start",
+-	"Stop",
+-	"RX up",
+-	"TX up",
+-	"RX down",
+-	"TX down",
+-	"Restart",
+-};
+-
+-/**
+- * Events of the channel statemachine
+- */
+-enum ch_events {
+-	/**
+-	 * Events, representing return code of
+-	 * I/O operations (ccw_device_start, ccw_device_halt et al.)
+-	 */
+-	CH_EVENT_IO_SUCCESS,
+-	CH_EVENT_IO_EBUSY,
+-	CH_EVENT_IO_ENODEV,
+-	CH_EVENT_IO_EIO,
+-	CH_EVENT_IO_UNKNOWN,
+-
+-	CH_EVENT_ATTNBUSY,
+-	CH_EVENT_ATTN,
+-	CH_EVENT_BUSY,
+-
+-	/**
+-	 * Events, representing unit-check
+-	 */
+-	CH_EVENT_UC_RCRESET,
+-	CH_EVENT_UC_RSRESET,
+-	CH_EVENT_UC_TXTIMEOUT,
+-	CH_EVENT_UC_TXPARITY,
+-	CH_EVENT_UC_HWFAIL,
+-	CH_EVENT_UC_RXPARITY,
+-	CH_EVENT_UC_ZERO,
+-	CH_EVENT_UC_UNKNOWN,
+-
+-	/**
+-	 * Events, representing subchannel-check
+-	 */
+-	CH_EVENT_SC_UNKNOWN,
+-
+-	/**
+-	 * Events, representing machine checks
+-	 */
+-	CH_EVENT_MC_FAIL,
+-	CH_EVENT_MC_GOOD,
+-
+-	/**
+-	 * Event, representing normal IRQ
+-	 */
+-	CH_EVENT_IRQ,
+-	CH_EVENT_FINSTAT,
+-
+-	/**
+-	 * Event, representing timer expiry.
+-	 */
+-	CH_EVENT_TIMER,
+-
+-	/**
+-	 * Events, representing commands from upper levels.
+-	 */
+-	CH_EVENT_START,
+-	CH_EVENT_STOP,
+-
+-	/**
+-	 * MUST be always the last element!!
+-	 */
+-	NR_CH_EVENTS,
+-};
+-
+-/**
+- * States of the channel statemachine.
+- */
+-enum ch_states {
+-	/**
+-	 * Channel not assigned to any device,
+-	 * initial state, direction invalid
+-	 */
+-	CH_STATE_IDLE,
+-
+-	/**
+-	 * Channel assigned but not operating
+-	 */
+-	CH_STATE_STOPPED,
+-	CH_STATE_STARTWAIT,
+-	CH_STATE_STARTRETRY,
+-	CH_STATE_SETUPWAIT,
+-	CH_STATE_RXINIT,
+-	CH_STATE_TXINIT,
+-	CH_STATE_RX,
+-	CH_STATE_TX,
+-	CH_STATE_RXIDLE,
+-	CH_STATE_TXIDLE,
+-	CH_STATE_RXERR,
+-	CH_STATE_TXERR,
+-	CH_STATE_TERM,
+-	CH_STATE_DTERM,
+-	CH_STATE_NOTOP,
+-
+-	/**
+-	 * MUST be always the last element!!
+-	 */
+-	NR_CH_STATES,
+-};
+-
+-static int loglevel = CTC_LOGLEVEL_DEFAULT;
+-
+-/**
+- * Linked list of all detected channels.
+- */
+-static struct channel *channels = NULL;
+-
+-/**
+- * Print Banner.
+- */
+-static void
+-print_banner(void)
+-{
+-	static int printed = 0;
+-
+-	if (printed)
+-		return;
+-
+-	printk(KERN_INFO "CTC driver initialized\n");
+-	printed = 1;
+-}
+-
+-/**
+- * Return type of a detected device.
+- */
+-static enum channel_types
+-get_channel_type(struct ccw_device_id *id)
+-{
+-	enum channel_types type = (enum channel_types) id->driver_info;
+-
+-	if (type == channel_type_ficon)
+-		type = channel_type_escon;
+-
+-	return type;
+-}
+-
+-static const char *ch_event_names[] = {
+-	"ccw_device success",
+-	"ccw_device busy",
+-	"ccw_device enodev",
+-	"ccw_device ioerr",
+-	"ccw_device unknown",
+-
+-	"Status ATTN & BUSY",
+-	"Status ATTN",
+-	"Status BUSY",
+-
+-	"Unit check remote reset",
+-	"Unit check remote system reset",
+-	"Unit check TX timeout",
+-	"Unit check TX parity",
+-	"Unit check Hardware failure",
+-	"Unit check RX parity",
+-	"Unit check ZERO",
+-	"Unit check Unknown",
+-
+-	"SubChannel check Unknown",
+-
+-	"Machine check failure",
+-	"Machine check operational",
+-
+-	"IRQ normal",
+-	"IRQ final",
+-
+-	"Timer",
+-
+-	"Start",
+-	"Stop",
+-};
+-
+-static const char *ch_state_names[] = {
+-	"Idle",
+-	"Stopped",
+-	"StartWait",
+-	"StartRetry",
+-	"SetupWait",
+-	"RX init",
+-	"TX init",
+-	"RX",
+-	"TX",
+-	"RX idle",
+-	"TX idle",
+-	"RX error",
+-	"TX error",
+-	"Terminating",
+-	"Restarting",
+-	"Not operational",
+-};
+-
+-#ifdef DEBUG
+-/**
+- * Dump header and first 16 bytes of an sk_buff for debugging purposes.
+- *
+- * @param skb    The sk_buff to dump.
+- * @param offset Offset relative to skb-data, where to start the dump.
+- */
+-static void
+-ctc_dump_skb(struct sk_buff *skb, int offset)
+-{
+-	unsigned char *p = skb->data;
+-	__u16 bl;
+-	struct ll_header *header;
+-	int i;
+-
+-	if (!(loglevel & CTC_LOGLEVEL_DEBUG))
+-		return;
+-	p += offset;
+-	bl = *((__u16 *) p);
+-	p += 2;
+-	header = (struct ll_header *) p;
+-	p -= 2;
+-
+-	printk(KERN_DEBUG "dump:\n");
+-	printk(KERN_DEBUG "blocklen=%d %04x\n", bl, bl);
+-
+-	printk(KERN_DEBUG "h->length=%d %04x\n", header->length,
+-	       header->length);
+-	printk(KERN_DEBUG "h->type=%04x\n", header->type);
+-	printk(KERN_DEBUG "h->unused=%04x\n", header->unused);
+-	if (bl > 16)
+-		bl = 16;
+-	printk(KERN_DEBUG "data: ");
+-	for (i = 0; i < bl; i++)
+-		printk("%02x%s", *p++, (i % 16) ? " " : "\n<7>");
+-	printk("\n");
+-}
+-#else
+-static inline void
+-ctc_dump_skb(struct sk_buff *skb, int offset)
+-{
+-}
+-#endif
+-
+-/**
+- * Unpack a just received skb and hand it over to
+- * upper layers.
+- *
+- * @param ch The channel where this skb has been received.
+- * @param pskb The received skb.
+- */
+-static void
+-ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
+-{
+-	struct net_device *dev = ch->netdev;
+-	struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
+-	__u16 len = *((__u16 *) pskb->data);
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-	skb_put(pskb, 2 + LL_HEADER_LENGTH);
+-	skb_pull(pskb, 2);
+-	pskb->dev = dev;
+-	pskb->ip_summed = CHECKSUM_UNNECESSARY;
+-	while (len > 0) {
+-		struct sk_buff *skb;
+-		struct ll_header *header = (struct ll_header *) pskb->data;
+-
+-		skb_pull(pskb, LL_HEADER_LENGTH);
+-		if ((ch->protocol == CTC_PROTO_S390) &&
+-		    (header->type != ETH_P_IP)) {
+-
+-#ifndef DEBUG
+-		        if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
+-#endif
+-				/**
+-				 * Check packet type only if we stick strictly
+-				 * to S/390's protocol of OS390. This only
+-				 * supports IP. Otherwise allow any packet
+-				 * type.
+-				 */
+-				ctc_pr_warn(
+-					"%s Illegal packet type 0x%04x received, dropping\n",
+-					dev->name, header->type);
+-				ch->logflags |= LOG_FLAG_ILLEGALPKT;
+-#ifndef DEBUG
+-			}
+-#endif
+-#ifdef DEBUG
+-			ctc_dump_skb(pskb, -6);
+-#endif
+-			privptr->stats.rx_dropped++;
+-			privptr->stats.rx_frame_errors++;
+-			return;
+-		}
+-		pskb->protocol = ntohs(header->type);
+-		if (header->length <= LL_HEADER_LENGTH) {
+-#ifndef DEBUG
+-		        if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
+-#endif
+-				ctc_pr_warn(
+-				       "%s Illegal packet size %d "
+-				       "received (MTU=%d blocklen=%d), "
+-				       "dropping\n", dev->name, header->length,
+-				       dev->mtu, len);
+-				ch->logflags |= LOG_FLAG_ILLEGALSIZE;
+-#ifndef DEBUG
+-			}
+-#endif
+-#ifdef DEBUG
+-			ctc_dump_skb(pskb, -6);
+-#endif
+-			privptr->stats.rx_dropped++;
+-			privptr->stats.rx_length_errors++;
+-			return;
+-		}
+-		header->length -= LL_HEADER_LENGTH;
+-		len -= LL_HEADER_LENGTH;
+-		if ((header->length > skb_tailroom(pskb)) ||
+-		    (header->length > len)) {
+-#ifndef DEBUG
+-		        if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
+-#endif
+-				ctc_pr_warn(
+-					"%s Illegal packet size %d "
+-					"(beyond the end of received data), "
+-					"dropping\n", dev->name, header->length);
+-				ch->logflags |= LOG_FLAG_OVERRUN;
+-#ifndef DEBUG
+-			}
+-#endif
+-#ifdef DEBUG
+-			ctc_dump_skb(pskb, -6);
+-#endif
+-			privptr->stats.rx_dropped++;
+-			privptr->stats.rx_length_errors++;
+-			return;
+-		}
+-		skb_put(pskb, header->length);
+-		skb_reset_mac_header(pskb);
+-		len -= header->length;
+-		skb = dev_alloc_skb(pskb->len);
+-		if (!skb) {
+-#ifndef DEBUG
+-		        if (!(ch->logflags & LOG_FLAG_NOMEM)) {
+-#endif
+-				ctc_pr_warn(
+-					"%s Out of memory in ctc_unpack_skb\n",
+-					dev->name);
+-				ch->logflags |= LOG_FLAG_NOMEM;
+-#ifndef DEBUG
+-			}
+-#endif
+-			privptr->stats.rx_dropped++;
+-			return;
+-		}
+-		skb_copy_from_linear_data(pskb, skb_put(skb, pskb->len),
+-					  pskb->len);
+-		skb_reset_mac_header(skb);
+-		skb->dev = pskb->dev;
+-		skb->protocol = pskb->protocol;
+-		pskb->ip_summed = CHECKSUM_UNNECESSARY;
+-		/**
+-		 * reset logflags
+-		 */
+-		ch->logflags = 0;
+-		privptr->stats.rx_packets++;
+-		privptr->stats.rx_bytes += skb->len;
+-		netif_rx_ni(skb);
+-		dev->last_rx = jiffies;
+-		if (len > 0) {
+-			skb_pull(pskb, header->length);
+-			if (skb_tailroom(pskb) < LL_HEADER_LENGTH) {
+-#ifndef DEBUG
+-				if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
+-#endif
+-					ctc_pr_warn(
+-						"%s Overrun in ctc_unpack_skb\n",
+-						dev->name);
+-					ch->logflags |= LOG_FLAG_OVERRUN;
+-#ifndef DEBUG
+-				}
+-#endif
+-				return;
+-			}
+-			skb_put(pskb, LL_HEADER_LENGTH);
+-		}
+-	}
+-}
+-
+-/**
+- * Check return code of a preceeding ccw_device call, halt_IO etc...
+- *
+- * @param ch          The channel, the error belongs to.
+- * @param return_code The error code to inspect.
+- */
+-static void
+-ccw_check_return_code(struct channel *ch, int return_code, char *msg)
+-{
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-	switch (return_code) {
+-		case 0:
+-			fsm_event(ch->fsm, CH_EVENT_IO_SUCCESS, ch);
+-			break;
+-		case -EBUSY:
+-			ctc_pr_warn("%s (%s): Busy !\n", ch->id, msg);
+-			fsm_event(ch->fsm, CH_EVENT_IO_EBUSY, ch);
+-			break;
+-		case -ENODEV:
+-			ctc_pr_emerg("%s (%s): Invalid device called for IO\n",
+-				     ch->id, msg);
+-			fsm_event(ch->fsm, CH_EVENT_IO_ENODEV, ch);
+-			break;
+-		case -EIO:
+-			ctc_pr_emerg("%s (%s): Status pending... \n",
+-				     ch->id, msg);
+-			fsm_event(ch->fsm, CH_EVENT_IO_EIO, ch);
+-			break;
+-		default:
+-			ctc_pr_emerg("%s (%s): Unknown error in do_IO %04x\n",
+-				     ch->id, msg, return_code);
+-			fsm_event(ch->fsm, CH_EVENT_IO_UNKNOWN, ch);
+-	}
+-}
+-
+-/**
+- * Check sense of a unit check.
+- *
+- * @param ch    The channel, the sense code belongs to.
+- * @param sense The sense code to inspect.
+- */
+-static void
+-ccw_unit_check(struct channel *ch, unsigned char sense)
+-{
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-	if (sense & SNS0_INTERVENTION_REQ) {
+-		if (sense & 0x01) {
+-			ctc_pr_debug("%s: Interface disc. or Sel. reset "
+-					"(remote)\n", ch->id);
+-			fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch);
+-		} else {
+-			ctc_pr_debug("%s: System reset (remote)\n", ch->id);
+-			fsm_event(ch->fsm, CH_EVENT_UC_RSRESET, ch);
+-		}
+-	} else if (sense & SNS0_EQUIPMENT_CHECK) {
+-		if (sense & SNS0_BUS_OUT_CHECK) {
+-			ctc_pr_warn("%s: Hardware malfunction (remote)\n",
+-				    ch->id);
+-			fsm_event(ch->fsm, CH_EVENT_UC_HWFAIL, ch);
+-		} else {
+-			ctc_pr_warn("%s: Read-data parity error (remote)\n",
+-				    ch->id);
+-			fsm_event(ch->fsm, CH_EVENT_UC_RXPARITY, ch);
+-		}
+-	} else if (sense & SNS0_BUS_OUT_CHECK) {
+-		if (sense & 0x04) {
+-			ctc_pr_warn("%s: Data-streaming timeout)\n", ch->id);
+-			fsm_event(ch->fsm, CH_EVENT_UC_TXTIMEOUT, ch);
+-		} else {
+-			ctc_pr_warn("%s: Data-transfer parity error\n", ch->id);
+-			fsm_event(ch->fsm, CH_EVENT_UC_TXPARITY, ch);
+-		}
+-	} else if (sense & SNS0_CMD_REJECT) {
+-		ctc_pr_warn("%s: Command reject\n", ch->id);
+-	} else if (sense == 0) {
+-		ctc_pr_debug("%s: Unit check ZERO\n", ch->id);
+-		fsm_event(ch->fsm, CH_EVENT_UC_ZERO, ch);
+-	} else {
+-		ctc_pr_warn("%s: Unit Check with sense code: %02x\n",
+-			    ch->id, sense);
+-		fsm_event(ch->fsm, CH_EVENT_UC_UNKNOWN, ch);
+-	}
+-}
+-
+-static void
+-ctc_purge_skb_queue(struct sk_buff_head *q)
+-{
+-	struct sk_buff *skb;
+-
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-
+-	while ((skb = skb_dequeue(q))) {
+-		atomic_dec(&skb->users);
+-		dev_kfree_skb_irq(skb);
+-	}
+-}
+-
+-static int
+-ctc_checkalloc_buffer(struct channel *ch, int warn)
+-{
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-	if ((ch->trans_skb == NULL) ||
+-	    (ch->flags & CHANNEL_FLAGS_BUFSIZE_CHANGED)) {
+-		if (ch->trans_skb != NULL)
+-			dev_kfree_skb(ch->trans_skb);
+-		clear_normalized_cda(&ch->ccw[1]);
+-		ch->trans_skb = __dev_alloc_skb(ch->max_bufsize,
+-						GFP_ATOMIC | GFP_DMA);
+-		if (ch->trans_skb == NULL) {
+-			if (warn)
+-				ctc_pr_warn(
+-					"%s: Couldn't alloc %s trans_skb\n",
+-					ch->id,
+-					(CHANNEL_DIRECTION(ch->flags) == READ) ?
+-					"RX" : "TX");
+-			return -ENOMEM;
+-		}
+-		ch->ccw[1].count = ch->max_bufsize;
+-		if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
+-			dev_kfree_skb(ch->trans_skb);
+-			ch->trans_skb = NULL;
+-			if (warn)
+-				ctc_pr_warn(
+-					"%s: set_normalized_cda for %s "
+-					"trans_skb failed, dropping packets\n",
+-					ch->id,
+-					(CHANNEL_DIRECTION(ch->flags) == READ) ?
+-					"RX" : "TX");
+-			return -ENOMEM;
+-		}
+-		ch->ccw[1].count = 0;
+-		ch->trans_skb_data = ch->trans_skb->data;
+-		ch->flags &= ~CHANNEL_FLAGS_BUFSIZE_CHANGED;
+-	}
+-	return 0;
+-}
+-
+-/**
+- * Dummy NOP action for statemachines
+- */
+-static void
+-fsm_action_nop(fsm_instance * fi, int event, void *arg)
+-{
+-}
+-
+-/**
+- * Actions for channel - statemachines.
+- *****************************************************************************/
+-
+-/**
+- * Normal data has been send. Free the corresponding
+- * skb (it's in io_queue), reset dev->tbusy and
+- * revert to idle state.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_txdone(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-	struct ctc_priv *privptr = dev->priv;
+-	struct sk_buff *skb;
+-	int first = 1;
+-	int i;
+-	unsigned long duration;
+-	struct timespec done_stamp = current_kernel_time();
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-
+-	duration =
+-	    (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
+-	    (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
+-	if (duration > ch->prof.tx_time)
+-		ch->prof.tx_time = duration;
+-
+-	if (ch->irb->scsw.count != 0)
+-		ctc_pr_debug("%s: TX not complete, remaining %d bytes\n",
+-			     dev->name, ch->irb->scsw.count);
+-	fsm_deltimer(&ch->timer);
+-	while ((skb = skb_dequeue(&ch->io_queue))) {
+-		privptr->stats.tx_packets++;
+-		privptr->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
+-		if (first) {
+-			privptr->stats.tx_bytes += 2;
+-			first = 0;
+-		}
+-		atomic_dec(&skb->users);
+-		dev_kfree_skb_irq(skb);
+-	}
+-	spin_lock(&ch->collect_lock);
+-	clear_normalized_cda(&ch->ccw[4]);
+-	if (ch->collect_len > 0) {
+-		int rc;
+-
+-		if (ctc_checkalloc_buffer(ch, 1)) {
+-			spin_unlock(&ch->collect_lock);
+-			return;
+-		}
+-		ch->trans_skb->data = ch->trans_skb_data;
+-		skb_reset_tail_pointer(ch->trans_skb);
+-		ch->trans_skb->len = 0;
+-		if (ch->prof.maxmulti < (ch->collect_len + 2))
+-			ch->prof.maxmulti = ch->collect_len + 2;
+-		if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
+-			ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
+-		*((__u16 *) skb_put(ch->trans_skb, 2)) = ch->collect_len + 2;
+-		i = 0;
+-		while ((skb = skb_dequeue(&ch->collect_queue))) {
+-			skb_copy_from_linear_data(skb, skb_put(ch->trans_skb,
+-							       skb->len),
+-						  skb->len);
+-			privptr->stats.tx_packets++;
+-			privptr->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
+-			atomic_dec(&skb->users);
+-			dev_kfree_skb_irq(skb);
+-			i++;
+-		}
+-		ch->collect_len = 0;
+-		spin_unlock(&ch->collect_lock);
+-		ch->ccw[1].count = ch->trans_skb->len;
+-		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+-		ch->prof.send_stamp = current_kernel_time();
+-		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+-				      (unsigned long) ch, 0xff, 0);
+-		ch->prof.doios_multi++;
+-		if (rc != 0) {
+-			privptr->stats.tx_dropped += i;
+-			privptr->stats.tx_errors += i;
+-			fsm_deltimer(&ch->timer);
+-			ccw_check_return_code(ch, rc, "chained TX");
+-		}
+-	} else {
+-		spin_unlock(&ch->collect_lock);
+-		fsm_newstate(fi, CH_STATE_TXIDLE);
+-	}
+-	ctc_clear_busy(dev);
+-}
+-
+-/**
+- * Initial data is sent.
+- * Notify device statemachine that we are up and
+- * running.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_txidle(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	fsm_newstate(fi, CH_STATE_TXIDLE);
+-	fsm_event(((struct ctc_priv *) ch->netdev->priv)->fsm, DEV_EVENT_TXUP,
+-		  ch->netdev);
+-}
+-
+-/**
+- * Got normal data, check for sanity, queue it up, allocate new buffer
+- * trigger bottom half, and initiate next read.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rx(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-	struct ctc_priv *privptr = dev->priv;
+-	int len = ch->max_bufsize - ch->irb->scsw.count;
+-	struct sk_buff *skb = ch->trans_skb;
+-	__u16 block_len = *((__u16 *) skb->data);
+-	int check_len;
+-	int rc;
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	if (len < 8) {
+-		ctc_pr_debug("%s: got packet with length %d < 8\n",
+-			     dev->name, len);
+-		privptr->stats.rx_dropped++;
+-		privptr->stats.rx_length_errors++;
+-		goto again;
+-	}
+-	if (len > ch->max_bufsize) {
+-		ctc_pr_debug("%s: got packet with length %d > %d\n",
+-			     dev->name, len, ch->max_bufsize);
+-		privptr->stats.rx_dropped++;
+-		privptr->stats.rx_length_errors++;
+-		goto again;
+-	}
+-
+-	/**
+-	 * VM TCP seems to have a bug sending 2 trailing bytes of garbage.
+-	 */
+-	switch (ch->protocol) {
+-		case CTC_PROTO_S390:
+-		case CTC_PROTO_OS390:
+-			check_len = block_len + 2;
+-			break;
+-		default:
+-			check_len = block_len;
+-			break;
+-	}
+-	if ((len < block_len) || (len > check_len)) {
+-		ctc_pr_debug("%s: got block length %d != rx length %d\n",
+-			     dev->name, block_len, len);
+-#ifdef DEBUG
+-		ctc_dump_skb(skb, 0);
+-#endif
+-		*((__u16 *) skb->data) = len;
+-		privptr->stats.rx_dropped++;
+-		privptr->stats.rx_length_errors++;
+-		goto again;
+-	}
+-	block_len -= 2;
+-	if (block_len > 0) {
+-		*((__u16 *) skb->data) = block_len;
+-		ctc_unpack_skb(ch, skb);
+-	}
+- again:
+-	skb->data = ch->trans_skb_data;
+-	skb_reset_tail_pointer(skb);
+-	skb->len = 0;
+-	if (ctc_checkalloc_buffer(ch, 1))
+-		return;
+-	ch->ccw[1].count = ch->max_bufsize;
+-	rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);
+-	if (rc != 0)
+-		ccw_check_return_code(ch, rc, "normal RX");
+-}
+-
+-static void ch_action_rxidle(fsm_instance * fi, int event, void *arg);
+-
+-/**
+- * Initialize connection by sending a __u16 of value 0.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_firstio(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	int rc;
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-
+-	if (fsm_getstate(fi) == CH_STATE_TXIDLE)
+-		ctc_pr_debug("%s: remote side issued READ?, init ...\n", ch->id);
+-	fsm_deltimer(&ch->timer);
+-	if (ctc_checkalloc_buffer(ch, 1))
+-		return;
+-	if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&
+-	    (ch->protocol == CTC_PROTO_OS390)) {
+-		/* OS/390 resp. z/OS */
+-		if (CHANNEL_DIRECTION(ch->flags) == READ) {
+-			*((__u16 *) ch->trans_skb->data) = CTC_INITIAL_BLOCKLEN;
+-			fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC,
+-				     CH_EVENT_TIMER, ch);
+-			ch_action_rxidle(fi, event, arg);
+-		} else {
+-			struct net_device *dev = ch->netdev;
+-			fsm_newstate(fi, CH_STATE_TXIDLE);
+-			fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-				  DEV_EVENT_TXUP, dev);
+-		}
+-		return;
+-	}
+-
+-	/**
+-	 * Don't setup a timer for receiving the initial RX frame
+-	 * if in compatibility mode, since VM TCP delays the initial
+-	 * frame until it has some data to send.
+-	 */
+-	if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||
+-	    (ch->protocol != CTC_PROTO_S390))
+-		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+-
+-	*((__u16 *) ch->trans_skb->data) = CTC_INITIAL_BLOCKLEN;
+-	ch->ccw[1].count = 2;	/* Transfer only length */
+-
+-	fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
+-		     ? CH_STATE_RXINIT : CH_STATE_TXINIT);
+-	rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);
+-	if (rc != 0) {
+-		fsm_deltimer(&ch->timer);
+-		fsm_newstate(fi, CH_STATE_SETUPWAIT);
+-		ccw_check_return_code(ch, rc, "init IO");
+-	}
+-	/**
+-	 * If in compatibility mode since we don't setup a timer, we
+-	 * also signal RX channel up immediately. This enables us
+-	 * to send packets early which in turn usually triggers some
+-	 * reply from VM TCP which brings up the RX channel to it's
+-	 * final state.
+-	 */
+-	if ((CHANNEL_DIRECTION(ch->flags) == READ) &&
+-	    (ch->protocol == CTC_PROTO_S390)) {
+-		struct net_device *dev = ch->netdev;
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXUP,
+-			  dev);
+-	}
+-}
+-
+-/**
+- * Got initial data, check it. If OK,
+- * notify device statemachine that we are up and
+- * running.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rxidle(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-	__u16 buflen;
+-	int rc;
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	buflen = *((__u16 *) ch->trans_skb->data);
+-#ifdef DEBUG
+-	ctc_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
+-#endif
+-	if (buflen >= CTC_INITIAL_BLOCKLEN) {
+-		if (ctc_checkalloc_buffer(ch, 1))
+-			return;
+-		ch->ccw[1].count = ch->max_bufsize;
+-		fsm_newstate(fi, CH_STATE_RXIDLE);
+-		rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+-				      (unsigned long) ch, 0xff, 0);
+-		if (rc != 0) {
+-			fsm_newstate(fi, CH_STATE_RXINIT);
+-			ccw_check_return_code(ch, rc, "initial RX");
+-		} else
+-			fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-				  DEV_EVENT_RXUP, dev);
+-	} else {
+-		ctc_pr_debug("%s: Initial RX count %d not %d\n",
+-			     dev->name, buflen, CTC_INITIAL_BLOCKLEN);
+-		ch_action_firstio(fi, event, arg);
+-	}
+-}
+-
+-/**
+- * Set channel into extended mode.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_setmode(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	int rc;
+-	unsigned long saveflags;
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+-	fsm_newstate(fi, CH_STATE_SETUPWAIT);
+-	saveflags = 0;	/* avoids compiler warning with
+-			   spin_unlock_irqrestore */
+-	if (event == CH_EVENT_TIMER)	// only for timer not yet locked
+-		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+-	rc = ccw_device_start(ch->cdev, &ch->ccw[6], (unsigned long) ch, 0xff, 0);
+-	if (event == CH_EVENT_TIMER)
+-		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+-	if (rc != 0) {
+-		fsm_deltimer(&ch->timer);
+-		fsm_newstate(fi, CH_STATE_STARTWAIT);
+-		ccw_check_return_code(ch, rc, "set Mode");
+-	} else
+-		ch->retry = 0;
+-}
+-
+-/**
+- * Setup channel.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_start(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	unsigned long saveflags;
+-	int rc;
+-	struct net_device *dev;
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-	if (ch == NULL) {
+-		ctc_pr_warn("ch_action_start ch=NULL\n");
+-		return;
+-	}
+-	if (ch->netdev == NULL) {
+-		ctc_pr_warn("ch_action_start dev=NULL, id=%s\n", ch->id);
+-		return;
+-	}
+-	dev = ch->netdev;
+-
+-#ifdef DEBUG
+-	ctc_pr_debug("%s: %s channel start\n", dev->name,
+-		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+-#endif
+-
+-	if (ch->trans_skb != NULL) {
+-		clear_normalized_cda(&ch->ccw[1]);
+-		dev_kfree_skb(ch->trans_skb);
+-		ch->trans_skb = NULL;
+-	}
+-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+-		ch->ccw[1].cmd_code = CCW_CMD_READ;
+-		ch->ccw[1].flags = CCW_FLAG_SLI;
+-		ch->ccw[1].count = 0;
+-	} else {
+-		ch->ccw[1].cmd_code = CCW_CMD_WRITE;
+-		ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+-		ch->ccw[1].count = 0;
+-	}
+-	if (ctc_checkalloc_buffer(ch, 0)) {
+-		ctc_pr_notice(
+-			"%s: Could not allocate %s trans_skb, delaying "
+-			"allocation until first transfer\n",
+-			dev->name,
+-			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+-	}
+-
+-	ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
+-	ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+-	ch->ccw[0].count = 0;
+-	ch->ccw[0].cda = 0;
+-	ch->ccw[2].cmd_code = CCW_CMD_NOOP;	/* jointed CE + DE */
+-	ch->ccw[2].flags = CCW_FLAG_SLI;
+-	ch->ccw[2].count = 0;
+-	ch->ccw[2].cda = 0;
+-	memcpy(&ch->ccw[3], &ch->ccw[0], sizeof (struct ccw1) * 3);
+-	ch->ccw[4].cda = 0;
+-	ch->ccw[4].flags &= ~CCW_FLAG_IDA;
+-
+-	fsm_newstate(fi, CH_STATE_STARTWAIT);
+-	fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);
+-	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+-	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
+-	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+-	if (rc != 0) {
+-		if (rc != -EBUSY)
+-		    fsm_deltimer(&ch->timer);
+-		ccw_check_return_code(ch, rc, "initial HaltIO");
+-	}
+-#ifdef DEBUG
+-	ctc_pr_debug("ctc: %s(): leaving\n", __func__);
+-#endif
+-}
+-
+-/**
+- * Shutdown a channel.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_haltio(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	unsigned long saveflags;
+-	int rc;
+-	int oldstate;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+-	saveflags = 0;	/* avoids comp warning with
+-			   spin_unlock_irqrestore */
+-	if (event == CH_EVENT_STOP)	// only for STOP not yet locked
+-		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+-	oldstate = fsm_getstate(fi);
+-	fsm_newstate(fi, CH_STATE_TERM);
+-	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
+-	if (event == CH_EVENT_STOP)
+-		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+-	if (rc != 0) {
+-		if (rc != -EBUSY) {
+-		    fsm_deltimer(&ch->timer);
+-		    fsm_newstate(fi, oldstate);
+-		}
+-		ccw_check_return_code(ch, rc, "HaltIO in ch_action_haltio");
+-	}
+-}
+-
+-/**
+- * A channel has successfully been halted.
+- * Cleanup it's queue and notify interface statemachine.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_stopped(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	fsm_newstate(fi, CH_STATE_STOPPED);
+-	if (ch->trans_skb != NULL) {
+-		clear_normalized_cda(&ch->ccw[1]);
+-		dev_kfree_skb(ch->trans_skb);
+-		ch->trans_skb = NULL;
+-	}
+-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+-		skb_queue_purge(&ch->io_queue);
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-			  DEV_EVENT_RXDOWN, dev);
+-	} else {
+-		ctc_purge_skb_queue(&ch->io_queue);
+-		spin_lock(&ch->collect_lock);
+-		ctc_purge_skb_queue(&ch->collect_queue);
+-		ch->collect_len = 0;
+-		spin_unlock(&ch->collect_lock);
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-			  DEV_EVENT_TXDOWN, dev);
+-	}
+-}
+-
+-/**
+- * A stop command from device statemachine arrived and we are in
+- * not operational mode. Set state to stopped.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_stop(fsm_instance * fi, int event, void *arg)
+-{
+-	fsm_newstate(fi, CH_STATE_STOPPED);
+-}
+-
+-/**
+- * A machine check for no path, not operational status or gone device has
+- * happened.
+- * Cleanup queue and notify interface statemachine.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_fail(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	fsm_newstate(fi, CH_STATE_NOTOP);
+-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+-		skb_queue_purge(&ch->io_queue);
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-			  DEV_EVENT_RXDOWN, dev);
+-	} else {
+-		ctc_purge_skb_queue(&ch->io_queue);
+-		spin_lock(&ch->collect_lock);
+-		ctc_purge_skb_queue(&ch->collect_queue);
+-		ch->collect_len = 0;
+-		spin_unlock(&ch->collect_lock);
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-			  DEV_EVENT_TXDOWN, dev);
+-	}
+-}
+-
+-/**
+- * Handle error during setup of channel.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_setuperr(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-	/**
+-	 * Special case: Got UC_RCRESET on setmode.
+-	 * This means that remote side isn't setup. In this case
+-	 * simply retry after some 10 secs...
+-	 */
+-	if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&
+-	    ((event == CH_EVENT_UC_RCRESET) ||
+-	     (event == CH_EVENT_UC_RSRESET))) {
+-		fsm_newstate(fi, CH_STATE_STARTRETRY);
+-		fsm_deltimer(&ch->timer);
+-		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+-		if (CHANNEL_DIRECTION(ch->flags) == READ) {
+-			int rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
+-			if (rc != 0)
+-				ccw_check_return_code(
+-					ch, rc, "HaltIO in ch_action_setuperr");
+-		}
+-		return;
+-	}
+-
+-	ctc_pr_debug("%s: Error %s during %s channel setup state=%s\n",
+-		     dev->name, ch_event_names[event],
+-		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
+-		     fsm_getstate_str(fi));
+-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+-		fsm_newstate(fi, CH_STATE_RXERR);
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-			  DEV_EVENT_RXDOWN, dev);
+-	} else {
+-		fsm_newstate(fi, CH_STATE_TXERR);
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-			  DEV_EVENT_TXDOWN, dev);
+-	}
+-}
+-
+-/**
+- * Restart a channel after an error.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_restart(fsm_instance * fi, int event, void *arg)
+-{
+-	unsigned long saveflags;
+-	int oldstate;
+-	int rc;
+-
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	ctc_pr_debug("%s: %s channel restart\n", dev->name,
+-		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+-	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+-	oldstate = fsm_getstate(fi);
+-	fsm_newstate(fi, CH_STATE_STARTWAIT);
+-	saveflags = 0;	/* avoids compiler warning with
+-			   spin_unlock_irqrestore */
+-	if (event == CH_EVENT_TIMER)	// only for timer not yet locked
+-		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+-	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
+-	if (event == CH_EVENT_TIMER)
+-		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+-	if (rc != 0) {
+-		if (rc != -EBUSY) {
+-		    fsm_deltimer(&ch->timer);
+-		    fsm_newstate(fi, oldstate);
+-		}
+-		ccw_check_return_code(ch, rc, "HaltIO in ch_action_restart");
+-	}
+-}
+-
+-/**
+- * Handle error during RX initial handshake (exchange of
+- * 0-length block header)
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rxiniterr(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-	if (event == CH_EVENT_TIMER) {
+-		fsm_deltimer(&ch->timer);
+-		ctc_pr_debug("%s: Timeout during RX init handshake\n", dev->name);
+-		if (ch->retry++ < 3)
+-			ch_action_restart(fi, event, arg);
+-		else {
+-			fsm_newstate(fi, CH_STATE_RXERR);
+-			fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-				  DEV_EVENT_RXDOWN, dev);
+-		}
+-	} else
+-		ctc_pr_warn("%s: Error during RX init handshake\n", dev->name);
+-}
+-
+-/**
+- * Notify device statemachine if we gave up initialization
+- * of RX channel.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rxinitfail(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-	fsm_newstate(fi, CH_STATE_RXERR);
+-	ctc_pr_warn("%s: RX initialization failed\n", dev->name);
+-	ctc_pr_warn("%s: RX <-> RX connection detected\n", dev->name);
+-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
+-}
+-
+-/**
+- * Handle RX Unit check remote reset (remote disconnected)
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rxdisc(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct channel *ch2;
+-	struct net_device *dev = ch->netdev;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	ctc_pr_debug("%s: Got remote disconnect, re-initializing ...\n",
+-		     dev->name);
+-
+-	/**
+-	 * Notify device statemachine
+-	 */
+-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
+-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);
+-
+-	fsm_newstate(fi, CH_STATE_DTERM);
+-	ch2 = ((struct ctc_priv *) dev->priv)->channel[WRITE];
+-	fsm_newstate(ch2->fsm, CH_STATE_DTERM);
+-
+-	ccw_device_halt(ch->cdev, (unsigned long) ch);
+-	ccw_device_halt(ch2->cdev, (unsigned long) ch2);
+-}
+-
+-/**
+- * Handle error during TX channel initialization.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_txiniterr(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-
+-	DBF_TEXT(setup, 2, __FUNCTION__);
+-	if (event == CH_EVENT_TIMER) {
+-		fsm_deltimer(&ch->timer);
+-		ctc_pr_debug("%s: Timeout during TX init handshake\n", dev->name);
+-		if (ch->retry++ < 3)
+-			ch_action_restart(fi, event, arg);
+-		else {
+-			fsm_newstate(fi, CH_STATE_TXERR);
+-			fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-				  DEV_EVENT_TXDOWN, dev);
+-		}
+-	} else
+-		ctc_pr_warn("%s: Error during TX init handshake\n", dev->name);
+-}
+-
+-/**
+- * Handle TX timeout by retrying operation.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_txretry(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-	unsigned long saveflags;
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	if (ch->retry++ > 3) {
+-		ctc_pr_debug("%s: TX retry failed, restarting channel\n",
+-			     dev->name);
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-			  DEV_EVENT_TXDOWN, dev);
+-		ch_action_restart(fi, event, arg);
+-	} else {
+-		struct sk_buff *skb;
+-
+-		ctc_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
+-		if ((skb = skb_peek(&ch->io_queue))) {
+-			int rc = 0;
+-
+-			clear_normalized_cda(&ch->ccw[4]);
+-			ch->ccw[4].count = skb->len;
+-			if (set_normalized_cda(&ch->ccw[4], skb->data)) {
+-				ctc_pr_debug(
+-					"%s: IDAL alloc failed, chan restart\n",
+-					dev->name);
+-				fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-					  DEV_EVENT_TXDOWN, dev);
+-				ch_action_restart(fi, event, arg);
+-				return;
+-			}
+-			fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);
+-			saveflags = 0;	/* avoids compiler warning with
+-					   spin_unlock_irqrestore */
+-			if (event == CH_EVENT_TIMER) // only for TIMER not yet locked
+-				spin_lock_irqsave(get_ccwdev_lock(ch->cdev),
+-						  saveflags);
+-			rc = ccw_device_start(ch->cdev, &ch->ccw[3],
+-					      (unsigned long) ch, 0xff, 0);
+-			if (event == CH_EVENT_TIMER)
+-				spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev),
+-						       saveflags);
+-			if (rc != 0) {
+-				fsm_deltimer(&ch->timer);
+-				ccw_check_return_code(ch, rc, "TX in ch_action_txretry");
+-				ctc_purge_skb_queue(&ch->io_queue);
+-			}
+-		}
+-	}
+-
+-}
+-
+-/**
+- * Handle fatal errors during an I/O command.
+- *
+- * @param fi    An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_iofatal(fsm_instance * fi, int event, void *arg)
+-{
+-	struct channel *ch = (struct channel *) arg;
+-	struct net_device *dev = ch->netdev;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	fsm_deltimer(&ch->timer);
+-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+-		ctc_pr_debug("%s: RX I/O error\n", dev->name);
+-		fsm_newstate(fi, CH_STATE_RXERR);
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-			  DEV_EVENT_RXDOWN, dev);
+-	} else {
+-		ctc_pr_debug("%s: TX I/O error\n", dev->name);
+-		fsm_newstate(fi, CH_STATE_TXERR);
+-		fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+-			  DEV_EVENT_TXDOWN, dev);
+-	}
+-}
+-
+-static void
+-ch_action_reinit(fsm_instance *fi, int event, void *arg)
+-{
+- 	struct channel *ch = (struct channel *)arg;
+- 	struct net_device *dev = ch->netdev;
+- 	struct ctc_priv *privptr = dev->priv;
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+- 	ch_action_iofatal(fi, event, arg);
+- 	fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
+-}
+-
+-/**
+- * The statemachine for a channel.
+- */
+-static const fsm_node ch_fsm[] = {
+-	{CH_STATE_STOPPED,    CH_EVENT_STOP,       fsm_action_nop       },
+-	{CH_STATE_STOPPED,    CH_EVENT_START,      ch_action_start      },
+-	{CH_STATE_STOPPED,    CH_EVENT_FINSTAT,    fsm_action_nop       },
+-	{CH_STATE_STOPPED,    CH_EVENT_MC_FAIL,    fsm_action_nop       },
+-
+-	{CH_STATE_NOTOP,      CH_EVENT_STOP,       ch_action_stop       },
+-	{CH_STATE_NOTOP,      CH_EVENT_START,      fsm_action_nop       },
+-	{CH_STATE_NOTOP,      CH_EVENT_FINSTAT,    fsm_action_nop       },
+-	{CH_STATE_NOTOP,      CH_EVENT_MC_FAIL,    fsm_action_nop       },
+-	{CH_STATE_NOTOP,      CH_EVENT_MC_GOOD,    ch_action_start      },
+-
+-	{CH_STATE_STARTWAIT,  CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_STARTWAIT,  CH_EVENT_START,      fsm_action_nop       },
+-	{CH_STATE_STARTWAIT,  CH_EVENT_FINSTAT,    ch_action_setmode    },
+-	{CH_STATE_STARTWAIT,  CH_EVENT_TIMER,      ch_action_setuperr   },
+-	{CH_STATE_STARTWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+-	{CH_STATE_STARTWAIT,  CH_EVENT_IO_EIO,     ch_action_reinit     },
+-	{CH_STATE_STARTWAIT,  CH_EVENT_MC_FAIL,    ch_action_fail       },
+-
+-	{CH_STATE_STARTRETRY, CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_STARTRETRY, CH_EVENT_TIMER,      ch_action_setmode    },
+-	{CH_STATE_STARTRETRY, CH_EVENT_FINSTAT,    fsm_action_nop       },
+-	{CH_STATE_STARTRETRY, CH_EVENT_MC_FAIL,    ch_action_fail       },
+-
+-	{CH_STATE_SETUPWAIT,  CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_SETUPWAIT,  CH_EVENT_START,      fsm_action_nop       },
+-	{CH_STATE_SETUPWAIT,  CH_EVENT_FINSTAT,    ch_action_firstio    },
+-	{CH_STATE_SETUPWAIT,  CH_EVENT_UC_RCRESET, ch_action_setuperr   },
+-	{CH_STATE_SETUPWAIT,  CH_EVENT_UC_RSRESET, ch_action_setuperr   },
+-	{CH_STATE_SETUPWAIT,  CH_EVENT_TIMER,      ch_action_setmode    },
+-	{CH_STATE_SETUPWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+-	{CH_STATE_SETUPWAIT,  CH_EVENT_IO_EIO,     ch_action_reinit     },
+-	{CH_STATE_SETUPWAIT,  CH_EVENT_MC_FAIL,    ch_action_fail       },
+-
+-	{CH_STATE_RXINIT,     CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_RXINIT,     CH_EVENT_START,      fsm_action_nop       },
+-	{CH_STATE_RXINIT,     CH_EVENT_FINSTAT,    ch_action_rxidle     },
+-	{CH_STATE_RXINIT,     CH_EVENT_UC_RCRESET, ch_action_rxiniterr  },
+-	{CH_STATE_RXINIT,     CH_EVENT_UC_RSRESET, ch_action_rxiniterr  },
+-	{CH_STATE_RXINIT,     CH_EVENT_TIMER,      ch_action_rxiniterr  },
+-	{CH_STATE_RXINIT,     CH_EVENT_ATTNBUSY,   ch_action_rxinitfail },
+-	{CH_STATE_RXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+-	{CH_STATE_RXINIT,     CH_EVENT_IO_EIO,     ch_action_reinit     },
+-	{CH_STATE_RXINIT,     CH_EVENT_UC_ZERO,    ch_action_firstio    },
+-	{CH_STATE_RXINIT,     CH_EVENT_MC_FAIL,    ch_action_fail       },
+-
+-	{CH_STATE_RXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_RXIDLE,     CH_EVENT_START,      fsm_action_nop       },
+-	{CH_STATE_RXIDLE,     CH_EVENT_FINSTAT,    ch_action_rx         },
+-	{CH_STATE_RXIDLE,     CH_EVENT_UC_RCRESET, ch_action_rxdisc     },
+-//      {CH_STATE_RXIDLE,     CH_EVENT_UC_RSRESET, ch_action_rxretry    },
+-	{CH_STATE_RXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+-	{CH_STATE_RXIDLE,     CH_EVENT_IO_EIO,     ch_action_reinit     },
+-	{CH_STATE_RXIDLE,     CH_EVENT_MC_FAIL,    ch_action_fail       },
+-	{CH_STATE_RXIDLE,     CH_EVENT_UC_ZERO,    ch_action_rx         },
+-
+-	{CH_STATE_TXINIT,     CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_TXINIT,     CH_EVENT_START,      fsm_action_nop       },
+-	{CH_STATE_TXINIT,     CH_EVENT_FINSTAT,    ch_action_txidle     },
+-	{CH_STATE_TXINIT,     CH_EVENT_UC_RCRESET, ch_action_txiniterr  },
+-	{CH_STATE_TXINIT,     CH_EVENT_UC_RSRESET, ch_action_txiniterr  },
+-	{CH_STATE_TXINIT,     CH_EVENT_TIMER,      ch_action_txiniterr  },
+-	{CH_STATE_TXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+-	{CH_STATE_TXINIT,     CH_EVENT_IO_EIO,     ch_action_reinit     },
+-	{CH_STATE_TXINIT,     CH_EVENT_MC_FAIL,    ch_action_fail       },
+-
+-	{CH_STATE_TXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_TXIDLE,     CH_EVENT_START,      fsm_action_nop       },
+-	{CH_STATE_TXIDLE,     CH_EVENT_FINSTAT,    ch_action_firstio    },
+-	{CH_STATE_TXIDLE,     CH_EVENT_UC_RCRESET, fsm_action_nop       },
+-	{CH_STATE_TXIDLE,     CH_EVENT_UC_RSRESET, fsm_action_nop       },
+-	{CH_STATE_TXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+-	{CH_STATE_TXIDLE,     CH_EVENT_IO_EIO,     ch_action_reinit     },
+-	{CH_STATE_TXIDLE,     CH_EVENT_MC_FAIL,    ch_action_fail       },
+-
+-	{CH_STATE_TERM,       CH_EVENT_STOP,       fsm_action_nop       },
+-	{CH_STATE_TERM,       CH_EVENT_START,      ch_action_restart    },
+-	{CH_STATE_TERM,       CH_EVENT_FINSTAT,    ch_action_stopped    },
+-	{CH_STATE_TERM,       CH_EVENT_UC_RCRESET, fsm_action_nop       },
+-	{CH_STATE_TERM,       CH_EVENT_UC_RSRESET, fsm_action_nop       },
+-	{CH_STATE_TERM,       CH_EVENT_MC_FAIL,    ch_action_fail       },
+-
+-	{CH_STATE_DTERM,      CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_DTERM,      CH_EVENT_START,      ch_action_restart    },
+-	{CH_STATE_DTERM,      CH_EVENT_FINSTAT,    ch_action_setmode    },
+-	{CH_STATE_DTERM,      CH_EVENT_UC_RCRESET, fsm_action_nop       },
+-	{CH_STATE_DTERM,      CH_EVENT_UC_RSRESET, fsm_action_nop       },
+-	{CH_STATE_DTERM,      CH_EVENT_MC_FAIL,    ch_action_fail       },
+-
+-	{CH_STATE_TX,         CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_TX,         CH_EVENT_START,      fsm_action_nop       },
+-	{CH_STATE_TX,         CH_EVENT_FINSTAT,    ch_action_txdone     },
+-	{CH_STATE_TX,         CH_EVENT_UC_RCRESET, ch_action_txretry    },
+-	{CH_STATE_TX,         CH_EVENT_UC_RSRESET, ch_action_txretry    },
+-	{CH_STATE_TX,         CH_EVENT_TIMER,      ch_action_txretry    },
+-	{CH_STATE_TX,         CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+-	{CH_STATE_TX,         CH_EVENT_IO_EIO,     ch_action_reinit     },
+-	{CH_STATE_TX,         CH_EVENT_MC_FAIL,    ch_action_fail       },
+-
+-	{CH_STATE_RXERR,      CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_TXERR,      CH_EVENT_STOP,       ch_action_haltio     },
+-	{CH_STATE_TXERR,      CH_EVENT_MC_FAIL,    ch_action_fail       },
+-	{CH_STATE_RXERR,      CH_EVENT_MC_FAIL,    ch_action_fail       },
+-};
+-
+-static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
+-
+-/**
+- * Functions related to setup and device detection.
+- *****************************************************************************/
+-
+-static inline int
+-less_than(char *id1, char *id2)
+-{
+-	int dev1, dev2, i;
+-
+-	for (i = 0; i < 5; i++) {
+-		id1++;
+-		id2++;
+-	}
+-	dev1 = simple_strtoul(id1, &id1, 16);
+-	dev2 = simple_strtoul(id2, &id2, 16);
+-
+-	return (dev1 < dev2);
+-}
+-
+-/**
+- * Add a new channel to the list of channels.
+- * Keeps the channel list sorted.
+- *
+- * @param cdev  The ccw_device to be added.
+- * @param type  The type class of the new channel.
+- *
+- * @return 0 on success, !0 on error.
+- */
+-static int
+-add_channel(struct ccw_device *cdev, enum channel_types type)
+-{
+-	struct channel **c = &channels;
+-	struct channel *ch;
+-
+-	DBF_TEXT(trace, 2, __FUNCTION__);
+-	ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
+-	if (!ch) {
+-		ctc_pr_warn("ctc: Out of memory in add_channel\n");
+-		return -1;
+-	}
+-	/* assure all flags and counters are reset */
+-	ch->ccw = kzalloc(8 * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
+-	if (!ch->ccw) {
+-		kfree(ch);
+-		ctc_pr_warn("ctc: Out of memory in add_channel\n");
+-		return -1;
+-	}
+-
+-
+-	/**
+-	 * "static" ccws are used in the following way:
+-	 *
+-	 * ccw[0..2] (Channel program for generic I/O):
+-	 *           0: prepare
+-	 *           1: read or write (depending on direction) with fixed
+-	 *              buffer (idal allocated once when buffer is allocated)
+-	 *           2: nop
+-	 * ccw[3..5] (Channel program for direct write of packets)
+-	 *           3: prepare
+-	 *           4: write (idal allocated on every write).
+-	 *           5: nop
+-	 * ccw[6..7] (Channel program for initial channel setup):
+-	 *           6: set extended mode
+-	 *           7: nop
+-	 *
+-	 * ch->ccw[0..5] are initialized in ch_action_start because
+-	 * the channel's direction is yet unknown here.
+-	 */
+-	ch->ccw[6].cmd_code = CCW_CMD_SET_EXTENDED;
+-	ch->ccw[6].flags = CCW_FLAG_SLI;
+-
+-	ch->ccw[7].cmd_code = CCW_CMD_NOOP;
+-	ch->ccw[7].flags = CCW_FLAG_SLI;
+-
+-	ch->cdev = cdev;
+-	snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
+-	ch->type = type;
+-	ch->fsm = init_fsm(ch->id, ch_state_names,
+-			   ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
+-			   ch_fsm, CH_FSM_LEN, GFP_KERNEL);
+-	if (ch->fsm == NULL) {
+-		ctc_pr_warn("ctc: Could not create FSM in add_channel\n");
+-		kfree(ch->ccw);
+-		kfree(ch);
+-		return -1;
+-	}
+-	fsm_newstate(ch->fsm, CH_STATE_IDLE);
+-	ch->irb = kzalloc(sizeof(struct irb), GFP_KERNEL);
+-	if (!ch->irb) {
+-		ctc_pr_warn("ctc: Out of memory in add_channel\n");
+-		kfree_fsm(ch->fsm);
+-		kfree(ch->ccw);
+-		kfree(ch);
+-		return -1;
+-	}
+-	while (*c && less_than((*c)->id, ch->id))
+-		c = &(*c)->next;
+-	if (*c && (!strncmp((*c)->id, ch->id, CTC_ID_SIZE))) {
+-		ctc_pr_debug(
+-			"ctc: add_channel: device %s already in list, "
+-			"using old entry\n", (*c)->id);
+-		kfree(ch->irb);
+-		kfree_fsm(ch->fsm);
+-		kfree(ch->ccw);
+-		kfree(ch);
+-		return 0;
+-	}
+-
+-	spin_lock_init(&ch->collect_lock);
+-
+-	fsm_settimer(ch->fsm, &ch->timer);
+-	skb_queue_head_init(&ch->io_queue);
+-	skb_queue_head_init(&ch->collect_queue);
+-	ch->next = *c;
+-	*c = ch;
+-	return 0;
+-}
+-
+-/**
+- * Release a specific channel in the channel list.
+- *
+- * @param ch Pointer to channel struct to be released.
+- */
+-static void
+-channel_free(struct channel *ch)
+-{
+-	ch->flags &= ~CHANNEL_FLAGS_INUSE;
+-	fsm_newstate(ch->fsm, CH_STATE_IDLE);
+-}
+-
+-/**
+- * Remove a specific channel in the channel list.
+- *
+- * @param ch Pointer to channel struct to be released.
+- */
+-static void
+-channel_remove(struct channel *ch)
+-{
+-	struct channel **c = &channels;
+-
+-	DBF_TEXT(trace, 2, __FUNCTION__);
+-	if (ch == NULL)
+-		return;
+-
+-	channel_free(ch);
+-	while (*c) {
+-		if (*c == ch) {
+-			*c = ch->next;
+-			fsm_deltimer(&ch->timer);
+-			kfree_fsm(ch->fsm);
+-			clear_normalized_cda(&ch->ccw[4]);
+-			if (ch->trans_skb != NULL) {
+-				clear_normalized_cda(&ch->ccw[1]);
+-				dev_kfree_skb(ch->trans_skb);
+-			}
+-			kfree(ch->ccw);
+-			kfree(ch->irb);
+-			kfree(ch);
+-			return;
+-		}
+-		c = &((*c)->next);
+-	}
+-}
+-
+-/**
+- * Get a specific channel from the channel list.
+- *
+- * @param type Type of channel we are interested in.
+- * @param id Id of channel we are interested in.
+- * @param direction Direction we want to use this channel for.
+- *
+- * @return Pointer to a channel or NULL if no matching channel available.
+- */
+-static struct channel
+-*
+-channel_get(enum channel_types type, char *id, int direction)
+-{
+-	struct channel *ch = channels;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-#ifdef DEBUG
+-	ctc_pr_debug("ctc: %s(): searching for ch with id %s and type %d\n",
+-		     __func__, id, type);
+-#endif
+-
+-	while (ch && ((strncmp(ch->id, id, CTC_ID_SIZE)) || (ch->type != type))) {
+-#ifdef DEBUG
+-		ctc_pr_debug("ctc: %s(): ch=0x%p (id=%s, type=%d\n",
+-			     __func__, ch, ch->id, ch->type);
+-#endif
+-		ch = ch->next;
+-	}
+-#ifdef DEBUG
+-	ctc_pr_debug("ctc: %s(): ch=0x%pq (id=%s, type=%d\n",
+-		     __func__, ch, ch->id, ch->type);
+-#endif
+-	if (!ch) {
+-		ctc_pr_warn("ctc: %s(): channel with id %s "
+-			    "and type %d not found in channel list\n",
+-			    __func__, id, type);
+-	} else {
+-		if (ch->flags & CHANNEL_FLAGS_INUSE)
+-			ch = NULL;
+-		else {
+-			ch->flags |= CHANNEL_FLAGS_INUSE;
+-			ch->flags &= ~CHANNEL_FLAGS_RWMASK;
+-			ch->flags |= (direction == WRITE)
+-			    ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ;
+-			fsm_newstate(ch->fsm, CH_STATE_STOPPED);
+-		}
+-	}
+-	return ch;
+-}
+-
+-/**
+- * Return the channel type by name.
+- *
+- * @param name Name of network interface.
+- *
+- * @return Type class of channel to be used for that interface.
+- */
+-static enum channel_types inline
+-extract_channel_media(char *name)
+-{
+-	enum channel_types ret = channel_type_unknown;
+-
+-	if (name != NULL) {
+-		if (strncmp(name, "ctc", 3) == 0)
+-			ret = channel_type_parallel;
+-		if (strncmp(name, "escon", 5) == 0)
+-			ret = channel_type_escon;
+-	}
+-	return ret;
+-}
+-
+-static long
+-__ctc_check_irb_error(struct ccw_device *cdev, struct irb *irb)
+-{
+-	if (!IS_ERR(irb))
+-		return 0;
+-
+-	switch (PTR_ERR(irb)) {
+-	case -EIO:
+-		ctc_pr_warn("i/o-error on device %s\n", cdev->dev.bus_id);
+-//		CTC_DBF_TEXT(trace, 2, "ckirberr");
+-//		CTC_DBF_TEXT_(trace, 2, "  rc%d", -EIO);
+-		break;
+-	case -ETIMEDOUT:
+-		ctc_pr_warn("timeout on device %s\n", cdev->dev.bus_id);
+-//		CTC_DBF_TEXT(trace, 2, "ckirberr");
+-//		CTC_DBF_TEXT_(trace, 2, "  rc%d", -ETIMEDOUT);
+-		break;
+-	default:
+-		ctc_pr_warn("unknown error %ld on device %s\n", PTR_ERR(irb),
+-			   cdev->dev.bus_id);
+-//		CTC_DBF_TEXT(trace, 2, "ckirberr");
+-//		CTC_DBF_TEXT(trace, 2, "  rc???");
+-	}
+-	return PTR_ERR(irb);
+-}
+-
+-/**
+- * Main IRQ handler.
+- *
+- * @param cdev    The ccw_device the interrupt is for.
+- * @param intparm interruption parameter.
+- * @param irb     interruption response block.
+- */
+-static void
+-ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
+-{
+-	struct channel *ch;
+-	struct net_device *dev;
+-	struct ctc_priv *priv;
+-
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-	if (__ctc_check_irb_error(cdev, irb))
+-		return;
+-
+-	/* Check for unsolicited interrupts. */
+-	if (!cdev->dev.driver_data) {
+-		ctc_pr_warn("ctc: Got unsolicited irq: %s c-%02x d-%02x\n",
+-			    cdev->dev.bus_id, irb->scsw.cstat,
+-			    irb->scsw.dstat);
+-		return;
+-	}
+-
+-	priv = ((struct ccwgroup_device *)cdev->dev.driver_data)
+-		->dev.driver_data;
+-
+-	/* Try to extract channel from driver data. */
+-	if (priv->channel[READ]->cdev == cdev)
+-		ch = priv->channel[READ];
+-	else if (priv->channel[WRITE]->cdev == cdev)
+-		ch = priv->channel[WRITE];
+-	else {
+-		ctc_pr_err("ctc: Can't determine channel for interrupt, "
+-			   "device %s\n", cdev->dev.bus_id);
+-		return;
+-	}
+-
+-	dev = (struct net_device *) (ch->netdev);
+-	if (dev == NULL) {
+-		ctc_pr_crit("ctc: ctc_irq_handler dev=NULL bus_id=%s, ch=0x%p\n",
+-			    cdev->dev.bus_id, ch);
+-		return;
+-	}
+-
+-#ifdef DEBUG
+-	ctc_pr_debug("%s: interrupt for device: %s received c-%02x d-%02x\n",
+-		     dev->name, ch->id, irb->scsw.cstat, irb->scsw.dstat);
+-#endif
+-
+-	/* Copy interruption response block. */
+-	memcpy(ch->irb, irb, sizeof(struct irb));
+-
+-	/* Check for good subchannel return code, otherwise error message */
+-	if (ch->irb->scsw.cstat) {
+-		fsm_event(ch->fsm, CH_EVENT_SC_UNKNOWN, ch);
+-		ctc_pr_warn("%s: subchannel check for device: %s - %02x %02x\n",
+-			    dev->name, ch->id, ch->irb->scsw.cstat,
+-			    ch->irb->scsw.dstat);
+-		return;
+-	}
+-
+-	/* Check the reason-code of a unit check */
+-	if (ch->irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+-		ccw_unit_check(ch, ch->irb->ecw[0]);
+-		return;
+-	}
+-	if (ch->irb->scsw.dstat & DEV_STAT_BUSY) {
+-		if (ch->irb->scsw.dstat & DEV_STAT_ATTENTION)
+-			fsm_event(ch->fsm, CH_EVENT_ATTNBUSY, ch);
+-		else
+-			fsm_event(ch->fsm, CH_EVENT_BUSY, ch);
+-		return;
+-	}
+-	if (ch->irb->scsw.dstat & DEV_STAT_ATTENTION) {
+-		fsm_event(ch->fsm, CH_EVENT_ATTN, ch);
+-		return;
+-	}
+-	if ((ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
+-	    (ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
+-	    (ch->irb->scsw.stctl ==
+-	     (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))
+-		fsm_event(ch->fsm, CH_EVENT_FINSTAT, ch);
+-	else
+-		fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
+-
+-}
+-
+-/**
+- * Actions for interface - statemachine.
+- *****************************************************************************/
+-
+-/**
+- * Startup channels by sending CH_EVENT_START to each channel.
+- *
+- * @param fi    An instance of an interface statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from struct net_device * upon call.
+- */
+-static void
+-dev_action_start(fsm_instance * fi, int event, void *arg)
+-{
+-	struct net_device *dev = (struct net_device *) arg;
+-	struct ctc_priv *privptr = dev->priv;
+-	int direction;
+-
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-	fsm_deltimer(&privptr->restart_timer);
+-	fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+-	for (direction = READ; direction <= WRITE; direction++) {
+-		struct channel *ch = privptr->channel[direction];
+-		fsm_event(ch->fsm, CH_EVENT_START, ch);
+-	}
+-}
+-
+-/**
+- * Shutdown channels by sending CH_EVENT_STOP to each channel.
+- *
+- * @param fi    An instance of an interface statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from struct net_device * upon call.
+- */
+-static void
+-dev_action_stop(fsm_instance * fi, int event, void *arg)
+-{
+-	struct net_device *dev = (struct net_device *) arg;
+-	struct ctc_priv *privptr = dev->priv;
+-	int direction;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+-	for (direction = READ; direction <= WRITE; direction++) {
+-		struct channel *ch = privptr->channel[direction];
+-		fsm_event(ch->fsm, CH_EVENT_STOP, ch);
+-	}
+-}
+-static void
+-dev_action_restart(fsm_instance *fi, int event, void *arg)
+-{
+-	struct net_device *dev = (struct net_device *)arg;
+-	struct ctc_priv *privptr = dev->priv;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	ctc_pr_debug("%s: Restarting\n", dev->name);
+-	dev_action_stop(fi, event, arg);
+-	fsm_event(privptr->fsm, DEV_EVENT_STOP, dev);
+-	fsm_addtimer(&privptr->restart_timer, CTC_TIMEOUT_5SEC,
+-		     DEV_EVENT_START, dev);
+-}
+-
+-/**
+- * Called from channel statemachine
+- * when a channel is up and running.
+- *
+- * @param fi    An instance of an interface statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from struct net_device * upon call.
+- */
+-static void
+-dev_action_chup(fsm_instance * fi, int event, void *arg)
+-{
+-	struct net_device *dev = (struct net_device *) arg;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	switch (fsm_getstate(fi)) {
+-		case DEV_STATE_STARTWAIT_RXTX:
+-			if (event == DEV_EVENT_RXUP)
+-				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+-			else
+-				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+-			break;
+-		case DEV_STATE_STARTWAIT_RX:
+-			if (event == DEV_EVENT_RXUP) {
+-				fsm_newstate(fi, DEV_STATE_RUNNING);
+-				ctc_pr_info("%s: connected with remote side\n",
+-					    dev->name);
+-				ctc_clear_busy(dev);
+-			}
+-			break;
+-		case DEV_STATE_STARTWAIT_TX:
+-			if (event == DEV_EVENT_TXUP) {
+-				fsm_newstate(fi, DEV_STATE_RUNNING);
+-				ctc_pr_info("%s: connected with remote side\n",
+-					    dev->name);
+-				ctc_clear_busy(dev);
+-			}
+-			break;
+-		case DEV_STATE_STOPWAIT_TX:
+-			if (event == DEV_EVENT_RXUP)
+-				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+-			break;
+-		case DEV_STATE_STOPWAIT_RX:
+-			if (event == DEV_EVENT_TXUP)
+-				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+-			break;
+-	}
+-}
+-
+-/**
+- * Called from channel statemachine
+- * when a channel has been shutdown.
+- *
+- * @param fi    An instance of an interface statemachine.
+- * @param event The event, just happened.
+- * @param arg   Generic pointer, casted from struct net_device * upon call.
+- */
+-static void
+-dev_action_chdown(fsm_instance * fi, int event, void *arg)
+-{
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	switch (fsm_getstate(fi)) {
+-		case DEV_STATE_RUNNING:
+-			if (event == DEV_EVENT_TXDOWN)
+-				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+-			else
+-				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+-			break;
+-		case DEV_STATE_STARTWAIT_RX:
+-			if (event == DEV_EVENT_TXDOWN)
+-				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+-			break;
+-		case DEV_STATE_STARTWAIT_TX:
+-			if (event == DEV_EVENT_RXDOWN)
+-				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+-			break;
+-		case DEV_STATE_STOPWAIT_RXTX:
+-			if (event == DEV_EVENT_TXDOWN)
+-				fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);
+-			else
+-				fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);
+-			break;
+-		case DEV_STATE_STOPWAIT_RX:
+-			if (event == DEV_EVENT_RXDOWN)
+-				fsm_newstate(fi, DEV_STATE_STOPPED);
+-			break;
+-		case DEV_STATE_STOPWAIT_TX:
+-			if (event == DEV_EVENT_TXDOWN)
+-				fsm_newstate(fi, DEV_STATE_STOPPED);
+-			break;
+-	}
+-}
+-
+-static const fsm_node dev_fsm[] = {
+-	{DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start},
+-
+-	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_START,   dev_action_start   },
+-	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RXDOWN,  dev_action_chdown  },
+-	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_TXDOWN,  dev_action_chdown  },
+- 	{DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RESTART, dev_action_restart },
+-
+-	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_START,   dev_action_start   },
+-	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXUP,    dev_action_chup    },
+-	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_TXUP,    dev_action_chup    },
+-	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXDOWN,  dev_action_chdown  },
+- 	{DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RESTART, dev_action_restart },
+-
+-	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_START,   dev_action_start   },
+-	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RXUP,    dev_action_chup    },
+-	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXUP,    dev_action_chup    },
+-	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXDOWN,  dev_action_chdown  },
+- 	{DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RESTART, dev_action_restart },
+-
+-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP,    dev_action_stop    },
+-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP,    dev_action_chup    },
+-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP,    dev_action_chup    },
+-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN,  dev_action_chdown  },
+-	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN,  dev_action_chdown  },
+- 	{DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
+-
+-	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_STOP,    dev_action_stop    },
+-	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXUP,    dev_action_chup    },
+-	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_TXUP,    dev_action_chup    },
+-	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXDOWN,  dev_action_chdown  },
+- 	{DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RESTART, dev_action_restart },
+-
+-	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_STOP,    dev_action_stop    },
+-	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RXUP,    dev_action_chup    },
+-	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXUP,    dev_action_chup    },
+-	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXDOWN,  dev_action_chdown  },
+- 	{DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RESTART, dev_action_restart },
+-
+-	{DEV_STATE_RUNNING,        DEV_EVENT_STOP,    dev_action_stop    },
+-	{DEV_STATE_RUNNING,        DEV_EVENT_RXDOWN,  dev_action_chdown  },
+-	{DEV_STATE_RUNNING,        DEV_EVENT_TXDOWN,  dev_action_chdown  },
+-	{DEV_STATE_RUNNING,        DEV_EVENT_TXUP,    fsm_action_nop     },
+-	{DEV_STATE_RUNNING,        DEV_EVENT_RXUP,    fsm_action_nop     },
+- 	{DEV_STATE_RUNNING,        DEV_EVENT_RESTART, dev_action_restart },
+-};
+-
+-static const int DEV_FSM_LEN = sizeof (dev_fsm) / sizeof (fsm_node);
+-
+-/**
+- * Transmit a packet.
+- * This is a helper function for ctc_tx().
+- *
+- * @param ch Channel to be used for sending.
+- * @param skb Pointer to struct sk_buff of packet to send.
+- *            The linklevel header has already been set up
+- *            by ctc_tx().
+- *
+- * @return 0 on success, -ERRNO on failure. (Never fails.)
+- */
+-static int
+-transmit_skb(struct channel *ch, struct sk_buff *skb)
+-{
+-	unsigned long saveflags;
+-	struct ll_header header;
+-	int rc = 0;
+-
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-	/* we need to acquire the lock for testing the state
+-	 * otherwise we can have an IRQ changing the state to
+-	 * TXIDLE after the test but before acquiring the lock.
+-	 */
+-	spin_lock_irqsave(&ch->collect_lock, saveflags);
+-	if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
+-		int l = skb->len + LL_HEADER_LENGTH;
+-
+-		if (ch->collect_len + l > ch->max_bufsize - 2) {
+-			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+-			return -EBUSY;
+-		} else {
+-			atomic_inc(&skb->users);
+-			header.length = l;
+-			header.type = skb->protocol;
+-			header.unused = 0;
+-			memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
+-			       LL_HEADER_LENGTH);
+-			skb_queue_tail(&ch->collect_queue, skb);
+-			ch->collect_len += l;
+-		}
+-		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+-	} else {
+-		__u16 block_len;
+-		int ccw_idx;
+-		struct sk_buff *nskb;
+-		unsigned long hi;
+-		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+-		/**
+-		 * Protect skb against beeing free'd by upper
+-		 * layers.
+-		 */
+-		atomic_inc(&skb->users);
+-		ch->prof.txlen += skb->len;
+-		header.length = skb->len + LL_HEADER_LENGTH;
+-		header.type = skb->protocol;
+-		header.unused = 0;
+-		memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
+-		       LL_HEADER_LENGTH);
+-		block_len = skb->len + 2;
+-		*((__u16 *) skb_push(skb, 2)) = block_len;
+-
+-		/**
+-		 * IDAL support in CTC is broken, so we have to
+-		 * care about skb's above 2G ourselves.
+-		 */
+-		hi = ((unsigned long)skb_tail_pointer(skb) +
+-		      LL_HEADER_LENGTH) >> 31;
+-		if (hi) {
+-			nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
+-			if (!nskb) {
+-				atomic_dec(&skb->users);
+-				skb_pull(skb, LL_HEADER_LENGTH + 2);
+-				ctc_clear_busy(ch->netdev);
+-				return -ENOMEM;
+-			} else {
+-				memcpy(skb_put(nskb, skb->len),
+-				       skb->data, skb->len);
+-				atomic_inc(&nskb->users);
+-				atomic_dec(&skb->users);
+-				dev_kfree_skb_irq(skb);
+-				skb = nskb;
+-			}
+-		}
+-
+-		ch->ccw[4].count = block_len;
+-		if (set_normalized_cda(&ch->ccw[4], skb->data)) {
+-			/**
+-			 * idal allocation failed, try via copying to
+-			 * trans_skb. trans_skb usually has a pre-allocated
+-			 * idal.
+-			 */
+-			if (ctc_checkalloc_buffer(ch, 1)) {
+-				/**
+-				 * Remove our header. It gets added
+-				 * again on retransmit.
+-				 */
+-				atomic_dec(&skb->users);
+-				skb_pull(skb, LL_HEADER_LENGTH + 2);
+-				ctc_clear_busy(ch->netdev);
+-				return -EBUSY;
+-			}
+-
+-			skb_reset_tail_pointer(ch->trans_skb);
+-			ch->trans_skb->len = 0;
+-			ch->ccw[1].count = skb->len;
+-			skb_copy_from_linear_data(skb, skb_put(ch->trans_skb,
+-							       skb->len),
+-						  skb->len);
+-			atomic_dec(&skb->users);
+-			dev_kfree_skb_irq(skb);
+-			ccw_idx = 0;
+-		} else {
+-			skb_queue_tail(&ch->io_queue, skb);
+-			ccw_idx = 3;
+-		}
+-		ch->retry = 0;
+-		fsm_newstate(ch->fsm, CH_STATE_TX);
+-		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+-		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+-		ch->prof.send_stamp = current_kernel_time();
+-		rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
+-				      (unsigned long) ch, 0xff, 0);
+-		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+-		if (ccw_idx == 3)
+-			ch->prof.doios_single++;
+-		if (rc != 0) {
+-			fsm_deltimer(&ch->timer);
+-			ccw_check_return_code(ch, rc, "single skb TX");
+-			if (ccw_idx == 3)
+-				skb_dequeue_tail(&ch->io_queue);
+-			/**
+-			 * Remove our header. It gets added
+-			 * again on retransmit.
+-			 */
+-			skb_pull(skb, LL_HEADER_LENGTH + 2);
+-		} else {
+-			if (ccw_idx == 0) {
+-				struct net_device *dev = ch->netdev;
+-				struct ctc_priv *privptr = dev->priv;
+-				privptr->stats.tx_packets++;
+-				privptr->stats.tx_bytes +=
+-				    skb->len - LL_HEADER_LENGTH;
+-			}
+-		}
+-	}
+-
+-	ctc_clear_busy(ch->netdev);
+-	return rc;
+-}
+-
+-/**
+- * Interface API for upper network layers
+- *****************************************************************************/
+-
+-/**
+- * Open an interface.
+- * Called from generic network layer when ifconfig up is run.
+- *
+- * @param dev Pointer to interface struct.
+- *
+- * @return 0 on success, -ERRNO on failure. (Never fails.)
+- */
+-static int
+-ctc_open(struct net_device * dev)
+-{
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_START, dev);
+-	return 0;
+-}
+-
+-/**
+- * Close an interface.
+- * Called from generic network layer when ifconfig down is run.
+- *
+- * @param dev Pointer to interface struct.
+- *
+- * @return 0 on success, -ERRNO on failure. (Never fails.)
+- */
+-static int
+-ctc_close(struct net_device * dev)
+-{
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_STOP, dev);
+-	return 0;
+-}
+-
+-/**
+- * Start transmission of a packet.
+- * Called from generic network device layer.
+- *
+- * @param skb Pointer to buffer containing the packet.
+- * @param dev Pointer to interface struct.
+- *
+- * @return 0 if packet consumed, !0 if packet rejected.
+- *         Note: If we return !0, then the packet is free'd by
+- *               the generic network layer.
+- */
+-static int
+-ctc_tx(struct sk_buff *skb, struct net_device * dev)
+-{
+-	int rc = 0;
+-	struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
+-
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-	/**
+-	 * Some sanity checks ...
+-	 */
+-	if (skb == NULL) {
+-		ctc_pr_warn("%s: NULL sk_buff passed\n", dev->name);
+-		privptr->stats.tx_dropped++;
+-		return 0;
+-	}
+-	if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
+-		ctc_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
+-			    dev->name, LL_HEADER_LENGTH + 2);
+-		dev_kfree_skb(skb);
+-		privptr->stats.tx_dropped++;
+-		return 0;
+-	}
+-
+-	/**
+-	 * If channels are not running, try to restart them
+-	 * and throw away packet.
+-	 */
+-	if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
+-		fsm_event(privptr->fsm, DEV_EVENT_START, dev);
+-		dev_kfree_skb(skb);
+-		privptr->stats.tx_dropped++;
+-		privptr->stats.tx_errors++;
+-		privptr->stats.tx_carrier_errors++;
+-		return 0;
+-	}
+-
+-	if (ctc_test_and_set_busy(dev))
+-		return -EBUSY;
+-
+-	dev->trans_start = jiffies;
+-	if (transmit_skb(privptr->channel[WRITE], skb) != 0)
+-		rc = 1;
+-	return rc;
+-}
+-
+-/**
+- * Sets MTU of an interface.
+- *
+- * @param dev     Pointer to interface struct.
+- * @param new_mtu The new MTU to use for this interface.
+- *
+- * @return 0 on success, -EINVAL if MTU is out of valid range.
+- *         (valid range is 576 .. 65527). If VM is on the
+- *         remote side, maximum MTU is 32760, however this is
+- *         <em>not</em> checked here.
+- */
+-static int
+-ctc_change_mtu(struct net_device * dev, int new_mtu)
+-{
+-	struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	if ((new_mtu < 576) || (new_mtu > 65527) ||
+-	    (new_mtu > (privptr->channel[READ]->max_bufsize -
+-			LL_HEADER_LENGTH - 2)))
+-		return -EINVAL;
+-	dev->mtu = new_mtu;
+-	dev->hard_header_len = LL_HEADER_LENGTH + 2;
+-	return 0;
+-}
+-
+-/**
+- * Returns interface statistics of a device.
+- *
+- * @param dev Pointer to interface struct.
+- *
+- * @return Pointer to stats struct of this interface.
+- */
+-static struct net_device_stats *
+-ctc_stats(struct net_device * dev)
+-{
+-	return &((struct ctc_priv *) dev->priv)->stats;
+-}
+-
+-/*
+- * sysfs attributes
+- */
+-
+-static ssize_t
+-buffer_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct ctc_priv *priv;
+-
+-	priv = dev->driver_data;
+-	if (!priv)
+-		return -ENODEV;
+-	return sprintf(buf, "%d\n",
+-			priv->buffer_size);
+-}
+-
+-static ssize_t
+-buffer_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct ctc_priv *priv;
+-	struct net_device *ndev;
+-	int bs1;
+-	char buffer[16];
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	DBF_TEXT(trace, 3, buf);
+-	priv = dev->driver_data;
+-	if (!priv) {
+-		DBF_TEXT(trace, 3, "bfnopriv");
+-		return -ENODEV;
+-	}
+-
+-	sscanf(buf, "%u", &bs1);
+-	if (bs1 > CTC_BUFSIZE_LIMIT)
+-		goto einval;
+-	if (bs1 < (576 + LL_HEADER_LENGTH + 2))
+-		goto einval;
+-	priv->buffer_size = bs1;	// just to overwrite the default
+-
+-	ndev = priv->channel[READ]->netdev;
+-	if (!ndev) {
+-		DBF_TEXT(trace, 3, "bfnondev");
+-		return -ENODEV;
+-	}
+-
+-	if ((ndev->flags & IFF_RUNNING) &&
+-	    (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
+-		goto einval;
+-
+-	priv->channel[READ]->max_bufsize = bs1;
+-	priv->channel[WRITE]->max_bufsize = bs1;
+-	if (!(ndev->flags & IFF_RUNNING))
+-		ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
+-	priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
+-	priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
+-
+-	sprintf(buffer, "%d",priv->buffer_size);
+-	DBF_TEXT(trace, 3, buffer);
+-	return count;
+-
+-einval:
+-	DBF_TEXT(trace, 3, "buff_err");
+-	return -EINVAL;
+-}
+-
+-static ssize_t
+-loglevel_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	return sprintf(buf, "%d\n", loglevel);
+-}
+-
+-static ssize_t
+-loglevel_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	int ll1;
+-
+-	DBF_TEXT(trace, 5, __FUNCTION__);
+-	sscanf(buf, "%i", &ll1);
+-
+-	if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0))
+-		return -EINVAL;
+-	loglevel = ll1;
+-	return count;
+-}
+-
+-static void
+-ctc_print_statistics(struct ctc_priv *priv)
+-{
+-	char *sbuf;
+-	char *p;
+-
+-	DBF_TEXT(trace, 4, __FUNCTION__);
+-	if (!priv)
+-		return;
+-	sbuf = kmalloc(2048, GFP_KERNEL);
+-	if (sbuf == NULL)
+-		return;
+-	p = sbuf;
+-
+-	p += sprintf(p, "  Device FSM state: %s\n",
+-		     fsm_getstate_str(priv->fsm));
+-	p += sprintf(p, "  RX channel FSM state: %s\n",
+-		     fsm_getstate_str(priv->channel[READ]->fsm));
+-	p += sprintf(p, "  TX channel FSM state: %s\n",
+-		     fsm_getstate_str(priv->channel[WRITE]->fsm));
+-	p += sprintf(p, "  Max. TX buffer used: %ld\n",
+-		     priv->channel[WRITE]->prof.maxmulti);
+-	p += sprintf(p, "  Max. chained SKBs: %ld\n",
+-		     priv->channel[WRITE]->prof.maxcqueue);
+-	p += sprintf(p, "  TX single write ops: %ld\n",
+-		     priv->channel[WRITE]->prof.doios_single);
+-	p += sprintf(p, "  TX multi write ops: %ld\n",
+-		     priv->channel[WRITE]->prof.doios_multi);
+-	p += sprintf(p, "  Netto bytes written: %ld\n",
+-		     priv->channel[WRITE]->prof.txlen);
+-	p += sprintf(p, "  Max. TX IO-time: %ld\n",
+-		     priv->channel[WRITE]->prof.tx_time);
+-
+-	ctc_pr_debug("Statistics for %s:\n%s",
+-		     priv->channel[WRITE]->netdev->name, sbuf);
+-	kfree(sbuf);
+-	return;
+-}
+-
+-static ssize_t
+-stats_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct ctc_priv *priv = dev->driver_data;
+-	if (!priv)
+-		return -ENODEV;
+-	ctc_print_statistics(priv);
+-	return sprintf(buf, "0\n");
+-}
+-
+-static ssize_t
+-stats_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct ctc_priv *priv = dev->driver_data;
+-	if (!priv)
+-		return -ENODEV;
+-	/* Reset statistics */
+-	memset(&priv->channel[WRITE]->prof, 0,
+-			sizeof(priv->channel[WRITE]->prof));
+-	return count;
+-}
+-
+-static void
+-ctc_netdev_unregister(struct net_device * dev)
+-{
+-	struct ctc_priv *privptr;
+-
+-	if (!dev)
+-		return;
+-	privptr = (struct ctc_priv *) dev->priv;
+-	unregister_netdev(dev);
+-}
+-
+-static int
+-ctc_netdev_register(struct net_device * dev)
+-{
+-	return register_netdev(dev);
+-}
+-
+-static void
+-ctc_free_netdevice(struct net_device * dev, int free_dev)
+-{
+-	struct ctc_priv *privptr;
+-	if (!dev)
+-		return;
+-	privptr = dev->priv;
+-	if (privptr) {
+-		if (privptr->fsm)
+-			kfree_fsm(privptr->fsm);
+-		kfree(privptr);
+-	}
+-#ifdef MODULE
+-	if (free_dev)
+-		free_netdev(dev);
+-#endif
+-}
+-
+-static ssize_t
+-ctc_proto_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct ctc_priv *priv;
+-
+-	priv = dev->driver_data;
+-	if (!priv)
+-		return -ENODEV;
+-
+-	return sprintf(buf, "%d\n", priv->protocol);
+-}
+-
+-static ssize_t
+-ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct ctc_priv *priv;
+-	int value;
+-
+-	DBF_TEXT(trace, 3, __FUNCTION__);
+-	pr_debug("%s() called\n", __FUNCTION__);
+-
+-	priv = dev->driver_data;
+-	if (!priv)
+-		return -ENODEV;
+-	sscanf(buf, "%u", &value);
+-	if (!((value == CTC_PROTO_S390)  ||
+-	      (value == CTC_PROTO_LINUX) ||
+-	      (value == CTC_PROTO_OS390)))
+-		return -EINVAL;
+-	priv->protocol = value;
+-
+-	return count;
+-}
+-
+-static ssize_t
+-ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct ccwgroup_device *cgdev;
+-
+-	cgdev = to_ccwgroupdev(dev);
+-	if (!cgdev)
+-		return -ENODEV;
+-
+-	return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]);
+-}
+-
+-static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
+-static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store);
+-static DEVICE_ATTR(type, 0444, ctc_type_show, NULL);
+-
+-static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
+-static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
+-
+-static struct attribute *ctc_attr[] = {
+-	&dev_attr_protocol.attr,
+-	&dev_attr_type.attr,
+-	&dev_attr_buffer.attr,
+-	NULL,
+-};
+-
+-static struct attribute_group ctc_attr_group = {
+-	.attrs = ctc_attr,
+-};
+-
+-static int
+-ctc_add_attributes(struct device *dev)
+-{
+-	int rc;
+-
+-	rc = device_create_file(dev, &dev_attr_loglevel);
+-	if (rc)
+-		goto out;
+-	rc = device_create_file(dev, &dev_attr_stats);
+-	if (!rc)
+-		goto out;
+-	device_remove_file(dev, &dev_attr_loglevel);
+-out:
+-	return rc;
+-}
+-
+-static void
+-ctc_remove_attributes(struct device *dev)
+-{
+-	device_remove_file(dev, &dev_attr_stats);
+-	device_remove_file(dev, &dev_attr_loglevel);
+-}
+-
+-static int
+-ctc_add_files(struct device *dev)
+-{
+-	pr_debug("%s() called\n", __FUNCTION__);
+-
+-	return sysfs_create_group(&dev->kobj, &ctc_attr_group);
+-}
+-
+-static void
+-ctc_remove_files(struct device *dev)
+-{
+-	pr_debug("%s() called\n", __FUNCTION__);
+-
+-	sysfs_remove_group(&dev->kobj, &ctc_attr_group);
+-}
+-
+-/**
+- * Add ctc specific attributes.
+- * Add ctc private data.
+- *
+- * @param cgdev pointer to ccwgroup_device just added
+- *
+- * @returns 0 on success, !0 on failure.
+- */
+-static int
+-ctc_probe_device(struct ccwgroup_device *cgdev)
+-{
+-	struct ctc_priv *priv;
+-	int rc;
+-	char buffer[16];
+-
+-	pr_debug("%s() called\n", __FUNCTION__);
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-
+-	if (!get_device(&cgdev->dev))
+-		return -ENODEV;
+-
+-	priv = kzalloc(sizeof(struct ctc_priv), GFP_KERNEL);
+-	if (!priv) {
+-		ctc_pr_err("%s: Out of memory\n", __func__);
+-		put_device(&cgdev->dev);
+-		return -ENOMEM;
+-	}
+-
+-	rc = ctc_add_files(&cgdev->dev);
+-	if (rc) {
+-		kfree(priv);
+-		put_device(&cgdev->dev);
+-		return rc;
+-	}
+-	priv->buffer_size = CTC_BUFSIZE_DEFAULT;
+-	cgdev->cdev[0]->handler = ctc_irq_handler;
+-	cgdev->cdev[1]->handler = ctc_irq_handler;
+-	cgdev->dev.driver_data = priv;
+-
+-	sprintf(buffer, "%p", priv);
+-	DBF_TEXT(data, 3, buffer);
+-
+-	sprintf(buffer, "%u", (unsigned int)sizeof(struct ctc_priv));
+-	DBF_TEXT(data, 3, buffer);
+-
+-	sprintf(buffer, "%p", &channels);
+-	DBF_TEXT(data, 3, buffer);
+-
+-	sprintf(buffer, "%u", (unsigned int)sizeof(struct channel));
+-	DBF_TEXT(data, 3, buffer);
+-
+-	return 0;
+-}
+-
+-/**
+- * Device setup function called by alloc_netdev().
+- *
+- * @param dev  Device to be setup.
+- */
+-void ctc_init_netdevice(struct net_device * dev)
+-{
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-
+-	if (dev->mtu == 0)
+-		dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
+-	dev->hard_start_xmit = ctc_tx;
+-	dev->open = ctc_open;
+-	dev->stop = ctc_close;
+-	dev->get_stats = ctc_stats;
+-	dev->change_mtu = ctc_change_mtu;
+-	dev->hard_header_len = LL_HEADER_LENGTH + 2;
+-	dev->addr_len = 0;
+-	dev->type = ARPHRD_SLIP;
+-	dev->tx_queue_len = 100;
+-	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+-}
+-
+-
+-/**
+- *
+- * Setup an interface.
+- *
+- * @param cgdev  Device to be setup.
+- *
+- * @returns 0 on success, !0 on failure.
+- */
+-static int
+-ctc_new_device(struct ccwgroup_device *cgdev)
+-{
+-	char read_id[CTC_ID_SIZE];
+-	char write_id[CTC_ID_SIZE];
+-	int direction;
+-	enum channel_types type;
+-	struct ctc_priv *privptr;
+-	struct net_device *dev;
+-	int ret;
+-	char buffer[16];
+-
+-	pr_debug("%s() called\n", __FUNCTION__);
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-
+-	privptr = cgdev->dev.driver_data;
+-	if (!privptr)
+-		return -ENODEV;
+-
+-	sprintf(buffer, "%d", privptr->buffer_size);
+-	DBF_TEXT(setup, 3, buffer);
+-
+-	type = get_channel_type(&cgdev->cdev[0]->id);
+-
+-	snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
+-	snprintf(write_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
+-
+-	if (add_channel(cgdev->cdev[0], type))
+-		return -ENOMEM;
+-	if (add_channel(cgdev->cdev[1], type))
+-		return -ENOMEM;
+-
+-	ret = ccw_device_set_online(cgdev->cdev[0]);
+-	if (ret != 0) {
+-			printk(KERN_WARNING
+-		 	"ccw_device_set_online (cdev[0]) failed with ret = %d\n", ret);
+-	}
+-
+-	ret = ccw_device_set_online(cgdev->cdev[1]);
+-	if (ret != 0) {
+-			printk(KERN_WARNING
+-		 	"ccw_device_set_online (cdev[1]) failed with ret = %d\n", ret);
+-	}
+-
+-	dev = alloc_netdev(0, "ctc%d", ctc_init_netdevice);
+-	if (!dev) {
+-		ctc_pr_warn("ctc_init_netdevice failed\n");
+-		goto out;
+-	}
+-	dev->priv = privptr;
+-
+-	privptr->fsm = init_fsm("ctcdev", dev_state_names,
+-			dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS,
+-			dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
+-	if (privptr->fsm == NULL) {
+-		free_netdev(dev);
+-		goto out;
+-	}
+-	fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
+-	fsm_settimer(privptr->fsm, &privptr->restart_timer);
+-
+-	for (direction = READ; direction <= WRITE; direction++) {
+-		privptr->channel[direction] =
+-		    channel_get(type, direction == READ ? read_id : write_id,
+-				direction);
+-		if (privptr->channel[direction] == NULL) {
+-			if (direction == WRITE)
+-				channel_free(privptr->channel[READ]);
+-
+-			ctc_free_netdevice(dev, 1);
+-			goto out;
+-		}
+-		privptr->channel[direction]->netdev = dev;
+-		privptr->channel[direction]->protocol = privptr->protocol;
+-		privptr->channel[direction]->max_bufsize = privptr->buffer_size;
+-	}
+-	/* sysfs magic */
+-	SET_NETDEV_DEV(dev, &cgdev->dev);
+-
+-	if (ctc_netdev_register(dev) != 0) {
+-		ctc_free_netdevice(dev, 1);
+-		goto out;
+-	}
+-
+-	if (ctc_add_attributes(&cgdev->dev)) {
+-		ctc_netdev_unregister(dev);
+-		dev->priv = NULL;
+-		ctc_free_netdevice(dev, 1);
+-		goto out;
+-	}
+-
+-	strlcpy(privptr->fsm->name, dev->name, sizeof (privptr->fsm->name));
+-
+-	print_banner();
+-
+-	ctc_pr_info("%s: read: %s, write: %s, proto: %d\n",
+-		    dev->name, privptr->channel[READ]->id,
+-		    privptr->channel[WRITE]->id, privptr->protocol);
+-
+-	return 0;
+-out:
+-	ccw_device_set_offline(cgdev->cdev[1]);
+-	ccw_device_set_offline(cgdev->cdev[0]);
+-
+-	return -ENODEV;
+-}
+-
+-/**
+- * Shutdown an interface.
+- *
+- * @param cgdev  Device to be shut down.
+- *
+- * @returns 0 on success, !0 on failure.
+- */
+-static int
+-ctc_shutdown_device(struct ccwgroup_device *cgdev)
+-{
+-	struct ctc_priv *priv;
+-	struct net_device *ndev;
+-
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-	pr_debug("%s() called\n", __FUNCTION__);
+-
+-
+-	priv = cgdev->dev.driver_data;
+-	ndev = NULL;
+-	if (!priv)
+-		return -ENODEV;
+-
+-	if (priv->channel[READ]) {
+-		ndev = priv->channel[READ]->netdev;
+-
+-		/* Close the device */
+-		ctc_close(ndev);
+-		ndev->flags &=~IFF_RUNNING;
+-
+-		ctc_remove_attributes(&cgdev->dev);
+-
+-		channel_free(priv->channel[READ]);
+-	}
+-	if (priv->channel[WRITE])
+-		channel_free(priv->channel[WRITE]);
+-
+-	if (ndev) {
+-		ctc_netdev_unregister(ndev);
+-		ndev->priv = NULL;
+-		ctc_free_netdevice(ndev, 1);
+-	}
+-
+-	if (priv->fsm)
+-		kfree_fsm(priv->fsm);
+-
+-	ccw_device_set_offline(cgdev->cdev[1]);
+-	ccw_device_set_offline(cgdev->cdev[0]);
+-
+-	if (priv->channel[READ])
+-		channel_remove(priv->channel[READ]);
+-	if (priv->channel[WRITE])
+-		channel_remove(priv->channel[WRITE]);
+-	priv->channel[READ] = priv->channel[WRITE] = NULL;
+-
+-	return 0;
+-
+-}
+-
+-static void
+-ctc_remove_device(struct ccwgroup_device *cgdev)
+-{
+-	struct ctc_priv *priv;
+-
+-	pr_debug("%s() called\n", __FUNCTION__);
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-
+-	priv = cgdev->dev.driver_data;
+-	if (!priv)
+-		return;
+-	if (cgdev->state == CCWGROUP_ONLINE)
+-		ctc_shutdown_device(cgdev);
+-	ctc_remove_files(&cgdev->dev);
+-	cgdev->dev.driver_data = NULL;
+-	kfree(priv);
+-	put_device(&cgdev->dev);
+-}
+-
+-static struct ccwgroup_driver ctc_group_driver = {
+-	.owner       = THIS_MODULE,
+-	.name        = "ctc",
+-	.max_slaves  = 2,
+-	.driver_id   = 0xC3E3C3,
+-	.probe       = ctc_probe_device,
+-	.remove      = ctc_remove_device,
+-	.set_online  = ctc_new_device,
+-	.set_offline = ctc_shutdown_device,
+-};
+-
+-/**
+- * Module related routines
+- *****************************************************************************/
+-
+-/**
+- * Prepare to be unloaded. Free IRQ's and release all resources.
+- * This is called just before this module is unloaded. It is
+- * <em>not</em> called, if the usage count is !0, so we don't need to check
+- * for that.
+- */
+-static void __exit
+-ctc_exit(void)
+-{
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-	unregister_cu3088_discipline(&ctc_group_driver);
+-	ctc_unregister_dbf_views();
+-	ctc_pr_info("CTC driver unloaded\n");
+-}
+-
+-/**
+- * Initialize module.
+- * This is called just after the module is loaded.
+- *
+- * @return 0 on success, !0 on error.
+- */
+-static int __init
+-ctc_init(void)
+-{
+-	int ret = 0;
+-
+-	loglevel = CTC_LOGLEVEL_DEFAULT;
+-
+-	DBF_TEXT(setup, 3, __FUNCTION__);
+-
+-	print_banner();
+-
+-	ret = ctc_register_dbf_views();
+-	if (ret){
+-		ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret);
+-		return ret;
+-	}
+-	ret = register_cu3088_discipline(&ctc_group_driver);
+-	if (ret) {
+-		ctc_unregister_dbf_views();
+-	}
+-	return ret;
+-}
+-
+-module_init(ctc_init);
+-module_exit(ctc_exit);
+-
+-/* --- This is the END my friend --- */
+diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h
+deleted file mode 100644
+index 7f305d1..0000000
+--- a/drivers/s390/net/ctcmain.h
++++ /dev/null
+@@ -1,270 +0,0 @@
+-/*
+- * CTC / ESCON network driver
+- *
+- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+- * Author(s): Fritz Elfert (elfert at de.ibm.com, felfert at millenux.com)
+-	      Peter Tiedemann (ptiedem at de.ibm.com)
+- *
+- *
+- * Documentation used:
+- *  - Principles of Operation (IBM doc#: SA22-7201-06)
+- *  - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
+- *  - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
+- *  - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
+- *  - ESCON I/O Interface (IBM doc#: SA22-7202-029
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-
+-#ifndef _CTCMAIN_H_
+-#define _CTCMAIN_H_
+-
+-#include <asm/ccwdev.h>
+-#include <asm/ccwgroup.h>
+-
+-#include <linux/skbuff.h>
+-#include <linux/netdevice.h>
+-
+-#include "fsm.h"
+-#include "cu3088.h"
+-
+-
+-/**
+- * CCW commands, used in this driver.
+- */
+-#define CCW_CMD_WRITE		0x01
+-#define CCW_CMD_READ		0x02
+-#define CCW_CMD_SET_EXTENDED	0xc3
+-#define CCW_CMD_PREPARE		0xe3
+-
+-#define CTC_PROTO_S390          0
+-#define CTC_PROTO_LINUX         1
+-#define CTC_PROTO_OS390         3
+-
+-#define CTC_BUFSIZE_LIMIT       65535
+-#define CTC_BUFSIZE_DEFAULT     32768
+-
+-#define CTC_TIMEOUT_5SEC        5000
+-
+-#define CTC_INITIAL_BLOCKLEN    2
+-
+-#define READ			0
+-#define WRITE			1
+-
+-#define CTC_ID_SIZE             BUS_ID_SIZE+3
+-
+-
+-struct ctc_profile {
+-	unsigned long maxmulti;
+-	unsigned long maxcqueue;
+-	unsigned long doios_single;
+-	unsigned long doios_multi;
+-	unsigned long txlen;
+-	unsigned long tx_time;
+-	struct timespec send_stamp;
+-};
+-
+-/**
+- * Definition of one channel
+- */
+-struct channel {
+-
+-	/**
+-	 * Pointer to next channel in list.
+-	 */
+-	struct channel *next;
+-	char id[CTC_ID_SIZE];
+-	struct ccw_device *cdev;
+-
+-	/**
+-	 * Type of this channel.
+-	 * CTC/A or Escon for valid channels.
+-	 */
+-	enum channel_types type;
+-
+-	/**
+-	 * Misc. flags. See CHANNEL_FLAGS_... below
+-	 */
+-	__u32 flags;
+-
+-	/**
+-	 * The protocol of this channel
+-	 */
+-	__u16 protocol;
+-
+-	/**
+-	 * I/O and irq related stuff
+-	 */
+-	struct ccw1 *ccw;
+-	struct irb *irb;
+-
+-	/**
+-	 * RX/TX buffer size
+-	 */
+-	int max_bufsize;
+-
+-	/**
+-	 * Transmit/Receive buffer.
+-	 */
+-	struct sk_buff *trans_skb;
+-
+-	/**
+-	 * Universal I/O queue.
+-	 */
+-	struct sk_buff_head io_queue;
+-
+-	/**
+-	 * TX queue for collecting skb's during busy.
+-	 */
+-	struct sk_buff_head collect_queue;
+-
+-	/**
+-	 * Amount of data in collect_queue.
+-	 */
+-	int collect_len;
+-
+-	/**
+-	 * spinlock for collect_queue and collect_len
+-	 */
+-	spinlock_t collect_lock;
+-
+-	/**
+-	 * Timer for detecting unresposive
+-	 * I/O operations.
+-	 */
+-	fsm_timer timer;
+-
+-	/**
+-	 * Retry counter for misc. operations.
+-	 */
+-	int retry;
+-
+-	/**
+-	 * The finite state machine of this channel
+-	 */
+-	fsm_instance *fsm;
+-
+-	/**
+-	 * The corresponding net_device this channel
+-	 * belongs to.
+-	 */
+-	struct net_device *netdev;
+-
+-	struct ctc_profile prof;
+-
+-	unsigned char *trans_skb_data;
+-
+-	__u16 logflags;
+-};
+-
+-#define CHANNEL_FLAGS_READ            0
+-#define CHANNEL_FLAGS_WRITE           1
+-#define CHANNEL_FLAGS_INUSE           2
+-#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
+-#define CHANNEL_FLAGS_FAILED          8
+-#define CHANNEL_FLAGS_WAITIRQ        16
+-#define CHANNEL_FLAGS_RWMASK 1
+-#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
+-
+-#define LOG_FLAG_ILLEGALPKT  1
+-#define LOG_FLAG_ILLEGALSIZE 2
+-#define LOG_FLAG_OVERRUN     4
+-#define LOG_FLAG_NOMEM       8
+-
+-#define CTC_LOGLEVEL_INFO     1
+-#define CTC_LOGLEVEL_NOTICE   2
+-#define CTC_LOGLEVEL_WARN     4
+-#define CTC_LOGLEVEL_EMERG    8
+-#define CTC_LOGLEVEL_ERR     16
+-#define CTC_LOGLEVEL_DEBUG   32
+-#define CTC_LOGLEVEL_CRIT    64
+-
+-#define CTC_LOGLEVEL_DEFAULT \
+-(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
+-
+-#define CTC_LOGLEVEL_MAX     ((CTC_LOGLEVEL_CRIT<<1)-1)
+-
+-#define ctc_pr_debug(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
+-
+-#define ctc_pr_info(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
+-
+-#define ctc_pr_notice(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
+-
+-#define ctc_pr_warn(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
+-
+-#define ctc_pr_emerg(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
+-
+-#define ctc_pr_err(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
+-
+-#define ctc_pr_crit(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
+-
+-struct ctc_priv {
+-	struct net_device_stats stats;
+-	unsigned long tbusy;
+-	/**
+-	 * The finite state machine of this interface.
+-	 */
+-	fsm_instance *fsm;
+-	/**
+-	 * The protocol of this device
+-	 */
+-	__u16 protocol;
+- 	/**
+- 	 * Timer for restarting after I/O Errors
+- 	 */
+- 	fsm_timer               restart_timer;
+-
+-	int buffer_size;
+-
+-	struct channel *channel[2];
+-};
+-
+-/**
+- * Definition of our link level header.
+- */
+-struct ll_header {
+-	__u16 length;
+-	__u16 type;
+-	__u16 unused;
+-};
+-#define LL_HEADER_LENGTH (sizeof(struct ll_header))
+-
+-/**
+- * Compatibility macros for busy handling
+- * of network devices.
+- */
+-static __inline__ void
+-ctc_clear_busy(struct net_device * dev)
+-{
+-	clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
+-	netif_wake_queue(dev);
+-}
+-
+-static __inline__ int
+-ctc_test_and_set_busy(struct net_device * dev)
+-{
+-	netif_stop_queue(dev);
+-	return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
+-}
+-
+-#endif
+diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
+index 874a199..8f876f6 100644
+--- a/drivers/s390/net/netiucv.c
++++ b/drivers/s390/net/netiucv.c
+@@ -670,7 +670,7 @@ static void conn_action_rx(fsm_instance *fi, int event, void *arg)
+ 	struct netiucv_priv *privptr = netdev_priv(conn->netdev);
+ 	int rc;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 
+ 	if (!conn->netdev) {
+ 		iucv_message_reject(conn->path, msg);
+@@ -718,7 +718,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
+ 	struct ll_header header;
+ 	int rc;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 
+ 	if (conn && conn->netdev)
+ 		privptr = netdev_priv(conn->netdev);
+@@ -799,7 +799,7 @@ static void conn_action_connaccept(fsm_instance *fi, int event, void *arg)
+ 	struct netiucv_priv *privptr = netdev_priv(netdev);
+ 	int rc;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	conn->path = path;
+ 	path->msglim = NETIUCV_QUEUELEN_DEFAULT;
+@@ -821,7 +821,7 @@ static void conn_action_connreject(fsm_instance *fi, int event, void *arg)
+ 	struct iucv_event *ev = arg;
+ 	struct iucv_path *path = ev->data;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	iucv_path_sever(path, NULL);
+ }
+ 
+@@ -831,7 +831,7 @@ static void conn_action_connack(fsm_instance *fi, int event, void *arg)
+ 	struct net_device *netdev = conn->netdev;
+ 	struct netiucv_priv *privptr = netdev_priv(netdev);
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	fsm_deltimer(&conn->timer);
+ 	fsm_newstate(fi, CONN_STATE_IDLE);
+ 	netdev->tx_queue_len = conn->path->msglim;
+@@ -842,7 +842,7 @@ static void conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
+ {
+ 	struct iucv_connection *conn = arg;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	fsm_deltimer(&conn->timer);
+ 	iucv_path_sever(conn->path, NULL);
+ 	fsm_newstate(fi, CONN_STATE_STARTWAIT);
+@@ -854,7 +854,7 @@ static void conn_action_connsever(fsm_instance *fi, int event, void *arg)
+ 	struct net_device *netdev = conn->netdev;
+ 	struct netiucv_priv *privptr = netdev_priv(netdev);
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	fsm_deltimer(&conn->timer);
+ 	iucv_path_sever(conn->path, NULL);
+@@ -870,7 +870,7 @@ static void conn_action_start(fsm_instance *fi, int event, void *arg)
+ 	struct iucv_connection *conn = arg;
+ 	int rc;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	fsm_newstate(fi, CONN_STATE_STARTWAIT);
+ 	PRINT_DEBUG("%s('%s'): connecting ...\n",
+@@ -948,7 +948,7 @@ static void conn_action_stop(fsm_instance *fi, int event, void *arg)
+ 	struct net_device *netdev = conn->netdev;
+ 	struct netiucv_priv *privptr = netdev_priv(netdev);
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	fsm_deltimer(&conn->timer);
+ 	fsm_newstate(fi, CONN_STATE_STOPPED);
+@@ -1024,7 +1024,7 @@ static void dev_action_start(fsm_instance *fi, int event, void *arg)
+ 	struct net_device   *dev = arg;
+ 	struct netiucv_priv *privptr = netdev_priv(dev);
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	fsm_newstate(fi, DEV_STATE_STARTWAIT);
+ 	fsm_event(privptr->conn->fsm, CONN_EVENT_START, privptr->conn);
+@@ -1044,7 +1044,7 @@ dev_action_stop(fsm_instance *fi, int event, void *arg)
+ 	struct netiucv_priv *privptr = netdev_priv(dev);
+ 	struct iucv_event   ev;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	ev.conn = privptr->conn;
+ 
+@@ -1066,7 +1066,7 @@ dev_action_connup(fsm_instance *fi, int event, void *arg)
+ 	struct net_device   *dev = arg;
+ 	struct netiucv_priv *privptr = netdev_priv(dev);
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	switch (fsm_getstate(fi)) {
+ 		case DEV_STATE_STARTWAIT:
+@@ -1097,7 +1097,7 @@ dev_action_connup(fsm_instance *fi, int event, void *arg)
+ static void
+ dev_action_conndown(fsm_instance *fi, int event, void *arg)
+ {
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	switch (fsm_getstate(fi)) {
+ 		case DEV_STATE_RUNNING:
+@@ -1288,7 +1288,7 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
+ 	struct netiucv_priv *privptr = netdev_priv(dev);
+ 	int rc;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 	/**
+ 	 * Some sanity checks ...
+ 	 */
+@@ -1344,7 +1344,7 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
+ {
+ 	struct netiucv_priv *priv = netdev_priv(dev);
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return &priv->stats;
+ }
+ 
+@@ -1360,7 +1360,7 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
+  */
+ static int netiucv_change_mtu(struct net_device * dev, int new_mtu)
+ {
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	if (new_mtu < 576 || new_mtu > NETIUCV_MTU_MAX) {
+ 		IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n");
+ 		return -EINVAL;
+@@ -1378,7 +1378,7 @@ static ssize_t user_show(struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
+ }
+ 
+@@ -1393,7 +1393,7 @@ static ssize_t user_write(struct device *dev, struct device_attribute *attr,
+ 	int 	i;
+ 	struct iucv_connection *cp;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	if (count > 9) {
+ 		PRINT_WARN("netiucv: username too long (%d)!\n", (int) count);
+ 		IUCV_DBF_TEXT_(setup, 2,
+@@ -1449,7 +1449,7 @@ static ssize_t buffer_show (struct device *dev, struct device_attribute *attr,
+ 			    char *buf)
+ {	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%d\n", priv->conn->max_buffsize);
+ }
+ 
+@@ -1461,7 +1461,7 @@ static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
+ 	char         *e;
+ 	int          bs1;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	if (count >= 39)
+ 		return -EINVAL;
+ 
+@@ -1513,7 +1513,7 @@ static ssize_t dev_fsm_show (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%s\n", fsm_getstate_str(priv->fsm));
+ }
+ 
+@@ -1524,7 +1524,7 @@ static ssize_t conn_fsm_show (struct device *dev,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%s\n", fsm_getstate_str(priv->conn->fsm));
+ }
+ 
+@@ -1535,7 +1535,7 @@ static ssize_t maxmulti_show (struct device *dev,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti);
+ }
+ 
+@@ -1545,7 +1545,7 @@ static ssize_t maxmulti_write (struct device *dev,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 	priv->conn->prof.maxmulti = 0;
+ 	return count;
+ }
+@@ -1557,7 +1557,7 @@ static ssize_t maxcq_show (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue);
+ }
+ 
+@@ -1566,7 +1566,7 @@ static ssize_t maxcq_write (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 	priv->conn->prof.maxcqueue = 0;
+ 	return count;
+ }
+@@ -1578,7 +1578,7 @@ static ssize_t sdoio_show (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%ld\n", priv->conn->prof.doios_single);
+ }
+ 
+@@ -1587,7 +1587,7 @@ static ssize_t sdoio_write (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 	priv->conn->prof.doios_single = 0;
+ 	return count;
+ }
+@@ -1599,7 +1599,7 @@ static ssize_t mdoio_show (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi);
+ }
+ 
+@@ -1608,7 +1608,7 @@ static ssize_t mdoio_write (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	priv->conn->prof.doios_multi = 0;
+ 	return count;
+ }
+@@ -1620,7 +1620,7 @@ static ssize_t txlen_show (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%ld\n", priv->conn->prof.txlen);
+ }
+ 
+@@ -1629,7 +1629,7 @@ static ssize_t txlen_write (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 	priv->conn->prof.txlen = 0;
+ 	return count;
+ }
+@@ -1641,7 +1641,7 @@ static ssize_t txtime_show (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%ld\n", priv->conn->prof.tx_time);
+ }
+ 
+@@ -1650,7 +1650,7 @@ static ssize_t txtime_write (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 	priv->conn->prof.tx_time = 0;
+ 	return count;
+ }
+@@ -1662,7 +1662,7 @@ static ssize_t txpend_show (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending);
+ }
+ 
+@@ -1671,7 +1671,7 @@ static ssize_t txpend_write (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 	priv->conn->prof.tx_pending = 0;
+ 	return count;
+ }
+@@ -1683,7 +1683,7 @@ static ssize_t txmpnd_show (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 5, __func__);
+ 	return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending);
+ }
+ 
+@@ -1692,7 +1692,7 @@ static ssize_t txmpnd_write (struct device *dev, struct device_attribute *attr,
+ {
+ 	struct netiucv_priv *priv = dev->driver_data;
+ 
+-	IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 4, __func__);
+ 	priv->conn->prof.tx_max_pending = 0;
+ 	return count;
+ }
+@@ -1732,7 +1732,7 @@ static int netiucv_add_files(struct device *dev)
+ {
+ 	int ret;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	ret = sysfs_create_group(&dev->kobj, &netiucv_attr_group);
+ 	if (ret)
+ 		return ret;
+@@ -1744,7 +1744,7 @@ static int netiucv_add_files(struct device *dev)
+ 
+ static void netiucv_remove_files(struct device *dev)
+ {
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
+ 	sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
+ }
+@@ -1756,7 +1756,7 @@ static int netiucv_register_device(struct net_device *ndev)
+ 	int ret;
+ 
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	if (dev) {
+ 		snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name);
+@@ -1792,7 +1792,7 @@ out_unreg:
+ 
+ static void netiucv_unregister_device(struct device *dev)
+ {
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	netiucv_remove_files(dev);
+ 	device_unregister(dev);
+ }
+@@ -1857,7 +1857,7 @@ out:
+  */
+ static void netiucv_remove_connection(struct iucv_connection *conn)
+ {
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	write_lock_bh(&iucv_connection_rwlock);
+ 	list_del_init(&conn->list);
+ 	write_unlock_bh(&iucv_connection_rwlock);
+@@ -1881,7 +1881,7 @@ static void netiucv_free_netdevice(struct net_device *dev)
+ {
+ 	struct netiucv_priv *privptr = netdev_priv(dev);
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+ 	if (!dev)
+ 		return;
+@@ -1963,7 +1963,7 @@ static ssize_t conn_write(struct device_driver *drv,
+ 	struct netiucv_priv *priv;
+ 	struct iucv_connection *cp;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	if (count>9) {
+ 		PRINT_WARN("netiucv: username too long (%d)!\n", (int)count);
+ 		IUCV_DBF_TEXT(setup, 2, "conn_write: too long\n");
+@@ -2048,7 +2048,7 @@ static ssize_t remove_write (struct device_driver *drv,
+ 	const char *p;
+         int i;
+ 
+-        IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 
+         if (count >= IFNAMSIZ)
+                 count = IFNAMSIZ - 1;;
+@@ -2116,7 +2116,7 @@ static void __exit netiucv_exit(void)
+ 	struct netiucv_priv *priv;
+ 	struct device *dev;
+ 
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	while (!list_empty(&iucv_connection_list)) {
+ 		cp = list_entry(iucv_connection_list.next,
+ 				struct iucv_connection, list);
+@@ -2146,8 +2146,7 @@ static int __init netiucv_init(void)
+ 	rc = iucv_register(&netiucv_handler, 1);
+ 	if (rc)
+ 		goto out_dbf;
+-	IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+-	netiucv_driver.groups = netiucv_drv_attr_groups;
++	IUCV_DBF_TEXT(trace, 3, __func__);
+ 	rc = driver_register(&netiucv_driver);
+ 	if (rc) {
+ 		PRINT_ERR("NETIUCV: failed to register driver.\n");
+diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
+deleted file mode 100644
+index 8c6b72d..0000000
+--- a/drivers/s390/net/qeth.h
++++ /dev/null
+@@ -1,1253 +0,0 @@
+-#ifndef __QETH_H__
+-#define __QETH_H__
+-
+-#include <linux/if.h>
+-#include <linux/if_arp.h>
+-
+-#include <linux/if_tr.h>
+-#include <linux/trdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/if_vlan.h>
+-#include <linux/ctype.h>
+-
+-#include <net/ipv6.h>
+-#include <linux/in6.h>
+-#include <net/if_inet6.h>
+-#include <net/addrconf.h>
+-
+-
+-#include <linux/bitops.h>
+-
+-#include <asm/debug.h>
+-#include <asm/qdio.h>
+-#include <asm/ccwdev.h>
+-#include <asm/ccwgroup.h>
+-
+-#include "qeth_mpc.h"
+-
+-#ifdef CONFIG_QETH_IPV6
+-#define QETH_VERSION_IPV6 	":IPv6"
+-#else
+-#define QETH_VERSION_IPV6 	""
+-#endif
+-#ifdef CONFIG_QETH_VLAN
+-#define QETH_VERSION_VLAN 	":VLAN"
+-#else
+-#define QETH_VERSION_VLAN 	""
+-#endif
+-
+-/**
+- * Debug Facility stuff
+- */
+-#define QETH_DBF_SETUP_NAME "qeth_setup"
+-#define QETH_DBF_SETUP_LEN 8
+-#define QETH_DBF_SETUP_PAGES 8
+-#define QETH_DBF_SETUP_NR_AREAS 1
+-#define QETH_DBF_SETUP_LEVEL 5
+-
+-#define QETH_DBF_MISC_NAME "qeth_misc"
+-#define QETH_DBF_MISC_LEN 128
+-#define QETH_DBF_MISC_PAGES 2
+-#define QETH_DBF_MISC_NR_AREAS 1
+-#define QETH_DBF_MISC_LEVEL 2
+-
+-#define QETH_DBF_DATA_NAME "qeth_data"
+-#define QETH_DBF_DATA_LEN 96
+-#define QETH_DBF_DATA_PAGES 8
+-#define QETH_DBF_DATA_NR_AREAS 1
+-#define QETH_DBF_DATA_LEVEL 2
+-
+-#define QETH_DBF_CONTROL_NAME "qeth_control"
+-#define QETH_DBF_CONTROL_LEN 256
+-#define QETH_DBF_CONTROL_PAGES 8
+-#define QETH_DBF_CONTROL_NR_AREAS 2
+-#define QETH_DBF_CONTROL_LEVEL 5
+-
+-#define QETH_DBF_TRACE_NAME "qeth_trace"
+-#define QETH_DBF_TRACE_LEN 8
+-#define QETH_DBF_TRACE_PAGES 4
+-#define QETH_DBF_TRACE_NR_AREAS 2
+-#define QETH_DBF_TRACE_LEVEL 3
+-extern debug_info_t *qeth_dbf_trace;
+-
+-#define QETH_DBF_SENSE_NAME "qeth_sense"
+-#define QETH_DBF_SENSE_LEN 64
+-#define QETH_DBF_SENSE_PAGES 2
+-#define QETH_DBF_SENSE_NR_AREAS 1
+-#define QETH_DBF_SENSE_LEVEL 2
+-
+-#define QETH_DBF_QERR_NAME "qeth_qerr"
+-#define QETH_DBF_QERR_LEN 8
+-#define QETH_DBF_QERR_PAGES 2
+-#define QETH_DBF_QERR_NR_AREAS 2
+-#define QETH_DBF_QERR_LEVEL 2
+-
+-#define QETH_DBF_TEXT(name,level,text) \
+-	do { \
+-		debug_text_event(qeth_dbf_##name,level,text); \
+-	} while (0)
+-
+-#define QETH_DBF_HEX(name,level,addr,len) \
+-	do { \
+-		debug_event(qeth_dbf_##name,level,(void*)(addr),len); \
+-	} while (0)
+-
+-DECLARE_PER_CPU(char[256], qeth_dbf_txt_buf);
+-
+-#define QETH_DBF_TEXT_(name,level,text...)				\
+-	do {								\
+-		char* dbf_txt_buf = get_cpu_var(qeth_dbf_txt_buf);	\
+-		sprintf(dbf_txt_buf, text);			  	\
+-		debug_text_event(qeth_dbf_##name,level,dbf_txt_buf);	\
+-		put_cpu_var(qeth_dbf_txt_buf);				\
+-	} while (0)
+-
+-#define QETH_DBF_SPRINTF(name,level,text...) \
+-	do { \
+-		debug_sprintf_event(qeth_dbf_trace, level, ##text ); \
+-		debug_sprintf_event(qeth_dbf_trace, level, text ); \
+-	} while (0)
+-
+-/**
+- * some more debug stuff
+- */
+-#define PRINTK_HEADER 	"qeth: "
+-
+-#define HEXDUMP16(importance,header,ptr) \
+-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+-		   *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
+-		   *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
+-		   *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
+-		   *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
+-		   *(((char*)ptr)+12),*(((char*)ptr)+13), \
+-		   *(((char*)ptr)+14),*(((char*)ptr)+15)); \
+-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+-		   *(((char*)ptr)+16),*(((char*)ptr)+17), \
+-		   *(((char*)ptr)+18),*(((char*)ptr)+19), \
+-		   *(((char*)ptr)+20),*(((char*)ptr)+21), \
+-		   *(((char*)ptr)+22),*(((char*)ptr)+23), \
+-		   *(((char*)ptr)+24),*(((char*)ptr)+25), \
+-		   *(((char*)ptr)+26),*(((char*)ptr)+27), \
+-		   *(((char*)ptr)+28),*(((char*)ptr)+29), \
+-		   *(((char*)ptr)+30),*(((char*)ptr)+31));
+-
+-static inline void
+-qeth_hex_dump(unsigned char *buf, size_t len)
+-{
+-	size_t i;
+-
+-	for (i = 0; i < len; i++) {
+-		if (i && !(i % 16))
+-			printk("\n");
+-		printk("%02x ", *(buf + i));
+-	}
+-	printk("\n");
+-}
+-
+-#define SENSE_COMMAND_REJECT_BYTE 0
+-#define SENSE_COMMAND_REJECT_FLAG 0x80
+-#define SENSE_RESETTING_EVENT_BYTE 1
+-#define SENSE_RESETTING_EVENT_FLAG 0x80
+-
+-/*
+- * Common IO related definitions
+- */
+-extern struct device *qeth_root_dev;
+-extern struct ccw_driver qeth_ccw_driver;
+-extern struct ccwgroup_driver qeth_ccwgroup_driver;
+-
+-#define CARD_RDEV(card) card->read.ccwdev
+-#define CARD_WDEV(card) card->write.ccwdev
+-#define CARD_DDEV(card) card->data.ccwdev
+-#define CARD_BUS_ID(card) card->gdev->dev.bus_id
+-#define CARD_RDEV_ID(card) card->read.ccwdev->dev.bus_id
+-#define CARD_WDEV_ID(card) card->write.ccwdev->dev.bus_id
+-#define CARD_DDEV_ID(card) card->data.ccwdev->dev.bus_id
+-#define CHANNEL_ID(channel) channel->ccwdev->dev.bus_id
+-
+-#define CARD_FROM_CDEV(cdev) (struct qeth_card *) \
+-		((struct ccwgroup_device *)cdev->dev.driver_data)\
+-		->dev.driver_data;
+-
+-/**
+- * card stuff
+- */
+-struct qeth_perf_stats {
+-	unsigned int bufs_rec;
+-	unsigned int bufs_sent;
+-
+-	unsigned int skbs_sent_pack;
+-	unsigned int bufs_sent_pack;
+-
+-	unsigned int sc_dp_p;
+-	unsigned int sc_p_dp;
+-	/* qdio_input_handler: number of times called, time spent in */
+-	__u64 inbound_start_time;
+-	unsigned int inbound_cnt;
+-	unsigned int inbound_time;
+-	/* qeth_send_packet: number of times called, time spent in */
+-	__u64 outbound_start_time;
+-	unsigned int outbound_cnt;
+-	unsigned int outbound_time;
+-	/* qdio_output_handler: number of times called, time spent in */
+-	__u64 outbound_handler_start_time;
+-	unsigned int outbound_handler_cnt;
+-	unsigned int outbound_handler_time;
+-	/* number of calls to and time spent in do_QDIO for inbound queue */
+-	__u64 inbound_do_qdio_start_time;
+-	unsigned int inbound_do_qdio_cnt;
+-	unsigned int inbound_do_qdio_time;
+-	/* number of calls to and time spent in do_QDIO for outbound queues */
+-	__u64 outbound_do_qdio_start_time;
+-	unsigned int outbound_do_qdio_cnt;
+-	unsigned int outbound_do_qdio_time;
+-	/* eddp data */
+-	unsigned int large_send_bytes;
+-	unsigned int large_send_cnt;
+-	unsigned int sg_skbs_sent;
+-	unsigned int sg_frags_sent;
+-	/* initial values when measuring starts */
+-	unsigned long initial_rx_packets;
+-	unsigned long initial_tx_packets;
+-	/* inbound scatter gather data */
+-	unsigned int sg_skbs_rx;
+-	unsigned int sg_frags_rx;
+-	unsigned int sg_alloc_page_rx;
+-};
+-
+-/* Routing stuff */
+-struct qeth_routing_info {
+-	enum qeth_routing_types type;
+-};
+-
+-/* IPA stuff */
+-struct qeth_ipa_info {
+-	__u32 supported_funcs;
+-	__u32 enabled_funcs;
+-};
+-
+-static inline int
+-qeth_is_ipa_supported(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
+-{
+-	return (ipa->supported_funcs & func);
+-}
+-
+-static inline int
+-qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
+-{
+-	return (ipa->supported_funcs & ipa->enabled_funcs & func);
+-}
+-
+-#define qeth_adp_supported(c,f) \
+-	qeth_is_ipa_supported(&c->options.adp, f)
+-#define qeth_adp_enabled(c,f) \
+-	qeth_is_ipa_enabled(&c->options.adp, f)
+-#define qeth_is_supported(c,f) \
+-	qeth_is_ipa_supported(&c->options.ipa4, f)
+-#define qeth_is_enabled(c,f) \
+-	qeth_is_ipa_enabled(&c->options.ipa4, f)
+-#ifdef CONFIG_QETH_IPV6
+-#define qeth_is_supported6(c,f) \
+-	qeth_is_ipa_supported(&c->options.ipa6, f)
+-#define qeth_is_enabled6(c,f) \
+-	qeth_is_ipa_enabled(&c->options.ipa6, f)
+-#else /* CONFIG_QETH_IPV6 */
+-#define qeth_is_supported6(c,f) 0
+-#define qeth_is_enabled6(c,f) 0
+-#endif /* CONFIG_QETH_IPV6 */
+-#define qeth_is_ipafunc_supported(c,prot,f) \
+-	 (prot==QETH_PROT_IPV6)? qeth_is_supported6(c,f):qeth_is_supported(c,f)
+-#define qeth_is_ipafunc_enabled(c,prot,f) \
+-	 (prot==QETH_PROT_IPV6)? qeth_is_enabled6(c,f):qeth_is_enabled(c,f)
+-
+-
+-#define QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT 0x0101
+-#define QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT 0x0101
+-#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108
+-#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108
+-
+-#define QETH_MODELLIST_ARRAY \
+-	{{0x1731,0x01,0x1732,0x01,QETH_CARD_TYPE_OSAE,1, \
+-	QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+-	QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+-	QETH_MAX_QUEUES,0}, \
+-	{0x1731,0x05,0x1732,0x05,QETH_CARD_TYPE_IQD,0, \
+-	QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
+-	QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
+-	QETH_MAX_QUEUES,0x103}, \
+-	{0x1731,0x06,0x1732,0x06,QETH_CARD_TYPE_OSN,0, \
+-	QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+-	QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+-	QETH_MAX_QUEUES,0}, \
+-	{0,0,0,0,0,0,0,0,0}}
+-
+-#define QETH_REAL_CARD		1
+-#define QETH_VLAN_CARD		2
+-#define QETH_BUFSIZE	 	4096
+-
+-/**
+- * some more defs
+- */
+-#define IF_NAME_LEN	 	16
+-#define QETH_TX_TIMEOUT		100 * HZ
+-#define QETH_RCD_TIMEOUT	60 * HZ
+-#define QETH_HEADER_SIZE	32
+-#define MAX_PORTNO 		15
+-#define QETH_FAKE_LL_LEN_ETH	ETH_HLEN
+-#define QETH_FAKE_LL_LEN_TR	(sizeof(struct trh_hdr)-TR_MAXRIFLEN+sizeof(struct trllc))
+-#define QETH_FAKE_LL_V6_ADDR_POS 24
+-
+-/*IPv6 address autoconfiguration stuff*/
+-#define UNIQUE_ID_IF_CREATE_ADDR_FAILED 0xfffe
+-#define UNIQUE_ID_NOT_BY_CARD 		0x10000
+-
+-/*****************************************************************************/
+-/* QDIO queue and buffer handling                                            */
+-/*****************************************************************************/
+-#define QETH_MAX_QUEUES 4
+-#define QETH_IN_BUF_SIZE_DEFAULT 65536
+-#define QETH_IN_BUF_COUNT_DEFAULT 16
+-#define QETH_IN_BUF_COUNT_MIN 8
+-#define QETH_IN_BUF_COUNT_MAX 128
+-#define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
+-#define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
+-		((card)->qdio.in_buf_pool.buf_count / 2)
+-
+-/* buffers we have to be behind before we get a PCI */
+-#define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
+-/*enqueued free buffers left before we get a PCI*/
+-#define QETH_PCI_THRESHOLD_B(card) 0
+-/*not used unless the microcode gets patched*/
+-#define QETH_PCI_TIMER_VALUE(card) 3
+-
+-#define QETH_MIN_INPUT_THRESHOLD 1
+-#define QETH_MAX_INPUT_THRESHOLD 500
+-#define QETH_MIN_OUTPUT_THRESHOLD 1
+-#define QETH_MAX_OUTPUT_THRESHOLD 300
+-
+-/* priority queing */
+-#define QETH_PRIOQ_DEFAULT QETH_NO_PRIO_QUEUEING
+-#define QETH_DEFAULT_QUEUE    2
+-#define QETH_NO_PRIO_QUEUEING 0
+-#define QETH_PRIO_Q_ING_PREC  1
+-#define QETH_PRIO_Q_ING_TOS   2
+-#define IP_TOS_LOWDELAY 0x10
+-#define IP_TOS_HIGHTHROUGHPUT 0x08
+-#define IP_TOS_HIGHRELIABILITY 0x04
+-#define IP_TOS_NOTIMPORTANT 0x02
+-
+-/* Packing */
+-#define QETH_LOW_WATERMARK_PACK  2
+-#define QETH_HIGH_WATERMARK_PACK 5
+-#define QETH_WATERMARK_PACK_FUZZ 1
+-
+-#define QETH_IP_HEADER_SIZE 40
+-
+-/* large receive scatter gather copy break */
+-#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
+-
+-struct qeth_hdr_layer3 {
+-	__u8  id;
+-	__u8  flags;
+-	__u16 inbound_checksum; /*TSO:__u16 seqno */
+-	__u32 token;		/*TSO: __u32 reserved */
+-	__u16 length;
+-	__u8  vlan_prio;
+-	__u8  ext_flags;
+-	__u16 vlan_id;
+-	__u16 frame_offset;
+-	__u8  dest_addr[16];
+-} __attribute__ ((packed));
+-
+-struct qeth_hdr_layer2 {
+-	__u8 id;
+-	__u8 flags[3];
+-	__u8 port_no;
+-	__u8 hdr_length;
+-	__u16 pkt_length;
+-	__u16 seq_no;
+-	__u16 vlan_id;
+-	__u32 reserved;
+-	__u8 reserved2[16];
+-} __attribute__ ((packed));
+-
+-struct qeth_hdr_osn {
+-	__u8 id;
+-	__u8 reserved;
+-	__u16 seq_no;
+-	__u16 reserved2;
+-	__u16 control_flags;
+-	__u16 pdu_length;
+-	__u8 reserved3[18];
+-	__u32 ccid;
+-} __attribute__ ((packed));
+-
+-struct qeth_hdr {
+-	union {
+-		struct qeth_hdr_layer2 l2;
+-		struct qeth_hdr_layer3 l3;
+-		struct qeth_hdr_osn    osn;
+-	} hdr;
+-} __attribute__ ((packed));
+-
+-/*TCP Segmentation Offload header*/
+-struct qeth_hdr_ext_tso {
+-        __u16 hdr_tot_len;
+-        __u8  imb_hdr_no;
+-        __u8  reserved;
+-        __u8  hdr_type;
+-        __u8  hdr_version;
+-        __u16 hdr_len;
+-        __u32 payload_len;
+-        __u16 mss;
+-        __u16 dg_hdr_len;
+-        __u8  padding[16];
+-} __attribute__ ((packed));
+-
+-struct qeth_hdr_tso {
+-        struct qeth_hdr hdr; 	/*hdr->hdr.l3.xxx*/
+-	struct qeth_hdr_ext_tso ext;
+-} __attribute__ ((packed));
+-
+-
+-/* flags for qeth_hdr.flags */
+-#define QETH_HDR_PASSTHRU 0x10
+-#define QETH_HDR_IPV6     0x80
+-#define QETH_HDR_CAST_MASK 0x07
+-enum qeth_cast_flags {
+-	QETH_CAST_UNICAST   = 0x06,
+-	QETH_CAST_MULTICAST = 0x04,
+-	QETH_CAST_BROADCAST = 0x05,
+-	QETH_CAST_ANYCAST   = 0x07,
+-	QETH_CAST_NOCAST    = 0x00,
+-};
+-
+-enum qeth_layer2_frame_flags {
+-	QETH_LAYER2_FLAG_MULTICAST = 0x01,
+-	QETH_LAYER2_FLAG_BROADCAST = 0x02,
+-	QETH_LAYER2_FLAG_UNICAST   = 0x04,
+-	QETH_LAYER2_FLAG_VLAN      = 0x10,
+-};
+-
+-enum qeth_header_ids {
+-	QETH_HEADER_TYPE_LAYER3 = 0x01,
+-	QETH_HEADER_TYPE_LAYER2 = 0x02,
+-	QETH_HEADER_TYPE_TSO	= 0x03,
+-	QETH_HEADER_TYPE_OSN    = 0x04,
+-};
+-/* flags for qeth_hdr.ext_flags */
+-#define QETH_HDR_EXT_VLAN_FRAME       0x01
+-#define QETH_HDR_EXT_TOKEN_ID         0x02
+-#define QETH_HDR_EXT_INCLUDE_VLAN_TAG 0x04
+-#define QETH_HDR_EXT_SRC_MAC_ADDR     0x08
+-#define QETH_HDR_EXT_CSUM_HDR_REQ     0x10
+-#define QETH_HDR_EXT_CSUM_TRANSP_REQ  0x20
+-#define QETH_HDR_EXT_UDP_TSO          0x40 /*bit off for TCP*/
+-
+-static inline int
+-qeth_is_last_sbale(struct qdio_buffer_element *sbale)
+-{
+-	return (sbale->flags & SBAL_FLAGS_LAST_ENTRY);
+-}
+-
+-enum qeth_qdio_buffer_states {
+-	/*
+-	 * inbound: read out by driver; owned by hardware in order to be filled
+-	 * outbound: owned by driver in order to be filled
+-	 */
+-	QETH_QDIO_BUF_EMPTY,
+-	/*
+-	 * inbound: filled by hardware; owned by driver in order to be read out
+-	 * outbound: filled by driver; owned by hardware in order to be sent
+-	 */
+-	QETH_QDIO_BUF_PRIMED,
+-};
+-
+-enum qeth_qdio_info_states {
+-	QETH_QDIO_UNINITIALIZED,
+-	QETH_QDIO_ALLOCATED,
+-	QETH_QDIO_ESTABLISHED,
+-	QETH_QDIO_CLEANING
+-};
+-
+-struct qeth_buffer_pool_entry {
+-	struct list_head list;
+-	struct list_head init_list;
+-	void *elements[QDIO_MAX_ELEMENTS_PER_BUFFER];
+-};
+-
+-struct qeth_qdio_buffer_pool {
+-	struct list_head entry_list;
+-	int buf_count;
+-};
+-
+-struct qeth_qdio_buffer {
+-	struct qdio_buffer *buffer;
+-	volatile enum qeth_qdio_buffer_states state;
+-	/* the buffer pool entry currently associated to this buffer */
+-	struct qeth_buffer_pool_entry *pool_entry;
+-};
+-
+-struct qeth_qdio_q {
+-	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+-	struct qeth_qdio_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
+-	/*
+-	 * buf_to_init means "buffer must be initialized by driver and must
+-	 * be made available for hardware" -> state is set to EMPTY
+-	 */
+-	volatile int next_buf_to_init;
+-} __attribute__ ((aligned(256)));
+-
+-/* possible types of qeth large_send support */
+-enum qeth_large_send_types {
+-	QETH_LARGE_SEND_NO,
+-	QETH_LARGE_SEND_EDDP,
+-	QETH_LARGE_SEND_TSO,
+-};
+-
+-struct qeth_qdio_out_buffer {
+-	struct qdio_buffer *buffer;
+-	atomic_t state;
+-	volatile int next_element_to_fill;
+-	struct sk_buff_head skb_list;
+-	struct list_head ctx_list;
+-};
+-
+-struct qeth_card;
+-
+-enum qeth_out_q_states {
+-       QETH_OUT_Q_UNLOCKED,
+-       QETH_OUT_Q_LOCKED,
+-       QETH_OUT_Q_LOCKED_FLUSH,
+-};
+-
+-struct qeth_qdio_out_q {
+-	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+-	struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
+-	int queue_no;
+-	struct qeth_card *card;
+-	atomic_t state;
+-	volatile int do_pack;
+-	/*
+-	 * index of buffer to be filled by driver; state EMPTY or PACKING
+-	 */
+-	volatile int next_buf_to_fill;
+-	/*
+-	 * number of buffers that are currently filled (PRIMED)
+-	 * -> these buffers are hardware-owned
+-	 */
+-	atomic_t used_buffers;
+-	/* indicates whether PCI flag must be set (or if one is outstanding) */
+-	atomic_t set_pci_flags_count;
+-} __attribute__ ((aligned(256)));
+-
+-struct qeth_qdio_info {
+-	atomic_t state;
+-	/* input */
+-	struct qeth_qdio_q *in_q;
+-	struct qeth_qdio_buffer_pool in_buf_pool;
+-	struct qeth_qdio_buffer_pool init_pool;
+-	int in_buf_size;
+-
+-	/* output */
+-	int no_out_queues;
+-	struct qeth_qdio_out_q **out_qs;
+-
+-	/* priority queueing */
+-	int do_prio_queueing;
+-	int default_out_queue;
+-};
+-
+-enum qeth_send_errors {
+-	QETH_SEND_ERROR_NONE,
+-	QETH_SEND_ERROR_LINK_FAILURE,
+-	QETH_SEND_ERROR_RETRY,
+-	QETH_SEND_ERROR_KICK_IT,
+-};
+-
+-#define QETH_ETH_MAC_V4      0x0100 /* like v4 */
+-#define QETH_ETH_MAC_V6      0x3333 /* like v6 */
+-/* tr mc mac is longer, but that will be enough to detect mc frames */
+-#define QETH_TR_MAC_NC       0xc000 /* non-canonical */
+-#define QETH_TR_MAC_C        0x0300 /* canonical */
+-
+-#define DEFAULT_ADD_HHLEN 0
+-#define MAX_ADD_HHLEN 1024
+-
+-/**
+- * buffer stuff for read channel
+- */
+-#define QETH_CMD_BUFFER_NO	8
+-
+-/**
+- *  channel state machine
+- */
+-enum qeth_channel_states {
+-	CH_STATE_UP,
+-	CH_STATE_DOWN,
+-	CH_STATE_ACTIVATING,
+-	CH_STATE_HALTED,
+-	CH_STATE_STOPPED,
+-	CH_STATE_RCD,
+-	CH_STATE_RCD_DONE,
+-};
+-/**
+- * card state machine
+- */
+-enum qeth_card_states {
+-	CARD_STATE_DOWN,
+-	CARD_STATE_HARDSETUP,
+-	CARD_STATE_SOFTSETUP,
+-	CARD_STATE_UP,
+-	CARD_STATE_RECOVER,
+-};
+-
+-/**
+- * Protocol versions
+- */
+-enum qeth_prot_versions {
+-	QETH_PROT_IPV4 = 0x0004,
+-	QETH_PROT_IPV6 = 0x0006,
+-};
+-
+-enum qeth_ip_types {
+-	QETH_IP_TYPE_NORMAL,
+-	QETH_IP_TYPE_VIPA,
+-	QETH_IP_TYPE_RXIP,
+-	QETH_IP_TYPE_DEL_ALL_MC,
+-};
+-
+-enum qeth_cmd_buffer_state {
+-	BUF_STATE_FREE,
+-	BUF_STATE_LOCKED,
+-	BUF_STATE_PROCESSED,
+-};
+-/**
+- * IP address and multicast list
+- */
+-struct qeth_ipaddr {
+-	struct list_head entry;
+-	enum qeth_ip_types type;
+-	enum qeth_ipa_setdelip_flags set_flags;
+-	enum qeth_ipa_setdelip_flags del_flags;
+-	int is_multicast;
+-	volatile int users;
+-	enum qeth_prot_versions proto;
+-	unsigned char mac[OSA_ADDR_LEN];
+-	union {
+-		struct {
+-			unsigned int addr;
+-			unsigned int mask;
+-		} a4;
+-		struct {
+-			struct in6_addr addr;
+-			unsigned int pfxlen;
+-		} a6;
+-	} u;
+-};
+-
+-struct qeth_ipato_entry {
+-	struct list_head entry;
+-	enum qeth_prot_versions proto;
+-	char addr[16];
+-	int mask_bits;
+-};
+-
+-struct qeth_ipato {
+-	int enabled;
+-	int invert4;
+-	int invert6;
+-	struct list_head entries;
+-};
+-
+-struct qeth_channel;
+-
+-struct qeth_cmd_buffer {
+-	enum qeth_cmd_buffer_state state;
+-	struct qeth_channel *channel;
+-	unsigned char *data;
+-	int rc;
+-	void (*callback) (struct qeth_channel *, struct qeth_cmd_buffer *);
+-};
+-
+-
+-/**
+- * definition of a qeth channel, used for read and write
+- */
+-struct qeth_channel {
+-	enum qeth_channel_states state;
+-	struct ccw1 ccw;
+-	spinlock_t iob_lock;
+-	wait_queue_head_t wait_q;
+-	struct tasklet_struct irq_tasklet;
+-	struct ccw_device *ccwdev;
+-/*command buffer for control data*/
+-	struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
+-	atomic_t irq_pending;
+-	volatile int io_buf_no;
+-	volatile int buf_no;
+-};
+-
+-/**
+- *  OSA card related definitions
+- */
+-struct qeth_token {
+-	__u32 issuer_rm_w;
+-	__u32 issuer_rm_r;
+-	__u32 cm_filter_w;
+-	__u32 cm_filter_r;
+-	__u32 cm_connection_w;
+-	__u32 cm_connection_r;
+-	__u32 ulp_filter_w;
+-	__u32 ulp_filter_r;
+-	__u32 ulp_connection_w;
+-	__u32 ulp_connection_r;
+-};
+-
+-struct qeth_seqno {
+-	__u32 trans_hdr;
+-	__u32 pdu_hdr;
+-	__u32 pdu_hdr_ack;
+-	__u16 ipa;
+-	__u32 pkt_seqno;
+-};
+-
+-struct qeth_reply {
+-	struct list_head list;
+-	wait_queue_head_t wait_q;
+-	int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long);
+- 	u32 seqno;
+-	unsigned long offset;
+-	atomic_t received;
+-	int rc;
+-	void *param;
+-	struct qeth_card *card;
+-	atomic_t refcnt;
+-};
+-
+-
+-struct qeth_card_blkt {
+-	int time_total;
+-	int inter_packet;
+-	int inter_packet_jumbo;
+-};
+-
+-#define QETH_BROADCAST_WITH_ECHO    0x01
+-#define QETH_BROADCAST_WITHOUT_ECHO 0x02
+-#define QETH_LAYER2_MAC_READ	    0x01
+-#define QETH_LAYER2_MAC_REGISTERED  0x02
+-struct qeth_card_info {
+-	unsigned short unit_addr2;
+-	unsigned short cula;
+-	unsigned short chpid;
+-	__u16 func_level;
+-	char mcl_level[QETH_MCL_LENGTH + 1];
+-	int guestlan;
+-	int mac_bits;
+-	int portname_required;
+-	int portno;
+-	char portname[9];
+-	enum qeth_card_types type;
+-	enum qeth_link_types link_type;
+-	int is_multicast_different;
+-	int initial_mtu;
+-	int max_mtu;
+-	int broadcast_capable;
+-	int unique_id;
+-	struct qeth_card_blkt blkt;
+-	__u32 csum_mask;
+-	enum qeth_ipa_promisc_modes promisc_mode;
+-};
+-
+-struct qeth_card_options {
+-	struct qeth_routing_info route4;
+-	struct qeth_ipa_info ipa4;
+-	struct qeth_ipa_info adp; /*Adapter parameters*/
+-#ifdef CONFIG_QETH_IPV6
+-	struct qeth_routing_info route6;
+-	struct qeth_ipa_info ipa6;
+-#endif /* QETH_IPV6 */
+-	enum qeth_checksum_types checksum_type;
+-	int broadcast_mode;
+-	int macaddr_mode;
+-	int fake_broadcast;
+-	int add_hhlen;
+-	int fake_ll;
+-	int layer2;
+-	enum qeth_large_send_types large_send;
+-	int performance_stats;
+-	int rx_sg_cb;
+-};
+-
+-/*
+- * thread bits for qeth_card thread masks
+- */
+-enum qeth_threads {
+-	QETH_SET_IP_THREAD  = 1,
+-	QETH_RECOVER_THREAD = 2,
+-	QETH_SET_PROMISC_MODE_THREAD = 4,
+-};
+-
+-struct qeth_osn_info {
+-	int (*assist_cb)(struct net_device *dev, void *data);
+-	int (*data_cb)(struct sk_buff *skb);
+-};
+-
+-struct qeth_card {
+-	struct list_head list;
+-	enum qeth_card_states state;
+-	int lan_online;
+-	spinlock_t lock;
+-/*hardware and sysfs stuff*/
+-	struct ccwgroup_device *gdev;
+-	struct qeth_channel read;
+-	struct qeth_channel write;
+-	struct qeth_channel data;
+-
+-	struct net_device *dev;
+-	struct net_device_stats stats;
+-
+-	struct qeth_card_info info;
+-	struct qeth_token token;
+-	struct qeth_seqno seqno;
+-	struct qeth_card_options options;
+-
+-	wait_queue_head_t wait_q;
+-#ifdef CONFIG_QETH_VLAN
+-	spinlock_t vlanlock;
+-	struct vlan_group *vlangrp;
+-#endif
+-	struct work_struct kernel_thread_starter;
+-	spinlock_t thread_mask_lock;
+-	volatile unsigned long thread_start_mask;
+-	volatile unsigned long thread_allowed_mask;
+-	volatile unsigned long thread_running_mask;
+-	spinlock_t ip_lock;
+-	struct list_head ip_list;
+-	struct list_head *ip_tbd_list;
+-	struct qeth_ipato ipato;
+-	struct list_head cmd_waiter_list;
+-	/* QDIO buffer handling */
+-	struct qeth_qdio_info qdio;
+-	struct qeth_perf_stats perf_stats;
+-	int use_hard_stop;
+-	const struct header_ops *orig_header_ops;
+-	struct qeth_osn_info osn_info;
+-	atomic_t force_alloc_skb;
+-};
+-
+-struct qeth_card_list_struct {
+-	struct list_head list;
+-	rwlock_t rwlock;
+-};
+-
+-extern struct qeth_card_list_struct qeth_card_list;
+-
+-/*notifier list */
+-struct qeth_notify_list_struct {
+-	struct list_head list;
+-	struct task_struct *task;
+-	int signum;
+-};
+-extern spinlock_t qeth_notify_lock;
+-extern struct list_head qeth_notify_list;
+-
+-/*some helper functions*/
+-
+-#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
+-
+-static inline __u8
+-qeth_get_ipa_adp_type(enum qeth_link_types link_type)
+-{
+-	switch (link_type) {
+-	case QETH_LINK_TYPE_HSTR:
+-		return 2;
+-	default:
+-		return 1;
+-	}
+-}
+-
+-static inline struct sk_buff *
+-qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size)
+-{
+-	struct sk_buff *new_skb = skb;
+-
+-	if (skb_headroom(skb) >= size)
+-		return skb;
+-	new_skb = skb_realloc_headroom(skb, size);
+-	if (!new_skb) 
+-		PRINT_ERR("Could not realloc headroom for qeth_hdr "
+-			  "on interface %s", QETH_CARD_IFNAME(card));
+-	return new_skb;
+-}
+-
+-static inline struct sk_buff *
+-qeth_pskb_unshare(struct sk_buff *skb, gfp_t pri)
+-{
+-        struct sk_buff *nskb;
+-        if (!skb_cloned(skb))
+-                return skb;
+-        nskb = skb_copy(skb, pri);
+-        return nskb;
+-}
+-
+-static inline void *
+-qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size)
+-{
+-        void *hdr;
+-
+-	hdr = (void *) skb_push(skb, size);
+-        /*
+-         * sanity check, the Linux memory allocation scheme should
+-         * never present us cases like this one (the qdio header size plus
+-         * the first 40 bytes of the paket cross a 4k boundary)
+-         */
+-        if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
+-            (((unsigned long) hdr + size +
+-              QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
+-                PRINT_ERR("Misaligned packet on interface %s. Discarded.",
+-                          QETH_CARD_IFNAME(card));
+-                return NULL;
+-        }
+-        return hdr;
+-}
+-
+-
+-static inline int
+-qeth_get_hlen(__u8 link_type)
+-{
+-#ifdef CONFIG_QETH_IPV6
+-	switch (link_type) {
+-	case QETH_LINK_TYPE_HSTR:
+-	case QETH_LINK_TYPE_LANE_TR:
+-		return sizeof(struct qeth_hdr_tso) + TR_HLEN;
+-	default:
+-#ifdef CONFIG_QETH_VLAN
+-		return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN;
+-#else
+-		return sizeof(struct qeth_hdr_tso) + ETH_HLEN;
+-#endif
+-	}
+-#else  /* CONFIG_QETH_IPV6 */
+-#ifdef CONFIG_QETH_VLAN
+-	return sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
+-#else
+-	return sizeof(struct qeth_hdr_tso);
+-#endif
+-#endif /* CONFIG_QETH_IPV6 */
+-}
+-
+-static inline unsigned short
+-qeth_get_netdev_flags(struct qeth_card *card)
+-{
+-	if (card->options.layer2 &&
+-	   (card->info.type == QETH_CARD_TYPE_OSAE))
+-		return 0;
+-	switch (card->info.type) {
+-	case QETH_CARD_TYPE_IQD:
+-	case QETH_CARD_TYPE_OSN:
+-		return IFF_NOARP;
+-#ifdef CONFIG_QETH_IPV6
+-	default:
+-		return 0;
+-#else
+-	default:
+-		return IFF_NOARP;
+-#endif
+-	}
+-}
+-
+-static inline int
+-qeth_get_initial_mtu_for_card(struct qeth_card * card)
+-{
+-	switch (card->info.type) {
+-	case QETH_CARD_TYPE_UNKNOWN:
+-		return 1500;
+-	case QETH_CARD_TYPE_IQD:
+-		return card->info.max_mtu;
+-	case QETH_CARD_TYPE_OSAE:
+-		switch (card->info.link_type) {
+-		case QETH_LINK_TYPE_HSTR:
+-		case QETH_LINK_TYPE_LANE_TR:
+-			return 2000;
+-		default:
+-			return 1492;
+-		}
+-	default:
+-		return 1500;
+-	}
+-}
+-
+-static inline int
+-qeth_get_max_mtu_for_card(int cardtype)
+-{
+-	switch (cardtype) {
+-
+-	case QETH_CARD_TYPE_UNKNOWN:
+-	case QETH_CARD_TYPE_OSAE:
+-	case QETH_CARD_TYPE_OSN:
+-		return 61440;
+-	case QETH_CARD_TYPE_IQD:
+-		return 57344;
+-	default:
+-		return 1500;
+-	}
+-}
+-
+-static inline int
+-qeth_get_mtu_out_of_mpc(int cardtype)
+-{
+-	switch (cardtype) {
+-	case QETH_CARD_TYPE_IQD:
+-		return 1;
+-	default:
+-		return 0;
+-	}
+-}
+-
+-static inline int
+-qeth_get_mtu_outof_framesize(int framesize)
+-{
+-	switch (framesize) {
+-	case 0x4000:
+-		return 8192;
+-	case 0x6000:
+-		return 16384;
+-	case 0xa000:
+-		return 32768;
+-	case 0xffff:
+-		return 57344;
+-	default:
+-		return 0;
+-	}
+-}
+-
+-static inline int
+-qeth_mtu_is_valid(struct qeth_card * card, int mtu)
+-{
+-	switch (card->info.type) {
+-	case QETH_CARD_TYPE_OSAE:
+-		return ((mtu >= 576) && (mtu <= 61440));
+-	case QETH_CARD_TYPE_IQD:
+-		return ((mtu >= 576) &&
+-			(mtu <= card->info.max_mtu + 4096 - 32));
+-	case QETH_CARD_TYPE_OSN:
+-	case QETH_CARD_TYPE_UNKNOWN:
+-	default:
+-		return 1;
+-	}
+-}
+-
+-static inline int
+-qeth_get_arphdr_type(int cardtype, int linktype)
+-{
+-	switch (cardtype) {
+-	case QETH_CARD_TYPE_OSAE:
+-	case QETH_CARD_TYPE_OSN:
+-		switch (linktype) {
+-		case QETH_LINK_TYPE_LANE_TR:
+-		case QETH_LINK_TYPE_HSTR:
+-			return ARPHRD_IEEE802_TR;
+-		default:
+-			return ARPHRD_ETHER;
+-		}
+-	case QETH_CARD_TYPE_IQD:
+-	default:
+-		return ARPHRD_ETHER;
+-	}
+-}
+-
+-static inline int
+-qeth_get_micros(void)
+-{
+-	return (int) (get_clock() >> 12);
+-}
+-
+-static inline int
+-qeth_get_qdio_q_format(struct qeth_card *card)
+-{
+-	switch (card->info.type) {
+-	case QETH_CARD_TYPE_IQD:
+-		return 2;
+-	default:
+-		return 0;
+-	}
+-}
+-
+-static inline int
+-qeth_isxdigit(char * buf)
+-{
+-	while (*buf) {
+-		if (!isxdigit(*buf++))
+-			return 0;
+-	}
+-	return 1;
+-}
+-
+-static inline void
+-qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
+-{
+-	sprintf(buf, "%i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
+-}
+-
+-static inline int
+-qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
+-{
+-	int count = 0, rc = 0;
+-	int in[4];
+-	char c;
+-
+-	rc = sscanf(buf, "%u.%u.%u.%u%c",
+-		    &in[0], &in[1], &in[2], &in[3], &c);
+-	if (rc != 4 && (rc != 5 || c != '\n'))
+-		return -EINVAL;
+-	for (count = 0; count < 4; count++) {
+-		if (in[count] > 255)
+-			return -EINVAL;
+-		addr[count] = in[count];
+-	}
+-	return 0;
+-}
+-
+-static inline void
+-qeth_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]);
+-}
+-
+-static inline int
+-qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
+-{
+-	const char *end, *end_tmp, *start;
+-	__u16 *in;
+-        char num[5];
+-        int num2, cnt, out, found, save_cnt;
+-        unsigned short in_tmp[8] = {0, };
+-
+-	cnt = out = found = save_cnt = num2 = 0;
+-        end = start = buf;
+-	in = (__u16 *) addr;
+-	memset(in, 0, 16);
+-        while (*end) {
+-                end = strchr(start,':');
+-                if (end == NULL) {
+-                        end = buf + strlen(buf);
+-			if ((end_tmp = strchr(start, '\n')) != NULL)
+-				end = end_tmp;
+-			out = 1;
+-                }
+-                if ((end - start)) {
+-                        memset(num, 0, 5);
+-			if ((end - start) > 4)
+-				return -EINVAL;
+-                        memcpy(num, start, end - start);
+-			if (!qeth_isxdigit(num))
+-				return -EINVAL;
+-                        sscanf(start, "%x", &num2);
+-                        if (found)
+-                                in_tmp[save_cnt++] = num2;
+-                        else
+-                                in[cnt++] = num2;
+-                        if (out)
+-                                break;
+-                } else {
+-			if (found)
+-				return -EINVAL;
+-                        found = 1;
+-		}
+-		start = ++end;
+-        }
+-	if (cnt + save_cnt > 8)
+-		return -EINVAL;
+-        cnt = 7;
+-	while (save_cnt)
+-                in[cnt--] = in_tmp[--save_cnt];
+-	return 0;
+-}
+-
+-static inline void
+-qeth_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
+-		      char *buf)
+-{
+-	if (proto == QETH_PROT_IPV4)
+-		qeth_ipaddr4_to_string(addr, buf);
+-	else if (proto == QETH_PROT_IPV6)
+-		qeth_ipaddr6_to_string(addr, buf);
+-}
+-
+-static inline int
+-qeth_string_to_ipaddr(const char *buf, enum qeth_prot_versions proto,
+-		      __u8 *addr)
+-{
+-	if (proto == QETH_PROT_IPV4)
+-		return qeth_string_to_ipaddr4(buf, addr);
+-	else if (proto == QETH_PROT_IPV6)
+-		return qeth_string_to_ipaddr6(buf, addr);
+-	else
+-		return -EINVAL;
+-}
+-
+-extern int
+-qeth_setrouting_v4(struct qeth_card *);
+-extern int
+-qeth_setrouting_v6(struct qeth_card *);
+-
+-extern int
+-qeth_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *);
+-
+-extern void
+-qeth_del_ipato_entry(struct qeth_card *, enum qeth_prot_versions, u8 *, int);
+-
+-extern int
+-qeth_add_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+-
+-extern void
+-qeth_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+-
+-extern int
+-qeth_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+-
+-extern void
+-qeth_del_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+-
+-extern int
+-qeth_notifier_register(struct task_struct *, int );
+-
+-extern int
+-qeth_notifier_unregister(struct task_struct * );
+-
+-extern void
+-qeth_schedule_recovery(struct qeth_card *);
+-
+-extern int
+-qeth_realloc_buffer_pool(struct qeth_card *, int);
+-
+-extern int
+-qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
+-
+-extern void
+-qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
+-		 struct sk_buff *, int, int);
+-extern void
+-qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
+-
+-extern int
+-qeth_osn_assist(struct net_device *, void *, int);
+-
+-extern int
+-qeth_osn_register(unsigned char *read_dev_no,
+-                 struct net_device **,
+-                 int (*assist_cb)(struct net_device *, void *),
+-                 int (*data_cb)(struct sk_buff *));
+-
+-extern void
+-qeth_osn_deregister(struct net_device *);
+-
+-#endif /* __QETH_H__ */
+diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
+new file mode 100644
+index 0000000..66f4f12
+--- /dev/null
++++ b/drivers/s390/net/qeth_core.h
+@@ -0,0 +1,905 @@
++/*
++ *  drivers/s390/net/qeth_core.h
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ *		 Frank Pavlic <fpavlic at de.ibm.com>,
++ *		 Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#ifndef __QETH_CORE_H__
++#define __QETH_CORE_H__
++
++#include <linux/if.h>
++#include <linux/if_arp.h>
++#include <linux/if_tr.h>
++#include <linux/trdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/if_vlan.h>
++#include <linux/ctype.h>
++#include <linux/in6.h>
++#include <linux/bitops.h>
++#include <linux/seq_file.h>
++#include <linux/ethtool.h>
++
++#include <net/ipv6.h>
++#include <net/if_inet6.h>
++#include <net/addrconf.h>
++
++#include <asm/debug.h>
++#include <asm/qdio.h>
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++
++#include "qeth_core_mpc.h"
++
++#define KMSG_COMPONENT "qeth"
++
++/**
++ * Debug Facility stuff
++ */
++enum qeth_dbf_names {
++	QETH_DBF_SETUP,
++	QETH_DBF_QERR,
++	QETH_DBF_TRACE,
++	QETH_DBF_MSG,
++	QETH_DBF_SENSE,
++	QETH_DBF_MISC,
++	QETH_DBF_CTRL,
++	QETH_DBF_INFOS	/* must be last element */
++};
++
++struct qeth_dbf_info {
++	char name[DEBUG_MAX_NAME_LEN];
++	int pages;
++	int areas;
++	int len;
++	int level;
++	struct debug_view *view;
++	debug_info_t *id;
++};
++
++#define QETH_DBF_CTRL_LEN 256
++
++#define QETH_DBF_TEXT(name, level, text) \
++	debug_text_event(qeth_dbf[QETH_DBF_##name].id, level, text)
++
++#define QETH_DBF_HEX(name, level, addr, len) \
++	debug_event(qeth_dbf[QETH_DBF_##name].id, level, (void *)(addr), len)
++
++#define QETH_DBF_MESSAGE(level, text...) \
++	debug_sprintf_event(qeth_dbf[QETH_DBF_MSG].id, level, text)
++
++#define QETH_DBF_TEXT_(name, level, text...) \
++	do { \
++		if (qeth_dbf_passes(qeth_dbf[QETH_DBF_##name].id, level)) { \
++			char *dbf_txt_buf = \
++				get_cpu_var(QETH_DBF_TXT_BUF); \
++			sprintf(dbf_txt_buf, text); \
++			debug_text_event(qeth_dbf[QETH_DBF_##name].id, \
++					level, dbf_txt_buf); \
++			put_cpu_var(QETH_DBF_TXT_BUF); \
++		} \
++	} while (0)
++
++/* Allow to sort out low debug levels early to avoid wasted sprints */
++static inline int qeth_dbf_passes(debug_info_t *dbf_grp, int level)
++{
++	return (level <= dbf_grp->level);
++}
++
++/**
++ * some more debug stuff
++ */
++#define PRINTK_HEADER	"qeth: "
++
++#define SENSE_COMMAND_REJECT_BYTE 0
++#define SENSE_COMMAND_REJECT_FLAG 0x80
++#define SENSE_RESETTING_EVENT_BYTE 1
++#define SENSE_RESETTING_EVENT_FLAG 0x80
++
++/*
++ * Common IO related definitions
++ */
++#define CARD_RDEV(card) card->read.ccwdev
++#define CARD_WDEV(card) card->write.ccwdev
++#define CARD_DDEV(card) card->data.ccwdev
++#define CARD_BUS_ID(card) card->gdev->dev.bus_id
++#define CARD_RDEV_ID(card) card->read.ccwdev->dev.bus_id
++#define CARD_WDEV_ID(card) card->write.ccwdev->dev.bus_id
++#define CARD_DDEV_ID(card) card->data.ccwdev->dev.bus_id
++#define CHANNEL_ID(channel) channel->ccwdev->dev.bus_id
++
++/**
++ * card stuff
++ */
++struct qeth_perf_stats {
++	unsigned int bufs_rec;
++	unsigned int bufs_sent;
++
++	unsigned int skbs_sent_pack;
++	unsigned int bufs_sent_pack;
++
++	unsigned int sc_dp_p;
++	unsigned int sc_p_dp;
++	/* qdio_input_handler: number of times called, time spent in */
++	__u64 inbound_start_time;
++	unsigned int inbound_cnt;
++	unsigned int inbound_time;
++	/* qeth_send_packet: number of times called, time spent in */
++	__u64 outbound_start_time;
++	unsigned int outbound_cnt;
++	unsigned int outbound_time;
++	/* qdio_output_handler: number of times called, time spent in */
++	__u64 outbound_handler_start_time;
++	unsigned int outbound_handler_cnt;
++	unsigned int outbound_handler_time;
++	/* number of calls to and time spent in do_QDIO for inbound queue */
++	__u64 inbound_do_qdio_start_time;
++	unsigned int inbound_do_qdio_cnt;
++	unsigned int inbound_do_qdio_time;
++	/* number of calls to and time spent in do_QDIO for outbound queues */
++	__u64 outbound_do_qdio_start_time;
++	unsigned int outbound_do_qdio_cnt;
++	unsigned int outbound_do_qdio_time;
++	/* eddp data */
++	unsigned int large_send_bytes;
++	unsigned int large_send_cnt;
++	unsigned int sg_skbs_sent;
++	unsigned int sg_frags_sent;
++	/* initial values when measuring starts */
++	unsigned long initial_rx_packets;
++	unsigned long initial_tx_packets;
++	/* inbound scatter gather data */
++	unsigned int sg_skbs_rx;
++	unsigned int sg_frags_rx;
++	unsigned int sg_alloc_page_rx;
++};
++
++/* Routing stuff */
++struct qeth_routing_info {
++	enum qeth_routing_types type;
++};
++
++/* IPA stuff */
++struct qeth_ipa_info {
++	__u32 supported_funcs;
++	__u32 enabled_funcs;
++};
++
++static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa,
++		enum qeth_ipa_funcs func)
++{
++	return (ipa->supported_funcs & func);
++}
++
++static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
++		enum qeth_ipa_funcs func)
++{
++	return (ipa->supported_funcs & ipa->enabled_funcs & func);
++}
++
++#define qeth_adp_supported(c, f) \
++	qeth_is_ipa_supported(&c->options.adp, f)
++#define qeth_adp_enabled(c, f) \
++	qeth_is_ipa_enabled(&c->options.adp, f)
++#define qeth_is_supported(c, f) \
++	qeth_is_ipa_supported(&c->options.ipa4, f)
++#define qeth_is_enabled(c, f) \
++	qeth_is_ipa_enabled(&c->options.ipa4, f)
++#define qeth_is_supported6(c, f) \
++	qeth_is_ipa_supported(&c->options.ipa6, f)
++#define qeth_is_enabled6(c, f) \
++	qeth_is_ipa_enabled(&c->options.ipa6, f)
++#define qeth_is_ipafunc_supported(c, prot, f) \
++	 ((prot == QETH_PROT_IPV6) ? \
++		qeth_is_supported6(c, f) : qeth_is_supported(c, f))
++#define qeth_is_ipafunc_enabled(c, prot, f) \
++	 ((prot == QETH_PROT_IPV6) ? \
++		qeth_is_enabled6(c, f) : qeth_is_enabled(c, f))
++
++#define QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT 0x0101
++#define QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT 0x0101
++#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108
++#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108
++
++#define QETH_MODELLIST_ARRAY \
++	{{0x1731, 0x01, 0x1732, 0x01, QETH_CARD_TYPE_OSAE, 1, \
++	QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
++	QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
++	QETH_MAX_QUEUES, 0}, \
++	{0x1731, 0x05, 0x1732, 0x05, QETH_CARD_TYPE_IQD, 0, \
++	QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
++	QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
++	QETH_MAX_QUEUES, 0x103}, \
++	{0x1731, 0x06, 0x1732, 0x06, QETH_CARD_TYPE_OSN, 0, \
++	QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
++	QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
++	QETH_MAX_QUEUES, 0}, \
++	{0, 0, 0, 0, 0, 0, 0, 0, 0} }
++
++#define QETH_REAL_CARD		1
++#define QETH_VLAN_CARD		2
++#define QETH_BUFSIZE		4096
++
++/**
++ * some more defs
++ */
++#define QETH_TX_TIMEOUT		100 * HZ
++#define QETH_RCD_TIMEOUT	60 * HZ
++#define QETH_HEADER_SIZE	32
++#define QETH_MAX_PORTNO		15
++
++/*IPv6 address autoconfiguration stuff*/
++#define UNIQUE_ID_IF_CREATE_ADDR_FAILED 0xfffe
++#define UNIQUE_ID_NOT_BY_CARD		0x10000
++
++/*****************************************************************************/
++/* QDIO queue and buffer handling                                            */
++/*****************************************************************************/
++#define QETH_MAX_QUEUES 4
++#define QETH_IN_BUF_SIZE_DEFAULT 65536
++#define QETH_IN_BUF_COUNT_DEFAULT 16
++#define QETH_IN_BUF_COUNT_MIN 8
++#define QETH_IN_BUF_COUNT_MAX 128
++#define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
++#define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
++		((card)->qdio.in_buf_pool.buf_count / 2)
++
++/* buffers we have to be behind before we get a PCI */
++#define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
++/*enqueued free buffers left before we get a PCI*/
++#define QETH_PCI_THRESHOLD_B(card) 0
++/*not used unless the microcode gets patched*/
++#define QETH_PCI_TIMER_VALUE(card) 3
++
++#define QETH_MIN_INPUT_THRESHOLD 1
++#define QETH_MAX_INPUT_THRESHOLD 500
++#define QETH_MIN_OUTPUT_THRESHOLD 1
++#define QETH_MAX_OUTPUT_THRESHOLD 300
++
++/* priority queing */
++#define QETH_PRIOQ_DEFAULT QETH_NO_PRIO_QUEUEING
++#define QETH_DEFAULT_QUEUE    2
++#define QETH_NO_PRIO_QUEUEING 0
++#define QETH_PRIO_Q_ING_PREC  1
++#define QETH_PRIO_Q_ING_TOS   2
++#define IP_TOS_LOWDELAY 0x10
++#define IP_TOS_HIGHTHROUGHPUT 0x08
++#define IP_TOS_HIGHRELIABILITY 0x04
++#define IP_TOS_NOTIMPORTANT 0x02
++
++/* Packing */
++#define QETH_LOW_WATERMARK_PACK  2
++#define QETH_HIGH_WATERMARK_PACK 5
++#define QETH_WATERMARK_PACK_FUZZ 1
++
++#define QETH_IP_HEADER_SIZE 40
++
++/* large receive scatter gather copy break */
++#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
++
++struct qeth_hdr_layer3 {
++	__u8  id;
++	__u8  flags;
++	__u16 inbound_checksum; /*TSO:__u16 seqno */
++	__u32 token;		/*TSO: __u32 reserved */
++	__u16 length;
++	__u8  vlan_prio;
++	__u8  ext_flags;
++	__u16 vlan_id;
++	__u16 frame_offset;
++	__u8  dest_addr[16];
++} __attribute__ ((packed));
++
++struct qeth_hdr_layer2 {
++	__u8 id;
++	__u8 flags[3];
++	__u8 port_no;
++	__u8 hdr_length;
++	__u16 pkt_length;
++	__u16 seq_no;
++	__u16 vlan_id;
++	__u32 reserved;
++	__u8 reserved2[16];
++} __attribute__ ((packed));
++
++struct qeth_hdr_osn {
++	__u8 id;
++	__u8 reserved;
++	__u16 seq_no;
++	__u16 reserved2;
++	__u16 control_flags;
++	__u16 pdu_length;
++	__u8 reserved3[18];
++	__u32 ccid;
++} __attribute__ ((packed));
++
++struct qeth_hdr {
++	union {
++		struct qeth_hdr_layer2 l2;
++		struct qeth_hdr_layer3 l3;
++		struct qeth_hdr_osn    osn;
++	} hdr;
++} __attribute__ ((packed));
++
++/*TCP Segmentation Offload header*/
++struct qeth_hdr_ext_tso {
++	__u16 hdr_tot_len;
++	__u8  imb_hdr_no;
++	__u8  reserved;
++	__u8  hdr_type;
++	__u8  hdr_version;
++	__u16 hdr_len;
++	__u32 payload_len;
++	__u16 mss;
++	__u16 dg_hdr_len;
++	__u8  padding[16];
++} __attribute__ ((packed));
++
++struct qeth_hdr_tso {
++	struct qeth_hdr hdr;	/*hdr->hdr.l3.xxx*/
++	struct qeth_hdr_ext_tso ext;
++} __attribute__ ((packed));
++
++
++/* flags for qeth_hdr.flags */
++#define QETH_HDR_PASSTHRU 0x10
++#define QETH_HDR_IPV6     0x80
++#define QETH_HDR_CAST_MASK 0x07
++enum qeth_cast_flags {
++	QETH_CAST_UNICAST   = 0x06,
++	QETH_CAST_MULTICAST = 0x04,
++	QETH_CAST_BROADCAST = 0x05,
++	QETH_CAST_ANYCAST   = 0x07,
++	QETH_CAST_NOCAST    = 0x00,
++};
++
++enum qeth_layer2_frame_flags {
++	QETH_LAYER2_FLAG_MULTICAST = 0x01,
++	QETH_LAYER2_FLAG_BROADCAST = 0x02,
++	QETH_LAYER2_FLAG_UNICAST   = 0x04,
++	QETH_LAYER2_FLAG_VLAN      = 0x10,
++};
++
++enum qeth_header_ids {
++	QETH_HEADER_TYPE_LAYER3 = 0x01,
++	QETH_HEADER_TYPE_LAYER2 = 0x02,
++	QETH_HEADER_TYPE_TSO	= 0x03,
++	QETH_HEADER_TYPE_OSN    = 0x04,
++};
++/* flags for qeth_hdr.ext_flags */
++#define QETH_HDR_EXT_VLAN_FRAME       0x01
++#define QETH_HDR_EXT_TOKEN_ID         0x02
++#define QETH_HDR_EXT_INCLUDE_VLAN_TAG 0x04
++#define QETH_HDR_EXT_SRC_MAC_ADDR     0x08
++#define QETH_HDR_EXT_CSUM_HDR_REQ     0x10
++#define QETH_HDR_EXT_CSUM_TRANSP_REQ  0x20
++#define QETH_HDR_EXT_UDP_TSO          0x40 /*bit off for TCP*/
++
++static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale)
++{
++	return (sbale->flags & SBAL_FLAGS_LAST_ENTRY);
++}
++
++enum qeth_qdio_buffer_states {
++	/*
++	 * inbound: read out by driver; owned by hardware in order to be filled
++	 * outbound: owned by driver in order to be filled
++	 */
++	QETH_QDIO_BUF_EMPTY,
++	/*
++	 * inbound: filled by hardware; owned by driver in order to be read out
++	 * outbound: filled by driver; owned by hardware in order to be sent
++	 */
++	QETH_QDIO_BUF_PRIMED,
++};
++
++enum qeth_qdio_info_states {
++	QETH_QDIO_UNINITIALIZED,
++	QETH_QDIO_ALLOCATED,
++	QETH_QDIO_ESTABLISHED,
++	QETH_QDIO_CLEANING
++};
++
++struct qeth_buffer_pool_entry {
++	struct list_head list;
++	struct list_head init_list;
++	void *elements[QDIO_MAX_ELEMENTS_PER_BUFFER];
++};
++
++struct qeth_qdio_buffer_pool {
++	struct list_head entry_list;
++	int buf_count;
++};
++
++struct qeth_qdio_buffer {
++	struct qdio_buffer *buffer;
++	/* the buffer pool entry currently associated to this buffer */
++	struct qeth_buffer_pool_entry *pool_entry;
++};
++
++struct qeth_qdio_q {
++	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
++	struct qeth_qdio_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
++	int next_buf_to_init;
++} __attribute__ ((aligned(256)));
++
++/* possible types of qeth large_send support */
++enum qeth_large_send_types {
++	QETH_LARGE_SEND_NO,
++	QETH_LARGE_SEND_EDDP,
++	QETH_LARGE_SEND_TSO,
++};
++
++struct qeth_qdio_out_buffer {
++	struct qdio_buffer *buffer;
++	atomic_t state;
++	int next_element_to_fill;
++	struct sk_buff_head skb_list;
++	struct list_head ctx_list;
++};
++
++struct qeth_card;
++
++enum qeth_out_q_states {
++       QETH_OUT_Q_UNLOCKED,
++       QETH_OUT_Q_LOCKED,
++       QETH_OUT_Q_LOCKED_FLUSH,
++};
++
++struct qeth_qdio_out_q {
++	struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
++	struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
++	int queue_no;
++	struct qeth_card *card;
++	atomic_t state;
++	int do_pack;
++	/*
++	 * index of buffer to be filled by driver; state EMPTY or PACKING
++	 */
++	int next_buf_to_fill;
++	/*
++	 * number of buffers that are currently filled (PRIMED)
++	 * -> these buffers are hardware-owned
++	 */
++	atomic_t used_buffers;
++	/* indicates whether PCI flag must be set (or if one is outstanding) */
++	atomic_t set_pci_flags_count;
++} __attribute__ ((aligned(256)));
++
++struct qeth_qdio_info {
++	atomic_t state;
++	/* input */
++	struct qeth_qdio_q *in_q;
++	struct qeth_qdio_buffer_pool in_buf_pool;
++	struct qeth_qdio_buffer_pool init_pool;
++	int in_buf_size;
++
++	/* output */
++	int no_out_queues;
++	struct qeth_qdio_out_q **out_qs;
++
++	/* priority queueing */
++	int do_prio_queueing;
++	int default_out_queue;
++};
++
++enum qeth_send_errors {
++	QETH_SEND_ERROR_NONE,
++	QETH_SEND_ERROR_LINK_FAILURE,
++	QETH_SEND_ERROR_RETRY,
++	QETH_SEND_ERROR_KICK_IT,
++};
++
++#define QETH_ETH_MAC_V4      0x0100 /* like v4 */
++#define QETH_ETH_MAC_V6      0x3333 /* like v6 */
++/* tr mc mac is longer, but that will be enough to detect mc frames */
++#define QETH_TR_MAC_NC       0xc000 /* non-canonical */
++#define QETH_TR_MAC_C        0x0300 /* canonical */
++
++#define DEFAULT_ADD_HHLEN 0
++#define MAX_ADD_HHLEN 1024
++
++/**
++ * buffer stuff for read channel
++ */
++#define QETH_CMD_BUFFER_NO	8
++
++/**
++ *  channel state machine
++ */
++enum qeth_channel_states {
++	CH_STATE_UP,
++	CH_STATE_DOWN,
++	CH_STATE_ACTIVATING,
++	CH_STATE_HALTED,
++	CH_STATE_STOPPED,
++	CH_STATE_RCD,
++	CH_STATE_RCD_DONE,
++};
++/**
++ * card state machine
++ */
++enum qeth_card_states {
++	CARD_STATE_DOWN,
++	CARD_STATE_HARDSETUP,
++	CARD_STATE_SOFTSETUP,
++	CARD_STATE_UP,
++	CARD_STATE_RECOVER,
++};
++
++/**
++ * Protocol versions
++ */
++enum qeth_prot_versions {
++	QETH_PROT_IPV4 = 0x0004,
++	QETH_PROT_IPV6 = 0x0006,
++};
++
++enum qeth_ip_types {
++	QETH_IP_TYPE_NORMAL,
++	QETH_IP_TYPE_VIPA,
++	QETH_IP_TYPE_RXIP,
++	QETH_IP_TYPE_DEL_ALL_MC,
++};
++
++enum qeth_cmd_buffer_state {
++	BUF_STATE_FREE,
++	BUF_STATE_LOCKED,
++	BUF_STATE_PROCESSED,
++};
++
++struct qeth_ipato {
++	int enabled;
++	int invert4;
++	int invert6;
++	struct list_head entries;
++};
++
++struct qeth_channel;
++
++struct qeth_cmd_buffer {
++	enum qeth_cmd_buffer_state state;
++	struct qeth_channel *channel;
++	unsigned char *data;
++	int rc;
++	void (*callback) (struct qeth_channel *, struct qeth_cmd_buffer *);
++};
++
++/**
++ * definition of a qeth channel, used for read and write
++ */
++struct qeth_channel {
++	enum qeth_channel_states state;
++	struct ccw1 ccw;
++	spinlock_t iob_lock;
++	wait_queue_head_t wait_q;
++	struct tasklet_struct irq_tasklet;
++	struct ccw_device *ccwdev;
++/*command buffer for control data*/
++	struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
++	atomic_t irq_pending;
++	int io_buf_no;
++	int buf_no;
++};
++
++/**
++ *  OSA card related definitions
++ */
++struct qeth_token {
++	__u32 issuer_rm_w;
++	__u32 issuer_rm_r;
++	__u32 cm_filter_w;
++	__u32 cm_filter_r;
++	__u32 cm_connection_w;
++	__u32 cm_connection_r;
++	__u32 ulp_filter_w;
++	__u32 ulp_filter_r;
++	__u32 ulp_connection_w;
++	__u32 ulp_connection_r;
++};
++
++struct qeth_seqno {
++	__u32 trans_hdr;
++	__u32 pdu_hdr;
++	__u32 pdu_hdr_ack;
++	__u16 ipa;
++	__u32 pkt_seqno;
++};
++
++struct qeth_reply {
++	struct list_head list;
++	wait_queue_head_t wait_q;
++	int (*callback)(struct qeth_card *, struct qeth_reply *,
++		unsigned long);
++	u32 seqno;
++	unsigned long offset;
++	atomic_t received;
++	int rc;
++	void *param;
++	struct qeth_card *card;
++	atomic_t refcnt;
++};
++
++
++struct qeth_card_blkt {
++	int time_total;
++	int inter_packet;
++	int inter_packet_jumbo;
++};
++
++#define QETH_BROADCAST_WITH_ECHO    0x01
++#define QETH_BROADCAST_WITHOUT_ECHO 0x02
++#define QETH_LAYER2_MAC_READ	    0x01
++#define QETH_LAYER2_MAC_REGISTERED  0x02
++struct qeth_card_info {
++	unsigned short unit_addr2;
++	unsigned short cula;
++	unsigned short chpid;
++	__u16 func_level;
++	char mcl_level[QETH_MCL_LENGTH + 1];
++	int guestlan;
++	int mac_bits;
++	int portname_required;
++	int portno;
++	char portname[9];
++	enum qeth_card_types type;
++	enum qeth_link_types link_type;
++	int is_multicast_different;
++	int initial_mtu;
++	int max_mtu;
++	int broadcast_capable;
++	int unique_id;
++	struct qeth_card_blkt blkt;
++	__u32 csum_mask;
++	enum qeth_ipa_promisc_modes promisc_mode;
++};
++
++struct qeth_card_options {
++	struct qeth_routing_info route4;
++	struct qeth_ipa_info ipa4;
++	struct qeth_ipa_info adp; /*Adapter parameters*/
++	struct qeth_routing_info route6;
++	struct qeth_ipa_info ipa6;
++	enum qeth_checksum_types checksum_type;
++	int broadcast_mode;
++	int macaddr_mode;
++	int fake_broadcast;
++	int add_hhlen;
++	int fake_ll;
++	int layer2;
++	enum qeth_large_send_types large_send;
++	int performance_stats;
++	int rx_sg_cb;
++};
++
++/*
++ * thread bits for qeth_card thread masks
++ */
++enum qeth_threads {
++	QETH_RECOVER_THREAD = 1,
++};
++
++struct qeth_osn_info {
++	int (*assist_cb)(struct net_device *dev, void *data);
++	int (*data_cb)(struct sk_buff *skb);
++};
++
++enum qeth_discipline_id {
++	QETH_DISCIPLINE_LAYER3 = 0,
++	QETH_DISCIPLINE_LAYER2 = 1,
++};
++
++struct qeth_discipline {
++	qdio_handler_t *input_handler;
++	qdio_handler_t *output_handler;
++	int (*recover)(void *ptr);
++	struct ccwgroup_driver *ccwgdriver;
++};
++
++struct qeth_vlan_vid {
++	struct list_head list;
++	unsigned short vid;
++};
++
++struct qeth_mc_mac {
++	struct list_head list;
++	__u8 mc_addr[MAX_ADDR_LEN];
++	unsigned char mc_addrlen;
++};
++
++struct qeth_card {
++	struct list_head list;
++	enum qeth_card_states state;
++	int lan_online;
++	spinlock_t lock;
++	struct ccwgroup_device *gdev;
++	struct qeth_channel read;
++	struct qeth_channel write;
++	struct qeth_channel data;
++
++	struct net_device *dev;
++	struct net_device_stats stats;
++
++	struct qeth_card_info info;
++	struct qeth_token token;
++	struct qeth_seqno seqno;
++	struct qeth_card_options options;
++
++	wait_queue_head_t wait_q;
++	spinlock_t vlanlock;
++	spinlock_t mclock;
++	struct vlan_group *vlangrp;
++	struct list_head vid_list;
++	struct list_head mc_list;
++	struct work_struct kernel_thread_starter;
++	spinlock_t thread_mask_lock;
++	unsigned long thread_start_mask;
++	unsigned long thread_allowed_mask;
++	unsigned long thread_running_mask;
++	spinlock_t ip_lock;
++	struct list_head ip_list;
++	struct list_head *ip_tbd_list;
++	struct qeth_ipato ipato;
++	struct list_head cmd_waiter_list;
++	/* QDIO buffer handling */
++	struct qeth_qdio_info qdio;
++	struct qeth_perf_stats perf_stats;
++	int use_hard_stop;
++	struct qeth_osn_info osn_info;
++	struct qeth_discipline discipline;
++	atomic_t force_alloc_skb;
++};
++
++struct qeth_card_list_struct {
++	struct list_head list;
++	rwlock_t rwlock;
++};
++
++/*some helper functions*/
++#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
++
++static inline struct qeth_card *CARD_FROM_CDEV(struct ccw_device *cdev)
++{
++	struct qeth_card *card = dev_get_drvdata(&((struct ccwgroup_device *)
++		dev_get_drvdata(&cdev->dev))->dev);
++	return card;
++}
++
++static inline int qeth_get_micros(void)
++{
++	return (int) (get_clock() >> 12);
++}
++
++static inline void *qeth_push_skb(struct qeth_card *card, struct sk_buff *skb,
++		int size)
++{
++	void *hdr;
++
++	hdr = (void *) skb_push(skb, size);
++	/*
++	 * sanity check, the Linux memory allocation scheme should
++	 * never present us cases like this one (the qdio header size plus
++	 * the first 40 bytes of the paket cross a 4k boundary)
++	 */
++	if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
++	    (((unsigned long) hdr + size +
++	    QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
++		PRINT_ERR("Misaligned packet on interface %s. Discarded.",
++			QETH_CARD_IFNAME(card));
++		return NULL;
++	}
++	return hdr;
++}
++
++static inline int qeth_get_ip_version(struct sk_buff *skb)
++{
++	switch (skb->protocol) {
++	case ETH_P_IPV6:
++		return 6;
++	case ETH_P_IP:
++		return 4;
++	default:
++		return 0;
++	}
++}
++
++struct qeth_eddp_context;
++extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
++extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
++const char *qeth_get_cardname_short(struct qeth_card *);
++int qeth_realloc_buffer_pool(struct qeth_card *, int);
++int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
++void qeth_core_free_discipline(struct qeth_card *);
++int qeth_core_create_device_attributes(struct device *);
++void qeth_core_remove_device_attributes(struct device *);
++int qeth_core_create_osn_attributes(struct device *);
++void qeth_core_remove_osn_attributes(struct device *);
++
++/* exports for qeth discipline device drivers */
++extern struct qeth_card_list_struct qeth_core_card_list;
++
++extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];
++
++void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
++int qeth_threads_running(struct qeth_card *, unsigned long);
++int qeth_wait_for_threads(struct qeth_card *, unsigned long);
++int qeth_do_run_thread(struct qeth_card *, unsigned long);
++void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long);
++void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long);
++int qeth_core_hardsetup_card(struct qeth_card *);
++void qeth_print_status_message(struct qeth_card *);
++int qeth_init_qdio_queues(struct qeth_card *);
++int qeth_send_startlan(struct qeth_card *);
++int qeth_send_stoplan(struct qeth_card *);
++int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *,
++		  int (*reply_cb)
++		  (struct qeth_card *, struct qeth_reply *, unsigned long),
++		  void *);
++struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *,
++			enum qeth_ipa_cmds, enum qeth_prot_versions);
++int qeth_query_setadapterparms(struct qeth_card *);
++int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int,
++		       unsigned int, const char *);
++void qeth_put_buffer_pool_entry(struct qeth_card *,
++			   struct qeth_buffer_pool_entry *);
++void qeth_queue_input_buffer(struct qeth_card *, int);
++struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
++		struct qdio_buffer *, struct qdio_buffer_element **, int *,
++		struct qeth_hdr **);
++void qeth_schedule_recovery(struct qeth_card *);
++void qeth_qdio_output_handler(struct ccw_device *, unsigned int,
++			unsigned int, unsigned int,
++			unsigned int, int, int,
++			unsigned long);
++void qeth_clear_ipacmd_list(struct qeth_card *);
++int qeth_qdio_clear_card(struct qeth_card *, int);
++void qeth_clear_working_pool_list(struct qeth_card *);
++void qeth_clear_cmd_buffers(struct qeth_channel *);
++void qeth_clear_qdio_buffers(struct qeth_card *);
++void qeth_setadp_promisc_mode(struct qeth_card *);
++struct net_device_stats *qeth_get_stats(struct net_device *);
++int qeth_change_mtu(struct net_device *, int);
++int qeth_setadpparms_change_macaddr(struct qeth_card *);
++void qeth_tx_timeout(struct net_device *);
++void qeth_prepare_control_data(struct qeth_card *, int,
++				struct qeth_cmd_buffer *);
++void qeth_release_buffer(struct qeth_channel *, struct qeth_cmd_buffer *);
++void qeth_prepare_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, char);
++struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
++int qeth_mdio_read(struct net_device *, int, int);
++int qeth_snmp_command(struct qeth_card *, char __user *);
++int qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
++struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32);
++int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *,
++					unsigned long);
++int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
++	int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
++	void *reply_param);
++int qeth_get_cast_type(struct qeth_card *, struct sk_buff *);
++int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
++struct sk_buff *qeth_prepare_skb(struct qeth_card *, struct sk_buff *,
++		 struct qeth_hdr **);
++int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int);
++int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
++			struct sk_buff *, struct qeth_hdr *, int,
++			struct qeth_eddp_context *);
++int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *,
++		    struct sk_buff *, struct qeth_hdr *,
++		    int, struct qeth_eddp_context *);
++int qeth_core_get_stats_count(struct net_device *);
++void qeth_core_get_ethtool_stats(struct net_device *,
++				struct ethtool_stats *, u64 *);
++void qeth_core_get_strings(struct net_device *, u32, u8 *);
++void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
++
++/* exports for OSN */
++int qeth_osn_assist(struct net_device *, void *, int);
++int qeth_osn_register(unsigned char *read_dev_no, struct net_device **,
++		int (*assist_cb)(struct net_device *, void *),
++		int (*data_cb)(struct sk_buff *));
++void qeth_osn_deregister(struct net_device *);
++
++#endif /* __QETH_CORE_H__ */
+diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
+new file mode 100644
+index 0000000..055f5c3
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_main.c
+@@ -0,0 +1,4492 @@
++/*
++ *  drivers/s390/net/qeth_core_main.c
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ *		 Frank Pavlic <fpavlic at de.ibm.com>,
++ *		 Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/ip.h>
++#include <linux/ipv6.h>
++#include <linux/tcp.h>
++#include <linux/mii.h>
++#include <linux/kthread.h>
++
++#include <asm-s390/ebcdic.h>
++#include <asm-s390/io.h>
++#include <asm/s390_rdev.h>
++
++#include "qeth_core.h"
++#include "qeth_core_offl.h"
++
++static DEFINE_PER_CPU(char[256], qeth_core_dbf_txt_buf);
++#define QETH_DBF_TXT_BUF qeth_core_dbf_txt_buf
++
++struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = {
++	/* define dbf - Name, Pages, Areas, Maxlen, Level, View, Handle */
++	/*                   N  P  A    M  L  V                      H  */
++	[QETH_DBF_SETUP] = {"qeth_setup",
++				8, 1,   8, 5, &debug_hex_ascii_view, NULL},
++	[QETH_DBF_QERR]  = {"qeth_qerr",
++				2, 1,   8, 2, &debug_hex_ascii_view, NULL},
++	[QETH_DBF_TRACE] = {"qeth_trace",
++				4, 1,   8, 3, &debug_hex_ascii_view, NULL},
++	[QETH_DBF_MSG]   = {"qeth_msg",
++				8, 1, 128, 3, &debug_sprintf_view,   NULL},
++	[QETH_DBF_SENSE] = {"qeth_sense",
++				2, 1,  64, 2, &debug_hex_ascii_view, NULL},
++	[QETH_DBF_MISC]	 = {"qeth_misc",
++				2, 1, 256, 2, &debug_hex_ascii_view, NULL},
++	[QETH_DBF_CTRL]  = {"qeth_control",
++		8, 1, QETH_DBF_CTRL_LEN, 5, &debug_hex_ascii_view, NULL},
++};
++EXPORT_SYMBOL_GPL(qeth_dbf);
++
++struct qeth_card_list_struct qeth_core_card_list;
++EXPORT_SYMBOL_GPL(qeth_core_card_list);
++
++static struct device *qeth_core_root_dev;
++static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
++static struct lock_class_key qdio_out_skb_queue_key;
++
++static void qeth_send_control_data_cb(struct qeth_channel *,
++			struct qeth_cmd_buffer *);
++static int qeth_issue_next_read(struct qeth_card *);
++static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *);
++static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32);
++static void qeth_free_buffer_pool(struct qeth_card *);
++static int qeth_qdio_establish(struct qeth_card *);
++
++
++static inline void __qeth_fill_buffer_frag(struct sk_buff *skb,
++		struct qdio_buffer *buffer, int is_tso,
++		int *next_element_to_fill)
++{
++	struct skb_frag_struct *frag;
++	int fragno;
++	unsigned long addr;
++	int element, cnt, dlen;
++
++	fragno = skb_shinfo(skb)->nr_frags;
++	element = *next_element_to_fill;
++	dlen = 0;
++
++	if (is_tso)
++		buffer->element[element].flags =
++			SBAL_FLAGS_MIDDLE_FRAG;
++	else
++		buffer->element[element].flags =
++			SBAL_FLAGS_FIRST_FRAG;
++	dlen = skb->len - skb->data_len;
++	if (dlen) {
++		buffer->element[element].addr = skb->data;
++		buffer->element[element].length = dlen;
++		element++;
++	}
++	for (cnt = 0; cnt < fragno; cnt++) {
++		frag = &skb_shinfo(skb)->frags[cnt];
++		addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
++			frag->page_offset;
++		buffer->element[element].addr = (char *)addr;
++		buffer->element[element].length = frag->size;
++		if (cnt < (fragno - 1))
++			buffer->element[element].flags =
++				SBAL_FLAGS_MIDDLE_FRAG;
++		else
++			buffer->element[element].flags =
++				SBAL_FLAGS_LAST_FRAG;
++		element++;
++	}
++	*next_element_to_fill = element;
++}
++
++static inline const char *qeth_get_cardname(struct qeth_card *card)
++{
++	if (card->info.guestlan) {
++		switch (card->info.type) {
++		case QETH_CARD_TYPE_OSAE:
++			return " Guest LAN QDIO";
++		case QETH_CARD_TYPE_IQD:
++			return " Guest LAN Hiper";
++		default:
++			return " unknown";
++		}
++	} else {
++		switch (card->info.type) {
++		case QETH_CARD_TYPE_OSAE:
++			return " OSD Express";
++		case QETH_CARD_TYPE_IQD:
++			return " HiperSockets";
++		case QETH_CARD_TYPE_OSN:
++			return " OSN QDIO";
++		default:
++			return " unknown";
++		}
++	}
++	return " n/a";
++}
++
++/* max length to be returned: 14 */
++const char *qeth_get_cardname_short(struct qeth_card *card)
++{
++	if (card->info.guestlan) {
++		switch (card->info.type) {
++		case QETH_CARD_TYPE_OSAE:
++			return "GuestLAN QDIO";
++		case QETH_CARD_TYPE_IQD:
++			return "GuestLAN Hiper";
++		default:
++			return "unknown";
++		}
++	} else {
++		switch (card->info.type) {
++		case QETH_CARD_TYPE_OSAE:
++			switch (card->info.link_type) {
++			case QETH_LINK_TYPE_FAST_ETH:
++				return "OSD_100";
++			case QETH_LINK_TYPE_HSTR:
++				return "HSTR";
++			case QETH_LINK_TYPE_GBIT_ETH:
++				return "OSD_1000";
++			case QETH_LINK_TYPE_10GBIT_ETH:
++				return "OSD_10GIG";
++			case QETH_LINK_TYPE_LANE_ETH100:
++				return "OSD_FE_LANE";
++			case QETH_LINK_TYPE_LANE_TR:
++				return "OSD_TR_LANE";
++			case QETH_LINK_TYPE_LANE_ETH1000:
++				return "OSD_GbE_LANE";
++			case QETH_LINK_TYPE_LANE:
++				return "OSD_ATM_LANE";
++			default:
++				return "OSD_Express";
++			}
++		case QETH_CARD_TYPE_IQD:
++			return "HiperSockets";
++		case QETH_CARD_TYPE_OSN:
++			return "OSN";
++		default:
++			return "unknown";
++		}
++	}
++	return "n/a";
++}
++
++void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
++			 int clear_start_mask)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&card->thread_mask_lock, flags);
++	card->thread_allowed_mask = threads;
++	if (clear_start_mask)
++		card->thread_start_mask &= threads;
++	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++	wake_up(&card->wait_q);
++}
++EXPORT_SYMBOL_GPL(qeth_set_allowed_threads);
++
++int qeth_threads_running(struct qeth_card *card, unsigned long threads)
++{
++	unsigned long flags;
++	int rc = 0;
++
++	spin_lock_irqsave(&card->thread_mask_lock, flags);
++	rc = (card->thread_running_mask & threads);
++	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_threads_running);
++
++int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
++{
++	return wait_event_interruptible(card->wait_q,
++			qeth_threads_running(card, threads) == 0);
++}
++EXPORT_SYMBOL_GPL(qeth_wait_for_threads);
++
++void qeth_clear_working_pool_list(struct qeth_card *card)
++{
++	struct qeth_buffer_pool_entry *pool_entry, *tmp;
++
++	QETH_DBF_TEXT(TRACE, 5, "clwrklst");
++	list_for_each_entry_safe(pool_entry, tmp,
++			    &card->qdio.in_buf_pool.entry_list, list){
++			list_del(&pool_entry->list);
++	}
++}
++EXPORT_SYMBOL_GPL(qeth_clear_working_pool_list);
++
++static int qeth_alloc_buffer_pool(struct qeth_card *card)
++{
++	struct qeth_buffer_pool_entry *pool_entry;
++	void *ptr;
++	int i, j;
++
++	QETH_DBF_TEXT(TRACE, 5, "alocpool");
++	for (i = 0; i < card->qdio.init_pool.buf_count; ++i) {
++		pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
++		if (!pool_entry) {
++			qeth_free_buffer_pool(card);
++			return -ENOMEM;
++		}
++		for (j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j) {
++			ptr = (void *) __get_free_page(GFP_KERNEL);
++			if (!ptr) {
++				while (j > 0)
++					free_page((unsigned long)
++						  pool_entry->elements[--j]);
++				kfree(pool_entry);
++				qeth_free_buffer_pool(card);
++				return -ENOMEM;
++			}
++			pool_entry->elements[j] = ptr;
++		}
++		list_add(&pool_entry->init_list,
++			 &card->qdio.init_pool.entry_list);
++	}
++	return 0;
++}
++
++int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
++{
++	QETH_DBF_TEXT(TRACE, 2, "realcbp");
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	/* TODO: steel/add buffers from/to a running card's buffer pool (?) */
++	qeth_clear_working_pool_list(card);
++	qeth_free_buffer_pool(card);
++	card->qdio.in_buf_pool.buf_count = bufcnt;
++	card->qdio.init_pool.buf_count = bufcnt;
++	return qeth_alloc_buffer_pool(card);
++}
++
++int qeth_set_large_send(struct qeth_card *card,
++		enum qeth_large_send_types type)
++{
++	int rc = 0;
++
++	if (card->dev == NULL) {
++		card->options.large_send = type;
++		return 0;
++	}
++	if (card->state == CARD_STATE_UP)
++		netif_tx_disable(card->dev);
++	card->options.large_send = type;
++	switch (card->options.large_send) {
++	case QETH_LARGE_SEND_EDDP:
++		card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
++					NETIF_F_HW_CSUM;
++		break;
++	case QETH_LARGE_SEND_TSO:
++		if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
++			card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
++						NETIF_F_HW_CSUM;
++		} else {
++			PRINT_WARN("TSO not supported on %s. "
++				   "large_send set to 'no'.\n",
++				   card->dev->name);
++			card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
++						NETIF_F_HW_CSUM);
++			card->options.large_send = QETH_LARGE_SEND_NO;
++			rc = -EOPNOTSUPP;
++		}
++		break;
++	default: /* includes QETH_LARGE_SEND_NO */
++		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
++					NETIF_F_HW_CSUM);
++		break;
++	}
++	if (card->state == CARD_STATE_UP)
++		netif_wake_queue(card->dev);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_set_large_send);
++
++static int qeth_issue_next_read(struct qeth_card *card)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(TRACE, 5, "issnxrd");
++	if (card->read.state != CH_STATE_UP)
++		return -EIO;
++	iob = qeth_get_buffer(&card->read);
++	if (!iob) {
++		PRINT_WARN("issue_next_read failed: no iob available!\n");
++		return -ENOMEM;
++	}
++	qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
++	QETH_DBF_TEXT(TRACE, 6, "noirqpnd");
++	rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
++			      (addr_t) iob, 0, 0);
++	if (rc) {
++		PRINT_ERR("Error in starting next read ccw! rc=%i\n", rc);
++		atomic_set(&card->read.irq_pending, 0);
++		qeth_schedule_recovery(card);
++		wake_up(&card->wait_q);
++	}
++	return rc;
++}
++
++static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
++{
++	struct qeth_reply *reply;
++
++	reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
++	if (reply) {
++		atomic_set(&reply->refcnt, 1);
++		atomic_set(&reply->received, 0);
++		reply->card = card;
++	};
++	return reply;
++}
++
++static void qeth_get_reply(struct qeth_reply *reply)
++{
++	WARN_ON(atomic_read(&reply->refcnt) <= 0);
++	atomic_inc(&reply->refcnt);
++}
++
++static void qeth_put_reply(struct qeth_reply *reply)
++{
++	WARN_ON(atomic_read(&reply->refcnt) <= 0);
++	if (atomic_dec_and_test(&reply->refcnt))
++		kfree(reply);
++}
++
++static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
++		struct qeth_card *card)
++{
++	char *ipa_name;
++	int com = cmd->hdr.command;
++	ipa_name = qeth_get_ipa_cmd_name(com);
++	if (rc)
++		QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s returned x%X \"%s\"\n",
++				ipa_name, com, QETH_CARD_IFNAME(card),
++					rc, qeth_get_ipa_msg(rc));
++	else
++		QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s succeeded\n",
++				ipa_name, com, QETH_CARD_IFNAME(card));
++}
++
++static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
++		struct qeth_cmd_buffer *iob)
++{
++	struct qeth_ipa_cmd *cmd = NULL;
++
++	QETH_DBF_TEXT(TRACE, 5, "chkipad");
++	if (IS_IPA(iob->data)) {
++		cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
++		if (IS_IPA_REPLY(cmd)) {
++			if (cmd->hdr.command < IPA_CMD_SETCCID ||
++			    cmd->hdr.command > IPA_CMD_MODCCID)
++				qeth_issue_ipa_msg(cmd,
++						cmd->hdr.return_code, card);
++			return cmd;
++		} else {
++			switch (cmd->hdr.command) {
++			case IPA_CMD_STOPLAN:
++				PRINT_WARN("Link failure on %s (CHPID 0x%X) - "
++					   "there is a network problem or "
++					   "someone pulled the cable or "
++					   "disabled the port.\n",
++					   QETH_CARD_IFNAME(card),
++					   card->info.chpid);
++				card->lan_online = 0;
++				if (card->dev && netif_carrier_ok(card->dev))
++					netif_carrier_off(card->dev);
++				return NULL;
++			case IPA_CMD_STARTLAN:
++				PRINT_INFO("Link reestablished on %s "
++					   "(CHPID 0x%X). Scheduling "
++					   "IP address reset.\n",
++					   QETH_CARD_IFNAME(card),
++					   card->info.chpid);
++				netif_carrier_on(card->dev);
++				card->lan_online = 1;
++				qeth_schedule_recovery(card);
++				return NULL;
++			case IPA_CMD_MODCCID:
++				return cmd;
++			case IPA_CMD_REGISTER_LOCAL_ADDR:
++				QETH_DBF_TEXT(TRACE, 3, "irla");
++				break;
++			case IPA_CMD_UNREGISTER_LOCAL_ADDR:
++				QETH_DBF_TEXT(TRACE, 3, "urla");
++				break;
++			default:
++				PRINT_WARN("Received data is IPA "
++					   "but not a reply!\n");
++				break;
++			}
++		}
++	}
++	return cmd;
++}
++
++void qeth_clear_ipacmd_list(struct qeth_card *card)
++{
++	struct qeth_reply *reply, *r;
++	unsigned long flags;
++
++	QETH_DBF_TEXT(TRACE, 4, "clipalst");
++
++	spin_lock_irqsave(&card->lock, flags);
++	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
++		qeth_get_reply(reply);
++		reply->rc = -EIO;
++		atomic_inc(&reply->received);
++		list_del_init(&reply->list);
++		wake_up(&reply->wait_q);
++		qeth_put_reply(reply);
++	}
++	spin_unlock_irqrestore(&card->lock, flags);
++}
++EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list);
++
++static int qeth_check_idx_response(unsigned char *buffer)
++{
++	if (!buffer)
++		return 0;
++
++	QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN);
++	if ((buffer[2] & 0xc0) == 0xc0) {
++		PRINT_WARN("received an IDX TERMINATE "
++			   "with cause code 0x%02x%s\n",
++			   buffer[4],
++			   ((buffer[4] == 0x22) ?
++			    " -- try another portname" : ""));
++		QETH_DBF_TEXT(TRACE, 2, "ckidxres");
++		QETH_DBF_TEXT(TRACE, 2, " idxterm");
++		QETH_DBF_TEXT_(TRACE, 2, "  rc%d", -EIO);
++		return -EIO;
++	}
++	return 0;
++}
++
++static void qeth_setup_ccw(struct qeth_channel *channel, unsigned char *iob,
++		__u32 len)
++{
++	struct qeth_card *card;
++
++	QETH_DBF_TEXT(TRACE, 4, "setupccw");
++	card = CARD_FROM_CDEV(channel->ccwdev);
++	if (channel == &card->read)
++		memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
++	else
++		memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
++	channel->ccw.count = len;
++	channel->ccw.cda = (__u32) __pa(iob);
++}
++
++static struct qeth_cmd_buffer *__qeth_get_buffer(struct qeth_channel *channel)
++{
++	__u8 index;
++
++	QETH_DBF_TEXT(TRACE, 6, "getbuff");
++	index = channel->io_buf_no;
++	do {
++		if (channel->iob[index].state == BUF_STATE_FREE) {
++			channel->iob[index].state = BUF_STATE_LOCKED;
++			channel->io_buf_no = (channel->io_buf_no + 1) %
++				QETH_CMD_BUFFER_NO;
++			memset(channel->iob[index].data, 0, QETH_BUFSIZE);
++			return channel->iob + index;
++		}
++		index = (index + 1) % QETH_CMD_BUFFER_NO;
++	} while (index != channel->io_buf_no);
++
++	return NULL;
++}
++
++void qeth_release_buffer(struct qeth_channel *channel,
++		struct qeth_cmd_buffer *iob)
++{
++	unsigned long flags;
++
++	QETH_DBF_TEXT(TRACE, 6, "relbuff");
++	spin_lock_irqsave(&channel->iob_lock, flags);
++	memset(iob->data, 0, QETH_BUFSIZE);
++	iob->state = BUF_STATE_FREE;
++	iob->callback = qeth_send_control_data_cb;
++	iob->rc = 0;
++	spin_unlock_irqrestore(&channel->iob_lock, flags);
++}
++EXPORT_SYMBOL_GPL(qeth_release_buffer);
++
++static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel)
++{
++	struct qeth_cmd_buffer *buffer = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&channel->iob_lock, flags);
++	buffer = __qeth_get_buffer(channel);
++	spin_unlock_irqrestore(&channel->iob_lock, flags);
++	return buffer;
++}
++
++struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *channel)
++{
++	struct qeth_cmd_buffer *buffer;
++	wait_event(channel->wait_q,
++		   ((buffer = qeth_get_buffer(channel)) != NULL));
++	return buffer;
++}
++EXPORT_SYMBOL_GPL(qeth_wait_for_buffer);
++
++void qeth_clear_cmd_buffers(struct qeth_channel *channel)
++{
++	int cnt;
++
++	for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
++		qeth_release_buffer(channel, &channel->iob[cnt]);
++	channel->buf_no = 0;
++	channel->io_buf_no = 0;
++}
++EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers);
++
++static void qeth_send_control_data_cb(struct qeth_channel *channel,
++		  struct qeth_cmd_buffer *iob)
++{
++	struct qeth_card *card;
++	struct qeth_reply *reply, *r;
++	struct qeth_ipa_cmd *cmd;
++	unsigned long flags;
++	int keep_reply;
++
++	QETH_DBF_TEXT(TRACE, 4, "sndctlcb");
++
++	card = CARD_FROM_CDEV(channel->ccwdev);
++	if (qeth_check_idx_response(iob->data)) {
++		qeth_clear_ipacmd_list(card);
++		qeth_schedule_recovery(card);
++		goto out;
++	}
++
++	cmd = qeth_check_ipa_data(card, iob);
++	if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
++		goto out;
++	/*in case of OSN : check if cmd is set */
++	if (card->info.type == QETH_CARD_TYPE_OSN &&
++	    cmd &&
++	    cmd->hdr.command != IPA_CMD_STARTLAN &&
++	    card->osn_info.assist_cb != NULL) {
++		card->osn_info.assist_cb(card->dev, cmd);
++		goto out;
++	}
++
++	spin_lock_irqsave(&card->lock, flags);
++	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
++		if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
++		    ((cmd) && (reply->seqno == cmd->hdr.seqno))) {
++			qeth_get_reply(reply);
++			list_del_init(&reply->list);
++			spin_unlock_irqrestore(&card->lock, flags);
++			keep_reply = 0;
++			if (reply->callback != NULL) {
++				if (cmd) {
++					reply->offset = (__u16)((char *)cmd -
++							(char *)iob->data);
++					keep_reply = reply->callback(card,
++							reply,
++							(unsigned long)cmd);
++				} else
++					keep_reply = reply->callback(card,
++							reply,
++							(unsigned long)iob);
++			}
++			if (cmd)
++				reply->rc = (u16) cmd->hdr.return_code;
++			else if (iob->rc)
++				reply->rc = iob->rc;
++			if (keep_reply) {
++				spin_lock_irqsave(&card->lock, flags);
++				list_add_tail(&reply->list,
++					      &card->cmd_waiter_list);
++				spin_unlock_irqrestore(&card->lock, flags);
++			} else {
++				atomic_inc(&reply->received);
++				wake_up(&reply->wait_q);
++			}
++			qeth_put_reply(reply);
++			goto out;
++		}
++	}
++	spin_unlock_irqrestore(&card->lock, flags);
++out:
++	memcpy(&card->seqno.pdu_hdr_ack,
++		QETH_PDU_HEADER_SEQ_NO(iob->data),
++		QETH_SEQ_NO_LENGTH);
++	qeth_release_buffer(channel, iob);
++}
++
++static int qeth_setup_channel(struct qeth_channel *channel)
++{
++	int cnt;
++
++	QETH_DBF_TEXT(SETUP, 2, "setupch");
++	for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
++		channel->iob[cnt].data = (char *)
++			kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
++		if (channel->iob[cnt].data == NULL)
++			break;
++		channel->iob[cnt].state = BUF_STATE_FREE;
++		channel->iob[cnt].channel = channel;
++		channel->iob[cnt].callback = qeth_send_control_data_cb;
++		channel->iob[cnt].rc = 0;
++	}
++	if (cnt < QETH_CMD_BUFFER_NO) {
++		while (cnt-- > 0)
++			kfree(channel->iob[cnt].data);
++		return -ENOMEM;
++	}
++	channel->buf_no = 0;
++	channel->io_buf_no = 0;
++	atomic_set(&channel->irq_pending, 0);
++	spin_lock_init(&channel->iob_lock);
++
++	init_waitqueue_head(&channel->wait_q);
++	return 0;
++}
++
++static int qeth_set_thread_start_bit(struct qeth_card *card,
++		unsigned long thread)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&card->thread_mask_lock, flags);
++	if (!(card->thread_allowed_mask & thread) ||
++	      (card->thread_start_mask & thread)) {
++		spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++		return -EPERM;
++	}
++	card->thread_start_mask |= thread;
++	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++	return 0;
++}
++
++void qeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&card->thread_mask_lock, flags);
++	card->thread_start_mask &= ~thread;
++	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++	wake_up(&card->wait_q);
++}
++EXPORT_SYMBOL_GPL(qeth_clear_thread_start_bit);
++
++void qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&card->thread_mask_lock, flags);
++	card->thread_running_mask &= ~thread;
++	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++	wake_up(&card->wait_q);
++}
++EXPORT_SYMBOL_GPL(qeth_clear_thread_running_bit);
++
++static int __qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
++{
++	unsigned long flags;
++	int rc = 0;
++
++	spin_lock_irqsave(&card->thread_mask_lock, flags);
++	if (card->thread_start_mask & thread) {
++		if ((card->thread_allowed_mask & thread) &&
++		    !(card->thread_running_mask & thread)) {
++			rc = 1;
++			card->thread_start_mask &= ~thread;
++			card->thread_running_mask |= thread;
++		} else
++			rc = -EPERM;
++	}
++	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++	return rc;
++}
++
++int qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
++{
++	int rc = 0;
++
++	wait_event(card->wait_q,
++		   (rc = __qeth_do_run_thread(card, thread)) >= 0);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_do_run_thread);
++
++void qeth_schedule_recovery(struct qeth_card *card)
++{
++	QETH_DBF_TEXT(TRACE, 2, "startrec");
++	if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
++		schedule_work(&card->kernel_thread_starter);
++}
++EXPORT_SYMBOL_GPL(qeth_schedule_recovery);
++
++static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
++{
++	int dstat, cstat;
++	char *sense;
++
++	sense = (char *) irb->ecw;
++	cstat = irb->scsw.cstat;
++	dstat = irb->scsw.dstat;
++
++	if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
++		     SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
++		     SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
++		QETH_DBF_TEXT(TRACE, 2, "CGENCHK");
++		PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ",
++			   cdev->dev.bus_id, dstat, cstat);
++		print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET,
++				16, 1, irb, 64, 1);
++		return 1;
++	}
++
++	if (dstat & DEV_STAT_UNIT_CHECK) {
++		if (sense[SENSE_RESETTING_EVENT_BYTE] &
++		    SENSE_RESETTING_EVENT_FLAG) {
++			QETH_DBF_TEXT(TRACE, 2, "REVIND");
++			return 1;
++		}
++		if (sense[SENSE_COMMAND_REJECT_BYTE] &
++		    SENSE_COMMAND_REJECT_FLAG) {
++			QETH_DBF_TEXT(TRACE, 2, "CMDREJi");
++			return 0;
++		}
++		if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) {
++			QETH_DBF_TEXT(TRACE, 2, "AFFE");
++			return 1;
++		}
++		if ((!sense[0]) && (!sense[1]) && (!sense[2]) && (!sense[3])) {
++			QETH_DBF_TEXT(TRACE, 2, "ZEROSEN");
++			return 0;
++		}
++		QETH_DBF_TEXT(TRACE, 2, "DGENCHK");
++			return 1;
++	}
++	return 0;
++}
++
++static long __qeth_check_irb_error(struct ccw_device *cdev,
++		unsigned long intparm, struct irb *irb)
++{
++	if (!IS_ERR(irb))
++		return 0;
++
++	switch (PTR_ERR(irb)) {
++	case -EIO:
++		PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
++		QETH_DBF_TEXT(TRACE, 2, "ckirberr");
++		QETH_DBF_TEXT_(TRACE, 2, "  rc%d", -EIO);
++		break;
++	case -ETIMEDOUT:
++		PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
++		QETH_DBF_TEXT(TRACE, 2, "ckirberr");
++		QETH_DBF_TEXT_(TRACE, 2, "  rc%d", -ETIMEDOUT);
++		if (intparm == QETH_RCD_PARM) {
++			struct qeth_card *card = CARD_FROM_CDEV(cdev);
++
++			if (card && (card->data.ccwdev == cdev)) {
++				card->data.state = CH_STATE_DOWN;
++				wake_up(&card->wait_q);
++			}
++		}
++		break;
++	default:
++		PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
++			   cdev->dev.bus_id);
++		QETH_DBF_TEXT(TRACE, 2, "ckirberr");
++		QETH_DBF_TEXT(TRACE, 2, "  rc???");
++	}
++	return PTR_ERR(irb);
++}
++
++static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
++		struct irb *irb)
++{
++	int rc;
++	int cstat, dstat;
++	struct qeth_cmd_buffer *buffer;
++	struct qeth_channel *channel;
++	struct qeth_card *card;
++	struct qeth_cmd_buffer *iob;
++	__u8 index;
++
++	QETH_DBF_TEXT(TRACE, 5, "irq");
++
++	if (__qeth_check_irb_error(cdev, intparm, irb))
++		return;
++	cstat = irb->scsw.cstat;
++	dstat = irb->scsw.dstat;
++
++	card = CARD_FROM_CDEV(cdev);
++	if (!card)
++		return;
++
++	if (card->read.ccwdev == cdev) {
++		channel = &card->read;
++		QETH_DBF_TEXT(TRACE, 5, "read");
++	} else if (card->write.ccwdev == cdev) {
++		channel = &card->write;
++		QETH_DBF_TEXT(TRACE, 5, "write");
++	} else {
++		channel = &card->data;
++		QETH_DBF_TEXT(TRACE, 5, "data");
++	}
++	atomic_set(&channel->irq_pending, 0);
++
++	if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC))
++		channel->state = CH_STATE_STOPPED;
++
++	if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC))
++		channel->state = CH_STATE_HALTED;
++
++	/*let's wake up immediately on data channel*/
++	if ((channel == &card->data) && (intparm != 0) &&
++	    (intparm != QETH_RCD_PARM))
++		goto out;
++
++	if (intparm == QETH_CLEAR_CHANNEL_PARM) {
++		QETH_DBF_TEXT(TRACE, 6, "clrchpar");
++		/* we don't have to handle this further */
++		intparm = 0;
++	}
++	if (intparm == QETH_HALT_CHANNEL_PARM) {
++		QETH_DBF_TEXT(TRACE, 6, "hltchpar");
++		/* we don't have to handle this further */
++		intparm = 0;
++	}
++	if ((dstat & DEV_STAT_UNIT_EXCEP) ||
++	    (dstat & DEV_STAT_UNIT_CHECK) ||
++	    (cstat)) {
++		if (irb->esw.esw0.erw.cons) {
++			/* TODO: we should make this s390dbf */
++			PRINT_WARN("sense data available on channel %s.\n",
++				   CHANNEL_ID(channel));
++			PRINT_WARN(" cstat 0x%X\n dstat 0x%X\n", cstat, dstat);
++			print_hex_dump(KERN_WARNING, "qeth: irb ",
++				DUMP_PREFIX_OFFSET, 16, 1, irb, 32, 1);
++			print_hex_dump(KERN_WARNING, "qeth: sense data ",
++				DUMP_PREFIX_OFFSET, 16, 1, irb->ecw, 32, 1);
++		}
++		if (intparm == QETH_RCD_PARM) {
++			channel->state = CH_STATE_DOWN;
++			goto out;
++		}
++		rc = qeth_get_problem(cdev, irb);
++		if (rc) {
++			qeth_schedule_recovery(card);
++			goto out;
++		}
++	}
++
++	if (intparm == QETH_RCD_PARM) {
++		channel->state = CH_STATE_RCD_DONE;
++		goto out;
++	}
++	if (intparm) {
++		buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
++		buffer->state = BUF_STATE_PROCESSED;
++	}
++	if (channel == &card->data)
++		return;
++	if (channel == &card->read &&
++	    channel->state == CH_STATE_UP)
++		qeth_issue_next_read(card);
++
++	iob = channel->iob;
++	index = channel->buf_no;
++	while (iob[index].state == BUF_STATE_PROCESSED) {
++		if (iob[index].callback != NULL)
++			iob[index].callback(channel, iob + index);
++
++		index = (index + 1) % QETH_CMD_BUFFER_NO;
++	}
++	channel->buf_no = index;
++out:
++	wake_up(&card->wait_q);
++	return;
++}
++
++static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
++		 struct qeth_qdio_out_buffer *buf)
++{
++	int i;
++	struct sk_buff *skb;
++
++	/* is PCI flag set on buffer? */
++	if (buf->buffer->element[0].flags & 0x40)
++		atomic_dec(&queue->set_pci_flags_count);
++
++	skb = skb_dequeue(&buf->skb_list);
++	while (skb) {
++		atomic_dec(&skb->users);
++		dev_kfree_skb_any(skb);
++		skb = skb_dequeue(&buf->skb_list);
++	}
++	qeth_eddp_buf_release_contexts(buf);
++	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) {
++		buf->buffer->element[i].length = 0;
++		buf->buffer->element[i].addr = NULL;
++		buf->buffer->element[i].flags = 0;
++	}
++	buf->next_element_to_fill = 0;
++	atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
++}
++
++void qeth_clear_qdio_buffers(struct qeth_card *card)
++{
++	int i, j;
++
++	QETH_DBF_TEXT(TRACE, 2, "clearqdbf");
++	/* clear outbound buffers to free skbs */
++	for (i = 0; i < card->qdio.no_out_queues; ++i)
++		if (card->qdio.out_qs[i]) {
++			for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
++				qeth_clear_output_buffer(card->qdio.out_qs[i],
++						&card->qdio.out_qs[i]->bufs[j]);
++		}
++}
++EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers);
++
++static void qeth_free_buffer_pool(struct qeth_card *card)
++{
++	struct qeth_buffer_pool_entry *pool_entry, *tmp;
++	int i = 0;
++	QETH_DBF_TEXT(TRACE, 5, "freepool");
++	list_for_each_entry_safe(pool_entry, tmp,
++				 &card->qdio.init_pool.entry_list, init_list){
++		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i)
++			free_page((unsigned long)pool_entry->elements[i]);
++		list_del(&pool_entry->init_list);
++		kfree(pool_entry);
++	}
++}
++
++static void qeth_free_qdio_buffers(struct qeth_card *card)
++{
++	int i, j;
++
++	QETH_DBF_TEXT(TRACE, 2, "freeqdbf");
++	if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
++		QETH_QDIO_UNINITIALIZED)
++		return;
++	kfree(card->qdio.in_q);
++	card->qdio.in_q = NULL;
++	/* inbound buffer pool */
++	qeth_free_buffer_pool(card);
++	/* free outbound qdio_qs */
++	if (card->qdio.out_qs) {
++		for (i = 0; i < card->qdio.no_out_queues; ++i) {
++			for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
++				qeth_clear_output_buffer(card->qdio.out_qs[i],
++						&card->qdio.out_qs[i]->bufs[j]);
++			kfree(card->qdio.out_qs[i]);
++		}
++		kfree(card->qdio.out_qs);
++		card->qdio.out_qs = NULL;
++	}
++}
++
++static void qeth_clean_channel(struct qeth_channel *channel)
++{
++	int cnt;
++
++	QETH_DBF_TEXT(SETUP, 2, "freech");
++	for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
++		kfree(channel->iob[cnt].data);
++}
++
++static int qeth_is_1920_device(struct qeth_card *card)
++{
++	int single_queue = 0;
++	struct ccw_device *ccwdev;
++	struct channelPath_dsc {
++		u8 flags;
++		u8 lsn;
++		u8 desc;
++		u8 chpid;
++		u8 swla;
++		u8 zeroes;
++		u8 chla;
++		u8 chpp;
++	} *chp_dsc;
++
++	QETH_DBF_TEXT(SETUP, 2, "chk_1920");
++
++	ccwdev = card->data.ccwdev;
++	chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
++	if (chp_dsc != NULL) {
++		/* CHPP field bit 6 == 1 -> single queue */
++		single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
++		kfree(chp_dsc);
++	}
++	QETH_DBF_TEXT_(SETUP, 2, "rc:%x", single_queue);
++	return single_queue;
++}
++
++static void qeth_init_qdio_info(struct qeth_card *card)
++{
++	QETH_DBF_TEXT(SETUP, 4, "intqdinf");
++	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
++	/* inbound */
++	card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
++	card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
++	card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
++	INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
++	INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
++}
++
++static void qeth_set_intial_options(struct qeth_card *card)
++{
++	card->options.route4.type = NO_ROUTER;
++	card->options.route6.type = NO_ROUTER;
++	card->options.checksum_type = QETH_CHECKSUM_DEFAULT;
++	card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
++	card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;
++	card->options.fake_broadcast = 0;
++	card->options.add_hhlen = DEFAULT_ADD_HHLEN;
++	card->options.fake_ll = 0;
++	card->options.performance_stats = 0;
++	card->options.rx_sg_cb = QETH_RX_SG_CB;
++}
++
++static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
++{
++	unsigned long flags;
++	int rc = 0;
++
++	spin_lock_irqsave(&card->thread_mask_lock, flags);
++	QETH_DBF_TEXT_(TRACE, 4, "  %02x%02x%02x",
++			(u8) card->thread_start_mask,
++			(u8) card->thread_allowed_mask,
++			(u8) card->thread_running_mask);
++	rc = (card->thread_start_mask & thread);
++	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++	return rc;
++}
++
++static void qeth_start_kernel_thread(struct work_struct *work)
++{
++	struct qeth_card *card = container_of(work, struct qeth_card,
++					kernel_thread_starter);
++	QETH_DBF_TEXT(TRACE , 2, "strthrd");
++
++	if (card->read.state != CH_STATE_UP &&
++	    card->write.state != CH_STATE_UP)
++		return;
++	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
++		kthread_run(card->discipline.recover, (void *) card,
++				"qeth_recover");
++}
++
++static int qeth_setup_card(struct qeth_card *card)
++{
++
++	QETH_DBF_TEXT(SETUP, 2, "setupcrd");
++	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++	card->read.state  = CH_STATE_DOWN;
++	card->write.state = CH_STATE_DOWN;
++	card->data.state  = CH_STATE_DOWN;
++	card->state = CARD_STATE_DOWN;
++	card->lan_online = 0;
++	card->use_hard_stop = 0;
++	card->dev = NULL;
++	spin_lock_init(&card->vlanlock);
++	spin_lock_init(&card->mclock);
++	card->vlangrp = NULL;
++	spin_lock_init(&card->lock);
++	spin_lock_init(&card->ip_lock);
++	spin_lock_init(&card->thread_mask_lock);
++	card->thread_start_mask = 0;
++	card->thread_allowed_mask = 0;
++	card->thread_running_mask = 0;
++	INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
++	INIT_LIST_HEAD(&card->ip_list);
++	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
++	if (!card->ip_tbd_list) {
++		QETH_DBF_TEXT(SETUP, 0, "iptbdnom");
++		return -ENOMEM;
++	}
++	INIT_LIST_HEAD(card->ip_tbd_list);
++	INIT_LIST_HEAD(&card->cmd_waiter_list);
++	init_waitqueue_head(&card->wait_q);
++	/* intial options */
++	qeth_set_intial_options(card);
++	/* IP address takeover */
++	INIT_LIST_HEAD(&card->ipato.entries);
++	card->ipato.enabled = 0;
++	card->ipato.invert4 = 0;
++	card->ipato.invert6 = 0;
++	/* init QDIO stuff */
++	qeth_init_qdio_info(card);
++	return 0;
++}
++
++static struct qeth_card *qeth_alloc_card(void)
++{
++	struct qeth_card *card;
++
++	QETH_DBF_TEXT(SETUP, 2, "alloccrd");
++	card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
++	if (!card)
++		return NULL;
++	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++	if (qeth_setup_channel(&card->read)) {
++		kfree(card);
++		return NULL;
++	}
++	if (qeth_setup_channel(&card->write)) {
++		qeth_clean_channel(&card->read);
++		kfree(card);
++		return NULL;
++	}
++	card->options.layer2 = -1;
++	return card;
++}
++
++static int qeth_determine_card_type(struct qeth_card *card)
++{
++	int i = 0;
++
++	QETH_DBF_TEXT(SETUP, 2, "detcdtyp");
++
++	card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
++	card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
++	while (known_devices[i][4]) {
++		if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
++		    (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
++			card->info.type = known_devices[i][4];
++			card->qdio.no_out_queues = known_devices[i][8];
++			card->info.is_multicast_different = known_devices[i][9];
++			if (qeth_is_1920_device(card)) {
++				PRINT_INFO("Priority Queueing not able "
++					   "due to hardware limitations!\n");
++				card->qdio.no_out_queues = 1;
++				card->qdio.default_out_queue = 0;
++			}
++			return 0;
++		}
++		i++;
++	}
++	card->info.type = QETH_CARD_TYPE_UNKNOWN;
++	PRINT_ERR("unknown card type on device %s\n", CARD_BUS_ID(card));
++	return -ENOENT;
++}
++
++static int qeth_clear_channel(struct qeth_channel *channel)
++{
++	unsigned long flags;
++	struct qeth_card *card;
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "clearch");
++	card = CARD_FROM_CDEV(channel->ccwdev);
++	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++	rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
++	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++
++	if (rc)
++		return rc;
++	rc = wait_event_interruptible_timeout(card->wait_q,
++			channel->state == CH_STATE_STOPPED, QETH_TIMEOUT);
++	if (rc == -ERESTARTSYS)
++		return rc;
++	if (channel->state != CH_STATE_STOPPED)
++		return -ETIME;
++	channel->state = CH_STATE_DOWN;
++	return 0;
++}
++
++static int qeth_halt_channel(struct qeth_channel *channel)
++{
++	unsigned long flags;
++	struct qeth_card *card;
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "haltch");
++	card = CARD_FROM_CDEV(channel->ccwdev);
++	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++	rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
++	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++
++	if (rc)
++		return rc;
++	rc = wait_event_interruptible_timeout(card->wait_q,
++			channel->state == CH_STATE_HALTED, QETH_TIMEOUT);
++	if (rc == -ERESTARTSYS)
++		return rc;
++	if (channel->state != CH_STATE_HALTED)
++		return -ETIME;
++	return 0;
++}
++
++static int qeth_halt_channels(struct qeth_card *card)
++{
++	int rc1 = 0, rc2 = 0, rc3 = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "haltchs");
++	rc1 = qeth_halt_channel(&card->read);
++	rc2 = qeth_halt_channel(&card->write);
++	rc3 = qeth_halt_channel(&card->data);
++	if (rc1)
++		return rc1;
++	if (rc2)
++		return rc2;
++	return rc3;
++}
++
++static int qeth_clear_channels(struct qeth_card *card)
++{
++	int rc1 = 0, rc2 = 0, rc3 = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "clearchs");
++	rc1 = qeth_clear_channel(&card->read);
++	rc2 = qeth_clear_channel(&card->write);
++	rc3 = qeth_clear_channel(&card->data);
++	if (rc1)
++		return rc1;
++	if (rc2)
++		return rc2;
++	return rc3;
++}
++
++static int qeth_clear_halt_card(struct qeth_card *card, int halt)
++{
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "clhacrd");
++	QETH_DBF_HEX(TRACE, 3, &card, sizeof(void *));
++
++	if (halt)
++		rc = qeth_halt_channels(card);
++	if (rc)
++		return rc;
++	return qeth_clear_channels(card);
++}
++
++int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
++{
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "qdioclr");
++	switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED,
++		QETH_QDIO_CLEANING)) {
++	case QETH_QDIO_ESTABLISHED:
++		if (card->info.type == QETH_CARD_TYPE_IQD)
++			rc = qdio_cleanup(CARD_DDEV(card),
++				QDIO_FLAG_CLEANUP_USING_HALT);
++		else
++			rc = qdio_cleanup(CARD_DDEV(card),
++				QDIO_FLAG_CLEANUP_USING_CLEAR);
++		if (rc)
++			QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc);
++		atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
++		break;
++	case QETH_QDIO_CLEANING:
++		return rc;
++	default:
++		break;
++	}
++	rc = qeth_clear_halt_card(card, use_halt);
++	if (rc)
++		QETH_DBF_TEXT_(TRACE, 3, "2err%d", rc);
++	card->state = CARD_STATE_DOWN;
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_qdio_clear_card);
++
++static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
++			       int *length)
++{
++	struct ciw *ciw;
++	char *rcd_buf;
++	int ret;
++	struct qeth_channel *channel = &card->data;
++	unsigned long flags;
++
++	/*
++	 * scan for RCD command in extended SenseID data
++	 */
++	ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
++	if (!ciw || ciw->cmd == 0)
++		return -EOPNOTSUPP;
++	rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
++	if (!rcd_buf)
++		return -ENOMEM;
++
++	channel->ccw.cmd_code = ciw->cmd;
++	channel->ccw.cda = (__u32) __pa(rcd_buf);
++	channel->ccw.count = ciw->count;
++	channel->ccw.flags = CCW_FLAG_SLI;
++	channel->state = CH_STATE_RCD;
++	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++	ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
++				       QETH_RCD_PARM, LPM_ANYPATH, 0,
++				       QETH_RCD_TIMEOUT);
++	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++	if (!ret)
++		wait_event(card->wait_q,
++			   (channel->state == CH_STATE_RCD_DONE ||
++			    channel->state == CH_STATE_DOWN));
++	if (channel->state == CH_STATE_DOWN)
++		ret = -EIO;
++	else
++		channel->state = CH_STATE_DOWN;
++	if (ret) {
++		kfree(rcd_buf);
++		*buffer = NULL;
++		*length = 0;
++	} else {
++		*length = ciw->count;
++		*buffer = rcd_buf;
++	}
++	return ret;
++}
++
++static int qeth_get_unitaddr(struct qeth_card *card)
++{
++	int length;
++	char *prcd;
++	int rc;
++
++	QETH_DBF_TEXT(SETUP, 2, "getunit");
++	rc = qeth_read_conf_data(card, (void **) &prcd, &length);
++	if (rc) {
++		PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
++			CARD_DDEV_ID(card), rc);
++		return rc;
++	}
++	card->info.chpid = prcd[30];
++	card->info.unit_addr2 = prcd[31];
++	card->info.cula = prcd[63];
++	card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
++			       (prcd[0x11] == _ascebc['M']));
++	kfree(prcd);
++	return 0;
++}
++
++static void qeth_init_tokens(struct qeth_card *card)
++{
++	card->token.issuer_rm_w = 0x00010103UL;
++	card->token.cm_filter_w = 0x00010108UL;
++	card->token.cm_connection_w = 0x0001010aUL;
++	card->token.ulp_filter_w = 0x0001010bUL;
++	card->token.ulp_connection_w = 0x0001010dUL;
++}
++
++static void qeth_init_func_level(struct qeth_card *card)
++{
++	if (card->ipato.enabled) {
++		if (card->info.type == QETH_CARD_TYPE_IQD)
++				card->info.func_level =
++					QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
++		else
++				card->info.func_level =
++					QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
++	} else {
++		if (card->info.type == QETH_CARD_TYPE_IQD)
++		/*FIXME:why do we have same values for  dis and ena for
++		  osae??? */
++			card->info.func_level =
++				QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
++		else
++			card->info.func_level =
++				QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT;
++	}
++}
++
++static inline __u16 qeth_raw_devno_from_bus_id(char *id)
++{
++	id += (strlen(id) - 4);
++	return (__u16) simple_strtoul(id, &id, 16);
++}
++
++static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
++		void (*idx_reply_cb)(struct qeth_channel *,
++			struct qeth_cmd_buffer *))
++{
++	struct qeth_cmd_buffer *iob;
++	unsigned long flags;
++	int rc;
++	struct qeth_card *card;
++
++	QETH_DBF_TEXT(SETUP, 2, "idxanswr");
++	card = CARD_FROM_CDEV(channel->ccwdev);
++	iob = qeth_get_buffer(channel);
++	iob->callback = idx_reply_cb;
++	memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
++	channel->ccw.count = QETH_BUFSIZE;
++	channel->ccw.cda = (__u32) __pa(iob->data);
++
++	wait_event(card->wait_q,
++		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
++	QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
++	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++	rc = ccw_device_start(channel->ccwdev,
++			      &channel->ccw, (addr_t) iob, 0, 0);
++	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++
++	if (rc) {
++		PRINT_ERR("Error2 in activating channel rc=%d\n", rc);
++		QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++		atomic_set(&channel->irq_pending, 0);
++		wake_up(&card->wait_q);
++		return rc;
++	}
++	rc = wait_event_interruptible_timeout(card->wait_q,
++			 channel->state == CH_STATE_UP, QETH_TIMEOUT);
++	if (rc == -ERESTARTSYS)
++		return rc;
++	if (channel->state != CH_STATE_UP) {
++		rc = -ETIME;
++		QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++		qeth_clear_cmd_buffers(channel);
++	} else
++		rc = 0;
++	return rc;
++}
++
++static int qeth_idx_activate_channel(struct qeth_channel *channel,
++		void (*idx_reply_cb)(struct qeth_channel *,
++			struct qeth_cmd_buffer *))
++{
++	struct qeth_card *card;
++	struct qeth_cmd_buffer *iob;
++	unsigned long flags;
++	__u16 temp;
++	__u8 tmp;
++	int rc;
++
++	card = CARD_FROM_CDEV(channel->ccwdev);
++
++	QETH_DBF_TEXT(SETUP, 2, "idxactch");
++
++	iob = qeth_get_buffer(channel);
++	iob->callback = idx_reply_cb;
++	memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
++	channel->ccw.count = IDX_ACTIVATE_SIZE;
++	channel->ccw.cda = (__u32) __pa(iob->data);
++	if (channel == &card->write) {
++		memcpy(iob->data, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);
++		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
++		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
++		card->seqno.trans_hdr++;
++	} else {
++		memcpy(iob->data, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE);
++		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
++		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
++	}
++	tmp = ((__u8)card->info.portno) | 0x80;
++	memcpy(QETH_IDX_ACT_PNO(iob->data), &tmp, 1);
++	memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
++	       &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH);
++	memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data),
++	       &card->info.func_level, sizeof(__u16));
++	temp = qeth_raw_devno_from_bus_id(CARD_DDEV_ID(card));
++	memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2);
++	temp = (card->info.cula << 8) + card->info.unit_addr2;
++	memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
++
++	wait_event(card->wait_q,
++		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
++	QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
++	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++	rc = ccw_device_start(channel->ccwdev,
++			      &channel->ccw, (addr_t) iob, 0, 0);
++	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++
++	if (rc) {
++		PRINT_ERR("Error1 in activating channel. rc=%d\n", rc);
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		atomic_set(&channel->irq_pending, 0);
++		wake_up(&card->wait_q);
++		return rc;
++	}
++	rc = wait_event_interruptible_timeout(card->wait_q,
++			channel->state == CH_STATE_ACTIVATING, QETH_TIMEOUT);
++	if (rc == -ERESTARTSYS)
++		return rc;
++	if (channel->state != CH_STATE_ACTIVATING) {
++		PRINT_WARN("IDX activate timed out!\n");
++		QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME);
++		qeth_clear_cmd_buffers(channel);
++		return -ETIME;
++	}
++	return qeth_idx_activate_get_answer(channel, idx_reply_cb);
++}
++
++static int qeth_peer_func_level(int level)
++{
++	if ((level & 0xff) == 8)
++		return (level & 0xff) + 0x400;
++	if (((level >> 8) & 3) == 1)
++		return (level & 0xff) + 0x200;
++	return level;
++}
++
++static void qeth_idx_write_cb(struct qeth_channel *channel,
++		struct qeth_cmd_buffer *iob)
++{
++	struct qeth_card *card;
++	__u16 temp;
++
++	QETH_DBF_TEXT(SETUP , 2, "idxwrcb");
++
++	if (channel->state == CH_STATE_DOWN) {
++		channel->state = CH_STATE_ACTIVATING;
++		goto out;
++	}
++	card = CARD_FROM_CDEV(channel->ccwdev);
++
++	if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
++		if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
++			PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
++				"adapter exclusively used by another host\n",
++			CARD_WDEV_ID(card));
++		else
++			PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
++				"negative reply\n", CARD_WDEV_ID(card));
++		goto out;
++	}
++	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
++	if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) {
++		PRINT_WARN("IDX_ACTIVATE on write channel device %s: "
++			   "function level mismatch "
++			   "(sent: 0x%x, received: 0x%x)\n",
++			   CARD_WDEV_ID(card), card->info.func_level, temp);
++		goto out;
++	}
++	channel->state = CH_STATE_UP;
++out:
++	qeth_release_buffer(channel, iob);
++}
++
++static void qeth_idx_read_cb(struct qeth_channel *channel,
++		struct qeth_cmd_buffer *iob)
++{
++	struct qeth_card *card;
++	__u16 temp;
++
++	QETH_DBF_TEXT(SETUP , 2, "idxrdcb");
++	if (channel->state == CH_STATE_DOWN) {
++		channel->state = CH_STATE_ACTIVATING;
++		goto out;
++	}
++
++	card = CARD_FROM_CDEV(channel->ccwdev);
++	if (qeth_check_idx_response(iob->data))
++			goto out;
++
++	if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
++		if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
++			PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
++				"adapter exclusively used by another host\n",
++				CARD_RDEV_ID(card));
++		else
++			PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
++				"negative reply\n", CARD_RDEV_ID(card));
++		goto out;
++	}
++
++/**
++ * temporary fix for microcode bug
++ * to revert it,replace OR by AND
++ */
++	if ((!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
++	     (card->info.type == QETH_CARD_TYPE_OSAE))
++		card->info.portname_required = 1;
++
++	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
++	if (temp != qeth_peer_func_level(card->info.func_level)) {
++		PRINT_WARN("IDX_ACTIVATE on read channel device %s: function "
++			   "level mismatch (sent: 0x%x, received: 0x%x)\n",
++			   CARD_RDEV_ID(card), card->info.func_level, temp);
++		goto out;
++	}
++	memcpy(&card->token.issuer_rm_r,
++	       QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
++	       QETH_MPC_TOKEN_LENGTH);
++	memcpy(&card->info.mcl_level[0],
++	       QETH_IDX_REPLY_LEVEL(iob->data), QETH_MCL_LENGTH);
++	channel->state = CH_STATE_UP;
++out:
++	qeth_release_buffer(channel, iob);
++}
++
++void qeth_prepare_control_data(struct qeth_card *card, int len,
++		struct qeth_cmd_buffer *iob)
++{
++	qeth_setup_ccw(&card->write, iob->data, len);
++	iob->callback = qeth_release_buffer;
++
++	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
++	       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
++	card->seqno.trans_hdr++;
++	memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
++	       &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
++	card->seqno.pdu_hdr++;
++	memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
++	       &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
++	QETH_DBF_HEX(CTRL, 2, iob->data, QETH_DBF_CTRL_LEN);
++}
++EXPORT_SYMBOL_GPL(qeth_prepare_control_data);
++
++int qeth_send_control_data(struct qeth_card *card, int len,
++		struct qeth_cmd_buffer *iob,
++		int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
++			unsigned long),
++		void *reply_param)
++{
++	int rc;
++	unsigned long flags;
++	struct qeth_reply *reply = NULL;
++	unsigned long timeout;
++
++	QETH_DBF_TEXT(TRACE, 2, "sendctl");
++
++	reply = qeth_alloc_reply(card);
++	if (!reply) {
++		PRINT_WARN("Could not alloc qeth_reply!\n");
++		return -ENOMEM;
++	}
++	reply->callback = reply_cb;
++	reply->param = reply_param;
++	if (card->state == CARD_STATE_DOWN)
++		reply->seqno = QETH_IDX_COMMAND_SEQNO;
++	else
++		reply->seqno = card->seqno.ipa++;
++	init_waitqueue_head(&reply->wait_q);
++	spin_lock_irqsave(&card->lock, flags);
++	list_add_tail(&reply->list, &card->cmd_waiter_list);
++	spin_unlock_irqrestore(&card->lock, flags);
++	QETH_DBF_HEX(CTRL, 2, iob->data, QETH_DBF_CTRL_LEN);
++
++	while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
++	qeth_prepare_control_data(card, len, iob);
++
++	if (IS_IPA(iob->data))
++		timeout = jiffies + QETH_IPA_TIMEOUT;
++	else
++		timeout = jiffies + QETH_TIMEOUT;
++
++	QETH_DBF_TEXT(TRACE, 6, "noirqpnd");
++	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
++	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
++			      (addr_t) iob, 0, 0);
++	spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
++	if (rc) {
++		PRINT_WARN("qeth_send_control_data: "
++			   "ccw_device_start rc = %i\n", rc);
++		QETH_DBF_TEXT_(TRACE, 2, " err%d", rc);
++		spin_lock_irqsave(&card->lock, flags);
++		list_del_init(&reply->list);
++		qeth_put_reply(reply);
++		spin_unlock_irqrestore(&card->lock, flags);
++		qeth_release_buffer(iob->channel, iob);
++		atomic_set(&card->write.irq_pending, 0);
++		wake_up(&card->wait_q);
++		return rc;
++	}
++	while (!atomic_read(&reply->received)) {
++		if (time_after(jiffies, timeout)) {
++			spin_lock_irqsave(&reply->card->lock, flags);
++			list_del_init(&reply->list);
++			spin_unlock_irqrestore(&reply->card->lock, flags);
++			reply->rc = -ETIME;
++			atomic_inc(&reply->received);
++			wake_up(&reply->wait_q);
++		}
++		cpu_relax();
++	};
++	rc = reply->rc;
++	qeth_put_reply(reply);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_send_control_data);
++
++static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
++		unsigned long data)
++{
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(SETUP, 2, "cmenblcb");
++
++	iob = (struct qeth_cmd_buffer *) data;
++	memcpy(&card->token.cm_filter_r,
++	       QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data),
++	       QETH_MPC_TOKEN_LENGTH);
++	QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
++	return 0;
++}
++
++static int qeth_cm_enable(struct qeth_card *card)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(SETUP, 2, "cmenable");
++
++	iob = qeth_wait_for_buffer(&card->write);
++	memcpy(iob->data, CM_ENABLE, CM_ENABLE_SIZE);
++	memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(iob->data),
++	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
++	memcpy(QETH_CM_ENABLE_FILTER_TOKEN(iob->data),
++	       &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH);
++
++	rc = qeth_send_control_data(card, CM_ENABLE_SIZE, iob,
++				    qeth_cm_enable_cb, NULL);
++	return rc;
++}
++
++static int qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
++		unsigned long data)
++{
++
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(SETUP, 2, "cmsetpcb");
++
++	iob = (struct qeth_cmd_buffer *) data;
++	memcpy(&card->token.cm_connection_r,
++	       QETH_CM_SETUP_RESP_DEST_ADDR(iob->data),
++	       QETH_MPC_TOKEN_LENGTH);
++	QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
++	return 0;
++}
++
++static int qeth_cm_setup(struct qeth_card *card)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(SETUP, 2, "cmsetup");
++
++	iob = qeth_wait_for_buffer(&card->write);
++	memcpy(iob->data, CM_SETUP, CM_SETUP_SIZE);
++	memcpy(QETH_CM_SETUP_DEST_ADDR(iob->data),
++	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
++	memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(iob->data),
++	       &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH);
++	memcpy(QETH_CM_SETUP_FILTER_TOKEN(iob->data),
++	       &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH);
++	rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob,
++				    qeth_cm_setup_cb, NULL);
++	return rc;
++
++}
++
++static inline int qeth_get_initial_mtu_for_card(struct qeth_card *card)
++{
++	switch (card->info.type) {
++	case QETH_CARD_TYPE_UNKNOWN:
++		return 1500;
++	case QETH_CARD_TYPE_IQD:
++		return card->info.max_mtu;
++	case QETH_CARD_TYPE_OSAE:
++		switch (card->info.link_type) {
++		case QETH_LINK_TYPE_HSTR:
++		case QETH_LINK_TYPE_LANE_TR:
++			return 2000;
++		default:
++			return 1492;
++		}
++	default:
++		return 1500;
++	}
++}
++
++static inline int qeth_get_max_mtu_for_card(int cardtype)
++{
++	switch (cardtype) {
++
++	case QETH_CARD_TYPE_UNKNOWN:
++	case QETH_CARD_TYPE_OSAE:
++	case QETH_CARD_TYPE_OSN:
++		return 61440;
++	case QETH_CARD_TYPE_IQD:
++		return 57344;
++	default:
++		return 1500;
++	}
++}
++
++static inline int qeth_get_mtu_out_of_mpc(int cardtype)
++{
++	switch (cardtype) {
++	case QETH_CARD_TYPE_IQD:
++		return 1;
++	default:
++		return 0;
++	}
++}
++
++static inline int qeth_get_mtu_outof_framesize(int framesize)
++{
++	switch (framesize) {
++	case 0x4000:
++		return 8192;
++	case 0x6000:
++		return 16384;
++	case 0xa000:
++		return 32768;
++	case 0xffff:
++		return 57344;
++	default:
++		return 0;
++	}
++}
++
++static inline int qeth_mtu_is_valid(struct qeth_card *card, int mtu)
++{
++	switch (card->info.type) {
++	case QETH_CARD_TYPE_OSAE:
++		return ((mtu >= 576) && (mtu <= 61440));
++	case QETH_CARD_TYPE_IQD:
++		return ((mtu >= 576) &&
++			(mtu <= card->info.max_mtu + 4096 - 32));
++	case QETH_CARD_TYPE_OSN:
++	case QETH_CARD_TYPE_UNKNOWN:
++	default:
++		return 1;
++	}
++}
++
++static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
++		unsigned long data)
++{
++
++	__u16 mtu, framesize;
++	__u16 len;
++	__u8 link_type;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(SETUP, 2, "ulpenacb");
++
++	iob = (struct qeth_cmd_buffer *) data;
++	memcpy(&card->token.ulp_filter_r,
++	       QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data),
++	       QETH_MPC_TOKEN_LENGTH);
++	if (qeth_get_mtu_out_of_mpc(card->info.type)) {
++		memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2);
++		mtu = qeth_get_mtu_outof_framesize(framesize);
++		if (!mtu) {
++			iob->rc = -EINVAL;
++			QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
++			return 0;
++		}
++		card->info.max_mtu = mtu;
++		card->info.initial_mtu = mtu;
++		card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE;
++	} else {
++		card->info.initial_mtu = qeth_get_initial_mtu_for_card(card);
++		card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type);
++		card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
++	}
++
++	memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2);
++	if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
++		memcpy(&link_type,
++		       QETH_ULP_ENABLE_RESP_LINK_TYPE(iob->data), 1);
++		card->info.link_type = link_type;
++	} else
++		card->info.link_type = 0;
++	QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
++	return 0;
++}
++
++static int qeth_ulp_enable(struct qeth_card *card)
++{
++	int rc;
++	char prot_type;
++	struct qeth_cmd_buffer *iob;
++
++	/*FIXME: trace view callbacks*/
++	QETH_DBF_TEXT(SETUP, 2, "ulpenabl");
++
++	iob = qeth_wait_for_buffer(&card->write);
++	memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE);
++
++	*(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
++		(__u8) card->info.portno;
++	if (card->options.layer2)
++		if (card->info.type == QETH_CARD_TYPE_OSN)
++			prot_type = QETH_PROT_OSN2;
++		else
++			prot_type = QETH_PROT_LAYER2;
++	else
++		prot_type = QETH_PROT_TCPIP;
++
++	memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data), &prot_type, 1);
++	memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data),
++	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
++	memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
++	       &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
++	memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data),
++	       card->info.portname, 9);
++	rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
++				    qeth_ulp_enable_cb, NULL);
++	return rc;
++
++}
++
++static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
++		unsigned long data)
++{
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(SETUP, 2, "ulpstpcb");
++
++	iob = (struct qeth_cmd_buffer *) data;
++	memcpy(&card->token.ulp_connection_r,
++	       QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
++	       QETH_MPC_TOKEN_LENGTH);
++	QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
++	return 0;
++}
++
++static int qeth_ulp_setup(struct qeth_card *card)
++{
++	int rc;
++	__u16 temp;
++	struct qeth_cmd_buffer *iob;
++	struct ccw_dev_id dev_id;
++
++	QETH_DBF_TEXT(SETUP, 2, "ulpsetup");
++
++	iob = qeth_wait_for_buffer(&card->write);
++	memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE);
++
++	memcpy(QETH_ULP_SETUP_DEST_ADDR(iob->data),
++	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
++	memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(iob->data),
++	       &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH);
++	memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data),
++	       &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
++
++	ccw_device_get_id(CARD_DDEV(card), &dev_id);
++	memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
++	temp = (card->info.cula << 8) + card->info.unit_addr2;
++	memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
++	rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
++				    qeth_ulp_setup_cb, NULL);
++	return rc;
++}
++
++static int qeth_alloc_qdio_buffers(struct qeth_card *card)
++{
++	int i, j;
++
++	QETH_DBF_TEXT(SETUP, 2, "allcqdbf");
++
++	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
++		QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
++		return 0;
++
++	card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
++				  GFP_KERNEL);
++	if (!card->qdio.in_q)
++		goto out_nomem;
++	QETH_DBF_TEXT(SETUP, 2, "inq");
++	QETH_DBF_HEX(SETUP, 2, &card->qdio.in_q, sizeof(void *));
++	memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
++	/* give inbound qeth_qdio_buffers their qdio_buffers */
++	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
++		card->qdio.in_q->bufs[i].buffer =
++			&card->qdio.in_q->qdio_bufs[i];
++	/* inbound buffer pool */
++	if (qeth_alloc_buffer_pool(card))
++		goto out_freeinq;
++	/* outbound */
++	card->qdio.out_qs =
++		kmalloc(card->qdio.no_out_queues *
++			sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
++	if (!card->qdio.out_qs)
++		goto out_freepool;
++	for (i = 0; i < card->qdio.no_out_queues; ++i) {
++		card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
++					       GFP_KERNEL);
++		if (!card->qdio.out_qs[i])
++			goto out_freeoutq;
++		QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
++		QETH_DBF_HEX(SETUP, 2, &card->qdio.out_qs[i], sizeof(void *));
++		memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
++		card->qdio.out_qs[i]->queue_no = i;
++		/* give outbound qeth_qdio_buffers their qdio_buffers */
++		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
++			card->qdio.out_qs[i]->bufs[j].buffer =
++				&card->qdio.out_qs[i]->qdio_bufs[j];
++			skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
++					    skb_list);
++			lockdep_set_class(
++				&card->qdio.out_qs[i]->bufs[j].skb_list.lock,
++				&qdio_out_skb_queue_key);
++			INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
++		}
++	}
++	return 0;
++
++out_freeoutq:
++	while (i > 0)
++		kfree(card->qdio.out_qs[--i]);
++	kfree(card->qdio.out_qs);
++	card->qdio.out_qs = NULL;
++out_freepool:
++	qeth_free_buffer_pool(card);
++out_freeinq:
++	kfree(card->qdio.in_q);
++	card->qdio.in_q = NULL;
++out_nomem:
++	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
++	return -ENOMEM;
++}
++
++static void qeth_create_qib_param_field(struct qeth_card *card,
++		char *param_field)
++{
++
++	param_field[0] = _ascebc['P'];
++	param_field[1] = _ascebc['C'];
++	param_field[2] = _ascebc['I'];
++	param_field[3] = _ascebc['T'];
++	*((unsigned int *) (&param_field[4])) = QETH_PCI_THRESHOLD_A(card);
++	*((unsigned int *) (&param_field[8])) = QETH_PCI_THRESHOLD_B(card);
++	*((unsigned int *) (&param_field[12])) = QETH_PCI_TIMER_VALUE(card);
++}
++
++static void qeth_create_qib_param_field_blkt(struct qeth_card *card,
++		char *param_field)
++{
++	param_field[16] = _ascebc['B'];
++	param_field[17] = _ascebc['L'];
++	param_field[18] = _ascebc['K'];
++	param_field[19] = _ascebc['T'];
++	*((unsigned int *) (&param_field[20])) = card->info.blkt.time_total;
++	*((unsigned int *) (&param_field[24])) = card->info.blkt.inter_packet;
++	*((unsigned int *) (&param_field[28])) =
++		card->info.blkt.inter_packet_jumbo;
++}
++
++static int qeth_qdio_activate(struct qeth_card *card)
++{
++	QETH_DBF_TEXT(SETUP, 3, "qdioact");
++	return qdio_activate(CARD_DDEV(card), 0);
++}
++
++static int qeth_dm_act(struct qeth_card *card)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(SETUP, 2, "dmact");
++
++	iob = qeth_wait_for_buffer(&card->write);
++	memcpy(iob->data, DM_ACT, DM_ACT_SIZE);
++
++	memcpy(QETH_DM_ACT_DEST_ADDR(iob->data),
++	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
++	memcpy(QETH_DM_ACT_CONNECTION_TOKEN(iob->data),
++	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
++	rc = qeth_send_control_data(card, DM_ACT_SIZE, iob, NULL, NULL);
++	return rc;
++}
++
++static int qeth_mpc_initialize(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(SETUP, 2, "mpcinit");
++
++	rc = qeth_issue_next_read(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		return rc;
++	}
++	rc = qeth_cm_enable(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++		goto out_qdio;
++	}
++	rc = qeth_cm_setup(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++		goto out_qdio;
++	}
++	rc = qeth_ulp_enable(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc);
++		goto out_qdio;
++	}
++	rc = qeth_ulp_setup(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
++		goto out_qdio;
++	}
++	rc = qeth_alloc_qdio_buffers(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
++		goto out_qdio;
++	}
++	rc = qeth_qdio_establish(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
++		qeth_free_qdio_buffers(card);
++		goto out_qdio;
++	}
++	rc = qeth_qdio_activate(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "7err%d", rc);
++		goto out_qdio;
++	}
++	rc = qeth_dm_act(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "8err%d", rc);
++		goto out_qdio;
++	}
++
++	return 0;
++out_qdio:
++	qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
++	return rc;
++}
++
++static void qeth_print_status_with_portname(struct qeth_card *card)
++{
++	char dbf_text[15];
++	int i;
++
++	sprintf(dbf_text, "%s", card->info.portname + 1);
++	for (i = 0; i < 8; i++)
++		dbf_text[i] =
++			(char) _ebcasc[(__u8) dbf_text[i]];
++	dbf_text[8] = 0;
++	PRINT_INFO("Device %s/%s/%s is a%s card%s%s%s\n"
++	       "with link type %s (portname: %s)\n",
++	       CARD_RDEV_ID(card),
++	       CARD_WDEV_ID(card),
++	       CARD_DDEV_ID(card),
++	       qeth_get_cardname(card),
++	       (card->info.mcl_level[0]) ? " (level: " : "",
++	       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
++	       (card->info.mcl_level[0]) ? ")" : "",
++	       qeth_get_cardname_short(card),
++	       dbf_text);
++
++}
++
++static void qeth_print_status_no_portname(struct qeth_card *card)
++{
++	if (card->info.portname[0])
++		PRINT_INFO("Device %s/%s/%s is a%s "
++		       "card%s%s%s\nwith link type %s "
++		       "(no portname needed by interface).\n",
++		       CARD_RDEV_ID(card),
++		       CARD_WDEV_ID(card),
++		       CARD_DDEV_ID(card),
++		       qeth_get_cardname(card),
++		       (card->info.mcl_level[0]) ? " (level: " : "",
++		       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
++		       (card->info.mcl_level[0]) ? ")" : "",
++		       qeth_get_cardname_short(card));
++	else
++		PRINT_INFO("Device %s/%s/%s is a%s "
++		       "card%s%s%s\nwith link type %s.\n",
++		       CARD_RDEV_ID(card),
++		       CARD_WDEV_ID(card),
++		       CARD_DDEV_ID(card),
++		       qeth_get_cardname(card),
++		       (card->info.mcl_level[0]) ? " (level: " : "",
++		       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
++		       (card->info.mcl_level[0]) ? ")" : "",
++		       qeth_get_cardname_short(card));
++}
++
++void qeth_print_status_message(struct qeth_card *card)
++{
++	switch (card->info.type) {
++	case QETH_CARD_TYPE_OSAE:
++		/* VM will use a non-zero first character
++		 * to indicate a HiperSockets like reporting
++		 * of the level OSA sets the first character to zero
++		 * */
++		if (!card->info.mcl_level[0]) {
++			sprintf(card->info.mcl_level, "%02x%02x",
++				card->info.mcl_level[2],
++				card->info.mcl_level[3]);
++
++			card->info.mcl_level[QETH_MCL_LENGTH] = 0;
++			break;
++		}
++		/* fallthrough */
++	case QETH_CARD_TYPE_IQD:
++		if (card->info.guestlan) {
++			card->info.mcl_level[0] = (char) _ebcasc[(__u8)
++				card->info.mcl_level[0]];
++			card->info.mcl_level[1] = (char) _ebcasc[(__u8)
++				card->info.mcl_level[1]];
++			card->info.mcl_level[2] = (char) _ebcasc[(__u8)
++				card->info.mcl_level[2]];
++			card->info.mcl_level[3] = (char) _ebcasc[(__u8)
++				card->info.mcl_level[3]];
++			card->info.mcl_level[QETH_MCL_LENGTH] = 0;
++		}
++		break;
++	default:
++		memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
++	}
++	if (card->info.portname_required)
++		qeth_print_status_with_portname(card);
++	else
++		qeth_print_status_no_portname(card);
++}
++EXPORT_SYMBOL_GPL(qeth_print_status_message);
++
++void qeth_put_buffer_pool_entry(struct qeth_card *card,
++		struct qeth_buffer_pool_entry *entry)
++{
++	QETH_DBF_TEXT(TRACE, 6, "ptbfplen");
++	list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
++}
++EXPORT_SYMBOL_GPL(qeth_put_buffer_pool_entry);
++
++static void qeth_initialize_working_pool_list(struct qeth_card *card)
++{
++	struct qeth_buffer_pool_entry *entry;
++
++	QETH_DBF_TEXT(TRACE, 5, "inwrklst");
++
++	list_for_each_entry(entry,
++			    &card->qdio.init_pool.entry_list, init_list) {
++		qeth_put_buffer_pool_entry(card, entry);
++	}
++}
++
++static inline struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry(
++		struct qeth_card *card)
++{
++	struct list_head *plh;
++	struct qeth_buffer_pool_entry *entry;
++	int i, free;
++	struct page *page;
++
++	if (list_empty(&card->qdio.in_buf_pool.entry_list))
++		return NULL;
++
++	list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
++		entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
++		free = 1;
++		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
++			if (page_count(virt_to_page(entry->elements[i])) > 1) {
++				free = 0;
++				break;
++			}
++		}
++		if (free) {
++			list_del_init(&entry->list);
++			return entry;
++		}
++	}
++
++	/* no free buffer in pool so take first one and swap pages */
++	entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
++			struct qeth_buffer_pool_entry, list);
++	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
++		if (page_count(virt_to_page(entry->elements[i])) > 1) {
++			page = alloc_page(GFP_ATOMIC);
++			if (!page) {
++				return NULL;
++			} else {
++				free_page((unsigned long)entry->elements[i]);
++				entry->elements[i] = page_address(page);
++				if (card->options.performance_stats)
++					card->perf_stats.sg_alloc_page_rx++;
++			}
++		}
++	}
++	list_del_init(&entry->list);
++	return entry;
++}
++
++static int qeth_init_input_buffer(struct qeth_card *card,
++		struct qeth_qdio_buffer *buf)
++{
++	struct qeth_buffer_pool_entry *pool_entry;
++	int i;
++
++	pool_entry = qeth_find_free_buffer_pool_entry(card);
++	if (!pool_entry)
++		return 1;
++
++	/*
++	 * since the buffer is accessed only from the input_tasklet
++	 * there shouldn't be a need to synchronize; also, since we use
++	 * the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run  out off
++	 * buffers
++	 */
++	BUG_ON(!pool_entry);
++
++	buf->pool_entry = pool_entry;
++	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
++		buf->buffer->element[i].length = PAGE_SIZE;
++		buf->buffer->element[i].addr =  pool_entry->elements[i];
++		if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
++			buf->buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY;
++		else
++			buf->buffer->element[i].flags = 0;
++	}
++	return 0;
++}
++
++int qeth_init_qdio_queues(struct qeth_card *card)
++{
++	int i, j;
++	int rc;
++
++	QETH_DBF_TEXT(SETUP, 2, "initqdqs");
++
++	/* inbound queue */
++	memset(card->qdio.in_q->qdio_bufs, 0,
++	       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
++	qeth_initialize_working_pool_list(card);
++	/*give only as many buffers to hardware as we have buffer pool entries*/
++	for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
++		qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
++	card->qdio.in_q->next_buf_to_init =
++		card->qdio.in_buf_pool.buf_count - 1;
++	rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
++		     card->qdio.in_buf_pool.buf_count - 1, NULL);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		return rc;
++	}
++	rc = qdio_synchronize(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++		return rc;
++	}
++	/* outbound queue */
++	for (i = 0; i < card->qdio.no_out_queues; ++i) {
++		memset(card->qdio.out_qs[i]->qdio_bufs, 0,
++		       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
++		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
++			qeth_clear_output_buffer(card->qdio.out_qs[i],
++					&card->qdio.out_qs[i]->bufs[j]);
++		}
++		card->qdio.out_qs[i]->card = card;
++		card->qdio.out_qs[i]->next_buf_to_fill = 0;
++		card->qdio.out_qs[i]->do_pack = 0;
++		atomic_set(&card->qdio.out_qs[i]->used_buffers, 0);
++		atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0);
++		atomic_set(&card->qdio.out_qs[i]->state,
++			   QETH_OUT_Q_UNLOCKED);
++	}
++	return 0;
++}
++EXPORT_SYMBOL_GPL(qeth_init_qdio_queues);
++
++static inline __u8 qeth_get_ipa_adp_type(enum qeth_link_types link_type)
++{
++	switch (link_type) {
++	case QETH_LINK_TYPE_HSTR:
++		return 2;
++	default:
++		return 1;
++	}
++}
++
++static void qeth_fill_ipacmd_header(struct qeth_card *card,
++		struct qeth_ipa_cmd *cmd, __u8 command,
++		enum qeth_prot_versions prot)
++{
++	memset(cmd, 0, sizeof(struct qeth_ipa_cmd));
++	cmd->hdr.command = command;
++	cmd->hdr.initiator = IPA_CMD_INITIATOR_HOST;
++	cmd->hdr.seqno = card->seqno.ipa;
++	cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type);
++	cmd->hdr.rel_adapter_no = (__u8) card->info.portno;
++	if (card->options.layer2)
++		cmd->hdr.prim_version_no = 2;
++	else
++		cmd->hdr.prim_version_no = 1;
++	cmd->hdr.param_count = 1;
++	cmd->hdr.prot_version = prot;
++	cmd->hdr.ipa_supported = 0;
++	cmd->hdr.ipa_enabled = 0;
++}
++
++struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
++		enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
++{
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	iob = qeth_wait_for_buffer(&card->write);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	qeth_fill_ipacmd_header(card, cmd, ipacmd, prot);
++
++	return iob;
++}
++EXPORT_SYMBOL_GPL(qeth_get_ipacmd_buffer);
++
++void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
++		char prot_type)
++{
++	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
++	memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data), &prot_type, 1);
++	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
++	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
++}
++EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd);
++
++int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
++		int (*reply_cb)(struct qeth_card *, struct qeth_reply*,
++			unsigned long),
++		void *reply_param)
++{
++	int rc;
++	char prot_type;
++
++	QETH_DBF_TEXT(TRACE, 4, "sendipa");
++
++	if (card->options.layer2)
++		if (card->info.type == QETH_CARD_TYPE_OSN)
++			prot_type = QETH_PROT_OSN2;
++		else
++			prot_type = QETH_PROT_LAYER2;
++	else
++		prot_type = QETH_PROT_TCPIP;
++	qeth_prepare_ipa_cmd(card, iob, prot_type);
++	rc = qeth_send_control_data(card, IPA_CMD_LENGTH,
++						iob, reply_cb, reply_param);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd);
++
++static int qeth_send_startstoplan(struct qeth_card *card,
++		enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++
++	iob = qeth_get_ipacmd_buffer(card, ipacmd, prot);
++	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++
++	return rc;
++}
++
++int qeth_send_startlan(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(SETUP, 2, "strtlan");
++
++	rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, 0);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_send_startlan);
++
++int qeth_send_stoplan(struct qeth_card *card)
++{
++	int rc = 0;
++
++	/*
++	 * TODO: according to the IPA format document page 14,
++	 * TCP/IP (we!) never issue a STOPLAN
++	 * is this right ?!?
++	 */
++	QETH_DBF_TEXT(SETUP, 2, "stoplan");
++
++	rc = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, 0);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_send_stoplan);
++
++int qeth_default_setadapterparms_cb(struct qeth_card *card,
++		struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 4, "defadpcb");
++
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->hdr.return_code == 0)
++		cmd->hdr.return_code =
++			cmd->data.setadapterparms.hdr.return_code;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(qeth_default_setadapterparms_cb);
++
++static int qeth_query_setadapterparms_cb(struct qeth_card *card,
++		struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 3, "quyadpcb");
++
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f)
++		card->info.link_type =
++		      cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
++	card->options.adp.supported_funcs =
++		cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
++	return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
++}
++
++struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
++		__u32 command, __u32 cmdlen)
++{
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETADAPTERPARMS,
++				     QETH_PROT_IPV4);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
++	cmd->data.setadapterparms.hdr.command_code = command;
++	cmd->data.setadapterparms.hdr.used_total = 1;
++	cmd->data.setadapterparms.hdr.seq_no = 1;
++
++	return iob;
++}
++EXPORT_SYMBOL_GPL(qeth_get_adapter_cmd);
++
++int qeth_query_setadapterparms(struct qeth_card *card)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(TRACE, 3, "queryadp");
++	iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_COMMANDS_SUPPORTED,
++				   sizeof(struct qeth_ipacmd_setadpparms));
++	rc = qeth_send_ipa_cmd(card, iob, qeth_query_setadapterparms_cb, NULL);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_query_setadapterparms);
++
++int qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
++		unsigned int siga_error, const char *dbftext)
++{
++	if (qdio_error || siga_error) {
++		QETH_DBF_TEXT(TRACE, 2, dbftext);
++		QETH_DBF_TEXT(QERR, 2, dbftext);
++		QETH_DBF_TEXT_(QERR, 2, " F15=%02X",
++			       buf->element[15].flags & 0xff);
++		QETH_DBF_TEXT_(QERR, 2, " F14=%02X",
++			       buf->element[14].flags & 0xff);
++		QETH_DBF_TEXT_(QERR, 2, " qerr=%X", qdio_error);
++		QETH_DBF_TEXT_(QERR, 2, " serr=%X", siga_error);
++		return 1;
++	}
++	return 0;
++}
++EXPORT_SYMBOL_GPL(qeth_check_qdio_errors);
++
++void qeth_queue_input_buffer(struct qeth_card *card, int index)
++{
++	struct qeth_qdio_q *queue = card->qdio.in_q;
++	int count;
++	int i;
++	int rc;
++	int newcount = 0;
++
++	QETH_DBF_TEXT(TRACE, 6, "queinbuf");
++	count = (index < queue->next_buf_to_init)?
++		card->qdio.in_buf_pool.buf_count -
++		(queue->next_buf_to_init - index) :
++		card->qdio.in_buf_pool.buf_count -
++		(queue->next_buf_to_init + QDIO_MAX_BUFFERS_PER_Q - index);
++	/* only requeue at a certain threshold to avoid SIGAs */
++	if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)) {
++		for (i = queue->next_buf_to_init;
++		     i < queue->next_buf_to_init + count; ++i) {
++			if (qeth_init_input_buffer(card,
++				&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
++				break;
++			} else {
++				newcount++;
++			}
++		}
++
++		if (newcount < count) {
++			/* we are in memory shortage so we switch back to
++			   traditional skb allocation and drop packages */
++			if (!atomic_read(&card->force_alloc_skb) &&
++			    net_ratelimit())
++				PRINT_WARN("Switch to alloc skb\n");
++			atomic_set(&card->force_alloc_skb, 3);
++			count = newcount;
++		} else {
++			if ((atomic_read(&card->force_alloc_skb) == 1) &&
++			    net_ratelimit())
++				PRINT_WARN("Switch to sg\n");
++			atomic_add_unless(&card->force_alloc_skb, -1, 0);
++		}
++
++		/*
++		 * according to old code it should be avoided to requeue all
++		 * 128 buffers in order to benefit from PCI avoidance.
++		 * this function keeps at least one buffer (the buffer at
++		 * 'index') un-requeued -> this buffer is the first buffer that
++		 * will be requeued the next time
++		 */
++		if (card->options.performance_stats) {
++			card->perf_stats.inbound_do_qdio_cnt++;
++			card->perf_stats.inbound_do_qdio_start_time =
++				qeth_get_micros();
++		}
++		rc = do_QDIO(CARD_DDEV(card),
++			     QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
++			     0, queue->next_buf_to_init, count, NULL);
++		if (card->options.performance_stats)
++			card->perf_stats.inbound_do_qdio_time +=
++				qeth_get_micros() -
++				card->perf_stats.inbound_do_qdio_start_time;
++		if (rc) {
++			PRINT_WARN("qeth_queue_input_buffer's do_QDIO "
++				   "return %i (device %s).\n",
++				   rc, CARD_DDEV_ID(card));
++			QETH_DBF_TEXT(TRACE, 2, "qinberr");
++			QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card));
++		}
++		queue->next_buf_to_init = (queue->next_buf_to_init + count) %
++					  QDIO_MAX_BUFFERS_PER_Q;
++	}
++}
++EXPORT_SYMBOL_GPL(qeth_queue_input_buffer);
++
++static int qeth_handle_send_error(struct qeth_card *card,
++		struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err,
++		unsigned int siga_err)
++{
++	int sbalf15 = buffer->buffer->element[15].flags & 0xff;
++	int cc = siga_err & 3;
++
++	QETH_DBF_TEXT(TRACE, 6, "hdsnderr");
++	qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr");
++	switch (cc) {
++	case 0:
++		if (qdio_err) {
++			QETH_DBF_TEXT(TRACE, 1, "lnkfail");
++			QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++			QETH_DBF_TEXT_(TRACE, 1, "%04x %02x",
++				       (u16)qdio_err, (u8)sbalf15);
++			return QETH_SEND_ERROR_LINK_FAILURE;
++		}
++		return QETH_SEND_ERROR_NONE;
++	case 2:
++		if (siga_err & QDIO_SIGA_ERROR_B_BIT_SET) {
++			QETH_DBF_TEXT(TRACE, 1, "SIGAcc2B");
++			QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++			return QETH_SEND_ERROR_KICK_IT;
++		}
++		if ((sbalf15 >= 15) && (sbalf15 <= 31))
++			return QETH_SEND_ERROR_RETRY;
++		return QETH_SEND_ERROR_LINK_FAILURE;
++		/* look at qdio_error and sbalf 15 */
++	case 1:
++		QETH_DBF_TEXT(TRACE, 1, "SIGAcc1");
++		QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++		return QETH_SEND_ERROR_LINK_FAILURE;
++	case 3:
++	default:
++		QETH_DBF_TEXT(TRACE, 1, "SIGAcc3");
++		QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++		return QETH_SEND_ERROR_KICK_IT;
++	}
++}
++
++/*
++ * Switched to packing state if the number of used buffers on a queue
++ * reaches a certain limit.
++ */
++static void qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
++{
++	if (!queue->do_pack) {
++		if (atomic_read(&queue->used_buffers)
++		    >= QETH_HIGH_WATERMARK_PACK){
++			/* switch non-PACKING -> PACKING */
++			QETH_DBF_TEXT(TRACE, 6, "np->pack");
++			if (queue->card->options.performance_stats)
++				queue->card->perf_stats.sc_dp_p++;
++			queue->do_pack = 1;
++		}
++	}
++}
++
++/*
++ * Switches from packing to non-packing mode. If there is a packing
++ * buffer on the queue this buffer will be prepared to be flushed.
++ * In that case 1 is returned to inform the caller. If no buffer
++ * has to be flushed, zero is returned.
++ */
++static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
++{
++	struct qeth_qdio_out_buffer *buffer;
++	int flush_count = 0;
++
++	if (queue->do_pack) {
++		if (atomic_read(&queue->used_buffers)
++		    <= QETH_LOW_WATERMARK_PACK) {
++			/* switch PACKING -> non-PACKING */
++			QETH_DBF_TEXT(TRACE, 6, "pack->np");
++			if (queue->card->options.performance_stats)
++				queue->card->perf_stats.sc_p_dp++;
++			queue->do_pack = 0;
++			/* flush packing buffers */
++			buffer = &queue->bufs[queue->next_buf_to_fill];
++			if ((atomic_read(&buffer->state) ==
++						QETH_QDIO_BUF_EMPTY) &&
++			    (buffer->next_element_to_fill > 0)) {
++				atomic_set(&buffer->state,
++						QETH_QDIO_BUF_PRIMED);
++				flush_count++;
++				queue->next_buf_to_fill =
++					(queue->next_buf_to_fill + 1) %
++					QDIO_MAX_BUFFERS_PER_Q;
++			}
++		}
++	}
++	return flush_count;
++}
++
++/*
++ * Called to flush a packing buffer if no more pci flags are on the queue.
++ * Checks if there is a packing buffer and prepares it to be flushed.
++ * In that case returns 1, otherwise zero.
++ */
++static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
++{
++	struct qeth_qdio_out_buffer *buffer;
++
++	buffer = &queue->bufs[queue->next_buf_to_fill];
++	if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
++	   (buffer->next_element_to_fill > 0)) {
++		/* it's a packing buffer */
++		atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
++		queue->next_buf_to_fill =
++			(queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
++		return 1;
++	}
++	return 0;
++}
++
++static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
++		int index, int count)
++{
++	struct qeth_qdio_out_buffer *buf;
++	int rc;
++	int i;
++	unsigned int qdio_flags;
++
++	QETH_DBF_TEXT(TRACE, 6, "flushbuf");
++
++	for (i = index; i < index + count; ++i) {
++		buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
++		buf->buffer->element[buf->next_element_to_fill - 1].flags |=
++				SBAL_FLAGS_LAST_ENTRY;
++
++		if (queue->card->info.type == QETH_CARD_TYPE_IQD)
++			continue;
++
++		if (!queue->do_pack) {
++			if ((atomic_read(&queue->used_buffers) >=
++				(QETH_HIGH_WATERMARK_PACK -
++				 QETH_WATERMARK_PACK_FUZZ)) &&
++			    !atomic_read(&queue->set_pci_flags_count)) {
++				/* it's likely that we'll go to packing
++				 * mode soon */
++				atomic_inc(&queue->set_pci_flags_count);
++				buf->buffer->element[0].flags |= 0x40;
++			}
++		} else {
++			if (!atomic_read(&queue->set_pci_flags_count)) {
++				/*
++				 * there's no outstanding PCI any more, so we
++				 * have to request a PCI to be sure the the PCI
++				 * will wake at some time in the future then we
++				 * can flush packed buffers that might still be
++				 * hanging around, which can happen if no
++				 * further send was requested by the stack
++				 */
++				atomic_inc(&queue->set_pci_flags_count);
++				buf->buffer->element[0].flags |= 0x40;
++			}
++		}
++	}
++
++	queue->card->dev->trans_start = jiffies;
++	if (queue->card->options.performance_stats) {
++		queue->card->perf_stats.outbound_do_qdio_cnt++;
++		queue->card->perf_stats.outbound_do_qdio_start_time =
++			qeth_get_micros();
++	}
++	qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
++	if (under_int)
++		qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
++	if (atomic_read(&queue->set_pci_flags_count))
++		qdio_flags |= QDIO_FLAG_PCI_OUT;
++	rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
++		     queue->queue_no, index, count, NULL);
++	if (queue->card->options.performance_stats)
++		queue->card->perf_stats.outbound_do_qdio_time +=
++			qeth_get_micros() -
++			queue->card->perf_stats.outbound_do_qdio_start_time;
++	if (rc) {
++		QETH_DBF_TEXT(TRACE, 2, "flushbuf");
++		QETH_DBF_TEXT_(TRACE, 2, " err%d", rc);
++		QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_DDEV_ID(queue->card));
++		queue->card->stats.tx_errors += count;
++		/* this must not happen under normal circumstances. if it
++		 * happens something is really wrong -> recover */
++		qeth_schedule_recovery(queue->card);
++		return;
++	}
++	atomic_add(count, &queue->used_buffers);
++	if (queue->card->options.performance_stats)
++		queue->card->perf_stats.bufs_sent += count;
++}
++
++static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
++{
++	int index;
++	int flush_cnt = 0;
++	int q_was_packing = 0;
++
++	/*
++	 * check if weed have to switch to non-packing mode or if
++	 * we have to get a pci flag out on the queue
++	 */
++	if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) ||
++	    !atomic_read(&queue->set_pci_flags_count)) {
++		if (atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) ==
++				QETH_OUT_Q_UNLOCKED) {
++			/*
++			 * If we get in here, there was no action in
++			 * do_send_packet. So, we check if there is a
++			 * packing buffer to be flushed here.
++			 */
++			netif_stop_queue(queue->card->dev);
++			index = queue->next_buf_to_fill;
++			q_was_packing = queue->do_pack;
++			/* queue->do_pack may change */
++			barrier();
++			flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
++			if (!flush_cnt &&
++			    !atomic_read(&queue->set_pci_flags_count))
++				flush_cnt +=
++					qeth_flush_buffers_on_no_pci(queue);
++			if (queue->card->options.performance_stats &&
++			    q_was_packing)
++				queue->card->perf_stats.bufs_sent_pack +=
++					flush_cnt;
++			if (flush_cnt)
++				qeth_flush_buffers(queue, 1, index, flush_cnt);
++			atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
++		}
++	}
++}
++
++void qeth_qdio_output_handler(struct ccw_device *ccwdev, unsigned int status,
++		unsigned int qdio_error, unsigned int siga_error,
++		unsigned int __queue, int first_element, int count,
++		unsigned long card_ptr)
++{
++	struct qeth_card *card        = (struct qeth_card *) card_ptr;
++	struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
++	struct qeth_qdio_out_buffer *buffer;
++	int i;
++
++	QETH_DBF_TEXT(TRACE, 6, "qdouhdl");
++	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
++		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
++			QETH_DBF_TEXT(TRACE, 2, "achkcond");
++			QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card));
++			QETH_DBF_TEXT_(TRACE, 2, "%08x", status);
++			netif_stop_queue(card->dev);
++			qeth_schedule_recovery(card);
++			return;
++		}
++	}
++	if (card->options.performance_stats) {
++		card->perf_stats.outbound_handler_cnt++;
++		card->perf_stats.outbound_handler_start_time =
++			qeth_get_micros();
++	}
++	for (i = first_element; i < (first_element + count); ++i) {
++		buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
++		/*we only handle the KICK_IT error by doing a recovery */
++		if (qeth_handle_send_error(card, buffer,
++					   qdio_error, siga_error)
++				== QETH_SEND_ERROR_KICK_IT){
++			netif_stop_queue(card->dev);
++			qeth_schedule_recovery(card);
++			return;
++		}
++		qeth_clear_output_buffer(queue, buffer);
++	}
++	atomic_sub(count, &queue->used_buffers);
++	/* check if we need to do something on this outbound queue */
++	if (card->info.type != QETH_CARD_TYPE_IQD)
++		qeth_check_outbound_queue(queue);
++
++	netif_wake_queue(queue->card->dev);
++	if (card->options.performance_stats)
++		card->perf_stats.outbound_handler_time += qeth_get_micros() -
++			card->perf_stats.outbound_handler_start_time;
++}
++EXPORT_SYMBOL_GPL(qeth_qdio_output_handler);
++
++int qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
++{
++	int cast_type = RTN_UNSPEC;
++
++	if (card->info.type == QETH_CARD_TYPE_OSN)
++		return cast_type;
++
++	if (skb->dst && skb->dst->neighbour) {
++		cast_type = skb->dst->neighbour->type;
++		if ((cast_type == RTN_BROADCAST) ||
++		    (cast_type == RTN_MULTICAST) ||
++		    (cast_type == RTN_ANYCAST))
++			return cast_type;
++		else
++			return RTN_UNSPEC;
++	}
++	/* try something else */
++	if (skb->protocol == ETH_P_IPV6)
++		return (skb_network_header(skb)[24] == 0xff) ?
++				RTN_MULTICAST : 0;
++	else if (skb->protocol == ETH_P_IP)
++		return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
++				RTN_MULTICAST : 0;
++	/* ... */
++	if (!memcmp(skb->data, skb->dev->broadcast, 6))
++		return RTN_BROADCAST;
++	else {
++		u16 hdr_mac;
++
++		hdr_mac = *((u16 *)skb->data);
++		/* tr multicast? */
++		switch (card->info.link_type) {
++		case QETH_LINK_TYPE_HSTR:
++		case QETH_LINK_TYPE_LANE_TR:
++			if ((hdr_mac == QETH_TR_MAC_NC) ||
++			    (hdr_mac == QETH_TR_MAC_C))
++				return RTN_MULTICAST;
++			break;
++		/* eth or so multicast? */
++		default:
++		if ((hdr_mac == QETH_ETH_MAC_V4) ||
++			    (hdr_mac == QETH_ETH_MAC_V6))
++				return RTN_MULTICAST;
++		}
++	}
++	return cast_type;
++}
++EXPORT_SYMBOL_GPL(qeth_get_cast_type);
++
++int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
++			int ipv, int cast_type)
++{
++	if (!ipv && (card->info.type == QETH_CARD_TYPE_OSAE))
++		return card->qdio.default_out_queue;
++	switch (card->qdio.no_out_queues) {
++	case 4:
++		if (cast_type && card->info.is_multicast_different)
++			return card->info.is_multicast_different &
++				(card->qdio.no_out_queues - 1);
++		if (card->qdio.do_prio_queueing && (ipv == 4)) {
++			const u8 tos = ip_hdr(skb)->tos;
++
++			if (card->qdio.do_prio_queueing ==
++				QETH_PRIO_Q_ING_TOS) {
++				if (tos & IP_TOS_NOTIMPORTANT)
++					return 3;
++				if (tos & IP_TOS_HIGHRELIABILITY)
++					return 2;
++				if (tos & IP_TOS_HIGHTHROUGHPUT)
++					return 1;
++				if (tos & IP_TOS_LOWDELAY)
++					return 0;
++			}
++			if (card->qdio.do_prio_queueing ==
++				QETH_PRIO_Q_ING_PREC)
++				return 3 - (tos >> 6);
++		} else if (card->qdio.do_prio_queueing && (ipv == 6)) {
++			/* TODO: IPv6!!! */
++		}
++		return card->qdio.default_out_queue;
++	case 1: /* fallthrough for single-out-queue 1920-device */
++	default:
++		return card->qdio.default_out_queue;
++	}
++}
++EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
++
++static void __qeth_free_new_skb(struct sk_buff *orig_skb,
++		struct sk_buff *new_skb)
++{
++	if (orig_skb != new_skb)
++		dev_kfree_skb_any(new_skb);
++}
++
++static inline struct sk_buff *qeth_realloc_headroom(struct qeth_card *card,
++		struct sk_buff *skb, int size)
++{
++	struct sk_buff *new_skb = skb;
++
++	if (skb_headroom(skb) >= size)
++		return skb;
++	new_skb = skb_realloc_headroom(skb, size);
++	if (!new_skb)
++		PRINT_ERR("Could not realloc headroom for qeth_hdr "
++			  "on interface %s", QETH_CARD_IFNAME(card));
++	return new_skb;
++}
++
++struct sk_buff *qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
++		 struct qeth_hdr **hdr)
++{
++	struct sk_buff *new_skb;
++
++	QETH_DBF_TEXT(TRACE, 6, "prepskb");
++
++	new_skb = qeth_realloc_headroom(card, skb,
++			sizeof(struct qeth_hdr));
++	if (!new_skb)
++		return NULL;
++
++	*hdr = ((struct qeth_hdr *)qeth_push_skb(card, new_skb,
++			sizeof(struct qeth_hdr)));
++	if (*hdr == NULL) {
++		__qeth_free_new_skb(skb, new_skb);
++		return NULL;
++	}
++	return new_skb;
++}
++EXPORT_SYMBOL_GPL(qeth_prepare_skb);
++
++int qeth_get_elements_no(struct qeth_card *card, void *hdr,
++		     struct sk_buff *skb, int elems)
++{
++	int elements_needed = 0;
++
++	if (skb_shinfo(skb)->nr_frags > 0)
++		elements_needed = (skb_shinfo(skb)->nr_frags + 1);
++	if (elements_needed == 0)
++		elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
++			+ skb->len) >> PAGE_SHIFT);
++	if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
++		PRINT_ERR("Invalid size of IP packet "
++			"(Number=%d / Length=%d). Discarded.\n",
++			(elements_needed+elems), skb->len);
++		return 0;
++	}
++	return elements_needed;
++}
++EXPORT_SYMBOL_GPL(qeth_get_elements_no);
++
++static void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
++		int is_tso, int *next_element_to_fill)
++{
++	int length = skb->len;
++	int length_here;
++	int element;
++	char *data;
++	int first_lap ;
++
++	element = *next_element_to_fill;
++	data = skb->data;
++	first_lap = (is_tso == 0 ? 1 : 0);
++
++	while (length > 0) {
++		/* length_here is the remaining amount of data in this page */
++		length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
++		if (length < length_here)
++			length_here = length;
++
++		buffer->element[element].addr = data;
++		buffer->element[element].length = length_here;
++		length -= length_here;
++		if (!length) {
++			if (first_lap)
++				buffer->element[element].flags = 0;
++			else
++				buffer->element[element].flags =
++				    SBAL_FLAGS_LAST_FRAG;
++		} else {
++			if (first_lap)
++				buffer->element[element].flags =
++				    SBAL_FLAGS_FIRST_FRAG;
++			else
++				buffer->element[element].flags =
++				    SBAL_FLAGS_MIDDLE_FRAG;
++		}
++		data += length_here;
++		element++;
++		first_lap = 0;
++	}
++	*next_element_to_fill = element;
++}
++
++static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
++		struct qeth_qdio_out_buffer *buf, struct sk_buff *skb)
++{
++	struct qdio_buffer *buffer;
++	struct qeth_hdr_tso *hdr;
++	int flush_cnt = 0, hdr_len, large_send = 0;
++
++	QETH_DBF_TEXT(TRACE, 6, "qdfillbf");
++
++	buffer = buf->buffer;
++	atomic_inc(&skb->users);
++	skb_queue_tail(&buf->skb_list, skb);
++
++	hdr  = (struct qeth_hdr_tso *) skb->data;
++	/*check first on TSO ....*/
++	if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
++		int element = buf->next_element_to_fill;
++
++		hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
++		/*fill first buffer entry only with header information */
++		buffer->element[element].addr = skb->data;
++		buffer->element[element].length = hdr_len;
++		buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
++		buf->next_element_to_fill++;
++		skb->data += hdr_len;
++		skb->len  -= hdr_len;
++		large_send = 1;
++	}
++	if (skb_shinfo(skb)->nr_frags == 0)
++		__qeth_fill_buffer(skb, buffer, large_send,
++				   (int *)&buf->next_element_to_fill);
++	else
++		__qeth_fill_buffer_frag(skb, buffer, large_send,
++					(int *)&buf->next_element_to_fill);
++
++	if (!queue->do_pack) {
++		QETH_DBF_TEXT(TRACE, 6, "fillbfnp");
++		/* set state to PRIMED -> will be flushed */
++		atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++		flush_cnt = 1;
++	} else {
++		QETH_DBF_TEXT(TRACE, 6, "fillbfpa");
++		if (queue->card->options.performance_stats)
++			queue->card->perf_stats.skbs_sent_pack++;
++		if (buf->next_element_to_fill >=
++				QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
++			/*
++			 * packed buffer if full -> set state PRIMED
++			 * -> will be flushed
++			 */
++			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++			flush_cnt = 1;
++		}
++	}
++	return flush_cnt;
++}
++
++int qeth_do_send_packet_fast(struct qeth_card *card,
++		struct qeth_qdio_out_q *queue, struct sk_buff *skb,
++		struct qeth_hdr *hdr, int elements_needed,
++		struct qeth_eddp_context *ctx)
++{
++	struct qeth_qdio_out_buffer *buffer;
++	int buffers_needed = 0;
++	int flush_cnt = 0;
++	int index;
++
++	QETH_DBF_TEXT(TRACE, 6, "dosndpfa");
++
++	/* spin until we get the queue ... */
++	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
++			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
++	/* ... now we've got the queue */
++	index = queue->next_buf_to_fill;
++	buffer = &queue->bufs[queue->next_buf_to_fill];
++	/*
++	 * check if buffer is empty to make sure that we do not 'overtake'
++	 * ourselves and try to fill a buffer that is already primed
++	 */
++	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
++		goto out;
++	if (ctx == NULL)
++		queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
++					  QDIO_MAX_BUFFERS_PER_Q;
++	else {
++		buffers_needed = qeth_eddp_check_buffers_for_context(queue,
++									ctx);
++		if (buffers_needed < 0)
++			goto out;
++		queue->next_buf_to_fill =
++			(queue->next_buf_to_fill + buffers_needed) %
++			QDIO_MAX_BUFFERS_PER_Q;
++	}
++	atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
++	if (ctx == NULL) {
++		qeth_fill_buffer(queue, buffer, skb);
++		qeth_flush_buffers(queue, 0, index, 1);
++	} else {
++		flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
++		WARN_ON(buffers_needed != flush_cnt);
++		qeth_flush_buffers(queue, 0, index, flush_cnt);
++	}
++	return 0;
++out:
++	atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
++	return -EBUSY;
++}
++EXPORT_SYMBOL_GPL(qeth_do_send_packet_fast);
++
++int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
++		struct sk_buff *skb, struct qeth_hdr *hdr,
++		int elements_needed, struct qeth_eddp_context *ctx)
++{
++	struct qeth_qdio_out_buffer *buffer;
++	int start_index;
++	int flush_count = 0;
++	int do_pack = 0;
++	int tmp;
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 6, "dosndpkt");
++
++	/* spin until we get the queue ... */
++	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
++			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
++	start_index = queue->next_buf_to_fill;
++	buffer = &queue->bufs[queue->next_buf_to_fill];
++	/*
++	 * check if buffer is empty to make sure that we do not 'overtake'
++	 * ourselves and try to fill a buffer that is already primed
++	 */
++	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
++		atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
++		return -EBUSY;
++	}
++	/* check if we need to switch packing state of this queue */
++	qeth_switch_to_packing_if_needed(queue);
++	if (queue->do_pack) {
++		do_pack = 1;
++		if (ctx == NULL) {
++			/* does packet fit in current buffer? */
++			if ((QETH_MAX_BUFFER_ELEMENTS(card) -
++			    buffer->next_element_to_fill) < elements_needed) {
++				/* ... no -> set state PRIMED */
++				atomic_set(&buffer->state,
++					QETH_QDIO_BUF_PRIMED);
++				flush_count++;
++				queue->next_buf_to_fill =
++					(queue->next_buf_to_fill + 1) %
++					QDIO_MAX_BUFFERS_PER_Q;
++				buffer = &queue->bufs[queue->next_buf_to_fill];
++				/* we did a step forward, so check buffer state
++				 * again */
++				if (atomic_read(&buffer->state) !=
++						QETH_QDIO_BUF_EMPTY){
++					qeth_flush_buffers(queue, 0,
++						start_index, flush_count);
++					atomic_set(&queue->state,
++						QETH_OUT_Q_UNLOCKED);
++					return -EBUSY;
++				}
++			}
++		} else {
++			/* check if we have enough elements (including following
++			 * free buffers) to handle eddp context */
++			if (qeth_eddp_check_buffers_for_context(queue, ctx)
++				< 0) {
++				if (net_ratelimit())
++					PRINT_WARN("eddp tx_dropped 1\n");
++				rc = -EBUSY;
++				goto out;
++			}
++		}
++	}
++	if (ctx == NULL)
++		tmp = qeth_fill_buffer(queue, buffer, skb);
++	else {
++		tmp = qeth_eddp_fill_buffer(queue, ctx,
++						queue->next_buf_to_fill);
++		if (tmp < 0) {
++			PRINT_ERR("eddp tx_dropped 2\n");
++			rc = -EBUSY;
++			goto out;
++		}
++	}
++	queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
++				  QDIO_MAX_BUFFERS_PER_Q;
++	flush_count += tmp;
++out:
++	if (flush_count)
++		qeth_flush_buffers(queue, 0, start_index, flush_count);
++	else if (!atomic_read(&queue->set_pci_flags_count))
++		atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
++	/*
++	 * queue->state will go from LOCKED -> UNLOCKED or from
++	 * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
++	 * (switch packing state or flush buffer to get another pci flag out).
++	 * In that case we will enter this loop
++	 */
++	while (atomic_dec_return(&queue->state)) {
++		flush_count = 0;
++		start_index = queue->next_buf_to_fill;
++		/* check if we can go back to non-packing state */
++		flush_count += qeth_switch_to_nonpacking_if_needed(queue);
++		/*
++		 * check if we need to flush a packing buffer to get a pci
++		 * flag out on the queue
++		 */
++		if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
++			flush_count += qeth_flush_buffers_on_no_pci(queue);
++		if (flush_count)
++			qeth_flush_buffers(queue, 0, start_index, flush_count);
++	}
++	/* at this point the queue is UNLOCKED again */
++	if (queue->card->options.performance_stats && do_pack)
++		queue->card->perf_stats.bufs_sent_pack += flush_count;
++
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_do_send_packet);
++
++static int qeth_setadp_promisc_mode_cb(struct qeth_card *card,
++		struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++	struct qeth_ipacmd_setadpparms *setparms;
++
++	QETH_DBF_TEXT(TRACE, 4, "prmadpcb");
++
++	cmd = (struct qeth_ipa_cmd *) data;
++	setparms = &(cmd->data.setadapterparms);
++
++	qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
++	if (cmd->hdr.return_code) {
++		QETH_DBF_TEXT_(TRACE, 4, "prmrc%2.2x", cmd->hdr.return_code);
++		setparms->data.mode = SET_PROMISC_MODE_OFF;
++	}
++	card->info.promisc_mode = setparms->data.mode;
++	return 0;
++}
++
++void qeth_setadp_promisc_mode(struct qeth_card *card)
++{
++	enum qeth_ipa_promisc_modes mode;
++	struct net_device *dev = card->dev;
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 4, "setprom");
++
++	if (((dev->flags & IFF_PROMISC) &&
++	     (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
++	    (!(dev->flags & IFF_PROMISC) &&
++	     (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
++		return;
++	mode = SET_PROMISC_MODE_OFF;
++	if (dev->flags & IFF_PROMISC)
++		mode = SET_PROMISC_MODE_ON;
++	QETH_DBF_TEXT_(TRACE, 4, "mode:%x", mode);
++
++	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
++			sizeof(struct qeth_ipacmd_setadpparms));
++	cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
++	cmd->data.setadapterparms.data.mode = mode;
++	qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
++}
++EXPORT_SYMBOL_GPL(qeth_setadp_promisc_mode);
++
++int qeth_change_mtu(struct net_device *dev, int new_mtu)
++{
++	struct qeth_card *card;
++	char dbf_text[15];
++
++	card = netdev_priv(dev);
++
++	QETH_DBF_TEXT(TRACE, 4, "chgmtu");
++	sprintf(dbf_text, "%8x", new_mtu);
++	QETH_DBF_TEXT(TRACE, 4, dbf_text);
++
++	if (new_mtu < 64)
++		return -EINVAL;
++	if (new_mtu > 65535)
++		return -EINVAL;
++	if ((!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) &&
++	    (!qeth_mtu_is_valid(card, new_mtu)))
++		return -EINVAL;
++	dev->mtu = new_mtu;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(qeth_change_mtu);
++
++struct net_device_stats *qeth_get_stats(struct net_device *dev)
++{
++	struct qeth_card *card;
++
++	card = netdev_priv(dev);
++
++	QETH_DBF_TEXT(TRACE, 5, "getstat");
++
++	return &card->stats;
++}
++EXPORT_SYMBOL_GPL(qeth_get_stats);
++
++static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
++		struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 4, "chgmaccb");
++
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (!card->options.layer2 ||
++	    !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
++		memcpy(card->dev->dev_addr,
++		       &cmd->data.setadapterparms.data.change_addr.addr,
++		       OSA_ADDR_LEN);
++		card->info.mac_bits |= QETH_LAYER2_MAC_READ;
++	}
++	qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
++	return 0;
++}
++
++int qeth_setadpparms_change_macaddr(struct qeth_card *card)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 4, "chgmac");
++
++	iob = qeth_get_adapter_cmd(card, IPA_SETADP_ALTER_MAC_ADDRESS,
++				   sizeof(struct qeth_ipacmd_setadpparms));
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	cmd->data.setadapterparms.data.change_addr.cmd = CHANGE_ADDR_READ_MAC;
++	cmd->data.setadapterparms.data.change_addr.addr_size = OSA_ADDR_LEN;
++	memcpy(&cmd->data.setadapterparms.data.change_addr.addr,
++	       card->dev->dev_addr, OSA_ADDR_LEN);
++	rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_change_macaddr_cb,
++			       NULL);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_setadpparms_change_macaddr);
++
++void qeth_tx_timeout(struct net_device *dev)
++{
++	struct qeth_card *card;
++
++	card = netdev_priv(dev);
++	card->stats.tx_errors++;
++	qeth_schedule_recovery(card);
++}
++EXPORT_SYMBOL_GPL(qeth_tx_timeout);
++
++int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	int rc = 0;
++
++	switch (regnum) {
++	case MII_BMCR: /* Basic mode control register */
++		rc = BMCR_FULLDPLX;
++		if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH) &&
++		    (card->info.link_type != QETH_LINK_TYPE_OSN) &&
++		    (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
++			rc |= BMCR_SPEED100;
++		break;
++	case MII_BMSR: /* Basic mode status register */
++		rc = BMSR_ERCAP | BMSR_ANEGCOMPLETE | BMSR_LSTATUS |
++		     BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL |
++		     BMSR_100BASE4;
++		break;
++	case MII_PHYSID1: /* PHYS ID 1 */
++		rc = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 8) |
++		     dev->dev_addr[2];
++		rc = (rc >> 5) & 0xFFFF;
++		break;
++	case MII_PHYSID2: /* PHYS ID 2 */
++		rc = (dev->dev_addr[2] << 10) & 0xFFFF;
++		break;
++	case MII_ADVERTISE: /* Advertisement control reg */
++		rc = ADVERTISE_ALL;
++		break;
++	case MII_LPA: /* Link partner ability reg */
++		rc = LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL |
++		     LPA_100BASE4 | LPA_LPACK;
++		break;
++	case MII_EXPANSION: /* Expansion register */
++		break;
++	case MII_DCOUNTER: /* disconnect counter */
++		break;
++	case MII_FCSCOUNTER: /* false carrier counter */
++		break;
++	case MII_NWAYTEST: /* N-way auto-neg test register */
++		break;
++	case MII_RERRCOUNTER: /* rx error counter */
++		rc = card->stats.rx_errors;
++		break;
++	case MII_SREVISION: /* silicon revision */
++		break;
++	case MII_RESV1: /* reserved 1 */
++		break;
++	case MII_LBRERROR: /* loopback, rx, bypass error */
++		break;
++	case MII_PHYADDR: /* physical address */
++		break;
++	case MII_RESV2: /* reserved 2 */
++		break;
++	case MII_TPISTATUS: /* TPI status for 10mbps */
++		break;
++	case MII_NCONFIG: /* network interface config */
++		break;
++	default:
++		break;
++	}
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_mdio_read);
++
++static int qeth_send_ipa_snmp_cmd(struct qeth_card *card,
++		struct qeth_cmd_buffer *iob, int len,
++		int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
++			unsigned long),
++		void *reply_param)
++{
++	u16 s1, s2;
++
++	QETH_DBF_TEXT(TRACE, 4, "sendsnmp");
++
++	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
++	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
++	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
++	/* adjust PDU length fields in IPA_PDU_HEADER */
++	s1 = (u32) IPA_PDU_HEADER_SIZE + len;
++	s2 = (u32) len;
++	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
++	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
++	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
++	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
++	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
++				      reply_cb, reply_param);
++}
++
++static int qeth_snmp_command_cb(struct qeth_card *card,
++		struct qeth_reply *reply, unsigned long sdata)
++{
++	struct qeth_ipa_cmd *cmd;
++	struct qeth_arp_query_info *qinfo;
++	struct qeth_snmp_cmd *snmp;
++	unsigned char *data;
++	__u16 data_len;
++
++	QETH_DBF_TEXT(TRACE, 3, "snpcmdcb");
++
++	cmd = (struct qeth_ipa_cmd *) sdata;
++	data = (unsigned char *)((char *)cmd - reply->offset);
++	qinfo = (struct qeth_arp_query_info *) reply->param;
++	snmp = &cmd->data.setadapterparms.data.snmp;
++
++	if (cmd->hdr.return_code) {
++		QETH_DBF_TEXT_(TRACE, 4, "scer1%i", cmd->hdr.return_code);
++		return 0;
++	}
++	if (cmd->data.setadapterparms.hdr.return_code) {
++		cmd->hdr.return_code =
++			cmd->data.setadapterparms.hdr.return_code;
++		QETH_DBF_TEXT_(TRACE, 4, "scer2%i", cmd->hdr.return_code);
++		return 0;
++	}
++	data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
++	if (cmd->data.setadapterparms.hdr.seq_no == 1)
++		data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
++	else
++		data_len -= (__u16)((char *)&snmp->request - (char *)cmd);
++
++	/* check if there is enough room in userspace */
++	if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
++		QETH_DBF_TEXT_(TRACE, 4, "scer3%i", -ENOMEM);
++		cmd->hdr.return_code = -ENOMEM;
++		return 0;
++	}
++	QETH_DBF_TEXT_(TRACE, 4, "snore%i",
++		       cmd->data.setadapterparms.hdr.used_total);
++	QETH_DBF_TEXT_(TRACE, 4, "sseqn%i",
++		cmd->data.setadapterparms.hdr.seq_no);
++	/*copy entries to user buffer*/
++	if (cmd->data.setadapterparms.hdr.seq_no == 1) {
++		memcpy(qinfo->udata + qinfo->udata_offset,
++		       (char *)snmp,
++		       data_len + offsetof(struct qeth_snmp_cmd, data));
++		qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
++	} else {
++		memcpy(qinfo->udata + qinfo->udata_offset,
++		       (char *)&snmp->request, data_len);
++	}
++	qinfo->udata_offset += data_len;
++	/* check if all replies received ... */
++		QETH_DBF_TEXT_(TRACE, 4, "srtot%i",
++			       cmd->data.setadapterparms.hdr.used_total);
++		QETH_DBF_TEXT_(TRACE, 4, "srseq%i",
++			       cmd->data.setadapterparms.hdr.seq_no);
++	if (cmd->data.setadapterparms.hdr.seq_no <
++	    cmd->data.setadapterparms.hdr.used_total)
++		return 1;
++	return 0;
++}
++
++int qeth_snmp_command(struct qeth_card *card, char __user *udata)
++{
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++	struct qeth_snmp_ureq *ureq;
++	int req_len;
++	struct qeth_arp_query_info qinfo = {0, };
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "snmpcmd");
++
++	if (card->info.guestlan)
++		return -EOPNOTSUPP;
++
++	if ((!qeth_adp_supported(card, IPA_SETADP_SET_SNMP_CONTROL)) &&
++	    (!card->options.layer2)) {
++		PRINT_WARN("SNMP Query MIBS not supported "
++			   "on %s!\n", QETH_CARD_IFNAME(card));
++		return -EOPNOTSUPP;
++	}
++	/* skip 4 bytes (data_len struct member) to get req_len */
++	if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
++		return -EFAULT;
++	ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
++	if (!ureq) {
++		QETH_DBF_TEXT(TRACE, 2, "snmpnome");
++		return -ENOMEM;
++	}
++	if (copy_from_user(ureq, udata,
++			req_len + sizeof(struct qeth_snmp_ureq_hdr))) {
++		kfree(ureq);
++		return -EFAULT;
++	}
++	qinfo.udata_len = ureq->hdr.data_len;
++	qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
++	if (!qinfo.udata) {
++		kfree(ureq);
++		return -ENOMEM;
++	}
++	qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
++
++	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
++				   QETH_SNMP_SETADP_CMDLENGTH + req_len);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
++	rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
++				    qeth_snmp_command_cb, (void *)&qinfo);
++	if (rc)
++		PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
++			   QETH_CARD_IFNAME(card), rc);
++	else {
++		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
++			rc = -EFAULT;
++	}
++
++	kfree(ureq);
++	kfree(qinfo.udata);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_snmp_command);
++
++static inline int qeth_get_qdio_q_format(struct qeth_card *card)
++{
++	switch (card->info.type) {
++	case QETH_CARD_TYPE_IQD:
++		return 2;
++	default:
++		return 0;
++	}
++}
++
++static int qeth_qdio_establish(struct qeth_card *card)
++{
++	struct qdio_initialize init_data;
++	char *qib_param_field;
++	struct qdio_buffer **in_sbal_ptrs;
++	struct qdio_buffer **out_sbal_ptrs;
++	int i, j, k;
++	int rc = 0;
++
++	QETH_DBF_TEXT(SETUP, 2, "qdioest");
++
++	qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
++			      GFP_KERNEL);
++	if (!qib_param_field)
++		return -ENOMEM;
++
++	qeth_create_qib_param_field(card, qib_param_field);
++	qeth_create_qib_param_field_blkt(card, qib_param_field);
++
++	in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
++			       GFP_KERNEL);
++	if (!in_sbal_ptrs) {
++		kfree(qib_param_field);
++		return -ENOMEM;
++	}
++	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
++		in_sbal_ptrs[i] = (struct qdio_buffer *)
++			virt_to_phys(card->qdio.in_q->bufs[i].buffer);
++
++	out_sbal_ptrs =
++		kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
++			sizeof(void *), GFP_KERNEL);
++	if (!out_sbal_ptrs) {
++		kfree(in_sbal_ptrs);
++		kfree(qib_param_field);
++		return -ENOMEM;
++	}
++	for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
++		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
++			out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
++				card->qdio.out_qs[i]->bufs[j].buffer);
++		}
++
++	memset(&init_data, 0, sizeof(struct qdio_initialize));
++	init_data.cdev                   = CARD_DDEV(card);
++	init_data.q_format               = qeth_get_qdio_q_format(card);
++	init_data.qib_param_field_format = 0;
++	init_data.qib_param_field        = qib_param_field;
++	init_data.min_input_threshold    = QETH_MIN_INPUT_THRESHOLD;
++	init_data.max_input_threshold    = QETH_MAX_INPUT_THRESHOLD;
++	init_data.min_output_threshold   = QETH_MIN_OUTPUT_THRESHOLD;
++	init_data.max_output_threshold   = QETH_MAX_OUTPUT_THRESHOLD;
++	init_data.no_input_qs            = 1;
++	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.int_parm               = (unsigned long) card;
++	init_data.flags                  = QDIO_INBOUND_0COPY_SBALS |
++					   QDIO_OUTBOUND_0COPY_SBALS |
++					   QDIO_USE_OUTBOUND_PCIS;
++	init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
++	init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
++
++	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
++		QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) {
++		rc = qdio_initialize(&init_data);
++		if (rc)
++			atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
++	}
++	kfree(out_sbal_ptrs);
++	kfree(in_sbal_ptrs);
++	kfree(qib_param_field);
++	return rc;
++}
++
++static void qeth_core_free_card(struct qeth_card *card)
++{
++
++	QETH_DBF_TEXT(SETUP, 2, "freecrd");
++	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++	qeth_clean_channel(&card->read);
++	qeth_clean_channel(&card->write);
++	if (card->dev)
++		free_netdev(card->dev);
++	kfree(card->ip_tbd_list);
++	qeth_free_qdio_buffers(card);
++	kfree(card);
++}
++
++static struct ccw_device_id qeth_ids[] = {
++	{CCW_DEVICE(0x1731, 0x01), .driver_info = QETH_CARD_TYPE_OSAE},
++	{CCW_DEVICE(0x1731, 0x05), .driver_info = QETH_CARD_TYPE_IQD},
++	{CCW_DEVICE(0x1731, 0x06), .driver_info = QETH_CARD_TYPE_OSN},
++	{},
++};
++MODULE_DEVICE_TABLE(ccw, qeth_ids);
++
++static struct ccw_driver qeth_ccw_driver = {
++	.name = "qeth",
++	.ids = qeth_ids,
++	.probe = ccwgroup_probe_ccwdev,
++	.remove = ccwgroup_remove_ccwdev,
++};
++
++static int qeth_core_driver_group(const char *buf, struct device *root_dev,
++				unsigned long driver_id)
++{
++	const char *start, *end;
++	char bus_ids[3][BUS_ID_SIZE], *argv[3];
++	int i;
++
++	start = buf;
++	for (i = 0; i < 3; i++) {
++		static const char delim[] = { ',', ',', '\n' };
++		int len;
++
++		end = strchr(start, delim[i]);
++		if (!end)
++			return -EINVAL;
++		len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
++		strncpy(bus_ids[i], start, len);
++		bus_ids[i][len] = '\0';
++		start = end + 1;
++		argv[i] = bus_ids[i];
++	}
++
++	return (ccwgroup_create(root_dev, driver_id,
++				&qeth_ccw_driver, 3, argv));
++}
++
++int qeth_core_hardsetup_card(struct qeth_card *card)
++{
++	int retries = 3;
++	int mpno;
++	int rc;
++
++	QETH_DBF_TEXT(SETUP, 2, "hrdsetup");
++	atomic_set(&card->force_alloc_skb, 0);
++retry:
++	if (retries < 3) {
++		PRINT_WARN("Retrying to do IDX activates.\n");
++		ccw_device_set_offline(CARD_DDEV(card));
++		ccw_device_set_offline(CARD_WDEV(card));
++		ccw_device_set_offline(CARD_RDEV(card));
++		ccw_device_set_online(CARD_RDEV(card));
++		ccw_device_set_online(CARD_WDEV(card));
++		ccw_device_set_online(CARD_DDEV(card));
++	}
++	rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
++	if (rc == -ERESTARTSYS) {
++		QETH_DBF_TEXT(SETUP, 2, "break1");
++		return rc;
++	} else if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		if (--retries < 0)
++			goto out;
++		else
++			goto retry;
++	}
++
++	rc = qeth_get_unitaddr(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++		return rc;
++	}
++
++	mpno = QETH_MAX_PORTNO;
++	if (card->info.portno > mpno) {
++		PRINT_ERR("Device %s does not offer port number %d \n.",
++			CARD_BUS_ID(card), card->info.portno);
++		rc = -ENODEV;
++		goto out;
++	}
++	qeth_init_tokens(card);
++	qeth_init_func_level(card);
++	rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb);
++	if (rc == -ERESTARTSYS) {
++		QETH_DBF_TEXT(SETUP, 2, "break2");
++		return rc;
++	} else if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++		if (--retries < 0)
++			goto out;
++		else
++			goto retry;
++	}
++	rc = qeth_idx_activate_channel(&card->write, qeth_idx_write_cb);
++	if (rc == -ERESTARTSYS) {
++		QETH_DBF_TEXT(SETUP, 2, "break3");
++		return rc;
++	} else if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc);
++		if (--retries < 0)
++			goto out;
++		else
++			goto retry;
++	}
++	rc = qeth_mpc_initialize(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
++		goto out;
++	}
++	return 0;
++out:
++	PRINT_ERR("Initialization in hardsetup failed! rc=%d\n", rc);
++	return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card);
++
++static inline int qeth_create_skb_frag(struct qdio_buffer_element *element,
++		struct sk_buff **pskb, int offset, int *pfrag, int data_len)
++{
++	struct page *page = virt_to_page(element->addr);
++	if (*pskb == NULL) {
++		/* the upper protocol layers assume that there is data in the
++		 * skb itself. Copy a small amount (64 bytes) to make them
++		 * happy. */
++		*pskb = dev_alloc_skb(64 + ETH_HLEN);
++		if (!(*pskb))
++			return -ENOMEM;
++		skb_reserve(*pskb, ETH_HLEN);
++		if (data_len <= 64) {
++			memcpy(skb_put(*pskb, data_len), element->addr + offset,
++				data_len);
++		} else {
++			get_page(page);
++			memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
++			skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
++				data_len - 64);
++			(*pskb)->data_len += data_len - 64;
++			(*pskb)->len      += data_len - 64;
++			(*pskb)->truesize += data_len - 64;
++			(*pfrag)++;
++		}
++	} else {
++		get_page(page);
++		skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
++		(*pskb)->data_len += data_len;
++		(*pskb)->len      += data_len;
++		(*pskb)->truesize += data_len;
++		(*pfrag)++;
++	}
++	return 0;
++}
++
++struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
++		struct qdio_buffer *buffer,
++		struct qdio_buffer_element **__element, int *__offset,
++		struct qeth_hdr **hdr)
++{
++	struct qdio_buffer_element *element = *__element;
++	int offset = *__offset;
++	struct sk_buff *skb = NULL;
++	int skb_len;
++	void *data_ptr;
++	int data_len;
++	int headroom = 0;
++	int use_rx_sg = 0;
++	int frag = 0;
++
++	QETH_DBF_TEXT(TRACE, 6, "nextskb");
++	/* qeth_hdr must not cross element boundaries */
++	if (element->length < offset + sizeof(struct qeth_hdr)) {
++		if (qeth_is_last_sbale(element))
++			return NULL;
++		element++;
++		offset = 0;
++		if (element->length < sizeof(struct qeth_hdr))
++			return NULL;
++	}
++	*hdr = element->addr + offset;
++
++	offset += sizeof(struct qeth_hdr);
++	if (card->options.layer2) {
++		if (card->info.type == QETH_CARD_TYPE_OSN) {
++			skb_len = (*hdr)->hdr.osn.pdu_length;
++			headroom = sizeof(struct qeth_hdr);
++		} else {
++			skb_len = (*hdr)->hdr.l2.pkt_length;
++		}
++	} else {
++		skb_len = (*hdr)->hdr.l3.length;
++		if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
++		    (card->info.link_type == QETH_LINK_TYPE_HSTR))
++			headroom = TR_HLEN;
++		else
++			headroom = ETH_HLEN;
++	}
++
++	if (!skb_len)
++		return NULL;
++
++	if ((skb_len >= card->options.rx_sg_cb) &&
++	    (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
++	    (!atomic_read(&card->force_alloc_skb))) {
++		use_rx_sg = 1;
++	} else {
++		skb = dev_alloc_skb(skb_len + headroom);
++		if (!skb)
++			goto no_mem;
++		if (headroom)
++			skb_reserve(skb, headroom);
++	}
++
++	data_ptr = element->addr + offset;
++	while (skb_len) {
++		data_len = min(skb_len, (int)(element->length - offset));
++		if (data_len) {
++			if (use_rx_sg) {
++				if (qeth_create_skb_frag(element, &skb, offset,
++				    &frag, data_len))
++					goto no_mem;
++			} else {
++				memcpy(skb_put(skb, data_len), data_ptr,
++					data_len);
++			}
++		}
++		skb_len -= data_len;
++		if (skb_len) {
++			if (qeth_is_last_sbale(element)) {
++				QETH_DBF_TEXT(TRACE, 4, "unexeob");
++				QETH_DBF_TEXT_(TRACE, 4, "%s",
++					CARD_BUS_ID(card));
++				QETH_DBF_TEXT(QERR, 2, "unexeob");
++				QETH_DBF_TEXT_(QERR, 2, "%s",
++					CARD_BUS_ID(card));
++				QETH_DBF_HEX(MISC, 4, buffer, sizeof(*buffer));
++				dev_kfree_skb_any(skb);
++				card->stats.rx_errors++;
++				return NULL;
++			}
++			element++;
++			offset = 0;
++			data_ptr = element->addr;
++		} else {
++			offset += data_len;
++		}
++	}
++	*__element = element;
++	*__offset = offset;
++	if (use_rx_sg && card->options.performance_stats) {
++		card->perf_stats.sg_skbs_rx++;
++		card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
++	}
++	return skb;
++no_mem:
++	if (net_ratelimit()) {
++		PRINT_WARN("No memory for packet received on %s.\n",
++			   QETH_CARD_IFNAME(card));
++		QETH_DBF_TEXT(TRACE, 2, "noskbmem");
++		QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card));
++	}
++	card->stats.rx_dropped++;
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_next_skb);
++
++static void qeth_unregister_dbf_views(void)
++{
++	int x;
++	for (x = 0; x < QETH_DBF_INFOS; x++) {
++		debug_unregister(qeth_dbf[x].id);
++		qeth_dbf[x].id = NULL;
++	}
++}
++
++static int qeth_register_dbf_views(void)
++{
++	int ret;
++	int x;
++
++	for (x = 0; x < QETH_DBF_INFOS; x++) {
++		/* register the areas */
++		qeth_dbf[x].id = debug_register(qeth_dbf[x].name,
++						qeth_dbf[x].pages,
++						qeth_dbf[x].areas,
++						qeth_dbf[x].len);
++		if (qeth_dbf[x].id == NULL) {
++			qeth_unregister_dbf_views();
++			return -ENOMEM;
++		}
++
++		/* register a view */
++		ret = debug_register_view(qeth_dbf[x].id, qeth_dbf[x].view);
++		if (ret) {
++			qeth_unregister_dbf_views();
++			return ret;
++		}
++
++		/* set a passing level */
++		debug_set_level(qeth_dbf[x].id, qeth_dbf[x].level);
++	}
++
++	return 0;
++}
++
++int qeth_core_load_discipline(struct qeth_card *card,
++		enum qeth_discipline_id discipline)
++{
++	int rc = 0;
++	switch (discipline) {
++	case QETH_DISCIPLINE_LAYER3:
++		card->discipline.ccwgdriver = try_then_request_module(
++			symbol_get(qeth_l3_ccwgroup_driver),
++			"qeth_l3");
++		break;
++	case QETH_DISCIPLINE_LAYER2:
++		card->discipline.ccwgdriver = try_then_request_module(
++			symbol_get(qeth_l2_ccwgroup_driver),
++			"qeth_l2");
++		break;
++	}
++	if (!card->discipline.ccwgdriver) {
++		PRINT_ERR("Support for discipline %d not present\n",
++				discipline);
++		rc = -EINVAL;
++	}
++	return rc;
++}
++
++void qeth_core_free_discipline(struct qeth_card *card)
++{
++	if (card->options.layer2)
++		symbol_put(qeth_l2_ccwgroup_driver);
++	else
++		symbol_put(qeth_l3_ccwgroup_driver);
++	card->discipline.ccwgdriver = NULL;
++}
++
++static int qeth_core_probe_device(struct ccwgroup_device *gdev)
++{
++	struct qeth_card *card;
++	struct device *dev;
++	int rc;
++	unsigned long flags;
++
++	QETH_DBF_TEXT(SETUP, 2, "probedev");
++
++	dev = &gdev->dev;
++	if (!get_device(dev))
++		return -ENODEV;
++
++	QETH_DBF_TEXT_(SETUP, 2, "%s", gdev->dev.bus_id);
++
++	card = qeth_alloc_card();
++	if (!card) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", -ENOMEM);
++		rc = -ENOMEM;
++		goto err_dev;
++	}
++	card->read.ccwdev  = gdev->cdev[0];
++	card->write.ccwdev = gdev->cdev[1];
++	card->data.ccwdev  = gdev->cdev[2];
++	dev_set_drvdata(&gdev->dev, card);
++	card->gdev = gdev;
++	gdev->cdev[0]->handler = qeth_irq;
++	gdev->cdev[1]->handler = qeth_irq;
++	gdev->cdev[2]->handler = qeth_irq;
++
++	rc = qeth_determine_card_type(card);
++	if (rc) {
++		PRINT_WARN("%s: not a valid card type\n", __func__);
++		QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++		goto err_card;
++	}
++	rc = qeth_setup_card(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++		goto err_card;
++	}
++
++	if (card->info.type == QETH_CARD_TYPE_OSN) {
++		rc = qeth_core_create_osn_attributes(dev);
++		if (rc)
++			goto err_card;
++		rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
++		if (rc) {
++			qeth_core_remove_osn_attributes(dev);
++			goto err_card;
++		}
++		rc = card->discipline.ccwgdriver->probe(card->gdev);
++		if (rc) {
++			qeth_core_free_discipline(card);
++			qeth_core_remove_osn_attributes(dev);
++			goto err_card;
++		}
++	} else {
++		rc = qeth_core_create_device_attributes(dev);
++		if (rc)
++			goto err_card;
++	}
++
++	write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++	list_add_tail(&card->list, &qeth_core_card_list.list);
++	write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++	return 0;
++
++err_card:
++	qeth_core_free_card(card);
++err_dev:
++	put_device(dev);
++	return rc;
++}
++
++static void qeth_core_remove_device(struct ccwgroup_device *gdev)
++{
++	unsigned long flags;
++	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++
++	if (card->discipline.ccwgdriver) {
++		card->discipline.ccwgdriver->remove(gdev);
++		qeth_core_free_discipline(card);
++	}
++
++	if (card->info.type == QETH_CARD_TYPE_OSN) {
++		qeth_core_remove_osn_attributes(&gdev->dev);
++	} else {
++		qeth_core_remove_device_attributes(&gdev->dev);
++	}
++	write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++	list_del(&card->list);
++	write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++	qeth_core_free_card(card);
++	dev_set_drvdata(&gdev->dev, NULL);
++	put_device(&gdev->dev);
++	return;
++}
++
++static int qeth_core_set_online(struct ccwgroup_device *gdev)
++{
++	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++	int rc = 0;
++	int def_discipline;
++
++	if (!card->discipline.ccwgdriver) {
++		if (card->info.type == QETH_CARD_TYPE_IQD)
++			def_discipline = QETH_DISCIPLINE_LAYER3;
++		else
++			def_discipline = QETH_DISCIPLINE_LAYER2;
++		rc = qeth_core_load_discipline(card, def_discipline);
++		if (rc)
++			goto err;
++		rc = card->discipline.ccwgdriver->probe(card->gdev);
++		if (rc)
++			goto err;
++	}
++	rc = card->discipline.ccwgdriver->set_online(gdev);
++err:
++	return rc;
++}
++
++static int qeth_core_set_offline(struct ccwgroup_device *gdev)
++{
++	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++	return card->discipline.ccwgdriver->set_offline(gdev);
++}
++
++static void qeth_core_shutdown(struct ccwgroup_device *gdev)
++{
++	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++	if (card->discipline.ccwgdriver &&
++	    card->discipline.ccwgdriver->shutdown)
++		card->discipline.ccwgdriver->shutdown(gdev);
++}
++
++static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
++	.owner = THIS_MODULE,
++	.name = "qeth",
++	.driver_id = 0xD8C5E3C8,
++	.probe = qeth_core_probe_device,
++	.remove = qeth_core_remove_device,
++	.set_online = qeth_core_set_online,
++	.set_offline = qeth_core_set_offline,
++	.shutdown = qeth_core_shutdown,
++};
++
++static ssize_t
++qeth_core_driver_group_store(struct device_driver *ddrv, const char *buf,
++			   size_t count)
++{
++	int err;
++	err = qeth_core_driver_group(buf, qeth_core_root_dev,
++					qeth_core_ccwgroup_driver.driver_id);
++	if (err)
++		return err;
++	else
++		return count;
++}
++
++static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store);
++
++static struct {
++	const char str[ETH_GSTRING_LEN];
++} qeth_ethtool_stats_keys[] = {
++/*  0 */{"rx skbs"},
++	{"rx buffers"},
++	{"tx skbs"},
++	{"tx buffers"},
++	{"tx skbs no packing"},
++	{"tx buffers no packing"},
++	{"tx skbs packing"},
++	{"tx buffers packing"},
++	{"tx sg skbs"},
++	{"tx sg frags"},
++/* 10 */{"rx sg skbs"},
++	{"rx sg frags"},
++	{"rx sg page allocs"},
++	{"tx large kbytes"},
++	{"tx large count"},
++	{"tx pk state ch n->p"},
++	{"tx pk state ch p->n"},
++	{"tx pk watermark low"},
++	{"tx pk watermark high"},
++	{"queue 0 buffer usage"},
++/* 20 */{"queue 1 buffer usage"},
++	{"queue 2 buffer usage"},
++	{"queue 3 buffer usage"},
++	{"rx handler time"},
++	{"rx handler count"},
++	{"rx do_QDIO time"},
++	{"rx do_QDIO count"},
++	{"tx handler time"},
++	{"tx handler count"},
++	{"tx time"},
++/* 30 */{"tx count"},
++	{"tx do_QDIO time"},
++	{"tx do_QDIO count"},
++};
++
++int qeth_core_get_stats_count(struct net_device *dev)
++{
++	return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN);
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_stats_count);
++
++void qeth_core_get_ethtool_stats(struct net_device *dev,
++		struct ethtool_stats *stats, u64 *data)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	data[0] = card->stats.rx_packets -
++				card->perf_stats.initial_rx_packets;
++	data[1] = card->perf_stats.bufs_rec;
++	data[2] = card->stats.tx_packets -
++				card->perf_stats.initial_tx_packets;
++	data[3] = card->perf_stats.bufs_sent;
++	data[4] = card->stats.tx_packets - card->perf_stats.initial_tx_packets
++			- card->perf_stats.skbs_sent_pack;
++	data[5] = card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack;
++	data[6] = card->perf_stats.skbs_sent_pack;
++	data[7] = card->perf_stats.bufs_sent_pack;
++	data[8] = card->perf_stats.sg_skbs_sent;
++	data[9] = card->perf_stats.sg_frags_sent;
++	data[10] = card->perf_stats.sg_skbs_rx;
++	data[11] = card->perf_stats.sg_frags_rx;
++	data[12] = card->perf_stats.sg_alloc_page_rx;
++	data[13] = (card->perf_stats.large_send_bytes >> 10);
++	data[14] = card->perf_stats.large_send_cnt;
++	data[15] = card->perf_stats.sc_dp_p;
++	data[16] = card->perf_stats.sc_p_dp;
++	data[17] = QETH_LOW_WATERMARK_PACK;
++	data[18] = QETH_HIGH_WATERMARK_PACK;
++	data[19] = atomic_read(&card->qdio.out_qs[0]->used_buffers);
++	data[20] = (card->qdio.no_out_queues > 1) ?
++			atomic_read(&card->qdio.out_qs[1]->used_buffers) : 0;
++	data[21] = (card->qdio.no_out_queues > 2) ?
++			atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0;
++	data[22] = (card->qdio.no_out_queues > 3) ?
++			atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0;
++	data[23] = card->perf_stats.inbound_time;
++	data[24] = card->perf_stats.inbound_cnt;
++	data[25] = card->perf_stats.inbound_do_qdio_time;
++	data[26] = card->perf_stats.inbound_do_qdio_cnt;
++	data[27] = card->perf_stats.outbound_handler_time;
++	data[28] = card->perf_stats.outbound_handler_cnt;
++	data[29] = card->perf_stats.outbound_time;
++	data[30] = card->perf_stats.outbound_cnt;
++	data[31] = card->perf_stats.outbound_do_qdio_time;
++	data[32] = card->perf_stats.outbound_do_qdio_cnt;
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
++
++void qeth_core_get_strings(struct net_device *dev, u32 stringset, u8 *data)
++{
++	switch (stringset) {
++	case ETH_SS_STATS:
++		memcpy(data, &qeth_ethtool_stats_keys,
++			sizeof(qeth_ethtool_stats_keys));
++		break;
++	default:
++		WARN_ON(1);
++		break;
++	}
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_strings);
++
++void qeth_core_get_drvinfo(struct net_device *dev,
++		struct ethtool_drvinfo *info)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	if (card->options.layer2)
++		strcpy(info->driver, "qeth_l2");
++	else
++		strcpy(info->driver, "qeth_l3");
++
++	strcpy(info->version, "1.0");
++	strcpy(info->fw_version, card->info.mcl_level);
++	sprintf(info->bus_info, "%s/%s/%s",
++			CARD_RDEV_ID(card),
++			CARD_WDEV_ID(card),
++			CARD_DDEV_ID(card));
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
++
++static int __init qeth_core_init(void)
++{
++	int rc;
++
++	PRINT_INFO("loading core functions\n");
++	INIT_LIST_HEAD(&qeth_core_card_list.list);
++	rwlock_init(&qeth_core_card_list.rwlock);
++
++	rc = qeth_register_dbf_views();
++	if (rc)
++		goto out_err;
++	rc = ccw_driver_register(&qeth_ccw_driver);
++	if (rc)
++		goto ccw_err;
++	rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver);
++	if (rc)
++		goto ccwgroup_err;
++	rc = driver_create_file(&qeth_core_ccwgroup_driver.driver,
++				&driver_attr_group);
++	if (rc)
++		goto driver_err;
++	qeth_core_root_dev = s390_root_dev_register("qeth");
++	rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0;
++	if (rc)
++		goto register_err;
++	return 0;
++
++register_err:
++	driver_remove_file(&qeth_core_ccwgroup_driver.driver,
++			   &driver_attr_group);
++driver_err:
++	ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
++ccwgroup_err:
++	ccw_driver_unregister(&qeth_ccw_driver);
++ccw_err:
++	qeth_unregister_dbf_views();
++out_err:
++	PRINT_ERR("Initialization failed with code %d\n", rc);
++	return rc;
++}
++
++static void __exit qeth_core_exit(void)
++{
++	s390_root_dev_unregister(qeth_core_root_dev);
++	driver_remove_file(&qeth_core_ccwgroup_driver.driver,
++			   &driver_attr_group);
++	ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
++	ccw_driver_unregister(&qeth_ccw_driver);
++	qeth_unregister_dbf_views();
++	PRINT_INFO("core functions removed\n");
++}
++
++module_init(qeth_core_init);
++module_exit(qeth_core_exit);
++MODULE_AUTHOR("Frank Blaschka <frank.blaschka at de.ibm.com>");
++MODULE_DESCRIPTION("qeth core functions");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c
+new file mode 100644
+index 0000000..06f4de1
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_mpc.c
+@@ -0,0 +1,266 @@
++/*
++ *  drivers/s390/net/qeth_core_mpc.c
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Frank Pavlic <fpavlic at de.ibm.com>,
++ *		 Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/module.h>
++#include <asm/cio.h>
++#include "qeth_core_mpc.h"
++
++unsigned char IDX_ACTIVATE_READ[] = {
++	0x00, 0x00, 0x80, 0x00,  0x00, 0x00, 0x00, 0x00,
++	0x19, 0x01, 0x01, 0x80,  0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0xc8, 0xc1,
++	0xd3, 0xd3, 0xd6, 0xd3,  0xc5, 0x40, 0x00, 0x00,
++	0x00, 0x00
++};
++
++unsigned char IDX_ACTIVATE_WRITE[] = {
++	0x00, 0x00, 0x80, 0x00,  0x00, 0x00, 0x00, 0x00,
++	0x15, 0x01, 0x01, 0x80,  0x00, 0x00, 0x00, 0x00,
++	0xff, 0xff, 0x00, 0x00,  0x00, 0x00, 0xc8, 0xc1,
++	0xd3, 0xd3, 0xd6, 0xd3,  0xc5, 0x40, 0x00, 0x00,
++	0x00, 0x00
++};
++
++unsigned char CM_ENABLE[] = {
++	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x01,
++	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x63,
++	0x10, 0x00, 0x00, 0x01,
++	0x00, 0x00, 0x00, 0x00,
++	0x81, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x23,
++	0x00, 0x00, 0x23, 0x05,  0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
++	0x01, 0x00, 0x00, 0x23,  0x00, 0x00, 0x00, 0x40,
++	0x00, 0x0c, 0x41, 0x02,  0x00, 0x17, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x0b, 0x04, 0x01,
++	0x7e, 0x04, 0x05, 0x00,  0x01, 0x01, 0x0f,
++	0x00,
++	0x0c, 0x04, 0x02, 0xff,  0xff, 0xff, 0xff, 0xff,
++	0xff, 0xff, 0xff
++};
++
++unsigned char CM_SETUP[] = {
++	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x02,
++	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x64,
++	0x10, 0x00, 0x00, 0x01,
++	0x00, 0x00, 0x00, 0x00,
++	0x81, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x24,
++	0x00, 0x00, 0x24, 0x05,  0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
++	0x01, 0x00, 0x00, 0x24,  0x00, 0x00, 0x00, 0x40,
++	0x00, 0x0c, 0x41, 0x04,  0x00, 0x18, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x09, 0x04, 0x04,
++	0x05, 0x00, 0x01, 0x01,  0x11,
++	0x00, 0x09, 0x04,
++	0x05, 0x05, 0x00, 0x00,  0x00, 0x00,
++	0x00, 0x06,
++	0x04, 0x06, 0xc8, 0x00
++};
++
++unsigned char ULP_ENABLE[] = {
++	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x03,
++	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x6b,
++	0x10, 0x00, 0x00, 0x01,
++	0x00, 0x00, 0x00, 0x00,
++	0x41, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x01,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x24, 0x00, 0x2b,
++	0x00, 0x00, 0x2b, 0x05,  0x20, 0x01, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
++	0x01, 0x00, 0x00, 0x2b,  0x00, 0x00, 0x00, 0x40,
++	0x00, 0x0c, 0x41, 0x02,  0x00, 0x1f, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x0b, 0x04, 0x01,
++	0x03, 0x04, 0x05, 0x00,  0x01, 0x01, 0x12,
++	0x00,
++	0x14, 0x04, 0x0a, 0x00,  0x20, 0x00, 0x00, 0xff,
++	0xff, 0x00, 0x08, 0xc8,  0xe8, 0xc4, 0xf1, 0xc7,
++	0xf1, 0x00, 0x00
++};
++
++unsigned char ULP_SETUP[] = {
++	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x04,
++	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x6c,
++	0x10, 0x00, 0x00, 0x01,
++	0x00, 0x00, 0x00, 0x00,
++	0x41, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x02,
++	0x00, 0x00, 0x00, 0x01,  0x00, 0x24, 0x00, 0x2c,
++	0x00, 0x00, 0x2c, 0x05,  0x20, 0x01, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
++	0x01, 0x00, 0x00, 0x2c,  0x00, 0x00, 0x00, 0x40,
++	0x00, 0x0c, 0x41, 0x04,  0x00, 0x20, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x09, 0x04, 0x04,
++	0x05, 0x00, 0x01, 0x01,  0x14,
++	0x00, 0x09, 0x04,
++	0x05, 0x05, 0x30, 0x01,  0x00, 0x00,
++	0x00, 0x06,
++	0x04, 0x06, 0x40, 0x00,
++	0x00, 0x08, 0x04, 0x0b,
++	0x00, 0x00, 0x00, 0x00
++};
++
++unsigned char DM_ACT[] = {
++	0x00, 0xe0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x05,
++	0x00, 0x00, 0x00, 0x14,  0x00, 0x00, 0x00, 0x55,
++	0x10, 0x00, 0x00, 0x01,
++	0x00, 0x00, 0x00, 0x00,
++	0x41, 0x7e, 0x00, 0x01,  0x00, 0x00, 0x00, 0x03,
++	0x00, 0x00, 0x00, 0x02,  0x00, 0x24, 0x00, 0x15,
++	0x00, 0x00, 0x2c, 0x05,  0x20, 0x01, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
++	0x01, 0x00, 0x00, 0x15,  0x00, 0x00, 0x00, 0x40,
++	0x00, 0x0c, 0x43, 0x60,  0x00, 0x09, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x09, 0x04, 0x04,
++	0x05, 0x40, 0x01, 0x01,  0x00
++};
++
++unsigned char IPA_PDU_HEADER[] = {
++	0x00, 0xe0, 0x00, 0x00,  0x77, 0x77, 0x77, 0x77,
++	0x00, 0x00, 0x00, 0x14,  0x00, 0x00,
++		(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) / 256,
++		(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) % 256,
++	0x10, 0x00, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
++	0xc1, 0x03, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x24,
++		sizeof(struct qeth_ipa_cmd) / 256,
++		sizeof(struct qeth_ipa_cmd) % 256,
++	0x00,
++		sizeof(struct qeth_ipa_cmd) / 256,
++		sizeof(struct qeth_ipa_cmd) % 256,
++	0x05,
++	0x77, 0x77, 0x77, 0x77,
++	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
++	0x01, 0x00,
++		sizeof(struct qeth_ipa_cmd) / 256,
++		sizeof(struct qeth_ipa_cmd) % 256,
++	0x00, 0x00, 0x00, 0x40,
++};
++EXPORT_SYMBOL_GPL(IPA_PDU_HEADER);
++
++unsigned char WRITE_CCW[] = {
++	0x01, CCW_FLAG_SLI, 0, 0,
++	0, 0, 0, 0
++};
++
++unsigned char READ_CCW[] = {
++	0x02, CCW_FLAG_SLI, 0, 0,
++	0, 0, 0, 0
++};
++
++
++struct ipa_rc_msg {
++	enum qeth_ipa_return_codes rc;
++	char *msg;
++};
++
++static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
++	{IPA_RC_SUCCESS,		"success"},
++	{IPA_RC_NOTSUPP,		"Command not supported"},
++	{IPA_RC_IP_TABLE_FULL,		"Add Addr IP Table Full - ipv6"},
++	{IPA_RC_UNKNOWN_ERROR,		"IPA command failed - reason unknown"},
++	{IPA_RC_UNSUPPORTED_COMMAND,	"Command not supported"},
++	{IPA_RC_DUP_IPV6_REMOTE, "ipv6 address already registered remote"},
++	{IPA_RC_DUP_IPV6_HOME,		"ipv6 address already registered"},
++	{IPA_RC_UNREGISTERED_ADDR,	"Address not registered"},
++	{IPA_RC_NO_ID_AVAILABLE,	"No identifiers available"},
++	{IPA_RC_ID_NOT_FOUND,		"Identifier not found"},
++	{IPA_RC_INVALID_IP_VERSION,	"IP version incorrect"},
++	{IPA_RC_LAN_FRAME_MISMATCH,	"LAN and frame mismatch"},
++	{IPA_RC_L2_UNSUPPORTED_CMD,	"Unsupported layer 2 command"},
++	{IPA_RC_L2_DUP_MAC,		"Duplicate MAC address"},
++	{IPA_RC_L2_ADDR_TABLE_FULL,	"Layer2 address table full"},
++	{IPA_RC_L2_DUP_LAYER3_MAC,	"Duplicate with layer 3 MAC"},
++	{IPA_RC_L2_GMAC_NOT_FOUND,	"GMAC not found"},
++	{IPA_RC_L2_MAC_NOT_FOUND,	"L2 mac address not found"},
++	{IPA_RC_L2_INVALID_VLAN_ID,	"L2 invalid vlan id"},
++	{IPA_RC_L2_DUP_VLAN_ID,		"L2 duplicate vlan id"},
++	{IPA_RC_L2_VLAN_ID_NOT_FOUND,	"L2 vlan id not found"},
++	{IPA_RC_DATA_MISMATCH,		"Data field mismatch (v4/v6 mixed)"},
++	{IPA_RC_INVALID_MTU_SIZE,	"Invalid MTU size"},
++	{IPA_RC_INVALID_LANTYPE,	"Invalid LAN type"},
++	{IPA_RC_INVALID_LANNUM,		"Invalid LAN num"},
++	{IPA_RC_DUPLICATE_IP_ADDRESS,	"Address already registered"},
++	{IPA_RC_IP_ADDR_TABLE_FULL,	"IP address table full"},
++	{IPA_RC_LAN_PORT_STATE_ERROR,	"LAN port state error"},
++	{IPA_RC_SETIP_NO_STARTLAN,	"Setip no startlan received"},
++	{IPA_RC_SETIP_ALREADY_RECEIVED,	"Setip already received"},
++	{IPA_RC_IP_ADDR_ALREADY_USED,	"IP address already in use on LAN"},
++	{IPA_RC_MC_ADDR_NOT_FOUND,	"Multicast address not found"},
++	{IPA_RC_SETIP_INVALID_VERSION,	"SETIP invalid IP version"},
++	{IPA_RC_UNSUPPORTED_SUBCMD,	"Unsupported assist subcommand"},
++	{IPA_RC_ARP_ASSIST_NO_ENABLE,	"Only partial success, no enable"},
++	{IPA_RC_PRIMARY_ALREADY_DEFINED, "Primary already defined"},
++	{IPA_RC_SECOND_ALREADY_DEFINED,	"Secondary already defined"},
++	{IPA_RC_INVALID_SETRTG_INDICATOR, "Invalid SETRTG indicator"},
++	{IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"},
++	{IPA_RC_LAN_OFFLINE,		"STRTLAN_LAN_DISABLED - LAN offline"},
++	{IPA_RC_INVALID_IP_VERSION2,	"Invalid IP version"},
++	{IPA_RC_FFFF,			"Unknown Error"}
++};
++
++
++
++char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
++{
++	int x = 0;
++	qeth_ipa_rc_msg[sizeof(qeth_ipa_rc_msg) /
++			sizeof(struct ipa_rc_msg) - 1].rc = rc;
++	while (qeth_ipa_rc_msg[x].rc != rc)
++		x++;
++	return qeth_ipa_rc_msg[x].msg;
++}
++
++
++struct ipa_cmd_names {
++	enum qeth_ipa_cmds cmd;
++	char *name;
++};
++
++static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
++	{IPA_CMD_STARTLAN,	"startlan"},
++	{IPA_CMD_STOPLAN,	"stoplan"},
++	{IPA_CMD_SETVMAC,	"setvmac"},
++	{IPA_CMD_DELVMAC,	"delvmac"},
++	{IPA_CMD_SETGMAC,	"setgmac"},
++	{IPA_CMD_DELGMAC,	"delgmac"},
++	{IPA_CMD_SETVLAN,	"setvlan"},
++	{IPA_CMD_DELVLAN,	"delvlan"},
++	{IPA_CMD_SETCCID,	"setccid"},
++	{IPA_CMD_DELCCID,	"delccid"},
++	{IPA_CMD_MODCCID,	"modccid"},
++	{IPA_CMD_SETIP,		"setip"},
++	{IPA_CMD_QIPASSIST,	"qipassist"},
++	{IPA_CMD_SETASSPARMS,	"setassparms"},
++	{IPA_CMD_SETIPM,	"setipm"},
++	{IPA_CMD_DELIPM,	"delipm"},
++	{IPA_CMD_SETRTG,	"setrtg"},
++	{IPA_CMD_DELIP,		"delip"},
++	{IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
++	{IPA_CMD_SET_DIAG_ASS,	"set_diag_ass"},
++	{IPA_CMD_CREATE_ADDR,	"create_addr"},
++	{IPA_CMD_DESTROY_ADDR,	"destroy_addr"},
++	{IPA_CMD_REGISTER_LOCAL_ADDR,	"register_local_addr"},
++	{IPA_CMD_UNREGISTER_LOCAL_ADDR,	"unregister_local_addr"},
++	{IPA_CMD_UNKNOWN,	"unknown"},
++};
++
++char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
++{
++	int x = 0;
++	qeth_ipa_cmd_names[
++		sizeof(qeth_ipa_cmd_names) /
++			sizeof(struct ipa_cmd_names)-1].cmd = cmd;
++	while (qeth_ipa_cmd_names[x].cmd != cmd)
++		x++;
++	return qeth_ipa_cmd_names[x].name;
++}
+diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
+new file mode 100644
+index 0000000..1854882
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_mpc.h
+@@ -0,0 +1,566 @@
++/*
++ *  drivers/s390/net/qeth_core_mpc.h
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Frank Pavlic <fpavlic at de.ibm.com>,
++ *		 Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#ifndef __QETH_CORE_MPC_H__
++#define __QETH_CORE_MPC_H__
++
++#include <asm/qeth.h>
++
++#define IPA_PDU_HEADER_SIZE	0x40
++#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer + 0x0e)
++#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer + 0x26)
++#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer + 0x29)
++#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer + 0x3a)
++
++extern unsigned char IPA_PDU_HEADER[];
++#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer + 0x2c)
++
++#define IPA_CMD_LENGTH	(IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
++
++#define QETH_SEQ_NO_LENGTH	4
++#define QETH_MPC_TOKEN_LENGTH	4
++#define QETH_MCL_LENGTH		4
++#define OSA_ADDR_LEN		6
++
++#define QETH_TIMEOUT		(10 * HZ)
++#define QETH_IPA_TIMEOUT	(45 * HZ)
++#define QETH_IDX_COMMAND_SEQNO	0xffff0000
++#define SR_INFO_LEN		16
++
++#define QETH_CLEAR_CHANNEL_PARM	-10
++#define QETH_HALT_CHANNEL_PARM	-11
++#define QETH_RCD_PARM -12
++
++/*****************************************************************************/
++/* IP Assist related definitions                                             */
++/*****************************************************************************/
++#define IPA_CMD_INITIATOR_HOST  0x00
++#define IPA_CMD_INITIATOR_OSA   0x01
++#define IPA_CMD_INITIATOR_HOST_REPLY  0x80
++#define IPA_CMD_INITIATOR_OSA_REPLY   0x81
++#define IPA_CMD_PRIM_VERSION_NO 0x01
++
++enum qeth_card_types {
++	QETH_CARD_TYPE_UNKNOWN = 0,
++	QETH_CARD_TYPE_OSAE    = 10,
++	QETH_CARD_TYPE_IQD     = 1234,
++	QETH_CARD_TYPE_OSN     = 11,
++};
++
++#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
++/* only the first two bytes are looked at in qeth_get_cardname_short */
++enum qeth_link_types {
++	QETH_LINK_TYPE_FAST_ETH     = 0x01,
++	QETH_LINK_TYPE_HSTR         = 0x02,
++	QETH_LINK_TYPE_GBIT_ETH     = 0x03,
++	QETH_LINK_TYPE_OSN          = 0x04,
++	QETH_LINK_TYPE_10GBIT_ETH   = 0x10,
++	QETH_LINK_TYPE_LANE_ETH100  = 0x81,
++	QETH_LINK_TYPE_LANE_TR      = 0x82,
++	QETH_LINK_TYPE_LANE_ETH1000 = 0x83,
++	QETH_LINK_TYPE_LANE         = 0x88,
++	QETH_LINK_TYPE_ATM_NATIVE   = 0x90,
++};
++
++enum qeth_tr_macaddr_modes {
++	QETH_TR_MACADDR_NONCANONICAL = 0,
++	QETH_TR_MACADDR_CANONICAL    = 1,
++};
++
++enum qeth_tr_broadcast_modes {
++	QETH_TR_BROADCAST_ALLRINGS = 0,
++	QETH_TR_BROADCAST_LOCAL    = 1,
++};
++
++/* these values match CHECKSUM_* in include/linux/skbuff.h */
++enum qeth_checksum_types {
++	SW_CHECKSUMMING = 0, /* TODO: set to bit flag used in IPA Command */
++	HW_CHECKSUMMING = 1,
++	NO_CHECKSUMMING = 2,
++};
++#define QETH_CHECKSUM_DEFAULT SW_CHECKSUMMING
++
++/*
++ * Routing stuff
++ */
++#define RESET_ROUTING_FLAG 0x10 /* indicate that routing type shall be set */
++enum qeth_routing_types {
++	/* TODO: set to bit flag used in IPA Command */
++	NO_ROUTER		= 0,
++	PRIMARY_ROUTER		= 1,
++	SECONDARY_ROUTER	= 2,
++	MULTICAST_ROUTER	= 3,
++	PRIMARY_CONNECTOR	= 4,
++	SECONDARY_CONNECTOR	= 5,
++};
++
++/* IPA Commands */
++enum qeth_ipa_cmds {
++	IPA_CMD_STARTLAN		= 0x01,
++	IPA_CMD_STOPLAN			= 0x02,
++	IPA_CMD_SETVMAC			= 0x21,
++	IPA_CMD_DELVMAC			= 0x22,
++	IPA_CMD_SETGMAC			= 0x23,
++	IPA_CMD_DELGMAC			= 0x24,
++	IPA_CMD_SETVLAN			= 0x25,
++	IPA_CMD_DELVLAN			= 0x26,
++	IPA_CMD_SETCCID			= 0x41,
++	IPA_CMD_DELCCID			= 0x42,
++	IPA_CMD_MODCCID			= 0x43,
++	IPA_CMD_SETIP			= 0xb1,
++	IPA_CMD_QIPASSIST		= 0xb2,
++	IPA_CMD_SETASSPARMS		= 0xb3,
++	IPA_CMD_SETIPM			= 0xb4,
++	IPA_CMD_DELIPM			= 0xb5,
++	IPA_CMD_SETRTG			= 0xb6,
++	IPA_CMD_DELIP			= 0xb7,
++	IPA_CMD_SETADAPTERPARMS		= 0xb8,
++	IPA_CMD_SET_DIAG_ASS		= 0xb9,
++	IPA_CMD_CREATE_ADDR		= 0xc3,
++	IPA_CMD_DESTROY_ADDR		= 0xc4,
++	IPA_CMD_REGISTER_LOCAL_ADDR	= 0xd1,
++	IPA_CMD_UNREGISTER_LOCAL_ADDR	= 0xd2,
++	IPA_CMD_UNKNOWN			= 0x00
++};
++
++enum qeth_ip_ass_cmds {
++	IPA_CMD_ASS_START	= 0x0001,
++	IPA_CMD_ASS_STOP	= 0x0002,
++	IPA_CMD_ASS_CONFIGURE	= 0x0003,
++	IPA_CMD_ASS_ENABLE	= 0x0004,
++};
++
++enum qeth_arp_process_subcmds {
++	IPA_CMD_ASS_ARP_SET_NO_ENTRIES	= 0x0003,
++	IPA_CMD_ASS_ARP_QUERY_CACHE	= 0x0004,
++	IPA_CMD_ASS_ARP_ADD_ENTRY	= 0x0005,
++	IPA_CMD_ASS_ARP_REMOVE_ENTRY	= 0x0006,
++	IPA_CMD_ASS_ARP_FLUSH_CACHE	= 0x0007,
++	IPA_CMD_ASS_ARP_QUERY_INFO	= 0x0104,
++	IPA_CMD_ASS_ARP_QUERY_STATS	= 0x0204,
++};
++
++
++/* Return Codes for IPA Commands
++ * according to OSA card Specs */
++
++enum qeth_ipa_return_codes {
++	IPA_RC_SUCCESS			= 0x0000,
++	IPA_RC_NOTSUPP			= 0x0001,
++	IPA_RC_IP_TABLE_FULL		= 0x0002,
++	IPA_RC_UNKNOWN_ERROR		= 0x0003,
++	IPA_RC_UNSUPPORTED_COMMAND	= 0x0004,
++	IPA_RC_DUP_IPV6_REMOTE		= 0x0008,
++	IPA_RC_DUP_IPV6_HOME		= 0x0010,
++	IPA_RC_UNREGISTERED_ADDR	= 0x0011,
++	IPA_RC_NO_ID_AVAILABLE		= 0x0012,
++	IPA_RC_ID_NOT_FOUND		= 0x0013,
++	IPA_RC_INVALID_IP_VERSION	= 0x0020,
++	IPA_RC_LAN_FRAME_MISMATCH	= 0x0040,
++	IPA_RC_L2_UNSUPPORTED_CMD	= 0x2003,
++	IPA_RC_L2_DUP_MAC		= 0x2005,
++	IPA_RC_L2_ADDR_TABLE_FULL	= 0x2006,
++	IPA_RC_L2_DUP_LAYER3_MAC	= 0x200a,
++	IPA_RC_L2_GMAC_NOT_FOUND	= 0x200b,
++	IPA_RC_L2_MAC_NOT_FOUND		= 0x2010,
++	IPA_RC_L2_INVALID_VLAN_ID	= 0x2015,
++	IPA_RC_L2_DUP_VLAN_ID		= 0x2016,
++	IPA_RC_L2_VLAN_ID_NOT_FOUND	= 0x2017,
++	IPA_RC_DATA_MISMATCH		= 0xe001,
++	IPA_RC_INVALID_MTU_SIZE		= 0xe002,
++	IPA_RC_INVALID_LANTYPE		= 0xe003,
++	IPA_RC_INVALID_LANNUM		= 0xe004,
++	IPA_RC_DUPLICATE_IP_ADDRESS	= 0xe005,
++	IPA_RC_IP_ADDR_TABLE_FULL	= 0xe006,
++	IPA_RC_LAN_PORT_STATE_ERROR	= 0xe007,
++	IPA_RC_SETIP_NO_STARTLAN	= 0xe008,
++	IPA_RC_SETIP_ALREADY_RECEIVED	= 0xe009,
++	IPA_RC_IP_ADDR_ALREADY_USED	= 0xe00a,
++	IPA_RC_MC_ADDR_NOT_FOUND	= 0xe00b,
++	IPA_RC_SETIP_INVALID_VERSION	= 0xe00d,
++	IPA_RC_UNSUPPORTED_SUBCMD	= 0xe00e,
++	IPA_RC_ARP_ASSIST_NO_ENABLE	= 0xe00f,
++	IPA_RC_PRIMARY_ALREADY_DEFINED	= 0xe010,
++	IPA_RC_SECOND_ALREADY_DEFINED	= 0xe011,
++	IPA_RC_INVALID_SETRTG_INDICATOR	= 0xe012,
++	IPA_RC_MC_ADDR_ALREADY_DEFINED	= 0xe013,
++	IPA_RC_LAN_OFFLINE		= 0xe080,
++	IPA_RC_INVALID_IP_VERSION2	= 0xf001,
++	IPA_RC_FFFF			= 0xffff
++};
++
++/* IPA function flags; each flag marks availability of respective function */
++enum qeth_ipa_funcs {
++	IPA_ARP_PROCESSING      = 0x00000001L,
++	IPA_INBOUND_CHECKSUM    = 0x00000002L,
++	IPA_OUTBOUND_CHECKSUM   = 0x00000004L,
++	IPA_IP_FRAGMENTATION    = 0x00000008L,
++	IPA_FILTERING           = 0x00000010L,
++	IPA_IPV6                = 0x00000020L,
++	IPA_MULTICASTING        = 0x00000040L,
++	IPA_IP_REASSEMBLY       = 0x00000080L,
++	IPA_QUERY_ARP_COUNTERS  = 0x00000100L,
++	IPA_QUERY_ARP_ADDR_INFO = 0x00000200L,
++	IPA_SETADAPTERPARMS     = 0x00000400L,
++	IPA_VLAN_PRIO           = 0x00000800L,
++	IPA_PASSTHRU            = 0x00001000L,
++	IPA_FLUSH_ARP_SUPPORT   = 0x00002000L,
++	IPA_FULL_VLAN           = 0x00004000L,
++	IPA_INBOUND_PASSTHRU    = 0x00008000L,
++	IPA_SOURCE_MAC          = 0x00010000L,
++	IPA_OSA_MC_ROUTER       = 0x00020000L,
++	IPA_QUERY_ARP_ASSIST	= 0x00040000L,
++	IPA_INBOUND_TSO         = 0x00080000L,
++	IPA_OUTBOUND_TSO        = 0x00100000L,
++};
++
++/* SETIP/DELIP IPA Command: ***************************************************/
++enum qeth_ipa_setdelip_flags {
++	QETH_IPA_SETDELIP_DEFAULT          = 0x00L, /* default */
++	QETH_IPA_SETIP_VIPA_FLAG           = 0x01L, /* no grat. ARP */
++	QETH_IPA_SETIP_TAKEOVER_FLAG       = 0x02L, /* nofail on grat. ARP */
++	QETH_IPA_DELIP_ADDR_2_B_TAKEN_OVER = 0x20L,
++	QETH_IPA_DELIP_VIPA_FLAG           = 0x40L,
++	QETH_IPA_DELIP_ADDR_NEEDS_SETIP    = 0x80L,
++};
++
++/* SETADAPTER IPA Command: ****************************************************/
++enum qeth_ipa_setadp_cmd {
++	IPA_SETADP_QUERY_COMMANDS_SUPPORTED	= 0x0001,
++	IPA_SETADP_ALTER_MAC_ADDRESS		= 0x0002,
++	IPA_SETADP_ADD_DELETE_GROUP_ADDRESS	= 0x0004,
++	IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR	= 0x0008,
++	IPA_SETADP_SET_ADDRESSING_MODE		= 0x0010,
++	IPA_SETADP_SET_CONFIG_PARMS		= 0x0020,
++	IPA_SETADP_SET_CONFIG_PARMS_EXTENDED	= 0x0040,
++	IPA_SETADP_SET_BROADCAST_MODE		= 0x0080,
++	IPA_SETADP_SEND_OSA_MESSAGE		= 0x0100,
++	IPA_SETADP_SET_SNMP_CONTROL		= 0x0200,
++	IPA_SETADP_QUERY_CARD_INFO		= 0x0400,
++	IPA_SETADP_SET_PROMISC_MODE		= 0x0800,
++};
++enum qeth_ipa_mac_ops {
++	CHANGE_ADDR_READ_MAC		= 0,
++	CHANGE_ADDR_REPLACE_MAC		= 1,
++	CHANGE_ADDR_ADD_MAC		= 2,
++	CHANGE_ADDR_DEL_MAC		= 4,
++	CHANGE_ADDR_RESET_MAC		= 8,
++};
++enum qeth_ipa_addr_ops {
++	CHANGE_ADDR_READ_ADDR		= 0,
++	CHANGE_ADDR_ADD_ADDR		= 1,
++	CHANGE_ADDR_DEL_ADDR		= 2,
++	CHANGE_ADDR_FLUSH_ADDR_TABLE	= 4,
++};
++enum qeth_ipa_promisc_modes {
++	SET_PROMISC_MODE_OFF		= 0,
++	SET_PROMISC_MODE_ON		= 1,
++};
++
++/* (SET)DELIP(M) IPA stuff ***************************************************/
++struct qeth_ipacmd_setdelip4 {
++	__u8   ip_addr[4];
++	__u8   mask[4];
++	__u32  flags;
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_setdelip6 {
++	__u8   ip_addr[16];
++	__u8   mask[16];
++	__u32  flags;
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_setdelipm {
++	__u8 mac[6];
++	__u8 padding[2];
++	__u8 ip6[12];
++	__u8 ip4[4];
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_layer2setdelmac {
++	__u32 mac_length;
++	__u8 mac[6];
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_layer2setdelvlan {
++	__u16 vlan_id;
++} __attribute__ ((packed));
++
++
++struct qeth_ipacmd_setassparms_hdr {
++	__u32 assist_no;
++	__u16 length;
++	__u16 command_code;
++	__u16 return_code;
++	__u8 number_of_replies;
++	__u8 seq_no;
++} __attribute__((packed));
++
++struct qeth_arp_query_data {
++	__u16 request_bits;
++	__u16 reply_bits;
++	__u32 no_entries;
++	char data;
++} __attribute__((packed));
++
++/* used as parameter for arp_query reply */
++struct qeth_arp_query_info {
++	__u32 udata_len;
++	__u16 mask_bits;
++	__u32 udata_offset;
++	__u32 no_entries;
++	char *udata;
++};
++
++/* SETASSPARMS IPA Command: */
++struct qeth_ipacmd_setassparms {
++	struct qeth_ipacmd_setassparms_hdr hdr;
++	union {
++		__u32 flags_32bit;
++		struct qeth_arp_cache_entry add_arp_entry;
++		struct qeth_arp_query_data query_arp;
++		__u8 ip[16];
++	} data;
++} __attribute__ ((packed));
++
++
++/* SETRTG IPA Command:    ****************************************************/
++struct qeth_set_routing {
++	__u8 type;
++};
++
++/* SETADAPTERPARMS IPA Command:    *******************************************/
++struct qeth_query_cmds_supp {
++	__u32 no_lantypes_supp;
++	__u8 lan_type;
++	__u8 reserved1[3];
++	__u32 supported_cmds;
++	__u8 reserved2[8];
++} __attribute__ ((packed));
++
++struct qeth_change_addr {
++	__u32 cmd;
++	__u32 addr_size;
++	__u32 no_macs;
++	__u8 addr[OSA_ADDR_LEN];
++} __attribute__ ((packed));
++
++
++struct qeth_snmp_cmd {
++	__u8  token[16];
++	__u32 request;
++	__u32 interface;
++	__u32 returncode;
++	__u32 firmwarelevel;
++	__u32 seqno;
++	__u8  data;
++} __attribute__ ((packed));
++
++struct qeth_snmp_ureq_hdr {
++	__u32   data_len;
++	__u32   req_len;
++	__u32   reserved1;
++	__u32   reserved2;
++} __attribute__ ((packed));
++
++struct qeth_snmp_ureq {
++	struct qeth_snmp_ureq_hdr hdr;
++	struct qeth_snmp_cmd cmd;
++} __attribute__((packed));
++
++struct qeth_ipacmd_setadpparms_hdr {
++	__u32 supp_hw_cmds;
++	__u32 reserved1;
++	__u16 cmdlength;
++	__u16 reserved2;
++	__u32 command_code;
++	__u16 return_code;
++	__u8  used_total;
++	__u8  seq_no;
++	__u32 reserved3;
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_setadpparms {
++	struct qeth_ipacmd_setadpparms_hdr hdr;
++	union {
++		struct qeth_query_cmds_supp query_cmds_supp;
++		struct qeth_change_addr change_addr;
++		struct qeth_snmp_cmd snmp;
++		__u32 mode;
++	} data;
++} __attribute__ ((packed));
++
++/* CREATE_ADDR IPA Command:    ***********************************************/
++struct qeth_create_destroy_address {
++	__u8 unique_id[8];
++} __attribute__ ((packed));
++
++/* Header for each IPA command */
++struct qeth_ipacmd_hdr {
++	__u8   command;
++	__u8   initiator;
++	__u16  seqno;
++	__u16  return_code;
++	__u8   adapter_type;
++	__u8   rel_adapter_no;
++	__u8   prim_version_no;
++	__u8   param_count;
++	__u16  prot_version;
++	__u32  ipa_supported;
++	__u32  ipa_enabled;
++} __attribute__ ((packed));
++
++/* The IPA command itself */
++struct qeth_ipa_cmd {
++	struct qeth_ipacmd_hdr hdr;
++	union {
++		struct qeth_ipacmd_setdelip4		setdelip4;
++		struct qeth_ipacmd_setdelip6		setdelip6;
++		struct qeth_ipacmd_setdelipm		setdelipm;
++		struct qeth_ipacmd_setassparms		setassparms;
++		struct qeth_ipacmd_layer2setdelmac	setdelmac;
++		struct qeth_ipacmd_layer2setdelvlan	setdelvlan;
++		struct qeth_create_destroy_address	create_destroy_addr;
++		struct qeth_ipacmd_setadpparms		setadapterparms;
++		struct qeth_set_routing			setrtg;
++	} data;
++} __attribute__ ((packed));
++
++/*
++ * special command for ARP processing.
++ * this is not included in setassparms command before, because we get
++ * problem with the size of struct qeth_ipacmd_setassparms otherwise
++ */
++enum qeth_ipa_arp_return_codes {
++	QETH_IPA_ARP_RC_SUCCESS      = 0x0000,
++	QETH_IPA_ARP_RC_FAILED       = 0x0001,
++	QETH_IPA_ARP_RC_NOTSUPP      = 0x0002,
++	QETH_IPA_ARP_RC_OUT_OF_RANGE = 0x0003,
++	QETH_IPA_ARP_RC_Q_NOTSUPP    = 0x0004,
++	QETH_IPA_ARP_RC_Q_NO_DATA    = 0x0008,
++};
++
++
++extern char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
++extern char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
++
++#define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
++			       sizeof(struct qeth_ipacmd_setassparms_hdr))
++#define QETH_IPA_ARP_DATA_POS(buffer) (buffer + IPA_PDU_HEADER_SIZE + \
++				       QETH_SETASS_BASE_LEN)
++#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
++			      sizeof(struct qeth_ipacmd_setadpparms_hdr))
++#define QETH_SNMP_SETADP_CMDLENGTH 16
++
++#define QETH_ARP_DATA_SIZE 3968
++#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
++/* Helper functions */
++#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
++			   (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
++
++/*****************************************************************************/
++/* END OF   IP Assist related definitions                                    */
++/*****************************************************************************/
++
++
++extern unsigned char WRITE_CCW[];
++extern unsigned char READ_CCW[];
++
++extern unsigned char CM_ENABLE[];
++#define CM_ENABLE_SIZE 0x63
++#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer + 0x2c)
++#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer + 0x53)
++#define QETH_CM_ENABLE_USER_DATA(buffer) (buffer + 0x5b)
++
++#define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) \
++		(PDU_ENCAPSULATION(buffer) + 0x13)
++
++
++extern unsigned char CM_SETUP[];
++#define CM_SETUP_SIZE 0x64
++#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
++#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
++#define QETH_CM_SETUP_FILTER_TOKEN(buffer) (buffer + 0x5a)
++
++#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) \
++		(PDU_ENCAPSULATION(buffer) + 0x1a)
++
++extern unsigned char ULP_ENABLE[];
++#define ULP_ENABLE_SIZE 0x6b
++#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer + 0x61)
++#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer + 0x2c)
++#define QETH_ULP_ENABLE_FILTER_TOKEN(buffer) (buffer + 0x53)
++#define QETH_ULP_ENABLE_PORTNAME_AND_LL(buffer) (buffer + 0x62)
++#define QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer) \
++		(PDU_ENCAPSULATION(buffer) + 0x13)
++#define QETH_ULP_ENABLE_RESP_MAX_MTU(buffer) \
++		(PDU_ENCAPSULATION(buffer) + 0x1f)
++#define QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer) \
++		(PDU_ENCAPSULATION(buffer) + 0x17)
++#define QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer) \
++		(PDU_ENCAPSULATION(buffer) + 0x2b)
++/* Layer 2 defintions */
++#define QETH_PROT_LAYER2 0x08
++#define QETH_PROT_TCPIP  0x03
++#define QETH_PROT_OSN2   0x0a
++#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer + 0x50)
++#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer + 0x19)
++
++extern unsigned char ULP_SETUP[];
++#define ULP_SETUP_SIZE 0x6c
++#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
++#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
++#define QETH_ULP_SETUP_FILTER_TOKEN(buffer) (buffer + 0x5a)
++#define QETH_ULP_SETUP_CUA(buffer) (buffer + 0x68)
++#define QETH_ULP_SETUP_REAL_DEVADDR(buffer) (buffer + 0x6a)
++
++#define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) \
++		(PDU_ENCAPSULATION(buffer) + 0x1a)
++
++
++extern unsigned char DM_ACT[];
++#define DM_ACT_SIZE 0x55
++#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer + 0x2c)
++#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer + 0x51)
++
++
++
++#define QETH_TRANSPORT_HEADER_SEQ_NO(buffer) (buffer + 4)
++#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer + 0x1c)
++#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer + 0x20)
++
++extern unsigned char IDX_ACTIVATE_READ[];
++extern unsigned char IDX_ACTIVATE_WRITE[];
++
++#define IDX_ACTIVATE_SIZE	0x22
++#define QETH_IDX_ACT_PNO(buffer) (buffer+0x0b)
++#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer + 0x0c)
++#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b] & 0x80)
++#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer + 0x10)
++#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer + 0x16)
++#define QETH_IDX_ACT_QDIO_DEV_CUA(buffer) (buffer + 0x1e)
++#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer + 0x20)
++#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08] & 3) == 2)
++#define QETH_IDX_REPLY_LEVEL(buffer) (buffer + 0x12)
++#define QETH_IDX_ACT_CAUSE_CODE(buffer) (buffer)[0x09]
++
++#define PDU_ENCAPSULATION(buffer) \
++	(buffer + *(buffer + (*(buffer + 0x0b)) + \
++	 *(buffer + *(buffer + 0x0b) + 0x11) + 0x07))
++
++#define IS_IPA(buffer) \
++	((buffer) && \
++	 (*(buffer + ((*(buffer + 0x0b)) + 4)) == 0xc1))
++
++#define ADDR_FRAME_TYPE_DIX 1
++#define ADDR_FRAME_TYPE_802_3 2
++#define ADDR_FRAME_TYPE_TR_WITHOUT_SR 0x10
++#define ADDR_FRAME_TYPE_TR_WITH_SR 0x20
++
++#endif
+diff --git a/drivers/s390/net/qeth_core_offl.c b/drivers/s390/net/qeth_core_offl.c
+new file mode 100644
+index 0000000..822df83
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_offl.c
+@@ -0,0 +1,701 @@
++/*
++ *  drivers/s390/net/qeth_core_offl.c
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/errno.h>
++#include <linux/ip.h>
++#include <linux/inetdevice.h>
++#include <linux/netdevice.h>
++#include <linux/kernel.h>
++#include <linux/tcp.h>
++#include <net/tcp.h>
++#include <linux/skbuff.h>
++
++#include <net/ip.h>
++#include <net/ip6_checksum.h>
++
++#include "qeth_core.h"
++#include "qeth_core_mpc.h"
++#include "qeth_core_offl.h"
++
++int qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue,
++		struct qeth_eddp_context *ctx)
++{
++	int index = queue->next_buf_to_fill;
++	int elements_needed = ctx->num_elements;
++	int elements_in_buffer;
++	int skbs_in_buffer;
++	int buffers_needed = 0;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpcbfc");
++	while (elements_needed > 0) {
++		buffers_needed++;
++		if (atomic_read(&queue->bufs[index].state) !=
++				QETH_QDIO_BUF_EMPTY)
++			return -EBUSY;
++
++		elements_in_buffer = QETH_MAX_BUFFER_ELEMENTS(queue->card) -
++				     queue->bufs[index].next_element_to_fill;
++		skbs_in_buffer = elements_in_buffer / ctx->elements_per_skb;
++		elements_needed -= skbs_in_buffer * ctx->elements_per_skb;
++		index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
++	}
++	return buffers_needed;
++}
++
++static void qeth_eddp_free_context(struct qeth_eddp_context *ctx)
++{
++	int i;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpfctx");
++	for (i = 0; i < ctx->num_pages; ++i)
++		free_page((unsigned long)ctx->pages[i]);
++	kfree(ctx->pages);
++	kfree(ctx->elements);
++	kfree(ctx);
++}
++
++
++static void qeth_eddp_get_context(struct qeth_eddp_context *ctx)
++{
++	atomic_inc(&ctx->refcnt);
++}
++
++void qeth_eddp_put_context(struct qeth_eddp_context *ctx)
++{
++	if (atomic_dec_return(&ctx->refcnt) == 0)
++		qeth_eddp_free_context(ctx);
++}
++EXPORT_SYMBOL_GPL(qeth_eddp_put_context);
++
++void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
++{
++	struct qeth_eddp_context_reference *ref;
++
++	QETH_DBF_TEXT(TRACE, 6, "eddprctx");
++	while (!list_empty(&buf->ctx_list)) {
++		ref = list_entry(buf->ctx_list.next,
++				 struct qeth_eddp_context_reference, list);
++		qeth_eddp_put_context(ref->ctx);
++		list_del(&ref->list);
++		kfree(ref);
++	}
++}
++
++static int qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf,
++		struct qeth_eddp_context *ctx)
++{
++	struct qeth_eddp_context_reference *ref;
++
++	QETH_DBF_TEXT(TRACE, 6, "eddprfcx");
++	ref = kmalloc(sizeof(struct qeth_eddp_context_reference), GFP_ATOMIC);
++	if (ref == NULL)
++		return -ENOMEM;
++	qeth_eddp_get_context(ctx);
++	ref->ctx = ctx;
++	list_add_tail(&ref->list, &buf->ctx_list);
++	return 0;
++}
++
++int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
++		struct qeth_eddp_context *ctx, int index)
++{
++	struct qeth_qdio_out_buffer *buf = NULL;
++	struct qdio_buffer *buffer;
++	int elements = ctx->num_elements;
++	int element = 0;
++	int flush_cnt = 0;
++	int must_refcnt = 1;
++	int i;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpfibu");
++	while (elements > 0) {
++		buf = &queue->bufs[index];
++		if (atomic_read(&buf->state) != QETH_QDIO_BUF_EMPTY) {
++			/* normally this should not happen since we checked for
++			 * available elements in qeth_check_elements_for_context
++			 */
++			if (element == 0)
++				return -EBUSY;
++			else {
++				PRINT_WARN("could only partially fill eddp "
++					   "buffer!\n");
++				goto out;
++			}
++		}
++		/* check if the whole next skb fits into current buffer */
++		if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
++					buf->next_element_to_fill)
++				< ctx->elements_per_skb){
++			/* no -> go to next buffer */
++			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++			index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
++			flush_cnt++;
++			/* new buffer, so we have to add ctx to buffer'ctx_list
++			 * and increment ctx's refcnt */
++			must_refcnt = 1;
++			continue;
++		}
++		if (must_refcnt) {
++			must_refcnt = 0;
++			if (qeth_eddp_buf_ref_context(buf, ctx)) {
++				PRINT_WARN("no memory to create eddp context "
++					   "reference\n");
++				goto out_check;
++			}
++		}
++		buffer = buf->buffer;
++		/* fill one skb into buffer */
++		for (i = 0; i < ctx->elements_per_skb; ++i) {
++			if (ctx->elements[element].length != 0) {
++				buffer->element[buf->next_element_to_fill].
++				addr = ctx->elements[element].addr;
++				buffer->element[buf->next_element_to_fill].
++				length = ctx->elements[element].length;
++				buffer->element[buf->next_element_to_fill].
++				flags = ctx->elements[element].flags;
++				buf->next_element_to_fill++;
++			}
++			element++;
++			elements--;
++		}
++	}
++out_check:
++	if (!queue->do_pack) {
++		QETH_DBF_TEXT(TRACE, 6, "fillbfnp");
++		/* set state to PRIMED -> will be flushed */
++		if (buf->next_element_to_fill > 0) {
++			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++			flush_cnt++;
++		}
++	} else {
++		if (queue->card->options.performance_stats)
++			queue->card->perf_stats.skbs_sent_pack++;
++		QETH_DBF_TEXT(TRACE, 6, "fillbfpa");
++		if (buf->next_element_to_fill >=
++				QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
++			/*
++			 * packed buffer if full -> set state PRIMED
++			 * -> will be flushed
++			 */
++			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++			flush_cnt++;
++		}
++	}
++out:
++	return flush_cnt;
++}
++
++static void qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
++		struct qeth_eddp_data *eddp, int data_len)
++{
++	u8 *page;
++	int page_remainder;
++	int page_offset;
++	int pkt_len;
++	struct qeth_eddp_element *element;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpcrsh");
++	page = ctx->pages[ctx->offset >> PAGE_SHIFT];
++	page_offset = ctx->offset % PAGE_SIZE;
++	element = &ctx->elements[ctx->num_elements];
++	pkt_len = eddp->nhl + eddp->thl + data_len;
++	/* FIXME: layer2 and VLAN !!! */
++	if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
++		pkt_len += ETH_HLEN;
++	if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
++		pkt_len += VLAN_HLEN;
++	/* does complete packet fit in current page ? */
++	page_remainder = PAGE_SIZE - page_offset;
++	if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)) {
++		/* no -> go to start of next page */
++		ctx->offset += page_remainder;
++		page = ctx->pages[ctx->offset >> PAGE_SHIFT];
++		page_offset = 0;
++	}
++	memcpy(page + page_offset, &eddp->qh, sizeof(struct qeth_hdr));
++	element->addr = page + page_offset;
++	element->length = sizeof(struct qeth_hdr);
++	ctx->offset += sizeof(struct qeth_hdr);
++	page_offset += sizeof(struct qeth_hdr);
++	/* add mac header (?) */
++	if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
++		memcpy(page + page_offset, &eddp->mac, ETH_HLEN);
++		element->length += ETH_HLEN;
++		ctx->offset += ETH_HLEN;
++		page_offset += ETH_HLEN;
++	}
++	/* add VLAN tag */
++	if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
++		memcpy(page + page_offset, &eddp->vlan, VLAN_HLEN);
++		element->length += VLAN_HLEN;
++		ctx->offset += VLAN_HLEN;
++		page_offset += VLAN_HLEN;
++	}
++	/* add network header */
++	memcpy(page + page_offset, (u8 *)&eddp->nh, eddp->nhl);
++	element->length += eddp->nhl;
++	eddp->nh_in_ctx = page + page_offset;
++	ctx->offset += eddp->nhl;
++	page_offset += eddp->nhl;
++	/* add transport header */
++	memcpy(page + page_offset, (u8 *)&eddp->th, eddp->thl);
++	element->length += eddp->thl;
++	eddp->th_in_ctx = page + page_offset;
++	ctx->offset += eddp->thl;
++}
++
++static void qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp,
++		int len, __wsum *hcsum)
++{
++	struct skb_frag_struct *frag;
++	int left_in_frag;
++	int copy_len;
++	u8 *src;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpcdtc");
++	if (skb_shinfo(eddp->skb)->nr_frags == 0) {
++		skb_copy_from_linear_data_offset(eddp->skb, eddp->skb_offset,
++						 dst, len);
++		*hcsum = csum_partial(eddp->skb->data + eddp->skb_offset, len,
++				      *hcsum);
++		eddp->skb_offset += len;
++	} else {
++		while (len > 0) {
++			if (eddp->frag < 0) {
++				/* we're in skb->data */
++				left_in_frag = (eddp->skb->len -
++						eddp->skb->data_len)
++						- eddp->skb_offset;
++				src = eddp->skb->data + eddp->skb_offset;
++			} else {
++				frag = &skb_shinfo(eddp->skb)->frags[
++					eddp->frag];
++				left_in_frag = frag->size - eddp->frag_offset;
++				src = (u8 *)((page_to_pfn(frag->page) <<
++					PAGE_SHIFT) + frag->page_offset +
++					eddp->frag_offset);
++			}
++			if (left_in_frag <= 0) {
++				eddp->frag++;
++				eddp->frag_offset = 0;
++				continue;
++			}
++			copy_len = min(left_in_frag, len);
++			memcpy(dst, src, copy_len);
++			*hcsum = csum_partial(src, copy_len, *hcsum);
++			dst += copy_len;
++			eddp->frag_offset += copy_len;
++			eddp->skb_offset += copy_len;
++			len -= copy_len;
++		}
++	}
++}
++
++static void qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
++		struct qeth_eddp_data *eddp, int data_len, __wsum hcsum)
++{
++	u8 *page;
++	int page_remainder;
++	int page_offset;
++	struct qeth_eddp_element *element;
++	int first_lap = 1;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpcsdt");
++	page = ctx->pages[ctx->offset >> PAGE_SHIFT];
++	page_offset = ctx->offset % PAGE_SIZE;
++	element = &ctx->elements[ctx->num_elements];
++	while (data_len) {
++		page_remainder = PAGE_SIZE - page_offset;
++		if (page_remainder < data_len) {
++			qeth_eddp_copy_data_tcp(page + page_offset, eddp,
++						page_remainder, &hcsum);
++			element->length += page_remainder;
++			if (first_lap)
++				element->flags = SBAL_FLAGS_FIRST_FRAG;
++			else
++				element->flags = SBAL_FLAGS_MIDDLE_FRAG;
++			ctx->num_elements++;
++			element++;
++			data_len -= page_remainder;
++			ctx->offset += page_remainder;
++			page = ctx->pages[ctx->offset >> PAGE_SHIFT];
++			page_offset = 0;
++			element->addr = page + page_offset;
++		} else {
++			qeth_eddp_copy_data_tcp(page + page_offset, eddp,
++						data_len, &hcsum);
++			element->length += data_len;
++			if (!first_lap)
++				element->flags = SBAL_FLAGS_LAST_FRAG;
++			ctx->num_elements++;
++			ctx->offset += data_len;
++			data_len = 0;
++		}
++		first_lap = 0;
++	}
++	((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum);
++}
++
++static __wsum qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp,
++		int data_len)
++{
++	__wsum phcsum; /* pseudo header checksum */
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpckt4");
++	eddp->th.tcp.h.check = 0;
++	/* compute pseudo header checksum */
++	phcsum = csum_tcpudp_nofold(eddp->nh.ip4.h.saddr, eddp->nh.ip4.h.daddr,
++				    eddp->thl + data_len, IPPROTO_TCP, 0);
++	/* compute checksum of tcp header */
++	return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum);
++}
++
++static __wsum qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp,
++		int data_len)
++{
++	__be32 proto;
++	__wsum phcsum; /* pseudo header checksum */
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpckt6");
++	eddp->th.tcp.h.check = 0;
++	/* compute pseudo header checksum */
++	phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.saddr,
++			      sizeof(struct in6_addr), 0);
++	phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.daddr,
++			      sizeof(struct in6_addr), phcsum);
++	proto = htonl(IPPROTO_TCP);
++	phcsum = csum_partial((u8 *)&proto, sizeof(u32), phcsum);
++	return phcsum;
++}
++
++static struct qeth_eddp_data *qeth_eddp_create_eddp_data(struct qeth_hdr *qh,
++		u8 *nh, u8 nhl, u8 *th, u8 thl)
++{
++	struct qeth_eddp_data *eddp;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpcrda");
++	eddp = kzalloc(sizeof(struct qeth_eddp_data), GFP_ATOMIC);
++	if (eddp) {
++		eddp->nhl = nhl;
++		eddp->thl = thl;
++		memcpy(&eddp->qh, qh, sizeof(struct qeth_hdr));
++		memcpy(&eddp->nh, nh, nhl);
++		memcpy(&eddp->th, th, thl);
++		eddp->frag = -1; /* initially we're in skb->data */
++	}
++	return eddp;
++}
++
++static void __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
++		struct qeth_eddp_data *eddp)
++{
++	struct tcphdr *tcph;
++	int data_len;
++	__wsum hcsum;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpftcp");
++	eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
++	if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
++		eddp->skb_offset += sizeof(struct ethhdr);
++		if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
++			eddp->skb_offset += VLAN_HLEN;
++	}
++	tcph = tcp_hdr(eddp->skb);
++	while (eddp->skb_offset < eddp->skb->len) {
++		data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
++			       (int)(eddp->skb->len - eddp->skb_offset));
++		/* prepare qdio hdr */
++		if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
++			eddp->qh.hdr.l2.pkt_length = data_len + ETH_HLEN +
++						     eddp->nhl + eddp->thl;
++			if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
++				eddp->qh.hdr.l2.pkt_length += VLAN_HLEN;
++		} else
++			eddp->qh.hdr.l3.length = data_len + eddp->nhl +
++						 eddp->thl;
++		/* prepare ip hdr */
++		if (eddp->skb->protocol == htons(ETH_P_IP)) {
++			eddp->nh.ip4.h.tot_len = htons(data_len + eddp->nhl +
++						 eddp->thl);
++			eddp->nh.ip4.h.check = 0;
++			eddp->nh.ip4.h.check =
++				ip_fast_csum((u8 *)&eddp->nh.ip4.h,
++						eddp->nh.ip4.h.ihl);
++		} else
++			eddp->nh.ip6.h.payload_len = htons(data_len +
++								eddp->thl);
++		/* prepare tcp hdr */
++		if (data_len == (eddp->skb->len - eddp->skb_offset)) {
++			/* last segment -> set FIN and PSH flags */
++			eddp->th.tcp.h.fin = tcph->fin;
++			eddp->th.tcp.h.psh = tcph->psh;
++		}
++		if (eddp->skb->protocol == htons(ETH_P_IP))
++			hcsum = qeth_eddp_check_tcp4_hdr(eddp, data_len);
++		else
++			hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
++		/* fill the next segment into the context */
++		qeth_eddp_create_segment_hdrs(ctx, eddp, data_len);
++		qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
++		if (eddp->skb_offset >= eddp->skb->len)
++			break;
++		/* prepare headers for next round */
++		if (eddp->skb->protocol == htons(ETH_P_IP))
++			eddp->nh.ip4.h.id = htons(ntohs(eddp->nh.ip4.h.id) + 1);
++		eddp->th.tcp.h.seq = htonl(ntohl(eddp->th.tcp.h.seq) +
++			data_len);
++	}
++}
++
++static int qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
++		struct sk_buff *skb, struct qeth_hdr *qhdr)
++{
++	struct qeth_eddp_data *eddp = NULL;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpficx");
++	/* create our segmentation headers and copy original headers */
++	if (skb->protocol == htons(ETH_P_IP))
++		eddp = qeth_eddp_create_eddp_data(qhdr,
++						  skb_network_header(skb),
++						  ip_hdrlen(skb),
++						  skb_transport_header(skb),
++						  tcp_hdrlen(skb));
++	else
++		eddp = qeth_eddp_create_eddp_data(qhdr,
++						  skb_network_header(skb),
++						  sizeof(struct ipv6hdr),
++						  skb_transport_header(skb),
++						  tcp_hdrlen(skb));
++
++	if (eddp == NULL) {
++		QETH_DBF_TEXT(TRACE, 2, "eddpfcnm");
++		return -ENOMEM;
++	}
++	if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
++		skb_set_mac_header(skb, sizeof(struct qeth_hdr));
++		memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
++		if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
++			eddp->vlan[0] = skb->protocol;
++			eddp->vlan[1] = htons(vlan_tx_tag_get(skb));
++		}
++	}
++	/* the next flags will only be set on the last segment */
++	eddp->th.tcp.h.fin = 0;
++	eddp->th.tcp.h.psh = 0;
++	eddp->skb = skb;
++	/* begin segmentation and fill context */
++	__qeth_eddp_fill_context_tcp(ctx, eddp);
++	kfree(eddp);
++	return 0;
++}
++
++static void qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx,
++		struct sk_buff *skb, int hdr_len)
++{
++	int skbs_per_page;
++
++	QETH_DBF_TEXT(TRACE, 5, "eddpcanp");
++	/* can we put multiple skbs in one page? */
++	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
++	if (skbs_per_page > 1) {
++		ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
++				 skbs_per_page + 1;
++		ctx->elements_per_skb = 1;
++	} else {
++		/* no -> how many elements per skb? */
++		ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
++				     PAGE_SIZE) >> PAGE_SHIFT;
++		ctx->num_pages = ctx->elements_per_skb *
++				 (skb_shinfo(skb)->gso_segs + 1);
++	}
++	ctx->num_elements = ctx->elements_per_skb *
++			    (skb_shinfo(skb)->gso_segs + 1);
++}
++
++static struct qeth_eddp_context *qeth_eddp_create_context_generic(
++		struct qeth_card *card, struct sk_buff *skb, int hdr_len)
++{
++	struct qeth_eddp_context *ctx = NULL;
++	u8 *addr;
++	int i;
++
++	QETH_DBF_TEXT(TRACE, 5, "creddpcg");
++	/* create the context and allocate pages */
++	ctx = kzalloc(sizeof(struct qeth_eddp_context), GFP_ATOMIC);
++	if (ctx == NULL) {
++		QETH_DBF_TEXT(TRACE, 2, "ceddpcn1");
++		return NULL;
++	}
++	ctx->type = QETH_LARGE_SEND_EDDP;
++	qeth_eddp_calc_num_pages(ctx, skb, hdr_len);
++	if (ctx->elements_per_skb > QETH_MAX_BUFFER_ELEMENTS(card)) {
++		QETH_DBF_TEXT(TRACE, 2, "ceddpcis");
++		kfree(ctx);
++		return NULL;
++	}
++	ctx->pages = kcalloc(ctx->num_pages, sizeof(u8 *), GFP_ATOMIC);
++	if (ctx->pages == NULL) {
++		QETH_DBF_TEXT(TRACE, 2, "ceddpcn2");
++		kfree(ctx);
++		return NULL;
++	}
++	for (i = 0; i < ctx->num_pages; ++i) {
++		addr = (u8 *)get_zeroed_page(GFP_ATOMIC);
++		if (addr == NULL) {
++			QETH_DBF_TEXT(TRACE, 2, "ceddpcn3");
++			ctx->num_pages = i;
++			qeth_eddp_free_context(ctx);
++			return NULL;
++		}
++		ctx->pages[i] = addr;
++	}
++	ctx->elements = kcalloc(ctx->num_elements,
++				sizeof(struct qeth_eddp_element), GFP_ATOMIC);
++	if (ctx->elements == NULL) {
++		QETH_DBF_TEXT(TRACE, 2, "ceddpcn4");
++		qeth_eddp_free_context(ctx);
++		return NULL;
++	}
++	/* reset num_elements; will be incremented again in fill_buffer to
++	 * reflect number of actually used elements */
++	ctx->num_elements = 0;
++	return ctx;
++}
++
++static struct qeth_eddp_context *qeth_eddp_create_context_tcp(
++		struct qeth_card *card, struct sk_buff *skb,
++		struct qeth_hdr *qhdr)
++{
++	struct qeth_eddp_context *ctx = NULL;
++
++	QETH_DBF_TEXT(TRACE, 5, "creddpct");
++	if (skb->protocol == htons(ETH_P_IP))
++		ctx = qeth_eddp_create_context_generic(card, skb,
++						(sizeof(struct qeth_hdr) +
++						ip_hdrlen(skb) +
++						tcp_hdrlen(skb)));
++	else if (skb->protocol == htons(ETH_P_IPV6))
++		ctx = qeth_eddp_create_context_generic(card, skb,
++			sizeof(struct qeth_hdr) + sizeof(struct ipv6hdr) +
++			tcp_hdrlen(skb));
++	else
++		QETH_DBF_TEXT(TRACE, 2, "cetcpinv");
++
++	if (ctx == NULL) {
++		QETH_DBF_TEXT(TRACE, 2, "creddpnl");
++		return NULL;
++	}
++	if (qeth_eddp_fill_context_tcp(ctx, skb, qhdr)) {
++		QETH_DBF_TEXT(TRACE, 2, "ceddptfe");
++		qeth_eddp_free_context(ctx);
++		return NULL;
++	}
++	atomic_set(&ctx->refcnt, 1);
++	return ctx;
++}
++
++struct qeth_eddp_context *qeth_eddp_create_context(struct qeth_card *card,
++		struct sk_buff *skb, struct qeth_hdr *qhdr,
++		unsigned char sk_protocol)
++{
++	QETH_DBF_TEXT(TRACE, 5, "creddpc");
++	switch (sk_protocol) {
++	case IPPROTO_TCP:
++		return qeth_eddp_create_context_tcp(card, skb, qhdr);
++	default:
++		QETH_DBF_TEXT(TRACE, 2, "eddpinvp");
++	}
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(qeth_eddp_create_context);
++
++void qeth_tso_fill_header(struct qeth_card *card, struct qeth_hdr *qhdr,
++		struct sk_buff *skb)
++{
++	struct qeth_hdr_tso *hdr = (struct qeth_hdr_tso *)qhdr;
++	struct tcphdr *tcph = tcp_hdr(skb);
++	struct iphdr *iph = ip_hdr(skb);
++	struct ipv6hdr *ip6h = ipv6_hdr(skb);
++
++	QETH_DBF_TEXT(TRACE, 5, "tsofhdr");
++
++	/*fix header to TSO values ...*/
++	hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
++	/*set values which are fix for the first approach ...*/
++	hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
++	hdr->ext.imb_hdr_no  = 1;
++	hdr->ext.hdr_type    = 1;
++	hdr->ext.hdr_version = 1;
++	hdr->ext.hdr_len     = 28;
++	/*insert non-fix values */
++	hdr->ext.mss = skb_shinfo(skb)->gso_size;
++	hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
++	hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
++				       sizeof(struct qeth_hdr_tso));
++	tcph->check = 0;
++	if (skb->protocol == ETH_P_IPV6) {
++		ip6h->payload_len = 0;
++		tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
++					       0, IPPROTO_TCP, 0);
++	} else {
++		/*OSA want us to set these values ...*/
++		tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
++					 0, IPPROTO_TCP, 0);
++		iph->tot_len = 0;
++		iph->check = 0;
++	}
++}
++EXPORT_SYMBOL_GPL(qeth_tso_fill_header);
++
++void qeth_tx_csum(struct sk_buff *skb)
++{
++	int tlen;
++	if (skb->protocol == htons(ETH_P_IP)) {
++		tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2);
++		switch (ip_hdr(skb)->protocol) {
++		case IPPROTO_TCP:
++			tcp_hdr(skb)->check = 0;
++			tcp_hdr(skb)->check = csum_tcpudp_magic(
++				ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
++				tlen, ip_hdr(skb)->protocol,
++				skb_checksum(skb, skb_transport_offset(skb),
++					tlen, 0));
++			break;
++		case IPPROTO_UDP:
++			udp_hdr(skb)->check = 0;
++			udp_hdr(skb)->check = csum_tcpudp_magic(
++				ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
++				tlen, ip_hdr(skb)->protocol,
++				skb_checksum(skb, skb_transport_offset(skb),
++					tlen, 0));
++			break;
++		}
++	} else if (skb->protocol == htons(ETH_P_IPV6)) {
++		switch (ipv6_hdr(skb)->nexthdr) {
++		case IPPROTO_TCP:
++			tcp_hdr(skb)->check = 0;
++			tcp_hdr(skb)->check = csum_ipv6_magic(
++				&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
++				ipv6_hdr(skb)->payload_len,
++				ipv6_hdr(skb)->nexthdr,
++				skb_checksum(skb, skb_transport_offset(skb),
++					ipv6_hdr(skb)->payload_len, 0));
++			break;
++		case IPPROTO_UDP:
++			udp_hdr(skb)->check = 0;
++			udp_hdr(skb)->check = csum_ipv6_magic(
++				&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
++				ipv6_hdr(skb)->payload_len,
++				ipv6_hdr(skb)->nexthdr,
++				skb_checksum(skb, skb_transport_offset(skb),
++					ipv6_hdr(skb)->payload_len, 0));
++			break;
++		}
++	}
++}
++EXPORT_SYMBOL_GPL(qeth_tx_csum);
+diff --git a/drivers/s390/net/qeth_core_offl.h b/drivers/s390/net/qeth_core_offl.h
+new file mode 100644
+index 0000000..86bf7df
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_offl.h
+@@ -0,0 +1,76 @@
++/*
++ *  drivers/s390/net/qeth_core_offl.h
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#ifndef __QETH_CORE_OFFL_H__
++#define __QETH_CORE_OFFL_H__
++
++struct qeth_eddp_element {
++	u32 flags;
++	u32 length;
++	void *addr;
++};
++
++struct qeth_eddp_context {
++	atomic_t refcnt;
++	enum qeth_large_send_types type;
++	int num_pages;			    /* # of allocated pages */
++	u8 **pages;			    /* pointers to pages */
++	int offset;			    /* offset in ctx during creation */
++	int num_elements;		    /* # of required 'SBALEs' */
++	struct qeth_eddp_element *elements; /* array of 'SBALEs' */
++	int elements_per_skb;		    /* # of 'SBALEs' per skb **/
++};
++
++struct qeth_eddp_context_reference {
++	struct list_head list;
++	struct qeth_eddp_context *ctx;
++};
++
++struct qeth_eddp_data {
++	struct qeth_hdr qh;
++	struct ethhdr mac;
++	__be16 vlan[2];
++	union {
++		struct {
++			struct iphdr h;
++			u8 options[40];
++		} ip4;
++		struct {
++			struct ipv6hdr h;
++		} ip6;
++	} nh;
++	u8 nhl;
++	void *nh_in_ctx;	/* address of nh within the ctx */
++	union {
++		struct {
++			struct tcphdr h;
++			u8 options[40];
++		} tcp;
++	} th;
++	u8 thl;
++	void *th_in_ctx;	/* address of th within the ctx */
++	struct sk_buff *skb;
++	int skb_offset;
++	int frag;
++	int frag_offset;
++} __attribute__ ((packed));
++
++extern struct qeth_eddp_context *qeth_eddp_create_context(struct qeth_card *,
++		 struct sk_buff *, struct qeth_hdr *, unsigned char);
++extern void qeth_eddp_put_context(struct qeth_eddp_context *);
++extern int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *,
++		struct qeth_eddp_context *, int);
++extern void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *);
++extern int qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *,
++		struct qeth_eddp_context *);
++
++void qeth_tso_fill_header(struct qeth_card *, struct qeth_hdr *,
++		struct sk_buff *);
++void qeth_tx_csum(struct sk_buff *skb);
++
++#endif /* __QETH_CORE_EDDP_H__ */
+diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
+new file mode 100644
+index 0000000..08a50f0
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_sys.c
+@@ -0,0 +1,651 @@
++/*
++ *  drivers/s390/net/qeth_core_sys.c
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ *		 Frank Pavlic <fpavlic at de.ibm.com>,
++ *		 Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/list.h>
++#include <linux/rwsem.h>
++#include <asm/ebcdic.h>
++
++#include "qeth_core.h"
++
++static ssize_t qeth_dev_state_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	if (!card)
++		return -EINVAL;
++
++	switch (card->state) {
++	case CARD_STATE_DOWN:
++		return sprintf(buf, "DOWN\n");
++	case CARD_STATE_HARDSETUP:
++		return sprintf(buf, "HARDSETUP\n");
++	case CARD_STATE_SOFTSETUP:
++		return sprintf(buf, "SOFTSETUP\n");
++	case CARD_STATE_UP:
++		if (card->lan_online)
++		return sprintf(buf, "UP (LAN ONLINE)\n");
++		else
++			return sprintf(buf, "UP (LAN OFFLINE)\n");
++	case CARD_STATE_RECOVER:
++		return sprintf(buf, "RECOVER\n");
++	default:
++		return sprintf(buf, "UNKNOWN\n");
++	}
++}
++
++static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
++
++static ssize_t qeth_dev_chpid_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%02X\n", card->info.chpid);
++}
++
++static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
++
++static ssize_t qeth_dev_if_name_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	if (!card)
++		return -EINVAL;
++	return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
++}
++
++static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
++
++static ssize_t qeth_dev_card_type_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
++}
++
++static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
++
++static inline const char *qeth_get_bufsize_str(struct qeth_card *card)
++{
++	if (card->qdio.in_buf_size == 16384)
++		return "16k";
++	else if (card->qdio.in_buf_size == 24576)
++		return "24k";
++	else if (card->qdio.in_buf_size == 32768)
++		return "32k";
++	else if (card->qdio.in_buf_size == 40960)
++		return "40k";
++	else
++		return "64k";
++}
++
++static ssize_t qeth_dev_inbuf_size_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%s\n", qeth_get_bufsize_str(card));
++}
++
++static DEVICE_ATTR(inbuf_size, 0444, qeth_dev_inbuf_size_show, NULL);
++
++static ssize_t qeth_dev_portno_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%i\n", card->info.portno);
++}
++
++static ssize_t qeth_dev_portno_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++	unsigned int portno;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	portno = simple_strtoul(buf, &tmp, 16);
++	if (portno > QETH_MAX_PORTNO) {
++		PRINT_WARN("portno 0x%X is out of range\n", portno);
++		return -EINVAL;
++	}
++
++	card->info.portno = portno;
++	return count;
++}
++
++static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
++
++static ssize_t qeth_dev_portname_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char portname[9] = {0, };
++
++	if (!card)
++		return -EINVAL;
++
++	if (card->info.portname_required) {
++		memcpy(portname, card->info.portname + 1, 8);
++		EBCASC(portname, 8);
++		return sprintf(buf, "%s\n", portname);
++	} else
++		return sprintf(buf, "no portname required\n");
++}
++
++static ssize_t qeth_dev_portname_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++	int i;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	tmp = strsep((char **) &buf, "\n");
++	if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
++		return -EINVAL;
++
++	card->info.portname[0] = strlen(tmp);
++	/* for beauty reasons */
++	for (i = 1; i < 9; i++)
++		card->info.portname[i] = ' ';
++	strcpy(card->info.portname + 1, tmp);
++	ASCEBC(card->info.portname + 1, 8);
++
++	return count;
++}
++
++static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
++		qeth_dev_portname_store);
++
++static ssize_t qeth_dev_prioqing_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	switch (card->qdio.do_prio_queueing) {
++	case QETH_PRIO_Q_ING_PREC:
++		return sprintf(buf, "%s\n", "by precedence");
++	case QETH_PRIO_Q_ING_TOS:
++		return sprintf(buf, "%s\n", "by type of service");
++	default:
++		return sprintf(buf, "always queue %i\n",
++			       card->qdio.default_out_queue);
++	}
++}
++
++static ssize_t qeth_dev_prioqing_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	/* check if 1920 devices are supported ,
++	 * if though we have to permit priority queueing
++	 */
++	if (card->qdio.no_out_queues == 1) {
++		PRINT_WARN("Priority queueing disabled due "
++			   "to hardware limitations!\n");
++		card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
++		return -EPERM;
++	}
++
++	tmp = strsep((char **) &buf, "\n");
++	if (!strcmp(tmp, "prio_queueing_prec"))
++		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
++	else if (!strcmp(tmp, "prio_queueing_tos"))
++		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
++	else if (!strcmp(tmp, "no_prio_queueing:0")) {
++		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++		card->qdio.default_out_queue = 0;
++	} else if (!strcmp(tmp, "no_prio_queueing:1")) {
++		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++		card->qdio.default_out_queue = 1;
++	} else if (!strcmp(tmp, "no_prio_queueing:2")) {
++		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++		card->qdio.default_out_queue = 2;
++	} else if (!strcmp(tmp, "no_prio_queueing:3")) {
++		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++		card->qdio.default_out_queue = 3;
++	} else if (!strcmp(tmp, "no_prio_queueing")) {
++		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++		card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
++	} else {
++		PRINT_WARN("Unknown queueing type '%s'\n", tmp);
++		return -EINVAL;
++	}
++	return count;
++}
++
++static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
++		qeth_dev_prioqing_store);
++
++static ssize_t qeth_dev_bufcnt_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
++}
++
++static ssize_t qeth_dev_bufcnt_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++	int cnt, old_cnt;
++	int rc;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	old_cnt = card->qdio.in_buf_pool.buf_count;
++	cnt = simple_strtoul(buf, &tmp, 10);
++	cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
++		((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
++	if (old_cnt != cnt) {
++		rc = qeth_realloc_buffer_pool(card, cnt);
++		if (rc)
++			PRINT_WARN("Error (%d) while setting "
++				   "buffer count.\n", rc);
++	}
++	return count;
++}
++
++static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
++		qeth_dev_bufcnt_store);
++
++static ssize_t qeth_dev_recover_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++	int i;
++
++	if (!card)
++		return -EINVAL;
++
++	if (card->state != CARD_STATE_UP)
++		return -EPERM;
++
++	i = simple_strtoul(buf, &tmp, 16);
++	if (i == 1)
++		qeth_schedule_recovery(card);
++
++	return count;
++}
++
++static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
++
++static ssize_t qeth_dev_performance_stats_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
++}
++
++static ssize_t qeth_dev_performance_stats_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++	int i;
++
++	if (!card)
++		return -EINVAL;
++
++	i = simple_strtoul(buf, &tmp, 16);
++	if ((i == 0) || (i == 1)) {
++		if (i == card->options.performance_stats)
++			return count;
++		card->options.performance_stats = i;
++		if (i == 0)
++			memset(&card->perf_stats, 0,
++				sizeof(struct qeth_perf_stats));
++		card->perf_stats.initial_rx_packets = card->stats.rx_packets;
++		card->perf_stats.initial_tx_packets = card->stats.tx_packets;
++	} else {
++		PRINT_WARN("performance_stats: write 0 or 1 to this file!\n");
++		return -EINVAL;
++	}
++	return count;
++}
++
++static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
++		   qeth_dev_performance_stats_store);
++
++static ssize_t qeth_dev_layer2_show(struct device *dev,
++		struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
++}
++
++static ssize_t qeth_dev_layer2_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++	int i, rc;
++	enum qeth_discipline_id newdis;
++
++	if (!card)
++		return -EINVAL;
++
++	if (((card->state != CARD_STATE_DOWN) &&
++	     (card->state != CARD_STATE_RECOVER)))
++		return -EPERM;
++
++	i = simple_strtoul(buf, &tmp, 16);
++	switch (i) {
++	case 0:
++		newdis = QETH_DISCIPLINE_LAYER3;
++		break;
++	case 1:
++		newdis = QETH_DISCIPLINE_LAYER2;
++		break;
++	default:
++		PRINT_WARN("layer2: write 0 or 1 to this file!\n");
++		return -EINVAL;
++	}
++
++	if (card->options.layer2 == newdis) {
++		return count;
++	} else {
++		if (card->discipline.ccwgdriver) {
++			card->discipline.ccwgdriver->remove(card->gdev);
++			qeth_core_free_discipline(card);
++		}
++	}
++
++	rc = qeth_core_load_discipline(card, newdis);
++	if (rc)
++		return rc;
++
++	rc = card->discipline.ccwgdriver->probe(card->gdev);
++	if (rc)
++		return rc;
++	return count;
++}
++
++static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
++		   qeth_dev_layer2_store);
++
++static ssize_t qeth_dev_large_send_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	switch (card->options.large_send) {
++	case QETH_LARGE_SEND_NO:
++		return sprintf(buf, "%s\n", "no");
++	case QETH_LARGE_SEND_EDDP:
++		return sprintf(buf, "%s\n", "EDDP");
++	case QETH_LARGE_SEND_TSO:
++		return sprintf(buf, "%s\n", "TSO");
++	default:
++		return sprintf(buf, "%s\n", "N/A");
++	}
++}
++
++static ssize_t qeth_dev_large_send_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	enum qeth_large_send_types type;
++	int rc = 0;
++	char *tmp;
++
++	if (!card)
++		return -EINVAL;
++	tmp = strsep((char **) &buf, "\n");
++	if (!strcmp(tmp, "no")) {
++		type = QETH_LARGE_SEND_NO;
++	} else if (!strcmp(tmp, "EDDP")) {
++		type = QETH_LARGE_SEND_EDDP;
++	} else if (!strcmp(tmp, "TSO")) {
++		type = QETH_LARGE_SEND_TSO;
++	} else {
++		PRINT_WARN("large_send: invalid mode %s!\n", tmp);
++		return -EINVAL;
++	}
++	if (card->options.large_send == type)
++		return count;
++	rc = qeth_set_large_send(card, type);
++	if (rc)
++		return rc;
++	return count;
++}
++
++static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
++		   qeth_dev_large_send_store);
++
++static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value)
++{
++
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%i\n", value);
++}
++
++static ssize_t qeth_dev_blkt_store(struct qeth_card *card,
++		const char *buf, size_t count, int *value, int max_value)
++{
++	char *tmp;
++	int i;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	i = simple_strtoul(buf, &tmp, 10);
++	if (i <= max_value) {
++		*value = i;
++	} else {
++		PRINT_WARN("blkt total time: write values between"
++			   " 0 and %d to this file!\n", max_value);
++		return -EINVAL;
++	}
++	return count;
++}
++
++static ssize_t qeth_dev_blkt_total_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
++}
++
++static ssize_t qeth_dev_blkt_total_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	return qeth_dev_blkt_store(card, buf, count,
++				   &card->info.blkt.time_total, 1000);
++}
++
++
++
++static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
++		   qeth_dev_blkt_total_store);
++
++static ssize_t qeth_dev_blkt_inter_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
++}
++
++static ssize_t qeth_dev_blkt_inter_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	return qeth_dev_blkt_store(card, buf, count,
++				   &card->info.blkt.inter_packet, 100);
++}
++
++static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
++		   qeth_dev_blkt_inter_store);
++
++static ssize_t qeth_dev_blkt_inter_jumbo_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	return qeth_dev_blkt_show(buf, card,
++				  card->info.blkt.inter_packet_jumbo);
++}
++
++static ssize_t qeth_dev_blkt_inter_jumbo_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	return qeth_dev_blkt_store(card, buf, count,
++				   &card->info.blkt.inter_packet_jumbo, 100);
++}
++
++static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
++		   qeth_dev_blkt_inter_jumbo_store);
++
++static struct attribute *qeth_blkt_device_attrs[] = {
++	&dev_attr_total.attr,
++	&dev_attr_inter.attr,
++	&dev_attr_inter_jumbo.attr,
++	NULL,
++};
++
++static struct attribute_group qeth_device_blkt_group = {
++	.name = "blkt",
++	.attrs = qeth_blkt_device_attrs,
++};
++
++static struct attribute *qeth_device_attrs[] = {
++	&dev_attr_state.attr,
++	&dev_attr_chpid.attr,
++	&dev_attr_if_name.attr,
++	&dev_attr_card_type.attr,
++	&dev_attr_inbuf_size.attr,
++	&dev_attr_portno.attr,
++	&dev_attr_portname.attr,
++	&dev_attr_priority_queueing.attr,
++	&dev_attr_buffer_count.attr,
++	&dev_attr_recover.attr,
++	&dev_attr_performance_stats.attr,
++	&dev_attr_layer2.attr,
++	&dev_attr_large_send.attr,
++	NULL,
++};
++
++static struct attribute_group qeth_device_attr_group = {
++	.attrs = qeth_device_attrs,
++};
++
++static struct attribute *qeth_osn_device_attrs[] = {
++	&dev_attr_state.attr,
++	&dev_attr_chpid.attr,
++	&dev_attr_if_name.attr,
++	&dev_attr_card_type.attr,
++	&dev_attr_buffer_count.attr,
++	&dev_attr_recover.attr,
++	NULL,
++};
++
++static struct attribute_group qeth_osn_device_attr_group = {
++	.attrs = qeth_osn_device_attrs,
++};
++
++int qeth_core_create_device_attributes(struct device *dev)
++{
++	int ret;
++	ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group);
++	if (ret)
++		return ret;
++	ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group);
++	if (ret)
++		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
++
++	return 0;
++}
++
++void qeth_core_remove_device_attributes(struct device *dev)
++{
++	sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
++	sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
++}
++
++int qeth_core_create_osn_attributes(struct device *dev)
++{
++	return sysfs_create_group(&dev->kobj, &qeth_osn_device_attr_group);
++}
++
++void qeth_core_remove_osn_attributes(struct device *dev)
++{
++	sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
++	return;
++}
+diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
+deleted file mode 100644
+index e3c268c..0000000
+--- a/drivers/s390/net/qeth_eddp.c
++++ /dev/null
+@@ -1,634 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_eddp.c
+- *
+- * Enhanced Device Driver Packing (EDDP) support for the qeth driver.
+- *
+- * Copyright 2004 IBM Corporation
+- *
+- *    Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#include <linux/errno.h>
+-#include <linux/ip.h>
+-#include <linux/inetdevice.h>
+-#include <linux/netdevice.h>
+-#include <linux/kernel.h>
+-#include <linux/tcp.h>
+-#include <net/tcp.h>
+-#include <linux/skbuff.h>
+-
+-#include <net/ip.h>
+-
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_eddp.h"
+-
+-int
+-qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue,
+-				    struct qeth_eddp_context *ctx)
+-{
+-	int index = queue->next_buf_to_fill;
+-	int elements_needed = ctx->num_elements;
+-	int elements_in_buffer;
+-	int skbs_in_buffer;
+-	int buffers_needed = 0;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpcbfc");
+-	while(elements_needed > 0) {
+-		buffers_needed++;
+-		if (atomic_read(&queue->bufs[index].state) !=
+-				QETH_QDIO_BUF_EMPTY)
+-			return -EBUSY;
+-
+-		elements_in_buffer = QETH_MAX_BUFFER_ELEMENTS(queue->card) -
+-				     queue->bufs[index].next_element_to_fill;
+-		skbs_in_buffer = elements_in_buffer / ctx->elements_per_skb;
+-		elements_needed -= skbs_in_buffer * ctx->elements_per_skb;
+-		index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
+-	}
+-	return buffers_needed;
+-}
+-
+-static void
+-qeth_eddp_free_context(struct qeth_eddp_context *ctx)
+-{
+-	int i;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpfctx");
+-	for (i = 0; i < ctx->num_pages; ++i)
+-		free_page((unsigned long)ctx->pages[i]);
+-	kfree(ctx->pages);
+-	kfree(ctx->elements);
+-	kfree(ctx);
+-}
+-
+-
+-static inline void
+-qeth_eddp_get_context(struct qeth_eddp_context *ctx)
+-{
+-	atomic_inc(&ctx->refcnt);
+-}
+-
+-void
+-qeth_eddp_put_context(struct qeth_eddp_context *ctx)
+-{
+-	if (atomic_dec_return(&ctx->refcnt) == 0)
+-		qeth_eddp_free_context(ctx);
+-}
+-
+-void
+-qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
+-{
+-	struct qeth_eddp_context_reference *ref;
+-
+-	QETH_DBF_TEXT(trace, 6, "eddprctx");
+-	while (!list_empty(&buf->ctx_list)){
+-		ref = list_entry(buf->ctx_list.next,
+-				 struct qeth_eddp_context_reference, list);
+-		qeth_eddp_put_context(ref->ctx);
+-		list_del(&ref->list);
+-		kfree(ref);
+-	}
+-}
+-
+-static int
+-qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf,
+-			  struct qeth_eddp_context *ctx)
+-{
+-	struct qeth_eddp_context_reference *ref;
+-
+-	QETH_DBF_TEXT(trace, 6, "eddprfcx");
+-	ref = kmalloc(sizeof(struct qeth_eddp_context_reference), GFP_ATOMIC);
+-	if (ref == NULL)
+-		return -ENOMEM;
+-	qeth_eddp_get_context(ctx);
+-	ref->ctx = ctx;
+-	list_add_tail(&ref->list, &buf->ctx_list);
+-	return 0;
+-}
+-
+-int
+-qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
+-		      struct qeth_eddp_context *ctx,
+-		      int index)
+-{
+-	struct qeth_qdio_out_buffer *buf = NULL;
+-	struct qdio_buffer *buffer;
+-	int elements = ctx->num_elements;
+-	int element = 0;
+-	int flush_cnt = 0;
+-	int must_refcnt = 1;
+-	int i;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpfibu");
+-	while (elements > 0) {
+-		buf = &queue->bufs[index];
+-		if (atomic_read(&buf->state) != QETH_QDIO_BUF_EMPTY){
+-			/* normally this should not happen since we checked for
+-			 * available elements in qeth_check_elements_for_context
+-			 */
+-			if (element == 0)
+-				return -EBUSY;
+-			else {
+-				PRINT_WARN("could only partially fill eddp "
+-					   "buffer!\n");
+-				goto out;
+-			}
+-		}
+-		/* check if the whole next skb fits into current buffer */
+-		if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
+-					buf->next_element_to_fill)
+-				< ctx->elements_per_skb){
+-			/* no -> go to next buffer */
+-			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+-			index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
+-			flush_cnt++;
+-			/* new buffer, so we have to add ctx to buffer'ctx_list
+-			 * and increment ctx's refcnt */
+-			must_refcnt = 1;
+-			continue;
+-		}
+-		if (must_refcnt){
+-			must_refcnt = 0;
+-			if (qeth_eddp_buf_ref_context(buf, ctx)){
+-				PRINT_WARN("no memory to create eddp context "
+-					   "reference\n");
+-				goto out_check;
+-			}
+-		}
+-		buffer = buf->buffer;
+-		/* fill one skb into buffer */
+-		for (i = 0; i < ctx->elements_per_skb; ++i){
+-			if (ctx->elements[element].length != 0) {
+-				buffer->element[buf->next_element_to_fill].
+-				addr = ctx->elements[element].addr;
+-				buffer->element[buf->next_element_to_fill].
+-				length = ctx->elements[element].length;
+-				buffer->element[buf->next_element_to_fill].
+-				flags = ctx->elements[element].flags;
+-				buf->next_element_to_fill++;
+-			}
+-			element++;
+-			elements--;
+-		}
+-	}
+-out_check:
+-	if (!queue->do_pack) {
+-		QETH_DBF_TEXT(trace, 6, "fillbfnp");
+-		/* set state to PRIMED -> will be flushed */
+-		if (buf->next_element_to_fill > 0){
+-			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+-			flush_cnt++;
+-		}
+-	} else {
+-		if (queue->card->options.performance_stats)
+-			queue->card->perf_stats.skbs_sent_pack++;
+-		QETH_DBF_TEXT(trace, 6, "fillbfpa");
+-		if (buf->next_element_to_fill >=
+-				QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
+-			/*
+-			 * packed buffer if full -> set state PRIMED
+-			 * -> will be flushed
+-			 */
+-			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+-			flush_cnt++;
+-		}
+-	}
+-out:
+-	return flush_cnt;
+-}
+-
+-static void
+-qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
+-			      struct qeth_eddp_data *eddp, int data_len)
+-{
+-	u8 *page;
+-	int page_remainder;
+-	int page_offset;
+-	int pkt_len;
+-	struct qeth_eddp_element *element;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpcrsh");
+-	page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+-	page_offset = ctx->offset % PAGE_SIZE;
+-	element = &ctx->elements[ctx->num_elements];
+-	pkt_len = eddp->nhl + eddp->thl + data_len;
+-	/* FIXME: layer2 and VLAN !!! */
+-	if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
+-		pkt_len += ETH_HLEN;
+-	if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+-		pkt_len += VLAN_HLEN;
+-	/* does complete packet fit in current page ? */
+-	page_remainder = PAGE_SIZE - page_offset;
+-	if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){
+-		/* no -> go to start of next page */
+-		ctx->offset += page_remainder;
+-		page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+-		page_offset = 0;
+-	}
+-	memcpy(page + page_offset, &eddp->qh, sizeof(struct qeth_hdr));
+-	element->addr = page + page_offset;
+-	element->length = sizeof(struct qeth_hdr);
+-	ctx->offset += sizeof(struct qeth_hdr);
+-	page_offset += sizeof(struct qeth_hdr);
+-	/* add mac header (?) */
+-	if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
+-		memcpy(page + page_offset, &eddp->mac, ETH_HLEN);
+-		element->length += ETH_HLEN;
+-		ctx->offset += ETH_HLEN;
+-		page_offset += ETH_HLEN;
+-	}
+-	/* add VLAN tag */
+-	if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)){
+-		memcpy(page + page_offset, &eddp->vlan, VLAN_HLEN);
+-		element->length += VLAN_HLEN;
+-		ctx->offset += VLAN_HLEN;
+-		page_offset += VLAN_HLEN;
+-	}
+-	/* add network header */
+-	memcpy(page + page_offset, (u8 *)&eddp->nh, eddp->nhl);
+-	element->length += eddp->nhl;
+-	eddp->nh_in_ctx = page + page_offset;
+-	ctx->offset += eddp->nhl;
+-	page_offset += eddp->nhl;
+-	/* add transport header */
+-	memcpy(page + page_offset, (u8 *)&eddp->th, eddp->thl);
+-	element->length += eddp->thl;
+-	eddp->th_in_ctx = page + page_offset;
+-	ctx->offset += eddp->thl;
+-}
+-
+-static void
+-qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
+-			__wsum *hcsum)
+-{
+-	struct skb_frag_struct *frag;
+-	int left_in_frag;
+-	int copy_len;
+-	u8 *src;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpcdtc");
+-	if (skb_shinfo(eddp->skb)->nr_frags == 0) {
+-		skb_copy_from_linear_data_offset(eddp->skb, eddp->skb_offset,
+-						 dst, len);
+-		*hcsum = csum_partial(eddp->skb->data + eddp->skb_offset, len,
+-				      *hcsum);
+-		eddp->skb_offset += len;
+-	} else {
+-		while (len > 0) {
+-			if (eddp->frag < 0) {
+-				/* we're in skb->data */
+-				left_in_frag = (eddp->skb->len - eddp->skb->data_len)
+-						- eddp->skb_offset;
+-				src = eddp->skb->data + eddp->skb_offset;
+-			} else {
+-				frag = &skb_shinfo(eddp->skb)->
+-					frags[eddp->frag];
+-				left_in_frag = frag->size - eddp->frag_offset;
+-				src = (u8 *)(
+-					(page_to_pfn(frag->page) << PAGE_SHIFT)+
+-					frag->page_offset + eddp->frag_offset);
+-			}
+-			if (left_in_frag <= 0) {
+-				eddp->frag++;
+-				eddp->frag_offset = 0;
+-				continue;
+-			}
+-			copy_len = min(left_in_frag, len);
+-			memcpy(dst, src, copy_len);
+-			*hcsum = csum_partial(src, copy_len, *hcsum);
+-			dst += copy_len;
+-			eddp->frag_offset += copy_len;
+-			eddp->skb_offset += copy_len;
+-			len -= copy_len;
+-		}
+-	}
+-}
+-
+-static void
+-qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
+-				  struct qeth_eddp_data *eddp, int data_len,
+-				  __wsum hcsum)
+-{
+-	u8 *page;
+-	int page_remainder;
+-	int page_offset;
+-	struct qeth_eddp_element *element;
+-	int first_lap = 1;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpcsdt");
+-	page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+-	page_offset = ctx->offset % PAGE_SIZE;
+-	element = &ctx->elements[ctx->num_elements];
+-	while (data_len){
+-		page_remainder = PAGE_SIZE - page_offset;
+-		if (page_remainder < data_len){
+-			qeth_eddp_copy_data_tcp(page + page_offset, eddp,
+-						page_remainder, &hcsum);
+-			element->length += page_remainder;
+-			if (first_lap)
+-				element->flags = SBAL_FLAGS_FIRST_FRAG;
+-			else
+-				element->flags = SBAL_FLAGS_MIDDLE_FRAG;
+-			ctx->num_elements++;
+-			element++;
+-			data_len -= page_remainder;
+-			ctx->offset += page_remainder;
+-			page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+-			page_offset = 0;
+-			element->addr = page + page_offset;
+-		} else {
+-			qeth_eddp_copy_data_tcp(page + page_offset, eddp,
+-						data_len, &hcsum);
+-			element->length += data_len;
+-			if (!first_lap)
+-				element->flags = SBAL_FLAGS_LAST_FRAG;
+-			ctx->num_elements++;
+-			ctx->offset += data_len;
+-			data_len = 0;
+-		}
+-		first_lap = 0;
+-	}
+-	((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum);
+-}
+-
+-static __wsum
+-qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len)
+-{
+-	__wsum phcsum; /* pseudo header checksum */
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpckt4");
+-	eddp->th.tcp.h.check = 0;
+-	/* compute pseudo header checksum */
+-	phcsum = csum_tcpudp_nofold(eddp->nh.ip4.h.saddr, eddp->nh.ip4.h.daddr,
+-				    eddp->thl + data_len, IPPROTO_TCP, 0);
+-	/* compute checksum of tcp header */
+-	return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum);
+-}
+-
+-static __wsum
+-qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len)
+-{
+-	__be32 proto;
+-	__wsum phcsum; /* pseudo header checksum */
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpckt6");
+-	eddp->th.tcp.h.check = 0;
+-	/* compute pseudo header checksum */
+-	phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.saddr,
+-			      sizeof(struct in6_addr), 0);
+-	phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.daddr,
+-			      sizeof(struct in6_addr), phcsum);
+-	proto = htonl(IPPROTO_TCP);
+-	phcsum = csum_partial((u8 *)&proto, sizeof(u32), phcsum);
+-	return phcsum;
+-}
+-
+-static struct qeth_eddp_data *
+-qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl)
+-{
+-	struct qeth_eddp_data *eddp;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpcrda");
+-	eddp = kzalloc(sizeof(struct qeth_eddp_data), GFP_ATOMIC);
+-	if (eddp){
+-		eddp->nhl = nhl;
+-		eddp->thl = thl;
+-		memcpy(&eddp->qh, qh, sizeof(struct qeth_hdr));
+-		memcpy(&eddp->nh, nh, nhl);
+-		memcpy(&eddp->th, th, thl);
+-		eddp->frag = -1; /* initially we're in skb->data */
+-	}
+-	return eddp;
+-}
+-
+-static void
+-__qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
+-			     struct qeth_eddp_data *eddp)
+-{
+-	struct tcphdr *tcph;
+-	int data_len;
+-	__wsum hcsum;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpftcp");
+-	eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
+-       if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+-               eddp->skb_offset += sizeof(struct ethhdr);
+-#ifdef CONFIG_QETH_VLAN
+-               if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+-                       eddp->skb_offset += VLAN_HLEN;
+-#endif /* CONFIG_QETH_VLAN */
+-       }
+-	tcph = tcp_hdr(eddp->skb);
+-	while (eddp->skb_offset < eddp->skb->len) {
+-		data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
+-			       (int)(eddp->skb->len - eddp->skb_offset));
+-		/* prepare qdio hdr */
+-		if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
+-			eddp->qh.hdr.l2.pkt_length = data_len + ETH_HLEN +
+-						     eddp->nhl + eddp->thl;
+-#ifdef CONFIG_QETH_VLAN
+-			if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+-				eddp->qh.hdr.l2.pkt_length += VLAN_HLEN;
+-#endif /* CONFIG_QETH_VLAN */
+-		} else
+-			eddp->qh.hdr.l3.length = data_len + eddp->nhl +
+-						 eddp->thl;
+-		/* prepare ip hdr */
+-		if (eddp->skb->protocol == htons(ETH_P_IP)){
+-			eddp->nh.ip4.h.tot_len = htons(data_len + eddp->nhl +
+-						 eddp->thl);
+-			eddp->nh.ip4.h.check = 0;
+-			eddp->nh.ip4.h.check =
+-				ip_fast_csum((u8 *)&eddp->nh.ip4.h,
+-						eddp->nh.ip4.h.ihl);
+-		} else
+-			eddp->nh.ip6.h.payload_len = htons(data_len + eddp->thl);
+-		/* prepare tcp hdr */
+-		if (data_len == (eddp->skb->len - eddp->skb_offset)){
+-			/* last segment -> set FIN and PSH flags */
+-			eddp->th.tcp.h.fin = tcph->fin;
+-			eddp->th.tcp.h.psh = tcph->psh;
+-		}
+-		if (eddp->skb->protocol == htons(ETH_P_IP))
+-			hcsum = qeth_eddp_check_tcp4_hdr(eddp, data_len);
+-		else
+-			hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
+-		/* fill the next segment into the context */
+-		qeth_eddp_create_segment_hdrs(ctx, eddp, data_len);
+-		qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
+-		if (eddp->skb_offset >= eddp->skb->len)
+-			break;
+-		/* prepare headers for next round */
+-		if (eddp->skb->protocol == htons(ETH_P_IP))
+-			eddp->nh.ip4.h.id = htons(ntohs(eddp->nh.ip4.h.id) + 1);
+-		eddp->th.tcp.h.seq = htonl(ntohl(eddp->th.tcp.h.seq) + data_len);
+-	}
+-}
+-
+-static int
+-qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
+-			   struct sk_buff *skb, struct qeth_hdr *qhdr)
+-{
+-	struct qeth_eddp_data *eddp = NULL;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpficx");
+-	/* create our segmentation headers and copy original headers */
+-	if (skb->protocol == htons(ETH_P_IP))
+-		eddp = qeth_eddp_create_eddp_data(qhdr,
+-						  skb_network_header(skb),
+-						  ip_hdrlen(skb),
+-						  skb_transport_header(skb),
+-						  tcp_hdrlen(skb));
+-	else
+-		eddp = qeth_eddp_create_eddp_data(qhdr,
+-						  skb_network_header(skb),
+-						  sizeof(struct ipv6hdr),
+-						  skb_transport_header(skb),
+-						  tcp_hdrlen(skb));
+-
+-	if (eddp == NULL) {
+-		QETH_DBF_TEXT(trace, 2, "eddpfcnm");
+-		return -ENOMEM;
+-	}
+-	if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+-		skb_set_mac_header(skb, sizeof(struct qeth_hdr));
+-		memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
+-#ifdef CONFIG_QETH_VLAN
+-		if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
+-			eddp->vlan[0] = skb->protocol;
+-			eddp->vlan[1] = htons(vlan_tx_tag_get(skb));
+-		}
+-#endif /* CONFIG_QETH_VLAN */
+-	}
+-	/* the next flags will only be set on the last segment */
+-	eddp->th.tcp.h.fin = 0;
+-	eddp->th.tcp.h.psh = 0;
+-	eddp->skb = skb;
+-	/* begin segmentation and fill context */
+-	__qeth_eddp_fill_context_tcp(ctx, eddp);
+-	kfree(eddp);
+-	return 0;
+-}
+-
+-static void
+-qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
+-			 int hdr_len)
+-{
+-	int skbs_per_page;
+-
+-	QETH_DBF_TEXT(trace, 5, "eddpcanp");
+-	/* can we put multiple skbs in one page? */
+-	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
+-	if (skbs_per_page > 1){
+-		ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
+-				 skbs_per_page + 1;
+-		ctx->elements_per_skb = 1;
+-	} else {
+-		/* no -> how many elements per skb? */
+-		ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
+-				     PAGE_SIZE) >> PAGE_SHIFT;
+-		ctx->num_pages = ctx->elements_per_skb *
+-				 (skb_shinfo(skb)->gso_segs + 1);
+-	}
+-	ctx->num_elements = ctx->elements_per_skb *
+-			    (skb_shinfo(skb)->gso_segs + 1);
+-}
+-
+-static struct qeth_eddp_context *
+-qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb,
+-				 int hdr_len)
+-{
+-	struct qeth_eddp_context *ctx = NULL;
+-	u8 *addr;
+-	int i;
+-
+-	QETH_DBF_TEXT(trace, 5, "creddpcg");
+-	/* create the context and allocate pages */
+-	ctx = kzalloc(sizeof(struct qeth_eddp_context), GFP_ATOMIC);
+-	if (ctx == NULL){
+-		QETH_DBF_TEXT(trace, 2, "ceddpcn1");
+-		return NULL;
+-	}
+-	ctx->type = QETH_LARGE_SEND_EDDP;
+-	qeth_eddp_calc_num_pages(ctx, skb, hdr_len);
+-	if (ctx->elements_per_skb > QETH_MAX_BUFFER_ELEMENTS(card)){
+-		QETH_DBF_TEXT(trace, 2, "ceddpcis");
+-		kfree(ctx);
+-		return NULL;
+-	}
+-	ctx->pages = kcalloc(ctx->num_pages, sizeof(u8 *), GFP_ATOMIC);
+-	if (ctx->pages == NULL){
+-		QETH_DBF_TEXT(trace, 2, "ceddpcn2");
+-		kfree(ctx);
+-		return NULL;
+-	}
+-	for (i = 0; i < ctx->num_pages; ++i){
+-		addr = (u8 *)__get_free_page(GFP_ATOMIC);
+-		if (addr == NULL){
+-			QETH_DBF_TEXT(trace, 2, "ceddpcn3");
+-			ctx->num_pages = i;
+-			qeth_eddp_free_context(ctx);
+-			return NULL;
+-		}
+-		memset(addr, 0, PAGE_SIZE);
+-		ctx->pages[i] = addr;
+-	}
+-	ctx->elements = kcalloc(ctx->num_elements,
+-				sizeof(struct qeth_eddp_element), GFP_ATOMIC);
+-	if (ctx->elements == NULL){
+-		QETH_DBF_TEXT(trace, 2, "ceddpcn4");
+-		qeth_eddp_free_context(ctx);
+-		return NULL;
+-	}
+-	/* reset num_elements; will be incremented again in fill_buffer to
+-	 * reflect number of actually used elements */
+-	ctx->num_elements = 0;
+-	return ctx;
+-}
+-
+-static struct qeth_eddp_context *
+-qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
+-			     struct qeth_hdr *qhdr)
+-{
+-	struct qeth_eddp_context *ctx = NULL;
+-
+-	QETH_DBF_TEXT(trace, 5, "creddpct");
+-	if (skb->protocol == htons(ETH_P_IP))
+-		ctx = qeth_eddp_create_context_generic(card, skb,
+-						       (sizeof(struct qeth_hdr) +
+-						        ip_hdrlen(skb) +
+-							tcp_hdrlen(skb)));
+-	else if (skb->protocol == htons(ETH_P_IPV6))
+-		ctx = qeth_eddp_create_context_generic(card, skb,
+-			sizeof(struct qeth_hdr) + sizeof(struct ipv6hdr) +
+-			tcp_hdrlen(skb));
+-	else
+-		QETH_DBF_TEXT(trace, 2, "cetcpinv");
+-
+-	if (ctx == NULL) {
+-		QETH_DBF_TEXT(trace, 2, "creddpnl");
+-		return NULL;
+-	}
+-	if (qeth_eddp_fill_context_tcp(ctx, skb, qhdr)){
+-		QETH_DBF_TEXT(trace, 2, "ceddptfe");
+-		qeth_eddp_free_context(ctx);
+-		return NULL;
+-	}
+-	atomic_set(&ctx->refcnt, 1);
+-	return ctx;
+-}
+-
+-struct qeth_eddp_context *
+-qeth_eddp_create_context(struct qeth_card *card, struct sk_buff *skb,
+-			 struct qeth_hdr *qhdr, unsigned char sk_protocol)
+-{
+-	QETH_DBF_TEXT(trace, 5, "creddpc");
+-	switch (sk_protocol) {
+-	case IPPROTO_TCP:
+-		return qeth_eddp_create_context_tcp(card, skb, qhdr);
+-	default:
+-		QETH_DBF_TEXT(trace, 2, "eddpinvp");
+-	}
+-	return NULL;
+-}
+diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h
+deleted file mode 100644
+index 52910c9..0000000
+--- a/drivers/s390/net/qeth_eddp.h
++++ /dev/null
+@@ -1,84 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_eddp.h
+- *
+- * Header file for qeth enhanced device driver packing.
+- *
+- * Copyright 2004 IBM Corporation
+- *
+- *    Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_EDDP_H__
+-#define __QETH_EDDP_H__
+-
+-struct qeth_eddp_element {
+-	u32 flags;
+-	u32 length;
+-	void *addr;
+-};
+-
+-struct qeth_eddp_context {
+-	atomic_t refcnt;
+-	enum qeth_large_send_types type;
+-	int num_pages;			    /* # of allocated pages */
+-	u8 **pages;			    /* pointers to pages */
+-	int offset;			    /* offset in ctx during creation */
+-	int num_elements;		    /* # of required 'SBALEs' */
+-	struct qeth_eddp_element *elements; /* array of 'SBALEs' */
+-	int elements_per_skb;		    /* # of 'SBALEs' per skb **/
+-};
+-
+-struct qeth_eddp_context_reference {
+-	struct list_head list;
+-	struct qeth_eddp_context *ctx;
+-};
+-
+-extern struct qeth_eddp_context *
+-qeth_eddp_create_context(struct qeth_card *,struct sk_buff *,
+-			 struct qeth_hdr *, unsigned char);
+-
+-extern void
+-qeth_eddp_put_context(struct qeth_eddp_context *);
+-
+-extern int
+-qeth_eddp_fill_buffer(struct qeth_qdio_out_q *,struct qeth_eddp_context *,int);
+-
+-extern void
+-qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *);
+-
+-extern int
+-qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *,
+-				    struct qeth_eddp_context *);
+-/*
+- * Data used for fragmenting a IP packet.
+- */
+-struct qeth_eddp_data {
+-	struct qeth_hdr qh;
+-	struct ethhdr mac;
+-	__be16 vlan[2];
+-	union {
+-		struct {
+-			struct iphdr h;
+-			u8 options[40];
+-		} ip4;
+-		struct {
+-			struct ipv6hdr h;
+-		} ip6;
+-	} nh;
+-	u8 nhl;
+-	void *nh_in_ctx;	/* address of nh within the ctx */
+-	union {
+-		struct {
+-			struct tcphdr h;
+-			u8 options[40];
+-		} tcp;
+-	} th;
+-	u8 thl;
+-	void *th_in_ctx;	/* address of th within the ctx */
+-	struct sk_buff *skb;
+-	int skb_offset;
+-	int frag;
+-	int frag_offset;
+-} __attribute__ ((packed));
+-
+-#endif /* __QETH_EDDP_H__ */
+diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
+deleted file mode 100644
+index 61faf05..0000000
+--- a/drivers/s390/net/qeth_fs.h
++++ /dev/null
+@@ -1,168 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_fs.h
+- *
+- * Linux on zSeries OSA Express and HiperSockets support.
+- *
+- * This header file contains definitions related to sysfs and procfs.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_FS_H__
+-#define __QETH_FS_H__
+-
+-#ifdef CONFIG_PROC_FS
+-extern int
+-qeth_create_procfs_entries(void);
+-
+-extern void
+-qeth_remove_procfs_entries(void);
+-#else
+-static inline int
+-qeth_create_procfs_entries(void)
+-{
+-	return 0;
+-}
+-
+-static inline void
+-qeth_remove_procfs_entries(void)
+-{
+-}
+-#endif /* CONFIG_PROC_FS */
+-
+-extern int
+-qeth_create_device_attributes(struct device *dev);
+-
+-extern void
+-qeth_remove_device_attributes(struct device *dev);
+-
+-extern int
+-qeth_create_device_attributes_osn(struct device *dev);
+-
+-extern void
+-qeth_remove_device_attributes_osn(struct device *dev);
+-
+-extern int
+-qeth_create_driver_attributes(void);
+-
+-extern void
+-qeth_remove_driver_attributes(void);
+-
+-/*
+- * utility functions used in qeth_proc.c and qeth_sys.c
+- */
+-
+-static inline const char *
+-qeth_get_checksum_str(struct qeth_card *card)
+-{
+-	if (card->options.checksum_type == SW_CHECKSUMMING)
+-		return "sw";
+-	else if (card->options.checksum_type == HW_CHECKSUMMING)
+-		return "hw";
+-	else
+-		return "no";
+-}
+-
+-static inline const char *
+-qeth_get_prioq_str(struct qeth_card *card, char *buf)
+-{
+-	if (card->qdio.do_prio_queueing == QETH_NO_PRIO_QUEUEING)
+-		sprintf(buf, "always_q_%i", card->qdio.default_out_queue);
+-	else
+-		strcpy(buf, (card->qdio.do_prio_queueing ==
+-					QETH_PRIO_Q_ING_PREC)?
+-				"by_prec." : "by_ToS");
+-	return buf;
+-}
+-
+-static inline const char *
+-qeth_get_bufsize_str(struct qeth_card *card)
+-{
+-	if (card->qdio.in_buf_size == 16384)
+-		return "16k";
+-	else if (card->qdio.in_buf_size == 24576)
+-		return "24k";
+-	else if (card->qdio.in_buf_size == 32768)
+-		return "32k";
+-	else if (card->qdio.in_buf_size == 40960)
+-		return "40k";
+-	else
+-		return "64k";
+-}
+-
+-static inline const char *
+-qeth_get_cardname(struct qeth_card *card)
+-{
+- 	if (card->info.guestlan) {
+- 		switch (card->info.type) {
+- 		case QETH_CARD_TYPE_OSAE:
+-			return " Guest LAN QDIO";
+- 		case QETH_CARD_TYPE_IQD:
+-			return " Guest LAN Hiper";
+-		default:
+-			return " unknown";
+- 		}
+-	} else {
+-		switch (card->info.type) {
+-		case QETH_CARD_TYPE_OSAE:
+-			return " OSD Express";
+-		case QETH_CARD_TYPE_IQD:
+-			return " HiperSockets";
+-		case QETH_CARD_TYPE_OSN:
+-			return " OSN QDIO";
+-		default:
+-			return " unknown";
+-		}
+-	}
+-	return " n/a";
+-}
+-
+-/* max length to be returned: 14 */
+-static inline const char *
+-qeth_get_cardname_short(struct qeth_card *card)
+-{
+-	if (card->info.guestlan){
+-		switch (card->info.type){
+-		case QETH_CARD_TYPE_OSAE:
+-			return "GuestLAN QDIO";
+-		case QETH_CARD_TYPE_IQD:
+-			return "GuestLAN Hiper";
+-		default:
+-			return "unknown";
+-		}
+-	} else {
+-		switch (card->info.type) {
+-		case QETH_CARD_TYPE_OSAE:
+-			switch (card->info.link_type) {
+-			case QETH_LINK_TYPE_FAST_ETH:
+-				return "OSD_100";
+-			case QETH_LINK_TYPE_HSTR:
+-				return "HSTR";
+-			case QETH_LINK_TYPE_GBIT_ETH:
+-				return "OSD_1000";
+-			case QETH_LINK_TYPE_10GBIT_ETH:
+-				return "OSD_10GIG";
+-			case QETH_LINK_TYPE_LANE_ETH100:
+-				return "OSD_FE_LANE";
+-			case QETH_LINK_TYPE_LANE_TR:
+-				return "OSD_TR_LANE";
+-			case QETH_LINK_TYPE_LANE_ETH1000:
+-				return "OSD_GbE_LANE";
+-			case QETH_LINK_TYPE_LANE:
+-				return "OSD_ATM_LANE";
+-			default:
+-				return "OSD_Express";
+-			}
+-		case QETH_CARD_TYPE_IQD:
+-			return "HiperSockets";
+-		case QETH_CARD_TYPE_OSN:
+-			return "OSN";
+-		default:
+-			return "unknown";
+-		}
+-	}
+-	return "n/a";
+-}
+-
+-#endif /* __QETH_FS_H__ */
+diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
+new file mode 100644
+index 0000000..3921d16
+--- /dev/null
++++ b/drivers/s390/net/qeth_l2_main.c
+@@ -0,0 +1,1234 @@
++/*
++ *  drivers/s390/net/qeth_l2_main.c
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ *		 Frank Pavlic <fpavlic at de.ibm.com>,
++ *		 Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/etherdevice.h>
++#include <linux/mii.h>
++#include <linux/ip.h>
++
++#include <asm/s390_rdev.h>
++
++#include "qeth_core.h"
++#include "qeth_core_offl.h"
++
++#define QETH_DBF_TXT_BUF qeth_l2_dbf_txt_buf
++static DEFINE_PER_CPU(char[256], qeth_l2_dbf_txt_buf);
++
++static int qeth_l2_set_offline(struct ccwgroup_device *);
++static int qeth_l2_stop(struct net_device *);
++static int qeth_l2_send_delmac(struct qeth_card *, __u8 *);
++static int qeth_l2_send_setdelmac(struct qeth_card *, __u8 *,
++			   enum qeth_ipa_cmds,
++			   int (*reply_cb) (struct qeth_card *,
++					    struct qeth_reply*,
++					    unsigned long));
++static void qeth_l2_set_multicast_list(struct net_device *);
++static int qeth_l2_recover(void *);
++
++static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	struct mii_ioctl_data *mii_data;
++	int rc = 0;
++
++	if (!card)
++		return -ENODEV;
++
++	if ((card->state != CARD_STATE_UP) &&
++		(card->state != CARD_STATE_SOFTSETUP))
++		return -ENODEV;
++
++	if (card->info.type == QETH_CARD_TYPE_OSN)
++		return -EPERM;
++
++	switch (cmd) {
++	case SIOC_QETH_ADP_SET_SNMP_CONTROL:
++		rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
++		break;
++	case SIOC_QETH_GET_CARD_TYPE:
++		if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
++		    !card->info.guestlan)
++			return 1;
++		return 0;
++		break;
++	case SIOCGMIIPHY:
++		mii_data = if_mii(rq);
++		mii_data->phy_id = 0;
++		break;
++	case SIOCGMIIREG:
++		mii_data = if_mii(rq);
++		if (mii_data->phy_id != 0)
++			rc = -EINVAL;
++		else
++			mii_data->val_out = qeth_mdio_read(dev,
++				mii_data->phy_id, mii_data->reg_num);
++		break;
++	default:
++		rc = -EOPNOTSUPP;
++	}
++	if (rc)
++		QETH_DBF_TEXT_(TRACE, 2, "ioce%d", rc);
++	return rc;
++}
++
++static int qeth_l2_verify_dev(struct net_device *dev)
++{
++	struct qeth_card *card;
++	unsigned long flags;
++	int rc = 0;
++
++	read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++	list_for_each_entry(card, &qeth_core_card_list.list, list) {
++		if (card->dev == dev) {
++			rc = QETH_REAL_CARD;
++			break;
++		}
++	}
++	read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++
++	return rc;
++}
++
++static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no)
++{
++	struct qeth_card *card;
++	struct net_device *ndev;
++	unsigned char *readno;
++	__u16 temp_dev_no, card_dev_no;
++	char *endp;
++	unsigned long flags;
++
++	ndev = NULL;
++	memcpy(&temp_dev_no, read_dev_no, 2);
++	read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++	list_for_each_entry(card, &qeth_core_card_list.list, list) {
++		readno = CARD_RDEV_ID(card);
++		readno += (strlen(readno) - 4);
++		card_dev_no = simple_strtoul(readno, &endp, 16);
++		if (card_dev_no == temp_dev_no) {
++			ndev = card->dev;
++			break;
++		}
++	}
++	read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++	return ndev;
++}
++
++static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card,
++				struct qeth_reply *reply,
++				unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++	__u8 *mac;
++
++	QETH_DBF_TEXT(TRACE, 2, "L2Sgmacb");
++	cmd = (struct qeth_ipa_cmd *) data;
++	mac = &cmd->data.setdelmac.mac[0];
++	/* MAC already registered, needed in couple/uncouple case */
++	if (cmd->hdr.return_code == 0x2005) {
++		PRINT_WARN("Group MAC %02x:%02x:%02x:%02x:%02x:%02x " \
++			  "already existing on %s \n",
++			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
++			  QETH_CARD_IFNAME(card));
++		cmd->hdr.return_code = 0;
++	}
++	if (cmd->hdr.return_code)
++		PRINT_ERR("Could not set group MAC " \
++			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
++			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
++			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
++	return 0;
++}
++
++static int qeth_l2_send_setgroupmac(struct qeth_card *card, __u8 *mac)
++{
++	QETH_DBF_TEXT(TRACE, 2, "L2Sgmac");
++	return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETGMAC,
++					  qeth_l2_send_setgroupmac_cb);
++}
++
++static int qeth_l2_send_delgroupmac_cb(struct qeth_card *card,
++				struct qeth_reply *reply,
++				unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++	__u8 *mac;
++
++	QETH_DBF_TEXT(TRACE, 2, "L2Dgmacb");
++	cmd = (struct qeth_ipa_cmd *) data;
++	mac = &cmd->data.setdelmac.mac[0];
++	if (cmd->hdr.return_code)
++		PRINT_ERR("Could not delete group MAC " \
++			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
++			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
++			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
++	return 0;
++}
++
++static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
++{
++	QETH_DBF_TEXT(TRACE, 2, "L2Dgmac");
++	return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELGMAC,
++					  qeth_l2_send_delgroupmac_cb);
++}
++
++static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac)
++{
++	struct qeth_mc_mac *mc;
++
++	mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC);
++
++	if (!mc) {
++		PRINT_ERR("no mem vor mc mac address\n");
++		return;
++	}
++
++	memcpy(mc->mc_addr, mac, OSA_ADDR_LEN);
++	mc->mc_addrlen = OSA_ADDR_LEN;
++
++	if (!qeth_l2_send_setgroupmac(card, mac))
++		list_add_tail(&mc->list, &card->mc_list);
++	else
++		kfree(mc);
++}
++
++static void qeth_l2_del_all_mc(struct qeth_card *card)
++{
++	struct qeth_mc_mac *mc, *tmp;
++
++	spin_lock_bh(&card->mclock);
++	list_for_each_entry_safe(mc, tmp, &card->mc_list, list) {
++		qeth_l2_send_delgroupmac(card, mc->mc_addr);
++		list_del(&mc->list);
++		kfree(mc);
++	}
++	spin_unlock_bh(&card->mclock);
++}
++
++static void qeth_l2_get_packet_type(struct qeth_card *card,
++			struct qeth_hdr *hdr, struct sk_buff *skb)
++{
++	__u16 hdr_mac;
++
++	if (!memcmp(skb->data + QETH_HEADER_SIZE,
++		    skb->dev->broadcast, 6)) {
++		/* broadcast? */
++		hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
++		return;
++	}
++	hdr_mac = *((__u16 *)skb->data);
++	/* tr multicast? */
++	switch (card->info.link_type) {
++	case QETH_LINK_TYPE_HSTR:
++	case QETH_LINK_TYPE_LANE_TR:
++		if ((hdr_mac == QETH_TR_MAC_NC) ||
++		    (hdr_mac == QETH_TR_MAC_C))
++			hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
++		else
++			hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
++		break;
++		/* eth or so multicast? */
++	default:
++		if ((hdr_mac == QETH_ETH_MAC_V4) ||
++		     (hdr_mac == QETH_ETH_MAC_V6))
++			hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
++		else
++			hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
++	}
++}
++
++static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
++			struct sk_buff *skb, int ipv, int cast_type)
++{
++	struct vlan_ethhdr *veth = (struct vlan_ethhdr *)((skb->data) +
++					QETH_HEADER_SIZE);
++
++	memset(hdr, 0, sizeof(struct qeth_hdr));
++	hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
++
++	/* set byte byte 3 to casting flags */
++	if (cast_type == RTN_MULTICAST)
++		hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
++	else if (cast_type == RTN_BROADCAST)
++		hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
++	else
++		qeth_l2_get_packet_type(card, hdr, skb);
++
++	hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
++	/* VSWITCH relies on the VLAN
++	 * information to be present in
++	 * the QDIO header */
++	if (veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
++		hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_VLAN;
++		hdr->hdr.l2.vlan_id = ntohs(veth->h_vlan_TCI);
++	}
++}
++
++static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
++			struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 2, "L2sdvcb");
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->hdr.return_code) {
++		PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
++			  "Continuing\n", cmd->data.setdelvlan.vlan_id,
++			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
++		QETH_DBF_TEXT_(TRACE, 2, "L2VL%4x", cmd->hdr.command);
++		QETH_DBF_TEXT_(TRACE, 2, "L2%s", CARD_BUS_ID(card));
++		QETH_DBF_TEXT_(TRACE, 2, "err%d", cmd->hdr.return_code);
++	}
++	return 0;
++}
++
++static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
++				enum qeth_ipa_cmds ipacmd)
++{
++	struct qeth_ipa_cmd *cmd;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT_(TRACE, 4, "L2sdv%x", ipacmd);
++	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	cmd->data.setdelvlan.vlan_id = i;
++	return qeth_send_ipa_cmd(card, iob,
++				 qeth_l2_send_setdelvlan_cb, NULL);
++}
++
++static void qeth_l2_process_vlans(struct qeth_card *card, int clear)
++{
++	struct qeth_vlan_vid *id;
++	QETH_DBF_TEXT(TRACE, 3, "L2prcvln");
++	spin_lock_bh(&card->vlanlock);
++	list_for_each_entry(id, &card->vid_list, list) {
++		if (clear)
++			qeth_l2_send_setdelvlan(card, id->vid,
++				IPA_CMD_DELVLAN);
++		else
++			qeth_l2_send_setdelvlan(card, id->vid,
++				IPA_CMD_SETVLAN);
++	}
++	spin_unlock_bh(&card->vlanlock);
++}
++
++static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	struct qeth_vlan_vid *id;
++
++	QETH_DBF_TEXT_(TRACE, 4, "aid:%d", vid);
++	id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC);
++	if (id) {
++		id->vid = vid;
++		qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
++		spin_lock_bh(&card->vlanlock);
++		list_add_tail(&id->list, &card->vid_list);
++		spin_unlock_bh(&card->vlanlock);
++	} else {
++		PRINT_ERR("no memory for vid\n");
++	}
++}
++
++static void qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
++{
++	struct qeth_vlan_vid *id, *tmpid = NULL;
++	struct qeth_card *card = netdev_priv(dev);
++
++	QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid);
++	spin_lock_bh(&card->vlanlock);
++	list_for_each_entry(id, &card->vid_list, list) {
++		if (id->vid == vid) {
++			list_del(&id->list);
++			tmpid = id;
++			break;
++		}
++	}
++	spin_unlock_bh(&card->vlanlock);
++	if (tmpid) {
++		qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
++		kfree(tmpid);
++	}
++	qeth_l2_set_multicast_list(card->dev);
++}
++
++static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
++{
++	int rc = 0;
++
++	QETH_DBF_TEXT(SETUP , 2, "stopcard");
++	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++	qeth_set_allowed_threads(card, 0, 1);
++	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
++		return -ERESTARTSYS;
++	if (card->read.state == CH_STATE_UP &&
++	    card->write.state == CH_STATE_UP &&
++	    (card->state == CARD_STATE_UP)) {
++		if (recovery_mode &&
++		    card->info.type != QETH_CARD_TYPE_OSN) {
++			qeth_l2_stop(card->dev);
++		} else {
++			rtnl_lock();
++			dev_close(card->dev);
++			rtnl_unlock();
++		}
++		if (!card->use_hard_stop) {
++			__u8 *mac = &card->dev->dev_addr[0];
++			rc = qeth_l2_send_delmac(card, mac);
++			QETH_DBF_TEXT_(SETUP, 2, "Lerr%d", rc);
++		}
++		card->state = CARD_STATE_SOFTSETUP;
++	}
++	if (card->state == CARD_STATE_SOFTSETUP) {
++		qeth_l2_process_vlans(card, 1);
++		qeth_l2_del_all_mc(card);
++		qeth_clear_ipacmd_list(card);
++		card->state = CARD_STATE_HARDSETUP;
++	}
++	if (card->state == CARD_STATE_HARDSETUP) {
++		qeth_qdio_clear_card(card, 0);
++		qeth_clear_qdio_buffers(card);
++		qeth_clear_working_pool_list(card);
++		card->state = CARD_STATE_DOWN;
++	}
++	if (card->state == CARD_STATE_DOWN) {
++		qeth_clear_cmd_buffers(&card->read);
++		qeth_clear_cmd_buffers(&card->write);
++	}
++	card->use_hard_stop = 0;
++	return rc;
++}
++
++static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
++			    struct qeth_qdio_buffer *buf, int index)
++{
++	struct qdio_buffer_element *element;
++	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;
++		}
++
++		switch (hdr->hdr.l2.id) {
++		case QETH_HEADER_TYPE_LAYER2:
++			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;
++			if (skb->protocol == htons(ETH_P_802_2))
++				*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
++			len = skb->len;
++			netif_rx(skb);
++			break;
++		case QETH_HEADER_TYPE_OSN:
++			skb_push(skb, sizeof(struct qeth_hdr));
++			skb_copy_to_linear_data(skb, hdr,
++						sizeof(struct qeth_hdr));
++			len = skb->len;
++			card->osn_info.data_cb(skb);
++			break;
++		default:
++			dev_kfree_skb_any(skb);
++			QETH_DBF_TEXT(TRACE, 3, "inbunkno");
++			QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
++			continue;
++		}
++		card->dev->last_rx = jiffies;
++		card->stats.rx_packets++;
++		card->stats.rx_bytes += len;
++	}
++}
++
++static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
++			   enum qeth_ipa_cmds ipacmd,
++			   int (*reply_cb) (struct qeth_card *,
++					    struct qeth_reply*,
++					    unsigned long))
++{
++	struct qeth_ipa_cmd *cmd;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(TRACE, 2, "L2sdmac");
++	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	cmd->data.setdelmac.mac_length = OSA_ADDR_LEN;
++	memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN);
++	return qeth_send_ipa_cmd(card, iob, reply_cb, NULL);
++}
++
++static int qeth_l2_send_setmac_cb(struct qeth_card *card,
++			   struct qeth_reply *reply,
++			   unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 2, "L2Smaccb");
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->hdr.return_code) {
++		QETH_DBF_TEXT_(TRACE, 2, "L2er%x", cmd->hdr.return_code);
++		card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
++		cmd->hdr.return_code = -EIO;
++	} else {
++		card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
++		memcpy(card->dev->dev_addr, cmd->data.setdelmac.mac,
++		       OSA_ADDR_LEN);
++		PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
++			   "successfully registered on device %s\n",
++			   card->dev->dev_addr[0], card->dev->dev_addr[1],
++			   card->dev->dev_addr[2], card->dev->dev_addr[3],
++			   card->dev->dev_addr[4], card->dev->dev_addr[5],
++			   card->dev->name);
++	}
++	return 0;
++}
++
++static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
++{
++	QETH_DBF_TEXT(TRACE, 2, "L2Setmac");
++	return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC,
++					  qeth_l2_send_setmac_cb);
++}
++
++static int qeth_l2_send_delmac_cb(struct qeth_card *card,
++			   struct qeth_reply *reply,
++			   unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 2, "L2Dmaccb");
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->hdr.return_code) {
++		QETH_DBF_TEXT_(TRACE, 2, "err%d", cmd->hdr.return_code);
++		cmd->hdr.return_code = -EIO;
++		return 0;
++	}
++	card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
++
++	return 0;
++}
++
++static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac)
++{
++	QETH_DBF_TEXT(TRACE, 2, "L2Delmac");
++	if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
++		return 0;
++	return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
++					  qeth_l2_send_delmac_cb);
++}
++
++static int qeth_l2_request_initial_mac(struct qeth_card *card)
++{
++	int rc = 0;
++	char vendor_pre[] = {0x02, 0x00, 0x00};
++
++	QETH_DBF_TEXT(SETUP, 2, "doL2init");
++	QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
++
++	rc = qeth_query_setadapterparms(card);
++	if (rc) {
++		PRINT_WARN("could not query adapter parameters on device %s: "
++			   "x%x\n", CARD_BUS_ID(card), rc);
++	}
++
++	if (card->info.guestlan) {
++		rc = qeth_setadpparms_change_macaddr(card);
++		if (rc) {
++			PRINT_WARN("couldn't get MAC address on "
++			   "device %s: x%x\n",
++			   CARD_BUS_ID(card), rc);
++			QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++			return rc;
++		}
++		QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, OSA_ADDR_LEN);
++	} else {
++		random_ether_addr(card->dev->dev_addr);
++		memcpy(card->dev->dev_addr, vendor_pre, 3);
++	}
++	return 0;
++}
++
++static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
++{
++	struct sockaddr *addr = p;
++	struct qeth_card *card = netdev_priv(dev);
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "setmac");
++
++	if (qeth_l2_verify_dev(dev) != QETH_REAL_CARD) {
++		QETH_DBF_TEXT(TRACE, 3, "setmcINV");
++		return -EOPNOTSUPP;
++	}
++
++	if (card->info.type == QETH_CARD_TYPE_OSN) {
++		PRINT_WARN("Setting MAC address on %s is not supported.\n",
++			   dev->name);
++		QETH_DBF_TEXT(TRACE, 3, "setmcOSN");
++		return -EOPNOTSUPP;
++	}
++	QETH_DBF_TEXT_(TRACE, 3, "%s", CARD_BUS_ID(card));
++	QETH_DBF_HEX(TRACE, 3, addr->sa_data, OSA_ADDR_LEN);
++	rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
++	if (!rc)
++		rc = qeth_l2_send_setmac(card, addr->sa_data);
++	return rc;
++}
++
++static void qeth_l2_set_multicast_list(struct net_device *dev)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	struct dev_mc_list *dm;
++
++	if (card->info.type == QETH_CARD_TYPE_OSN)
++		return ;
++
++	QETH_DBF_TEXT(TRACE, 3, "setmulti");
++	qeth_l2_del_all_mc(card);
++	spin_lock_bh(&card->mclock);
++	for (dm = dev->mc_list; dm; dm = dm->next)
++		qeth_l2_add_mc(card, dm->dmi_addr);
++	spin_unlock_bh(&card->mclock);
++	if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
++		return;
++	qeth_setadp_promisc_mode(card);
++}
++
++static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	int rc;
++	struct qeth_hdr *hdr = NULL;
++	int elements = 0;
++	struct qeth_card *card = netdev_priv(dev);
++	struct sk_buff *new_skb = skb;
++	int ipv = qeth_get_ip_version(skb);
++	int cast_type = qeth_get_cast_type(card, skb);
++	struct qeth_qdio_out_q *queue = card->qdio.out_qs
++		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
++	int tx_bytes = skb->len;
++	enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
++	struct qeth_eddp_context *ctx = NULL;
++
++	QETH_DBF_TEXT(TRACE, 6, "l2xmit");
++
++	if ((card->state != CARD_STATE_UP) || !card->lan_online) {
++		card->stats.tx_carrier_errors++;
++		goto tx_drop;
++	}
++
++	if ((card->info.type == QETH_CARD_TYPE_OSN) &&
++	    (skb->protocol == htons(ETH_P_IPV6)))
++		goto tx_drop;
++
++	if (card->options.performance_stats) {
++		card->perf_stats.outbound_cnt++;
++		card->perf_stats.outbound_start_time = qeth_get_micros();
++	}
++	netif_stop_queue(dev);
++
++	if (skb_is_gso(skb))
++		large_send = QETH_LARGE_SEND_EDDP;
++
++	if (card->info.type == QETH_CARD_TYPE_OSN)
++		hdr = (struct qeth_hdr *)skb->data;
++	else {
++		new_skb = qeth_prepare_skb(card, skb, &hdr);
++		if (!new_skb)
++			goto tx_drop;
++		qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type);
++	}
++
++	if (large_send == QETH_LARGE_SEND_EDDP) {
++		ctx = qeth_eddp_create_context(card, new_skb, hdr,
++						skb->sk->sk_protocol);
++		if (ctx == NULL) {
++			PRINT_WARN("could not create eddp context\n");
++			goto tx_drop;
++		}
++	} else {
++		elements = qeth_get_elements_no(card, (void *)hdr, new_skb, 0);
++		if (!elements)
++			goto tx_drop;
++	}
++
++	if ((large_send == QETH_LARGE_SEND_NO) &&
++	    (skb->ip_summed == CHECKSUM_PARTIAL))
++		qeth_tx_csum(new_skb);
++
++	if (card->info.type != QETH_CARD_TYPE_IQD)
++		rc = qeth_do_send_packet(card, queue, new_skb, hdr,
++					 elements, ctx);
++	else
++		rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
++					      elements, ctx);
++	if (!rc) {
++		card->stats.tx_packets++;
++		card->stats.tx_bytes += tx_bytes;
++		if (new_skb != skb)
++			dev_kfree_skb_any(skb);
++		if (card->options.performance_stats) {
++			if (large_send != QETH_LARGE_SEND_NO) {
++				card->perf_stats.large_send_bytes += tx_bytes;
++				card->perf_stats.large_send_cnt++;
++			}
++			if (skb_shinfo(new_skb)->nr_frags > 0) {
++				card->perf_stats.sg_skbs_sent++;
++				/* nr_frags + skb->data */
++				card->perf_stats.sg_frags_sent +=
++					skb_shinfo(new_skb)->nr_frags + 1;
++			}
++		}
++
++		if (ctx != NULL) {
++			qeth_eddp_put_context(ctx);
++			dev_kfree_skb_any(new_skb);
++		}
++	} else {
++		if (ctx != NULL)
++			qeth_eddp_put_context(ctx);
++
++		if (rc == -EBUSY) {
++			if (new_skb != skb)
++				dev_kfree_skb_any(new_skb);
++			return NETDEV_TX_BUSY;
++		} else
++			goto tx_drop;
++	}
++
++	netif_wake_queue(dev);
++	if (card->options.performance_stats)
++		card->perf_stats.outbound_time += qeth_get_micros() -
++			card->perf_stats.outbound_start_time;
++	return rc;
++
++tx_drop:
++	card->stats.tx_dropped++;
++	card->stats.tx_errors++;
++	if ((new_skb != skb) && new_skb)
++		dev_kfree_skb_any(new_skb);
++	dev_kfree_skb_any(skb);
++	return NETDEV_TX_OK;
++}
++
++static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
++			unsigned int status, unsigned int qdio_err,
++			unsigned int siga_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;
++
++	QETH_DBF_TEXT(TRACE, 6, "qdinput");
++	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 (status & QDIO_STATUS_LOOK_FOR_ERROR) {
++		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
++			QETH_DBF_TEXT(TRACE, 1, "qdinchk");
++			QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++			QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", first_element,
++					count);
++			QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", queue, status);
++			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 (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
++		      qeth_check_qdio_errors(buffer->buffer,
++					     qdio_err, siga_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 = netdev_priv(dev);
++
++	QETH_DBF_TEXT(TRACE, 4, "qethopen");
++	if (card->state != CARD_STATE_SOFTSETUP)
++		return -ENODEV;
++
++	if ((card->info.type != QETH_CARD_TYPE_OSN) &&
++	     (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
++		QETH_DBF_TEXT(TRACE, 4, "nomacadr");
++		return -EPERM;
++	}
++	card->data.state = CH_STATE_UP;
++	card->state = CARD_STATE_UP;
++	card->dev->flags |= IFF_UP;
++	netif_start_queue(dev);
++
++	if (!card->lan_online && netif_carrier_ok(dev))
++		netif_carrier_off(dev);
++	return 0;
++}
++
++
++static int qeth_l2_stop(struct net_device *dev)
++{
++	struct qeth_card *card = netdev_priv(dev);
++
++	QETH_DBF_TEXT(TRACE, 4, "qethstop");
++	netif_tx_disable(dev);
++	card->dev->flags &= ~IFF_UP;
++	if (card->state == CARD_STATE_UP)
++		card->state = CARD_STATE_SOFTSETUP;
++	return 0;
++}
++
++static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
++{
++	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++
++	INIT_LIST_HEAD(&card->vid_list);
++	INIT_LIST_HEAD(&card->mc_list);
++	card->options.layer2 = 1;
++	card->discipline.input_handler = (qdio_handler_t *)
++		qeth_l2_qdio_input_handler;
++	card->discipline.output_handler = (qdio_handler_t *)
++		qeth_qdio_output_handler;
++	card->discipline.recover = qeth_l2_recover;
++	return 0;
++}
++
++static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
++{
++	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
++
++	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
++
++	if (cgdev->state == CCWGROUP_ONLINE) {
++		card->use_hard_stop = 1;
++		qeth_l2_set_offline(cgdev);
++	}
++
++	if (card->dev) {
++		unregister_netdev(card->dev);
++		card->dev = NULL;
++	}
++
++	qeth_l2_del_all_mc(card);
++	return;
++}
++
++static struct ethtool_ops qeth_l2_ethtool_ops = {
++	.get_link = ethtool_op_get_link,
++	.get_tx_csum = ethtool_op_get_tx_csum,
++	.set_tx_csum = ethtool_op_set_tx_hw_csum,
++	.get_sg = ethtool_op_get_sg,
++	.set_sg = ethtool_op_set_sg,
++	.get_tso = ethtool_op_get_tso,
++	.set_tso = ethtool_op_set_tso,
++	.get_strings = qeth_core_get_strings,
++	.get_ethtool_stats = qeth_core_get_ethtool_stats,
++	.get_stats_count = qeth_core_get_stats_count,
++	.get_drvinfo = qeth_core_get_drvinfo,
++};
++
++static struct ethtool_ops qeth_l2_osn_ops = {
++	.get_strings = qeth_core_get_strings,
++	.get_ethtool_stats = qeth_core_get_ethtool_stats,
++	.get_stats_count = qeth_core_get_stats_count,
++	.get_drvinfo = qeth_core_get_drvinfo,
++};
++
++static int qeth_l2_setup_netdev(struct qeth_card *card)
++{
++	switch (card->info.type) {
++	case QETH_CARD_TYPE_OSAE:
++		card->dev = alloc_etherdev(0);
++		break;
++	case QETH_CARD_TYPE_IQD:
++		card->dev = alloc_netdev(0, "hsi%d", ether_setup);
++		break;
++	case QETH_CARD_TYPE_OSN:
++		card->dev = alloc_netdev(0, "osn%d", ether_setup);
++		card->dev->flags |= IFF_NOARP;
++		break;
++	default:
++		card->dev = alloc_etherdev(0);
++	}
++
++	if (!card->dev)
++		return -ENODEV;
++
++	card->dev->priv = card;
++	card->dev->tx_timeout = &qeth_tx_timeout;
++	card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
++	card->dev->open = qeth_l2_open;
++	card->dev->stop = qeth_l2_stop;
++	card->dev->hard_start_xmit = qeth_l2_hard_start_xmit;
++	card->dev->do_ioctl = qeth_l2_do_ioctl;
++	card->dev->get_stats = qeth_get_stats;
++	card->dev->change_mtu = qeth_change_mtu;
++	card->dev->set_multicast_list = qeth_l2_set_multicast_list;
++	card->dev->vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid;
++	card->dev->vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid;
++	card->dev->set_mac_address = qeth_l2_set_mac_address;
++	card->dev->mtu = card->info.initial_mtu;
++	if (card->info.type != QETH_CARD_TYPE_OSN)
++		SET_ETHTOOL_OPS(card->dev, &qeth_l2_ethtool_ops);
++	else
++		SET_ETHTOOL_OPS(card->dev, &qeth_l2_osn_ops);
++	card->dev->features |= NETIF_F_HW_VLAN_FILTER;
++	card->info.broadcast_capable = 1;
++	qeth_l2_request_initial_mac(card);
++	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
++	return register_netdev(card->dev);
++}
++
++static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
++{
++	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++	int rc = 0;
++	enum qeth_card_states recover_flag;
++
++	BUG_ON(!card);
++	QETH_DBF_TEXT(SETUP, 2, "setonlin");
++	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++	qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
++	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) {
++		PRINT_WARN("set_online of card %s interrupted by user!\n",
++			   CARD_BUS_ID(card));
++		return -ERESTARTSYS;
++	}
++
++	recover_flag = card->state;
++	rc = ccw_device_set_online(CARD_RDEV(card));
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		return -EIO;
++	}
++	rc = ccw_device_set_online(CARD_WDEV(card));
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		return -EIO;
++	}
++	rc = ccw_device_set_online(CARD_DDEV(card));
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		return -EIO;
++	}
++
++	rc = qeth_core_hardsetup_card(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++		goto out_remove;
++	}
++
++	if (!card->dev && qeth_l2_setup_netdev(card))
++		goto out_remove;
++
++	if (card->info.type != QETH_CARD_TYPE_OSN)
++		qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
++
++	card->state = CARD_STATE_HARDSETUP;
++	qeth_print_status_message(card);
++
++	/* softsetup */
++	QETH_DBF_TEXT(SETUP, 2, "softsetp");
++
++	rc = qeth_send_startlan(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		if (rc == 0xe080) {
++			PRINT_WARN("LAN on card %s if offline! "
++				   "Waiting for STARTLAN from card.\n",
++				   CARD_BUS_ID(card));
++			card->lan_online = 0;
++		}
++		return rc;
++	} else
++		card->lan_online = 1;
++
++	if (card->info.type != QETH_CARD_TYPE_OSN) {
++		qeth_set_large_send(card, card->options.large_send);
++		qeth_l2_process_vlans(card, 0);
++	}
++
++	netif_tx_disable(card->dev);
++
++	rc = qeth_init_qdio_queues(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
++		goto out_remove;
++	}
++	card->state = CARD_STATE_SOFTSETUP;
++	netif_carrier_on(card->dev);
++
++	qeth_set_allowed_threads(card, 0xffffffff, 0);
++	if (recover_flag == CARD_STATE_RECOVER) {
++		if (recovery_mode &&
++		    card->info.type != QETH_CARD_TYPE_OSN) {
++			qeth_l2_open(card->dev);
++		} else {
++			rtnl_lock();
++			dev_open(card->dev);
++			rtnl_unlock();
++		}
++		/* this also sets saved unicast addresses */
++		qeth_l2_set_multicast_list(card->dev);
++	}
++	/* let user_space know that device is online */
++	kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
++	return 0;
++out_remove:
++	card->use_hard_stop = 1;
++	qeth_l2_stop_card(card, 0);
++	ccw_device_set_offline(CARD_DDEV(card));
++	ccw_device_set_offline(CARD_WDEV(card));
++	ccw_device_set_offline(CARD_RDEV(card));
++	if (recover_flag == CARD_STATE_RECOVER)
++		card->state = CARD_STATE_RECOVER;
++	else
++		card->state = CARD_STATE_DOWN;
++	return -ENODEV;
++}
++
++static int qeth_l2_set_online(struct ccwgroup_device *gdev)
++{
++	return __qeth_l2_set_online(gdev, 0);
++}
++
++static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
++					int recovery_mode)
++{
++	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
++	int rc = 0, rc2 = 0, rc3 = 0;
++	enum qeth_card_states recover_flag;
++
++	QETH_DBF_TEXT(SETUP, 3, "setoffl");
++	QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
++
++	if (card->dev && netif_carrier_ok(card->dev))
++		netif_carrier_off(card->dev);
++	recover_flag = card->state;
++	if (qeth_l2_stop_card(card, recovery_mode) == -ERESTARTSYS) {
++		PRINT_WARN("Stopping card %s interrupted by user!\n",
++			   CARD_BUS_ID(card));
++		return -ERESTARTSYS;
++	}
++	rc  = ccw_device_set_offline(CARD_DDEV(card));
++	rc2 = ccw_device_set_offline(CARD_WDEV(card));
++	rc3 = ccw_device_set_offline(CARD_RDEV(card));
++	if (!rc)
++		rc = (rc2) ? rc2 : rc3;
++	if (rc)
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++	if (recover_flag == CARD_STATE_UP)
++		card->state = CARD_STATE_RECOVER;
++	/* let user_space know that device is offline */
++	kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
++	return 0;
++}
++
++static int qeth_l2_set_offline(struct ccwgroup_device *cgdev)
++{
++	return __qeth_l2_set_offline(cgdev, 0);
++}
++
++static int qeth_l2_recover(void *ptr)
++{
++	struct qeth_card *card;
++	int rc = 0;
++
++	card = (struct qeth_card *) ptr;
++	QETH_DBF_TEXT(TRACE, 2, "recover1");
++	QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *));
++	if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
++		return 0;
++	QETH_DBF_TEXT(TRACE, 2, "recover2");
++	PRINT_WARN("Recovery of device %s started ...\n",
++		   CARD_BUS_ID(card));
++	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)
++		PRINT_INFO("Device %s successfully recovered!\n",
++			   CARD_BUS_ID(card));
++	else
++		PRINT_INFO("Device %s could not be recovered!\n",
++			   CARD_BUS_ID(card));
++	return 0;
++}
++
++static int __init qeth_l2_init(void)
++{
++	PRINT_INFO("register layer 2 discipline\n");
++	return 0;
++}
++
++static void __exit qeth_l2_exit(void)
++{
++	PRINT_INFO("unregister layer 2 discipline\n");
++}
++
++static void qeth_l2_shutdown(struct ccwgroup_device *gdev)
++{
++	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++	qeth_qdio_clear_card(card, 0);
++	qeth_clear_qdio_buffers(card);
++}
++
++struct ccwgroup_driver qeth_l2_ccwgroup_driver = {
++	.probe = qeth_l2_probe_device,
++	.remove = qeth_l2_remove_device,
++	.set_online = qeth_l2_set_online,
++	.set_offline = qeth_l2_set_offline,
++	.shutdown = qeth_l2_shutdown,
++};
++EXPORT_SYMBOL_GPL(qeth_l2_ccwgroup_driver);
++
++static int qeth_osn_send_control_data(struct qeth_card *card, int len,
++			   struct qeth_cmd_buffer *iob)
++{
++	unsigned long flags;
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 5, "osndctrd");
++
++	wait_event(card->wait_q,
++		   atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
++	qeth_prepare_control_data(card, len, iob);
++	QETH_DBF_TEXT(TRACE, 6, "osnoirqp");
++	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
++	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
++			      (addr_t) iob, 0, 0);
++	spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
++	if (rc) {
++		PRINT_WARN("qeth_osn_send_control_data: "
++			   "ccw_device_start rc = %i\n", rc);
++		QETH_DBF_TEXT_(TRACE, 2, " err%d", rc);
++		qeth_release_buffer(iob->channel, iob);
++		atomic_set(&card->write.irq_pending, 0);
++		wake_up(&card->wait_q);
++	}
++	return rc;
++}
++
++static int qeth_osn_send_ipa_cmd(struct qeth_card *card,
++			struct qeth_cmd_buffer *iob, int data_len)
++{
++	u16 s1, s2;
++
++	QETH_DBF_TEXT(TRACE, 4, "osndipa");
++
++	qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
++	s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
++	s2 = (u16)data_len;
++	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
++	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
++	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
++	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
++	return qeth_osn_send_control_data(card, s1, iob);
++}
++
++int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
++{
++	struct qeth_cmd_buffer *iob;
++	struct qeth_card *card;
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 2, "osnsdmc");
++	if (!dev)
++		return -ENODEV;
++	card = netdev_priv(dev);
++	if (!card)
++		return -ENODEV;
++	if ((card->state != CARD_STATE_UP) &&
++	    (card->state != CARD_STATE_SOFTSETUP))
++		return -ENODEV;
++	iob = qeth_wait_for_buffer(&card->write);
++	memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
++	rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
++	return rc;
++}
++EXPORT_SYMBOL(qeth_osn_assist);
++
++int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
++		  int (*assist_cb)(struct net_device *, void *),
++		  int (*data_cb)(struct sk_buff *))
++{
++	struct qeth_card *card;
++
++	QETH_DBF_TEXT(TRACE, 2, "osnreg");
++	*dev = qeth_l2_netdev_by_devno(read_dev_no);
++	if (*dev == NULL)
++		return -ENODEV;
++	card = netdev_priv(*dev);
++	if (!card)
++		return -ENODEV;
++	if ((assist_cb == NULL) || (data_cb == NULL))
++		return -EINVAL;
++	card->osn_info.assist_cb = assist_cb;
++	card->osn_info.data_cb = data_cb;
++	return 0;
++}
++EXPORT_SYMBOL(qeth_osn_register);
++
++void qeth_osn_deregister(struct net_device *dev)
++{
++	struct qeth_card *card;
++
++	QETH_DBF_TEXT(TRACE, 2, "osndereg");
++	if (!dev)
++		return;
++	card = netdev_priv(dev);
++	if (!card)
++		return;
++	card->osn_info.assist_cb = NULL;
++	card->osn_info.data_cb = NULL;
++	return;
++}
++EXPORT_SYMBOL(qeth_osn_deregister);
++
++module_init(qeth_l2_init);
++module_exit(qeth_l2_exit);
++MODULE_AUTHOR("Frank Blaschka <frank.blaschka at de.ibm.com>");
++MODULE_DESCRIPTION("qeth layer 2 discipline");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h
+new file mode 100644
+index 0000000..1be3535
+--- /dev/null
++++ b/drivers/s390/net/qeth_l3.h
+@@ -0,0 +1,67 @@
++/*
++ *  drivers/s390/net/qeth_l3.h
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ *		 Frank Pavlic <fpavlic at de.ibm.com>,
++ *		 Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#ifndef __QETH_L3_H__
++#define __QETH_L3_H__
++
++#include "qeth_core.h"
++
++#define QETH_DBF_TXT_BUF qeth_l3_dbf_txt_buf
++DECLARE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
++
++struct qeth_ipaddr {
++	struct list_head entry;
++	enum qeth_ip_types type;
++	enum qeth_ipa_setdelip_flags set_flags;
++	enum qeth_ipa_setdelip_flags del_flags;
++	int is_multicast;
++	int users;
++	enum qeth_prot_versions proto;
++	unsigned char mac[OSA_ADDR_LEN];
++	union {
++		struct {
++			unsigned int addr;
++			unsigned int mask;
++		} a4;
++		struct {
++			struct in6_addr addr;
++			unsigned int pfxlen;
++		} a6;
++	} u;
++};
++
++struct qeth_ipato_entry {
++	struct list_head entry;
++	enum qeth_prot_versions proto;
++	char addr[16];
++	int mask_bits;
++};
++
++
++void qeth_l3_ipaddr4_to_string(const __u8 *, char *);
++int qeth_l3_string_to_ipaddr4(const char *, __u8 *);
++void qeth_l3_ipaddr6_to_string(const __u8 *, char *);
++int qeth_l3_string_to_ipaddr6(const char *, __u8 *);
++void qeth_l3_ipaddr_to_string(enum qeth_prot_versions, const __u8 *, char *);
++int qeth_l3_string_to_ipaddr(const char *, enum qeth_prot_versions, __u8 *);
++int qeth_l3_create_device_attributes(struct device *);
++void qeth_l3_remove_device_attributes(struct device *);
++int qeth_l3_setrouting_v4(struct qeth_card *);
++int qeth_l3_setrouting_v6(struct qeth_card *);
++int qeth_l3_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *);
++void qeth_l3_del_ipato_entry(struct qeth_card *, enum qeth_prot_versions,
++			u8 *, int);
++int qeth_l3_add_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
++void qeth_l3_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
++int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
++void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
++			const u8 *);
++
++#endif /* __QETH_L3_H__ */
+diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
+new file mode 100644
+index 0000000..e1bfe56
+--- /dev/null
++++ b/drivers/s390/net/qeth_l3_main.c
+@@ -0,0 +1,3396 @@
++/*
++ *  drivers/s390/net/qeth_l3_main.c
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ *		 Frank Pavlic <fpavlic at de.ibm.com>,
++ *		 Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/etherdevice.h>
++#include <linux/mii.h>
++#include <linux/ip.h>
++#include <linux/reboot.h>
++#include <linux/inetdevice.h>
++#include <linux/igmp.h>
++
++#include <net/ip.h>
++#include <net/arp.h>
++
++#include <asm/s390_rdev.h>
++
++#include "qeth_l3.h"
++#include "qeth_core_offl.h"
++
++DEFINE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
++
++static int qeth_l3_set_offline(struct ccwgroup_device *);
++static int qeth_l3_recover(void *);
++static int qeth_l3_stop(struct net_device *);
++static void qeth_l3_set_multicast_list(struct net_device *);
++static int qeth_l3_neigh_setup(struct net_device *, struct neigh_parms *);
++static int qeth_l3_register_addr_entry(struct qeth_card *,
++		struct qeth_ipaddr *);
++static int qeth_l3_deregister_addr_entry(struct qeth_card *,
++		struct qeth_ipaddr *);
++static int __qeth_l3_set_online(struct ccwgroup_device *, int);
++static int __qeth_l3_set_offline(struct ccwgroup_device *, int);
++
++
++static int qeth_l3_isxdigit(char *buf)
++{
++	while (*buf) {
++		if (!isxdigit(*buf++))
++			return 0;
++	}
++	return 1;
++}
++
++void qeth_l3_ipaddr4_to_string(const __u8 *addr, char *buf)
++{
++	sprintf(buf, "%i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
++}
++
++int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr)
++{
++	int count = 0, rc = 0;
++	int in[4];
++	char c;
++
++	rc = sscanf(buf, "%u.%u.%u.%u%c",
++		    &in[0], &in[1], &in[2], &in[3], &c);
++	if (rc != 4 && (rc != 5 || c != '\n'))
++		return -EINVAL;
++	for (count = 0; count < 4; count++) {
++		if (in[count] > 255)
++			return -EINVAL;
++		addr[count] = in[count];
++	}
++	return 0;
++}
++
++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]);
++}
++
++int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr)
++{
++	const char *end, *end_tmp, *start;
++	__u16 *in;
++	char num[5];
++	int num2, cnt, out, found, save_cnt;
++	unsigned short in_tmp[8] = {0, };
++
++	cnt = out = found = save_cnt = num2 = 0;
++	end = start = buf;
++	in = (__u16 *) addr;
++	memset(in, 0, 16);
++	while (*end) {
++		end = strchr(start, ':');
++		if (end == NULL) {
++			end = buf + strlen(buf);
++			end_tmp = strchr(start, '\n');
++			if (end_tmp != NULL)
++				end = end_tmp;
++			out = 1;
++		}
++		if ((end - start)) {
++			memset(num, 0, 5);
++			if ((end - start) > 4)
++				return -EINVAL;
++			memcpy(num, start, end - start);
++			if (!qeth_l3_isxdigit(num))
++				return -EINVAL;
++			sscanf(start, "%x", &num2);
++			if (found)
++				in_tmp[save_cnt++] = num2;
++			else
++				in[cnt++] = num2;
++			if (out)
++				break;
++		} else {
++			if (found)
++				return -EINVAL;
++			found = 1;
++		}
++		start = ++end;
++	}
++	if (cnt + save_cnt > 8)
++		return -EINVAL;
++	cnt = 7;
++	while (save_cnt)
++		in[cnt--] = in_tmp[--save_cnt];
++	return 0;
++}
++
++void qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
++				char *buf)
++{
++	if (proto == QETH_PROT_IPV4)
++		qeth_l3_ipaddr4_to_string(addr, buf);
++	else if (proto == QETH_PROT_IPV6)
++		qeth_l3_ipaddr6_to_string(addr, buf);
++}
++
++int qeth_l3_string_to_ipaddr(const char *buf, enum qeth_prot_versions proto,
++				__u8 *addr)
++{
++	if (proto == QETH_PROT_IPV4)
++		return qeth_l3_string_to_ipaddr4(buf, addr);
++	else if (proto == QETH_PROT_IPV6)
++		return qeth_l3_string_to_ipaddr6(buf, addr);
++	else
++		return -EINVAL;
++}
++
++static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
++{
++	int i, j;
++	u8 octet;
++
++	for (i = 0; i < len; ++i) {
++		octet = addr[i];
++		for (j = 7; j >= 0; --j) {
++			bits[i*8 + j] = octet & 1;
++			octet >>= 1;
++		}
++	}
++}
++
++static int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card,
++						struct qeth_ipaddr *addr)
++{
++	struct qeth_ipato_entry *ipatoe;
++	u8 addr_bits[128] = {0, };
++	u8 ipatoe_bits[128] = {0, };
++	int rc = 0;
++
++	if (!card->ipato.enabled)
++		return 0;
++
++	qeth_l3_convert_addr_to_bits((u8 *) &addr->u, addr_bits,
++				  (addr->proto == QETH_PROT_IPV4)? 4:16);
++	list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
++		if (addr->proto != ipatoe->proto)
++			continue;
++		qeth_l3_convert_addr_to_bits(ipatoe->addr, ipatoe_bits,
++					  (ipatoe->proto == QETH_PROT_IPV4) ?
++					  4 : 16);
++		if (addr->proto == QETH_PROT_IPV4)
++			rc = !memcmp(addr_bits, ipatoe_bits,
++				     min(32, ipatoe->mask_bits));
++		else
++			rc = !memcmp(addr_bits, ipatoe_bits,
++				     min(128, ipatoe->mask_bits));
++		if (rc)
++			break;
++	}
++	/* invert? */
++	if ((addr->proto == QETH_PROT_IPV4) && card->ipato.invert4)
++		rc = !rc;
++	else if ((addr->proto == QETH_PROT_IPV6) && card->ipato.invert6)
++		rc = !rc;
++
++	return rc;
++}
++
++/*
++ * Add IP to be added to todo list. If there is already an "add todo"
++ * in this list we just incremenent the reference count.
++ * Returns 0 if we  just incremented reference count.
++ */
++static int __qeth_l3_insert_ip_todo(struct qeth_card *card,
++					struct qeth_ipaddr *addr, int add)
++{
++	struct qeth_ipaddr *tmp, *t;
++	int found = 0;
++
++	list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) {
++		if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
++		    (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
++			return 0;
++		if ((tmp->proto        == QETH_PROT_IPV4)     &&
++		    (addr->proto       == QETH_PROT_IPV4)     &&
++		    (tmp->type         == addr->type)         &&
++		    (tmp->is_multicast == addr->is_multicast) &&
++		    (tmp->u.a4.addr    == addr->u.a4.addr)    &&
++		    (tmp->u.a4.mask    == addr->u.a4.mask)) {
++			found = 1;
++			break;
++		}
++		if ((tmp->proto        == QETH_PROT_IPV6)      &&
++		    (addr->proto       == QETH_PROT_IPV6)      &&
++		    (tmp->type         == addr->type)          &&
++		    (tmp->is_multicast == addr->is_multicast)  &&
++		    (tmp->u.a6.pfxlen  == addr->u.a6.pfxlen)   &&
++		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
++			    sizeof(struct in6_addr)) == 0)) {
++			found = 1;
++			break;
++		}
++	}
++	if (found) {
++		if (addr->users != 0)
++			tmp->users += addr->users;
++		else
++			tmp->users += add ? 1 : -1;
++		if (tmp->users == 0) {
++			list_del(&tmp->entry);
++			kfree(tmp);
++		}
++		return 0;
++	} else {
++		if (addr->type == QETH_IP_TYPE_DEL_ALL_MC)
++			list_add(&addr->entry, card->ip_tbd_list);
++		else {
++			if (addr->users == 0)
++				addr->users += add ? 1 : -1;
++			if (add && (addr->type == QETH_IP_TYPE_NORMAL) &&
++			    qeth_l3_is_addr_covered_by_ipato(card, addr)) {
++				QETH_DBF_TEXT(TRACE, 2, "tkovaddr");
++				addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG;
++			}
++			list_add_tail(&addr->entry, card->ip_tbd_list);
++		}
++		return 1;
++	}
++}
++
++static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
++{
++	unsigned long flags;
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 4, "delip");
++
++	if (addr->proto == QETH_PROT_IPV4)
++		QETH_DBF_HEX(TRACE, 4, &addr->u.a4.addr, 4);
++	else {
++		QETH_DBF_HEX(TRACE, 4, &addr->u.a6.addr, 8);
++		QETH_DBF_HEX(TRACE, 4, ((char *)&addr->u.a6.addr) + 8, 8);
++	}
++	spin_lock_irqsave(&card->ip_lock, flags);
++	rc = __qeth_l3_insert_ip_todo(card, addr, 0);
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++	return rc;
++}
++
++static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
++{
++	unsigned long flags;
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 4, "addip");
++	if (addr->proto == QETH_PROT_IPV4)
++		QETH_DBF_HEX(TRACE, 4, &addr->u.a4.addr, 4);
++	else {
++		QETH_DBF_HEX(TRACE, 4, &addr->u.a6.addr, 8);
++		QETH_DBF_HEX(TRACE, 4, ((char *)&addr->u.a6.addr) + 8, 8);
++	}
++	spin_lock_irqsave(&card->ip_lock, flags);
++	rc = __qeth_l3_insert_ip_todo(card, addr, 1);
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++	return rc;
++}
++
++
++static struct qeth_ipaddr *qeth_l3_get_addr_buffer(
++				enum qeth_prot_versions prot)
++{
++	struct qeth_ipaddr *addr;
++
++	addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC);
++	if (addr == NULL) {
++		PRINT_WARN("Not enough memory to add address\n");
++		return NULL;
++	}
++	addr->type = QETH_IP_TYPE_NORMAL;
++	addr->proto = prot;
++	return addr;
++}
++
++static void qeth_l3_delete_mc_addresses(struct qeth_card *card)
++{
++	struct qeth_ipaddr *iptodo;
++	unsigned long flags;
++
++	QETH_DBF_TEXT(TRACE, 4, "delmc");
++	iptodo = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
++	if (!iptodo) {
++		QETH_DBF_TEXT(TRACE, 2, "dmcnomem");
++		return;
++	}
++	iptodo->type = QETH_IP_TYPE_DEL_ALL_MC;
++	spin_lock_irqsave(&card->ip_lock, flags);
++	if (!__qeth_l3_insert_ip_todo(card, iptodo, 0))
++		kfree(iptodo);
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++}
++
++/*
++ * Add/remove address to/from card's ip list, i.e. try to add or remove
++ * reference to/from an IP address that is already registered on the card.
++ * Returns:
++ *	0  address was on card and its reference count has been adjusted,
++ *	   but is still > 0, so nothing has to be done
++ *	   also returns 0 if card was not on card and the todo was to delete
++ *	   the address -> there is also nothing to be done
++ *	1  address was not on card and the todo is to add it to the card's ip
++ *	   list
++ *	-1 address was on card and its reference count has been decremented
++ *	   to <= 0 by the todo -> address must be removed from card
++ */
++static int __qeth_l3_ref_ip_on_card(struct qeth_card *card,
++		struct qeth_ipaddr *todo, struct qeth_ipaddr **__addr)
++{
++	struct qeth_ipaddr *addr;
++	int found = 0;
++
++	list_for_each_entry(addr, &card->ip_list, entry) {
++		if ((addr->proto == QETH_PROT_IPV4) &&
++		    (todo->proto == QETH_PROT_IPV4) &&
++		    (addr->type == todo->type) &&
++		    (addr->u.a4.addr == todo->u.a4.addr) &&
++		    (addr->u.a4.mask == todo->u.a4.mask)) {
++			found = 1;
++			break;
++		}
++		if ((addr->proto == QETH_PROT_IPV6) &&
++		    (todo->proto == QETH_PROT_IPV6) &&
++		    (addr->type == todo->type) &&
++		    (addr->u.a6.pfxlen == todo->u.a6.pfxlen) &&
++		    (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
++			    sizeof(struct in6_addr)) == 0)) {
++			found = 1;
++			break;
++		}
++	}
++	if (found) {
++		addr->users += todo->users;
++		if (addr->users <= 0) {
++			*__addr = addr;
++			return -1;
++		} else {
++			/* for VIPA and RXIP limit refcount to 1 */
++			if (addr->type != QETH_IP_TYPE_NORMAL)
++				addr->users = 1;
++			return 0;
++		}
++	}
++	if (todo->users > 0) {
++		/* for VIPA and RXIP limit refcount to 1 */
++		if (todo->type != QETH_IP_TYPE_NORMAL)
++			todo->users = 1;
++		return 1;
++	} else
++		return 0;
++}
++
++static void __qeth_l3_delete_all_mc(struct qeth_card *card,
++					unsigned long *flags)
++{
++	struct list_head fail_list;
++	struct qeth_ipaddr *addr, *tmp;
++	int rc;
++
++	INIT_LIST_HEAD(&fail_list);
++again:
++	list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
++		if (addr->is_multicast) {
++			list_del(&addr->entry);
++			spin_unlock_irqrestore(&card->ip_lock, *flags);
++			rc = qeth_l3_deregister_addr_entry(card, addr);
++			spin_lock_irqsave(&card->ip_lock, *flags);
++			if (!rc || (rc == IPA_RC_MC_ADDR_NOT_FOUND))
++				kfree(addr);
++			else
++				list_add_tail(&addr->entry, &fail_list);
++			goto again;
++		}
++	}
++	list_splice(&fail_list, &card->ip_list);
++}
++
++static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
++{
++	struct list_head *tbd_list;
++	struct qeth_ipaddr *todo, *addr;
++	unsigned long flags;
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 2, "sdiplist");
++	QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *));
++
++	spin_lock_irqsave(&card->ip_lock, flags);
++	tbd_list = card->ip_tbd_list;
++	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
++	if (!card->ip_tbd_list) {
++		QETH_DBF_TEXT(TRACE, 0, "silnomem");
++		card->ip_tbd_list = tbd_list;
++		spin_unlock_irqrestore(&card->ip_lock, flags);
++		return;
++	} else
++		INIT_LIST_HEAD(card->ip_tbd_list);
++
++	while (!list_empty(tbd_list)) {
++		todo = list_entry(tbd_list->next, struct qeth_ipaddr, entry);
++		list_del(&todo->entry);
++		if (todo->type == QETH_IP_TYPE_DEL_ALL_MC) {
++			__qeth_l3_delete_all_mc(card, &flags);
++			kfree(todo);
++			continue;
++		}
++		rc = __qeth_l3_ref_ip_on_card(card, todo, &addr);
++		if (rc == 0) {
++			/* nothing to be done; only adjusted refcount */
++			kfree(todo);
++		} else if (rc == 1) {
++			/* new entry to be added to on-card list */
++			spin_unlock_irqrestore(&card->ip_lock, flags);
++			rc = qeth_l3_register_addr_entry(card, todo);
++			spin_lock_irqsave(&card->ip_lock, flags);
++			if (!rc || (rc == IPA_RC_LAN_OFFLINE))
++				list_add_tail(&todo->entry, &card->ip_list);
++			else
++				kfree(todo);
++		} else if (rc == -1) {
++			/* on-card entry to be removed */
++			list_del_init(&addr->entry);
++			spin_unlock_irqrestore(&card->ip_lock, flags);
++			rc = qeth_l3_deregister_addr_entry(card, addr);
++			spin_lock_irqsave(&card->ip_lock, flags);
++			if (!rc || (rc == IPA_RC_PRIMARY_ALREADY_DEFINED))
++				kfree(addr);
++			else
++				list_add_tail(&addr->entry, &card->ip_list);
++			kfree(todo);
++		}
++	}
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++	kfree(tbd_list);
++}
++
++static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean,
++					int recover)
++{
++	struct qeth_ipaddr *addr, *tmp;
++	unsigned long flags;
++
++	QETH_DBF_TEXT(TRACE, 4, "clearip");
++	spin_lock_irqsave(&card->ip_lock, flags);
++	/* clear todo list */
++	list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry) {
++		list_del(&addr->entry);
++		kfree(addr);
++	}
++
++	while (!list_empty(&card->ip_list)) {
++		addr = list_entry(card->ip_list.next,
++				  struct qeth_ipaddr, entry);
++		list_del_init(&addr->entry);
++		if (clean) {
++			spin_unlock_irqrestore(&card->ip_lock, flags);
++			qeth_l3_deregister_addr_entry(card, addr);
++			spin_lock_irqsave(&card->ip_lock, flags);
++		}
++		if (!recover || addr->is_multicast) {
++			kfree(addr);
++			continue;
++		}
++		list_add_tail(&addr->entry, card->ip_tbd_list);
++	}
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++}
++
++static int qeth_l3_address_exists_in_list(struct list_head *list,
++		struct qeth_ipaddr *addr, int same_type)
++{
++	struct qeth_ipaddr *tmp;
++
++	list_for_each_entry(tmp, list, entry) {
++		if ((tmp->proto == QETH_PROT_IPV4) &&
++		    (addr->proto == QETH_PROT_IPV4) &&
++		    ((same_type && (tmp->type == addr->type)) ||
++		    (!same_type && (tmp->type != addr->type))) &&
++		    (tmp->u.a4.addr == addr->u.a4.addr))
++			return 1;
++
++		if ((tmp->proto == QETH_PROT_IPV6) &&
++		    (addr->proto == QETH_PROT_IPV6) &&
++		    ((same_type && (tmp->type == addr->type)) ||
++		    (!same_type && (tmp->type != addr->type))) &&
++		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
++			    sizeof(struct in6_addr)) == 0))
++			return 1;
++
++	}
++	return 0;
++}
++
++static int qeth_l3_send_setdelmc(struct qeth_card *card,
++			struct qeth_ipaddr *addr, int ipacmd)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 4, "setdelmc");
++
++	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	memcpy(&cmd->data.setdelipm.mac, addr->mac, OSA_ADDR_LEN);
++	if (addr->proto == QETH_PROT_IPV6)
++		memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr,
++		       sizeof(struct in6_addr));
++	else
++		memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr, 4);
++
++	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++
++	return rc;
++}
++
++static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len)
++{
++	int i, j;
++	for (i = 0; i < 16; i++) {
++		j = (len) - (i * 8);
++		if (j >= 8)
++			netmask[i] = 0xff;
++		else if (j > 0)
++			netmask[i] = (u8)(0xFF00 >> j);
++		else
++			netmask[i] = 0;
++	}
++}
++
++static int qeth_l3_send_setdelip(struct qeth_card *card,
++		struct qeth_ipaddr *addr, int ipacmd, unsigned int flags)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++	__u8 netmask[16];
++
++	QETH_DBF_TEXT(TRACE, 4, "setdelip");
++	QETH_DBF_TEXT_(TRACE, 4, "flags%02X", flags);
++
++	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	if (addr->proto == QETH_PROT_IPV6) {
++		memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr,
++		       sizeof(struct in6_addr));
++		qeth_l3_fill_netmask(netmask, addr->u.a6.pfxlen);
++		memcpy(cmd->data.setdelip6.mask, netmask,
++		       sizeof(struct in6_addr));
++		cmd->data.setdelip6.flags = flags;
++	} else {
++		memcpy(cmd->data.setdelip4.ip_addr, &addr->u.a4.addr, 4);
++		memcpy(cmd->data.setdelip4.mask, &addr->u.a4.mask, 4);
++		cmd->data.setdelip4.flags = flags;
++	}
++
++	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++
++	return rc;
++}
++
++static int qeth_l3_send_setrouting(struct qeth_card *card,
++	enum qeth_routing_types type, enum qeth_prot_versions prot)
++{
++	int rc;
++	struct qeth_ipa_cmd *cmd;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(TRACE, 4, "setroutg");
++	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	cmd->data.setrtg.type = (type);
++	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++
++	return rc;
++}
++
++static void qeth_l3_correct_routing_type(struct qeth_card *card,
++		enum qeth_routing_types *type, enum qeth_prot_versions prot)
++{
++	if (card->info.type == QETH_CARD_TYPE_IQD) {
++		switch (*type) {
++		case NO_ROUTER:
++		case PRIMARY_CONNECTOR:
++		case SECONDARY_CONNECTOR:
++		case MULTICAST_ROUTER:
++			return;
++		default:
++			goto out_inval;
++		}
++	} else {
++		switch (*type) {
++		case NO_ROUTER:
++		case PRIMARY_ROUTER:
++		case SECONDARY_ROUTER:
++			return;
++		case MULTICAST_ROUTER:
++			if (qeth_is_ipafunc_supported(card, prot,
++						      IPA_OSA_MC_ROUTER))
++				return;
++		default:
++			goto out_inval;
++		}
++	}
++out_inval:
++	PRINT_WARN("Routing type '%s' not supported for interface %s.\n"
++		   "Router status set to 'no router'.\n",
++		   ((*type == PRIMARY_ROUTER)? "primary router" :
++		    (*type == SECONDARY_ROUTER)? "secondary router" :
++		    (*type == PRIMARY_CONNECTOR)? "primary connector" :
++		    (*type == SECONDARY_CONNECTOR)? "secondary connector" :
++		    (*type == MULTICAST_ROUTER)? "multicast router" :
++		    "unknown"),
++		   card->dev->name);
++	*type = NO_ROUTER;
++}
++
++int qeth_l3_setrouting_v4(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "setrtg4");
++
++	qeth_l3_correct_routing_type(card, &card->options.route4.type,
++				  QETH_PROT_IPV4);
++
++	rc = qeth_l3_send_setrouting(card, card->options.route4.type,
++				  QETH_PROT_IPV4);
++	if (rc) {
++		card->options.route4.type = NO_ROUTER;
++		PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
++			   "Type set to 'no router'.\n",
++			   rc, QETH_CARD_IFNAME(card));
++	}
++	return rc;
++}
++
++int qeth_l3_setrouting_v6(struct qeth_card *card)
++{
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "setrtg6");
++#ifdef CONFIG_QETH_IPV6
++
++	if (!qeth_is_supported(card, IPA_IPV6))
++		return 0;
++	qeth_l3_correct_routing_type(card, &card->options.route6.type,
++				  QETH_PROT_IPV6);
++
++	rc = qeth_l3_send_setrouting(card, card->options.route6.type,
++				  QETH_PROT_IPV6);
++	if (rc) {
++		card->options.route6.type = NO_ROUTER;
++		PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
++			   "Type set to 'no router'.\n",
++			   rc, QETH_CARD_IFNAME(card));
++	}
++#endif
++	return rc;
++}
++
++/*
++ * IP address takeover related functions
++ */
++static void qeth_l3_clear_ipato_list(struct qeth_card *card)
++{
++
++	struct qeth_ipato_entry *ipatoe, *tmp;
++	unsigned long flags;
++
++	spin_lock_irqsave(&card->ip_lock, flags);
++	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
++		list_del(&ipatoe->entry);
++		kfree(ipatoe);
++	}
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++}
++
++int qeth_l3_add_ipato_entry(struct qeth_card *card,
++				struct qeth_ipato_entry *new)
++{
++	struct qeth_ipato_entry *ipatoe;
++	unsigned long flags;
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 2, "addipato");
++	spin_lock_irqsave(&card->ip_lock, flags);
++	list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
++		if (ipatoe->proto != new->proto)
++			continue;
++		if (!memcmp(ipatoe->addr, new->addr,
++			    (ipatoe->proto == QETH_PROT_IPV4)? 4:16) &&
++		    (ipatoe->mask_bits == new->mask_bits)) {
++			PRINT_WARN("ipato entry already exists!\n");
++			rc = -EEXIST;
++			break;
++		}
++	}
++	if (!rc)
++		list_add_tail(&new->entry, &card->ipato.entries);
++
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++	return rc;
++}
++
++void qeth_l3_del_ipato_entry(struct qeth_card *card,
++		enum qeth_prot_versions proto, u8 *addr, int mask_bits)
++{
++	struct qeth_ipato_entry *ipatoe, *tmp;
++	unsigned long flags;
++
++	QETH_DBF_TEXT(TRACE, 2, "delipato");
++	spin_lock_irqsave(&card->ip_lock, flags);
++	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
++		if (ipatoe->proto != proto)
++			continue;
++		if (!memcmp(ipatoe->addr, addr,
++			    (proto == QETH_PROT_IPV4)? 4:16) &&
++		    (ipatoe->mask_bits == mask_bits)) {
++			list_del(&ipatoe->entry);
++			kfree(ipatoe);
++		}
++	}
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++}
++
++/*
++ * VIPA related functions
++ */
++int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
++	      const u8 *addr)
++{
++	struct qeth_ipaddr *ipaddr;
++	unsigned long flags;
++	int rc = 0;
++
++	ipaddr = qeth_l3_get_addr_buffer(proto);
++	if (ipaddr) {
++		if (proto == QETH_PROT_IPV4) {
++			QETH_DBF_TEXT(TRACE, 2, "addvipa4");
++			memcpy(&ipaddr->u.a4.addr, addr, 4);
++			ipaddr->u.a4.mask = 0;
++		} else if (proto == QETH_PROT_IPV6) {
++			QETH_DBF_TEXT(TRACE, 2, "addvipa6");
++			memcpy(&ipaddr->u.a6.addr, addr, 16);
++			ipaddr->u.a6.pfxlen = 0;
++		}
++		ipaddr->type = QETH_IP_TYPE_VIPA;
++		ipaddr->set_flags = QETH_IPA_SETIP_VIPA_FLAG;
++		ipaddr->del_flags = QETH_IPA_DELIP_VIPA_FLAG;
++	} else
++		return -ENOMEM;
++	spin_lock_irqsave(&card->ip_lock, flags);
++	if (qeth_l3_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
++	    qeth_l3_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
++		rc = -EEXIST;
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++	if (rc) {
++		PRINT_WARN("Cannot add VIPA. Address already exists!\n");
++		return rc;
++	}
++	if (!qeth_l3_add_ip(card, ipaddr))
++		kfree(ipaddr);
++	qeth_l3_set_ip_addr_list(card);
++	return rc;
++}
++
++void qeth_l3_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
++	      const u8 *addr)
++{
++	struct qeth_ipaddr *ipaddr;
++
++	ipaddr = qeth_l3_get_addr_buffer(proto);
++	if (ipaddr) {
++		if (proto == QETH_PROT_IPV4) {
++			QETH_DBF_TEXT(TRACE, 2, "delvipa4");
++			memcpy(&ipaddr->u.a4.addr, addr, 4);
++			ipaddr->u.a4.mask = 0;
++		} else if (proto == QETH_PROT_IPV6) {
++			QETH_DBF_TEXT(TRACE, 2, "delvipa6");
++			memcpy(&ipaddr->u.a6.addr, addr, 16);
++			ipaddr->u.a6.pfxlen = 0;
++		}
++		ipaddr->type = QETH_IP_TYPE_VIPA;
++	} else
++		return;
++	if (!qeth_l3_delete_ip(card, ipaddr))
++		kfree(ipaddr);
++	qeth_l3_set_ip_addr_list(card);
++}
++
++/*
++ * proxy ARP related functions
++ */
++int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
++	      const u8 *addr)
++{
++	struct qeth_ipaddr *ipaddr;
++	unsigned long flags;
++	int rc = 0;
++
++	ipaddr = qeth_l3_get_addr_buffer(proto);
++	if (ipaddr) {
++		if (proto == QETH_PROT_IPV4) {
++			QETH_DBF_TEXT(TRACE, 2, "addrxip4");
++			memcpy(&ipaddr->u.a4.addr, addr, 4);
++			ipaddr->u.a4.mask = 0;
++		} else if (proto == QETH_PROT_IPV6) {
++			QETH_DBF_TEXT(TRACE, 2, "addrxip6");
++			memcpy(&ipaddr->u.a6.addr, addr, 16);
++			ipaddr->u.a6.pfxlen = 0;
++		}
++		ipaddr->type = QETH_IP_TYPE_RXIP;
++		ipaddr->set_flags = QETH_IPA_SETIP_TAKEOVER_FLAG;
++		ipaddr->del_flags = 0;
++	} else
++		return -ENOMEM;
++	spin_lock_irqsave(&card->ip_lock, flags);
++	if (qeth_l3_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
++	    qeth_l3_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
++		rc = -EEXIST;
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++	if (rc) {
++		PRINT_WARN("Cannot add RXIP. Address already exists!\n");
++		return rc;
++	}
++	if (!qeth_l3_add_ip(card, ipaddr))
++		kfree(ipaddr);
++	qeth_l3_set_ip_addr_list(card);
++	return 0;
++}
++
++void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
++			const u8 *addr)
++{
++	struct qeth_ipaddr *ipaddr;
++
++	ipaddr = qeth_l3_get_addr_buffer(proto);
++	if (ipaddr) {
++		if (proto == QETH_PROT_IPV4) {
++			QETH_DBF_TEXT(TRACE, 2, "addrxip4");
++			memcpy(&ipaddr->u.a4.addr, addr, 4);
++			ipaddr->u.a4.mask = 0;
++		} else if (proto == QETH_PROT_IPV6) {
++			QETH_DBF_TEXT(TRACE, 2, "addrxip6");
++			memcpy(&ipaddr->u.a6.addr, addr, 16);
++			ipaddr->u.a6.pfxlen = 0;
++		}
++		ipaddr->type = QETH_IP_TYPE_RXIP;
++	} else
++		return;
++	if (!qeth_l3_delete_ip(card, ipaddr))
++		kfree(ipaddr);
++	qeth_l3_set_ip_addr_list(card);
++}
++
++static int qeth_l3_register_addr_entry(struct qeth_card *card,
++				struct qeth_ipaddr *addr)
++{
++	char buf[50];
++	int rc = 0;
++	int cnt = 3;
++
++	if (addr->proto == QETH_PROT_IPV4) {
++		QETH_DBF_TEXT(TRACE, 2, "setaddr4");
++		QETH_DBF_HEX(TRACE, 3, &addr->u.a4.addr, sizeof(int));
++	} else if (addr->proto == QETH_PROT_IPV6) {
++		QETH_DBF_TEXT(TRACE, 2, "setaddr6");
++		QETH_DBF_HEX(TRACE, 3, &addr->u.a6.addr, 8);
++		QETH_DBF_HEX(TRACE, 3, ((char *)&addr->u.a6.addr) + 8, 8);
++	} else {
++		QETH_DBF_TEXT(TRACE, 2, "setaddr?");
++		QETH_DBF_HEX(TRACE, 3, addr, sizeof(struct qeth_ipaddr));
++	}
++	do {
++		if (addr->is_multicast)
++			rc =  qeth_l3_send_setdelmc(card, addr, IPA_CMD_SETIPM);
++		else
++			rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_SETIP,
++					addr->set_flags);
++		if (rc)
++			QETH_DBF_TEXT(TRACE, 2, "failed");
++	} while ((--cnt > 0) && rc);
++	if (rc) {
++		QETH_DBF_TEXT(TRACE, 2, "FAILED");
++		qeth_l3_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
++		PRINT_WARN("Could not register IP address %s (rc=0x%x/%d)\n",
++			   buf, rc, rc);
++	}
++	return rc;
++}
++
++static int qeth_l3_deregister_addr_entry(struct qeth_card *card,
++						struct qeth_ipaddr *addr)
++{
++	int rc = 0;
++
++	if (addr->proto == QETH_PROT_IPV4) {
++		QETH_DBF_TEXT(TRACE, 2, "deladdr4");
++		QETH_DBF_HEX(TRACE, 3, &addr->u.a4.addr, sizeof(int));
++	} else if (addr->proto == QETH_PROT_IPV6) {
++		QETH_DBF_TEXT(TRACE, 2, "deladdr6");
++		QETH_DBF_HEX(TRACE, 3, &addr->u.a6.addr, 8);
++		QETH_DBF_HEX(TRACE, 3, ((char *)&addr->u.a6.addr) + 8, 8);
++	} else {
++		QETH_DBF_TEXT(TRACE, 2, "deladdr?");
++		QETH_DBF_HEX(TRACE, 3, addr, sizeof(struct qeth_ipaddr));
++	}
++	if (addr->is_multicast)
++		rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_DELIPM);
++	else
++		rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_DELIP,
++					addr->del_flags);
++	if (rc) {
++		QETH_DBF_TEXT(TRACE, 2, "failed");
++		/* TODO: re-activate this warning as soon as we have a
++		 * clean mirco code
++		qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
++		PRINT_WARN("Could not deregister IP address %s (rc=%x)\n",
++			   buf, rc);
++		*/
++	}
++
++	return rc;
++}
++
++static inline u8 qeth_l3_get_qeth_hdr_flags4(int cast_type)
++{
++	if (cast_type == RTN_MULTICAST)
++		return QETH_CAST_MULTICAST;
++	if (cast_type == RTN_BROADCAST)
++		return QETH_CAST_BROADCAST;
++	return QETH_CAST_UNICAST;
++}
++
++static inline u8 qeth_l3_get_qeth_hdr_flags6(int cast_type)
++{
++	u8 ct = QETH_HDR_PASSTHRU | QETH_HDR_IPV6;
++	if (cast_type == RTN_MULTICAST)
++		return ct | QETH_CAST_MULTICAST;
++	if (cast_type == RTN_ANYCAST)
++		return ct | QETH_CAST_ANYCAST;
++	if (cast_type == RTN_BROADCAST)
++		return ct | QETH_CAST_BROADCAST;
++	return ct | QETH_CAST_UNICAST;
++}
++
++static int qeth_l3_send_setadp_mode(struct qeth_card *card, __u32 command,
++					__u32 mode)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 4, "adpmode");
++
++	iob = qeth_get_adapter_cmd(card, command,
++				   sizeof(struct qeth_ipacmd_setadpparms));
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	cmd->data.setadapterparms.data.mode = mode;
++	rc = qeth_send_ipa_cmd(card, iob, qeth_default_setadapterparms_cb,
++			       NULL);
++	return rc;
++}
++
++static int qeth_l3_setadapter_hstr(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 4, "adphstr");
++
++	if (qeth_adp_supported(card, IPA_SETADP_SET_BROADCAST_MODE)) {
++		rc = qeth_l3_send_setadp_mode(card,
++					IPA_SETADP_SET_BROADCAST_MODE,
++					card->options.broadcast_mode);
++		if (rc)
++			PRINT_WARN("couldn't set broadcast mode on "
++				   "device %s: x%x\n",
++				   CARD_BUS_ID(card), rc);
++		rc = qeth_l3_send_setadp_mode(card,
++					IPA_SETADP_ALTER_MAC_ADDRESS,
++					card->options.macaddr_mode);
++		if (rc)
++			PRINT_WARN("couldn't set macaddr mode on "
++				   "device %s: x%x\n", CARD_BUS_ID(card), rc);
++		return rc;
++	}
++	if (card->options.broadcast_mode == QETH_TR_BROADCAST_LOCAL)
++		PRINT_WARN("set adapter parameters not available "
++			   "to set broadcast mode, using ALLRINGS "
++			   "on device %s:\n", CARD_BUS_ID(card));
++	if (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL)
++		PRINT_WARN("set adapter parameters not available "
++			   "to set macaddr mode, using NONCANONICAL "
++			   "on device %s:\n", CARD_BUS_ID(card));
++	return 0;
++}
++
++static int qeth_l3_setadapter_parms(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(SETUP, 2, "setadprm");
++
++	if (!qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
++		PRINT_WARN("set adapter parameters not supported "
++			   "on device %s.\n",
++			   CARD_BUS_ID(card));
++		QETH_DBF_TEXT(SETUP, 2, " notsupp");
++		return 0;
++	}
++	rc = qeth_query_setadapterparms(card);
++	if (rc) {
++		PRINT_WARN("couldn't set adapter parameters on device %s: "
++			   "x%x\n", CARD_BUS_ID(card), rc);
++		return rc;
++	}
++	if (qeth_adp_supported(card, IPA_SETADP_ALTER_MAC_ADDRESS)) {
++		rc = qeth_setadpparms_change_macaddr(card);
++		if (rc)
++			PRINT_WARN("couldn't get MAC address on "
++				   "device %s: x%x\n",
++				   CARD_BUS_ID(card), rc);
++	}
++
++	if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++	    (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
++		rc = qeth_l3_setadapter_hstr(card);
++
++	return rc;
++}
++
++static int qeth_l3_default_setassparms_cb(struct qeth_card *card,
++			struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 4, "defadpcb");
++
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->hdr.return_code == 0) {
++		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
++		if (cmd->hdr.prot_version == QETH_PROT_IPV4)
++			card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
++		if (cmd->hdr.prot_version == QETH_PROT_IPV6)
++			card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
++	}
++	if (cmd->data.setassparms.hdr.assist_no == IPA_INBOUND_CHECKSUM &&
++	    cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
++		card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
++		QETH_DBF_TEXT_(TRACE, 3, "csum:%d", card->info.csum_mask);
++	}
++	return 0;
++}
++
++static struct qeth_cmd_buffer *qeth_l3_get_setassparms_cmd(
++	struct qeth_card *card, enum qeth_ipa_funcs ipa_func, __u16 cmd_code,
++	__u16 len, enum qeth_prot_versions prot)
++{
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 4, "getasscm");
++	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot);
++
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	cmd->data.setassparms.hdr.assist_no = ipa_func;
++	cmd->data.setassparms.hdr.length = 8 + len;
++	cmd->data.setassparms.hdr.command_code = cmd_code;
++	cmd->data.setassparms.hdr.return_code = 0;
++	cmd->data.setassparms.hdr.seq_no = 0;
++
++	return iob;
++}
++
++static int qeth_l3_send_setassparms(struct qeth_card *card,
++	struct qeth_cmd_buffer *iob, __u16 len, long data,
++	int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
++		unsigned long),
++	void *reply_param)
++{
++	int rc;
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 4, "sendassp");
++
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	if (len <= sizeof(__u32))
++		cmd->data.setassparms.data.flags_32bit = (__u32) data;
++	else   /* (len > sizeof(__u32)) */
++		memcpy(&cmd->data.setassparms.data, (void *) data, len);
++
++	rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
++	return rc;
++}
++
++#ifdef CONFIG_QETH_IPV6
++static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card,
++		enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(TRACE, 4, "simassp6");
++	iob = qeth_l3_get_setassparms_cmd(card, ipa_func, cmd_code,
++				       0, QETH_PROT_IPV6);
++	rc = qeth_l3_send_setassparms(card, iob, 0, 0,
++				   qeth_l3_default_setassparms_cb, NULL);
++	return rc;
++}
++#endif
++
++static int qeth_l3_send_simple_setassparms(struct qeth_card *card,
++		enum qeth_ipa_funcs ipa_func, __u16 cmd_code, long data)
++{
++	int rc;
++	int length = 0;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT(TRACE, 4, "simassp4");
++	if (data)
++		length = sizeof(__u32);
++	iob = qeth_l3_get_setassparms_cmd(card, ipa_func, cmd_code,
++				       length, QETH_PROT_IPV4);
++	rc = qeth_l3_send_setassparms(card, iob, length, data,
++				   qeth_l3_default_setassparms_cb, NULL);
++	return rc;
++}
++
++static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "ipaarp");
++
++	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++		PRINT_WARN("ARP processing not supported "
++			   "on %s!\n", QETH_CARD_IFNAME(card));
++		return 0;
++	}
++	rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
++					IPA_CMD_ASS_START, 0);
++	if (rc) {
++		PRINT_WARN("Could not start ARP processing "
++			   "assist on %s: 0x%x\n",
++			   QETH_CARD_IFNAME(card), rc);
++	}
++	return rc;
++}
++
++static int qeth_l3_start_ipa_ip_fragmentation(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "ipaipfrg");
++
++	if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
++		PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
++			   QETH_CARD_IFNAME(card));
++		return  -EOPNOTSUPP;
++	}
++
++	rc = qeth_l3_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
++					  IPA_CMD_ASS_START, 0);
++	if (rc) {
++		PRINT_WARN("Could not start Hardware IP fragmentation "
++			   "assist on %s: 0x%x\n",
++			   QETH_CARD_IFNAME(card), rc);
++	} else
++		PRINT_INFO("Hardware IP fragmentation enabled \n");
++	return rc;
++}
++
++static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "stsrcmac");
++
++	if (!card->options.fake_ll)
++		return -EOPNOTSUPP;
++
++	if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
++		PRINT_INFO("Inbound source address not "
++			   "supported on %s\n", QETH_CARD_IFNAME(card));
++		return -EOPNOTSUPP;
++	}
++
++	rc = qeth_l3_send_simple_setassparms(card, IPA_SOURCE_MAC,
++					  IPA_CMD_ASS_START, 0);
++	if (rc)
++		PRINT_WARN("Could not start inbound source "
++			   "assist on %s: 0x%x\n",
++			   QETH_CARD_IFNAME(card), rc);
++	return rc;
++}
++
++static int qeth_l3_start_ipa_vlan(struct qeth_card *card)
++{
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "strtvlan");
++
++	if (!qeth_is_supported(card, IPA_FULL_VLAN)) {
++		PRINT_WARN("VLAN not supported on %s\n",
++				QETH_CARD_IFNAME(card));
++		return -EOPNOTSUPP;
++	}
++
++	rc = qeth_l3_send_simple_setassparms(card, IPA_VLAN_PRIO,
++					  IPA_CMD_ASS_START, 0);
++	if (rc) {
++		PRINT_WARN("Could not start vlan "
++			   "assist on %s: 0x%x\n",
++			   QETH_CARD_IFNAME(card), rc);
++	} else {
++		PRINT_INFO("VLAN enabled \n");
++	}
++	return rc;
++}
++
++static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "stmcast");
++
++	if (!qeth_is_supported(card, IPA_MULTICASTING)) {
++		PRINT_WARN("Multicast not supported on %s\n",
++			   QETH_CARD_IFNAME(card));
++		return -EOPNOTSUPP;
++	}
++
++	rc = qeth_l3_send_simple_setassparms(card, IPA_MULTICASTING,
++					  IPA_CMD_ASS_START, 0);
++	if (rc) {
++		PRINT_WARN("Could not start multicast "
++			   "assist on %s: rc=%i\n",
++			   QETH_CARD_IFNAME(card), rc);
++	} else {
++		PRINT_INFO("Multicast enabled\n");
++		card->dev->flags |= IFF_MULTICAST;
++	}
++	return rc;
++}
++
++static int qeth_l3_query_ipassists_cb(struct qeth_card *card,
++		struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(SETUP, 2, "qipasscb");
++
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
++		card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
++		card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
++	} else {
++		card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
++		card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
++	}
++	QETH_DBF_TEXT(SETUP, 2, "suppenbl");
++	QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported);
++	QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled);
++	return 0;
++}
++
++static int qeth_l3_query_ipassists(struct qeth_card *card,
++				enum qeth_prot_versions prot)
++{
++	int rc;
++	struct qeth_cmd_buffer *iob;
++
++	QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot);
++	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot);
++	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_query_ipassists_cb, NULL);
++	return rc;
++}
++
++#ifdef CONFIG_QETH_IPV6
++static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "softipv6");
++
++	if (card->info.type == QETH_CARD_TYPE_IQD)
++		goto out;
++
++	rc = qeth_l3_query_ipassists(card, QETH_PROT_IPV6);
++	if (rc) {
++		PRINT_ERR("IPv6 query ipassist failed on %s\n",
++			  QETH_CARD_IFNAME(card));
++		return rc;
++	}
++	rc = qeth_l3_send_simple_setassparms(card, IPA_IPV6,
++					  IPA_CMD_ASS_START, 3);
++	if (rc) {
++		PRINT_WARN("IPv6 start assist (version 4) failed "
++			   "on %s: 0x%x\n",
++			   QETH_CARD_IFNAME(card), rc);
++		return rc;
++	}
++	rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_IPV6,
++					       IPA_CMD_ASS_START);
++	if (rc) {
++		PRINT_WARN("IPV6 start assist (version 6) failed  "
++			   "on %s: 0x%x\n",
++			   QETH_CARD_IFNAME(card), rc);
++		return rc;
++	}
++	rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_PASSTHRU,
++					       IPA_CMD_ASS_START);
++	if (rc) {
++		PRINT_WARN("Could not enable passthrough "
++			   "on %s: 0x%x\n",
++			   QETH_CARD_IFNAME(card), rc);
++		return rc;
++	}
++out:
++	PRINT_INFO("IPV6 enabled \n");
++	return 0;
++}
++#endif
++
++static int qeth_l3_start_ipa_ipv6(struct qeth_card *card)
++{
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "strtipv6");
++
++	if (!qeth_is_supported(card, IPA_IPV6)) {
++		PRINT_WARN("IPv6 not supported on %s\n",
++			   QETH_CARD_IFNAME(card));
++		return 0;
++	}
++#ifdef CONFIG_QETH_IPV6
++	rc = qeth_l3_softsetup_ipv6(card);
++#endif
++	return rc ;
++}
++
++static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "stbrdcst");
++	card->info.broadcast_capable = 0;
++	if (!qeth_is_supported(card, IPA_FILTERING)) {
++		PRINT_WARN("Broadcast not supported on %s\n",
++			   QETH_CARD_IFNAME(card));
++		rc = -EOPNOTSUPP;
++		goto out;
++	}
++	rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
++					  IPA_CMD_ASS_START, 0);
++	if (rc) {
++		PRINT_WARN("Could not enable broadcasting filtering "
++			   "on %s: 0x%x\n",
++			   QETH_CARD_IFNAME(card), rc);
++		goto out;
++	}
++
++	rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
++					  IPA_CMD_ASS_CONFIGURE, 1);
++	if (rc) {
++		PRINT_WARN("Could not set up broadcast filtering on %s: 0x%x\n",
++			   QETH_CARD_IFNAME(card), rc);
++		goto out;
++	}
++	card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
++	PRINT_INFO("Broadcast enabled \n");
++	rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
++					  IPA_CMD_ASS_ENABLE, 1);
++	if (rc) {
++		PRINT_WARN("Could not set up broadcast echo filtering on "
++			   "%s: 0x%x\n", QETH_CARD_IFNAME(card), rc);
++		goto out;
++	}
++	card->info.broadcast_capable = QETH_BROADCAST_WITHOUT_ECHO;
++out:
++	if (card->info.broadcast_capable)
++		card->dev->flags |= IFF_BROADCAST;
++	else
++		card->dev->flags &= ~IFF_BROADCAST;
++	return rc;
++}
++
++static int qeth_l3_send_checksum_command(struct qeth_card *card)
++{
++	int rc;
++
++	rc = qeth_l3_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
++					  IPA_CMD_ASS_START, 0);
++	if (rc) {
++		PRINT_WARN("Starting Inbound HW Checksumming failed on %s: "
++			   "0x%x,\ncontinuing using Inbound SW Checksumming\n",
++			   QETH_CARD_IFNAME(card), rc);
++		return rc;
++	}
++	rc = qeth_l3_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
++					  IPA_CMD_ASS_ENABLE,
++					  card->info.csum_mask);
++	if (rc) {
++		PRINT_WARN("Enabling Inbound HW Checksumming failed on %s: "
++			   "0x%x,\ncontinuing using Inbound SW Checksumming\n",
++			   QETH_CARD_IFNAME(card), rc);
++		return rc;
++	}
++	return 0;
++}
++
++static int qeth_l3_start_ipa_checksum(struct qeth_card *card)
++{
++	int rc = 0;
++
++	QETH_DBF_TEXT(TRACE, 3, "strtcsum");
++
++	if (card->options.checksum_type == NO_CHECKSUMMING) {
++		PRINT_WARN("Using no checksumming on %s.\n",
++			   QETH_CARD_IFNAME(card));
++		return 0;
++	}
++	if (card->options.checksum_type == SW_CHECKSUMMING) {
++		PRINT_WARN("Using SW checksumming on %s.\n",
++			   QETH_CARD_IFNAME(card));
++		return 0;
++	}
++	if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) {
++		PRINT_WARN("Inbound HW Checksumming not "
++			   "supported on %s,\ncontinuing "
++			   "using Inbound SW Checksumming\n",
++			   QETH_CARD_IFNAME(card));
++		card->options.checksum_type = SW_CHECKSUMMING;
++		return 0;
++	}
++	rc = qeth_l3_send_checksum_command(card);
++	if (!rc)
++		PRINT_INFO("HW Checksumming (inbound) enabled \n");
++
++	return rc;
++}
++
++static int qeth_l3_start_ipa_tso(struct qeth_card *card)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "sttso");
++
++	if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
++		PRINT_WARN("Outbound TSO not supported on %s\n",
++			   QETH_CARD_IFNAME(card));
++		rc = -EOPNOTSUPP;
++	} else {
++		rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
++						IPA_CMD_ASS_START, 0);
++		if (rc)
++			PRINT_WARN("Could not start outbound TSO "
++				   "assist on %s: rc=%i\n",
++				   QETH_CARD_IFNAME(card), rc);
++		else
++			PRINT_INFO("Outbound TSO enabled\n");
++	}
++	if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)) {
++		card->options.large_send = QETH_LARGE_SEND_NO;
++		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
++	}
++	return rc;
++}
++
++static int qeth_l3_start_ipassists(struct qeth_card *card)
++{
++	QETH_DBF_TEXT(TRACE, 3, "strtipas");
++	qeth_l3_start_ipa_arp_processing(card);	/* go on*/
++	qeth_l3_start_ipa_ip_fragmentation(card);	/* go on*/
++	qeth_l3_start_ipa_source_mac(card);	/* go on*/
++	qeth_l3_start_ipa_vlan(card);		/* go on*/
++	qeth_l3_start_ipa_multicast(card);		/* go on*/
++	qeth_l3_start_ipa_ipv6(card);		/* go on*/
++	qeth_l3_start_ipa_broadcast(card);		/* go on*/
++	qeth_l3_start_ipa_checksum(card);		/* go on*/
++	qeth_l3_start_ipa_tso(card);		/* go on*/
++	return 0;
++}
++
++static int qeth_l3_put_unique_id(struct qeth_card *card)
++{
++
++	int rc = 0;
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(TRACE, 2, "puniqeid");
++
++	if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) ==
++		UNIQUE_ID_NOT_BY_CARD)
++		return -1;
++	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR,
++				     QETH_PROT_IPV6);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
++				card->info.unique_id;
++	memcpy(&cmd->data.create_destroy_addr.unique_id[0],
++	       card->dev->dev_addr, OSA_ADDR_LEN);
++	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++	return rc;
++}
++
++static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card,
++		struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->hdr.return_code == 0)
++		memcpy(card->dev->dev_addr,
++			cmd->data.create_destroy_addr.unique_id, ETH_ALEN);
++	else
++		random_ether_addr(card->dev->dev_addr);
++
++	return 0;
++}
++
++static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card)
++{
++	int rc = 0;
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(SETUP, 2, "hsrmac");
++
++	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
++				     QETH_PROT_IPV6);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
++			card->info.unique_id;
++
++	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_iqd_read_initial_mac_cb,
++				NULL);
++	return rc;
++}
++
++static int qeth_l3_get_unique_id_cb(struct qeth_card *card,
++		struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->hdr.return_code == 0)
++		card->info.unique_id = *((__u16 *)
++				&cmd->data.create_destroy_addr.unique_id[6]);
++	else {
++		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
++					UNIQUE_ID_NOT_BY_CARD;
++		PRINT_WARN("couldn't get a unique id from the card on device "
++			   "%s (result=x%x), using default id. ipv6 "
++			   "autoconfig on other lpars may lead to duplicate "
++			   "ip addresses. please use manually "
++			   "configured ones.\n",
++			   CARD_BUS_ID(card), cmd->hdr.return_code);
++	}
++	return 0;
++}
++
++static int qeth_l3_get_unique_id(struct qeth_card *card)
++{
++	int rc = 0;
++	struct qeth_cmd_buffer *iob;
++	struct qeth_ipa_cmd *cmd;
++
++	QETH_DBF_TEXT(SETUP, 2, "guniqeid");
++
++	if (!qeth_is_supported(card, IPA_IPV6)) {
++		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
++					UNIQUE_ID_NOT_BY_CARD;
++		return 0;
++	}
++
++	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
++				     QETH_PROT_IPV6);
++	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
++			card->info.unique_id;
++
++	rc = qeth_send_ipa_cmd(card, iob, qeth_l3_get_unique_id_cb, NULL);
++	return rc;
++}
++
++static void qeth_l3_get_mac_for_ipm(__u32 ipm, char *mac,
++				struct net_device *dev)
++{
++	if (dev->type == ARPHRD_IEEE802_TR)
++		ip_tr_mc_map(ipm, mac);
++	else
++		ip_eth_mc_map(ipm, mac);
++}
++
++static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev)
++{
++	struct qeth_ipaddr *ipm;
++	struct ip_mc_list *im4;
++	char buf[MAX_ADDR_LEN];
++
++	QETH_DBF_TEXT(TRACE, 4, "addmc");
++	for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
++		qeth_l3_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev);
++		ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
++		if (!ipm)
++			continue;
++		ipm->u.a4.addr = im4->multiaddr;
++		memcpy(ipm->mac, buf, OSA_ADDR_LEN);
++		ipm->is_multicast = 1;
++		if (!qeth_l3_add_ip(card, ipm))
++			kfree(ipm);
++	}
++}
++
++static void qeth_l3_add_vlan_mc(struct qeth_card *card)
++{
++	struct in_device *in_dev;
++	struct vlan_group *vg;
++	int i;
++
++	QETH_DBF_TEXT(TRACE, 4, "addmcvl");
++	if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
++		return;
++
++	vg = card->vlangrp;
++	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++		struct net_device *netdev = vlan_group_get_device(vg, i);
++		if (netdev == NULL ||
++		    !(netdev->flags & IFF_UP))
++			continue;
++		in_dev = in_dev_get(netdev);
++		if (!in_dev)
++			continue;
++		read_lock(&in_dev->mc_list_lock);
++		qeth_l3_add_mc(card, in_dev);
++		read_unlock(&in_dev->mc_list_lock);
++		in_dev_put(in_dev);
++	}
++}
++
++static void qeth_l3_add_multicast_ipv4(struct qeth_card *card)
++{
++	struct in_device *in4_dev;
++
++	QETH_DBF_TEXT(TRACE, 4, "chkmcv4");
++	in4_dev = in_dev_get(card->dev);
++	if (in4_dev == NULL)
++		return;
++	read_lock(&in4_dev->mc_list_lock);
++	qeth_l3_add_mc(card, in4_dev);
++	qeth_l3_add_vlan_mc(card);
++	read_unlock(&in4_dev->mc_list_lock);
++	in_dev_put(in4_dev);
++}
++
++#ifdef CONFIG_QETH_IPV6
++static void qeth_l3_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
++{
++	struct qeth_ipaddr *ipm;
++	struct ifmcaddr6 *im6;
++	char buf[MAX_ADDR_LEN];
++
++	QETH_DBF_TEXT(TRACE, 4, "addmc6");
++	for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
++		ndisc_mc_map(&im6->mca_addr, buf, in6_dev->dev, 0);
++		ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
++		if (!ipm)
++			continue;
++		ipm->is_multicast = 1;
++		memcpy(ipm->mac, buf, OSA_ADDR_LEN);
++		memcpy(&ipm->u.a6.addr, &im6->mca_addr.s6_addr,
++		       sizeof(struct in6_addr));
++		if (!qeth_l3_add_ip(card, ipm))
++			kfree(ipm);
++	}
++}
++
++static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
++{
++	struct inet6_dev *in_dev;
++	struct vlan_group *vg;
++	int i;
++
++	QETH_DBF_TEXT(TRACE, 4, "admc6vl");
++	if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
++		return;
++
++	vg = card->vlangrp;
++	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++		struct net_device *netdev = vlan_group_get_device(vg, i);
++		if (netdev == NULL ||
++		    !(netdev->flags & IFF_UP))
++			continue;
++		in_dev = in6_dev_get(netdev);
++		if (!in_dev)
++			continue;
++		read_lock_bh(&in_dev->lock);
++		qeth_l3_add_mc6(card, in_dev);
++		read_unlock_bh(&in_dev->lock);
++		in6_dev_put(in_dev);
++	}
++}
++
++static void qeth_l3_add_multicast_ipv6(struct qeth_card *card)
++{
++	struct inet6_dev *in6_dev;
++
++	QETH_DBF_TEXT(TRACE, 4, "chkmcv6");
++	if (!qeth_is_supported(card, IPA_IPV6))
++		return ;
++	in6_dev = in6_dev_get(card->dev);
++	if (in6_dev == NULL)
++		return;
++	read_lock_bh(&in6_dev->lock);
++	qeth_l3_add_mc6(card, in6_dev);
++	qeth_l3_add_vlan_mc6(card);
++	read_unlock_bh(&in6_dev->lock);
++	in6_dev_put(in6_dev);
++}
++#endif /* CONFIG_QETH_IPV6 */
++
++static void qeth_l3_free_vlan_addresses4(struct qeth_card *card,
++			unsigned short vid)
++{
++	struct in_device *in_dev;
++	struct in_ifaddr *ifa;
++	struct qeth_ipaddr *addr;
++
++	QETH_DBF_TEXT(TRACE, 4, "frvaddr4");
++
++	in_dev = in_dev_get(vlan_group_get_device(card->vlangrp, vid));
++	if (!in_dev)
++		return;
++	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
++		addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
++		if (addr) {
++			addr->u.a4.addr = ifa->ifa_address;
++			addr->u.a4.mask = ifa->ifa_mask;
++			addr->type = QETH_IP_TYPE_NORMAL;
++			if (!qeth_l3_delete_ip(card, addr))
++				kfree(addr);
++		}
++	}
++	in_dev_put(in_dev);
++}
++
++static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
++			unsigned short vid)
++{
++#ifdef CONFIG_QETH_IPV6
++	struct inet6_dev *in6_dev;
++	struct inet6_ifaddr *ifa;
++	struct qeth_ipaddr *addr;
++
++	QETH_DBF_TEXT(TRACE, 4, "frvaddr6");
++
++	in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
++	if (!in6_dev)
++		return;
++	for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next) {
++		addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
++		if (addr) {
++			memcpy(&addr->u.a6.addr, &ifa->addr,
++			       sizeof(struct in6_addr));
++			addr->u.a6.pfxlen = ifa->prefix_len;
++			addr->type = QETH_IP_TYPE_NORMAL;
++			if (!qeth_l3_delete_ip(card, addr))
++				kfree(addr);
++		}
++	}
++	in6_dev_put(in6_dev);
++#endif /* CONFIG_QETH_IPV6 */
++}
++
++static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
++			unsigned short vid)
++{
++	if (!card->vlangrp)
++		return;
++	qeth_l3_free_vlan_addresses4(card, vid);
++	qeth_l3_free_vlan_addresses6(card, vid);
++}
++
++static void qeth_l3_vlan_rx_register(struct net_device *dev,
++			struct vlan_group *grp)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	unsigned long flags;
++
++	QETH_DBF_TEXT(TRACE, 4, "vlanreg");
++	spin_lock_irqsave(&card->vlanlock, flags);
++	card->vlangrp = grp;
++	spin_unlock_irqrestore(&card->vlanlock, flags);
++}
++
++static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
++{
++	struct net_device *vlandev;
++	struct qeth_card *card = (struct qeth_card *) dev->priv;
++	struct in_device *in_dev;
++
++	if (card->info.type == QETH_CARD_TYPE_IQD)
++		return;
++
++	vlandev = vlan_group_get_device(card->vlangrp, vid);
++	vlandev->neigh_setup = qeth_l3_neigh_setup;
++
++	in_dev = in_dev_get(vlandev);
++#ifdef CONFIG_SYSCTL
++	neigh_sysctl_unregister(in_dev->arp_parms);
++#endif
++	neigh_parms_release(&arp_tbl, in_dev->arp_parms);
++
++	in_dev->arp_parms = neigh_parms_alloc(vlandev, &arp_tbl);
++#ifdef CONFIG_SYSCTL
++	neigh_sysctl_register(vlandev, in_dev->arp_parms, NET_IPV4,
++			      NET_IPV4_NEIGH, "ipv4", NULL, NULL);
++#endif
++	in_dev_put(in_dev);
++	return;
++}
++
++static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	unsigned long flags;
++
++	QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid);
++	spin_lock_irqsave(&card->vlanlock, flags);
++	/* unregister IP addresses of vlan device */
++	qeth_l3_free_vlan_addresses(card, vid);
++	vlan_group_set_device(card->vlangrp, vid, NULL);
++	spin_unlock_irqrestore(&card->vlanlock, flags);
++	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)
++{
++	unsigned short vlan_id = 0;
++	__be16 prot;
++	struct iphdr *ip_hdr;
++	unsigned char tg_addr[MAX_ADDR_LEN];
++
++	if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
++		prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
++			      ETH_P_IP);
++		switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK) {
++		case QETH_CAST_MULTICAST:
++			switch (prot) {
++#ifdef CONFIG_QETH_IPV6
++			case __constant_htons(ETH_P_IPV6):
++				ndisc_mc_map((struct in6_addr *)
++				     skb->data + 24,
++				     tg_addr, card->dev, 0);
++				break;
++#endif
++			case __constant_htons(ETH_P_IP):
++				ip_hdr = (struct iphdr *)skb->data;
++				(card->dev->type == ARPHRD_IEEE802_TR) ?
++				ip_tr_mc_map(ip_hdr->daddr, tg_addr):
++				ip_eth_mc_map(ip_hdr->daddr, tg_addr);
++				break;
++			default:
++				memcpy(tg_addr, card->dev->broadcast,
++					card->dev->addr_len);
++			}
++			card->stats.multicast++;
++			skb->pkt_type = PACKET_MULTICAST;
++			break;
++		case QETH_CAST_BROADCAST:
++			memcpy(tg_addr, card->dev->broadcast,
++				card->dev->addr_len);
++			card->stats.multicast++;
++			skb->pkt_type = PACKET_BROADCAST;
++			break;
++		case QETH_CAST_UNICAST:
++		case QETH_CAST_ANYCAST:
++		case QETH_CAST_NOCAST:
++		default:
++			skb->pkt_type = PACKET_HOST;
++			memcpy(tg_addr, card->dev->dev_addr,
++				card->dev->addr_len);
++		}
++		card->dev->header_ops->create(skb, card->dev, prot, tg_addr,
++					      "FAKELL", card->dev->addr_len);
++	}
++
++#ifdef CONFIG_TR
++	if (card->dev->type == ARPHRD_IEEE802_TR)
++		skb->protocol = tr_type_trans(skb, card->dev);
++	else
++#endif
++		skb->protocol = eth_type_trans(skb, card->dev);
++
++	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)?
++		 hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
++	}
++
++	skb->ip_summed = card->options.checksum_type;
++	if (card->options.checksum_type == HW_CHECKSUMMING) {
++		if ((hdr->hdr.l3.ext_flags &
++		      (QETH_HDR_EXT_CSUM_HDR_REQ |
++		       QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
++		     (QETH_HDR_EXT_CSUM_HDR_REQ |
++		      QETH_HDR_EXT_CSUM_TRANSP_REQ))
++			skb->ip_summed = CHECKSUM_UNNECESSARY;
++		else
++			skb->ip_summed = SW_CHECKSUMMING;
++	}
++
++	return vlan_id;
++}
++
++static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
++			    struct qeth_qdio_buffer *buf, int index)
++{
++	struct qdio_buffer_element *element;
++	struct sk_buff *skb;
++	struct qeth_hdr *hdr;
++	int offset;
++	__u16 vlan_tag = 0;
++	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;
++		}
++
++		switch (hdr->hdr.l3.id) {
++		case QETH_HEADER_TYPE_LAYER3:
++			vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr);
++			len = skb->len;
++			if (vlan_tag)
++				if (card->vlangrp)
++					vlan_hwaccel_rx(skb, card->vlangrp,
++						vlan_tag);
++				else {
++					dev_kfree_skb_any(skb);
++					continue;
++				}
++			else
++				netif_rx(skb);
++			break;
++		default:
++			dev_kfree_skb_any(skb);
++			QETH_DBF_TEXT(TRACE, 3, "inbunkno");
++			QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
++			continue;
++		}
++
++		card->dev->last_rx = jiffies;
++		card->stats.rx_packets++;
++		card->stats.rx_bytes += len;
++	}
++}
++
++static int qeth_l3_verify_vlan_dev(struct net_device *dev,
++			struct qeth_card *card)
++{
++	int rc = 0;
++	struct vlan_group *vg;
++	int i;
++
++	vg = card->vlangrp;
++	if (!vg)
++		return rc;
++
++	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++		if (vlan_group_get_device(vg, i) == dev) {
++			rc = QETH_VLAN_CARD;
++			break;
++		}
++	}
++
++	if (rc && !(netdev_priv(vlan_dev_info(dev)->real_dev) == (void *)card))
++		return 0;
++
++	return rc;
++}
++
++static int qeth_l3_verify_dev(struct net_device *dev)
++{
++	struct qeth_card *card;
++	unsigned long flags;
++	int rc = 0;
++
++	read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++	list_for_each_entry(card, &qeth_core_card_list.list, list) {
++		if (card->dev == dev) {
++			rc = QETH_REAL_CARD;
++			break;
++		}
++		rc = qeth_l3_verify_vlan_dev(dev, card);
++		if (rc)
++			break;
++	}
++	read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++
++	return rc;
++}
++
++static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
++{
++	struct qeth_card *card = NULL;
++	int rc;
++
++	rc = qeth_l3_verify_dev(dev);
++	if (rc == QETH_REAL_CARD)
++		card = netdev_priv(dev);
++	else if (rc == QETH_VLAN_CARD)
++		card = netdev_priv(vlan_dev_info(dev)->real_dev);
++	if (card->options.layer2)
++		card = NULL;
++	QETH_DBF_TEXT_(TRACE, 4, "%d", rc);
++	return card ;
++}
++
++static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
++{
++	int rc = 0;
++
++	QETH_DBF_TEXT(SETUP, 2, "stopcard");
++	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++	qeth_set_allowed_threads(card, 0, 1);
++	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
++		return -ERESTARTSYS;
++	if (card->read.state == CH_STATE_UP &&
++	    card->write.state == CH_STATE_UP &&
++	    (card->state == CARD_STATE_UP)) {
++		if (recovery_mode)
++			qeth_l3_stop(card->dev);
++		if (!card->use_hard_stop) {
++			rc = qeth_send_stoplan(card);
++			if (rc)
++				QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		}
++		card->state = CARD_STATE_SOFTSETUP;
++	}
++	if (card->state == CARD_STATE_SOFTSETUP) {
++		qeth_l3_clear_ip_list(card, !card->use_hard_stop, 1);
++		qeth_clear_ipacmd_list(card);
++		card->state = CARD_STATE_HARDSETUP;
++	}
++	if (card->state == CARD_STATE_HARDSETUP) {
++		if (!card->use_hard_stop &&
++		    (card->info.type != QETH_CARD_TYPE_IQD)) {
++			rc = qeth_l3_put_unique_id(card);
++			if (rc)
++				QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++		}
++		qeth_qdio_clear_card(card, 0);
++		qeth_clear_qdio_buffers(card);
++		qeth_clear_working_pool_list(card);
++		card->state = CARD_STATE_DOWN;
++	}
++	if (card->state == CARD_STATE_DOWN) {
++		qeth_clear_cmd_buffers(&card->read);
++		qeth_clear_cmd_buffers(&card->write);
++	}
++	card->use_hard_stop = 0;
++	return rc;
++}
++
++static void qeth_l3_set_multicast_list(struct net_device *dev)
++{
++	struct qeth_card *card = netdev_priv(dev);
++
++	QETH_DBF_TEXT(TRACE, 3, "setmulti");
++	qeth_l3_delete_mc_addresses(card);
++	qeth_l3_add_multicast_ipv4(card);
++#ifdef CONFIG_QETH_IPV6
++	qeth_l3_add_multicast_ipv6(card);
++#endif
++	qeth_l3_set_ip_addr_list(card);
++	if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
++		return;
++	qeth_setadp_promisc_mode(card);
++}
++
++static const char *qeth_l3_arp_get_error_cause(int *rc)
++{
++	switch (*rc) {
++	case QETH_IPA_ARP_RC_FAILED:
++		*rc = -EIO;
++		return "operation failed";
++	case QETH_IPA_ARP_RC_NOTSUPP:
++		*rc = -EOPNOTSUPP;
++		return "operation not supported";
++	case QETH_IPA_ARP_RC_OUT_OF_RANGE:
++		*rc = -EINVAL;
++		return "argument out of range";
++	case QETH_IPA_ARP_RC_Q_NOTSUPP:
++		*rc = -EOPNOTSUPP;
++		return "query operation not supported";
++	case QETH_IPA_ARP_RC_Q_NO_DATA:
++		*rc = -ENOENT;
++		return "no query data available";
++	default:
++		return "unknown error";
++	}
++}
++
++static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
++{
++	int tmp;
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "arpstnoe");
++
++	/*
++	 * currently GuestLAN only supports the ARP assist function
++	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
++	 * thus we say EOPNOTSUPP for this ARP function
++	 */
++	if (card->info.guestlan)
++		return -EOPNOTSUPP;
++	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++		PRINT_WARN("ARP processing not supported "
++			   "on %s!\n", QETH_CARD_IFNAME(card));
++		return -EOPNOTSUPP;
++	}
++	rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
++					  IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
++					  no_entries);
++	if (rc) {
++		tmp = rc;
++		PRINT_WARN("Could not set number of ARP entries on %s: "
++			"%s (0x%x/%d)\n", QETH_CARD_IFNAME(card),
++			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++	}
++	return rc;
++}
++
++static void qeth_l3_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
++		struct qeth_arp_query_data *qdata, int entry_size,
++		int uentry_size)
++{
++	char *entry_ptr;
++	char *uentry_ptr;
++	int i;
++
++	entry_ptr = (char *)&qdata->data;
++	uentry_ptr = (char *)(qinfo->udata + qinfo->udata_offset);
++	for (i = 0; i < qdata->no_entries; ++i) {
++		/* strip off 32 bytes "media specific information" */
++		memcpy(uentry_ptr, (entry_ptr + 32), entry_size - 32);
++		entry_ptr += entry_size;
++		uentry_ptr += uentry_size;
++	}
++}
++
++static int qeth_l3_arp_query_cb(struct qeth_card *card,
++		struct qeth_reply *reply, unsigned long data)
++{
++	struct qeth_ipa_cmd *cmd;
++	struct qeth_arp_query_data *qdata;
++	struct qeth_arp_query_info *qinfo;
++	int entry_size;
++	int uentry_size;
++	int i;
++
++	QETH_DBF_TEXT(TRACE, 4, "arpquecb");
++
++	qinfo = (struct qeth_arp_query_info *) reply->param;
++	cmd = (struct qeth_ipa_cmd *) data;
++	if (cmd->hdr.return_code) {
++		QETH_DBF_TEXT_(TRACE, 4, "qaer1%i", cmd->hdr.return_code);
++		return 0;
++	}
++	if (cmd->data.setassparms.hdr.return_code) {
++		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
++		QETH_DBF_TEXT_(TRACE, 4, "qaer2%i", cmd->hdr.return_code);
++		return 0;
++	}
++	qdata = &cmd->data.setassparms.data.query_arp;
++	switch (qdata->reply_bits) {
++	case 5:
++		uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry5);
++		if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
++			uentry_size = sizeof(struct qeth_arp_qi_entry5_short);
++		break;
++	case 7:
++		/* fall through to default */
++	default:
++		/* tr is the same as eth -> entry7 */
++		uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry7);
++		if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
++			uentry_size = sizeof(struct qeth_arp_qi_entry7_short);
++		break;
++	}
++	/* check if there is enough room in userspace */
++	if ((qinfo->udata_len - qinfo->udata_offset) <
++			qdata->no_entries * uentry_size){
++		QETH_DBF_TEXT_(TRACE, 4, "qaer3%i", -ENOMEM);
++		cmd->hdr.return_code = -ENOMEM;
++		PRINT_WARN("query ARP user space buffer is too small for "
++			   "the returned number of ARP entries. "
++			   "Aborting query!\n");
++		goto out_error;
++	}
++	QETH_DBF_TEXT_(TRACE, 4, "anore%i",
++		       cmd->data.setassparms.hdr.number_of_replies);
++	QETH_DBF_TEXT_(TRACE, 4, "aseqn%i", cmd->data.setassparms.hdr.seq_no);
++	QETH_DBF_TEXT_(TRACE, 4, "anoen%i", qdata->no_entries);
++
++	if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) {
++		/* strip off "media specific information" */
++		qeth_l3_copy_arp_entries_stripped(qinfo, qdata, entry_size,
++					       uentry_size);
++	} else
++		/*copy entries to user buffer*/
++		memcpy(qinfo->udata + qinfo->udata_offset,
++		       (char *)&qdata->data, qdata->no_entries*uentry_size);
++
++	qinfo->no_entries += qdata->no_entries;
++	qinfo->udata_offset += (qdata->no_entries*uentry_size);
++	/* check if all replies received ... */
++	if (cmd->data.setassparms.hdr.seq_no <
++	    cmd->data.setassparms.hdr.number_of_replies)
++		return 1;
++	memcpy(qinfo->udata, &qinfo->no_entries, 4);
++	/* keep STRIP_ENTRIES flag so the user program can distinguish
++	 * stripped entries from normal ones */
++	if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
++		qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES;
++	memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2);
++	return 0;
++out_error:
++	i = 0;
++	memcpy(qinfo->udata, &i, 4);
++	return 0;
++}
++
++static int qeth_l3_send_ipa_arp_cmd(struct qeth_card *card,
++		struct qeth_cmd_buffer *iob, int len,
++		int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
++			unsigned long),
++		void *reply_param)
++{
++	QETH_DBF_TEXT(TRACE, 4, "sendarp");
++
++	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
++	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
++	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
++	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
++				      reply_cb, reply_param);
++}
++
++static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
++{
++	struct qeth_cmd_buffer *iob;
++	struct qeth_arp_query_info qinfo = {0, };
++	int tmp;
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "arpquery");
++
++	if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
++			       IPA_ARP_PROCESSING)) {
++		PRINT_WARN("ARP processing not supported "
++			   "on %s!\n", QETH_CARD_IFNAME(card));
++		return -EOPNOTSUPP;
++	}
++	/* get size of userspace buffer and mask_bits -> 6 bytes */
++	if (copy_from_user(&qinfo, udata, 6))
++		return -EFAULT;
++	qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
++	if (!qinfo.udata)
++		return -ENOMEM;
++	qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
++	iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
++				       IPA_CMD_ASS_ARP_QUERY_INFO,
++				       sizeof(int), QETH_PROT_IPV4);
++
++	rc = qeth_l3_send_ipa_arp_cmd(card, iob,
++				   QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
++				   qeth_l3_arp_query_cb, (void *)&qinfo);
++	if (rc) {
++		tmp = rc;
++		PRINT_WARN("Error while querying ARP cache on %s: %s "
++			"(0x%x/%d)\n", QETH_CARD_IFNAME(card),
++			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++		if (copy_to_user(udata, qinfo.udata, 4))
++			rc = -EFAULT;
++	} else {
++		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
++			rc = -EFAULT;
++	}
++	kfree(qinfo.udata);
++	return rc;
++}
++
++static int qeth_l3_arp_add_entry(struct qeth_card *card,
++				struct qeth_arp_cache_entry *entry)
++{
++	struct qeth_cmd_buffer *iob;
++	char buf[16];
++	int tmp;
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "arpadent");
++
++	/*
++	 * currently GuestLAN only supports the ARP assist function
++	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
++	 * thus we say EOPNOTSUPP for this ARP function
++	 */
++	if (card->info.guestlan)
++		return -EOPNOTSUPP;
++	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++		PRINT_WARN("ARP processing not supported "
++			   "on %s!\n", QETH_CARD_IFNAME(card));
++		return -EOPNOTSUPP;
++	}
++
++	iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
++				       IPA_CMD_ASS_ARP_ADD_ENTRY,
++				       sizeof(struct qeth_arp_cache_entry),
++				       QETH_PROT_IPV4);
++	rc = qeth_l3_send_setassparms(card, iob,
++				   sizeof(struct qeth_arp_cache_entry),
++				   (unsigned long) entry,
++				   qeth_l3_default_setassparms_cb, NULL);
++	if (rc) {
++		tmp = rc;
++		qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
++		PRINT_WARN("Could not add ARP entry for address %s on %s: "
++			   "%s (0x%x/%d)\n",
++			   buf, QETH_CARD_IFNAME(card),
++			   qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++	}
++	return rc;
++}
++
++static int qeth_l3_arp_remove_entry(struct qeth_card *card,
++				struct qeth_arp_cache_entry *entry)
++{
++	struct qeth_cmd_buffer *iob;
++	char buf[16] = {0, };
++	int tmp;
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 3, "arprment");
++
++	/*
++	 * currently GuestLAN only supports the ARP assist function
++	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
++	 * thus we say EOPNOTSUPP for this ARP function
++	 */
++	if (card->info.guestlan)
++		return -EOPNOTSUPP;
++	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++		PRINT_WARN("ARP processing not supported "
++			   "on %s!\n", QETH_CARD_IFNAME(card));
++		return -EOPNOTSUPP;
++	}
++	memcpy(buf, entry, 12);
++	iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
++				       IPA_CMD_ASS_ARP_REMOVE_ENTRY,
++				       12,
++				       QETH_PROT_IPV4);
++	rc = qeth_l3_send_setassparms(card, iob,
++				   12, (unsigned long)buf,
++				   qeth_l3_default_setassparms_cb, NULL);
++	if (rc) {
++		tmp = rc;
++		memset(buf, 0, 16);
++		qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
++		PRINT_WARN("Could not delete ARP entry for address %s on %s: "
++			   "%s (0x%x/%d)\n",
++			   buf, QETH_CARD_IFNAME(card),
++			   qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++	}
++	return rc;
++}
++
++static int qeth_l3_arp_flush_cache(struct qeth_card *card)
++{
++	int rc;
++	int tmp;
++
++	QETH_DBF_TEXT(TRACE, 3, "arpflush");
++
++	/*
++	 * currently GuestLAN only supports the ARP assist function
++	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
++	 * thus we say EOPNOTSUPP for this ARP function
++	*/
++	if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
++		return -EOPNOTSUPP;
++	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++		PRINT_WARN("ARP processing not supported "
++			   "on %s!\n", QETH_CARD_IFNAME(card));
++		return -EOPNOTSUPP;
++	}
++	rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
++					  IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
++	if (rc) {
++		tmp = rc;
++		PRINT_WARN("Could not flush ARP cache on %s: %s (0x%x/%d)\n",
++			QETH_CARD_IFNAME(card),
++			qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++	}
++	return rc;
++}
++
++static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	struct qeth_arp_cache_entry arp_entry;
++	struct mii_ioctl_data *mii_data;
++	int rc = 0;
++
++	if (!card)
++		return -ENODEV;
++
++	if ((card->state != CARD_STATE_UP) &&
++		(card->state != CARD_STATE_SOFTSETUP))
++		return -ENODEV;
++
++	switch (cmd) {
++	case SIOC_QETH_ARP_SET_NO_ENTRIES:
++		if (!capable(CAP_NET_ADMIN)) {
++			rc = -EPERM;
++			break;
++		}
++		rc = qeth_l3_arp_set_no_entries(card, rq->ifr_ifru.ifru_ivalue);
++		break;
++	case SIOC_QETH_ARP_QUERY_INFO:
++		if (!capable(CAP_NET_ADMIN)) {
++			rc = -EPERM;
++			break;
++		}
++		rc = qeth_l3_arp_query(card, rq->ifr_ifru.ifru_data);
++		break;
++	case SIOC_QETH_ARP_ADD_ENTRY:
++		if (!capable(CAP_NET_ADMIN)) {
++			rc = -EPERM;
++			break;
++		}
++		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
++				   sizeof(struct qeth_arp_cache_entry)))
++			rc = -EFAULT;
++		else
++			rc = qeth_l3_arp_add_entry(card, &arp_entry);
++		break;
++	case SIOC_QETH_ARP_REMOVE_ENTRY:
++		if (!capable(CAP_NET_ADMIN)) {
++			rc = -EPERM;
++			break;
++		}
++		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
++				   sizeof(struct qeth_arp_cache_entry)))
++			rc = -EFAULT;
++		else
++			rc = qeth_l3_arp_remove_entry(card, &arp_entry);
++		break;
++	case SIOC_QETH_ARP_FLUSH_CACHE:
++		if (!capable(CAP_NET_ADMIN)) {
++			rc = -EPERM;
++			break;
++		}
++		rc = qeth_l3_arp_flush_cache(card);
++		break;
++	case SIOC_QETH_ADP_SET_SNMP_CONTROL:
++		rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
++		break;
++	case SIOC_QETH_GET_CARD_TYPE:
++		if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
++		    !card->info.guestlan)
++			return 1;
++		return 0;
++		break;
++	case SIOCGMIIPHY:
++		mii_data = if_mii(rq);
++		mii_data->phy_id = 0;
++		break;
++	case SIOCGMIIREG:
++		mii_data = if_mii(rq);
++		if (mii_data->phy_id != 0)
++			rc = -EINVAL;
++		else
++			mii_data->val_out = qeth_mdio_read(dev,
++							mii_data->phy_id,
++							mii_data->reg_num);
++		break;
++	default:
++		rc = -EOPNOTSUPP;
++	}
++	if (rc)
++		QETH_DBF_TEXT_(TRACE, 2, "ioce%d", rc);
++	return rc;
++}
++
++static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
++		struct sk_buff *skb, int ipv, int cast_type)
++{
++	QETH_DBF_TEXT(TRACE, 6, "fillhdr");
++
++	memset(hdr, 0, sizeof(struct qeth_hdr));
++	hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
++	hdr->hdr.l3.ext_flags = 0;
++
++	/*
++	 * before we're going to overwrite this location with next hop ip.
++	 * v6 uses passthrough, v4 sets the tag in the QDIO header.
++	 */
++	if (card->vlangrp && vlan_tx_tag_present(skb)) {
++		hdr->hdr.l3.ext_flags = (ipv == 4) ?
++			QETH_HDR_EXT_VLAN_FRAME :
++			QETH_HDR_EXT_INCLUDE_VLAN_TAG;
++		hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
++	}
++
++	hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
++	if (ipv == 4) {
++		/* IPv4 */
++		hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type);
++		memset(hdr->hdr.l3.dest_addr, 0, 12);
++		if ((skb->dst) && (skb->dst->neighbour)) {
++			*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
++			    *((u32 *) skb->dst->neighbour->primary_key);
++		} else {
++			/* fill in destination address used in ip header */
++			*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
++							ip_hdr(skb)->daddr;
++		}
++	} else if (ipv == 6) {
++		/* IPv6 */
++		hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type);
++		if (card->info.type == QETH_CARD_TYPE_IQD)
++			hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU;
++		if ((skb->dst) && (skb->dst->neighbour)) {
++			memcpy(hdr->hdr.l3.dest_addr,
++			       skb->dst->neighbour->primary_key, 16);
++		} else {
++			/* fill in destination address used in ip header */
++			memcpy(hdr->hdr.l3.dest_addr,
++			       &ipv6_hdr(skb)->daddr, 16);
++		}
++	} else {
++		/* passthrough */
++		if ((skb->dev->type == ARPHRD_IEEE802_TR) &&
++			!memcmp(skb->data + sizeof(struct qeth_hdr) +
++			sizeof(__u16), skb->dev->broadcast, 6)) {
++			hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
++						QETH_HDR_PASSTHRU;
++		} else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
++			    skb->dev->broadcast, 6)) {
++			/* broadcast? */
++			hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
++						QETH_HDR_PASSTHRU;
++		} else {
++			hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
++				QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
++				QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
++		}
++	}
++}
++
++static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	int rc;
++	u16 *tag;
++	struct qeth_hdr *hdr = NULL;
++	int elements_needed = 0;
++	struct qeth_card *card = netdev_priv(dev);
++	struct sk_buff *new_skb = NULL;
++	int ipv = qeth_get_ip_version(skb);
++	int cast_type = qeth_get_cast_type(card, skb);
++	struct qeth_qdio_out_q *queue = card->qdio.out_qs
++		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
++	int tx_bytes = skb->len;
++	enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
++	struct qeth_eddp_context *ctx = NULL;
++
++	QETH_DBF_TEXT(TRACE, 6, "l3xmit");
++
++	if ((card->info.type == QETH_CARD_TYPE_IQD) &&
++	    (skb->protocol != htons(ETH_P_IPV6)) &&
++	    (skb->protocol != htons(ETH_P_IP)))
++			goto tx_drop;
++
++	if ((card->state != CARD_STATE_UP) || !card->lan_online) {
++		card->stats.tx_carrier_errors++;
++		goto tx_drop;
++	}
++
++	if ((cast_type == RTN_BROADCAST) &&
++	    (card->info.broadcast_capable == 0))
++		goto tx_drop;
++
++	if (card->options.performance_stats) {
++		card->perf_stats.outbound_cnt++;
++		card->perf_stats.outbound_start_time = qeth_get_micros();
++	}
++
++	/* create a clone with writeable headroom */
++	new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso) +
++					VLAN_HLEN);
++	if (!new_skb)
++		goto tx_drop;
++
++	if (card->info.type == QETH_CARD_TYPE_IQD) {
++		skb_pull(new_skb, ETH_HLEN);
++	} else {
++		if (new_skb->protocol == htons(ETH_P_IP)) {
++			if (card->dev->type == ARPHRD_IEEE802_TR)
++				skb_pull(new_skb, TR_HLEN);
++			else
++				skb_pull(new_skb, ETH_HLEN);
++		}
++
++		if (new_skb->protocol == ETH_P_IPV6 && card->vlangrp &&
++				vlan_tx_tag_present(new_skb)) {
++			skb_push(new_skb, VLAN_HLEN);
++			skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4);
++			skb_copy_to_linear_data_offset(new_skb, 4,
++				new_skb->data + 8, 4);
++			skb_copy_to_linear_data_offset(new_skb, 8,
++				new_skb->data + 12, 4);
++			tag = (u16 *)(new_skb->data + 12);
++			*tag = __constant_htons(ETH_P_8021Q);
++			*(tag + 1) = htons(vlan_tx_tag_get(new_skb));
++			VLAN_TX_SKB_CB(new_skb)->magic = 0;
++		}
++	}
++
++	netif_stop_queue(dev);
++
++	if (skb_is_gso(new_skb))
++		large_send = card->options.large_send;
++
++	/* fix hardware limitation: as long as we do not have sbal
++	 * chaining we can not send long frag lists so we temporary
++	 * switch to EDDP
++	 */
++	if ((large_send == QETH_LARGE_SEND_TSO) &&
++		((skb_shinfo(new_skb)->nr_frags + 2) > 16))
++		large_send = QETH_LARGE_SEND_EDDP;
++
++	if ((large_send == QETH_LARGE_SEND_TSO) &&
++	    (cast_type == RTN_UNSPEC)) {
++		hdr = (struct qeth_hdr *)skb_push(new_skb,
++						sizeof(struct qeth_hdr_tso));
++		memset(hdr, 0, sizeof(struct qeth_hdr_tso));
++		qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
++		qeth_tso_fill_header(card, hdr, new_skb);
++		elements_needed++;
++	} else {
++		hdr = (struct qeth_hdr *)skb_push(new_skb,
++						sizeof(struct qeth_hdr));
++		qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
++	}
++
++	if (large_send == QETH_LARGE_SEND_EDDP) {
++		/* new_skb is not owned by a socket so we use skb to get
++		 * the protocol
++		 */
++		ctx = qeth_eddp_create_context(card, new_skb, hdr,
++						skb->sk->sk_protocol);
++		if (ctx == NULL) {
++			PRINT_WARN("could not create eddp context\n");
++			goto tx_drop;
++		}
++	} else {
++		int elems = qeth_get_elements_no(card, (void *)hdr, new_skb,
++						 elements_needed);
++		if (!elems)
++			goto tx_drop;
++		elements_needed += elems;
++	}
++
++	if ((large_send == QETH_LARGE_SEND_NO) &&
++	    (new_skb->ip_summed == CHECKSUM_PARTIAL))
++		qeth_tx_csum(new_skb);
++
++	if (card->info.type != QETH_CARD_TYPE_IQD)
++		rc = qeth_do_send_packet(card, queue, new_skb, hdr,
++					 elements_needed, ctx);
++	else
++		rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
++					      elements_needed, ctx);
++
++	if (!rc) {
++		card->stats.tx_packets++;
++		card->stats.tx_bytes += tx_bytes;
++		if (new_skb != skb)
++			dev_kfree_skb_any(skb);
++		if (card->options.performance_stats) {
++			if (large_send != QETH_LARGE_SEND_NO) {
++				card->perf_stats.large_send_bytes += tx_bytes;
++				card->perf_stats.large_send_cnt++;
++			}
++			if (skb_shinfo(new_skb)->nr_frags > 0) {
++				card->perf_stats.sg_skbs_sent++;
++				/* nr_frags + skb->data */
++				card->perf_stats.sg_frags_sent +=
++					skb_shinfo(new_skb)->nr_frags + 1;
++			}
++		}
++
++		if (ctx != NULL) {
++			qeth_eddp_put_context(ctx);
++			dev_kfree_skb_any(new_skb);
++		}
++	} else {
++		if (ctx != NULL)
++			qeth_eddp_put_context(ctx);
++
++		if (rc == -EBUSY) {
++			if (new_skb != skb)
++				dev_kfree_skb_any(new_skb);
++			return NETDEV_TX_BUSY;
++		} else
++			goto tx_drop;
++	}
++
++	netif_wake_queue(dev);
++	if (card->options.performance_stats)
++		card->perf_stats.outbound_time += qeth_get_micros() -
++			card->perf_stats.outbound_start_time;
++	return rc;
++
++tx_drop:
++	card->stats.tx_dropped++;
++	card->stats.tx_errors++;
++	if ((new_skb != skb) && new_skb)
++		dev_kfree_skb_any(new_skb);
++	dev_kfree_skb_any(skb);
++	return NETDEV_TX_OK;
++}
++
++static int qeth_l3_open(struct net_device *dev)
++{
++	struct qeth_card *card = netdev_priv(dev);
++
++	QETH_DBF_TEXT(TRACE, 4, "qethopen");
++	if (card->state != CARD_STATE_SOFTSETUP)
++		return -ENODEV;
++	card->data.state = CH_STATE_UP;
++	card->state = CARD_STATE_UP;
++	card->dev->flags |= IFF_UP;
++	netif_start_queue(dev);
++
++	if (!card->lan_online && netif_carrier_ok(dev))
++		netif_carrier_off(dev);
++	return 0;
++}
++
++static int qeth_l3_stop(struct net_device *dev)
++{
++	struct qeth_card *card = netdev_priv(dev);
++
++	QETH_DBF_TEXT(TRACE, 4, "qethstop");
++	netif_tx_disable(dev);
++	card->dev->flags &= ~IFF_UP;
++	if (card->state == CARD_STATE_UP)
++		card->state = CARD_STATE_SOFTSETUP;
++	return 0;
++}
++
++static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev)
++{
++	struct qeth_card *card = netdev_priv(dev);
++
++	return (card->options.checksum_type == HW_CHECKSUMMING);
++}
++
++static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data)
++{
++	struct qeth_card *card = netdev_priv(dev);
++	enum qeth_card_states old_state;
++	enum qeth_checksum_types csum_type;
++
++	if ((card->state != CARD_STATE_UP) &&
++	    (card->state != CARD_STATE_DOWN))
++		return -EPERM;
++
++	if (data)
++		csum_type = HW_CHECKSUMMING;
++	else
++		csum_type = SW_CHECKSUMMING;
++
++	if (card->options.checksum_type != csum_type) {
++		old_state = card->state;
++		if (card->state == CARD_STATE_UP)
++			__qeth_l3_set_offline(card->gdev, 1);
++		card->options.checksum_type = csum_type;
++		if (old_state == CARD_STATE_UP)
++			__qeth_l3_set_online(card->gdev, 1);
++	}
++	return 0;
++}
++
++static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data)
++{
++	struct qeth_card *card = netdev_priv(dev);
++
++	if (data) {
++		if (card->options.large_send == QETH_LARGE_SEND_NO) {
++			if (card->info.type == QETH_CARD_TYPE_IQD)
++				card->options.large_send = QETH_LARGE_SEND_EDDP;
++			else
++				card->options.large_send = QETH_LARGE_SEND_TSO;
++			dev->features |= NETIF_F_TSO;
++		}
++	} else {
++		dev->features &= ~NETIF_F_TSO;
++		card->options.large_send = QETH_LARGE_SEND_NO;
++	}
++	return 0;
++}
++
++static struct ethtool_ops qeth_l3_ethtool_ops = {
++	.get_link = ethtool_op_get_link,
++	.get_tx_csum = ethtool_op_get_tx_csum,
++	.set_tx_csum = ethtool_op_set_tx_hw_csum,
++	.get_rx_csum = qeth_l3_ethtool_get_rx_csum,
++	.set_rx_csum = qeth_l3_ethtool_set_rx_csum,
++	.get_sg      = ethtool_op_get_sg,
++	.set_sg      = ethtool_op_set_sg,
++	.get_tso     = ethtool_op_get_tso,
++	.set_tso     = qeth_l3_ethtool_set_tso,
++	.get_strings = qeth_core_get_strings,
++	.get_ethtool_stats = qeth_core_get_ethtool_stats,
++	.get_stats_count = qeth_core_get_stats_count,
++	.get_drvinfo = qeth_core_get_drvinfo,
++};
++
++/*
++ * we need NOARP for IPv4 but we want neighbor solicitation for IPv6. Setting
++ * NOARP on the netdevice is no option because it also turns off neighbor
++ * solicitation. For IPv4 we install a neighbor_setup function. We don't want
++ * arp resolution but we want the hard header (packet socket will work
++ * e.g. tcpdump)
++ */
++static int qeth_l3_neigh_setup_noarp(struct neighbour *n)
++{
++	n->nud_state = NUD_NOARP;
++	memcpy(n->ha, "FAKELL", 6);
++	n->output = n->ops->connected_output;
++	return 0;
++}
++
++static int
++qeth_l3_neigh_setup(struct net_device *dev, struct neigh_parms *np)
++{
++	if (np->tbl->family == AF_INET)
++		np->neigh_setup = qeth_l3_neigh_setup_noarp;
++
++	return 0;
++}
++
++static int qeth_l3_setup_netdev(struct qeth_card *card)
++{
++	if (card->info.type == QETH_CARD_TYPE_OSAE) {
++		if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
++		    (card->info.link_type == QETH_LINK_TYPE_HSTR)) {
++#ifdef CONFIG_TR
++			card->dev = alloc_trdev(0);
++#endif
++			if (!card->dev)
++				return -ENODEV;
++		} else {
++			card->dev = alloc_etherdev(0);
++			if (!card->dev)
++				return -ENODEV;
++			card->dev->neigh_setup = qeth_l3_neigh_setup;
++
++			/*IPv6 address autoconfiguration stuff*/
++			qeth_l3_get_unique_id(card);
++			if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
++				card->dev->dev_id = card->info.unique_id &
++							 0xffff;
++		}
++	} else if (card->info.type == QETH_CARD_TYPE_IQD) {
++		card->dev = alloc_netdev(0, "hsi%d", ether_setup);
++		if (!card->dev)
++			return -ENODEV;
++		card->dev->flags |= IFF_NOARP;
++		qeth_l3_iqd_read_initial_mac(card);
++	} else
++		return -ENODEV;
++
++	card->dev->hard_start_xmit = qeth_l3_hard_start_xmit;
++	card->dev->priv = card;
++	card->dev->tx_timeout = &qeth_tx_timeout;
++	card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
++	card->dev->open = qeth_l3_open;
++	card->dev->stop = qeth_l3_stop;
++	card->dev->do_ioctl = qeth_l3_do_ioctl;
++	card->dev->get_stats = qeth_get_stats;
++	card->dev->change_mtu = qeth_change_mtu;
++	card->dev->set_multicast_list = qeth_l3_set_multicast_list;
++	card->dev->vlan_rx_register = qeth_l3_vlan_rx_register;
++	card->dev->vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid;
++	card->dev->vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid;
++	card->dev->mtu = card->info.initial_mtu;
++	card->dev->set_mac_address = NULL;
++	SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops);
++	card->dev->features |=	NETIF_F_HW_VLAN_TX |
++				NETIF_F_HW_VLAN_RX |
++				NETIF_F_HW_VLAN_FILTER;
++
++	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
++	return register_netdev(card->dev);
++}
++
++static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
++		unsigned int status, unsigned int qdio_err,
++		unsigned int siga_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;
++
++	QETH_DBF_TEXT(TRACE, 6, "qdinput");
++	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 (status & QDIO_STATUS_LOOK_FOR_ERROR) {
++		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
++			QETH_DBF_TEXT(TRACE, 1, "qdinchk");
++			QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++			QETH_DBF_TEXT_(TRACE, 1, "%04X%04X",
++					first_element, count);
++			QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", queue, status);
++			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 (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
++		      qeth_check_qdio_errors(buffer->buffer,
++					     qdio_err, siga_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.input_handler = (qdio_handler_t *)
++		qeth_l3_qdio_input_handler;
++	card->discipline.output_handler = (qdio_handler_t *)
++		qeth_qdio_output_handler;
++	card->discipline.recover = qeth_l3_recover;
++	return 0;
++}
++
++static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
++{
++	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
++
++	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
++
++	if (cgdev->state == CCWGROUP_ONLINE) {
++		card->use_hard_stop = 1;
++		qeth_l3_set_offline(cgdev);
++	}
++
++	if (card->dev) {
++		unregister_netdev(card->dev);
++		card->dev = NULL;
++	}
++
++	qeth_l3_remove_device_attributes(&cgdev->dev);
++	qeth_l3_clear_ip_list(card, 0, 0);
++	qeth_l3_clear_ipato_list(card);
++	return;
++}
++
++static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
++{
++	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++	int rc = 0;
++	enum qeth_card_states recover_flag;
++
++	BUG_ON(!card);
++	QETH_DBF_TEXT(SETUP, 2, "setonlin");
++	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++	qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
++	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) {
++		PRINT_WARN("set_online of card %s interrupted by user!\n",
++			   CARD_BUS_ID(card));
++		return -ERESTARTSYS;
++	}
++
++	recover_flag = card->state;
++	rc = ccw_device_set_online(CARD_RDEV(card));
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		return -EIO;
++	}
++	rc = ccw_device_set_online(CARD_WDEV(card));
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		return -EIO;
++	}
++	rc = ccw_device_set_online(CARD_DDEV(card));
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		return -EIO;
++	}
++
++	rc = qeth_core_hardsetup_card(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++		goto out_remove;
++	}
++
++	qeth_l3_query_ipassists(card, QETH_PROT_IPV4);
++
++	if (!card->dev && qeth_l3_setup_netdev(card))
++		goto out_remove;
++
++	card->state = CARD_STATE_HARDSETUP;
++	qeth_print_status_message(card);
++
++	/* softsetup */
++	QETH_DBF_TEXT(SETUP, 2, "softsetp");
++
++	rc = qeth_send_startlan(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++		if (rc == 0xe080) {
++			PRINT_WARN("LAN on card %s if offline! "
++				   "Waiting for STARTLAN from card.\n",
++				   CARD_BUS_ID(card));
++			card->lan_online = 0;
++		}
++		return rc;
++	} else
++		card->lan_online = 1;
++	qeth_set_large_send(card, card->options.large_send);
++
++	rc = qeth_l3_setadapter_parms(card);
++	if (rc)
++		QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++	rc = qeth_l3_start_ipassists(card);
++	if (rc)
++		QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++	rc = qeth_l3_setrouting_v4(card);
++	if (rc)
++		QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc);
++	rc = qeth_l3_setrouting_v6(card);
++	if (rc)
++		QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
++	netif_tx_disable(card->dev);
++
++	rc = qeth_init_qdio_queues(card);
++	if (rc) {
++		QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
++		goto out_remove;
++	}
++	card->state = CARD_STATE_SOFTSETUP;
++	netif_carrier_on(card->dev);
++
++	qeth_set_allowed_threads(card, 0xffffffff, 0);
++	if ((recover_flag == CARD_STATE_RECOVER) && recovery_mode) {
++			qeth_l3_open(card->dev);
++			qeth_l3_set_multicast_list(card->dev);
++	}
++	/* let user_space know that device is online */
++	kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
++	return 0;
++out_remove:
++	card->use_hard_stop = 1;
++	qeth_l3_stop_card(card, 0);
++	ccw_device_set_offline(CARD_DDEV(card));
++	ccw_device_set_offline(CARD_WDEV(card));
++	ccw_device_set_offline(CARD_RDEV(card));
++	if (recover_flag == CARD_STATE_RECOVER)
++		card->state = CARD_STATE_RECOVER;
++	else
++		card->state = CARD_STATE_DOWN;
++	return -ENODEV;
++}
++
++static int qeth_l3_set_online(struct ccwgroup_device *gdev)
++{
++	return __qeth_l3_set_online(gdev, 0);
++}
++
++static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
++			int recovery_mode)
++{
++	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
++	int rc = 0, rc2 = 0, rc3 = 0;
++	enum qeth_card_states recover_flag;
++
++	QETH_DBF_TEXT(SETUP, 3, "setoffl");
++	QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
++
++	if (card->dev && netif_carrier_ok(card->dev))
++		netif_carrier_off(card->dev);
++	recover_flag = card->state;
++	if (qeth_l3_stop_card(card, recovery_mode) == -ERESTARTSYS) {
++		PRINT_WARN("Stopping card %s interrupted by user!\n",
++			   CARD_BUS_ID(card));
++		return -ERESTARTSYS;
++	}
++	rc  = ccw_device_set_offline(CARD_DDEV(card));
++	rc2 = ccw_device_set_offline(CARD_WDEV(card));
++	rc3 = ccw_device_set_offline(CARD_RDEV(card));
++	if (!rc)
++		rc = (rc2) ? rc2 : rc3;
++	if (rc)
++		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++	if (recover_flag == CARD_STATE_UP)
++		card->state = CARD_STATE_RECOVER;
++	/* let user_space know that device is offline */
++	kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
++	return 0;
++}
++
++static int qeth_l3_set_offline(struct ccwgroup_device *cgdev)
++{
++	return __qeth_l3_set_offline(cgdev, 0);
++}
++
++static int qeth_l3_recover(void *ptr)
++{
++	struct qeth_card *card;
++	int rc = 0;
++
++	card = (struct qeth_card *) ptr;
++	QETH_DBF_TEXT(TRACE, 2, "recover1");
++	QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *));
++	if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
++		return 0;
++	QETH_DBF_TEXT(TRACE, 2, "recover2");
++	PRINT_WARN("Recovery of device %s started ...\n",
++		   CARD_BUS_ID(card));
++	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)
++		PRINT_INFO("Device %s successfully recovered!\n",
++			   CARD_BUS_ID(card));
++	else
++		PRINT_INFO("Device %s could not be recovered!\n",
++			   CARD_BUS_ID(card));
++	return 0;
++}
++
++static void qeth_l3_shutdown(struct ccwgroup_device *gdev)
++{
++	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++	qeth_l3_clear_ip_list(card, 0, 0);
++	qeth_qdio_clear_card(card, 0);
++	qeth_clear_qdio_buffers(card);
++}
++
++struct ccwgroup_driver qeth_l3_ccwgroup_driver = {
++	.probe = qeth_l3_probe_device,
++	.remove = qeth_l3_remove_device,
++	.set_online = qeth_l3_set_online,
++	.set_offline = qeth_l3_set_offline,
++	.shutdown = qeth_l3_shutdown,
++};
++EXPORT_SYMBOL_GPL(qeth_l3_ccwgroup_driver);
++
++static int qeth_l3_ip_event(struct notifier_block *this,
++			    unsigned long event, void *ptr)
++{
++	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
++	struct net_device *dev = (struct net_device *)ifa->ifa_dev->dev;
++	struct qeth_ipaddr *addr;
++	struct qeth_card *card;
++
++	if (dev_net(dev) != &init_net)
++		return NOTIFY_DONE;
++
++	QETH_DBF_TEXT(TRACE, 3, "ipevent");
++	card = qeth_l3_get_card_from_dev(dev);
++	if (!card)
++		return NOTIFY_DONE;
++
++	addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
++	if (addr != NULL) {
++		addr->u.a4.addr = ifa->ifa_address;
++		addr->u.a4.mask = ifa->ifa_mask;
++		addr->type = QETH_IP_TYPE_NORMAL;
++	} else
++		goto out;
++
++	switch (event) {
++	case NETDEV_UP:
++		if (!qeth_l3_add_ip(card, addr))
++			kfree(addr);
++		break;
++	case NETDEV_DOWN:
++		if (!qeth_l3_delete_ip(card, addr))
++			kfree(addr);
++		break;
++	default:
++		break;
++	}
++	qeth_l3_set_ip_addr_list(card);
++out:
++	return NOTIFY_DONE;
++}
++
++static struct notifier_block qeth_l3_ip_notifier = {
++	qeth_l3_ip_event,
++	NULL,
++};
++
++#ifdef CONFIG_QETH_IPV6
++/**
++ * IPv6 event handler
++ */
++static int qeth_l3_ip6_event(struct notifier_block *this,
++			     unsigned long event, void *ptr)
++{
++	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
++	struct net_device *dev = (struct net_device *)ifa->idev->dev;
++	struct qeth_ipaddr *addr;
++	struct qeth_card *card;
++
++	QETH_DBF_TEXT(TRACE, 3, "ip6event");
++
++	card = qeth_l3_get_card_from_dev(dev);
++	if (!card)
++		return NOTIFY_DONE;
++	if (!qeth_is_supported(card, IPA_IPV6))
++		return NOTIFY_DONE;
++
++	addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
++	if (addr != NULL) {
++		memcpy(&addr->u.a6.addr, &ifa->addr, sizeof(struct in6_addr));
++		addr->u.a6.pfxlen = ifa->prefix_len;
++		addr->type = QETH_IP_TYPE_NORMAL;
++	} else
++		goto out;
++
++	switch (event) {
++	case NETDEV_UP:
++		if (!qeth_l3_add_ip(card, addr))
++			kfree(addr);
++		break;
++	case NETDEV_DOWN:
++		if (!qeth_l3_delete_ip(card, addr))
++			kfree(addr);
++		break;
++	default:
++		break;
++	}
++	qeth_l3_set_ip_addr_list(card);
++out:
++	return NOTIFY_DONE;
++}
++
++static struct notifier_block qeth_l3_ip6_notifier = {
++	qeth_l3_ip6_event,
++	NULL,
++};
++#endif
++
++static int qeth_l3_register_notifiers(void)
++{
++	int rc;
++
++	QETH_DBF_TEXT(TRACE, 5, "regnotif");
++	rc = register_inetaddr_notifier(&qeth_l3_ip_notifier);
++	if (rc)
++		return rc;
++#ifdef CONFIG_QETH_IPV6
++	rc = register_inet6addr_notifier(&qeth_l3_ip6_notifier);
++	if (rc) {
++		unregister_inetaddr_notifier(&qeth_l3_ip_notifier);
++		return rc;
++	}
++#else
++	PRINT_WARN("layer 3 discipline no IPv6 support\n");
++#endif
++	return 0;
++}
++
++static void qeth_l3_unregister_notifiers(void)
++{
++
++	QETH_DBF_TEXT(TRACE, 5, "unregnot");
++	BUG_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
++#ifdef CONFIG_QETH_IPV6
++	BUG_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
++#endif /* QETH_IPV6 */
++}
++
++static int __init qeth_l3_init(void)
++{
++	int rc = 0;
++
++	PRINT_INFO("register layer 3 discipline\n");
++	rc = qeth_l3_register_notifiers();
++	return rc;
++}
++
++static void __exit qeth_l3_exit(void)
++{
++	qeth_l3_unregister_notifiers();
++	PRINT_INFO("unregister layer 3 discipline\n");
++}
++
++module_init(qeth_l3_init);
++module_exit(qeth_l3_exit);
++MODULE_AUTHOR("Frank Blaschka <frank.blaschka at de.ibm.com>");
++MODULE_DESCRIPTION("qeth layer 3 discipline");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
+new file mode 100644
+index 0000000..08f51fd
+--- /dev/null
++++ b/drivers/s390/net/qeth_l3_sys.c
+@@ -0,0 +1,1051 @@
++/*
++ *  drivers/s390/net/qeth_l3_sys.c
++ *
++ *    Copyright IBM Corp. 2007
++ *    Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ *		 Frank Pavlic <fpavlic at de.ibm.com>,
++ *		 Thomas Spatzier <tspat at de.ibm.com>,
++ *		 Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include "qeth_l3.h"
++
++#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
++struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
++
++static const char *qeth_l3_get_checksum_str(struct qeth_card *card)
++{
++	if (card->options.checksum_type == SW_CHECKSUMMING)
++		return "sw";
++	else if (card->options.checksum_type == HW_CHECKSUMMING)
++		return "hw";
++	else
++		return "no";
++}
++
++static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
++			struct qeth_routing_info *route, char *buf)
++{
++	switch (route->type) {
++	case PRIMARY_ROUTER:
++		return sprintf(buf, "%s\n", "primary router");
++	case SECONDARY_ROUTER:
++		return sprintf(buf, "%s\n", "secondary router");
++	case MULTICAST_ROUTER:
++		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
++			return sprintf(buf, "%s\n", "multicast router+");
++		else
++			return sprintf(buf, "%s\n", "multicast router");
++	case PRIMARY_CONNECTOR:
++		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
++			return sprintf(buf, "%s\n", "primary connector+");
++		else
++			return sprintf(buf, "%s\n", "primary connector");
++	case SECONDARY_CONNECTOR:
++		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
++			return sprintf(buf, "%s\n", "secondary connector+");
++		else
++			return sprintf(buf, "%s\n", "secondary connector");
++	default:
++		return sprintf(buf, "%s\n", "no");
++	}
++}
++
++static ssize_t qeth_l3_dev_route4_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_route_show(card, &card->options.route4, buf);
++}
++
++static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
++		struct qeth_routing_info *route, enum qeth_prot_versions prot,
++		const char *buf, size_t count)
++{
++	enum qeth_routing_types old_route_type = route->type;
++	char *tmp;
++	int rc;
++
++	tmp = strsep((char **) &buf, "\n");
++
++	if (!strcmp(tmp, "no_router")) {
++		route->type = NO_ROUTER;
++	} else if (!strcmp(tmp, "primary_connector")) {
++		route->type = PRIMARY_CONNECTOR;
++	} else if (!strcmp(tmp, "secondary_connector")) {
++		route->type = SECONDARY_CONNECTOR;
++	} else if (!strcmp(tmp, "primary_router")) {
++		route->type = PRIMARY_ROUTER;
++	} else if (!strcmp(tmp, "secondary_router")) {
++		route->type = SECONDARY_ROUTER;
++	} else if (!strcmp(tmp, "multicast_router")) {
++		route->type = MULTICAST_ROUTER;
++	} else {
++		PRINT_WARN("Invalid routing type '%s'.\n", tmp);
++		return -EINVAL;
++	}
++	if (((card->state == CARD_STATE_SOFTSETUP) ||
++	     (card->state == CARD_STATE_UP)) &&
++	    (old_route_type != route->type)) {
++		if (prot == QETH_PROT_IPV4)
++			rc = qeth_l3_setrouting_v4(card);
++		else if (prot == QETH_PROT_IPV6)
++			rc = qeth_l3_setrouting_v6(card);
++	}
++	return count;
++}
++
++static ssize_t qeth_l3_dev_route4_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_route_store(card, &card->options.route4,
++				QETH_PROT_IPV4, buf, count);
++}
++
++static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
++			qeth_l3_dev_route4_store);
++
++static ssize_t qeth_l3_dev_route6_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	if (!qeth_is_supported(card, IPA_IPV6))
++		return sprintf(buf, "%s\n", "n/a");
++
++	return qeth_l3_dev_route_show(card, &card->options.route6, buf);
++}
++
++static ssize_t qeth_l3_dev_route6_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	if (!qeth_is_supported(card, IPA_IPV6)) {
++		PRINT_WARN("IPv6 not supported for interface %s.\n"
++			   "Routing status no changed.\n",
++			   QETH_CARD_IFNAME(card));
++		return -ENOTSUPP;
++	}
++
++	return qeth_l3_dev_route_store(card, &card->options.route6,
++				QETH_PROT_IPV6, buf, count);
++}
++
++static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
++			qeth_l3_dev_route6_store);
++
++static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
++}
++
++static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++	int i;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	i = simple_strtoul(buf, &tmp, 16);
++	if ((i == 0) || (i == 1))
++		card->options.fake_broadcast = i;
++	else {
++		PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n");
++		return -EINVAL;
++	}
++	return count;
++}
++
++static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
++		   qeth_l3_dev_fake_broadcast_store);
++
++static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
++		return sprintf(buf, "n/a\n");
++
++	return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
++				     QETH_TR_BROADCAST_ALLRINGS)?
++		       "all rings":"local");
++}
++
++static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
++		PRINT_WARN("Device is not a tokenring device!\n");
++		return -EINVAL;
++	}
++
++	tmp = strsep((char **) &buf, "\n");
++
++	if (!strcmp(tmp, "local")) {
++		card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
++		return count;
++	} else if (!strcmp(tmp, "all_rings")) {
++		card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
++		return count;
++	} else {
++		PRINT_WARN("broadcast_mode: invalid mode %s!\n",
++			   tmp);
++		return -EINVAL;
++	}
++	return count;
++}
++
++static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
++		   qeth_l3_dev_broadcast_mode_store);
++
++static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
++		return sprintf(buf, "n/a\n");
++
++	return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
++				     QETH_TR_MACADDR_CANONICAL)? 1:0);
++}
++
++static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++	int i;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
++		PRINT_WARN("Device is not a tokenring device!\n");
++		return -EINVAL;
++	}
++
++	i = simple_strtoul(buf, &tmp, 16);
++	if ((i == 0) || (i == 1))
++		card->options.macaddr_mode = i?
++			QETH_TR_MACADDR_CANONICAL :
++			QETH_TR_MACADDR_NONCANONICAL;
++	else {
++		PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n");
++		return -EINVAL;
++	}
++	return count;
++}
++
++static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
++		   qeth_l3_dev_canonical_macaddr_store);
++
++static ssize_t qeth_l3_dev_checksum_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%s checksumming\n",
++			qeth_l3_get_checksum_str(card));
++}
++
++static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	tmp = strsep((char **) &buf, "\n");
++	if (!strcmp(tmp, "sw_checksumming"))
++		card->options.checksum_type = SW_CHECKSUMMING;
++	else if (!strcmp(tmp, "hw_checksumming"))
++		card->options.checksum_type = HW_CHECKSUMMING;
++	else if (!strcmp(tmp, "no_checksumming"))
++		card->options.checksum_type = NO_CHECKSUMMING;
++	else {
++		PRINT_WARN("Unknown checksumming type '%s'\n", tmp);
++		return -EINVAL;
++	}
++	return count;
++}
++
++static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
++		qeth_l3_dev_checksum_store);
++
++static struct attribute *qeth_l3_device_attrs[] = {
++	&dev_attr_route4.attr,
++	&dev_attr_route6.attr,
++	&dev_attr_fake_broadcast.attr,
++	&dev_attr_broadcast_mode.attr,
++	&dev_attr_canonical_macaddr.attr,
++	&dev_attr_checksumming.attr,
++	NULL,
++};
++
++static struct attribute_group qeth_l3_device_attr_group = {
++	.attrs = qeth_l3_device_attrs,
++};
++
++static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
++}
++
++static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++
++	if (!card)
++		return -EINVAL;
++
++	if ((card->state != CARD_STATE_DOWN) &&
++	    (card->state != CARD_STATE_RECOVER))
++		return -EPERM;
++
++	tmp = strsep((char **) &buf, "\n");
++	if (!strcmp(tmp, "toggle")) {
++		card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
++	} else if (!strcmp(tmp, "1")) {
++		card->ipato.enabled = 1;
++	} else if (!strcmp(tmp, "0")) {
++		card->ipato.enabled = 0;
++	} else {
++		PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
++			   "this file\n");
++		return -EINVAL;
++	}
++	return count;
++}
++
++static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
++			qeth_l3_dev_ipato_enable_show,
++			qeth_l3_dev_ipato_enable_store);
++
++static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
++}
++
++static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
++				struct device_attribute *attr,
++				const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++
++	if (!card)
++		return -EINVAL;
++
++	tmp = strsep((char **) &buf, "\n");
++	if (!strcmp(tmp, "toggle")) {
++		card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
++	} else if (!strcmp(tmp, "1")) {
++		card->ipato.invert4 = 1;
++	} else if (!strcmp(tmp, "0")) {
++		card->ipato.invert4 = 0;
++	} else {
++		PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
++			   "this file\n");
++		return -EINVAL;
++	}
++	return count;
++}
++
++static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
++			qeth_l3_dev_ipato_invert4_show,
++			qeth_l3_dev_ipato_invert4_store);
++
++static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
++			enum qeth_prot_versions proto)
++{
++	struct qeth_ipato_entry *ipatoe;
++	unsigned long flags;
++	char addr_str[40];
++	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
++	int i = 0;
++
++	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
++	/* add strlen for "/<mask>\n" */
++	entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
++	spin_lock_irqsave(&card->ip_lock, flags);
++	list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
++		if (ipatoe->proto != proto)
++			continue;
++		/* String must not be longer than PAGE_SIZE. So we check if
++		 * string length gets near PAGE_SIZE. Then we can savely display
++		 * the next IPv6 address (worst case, compared to IPv4) */
++		if ((PAGE_SIZE - i) <= entry_len)
++			break;
++		qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
++		i += snprintf(buf + i, PAGE_SIZE - i,
++			      "%s/%i\n", addr_str, ipatoe->mask_bits);
++	}
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
++
++	return i;
++}
++
++static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
++}
++
++static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
++		  u8 *addr, int *mask_bits)
++{
++	const char *start, *end;
++	char *tmp;
++	char buffer[40] = {0, };
++
++	start = buf;
++	/* get address string */
++	end = strchr(start, '/');
++	if (!end || (end - start >= 40)) {
++		PRINT_WARN("Invalid format for ipato_addx/delx. "
++			   "Use <ip addr>/<mask bits>\n");
++		return -EINVAL;
++	}
++	strncpy(buffer, start, end - start);
++	if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
++		PRINT_WARN("Invalid IP address format!\n");
++		return -EINVAL;
++	}
++	start = end + 1;
++	*mask_bits = simple_strtoul(start, &tmp, 10);
++	if (!strlen(start) ||
++	    (tmp == start) ||
++	    (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
++		PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n");
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
++			 struct qeth_card *card, enum qeth_prot_versions proto)
++{
++	struct qeth_ipato_entry *ipatoe;
++	u8 addr[16];
++	int mask_bits;
++	int rc;
++
++	rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
++	if (rc)
++		return rc;
++
++	ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
++	if (!ipatoe) {
++		PRINT_WARN("No memory to allocate ipato entry\n");
++		return -ENOMEM;
++	}
++	ipatoe->proto = proto;
++	memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
++	ipatoe->mask_bits = mask_bits;
++
++	rc = qeth_l3_add_ipato_entry(card, ipatoe);
++	if (rc) {
++		kfree(ipatoe);
++		return rc;
++	}
++
++	return count;
++}
++
++static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
++			qeth_l3_dev_ipato_add4_show,
++			qeth_l3_dev_ipato_add4_store);
++
++static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
++			 struct qeth_card *card, enum qeth_prot_versions proto)
++{
++	u8 addr[16];
++	int mask_bits;
++	int rc;
++
++	rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
++	if (rc)
++		return rc;
++
++	qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
++
++	return count;
++}
++
++static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
++			qeth_l3_dev_ipato_del4_store);
++
++static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
++		struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
++}
++
++static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++	char *tmp;
++
++	if (!card)
++		return -EINVAL;
++
++	tmp = strsep((char **) &buf, "\n");
++	if (!strcmp(tmp, "toggle")) {
++		card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
++	} else if (!strcmp(tmp, "1")) {
++		card->ipato.invert6 = 1;
++	} else if (!strcmp(tmp, "0")) {
++		card->ipato.invert6 = 0;
++	} else {
++		PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to "
++			   "this file\n");
++		return -EINVAL;
++	}
++	return count;
++}
++
++static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
++			qeth_l3_dev_ipato_invert6_show,
++			qeth_l3_dev_ipato_invert6_store);
++
++
++static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
++}
++
++static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
++			qeth_l3_dev_ipato_add6_show,
++			qeth_l3_dev_ipato_add6_store);
++
++static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
++			qeth_l3_dev_ipato_del6_store);
++
++static struct attribute *qeth_ipato_device_attrs[] = {
++	&dev_attr_ipato_enable.attr,
++	&dev_attr_ipato_invert4.attr,
++	&dev_attr_ipato_add4.attr,
++	&dev_attr_ipato_del4.attr,
++	&dev_attr_ipato_invert6.attr,
++	&dev_attr_ipato_add6.attr,
++	&dev_attr_ipato_del6.attr,
++	NULL,
++};
++
++static struct attribute_group qeth_device_ipato_group = {
++	.name = "ipa_takeover",
++	.attrs = qeth_ipato_device_attrs,
++};
++
++static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
++			enum qeth_prot_versions proto)
++{
++	struct qeth_ipaddr *ipaddr;
++	char addr_str[40];
++	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
++	unsigned long flags;
++	int i = 0;
++
++	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
++	entry_len += 2; /* \n + terminator */
++	spin_lock_irqsave(&card->ip_lock, flags);
++	list_for_each_entry(ipaddr, &card->ip_list, entry) {
++		if (ipaddr->proto != proto)
++			continue;
++		if (ipaddr->type != QETH_IP_TYPE_VIPA)
++			continue;
++		/* String must not be longer than PAGE_SIZE. So we check if
++		 * string length gets near PAGE_SIZE. Then we can savely display
++		 * the next IPv6 address (worst case, compared to IPv4) */
++		if ((PAGE_SIZE - i) <= entry_len)
++			break;
++		qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
++			addr_str);
++		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
++	}
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
++
++	return i;
++}
++
++static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
++}
++
++static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
++		 u8 *addr)
++{
++	if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
++		PRINT_WARN("Invalid IP address format!\n");
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
++			struct qeth_card *card, enum qeth_prot_versions proto)
++{
++	u8 addr[16] = {0, };
++	int rc;
++
++	rc = qeth_l3_parse_vipae(buf, proto, addr);
++	if (rc)
++		return rc;
++
++	rc = qeth_l3_add_vipa(card, proto, addr);
++	if (rc)
++		return rc;
++
++	return count;
++}
++
++static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
++			qeth_l3_dev_vipa_add4_show,
++			qeth_l3_dev_vipa_add4_store);
++
++static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
++			 struct qeth_card *card, enum qeth_prot_versions proto)
++{
++	u8 addr[16];
++	int rc;
++
++	rc = qeth_l3_parse_vipae(buf, proto, addr);
++	if (rc)
++		return rc;
++
++	qeth_l3_del_vipa(card, proto, addr);
++
++	return count;
++}
++
++static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
++			qeth_l3_dev_vipa_del4_store);
++
++static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
++}
++
++static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
++			qeth_l3_dev_vipa_add6_show,
++			qeth_l3_dev_vipa_add6_store);
++
++static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
++			qeth_l3_dev_vipa_del6_store);
++
++static struct attribute *qeth_vipa_device_attrs[] = {
++	&dev_attr_vipa_add4.attr,
++	&dev_attr_vipa_del4.attr,
++	&dev_attr_vipa_add6.attr,
++	&dev_attr_vipa_del6.attr,
++	NULL,
++};
++
++static struct attribute_group qeth_device_vipa_group = {
++	.name = "vipa",
++	.attrs = qeth_vipa_device_attrs,
++};
++
++static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
++		       enum qeth_prot_versions proto)
++{
++	struct qeth_ipaddr *ipaddr;
++	char addr_str[40];
++	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
++	unsigned long flags;
++	int i = 0;
++
++	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
++	entry_len += 2; /* \n + terminator */
++	spin_lock_irqsave(&card->ip_lock, flags);
++	list_for_each_entry(ipaddr, &card->ip_list, entry) {
++		if (ipaddr->proto != proto)
++			continue;
++		if (ipaddr->type != QETH_IP_TYPE_RXIP)
++			continue;
++		/* String must not be longer than PAGE_SIZE. So we check if
++		 * string length gets near PAGE_SIZE. Then we can savely display
++		 * the next IPv6 address (worst case, compared to IPv4) */
++		if ((PAGE_SIZE - i) <= entry_len)
++			break;
++		qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
++			addr_str);
++		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
++	}
++	spin_unlock_irqrestore(&card->ip_lock, flags);
++	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
++
++	return i;
++}
++
++static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
++}
++
++static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
++		 u8 *addr)
++{
++	if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
++		PRINT_WARN("Invalid IP address format!\n");
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
++			struct qeth_card *card, enum qeth_prot_versions proto)
++{
++	u8 addr[16] = {0, };
++	int rc;
++
++	rc = qeth_l3_parse_rxipe(buf, proto, addr);
++	if (rc)
++		return rc;
++
++	rc = qeth_l3_add_rxip(card, proto, addr);
++	if (rc)
++		return rc;
++
++	return count;
++}
++
++static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
++			qeth_l3_dev_rxip_add4_show,
++			qeth_l3_dev_rxip_add4_store);
++
++static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
++			struct qeth_card *card, enum qeth_prot_versions proto)
++{
++	u8 addr[16];
++	int rc;
++
++	rc = qeth_l3_parse_rxipe(buf, proto, addr);
++	if (rc)
++		return rc;
++
++	qeth_l3_del_rxip(card, proto, addr);
++
++	return count;
++}
++
++static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
++			qeth_l3_dev_rxip_del4_store);
++
++static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
++		struct device_attribute *attr, char *buf)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
++}
++
++static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
++			qeth_l3_dev_rxip_add6_show,
++			qeth_l3_dev_rxip_add6_store);
++
++static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct qeth_card *card = dev_get_drvdata(dev);
++
++	if (!card)
++		return -EINVAL;
++
++	return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
++			qeth_l3_dev_rxip_del6_store);
++
++static struct attribute *qeth_rxip_device_attrs[] = {
++	&dev_attr_rxip_add4.attr,
++	&dev_attr_rxip_del4.attr,
++	&dev_attr_rxip_add6.attr,
++	&dev_attr_rxip_del6.attr,
++	NULL,
++};
++
++static struct attribute_group qeth_device_rxip_group = {
++	.name = "rxip",
++	.attrs = qeth_rxip_device_attrs,
++};
++
++int qeth_l3_create_device_attributes(struct device *dev)
++{
++	int ret;
++
++	ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
++	if (ret)
++		return ret;
++
++	ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
++	if (ret) {
++		sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
++		return ret;
++	}
++
++	ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
++	if (ret) {
++		sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
++		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
++		return ret;
++	}
++
++	ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
++	if (ret) {
++		sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
++		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
++		sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
++		return ret;
++	}
++	return 0;
++}
++
++void qeth_l3_remove_device_attributes(struct device *dev)
++{
++	sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
++	sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
++	sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
++	sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
++}
+diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
+deleted file mode 100644
+index 62606ce..0000000
+--- a/drivers/s390/net/qeth_main.c
++++ /dev/null
+@@ -1,8956 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_main.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- *    Author(s): Original Code written by
+- *			  Utz Bacher (utz.bacher at de.ibm.com)
+- *		 Rewritten by
+- *			  Frank Pavlic (fpavlic at de.ibm.com) and
+- *		 	  Thomas Spatzier <tspat at de.ibm.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/mm.h>
+-#include <linux/ip.h>
+-#include <linux/inetdevice.h>
+-#include <linux/netdevice.h>
+-#include <linux/sched.h>
+-#include <linux/workqueue.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
+-#include <linux/interrupt.h>
+-#include <linux/tcp.h>
+-#include <linux/icmp.h>
+-#include <linux/skbuff.h>
+-#include <linux/in.h>
+-#include <linux/igmp.h>
+-#include <linux/init.h>
+-#include <linux/reboot.h>
+-#include <linux/mii.h>
+-#include <linux/rcupdate.h>
+-#include <linux/ethtool.h>
+-
+-#include <net/arp.h>
+-#include <net/ip.h>
+-#include <net/route.h>
+-
+-#include <asm/ebcdic.h>
+-#include <asm/io.h>
+-#include <asm/qeth.h>
+-#include <asm/timex.h>
+-#include <asm/semaphore.h>
+-#include <asm/uaccess.h>
+-#include <asm/s390_rdev.h>
+-
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_fs.h"
+-#include "qeth_eddp.h"
+-#include "qeth_tso.h"
+-
+-static const char *version = "qeth S/390 OSA-Express driver";
+-
+-/**
+- * Debug Facility Stuff
+- */
+-static debug_info_t *qeth_dbf_setup = NULL;
+-static debug_info_t *qeth_dbf_data = NULL;
+-static debug_info_t *qeth_dbf_misc = NULL;
+-static debug_info_t *qeth_dbf_control = NULL;
+-debug_info_t *qeth_dbf_trace = NULL;
+-static debug_info_t *qeth_dbf_sense = NULL;
+-static debug_info_t *qeth_dbf_qerr = NULL;
+-
+-DEFINE_PER_CPU(char[256], qeth_dbf_txt_buf);
+-
+-static struct lock_class_key qdio_out_skb_queue_key;
+-
+-/**
+- * some more definitions and declarations
+- */
+-static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
+-
+-/* list of our cards */
+-struct qeth_card_list_struct qeth_card_list;
+-/*process list want to be notified*/
+-spinlock_t qeth_notify_lock;
+-struct list_head qeth_notify_list;
+-
+-static void qeth_send_control_data_cb(struct qeth_channel *,
+-				      struct qeth_cmd_buffer *);
+-
+-/**
+- * here we go with function implementation
+- */
+-static void
+-qeth_init_qdio_info(struct qeth_card *card);
+-
+-static int
+-qeth_init_qdio_queues(struct qeth_card *card);
+-
+-static int
+-qeth_alloc_qdio_buffers(struct qeth_card *card);
+-
+-static void
+-qeth_free_qdio_buffers(struct qeth_card *);
+-
+-static void
+-qeth_clear_qdio_buffers(struct qeth_card *);
+-
+-static void
+-qeth_clear_ip_list(struct qeth_card *, int, int);
+-
+-static void
+-qeth_clear_ipacmd_list(struct qeth_card *);
+-
+-static int
+-qeth_qdio_clear_card(struct qeth_card *, int);
+-
+-static void
+-qeth_clear_working_pool_list(struct qeth_card *);
+-
+-static void
+-qeth_clear_cmd_buffers(struct qeth_channel *);
+-
+-static int
+-qeth_stop(struct net_device *);
+-
+-static void
+-qeth_clear_ipato_list(struct qeth_card *);
+-
+-static int
+-qeth_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *);
+-
+-static void
+-qeth_irq_tasklet(unsigned long);
+-
+-static int
+-qeth_set_online(struct ccwgroup_device *);
+-
+-static int
+-__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode);
+-
+-static struct qeth_ipaddr *
+-qeth_get_addr_buffer(enum qeth_prot_versions);
+-
+-static void
+-qeth_set_multicast_list(struct net_device *);
+-
+-static void
+-qeth_setadp_promisc_mode(struct qeth_card *);
+-
+-static int
+-qeth_hard_header_parse(const struct sk_buff *skb, unsigned char *haddr);
+-
+-static void
+-qeth_notify_processes(void)
+-{
+-	/*notify all  registered processes */
+-	struct qeth_notify_list_struct *n_entry;
+-
+-	QETH_DBF_TEXT(trace,3,"procnoti");
+-	spin_lock(&qeth_notify_lock);
+-	list_for_each_entry(n_entry, &qeth_notify_list, list) {
+-		send_sig(n_entry->signum, n_entry->task, 1);
+-	}
+-	spin_unlock(&qeth_notify_lock);
+-
+-}
+-int
+-qeth_notifier_unregister(struct task_struct *p)
+-{
+-	struct qeth_notify_list_struct *n_entry, *tmp;
+-
+-	QETH_DBF_TEXT(trace, 2, "notunreg");
+-	spin_lock(&qeth_notify_lock);
+-	list_for_each_entry_safe(n_entry, tmp, &qeth_notify_list, list) {
+-		if (n_entry->task == p) {
+-			list_del(&n_entry->list);
+-			kfree(n_entry);
+-			goto out;
+-		}
+-	}
+-out:
+-	spin_unlock(&qeth_notify_lock);
+-	return 0;
+-}
+-int
+-qeth_notifier_register(struct task_struct *p, int signum)
+-{
+-	struct qeth_notify_list_struct *n_entry;
+-
+-	/*check first if entry already exists*/
+-	spin_lock(&qeth_notify_lock);
+-	list_for_each_entry(n_entry, &qeth_notify_list, list) {
+-		if (n_entry->task == p) {
+-			n_entry->signum = signum;
+-			spin_unlock(&qeth_notify_lock);
+-			return 0;
+-		}
+-	}
+-	spin_unlock(&qeth_notify_lock);
+-
+-	n_entry = (struct qeth_notify_list_struct *)
+-		kmalloc(sizeof(struct qeth_notify_list_struct),GFP_KERNEL);
+-	if (!n_entry)
+-		return -ENOMEM;
+-	n_entry->task = p;
+-	n_entry->signum = signum;
+-	spin_lock(&qeth_notify_lock);
+-	list_add(&n_entry->list,&qeth_notify_list);
+-	spin_unlock(&qeth_notify_lock);
+-	return 0;
+-}
+-
+-
+-/**
+- * free channel command buffers
+- */
+-static void
+-qeth_clean_channel(struct qeth_channel *channel)
+-{
+-	int cnt;
+-
+-	QETH_DBF_TEXT(setup, 2, "freech");
+-	for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
+-		kfree(channel->iob[cnt].data);
+-}
+-
+-/**
+- * free card
+- */
+-static void
+-qeth_free_card(struct qeth_card *card)
+-{
+-
+-	QETH_DBF_TEXT(setup, 2, "freecrd");
+-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-	qeth_clean_channel(&card->read);
+-	qeth_clean_channel(&card->write);
+-	if (card->dev)
+-		free_netdev(card->dev);
+-	qeth_clear_ip_list(card, 0, 0);
+-	qeth_clear_ipato_list(card);
+-	kfree(card->ip_tbd_list);
+-	qeth_free_qdio_buffers(card);
+-	kfree(card);
+-}
+-
+-/**
+- * alloc memory for command buffer per channel
+- */
+-static int
+-qeth_setup_channel(struct qeth_channel *channel)
+-{
+-	int cnt;
+-
+-	QETH_DBF_TEXT(setup, 2, "setupch");
+-	for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
+-		channel->iob[cnt].data = (char *)
+-			kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
+-		if (channel->iob[cnt].data == NULL)
+-			break;
+-		channel->iob[cnt].state = BUF_STATE_FREE;
+-		channel->iob[cnt].channel = channel;
+-		channel->iob[cnt].callback = qeth_send_control_data_cb;
+-		channel->iob[cnt].rc = 0;
+-	}
+-	if (cnt < QETH_CMD_BUFFER_NO) {
+-		while (cnt-- > 0)
+-			kfree(channel->iob[cnt].data);
+-		return -ENOMEM;
+-	}
+-	channel->buf_no = 0;
+-	channel->io_buf_no = 0;
+-	atomic_set(&channel->irq_pending, 0);
+-	spin_lock_init(&channel->iob_lock);
+-
+-	init_waitqueue_head(&channel->wait_q);
+-	channel->irq_tasklet.data = (unsigned long) channel;
+-	channel->irq_tasklet.func = qeth_irq_tasklet;
+-	return 0;
+-}
+-
+-/**
+- * alloc memory for card structure
+- */
+-static struct qeth_card *
+-qeth_alloc_card(void)
+-{
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(setup, 2, "alloccrd");
+-	card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
+-	if (!card)
+-		return NULL;
+-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-	if (qeth_setup_channel(&card->read)) {
+-		kfree(card);
+-		return NULL;
+-	}
+-	if (qeth_setup_channel(&card->write)) {
+-		qeth_clean_channel(&card->read);
+-		kfree(card);
+-		return NULL;
+-	}
+-	return card;
+-}
+-
+-static long
+-__qeth_check_irb_error(struct ccw_device *cdev, unsigned long intparm,
+-		       struct irb *irb)
+-{
+-	if (!IS_ERR(irb))
+-		return 0;
+-
+-	switch (PTR_ERR(irb)) {
+-	case -EIO:
+-		PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
+-		QETH_DBF_TEXT(trace, 2, "ckirberr");
+-		QETH_DBF_TEXT_(trace, 2, "  rc%d", -EIO);
+-		break;
+-	case -ETIMEDOUT:
+-		PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
+-		QETH_DBF_TEXT(trace, 2, "ckirberr");
+-		QETH_DBF_TEXT_(trace, 2, "  rc%d", -ETIMEDOUT);
+-		if (intparm == QETH_RCD_PARM) {
+-			struct qeth_card *card = CARD_FROM_CDEV(cdev);
+-
+-			if (card && (card->data.ccwdev == cdev)) {
+-				card->data.state = CH_STATE_DOWN;
+-				wake_up(&card->wait_q);
+-			}
+-		}
+-		break;
+-	default:
+-		PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
+-			   cdev->dev.bus_id);
+-		QETH_DBF_TEXT(trace, 2, "ckirberr");
+-		QETH_DBF_TEXT(trace, 2, "  rc???");
+-	}
+-	return PTR_ERR(irb);
+-}
+-
+-static int
+-qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
+-{
+-	int dstat,cstat;
+-	char *sense;
+-
+-	sense = (char *) irb->ecw;
+-	cstat = irb->scsw.cstat;
+-	dstat = irb->scsw.dstat;
+-
+-	if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
+-		     SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
+-		     SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
+-		QETH_DBF_TEXT(trace,2, "CGENCHK");
+-		PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ",
+-			   cdev->dev.bus_id, dstat, cstat);
+-		HEXDUMP16(WARN, "irb: ", irb);
+-		HEXDUMP16(WARN, "irb: ", ((char *) irb) + 32);
+-		return 1;
+-	}
+-
+-	if (dstat & DEV_STAT_UNIT_CHECK) {
+-		if (sense[SENSE_RESETTING_EVENT_BYTE] &
+-		    SENSE_RESETTING_EVENT_FLAG) {
+-			QETH_DBF_TEXT(trace,2,"REVIND");
+-			return 1;
+-		}
+-		if (sense[SENSE_COMMAND_REJECT_BYTE] &
+-		    SENSE_COMMAND_REJECT_FLAG) {
+-			QETH_DBF_TEXT(trace,2,"CMDREJi");
+-			return 0;
+-		}
+-		if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) {
+-			QETH_DBF_TEXT(trace,2,"AFFE");
+-			return 1;
+-		}
+-		if ((!sense[0]) && (!sense[1]) && (!sense[2]) && (!sense[3])) {
+-			QETH_DBF_TEXT(trace,2,"ZEROSEN");
+-			return 0;
+-		}
+-		QETH_DBF_TEXT(trace,2,"DGENCHK");
+-			return 1;
+-	}
+-	return 0;
+-}
+-static int qeth_issue_next_read(struct qeth_card *);
+-
+-/**
+- * interrupt handler
+- */
+-static void
+-qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
+-{
+-	int rc;
+-	int cstat,dstat;
+-	struct qeth_cmd_buffer *buffer;
+-	struct qeth_channel *channel;
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(trace,5,"irq");
+-
+-	if (__qeth_check_irb_error(cdev, intparm, irb))
+-		return;
+-	cstat = irb->scsw.cstat;
+-	dstat = irb->scsw.dstat;
+-
+-	card = CARD_FROM_CDEV(cdev);
+-	if (!card)
+-		return;
+-
+-	if (card->read.ccwdev == cdev){
+-		channel = &card->read;
+-		QETH_DBF_TEXT(trace,5,"read");
+-	} else if (card->write.ccwdev == cdev) {
+-		channel = &card->write;
+-		QETH_DBF_TEXT(trace,5,"write");
+-	} else {
+-		channel = &card->data;
+-		QETH_DBF_TEXT(trace,5,"data");
+-	}
+-	atomic_set(&channel->irq_pending, 0);
+-
+-	if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC))
+-		channel->state = CH_STATE_STOPPED;
+-
+-	if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC))
+-		channel->state = CH_STATE_HALTED;
+-
+-	/*let's wake up immediately on data channel*/
+-	if ((channel == &card->data) && (intparm != 0) &&
+-	    (intparm != QETH_RCD_PARM))
+-		goto out;
+-
+-	if (intparm == QETH_CLEAR_CHANNEL_PARM) {
+-		QETH_DBF_TEXT(trace, 6, "clrchpar");
+-		/* we don't have to handle this further */
+-		intparm = 0;
+-	}
+-	if (intparm == QETH_HALT_CHANNEL_PARM) {
+-		QETH_DBF_TEXT(trace, 6, "hltchpar");
+-		/* we don't have to handle this further */
+-		intparm = 0;
+-	}
+-	if ((dstat & DEV_STAT_UNIT_EXCEP) ||
+-	    (dstat & DEV_STAT_UNIT_CHECK) ||
+-	    (cstat)) {
+-		if (irb->esw.esw0.erw.cons) {
+-			/* TODO: we should make this s390dbf */
+-			PRINT_WARN("sense data available on channel %s.\n",
+-				   CHANNEL_ID(channel));
+-			PRINT_WARN(" cstat 0x%X\n dstat 0x%X\n", cstat, dstat);
+-			HEXDUMP16(WARN,"irb: ",irb);
+-			HEXDUMP16(WARN,"sense data: ",irb->ecw);
+-		}
+-		if (intparm == QETH_RCD_PARM) {
+-			channel->state = CH_STATE_DOWN;
+-			goto out;
+-		}
+-		rc = qeth_get_problem(cdev,irb);
+-		if (rc) {
+-			qeth_schedule_recovery(card);
+-			goto out;
+-		}
+-	}
+-
+-	if (intparm == QETH_RCD_PARM) {
+-		channel->state = CH_STATE_RCD_DONE;
+-		goto out;
+-	}
+-	if (intparm) {
+-		buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
+-		buffer->state = BUF_STATE_PROCESSED;
+-	}
+-	if (channel == &card->data)
+-		return;
+-
+-	if (channel == &card->read &&
+-	    channel->state == CH_STATE_UP)
+-		qeth_issue_next_read(card);
+-
+-	qeth_irq_tasklet((unsigned long)channel);
+-	return;
+-out:
+-	wake_up(&card->wait_q);
+-}
+-
+-/**
+- * tasklet function scheduled from irq handler
+- */
+-static void
+-qeth_irq_tasklet(unsigned long data)
+-{
+-	struct qeth_card *card;
+-	struct qeth_channel *channel;
+-	struct qeth_cmd_buffer *iob;
+-	__u8 index;
+-
+-	QETH_DBF_TEXT(trace,5,"irqtlet");
+-	channel = (struct qeth_channel *) data;
+-	iob = channel->iob;
+-	index = channel->buf_no;
+-	card = CARD_FROM_CDEV(channel->ccwdev);
+-	while (iob[index].state == BUF_STATE_PROCESSED) {
+-		if (iob[index].callback !=NULL) {
+-			iob[index].callback(channel,iob + index);
+-		}
+-		index = (index + 1) % QETH_CMD_BUFFER_NO;
+-	}
+-	channel->buf_no = index;
+-	wake_up(&card->wait_q);
+-}
+-
+-static int qeth_stop_card(struct qeth_card *, int);
+-
+-static int
+-__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
+-{
+-	struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
+-	int rc = 0, rc2 = 0, rc3 = 0;
+-	enum qeth_card_states recover_flag;
+-
+-	QETH_DBF_TEXT(setup, 3, "setoffl");
+-	QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+-
+-	if (card->dev && netif_carrier_ok(card->dev))
+-		netif_carrier_off(card->dev);
+-	recover_flag = card->state;
+-	if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
+-		PRINT_WARN("Stopping card %s interrupted by user!\n",
+-			   CARD_BUS_ID(card));
+-		return -ERESTARTSYS;
+-	}
+-	rc  = ccw_device_set_offline(CARD_DDEV(card));
+-	rc2 = ccw_device_set_offline(CARD_WDEV(card));
+-	rc3 = ccw_device_set_offline(CARD_RDEV(card));
+-	if (!rc)
+-		rc = (rc2) ? rc2 : rc3;
+-	if (rc)
+-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+-	if (recover_flag == CARD_STATE_UP)
+-		card->state = CARD_STATE_RECOVER;
+-	qeth_notify_processes();
+-	return 0;
+-}
+-
+-static int
+-qeth_set_offline(struct ccwgroup_device *cgdev)
+-{
+-	return  __qeth_set_offline(cgdev, 0);
+-}
+-
+-static int
+-qeth_threads_running(struct qeth_card *card, unsigned long threads);
+-
+-
+-static void
+-qeth_remove_device(struct ccwgroup_device *cgdev)
+-{
+-	struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
+-	unsigned long flags;
+-
+-	QETH_DBF_TEXT(setup, 3, "rmdev");
+-	QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+-
+-	if (!card)
+-		return;
+-
+-	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
+-
+-	if (cgdev->state == CCWGROUP_ONLINE){
+-		card->use_hard_stop = 1;
+-		qeth_set_offline(cgdev);
+-	}
+-	/* remove form our internal list */
+-	write_lock_irqsave(&qeth_card_list.rwlock, flags);
+-	list_del(&card->list);
+-	write_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+-	if (card->dev)
+-		unregister_netdev(card->dev);
+-	qeth_remove_device_attributes(&cgdev->dev);
+-	qeth_free_card(card);
+-	cgdev->dev.driver_data = NULL;
+-	put_device(&cgdev->dev);
+-}
+-
+-static int
+-qeth_register_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
+-static int
+-qeth_deregister_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
+-
+-/**
+- * Add/remove address to/from card's ip list, i.e. try to add or remove
+- * reference to/from an IP address that is already registered on the card.
+- * Returns:
+- * 	0  address was on card and its reference count has been adjusted,
+- * 	   but is still > 0, so nothing has to be done
+- * 	   also returns 0 if card was not on card and the todo was to delete
+- * 	   the address -> there is also nothing to be done
+- * 	1  address was not on card and the todo is to add it to the card's ip
+- * 	   list
+- * 	-1 address was on card and its reference count has been decremented
+- * 	   to <= 0 by the todo -> address must be removed from card
+- */
+-static int
+-__qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
+-		      struct qeth_ipaddr **__addr)
+-{
+-	struct qeth_ipaddr *addr;
+-	int found = 0;
+-
+-	list_for_each_entry(addr, &card->ip_list, entry) {
+-		if (card->options.layer2) {
+-			if ((addr->type == todo->type) &&
+-			    (memcmp(&addr->mac, &todo->mac,
+-				    OSA_ADDR_LEN) == 0)) {
+-				found = 1;
+-				break;
+-			}
+-			continue;
+-		}
+-		if ((addr->proto     == QETH_PROT_IPV4)  &&
+-		    (todo->proto     == QETH_PROT_IPV4)  &&
+-		    (addr->type      == todo->type)      &&
+-		    (addr->u.a4.addr == todo->u.a4.addr) &&
+-		    (addr->u.a4.mask == todo->u.a4.mask)) {
+-			found = 1;
+-			break;
+-		}
+-		if ((addr->proto       == QETH_PROT_IPV6)     &&
+-		    (todo->proto       == QETH_PROT_IPV6)     &&
+-		    (addr->type        == todo->type)         &&
+-		    (addr->u.a6.pfxlen == todo->u.a6.pfxlen)  &&
+-		    (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
+-			    sizeof(struct in6_addr)) == 0)) {
+-			found = 1;
+-			break;
+-		}
+-	}
+-	if (found) {
+-		addr->users += todo->users;
+-		if (addr->users <= 0){
+-			*__addr = addr;
+-			return -1;
+-		} else {
+-			/* for VIPA and RXIP limit refcount to 1 */
+-			if (addr->type != QETH_IP_TYPE_NORMAL)
+-				addr->users = 1;
+-			return 0;
+-		}
+-	}
+-	if (todo->users > 0) {
+-		/* for VIPA and RXIP limit refcount to 1 */
+-		if (todo->type != QETH_IP_TYPE_NORMAL)
+-			todo->users = 1;
+-		return 1;
+-	} else
+-		return 0;
+-}
+-
+-static int
+-__qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr,
+-		              int same_type)
+-{
+-	struct qeth_ipaddr *tmp;
+-
+-	list_for_each_entry(tmp, list, entry) {
+-		if ((tmp->proto     == QETH_PROT_IPV4)            &&
+-		    (addr->proto    == QETH_PROT_IPV4)            &&
+-		    ((same_type && (tmp->type == addr->type)) ||
+-		     (!same_type && (tmp->type != addr->type))  ) &&
+-		    (tmp->u.a4.addr == addr->u.a4.addr)             ){
+-			return 1;
+-		}
+-		if ((tmp->proto  == QETH_PROT_IPV6)               &&
+-		    (addr->proto == QETH_PROT_IPV6)               &&
+-		    ((same_type && (tmp->type == addr->type)) ||
+-		     (!same_type && (tmp->type != addr->type))  ) &&
+-		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
+-			    sizeof(struct in6_addr)) == 0)          ) {
+-			return 1;
+-		}
+-	}
+-	return 0;
+-}
+-
+-/*
+- * Add IP to be added to todo list. If there is already an "add todo"
+- * in this list we just incremenent the reference count.
+- * Returns 0 if we  just incremented reference count.
+- */
+-static int
+-__qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
+-{
+-	struct qeth_ipaddr *tmp, *t;
+-	int found = 0;
+-
+-	list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) {
+-		if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
+-		    (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
+-			return 0;
+-		if (card->options.layer2) {
+-			if ((tmp->type	== addr->type)	&&
+-			    (tmp->is_multicast == addr->is_multicast) &&
+-			    (memcmp(&tmp->mac, &addr->mac,
+-				    OSA_ADDR_LEN) == 0)) {
+-				found = 1;
+-				break;
+-			}
+-			continue;
+-		}
+-		if ((tmp->proto        == QETH_PROT_IPV4)     &&
+-		    (addr->proto       == QETH_PROT_IPV4)     &&
+-		    (tmp->type         == addr->type)         &&
+-		    (tmp->is_multicast == addr->is_multicast) &&
+-		    (tmp->u.a4.addr    == addr->u.a4.addr)    &&
+-		    (tmp->u.a4.mask    == addr->u.a4.mask)) {
+-			found = 1;
+-			break;
+-		}
+-		if ((tmp->proto        == QETH_PROT_IPV6)      &&
+-		    (addr->proto       == QETH_PROT_IPV6)      &&
+-		    (tmp->type         == addr->type)          &&
+-		    (tmp->is_multicast == addr->is_multicast)  &&
+-		    (tmp->u.a6.pfxlen  == addr->u.a6.pfxlen)   &&
+-		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
+-			    sizeof(struct in6_addr)) == 0)) {
+-			found = 1;
+-			break;
+-		}
+-	}
+-	if (found){
+-		if (addr->users != 0)
+-			tmp->users += addr->users;
+-		else
+-			tmp->users += add? 1:-1;
+-		if (tmp->users == 0) {
+-			list_del(&tmp->entry);
+-			kfree(tmp);
+-		}
+-		return 0;
+-	} else {
+-		if (addr->type == QETH_IP_TYPE_DEL_ALL_MC)
+-			list_add(&addr->entry, card->ip_tbd_list);
+-		else {
+-			if (addr->users == 0)
+-				addr->users += add? 1:-1;
+-			if (add && (addr->type == QETH_IP_TYPE_NORMAL) &&
+-			    qeth_is_addr_covered_by_ipato(card, addr)){
+-				QETH_DBF_TEXT(trace, 2, "tkovaddr");
+-				addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG;
+-			}
+-			list_add_tail(&addr->entry, card->ip_tbd_list);
+-		}
+-		return 1;
+-	}
+-}
+-
+-/**
+- * Remove IP address from list
+- */
+-static int
+-qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace, 4, "delip");
+-
+-	if (card->options.layer2)
+-		QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+-	else if (addr->proto == QETH_PROT_IPV4)
+-		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
+-	else {
+-		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+-		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
+-	}
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	rc = __qeth_insert_ip_todo(card, addr, 0);
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-	return rc;
+-}
+-
+-static int
+-qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace, 4, "addip");
+-	if (card->options.layer2)
+-		QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+-	else if (addr->proto == QETH_PROT_IPV4)
+-		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
+-	else {
+-		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+-		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
+-	}
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	rc = __qeth_insert_ip_todo(card, addr, 1);
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-	return rc;
+-}
+-
+-static void
+-__qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
+-{
+-	struct qeth_ipaddr *addr, *tmp;
+-	int rc;
+-again:
+-	list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
+-		if (addr->is_multicast) {
+-			list_del(&addr->entry);
+-			spin_unlock_irqrestore(&card->ip_lock, *flags);
+-			rc = qeth_deregister_addr_entry(card, addr);
+-			spin_lock_irqsave(&card->ip_lock, *flags);
+-			if (!rc) {
+-				kfree(addr);
+-				goto again;
+-			} else
+-				list_add(&addr->entry, &card->ip_list);
+-		}
+-	}
+-}
+-
+-static void
+-qeth_set_ip_addr_list(struct qeth_card *card)
+-{
+-	struct list_head *tbd_list;
+-	struct qeth_ipaddr *todo, *addr;
+-	unsigned long flags;
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace, 2, "sdiplist");
+-	QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+-
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	tbd_list = card->ip_tbd_list;
+-	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
+-	if (!card->ip_tbd_list) {
+-		QETH_DBF_TEXT(trace, 0, "silnomem");
+-		card->ip_tbd_list = tbd_list;
+-		spin_unlock_irqrestore(&card->ip_lock, flags);
+-		return;
+-	} else
+-		INIT_LIST_HEAD(card->ip_tbd_list);
+-
+-	while (!list_empty(tbd_list)){
+-		todo = list_entry(tbd_list->next, struct qeth_ipaddr, entry);
+-		list_del(&todo->entry);
+-		if (todo->type == QETH_IP_TYPE_DEL_ALL_MC){
+-			__qeth_delete_all_mc(card, &flags);
+-			kfree(todo);
+-			continue;
+-		}
+-		rc = __qeth_ref_ip_on_card(card, todo, &addr);
+-		if (rc == 0) {
+-			/* nothing to be done; only adjusted refcount */
+-			kfree(todo);
+-		} else if (rc == 1) {
+-			/* new entry to be added to on-card list */
+-			spin_unlock_irqrestore(&card->ip_lock, flags);
+-			rc = qeth_register_addr_entry(card, todo);
+-			spin_lock_irqsave(&card->ip_lock, flags);
+-			if (!rc)
+-				list_add_tail(&todo->entry, &card->ip_list);
+-			else
+-				kfree(todo);
+-		} else if (rc == -1) {
+-			/* on-card entry to be removed */
+-			list_del_init(&addr->entry);
+-			spin_unlock_irqrestore(&card->ip_lock, flags);
+-			rc = qeth_deregister_addr_entry(card, addr);
+-			spin_lock_irqsave(&card->ip_lock, flags);
+-			if (!rc)
+-				kfree(addr);
+-			else
+-				list_add_tail(&addr->entry, &card->ip_list);
+-			kfree(todo);
+-		}
+-	}
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-	kfree(tbd_list);
+-}
+-
+-static void qeth_delete_mc_addresses(struct qeth_card *);
+-static void qeth_add_multicast_ipv4(struct qeth_card *);
+-static void qeth_layer2_add_multicast(struct qeth_card *);
+-#ifdef CONFIG_QETH_IPV6
+-static void qeth_add_multicast_ipv6(struct qeth_card *);
+-#endif
+-
+-static int
+-qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&card->thread_mask_lock, flags);
+-	if ( !(card->thread_allowed_mask & thread) ||
+-	      (card->thread_start_mask & thread) ) {
+-		spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+-		return -EPERM;
+-	}
+-	card->thread_start_mask |= thread;
+-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+-	return 0;
+-}
+-
+-static void
+-qeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&card->thread_mask_lock, flags);
+-	card->thread_start_mask &= ~thread;
+-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+-	wake_up(&card->wait_q);
+-}
+-
+-static void
+-qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&card->thread_mask_lock, flags);
+-	card->thread_running_mask &= ~thread;
+-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+-	wake_up(&card->wait_q);
+-}
+-
+-static int
+-__qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+-{
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	spin_lock_irqsave(&card->thread_mask_lock, flags);
+-	if (card->thread_start_mask & thread){
+-		if ((card->thread_allowed_mask & thread) &&
+-		    !(card->thread_running_mask & thread)){
+-			rc = 1;
+-			card->thread_start_mask &= ~thread;
+-			card->thread_running_mask |= thread;
+-		} else
+-			rc = -EPERM;
+-	}
+-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+-	return rc;
+-}
+-
+-static int
+-qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+-{
+-	int rc = 0;
+-
+-	wait_event(card->wait_q,
+-		   (rc = __qeth_do_run_thread(card, thread)) >= 0);
+-	return rc;
+-}
+-
+-static int
+-qeth_recover(void *ptr)
+-{
+-	struct qeth_card *card;
+-	int rc = 0;
+-
+-	card = (struct qeth_card *) ptr;
+-	daemonize("qeth_recover");
+-	QETH_DBF_TEXT(trace,2,"recover1");
+-	QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+-	if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
+-		return 0;
+-	QETH_DBF_TEXT(trace,2,"recover2");
+-	PRINT_WARN("Recovery of device %s started ...\n",
+-		   CARD_BUS_ID(card));
+-	card->use_hard_stop = 1;
+-	__qeth_set_offline(card->gdev,1);
+-	rc = __qeth_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)
+-		PRINT_INFO("Device %s successfully recovered!\n",
+-			   CARD_BUS_ID(card));
+-	else
+-		PRINT_INFO("Device %s could not be recovered!\n",
+-			   CARD_BUS_ID(card));
+-	return 0;
+-}
+-
+-void
+-qeth_schedule_recovery(struct qeth_card *card)
+-{
+-	QETH_DBF_TEXT(trace,2,"startrec");
+-	if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
+-		schedule_work(&card->kernel_thread_starter);
+-}
+-
+-static int
+-qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
+-{
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	spin_lock_irqsave(&card->thread_mask_lock, flags);
+-	QETH_DBF_TEXT_(trace, 4, "  %02x%02x%02x",
+-			(u8) card->thread_start_mask,
+-			(u8) card->thread_allowed_mask,
+-			(u8) card->thread_running_mask);
+-	rc = (card->thread_start_mask & thread);
+-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+-	return rc;
+-}
+-
+-static void
+-qeth_start_kernel_thread(struct work_struct *work)
+-{
+-	struct qeth_card *card = container_of(work, struct qeth_card, kernel_thread_starter);
+-	QETH_DBF_TEXT(trace , 2, "strthrd");
+-
+-	if (card->read.state != CH_STATE_UP &&
+-	    card->write.state != CH_STATE_UP)
+-		return;
+-	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
+-		kernel_thread(qeth_recover, (void *) card, SIGCHLD);
+-}
+-
+-
+-static void
+-qeth_set_intial_options(struct qeth_card *card)
+-{
+-	card->options.route4.type = NO_ROUTER;
+-#ifdef CONFIG_QETH_IPV6
+-	card->options.route6.type = NO_ROUTER;
+-#endif /* QETH_IPV6 */
+-	card->options.checksum_type = QETH_CHECKSUM_DEFAULT;
+-	card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
+-	card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;
+-	card->options.fake_broadcast = 0;
+-	card->options.add_hhlen = DEFAULT_ADD_HHLEN;
+-	card->options.fake_ll = 0;
+-	if (card->info.type == QETH_CARD_TYPE_OSN)
+-		card->options.layer2 = 1;
+-	else
+-		card->options.layer2 = 0;
+-	card->options.performance_stats = 0;
+-	card->options.rx_sg_cb = QETH_RX_SG_CB;
+-}
+-
+-/**
+- * initialize channels ,card and all state machines
+- */
+-static int
+-qeth_setup_card(struct qeth_card *card)
+-{
+-
+-	QETH_DBF_TEXT(setup, 2, "setupcrd");
+-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-
+-	card->read.state  = CH_STATE_DOWN;
+-	card->write.state = CH_STATE_DOWN;
+-	card->data.state  = CH_STATE_DOWN;
+-	card->state = CARD_STATE_DOWN;
+-	card->lan_online = 0;
+-	card->use_hard_stop = 0;
+-	card->dev = NULL;
+-#ifdef CONFIG_QETH_VLAN
+-	spin_lock_init(&card->vlanlock);
+-	card->vlangrp = NULL;
+-#endif
+-	spin_lock_init(&card->lock);
+-	spin_lock_init(&card->ip_lock);
+-	spin_lock_init(&card->thread_mask_lock);
+-	card->thread_start_mask = 0;
+-	card->thread_allowed_mask = 0;
+-	card->thread_running_mask = 0;
+-	INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
+-	INIT_LIST_HEAD(&card->ip_list);
+-	card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+-	if (!card->ip_tbd_list) {
+-		QETH_DBF_TEXT(setup, 0, "iptbdnom");
+-		return -ENOMEM;
+-	}
+-	INIT_LIST_HEAD(card->ip_tbd_list);
+-	INIT_LIST_HEAD(&card->cmd_waiter_list);
+-	init_waitqueue_head(&card->wait_q);
+-	/* intial options */
+-	qeth_set_intial_options(card);
+-	/* IP address takeover */
+-	INIT_LIST_HEAD(&card->ipato.entries);
+-	card->ipato.enabled = 0;
+-	card->ipato.invert4 = 0;
+-	card->ipato.invert6 = 0;
+-	/* init QDIO stuff */
+-	qeth_init_qdio_info(card);
+-	return 0;
+-}
+-
+-static int
+-is_1920_device (struct qeth_card *card)
+-{
+-	int single_queue = 0;
+-	struct ccw_device *ccwdev;
+-	struct channelPath_dsc {
+-		u8 flags;
+-		u8 lsn;
+-		u8 desc;
+-		u8 chpid;
+-		u8 swla;
+-		u8 zeroes;
+-		u8 chla;
+-		u8 chpp;
+-	} *chp_dsc;
+-
+-	QETH_DBF_TEXT(setup, 2, "chk_1920");
+-
+-	ccwdev = card->data.ccwdev;
+-	chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
+-	if (chp_dsc != NULL) {
+-		/* CHPP field bit 6 == 1 -> single queue */
+-		single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
+-		kfree(chp_dsc);
+-	}
+-	QETH_DBF_TEXT_(setup, 2, "rc:%x", single_queue);
+-	return single_queue;
+-}
+-
+-static int
+-qeth_determine_card_type(struct qeth_card *card)
+-{
+-	int i = 0;
+-
+-	QETH_DBF_TEXT(setup, 2, "detcdtyp");
+-
+-	card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+-	card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
+-	while (known_devices[i][4]) {
+-		if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
+-		    (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
+-			card->info.type = known_devices[i][4];
+-			card->qdio.no_out_queues = known_devices[i][8];
+-			card->info.is_multicast_different = known_devices[i][9];
+-			if (is_1920_device(card)) {
+-				PRINT_INFO("Priority Queueing not able "
+-					   "due to hardware limitations!\n");
+-				card->qdio.no_out_queues = 1;
+-				card->qdio.default_out_queue = 0;
+-			}
+-			return 0;
+-		}
+-		i++;
+-	}
+-	card->info.type = QETH_CARD_TYPE_UNKNOWN;
+-	PRINT_ERR("unknown card type on device %s\n", CARD_BUS_ID(card));
+-	return -ENOENT;
+-}
+-
+-static int
+-qeth_probe_device(struct ccwgroup_device *gdev)
+-{
+-	struct qeth_card *card;
+-	struct device *dev;
+-	unsigned long flags;
+-	int rc;
+-
+-	QETH_DBF_TEXT(setup, 2, "probedev");
+-
+-	dev = &gdev->dev;
+-	if (!get_device(dev))
+-		return -ENODEV;
+-
+-	QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+-
+-	card = qeth_alloc_card();
+-	if (!card) {
+-		put_device(dev);
+-		QETH_DBF_TEXT_(setup, 2, "1err%d", -ENOMEM);
+-		return -ENOMEM;
+-	}
+-	card->read.ccwdev  = gdev->cdev[0];
+-	card->write.ccwdev = gdev->cdev[1];
+-	card->data.ccwdev  = gdev->cdev[2];
+-	gdev->dev.driver_data = card;
+-	card->gdev = gdev;
+-	gdev->cdev[0]->handler = qeth_irq;
+-	gdev->cdev[1]->handler = qeth_irq;
+-	gdev->cdev[2]->handler = qeth_irq;
+-
+-	if ((rc = qeth_determine_card_type(card))){
+-		PRINT_WARN("%s: not a valid card type\n", __func__);
+-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+-		put_device(dev);
+-		qeth_free_card(card);
+-		return rc;
+-	}
+-	if ((rc = qeth_setup_card(card))){
+-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+-		put_device(dev);
+-		qeth_free_card(card);
+-		return rc;
+-	}
+-	rc = qeth_create_device_attributes(dev);
+-	if (rc) {
+-		put_device(dev);
+-		qeth_free_card(card);
+-		return rc;
+-	}
+-	/* insert into our internal list */
+-	write_lock_irqsave(&qeth_card_list.rwlock, flags);
+-	list_add_tail(&card->list, &qeth_card_list.list);
+-	write_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+-	return rc;
+-}
+-
+-
+-static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
+-			       int *length)
+-{
+-	struct ciw *ciw;
+-	char *rcd_buf;
+-	int ret;
+-	struct qeth_channel *channel = &card->data;
+-	unsigned long flags;
+-
+-	/*
+-	 * scan for RCD command in extended SenseID data
+-	 */
+-	ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
+-	if (!ciw || ciw->cmd == 0)
+-		return -EOPNOTSUPP;
+-	rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+-	if (!rcd_buf)
+-		return -ENOMEM;
+-
+-	channel->ccw.cmd_code = ciw->cmd;
+-	channel->ccw.cda = (__u32) __pa (rcd_buf);
+-	channel->ccw.count = ciw->count;
+-	channel->ccw.flags = CCW_FLAG_SLI;
+-	channel->state = CH_STATE_RCD;
+-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+-	ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+-				       QETH_RCD_PARM, LPM_ANYPATH, 0,
+-				       QETH_RCD_TIMEOUT);
+-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-	if (!ret)
+-		wait_event(card->wait_q,
+-			   (channel->state == CH_STATE_RCD_DONE ||
+-			    channel->state == CH_STATE_DOWN));
+-	if (channel->state == CH_STATE_DOWN)
+-		ret = -EIO;
+-	else
+-		channel->state = CH_STATE_DOWN;
+-	if (ret) {
+-		kfree(rcd_buf);
+-		*buffer = NULL;
+-		*length = 0;
+-	} else {
+-		*length = ciw->count;
+-		*buffer = rcd_buf;
+-	}
+-	return ret;
+-}
+-
+-static int
+-qeth_get_unitaddr(struct qeth_card *card)
+-{
+- 	int length;
+-	char *prcd;
+-	int rc;
+-
+-	QETH_DBF_TEXT(setup, 2, "getunit");
+-	rc = qeth_read_conf_data(card, (void **) &prcd, &length);
+-	if (rc) {
+-		PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
+-			  CARD_DDEV_ID(card), rc);
+-		return rc;
+-	}
+-	card->info.chpid = prcd[30];
+-	card->info.unit_addr2 = prcd[31];
+-	card->info.cula = prcd[63];
+-	card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
+-			       (prcd[0x11] == _ascebc['M']));
+-	kfree(prcd);
+-	return 0;
+-}
+-
+-static void
+-qeth_init_tokens(struct qeth_card *card)
+-{
+-	card->token.issuer_rm_w = 0x00010103UL;
+-	card->token.cm_filter_w = 0x00010108UL;
+-	card->token.cm_connection_w = 0x0001010aUL;
+-	card->token.ulp_filter_w = 0x0001010bUL;
+-	card->token.ulp_connection_w = 0x0001010dUL;
+-}
+-
+-static inline __u16
+-raw_devno_from_bus_id(char *id)
+-{
+-        id += (strlen(id) - 4);
+-        return (__u16) simple_strtoul(id, &id, 16);
+-}
+-/**
+- * setup channel
+- */
+-static void
+-qeth_setup_ccw(struct qeth_channel *channel,unsigned char *iob, __u32 len)
+-{
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(trace, 4, "setupccw");
+-	card = CARD_FROM_CDEV(channel->ccwdev);
+-	if (channel == &card->read)
+-		memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
+-	else
+-		memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
+-	channel->ccw.count = len;
+-	channel->ccw.cda = (__u32) __pa(iob);
+-}
+-
+-/**
+- * get free buffer for ccws (IDX activation, lancmds,ipassists...)
+- */
+-static struct qeth_cmd_buffer *
+-__qeth_get_buffer(struct qeth_channel *channel)
+-{
+-	__u8 index;
+-
+-	QETH_DBF_TEXT(trace, 6, "getbuff");
+-	index = channel->io_buf_no;
+-	do {
+-		if (channel->iob[index].state == BUF_STATE_FREE) {
+-			channel->iob[index].state = BUF_STATE_LOCKED;
+-			channel->io_buf_no = (channel->io_buf_no + 1) %
+-				QETH_CMD_BUFFER_NO;
+-			memset(channel->iob[index].data, 0, QETH_BUFSIZE);
+-			return channel->iob + index;
+-		}
+-		index = (index + 1) % QETH_CMD_BUFFER_NO;
+-	} while(index != channel->io_buf_no);
+-
+-	return NULL;
+-}
+-
+-/**
+- * release command buffer
+- */
+-static void
+-qeth_release_buffer(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-{
+-	unsigned long flags;
+-
+-	QETH_DBF_TEXT(trace, 6, "relbuff");
+-	spin_lock_irqsave(&channel->iob_lock, flags);
+-	memset(iob->data, 0, QETH_BUFSIZE);
+-	iob->state = BUF_STATE_FREE;
+-	iob->callback = qeth_send_control_data_cb;
+-	iob->rc = 0;
+-	spin_unlock_irqrestore(&channel->iob_lock, flags);
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_buffer(struct qeth_channel *channel)
+-{
+-	struct qeth_cmd_buffer *buffer = NULL;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&channel->iob_lock, flags);
+-	buffer = __qeth_get_buffer(channel);
+-	spin_unlock_irqrestore(&channel->iob_lock, flags);
+-	return buffer;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_wait_for_buffer(struct qeth_channel *channel)
+-{
+-	struct qeth_cmd_buffer *buffer;
+-	wait_event(channel->wait_q,
+-		   ((buffer = qeth_get_buffer(channel)) != NULL));
+-	return buffer;
+-}
+-
+-static void
+-qeth_clear_cmd_buffers(struct qeth_channel *channel)
+-{
+-	int cnt;
+-
+-	for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++)
+-		qeth_release_buffer(channel,&channel->iob[cnt]);
+-	channel->buf_no = 0;
+-	channel->io_buf_no = 0;
+-}
+-
+-/**
+- * start IDX for read and write channel
+- */
+-static int
+-qeth_idx_activate_get_answer(struct qeth_channel *channel,
+-			      void (*idx_reply_cb)(struct qeth_channel *,
+-						   struct qeth_cmd_buffer *))
+-{
+-	struct qeth_cmd_buffer *iob;
+-	unsigned long flags;
+-	int rc;
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(setup, 2, "idxanswr");
+-	card = CARD_FROM_CDEV(channel->ccwdev);
+-	iob = qeth_get_buffer(channel);
+-	iob->callback = idx_reply_cb;
+-	memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
+-	channel->ccw.count = QETH_BUFSIZE;
+-	channel->ccw.cda = (__u32) __pa(iob->data);
+-
+-	wait_event(card->wait_q,
+-		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
+-	QETH_DBF_TEXT(setup, 6, "noirqpnd");
+-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+-	rc = ccw_device_start(channel->ccwdev,
+-			      &channel->ccw,(addr_t) iob, 0, 0);
+-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+-	if (rc) {
+-		PRINT_ERR("qeth: Error2 in activating channel rc=%d\n",rc);
+-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+-		atomic_set(&channel->irq_pending, 0);
+-		wake_up(&card->wait_q);
+-		return rc;
+-	}
+-	rc = wait_event_interruptible_timeout(card->wait_q,
+-			 channel->state == CH_STATE_UP, QETH_TIMEOUT);
+-	if (rc == -ERESTARTSYS)
+-		return rc;
+-	if (channel->state != CH_STATE_UP){
+-		rc = -ETIME;
+-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+-		qeth_clear_cmd_buffers(channel);
+-	} else
+-		rc = 0;
+-	return rc;
+-}
+-
+-static int
+-qeth_idx_activate_channel(struct qeth_channel *channel,
+-			   void (*idx_reply_cb)(struct qeth_channel *,
+-						struct qeth_cmd_buffer *))
+-{
+-	struct qeth_card *card;
+-	struct qeth_cmd_buffer *iob;
+-	unsigned long flags;
+-	__u16 temp;
+-	int rc;
+-
+-	card = CARD_FROM_CDEV(channel->ccwdev);
+-
+-	QETH_DBF_TEXT(setup, 2, "idxactch");
+-
+-	iob = qeth_get_buffer(channel);
+-	iob->callback = idx_reply_cb;
+-	memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
+-	channel->ccw.count = IDX_ACTIVATE_SIZE;
+-	channel->ccw.cda = (__u32) __pa(iob->data);
+-	if (channel == &card->write) {
+-		memcpy(iob->data, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);
+-		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+-		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+-		card->seqno.trans_hdr++;
+-	} else {
+-		memcpy(iob->data, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE);
+-		memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+-		       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+-	}
+-	memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
+-	       &card->token.issuer_rm_w,QETH_MPC_TOKEN_LENGTH);
+-	memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data),
+-	       &card->info.func_level,sizeof(__u16));
+-	temp = raw_devno_from_bus_id(CARD_DDEV_ID(card));
+-	memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2);
+-	temp = (card->info.cula << 8) + card->info.unit_addr2;
+-	memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
+-
+-	wait_event(card->wait_q,
+-		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
+-	QETH_DBF_TEXT(setup, 6, "noirqpnd");
+-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+-	rc = ccw_device_start(channel->ccwdev,
+-			      &channel->ccw,(addr_t) iob, 0, 0);
+-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+-	if (rc) {
+-		PRINT_ERR("qeth: Error1 in activating channel. rc=%d\n",rc);
+-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+-		atomic_set(&channel->irq_pending, 0);
+-		wake_up(&card->wait_q);
+-		return rc;
+-	}
+-	rc = wait_event_interruptible_timeout(card->wait_q,
+-			channel->state == CH_STATE_ACTIVATING, QETH_TIMEOUT);
+-	if (rc == -ERESTARTSYS)
+-		return rc;
+-	if (channel->state != CH_STATE_ACTIVATING) {
+-		PRINT_WARN("qeth: IDX activate timed out!\n");
+-		QETH_DBF_TEXT_(setup, 2, "2err%d", -ETIME);
+-		qeth_clear_cmd_buffers(channel);
+-		return -ETIME;
+-	}
+-	return qeth_idx_activate_get_answer(channel,idx_reply_cb);
+-}
+-
+-static int
+-qeth_peer_func_level(int level)
+-{
+-	if ((level & 0xff) == 8)
+-		return (level & 0xff) + 0x400;
+-	if (((level >> 8) & 3) == 1)
+-		return (level & 0xff) + 0x200;
+-	return level;
+-}
+-
+-static void
+-qeth_idx_write_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-{
+-	struct qeth_card *card;
+-	__u16 temp;
+-
+-	QETH_DBF_TEXT(setup ,2, "idxwrcb");
+-
+-	if (channel->state == CH_STATE_DOWN) {
+-		channel->state = CH_STATE_ACTIVATING;
+-		goto out;
+-	}
+-	card = CARD_FROM_CDEV(channel->ccwdev);
+-
+-	if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
+-		if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+-			PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
+-				"adapter exclusively used by another host\n",
+-				CARD_WDEV_ID(card));
+-		else
+-			PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
+-				"negative reply\n", CARD_WDEV_ID(card));
+-		goto out;
+-	}
+-	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
+-	if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) {
+-		PRINT_WARN("IDX_ACTIVATE on write channel device %s: "
+-			"function level mismatch "
+-			"(sent: 0x%x, received: 0x%x)\n",
+-			CARD_WDEV_ID(card), card->info.func_level, temp);
+-		goto out;
+-	}
+-	channel->state = CH_STATE_UP;
+-out:
+-	qeth_release_buffer(channel, iob);
+-}
+-
+-static int
+-qeth_check_idx_response(unsigned char *buffer)
+-{
+-	if (!buffer)
+-		return 0;
+-
+-	QETH_DBF_HEX(control, 2, buffer, QETH_DBF_CONTROL_LEN);
+-	if ((buffer[2] & 0xc0) == 0xc0) {
+-		PRINT_WARN("received an IDX TERMINATE "
+-			   "with cause code 0x%02x%s\n",
+-			   buffer[4],
+-			   ((buffer[4] == 0x22) ?
+-			    " -- try another portname" : ""));
+-		QETH_DBF_TEXT(trace, 2, "ckidxres");
+-		QETH_DBF_TEXT(trace, 2, " idxterm");
+-		QETH_DBF_TEXT_(trace, 2, "  rc%d", -EIO);
+-		return -EIO;
+-	}
+-	return 0;
+-}
+-
+-static void
+-qeth_idx_read_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-{
+-	struct qeth_card *card;
+-	__u16 temp;
+-
+-	QETH_DBF_TEXT(setup , 2, "idxrdcb");
+-	if (channel->state == CH_STATE_DOWN) {
+-		channel->state = CH_STATE_ACTIVATING;
+-		goto out;
+-	}
+-
+-	card = CARD_FROM_CDEV(channel->ccwdev);
+-	if (qeth_check_idx_response(iob->data)) {
+-			goto out;
+-	}
+-	if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
+-		if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+-			PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
+-				"adapter exclusively used by another host\n",
+-				CARD_RDEV_ID(card));
+-		else
+-			PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
+-				"negative reply\n", CARD_RDEV_ID(card));
+-		goto out;
+-	}
+-
+-/**
+- * temporary fix for microcode bug
+- * to revert it,replace OR by AND
+- */
+-	if ( (!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
+-	     (card->info.type == QETH_CARD_TYPE_OSAE) )
+-		card->info.portname_required = 1;
+-
+-	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
+-	if (temp != qeth_peer_func_level(card->info.func_level)) {
+-		PRINT_WARN("IDX_ACTIVATE on read channel device %s: function "
+-			"level mismatch (sent: 0x%x, received: 0x%x)\n",
+-			CARD_RDEV_ID(card), card->info.func_level, temp);
+-		goto out;
+-	}
+-	memcpy(&card->token.issuer_rm_r,
+-	       QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
+-	       QETH_MPC_TOKEN_LENGTH);
+-	memcpy(&card->info.mcl_level[0],
+-	       QETH_IDX_REPLY_LEVEL(iob->data), QETH_MCL_LENGTH);
+-	channel->state = CH_STATE_UP;
+-out:
+-	qeth_release_buffer(channel,iob);
+-}
+-
+-static int
+-qeth_issue_next_read(struct qeth_card *card)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(trace,5,"issnxrd");
+-	if (card->read.state != CH_STATE_UP)
+-		return -EIO;
+-	iob = qeth_get_buffer(&card->read);
+-	if (!iob) {
+-		PRINT_WARN("issue_next_read failed: no iob available!\n");
+-		return -ENOMEM;
+-	}
+-	qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
+-	QETH_DBF_TEXT(trace, 6, "noirqpnd");
+-	rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
+-			      (addr_t) iob, 0, 0);
+-	if (rc) {
+-		PRINT_ERR("Error in starting next read ccw! rc=%i\n", rc);
+-		atomic_set(&card->read.irq_pending, 0);
+-		qeth_schedule_recovery(card);
+-		wake_up(&card->wait_q);
+-	}
+-	return rc;
+-}
+-
+-static struct qeth_reply *
+-qeth_alloc_reply(struct qeth_card *card)
+-{
+-	struct qeth_reply *reply;
+-
+-	reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
+-	if (reply){
+-		atomic_set(&reply->refcnt, 1);
+-		atomic_set(&reply->received, 0);
+-		reply->card = card;
+-	};
+-	return reply;
+-}
+-
+-static void
+-qeth_get_reply(struct qeth_reply *reply)
+-{
+-	WARN_ON(atomic_read(&reply->refcnt) <= 0);
+-	atomic_inc(&reply->refcnt);
+-}
+-
+-static void
+-qeth_put_reply(struct qeth_reply *reply)
+-{
+-	WARN_ON(atomic_read(&reply->refcnt) <= 0);
+-	if (atomic_dec_and_test(&reply->refcnt))
+-		kfree(reply);
+-}
+-
+-static void
+-qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, struct qeth_card *card)
+-{
+-	int rc;
+-	int com;
+-	char * ipa_name;
+-
+-	com = cmd->hdr.command;
+-	rc  = cmd->hdr.return_code;
+-	ipa_name = qeth_get_ipa_cmd_name(com);
+-
+-	PRINT_ERR("%s(x%X) for %s returned x%X \"%s\"\n", ipa_name, com,
+-		   QETH_CARD_IFNAME(card), rc, qeth_get_ipa_msg(rc));
+-}
+-
+-static struct qeth_ipa_cmd *
+-qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
+-{
+-	struct qeth_ipa_cmd *cmd = NULL;
+-
+-	QETH_DBF_TEXT(trace,5,"chkipad");
+-	if (IS_IPA(iob->data)){
+-		cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
+-		if (IS_IPA_REPLY(cmd)) {
+-			if (cmd->hdr.return_code)
+-				qeth_issue_ipa_msg(cmd, card);
+-			return cmd;
+-		}
+-		else {
+-			switch (cmd->hdr.command) {
+-			case IPA_CMD_STOPLAN:
+-				PRINT_WARN("Link failure on %s (CHPID 0x%X) - "
+-					   "there is a network problem or "
+-					   "someone pulled the cable or "
+-					   "disabled the port.\n",
+-					   QETH_CARD_IFNAME(card),
+-					   card->info.chpid);
+-				card->lan_online = 0;
+-				if (card->dev && netif_carrier_ok(card->dev))
+-					netif_carrier_off(card->dev);
+-				return NULL;
+-			case IPA_CMD_STARTLAN:
+-				PRINT_INFO("Link reestablished on %s "
+-					   "(CHPID 0x%X). Scheduling "
+-					   "IP address reset.\n",
+-					   QETH_CARD_IFNAME(card),
+-					   card->info.chpid);
+-				netif_carrier_on(card->dev);
+-				qeth_schedule_recovery(card);
+-				return NULL;
+-			case IPA_CMD_MODCCID:
+-				return cmd;
+-			case IPA_CMD_REGISTER_LOCAL_ADDR:
+-				QETH_DBF_TEXT(trace,3, "irla");
+-				break;
+-			case IPA_CMD_UNREGISTER_LOCAL_ADDR:
+-				QETH_DBF_TEXT(trace,3, "urla");
+-				break;
+-			default:
+-				PRINT_WARN("Received data is IPA "
+-					   "but not a reply!\n");
+-				break;
+-			}
+-		}
+-	}
+-	return cmd;
+-}
+-
+-/**
+- * wake all waiting ipa commands
+- */
+-static void
+-qeth_clear_ipacmd_list(struct qeth_card *card)
+-{
+-	struct qeth_reply *reply, *r;
+-	unsigned long flags;
+-
+-	QETH_DBF_TEXT(trace, 4, "clipalst");
+-
+-	spin_lock_irqsave(&card->lock, flags);
+-	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
+-		qeth_get_reply(reply);
+-		reply->rc = -EIO;
+-		atomic_inc(&reply->received);
+-		list_del_init(&reply->list);
+-		wake_up(&reply->wait_q);
+-		qeth_put_reply(reply);
+-	}
+-	spin_unlock_irqrestore(&card->lock, flags);
+-}
+-
+-static void
+-qeth_send_control_data_cb(struct qeth_channel *channel,
+-			  struct qeth_cmd_buffer *iob)
+-{
+-	struct qeth_card *card;
+-	struct qeth_reply *reply, *r;
+-	struct qeth_ipa_cmd *cmd;
+-	unsigned long flags;
+-	int keep_reply;
+-
+-	QETH_DBF_TEXT(trace,4,"sndctlcb");
+-
+-	card = CARD_FROM_CDEV(channel->ccwdev);
+-	if (qeth_check_idx_response(iob->data)) {
+-		qeth_clear_ipacmd_list(card);
+-		qeth_schedule_recovery(card);
+-		goto out;
+-	}
+-
+-	cmd = qeth_check_ipa_data(card, iob);
+-	if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
+-		goto out;
+-	/*in case of OSN : check if cmd is set */
+-	if (card->info.type == QETH_CARD_TYPE_OSN &&
+-	    cmd &&
+-	    cmd->hdr.command != IPA_CMD_STARTLAN &&
+-	    card->osn_info.assist_cb != NULL) {
+-		card->osn_info.assist_cb(card->dev, cmd);
+-		goto out;
+-	}
+-
+-	spin_lock_irqsave(&card->lock, flags);
+-	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
+-		if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
+-		    ((cmd) && (reply->seqno == cmd->hdr.seqno))) {
+-			qeth_get_reply(reply);
+-			list_del_init(&reply->list);
+-			spin_unlock_irqrestore(&card->lock, flags);
+-			keep_reply = 0;
+-			if (reply->callback != NULL) {
+-				if (cmd) {
+-					reply->offset = (__u16)((char*)cmd -
+-								(char *)iob->data);
+-					keep_reply = reply->callback(card,
+-							reply,
+-							(unsigned long)cmd);
+-				} else
+-					keep_reply = reply->callback(card,
+-							reply,
+-							(unsigned long)iob);
+-			}
+-			if (cmd)
+-				reply->rc = (u16) cmd->hdr.return_code;
+-			else if (iob->rc)
+-				reply->rc = iob->rc;
+-			if (keep_reply) {
+-				spin_lock_irqsave(&card->lock, flags);
+-				list_add_tail(&reply->list,
+-					      &card->cmd_waiter_list);
+-				spin_unlock_irqrestore(&card->lock, flags);
+-			} else {
+-				atomic_inc(&reply->received);
+-				wake_up(&reply->wait_q);
+-			}
+-			qeth_put_reply(reply);
+-			goto out;
+-		}
+-	}
+-	spin_unlock_irqrestore(&card->lock, flags);
+-out:
+-	memcpy(&card->seqno.pdu_hdr_ack,
+-		QETH_PDU_HEADER_SEQ_NO(iob->data),
+-		QETH_SEQ_NO_LENGTH);
+-	qeth_release_buffer(channel,iob);
+-}
+-
+-static void
+-qeth_prepare_control_data(struct qeth_card *card, int len,
+-			  struct qeth_cmd_buffer *iob)
+-{
+-	qeth_setup_ccw(&card->write,iob->data,len);
+-	iob->callback = qeth_release_buffer;
+-
+-	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+-	       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+-	card->seqno.trans_hdr++;
+-	memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
+-	       &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+-	card->seqno.pdu_hdr++;
+-	memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
+-	       &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+-	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+-}
+-
+-static int
+-qeth_send_control_data(struct qeth_card *card, int len,
+-		       struct qeth_cmd_buffer *iob,
+-		       int (*reply_cb)
+-		       (struct qeth_card *, struct qeth_reply*, unsigned long),
+-		       void *reply_param)
+-
+-{
+-	int rc;
+-	unsigned long flags;
+-	struct qeth_reply *reply = NULL;
+-	unsigned long timeout;
+-
+-	QETH_DBF_TEXT(trace, 2, "sendctl");
+-
+-	reply = qeth_alloc_reply(card);
+-	if (!reply) {
+-		PRINT_WARN("Could no alloc qeth_reply!\n");
+-		return -ENOMEM;
+-	}
+-	reply->callback = reply_cb;
+-	reply->param = reply_param;
+-	if (card->state == CARD_STATE_DOWN)
+-		reply->seqno = QETH_IDX_COMMAND_SEQNO;
+-	else
+-		reply->seqno = card->seqno.ipa++;
+-	init_waitqueue_head(&reply->wait_q);
+-	spin_lock_irqsave(&card->lock, flags);
+-	list_add_tail(&reply->list, &card->cmd_waiter_list);
+-	spin_unlock_irqrestore(&card->lock, flags);
+-	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+-
+-	while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
+-	qeth_prepare_control_data(card, len, iob);
+-
+-	if (IS_IPA(iob->data))
+-		timeout = jiffies + QETH_IPA_TIMEOUT;
+-	else
+-		timeout = jiffies + QETH_TIMEOUT;
+-
+-	QETH_DBF_TEXT(trace, 6, "noirqpnd");
+-	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+-	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+-			      (addr_t) iob, 0, 0);
+-	spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+-	if (rc){
+-		PRINT_WARN("qeth_send_control_data: "
+-			   "ccw_device_start rc = %i\n", rc);
+-		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+-		spin_lock_irqsave(&card->lock, flags);
+-		list_del_init(&reply->list);
+-		qeth_put_reply(reply);
+-		spin_unlock_irqrestore(&card->lock, flags);
+-		qeth_release_buffer(iob->channel, iob);
+-		atomic_set(&card->write.irq_pending, 0);
+-		wake_up(&card->wait_q);
+-		return rc;
+-	}
+-	while (!atomic_read(&reply->received)) {
+-		if (time_after(jiffies, timeout)) {
+-			spin_lock_irqsave(&reply->card->lock, flags);
+-			list_del_init(&reply->list);
+-			spin_unlock_irqrestore(&reply->card->lock, flags);
+-			reply->rc = -ETIME;
+-			atomic_inc(&reply->received);
+-			wake_up(&reply->wait_q);
+-		}
+-		cpu_relax();
+-	};
+-	rc = reply->rc;
+-	qeth_put_reply(reply);
+-	return rc;
+-}
+-
+-static int
+-qeth_osn_send_control_data(struct qeth_card *card, int len,
+-			   struct qeth_cmd_buffer *iob)
+-{
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace, 5, "osndctrd");
+-
+-	wait_event(card->wait_q,
+-		   atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
+-	qeth_prepare_control_data(card, len, iob);
+-	QETH_DBF_TEXT(trace, 6, "osnoirqp");
+-	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+-	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+-			      (addr_t) iob, 0, 0);
+-	spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+-	if (rc){
+-		PRINT_WARN("qeth_osn_send_control_data: "
+-			   "ccw_device_start rc = %i\n", rc);
+-		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+-		qeth_release_buffer(iob->channel, iob);
+-		atomic_set(&card->write.irq_pending, 0);
+-		wake_up(&card->wait_q);
+-	}
+-	return rc;
+-}
+-
+-static inline void
+-qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+-		     char prot_type)
+-{
+-	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+-	memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
+-	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+-	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+-}
+-
+-static int
+-qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+-		      int data_len)
+-{
+-	u16 s1, s2;
+-
+-	QETH_DBF_TEXT(trace,4,"osndipa");
+-
+-	qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
+-	s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
+-	s2 = (u16)data_len;
+-	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+-	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+-	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+-	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+-	return qeth_osn_send_control_data(card, s1, iob);
+-}
+-
+-static int
+-qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+-		  int (*reply_cb)
+-		  (struct qeth_card *,struct qeth_reply*, unsigned long),
+-		  void *reply_param)
+-{
+-	int rc;
+-	char prot_type;
+-
+-	QETH_DBF_TEXT(trace,4,"sendipa");
+-
+-	if (card->options.layer2)
+-		if (card->info.type == QETH_CARD_TYPE_OSN)
+-			prot_type = QETH_PROT_OSN2;
+-		else
+-			prot_type = QETH_PROT_LAYER2;
+-	else
+-		prot_type = QETH_PROT_TCPIP;
+-	qeth_prepare_ipa_cmd(card,iob,prot_type);
+-	rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
+-				    reply_cb, reply_param);
+-	return rc;
+-}
+-
+-
+-static int
+-qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
+-		  unsigned long data)
+-{
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(setup, 2, "cmenblcb");
+-
+-	iob = (struct qeth_cmd_buffer *) data;
+-	memcpy(&card->token.cm_filter_r,
+-	       QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data),
+-	       QETH_MPC_TOKEN_LENGTH);
+-	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+-	return 0;
+-}
+-
+-static int
+-qeth_cm_enable(struct qeth_card *card)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(setup,2,"cmenable");
+-
+-	iob = qeth_wait_for_buffer(&card->write);
+-	memcpy(iob->data, CM_ENABLE, CM_ENABLE_SIZE);
+-	memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(iob->data),
+-	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+-	memcpy(QETH_CM_ENABLE_FILTER_TOKEN(iob->data),
+-	       &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH);
+-
+-	rc = qeth_send_control_data(card, CM_ENABLE_SIZE, iob,
+-				    qeth_cm_enable_cb, NULL);
+-	return rc;
+-}
+-
+-static int
+-qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
+-		 unsigned long data)
+-{
+-
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(setup, 2, "cmsetpcb");
+-
+-	iob = (struct qeth_cmd_buffer *) data;
+-	memcpy(&card->token.cm_connection_r,
+-	       QETH_CM_SETUP_RESP_DEST_ADDR(iob->data),
+-	       QETH_MPC_TOKEN_LENGTH);
+-	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+-	return 0;
+-}
+-
+-static int
+-qeth_cm_setup(struct qeth_card *card)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(setup,2,"cmsetup");
+-
+-	iob = qeth_wait_for_buffer(&card->write);
+-	memcpy(iob->data, CM_SETUP, CM_SETUP_SIZE);
+-	memcpy(QETH_CM_SETUP_DEST_ADDR(iob->data),
+-	       &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+-	memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(iob->data),
+-	       &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH);
+-	memcpy(QETH_CM_SETUP_FILTER_TOKEN(iob->data),
+-	       &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH);
+-	rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob,
+-				    qeth_cm_setup_cb, NULL);
+-	return rc;
+-
+-}
+-
+-static int
+-qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
+-		   unsigned long data)
+-{
+-
+-	__u16 mtu, framesize;
+-	__u16 len;
+-	__u8 link_type;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(setup, 2, "ulpenacb");
+-
+-	iob = (struct qeth_cmd_buffer *) data;
+-	memcpy(&card->token.ulp_filter_r,
+-	       QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data),
+-	       QETH_MPC_TOKEN_LENGTH);
+-	if (qeth_get_mtu_out_of_mpc(card->info.type)) {
+-		memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2);
+-		mtu = qeth_get_mtu_outof_framesize(framesize);
+-		if (!mtu) {
+-			iob->rc = -EINVAL;
+-			QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+-			return 0;
+-		}
+-		card->info.max_mtu = mtu;
+-		card->info.initial_mtu = mtu;
+-		card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE;
+-	} else {
+-		card->info.initial_mtu = qeth_get_initial_mtu_for_card(card);
+-		card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type);
+-		card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
+-	}
+-
+-	memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2);
+-	if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
+-		memcpy(&link_type,
+-		       QETH_ULP_ENABLE_RESP_LINK_TYPE(iob->data), 1);
+-		card->info.link_type = link_type;
+-	} else
+-		card->info.link_type = 0;
+-	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+-	return 0;
+-}
+-
+-static int
+-qeth_ulp_enable(struct qeth_card *card)
+-{
+-	int rc;
+-	char prot_type;
+-	struct qeth_cmd_buffer *iob;
+-
+-	/*FIXME: trace view callbacks*/
+-	QETH_DBF_TEXT(setup,2,"ulpenabl");
+-
+-	iob = qeth_wait_for_buffer(&card->write);
+-	memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE);
+-
+-	*(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
+-		(__u8) card->info.portno;
+-	if (card->options.layer2)
+-		if (card->info.type == QETH_CARD_TYPE_OSN)
+-			prot_type = QETH_PROT_OSN2;
+-		else
+-			prot_type = QETH_PROT_LAYER2;
+-	else
+-		prot_type = QETH_PROT_TCPIP;
+-
+-	memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data),&prot_type,1);
+-	memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data),
+-	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+-	memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
+-	       &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
+-	memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data),
+-	       card->info.portname, 9);
+-	rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
+-				    qeth_ulp_enable_cb, NULL);
+-	return rc;
+-
+-}
+-
+-static int
+-qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
+-		  unsigned long data)
+-{
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(setup, 2, "ulpstpcb");
+-
+-	iob = (struct qeth_cmd_buffer *) data;
+-	memcpy(&card->token.ulp_connection_r,
+-	       QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
+-	       QETH_MPC_TOKEN_LENGTH);
+-	QETH_DBF_TEXT_(setup, 2, "  rc%d", iob->rc);
+-	return 0;
+-}
+-
+-static int
+-qeth_ulp_setup(struct qeth_card *card)
+-{
+-	int rc;
+-	__u16 temp;
+-	struct qeth_cmd_buffer *iob;
+-	struct ccw_dev_id dev_id;
+-
+-	QETH_DBF_TEXT(setup,2,"ulpsetup");
+-
+-	iob = qeth_wait_for_buffer(&card->write);
+-	memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE);
+-
+-	memcpy(QETH_ULP_SETUP_DEST_ADDR(iob->data),
+-	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+-	memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(iob->data),
+-	       &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH);
+-	memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data),
+-	       &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
+-
+-	ccw_device_get_id(CARD_DDEV(card), &dev_id);
+-	memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
+-	temp = (card->info.cula << 8) + card->info.unit_addr2;
+-	memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
+-	rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
+-				    qeth_ulp_setup_cb, NULL);
+-	return rc;
+-}
+-
+-static inline int
+-qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
+-		       unsigned int siga_error, const char *dbftext)
+-{
+-	if (qdio_error || siga_error) {
+-		QETH_DBF_TEXT(trace, 2, dbftext);
+-		QETH_DBF_TEXT(qerr, 2, dbftext);
+-		QETH_DBF_TEXT_(qerr, 2, " F15=%02X",
+-			       buf->element[15].flags & 0xff);
+-		QETH_DBF_TEXT_(qerr, 2, " F14=%02X",
+-			       buf->element[14].flags & 0xff);
+-		QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error);
+-		QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error);
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static struct sk_buff *
+-qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
+-{
+-	struct sk_buff* skb;
+-	int add_len;
+-
+-	add_len = 0;
+-	if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN)
+-		add_len = sizeof(struct qeth_hdr);
+-#ifdef CONFIG_QETH_VLAN
+-	else
+-		add_len = VLAN_HLEN;
+-#endif
+-	skb = dev_alloc_skb(length + add_len);
+-	if (skb && add_len)
+-		skb_reserve(skb, add_len);
+-	return skb;
+-}
+-
+-static inline int
+-qeth_create_skb_frag(struct qdio_buffer_element *element,
+-		     struct sk_buff **pskb,
+-		     int offset, int *pfrag, int data_len)
+-{
+-	struct page *page = virt_to_page(element->addr);
+-	if (*pfrag == 0) {
+-		/* the upper protocol layers assume that there is data in the
+-		 * skb itself. Copy a small amount (64 bytes) to make them
+-		 * happy. */
+-		*pskb = dev_alloc_skb(64 + QETH_FAKE_LL_LEN_ETH);
+-		if (!(*pskb))
+-			return -ENOMEM;
+-		skb_reserve(*pskb, QETH_FAKE_LL_LEN_ETH);
+-		if (data_len <= 64) {
+-			memcpy(skb_put(*pskb, data_len), element->addr + offset,
+-				data_len);
+-		} else {
+-			get_page(page);
+-			memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
+-			skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
+-				data_len - 64);
+-			(*pskb)->data_len += data_len - 64;
+-			(*pskb)->len	  += data_len - 64;
+-			(*pskb)->truesize += data_len - 64;
+-		}
+-	} else {
+-		get_page(page);
+-		skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
+-		(*pskb)->data_len += data_len;
+-		(*pskb)->len	  += data_len;
+-		(*pskb)->truesize += data_len;
+-	}
+-	(*pfrag)++;
+-	return 0;
+-}
+-
+-static inline struct qeth_buffer_pool_entry *
+-qeth_find_free_buffer_pool_entry(struct qeth_card *card)
+-{
+-	struct list_head *plh;
+-	struct qeth_buffer_pool_entry *entry;
+-	int i, free;
+-	struct page *page;
+-
+-	if (list_empty(&card->qdio.in_buf_pool.entry_list))
+-		return NULL;
+-
+-	list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
+-		entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
+-		free = 1;
+-		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+-			if (page_count(virt_to_page(entry->elements[i])) > 1) {
+-				free = 0;
+-				break;
+-			}
+-		}
+-		if (free) {
+-			list_del_init(&entry->list);
+-			return entry;
+-		}
+-	}
+-
+-	/* no free buffer in pool so take first one and swap pages */
+-	entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
+-			struct qeth_buffer_pool_entry, list);
+-	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+-		if (page_count(virt_to_page(entry->elements[i])) > 1) {
+-			page = alloc_page(GFP_ATOMIC|GFP_DMA);
+-			if (!page) {
+-				return NULL;
+-			} else {
+-				free_page((unsigned long)entry->elements[i]);
+-				entry->elements[i] = page_address(page);
+-				if (card->options.performance_stats)
+-					card->perf_stats.sg_alloc_page_rx++;
+-			}
+-		}
+-	}
+-	list_del_init(&entry->list);
+-	return entry;
+-}
+-
+-static struct sk_buff *
+-qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
+-		  struct qdio_buffer_element **__element, int *__offset,
+-		  struct qeth_hdr **hdr)
+-{
+-	struct qdio_buffer_element *element = *__element;
+-	int offset = *__offset;
+-	struct sk_buff *skb = NULL;
+-	int skb_len;
+-	void *data_ptr;
+-	int data_len;
+-	int use_rx_sg = 0;
+-	int frag = 0;
+-
+-	QETH_DBF_TEXT(trace,6,"nextskb");
+-	/* qeth_hdr must not cross element boundaries */
+-	if (element->length < offset + sizeof(struct qeth_hdr)){
+-		if (qeth_is_last_sbale(element))
+-			return NULL;
+-		element++;
+-		offset = 0;
+-		if (element->length < sizeof(struct qeth_hdr))
+-			return NULL;
+-	}
+-	*hdr = element->addr + offset;
+-
+-	offset += sizeof(struct qeth_hdr);
+-	if (card->options.layer2)
+-		if (card->info.type == QETH_CARD_TYPE_OSN)
+-			skb_len = (*hdr)->hdr.osn.pdu_length;
+-		else
+-			skb_len = (*hdr)->hdr.l2.pkt_length;
+-	else
+-		skb_len = (*hdr)->hdr.l3.length;
+-
+-	if (!skb_len)
+-		return NULL;
+-	if ((skb_len >= card->options.rx_sg_cb) &&
+-	    (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+-	    (!atomic_read(&card->force_alloc_skb))) {
+-		use_rx_sg = 1;
+-	} else {
+-		if (card->options.fake_ll) {
+-			if (card->dev->type == ARPHRD_IEEE802_TR) {
+-				if (!(skb = qeth_get_skb(skb_len +
+-						QETH_FAKE_LL_LEN_TR, *hdr)))
+-					goto no_mem;
+-				skb_reserve(skb, QETH_FAKE_LL_LEN_TR);
+-			} else {
+-				if (!(skb = qeth_get_skb(skb_len +
+-						QETH_FAKE_LL_LEN_ETH, *hdr)))
+-					goto no_mem;
+-				skb_reserve(skb, QETH_FAKE_LL_LEN_ETH);
+-			}
+-		} else {
+-			skb = qeth_get_skb(skb_len, *hdr);
+-			if (!skb)
+-				goto no_mem;
+-		}
+-	}
+-
+-	data_ptr = element->addr + offset;
+-	while (skb_len) {
+-		data_len = min(skb_len, (int)(element->length - offset));
+-		if (data_len) {
+-			if (use_rx_sg) {
+-				if (qeth_create_skb_frag(element, &skb, offset,
+-				    &frag, data_len))
+-					goto no_mem;
+-			} else {
+-				memcpy(skb_put(skb, data_len), data_ptr,
+-					data_len);
+-			}
+-		}
+-		skb_len -= data_len;
+-		if (skb_len){
+-			if (qeth_is_last_sbale(element)){
+-				QETH_DBF_TEXT(trace,4,"unexeob");
+-				QETH_DBF_TEXT_(trace,4,"%s",CARD_BUS_ID(card));
+-				QETH_DBF_TEXT(qerr,2,"unexeob");
+-				QETH_DBF_TEXT_(qerr,2,"%s",CARD_BUS_ID(card));
+-				QETH_DBF_HEX(misc,4,buffer,sizeof(*buffer));
+-				dev_kfree_skb_any(skb);
+-				card->stats.rx_errors++;
+-				return NULL;
+-			}
+-			element++;
+-			offset = 0;
+-			data_ptr = element->addr;
+-		} else {
+-			offset += data_len;
+-		}
+-	}
+-	*__element = element;
+-	*__offset = offset;
+-	if (use_rx_sg && card->options.performance_stats) {
+-		card->perf_stats.sg_skbs_rx++;
+-		card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
+-	}
+-	return skb;
+-no_mem:
+-	if (net_ratelimit()){
+-		PRINT_WARN("No memory for packet received on %s.\n",
+-			   QETH_CARD_IFNAME(card));
+-		QETH_DBF_TEXT(trace,2,"noskbmem");
+-		QETH_DBF_TEXT_(trace,2,"%s",CARD_BUS_ID(card));
+-	}
+-	card->stats.rx_dropped++;
+-	return NULL;
+-}
+-
+-static __be16
+-qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
+-{
+-	struct qeth_card *card;
+-	struct ethhdr *eth;
+-
+-	QETH_DBF_TEXT(trace,6,"typtrans");
+-
+-	card = (struct qeth_card *)dev->priv;
+-#ifdef CONFIG_TR
+-	if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+-	    (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
+-	 	return tr_type_trans(skb,dev);
+-#endif /* CONFIG_TR */
+-	skb_reset_mac_header(skb);
+-	skb_pull(skb, ETH_HLEN );
+-	eth = eth_hdr(skb);
+-
+-	if (*eth->h_dest & 1) {
+-		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+-			skb->pkt_type = PACKET_BROADCAST;
+-		else
+-			skb->pkt_type = PACKET_MULTICAST;
+-	} else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+-		skb->pkt_type = PACKET_OTHERHOST;
+-
+-	if (ntohs(eth->h_proto) >= 1536)
+-		return eth->h_proto;
+-	if (*(unsigned short *) (skb->data) == 0xFFFF)
+-		return htons(ETH_P_802_3);
+-	return htons(ETH_P_802_2);
+-}
+-
+-static void
+-qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
+-			 struct qeth_hdr *hdr)
+-{
+-	struct trh_hdr *fake_hdr;
+-	struct trllc *fake_llc;
+-	struct iphdr *ip_hdr;
+-
+-	QETH_DBF_TEXT(trace,5,"skbfktr");
+-	skb_set_mac_header(skb, (int)-QETH_FAKE_LL_LEN_TR);
+-	/* this is a fake ethernet header */
+-	fake_hdr = tr_hdr(skb);
+-
+-	/* the destination MAC address */
+-	switch (skb->pkt_type){
+-	case PACKET_MULTICAST:
+-		switch (skb->protocol){
+-#ifdef CONFIG_QETH_IPV6
+-		case __constant_htons(ETH_P_IPV6):
+-			ndisc_mc_map((struct in6_addr *)
+-				     skb->data + QETH_FAKE_LL_V6_ADDR_POS,
+-				     fake_hdr->daddr, card->dev, 0);
+-			break;
+-#endif /* CONFIG_QETH_IPV6 */
+-		case __constant_htons(ETH_P_IP):
+-			ip_hdr = (struct iphdr *)skb->data;
+-			ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr);
+-			break;
+-		default:
+-			memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
+-		}
+-		break;
+-	case PACKET_BROADCAST:
+-		memset(fake_hdr->daddr, 0xff, TR_ALEN);
+-		break;
+-	default:
+-		memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
+-	}
+-	/* the source MAC address */
+-	if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
+-		memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN);
+-	else
+-		memset(fake_hdr->saddr, 0, TR_ALEN);
+-	fake_hdr->rcf=0;
+-	fake_llc = (struct trllc*)&(fake_hdr->rcf);
+-	fake_llc->dsap = EXTENDED_SAP;
+-	fake_llc->ssap = EXTENDED_SAP;
+-	fake_llc->llc  = UI_CMD;
+-	fake_llc->protid[0] = 0;
+-	fake_llc->protid[1] = 0;
+-	fake_llc->protid[2] = 0;
+-	fake_llc->ethertype = ETH_P_IP;
+-}
+-
+-static void
+-qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
+-			 struct qeth_hdr *hdr)
+-{
+-	struct ethhdr *fake_hdr;
+-	struct iphdr *ip_hdr;
+-
+-	QETH_DBF_TEXT(trace,5,"skbfketh");
+-	skb_set_mac_header(skb, -QETH_FAKE_LL_LEN_ETH);
+-	/* this is a fake ethernet header */
+-	fake_hdr = eth_hdr(skb);
+-
+-	/* the destination MAC address */
+-	switch (skb->pkt_type){
+-	case PACKET_MULTICAST:
+-		switch (skb->protocol){
+-#ifdef CONFIG_QETH_IPV6
+-		case __constant_htons(ETH_P_IPV6):
+-			ndisc_mc_map((struct in6_addr *)
+-				     skb->data + QETH_FAKE_LL_V6_ADDR_POS,
+-				     fake_hdr->h_dest, card->dev, 0);
+-			break;
+-#endif /* CONFIG_QETH_IPV6 */
+-		case __constant_htons(ETH_P_IP):
+-			ip_hdr = (struct iphdr *)skb->data;
+-			ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
+-			break;
+-		default:
+-			memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
+-		}
+-		break;
+-	case PACKET_BROADCAST:
+-		memset(fake_hdr->h_dest, 0xff, ETH_ALEN);
+-		break;
+-	default:
+-		memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
+-	}
+-	/* the source MAC address */
+-	if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
+-		memcpy(fake_hdr->h_source, &hdr->hdr.l3.dest_addr[2], ETH_ALEN);
+-	else
+-		memset(fake_hdr->h_source, 0, ETH_ALEN);
+-	/* the protocol */
+-	fake_hdr->h_proto = skb->protocol;
+-}
+-
+-static inline void
+-qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
+-			struct qeth_hdr *hdr)
+-{
+-	if (card->dev->type == ARPHRD_IEEE802_TR)
+-		qeth_rebuild_skb_fake_ll_tr(card, skb, hdr);
+-	else
+-		qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
+-}
+-
+-static inline void
+-qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
+-			struct qeth_hdr *hdr)
+-{
+-	skb->pkt_type = PACKET_HOST;
+-	skb->protocol = qeth_type_trans(skb, skb->dev);
+-	if (card->options.checksum_type == NO_CHECKSUMMING)
+-		skb->ip_summed = CHECKSUM_UNNECESSARY;
+-	else
+-		skb->ip_summed = CHECKSUM_NONE;
+-	*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
+-}
+-
+-static __u16
+-qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
+-		 struct qeth_hdr *hdr)
+-{
+-	unsigned short vlan_id = 0;
+-#ifdef CONFIG_QETH_IPV6
+-	if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) {
+-		skb->pkt_type = PACKET_HOST;
+-		skb->protocol = qeth_type_trans(skb, card->dev);
+-		return 0;
+-	}
+-#endif /* CONFIG_QETH_IPV6 */
+-	skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
+-			      ETH_P_IP);
+-	switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK){
+-	case QETH_CAST_UNICAST:
+-		skb->pkt_type = PACKET_HOST;
+-		break;
+-	case QETH_CAST_MULTICAST:
+-		skb->pkt_type = PACKET_MULTICAST;
+-		card->stats.multicast++;
+-		break;
+-	case QETH_CAST_BROADCAST:
+-		skb->pkt_type = PACKET_BROADCAST;
+-		card->stats.multicast++;
+-		break;
+-	case QETH_CAST_ANYCAST:
+-	case QETH_CAST_NOCAST:
+-	default:
+-		skb->pkt_type = PACKET_HOST;
+-	}
+-
+-	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)?
+-			hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
+-	}
+-
+-	if (card->options.fake_ll)
+-		qeth_rebuild_skb_fake_ll(card, skb, hdr);
+-	else
+-		skb_reset_mac_header(skb);
+-	skb->ip_summed = card->options.checksum_type;
+-	if (card->options.checksum_type == HW_CHECKSUMMING){
+-		if ( (hdr->hdr.l3.ext_flags &
+-		      (QETH_HDR_EXT_CSUM_HDR_REQ |
+-		       QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
+-		     (QETH_HDR_EXT_CSUM_HDR_REQ |
+-		      QETH_HDR_EXT_CSUM_TRANSP_REQ) )
+-			skb->ip_summed = CHECKSUM_UNNECESSARY;
+-		else
+-			skb->ip_summed = SW_CHECKSUMMING;
+-	}
+-	return vlan_id;
+-}
+-
+-static void
+-qeth_process_inbound_buffer(struct qeth_card *card,
+-			    struct qeth_qdio_buffer *buf, int index)
+-{
+-	struct qdio_buffer_element *element;
+-	struct sk_buff *skb;
+-	struct qeth_hdr *hdr;
+-	int offset;
+-	int rxrc;
+-	__u16 vlan_tag = 0;
+-
+-	/* 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_get_next_skb(card, buf->buffer, &element,
+-				       &offset, &hdr))) {
+-		skb->dev = card->dev;
+-		if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
+-			qeth_layer2_rebuild_skb(card, skb, hdr);
+-		else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
+-			vlan_tag = qeth_rebuild_skb(card, skb, hdr);
+-		else if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN) {
+-			skb_push(skb, sizeof(struct qeth_hdr));
+-			skb_copy_to_linear_data(skb, hdr,
+-						sizeof(struct qeth_hdr));
+-		} else { /* unknown header type */
+-			dev_kfree_skb_any(skb);
+-			QETH_DBF_TEXT(trace, 3, "inbunkno");
+-			QETH_DBF_HEX(control, 3, hdr, QETH_DBF_CONTROL_LEN);
+-			continue;
+-		}
+-		/* is device UP ? */
+-		if (!(card->dev->flags & IFF_UP)){
+-			dev_kfree_skb_any(skb);
+-			continue;
+-		}
+-		if (card->info.type == QETH_CARD_TYPE_OSN)
+-			rxrc = card->osn_info.data_cb(skb);
+-		else
+-#ifdef CONFIG_QETH_VLAN
+-		if (vlan_tag)
+-			if (card->vlangrp)
+-				vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
+-			else {
+-				dev_kfree_skb_any(skb);
+-				continue;
+-			}
+-		else
+-#endif
+-			rxrc = netif_rx(skb);
+-		card->dev->last_rx = jiffies;
+-		card->stats.rx_packets++;
+-		card->stats.rx_bytes += skb->len;
+-	}
+-}
+-
+-static int
+-qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
+-{
+-	struct qeth_buffer_pool_entry *pool_entry;
+-	int i;
+-
+-	pool_entry = qeth_find_free_buffer_pool_entry(card);
+-	if (!pool_entry)
+-		return 1;
+-	/*
+-	 * since the buffer is accessed only from the input_tasklet
+-	 * there shouldn't be a need to synchronize; also, since we use
+-	 * the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run  out off
+-	 * buffers
+-	 */
+-	BUG_ON(!pool_entry);
+-
+-	buf->pool_entry = pool_entry;
+-	for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i){
+-		buf->buffer->element[i].length = PAGE_SIZE;
+-		buf->buffer->element[i].addr =  pool_entry->elements[i];
+-		if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
+-			buf->buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY;
+-		else
+-			buf->buffer->element[i].flags = 0;
+-	}
+-	buf->state = QETH_QDIO_BUF_EMPTY;
+-	return 0;
+-}
+-
+-static void
+-qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+-			 struct qeth_qdio_out_buffer *buf)
+-{
+-	int i;
+-	struct sk_buff *skb;
+-
+-	/* is PCI flag set on buffer? */
+-	if (buf->buffer->element[0].flags & 0x40)
+-		atomic_dec(&queue->set_pci_flags_count);
+-
+-	while ((skb = skb_dequeue(&buf->skb_list))){
+-		atomic_dec(&skb->users);
+-		dev_kfree_skb_any(skb);
+-	}
+-	qeth_eddp_buf_release_contexts(buf);
+-	for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i){
+-		buf->buffer->element[i].length = 0;
+-		buf->buffer->element[i].addr = NULL;
+-		buf->buffer->element[i].flags = 0;
+-	}
+-	buf->next_element_to_fill = 0;
+-	atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
+-}
+-
+-static void
+-qeth_queue_input_buffer(struct qeth_card *card, int index)
+-{
+-	struct qeth_qdio_q *queue = card->qdio.in_q;
+-	int count;
+-	int i;
+-	int rc;
+-	int newcount = 0;
+-
+-	QETH_DBF_TEXT(trace,6,"queinbuf");
+-	count = (index < queue->next_buf_to_init)?
+-		card->qdio.in_buf_pool.buf_count -
+-		(queue->next_buf_to_init - index) :
+-		card->qdio.in_buf_pool.buf_count -
+-		(queue->next_buf_to_init + QDIO_MAX_BUFFERS_PER_Q - index);
+-	/* only requeue at a certain threshold to avoid SIGAs */
+-	if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)){
+-		for (i = queue->next_buf_to_init;
+-		     i < queue->next_buf_to_init + count; ++i) {
+-			if (qeth_init_input_buffer(card,
+-				&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
+-				break;
+-			} else {
+-				newcount++;
+-			}
+-		}
+-
+-		if (newcount < count) {
+-			/* we are in memory shortage so we switch back to
+-			   traditional skb allocation and drop packages */
+-			if (!atomic_read(&card->force_alloc_skb) &&
+-			    net_ratelimit())
+-				PRINT_WARN("Switch to alloc skb\n");
+-			atomic_set(&card->force_alloc_skb, 3);
+-			count = newcount;
+-		} else {
+-			if ((atomic_read(&card->force_alloc_skb) == 1) &&
+-			    net_ratelimit())
+-				PRINT_WARN("Switch to sg\n");
+-			atomic_add_unless(&card->force_alloc_skb, -1, 0);
+-		}
+-
+-		/*
+-		 * according to old code it should be avoided to requeue all
+-		 * 128 buffers in order to benefit from PCI avoidance.
+-		 * this function keeps at least one buffer (the buffer at
+-		 * 'index') un-requeued -> this buffer is the first buffer that
+-		 * will be requeued the next time
+-		 */
+-		if (card->options.performance_stats) {
+-			card->perf_stats.inbound_do_qdio_cnt++;
+-			card->perf_stats.inbound_do_qdio_start_time =
+-				qeth_get_micros();
+-		}
+-		rc = do_QDIO(CARD_DDEV(card),
+-			     QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
+-			     0, queue->next_buf_to_init, count, NULL);
+-		if (card->options.performance_stats)
+-			card->perf_stats.inbound_do_qdio_time +=
+-				qeth_get_micros() -
+-				card->perf_stats.inbound_do_qdio_start_time;
+-		if (rc){
+-			PRINT_WARN("qeth_queue_input_buffer's do_QDIO "
+-				   "return %i (device %s).\n",
+-				   rc, CARD_DDEV_ID(card));
+-			QETH_DBF_TEXT(trace,2,"qinberr");
+-			QETH_DBF_TEXT_(trace,2,"%s",CARD_BUS_ID(card));
+-		}
+-		queue->next_buf_to_init = (queue->next_buf_to_init + count) %
+-					  QDIO_MAX_BUFFERS_PER_Q;
+-	}
+-}
+-
+-static inline void
+-qeth_put_buffer_pool_entry(struct qeth_card *card,
+-			   struct qeth_buffer_pool_entry *entry)
+-{
+-	QETH_DBF_TEXT(trace, 6, "ptbfplen");
+-	list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
+-}
+-
+-static void
+-qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
+-		        unsigned int qdio_err, unsigned int siga_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;
+-
+-	QETH_DBF_TEXT(trace, 6, "qdinput");
+-	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 (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+-		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
+-			QETH_DBF_TEXT(trace, 1,"qdinchk");
+-			QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+-			QETH_DBF_TEXT_(trace,1,"%04X%04X",first_element,count);
+-			QETH_DBF_TEXT_(trace,1,"%04X%04X", queue, status);
+-			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 (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
+-		      qeth_check_qdio_errors(buffer->buffer,
+-					     qdio_err, siga_err,"qinerr")))
+-			qeth_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_handle_send_error(struct qeth_card *card,
+-		       struct qeth_qdio_out_buffer *buffer,
+-		       unsigned int qdio_err, unsigned int siga_err)
+-{
+-	int sbalf15 = buffer->buffer->element[15].flags & 0xff;
+-	int cc = siga_err & 3;
+-
+-	QETH_DBF_TEXT(trace, 6, "hdsnderr");
+-	qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr");
+-	switch (cc) {
+-	case 0:
+-		if (qdio_err){
+-			QETH_DBF_TEXT(trace, 1,"lnkfail");
+-			QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+-			QETH_DBF_TEXT_(trace,1,"%04x %02x",
+-				       (u16)qdio_err, (u8)sbalf15);
+-			return QETH_SEND_ERROR_LINK_FAILURE;
+-		}
+-		return QETH_SEND_ERROR_NONE;
+-	case 2:
+-		if (siga_err & QDIO_SIGA_ERROR_B_BIT_SET) {
+-			QETH_DBF_TEXT(trace, 1, "SIGAcc2B");
+-			QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+-			return QETH_SEND_ERROR_KICK_IT;
+-		}
+-		if ((sbalf15 >= 15) && (sbalf15 <= 31))
+-			return QETH_SEND_ERROR_RETRY;
+-		return QETH_SEND_ERROR_LINK_FAILURE;
+-		/* look at qdio_error and sbalf 15 */
+-	case 1:
+-		QETH_DBF_TEXT(trace, 1, "SIGAcc1");
+-		QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+-		return QETH_SEND_ERROR_LINK_FAILURE;
+-	case 3:
+-	default:
+-		QETH_DBF_TEXT(trace, 1, "SIGAcc3");
+-		QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+-		return QETH_SEND_ERROR_KICK_IT;
+-	}
+-}
+-
+-void
+-qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
+-		   int index, int count)
+-{
+-	struct qeth_qdio_out_buffer *buf;
+-	int rc;
+-	int i;
+-	unsigned int qdio_flags;
+-
+-	QETH_DBF_TEXT(trace, 6, "flushbuf");
+-
+-	for (i = index; i < index + count; ++i) {
+-		buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+-		buf->buffer->element[buf->next_element_to_fill - 1].flags |=
+-				SBAL_FLAGS_LAST_ENTRY;
+-
+-		if (queue->card->info.type == QETH_CARD_TYPE_IQD)
+-			continue;
+-
+-		if (!queue->do_pack){
+-			if ((atomic_read(&queue->used_buffers) >=
+-		    		(QETH_HIGH_WATERMARK_PACK -
+-				 QETH_WATERMARK_PACK_FUZZ)) &&
+-		    	    !atomic_read(&queue->set_pci_flags_count)){
+-				/* it's likely that we'll go to packing
+-				 * mode soon */
+-				atomic_inc(&queue->set_pci_flags_count);
+-				buf->buffer->element[0].flags |= 0x40;
+-			}
+-		} else {
+-			if (!atomic_read(&queue->set_pci_flags_count)){
+-				/*
+-				 * there's no outstanding PCI any more, so we
+-				 * have to request a PCI to be sure that the PCI
+-				 * will wake at some time in the future then we
+-				 * can flush packed buffers that might still be
+-				 * hanging around, which can happen if no
+-				 * further send was requested by the stack
+-				 */
+-				atomic_inc(&queue->set_pci_flags_count);
+-				buf->buffer->element[0].flags |= 0x40;
+-			}
+-		}
+-	}
+-
+-	queue->card->dev->trans_start = jiffies;
+-	if (queue->card->options.performance_stats) {
+-		queue->card->perf_stats.outbound_do_qdio_cnt++;
+-		queue->card->perf_stats.outbound_do_qdio_start_time =
+-			qeth_get_micros();
+-	}
+-	qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
+-	if (under_int)
+-		qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
+-	if (atomic_read(&queue->set_pci_flags_count))
+-		qdio_flags |= QDIO_FLAG_PCI_OUT;
+-	rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
+-		     queue->queue_no, index, count, NULL);
+-	if (queue->card->options.performance_stats)
+-		queue->card->perf_stats.outbound_do_qdio_time +=
+-			qeth_get_micros() -
+-			queue->card->perf_stats.outbound_do_qdio_start_time;
+-	if (rc){
+-		QETH_DBF_TEXT(trace, 2, "flushbuf");
+-		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+-		QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
+-		queue->card->stats.tx_errors += count;
+-		/* this must not happen under normal circumstances. if it
+-		 * happens something is really wrong -> recover */
+-		qeth_schedule_recovery(queue->card);
+-		return;
+-	}
+-	atomic_add(count, &queue->used_buffers);
+-	if (queue->card->options.performance_stats)
+-		queue->card->perf_stats.bufs_sent += count;
+-}
+-
+-/*
+- * Switched to packing state if the number of used buffers on a queue
+- * reaches a certain limit.
+- */
+-static void
+-qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
+-{
+-	if (!queue->do_pack) {
+-		if (atomic_read(&queue->used_buffers)
+-		    >= QETH_HIGH_WATERMARK_PACK){
+-			/* switch non-PACKING -> PACKING */
+-			QETH_DBF_TEXT(trace, 6, "np->pack");
+-			if (queue->card->options.performance_stats)
+-				queue->card->perf_stats.sc_dp_p++;
+-			queue->do_pack = 1;
+-		}
+-	}
+-}
+-
+-/*
+- * Switches from packing to non-packing mode. If there is a packing
+- * buffer on the queue this buffer will be prepared to be flushed.
+- * In that case 1 is returned to inform the caller. If no buffer
+- * has to be flushed, zero is returned.
+- */
+-static int
+-qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
+-{
+-	struct qeth_qdio_out_buffer *buffer;
+-	int flush_count = 0;
+-
+-	if (queue->do_pack) {
+-		if (atomic_read(&queue->used_buffers)
+-		    <= QETH_LOW_WATERMARK_PACK) {
+-			/* switch PACKING -> non-PACKING */
+-			QETH_DBF_TEXT(trace, 6, "pack->np");
+-			if (queue->card->options.performance_stats)
+-				queue->card->perf_stats.sc_p_dp++;
+-			queue->do_pack = 0;
+-			/* flush packing buffers */
+-			buffer = &queue->bufs[queue->next_buf_to_fill];
+-			if ((atomic_read(&buffer->state) ==
+-						QETH_QDIO_BUF_EMPTY) &&
+-			    (buffer->next_element_to_fill > 0)) {
+-				atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
+-				flush_count++;
+-				queue->next_buf_to_fill =
+-					(queue->next_buf_to_fill + 1) %
+-					QDIO_MAX_BUFFERS_PER_Q;
+-			}
+-		}
+-	}
+-	return flush_count;
+-}
+-
+-/*
+- * Called to flush a packing buffer if no more pci flags are on the queue.
+- * Checks if there is a packing buffer and prepares it to be flushed.
+- * In that case returns 1, otherwise zero.
+- */
+-static int
+-qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
+-{
+-	struct qeth_qdio_out_buffer *buffer;
+-
+-	buffer = &queue->bufs[queue->next_buf_to_fill];
+-	if((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
+-	   (buffer->next_element_to_fill > 0)){
+-		/* it's a packing buffer */
+-		atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
+-		queue->next_buf_to_fill =
+-			(queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static void
+-qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
+-{
+-	int index;
+-	int flush_cnt = 0;
+-	int q_was_packing = 0;
+-
+-	/*
+-	 * check if weed have to switch to non-packing mode or if
+-	 * we have to get a pci flag out on the queue
+-	 */
+-	if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) ||
+-	    !atomic_read(&queue->set_pci_flags_count)){
+-		if (atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) ==
+-				QETH_OUT_Q_UNLOCKED) {
+-			/*
+-			 * If we get in here, there was no action in
+-			 * do_send_packet. So, we check if there is a
+-			 * packing buffer to be flushed here.
+-			 */
+-			netif_stop_queue(queue->card->dev);
+-			index = queue->next_buf_to_fill;
+-			q_was_packing = queue->do_pack;
+-			flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
+-			if (!flush_cnt &&
+-			    !atomic_read(&queue->set_pci_flags_count))
+-				flush_cnt +=
+-					qeth_flush_buffers_on_no_pci(queue);
+-			if (queue->card->options.performance_stats &&
+-			    q_was_packing)
+-				queue->card->perf_stats.bufs_sent_pack +=
+-					flush_cnt;
+-			if (flush_cnt)
+-				qeth_flush_buffers(queue, 1, index, flush_cnt);
+-			atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+-		}
+-	}
+-}
+-
+-static void
+-qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
+-		        unsigned int qdio_error, unsigned int siga_error,
+-			unsigned int __queue, int first_element, int count,
+-			unsigned long card_ptr)
+-{
+-	struct qeth_card *card        = (struct qeth_card *) card_ptr;
+-	struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
+-	struct qeth_qdio_out_buffer *buffer;
+-	int i;
+-
+-	QETH_DBF_TEXT(trace, 6, "qdouhdl");
+-	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+-		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
+-			QETH_DBF_TEXT(trace, 2, "achkcond");
+-			QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
+-			QETH_DBF_TEXT_(trace, 2, "%08x", status);
+-			netif_stop_queue(card->dev);
+-			qeth_schedule_recovery(card);
+-			return;
+-		}
+-	}
+-	if (card->options.performance_stats) {
+-		card->perf_stats.outbound_handler_cnt++;
+-		card->perf_stats.outbound_handler_start_time =
+-			qeth_get_micros();
+-	}
+-	for(i = first_element; i < (first_element + count); ++i){
+-		buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+-		/*we only handle the KICK_IT error by doing a recovery */
+-		if (qeth_handle_send_error(card, buffer,
+-					   qdio_error, siga_error)
+-				== QETH_SEND_ERROR_KICK_IT){
+-			netif_stop_queue(card->dev);
+-			qeth_schedule_recovery(card);
+-			return;
+-		}
+-		qeth_clear_output_buffer(queue, buffer);
+-	}
+-	atomic_sub(count, &queue->used_buffers);
+-	/* check if we need to do something on this outbound queue */
+-	if (card->info.type != QETH_CARD_TYPE_IQD)
+-		qeth_check_outbound_queue(queue);
+-
+-	netif_wake_queue(queue->card->dev);
+-	if (card->options.performance_stats)
+-		card->perf_stats.outbound_handler_time += qeth_get_micros() -
+-			card->perf_stats.outbound_handler_start_time;
+-}
+-
+-static void
+-qeth_create_qib_param_field(struct qeth_card *card, char *param_field)
+-{
+-
+-	param_field[0] = _ascebc['P'];
+-	param_field[1] = _ascebc['C'];
+-	param_field[2] = _ascebc['I'];
+-	param_field[3] = _ascebc['T'];
+-	*((unsigned int *) (&param_field[4])) = QETH_PCI_THRESHOLD_A(card);
+-	*((unsigned int *) (&param_field[8])) = QETH_PCI_THRESHOLD_B(card);
+-	*((unsigned int *) (&param_field[12])) = QETH_PCI_TIMER_VALUE(card);
+-}
+-
+-static void
+-qeth_create_qib_param_field_blkt(struct qeth_card *card, char *param_field)
+-{
+-	param_field[16] = _ascebc['B'];
+-        param_field[17] = _ascebc['L'];
+-        param_field[18] = _ascebc['K'];
+-        param_field[19] = _ascebc['T'];
+-        *((unsigned int *) (&param_field[20])) = card->info.blkt.time_total;
+-        *((unsigned int *) (&param_field[24])) = card->info.blkt.inter_packet;
+-        *((unsigned int *) (&param_field[28])) = card->info.blkt.inter_packet_jumbo;
+-}
+-
+-static void
+-qeth_initialize_working_pool_list(struct qeth_card *card)
+-{
+-	struct qeth_buffer_pool_entry *entry;
+-
+-	QETH_DBF_TEXT(trace,5,"inwrklst");
+-
+-	list_for_each_entry(entry,
+-			    &card->qdio.init_pool.entry_list, init_list) {
+-		qeth_put_buffer_pool_entry(card,entry);
+-	}
+-}
+-
+-static void
+-qeth_clear_working_pool_list(struct qeth_card *card)
+-{
+-	struct qeth_buffer_pool_entry *pool_entry, *tmp;
+-
+-	QETH_DBF_TEXT(trace,5,"clwrklst");
+-	list_for_each_entry_safe(pool_entry, tmp,
+-			    &card->qdio.in_buf_pool.entry_list, list){
+-			list_del(&pool_entry->list);
+-	}
+-}
+-
+-static void
+-qeth_free_buffer_pool(struct qeth_card *card)
+-{
+-	struct qeth_buffer_pool_entry *pool_entry, *tmp;
+-	int i=0;
+-	QETH_DBF_TEXT(trace,5,"freepool");
+-	list_for_each_entry_safe(pool_entry, tmp,
+-				 &card->qdio.init_pool.entry_list, init_list){
+-		for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i)
+-			free_page((unsigned long)pool_entry->elements[i]);
+-		list_del(&pool_entry->init_list);
+-		kfree(pool_entry);
+-	}
+-}
+-
+-static int
+-qeth_alloc_buffer_pool(struct qeth_card *card)
+-{
+-	struct qeth_buffer_pool_entry *pool_entry;
+-	void *ptr;
+-	int i, j;
+-
+-	QETH_DBF_TEXT(trace,5,"alocpool");
+-	for (i = 0; i < card->qdio.init_pool.buf_count; ++i){
+-	 	pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
+-		if (!pool_entry){
+-			qeth_free_buffer_pool(card);
+-			return -ENOMEM;
+-		}
+-		for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){
+-			ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA);
+-			if (!ptr) {
+-				while (j > 0)
+-					free_page((unsigned long)
+-						  pool_entry->elements[--j]);
+-				kfree(pool_entry);
+-				qeth_free_buffer_pool(card);
+-				return -ENOMEM;
+-			}
+-			pool_entry->elements[j] = ptr;
+-		}
+-		list_add(&pool_entry->init_list,
+-			 &card->qdio.init_pool.entry_list);
+-	}
+-	return 0;
+-}
+-
+-int
+-qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
+-{
+-	QETH_DBF_TEXT(trace, 2, "realcbp");
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	/* TODO: steel/add buffers from/to a running card's buffer pool (?) */
+-	qeth_clear_working_pool_list(card);
+-	qeth_free_buffer_pool(card);
+-	card->qdio.in_buf_pool.buf_count = bufcnt;
+-	card->qdio.init_pool.buf_count = bufcnt;
+-	return qeth_alloc_buffer_pool(card);
+-}
+-
+-static int
+-qeth_alloc_qdio_buffers(struct qeth_card *card)
+-{
+-	int i, j;
+-
+-	QETH_DBF_TEXT(setup, 2, "allcqdbf");
+-
+-	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
+-		QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
+-		return 0;
+-
+-	card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
+-				  GFP_KERNEL|GFP_DMA);
+-	if (!card->qdio.in_q)
+-		goto out_nomem;
+-	QETH_DBF_TEXT(setup, 2, "inq");
+-	QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *));
+-	memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
+-	/* give inbound qeth_qdio_buffers their qdio_buffers */
+-	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+-		card->qdio.in_q->bufs[i].buffer =
+-			&card->qdio.in_q->qdio_bufs[i];
+-	/* inbound buffer pool */
+-	if (qeth_alloc_buffer_pool(card))
+-		goto out_freeinq;
+-	/* outbound */
+-	card->qdio.out_qs =
+-		kmalloc(card->qdio.no_out_queues *
+-			sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
+-	if (!card->qdio.out_qs)
+-		goto out_freepool;
+-	for (i = 0; i < card->qdio.no_out_queues; ++i) {
+-		card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
+-					       GFP_KERNEL|GFP_DMA);
+-		if (!card->qdio.out_qs[i])
+-			goto out_freeoutq;
+-		QETH_DBF_TEXT_(setup, 2, "outq %i", i);
+-		QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *));
+-		memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
+-		card->qdio.out_qs[i]->queue_no = i;
+-		/* give outbound qeth_qdio_buffers their qdio_buffers */
+-		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
+-			card->qdio.out_qs[i]->bufs[j].buffer =
+-				&card->qdio.out_qs[i]->qdio_bufs[j];
+-			skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
+-					    skb_list);
+-			lockdep_set_class(
+-				&card->qdio.out_qs[i]->bufs[j].skb_list.lock,
+-				&qdio_out_skb_queue_key);
+-			INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
+-		}
+-	}
+-	return 0;
+-
+-out_freeoutq:
+-	while (i > 0)
+-		kfree(card->qdio.out_qs[--i]);
+-	kfree(card->qdio.out_qs);
+-	card->qdio.out_qs = NULL;
+-out_freepool:
+-	qeth_free_buffer_pool(card);
+-out_freeinq:
+-	kfree(card->qdio.in_q);
+-	card->qdio.in_q = NULL;
+-out_nomem:
+-	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+-	return -ENOMEM;
+-}
+-
+-static void
+-qeth_free_qdio_buffers(struct qeth_card *card)
+-{
+-	int i, j;
+-
+-	QETH_DBF_TEXT(trace, 2, "freeqdbf");
+-	if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
+-		QETH_QDIO_UNINITIALIZED)
+-		return;
+-	kfree(card->qdio.in_q);
+-	card->qdio.in_q = NULL;
+-	/* inbound buffer pool */
+-	qeth_free_buffer_pool(card);
+-	/* free outbound qdio_qs */
+-	if (card->qdio.out_qs) {
+-		for (i = 0; i < card->qdio.no_out_queues; ++i) {
+-			for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+-				qeth_clear_output_buffer(card->qdio.out_qs[i],
+-						&card->qdio.out_qs[i]->bufs[j]);
+-			kfree(card->qdio.out_qs[i]);
+-		}
+-		kfree(card->qdio.out_qs);
+-		card->qdio.out_qs = NULL;
+-	}
+-}
+-
+-static void
+-qeth_clear_qdio_buffers(struct qeth_card *card)
+-{
+-	int i, j;
+-
+-	QETH_DBF_TEXT(trace, 2, "clearqdbf");
+-	/* clear outbound buffers to free skbs */
+-	for (i = 0; i < card->qdio.no_out_queues; ++i)
+-		if (card->qdio.out_qs && card->qdio.out_qs[i]) {
+-			for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+-				qeth_clear_output_buffer(card->qdio.out_qs[i],
+-						&card->qdio.out_qs[i]->bufs[j]);
+-		}
+-}
+-
+-static void
+-qeth_init_qdio_info(struct qeth_card *card)
+-{
+-	QETH_DBF_TEXT(setup, 4, "intqdinf");
+-	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+-	/* inbound */
+-	card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
+-	card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
+-	card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
+-	INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
+-	INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
+-}
+-
+-static int
+-qeth_init_qdio_queues(struct qeth_card *card)
+-{
+-	int i, j;
+-	int rc;
+-
+-	QETH_DBF_TEXT(setup, 2, "initqdqs");
+-
+-	/* inbound queue */
+-	memset(card->qdio.in_q->qdio_bufs, 0,
+-	       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+-	qeth_initialize_working_pool_list(card);
+-	/*give only as many buffers to hardware as we have buffer pool entries*/
+-	for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
+-		qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
+-	card->qdio.in_q->next_buf_to_init = card->qdio.in_buf_pool.buf_count - 1;
+-	rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
+-		     card->qdio.in_buf_pool.buf_count - 1, NULL);
+-	if (rc) {
+-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+-		return rc;
+-	}
+-	rc = qdio_synchronize(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0);
+-	if (rc) {
+-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+-		return rc;
+-	}
+-	/* outbound queue */
+-	for (i = 0; i < card->qdio.no_out_queues; ++i){
+-		memset(card->qdio.out_qs[i]->qdio_bufs, 0,
+-		       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+-		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
+-			qeth_clear_output_buffer(card->qdio.out_qs[i],
+-					&card->qdio.out_qs[i]->bufs[j]);
+-		}
+-		card->qdio.out_qs[i]->card = card;
+-		card->qdio.out_qs[i]->next_buf_to_fill = 0;
+-		card->qdio.out_qs[i]->do_pack = 0;
+-		atomic_set(&card->qdio.out_qs[i]->used_buffers,0);
+-		atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0);
+-		atomic_set(&card->qdio.out_qs[i]->state,
+-			   QETH_OUT_Q_UNLOCKED);
+-	}
+-	return 0;
+-}
+-
+-static int
+-qeth_qdio_establish(struct qeth_card *card)
+-{
+-	struct qdio_initialize init_data;
+-	char *qib_param_field;
+-	struct qdio_buffer **in_sbal_ptrs;
+-	struct qdio_buffer **out_sbal_ptrs;
+-	int i, j, k;
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(setup, 2, "qdioest");
+-
+-	qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
+-			      GFP_KERNEL);
+- 	if (!qib_param_field)
+-		return -ENOMEM;
+-
+-	qeth_create_qib_param_field(card, qib_param_field);
+-	qeth_create_qib_param_field_blkt(card, qib_param_field);
+-
+-	in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
+-			       GFP_KERNEL);
+-	if (!in_sbal_ptrs) {
+-		kfree(qib_param_field);
+-		return -ENOMEM;
+-	}
+-	for(i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+-		in_sbal_ptrs[i] = (struct qdio_buffer *)
+-			virt_to_phys(card->qdio.in_q->bufs[i].buffer);
+-
+-	out_sbal_ptrs =
+-		kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
+-			sizeof(void *), GFP_KERNEL);
+-	if (!out_sbal_ptrs) {
+-		kfree(in_sbal_ptrs);
+-		kfree(qib_param_field);
+-		return -ENOMEM;
+-	}
+-	for(i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
+-		for(j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k){
+-			out_sbal_ptrs[k] = (struct qdio_buffer *)
+-				virt_to_phys(card->qdio.out_qs[i]->
+-					     bufs[j].buffer);
+-		}
+-
+-	memset(&init_data, 0, sizeof(struct qdio_initialize));
+-	init_data.cdev                   = CARD_DDEV(card);
+-	init_data.q_format               = qeth_get_qdio_q_format(card);
+-	init_data.qib_param_field_format = 0;
+-	init_data.qib_param_field        = qib_param_field;
+-	init_data.min_input_threshold    = QETH_MIN_INPUT_THRESHOLD;
+-	init_data.max_input_threshold    = QETH_MAX_INPUT_THRESHOLD;
+-	init_data.min_output_threshold   = QETH_MIN_OUTPUT_THRESHOLD;
+-	init_data.max_output_threshold   = QETH_MAX_OUTPUT_THRESHOLD;
+-	init_data.no_input_qs            = 1;
+-	init_data.no_output_qs           = card->qdio.no_out_queues;
+-	init_data.input_handler          = (qdio_handler_t *)
+-					   qeth_qdio_input_handler;
+-	init_data.output_handler         = (qdio_handler_t *)
+-					   qeth_qdio_output_handler;
+-	init_data.int_parm               = (unsigned long) card;
+-	init_data.flags                  = QDIO_INBOUND_0COPY_SBALS |
+-					   QDIO_OUTBOUND_0COPY_SBALS |
+-					   QDIO_USE_OUTBOUND_PCIS;
+-	init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
+-	init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+-
+-	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
+-		QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED)
+-		if ((rc = qdio_initialize(&init_data)))
+-			atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
+-
+-	kfree(out_sbal_ptrs);
+-	kfree(in_sbal_ptrs);
+-	kfree(qib_param_field);
+-	return rc;
+-}
+-
+-static int
+-qeth_qdio_activate(struct qeth_card *card)
+-{
+-	QETH_DBF_TEXT(setup,3,"qdioact");
+-	return qdio_activate(CARD_DDEV(card), 0);
+-}
+-
+-static int
+-qeth_clear_channel(struct qeth_channel *channel)
+-{
+-	unsigned long flags;
+-	struct qeth_card *card;
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"clearch");
+-	card = CARD_FROM_CDEV(channel->ccwdev);
+-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+-	rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
+-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+-	if (rc)
+-		return rc;
+-	rc = wait_event_interruptible_timeout(card->wait_q,
+-			channel->state==CH_STATE_STOPPED, QETH_TIMEOUT);
+-	if (rc == -ERESTARTSYS)
+-		return rc;
+-	if (channel->state != CH_STATE_STOPPED)
+-		return -ETIME;
+-	channel->state = CH_STATE_DOWN;
+-	return 0;
+-}
+-
+-static int
+-qeth_halt_channel(struct qeth_channel *channel)
+-{
+-	unsigned long flags;
+-	struct qeth_card *card;
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"haltch");
+-	card = CARD_FROM_CDEV(channel->ccwdev);
+-	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+-	rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
+-	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+-	if (rc)
+-		return rc;
+-	rc = wait_event_interruptible_timeout(card->wait_q,
+-			channel->state==CH_STATE_HALTED, QETH_TIMEOUT);
+-	if (rc == -ERESTARTSYS)
+-		return rc;
+-	if (channel->state != CH_STATE_HALTED)
+-		return -ETIME;
+-	return 0;
+-}
+-
+-static int
+-qeth_halt_channels(struct qeth_card *card)
+-{
+-	int rc1 = 0, rc2=0, rc3 = 0;
+-
+-	QETH_DBF_TEXT(trace,3,"haltchs");
+-	rc1 = qeth_halt_channel(&card->read);
+-	rc2 = qeth_halt_channel(&card->write);
+-	rc3 = qeth_halt_channel(&card->data);
+-	if (rc1)
+-		return rc1;
+-	if (rc2)
+-		return rc2;
+-	return rc3;
+-}
+-static int
+-qeth_clear_channels(struct qeth_card *card)
+-{
+-	int rc1 = 0, rc2=0, rc3 = 0;
+-
+-	QETH_DBF_TEXT(trace,3,"clearchs");
+-	rc1 = qeth_clear_channel(&card->read);
+-	rc2 = qeth_clear_channel(&card->write);
+-	rc3 = qeth_clear_channel(&card->data);
+-	if (rc1)
+-		return rc1;
+-	if (rc2)
+-		return rc2;
+-	return rc3;
+-}
+-
+-static int
+-qeth_clear_halt_card(struct qeth_card *card, int halt)
+-{
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace,3,"clhacrd");
+-	QETH_DBF_HEX(trace, 3, &card, sizeof(void *));
+-
+-	if (halt)
+-		rc = qeth_halt_channels(card);
+-	if (rc)
+-		return rc;
+-	return qeth_clear_channels(card);
+-}
+-
+-static int
+-qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
+-{
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace,3,"qdioclr");
+-	switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED,
+-		QETH_QDIO_CLEANING)) {
+-	case QETH_QDIO_ESTABLISHED:
+-		if ((rc = qdio_cleanup(CARD_DDEV(card),
+-				(card->info.type == QETH_CARD_TYPE_IQD) ?
+-				QDIO_FLAG_CLEANUP_USING_HALT :
+-				QDIO_FLAG_CLEANUP_USING_CLEAR)))
+-			QETH_DBF_TEXT_(trace, 3, "1err%d", rc);
+-		atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
+-		break;
+-	case QETH_QDIO_CLEANING:
+-		return rc;
+-	default:
+-		break;
+-	}
+-	if ((rc = qeth_clear_halt_card(card, use_halt)))
+-		QETH_DBF_TEXT_(trace, 3, "2err%d", rc);
+-	card->state = CARD_STATE_DOWN;
+-	return rc;
+-}
+-
+-static int
+-qeth_dm_act(struct qeth_card *card)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(setup,2,"dmact");
+-
+-	iob = qeth_wait_for_buffer(&card->write);
+-	memcpy(iob->data, DM_ACT, DM_ACT_SIZE);
+-
+-	memcpy(QETH_DM_ACT_DEST_ADDR(iob->data),
+-	       &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+-	memcpy(QETH_DM_ACT_CONNECTION_TOKEN(iob->data),
+-	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+-	rc = qeth_send_control_data(card, DM_ACT_SIZE, iob, NULL, NULL);
+-	return rc;
+-}
+-
+-static int
+-qeth_mpc_initialize(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(setup,2,"mpcinit");
+-
+-	if ((rc = qeth_issue_next_read(card))){
+-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+-		return rc;
+-	}
+-	if ((rc = qeth_cm_enable(card))){
+-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+-		goto out_qdio;
+-	}
+-	if ((rc = qeth_cm_setup(card))){
+-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+-		goto out_qdio;
+-	}
+-	if ((rc = qeth_ulp_enable(card))){
+-		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+-		goto out_qdio;
+-	}
+-	if ((rc = qeth_ulp_setup(card))){
+-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+-		goto out_qdio;
+-	}
+-	if ((rc = qeth_alloc_qdio_buffers(card))){
+-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+-		goto out_qdio;
+-	}
+-	if ((rc = qeth_qdio_establish(card))){
+-		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+-		qeth_free_qdio_buffers(card);
+-		goto out_qdio;
+-	}
+- 	if ((rc = qeth_qdio_activate(card))){
+-		QETH_DBF_TEXT_(setup, 2, "7err%d", rc);
+-		goto out_qdio;
+-	}
+-	if ((rc = qeth_dm_act(card))){
+-		QETH_DBF_TEXT_(setup, 2, "8err%d", rc);
+-		goto out_qdio;
+-	}
+-
+-	return 0;
+-out_qdio:
+-	qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
+-	return rc;
+-}
+-
+-static struct net_device *
+-qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype)
+-{
+-	struct net_device *dev = NULL;
+-
+-	switch (type) {
+-	case QETH_CARD_TYPE_OSAE:
+-		switch (linktype) {
+-		case QETH_LINK_TYPE_LANE_TR:
+-		case QETH_LINK_TYPE_HSTR:
+-#ifdef CONFIG_TR
+-			dev = alloc_trdev(0);
+-#endif /* CONFIG_TR */
+-			break;
+-		default:
+-			dev = alloc_etherdev(0);
+-		}
+-		break;
+-	case QETH_CARD_TYPE_IQD:
+-		dev = alloc_netdev(0, "hsi%d", ether_setup);
+-		break;
+-	case QETH_CARD_TYPE_OSN:
+-		dev = alloc_netdev(0, "osn%d", ether_setup);
+-		break;
+-	default:
+-		dev = alloc_etherdev(0);
+-	}
+-	return dev;
+-}
+-
+-/*hard_header fake function; used in case fake_ll is set */
+-static int
+-qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
+-		 unsigned short type, const void *daddr, const void *saddr,
+-		 unsigned len)
+-{
+-	if(dev->type == ARPHRD_IEEE802_TR){
+-		struct trh_hdr *hdr;
+-        	hdr = (struct trh_hdr *)skb_push(skb, QETH_FAKE_LL_LEN_TR);
+-		memcpy(hdr->saddr, dev->dev_addr, TR_ALEN);
+-        	memcpy(hdr->daddr, "FAKELL", TR_ALEN);
+-		return QETH_FAKE_LL_LEN_TR;
+-
+-	} else {
+-		struct ethhdr *hdr;
+-        	hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN_ETH);
+-		memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
+-        	memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
+-        	if (type != ETH_P_802_3)
+-                	hdr->h_proto = htons(type);
+-        	else
+-                	hdr->h_proto = htons(len);
+-		return QETH_FAKE_LL_LEN_ETH;
+-
+-	}
+-}
+-
+-static const struct header_ops qeth_fake_ops = {
+-	.create	= qeth_fake_header,
+-	.parse  = qeth_hard_header_parse,
+-};
+-
+-static int
+-qeth_send_packet(struct qeth_card *, struct sk_buff *);
+-
+-static int
+-qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+-{
+-	int rc;
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(trace, 6, "hrdstxmi");
+-	card = (struct qeth_card *)dev->priv;
+-	if (skb==NULL) {
+-		card->stats.tx_dropped++;
+-		card->stats.tx_errors++;
+-		/* return OK; otherwise ksoftirqd goes to 100% */
+-		return NETDEV_TX_OK;
+-	}
+-	if ((card->state != CARD_STATE_UP) || !card->lan_online) {
+-		card->stats.tx_dropped++;
+-		card->stats.tx_errors++;
+-		card->stats.tx_carrier_errors++;
+-		dev_kfree_skb_any(skb);
+-		/* return OK; otherwise ksoftirqd goes to 100% */
+-		return NETDEV_TX_OK;
+-	}
+-	if (card->options.performance_stats) {
+-		card->perf_stats.outbound_cnt++;
+-		card->perf_stats.outbound_start_time = qeth_get_micros();
+-	}
+-	netif_stop_queue(dev);
+-	if ((rc = qeth_send_packet(card, skb))) {
+-		if (rc == -EBUSY) {
+-			return NETDEV_TX_BUSY;
+-		} else {
+-			card->stats.tx_errors++;
+-			card->stats.tx_dropped++;
+-			dev_kfree_skb_any(skb);
+-			/*set to OK; otherwise ksoftirqd goes to 100% */
+-			rc = NETDEV_TX_OK;
+-		}
+-	}
+-	netif_wake_queue(dev);
+-	if (card->options.performance_stats)
+-		card->perf_stats.outbound_time += qeth_get_micros() -
+-			card->perf_stats.outbound_start_time;
+-	return rc;
+-}
+-
+-static int
+-qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card)
+-{
+-	int rc = 0;
+-#ifdef CONFIG_QETH_VLAN
+-	struct vlan_group *vg;
+-	int i;
+-
+-	if (!(vg = card->vlangrp))
+-		return rc;
+-
+-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++){
+-		if (vlan_group_get_device(vg, i) == dev){
+-			rc = QETH_VLAN_CARD;
+-			break;
+-		}
+-	}
+-	if (rc && !(vlan_dev_info(dev)->real_dev->priv == (void *)card))
+-		return 0;
+-
+-#endif
+-	return rc;
+-}
+-
+-static int
+-qeth_verify_dev(struct net_device *dev)
+-{
+-	struct qeth_card *card;
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	read_lock_irqsave(&qeth_card_list.rwlock, flags);
+-	list_for_each_entry(card, &qeth_card_list.list, list){
+-		if (card->dev == dev){
+-			rc = QETH_REAL_CARD;
+-			break;
+-		}
+-		rc = qeth_verify_vlan_dev(dev, card);
+-		if (rc)
+-			break;
+-	}
+-	read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+-
+-	return rc;
+-}
+-
+-static struct qeth_card *
+-qeth_get_card_from_dev(struct net_device *dev)
+-{
+-	struct qeth_card *card = NULL;
+-	int rc;
+-
+-	rc = qeth_verify_dev(dev);
+-	if (rc == QETH_REAL_CARD)
+-		card = (struct qeth_card *)dev->priv;
+-	else if (rc == QETH_VLAN_CARD)
+-		card = (struct qeth_card *)
+-			vlan_dev_info(dev)->real_dev->priv;
+-
+-	QETH_DBF_TEXT_(trace, 4, "%d", rc);
+-	return card ;
+-}
+-
+-static void
+-qeth_tx_timeout(struct net_device *dev)
+-{
+-	struct qeth_card *card;
+-
+-	card = (struct qeth_card *) dev->priv;
+-	card->stats.tx_errors++;
+-	qeth_schedule_recovery(card);
+-}
+-
+-static int
+-qeth_open(struct net_device *dev)
+-{
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(trace, 4, "qethopen");
+-
+-	card = (struct qeth_card *) dev->priv;
+-
+-	if (card->state != CARD_STATE_SOFTSETUP)
+-		return -ENODEV;
+-
+-	if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
+-	     (card->options.layer2) &&
+-	     (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
+-		QETH_DBF_TEXT(trace,4,"nomacadr");
+-		return -EPERM;
+-	}
+-	card->data.state = CH_STATE_UP;
+-	card->state = CARD_STATE_UP;
+-	card->dev->flags |= IFF_UP;
+-	netif_start_queue(dev);
+-
+-	if (!card->lan_online && netif_carrier_ok(dev))
+-		netif_carrier_off(dev);
+-	return 0;
+-}
+-
+-static int
+-qeth_stop(struct net_device *dev)
+-{
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(trace, 4, "qethstop");
+-
+-	card = (struct qeth_card *) dev->priv;
+-
+-	netif_tx_disable(dev);
+-	card->dev->flags &= ~IFF_UP;
+-	if (card->state == CARD_STATE_UP)
+-		card->state = CARD_STATE_SOFTSETUP;
+-	return 0;
+-}
+-
+-static int
+-qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
+-{
+-	int cast_type = RTN_UNSPEC;
+-
+-	if (card->info.type == QETH_CARD_TYPE_OSN)
+-		return cast_type;
+-
+-	if (skb->dst && skb->dst->neighbour){
+-		cast_type = skb->dst->neighbour->type;
+-		if ((cast_type == RTN_BROADCAST) ||
+-		    (cast_type == RTN_MULTICAST) ||
+-		    (cast_type == RTN_ANYCAST))
+-			return cast_type;
+-		else
+-			return RTN_UNSPEC;
+-	}
+-	/* try something else */
+-	if (skb->protocol == ETH_P_IPV6)
+-		return (skb_network_header(skb)[24] == 0xff) ?
+-				RTN_MULTICAST : 0;
+-	else if (skb->protocol == ETH_P_IP)
+-		return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
+-				RTN_MULTICAST : 0;
+-	/* ... */
+-	if (!memcmp(skb->data, skb->dev->broadcast, 6))
+-		return RTN_BROADCAST;
+-	else {
+-		u16 hdr_mac;
+-
+-	        hdr_mac = *((u16 *)skb->data);
+-	        /* tr multicast? */
+-	        switch (card->info.link_type) {
+-	        case QETH_LINK_TYPE_HSTR:
+-	        case QETH_LINK_TYPE_LANE_TR:
+-	        	if ((hdr_mac == QETH_TR_MAC_NC) ||
+-			    (hdr_mac == QETH_TR_MAC_C))
+-				return RTN_MULTICAST;
+-			break;
+-	        /* eth or so multicast? */
+-                default:
+-                      	if ((hdr_mac == QETH_ETH_MAC_V4) ||
+-			    (hdr_mac == QETH_ETH_MAC_V6))
+-			        return RTN_MULTICAST;
+-	        }
+-        }
+-	return cast_type;
+-}
+-
+-static int
+-qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
+-		        int ipv, int cast_type)
+-{
+-	if (!ipv && (card->info.type == QETH_CARD_TYPE_OSAE))
+-		return card->qdio.default_out_queue;
+-	switch (card->qdio.no_out_queues) {
+-	case 4:
+-		if (cast_type && card->info.is_multicast_different)
+-			return card->info.is_multicast_different &
+-				(card->qdio.no_out_queues - 1);
+-		if (card->qdio.do_prio_queueing && (ipv == 4)) {
+-			const u8 tos = ip_hdr(skb)->tos;
+-
+-			if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_TOS){
+-				if (tos & IP_TOS_NOTIMPORTANT)
+-					return 3;
+-				if (tos & IP_TOS_HIGHRELIABILITY)
+-					return 2;
+-				if (tos & IP_TOS_HIGHTHROUGHPUT)
+-					return 1;
+-				if (tos & IP_TOS_LOWDELAY)
+-					return 0;
+-			}
+-			if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_PREC)
+-				return 3 - (tos >> 6);
+-		} else if (card->qdio.do_prio_queueing && (ipv == 6)) {
+-			/* TODO: IPv6!!! */
+-		}
+-		return card->qdio.default_out_queue;
+-	case 1: /* fallthrough for single-out-queue 1920-device */
+-	default:
+-		return card->qdio.default_out_queue;
+-	}
+-}
+-
+-static inline int
+-qeth_get_ip_version(struct sk_buff *skb)
+-{
+-	switch (skb->protocol) {
+-	case ETH_P_IPV6:
+-		return 6;
+-	case ETH_P_IP:
+-		return 4;
+-	default:
+-		return 0;
+-	}
+-}
+-
+-static struct qeth_hdr *
+-__qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
+-{
+-#ifdef CONFIG_QETH_VLAN
+-	u16 *tag;
+-	if (card->vlangrp && vlan_tx_tag_present(skb) &&
+-	    ((ipv == 6) || card->options.layer2) ) {
+-		/*
+-		 * Move the mac addresses (6 bytes src, 6 bytes dest)
+-		 * to the beginning of the new header.  We are using three
+-		 * memcpys instead of one memmove to save cycles.
+-		 */
+-		skb_push(skb, VLAN_HLEN);
+-		skb_copy_to_linear_data(skb, skb->data + 4, 4);
+-		skb_copy_to_linear_data_offset(skb, 4, skb->data + 8, 4);
+-		skb_copy_to_linear_data_offset(skb, 8, skb->data + 12, 4);
+-		tag = (u16 *)(skb->data + 12);
+-		/*
+-		 * first two bytes  = ETH_P_8021Q (0x8100)
+-		 * second two bytes = VLANID
+-		 */
+-		*tag = __constant_htons(ETH_P_8021Q);
+-		*(tag + 1) = htons(vlan_tx_tag_get(skb));
+-	}
+-#endif
+-	return ((struct qeth_hdr *)
+-		qeth_push_skb(card, skb, sizeof(struct qeth_hdr)));
+-}
+-
+-static void
+-__qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb)
+-{
+-	if (orig_skb != new_skb)
+-		dev_kfree_skb_any(new_skb);
+-}
+-
+-static struct sk_buff *
+-qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
+-		 struct qeth_hdr **hdr, int ipv)
+-{
+-	struct sk_buff *new_skb, *new_skb2;
+-	
+-	QETH_DBF_TEXT(trace, 6, "prepskb");
+-	new_skb = skb;
+-	new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
+-	if (!new_skb)
+-		return NULL;
+-	new_skb2 = qeth_realloc_headroom(card, new_skb,
+-					 sizeof(struct qeth_hdr));
+-	if (!new_skb2) {
+-		__qeth_free_new_skb(skb, new_skb);
+-		return NULL;
+-	}
+-	if (new_skb != skb)
+-		__qeth_free_new_skb(new_skb2, new_skb);
+-	new_skb = new_skb2;
+-	*hdr = __qeth_prepare_skb(card, new_skb, ipv);
+-	if (*hdr == NULL) {
+-		__qeth_free_new_skb(skb, new_skb);
+-		return NULL;
+-	}
+-	return new_skb;
+-}
+-
+-static inline u8
+-qeth_get_qeth_hdr_flags4(int cast_type)
+-{
+-	if (cast_type == RTN_MULTICAST)
+-		return QETH_CAST_MULTICAST;
+-	if (cast_type == RTN_BROADCAST)
+-		return QETH_CAST_BROADCAST;
+-	return QETH_CAST_UNICAST;
+-}
+-
+-static inline u8
+-qeth_get_qeth_hdr_flags6(int cast_type)
+-{
+-	u8 ct = QETH_HDR_PASSTHRU | QETH_HDR_IPV6;
+-	if (cast_type == RTN_MULTICAST)
+-		return ct | QETH_CAST_MULTICAST;
+-	if (cast_type == RTN_ANYCAST)
+-		return ct | QETH_CAST_ANYCAST;
+-	if (cast_type == RTN_BROADCAST)
+-		return ct | QETH_CAST_BROADCAST;
+-	return ct | QETH_CAST_UNICAST;
+-}
+-
+-static void
+-qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr,
+-			    struct sk_buff *skb)
+-{
+-	__u16 hdr_mac;
+-
+-	if (!memcmp(skb->data+QETH_HEADER_SIZE,
+-		    skb->dev->broadcast,6)) { /* broadcast? */
+-		*(__u32 *)hdr->hdr.l2.flags |=
+-			 QETH_LAYER2_FLAG_BROADCAST << 8;
+-		return;
+-	}
+-	hdr_mac=*((__u16*)skb->data);
+-	/* tr multicast? */
+-	switch (card->info.link_type) {
+-	case QETH_LINK_TYPE_HSTR:
+-	case QETH_LINK_TYPE_LANE_TR:
+-		if ((hdr_mac == QETH_TR_MAC_NC) ||
+-		    (hdr_mac == QETH_TR_MAC_C) )
+-			*(__u32 *)hdr->hdr.l2.flags |=
+-				QETH_LAYER2_FLAG_MULTICAST << 8;
+-		else
+-			*(__u32 *)hdr->hdr.l2.flags |=
+-				QETH_LAYER2_FLAG_UNICAST << 8;
+-		break;
+-		/* eth or so multicast? */
+-	default:
+-		if ( (hdr_mac==QETH_ETH_MAC_V4) ||
+-		     (hdr_mac==QETH_ETH_MAC_V6) )
+-			*(__u32 *)hdr->hdr.l2.flags |=
+-				QETH_LAYER2_FLAG_MULTICAST << 8;
+-		else
+-			*(__u32 *)hdr->hdr.l2.flags |=
+-				QETH_LAYER2_FLAG_UNICAST << 8;
+-	}
+-}
+-
+-static void
+-qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
+-			struct sk_buff *skb, int cast_type)
+-{
+-	memset(hdr, 0, sizeof(struct qeth_hdr));
+-	hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
+-
+-	/* set byte 0 to "0x02" and byte 3 to casting flags */
+-	if (cast_type==RTN_MULTICAST)
+-		*(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_MULTICAST << 8;
+-	else if (cast_type==RTN_BROADCAST)
+-		*(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_BROADCAST << 8;
+-	 else
+-		qeth_layer2_get_packet_type(card, hdr, skb);
+-
+-	hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
+-#ifdef CONFIG_QETH_VLAN
+-	/* VSWITCH relies on the VLAN
+-	 * information to be present in
+-	 * the QDIO header */
+-	if ((card->vlangrp != NULL) &&
+-	    vlan_tx_tag_present(skb)) {
+-		*(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_VLAN << 8;
+-		hdr->hdr.l2.vlan_id = vlan_tx_tag_get(skb);
+-	}
+-#endif
+-}
+-
+-void
+-qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
+-		struct sk_buff *skb, int ipv, int cast_type)
+-{
+-	QETH_DBF_TEXT(trace, 6, "fillhdr");
+-
+-	memset(hdr, 0, sizeof(struct qeth_hdr));
+-	if (card->options.layer2) {
+-		qeth_layer2_fill_header(card, hdr, skb, cast_type);
+-		return;
+-	}
+-	hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
+-	hdr->hdr.l3.ext_flags = 0;
+-#ifdef CONFIG_QETH_VLAN
+-	/*
+-	 * before we're going to overwrite this location with next hop ip.
+-	 * v6 uses passthrough, v4 sets the tag in the QDIO header.
+-	 */
+-	if (card->vlangrp && vlan_tx_tag_present(skb)) {
+-		hdr->hdr.l3.ext_flags = (ipv == 4) ?
+-			QETH_HDR_EXT_VLAN_FRAME :
+-			QETH_HDR_EXT_INCLUDE_VLAN_TAG;
+-		hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
+-	}
+-#endif /* CONFIG_QETH_VLAN */
+-	hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+-	if (ipv == 4) {	 /* IPv4 */
+-		hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags4(cast_type);
+-		memset(hdr->hdr.l3.dest_addr, 0, 12);
+-		if ((skb->dst) && (skb->dst->neighbour)) {
+-			*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
+-			    *((u32 *) skb->dst->neighbour->primary_key);
+-		} else {
+-			/* fill in destination address used in ip header */
+-			*((u32 *)(&hdr->hdr.l3.dest_addr[12])) =
+-							   ip_hdr(skb)->daddr;
+-		}
+-	} else if (ipv == 6) { /* IPv6 or passthru */
+-		hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags6(cast_type);
+-		if ((skb->dst) && (skb->dst->neighbour)) {
+-			memcpy(hdr->hdr.l3.dest_addr,
+-			       skb->dst->neighbour->primary_key, 16);
+-		} else {
+-			/* fill in destination address used in ip header */
+-			memcpy(hdr->hdr.l3.dest_addr,
+-			       &ipv6_hdr(skb)->daddr, 16);
+-		}
+-	} else { /* passthrough */
+-                if((skb->dev->type == ARPHRD_IEEE802_TR) &&
+-		    !memcmp(skb->data + sizeof(struct qeth_hdr) +
+-		    sizeof(__u16), skb->dev->broadcast, 6)) {
+-			hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+-						QETH_HDR_PASSTHRU;
+-		} else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
+-			    skb->dev->broadcast, 6)) {   /* broadcast? */
+-			hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+-						QETH_HDR_PASSTHRU;
+-		} else {
+- 			hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
+- 				QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
+- 				QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
+-		}
+-	}
+-}
+-
+-static void
+-__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
+-		   int is_tso, int *next_element_to_fill)
+-{
+-	int length = skb->len;
+-	int length_here;
+-	int element;
+-	char *data;
+-	int first_lap ;
+-
+-	element = *next_element_to_fill;
+-	data = skb->data;
+-	first_lap = (is_tso == 0 ? 1 : 0);
+-
+-	while (length > 0) {
+-		/* length_here is the remaining amount of data in this page */
+-		length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
+-		if (length < length_here)
+-			length_here = length;
+-
+-		buffer->element[element].addr = data;
+-		buffer->element[element].length = length_here;
+-		length -= length_here;
+-		if (!length) {
+-			if (first_lap)
+-				buffer->element[element].flags = 0;
+-			else
+-				buffer->element[element].flags =
+-				    SBAL_FLAGS_LAST_FRAG;
+-		} else {
+-			if (first_lap)
+-				buffer->element[element].flags =
+-				    SBAL_FLAGS_FIRST_FRAG;
+-			else
+-				buffer->element[element].flags =
+-				    SBAL_FLAGS_MIDDLE_FRAG;
+-		}
+-		data += length_here;
+-		element++;
+-		first_lap = 0;
+-	}
+-	*next_element_to_fill = element;
+-}
+-
+-static int
+-qeth_fill_buffer(struct qeth_qdio_out_q *queue,
+-		 struct qeth_qdio_out_buffer *buf,
+-		 struct sk_buff *skb)
+-{
+-	struct qdio_buffer *buffer;
+-	struct qeth_hdr_tso *hdr;
+-	int flush_cnt = 0, hdr_len, large_send = 0;
+-
+-	QETH_DBF_TEXT(trace, 6, "qdfillbf");
+-
+-	buffer = buf->buffer;
+-	atomic_inc(&skb->users);
+-	skb_queue_tail(&buf->skb_list, skb);
+-
+-	hdr  = (struct qeth_hdr_tso *) skb->data;
+-	/*check first on TSO ....*/
+-	if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
+-		int element = buf->next_element_to_fill;
+-
+-		hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
+-		/*fill first buffer entry only with header information */
+-		buffer->element[element].addr = skb->data;
+-		buffer->element[element].length = hdr_len;
+-		buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
+-		buf->next_element_to_fill++;
+-		skb->data += hdr_len;
+-		skb->len  -= hdr_len;
+-		large_send = 1;
+-	}
+-	if (skb_shinfo(skb)->nr_frags == 0)
+-		__qeth_fill_buffer(skb, buffer, large_send,
+-				   (int *)&buf->next_element_to_fill);
+-	else
+-		__qeth_fill_buffer_frag(skb, buffer, large_send,
+-					(int *)&buf->next_element_to_fill);
+-
+-	if (!queue->do_pack) {
+-		QETH_DBF_TEXT(trace, 6, "fillbfnp");
+-		/* set state to PRIMED -> will be flushed */
+-		atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+-		flush_cnt = 1;
+-	} else {
+-		QETH_DBF_TEXT(trace, 6, "fillbfpa");
+-		if (queue->card->options.performance_stats)
+-			queue->card->perf_stats.skbs_sent_pack++;
+-		if (buf->next_element_to_fill >=
+-				QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
+-			/*
+-			 * packed buffer if full -> set state PRIMED
+-			 * -> will be flushed
+-			 */
+-			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+-			flush_cnt = 1;
+-		}
+-	}
+-	return flush_cnt;
+-}
+-
+-static int
+-qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
+-			 struct sk_buff *skb, struct qeth_hdr *hdr,
+-			 int elements_needed,
+-			 struct qeth_eddp_context *ctx)
+-{
+-	struct qeth_qdio_out_buffer *buffer;
+-	int buffers_needed = 0;
+-	int flush_cnt = 0;
+-	int index;
+-
+-	QETH_DBF_TEXT(trace, 6, "dosndpfa");
+-
+-	/* spin until we get the queue ... */
+-	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+-			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
+-	/* ... now we've got the queue */
+-	index = queue->next_buf_to_fill;
+-	buffer = &queue->bufs[queue->next_buf_to_fill];
+-	/*
+-	 * check if buffer is empty to make sure that we do not 'overtake'
+-	 * ourselves and try to fill a buffer that is already primed
+-	 */
+-	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) 
+-		goto out;
+-	if (ctx == NULL)
+-		queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
+-					  QDIO_MAX_BUFFERS_PER_Q;
+-	else {
+-		buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx);
+-		if (buffers_needed < 0) 
+-			goto out;
+-		queue->next_buf_to_fill =
+-			(queue->next_buf_to_fill + buffers_needed) %
+-			QDIO_MAX_BUFFERS_PER_Q;
+-	}
+-	atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+-	if (ctx == NULL) {
+-		qeth_fill_buffer(queue, buffer, skb);
+-		qeth_flush_buffers(queue, 0, index, 1);
+-	} else {
+-		flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
+-		WARN_ON(buffers_needed != flush_cnt);
+-		qeth_flush_buffers(queue, 0, index, flush_cnt);
+-	}
+-	return 0;
+-out:
+-	atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+-	return -EBUSY;
+-}
+-
+-static int
+-qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
+-		    struct sk_buff *skb, struct qeth_hdr *hdr,
+-		    int elements_needed, struct qeth_eddp_context *ctx)
+-{
+-	struct qeth_qdio_out_buffer *buffer;
+-	int start_index;
+-	int flush_count = 0;
+-	int do_pack = 0;
+-	int tmp;
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace, 6, "dosndpkt");
+-
+-	/* spin until we get the queue ... */
+-	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+-			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
+-	start_index = queue->next_buf_to_fill;
+-	buffer = &queue->bufs[queue->next_buf_to_fill];
+-	/*
+-	 * check if buffer is empty to make sure that we do not 'overtake'
+-	 * ourselves and try to fill a buffer that is already primed
+-	 */
+-	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
+-		atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+-		return -EBUSY;
+-	}
+-	/* check if we need to switch packing state of this queue */
+-	qeth_switch_to_packing_if_needed(queue);
+-	if (queue->do_pack){
+-		do_pack = 1;
+-		if (ctx == NULL) {
+-			/* does packet fit in current buffer? */
+-			if((QETH_MAX_BUFFER_ELEMENTS(card) -
+-			    buffer->next_element_to_fill) < elements_needed){
+-				/* ... no -> set state PRIMED */
+-				atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
+-				flush_count++;
+-				queue->next_buf_to_fill =
+-					(queue->next_buf_to_fill + 1) %
+-					QDIO_MAX_BUFFERS_PER_Q;
+-				buffer = &queue->bufs[queue->next_buf_to_fill];
+-				/* we did a step forward, so check buffer state
+-				 * again */
+-				if (atomic_read(&buffer->state) !=
+-						QETH_QDIO_BUF_EMPTY){
+-					qeth_flush_buffers(queue, 0, start_index, flush_count);
+-					atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+-					return -EBUSY;
+-				}
+-			}
+-		} else {
+-			/* check if we have enough elements (including following
+-			 * free buffers) to handle eddp context */
+-			if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){
+-				if (net_ratelimit())
+-					PRINT_WARN("eddp tx_dropped 1\n");
+-				rc = -EBUSY;
+-				goto out;
+-			}
+-		}
+-	}
+-	if (ctx == NULL)
+-		tmp = qeth_fill_buffer(queue, buffer, skb);
+-	else {
+-		tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill);
+-		if (tmp < 0) {
+-			printk("eddp tx_dropped 2\n");
+-			rc = - EBUSY;
+-			goto out;
+-		}
+-	}
+-	queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
+-				  QDIO_MAX_BUFFERS_PER_Q;
+-	flush_count += tmp;
+-out:
+-	if (flush_count)
+-		qeth_flush_buffers(queue, 0, start_index, flush_count);
+-	else if (!atomic_read(&queue->set_pci_flags_count))
+-		atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
+-	/*
+-	 * queue->state will go from LOCKED -> UNLOCKED or from
+-	 * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
+-	 * (switch packing state or flush buffer to get another pci flag out).
+-	 * In that case we will enter this loop
+-	 */
+-	while (atomic_dec_return(&queue->state)){
+-		flush_count = 0;
+-		start_index = queue->next_buf_to_fill;
+-		/* check if we can go back to non-packing state */
+-		flush_count += qeth_switch_to_nonpacking_if_needed(queue);
+-		/*
+-		 * check if we need to flush a packing buffer to get a pci
+-		 * flag out on the queue
+-		 */
+-		if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
+-			flush_count += qeth_flush_buffers_on_no_pci(queue);
+-		if (flush_count)
+-			qeth_flush_buffers(queue, 0, start_index, flush_count);
+-	}
+-	/* at this point the queue is UNLOCKED again */
+-	if (queue->card->options.performance_stats && do_pack)
+-		queue->card->perf_stats.bufs_sent_pack += flush_count;
+-
+-	return rc;
+-}
+-
+-static int
+-qeth_get_elements_no(struct qeth_card *card, void *hdr,
+-		     struct sk_buff *skb, int elems)
+-{
+-	int elements_needed = 0;
+-
+-        if (skb_shinfo(skb)->nr_frags > 0) 
+-                elements_needed = (skb_shinfo(skb)->nr_frags + 1);
+-        if (elements_needed == 0)
+-                elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+-                                        + skb->len) >> PAGE_SHIFT);
+-	if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
+-                PRINT_ERR("Invalid size of IP packet "
+-			  "(Number=%d / Length=%d). Discarded.\n",
+-                          (elements_needed+elems), skb->len);
+-                return 0;
+-        }
+-        return elements_needed;
+-}
+-
+-static void qeth_tx_csum(struct sk_buff *skb)
+-{
+-	int tlen;
+-
+-	if (skb->protocol == htons(ETH_P_IP)) {
+-		tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2);
+-		switch (ip_hdr(skb)->protocol) {
+-		case IPPROTO_TCP:
+-			tcp_hdr(skb)->check = 0;
+-			tcp_hdr(skb)->check = csum_tcpudp_magic(
+-				ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
+-				tlen, ip_hdr(skb)->protocol,
+-				skb_checksum(skb, skb_transport_offset(skb),
+-					tlen, 0));
+-			break;
+-		case IPPROTO_UDP:
+-			udp_hdr(skb)->check = 0;
+-			udp_hdr(skb)->check = csum_tcpudp_magic(
+-				ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
+-				tlen, ip_hdr(skb)->protocol,
+-				skb_checksum(skb, skb_transport_offset(skb),
+-					tlen, 0));
+-			break;
+-		}
+-	} else if (skb->protocol == htons(ETH_P_IPV6)) {
+-		switch (ipv6_hdr(skb)->nexthdr) {
+-		case IPPROTO_TCP:
+-			tcp_hdr(skb)->check = 0;
+-			tcp_hdr(skb)->check = csum_ipv6_magic(
+-				&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
+-				ipv6_hdr(skb)->payload_len,
+-				ipv6_hdr(skb)->nexthdr,
+-				skb_checksum(skb, skb_transport_offset(skb),
+-					ipv6_hdr(skb)->payload_len, 0));
+-			break;
+-		case IPPROTO_UDP:
+-			udp_hdr(skb)->check = 0;
+-			udp_hdr(skb)->check = csum_ipv6_magic(
+-				&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
+-				ipv6_hdr(skb)->payload_len,
+-				ipv6_hdr(skb)->nexthdr,
+-				skb_checksum(skb, skb_transport_offset(skb),
+-					ipv6_hdr(skb)->payload_len, 0));
+-			break;
+-		}
+-	}
+-}
+-
+-static int
+-qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
+-{
+-	int ipv = 0;
+-	int cast_type;
+-	struct qeth_qdio_out_q *queue;
+-	struct qeth_hdr *hdr = NULL;
+-	int elements_needed = 0;
+-	enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
+-	struct qeth_eddp_context *ctx = NULL;
+-	int tx_bytes = skb->len;
+-	unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
+-	unsigned short tso_size = skb_shinfo(skb)->gso_size;
+-	struct sk_buff *new_skb, *new_skb2;
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace, 6, "sendpkt");
+-
+-	new_skb = skb;
+-	if ((card->info.type == QETH_CARD_TYPE_OSN) &&
+-	    (skb->protocol == htons(ETH_P_IPV6)))
+-		return -EPERM;
+-	cast_type = qeth_get_cast_type(card, skb);
+-	if ((cast_type == RTN_BROADCAST) &&
+-	    (card->info.broadcast_capable == 0))
+-		return -EPERM;
+-	queue = card->qdio.out_qs
+-		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
+-	if (!card->options.layer2) {
+-		ipv = qeth_get_ip_version(skb);
+-		if ((card->dev->header_ops == &qeth_fake_ops) && ipv) {
+-			new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
+-			if (!new_skb)
+-				return -ENOMEM;
+-			if(card->dev->type == ARPHRD_IEEE802_TR){
+-				skb_pull(new_skb, QETH_FAKE_LL_LEN_TR);
+-			} else {
+-				skb_pull(new_skb, QETH_FAKE_LL_LEN_ETH);
+-			}
+-		}
+-	}
+-	if (skb_is_gso(skb))
+-		large_send = card->options.large_send;
+-	/* check on OSN device*/
+-	if (card->info.type == QETH_CARD_TYPE_OSN)
+-		hdr = (struct qeth_hdr *)new_skb->data;
+-	/*are we able to do TSO ? */
+-	if ((large_send == QETH_LARGE_SEND_TSO) &&
+-	    (cast_type == RTN_UNSPEC)) {
+-		rc = qeth_tso_prepare_packet(card, new_skb, ipv, cast_type);
+-		if (rc) {
+-			__qeth_free_new_skb(skb, new_skb);
+-			return rc;
+-		}
+-		elements_needed++;
+-	} else if (card->info.type != QETH_CARD_TYPE_OSN) {
+-		new_skb2 = qeth_prepare_skb(card, new_skb, &hdr, ipv);
+-		if (!new_skb2) {
+-			__qeth_free_new_skb(skb, new_skb);
+-			return -EINVAL;
+-		}
+-		if (new_skb != skb)
+-			__qeth_free_new_skb(new_skb2, new_skb);
+-		new_skb = new_skb2;
+-		qeth_fill_header(card, hdr, new_skb, ipv, cast_type);
+-	}
+-	if (large_send == QETH_LARGE_SEND_EDDP) {
+-		ctx = qeth_eddp_create_context(card, new_skb, hdr,
+-					       skb->sk->sk_protocol);
+-		if (ctx == NULL) {
+-			__qeth_free_new_skb(skb, new_skb);
+-			PRINT_WARN("could not create eddp context\n");
+-			return -EINVAL;
+-		}
+-	} else {
+-		int elems = qeth_get_elements_no(card,(void*) hdr, new_skb,
+-						 elements_needed);
+-		if (!elems) {
+-			__qeth_free_new_skb(skb, new_skb);
+-			return -EINVAL;
+-		}
+-		elements_needed += elems;
+-	}
+-
+-	if ((large_send == QETH_LARGE_SEND_NO) &&
+-	    (skb->ip_summed == CHECKSUM_PARTIAL))
+-		qeth_tx_csum(new_skb);
+-
+-	if (card->info.type != QETH_CARD_TYPE_IQD)
+-		rc = qeth_do_send_packet(card, queue, new_skb, hdr,
+-					 elements_needed, ctx);
+-	else {
+-		if ((!card->options.layer2) &&
+-		    (ipv == 0)) {
+-			__qeth_free_new_skb(skb, new_skb);
+-			return -EPERM;
+-		}
+-		rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
+-					      elements_needed, ctx);
+-	}
+-	if (!rc) {
+-		card->stats.tx_packets++;
+-		card->stats.tx_bytes += tx_bytes;
+-		if (new_skb != skb)
+-			dev_kfree_skb_any(skb);
+-		if (card->options.performance_stats) {
+-			if (tso_size &&
+-			    !(large_send == QETH_LARGE_SEND_NO)) {
+-				card->perf_stats.large_send_bytes += tx_bytes;
+-				card->perf_stats.large_send_cnt++;
+-			}
+-			if (nr_frags > 0) {
+-				card->perf_stats.sg_skbs_sent++;
+-				/* nr_frags + skb->data */
+-				card->perf_stats.sg_frags_sent +=
+-					nr_frags + 1;
+-			}
+-		}
+-	} else {
+-		card->stats.tx_dropped++;
+-		__qeth_free_new_skb(skb, new_skb);
+-	}
+-	if (ctx != NULL) {
+-		/* drop creator's reference */
+-		qeth_eddp_put_context(ctx);
+-		/* free skb; it's not referenced by a buffer */
+-		if (!rc)
+-		       dev_kfree_skb_any(new_skb);
+-	}
+-	return rc;
+-}
+-
+-static int
+-qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
+-{
+-	struct qeth_card *card = (struct qeth_card *) dev->priv;
+-	int rc = 0;
+-
+-	switch(regnum){
+-	case MII_BMCR: /* Basic mode control register */
+-		rc = BMCR_FULLDPLX;
+-		if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&&
+-		    (card->info.link_type != QETH_LINK_TYPE_OSN) &&
+-		    (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
+-			rc |= BMCR_SPEED100;
+-		break;
+-	case MII_BMSR: /* Basic mode status register */
+-		rc = BMSR_ERCAP | BMSR_ANEGCOMPLETE | BMSR_LSTATUS |
+-		     BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL |
+-		     BMSR_100BASE4;
+-		break;
+-	case MII_PHYSID1: /* PHYS ID 1 */
+-		rc = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 8) |
+-		     dev->dev_addr[2];
+-		rc = (rc >> 5) & 0xFFFF;
+-		break;
+-	case MII_PHYSID2: /* PHYS ID 2 */
+-		rc = (dev->dev_addr[2] << 10) & 0xFFFF;
+-		break;
+-	case MII_ADVERTISE: /* Advertisement control reg */
+-		rc = ADVERTISE_ALL;
+-		break;
+-	case MII_LPA: /* Link partner ability reg */
+-		rc = LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL |
+-		     LPA_100BASE4 | LPA_LPACK;
+-		break;
+-	case MII_EXPANSION: /* Expansion register */
+-		break;
+-	case MII_DCOUNTER: /* disconnect counter */
+-		break;
+-	case MII_FCSCOUNTER: /* false carrier counter */
+-		break;
+-	case MII_NWAYTEST: /* N-way auto-neg test register */
+-		break;
+-	case MII_RERRCOUNTER: /* rx error counter */
+-		rc = card->stats.rx_errors;
+-		break;
+-	case MII_SREVISION: /* silicon revision */
+-		break;
+-	case MII_RESV1: /* reserved 1 */
+-		break;
+-	case MII_LBRERROR: /* loopback, rx, bypass error */
+-		break;
+-	case MII_PHYADDR: /* physical address */
+-		break;
+-	case MII_RESV2: /* reserved 2 */
+-		break;
+-	case MII_TPISTATUS: /* TPI status for 10mbps */
+-		break;
+-	case MII_NCONFIG: /* network interface config */
+-		break;
+-	default:
+-		break;
+-	}
+-	return rc;
+-}
+-
+-
+-static const char *
+-qeth_arp_get_error_cause(int *rc)
+-{
+-	switch (*rc) {
+-	case QETH_IPA_ARP_RC_FAILED:
+-		*rc = -EIO;
+-		return "operation failed";
+-	case QETH_IPA_ARP_RC_NOTSUPP:
+-		*rc = -EOPNOTSUPP;
+-		return "operation not supported";
+-	case QETH_IPA_ARP_RC_OUT_OF_RANGE:
+-		*rc = -EINVAL;
+-		return "argument out of range";
+-	case QETH_IPA_ARP_RC_Q_NOTSUPP:
+-		*rc = -EOPNOTSUPP;
+-		return "query operation not supported";
+-	case QETH_IPA_ARP_RC_Q_NO_DATA:
+-		*rc = -ENOENT;
+-		return "no query data available";
+-	default:
+-		return "unknown error";
+-	}
+-}
+-
+-static int
+-qeth_send_simple_setassparms(struct qeth_card *, enum qeth_ipa_funcs,
+-			     __u16, long);
+-
+-static int
+-qeth_arp_set_no_entries(struct qeth_card *card, int no_entries)
+-{
+-	int tmp;
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"arpstnoe");
+-
+-	/*
+-	 * currently GuestLAN only supports the ARP assist function
+-	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+-	 * thus we say EOPNOTSUPP for this ARP function
+-	 */
+-	if (card->info.guestlan)
+-		return -EOPNOTSUPP;
+-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+-		PRINT_WARN("ARP processing not supported "
+-			   "on %s!\n", QETH_CARD_IFNAME(card));
+-		return -EOPNOTSUPP;
+-	}
+-	rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+-					  IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
+-					  no_entries);
+-	if (rc) {
+-		tmp = rc;
+-		PRINT_WARN("Could not set number of ARP entries on %s: "
+-			   "%s (0x%x/%d)\n",
+-			   QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
+-			   tmp, tmp);
+-	}
+-	return rc;
+-}
+-
+-static void
+-qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
+-		               struct qeth_arp_query_data *qdata,
+-			       int entry_size, int uentry_size)
+-{
+-	char *entry_ptr;
+-	char *uentry_ptr;
+-	int i;
+-
+-	entry_ptr = (char *)&qdata->data;
+-	uentry_ptr = (char *)(qinfo->udata + qinfo->udata_offset);
+-	for (i = 0; i < qdata->no_entries; ++i){
+-		/* strip off 32 bytes "media specific information" */
+-		memcpy(uentry_ptr, (entry_ptr + 32), entry_size - 32);
+-		entry_ptr += entry_size;
+-		uentry_ptr += uentry_size;
+-	}
+-}
+-
+-static int
+-qeth_arp_query_cb(struct qeth_card *card, struct qeth_reply *reply,
+-		  unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-	struct qeth_arp_query_data *qdata;
+-	struct qeth_arp_query_info *qinfo;
+-	int entry_size;
+-	int uentry_size;
+-	int i;
+-
+-	QETH_DBF_TEXT(trace,4,"arpquecb");
+-
+-	qinfo = (struct qeth_arp_query_info *) reply->param;
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	if (cmd->hdr.return_code) {
+-		QETH_DBF_TEXT_(trace,4,"qaer1%i", cmd->hdr.return_code);
+-		return 0;
+-	}
+-	if (cmd->data.setassparms.hdr.return_code) {
+-		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
+-		QETH_DBF_TEXT_(trace,4,"qaer2%i", cmd->hdr.return_code);
+-		return 0;
+-	}
+-	qdata = &cmd->data.setassparms.data.query_arp;
+-	switch(qdata->reply_bits){
+-	case 5:
+-		uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry5);
+-		if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+-			uentry_size = sizeof(struct qeth_arp_qi_entry5_short);
+-		break;
+-	case 7:
+-		/* fall through to default */
+-	default:
+-		/* tr is the same as eth -> entry7 */
+-		uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry7);
+-		if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+-			uentry_size = sizeof(struct qeth_arp_qi_entry7_short);
+-		break;
+-	}
+-	/* check if there is enough room in userspace */
+-	if ((qinfo->udata_len - qinfo->udata_offset) <
+-			qdata->no_entries * uentry_size){
+-		QETH_DBF_TEXT_(trace, 4, "qaer3%i", -ENOMEM);
+-		cmd->hdr.return_code = -ENOMEM;
+-		PRINT_WARN("query ARP user space buffer is too small for "
+-			   "the returned number of ARP entries. "
+-			   "Aborting query!\n");
+-		goto out_error;
+-	}
+-	QETH_DBF_TEXT_(trace, 4, "anore%i",
+-		       cmd->data.setassparms.hdr.number_of_replies);
+-	QETH_DBF_TEXT_(trace, 4, "aseqn%i", cmd->data.setassparms.hdr.seq_no);
+-	QETH_DBF_TEXT_(trace, 4, "anoen%i", qdata->no_entries);
+-
+-	if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) {
+-		/* strip off "media specific information" */
+-		qeth_copy_arp_entries_stripped(qinfo, qdata, entry_size,
+-					       uentry_size);
+-	} else
+-		/*copy entries to user buffer*/
+-		memcpy(qinfo->udata + qinfo->udata_offset,
+-		       (char *)&qdata->data, qdata->no_entries*uentry_size);
+-
+-	qinfo->no_entries += qdata->no_entries;
+-	qinfo->udata_offset += (qdata->no_entries*uentry_size);
+-	/* check if all replies received ... */
+-	if (cmd->data.setassparms.hdr.seq_no <
+-	    cmd->data.setassparms.hdr.number_of_replies)
+-		return 1;
+-	memcpy(qinfo->udata, &qinfo->no_entries, 4);
+-	/* keep STRIP_ENTRIES flag so the user program can distinguish
+-	 * stripped entries from normal ones */
+-	if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+-		qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES;
+-	memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET,&qdata->reply_bits,2);
+-	return 0;
+-out_error:
+-	i = 0;
+-	memcpy(qinfo->udata, &i, 4);
+-	return 0;
+-}
+-
+-static int
+-qeth_send_ipa_arp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+-		      int len, int (*reply_cb)(struct qeth_card *,
+-					       struct qeth_reply *,
+-					       unsigned long),
+-		      void *reply_param)
+-{
+-	QETH_DBF_TEXT(trace,4,"sendarp");
+-
+-	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+-	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+-	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+-	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+-				      reply_cb, reply_param);
+-}
+-
+-static int
+-qeth_send_ipa_snmp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+-		      int len, int (*reply_cb)(struct qeth_card *,
+-					       struct qeth_reply *,
+-					       unsigned long),
+-		      void *reply_param)
+-{
+-	u16 s1, s2;
+-
+-	QETH_DBF_TEXT(trace,4,"sendsnmp");
+-
+-	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+-	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+-	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+-	/* adjust PDU length fields in IPA_PDU_HEADER */
+-	s1 = (u32) IPA_PDU_HEADER_SIZE + len;
+-	s2 = (u32) len;
+-	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+-	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+-	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+-	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+-	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+-				      reply_cb, reply_param);
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_setassparms_cmd(struct qeth_card *, enum qeth_ipa_funcs,
+-			 __u16, __u16, enum qeth_prot_versions);
+-static int
+-qeth_arp_query(struct qeth_card *card, char __user *udata)
+-{
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_arp_query_info qinfo = {0, };
+-	int tmp;
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"arpquery");
+-
+-	if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
+-			       IPA_ARP_PROCESSING)) {
+-		PRINT_WARN("ARP processing not supported "
+-			   "on %s!\n", QETH_CARD_IFNAME(card));
+-		return -EOPNOTSUPP;
+-	}
+-	/* get size of userspace buffer and mask_bits -> 6 bytes */
+-	if (copy_from_user(&qinfo, udata, 6))
+-		return -EFAULT;
+-	if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL)))
+-		return -ENOMEM;
+-	qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
+-	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+-				       IPA_CMD_ASS_ARP_QUERY_INFO,
+-				       sizeof(int),QETH_PROT_IPV4);
+-
+-	rc = qeth_send_ipa_arp_cmd(card, iob,
+-				   QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
+-				   qeth_arp_query_cb, (void *)&qinfo);
+-	if (rc) {
+-		tmp = rc;
+-		PRINT_WARN("Error while querying ARP cache on %s: %s "
+-			   "(0x%x/%d)\n",
+-			   QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
+-			   tmp, tmp);
+-		if (copy_to_user(udata, qinfo.udata, 4))
+-			rc = -EFAULT;
+-	} else {
+-		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+-			rc = -EFAULT;
+-	}
+-	kfree(qinfo.udata);
+-	return rc;
+-}
+-
+-/**
+- * SNMP command callback
+- */
+-static int
+-qeth_snmp_command_cb(struct qeth_card *card, struct qeth_reply *reply,
+-		     unsigned long sdata)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-	struct qeth_arp_query_info *qinfo;
+-	struct qeth_snmp_cmd *snmp;
+-	unsigned char *data;
+-	__u16 data_len;
+-
+-	QETH_DBF_TEXT(trace,3,"snpcmdcb");
+-
+-	cmd = (struct qeth_ipa_cmd *) sdata;
+-	data = (unsigned char *)((char *)cmd - reply->offset);
+-	qinfo = (struct qeth_arp_query_info *) reply->param;
+-	snmp = &cmd->data.setadapterparms.data.snmp;
+-
+-	if (cmd->hdr.return_code) {
+-		QETH_DBF_TEXT_(trace,4,"scer1%i", cmd->hdr.return_code);
+-		return 0;
+-	}
+-	if (cmd->data.setadapterparms.hdr.return_code) {
+-		cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code;
+-		QETH_DBF_TEXT_(trace,4,"scer2%i", cmd->hdr.return_code);
+-		return 0;
+-	}
+-	data_len = *((__u16*)QETH_IPA_PDU_LEN_PDU1(data));
+-	if (cmd->data.setadapterparms.hdr.seq_no == 1)
+-		data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
+-	else
+-		data_len -= (__u16)((char*)&snmp->request - (char *)cmd);
+-
+-	/* check if there is enough room in userspace */
+-	if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
+-		QETH_DBF_TEXT_(trace, 4, "scer3%i", -ENOMEM);
+-		cmd->hdr.return_code = -ENOMEM;
+-		return 0;
+-	}
+-	QETH_DBF_TEXT_(trace, 4, "snore%i",
+-		       cmd->data.setadapterparms.hdr.used_total);
+-	QETH_DBF_TEXT_(trace, 4, "sseqn%i", cmd->data.setadapterparms.hdr.seq_no);
+-	/*copy entries to user buffer*/
+-	if (cmd->data.setadapterparms.hdr.seq_no == 1) {
+-		memcpy(qinfo->udata + qinfo->udata_offset,
+-		       (char *)snmp,
+-		       data_len + offsetof(struct qeth_snmp_cmd,data));
+-		qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
+-	} else {
+-		memcpy(qinfo->udata + qinfo->udata_offset,
+-		       (char *)&snmp->request, data_len);
+-	}
+-	qinfo->udata_offset += data_len;
+-	/* check if all replies received ... */
+-		QETH_DBF_TEXT_(trace, 4, "srtot%i",
+-			       cmd->data.setadapterparms.hdr.used_total);
+-		QETH_DBF_TEXT_(trace, 4, "srseq%i",
+-			       cmd->data.setadapterparms.hdr.seq_no);
+-	if (cmd->data.setadapterparms.hdr.seq_no <
+-	    cmd->data.setadapterparms.hdr.used_total)
+-		return 1;
+-	return 0;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_ipacmd_buffer(struct qeth_card *, enum qeth_ipa_cmds,
+-		       enum qeth_prot_versions );
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_adapter_cmd(struct qeth_card *card, __u32 command, __u32 cmdlen)
+-{
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	iob = qeth_get_ipacmd_buffer(card,IPA_CMD_SETADAPTERPARMS,
+-				     QETH_PROT_IPV4);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
+-	cmd->data.setadapterparms.hdr.command_code = command;
+-	cmd->data.setadapterparms.hdr.used_total = 1;
+-	cmd->data.setadapterparms.hdr.seq_no = 1;
+-
+-	return iob;
+-}
+-
+-/**
+- * function to send SNMP commands to OSA-E card
+- */
+-static int
+-qeth_snmp_command(struct qeth_card *card, char __user *udata)
+-{
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-	struct qeth_snmp_ureq *ureq;
+-	int req_len;
+-	struct qeth_arp_query_info qinfo = {0, };
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace,3,"snmpcmd");
+-
+-	if (card->info.guestlan)
+-		return -EOPNOTSUPP;
+-
+-	if ((!qeth_adp_supported(card,IPA_SETADP_SET_SNMP_CONTROL)) &&
+-	    (!card->options.layer2) ) {
+-		PRINT_WARN("SNMP Query MIBS not supported "
+-			   "on %s!\n", QETH_CARD_IFNAME(card));
+-		return -EOPNOTSUPP;
+-	}
+-	/* skip 4 bytes (data_len struct member) to get req_len */
+-	if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
+-		return -EFAULT;
+-	ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
+-	if (!ureq) {
+-		QETH_DBF_TEXT(trace, 2, "snmpnome");
+-		return -ENOMEM;
+-	}
+-	if (copy_from_user(ureq, udata,
+-			req_len+sizeof(struct qeth_snmp_ureq_hdr))){
+-		kfree(ureq);
+-		return -EFAULT;
+-	}
+-	qinfo.udata_len = ureq->hdr.data_len;
+-	if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL))){
+-		kfree(ureq);
+-		return -ENOMEM;
+-	}
+-	qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
+-
+-	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
+-				   QETH_SNMP_SETADP_CMDLENGTH + req_len);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
+-	rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
+-				    qeth_snmp_command_cb, (void *)&qinfo);
+-	if (rc)
+-		PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-	else {
+-		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+-			rc = -EFAULT;
+-	}
+-
+-	kfree(ureq);
+-	kfree(qinfo.udata);
+-	return rc;
+-}
+-
+-static int
+-qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *,
+-			    unsigned long);
+-
+-static int
+-qeth_default_setadapterparms_cb(struct qeth_card *card,
+-                                struct qeth_reply *reply,
+-                                unsigned long data);
+-static int
+-qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *,
+-		      __u16, long,
+-		      int (*reply_cb)
+-		      (struct qeth_card *, struct qeth_reply *, unsigned long),
+-		      void *reply_param);
+-
+-static int
+-qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
+-{
+-	struct qeth_cmd_buffer *iob;
+-	char buf[16];
+-	int tmp;
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"arpadent");
+-
+-	/*
+-	 * currently GuestLAN only supports the ARP assist function
+-	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+-	 * thus we say EOPNOTSUPP for this ARP function
+-	 */
+-	if (card->info.guestlan)
+-		return -EOPNOTSUPP;
+-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+-		PRINT_WARN("ARP processing not supported "
+-			   "on %s!\n", QETH_CARD_IFNAME(card));
+-		return -EOPNOTSUPP;
+-	}
+-
+-	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+-				       IPA_CMD_ASS_ARP_ADD_ENTRY,
+-				       sizeof(struct qeth_arp_cache_entry),
+-				       QETH_PROT_IPV4);
+-	rc = qeth_send_setassparms(card, iob,
+-				   sizeof(struct qeth_arp_cache_entry),
+-				   (unsigned long) entry,
+-				   qeth_default_setassparms_cb, NULL);
+-	if (rc) {
+-		tmp = rc;
+-		qeth_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
+-		PRINT_WARN("Could not add ARP entry for address %s on %s: "
+-			   "%s (0x%x/%d)\n",
+-			   buf, QETH_CARD_IFNAME(card),
+-			   qeth_arp_get_error_cause(&rc), tmp, tmp);
+-	}
+-	return rc;
+-}
+-
+-static int
+-qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
+-{
+-	struct qeth_cmd_buffer *iob;
+-	char buf[16] = {0, };
+-	int tmp;
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"arprment");
+-
+-	/*
+-	 * currently GuestLAN only supports the ARP assist function
+-	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+-	 * thus we say EOPNOTSUPP for this ARP function
+-	 */
+-	if (card->info.guestlan)
+-		return -EOPNOTSUPP;
+-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+-		PRINT_WARN("ARP processing not supported "
+-			   "on %s!\n", QETH_CARD_IFNAME(card));
+-		return -EOPNOTSUPP;
+-	}
+-	memcpy(buf, entry, 12);
+-	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+-				       IPA_CMD_ASS_ARP_REMOVE_ENTRY,
+-				       12,
+-				       QETH_PROT_IPV4);
+-	rc = qeth_send_setassparms(card, iob,
+-				   12, (unsigned long)buf,
+-				   qeth_default_setassparms_cb, NULL);
+-	if (rc) {
+-		tmp = rc;
+-		memset(buf, 0, 16);
+-		qeth_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
+-		PRINT_WARN("Could not delete ARP entry for address %s on %s: "
+-			   "%s (0x%x/%d)\n",
+-			   buf, QETH_CARD_IFNAME(card),
+-			   qeth_arp_get_error_cause(&rc), tmp, tmp);
+-	}
+-	return rc;
+-}
+-
+-static int
+-qeth_arp_flush_cache(struct qeth_card *card)
+-{
+-	int rc;
+-	int tmp;
+-
+-	QETH_DBF_TEXT(trace,3,"arpflush");
+-
+-	/*
+-	 * currently GuestLAN only supports the ARP assist function
+-	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+-	 * thus we say EOPNOTSUPP for this ARP function
+-	*/
+-	if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
+-		return -EOPNOTSUPP;
+-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+-		PRINT_WARN("ARP processing not supported "
+-			   "on %s!\n", QETH_CARD_IFNAME(card));
+-		return -EOPNOTSUPP;
+-	}
+-	rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+-					  IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
+-	if (rc){
+-		tmp = rc;
+-		PRINT_WARN("Could not flush ARP cache on %s: %s (0x%x/%d)\n",
+-			   QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
+-			   tmp, tmp);
+-	}
+-	return rc;
+-}
+-
+-static int
+-qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+-{
+-	struct qeth_card *card = (struct qeth_card *)dev->priv;
+-	struct qeth_arp_cache_entry arp_entry;
+-	struct mii_ioctl_data *mii_data;
+-	int rc = 0;
+-
+-	if (!card)
+-		return -ENODEV;
+-
+-	if ((card->state != CARD_STATE_UP) &&
+-            (card->state != CARD_STATE_SOFTSETUP))
+-		return -ENODEV;
+-
+-	if (card->info.type == QETH_CARD_TYPE_OSN)
+-		return -EPERM;
+-
+-	switch (cmd){
+-	case SIOC_QETH_ARP_SET_NO_ENTRIES:
+-		if ( !capable(CAP_NET_ADMIN) ||
+-		     (card->options.layer2) ) {
+-			rc = -EPERM;
+-			break;
+-		}
+-		rc = qeth_arp_set_no_entries(card, rq->ifr_ifru.ifru_ivalue);
+-		break;
+-	case SIOC_QETH_ARP_QUERY_INFO:
+-		if ( !capable(CAP_NET_ADMIN) ||
+-		     (card->options.layer2) ) {
+-			rc = -EPERM;
+-			break;
+-		}
+-		rc = qeth_arp_query(card, rq->ifr_ifru.ifru_data);
+-		break;
+-	case SIOC_QETH_ARP_ADD_ENTRY:
+-		if ( !capable(CAP_NET_ADMIN) ||
+-		     (card->options.layer2) ) {
+-			rc = -EPERM;
+-			break;
+-		}
+-		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
+-				   sizeof(struct qeth_arp_cache_entry)))
+-			rc = -EFAULT;
+-		else
+-			rc = qeth_arp_add_entry(card, &arp_entry);
+-		break;
+-	case SIOC_QETH_ARP_REMOVE_ENTRY:
+-		if ( !capable(CAP_NET_ADMIN) ||
+-		     (card->options.layer2) ) {
+-			rc = -EPERM;
+-			break;
+-		}
+-		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
+-				   sizeof(struct qeth_arp_cache_entry)))
+-			rc = -EFAULT;
+-		else
+-			rc = qeth_arp_remove_entry(card, &arp_entry);
+-		break;
+-	case SIOC_QETH_ARP_FLUSH_CACHE:
+-		if ( !capable(CAP_NET_ADMIN) ||
+-		     (card->options.layer2) ) {
+-			rc = -EPERM;
+-			break;
+-		}
+-		rc = qeth_arp_flush_cache(card);
+-		break;
+-	case SIOC_QETH_ADP_SET_SNMP_CONTROL:
+-		rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
+-		break;
+-	case SIOC_QETH_GET_CARD_TYPE:
+-		if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
+-		    !card->info.guestlan)
+-			return 1;
+-		return 0;
+-		break;
+-	case SIOCGMIIPHY:
+-		mii_data = if_mii(rq);
+-		mii_data->phy_id = 0;
+-		break;
+-	case SIOCGMIIREG:
+-		mii_data = if_mii(rq);
+-		if (mii_data->phy_id != 0)
+-			rc = -EINVAL;
+-		else
+-			mii_data->val_out = qeth_mdio_read(dev,mii_data->phy_id,
+-							   mii_data->reg_num);
+-		break;
+-	default:
+-		rc = -EOPNOTSUPP;
+-	}
+-	if (rc)
+-		QETH_DBF_TEXT_(trace, 2, "ioce%d", rc);
+-	return rc;
+-}
+-
+-static struct net_device_stats *
+-qeth_get_stats(struct net_device *dev)
+-{
+-	struct qeth_card *card;
+-
+-	card = (struct qeth_card *) (dev->priv);
+-
+-	QETH_DBF_TEXT(trace,5,"getstat");
+-
+-	return &card->stats;
+-}
+-
+-static int
+-qeth_change_mtu(struct net_device *dev, int new_mtu)
+-{
+-	struct qeth_card *card;
+-	char dbf_text[15];
+-
+-	card = (struct qeth_card *) (dev->priv);
+-
+-	QETH_DBF_TEXT(trace,4,"chgmtu");
+-	sprintf(dbf_text, "%8x", new_mtu);
+-	QETH_DBF_TEXT(trace,4,dbf_text);
+-
+-	if (new_mtu < 64)
+-		return -EINVAL;
+-	if (new_mtu > 65535)
+-		return -EINVAL;
+-	if ((!qeth_is_supported(card,IPA_IP_FRAGMENTATION)) &&
+-	    (!qeth_mtu_is_valid(card, new_mtu)))
+-		return -EINVAL;
+-	dev->mtu = new_mtu;
+-	return 0;
+-}
+-
+-#ifdef CONFIG_QETH_VLAN
+-static void
+-qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+-{
+-	struct qeth_card *card;
+-	unsigned long flags;
+-
+-	QETH_DBF_TEXT(trace,4,"vlanreg");
+-
+-	card = (struct qeth_card *) dev->priv;
+-	spin_lock_irqsave(&card->vlanlock, flags);
+-	card->vlangrp = grp;
+-	spin_unlock_irqrestore(&card->vlanlock, flags);
+-}
+-
+-static void
+-qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf,
+-		      unsigned short vid)
+-{
+-	int i;
+-	struct sk_buff *skb;
+-	struct sk_buff_head tmp_list;
+-
+-	skb_queue_head_init(&tmp_list);
+-	lockdep_set_class(&tmp_list.lock, &qdio_out_skb_queue_key);
+-	for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i){
+-		while ((skb = skb_dequeue(&buf->skb_list))){
+-			if (vlan_tx_tag_present(skb) &&
+-			    (vlan_tx_tag_get(skb) == vid)) {
+-				atomic_dec(&skb->users);
+-				dev_kfree_skb(skb);
+-			} else
+-				skb_queue_tail(&tmp_list, skb);
+-		}
+-	}
+-	while ((skb = skb_dequeue(&tmp_list)))
+-		skb_queue_tail(&buf->skb_list, skb);
+-}
+-
+-static void
+-qeth_free_vlan_skbs(struct qeth_card *card, unsigned short vid)
+-{
+-	int i, j;
+-
+-	QETH_DBF_TEXT(trace, 4, "frvlskbs");
+-	for (i = 0; i < card->qdio.no_out_queues; ++i){
+-		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+-			qeth_free_vlan_buffer(card, &card->qdio.
+-					      out_qs[i]->bufs[j], vid);
+-	}
+-}
+-
+-static void
+-qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
+-{
+-	struct in_device *in_dev;
+-	struct in_ifaddr *ifa;
+-	struct qeth_ipaddr *addr;
+-
+-	QETH_DBF_TEXT(trace, 4, "frvaddr4");
+-
+-	rcu_read_lock();
+-	in_dev = __in_dev_get_rcu(vlan_group_get_device(card->vlangrp, vid));
+-	if (!in_dev)
+-		goto out;
+-	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
+-		addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
+-		if (addr){
+-			addr->u.a4.addr = ifa->ifa_address;
+-			addr->u.a4.mask = ifa->ifa_mask;
+-			addr->type = QETH_IP_TYPE_NORMAL;
+-			if (!qeth_delete_ip(card, addr))
+-				kfree(addr);
+-		}
+-	}
+-out:
+-	rcu_read_unlock();
+-}
+-
+-static void
+-qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
+-{
+-#ifdef CONFIG_QETH_IPV6
+-	struct inet6_dev *in6_dev;
+-	struct inet6_ifaddr *ifa;
+-	struct qeth_ipaddr *addr;
+-
+-	QETH_DBF_TEXT(trace, 4, "frvaddr6");
+-
+-	in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
+-	if (!in6_dev)
+-		return;
+-	for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next){
+-		addr = qeth_get_addr_buffer(QETH_PROT_IPV6);
+-		if (addr){
+-			memcpy(&addr->u.a6.addr, &ifa->addr,
+-			       sizeof(struct in6_addr));
+-			addr->u.a6.pfxlen = ifa->prefix_len;
+-			addr->type = QETH_IP_TYPE_NORMAL;
+-			if (!qeth_delete_ip(card, addr))
+-				kfree(addr);
+-		}
+-	}
+-	in6_dev_put(in6_dev);
+-#endif /* CONFIG_QETH_IPV6 */
+-}
+-
+-static void
+-qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid)
+-{
+-	if (card->options.layer2 || !card->vlangrp)
+-		return;
+-	qeth_free_vlan_addresses4(card, vid);
+-	qeth_free_vlan_addresses6(card, vid);
+-}
+-
+-static int
+-qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
+-                               struct qeth_reply *reply,
+-                               unsigned long data)
+-{
+-        struct qeth_ipa_cmd *cmd;
+-
+-        QETH_DBF_TEXT(trace, 2, "L2sdvcb");
+-        cmd = (struct qeth_ipa_cmd *) data;
+-        if (cmd->hdr.return_code) {
+-		PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
+-			  "Continuing\n",cmd->data.setdelvlan.vlan_id,
+-			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+-		QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
+-		QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
+-		QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+-	}
+-        return 0;
+-}
+-
+-static int
+-qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
+-			    enum qeth_ipa_cmds ipacmd)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT_(trace, 4, "L2sdv%x",ipacmd);
+-	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-        cmd->data.setdelvlan.vlan_id = i;
+-	return qeth_send_ipa_cmd(card, iob,
+-				 qeth_layer2_send_setdelvlan_cb, NULL);
+-}
+-
+-static void
+-qeth_layer2_process_vlans(struct qeth_card *card, int clear)
+-{
+-        unsigned short  i;
+-
+-	QETH_DBF_TEXT(trace, 3, "L2prcvln");
+-
+-	if (!card->vlangrp)
+-		return;
+-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+-		if (vlan_group_get_device(card->vlangrp, i) == NULL)
+-			continue;
+-		if (clear)
+-			qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN);
+-		else
+-			qeth_layer2_send_setdelvlan(card, i, IPA_CMD_SETVLAN);
+-        }
+-}
+-
+-/*add_vid is layer 2 used only ....*/
+-static void
+-qeth_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+-{
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT_(trace, 4, "aid:%d", vid);
+-
+-	card = (struct qeth_card *) dev->priv;
+-	if (!card->options.layer2)
+-		return;
+-	qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
+-}
+-
+-/*... kill_vid used for both modes*/
+-static void
+-qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+-{
+-	struct qeth_card *card;
+-	unsigned long flags;
+-
+-	QETH_DBF_TEXT_(trace, 4, "kid:%d", vid);
+-
+-	card = (struct qeth_card *) dev->priv;
+-	/* free all skbs for the vlan device */
+-	qeth_free_vlan_skbs(card, vid);
+-	spin_lock_irqsave(&card->vlanlock, flags);
+-	/* unregister IP addresses of vlan device */
+-	qeth_free_vlan_addresses(card, vid);
+-	vlan_group_set_device(card->vlangrp, vid, NULL);
+-	spin_unlock_irqrestore(&card->vlanlock, flags);
+-	if (card->options.layer2)
+-		qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
+-	qeth_set_multicast_list(card->dev);
+-}
+-#endif
+-/**
+- * Examine hardware response to SET_PROMISC_MODE
+- */
+-static int
+-qeth_setadp_promisc_mode_cb(struct qeth_card *card,
+-			    struct qeth_reply *reply,
+-			    unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-	struct qeth_ipacmd_setadpparms *setparms;
+-
+-	QETH_DBF_TEXT(trace,4,"prmadpcb");
+-
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	setparms = &(cmd->data.setadapterparms);
+-
+-        qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+-	if (cmd->hdr.return_code) {
+-		QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
+-		setparms->data.mode = SET_PROMISC_MODE_OFF;
+-	}
+-	card->info.promisc_mode = setparms->data.mode;
+-	return 0;
+-}
+-/*
+- * Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
+- */
+-static void
+-qeth_setadp_promisc_mode(struct qeth_card *card)
+-{
+-	enum qeth_ipa_promisc_modes mode;
+-	struct net_device *dev = card->dev;
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace, 4, "setprom");
+-
+-	if (((dev->flags & IFF_PROMISC) &&
+-	     (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
+-	    (!(dev->flags & IFF_PROMISC) &&
+-	     (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
+-		return;
+-	mode = SET_PROMISC_MODE_OFF;
+-	if (dev->flags & IFF_PROMISC)
+-		mode = SET_PROMISC_MODE_ON;
+-	QETH_DBF_TEXT_(trace, 4, "mode:%x", mode);
+-
+-	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
+-			sizeof(struct qeth_ipacmd_setadpparms));
+-	cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
+-	cmd->data.setadapterparms.data.mode = mode;
+-	qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
+-}
+-
+-/**
+- * set multicast address on card
+- */
+-static void
+-qeth_set_multicast_list(struct net_device *dev)
+-{
+-	struct qeth_card *card = (struct qeth_card *) dev->priv;
+-
+-	if (card->info.type == QETH_CARD_TYPE_OSN)
+-		return ;
+-
+-	QETH_DBF_TEXT(trace, 3, "setmulti");
+-	qeth_delete_mc_addresses(card);
+-	if (card->options.layer2) {
+-		qeth_layer2_add_multicast(card);
+-		goto out;
+-	}
+-	qeth_add_multicast_ipv4(card);
+-#ifdef CONFIG_QETH_IPV6
+-	qeth_add_multicast_ipv6(card);
+-#endif
+-out:
+-	qeth_set_ip_addr_list(card);
+-	if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
+-		return;
+-	qeth_setadp_promisc_mode(card);
+-}
+-
+-static int
+-qeth_neigh_setup(struct net_device *dev, struct neigh_parms *np)
+-{
+-	return 0;
+-}
+-
+-static void
+-qeth_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev)
+-{
+-	if (dev->type == ARPHRD_IEEE802_TR)
+-		ip_tr_mc_map(ipm, mac);
+-	else
+-		ip_eth_mc_map(ipm, mac);
+-}
+-
+-static struct qeth_ipaddr *
+-qeth_get_addr_buffer(enum qeth_prot_versions prot)
+-{
+-	struct qeth_ipaddr *addr;
+-
+-	addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC);
+-	if (addr == NULL) {
+-		PRINT_WARN("Not enough memory to add address\n");
+-		return NULL;
+-	}
+-	addr->type = QETH_IP_TYPE_NORMAL;
+-	addr->proto = prot;
+-	return addr;
+-}
+-
+-int
+-qeth_osn_assist(struct net_device *dev,
+-		void *data,
+-		int data_len)
+-{
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_card *card;
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace, 2, "osnsdmc");
+-	if (!dev)
+-		return -ENODEV;
+-	card = (struct qeth_card *)dev->priv;
+-	if (!card)
+-		return -ENODEV;
+-	if ((card->state != CARD_STATE_UP) &&
+-	    (card->state != CARD_STATE_SOFTSETUP))
+-		return -ENODEV;
+-	iob = qeth_wait_for_buffer(&card->write);
+-	memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
+-	rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
+-	return rc;
+-}
+-
+-static struct net_device *
+-qeth_netdev_by_devno(unsigned char *read_dev_no)
+-{
+-	struct qeth_card *card;
+-	struct net_device *ndev;
+-	unsigned char *readno;
+-	__u16 temp_dev_no, card_dev_no;
+-	char *endp;
+-	unsigned long flags;
+-
+-	ndev = NULL;
+-	memcpy(&temp_dev_no, read_dev_no, 2);
+-	read_lock_irqsave(&qeth_card_list.rwlock, flags);
+-	list_for_each_entry(card, &qeth_card_list.list, list) {
+-		readno = CARD_RDEV_ID(card);
+-		readno += (strlen(readno) - 4);
+-		card_dev_no = simple_strtoul(readno, &endp, 16);
+-		if (card_dev_no == temp_dev_no) {
+-			ndev = card->dev;
+-			break;
+-		}
+-	}
+-	read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+-	return ndev;
+-}
+-
+-int
+-qeth_osn_register(unsigned char *read_dev_no,
+-		  struct net_device **dev,
+-		  int (*assist_cb)(struct net_device *, void *),
+-		  int (*data_cb)(struct sk_buff *))
+-{
+-	struct qeth_card * card;
+-
+-	QETH_DBF_TEXT(trace, 2, "osnreg");
+-	*dev = qeth_netdev_by_devno(read_dev_no);
+-	if (*dev == NULL)
+-		return -ENODEV;
+-	card = (struct qeth_card *)(*dev)->priv;
+-	if (!card)
+-		return -ENODEV;
+-	if ((assist_cb == NULL) || (data_cb == NULL))
+-		return -EINVAL;
+-	card->osn_info.assist_cb = assist_cb;
+-	card->osn_info.data_cb = data_cb;
+-	return 0;
+-}
+-
+-void
+-qeth_osn_deregister(struct net_device * dev)
+-{
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(trace, 2, "osndereg");
+-	if (!dev)
+-		return;
+-	card = (struct qeth_card *)dev->priv;
+-	if (!card)
+-		return;
+-	card->osn_info.assist_cb = NULL;
+-	card->osn_info.data_cb = NULL;
+-	return;
+-}
+-
+-static void
+-qeth_delete_mc_addresses(struct qeth_card *card)
+-{
+-	struct qeth_ipaddr *iptodo;
+-	unsigned long flags;
+-
+-	QETH_DBF_TEXT(trace,4,"delmc");
+-	iptodo = qeth_get_addr_buffer(QETH_PROT_IPV4);
+-	if (!iptodo) {
+-		QETH_DBF_TEXT(trace, 2, "dmcnomem");
+-		return;
+-	}
+-	iptodo->type = QETH_IP_TYPE_DEL_ALL_MC;
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	if (!__qeth_insert_ip_todo(card, iptodo, 0))
+-		kfree(iptodo);
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-}
+-
+-static void
+-qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev)
+-{
+-	struct qeth_ipaddr *ipm;
+-	struct ip_mc_list *im4;
+-	char buf[MAX_ADDR_LEN];
+-
+-	QETH_DBF_TEXT(trace,4,"addmc");
+-	for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
+-		qeth_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev);
+-		ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
+-		if (!ipm)
+-			continue;
+-		ipm->u.a4.addr = im4->multiaddr;
+-		memcpy(ipm->mac,buf,OSA_ADDR_LEN);
+-		ipm->is_multicast = 1;
+-		if (!qeth_add_ip(card,ipm))
+-			kfree(ipm);
+-	}
+-}
+-
+-static inline void
+-qeth_add_vlan_mc(struct qeth_card *card)
+-{
+-#ifdef CONFIG_QETH_VLAN
+-	struct in_device *in_dev;
+-	struct vlan_group *vg;
+-	int i;
+-
+-	QETH_DBF_TEXT(trace,4,"addmcvl");
+-	if ( ((card->options.layer2 == 0) &&
+-	      (!qeth_is_supported(card,IPA_FULL_VLAN))) ||
+-	     (card->vlangrp == NULL) )
+-		return ;
+-
+-	vg = card->vlangrp;
+-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+-		struct net_device *netdev = vlan_group_get_device(vg, i);
+-		if (netdev == NULL ||
+-		    !(netdev->flags & IFF_UP))
+-			continue;
+-		in_dev = in_dev_get(netdev);
+-		if (!in_dev)
+-			continue;
+-		read_lock(&in_dev->mc_list_lock);
+-		qeth_add_mc(card,in_dev);
+-		read_unlock(&in_dev->mc_list_lock);
+-		in_dev_put(in_dev);
+-	}
+-#endif
+-}
+-
+-static void
+-qeth_add_multicast_ipv4(struct qeth_card *card)
+-{
+-	struct in_device *in4_dev;
+-
+-	QETH_DBF_TEXT(trace,4,"chkmcv4");
+-	in4_dev = in_dev_get(card->dev);
+-	if (in4_dev == NULL)
+-		return;
+-	read_lock(&in4_dev->mc_list_lock);
+-	qeth_add_mc(card, in4_dev);
+-	qeth_add_vlan_mc(card);
+-	read_unlock(&in4_dev->mc_list_lock);
+-	in_dev_put(in4_dev);
+-}
+-
+-static void
+-qeth_layer2_add_multicast(struct qeth_card *card)
+-{
+-	struct qeth_ipaddr *ipm;
+-	struct dev_mc_list *dm;
+-
+-	QETH_DBF_TEXT(trace,4,"L2addmc");
+-	for (dm = card->dev->mc_list; dm; dm = dm->next) {
+-		ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
+-		if (!ipm)
+-			continue;
+-		memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN);
+-		ipm->is_multicast = 1;
+-		if (!qeth_add_ip(card, ipm))
+-			kfree(ipm);
+-	}
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static void
+-qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
+-{
+-	struct qeth_ipaddr *ipm;
+-	struct ifmcaddr6 *im6;
+-	char buf[MAX_ADDR_LEN];
+-
+-	QETH_DBF_TEXT(trace,4,"addmc6");
+-	for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
+-		ndisc_mc_map(&im6->mca_addr, buf, in6_dev->dev, 0);
+-		ipm = qeth_get_addr_buffer(QETH_PROT_IPV6);
+-		if (!ipm)
+-			continue;
+-		ipm->is_multicast = 1;
+-		memcpy(ipm->mac,buf,OSA_ADDR_LEN);
+-		memcpy(&ipm->u.a6.addr,&im6->mca_addr.s6_addr,
+-		       sizeof(struct in6_addr));
+-		if (!qeth_add_ip(card,ipm))
+-			kfree(ipm);
+-	}
+-}
+-
+-static inline void
+-qeth_add_vlan_mc6(struct qeth_card *card)
+-{
+-#ifdef CONFIG_QETH_VLAN
+-	struct inet6_dev *in_dev;
+-	struct vlan_group *vg;
+-	int i;
+-
+-	QETH_DBF_TEXT(trace,4,"admc6vl");
+-	if ( ((card->options.layer2 == 0) &&
+-	      (!qeth_is_supported(card,IPA_FULL_VLAN))) ||
+-	     (card->vlangrp == NULL))
+-		return ;
+-
+-	vg = card->vlangrp;
+-	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+-		struct net_device *netdev = vlan_group_get_device(vg, i);
+-		if (netdev == NULL ||
+-		    !(netdev->flags & IFF_UP))
+-			continue;
+-		in_dev = in6_dev_get(netdev);
+-		if (!in_dev)
+-			continue;
+-		read_lock_bh(&in_dev->lock);
+-		qeth_add_mc6(card,in_dev);
+-		read_unlock_bh(&in_dev->lock);
+-		in6_dev_put(in_dev);
+-	}
+-#endif /* CONFIG_QETH_VLAN */
+-}
+-
+-static void
+-qeth_add_multicast_ipv6(struct qeth_card *card)
+-{
+-	struct inet6_dev *in6_dev;
+-
+-	QETH_DBF_TEXT(trace,4,"chkmcv6");
+-	if (!qeth_is_supported(card, IPA_IPV6))
+-		return ;
+-	in6_dev = in6_dev_get(card->dev);
+-	if (in6_dev == NULL)
+-		return;
+-	read_lock_bh(&in6_dev->lock);
+-	qeth_add_mc6(card, in6_dev);
+-	qeth_add_vlan_mc6(card);
+-	read_unlock_bh(&in6_dev->lock);
+-	in6_dev_put(in6_dev);
+-}
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static int
+-qeth_layer2_send_setdelmac(struct qeth_card *card, __u8 *mac,
+-			   enum qeth_ipa_cmds ipacmd,
+-			   int (*reply_cb) (struct qeth_card *,
+-					    struct qeth_reply*,
+-					    unsigned long))
+-{
+-	struct qeth_ipa_cmd *cmd;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(trace, 2, "L2sdmac");
+-	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-        cmd->data.setdelmac.mac_length = OSA_ADDR_LEN;
+-        memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN);
+-	return qeth_send_ipa_cmd(card, iob, reply_cb, NULL);
+-}
+-
+-static int
+-qeth_layer2_send_setgroupmac_cb(struct qeth_card *card,
+-				struct qeth_reply *reply,
+-				unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-	__u8 *mac;
+-
+-	QETH_DBF_TEXT(trace, 2, "L2Sgmacb");
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	mac = &cmd->data.setdelmac.mac[0];
+-	/* MAC already registered, needed in couple/uncouple case */
+-	if (cmd->hdr.return_code == 0x2005) {
+-		PRINT_WARN("Group MAC %02x:%02x:%02x:%02x:%02x:%02x " \
+-			  "already existing on %s \n",
+-			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+-			  QETH_CARD_IFNAME(card));
+-		cmd->hdr.return_code = 0;
+-	}
+-	if (cmd->hdr.return_code)
+-		PRINT_ERR("Could not set group MAC " \
+-			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
+-			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+-			  QETH_CARD_IFNAME(card),cmd->hdr.return_code);
+-	return 0;
+-}
+-
+-static int
+-qeth_layer2_send_setgroupmac(struct qeth_card *card, __u8 *mac)
+-{
+-	QETH_DBF_TEXT(trace, 2, "L2Sgmac");
+-	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_SETGMAC,
+-					  qeth_layer2_send_setgroupmac_cb);
+-}
+-
+-static int
+-qeth_layer2_send_delgroupmac_cb(struct qeth_card *card,
+-				struct qeth_reply *reply,
+-				unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-	__u8 *mac;
+-
+-	QETH_DBF_TEXT(trace, 2, "L2Dgmacb");
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	mac = &cmd->data.setdelmac.mac[0];
+-	if (cmd->hdr.return_code)
+-		PRINT_ERR("Could not delete group MAC " \
+-			  "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
+-			  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+-			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+-	return 0;
+-}
+-
+-static int
+-qeth_layer2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
+-{
+-	QETH_DBF_TEXT(trace, 2, "L2Dgmac");
+-	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELGMAC,
+-					  qeth_layer2_send_delgroupmac_cb);
+-}
+-
+-static int
+-qeth_layer2_send_setmac_cb(struct qeth_card *card,
+-			   struct qeth_reply *reply,
+-			   unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace, 2, "L2Smaccb");
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	if (cmd->hdr.return_code) {
+-		QETH_DBF_TEXT_(trace, 2, "L2er%x", cmd->hdr.return_code);
+-		card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
+-		cmd->hdr.return_code = -EIO;
+-	} else {
+-		card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
+-		memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac,
+-		       OSA_ADDR_LEN);
+-		PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
+-			   "successfully registered on device %s\n",
+-			   card->dev->dev_addr[0], card->dev->dev_addr[1],
+-			   card->dev->dev_addr[2], card->dev->dev_addr[3],
+-			   card->dev->dev_addr[4], card->dev->dev_addr[5],
+-			   card->dev->name);
+-	}
+-	return 0;
+-}
+-
+-static int
+-qeth_layer2_send_setmac(struct qeth_card *card, __u8 *mac)
+-{
+-	QETH_DBF_TEXT(trace, 2, "L2Setmac");
+-	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_SETVMAC,
+-					  qeth_layer2_send_setmac_cb);
+-}
+-
+-static int
+-qeth_layer2_send_delmac_cb(struct qeth_card *card,
+-			   struct qeth_reply *reply,
+-			   unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace, 2, "L2Dmaccb");
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	if (cmd->hdr.return_code) {
+-		QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+-		cmd->hdr.return_code = -EIO;
+-		return 0;
+-	}
+-	card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
+-
+-	return 0;
+-}
+-static int
+-qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac)
+-{
+-	QETH_DBF_TEXT(trace, 2, "L2Delmac");
+-	if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
+-		return 0;
+-	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
+-					  qeth_layer2_send_delmac_cb);
+-}
+-
+-static int
+-qeth_layer2_set_mac_address(struct net_device *dev, void *p)
+-{
+-	struct sockaddr *addr = p;
+-	struct qeth_card *card;
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace, 3, "setmac");
+-
+-	if (qeth_verify_dev(dev) != QETH_REAL_CARD) {
+-		QETH_DBF_TEXT(trace, 3, "setmcINV");
+-		return -EOPNOTSUPP;
+-	}
+-	card = (struct qeth_card *) dev->priv;
+-
+-	if (!card->options.layer2) {
+-		PRINT_WARN("Setting MAC address on %s is not supported "
+-			   "in Layer 3 mode.\n", dev->name);
+-		QETH_DBF_TEXT(trace, 3, "setmcLY3");
+-		return -EOPNOTSUPP;
+-	}
+-	if (card->info.type == QETH_CARD_TYPE_OSN) {
+-		PRINT_WARN("Setting MAC address on %s is not supported.\n",
+-			   dev->name);
+-		QETH_DBF_TEXT(trace, 3, "setmcOSN");
+-		return -EOPNOTSUPP;
+-	}
+-	QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card));
+-	QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN);
+-	rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]);
+-	if (!rc)
+-		rc = qeth_layer2_send_setmac(card, addr->sa_data);
+-	return rc;
+-}
+-
+-static void
+-qeth_fill_ipacmd_header(struct qeth_card *card, struct qeth_ipa_cmd *cmd,
+-			__u8 command, enum qeth_prot_versions prot)
+-{
+-	memset(cmd, 0, sizeof (struct qeth_ipa_cmd));
+-	cmd->hdr.command = command;
+-	cmd->hdr.initiator = IPA_CMD_INITIATOR_HOST;
+-	cmd->hdr.seqno = card->seqno.ipa;
+-	cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type);
+-	cmd->hdr.rel_adapter_no = (__u8) card->info.portno;
+-	if (card->options.layer2)
+-		cmd->hdr.prim_version_no = 2;
+-	else
+-		cmd->hdr.prim_version_no = 1;
+-	cmd->hdr.param_count = 1;
+-	cmd->hdr.prot_version = prot;
+-	cmd->hdr.ipa_supported = 0;
+-	cmd->hdr.ipa_enabled = 0;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_ipacmd_buffer(struct qeth_card *card, enum qeth_ipa_cmds ipacmd,
+-		       enum qeth_prot_versions prot)
+-{
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	iob = qeth_wait_for_buffer(&card->write);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	qeth_fill_ipacmd_header(card, cmd, ipacmd, prot);
+-
+-	return iob;
+-}
+-
+-static int
+-qeth_send_setdelmc(struct qeth_card *card, struct qeth_ipaddr *addr, int ipacmd)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,4,"setdelmc");
+-
+-	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	memcpy(&cmd->data.setdelipm.mac,addr->mac, OSA_ADDR_LEN);
+-	if (addr->proto == QETH_PROT_IPV6)
+-		memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr,
+-		       sizeof(struct in6_addr));
+-	else
+-		memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr,4);
+-
+-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-
+-	return rc;
+-}
+-static void
+-qeth_fill_netmask(u8 *netmask, unsigned int len)
+-{
+-	int i,j;
+-	for (i=0;i<16;i++) {
+-		j=(len)-(i*8);
+-		if (j >= 8)
+-			netmask[i] = 0xff;
+-		else if (j > 0)
+-			netmask[i] = (u8)(0xFF00>>j);
+-		else
+-			netmask[i] = 0;
+-	}
+-}
+-
+-static int
+-qeth_send_setdelip(struct qeth_card *card, struct qeth_ipaddr *addr,
+-		   int ipacmd, unsigned int flags)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-	__u8 netmask[16];
+-
+-	QETH_DBF_TEXT(trace,4,"setdelip");
+-	QETH_DBF_TEXT_(trace,4,"flags%02X", flags);
+-
+-	iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	if (addr->proto == QETH_PROT_IPV6) {
+-		memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr,
+-		       sizeof(struct in6_addr));
+-		qeth_fill_netmask(netmask,addr->u.a6.pfxlen);
+-		memcpy(cmd->data.setdelip6.mask, netmask,
+-		       sizeof(struct in6_addr));
+-		cmd->data.setdelip6.flags = flags;
+-	} else {
+-		memcpy(cmd->data.setdelip4.ip_addr, &addr->u.a4.addr, 4);
+-		memcpy(cmd->data.setdelip4.mask, &addr->u.a4.mask, 4);
+-		cmd->data.setdelip4.flags = flags;
+-	}
+-
+-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-
+-	return rc;
+-}
+-
+-static int
+-qeth_layer2_register_addr_entry(struct qeth_card *card,
+-				struct qeth_ipaddr *addr)
+-{
+-	if (!addr->is_multicast)
+-		return 0;
+-	QETH_DBF_TEXT(trace, 2, "setgmac");
+-	QETH_DBF_HEX(trace,3,&addr->mac[0],OSA_ADDR_LEN);
+-	return qeth_layer2_send_setgroupmac(card, &addr->mac[0]);
+-}
+-
+-static int
+-qeth_layer2_deregister_addr_entry(struct qeth_card *card,
+-				  struct qeth_ipaddr *addr)
+-{
+-	if (!addr->is_multicast)
+-		return 0;
+-	QETH_DBF_TEXT(trace, 2, "delgmac");
+-	QETH_DBF_HEX(trace,3,&addr->mac[0],OSA_ADDR_LEN);
+-	return qeth_layer2_send_delgroupmac(card, &addr->mac[0]);
+-}
+-
+-static int
+-qeth_layer3_register_addr_entry(struct qeth_card *card,
+-				struct qeth_ipaddr *addr)
+-{
+-	char buf[50];
+-	int rc;
+-	int cnt = 3;
+-
+-	if (addr->proto == QETH_PROT_IPV4) {
+-		QETH_DBF_TEXT(trace, 2,"setaddr4");
+-		QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
+-	} else if (addr->proto == QETH_PROT_IPV6) {
+-		QETH_DBF_TEXT(trace, 2, "setaddr6");
+-		QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8);
+-		QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8);
+-	} else {
+-		QETH_DBF_TEXT(trace, 2, "setaddr?");
+-		QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
+-	}
+-	do {
+-		if (addr->is_multicast)
+-			rc =  qeth_send_setdelmc(card, addr, IPA_CMD_SETIPM);
+-		else
+-			rc = qeth_send_setdelip(card, addr, IPA_CMD_SETIP,
+-					addr->set_flags);
+-		if (rc)
+-			QETH_DBF_TEXT(trace, 2, "failed");
+-	} while ((--cnt > 0) && rc);
+-	if (rc){
+-		QETH_DBF_TEXT(trace, 2, "FAILED");
+-		qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
+-		PRINT_WARN("Could not register IP address %s (rc=0x%x/%d)\n",
+-			   buf, rc, rc);
+-	}
+-	return rc;
+-}
+-
+-static int
+-qeth_layer3_deregister_addr_entry(struct qeth_card *card,
+-				  struct qeth_ipaddr *addr)
+-{
+-	//char buf[50];
+-	int rc;
+-
+-	if (addr->proto == QETH_PROT_IPV4) {
+-		QETH_DBF_TEXT(trace, 2,"deladdr4");
+-		QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
+-	} else if (addr->proto == QETH_PROT_IPV6) {
+-		QETH_DBF_TEXT(trace, 2, "deladdr6");
+-		QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8);
+-		QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8);
+-	} else {
+-		QETH_DBF_TEXT(trace, 2, "deladdr?");
+-		QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
+-	}
+-	if (addr->is_multicast)
+-		rc = qeth_send_setdelmc(card, addr, IPA_CMD_DELIPM);
+-	else
+-		rc = qeth_send_setdelip(card, addr, IPA_CMD_DELIP,
+-					addr->del_flags);
+-	if (rc) {
+-		QETH_DBF_TEXT(trace, 2, "failed");
+-		/* TODO: re-activate this warning as soon as we have a
+-		 * clean mirco code
+-		qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
+-		PRINT_WARN("Could not deregister IP address %s (rc=%x)\n",
+-			   buf, rc);
+-		*/
+-	}
+-	return rc;
+-}
+-
+-static int
+-qeth_register_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+-	if (card->options.layer2)
+-		return qeth_layer2_register_addr_entry(card, addr);
+-
+-	return qeth_layer3_register_addr_entry(card, addr);
+-}
+-
+-static int
+-qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+-	if (card->options.layer2)
+-		return qeth_layer2_deregister_addr_entry(card, addr);
+-
+-	return qeth_layer3_deregister_addr_entry(card, addr);
+-}
+-
+-static u32
+-qeth_ethtool_get_tx_csum(struct net_device *dev)
+-{
+-	return (dev->features & NETIF_F_HW_CSUM) != 0;
+-}
+-
+-static int
+-qeth_ethtool_set_tx_csum(struct net_device *dev, u32 data)
+-{
+-	if (data)
+-		dev->features |= NETIF_F_HW_CSUM;
+-	else
+-		dev->features &= ~NETIF_F_HW_CSUM;
+-
+-	return 0;
+-}
+-
+-static u32
+-qeth_ethtool_get_rx_csum(struct net_device *dev)
+-{
+-	struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+-	return (card->options.checksum_type == HW_CHECKSUMMING);
+-}
+-
+-static int
+-qeth_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+-{
+-	struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-	if (data)
+-		card->options.checksum_type = HW_CHECKSUMMING;
+-	else
+-		card->options.checksum_type = SW_CHECKSUMMING;
+-	return 0;
+-}
+-
+-static u32
+-qeth_ethtool_get_sg(struct net_device *dev)
+-{
+-	struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+-	return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
+-		(dev->features & NETIF_F_SG));
+-}
+-
+-static int
+-qeth_ethtool_set_sg(struct net_device *dev, u32 data)
+-{
+-	struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+-	if (data) {
+-		if (card->options.large_send != QETH_LARGE_SEND_NO)
+-			dev->features |= NETIF_F_SG;
+-		else {
+-			dev->features &= ~NETIF_F_SG;
+-			return -EINVAL;
+-		}
+-	} else
+-		dev->features &= ~NETIF_F_SG;
+-	return 0;
+-}
+-
+-static u32
+-qeth_ethtool_get_tso(struct net_device *dev)
+-{
+-	struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+-	return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
+-		(dev->features & NETIF_F_TSO));
+-}
+-
+-static int
+-qeth_ethtool_set_tso(struct net_device *dev, u32 data)
+-{
+-	struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+-	if (data) {
+-		if (card->options.large_send != QETH_LARGE_SEND_NO)
+-			dev->features |= NETIF_F_TSO;
+-		else {
+-			dev->features &= ~NETIF_F_TSO;
+-			return -EINVAL;
+-		}
+-	} else
+-		dev->features &= ~NETIF_F_TSO;
+-	return 0;
+-}
+-
+-static struct ethtool_ops qeth_ethtool_ops = {
+-	.get_tx_csum = qeth_ethtool_get_tx_csum,
+-	.set_tx_csum = qeth_ethtool_set_tx_csum,
+-	.get_rx_csum = qeth_ethtool_get_rx_csum,
+-	.set_rx_csum = qeth_ethtool_set_rx_csum,
+-	.get_sg      = qeth_ethtool_get_sg,
+-	.set_sg      = qeth_ethtool_set_sg,
+-	.get_tso     = qeth_ethtool_get_tso,
+-	.set_tso     = qeth_ethtool_set_tso,
+-};
+-
+-static int
+-qeth_hard_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+-{
+-	const struct qeth_card *card;
+-	const struct ethhdr *eth;
+-	struct net_device *dev = skb->dev;
+-
+-	if (dev->type != ARPHRD_IEEE802_TR)
+-		return 0;
+-
+-	card = qeth_get_card_from_dev(dev);
+-	if (card->options.layer2)
+-		goto haveheader;
+-#ifdef CONFIG_QETH_IPV6
+-	/* cause of the manipulated arp constructor and the ARP
+-	   flag for OSAE devices we have some nasty exceptions */
+-	if (card->info.type == QETH_CARD_TYPE_OSAE) {
+-		if (!card->options.fake_ll) {
+-			if ((skb->pkt_type==PACKET_OUTGOING) &&
+-			    (skb->protocol==ETH_P_IPV6))
+-				goto haveheader;
+-			else
+-				return 0;
+-		} else {
+-			if ((skb->pkt_type==PACKET_OUTGOING) &&
+-			    (skb->protocol==ETH_P_IP))
+-				return 0;
+-			else
+-				goto haveheader;
+-		}
+-	}
+-#endif
+-	if (!card->options.fake_ll)
+-		return 0;
+-haveheader:
+-	eth = eth_hdr(skb);
+-	memcpy(haddr, eth->h_source, ETH_ALEN);
+-	return ETH_ALEN;
+-}
+-
+-static const struct header_ops qeth_null_ops = {
+-	.parse = qeth_hard_header_parse,
+-};
+-
+-static int
+-qeth_netdev_init(struct net_device *dev)
+-{
+-	struct qeth_card *card;
+-
+-	card = (struct qeth_card *) dev->priv;
+-
+-	QETH_DBF_TEXT(trace,3,"initdev");
+-
+-	dev->tx_timeout = &qeth_tx_timeout;
+-	dev->watchdog_timeo = QETH_TX_TIMEOUT;
+-	dev->open = qeth_open;
+-	dev->stop = qeth_stop;
+-	dev->hard_start_xmit = qeth_hard_start_xmit;
+-	dev->do_ioctl = qeth_do_ioctl;
+-	dev->get_stats = qeth_get_stats;
+-	dev->change_mtu = qeth_change_mtu;
+-	dev->neigh_setup = qeth_neigh_setup;
+-	dev->set_multicast_list = qeth_set_multicast_list;
+-#ifdef CONFIG_QETH_VLAN
+-	dev->vlan_rx_register = qeth_vlan_rx_register;
+-	dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
+-	dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
+-#endif
+-	if (qeth_get_netdev_flags(card) & IFF_NOARP)
+-		dev->header_ops = &qeth_null_ops;
+-
+-#ifdef CONFIG_QETH_IPV6
+-	/*IPv6 address autoconfiguration stuff*/
+-	if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
+-		card->dev->dev_id = card->info.unique_id & 0xffff;
+-#endif
+-	if (card->options.fake_ll &&
+-		(qeth_get_netdev_flags(card) & IFF_NOARP))
+-			dev->header_ops = &qeth_fake_ops;
+-
+-	dev->set_mac_address = qeth_layer2_set_mac_address;
+-	dev->flags |= qeth_get_netdev_flags(card);
+-	if ((card->options.fake_broadcast) ||
+-	    (card->info.broadcast_capable))
+-		dev->flags |= IFF_BROADCAST;
+-	dev->hard_header_len =
+-			qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
+-	dev->addr_len = OSA_ADDR_LEN;
+-	dev->mtu = card->info.initial_mtu;
+-	if (card->info.type != QETH_CARD_TYPE_OSN)
+-		SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
+-	return 0;
+-}
+-
+-static void
+-qeth_init_func_level(struct qeth_card *card)
+-{
+-	if (card->ipato.enabled) {
+-		if (card->info.type == QETH_CARD_TYPE_IQD)
+-				card->info.func_level =
+-					QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
+-		else
+-				card->info.func_level =
+-					QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
+-	} else {
+-		if (card->info.type == QETH_CARD_TYPE_IQD)
+-		/*FIXME:why do we have same values for  dis and ena for osae??? */
+-			card->info.func_level =
+-				QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
+-		else
+-			card->info.func_level =
+-				QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT;
+-	}
+-}
+-
+-/**
+- * hardsetup card, initialize MPC and QDIO stuff
+- */
+-static int
+-qeth_hardsetup_card(struct qeth_card *card)
+-{
+-	int retries = 3;
+-	int rc;
+-
+-	QETH_DBF_TEXT(setup, 2, "hrdsetup");
+-
+-	atomic_set(&card->force_alloc_skb, 0);
+-retry:
+-	if (retries < 3){
+-		PRINT_WARN("Retrying to do IDX activates.\n");
+-		ccw_device_set_offline(CARD_DDEV(card));
+-		ccw_device_set_offline(CARD_WDEV(card));
+-		ccw_device_set_offline(CARD_RDEV(card));
+-		ccw_device_set_online(CARD_RDEV(card));
+-		ccw_device_set_online(CARD_WDEV(card));
+-		ccw_device_set_online(CARD_DDEV(card));
+-	}
+-	rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD);
+-	if (rc == -ERESTARTSYS) {
+-		QETH_DBF_TEXT(setup, 2, "break1");
+-		return rc;
+-	} else if (rc) {
+-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+-		if (--retries < 0)
+-			goto out;
+-		else
+-			goto retry;
+-	}
+-	if ((rc = qeth_get_unitaddr(card))){
+-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+-		return rc;
+-	}
+-	qeth_init_tokens(card);
+-	qeth_init_func_level(card);
+-	rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb);
+-	if (rc == -ERESTARTSYS) {
+-		QETH_DBF_TEXT(setup, 2, "break2");
+-		return rc;
+-	} else if (rc) {
+-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+-		if (--retries < 0)
+-			goto out;
+-		else
+-			goto retry;
+-	}
+-	rc = qeth_idx_activate_channel(&card->write, qeth_idx_write_cb);
+-	if (rc == -ERESTARTSYS) {
+-		QETH_DBF_TEXT(setup, 2, "break3");
+-		return rc;
+-	} else if (rc) {
+-		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+-		if (--retries < 0)
+-			goto out;
+-		else
+-			goto retry;
+-	}
+-	if ((rc = qeth_mpc_initialize(card))){
+-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+-		goto out;
+-	}
+-	/*network device will be recovered*/
+-	if (card->dev) {
+-		card->dev->header_ops = card->orig_header_ops;
+-		if (card->options.fake_ll &&
+-		    (qeth_get_netdev_flags(card) & IFF_NOARP))
+-			card->dev->header_ops = &qeth_fake_ops;
+-		return 0;
+-	}
+-	/* at first set_online allocate netdev */
+-	card->dev = qeth_get_netdevice(card->info.type,
+-				       card->info.link_type);
+-	if (!card->dev){
+-		qeth_qdio_clear_card(card, card->info.type !=
+-				     QETH_CARD_TYPE_IQD);
+-		rc = -ENODEV;
+-		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+-		goto out;
+-	}
+-	card->dev->priv = card;
+-	card->orig_header_ops = card->dev->header_ops;
+-	card->dev->type = qeth_get_arphdr_type(card->info.type,
+-					       card->info.link_type);
+-	card->dev->init = qeth_netdev_init;
+-	return 0;
+-out:
+-	PRINT_ERR("Initialization in hardsetup failed! rc=%d\n", rc);
+-	return rc;
+-}
+-
+-static int
+-qeth_default_setassparms_cb(struct qeth_card *card, struct qeth_reply *reply,
+-			    unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,4,"defadpcb");
+-
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	if (cmd->hdr.return_code == 0){
+-		cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
+-		if (cmd->hdr.prot_version == QETH_PROT_IPV4)
+-			card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+-#ifdef CONFIG_QETH_IPV6
+-		if (cmd->hdr.prot_version == QETH_PROT_IPV6)
+-			card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
+-#endif
+-	}
+-	if (cmd->data.setassparms.hdr.assist_no == IPA_INBOUND_CHECKSUM &&
+-	    cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
+-		card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
+-		QETH_DBF_TEXT_(trace, 3, "csum:%d", card->info.csum_mask);
+-	}
+-	return 0;
+-}
+-
+-static int
+-qeth_default_setadapterparms_cb(struct qeth_card *card,
+-				struct qeth_reply *reply,
+-				unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,4,"defadpcb");
+-
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	if (cmd->hdr.return_code == 0)
+-		cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code;
+-	return 0;
+-}
+-
+-
+-
+-static int
+-qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
+-			      unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,3,"quyadpcb");
+-
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f)
+-		card->info.link_type =
+-		      cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
+-	card->options.adp.supported_funcs =
+-		cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
+-	return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+-}
+-
+-static int
+-qeth_query_setadapterparms(struct qeth_card *card)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(trace,3,"queryadp");
+-	iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_COMMANDS_SUPPORTED,
+-				   sizeof(struct qeth_ipacmd_setadpparms));
+-	rc = qeth_send_ipa_cmd(card, iob, qeth_query_setadapterparms_cb, NULL);
+-	return rc;
+-}
+-
+-static int
+-qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
+-				   struct qeth_reply *reply,
+-				   unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,4,"chgmaccb");
+-
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	if (!card->options.layer2 ||
+-	    !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
+-		memcpy(card->dev->dev_addr,
+-		       &cmd->data.setadapterparms.data.change_addr.addr,
+-		       OSA_ADDR_LEN);
+-		card->info.mac_bits |= QETH_LAYER2_MAC_READ;
+-	}
+-	qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
+-	return 0;
+-}
+-
+-static int
+-qeth_setadpparms_change_macaddr(struct qeth_card *card)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,4,"chgmac");
+-
+-	iob = qeth_get_adapter_cmd(card,IPA_SETADP_ALTER_MAC_ADDRESS,
+-				   sizeof(struct qeth_ipacmd_setadpparms));
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	cmd->data.setadapterparms.data.change_addr.cmd = CHANGE_ADDR_READ_MAC;
+-	cmd->data.setadapterparms.data.change_addr.addr_size = OSA_ADDR_LEN;
+-	memcpy(&cmd->data.setadapterparms.data.change_addr.addr,
+-	       card->dev->dev_addr, OSA_ADDR_LEN);
+-	rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_change_macaddr_cb,
+-			       NULL);
+-	return rc;
+-}
+-
+-static int
+-qeth_send_setadp_mode(struct qeth_card *card, __u32 command, __u32 mode)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,4,"adpmode");
+-
+-	iob = qeth_get_adapter_cmd(card, command,
+-				   sizeof(struct qeth_ipacmd_setadpparms));
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	cmd->data.setadapterparms.data.mode = mode;
+-	rc = qeth_send_ipa_cmd(card, iob, qeth_default_setadapterparms_cb,
+-			       NULL);
+-	return rc;
+-}
+-
+-static int
+-qeth_setadapter_hstr(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,4,"adphstr");
+-
+-	if (qeth_adp_supported(card,IPA_SETADP_SET_BROADCAST_MODE)) {
+-		rc = qeth_send_setadp_mode(card, IPA_SETADP_SET_BROADCAST_MODE,
+-					   card->options.broadcast_mode);
+-		if (rc)
+-			PRINT_WARN("couldn't set broadcast mode on "
+-				   "device %s: x%x\n",
+-				   CARD_BUS_ID(card), rc);
+-		rc = qeth_send_setadp_mode(card, IPA_SETADP_ALTER_MAC_ADDRESS,
+-					   card->options.macaddr_mode);
+-		if (rc)
+-			PRINT_WARN("couldn't set macaddr mode on "
+-				   "device %s: x%x\n", CARD_BUS_ID(card), rc);
+-		return rc;
+-	}
+-	if (card->options.broadcast_mode == QETH_TR_BROADCAST_LOCAL)
+-		PRINT_WARN("set adapter parameters not available "
+-			   "to set broadcast mode, using ALLRINGS "
+-			   "on device %s:\n", CARD_BUS_ID(card));
+-	if (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL)
+-		PRINT_WARN("set adapter parameters not available "
+-			   "to set macaddr mode, using NONCANONICAL "
+-			   "on device %s:\n", CARD_BUS_ID(card));
+-	return 0;
+-}
+-
+-static int
+-qeth_setadapter_parms(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(setup, 2, "setadprm");
+-
+-	if (!qeth_is_supported(card, IPA_SETADAPTERPARMS)){
+-		PRINT_WARN("set adapter parameters not supported "
+-			   "on device %s.\n",
+-			   CARD_BUS_ID(card));
+-		QETH_DBF_TEXT(setup, 2, " notsupp");
+-		return 0;
+-	}
+-	rc = qeth_query_setadapterparms(card);
+-	if (rc) {
+-		PRINT_WARN("couldn't set adapter parameters on device %s: "
+-			   "x%x\n", CARD_BUS_ID(card), rc);
+-		return rc;
+-	}
+-	if (qeth_adp_supported(card,IPA_SETADP_ALTER_MAC_ADDRESS)) {
+-		rc = qeth_setadpparms_change_macaddr(card);
+-		if (rc)
+-			PRINT_WARN("couldn't get MAC address on "
+-				   "device %s: x%x\n",
+-				   CARD_BUS_ID(card), rc);
+-	}
+-
+-	if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+-	    (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
+-		rc = qeth_setadapter_hstr(card);
+-
+-	return rc;
+-}
+-
+-static int
+-qeth_layer2_initialize(struct qeth_card *card)
+-{
+-        int rc = 0;
+-
+-
+-        QETH_DBF_TEXT(setup, 2, "doL2init");
+-        QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
+-
+-	rc = qeth_query_setadapterparms(card);
+-	if (rc) {
+-		PRINT_WARN("could not query adapter parameters on device %s: "
+-			   "x%x\n", CARD_BUS_ID(card), rc);
+-	}
+-
+-	rc = qeth_setadpparms_change_macaddr(card);
+-	if (rc) {
+-		PRINT_WARN("couldn't get MAC address on "
+-			   "device %s: x%x\n",
+-			   CARD_BUS_ID(card), rc);
+-		QETH_DBF_TEXT_(setup, 2,"1err%d",rc);
+-		return rc;
+-        }
+-	QETH_DBF_HEX(setup,2, card->dev->dev_addr, OSA_ADDR_LEN);
+-
+-	rc = qeth_layer2_send_setmac(card, &card->dev->dev_addr[0]);
+-        if (rc)
+-		QETH_DBF_TEXT_(setup, 2,"2err%d",rc);
+-        return 0;
+-}
+-
+-
+-static int
+-qeth_send_startstoplan(struct qeth_card *card, enum qeth_ipa_cmds ipacmd,
+-		       enum qeth_prot_versions prot)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-
+-	iob = qeth_get_ipacmd_buffer(card,ipacmd,prot);
+-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-
+-	return rc;
+-}
+-
+-static int
+-qeth_send_startlan(struct qeth_card *card, enum qeth_prot_versions prot)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT_(setup, 2, "strtlan%i", prot);
+-
+-	rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, prot);
+-	return rc;
+-}
+-
+-static int
+-qeth_send_stoplan(struct qeth_card *card)
+-{
+-	int rc = 0;
+-
+-	/*
+-	 * TODO: according to the IPA format document page 14,
+-	 * TCP/IP (we!) never issue a STOPLAN
+-	 * is this right ?!?
+-	 */
+-	QETH_DBF_TEXT(trace, 2, "stoplan");
+-
+-	rc = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, QETH_PROT_IPV4);
+-	return rc;
+-}
+-
+-static int
+-qeth_query_ipassists_cb(struct qeth_card *card, struct qeth_reply *reply,
+-			unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(setup, 2, "qipasscb");
+-
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
+-		card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
+-		card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+-		/* Disable IPV6 support hard coded for Hipersockets */
+-		if(card->info.type == QETH_CARD_TYPE_IQD)
+-			card->options.ipa4.supported_funcs &= ~IPA_IPV6;
+-	} else {
+-#ifdef CONFIG_QETH_IPV6
+-		card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
+-		card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
+-#endif
+-	}
+-	QETH_DBF_TEXT(setup, 2, "suppenbl");
+-	QETH_DBF_TEXT_(setup, 2, "%x",cmd->hdr.ipa_supported);
+-	QETH_DBF_TEXT_(setup, 2, "%x",cmd->hdr.ipa_enabled);
+-	return 0;
+-}
+-
+-static int
+-qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot)
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT_(setup, 2, "qipassi%i", prot);
+-	if (card->options.layer2) {
+-		QETH_DBF_TEXT(setup, 2, "noprmly2");
+-		return -EPERM;
+-	}
+-
+-	iob = qeth_get_ipacmd_buffer(card,IPA_CMD_QIPASSIST,prot);
+-	rc = qeth_send_ipa_cmd(card, iob, qeth_query_ipassists_cb, NULL);
+-	return rc;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_setassparms_cmd(struct qeth_card *card, enum qeth_ipa_funcs ipa_func,
+-			 __u16 cmd_code, __u16 len,
+-			 enum qeth_prot_versions prot)
+-{
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,4,"getasscm");
+-	iob = qeth_get_ipacmd_buffer(card,IPA_CMD_SETASSPARMS,prot);
+-
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	cmd->data.setassparms.hdr.assist_no = ipa_func;
+-	cmd->data.setassparms.hdr.length = 8 + len;
+-	cmd->data.setassparms.hdr.command_code = cmd_code;
+-	cmd->data.setassparms.hdr.return_code = 0;
+-	cmd->data.setassparms.hdr.seq_no = 0;
+-
+-	return iob;
+-}
+-
+-static int
+-qeth_send_setassparms(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+-		      __u16 len, long data,
+-		      int (*reply_cb)
+-		      (struct qeth_card *,struct qeth_reply *,unsigned long),
+-		      void *reply_param)
+-{
+-	int rc;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,4,"sendassp");
+-
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	if (len <= sizeof(__u32))
+-		cmd->data.setassparms.data.flags_32bit = (__u32) data;
+-	else   /* (len > sizeof(__u32)) */
+-		memcpy(&cmd->data.setassparms.data, (void *) data, len);
+-
+-	rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
+-	return rc;
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static int
+-qeth_send_simple_setassparms_ipv6(struct qeth_card *card,
+-				  enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
+-
+-{
+-	int rc;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(trace,4,"simassp6");
+-	iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
+-				       0, QETH_PROT_IPV6);
+-	rc = qeth_send_setassparms(card, iob, 0, 0,
+-				   qeth_default_setassparms_cb, NULL);
+-	return rc;
+-}
+-#endif
+-
+-static int
+-qeth_send_simple_setassparms(struct qeth_card *card,
+-			     enum qeth_ipa_funcs ipa_func,
+-			     __u16 cmd_code, long data)
+-{
+-	int rc;
+-	int length = 0;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(trace,4,"simassp4");
+-	if (data)
+-		length = sizeof(__u32);
+-	iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
+-				       length, QETH_PROT_IPV4);
+-	rc = qeth_send_setassparms(card, iob, length, data,
+-				   qeth_default_setassparms_cb, NULL);
+-	return rc;
+-}
+-
+-static int
+-qeth_start_ipa_arp_processing(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"ipaarp");
+-
+-	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+-		PRINT_WARN("ARP processing not supported "
+-			   "on %s!\n", QETH_CARD_IFNAME(card));
+-		return 0;
+-	}
+-	rc = qeth_send_simple_setassparms(card,IPA_ARP_PROCESSING,
+-					  IPA_CMD_ASS_START, 0);
+-	if (rc) {
+-		PRINT_WARN("Could not start ARP processing "
+-			   "assist on %s: 0x%x\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-	}
+-	return rc;
+-}
+-
+-static int
+-qeth_start_ipa_ip_fragmentation(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"ipaipfrg");
+-
+-	if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
+-		PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
+-			   QETH_CARD_IFNAME(card));
+-		return  -EOPNOTSUPP;
+-	}
+-
+-	rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
+-					  IPA_CMD_ASS_START, 0);
+-	if (rc) {
+-		PRINT_WARN("Could not start Hardware IP fragmentation "
+-			   "assist on %s: 0x%x\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-	} else
+-		PRINT_INFO("Hardware IP fragmentation enabled \n");
+-	return rc;
+-}
+-
+-static int
+-qeth_start_ipa_source_mac(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"stsrcmac");
+-
+-	if (!card->options.fake_ll)
+-		return -EOPNOTSUPP;
+-
+-	if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
+-		PRINT_INFO("Inbound source address not "
+-			   "supported on %s\n", QETH_CARD_IFNAME(card));
+-		return -EOPNOTSUPP;
+-	}
+-
+-	rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
+-					  IPA_CMD_ASS_START, 0);
+-	if (rc)
+-		PRINT_WARN("Could not start inbound source "
+-			   "assist on %s: 0x%x\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-	return rc;
+-}
+-
+-static int
+-qeth_start_ipa_vlan(struct qeth_card *card)
+-{
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace,3,"strtvlan");
+-
+-#ifdef CONFIG_QETH_VLAN
+-	if (!qeth_is_supported(card, IPA_FULL_VLAN)) {
+-		PRINT_WARN("VLAN not supported on %s\n", QETH_CARD_IFNAME(card));
+-		return -EOPNOTSUPP;
+-	}
+-
+-	rc = qeth_send_simple_setassparms(card, IPA_VLAN_PRIO,
+-					  IPA_CMD_ASS_START,0);
+-	if (rc) {
+-		PRINT_WARN("Could not start vlan "
+-			   "assist on %s: 0x%x\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-	} else {
+-		PRINT_INFO("VLAN enabled \n");
+-		card->dev->features |=
+-			NETIF_F_HW_VLAN_FILTER |
+-			NETIF_F_HW_VLAN_TX |
+-			NETIF_F_HW_VLAN_RX;
+-	}
+-#endif /* QETH_VLAN */
+-	return rc;
+-}
+-
+-static int
+-qeth_start_ipa_multicast(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"stmcast");
+-
+-	if (!qeth_is_supported(card, IPA_MULTICASTING)) {
+-		PRINT_WARN("Multicast not supported on %s\n",
+-			   QETH_CARD_IFNAME(card));
+-		return -EOPNOTSUPP;
+-	}
+-
+-	rc = qeth_send_simple_setassparms(card, IPA_MULTICASTING,
+-					  IPA_CMD_ASS_START,0);
+-	if (rc) {
+-		PRINT_WARN("Could not start multicast "
+-			   "assist on %s: rc=%i\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-	} else {
+-		PRINT_INFO("Multicast enabled\n");
+-		card->dev->flags |= IFF_MULTICAST;
+-	}
+-	return rc;
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static int
+-qeth_softsetup_ipv6(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"softipv6");
+-
+-	rc = qeth_send_startlan(card, QETH_PROT_IPV6);
+-	if (rc) {
+-		PRINT_ERR("IPv6 startlan failed on %s\n",
+-			  QETH_CARD_IFNAME(card));
+-		return rc;
+-	}
+-	rc = qeth_query_ipassists(card,QETH_PROT_IPV6);
+-	if (rc) {
+-		PRINT_ERR("IPv6 query ipassist failed on %s\n",
+-			  QETH_CARD_IFNAME(card));
+-		return rc;
+-	}
+-	rc = qeth_send_simple_setassparms(card, IPA_IPV6,
+-					  IPA_CMD_ASS_START, 3);
+-	if (rc) {
+-		PRINT_WARN("IPv6 start assist (version 4) failed "
+-			   "on %s: 0x%x\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-		return rc;
+-	}
+-	rc = qeth_send_simple_setassparms_ipv6(card, IPA_IPV6,
+-					       IPA_CMD_ASS_START);
+-	if (rc) {
+-		PRINT_WARN("IPV6 start assist (version 6) failed  "
+-			   "on %s: 0x%x\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-		return rc;
+-	}
+-	rc = qeth_send_simple_setassparms_ipv6(card, IPA_PASSTHRU,
+-					       IPA_CMD_ASS_START);
+-	if (rc) {
+-		PRINT_WARN("Could not enable passthrough "
+-			   "on %s: 0x%x\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-		return rc;
+-	}
+-	PRINT_INFO("IPV6 enabled \n");
+-	return 0;
+-}
+-
+-#endif
+-
+-static int
+-qeth_start_ipa_ipv6(struct qeth_card *card)
+-{
+-	int rc = 0;
+-#ifdef CONFIG_QETH_IPV6
+-	QETH_DBF_TEXT(trace,3,"strtipv6");
+-
+-	if (!qeth_is_supported(card, IPA_IPV6)) {
+-		PRINT_WARN("IPv6 not supported on %s\n",
+-			   QETH_CARD_IFNAME(card));
+-		return 0;
+-	}
+-	rc = qeth_softsetup_ipv6(card);
+-#endif
+-	return rc ;
+-}
+-
+-static int
+-qeth_start_ipa_broadcast(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"stbrdcst");
+-	card->info.broadcast_capable = 0;
+-	if (!qeth_is_supported(card, IPA_FILTERING)) {
+-		PRINT_WARN("Broadcast not supported on %s\n",
+-			   QETH_CARD_IFNAME(card));
+-		rc = -EOPNOTSUPP;
+-		goto out;
+-	}
+-	rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
+-					  IPA_CMD_ASS_START, 0);
+-	if (rc) {
+-		PRINT_WARN("Could not enable broadcasting filtering "
+-			   "on %s: 0x%x\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-		goto out;
+-	}
+-
+-	rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
+-					  IPA_CMD_ASS_CONFIGURE, 1);
+-	if (rc) {
+-		PRINT_WARN("Could not set up broadcast filtering on %s: 0x%x\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-		goto out;
+-	}
+-	card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
+-	PRINT_INFO("Broadcast enabled \n");
+-	rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
+-					  IPA_CMD_ASS_ENABLE, 1);
+-	if (rc) {
+-		PRINT_WARN("Could not set up broadcast echo filtering on "
+-			   "%s: 0x%x\n", QETH_CARD_IFNAME(card), rc);
+-		goto out;
+-	}
+-	card->info.broadcast_capable = QETH_BROADCAST_WITHOUT_ECHO;
+-out:
+-	if (card->info.broadcast_capable)
+-		card->dev->flags |= IFF_BROADCAST;
+-	else
+-		card->dev->flags &= ~IFF_BROADCAST;
+-	return rc;
+-}
+-
+-static int
+-qeth_send_checksum_command(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+-					  IPA_CMD_ASS_START, 0);
+-	if (rc) {
+-		PRINT_WARN("Starting Inbound HW Checksumming failed on %s: "
+-			   "0x%x,\ncontinuing using Inbound SW Checksumming\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-		return rc;
+-	}
+-	rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+-					  IPA_CMD_ASS_ENABLE,
+-					  card->info.csum_mask);
+-	if (rc) {
+-		PRINT_WARN("Enabling Inbound HW Checksumming failed on %s: "
+-			   "0x%x,\ncontinuing using Inbound SW Checksumming\n",
+-			   QETH_CARD_IFNAME(card), rc);
+-		return rc;
+-	}
+-	return 0;
+-}
+-
+-static int
+-qeth_start_ipa_checksum(struct qeth_card *card)
+-{
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace,3,"strtcsum");
+-
+-	if (card->options.checksum_type == NO_CHECKSUMMING) {
+-		PRINT_WARN("Using no checksumming on %s.\n",
+-			   QETH_CARD_IFNAME(card));
+-		return 0;
+-	}
+-	if (card->options.checksum_type == SW_CHECKSUMMING) {
+-		PRINT_WARN("Using SW checksumming on %s.\n",
+-			   QETH_CARD_IFNAME(card));
+-		return 0;
+-	}
+-	if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) {
+-		PRINT_WARN("Inbound HW Checksumming not "
+-			   "supported on %s,\ncontinuing "
+-			   "using Inbound SW Checksumming\n",
+-			   QETH_CARD_IFNAME(card));
+-		card->options.checksum_type = SW_CHECKSUMMING;
+-		return 0;
+-	}
+-	rc = qeth_send_checksum_command(card);
+-	if (!rc) {
+-		PRINT_INFO("HW Checksumming (inbound) enabled \n");
+-	}
+-	return rc;
+-}
+-
+-static int
+-qeth_start_ipa_tso(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"sttso");
+-
+-	if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
+-		PRINT_WARN("Outbound TSO not supported on %s\n",
+-			   QETH_CARD_IFNAME(card));
+-		rc = -EOPNOTSUPP;
+-	} else {
+-		rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
+-						  IPA_CMD_ASS_START,0);
+-		if (rc)
+-			PRINT_WARN("Could not start outbound TSO "
+-				   "assist on %s: rc=%i\n",
+-				   QETH_CARD_IFNAME(card), rc);
+-		else
+-			PRINT_INFO("Outbound TSO enabled\n");
+-	}
+-	if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)){
+-		card->options.large_send = QETH_LARGE_SEND_NO;
+-		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+-						NETIF_F_HW_CSUM);
+-	}
+-	return rc;
+-}
+-
+-static int
+-qeth_start_ipassists(struct qeth_card *card)
+-{
+-	QETH_DBF_TEXT(trace,3,"strtipas");
+-	qeth_start_ipa_arp_processing(card);	/* go on*/
+-	qeth_start_ipa_ip_fragmentation(card); 	/* go on*/
+-	qeth_start_ipa_source_mac(card);	/* go on*/
+-	qeth_start_ipa_vlan(card);		/* go on*/
+-	qeth_start_ipa_multicast(card);		/* go on*/
+-	qeth_start_ipa_ipv6(card);		/* go on*/
+-	qeth_start_ipa_broadcast(card);		/* go on*/
+-	qeth_start_ipa_checksum(card);		/* go on*/
+-	qeth_start_ipa_tso(card);		/* go on*/
+-	return 0;
+-}
+-
+-static int
+-qeth_send_setrouting(struct qeth_card *card, enum qeth_routing_types type,
+-		     enum qeth_prot_versions prot)
+-{
+-	int rc;
+-	struct qeth_ipa_cmd *cmd;
+-	struct qeth_cmd_buffer *iob;
+-
+-	QETH_DBF_TEXT(trace,4,"setroutg");
+-	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	cmd->data.setrtg.type = (type);
+-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-
+-	return rc;
+-
+-}
+-
+-static void
+-qeth_correct_routing_type(struct qeth_card *card, enum qeth_routing_types *type,
+-			enum qeth_prot_versions prot)
+-{
+-	if (card->info.type == QETH_CARD_TYPE_IQD) {
+-		switch (*type) {
+-		case NO_ROUTER:
+-		case PRIMARY_CONNECTOR:
+-		case SECONDARY_CONNECTOR:
+-		case MULTICAST_ROUTER:
+-			return;
+-		default:
+-			goto out_inval;
+-		}
+-	} else {
+-		switch (*type) {
+-		case NO_ROUTER:
+-		case PRIMARY_ROUTER:
+-		case SECONDARY_ROUTER:
+-			return;
+-		case MULTICAST_ROUTER:
+-			if (qeth_is_ipafunc_supported(card, prot,
+-						      IPA_OSA_MC_ROUTER))
+-				return;
+-		default:
+-			goto out_inval;
+-		}
+-	}
+-out_inval:
+-	PRINT_WARN("Routing type '%s' not supported for interface %s.\n"
+-		   "Router status set to 'no router'.\n",
+-		   ((*type == PRIMARY_ROUTER)? "primary router" :
+-		    (*type == SECONDARY_ROUTER)? "secondary router" :
+-		    (*type == PRIMARY_CONNECTOR)? "primary connector" :
+-		    (*type == SECONDARY_CONNECTOR)? "secondary connector" :
+-		    (*type == MULTICAST_ROUTER)? "multicast router" :
+-		    "unknown"),
+-		   card->dev->name);
+-	*type = NO_ROUTER;
+-}
+-
+-int
+-qeth_setrouting_v4(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(trace,3,"setrtg4");
+-
+-	qeth_correct_routing_type(card, &card->options.route4.type,
+-				  QETH_PROT_IPV4);
+-
+-	rc = qeth_send_setrouting(card, card->options.route4.type,
+-				  QETH_PROT_IPV4);
+-	if (rc) {
+- 		card->options.route4.type = NO_ROUTER;
+-		PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
+-			   "Type set to 'no router'.\n",
+-			   rc, QETH_CARD_IFNAME(card));
+-	}
+-	return rc;
+-}
+-
+-int
+-qeth_setrouting_v6(struct qeth_card *card)
+-{
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace,3,"setrtg6");
+-#ifdef CONFIG_QETH_IPV6
+-
+-	if (!qeth_is_supported(card, IPA_IPV6))
+-		return 0;
+-	qeth_correct_routing_type(card, &card->options.route6.type,
+-				  QETH_PROT_IPV6);
+-
+-	rc = qeth_send_setrouting(card, card->options.route6.type,
+-				  QETH_PROT_IPV6);
+-	if (rc) {
+-	 	card->options.route6.type = NO_ROUTER;
+-		PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
+-			   "Type set to 'no router'.\n",
+-			   rc, QETH_CARD_IFNAME(card));
+-	}
+-#endif
+-	return rc;
+-}
+-
+-int
+-qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
+-{
+-	int rc = 0;
+-
+-	if (card->dev == NULL) {
+-		card->options.large_send = type;
+-		return 0;
+-	}
+-	if (card->state == CARD_STATE_UP)
+-		netif_tx_disable(card->dev);
+-	card->options.large_send = type;
+-	switch (card->options.large_send) {
+-	case QETH_LARGE_SEND_EDDP:
+-		card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
+-					NETIF_F_HW_CSUM;
+-		break;
+-	case QETH_LARGE_SEND_TSO:
+-		if (qeth_is_supported(card, IPA_OUTBOUND_TSO)){
+-			card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
+-						NETIF_F_HW_CSUM;
+-		} else {
+-			PRINT_WARN("TSO not supported on %s. "
+-				   "large_send set to 'no'.\n",
+-				   card->dev->name);
+-			card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+-						NETIF_F_HW_CSUM);
+-			card->options.large_send = QETH_LARGE_SEND_NO;
+-			rc = -EOPNOTSUPP;
+-		}
+-		break;
+-	default: /* includes QETH_LARGE_SEND_NO */
+-		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+-					NETIF_F_HW_CSUM);
+-		break;
+-	}
+-	if (card->state == CARD_STATE_UP)
+-		netif_wake_queue(card->dev);
+-	return rc;
+-}
+-
+-/*
+- * softsetup card: init IPA stuff
+- */
+-static int
+-qeth_softsetup_card(struct qeth_card *card)
+-{
+-	int rc;
+-
+-	QETH_DBF_TEXT(setup, 2, "softsetp");
+-
+-	if ((rc = qeth_send_startlan(card, QETH_PROT_IPV4))){
+-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+-		if (rc == 0xe080){
+-			PRINT_WARN("LAN on card %s if offline! "
+-				   "Waiting for STARTLAN from card.\n",
+-				   CARD_BUS_ID(card));
+-			card->lan_online = 0;
+-		}
+-		return rc;
+-	} else
+-		card->lan_online = 1;
+-	if (card->info.type==QETH_CARD_TYPE_OSN)
+-		goto out;
+-	qeth_set_large_send(card, card->options.large_send);
+-	if (card->options.layer2) {
+-		card->dev->features |=
+-			NETIF_F_HW_VLAN_FILTER |
+-			NETIF_F_HW_VLAN_TX |
+-			NETIF_F_HW_VLAN_RX;
+-		card->dev->flags|=IFF_MULTICAST|IFF_BROADCAST;
+-		card->info.broadcast_capable=1;
+-		if ((rc = qeth_layer2_initialize(card))) {
+-			QETH_DBF_TEXT_(setup, 2, "L2err%d", rc);
+-			return rc;
+-		}
+-#ifdef CONFIG_QETH_VLAN
+-		qeth_layer2_process_vlans(card, 0);
+-#endif
+-		goto out;
+-	}
+-	if ((rc = qeth_setadapter_parms(card)))
+-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+-	if ((rc = qeth_start_ipassists(card)))
+-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+-	if ((rc = qeth_setrouting_v4(card)))
+-		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+-	if ((rc = qeth_setrouting_v6(card)))
+-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+-out:
+-	netif_tx_disable(card->dev);
+-	return 0;
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static int
+-qeth_get_unique_id_cb(struct qeth_card *card, struct qeth_reply *reply,
+-		      unsigned long data)
+-{
+-	struct qeth_ipa_cmd *cmd;
+-
+-	cmd = (struct qeth_ipa_cmd *) data;
+-	if (cmd->hdr.return_code == 0)
+-		card->info.unique_id = *((__u16 *)
+-				&cmd->data.create_destroy_addr.unique_id[6]);
+-	else {
+-		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+-					UNIQUE_ID_NOT_BY_CARD;
+-		PRINT_WARN("couldn't get a unique id from the card on device "
+-			   "%s (result=x%x), using default id. ipv6 "
+-			   "autoconfig on other lpars may lead to duplicate "
+-			   "ip addresses. please use manually "
+-			   "configured ones.\n",
+-			   CARD_BUS_ID(card), cmd->hdr.return_code);
+-	}
+-	return 0;
+-}
+-#endif
+-
+-static int
+-qeth_put_unique_id(struct qeth_card *card)
+-{
+-
+-	int rc = 0;
+-#ifdef CONFIG_QETH_IPV6
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(trace,2,"puniqeid");
+-
+-	if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) ==
+-	    	UNIQUE_ID_NOT_BY_CARD)
+-		return -1;
+-	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR,
+-				     QETH_PROT_IPV6);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
+-		            card->info.unique_id;
+-	memcpy(&cmd->data.create_destroy_addr.unique_id[0],
+-	       card->dev->dev_addr, OSA_ADDR_LEN);
+-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-#else
+-	card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+-				UNIQUE_ID_NOT_BY_CARD;
+-#endif
+-	return rc;
+-}
+-
+-/**
+- * Clear IP List
+- */
+-static void
+-qeth_clear_ip_list(struct qeth_card *card, int clean, int recover)
+-{
+-	struct qeth_ipaddr *addr, *tmp;
+-	unsigned long flags;
+-
+-	QETH_DBF_TEXT(trace,4,"clearip");
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	/* clear todo list */
+-	list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry){
+-		list_del(&addr->entry);
+-		kfree(addr);
+-	}
+-
+-	while (!list_empty(&card->ip_list)) {
+-		addr = list_entry(card->ip_list.next,
+-				  struct qeth_ipaddr, entry);
+-		list_del_init(&addr->entry);
+-		if (clean) {
+-			spin_unlock_irqrestore(&card->ip_lock, flags);
+-			qeth_deregister_addr_entry(card, addr);
+-			spin_lock_irqsave(&card->ip_lock, flags);
+-		}
+-		if (!recover || addr->is_multicast) {
+-			kfree(addr);
+-			continue;
+-		}
+-		list_add_tail(&addr->entry, card->ip_tbd_list);
+-	}
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-}
+-
+-static void
+-qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
+-			 int clear_start_mask)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&card->thread_mask_lock, flags);
+-	card->thread_allowed_mask = threads;
+-	if (clear_start_mask)
+-		card->thread_start_mask &= threads;
+-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+-	wake_up(&card->wait_q);
+-}
+-
+-static int
+-qeth_threads_running(struct qeth_card *card, unsigned long threads)
+-{
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	spin_lock_irqsave(&card->thread_mask_lock, flags);
+-	rc = (card->thread_running_mask & threads);
+-	spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+-	return rc;
+-}
+-
+-static int
+-qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
+-{
+-	return wait_event_interruptible(card->wait_q,
+-			qeth_threads_running(card, threads) == 0);
+-}
+-
+-static int
+-qeth_stop_card(struct qeth_card *card, int recovery_mode)
+-{
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(setup ,2,"stopcard");
+-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-
+-	qeth_set_allowed_threads(card, 0, 1);
+-	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
+-		return -ERESTARTSYS;
+-	if (card->read.state == CH_STATE_UP &&
+-	    card->write.state == CH_STATE_UP &&
+-	    (card->state == CARD_STATE_UP)) {
+-		if (recovery_mode &&
+-		    card->info.type != QETH_CARD_TYPE_OSN) {
+-			qeth_stop(card->dev);
+-		} else {
+-			rtnl_lock();
+-			dev_close(card->dev);
+-			rtnl_unlock();
+-		}
+-		if (!card->use_hard_stop) {
+-			__u8 *mac = &card->dev->dev_addr[0];
+-			rc = qeth_layer2_send_delmac(card, mac);
+-			QETH_DBF_TEXT_(setup, 2, "Lerr%d", rc);
+-			if ((rc = qeth_send_stoplan(card)))
+-				QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+-		}
+-		card->state = CARD_STATE_SOFTSETUP;
+-	}
+-	if (card->state == CARD_STATE_SOFTSETUP) {
+-#ifdef CONFIG_QETH_VLAN
+-		if (card->options.layer2)
+-			qeth_layer2_process_vlans(card, 1);
+-#endif
+-		qeth_clear_ip_list(card, !card->use_hard_stop, 1);
+-		qeth_clear_ipacmd_list(card);
+-		card->state = CARD_STATE_HARDSETUP;
+-	}
+-	if (card->state == CARD_STATE_HARDSETUP) {
+-		if ((!card->use_hard_stop) &&
+-		    (!card->options.layer2))
+-			if ((rc = qeth_put_unique_id(card)))
+-				QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+-		qeth_qdio_clear_card(card, 0);
+-		qeth_clear_qdio_buffers(card);
+-		qeth_clear_working_pool_list(card);
+-		card->state = CARD_STATE_DOWN;
+-	}
+-	if (card->state == CARD_STATE_DOWN) {
+-		qeth_clear_cmd_buffers(&card->read);
+-		qeth_clear_cmd_buffers(&card->write);
+-	}
+-	card->use_hard_stop = 0;
+-	return rc;
+-}
+-
+-
+-static int
+-qeth_get_unique_id(struct qeth_card *card)
+-{
+-	int rc = 0;
+-#ifdef CONFIG_QETH_IPV6
+-	struct qeth_cmd_buffer *iob;
+-	struct qeth_ipa_cmd *cmd;
+-
+-	QETH_DBF_TEXT(setup, 2, "guniqeid");
+-
+-	if (!qeth_is_supported(card,IPA_IPV6)) {
+-		card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+-					UNIQUE_ID_NOT_BY_CARD;
+-		return 0;
+-	}
+-
+-	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
+-				     QETH_PROT_IPV6);
+-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+-	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
+-		            card->info.unique_id;
+-
+-	rc = qeth_send_ipa_cmd(card, iob, qeth_get_unique_id_cb, NULL);
+-#else
+-	card->info.unique_id =  UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+-				UNIQUE_ID_NOT_BY_CARD;
+-#endif
+-	return rc;
+-}
+-static void
+-qeth_print_status_with_portname(struct qeth_card *card)
+-{
+-	char dbf_text[15];
+-	int i;
+-
+-	sprintf(dbf_text, "%s", card->info.portname + 1);
+-	for (i = 0; i < 8; i++)
+-		dbf_text[i] =
+-			(char) _ebcasc[(__u8) dbf_text[i]];
+-	dbf_text[8] = 0;
+-	printk("qeth: Device %s/%s/%s is a%s card%s%s%s\n"
+-	       "with link type %s (portname: %s)\n",
+-	       CARD_RDEV_ID(card),
+-	       CARD_WDEV_ID(card),
+-	       CARD_DDEV_ID(card),
+-	       qeth_get_cardname(card),
+-	       (card->info.mcl_level[0]) ? " (level: " : "",
+-	       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+-	       (card->info.mcl_level[0]) ? ")" : "",
+-	       qeth_get_cardname_short(card),
+-	       dbf_text);
+-
+-}
+-
+-static void
+-qeth_print_status_no_portname(struct qeth_card *card)
+-{
+-	if (card->info.portname[0])
+-		printk("qeth: Device %s/%s/%s is a%s "
+-		       "card%s%s%s\nwith link type %s "
+-		       "(no portname needed by interface).\n",
+-		       CARD_RDEV_ID(card),
+-		       CARD_WDEV_ID(card),
+-		       CARD_DDEV_ID(card),
+-		       qeth_get_cardname(card),
+-		       (card->info.mcl_level[0]) ? " (level: " : "",
+-		       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+-		       (card->info.mcl_level[0]) ? ")" : "",
+-		       qeth_get_cardname_short(card));
+-	else
+-		printk("qeth: Device %s/%s/%s is a%s "
+-		       "card%s%s%s\nwith link type %s.\n",
+-		       CARD_RDEV_ID(card),
+-		       CARD_WDEV_ID(card),
+-		       CARD_DDEV_ID(card),
+-		       qeth_get_cardname(card),
+-		       (card->info.mcl_level[0]) ? " (level: " : "",
+-		       (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+-		       (card->info.mcl_level[0]) ? ")" : "",
+-		       qeth_get_cardname_short(card));
+-}
+-
+-static void
+-qeth_print_status_message(struct qeth_card *card)
+-{
+-	switch (card->info.type) {
+-	case QETH_CARD_TYPE_OSAE:
+-		/* VM will use a non-zero first character
+-		 * to indicate a HiperSockets like reporting
+-		 * of the level OSA sets the first character to zero
+-		 * */
+-		if (!card->info.mcl_level[0]) {
+-			sprintf(card->info.mcl_level,"%02x%02x",
+-				card->info.mcl_level[2],
+-				card->info.mcl_level[3]);
+-
+-			card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+-			break;
+-		}
+-		/* fallthrough */
+-	case QETH_CARD_TYPE_IQD:
+-		if (card->info.guestlan) {
+-			card->info.mcl_level[0] = (char) _ebcasc[(__u8)
+-				card->info.mcl_level[0]];
+-			card->info.mcl_level[1] = (char) _ebcasc[(__u8)
+-				card->info.mcl_level[1]];
+-			card->info.mcl_level[2] = (char) _ebcasc[(__u8)
+-				card->info.mcl_level[2]];
+-			card->info.mcl_level[3] = (char) _ebcasc[(__u8)
+-				card->info.mcl_level[3]];
+-			card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+-		}
+-		break;
+-	default:
+-		memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
+-	}
+-	if (card->info.portname_required)
+-		qeth_print_status_with_portname(card);
+-	else
+-		qeth_print_status_no_portname(card);
+-}
+-
+-static int
+-qeth_register_netdev(struct qeth_card *card)
+-{
+-	QETH_DBF_TEXT(setup, 3, "regnetd");
+-	if (card->dev->reg_state != NETREG_UNINITIALIZED)
+-		return 0;
+-	/* sysfs magic */
+-	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
+-	return register_netdev(card->dev);
+-}
+-
+-static void
+-qeth_start_again(struct qeth_card *card, int recovery_mode)
+-{
+-	QETH_DBF_TEXT(setup ,2, "startag");
+-
+-	if (recovery_mode &&
+-	    card->info.type != QETH_CARD_TYPE_OSN) {
+-		qeth_open(card->dev);
+-	} else {
+-		rtnl_lock();
+-		dev_open(card->dev);
+-		rtnl_unlock();
+-	}
+-	/* this also sets saved unicast addresses */
+-	qeth_set_multicast_list(card->dev);
+-}
+-
+-
+-/* Layer 2 specific stuff */
+-#define IGNORE_PARAM_EQ(option,value,reset_value,msg) \
+-        if (card->options.option == value) { \
+-                PRINT_ERR("%s not supported with layer 2 " \
+-                          "functionality, ignoring option on read" \
+-			  "channel device %s .\n",msg,CARD_RDEV_ID(card)); \
+-                card->options.option = reset_value; \
+-        }
+-#define IGNORE_PARAM_NEQ(option,value,reset_value,msg) \
+-        if (card->options.option != value) { \
+-                PRINT_ERR("%s not supported with layer 2 " \
+-                          "functionality, ignoring option on read" \
+-			  "channel device %s .\n",msg,CARD_RDEV_ID(card)); \
+-                card->options.option = reset_value; \
+-        }
+-
+-
+-static void qeth_make_parameters_consistent(struct qeth_card *card)
+-{
+-
+-	if (card->options.layer2 == 0)
+-		return;
+-	if (card->info.type == QETH_CARD_TYPE_OSN)
+-		return;
+-	if (card->info.type == QETH_CARD_TYPE_IQD) {
+-       		PRINT_ERR("Device %s does not support layer 2 functionality." \
+-	               	  " Ignoring layer2 option.\n",CARD_BUS_ID(card));
+-       		card->options.layer2 = 0;
+-		return;
+-	}
+-       	IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
+-               	         "Routing options are");
+-#ifdef CONFIG_QETH_IPV6
+-       	IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
+-               	         "Routing options are");
+-#endif
+-       	IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
+-                       	QETH_CHECKSUM_DEFAULT,
+-               	        "Checksumming options are");
+-       	IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
+-                       	 QETH_TR_BROADCAST_ALLRINGS,
+-               	         "Broadcast mode options are");
+-       	IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
+-                       	 QETH_TR_MACADDR_NONCANONICAL,
+-               	         "Canonical MAC addr options are");
+-       	IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
+-			 "Broadcast faking options are");
+-       	IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
+-       	                 DEFAULT_ADD_HHLEN,"Option add_hhlen is");
+-        IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
+-}
+-
+-
+-static int
+-__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
+-{
+-	struct qeth_card *card = gdev->dev.driver_data;
+-	int rc = 0;
+-	enum qeth_card_states recover_flag;
+-
+-	BUG_ON(!card);
+-	QETH_DBF_TEXT(setup ,2, "setonlin");
+-	QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-
+-	qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
+-	if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)){
+-		PRINT_WARN("set_online of card %s interrupted by user!\n",
+-			   CARD_BUS_ID(card));
+-		return -ERESTARTSYS;
+-	}
+-
+-	recover_flag = card->state;
+-	if ((rc = ccw_device_set_online(CARD_RDEV(card))) ||
+-	    (rc = ccw_device_set_online(CARD_WDEV(card))) ||
+-	    (rc = ccw_device_set_online(CARD_DDEV(card)))){
+-		QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+-		return -EIO;
+-	}
+-
+-	qeth_make_parameters_consistent(card);
+-
+-	if ((rc = qeth_hardsetup_card(card))){
+-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+-		goto out_remove;
+-	}
+-	card->state = CARD_STATE_HARDSETUP;
+-
+-	if (!(rc = qeth_query_ipassists(card,QETH_PROT_IPV4)))
+-		rc = qeth_get_unique_id(card);
+-
+-	if (rc && card->options.layer2 == 0) {
+-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+-		goto out_remove;
+-	}
+-	qeth_print_status_message(card);
+-	if ((rc = qeth_register_netdev(card))){
+-		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+-		goto out_remove;
+-	}
+-	if ((rc = qeth_softsetup_card(card))){
+-		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+-		goto out_remove;
+-	}
+-
+-	if ((rc = qeth_init_qdio_queues(card))){
+-		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+-		goto out_remove;
+-	}
+-	card->state = CARD_STATE_SOFTSETUP;
+-	netif_carrier_on(card->dev);
+-
+-	qeth_set_allowed_threads(card, 0xffffffff, 0);
+-	if (recover_flag == CARD_STATE_RECOVER)
+-		qeth_start_again(card, recovery_mode);
+-	qeth_notify_processes();
+-	return 0;
+-out_remove:
+-	card->use_hard_stop = 1;
+-	qeth_stop_card(card, 0);
+-	ccw_device_set_offline(CARD_DDEV(card));
+-	ccw_device_set_offline(CARD_WDEV(card));
+-	ccw_device_set_offline(CARD_RDEV(card));
+-	if (recover_flag == CARD_STATE_RECOVER)
+-		card->state = CARD_STATE_RECOVER;
+-	else
+-		card->state = CARD_STATE_DOWN;
+-	return -ENODEV;
+-}
+-
+-static int
+-qeth_set_online(struct ccwgroup_device *gdev)
+-{
+-	return __qeth_set_online(gdev, 0);
+-}
+-
+-static struct ccw_device_id qeth_ids[] = {
+-	{CCW_DEVICE(0x1731, 0x01), .driver_info = QETH_CARD_TYPE_OSAE},
+-	{CCW_DEVICE(0x1731, 0x05), .driver_info = QETH_CARD_TYPE_IQD},
+-	{CCW_DEVICE(0x1731, 0x06), .driver_info = QETH_CARD_TYPE_OSN},
+-	{},
+-};
+-MODULE_DEVICE_TABLE(ccw, qeth_ids);
+-
+-struct device *qeth_root_dev = NULL;
+-
+-struct ccwgroup_driver qeth_ccwgroup_driver = {
+-	.owner = THIS_MODULE,
+-	.name = "qeth",
+-	.driver_id = 0xD8C5E3C8,
+-	.probe = qeth_probe_device,
+-	.remove = qeth_remove_device,
+-	.set_online = qeth_set_online,
+-	.set_offline = qeth_set_offline,
+-};
+-
+-struct ccw_driver qeth_ccw_driver = {
+-	.name = "qeth",
+-	.ids = qeth_ids,
+-	.probe = ccwgroup_probe_ccwdev,
+-	.remove = ccwgroup_remove_ccwdev,
+-};
+-
+-
+-static void
+-qeth_unregister_dbf_views(void)
+-{
+-	if (qeth_dbf_setup)
+-		debug_unregister(qeth_dbf_setup);
+-	if (qeth_dbf_qerr)
+-		debug_unregister(qeth_dbf_qerr);
+-	if (qeth_dbf_sense)
+-		debug_unregister(qeth_dbf_sense);
+-	if (qeth_dbf_misc)
+-		debug_unregister(qeth_dbf_misc);
+-	if (qeth_dbf_data)
+-		debug_unregister(qeth_dbf_data);
+-	if (qeth_dbf_control)
+-		debug_unregister(qeth_dbf_control);
+-	if (qeth_dbf_trace)
+-		debug_unregister(qeth_dbf_trace);
+-}
+-static int
+-qeth_register_dbf_views(void)
+-{
+-	qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME,
+-					QETH_DBF_SETUP_PAGES,
+-					QETH_DBF_SETUP_NR_AREAS,
+-					QETH_DBF_SETUP_LEN);
+-	qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME,
+-				       QETH_DBF_MISC_PAGES,
+-				       QETH_DBF_MISC_NR_AREAS,
+-				       QETH_DBF_MISC_LEN);
+-	qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME,
+-				       QETH_DBF_DATA_PAGES,
+-				       QETH_DBF_DATA_NR_AREAS,
+-				       QETH_DBF_DATA_LEN);
+-	qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME,
+-					  QETH_DBF_CONTROL_PAGES,
+-					  QETH_DBF_CONTROL_NR_AREAS,
+-					  QETH_DBF_CONTROL_LEN);
+-	qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME,
+-					QETH_DBF_SENSE_PAGES,
+-					QETH_DBF_SENSE_NR_AREAS,
+-					QETH_DBF_SENSE_LEN);
+-	qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME,
+-				       QETH_DBF_QERR_PAGES,
+-				       QETH_DBF_QERR_NR_AREAS,
+-				       QETH_DBF_QERR_LEN);
+-	qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME,
+-					QETH_DBF_TRACE_PAGES,
+-					QETH_DBF_TRACE_NR_AREAS,
+-					QETH_DBF_TRACE_LEN);
+-
+-	if ((qeth_dbf_setup == NULL) || (qeth_dbf_misc == NULL)    ||
+-	    (qeth_dbf_data == NULL)  || (qeth_dbf_control == NULL) ||
+-	    (qeth_dbf_sense == NULL) || (qeth_dbf_qerr == NULL)    ||
+-	    (qeth_dbf_trace == NULL)) {
+-		qeth_unregister_dbf_views();
+-		return -ENOMEM;
+-	}
+-	debug_register_view(qeth_dbf_setup, &debug_hex_ascii_view);
+-	debug_set_level(qeth_dbf_setup, QETH_DBF_SETUP_LEVEL);
+-
+-	debug_register_view(qeth_dbf_misc, &debug_hex_ascii_view);
+-	debug_set_level(qeth_dbf_misc, QETH_DBF_MISC_LEVEL);
+-
+-	debug_register_view(qeth_dbf_data, &debug_hex_ascii_view);
+-	debug_set_level(qeth_dbf_data, QETH_DBF_DATA_LEVEL);
+-
+-	debug_register_view(qeth_dbf_control, &debug_hex_ascii_view);
+-	debug_set_level(qeth_dbf_control, QETH_DBF_CONTROL_LEVEL);
+-
+-	debug_register_view(qeth_dbf_sense, &debug_hex_ascii_view);
+-	debug_set_level(qeth_dbf_sense, QETH_DBF_SENSE_LEVEL);
+-
+-	debug_register_view(qeth_dbf_qerr, &debug_hex_ascii_view);
+-	debug_set_level(qeth_dbf_qerr, QETH_DBF_QERR_LEVEL);
+-
+-	debug_register_view(qeth_dbf_trace, &debug_hex_ascii_view);
+-	debug_set_level(qeth_dbf_trace, QETH_DBF_TRACE_LEVEL);
+-
+-	return 0;
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-extern struct neigh_table arp_tbl;
+-static struct neigh_ops *arp_direct_ops;
+-static int (*qeth_old_arp_constructor) (struct neighbour *);
+-
+-static struct neigh_ops arp_direct_ops_template = {
+-	.family = AF_INET,
+-	.solicit = NULL,
+-	.error_report = NULL,
+-	.output = dev_queue_xmit,
+-	.connected_output = dev_queue_xmit,
+-	.hh_output = dev_queue_xmit,
+-	.queue_xmit = dev_queue_xmit
+-};
+-
+-static int
+-qeth_arp_constructor(struct neighbour *neigh)
+-{
+-	struct net_device *dev = neigh->dev;
+-	struct in_device *in_dev;
+-	struct neigh_parms *parms;
+-	struct qeth_card *card;
+-
+-	card = qeth_get_card_from_dev(dev);
+-	if (card == NULL)
+-		goto out;
+-	if((card->options.layer2) ||
+-	   (card->dev->header_ops == &qeth_fake_ops))
+-		goto out;
+-
+-	rcu_read_lock();
+-	in_dev = __in_dev_get_rcu(dev);
+-	if (in_dev == NULL) {
+-		rcu_read_unlock();
+-		return -EINVAL;
+-	}
+-
+-	parms = in_dev->arp_parms;
+-	__neigh_parms_put(neigh->parms);
+-	neigh->parms = neigh_parms_clone(parms);
+-	rcu_read_unlock();
+-
+-	neigh->type = inet_addr_type(&init_net, *(__be32 *) neigh->primary_key);
+-	neigh->nud_state = NUD_NOARP;
+-	neigh->ops = arp_direct_ops;
+-	neigh->output = neigh->ops->queue_xmit;
+-	return 0;
+-out:
+-	return qeth_old_arp_constructor(neigh);
+-}
+-#endif  /*CONFIG_QETH_IPV6*/
+-
+-/*
+- * IP address takeover related functions
+- */
+-static void
+-qeth_clear_ipato_list(struct qeth_card *card)
+-{
+-	struct qeth_ipato_entry *ipatoe, *tmp;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
+-		list_del(&ipatoe->entry);
+-		kfree(ipatoe);
+-	}
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-}
+-
+-int
+-qeth_add_ipato_entry(struct qeth_card *card, struct qeth_ipato_entry *new)
+-{
+-	struct qeth_ipato_entry *ipatoe;
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	QETH_DBF_TEXT(trace, 2, "addipato");
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	list_for_each_entry(ipatoe, &card->ipato.entries, entry){
+-		if (ipatoe->proto != new->proto)
+-			continue;
+-		if (!memcmp(ipatoe->addr, new->addr,
+-			    (ipatoe->proto == QETH_PROT_IPV4)? 4:16) &&
+-		    (ipatoe->mask_bits == new->mask_bits)){
+-			PRINT_WARN("ipato entry already exists!\n");
+-			rc = -EEXIST;
+-			break;
+-		}
+-	}
+-	if (!rc) {
+-		list_add_tail(&new->entry, &card->ipato.entries);
+-	}
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-	return rc;
+-}
+-
+-void
+-qeth_del_ipato_entry(struct qeth_card *card, enum qeth_prot_versions proto,
+-		     u8 *addr, int mask_bits)
+-{
+-	struct qeth_ipato_entry *ipatoe, *tmp;
+-	unsigned long flags;
+-
+-	QETH_DBF_TEXT(trace, 2, "delipato");
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry){
+-		if (ipatoe->proto != proto)
+-			continue;
+-		if (!memcmp(ipatoe->addr, addr,
+-			    (proto == QETH_PROT_IPV4)? 4:16) &&
+-		    (ipatoe->mask_bits == mask_bits)){
+-			list_del(&ipatoe->entry);
+-			kfree(ipatoe);
+-		}
+-	}
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-}
+-
+-static void
+-qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
+-{
+-	int i, j;
+-	u8 octet;
+-
+-	for (i = 0; i < len; ++i){
+-		octet = addr[i];
+-		for (j = 7; j >= 0; --j){
+-			bits[i*8 + j] = octet & 1;
+-			octet >>= 1;
+-		}
+-	}
+-}
+-
+-static int
+-qeth_is_addr_covered_by_ipato(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+-	struct qeth_ipato_entry *ipatoe;
+-	u8 addr_bits[128] = {0, };
+-	u8 ipatoe_bits[128] = {0, };
+-	int rc = 0;
+-
+-	if (!card->ipato.enabled)
+-		return 0;
+-
+-	qeth_convert_addr_to_bits((u8 *) &addr->u, addr_bits,
+-				  (addr->proto == QETH_PROT_IPV4)? 4:16);
+-	list_for_each_entry(ipatoe, &card->ipato.entries, entry){
+-		if (addr->proto != ipatoe->proto)
+-			continue;
+-		qeth_convert_addr_to_bits(ipatoe->addr, ipatoe_bits,
+-					  (ipatoe->proto==QETH_PROT_IPV4) ?
+-					  4:16);
+-		if (addr->proto == QETH_PROT_IPV4)
+-			rc = !memcmp(addr_bits, ipatoe_bits,
+-				     min(32, ipatoe->mask_bits));
+-		else
+-			rc = !memcmp(addr_bits, ipatoe_bits,
+-				     min(128, ipatoe->mask_bits));
+-		if (rc)
+-			break;
+-	}
+-	/* invert? */
+-	if ((addr->proto == QETH_PROT_IPV4) && card->ipato.invert4)
+-		rc = !rc;
+-	else if ((addr->proto == QETH_PROT_IPV6) && card->ipato.invert6)
+-		rc = !rc;
+-
+-	return rc;
+-}
+-
+-/*
+- * VIPA related functions
+- */
+-int
+-qeth_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
+-	      const u8 *addr)
+-{
+-	struct qeth_ipaddr *ipaddr;
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	ipaddr = qeth_get_addr_buffer(proto);
+-	if (ipaddr){
+-		if (proto == QETH_PROT_IPV4){
+-			QETH_DBF_TEXT(trace, 2, "addvipa4");
+-			memcpy(&ipaddr->u.a4.addr, addr, 4);
+-			ipaddr->u.a4.mask = 0;
+-#ifdef CONFIG_QETH_IPV6
+-		} else if (proto == QETH_PROT_IPV6){
+-			QETH_DBF_TEXT(trace, 2, "addvipa6");
+-			memcpy(&ipaddr->u.a6.addr, addr, 16);
+-			ipaddr->u.a6.pfxlen = 0;
+-#endif
+-		}
+-		ipaddr->type = QETH_IP_TYPE_VIPA;
+-		ipaddr->set_flags = QETH_IPA_SETIP_VIPA_FLAG;
+-		ipaddr->del_flags = QETH_IPA_DELIP_VIPA_FLAG;
+-	} else
+-		return -ENOMEM;
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	if (__qeth_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
+-	    __qeth_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
+-		rc = -EEXIST;
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-	if (rc){
+-		PRINT_WARN("Cannot add VIPA. Address already exists!\n");
+-		return rc;
+-	}
+-	if (!qeth_add_ip(card, ipaddr))
+-		kfree(ipaddr);
+-	qeth_set_ip_addr_list(card);
+-	return rc;
+-}
+-
+-void
+-qeth_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
+-	      const u8 *addr)
+-{
+-	struct qeth_ipaddr *ipaddr;
+-
+-	ipaddr = qeth_get_addr_buffer(proto);
+-	if (ipaddr){
+-		if (proto == QETH_PROT_IPV4){
+-			QETH_DBF_TEXT(trace, 2, "delvipa4");
+-			memcpy(&ipaddr->u.a4.addr, addr, 4);
+-			ipaddr->u.a4.mask = 0;
+-#ifdef CONFIG_QETH_IPV6
+-		} else if (proto == QETH_PROT_IPV6){
+-			QETH_DBF_TEXT(trace, 2, "delvipa6");
+-			memcpy(&ipaddr->u.a6.addr, addr, 16);
+-			ipaddr->u.a6.pfxlen = 0;
+-#endif
+-		}
+-		ipaddr->type = QETH_IP_TYPE_VIPA;
+-	} else
+-		return;
+-	if (!qeth_delete_ip(card, ipaddr))
+-		kfree(ipaddr);
+-	qeth_set_ip_addr_list(card);
+-}
+-
+-/*
+- * proxy ARP related functions
+- */
+-int
+-qeth_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
+-	      const u8 *addr)
+-{
+-	struct qeth_ipaddr *ipaddr;
+-	unsigned long flags;
+-	int rc = 0;
+-
+-	ipaddr = qeth_get_addr_buffer(proto);
+-	if (ipaddr){
+-		if (proto == QETH_PROT_IPV4){
+-			QETH_DBF_TEXT(trace, 2, "addrxip4");
+-			memcpy(&ipaddr->u.a4.addr, addr, 4);
+-			ipaddr->u.a4.mask = 0;
+-#ifdef CONFIG_QETH_IPV6
+-		} else if (proto == QETH_PROT_IPV6){
+-			QETH_DBF_TEXT(trace, 2, "addrxip6");
+-			memcpy(&ipaddr->u.a6.addr, addr, 16);
+-			ipaddr->u.a6.pfxlen = 0;
+-#endif
+-		}
+-		ipaddr->type = QETH_IP_TYPE_RXIP;
+-		ipaddr->set_flags = QETH_IPA_SETIP_TAKEOVER_FLAG;
+-		ipaddr->del_flags = 0;
+-	} else
+-		return -ENOMEM;
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	if (__qeth_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
+-	    __qeth_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
+-		rc = -EEXIST;
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-	if (rc){
+-		PRINT_WARN("Cannot add RXIP. Address already exists!\n");
+-		return rc;
+-	}
+-	if (!qeth_add_ip(card, ipaddr))
+-		kfree(ipaddr);
+-	qeth_set_ip_addr_list(card);
+-	return 0;
+-}
+-
+-void
+-qeth_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
+-	      const u8 *addr)
+-{
+-	struct qeth_ipaddr *ipaddr;
+-
+-	ipaddr = qeth_get_addr_buffer(proto);
+-	if (ipaddr){
+-		if (proto == QETH_PROT_IPV4){
+-			QETH_DBF_TEXT(trace, 2, "addrxip4");
+-			memcpy(&ipaddr->u.a4.addr, addr, 4);
+-			ipaddr->u.a4.mask = 0;
+-#ifdef CONFIG_QETH_IPV6
+-		} else if (proto == QETH_PROT_IPV6){
+-			QETH_DBF_TEXT(trace, 2, "addrxip6");
+-			memcpy(&ipaddr->u.a6.addr, addr, 16);
+-			ipaddr->u.a6.pfxlen = 0;
+-#endif
+-		}
+-		ipaddr->type = QETH_IP_TYPE_RXIP;
+-	} else
+-		return;
+-	if (!qeth_delete_ip(card, ipaddr))
+-		kfree(ipaddr);
+-	qeth_set_ip_addr_list(card);
+-}
+-
+-/**
+- * IP event handler
+- */
+-static int
+-qeth_ip_event(struct notifier_block *this,
+-	      unsigned long event,void *ptr)
+-{
+-	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+-	struct net_device *dev =(struct net_device *) ifa->ifa_dev->dev;
+-	struct qeth_ipaddr *addr;
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(trace,3,"ipevent");
+-	card = qeth_get_card_from_dev(dev);
+-	if (!card)
+-		return NOTIFY_DONE;
+-	if (card->options.layer2)
+-		return NOTIFY_DONE;
+-
+-	addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
+-	if (addr != NULL) {
+-		addr->u.a4.addr = ifa->ifa_address;
+-		addr->u.a4.mask = ifa->ifa_mask;
+-		addr->type = QETH_IP_TYPE_NORMAL;
+-	} else
+-		goto out;
+-
+-	switch(event) {
+-	case NETDEV_UP:
+-		if (!qeth_add_ip(card, addr))
+-			kfree(addr);
+-		break;
+-	case NETDEV_DOWN:
+-		if (!qeth_delete_ip(card, addr))
+-			kfree(addr);
+-		break;
+-	default:
+-		break;
+-	}
+-	qeth_set_ip_addr_list(card);
+-out:
+-	return NOTIFY_DONE;
+-}
+-
+-static struct notifier_block qeth_ip_notifier = {
+-	qeth_ip_event,
+-	NULL,
+-};
+-
+-#ifdef CONFIG_QETH_IPV6
+-/**
+- * IPv6 event handler
+- */
+-static int
+-qeth_ip6_event(struct notifier_block *this,
+-	      unsigned long event,void *ptr)
+-{
+-
+-	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
+-	struct net_device *dev = (struct net_device *)ifa->idev->dev;
+-	struct qeth_ipaddr *addr;
+-	struct qeth_card *card;
+-
+-	QETH_DBF_TEXT(trace,3,"ip6event");
+-
+-	card = qeth_get_card_from_dev(dev);
+-	if (!card)
+-		return NOTIFY_DONE;
+-	if (!qeth_is_supported(card, IPA_IPV6))
+-		return NOTIFY_DONE;
+-
+-	addr = qeth_get_addr_buffer(QETH_PROT_IPV6);
+-	if (addr != NULL) {
+-		memcpy(&addr->u.a6.addr, &ifa->addr, sizeof(struct in6_addr));
+-		addr->u.a6.pfxlen = ifa->prefix_len;
+-		addr->type = QETH_IP_TYPE_NORMAL;
+-	} else
+-		goto out;
+-
+-	switch(event) {
+-	case NETDEV_UP:
+-		if (!qeth_add_ip(card, addr))
+-			kfree(addr);
+-		break;
+-	case NETDEV_DOWN:
+-		if (!qeth_delete_ip(card, addr))
+-			kfree(addr);
+-		break;
+-	default:
+-		break;
+-	}
+-	qeth_set_ip_addr_list(card);
+-out:
+-	return NOTIFY_DONE;
+-}
+-
+-static struct notifier_block qeth_ip6_notifier = {
+-	qeth_ip6_event,
+-	NULL,
+-};
+-#endif
+-
+-static int
+-__qeth_reboot_event_card(struct device *dev, void *data)
+-{
+-	struct qeth_card *card;
+-
+-	card = (struct qeth_card *) dev->driver_data;
+-	qeth_clear_ip_list(card, 0, 0);
+-	qeth_qdio_clear_card(card, 0);
+-	qeth_clear_qdio_buffers(card);
+-	return 0;
+-}
+-
+-static int
+-qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+-{
+-	int ret;
+-
+-	ret = driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+-				     __qeth_reboot_event_card);
+-	return ret ? NOTIFY_BAD : NOTIFY_DONE;
+-}
+-
+-
+-static struct notifier_block qeth_reboot_notifier = {
+-	qeth_reboot_event,
+-	NULL,
+-};
+-
+-static int
+-qeth_register_notifiers(void)
+-{
+-        int r;
+-
+-	QETH_DBF_TEXT(trace,5,"regnotif");
+-	if ((r = register_reboot_notifier(&qeth_reboot_notifier)))
+-		return r;
+-	if ((r = register_inetaddr_notifier(&qeth_ip_notifier)))
+-		goto out_reboot;
+-#ifdef CONFIG_QETH_IPV6
+-	if ((r = register_inet6addr_notifier(&qeth_ip6_notifier)))
+-		goto out_ipv4;
+-#endif
+-	return 0;
+-
+-#ifdef CONFIG_QETH_IPV6
+-out_ipv4:
+-	unregister_inetaddr_notifier(&qeth_ip_notifier);
+-#endif
+-out_reboot:
+-	unregister_reboot_notifier(&qeth_reboot_notifier);
+-	return r;
+-}
+-
+-/**
+- * unregister all event notifiers
+- */
+-static void
+-qeth_unregister_notifiers(void)
+-{
+-
+-	QETH_DBF_TEXT(trace,5,"unregnot");
+-	BUG_ON(unregister_reboot_notifier(&qeth_reboot_notifier));
+-	BUG_ON(unregister_inetaddr_notifier(&qeth_ip_notifier));
+-#ifdef CONFIG_QETH_IPV6
+-	BUG_ON(unregister_inet6addr_notifier(&qeth_ip6_notifier));
+-#endif /* QETH_IPV6 */
+-
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static int
+-qeth_ipv6_init(void)
+-{
+-	qeth_old_arp_constructor = arp_tbl.constructor;
+-	write_lock_bh(&arp_tbl.lock);
+-	arp_tbl.constructor = qeth_arp_constructor;
+-	write_unlock_bh(&arp_tbl.lock);
+-
+-	arp_direct_ops = (struct neigh_ops*)
+-		kmalloc(sizeof(struct neigh_ops), GFP_KERNEL);
+-	if (!arp_direct_ops)
+-		return -ENOMEM;
+-
+-	memcpy(arp_direct_ops, &arp_direct_ops_template,
+-	       sizeof(struct neigh_ops));
+-
+-	return 0;
+-}
+-
+-static void
+-qeth_ipv6_uninit(void)
+-{
+-	write_lock_bh(&arp_tbl.lock);
+-	arp_tbl.constructor = qeth_old_arp_constructor;
+-	write_unlock_bh(&arp_tbl.lock);
+-	kfree(arp_direct_ops);
+-}
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static void
+-qeth_sysfs_unregister(void)
+-{
+-	s390_root_dev_unregister(qeth_root_dev);
+-	qeth_remove_driver_attributes();
+-	ccw_driver_unregister(&qeth_ccw_driver);
+-	ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
+-}
+-
+-/**
+- * register qeth at sysfs
+- */
+-static int
+-qeth_sysfs_register(void)
+-{
+-	int rc;
+-
+-	rc = ccwgroup_driver_register(&qeth_ccwgroup_driver);
+-	if (rc)
+-		goto out;
+-
+-	rc = ccw_driver_register(&qeth_ccw_driver);
+-	if (rc)
+-		goto out_ccw_driver;
+-
+-	rc = qeth_create_driver_attributes();
+-	if (rc)
+-		goto out_qeth_attr;
+-
+-	qeth_root_dev = s390_root_dev_register("qeth");
+-	rc = IS_ERR(qeth_root_dev) ? PTR_ERR(qeth_root_dev) : 0;
+-	if (!rc)
+-		goto out;
+-
+-	qeth_remove_driver_attributes();
+-out_qeth_attr:
+-	ccw_driver_unregister(&qeth_ccw_driver);
+-out_ccw_driver:
+-	ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
+-out:
+-	return rc;
+-}
+-
+-/***
+- * init function
+- */
+-static int __init
+-qeth_init(void)
+-{
+-	int rc;
+-
+-	PRINT_INFO("loading %s\n", version);
+-
+-	INIT_LIST_HEAD(&qeth_card_list.list);
+-	INIT_LIST_HEAD(&qeth_notify_list);
+-	spin_lock_init(&qeth_notify_lock);
+-	rwlock_init(&qeth_card_list.rwlock);
+-
+-	rc = qeth_register_dbf_views();
+-	if (rc)
+-		goto out_err;
+-
+-	rc = qeth_sysfs_register();
+-	if (rc)
+-		goto out_dbf;
+-
+-#ifdef CONFIG_QETH_IPV6
+-	rc = qeth_ipv6_init();
+-	if (rc) {
+-		PRINT_ERR("Out of memory during ipv6 init code = %d\n", rc);
+-		goto out_sysfs;
+-	}
+-#endif /* QETH_IPV6 */
+-	rc = qeth_register_notifiers();
+-	if (rc)
+-		goto out_ipv6;
+-	rc = qeth_create_procfs_entries();
+-	if (rc)
+-		goto out_notifiers;
+-
+-	return rc;
+-
+-out_notifiers:
+-	qeth_unregister_notifiers();
+-out_ipv6:
+-#ifdef CONFIG_QETH_IPV6
+-	qeth_ipv6_uninit();
+-out_sysfs:
+-#endif /* QETH_IPV6 */
+-	qeth_sysfs_unregister();
+-out_dbf:
+-	qeth_unregister_dbf_views();
+-out_err:
+-	PRINT_ERR("Initialization failed with code %d\n", rc);
+-	return rc;
+-}
+-
+-static void
+-__exit qeth_exit(void)
+-{
+-	struct qeth_card *card, *tmp;
+-	unsigned long flags;
+-
+-	QETH_DBF_TEXT(trace,1, "cleanup.");
+-
+-	/*
+-	 * Weed would not need to clean up our devices here, because the
+-	 * common device layer calls qeth_remove_device for each device
+-	 * as soon as we unregister our driver (done in qeth_sysfs_unregister).
+-	 * But we do cleanup here so we can do a "soft" shutdown of our cards.
+-	 * qeth_remove_device called by the common device layer would otherwise
+-	 * do a "hard" shutdown (card->use_hard_stop is set to one in
+-	 * qeth_remove_device).
+-	 */
+-again:
+-	read_lock_irqsave(&qeth_card_list.rwlock, flags);
+-	list_for_each_entry_safe(card, tmp, &qeth_card_list.list, list){
+-		read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+-		qeth_set_offline(card->gdev);
+-		qeth_remove_device(card->gdev);
+-		goto again;
+-	}
+-	read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+-#ifdef CONFIG_QETH_IPV6
+-	qeth_ipv6_uninit();
+-#endif
+-	qeth_unregister_notifiers();
+-	qeth_remove_procfs_entries();
+-	qeth_sysfs_unregister();
+-	qeth_unregister_dbf_views();
+-	printk("qeth: removed\n");
+-}
+-
+-EXPORT_SYMBOL(qeth_osn_register);
+-EXPORT_SYMBOL(qeth_osn_deregister);
+-EXPORT_SYMBOL(qeth_osn_assist);
+-module_init(qeth_init);
+-module_exit(qeth_exit);
+-MODULE_AUTHOR("Frank Pavlic <fpavlic at de.ibm.com>");
+-MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
+-		                      "Copyright 2000,2003 IBM Corporation\n");
+-
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
+deleted file mode 100644
+index f29a4bc..0000000
+--- a/drivers/s390/net/qeth_mpc.c
++++ /dev/null
+@@ -1,269 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_mpc.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- *
+- * Copyright 2000,2003 IBM Corporation
+- * Author(s): Frank Pavlic <fpavlic at de.ibm.com>
+- * 	      Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#include <asm/cio.h>
+-#include "qeth_mpc.h"
+-
+-unsigned char IDX_ACTIVATE_READ[]={
+-	0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
+-	0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
+-	0x00,0x00,0x00,0x00, 0x00,0x00,0xc8,0xc1,
+-	0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00,
+-	0x00,0x00
+-};
+-
+-unsigned char IDX_ACTIVATE_WRITE[]={
+-	0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
+-	0x15,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
+-	0xff,0xff,0x00,0x00, 0x00,0x00,0xc8,0xc1,
+-	0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00,
+-	0x00,0x00
+-};
+-
+-unsigned char CM_ENABLE[]={
+-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x01,
+-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x63,
+-	0x10,0x00,0x00,0x01,
+-	0x00,0x00,0x00,0x00,
+-	0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00,
+-	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x23,
+-	0x00,0x00,0x23,0x05, 0x00,0x00,0x00,0x00,
+-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+-	0x01,0x00,0x00,0x23, 0x00,0x00,0x00,0x40,
+-	0x00,0x0c,0x41,0x02, 0x00,0x17,0x00,0x00,
+-	0x00,0x00,0x00,0x00,
+-	0x00,0x0b,0x04,0x01,
+-	0x7e,0x04,0x05,0x00, 0x01,0x01,0x0f,
+-	0x00,
+-	0x0c,0x04,0x02,0xff, 0xff,0xff,0xff,0xff,
+-	0xff,0xff,0xff
+-};
+-
+-unsigned char CM_SETUP[]={
+-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x02,
+-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x64,
+-	0x10,0x00,0x00,0x01,
+-	0x00,0x00,0x00,0x00,
+-	0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00,
+-	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x24,
+-	0x00,0x00,0x24,0x05, 0x00,0x00,0x00,0x00,
+-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+-	0x01,0x00,0x00,0x24, 0x00,0x00,0x00,0x40,
+-	0x00,0x0c,0x41,0x04, 0x00,0x18,0x00,0x00,
+-	0x00,0x00,0x00,0x00,
+-	0x00,0x09,0x04,0x04,
+-	0x05,0x00,0x01,0x01, 0x11,
+-	0x00,0x09,0x04,
+-	0x05,0x05,0x00,0x00, 0x00,0x00,
+-	0x00,0x06,
+-	0x04,0x06,0xc8,0x00
+-};
+-
+-unsigned char ULP_ENABLE[]={
+-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x03,
+-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6b,
+-	0x10,0x00,0x00,0x01,
+-	0x00,0x00,0x00,0x00,
+-	0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x01,
+-	0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x2b,
+-	0x00,0x00,0x2b,0x05, 0x20,0x01,0x00,0x00,
+-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+-	0x01,0x00,0x00,0x2b, 0x00,0x00,0x00,0x40,
+-	0x00,0x0c,0x41,0x02, 0x00,0x1f,0x00,0x00,
+-	0x00,0x00,0x00,0x00,
+-	0x00,0x0b,0x04,0x01,
+-	0x03,0x04,0x05,0x00, 0x01,0x01,0x12,
+-	0x00,
+-	0x14,0x04,0x0a,0x00, 0x20,0x00,0x00,0xff,
+-	0xff,0x00,0x08,0xc8, 0xe8,0xc4,0xf1,0xc7,
+-	0xf1,0x00,0x00
+-};
+-
+-unsigned char ULP_SETUP[]={
+-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x04,
+-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6c,
+-	0x10,0x00,0x00,0x01,
+-	0x00,0x00,0x00,0x00,
+-	0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x02,
+-	0x00,0x00,0x00,0x01, 0x00,0x24,0x00,0x2c,
+-	0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00,
+-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+-	0x01,0x00,0x00,0x2c, 0x00,0x00,0x00,0x40,
+-	0x00,0x0c,0x41,0x04, 0x00,0x20,0x00,0x00,
+-	0x00,0x00,0x00,0x00,
+-	0x00,0x09,0x04,0x04,
+-	0x05,0x00,0x01,0x01, 0x14,
+-	0x00,0x09,0x04,
+-	0x05,0x05,0x30,0x01, 0x00,0x00,
+-	0x00,0x06,
+-	0x04,0x06,0x40,0x00,
+-	0x00,0x08,0x04,0x0b,
+-	0x00,0x00,0x00,0x00
+-};
+-
+-unsigned char DM_ACT[]={
+-	0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x05,
+-	0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x55,
+-	0x10,0x00,0x00,0x01,
+-	0x00,0x00,0x00,0x00,
+-	0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x03,
+-	0x00,0x00,0x00,0x02, 0x00,0x24,0x00,0x15,
+-	0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00,
+-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+-	0x01,0x00,0x00,0x15, 0x00,0x00,0x00,0x40,
+-	0x00,0x0c,0x43,0x60, 0x00,0x09,0x00,0x00,
+-	0x00,0x00,0x00,0x00,
+-	0x00,0x09,0x04,0x04,
+-	0x05,0x40,0x01,0x01, 0x00
+-};
+-
+-unsigned char IPA_PDU_HEADER[]={
+-	0x00,0xe0,0x00,0x00, 0x77,0x77,0x77,0x77,
+-	0x00,0x00,0x00,0x14, 0x00,0x00,
+-		(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd))/256,
+-		(IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd))%256,
+-	0x10,0x00,0x00,0x01, 0x00,0x00,0x00,0x00,
+-	0xc1,0x03,0x00,0x01, 0x00,0x00,0x00,0x00,
+-	0x00,0x00,0x00,0x00, 0x00,0x24,
+-		sizeof(struct qeth_ipa_cmd)/256,
+-		sizeof(struct qeth_ipa_cmd)%256,
+-	0x00,
+-		sizeof(struct qeth_ipa_cmd)/256,
+-		sizeof(struct qeth_ipa_cmd)%256,
+-	0x05,
+-	0x77,0x77,0x77,0x77,
+-	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+-	0x01,0x00,
+-		sizeof(struct qeth_ipa_cmd)/256,
+-		sizeof(struct qeth_ipa_cmd)%256,
+-	0x00,0x00,0x00,0x40,
+-};
+-
+-unsigned char WRITE_CCW[]={
+-	0x01,CCW_FLAG_SLI,0,0,
+-	0,0,0,0
+-};
+-
+-unsigned char READ_CCW[]={
+-	0x02,CCW_FLAG_SLI,0,0,
+-	0,0,0,0
+-};
+-
+-
+-struct ipa_rc_msg {
+-	enum qeth_ipa_return_codes rc;
+-	char *msg;
+-};
+-
+-static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
+-	{IPA_RC_SUCCESS,		"success"},
+-	{IPA_RC_NOTSUPP,		"Command not supported"},
+-	{IPA_RC_IP_TABLE_FULL,		"Add Addr IP Table Full - ipv6"},
+-	{IPA_RC_UNKNOWN_ERROR,		"IPA command failed - reason unknown"},
+-	{IPA_RC_UNSUPPORTED_COMMAND,	"Command not supported"},
+-	{IPA_RC_DUP_IPV6_REMOTE,"ipv6 address already registered remote"},
+-	{IPA_RC_DUP_IPV6_HOME,		"ipv6 address already registered"},
+-	{IPA_RC_UNREGISTERED_ADDR,	"Address not registered"},
+-	{IPA_RC_NO_ID_AVAILABLE,	"No identifiers available"},
+-	{IPA_RC_ID_NOT_FOUND,		"Identifier not found"},
+-	{IPA_RC_INVALID_IP_VERSION,	"IP version incorrect"},
+-	{IPA_RC_LAN_FRAME_MISMATCH,	"LAN and frame mismatch"},
+-	{IPA_RC_L2_UNSUPPORTED_CMD,	"Unsupported layer 2 command"},
+-	{IPA_RC_L2_DUP_MAC,		"Duplicate MAC address"},
+-	{IPA_RC_L2_ADDR_TABLE_FULL,	"Layer2 address table full"},
+-	{IPA_RC_L2_DUP_LAYER3_MAC,	"Duplicate with layer 3 MAC"},
+-	{IPA_RC_L2_GMAC_NOT_FOUND,	"GMAC not found"},
+-	{IPA_RC_L2_MAC_NOT_FOUND,	"L2 mac address not found"},
+-	{IPA_RC_L2_INVALID_VLAN_ID,	"L2 invalid vlan id"},
+-	{IPA_RC_L2_DUP_VLAN_ID,		"L2 duplicate vlan id"},
+-	{IPA_RC_L2_VLAN_ID_NOT_FOUND,	"L2 vlan id not found"},
+-	{IPA_RC_DATA_MISMATCH,		"Data field mismatch (v4/v6 mixed)"},
+-	{IPA_RC_INVALID_MTU_SIZE,	"Invalid MTU size"},
+-	{IPA_RC_INVALID_LANTYPE,	"Invalid LAN type"},
+-	{IPA_RC_INVALID_LANNUM,		"Invalid LAN num"},
+-	{IPA_RC_DUPLICATE_IP_ADDRESS,	"Address already registered"},
+-	{IPA_RC_IP_ADDR_TABLE_FULL,	"IP address table full"},
+-	{IPA_RC_LAN_PORT_STATE_ERROR,	"LAN port state error"},
+-	{IPA_RC_SETIP_NO_STARTLAN,	"Setip no startlan received"},
+-	{IPA_RC_SETIP_ALREADY_RECEIVED,	"Setip already received"},
+-	{IPA_RC_IP_ADDR_ALREADY_USED,	"IP address already in use on LAN"},
+-	{IPA_RC_MULTICAST_FULL,		"No task available, multicast full"},
+-	{IPA_RC_SETIP_INVALID_VERSION,	"SETIP invalid IP version"},
+-	{IPA_RC_UNSUPPORTED_SUBCMD,	"Unsupported assist subcommand"},
+-	{IPA_RC_ARP_ASSIST_NO_ENABLE,	"Only partial success, no enable"},
+-	{IPA_RC_PRIMARY_ALREADY_DEFINED,"Primary already defined"},
+-	{IPA_RC_SECOND_ALREADY_DEFINED,	"Secondary already defined"},
+-	{IPA_RC_INVALID_SETRTG_INDICATOR,"Invalid SETRTG indicator"},
+-	{IPA_RC_MC_ADDR_ALREADY_DEFINED,"Multicast address already defined"},
+-	{IPA_RC_LAN_OFFLINE,		"STRTLAN_LAN_DISABLED - LAN offline"},
+-	{IPA_RC_INVALID_IP_VERSION2,	"Invalid IP version"},
+-	{IPA_RC_FFFF,			"Unknown Error"}
+-};
+-
+-
+-
+-char *
+-qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
+-{
+-	int x = 0;
+-	qeth_ipa_rc_msg[sizeof(qeth_ipa_rc_msg) /
+-			sizeof(struct ipa_rc_msg) - 1].rc = rc;
+-	while(qeth_ipa_rc_msg[x].rc != rc)
+-		x++;
+-	return qeth_ipa_rc_msg[x].msg;
+-}
+-
+-
+-struct ipa_cmd_names {
+-	enum qeth_ipa_cmds cmd;
+-	char *name;
+-};
+-
+-static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
+-	{IPA_CMD_STARTLAN,	"startlan"},
+-	{IPA_CMD_STOPLAN,	"stoplan"},
+-	{IPA_CMD_SETVMAC,	"setvmac"},
+-	{IPA_CMD_DELVMAC,	"delvmca"},
+-	{IPA_CMD_SETGMAC,	"setgmac"},
+-	{IPA_CMD_DELGMAC,	"delgmac"},
+-	{IPA_CMD_SETVLAN,	"setvlan"},
+-	{IPA_CMD_DELVLAN,	"delvlan"},
+-	{IPA_CMD_SETCCID,	"setccid"},
+-	{IPA_CMD_DELCCID,	"delccid"},
+-	{IPA_CMD_MODCCID,	"setip"},
+-	{IPA_CMD_SETIP,		"setip"},
+-	{IPA_CMD_QIPASSIST,	"qipassist"},
+-	{IPA_CMD_SETASSPARMS,	"setassparms"},
+-	{IPA_CMD_SETIPM,	"setipm"},
+-	{IPA_CMD_DELIPM,	"delipm"},
+-	{IPA_CMD_SETRTG,	"setrtg"},
+-	{IPA_CMD_DELIP,		"delip"},
+-	{IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
+-	{IPA_CMD_SET_DIAG_ASS,	"set_diag_ass"},
+-	{IPA_CMD_CREATE_ADDR,	"create_addr"},
+-	{IPA_CMD_DESTROY_ADDR,	"destroy_addr"},
+-	{IPA_CMD_REGISTER_LOCAL_ADDR,	"register_local_addr"},
+-	{IPA_CMD_UNREGISTER_LOCAL_ADDR,	"unregister_local_addr"},
+-	{IPA_CMD_UNKNOWN,	"unknown"},
+-};
+-
+-char *
+-qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
+-{
+-	int x = 0;
+-	qeth_ipa_cmd_names[
+-		sizeof(qeth_ipa_cmd_names)/
+-			sizeof(struct ipa_cmd_names)-1].cmd = cmd;
+-	while(qeth_ipa_cmd_names[x].cmd != cmd)
+-		x++;
+-	return qeth_ipa_cmd_names[x].name;
+-}
+-
+-
+diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
+deleted file mode 100644
+index 6de2da5..0000000
+--- a/drivers/s390/net/qeth_mpc.h
++++ /dev/null
+@@ -1,583 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_mpc.h
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- *
+- * Copyright 2000,2003 IBM Corporation
+- * Author(s): Utz Bacher <utz.bacher at de.ibm.com>
+- *            Thomas Spatzier <tspat at de.ibm.com>
+- *            Frank Pavlic <fpavlic at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_MPC_H__
+-#define __QETH_MPC_H__
+-
+-#include <asm/qeth.h>
+-
+-#define IPA_PDU_HEADER_SIZE	0x40
+-#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e)
+-#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26)
+-#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer+0x29)
+-#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer+0x3a)
+-
+-extern unsigned char IPA_PDU_HEADER[];
+-#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer+0x2c)
+-
+-#define IPA_CMD_LENGTH	(IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
+-
+-#define QETH_SEQ_NO_LENGTH	4
+-#define QETH_MPC_TOKEN_LENGTH	4
+-#define QETH_MCL_LENGTH		4
+-#define OSA_ADDR_LEN		6
+-
+-#define QETH_TIMEOUT		(10 * HZ)
+-#define QETH_IPA_TIMEOUT	(45 * HZ)
+-#define QETH_IDX_COMMAND_SEQNO	0xffff0000
+-#define SR_INFO_LEN		16
+-
+-#define QETH_CLEAR_CHANNEL_PARM	-10
+-#define QETH_HALT_CHANNEL_PARM	-11
+-#define QETH_RCD_PARM -12
+-
+-/*****************************************************************************/
+-/* IP Assist related definitions                                             */
+-/*****************************************************************************/
+-#define IPA_CMD_INITIATOR_HOST  0x00
+-#define IPA_CMD_INITIATOR_OSA   0x01
+-#define IPA_CMD_INITIATOR_HOST_REPLY  0x80
+-#define IPA_CMD_INITIATOR_OSA_REPLY   0x81
+-#define IPA_CMD_PRIM_VERSION_NO 0x01
+-
+-enum qeth_card_types {
+-	QETH_CARD_TYPE_UNKNOWN = 0,
+-	QETH_CARD_TYPE_OSAE    = 10,
+-	QETH_CARD_TYPE_IQD     = 1234,
+-	QETH_CARD_TYPE_OSN     = 11,
+-};
+-
+-#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
+-/* only the first two bytes are looked at in qeth_get_cardname_short */
+-enum qeth_link_types {
+-	QETH_LINK_TYPE_FAST_ETH     = 0x01,
+-	QETH_LINK_TYPE_HSTR         = 0x02,
+-	QETH_LINK_TYPE_GBIT_ETH     = 0x03,
+-	QETH_LINK_TYPE_OSN          = 0x04,
+-	QETH_LINK_TYPE_10GBIT_ETH   = 0x10,
+-	QETH_LINK_TYPE_LANE_ETH100  = 0x81,
+-	QETH_LINK_TYPE_LANE_TR      = 0x82,
+-	QETH_LINK_TYPE_LANE_ETH1000 = 0x83,
+-	QETH_LINK_TYPE_LANE         = 0x88,
+-	QETH_LINK_TYPE_ATM_NATIVE   = 0x90,
+-};
+-
+-enum qeth_tr_macaddr_modes {
+-	QETH_TR_MACADDR_NONCANONICAL = 0,
+-	QETH_TR_MACADDR_CANONICAL    = 1,
+-};
+-
+-enum qeth_tr_broadcast_modes {
+-	QETH_TR_BROADCAST_ALLRINGS = 0,
+-	QETH_TR_BROADCAST_LOCAL    = 1,
+-};
+-
+-/* these values match CHECKSUM_* in include/linux/skbuff.h */
+-enum qeth_checksum_types {
+-	SW_CHECKSUMMING = 0, /* TODO: set to bit flag used in IPA Command */
+-	HW_CHECKSUMMING = 1,
+-	NO_CHECKSUMMING = 2,
+-};
+-#define QETH_CHECKSUM_DEFAULT SW_CHECKSUMMING
+-
+-/*
+- * Routing stuff
+- */
+-#define RESET_ROUTING_FLAG 0x10 /* indicate that routing type shall be set */
+-enum qeth_routing_types {
+-	NO_ROUTER		= 0, /* TODO: set to bit flag used in IPA Command */
+-	PRIMARY_ROUTER		= 1,
+-	SECONDARY_ROUTER	= 2,
+-	MULTICAST_ROUTER	= 3,
+-	PRIMARY_CONNECTOR	= 4,
+-	SECONDARY_CONNECTOR	= 5,
+-};
+-
+-/* IPA Commands */
+-enum qeth_ipa_cmds {
+-	IPA_CMD_STARTLAN		= 0x01,
+-	IPA_CMD_STOPLAN			= 0x02,
+-	IPA_CMD_SETVMAC			= 0x21,
+-	IPA_CMD_DELVMAC			= 0x22,
+-	IPA_CMD_SETGMAC			= 0x23,
+-	IPA_CMD_DELGMAC			= 0x24,
+-	IPA_CMD_SETVLAN			= 0x25,
+-	IPA_CMD_DELVLAN			= 0x26,
+-	IPA_CMD_SETCCID			= 0x41,
+-	IPA_CMD_DELCCID			= 0x42,
+-	IPA_CMD_MODCCID			= 0x43,
+-	IPA_CMD_SETIP			= 0xb1,
+-	IPA_CMD_QIPASSIST		= 0xb2,
+-	IPA_CMD_SETASSPARMS		= 0xb3,
+-	IPA_CMD_SETIPM			= 0xb4,
+-	IPA_CMD_DELIPM			= 0xb5,
+-	IPA_CMD_SETRTG			= 0xb6,
+-	IPA_CMD_DELIP			= 0xb7,
+-	IPA_CMD_SETADAPTERPARMS		= 0xb8,
+-	IPA_CMD_SET_DIAG_ASS		= 0xb9,
+-	IPA_CMD_CREATE_ADDR		= 0xc3,
+-	IPA_CMD_DESTROY_ADDR		= 0xc4,
+-	IPA_CMD_REGISTER_LOCAL_ADDR	= 0xd1,
+-	IPA_CMD_UNREGISTER_LOCAL_ADDR	= 0xd2,
+-	IPA_CMD_UNKNOWN			= 0x00
+-};
+-
+-enum qeth_ip_ass_cmds {
+-	IPA_CMD_ASS_START	= 0x0001,
+-	IPA_CMD_ASS_STOP	= 0x0002,
+-	IPA_CMD_ASS_CONFIGURE	= 0x0003,
+-	IPA_CMD_ASS_ENABLE	= 0x0004,
+-};
+-
+-enum qeth_arp_process_subcmds {
+-	IPA_CMD_ASS_ARP_SET_NO_ENTRIES	= 0x0003,
+-	IPA_CMD_ASS_ARP_QUERY_CACHE	= 0x0004,
+-	IPA_CMD_ASS_ARP_ADD_ENTRY	= 0x0005,
+-	IPA_CMD_ASS_ARP_REMOVE_ENTRY	= 0x0006,
+-	IPA_CMD_ASS_ARP_FLUSH_CACHE	= 0x0007,
+-	IPA_CMD_ASS_ARP_QUERY_INFO	= 0x0104,
+-	IPA_CMD_ASS_ARP_QUERY_STATS	= 0x0204,
+-};
+-
+-
+-/* Return Codes for IPA Commands
+- * according to OSA card Specs */
+-
+-enum qeth_ipa_return_codes {
+-	IPA_RC_SUCCESS			= 0x0000,
+-	IPA_RC_NOTSUPP			= 0x0001,
+-	IPA_RC_IP_TABLE_FULL		= 0x0002,
+-	IPA_RC_UNKNOWN_ERROR		= 0x0003,
+-	IPA_RC_UNSUPPORTED_COMMAND	= 0x0004,
+-	IPA_RC_DUP_IPV6_REMOTE		= 0x0008,
+-	IPA_RC_DUP_IPV6_HOME		= 0x0010,
+-	IPA_RC_UNREGISTERED_ADDR	= 0x0011,
+-	IPA_RC_NO_ID_AVAILABLE		= 0x0012,
+-	IPA_RC_ID_NOT_FOUND		= 0x0013,
+-	IPA_RC_INVALID_IP_VERSION	= 0x0020,
+-	IPA_RC_LAN_FRAME_MISMATCH	= 0x0040,
+-	IPA_RC_L2_UNSUPPORTED_CMD	= 0x2003,
+-	IPA_RC_L2_DUP_MAC		= 0x2005,
+-	IPA_RC_L2_ADDR_TABLE_FULL	= 0x2006,
+-	IPA_RC_L2_DUP_LAYER3_MAC	= 0x200a,
+-	IPA_RC_L2_GMAC_NOT_FOUND	= 0x200b,
+-	IPA_RC_L2_MAC_NOT_FOUND		= 0x2010,
+-	IPA_RC_L2_INVALID_VLAN_ID	= 0x2015,
+-	IPA_RC_L2_DUP_VLAN_ID		= 0x2016,
+-	IPA_RC_L2_VLAN_ID_NOT_FOUND	= 0x2017,
+-	IPA_RC_DATA_MISMATCH		= 0xe001,
+-	IPA_RC_INVALID_MTU_SIZE		= 0xe002,
+-	IPA_RC_INVALID_LANTYPE		= 0xe003,
+-	IPA_RC_INVALID_LANNUM		= 0xe004,
+-	IPA_RC_DUPLICATE_IP_ADDRESS	= 0xe005,
+-	IPA_RC_IP_ADDR_TABLE_FULL	= 0xe006,
+-	IPA_RC_LAN_PORT_STATE_ERROR	= 0xe007,
+-	IPA_RC_SETIP_NO_STARTLAN	= 0xe008,
+-	IPA_RC_SETIP_ALREADY_RECEIVED	= 0xe009,
+-	IPA_RC_IP_ADDR_ALREADY_USED	= 0xe00a,
+-	IPA_RC_MULTICAST_FULL		= 0xe00b,
+-	IPA_RC_SETIP_INVALID_VERSION	= 0xe00d,
+-	IPA_RC_UNSUPPORTED_SUBCMD	= 0xe00e,
+-	IPA_RC_ARP_ASSIST_NO_ENABLE	= 0xe00f,
+-	IPA_RC_PRIMARY_ALREADY_DEFINED	= 0xe010,
+-	IPA_RC_SECOND_ALREADY_DEFINED	= 0xe011,
+-	IPA_RC_INVALID_SETRTG_INDICATOR	= 0xe012,
+-	IPA_RC_MC_ADDR_ALREADY_DEFINED	= 0xe013,
+-	IPA_RC_LAN_OFFLINE		= 0xe080,
+-	IPA_RC_INVALID_IP_VERSION2	= 0xf001,
+-	IPA_RC_FFFF			= 0xffff
+-};
+-
+-/* IPA function flags; each flag marks availability of respective function */
+-enum qeth_ipa_funcs {
+-	IPA_ARP_PROCESSING      = 0x00000001L,
+-	IPA_INBOUND_CHECKSUM    = 0x00000002L,
+-	IPA_OUTBOUND_CHECKSUM   = 0x00000004L,
+-	IPA_IP_FRAGMENTATION    = 0x00000008L,
+-	IPA_FILTERING           = 0x00000010L,
+-	IPA_IPV6                = 0x00000020L,
+-	IPA_MULTICASTING        = 0x00000040L,
+-	IPA_IP_REASSEMBLY       = 0x00000080L,
+-	IPA_QUERY_ARP_COUNTERS  = 0x00000100L,
+-	IPA_QUERY_ARP_ADDR_INFO = 0x00000200L,
+-	IPA_SETADAPTERPARMS     = 0x00000400L,
+-	IPA_VLAN_PRIO           = 0x00000800L,
+-	IPA_PASSTHRU            = 0x00001000L,
+-	IPA_FLUSH_ARP_SUPPORT   = 0x00002000L,
+-	IPA_FULL_VLAN           = 0x00004000L,
+-	IPA_INBOUND_PASSTHRU    = 0x00008000L,
+-	IPA_SOURCE_MAC          = 0x00010000L,
+-	IPA_OSA_MC_ROUTER       = 0x00020000L,
+-	IPA_QUERY_ARP_ASSIST	= 0x00040000L,
+-	IPA_INBOUND_TSO         = 0x00080000L,
+-	IPA_OUTBOUND_TSO        = 0x00100000L,
+-};
+-
+-/* SETIP/DELIP IPA Command: ***************************************************/
+-enum qeth_ipa_setdelip_flags {
+-	QETH_IPA_SETDELIP_DEFAULT          = 0x00L, /* default */
+-	QETH_IPA_SETIP_VIPA_FLAG           = 0x01L, /* no grat. ARP */
+-	QETH_IPA_SETIP_TAKEOVER_FLAG       = 0x02L, /* nofail on grat. ARP */
+-	QETH_IPA_DELIP_ADDR_2_B_TAKEN_OVER = 0x20L,
+-	QETH_IPA_DELIP_VIPA_FLAG           = 0x40L,
+-	QETH_IPA_DELIP_ADDR_NEEDS_SETIP    = 0x80L,
+-};
+-
+-/* SETADAPTER IPA Command: ****************************************************/
+-enum qeth_ipa_setadp_cmd {
+-	IPA_SETADP_QUERY_COMMANDS_SUPPORTED	= 0x01,
+-	IPA_SETADP_ALTER_MAC_ADDRESS		= 0x02,
+-	IPA_SETADP_ADD_DELETE_GROUP_ADDRESS	= 0x04,
+-	IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR	= 0x08,
+-	IPA_SETADP_SET_ADDRESSING_MODE		= 0x10,
+-	IPA_SETADP_SET_CONFIG_PARMS		= 0x20,
+-	IPA_SETADP_SET_CONFIG_PARMS_EXTENDED	= 0x40,
+-	IPA_SETADP_SET_BROADCAST_MODE		= 0x80,
+-	IPA_SETADP_SEND_OSA_MESSAGE		= 0x0100,
+-	IPA_SETADP_SET_SNMP_CONTROL		= 0x0200,
+-	IPA_SETADP_QUERY_CARD_INFO		= 0x0400,
+-	IPA_SETADP_SET_PROMISC_MODE		= 0x0800,
+-};
+-enum qeth_ipa_mac_ops {
+-	CHANGE_ADDR_READ_MAC		= 0,
+-	CHANGE_ADDR_REPLACE_MAC		= 1,
+-	CHANGE_ADDR_ADD_MAC		= 2,
+-	CHANGE_ADDR_DEL_MAC		= 4,
+-	CHANGE_ADDR_RESET_MAC		= 8,
+-};
+-enum qeth_ipa_addr_ops {
+-	CHANGE_ADDR_READ_ADDR		= 0,
+-	CHANGE_ADDR_ADD_ADDR		= 1,
+-	CHANGE_ADDR_DEL_ADDR		= 2,
+-	CHANGE_ADDR_FLUSH_ADDR_TABLE	= 4,
+-};
+-enum qeth_ipa_promisc_modes {
+-	SET_PROMISC_MODE_OFF		= 0,
+-	SET_PROMISC_MODE_ON		= 1,
+-};
+-
+-/* (SET)DELIP(M) IPA stuff ***************************************************/
+-struct qeth_ipacmd_setdelip4 {
+-	__u8   ip_addr[4];
+-	__u8   mask[4];
+-	__u32  flags;
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_setdelip6 {
+-	__u8   ip_addr[16];
+-	__u8   mask[16];
+-	__u32  flags;
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_setdelipm {
+-	__u8 mac[6];
+-	__u8 padding[2];
+-	__u8 ip6[12];
+-	__u8 ip4[4];
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_layer2setdelmac {
+-	__u32 mac_length;
+-	__u8 mac[6];
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_layer2setdelvlan {
+-	__u16 vlan_id;
+-} __attribute__ ((packed));
+-
+-
+-struct qeth_ipacmd_setassparms_hdr {
+-	__u32 assist_no;
+-	__u16 length;
+-	__u16 command_code;
+-	__u16 return_code;
+-	__u8 number_of_replies;
+-	__u8 seq_no;
+-} __attribute__((packed));
+-
+-struct qeth_arp_query_data {
+-	__u16 request_bits;
+-	__u16 reply_bits;
+-	__u32 no_entries;
+-	char data;
+-} __attribute__((packed));
+-
+-/* used as parameter for arp_query reply */
+-struct qeth_arp_query_info {
+-	__u32 udata_len;
+-	__u16 mask_bits;
+-	__u32 udata_offset;
+-	__u32 no_entries;
+-	char *udata;
+-};
+-
+-/* SETASSPARMS IPA Command: */
+-struct qeth_ipacmd_setassparms {
+-	struct qeth_ipacmd_setassparms_hdr hdr;
+-	union {
+-		__u32 flags_32bit;
+-		struct qeth_arp_cache_entry add_arp_entry;
+-		struct qeth_arp_query_data query_arp;
+-		__u8 ip[16];
+-	} data;
+-} __attribute__ ((packed));
+-
+-
+-/* SETRTG IPA Command:    ****************************************************/
+-struct qeth_set_routing {
+-	__u8 type;
+-};
+-
+-/* SETADAPTERPARMS IPA Command:    *******************************************/
+-struct qeth_query_cmds_supp {
+-	__u32 no_lantypes_supp;
+-	__u8 lan_type;
+-	__u8 reserved1[3];
+-	__u32 supported_cmds;
+-	__u8 reserved2[8];
+-} __attribute__ ((packed));
+-
+-struct qeth_change_addr {
+-	__u32 cmd;
+-	__u32 addr_size;
+-	__u32 no_macs;
+-	__u8 addr[OSA_ADDR_LEN];
+-} __attribute__ ((packed));
+-
+-
+-struct qeth_snmp_cmd {
+-	__u8  token[16];
+-	__u32 request;
+-	__u32 interface;
+-	__u32 returncode;
+-	__u32 firmwarelevel;
+-	__u32 seqno;
+-	__u8  data;
+-} __attribute__ ((packed));
+-
+-struct qeth_snmp_ureq_hdr {
+-	__u32   data_len;
+-	__u32   req_len;
+-	__u32   reserved1;
+-	__u32   reserved2;
+-} __attribute__ ((packed));
+-
+-struct qeth_snmp_ureq {
+-	struct qeth_snmp_ureq_hdr hdr;
+-	struct qeth_snmp_cmd cmd;
+-} __attribute__((packed));
+-
+-struct qeth_ipacmd_setadpparms_hdr {
+-	__u32 supp_hw_cmds;
+-	__u32 reserved1;
+-	__u16 cmdlength;
+-	__u16 reserved2;
+-	__u32 command_code;
+-	__u16 return_code;
+-	__u8  used_total;
+-	__u8  seq_no;
+-	__u32 reserved3;
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_setadpparms {
+-	struct qeth_ipacmd_setadpparms_hdr hdr;
+-	union {
+-		struct qeth_query_cmds_supp query_cmds_supp;
+-		struct qeth_change_addr change_addr;
+-		struct qeth_snmp_cmd snmp;
+-		__u32 mode;
+-	} data;
+-} __attribute__ ((packed));
+-
+-/* IPFRAME IPA Command:    ***************************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* ADD_ADDR_ENTRY IPA Command:    ********************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* DELETE_ADDR_ENTRY IPA Command:    *****************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* CREATE_ADDR IPA Command:    ***********************************************/
+-struct qeth_create_destroy_address {
+-	__u8 unique_id[8];
+-} __attribute__ ((packed));
+-
+-/* REGISTER_LOCAL_ADDR IPA Command:    ***************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* UNREGISTER_LOCAL_ADDR IPA Command:    *************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* Header for each IPA command */
+-struct qeth_ipacmd_hdr {
+-	__u8   command;
+-	__u8   initiator;
+-	__u16  seqno;
+-	__u16  return_code;
+-	__u8   adapter_type;
+-	__u8   rel_adapter_no;
+-	__u8   prim_version_no;
+-	__u8   param_count;
+-	__u16  prot_version;
+-	__u32  ipa_supported;
+-	__u32  ipa_enabled;
+-} __attribute__ ((packed));
+-
+-/* The IPA command itself */
+-struct qeth_ipa_cmd {
+-	struct qeth_ipacmd_hdr hdr;
+-	union {
+-		struct qeth_ipacmd_setdelip4		setdelip4;
+-		struct qeth_ipacmd_setdelip6		setdelip6;
+-		struct qeth_ipacmd_setdelipm		setdelipm;
+-		struct qeth_ipacmd_setassparms		setassparms;
+-		struct qeth_ipacmd_layer2setdelmac	setdelmac;
+-		struct qeth_ipacmd_layer2setdelvlan	setdelvlan;
+-		struct qeth_create_destroy_address	create_destroy_addr;
+-		struct qeth_ipacmd_setadpparms		setadapterparms;
+-		struct qeth_set_routing			setrtg;
+-	} data;
+-} __attribute__ ((packed));
+-
+-/*
+- * special command for ARP processing.
+- * this is not included in setassparms command before, because we get
+- * problem with the size of struct qeth_ipacmd_setassparms otherwise
+- */
+-enum qeth_ipa_arp_return_codes {
+-	QETH_IPA_ARP_RC_SUCCESS      = 0x0000,
+-	QETH_IPA_ARP_RC_FAILED       = 0x0001,
+-	QETH_IPA_ARP_RC_NOTSUPP      = 0x0002,
+-	QETH_IPA_ARP_RC_OUT_OF_RANGE = 0x0003,
+-	QETH_IPA_ARP_RC_Q_NOTSUPP    = 0x0004,
+-	QETH_IPA_ARP_RC_Q_NO_DATA    = 0x0008,
+-};
+-
+-
+-extern char *
+-qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
+-extern char *
+-qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
+-
+-#define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
+-			       sizeof(struct qeth_ipacmd_setassparms_hdr))
+-#define QETH_IPA_ARP_DATA_POS(buffer) (buffer + IPA_PDU_HEADER_SIZE + \
+-				       QETH_SETASS_BASE_LEN)
+-#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
+-			      sizeof(struct qeth_ipacmd_setadpparms_hdr))
+-#define QETH_SNMP_SETADP_CMDLENGTH 16
+-
+-#define QETH_ARP_DATA_SIZE 3968
+-#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
+-/* Helper functions */
+-#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
+-			   (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
+-
+-/*****************************************************************************/
+-/* END OF   IP Assist related definitions                                    */
+-/*****************************************************************************/
+-
+-
+-extern unsigned char WRITE_CCW[];
+-extern unsigned char READ_CCW[];
+-
+-extern unsigned char CM_ENABLE[];
+-#define CM_ENABLE_SIZE 0x63
+-#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer+0x2c)
+-#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53)
+-#define QETH_CM_ENABLE_USER_DATA(buffer) (buffer+0x5b)
+-
+-#define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) \
+-		(PDU_ENCAPSULATION(buffer)+ 0x13)
+-
+-
+-extern unsigned char CM_SETUP[];
+-#define CM_SETUP_SIZE 0x64
+-#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer+0x2c)
+-#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51)
+-#define QETH_CM_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a)
+-
+-#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) \
+-		(PDU_ENCAPSULATION(buffer) + 0x1a)
+-
+-extern unsigned char ULP_ENABLE[];
+-#define ULP_ENABLE_SIZE 0x6b
+-#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer+0x61)
+-#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer+0x2c)
+-#define QETH_ULP_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53)
+-#define QETH_ULP_ENABLE_PORTNAME_AND_LL(buffer) (buffer+0x62)
+-#define QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer) \
+-		(PDU_ENCAPSULATION(buffer) + 0x13)
+-#define QETH_ULP_ENABLE_RESP_MAX_MTU(buffer) \
+-		(PDU_ENCAPSULATION(buffer)+ 0x1f)
+-#define QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer) \
+-		(PDU_ENCAPSULATION(buffer) + 0x17)
+-#define QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer) \
+-		(PDU_ENCAPSULATION(buffer)+ 0x2b)
+-/* Layer 2 defintions */
+-#define QETH_PROT_LAYER2 0x08
+-#define QETH_PROT_TCPIP  0x03
+-#define QETH_PROT_OSN2   0x0a
+-#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
+-#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
+-
+-extern unsigned char ULP_SETUP[];
+-#define ULP_SETUP_SIZE 0x6c
+-#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer+0x2c)
+-#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51)
+-#define QETH_ULP_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a)
+-#define QETH_ULP_SETUP_CUA(buffer) (buffer+0x68)
+-#define QETH_ULP_SETUP_REAL_DEVADDR(buffer) (buffer+0x6a)
+-
+-#define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) \
+-		(PDU_ENCAPSULATION(buffer)+0x1a)
+-
+-
+-extern unsigned char DM_ACT[];
+-#define DM_ACT_SIZE 0x55
+-#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer+0x2c)
+-#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer+0x51)
+-
+-
+-
+-#define QETH_TRANSPORT_HEADER_SEQ_NO(buffer) (buffer+4)
+-#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer+0x1c)
+-#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer+0x20)
+-
+-extern unsigned char IDX_ACTIVATE_READ[];
+-extern unsigned char IDX_ACTIVATE_WRITE[];
+-
+-#define IDX_ACTIVATE_SIZE	0x22
+-#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer+0x0c)
+-#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b]&0x80)
+-#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer+0x10)
+-#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer+0x16)
+-#define QETH_IDX_ACT_QDIO_DEV_CUA(buffer) (buffer+0x1e)
+-#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer+0x20)
+-#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08]&3)==2)
+-#define QETH_IDX_REPLY_LEVEL(buffer) (buffer+0x12)
+-#define QETH_IDX_ACT_CAUSE_CODE(buffer) (buffer)[0x09]
+-
+-#define PDU_ENCAPSULATION(buffer) \
+-	(buffer + *(buffer + (*(buffer+0x0b)) + \
+-	 *(buffer + *(buffer+0x0b)+0x11) +0x07))
+-
+-#define IS_IPA(buffer) \
+-	((buffer) && \
+-	 ( *(buffer + ((*(buffer+0x0b))+4) )==0xc1) )
+-
+-#define ADDR_FRAME_TYPE_DIX 1
+-#define ADDR_FRAME_TYPE_802_3 2
+-#define ADDR_FRAME_TYPE_TR_WITHOUT_SR 0x10
+-#define ADDR_FRAME_TYPE_TR_WITH_SR 0x20
+-
+-#endif
+diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
+deleted file mode 100644
+index 46ecd03..0000000
+--- a/drivers/s390/net/qeth_proc.c
++++ /dev/null
+@@ -1,316 +0,0 @@
+-/*
+- *
+- * linux/drivers/s390/net/qeth_fs.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- * This file contains code related to procfs.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/proc_fs.h>
+-#include <linux/seq_file.h>
+-#include <linux/list.h>
+-#include <linux/rwsem.h>
+-
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_fs.h"
+-
+-/***** /proc/qeth *****/
+-#define QETH_PROCFILE_NAME "qeth"
+-static struct proc_dir_entry *qeth_procfile;
+-
+-static int
+-qeth_procfile_seq_match(struct device *dev, void *data)
+-{
+-	return(dev ? 1 : 0);
+-}
+-
+-static void *
+-qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
+-{
+-	struct device *dev = NULL;
+-	loff_t nr = 0;
+-
+-	if (*offset == 0)
+-		return SEQ_START_TOKEN;
+-	while (1) {
+-		dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+-					 NULL, qeth_procfile_seq_match);
+-		if (++nr == *offset)
+-			break;
+-		put_device(dev);
+-	}
+-	return dev;
+-}
+-
+-static void
+-qeth_procfile_seq_stop(struct seq_file *s, void* it)
+-{
+-}
+-
+-static void *
+-qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
+-{
+-	struct device *prev, *next;
+-
+-	if (it == SEQ_START_TOKEN)
+-		prev = NULL;
+-	else
+-		prev = (struct device *) it;
+-	next = driver_find_device(&qeth_ccwgroup_driver.driver,
+-				  prev, NULL, qeth_procfile_seq_match);
+-	(*offset)++;
+-	return (void *) next;
+-}
+-
+-static inline const char *
+-qeth_get_router_str(struct qeth_card *card, int ipv)
+-{
+-	enum qeth_routing_types routing_type = NO_ROUTER;
+-
+-	if (ipv == 4) {
+-		routing_type = card->options.route4.type;
+-	} else {
+-#ifdef CONFIG_QETH_IPV6
+-		routing_type = card->options.route6.type;
+-#else
+-		return "n/a";
+-#endif /* CONFIG_QETH_IPV6 */
+-	}
+-
+-	switch (routing_type){
+-	case PRIMARY_ROUTER:
+-		return "pri";
+-	case SECONDARY_ROUTER:
+-		return "sec";
+-	case MULTICAST_ROUTER:
+-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+-			return "mc+";
+-		return "mc";
+-	case PRIMARY_CONNECTOR:
+-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+-			return "p+c";
+-		return "p.c";
+-	case SECONDARY_CONNECTOR:
+-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+-			return "s+c";
+-		return "s.c";
+-	default:   /* NO_ROUTER */
+-		return "no";
+-	}
+-}
+-
+-static int
+-qeth_procfile_seq_show(struct seq_file *s, void *it)
+-{
+-	struct device *device;
+-	struct qeth_card *card;
+-	char tmp[12]; /* for qeth_get_prioq_str */
+-
+-	if (it == SEQ_START_TOKEN){
+-		seq_printf(s, "devices                    CHPID interface  "
+-		              "cardtype       port chksum prio-q'ing rtr4 "
+-			      "rtr6 fsz   cnt\n");
+-		seq_printf(s, "-------------------------- ----- ---------- "
+-			      "-------------- ---- ------ ---------- ---- "
+-			      "---- ----- -----\n");
+-	} else {
+-		device = (struct device *) it;
+-		card = device->driver_data;
+-		seq_printf(s, "%s/%s/%s x%02X   %-10s %-14s %-4i ",
+-				CARD_RDEV_ID(card),
+-				CARD_WDEV_ID(card),
+-				CARD_DDEV_ID(card),
+-				card->info.chpid,
+-				QETH_CARD_IFNAME(card),
+-				qeth_get_cardname_short(card),
+-				card->info.portno);
+-		if (card->lan_online)
+-			seq_printf(s, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
+-					qeth_get_checksum_str(card),
+-					qeth_get_prioq_str(card, tmp),
+-					qeth_get_router_str(card, 4),
+-					qeth_get_router_str(card, 6),
+-					qeth_get_bufsize_str(card),
+-					card->qdio.in_buf_pool.buf_count);
+-		else
+-			seq_printf(s, "  +++ LAN OFFLINE +++\n");
+-		put_device(device);
+-	}
+-	return 0;
+-}
+-
+-static const struct seq_operations qeth_procfile_seq_ops = {
+-	.start = qeth_procfile_seq_start,
+-	.stop  = qeth_procfile_seq_stop,
+-	.next  = qeth_procfile_seq_next,
+-	.show  = qeth_procfile_seq_show,
+-};
+-
+-static int
+-qeth_procfile_open(struct inode *inode, struct file *file)
+-{
+-	return seq_open(file, &qeth_procfile_seq_ops);
+-}
+-
+-static const struct file_operations qeth_procfile_fops = {
+-	.owner   = THIS_MODULE,
+-	.open    = qeth_procfile_open,
+-	.read    = seq_read,
+-	.llseek  = seq_lseek,
+-	.release = seq_release,
+-};
+-
+-/***** /proc/qeth_perf *****/
+-#define QETH_PERF_PROCFILE_NAME "qeth_perf"
+-static struct proc_dir_entry *qeth_perf_procfile;
+-
+-static int
+-qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
+-{
+-	struct device *device;
+-	struct qeth_card *card;
+-
+-
+-	if (it == SEQ_START_TOKEN)
+-		return 0;
+-
+-	device = (struct device *) it;
+-	card = device->driver_data;
+-	seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
+-			CARD_RDEV_ID(card),
+-			CARD_WDEV_ID(card),
+-			CARD_DDEV_ID(card),
+-			QETH_CARD_IFNAME(card)
+-		  );
+-	if (!card->options.performance_stats)
+-		seq_printf(s, "Performance statistics are deactivated.\n");
+-	seq_printf(s, "  Skb's/buffers received                 : %lu/%u\n"
+-		      "  Skb's/buffers sent                     : %lu/%u\n\n",
+-		        card->stats.rx_packets -
+-				card->perf_stats.initial_rx_packets,
+-			card->perf_stats.bufs_rec,
+-		        card->stats.tx_packets -
+-				card->perf_stats.initial_tx_packets,
+-			card->perf_stats.bufs_sent
+-		  );
+-	seq_printf(s, "  Skb's/buffers sent without packing     : %lu/%u\n"
+-		      "  Skb's/buffers sent with packing        : %u/%u\n\n",
+-		   card->stats.tx_packets - card->perf_stats.initial_tx_packets
+-					  - card->perf_stats.skbs_sent_pack,
+-		   card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack,
+-		   card->perf_stats.skbs_sent_pack,
+-		   card->perf_stats.bufs_sent_pack
+-		  );
+-	seq_printf(s, "  Skbs sent in SG mode                   : %u\n"
+-		      "  Skb fragments sent in SG mode          : %u\n\n",
+-		      card->perf_stats.sg_skbs_sent,
+-		      card->perf_stats.sg_frags_sent);
+-	seq_printf(s, "  Skbs received in SG mode               : %u\n"
+-		      "  Skb fragments received in SG mode      : %u\n"
+-		      "  Page allocations for rx SG mode        : %u\n\n",
+-		      card->perf_stats.sg_skbs_rx,
+-		      card->perf_stats.sg_frags_rx,
+-		      card->perf_stats.sg_alloc_page_rx);
+-	seq_printf(s, "  large_send tx (in Kbytes)              : %u\n"
+-		      "  large_send count                       : %u\n\n",
+-		      card->perf_stats.large_send_bytes >> 10,
+-		      card->perf_stats.large_send_cnt);
+-	seq_printf(s, "  Packing state changes no pkg.->packing : %u/%u\n"
+-		      "  Watermarks L/H                         : %i/%i\n"
+-		      "  Current buffer usage (outbound q's)    : "
+-		      "%i/%i/%i/%i\n\n",
+-		        card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp,
+-			QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK,
+-			atomic_read(&card->qdio.out_qs[0]->used_buffers),
+-			(card->qdio.no_out_queues > 1)?
+-				atomic_read(&card->qdio.out_qs[1]->used_buffers)
+-				: 0,
+-			(card->qdio.no_out_queues > 2)?
+-				atomic_read(&card->qdio.out_qs[2]->used_buffers)
+-				: 0,
+-			(card->qdio.no_out_queues > 3)?
+-				atomic_read(&card->qdio.out_qs[3]->used_buffers)
+-				: 0
+-		  );
+-	seq_printf(s, "  Inbound handler time (in us)           : %u\n"
+-		      "  Inbound handler count                  : %u\n"
+-		      "  Inbound do_QDIO time (in us)           : %u\n"
+-		      "  Inbound do_QDIO count                  : %u\n\n"
+-		      "  Outbound handler time (in us)          : %u\n"
+-		      "  Outbound handler count                 : %u\n\n"
+-		      "  Outbound time (in us, incl QDIO)       : %u\n"
+-		      "  Outbound count                         : %u\n"
+-		      "  Outbound do_QDIO time (in us)          : %u\n"
+-		      "  Outbound do_QDIO count                 : %u\n\n",
+-		        card->perf_stats.inbound_time,
+-			card->perf_stats.inbound_cnt,
+-		        card->perf_stats.inbound_do_qdio_time,
+-			card->perf_stats.inbound_do_qdio_cnt,
+-			card->perf_stats.outbound_handler_time,
+-			card->perf_stats.outbound_handler_cnt,
+-			card->perf_stats.outbound_time,
+-			card->perf_stats.outbound_cnt,
+-		        card->perf_stats.outbound_do_qdio_time,
+-			card->perf_stats.outbound_do_qdio_cnt
+-		  );
+-	put_device(device);
+-	return 0;
+-}
+-
+-static const struct seq_operations qeth_perf_procfile_seq_ops = {
+-	.start = qeth_procfile_seq_start,
+-	.stop  = qeth_procfile_seq_stop,
+-	.next  = qeth_procfile_seq_next,
+-	.show  = qeth_perf_procfile_seq_show,
+-};
+-
+-static int
+-qeth_perf_procfile_open(struct inode *inode, struct file *file)
+-{
+-	return seq_open(file, &qeth_perf_procfile_seq_ops);
+-}
+-
+-static const struct file_operations qeth_perf_procfile_fops = {
+-	.owner   = THIS_MODULE,
+-	.open    = qeth_perf_procfile_open,
+-	.read    = seq_read,
+-	.llseek  = seq_lseek,
+-	.release = seq_release,
+-};
+-
+-int __init
+-qeth_create_procfs_entries(void)
+-{
+-	qeth_procfile = create_proc_entry(QETH_PROCFILE_NAME,
+-					   S_IFREG | 0444, NULL);
+-	if (qeth_procfile)
+-		qeth_procfile->proc_fops = &qeth_procfile_fops;
+-
+-	qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
+-					   S_IFREG | 0444, NULL);
+-	if (qeth_perf_procfile)
+-		qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
+-
+-	if (qeth_procfile &&
+-	    qeth_perf_procfile)
+-		return 0;
+-	else
+-		return -ENOMEM;
+-}
+-
+-void __exit
+-qeth_remove_procfs_entries(void)
+-{
+-	if (qeth_procfile)
+-		remove_proc_entry(QETH_PROCFILE_NAME, NULL);
+-	if (qeth_perf_procfile)
+-		remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
+-}
+-
+diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
+deleted file mode 100644
+index 2cc3f3a..0000000
+--- a/drivers/s390/net/qeth_sys.c
++++ /dev/null
+@@ -1,1858 +0,0 @@
+-/*
+- *
+- * linux/drivers/s390/net/qeth_sys.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- * This file contains code related to sysfs.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- * 	      Frank Pavlic <fpavlic at de.ibm.com>
+- *
+- */
+-#include <linux/list.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/ebcdic.h>
+-
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_fs.h"
+-
+-/*****************************************************************************/
+-/*                                                                           */
+-/*          /sys-fs stuff UNDER DEVELOPMENT !!!                              */
+-/*                                                                           */
+-/*****************************************************************************/
+-//low/high watermark
+-
+-static ssize_t
+-qeth_dev_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	if (!card)
+-		return -EINVAL;
+-
+-	switch (card->state) {
+-	case CARD_STATE_DOWN:
+-		return sprintf(buf, "DOWN\n");
+-	case CARD_STATE_HARDSETUP:
+-		return sprintf(buf, "HARDSETUP\n");
+-	case CARD_STATE_SOFTSETUP:
+-		return sprintf(buf, "SOFTSETUP\n");
+-	case CARD_STATE_UP:
+-		if (card->lan_online)
+-		return sprintf(buf, "UP (LAN ONLINE)\n");
+-		else
+-			return sprintf(buf, "UP (LAN OFFLINE)\n");
+-	case CARD_STATE_RECOVER:
+-		return sprintf(buf, "RECOVER\n");
+-	default:
+-		return sprintf(buf, "UNKNOWN\n");
+-	}
+-}
+-
+-static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
+-
+-static ssize_t
+-qeth_dev_chpid_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%02X\n", card->info.chpid);
+-}
+-
+-static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
+-
+-static ssize_t
+-qeth_dev_if_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	if (!card)
+-		return -EINVAL;
+-	return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
+-}
+-
+-static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
+-
+-static ssize_t
+-qeth_dev_card_type_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
+-}
+-
+-static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
+-
+-static ssize_t
+-qeth_dev_portno_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%i\n", card->info.portno);
+-}
+-
+-static ssize_t
+-qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	unsigned int portno;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	portno = simple_strtoul(buf, &tmp, 16);
+-	if (portno > MAX_PORTNO){
+-		PRINT_WARN("portno 0x%X is out of range\n", portno);
+-		return -EINVAL;
+-	}
+-
+-	card->info.portno = portno;
+-	return count;
+-}
+-
+-static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
+-
+-static ssize_t
+-qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char portname[9] = {0, };
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (card->info.portname_required) {
+-		memcpy(portname, card->info.portname + 1, 8);
+-		EBCASC(portname, 8);
+-		return sprintf(buf, "%s\n", portname);
+-	} else
+-		return sprintf(buf, "no portname required\n");
+-}
+-
+-static ssize_t
+-qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	int i;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	tmp = strsep((char **) &buf, "\n");
+-	if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
+-		return -EINVAL;
+-
+-	card->info.portname[0] = strlen(tmp);
+-	/* for beauty reasons */
+-	for (i = 1; i < 9; i++)
+-		card->info.portname[i] = ' ';
+-	strcpy(card->info.portname + 1, tmp);
+-	ASCEBC(card->info.portname + 1, 8);
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
+-		qeth_dev_portname_store);
+-
+-static ssize_t
+-qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%s checksumming\n", qeth_get_checksum_str(card));
+-}
+-
+-static ssize_t
+-qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	tmp = strsep((char **) &buf, "\n");
+-	if (!strcmp(tmp, "sw_checksumming"))
+-		card->options.checksum_type = SW_CHECKSUMMING;
+-	else if (!strcmp(tmp, "hw_checksumming"))
+-		card->options.checksum_type = HW_CHECKSUMMING;
+-	else if (!strcmp(tmp, "no_checksumming"))
+-		card->options.checksum_type = NO_CHECKSUMMING;
+-	else {
+-		PRINT_WARN("Unknown checksumming type '%s'\n", tmp);
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show,
+-		qeth_dev_checksum_store);
+-
+-static ssize_t
+-qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	switch (card->qdio.do_prio_queueing) {
+-	case QETH_PRIO_Q_ING_PREC:
+-		return sprintf(buf, "%s\n", "by precedence");
+-	case QETH_PRIO_Q_ING_TOS:
+-		return sprintf(buf, "%s\n", "by type of service");
+-	default:
+-		return sprintf(buf, "always queue %i\n",
+-			       card->qdio.default_out_queue);
+-	}
+-}
+-
+-static ssize_t
+-qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	/* check if 1920 devices are supported ,
+-	 * if though we have to permit priority queueing
+-	 */
+-	if (card->qdio.no_out_queues == 1) {
+-		PRINT_WARN("Priority queueing disabled due "
+-			   "to hardware limitations!\n");
+-		card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+-		return -EPERM;
+-	}
+-
+-	tmp = strsep((char **) &buf, "\n");
+-	if (!strcmp(tmp, "prio_queueing_prec"))
+-		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
+-	else if (!strcmp(tmp, "prio_queueing_tos"))
+-		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
+-	else if (!strcmp(tmp, "no_prio_queueing:0")) {
+-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+-		card->qdio.default_out_queue = 0;
+-	} else if (!strcmp(tmp, "no_prio_queueing:1")) {
+-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+-		card->qdio.default_out_queue = 1;
+-	} else if (!strcmp(tmp, "no_prio_queueing:2")) {
+-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+-		card->qdio.default_out_queue = 2;
+-	} else if (!strcmp(tmp, "no_prio_queueing:3")) {
+-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+-		card->qdio.default_out_queue = 3;
+-	} else if (!strcmp(tmp, "no_prio_queueing")) {
+-		card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+-		card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
+-	} else {
+-		PRINT_WARN("Unknown queueing type '%s'\n", tmp);
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
+-		qeth_dev_prioqing_store);
+-
+-static ssize_t
+-qeth_dev_bufcnt_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
+-}
+-
+-static ssize_t
+-qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	int cnt, old_cnt;
+-	int rc;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	old_cnt = card->qdio.in_buf_pool.buf_count;
+-	cnt = simple_strtoul(buf, &tmp, 10);
+-	cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
+-		((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
+-	if (old_cnt != cnt) {
+-		if ((rc = qeth_realloc_buffer_pool(card, cnt)))
+-			PRINT_WARN("Error (%d) while setting "
+-				   "buffer count.\n", rc);
+-	}
+-	return count;
+-}
+-
+-static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
+-		qeth_dev_bufcnt_store);
+-
+-static ssize_t
+-qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route,
+-		    char *buf)
+-{
+-	switch (route->type) {
+-	case PRIMARY_ROUTER:
+-		return sprintf(buf, "%s\n", "primary router");
+-	case SECONDARY_ROUTER:
+-		return sprintf(buf, "%s\n", "secondary router");
+-	case MULTICAST_ROUTER:
+-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+-			return sprintf(buf, "%s\n", "multicast router+");
+-		else
+-			return sprintf(buf, "%s\n", "multicast router");
+-	case PRIMARY_CONNECTOR:
+-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+-			return sprintf(buf, "%s\n", "primary connector+");
+-		else
+-			return sprintf(buf, "%s\n", "primary connector");
+-	case SECONDARY_CONNECTOR:
+-		if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+-			return sprintf(buf, "%s\n", "secondary connector+");
+-		else
+-			return sprintf(buf, "%s\n", "secondary connector");
+-	default:
+-		return sprintf(buf, "%s\n", "no");
+-	}
+-}
+-
+-static ssize_t
+-qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_route_show(card, &card->options.route4, buf);
+-}
+-
+-static ssize_t
+-qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route,
+-		enum qeth_prot_versions prot, const char *buf, size_t count)
+-{
+-	enum qeth_routing_types old_route_type = route->type;
+-	char *tmp;
+-	int rc;
+-
+-	tmp = strsep((char **) &buf, "\n");
+-
+-	if (!strcmp(tmp, "no_router")){
+-		route->type = NO_ROUTER;
+-	} else if (!strcmp(tmp, "primary_connector")) {
+-		route->type = PRIMARY_CONNECTOR;
+-	} else if (!strcmp(tmp, "secondary_connector")) {
+-		route->type = SECONDARY_CONNECTOR;
+-	} else if (!strcmp(tmp, "primary_router")) {
+-		route->type = PRIMARY_ROUTER;
+-	} else if (!strcmp(tmp, "secondary_router")) {
+-		route->type = SECONDARY_ROUTER;
+-	} else if (!strcmp(tmp, "multicast_router")) {
+-		route->type = MULTICAST_ROUTER;
+-	} else {
+-		PRINT_WARN("Invalid routing type '%s'.\n", tmp);
+-		return -EINVAL;
+-	}
+-	if (((card->state == CARD_STATE_SOFTSETUP) ||
+-	     (card->state == CARD_STATE_UP)) &&
+-	    (old_route_type != route->type)){
+-		if (prot == QETH_PROT_IPV4)
+-			rc = qeth_setrouting_v4(card);
+-		else if (prot == QETH_PROT_IPV6)
+-			rc = qeth_setrouting_v6(card);
+-	}
+-	return count;
+-}
+-
+-static ssize_t
+-qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_route_store(card, &card->options.route4,
+-			            QETH_PROT_IPV4, buf, count);
+-}
+-
+-static DEVICE_ATTR(route4, 0644, qeth_dev_route4_show, qeth_dev_route4_store);
+-
+-#ifdef CONFIG_QETH_IPV6
+-static ssize_t
+-qeth_dev_route6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (!qeth_is_supported(card, IPA_IPV6))
+-		return sprintf(buf, "%s\n", "n/a");
+-
+-	return qeth_dev_route_show(card, &card->options.route6, buf);
+-}
+-
+-static ssize_t
+-qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (!qeth_is_supported(card, IPA_IPV6)){
+-		PRINT_WARN("IPv6 not supported for interface %s.\n"
+-			   "Routing status no changed.\n",
+-			   QETH_CARD_IFNAME(card));
+-		return -ENOTSUPP;
+-	}
+-
+-	return qeth_dev_route_store(card, &card->options.route6,
+-			            QETH_PROT_IPV6, buf, count);
+-}
+-
+-static DEVICE_ATTR(route6, 0644, qeth_dev_route6_show, qeth_dev_route6_store);
+-#endif
+-
+-static ssize_t
+-qeth_dev_add_hhlen_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%i\n", card->options.add_hhlen);
+-}
+-
+-static ssize_t
+-qeth_dev_add_hhlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	int i;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	i = simple_strtoul(buf, &tmp, 10);
+-	if ((i < 0) || (i > MAX_ADD_HHLEN)) {
+-		PRINT_WARN("add_hhlen out of range\n");
+-		return -EINVAL;
+-	}
+-	card->options.add_hhlen = i;
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(add_hhlen, 0644, qeth_dev_add_hhlen_show,
+-		   qeth_dev_add_hhlen_store);
+-
+-static ssize_t
+-qeth_dev_fake_ll_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%i\n", card->options.fake_ll? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	int i;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	i = simple_strtoul(buf, &tmp, 16);
+-	if ((i != 0) && (i != 1)) {
+-		PRINT_WARN("fake_ll: write 0 or 1 to this file!\n");
+-		return -EINVAL;
+-	}
+-	card->options.fake_ll = i;
+-	return count;
+-}
+-
+-static DEVICE_ATTR(fake_ll, 0644, qeth_dev_fake_ll_show,
+-		   qeth_dev_fake_ll_store);
+-
+-static ssize_t
+-qeth_dev_fake_broadcast_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	int i;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	i = simple_strtoul(buf, &tmp, 16);
+-	if ((i == 0) || (i == 1))
+-		card->options.fake_broadcast = i;
+-	else {
+-		PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n");
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static DEVICE_ATTR(fake_broadcast, 0644, qeth_dev_fake_broadcast_show,
+-		   qeth_dev_fake_broadcast_store);
+-
+-static ssize_t
+-qeth_dev_recover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	int i;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (card->state != CARD_STATE_UP)
+-		return -EPERM;
+-
+-	i = simple_strtoul(buf, &tmp, 16);
+-	if (i == 1)
+-		qeth_schedule_recovery(card);
+-
+-	return count;
+-}
+-
+-static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
+-
+-static ssize_t
+-qeth_dev_broadcast_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+-	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
+-		return sprintf(buf, "n/a\n");
+-
+-	return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
+-				     QETH_TR_BROADCAST_ALLRINGS)?
+-		       "all rings":"local");
+-}
+-
+-static ssize_t
+-qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+-	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
+-		PRINT_WARN("Device is not a tokenring device!\n");
+-		return -EINVAL;
+-	}
+-
+-	tmp = strsep((char **) &buf, "\n");
+-
+-	if (!strcmp(tmp, "local")){
+-		card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
+-		return count;
+-	} else if (!strcmp(tmp, "all_rings")) {
+-		card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
+-		return count;
+-	} else {
+-		PRINT_WARN("broadcast_mode: invalid mode %s!\n",
+-			   tmp);
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show,
+-		   qeth_dev_broadcast_mode_store);
+-
+-static ssize_t
+-qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+-	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
+-		return sprintf(buf, "n/a\n");
+-
+-	return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
+-				     QETH_TR_MACADDR_CANONICAL)? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf,
+-				  size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	int i;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+-	      (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
+-		PRINT_WARN("Device is not a tokenring device!\n");
+-		return -EINVAL;
+-	}
+-
+-	i = simple_strtoul(buf, &tmp, 16);
+-	if ((i == 0) || (i == 1))
+-		card->options.macaddr_mode = i?
+-			QETH_TR_MACADDR_CANONICAL :
+-			QETH_TR_MACADDR_NONCANONICAL;
+-	else {
+-		PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n");
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show,
+-		   qeth_dev_canonical_macaddr_store);
+-
+-static ssize_t
+-qeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	int i;
+-
+-	if (!card)
+-		return -EINVAL;
+-	if (card->info.type == QETH_CARD_TYPE_IQD) {
+-                PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
+-                return -EPERM;
+-        }
+-
+-	if (((card->state != CARD_STATE_DOWN) &&
+-	     (card->state != CARD_STATE_RECOVER)))
+-		return -EPERM;
+-
+-	i = simple_strtoul(buf, &tmp, 16);
+-	if ((i == 0) || (i == 1))
+-		card->options.layer2 = i;
+-	else {
+-		PRINT_WARN("layer2: write 0 or 1 to this file!\n");
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
+-		   qeth_dev_layer2_store);
+-
+-static ssize_t
+-qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-	int i;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	i = simple_strtoul(buf, &tmp, 16);
+-	if ((i == 0) || (i == 1)) {
+-		if (i == card->options.performance_stats)
+-			return count;
+-		card->options.performance_stats = i;
+-		if (i == 0)
+-			memset(&card->perf_stats, 0,
+-				sizeof(struct qeth_perf_stats));
+-		card->perf_stats.initial_rx_packets = card->stats.rx_packets;
+-		card->perf_stats.initial_tx_packets = card->stats.tx_packets;
+-	} else {
+-		PRINT_WARN("performance_stats: write 0 or 1 to this file!\n");
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
+-		   qeth_dev_performance_stats_store);
+-
+-static ssize_t
+-qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	switch (card->options.large_send) {
+-	case QETH_LARGE_SEND_NO:
+-		return sprintf(buf, "%s\n", "no");
+-	case QETH_LARGE_SEND_EDDP:
+-		return sprintf(buf, "%s\n", "EDDP");
+-	case QETH_LARGE_SEND_TSO:
+-		return sprintf(buf, "%s\n", "TSO");
+-	default:
+-		return sprintf(buf, "%s\n", "N/A");
+-	}
+-}
+-
+-static ssize_t
+-qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	enum qeth_large_send_types type;
+-	int rc = 0;
+-	char *tmp;
+-
+-	if (!card)
+-		return -EINVAL;
+-	tmp = strsep((char **) &buf, "\n");
+-	if (!strcmp(tmp, "no")){
+-		type = QETH_LARGE_SEND_NO;
+-	} else if (!strcmp(tmp, "EDDP")) {
+-		type = QETH_LARGE_SEND_EDDP;
+-	} else if (!strcmp(tmp, "TSO")) {
+-		type = QETH_LARGE_SEND_TSO;
+-	} else {
+-		PRINT_WARN("large_send: invalid mode %s!\n", tmp);
+-		return -EINVAL;
+-	}
+-	if (card->options.large_send == type)
+-		return count;
+-	if ((rc = qeth_set_large_send(card, type)))
+-		return rc;
+-	return count;
+-}
+-
+-static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
+-		   qeth_dev_large_send_store);
+-
+-static ssize_t
+-qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value )
+-{
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return sprintf(buf, "%i\n", value);
+-}
+-
+-static ssize_t
+-qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count,
+-			  int *value, int max_value)
+-{
+-	char *tmp;
+-	int i;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	i = simple_strtoul(buf, &tmp, 10);
+-	if (i <= max_value) {
+-		*value = i;
+-	} else {
+-		PRINT_WARN("blkt total time: write values between"
+-			   " 0 and %d to this file!\n", max_value);
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static ssize_t
+-qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
+-}
+-
+-
+-static ssize_t
+-qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	return qeth_dev_blkt_store(card, buf, count,
+-				   &card->info.blkt.time_total,1000);
+-}
+-
+-
+-
+-static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
+-		   qeth_dev_blkt_total_store);
+-
+-static ssize_t
+-qeth_dev_blkt_inter_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
+-}
+-
+-
+-static ssize_t
+-qeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	return qeth_dev_blkt_store(card, buf, count,
+-				   &card->info.blkt.inter_packet,100);
+-}
+-
+-static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
+-		   qeth_dev_blkt_inter_store);
+-
+-static ssize_t
+-qeth_dev_blkt_inter_jumbo_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	return qeth_dev_blkt_show(buf, card,
+-				  card->info.blkt.inter_packet_jumbo);
+-}
+-
+-
+-static ssize_t
+-qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	return qeth_dev_blkt_store(card, buf, count,
+-				   &card->info.blkt.inter_packet_jumbo,100);
+-}
+-
+-static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
+-		   qeth_dev_blkt_inter_jumbo_store);
+-
+-static struct device_attribute * qeth_blkt_device_attrs[] = {
+-	&dev_attr_total,
+-	&dev_attr_inter,
+-	&dev_attr_inter_jumbo,
+-	NULL,
+-};
+-
+-static struct attribute_group qeth_device_blkt_group = {
+-	.name = "blkt",
+-	.attrs = (struct attribute **)qeth_blkt_device_attrs,
+-};
+-
+-static struct device_attribute * qeth_device_attrs[] = {
+-	&dev_attr_state,
+-	&dev_attr_chpid,
+-	&dev_attr_if_name,
+-	&dev_attr_card_type,
+-	&dev_attr_portno,
+-	&dev_attr_portname,
+-	&dev_attr_checksumming,
+-	&dev_attr_priority_queueing,
+-	&dev_attr_buffer_count,
+-	&dev_attr_route4,
+-#ifdef CONFIG_QETH_IPV6
+-	&dev_attr_route6,
+-#endif
+-	&dev_attr_add_hhlen,
+-	&dev_attr_fake_ll,
+-	&dev_attr_fake_broadcast,
+-	&dev_attr_recover,
+-	&dev_attr_broadcast_mode,
+-	&dev_attr_canonical_macaddr,
+-	&dev_attr_layer2,
+-	&dev_attr_large_send,
+-	&dev_attr_performance_stats,
+-	NULL,
+-};
+-
+-static struct attribute_group qeth_device_attr_group = {
+-	.attrs = (struct attribute **)qeth_device_attrs,
+-};
+-
+-static struct device_attribute * qeth_osn_device_attrs[] = {
+-	&dev_attr_state,
+-	&dev_attr_chpid,
+-	&dev_attr_if_name,
+-	&dev_attr_card_type,
+-	&dev_attr_buffer_count,
+-	&dev_attr_recover,
+-	NULL,
+-};
+-
+-static struct attribute_group qeth_osn_device_attr_group = {
+-	.attrs = (struct attribute **)qeth_osn_device_attrs,
+-};
+-
+-#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)			     \
+-struct device_attribute dev_attr_##_id = {				     \
+-	.attr = {.name=__stringify(_name), .mode=_mode, },\
+-	.show	= _show,						     \
+-	.store	= _store,						     \
+-};
+-
+-static int
+-qeth_check_layer2(struct qeth_card *card)
+-{
+-	if (card->options.layer2)
+-		return -EPERM;
+-	return 0;
+-}
+-
+-
+-static ssize_t
+-qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-	return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if ((card->state != CARD_STATE_DOWN) &&
+-	    (card->state != CARD_STATE_RECOVER))
+-		return -EPERM;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-
+-	tmp = strsep((char **) &buf, "\n");
+-	if (!strcmp(tmp, "toggle")){
+-		card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
+-	} else if (!strcmp(tmp, "1")){
+-		card->ipato.enabled = 1;
+-	} else if (!strcmp(tmp, "0")){
+-		card->ipato.enabled = 0;
+-	} else {
+-		PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
+-			   "this file\n");
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
+-			qeth_dev_ipato_enable_show,
+-			qeth_dev_ipato_enable_store);
+-
+-static ssize_t
+-qeth_dev_ipato_invert4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-
+-	return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-
+-	tmp = strsep((char **) &buf, "\n");
+-	if (!strcmp(tmp, "toggle")){
+-		card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
+-	} else if (!strcmp(tmp, "1")){
+-		card->ipato.invert4 = 1;
+-	} else if (!strcmp(tmp, "0")){
+-		card->ipato.invert4 = 0;
+-	} else {
+-		PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
+-			   "this file\n");
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
+-			qeth_dev_ipato_invert4_show,
+-			qeth_dev_ipato_invert4_store);
+-
+-static ssize_t
+-qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
+-			enum qeth_prot_versions proto)
+-{
+-	struct qeth_ipato_entry *ipatoe;
+-	unsigned long flags;
+-	char addr_str[40];
+-	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
+-	int i = 0;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-
+-	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+-	/* add strlen for "/<mask>\n" */
+-	entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	list_for_each_entry(ipatoe, &card->ipato.entries, entry){
+-		if (ipatoe->proto != proto)
+-			continue;
+-		/* String must not be longer than PAGE_SIZE. So we check if
+-		 * string length gets near PAGE_SIZE. Then we can savely display
+-		 * the next IPv6 address (worst case, compared to IPv4) */
+-		if ((PAGE_SIZE - i) <= entry_len)
+-			break;
+-		qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str);
+-		i += snprintf(buf + i, PAGE_SIZE - i,
+-			      "%s/%i\n", addr_str, ipatoe->mask_bits);
+-	}
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+-
+-	return i;
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
+-}
+-
+-static int
+-qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
+-		  u8 *addr, int *mask_bits)
+-{
+-	const char *start, *end;
+-	char *tmp;
+-	char buffer[40] = {0, };
+-
+-	start = buf;
+-	/* get address string */
+-	end = strchr(start, '/');
+-	if (!end || (end - start >= 40)){
+-		PRINT_WARN("Invalid format for ipato_addx/delx. "
+-			   "Use <ip addr>/<mask bits>\n");
+-		return -EINVAL;
+-	}
+-	strncpy(buffer, start, end - start);
+-	if (qeth_string_to_ipaddr(buffer, proto, addr)){
+-		PRINT_WARN("Invalid IP address format!\n");
+-		return -EINVAL;
+-	}
+-	start = end + 1;
+-	*mask_bits = simple_strtoul(start, &tmp, 10);
+-	if (!strlen(start) ||
+-	    (tmp == start) ||
+-	    (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
+-		PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n");
+-		return -EINVAL;
+-	}
+-	return 0;
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_add_store(const char *buf, size_t count,
+-			 struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+-	struct qeth_ipato_entry *ipatoe;
+-	u8 addr[16];
+-	int mask_bits;
+-	int rc;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-	if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
+-		return rc;
+-
+-	if (!(ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){
+-		PRINT_WARN("No memory to allocate ipato entry\n");
+-		return -ENOMEM;
+-	}
+-	ipatoe->proto = proto;
+-	memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
+-	ipatoe->mask_bits = mask_bits;
+-
+-	if ((rc = qeth_add_ipato_entry(card, ipatoe))){
+-		kfree(ipatoe);
+-		return rc;
+-	}
+-
+-	return count;
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
+-			qeth_dev_ipato_add4_show,
+-			qeth_dev_ipato_add4_store);
+-
+-static ssize_t
+-qeth_dev_ipato_del_store(const char *buf, size_t count,
+-			 struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+-	u8 addr[16];
+-	int mask_bits;
+-	int rc;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-	if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
+-		return rc;
+-
+-	qeth_del_ipato_entry(card, proto, addr, mask_bits);
+-
+-	return count;
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
+-			qeth_dev_ipato_del4_store);
+-
+-#ifdef CONFIG_QETH_IPV6
+-static ssize_t
+-qeth_dev_ipato_invert6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-
+-	return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_invert6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-	char *tmp;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-
+-	tmp = strsep((char **) &buf, "\n");
+-	if (!strcmp(tmp, "toggle")){
+-		card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
+-	} else if (!strcmp(tmp, "1")){
+-		card->ipato.invert6 = 1;
+-	} else if (!strcmp(tmp, "0")){
+-		card->ipato.invert6 = 0;
+-	} else {
+-		PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to "
+-			   "this file\n");
+-		return -EINVAL;
+-	}
+-	return count;
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
+-			qeth_dev_ipato_invert6_show,
+-			qeth_dev_ipato_invert6_store);
+-
+-
+-static ssize_t
+-qeth_dev_ipato_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
+-			qeth_dev_ipato_add6_show,
+-			qeth_dev_ipato_add6_store);
+-
+-static ssize_t
+-qeth_dev_ipato_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
+-			qeth_dev_ipato_del6_store);
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static struct device_attribute * qeth_ipato_device_attrs[] = {
+-	&dev_attr_ipato_enable,
+-	&dev_attr_ipato_invert4,
+-	&dev_attr_ipato_add4,
+-	&dev_attr_ipato_del4,
+-#ifdef CONFIG_QETH_IPV6
+-	&dev_attr_ipato_invert6,
+-	&dev_attr_ipato_add6,
+-	&dev_attr_ipato_del6,
+-#endif
+-	NULL,
+-};
+-
+-static struct attribute_group qeth_device_ipato_group = {
+-	.name = "ipa_takeover",
+-	.attrs = (struct attribute **)qeth_ipato_device_attrs,
+-};
+-
+-static ssize_t
+-qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
+-			enum qeth_prot_versions proto)
+-{
+-	struct qeth_ipaddr *ipaddr;
+-	char addr_str[40];
+-	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
+-	unsigned long flags;
+-	int i = 0;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-
+-	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+-	entry_len += 2; /* \n + terminator */
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	list_for_each_entry(ipaddr, &card->ip_list, entry){
+-		if (ipaddr->proto != proto)
+-			continue;
+-		if (ipaddr->type != QETH_IP_TYPE_VIPA)
+-			continue;
+-		/* String must not be longer than PAGE_SIZE. So we check if
+-		 * string length gets near PAGE_SIZE. Then we can savely display
+-		 * the next IPv6 address (worst case, compared to IPv4) */
+-		if ((PAGE_SIZE - i) <= entry_len)
+-			break;
+-		qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
+-		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
+-	}
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+-
+-	return i;
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
+-}
+-
+-static int
+-qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto,
+-		 u8 *addr)
+-{
+-	if (qeth_string_to_ipaddr(buf, proto, addr)){
+-		PRINT_WARN("Invalid IP address format!\n");
+-		return -EINVAL;
+-	}
+-	return 0;
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_add_store(const char *buf, size_t count,
+-			 struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+-	u8 addr[16] = {0, };
+-	int rc;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-	if ((rc = qeth_parse_vipae(buf, proto, addr)))
+-		return rc;
+-
+-	if ((rc = qeth_add_vipa(card, proto, addr)))
+-		return rc;
+-
+-	return count;
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
+-			qeth_dev_vipa_add4_show,
+-			qeth_dev_vipa_add4_store);
+-
+-static ssize_t
+-qeth_dev_vipa_del_store(const char *buf, size_t count,
+-			 struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+-	u8 addr[16];
+-	int rc;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-	if ((rc = qeth_parse_vipae(buf, proto, addr)))
+-		return rc;
+-
+-	qeth_del_vipa(card, proto, addr);
+-
+-	return count;
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
+-			qeth_dev_vipa_del4_store);
+-
+-#ifdef CONFIG_QETH_IPV6
+-static ssize_t
+-qeth_dev_vipa_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
+-			qeth_dev_vipa_add6_show,
+-			qeth_dev_vipa_add6_store);
+-
+-static ssize_t
+-qeth_dev_vipa_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-
+-	return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
+-			qeth_dev_vipa_del6_store);
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static struct device_attribute * qeth_vipa_device_attrs[] = {
+-	&dev_attr_vipa_add4,
+-	&dev_attr_vipa_del4,
+-#ifdef CONFIG_QETH_IPV6
+-	&dev_attr_vipa_add6,
+-	&dev_attr_vipa_del6,
+-#endif
+-	NULL,
+-};
+-
+-static struct attribute_group qeth_device_vipa_group = {
+-	.name = "vipa",
+-	.attrs = (struct attribute **)qeth_vipa_device_attrs,
+-};
+-
+-static ssize_t
+-qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
+-		       enum qeth_prot_versions proto)
+-{
+-	struct qeth_ipaddr *ipaddr;
+-	char addr_str[40];
+-	int entry_len; /* length of 1 entry string, differs between v4 and v6 */
+-	unsigned long flags;
+-	int i = 0;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-
+-	entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+-	entry_len += 2; /* \n + terminator */
+-	spin_lock_irqsave(&card->ip_lock, flags);
+-	list_for_each_entry(ipaddr, &card->ip_list, entry){
+-		if (ipaddr->proto != proto)
+-			continue;
+-		if (ipaddr->type != QETH_IP_TYPE_RXIP)
+-			continue;
+-		/* String must not be longer than PAGE_SIZE. So we check if
+-		 * string length gets near PAGE_SIZE. Then we can savely display
+-		 * the next IPv6 address (worst case, compared to IPv4) */
+-		if ((PAGE_SIZE - i) <= entry_len)
+-			break;
+-		qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
+-		i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
+-	}
+-	spin_unlock_irqrestore(&card->ip_lock, flags);
+-	i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+-
+-	return i;
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
+-}
+-
+-static int
+-qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto,
+-		 u8 *addr)
+-{
+-	if (qeth_string_to_ipaddr(buf, proto, addr)){
+-		PRINT_WARN("Invalid IP address format!\n");
+-		return -EINVAL;
+-	}
+-	return 0;
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_add_store(const char *buf, size_t count,
+-			struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+-	u8 addr[16] = {0, };
+-	int rc;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-	if ((rc = qeth_parse_rxipe(buf, proto, addr)))
+-		return rc;
+-
+-	if ((rc = qeth_add_rxip(card, proto, addr)))
+-		return rc;
+-
+-	return count;
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
+-			qeth_dev_rxip_add4_show,
+-			qeth_dev_rxip_add4_store);
+-
+-static ssize_t
+-qeth_dev_rxip_del_store(const char *buf, size_t count,
+-			struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+-	u8 addr[16];
+-	int rc;
+-
+-	if (qeth_check_layer2(card))
+-		return -EPERM;
+-	if ((rc = qeth_parse_rxipe(buf, proto, addr)))
+-		return rc;
+-
+-	qeth_del_rxip(card, proto, addr);
+-
+-	return count;
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
+-			qeth_dev_rxip_del4_store);
+-
+-#ifdef CONFIG_QETH_IPV6
+-static ssize_t
+-qeth_dev_rxip_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
+-			qeth_dev_rxip_add6_show,
+-			qeth_dev_rxip_add6_store);
+-
+-static ssize_t
+-qeth_dev_rxip_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (!card)
+-		return -EINVAL;
+-
+-	return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
+-			qeth_dev_rxip_del6_store);
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static struct device_attribute * qeth_rxip_device_attrs[] = {
+-	&dev_attr_rxip_add4,
+-	&dev_attr_rxip_del4,
+-#ifdef CONFIG_QETH_IPV6
+-	&dev_attr_rxip_add6,
+-	&dev_attr_rxip_del6,
+-#endif
+-	NULL,
+-};
+-
+-static struct attribute_group qeth_device_rxip_group = {
+-	.name = "rxip",
+-	.attrs = (struct attribute **)qeth_rxip_device_attrs,
+-};
+-
+-int
+-qeth_create_device_attributes(struct device *dev)
+-{
+-	int ret;
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (card->info.type == QETH_CARD_TYPE_OSN)
+-		return sysfs_create_group(&dev->kobj,
+-					  &qeth_osn_device_attr_group);
+-
+-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
+-		return ret;
+-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
+-		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+-		return ret;
+-	}
+-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group))){
+-		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+-		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+-		return ret;
+-	}
+-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group))){
+-		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+-		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+-		sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
+-		return ret;
+-	}
+-	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group))){
+-		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+-		sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+-		sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
+-		sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
+-		return ret;
+-	}
+-	return 0;
+-}
+-
+-void
+-qeth_remove_device_attributes(struct device *dev)
+-{
+-	struct qeth_card *card = dev->driver_data;
+-
+-	if (card->info.type == QETH_CARD_TYPE_OSN) {
+-		sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
+-		return;
+-	}
+-	sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+-	sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+-	sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
+-	sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
+-	sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
+-}
+-
+-/**********************/
+-/* DRIVER ATTRIBUTES  */
+-/**********************/
+-static ssize_t
+-qeth_driver_group_store(struct device_driver *ddrv, const char *buf,
+-			size_t count)
+-{
+-	const char *start, *end;
+-	char bus_ids[3][BUS_ID_SIZE], *argv[3];
+-	int i;
+-	int err;
+-
+-	start = buf;
+-	for (i = 0; i < 3; i++) {
+-		static const char delim[] = { ',', ',', '\n' };
+-		int len;
+-
+-		if (!(end = strchr(start, delim[i])))
+-			return -EINVAL;
+-		len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
+-		strncpy(bus_ids[i], start, len);
+-		bus_ids[i][len] = '\0';
+-		start = end + 1;
+-		argv[i] = bus_ids[i];
+-	}
+-	err = ccwgroup_create(qeth_root_dev, qeth_ccwgroup_driver.driver_id,
+-			&qeth_ccw_driver, 3, argv);
+-	if (err)
+-		return err;
+-	else
+-		return count;
+-}
+-
+-
+-static DRIVER_ATTR(group, 0200, NULL, qeth_driver_group_store);
+-
+-static ssize_t
+-qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf,
+-				size_t count)
+-{
+-	int rc;
+-	int signum;
+-	char *tmp, *tmp2;
+-
+-	tmp = strsep((char **) &buf, "\n");
+-	if (!strncmp(tmp, "unregister", 10)){
+-		if ((rc = qeth_notifier_unregister(current)))
+-			return rc;
+-		return count;
+-	}
+-
+-	signum = simple_strtoul(tmp, &tmp2, 10);
+-	if ((signum < 0) || (signum > 32)){
+-		PRINT_WARN("Signal number %d is out of range\n", signum);
+-		return -EINVAL;
+-	}
+-	if ((rc = qeth_notifier_register(current, signum)))
+-		return rc;
+-
+-	return count;
+-}
+-
+-static DRIVER_ATTR(notifier_register, 0200, NULL,
+-		   qeth_driver_notifier_register_store);
+-
+-int
+-qeth_create_driver_attributes(void)
+-{
+-	int rc;
+-
+-	if ((rc = driver_create_file(&qeth_ccwgroup_driver.driver,
+-				     &driver_attr_group)))
+-		return rc;
+-	return driver_create_file(&qeth_ccwgroup_driver.driver,
+-				  &driver_attr_notifier_register);
+-}
+-
+-void
+-qeth_remove_driver_attributes(void)
+-{
+-	driver_remove_file(&qeth_ccwgroup_driver.driver,
+-			&driver_attr_group);
+-	driver_remove_file(&qeth_ccwgroup_driver.driver,
+-			&driver_attr_notifier_register);
+-}
+diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
+deleted file mode 100644
+index c20e923..0000000
+--- a/drivers/s390/net/qeth_tso.h
++++ /dev/null
+@@ -1,148 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_tso.h
+- *
+- * Header file for qeth TCP Segmentation Offload support.
+- *
+- * Copyright 2004 IBM Corporation
+- *
+- *    Author(s): Frank Pavlic <fpavlic at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_TSO_H__
+-#define __QETH_TSO_H__
+-
+-#include <linux/skbuff.h>
+-#include <linux/tcp.h>
+-#include <linux/ip.h>
+-#include <linux/ipv6.h>
+-#include <net/ip6_checksum.h>
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-
+-
+-static inline struct qeth_hdr_tso *
+-qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
+-{
+-	QETH_DBF_TEXT(trace, 5, "tsoprsk");
+-	return qeth_push_skb(card, *skb, sizeof(struct qeth_hdr_tso));
+-}
+-
+-/**
+- * fill header for a TSO packet
+- */
+-static inline void
+-qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
+-{
+-	struct qeth_hdr_tso *hdr;
+-	struct tcphdr *tcph;
+-	struct iphdr *iph;
+-
+-	QETH_DBF_TEXT(trace, 5, "tsofhdr");
+-
+-	hdr  = (struct qeth_hdr_tso *) skb->data;
+-	iph  = ip_hdr(skb);
+-	tcph = tcp_hdr(skb);
+-	/*fix header to TSO values ...*/
+-	hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
+-	/*set values which are fix for the first approach ...*/
+-	hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
+-	hdr->ext.imb_hdr_no  = 1;
+-	hdr->ext.hdr_type    = 1;
+-	hdr->ext.hdr_version = 1;
+-	hdr->ext.hdr_len     = 28;
+-	/*insert non-fix values */
+-	hdr->ext.mss = skb_shinfo(skb)->gso_size;
+-	hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
+-	hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
+-				       sizeof(struct qeth_hdr_tso));
+-}
+-
+-/**
+- * change some header values as requested by hardware
+- */
+-static inline void
+-qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
+-{
+-	struct iphdr *iph    = ip_hdr(skb);
+-	struct ipv6hdr *ip6h = ipv6_hdr(skb);
+-	struct tcphdr *tcph  = tcp_hdr(skb);
+-
+-	tcph->check = 0;
+-	if (skb->protocol == ETH_P_IPV6) {
+-		ip6h->payload_len = 0;
+-		tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+-					       0, IPPROTO_TCP, 0);
+-		return;
+-	}
+-	/*OSA want us to set these values ...*/
+-	tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+-					 0, IPPROTO_TCP, 0);
+-	iph->tot_len = 0;
+-	iph->check = 0;
+-}
+-
+-static inline int
+-qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
+-			int ipv, int cast_type)
+-{
+-	struct qeth_hdr_tso *hdr;
+-
+-	QETH_DBF_TEXT(trace, 5, "tsoprep");
+-
+-	hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
+-	if (hdr == NULL) {
+-		QETH_DBF_TEXT(trace, 4, "tsoperr");
+-		return -ENOMEM;
+-	}
+-	memset(hdr, 0, sizeof(struct qeth_hdr_tso));
+-	/*fill first 32 bytes of  qdio header as used
+-	 *FIXME: TSO has two struct members
+-	 * with different names but same size
+-	 * */
+-	qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
+-	qeth_tso_fill_header(card, skb);
+-	qeth_tso_set_tcpip_header(card, skb);
+-	return 0;
+-}
+-
+-static inline void
+-__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
+-			int is_tso, int *next_element_to_fill)
+-{
+-	struct skb_frag_struct *frag;
+-	int fragno;
+-	unsigned long addr;
+-	int element, cnt, dlen;
+-
+-	fragno = skb_shinfo(skb)->nr_frags;
+-	element = *next_element_to_fill;
+-	dlen = 0;
+-
+-	if (is_tso)
+-		buffer->element[element].flags =
+-			SBAL_FLAGS_MIDDLE_FRAG;
+-	else
+-		buffer->element[element].flags =
+-			SBAL_FLAGS_FIRST_FRAG;
+-	if ( (dlen = (skb->len - skb->data_len)) ) {
+-		buffer->element[element].addr = skb->data;
+-		buffer->element[element].length = dlen;
+-		element++;
+-	}
+-	for (cnt = 0; cnt < fragno; cnt++) {
+-		frag = &skb_shinfo(skb)->frags[cnt];
+-		addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
+-			frag->page_offset;
+-		buffer->element[element].addr = (char *)addr;
+-		buffer->element[element].length = frag->size;
+-		if (cnt < (fragno - 1))
+-			buffer->element[element].flags =
+-				SBAL_FLAGS_MIDDLE_FRAG;
+-		else
+-			buffer->element[element].flags =
+-				SBAL_FLAGS_LAST_FRAG;
+-		element++;
+-	}
+-	*next_element_to_fill = element;
+-}
+-#endif /* __QETH_TSO_H__ */
+diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
+index 644a06e..4d4b542 100644
+--- a/drivers/s390/s390mach.c
++++ b/drivers/s390/s390mach.c
+@@ -59,15 +59,15 @@ repeat:
+ 
+ 			printk(KERN_WARNING"%s: Code does not support more "
+ 			       "than two chained crws; please report to "
+-			       "linux390 at de.ibm.com!\n", __FUNCTION__);
++			       "linux390 at de.ibm.com!\n", __func__);
+ 			ccode = stcrw(&tmp_crw);
+ 			printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
+ 			       "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+-			       __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
++			       __func__, tmp_crw.slct, tmp_crw.oflw,
+ 			       tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
+ 			       tmp_crw.erc, tmp_crw.rsid);
+ 			printk(KERN_WARNING"%s: This was crw number %x in the "
+-			       "chain\n", __FUNCTION__, chain);
++			       "chain\n", __func__, chain);
+ 			if (ccode != 0)
+ 				break;
+ 			chain = tmp_crw.chn ? chain + 1 : 0;
+@@ -83,7 +83,7 @@ repeat:
+ 		       crw[chain].rsid);
+ 		/* Check for overflows. */
+ 		if (crw[chain].oflw) {
+-			pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
++			pr_debug("%s: crw overflow detected!\n", __func__);
+ 			css_schedule_eval_all();
+ 			chain = 0;
+ 			continue;
+diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
+index d3ca428..ca681f9 100644
+--- a/drivers/s390/s390mach.h
++++ b/drivers/s390/s390mach.h
+@@ -105,4 +105,8 @@ static inline int stcrw(struct crw *pcrw )
+ #define ED_ETR_SYNC	12	/* External damage ETR sync check */
+ #define ED_ETR_SWITCH	13	/* External damage ETR switch to local */
+ 
++struct pt_regs;
++
++void s390_handle_mcck(void);
++void s390_do_machine_check(struct pt_regs *regs);
+ #endif /* __s390mach */
+diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
+index 874b55e..8c7e2b7 100644
+--- a/drivers/s390/scsi/zfcp_aux.c
++++ b/drivers/s390/scsi/zfcp_aux.c
+@@ -1030,10 +1030,10 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
+ 
+ 	/* initialize debug locks */
+ 
+-	spin_lock_init(&adapter->erp_dbf_lock);
+ 	spin_lock_init(&adapter->hba_dbf_lock);
+ 	spin_lock_init(&adapter->san_dbf_lock);
+ 	spin_lock_init(&adapter->scsi_dbf_lock);
++	spin_lock_init(&adapter->rec_dbf_lock);
+ 
+ 	retval = zfcp_adapter_debug_register(adapter);
+ 	if (retval)
+@@ -1325,10 +1325,10 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
+ 
+ #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_FC
+ 
+-static void
+-zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
+-			   struct fsf_status_read_buffer *status_buffer)
++static void zfcp_fsf_incoming_els_rscn(struct zfcp_fsf_req *fsf_req)
+ {
++	struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
++	struct zfcp_adapter *adapter = fsf_req->adapter;
+ 	struct fcp_rscn_head *fcp_rscn_head;
+ 	struct fcp_rscn_element *fcp_rscn_element;
+ 	struct zfcp_port *port;
+@@ -1375,7 +1375,8 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
+ 				ZFCP_LOG_INFO("incoming RSCN, trying to open "
+ 					      "port 0x%016Lx\n", port->wwpn);
+ 				zfcp_erp_port_reopen(port,
+-						     ZFCP_STATUS_COMMON_ERP_FAILED);
++						     ZFCP_STATUS_COMMON_ERP_FAILED,
++						     82, fsf_req);
+ 				continue;
+ 			}
+ 
+@@ -1406,10 +1407,10 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
+ 	}
+ }
+ 
+-static void
+-zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
+-			    struct fsf_status_read_buffer *status_buffer)
++static void zfcp_fsf_incoming_els_plogi(struct zfcp_fsf_req *fsf_req)
+ {
++	struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
++	struct zfcp_adapter *adapter = fsf_req->adapter;
+ 	struct fsf_plogi *els_plogi;
+ 	struct zfcp_port *port;
+ 	unsigned long flags;
+@@ -1428,14 +1429,14 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
+ 			       status_buffer->d_id,
+ 			       zfcp_get_busid_by_adapter(adapter));
+ 	} else {
+-		zfcp_erp_port_forced_reopen(port, 0);
++		zfcp_erp_port_forced_reopen(port, 0, 83, fsf_req);
+ 	}
+ }
+ 
+-static void
+-zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
+-			   struct fsf_status_read_buffer *status_buffer)
++static void zfcp_fsf_incoming_els_logo(struct zfcp_fsf_req *fsf_req)
+ {
++	struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
++	struct zfcp_adapter *adapter = fsf_req->adapter;
+ 	struct fcp_logo *els_logo = (struct fcp_logo *) status_buffer->payload;
+ 	struct zfcp_port *port;
+ 	unsigned long flags;
+@@ -1453,7 +1454,7 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
+ 			       status_buffer->d_id,
+ 			       zfcp_get_busid_by_adapter(adapter));
+ 	} else {
+-		zfcp_erp_port_forced_reopen(port, 0);
++		zfcp_erp_port_forced_reopen(port, 0, 84, fsf_req);
+ 	}
+ }
+ 
+@@ -1480,12 +1481,12 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req)
+ 
+ 	zfcp_san_dbf_event_incoming_els(fsf_req);
+ 	if (els_type == LS_PLOGI)
+-		zfcp_fsf_incoming_els_plogi(adapter, status_buffer);
++		zfcp_fsf_incoming_els_plogi(fsf_req);
+ 	else if (els_type == LS_LOGO)
+-		zfcp_fsf_incoming_els_logo(adapter, status_buffer);
++		zfcp_fsf_incoming_els_logo(fsf_req);
+ 	else if ((els_type & 0xffff0000) == LS_RSCN)
+ 		/* we are only concerned with the command, not the length */
+-		zfcp_fsf_incoming_els_rscn(adapter, status_buffer);
++		zfcp_fsf_incoming_els_rscn(fsf_req);
+ 	else
+ 		zfcp_fsf_incoming_els_unknown(adapter, status_buffer);
+ }
+diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
+index edc5015..66d3b88 100644
+--- a/drivers/s390/scsi/zfcp_ccw.c
++++ b/drivers/s390/scsi/zfcp_ccw.c
+@@ -170,9 +170,10 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
+ 	BUG_ON(!zfcp_reqlist_isempty(adapter));
+ 	adapter->req_no = 0;
+ 
+-	zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
+-				       ZFCP_SET);
+-	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++	zfcp_erp_modify_adapter_status(adapter, 10, NULL,
++				       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85,
++				NULL);
+ 	zfcp_erp_wait(adapter);
+ 	goto out;
+ 
+@@ -197,7 +198,7 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device)
+ 
+ 	down(&zfcp_data.config_sema);
+ 	adapter = dev_get_drvdata(&ccw_device->dev);
+-	zfcp_erp_adapter_shutdown(adapter, 0);
++	zfcp_erp_adapter_shutdown(adapter, 0, 86, NULL);
+ 	zfcp_erp_wait(adapter);
+ 	zfcp_erp_thread_kill(adapter);
+ 	up(&zfcp_data.config_sema);
+@@ -223,24 +224,21 @@ zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
+ 	case CIO_GONE:
+ 		ZFCP_LOG_NORMAL("adapter %s: device gone\n",
+ 				zfcp_get_busid_by_adapter(adapter));
+-		debug_text_event(adapter->erp_dbf,1,"dev_gone");
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL);
+ 		break;
+ 	case CIO_NO_PATH:
+ 		ZFCP_LOG_NORMAL("adapter %s: no path\n",
+ 				zfcp_get_busid_by_adapter(adapter));
+-		debug_text_event(adapter->erp_dbf,1,"no_path");
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL);
+ 		break;
+ 	case CIO_OPER:
+ 		ZFCP_LOG_NORMAL("adapter %s: operational again\n",
+ 				zfcp_get_busid_by_adapter(adapter));
+-		debug_text_event(adapter->erp_dbf,1,"dev_oper");
+-		zfcp_erp_modify_adapter_status(adapter,
++		zfcp_erp_modify_adapter_status(adapter, 11, NULL,
+ 					       ZFCP_STATUS_COMMON_RUNNING,
+ 					       ZFCP_SET);
+-		zfcp_erp_adapter_reopen(adapter,
+-					ZFCP_STATUS_COMMON_ERP_FAILED);
++		zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
++					89, NULL);
+ 		break;
+ 	}
+ 	zfcp_erp_wait(adapter);
+@@ -272,7 +270,7 @@ zfcp_ccw_shutdown(struct ccw_device *cdev)
+ 
+ 	down(&zfcp_data.config_sema);
+ 	adapter = dev_get_drvdata(&cdev->dev);
+-	zfcp_erp_adapter_shutdown(adapter, 0);
++	zfcp_erp_adapter_shutdown(adapter, 0, 90, NULL);
+ 	zfcp_erp_wait(adapter);
+ 	up(&zfcp_data.config_sema);
+ }
+diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
+index 701046c..37b85c6 100644
+--- a/drivers/s390/scsi/zfcp_dbf.c
++++ b/drivers/s390/scsi/zfcp_dbf.c
+@@ -31,123 +31,128 @@ MODULE_PARM_DESC(dbfsize,
+ 
+ #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_OTHER
+ 
+-static int
+-zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
++static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len,
++			     int level, char *from, int from_len)
++{
++	int offset;
++	struct zfcp_dbf_dump *dump = to;
++	int room = to_len - sizeof(*dump);
++
++	for (offset = 0; offset < from_len; offset += dump->size) {
++		memset(to, 0, to_len);
++		strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
++		dump->total_size = from_len;
++		dump->offset = offset;
++		dump->size = min(from_len - offset, room);
++		memcpy(dump->data, from + offset, dump->size);
++		debug_event(dbf, level, dump, dump->size);
++	}
++}
++
++/* FIXME: this duplicate this code in s390 debug feature */
++static void zfcp_dbf_timestamp(unsigned long long stck, struct timespec *time)
+ {
+ 	unsigned long long sec;
+-	struct timespec dbftime;
+-	int len = 0;
+ 
+ 	stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
+ 	sec = stck >> 12;
+ 	do_div(sec, 1000000);
+-	dbftime.tv_sec = sec;
++	time->tv_sec = sec;
+ 	stck -= (sec * 1000000) << 12;
+-	dbftime.tv_nsec = ((stck * 1000) >> 12);
+-	len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n",
+-		       label, dbftime.tv_sec, dbftime.tv_nsec);
+-
+-	return len;
++	time->tv_nsec = ((stck * 1000) >> 12);
+ }
+ 
+-static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag)
++static void zfcp_dbf_tag(char **p, const char *label, const char *tag)
+ {
+-	int len = 0, i;
++	int i;
+ 
+-	len += sprintf(out_buf + len, "%-24s", label);
++	*p += sprintf(*p, "%-24s", label);
+ 	for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++)
+-		len += sprintf(out_buf + len, "%c", tag[i]);
+-	len += sprintf(out_buf + len, "\n");
++		*p += sprintf(*p, "%c", tag[i]);
++	*p += sprintf(*p, "\n");
++}
+ 
+-	return len;
++static void zfcp_dbf_outs(char **buf, const char *s1, const char *s2)
++{
++	*buf += sprintf(*buf, "%-24s%s\n", s1, s2);
+ }
+ 
+-static int
+-zfcp_dbf_view(char *out_buf, const char *label, const char *format, ...)
++static void zfcp_dbf_out(char **buf, const char *s, const char *format, ...)
+ {
+ 	va_list arg;
+-	int len = 0;
+ 
+-	len += sprintf(out_buf + len, "%-24s", label);
++	*buf += sprintf(*buf, "%-24s", s);
+ 	va_start(arg, format);
+-	len += vsprintf(out_buf + len, format, arg);
++	*buf += vsprintf(*buf, format, arg);
+ 	va_end(arg);
+-	len += sprintf(out_buf + len, "\n");
+-
+-	return len;
++	*buf += sprintf(*buf, "\n");
+ }
+ 
+-static int
+-zfcp_dbf_view_dump(char *out_buf, const char *label,
+-		   char *buffer, int buflen, int offset, int total_size)
++static void zfcp_dbf_outd(char **p, const char *label, char *buffer,
++			  int buflen, int offset, int total_size)
+ {
+-	int len = 0;
+-
+-	if (offset == 0)
+-		len += sprintf(out_buf + len, "%-24s  ", label);
+-
++	if (!offset)
++		*p += sprintf(*p, "%-24s  ", label);
+ 	while (buflen--) {
+ 		if (offset > 0) {
+ 			if ((offset % 32) == 0)
+-				len += sprintf(out_buf + len, "\n%-24c  ", ' ');
++				*p += sprintf(*p, "\n%-24c  ", ' ');
+ 			else if ((offset % 4) == 0)
+-				len += sprintf(out_buf + len, " ");
++				*p += sprintf(*p, " ");
+ 		}
+-		len += sprintf(out_buf + len, "%02x", *buffer++);
++		*p += sprintf(*p, "%02x", *buffer++);
+ 		if (++offset == total_size) {
+-			len += sprintf(out_buf + len, "\n");
++			*p += sprintf(*p, "\n");
+ 			break;
+ 		}
+ 	}
+-
+-	if (total_size == 0)
+-		len += sprintf(out_buf + len, "\n");
+-
+-	return len;
++	if (!total_size)
++		*p += sprintf(*p, "\n");
+ }
+ 
+-static int
+-zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
+-		     debug_entry_t * entry, char *out_buf)
++static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view,
++				int area, debug_entry_t *entry, char *out_buf)
+ {
+ 	struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry);
+-	int len = 0;
++	struct timespec t;
++	char *p = out_buf;
+ 
+ 	if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) {
+-		len += zfcp_dbf_stck(out_buf + len, "timestamp",
+-				     entry->id.stck);
+-		len += zfcp_dbf_view(out_buf + len, "cpu", "%02i",
+-				     entry->id.fields.cpuid);
+-	} else {
+-		len += zfcp_dbf_view_dump(out_buf + len, NULL,
+-					  dump->data,
+-					  dump->size,
+-					  dump->offset, dump->total_size);
++		zfcp_dbf_timestamp(entry->id.stck, &t);
++		zfcp_dbf_out(&p, "timestamp", "%011lu:%06lu",
++			     t.tv_sec, t.tv_nsec);
++		zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid);
++	} else	{
++		zfcp_dbf_outd(&p, NULL, dump->data, dump->size, dump->offset,
++			      dump->total_size);
+ 		if ((dump->offset + dump->size) == dump->total_size)
+-			len += sprintf(out_buf + len, "\n");
++			p += sprintf(p, "\n");
+ 	}
+-
+-	return len;
++	return p - out_buf;
+ }
+ 
++/**
++ * zfcp_hba_dbf_event_fsf_response - trace event for request completion
++ * @fsf_req: request that has been completed
++ */
+ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ {
+ 	struct zfcp_adapter *adapter = fsf_req->adapter;
+ 	struct fsf_qtcb *qtcb = fsf_req->qtcb;
+ 	union fsf_prot_status_qual *prot_status_qual =
+-	    &qtcb->prefix.prot_status_qual;
++					&qtcb->prefix.prot_status_qual;
+ 	union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual;
+ 	struct scsi_cmnd *scsi_cmnd;
+ 	struct zfcp_port *port;
+ 	struct zfcp_unit *unit;
+ 	struct zfcp_send_els *send_els;
+ 	struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+-	struct zfcp_hba_dbf_record_response *response = &rec->type.response;
++	struct zfcp_hba_dbf_record_response *response = &rec->u.response;
+ 	int level;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+-	memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
++	memset(rec, 0, sizeof(*rec));
+ 	strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE);
+ 
+ 	if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
+@@ -161,6 +166,9 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ 		   (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) {
+ 		strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE);
+ 		level = 4;
++	} else if (qtcb->header.log_length) {
++		strncpy(rec->tag2, "qtcb", ZFCP_DBF_TAG_SIZE);
++		level = 5;
+ 	} else {
+ 		strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE);
+ 		level = 6;
+@@ -188,11 +196,9 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ 		if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
+ 			break;
+ 		scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
+-		if (scsi_cmnd != NULL) {
+-			response->data.send_fcp.scsi_cmnd
+-			    = (unsigned long)scsi_cmnd;
+-			response->data.send_fcp.scsi_serial
+-			    = scsi_cmnd->serial_number;
++		if (scsi_cmnd) {
++			response->u.fcp.cmnd = (unsigned long)scsi_cmnd;
++			response->u.fcp.serial = scsi_cmnd->serial_number;
+ 		}
+ 		break;
+ 
+@@ -200,25 +206,25 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ 	case FSF_QTCB_CLOSE_PORT:
+ 	case FSF_QTCB_CLOSE_PHYSICAL_PORT:
+ 		port = (struct zfcp_port *)fsf_req->data;
+-		response->data.port.wwpn = port->wwpn;
+-		response->data.port.d_id = port->d_id;
+-		response->data.port.port_handle = qtcb->header.port_handle;
++		response->u.port.wwpn = port->wwpn;
++		response->u.port.d_id = port->d_id;
++		response->u.port.port_handle = qtcb->header.port_handle;
+ 		break;
+ 
+ 	case FSF_QTCB_OPEN_LUN:
+ 	case FSF_QTCB_CLOSE_LUN:
+ 		unit = (struct zfcp_unit *)fsf_req->data;
+ 		port = unit->port;
+-		response->data.unit.wwpn = port->wwpn;
+-		response->data.unit.fcp_lun = unit->fcp_lun;
+-		response->data.unit.port_handle = qtcb->header.port_handle;
+-		response->data.unit.lun_handle = qtcb->header.lun_handle;
++		response->u.unit.wwpn = port->wwpn;
++		response->u.unit.fcp_lun = unit->fcp_lun;
++		response->u.unit.port_handle = qtcb->header.port_handle;
++		response->u.unit.lun_handle = qtcb->header.lun_handle;
+ 		break;
+ 
+ 	case FSF_QTCB_SEND_ELS:
+ 		send_els = (struct zfcp_send_els *)fsf_req->data;
+-		response->data.send_els.d_id = qtcb->bottom.support.d_id;
+-		response->data.send_els.ls_code = send_els->ls_code >> 24;
++		response->u.els.d_id = qtcb->bottom.support.d_id;
++		response->u.els.ls_code = send_els->ls_code >> 24;
+ 		break;
+ 
+ 	case FSF_QTCB_ABORT_FCP_CMND:
+@@ -230,39 +236,54 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ 		break;
+ 	}
+ 
+-	debug_event(adapter->hba_dbf, level,
+-		    rec, sizeof(struct zfcp_hba_dbf_record));
++	debug_event(adapter->hba_dbf, level, rec, sizeof(*rec));
++
++	/* have fcp channel microcode fixed to use as little as possible */
++	if (fsf_req->fsf_command != FSF_QTCB_FCP_CMND) {
++		/* adjust length skipping trailing zeros */
++		char *buf = (char *)qtcb + qtcb->header.log_start;
++		int len = qtcb->header.log_length;
++		for (; len && !buf[len - 1]; len--);
++		zfcp_dbf_hexdump(adapter->hba_dbf, rec, sizeof(*rec), level,
++				 buf, len);
++	}
++
+ 	spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ }
+ 
+-void
+-zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
+-			     struct fsf_status_read_buffer *status_buffer)
++/**
++ * zfcp_hba_dbf_event_fsf_unsol - trace event for an unsolicited status buffer
++ * @tag: tag indicating which kind of unsolicited status has been received
++ * @adapter: adapter that has issued the unsolicited status buffer
++ * @status_buffer: buffer containing payload of unsolicited status
++ */
++void zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
++				  struct fsf_status_read_buffer *status_buffer)
+ {
+ 	struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+-	memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
++	memset(rec, 0, sizeof(*rec));
+ 	strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE);
+ 	strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE);
+ 
+-	rec->type.status.failed = adapter->status_read_failed;
++	rec->u.status.failed = adapter->status_read_failed;
+ 	if (status_buffer != NULL) {
+-		rec->type.status.status_type = status_buffer->status_type;
+-		rec->type.status.status_subtype = status_buffer->status_subtype;
+-		memcpy(&rec->type.status.queue_designator,
++		rec->u.status.status_type = status_buffer->status_type;
++		rec->u.status.status_subtype = status_buffer->status_subtype;
++		memcpy(&rec->u.status.queue_designator,
+ 		       &status_buffer->queue_designator,
+ 		       sizeof(struct fsf_queue_designator));
+ 
+ 		switch (status_buffer->status_type) {
+ 		case FSF_STATUS_READ_SENSE_DATA_AVAIL:
+-			rec->type.status.payload_size =
++			rec->u.status.payload_size =
+ 			    ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL;
+ 			break;
+ 
+ 		case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
+-			rec->type.status.payload_size =
++			rec->u.status.payload_size =
+ 			    ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD;
+ 			break;
+ 
+@@ -270,119 +291,101 @@ zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
+ 			switch (status_buffer->status_subtype) {
+ 			case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
+ 			case FSF_STATUS_READ_SUB_FDISC_FAILED:
+-				rec->type.status.payload_size =
++				rec->u.status.payload_size =
+ 					sizeof(struct fsf_link_down_info);
+ 			}
+ 			break;
+ 
+ 		case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
+-			rec->type.status.payload_size =
++			rec->u.status.payload_size =
+ 			    ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT;
+ 			break;
+ 		}
+-		memcpy(&rec->type.status.payload,
+-		       &status_buffer->payload, rec->type.status.payload_size);
++		memcpy(&rec->u.status.payload,
++		       &status_buffer->payload, rec->u.status.payload_size);
+ 	}
+ 
+-	debug_event(adapter->hba_dbf, 2,
+-		    rec, sizeof(struct zfcp_hba_dbf_record));
++	debug_event(adapter->hba_dbf, 2, rec, sizeof(*rec));
+ 	spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ }
+ 
+-void
+-zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
+-			unsigned int qdio_error, unsigned int siga_error,
+-			int sbal_index, int sbal_count)
++/**
++ * zfcp_hba_dbf_event_qdio - trace event for QDIO related failure
++ * @adapter: adapter affected by this QDIO related event
++ * @status: as passed by qdio module
++ * @qdio_error: as passed by qdio module
++ * @siga_error: as passed by qdio module
++ * @sbal_index: first buffer with error condition, as passed by qdio module
++ * @sbal_count: number of buffers affected, as passed by qdio module
++ */
++void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
++			     unsigned int qdio_error, unsigned int siga_error,
++			     int sbal_index, int sbal_count)
+ {
+-	struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
++	struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+-	memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+-	strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE);
+-	rec->type.qdio.status = status;
+-	rec->type.qdio.qdio_error = qdio_error;
+-	rec->type.qdio.siga_error = siga_error;
+-	rec->type.qdio.sbal_index = sbal_index;
+-	rec->type.qdio.sbal_count = sbal_count;
+-	debug_event(adapter->hba_dbf, 0,
+-		    rec, sizeof(struct zfcp_hba_dbf_record));
++	memset(r, 0, sizeof(*r));
++	strncpy(r->tag, "qdio", ZFCP_DBF_TAG_SIZE);
++	r->u.qdio.status = status;
++	r->u.qdio.qdio_error = qdio_error;
++	r->u.qdio.siga_error = siga_error;
++	r->u.qdio.sbal_index = sbal_index;
++	r->u.qdio.sbal_count = sbal_count;
++	debug_event(adapter->hba_dbf, 0, r, sizeof(*r));
+ 	spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ }
+ 
+-static int
+-zfcp_hba_dbf_view_response(char *out_buf,
+-			   struct zfcp_hba_dbf_record_response *rec)
+-{
+-	int len = 0;
+-
+-	len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x",
+-			     rec->fsf_command);
+-	len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+-			     rec->fsf_reqid);
+-	len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+-			     rec->fsf_seqno);
+-	len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
+-	len += zfcp_dbf_view(out_buf + len, "fsf_prot_status", "0x%08x",
+-			     rec->fsf_prot_status);
+-	len += zfcp_dbf_view(out_buf + len, "fsf_status", "0x%08x",
+-			     rec->fsf_status);
+-	len += zfcp_dbf_view_dump(out_buf + len, "fsf_prot_status_qual",
+-				  rec->fsf_prot_status_qual,
+-				  FSF_PROT_STATUS_QUAL_SIZE,
+-				  0, FSF_PROT_STATUS_QUAL_SIZE);
+-	len += zfcp_dbf_view_dump(out_buf + len, "fsf_status_qual",
+-				  rec->fsf_status_qual,
+-				  FSF_STATUS_QUALIFIER_SIZE,
+-				  0, FSF_STATUS_QUALIFIER_SIZE);
+-	len += zfcp_dbf_view(out_buf + len, "fsf_req_status", "0x%08x",
+-			     rec->fsf_req_status);
+-	len += zfcp_dbf_view(out_buf + len, "sbal_first", "0x%02x",
+-			     rec->sbal_first);
+-	len += zfcp_dbf_view(out_buf + len, "sbal_curr", "0x%02x",
+-			     rec->sbal_curr);
+-	len += zfcp_dbf_view(out_buf + len, "sbal_last", "0x%02x",
+-			     rec->sbal_last);
+-	len += zfcp_dbf_view(out_buf + len, "pool", "0x%02x", rec->pool);
+-
+-	switch (rec->fsf_command) {
++static void zfcp_hba_dbf_view_response(char **p,
++				       struct zfcp_hba_dbf_record_response *r)
++{
++	struct timespec t;
++
++	zfcp_dbf_out(p, "fsf_command", "0x%08x", r->fsf_command);
++	zfcp_dbf_out(p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
++	zfcp_dbf_out(p, "fsf_seqno", "0x%08x", r->fsf_seqno);
++	zfcp_dbf_timestamp(r->fsf_issued, &t);
++	zfcp_dbf_out(p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
++	zfcp_dbf_out(p, "fsf_prot_status", "0x%08x", r->fsf_prot_status);
++	zfcp_dbf_out(p, "fsf_status", "0x%08x", r->fsf_status);
++	zfcp_dbf_outd(p, "fsf_prot_status_qual", r->fsf_prot_status_qual,
++		      FSF_PROT_STATUS_QUAL_SIZE, 0, FSF_PROT_STATUS_QUAL_SIZE);
++	zfcp_dbf_outd(p, "fsf_status_qual", r->fsf_status_qual,
++		      FSF_STATUS_QUALIFIER_SIZE, 0, FSF_STATUS_QUALIFIER_SIZE);
++	zfcp_dbf_out(p, "fsf_req_status", "0x%08x", r->fsf_req_status);
++	zfcp_dbf_out(p, "sbal_first", "0x%02x", r->sbal_first);
++	zfcp_dbf_out(p, "sbal_curr", "0x%02x", r->sbal_curr);
++	zfcp_dbf_out(p, "sbal_last", "0x%02x", r->sbal_last);
++	zfcp_dbf_out(p, "pool", "0x%02x", r->pool);
++
++	switch (r->fsf_command) {
+ 	case FSF_QTCB_FCP_CMND:
+-		if (rec->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
++		if (r->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
+ 			break;
+-		len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
+-				     rec->data.send_fcp.scsi_cmnd);
+-		len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
+-				     rec->data.send_fcp.scsi_serial);
++		zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
++		zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
+ 		break;
+ 
+ 	case FSF_QTCB_OPEN_PORT_WITH_DID:
+ 	case FSF_QTCB_CLOSE_PORT:
+ 	case FSF_QTCB_CLOSE_PHYSICAL_PORT:
+-		len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
+-				     rec->data.port.wwpn);
+-		len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
+-				     rec->data.port.d_id);
+-		len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
+-				     rec->data.port.port_handle);
++		zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.port.wwpn);
++		zfcp_dbf_out(p, "d_id", "0x%06x", r->u.port.d_id);
++		zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.port.port_handle);
+ 		break;
+ 
+ 	case FSF_QTCB_OPEN_LUN:
+ 	case FSF_QTCB_CLOSE_LUN:
+-		len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
+-				     rec->data.unit.wwpn);
+-		len += zfcp_dbf_view(out_buf + len, "fcp_lun", "0x%016Lx",
+-				     rec->data.unit.fcp_lun);
+-		len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
+-				     rec->data.unit.port_handle);
+-		len += zfcp_dbf_view(out_buf + len, "lun_handle", "0x%08x",
+-				     rec->data.unit.lun_handle);
++		zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.unit.wwpn);
++		zfcp_dbf_out(p, "fcp_lun", "0x%016Lx", r->u.unit.fcp_lun);
++		zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.unit.port_handle);
++		zfcp_dbf_out(p, "lun_handle", "0x%08x", r->u.unit.lun_handle);
+ 		break;
+ 
+ 	case FSF_QTCB_SEND_ELS:
+-		len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
+-				     rec->data.send_els.d_id);
+-		len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
+-				     rec->data.send_els.ls_code);
++		zfcp_dbf_out(p, "d_id", "0x%06x", r->u.els.d_id);
++		zfcp_dbf_out(p, "ls_code", "0x%02x", r->u.els.ls_code);
+ 		break;
+ 
+ 	case FSF_QTCB_ABORT_FCP_CMND:
+@@ -393,74 +396,52 @@ zfcp_hba_dbf_view_response(char *out_buf,
+ 	case FSF_QTCB_UPLOAD_CONTROL_FILE:
+ 		break;
+ 	}
+-
+-	return len;
+ }
+ 
+-static int
+-zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
++static void zfcp_hba_dbf_view_status(char **p,
++				     struct zfcp_hba_dbf_record_status *r)
+ {
+-	int len = 0;
+-
+-	len += zfcp_dbf_view(out_buf + len, "failed", "0x%02x", rec->failed);
+-	len += zfcp_dbf_view(out_buf + len, "status_type", "0x%08x",
+-			     rec->status_type);
+-	len += zfcp_dbf_view(out_buf + len, "status_subtype", "0x%08x",
+-			     rec->status_subtype);
+-	len += zfcp_dbf_view_dump(out_buf + len, "queue_designator",
+-				  (char *)&rec->queue_designator,
+-				  sizeof(struct fsf_queue_designator),
+-				  0, sizeof(struct fsf_queue_designator));
+-	len += zfcp_dbf_view_dump(out_buf + len, "payload",
+-				  (char *)&rec->payload,
+-				  rec->payload_size, 0, rec->payload_size);
+-
+-	return len;
++	zfcp_dbf_out(p, "failed", "0x%02x", r->failed);
++	zfcp_dbf_out(p, "status_type", "0x%08x", r->status_type);
++	zfcp_dbf_out(p, "status_subtype", "0x%08x", r->status_subtype);
++	zfcp_dbf_outd(p, "queue_designator", (char *)&r->queue_designator,
++		      sizeof(struct fsf_queue_designator), 0,
++		      sizeof(struct fsf_queue_designator));
++	zfcp_dbf_outd(p, "payload", (char *)&r->payload, r->payload_size, 0,
++		      r->payload_size);
+ }
+ 
+-static int
+-zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec)
++static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r)
+ {
+-	int len = 0;
+-
+-	len += zfcp_dbf_view(out_buf + len, "status", "0x%08x", rec->status);
+-	len += zfcp_dbf_view(out_buf + len, "qdio_error", "0x%08x",
+-			     rec->qdio_error);
+-	len += zfcp_dbf_view(out_buf + len, "siga_error", "0x%08x",
+-			     rec->siga_error);
+-	len += zfcp_dbf_view(out_buf + len, "sbal_index", "0x%02x",
+-			     rec->sbal_index);
+-	len += zfcp_dbf_view(out_buf + len, "sbal_count", "0x%02x",
+-			     rec->sbal_count);
+-
+-	return len;
++	zfcp_dbf_out(p, "status", "0x%08x", r->status);
++	zfcp_dbf_out(p, "qdio_error", "0x%08x", r->qdio_error);
++	zfcp_dbf_out(p, "siga_error", "0x%08x", r->siga_error);
++	zfcp_dbf_out(p, "sbal_index", "0x%02x", r->sbal_index);
++	zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count);
+ }
+ 
+-static int
+-zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view,
+-			 char *out_buf, const char *in_buf)
++static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
++				    char *out_buf, const char *in_buf)
+ {
+-	struct zfcp_hba_dbf_record *rec = (struct zfcp_hba_dbf_record *)in_buf;
+-	int len = 0;
++	struct zfcp_hba_dbf_record *r = (struct zfcp_hba_dbf_record *)in_buf;
++	char *p = out_buf;
+ 
+-	if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
++	if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+ 		return 0;
+ 
+-	len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+-	if (isalpha(rec->tag2[0]))
+-		len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
+-	if (strncmp(rec->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
+-		len += zfcp_hba_dbf_view_response(out_buf + len,
+-						  &rec->type.response);
+-	else if (strncmp(rec->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
+-		len += zfcp_hba_dbf_view_status(out_buf + len,
+-						&rec->type.status);
+-	else if (strncmp(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
+-		len += zfcp_hba_dbf_view_qdio(out_buf + len, &rec->type.qdio);
++	zfcp_dbf_tag(&p, "tag", r->tag);
++	if (isalpha(r->tag2[0]))
++		zfcp_dbf_tag(&p, "tag2", r->tag2);
+ 
+-	len += sprintf(out_buf + len, "\n");
++	if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
++		zfcp_hba_dbf_view_response(&p, &r->u.response);
++	else if (strncmp(r->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
++		zfcp_hba_dbf_view_status(&p, &r->u.status);
++	else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
++		zfcp_hba_dbf_view_qdio(&p, &r->u.qdio);
+ 
+-	return len;
++	p += sprintf(p, "\n");
++	return p - out_buf;
+ }
+ 
+ static struct debug_view zfcp_hba_dbf_view = {
+@@ -472,219 +453,570 @@ static struct debug_view zfcp_hba_dbf_view = {
+ 	NULL
+ };
+ 
+-static void
+-_zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
+-			      u32 s_id, u32 d_id, void *buffer, int buflen)
++static const char *zfcp_rec_dbf_tags[] = {
++	[ZFCP_REC_DBF_ID_THREAD] = "thread",
++	[ZFCP_REC_DBF_ID_TARGET] = "target",
++	[ZFCP_REC_DBF_ID_TRIGGER] = "trigger",
++	[ZFCP_REC_DBF_ID_ACTION] = "action",
++};
++
++static const char *zfcp_rec_dbf_ids[] = {
++	[1]	= "new",
++	[2]	= "ready",
++	[3]	= "kill",
++	[4]	= "down sleep",
++	[5]	= "down wakeup",
++	[6]	= "down sleep ecd",
++	[7]	= "down wakeup ecd",
++	[8]	= "down sleep epd",
++	[9]	= "down wakeup epd",
++	[10]	= "online",
++	[11]	= "operational",
++	[12]	= "scsi slave destroy",
++	[13]	= "propagate failed adapter",
++	[14]	= "propagate failed port",
++	[15]	= "block adapter",
++	[16]	= "unblock adapter",
++	[17]	= "block port",
++	[18]	= "unblock port",
++	[19]	= "block unit",
++	[20]	= "unblock unit",
++	[21]	= "unit recovery failed",
++	[22]	= "port recovery failed",
++	[23]	= "adapter recovery failed",
++	[24]	= "qdio queues down",
++	[25]	= "p2p failed",
++	[26]	= "nameserver lookup failed",
++	[27]	= "nameserver port failed",
++	[28]	= "link up",
++	[29]	= "link down",
++	[30]	= "link up status read",
++	[31]	= "open port failed",
++	[32]	= "open port failed",
++	[33]	= "close port",
++	[34]	= "open unit failed",
++	[35]	= "exclusive open unit failed",
++	[36]	= "shared open unit failed",
++	[37]	= "link down",
++	[38]	= "link down status read no link",
++	[39]	= "link down status read fdisc login",
++	[40]	= "link down status read firmware update",
++	[41]	= "link down status read unknown reason",
++	[42]	= "link down ecd incomplete",
++	[43]	= "link down epd incomplete",
++	[44]	= "sysfs adapter recovery",
++	[45]	= "sysfs port recovery",
++	[46]	= "sysfs unit recovery",
++	[47]	= "port boxed abort",
++	[48]	= "unit boxed abort",
++	[49]	= "port boxed ct",
++	[50]	= "port boxed close physical",
++	[51]	= "port boxed open unit",
++	[52]	= "port boxed close unit",
++	[53]	= "port boxed fcp",
++	[54]	= "unit boxed fcp",
++	[55]	= "port access denied ct",
++	[56]	= "port access denied els",
++	[57]	= "port access denied open port",
++	[58]	= "port access denied close physical",
++	[59]	= "unit access denied open unit",
++	[60]	= "shared unit access denied open unit",
++	[61]	= "unit access denied fcp",
++	[62]	= "request timeout",
++	[63]	= "adisc link test reject or timeout",
++	[64]	= "adisc link test d_id changed",
++	[65]	= "adisc link test failed",
++	[66]	= "recovery out of memory",
++	[67]	= "adapter recovery repeated after state change",
++	[68]	= "port recovery repeated after state change",
++	[69]	= "unit recovery repeated after state change",
++	[70]	= "port recovery follow-up after successful adapter recovery",
++	[71]	= "adapter recovery escalation after failed adapter recovery",
++	[72]	= "port recovery follow-up after successful physical port "
++		  "recovery",
++	[73]	= "adapter recovery escalation after failed physical port "
++		  "recovery",
++	[74]	= "unit recovery follow-up after successful port recovery",
++	[75]	= "physical port recovery escalation after failed port "
++		  "recovery",
++	[76]	= "port recovery escalation after failed unit recovery",
++	[77]	= "recovery opening nameserver port",
++	[78]	= "duplicate request id",
++	[79]	= "link down",
++	[80]	= "exclusive read-only unit access unsupported",
++	[81]	= "shared read-write unit access unsupported",
++	[82]	= "incoming rscn",
++	[83]	= "incoming plogi",
++	[84]	= "incoming logo",
++	[85]	= "online",
++	[86]	= "offline",
++	[87]	= "ccw device gone",
++	[88]	= "ccw device no path",
++	[89]	= "ccw device operational",
++	[90]	= "ccw device shutdown",
++	[91]	= "sysfs port addition",
++	[92]	= "sysfs port removal",
++	[93]	= "sysfs adapter recovery",
++	[94]	= "sysfs unit addition",
++	[95]	= "sysfs unit removal",
++	[96]	= "sysfs port recovery",
++	[97]	= "sysfs unit recovery",
++	[98]	= "sequence number mismatch",
++	[99]	= "link up",
++	[100]	= "error state",
++	[101]	= "status read physical port closed",
++	[102]	= "link up status read",
++	[103]	= "too many failed status read buffers",
++	[104]	= "port handle not valid abort",
++	[105]	= "lun handle not valid abort",
++	[106]	= "port handle not valid ct",
++	[107]	= "port handle not valid close port",
++	[108]	= "port handle not valid close physical port",
++	[109]	= "port handle not valid open unit",
++	[110]	= "port handle not valid close unit",
++	[111]	= "lun handle not valid close unit",
++	[112]	= "port handle not valid fcp",
++	[113]	= "lun handle not valid fcp",
++	[114]	= "handle mismatch fcp",
++	[115]	= "lun not valid fcp",
++	[116]	= "qdio send failed",
++	[117]	= "version mismatch",
++	[118]	= "incompatible qtcb type",
++	[119]	= "unknown protocol status",
++	[120]	= "unknown fsf command",
++	[121]	= "no recommendation for status qualifier",
++	[122]	= "status read physical port closed in error",
++	[123]	= "fc service class not supported ct",
++	[124]	= "fc service class not supported els",
++	[125]	= "need newer zfcp",
++	[126]	= "need newer microcode",
++	[127]	= "arbitrated loop not supported",
++	[128]	= "unknown topology",
++	[129]	= "qtcb size mismatch",
++	[130]	= "unknown fsf status ecd",
++	[131]	= "fcp request too big",
++	[132]	= "fc service class not supported fcp",
++	[133]	= "data direction not valid fcp",
++	[134]	= "command length not valid fcp",
++	[135]	= "status read act update",
++	[136]	= "status read cfdc update",
++	[137]	= "hbaapi port open",
++	[138]	= "hbaapi unit open",
++	[139]	= "hbaapi unit shutdown",
++	[140]	= "qdio error",
++	[141]	= "scsi host reset",
++	[142]	= "dismissing fsf request for recovery action",
++	[143]	= "recovery action timed out",
++	[144]	= "recovery action gone",
++	[145]	= "recovery action being processed",
++	[146]	= "recovery action ready for next step",
++};
++
++static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
++				    char *buf, const char *_rec)
++{
++	struct zfcp_rec_dbf_record *r = (struct zfcp_rec_dbf_record *)_rec;
++	char *p = buf;
++
++	zfcp_dbf_outs(&p, "tag", zfcp_rec_dbf_tags[r->id]);
++	zfcp_dbf_outs(&p, "hint", zfcp_rec_dbf_ids[r->id2]);
++	zfcp_dbf_out(&p, "id", "%d", r->id2);
++	switch (r->id) {
++	case ZFCP_REC_DBF_ID_THREAD:
++		zfcp_dbf_out(&p, "total", "%d", r->u.thread.total);
++		zfcp_dbf_out(&p, "ready", "%d", r->u.thread.ready);
++		zfcp_dbf_out(&p, "running", "%d", r->u.thread.running);
++		break;
++	case ZFCP_REC_DBF_ID_TARGET:
++		zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.target.ref);
++		zfcp_dbf_out(&p, "status", "0x%08x", r->u.target.status);
++		zfcp_dbf_out(&p, "erp_count", "%d", r->u.target.erp_count);
++		zfcp_dbf_out(&p, "d_id", "0x%06x", r->u.target.d_id);
++		zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.target.wwpn);
++		zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.target.fcp_lun);
++		break;
++	case ZFCP_REC_DBF_ID_TRIGGER:
++		zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.trigger.ref);
++		zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.trigger.action);
++		zfcp_dbf_out(&p, "requested", "%d", r->u.trigger.want);
++		zfcp_dbf_out(&p, "executed", "%d", r->u.trigger.need);
++		zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.trigger.wwpn);
++		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);
++		break;
++	case ZFCP_REC_DBF_ID_ACTION:
++		zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action);
++		zfcp_dbf_out(&p, "fsf_req", "0x%016Lx", r->u.action.fsf_req);
++		zfcp_dbf_out(&p, "status", "0x%08Lx", r->u.action.status);
++		zfcp_dbf_out(&p, "step", "0x%08Lx", r->u.action.step);
++		break;
++	}
++	p += sprintf(p, "\n");
++	return p - buf;
++}
++
++static struct debug_view zfcp_rec_dbf_view = {
++	"structured",
++	NULL,
++	&zfcp_dbf_view_header,
++	&zfcp_rec_dbf_view_format,
++	NULL,
++	NULL
++};
++
++/**
++ * zfcp_rec_dbf_event_thread - trace event related to recovery thread operation
++ * @id2: identifier for event
++ * @adapter: adapter
++ * @lock: non-zero value indicates that erp_lock has not yet been acquired
++ */
++void zfcp_rec_dbf_event_thread(u8 id2, struct zfcp_adapter *adapter, int lock)
++{
++	struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
++	unsigned long flags = 0;
++	struct list_head *entry;
++	unsigned ready = 0, running = 0, total;
++
++	if (lock)
++		read_lock_irqsave(&adapter->erp_lock, flags);
++	list_for_each(entry, &adapter->erp_ready_head)
++		ready++;
++	list_for_each(entry, &adapter->erp_running_head)
++		running++;
++	total = adapter->erp_total_count;
++	if (lock)
++		read_unlock_irqrestore(&adapter->erp_lock, flags);
++
++	spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
++	memset(r, 0, sizeof(*r));
++	r->id = ZFCP_REC_DBF_ID_THREAD;
++	r->id2 = id2;
++	r->u.thread.total = total;
++	r->u.thread.ready = ready;
++	r->u.thread.running = running;
++	debug_event(adapter->rec_dbf, 5, r, sizeof(*r));
++	spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
++}
++
++static void zfcp_rec_dbf_event_target(u8 id2, void *ref,
++				      struct zfcp_adapter *adapter,
++				      atomic_t *status, atomic_t *erp_count,
++				      u64 wwpn, u32 d_id, u64 fcp_lun)
++{
++	struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
++	unsigned long flags;
++
++	spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
++	memset(r, 0, sizeof(*r));
++	r->id = ZFCP_REC_DBF_ID_TARGET;
++	r->id2 = id2;
++	r->u.target.ref = (unsigned long)ref;
++	r->u.target.status = atomic_read(status);
++	r->u.target.wwpn = wwpn;
++	r->u.target.d_id = d_id;
++	r->u.target.fcp_lun = fcp_lun;
++	r->u.target.erp_count = atomic_read(erp_count);
++	debug_event(adapter->rec_dbf, 3, r, sizeof(*r));
++	spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
++}
++
++/**
++ * zfcp_rec_dbf_event_adapter - trace event for adapter state change
++ * @id: identifier for trigger of state change
++ * @ref: additional reference (e.g. request)
++ * @adapter: adapter
++ */
++void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *adapter)
++{
++	zfcp_rec_dbf_event_target(id, ref, adapter, &adapter->status,
++				  &adapter->erp_counter, 0, 0, 0);
++}
++
++/**
++ * zfcp_rec_dbf_event_port - trace event for port state change
++ * @id: identifier for trigger of state change
++ * @ref: additional reference (e.g. request)
++ * @port: port
++ */
++void zfcp_rec_dbf_event_port(u8 id, void *ref, struct zfcp_port *port)
+ {
+-	struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data;
+-	struct zfcp_port *port = send_ct->port;
+ 	struct zfcp_adapter *adapter = port->adapter;
+-	struct ct_hdr *header = (struct ct_hdr *)buffer;
+-	struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
+-	struct zfcp_san_dbf_record_ct *ct = &rec->type.ct;
++
++	zfcp_rec_dbf_event_target(id, ref, adapter, &port->status,
++				  &port->erp_counter, port->wwpn, port->d_id,
++				  0);
++}
++
++/**
++ * zfcp_rec_dbf_event_unit - trace event for unit state change
++ * @id: identifier for trigger of state change
++ * @ref: additional reference (e.g. request)
++ * @unit: unit
++ */
++void zfcp_rec_dbf_event_unit(u8 id, void *ref, struct zfcp_unit *unit)
++{
++	struct zfcp_port *port = unit->port;
++	struct zfcp_adapter *adapter = port->adapter;
++
++	zfcp_rec_dbf_event_target(id, ref, adapter, &unit->status,
++				  &unit->erp_counter, port->wwpn, port->d_id,
++				  unit->fcp_lun);
++}
++
++/**
++ * zfcp_rec_dbf_event_trigger - trace event for triggered error recovery
++ * @id2: identifier for error recovery trigger
++ * @ref: additional reference (e.g. request)
++ * @want: originally requested error recovery action
++ * @need: error recovery action actually initiated
++ * @action: address of error recovery action struct
++ * @adapter: adapter
++ * @port: port
++ * @unit: unit
++ */
++void zfcp_rec_dbf_event_trigger(u8 id2, void *ref, u8 want, u8 need,
++				void *action, struct zfcp_adapter *adapter,
++				struct zfcp_port *port, struct zfcp_unit *unit)
++{
++	struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+ 	unsigned long flags;
+ 
+-	spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+-	memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
+-	strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+-	rec->fsf_reqid = (unsigned long)fsf_req;
+-	rec->fsf_seqno = fsf_req->seq_no;
+-	rec->s_id = s_id;
+-	rec->d_id = d_id;
+-	if (strncmp(tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
+-		ct->type.request.cmd_req_code = header->cmd_rsp_code;
+-		ct->type.request.revision = header->revision;
+-		ct->type.request.gs_type = header->gs_type;
+-		ct->type.request.gs_subtype = header->gs_subtype;
+-		ct->type.request.options = header->options;
+-		ct->type.request.max_res_size = header->max_res_size;
+-	} else if (strncmp(tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
+-		ct->type.response.cmd_rsp_code = header->cmd_rsp_code;
+-		ct->type.response.revision = header->revision;
+-		ct->type.response.reason_code = header->reason_code;
+-		ct->type.response.reason_code_expl = header->reason_code_expl;
+-		ct->type.response.vendor_unique = header->vendor_unique;
++	spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
++	memset(r, 0, sizeof(*r));
++	r->id = ZFCP_REC_DBF_ID_TRIGGER;
++	r->id2 = id2;
++	r->u.trigger.ref = (unsigned long)ref;
++	r->u.trigger.want = want;
++	r->u.trigger.need = need;
++	r->u.trigger.action = (unsigned long)action;
++	r->u.trigger.as = atomic_read(&adapter->status);
++	if (port) {
++		r->u.trigger.ps = atomic_read(&port->status);
++		r->u.trigger.wwpn = port->wwpn;
+ 	}
+-	ct->payload_size =
+-	    min(buflen - (int)sizeof(struct ct_hdr), ZFCP_DBF_CT_PAYLOAD);
+-	memcpy(ct->payload, buffer + sizeof(struct ct_hdr), ct->payload_size);
+-	debug_event(adapter->san_dbf, 3,
+-		    rec, sizeof(struct zfcp_san_dbf_record));
+-	spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
++	if (unit) {
++		r->u.trigger.us = atomic_read(&unit->status);
++		r->u.trigger.fcp_lun = unit->fcp_lun;
++	}
++	debug_event(adapter->rec_dbf, action ? 1 : 4, r, sizeof(*r));
++	spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+ }
+ 
++/**
++ * zfcp_rec_dbf_event_action - trace event showing progress of recovery action
++ * @id2: identifier
++ * @erp_action: error recovery action struct pointer
++ */
++void zfcp_rec_dbf_event_action(u8 id2, struct zfcp_erp_action *erp_action)
++{
++	struct zfcp_adapter *adapter = erp_action->adapter;
++	struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
++	unsigned long flags;
++
++	spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
++	memset(r, 0, sizeof(*r));
++	r->id = ZFCP_REC_DBF_ID_ACTION;
++	r->id2 = id2;
++	r->u.action.action = (unsigned long)erp_action;
++	r->u.action.status = erp_action->status;
++	r->u.action.step = erp_action->step;
++	r->u.action.fsf_req = (unsigned long)erp_action->fsf_req;
++	debug_event(adapter->rec_dbf, 4, r, sizeof(*r));
++	spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
++}
++
++/**
++ * zfcp_san_dbf_event_ct_request - trace event for issued CT request
++ * @fsf_req: request containing issued CT data
++ */
+ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
+ {
+ 	struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
+ 	struct zfcp_port *port = ct->port;
+ 	struct zfcp_adapter *adapter = port->adapter;
++	struct ct_hdr *hdr = zfcp_sg_to_address(ct->req);
++	struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
++	struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req;
++	unsigned long flags;
+ 
+-	_zfcp_san_dbf_event_common_ct("octc", fsf_req,
+-				      fc_host_port_id(adapter->scsi_host),
+-				      port->d_id, zfcp_sg_to_address(ct->req),
+-				      ct->req->length);
++	spin_lock_irqsave(&adapter->san_dbf_lock, flags);
++	memset(r, 0, sizeof(*r));
++	strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE);
++	r->fsf_reqid = (unsigned long)fsf_req;
++	r->fsf_seqno = fsf_req->seq_no;
++	r->s_id = fc_host_port_id(adapter->scsi_host);
++	r->d_id = port->d_id;
++	oct->cmd_req_code = hdr->cmd_rsp_code;
++	oct->revision = hdr->revision;
++	oct->gs_type = hdr->gs_type;
++	oct->gs_subtype = hdr->gs_subtype;
++	oct->options = hdr->options;
++	oct->max_res_size = hdr->max_res_size;
++	oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr),
++		       ZFCP_DBF_CT_PAYLOAD);
++	memcpy(oct->payload, (void *)hdr + sizeof(struct ct_hdr), oct->len);
++	debug_event(adapter->san_dbf, 3, r, sizeof(*r));
++	spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+ }
+ 
++/**
++ * zfcp_san_dbf_event_ct_response - trace event for completion of CT request
++ * @fsf_req: request containing CT response
++ */
+ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
+ {
+ 	struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
+ 	struct zfcp_port *port = ct->port;
+ 	struct zfcp_adapter *adapter = port->adapter;
++	struct ct_hdr *hdr = zfcp_sg_to_address(ct->resp);
++	struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
++	struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp;
++	unsigned long flags;
+ 
+-	_zfcp_san_dbf_event_common_ct("rctc", fsf_req, port->d_id,
+-				      fc_host_port_id(adapter->scsi_host),
+-				      zfcp_sg_to_address(ct->resp),
+-				      ct->resp->length);
++	spin_lock_irqsave(&adapter->san_dbf_lock, flags);
++	memset(r, 0, sizeof(*r));
++	strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE);
++	r->fsf_reqid = (unsigned long)fsf_req;
++	r->fsf_seqno = fsf_req->seq_no;
++	r->s_id = port->d_id;
++	r->d_id = fc_host_port_id(adapter->scsi_host);
++	rct->cmd_rsp_code = hdr->cmd_rsp_code;
++	rct->revision = hdr->revision;
++	rct->reason_code = hdr->reason_code;
++	rct->expl = hdr->reason_code_expl;
++	rct->vendor_unique = hdr->vendor_unique;
++	rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
++		       ZFCP_DBF_CT_PAYLOAD);
++	memcpy(rct->payload, (void *)hdr + sizeof(struct ct_hdr), rct->len);
++	debug_event(adapter->san_dbf, 3, r, sizeof(*r));
++	spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+ }
+ 
+-static void
+-_zfcp_san_dbf_event_common_els(const char *tag, int level,
+-			       struct zfcp_fsf_req *fsf_req, u32 s_id,
+-			       u32 d_id, u8 ls_code, void *buffer, int buflen)
++static void zfcp_san_dbf_event_els(const char *tag, int level,
++				   struct zfcp_fsf_req *fsf_req, u32 s_id,
++				   u32 d_id, u8 ls_code, void *buffer,
++				   int buflen)
+ {
+ 	struct zfcp_adapter *adapter = fsf_req->adapter;
+ 	struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
+-	struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
+ 	unsigned long flags;
+-	int offset = 0;
+ 
+ 	spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+-	do {
+-		memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
+-		if (offset == 0) {
+-			strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+-			rec->fsf_reqid = (unsigned long)fsf_req;
+-			rec->fsf_seqno = fsf_req->seq_no;
+-			rec->s_id = s_id;
+-			rec->d_id = d_id;
+-			rec->type.els.ls_code = ls_code;
+-			buflen = min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD);
+-			rec->type.els.payload_size = buflen;
+-			memcpy(rec->type.els.payload,
+-			       buffer, min(buflen, ZFCP_DBF_ELS_PAYLOAD));
+-			offset += min(buflen, ZFCP_DBF_ELS_PAYLOAD);
+-		} else {
+-			strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
+-			dump->total_size = buflen;
+-			dump->offset = offset;
+-			dump->size = min(buflen - offset,
+-					 (int)sizeof(struct zfcp_san_dbf_record)
+-					 - (int)sizeof(struct zfcp_dbf_dump));
+-			memcpy(dump->data, buffer + offset, dump->size);
+-			offset += dump->size;
+-		}
+-		debug_event(adapter->san_dbf, level,
+-			    rec, sizeof(struct zfcp_san_dbf_record));
+-	} while (offset < buflen);
++	memset(rec, 0, sizeof(*rec));
++	strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
++	rec->fsf_reqid = (unsigned long)fsf_req;
++	rec->fsf_seqno = fsf_req->seq_no;
++	rec->s_id = s_id;
++	rec->d_id = d_id;
++	rec->u.els.ls_code = ls_code;
++	debug_event(adapter->san_dbf, level, rec, sizeof(*rec));
++	zfcp_dbf_hexdump(adapter->san_dbf, rec, sizeof(*rec), level,
++			 buffer, min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD));
+ 	spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+ }
+ 
++/**
++ * zfcp_san_dbf_event_els_request - trace event for issued ELS
++ * @fsf_req: request containing issued ELS
++ */
+ void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
+ {
+ 	struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+ 
+-	_zfcp_san_dbf_event_common_els("oels", 2, fsf_req,
+-				       fc_host_port_id(els->adapter->scsi_host),
+-				       els->d_id,
+-				       *(u8 *) zfcp_sg_to_address(els->req),
+-				       zfcp_sg_to_address(els->req),
+-				       els->req->length);
++	zfcp_san_dbf_event_els("oels", 2, fsf_req,
++			       fc_host_port_id(els->adapter->scsi_host),
++			       els->d_id, *(u8 *) zfcp_sg_to_address(els->req),
++			       zfcp_sg_to_address(els->req), els->req->length);
+ }
+ 
++/**
++ * zfcp_san_dbf_event_els_response - trace event for completed ELS
++ * @fsf_req: request containing ELS response
++ */
+ void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
+ {
+ 	struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+ 
+-	_zfcp_san_dbf_event_common_els("rels", 2, fsf_req, els->d_id,
+-				       fc_host_port_id(els->adapter->scsi_host),
+-				       *(u8 *) zfcp_sg_to_address(els->req),
+-				       zfcp_sg_to_address(els->resp),
+-				       els->resp->length);
++	zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id,
++			       fc_host_port_id(els->adapter->scsi_host),
++			       *(u8 *)zfcp_sg_to_address(els->req),
++			       zfcp_sg_to_address(els->resp),
++			       els->resp->length);
+ }
+ 
++/**
++ * zfcp_san_dbf_event_incoming_els - trace event for incomig ELS
++ * @fsf_req: request containing unsolicited status buffer with incoming ELS
++ */
+ void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
+ {
+ 	struct zfcp_adapter *adapter = fsf_req->adapter;
+-	struct fsf_status_read_buffer *status_buffer =
+-	    (struct fsf_status_read_buffer *)fsf_req->data;
+-	int length = (int)status_buffer->length -
+-	    (int)((void *)&status_buffer->payload - (void *)status_buffer);
+-
+-	_zfcp_san_dbf_event_common_els("iels", 1, fsf_req, status_buffer->d_id,
+-				       fc_host_port_id(adapter->scsi_host),
+-				       *(u8 *) status_buffer->payload,
+-				       (void *)status_buffer->payload, length);
++	struct fsf_status_read_buffer *buf =
++			(struct fsf_status_read_buffer *)fsf_req->data;
++	int length = (int)buf->length -
++		     (int)((void *)&buf->payload - (void *)buf);
++
++	zfcp_san_dbf_event_els("iels", 1, fsf_req, buf->d_id,
++			       fc_host_port_id(adapter->scsi_host),
++			       *(u8 *)buf->payload, (void *)buf->payload,
++			       length);
+ }
+ 
+-static int
+-zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view,
+-			 char *out_buf, const char *in_buf)
++static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
++				    char *out_buf, const char *in_buf)
+ {
+-	struct zfcp_san_dbf_record *rec = (struct zfcp_san_dbf_record *)in_buf;
++	struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf;
+ 	char *buffer = NULL;
+ 	int buflen = 0, total = 0;
+-	int len = 0;
++	char *p = out_buf;
+ 
+-	if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
++	if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+ 		return 0;
+ 
+-	len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+-	len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+-			     rec->fsf_reqid);
+-	len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+-			     rec->fsf_seqno);
+-	len += zfcp_dbf_view(out_buf + len, "s_id", "0x%06x", rec->s_id);
+-	len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", rec->d_id);
+-
+-	if (strncmp(rec->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
+-		len += zfcp_dbf_view(out_buf + len, "cmd_req_code", "0x%04x",
+-				     rec->type.ct.type.request.cmd_req_code);
+-		len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
+-				     rec->type.ct.type.request.revision);
+-		len += zfcp_dbf_view(out_buf + len, "gs_type", "0x%02x",
+-				     rec->type.ct.type.request.gs_type);
+-		len += zfcp_dbf_view(out_buf + len, "gs_subtype", "0x%02x",
+-				     rec->type.ct.type.request.gs_subtype);
+-		len += zfcp_dbf_view(out_buf + len, "options", "0x%02x",
+-				     rec->type.ct.type.request.options);
+-		len += zfcp_dbf_view(out_buf + len, "max_res_size", "0x%04x",
+-				     rec->type.ct.type.request.max_res_size);
+-		total = rec->type.ct.payload_size;
+-		buffer = rec->type.ct.payload;
++	zfcp_dbf_tag(&p, "tag", r->tag);
++	zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
++	zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
++	zfcp_dbf_out(&p, "s_id", "0x%06x", r->s_id);
++	zfcp_dbf_out(&p, "d_id", "0x%06x", r->d_id);
++
++	if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
++		struct zfcp_san_dbf_record_ct_request *ct = &r->u.ct_req;
++		zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code);
++		zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
++		zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type);
++		zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype);
++		zfcp_dbf_out(&p, "options", "0x%02x", ct->options);
++		zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
++		total = ct->len;
++		buffer = ct->payload;
+ 		buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
+-	} else if (strncmp(rec->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
+-		len += zfcp_dbf_view(out_buf + len, "cmd_rsp_code", "0x%04x",
+-				     rec->type.ct.type.response.cmd_rsp_code);
+-		len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
+-				     rec->type.ct.type.response.revision);
+-		len += zfcp_dbf_view(out_buf + len, "reason_code", "0x%02x",
+-				     rec->type.ct.type.response.reason_code);
+-		len +=
+-		    zfcp_dbf_view(out_buf + len, "reason_code_expl", "0x%02x",
+-				  rec->type.ct.type.response.reason_code_expl);
+-		len +=
+-		    zfcp_dbf_view(out_buf + len, "vendor_unique", "0x%02x",
+-				  rec->type.ct.type.response.vendor_unique);
+-		total = rec->type.ct.payload_size;
+-		buffer = rec->type.ct.payload;
++	} else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
++		struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp;
++		zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code);
++		zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
++		zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code);
++		zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl);
++		zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique);
++		total = ct->len;
++		buffer = ct->payload;
+ 		buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
+-	} else if (strncmp(rec->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
+-		   strncmp(rec->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
+-		   strncmp(rec->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
+-		len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
+-				     rec->type.els.ls_code);
+-		total = rec->type.els.payload_size;
+-		buffer = rec->type.els.payload;
++	} else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
++		   strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
++		   strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
++		struct zfcp_san_dbf_record_els *els = &r->u.els;
++		zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code);
++		total = els->len;
++		buffer = els->payload;
+ 		buflen = min(total, ZFCP_DBF_ELS_PAYLOAD);
+ 	}
+ 
+-	len += zfcp_dbf_view_dump(out_buf + len, "payload",
+-				  buffer, buflen, 0, total);
+-
++	zfcp_dbf_outd(&p, "payload", buffer, buflen, 0, total);
+ 	if (buflen == total)
+-		len += sprintf(out_buf + len, "\n");
++		p += sprintf(p, "\n");
+ 
+-	return len;
++	return p - out_buf;
+ }
+ 
+ static struct debug_view zfcp_san_dbf_view = {
+@@ -696,12 +1028,11 @@ static struct debug_view zfcp_san_dbf_view = {
+ 	NULL
+ };
+ 
+-static void
+-_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+-			    struct zfcp_adapter *adapter,
+-			    struct scsi_cmnd *scsi_cmnd,
+-			    struct zfcp_fsf_req *fsf_req,
+-			    unsigned long old_req_id)
++static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
++				struct zfcp_adapter *adapter,
++				struct scsi_cmnd *scsi_cmnd,
++				struct zfcp_fsf_req *fsf_req,
++				unsigned long old_req_id)
+ {
+ 	struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
+ 	struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
+@@ -712,7 +1043,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+ 
+ 	spin_lock_irqsave(&adapter->scsi_dbf_lock, flags);
+ 	do {
+-		memset(rec, 0, sizeof(struct zfcp_scsi_dbf_record));
++		memset(rec, 0, sizeof(*rec));
+ 		if (offset == 0) {
+ 			strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+ 			strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
+@@ -738,20 +1069,16 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+ 				fcp_sns_info =
+ 				    zfcp_get_fcp_sns_info_ptr(fcp_rsp);
+ 
+-				rec->type.fcp.rsp_validity =
+-				    fcp_rsp->validity.value;
+-				rec->type.fcp.rsp_scsi_status =
+-				    fcp_rsp->scsi_status;
+-				rec->type.fcp.rsp_resid = fcp_rsp->fcp_resid;
++				rec->rsp_validity = fcp_rsp->validity.value;
++				rec->rsp_scsi_status = fcp_rsp->scsi_status;
++				rec->rsp_resid = fcp_rsp->fcp_resid;
+ 				if (fcp_rsp->validity.bits.fcp_rsp_len_valid)
+-					rec->type.fcp.rsp_code =
+-					    *(fcp_rsp_info + 3);
++					rec->rsp_code = *(fcp_rsp_info + 3);
+ 				if (fcp_rsp->validity.bits.fcp_sns_len_valid) {
+ 					buflen = min((int)fcp_rsp->fcp_sns_len,
+ 						     ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
+-					rec->type.fcp.sns_info_len = buflen;
+-					memcpy(rec->type.fcp.sns_info,
+-					       fcp_sns_info,
++					rec->sns_info_len = buflen;
++					memcpy(rec->sns_info, fcp_sns_info,
+ 					       min(buflen,
+ 						   ZFCP_DBF_SCSI_FCP_SNS_INFO));
+ 					offset += min(buflen,
+@@ -762,7 +1089,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+ 				rec->fsf_seqno = fsf_req->seq_no;
+ 				rec->fsf_issued = fsf_req->issued;
+ 			}
+-			rec->type.old_fsf_reqid = old_req_id;
++			rec->old_fsf_reqid = old_req_id;
+ 		} else {
+ 			strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
+ 			dump->total_size = buflen;
+@@ -774,108 +1101,101 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+ 			memcpy(dump->data, fcp_sns_info + offset, dump->size);
+ 			offset += dump->size;
+ 		}
+-		debug_event(adapter->scsi_dbf, level,
+-			    rec, sizeof(struct zfcp_scsi_dbf_record));
++		debug_event(adapter->scsi_dbf, level, rec, sizeof(*rec));
+ 	} while (offset < buflen);
+ 	spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
+ }
+ 
+-void
+-zfcp_scsi_dbf_event_result(const char *tag, int level,
+-			   struct zfcp_adapter *adapter,
+-			   struct scsi_cmnd *scsi_cmnd,
+-			   struct zfcp_fsf_req *fsf_req)
++/**
++ * zfcp_scsi_dbf_event_result - trace event for SCSI command completion
++ * @tag: tag indicating success or failure of SCSI command
++ * @level: trace level applicable for this event
++ * @adapter: adapter that has been used to issue the SCSI command
++ * @scsi_cmnd: SCSI command pointer
++ * @fsf_req: request used to issue SCSI command (might be NULL)
++ */
++void zfcp_scsi_dbf_event_result(const char *tag, int level,
++				struct zfcp_adapter *adapter,
++				struct scsi_cmnd *scsi_cmnd,
++				struct zfcp_fsf_req *fsf_req)
+ {
+-	_zfcp_scsi_dbf_event_common("rslt", tag, level,
+-			adapter, scsi_cmnd, fsf_req, 0);
++	zfcp_scsi_dbf_event("rslt", tag, level, adapter, scsi_cmnd, fsf_req, 0);
+ }
+ 
+-void
+-zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
+-			  struct scsi_cmnd *scsi_cmnd,
+-			  struct zfcp_fsf_req *new_fsf_req,
+-			  unsigned long old_req_id)
++/**
++ * zfcp_scsi_dbf_event_abort - trace event for SCSI command abort
++ * @tag: tag indicating success or failure of abort operation
++ * @adapter: adapter thas has been used to issue SCSI command to be aborted
++ * @scsi_cmnd: SCSI command to be aborted
++ * @new_fsf_req: request containing abort (might be NULL)
++ * @old_req_id: identifier of request containg SCSI command to be aborted
++ */
++void zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
++			       struct scsi_cmnd *scsi_cmnd,
++			       struct zfcp_fsf_req *new_fsf_req,
++			       unsigned long old_req_id)
+ {
+-	_zfcp_scsi_dbf_event_common("abrt", tag, 1,
+-			adapter, scsi_cmnd, new_fsf_req, old_req_id);
++	zfcp_scsi_dbf_event("abrt", tag, 1, adapter, scsi_cmnd, new_fsf_req,
++			    old_req_id);
+ }
+ 
+-void
+-zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
+-			     struct scsi_cmnd *scsi_cmnd)
++/**
++ * zfcp_scsi_dbf_event_devreset - trace event for Logical Unit or Target Reset
++ * @tag: tag indicating success or failure of reset operation
++ * @flag: indicates type of reset (Target Reset, Logical Unit Reset)
++ * @unit: unit that needs reset
++ * @scsi_cmnd: SCSI command which caused this error recovery
++ */
++void zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag,
++				  struct zfcp_unit *unit,
++				  struct scsi_cmnd *scsi_cmnd)
+ {
+-	struct zfcp_adapter *adapter = unit->port->adapter;
+-
+-	_zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
+-			tag, 1, adapter, scsi_cmnd, NULL, 0);
++	zfcp_scsi_dbf_event(flag == FCP_TARGET_RESET ? "trst" : "lrst", tag, 1,
++			    unit->port->adapter, scsi_cmnd, NULL, 0);
+ }
+ 
+-static int
+-zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
+-			  char *out_buf, const char *in_buf)
++static int zfcp_scsi_dbf_view_format(debug_info_t *id, struct debug_view *view,
++				     char *out_buf, const char *in_buf)
+ {
+-	struct zfcp_scsi_dbf_record *rec =
+-	    (struct zfcp_scsi_dbf_record *)in_buf;
+-	int len = 0;
++	struct zfcp_scsi_dbf_record *r = (struct zfcp_scsi_dbf_record *)in_buf;
++	struct timespec t;
++	char *p = out_buf;
+ 
+-	if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
++	if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+ 		return 0;
+ 
+-	len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+-	len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
+-	len += zfcp_dbf_view(out_buf + len, "scsi_id", "0x%08x", rec->scsi_id);
+-	len += zfcp_dbf_view(out_buf + len, "scsi_lun", "0x%08x",
+-			     rec->scsi_lun);
+-	len += zfcp_dbf_view(out_buf + len, "scsi_result", "0x%08x",
+-			     rec->scsi_result);
+-	len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
+-			     rec->scsi_cmnd);
+-	len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
+-			     rec->scsi_serial);
+-	len += zfcp_dbf_view_dump(out_buf + len, "scsi_opcode",
+-				  rec->scsi_opcode,
+-				  ZFCP_DBF_SCSI_OPCODE,
+-				  0, ZFCP_DBF_SCSI_OPCODE);
+-	len += zfcp_dbf_view(out_buf + len, "scsi_retries", "0x%02x",
+-			     rec->scsi_retries);
+-	len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
+-			     rec->scsi_allowed);
+-	if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
+-		len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx",
+-				     rec->type.old_fsf_reqid);
+-	}
+-	len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+-			     rec->fsf_reqid);
+-	len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+-			     rec->fsf_seqno);
+-	len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
+-	if (strncmp(rec->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
+-		len +=
+-		    zfcp_dbf_view(out_buf + len, "fcp_rsp_validity", "0x%02x",
+-				  rec->type.fcp.rsp_validity);
+-		len +=
+-		    zfcp_dbf_view(out_buf + len, "fcp_rsp_scsi_status",
+-				  "0x%02x", rec->type.fcp.rsp_scsi_status);
+-		len +=
+-		    zfcp_dbf_view(out_buf + len, "fcp_rsp_resid", "0x%08x",
+-				  rec->type.fcp.rsp_resid);
+-		len +=
+-		    zfcp_dbf_view(out_buf + len, "fcp_rsp_code", "0x%08x",
+-				  rec->type.fcp.rsp_code);
+-		len +=
+-		    zfcp_dbf_view(out_buf + len, "fcp_sns_info_len", "0x%08x",
+-				  rec->type.fcp.sns_info_len);
+-		len +=
+-		    zfcp_dbf_view_dump(out_buf + len, "fcp_sns_info",
+-				       rec->type.fcp.sns_info,
+-				       min((int)rec->type.fcp.sns_info_len,
+-					   ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
+-				       rec->type.fcp.sns_info_len);
++	zfcp_dbf_tag(&p, "tag", r->tag);
++	zfcp_dbf_tag(&p, "tag2", r->tag2);
++	zfcp_dbf_out(&p, "scsi_id", "0x%08x", r->scsi_id);
++	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);
++	zfcp_dbf_out(&p, "scsi_allowed", "0x%02x", r->scsi_allowed);
++	if (strncmp(r->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0)
++		zfcp_dbf_out(&p, "old_fsf_reqid", "0x%0Lx", r->old_fsf_reqid);
++	zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
++	zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
++	zfcp_dbf_timestamp(r->fsf_issued, &t);
++	zfcp_dbf_out(&p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
++
++	if (strncmp(r->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
++		zfcp_dbf_out(&p, "fcp_rsp_validity", "0x%02x", r->rsp_validity);
++		zfcp_dbf_out(&p, "fcp_rsp_scsi_status", "0x%02x",
++			     r->rsp_scsi_status);
++		zfcp_dbf_out(&p, "fcp_rsp_resid", "0x%08x", r->rsp_resid);
++		zfcp_dbf_out(&p, "fcp_rsp_code", "0x%08x", r->rsp_code);
++		zfcp_dbf_out(&p, "fcp_sns_info_len", "0x%08x", r->sns_info_len);
++		zfcp_dbf_outd(&p, "fcp_sns_info", r->sns_info,
++			      min((int)r->sns_info_len,
++			      ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
++			      r->sns_info_len);
+ 	}
+-
+-	len += sprintf(out_buf + len, "\n");
+-
+-	return len;
++	p += sprintf(p, "\n");
++	return p - out_buf;
+ }
+ 
+ static struct debug_view zfcp_scsi_dbf_view = {
+@@ -897,13 +1217,14 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
+ 	char dbf_name[DEBUG_MAX_NAME_LEN];
+ 
+ 	/* debug feature area which records recovery activity */
+-	sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
+-	adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
+-					  sizeof(struct zfcp_erp_dbf_record));
+-	if (!adapter->erp_dbf)
++	sprintf(dbf_name, "zfcp_%s_rec", zfcp_get_busid_by_adapter(adapter));
++	adapter->rec_dbf = debug_register(dbf_name, dbfsize, 1,
++					  sizeof(struct zfcp_rec_dbf_record));
++	if (!adapter->rec_dbf)
+ 		goto failed;
+-	debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
+-	debug_set_level(adapter->erp_dbf, 3);
++	debug_register_view(adapter->rec_dbf, &debug_hex_ascii_view);
++	debug_register_view(adapter->rec_dbf, &zfcp_rec_dbf_view);
++	debug_set_level(adapter->rec_dbf, 3);
+ 
+ 	/* debug feature area which records HBA (FSF and QDIO) conditions */
+ 	sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
+@@ -952,11 +1273,11 @@ void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
+ 	debug_unregister(adapter->scsi_dbf);
+ 	debug_unregister(adapter->san_dbf);
+ 	debug_unregister(adapter->hba_dbf);
+-	debug_unregister(adapter->erp_dbf);
++	debug_unregister(adapter->rec_dbf);
+ 	adapter->scsi_dbf = NULL;
+ 	adapter->san_dbf = NULL;
+ 	adapter->hba_dbf = NULL;
+-	adapter->erp_dbf = NULL;
++	adapter->rec_dbf = NULL;
+ }
+ 
+ #undef ZFCP_LOG_AREA
+diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
+new file mode 100644
+index 0000000..54c34e4
+--- /dev/null
++++ b/drivers/s390/scsi/zfcp_dbf.h
+@@ -0,0 +1,228 @@
++/*
++ * This file is part of the zfcp device driver for
++ * FCP adapters for IBM System z9 and zSeries.
++ *
++ * Copyright IBM Corp. 2008, 2008
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef ZFCP_DBF_H
++#define ZFCP_DBF_H
++
++#include "zfcp_fsf.h"
++
++#define ZFCP_DBF_TAG_SIZE      4
++
++struct zfcp_dbf_dump {
++	u8 tag[ZFCP_DBF_TAG_SIZE];
++	u32 total_size;		/* size of total dump data */
++	u32 offset;		/* how much data has being already dumped */
++	u32 size;		/* how much data comes with this record */
++	u8 data[];		/* dump data */
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_thread {
++	u32 total;
++	u32 ready;
++	u32 running;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_target {
++	u64 ref;
++	u32 status;
++	u32 d_id;
++	u64 wwpn;
++	u64 fcp_lun;
++	u32 erp_count;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_trigger {
++	u8 want;
++	u8 need;
++	u32 as;
++	u32 ps;
++	u32 us;
++	u64 ref;
++	u64 action;
++	u64 wwpn;
++	u64 fcp_lun;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_action {
++	u32 status;
++	u32 step;
++	u64 action;
++	u64 fsf_req;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record {
++	u8 id;
++	u8 id2;
++	union {
++		struct zfcp_rec_dbf_record_action action;
++		struct zfcp_rec_dbf_record_thread thread;
++		struct zfcp_rec_dbf_record_target target;
++		struct zfcp_rec_dbf_record_trigger trigger;
++	} u;
++} __attribute__ ((packed));
++
++enum {
++	ZFCP_REC_DBF_ID_ACTION,
++	ZFCP_REC_DBF_ID_THREAD,
++	ZFCP_REC_DBF_ID_TARGET,
++	ZFCP_REC_DBF_ID_TRIGGER,
++};
++
++struct zfcp_hba_dbf_record_response {
++	u32 fsf_command;
++	u64 fsf_reqid;
++	u32 fsf_seqno;
++	u64 fsf_issued;
++	u32 fsf_prot_status;
++	u32 fsf_status;
++	u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
++	u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
++	u32 fsf_req_status;
++	u8 sbal_first;
++	u8 sbal_curr;
++	u8 sbal_last;
++	u8 pool;
++	u64 erp_action;
++	union {
++		struct {
++			u64 cmnd;
++			u64 serial;
++		} fcp;
++		struct {
++			u64 wwpn;
++			u32 d_id;
++			u32 port_handle;
++		} port;
++		struct {
++			u64 wwpn;
++			u64 fcp_lun;
++			u32 port_handle;
++			u32 lun_handle;
++		} unit;
++		struct {
++			u32 d_id;
++			u8 ls_code;
++		} els;
++	} u;
++} __attribute__ ((packed));
++
++struct zfcp_hba_dbf_record_status {
++	u8 failed;
++	u32 status_type;
++	u32 status_subtype;
++	struct fsf_queue_designator
++	 queue_designator;
++	u32 payload_size;
++#define ZFCP_DBF_UNSOL_PAYLOAD				80
++#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL		32
++#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD	56
++#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT	2 * sizeof(u32)
++	u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_hba_dbf_record_qdio {
++	u32 status;
++	u32 qdio_error;
++	u32 siga_error;
++	u8 sbal_index;
++	u8 sbal_count;
++} __attribute__ ((packed));
++
++struct zfcp_hba_dbf_record {
++	u8 tag[ZFCP_DBF_TAG_SIZE];
++	u8 tag2[ZFCP_DBF_TAG_SIZE];
++	union {
++		struct zfcp_hba_dbf_record_response response;
++		struct zfcp_hba_dbf_record_status status;
++		struct zfcp_hba_dbf_record_qdio qdio;
++	} u;
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record_ct_request {
++	u16 cmd_req_code;
++	u8 revision;
++	u8 gs_type;
++	u8 gs_subtype;
++	u8 options;
++	u16 max_res_size;
++	u32 len;
++#define ZFCP_DBF_CT_PAYLOAD	24
++	u8 payload[ZFCP_DBF_CT_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record_ct_response {
++	u16 cmd_rsp_code;
++	u8 revision;
++	u8 reason_code;
++	u8 expl;
++	u8 vendor_unique;
++	u32 len;
++	u8 payload[ZFCP_DBF_CT_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record_els {
++	u8 ls_code;
++	u32 len;
++#define ZFCP_DBF_ELS_PAYLOAD	32
++#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
++	u8 payload[ZFCP_DBF_ELS_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record {
++	u8 tag[ZFCP_DBF_TAG_SIZE];
++	u64 fsf_reqid;
++	u32 fsf_seqno;
++	u32 s_id;
++	u32 d_id;
++	union {
++		struct zfcp_san_dbf_record_ct_request ct_req;
++		struct zfcp_san_dbf_record_ct_response ct_resp;
++		struct zfcp_san_dbf_record_els els;
++	} u;
++} __attribute__ ((packed));
++
++struct zfcp_scsi_dbf_record {
++	u8 tag[ZFCP_DBF_TAG_SIZE];
++	u8 tag2[ZFCP_DBF_TAG_SIZE];
++	u32 scsi_id;
++	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;
++	u8 scsi_allowed;
++	u64 fsf_reqid;
++	u32 fsf_seqno;
++	u64 fsf_issued;
++	u64 old_fsf_reqid;
++	u8 rsp_validity;
++	u8 rsp_scsi_status;
++	u32 rsp_resid;
++	u8 rsp_code;
++#define ZFCP_DBF_SCSI_FCP_SNS_INFO	16
++#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO	256
++	u32 sns_info_len;
++	u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
++} __attribute__ ((packed));
++
++#endif /* ZFCP_DBF_H */
+diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
+index 9e9f6c1..bda8c77 100644
+--- a/drivers/s390/scsi/zfcp_def.h
++++ b/drivers/s390/scsi/zfcp_def.h
+@@ -47,6 +47,7 @@
+ #include <asm/qdio.h>
+ #include <asm/debug.h>
+ #include <asm/ebcdic.h>
++#include "zfcp_dbf.h"
+ #include "zfcp_fsf.h"
+ 
+ 
+@@ -262,167 +263,6 @@ struct fcp_logo {
+ } __attribute__((packed));
+ 
+ /*
+- * DBF stuff
+- */
+-#define ZFCP_DBF_TAG_SIZE      4
+-
+-struct zfcp_dbf_dump {
+-	u8 tag[ZFCP_DBF_TAG_SIZE];
+-	u32 total_size;		/* size of total dump data */
+-	u32 offset;		/* how much data has being already dumped */
+-	u32 size;		/* how much data comes with this record */
+-	u8 data[];		/* dump data */
+-} __attribute__ ((packed));
+-
+-/* FIXME: to be inflated when reworking the erp dbf */
+-struct zfcp_erp_dbf_record {
+-	u8 dummy[16];
+-} __attribute__ ((packed));
+-
+-struct zfcp_hba_dbf_record_response {
+-	u32 fsf_command;
+-	u64 fsf_reqid;
+-	u32 fsf_seqno;
+-	u64 fsf_issued;
+-	u32 fsf_prot_status;
+-	u32 fsf_status;
+-	u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
+-	u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
+-	u32 fsf_req_status;
+-	u8 sbal_first;
+-	u8 sbal_curr;
+-	u8 sbal_last;
+-	u8 pool;
+-	u64 erp_action;
+-	union {
+-		struct {
+-			u64 scsi_cmnd;
+-			u64 scsi_serial;
+-		} send_fcp;
+-		struct {
+-			u64 wwpn;
+-			u32 d_id;
+-			u32 port_handle;
+-		} port;
+-		struct {
+-			u64 wwpn;
+-			u64 fcp_lun;
+-			u32 port_handle;
+-			u32 lun_handle;
+-		} unit;
+-		struct {
+-			u32 d_id;
+-			u8 ls_code;
+-		} send_els;
+-	} data;
+-} __attribute__ ((packed));
+-
+-struct zfcp_hba_dbf_record_status {
+-	u8 failed;
+-	u32 status_type;
+-	u32 status_subtype;
+-	struct fsf_queue_designator
+-	 queue_designator;
+-	u32 payload_size;
+-#define ZFCP_DBF_UNSOL_PAYLOAD				80
+-#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL		32
+-#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD	56
+-#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT	2 * sizeof(u32)
+-	u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
+-} __attribute__ ((packed));
+-
+-struct zfcp_hba_dbf_record_qdio {
+-	u32 status;
+-	u32 qdio_error;
+-	u32 siga_error;
+-	u8 sbal_index;
+-	u8 sbal_count;
+-} __attribute__ ((packed));
+-
+-struct zfcp_hba_dbf_record {
+-	u8 tag[ZFCP_DBF_TAG_SIZE];
+-	u8 tag2[ZFCP_DBF_TAG_SIZE];
+-	union {
+-		struct zfcp_hba_dbf_record_response response;
+-		struct zfcp_hba_dbf_record_status status;
+-		struct zfcp_hba_dbf_record_qdio qdio;
+-	} type;
+-} __attribute__ ((packed));
+-
+-struct zfcp_san_dbf_record_ct {
+-	union {
+-		struct {
+-			u16 cmd_req_code;
+-			u8 revision;
+-			u8 gs_type;
+-			u8 gs_subtype;
+-			u8 options;
+-			u16 max_res_size;
+-		} request;
+-		struct {
+-			u16 cmd_rsp_code;
+-			u8 revision;
+-			u8 reason_code;
+-			u8 reason_code_expl;
+-			u8 vendor_unique;
+-		} response;
+-	} type;
+-	u32 payload_size;
+-#define ZFCP_DBF_CT_PAYLOAD	24
+-	u8 payload[ZFCP_DBF_CT_PAYLOAD];
+-} __attribute__ ((packed));
+-
+-struct zfcp_san_dbf_record_els {
+-	u8 ls_code;
+-	u32 payload_size;
+-#define ZFCP_DBF_ELS_PAYLOAD	32
+-#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
+-	u8 payload[ZFCP_DBF_ELS_PAYLOAD];
+-} __attribute__ ((packed));
+-
+-struct zfcp_san_dbf_record {
+-	u8 tag[ZFCP_DBF_TAG_SIZE];
+-	u64 fsf_reqid;
+-	u32 fsf_seqno;
+-	u32 s_id;
+-	u32 d_id;
+-	union {
+-		struct zfcp_san_dbf_record_ct ct;
+-		struct zfcp_san_dbf_record_els els;
+-	} type;
+-} __attribute__ ((packed));
+-
+-struct zfcp_scsi_dbf_record {
+-	u8 tag[ZFCP_DBF_TAG_SIZE];
+-	u8 tag2[ZFCP_DBF_TAG_SIZE];
+-	u32 scsi_id;
+-	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;
+-	u8 scsi_allowed;
+-	u64 fsf_reqid;
+-	u32 fsf_seqno;
+-	u64 fsf_issued;
+-	union {
+-		u64 old_fsf_reqid;
+-		struct {
+-			u8 rsp_validity;
+-			u8 rsp_scsi_status;
+-			u32 rsp_resid;
+-			u8 rsp_code;
+-#define ZFCP_DBF_SCSI_FCP_SNS_INFO	16
+-#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO	256
+-			u32 sns_info_len;
+-			u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
+-		} fcp;
+-	} type;
+-} __attribute__ ((packed));
+-
+-/*
+  * FC-FS stuff
+  */
+ #define R_A_TOV				10 /* seconds */
+@@ -539,7 +379,7 @@ struct zfcp_rc_entry {
+ 
+ /* logging routine for zfcp */
+ #define _ZFCP_LOG(fmt, args...) \
+-	printk(KERN_ERR ZFCP_NAME": %s(%d): " fmt, __FUNCTION__, \
++	printk(KERN_ERR ZFCP_NAME": %s(%d): " fmt, __func__, \
+ 	       __LINE__ , ##args)
+ 
+ #define ZFCP_LOG(level, fmt, args...) \
+@@ -634,7 +474,6 @@ do { \
+ 		 ZFCP_STATUS_PORT_NO_SCSI_ID)
+ 
+ /* logical unit status */
+-#define ZFCP_STATUS_UNIT_NOTSUPPUNITRESET	0x00000001
+ #define ZFCP_STATUS_UNIT_TEMPORARY		0x00000002
+ #define ZFCP_STATUS_UNIT_SHARED			0x00000004
+ #define ZFCP_STATUS_UNIT_READONLY		0x00000008
+@@ -917,15 +756,15 @@ struct zfcp_adapter {
+ 	u32			erp_low_mem_count; /* nr of erp actions waiting
+ 						      for memory */
+ 	struct zfcp_port	*nameserver_port;  /* adapter's nameserver */
+-	debug_info_t		*erp_dbf;
++	debug_info_t		*rec_dbf;
+ 	debug_info_t		*hba_dbf;
+ 	debug_info_t		*san_dbf;          /* debug feature areas */
+ 	debug_info_t		*scsi_dbf;
+-	spinlock_t		erp_dbf_lock;
++	spinlock_t		rec_dbf_lock;
+ 	spinlock_t		hba_dbf_lock;
+ 	spinlock_t		san_dbf_lock;
+ 	spinlock_t		scsi_dbf_lock;
+-	struct zfcp_erp_dbf_record	erp_dbf_buf;
++	struct zfcp_rec_dbf_record	rec_dbf_buf;
+ 	struct zfcp_hba_dbf_record	hba_dbf_buf;
+ 	struct zfcp_san_dbf_record	san_dbf_buf;
+ 	struct zfcp_scsi_dbf_record	scsi_dbf_buf;
+diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
+index 2dc8110..8054846 100644
+--- a/drivers/s390/scsi/zfcp_erp.c
++++ b/drivers/s390/scsi/zfcp_erp.c
+@@ -26,13 +26,17 @@
+ static int zfcp_erp_adisc(struct zfcp_port *);
+ static void zfcp_erp_adisc_handler(unsigned long);
+ 
+-static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
+-static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int);
+-static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int);
+-static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int);
+-
+-static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int);
+-static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int);
++static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int, u8,
++					    void *);
++static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int, u8,
++						void *);
++static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int, u8, void *);
++static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int, u8, void *);
++
++static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int, u8,
++					     void *);
++static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int, u8,
++					     void *);
+ 
+ static void zfcp_erp_adapter_block(struct zfcp_adapter *, int);
+ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *);
+@@ -97,7 +101,8 @@ static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *);
+ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *);
+ 
+ static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *,
+-				   struct zfcp_port *, struct zfcp_unit *);
++				   struct zfcp_port *, struct zfcp_unit *,
++				   u8 id, void *ref);
+ static int zfcp_erp_action_dequeue(struct zfcp_erp_action *);
+ static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *,
+ 				    struct zfcp_port *, struct zfcp_unit *,
+@@ -128,11 +133,9 @@ static void zfcp_close_qdio(struct zfcp_adapter *adapter)
+ 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
+ 	write_unlock_irq(&req_queue->queue_lock);
+ 
+-	debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
+ 	while (qdio_shutdown(adapter->ccw_device,
+ 			     QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
+ 		ssleep(1);
+-	debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
+ 
+ 	/* cleanup used outbound sbals */
+ 	count = atomic_read(&req_queue->free_count);
+@@ -163,7 +166,7 @@ static void zfcp_close_fsf(struct zfcp_adapter *adapter)
+ 	/* reset FSF request sequence number */
+ 	adapter->fsf_req_seq_no = 0;
+ 	/* all ports and units are closed */
+-	zfcp_erp_modify_adapter_status(adapter,
++	zfcp_erp_modify_adapter_status(adapter, 24, NULL,
+ 				       ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
+ }
+ 
+@@ -179,7 +182,8 @@ static void zfcp_close_fsf(struct zfcp_adapter *adapter)
+ static void zfcp_fsf_request_timeout_handler(unsigned long data)
+ {
+ 	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
+-	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 62,
++				NULL);
+ }
+ 
+ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
+@@ -200,12 +204,11 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
+  * returns:	0	- initiated action successfully
+  *		<0	- failed to initiate action
+  */
+-static int
+-zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
++static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter,
++					    int clear_mask, u8 id, void *ref)
+ {
+ 	int retval;
+ 
+-	debug_text_event(adapter->erp_dbf, 5, "a_ro");
+ 	ZFCP_LOG_DEBUG("reopen adapter %s\n",
+ 		       zfcp_get_busid_by_adapter(adapter));
+ 
+@@ -214,14 +217,13 @@ zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
+ 	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) {
+ 		ZFCP_LOG_DEBUG("skipped reopen of failed adapter %s\n",
+ 			       zfcp_get_busid_by_adapter(adapter));
+-		debug_text_event(adapter->erp_dbf, 5, "a_ro_f");
+ 		/* ensure propagation of failed status to new devices */
+-		zfcp_erp_adapter_failed(adapter);
++		zfcp_erp_adapter_failed(adapter, 13, NULL);
+ 		retval = -EIO;
+ 		goto out;
+ 	}
+ 	retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
+-					 adapter, NULL, NULL);
++					 adapter, NULL, NULL, id, ref);
+ 
+  out:
+ 	return retval;
+@@ -236,56 +238,56 @@ zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
+  * returns:	0	- initiated action successfully
+  *		<0	- failed to initiate action
+  */
+-int
+-zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask)
++int zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask,
++			    u8 id, void *ref)
+ {
+ 	int retval;
+ 	unsigned long flags;
+ 
+ 	read_lock_irqsave(&zfcp_data.config_lock, flags);
+ 	write_lock(&adapter->erp_lock);
+-	retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask);
++	retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask, id, ref);
+ 	write_unlock(&adapter->erp_lock);
+ 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ 
+ 	return retval;
+ }
+ 
+-int
+-zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask)
++int zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask,
++			      u8 id, void *ref)
+ {
+ 	int retval;
+ 
+ 	retval = zfcp_erp_adapter_reopen(adapter,
+ 					 ZFCP_STATUS_COMMON_RUNNING |
+ 					 ZFCP_STATUS_COMMON_ERP_FAILED |
+-					 clear_mask);
++					 clear_mask, id, ref);
+ 
+ 	return retval;
+ }
+ 
+-int
+-zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask)
++int zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask, u8 id,
++			   void *ref)
+ {
+ 	int retval;
+ 
+ 	retval = zfcp_erp_port_reopen(port,
+ 				      ZFCP_STATUS_COMMON_RUNNING |
+ 				      ZFCP_STATUS_COMMON_ERP_FAILED |
+-				      clear_mask);
++				      clear_mask, id, ref);
+ 
+ 	return retval;
+ }
+ 
+-int
+-zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
++int zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask, u8 id,
++			   void *ref)
+ {
+ 	int retval;
+ 
+ 	retval = zfcp_erp_unit_reopen(unit,
+ 				      ZFCP_STATUS_COMMON_RUNNING |
+ 				      ZFCP_STATUS_COMMON_ERP_FAILED |
+-				      clear_mask);
++				      clear_mask, id, ref);
+ 
+ 	return retval;
+ }
+@@ -399,8 +401,7 @@ zfcp_erp_adisc_handler(unsigned long data)
+ 				"force physical port reopen "
+ 				"(adapter %s, port d_id=0x%06x)\n",
+ 				zfcp_get_busid_by_adapter(adapter), d_id);
+-		debug_text_event(adapter->erp_dbf, 3, "forcreop");
+-		if (zfcp_erp_port_forced_reopen(port, 0))
++		if (zfcp_erp_port_forced_reopen(port, 0, 63, NULL))
+ 			ZFCP_LOG_NORMAL("failed reopen of port "
+ 					"(adapter %s, wwpn=0x%016Lx)\n",
+ 					zfcp_get_busid_by_port(port),
+@@ -427,7 +428,7 @@ zfcp_erp_adisc_handler(unsigned long data)
+ 				"adisc_resp_wwpn=0x%016Lx)\n",
+ 				zfcp_get_busid_by_port(port),
+ 				port->wwpn, (wwn_t) adisc->wwpn);
+-		if (zfcp_erp_port_reopen(port, 0))
++		if (zfcp_erp_port_reopen(port, 0, 64, NULL))
+ 			ZFCP_LOG_NORMAL("failed reopen of port "
+ 					"(adapter %s, wwpn=0x%016Lx)\n",
+ 					zfcp_get_busid_by_port(port),
+@@ -461,7 +462,7 @@ zfcp_test_link(struct zfcp_port *port)
+ 		ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
+ 				"on adapter %s\n ", port->wwpn,
+ 				zfcp_get_busid_by_port(port));
+-		retval = zfcp_erp_port_forced_reopen(port, 0);
++		retval = zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
+ 		if (retval != 0) {
+ 			ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx "
+ 					"on adapter %s failed\n", port->wwpn,
+@@ -484,14 +485,11 @@ zfcp_test_link(struct zfcp_port *port)
+  * returns:	0	- initiated action successfully
+  *		<0	- failed to initiate action
+  */
+-static int
+-zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
++static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port,
++						int clear_mask, u8 id,
++						void *ref)
+ {
+ 	int retval;
+-	struct zfcp_adapter *adapter = port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 5, "pf_ro");
+-	debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 
+ 	ZFCP_LOG_DEBUG("forced reopen of port 0x%016Lx on adapter %s\n",
+ 		       port->wwpn, zfcp_get_busid_by_port(port));
+@@ -502,14 +500,12 @@ zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
+ 		ZFCP_LOG_DEBUG("skipped forced reopen of failed port 0x%016Lx "
+ 			       "on adapter %s\n", port->wwpn,
+ 			       zfcp_get_busid_by_port(port));
+-		debug_text_event(adapter->erp_dbf, 5, "pf_ro_f");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		retval = -EIO;
+ 		goto out;
+ 	}
+ 
+ 	retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
+-					 port->adapter, port, NULL);
++					 port->adapter, port, NULL, id, ref);
+ 
+  out:
+ 	return retval;
+@@ -524,8 +520,8 @@ zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
+  * returns:	0	- initiated action successfully
+  *		<0	- failed to initiate action
+  */
+-int
+-zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
++int zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask, u8 id,
++				void *ref)
+ {
+ 	int retval;
+ 	unsigned long flags;
+@@ -534,7 +530,8 @@ zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
+ 	adapter = port->adapter;
+ 	read_lock_irqsave(&zfcp_data.config_lock, flags);
+ 	write_lock(&adapter->erp_lock);
+-	retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask);
++	retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask, id,
++						      ref);
+ 	write_unlock(&adapter->erp_lock);
+ 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ 
+@@ -551,14 +548,10 @@ zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
+  * returns:	0	- initiated action successfully
+  *		<0	- failed to initiate action
+  */
+-static int
+-zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
++static int zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask,
++					 u8 id, void *ref)
+ {
+ 	int retval;
+-	struct zfcp_adapter *adapter = port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 5, "p_ro");
+-	debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 
+ 	ZFCP_LOG_DEBUG("reopen of port 0x%016Lx on adapter %s\n",
+ 		       port->wwpn, zfcp_get_busid_by_port(port));
+@@ -569,16 +562,14 @@ zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
+ 		ZFCP_LOG_DEBUG("skipped reopen of failed port 0x%016Lx "
+ 			       "on adapter %s\n", port->wwpn,
+ 			       zfcp_get_busid_by_port(port));
+-		debug_text_event(adapter->erp_dbf, 5, "p_ro_f");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		/* ensure propagation of failed status to new devices */
+-		zfcp_erp_port_failed(port);
++		zfcp_erp_port_failed(port, 14, NULL);
+ 		retval = -EIO;
+ 		goto out;
+ 	}
+ 
+ 	retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
+-					 port->adapter, port, NULL);
++					 port->adapter, port, NULL, id, ref);
+ 
+  out:
+ 	return retval;
+@@ -594,8 +585,8 @@ zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
+  * correct locking. An error recovery task is initiated to do the reopen.
+  * To wait for the completion of the reopen zfcp_erp_wait should be used.
+  */
+-int
+-zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
++int zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask, u8 id,
++			 void *ref)
+ {
+ 	int retval;
+ 	unsigned long flags;
+@@ -603,7 +594,7 @@ zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
+ 
+ 	read_lock_irqsave(&zfcp_data.config_lock, flags);
+ 	write_lock(&adapter->erp_lock);
+-	retval = zfcp_erp_port_reopen_internal(port, clear_mask);
++	retval = zfcp_erp_port_reopen_internal(port, clear_mask, id, ref);
+ 	write_unlock(&adapter->erp_lock);
+ 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ 
+@@ -620,14 +611,12 @@ zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
+  * returns:	0	- initiated action successfully
+  *		<0	- failed to initiate action
+  */
+-static int
+-zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
++static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask,
++					 u8 id, void *ref)
+ {
+ 	int retval;
+ 	struct zfcp_adapter *adapter = unit->port->adapter;
+ 
+-	debug_text_event(adapter->erp_dbf, 5, "u_ro");
+-	debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
+ 	ZFCP_LOG_DEBUG("reopen of unit 0x%016Lx on port 0x%016Lx "
+ 		       "on adapter %s\n", unit->fcp_lun,
+ 		       unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+@@ -639,15 +628,12 @@ zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
+ 			       "on port 0x%016Lx on adapter %s\n",
+ 			       unit->fcp_lun, unit->port->wwpn,
+ 			       zfcp_get_busid_by_unit(unit));
+-		debug_text_event(adapter->erp_dbf, 5, "u_ro_f");
+-		debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+-			    sizeof (fcp_lun_t));
+ 		retval = -EIO;
+ 		goto out;
+ 	}
+ 
+ 	retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
+-					 unit->port->adapter, unit->port, unit);
++					 adapter, unit->port, unit, id, ref);
+  out:
+ 	return retval;
+ }
+@@ -662,8 +648,8 @@ zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
+  * locking. An error recovery task is initiated to do the reopen.
+  * To wait for the completion of the reopen zfcp_erp_wait should be used.
+  */
+-int
+-zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
++int zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask, u8 id,
++			 void *ref)
+ {
+ 	int retval;
+ 	unsigned long flags;
+@@ -675,7 +661,7 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
+ 
+ 	read_lock_irqsave(&zfcp_data.config_lock, flags);
+ 	write_lock(&adapter->erp_lock);
+-	retval = zfcp_erp_unit_reopen_internal(unit, clear_mask);
++	retval = zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref);
+ 	write_unlock(&adapter->erp_lock);
+ 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ 
+@@ -687,19 +673,43 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
+  */
+ static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask)
+ {
+-	debug_text_event(adapter->erp_dbf, 6, "a_bl");
+-	zfcp_erp_modify_adapter_status(adapter,
++	zfcp_erp_modify_adapter_status(adapter, 15, NULL,
+ 				       ZFCP_STATUS_COMMON_UNBLOCKED |
+ 				       clear_mask, ZFCP_CLEAR);
+ }
+ 
++/* FIXME: isn't really atomic */
++/*
++ * returns the mask which has not been set so far, i.e.
++ * 0 if no bit has been changed, !0 if some bit has been changed
++ */
++static int atomic_test_and_set_mask(unsigned long mask, atomic_t *v)
++{
++	int changed_bits = (atomic_read(v) /*XOR*/^ mask) & mask;
++	atomic_set_mask(mask, v);
++	return changed_bits;
++}
++
++/* FIXME: isn't really atomic */
++/*
++ * returns the mask which has not been cleared so far, i.e.
++ * 0 if no bit has been changed, !0 if some bit has been changed
++ */
++static int atomic_test_and_clear_mask(unsigned long mask, atomic_t *v)
++{
++	int changed_bits = atomic_read(v) & mask;
++	atomic_clear_mask(mask, v);
++	return changed_bits;
++}
++
+ /**
+  * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests
+  */
+ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
+ {
+-	debug_text_event(adapter->erp_dbf, 6, "a_ubl");
+-	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
++	if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
++				     &adapter->status))
++		zfcp_rec_dbf_event_adapter(16, NULL, adapter);
+ }
+ 
+ /*
+@@ -714,11 +724,7 @@ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
+ static void
+ zfcp_erp_port_block(struct zfcp_port *port, int clear_mask)
+ {
+-	struct zfcp_adapter *adapter = port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 6, "p_bl");
+-	debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+-	zfcp_erp_modify_port_status(port,
++	zfcp_erp_modify_port_status(port, 17, NULL,
+ 				    ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
+ 				    ZFCP_CLEAR);
+ }
+@@ -733,11 +739,9 @@ zfcp_erp_port_block(struct zfcp_port *port, int clear_mask)
+ static void
+ zfcp_erp_port_unblock(struct zfcp_port *port)
+ {
+-	struct zfcp_adapter *adapter = port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 6, "p_ubl");
+-	debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+-	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
++	if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
++				     &port->status))
++		zfcp_rec_dbf_event_port(18, NULL, port);
+ }
+ 
+ /*
+@@ -752,11 +756,7 @@ zfcp_erp_port_unblock(struct zfcp_port *port)
+ static void
+ zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
+ {
+-	struct zfcp_adapter *adapter = unit->port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 6, "u_bl");
+-	debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
+-	zfcp_erp_modify_unit_status(unit,
++	zfcp_erp_modify_unit_status(unit, 19, NULL,
+ 				    ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
+ 				    ZFCP_CLEAR);
+ }
+@@ -771,11 +771,9 @@ zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
+ static void
+ zfcp_erp_unit_unblock(struct zfcp_unit *unit)
+ {
+-	struct zfcp_adapter *adapter = unit->port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 6, "u_ubl");
+-	debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
+-	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
++	if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
++				     &unit->status))
++		zfcp_rec_dbf_event_unit(20, NULL, unit);
+ }
+ 
+ static void
+@@ -783,11 +781,9 @@ zfcp_erp_action_ready(struct zfcp_erp_action *erp_action)
+ {
+ 	struct zfcp_adapter *adapter = erp_action->adapter;
+ 
+-	debug_text_event(adapter->erp_dbf, 4, "a_ar");
+-	debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int));
+-
+ 	zfcp_erp_action_to_ready(erp_action);
+ 	up(&adapter->erp_ready_sem);
++	zfcp_rec_dbf_event_thread(2, adapter, 0);
+ }
+ 
+ /*
+@@ -849,18 +845,15 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
+ 		if (zfcp_reqlist_find_safe(adapter, erp_action->fsf_req) &&
+ 		    erp_action->fsf_req->erp_action == erp_action) {
+ 			/* fsf_req still exists */
+-			debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
+-			debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
+-				    sizeof (unsigned long));
+ 			/* dismiss fsf_req of timed out/dismissed erp_action */
+ 			if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
+ 						  ZFCP_STATUS_ERP_TIMEDOUT)) {
+-				debug_text_event(adapter->erp_dbf, 3,
+-						 "a_ca_disreq");
+ 				erp_action->fsf_req->status |=
+ 					ZFCP_STATUS_FSFREQ_DISMISSED;
++				zfcp_rec_dbf_event_action(142, erp_action);
+ 			}
+ 			if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
++				zfcp_rec_dbf_event_action(143, erp_action);
+ 				ZFCP_LOG_NORMAL("error: erp step timed out "
+ 						"(action=%d, fsf_req=%p)\n ",
+ 						erp_action->action,
+@@ -879,7 +872,6 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
+ 				erp_action->fsf_req = NULL;
+ 			}
+ 		} else {
+-			debug_text_event(adapter->erp_dbf, 3, "a_ca_gonereq");
+ 			/*
+ 			 * even if this fsf_req has gone, forget about
+ 			 * association between erp_action and fsf_req
+@@ -887,8 +879,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
+ 			erp_action->fsf_req = NULL;
+ 		}
+ 		spin_unlock(&adapter->req_list_lock);
+-	} else
+-		debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
++	}
+ }
+ 
+ /**
+@@ -900,19 +891,11 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
+ static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
+ 					  unsigned long set_mask)
+ {
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-
+ 	if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
+-		debug_text_event(adapter->erp_dbf, 2, "a_asyh_ex");
+-		debug_event(adapter->erp_dbf, 2, &erp_action->action,
+-			    sizeof (int));
+ 		erp_action->status |= set_mask;
+ 		zfcp_erp_action_ready(erp_action);
+ 	} else {
+ 		/* action is ready or gone - nothing to do */
+-		debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone");
+-		debug_event(adapter->erp_dbf, 3, &erp_action->action,
+-			    sizeof (int));
+ 	}
+ }
+ 
+@@ -939,10 +922,6 @@ static void
+ zfcp_erp_memwait_handler(unsigned long data)
+ {
+ 	struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 2, "a_mwh");
+-	debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
+ 
+ 	zfcp_erp_async_handler(erp_action, 0);
+ }
+@@ -955,10 +934,6 @@ zfcp_erp_memwait_handler(unsigned long data)
+ static void zfcp_erp_timeout_handler(unsigned long data)
+ {
+ 	struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 2, "a_th");
+-	debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
+ 
+ 	zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT);
+ }
+@@ -973,11 +948,6 @@ static void zfcp_erp_timeout_handler(unsigned long data)
+  */
+ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action)
+ {
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 2, "a_adis");
+-	debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
+-
+ 	erp_action->status |= ZFCP_STATUS_ERP_DISMISSED;
+ 	if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING)
+ 		zfcp_erp_action_ready(erp_action);
+@@ -995,12 +965,10 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
+ 		ZFCP_LOG_NORMAL("error: creation of erp thread failed for "
+ 				"adapter %s\n",
+ 				zfcp_get_busid_by_adapter(adapter));
+-		debug_text_event(adapter->erp_dbf, 5, "a_thset_fail");
+ 	} else {
+ 		wait_event(adapter->erp_thread_wqh,
+ 			   atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
+ 					    &adapter->status));
+-		debug_text_event(adapter->erp_dbf, 5, "a_thset_ok");
+ 	}
+ 
+ 	return (retval < 0);
+@@ -1027,6 +995,7 @@ zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
+ 
+ 	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
+ 	up(&adapter->erp_ready_sem);
++	zfcp_rec_dbf_event_thread(2, adapter, 1);
+ 
+ 	wait_event(adapter->erp_thread_wqh,
+ 		   !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
+@@ -1035,8 +1004,6 @@ zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
+ 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
+ 			  &adapter->status);
+ 
+-	debug_text_event(adapter->erp_dbf, 5, "a_thki_ok");
+-
+ 	return retval;
+ }
+ 
+@@ -1059,7 +1026,6 @@ zfcp_erp_thread(void *data)
+ 	/* Block all signals */
+ 	siginitsetinv(&current->blocked, 0);
+ 	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
+-	debug_text_event(adapter->erp_dbf, 5, "a_th_run");
+ 	wake_up(&adapter->erp_thread_wqh);
+ 
+ 	while (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
+@@ -1084,12 +1050,12 @@ zfcp_erp_thread(void *data)
+ 		 * no action in 'ready' queue to be processed and
+ 		 * thread is not to be killed
+ 		 */
++		zfcp_rec_dbf_event_thread(4, adapter, 1);
+ 		down_interruptible(&adapter->erp_ready_sem);
+-		debug_text_event(adapter->erp_dbf, 5, "a_th_woken");
++		zfcp_rec_dbf_event_thread(5, adapter, 1);
+ 	}
+ 
+ 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
+-	debug_text_event(adapter->erp_dbf, 5, "a_th_stop");
+ 	wake_up(&adapter->erp_thread_wqh);
+ 
+ 	return 0;
+@@ -1125,7 +1091,6 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ 	/* dequeue dismissed action and leave, if required */
+ 	retval = zfcp_erp_strategy_check_action(erp_action, retval);
+ 	if (retval == ZFCP_ERP_DISMISSED) {
+-		debug_text_event(adapter->erp_dbf, 4, "a_st_dis1");
+ 		goto unlock;
+ 	}
+ 
+@@ -1176,20 +1141,17 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ 		   element was timed out.
+ 		 */
+ 		if (adapter->erp_total_count == adapter->erp_low_mem_count) {
+-			debug_text_event(adapter->erp_dbf, 3, "a_st_lowmem");
+ 			ZFCP_LOG_NORMAL("error: no mempool elements available, "
+ 					"restarting I/O on adapter %s "
+ 					"to free mempool\n",
+ 					zfcp_get_busid_by_adapter(adapter));
+-			zfcp_erp_adapter_reopen_internal(adapter, 0);
++			zfcp_erp_adapter_reopen_internal(adapter, 0, 66, NULL);
+ 		} else {
+-		debug_text_event(adapter->erp_dbf, 2, "a_st_memw");
+ 		retval = zfcp_erp_strategy_memwait(erp_action);
+ 		}
+ 		goto unlock;
+ 	case ZFCP_ERP_CONTINUES:
+ 		/* leave since this action runs asynchronously */
+-		debug_text_event(adapter->erp_dbf, 6, "a_st_cont");
+ 		if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
+ 			--adapter->erp_low_mem_count;
+ 			erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
+@@ -1218,7 +1180,6 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ 	 * action is repeated in order to process state change
+ 	 */
+ 	if (retval == ZFCP_ERP_EXIT) {
+-		debug_text_event(adapter->erp_dbf, 2, "a_st_exit");
+ 		goto unlock;
+ 	}
+ 
+@@ -1244,8 +1205,6 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ 	if (retval != ZFCP_ERP_DISMISSED)
+ 		zfcp_erp_strategy_check_queues(adapter);
+ 
+-	debug_text_event(adapter->erp_dbf, 6, "a_st_done");
+-
+ 	return retval;
+ }
+ 
+@@ -1260,17 +1219,12 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ static int
+ zfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval)
+ {
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-
+ 	zfcp_erp_strategy_check_fsfreq(erp_action);
+ 
+-	debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int));
+ 	if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
+-		debug_text_event(adapter->erp_dbf, 3, "a_stcd_dis");
+ 		zfcp_erp_action_dequeue(erp_action);
+ 		retval = ZFCP_ERP_DISMISSED;
+-	} else
+-		debug_text_event(adapter->erp_dbf, 5, "a_stcd_nodis");
++	}
+ 
+ 	return retval;
+ }
+@@ -1279,7 +1233,6 @@ static int
+ zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval = ZFCP_ERP_FAILED;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+ 
+ 	/*
+ 	 * try to execute/continue action as far as possible,
+@@ -1309,9 +1262,6 @@ zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
+ 		break;
+ 
+ 	default:
+-		debug_text_exception(adapter->erp_dbf, 1, "a_stda_bug");
+-		debug_event(adapter->erp_dbf, 1, &erp_action->action,
+-			    sizeof (int));
+ 		ZFCP_LOG_NORMAL("bug: unknown erp action requested on "
+ 				"adapter %s (action=%d)\n",
+ 				zfcp_get_busid_by_adapter(erp_action->adapter),
+@@ -1333,10 +1283,7 @@ static int
+ zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval = ZFCP_ERP_CONTINUES;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+ 
+-	debug_text_event(adapter->erp_dbf, 6, "a_mwinit");
+-	debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int));
+ 	init_timer(&erp_action->timer);
+ 	erp_action->timer.function = zfcp_erp_memwait_handler;
+ 	erp_action->timer.data = (unsigned long) erp_action;
+@@ -1353,13 +1300,12 @@ zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
+  *
+  */
+ void
+-zfcp_erp_adapter_failed(struct zfcp_adapter *adapter)
++zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref)
+ {
+-	zfcp_erp_modify_adapter_status(adapter,
++	zfcp_erp_modify_adapter_status(adapter, id, ref,
+ 				       ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
+ 	ZFCP_LOG_NORMAL("adapter erp failed on adapter %s\n",
+ 			zfcp_get_busid_by_adapter(adapter));
+-	debug_text_event(adapter->erp_dbf, 2, "a_afail");
+ }
+ 
+ /*
+@@ -1369,9 +1315,9 @@ zfcp_erp_adapter_failed(struct zfcp_adapter *adapter)
+  *
+  */
+ void
+-zfcp_erp_port_failed(struct zfcp_port *port)
++zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref)
+ {
+-	zfcp_erp_modify_port_status(port,
++	zfcp_erp_modify_port_status(port, id, ref,
+ 				    ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
+ 
+ 	if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
+@@ -1381,9 +1327,6 @@ zfcp_erp_port_failed(struct zfcp_port *port)
+ 	else
+ 		ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n",
+ 				zfcp_get_busid_by_port(port), port->wwpn);
+-
+-	debug_text_event(port->adapter->erp_dbf, 2, "p_pfail");
+-	debug_event(port->adapter->erp_dbf, 2, &port->wwpn, sizeof (wwn_t));
+ }
+ 
+ /*
+@@ -1393,17 +1336,14 @@ zfcp_erp_port_failed(struct zfcp_port *port)
+  *
+  */
+ void
+-zfcp_erp_unit_failed(struct zfcp_unit *unit)
++zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref)
+ {
+-	zfcp_erp_modify_unit_status(unit,
++	zfcp_erp_modify_unit_status(unit, id, ref,
+ 				    ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
+ 
+ 	ZFCP_LOG_NORMAL("unit erp failed on unit 0x%016Lx on port 0x%016Lx "
+ 			" on adapter %s\n", unit->fcp_lun,
+ 			unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+-	debug_text_event(unit->port->adapter->erp_dbf, 2, "u_ufail");
+-	debug_event(unit->port->adapter->erp_dbf, 2,
+-		    &unit->fcp_lun, sizeof (fcp_lun_t));
+ }
+ 
+ /*
+@@ -1427,10 +1367,6 @@ zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result)
+ 	struct zfcp_port *port = erp_action->port;
+ 	struct zfcp_unit *unit = erp_action->unit;
+ 
+-	debug_text_event(adapter->erp_dbf, 5, "a_stct_norm");
+-	debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int));
+-	debug_event(adapter->erp_dbf, 5, &result, sizeof (int));
+-
+ 	switch (erp_action->action) {
+ 
+ 	case ZFCP_ERP_ACTION_REOPEN_UNIT:
+@@ -1457,15 +1393,14 @@ zfcp_erp_strategy_statechange(int action,
+ 			      struct zfcp_port *port,
+ 			      struct zfcp_unit *unit, int retval)
+ {
+-	debug_text_event(adapter->erp_dbf, 3, "a_stsc");
+-	debug_event(adapter->erp_dbf, 3, &action, sizeof (int));
+-
+ 	switch (action) {
+ 
+ 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+ 		if (zfcp_erp_strategy_statechange_detected(&adapter->status,
+ 							   status)) {
+-			zfcp_erp_adapter_reopen_internal(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++			zfcp_erp_adapter_reopen_internal(adapter,
++						ZFCP_STATUS_COMMON_ERP_FAILED,
++						67, NULL);
+ 			retval = ZFCP_ERP_EXIT;
+ 		}
+ 		break;
+@@ -1474,7 +1409,9 @@ zfcp_erp_strategy_statechange(int action,
+ 	case ZFCP_ERP_ACTION_REOPEN_PORT:
+ 		if (zfcp_erp_strategy_statechange_detected(&port->status,
+ 							   status)) {
+-			zfcp_erp_port_reopen_internal(port, ZFCP_STATUS_COMMON_ERP_FAILED);
++			zfcp_erp_port_reopen_internal(port,
++						ZFCP_STATUS_COMMON_ERP_FAILED,
++						68, NULL);
+ 			retval = ZFCP_ERP_EXIT;
+ 		}
+ 		break;
+@@ -1482,7 +1419,9 @@ zfcp_erp_strategy_statechange(int action,
+ 	case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ 		if (zfcp_erp_strategy_statechange_detected(&unit->status,
+ 							   status)) {
+-			zfcp_erp_unit_reopen_internal(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
++			zfcp_erp_unit_reopen_internal(unit,
++						ZFCP_STATUS_COMMON_ERP_FAILED,
++						69, NULL);
+ 			retval = ZFCP_ERP_EXIT;
+ 		}
+ 		break;
+@@ -1506,10 +1445,6 @@ zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status)
+ static int
+ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
+ {
+-	debug_text_event(unit->port->adapter->erp_dbf, 5, "u_stct");
+-	debug_event(unit->port->adapter->erp_dbf, 5, &unit->fcp_lun,
+-		    sizeof (fcp_lun_t));
+-
+ 	switch (result) {
+ 	case ZFCP_ERP_SUCCEEDED :
+ 		atomic_set(&unit->erp_counter, 0);
+@@ -1518,7 +1453,7 @@ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
+ 	case ZFCP_ERP_FAILED :
+ 		atomic_inc(&unit->erp_counter);
+ 		if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS)
+-			zfcp_erp_unit_failed(unit);
++			zfcp_erp_unit_failed(unit, 21, NULL);
+ 		break;
+ 	case ZFCP_ERP_EXIT :
+ 		/* nothing */
+@@ -1536,9 +1471,6 @@ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
+ static int
+ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
+ {
+-	debug_text_event(port->adapter->erp_dbf, 5, "p_stct");
+-	debug_event(port->adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+-
+ 	switch (result) {
+ 	case ZFCP_ERP_SUCCEEDED :
+ 		atomic_set(&port->erp_counter, 0);
+@@ -1547,7 +1479,7 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
+ 	case ZFCP_ERP_FAILED :
+ 		atomic_inc(&port->erp_counter);
+ 		if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS)
+-			zfcp_erp_port_failed(port);
++			zfcp_erp_port_failed(port, 22, NULL);
+ 		break;
+ 	case ZFCP_ERP_EXIT :
+ 		/* nothing */
+@@ -1565,8 +1497,6 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
+ static int
+ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
+ {
+-	debug_text_event(adapter->erp_dbf, 5, "a_stct");
+-
+ 	switch (result) {
+ 	case ZFCP_ERP_SUCCEEDED :
+ 		atomic_set(&adapter->erp_counter, 0);
+@@ -1575,7 +1505,7 @@ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
+ 	case ZFCP_ERP_FAILED :
+ 		atomic_inc(&adapter->erp_counter);
+ 		if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS)
+-			zfcp_erp_adapter_failed(adapter);
++			zfcp_erp_adapter_failed(adapter, 23, NULL);
+ 		break;
+ 	case ZFCP_ERP_EXIT :
+ 		/* nothing */
+@@ -1658,37 +1588,34 @@ zfcp_erp_strategy_followup_actions(int action,
+ 				   struct zfcp_port *port,
+ 				   struct zfcp_unit *unit, int status)
+ {
+-	debug_text_event(adapter->erp_dbf, 5, "a_stfol");
+-	debug_event(adapter->erp_dbf, 5, &action, sizeof (int));
+-
+ 	/* initiate follow-up actions depending on success of finished action */
+ 	switch (action) {
+ 
+ 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+ 		if (status == ZFCP_ERP_SUCCEEDED)
+-			zfcp_erp_port_reopen_all_internal(adapter, 0);
++			zfcp_erp_port_reopen_all_internal(adapter, 0, 70, NULL);
+ 		else
+-			zfcp_erp_adapter_reopen_internal(adapter, 0);
++			zfcp_erp_adapter_reopen_internal(adapter, 0, 71, NULL);
+ 		break;
+ 
+ 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
+ 		if (status == ZFCP_ERP_SUCCEEDED)
+-			zfcp_erp_port_reopen_internal(port, 0);
++			zfcp_erp_port_reopen_internal(port, 0, 72, NULL);
+ 		else
+-			zfcp_erp_adapter_reopen_internal(adapter, 0);
++			zfcp_erp_adapter_reopen_internal(adapter, 0, 73, NULL);
+ 		break;
+ 
+ 	case ZFCP_ERP_ACTION_REOPEN_PORT:
+ 		if (status == ZFCP_ERP_SUCCEEDED)
+-			zfcp_erp_unit_reopen_all_internal(port, 0);
++			zfcp_erp_unit_reopen_all_internal(port, 0, 74, NULL);
+ 		else
+-			zfcp_erp_port_forced_reopen_internal(port, 0);
++			zfcp_erp_port_forced_reopen_internal(port, 0, 75, NULL);
+ 		break;
+ 
+ 	case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ 		/* Nothing to do if status == ZFCP_ERP_SUCCEEDED */
+ 		if (status != ZFCP_ERP_SUCCEEDED)
+-			zfcp_erp_port_reopen_internal(unit->port, 0);
++			zfcp_erp_port_reopen_internal(unit->port, 0, 76, NULL);
+ 		break;
+ 	}
+ 
+@@ -1704,12 +1631,10 @@ zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter)
+ 	read_lock(&adapter->erp_lock);
+ 	if (list_empty(&adapter->erp_ready_head) &&
+ 	    list_empty(&adapter->erp_running_head)) {
+-			debug_text_event(adapter->erp_dbf, 4, "a_cq_wake");
+ 			atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
+ 					  &adapter->status);
+ 			wake_up(&adapter->erp_done_wqh);
+-	} else
+-		debug_text_event(adapter->erp_dbf, 5, "a_cq_notempty");
++	}
+ 	read_unlock(&adapter->erp_lock);
+ 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ 
+@@ -1733,29 +1658,27 @@ zfcp_erp_wait(struct zfcp_adapter *adapter)
+ 	return retval;
+ }
+ 
+-void
+-zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter,
+-			       u32 mask, int set_or_clear)
++void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id,
++				    void *ref, u32 mask, int set_or_clear)
+ {
+ 	struct zfcp_port *port;
+-	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
++	u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS;
+ 
+ 	if (set_or_clear == ZFCP_SET) {
+-		atomic_set_mask(mask, &adapter->status);
+-		debug_text_event(adapter->erp_dbf, 3, "a_mod_as_s");
++		changed = atomic_test_and_set_mask(mask, &adapter->status);
+ 	} else {
+-		atomic_clear_mask(mask, &adapter->status);
++		changed = atomic_test_and_clear_mask(mask, &adapter->status);
+ 		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
+ 			atomic_set(&adapter->erp_counter, 0);
+-		debug_text_event(adapter->erp_dbf, 3, "a_mod_as_c");
+ 	}
+-	debug_event(adapter->erp_dbf, 3, &mask, sizeof (u32));
++	if (changed)
++		zfcp_rec_dbf_event_adapter(id, ref, adapter);
+ 
+ 	/* Deal with all underlying devices, only pass common_mask */
+ 	if (common_mask)
+ 		list_for_each_entry(port, &adapter->port_list_head, list)
+-		    zfcp_erp_modify_port_status(port, common_mask,
+-						set_or_clear);
++			zfcp_erp_modify_port_status(port, id, ref, common_mask,
++						    set_or_clear);
+ }
+ 
+ /*
+@@ -1764,29 +1687,27 @@ zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter,
+  * purpose:	sets the port and all underlying devices to ERP_FAILED
+  *
+  */
+-void
+-zfcp_erp_modify_port_status(struct zfcp_port *port, u32 mask, int set_or_clear)
++void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref,
++				 u32 mask, int set_or_clear)
+ {
+ 	struct zfcp_unit *unit;
+-	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
++	u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS;
+ 
+ 	if (set_or_clear == ZFCP_SET) {
+-		atomic_set_mask(mask, &port->status);
+-		debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_s");
++		changed = atomic_test_and_set_mask(mask, &port->status);
+ 	} else {
+-		atomic_clear_mask(mask, &port->status);
++		changed = atomic_test_and_clear_mask(mask, &port->status);
+ 		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
+ 			atomic_set(&port->erp_counter, 0);
+-		debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_c");
+ 	}
+-	debug_event(port->adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t));
+-	debug_event(port->adapter->erp_dbf, 3, &mask, sizeof (u32));
++	if (changed)
++		zfcp_rec_dbf_event_port(id, ref, port);
+ 
+ 	/* Modify status of all underlying devices, only pass common mask */
+ 	if (common_mask)
+ 		list_for_each_entry(unit, &port->unit_list_head, list)
+-		    zfcp_erp_modify_unit_status(unit, common_mask,
+-						set_or_clear);
++			zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
++						    set_or_clear);
+ }
+ 
+ /*
+@@ -1795,22 +1716,21 @@ zfcp_erp_modify_port_status(struct zfcp_port *port, u32 mask, int set_or_clear)
+  * purpose:	sets the unit to ERP_FAILED
+  *
+  */
+-void
+-zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear)
++void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref,
++				 u32 mask, int set_or_clear)
+ {
++	u32 changed;
++
+ 	if (set_or_clear == ZFCP_SET) {
+-		atomic_set_mask(mask, &unit->status);
+-		debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_s");
++		changed = atomic_test_and_set_mask(mask, &unit->status);
+ 	} else {
+-		atomic_clear_mask(mask, &unit->status);
++		changed = atomic_test_and_clear_mask(mask, &unit->status);
+ 		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
+ 			atomic_set(&unit->erp_counter, 0);
+ 		}
+-		debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_c");
+ 	}
+-	debug_event(unit->port->adapter->erp_dbf, 3, &unit->fcp_lun,
+-		    sizeof (fcp_lun_t));
+-	debug_event(unit->port->adapter->erp_dbf, 3, &mask, sizeof (u32));
++	if (changed)
++		zfcp_rec_dbf_event_unit(id, ref, unit);
+ }
+ 
+ /*
+@@ -1822,30 +1742,32 @@ zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear)
+  * returns:	0	- initiated action successfully
+  *		<0	- failed to initiate action
+  */
+-int
+-zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask)
++int zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask,
++			     u8 id, void *ref)
+ {
+ 	int retval;
+ 	unsigned long flags;
+ 
+ 	read_lock_irqsave(&zfcp_data.config_lock, flags);
+ 	write_lock(&adapter->erp_lock);
+-	retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask);
++	retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask, id,
++						   ref);
+ 	write_unlock(&adapter->erp_lock);
+ 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ 
+ 	return retval;
+ }
+ 
+-static int
+-zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
++static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter,
++					     int clear_mask, u8 id, void *ref)
+ {
+ 	int retval = 0;
+ 	struct zfcp_port *port;
+ 
+ 	list_for_each_entry(port, &adapter->port_list_head, list)
+ 		if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
+-			zfcp_erp_port_reopen_internal(port, clear_mask);
++			zfcp_erp_port_reopen_internal(port, clear_mask, id,
++						      ref);
+ 
+ 	return retval;
+ }
+@@ -1857,14 +1779,14 @@ zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
+  *
+  * returns:	FIXME
+  */
+-static int
+-zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, int clear_mask)
++static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port,
++					     int clear_mask, u8 id, void *ref)
+ {
+ 	int retval = 0;
+ 	struct zfcp_unit *unit;
+ 
+ 	list_for_each_entry(unit, &port->unit_list_head, list)
+-	    zfcp_erp_unit_reopen_internal(unit, clear_mask);
++		zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref);
+ 
+ 	return retval;
+ }
+@@ -1892,10 +1814,6 @@ zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action)
+ 	else
+ 		retval = zfcp_erp_adapter_strategy_open(erp_action);
+ 
+-	debug_text_event(adapter->erp_dbf, 3, "a_ast/ret");
+-	debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
+-	debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
+-
+ 	if (retval == ZFCP_ERP_FAILED) {
+ 		ZFCP_LOG_INFO("Waiting to allow the adapter %s "
+ 			      "to recover itself\n",
+@@ -2021,7 +1939,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
+ 			      zfcp_get_busid_by_adapter(adapter));
+ 		goto failed_qdio_establish;
+ 	}
+-	debug_text_event(adapter->erp_dbf, 3, "qdio_est");
+ 
+ 	if (qdio_activate(adapter->ccw_device, 0) != 0) {
+ 		ZFCP_LOG_INFO("error: activation of QDIO queues failed "
+@@ -2029,7 +1946,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
+ 			      zfcp_get_busid_by_adapter(adapter));
+ 		goto failed_qdio_activate;
+ 	}
+-	debug_text_event(adapter->erp_dbf, 3, "qdio_act");
+ 
+ 	/*
+ 	 * put buffers into response queue,
+@@ -2077,11 +1993,9 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
+ 	/* NOP */
+ 
+  failed_qdio_activate:
+-	debug_text_event(adapter->erp_dbf, 3, "qdio_down1a");
+ 	while (qdio_shutdown(adapter->ccw_device,
+ 			     QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
+ 		ssleep(1);
+-	debug_text_event(adapter->erp_dbf, 3, "qdio_down1b");
+ 
+  failed_qdio_establish:
+  failed_sanity:
+@@ -2127,14 +2041,12 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
+ 		write_unlock_irq(&adapter->erp_lock);
+ 		if (zfcp_fsf_exchange_config_data(erp_action)) {
+ 			retval = ZFCP_ERP_FAILED;
+-			debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
+ 			ZFCP_LOG_INFO("error:  initiation of exchange of "
+ 				      "configuration data failed for "
+ 				      "adapter %s\n",
+ 				      zfcp_get_busid_by_adapter(adapter));
+ 			break;
+ 		}
+-		debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");
+ 		ZFCP_LOG_DEBUG("Xchange underway\n");
+ 
+ 		/*
+@@ -2150,7 +2062,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
+ 		 * _must_ be the one belonging to the 'exchange config
+ 		 * data' request.
+ 		 */
++		zfcp_rec_dbf_event_thread(6, adapter, 1);
+ 		down(&adapter->erp_ready_sem);
++		zfcp_rec_dbf_event_thread(7, adapter, 1);
+ 		if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+ 			ZFCP_LOG_INFO("error: exchange of configuration data "
+ 				      "for adapter %s timed out\n",
+@@ -2198,16 +2112,15 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
+ 
+ 	ret = zfcp_fsf_exchange_port_data(erp_action);
+ 	if (ret == -EOPNOTSUPP) {
+-		debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
+ 		return ZFCP_ERP_SUCCEEDED;
+ 	} else if (ret) {
+-		debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
+ 		return ZFCP_ERP_FAILED;
+ 	}
+-	debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
+ 
+ 	ret = ZFCP_ERP_SUCCEEDED;
++	zfcp_rec_dbf_event_thread(8, adapter, 1);
+ 	down(&adapter->erp_ready_sem);
++	zfcp_rec_dbf_event_thread(9, adapter, 1);
+ 	if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+ 		ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
+ 			      "%s)\n", zfcp_get_busid_by_adapter(adapter));
+@@ -2261,7 +2174,6 @@ zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval = ZFCP_ERP_FAILED;
+ 	struct zfcp_port *port = erp_action->port;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+ 
+ 	switch (erp_action->step) {
+ 
+@@ -2298,11 +2210,6 @@ zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
+ 		break;
+ 	}
+ 
+-	debug_text_event(adapter->erp_dbf, 3, "p_pfst/ret");
+-	debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t));
+-	debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
+-	debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
+-
+ 	return retval;
+ }
+ 
+@@ -2320,7 +2227,6 @@ zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval = ZFCP_ERP_FAILED;
+ 	struct zfcp_port *port = erp_action->port;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+ 
+ 	switch (erp_action->step) {
+ 
+@@ -2353,11 +2259,6 @@ zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
+ 		retval = zfcp_erp_port_strategy_open(erp_action);
+ 
+  out:
+-	debug_text_event(adapter->erp_dbf, 3, "p_pst/ret");
+-	debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t));
+-	debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
+-	debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
+-
+ 	return retval;
+ }
+ 
+@@ -2395,7 +2296,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
+ 						port->wwpn,
+ 						zfcp_get_busid_by_adapter(adapter),
+ 						adapter->peer_wwpn);
+-				zfcp_erp_port_failed(port);
++				zfcp_erp_port_failed(port, 25, NULL);
+ 				retval = ZFCP_ERP_FAILED;
+ 				break;
+ 			}
+@@ -2421,8 +2322,8 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
+ 			/* nameserver port may live again */
+ 			atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING,
+ 					&adapter->nameserver_port->status);
+-			if (zfcp_erp_port_reopen(adapter->nameserver_port, 0)
+-			    >= 0) {
++			if (zfcp_erp_port_reopen(adapter->nameserver_port, 0,
++						 77, erp_action) >= 0) {
+ 				erp_action->step =
+ 					ZFCP_ERP_STEP_NAMESERVER_OPEN;
+ 				retval = ZFCP_ERP_CONTINUES;
+@@ -2453,7 +2354,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
+ 					       "for port 0x%016Lx "
+ 					       "(misconfigured WWPN?)\n",
+ 					       port->wwpn);
+-				zfcp_erp_port_failed(port);
++				zfcp_erp_port_failed(port, 26, NULL);
+ 				retval = ZFCP_ERP_EXIT;
+ 			} else {
+ 				ZFCP_LOG_DEBUG("nameserver look-up failed for "
+@@ -2549,17 +2450,12 @@ zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action
+ 	read_lock_irqsave(&adapter->erp_lock, flags);
+ 	list_for_each_entry_safe(erp_action, tmp, &adapter->erp_running_head,
+ 				 list) {
+-		debug_text_event(adapter->erp_dbf, 4, "p_pstnsw_n");
+-		debug_event(adapter->erp_dbf, 4, &erp_action->port->wwpn,
+-			    sizeof (wwn_t));
+ 		if (erp_action->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) {
+-			debug_text_event(adapter->erp_dbf, 3, "p_pstnsw_w");
+-			debug_event(adapter->erp_dbf, 3,
+-				    &erp_action->port->wwpn, sizeof (wwn_t));
+ 			if (atomic_test_mask(
+ 				    ZFCP_STATUS_COMMON_ERP_FAILED,
+ 				    &adapter->nameserver_port->status))
+-				zfcp_erp_port_failed(erp_action->port);
++				zfcp_erp_port_failed(erp_action->port, 27,
++						     NULL);
+ 			zfcp_erp_action_ready(erp_action);
+ 		}
+ 	}
+@@ -2580,26 +2476,18 @@ static int
+ zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-	struct zfcp_port *port = erp_action->port;
+ 
+ 	retval = zfcp_fsf_close_physical_port(erp_action);
+ 	if (retval == -ENOMEM) {
+-		debug_text_event(adapter->erp_dbf, 5, "o_pfstc_nomem");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		retval = ZFCP_ERP_NOMEM;
+ 		goto out;
+ 	}
+ 	erp_action->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING;
+ 	if (retval != 0) {
+-		debug_text_event(adapter->erp_dbf, 5, "o_pfstc_cpf");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		/* could not send 'open', fail */
+ 		retval = ZFCP_ERP_FAILED;
+ 		goto out;
+ 	}
+-	debug_text_event(adapter->erp_dbf, 6, "o_pfstc_cpok");
+-	debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+ 	retval = ZFCP_ERP_CONTINUES;
+  out:
+ 	return retval;
+@@ -2609,10 +2497,6 @@ static int
+ zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
+ {
+ 	int retval = 0;
+-	struct zfcp_adapter *adapter = port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 5, "p_pstclst");
+-	debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 
+ 	atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
+ 			  ZFCP_STATUS_COMMON_CLOSING |
+@@ -2636,26 +2520,18 @@ static int
+ zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-	struct zfcp_port *port = erp_action->port;
+ 
+ 	retval = zfcp_fsf_close_port(erp_action);
+ 	if (retval == -ENOMEM) {
+-		debug_text_event(adapter->erp_dbf, 5, "p_pstc_nomem");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		retval = ZFCP_ERP_NOMEM;
+ 		goto out;
+ 	}
+ 	erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING;
+ 	if (retval != 0) {
+-		debug_text_event(adapter->erp_dbf, 5, "p_pstc_cpf");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		/* could not send 'close', fail */
+ 		retval = ZFCP_ERP_FAILED;
+ 		goto out;
+ 	}
+-	debug_text_event(adapter->erp_dbf, 6, "p_pstc_cpok");
+-	debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+ 	retval = ZFCP_ERP_CONTINUES;
+  out:
+ 	return retval;
+@@ -2673,26 +2549,18 @@ static int
+ zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-	struct zfcp_port *port = erp_action->port;
+ 
+ 	retval = zfcp_fsf_open_port(erp_action);
+ 	if (retval == -ENOMEM) {
+-		debug_text_event(adapter->erp_dbf, 5, "p_psto_nomem");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		retval = ZFCP_ERP_NOMEM;
+ 		goto out;
+ 	}
+ 	erp_action->step = ZFCP_ERP_STEP_PORT_OPENING;
+ 	if (retval != 0) {
+-		debug_text_event(adapter->erp_dbf, 5, "p_psto_opf");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		/* could not send 'open', fail */
+ 		retval = ZFCP_ERP_FAILED;
+ 		goto out;
+ 	}
+-	debug_text_event(adapter->erp_dbf, 6, "p_psto_opok");
+-	debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+ 	retval = ZFCP_ERP_CONTINUES;
+  out:
+ 	return retval;
+@@ -2710,26 +2578,18 @@ static int
+ zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-	struct zfcp_port *port = erp_action->port;
+ 
+ 	retval = zfcp_ns_gid_pn_request(erp_action);
+ 	if (retval == -ENOMEM) {
+-		debug_text_event(adapter->erp_dbf, 5, "p_pstn_nomem");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		retval = ZFCP_ERP_NOMEM;
+ 		goto out;
+ 	}
+ 	erp_action->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
+ 	if (retval != 0) {
+-		debug_text_event(adapter->erp_dbf, 5, "p_pstn_ref");
+-		debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 		/* could not send nameserver request, fail */
+ 		retval = ZFCP_ERP_FAILED;
+ 		goto out;
+ 	}
+-	debug_text_event(adapter->erp_dbf, 6, "p_pstn_reok");
+-	debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+ 	retval = ZFCP_ERP_CONTINUES;
+  out:
+ 	return retval;
+@@ -2750,7 +2610,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval = ZFCP_ERP_FAILED;
+ 	struct zfcp_unit *unit = erp_action->unit;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+ 
+ 	switch (erp_action->step) {
+ 
+@@ -2797,10 +2656,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
+ 		break;
+ 	}
+ 
+-	debug_text_event(adapter->erp_dbf, 3, "u_ust/ret");
+-	debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof (fcp_lun_t));
+-	debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
+-	debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
+ 	return retval;
+ }
+ 
+@@ -2808,10 +2663,6 @@ static int
+ zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
+ {
+ 	int retval = 0;
+-	struct zfcp_adapter *adapter = unit->port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 5, "u_ustclst");
+-	debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
+ 
+ 	atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
+ 			  ZFCP_STATUS_COMMON_CLOSING |
+@@ -2835,28 +2686,18 @@ static int
+ zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-	struct zfcp_unit *unit = erp_action->unit;
+ 
+ 	retval = zfcp_fsf_close_unit(erp_action);
+ 	if (retval == -ENOMEM) {
+-		debug_text_event(adapter->erp_dbf, 5, "u_ustc_nomem");
+-		debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+-			    sizeof (fcp_lun_t));
+ 		retval = ZFCP_ERP_NOMEM;
+ 		goto out;
+ 	}
+ 	erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING;
+ 	if (retval != 0) {
+-		debug_text_event(adapter->erp_dbf, 5, "u_ustc_cuf");
+-		debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+-			    sizeof (fcp_lun_t));
+ 		/* could not send 'close', fail */
+ 		retval = ZFCP_ERP_FAILED;
+ 		goto out;
+ 	}
+-	debug_text_event(adapter->erp_dbf, 6, "u_ustc_cuok");
+-	debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
+ 	retval = ZFCP_ERP_CONTINUES;
+ 
+  out:
+@@ -2875,28 +2716,18 @@ static int
+ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
+ {
+ 	int retval;
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-	struct zfcp_unit *unit = erp_action->unit;
+ 
+ 	retval = zfcp_fsf_open_unit(erp_action);
+ 	if (retval == -ENOMEM) {
+-		debug_text_event(adapter->erp_dbf, 5, "u_usto_nomem");
+-		debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+-			    sizeof (fcp_lun_t));
+ 		retval = ZFCP_ERP_NOMEM;
+ 		goto out;
+ 	}
+ 	erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING;
+ 	if (retval != 0) {
+-		debug_text_event(adapter->erp_dbf, 5, "u_usto_ouf");
+-		debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+-			    sizeof (fcp_lun_t));
+ 		/* could not send 'open', fail */
+ 		retval = ZFCP_ERP_FAILED;
+ 		goto out;
+ 	}
+-	debug_text_event(adapter->erp_dbf, 6, "u_usto_ouok");
+-	debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
+ 	retval = ZFCP_ERP_CONTINUES;
+  out:
+ 	return retval;
+@@ -2918,14 +2749,12 @@ void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req)
+  *
+  * returns:
+  */
+-static int
+-zfcp_erp_action_enqueue(int action,
+-			struct zfcp_adapter *adapter,
+-			struct zfcp_port *port, struct zfcp_unit *unit)
++static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
++				   struct zfcp_port *port,
++				   struct zfcp_unit *unit, u8 id, void *ref)
+ {
+-	int retval = 1;
++	int retval = 1, need = want;
+ 	struct zfcp_erp_action *erp_action = NULL;
+-	int stronger_action = 0;
+ 	u32 status = 0;
+ 
+ 	/*
+@@ -2944,17 +2773,11 @@ zfcp_erp_action_enqueue(int action,
+ 			      &adapter->status))
+ 		return -EIO;
+ 
+-	debug_event(adapter->erp_dbf, 4, &action, sizeof (int));
+ 	/* check whether we really need this */
+-	switch (action) {
++	switch (want) {
+ 	case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ 		if (atomic_test_mask
+ 		    (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) {
+-			debug_text_event(adapter->erp_dbf, 4, "u_actenq_drp");
+-			debug_event(adapter->erp_dbf, 4, &port->wwpn,
+-				    sizeof (wwn_t));
+-			debug_event(adapter->erp_dbf, 4, &unit->fcp_lun,
+-				    sizeof (fcp_lun_t));
+ 			goto out;
+ 		}
+ 		if (!atomic_test_mask
+@@ -2964,18 +2787,13 @@ zfcp_erp_action_enqueue(int action,
+ 			goto out;
+ 		}
+ 		if (!atomic_test_mask
+-		    (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) {
+-			stronger_action = ZFCP_ERP_ACTION_REOPEN_PORT;
+-			unit = NULL;
+-		}
++		    (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
++			need = ZFCP_ERP_ACTION_REOPEN_PORT;
+ 		/* fall through !!! */
+ 
+ 	case ZFCP_ERP_ACTION_REOPEN_PORT:
+ 		if (atomic_test_mask
+ 		    (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) {
+-			debug_text_event(adapter->erp_dbf, 4, "p_actenq_drp");
+-			debug_event(adapter->erp_dbf, 4, &port->wwpn,
+-				    sizeof (wwn_t));
+ 			goto out;
+ 		}
+ 		/* fall through !!! */
+@@ -2987,15 +2805,9 @@ zfcp_erp_action_enqueue(int action,
+ 			    ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) {
+ 				ZFCP_LOG_INFO("dropped erp action %i (port "
+ 					      "0x%016Lx, action in use: %i)\n",
+-					      action, port->wwpn,
++					      want, port->wwpn,
+ 					      port->erp_action.action);
+-				debug_text_event(adapter->erp_dbf, 4,
+-						 "pf_actenq_drp");
+-			} else
+-				debug_text_event(adapter->erp_dbf, 4,
+-						 "pf_actenq_drpcp");
+-			debug_event(adapter->erp_dbf, 4, &port->wwpn,
+-				    sizeof (wwn_t));
++			}
+ 			goto out;
+ 		}
+ 		if (!atomic_test_mask
+@@ -3005,46 +2817,36 @@ zfcp_erp_action_enqueue(int action,
+ 			goto out;
+ 		}
+ 		if (!atomic_test_mask
+-		    (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) {
+-			stronger_action = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
+-			port = NULL;
+-		}
++		    (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
++			need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
+ 		/* fall through !!! */
+ 
+ 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+ 		if (atomic_test_mask
+ 		    (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) {
+-			debug_text_event(adapter->erp_dbf, 4, "a_actenq_drp");
+ 			goto out;
+ 		}
+ 		break;
+ 
+ 	default:
+-		debug_text_exception(adapter->erp_dbf, 1, "a_actenq_bug");
+-		debug_event(adapter->erp_dbf, 1, &action, sizeof (int));
+ 		ZFCP_LOG_NORMAL("bug: unknown erp action requested "
+ 				"on adapter %s (action=%d)\n",
+-				zfcp_get_busid_by_adapter(adapter), action);
++				zfcp_get_busid_by_adapter(adapter), want);
+ 		goto out;
+ 	}
+ 
+ 	/* check whether we need something stronger first */
+-	if (stronger_action) {
+-		debug_text_event(adapter->erp_dbf, 4, "a_actenq_str");
+-		debug_event(adapter->erp_dbf, 4, &stronger_action,
+-			    sizeof (int));
++	if (need) {
+ 		ZFCP_LOG_DEBUG("stronger erp action %d needed before "
+ 			       "erp action %d on adapter %s\n",
+-			       stronger_action, action,
+-			       zfcp_get_busid_by_adapter(adapter));
+-		action = stronger_action;
++			       need, want, zfcp_get_busid_by_adapter(adapter));
+ 	}
+ 
+ 	/* mark adapter to have some error recovery pending */
+ 	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
+ 
+ 	/* setup error recovery action */
+-	switch (action) {
++	switch (need) {
+ 
+ 	case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ 		zfcp_unit_get(unit);
+@@ -3077,13 +2879,11 @@ zfcp_erp_action_enqueue(int action,
+ 		break;
+ 	}
+ 
+-	debug_text_event(adapter->erp_dbf, 4, "a_actenq");
+-
+ 	memset(erp_action, 0, sizeof (struct zfcp_erp_action));
+ 	erp_action->adapter = adapter;
+ 	erp_action->port = port;
+ 	erp_action->unit = unit;
+-	erp_action->action = action;
++	erp_action->action = need;
+ 	erp_action->status = status;
+ 
+ 	++adapter->erp_total_count;
+@@ -3091,8 +2891,11 @@ zfcp_erp_action_enqueue(int action,
+ 	/* finally put it into 'ready' queue and kick erp thread */
+ 	list_add_tail(&erp_action->list, &adapter->erp_ready_head);
+ 	up(&adapter->erp_ready_sem);
++	zfcp_rec_dbf_event_thread(1, adapter, 0);
+ 	retval = 0;
+  out:
++	zfcp_rec_dbf_event_trigger(id, ref, want, need, erp_action,
++				   adapter, port, unit);
+ 	return retval;
+ }
+ 
+@@ -3108,9 +2911,9 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
+ 		erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
+ 	}
+ 
+-	debug_text_event(adapter->erp_dbf, 4, "a_actdeq");
+-	debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int));
+ 	list_del(&erp_action->list);
++	zfcp_rec_dbf_event_action(144, erp_action);
++
+ 	switch (erp_action->action) {
+ 	case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ 		atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
+@@ -3215,7 +3018,6 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
+ {
+ 	struct zfcp_port *port;
+ 
+-	debug_text_event(adapter->erp_dbf, 5, "a_actab");
+ 	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status))
+ 		zfcp_erp_action_dismiss(&adapter->erp_action);
+ 	else
+@@ -3226,10 +3028,7 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
+ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
+ {
+ 	struct zfcp_unit *unit;
+-	struct zfcp_adapter *adapter = port->adapter;
+ 
+-	debug_text_event(adapter->erp_dbf, 5, "p_actab");
+-	debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ 	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status))
+ 		zfcp_erp_action_dismiss(&port->erp_action);
+ 	else
+@@ -3239,92 +3038,60 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
+ 
+ static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
+ {
+-	struct zfcp_adapter *adapter = unit->port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 5, "u_actab");
+-	debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
+ 	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status))
+ 		zfcp_erp_action_dismiss(&unit->erp_action);
+ }
+ 
+ static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
+ {
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 6, "a_toru");
+-	debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int));
+ 	list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
++	zfcp_rec_dbf_event_action(145, erp_action);
+ }
+ 
+ static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
+ {
+-	struct zfcp_adapter *adapter = erp_action->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 6, "a_tore");
+-	debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int));
+ 	list_move(&erp_action->list, &erp_action->adapter->erp_ready_head);
++	zfcp_rec_dbf_event_action(146, erp_action);
+ }
+ 
+-void
+-zfcp_erp_port_boxed(struct zfcp_port *port)
++void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref)
+ {
+-	struct zfcp_adapter *adapter = port->adapter;
+ 	unsigned long flags;
+ 
+-	debug_text_event(adapter->erp_dbf, 3, "p_access_boxed");
+-	debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
+ 	read_lock_irqsave(&zfcp_data.config_lock, flags);
+-	zfcp_erp_modify_port_status(port,
+-			ZFCP_STATUS_COMMON_ACCESS_BOXED,
+-			ZFCP_SET);
++	zfcp_erp_modify_port_status(port, id, ref,
++				    ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
+ 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+-	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
++	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
+ }
+ 
+-void
+-zfcp_erp_unit_boxed(struct zfcp_unit *unit)
++void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref)
+ {
+-	struct zfcp_adapter *adapter = unit->port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 3, "u_access_boxed");
+-	debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
+-	zfcp_erp_modify_unit_status(unit,
+-			ZFCP_STATUS_COMMON_ACCESS_BOXED,
+-			ZFCP_SET);
+-	zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
++	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);
+ }
+ 
+-void
+-zfcp_erp_port_access_denied(struct zfcp_port *port)
++void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref)
+ {
+-	struct zfcp_adapter *adapter = port->adapter;
+ 	unsigned long flags;
+ 
+-	debug_text_event(adapter->erp_dbf, 3, "p_access_denied");
+-	debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
+ 	read_lock_irqsave(&zfcp_data.config_lock, flags);
+-	zfcp_erp_modify_port_status(port,
+-			ZFCP_STATUS_COMMON_ERP_FAILED |
+-			ZFCP_STATUS_COMMON_ACCESS_DENIED,
+-			ZFCP_SET);
++	zfcp_erp_modify_port_status(port, id, ref,
++				    ZFCP_STATUS_COMMON_ERP_FAILED |
++				    ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
+ 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ }
+ 
+-void
+-zfcp_erp_unit_access_denied(struct zfcp_unit *unit)
++void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref)
+ {
+-	struct zfcp_adapter *adapter = unit->port->adapter;
+-
+-	debug_text_event(adapter->erp_dbf, 3, "u_access_denied");
+-	debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
+-	zfcp_erp_modify_unit_status(unit,
+-			ZFCP_STATUS_COMMON_ERP_FAILED |
+-			ZFCP_STATUS_COMMON_ACCESS_DENIED,
+-			ZFCP_SET);
++	zfcp_erp_modify_unit_status(unit, id, ref,
++				    ZFCP_STATUS_COMMON_ERP_FAILED |
++				    ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
+ }
+ 
+-void
+-zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
++void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id,
++				     void *ref)
+ {
+ 	struct zfcp_port *port;
+ 	unsigned long flags;
+@@ -3332,54 +3099,43 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
+ 	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ 		return;
+ 
+-	debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
+-	debug_event(adapter->erp_dbf, 3, zfcp_get_busid_by_adapter(adapter), 8);
+-
+ 	read_lock_irqsave(&zfcp_data.config_lock, flags);
+ 	if (adapter->nameserver_port)
+-		zfcp_erp_port_access_changed(adapter->nameserver_port);
++		zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref);
+ 	list_for_each_entry(port, &adapter->port_list_head, list)
+ 		if (port != adapter->nameserver_port)
+-			zfcp_erp_port_access_changed(port);
++			zfcp_erp_port_access_changed(port, id, ref);
+ 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ }
+ 
+-void
+-zfcp_erp_port_access_changed(struct zfcp_port *port)
++void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, void *ref)
+ {
+ 	struct zfcp_adapter *adapter = port->adapter;
+ 	struct zfcp_unit *unit;
+ 
+-	debug_text_event(adapter->erp_dbf, 3, "p_access_recover");
+-	debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
+-
+ 	if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
+ 			      &port->status) &&
+ 	    !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
+ 			      &port->status)) {
+ 		if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
+ 			list_for_each_entry(unit, &port->unit_list_head, list)
+-				zfcp_erp_unit_access_changed(unit);
++				zfcp_erp_unit_access_changed(unit, id, ref);
+ 		return;
+ 	}
+ 
+ 	ZFCP_LOG_NORMAL("reopen of port 0x%016Lx on adapter %s "
+ 			"(due to ACT update)\n",
+ 			port->wwpn, zfcp_get_busid_by_adapter(adapter));
+-	if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
++	if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref))
+ 		ZFCP_LOG_NORMAL("failed reopen of port"
+ 				"(adapter %s, wwpn=0x%016Lx)\n",
+ 				zfcp_get_busid_by_adapter(adapter), port->wwpn);
+ }
+ 
+-void
+-zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
++void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, void *ref)
+ {
+ 	struct zfcp_adapter *adapter = unit->port->adapter;
+ 
+-	debug_text_event(adapter->erp_dbf, 3, "u_access_recover");
+-	debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
+-
+ 	if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
+ 			      &unit->status) &&
+ 	    !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
+@@ -3390,7 +3146,7 @@ zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
+ 			" on adapter %s (due to ACT update)\n",
+ 			unit->fcp_lun, unit->port->wwpn,
+ 			zfcp_get_busid_by_adapter(adapter));
+-	if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
++	if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref))
+ 		ZFCP_LOG_NORMAL("failed reopen of unit (adapter %s, "
+ 				"wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
+ 				zfcp_get_busid_by_adapter(adapter),
+diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
+index 06b1079..6abf178 100644
+--- a/drivers/s390/scsi/zfcp_ext.h
++++ b/drivers/s390/scsi/zfcp_ext.h
+@@ -131,22 +131,25 @@ extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, int);
+ extern struct fc_function_template zfcp_transport_functions;
+ 
+ /******************************** ERP ****************************************/
+-extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int);
+-extern int  zfcp_erp_adapter_reopen(struct zfcp_adapter *, int);
+-extern int  zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int);
+-extern void zfcp_erp_adapter_failed(struct zfcp_adapter *);
+-
+-extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int);
+-extern int  zfcp_erp_port_reopen(struct zfcp_port *, int);
+-extern int  zfcp_erp_port_shutdown(struct zfcp_port *, int);
+-extern int  zfcp_erp_port_forced_reopen(struct zfcp_port *, int);
+-extern void zfcp_erp_port_failed(struct zfcp_port *);
+-extern int  zfcp_erp_port_reopen_all(struct zfcp_adapter *, int);
+-
+-extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u32, int);
+-extern int  zfcp_erp_unit_reopen(struct zfcp_unit *, int);
+-extern int  zfcp_erp_unit_shutdown(struct zfcp_unit *, int);
+-extern void zfcp_erp_unit_failed(struct zfcp_unit *);
++extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u8, void *,
++					   u32, int);
++extern int  zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, u8, void *);
++extern int  zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, u8, void *);
++extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, u8, void *);
++
++extern void zfcp_erp_modify_port_status(struct zfcp_port *, u8, void *, u32,
++					int);
++extern int  zfcp_erp_port_reopen(struct zfcp_port *, int, u8, void *);
++extern int  zfcp_erp_port_shutdown(struct zfcp_port *, int, u8, void *);
++extern int  zfcp_erp_port_forced_reopen(struct zfcp_port *, int, u8, void *);
++extern void zfcp_erp_port_failed(struct zfcp_port *, u8, void *);
++extern int  zfcp_erp_port_reopen_all(struct zfcp_adapter *, int, u8, void *);
++
++extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u8, void *, u32,
++					int);
++extern int  zfcp_erp_unit_reopen(struct zfcp_unit *, int, u8, void *);
++extern int  zfcp_erp_unit_shutdown(struct zfcp_unit *, int, u8, void *);
++extern void zfcp_erp_unit_failed(struct zfcp_unit *, u8, void *);
+ 
+ extern int  zfcp_erp_thread_setup(struct zfcp_adapter *);
+ extern int  zfcp_erp_thread_kill(struct zfcp_adapter *);
+@@ -155,15 +158,25 @@ extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
+ 
+ extern int  zfcp_test_link(struct zfcp_port *);
+ 
+-extern void zfcp_erp_port_boxed(struct zfcp_port *);
+-extern void zfcp_erp_unit_boxed(struct zfcp_unit *);
+-extern void zfcp_erp_port_access_denied(struct zfcp_port *);
+-extern void zfcp_erp_unit_access_denied(struct zfcp_unit *);
+-extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *);
+-extern void zfcp_erp_port_access_changed(struct zfcp_port *);
+-extern void zfcp_erp_unit_access_changed(struct zfcp_unit *);
++extern void zfcp_erp_port_boxed(struct zfcp_port *, u8 id, void *ref);
++extern void zfcp_erp_unit_boxed(struct zfcp_unit *, u8 id, void *ref);
++extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8 id, void *ref);
++extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8 id, void *ref);
++extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *);
++extern void zfcp_erp_port_access_changed(struct zfcp_port *, u8, void *);
++extern void zfcp_erp_unit_access_changed(struct zfcp_unit *, u8, void *);
+ 
+ /******************************** AUX ****************************************/
++extern void zfcp_rec_dbf_event_thread(u8 id, struct zfcp_adapter *adapter,
++				      int lock);
++extern void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *);
++extern void zfcp_rec_dbf_event_port(u8 id, void *ref, struct zfcp_port *port);
++extern void zfcp_rec_dbf_event_unit(u8 id, void *ref, struct zfcp_unit *unit);
++extern void zfcp_rec_dbf_event_trigger(u8 id, void *ref, u8 want, u8 need,
++				       void *action, struct zfcp_adapter *,
++				       struct zfcp_port *, struct zfcp_unit *);
++extern void zfcp_rec_dbf_event_action(u8 id, struct zfcp_erp_action *);
++
+ extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *);
+ extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *,
+ 					 struct fsf_status_read_buffer *);
+diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
+index 0dff058..7c3f028 100644
+--- a/drivers/s390/scsi/zfcp_fsf.c
++++ b/drivers/s390/scsi/zfcp_fsf.c
+@@ -46,7 +46,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *);
+ static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *);
+ static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
+ static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
+-static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *,
++static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *, u8,
+ 	struct fsf_link_down_info *);
+ static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
+ 
+@@ -284,37 +284,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ 		goto skip_protstatus;
+ 	}
+ 
+-	/* log additional information provided by FSF (if any) */
+-	if (likely(qtcb->header.log_length)) {
+-		/* do not trust them ;-) */
+-		if (unlikely(qtcb->header.log_start >
+-			     sizeof(struct fsf_qtcb))) {
+-			ZFCP_LOG_NORMAL
+-			    ("bug: ULP (FSF logging) log data starts "
+-			     "beyond end of packet header. Ignored. "
+-			     "(start=%i, size=%li)\n",
+-			     qtcb->header.log_start,
+-			     sizeof(struct fsf_qtcb));
+-			goto forget_log;
+-		}
+-		if (unlikely((size_t) (qtcb->header.log_start +
+-				       qtcb->header.log_length) >
+-			     sizeof(struct fsf_qtcb))) {
+-			ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
+-					"beyond end of packet header. Ignored. "
+-					"(start=%i, length=%i, size=%li)\n",
+-					qtcb->header.log_start,
+-					qtcb->header.log_length,
+-					sizeof(struct fsf_qtcb));
+-			goto forget_log;
+-		}
+-		ZFCP_LOG_TRACE("ULP log data: \n");
+-		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
+-			      (char *) qtcb + qtcb->header.log_start,
+-			      qtcb->header.log_length);
+-	}
+- forget_log:
+-
+ 	/* evaluate FSF Protocol Status */
+ 	switch (qtcb->prefix.prot_status) {
+ 
+@@ -329,7 +298,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ 				zfcp_get_busid_by_adapter(adapter),
+ 				prot_status_qual->version_error.fsf_version,
+ 				ZFCP_QTCB_VERSION);
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 117, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -340,7 +309,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ 				qtcb->prefix.req_seq_no,
+ 				zfcp_get_busid_by_adapter(adapter),
+ 				prot_status_qual->sequence_error.exp_req_seq_no);
+-		zfcp_erp_adapter_reopen(adapter, 0);
++		zfcp_erp_adapter_reopen(adapter, 0, 98, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+@@ -351,7 +320,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ 				"that used on adapter %s. "
+ 				"Stopping all operations on this adapter.\n",
+ 				zfcp_get_busid_by_adapter(adapter));
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 118, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -368,14 +337,15 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ 				*(unsigned long long*)
+ 				(&qtcb->bottom.support.req_handle),
+ 					zfcp_get_busid_by_adapter(adapter));
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 78, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+ 	case FSF_PROT_LINK_DOWN:
+-		zfcp_fsf_link_down_info_eval(adapter,
++		zfcp_fsf_link_down_info_eval(fsf_req, 37,
+ 					     &prot_status_qual->link_down_info);
+-		zfcp_erp_adapter_reopen(adapter, 0);
++		/* FIXME: reopening adapter now? better wait for link up */
++		zfcp_erp_adapter_reopen(adapter, 0, 79, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -385,12 +355,13 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ 			      "Re-starting operations on this adapter.\n",
+ 			      zfcp_get_busid_by_adapter(adapter));
+ 		/* All ports should be marked as ready to run again */
+-		zfcp_erp_modify_adapter_status(adapter,
++		zfcp_erp_modify_adapter_status(adapter, 28, NULL,
+ 					       ZFCP_STATUS_COMMON_RUNNING,
+ 					       ZFCP_SET);
+ 		zfcp_erp_adapter_reopen(adapter,
+ 					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
+-					| ZFCP_STATUS_COMMON_ERP_FAILED);
++					| ZFCP_STATUS_COMMON_ERP_FAILED,
++					99, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -400,7 +371,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ 				"Restarting all operations on this "
+ 				"adapter.\n",
+ 				zfcp_get_busid_by_adapter(adapter));
+-		zfcp_erp_adapter_reopen(adapter, 0);
++		zfcp_erp_adapter_reopen(adapter, 0, 100, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+@@ -413,7 +384,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ 				"(debug info 0x%x).\n",
+ 				zfcp_get_busid_by_adapter(adapter),
+ 				qtcb->prefix.prot_status);
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 119, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 	}
+ 
+@@ -452,7 +423,7 @@ zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req)
+ 				"(debug info 0x%x).\n",
+ 				zfcp_get_busid_by_adapter(fsf_req->adapter),
+ 				fsf_req->qtcb->header.fsf_command);
+-		zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
++		zfcp_erp_adapter_shutdown(fsf_req->adapter, 0, 120, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -506,7 +477,7 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
+ 				"problem on the adapter %s "
+ 				"Stopping all operations on this adapter. ",
+ 				zfcp_get_busid_by_adapter(fsf_req->adapter));
+-		zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
++		zfcp_erp_adapter_shutdown(fsf_req->adapter, 0, 121, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 	case FSF_SQ_ULP_PROGRAMMING_ERROR:
+@@ -537,9 +508,11 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
+  * zfcp_fsf_link_down_info_eval - evaluate link down information block
+  */
+ static void
+-zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
++zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *fsf_req, u8 id,
+ 			     struct fsf_link_down_info *link_down)
+ {
++	struct zfcp_adapter *adapter = fsf_req->adapter;
++
+ 	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ 	                     &adapter->status))
+ 		return;
+@@ -630,7 +603,7 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
+ 				link_down->vendor_specific_code);
+ 
+  out:
+-	zfcp_erp_adapter_failed(adapter);
++	zfcp_erp_adapter_failed(adapter, id, fsf_req);
+ }
+ 
+ /*
+@@ -824,19 +797,14 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
+ 	switch (status_buffer->status_subtype) {
+ 
+ 	case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT:
+-		debug_text_event(adapter->erp_dbf, 3, "unsol_pc_phys:");
+-		zfcp_erp_port_reopen(port, 0);
++		zfcp_erp_port_reopen(port, 0, 101, fsf_req);
+ 		break;
+ 
+ 	case FSF_STATUS_READ_SUB_ERROR_PORT:
+-		debug_text_event(adapter->erp_dbf, 1, "unsol_pc_err:");
+-		zfcp_erp_port_shutdown(port, 0);
++		zfcp_erp_port_shutdown(port, 0, 122, fsf_req);
+ 		break;
+ 
+ 	default:
+-		debug_text_event(adapter->erp_dbf, 0, "unsol_unk_sub:");
+-		debug_exception(adapter->erp_dbf, 0,
+-				&status_buffer->status_subtype, sizeof (u32));
+ 		ZFCP_LOG_NORMAL("bug: Undefined status subtype received "
+ 				"for a reopen indication on port with "
+ 				"d_id 0x%06x on the adapter %s. "
+@@ -928,7 +896,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ 		case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
+ 			ZFCP_LOG_INFO("Physical link to adapter %s is down\n",
+ 				      zfcp_get_busid_by_adapter(adapter));
+-			zfcp_fsf_link_down_info_eval(adapter,
++			zfcp_fsf_link_down_info_eval(fsf_req, 38,
+ 				(struct fsf_link_down_info *)
+ 				&status_buffer->payload);
+ 			break;
+@@ -936,7 +904,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ 			ZFCP_LOG_INFO("Local link to adapter %s is down "
+ 				      "due to failed FDISC login\n",
+ 				      zfcp_get_busid_by_adapter(adapter));
+-			zfcp_fsf_link_down_info_eval(adapter,
++			zfcp_fsf_link_down_info_eval(fsf_req, 39,
+ 				(struct fsf_link_down_info *)
+ 				&status_buffer->payload);
+ 			break;
+@@ -944,13 +912,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ 			ZFCP_LOG_INFO("Local link to adapter %s is down "
+ 				      "due to firmware update on adapter\n",
+ 				      zfcp_get_busid_by_adapter(adapter));
+-			zfcp_fsf_link_down_info_eval(adapter, NULL);
++			zfcp_fsf_link_down_info_eval(fsf_req, 40, NULL);
+ 			break;
+ 		default:
+ 			ZFCP_LOG_INFO("Local link to adapter %s is down "
+ 				      "due to unknown reason\n",
+ 				      zfcp_get_busid_by_adapter(adapter));
+-			zfcp_fsf_link_down_info_eval(adapter, NULL);
++			zfcp_fsf_link_down_info_eval(fsf_req, 41, NULL);
+ 		};
+ 		break;
+ 
+@@ -959,12 +927,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ 				"Restarting operations on this adapter\n",
+ 				zfcp_get_busid_by_adapter(adapter));
+ 		/* All ports should be marked as ready to run again */
+-		zfcp_erp_modify_adapter_status(adapter,
++		zfcp_erp_modify_adapter_status(adapter, 30, NULL,
+ 					       ZFCP_STATUS_COMMON_RUNNING,
+ 					       ZFCP_SET);
+ 		zfcp_erp_adapter_reopen(adapter,
+ 					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
+-					| ZFCP_STATUS_COMMON_ERP_FAILED);
++					| ZFCP_STATUS_COMMON_ERP_FAILED,
++					102, fsf_req);
+ 		break;
+ 
+ 	case FSF_STATUS_READ_NOTIFICATION_LOST:
+@@ -998,13 +967,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ 
+ 		if (status_buffer->status_subtype &
+ 		    FSF_STATUS_READ_SUB_ACT_UPDATED)
+-			zfcp_erp_adapter_access_changed(adapter);
++			zfcp_erp_adapter_access_changed(adapter, 135, fsf_req);
+ 		break;
+ 
+ 	case FSF_STATUS_READ_CFDC_UPDATED:
+ 		ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
+ 			      zfcp_get_busid_by_adapter(adapter));
+-		zfcp_erp_adapter_access_changed(adapter);
++		zfcp_erp_adapter_access_changed(adapter, 136, fsf_req);
+ 		break;
+ 
+ 	case FSF_STATUS_READ_CFDC_HARDENED:
+@@ -1025,7 +994,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ 		break;
+ 
+ 	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
+-		debug_text_event(adapter->erp_dbf, 2, "unsol_features:");
+ 		ZFCP_LOG_INFO("List of supported features on adapter %s has "
+ 			      "been changed from 0x%08X to 0x%08X\n",
+ 			      zfcp_get_busid_by_adapter(adapter),
+@@ -1073,7 +1041,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ 			ZFCP_LOG_INFO("restart adapter %s due to status read "
+ 				      "buffer shortage\n",
+ 				      zfcp_get_busid_by_adapter(adapter));
+-			zfcp_erp_adapter_reopen(adapter, 0);
++			zfcp_erp_adapter_reopen(adapter, 0, 103, fsf_req);
+ 		}
+ 	}
+  out:
+@@ -1174,8 +1142,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ 
+ 	case FSF_PORT_HANDLE_NOT_VALID:
+ 		if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) {
+-			debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
+-					 "fsf_s_phand_nv0");
+ 			/*
+ 			 * In this case a command that was sent prior to a port
+ 			 * reopen was aborted (handles are different). This is
+@@ -1194,17 +1160,14 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ 				      fsf_status_qual,
+ 				      sizeof (union fsf_status_qual));
+ 			/* Let's hope this sorts out the mess */
+-			debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_s_phand_nv1");
+-			zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++			zfcp_erp_adapter_reopen(unit->port->adapter, 0, 104,
++						new_fsf_req);
+ 			new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		}
+ 		break;
+ 
+ 	case FSF_LUN_HANDLE_NOT_VALID:
+ 		if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) {
+-			debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
+-					 "fsf_s_lhand_nv0");
+ 			/*
+ 			 * In this case a command that was sent prior to a unit
+ 			 * reopen was aborted (handles are different).
+@@ -1226,17 +1189,13 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ 				      fsf_status_qual,
+ 				      sizeof (union fsf_status_qual));
+ 			/* Let's hope this sorts out the mess */
+-			debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_s_lhand_nv1");
+-			zfcp_erp_port_reopen(unit->port, 0);
++			zfcp_erp_port_reopen(unit->port, 0, 105, new_fsf_req);
+ 			new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		}
+ 		break;
+ 
+ 	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
+ 		retval = 0;
+-		debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
+-				 "fsf_s_no_exist");
+ 		new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
+ 		break;
+ 
+@@ -1244,9 +1203,7 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ 		ZFCP_LOG_INFO("Remote port 0x%016Lx on adapter %s needs to "
+ 			      "be reopened\n", unit->port->wwpn,
+ 			      zfcp_get_busid_by_unit(unit));
+-		debug_text_event(new_fsf_req->adapter->erp_dbf, 2,
+-				 "fsf_s_pboxed");
+-		zfcp_erp_port_boxed(unit->port);
++		zfcp_erp_port_boxed(unit->port, 47, new_fsf_req);
+ 		new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+ 		    | ZFCP_STATUS_FSFREQ_RETRY;
+ 		break;
+@@ -1257,8 +1214,7 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+                         "to be reopened\n",
+                         unit->fcp_lun, unit->port->wwpn,
+                         zfcp_get_busid_by_unit(unit));
+-                debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
+-		zfcp_erp_unit_boxed(unit);
++		zfcp_erp_unit_boxed(unit, 48, new_fsf_req);
+                 new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+                         | ZFCP_STATUS_FSFREQ_RETRY;
+                 break;
+@@ -1266,26 +1222,17 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ 	case FSF_ADAPTER_STATUS_AVAILABLE:
+ 		switch (new_fsf_req->qtcb->header.fsf_status_qual.word[0]) {
+ 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+-			debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ltest");
+ 			zfcp_test_link(unit->port);
+ 			new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ 			/* SCSI stack will escalate */
+-			debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ulp");
+ 			new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		default:
+ 			ZFCP_LOG_NORMAL
+ 			    ("bug: Wrong status qualifier 0x%x arrived.\n",
+ 			     new_fsf_req->qtcb->header.fsf_status_qual.word[0]);
+-			debug_text_event(new_fsf_req->adapter->erp_dbf, 0,
+-					 "fsf_sq_inval:");
+-			debug_exception(new_fsf_req->adapter->erp_dbf, 0,
+-					&new_fsf_req->qtcb->header.
+-					fsf_status_qual.word[0], sizeof (u32));
+ 			break;
+ 		}
+ 		break;
+@@ -1299,11 +1246,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ 				"(debug info 0x%x)\n",
+ 				new_fsf_req->qtcb->header.fsf_status);
+-		debug_text_event(new_fsf_req->adapter->erp_dbf, 0,
+-				 "fsf_s_inval:");
+-		debug_exception(new_fsf_req->adapter->erp_dbf, 0,
+-				&new_fsf_req->qtcb->header.fsf_status,
+-				sizeof (u32));
+ 		break;
+ 	}
+  skip_fsfstatus:
+@@ -1506,8 +1448,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ 			      zfcp_get_busid_by_port(port),
+ 			      ZFCP_FC_SERVICE_CLASS_DEFAULT);
+ 		/* stop operation for this adapter */
+-		debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 123, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -1515,13 +1456,11 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+                 switch (header->fsf_status_qual.word[0]){
+                 case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+ 			/* reopening link to port */
+-			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
+ 			zfcp_test_link(port);
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+                 case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ 			/* ERP strategy will escalate */
+-			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+                 default:
+@@ -1549,8 +1488,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ 				break;
+ 			}
+ 		}
+-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
+-		zfcp_erp_port_access_denied(port);
++		zfcp_erp_port_access_denied(port, 55, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -1562,7 +1500,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
+ 			      (char *) &header->fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_gcom_rej");
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -1575,8 +1512,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
+ 			      (char *) &header->fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv");
+-		zfcp_erp_adapter_reopen(adapter, 0);
++		zfcp_erp_adapter_reopen(adapter, 0, 106, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -1584,8 +1520,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_INFO("port needs to be reopened "
+ 			      "(adapter %s, port d_id=0x%06x)\n",
+ 			      zfcp_get_busid_by_port(port), port->d_id);
+-		debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
+-		zfcp_erp_port_boxed(port);
++		zfcp_erp_port_boxed(port, 49, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+ 		    | ZFCP_STATUS_FSFREQ_RETRY;
+ 		break;
+@@ -1624,9 +1559,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+        default:
+ 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ 				"(debug info 0x%x)\n", header->fsf_status);
+-		debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:");
+-		debug_exception(adapter->erp_dbf, 0,
+-				&header->fsf_status_qual.word[0], sizeof (u32));
+ 		break;
+ 	}
+ 
+@@ -1810,21 +1742,18 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
+ 			      zfcp_get_busid_by_adapter(adapter),
+ 			      ZFCP_FC_SERVICE_CLASS_DEFAULT);
+ 		/* stop operation for this adapter */
+-		debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 124, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+ 	case FSF_ADAPTER_STATUS_AVAILABLE:
+ 		switch (header->fsf_status_qual.word[0]){
+ 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+-			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
+ 			if (port && (send_els->ls_code != ZFCP_LS_ADISC))
+ 				zfcp_test_link(port);
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+-			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			retval =
+ 			  zfcp_handle_els_rjt(header->fsf_status_qual.word[1],
+@@ -1832,7 +1761,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
+ 					      &header->fsf_status_qual.word[2]);
+ 			break;
+ 		case FSF_SQ_RETRY_IF_POSSIBLE:
+-			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry");
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		default:
+@@ -1909,9 +1837,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
+ 				break;
+ 			}
+ 		}
+-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
+ 		if (port != NULL)
+-			zfcp_erp_port_access_denied(port);
++			zfcp_erp_port_access_denied(port, 56, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -1921,9 +1848,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
+ 			"(adapter: %s, fsf_status=0x%08x)\n",
+ 			zfcp_get_busid_by_adapter(adapter),
+ 			header->fsf_status);
+-		debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval");
+-		debug_exception(adapter->erp_dbf, 0,
+-			&header->fsf_status_qual.word[0], sizeof(u32));
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 	}
+@@ -2132,8 +2056,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
+ 				"versions in comparison to this device "
+ 				"driver (try updated device driver)\n",
+ 				zfcp_get_busid_by_adapter(adapter));
+-		debug_text_event(adapter->erp_dbf, 0, "low_qtcb_ver");
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 125, fsf_req);
+ 		return -EIO;
+ 	}
+ 	if (ZFCP_QTCB_VERSION > bottom->high_qtcb_version) {
+@@ -2142,8 +2065,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
+ 				"versions than this device driver uses"
+ 				"(consider a microcode upgrade)\n",
+ 				zfcp_get_busid_by_adapter(adapter));
+-		debug_text_event(adapter->erp_dbf, 0, "high_qtcb_ver");
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 126, fsf_req);
+ 		return -EIO;
+ 	}
+ 	return 0;
+@@ -2183,17 +2105,13 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
+ 					adapter->peer_wwnn,
+ 					adapter->peer_wwpn,
+ 					adapter->peer_d_id);
+-			debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-					"top-p-to-p");
+ 			break;
+ 		case FC_PORTTYPE_NLPORT:
+ 			ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
+ 					"topology detected at adapter %s "
+ 					"unsupported, shutting down adapter\n",
+ 					zfcp_get_busid_by_adapter(adapter));
+-			debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-					 "top-al");
+-			zfcp_erp_adapter_shutdown(adapter, 0);
++			zfcp_erp_adapter_shutdown(adapter, 0, 127, fsf_req);
+ 			return -EIO;
+ 		case FC_PORTTYPE_NPORT:
+ 			ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
+@@ -2208,9 +2126,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
+ 					"of a type known to the zfcp "
+ 					"driver, shutting down adapter\n",
+ 					zfcp_get_busid_by_adapter(adapter));
+-			debug_text_exception(fsf_req->adapter->erp_dbf, 0,
+-					     "unknown-topo");
+-			zfcp_erp_adapter_shutdown(adapter, 0);
++			zfcp_erp_adapter_shutdown(adapter, 0, 128, fsf_req);
+ 			return -EIO;
+ 		}
+ 		bottom = &qtcb->bottom.config;
+@@ -2222,33 +2138,24 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
+ 					bottom->max_qtcb_size,
+ 					zfcp_get_busid_by_adapter(adapter),
+ 					sizeof(struct fsf_qtcb));
+-			debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-					 "qtcb-size");
+-			debug_event(fsf_req->adapter->erp_dbf, 0,
+-				    &bottom->max_qtcb_size, sizeof (u32));
+-			zfcp_erp_adapter_shutdown(adapter, 0);
++			zfcp_erp_adapter_shutdown(adapter, 0, 129, fsf_req);
+ 			return -EIO;
+ 		}
+ 		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
+ 				&adapter->status);
+ 		break;
+ 	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+-		debug_text_event(adapter->erp_dbf, 0, "xchg-inco");
+-
+ 		if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0))
+ 			return -EIO;
+ 
+ 		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
+ 				&adapter->status);
+ 
+-		zfcp_fsf_link_down_info_eval(adapter,
++		zfcp_fsf_link_down_info_eval(fsf_req, 42,
+ 			&qtcb->header.fsf_status_qual.link_down_info);
+ 		break;
+ 	default:
+-		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
+-		debug_event(fsf_req->adapter->erp_dbf, 0,
+-			    &fsf_req->qtcb->header.fsf_status, sizeof(u32));
+-		zfcp_erp_adapter_shutdown(adapter, 0);
++		zfcp_erp_adapter_shutdown(adapter, 0, 130, fsf_req);
+ 		return -EIO;
+ 	}
+ 	return 0;
+@@ -2424,13 +2331,9 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
+ 	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+ 		zfcp_fsf_exchange_port_evaluate(fsf_req, 0);
+ 		atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
+-		zfcp_fsf_link_down_info_eval(adapter,
++		zfcp_fsf_link_down_info_eval(fsf_req, 43,
+ 			&qtcb->header.fsf_status_qual.link_down_info);
+                 break;
+-        default:
+-		debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
+-		debug_event(adapter->erp_dbf, 0,
+-			    &fsf_req->qtcb->header.fsf_status, sizeof(u32));
+ 	}
+ }
+ 
+@@ -2528,8 +2431,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_NORMAL("bug: remote port 0x%016Lx on adapter %s "
+ 				"is already open.\n",
+ 				port->wwpn, zfcp_get_busid_by_port(port));
+-		debug_text_exception(fsf_req->adapter->erp_dbf, 0,
+-				     "fsf_s_popen");
+ 		/*
+ 		 * This is a bug, however operation should continue normally
+ 		 * if it is simply ignored
+@@ -2553,8 +2454,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ 				break;
+ 			}
+ 		}
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+-		zfcp_erp_port_access_denied(port);
++		zfcp_erp_port_access_denied(port, 57, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -2563,24 +2463,18 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ 			      "The remote port 0x%016Lx on adapter %s "
+ 			      "could not be opened. Disabling it.\n",
+ 			      port->wwpn, zfcp_get_busid_by_port(port));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-				 "fsf_s_max_ports");
+-		zfcp_erp_port_failed(port);
++		zfcp_erp_port_failed(port, 31, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+ 	case FSF_ADAPTER_STATUS_AVAILABLE:
+ 		switch (header->fsf_status_qual.word[0]) {
+ 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ltest");
+ 			/* ERP strategy will escalate */
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ 			/* ERP strategy will escalate */
+-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ulp");
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		case FSF_SQ_NO_RETRY_POSSIBLE:
+@@ -2589,21 +2483,13 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ 					"Disabling it.\n",
+ 					port->wwpn,
+ 					zfcp_get_busid_by_port(port));
+-			debug_text_exception(fsf_req->adapter->erp_dbf, 0,
+-					     "fsf_sq_no_retry");
+-			zfcp_erp_port_failed(port);
++			zfcp_erp_port_failed(port, 32, fsf_req);
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		default:
+ 			ZFCP_LOG_NORMAL
+ 			    ("bug: Wrong status qualifier 0x%x arrived.\n",
+ 			     header->fsf_status_qual.word[0]);
+-			debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-					 "fsf_sq_inval:");
+-			debug_exception(
+-				fsf_req->adapter->erp_dbf, 0,
+-				&header->fsf_status_qual.word[0],
+-				sizeof (u32));
+ 			break;
+ 		}
+ 		break;
+@@ -2646,17 +2532,12 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ 					"warning: insufficient length of "
+ 					"PLOGI payload (%i)\n",
+ 					fsf_req->qtcb->bottom.support.els1_length);
+-				debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-						 "fsf_s_short_plogi:");
+ 				/* skip sanity check and assume wwpn is ok */
+ 			} else {
+ 				if (plogi->serv_param.wwpn != port->wwpn) {
+ 					ZFCP_LOG_INFO("warning: d_id of port "
+ 						      "0x%016Lx changed during "
+ 						      "open\n", port->wwpn);
+-					debug_text_event(
+-						fsf_req->adapter->erp_dbf, 0,
+-						"fsf_s_did_change:");
+ 					atomic_clear_mask(
+ 						ZFCP_STATUS_PORT_DID_DID,
+ 						&port->status);
+@@ -2681,9 +2562,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ 				"(debug info 0x%x)\n",
+ 				header->fsf_status);
+-		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+-		debug_exception(fsf_req->adapter->erp_dbf, 0,
+-				&header->fsf_status, sizeof (u32));
+ 		break;
+ 	}
+ 
+@@ -2787,9 +2665,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ 			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-				 "fsf_s_phand_nv");
+-		zfcp_erp_adapter_reopen(port->adapter, 0);
++		zfcp_erp_adapter_reopen(port->adapter, 0, 107, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -2804,7 +2680,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_TRACE("remote port 0x016%Lx on adapter %s closed, "
+ 			       "port handle 0x%x\n", port->wwpn,
+ 			       zfcp_get_busid_by_port(port), port->handle);
+-		zfcp_erp_modify_port_status(port,
++		zfcp_erp_modify_port_status(port, 33, fsf_req,
+ 					    ZFCP_STATUS_COMMON_OPEN,
+ 					    ZFCP_CLEAR);
+ 		retval = 0;
+@@ -2814,10 +2690,6 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ 				"(debug info 0x%x)\n",
+ 				fsf_req->qtcb->header.fsf_status);
+-		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+-		debug_exception(fsf_req->adapter->erp_dbf, 0,
+-				&fsf_req->qtcb->header.fsf_status,
+-				sizeof (u32));
+ 		break;
+ 	}
+ 
+@@ -2930,9 +2802,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ 			      (char *) &header->fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-				 "fsf_s_phand_nv");
+-		zfcp_erp_adapter_reopen(port->adapter, 0);
++		zfcp_erp_adapter_reopen(port->adapter, 0, 108, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -2953,8 +2823,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
+ 				break;
+ 			}
+ 		}
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+-		zfcp_erp_port_access_denied(port);
++		zfcp_erp_port_access_denied(port, 58, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -2964,35 +2833,32 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
+ 			       "to close it physically.\n",
+ 			       port->wwpn,
+ 			       zfcp_get_busid_by_port(port));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_pboxed");
+-		zfcp_erp_port_boxed(port);
++		zfcp_erp_port_boxed(port, 50, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
+ 			ZFCP_STATUS_FSFREQ_RETRY;
++
++		/* 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);
++		list_for_each_entry(unit, &port->unit_list_head, list)
++			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
++					  &unit->status);
+ 		break;
+ 
+ 	case FSF_ADAPTER_STATUS_AVAILABLE:
+ 		switch (header->fsf_status_qual.word[0]) {
+ 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ltest");
+ 			/* This will now be escalated by ERP */
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ 			/* ERP strategy will escalate */
+-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ulp");
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		default:
+ 			ZFCP_LOG_NORMAL
+ 			    ("bug: Wrong status qualifier 0x%x arrived.\n",
+ 			     header->fsf_status_qual.word[0]);
+-			debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-					 "fsf_sq_inval:");
+-			debug_exception(
+-				fsf_req->adapter->erp_dbf, 0,
+-				&header->fsf_status_qual.word[0], sizeof (u32));
+ 			break;
+ 		}
+ 		break;
+@@ -3015,9 +2881,6 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ 				"(debug info 0x%x)\n",
+ 				header->fsf_status);
+-		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+-		debug_exception(fsf_req->adapter->erp_dbf, 0,
+-				&header->fsf_status, sizeof (u32));
+ 		break;
+ 	}
+ 
+@@ -3149,8 +3012,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ 			      (char *) &header->fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_ph_nv");
+-		zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++		zfcp_erp_adapter_reopen(unit->port->adapter, 0, 109, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3159,8 +3021,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 				"remote port 0x%016Lx on adapter %s twice.\n",
+ 				unit->fcp_lun,
+ 				unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+-		debug_text_exception(adapter->erp_dbf, 0,
+-				     "fsf_s_uopen");
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3182,8 +3042,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 				break;
+ 			}
+ 		}
+-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
+-		zfcp_erp_unit_access_denied(unit);
++		zfcp_erp_unit_access_denied(unit, 59, fsf_req);
+ 		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
+                 atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+@@ -3193,8 +3052,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
+ 			       "needs to be reopened\n",
+ 			       unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+-		debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
+-		zfcp_erp_port_boxed(unit->port);
++		zfcp_erp_port_boxed(unit->port, 51, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
+ 			ZFCP_STATUS_FSFREQ_RETRY;
+ 		break;
+@@ -3234,9 +3092,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ 			      (char *) &header->fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(adapter->erp_dbf, 2,
+-				 "fsf_s_l_sh_vio");
+-		zfcp_erp_unit_access_denied(unit);
++		zfcp_erp_unit_access_denied(unit, 60, fsf_req);
+ 		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
+ 		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+@@ -3250,9 +3106,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 			      unit->fcp_lun,
+ 			      unit->port->wwpn,
+ 			      zfcp_get_busid_by_unit(unit));
+-		debug_text_event(adapter->erp_dbf, 1,
+-				 "fsf_s_max_units");
+-		zfcp_erp_unit_failed(unit);
++		zfcp_erp_unit_failed(unit, 34, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3260,26 +3114,17 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 		switch (header->fsf_status_qual.word[0]) {
+ 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+ 			/* Re-establish link to port */
+-			debug_text_event(adapter->erp_dbf, 1,
+-					 "fsf_sq_ltest");
+ 			zfcp_test_link(unit->port);
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ 			/* ERP strategy will escalate */
+-			debug_text_event(adapter->erp_dbf, 1,
+-					 "fsf_sq_ulp");
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		default:
+ 			ZFCP_LOG_NORMAL
+ 			    ("bug: Wrong status qualifier 0x%x arrived.\n",
+ 			     header->fsf_status_qual.word[0]);
+-			debug_text_event(adapter->erp_dbf, 0,
+-					 "fsf_sq_inval:");
+-			debug_exception(adapter->erp_dbf, 0,
+-					&header->fsf_status_qual.word[0],
+-				sizeof (u32));
+ 		}
+ 		break;
+ 
+@@ -3331,15 +3176,15 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+         		if (exclusive && !readwrite) {
+                 		ZFCP_LOG_NORMAL("exclusive access of read-only "
+ 						"unit not supported\n");
+-				zfcp_erp_unit_failed(unit);
++				zfcp_erp_unit_failed(unit, 35, fsf_req);
+ 				fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+-				zfcp_erp_unit_shutdown(unit, 0);
++				zfcp_erp_unit_shutdown(unit, 0, 80, fsf_req);
+         		} else if (!exclusive && readwrite) {
+                 		ZFCP_LOG_NORMAL("shared access of read-write "
+ 						"unit not supported\n");
+-                		zfcp_erp_unit_failed(unit);
++				zfcp_erp_unit_failed(unit, 36, fsf_req);
+ 				fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+-				zfcp_erp_unit_shutdown(unit, 0);
++				zfcp_erp_unit_shutdown(unit, 0, 81, fsf_req);
+         		}
+ 		}
+ 
+@@ -3350,9 +3195,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ 				"(debug info 0x%x)\n",
+ 				header->fsf_status);
+-		debug_text_event(adapter->erp_dbf, 0, "fsf_s_inval:");
+-		debug_exception(adapter->erp_dbf, 0,
+-				&header->fsf_status, sizeof (u32));
+ 		break;
+ 	}
+ 
+@@ -3465,9 +3307,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ 			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-				 "fsf_s_phand_nv");
+-		zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++		zfcp_erp_adapter_reopen(unit->port->adapter, 0, 110, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3483,9 +3323,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ 			      (char *) &fsf_req->qtcb->header.fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-				 "fsf_s_lhand_nv");
+-		zfcp_erp_port_reopen(unit->port, 0);
++		zfcp_erp_port_reopen(unit->port, 0, 111, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3494,8 +3332,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 			       "needs to be reopened\n",
+ 			       unit->port->wwpn,
+ 			       zfcp_get_busid_by_unit(unit));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
+-		zfcp_erp_port_boxed(unit->port);
++		zfcp_erp_port_boxed(unit->port, 52, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
+ 			ZFCP_STATUS_FSFREQ_RETRY;
+ 		break;
+@@ -3504,27 +3341,17 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 		switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
+ 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+ 			/* re-establish link to port */
+-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ltest");
+ 			zfcp_test_link(unit->port);
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ 			/* ERP strategy will escalate */
+-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ulp");
+ 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			break;
+ 		default:
+ 			ZFCP_LOG_NORMAL
+ 			    ("bug: Wrong status qualifier 0x%x arrived.\n",
+ 			     fsf_req->qtcb->header.fsf_status_qual.word[0]);
+-			debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-					 "fsf_sq_inval:");
+-			debug_exception(
+-				fsf_req->adapter->erp_dbf, 0,
+-				&fsf_req->qtcb->header.fsf_status_qual.word[0],
+-				sizeof (u32));
+ 			break;
+ 		}
+ 		break;
+@@ -3545,10 +3372,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ 				"(debug info 0x%x)\n",
+ 				fsf_req->qtcb->header.fsf_status);
+-		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+-		debug_exception(fsf_req->adapter->erp_dbf, 0,
+-				&fsf_req->qtcb->header.fsf_status,
+-				sizeof (u32));
+ 		break;
+ 	}
+ 
+@@ -3703,7 +3526,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
+ 					zfcp_get_busid_by_unit(unit),
+ 					unit->port->wwpn,
+ 					unit->fcp_lun);
+-			zfcp_erp_unit_shutdown(unit, 0);
++			zfcp_erp_unit_shutdown(unit, 0, 131, fsf_req);
+ 			retval = -EINVAL;
+ 		}
+ 		goto no_fit;
+@@ -3739,8 +3562,8 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
+  send_failed:
+  no_fit:
+  failed_scsi_cmnd:
+- unit_blocked:
+ 	zfcp_unit_put(unit);
++ unit_blocked:
+ 	zfcp_fsf_req_free(fsf_req);
+ 	fsf_req = NULL;
+ 	scsi_cmnd->host_scribble = NULL;
+@@ -3861,9 +3684,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ 			      (char *) &header->fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-				 "fsf_s_phand_nv");
+-		zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++		zfcp_erp_adapter_reopen(unit->port->adapter, 0, 112, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3879,9 +3700,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
+ 			      (char *) &header->fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-				 "fsf_s_uhand_nv");
+-		zfcp_erp_port_reopen(unit->port, 0);
++		zfcp_erp_port_reopen(unit->port, 0, 113, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3897,9 +3716,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
+ 			      (char *) &header->fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-				 "fsf_s_hand_mis");
+-		zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++		zfcp_erp_adapter_reopen(unit->port->adapter, 0, 114, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3909,9 +3726,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 			      zfcp_get_busid_by_unit(unit),
+ 			      ZFCP_FC_SERVICE_CLASS_DEFAULT);
+ 		/* stop operation for this adapter */
+-		debug_text_exception(fsf_req->adapter->erp_dbf, 0,
+-				     "fsf_s_class_nsup");
+-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
++		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 132, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3927,9 +3742,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ 			      (char *) &header->fsf_status_qual,
+ 			      sizeof (union fsf_status_qual));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-				 "fsf_s_fcp_lun_nv");
+-		zfcp_erp_port_reopen(unit->port, 0);
++		zfcp_erp_port_reopen(unit->port, 0, 115, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3951,8 +3764,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 				break;
+ 			}
+ 		}
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+-		zfcp_erp_unit_access_denied(unit);
++		zfcp_erp_unit_access_denied(unit, 61, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3965,9 +3777,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 			      zfcp_get_busid_by_unit(unit),
+ 			      fsf_req->qtcb->bottom.io.data_direction);
+ 		/* stop operation for this adapter */
+-		debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-				 "fsf_s_dir_ind_nv");
+-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
++		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 133, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3980,9 +3790,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 		     zfcp_get_busid_by_unit(unit),
+ 		     fsf_req->qtcb->bottom.io.fcp_cmnd_length);
+ 		/* stop operation for this adapter */
+-		debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-				 "fsf_s_cmd_len_nv");
+-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
++		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 134, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		break;
+ 
+@@ -3990,8 +3798,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 		ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
+ 			       "needs to be reopened\n",
+ 			       unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
+-		zfcp_erp_port_boxed(unit->port);
++		zfcp_erp_port_boxed(unit->port, 53, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
+ 			ZFCP_STATUS_FSFREQ_RETRY;
+ 		break;
+@@ -4001,8 +3808,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 				"wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
+ 				zfcp_get_busid_by_unit(unit),
+ 				unit->port->wwpn, unit->fcp_lun);
+-		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
+-		zfcp_erp_unit_boxed(unit);
++		zfcp_erp_unit_boxed(unit, 54, fsf_req);
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+ 			| ZFCP_STATUS_FSFREQ_RETRY;
+ 		break;
+@@ -4011,25 +3817,16 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 		switch (header->fsf_status_qual.word[0]) {
+ 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+ 			/* re-establish link to port */
+-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ltest");
+  			zfcp_test_link(unit->port);
+ 			break;
+ 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ 			/* FIXME(hw) need proper specs for proper action */
+ 			/* let scsi stack deal with retries and escalation */
+-			debug_text_event(fsf_req->adapter->erp_dbf, 1,
+-					 "fsf_sq_ulp");
+ 			break;
+ 		default:
+ 			ZFCP_LOG_NORMAL
+  			    ("Unknown status qualifier 0x%x arrived.\n",
+ 			     header->fsf_status_qual.word[0]);
+-			debug_text_event(fsf_req->adapter->erp_dbf, 0,
+-					 "fsf_sq_inval:");
+-			debug_exception(fsf_req->adapter->erp_dbf, 0,
+-					&header->fsf_status_qual.word[0],
+-					sizeof(u32));
+ 			break;
+ 		}
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+@@ -4040,12 +3837,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ 
+ 	case FSF_FCP_RSP_AVAILABLE:
+ 		break;
+-
+-	default:
+-		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+-		debug_exception(fsf_req->adapter->erp_dbf, 0,
+-				&header->fsf_status, sizeof(u32));
+-		break;
+ 	}
+ 
+  skip_fsfstatus:
+@@ -4625,9 +4416,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
+ 			"was presented on the adapter %s\n",
+ 			header->fsf_status,
+ 			zfcp_get_busid_by_adapter(adapter));
+-		debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval");
+-		debug_exception(fsf_req->adapter->erp_dbf, 0,
+-			&header->fsf_status_qual.word[0], sizeof(u32));
+ 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 		retval = -EINVAL;
+ 		break;
+@@ -4817,7 +4605,6 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
+ 	volatile struct qdio_buffer_element *sbale;
+ 	int inc_seq_no;
+ 	int new_distance_from_int;
+-	u64 dbg_tmp[2];
+ 	int retval = 0;
+ 
+ 	adapter = fsf_req->adapter;
+@@ -4867,10 +4654,6 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
+ 			 QDIO_FLAG_SYNC_OUTPUT,
+ 			 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL);
+ 
+-	dbg_tmp[0] = (unsigned long) sbale[0].addr;
+-	dbg_tmp[1] = (u64) retval;
+-	debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
+-
+ 	if (unlikely(retval)) {
+ 		/* Queues are down..... */
+ 		retval = -EIO;
+@@ -4885,7 +4668,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
+ 		req_queue->free_index -= fsf_req->sbal_number;
+ 		req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q;
+ 		req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */
+-		zfcp_erp_adapter_reopen(adapter, 0);
++		zfcp_erp_adapter_reopen(adapter, 0, 116, fsf_req);
+ 	} else {
+ 		req_queue->distance_from_int = new_distance_from_int;
+ 		/*
+diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
+index 22fdc17..8ca5f07 100644
+--- a/drivers/s390/scsi/zfcp_qdio.c
++++ b/drivers/s390/scsi/zfcp_qdio.c
+@@ -175,8 +175,9 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
+                 * which is set again in case we have missed by a mile.
+                 */
+ 		zfcp_erp_adapter_reopen(adapter,
+-				       ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
+-				       ZFCP_STATUS_COMMON_ERP_FAILED);
++					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
++					ZFCP_STATUS_COMMON_ERP_FAILED, 140,
++					NULL);
+ 	}
+ 	return retval;
+ }
+@@ -239,8 +240,6 @@ static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
+ 	struct zfcp_fsf_req *fsf_req;
+ 	unsigned long flags;
+ 
+-	debug_long_event(adapter->erp_dbf, 4, req_id);
+-
+ 	spin_lock_irqsave(&adapter->req_list_lock, flags);
+ 	fsf_req = zfcp_reqlist_find(adapter, req_id);
+ 
+diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
+index b9daf5c..f818506 100644
+--- a/drivers/s390/scsi/zfcp_scsi.c
++++ b/drivers/s390/scsi/zfcp_scsi.c
+@@ -31,6 +31,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *,
+ 				  void (*done) (struct scsi_cmnd *));
+ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *);
+ static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *);
++static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *);
+ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
+ static int zfcp_task_management_function(struct zfcp_unit *, u8,
+ 					 struct scsi_cmnd *);
+@@ -51,6 +52,7 @@ struct zfcp_data zfcp_data = {
+ 		.queuecommand		= zfcp_scsi_queuecommand,
+ 		.eh_abort_handler	= zfcp_scsi_eh_abort_handler,
+ 		.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
++		.eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
+ 		.eh_host_reset_handler	= zfcp_scsi_eh_host_reset_handler,
+ 		.can_queue		= 4096,
+ 		.this_id		= -1,
+@@ -179,11 +181,10 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
+ 	struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
+ 
+ 	if (unit) {
+-		zfcp_erp_wait(unit->port->adapter);
+ 		atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
+ 		sdpnt->hostdata = NULL;
+ 		unit->device = NULL;
+-		zfcp_erp_unit_failed(unit);
++		zfcp_erp_unit_failed(unit, 12, NULL);
+ 		zfcp_unit_put(unit);
+ 	} else
+ 		ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at "
+@@ -442,58 +443,32 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+ 	return retval;
+ }
+ 
+-static int
+-zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
++static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
+ {
+ 	int retval;
+-	struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
++	struct zfcp_unit *unit = scpnt->device->hostdata;
+ 
+ 	if (!unit) {
+-		ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
+-		retval = SUCCESS;
+-		goto out;
++		WARN_ON(1);
++		return SUCCESS;
+ 	}
+-	ZFCP_LOG_NORMAL("resetting unit 0x%016Lx on port 0x%016Lx, adapter %s\n",
+-			unit->fcp_lun, unit->port->wwpn,
+-			zfcp_get_busid_by_adapter(unit->port->adapter));
++	retval = zfcp_task_management_function(unit,
++					       FCP_LOGICAL_UNIT_RESET,
++					       scpnt);
++	return retval ? FAILED : SUCCESS;
++}
+ 
+-	/*
+-	 * If we do not know whether the unit supports 'logical unit reset'
+-	 * then try 'logical unit reset' and proceed with 'target reset'
+-	 * if 'logical unit reset' fails.
+-	 * If the unit is known not to support 'logical unit reset' then
+-	 * skip 'logical unit reset' and try 'target reset' immediately.
+-	 */
+-	if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,
+-			      &unit->status)) {
+-		retval = zfcp_task_management_function(unit,
+-						       FCP_LOGICAL_UNIT_RESET,
+-						       scpnt);
+-		if (retval) {
+-			ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit);
+-			if (retval == -ENOTSUPP)
+-				atomic_set_mask
+-				    (ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,
+-				     &unit->status);
+-			/* fall through and try 'target reset' next */
+-		} else {
+-			ZFCP_LOG_DEBUG("unit reset succeeded (unit=%p)\n",
+-				       unit);
+-			/* avoid 'target reset' */
+-			retval = SUCCESS;
+-			goto out;
+-		}
++static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
++{
++	int retval;
++	struct zfcp_unit *unit = scpnt->device->hostdata;
++
++	if (!unit) {
++		WARN_ON(1);
++		return SUCCESS;
+ 	}
+ 	retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt);
+-	if (retval) {
+-		ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit);
+-		retval = FAILED;
+-	} else {
+-		ZFCP_LOG_DEBUG("target reset succeeded (unit=%p)\n", unit);
+-		retval = SUCCESS;
+-	}
+- out:
+-	return retval;
++	return retval ? FAILED : SUCCESS;
+ }
+ 
+ static int
+@@ -553,7 +528,7 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
+ 		unit->fcp_lun, unit->port->wwpn,
+ 		zfcp_get_busid_by_adapter(unit->port->adapter));
+ 
+-	zfcp_erp_adapter_reopen(adapter, 0);
++	zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt);
+ 	zfcp_erp_wait(adapter);
+ 
+ 	return SUCCESS;
+diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
+index 705c6d4..ccbba4d 100644
+--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
++++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
+@@ -89,7 +89,7 @@ zfcp_sysfs_port_add_store(struct device *dev, struct device_attribute *attr, con
+ 
+ 	retval = 0;
+ 
+-	zfcp_erp_port_reopen(port, 0);
++	zfcp_erp_port_reopen(port, 0, 91, NULL);
+ 	zfcp_erp_wait(port->adapter);
+ 	zfcp_port_put(port);
+  out:
+@@ -147,7 +147,7 @@ zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr,
+ 		goto out;
+ 	}
+ 
+-	zfcp_erp_port_shutdown(port, 0);
++	zfcp_erp_port_shutdown(port, 0, 92, NULL);
+ 	zfcp_erp_wait(adapter);
+ 	zfcp_port_put(port);
+ 	zfcp_port_dequeue(port);
+@@ -191,9 +191,10 @@ zfcp_sysfs_adapter_failed_store(struct device *dev, struct device_attribute *att
+ 		goto out;
+ 	}
+ 
+-	zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
+-				       ZFCP_SET);
+-	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++	zfcp_erp_modify_adapter_status(adapter, 44, NULL,
++				       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 93,
++				NULL);
+ 	zfcp_erp_wait(adapter);
+  out:
+ 	up(&zfcp_data.config_sema);
+diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
+index 1320c05..703c1b5 100644
+--- a/drivers/s390/scsi/zfcp_sysfs_port.c
++++ b/drivers/s390/scsi/zfcp_sysfs_port.c
+@@ -94,7 +94,7 @@ zfcp_sysfs_unit_add_store(struct device *dev, struct device_attribute *attr, con
+ 
+ 	retval = 0;
+ 
+-	zfcp_erp_unit_reopen(unit, 0);
++	zfcp_erp_unit_reopen(unit, 0, 94, NULL);
+ 	zfcp_erp_wait(unit->port->adapter);
+ 	zfcp_unit_put(unit);
+  out:
+@@ -150,7 +150,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr,
+ 		goto out;
+ 	}
+ 
+-	zfcp_erp_unit_shutdown(unit, 0);
++	zfcp_erp_unit_shutdown(unit, 0, 95, NULL);
+ 	zfcp_erp_wait(unit->port->adapter);
+ 	zfcp_unit_put(unit);
+ 	zfcp_unit_dequeue(unit);
+@@ -193,8 +193,9 @@ zfcp_sysfs_port_failed_store(struct device *dev, struct device_attribute *attr,
+ 		goto out;
+ 	}
+ 
+-	zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+-	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
++	zfcp_erp_modify_port_status(port, 45, NULL,
++				    ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, 96, NULL);
+ 	zfcp_erp_wait(port->adapter);
+  out:
+ 	up(&zfcp_data.config_sema);
+diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
+index 63f75ee..80fb2c2 100644
+--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
++++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
+@@ -94,8 +94,9 @@ zfcp_sysfs_unit_failed_store(struct device *dev, struct device_attribute *attr,
+ 		goto out;
+ 	}
+ 
+-	zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+-	zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
++	zfcp_erp_modify_unit_status(unit, 46, NULL,
++				    ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++	zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, 97, NULL);
+ 	zfcp_erp_wait(unit->port->adapter);
+  out:
+ 	up(&zfcp_data.config_sema);
+diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
+index 291ff62..c3e4ab0 100644
+--- a/drivers/s390/sysinfo.c
++++ b/drivers/s390/sysinfo.c
+@@ -11,111 +11,13 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <asm/ebcdic.h>
++#include <asm/sysinfo.h>
+ 
+ /* Sigh, math-emu. Don't ask. */
+ #include <asm/sfp-util.h>
+ #include <math-emu/soft-fp.h>
+ #include <math-emu/single.h>
+ 
+-struct sysinfo_1_1_1 {
+-	char reserved_0[32];
+-	char manufacturer[16];
+-	char type[4];
+-	char reserved_1[12];
+-	char model_capacity[16];
+-	char sequence[16];
+-	char plant[4];
+-	char model[16];
+-};
+-
+-struct sysinfo_1_2_1 {
+-	char reserved_0[80];
+-	char sequence[16];
+-	char plant[4];
+-	char reserved_1[2];
+-	unsigned short cpu_address;
+-};
+-
+-struct sysinfo_1_2_2 {
+-	char format;
+-	char reserved_0[1];
+-	unsigned short acc_offset;
+-	char reserved_1[24];
+-	unsigned int secondary_capability;
+-	unsigned int capability;
+-	unsigned short cpus_total;
+-	unsigned short cpus_configured;
+-	unsigned short cpus_standby;
+-	unsigned short cpus_reserved;
+-	unsigned short adjustment[0];
+-};
+-
+-struct sysinfo_1_2_2_extension {
+-	unsigned int alt_capability;
+-	unsigned short alt_adjustment[0];
+-};
+-
+-struct sysinfo_2_2_1 {
+-	char reserved_0[80];
+-	char sequence[16];
+-	char plant[4];
+-	unsigned short cpu_id;
+-	unsigned short cpu_address;
+-};
+-
+-struct sysinfo_2_2_2 {
+-	char reserved_0[32];
+-	unsigned short lpar_number;
+-	char reserved_1;
+-	unsigned char characteristics;
+-	unsigned short cpus_total;
+-	unsigned short cpus_configured;
+-	unsigned short cpus_standby;
+-	unsigned short cpus_reserved;
+-	char name[8];
+-	unsigned int caf;
+-	char reserved_2[16];
+-	unsigned short cpus_dedicated;
+-	unsigned short cpus_shared;
+-};
+-
+-#define LPAR_CHAR_DEDICATED	(1 << 7)
+-#define LPAR_CHAR_SHARED	(1 << 6)
+-#define LPAR_CHAR_LIMITED	(1 << 5)
+-
+-struct sysinfo_3_2_2 {
+-	char reserved_0[31];
+-	unsigned char count;
+-	struct {
+-		char reserved_0[4];
+-		unsigned short cpus_total;
+-		unsigned short cpus_configured;
+-		unsigned short cpus_standby;
+-		unsigned short cpus_reserved;
+-		char name[8];
+-		unsigned int caf;
+-		char cpi[16];
+-		char reserved_1[24];
+-
+-	} vm[8];
+-};
+-
+-static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
+-{
+-	register int r0 asm("0") = (fc << 28) | sel1;
+-	register int r1 asm("1") = sel2;
+-
+-	asm volatile(
+-		"   stsi 0(%2)\n"
+-		"0: jz   2f\n"
+-		"1: lhi  %0,%3\n"
+-		"2:\n"
+-		EX_TABLE(0b,1b)
+-		: "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS)
+-		: "cc", "memory" );
+-	return r0;
+-}
+-
+ static inline int stsi_0(void)
+ {
+ 	int rc = stsi (NULL, 0, 0, 0);
+@@ -133,6 +35,8 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
+ 	EBCASC(info->sequence, sizeof(info->sequence));
+ 	EBCASC(info->plant, sizeof(info->plant));
+ 	EBCASC(info->model_capacity, sizeof(info->model_capacity));
++	EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap));
++	EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap));
+ 	len += sprintf(page + len, "Manufacturer:         %-16.16s\n",
+ 		       info->manufacturer);
+ 	len += sprintf(page + len, "Type:                 %-4.4s\n",
+@@ -155,8 +59,18 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
+ 		       info->sequence);
+ 	len += sprintf(page + len, "Plant:                %-4.4s\n",
+ 		       info->plant);
+-	len += sprintf(page + len, "Model Capacity:       %-16.16s\n",
+-		       info->model_capacity);
++	len += sprintf(page + len, "Model Capacity:       %-16.16s %08u\n",
++		       info->model_capacity, *(u32 *) info->model_cap_rating);
++	if (info->model_perm_cap[0] != '\0')
++		len += sprintf(page + len,
++			       "Model Perm. Capacity: %-16.16s %08u\n",
++			       info->model_perm_cap,
++			       *(u32 *) info->model_perm_cap_rating);
++	if (info->model_temp_cap[0] != '\0')
++		len += sprintf(page + len,
++			       "Model Temp. Capacity: %-16.16s %08u\n",
++			       info->model_temp_cap,
++			       *(u32 *) info->model_temp_cap_rating);
+ 	return len;
+ }
+ 
+diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
+index b4912d1..b31faec 100644
+--- a/drivers/scsi/3w-9xxx.c
++++ b/drivers/scsi/3w-9xxx.c
+@@ -140,9 +140,10 @@ static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
+ /* Functions */
+ 
+ /* Show some statistics about the card */
+-static ssize_t twa_show_stats(struct class_device *class_dev, char *buf)
++static ssize_t twa_show_stats(struct device *dev,
++			      struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(class_dev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+ 	unsigned long flags = 0;
+ 	ssize_t len;
+@@ -184,7 +185,7 @@ static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+ } /* End twa_change_queue_depth() */
+ 
+ /* Create sysfs 'stats' entry */
+-static struct class_device_attribute twa_host_stats_attr = {
++static struct device_attribute twa_host_stats_attr = {
+ 	.attr = {
+ 		.name = 	"stats",
+ 		.mode =		S_IRUGO,
+@@ -193,7 +194,7 @@ static struct class_device_attribute twa_host_stats_attr = {
+ };
+ 
+ /* Host attributes initializer */
+-static struct class_device_attribute *twa_host_attrs[] = {
++static struct device_attribute *twa_host_attrs[] = {
+ 	&twa_host_stats_attr,
+ 	NULL,
+ };
+@@ -1838,12 +1839,11 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
+ 		if (scsi_sg_count(srb)) {
+ 			if ((scsi_sg_count(srb) == 1) &&
+ 			    (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
+-				if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) {
+-					struct scatterlist *sg = scsi_sglist(srb);
+-					char *buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+-					memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
+-					kunmap_atomic(buf - sg->offset, KM_IRQ0);
+-				}
++				if (srb->sc_data_direction == DMA_TO_DEVICE ||
++				    srb->sc_data_direction == DMA_BIDIRECTIONAL)
++					scsi_sg_copy_to_buffer(srb,
++							       tw_dev->generic_buffer_virt[request_id],
++							       TW_SECTOR_SIZE);
+ 				command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
+ 				command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
+ 			} else {
+@@ -1915,13 +1915,11 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
+ 	    (cmd->sc_data_direction == DMA_FROM_DEVICE ||
+ 	     cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
+ 		if (scsi_sg_count(cmd) == 1) {
+-			struct scatterlist *sg = scsi_sglist(tw_dev->srb[request_id]);
+-			char *buf;
+-			unsigned long flags = 0;
++			unsigned long flags;
++			void *buf = tw_dev->generic_buffer_virt[request_id];
++
+ 			local_irq_save(flags);
+-			buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+-			memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
+-			kunmap_atomic(buf - sg->offset, KM_IRQ0);
++			scsi_sg_copy_from_buffer(cmd, buf, TW_SECTOR_SIZE);
+ 			local_irq_restore(flags);
+ 		}
+ 	}
+@@ -2028,8 +2026,6 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
+ 	}
+ 	tw_dev = (TW_Device_Extension *)host->hostdata;
+ 
+-	memset(tw_dev, 0, sizeof(TW_Device_Extension));
+-
+ 	/* Save values to device extension */
+ 	tw_dev->host = host;
+ 	tw_dev->tw_pci_dev = pdev;
+diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
+index d095321..8c22329 100644
+--- a/drivers/scsi/3w-xxxx.c
++++ b/drivers/scsi/3w-xxxx.c
+@@ -484,9 +484,10 @@ static void tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id)
+ } /* End tw_state_request_start() */
+ 
+ /* Show some statistics about the card */
+-static ssize_t tw_show_stats(struct class_device *class_dev, char *buf)
++static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr,
++			     char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(class_dev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+ 	unsigned long flags = 0;
+ 	ssize_t len;
+@@ -528,7 +529,7 @@ static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+ } /* End tw_change_queue_depth() */
+ 
+ /* Create sysfs 'stats' entry */
+-static struct class_device_attribute tw_host_stats_attr = {
++static struct device_attribute tw_host_stats_attr = {
+ 	.attr = {
+ 		.name = 	"stats",
+ 		.mode =		S_IRUGO,
+@@ -537,7 +538,7 @@ static struct class_device_attribute tw_host_stats_attr = {
+ };
+ 
+ /* Host attributes initializer */
+-static struct class_device_attribute *tw_host_attrs[] = {
++static struct device_attribute *tw_host_attrs[] = {
+ 	&tw_host_stats_attr,
+ 	NULL,
+ };
+@@ -1463,18 +1464,10 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
+ 				 void *data, unsigned int len)
+ {
+ 	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+-	void *buf;
+-	unsigned int transfer_len;
+-	unsigned long flags = 0;
+-	struct scatterlist *sg = scsi_sglist(cmd);
++	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+-	buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+-	transfer_len = min(sg->length, len);
+-
+-	memcpy(buf, data, transfer_len);
+-
+-	kunmap_atomic(buf - sg->offset, KM_IRQ0);
++	scsi_sg_copy_from_buffer(cmd, data, len);
+ 	local_irq_restore(flags);
+ }
+ 
+@@ -2294,8 +2287,6 @@ static int __devinit tw_probe(struct pci_dev *pdev, const struct pci_device_id *
+ 	}
+ 	tw_dev = (TW_Device_Extension *)host->hostdata;
+ 
+-	memset(tw_dev, 0, sizeof(TW_Device_Extension));
+-
+ 	/* Save values to device extension */
+ 	tw_dev->host = host;
+ 	tw_dev->tw_pci_dev = pdev;
+diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
+index 4d3ebb1..2d689af 100644
+--- a/drivers/scsi/BusLogic.c
++++ b/drivers/scsi/BusLogic.c
+@@ -896,7 +896,7 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda
+ 		IRQ_Channel = PCI_Device->irq;
+ 		IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
+ 		PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
+-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
++#ifdef CONFIG_SCSI_FLASHPOINT
+ 		if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
+ 			BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0);
+ 			BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+@@ -1006,6 +1006,9 @@ static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter
+ }
+ 
+ 
++#else
++#define BusLogic_InitializeProbeInfoList(adapter) \
++		BusLogic_InitializeProbeInfoListISA(adapter)
+ #endif				/* CONFIG_PCI */
+ 
+ 
+diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
+index bfbfb5c..73f237a 100644
+--- a/drivers/scsi/BusLogic.h
++++ b/drivers/scsi/BusLogic.h
+@@ -34,23 +34,6 @@
+ #endif
+ 
+ /*
+-  FlashPoint support is only available for the Intel x86 Architecture with
+-  CONFIG_PCI set.
+-*/
+-
+-#ifndef __i386__
+-#undef CONFIG_SCSI_OMIT_FLASHPOINT
+-#define CONFIG_SCSI_OMIT_FLASHPOINT
+-#endif
+-
+-#ifndef CONFIG_PCI
+-#undef CONFIG_SCSI_OMIT_FLASHPOINT
+-#define CONFIG_SCSI_OMIT_FLASHPOINT
+-#define BusLogic_InitializeProbeInfoListISA BusLogic_InitializeProbeInfoList
+-#endif
+-
+-
+-/*
+   Define the maximum number of BusLogic Host Adapters supported by this driver.
+ */
+ 
+@@ -178,7 +161,7 @@ static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddres
+   Define macros for testing the Host Adapter Type.
+ */
+ 
+-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
++#ifdef CONFIG_SCSI_FLASHPOINT
+ 
+ #define BusLogic_MultiMasterHostAdapterP(HostAdapter) \
+   (HostAdapter->HostAdapterType == BusLogic_MultiMaster)
+@@ -871,7 +854,7 @@ struct BusLogic_CCB {
+ 	void (*CallbackFunction) (struct BusLogic_CCB *);	/* Bytes 40-43 */
+ 	u32 BaseAddress;	/* Bytes 44-47 */
+ 	enum BusLogic_CompletionCode CompletionCode;	/* Byte 48 */
+-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
++#ifdef CONFIG_SCSI_FLASHPOINT
+ 	unsigned char:8;	/* Byte 49 */
+ 	unsigned short OS_Flags;	/* Bytes 50-51 */
+ 	unsigned char Private[48];	/* Bytes 52-99 */
+diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
+index 1c90781..b374e45 100644
+--- a/drivers/scsi/FlashPoint.c
++++ b/drivers/scsi/FlashPoint.c
+@@ -16,7 +16,7 @@
+ */
+ 
+ 
+-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
++#ifdef CONFIG_SCSI_FLASHPOINT
+ 
+ #define MAX_CARDS	8
+ #undef BUSTYPE_PCI
+@@ -7626,7 +7626,7 @@ FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
+ #define FlashPoint_InterruptPending	    FlashPoint__InterruptPending
+ #define FlashPoint_HandleInterrupt	    FlashPoint__HandleInterrupt
+ 
+-#else				/* CONFIG_SCSI_OMIT_FLASHPOINT */
++#else				/* !CONFIG_SCSI_FLASHPOINT */
+ 
+ /*
+   Define prototypes for the FlashPoint SCCB Manager Functions.
+@@ -7641,4 +7641,4 @@ extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
+ extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
+ extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
+ 
+-#endif				/* CONFIG_SCSI_OMIT_FLASHPOINT */
++#endif				/* CONFIG_SCSI_FLASHPOINT */
+diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
+index b9d3740..7f78e3e 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -588,18 +588,20 @@ config SCSI_BUSLOGIC
+ 	  <http://www.tldp.org/docs.html#howto>, and the files
+ 	  <file:Documentation/scsi/BusLogic.txt> and
+ 	  <file:Documentation/scsi/FlashPoint.txt> for more information.
++	  Note that support for FlashPoint is only available for 32-bit
++	  x86 configurations.
+ 
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called BusLogic.
+ 
+-config SCSI_OMIT_FLASHPOINT
+-	bool "Omit FlashPoint support"
+-	depends on SCSI_BUSLOGIC
++config SCSI_FLASHPOINT
++	bool "FlashPoint support"
++	depends on SCSI_BUSLOGIC && PCI && X86_32
+ 	help
+-	  This option allows you to omit the FlashPoint support from the
++	  This option allows you to add FlashPoint support to the
+ 	  BusLogic SCSI driver. The FlashPoint SCCB Manager code is
+-	  substantial, so users of MultiMaster Host Adapters may wish to omit
+-	  it.
++	  substantial, so users of MultiMaster Host Adapters may not
++	  wish to include it.
+ 
+ config SCSI_DMX3191D
+ 	tristate "DMX3191D SCSI support"
+diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
+index 5ac3a3e..07d572f 100644
+--- a/drivers/scsi/a2091.c
++++ b/drivers/scsi/a2091.c
+@@ -179,6 +179,9 @@ int __init a2091_detect(struct scsi_host_template *tpnt)
+ 	DMA(instance)->DAWR = DAWR_A2091;
+ 	regs.SASR = &(DMA(instance)->SASR);
+ 	regs.SCMD = &(DMA(instance)->SCMD);
++	HDATA(instance)->no_sync = 0xff;
++	HDATA(instance)->fast = 0;
++	HDATA(instance)->dma_mode = CTRL_DMA;
+ 	wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
+ 	request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, "A2091 SCSI",
+ 		    instance);
+diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
+index 3aeec96..8b449d8 100644
+--- a/drivers/scsi/a3000.c
++++ b/drivers/scsi/a3000.c
+@@ -178,6 +178,9 @@ int __init a3000_detect(struct scsi_host_template *tpnt)
+     DMA(a3000_host)->DAWR = DAWR_A3000;
+     regs.SASR = &(DMA(a3000_host)->SASR);
+     regs.SCMD = &(DMA(a3000_host)->SCMD);
++    HDATA(a3000_host)->no_sync = 0xff;
++    HDATA(a3000_host)->fast = 0;
++    HDATA(a3000_host)->dma_mode = CTRL_DMA;
+     wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15);
+     if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI",
+ 		    a3000_intr))
+diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
+index c05092f..460d402 100644
+--- a/drivers/scsi/aacraid/aachba.c
++++ b/drivers/scsi/aacraid/aachba.c
+@@ -31,7 +31,6 @@
+ #include <linux/slab.h>
+ #include <linux/completion.h>
+ #include <linux/blkdev.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <linux/highmem.h> /* For flush_kernel_dcache_page */
+ 
+@@ -205,7 +204,7 @@ MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health"
+ 
+ int aac_check_reset = 1;
+ module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
+-MODULE_PARM_DESC(aac_check_reset, "If adapter fails health check, reset the"
++MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the"
+ 	" adapter. a value of -1 forces the reset to adapters programmed to"
+ 	" ignore it.");
+ 
+@@ -379,24 +378,6 @@ int aac_get_containers(struct aac_dev *dev)
+ 	return status;
+ }
+ 
+-static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
+-{
+-	void *buf;
+-	int transfer_len;
+-	struct scatterlist *sg = scsi_sglist(scsicmd);
+-
+-	buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+-	transfer_len = min(sg->length, len + offset);
+-
+-	transfer_len -= offset;
+-	if (buf && transfer_len > 0)
+-		memcpy(buf + offset, data, transfer_len);
+-
+-	flush_kernel_dcache_page(kmap_atomic_to_page(buf - sg->offset));
+-	kunmap_atomic(buf - sg->offset, KM_IRQ0);
+-
+-}
+-
+ static void get_container_name_callback(void *context, struct fib * fibptr)
+ {
+ 	struct aac_get_name_resp * get_name_reply;
+@@ -419,14 +400,17 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
+ 		while (*sp == ' ')
+ 			++sp;
+ 		if (*sp) {
++			struct inquiry_data inq;
+ 			char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
+ 			int count = sizeof(d);
+ 			char *dp = d;
+ 			do {
+ 				*dp++ = (*sp) ? *sp++ : ' ';
+ 			} while (--count > 0);
+-			aac_internal_transfer(scsicmd, d,
+-			  offsetof(struct inquiry_data, inqd_pid), sizeof(d));
++
++			scsi_sg_copy_to_buffer(scsicmd, &inq, sizeof(inq));
++			memcpy(inq.inqd_pid, d, sizeof(d));
++			scsi_sg_copy_from_buffer(scsicmd, &inq, sizeof(inq));
+ 		}
+ 	}
+ 
+@@ -811,7 +795,7 @@ static void get_container_serial_callback(void *context, struct fib * fibptr)
+ 		sp[2] = 0;
+ 		sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
+ 		  le32_to_cpu(get_serial_reply->uid));
+-		aac_internal_transfer(scsicmd, sp, 0, sizeof(sp));
++		scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp));
+ 	}
+ 
+ 	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+@@ -1331,7 +1315,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
+ 			tmp>>24,(tmp>>16)&0xff,tmp&0xff,
+ 			le32_to_cpu(dev->adapter_info.biosbuild));
+ 		buffer[0] = '\0';
+-		if (aac_show_serial_number(
++		if (aac_get_serial_number(
+ 		  shost_to_class(dev->scsi_host_ptr), buffer))
+ 			printk(KERN_INFO "%s%d: serial %s",
+ 			  dev->name, dev->id, buffer);
+@@ -1986,8 +1970,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ 				arr[4] = 0x0;
+ 				arr[5] = 0x80;
+ 				arr[1] = scsicmd->cmnd[2];
+-				aac_internal_transfer(scsicmd, &inq_data, 0,
+-				  sizeof(inq_data));
++				scsi_sg_copy_from_buffer(scsicmd, &inq_data,
++							 sizeof(inq_data));
+ 				scsicmd->result = DID_OK << 16 |
+ 				  COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ 			} else if (scsicmd->cmnd[2] == 0x80) {
+@@ -1995,8 +1979,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ 				arr[3] = setinqserial(dev, &arr[4],
+ 				  scmd_id(scsicmd));
+ 				arr[1] = scsicmd->cmnd[2];
+-				aac_internal_transfer(scsicmd, &inq_data, 0,
+-				  sizeof(inq_data));
++				scsi_sg_copy_from_buffer(scsicmd, &inq_data,
++							 sizeof(inq_data));
+ 				return aac_get_container_serial(scsicmd);
+ 			} else {
+ 				/* vpd page not implemented */
+@@ -2027,7 +2011,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ 		if (cid == host->this_id) {
+ 			setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
+ 			inq_data.inqd_pdt = INQD_PDT_PROC;	/* Processor device */
+-			aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
++			scsi_sg_copy_from_buffer(scsicmd, &inq_data,
++						 sizeof(inq_data));
+ 			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ 			scsicmd->scsi_done(scsicmd);
+ 			return 0;
+@@ -2036,7 +2021,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ 			return -1;
+ 		setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
+ 		inq_data.inqd_pdt = INQD_PDT_DA;	/* Direct/random access device */
+-		aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
++		scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
+ 		return aac_get_container_name(scsicmd);
+ 	}
+ 	case SERVICE_ACTION_IN:
+@@ -2047,6 +2032,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ 	{
+ 		u64 capacity;
+ 		char cp[13];
++		unsigned int alloc_len;
+ 
+ 		dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));
+ 		capacity = fsa_dev_ptr[cid].size - 1;
+@@ -2063,18 +2049,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ 		cp[10] = 2;
+ 		cp[11] = 0;
+ 		cp[12] = 0;
+-		aac_internal_transfer(scsicmd, cp, 0,
+-		  min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
+-		if (sizeof(cp) < scsicmd->cmnd[13]) {
+-			unsigned int len, offset = sizeof(cp);
+ 
+-			memset(cp, 0, offset);
+-			do {
+-				len = min_t(size_t, scsicmd->cmnd[13] - offset,
+-						sizeof(cp));
+-				aac_internal_transfer(scsicmd, cp, offset, len);
+-			} while ((offset += len) < scsicmd->cmnd[13]);
+-		}
++		alloc_len = ((scsicmd->cmnd[10] << 24)
++			     + (scsicmd->cmnd[11] << 16)
++			     + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]);
++
++		alloc_len = min_t(size_t, alloc_len, sizeof(cp));
++		scsi_sg_copy_from_buffer(scsicmd, cp, alloc_len);
++		if (alloc_len < scsi_bufflen(scsicmd))
++			scsi_set_resid(scsicmd,
++				       scsi_bufflen(scsicmd) - alloc_len);
+ 
+ 		/* Do not cache partition table for arrays */
+ 		scsicmd->device->removable = 1;
+@@ -2104,7 +2088,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ 		cp[5] = 0;
+ 		cp[6] = 2;
+ 		cp[7] = 0;
+-		aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
++		scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp));
+ 		/* Do not cache partition table for arrays */
+ 		scsicmd->device->removable = 1;
+ 
+@@ -2139,7 +2123,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ 			if (mode_buf_length > scsicmd->cmnd[4])
+ 				mode_buf_length = scsicmd->cmnd[4];
+ 		}
+-		aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
++		scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
+ 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ 		scsicmd->scsi_done(scsicmd);
+ 
+@@ -2174,7 +2158,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ 			if (mode_buf_length > scsicmd->cmnd[8])
+ 				mode_buf_length = scsicmd->cmnd[8];
+ 		}
+-		aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
++		scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
+ 
+ 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ 		scsicmd->scsi_done(scsicmd);
+diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
+index ace0b75..113ca9c 100644
+--- a/drivers/scsi/aacraid/aacraid.h
++++ b/drivers/scsi/aacraid/aacraid.h
+@@ -1850,9 +1850,9 @@ int aac_get_containers(struct aac_dev *dev);
+ int aac_scsi_cmd(struct scsi_cmnd *cmd);
+ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg);
+ #ifndef shost_to_class
+-#define shost_to_class(shost) &shost->shost_classdev
++#define shost_to_class(shost) &shost->shost_dev
+ #endif
+-ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf);
++ssize_t aac_get_serial_number(struct device *dev, char *buf);
+ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg);
+ int aac_rx_init(struct aac_dev *dev);
+ int aac_rkt_init(struct aac_dev *dev);
+diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
+index abef051..5fd83de 100644
+--- a/drivers/scsi/aacraid/commctrl.c
++++ b/drivers/scsi/aacraid/commctrl.c
+@@ -39,7 +39,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/delay.h> /* ssleep prototype */
+ #include <linux/kthread.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include "aacraid.h"
+diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
+index 89cc8b7..294a802 100644
+--- a/drivers/scsi/aacraid/comminit.c
++++ b/drivers/scsi/aacraid/comminit.c
+@@ -39,7 +39,6 @@
+ #include <linux/completion.h>
+ #include <linux/mm.h>
+ #include <scsi/scsi_host.h>
+-#include <asm/semaphore.h>
+ 
+ #include "aacraid.h"
+ 
+diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
+index 4743449..ef67816 100644
+--- a/drivers/scsi/aacraid/commsup.c
++++ b/drivers/scsi/aacraid/commsup.c
+@@ -41,11 +41,11 @@
+ #include <linux/delay.h>
+ #include <linux/kthread.h>
+ #include <linux/interrupt.h>
++#include <linux/semaphore.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_cmnd.h>
+-#include <asm/semaphore.h>
+ 
+ #include "aacraid.h"
+ 
+@@ -515,10 +515,12 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
+ 				}
+ 				udelay(5);
+ 			}
+-		} else
+-			(void)down_interruptible(&fibptr->event_wait);
++		} else if (down_interruptible(&fibptr->event_wait) == 0) {
++			fibptr->done = 2;
++			up(&fibptr->event_wait);
++		}
+ 		spin_lock_irqsave(&fibptr->event_lock, flags);
+-		if (fibptr->done == 0) {
++		if ((fibptr->done == 0) || (fibptr->done == 2)) {
+ 			fibptr->done = 2; /* Tell interrupt we aborted */
+ 			spin_unlock_irqrestore(&fibptr->event_lock, flags);
+ 			return -EINTR;
+@@ -594,7 +596,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
+ 	if (le32_to_cpu(*q->headers.consumer) >= q->entries)
+ 		*q->headers.consumer = cpu_to_le32(1);
+ 	else
+-		*q->headers.consumer = cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1);
++		le32_add_cpu(q->headers.consumer, 1);
+ 
+ 	if (wasfull) {
+ 		switch (qid) {
+diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
+index d1163de..933f208 100644
+--- a/drivers/scsi/aacraid/dpcsup.c
++++ b/drivers/scsi/aacraid/dpcsup.c
+@@ -36,7 +36,7 @@
+ #include <linux/slab.h>
+ #include <linux/completion.h>
+ #include <linux/blkdev.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ 
+ #include "aacraid.h"
+ 
+diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
+index ae5f74f..c109f63 100644
+--- a/drivers/scsi/aacraid/linit.c
++++ b/drivers/scsi/aacraid/linit.c
+@@ -42,7 +42,6 @@
+ #include <linux/syscalls.h>
+ #include <linux/delay.h>
+ #include <linux/kthread.h>
+-#include <asm/semaphore.h>
+ 
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+@@ -755,10 +754,10 @@ static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long
+ }
+ #endif
+ 
+-static ssize_t aac_show_model(struct class_device *class_dev,
+-		char *buf)
++static ssize_t aac_show_model(struct device *device,
++			      struct device_attribute *attr, char *buf)
+ {
+-	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ 	int len;
+ 
+ 	if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+@@ -774,10 +773,10 @@ static ssize_t aac_show_model(struct class_device *class_dev,
+ 	return len;
+ }
+ 
+-static ssize_t aac_show_vendor(struct class_device *class_dev,
+-		char *buf)
++static ssize_t aac_show_vendor(struct device *device,
++			       struct device_attribute *attr, char *buf)
+ {
+-	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ 	int len;
+ 
+ 	if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+@@ -793,10 +792,11 @@ static ssize_t aac_show_vendor(struct class_device *class_dev,
+ 	return len;
+ }
+ 
+-static ssize_t aac_show_flags(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_flags(struct device *cdev,
++			      struct device_attribute *attr, char *buf)
+ {
+ 	int len = 0;
+-	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++	struct aac_dev *dev = (struct aac_dev*)class_to_shost(cdev)->hostdata;
+ 
+ 	if (nblank(dprintk(x)))
+ 		len = snprintf(buf, PAGE_SIZE, "dprintk\n");
+@@ -812,10 +812,11 @@ static ssize_t aac_show_flags(struct class_device *class_dev, char *buf)
+ 	return len;
+ }
+ 
+-static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+-		char *buf)
++static ssize_t aac_show_kernel_version(struct device *device,
++				       struct device_attribute *attr,
++				       char *buf)
+ {
+-	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ 	int len, tmp;
+ 
+ 	tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+@@ -825,10 +826,11 @@ static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+ 	return len;
+ }
+ 
+-static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+-		char *buf)
++static ssize_t aac_show_monitor_version(struct device *device,
++					struct device_attribute *attr,
++					char *buf)
+ {
+-	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ 	int len, tmp;
+ 
+ 	tmp = le32_to_cpu(dev->adapter_info.monitorrev);
+@@ -838,10 +840,11 @@ static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+ 	return len;
+ }
+ 
+-static ssize_t aac_show_bios_version(struct class_device *class_dev,
+-		char *buf)
++static ssize_t aac_show_bios_version(struct device *device,
++				     struct device_attribute *attr,
++				     char *buf)
+ {
+-	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ 	int len, tmp;
+ 
+ 	tmp = le32_to_cpu(dev->adapter_info.biosrev);
+@@ -851,9 +854,10 @@ static ssize_t aac_show_bios_version(struct class_device *class_dev,
+ 	return len;
+ }
+ 
+-ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
++ssize_t aac_show_serial_number(struct device *device,
++			       struct device_attribute *attr, char *buf)
+ {
+-	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ 	int len = 0;
+ 
+ 	if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+@@ -869,35 +873,39 @@ ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
+ 	return len;
+ }
+ 
+-static ssize_t aac_show_max_channel(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_max_channel(struct device *device,
++				    struct device_attribute *attr, char *buf)
+ {
+ 	return snprintf(buf, PAGE_SIZE, "%d\n",
+-	  class_to_shost(class_dev)->max_channel);
++	  class_to_shost(device)->max_channel);
+ }
+ 
+-static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_max_id(struct device *device,
++			       struct device_attribute *attr, char *buf)
+ {
+ 	return snprintf(buf, PAGE_SIZE, "%d\n",
+-	  class_to_shost(class_dev)->max_id);
++	  class_to_shost(device)->max_id);
+ }
+ 
+-static ssize_t aac_store_reset_adapter(struct class_device *class_dev,
+-		const char *buf, size_t count)
++static ssize_t aac_store_reset_adapter(struct device *device,
++				       struct device_attribute *attr,
++				       const char *buf, size_t count)
+ {
+ 	int retval = -EACCES;
+ 
+ 	if (!capable(CAP_SYS_ADMIN))
+ 		return retval;
+-	retval = aac_reset_adapter((struct aac_dev*)class_to_shost(class_dev)->hostdata, buf[0] == '!');
++	retval = aac_reset_adapter((struct aac_dev*)class_to_shost(device)->hostdata, buf[0] == '!');
+ 	if (retval >= 0)
+ 		retval = count;
+ 	return retval;
+ }
+ 
+-static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
+-		char *buf)
++static ssize_t aac_show_reset_adapter(struct device *device,
++				      struct device_attribute *attr,
++				      char *buf)
+ {
+-	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++	struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ 	int len, tmp;
+ 
+ 	tmp = aac_adapter_check_health(dev);
+@@ -907,70 +915,70 @@ static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
+ 	return len;
+ }
+ 
+-static struct class_device_attribute aac_model = {
++static struct device_attribute aac_model = {
+ 	.attr = {
+ 		.name = "model",
+ 		.mode = S_IRUGO,
+ 	},
+ 	.show = aac_show_model,
+ };
+-static struct class_device_attribute aac_vendor = {
++static struct device_attribute aac_vendor = {
+ 	.attr = {
+ 		.name = "vendor",
+ 		.mode = S_IRUGO,
+ 	},
+ 	.show = aac_show_vendor,
+ };
+-static struct class_device_attribute aac_flags = {
++static struct device_attribute aac_flags = {
+ 	.attr = {
+ 		.name = "flags",
+ 		.mode = S_IRUGO,
+ 	},
+ 	.show = aac_show_flags,
+ };
+-static struct class_device_attribute aac_kernel_version = {
++static struct device_attribute aac_kernel_version = {
+ 	.attr = {
+ 		.name = "hba_kernel_version",
+ 		.mode = S_IRUGO,
+ 	},
+ 	.show = aac_show_kernel_version,
+ };
+-static struct class_device_attribute aac_monitor_version = {
++static struct device_attribute aac_monitor_version = {
+ 	.attr = {
+ 		.name = "hba_monitor_version",
+ 		.mode = S_IRUGO,
+ 	},
+ 	.show = aac_show_monitor_version,
+ };
+-static struct class_device_attribute aac_bios_version = {
++static struct device_attribute aac_bios_version = {
+ 	.attr = {
+ 		.name = "hba_bios_version",
+ 		.mode = S_IRUGO,
+ 	},
+ 	.show = aac_show_bios_version,
+ };
+-static struct class_device_attribute aac_serial_number = {
++static struct device_attribute aac_serial_number = {
+ 	.attr = {
+ 		.name = "serial_number",
+ 		.mode = S_IRUGO,
+ 	},
+ 	.show = aac_show_serial_number,
+ };
+-static struct class_device_attribute aac_max_channel = {
++static struct device_attribute aac_max_channel = {
+ 	.attr = {
+ 		.name = "max_channel",
+ 		.mode = S_IRUGO,
+ 	},
+ 	.show = aac_show_max_channel,
+ };
+-static struct class_device_attribute aac_max_id = {
++static struct device_attribute aac_max_id = {
+ 	.attr = {
+ 		.name = "max_id",
+ 		.mode = S_IRUGO,
+ 	},
+ 	.show = aac_show_max_id,
+ };
+-static struct class_device_attribute aac_reset = {
++static struct device_attribute aac_reset = {
+ 	.attr = {
+ 		.name = "reset_host",
+ 		.mode = S_IWUSR|S_IRUGO,
+@@ -979,7 +987,7 @@ static struct class_device_attribute aac_reset = {
+ 	.show = aac_show_reset_adapter,
+ };
+ 
+-static struct class_device_attribute *aac_attrs[] = {
++static struct device_attribute *aac_attrs[] = {
+ 	&aac_model,
+ 	&aac_vendor,
+ 	&aac_flags,
+@@ -993,6 +1001,10 @@ static struct class_device_attribute *aac_attrs[] = {
+ 	NULL
+ };
+ 
++ssize_t aac_get_serial_number(struct device *device, char *buf)
++{
++	return aac_show_serial_number(device, &aac_serial_number, buf);
++}
+ 
+ static const struct file_operations aac_cfg_fops = {
+ 	.owner		= THIS_MODULE,
+diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
+index 1f18b83..073208b 100644
+--- a/drivers/scsi/aacraid/rx.c
++++ b/drivers/scsi/aacraid/rx.c
+@@ -39,7 +39,6 @@
+ #include <linux/completion.h>
+ #include <linux/time.h>
+ #include <linux/interrupt.h>
+-#include <asm/semaphore.h>
+ 
+ #include <scsi/scsi_host.h>
+ 
+diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
+index cfc3410..fc1a557 100644
+--- a/drivers/scsi/aacraid/sa.c
++++ b/drivers/scsi/aacraid/sa.c
+@@ -39,7 +39,6 @@
+ #include <linux/completion.h>
+ #include <linux/time.h>
+ #include <linux/interrupt.h>
+-#include <asm/semaphore.h>
+ 
+ #include <scsi/scsi_host.h>
+ 
+diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
+index 72fccd9..0081aa3 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
++++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
+@@ -1413,6 +1413,10 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
+ 	unsigned long flags;
+ 	int nseg;
+ 
++	nseg = scsi_dma_map(cmd);
++	if (nseg < 0)
++		return SCSI_MLQUEUE_HOST_BUSY;
++
+ 	ahd_lock(ahd, &flags);
+ 
+ 	/*
+@@ -1430,6 +1434,7 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
+ 	if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
+ 		ahd->flags |= AHD_RESOURCE_SHORTAGE;
+ 		ahd_unlock(ahd, &flags);
++		scsi_dma_unmap(cmd);
+ 		return SCSI_MLQUEUE_HOST_BUSY;
+ 	}
+ 
+@@ -1485,8 +1490,6 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
+ 	ahd_set_sense_residual(scb, 0);
+ 	scb->sg_count = 0;
+ 
+-	nseg = scsi_dma_map(cmd);
+-	BUG_ON(nseg < 0);
+ 	if (nseg > 0) {
+ 		void *sg = scb->sg_list;
+ 		struct scatterlist *cur_seg;
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
+index 282aff6..42ad48e 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
++++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
+@@ -1398,12 +1398,18 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
+ 			return SCSI_MLQUEUE_DEVICE_BUSY;
+ 	}
+ 
++	nseg = scsi_dma_map(cmd);
++	if (nseg < 0)
++		return SCSI_MLQUEUE_HOST_BUSY;
++
+ 	/*
+ 	 * Get an scb to use.
+ 	 */
+ 	scb = ahc_get_scb(ahc);
+-	if (!scb)
++	if (!scb) {
++		scsi_dma_unmap(cmd);
+ 		return SCSI_MLQUEUE_HOST_BUSY;
++	}
+ 
+ 	scb->io_ctx = cmd;
+ 	scb->platform_data->dev = dev;
+@@ -1464,8 +1470,6 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
+ 	ahc_set_sense_residual(scb, 0);
+ 	scb->sg_count = 0;
+ 
+-	nseg = scsi_dma_map(cmd);
+-	BUG_ON(nseg < 0);
+ 	if (nseg > 0) {
+ 		struct	ahc_dma_seg *sg;
+ 		struct	scatterlist *cur_seg;
+diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+index 6066998..702e2db 100644
+--- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
++++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+@@ -1837,7 +1837,7 @@ type_check(symbol_t *symbol, expression_t *expression, int opcode)
+ 	int and_op;
+ 
+ 	and_op = FALSE;
+-	if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ)
++	if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || opcode == AIC_OP_JZ)
+ 		and_op = TRUE;
+ 
+ 	/*
+diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h
+index eb8efdc..2ef459e 100644
+--- a/drivers/scsi/aic94xx/aic94xx.h
++++ b/drivers/scsi/aic94xx/aic94xx.h
+@@ -58,7 +58,6 @@
+ 
+ extern struct kmem_cache *asd_dma_token_cache;
+ extern struct kmem_cache *asd_ascb_cache;
+-extern char sas_addr_str[2*SAS_ADDR_SIZE + 1];
+ 
+ static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
+ {
+@@ -68,21 +67,6 @@ static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
+ 	*p = '\0';
+ }
+ 
+-static inline void asd_destringify_sas_addr(u8 *sas_addr, const char *p)
+-{
+-	int i;
+-	for (i = 0; i < SAS_ADDR_SIZE; i++) {
+-		u8 h, l;
+-		if (!*p)
+-			break;
+-		h = isdigit(*p) ? *p-'0' : *p-'A'+10;
+-		p++;
+-		l = isdigit(*p) ? *p-'0' : *p-'A'+10;
+-		p++;
+-		sas_addr[i] = (h<<4) | l;
+-	}
+-}
+-
+ struct asd_ha_struct;
+ struct asd_ascb;
+ 
+diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c
+index 72042ca..2e2ddec 100644
+--- a/drivers/scsi/aic94xx/aic94xx_dev.c
++++ b/drivers/scsi/aic94xx/aic94xx_dev.c
+@@ -35,7 +35,7 @@
+ #define SET_DDB(_ddb, _ha) set_bit(_ddb, (_ha)->hw_prof.ddb_bitmap)
+ #define CLEAR_DDB(_ddb, _ha) clear_bit(_ddb, (_ha)->hw_prof.ddb_bitmap)
+ 
+-static inline int asd_get_ddb(struct asd_ha_struct *asd_ha)
++static int asd_get_ddb(struct asd_ha_struct *asd_ha)
+ {
+ 	int ddb, i;
+ 
+@@ -71,7 +71,7 @@ out:
+ #define NCQ_DATA_SCB_PTR offsetof(struct asd_ddb_stp_sata_target_port, ncq_data_scb_ptr)
+ #define ITNL_TIMEOUT    offsetof(struct asd_ddb_ssp_smp_target_port, itnl_timeout)
+ 
+-static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
++static void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
+ {
+ 	if (!ddb || ddb >= 0xFFFF)
+ 		return;
+@@ -79,7 +79,7 @@ static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
+ 	CLEAR_DDB(ddb, asd_ha);
+ }
+ 
+-static inline void asd_set_ddb_type(struct domain_device *dev)
++static void asd_set_ddb_type(struct domain_device *dev)
+ {
+ 	struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
+ 	int ddb = (int) (unsigned long) dev->lldd_dev;
+@@ -109,7 +109,7 @@ static int asd_init_sata_tag_ddb(struct domain_device *dev)
+ 	return 0;
+ }
+ 
+-static inline int asd_init_sata(struct domain_device *dev)
++static int asd_init_sata(struct domain_device *dev)
+ {
+ 	struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
+ 	int ddb = (int) (unsigned long) dev->lldd_dev;
+diff --git a/drivers/scsi/aic94xx/aic94xx_dump.c b/drivers/scsi/aic94xx/aic94xx_dump.c
+index 3d8c4ff..67eeba3 100644
+--- a/drivers/scsi/aic94xx/aic94xx_dump.c
++++ b/drivers/scsi/aic94xx/aic94xx_dump.c
+@@ -738,6 +738,8 @@ static void asd_dump_lseq_state(struct asd_ha_struct *asd_ha, int lseq)
+ 	PRINT_LMIP_dword(asd_ha, lseq, DEV_PRES_TIMER_TERM_TS);
+ }
+ 
++#if 0
++
+ /**
+  * asd_dump_ddb_site -- dump a CSEQ DDB site
+  * @asd_ha: pointer to host adapter structure
+@@ -880,6 +882,8 @@ void asd_dump_scb_sites(struct asd_ha_struct *asd_ha)
+ 	}
+ }
+ 
++#endif  /*  0  */
++
+ /**
+  * ads_dump_seq_state -- dump CSEQ and LSEQ states
+  * @asd_ha: pointer to host adapter structure
+@@ -922,7 +926,9 @@ void asd_dump_frame_rcvd(struct asd_phy *phy,
+ 	spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
+ }
+ 
+-static inline void asd_dump_scb(struct asd_ascb *ascb, int ind)
++#if 0
++
++static void asd_dump_scb(struct asd_ascb *ascb, int ind)
+ {
+ 	asd_printk("scb%d: vaddr: 0x%p, dma_handle: 0x%llx, next: 0x%llx, "
+ 		   "index:%d, opcode:0x%02x\n",
+@@ -956,4 +962,6 @@ void asd_dump_scb_list(struct asd_ascb *ascb, int num)
+ 	}
+ }
+ 
++#endif  /*  0  */
++
+ #endif /* ASD_DEBUG */
+diff --git a/drivers/scsi/aic94xx/aic94xx_dump.h b/drivers/scsi/aic94xx/aic94xx_dump.h
+index 0c388e7..191a753 100644
+--- a/drivers/scsi/aic94xx/aic94xx_dump.h
++++ b/drivers/scsi/aic94xx/aic94xx_dump.h
+@@ -29,24 +29,15 @@
+ 
+ #ifdef ASD_DEBUG
+ 
+-void asd_dump_ddb_0(struct asd_ha_struct *asd_ha);
+-void asd_dump_target_ddb(struct asd_ha_struct *asd_ha, u16 site_no);
+-void asd_dump_scb_sites(struct asd_ha_struct *asd_ha);
+ void asd_dump_seq_state(struct asd_ha_struct *asd_ha, u8 lseq_mask);
+ void asd_dump_frame_rcvd(struct asd_phy *phy,
+ 			 struct done_list_struct *dl);
+-void asd_dump_scb_list(struct asd_ascb *ascb, int num);
+ #else /* ASD_DEBUG */
+ 
+-static inline void asd_dump_ddb_0(struct asd_ha_struct *asd_ha) { }
+-static inline void asd_dump_target_ddb(struct asd_ha_struct *asd_ha,
+-				     u16 site_no) { }
+-static inline void asd_dump_scb_sites(struct asd_ha_struct *asd_ha) { }
+ static inline void asd_dump_seq_state(struct asd_ha_struct *asd_ha,
+ 				      u8 lseq_mask) { }
+ static inline void asd_dump_frame_rcvd(struct asd_phy *phy,
+ 				       struct done_list_struct *dl) { }
+-static inline void asd_dump_scb_list(struct asd_ascb *ascb, int num) { }
+ #endif /* ASD_DEBUG */
+ 
+ #endif /* _AIC94XX_DUMP_H_ */
+diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
+index 098b5f3..83a7822 100644
+--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
++++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
+@@ -27,6 +27,7 @@
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/module.h>
++#include <linux/firmware.h>
+ 
+ #include "aic94xx.h"
+ #include "aic94xx_reg.h"
+@@ -38,16 +39,14 @@ u32 MBAR0_SWB_SIZE;
+ 
+ /* ---------- Initialization ---------- */
+ 
+-static void asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
++static int asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
+ {
+-	extern char sas_addr_str[];
+-	/* If the user has specified a WWN it overrides other settings
+-	 */
+-	if (sas_addr_str[0] != '\0')
+-		asd_destringify_sas_addr(asd_ha->hw_prof.sas_addr,
+-					 sas_addr_str);
+-	else if (asd_ha->hw_prof.sas_addr[0] != 0)
+-		asd_stringify_sas_addr(sas_addr_str, asd_ha->hw_prof.sas_addr);
++	/* adapter came with a sas address */
++	if (asd_ha->hw_prof.sas_addr[0])
++		return 0;
++
++	return sas_request_addr(asd_ha->sas_ha.core.shost,
++				asd_ha->hw_prof.sas_addr);
+ }
+ 
+ static void asd_propagate_sas_addr(struct asd_ha_struct *asd_ha)
+@@ -251,7 +250,7 @@ static int asd_init_scbs(struct asd_ha_struct *asd_ha)
+ 	return 0;
+ }
+ 
+-static inline void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha)
++static void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha)
+ {
+ 	asd_ha->hw_prof.max_scbs = asd_get_cmdctx_size(asd_ha)/ASD_SCB_SIZE;
+ 	asd_ha->hw_prof.max_ddbs = asd_get_devctx_size(asd_ha)/ASD_DDB_SIZE;
+@@ -657,8 +656,7 @@ int asd_init_hw(struct asd_ha_struct *asd_ha)
+ 
+ 	asd_init_ctxmem(asd_ha);
+ 
+-	asd_get_user_sas_addr(asd_ha);
+-	if (!asd_ha->hw_prof.sas_addr[0]) {
++	if (asd_get_user_sas_addr(asd_ha)) {
+ 		asd_printk("No SAS Address provided for %s\n",
+ 			   pci_name(asd_ha->pcidev));
+ 		err = -ENODEV;
+@@ -773,7 +771,7 @@ static void asd_dl_tasklet_handler(unsigned long data)
+  * asd_process_donelist_isr -- schedule processing of done list entries
+  * @asd_ha: pointer to host adapter structure
+  */
+-static inline void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
++static void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
+ {
+ 	tasklet_schedule(&asd_ha->seq.dl_tasklet);
+ }
+@@ -782,7 +780,7 @@ static inline void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
+  * asd_com_sas_isr -- process device communication interrupt (COMINT)
+  * @asd_ha: pointer to host adapter structure
+  */
+-static inline void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
++static void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
+ {
+ 	u32 comstat = asd_read_reg_dword(asd_ha, COMSTAT);
+ 
+@@ -821,7 +819,7 @@ static inline void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
+ 	asd_chip_reset(asd_ha);
+ }
+ 
+-static inline void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
++static void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
+ {
+ 	static const char *halt_code[256] = {
+ 		"UNEXPECTED_INTERRUPT0",
+@@ -908,7 +906,7 @@ static inline void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
+  * asd_dch_sas_isr -- process device channel interrupt (DEVINT)
+  * @asd_ha: pointer to host adapter structure
+  */
+-static inline void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
++static void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
+ {
+ 	u32 dchstatus = asd_read_reg_dword(asd_ha, DCHSTATUS);
+ 
+@@ -923,7 +921,7 @@ static inline void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
+  * ads_rbi_exsi_isr -- process external system interface interrupt (INITERR)
+  * @asd_ha: pointer to host adapter structure
+  */
+-static inline void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
++static void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
+ {
+ 	u32 stat0r = asd_read_reg_dword(asd_ha, ASISTAT0R);
+ 
+@@ -971,7 +969,7 @@ static inline void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
+  *
+  * Asserted on PCIX errors: target abort, etc.
+  */
+-static inline void asd_hst_pcix_isr(struct asd_ha_struct *asd_ha)
++static void asd_hst_pcix_isr(struct asd_ha_struct *asd_ha)
+ {
+ 	u16 status;
+ 	u32 pcix_status;
+@@ -1044,8 +1042,8 @@ irqreturn_t asd_hw_isr(int irq, void *dev_id)
+ 
+ /* ---------- SCB handling ---------- */
+ 
+-static inline struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
+-					      gfp_t gfp_flags)
++static struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
++				       gfp_t gfp_flags)
+ {
+ 	extern struct kmem_cache *asd_ascb_cache;
+ 	struct asd_seq_data *seq = &asd_ha->seq;
+@@ -1144,8 +1142,8 @@ struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
+  *
+  * LOCKING: called with the pending list lock held.
+  */
+-static inline void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
+-				     struct asd_ascb *ascb)
++static void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
++			      struct asd_ascb *ascb)
+ {
+ 	struct asd_seq_data *seq = &asd_ha->seq;
+ 	struct asd_ascb *last = list_entry(ascb->list.prev,
+@@ -1171,7 +1169,7 @@ static inline void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
+  * intended to be called from asd_post_ascb_list(), just prior to
+  * posting the SCBs to the sequencer.
+  */
+-static inline void asd_start_scb_timers(struct list_head *list)
++static void asd_start_scb_timers(struct list_head *list)
+ {
+ 	struct asd_ascb *ascb;
+ 	list_for_each_entry(ascb, list, list) {
+diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h
+index abc7575..8c1c282 100644
+--- a/drivers/scsi/aic94xx/aic94xx_hwi.h
++++ b/drivers/scsi/aic94xx/aic94xx_hwi.h
+@@ -391,8 +391,6 @@ void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc);
+ void asd_control_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
+ void asd_turn_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
+ int  asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask);
+-void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
+-				      u8 subfunc);
+ 
+ void asd_ascb_timedout(unsigned long data);
+ int  asd_chip_hardrst(struct asd_ha_struct *asd_ha);
+diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
+index 88d1e73..90f5e0a 100644
+--- a/drivers/scsi/aic94xx/aic94xx_init.c
++++ b/drivers/scsi/aic94xx/aic94xx_init.c
+@@ -56,8 +56,6 @@ MODULE_PARM_DESC(collector, "\n"
+ 	"\tThe aic94xx SAS LLDD supports both modes.\n"
+ 	"\tDefault: 0 (Direct Mode).\n");
+ 
+-char sas_addr_str[2*SAS_ADDR_SIZE + 1] = "";
+-
+ static struct scsi_transport_template *aic94xx_transport_template;
+ static int asd_scan_finished(struct Scsi_Host *, unsigned long);
+ static void asd_scan_start(struct Scsi_Host *);
+@@ -547,7 +545,7 @@ static struct asd_pcidev_struct {
+ 	},
+ };
+ 
+-static inline int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
++static int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
+ {
+ 	asd_ha->scb_pool = dma_pool_create(ASD_DRIVER_NAME "_scb_pool",
+ 					   &asd_ha->pcidev->dev,
+@@ -565,7 +563,7 @@ static inline int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
+  * asd_free_edbs -- free empty data buffers
+  * asd_ha: pointer to host adapter structure
+  */
+-static inline void asd_free_edbs(struct asd_ha_struct *asd_ha)
++static void asd_free_edbs(struct asd_ha_struct *asd_ha)
+ {
+ 	struct asd_seq_data *seq = &asd_ha->seq;
+ 	int i;
+@@ -576,7 +574,7 @@ static inline void asd_free_edbs(struct asd_ha_struct *asd_ha)
+ 	seq->edb_arr = NULL;
+ }
+ 
+-static inline void asd_free_escbs(struct asd_ha_struct *asd_ha)
++static void asd_free_escbs(struct asd_ha_struct *asd_ha)
+ {
+ 	struct asd_seq_data *seq = &asd_ha->seq;
+ 	int i;
+@@ -591,7 +589,7 @@ static inline void asd_free_escbs(struct asd_ha_struct *asd_ha)
+ 	seq->escb_arr = NULL;
+ }
+ 
+-static inline void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha)
++static void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha)
+ {
+ 	int i;
+ 
+diff --git a/drivers/scsi/aic94xx/aic94xx_reg.c b/drivers/scsi/aic94xx/aic94xx_reg.c
+index f210dac..56b17c2 100644
+--- a/drivers/scsi/aic94xx/aic94xx_reg.c
++++ b/drivers/scsi/aic94xx/aic94xx_reg.c
+@@ -32,8 +32,8 @@
+  * Offset comes before value to remind that the operation of
+  * this function is *offs = val.
+  */
+-static inline void asd_write_byte(struct asd_ha_struct *asd_ha,
+-				  unsigned long offs, u8 val)
++static void asd_write_byte(struct asd_ha_struct *asd_ha,
++			   unsigned long offs, u8 val)
+ {
+ 	if (unlikely(asd_ha->iospace))
+ 		outb(val,
+@@ -43,8 +43,8 @@ static inline void asd_write_byte(struct asd_ha_struct *asd_ha,
+ 	wmb();
+ }
+ 
+-static inline void asd_write_word(struct asd_ha_struct *asd_ha,
+-				  unsigned long offs, u16 val)
++static void asd_write_word(struct asd_ha_struct *asd_ha,
++			   unsigned long offs, u16 val)
+ {
+ 	if (unlikely(asd_ha->iospace))
+ 		outw(val,
+@@ -54,8 +54,8 @@ static inline void asd_write_word(struct asd_ha_struct *asd_ha,
+ 	wmb();
+ }
+ 
+-static inline void asd_write_dword(struct asd_ha_struct *asd_ha,
+-				   unsigned long offs, u32 val)
++static void asd_write_dword(struct asd_ha_struct *asd_ha,
++			    unsigned long offs, u32 val)
+ {
+ 	if (unlikely(asd_ha->iospace))
+ 		outl(val,
+@@ -67,8 +67,7 @@ static inline void asd_write_dword(struct asd_ha_struct *asd_ha,
+ 
+ /* Reading from device address space.
+  */
+-static inline u8 asd_read_byte(struct asd_ha_struct *asd_ha,
+-			       unsigned long offs)
++static u8 asd_read_byte(struct asd_ha_struct *asd_ha, unsigned long offs)
+ {
+ 	u8 val;
+ 	if (unlikely(asd_ha->iospace))
+@@ -80,8 +79,8 @@ static inline u8 asd_read_byte(struct asd_ha_struct *asd_ha,
+ 	return val;
+ }
+ 
+-static inline u16 asd_read_word(struct asd_ha_struct *asd_ha,
+-				unsigned long offs)
++static u16 asd_read_word(struct asd_ha_struct *asd_ha,
++			 unsigned long offs)
+ {
+ 	u16 val;
+ 	if (unlikely(asd_ha->iospace))
+@@ -93,8 +92,8 @@ static inline u16 asd_read_word(struct asd_ha_struct *asd_ha,
+ 	return val;
+ }
+ 
+-static inline u32 asd_read_dword(struct asd_ha_struct *asd_ha,
+-				 unsigned long offs)
++static u32 asd_read_dword(struct asd_ha_struct *asd_ha,
++			  unsigned long offs)
+ {
+ 	u32 val;
+ 	if (unlikely(asd_ha->iospace))
+@@ -124,22 +123,22 @@ static inline u32 asd_mem_offs_swb(void)
+ /* We know that the register wanted is in the range
+  * of the sliding window.
+  */
+-#define ASD_READ_SW(ww, type, ord)                                     \
+-static inline type asd_read_##ww##_##ord (struct asd_ha_struct *asd_ha,\
+-					  u32 reg)                     \
+-{                                                                      \
+-	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];    \
+-	u32 map_offs=(reg - io_handle-> ww##_base )+asd_mem_offs_##ww ();\
+-	return asd_read_##ord (asd_ha, (unsigned long) map_offs);      \
++#define ASD_READ_SW(ww, type, ord)					\
++static type asd_read_##ww##_##ord(struct asd_ha_struct *asd_ha,		\
++				   u32 reg)				\
++{									\
++	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];	\
++	u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
++	return asd_read_##ord(asd_ha, (unsigned long)map_offs);	\
+ }
+ 
+-#define ASD_WRITE_SW(ww, type, ord)                                    \
+-static inline void asd_write_##ww##_##ord (struct asd_ha_struct *asd_ha,\
+-				  u32 reg, type val)                   \
+-{                                                                      \
+-	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];    \
+-	u32 map_offs=(reg - io_handle-> ww##_base )+asd_mem_offs_##ww ();\
+-	asd_write_##ord (asd_ha, (unsigned long) map_offs, val);       \
++#define ASD_WRITE_SW(ww, type, ord)					\
++static void asd_write_##ww##_##ord(struct asd_ha_struct *asd_ha,	\
++				    u32 reg, type val)			\
++{									\
++	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];	\
++	u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
++	asd_write_##ord(asd_ha, (unsigned long)map_offs, val);		\
+ }
+ 
+ ASD_READ_SW(swa, u8,  byte);
+@@ -186,7 +185,7 @@ ASD_WRITE_SW(swc, u32, dword);
+  * @asd_ha: pointer to host adapter structure
+  * @reg: register desired to be within range of the new window
+  */
+-static inline void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg)
++static void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg)
+ {
+ 	u32 base = reg & ~(MBAR0_SWB_SIZE-1);
+ 	pci_write_config_dword(asd_ha->pcidev, PCI_CONF_MBAR0_SWB, base);
+diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
+index ab35050..4664331 100644
+--- a/drivers/scsi/aic94xx/aic94xx_scb.c
++++ b/drivers/scsi/aic94xx/aic94xx_scb.c
+@@ -50,7 +50,7 @@
+ 			   | CURRENT_SPINUP_HOLD | CURRENT_GTO_TIMEOUT \
+ 			   | CURRENT_OOB_ERROR)
+ 
+-static inline void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
++static void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
+ {
+ 	struct sas_phy *sas_phy = phy->sas_phy.phy;
+ 
+@@ -81,7 +81,7 @@ static inline void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
+ 		phy->sas_phy.oob_mode = SATA_OOB_MODE;
+ }
+ 
+-static inline void asd_phy_event_tasklet(struct asd_ascb *ascb,
++static void asd_phy_event_tasklet(struct asd_ascb *ascb,
+ 					 struct done_list_struct *dl)
+ {
+ 	struct asd_ha_struct *asd_ha = ascb->ha;
+@@ -125,8 +125,7 @@ static inline void asd_phy_event_tasklet(struct asd_ascb *ascb,
+ }
+ 
+ /* If phys are enabled sparsely, this will do the right thing. */
+-static inline unsigned ord_phy(struct asd_ha_struct *asd_ha,
+-			       struct asd_phy *phy)
++static unsigned ord_phy(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
+ {
+ 	u8 enabled_mask = asd_ha->hw_prof.enabled_phys;
+ 	int i, k = 0;
+@@ -151,7 +150,7 @@ static inline unsigned ord_phy(struct asd_ha_struct *asd_ha,
+  * LOCKING: the frame_rcvd_lock needs to be held since this parses the frame
+  * buffer.
+  */
+-static inline void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr)
++static void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr)
+ {
+ 	if (phy->sas_phy.frame_rcvd[0] == 0x34
+ 	    && phy->sas_phy.oob_mode == SATA_OOB_MODE) {
+@@ -232,9 +231,9 @@ static void asd_deform_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
+ 	spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
+ }
+ 
+-static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
+-					   struct done_list_struct *dl,
+-					   int edb_id, int phy_id)
++static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
++				    struct done_list_struct *dl,
++				    int edb_id, int phy_id)
+ {
+ 	unsigned long flags;
+ 	int edb_el = edb_id + ascb->edb_index;
+@@ -255,9 +254,9 @@ static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
+ 	sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED);
+ }
+ 
+-static inline void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
+-					      struct done_list_struct *dl,
+-					      int phy_id)
++static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
++				       struct done_list_struct *dl,
++				       int phy_id)
+ {
+ 	struct asd_ha_struct *asd_ha = ascb->ha;
+ 	struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
+@@ -308,9 +307,9 @@ out:
+ 	;
+ }
+ 
+-static inline void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb,
+-					      struct done_list_struct *dl,
+-					      int phy_id)
++static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb,
++				       struct done_list_struct *dl,
++				       int phy_id)
+ {
+ 	unsigned long flags;
+ 	struct sas_ha_struct *sas_ha = &ascb->ha->sas_ha;
+@@ -715,7 +714,7 @@ out:
+ 	asd_ascb_free(ascb);
+ }
+ 
+-static inline void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd)
++static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd)
+ {
+ 	/* disable all speeds, then enable defaults */
+ 	*speed_mask = SAS_SPEED_60_DIS | SAS_SPEED_30_DIS | SAS_SPEED_15_DIS
+@@ -820,6 +819,8 @@ void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc)
+ 
+ /* ---------- INITIATE LINK ADM TASK ---------- */
+ 
++#if 0
++
+ static void link_adm_tasklet_complete(struct asd_ascb *ascb,
+ 				      struct done_list_struct *dl)
+ {
+@@ -852,6 +853,8 @@ void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
+ 	ascb->tasklet_complete = link_adm_tasklet_complete;
+ }
+ 
++#endif  /*  0  */
++
+ /* ---------- SCB timer ---------- */
+ 
+ /**
+diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c
+index 2a4c933..4446e3d 100644
+--- a/drivers/scsi/aic94xx/aic94xx_sds.c
++++ b/drivers/scsi/aic94xx/aic94xx_sds.c
+@@ -590,8 +590,8 @@ static int asd_reset_flash(struct asd_ha_struct *asd_ha)
+ 	return err;
+ }
+ 
+-static inline int asd_read_flash_seg(struct asd_ha_struct *asd_ha,
+-				     void *buffer, u32 offs, int size)
++static int asd_read_flash_seg(struct asd_ha_struct *asd_ha,
++			      void *buffer, u32 offs, int size)
+ {
+ 	asd_read_reg_string(asd_ha, buffer, asd_ha->hw_prof.flash.bar+offs,
+ 			    size);
+diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c
+index c750fbf..f4272ac 100644
+--- a/drivers/scsi/aic94xx/aic94xx_seq.c
++++ b/drivers/scsi/aic94xx/aic94xx_seq.c
+@@ -60,7 +60,7 @@ static u16 last_scb_site_no;
+  *
+  * Return 0 on success, negative on failure.
+  */
+-int asd_pause_cseq(struct asd_ha_struct *asd_ha)
++static int asd_pause_cseq(struct asd_ha_struct *asd_ha)
+ {
+ 	int	count = PAUSE_TRIES;
+ 	u32	arp2ctl;
+@@ -87,7 +87,7 @@ int asd_pause_cseq(struct asd_ha_struct *asd_ha)
+  *
+  * Return 0 on success, negative on error.
+  */
+-int asd_unpause_cseq(struct asd_ha_struct *asd_ha)
++static int asd_unpause_cseq(struct asd_ha_struct *asd_ha)
+ {
+ 	u32	arp2ctl;
+ 	int	count = PAUSE_TRIES;
+@@ -115,7 +115,7 @@ int asd_unpause_cseq(struct asd_ha_struct *asd_ha)
+  *
+  * Return 0 on success, negative on error.
+  */
+-static inline int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq)
++static int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+ {
+ 	u32    arp2ctl;
+ 	int    count = PAUSE_TRIES;
+@@ -143,7 +143,7 @@ static inline int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+  *
+  * Return 0 on success, negative on failure.
+  */
+-int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
++static int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
+ {
+ 	int lseq;
+ 	int err = 0;
+@@ -164,7 +164,7 @@ int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
+  *
+  * Return 0 on success, negative on error.
+  */
+-static inline int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq)
++static int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+ {
+ 	u32 arp2ctl;
+ 	int count = PAUSE_TRIES;
+@@ -186,27 +186,6 @@ static inline int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+ }
+ 
+ 
+-/**
+- * asd_unpause_lseq - unpause the link sequencer(s)
+- * @asd_ha: pointer to host adapter structure
+- * @lseq_mask: mask of link sequencers of interest
+- *
+- * Return 0 on success, negative on failure.
+- */
+-int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
+-{
+-	int lseq;
+-	int err = 0;
+-
+-	for_each_sequencer(lseq_mask, lseq_mask, lseq) {
+-		err = asd_seq_unpause_lseq(asd_ha, lseq);
+-		if (err)
+-			return err;
+-	}
+-
+-	return err;
+-}
+-
+ /* ---------- Downloading CSEQ/LSEQ microcode ---------- */
+ 
+ static int asd_verify_cseq(struct asd_ha_struct *asd_ha, const u8 *_prog,
+diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h
+index 2ea6a0d..ad787c5 100644
+--- a/drivers/scsi/aic94xx/aic94xx_seq.h
++++ b/drivers/scsi/aic94xx/aic94xx_seq.h
+@@ -58,10 +58,6 @@ struct sequencer_file_header {
+ } __attribute__((packed));
+ 
+ #ifdef __KERNEL__
+-int asd_pause_cseq(struct asd_ha_struct *asd_ha);
+-int asd_unpause_cseq(struct asd_ha_struct *asd_ha);
+-int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
+-int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
+ int asd_init_seqs(struct asd_ha_struct *asd_ha);
+ int asd_start_seqs(struct asd_ha_struct *asd_ha);
+ int asd_release_firmware(void);
+diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
+index 008df9a..326765c 100644
+--- a/drivers/scsi/aic94xx/aic94xx_task.c
++++ b/drivers/scsi/aic94xx/aic94xx_task.c
+@@ -33,7 +33,7 @@ static void asd_unbuild_ata_ascb(struct asd_ascb *a);
+ static void asd_unbuild_smp_ascb(struct asd_ascb *a);
+ static void asd_unbuild_ssp_ascb(struct asd_ascb *a);
+ 
+-static inline void asd_can_dequeue(struct asd_ha_struct *asd_ha, int num)
++static void asd_can_dequeue(struct asd_ha_struct *asd_ha, int num)
+ {
+ 	unsigned long flags;
+ 
+@@ -51,9 +51,9 @@ static const u8 data_dir_flags[] = {
+ 	[PCI_DMA_NONE]          = DATA_DIR_NONE, /* NO TRANSFER */
+ };
+ 
+-static inline int asd_map_scatterlist(struct sas_task *task,
+-				      struct sg_el *sg_arr,
+-				      gfp_t gfp_flags)
++static int asd_map_scatterlist(struct sas_task *task,
++			       struct sg_el *sg_arr,
++			       gfp_t gfp_flags)
+ {
+ 	struct asd_ascb *ascb = task->lldd_task;
+ 	struct asd_ha_struct *asd_ha = ascb->ha;
+@@ -131,7 +131,7 @@ err_unmap:
+ 	return res;
+ }
+ 
+-static inline void asd_unmap_scatterlist(struct asd_ascb *ascb)
++static void asd_unmap_scatterlist(struct asd_ascb *ascb)
+ {
+ 	struct asd_ha_struct *asd_ha = ascb->ha;
+ 	struct sas_task *task = ascb->uldd_task;
+@@ -527,7 +527,7 @@ static void asd_unbuild_ssp_ascb(struct asd_ascb *a)
+ 
+ /* ---------- Execute Task ---------- */
+ 
+-static inline int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
++static int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
+ {
+ 	int res = 0;
+ 	unsigned long flags;
+diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
+index b9ac8f7..633ff40 100644
+--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
++++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
+@@ -336,7 +336,7 @@ static void asd_tmf_tasklet_complete(struct asd_ascb *ascb,
+ 	asd_ascb_free(ascb);
+ }
+ 
+-static inline int asd_clear_nexus(struct sas_task *task)
++static int asd_clear_nexus(struct sas_task *task)
+ {
+ 	int res = TMF_RESP_FUNC_FAILED;
+ 	int leftover;
+diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
+index 3288be2..ab646e5 100644
+--- a/drivers/scsi/arcmsr/arcmsr.h
++++ b/drivers/scsi/arcmsr/arcmsr.h
+@@ -44,7 +44,7 @@
+ */
+ #include <linux/interrupt.h>
+ 
+-struct class_device_attribute;
++struct device_attribute;
+ /*The limit of outstanding scsi command that firmware can handle*/
+ #define ARCMSR_MAX_OUTSTANDING_CMD						256
+ #define ARCMSR_MAX_FREECCB_NUM							320
+@@ -556,6 +556,6 @@ struct SENSE_DATA
+ extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *);
+ extern void arcmsr_iop_message_read(struct AdapterControlBlock *);
+ extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
+-extern struct class_device_attribute *arcmsr_host_attrs[];
++extern struct device_attribute *arcmsr_host_attrs[];
+ extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
+ void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
+diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
+index 7d7b0a5..69f8346 100644
+--- a/drivers/scsi/arcmsr/arcmsr_attr.c
++++ b/drivers/scsi/arcmsr/arcmsr_attr.c
+@@ -57,15 +57,15 @@
+ #include <scsi/scsi_transport.h>
+ #include "arcmsr.h"
+ 
+-struct class_device_attribute *arcmsr_host_attrs[];
++struct device_attribute *arcmsr_host_attrs[];
+ 
+ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj,
+ 					     struct bin_attribute *bin,
+ 					     char *buf, loff_t off,
+ 					     size_t count)
+ {
+-	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct device *dev = container_of(kobj,struct device,kobj);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+ 	uint8_t *pQbuffer,*ptmpQbuffer;
+ 	int32_t allxfer_len = 0;
+@@ -110,8 +110,8 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj,
+ 					      char *buf, loff_t off,
+ 					      size_t count)
+ {
+-	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct device *dev = container_of(kobj,struct device,kobj);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+ 	int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
+ 	uint8_t *pQbuffer, *ptmpuserbuffer;
+@@ -158,8 +158,8 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
+ 					      char *buf, loff_t off,
+ 					      size_t count)
+ {
+-	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct device *dev = container_of(kobj,struct device,kobj);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+ 	uint8_t *pQbuffer;
+ 
+@@ -220,87 +220,104 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
+ 	struct Scsi_Host *host = acb->host;
+ 	int error;
+ 
+-	error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
++	error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
+ 	if (error) {
+ 		printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
+ 		goto error_bin_file_message_read;
+ 	}
+-	error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
++	error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
+ 	if (error) {
+ 		printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
+ 		goto error_bin_file_message_write;
+ 	}
+-	error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
++	error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
+ 	if (error) {
+ 		printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
+ 		goto error_bin_file_message_clear;
+ 	}
+ 	return 0;
+ error_bin_file_message_clear:
+-	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
++	sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
+ error_bin_file_message_write:
+-	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
++	sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
+ error_bin_file_message_read:
+ 	return error;
+ }
+ 
+-void
+-arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
++void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb)
++{
+ 	struct Scsi_Host *host = acb->host;
+ 
+-	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
+-	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
+-	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
++	sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
++	sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
++	sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
+ }
+ 
+ 
+ static ssize_t
+-arcmsr_attr_host_driver_version(struct class_device *cdev, char *buf) {
++arcmsr_attr_host_driver_version(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%s\n",
+ 			ARCMSR_DRIVER_VERSION);
+ }
+ 
+ static ssize_t
+-arcmsr_attr_host_driver_posted_cmd(struct class_device *cdev, char *buf) {
+-	struct Scsi_Host *host = class_to_shost(cdev);
+-	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_driver_posted_cmd(struct device *dev,
++				   struct device_attribute *attr, char *buf)
++{
++	struct Scsi_Host *host = class_to_shost(dev);
++	struct AdapterControlBlock *acb =
++		(struct AdapterControlBlock *) host->hostdata;
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%4d\n",
+ 			atomic_read(&acb->ccboutstandingcount));
+ }
+ 
+ static ssize_t
+-arcmsr_attr_host_driver_reset(struct class_device *cdev, char *buf) {
+-	struct Scsi_Host *host = class_to_shost(cdev);
+-	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_driver_reset(struct device *dev,
++			      struct device_attribute *attr, char *buf)
++{
++	struct Scsi_Host *host = class_to_shost(dev);
++	struct AdapterControlBlock *acb =
++		(struct AdapterControlBlock *) host->hostdata;
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%4d\n",
+ 			acb->num_resets);
+ }
+ 
+ static ssize_t
+-arcmsr_attr_host_driver_abort(struct class_device *cdev, char *buf) {
+-	struct Scsi_Host *host = class_to_shost(cdev);
+-	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_driver_abort(struct device *dev,
++			      struct device_attribute *attr, char *buf)
++{
++	struct Scsi_Host *host = class_to_shost(dev);
++	struct AdapterControlBlock *acb =
++		(struct AdapterControlBlock *) host->hostdata;
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%4d\n",
+ 			acb->num_aborts);
+ }
+ 
+ static ssize_t
+-arcmsr_attr_host_fw_model(struct class_device *cdev, char *buf) {
+-    struct Scsi_Host *host = class_to_shost(cdev);
+-	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_model(struct device *dev, struct device_attribute *attr,
++			  char *buf)
++{
++	struct Scsi_Host *host = class_to_shost(dev);
++	struct AdapterControlBlock *acb =
++		(struct AdapterControlBlock *) host->hostdata;
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%s\n",
+ 			acb->firm_model);
+ }
+ 
+ static ssize_t
+-arcmsr_attr_host_fw_version(struct class_device *cdev, char *buf) {
+-	struct Scsi_Host *host = class_to_shost(cdev);
+-	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_version(struct device *dev,
++			    struct device_attribute *attr, char *buf)
++{
++	struct Scsi_Host *host = class_to_shost(dev);
++	struct AdapterControlBlock *acb =
++			(struct AdapterControlBlock *) host->hostdata;
+ 
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%s\n",
+@@ -308,9 +325,12 @@ arcmsr_attr_host_fw_version(struct class_device *cdev, char *buf) {
+ }
+ 
+ static ssize_t
+-arcmsr_attr_host_fw_request_len(struct class_device *cdev, char *buf) {
+-	struct Scsi_Host *host = class_to_shost(cdev);
+-	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_request_len(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct Scsi_Host *host = class_to_shost(dev);
++	struct AdapterControlBlock *acb =
++		(struct AdapterControlBlock *) host->hostdata;
+ 
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%4d\n",
+@@ -318,9 +338,12 @@ arcmsr_attr_host_fw_request_len(struct class_device *cdev, char *buf) {
+ }
+ 
+ static ssize_t
+-arcmsr_attr_host_fw_numbers_queue(struct class_device *cdev, char *buf) {
+-	struct Scsi_Host *host = class_to_shost(cdev);
+-	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_numbers_queue(struct device *dev,
++				  struct device_attribute *attr, char *buf)
++{
++	struct Scsi_Host *host = class_to_shost(dev);
++	struct AdapterControlBlock *acb =
++		(struct AdapterControlBlock *) host->hostdata;
+ 
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%4d\n",
+@@ -328,9 +351,12 @@ arcmsr_attr_host_fw_numbers_queue(struct class_device *cdev, char *buf) {
+ }
+ 
+ static ssize_t
+-arcmsr_attr_host_fw_sdram_size(struct class_device *cdev, char *buf) {
+-	struct Scsi_Host *host = class_to_shost(cdev);
+-	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_sdram_size(struct device *dev,
++			       struct device_attribute *attr, char *buf)
++{
++	struct Scsi_Host *host = class_to_shost(dev);
++	struct AdapterControlBlock *acb =
++		(struct AdapterControlBlock *) host->hostdata;
+ 
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%4d\n",
+@@ -338,36 +364,39 @@ arcmsr_attr_host_fw_sdram_size(struct class_device *cdev, char *buf) {
+ }
+ 
+ static ssize_t
+-arcmsr_attr_host_fw_hd_channels(struct class_device *cdev, char *buf) {
+-	struct Scsi_Host *host = class_to_shost(cdev);
+-	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_hd_channels(struct device *dev,
++				struct device_attribute *attr, char *buf)
++{
++	struct Scsi_Host *host = class_to_shost(dev);
++	struct AdapterControlBlock *acb =
++		(struct AdapterControlBlock *) host->hostdata;
+ 
+ 	return snprintf(buf, PAGE_SIZE,
+ 			"%4d\n",
+ 			acb->firm_hd_channels);
+ }
+ 
+-static CLASS_DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL);
+-static CLASS_DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL);
+-static CLASS_DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL);
+-static CLASS_DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL);
+-
+-struct class_device_attribute *arcmsr_host_attrs[] = {
+-	&class_device_attr_host_driver_version,
+-	&class_device_attr_host_driver_posted_cmd,
+-	&class_device_attr_host_driver_reset,
+-	&class_device_attr_host_driver_abort,
+-	&class_device_attr_host_fw_model,
+-	&class_device_attr_host_fw_version,
+-	&class_device_attr_host_fw_request_len,
+-	&class_device_attr_host_fw_numbers_queue,
+-	&class_device_attr_host_fw_sdram_size,
+-	&class_device_attr_host_fw_hd_channels,
++static DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL);
++static DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL);
++static DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL);
++static DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL);
++static DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL);
++static DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL);
++static DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL);
++static DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL);
++static DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL);
++static DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL);
++
++struct device_attribute *arcmsr_host_attrs[] = {
++	&dev_attr_host_driver_version,
++	&dev_attr_host_driver_posted_cmd,
++	&dev_attr_host_driver_reset,
++	&dev_attr_host_driver_abort,
++	&dev_attr_host_fw_model,
++	&dev_attr_host_fw_version,
++	&dev_attr_host_fw_request_len,
++	&dev_attr_host_fw_numbers_queue,
++	&dev_attr_host_fw_sdram_size,
++	&dev_attr_host_fw_hd_channels,
+ 	NULL,
+ };
+diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
+index 3bedf24..8e53f02 100644
+--- a/drivers/scsi/arm/acornscsi.c
++++ b/drivers/scsi/arm/acornscsi.c
+@@ -2983,7 +2983,6 @@ static struct scsi_host_template acornscsi_template = {
+ 	.this_id		= 7,
+ 	.sg_tablesize		= SG_ALL,
+ 	.cmd_per_lun		= 2,
+-	.unchecked_isa_dma	= 0,
+ 	.use_clustering		= DISABLE_CLUSTERING,
+ 	.proc_name		= "acornscsi",
+ };
+diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
+index 49d838e..a3398fe 100644
+--- a/drivers/scsi/arm/cumana_1.c
++++ b/drivers/scsi/arm/cumana_1.c
+@@ -222,7 +222,6 @@ static struct scsi_host_template cumanascsi_template = {
+ 	.this_id		= 7,
+ 	.sg_tablesize		= SG_ALL,
+ 	.cmd_per_lun		= 2,
+-	.unchecked_isa_dma	= 0,
+ 	.use_clustering		= DISABLE_CLUSTERING,
+ 	.proc_name		= "CumanaSCSI-1",
+ };
+diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
+index 7aad154..75c84d7 100644
+--- a/drivers/scsi/ch.c
++++ b/drivers/scsi/ch.c
+@@ -113,7 +113,7 @@ static const struct {
+ 	unsigned char  asc;
+ 	unsigned char  ascq;
+ 	int	       errno;
+-} err[] = {
++} ch_err[] = {
+ /* Just filled in what looks right. Hav'nt checked any standard paper for
+    these errno assignments, so they may be wrong... */
+ 	{
+@@ -155,11 +155,11 @@ static int ch_find_errno(struct scsi_sense_hdr *sshdr)
+ 	/* Check to see if additional sense information is available */
+ 	if (scsi_sense_valid(sshdr) &&
+ 	    sshdr->asc != 0) {
+-		for (i = 0; err[i].errno != 0; i++) {
+-			if (err[i].sense == sshdr->sense_key &&
+-			    err[i].asc   == sshdr->asc &&
+-			    err[i].ascq  == sshdr->ascq) {
+-				errno = -err[i].errno;
++		for (i = 0; ch_err[i].errno != 0; i++) {
++			if (ch_err[i].sense == sshdr->sense_key &&
++			    ch_err[i].asc   == sshdr->asc &&
++			    ch_err[i].ascq  == sshdr->ascq) {
++				errno = -ch_err[i].errno;
+ 				break;
+ 			}
+ 		}
+@@ -721,8 +721,8 @@ static long ch_ioctl(struct file *file,
+ 	case CHIOGELEM:
+ 	{
+ 		struct changer_get_element cge;
+-		u_char  cmd[12];
+-		u_char  *buffer;
++		u_char ch_cmd[12];
++		u_char *buffer;
+ 		unsigned int elem;
+ 		int     result,i;
+ 
+@@ -739,17 +739,18 @@ static long ch_ioctl(struct file *file,
+ 		mutex_lock(&ch->lock);
+ 
+ 	voltag_retry:
+-		memset(cmd,0,sizeof(cmd));
+-		cmd[0] = READ_ELEMENT_STATUS;
+-		cmd[1] = (ch->device->lun << 5) |
++		memset(ch_cmd, 0, sizeof(ch_cmd));
++		ch_cmd[0] = READ_ELEMENT_STATUS;
++		ch_cmd[1] = (ch->device->lun << 5) |
+ 			(ch->voltags ? 0x10 : 0) |
+ 			ch_elem_to_typecode(ch,elem);
+-		cmd[2] = (elem >> 8) & 0xff;
+-		cmd[3] = elem        & 0xff;
+-		cmd[5] = 1;
+-		cmd[9] = 255;
++		ch_cmd[2] = (elem >> 8) & 0xff;
++		ch_cmd[3] = elem        & 0xff;
++		ch_cmd[5] = 1;
++		ch_cmd[9] = 255;
+ 
+-		if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
++		result = ch_do_scsi(ch, ch_cmd, buffer, 256, DMA_FROM_DEVICE);
++		if (!result) {
+ 			cge.cge_status = buffer[18];
+ 			cge.cge_flags = 0;
+ 			if (buffer[18] & CESTATUS_EXCEPT) {
+@@ -880,7 +881,7 @@ static long ch_ioctl_compat(struct file * file,
+ static int ch_probe(struct device *dev)
+ {
+ 	struct scsi_device *sd = to_scsi_device(dev);
+-	struct class_device *class_dev;
++	struct device *class_dev;
+ 	int minor, ret = -ENOMEM;
+ 	scsi_changer *ch;
+ 
+@@ -909,11 +910,11 @@ static int ch_probe(struct device *dev)
+ 	ch->minor = minor;
+ 	sprintf(ch->name,"ch%d",ch->minor);
+ 
+-	class_dev = class_device_create(ch_sysfs_class, NULL,
+-					MKDEV(SCSI_CHANGER_MAJOR, ch->minor),
+-					dev, "s%s", ch->name);
++	class_dev = device_create(ch_sysfs_class, dev,
++				  MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
++				  "s%s", ch->name);
+ 	if (IS_ERR(class_dev)) {
+-		printk(KERN_WARNING "ch%d: class_device_create failed\n",
++		printk(KERN_WARNING "ch%d: device_create failed\n",
+ 		       ch->minor);
+ 		ret = PTR_ERR(class_dev);
+ 		goto remove_idr;
+@@ -944,8 +945,7 @@ static int ch_remove(struct device *dev)
+ 	idr_remove(&ch_index_idr, ch->minor);
+ 	spin_unlock(&ch_index_lock);
+ 
+-	class_device_destroy(ch_sysfs_class,
+-			     MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
++	device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
+ 	kfree(ch->dt);
+ 	kfree(ch);
+ 	return 0;
+diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
+index e351db6..075e239 100644
+--- a/drivers/scsi/dc395x.c
++++ b/drivers/scsi/dc395x.c
+@@ -4761,7 +4761,6 @@ static struct scsi_host_template dc395x_driver_template = {
+ 	.cmd_per_lun            = DC395x_MAX_CMD_PER_LUN,
+ 	.eh_abort_handler       = dc395x_eh_abort,
+ 	.eh_bus_reset_handler   = dc395x_eh_bus_reset,
+-	.unchecked_isa_dma      = 0,
+ 	.use_clustering         = DISABLE_CLUSTERING,
+ };
+ 
+diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
+index 100b49b..19406ce 100644
+--- a/drivers/scsi/dpt/dpti_i2o.h
++++ b/drivers/scsi/dpt/dpti_i2o.h
+@@ -21,7 +21,6 @@
+ 
+ #include <linux/i2o-dev.h>
+ 
+-#include <asm/semaphore.h> /* Needed for MUTEX init macros */
+ #include <linux/version.h>
+ #include <linux/notifier.h>
+ #include <asm/atomic.h>
+diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
+index b5a6092..952505c 100644
+--- a/drivers/scsi/eata_pio.c
++++ b/drivers/scsi/eata_pio.c
+@@ -815,8 +815,6 @@ static int register_pio_HBA(long base, struct get_conf *gc, struct pci_dev *pdev
+ 	else
+ 		hd->primary = 1;
+ 
+-	sh->unchecked_isa_dma = 0;	/* We can only do PIO */
+-
+ 	hd->next = NULL;	/* build a linked list of all HBAs */
+ 	hd->prev = last_HBA;
+ 	if (hd->prev != NULL)
+diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
+index 0b2080d..c6d6e7c 100644
+--- a/drivers/scsi/gdth.c
++++ b/drivers/scsi/gdth.c
+@@ -85,10 +85,10 @@
+ 
+ /* The meaning of the Scsi_Pointer members in this driver is as follows:
+  * ptr:                     Chaining
+- * this_residual:           gdth_bufflen
+- * buffer:                  gdth_sglist
++ * this_residual:           unused
++ * buffer:                  unused
+  * dma_handle:              unused
+- * buffers_residual:        gdth_sg_count
++ * buffers_residual:        unused
+  * Status:                  unused
+  * Message:                 unused
+  * have_data_in:            unused
+@@ -372,47 +372,6 @@ static const struct file_operations gdth_fops = {
+     .release = gdth_close,
+ };
+ 
+-/*
+- * gdth scsi_command access wrappers.
+- *   below 6 functions are used throughout the driver to access scsi_command's
+- *   io parameters. The reason we do not use the regular accessors from
+- *   scsi_cmnd.h is because of gdth_execute(). Since it is unrecommended for
+- *   llds to directly set scsi_cmnd's IO members. This driver will use SCp
+- *   members for IO parameters, and will copy scsi_cmnd's members to Scp
+- *   members in queuecommand. For internal commands through gdth_execute()
+- *   SCp's members will be set directly.
+- */
+-static inline unsigned gdth_bufflen(struct scsi_cmnd *cmd)
+-{
+-	return (unsigned)cmd->SCp.this_residual;
+-}
+-
+-static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen)
+-{
+-	cmd->SCp.this_residual = bufflen;
+-}
+-
+-static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd)
+-{
+-	return (unsigned)cmd->SCp.buffers_residual;
+-}
+-
+-static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count)
+-{
+-	cmd->SCp.buffers_residual = sg_count;
+-}
+-
+-static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd)
+-{
+-	return cmd->SCp.buffer;
+-}
+-
+-static inline void gdth_set_sglist(struct scsi_cmnd *cmd,
+-                                   struct scatterlist *sglist)
+-{
+-	cmd->SCp.buffer = sglist;
+-}
+-
+ #include "gdth_proc.h"
+ #include "gdth_proc.c"
+ 
+@@ -591,125 +550,111 @@ static int __init gdth_search_isa(ulong32 bios_adr)
+ #endif /* CONFIG_ISA */
+ 
+ #ifdef CONFIG_PCI
+-static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
+-                            ushort vendor, ushort dev);
++static bool gdth_pci_registered;
+ 
+-static int __init gdth_search_pci(gdth_pci_str *pcistr)
++static bool gdth_search_vortex(ushort device)
+ {
+-    ushort device, cnt;
+-    
+-    TRACE(("gdth_search_pci()\n"));
+-
+-    cnt = 0;
+-    for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device)
+-        gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
+-    for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP; 
+-         device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device)
+-        gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
+-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
+-                    PCI_DEVICE_ID_VORTEX_GDTNEWRX);
+-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
+-                    PCI_DEVICE_ID_VORTEX_GDTNEWRX2);
+-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
+-                    PCI_DEVICE_ID_INTEL_SRC);
+-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
+-                    PCI_DEVICE_ID_INTEL_SRC_XSCALE);
+-    return cnt;
++	if (device <= PCI_DEVICE_ID_VORTEX_GDT6555)
++		return true;
++	if (device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP &&
++	    device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP)
++		return true;
++	if (device == PCI_DEVICE_ID_VORTEX_GDTNEWRX ||
++	    device == PCI_DEVICE_ID_VORTEX_GDTNEWRX2)
++		return true;
++	return false;
+ }
+ 
++static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out);
++static int gdth_pci_init_one(struct pci_dev *pdev,
++			     const struct pci_device_id *ent);
++static void gdth_pci_remove_one(struct pci_dev *pdev);
++static void gdth_remove_one(gdth_ha_str *ha);
++
+ /* Vortex only makes RAID controllers.
+  * We do not really want to specify all 550 ids here, so wildcard match.
+  */
+-static struct pci_device_id gdthtable[] __maybe_unused = {
+-    {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
+-    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
+-    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
+-    {0}
++static const struct pci_device_id gdthtable[] = {
++	{ PCI_VDEVICE(VORTEX, PCI_ANY_ID) },
++	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC) },
++	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC_XSCALE) },
++	{ }	/* terminate list */
++};
++MODULE_DEVICE_TABLE(pci, gdthtable);
++
++static struct pci_driver gdth_pci_driver = {
++	.name		= "gdth",
++	.id_table	= gdthtable,
++	.probe		= gdth_pci_init_one,
++	.remove		= gdth_pci_remove_one,
+ };
+-MODULE_DEVICE_TABLE(pci,gdthtable);
+ 
+-static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
+-                                   ushort vendor, ushort device)
++static void gdth_pci_remove_one(struct pci_dev *pdev)
+ {
+-    ulong base0, base1, base2;
+-    struct pci_dev *pdev;
++	gdth_ha_str *ha = pci_get_drvdata(pdev);
++
++	pci_set_drvdata(pdev, NULL);
++
++	list_del(&ha->list);
++	gdth_remove_one(ha);
++
++	pci_disable_device(pdev);
++}
++
++static int gdth_pci_init_one(struct pci_dev *pdev,
++				       const struct pci_device_id *ent)
++{
++	ushort vendor = pdev->vendor;
++	ushort device = pdev->device;
++	ulong base0, base1, base2;
++	int rc;
++	gdth_pci_str gdth_pcistr;
++	gdth_ha_str *ha = NULL;
+     
+-    TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
+-          *cnt, vendor, device));
++	TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
++	       gdth_ctr_count, vendor, device));
+ 
+-    pdev = NULL;
+-    while ((pdev = pci_get_device(vendor, device, pdev))
+-           != NULL) {
+-        if (pci_enable_device(pdev))
+-            continue;
+-        if (*cnt >= MAXHA) {
+-            pci_dev_put(pdev);
+-            return;
+-        }
++	memset(&gdth_pcistr, 0, sizeof(gdth_pcistr));
++
++	if (vendor == PCI_VENDOR_ID_VORTEX && !gdth_search_vortex(device))
++		return -ENODEV;
++
++	rc = pci_enable_device(pdev);
++	if (rc)
++		return rc;
++
++	if (gdth_ctr_count >= MAXHA)
++		return -EBUSY;
+ 
+         /* GDT PCI controller found, resources are already in pdev */
+-        pcistr[*cnt].pdev = pdev;
+-        pcistr[*cnt].irq = pdev->irq;
++	gdth_pcistr.pdev = pdev;
+         base0 = pci_resource_flags(pdev, 0);
+         base1 = pci_resource_flags(pdev, 1);
+         base2 = pci_resource_flags(pdev, 2);
+         if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
+             device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
+             if (!(base0 & IORESOURCE_MEM)) 
+-                continue;
+-            pcistr[*cnt].dpmem = pci_resource_start(pdev, 0);
++		return -ENODEV;
++	    gdth_pcistr.dpmem = pci_resource_start(pdev, 0);
+         } else {                                  /* GDT6110, GDT6120, .. */
+             if (!(base0 & IORESOURCE_MEM) ||
+                 !(base2 & IORESOURCE_MEM) ||
+                 !(base1 & IORESOURCE_IO)) 
+-                continue;
+-            pcistr[*cnt].dpmem = pci_resource_start(pdev, 2);
+-            pcistr[*cnt].io_mm = pci_resource_start(pdev, 0);
+-            pcistr[*cnt].io    = pci_resource_start(pdev, 1);
++		return -ENODEV;
++	    gdth_pcistr.dpmem = pci_resource_start(pdev, 2);
++	    gdth_pcistr.io    = pci_resource_start(pdev, 1);
+         }
+         TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
+-                pcistr[*cnt].pdev->bus->number,
+-		PCI_SLOT(pcistr[*cnt].pdev->devfn),
+-                pcistr[*cnt].irq, pcistr[*cnt].dpmem));
+-        (*cnt)++;
+-    }       
+-}   
++		gdth_pcistr.pdev->bus->number,
++		PCI_SLOT(gdth_pcistr.pdev->devfn),
++		gdth_pcistr.irq,
++		gdth_pcistr.dpmem));
+ 
+-static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
+-{    
+-    gdth_pci_str temp;
+-    int i, changed;
+-    
+-    TRACE(("gdth_sort_pci() cnt %d\n",cnt));
+-    if (cnt == 0)
+-        return;
++	rc = gdth_pci_probe_one(&gdth_pcistr, &ha);
++	if (rc)
++		return rc;
+ 
+-    do {
+-        changed = FALSE;
+-        for (i = 0; i < cnt-1; ++i) {
+-            if (!reverse_scan) {
+-                if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) ||
+-                    (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
+-                     PCI_SLOT(pcistr[i].pdev->devfn) >
+-                     PCI_SLOT(pcistr[i+1].pdev->devfn))) {
+-                    temp = pcistr[i];
+-                    pcistr[i] = pcistr[i+1];
+-                    pcistr[i+1] = temp;
+-                    changed = TRUE;
+-                }
+-            } else {
+-                if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) ||
+-                    (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
+-                     PCI_SLOT(pcistr[i].pdev->devfn) <
+-                     PCI_SLOT(pcistr[i+1].pdev->devfn))) {
+-                    temp = pcistr[i];
+-                    pcistr[i] = pcistr[i+1];
+-                    pcistr[i+1] = temp;
+-                    changed = TRUE;
+-                }
+-            }
+-        }
+-    } while (changed);
++	return 0;
+ }
+ #endif /* CONFIG_PCI */
+ 
+@@ -909,7 +854,8 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
+ #endif /* CONFIG_ISA */
+ 
+ #ifdef CONFIG_PCI
+-static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
++static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
++				   gdth_ha_str *ha)
+ {
+     register gdt6_dpram_str __iomem *dp6_ptr;
+     register gdt6c_dpram_str __iomem *dp6c_ptr;
+@@ -921,14 +867,14 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+ 
+     TRACE(("gdth_init_pci()\n"));
+ 
+-    if (pcistr->pdev->vendor == PCI_VENDOR_ID_INTEL)
++    if (pdev->vendor == PCI_VENDOR_ID_INTEL)
+         ha->oem_id = OEM_ID_INTEL;
+     else
+         ha->oem_id = OEM_ID_ICP;
+-    ha->brd_phys = (pcistr->pdev->bus->number << 8) | (pcistr->pdev->devfn & 0xf8);
+-    ha->stype = (ulong32)pcistr->pdev->device;
+-    ha->irq = pcistr->irq;
+-    ha->pdev = pcistr->pdev;
++    ha->brd_phys = (pdev->bus->number << 8) | (pdev->devfn & 0xf8);
++    ha->stype = (ulong32)pdev->device;
++    ha->irq = pdev->irq;
++    ha->pdev = pdev;
+     
+     if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6000B) {  /* GDT6000/B */
+         TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
+@@ -956,8 +902,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+                     continue;
+                 }
+                 iounmap(ha->brd);
+-                pci_write_config_dword(pcistr->pdev, 
+-                                       PCI_BASE_ADDRESS_0, i);
++		pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
+                 ha->brd = ioremap(i, sizeof(gdt6_dpram_str)); 
+                 if (ha->brd == NULL) {
+                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+@@ -1066,8 +1011,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+                     continue;
+                 }
+                 iounmap(ha->brd);
+-                pci_write_config_dword(pcistr->pdev, 
+-                                       PCI_BASE_ADDRESS_2, i);
++		pci_write_config_dword(pdev, PCI_BASE_ADDRESS_2, i);
+                 ha->brd = ioremap(i, sizeof(gdt6c_dpram_str)); 
+                 if (ha->brd == NULL) {
+                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+@@ -1159,16 +1103,16 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+         }
+ 
+         /* manipulate config. space to enable DPMEM, start RP controller */
+-        pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
++	pci_read_config_word(pdev, PCI_COMMAND, &command);
+         command |= 6;
+-        pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
+-        if (pci_resource_start(pcistr->pdev, 8) == 1UL)
+-            pci_resource_start(pcistr->pdev, 8) = 0UL;
++	pci_write_config_word(pdev, PCI_COMMAND, command);
++	if (pci_resource_start(pdev, 8) == 1UL)
++	    pci_resource_start(pdev, 8) = 0UL;
+         i = 0xFEFF0001UL;
+-        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
++	pci_write_config_dword(pdev, PCI_ROM_ADDRESS, i);
+         gdth_delay(1);
+-        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
+-                               pci_resource_start(pcistr->pdev, 8));
++	pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
++			       pci_resource_start(pdev, 8));
+         
+         dp6m_ptr = ha->brd;
+ 
+@@ -1195,8 +1139,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+                     continue;
+                 }
+                 iounmap(ha->brd);
+-                pci_write_config_dword(pcistr->pdev, 
+-                                       PCI_BASE_ADDRESS_0, i);
++		pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
+                 ha->brd = ioremap(i, sizeof(gdt6m_dpram_str)); 
+                 if (ha->brd == NULL) {
+                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+@@ -2353,12 +2296,12 @@ static void gdth_next(gdth_ha_str *ha)
+ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
+                                     char *buffer, ushort count)
+ {
+-    ushort cpcount,i, max_sg = gdth_sg_count(scp);
++    ushort cpcount,i, max_sg = scsi_sg_count(scp);
+     ushort cpsum,cpnow;
+     struct scatterlist *sl;
+     char *address;
+ 
+-    cpcount = min_t(ushort, count, gdth_bufflen(scp));
++    cpcount = min_t(ushort, count, scsi_bufflen(scp));
+ 
+     if (cpcount) {
+         cpsum=0;
+@@ -2366,7 +2309,7 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
+             unsigned long flags;
+             cpnow = (ushort)sl->length;
+             TRACE(("copy_internal() now %d sum %d count %d %d\n",
+-                          cpnow, cpsum, cpcount, gdth_bufflen(scp)));
++                          cpnow, cpsum, cpcount, scsi_bufflen(scp)));
+             if (cpsum+cpnow > cpcount) 
+                 cpnow = cpcount - cpsum;
+             cpsum += cpnow;
+@@ -2589,10 +2532,10 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive)
+             cmdp->u.cache.BlockCnt = blockcnt;
+         }
+ 
+-        if (gdth_bufflen(scp)) {
++        if (scsi_bufflen(scp)) {
+             cmndinfo->dma_dir = (read_write == 1 ?
+                 PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);   
+-            sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
++            sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
+                                cmndinfo->dma_dir);
+             if (mode64) {
+                 struct scatterlist *sl;
+@@ -2739,7 +2682,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
+             cmdp->u.raw64.lun        = l;
+             cmdp->u.raw64.bus        = b;
+             cmdp->u.raw64.priority   = 0;
+-            cmdp->u.raw64.sdlen      = gdth_bufflen(scp);
++            cmdp->u.raw64.sdlen      = scsi_bufflen(scp);
+             cmdp->u.raw64.sense_len  = 16;
+             cmdp->u.raw64.sense_data = sense_paddr;
+             cmdp->u.raw64.direction  = 
+@@ -2756,7 +2699,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
+             cmdp->u.raw.bus        = b;
+             cmdp->u.raw.priority   = 0;
+             cmdp->u.raw.link_p     = 0;
+-            cmdp->u.raw.sdlen      = gdth_bufflen(scp);
++            cmdp->u.raw.sdlen      = scsi_bufflen(scp);
+             cmdp->u.raw.sense_len  = 16;
+             cmdp->u.raw.sense_data = sense_paddr;
+             cmdp->u.raw.direction  = 
+@@ -2765,9 +2708,9 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
+             cmdp->u.raw.sg_ranz    = 0;
+         }
+ 
+-        if (gdth_bufflen(scp)) {
++        if (scsi_bufflen(scp)) {
+             cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL;
+-            sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
++            sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
+                                cmndinfo->dma_dir);
+             if (mode64) {
+                 struct scatterlist *sl;
+@@ -3388,8 +3331,8 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
+             /* retry */
+             return 2;
+         }
+-        if (gdth_bufflen(scp))
+-            pci_unmap_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
++        if (scsi_bufflen(scp))
++            pci_unmap_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
+                          cmndinfo->dma_dir);
+ 
+         if (cmndinfo->sense_paddr)
+@@ -4031,10 +3974,6 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
+     gdth_update_timeout(scp, scp->timeout_per_command * 6);
+     cmndinfo->priority = DEFAULT_PRI;
+ 
+-    gdth_set_bufflen(scp, scsi_bufflen(scp));
+-    gdth_set_sg_count(scp, scsi_sg_count(scp));
+-    gdth_set_sglist(scp, scsi_sglist(scp));
+-
+     return __gdth_queuecommand(ha, scp, cmndinfo);
+ }
+ 
+@@ -4955,12 +4894,16 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)
+ #endif /* CONFIG_EISA */
+ 
+ #ifdef CONFIG_PCI
+-static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
++static int gdth_pci_probe_one(gdth_pci_str *pcistr,
++			     gdth_ha_str **ha_out)
+ {
+ 	struct Scsi_Host *shp;
+ 	gdth_ha_str *ha;
+ 	dma_addr_t scratch_dma_handle = 0;
+ 	int error, i;
++	struct pci_dev *pdev = pcistr->pdev;
++
++	*ha_out = NULL;
+ 
+ 	shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
+ 	if (!shp)
+@@ -4968,13 +4911,13 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+ 	ha = shost_priv(shp);
+ 
+ 	error = -ENODEV;
+-	if (!gdth_init_pci(&pcistr[ctr],ha))
++	if (!gdth_init_pci(pdev, pcistr, ha))
+ 		goto out_host_put;
+ 
+ 	/* controller found and initialized */
+ 	printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
+-		pcistr[ctr].pdev->bus->number,
+-		PCI_SLOT(pcistr[ctr].pdev->devfn),
++		pdev->bus->number,
++		PCI_SLOT(pdev->devfn),
+ 		ha->irq);
+ 
+ 	error = request_irq(ha->irq, gdth_interrupt,
+@@ -5019,7 +4962,7 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+ 
+ 	ha->scratch_busy = FALSE;
+ 	ha->req_first = NULL;
+-	ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
++	ha->tid_cnt = pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
+ 	if (max_ids > 0 && max_ids < ha->tid_cnt)
+ 		ha->tid_cnt = max_ids;
+ 	for (i = 0; i < GDTH_MAXCMDS; ++i)
+@@ -5039,16 +4982,16 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+ 	/* 64-bit DMA only supported from FW >= x.43 */
+ 	if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) ||
+ 	    !ha->dma64_support) {
+-		if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
++		if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ 			printk(KERN_WARNING "GDT-PCI %d: "
+ 				"Unable to set 32-bit DMA\n", ha->hanum);
+ 				goto out_free_coal_stat;
+ 		}
+ 	} else {
+ 		shp->max_cmd_len = 16;
+-		if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
++		if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ 			printk("GDT-PCI %d: 64-bit DMA enabled\n", ha->hanum);
+-		} else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
++		} else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ 			printk(KERN_WARNING "GDT-PCI %d: "
+ 				"Unable to set 64/32-bit DMA\n", ha->hanum);
+ 			goto out_free_coal_stat;
+@@ -5062,13 +5005,17 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+ 	spin_lock_init(&ha->smp_lock);
+ 	gdth_enable_int(ha);
+ 
+-	error = scsi_add_host(shp, &pcistr[ctr].pdev->dev);
++	error = scsi_add_host(shp, &pdev->dev);
+ 	if (error)
+ 		goto out_free_coal_stat;
+ 	list_add_tail(&ha->list, &gdth_instances);
+ 
++	pci_set_drvdata(ha->pdev, ha);
++
+ 	scsi_scan_host(shp);
+ 
++	*ha_out = ha;
++
+ 	return 0;
+ 
+  out_free_coal_stat:
+@@ -5185,16 +5132,8 @@ static int __init gdth_init(void)
+ 
+ #ifdef CONFIG_PCI
+ 	/* scanning for PCI controllers */
+-	{
+-		gdth_pci_str pcistr[MAXHA];
+-		int cnt,ctr;
+-
+-		cnt = gdth_search_pci(pcistr);
+-		printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt);
+-		gdth_sort_pci(pcistr,cnt);
+-		for (ctr = 0; ctr < cnt; ++ctr)
+-			gdth_pci_probe_one(pcistr, ctr);
+-	}
++	if (pci_register_driver(&gdth_pci_driver) == 0)
++		gdth_pci_registered = true;
+ #endif /* CONFIG_PCI */
+ 
+ 	TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count));
+@@ -5227,6 +5166,11 @@ static void __exit gdth_exit(void)
+ 	del_timer_sync(&gdth_timer);
+ #endif
+ 
++#ifdef CONFIG_PCI
++	if (gdth_pci_registered)
++		pci_unregister_driver(&gdth_pci_driver);
++#endif
++
+ 	list_for_each_entry(ha, &gdth_instances, list)
+ 		gdth_remove_one(ha);
+ }
+diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
+index 26e4e92..ca92476 100644
+--- a/drivers/scsi/gdth.h
++++ b/drivers/scsi/gdth.h
+@@ -839,8 +839,6 @@ typedef struct {
+     struct pci_dev      *pdev;
+     ulong               dpmem;                  /* DPRAM address */
+     ulong               io;                     /* IO address */
+-    ulong               io_mm;                  /* IO address mem. mapped */
+-    unchar              irq;                    /* IRQ */
+ } gdth_pci_str;
+ 
+ 
+diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
+index 91f8522..ca73637 100644
+--- a/drivers/scsi/gvp11.c
++++ b/drivers/scsi/gvp11.c
+@@ -322,6 +322,9 @@ int __init gvp11_detect(struct scsi_host_template *tpnt)
+ 	 */
+ 	regs.SASR = &(DMA(instance)->SASR);
+ 	regs.SCMD = &(DMA(instance)->SCMD);
++	HDATA(instance)->no_sync = 0xff;
++	HDATA(instance)->fast = 0;
++	HDATA(instance)->dma_mode = CTRL_DMA;
+ 	wd33c93_init(instance, regs, dma_setup, dma_stop,
+ 		     (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
+ 					     : WD33C93_FS_12_15);
+diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
+index ed7e0a1..c264a8c 100644
+--- a/drivers/scsi/hosts.c
++++ b/drivers/scsi/hosts.c
+@@ -43,14 +43,14 @@
+ static int scsi_host_next_hn;		/* host_no for next new host */
+ 
+ 
+-static void scsi_host_cls_release(struct class_device *class_dev)
++static void scsi_host_cls_release(struct device *dev)
+ {
+-	put_device(&class_to_shost(class_dev)->shost_gendev);
++	put_device(&class_to_shost(dev)->shost_gendev);
+ }
+ 
+ static struct class shost_class = {
+ 	.name		= "scsi_host",
+-	.release	= scsi_host_cls_release,
++	.dev_release	= scsi_host_cls_release,
+ };
+ 
+ /**
+@@ -174,7 +174,7 @@ void scsi_remove_host(struct Scsi_Host *shost)
+ 	spin_unlock_irqrestore(shost->host_lock, flags);
+ 
+ 	transport_unregister_device(&shost->shost_gendev);
+-	class_device_unregister(&shost->shost_classdev);
++	device_unregister(&shost->shost_dev);
+ 	device_del(&shost->shost_gendev);
+ 	scsi_proc_hostdir_rm(shost->hostt);
+ }
+@@ -212,7 +212,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
+ 	scsi_host_set_state(shost, SHOST_RUNNING);
+ 	get_device(shost->shost_gendev.parent);
+ 
+-	error = class_device_add(&shost->shost_classdev);
++	error = device_add(&shost->shost_dev);
+ 	if (error)
+ 		goto out_del_gendev;
+ 
+@@ -223,7 +223,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
+ 					 GFP_KERNEL);
+ 		if (shost->shost_data == NULL) {
+ 			error = -ENOMEM;
+-			goto out_del_classdev;
++			goto out_del_dev;
+ 		}
+ 	}
+ 
+@@ -250,8 +250,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
+ 		destroy_workqueue(shost->work_q);
+  out_free_shost_data:
+ 	kfree(shost->shost_data);
+- out_del_classdev:
+-	class_device_del(&shost->shost_classdev);
++ out_del_dev:
++	device_del(&shost->shost_dev);
+  out_del_gendev:
+ 	device_del(&shost->shost_gendev);
+  out:
+@@ -347,7 +347,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
+ 	shost->unchecked_isa_dma = sht->unchecked_isa_dma;
+ 	shost->use_clustering = sht->use_clustering;
+ 	shost->ordered_tag = sht->ordered_tag;
+-	shost->active_mode = sht->supported_mode;
+ 
+ 	if (sht->supported_mode == MODE_UNKNOWN)
+ 		/* means we didn't set it ... default to INITIATOR */
+@@ -386,11 +385,11 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
+ 		shost->host_no);
+ 	shost->shost_gendev.release = scsi_host_dev_release;
+ 
+-	class_device_initialize(&shost->shost_classdev);
+-	shost->shost_classdev.dev = &shost->shost_gendev;
+-	shost->shost_classdev.class = &shost_class;
+-	snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
+-		  shost->host_no);
++	device_initialize(&shost->shost_dev);
++	shost->shost_dev.parent = &shost->shost_gendev;
++	shost->shost_dev.class = &shost_class;
++	snprintf(shost->shost_dev.bus_id, BUS_ID_SIZE, "host%d",
++		 shost->host_no);
+ 
+ 	shost->ehandler = kthread_run(scsi_error_handler, shost,
+ 			"scsi_eh_%d", shost->host_no);
+@@ -433,12 +432,12 @@ void scsi_unregister(struct Scsi_Host *shost)
+ }
+ EXPORT_SYMBOL(scsi_unregister);
+ 
+-static int __scsi_host_match(struct class_device *cdev, void *data)
++static int __scsi_host_match(struct device *dev, void *data)
+ {
+ 	struct Scsi_Host *p;
+ 	unsigned short *hostnum = (unsigned short *)data;
+ 
+-	p = class_to_shost(cdev);
++	p = class_to_shost(dev);
+ 	return p->host_no == *hostnum;
+ }
+ 
+@@ -451,10 +450,10 @@ static int __scsi_host_match(struct class_device *cdev, void *data)
+  **/
+ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
+ {
+-	struct class_device *cdev;
++	struct device *cdev;
+ 	struct Scsi_Host *shost = ERR_PTR(-ENXIO);
+ 
+-	cdev = class_find_child(&shost_class, &hostnum, __scsi_host_match);
++	cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match);
+ 	if (cdev)
+ 		shost = scsi_host_get(class_to_shost(cdev));
+ 
+diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
+index ff149ad..5b7be1e 100644
+--- a/drivers/scsi/hptiop.c
++++ b/drivers/scsi/hptiop.c
+@@ -338,7 +338,8 @@ static int iop_get_config_mv(struct hptiop_hba *hba,
+ 	req->header.size =
+ 		cpu_to_le32(sizeof(struct hpt_iop_request_get_config));
+ 	req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
+-	req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_GET_CONFIG<<5);
++	req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG<<5);
++	req->header.context_hi32 = 0;
+ 
+ 	if (iop_send_sync_request_mv(hba, 0, 20000)) {
+ 		dprintk("Get config send cmd failed\n");
+@@ -392,7 +393,8 @@ static int iop_set_config_mv(struct hptiop_hba *hba,
+ 	req->header.size =
+ 		cpu_to_le32(sizeof(struct hpt_iop_request_set_config));
+ 	req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
+-	req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_SET_CONFIG<<5);
++	req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);
++	req->header.context_hi32 = 0;
+ 
+ 	if (iop_send_sync_request_mv(hba, 0, 20000)) {
+ 		dprintk("Set config send cmd failed\n");
+@@ -857,14 +859,16 @@ static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
+ 	return queue_depth;
+ }
+ 
+-static ssize_t hptiop_show_version(struct class_device *class_dev, char *buf)
++static ssize_t hptiop_show_version(struct device *dev,
++				   struct device_attribute *attr, char *buf)
+ {
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", driver_ver);
+ }
+ 
+-static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf)
++static ssize_t hptiop_show_fw_version(struct device *dev,
++				      struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(class_dev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
+@@ -874,7 +878,7 @@ static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf)
+ 				hba->firmware_version & 0xff);
+ }
+ 
+-static struct class_device_attribute hptiop_attr_version = {
++static struct device_attribute hptiop_attr_version = {
+ 	.attr = {
+ 		.name = "driver-version",
+ 		.mode = S_IRUGO,
+@@ -882,7 +886,7 @@ static struct class_device_attribute hptiop_attr_version = {
+ 	.show = hptiop_show_version,
+ };
+ 
+-static struct class_device_attribute hptiop_attr_fw_version = {
++static struct device_attribute hptiop_attr_fw_version = {
+ 	.attr = {
+ 		.name = "firmware-version",
+ 		.mode = S_IRUGO,
+@@ -890,7 +894,7 @@ static struct class_device_attribute hptiop_attr_fw_version = {
+ 	.show = hptiop_show_fw_version,
+ };
+ 
+-static struct class_device_attribute *hptiop_attrs[] = {
++static struct device_attribute *hptiop_attrs[] = {
+ 	&hptiop_attr_version,
+ 	&hptiop_attr_fw_version,
+ 	NULL
+@@ -903,7 +907,6 @@ static struct scsi_host_template driver_template = {
+ 	.eh_device_reset_handler    = hptiop_reset,
+ 	.eh_bus_reset_handler       = hptiop_reset,
+ 	.info                       = hptiop_info,
+-	.unchecked_isa_dma          = 0,
+ 	.emulated                   = 0,
+ 	.use_clustering             = ENABLE_CLUSTERING,
+ 	.proc_name                  = driver_name,
+diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
+index 78d46a9..4a922c5 100644
+--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
+@@ -1456,9 +1456,10 @@ static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
+ /* ------------------------------------------------------------
+  * sysfs attributes
+  */
+-static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf)
++static ssize_t show_host_srp_version(struct device *dev,
++				     struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ 	int len;
+ 
+@@ -1467,7 +1468,7 @@ static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf)
+ 	return len;
+ }
+ 
+-static struct class_device_attribute ibmvscsi_host_srp_version = {
++static struct device_attribute ibmvscsi_host_srp_version = {
+ 	.attr = {
+ 		 .name = "srp_version",
+ 		 .mode = S_IRUGO,
+@@ -1475,10 +1476,11 @@ static struct class_device_attribute ibmvscsi_host_srp_version = {
+ 	.show = show_host_srp_version,
+ };
+ 
+-static ssize_t show_host_partition_name(struct class_device *class_dev,
++static ssize_t show_host_partition_name(struct device *dev,
++					struct device_attribute *attr,
+ 					char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ 	int len;
+ 
+@@ -1487,7 +1489,7 @@ static ssize_t show_host_partition_name(struct class_device *class_dev,
+ 	return len;
+ }
+ 
+-static struct class_device_attribute ibmvscsi_host_partition_name = {
++static struct device_attribute ibmvscsi_host_partition_name = {
+ 	.attr = {
+ 		 .name = "partition_name",
+ 		 .mode = S_IRUGO,
+@@ -1495,10 +1497,11 @@ static struct class_device_attribute ibmvscsi_host_partition_name = {
+ 	.show = show_host_partition_name,
+ };
+ 
+-static ssize_t show_host_partition_number(struct class_device *class_dev,
++static ssize_t show_host_partition_number(struct device *dev,
++					  struct device_attribute *attr,
+ 					  char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ 	int len;
+ 
+@@ -1507,7 +1510,7 @@ static ssize_t show_host_partition_number(struct class_device *class_dev,
+ 	return len;
+ }
+ 
+-static struct class_device_attribute ibmvscsi_host_partition_number = {
++static struct device_attribute ibmvscsi_host_partition_number = {
+ 	.attr = {
+ 		 .name = "partition_number",
+ 		 .mode = S_IRUGO,
+@@ -1515,9 +1518,10 @@ static struct class_device_attribute ibmvscsi_host_partition_number = {
+ 	.show = show_host_partition_number,
+ };
+ 
+-static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf)
++static ssize_t show_host_mad_version(struct device *dev,
++				     struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ 	int len;
+ 
+@@ -1526,7 +1530,7 @@ static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf)
+ 	return len;
+ }
+ 
+-static struct class_device_attribute ibmvscsi_host_mad_version = {
++static struct device_attribute ibmvscsi_host_mad_version = {
+ 	.attr = {
+ 		 .name = "mad_version",
+ 		 .mode = S_IRUGO,
+@@ -1534,9 +1538,10 @@ static struct class_device_attribute ibmvscsi_host_mad_version = {
+ 	.show = show_host_mad_version,
+ };
+ 
+-static ssize_t show_host_os_type(struct class_device *class_dev, char *buf)
++static ssize_t show_host_os_type(struct device *dev,
++				 struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ 	int len;
+ 
+@@ -1544,7 +1549,7 @@ static ssize_t show_host_os_type(struct class_device *class_dev, char *buf)
+ 	return len;
+ }
+ 
+-static struct class_device_attribute ibmvscsi_host_os_type = {
++static struct device_attribute ibmvscsi_host_os_type = {
+ 	.attr = {
+ 		 .name = "os_type",
+ 		 .mode = S_IRUGO,
+@@ -1552,9 +1557,10 @@ static struct class_device_attribute ibmvscsi_host_os_type = {
+ 	.show = show_host_os_type,
+ };
+ 
+-static ssize_t show_host_config(struct class_device *class_dev, char *buf)
++static ssize_t show_host_config(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ 
+ 	/* returns null-terminated host config data */
+@@ -1564,7 +1570,7 @@ static ssize_t show_host_config(struct class_device *class_dev, char *buf)
+ 		return 0;
+ }
+ 
+-static struct class_device_attribute ibmvscsi_host_config = {
++static struct device_attribute ibmvscsi_host_config = {
+ 	.attr = {
+ 		 .name = "config",
+ 		 .mode = S_IRUGO,
+@@ -1572,7 +1578,7 @@ static struct class_device_attribute ibmvscsi_host_config = {
+ 	.show = show_host_config,
+ };
+ 
+-static struct class_device_attribute *ibmvscsi_attrs[] = {
++static struct device_attribute *ibmvscsi_attrs[] = {
+ 	&ibmvscsi_host_srp_version,
+ 	&ibmvscsi_host_partition_name,
+ 	&ibmvscsi_host_partition_number,
+diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
+index e5881e9..3b9514c 100644
+--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
++++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
+@@ -780,32 +780,35 @@ static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id,
+ 	return 0;
+ }
+ 
+-static ssize_t system_id_show(struct class_device *cdev, char *buf)
++static ssize_t system_id_show(struct device *dev,
++			      struct device_attribute *attr, char *buf)
+ {
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", system_id);
+ }
+ 
+-static ssize_t partition_number_show(struct class_device *cdev, char *buf)
++static ssize_t partition_number_show(struct device *dev,
++				     struct device_attribute *attr, char *buf)
+ {
+ 	return snprintf(buf, PAGE_SIZE, "%x\n", partition_number);
+ }
+ 
+-static ssize_t unit_address_show(struct class_device *cdev, char *buf)
++static ssize_t unit_address_show(struct device *dev,
++				  struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(cdev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct srp_target *target = host_to_srp_target(shost);
+ 	struct vio_port *vport = target_to_port(target);
+ 	return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address);
+ }
+ 
+-static CLASS_DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL);
+-static CLASS_DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL);
+-static CLASS_DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL);
++static DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL);
++static DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL);
++static DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL);
+ 
+-static struct class_device_attribute *ibmvstgt_attrs[] = {
+-	&class_device_attr_system_id,
+-	&class_device_attr_partition_number,
+-	&class_device_attr_unit_address,
++static struct device_attribute *ibmvstgt_attrs[] = {
++	&dev_attr_system_id,
++	&dev_attr_partition_number,
++	&dev_attr_unit_address,
+ 	NULL,
+ };
+ 
+diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
+index 68e5c63..93c3fc2 100644
+--- a/drivers/scsi/ide-scsi.c
++++ b/drivers/scsi/ide-scsi.c
+@@ -60,31 +60,6 @@
+ 
+ #define IDESCSI_DEBUG_LOG		0
+ 
+-typedef struct idescsi_pc_s {
+-	u8 c[12];				/* Actual packet bytes */
+-	int request_transfer;			/* Bytes to transfer */
+-	int actually_transferred;		/* Bytes actually transferred */
+-	int buffer_size;			/* Size of our data buffer */
+-	struct request *rq;			/* The corresponding request */
+-	u8 *buffer;				/* Data buffer */
+-	u8 *current_position;			/* Pointer into the above buffer */
+-	struct scatterlist *sg;			/* Scatter gather table */
+-	unsigned int sg_cnt;			/* Number of entries in sg */
+-	int b_count;				/* Bytes transferred from current entry */
+-	struct scsi_cmnd *scsi_cmd;		/* SCSI command */
+-	void (*done)(struct scsi_cmnd *);	/* Scsi completion routine */
+-	unsigned long flags;			/* Status/Action flags */
+-	unsigned long timeout;			/* Command timeout */
+-} idescsi_pc_t;
+-
+-/*
+- *	Packet command status bits.
+- */
+-#define PC_DMA_IN_PROGRESS		0	/* 1 while DMA in progress */
+-#define PC_WRITING			1	/* Data direction */
+-#define PC_TIMEDOUT			3	/* command timed out */
+-#define PC_DMA_OK			4	/* Use DMA */
+-
+ /*
+  *	SCSI command transformation layer
+  */
+@@ -101,14 +76,15 @@ typedef struct ide_scsi_obj {
+ 	struct gendisk		*disk;
+ 	struct Scsi_Host	*host;
+ 
+-	idescsi_pc_t *pc;			/* Current packet command */
++	struct ide_atapi_pc *pc;		/* Current packet command */
+ 	unsigned long flags;			/* Status/Action flags */
+ 	unsigned long transform;		/* SCSI cmd translation layer */
+ 	unsigned long log;			/* log flags */
+ } idescsi_scsi_t;
+ 
+ static DEFINE_MUTEX(idescsi_ref_mutex);
+-static int idescsi_nocd;			/* Set by module param to skip cd */
++/* Set by module param to skip cd */
++static int idescsi_nocd;
+ 
+ #define ide_scsi_g(disk) \
+ 	container_of((disk)->private_data, struct ide_scsi_obj, driver)
+@@ -152,22 +128,11 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
+  */
+ #define IDESCSI_PC_RQ			90
+ 
+-static void idescsi_discard_data (ide_drive_t *drive, unsigned int bcount)
+-{
+-	while (bcount--)
+-		(void) HWIF(drive)->INB(IDE_DATA_REG);
+-}
+-
+-static void idescsi_output_zeros (ide_drive_t *drive, unsigned int bcount)
+-{
+-	while (bcount--)
+-		HWIF(drive)->OUTB(0, IDE_DATA_REG);
+-}
+-
+ /*
+  *	PIO data transfer routines using the scatter gather table.
+  */
+-static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
++static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
++		unsigned int bcount)
+ {
+ 	int count;
+ 	char *buf;
+@@ -200,11 +165,12 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne
+ 
+ 	if (bcount) {
+ 		printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
+-		idescsi_discard_data (drive, bcount);
++		ide_atapi_discard_data(drive, bcount);
+ 	}
+ }
+ 
+-static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
++static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
++		unsigned int bcount)
+ {
+ 	int count;
+ 	char *buf;
+@@ -237,7 +203,7 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
+ 
+ 	if (bcount) {
+ 		printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
+-		idescsi_output_zeros (drive, bcount);
++		ide_atapi_write_zeros(drive, bcount);
+ 	}
+ }
+ 
+@@ -246,15 +212,16 @@ static void ide_scsi_hex_dump(u8 *data, int len)
+ 	print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0);
+ }
+ 
+-static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_command)
++static int idescsi_check_condition(ide_drive_t *drive,
++		struct request *failed_cmd)
+ {
+ 	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+-	idescsi_pc_t   *pc;
++	struct ide_atapi_pc   *pc;
+ 	struct request *rq;
+ 	u8             *buf;
+ 
+ 	/* stuff a sense request in front of our current request */
+-	pc = kzalloc(sizeof(idescsi_pc_t), GFP_ATOMIC);
++	pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
+ 	rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+ 	buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
+ 	if (!pc || !rq || !buf) {
+@@ -266,14 +233,14 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
+ 	ide_init_drive_cmd(rq);
+ 	rq->special = (char *) pc;
+ 	pc->rq = rq;
+-	pc->buffer = buf;
++	pc->buf = buf;
+ 	pc->c[0] = REQUEST_SENSE;
+-	pc->c[4] = pc->request_transfer = pc->buffer_size = SCSI_SENSE_BUFFERSIZE;
++	pc->c[4] = pc->req_xfer = pc->buf_size = SCSI_SENSE_BUFFERSIZE;
+ 	rq->cmd_type = REQ_TYPE_SENSE;
+ 	pc->timeout = jiffies + WAIT_READY;
+ 	/* NOTE! Save the failed packet command in "rq->buffer" */
+-	rq->buffer = (void *) failed_command->special;
+-	pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd;
++	rq->buffer = (void *) failed_cmd->special;
++	pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;
+ 	if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
+ 		printk ("ide-scsi: %s: queue cmd = ", drive->name);
+ 		ide_scsi_hex_dump(pc->c, 6);
+@@ -287,9 +254,12 @@ static int idescsi_end_request(ide_drive_t *, int, int);
+ static ide_startstop_t
+ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
+ {
++	ide_hwif_t *hwif = drive->hwif;
++
+ 	if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ 		/* force an abort */
+-		HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
++		hwif->OUTB(WIN_IDLEIMMEDIATE,
++			   hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 
+ 	rq->errors++;
+ 
+@@ -303,7 +273,7 @@ idescsi_atapi_abort(ide_drive_t *drive, struct request *rq)
+ {
+ #if IDESCSI_DEBUG_LOG
+ 	printk(KERN_WARNING "idescsi_atapi_abort called for %lu\n",
+-			((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number);
++		((struct ide_atapi_pc *) rq->special)->scsi_cmd->serial_number);
+ #endif
+ 	rq->errors |= ERROR_MAX;
+ 
+@@ -316,7 +286,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
+ {
+ 	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+ 	struct request *rq = HWGROUP(drive)->rq;
+-	idescsi_pc_t *pc = (idescsi_pc_t *) rq->special;
++	struct ide_atapi_pc *pc = (struct ide_atapi_pc *) rq->special;
+ 	int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
+ 	struct Scsi_Host *host;
+ 	int errors = rq->errors;
+@@ -328,20 +298,23 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
+ 	}
+ 	ide_end_drive_cmd (drive, 0, 0);
+ 	if (blk_sense_request(rq)) {
+-		idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer;
++		struct ide_atapi_pc *opc = (struct ide_atapi_pc *) rq->buffer;
+ 		if (log) {
+ 			printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
+-			ide_scsi_hex_dump(pc->buffer, 16);
++			ide_scsi_hex_dump(pc->buf, 16);
+ 		}
+-		memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE);
+-		kfree(pc->buffer);
++		memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buf,
++			SCSI_SENSE_BUFFERSIZE);
++		kfree(pc->buf);
+ 		kfree(pc);
+ 		kfree(rq);
+ 		pc = opc;
+ 		rq = pc->rq;
+ 		pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
+-					((test_bit(PC_TIMEDOUT, &pc->flags)?DID_TIME_OUT:DID_OK) << 16);
+-	} else if (test_bit(PC_TIMEDOUT, &pc->flags)) {
++				(((pc->flags & PC_FLAG_TIMEDOUT) ?
++				  DID_TIME_OUT :
++				  DID_OK) << 16);
++	} else if (pc->flags & PC_FLAG_TIMEDOUT) {
+ 		if (log)
+ 			printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",
+ 					drive->name, pc->scsi_cmd->serial_number);
+@@ -370,7 +343,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
+ 	return 0;
+ }
+ 
+-static inline unsigned long get_timeout(idescsi_pc_t *pc)
++static inline unsigned long get_timeout(struct ide_atapi_pc *pc)
+ {
+ 	return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies);
+ }
+@@ -378,12 +351,12 @@ static inline unsigned long get_timeout(idescsi_pc_t *pc)
+ static int idescsi_expiry(ide_drive_t *drive)
+ {
+ 	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+-	idescsi_pc_t   *pc   = scsi->pc;
++	struct ide_atapi_pc   *pc   = scsi->pc;
+ 
+ #if IDESCSI_DEBUG_LOG
+ 	printk(KERN_WARNING "idescsi_expiry called for %lu at %lu\n", pc->scsi_cmd->serial_number, jiffies);
+ #endif
+-	set_bit(PC_TIMEDOUT, &pc->flags);
++	pc->flags |= PC_FLAG_TIMEDOUT;
+ 
+ 	return 0;					/* we do not want the ide subsystem to retry */
+ }
+@@ -395,7 +368,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ {
+ 	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+ 	ide_hwif_t *hwif = drive->hwif;
+-	idescsi_pc_t *pc = scsi->pc;
++	struct ide_atapi_pc *pc = scsi->pc;
+ 	struct request *rq = pc->rq;
+ 	unsigned int temp;
+ 	u16 bcount;
+@@ -405,7 +378,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ 	printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n");
+ #endif /* IDESCSI_DEBUG_LOG */
+ 
+-	if (test_bit(PC_TIMEDOUT, &pc->flags)){
++	if (pc->flags & PC_FLAG_TIMEDOUT) {
+ #if IDESCSI_DEBUG_LOG
+ 		printk(KERN_WARNING "idescsi_pc_intr: got timed out packet  %lu at %lu\n",
+ 				pc->scsi_cmd->serial_number, jiffies);
+@@ -414,11 +387,12 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ 		idescsi_end_request (drive, 1, 0);
+ 		return ide_stopped;
+ 	}
+-	if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
++	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
++		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+ #if IDESCSI_DEBUG_LOG
+ 		printk ("ide-scsi: %s: DMA complete\n", drive->name);
+ #endif /* IDESCSI_DEBUG_LOG */
+-		pc->actually_transferred=pc->request_transfer;
++		pc->xferred = pc->req_xfer;
+ 		(void) HWIF(drive)->ide_dma_end(drive);
+ 	}
+ 
+@@ -428,42 +402,44 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ 	if ((stat & DRQ_STAT) == 0) {
+ 		/* No more interrupts */
+ 		if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+-			printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
++			printk(KERN_INFO "Packet command completed, %d bytes"
++					" transferred\n", pc->xferred);
+ 		local_irq_enable_in_hardirq();
+ 		if (stat & ERR_STAT)
+ 			rq->errors++;
+ 		idescsi_end_request (drive, 1, 0);
+ 		return ide_stopped;
+ 	}
+-	bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
+-		  hwif->INB(IDE_BCOUNTL_REG);
+-	ireason = hwif->INB(IDE_IREASON_REG);
++	bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
++		  hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
++	ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ 
+ 	if (ireason & CD) {
+ 		printk(KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n");
+ 		return ide_do_reset (drive);
+ 	}
+ 	if (ireason & IO) {
+-		temp = pc->actually_transferred + bcount;
+-		if (temp > pc->request_transfer) {
+-			if (temp > pc->buffer_size) {
++		temp = pc->xferred + bcount;
++		if (temp > pc->req_xfer) {
++			if (temp > pc->buf_size) {
+ 				printk(KERN_ERR "ide-scsi: The scsi wants to "
+ 					"send us more data than expected "
+ 					"- discarding data\n");
+-				temp = pc->buffer_size - pc->actually_transferred;
++				temp = pc->buf_size - pc->xferred;
+ 				if (temp) {
+-					clear_bit(PC_WRITING, &pc->flags);
++					pc->flags &= ~PC_FLAG_WRITING;
+ 					if (pc->sg)
+-						idescsi_input_buffers(drive, pc, temp);
++						idescsi_input_buffers(drive, pc,
++									temp);
+ 					else
+-						drive->hwif->atapi_input_bytes(drive, pc->current_position, temp);
++						drive->hwif->atapi_input_bytes(drive, pc->cur_pos, temp);
+ 					printk(KERN_ERR "ide-scsi: transferred"
+ 							" %d of %d bytes\n",
+ 							temp, bcount);
+ 				}
+-				pc->actually_transferred += temp;
+-				pc->current_position += temp;
+-				idescsi_discard_data(drive, bcount - temp);
++				pc->xferred += temp;
++				pc->cur_pos += temp;
++				ide_atapi_discard_data(drive, bcount - temp);
+ 				ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
+ 				return ide_started;
+ 			}
+@@ -473,23 +449,23 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ 		}
+ 	}
+ 	if (ireason & IO) {
+-		clear_bit(PC_WRITING, &pc->flags);
++		pc->flags &= ~PC_FLAG_WRITING;
+ 		if (pc->sg)
+ 			idescsi_input_buffers(drive, pc, bcount);
+ 		else
+-			hwif->atapi_input_bytes(drive, pc->current_position,
++			hwif->atapi_input_bytes(drive, pc->cur_pos,
+ 						bcount);
+ 	} else {
+-		set_bit(PC_WRITING, &pc->flags);
++		pc->flags |= PC_FLAG_WRITING;
+ 		if (pc->sg)
+ 			idescsi_output_buffers(drive, pc, bcount);
+ 		else
+-			hwif->atapi_output_bytes(drive, pc->current_position,
++			hwif->atapi_output_bytes(drive, pc->cur_pos,
+ 						 bcount);
+ 	}
+ 	/* Update the current position */
+-	pc->actually_transferred += bcount;
+-	pc->current_position += bcount;
++	pc->xferred += bcount;
++	pc->cur_pos += bcount;
+ 
+ 	/* And set the interrupt handler again */
+ 	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
+@@ -500,7 +476,7 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+-	idescsi_pc_t *pc = scsi->pc;
++	struct ide_atapi_pc *pc = scsi->pc;
+ 	ide_startstop_t startstop;
+ 	u8 ireason;
+ 
+@@ -509,7 +485,7 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
+ 			"initiated yet DRQ isn't asserted\n");
+ 		return startstop;
+ 	}
+-	ireason = hwif->INB(IDE_IREASON_REG);
++	ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ 	if ((ireason & CD) == 0 || (ireason & IO)) {
+ 		printk(KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while "
+ 				"issuing a packet command\n");
+@@ -520,34 +496,34 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
+ 	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
+ 	/* Send the actual packet */
+ 	drive->hwif->atapi_output_bytes(drive, scsi->pc->c, 12);
+-	if (test_bit (PC_DMA_OK, &pc->flags)) {
+-		set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
++	if (pc->flags & PC_FLAG_DMA_OK) {
++		pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
+ 		hwif->dma_start(drive);
+ 	}
+ 	return ide_started;
+ }
+ 
+-static inline int idescsi_set_direction(idescsi_pc_t *pc)
++static inline int idescsi_set_direction(struct ide_atapi_pc *pc)
+ {
+ 	switch (pc->c[0]) {
+ 		case READ_6: case READ_10: case READ_12:
+-			clear_bit(PC_WRITING, &pc->flags);
++			pc->flags &= ~PC_FLAG_WRITING;
+ 			return 0;
+ 		case WRITE_6: case WRITE_10: case WRITE_12:
+-			set_bit(PC_WRITING, &pc->flags);
++			pc->flags |= PC_FLAG_WRITING;
+ 			return 0;
+ 		default:
+ 			return 1;
+ 	}
+ }
+ 
+-static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc)
++static int idescsi_map_sg(ide_drive_t *drive, struct ide_atapi_pc *pc)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	struct scatterlist *sg, *scsi_sg;
+ 	int segments;
+ 
+-	if (!pc->request_transfer || pc->request_transfer % 1024)
++	if (!pc->req_xfer || pc->req_xfer % 1024)
+ 		return 1;
+ 
+ 	if (idescsi_set_direction(pc))
+@@ -566,21 +542,21 @@ static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc)
+ 	return 0;
+ }
+ 
+-/*
+- *	Issue a packet command
+- */
+-static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc)
++static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
++		struct ide_atapi_pc *pc)
+ {
+ 	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	u16 bcount;
+ 	u8 dma = 0;
+ 
+-	scsi->pc=pc;							/* Set the current packet command */
+-	pc->actually_transferred=0;					/* We haven't transferred any data yet */
+-	pc->current_position=pc->buffer;
++	/* Set the current packet command */
++	scsi->pc = pc;
++	/* We haven't transferred any data yet */
++	pc->xferred = 0;
++	pc->cur_pos = pc->buf;
+ 	/* Request to transfer the entire buffer at once */
+-	bcount = min(pc->request_transfer, 63 * 1024);
++	bcount = min(pc->req_xfer, 63 * 1024);
+ 
+ 	if (drive->using_dma && !idescsi_map_sg(drive, pc)) {
+ 		hwif->sg_mapped = 1;
+@@ -591,7 +567,7 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc)
+ 	ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK, bcount, dma);
+ 
+ 	if (dma)
+-		set_bit(PC_DMA_OK, &pc->flags);
++		pc->flags |= PC_FLAG_DMA_OK;
+ 
+ 	if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
+ 		ide_execute_command(drive, WIN_PACKETCMD, &idescsi_transfer_pc,
+@@ -599,7 +575,7 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc)
+ 		return ide_started;
+ 	} else {
+ 		/* Issue the packet command */
+-		HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
++		hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ 		return idescsi_transfer_pc(drive);
+ 	}
+ }
+@@ -615,7 +591,8 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
+ #endif /* IDESCSI_DEBUG_LOG */
+ 
+ 	if (blk_sense_request(rq) || blk_special_request(rq)) {
+-		return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->special);
++		return idescsi_issue_pc(drive,
++				(struct ide_atapi_pc *) rq->special);
+ 	}
+ 	blk_dump_rq_flags(rq, "ide-scsi: unsup command");
+ 	idescsi_end_request (drive, 0, 0);
+@@ -773,15 +750,15 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
+ 	idescsi_scsi_t *scsi = scsihost_to_idescsi(host);
+ 	ide_drive_t *drive = scsi->drive;
+ 	struct request *rq = NULL;
+-	idescsi_pc_t *pc = NULL;
++	struct ide_atapi_pc *pc = NULL;
+ 
+ 	if (!drive) {
+ 		scmd_printk (KERN_ERR, cmd, "drive not present\n");
+ 		goto abort;
+ 	}
+ 	scsi = drive_to_idescsi(drive);
+-	pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC);
+-	rq = kmalloc (sizeof (struct request), GFP_ATOMIC);
++	pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
++	rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+ 	if (rq == NULL || pc == NULL) {
+ 		printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
+ 		goto abort;
+@@ -791,11 +768,11 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
+ 	pc->flags = 0;
+ 	pc->rq = rq;
+ 	memcpy (pc->c, cmd->cmnd, cmd->cmd_len);
+-	pc->buffer = NULL;
++	pc->buf = NULL;
+ 	pc->sg = scsi_sglist(cmd);
+ 	pc->sg_cnt = scsi_sg_count(cmd);
+ 	pc->b_count = 0;
+-	pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd);
++	pc->req_xfer = pc->buf_size = scsi_bufflen(cmd);
+ 	pc->scsi_cmd = cmd;
+ 	pc->done = done;
+ 	pc->timeout = jiffies + cmd->timeout_per_command;
+@@ -866,7 +843,7 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
+ 		printk (KERN_ERR "ide-scsi: cmd aborted!\n");
+ 
+ 		if (blk_sense_request(scsi->pc->rq))
+-			kfree(scsi->pc->buffer);
++			kfree(scsi->pc->buf);
+ 		kfree(scsi->pc->rq);
+ 		kfree(scsi->pc);
+ 		scsi->pc = NULL;
+@@ -916,7 +893,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
+ 	if (__blk_end_request(req, -EIO, 0))
+ 		BUG();
+ 	if (blk_sense_request(req))
+-		kfree(scsi->pc->buffer);
++		kfree(scsi->pc->buf);
+ 	kfree(scsi->pc);
+ 	scsi->pc = NULL;
+ 	kfree(req);
+diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
+index 0cc8868..dbae3fd 100644
+--- a/drivers/scsi/initio.c
++++ b/drivers/scsi/initio.c
+@@ -2581,8 +2581,8 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
+ 	/* Map the sense buffer into bus memory */
+ 	dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,
+ 				  SENSE_SIZE, DMA_FROM_DEVICE);
+-	cblk->senseptr = cpu_to_le32((u32)dma_addr);
+-	cblk->senselen = cpu_to_le32(SENSE_SIZE);
++	cblk->senseptr = (u32)dma_addr;
++	cblk->senselen = SENSE_SIZE;
+ 	cmnd->SCp.ptr = (char *)(unsigned long)dma_addr;
+ 	cblk->cdblen = cmnd->cmd_len;
+ 
+@@ -2606,7 +2606,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
+ 		dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],
+ 					  sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
+ 					  DMA_BIDIRECTIONAL);
+-		cblk->bufptr = cpu_to_le32((u32)dma_addr);
++		cblk->bufptr = (u32)dma_addr;
+ 		cmnd->SCp.dma_handle = dma_addr;
+ 
+ 		cblk->sglen = nseg;
+@@ -2616,7 +2616,8 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
+ 		sg = &cblk->sglist[0];
+ 		scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {
+ 			sg->data = cpu_to_le32((u32)sg_dma_address(sglist));
+-			total_len += sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
++			sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
++			total_len += sg_dma_len(sglist);
+ 			++sg;
+ 		}
+ 
+diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
+index c72014a..de5ae6a 100644
+--- a/drivers/scsi/ipr.c
++++ b/drivers/scsi/ipr.c
+@@ -2431,7 +2431,7 @@ restart:
+ 	}
+ 
+ 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+-	kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE);
++	kobject_uevent(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE);
+ 	LEAVE;
+ }
+ 
+@@ -2451,8 +2451,8 @@ static ssize_t ipr_read_trace(struct kobject *kobj,
+ 			      struct bin_attribute *bin_attr,
+ 			      char *buf, loff_t off, size_t count)
+ {
+-	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+-	struct Scsi_Host *shost = class_to_shost(cdev);
++	struct device *dev = container_of(kobj, struct device, kobj);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	unsigned long lock_flags = 0;
+ 	int size = IPR_TRACE_SIZE;
+@@ -2492,15 +2492,16 @@ static const struct {
+ 
+ /**
+  * ipr_show_write_caching - Show the write caching attribute
+- * @class_dev:	class device struct
+- * @buf:		buffer
++ * @dev:	device struct
++ * @buf:	buffer
+  *
+  * Return value:
+  *	number of bytes printed to buffer
+  **/
+-static ssize_t ipr_show_write_caching(struct class_device *class_dev, char *buf)
++static ssize_t ipr_show_write_caching(struct device *dev,
++				      struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	unsigned long lock_flags = 0;
+ 	int i, len = 0;
+@@ -2519,19 +2520,20 @@ static ssize_t ipr_show_write_caching(struct class_device *class_dev, char *buf)
+ 
+ /**
+  * ipr_store_write_caching - Enable/disable adapter write cache
+- * @class_dev:	class_device struct
+- * @buf:		buffer
+- * @count:		buffer size
++ * @dev:	device struct
++ * @buf:	buffer
++ * @count:	buffer size
+  *
+  * This function will enable/disable adapter write cache.
+  *
+  * Return value:
+  * 	count on success / other on failure
+  **/
+-static ssize_t ipr_store_write_caching(struct class_device *class_dev,
+-					const char *buf, size_t count)
++static ssize_t ipr_store_write_caching(struct device *dev,
++				       struct device_attribute *attr,
++				       const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	unsigned long lock_flags = 0;
+ 	enum ipr_cache_state new_state = CACHE_INVALID;
+@@ -2569,7 +2571,7 @@ static ssize_t ipr_store_write_caching(struct class_device *class_dev,
+ 	return count;
+ }
+ 
+-static struct class_device_attribute ipr_ioa_cache_attr = {
++static struct device_attribute ipr_ioa_cache_attr = {
+ 	.attr = {
+ 		.name =		"write_cache",
+ 		.mode =		S_IRUGO | S_IWUSR,
+@@ -2580,15 +2582,16 @@ static struct class_device_attribute ipr_ioa_cache_attr = {
+ 
+ /**
+  * ipr_show_fw_version - Show the firmware version
+- * @class_dev:	class device struct
+- * @buf:		buffer
++ * @dev:	class device struct
++ * @buf:	buffer
+  *
+  * Return value:
+  *	number of bytes printed to buffer
+  **/
+-static ssize_t ipr_show_fw_version(struct class_device *class_dev, char *buf)
++static ssize_t ipr_show_fw_version(struct device *dev,
++				   struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	struct ipr_inquiry_page3 *ucode_vpd = &ioa_cfg->vpd_cbs->page3_data;
+ 	unsigned long lock_flags = 0;
+@@ -2603,7 +2606,7 @@ static ssize_t ipr_show_fw_version(struct class_device *class_dev, char *buf)
+ 	return len;
+ }
+ 
+-static struct class_device_attribute ipr_fw_version_attr = {
++static struct device_attribute ipr_fw_version_attr = {
+ 	.attr = {
+ 		.name =		"fw_version",
+ 		.mode =		S_IRUGO,
+@@ -2613,15 +2616,16 @@ static struct class_device_attribute ipr_fw_version_attr = {
+ 
+ /**
+  * ipr_show_log_level - Show the adapter's error logging level
+- * @class_dev:	class device struct
+- * @buf:		buffer
++ * @dev:	class device struct
++ * @buf:	buffer
+  *
+  * Return value:
+  * 	number of bytes printed to buffer
+  **/
+-static ssize_t ipr_show_log_level(struct class_device *class_dev, char *buf)
++static ssize_t ipr_show_log_level(struct device *dev,
++				   struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	unsigned long lock_flags = 0;
+ 	int len;
+@@ -2634,16 +2638,17 @@ static ssize_t ipr_show_log_level(struct class_device *class_dev, char *buf)
+ 
+ /**
+  * ipr_store_log_level - Change the adapter's error logging level
+- * @class_dev:	class device struct
+- * @buf:		buffer
++ * @dev:	class device struct
++ * @buf:	buffer
+  *
+  * Return value:
+  * 	number of bytes printed to buffer
+  **/
+-static ssize_t ipr_store_log_level(struct class_device *class_dev,
++static ssize_t ipr_store_log_level(struct device *dev,
++			           struct device_attribute *attr,
+ 				   const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	unsigned long lock_flags = 0;
+ 
+@@ -2653,7 +2658,7 @@ static ssize_t ipr_store_log_level(struct class_device *class_dev,
+ 	return strlen(buf);
+ }
+ 
+-static struct class_device_attribute ipr_log_level_attr = {
++static struct device_attribute ipr_log_level_attr = {
+ 	.attr = {
+ 		.name =		"log_level",
+ 		.mode =		S_IRUGO | S_IWUSR,
+@@ -2664,9 +2669,9 @@ static struct class_device_attribute ipr_log_level_attr = {
+ 
+ /**
+  * ipr_store_diagnostics - IOA Diagnostics interface
+- * @class_dev:	class_device struct
+- * @buf:		buffer
+- * @count:		buffer size
++ * @dev:	device struct
++ * @buf:	buffer
++ * @count:	buffer size
+  *
+  * This function will reset the adapter and wait a reasonable
+  * amount of time for any errors that the adapter might log.
+@@ -2674,10 +2679,11 @@ static struct class_device_attribute ipr_log_level_attr = {
+  * Return value:
+  * 	count on success / other on failure
+  **/
+-static ssize_t ipr_store_diagnostics(struct class_device *class_dev,
++static ssize_t ipr_store_diagnostics(struct device *dev,
++				     struct device_attribute *attr,
+ 				     const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	unsigned long lock_flags = 0;
+ 	int rc = count;
+@@ -2714,7 +2720,7 @@ static ssize_t ipr_store_diagnostics(struct class_device *class_dev,
+ 	return rc;
+ }
+ 
+-static struct class_device_attribute ipr_diagnostics_attr = {
++static struct device_attribute ipr_diagnostics_attr = {
+ 	.attr = {
+ 		.name =		"run_diagnostics",
+ 		.mode =		S_IWUSR,
+@@ -2724,15 +2730,16 @@ static struct class_device_attribute ipr_diagnostics_attr = {
+ 
+ /**
+  * ipr_show_adapter_state - Show the adapter's state
+- * @class_dev:	class device struct
+- * @buf:		buffer
++ * @class_dev:	device struct
++ * @buf:	buffer
+  *
+  * Return value:
+  * 	number of bytes printed to buffer
+  **/
+-static ssize_t ipr_show_adapter_state(struct class_device *class_dev, char *buf)
++static ssize_t ipr_show_adapter_state(struct device *dev,
++				      struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	unsigned long lock_flags = 0;
+ 	int len;
+@@ -2748,19 +2755,20 @@ static ssize_t ipr_show_adapter_state(struct class_device *class_dev, char *buf)
+ 
+ /**
+  * ipr_store_adapter_state - Change adapter state
+- * @class_dev:	class_device struct
+- * @buf:		buffer
+- * @count:		buffer size
++ * @dev:	device struct
++ * @buf:	buffer
++ * @count:	buffer size
+  *
+  * This function will change the adapter's state.
+  *
+  * Return value:
+  * 	count on success / other on failure
+  **/
+-static ssize_t ipr_store_adapter_state(struct class_device *class_dev,
++static ssize_t ipr_store_adapter_state(struct device *dev,
++				       struct device_attribute *attr,
+ 				       const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	unsigned long lock_flags;
+ 	int result = count;
+@@ -2781,7 +2789,7 @@ static ssize_t ipr_store_adapter_state(struct class_device *class_dev,
+ 	return result;
+ }
+ 
+-static struct class_device_attribute ipr_ioa_state_attr = {
++static struct device_attribute ipr_ioa_state_attr = {
+ 	.attr = {
+ 		.name =		"state",
+ 		.mode =		S_IRUGO | S_IWUSR,
+@@ -2792,19 +2800,20 @@ static struct class_device_attribute ipr_ioa_state_attr = {
+ 
+ /**
+  * ipr_store_reset_adapter - Reset the adapter
+- * @class_dev:	class_device struct
+- * @buf:		buffer
+- * @count:		buffer size
++ * @dev:	device struct
++ * @buf:	buffer
++ * @count:	buffer size
+  *
+  * This function will reset the adapter.
+  *
+  * Return value:
+  * 	count on success / other on failure
+  **/
+-static ssize_t ipr_store_reset_adapter(struct class_device *class_dev,
++static ssize_t ipr_store_reset_adapter(struct device *dev,
++				       struct device_attribute *attr,
+ 				       const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	unsigned long lock_flags;
+ 	int result = count;
+@@ -2821,7 +2830,7 @@ static ssize_t ipr_store_reset_adapter(struct class_device *class_dev,
+ 	return result;
+ }
+ 
+-static struct class_device_attribute ipr_ioa_reset_attr = {
++static struct device_attribute ipr_ioa_reset_attr = {
+ 	.attr = {
+ 		.name =		"reset_host",
+ 		.mode =		S_IWUSR,
+@@ -3054,19 +3063,20 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg,
+ 
+ /**
+  * ipr_store_update_fw - Update the firmware on the adapter
+- * @class_dev:	class_device struct
+- * @buf:		buffer
+- * @count:		buffer size
++ * @class_dev:	device struct
++ * @buf:	buffer
++ * @count:	buffer size
+  *
+  * This function will update the firmware on the adapter.
+  *
+  * Return value:
+  * 	count on success / other on failure
+  **/
+-static ssize_t ipr_store_update_fw(struct class_device *class_dev,
+-				       const char *buf, size_t count)
++static ssize_t ipr_store_update_fw(struct device *dev,
++				   struct device_attribute *attr,
++				   const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	struct ipr_ucode_image_header *image_hdr;
+ 	const struct firmware *fw_entry;
+@@ -3124,7 +3134,7 @@ out:
+ 	return result;
+ }
+ 
+-static struct class_device_attribute ipr_update_fw_attr = {
++static struct device_attribute ipr_update_fw_attr = {
+ 	.attr = {
+ 		.name =		"update_fw",
+ 		.mode =		S_IWUSR,
+@@ -3132,7 +3142,7 @@ static struct class_device_attribute ipr_update_fw_attr = {
+ 	.store = ipr_store_update_fw
+ };
+ 
+-static struct class_device_attribute *ipr_ioa_attrs[] = {
++static struct device_attribute *ipr_ioa_attrs[] = {
+ 	&ipr_fw_version_attr,
+ 	&ipr_log_level_attr,
+ 	&ipr_diagnostics_attr,
+@@ -3159,7 +3169,7 @@ static ssize_t ipr_read_dump(struct kobject *kobj,
+ 			     struct bin_attribute *bin_attr,
+ 			     char *buf, loff_t off, size_t count)
+ {
+-	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
++	struct device *cdev = container_of(kobj, struct device, kobj);
+ 	struct Scsi_Host *shost = class_to_shost(cdev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	struct ipr_dump *dump;
+@@ -3322,7 +3332,7 @@ static ssize_t ipr_write_dump(struct kobject *kobj,
+ 			      struct bin_attribute *bin_attr,
+ 			      char *buf, loff_t off, size_t count)
+ {
+-	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
++	struct device *cdev = container_of(kobj, struct device, kobj);
+ 	struct Scsi_Host *shost = class_to_shost(cdev);
+ 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ 	int rc;
+@@ -3937,7 +3947,7 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
+ 	if (ipr_is_gata(res) && res->sata_port) {
+ 		ap = res->sata_port->ap;
+ 		spin_unlock_irq(scsi_cmd->device->host->host_lock);
+-		ata_do_eh(ap, NULL, NULL, ipr_sata_reset, NULL);
++		ata_std_error_handler(ap);
+ 		spin_lock_irq(scsi_cmd->device->host->host_lock);
+ 
+ 		list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
+@@ -5041,33 +5051,6 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc)
+ }
+ 
+ /**
+- * ipr_tf_read - Read the current ATA taskfile for the ATA port
+- * @ap:	ATA port
+- * @tf:	destination ATA taskfile
+- *
+- * Return value:
+- * 	none
+- **/
+-static void ipr_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+-	struct ipr_sata_port *sata_port = ap->private_data;
+-	struct ipr_ioasa_gata *g = &sata_port->ioasa;
+-
+-	tf->feature = g->error;
+-	tf->nsect = g->nsect;
+-	tf->lbal = g->lbal;
+-	tf->lbam = g->lbam;
+-	tf->lbah = g->lbah;
+-	tf->device = g->device;
+-	tf->command = g->status;
+-	tf->hob_nsect = g->hob_nsect;
+-	tf->hob_lbal = g->hob_lbal;
+-	tf->hob_lbam = g->hob_lbam;
+-	tf->hob_lbah = g->hob_lbah;
+-	tf->ctl = g->alt_status;
+-}
+-
+-/**
+  * ipr_copy_sata_tf - Copy a SATA taskfile to an IOA data structure
+  * @regs:	destination
+  * @tf:	source ATA taskfile
+@@ -5245,40 +5228,41 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
+ }
+ 
+ /**
+- * ipr_ata_check_status - Return last ATA status
+- * @ap:	ATA port
++ * ipr_qc_fill_rtf - Read result TF
++ * @qc: ATA queued command
+  *
+  * Return value:
+- * 	ATA status
++ * 	true
+  **/
+-static u8 ipr_ata_check_status(struct ata_port *ap)
++static bool ipr_qc_fill_rtf(struct ata_queued_cmd *qc)
+ {
+-	struct ipr_sata_port *sata_port = ap->private_data;
+-	return sata_port->ioasa.status;
+-}
++	struct ipr_sata_port *sata_port = qc->ap->private_data;
++	struct ipr_ioasa_gata *g = &sata_port->ioasa;
++	struct ata_taskfile *tf = &qc->result_tf;
+ 
+-/**
+- * ipr_ata_check_altstatus - Return last ATA altstatus
+- * @ap:	ATA port
+- *
+- * Return value:
+- * 	Alt ATA status
+- **/
+-static u8 ipr_ata_check_altstatus(struct ata_port *ap)
+-{
+-	struct ipr_sata_port *sata_port = ap->private_data;
+-	return sata_port->ioasa.alt_status;
++	tf->feature = g->error;
++	tf->nsect = g->nsect;
++	tf->lbal = g->lbal;
++	tf->lbam = g->lbam;
++	tf->lbah = g->lbah;
++	tf->device = g->device;
++	tf->command = g->status;
++	tf->hob_nsect = g->hob_nsect;
++	tf->hob_lbal = g->hob_lbal;
++	tf->hob_lbam = g->hob_lbam;
++	tf->hob_lbah = g->hob_lbah;
++	tf->ctl = g->alt_status;
++
++	return true;
+ }
+ 
+ static struct ata_port_operations ipr_sata_ops = {
+-	.check_status = ipr_ata_check_status,
+-	.check_altstatus = ipr_ata_check_altstatus,
+-	.dev_select = ata_noop_dev_select,
+ 	.phy_reset = ipr_ata_phy_reset,
++	.hardreset = ipr_sata_reset,
+ 	.post_internal_cmd = ipr_ata_post_internal,
+-	.tf_read = ipr_tf_read,
+ 	.qc_prep = ata_noop_qc_prep,
+ 	.qc_issue = ipr_qc_issue,
++	.qc_fill_rtf = ipr_qc_fill_rtf,
+ 	.port_start = ata_sas_port_start,
+ 	.port_stop = ata_sas_port_stop
+ };
+@@ -7697,9 +7681,9 @@ static void ipr_remove(struct pci_dev *pdev)
+ 
+ 	ENTER;
+ 
+-	ipr_remove_trace_file(&ioa_cfg->host->shost_classdev.kobj,
++	ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj,
+ 			      &ipr_trace_attr);
+-	ipr_remove_dump_file(&ioa_cfg->host->shost_classdev.kobj,
++	ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj,
+ 			     &ipr_dump_attr);
+ 	scsi_remove_host(ioa_cfg->host);
+ 
+@@ -7740,7 +7724,7 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
+ 		return rc;
+ 	}
+ 
+-	rc = ipr_create_trace_file(&ioa_cfg->host->shost_classdev.kobj,
++	rc = ipr_create_trace_file(&ioa_cfg->host->shost_dev.kobj,
+ 				   &ipr_trace_attr);
+ 
+ 	if (rc) {
+@@ -7749,11 +7733,11 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
+ 		return rc;
+ 	}
+ 
+-	rc = ipr_create_dump_file(&ioa_cfg->host->shost_classdev.kobj,
++	rc = ipr_create_dump_file(&ioa_cfg->host->shost_dev.kobj,
+ 				   &ipr_dump_attr);
+ 
+ 	if (rc) {
+-		ipr_remove_trace_file(&ioa_cfg->host->shost_classdev.kobj,
++		ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj,
+ 				      &ipr_trace_attr);
+ 		scsi_remove_host(ioa_cfg->host);
+ 		__ipr_remove(pdev);
+diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
+index 7ed568f..7c615c7 100644
+--- a/drivers/scsi/ips.c
++++ b/drivers/scsi/ips.c
+@@ -2377,7 +2377,7 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
+ 			if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
+ 				return;
+ 
+-			outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
++			outl(1, ha->io_addr + IPS_REG_FLAP);
+ 			if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ 				udelay(25);	/* 25 us */
+ 
+@@ -2385,21 +2385,21 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
+ 				return;
+ 
+ 			/* Get Major version */
+-			outl(cpu_to_le32(0x1FF), ha->io_addr + IPS_REG_FLAP);
++			outl(0x1FF, ha->io_addr + IPS_REG_FLAP);
+ 			if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ 				udelay(25);	/* 25 us */
+ 
+ 			major = inb(ha->io_addr + IPS_REG_FLDP);
+ 
+ 			/* Get Minor version */
+-			outl(cpu_to_le32(0x1FE), ha->io_addr + IPS_REG_FLAP);
++			outl(0x1FE, ha->io_addr + IPS_REG_FLAP);
+ 			if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ 				udelay(25);	/* 25 us */
+ 
+ 			minor = inb(ha->io_addr + IPS_REG_FLDP);
+ 
+ 			/* Get SubMinor version */
+-			outl(cpu_to_le32(0x1FD), ha->io_addr + IPS_REG_FLAP);
++			outl(0x1FD, ha->io_addr + IPS_REG_FLAP);
+ 			if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ 				udelay(25);	/* 25 us */
+ 
+@@ -3502,27 +3502,11 @@ ips_send_wait(ips_ha_t * ha, ips_scb_t * scb, int timeout, int intr)
+ static void
+ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
+ {
+-        int i;
+-        unsigned int min_cnt, xfer_cnt;
+-        char *cdata = (char *) data;
+-        unsigned char *buffer;
+-        unsigned long flags;
+-        struct scatterlist *sg = scsi_sglist(scmd);
+-
+-        for (i = 0, xfer_cnt = 0;
+-             (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+-                min_cnt = min(count - xfer_cnt, sg[i].length);
+-
+-                /* kmap_atomic() ensures addressability of the data buffer.*/
+-                /* local_irq_save() protects the KM_IRQ0 address slot.     */
+-                local_irq_save(flags);
+-                buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
+-                memcpy(buffer, &cdata[xfer_cnt], min_cnt);
+-                kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+-                local_irq_restore(flags);
++	unsigned long flags;
+ 
+-                xfer_cnt += min_cnt;
+-        }
++	local_irq_save(flags);
++	scsi_sg_copy_from_buffer(scmd, data, count);
++	local_irq_restore(flags);
+ }
+ 
+ /****************************************************************************/
+@@ -3535,27 +3519,11 @@ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
+ static void
+ ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
+ {
+-        int i;
+-        unsigned int min_cnt, xfer_cnt;
+-        char *cdata = (char *) data;
+-        unsigned char *buffer;
+-        unsigned long flags;
+-        struct scatterlist *sg = scsi_sglist(scmd);
+-
+-        for (i = 0, xfer_cnt = 0;
+-             (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+-                min_cnt = min(count - xfer_cnt, sg[i].length);
+-
+-                /* kmap_atomic() ensures addressability of the data buffer.*/
+-                /* local_irq_save() protects the KM_IRQ0 address slot.     */
+-                local_irq_save(flags);
+-                buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
+-                memcpy(&cdata[xfer_cnt], buffer, min_cnt);
+-                kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+-                local_irq_restore(flags);
++	unsigned long flags;
+ 
+-                xfer_cnt += min_cnt;
+-        }
++	local_irq_save(flags);
++	scsi_sg_copy_to_buffer(scmd, data, count);
++	local_irq_restore(flags);
+ }
+ 
+ /****************************************************************************/
+@@ -3696,9 +3664,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
+ 			scb->cmd.basic_io.sg_count = scb->sg_len;
+ 
+ 			if (scb->cmd.basic_io.lba)
+-				scb->cmd.basic_io.lba =
+-				    cpu_to_le32(le32_to_cpu
+-						(scb->cmd.basic_io.lba) +
++				le32_add_cpu(&scb->cmd.basic_io.lba,
+ 						le16_to_cpu(scb->cmd.basic_io.
+ 							    sector_count));
+ 			else
+@@ -3744,9 +3710,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
+ 			scb->cmd.basic_io.sg_count = scb->sg_len;
+ 
+ 			if (scb->cmd.basic_io.lba)
+-				scb->cmd.basic_io.lba =
+-				    cpu_to_le32(le32_to_cpu
+-						(scb->cmd.basic_io.lba) +
++				le32_add_cpu(&scb->cmd.basic_io.lba,
+ 						le16_to_cpu(scb->cmd.basic_io.
+ 							    sector_count));
+ 			else
+@@ -4888,7 +4852,7 @@ ips_init_copperhead(ips_ha_t * ha)
+ 		return (0);
+ 
+ 	/* setup CCCR */
+-	outl(cpu_to_le32(0x1010), ha->io_addr + IPS_REG_CCCR);
++	outl(0x1010, ha->io_addr + IPS_REG_CCCR);
+ 
+ 	/* Enable busmastering */
+ 	outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
+@@ -5270,12 +5234,12 @@ ips_statinit(ips_ha_t * ha)
+ 	ha->adapt->p_status_tail = ha->adapt->status;
+ 
+ 	phys_status_start = ha->adapt->hw_status_start;
+-	outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQSR);
+-	outl(cpu_to_le32(phys_status_start + IPS_STATUS_Q_SIZE),
++	outl(phys_status_start, ha->io_addr + IPS_REG_SQSR);
++	outl(phys_status_start + IPS_STATUS_Q_SIZE,
+ 	     ha->io_addr + IPS_REG_SQER);
+-	outl(cpu_to_le32(phys_status_start + IPS_STATUS_SIZE),
++	outl(phys_status_start + IPS_STATUS_SIZE,
+ 	     ha->io_addr + IPS_REG_SQHR);
+-	outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQTR);
++	outl(phys_status_start, ha->io_addr + IPS_REG_SQTR);
+ 
+ 	ha->adapt->hw_status_tail = phys_status_start;
+ }
+@@ -5332,7 +5296,7 @@ ips_statupd_copperhead(ips_ha_t * ha)
+ 		ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
+ 	}
+ 
+-	outl(cpu_to_le32(ha->adapt->hw_status_tail),
++	outl(ha->adapt->hw_status_tail,
+ 	     ha->io_addr + IPS_REG_SQTR);
+ 
+ 	return (ha->adapt->p_status_tail->value);
+@@ -5434,8 +5398,8 @@ ips_issue_copperhead(ips_ha_t * ha, ips_scb_t * scb)
+ 		}		/* end if */
+ 	}			/* end while */
+ 
+-	outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR);
+-	outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR);
++	outl(scb->scb_busaddr, ha->io_addr + IPS_REG_CCSAR);
++	outw(IPS_BIT_START_CMD, ha->io_addr + IPS_REG_CCCR);
+ 
+ 	return (IPS_SUCCESS);
+ }
+@@ -5520,7 +5484,7 @@ ips_issue_i2o(ips_ha_t * ha, ips_scb_t * scb)
+ 			  ips_name, ha->host_num, scb->cmd.basic_io.command_id);
+ 	}
+ 
+-	outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ);
++	outl(scb->scb_busaddr, ha->io_addr + IPS_REG_I2O_INMSGQ);
+ 
+ 	return (IPS_SUCCESS);
+ }
+@@ -6412,7 +6376,7 @@ ips_program_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
+ 
+ 	for (i = 0; i < buffersize; i++) {
+ 		/* write a byte */
+-		outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
++		outl(i + offset, ha->io_addr + IPS_REG_FLAP);
+ 		if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ 			udelay(25);	/* 25 us */
+ 
+@@ -6597,7 +6561,7 @@ ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
+ 	if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
+ 		return (1);
+ 
+-	outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
++	outl(1, ha->io_addr + IPS_REG_FLAP);
+ 	if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ 		udelay(25);	/* 25 us */
+ 	if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
+@@ -6606,7 +6570,7 @@ ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
+ 	checksum = 0xff;
+ 	for (i = 2; i < buffersize; i++) {
+ 
+-		outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
++		outl(i + offset, ha->io_addr + IPS_REG_FLAP);
+ 		if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ 			udelay(25);	/* 25 us */
+ 
+@@ -6842,7 +6806,6 @@ ips_register_scsi(int index)
+ 	sh->sg_tablesize = sh->hostt->sg_tablesize;
+ 	sh->can_queue = sh->hostt->can_queue;
+ 	sh->cmd_per_lun = sh->hostt->cmd_per_lun;
+-	sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
+ 	sh->use_clustering = sh->hostt->use_clustering;
+ 	sh->max_sectors = 128;
+ 
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 8a17867..72b9b2a 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -528,6 +528,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	struct iscsi_session *session = conn->session;
+ 	struct scsi_cmnd *sc = ctask->sc;
+ 	int datasn = be32_to_cpu(rhdr->datasn);
++	unsigned total_in_length = scsi_in(sc)->length;
+ 
+ 	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ 	if (tcp_conn->in.datalen == 0)
+@@ -542,10 +543,10 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 	tcp_ctask->exp_datasn++;
+ 
+ 	tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+-	if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
++	if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
+ 		debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+ 		          __FUNCTION__, tcp_ctask->data_offset,
+-		          tcp_conn->in.datalen, scsi_bufflen(sc));
++		          tcp_conn->in.datalen, total_in_length);
+ 		return ISCSI_ERR_DATA_OFFSET;
+ 	}
+ 
+@@ -558,8 +559,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 
+ 			if (res_count > 0 &&
+ 			    (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+-			     res_count <= scsi_bufflen(sc)))
+-				scsi_set_resid(sc, res_count);
++			     res_count <= total_in_length))
++				scsi_in(sc)->resid = res_count;
+ 			else
+ 				sc->result = (DID_BAD_TARGET << 16) |
+ 					rhdr->cmd_status;
+@@ -670,11 +671,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ 			    r2t->data_length, session->max_burst);
+ 
+ 	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+-	if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
++	if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
+ 		iscsi_conn_printk(KERN_ERR, conn,
+ 				  "invalid R2T with data len %u at offset %u "
+ 				  "and total length %d\n", r2t->data_length,
+-				  r2t->data_offset, scsi_bufflen(ctask->sc));
++				  r2t->data_offset, scsi_out(ctask->sc)->length);
+ 		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ 			    sizeof(void*));
+ 		return ISCSI_ERR_DATALEN;
+@@ -771,6 +772,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 		if (tcp_conn->in.datalen) {
+ 			struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 			struct hash_desc *rx_hash = NULL;
++			struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
+ 
+ 			/*
+ 			 * Setup copy of Data-In into the Scsi_Cmnd
+@@ -788,8 +790,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ 				  tcp_ctask->data_offset,
+ 				  tcp_conn->in.datalen);
+ 			return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+-						     scsi_sglist(ctask->sc),
+-						     scsi_sg_count(ctask->sc),
++						     sdb->table.sgl,
++						     sdb->table.nents,
+ 						     tcp_ctask->data_offset,
+ 						     tcp_conn->in.datalen,
+ 						     iscsi_tcp_process_data_in,
+@@ -1332,7 +1334,8 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
+ 		return 0;
+ 
+ 	/* If we have immediate data, attach a payload */
+-	err = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc), scsi_sg_count(sc),
++	err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
++				       scsi_out(sc)->table.nents,
+ 				       0, ctask->imm_count);
+ 	if (err)
+ 		return err;
+@@ -1386,6 +1389,7 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ 	struct scsi_cmnd *sc = ctask->sc;
++	struct scsi_data_buffer *sdb = scsi_out(sc);
+ 	int rc = 0;
+ 
+ flush:
+@@ -1412,9 +1416,8 @@ flush:
+ 				ctask->itt, tcp_ctask->sent, ctask->data_count);
+ 
+ 		iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+-		rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
+-					      scsi_sg_count(sc),
+-					      tcp_ctask->sent,
++		rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
++					      sdb->table.nents, tcp_ctask->sent,
+ 					      ctask->data_count);
+ 		if (rc)
+ 			goto fail;
+@@ -1460,8 +1463,8 @@ flush:
+ 		iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+ 					sizeof(struct iscsi_hdr));
+ 
+-		rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
+-					      scsi_sg_count(sc),
++		rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
++					      sdb->table.nents,
+ 					      r2t->data_offset + r2t->sent,
+ 					      r2t->data_count);
+ 		if (rc)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index bdd7de7..010c1b9 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -137,6 +137,70 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
+ 	return 0;
+ }
+ 
++/*
++ * make an extended cdb AHS
++ */
++static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
++{
++	struct scsi_cmnd *cmd = ctask->sc;
++	unsigned rlen, pad_len;
++	unsigned short ahslength;
++	struct iscsi_ecdb_ahdr *ecdb_ahdr;
++	int rc;
++
++	ecdb_ahdr = iscsi_next_hdr(ctask);
++	rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
++
++	BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
++	ahslength = rlen + sizeof(ecdb_ahdr->reserved);
++
++	pad_len = iscsi_padding(rlen);
++
++	rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
++	                   sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
++	if (rc)
++		return rc;
++
++	if (pad_len)
++		memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
++
++	ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
++	ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
++	ecdb_ahdr->reserved = 0;
++	memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
++
++	debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
++		   "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
++		   cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
++
++	return 0;
++}
++
++static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
++{
++	struct scsi_cmnd *sc = ctask->sc;
++	struct iscsi_rlength_ahdr *rlen_ahdr;
++	int rc;
++
++	rlen_ahdr = iscsi_next_hdr(ctask);
++	rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
++	if (rc)
++		return rc;
++
++	rlen_ahdr->ahslength =
++		cpu_to_be16(sizeof(rlen_ahdr->read_length) +
++						  sizeof(rlen_ahdr->reserved));
++	rlen_ahdr->ahstype = ISCSI_AHSTYPE_RLENGTH;
++	rlen_ahdr->reserved = 0;
++	rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length);
++
++	debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
++		   "rlen_ahdr->ahslength(%d)\n",
++		   be32_to_cpu(rlen_ahdr->read_length),
++		   be16_to_cpu(rlen_ahdr->ahslength));
++	return 0;
++}
++
+ /**
+  * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+  * @ctask: iscsi cmd task
+@@ -150,7 +214,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	struct iscsi_session *session = conn->session;
+ 	struct iscsi_cmd *hdr = ctask->hdr;
+ 	struct scsi_cmnd *sc = ctask->sc;
+-	unsigned hdrlength;
++	unsigned hdrlength, cmd_len;
+ 	int rc;
+ 
+ 	ctask->hdr_len = 0;
+@@ -161,17 +225,30 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	hdr->flags = ISCSI_ATTR_SIMPLE;
+ 	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ 	hdr->itt = build_itt(ctask->itt, session->age);
+-	hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+ 	hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ 	session->cmdsn++;
+ 	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+-	memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
+-	if (sc->cmd_len < MAX_COMMAND_SIZE)
+-		memset(&hdr->cdb[sc->cmd_len], 0,
+-			MAX_COMMAND_SIZE - sc->cmd_len);
++	cmd_len = sc->cmd_len;
++	if (cmd_len < ISCSI_CDB_SIZE)
++		memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
++	else if (cmd_len > ISCSI_CDB_SIZE) {
++		rc = iscsi_prep_ecdb_ahs(ctask);
++		if (rc)
++			return rc;
++		cmd_len = ISCSI_CDB_SIZE;
++	}
++	memcpy(hdr->cdb, sc->cmnd, cmd_len);
+ 
+ 	ctask->imm_count = 0;
++	if (scsi_bidi_cmnd(sc)) {
++		hdr->flags |= ISCSI_FLAG_CMD_READ;
++		rc = iscsi_prep_bidi_ahs(ctask);
++		if (rc)
++			return rc;
++	}
+ 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
++		unsigned out_len = scsi_out(sc)->length;
++		hdr->data_length = cpu_to_be32(out_len);
+ 		hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ 		/*
+ 		 * Write counters:
+@@ -192,19 +269,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 		ctask->unsol_datasn = 0;
+ 
+ 		if (session->imm_data_en) {
+-			if (scsi_bufflen(sc) >= session->first_burst)
++			if (out_len >= session->first_burst)
+ 				ctask->imm_count = min(session->first_burst,
+ 							conn->max_xmit_dlength);
+ 			else
+-				ctask->imm_count = min(scsi_bufflen(sc),
++				ctask->imm_count = min(out_len,
+ 							conn->max_xmit_dlength);
+ 			hton24(hdr->dlength, ctask->imm_count);
+ 		} else
+ 			zero_data(hdr->dlength);
+ 
+ 		if (!session->initial_r2t_en) {
+-			ctask->unsol_count = min((session->first_burst),
+-				(scsi_bufflen(sc))) - ctask->imm_count;
++			ctask->unsol_count = min(session->first_burst, out_len)
++							     - ctask->imm_count;
+ 			ctask->unsol_offset = ctask->imm_count;
+ 		}
+ 
+@@ -214,6 +291,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 	} else {
+ 		hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ 		zero_data(hdr->dlength);
++		hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+ 
+ 		if (sc->sc_data_direction == DMA_FROM_DEVICE)
+ 			hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -232,10 +310,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ 		return EIO;
+ 
+ 	conn->scsicmd_pdus_cnt++;
+-	debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
+-		"cmdsn %d win %d]\n",
+-		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+-		conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
++	debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
++		"len %d bidi_len %d cmdsn %d win %d]\n",
++		scsi_bidi_cmnd(sc) ? "bidirectional" :
++		     sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++		conn->id, sc, sc->cmnd[0], ctask->itt,
++		scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
+ 		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ 	return 0;
+ }
+@@ -298,7 +378,12 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ 		conn->session->tt->cleanup_cmd_task(conn, ctask);
+ 
+ 	sc->result = err;
+-	scsi_set_resid(sc, scsi_bufflen(sc));
++	if (!scsi_bidi_cmnd(sc))
++		scsi_set_resid(sc, scsi_bufflen(sc));
++	else {
++		scsi_out(sc)->resid = scsi_out(sc)->length;
++		scsi_in(sc)->resid = scsi_in(sc)->length;
++	}
+ 	if (conn->ctask == ctask)
+ 		conn->ctask = NULL;
+ 	/* release ref from queuecommand */
+@@ -433,6 +518,18 @@ invalid_datalen:
+ 			   min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ 	}
+ 
++	if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
++			   ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
++		int res_count = be32_to_cpu(rhdr->bi_residual_count);
++
++		if (scsi_bidi_cmnd(sc) && res_count > 0 &&
++				(rhdr->flags & ISCSI_FLAG_CMD_BIDI_OVERFLOW ||
++				 res_count <= scsi_in(sc)->length))
++			scsi_in(sc)->resid = res_count;
++		else
++			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++	}
++
+ 	if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+ 	                   ISCSI_FLAG_CMD_OVERFLOW)) {
+ 		int res_count = be32_to_cpu(rhdr->residual_count);
+@@ -440,13 +537,11 @@ invalid_datalen:
+ 		if (res_count > 0 &&
+ 		    (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+ 		     res_count <= scsi_bufflen(sc)))
++			/* write side for bidi or uni-io set_resid */
+ 			scsi_set_resid(sc, res_count);
+ 		else
+ 			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+-	} else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+-	                          ISCSI_FLAG_CMD_BIDI_OVERFLOW))
+-		sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+-
++	}
+ out:
+ 	debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+ 		   (long)sc, sc->result, ctask->itt);
+@@ -1102,7 +1197,12 @@ reject:
+ fault:
+ 	spin_unlock(&session->lock);
+ 	debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
+-	scsi_set_resid(sc, scsi_bufflen(sc));
++	if (!scsi_bidi_cmnd(sc))
++		scsi_set_resid(sc, scsi_bufflen(sc));
++	else {
++		scsi_out(sc)->resid = scsi_out(sc)->length;
++		scsi_in(sc)->resid = scsi_in(sc)->length;
++	}
+ 	sc->scsi_done(sc);
+ 	spin_lock(host->host_lock);
+ 	return 0;
+diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
+index b0e5ac3..744f06d 100644
+--- a/drivers/scsi/libsas/sas_ata.c
++++ b/drivers/scsi/libsas/sas_ata.c
+@@ -225,10 +225,12 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
+ 	return 0;
+ }
+ 
+-static u8 sas_ata_check_status(struct ata_port *ap)
++static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
+ {
+-	struct domain_device *dev = ap->private_data;
+-	return dev->sata_dev.tf.command;
++	struct domain_device *dev = qc->ap->private_data;
++
++	memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf));
++	return true;
+ }
+ 
+ static void sas_ata_phy_reset(struct ata_port *ap)
+@@ -292,12 +294,6 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc)
+ 	}
+ }
+ 
+-static void sas_ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+-	struct domain_device *dev = ap->private_data;
+-	memcpy(tf, &dev->sata_dev.tf, sizeof (*tf));
+-}
+-
+ static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
+ 			      u32 val)
+ {
+@@ -348,14 +344,11 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
+ }
+ 
+ static struct ata_port_operations sas_sata_ops = {
+-	.check_status		= sas_ata_check_status,
+-	.check_altstatus	= sas_ata_check_status,
+-	.dev_select		= ata_noop_dev_select,
+ 	.phy_reset		= sas_ata_phy_reset,
+ 	.post_internal_cmd	= sas_ata_post_internal,
+-	.tf_read		= sas_ata_tf_read,
+ 	.qc_prep		= ata_noop_qc_prep,
+ 	.qc_issue		= sas_ata_qc_issue,
++	.qc_fill_rtf		= sas_ata_qc_fill_rtf,
+ 	.port_start		= ata_sas_port_start,
+ 	.port_stop		= ata_sas_port_stop,
+ 	.scr_read		= sas_ata_scr_read,
+@@ -698,7 +691,7 @@ static int sas_discover_sata_dev(struct domain_device *dev)
+ 		/* incomplete response */
+ 		SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to "
+ 			    "dev %llx\n", SAS_ADDR(dev->sas_addr));
+-		if (!le16_to_cpu(identify_x[83] & (1<<6)))
++		if (!(identify_x[83] & cpu_to_le16(1<<6)))
+ 			goto cont1;
+ 		res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES,
+ 					ATA_FEATURE_PUP_STBY_SPIN_UP,
+diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
+index 1f82415..601ec5b 100644
+--- a/drivers/scsi/libsas/sas_scsi_host.c
++++ b/drivers/scsi/libsas/sas_scsi_host.c
+@@ -24,6 +24,8 @@
+  */
+ 
+ #include <linux/kthread.h>
++#include <linux/firmware.h>
++#include <linux/ctype.h>
+ 
+ #include "sas_internal.h"
+ 
+@@ -1064,6 +1066,45 @@ void sas_target_destroy(struct scsi_target *starget)
+ 	return;
+ }
+ 
++static void sas_parse_addr(u8 *sas_addr, const char *p)
++{
++	int i;
++	for (i = 0; i < SAS_ADDR_SIZE; i++) {
++		u8 h, l;
++		if (!*p)
++			break;
++		h = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
++		p++;
++		l = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
++		p++;
++		sas_addr[i] = (h<<4) | l;
++	}
++}
++
++#define SAS_STRING_ADDR_SIZE	16
++
++int sas_request_addr(struct Scsi_Host *shost, u8 *addr)
++{
++	int res;
++	const struct firmware *fw;
++
++	res = request_firmware(&fw, "sas_addr", &shost->shost_gendev);
++	if (res)
++		return res;
++
++	if (fw->size < SAS_STRING_ADDR_SIZE) {
++		res = -ENODEV;
++		goto out;
++	}
++
++	sas_parse_addr(addr, fw->data);
++
++out:
++	release_firmware(fw);
++	return res;
++}
++EXPORT_SYMBOL_GPL(sas_request_addr);
++
+ EXPORT_SYMBOL_GPL(sas_queuecommand);
+ EXPORT_SYMBOL_GPL(sas_target_alloc);
+ EXPORT_SYMBOL_GPL(sas_slave_configure);
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 2ab2d24..ec0b0f6 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -23,7 +23,7 @@
+ 
+ struct lpfc_sli2_slim;
+ 
+-#define LPFC_MAX_TARGET		256	/* max number of targets supported */
++#define LPFC_MAX_TARGET		4096	/* max number of targets supported */
+ #define LPFC_MAX_DISC_THREADS	64	/* max outstanding discovery els
+ 					   requests */
+ #define LPFC_MAX_NS_RETRY	3	/* Number of retry attempts to contact
+@@ -268,7 +268,6 @@ struct lpfc_vport {
+ #define FC_NLP_MORE             0x40	 /* More node to process in node tbl */
+ #define FC_OFFLINE_MODE         0x80	 /* Interface is offline for diag */
+ #define FC_FABRIC               0x100	 /* We are fabric attached */
+-#define FC_ESTABLISH_LINK       0x200	 /* Reestablish Link */
+ #define FC_RSCN_DISCOVERY       0x400	 /* Auth all devices after RSCN */
+ #define FC_SCSI_SCAN_TMO        0x4000	 /* scsi scan timer running */
+ #define FC_ABORT_DISCOVERY      0x8000	 /* we want to abort discovery */
+@@ -433,8 +432,6 @@ struct lpfc_hba {
+ 
+ 	uint32_t fc_eventTag;	/* event tag for link attention */
+ 
+-
+-	struct timer_list fc_estabtmo;	/* link establishment timer */
+ 	/* These fields used to be binfo */
+ 	uint32_t fc_pref_DID;	/* preferred D_ID */
+ 	uint8_t  fc_pref_ALPA;	/* preferred AL_PA */
+diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
+index b12a841..a9fbb3f 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.c
++++ b/drivers/scsi/lpfc/lpfc_attr.c
+@@ -66,23 +66,26 @@ lpfc_jedec_to_ascii(int incr, char hdw[])
+ }
+ 
+ static ssize_t
+-lpfc_drvr_version_show(struct class_device *cdev, char *buf)
++lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr,
++		       char *buf)
+ {
+ 	return snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
+ }
+ 
+ static ssize_t
+-lpfc_info_show(struct class_device *cdev, char *buf)
++lpfc_info_show(struct device *dev, struct device_attribute *attr,
++	       char *buf)
+ {
+-	struct Scsi_Host *host = class_to_shost(cdev);
++	struct Scsi_Host *host = class_to_shost(dev);
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
+ }
+ 
+ static ssize_t
+-lpfc_serialnum_show(struct class_device *cdev, char *buf)
++lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -90,18 +93,20 @@ lpfc_serialnum_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_temp_sensor_show(struct class_device *cdev, char *buf)
++lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr,
++		      char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(cdev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support);
+ }
+ 
+ static ssize_t
+-lpfc_modeldesc_show(struct class_device *cdev, char *buf)
++lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -109,9 +114,10 @@ lpfc_modeldesc_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_modelname_show(struct class_device *cdev, char *buf)
++lpfc_modelname_show(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -119,9 +125,10 @@ lpfc_modelname_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_programtype_show(struct class_device *cdev, char *buf)
++lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
++		      char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -129,9 +136,10 @@ lpfc_programtype_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_vportnum_show(struct class_device *cdev, char *buf)
++lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
++		   char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -139,9 +147,10 @@ lpfc_vportnum_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_fwrev_show(struct class_device *cdev, char *buf)
++lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
++		char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	char fwrev[32];
+@@ -151,10 +160,10 @@ lpfc_fwrev_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_hdw_show(struct class_device *cdev, char *buf)
++lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ 	char hdw[9];
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	lpfc_vpd_t *vp = &phba->vpd;
+@@ -163,18 +172,20 @@ lpfc_hdw_show(struct class_device *cdev, char *buf)
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
+ }
+ static ssize_t
+-lpfc_option_rom_version_show(struct class_device *cdev, char *buf)
++lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
++			     char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
+ }
+ static ssize_t
+-lpfc_state_show(struct class_device *cdev, char *buf)
++lpfc_state_show(struct device *dev, struct device_attribute *attr,
++		char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	int  len = 0;
+@@ -243,9 +254,10 @@ lpfc_state_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
++lpfc_num_discovered_ports_show(struct device *dev,
++			       struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%d\n",
+@@ -367,9 +379,10 @@ lpfc_selective_reset(struct lpfc_hba *phba)
+ }
+ 
+ static ssize_t
+-lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
++lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
++		 const char *buf, size_t count)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -385,9 +398,10 @@ lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
+ }
+ 
+ static ssize_t
+-lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
++lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -395,9 +409,10 @@ lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_board_mode_show(struct class_device *cdev, char *buf)
++lpfc_board_mode_show(struct device *dev, struct device_attribute *attr,
++		     char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	char  * state;
+@@ -415,9 +430,10 @@ lpfc_board_mode_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
++lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
++		      const char *buf, size_t count)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	struct completion online_compl;
+@@ -509,9 +525,10 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
+ }
+ 
+ static ssize_t
+-lpfc_max_rpi_show(struct class_device *cdev, char *buf)
++lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
++		  char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	uint32_t cnt;
+@@ -522,9 +539,10 @@ lpfc_max_rpi_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_used_rpi_show(struct class_device *cdev, char *buf)
++lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
++		   char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	uint32_t cnt, acnt;
+@@ -535,9 +553,10 @@ lpfc_used_rpi_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_max_xri_show(struct class_device *cdev, char *buf)
++lpfc_max_xri_show(struct device *dev, struct device_attribute *attr,
++		  char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	uint32_t cnt;
+@@ -548,9 +567,10 @@ lpfc_max_xri_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_used_xri_show(struct class_device *cdev, char *buf)
++lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
++		   char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	uint32_t cnt, acnt;
+@@ -561,9 +581,10 @@ lpfc_used_xri_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_max_vpi_show(struct class_device *cdev, char *buf)
++lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
++		  char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	uint32_t cnt;
+@@ -574,9 +595,10 @@ lpfc_max_vpi_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_used_vpi_show(struct class_device *cdev, char *buf)
++lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
++		   char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	uint32_t cnt, acnt;
+@@ -587,9 +609,10 @@ lpfc_used_vpi_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_npiv_info_show(struct class_device *cdev, char *buf)
++lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -601,9 +624,10 @@ lpfc_npiv_info_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_poll_show(struct class_device *cdev, char *buf)
++lpfc_poll_show(struct device *dev, struct device_attribute *attr,
++	       char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -611,10 +635,10 @@ lpfc_poll_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-lpfc_poll_store(struct class_device *cdev, const char *buf,
+-		size_t count)
++lpfc_poll_store(struct device *dev, struct device_attribute *attr,
++		const char *buf, size_t count)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	uint32_t creg_val;
+@@ -670,9 +694,10 @@ lpfc_poll_store(struct class_device *cdev, const char *buf,
+ 
+ #define lpfc_param_show(attr)	\
+ static ssize_t \
+-lpfc_##attr##_show(struct class_device *cdev, char *buf) \
++lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
++		   char *buf) \
+ { \
+-	struct Scsi_Host  *shost = class_to_shost(cdev);\
++	struct Scsi_Host  *shost = class_to_shost(dev);\
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ 	struct lpfc_hba   *phba = vport->phba;\
+ 	int val = 0;\
+@@ -683,9 +708,10 @@ lpfc_##attr##_show(struct class_device *cdev, char *buf) \
+ 
+ #define lpfc_param_hex_show(attr)	\
+ static ssize_t \
+-lpfc_##attr##_show(struct class_device *cdev, char *buf) \
++lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
++		   char *buf) \
+ { \
+-	struct Scsi_Host  *shost = class_to_shost(cdev);\
++	struct Scsi_Host  *shost = class_to_shost(dev);\
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ 	struct lpfc_hba   *phba = vport->phba;\
+ 	int val = 0;\
+@@ -725,9 +751,10 @@ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \
+ 
+ #define lpfc_param_store(attr)	\
+ static ssize_t \
+-lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
++lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
++		    const char *buf, size_t count) \
+ { \
+-	struct Scsi_Host  *shost = class_to_shost(cdev);\
++	struct Scsi_Host  *shost = class_to_shost(dev);\
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ 	struct lpfc_hba   *phba = vport->phba;\
+ 	int val=0;\
+@@ -743,9 +770,10 @@ lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
+ 
+ #define lpfc_vport_param_show(attr)	\
+ static ssize_t \
+-lpfc_##attr##_show(struct class_device *cdev, char *buf) \
++lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
++		   char *buf) \
+ { \
+-	struct Scsi_Host  *shost = class_to_shost(cdev);\
++	struct Scsi_Host  *shost = class_to_shost(dev);\
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ 	int val = 0;\
+ 	val = vport->cfg_##attr;\
+@@ -754,9 +782,10 @@ lpfc_##attr##_show(struct class_device *cdev, char *buf) \
+ 
+ #define lpfc_vport_param_hex_show(attr)	\
+ static ssize_t \
+-lpfc_##attr##_show(struct class_device *cdev, char *buf) \
++lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
++		   char *buf) \
+ { \
+-	struct Scsi_Host  *shost = class_to_shost(cdev);\
++	struct Scsi_Host  *shost = class_to_shost(dev);\
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ 	int val = 0;\
+ 	val = vport->cfg_##attr;\
+@@ -794,9 +823,10 @@ lpfc_##attr##_set(struct lpfc_vport *vport, int val) \
+ 
+ #define lpfc_vport_param_store(attr)	\
+ static ssize_t \
+-lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
++lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
++		    const char *buf, size_t count) \
+ { \
+-	struct Scsi_Host  *shost = class_to_shost(cdev);\
++	struct Scsi_Host  *shost = class_to_shost(dev);\
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ 	int val=0;\
+ 	if (!isdigit(buf[0]))\
+@@ -822,7 +852,7 @@ module_param(lpfc_##name, int, 0);\
+ MODULE_PARM_DESC(lpfc_##name, desc);\
+ lpfc_param_show(name)\
+ lpfc_param_init(name, defval, minval, maxval)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
+ 
+ #define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -832,8 +862,8 @@ lpfc_param_show(name)\
+ lpfc_param_init(name, defval, minval, maxval)\
+ lpfc_param_set(name, defval, minval, maxval)\
+ lpfc_param_store(name)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
+-			 lpfc_##name##_show, lpfc_##name##_store)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
++		   lpfc_##name##_show, lpfc_##name##_store)
+ 
+ #define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -841,7 +871,7 @@ module_param(lpfc_##name, int, 0);\
+ MODULE_PARM_DESC(lpfc_##name, desc);\
+ lpfc_param_hex_show(name)\
+ lpfc_param_init(name, defval, minval, maxval)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
+ 
+ #define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -851,8 +881,8 @@ lpfc_param_hex_show(name)\
+ lpfc_param_init(name, defval, minval, maxval)\
+ lpfc_param_set(name, defval, minval, maxval)\
+ lpfc_param_store(name)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
+-			 lpfc_##name##_show, lpfc_##name##_store)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
++		   lpfc_##name##_show, lpfc_##name##_store)
+ 
+ #define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -866,7 +896,7 @@ module_param(lpfc_##name, int, 0);\
+ MODULE_PARM_DESC(lpfc_##name, desc);\
+ lpfc_vport_param_show(name)\
+ lpfc_vport_param_init(name, defval, minval, maxval)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
+ 
+ #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -876,8 +906,8 @@ lpfc_vport_param_show(name)\
+ lpfc_vport_param_init(name, defval, minval, maxval)\
+ lpfc_vport_param_set(name, defval, minval, maxval)\
+ lpfc_vport_param_store(name)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
+-			 lpfc_##name##_show, lpfc_##name##_store)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
++		   lpfc_##name##_show, lpfc_##name##_store)
+ 
+ #define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -885,7 +915,7 @@ module_param(lpfc_##name, int, 0);\
+ MODULE_PARM_DESC(lpfc_##name, desc);\
+ lpfc_vport_param_hex_show(name)\
+ lpfc_vport_param_init(name, defval, minval, maxval)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
+ 
+ #define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -895,46 +925,44 @@ lpfc_vport_param_hex_show(name)\
+ lpfc_vport_param_init(name, defval, minval, maxval)\
+ lpfc_vport_param_set(name, defval, minval, maxval)\
+ lpfc_vport_param_store(name)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
+-			 lpfc_##name##_show, lpfc_##name##_store)
+-
+-static CLASS_DEVICE_ATTR(info, S_IRUGO, lpfc_info_show, NULL);
+-static CLASS_DEVICE_ATTR(serialnum, S_IRUGO, lpfc_serialnum_show, NULL);
+-static CLASS_DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
+-static CLASS_DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
+-static CLASS_DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
+-static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
+-static CLASS_DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
+-static CLASS_DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
+-static CLASS_DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
+-static CLASS_DEVICE_ATTR(option_rom_version, S_IRUGO,
+-					lpfc_option_rom_version_show, NULL);
+-static CLASS_DEVICE_ATTR(num_discovered_ports, S_IRUGO,
+-					lpfc_num_discovered_ports_show, NULL);
+-static CLASS_DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);
+-static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show,
+-			 NULL);
+-static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
+-			 lpfc_board_mode_show, lpfc_board_mode_store);
+-static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
+-static CLASS_DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
+-static CLASS_DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
+-static CLASS_DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
+-static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
+-static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
+-static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
+-static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
+-static CLASS_DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show,
+-			 NULL);
++static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
++		   lpfc_##name##_show, lpfc_##name##_store)
++
++static DEVICE_ATTR(info, S_IRUGO, lpfc_info_show, NULL);
++static DEVICE_ATTR(serialnum, S_IRUGO, lpfc_serialnum_show, NULL);
++static DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
++static DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
++static DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
++static DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
++static DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
++static DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
++static DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
++static DEVICE_ATTR(option_rom_version, S_IRUGO,
++		   lpfc_option_rom_version_show, NULL);
++static DEVICE_ATTR(num_discovered_ports, S_IRUGO,
++		   lpfc_num_discovered_ports_show, NULL);
++static DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);
++static DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show, NULL);
++static DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
++		   lpfc_board_mode_show, lpfc_board_mode_store);
++static DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
++static DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
++static DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
++static DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
++static DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
++static DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
++static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
++static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
++static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL);
+ 
+ 
+ static char *lpfc_soft_wwn_key = "C99G71SL8032A";
+ 
+ static ssize_t
+-lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
+-				size_t count)
++lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
++			   const char *buf, size_t count)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	unsigned int cnt = count;
+@@ -963,13 +991,14 @@ lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
+ 	phba->soft_wwn_enable = 1;
+ 	return count;
+ }
+-static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
+-				lpfc_soft_wwn_enable_store);
++static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
++		   lpfc_soft_wwn_enable_store);
+ 
+ static ssize_t
+-lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
++lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -979,9 +1008,10 @@ lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
+ 
+ 
+ static ssize_t
+-lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
++lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
++		     const char *buf, size_t count)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	struct completion online_compl;
+@@ -1047,13 +1077,14 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
+ 				"reinit adapter - %d\n", stat2);
+ 	return (stat1 || stat2) ? -EIO : count;
+ }
+-static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
+-			 lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
++static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
++		   lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
+ 
+ static ssize_t
+-lpfc_soft_wwnn_show(struct class_device *cdev, char *buf)
++lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(cdev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+ 	return snprintf(buf, PAGE_SIZE, "0x%llx\n",
+ 			(unsigned long long)phba->cfg_soft_wwnn);
+@@ -1061,9 +1092,10 @@ lpfc_soft_wwnn_show(struct class_device *cdev, char *buf)
+ 
+ 
+ static ssize_t
+-lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count)
++lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
++		     const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = class_to_shost(cdev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+ 	unsigned int i, j, cnt=count;
+ 	u8 wwnn[8];
+@@ -1107,8 +1139,8 @@ lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count)
+ 
+ 	return count;
+ }
+-static CLASS_DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\
+-			 lpfc_soft_wwnn_show, lpfc_soft_wwnn_store);
++static DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\
++		   lpfc_soft_wwnn_show, lpfc_soft_wwnn_store);
+ 
+ 
+ static int lpfc_poll = 0;
+@@ -1118,8 +1150,8 @@ MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
+ 		 " 1 - poll with interrupts enabled"
+ 		 " 3 - poll and disable FCP ring interrupts");
+ 
+-static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
+-			 lpfc_poll_show, lpfc_poll_store);
++static DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
++		   lpfc_poll_show, lpfc_poll_store);
+ 
+ int  lpfc_sli_mode = 0;
+ module_param(lpfc_sli_mode, int, 0);
+@@ -1133,7 +1165,7 @@ module_param(lpfc_enable_npiv, int, 0);
+ MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality");
+ lpfc_param_show(enable_npiv);
+ lpfc_param_init(enable_npiv, 0, 0, 1);
+-static CLASS_DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO,
++static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO,
+ 			 lpfc_enable_npiv_show, NULL);
+ 
+ /*
+@@ -1147,9 +1179,10 @@ MODULE_PARM_DESC(lpfc_nodev_tmo,
+ 		 "Seconds driver will hold I/O waiting "
+ 		 "for a device to come back");
+ static ssize_t
+-lpfc_nodev_tmo_show(struct class_device *cdev, char *buf)
++lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	int val = 0;
+ 	val = vport->cfg_devloss_tmo;
+@@ -1221,8 +1254,8 @@ lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
+ 
+ lpfc_vport_param_store(nodev_tmo)
+ 
+-static CLASS_DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR,
+-			 lpfc_nodev_tmo_show, lpfc_nodev_tmo_store);
++static DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR,
++		   lpfc_nodev_tmo_show, lpfc_nodev_tmo_store);
+ 
+ /*
+ # lpfc_devloss_tmo: If set, it will hold all I/O errors on devices that
+@@ -1255,8 +1288,8 @@ lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val)
+ }
+ 
+ lpfc_vport_param_store(devloss_tmo)
+-static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR,
+-	lpfc_devloss_tmo_show, lpfc_devloss_tmo_store);
++static DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR,
++		   lpfc_devloss_tmo_show, lpfc_devloss_tmo_store);
+ 
+ /*
+ # lpfc_log_verbose: Only turn this flag on if you are willing to risk being
+@@ -1374,8 +1407,8 @@ lpfc_restrict_login_set(struct lpfc_vport *vport, int val)
+ 	return 0;
+ }
+ lpfc_vport_param_store(restrict_login);
+-static CLASS_DEVICE_ATTR(lpfc_restrict_login, S_IRUGO | S_IWUSR,
+-			 lpfc_restrict_login_show, lpfc_restrict_login_store);
++static DEVICE_ATTR(lpfc_restrict_login, S_IRUGO | S_IWUSR,
++		   lpfc_restrict_login_show, lpfc_restrict_login_store);
+ 
+ /*
+ # Some disk devices have a "select ID" or "select Target" capability.
+@@ -1433,7 +1466,7 @@ MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology");
+ lpfc_param_show(topology)
+ lpfc_param_init(topology, 0, 0, 6)
+ lpfc_param_store(topology)
+-static CLASS_DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
++static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
+ 		lpfc_topology_show, lpfc_topology_store);
+ 
+ /*
+@@ -1497,7 +1530,7 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val)
+ }
+ 
+ lpfc_param_store(link_speed)
+-static CLASS_DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
++static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
+ 		lpfc_link_speed_show, lpfc_link_speed_store);
+ 
+ /*
+@@ -1623,82 +1656,81 @@ LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat.");
+ LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT,
+ 	    LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count");
+ 
+-struct class_device_attribute *lpfc_hba_attrs[] = {
+-	&class_device_attr_info,
+-	&class_device_attr_serialnum,
+-	&class_device_attr_modeldesc,
+-	&class_device_attr_modelname,
+-	&class_device_attr_programtype,
+-	&class_device_attr_portnum,
+-	&class_device_attr_fwrev,
+-	&class_device_attr_hdw,
+-	&class_device_attr_option_rom_version,
+-	&class_device_attr_state,
+-	&class_device_attr_num_discovered_ports,
+-	&class_device_attr_lpfc_drvr_version,
+-	&class_device_attr_lpfc_temp_sensor,
+-	&class_device_attr_lpfc_log_verbose,
+-	&class_device_attr_lpfc_lun_queue_depth,
+-	&class_device_attr_lpfc_hba_queue_depth,
+-	&class_device_attr_lpfc_peer_port_login,
+-	&class_device_attr_lpfc_nodev_tmo,
+-	&class_device_attr_lpfc_devloss_tmo,
+-	&class_device_attr_lpfc_fcp_class,
+-	&class_device_attr_lpfc_use_adisc,
+-	&class_device_attr_lpfc_ack0,
+-	&class_device_attr_lpfc_topology,
+-	&class_device_attr_lpfc_scan_down,
+-	&class_device_attr_lpfc_link_speed,
+-	&class_device_attr_lpfc_cr_delay,
+-	&class_device_attr_lpfc_cr_count,
+-	&class_device_attr_lpfc_multi_ring_support,
+-	&class_device_attr_lpfc_multi_ring_rctl,
+-	&class_device_attr_lpfc_multi_ring_type,
+-	&class_device_attr_lpfc_fdmi_on,
+-	&class_device_attr_lpfc_max_luns,
+-	&class_device_attr_lpfc_enable_npiv,
+-	&class_device_attr_nport_evt_cnt,
+-	&class_device_attr_board_mode,
+-	&class_device_attr_max_vpi,
+-	&class_device_attr_used_vpi,
+-	&class_device_attr_max_rpi,
+-	&class_device_attr_used_rpi,
+-	&class_device_attr_max_xri,
+-	&class_device_attr_used_xri,
+-	&class_device_attr_npiv_info,
+-	&class_device_attr_issue_reset,
+-	&class_device_attr_lpfc_poll,
+-	&class_device_attr_lpfc_poll_tmo,
+-	&class_device_attr_lpfc_use_msi,
+-	&class_device_attr_lpfc_soft_wwnn,
+-	&class_device_attr_lpfc_soft_wwpn,
+-	&class_device_attr_lpfc_soft_wwn_enable,
+-	&class_device_attr_lpfc_enable_hba_reset,
+-	&class_device_attr_lpfc_enable_hba_heartbeat,
+-	&class_device_attr_lpfc_sg_seg_cnt,
++struct device_attribute *lpfc_hba_attrs[] = {
++	&dev_attr_info,
++	&dev_attr_serialnum,
++	&dev_attr_modeldesc,
++	&dev_attr_modelname,
++	&dev_attr_programtype,
++	&dev_attr_portnum,
++	&dev_attr_fwrev,
++	&dev_attr_hdw,
++	&dev_attr_option_rom_version,
++	&dev_attr_state,
++	&dev_attr_num_discovered_ports,
++	&dev_attr_lpfc_drvr_version,
++	&dev_attr_lpfc_temp_sensor,
++	&dev_attr_lpfc_log_verbose,
++	&dev_attr_lpfc_lun_queue_depth,
++	&dev_attr_lpfc_hba_queue_depth,
++	&dev_attr_lpfc_peer_port_login,
++	&dev_attr_lpfc_nodev_tmo,
++	&dev_attr_lpfc_devloss_tmo,
++	&dev_attr_lpfc_fcp_class,
++	&dev_attr_lpfc_use_adisc,
++	&dev_attr_lpfc_ack0,
++	&dev_attr_lpfc_topology,
++	&dev_attr_lpfc_scan_down,
++	&dev_attr_lpfc_link_speed,
++	&dev_attr_lpfc_cr_delay,
++	&dev_attr_lpfc_cr_count,
++	&dev_attr_lpfc_multi_ring_support,
++	&dev_attr_lpfc_multi_ring_rctl,
++	&dev_attr_lpfc_multi_ring_type,
++	&dev_attr_lpfc_fdmi_on,
++	&dev_attr_lpfc_max_luns,
++	&dev_attr_lpfc_enable_npiv,
++	&dev_attr_nport_evt_cnt,
++	&dev_attr_board_mode,
++	&dev_attr_max_vpi,
++	&dev_attr_used_vpi,
++	&dev_attr_max_rpi,
++	&dev_attr_used_rpi,
++	&dev_attr_max_xri,
++	&dev_attr_used_xri,
++	&dev_attr_npiv_info,
++	&dev_attr_issue_reset,
++	&dev_attr_lpfc_poll,
++	&dev_attr_lpfc_poll_tmo,
++	&dev_attr_lpfc_use_msi,
++	&dev_attr_lpfc_soft_wwnn,
++	&dev_attr_lpfc_soft_wwpn,
++	&dev_attr_lpfc_soft_wwn_enable,
++	&dev_attr_lpfc_enable_hba_reset,
++	&dev_attr_lpfc_enable_hba_heartbeat,
++	&dev_attr_lpfc_sg_seg_cnt,
+ 	NULL,
+ };
+ 
+-struct class_device_attribute *lpfc_vport_attrs[] = {
+-	&class_device_attr_info,
+-	&class_device_attr_state,
+-	&class_device_attr_num_discovered_ports,
+-	&class_device_attr_lpfc_drvr_version,
+-
+-	&class_device_attr_lpfc_log_verbose,
+-	&class_device_attr_lpfc_lun_queue_depth,
+-	&class_device_attr_lpfc_nodev_tmo,
+-	&class_device_attr_lpfc_devloss_tmo,
+-	&class_device_attr_lpfc_hba_queue_depth,
+-	&class_device_attr_lpfc_peer_port_login,
+-	&class_device_attr_lpfc_restrict_login,
+-	&class_device_attr_lpfc_fcp_class,
+-	&class_device_attr_lpfc_use_adisc,
+-	&class_device_attr_lpfc_fdmi_on,
+-	&class_device_attr_lpfc_max_luns,
+-	&class_device_attr_nport_evt_cnt,
+-	&class_device_attr_npiv_info,
+-	&class_device_attr_lpfc_enable_da_id,
++struct device_attribute *lpfc_vport_attrs[] = {
++	&dev_attr_info,
++	&dev_attr_state,
++	&dev_attr_num_discovered_ports,
++	&dev_attr_lpfc_drvr_version,
++	&dev_attr_lpfc_log_verbose,
++	&dev_attr_lpfc_lun_queue_depth,
++	&dev_attr_lpfc_nodev_tmo,
++	&dev_attr_lpfc_devloss_tmo,
++	&dev_attr_lpfc_hba_queue_depth,
++	&dev_attr_lpfc_peer_port_login,
++	&dev_attr_lpfc_restrict_login,
++	&dev_attr_lpfc_fcp_class,
++	&dev_attr_lpfc_use_adisc,
++	&dev_attr_lpfc_fdmi_on,
++	&dev_attr_lpfc_max_luns,
++	&dev_attr_nport_evt_cnt,
++	&dev_attr_npiv_info,
++	&dev_attr_lpfc_enable_da_id,
+ 	NULL,
+ };
+ 
+@@ -1707,9 +1739,8 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+ 		   char *buf, loff_t off, size_t count)
+ {
+ 	size_t buf_off;
+-	struct class_device *cdev = container_of(kobj, struct class_device,
+-						 kobj);
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct device *dev = container_of(kobj, struct device, kobj);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -1741,9 +1772,8 @@ sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ {
+ 	size_t buf_off;
+ 	uint32_t * tmp_ptr;
+-	struct class_device *cdev = container_of(kobj, struct class_device,
+-						 kobj);
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct device *dev = container_of(kobj, struct device, kobj);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 
+@@ -1798,9 +1828,8 @@ static ssize_t
+ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+ 		 char *buf, loff_t off, size_t count)
+ {
+-	struct class_device *cdev = container_of(kobj, struct class_device,
+-						 kobj);
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct device *dev = container_of(kobj, struct device, kobj);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	struct lpfcMboxq  *mbox = NULL;
+@@ -1853,9 +1882,8 @@ static ssize_t
+ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ 		char *buf, loff_t off, size_t count)
+ {
+-	struct class_device *cdev = container_of(kobj, struct class_device,
+-						 kobj);
+-	struct Scsi_Host  *shost = class_to_shost(cdev);
++	struct device *dev = container_of(kobj, struct device, kobj);
++	struct Scsi_Host  *shost = class_to_shost(dev);
+ 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ 	struct lpfc_hba   *phba = vport->phba;
+ 	int rc;
+@@ -1954,7 +1982,9 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ 			(phba->sysfs_mbox.mbox->mb.mbxCommand !=
+ 				MBX_DUMP_MEMORY &&
+ 			 phba->sysfs_mbox.mbox->mb.mbxCommand !=
+-				MBX_RESTART)) {
++				MBX_RESTART &&
++			 phba->sysfs_mbox.mbox->mb.mbxCommand !=
++				MBX_WRITE_VPARMS)) {
+ 			sysfs_mbox_idle(phba);
+ 			spin_unlock_irq(&phba->hbalock);
+ 			return -EPERM;
+@@ -1962,7 +1992,11 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ 
+ 		phba->sysfs_mbox.mbox->vport = vport;
+ 
+-		if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
++		/* Don't allow mailbox commands to be sent when blocked
++		 * or when in the middle of discovery
++		 */
++		if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO ||
++		    vport->fc_flag & FC_NDISC_ACTIVE) {
+ 			sysfs_mbox_idle(phba);
+ 			spin_unlock_irq(&phba->hbalock);
+ 			return  -EAGAIN;
+@@ -2032,19 +2066,19 @@ lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
+ 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ 	int error;
+ 
+-	error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
++	error = sysfs_create_bin_file(&shost->shost_dev.kobj,
+ 				      &sysfs_ctlreg_attr);
+ 	if (error)
+ 		goto out;
+ 
+-	error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
++	error = sysfs_create_bin_file(&shost->shost_dev.kobj,
+ 				      &sysfs_mbox_attr);
+ 	if (error)
+ 		goto out_remove_ctlreg_attr;
+ 
+ 	return 0;
+ out_remove_ctlreg_attr:
+-	sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
++	sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
+ out:
+ 	return error;
+ }
+@@ -2054,8 +2088,8 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport)
+ {
+ 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ 
+-	sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_mbox_attr);
+-	sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
++	sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
++	sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
+ }
+ 
+ 
+@@ -2437,9 +2471,11 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+ 
+ #define lpfc_rport_show_function(field, format_string, sz, cast)	\
+ static ssize_t								\
+-lpfc_show_rport_##field (struct class_device *cdev, char *buf)		\
++lpfc_show_rport_##field (struct device *dev,				\
++			 struct device_attribute *attr,			\
++			 char *buf)					\
+ {									\
+-	struct fc_rport *rport = transport_class_to_rport(cdev);	\
++	struct fc_rport *rport = transport_class_to_rport(dev);		\
+ 	struct lpfc_rport_data *rdata = rport->hostdata;		\
+ 	return snprintf(buf, sz, format_string,				\
+ 		(rdata->target) ? cast rdata->target->field : 0);	\
+diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
+index 0819f5f..7c9f831 100644
+--- a/drivers/scsi/lpfc/lpfc_crtn.h
++++ b/drivers/scsi/lpfc/lpfc_crtn.h
+@@ -253,8 +253,8 @@ void lpfc_get_cfgparam(struct lpfc_hba *);
+ void lpfc_get_vport_cfgparam(struct lpfc_vport *);
+ int lpfc_alloc_sysfs_attr(struct lpfc_vport *);
+ void lpfc_free_sysfs_attr(struct lpfc_vport *);
+-extern struct class_device_attribute *lpfc_hba_attrs[];
+-extern struct class_device_attribute *lpfc_vport_attrs[];
++extern struct device_attribute *lpfc_hba_attrs[];
++extern struct device_attribute *lpfc_vport_attrs[];
+ extern struct scsi_host_template lpfc_template;
+ extern struct scsi_host_template lpfc_vport_template;
+ extern struct fc_function_template lpfc_transport_functions;
+diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
+index 3d0ccd9..153afae 100644
+--- a/drivers/scsi/lpfc/lpfc_ct.c
++++ b/drivers/scsi/lpfc/lpfc_ct.c
+@@ -63,7 +63,7 @@ lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
+ {
+ 	if (!mp) {
+ 		lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+-				"0146 Ignoring unsolicted CT No HBQ "
++				"0146 Ignoring unsolicited CT No HBQ "
+ 				"status = x%x\n",
+ 				piocbq->iocb.ulpStatus);
+ 	}
+@@ -438,7 +438,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
+ 				    (!(vport->ct_flags & FC_CT_RFF_ID)) ||
+ 				    (!vport->cfg_restrict_login)) {
+ 					ndlp = lpfc_setup_disc_node(vport, Did);
+-					if (ndlp) {
++					if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ 						lpfc_debugfs_disc_trc(vport,
+ 						LPFC_DISC_TRC_CT,
+ 						"Parse GID_FTrsp: "
+@@ -543,7 +543,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 	struct lpfc_dmabuf *outp;
+ 	struct lpfc_sli_ct_request *CTrsp;
+ 	struct lpfc_nodelist *ndlp;
+-	int rc, retry;
++	int rc;
+ 
+ 	/* First save ndlp, before we overwrite it */
+ 	ndlp = cmdiocb->context_un.ndlp;
+@@ -563,45 +563,29 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 	if (vport->load_flag & FC_UNLOADING)
+ 		goto out;
+ 
+-	if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) {
++	if (lpfc_els_chk_latt(vport)) {
+ 		lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ 				 "0216 Link event during NS query\n");
+ 		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+ 		goto out;
+ 	}
+-
++	if (lpfc_error_lost_link(irsp)) {
++		lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
++				 "0226 NS query failed due to link event\n");
++		goto out;
++	}
+ 	if (irsp->ulpStatus) {
+ 		/* Check for retry */
+ 		if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
+-			retry = 1;
+-			if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
+-				switch (irsp->un.ulpWord[4]) {
+-				case IOERR_NO_RESOURCES:
+-					/* We don't increment the retry
+-					 * count for this case.
+-					 */
+-					break;
+-				case IOERR_LINK_DOWN:
+-				case IOERR_SLI_ABORTED:
+-				case IOERR_SLI_DOWN:
+-					retry = 0;
+-					break;
+-				default:
+-					vport->fc_ns_retry++;
+-				}
+-			}
+-			else
++			if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
++			    irsp->un.ulpWord[4] != IOERR_NO_RESOURCES)
+ 				vport->fc_ns_retry++;
+ 
+-			if (retry) {
+-				/* CT command is being retried */
+-				rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
++			/* CT command is being retried */
++			rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
+ 					 vport->fc_ns_retry, 0);
+-				if (rc == 0) {
+-					/* success */
+-					goto out;
+-				}
+-			}
++			if (rc == 0)
++				goto out;
+ 		}
+ 		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+ 		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+@@ -780,7 +764,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 
+ 	/* This is a target port, unregistered port, or the GFF_ID failed */
+ 	ndlp = lpfc_setup_disc_node(vport, did);
+-	if (ndlp) {
++	if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ 		lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ 				 "0242 Process x%x GFF "
+ 				 "NameServer Rsp Data: x%x x%x x%x\n",
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
+index 783d1ee..90272e6 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.c
++++ b/drivers/scsi/lpfc/lpfc_debugfs.c
+@@ -503,6 +503,8 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
+ 				ndlp->nlp_sid);
+ 		if (ndlp->nlp_type & NLP_FCP_INITIATOR)
+ 			len +=  snprintf(buf+len, size-len, "FCP_INITIATOR ");
++		len += snprintf(buf+len, size-len, "usgmap:%x ",
++			ndlp->nlp_usg_map);
+ 		len += snprintf(buf+len, size-len, "refcnt:%x",
+ 			atomic_read(&ndlp->kref.refcount));
+ 		len +=  snprintf(buf+len, size-len, "\n");
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index cbb68a9..886c5f1 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -719,9 +719,9 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
+ 		if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
+ 		    icmd->un.elsreq64.bdl.ulpIoTag32) {
+ 			ndlp = (struct lpfc_nodelist *)(iocb->context1);
+-			if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
++			if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
++			    (ndlp->nlp_DID == Fabric_DID))
+ 				lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+-			}
+ 		}
+ 	}
+ 	spin_unlock_irq(&phba->hbalock);
+@@ -829,7 +829,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
+ 	struct fc_rport *rport;
+ 	struct serv_parm *sp;
+ 	uint8_t  name[sizeof(struct lpfc_name)];
+-	uint32_t rc;
++	uint32_t rc, keepDID = 0;
+ 
+ 	/* Fabric nodes can have the same WWPN so we don't bother searching
+ 	 * by WWPN.  Just return the ndlp that was given to us.
+@@ -858,11 +858,17 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
+ 			return ndlp;
+ 		lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID);
+ 	} else if (!NLP_CHK_NODE_ACT(new_ndlp)) {
++		rc = memcmp(&ndlp->nlp_portname, name,
++			    sizeof(struct lpfc_name));
++		if (!rc)
++			return ndlp;
+ 		new_ndlp = lpfc_enable_node(vport, new_ndlp,
+ 						NLP_STE_UNUSED_NODE);
+ 		if (!new_ndlp)
+ 			return ndlp;
+-	}
++		keepDID = new_ndlp->nlp_DID;
++	} else
++		keepDID = new_ndlp->nlp_DID;
+ 
+ 	lpfc_unreg_rpi(vport, new_ndlp);
+ 	new_ndlp->nlp_DID = ndlp->nlp_DID;
+@@ -893,12 +899,24 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
+ 			}
+ 			new_ndlp->nlp_type = ndlp->nlp_type;
+ 		}
++		/* We shall actually free the ndlp with both nlp_DID and
++		 * nlp_portname fields equals 0 to avoid any ndlp on the
++		 * nodelist never to be used.
++		 */
++		if (ndlp->nlp_DID == 0) {
++			spin_lock_irq(&phba->ndlp_lock);
++			NLP_SET_FREE_REQ(ndlp);
++			spin_unlock_irq(&phba->ndlp_lock);
++		}
+ 
++		/* Two ndlps cannot have the same did on the nodelist */
++		ndlp->nlp_DID = keepDID;
+ 		lpfc_drop_node(vport, ndlp);
+ 	}
+ 	else {
+ 		lpfc_unreg_rpi(vport, ndlp);
+-		ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
++		/* Two ndlps cannot have the same did */
++		ndlp->nlp_DID = keepDID;
+ 		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+ 	}
+ 	return new_ndlp;
+@@ -2091,7 +2109,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 		}
+ 
+ 		phba->fc_stat.elsXmitRetry++;
+-		if (ndlp && delay) {
++		if (ndlp && NLP_CHK_NODE_ACT(ndlp) && delay) {
+ 			phba->fc_stat.elsDelayRetry++;
+ 			ndlp->nlp_retry = cmdiocb->retry;
+ 
+@@ -2121,7 +2139,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 			lpfc_issue_els_fdisc(vport, ndlp, cmdiocb->retry);
+ 			return 1;
+ 		case ELS_CMD_PLOGI:
+-			if (ndlp) {
++			if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ 				ndlp->nlp_prev_state = ndlp->nlp_state;
+ 				lpfc_nlp_set_state(vport, ndlp,
+ 						   NLP_STE_PLOGI_ISSUE);
+@@ -2302,7 +2320,7 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
+ 	kfree(mp);
+ 	mempool_free(pmb, phba->mbox_mem_pool);
+-	if (ndlp) {
++	if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ 		lpfc_nlp_put(ndlp);
+ 		/* This is the end of the default RPI cleanup logic for this
+ 		 * ndlp. If no other discovery threads are using this ndlp.
+@@ -2335,7 +2353,8 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 	 * function can have cmdiocb->contest1 (ndlp) field set to NULL.
+ 	 */
+ 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt);
+-	if (ndlp && (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) {
++	if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
++	    (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) {
+ 		/* A LS_RJT associated with Default RPI cleanup has its own
+ 		 * seperate code path.
+ 		 */
+@@ -2344,7 +2363,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 	}
+ 
+ 	/* Check to see if link went down during discovery */
+-	if (!ndlp || lpfc_els_chk_latt(vport)) {
++	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || lpfc_els_chk_latt(vport)) {
+ 		if (mbox) {
+ 			mp = (struct lpfc_dmabuf *) mbox->context1;
+ 			if (mp) {
+@@ -2353,7 +2372,8 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 			}
+ 			mempool_free(mbox, phba->mbox_mem_pool);
+ 		}
+-		if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
++		if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
++		    (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
+ 			if (lpfc_nlp_not_used(ndlp)) {
+ 				ndlp = NULL;
+ 				/* Indicate the node has already released,
+@@ -2443,7 +2463,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 		mempool_free(mbox, phba->mbox_mem_pool);
+ 	}
+ out:
+-	if (ndlp) {
++	if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ 		spin_lock_irq(shost->host_lock);
+ 		ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
+ 		spin_unlock_irq(shost->host_lock);
+@@ -3139,6 +3159,8 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+ 		/* Another thread is walking fc_rscn_id_list on this vport */
+ 		spin_unlock_irq(shost->host_lock);
+ 		vport->fc_flag |= FC_RSCN_DISCOVERY;
++		/* Send back ACC */
++		lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
+ 		return 0;
+ 	}
+ 	/* Indicate we are walking fc_rscn_id_list on this vport */
+@@ -3928,7 +3950,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
+ 		else {
+ 			struct lpfc_nodelist *ndlp;
+ 			ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext);
+-			if (ndlp)
++			if (ndlp && NLP_CHK_NODE_ACT(ndlp))
+ 				remote_ID = ndlp->nlp_DID;
+ 		}
+ 		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+@@ -4097,21 +4119,22 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ 		newnode = 1;
+ 		if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
+ 			ndlp->nlp_type |= NLP_FABRIC;
+-	} else {
+-		if (!NLP_CHK_NODE_ACT(ndlp)) {
+-			ndlp = lpfc_enable_node(vport, ndlp,
+-						NLP_STE_UNUSED_NODE);
+-			if (!ndlp)
+-				goto dropit;
+-		}
+-		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
+-			/* This is simular to the new node path */
+-			ndlp = lpfc_nlp_get(ndlp);
+-			if (!ndlp)
+-				goto dropit;
+-			lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+-			newnode = 1;
+-		}
++	} else if (!NLP_CHK_NODE_ACT(ndlp)) {
++		ndlp = lpfc_enable_node(vport, ndlp,
++					NLP_STE_UNUSED_NODE);
++		if (!ndlp)
++			goto dropit;
++		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++		newnode = 1;
++		if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
++			ndlp->nlp_type |= NLP_FABRIC;
++	} else if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
++		/* This is similar to the new node path */
++		ndlp = lpfc_nlp_get(ndlp);
++		if (!ndlp)
++			goto dropit;
++		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++		newnode = 1;
+ 	}
+ 
+ 	phba->fc_stat.elsRcvFrame++;
+@@ -4451,7 +4474,6 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+ 			return;
+ 		}
+ 		lpfc_nlp_init(vport, ndlp, NameServer_DID);
+-		ndlp->nlp_type |= NLP_FABRIC;
+ 	} else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ 		ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+ 		if (!ndlp) {
+@@ -4465,6 +4487,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+ 			return;
+ 		}
+ 	}
++	ndlp->nlp_type |= NLP_FABRIC;
+ 
+ 	lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+ 
+@@ -4481,8 +4504,8 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+ 		if (ndlp_fdmi) {
+ 			lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
+ 			ndlp_fdmi->nlp_type |= NLP_FABRIC;
+-			ndlp_fdmi->nlp_state =
+-				NLP_STE_PLOGI_ISSUE;
++			lpfc_nlp_set_state(vport, ndlp_fdmi,
++				NLP_STE_PLOGI_ISSUE);
+ 			lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
+ 					     0);
+ 		}
+@@ -5074,39 +5097,3 @@ void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
+ 		(piocb->iocb_cmpl) (phba, piocb, piocb);
+ 	}
+ }
+-
+-
+-#if 0
+-void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
+-{
+-	LIST_HEAD(completions);
+-	struct lpfc_iocbq *tmp_iocb, *piocb;
+-	IOCB_t *cmd;
+-	struct lpfc_nodelist *ndlp;
+-
+-	spin_lock_irq(&phba->hbalock);
+-	list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
+-				 list) {
+-
+-		cmd = &piocb->iocb;
+-		ndlp = (struct lpfc_nodelist *) piocb->context1;
+-		if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
+-		    ndlp != NULL &&
+-		    ndlp->nlp_DID == Fabric_DID)
+-			list_move_tail(&piocb->list, &completions);
+-	}
+-	spin_unlock_irq(&phba->hbalock);
+-
+-	while (!list_empty(&completions)) {
+-		piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+-		list_del_init(&piocb->list);
+-
+-		cmd = &piocb->iocb;
+-		cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+-		cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+-		(piocb->iocb_cmpl) (phba, piocb, piocb);
+-	}
+-}
+-#endif  /*  0  */
+-
+-
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index 9766534..7cb68fe 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -69,7 +69,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
+ 	rdata = rport->dd_data;
+ 	ndlp = rdata->pnode;
+ 
+-	if (!ndlp) {
++	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
+ 		if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ 			printk(KERN_ERR "Cannot find remote node"
+ 			" to terminate I/O Data x%x\n",
+@@ -114,7 +114,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
+ 
+ 	rdata = rport->dd_data;
+ 	ndlp = rdata->pnode;
+-	if (!ndlp)
++	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+ 		return;
+ 
+ 	vport = ndlp->vport;
+@@ -243,8 +243,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
+ 	if (warn_on) {
+ 		lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ 				 "0203 Devloss timeout on "
+-				 "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
+-				 "NPort x%x Data: x%x x%x x%x\n",
++				 "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
++				 "NPort x%06x Data: x%x x%x x%x\n",
+ 				 *name, *(name+1), *(name+2), *(name+3),
+ 				 *(name+4), *(name+5), *(name+6), *(name+7),
+ 				 ndlp->nlp_DID, ndlp->nlp_flag,
+@@ -252,8 +252,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
+ 	} else {
+ 		lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ 				 "0204 Devloss timeout on "
+-				 "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
+-				 "NPort x%x Data: x%x x%x x%x\n",
++				 "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
++				 "NPort x%06x Data: x%x x%x x%x\n",
+ 				 *name, *(name+1), *(name+2), *(name+3),
+ 				 *(name+4), *(name+5), *(name+6), *(name+7),
+ 				 ndlp->nlp_DID, ndlp->nlp_flag,
+@@ -399,7 +399,10 @@ lpfc_work_done(struct lpfc_hba *phba)
+ 				vport = vports[i];
+ 			if (vport == NULL)
+ 				break;
++			spin_lock_irq(&vport->work_port_lock);
+ 			work_port_events = vport->work_port_events;
++			vport->work_port_events &= ~work_port_events;
++			spin_unlock_irq(&vport->work_port_lock);
+ 			if (work_port_events & WORKER_DISC_TMO)
+ 				lpfc_disc_timeout_handler(vport);
+ 			if (work_port_events & WORKER_ELS_TMO)
+@@ -416,9 +419,6 @@ lpfc_work_done(struct lpfc_hba *phba)
+ 				lpfc_ramp_down_queue_handler(phba);
+ 			if (work_port_events & WORKER_RAMP_UP_QUEUE)
+ 				lpfc_ramp_up_queue_handler(phba);
+-			spin_lock_irq(&vport->work_port_lock);
+-			vport->work_port_events &= ~work_port_events;
+-			spin_unlock_irq(&vport->work_port_lock);
+ 		}
+ 	lpfc_destroy_vport_work_array(phba, vports);
+ 
+@@ -430,10 +430,10 @@ lpfc_work_done(struct lpfc_hba *phba)
+ 		if (pring->flag & LPFC_STOP_IOCB_EVENT) {
+ 			pring->flag |= LPFC_DEFERRED_RING_EVENT;
+ 		} else {
++			pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
+ 			lpfc_sli_handle_slow_ring_event(phba, pring,
+ 							(status &
+ 							 HA_RXMASK));
+-			pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
+ 		}
+ 		/*
+ 		 * Turn on Ring interrupts
+@@ -519,7 +519,9 @@ lpfc_do_work(void *p)
+ 			schedule();
+ 		}
+ 	}
++	spin_lock_irq(&phba->hbalock);
+ 	phba->work_wait = NULL;
++	spin_unlock_irq(&phba->hbalock);
+ 	return 0;
+ }
+ 
+@@ -809,11 +811,9 @@ out:
+ 	mempool_free(pmb, phba->mbox_mem_pool);
+ 
+ 	spin_lock_irq(shost->host_lock);
+-	vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_ESTABLISH_LINK);
++	vport->fc_flag &= ~FC_ABORT_DISCOVERY;
+ 	spin_unlock_irq(shost->host_lock);
+ 
+-	del_timer_sync(&phba->fc_estabtmo);
+-
+ 	lpfc_can_disctmo(vport);
+ 
+ 	/* turn on Link Attention interrupts */
+@@ -1340,10 +1340,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ 			    i++) {
+ 				if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
+ 					continue;
++				if (phba->fc_topology == TOPOLOGY_LOOP) {
++					lpfc_vport_set_state(vports[i],
++							FC_VPORT_LINKDOWN);
++					continue;
++				}
+ 				if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
+ 					lpfc_initial_fdisc(vports[i]);
+-				else if (phba->sli3_options &
+-						LPFC_SLI3_NPIV_ENABLED) {
++				else {
+ 					lpfc_vport_set_state(vports[i],
+ 						FC_VPORT_NO_FABRIC_SUPP);
+ 					lpfc_printf_vlog(vport, KERN_ERR,
+@@ -2190,10 +2194,6 @@ lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ 	if (did == Bcast_DID)
+ 		return 0;
+ 
+-	if (ndlp->nlp_DID == 0) {
+-		return 0;
+-	}
+-
+ 	/* First check for Direct match */
+ 	if (ndlp->nlp_DID == did)
+ 		return 1;
+@@ -2301,7 +2301,8 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
+ 		return ndlp;
+ 	}
+ 
+-	if (vport->fc_flag & FC_RSCN_MODE) {
++	if ((vport->fc_flag & FC_RSCN_MODE) &&
++	    !(vport->fc_flag & FC_NDISC_ACTIVE)) {
+ 		if (lpfc_rscn_payload_check(vport, did)) {
+ 			/* If we've already recieved a PLOGI from this NPort
+ 			 * we don't need to try to discover it again.
+@@ -2947,24 +2948,6 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
+ 	return NULL;
+ }
+ 
+-#if 0
+-/*
+- * Search node lists for a remote port matching filter criteria
+- * Caller needs to hold host_lock before calling this routine.
+- */
+-struct lpfc_nodelist *
+-lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
+-{
+-	struct Scsi_Host     *shost = lpfc_shost_from_vport(vport);
+-	struct lpfc_nodelist *ndlp;
+-
+-	spin_lock_irq(shost->host_lock);
+-	ndlp = __lpfc_find_node(vport, filter, param);
+-	spin_unlock_irq(shost->host_lock);
+-	return ndlp;
+-}
+-#endif  /*  0  */
+-
+ /*
+  * This routine looks up the ndlp lists for the given RPI. If rpi found it
+  * returns the node list element pointer else return NULL.
+@@ -2975,20 +2958,6 @@ __lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
+ 	return __lpfc_find_node(vport, lpfc_filter_by_rpi, &rpi);
+ }
+ 
+-#if 0
+-struct lpfc_nodelist *
+-lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
+-{
+-	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+-	struct lpfc_nodelist *ndlp;
+-
+-	spin_lock_irq(shost->host_lock);
+-	ndlp = __lpfc_findnode_rpi(vport, rpi);
+-	spin_unlock_irq(shost->host_lock);
+-	return ndlp;
+-}
+-#endif  /*  0  */
+-
+ /*
+  * This routine looks up the ndlp lists for the given WWPN. If WWPN found it
+  * returns the node element list pointer else return NULL.
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 2284375..fa757b2 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -559,8 +559,10 @@ lpfc_hb_timeout(unsigned long ptr)
+ 		phba->pport->work_port_events |= WORKER_HB_TMO;
+ 	spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+ 
++	spin_lock_irqsave(&phba->hbalock, iflag);
+ 	if (phba->work_wait)
+ 		wake_up(phba->work_wait);
++	spin_unlock_irqrestore(&phba->hbalock, iflag);
+ 	return;
+ }
+ 
+@@ -714,12 +716,10 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
+ 	struct lpfc_vport *vport = phba->pport;
+ 	struct lpfc_sli   *psli = &phba->sli;
+ 	struct lpfc_sli_ring  *pring;
+-	struct lpfc_vport **vports;
+ 	uint32_t event_data;
+ 	unsigned long temperature;
+ 	struct temp_event temp_event_data;
+ 	struct Scsi_Host  *shost;
+-	int i;
+ 
+ 	/* If the pci channel is offline, ignore possible errors,
+ 	 * since we cannot communicate with the pci card anyway. */
+@@ -729,25 +729,14 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
+ 	if (!phba->cfg_enable_hba_reset)
+ 		return;
+ 
+-	if (phba->work_hs & HS_FFER6 ||
+-	    phba->work_hs & HS_FFER5) {
++	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]);
+-		vports = lpfc_create_vport_work_array(phba);
+-		if (vports != NULL)
+-			for(i = 0;
+-			    i <= phba->max_vpi && vports[i] != NULL;
+-			    i++){
+-				shost = lpfc_shost_from_vport(vports[i]);
+-				spin_lock_irq(shost->host_lock);
+-				vports[i]->fc_flag |= FC_ESTABLISH_LINK;
+-				spin_unlock_irq(shost->host_lock);
+-			}
+-		lpfc_destroy_vport_work_array(phba, vports);
++
+ 		spin_lock_irq(&phba->hbalock);
+ 		psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+ 		spin_unlock_irq(&phba->hbalock);
+@@ -761,7 +750,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
+ 		pring = &psli->ring[psli->fcp_ring];
+ 		lpfc_sli_abort_iocb_ring(phba, pring);
+ 
+-
+ 		/*
+ 		 * There was a firmware error.  Take the hba offline and then
+ 		 * attempt to restart it.
+@@ -770,7 +758,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
+ 		lpfc_offline(phba);
+ 		lpfc_sli_brdrestart(phba);
+ 		if (lpfc_online(phba) == 0) {	/* Initialize the HBA */
+-			mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+ 			lpfc_unblock_mgmt_io(phba);
+ 			return;
+ 		}
+@@ -1454,6 +1441,13 @@ lpfc_cleanup(struct lpfc_vport *vport)
+ 			NLP_SET_FREE_REQ(ndlp);
+ 		spin_unlock_irq(&phba->ndlp_lock);
+ 
++		if (vport->port_type != LPFC_PHYSICAL_PORT &&
++		    ndlp->nlp_DID == Fabric_DID) {
++			/* Just free up ndlp with Fabric_DID for vports */
++			lpfc_nlp_put(ndlp);
++			continue;
++		}
++
+ 		if (ndlp->nlp_type & NLP_FABRIC)
+ 			lpfc_disc_state_machine(vport, ndlp, NULL,
+ 					NLP_EVT_DEVICE_RECOVERY);
+@@ -1491,31 +1485,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
+ 	return;
+ }
+ 
+-static void
+-lpfc_establish_link_tmo(unsigned long ptr)
+-{
+-	struct lpfc_hba   *phba = (struct lpfc_hba *) ptr;
+-	struct lpfc_vport **vports;
+-	unsigned long iflag;
+-	int i;
+-
+-	/* Re-establishing Link, timer expired */
+-	lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
+-			"1300 Re-establishing Link, timer expired "
+-			"Data: x%x x%x\n",
+-			phba->pport->fc_flag, phba->pport->port_state);
+-	vports = lpfc_create_vport_work_array(phba);
+-	if (vports != NULL)
+-		for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
+-			struct Scsi_Host *shost;
+-			shost = lpfc_shost_from_vport(vports[i]);
+-			spin_lock_irqsave(shost->host_lock, iflag);
+-			vports[i]->fc_flag &= ~FC_ESTABLISH_LINK;
+-			spin_unlock_irqrestore(shost->host_lock, iflag);
+-		}
+-	lpfc_destroy_vport_work_array(phba, vports);
+-}
+-
+ void
+ lpfc_stop_vport_timers(struct lpfc_vport *vport)
+ {
+@@ -1529,7 +1498,6 @@ static void
+ lpfc_stop_phba_timers(struct lpfc_hba *phba)
+ {
+ 	del_timer_sync(&phba->fcp_poll_timer);
+-	del_timer_sync(&phba->fc_estabtmo);
+ 	lpfc_stop_vport_timers(phba->pport);
+ 	del_timer_sync(&phba->sli.mbox_tmo);
+ 	del_timer_sync(&phba->fabric_block_timer);
+@@ -2005,10 +1973,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
+ 	phba->max_vpi = LPFC_MAX_VPI;
+ 
+ 	/* Initialize timers used by driver */
+-	init_timer(&phba->fc_estabtmo);
+-	phba->fc_estabtmo.function = lpfc_establish_link_tmo;
+-	phba->fc_estabtmo.data = (unsigned long)phba;
+-
+ 	init_timer(&phba->hb_tmofunc);
+ 	phba->hb_tmofunc.function = lpfc_hb_timeout;
+ 	phba->hb_tmofunc.data = (unsigned long)phba;
+@@ -2406,6 +2370,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
+ 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+ 	struct lpfc_sli *psli = &phba->sli;
++	int error, retval;
+ 
+ 	dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
+ 	if (pci_enable_device_mem(pdev)) {
+@@ -2416,15 +2381,40 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
+ 
+ 	pci_set_master(pdev);
+ 
+-	/* Re-establishing Link */
+-	spin_lock_irq(shost->host_lock);
+-	phba->pport->fc_flag |= FC_ESTABLISH_LINK;
+-	spin_unlock_irq(shost->host_lock);
+-
+ 	spin_lock_irq(&phba->hbalock);
+ 	psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+ 	spin_unlock_irq(&phba->hbalock);
+ 
++	/* Enable configured interrupt method */
++	phba->intr_type = NONE;
++	if (phba->cfg_use_msi == 2) {
++		error = lpfc_enable_msix(phba);
++		if (!error)
++			phba->intr_type = MSIX;
++	}
++
++	/* Fallback to MSI if MSI-X initialization failed */
++	if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
++		retval = pci_enable_msi(phba->pcidev);
++		if (!retval)
++			phba->intr_type = MSI;
++		else
++			lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
++					"0470 Enable MSI failed, continuing "
++					"with IRQ\n");
++	}
++
++	/* MSI-X is the only case the doesn't need to call request_irq */
++	if (phba->intr_type != MSIX) {
++		retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
++				     IRQF_SHARED, LPFC_DRIVER_NAME, phba);
++		if (retval) {
++			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++					"0471 Enable interrupt handler "
++					"failed\n");
++		} else if (phba->intr_type != MSI)
++			phba->intr_type = INTx;
++	}
+ 
+ 	/* Take device offline; this will perform cleanup */
+ 	lpfc_offline(phba);
+@@ -2445,9 +2435,7 @@ static void lpfc_io_resume(struct pci_dev *pdev)
+ 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ 	struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+ 
+-	if (lpfc_online(phba) == 0) {
+-		mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+-	}
++	lpfc_online(phba);
+ }
+ 
+ static struct pci_device_id lpfc_id_table[] = {
+diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
+index d513813..d08c4c8 100644
+--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
+@@ -451,7 +451,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ 			spin_unlock_irq(shost->host_lock);
+ 
+ 			if ((ndlp->nlp_flag & NLP_ADISC_SND) &&
+-				(vport->num_disc_nodes)) {
++			    (vport->num_disc_nodes)) {
+ 				/* Check to see if there are more
+ 				 * ADISCs to be sent
+ 				 */
+@@ -469,20 +469,23 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ 					lpfc_end_rscn(vport);
+ 				}
+ 			}
+-			else if (vport->num_disc_nodes) {
+-				/* Check to see if there are more
+-				 * PLOGIs to be sent
+-				 */
+-				lpfc_more_plogi(vport);
+-
+-				if (vport->num_disc_nodes == 0) {
+-					spin_lock_irq(shost->host_lock);
+-					vport->fc_flag &= ~FC_NDISC_ACTIVE;
+-					spin_unlock_irq(shost->host_lock);
+-					lpfc_can_disctmo(vport);
+-					lpfc_end_rscn(vport);
+-				}
+-			}
++		}
++	} else if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) &&
++		   (ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
++		   (vport->num_disc_nodes)) {
++		spin_lock_irq(shost->host_lock);
++		ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
++		spin_unlock_irq(shost->host_lock);
++		/* Check to see if there are more
++		 * PLOGIs to be sent
++		 */
++		lpfc_more_plogi(vport);
++		if (vport->num_disc_nodes == 0) {
++			spin_lock_irq(shost->host_lock);
++			vport->fc_flag &= ~FC_NDISC_ACTIVE;
++			spin_unlock_irq(shost->host_lock);
++			lpfc_can_disctmo(vport);
++			lpfc_end_rscn(vport);
+ 		}
+ 	}
+ 
+@@ -869,8 +872,11 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
+ 
+ 	lp = (uint32_t *) prsp->virt;
+ 	sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+-	if (wwn_to_u64(sp->portName.u.wwn) == 0 ||
+-	    wwn_to_u64(sp->nodeName.u.wwn) == 0) {
++
++	/* Some switches have FDMI servers returning 0 for WWN */
++	if ((ndlp->nlp_DID != FDMI_DID) &&
++		(wwn_to_u64(sp->portName.u.wwn) == 0 ||
++		wwn_to_u64(sp->nodeName.u.wwn) == 0)) {
+ 		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ 				 "0142 PLOGI RSP: Invalid WWN.\n");
+ 		goto out;
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 70255c1..0910a9a 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -169,6 +169,9 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
+ 		for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
+ 			shost = lpfc_shost_from_vport(vports[i]);
+ 			shost_for_each_device(sdev, shost) {
++				if (vports[i]->cfg_lun_queue_depth <=
++				    sdev->queue_depth)
++					continue;
+ 				if (sdev->ordered_tags)
+ 					scsi_adjust_queue_depth(sdev,
+ 							MSG_ORDERED_TAG,
+@@ -578,14 +581,14 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ 			    lpfc_cmd->result == IOERR_NO_RESOURCES ||
+ 			    lpfc_cmd->result == RJT_LOGIN_REQUIRED) {
+ 				cmd->result = ScsiResult(DID_REQUEUE, 0);
+-			break;
+-		} /* else: fall through */
++				break;
++			} /* else: fall through */
+ 		default:
+ 			cmd->result = ScsiResult(DID_ERROR, 0);
+ 			break;
+ 		}
+ 
+-		if ((pnode == NULL )
++		if (!pnode || !NLP_CHK_NODE_ACT(pnode)
+ 		    || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
+ 			cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY);
+ 	} else {
+@@ -606,6 +609,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ 	result = cmd->result;
+ 	sdev = cmd->device;
+ 	lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
++	spin_lock_irqsave(sdev->host->host_lock, flags);
++	lpfc_cmd->pCmd = NULL;	/* This must be done before scsi_done */
++	spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ 	cmd->scsi_done(cmd);
+ 
+ 	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+@@ -614,7 +620,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ 		 * wake up the thread.
+ 		 */
+ 		spin_lock_irqsave(sdev->host->host_lock, flags);
+-		lpfc_cmd->pCmd = NULL;
+ 		if (lpfc_cmd->waitq)
+ 			wake_up(lpfc_cmd->waitq);
+ 		spin_unlock_irqrestore(sdev->host->host_lock, flags);
+@@ -626,7 +631,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ 	if (!result)
+ 		lpfc_rampup_queue_depth(vport, sdev);
+ 
+-	if (!result && pnode != NULL &&
++	if (!result && pnode && NLP_CHK_NODE_ACT(pnode) &&
+ 	   ((jiffies - pnode->last_ramp_up_time) >
+ 		LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
+ 	   ((jiffies - pnode->last_q_full_time) >
+@@ -654,7 +659,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ 	 * Check for queue full.  If the lun is reporting queue full, then
+ 	 * back off the lun queue depth to prevent target overloads.
+ 	 */
+-	if (result == SAM_STAT_TASK_SET_FULL && pnode != NULL) {
++	if (result == SAM_STAT_TASK_SET_FULL && pnode &&
++	    NLP_CHK_NODE_ACT(pnode)) {
+ 		pnode->last_q_full_time = jiffies;
+ 
+ 		shost_for_each_device(tmp_sdev, sdev->host) {
+@@ -684,7 +690,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ 	 * wake up the thread.
+ 	 */
+ 	spin_lock_irqsave(sdev->host->host_lock, flags);
+-	lpfc_cmd->pCmd = NULL;
+ 	if (lpfc_cmd->waitq)
+ 		wake_up(lpfc_cmd->waitq);
+ 	spin_unlock_irqrestore(sdev->host->host_lock, flags);
+@@ -704,6 +709,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
+ 	int datadir = scsi_cmnd->sc_data_direction;
+ 	char tag[2];
+ 
++	if (!pnode || !NLP_CHK_NODE_ACT(pnode))
++		return;
++
+ 	lpfc_cmd->fcp_rsp->rspSnsLen = 0;
+ 	/* clear task management bits */
+ 	lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
+@@ -785,9 +793,9 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
+ 	struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
+ 	struct lpfc_nodelist *ndlp = rdata->pnode;
+ 
+-	if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
++	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
++	    ndlp->nlp_state != NLP_STE_MAPPED_NODE)
+ 		return 0;
+-	}
+ 
+ 	piocbq = &(lpfc_cmd->cur_iocbq);
+ 	piocbq->vport = vport;
+@@ -842,7 +850,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
+ 	struct lpfc_iocbq *iocbqrsp;
+ 	int ret;
+ 
+-	if (!rdata->pnode)
++	if (!rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode))
+ 		return FAILED;
+ 
+ 	lpfc_cmd->rdata = rdata;
+@@ -959,7 +967,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
+ 	 * Catch race where our node has transitioned, but the
+ 	 * transport is still transitioning.
+ 	 */
+-	if (!ndlp) {
++	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
+ 		cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+ 		goto out_fail_command;
+ 	}
+@@ -1146,7 +1154,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
+ 	 * target is rediscovered or devloss timeout expires.
+ 	 */
+ 	while (1) {
+-		if (!pnode)
++		if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+ 			goto out;
+ 
+ 		if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
+@@ -1162,7 +1170,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
+ 				goto out;
+ 			}
+ 			pnode = rdata->pnode;
+-			if (!pnode)
++			if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+ 				goto out;
+ 		}
+ 		if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index fc0d950..70a0a9e 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -2648,7 +2648,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
+ 	spin_unlock_irq(&phba->pport->work_port_lock);
+ 	spin_lock_irq(&phba->hbalock);
+ 	phba->link_state = LPFC_LINK_UNKNOWN;
+-	phba->pport->fc_flag |= FC_ESTABLISH_LINK;
+ 	psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+ 	spin_unlock_irq(&phba->hbalock);
+ 
+@@ -2669,8 +2668,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
+ 	lpfc_offline_prep(phba);
+ 	lpfc_offline(phba);
+ 	lpfc_sli_brdrestart(phba);
+-	if (lpfc_online(phba) == 0)		/* Initialize the HBA */
+-		mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
++	lpfc_online(phba);
+ 	lpfc_unblock_mgmt_io(phba);
+ 	return;
+ }
+@@ -2687,28 +2685,41 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ 	unsigned long drvr_flag = 0;
+ 	volatile uint32_t word0, ldata;
+ 	void __iomem *to_slim;
++	int processing_queue = 0;
++
++	spin_lock_irqsave(&phba->hbalock, drvr_flag);
++	if (!pmbox) {
++		/* processing mbox queue from intr_handler */
++		processing_queue = 1;
++		phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
++		pmbox = lpfc_mbox_get(phba);
++		if (!pmbox) {
++			spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
++			return MBX_SUCCESS;
++		}
++	}
+ 
+ 	if (pmbox->mbox_cmpl && pmbox->mbox_cmpl != lpfc_sli_def_mbox_cmpl &&
+ 		pmbox->mbox_cmpl != lpfc_sli_wake_mbox_wait) {
+ 		if(!pmbox->vport) {
++			spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ 			lpfc_printf_log(phba, KERN_ERR,
+ 					LOG_MBOX | LOG_VPORT,
+ 					"1806 Mbox x%x failed. No vport\n",
+ 					pmbox->mb.mbxCommand);
+ 			dump_stack();
+-			return MBX_NOT_FINISHED;
++			goto out_not_finished;
+ 		}
+ 	}
+ 
+-
+ 	/* If the PCI channel is in offline state, do not post mbox. */
+-	if (unlikely(pci_channel_offline(phba->pcidev)))
+-		return MBX_NOT_FINISHED;
++	if (unlikely(pci_channel_offline(phba->pcidev))) {
++		spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
++		goto out_not_finished;
++	}
+ 
+-	spin_lock_irqsave(&phba->hbalock, drvr_flag);
+ 	psli = &phba->sli;
+ 
+-
+ 	mb = &pmbox->mb;
+ 	status = MBX_SUCCESS;
+ 
+@@ -2717,14 +2728,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ 
+ 		/* Mbox command <mbxCommand> cannot issue */
+ 		LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+-		return MBX_NOT_FINISHED;
++		goto out_not_finished;
+ 	}
+ 
+ 	if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
+ 	    !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
+ 		spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ 		LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+-		return MBX_NOT_FINISHED;
++		goto out_not_finished;
+ 	}
+ 
+ 	if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
+@@ -2738,14 +2749,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ 
+ 			/* Mbox command <mbxCommand> cannot issue */
+ 			LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+-			return MBX_NOT_FINISHED;
++			goto out_not_finished;
+ 		}
+ 
+ 		if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
+ 			spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ 			/* Mbox command <mbxCommand> cannot issue */
+ 			LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+-			return MBX_NOT_FINISHED;
++			goto out_not_finished;
+ 		}
+ 
+ 		/* Another mailbox command is still being processed, queue this
+@@ -2792,7 +2803,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ 			spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ 			/* Mbox command <mbxCommand> cannot issue */
+ 			LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+-			return MBX_NOT_FINISHED;
++			goto out_not_finished;
+ 		}
+ 		/* timeout active mbox command */
+ 		mod_timer(&psli->mbox_tmo, (jiffies +
+@@ -2900,7 +2911,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ 				psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ 				spin_unlock_irqrestore(&phba->hbalock,
+ 						       drvr_flag);
+-				return MBX_NOT_FINISHED;
++				goto out_not_finished;
+ 			}
+ 
+ 			/* Check if we took a mbox interrupt while we were
+@@ -2967,6 +2978,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ 
+ 	spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ 	return status;
++
++out_not_finished:
++	if (processing_queue) {
++		pmbox->mb.mbxStatus = MBX_NOT_FINISHED;
++		lpfc_mbox_cmpl_put(phba, pmbox);
++	}
++	return MBX_NOT_FINISHED;
+ }
+ 
+ /*
+@@ -3463,26 +3481,21 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
+ 	phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+ 	spin_unlock(&phba->pport->work_port_lock);
+ 
++	/* Return any pending or completed mbox cmds */
++	list_splice_init(&phba->sli.mboxq, &completions);
+ 	if (psli->mbox_active) {
+ 		list_add_tail(&psli->mbox_active->list, &completions);
+ 		psli->mbox_active = NULL;
+ 		psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ 	}
+-
+-	/* Return any pending or completed mbox cmds */
+-	list_splice_init(&phba->sli.mboxq, &completions);
+ 	list_splice_init(&phba->sli.mboxq_cmpl, &completions);
+-	INIT_LIST_HEAD(&psli->mboxq);
+-	INIT_LIST_HEAD(&psli->mboxq_cmpl);
+-
+ 	spin_unlock_irqrestore(&phba->hbalock, flags);
+ 
+ 	while (!list_empty(&completions)) {
+ 		list_remove_head(&completions, pmb, LPFC_MBOXQ_t, list);
+ 		pmb->mb.mbxStatus = MBX_NOT_FINISHED;
+-		if (pmb->mbox_cmpl) {
++		if (pmb->mbox_cmpl)
+ 			pmb->mbox_cmpl(phba,pmb);
+-		}
+ 	}
+ 	return 1;
+ }
+@@ -3613,6 +3626,15 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ 				irsp->ulpStatus, irsp->un.ulpWord[4]);
+ 
+ 		/*
++		 *  If the iocb is not found in Firmware queue the iocb
++		 *  might have completed already. Do not free it again.
++		 */
++		if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
++			spin_unlock_irq(&phba->hbalock);
++			lpfc_sli_release_iocbq(phba, cmdiocb);
++			return;
++		}
++		/*
+ 		 * make sure we have the right iocbq before taking it
+ 		 * off the txcmplq and try to call completion routine.
+ 		 */
+@@ -4174,6 +4196,7 @@ lpfc_intr_handler(int irq, void *dev_id)
+ 			phba->pport->stopped = 1;
+ 		}
+ 
++		spin_lock(&phba->hbalock);
+ 		if ((work_ha_copy & HA_MBATT) &&
+ 		    (phba->sli.mbox_active)) {
+ 			pmb = phba->sli.mbox_active;
+@@ -4184,6 +4207,7 @@ lpfc_intr_handler(int irq, void *dev_id)
+ 			/* First check out the status word */
+ 			lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
+ 			if (pmbox->mbxOwner != OWN_HOST) {
++				spin_unlock(&phba->hbalock);
+ 				/*
+ 				 * Stray Mailbox Interrupt, mbxCommand <cmd>
+ 				 * mbxStatus <status>
+@@ -4199,10 +4223,10 @@ lpfc_intr_handler(int irq, void *dev_id)
+ 				/* clear mailbox attention bit */
+ 				work_ha_copy &= ~HA_MBATT;
+ 			} else {
++				phba->sli.mbox_active = NULL;
++				spin_unlock(&phba->hbalock);
+ 				phba->last_completion_time = jiffies;
+ 				del_timer(&phba->sli.mbox_tmo);
+-
+-				phba->sli.mbox_active = NULL;
+ 				if (pmb->mbox_cmpl) {
+ 					lpfc_sli_pcimem_bcopy(mbox, pmbox,
+ 							MAILBOX_CMD_SIZE);
+@@ -4237,10 +4261,15 @@ lpfc_intr_handler(int irq, void *dev_id)
+ 						pmb->context1 = mp;
+ 						pmb->context2 = ndlp;
+ 						pmb->vport = vport;
+-						spin_lock(&phba->hbalock);
+-						phba->sli.sli_flag &=
+-							~LPFC_SLI_MBOX_ACTIVE;
+-						spin_unlock(&phba->hbalock);
++						rc = lpfc_sli_issue_mbox(phba,
++								pmb,
++								MBX_NOWAIT);
++						if (rc != MBX_BUSY)
++							lpfc_printf_log(phba,
++							KERN_ERR,
++							LOG_MBOX | LOG_SLI,
++							"0306 rc should have"
++							"been MBX_BUSY");
+ 						goto send_current_mbox;
+ 					}
+ 				}
+@@ -4250,25 +4279,20 @@ lpfc_intr_handler(int irq, void *dev_id)
+ 				spin_unlock(&phba->pport->work_port_lock);
+ 				lpfc_mbox_cmpl_put(phba, pmb);
+ 			}
+-		}
++		} else
++			spin_unlock(&phba->hbalock);
+ 		if ((work_ha_copy & HA_MBATT) &&
+ 		    (phba->sli.mbox_active == NULL)) {
+-send_next_mbox:
+-			spin_lock(&phba->hbalock);
+-			phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+-			pmb = lpfc_mbox_get(phba);
+-			spin_unlock(&phba->hbalock);
+ send_current_mbox:
+ 			/* Process next mailbox command if there is one */
+-			if (pmb != NULL) {
+-				rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+-				if (rc == MBX_NOT_FINISHED) {
+-					pmb->mb.mbxStatus = MBX_NOT_FINISHED;
+-					lpfc_mbox_cmpl_put(phba, pmb);
+-					goto send_next_mbox;
+-				}
+-			}
+-
++			do {
++				rc = lpfc_sli_issue_mbox(phba, NULL,
++							 MBX_NOWAIT);
++			} while (rc == MBX_NOT_FINISHED);
++			if (rc != MBX_SUCCESS)
++				lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
++						LOG_SLI, "0349 rc should be "
++						"MBX_SUCCESS");
+ 		}
+ 
+ 		spin_lock(&phba->hbalock);
+diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
+index ca540d1..b22b893 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.2.5"
++#define LPFC_DRIVER_VERSION "8.2.6"
+ 
+ #define LPFC_DRIVER_NAME "lpfc"
+ 
+diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
+index 86d05be..6feaf59 100644
+--- a/drivers/scsi/lpfc/lpfc_vport.c
++++ b/drivers/scsi/lpfc/lpfc_vport.c
+@@ -538,7 +538,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
+ 	/* Otherwise, we will perform fabric logo as needed */
+ 	if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
+ 	    ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
+-	    phba->link_state >= LPFC_LINK_UP) {
++	    phba->link_state >= LPFC_LINK_UP &&
++	    phba->fc_topology != TOPOLOGY_LOOP) {
+ 		if (vport->cfg_enable_da_id) {
+ 			timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
+ 			if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0))
+diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
+index 3b09ab2..0248919 100644
+--- a/drivers/scsi/mac_scsi.c
++++ b/drivers/scsi/mac_scsi.c
+@@ -592,7 +592,6 @@ static struct scsi_host_template driver_template = {
+ 	.this_id			= 7,
+ 	.sg_tablesize			= SG_ALL,
+ 	.cmd_per_lun			= CMD_PER_LUN,
+-	.unchecked_isa_dma		= 0,
+ 	.use_clustering			= DISABLE_CLUSTERING
+ };
+ 
+diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
+index fef9ac9..f62ed46 100644
+--- a/drivers/scsi/megaraid/mega_common.h
++++ b/drivers/scsi/megaraid/mega_common.h
+@@ -28,7 +28,6 @@
+ #include <linux/list.h>
+ #include <linux/moduleparam.h>
+ #include <linux/dma-mapping.h>
+-#include <asm/semaphore.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_device.h>
+diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h
+index 706fa05..05f6e4e 100644
+--- a/drivers/scsi/megaraid/megaraid_ioctl.h
++++ b/drivers/scsi/megaraid/megaraid_ioctl.h
+@@ -18,7 +18,7 @@
+ #define _MEGARAID_IOCTL_H_
+ 
+ #include <linux/types.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ 
+ #include "mbox_defs.h"
+ 
+diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
+index 9f04192..820f91f 100644
+--- a/drivers/scsi/megaraid/megaraid_mbox.c
++++ b/drivers/scsi/megaraid/megaraid_mbox.c
+@@ -125,7 +125,7 @@ static irqreturn_t megaraid_isr(int, void *);
+ 
+ static void megaraid_mbox_dpc(unsigned long);
+ 
+-static ssize_t megaraid_sysfs_show_app_hndl(struct class_device *, char *);
++static ssize_t megaraid_sysfs_show_app_hndl(struct device *, struct device_attribute *attr, char *);
+ static ssize_t megaraid_sysfs_show_ldnum(struct device *, struct device_attribute *attr, char *);
+ 
+ static int megaraid_cmm_register(adapter_t *);
+@@ -313,12 +313,12 @@ static struct pci_driver megaraid_pci_driver = {
+ // definitions for the device attributes for exporting logical drive number
+ // for a scsi address (Host, Channel, Id, Lun)
+ 
+-CLASS_DEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl,
++DEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl,
+ 		NULL);
+ 
+ // Host template initializer for megaraid mbox sysfs device attributes
+-static struct class_device_attribute *megaraid_shost_attrs[] = {
+-	&class_device_attr_megaraid_mbox_app_hndl,
++static struct device_attribute *megaraid_shost_attrs[] = {
++	&dev_attr_megaraid_mbox_app_hndl,
+ 	NULL,
+ };
+ 
+@@ -4063,9 +4063,10 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter)
+  * handle, since we do not interface with applications directly.
+  */
+ static ssize_t
+-megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf)
++megaraid_sysfs_show_app_hndl(struct device *dev, struct device_attribute *attr,
++			     char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(cdev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	adapter_t	*adapter = (adapter_t *)SCSIHOST2ADAP(shost);
+ 	uint32_t	app_hndl;
+ 
+diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
+index 77a62a1..b937e9c 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.c
++++ b/drivers/scsi/megaraid/megaraid_sas.c
+@@ -68,6 +68,8 @@ static struct pci_device_id megasas_pci_table[] = {
+ 	/* xscale IOP */
+ 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
+ 	/* ppc IOP */
++	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
++	/* ppc IOP */
+ 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
+ 	/* xscale IOP, vega */
+ 	{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
+@@ -488,12 +490,13 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 
+  /**
+  * megasas_get_frame_count - Computes the number of frames
++ * @frame_type		: type of frame- io or pthru frame
+  * @sge_count		: number of sg elements
+  *
+  * Returns the number of frames required for numnber of sge's (sge_count)
+  */
+ 
+-static u32 megasas_get_frame_count(u8 sge_count)
++static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
+ {
+ 	int num_cnt;
+ 	int sge_bytes;
+@@ -504,13 +507,22 @@ static u32 megasas_get_frame_count(u8 sge_count)
+ 	    sizeof(struct megasas_sge32);
+ 
+ 	/*
+-	* Main frame can contain 2 SGEs for 64-bit SGLs and
+-	* 3 SGEs for 32-bit SGLs
+-	*/
+-	if (IS_DMA64)
+-		num_cnt = sge_count - 2;
+-	else
+-		num_cnt = sge_count - 3;
++	 * Main frame can contain 2 SGEs for 64-bit SGLs and
++	 * 3 SGEs for 32-bit SGLs for ldio &
++	 * 1 SGEs for 64-bit SGLs and
++	 * 2 SGEs for 32-bit SGLs for pthru frame
++	 */
++	if (unlikely(frame_type == PTHRU_FRAME)) {
++		if (IS_DMA64)
++			num_cnt = sge_count - 1;
++		else
++			num_cnt = sge_count - 2;
++	} else {
++		if (IS_DMA64)
++			num_cnt = sge_count - 2;
++		else
++			num_cnt = sge_count - 3;
++	}
+ 
+ 	if(num_cnt>0){
+ 		sge_bytes = sge_sz * num_cnt;
+@@ -592,7 +604,8 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 	 * Compute the total number of frames this command consumes. FW uses
+ 	 * this number to pull sufficient number of frames from host memory.
+ 	 */
+-	cmd->frame_count = megasas_get_frame_count(pthru->sge_count);
++	cmd->frame_count = megasas_get_frame_count(pthru->sge_count,
++							PTHRU_FRAME);
+ 
+ 	return cmd->frame_count;
+ }
+@@ -709,7 +722,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ 	 * Compute the total number of frames this command consumes. FW uses
+ 	 * this number to pull sufficient number of frames from host memory.
+ 	 */
+-	cmd->frame_count = megasas_get_frame_count(ldio->sge_count);
++	cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME);
+ 
+ 	return cmd->frame_count;
+ }
+@@ -1460,7 +1473,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ 			instance->instancet->disable_intr(instance->reg_set);
+ 			writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
+ 
+-			max_wait = 10;
++			max_wait = 60;
+ 			cur_state = MFI_STATE_OPERATIONAL;
+ 			break;
+ 
+@@ -1980,7 +1993,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+ 
+ 	switch(instance->pdev->device)
+ 	{
+-		case PCI_DEVICE_ID_LSI_SAS1078R:	
++		case PCI_DEVICE_ID_LSI_SAS1078R:
++		case PCI_DEVICE_ID_LSI_SAS1078DE:
+ 			instance->instancet = &megasas_instance_template_ppc;
+ 			break;
+ 		case PCI_DEVICE_ID_LSI_SAS1064R:
+@@ -2909,7 +2923,6 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
+ 	void *sense = NULL;
+ 	dma_addr_t sense_handle;
+ 	u32 *sense_ptr;
+-	unsigned long *sense_buff;
+ 
+ 	memset(kbuff_arr, 0, sizeof(kbuff_arr));
+ 
+@@ -3014,14 +3027,14 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
+ 	 */
+ 	if (ioc->sense_len) {
+ 		/*
+-		 * sense_buff points to the location that has the user
++		 * sense_ptr points to the location that has the user
+ 		 * sense buffer address
+ 		 */
+-		sense_buff = (unsigned long *) ((unsigned long)ioc->frame.raw +
+-								ioc->sense_off);
++		sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
++				     ioc->sense_off);
+ 
+-		if (copy_to_user((void __user *)(unsigned long)(*sense_buff),
+-				sense, ioc->sense_len)) {
++		if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
++				 sense, ioc->sense_len)) {
+ 			printk(KERN_ERR "megasas: Failed to copy out to user "
+ 					"sense data\n");
+ 			error = -EFAULT;
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 6466bdf..3a997eb 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -26,6 +26,7 @@
+  * Device IDs
+  */
+ #define	PCI_DEVICE_ID_LSI_SAS1078R		0x0060
++#define	PCI_DEVICE_ID_LSI_SAS1078DE		0x007C
+ #define	PCI_DEVICE_ID_LSI_VERDE_ZCR		0x0413
+ 
+ /*
+@@ -542,6 +543,10 @@ struct megasas_ctrl_info {
+ 
+ #define MEGASAS_FW_BUSY				1
+ 
++/* Frame Type */
++#define IO_FRAME				0
++#define PTHRU_FRAME				1
++
+ /*
+  * When SCSI mid-layer calls driver's reset routine, driver waits for
+  * MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
+diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
+index be41aad..d722235 100644
+--- a/drivers/scsi/mvme147.c
++++ b/drivers/scsi/mvme147.c
+@@ -82,6 +82,9 @@ int mvme147_detect(struct scsi_host_template *tpnt)
+     mvme147_host->irq = MVME147_IRQ_SCSI_PORT;
+     regs.SASR = (volatile unsigned char *)0xfffe4000;
+     regs.SCMD = (volatile unsigned char *)0xfffe4001;
++    HDATA(mvme147_host)->no_sync = 0xff;
++    HDATA(mvme147_host)->fast = 0;
++    HDATA(mvme147_host)->dma_mode = CTRL_DMA;
+     wd33c93_init(mvme147_host, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
+ 
+     if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, "MVME147 SCSI PORT", mvme147_intr))
+diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
+index c5ebf01..d892894 100644
+--- a/drivers/scsi/ncr53c8xx.c
++++ b/drivers/scsi/ncr53c8xx.c
+@@ -8243,7 +8243,8 @@ static void process_waiting_list(struct ncb *np, int sts)
+ 
+ #undef next_wcmd
+ 
+-static ssize_t show_ncr53c8xx_revision(struct class_device *dev, char *buf)
++static ssize_t show_ncr53c8xx_revision(struct device *dev,
++				       struct device_attribute *attr, char *buf)
+ {
+ 	struct Scsi_Host *host = class_to_shost(dev);
+ 	struct host_data *host_data = (struct host_data *)host->hostdata;
+@@ -8251,12 +8252,12 @@ static ssize_t show_ncr53c8xx_revision(struct class_device *dev, char *buf)
+ 	return snprintf(buf, 20, "0x%x\n", host_data->ncb->revision_id);
+ }
+   
+-static struct class_device_attribute ncr53c8xx_revision_attr = {
++static struct device_attribute ncr53c8xx_revision_attr = {
+ 	.attr	= { .name = "revision", .mode = S_IRUGO, },
+ 	.show	= show_ncr53c8xx_revision,
+ };
+   
+-static struct class_device_attribute *ncr53c8xx_host_attrs[] = {
++static struct device_attribute *ncr53c8xx_host_attrs[] = {
+ 	&ncr53c8xx_revision_attr,
+ 	NULL
+ };
+diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
+index abef704..31f7aec 100644
+--- a/drivers/scsi/osst.c
++++ b/drivers/scsi/osst.c
+@@ -5591,9 +5591,10 @@ static void osst_remove_sysfs_files(struct device_driver *sysfs)
+  * sysfs support for accessing ADR header information
+  */
+ 
+-static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_adr_rev_show(struct device *dev,
++				 struct device_attribute *attr, char *buf)
+ {
+-	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ 	ssize_t l = 0;
+ 
+ 	if (STp && STp->header_ok && STp->linux_media)
+@@ -5601,11 +5602,13 @@ static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
++DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
+ 
+-static ssize_t osst_linux_media_version_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_linux_media_version_show(struct device *dev,
++					     struct device_attribute *attr,
++					     char *buf)
+ {
+-	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ 	ssize_t l = 0;
+ 
+ 	if (STp && STp->header_ok && STp->linux_media)
+@@ -5613,11 +5616,12 @@ static ssize_t osst_linux_media_version_show(struct class_device *class_dev, cha
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
++DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
+ 
+-static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_capacity_show(struct device *dev,
++				  struct device_attribute *attr, char *buf)
+ {
+-	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ 	ssize_t l = 0;
+ 
+ 	if (STp && STp->header_ok && STp->linux_media)
+@@ -5625,11 +5629,13 @@ static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
++DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
+ 
+-static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_first_data_ppos_show(struct device *dev,
++					 struct device_attribute *attr,
++					 char *buf)
+ {
+-	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ 	ssize_t l = 0;
+ 
+ 	if (STp && STp->header_ok && STp->linux_media)
+@@ -5637,11 +5643,13 @@ static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *b
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
++DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
+ 
+-static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_eod_frame_ppos_show(struct device *dev,
++					struct device_attribute *attr,
++					char *buf)
+ {
+-	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ 	ssize_t l = 0;
+ 
+ 	if (STp && STp->header_ok && STp->linux_media)
+@@ -5649,11 +5657,12 @@ static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *bu
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
++DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
+ 
+-static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_filemark_cnt_show(struct device *dev,
++				      struct device_attribute *attr, char *buf)
+ {
+-	struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++	struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ 	ssize_t l = 0;
+ 
+ 	if (STp && STp->header_ok && STp->linux_media)
+@@ -5661,7 +5670,7 @@ static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
++DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
+ 
+ static struct class *osst_sysfs_class;
+ 
+@@ -5678,44 +5687,37 @@ static int osst_sysfs_init(void)
+ 
+ static void osst_sysfs_destroy(dev_t dev)
+ {
+-	class_device_destroy(osst_sysfs_class, dev);
++	device_destroy(osst_sysfs_class, dev);
+ }
+ 
+ static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
+ {
+-	struct class_device *osst_class_member;
++	struct device *osst_member;
+ 	int err;
+ 
+-	osst_class_member = class_device_create(osst_sysfs_class, NULL, dev,
+-						device, "%s", name);
+-	if (IS_ERR(osst_class_member)) {
++	osst_member = device_create(osst_sysfs_class, device, dev, "%s", name);
++	if (IS_ERR(osst_member)) {
+ 		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
+-		return PTR_ERR(osst_class_member);
++		return PTR_ERR(osst_member);
+ 	}
+ 
+-	class_set_devdata(osst_class_member, STp);
+-	err = class_device_create_file(osst_class_member,
+-				       &class_device_attr_ADR_rev);
++	dev_set_drvdata(osst_member, STp);
++	err = device_create_file(osst_member, &dev_attr_ADR_rev);
+ 	if (err)
+ 		goto err_out;
+-	err = class_device_create_file(osst_class_member,
+-				       &class_device_attr_media_version);
++	err = device_create_file(osst_member, &dev_attr_media_version);
+ 	if (err)
+ 		goto err_out;
+-	err = class_device_create_file(osst_class_member,
+-				       &class_device_attr_capacity);
++	err = device_create_file(osst_member, &dev_attr_capacity);
+ 	if (err)
+ 		goto err_out;
+-	err = class_device_create_file(osst_class_member,
+-				       &class_device_attr_BOT_frame);
++	err = device_create_file(osst_member, &dev_attr_BOT_frame);
+ 	if (err)
+ 		goto err_out;
+-	err = class_device_create_file(osst_class_member,
+-				       &class_device_attr_EOD_frame);
++	err = device_create_file(osst_member, &dev_attr_EOD_frame);
+ 	if (err)
+ 		goto err_out;
+-	err = class_device_create_file(osst_class_member,
+-				       &class_device_attr_file_count);
++	err = device_create_file(osst_member, &dev_attr_file_count);
+ 	if (err)
+ 		goto err_out;
+ 
+diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
+index 3454a57..0be232b 100644
+--- a/drivers/scsi/pcmcia/sym53c500_cs.c
++++ b/drivers/scsi/pcmcia/sym53c500_cs.c
+@@ -632,9 +632,10 @@ SYM53C500_biosparm(struct scsi_device *disk,
+ }
+ 
+ static ssize_t
+-SYM53C500_show_pio(struct class_device *cdev, char *buf)
++SYM53C500_show_pio(struct device *dev, struct device_attribute *attr,
++		   char *buf)
+ {
+-	struct Scsi_Host *SHp = class_to_shost(cdev);
++	struct Scsi_Host *SHp = class_to_shost(dev);
+ 	struct sym53c500_data *data =
+ 	    (struct sym53c500_data *)SHp->hostdata;
+ 
+@@ -642,10 +643,11 @@ SYM53C500_show_pio(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-SYM53C500_store_pio(struct class_device *cdev, const char *buf, size_t count)
++SYM53C500_store_pio(struct device *dev, struct device_attribute *attr,
++		    const char *buf, size_t count)
+ {
+ 	int pio;
+-	struct Scsi_Host *SHp = class_to_shost(cdev);
++	struct Scsi_Host *SHp = class_to_shost(dev);
+ 	struct sym53c500_data *data =
+ 	    (struct sym53c500_data *)SHp->hostdata;
+ 
+@@ -662,7 +664,7 @@ SYM53C500_store_pio(struct class_device *cdev, const char *buf, size_t count)
+ *  SCSI HBA device attributes we want to
+ *  make available via sysfs.
+ */
+-static struct class_device_attribute SYM53C500_pio_attr = {
++static struct device_attribute SYM53C500_pio_attr = {
+ 	.attr = {
+ 		.name = "fast_pio",
+ 		.mode = (S_IRUGO | S_IWUSR),
+@@ -671,7 +673,7 @@ static struct class_device_attribute SYM53C500_pio_attr = {
+ 	.store = SYM53C500_store_pio,
+ };
+ 
+-static struct class_device_attribute *SYM53C500_shost_attrs[] = {
++static struct device_attribute *SYM53C500_shost_attrs[] = {
+ 	&SYM53C500_pio_attr,
+ 	NULL,
+ };
+diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
+index fad6cb5..ce48e2d 100644
+--- a/drivers/scsi/ps3rom.c
++++ b/drivers/scsi/ps3rom.c
+@@ -26,6 +26,7 @@
+ #include <scsi/scsi_dbg.h>
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_host.h>
++#include <scsi/scsi_eh.h>
+ 
+ #include <asm/lv1call.h>
+ #include <asm/ps3stor.h>
+@@ -90,78 +91,6 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
+ 	return 0;
+ }
+ 
+-/*
+- * copy data from device into scatter/gather buffer
+- */
+-static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
+-{
+-	int k, req_len, act_len, len, active;
+-	void *kaddr;
+-	struct scatterlist *sgpnt;
+-	unsigned int buflen;
+-
+-	buflen = scsi_bufflen(cmd);
+-	if (!buflen)
+-		return 0;
+-
+-	if (!scsi_sglist(cmd))
+-		return -1;
+-
+-	active = 1;
+-	req_len = act_len = 0;
+-	scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
+-		if (active) {
+-			kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
+-			len = sgpnt->length;
+-			if ((req_len + len) > buflen) {
+-				active = 0;
+-				len = buflen - req_len;
+-			}
+-			memcpy(kaddr + sgpnt->offset, buf + req_len, len);
+-			flush_kernel_dcache_page(sg_page(sgpnt));
+-			kunmap_atomic(kaddr, KM_IRQ0);
+-			act_len += len;
+-		}
+-		req_len += sgpnt->length;
+-	}
+-	scsi_set_resid(cmd, buflen - act_len);
+-	return 0;
+-}
+-
+-/*
+- * copy data from scatter/gather into device's buffer
+- */
+-static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf)
+-{
+-	int k, req_len, len, fin;
+-	void *kaddr;
+-	struct scatterlist *sgpnt;
+-	unsigned int buflen;
+-
+-	buflen = scsi_bufflen(cmd);
+-	if (!buflen)
+-		return 0;
+-
+-	if (!scsi_sglist(cmd))
+-		return -1;
+-
+-	req_len = fin = 0;
+-	scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
+-		kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
+-		len = sgpnt->length;
+-		if ((req_len + len) > buflen) {
+-			len = buflen - req_len;
+-			fin = 1;
+-		}
+-		memcpy(buf + req_len, kaddr + sgpnt->offset, len);
+-		kunmap_atomic(kaddr, KM_IRQ0);
+-		if (fin)
+-			return req_len + len;
+-		req_len += sgpnt->length;
+-	}
+-	return req_len;
+-}
+-
+ static int ps3rom_atapi_request(struct ps3_storage_device *dev,
+ 				struct scsi_cmnd *cmd)
+ {
+@@ -195,9 +124,7 @@ static int ps3rom_atapi_request(struct ps3_storage_device *dev,
+ 		else
+ 			atapi_cmnd.proto = PIO_DATA_OUT_PROTO;
+ 		atapi_cmnd.in_out = DIR_WRITE;
+-		res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
+-		if (res < 0)
+-			return DID_ERROR << 16;
++		scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
+ 		break;
+ 
+ 	default:
+@@ -269,9 +196,7 @@ static int ps3rom_write_request(struct ps3_storage_device *dev,
+ 	dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n",
+ 		__func__, __LINE__, sectors, start_sector);
+ 
+-	res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
+-	if (res < 0)
+-		return DID_ERROR << 16;
++	scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
+ 
+ 	res = lv1_storage_write(dev->sbd.dev_id,
+ 				dev->regions[dev->region_idx].id, start_sector,
+@@ -381,11 +306,13 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data)
+ 	if (!status) {
+ 		/* OK, completed */
+ 		if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
+-			res = fill_from_dev_buffer(cmd, dev->bounce_buf);
+-			if (res) {
+-				cmd->result = DID_ERROR << 16;
+-				goto done;
+-			}
++			int len;
++
++			len = scsi_sg_copy_from_buffer(cmd,
++						       dev->bounce_buf,
++						       dev->bounce_size);
++
++			scsi_set_resid(cmd, scsi_bufflen(cmd) - len);
+ 		}
+ 		cmd->result = DID_OK << 16;
+ 		goto done;
+@@ -404,11 +331,7 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data)
+ 		goto done;
+ 	}
+ 
+-	cmd->sense_buffer[0]  = 0x70;
+-	cmd->sense_buffer[2]  = sense_key;
+-	cmd->sense_buffer[7]  = 16 - 6;
+-	cmd->sense_buffer[12] = asc;
+-	cmd->sense_buffer[13] = ascq;
++	scsi_build_sense_buffer(0, cmd->sense_buffer, sense_key, asc, ascq);
+ 	cmd->result = SAM_STAT_CHECK_CONDITION;
+ 
+ done:
+@@ -427,7 +350,7 @@ static struct scsi_host_template ps3rom_host_template = {
+ 	.cmd_per_lun =		1,
+ 	.emulated =             1,		/* only sg driver uses this */
+ 	.max_sectors =		PS3ROM_MAX_SECTORS,
+-	.use_clustering =	DISABLE_CLUSTERING,
++	.use_clustering =	ENABLE_CLUSTERING,
+ 	.module =		THIS_MODULE,
+ };
+ 
+diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
+index 68c0d09..09ab3ea 100644
+--- a/drivers/scsi/qla1280.c
++++ b/drivers/scsi/qla1280.c
+@@ -333,7 +333,6 @@
+ 
+ #include <linux/module.h>
+ 
+-#include <linux/version.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+ #include <linux/errno.h>
+@@ -367,10 +366,6 @@
+ #include <asm/sn/io.h>
+ #endif
+ 
+-#if LINUX_VERSION_CODE < 0x020600
+-#error "Kernels older than 2.6.0 are no longer supported"
+-#endif
+-
+ 
+ /*
+  * Compile time Options:
+diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
+index 8c865b9..6208d56 100644
+--- a/drivers/scsi/qla2xxx/Kconfig
++++ b/drivers/scsi/qla2xxx/Kconfig
+@@ -16,7 +16,8 @@ config SCSI_QLA_FC
+ 	22xx              ql2200_fw.bin
+ 	2300, 2312, 6312  ql2300_fw.bin
+ 	2322, 6322        ql2322_fw.bin
+-	24xx              ql2400_fw.bin
++	24xx, 54xx        ql2400_fw.bin
++	25xx              ql2500_fw.bin
+ 
+ 	Upon request, the driver caches the firmware image until
+ 	the driver is unloaded.
+diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
+index 4894dc8..d61df03 100644
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -530,15 +530,17 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
+ /* Scsi_Host attributes. */
+ 
+ static ssize_t
+-qla2x00_drvr_version_show(struct class_device *cdev, char *buf)
++qla2x00_drvr_version_show(struct device *dev,
++			  struct device_attribute *attr, char *buf)
+ {
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
+ }
+ 
+ static ssize_t
+-qla2x00_fw_version_show(struct class_device *cdev, char *buf)
++qla2x00_fw_version_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	char fw_str[30];
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%s\n",
+@@ -546,9 +548,10 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-qla2x00_serial_num_show(struct class_device *cdev, char *buf)
++qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	uint32_t sn;
+ 
+ 	if (IS_FWI2_CAPABLE(ha))
+@@ -560,40 +563,45 @@ qla2x00_serial_num_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-qla2x00_isp_name_show(struct class_device *cdev, char *buf)
++qla2x00_isp_name_show(struct device *dev, struct device_attribute *attr,
++		      char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device);
+ }
+ 
+ static ssize_t
+-qla2x00_isp_id_show(struct class_device *cdev, char *buf)
++qla2x00_isp_id_show(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
+ 	    ha->product_id[0], ha->product_id[1], ha->product_id[2],
+ 	    ha->product_id[3]);
+ }
+ 
+ static ssize_t
+-qla2x00_model_name_show(struct class_device *cdev, char *buf)
++qla2x00_model_name_show(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number);
+ }
+ 
+ static ssize_t
+-qla2x00_model_desc_show(struct class_device *cdev, char *buf)
++qla2x00_model_desc_show(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	return snprintf(buf, PAGE_SIZE, "%s\n",
+ 	    ha->model_desc ? ha->model_desc: "");
+ }
+ 
+ static ssize_t
+-qla2x00_pci_info_show(struct class_device *cdev, char *buf)
++qla2x00_pci_info_show(struct device *dev, struct device_attribute *attr,
++		      char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	char pci_info[30];
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%s\n",
+@@ -601,9 +609,10 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-qla2x00_state_show(struct class_device *cdev, char *buf)
++qla2x00_state_show(struct device *dev, struct device_attribute *attr,
++		   char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	int len = 0;
+ 
+ 	if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
+@@ -639,9 +648,10 @@ qla2x00_state_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-qla2x00_zio_show(struct class_device *cdev, char *buf)
++qla2x00_zio_show(struct device *dev, struct device_attribute *attr,
++		 char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	int len = 0;
+ 
+ 	switch (ha->zio_mode) {
+@@ -656,9 +666,10 @@ qla2x00_zio_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
++qla2x00_zio_store(struct device *dev, struct device_attribute *attr,
++		  const char *buf, size_t count)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	int val = 0;
+ 	uint16_t zio_mode;
+ 
+@@ -682,18 +693,19 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
+ }
+ 
+ static ssize_t
+-qla2x00_zio_timer_show(struct class_device *cdev, char *buf)
++qla2x00_zio_timer_show(struct device *dev, struct device_attribute *attr,
++		       char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100);
+ }
+ 
+ static ssize_t
+-qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
+-    size_t count)
++qla2x00_zio_timer_store(struct device *dev, struct device_attribute *attr,
++			const char *buf, size_t count)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	int val = 0;
+ 	uint16_t zio_timer;
+ 
+@@ -709,9 +721,10 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
+ }
+ 
+ static ssize_t
+-qla2x00_beacon_show(struct class_device *cdev, char *buf)
++qla2x00_beacon_show(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	int len = 0;
+ 
+ 	if (ha->beacon_blink_led)
+@@ -722,10 +735,10 @@ qla2x00_beacon_show(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-qla2x00_beacon_store(struct class_device *cdev, const char *buf,
+-    size_t count)
++qla2x00_beacon_store(struct device *dev, struct device_attribute *attr,
++		     const char *buf, size_t count)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 	int val = 0;
+ 	int rval;
+ 
+@@ -753,84 +766,86 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf,
+ }
+ 
+ static ssize_t
+-qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf)
++qla2x00_optrom_bios_version_show(struct device *dev,
++				 struct device_attribute *attr, char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
+ 	    ha->bios_revision[0]);
+ }
+ 
+ static ssize_t
+-qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf)
++qla2x00_optrom_efi_version_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
+ 	    ha->efi_revision[0]);
+ }
+ 
+ static ssize_t
+-qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf)
++qla2x00_optrom_fcode_version_show(struct device *dev,
++				  struct device_attribute *attr, char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1],
+ 	    ha->fcode_revision[0]);
+ }
+ 
+ static ssize_t
+-qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf)
++qla2x00_optrom_fw_version_show(struct device *dev,
++			       struct device_attribute *attr, char *buf)
+ {
+-	scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++	scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ 
+ 	return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n",
+ 	    ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2],
+ 	    ha->fw_revision[3]);
+ }
+ 
+-static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
+-	NULL);
+-static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
+-static CLASS_DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
+-static CLASS_DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
+-static CLASS_DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
+-static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
+-static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
+-static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
+-static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
+-static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show,
+-    qla2x00_zio_store);
+-static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
+-    qla2x00_zio_timer_store);
+-static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
+-    qla2x00_beacon_store);
+-static CLASS_DEVICE_ATTR(optrom_bios_version, S_IRUGO,
+-    qla2x00_optrom_bios_version_show, NULL);
+-static CLASS_DEVICE_ATTR(optrom_efi_version, S_IRUGO,
+-    qla2x00_optrom_efi_version_show, NULL);
+-static CLASS_DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
+-    qla2x00_optrom_fcode_version_show, NULL);
+-static CLASS_DEVICE_ATTR(optrom_fw_version, S_IRUGO,
+-    qla2x00_optrom_fw_version_show, NULL);
+-
+-struct class_device_attribute *qla2x00_host_attrs[] = {
+-	&class_device_attr_driver_version,
+-	&class_device_attr_fw_version,
+-	&class_device_attr_serial_num,
+-	&class_device_attr_isp_name,
+-	&class_device_attr_isp_id,
+-	&class_device_attr_model_name,
+-	&class_device_attr_model_desc,
+-	&class_device_attr_pci_info,
+-	&class_device_attr_state,
+-	&class_device_attr_zio,
+-	&class_device_attr_zio_timer,
+-	&class_device_attr_beacon,
+-	&class_device_attr_optrom_bios_version,
+-	&class_device_attr_optrom_efi_version,
+-	&class_device_attr_optrom_fcode_version,
+-	&class_device_attr_optrom_fw_version,
++static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
++static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
++static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
++static DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
++static DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
++static DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
++static DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
++static DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
++static DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
++static DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, qla2x00_zio_store);
++static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
++		   qla2x00_zio_timer_store);
++static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
++		   qla2x00_beacon_store);
++static DEVICE_ATTR(optrom_bios_version, S_IRUGO,
++		   qla2x00_optrom_bios_version_show, NULL);
++static DEVICE_ATTR(optrom_efi_version, S_IRUGO,
++		   qla2x00_optrom_efi_version_show, NULL);
++static DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
++		   qla2x00_optrom_fcode_version_show, NULL);
++static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
++		   NULL);
++
++struct device_attribute *qla2x00_host_attrs[] = {
++	&dev_attr_driver_version,
++	&dev_attr_fw_version,
++	&dev_attr_serial_num,
++	&dev_attr_isp_name,
++	&dev_attr_isp_id,
++	&dev_attr_model_name,
++	&dev_attr_model_desc,
++	&dev_attr_pci_info,
++	&dev_attr_state,
++	&dev_attr_zio,
++	&dev_attr_zio_timer,
++	&dev_attr_beacon,
++	&dev_attr_optrom_bios_version,
++	&dev_attr_optrom_efi_version,
++	&dev_attr_optrom_fcode_version,
++	&dev_attr_optrom_fw_version,
+ 	NULL,
+ };
+ 
+@@ -849,20 +864,20 @@ static void
+ qla2x00_get_host_speed(struct Scsi_Host *shost)
+ {
+ 	scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
+-	uint32_t speed = 0;
++	u32 speed = FC_PORTSPEED_UNKNOWN;
+ 
+ 	switch (ha->link_data_rate) {
+ 	case PORT_SPEED_1GB:
+-		speed = 1;
++		speed = FC_PORTSPEED_1GBIT;
+ 		break;
+ 	case PORT_SPEED_2GB:
+-		speed = 2;
++		speed = FC_PORTSPEED_2GBIT;
+ 		break;
+ 	case PORT_SPEED_4GB:
+-		speed = 4;
++		speed = FC_PORTSPEED_4GBIT;
+ 		break;
+ 	case PORT_SPEED_8GB:
+-		speed = 8;
++		speed = FC_PORTSPEED_8GBIT;
+ 		break;
+ 	}
+ 	fc_host_speed(shost) = speed;
+@@ -900,7 +915,8 @@ qla2x00_get_starget_node_name(struct scsi_target *starget)
+ 	u64 node_name = 0;
+ 
+ 	list_for_each_entry(fcport, &ha->fcports, list) {
+-		if (starget->id == fcport->os_target_id) {
++		if (fcport->rport &&
++		    starget->id == fcport->rport->scsi_target_id) {
+ 			node_name = wwn_to_u64(fcport->node_name);
+ 			break;
+ 		}
+@@ -918,7 +934,8 @@ qla2x00_get_starget_port_name(struct scsi_target *starget)
+ 	u64 port_name = 0;
+ 
+ 	list_for_each_entry(fcport, &ha->fcports, list) {
+-		if (starget->id == fcport->os_target_id) {
++		if (fcport->rport &&
++		    starget->id == fcport->rport->scsi_target_id) {
+ 			port_name = wwn_to_u64(fcport->port_name);
+ 			break;
+ 		}
+@@ -936,7 +953,8 @@ qla2x00_get_starget_port_id(struct scsi_target *starget)
+ 	uint32_t port_id = ~0U;
+ 
+ 	list_for_each_entry(fcport, &ha->fcports, list) {
+-		if (starget->id == fcport->os_target_id) {
++		if (fcport->rport &&
++		    starget->id == fcport->rport->scsi_target_id) {
+ 			port_id = fcport->d_id.b.domain << 16 |
+ 			    fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
+ 			break;
+@@ -1196,6 +1214,7 @@ struct fc_function_template qla2xxx_transport_functions = {
+ 	.show_host_node_name = 1,
+ 	.show_host_port_name = 1,
+ 	.show_host_supported_classes = 1,
++	.show_host_supported_speeds = 1,
+ 
+ 	.get_host_port_id = qla2x00_get_host_port_id,
+ 	.show_host_port_id = 1,
+@@ -1276,9 +1295,23 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
+ void
+ qla2x00_init_host_attr(scsi_qla_host_t *ha)
+ {
++	u32 speed = FC_PORTSPEED_UNKNOWN;
++
+ 	fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name);
+ 	fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
+ 	fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
+ 	fc_host_max_npiv_vports(ha->host) = ha->max_npiv_vports;;
+ 	fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count;
++
++	if (IS_QLA25XX(ha))
++		speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
++		    FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
++	else if (IS_QLA24XX_TYPE(ha))
++		speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
++		    FC_PORTSPEED_1GBIT;
++	else if (IS_QLA23XX(ha))
++		speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
++	else
++		speed = FC_PORTSPEED_1GBIT;
++	fc_host_supported_speeds(ha->host) = speed;
+ }
+diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
+index d88e98c..9d12d9f 100644
+--- a/drivers/scsi/qla2xxx/qla_dbg.c
++++ b/drivers/scsi/qla2xxx/qla_dbg.c
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -1410,125 +1410,3 @@ qla2x00_dump_buffer(uint8_t * b, uint32_t size)
+ 	if (cnt % 16)
+ 		printk("\n");
+ }
+-
+-/**************************************************************************
+- *   qla2x00_print_scsi_cmd
+- *	 Dumps out info about the scsi cmd and srb.
+- *   Input
+- *	 cmd : struct scsi_cmnd
+- **************************************************************************/
+-void
+-qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd)
+-{
+-	int i;
+-	struct scsi_qla_host *ha;
+-	srb_t *sp;
+-
+-	ha = shost_priv(cmd->device->host);
+-
+-	sp = (srb_t *) cmd->SCp.ptr;
+-	printk("SCSI Command @=0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
+-	printk("  chan=0x%02x, target=0x%02x, lun=0x%02x, cmd_len=0x%02x\n",
+-	    cmd->device->channel, cmd->device->id, cmd->device->lun,
+-	    cmd->cmd_len);
+-	printk(" CDB: ");
+-	for (i = 0; i < cmd->cmd_len; i++) {
+-		printk("0x%02x ", cmd->cmnd[i]);
+-	}
+-	printk("\n  seg_cnt=%d, allowed=%d, retries=%d\n",
+-	       scsi_sg_count(cmd), cmd->allowed, cmd->retries);
+-	printk("  request buffer=0x%p, request buffer len=0x%x\n",
+-	       scsi_sglist(cmd), scsi_bufflen(cmd));
+-	printk("  tag=%d, transfersize=0x%x\n",
+-	    cmd->tag, cmd->transfersize);
+-	printk("  serial_number=%lx, SP=%p\n", cmd->serial_number, sp);
+-	printk("  data direction=%d\n", cmd->sc_data_direction);
+-
+-	if (!sp)
+-		return;
+-
+-	printk("  sp flags=0x%x\n", sp->flags);
+-}
+-
+-#if defined(QL_DEBUG_ROUTINES)
+-/*
+- * qla2x00_formatted_dump_buffer
+- *       Prints string plus buffer.
+- *
+- * Input:
+- *       string  = Null terminated string (no newline at end).
+- *       buffer  = buffer address.
+- *       wd_size = word size 8, 16, 32 or 64 bits
+- *       count   = number of words.
+- */
+-void
+-qla2x00_formatted_dump_buffer(char *string, uint8_t * buffer,
+-				uint8_t wd_size, uint32_t count)
+-{
+-	uint32_t cnt;
+-	uint16_t *buf16;
+-	uint32_t *buf32;
+-
+-	if (strcmp(string, "") != 0)
+-		printk("%s\n",string);
+-
+-	switch (wd_size) {
+-		case 8:
+-			printk(" 0    1    2    3    4    5    6    7    "
+-				"8    9    Ah   Bh   Ch   Dh   Eh   Fh\n");
+-			printk("-----------------------------------------"
+-				"-------------------------------------\n");
+-
+-			for (cnt = 1; cnt <= count; cnt++, buffer++) {
+-				printk("%02x",*buffer);
+-				if (cnt % 16 == 0)
+-					printk("\n");
+-				else
+-					printk("  ");
+-			}
+-			if (cnt % 16 != 0)
+-				printk("\n");
+-			break;
+-		case 16:
+-			printk("   0      2      4      6      8      Ah "
+-				"	Ch     Eh\n");
+-			printk("-----------------------------------------"
+-				"-------------\n");
+-
+-			buf16 = (uint16_t *) buffer;
+-			for (cnt = 1; cnt <= count; cnt++, buf16++) {
+-				printk("%4x",*buf16);
+-
+-				if (cnt % 8 == 0)
+-					printk("\n");
+-				else if (*buf16 < 10)
+-					printk("   ");
+-				else
+-					printk("  ");
+-			}
+-			if (cnt % 8 != 0)
+-				printk("\n");
+-			break;
+-		case 32:
+-			printk("       0          4          8          Ch\n");
+-			printk("------------------------------------------\n");
+-
+-			buf32 = (uint32_t *) buffer;
+-			for (cnt = 1; cnt <= count; cnt++, buf32++) {
+-				printk("%8x", *buf32);
+-
+-				if (cnt % 4 == 0)
+-					printk("\n");
+-				else if (*buf32 < 10)
+-					printk("   ");
+-				else
+-					printk("  ");
+-			}
+-			if (cnt % 4 != 0)
+-				printk("\n");
+-			break;
+-		default:
+-			break;
+-	}
+-}
+-#endif
+diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
+index 524598a..2e9c0c0 100644
+--- a/drivers/scsi/qla2xxx/qla_dbg.h
++++ b/drivers/scsi/qla2xxx/qla_dbg.h
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -22,19 +22,7 @@
+ /* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */
+ /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */
+ /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
+-/*
+- *  Local Macro Definitions.
+- */
+-#if defined(QL_DEBUG_LEVEL_1)  || defined(QL_DEBUG_LEVEL_2) || \
+-    defined(QL_DEBUG_LEVEL_3)  || defined(QL_DEBUG_LEVEL_4) || \
+-    defined(QL_DEBUG_LEVEL_5)  || defined(QL_DEBUG_LEVEL_6) || \
+-    defined(QL_DEBUG_LEVEL_7)  || defined(QL_DEBUG_LEVEL_8) || \
+-    defined(QL_DEBUG_LEVEL_9)  || defined(QL_DEBUG_LEVEL_10) || \
+-    defined(QL_DEBUG_LEVEL_11) || defined(QL_DEBUG_LEVEL_12) || \
+-    defined(QL_DEBUG_LEVEL_13) || defined(QL_DEBUG_LEVEL_14) || \
+-    defined(QL_DEBUG_LEVEL_15)
+-    #define QL_DEBUG_ROUTINES
+-#endif
++/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
+ 
+ /*
+ * Macros use for debugging the driver.
+@@ -54,6 +42,7 @@
+ #define DEBUG2_9_10(x)	do { if (ql2xextended_error_logging) { x; } } while (0)
+ #define DEBUG2_11(x)	do { if (ql2xextended_error_logging) { x; } } while (0)
+ #define DEBUG2_13(x)	do { if (ql2xextended_error_logging) { x; } } while (0)
++#define DEBUG2_16(x)	do { if (ql2xextended_error_logging) { x; } } while (0)
+ 
+ #if defined(QL_DEBUG_LEVEL_3)
+ #define DEBUG3(x)	do {x;} while (0)
+@@ -133,6 +122,12 @@
+ #define DEBUG15(x)	do {} while (0)
+ #endif
+ 
++#if defined(QL_DEBUG_LEVEL_16)
++#define DEBUG16(x)	do {x;} while (0)
++#else
++#define DEBUG16(x)	do {} while (0)
++#endif
++
+ /*
+  * Firmware Dump structure definition
+  */
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 3750319..299eccf 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -24,7 +24,8 @@
+ #include <linux/workqueue.h>
+ #include <linux/firmware.h>
+ #include <linux/aer.h>
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
++#include <linux/semaphore.h>
+ 
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_host.h>
+@@ -192,9 +193,6 @@ typedef struct srb {
+ 
+ 	uint16_t flags;
+ 
+-	/* Single transfer DMA context */
+-	dma_addr_t dma_handle;
+-
+ 	uint32_t request_sense_length;
+ 	uint8_t *request_sense_ptr;
+ } srb_t;
+@@ -1542,8 +1540,6 @@ typedef struct fc_port {
+ 	atomic_t state;
+ 	uint32_t flags;
+ 
+-	unsigned int os_target_id;
+-
+ 	int port_login_retry_count;
+ 	int login_retry;
+ 	atomic_t port_down_timer;
+@@ -1613,6 +1609,7 @@ typedef struct fc_port {
+ #define CT_ACCEPT_RESPONSE	0x8002
+ #define CT_REASON_INVALID_COMMAND_CODE	0x01
+ #define CT_REASON_CANNOT_PERFORM	0x09
++#define CT_REASON_COMMAND_UNSUPPORTED	0x0b
+ #define CT_EXPL_ALREADY_REGISTERED	0x10
+ 
+ #define NS_N_PORT_TYPE	0x01
+@@ -2063,7 +2060,8 @@ struct isp_operations {
+ 	void (*disable_intrs) (struct scsi_qla_host *);
+ 
+ 	int (*abort_command) (struct scsi_qla_host *, srb_t *);
+-	int (*abort_target) (struct fc_port *);
++	int (*target_reset) (struct fc_port *, unsigned int);
++	int (*lun_reset) (struct fc_port *, unsigned int);
+ 	int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t,
+ 		uint8_t, uint8_t, uint16_t *, uint8_t);
+ 	int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t,
+@@ -2117,6 +2115,46 @@ struct qla_msix_entry {
+ 
+ #define	WATCH_INTERVAL		1       /* number of seconds */
+ 
++/* Work events.  */
++enum qla_work_type {
++	QLA_EVT_AEN,
++	QLA_EVT_HWE_LOG,
++};
++
++
++struct qla_work_evt {
++	struct list_head	list;
++	enum qla_work_type	type;
++	u32			flags;
++#define QLA_EVT_FLAG_FREE	0x1
++
++	union {
++		struct {
++			enum fc_host_event_code code;
++			u32 data;
++		} aen;
++		struct {
++			uint16_t code;
++			uint16_t d1, d2, d3;
++		} hwe;
++	} u;
++};
++
++struct qla_chip_state_84xx {
++	struct list_head list;
++	struct kref kref;
++
++	void *bus;
++	spinlock_t access_lock;
++	struct mutex fw_update_mutex;
++	uint32_t fw_update;
++	uint32_t op_fw_version;
++	uint32_t op_fw_size;
++	uint32_t op_fw_seq_size;
++	uint32_t diag_fw_version;
++	uint32_t gold_fw_version;
++};
++
+ /*
+  * Linux Host Adapter structure
+  */
+@@ -2155,6 +2193,7 @@ typedef struct scsi_qla_host {
+ 		uint32_t        vsan_enabled            :1;
+ 		uint32_t	npiv_supported		:1;
+ 		uint32_t	fce_enabled		:1;
++		uint32_t	hw_event_marker_found	:1;
+ 	} flags;
+ 
+ 	atomic_t	loop_state;
+@@ -2204,6 +2243,7 @@ typedef struct scsi_qla_host {
+ #define	DFLG_NO_CABLE			BIT_4
+ 
+ #define PCI_DEVICE_ID_QLOGIC_ISP2532	0x2532
++#define PCI_DEVICE_ID_QLOGIC_ISP8432	0x8432
+ 	uint32_t	device_type;
+ #define DT_ISP2100			BIT_0
+ #define DT_ISP2200			BIT_1
+@@ -2217,7 +2257,8 @@ typedef struct scsi_qla_host {
+ #define DT_ISP5422			BIT_9
+ #define DT_ISP5432			BIT_10
+ #define DT_ISP2532			BIT_11
+-#define DT_ISP_LAST			(DT_ISP2532 << 1)
++#define DT_ISP8432			BIT_12
++#define DT_ISP_LAST			(DT_ISP8432 << 1)
+ 
+ #define DT_IIDMA			BIT_26
+ #define DT_FWI2				BIT_27
+@@ -2239,12 +2280,16 @@ typedef struct scsi_qla_host {
+ #define IS_QLA5422(ha)	(DT_MASK(ha) & DT_ISP5422)
+ #define IS_QLA5432(ha)	(DT_MASK(ha) & DT_ISP5432)
+ #define IS_QLA2532(ha)	(DT_MASK(ha) & DT_ISP2532)
++#define IS_QLA8432(ha)	(DT_MASK(ha) & DT_ISP8432)
+ 
+ #define IS_QLA23XX(ha)	(IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
+     			 IS_QLA6312(ha) || IS_QLA6322(ha))
+ #define IS_QLA24XX(ha)	(IS_QLA2422(ha) || IS_QLA2432(ha))
+ #define IS_QLA54XX(ha)	(IS_QLA5422(ha) || IS_QLA5432(ha))
+ #define IS_QLA25XX(ha)	(IS_QLA2532(ha))
++#define IS_QLA84XX(ha)	(IS_QLA8432(ha))
++#define IS_QLA24XX_TYPE(ha)	(IS_QLA24XX(ha) || IS_QLA54XX(ha) || \
++			IS_QLA84XX(ha))
+ 
+ #define IS_IIDMA_CAPABLE(ha)	((ha)->device_type & DT_IIDMA)
+ #define IS_FWI2_CAPABLE(ha)	((ha)->device_type & DT_FWI2)
+@@ -2356,6 +2401,8 @@ typedef struct scsi_qla_host {
+         uint32_t	login_retry_count;
+ 	int		max_q_depth;
+ 
++	struct list_head	work_list;
++
+ 	/* Fibre Channel Device List. */
+ 	struct list_head	fcports;
+ 
+@@ -2423,8 +2470,6 @@ typedef struct scsi_qla_host {
+ #define  MBX_TIMEDOUT		BIT_5
+ #define  MBX_ACCESS_TIMEDOUT	BIT_6
+ 
+-	mbx_cmd_t 	mc;
+-
+ 	/* Basic firmware related information. */
+ 	uint16_t	fw_major_version;
+ 	uint16_t	fw_minor_version;
+@@ -2458,6 +2503,10 @@ typedef struct scsi_qla_host {
+ 	uint64_t	fce_wr, fce_rd;
+ 	struct mutex	fce_mutex;
+ 
++	uint32_t	hw_event_start;
++	uint32_t	hw_event_ptr;
++	uint32_t	hw_event_pause_errors;
++
+ 	uint8_t		host_str[16];
+ 	uint32_t	pci_attr;
+ 	uint16_t	chip_revision;
+@@ -2493,6 +2542,13 @@ typedef struct scsi_qla_host {
+ 	uint8_t		fcode_revision[16];
+ 	uint32_t	fw_revision[4];
+ 
++	uint16_t	fdt_odd_index;
++	uint32_t	fdt_wrt_disable;
++	uint32_t	fdt_erase_cmd;
++	uint32_t	fdt_block_size;
++	uint32_t	fdt_unprotect_sec_cmd;
++	uint32_t	fdt_protect_sec_cmd;
++
+ 	/* Needed for BEACON */
+ 	uint16_t	beacon_blink_led;
+ 	uint8_t		beacon_color_state;
+@@ -2538,6 +2594,8 @@ typedef struct scsi_qla_host {
+ #define VP_ERR_ADAP_NORESOURCES	5
+ 	uint16_t	max_npiv_vports;	/* 63 or 125 per topoloty */
+ 	int		cur_vport_count;
++
++	struct qla_chip_state_84xx *cs84xx;
+ } scsi_qla_host_t;
+ 
+ 
+diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
+index 2cd899b..561a441 100644
+--- a/drivers/scsi/qla2xxx/qla_dfs.c
++++ b/drivers/scsi/qla2xxx/qla_dfs.c
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
+index 9337e13..078f2a1 100644
+--- a/drivers/scsi/qla2xxx/qla_fw.h
++++ b/drivers/scsi/qla2xxx/qla_fw.h
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -719,7 +719,7 @@ struct tsk_mgmt_entry {
+ 
+ 	uint16_t timeout;		/* Command timeout. */
+ 
+-	uint8_t lun[8];			/* FCP LUN (BE). */
++	struct scsi_lun lun;		/* FCP LUN (BE). */
+ 
+ 	uint32_t control_flags;		/* Control Flags. */
+ #define TCF_NOTMCMD_TO_TARGET	BIT_31
+@@ -793,7 +793,19 @@ struct device_reg_24xx {
+ #define FA_VPD_NVRAM_ADDR	0x48000
+ #define FA_FEATURE_ADDR		0x4C000
+ #define FA_FLASH_DESCR_ADDR	0x50000
+-#define FA_HW_EVENT_ADDR	0x54000
++#define FA_HW_EVENT0_ADDR	0x54000
++#define FA_HW_EVENT1_ADDR	0x54200
++#define FA_HW_EVENT_SIZE	0x200
++#define FA_HW_EVENT_ENTRY_SIZE	4
++/*
++ * Flash Error Log Event Codes.
++ */
++#define HW_EVENT_RESET_ERR	0xF00B
++#define HW_EVENT_ISP_ERR	0xF020
++#define HW_EVENT_PARITY_ERR	0xF022
++#define HW_EVENT_NVRAM_CHKSUM_ERR	0xF023
++#define HW_EVENT_FLASH_FW_ERR	0xF024
++
+ #define FA_BOOT_LOG_ADDR	0x58000
+ #define FA_FW_DUMP0_ADDR	0x60000
+ #define FA_FW_DUMP1_ADDR	0x70000
+@@ -1174,4 +1186,159 @@ struct vf_evfp_entry_24xx {
+ };
+ 
+ /* END MID Support ***********************************************************/
++
++/* Flash Description Table ***************************************************/
++
++struct qla_fdt_layout {
++	uint8_t sig[4];
++	uint16_t version;
++	uint16_t len;
++	uint16_t checksum;
++	uint8_t unused1[2];
++	uint8_t model[16];
++	uint16_t man_id;
++	uint16_t id;
++	uint8_t flags;
++	uint8_t erase_cmd;
++	uint8_t alt_erase_cmd;
++	uint8_t wrt_enable_cmd;
++	uint8_t wrt_enable_bits;
++	uint8_t wrt_sts_reg_cmd;
++	uint8_t unprotect_sec_cmd;
++	uint8_t read_man_id_cmd;
++	uint32_t block_size;
++	uint32_t alt_block_size;
++	uint32_t flash_size;
++	uint32_t wrt_enable_data;
++	uint8_t read_id_addr_len;
++	uint8_t wrt_disable_bits;
++	uint8_t read_dev_id_len;
++	uint8_t chip_erase_cmd;
++	uint16_t read_timeout;
++	uint8_t protect_sec_cmd;
++	uint8_t unused2[65];
++};
++
++/* 84XX Support **************************************************************/
++
++#define MBA_ISP84XX_ALERT	0x800f  /* Alert Notification. */
++#define A84_PANIC_RECOVERY	0x1
++#define A84_OP_LOGIN_COMPLETE	0x2
++#define A84_DIAG_LOGIN_COMPLETE	0x3
++#define A84_GOLD_LOGIN_COMPLETE	0x4
++
++#define MBC_ISP84XX_RESET	0x3a    /* Reset. */
++
++#define FSTATE_REMOTE_FC_DOWN	BIT_0
++#define FSTATE_NSL_LINK_DOWN	BIT_1
++#define FSTATE_IS_DIAG_FW	BIT_2
++#define FSTATE_LOGGED_IN	BIT_3
++#define FSTATE_WAITING_FOR_VERIFY	BIT_4
++
++#define VERIFY_CHIP_IOCB_TYPE	0x1B
++struct verify_chip_entry_84xx {
++	uint8_t entry_type;
++	uint8_t entry_count;
++	uint8_t sys_defined;
++	uint8_t entry_status;
++
++	uint32_t handle;
++
++	uint16_t options;
++#define VCO_DONT_UPDATE_FW	BIT_0
++#define VCO_FORCE_UPDATE	BIT_1
++#define VCO_DONT_RESET_UPDATE	BIT_2
++#define VCO_DIAG_FW		BIT_3
++#define VCO_END_OF_DATA		BIT_14
++#define VCO_ENABLE_DSD		BIT_15
++
++	uint16_t reserved_1;
++
++	uint16_t data_seg_cnt;
++	uint16_t reserved_2[3];
++
++	uint32_t fw_ver;
++	uint32_t exchange_address;
++
++	uint32_t reserved_3[3];
++	uint32_t fw_size;
++	uint32_t fw_seq_size;
++	uint32_t relative_offset;
++
++	uint32_t dseg_address[2];
++	uint32_t dseg_length;
++};
++
++struct verify_chip_rsp_84xx {
++	uint8_t entry_type;
++	uint8_t entry_count;
++	uint8_t sys_defined;
++	uint8_t entry_status;
++
++	uint32_t handle;
++
++	uint16_t comp_status;
++#define CS_VCS_CHIP_FAILURE	0x3
++#define CS_VCS_BAD_EXCHANGE	0x8
++#define CS_VCS_SEQ_COMPLETEi	0x40
++
++	uint16_t failure_code;
++#define VFC_CHECKSUM_ERROR	0x1
++#define VFC_INVALID_LEN		0x2
++#define VFC_ALREADY_IN_PROGRESS	0x8
++
++	uint16_t reserved_1[4];
++
++	uint32_t fw_ver;
++	uint32_t exchange_address;
++
++	uint32_t reserved_2[6];
++};
++
++#define ACCESS_CHIP_IOCB_TYPE	0x2B
++struct access_chip_84xx {
++	uint8_t entry_type;
++	uint8_t entry_count;
++	uint8_t sys_defined;
++	uint8_t entry_status;
++
++	uint32_t handle;
++
++	uint16_t options;
++#define ACO_DUMP_MEMORY		0x0
++#define ACO_LOAD_MEMORY		0x1
++#define ACO_CHANGE_CONFIG_PARAM	0x2
++#define ACO_REQUEST_INFO	0x3
++
++	uint16_t reserved1;
++
++	uint16_t dseg_count;
++	uint16_t reserved2[3];
++
++	uint32_t parameter1;
++	uint32_t parameter2;
++	uint32_t parameter3;
++
++	uint32_t reserved3[3];
++	uint32_t total_byte_cnt;
++	uint32_t reserved4;
++
++	uint32_t dseg_address[2];
++	uint32_t dseg_length;
++};
++
++struct access_chip_rsp_84xx {
++	uint8_t entry_type;
++	uint8_t entry_count;
++	uint8_t sys_defined;
++	uint8_t entry_status;
++
++	uint32_t handle;
++
++	uint16_t comp_status;
++	uint16_t failure_code;
++	uint32_t residual_count;
++
++	uint32_t reserved[12];
++};
+ #endif
+diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
+index 193f688..76eb4fe 100644
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -38,9 +38,6 @@ extern int qla2x00_loop_resync(scsi_qla_host_t *);
+ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
+ extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
+ 
+-extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t);
+-
+-extern void qla2x00_rescan_fcports(scsi_qla_host_t *);
+ extern void qla2x00_update_fcports(scsi_qla_host_t *);
+ 
+ extern int qla2x00_abort_isp(scsi_qla_host_t *);
+@@ -50,6 +47,8 @@ extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
+ extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *);
+ extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
+ 
++extern void qla84xx_put_chip(struct scsi_qla_host *);
++
+ /*
+  * Global Data in qla_os.c source file.
+  */
+@@ -67,6 +66,10 @@ extern int num_hosts;
+ 
+ extern int qla2x00_loop_reset(scsi_qla_host_t *);
+ extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
++extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
++    fc_host_event_code, u32);
++extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
++    uint16_t, uint16_t);
+ 
+ /*
+  * Global Functions in qla_mid.c source file.
+@@ -149,12 +152,17 @@ extern int
+ qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
+ 
+ extern int
++qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *, dma_addr_t, size_t,
++    uint32_t);
++
++extern int
+ qla2x00_abort_command(scsi_qla_host_t *, srb_t *);
+ 
+-#if USE_ABORT_TGT
+ extern int
+-qla2x00_abort_target(fc_port_t *);
+-#endif
++qla2x00_abort_target(struct fc_port *, unsigned int);
++
++extern int
++qla2x00_lun_reset(struct fc_port *, unsigned int);
+ 
+ extern int
+ qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
+@@ -220,7 +228,8 @@ qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
+     dma_addr_t);
+ 
+ extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *);
+-extern int qla24xx_abort_target(fc_port_t *);
++extern int qla24xx_abort_target(struct fc_port *, unsigned int);
++extern int qla24xx_lun_reset(struct fc_port *, unsigned int);
+ 
+ extern int
+ qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
+@@ -246,6 +255,8 @@ qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
+ extern int
+ qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
+ 
++extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
++
+ /*
+  * Global Function Prototypes in qla_isr.c source file.
+  */
+@@ -298,6 +309,11 @@ extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+ extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
+ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
+ 
++extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
++    uint16_t, uint16_t);
++
++extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
++
+ /*
+  * Global Function Prototypes in qla_dbg.c source file.
+  */
+@@ -307,7 +323,6 @@ extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
+ extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
+ extern void qla2x00_dump_regs(scsi_qla_host_t *);
+ extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
+-extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *);
+ 
+ /*
+  * Global Function Prototypes in qla_gs.c source file.
+@@ -332,8 +347,8 @@ extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *);
+ /*
+  * Global Function Prototypes in qla_attr.c source file.
+  */
+-struct class_device_attribute;
+-extern struct class_device_attribute *qla2x00_host_attrs[];
++struct device_attribute;
++extern struct device_attribute *qla2x00_host_attrs[];
+ struct fc_function_template;
+ extern struct fc_function_template qla2xxx_transport_functions;
+ extern struct fc_function_template qla2xxx_transport_vport_functions;
+diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
+index c180876..750d7ef 100644
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -1,17 +1,11 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+ #include "qla_def.h"
+ 
+-static inline struct ct_sns_req *
+-qla2x00_prep_ct_req(struct ct_sns_req *, uint16_t, uint16_t);
+-
+-static inline struct sns_cmd_pkt *
+-qla2x00_prep_sns_cmd(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
+-
+ static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
+ static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
+ static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
+@@ -1538,7 +1532,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
+ 		eiter->a.sup_speed = __constant_cpu_to_be32(
+ 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
+ 		    FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
+-	else if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
++	else if (IS_QLA24XX_TYPE(ha))
+ 		eiter->a.sup_speed = __constant_cpu_to_be32(
+ 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
+ 		    FDMI_PORT_SPEED_4GB);
+@@ -1847,8 +1841,10 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
+ 		    "GPSC")) != QLA_SUCCESS) {
+ 			/* FM command unsupported? */
+ 			if (rval == QLA_INVALID_COMMAND &&
+-			    ct_rsp->header.reason_code ==
+-			    CT_REASON_INVALID_COMMAND_CODE) {
++			    (ct_rsp->header.reason_code ==
++				CT_REASON_INVALID_COMMAND_CODE ||
++			     ct_rsp->header.reason_code ==
++				CT_REASON_COMMAND_UNSUPPORTED)) {
+ 				DEBUG2(printk("scsi(%ld): GPSC command "
+ 				    "unsupported, disabling query...\n",
+ 				    ha->host_no));
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index 364be7d..01e2608 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -15,14 +15,6 @@
+ #include <asm/prom.h>
+ #endif
+ 
+-/* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
+-#ifndef EXT_IS_LUN_BIT_SET
+-#define EXT_IS_LUN_BIT_SET(P,L) \
+-    (((P)->mask[L/8] & (0x80 >> (L%8)))?1:0)
+-#define EXT_SET_LUN_BIT(P,L) \
+-    ((P)->mask[L/8] |= (0x80 >> (L%8)))
+-#endif
+-
+ /*
+ *  QLogic ISP2x00 Hardware Support Function Prototypes.
+ */
+@@ -45,6 +37,9 @@ static int qla2x00_restart_isp(scsi_qla_host_t *);
+ 
+ static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev);
+ 
++static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
++static int qla84xx_init_chip(scsi_qla_host_t *);
++
+ /****************************************************************************/
+ /*                QLogic ISP2x00 Hardware Support Functions.                */
+ /****************************************************************************/
+@@ -114,6 +109,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
+ 		rval = qla2x00_setup_chip(ha);
+ 		if (rval)
+ 			return (rval);
++		qla2xxx_get_flash_info(ha);
++	}
++	if (IS_QLA84XX(ha)) {
++		ha->cs84xx = qla84xx_get_chip(ha);
++		if (!ha->cs84xx) {
++			qla_printk(KERN_ERR, ha,
++			    "Unable to configure ISP84XX.\n");
++			return QLA_FUNCTION_FAILED;
++		}
+ 	}
+ 	rval = qla2x00_init_rings(ha);
+ 
+@@ -500,6 +504,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha)
+ static inline void
+ qla24xx_reset_risc(scsi_qla_host_t *ha)
+ {
++	int hw_evt = 0;
+ 	unsigned long flags = 0;
+ 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ 	uint32_t cnt, d2;
+@@ -528,6 +533,8 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
+ 		d2 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
+ 		barrier();
+ 	}
++	if (cnt == 0)
++		hw_evt = 1;
+ 
+ 	/* Wait for soft-reset to complete. */
+ 	d2 = RD_REG_DWORD(&reg->ctrl_status);
+@@ -536,6 +543,10 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
+ 		d2 = RD_REG_DWORD(&reg->ctrl_status);
+ 		barrier();
+ 	}
++	if (cnt == 0 || hw_evt)
++		qla2xxx_hw_event_log(ha, HW_EVENT_RESET_ERR,
++		    RD_REG_WORD(&reg->mailbox1), RD_REG_WORD(&reg->mailbox2),
++		    RD_REG_WORD(&reg->mailbox3));
+ 
+ 	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
+ 	RD_REG_DWORD(&reg->hccr);
+@@ -1243,10 +1254,10 @@ static int
+ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ {
+ 	int		rval;
+-	unsigned long	wtime, mtime;
++	unsigned long	wtime, mtime, cs84xx_time;
+ 	uint16_t	min_wait;	/* Minimum wait time if loop is down */
+ 	uint16_t	wait_time;	/* Wait time if loop is coming ready */
+-	uint16_t	fw_state;
++	uint16_t	state[3];
+ 
+ 	rval = QLA_SUCCESS;
+ 
+@@ -1275,12 +1286,34 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ 	    ha->host_no));
+ 
+ 	do {
+-		rval = qla2x00_get_firmware_state(ha, &fw_state);
++		rval = qla2x00_get_firmware_state(ha, state);
+ 		if (rval == QLA_SUCCESS) {
+-			if (fw_state < FSTATE_LOSS_OF_SYNC) {
++			if (state[0] < FSTATE_LOSS_OF_SYNC) {
+ 				ha->device_flags &= ~DFLG_NO_CABLE;
+ 			}
+-			if (fw_state == FSTATE_READY) {
++			if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
++				DEBUG16(printk("scsi(%ld): fw_state=%x "
++				    "84xx=%x.\n", ha->host_no, state[0],
++				    state[2]));
++				if ((state[2] & FSTATE_LOGGED_IN) &&
++				     (state[2] & FSTATE_WAITING_FOR_VERIFY)) {
++					DEBUG16(printk("scsi(%ld): Sending "
++					    "verify iocb.\n", ha->host_no));
++
++					cs84xx_time = jiffies;
++					rval = qla84xx_init_chip(ha);
++					if (rval != QLA_SUCCESS)
++						break;
++
++					/* Add time taken to initialize. */
++					cs84xx_time = jiffies - cs84xx_time;
++					wtime += cs84xx_time;
++					mtime += cs84xx_time;
++					DEBUG16(printk("scsi(%ld): Increasing "
++					    "wait time by %ld. New time %ld\n",
++					    ha->host_no, cs84xx_time, wtime));
++				}
++			} else if (state[0] == FSTATE_READY) {
+ 				DEBUG(printk("scsi(%ld): F/W Ready - OK \n",
+ 				    ha->host_no));
+ 
+@@ -1294,7 +1327,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ 			rval = QLA_FUNCTION_FAILED;
+ 
+ 			if (atomic_read(&ha->loop_down_timer) &&
+-			    fw_state != FSTATE_READY) {
++			    state[0] != FSTATE_READY) {
+ 				/* Loop down. Timeout on min_wait for states
+ 				 * other than Wait for Login.
+ 				 */
+@@ -1319,11 +1352,11 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ 		msleep(500);
+ 
+ 		DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
+-		    ha->host_no, fw_state, jiffies));
++		    ha->host_no, state[0], jiffies));
+ 	} while (1);
+ 
+ 	DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
+-	    ha->host_no, fw_state, jiffies));
++	    ha->host_no, state[0], jiffies));
+ 
+ 	if (rval) {
+ 		DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n",
+@@ -1555,6 +1588,10 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
+ 		qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+ 		    "invalid -- WWPN) defaults.\n");
+ 
++		if (chksum)
++			qla2xxx_hw_event_log(ha, HW_EVENT_NVRAM_CHKSUM_ERR, 0,
++			    MSW(chksum), LSW(chksum));
++
+ 		/*
+ 		 * Set default initialization control block.
+ 		 */
+@@ -2165,20 +2202,6 @@ cleanup_allocation:
+ }
+ 
+ static void
+-qla2x00_probe_for_all_luns(scsi_qla_host_t *ha)
+-{
+-	fc_port_t	*fcport;
+-
+-	qla2x00_mark_all_devices_lost(ha, 0);
+- 	list_for_each_entry(fcport, &ha->fcports, list) {
+-		if (fcport->port_type != FCT_TARGET)
+-			continue;
+-
+-		qla2x00_update_fcport(ha, fcport);
+-	}
+-}
+-
+-static void
+ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
+ {
+ #define LS_UNKNOWN      2
+@@ -2251,10 +2274,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
+ 	if (fcport->port_type == FCT_TARGET)
+ 		rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+ 	fc_remote_port_rolechg(rport, rport_ids.roles);
+-
+-	if (rport->scsi_target_id != -1 &&
+-	    rport->scsi_target_id < ha->host->max_id)
+-		fcport->os_target_id = rport->scsi_target_id;
+ }
+ 
+ /*
+@@ -2434,7 +2453,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
+ 
+ 			if (fcport->loop_id == FC_NO_LOOP_ID) {
+ 				fcport->loop_id = next_loopid;
+-				rval = qla2x00_find_new_loop_id(ha, fcport);
++				rval = qla2x00_find_new_loop_id(
++				    to_qla_parent(ha), fcport);
+ 				if (rval != QLA_SUCCESS) {
+ 					/* Ran out of IDs to use */
+ 					break;
+@@ -2459,7 +2479,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
+ 
+ 			/* Find a new loop ID to use. */
+ 			fcport->loop_id = next_loopid;
+-			rval = qla2x00_find_new_loop_id(ha, fcport);
++			rval = qla2x00_find_new_loop_id(to_qla_parent(ha),
++			    fcport);
+ 			if (rval != QLA_SUCCESS) {
+ 				/* Ran out of IDs to use */
+ 				break;
+@@ -3193,25 +3214,6 @@ qla2x00_loop_resync(scsi_qla_host_t *ha)
+ }
+ 
+ void
+-qla2x00_rescan_fcports(scsi_qla_host_t *ha)
+-{
+-	int rescan_done;
+-	fc_port_t *fcport;
+-
+-	rescan_done = 0;
+-	list_for_each_entry(fcport, &ha->fcports, list) {
+-		if ((fcport->flags & FCF_RESCAN_NEEDED) == 0)
+-			continue;
+-
+-		qla2x00_update_fcport(ha, fcport);
+-		fcport->flags &= ~FCF_RESCAN_NEEDED;
+-
+-		rescan_done = 1;
+-	}
+-	qla2x00_probe_for_all_luns(ha);
+-}
+-
+-void
+ qla2x00_update_fcports(scsi_qla_host_t *ha)
+ {
+ 	fc_port_t *fcport;
+@@ -4044,16 +4046,16 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
+ 	if (!ha->parent)
+ 		return -EINVAL;
+ 
+-	rval = qla2x00_fw_ready(ha);
++	rval = qla2x00_fw_ready(ha->parent);
+ 	if (rval == QLA_SUCCESS) {
+ 		clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
+-		qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
++		qla2x00_marker(ha->parent, 0, 0, MK_SYNC_ALL);
+ 	}
+ 
+ 	ha->flags.management_server_logged_in = 0;
+ 
+ 	/* Login to SNS first */
+-	qla24xx_login_fabric(ha, NPH_SNS, 0xff, 0xff, 0xfc,
++	qla24xx_login_fabric(ha->parent, NPH_SNS, 0xff, 0xff, 0xfc,
+ 	    mb, BIT_1);
+ 	if (mb[0] != MBS_COMMAND_COMPLETE) {
+ 		DEBUG15(qla_printk(KERN_INFO, ha,
+@@ -4067,7 +4069,77 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
+ 	atomic_set(&ha->loop_state, LOOP_UP);
+ 	set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+ 	set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
+-	rval = qla2x00_loop_resync(ha);
++	rval = qla2x00_loop_resync(ha->parent);
+ 
+ 	return rval;
+ }
++
++/* 84XX Support **************************************************************/
++
++static LIST_HEAD(qla_cs84xx_list);
++static DEFINE_MUTEX(qla_cs84xx_mutex);
++
++static struct qla_chip_state_84xx *
++qla84xx_get_chip(struct scsi_qla_host *ha)
++{
++	struct qla_chip_state_84xx *cs84xx;
++
++	mutex_lock(&qla_cs84xx_mutex);
++
++	/* Find any shared 84xx chip. */
++	list_for_each_entry(cs84xx, &qla_cs84xx_list, list) {
++		if (cs84xx->bus == ha->pdev->bus) {
++			kref_get(&cs84xx->kref);
++			goto done;
++		}
++	}
++
++	cs84xx = kzalloc(sizeof(*cs84xx), GFP_KERNEL);
++	if (!cs84xx)
++		goto done;
++
++	kref_init(&cs84xx->kref);
++	spin_lock_init(&cs84xx->access_lock);
++	mutex_init(&cs84xx->fw_update_mutex);
++	cs84xx->bus = ha->pdev->bus;
++
++	list_add_tail(&cs84xx->list, &qla_cs84xx_list);
++done:
++	mutex_unlock(&qla_cs84xx_mutex);
++	return cs84xx;
++}
++
++static void
++__qla84xx_chip_release(struct kref *kref)
++{
++	struct qla_chip_state_84xx *cs84xx =
++	    container_of(kref, struct qla_chip_state_84xx, kref);
++
++	mutex_lock(&qla_cs84xx_mutex);
++	list_del(&cs84xx->list);
++	mutex_unlock(&qla_cs84xx_mutex);
++	kfree(cs84xx);
++}
++
++void
++qla84xx_put_chip(struct scsi_qla_host *ha)
++{
++	if (ha->cs84xx)
++		kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
++}
++
++static int
++qla84xx_init_chip(scsi_qla_host_t *ha)
++{
++	int rval;
++	uint16_t status[2];
++
++	mutex_lock(&ha->cs84xx->fw_update_mutex);
++
++	rval = qla84xx_verify_chip(ha, status);
++
++	mutex_unlock(&ha->cs84xx->fw_update_mutex);
++
++	return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
++	    QLA_SUCCESS;
++}
+diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
+index 5d1a3f7..e9bae27 100644
+--- a/drivers/scsi/qla2xxx/qla_inline.h
++++ b/drivers/scsi/qla2xxx/qla_inline.h
+@@ -1,11 +1,10 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+ 
+-static __inline__ uint16_t qla2x00_debounce_register(volatile uint16_t __iomem *);
+ /*
+  * qla2x00_debounce_register
+  *      Debounce register.
+@@ -32,94 +31,12 @@ qla2x00_debounce_register(volatile uint16_t __iomem *addr)
+ 	return (first);
+ }
+ 
+-static __inline__ int qla2x00_normalize_dma_addr(
+-    dma_addr_t *e_addr,  uint32_t *e_len,
+-    dma_addr_t *ne_addr, uint32_t *ne_len);
+-
+-/**
+- * qla2x00_normalize_dma_addr() - Normalize an DMA address.
+- * @e_addr: Raw DMA address
+- * @e_len: Raw DMA length
+- * @ne_addr: Normalized second DMA address
+- * @ne_len: Normalized second DMA length
+- *
+- * If the address does not span a 4GB page boundary, the contents of @ne_addr
+- * and @ne_len are undefined.  @e_len is updated to reflect a normalization.
+- *
+- * Example:
+- *
+- * 	ffffabc0ffffeeee	(e_addr) start of DMA address
+- * 	0000000020000000	(e_len)  length of DMA transfer
+- *	ffffabc11fffeeed	end of DMA transfer
+- *
+- * Is the 4GB boundary crossed?
+- *
+- * 	ffffabc0ffffeeee	(e_addr)
+- *	ffffabc11fffeeed	(e_addr + e_len - 1)
+- *	00000001e0000003	((e_addr ^ (e_addr + e_len - 1))
+- *	0000000100000000	((e_addr ^ (e_addr + e_len - 1)) & ~(0xffffffff)
+- *
+- * Compute start of second DMA segment:
+- *
+- * 	ffffabc0ffffeeee	(e_addr)
+- *	ffffabc1ffffeeee	(0x100000000 + e_addr)
+- *	ffffabc100000000	(0x100000000 + e_addr) & ~(0xffffffff)
+- *	ffffabc100000000	(ne_addr)
+- *
+- * Compute length of second DMA segment:
+- *
+- *	00000000ffffeeee	(e_addr & 0xffffffff)
+- *	0000000000001112	(0x100000000 - (e_addr & 0xffffffff))
+- *	000000001fffeeee	(e_len - (0x100000000 - (e_addr & 0xffffffff))
+- *	000000001fffeeee	(ne_len)
+- *
+- * Adjust length of first DMA segment
+- *
+- * 	0000000020000000	(e_len)
+- *	0000000000001112	(e_len - ne_len)
+- *	0000000000001112	(e_len)
+- *
+- * Returns non-zero if the specified address was normalized, else zero.
+- */
+-static __inline__ int
+-qla2x00_normalize_dma_addr(
+-    dma_addr_t *e_addr,  uint32_t *e_len,
+-    dma_addr_t *ne_addr, uint32_t *ne_len)
+-{
+-	int normalized;
+-
+-	normalized = 0;
+-	if ((*e_addr ^ (*e_addr + *e_len - 1)) & ~(0xFFFFFFFFULL)) {
+-		/* Compute normalized crossed address and len */
+-		*ne_addr = (0x100000000ULL + *e_addr) & ~(0xFFFFFFFFULL);
+-		*ne_len = *e_len - (0x100000000ULL - (*e_addr & 0xFFFFFFFFULL));
+-		*e_len -= *ne_len;
+-
+-		normalized++;
+-	}
+-	return (normalized);
+-}
+-
+-static __inline__ void qla2x00_poll(scsi_qla_host_t *);
+ static inline void
+ qla2x00_poll(scsi_qla_host_t *ha)
+ {
+ 	ha->isp_ops->intr_handler(0, ha);
+ }
+ 
+-static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *);
+-/*
+- * This routine will wait for fabric devices for
+- * the reset delay.
+- */
+-static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *ha)
+-{
+-	uint16_t	fw_state;
+-
+-	qla2x00_get_firmware_state(ha, &fw_state);
+-}
+-
+-static __inline__ scsi_qla_host_t * to_qla_parent(scsi_qla_host_t *);
+ static __inline__ scsi_qla_host_t *
+ to_qla_parent(scsi_qla_host_t *ha)
+ {
+@@ -152,7 +69,6 @@ qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked)
+ 	return (QLA_SUCCESS);
+ }
+ 
+-static inline uint8_t *host_to_fcp_swap(uint8_t *, uint32_t);
+ static inline uint8_t *
+ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
+ {
+@@ -166,7 +82,6 @@ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
+        return fcp;
+ }
+ 
+-static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t);
+ static inline int
+ qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id)
+ {
+diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
+index 024c662..5489d50 100644
+--- a/drivers/scsi/qla2xxx/qla_iocb.c
++++ b/drivers/scsi/qla2xxx/qla_iocb.c
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -11,9 +11,6 @@
+ 
+ #include <scsi/scsi_tcq.h>
+ 
+-static inline uint16_t qla2x00_get_cmd_direction(struct scsi_cmnd *cmd);
+-static inline cont_entry_t *qla2x00_prep_cont_type0_iocb(scsi_qla_host_t *);
+-static inline cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *);
+ static request_t *qla2x00_req_pkt(scsi_qla_host_t *ha);
+ static void qla2x00_isp_cmd(scsi_qla_host_t *ha);
+ 
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index f033703..285479b 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -14,9 +14,6 @@ static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
+ static void qla2x00_status_entry(scsi_qla_host_t *, void *);
+ static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
+ static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *);
+-static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);
+-
+-static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *);
+ 
+ /**
+  * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
+@@ -33,7 +30,6 @@ qla2100_intr_handler(int irq, void *dev_id)
+ 	scsi_qla_host_t	*ha;
+ 	struct device_reg_2xxx __iomem *reg;
+ 	int		status;
+-	unsigned long	flags;
+ 	unsigned long	iter;
+ 	uint16_t	hccr;
+ 	uint16_t	mb[4];
+@@ -48,7 +44,7 @@ qla2100_intr_handler(int irq, void *dev_id)
+ 	reg = &ha->iobase->isp;
+ 	status = 0;
+ 
+-	spin_lock_irqsave(&ha->hardware_lock, flags);
++	spin_lock(&ha->hardware_lock);
+ 	for (iter = 50; iter--; ) {
+ 		hccr = RD_REG_WORD(&reg->hccr);
+ 		if (hccr & HCCR_RISC_PAUSE) {
+@@ -99,7 +95,7 @@ qla2100_intr_handler(int irq, void *dev_id)
+ 			RD_REG_WORD(&reg->hccr);
+ 		}
+ 	}
+-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
++	spin_unlock(&ha->hardware_lock);
+ 
+ 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+ 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+@@ -125,7 +121,6 @@ qla2300_intr_handler(int irq, void *dev_id)
+ 	scsi_qla_host_t	*ha;
+ 	struct device_reg_2xxx __iomem *reg;
+ 	int		status;
+-	unsigned long	flags;
+ 	unsigned long	iter;
+ 	uint32_t	stat;
+ 	uint16_t	hccr;
+@@ -141,7 +136,7 @@ qla2300_intr_handler(int irq, void *dev_id)
+ 	reg = &ha->iobase->isp;
+ 	status = 0;
+ 
+-	spin_lock_irqsave(&ha->hardware_lock, flags);
++	spin_lock(&ha->hardware_lock);
+ 	for (iter = 50; iter--; ) {
+ 		stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
+ 		if (stat & HSR_RISC_PAUSED) {
+@@ -211,7 +206,7 @@ qla2300_intr_handler(int irq, void *dev_id)
+ 		WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
+ 		RD_REG_WORD_RELAXED(&reg->hccr);
+ 	}
+-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
++	spin_unlock(&ha->hardware_lock);
+ 
+ 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+ 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+@@ -276,6 +271,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+ 	uint32_t	rscn_entry, host_pid;
+ 	uint8_t		rscn_queue_index;
++	unsigned long	flags;
++	scsi_qla_host_t	*vha;
++	int		i;
+ 
+ 	/* Setup to process RIO completion. */
+ 	handle_cnt = 0;
+@@ -351,6 +349,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 		    "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
+ 		    mb[1], mb[2], mb[3]);
+ 
++		qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
+ 		ha->isp_ops->fw_dump(ha, 1);
+ 
+ 		if (IS_FWI2_CAPABLE(ha)) {
+@@ -375,6 +374,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 		    ha->host_no));
+ 		qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n");
+ 
++		qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
+ 		set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ 		break;
+ 
+@@ -383,6 +383,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 		    ha->host_no));
+ 		qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");
+ 
++		qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
+ 		set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ 		break;
+ 
+@@ -410,6 +411,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 		set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+ 
+ 		ha->flags.management_server_logged_in = 0;
++		qla2x00_post_aen_work(ha, FCH_EVT_LIP, mb[1]);
+ 		break;
+ 
+ 	case MBA_LOOP_UP:		/* Loop Up Event */
+@@ -429,12 +431,14 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 		    link_speed);
+ 
+ 		ha->flags.management_server_logged_in = 0;
++		qla2x00_post_aen_work(ha, FCH_EVT_LINKUP, ha->link_data_rate);
+ 		break;
+ 
+ 	case MBA_LOOP_DOWN:		/* Loop Down Event */
+-		DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n",
+-		    ha->host_no, mb[1]));
+-		qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]);
++		DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
++		    "(%x %x %x).\n", ha->host_no, mb[1], mb[2], mb[3]));
++		qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x %x %x).\n",
++		    mb[1], mb[2], mb[3]);
+ 
+ 		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
+ 			atomic_set(&ha->loop_state, LOOP_DOWN);
+@@ -452,6 +456,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 		ha->link_data_rate = PORT_SPEED_UNKNOWN;
+ 		if (ql2xfdmienable)
+ 			set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
++		qla2x00_post_aen_work(ha, FCH_EVT_LINKDOWN, 0);
+ 		break;
+ 
+ 	case MBA_LIP_RESET:		/* LIP reset occurred */
+@@ -475,6 +480,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 
+ 		ha->operating_mode = LOOP;
+ 		ha->flags.management_server_logged_in = 0;
++		qla2x00_post_aen_work(ha, FCH_EVT_LIPRESET, mb[1]);
+ 		break;
+ 
+ 	case MBA_POINT_TO_POINT:	/* Point-to-Point */
+@@ -538,6 +544,18 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 		break;
+ 
+ 	case MBA_PORT_UPDATE:		/* Port database update */
++		if ((ha->flags.npiv_supported) && (ha->num_vhosts)) {
++			for_each_mapped_vp_idx(ha, i) {
++				list_for_each_entry(vha, &ha->vp_list,
++				    vp_list) {
++					if ((mb[3] & 0xff)
++					    == vha->vp_idx) {
++						ha = vha;
++						break;
++					}
++				}
++			}
++		}
+ 		/*
+ 		 * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
+ 		 * event etc. earlier indicating loop is down) then process
+@@ -572,12 +590,18 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 		break;
+ 
+ 	case MBA_RSCN_UPDATE:		/* State Change Registration */
+-		/* Check if the Vport has issued a SCR */
+-		if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags))
+-			break;
+-		/* Only handle SCNs for our Vport index. */
+-		if (ha->flags.npiv_supported && ha->vp_idx != mb[3])
+-			break;
++		if ((ha->flags.npiv_supported) && (ha->num_vhosts)) {
++			for_each_mapped_vp_idx(ha, i) {
++				list_for_each_entry(vha, &ha->vp_list,
++				    vp_list) {
++					if ((mb[3] & 0xff)
++					    == vha->vp_idx) {
++						ha = vha;
++						break;
++					}
++				}
++			}
++		}
+ 
+ 		DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
+ 		    ha->host_no));
+@@ -612,6 +636,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 
+ 		set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+ 		set_bit(RSCN_UPDATE, &ha->dpc_flags);
++		qla2x00_post_aen_work(ha, FCH_EVT_RSCN, rscn_entry);
+ 		break;
+ 
+ 	/* case MBA_RIO_RESPONSE: */
+@@ -637,6 +662,42 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ 		DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
+ 		ha->host_no, mb[1], mb[2]));
+ 		break;
++
++	case MBA_ISP84XX_ALERT:
++		DEBUG2(printk("scsi(%ld): ISP84XX Alert Notification -- "
++		    "%04x %04x %04x\n", ha->host_no, mb[1], mb[2], mb[3]));
++
++		spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
++		switch (mb[1]) {
++		case A84_PANIC_RECOVERY:
++			qla_printk(KERN_INFO, ha, "Alert 84XX: panic recovery "
++			    "%04x %04x\n", mb[2], mb[3]);
++			break;
++		case A84_OP_LOGIN_COMPLETE:
++			ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
++			DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
++			    "firmware version %x\n", ha->cs84xx->op_fw_version));
++			break;
++		case A84_DIAG_LOGIN_COMPLETE:
++			ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
++			DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
++			    "diagnostic firmware version %x\n",
++			    ha->cs84xx->diag_fw_version));
++			break;
++		case A84_GOLD_LOGIN_COMPLETE:
++			ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
++			ha->cs84xx->fw_update = 1;
++			DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX: gold "
++			    "firmware version %x\n",
++			    ha->cs84xx->gold_fw_version));
++			break;
++		default:
++			qla_printk(KERN_ERR, ha,
++			    "Alert 84xx: Invalid Alert %04x %04x %04x\n",
++			    mb[1], mb[2], mb[3]);
++		}
++		spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
++		break;
+ 	}
+ 
+ 	if (!ha->parent && ha->num_vhosts)
+@@ -803,9 +864,6 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
+ 		case STATUS_CONT_TYPE:
+ 			qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
+ 			break;
+-		case MS_IOCB_TYPE:
+-			qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt);
+-			break;
+ 		default:
+ 			/* Type Not Supported. */
+ 			DEBUG4(printk(KERN_WARNING
+@@ -1340,44 +1398,6 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
+ }
+ 
+ /**
+- * qla2x00_ms_entry() - Process a Management Server entry.
+- * @ha: SCSI driver HA context
+- * @index: Response queue out pointer
+- */
+-static void
+-qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt)
+-{
+-	srb_t          *sp;
+-
+-	DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
+-	    __func__, ha->host_no, pkt, pkt->handle1));
+-
+-	/* Validate handle. */
+- 	if (pkt->handle1 < MAX_OUTSTANDING_COMMANDS)
+- 		sp = ha->outstanding_cmds[pkt->handle1];
+-	else
+-		sp = NULL;
+-
+-	if (sp == NULL) {
+-		DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
+-		    ha->host_no));
+-		qla_printk(KERN_WARNING, ha, "MS entry - invalid handle\n");
+-
+-		set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+-		return;
+-	}
+-
+-	CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->status);
+-	CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
+-
+-	/* Free outstanding command slot. */
+-	ha->outstanding_cmds[pkt->handle1] = NULL;
+-
+-	qla2x00_sp_compl(ha, sp);
+-}
+-
+-
+-/**
+  * qla24xx_mbx_completion() - Process mailbox command completions.
+  * @ha: SCSI driver HA context
+  * @mb0: Mailbox0 register
+@@ -1449,9 +1469,6 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
+ 		case STATUS_CONT_TYPE:
+ 			qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
+ 			break;
+-		case MS_IOCB_TYPE:
+-			qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt);
+-			break;
+ 		case VP_RPT_ID_IOCB_TYPE:
+ 			qla24xx_report_id_acquisition(ha,
+ 			    (struct vp_rpt_id_entry_24xx *)pkt);
+@@ -1533,7 +1550,6 @@ qla24xx_intr_handler(int irq, void *dev_id)
+ 	scsi_qla_host_t	*ha;
+ 	struct device_reg_24xx __iomem *reg;
+ 	int		status;
+-	unsigned long	flags;
+ 	unsigned long	iter;
+ 	uint32_t	stat;
+ 	uint32_t	hccr;
+@@ -1549,13 +1565,19 @@ qla24xx_intr_handler(int irq, void *dev_id)
+ 	reg = &ha->iobase->isp24;
+ 	status = 0;
+ 
+-	spin_lock_irqsave(&ha->hardware_lock, flags);
++	spin_lock(&ha->hardware_lock);
+ 	for (iter = 50; iter--; ) {
+ 		stat = RD_REG_DWORD(&reg->host_status);
+ 		if (stat & HSRX_RISC_PAUSED) {
+ 			if (pci_channel_offline(ha->pdev))
+ 				break;
+ 
++			if (ha->hw_event_pause_errors == 0)
++				qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
++				    0, MSW(stat), LSW(stat));
++			else if (ha->hw_event_pause_errors < 0xffffffff)
++				ha->hw_event_pause_errors++;
++
+ 			hccr = RD_REG_DWORD(&reg->hccr);
+ 
+ 			qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
+@@ -1597,7 +1619,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
+ 		WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+ 		RD_REG_DWORD_RELAXED(&reg->hccr);
+ 	}
+-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
++	spin_unlock(&ha->hardware_lock);
+ 
+ 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+ 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+@@ -1608,66 +1630,21 @@ qla24xx_intr_handler(int irq, void *dev_id)
+ 	return IRQ_HANDLED;
+ }
+ 
+-/**
+- * qla24xx_ms_entry() - Process a Management Server entry.
+- * @ha: SCSI driver HA context
+- * @index: Response queue out pointer
+- */
+-static void
+-qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
+-{
+-	srb_t          *sp;
+-
+-	DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
+-	    __func__, ha->host_no, pkt, pkt->handle));
+-
+-	DEBUG9(printk("%s: ct pkt dump:\n", __func__));
+-	DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx)));
+-
+-	/* Validate handle. */
+- 	if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
+- 		sp = ha->outstanding_cmds[pkt->handle];
+-	else
+-		sp = NULL;
+-
+-	if (sp == NULL) {
+-		DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
+-		    ha->host_no));
+-		DEBUG10(printk("scsi(%ld): MS entry - invalid handle\n",
+-		    ha->host_no));
+-		qla_printk(KERN_WARNING, ha, "MS entry - invalid handle %d\n",
+-		    pkt->handle);
+-
+-		set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+-		return;
+-	}
+-
+-	CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->comp_status);
+-	CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
+-
+-	/* Free outstanding command slot. */
+-	ha->outstanding_cmds[pkt->handle] = NULL;
+-
+-	qla2x00_sp_compl(ha, sp);
+-}
+-
+ static irqreturn_t
+ qla24xx_msix_rsp_q(int irq, void *dev_id)
+ {
+ 	scsi_qla_host_t	*ha;
+ 	struct device_reg_24xx __iomem *reg;
+-	unsigned long flags;
+ 
+ 	ha = dev_id;
+ 	reg = &ha->iobase->isp24;
+ 
+-	spin_lock_irqsave(&ha->hardware_lock, flags);
++	spin_lock(&ha->hardware_lock);
+ 
+ 	qla24xx_process_response_queue(ha);
+-
+ 	WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+ 
+-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
++	spin_unlock(&ha->hardware_lock);
+ 
+ 	return IRQ_HANDLED;
+ }
+@@ -1678,7 +1655,6 @@ qla24xx_msix_default(int irq, void *dev_id)
+ 	scsi_qla_host_t	*ha;
+ 	struct device_reg_24xx __iomem *reg;
+ 	int		status;
+-	unsigned long	flags;
+ 	uint32_t	stat;
+ 	uint32_t	hccr;
+ 	uint16_t	mb[4];
+@@ -1687,13 +1663,19 @@ qla24xx_msix_default(int irq, void *dev_id)
+ 	reg = &ha->iobase->isp24;
+ 	status = 0;
+ 
+-	spin_lock_irqsave(&ha->hardware_lock, flags);
++	spin_lock(&ha->hardware_lock);
+ 	do {
+ 		stat = RD_REG_DWORD(&reg->host_status);
+ 		if (stat & HSRX_RISC_PAUSED) {
+ 			if (pci_channel_offline(ha->pdev))
+ 				break;
+ 
++			if (ha->hw_event_pause_errors == 0)
++				qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
++				    0, MSW(stat), LSW(stat));
++			else if (ha->hw_event_pause_errors < 0xffffffff)
++				ha->hw_event_pause_errors++;
++
+ 			hccr = RD_REG_DWORD(&reg->hccr);
+ 
+ 			qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
+@@ -1734,7 +1716,7 @@ qla24xx_msix_default(int irq, void *dev_id)
+ 		}
+ 		WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+ 	} while (0);
+-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
++	spin_unlock(&ha->hardware_lock);
+ 
+ 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+ 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+@@ -1821,10 +1803,9 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
+ {
+ 	int ret;
+ 	device_reg_t __iomem *reg = ha->iobase;
+-	unsigned long flags;
+ 
+ 	/* If possible, enable MSI-X. */
+-	if (!IS_QLA2432(ha) && !IS_QLA2532(ha))
++	if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
+ 		goto skip_msix;
+ 
+         if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
+@@ -1859,7 +1840,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
+ 	    "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
+ skip_msix:
+ 
+-	if (!IS_QLA24XX(ha) && !IS_QLA2532(ha))
++	if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
+ 		goto skip_msi;
+ 
+ 	ret = pci_enable_msi(ha->pdev);
+@@ -1882,7 +1863,7 @@ skip_msi:
+ clear_risc_ints:
+ 
+ 	ha->isp_ops->disable_intrs(ha);
+-	spin_lock_irqsave(&ha->hardware_lock, flags);
++	spin_lock_irq(&ha->hardware_lock);
+ 	if (IS_FWI2_CAPABLE(ha)) {
+ 		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
+ 		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
+@@ -1891,7 +1872,7 @@ clear_risc_ints:
+ 		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);
+ 		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);
+ 	}
+-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
++	spin_unlock_irq(&ha->hardware_lock);
+ 	ha->isp_ops->enable_intrs(ha);
+ 
+ fail:
+diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
+index bb10358..7d0a8a4 100644
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -310,7 +310,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
+ 	}
+ 
+ 	mcp->in_mb = MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -367,7 +367,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
+ 		}
+ 	}
+ 
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -417,7 +417,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *ha, uint16_t *major, uint16_t *minor,
+ 	mcp->out_mb = MBX_0;
+ 	mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ 	mcp->flags = 0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+ 	/* Return mailbox data. */
+@@ -466,7 +466,7 @@ qla2x00_get_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
+ 	mcp->mb[0] = MBC_GET_FIRMWARE_OPTION;
+ 	mcp->out_mb = MBX_0;
+ 	mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -524,7 +524,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
+ 		mcp->mb[12] = 0;	/* Undocumented, but used */
+ 		mcp->out_mb |= MBX_12|MBX_11|MBX_10;
+ 	}
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -576,7 +576,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
+ 	mcp->mb[7] = 0x2525;
+ 	mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -587,6 +587,14 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
+ 		if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
+ 		    mcp->mb[7] != 0x2525)
+ 			rval = QLA_FUNCTION_FAILED;
++		if (rval == QLA_FUNCTION_FAILED) {
++			struct device_reg_24xx __iomem *reg =
++			    &ha->iobase->isp24;
++
++			qla2xxx_hw_event_log(ha, HW_EVENT_ISP_ERR, 0,
++			    LSW(RD_REG_DWORD(&reg->hccr)),
++			    LSW(RD_REG_DWORD(&reg->istatus)));
++		}
+ 	}
+ 
+ 	if (rval != QLA_SUCCESS) {
+@@ -640,7 +648,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
+ 		mcp->in_mb |= MBX_1;
+ 	}
+ 
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -674,8 +682,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
+  *	Kernel context.
+  */
+ int
+-qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
+-    size_t size)
++qla2x00_issue_iocb_timeout(scsi_qla_host_t *ha, void *buffer,
++    dma_addr_t phys_addr, size_t size, uint32_t tov)
+ {
+ 	int		rval;
+ 	mbx_cmd_t	mc;
+@@ -689,7 +697,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
+ 	mcp->mb[7] = LSW(MSD(phys_addr));
+ 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_2|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = tov;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -710,6 +718,14 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
+ 	return rval;
+ }
+ 
++int
++qla2x00_issue_iocb(scsi_qla_host_t *ha, void *buffer, dma_addr_t phys_addr,
++    size_t size)
++{
++	return qla2x00_issue_iocb_timeout(ha, buffer, phys_addr, size,
++	    MBX_TOV_SECONDS);
++}
++
+ /*
+  * qla2x00_abort_command
+  *	Abort command aborts a specified IOCB.
+@@ -760,7 +776,7 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+ 	mcp->mb[6] = (uint16_t)sp->cmd->device->lun;
+ 	mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -776,36 +792,20 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+ 	return rval;
+ }
+ 
+-#if USE_ABORT_TGT
+-/*
+- * qla2x00_abort_target
+- *	Issue abort target mailbox command.
+- *
+- * Input:
+- *	ha = adapter block pointer.
+- *
+- * Returns:
+- *	qla2x00 local function return status code.
+- *
+- * Context:
+- *	Kernel context.
+- */
+ int
+-qla2x00_abort_target(fc_port_t *fcport)
++qla2x00_abort_target(struct fc_port *fcport, unsigned int l)
+ {
+-	int        rval;
++	int rval, rval2;
+ 	mbx_cmd_t  mc;
+ 	mbx_cmd_t  *mcp = &mc;
+ 	scsi_qla_host_t *ha;
+ 
+-	if (fcport == NULL)
+-		return 0;
+-
+ 	DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
+ 
++	l = l;
+ 	ha = fcport->ha;
+ 	mcp->mb[0] = MBC_ABORT_TARGET;
+-	mcp->out_mb = MBX_2|MBX_1|MBX_0;
++	mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
+ 	if (HAS_EXTENDED_IDS(ha)) {
+ 		mcp->mb[1] = fcport->loop_id;
+ 		mcp->mb[10] = 0;
+@@ -814,27 +814,70 @@ qla2x00_abort_target(fc_port_t *fcport)
+ 		mcp->mb[1] = fcport->loop_id << 8;
+ 	}
+ 	mcp->mb[2] = ha->loop_reset_delay;
++	mcp->mb[9] = ha->vp_idx;
+ 
+ 	mcp->in_mb = MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
++	if (rval != QLA_SUCCESS) {
++		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
++		    ha->host_no, rval));
++	}
+ 
+-	/* Issue marker command. */
+-	ha->marker_needed = 1;
++	/* Issue marker IOCB. */
++	rval2 = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID);
++	if (rval2 != QLA_SUCCESS) {
++		DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
++		    "(%x).\n", __func__, ha->host_no, rval2));
++	} else {
++		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
++	}
++
++	return rval;
++}
++
++int
++qla2x00_lun_reset(struct fc_port *fcport, unsigned int l)
++{
++	int rval, rval2;
++	mbx_cmd_t  mc;
++	mbx_cmd_t  *mcp = &mc;
++	scsi_qla_host_t *ha;
++
++	DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
++
++	ha = fcport->ha;
++	mcp->mb[0] = MBC_LUN_RESET;
++	mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
++	if (HAS_EXTENDED_IDS(ha))
++		mcp->mb[1] = fcport->loop_id;
++	else
++		mcp->mb[1] = fcport->loop_id << 8;
++	mcp->mb[2] = l;
++	mcp->mb[3] = 0;
++	mcp->mb[9] = ha->vp_idx;
+ 
++	mcp->in_mb = MBX_0;
++	mcp->tov = MBX_TOV_SECONDS;
++	mcp->flags = 0;
++	rval = qla2x00_mailbox_command(ha, mcp);
+ 	if (rval != QLA_SUCCESS) {
+-		DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n",
++		DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+ 		    ha->host_no, rval));
++	}
++
++	/* Issue marker IOCB. */
++	rval2 = qla2x00_marker(ha, fcport->loop_id, l, MK_SYNC_ID_LUN);
++	if (rval2 != QLA_SUCCESS) {
++		DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
++		    "(%x).\n", __func__, ha->host_no, rval2));
+ 	} else {
+-		/*EMPTY*/
+-		DEBUG11(printk("qla2x00_abort_target(%ld): done.\n",
+-		    ha->host_no));
++		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ 	}
+ 
+ 	return rval;
+ }
+-#endif
+ 
+ /*
+  * qla2x00_get_adapter_id
+@@ -871,7 +914,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
+ 	mcp->mb[9] = ha->vp_idx;
+ 	mcp->out_mb = MBX_9|MBX_0;
+ 	mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 	if (mcp->mb[0] == MBS_COMMAND_ERROR)
+@@ -928,7 +971,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *ha, uint8_t *retry_cnt, uint8_t *tov,
+ 	mcp->mb[0] = MBC_GET_RETRY_COUNT;
+ 	mcp->out_mb = MBX_0;
+ 	mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -995,7 +1038,7 @@ qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size)
+ 	mcp->in_mb = MBX_5|MBX_4|MBX_0;
+ 	mcp->buf_size = size;
+ 	mcp->flags = MBX_DMA_OUT;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+ 	if (rval != QLA_SUCCESS) {
+@@ -1173,7 +1216,7 @@ gpd_error_out:
+  *	Kernel context.
+  */
+ int
+-qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
++qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *states)
+ {
+ 	int rval;
+ 	mbx_cmd_t mc;
+@@ -1184,13 +1227,15 @@ qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
+ 
+ 	mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
+ 	mcp->out_mb = MBX_0;
+-	mcp->in_mb = MBX_2|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+-	/* Return firmware state. */
+-	*dptr = mcp->mb[1];
++	/* Return firmware states. */
++	states[0] = mcp->mb[1];
++	states[1] = mcp->mb[2];
++	states[2] = mcp->mb[3];
+ 
+ 	if (rval != QLA_SUCCESS) {
+ 		/*EMPTY*/
+@@ -1246,7 +1291,7 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
+ 	}
+ 
+ 	mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -1318,7 +1363,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha)
+ 		mcp->mb[3] = 0;
+ 	}
+ 	mcp->in_mb = MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -1743,7 +1788,7 @@ qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
+ 	}
+ 
+ 	mcp->in_mb = MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -1791,7 +1836,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha)
+ 	mcp->mb[3] = 0;
+ 	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -1852,7 +1897,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
+ 		mcp->out_mb |= MBX_6|MBX_3|MBX_2|MBX_1;
+ 	}
+ 	mcp->in_mb = MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -1896,7 +1941,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
+ 	mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
+ 	mcp->out_mb = MBX_0;
+ 	mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -2036,7 +2081,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
+ 		mcp->mb[1] = loop_id << 8;
+ 		mcp->out_mb |= MBX_1;
+ 	}
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = IOCTL_CMD;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -2082,7 +2127,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, struct link_statistics *stats,
+ 	mcp->mb[10] = 0;
+ 	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
+ 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = IOCTL_CMD;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -2180,17 +2225,15 @@ struct tsk_mgmt_cmd {
+ 	} p;
+ };
+ 
+-int
+-qla24xx_abort_target(fc_port_t *fcport)
++static int
++__qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
++    unsigned int l)
+ {
+-	int		rval;
++	int		rval, rval2;
+ 	struct tsk_mgmt_cmd *tsk;
+ 	dma_addr_t	tsk_dma;
+ 	scsi_qla_host_t *ha, *pha;
+ 
+-	if (fcport == NULL)
+-		return 0;
+-
+ 	DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
+ 
+ 	ha = fcport->ha;
+@@ -2207,47 +2250,61 @@ qla24xx_abort_target(fc_port_t *fcport)
+ 	tsk->p.tsk.entry_count = 1;
+ 	tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
+ 	tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
+-	tsk->p.tsk.control_flags = __constant_cpu_to_le32(TCF_TARGET_RESET);
++	tsk->p.tsk.control_flags = cpu_to_le32(type);
+ 	tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa;
+ 	tsk->p.tsk.port_id[1] = fcport->d_id.b.area;
+ 	tsk->p.tsk.port_id[2] = fcport->d_id.b.domain;
+ 	tsk->p.tsk.vp_index = fcport->vp_idx;
++	if (type == TCF_LUN_RESET) {
++		int_to_scsilun(l, &tsk->p.tsk.lun);
++		host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun,
++		    sizeof(tsk->p.tsk.lun));
++	}
+ 
+ 	rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0);
+ 	if (rval != QLA_SUCCESS) {
+-		DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB "
+-		    "(%x).\n", __func__, ha->host_no, rval));
+-		goto atarget_done;
++		DEBUG2_3_11(printk("%s(%ld): failed to issue %s Reset IOCB "
++		    "(%x).\n", __func__, ha->host_no, name, rval));
+ 	} else if (tsk->p.sts.entry_status != 0) {
+ 		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+ 		    "-- error status (%x).\n", __func__, ha->host_no,
+ 		    tsk->p.sts.entry_status));
+ 		rval = QLA_FUNCTION_FAILED;
+-		goto atarget_done;
+ 	} else if (tsk->p.sts.comp_status !=
+ 	    __constant_cpu_to_le16(CS_COMPLETE)) {
+ 		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+ 		    "-- completion status (%x).\n", __func__,
+ 		    ha->host_no, le16_to_cpu(tsk->p.sts.comp_status)));
+ 		rval = QLA_FUNCTION_FAILED;
+-		goto atarget_done;
+ 	}
+ 
+ 	/* Issue marker IOCB. */
+-	rval = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID);
+-	if (rval != QLA_SUCCESS) {
++	rval2 = qla2x00_marker(ha, fcport->loop_id, l,
++	    type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID);
++	if (rval2 != QLA_SUCCESS) {
+ 		DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
+-		    "(%x).\n", __func__, ha->host_no, rval));
++		    "(%x).\n", __func__, ha->host_no, rval2));
+ 	} else {
+ 		DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ 	}
+ 
+-atarget_done:
+ 	dma_pool_free(pha->s_dma_pool, tsk, tsk_dma);
+ 
+ 	return rval;
+ }
+ 
++int
++qla24xx_abort_target(struct fc_port *fcport, unsigned int l)
++{
++	return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l);
++}
++
++int
++qla24xx_lun_reset(struct fc_port *fcport, unsigned int l)
++{
++	return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l);
++}
++
+ #if 0
+ 
+ int
+@@ -2304,7 +2361,7 @@ qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g,
+ 	mcp->mb[4] = sw_em_4g | BIT_15;
+ 	mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -2372,7 +2429,7 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *ha, dma_addr_t eft_dma,
+ 	mcp->mb[7] = TC_AEN_DISABLE;
+ 	mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 	if (rval != QLA_SUCCESS) {
+@@ -2401,7 +2458,7 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *ha)
+ 	mcp->mb[1] = TC_EFT_DISABLE;
+ 	mcp->out_mb = MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 	if (rval != QLA_SUCCESS) {
+@@ -2441,7 +2498,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *ha, dma_addr_t fce_dma,
+ 	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
+ 	    MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 	if (rval != QLA_SUCCESS) {
+@@ -2477,7 +2534,7 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *ha, uint64_t *wr, uint64_t *rd)
+ 	mcp->out_mb = MBX_2|MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
+ 	    MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 	if (rval != QLA_SUCCESS) {
+@@ -2525,7 +2582,7 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr,
+ 	mcp->mb[10] = 0;
+ 	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -2559,7 +2616,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id,
+ 	mcp->mb[4] = mcp->mb[5] = 0;
+ 	mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ 	mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -2877,7 +2934,7 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
+ 	}
+ 
+ 	mcp->in_mb = MBX_0;
+-	mcp->tov = 30;
++	mcp->tov = MBX_TOV_SECONDS;
+ 	mcp->flags = 0;
+ 	rval = qla2x00_mailbox_command(ha, mcp);
+ 
+@@ -2890,3 +2947,104 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
+ 
+ 	return rval;
+ }
++
++/* 84XX Support **************************************************************/
++
++struct cs84xx_mgmt_cmd {
++	union {
++		struct verify_chip_entry_84xx req;
++		struct verify_chip_rsp_84xx rsp;
++	} p;
++};
++
++int
++qla84xx_verify_chip(struct scsi_qla_host *ha, uint16_t *status)
++{
++	int rval, retry;
++	struct cs84xx_mgmt_cmd *mn;
++	dma_addr_t mn_dma;
++	uint16_t options;
++	unsigned long flags;
++
++	DEBUG16(printk("%s(%ld): entered.\n", __func__, ha->host_no));
++
++	mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
++	if (mn == NULL) {
++		DEBUG2_3(printk("%s(%ld): failed to allocate Verify ISP84XX "
++		    "IOCB.\n", __func__, ha->host_no));
++		return QLA_MEMORY_ALLOC_FAILED;
++	}
++
++	/* Force Update? */
++	options = ha->cs84xx->fw_update ? VCO_FORCE_UPDATE : 0;
++	/* Diagnostic firmware? */
++	/* options |= MENLO_DIAG_FW; */
++	/* We update the firmware with only one data sequence. */
++	options |= VCO_END_OF_DATA;
++
++	retry = 0;
++	do {
++		memset(mn, 0, sizeof(*mn));
++		mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE;
++		mn->p.req.entry_count = 1;
++		mn->p.req.options = cpu_to_le16(options);
++
++		DEBUG16(printk("%s(%ld): Dump of Verify Request.\n", __func__,
++		    ha->host_no));
++		DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
++		    sizeof(*mn)));
++
++		rval = qla2x00_issue_iocb_timeout(ha, mn, mn_dma, 0, 120);
++		if (rval != QLA_SUCCESS) {
++			DEBUG2_16(printk("%s(%ld): failed to issue Verify "
++			    "IOCB (%x).\n", __func__, ha->host_no, rval));
++			goto verify_done;
++		}
++
++		DEBUG16(printk("%s(%ld): Dump of Verify Response.\n", __func__,
++		    ha->host_no));
++		DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
++		    sizeof(*mn)));
++
++		status[0] = le16_to_cpu(mn->p.rsp.comp_status);
++		status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
++		    le16_to_cpu(mn->p.rsp.failure_code) : 0;
++		DEBUG2_16(printk("%s(%ld): cs=%x fc=%x\n", __func__,
++		    ha->host_no, status[0], status[1]));
++
++		if (status[0] != CS_COMPLETE) {
++			rval = QLA_FUNCTION_FAILED;
++			if (!(options & VCO_DONT_UPDATE_FW)) {
++				DEBUG2_16(printk("%s(%ld): Firmware update "
++				    "failed. Retrying without update "
++				    "firmware.\n", __func__, ha->host_no));
++				options |= VCO_DONT_UPDATE_FW;
++				options &= ~VCO_FORCE_UPDATE;
++				retry = 1;
++			}
++		} else {
++			DEBUG2_16(printk("%s(%ld): firmware updated to %x.\n",
++			    __func__, ha->host_no,
++			    le32_to_cpu(mn->p.rsp.fw_ver)));
++
++			/* NOTE: we only update OP firmware. */
++			spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
++			ha->cs84xx->op_fw_version =
++			    le32_to_cpu(mn->p.rsp.fw_ver);
++			spin_unlock_irqrestore(&ha->cs84xx->access_lock,
++			    flags);
++		}
++	} while (retry);
++
++verify_done:
++	dma_pool_free(ha->s_dma_pool, mn, mn_dma);
++
++	if (rval != QLA_SUCCESS) {
++		DEBUG2_16(printk("%s(%ld): failed=%x.\n", __func__,
++		    ha->host_no, rval));
++	} else {
++		DEBUG16(printk("%s(%ld): done.\n", __func__, ha->host_no));
++	}
++
++	return rval;
++}
+diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
+index cf784cd..f2b0497 100644
+--- a/drivers/scsi/qla2xxx/qla_mid.c
++++ b/drivers/scsi/qla2xxx/qla_mid.c
+@@ -1,20 +1,8 @@
+ /*
+- *                  QLOGIC LINUX SOFTWARE
+- *
+- * QLogic ISP2x00 device driver for Linux 2.6.x
+- * Copyright (C) 2003-2005 QLogic Corporation
+- * (www.qlogic.com)
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * General Public License for more details.
++ * QLogic Fibre Channel HBA Driver
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
++ * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+ #include "qla_def.h"
+ 
+@@ -28,8 +16,6 @@
+ #include <scsi/scsicam.h>
+ #include <linux/delay.h>
+ 
+-void qla2x00_vp_stop_timer(scsi_qla_host_t *);
+-
+ void
+ qla2x00_vp_stop_timer(scsi_qla_host_t *vha)
+ {
+@@ -268,9 +254,17 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
+ static int
+ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
+ {
++	scsi_qla_host_t *ha = vha->parent;
++
+ 	if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) {
+ 		/* VP acquired. complete port configuration */
+-		qla24xx_configure_vp(vha);
++		if (atomic_read(&ha->loop_state) == LOOP_READY) {
++			qla24xx_configure_vp(vha);
++		} else {
++			set_bit(VP_IDX_ACQUIRED, &vha->vp_flags);
++			set_bit(VP_DPC_NEEDED, &ha->dpc_flags);
++		}
++
+ 		return 0;
+ 	}
+ 
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 3c1b433..8b33b16 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -26,9 +26,6 @@ char qla2x00_version_str[40];
+  */
+ static struct kmem_cache *srb_cachep;
+ 
+-/*
+- * Ioctl related information.
+- */
+ int num_hosts;
+ int ql2xlogintimeout = 20;
+ module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
+@@ -103,9 +100,9 @@ static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
+ 		void (*fn)(struct scsi_cmnd *));
+ static int qla2xxx_eh_abort(struct scsi_cmnd *);
+ static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
++static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
+ static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
+ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
+-static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *);
+ 
+ static int qla2x00_change_queue_depth(struct scsi_device *, int);
+ static int qla2x00_change_queue_type(struct scsi_device *, int);
+@@ -117,6 +114,7 @@ static struct scsi_host_template qla2x00_driver_template = {
+ 
+ 	.eh_abort_handler	= qla2xxx_eh_abort,
+ 	.eh_device_reset_handler = qla2xxx_eh_device_reset,
++	.eh_target_reset_handler = qla2xxx_eh_target_reset,
+ 	.eh_bus_reset_handler	= qla2xxx_eh_bus_reset,
+ 	.eh_host_reset_handler	= qla2xxx_eh_host_reset,
+ 
+@@ -148,6 +146,7 @@ struct scsi_host_template qla24xx_driver_template = {
+ 
+ 	.eh_abort_handler	= qla2xxx_eh_abort,
+ 	.eh_device_reset_handler = qla2xxx_eh_device_reset,
++	.eh_target_reset_handler = qla2xxx_eh_target_reset,
+ 	.eh_bus_reset_handler	= qla2xxx_eh_bus_reset,
+ 	.eh_host_reset_handler	= qla2xxx_eh_host_reset,
+ 
+@@ -253,9 +252,9 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str)
+ 
+ 		strcpy(str, "PCIe (");
+ 		if (lspeed == 1)
+-			strcat(str, "2.5Gb/s ");
++			strcat(str, "2.5GT/s ");
+ 		else if (lspeed == 2)
+-			strcat(str, "5.0Gb/s ");
++			strcat(str, "5.0GT/s ");
+ 		else
+ 			strcat(str, "<unknown> ");
+ 		snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth);
+@@ -340,6 +339,8 @@ qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str)
+ 		strcat(str, "[T10 CRC] ");
+ 	if (ha->fw_attributes & BIT_5)
+ 		strcat(str, "[VI] ");
++	if (ha->fw_attributes & BIT_10)
++		strcat(str, "[84XX] ");
+ 	if (ha->fw_attributes & BIT_13)
+ 		strcat(str, "[Experimental]");
+ 	return str;
+@@ -570,8 +571,6 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
+ 	else
+ 		return_status = QLA_FUNCTION_FAILED;
+ 
+-	DEBUG2(printk("%s return_status=%d\n",__func__,return_status));
+-
+ 	return (return_status);
+ }
+ 
+@@ -685,7 +684,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+ 
+ 		DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n",
+ 		    __func__, ha->host_no, sp, serial));
+-		DEBUG3(qla2x00_print_scsi_cmd(cmd));
+ 
+ 		spin_unlock_irqrestore(&pha->hardware_lock, flags);
+ 		if (ha->isp_ops->abort_command(ha, sp)) {
+@@ -719,190 +717,122 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+ 	return ret;
+ }
+ 
+-/**************************************************************************
+-* qla2x00_eh_wait_for_pending_target_commands
+-*
+-* Description:
+-*    Waits for all the commands to come back from the specified target.
+-*
+-* Input:
+-*    ha - pointer to scsi_qla_host structure.
+-*    t  - target
+-* Returns:
+-*    Either SUCCESS or FAILED.
+-*
+-* Note:
+-**************************************************************************/
++enum nexus_wait_type {
++	WAIT_HOST = 0,
++	WAIT_TARGET,
++	WAIT_LUN,
++};
++
+ static int
+-qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
++qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha, unsigned int t,
++    unsigned int l, enum nexus_wait_type type)
+ {
+-	int	cnt;
+-	int	status;
+-	srb_t		*sp;
+-	struct scsi_cmnd *cmd;
++	int cnt, match, status;
++	srb_t *sp;
+ 	unsigned long flags;
+ 	scsi_qla_host_t *pha = to_qla_parent(ha);
+ 
+-	status = 0;
+-
+-	/*
+-	 * Waiting for all commands for the designated target in the active
+-	 * array
+-	 */
+-	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+-		spin_lock_irqsave(&pha->hardware_lock, flags);
++	status = QLA_SUCCESS;
++	spin_lock_irqsave(&pha->hardware_lock, flags);
++	for (cnt = 1; status == QLA_SUCCESS && cnt < MAX_OUTSTANDING_COMMANDS;
++	    cnt++) {
+ 		sp = pha->outstanding_cmds[cnt];
+-		if (sp) {
+-			cmd = sp->cmd;
+-			spin_unlock_irqrestore(&pha->hardware_lock, flags);
+-			if (cmd->device->id == t &&
+-			    ha->vp_idx == sp->ha->vp_idx) {
+-				if (!qla2x00_eh_wait_on_command(ha, cmd)) {
+-					status = 1;
+-					break;
+-				}
+-			}
+-		} else {
+-			spin_unlock_irqrestore(&pha->hardware_lock, flags);
++		if (!sp)
++			continue;
++		if (ha->vp_idx != sp->ha->vp_idx)
++			continue;
++		match = 0;
++		switch (type) {
++		case WAIT_HOST:
++			match = 1;
++			break;
++		case WAIT_TARGET:
++			match = sp->cmd->device->id == t;
++			break;
++		case WAIT_LUN:
++			match = (sp->cmd->device->id == t &&
++			    sp->cmd->device->lun == l);
++			break;
+ 		}
++		if (!match)
++			continue;
++
++		spin_unlock_irqrestore(&pha->hardware_lock, flags);
++		status = qla2x00_eh_wait_on_command(ha, sp->cmd);
++		spin_lock_irqsave(&pha->hardware_lock, flags);
+ 	}
+-	return (status);
++	spin_unlock_irqrestore(&pha->hardware_lock, flags);
++
++	return status;
+ }
+ 
++static char *reset_errors[] = {
++	"HBA not online",
++	"HBA not ready",
++	"Task management failed",
++	"Waiting for command completions",
++};
+ 
+-/**************************************************************************
+-* qla2xxx_eh_device_reset
+-*
+-* Description:
+-*    The device reset function will reset the target and abort any
+-*    executing commands.
+-*
+-*    NOTE: The use of SP is undefined within this context.  Do *NOT*
+-*          attempt to use this value, even if you determine it is
+-*          non-null.
+-*
+-* Input:
+-*    cmd = Linux SCSI command packet of the command that cause the
+-*          bus device reset.
+-*
+-* Returns:
+-*    SUCCESS/FAILURE (defined as macro in scsi.h).
+-*
+-**************************************************************************/
+ static int
+-qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
++__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
++    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int))
+ {
+ 	scsi_qla_host_t *ha = shost_priv(cmd->device->host);
+ 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
+-	int ret = FAILED;
+-	unsigned int id, lun;
+-	unsigned long serial;
++	int err;
+ 
+ 	qla2x00_block_error_handler(cmd);
+ 
+-	id = cmd->device->id;
+-	lun = cmd->device->lun;
+-	serial = cmd->serial_number;
+-
+ 	if (!fcport)
+-		return ret;
++		return FAILED;
+ 
+-	qla_printk(KERN_INFO, ha,
+-	    "scsi(%ld:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, id, lun);
++	qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
++	    ha->host_no, cmd->device->id, cmd->device->lun, name);
+ 
++	err = 0;
+ 	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
+-		goto eh_dev_reset_done;
+-
+-	if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {
+-		if (qla2x00_device_reset(ha, fcport) == 0)
+-			ret = SUCCESS;
+-
+-#if defined(LOGOUT_AFTER_DEVICE_RESET)
+-		if (ret == SUCCESS) {
+-			if (fcport->flags & FC_FABRIC_DEVICE) {
+-				ha->isp_ops->fabric_logout(ha, fcport->loop_id);
+-				qla2x00_mark_device_lost(ha, fcport, 0, 0);
+-			}
+-		}
+-#endif
+-	} else {
+-		DEBUG2(printk(KERN_INFO
+-		    "%s failed: loop not ready\n",__func__));
+-	}
+-
+-	if (ret == FAILED) {
+-		DEBUG3(printk("%s(%ld): device reset failed\n",
+-		    __func__, ha->host_no));
+-		qla_printk(KERN_INFO, ha, "%s: device reset failed\n",
+-		    __func__);
++		goto eh_reset_failed;
++	err = 1;
++	if (qla2x00_wait_for_loop_ready(ha) != QLA_SUCCESS)
++		goto eh_reset_failed;
++	err = 2;
++	if (do_reset(fcport, cmd->device->lun) != QLA_SUCCESS)
++		goto eh_reset_failed;
++	err = 3;
++	if (qla2x00_eh_wait_for_pending_commands(ha, cmd->device->id,
++	    cmd->device->lun, type) != QLA_SUCCESS)
++		goto eh_reset_failed;
++
++	qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
++	    ha->host_no, cmd->device->id, cmd->device->lun, name);
++
++	return SUCCESS;
++
++ eh_reset_failed:
++	qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET FAILED: %s.\n",
++	    ha->host_no, cmd->device->id, cmd->device->lun, name,
++	    reset_errors[err]);
++	return FAILED;
++}
+ 
+-		goto eh_dev_reset_done;
+-	}
++static int
++qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
++{
++	scsi_qla_host_t *ha = shost_priv(cmd->device->host);
+ 
+-	/* Flush outstanding commands. */
+-	if (qla2x00_eh_wait_for_pending_target_commands(ha, id))
+-		ret = FAILED;
+-	if (ret == FAILED) {
+-		DEBUG3(printk("%s(%ld): failed while waiting for commands\n",
+-		    __func__, ha->host_no));
+-		qla_printk(KERN_INFO, ha,
+-		    "%s: failed while waiting for commands\n", __func__);
+-	} else
+-		qla_printk(KERN_INFO, ha,
+-		    "scsi(%ld:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no,
+-		    id, lun);
+- eh_dev_reset_done:
+-	return ret;
++	return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
++	    ha->isp_ops->lun_reset);
+ }
+ 
+-/**************************************************************************
+-* qla2x00_eh_wait_for_pending_commands
+-*
+-* Description:
+-*    Waits for all the commands to come back from the specified host.
+-*
+-* Input:
+-*    ha - pointer to scsi_qla_host structure.
+-*
+-* Returns:
+-*    1 : SUCCESS
+-*    0 : FAILED
+-*
+-* Note:
+-**************************************************************************/
+ static int
+-qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
++qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
+ {
+-	int	cnt;
+-	int	status;
+-	srb_t		*sp;
+-	struct scsi_cmnd *cmd;
+-	unsigned long flags;
+-
+-	status = 1;
++	scsi_qla_host_t *ha = shost_priv(cmd->device->host);
+ 
+-	/*
+-	 * Waiting for all commands for the designated target in the active
+-	 * array
+-	 */
+-	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+-		spin_lock_irqsave(&ha->hardware_lock, flags);
+-		sp = ha->outstanding_cmds[cnt];
+-		if (sp) {
+-			cmd = sp->cmd;
+-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
+-			status = qla2x00_eh_wait_on_command(ha, cmd);
+-			if (status == 0)
+-				break;
+-		}
+-		else {
+-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
+-		}
+-	}
+-	return (status);
++	return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
++	    ha->isp_ops->target_reset);
+ }
+ 
+-
+ /**************************************************************************
+ * qla2xxx_eh_bus_reset
+ *
+@@ -953,7 +883,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
+ 		goto eh_bus_reset_done;
+ 
+ 	/* Flush outstanding commands. */
+-	if (!qla2x00_eh_wait_for_pending_commands(pha))
++	if (qla2x00_eh_wait_for_pending_commands(pha, 0, 0, WAIT_HOST) !=
++	    QLA_SUCCESS)
+ 		ret = FAILED;
+ 
+ eh_bus_reset_done:
+@@ -1024,7 +955,8 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
+ 	clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
+ 
+ 	/* Waiting for our command in done_queue to be returned to OS.*/
+-	if (qla2x00_eh_wait_for_pending_commands(pha))
++	if (qla2x00_eh_wait_for_pending_commands(pha, 0, 0, WAIT_HOST) ==
++	    QLA_SUCCESS)
+ 		ret = SUCCESS;
+ 
+ 	if (ha->parent)
+@@ -1080,7 +1012,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
+ 			if (fcport->port_type != FCT_TARGET)
+ 				continue;
+ 
+-			ret = qla2x00_device_reset(ha, fcport);
++			ret = ha->isp_ops->target_reset(fcport, 0);
+ 			if (ret != QLA_SUCCESS) {
+ 				DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+ 				    "target_reset=%d d_id=%x.\n", __func__,
+@@ -1095,26 +1027,6 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
+ 	return QLA_SUCCESS;
+ }
+ 
+-/*
+- * qla2x00_device_reset
+- *	Issue bus device reset message to the target.
+- *
+- * Input:
+- *	ha = adapter block pointer.
+- *	t = SCSI ID.
+- *	TARGET_QUEUE_LOCK must be released.
+- *	ADAPTER_STATE_LOCK must be released.
+- *
+- * Context:
+- *	Kernel context.
+- */
+-static int
+-qla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport)
+-{
+-	/* Abort Target command will clear Reservation */
+-	return ha->isp_ops->abort_target(reset_fcport);
+-}
+-
+ void
+ qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res)
+ {
+@@ -1292,7 +1204,8 @@ static struct isp_operations qla2100_isp_ops = {
+ 	.enable_intrs		= qla2x00_enable_intrs,
+ 	.disable_intrs		= qla2x00_disable_intrs,
+ 	.abort_command		= qla2x00_abort_command,
+-	.abort_target		= qla2x00_abort_target,
++	.target_reset		= qla2x00_abort_target,
++	.lun_reset		= qla2x00_lun_reset,
+ 	.fabric_login		= qla2x00_login_fabric,
+ 	.fabric_logout		= qla2x00_fabric_logout,
+ 	.calc_req_entries	= qla2x00_calc_iocbs_32,
+@@ -1325,7 +1238,8 @@ static struct isp_operations qla2300_isp_ops = {
+ 	.enable_intrs		= qla2x00_enable_intrs,
+ 	.disable_intrs		= qla2x00_disable_intrs,
+ 	.abort_command		= qla2x00_abort_command,
+-	.abort_target		= qla2x00_abort_target,
++	.target_reset		= qla2x00_abort_target,
++	.lun_reset		= qla2x00_lun_reset,
+ 	.fabric_login		= qla2x00_login_fabric,
+ 	.fabric_logout		= qla2x00_fabric_logout,
+ 	.calc_req_entries	= qla2x00_calc_iocbs_32,
+@@ -1358,7 +1272,8 @@ static struct isp_operations qla24xx_isp_ops = {
+ 	.enable_intrs		= qla24xx_enable_intrs,
+ 	.disable_intrs		= qla24xx_disable_intrs,
+ 	.abort_command		= qla24xx_abort_command,
+-	.abort_target		= qla24xx_abort_target,
++	.target_reset		= qla24xx_abort_target,
++	.lun_reset		= qla24xx_lun_reset,
+ 	.fabric_login		= qla24xx_login_fabric,
+ 	.fabric_logout		= qla24xx_fabric_logout,
+ 	.calc_req_entries	= NULL,
+@@ -1391,7 +1306,8 @@ static struct isp_operations qla25xx_isp_ops = {
+ 	.enable_intrs		= qla24xx_enable_intrs,
+ 	.disable_intrs		= qla24xx_disable_intrs,
+ 	.abort_command		= qla24xx_abort_command,
+-	.abort_target		= qla24xx_abort_target,
++	.target_reset		= qla24xx_abort_target,
++	.lun_reset		= qla24xx_lun_reset,
+ 	.fabric_login		= qla24xx_login_fabric,
+ 	.fabric_logout		= qla24xx_fabric_logout,
+ 	.calc_req_entries	= NULL,
+@@ -1464,6 +1380,13 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha)
+ 		ha->device_type |= DT_IIDMA;
+ 		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
+ 		break;
++	case PCI_DEVICE_ID_QLOGIC_ISP8432:
++		ha->device_type |= DT_ISP8432;
++		ha->device_type |= DT_ZIO_SUPPORTED;
++		ha->device_type |= DT_FWI2;
++		ha->device_type |= DT_IIDMA;
++		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
++		break;
+ 	case PCI_DEVICE_ID_QLOGIC_ISP5422:
+ 		ha->device_type |= DT_ISP5422;
+ 		ha->device_type |= DT_FWI2;
+@@ -1587,6 +1510,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	sht = &qla2x00_driver_template;
+ 	if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
+ 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
++	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
+ 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
+ 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
+ 	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
+@@ -1677,7 +1601,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		if (IS_QLA2322(ha) || IS_QLA6322(ha))
+ 			ha->optrom_size = OPTROM_SIZE_2322;
+ 		ha->isp_ops = &qla2300_isp_ops;
+-	} else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
++	} else if (IS_QLA24XX_TYPE(ha)) {
+ 		host->max_id = MAX_TARGETS_2200;
+ 		ha->mbx_count = MAILBOX_REGISTER_COUNT;
+ 		ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
+@@ -1699,6 +1623,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		ha->gid_list_info_size = 8;
+ 		ha->optrom_size = OPTROM_SIZE_25XX;
+ 		ha->isp_ops = &qla25xx_isp_ops;
++		ha->hw_event_start = PCI_FUNC(pdev->devfn) ?
++		    FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR;
+ 	}
+ 	host->can_queue = ha->request_q_length + 128;
+ 
+@@ -1713,6 +1639,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	INIT_LIST_HEAD(&ha->list);
+ 	INIT_LIST_HEAD(&ha->fcports);
+ 	INIT_LIST_HEAD(&ha->vp_list);
++	INIT_LIST_HEAD(&ha->work_list);
+ 
+ 	set_bit(0, (unsigned long *) ha->vp_idx_map);
+ 
+@@ -1819,6 +1746,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
+ 
+ 	qla2x00_dfs_remove(ha);
+ 
++	qla84xx_put_chip(ha);
++
+ 	qla2x00_free_sysfs_attr(ha);
+ 
+ 	fc_remove_host(ha->host);
+@@ -2206,6 +2135,97 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
+ 	kfree(ha->nvram);
+ }
+ 
++struct qla_work_evt *
++qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
++    int locked)
++{
++	struct qla_work_evt *e;
++
++	e = kzalloc(sizeof(struct qla_work_evt), locked ? GFP_ATOMIC:
++	    GFP_KERNEL);
++	if (!e)
++		return NULL;
++
++	INIT_LIST_HEAD(&e->list);
++	e->type = type;
++	e->flags = QLA_EVT_FLAG_FREE;
++	return e;
++}
++
++int
++qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
++{
++	unsigned long flags;
++
++	if (!locked)
++		spin_lock_irqsave(&ha->hardware_lock, flags);
++	list_add_tail(&e->list, &ha->work_list);
++	qla2xxx_wake_dpc(ha);
++	if (!locked)
++		spin_unlock_irqrestore(&ha->hardware_lock, flags);
++	return QLA_SUCCESS;
++}
++
++int
++qla2x00_post_aen_work(struct scsi_qla_host *ha, enum fc_host_event_code code,
++    u32 data)
++{
++	struct qla_work_evt *e;
++
++	e = qla2x00_alloc_work(ha, QLA_EVT_AEN, 1);
++	if (!e)
++		return QLA_FUNCTION_FAILED;
++
++	e->u.aen.code = code;
++	e->u.aen.data = data;
++	return qla2x00_post_work(ha, e, 1);
++}
++
++int
++qla2x00_post_hwe_work(struct scsi_qla_host *ha, uint16_t code, uint16_t d1,
++    uint16_t d2, uint16_t d3)
++{
++	struct qla_work_evt *e;
++
++	e = qla2x00_alloc_work(ha, QLA_EVT_HWE_LOG, 1);
++	if (!e)
++		return QLA_FUNCTION_FAILED;
++
++	e->u.hwe.code = code;
++	e->u.hwe.d1 = d1;
++	e->u.hwe.d2 = d2;
++	e->u.hwe.d3 = d3;
++	return qla2x00_post_work(ha, e, 1);
++}
++
++static void
++qla2x00_do_work(struct scsi_qla_host *ha)
++{
++	struct qla_work_evt *e;
++
++	spin_lock_irq(&ha->hardware_lock);
++	while (!list_empty(&ha->work_list)) {
++		e = list_entry(ha->work_list.next, struct qla_work_evt, list);
++		list_del_init(&e->list);
++		spin_unlock_irq(&ha->hardware_lock);
++
++		switch (e->type) {
++		case QLA_EVT_AEN:
++			fc_host_post_event(ha->host, fc_get_event_number(),
++			    e->u.aen.code, e->u.aen.data);
++			break;
++		case QLA_EVT_HWE_LOG:
++			qla2xxx_hw_event_log(ha, e->u.hwe.code, e->u.hwe.d1,
++			    e->u.hwe.d2, e->u.hwe.d3);
++			break;
++		}
++		if (e->flags & QLA_EVT_FLAG_FREE)
++			kfree(e);
++		spin_lock_irq(&ha->hardware_lock);
++	}
++	spin_unlock_irq(&ha->hardware_lock);
++}
++
+ /**************************************************************************
+ * qla2x00_do_dpc
+ *   This kernel thread is a task that is schedule by the interrupt handler
+@@ -2257,6 +2277,8 @@ qla2x00_do_dpc(void *data)
+ 			continue;
+ 		}
+ 
++		qla2x00_do_work(ha);
++
+ 		if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) {
+ 
+ 			DEBUG(printk("scsi(%ld): dpc: sched "
+@@ -2291,12 +2313,6 @@ qla2x00_do_dpc(void *data)
+ 		if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))
+ 			qla2x00_update_fcports(ha);
+ 
+-		if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) {
+-			DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n",
+-			    ha->host_no));
+-			qla2x00_loop_reset(ha);
+-		}
+-
+ 		if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) &&
+ 		    (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) {
+ 
+@@ -2367,19 +2383,6 @@ qla2x00_do_dpc(void *data)
+ 			    ha->host_no));
+ 		}
+ 
+-		if ((test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags)) &&
+-		    atomic_read(&ha->loop_state) != LOOP_DOWN) {
+-
+-			clear_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags);
+-			DEBUG(printk("scsi(%ld): qla2x00_login_retry()\n",
+-			    ha->host_no));
+-
+-			set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+-
+-			DEBUG(printk("scsi(%ld): qla2x00_login_retry - end\n",
+-			    ha->host_no));
+-		}
+-
+ 		if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
+ 
+ 			DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n",
+@@ -2397,18 +2400,6 @@ qla2x00_do_dpc(void *data)
+ 			    ha->host_no));
+ 		}
+ 
+-		if (test_and_clear_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags)) {
+-
+-			DEBUG(printk("scsi(%ld): Rescan flagged fcports...\n",
+-			    ha->host_no));
+-
+-			qla2x00_rescan_fcports(ha);
+-
+-			DEBUG(printk("scsi(%ld): Rescan flagged fcports..."
+-			    "end.\n",
+-			    ha->host_no));
+-		}
+-
+ 		if (!ha->interrupts_on)
+ 			ha->isp_ops->enable_intrs(ha);
+ 
+@@ -2586,7 +2577,8 @@ qla2x00_timer(scsi_qla_host_t *ha)
+ 			set_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags);
+ 			start_dpc++;
+ 
+-			if (!(ha->device_flags & DFLG_NO_CABLE)) {
++			if (!(ha->device_flags & DFLG_NO_CABLE) &&
++			    !ha->parent) {
+ 				DEBUG(printk("scsi(%ld): Loop down - "
+ 				    "aborting ISP.\n",
+ 				    ha->host_no));
+@@ -2610,10 +2602,8 @@ qla2x00_timer(scsi_qla_host_t *ha)
+ 	/* Schedule the DPC routine if needed */
+ 	if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
+ 	    test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
+-	    test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) ||
+ 	    test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags) ||
+ 	    start_dpc ||
+-	    test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
+ 	    test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
+ 	    test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
+ 	    test_bit(VP_DPC_NEEDED, &ha->dpc_flags) ||
+@@ -2665,7 +2655,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha)
+ 		blob = &qla_fw_blobs[FW_ISP2300];
+ 	} else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ 		blob = &qla_fw_blobs[FW_ISP2322];
+-	} else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
++	} else if (IS_QLA24XX_TYPE(ha)) {
+ 		blob = &qla_fw_blobs[FW_ISP24XX];
+ 	} else if (IS_QLA25XX(ha)) {
+ 		blob = &qla_fw_blobs[FW_ISP25XX];
+@@ -2815,6 +2805,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8432) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
+diff --git a/drivers/scsi/qla2xxx/qla_settings.h b/drivers/scsi/qla2xxx/qla_settings.h
+index 249e4d9..2801c26 100644
+--- a/drivers/scsi/qla2xxx/qla_settings.h
++++ b/drivers/scsi/qla2xxx/qla_settings.h
+@@ -1,26 +1,12 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+-/*
+- * Compile time Options:
+- *     0 - Disable and 1 - Enable
+- */
+-#define DEBUG_QLA2100		0	/* For Debug of qla2x00 */
+-
+-#define USE_ABORT_TGT		1	/* Use Abort Target mbx cmd */
+-
+ #define MAX_RETRIES_OF_ISP_ABORT	5
+ 
+ /* Max time to wait for the loop to be in LOOP_READY state */
+ #define MAX_LOOP_TIMEOUT	(60 * 5)
+ 
+-/*
+- * Some vendor subsystems do not recover properly after a device reset.  Define
+- * the following to force a logout after a successful device reset.
+- */
+-#undef LOGOUT_AFTER_DEVICE_RESET
+-
+ #include "qla_version.h"
+diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
+index 26822c8..1728ab3 100644
+--- a/drivers/scsi/qla2xxx/qla_sup.c
++++ b/drivers/scsi/qla2xxx/qla_sup.c
+@@ -1,6 +1,6 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+@@ -543,79 +543,174 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
+ 	}
+ }
+ 
+-static int
+-qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
+-    uint32_t dwords)
++void
++qla2xxx_get_flash_info(scsi_qla_host_t *ha)
+ {
+-	int ret;
+-	uint32_t liter, miter;
+-	uint32_t sec_mask, rest_addr, conf_addr;
+-	uint32_t fdata, findex, cnt;
++#define FLASH_BLK_SIZE_32K	0x8000
++#define FLASH_BLK_SIZE_64K	0x10000
++	uint16_t cnt, chksum;
++	uint16_t *wptr;
++	struct qla_fdt_layout *fdt;
+ 	uint8_t	man_id, flash_id;
+-	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+-	dma_addr_t optrom_dma;
+-	void *optrom = NULL;
+-	uint32_t *s, *d;
+ 
+-	ret = QLA_SUCCESS;
++	if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
++		return;
+ 
+-	/* Prepare burst-capable write on supported ISPs. */
+-	if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
+-	    dwords > OPTROM_BURST_DWORDS) {
+-		optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
+-		    &optrom_dma, GFP_KERNEL);
+-		if (!optrom) {
+-			qla_printk(KERN_DEBUG, ha,
+-			    "Unable to allocate memory for optrom burst write "
+-			    "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
+-		}
++	wptr = (uint16_t *)ha->request_ring;
++	fdt = (struct qla_fdt_layout *)ha->request_ring;
++	ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring,
++	    FA_FLASH_DESCR_ADDR << 2, OPTROM_BURST_SIZE);
++	if (*wptr == __constant_cpu_to_le16(0xffff))
++		goto no_flash_data;
++	if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' ||
++	    fdt->sig[3] != 'D')
++		goto no_flash_data;
++
++	for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1;
++	    cnt++)
++		chksum += le16_to_cpu(*wptr++);
++	if (chksum) {
++		DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FDT detected: "
++		    "checksum=0x%x id=%c version=0x%x.\n", chksum, fdt->sig[0],
++		    le16_to_cpu(fdt->version)));
++		DEBUG9(qla2x00_dump_buffer((uint8_t *)fdt, sizeof(*fdt)));
++		goto no_flash_data;
+ 	}
+ 
+-	qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
+-	DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
+-	    ha->host_no, man_id, flash_id));
++	ha->fdt_odd_index = le16_to_cpu(fdt->man_id) == 0x1f;
++	ha->fdt_wrt_disable = fdt->wrt_disable_bits;
++	ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd);
++	ha->fdt_block_size = le32_to_cpu(fdt->block_size);
++	if (fdt->unprotect_sec_cmd) {
++		ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0300 |
++		    fdt->unprotect_sec_cmd);
++		ha->fdt_protect_sec_cmd = fdt->protect_sec_cmd ?
++		    flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd):
++		    flash_conf_to_access_addr(0x0336);
++	}
+ 
+-	conf_addr = flash_conf_to_access_addr(0x03d8);
++	DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[FDT]: (0x%x/0x%x) erase=0x%x "
++	    "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n",
++	    le16_to_cpu(fdt->man_id), le16_to_cpu(fdt->id), ha->fdt_erase_cmd,
++	    ha->fdt_protect_sec_cmd, ha->fdt_unprotect_sec_cmd,
++	    ha->fdt_odd_index, ha->fdt_wrt_disable, ha->fdt_block_size));
++	return;
++
++no_flash_data:
++	qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
++	ha->fdt_wrt_disable = 0x9c;
++	ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8);
+ 	switch (man_id) {
+ 	case 0xbf: /* STT flash. */
+-		if (flash_id == 0x8e) {
+-			rest_addr = 0x3fff;
+-			sec_mask = 0x7c000;
+-		} else {
+-			rest_addr = 0x1fff;
+-			sec_mask = 0x7e000;
+-		}
++		if (flash_id == 0x8e)
++			ha->fdt_block_size = FLASH_BLK_SIZE_64K;
++		else
++			ha->fdt_block_size = FLASH_BLK_SIZE_32K;
++
+ 		if (flash_id == 0x80)
+-			conf_addr = flash_conf_to_access_addr(0x0352);
++			ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0352);
+ 		break;
+ 	case 0x13: /* ST M25P80. */
+-		rest_addr = 0x3fff;
+-		sec_mask = 0x7c000;
++		ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+ 		break;
+-	case 0x1f: // Atmel 26DF081A
+-		rest_addr = 0x3fff;
+-		sec_mask = 0x7c000;
+-		conf_addr = flash_conf_to_access_addr(0x0320);
++	case 0x1f: /* Atmel 26DF081A. */
++		ha->fdt_odd_index = 1;
++		ha->fdt_block_size = FLASH_BLK_SIZE_64K;
++		ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0320);
++		ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0339);
++		ha->fdt_protect_sec_cmd = flash_conf_to_access_addr(0x0336);
+ 		break;
+ 	default:
+ 		/* Default to 64 kb sector size. */
+-		rest_addr = 0x3fff;
+-		sec_mask = 0x7c000;
++		ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+ 		break;
+ 	}
+ 
++	DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[MID]: (0x%x/0x%x) erase=0x%x "
++	    "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", man_id, flash_id,
++	    ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd,
++	    ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable,
++	    ha->fdt_block_size));
++}
++
++static void
++qla24xx_unprotect_flash(scsi_qla_host_t *ha)
++{
++	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
++
+ 	/* Enable flash write. */
+ 	WRT_REG_DWORD(&reg->ctrl_status,
+ 	    RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
+ 	RD_REG_DWORD(&reg->ctrl_status);	/* PCI Posting. */
+ 
++	if (!ha->fdt_wrt_disable)
++		return;
++
+ 	/* Disable flash write-protection. */
+ 	qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
+ 	/* Some flash parts need an additional zero-write to clear bits.*/
+ 	qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
++}
++
++static void
++qla24xx_protect_flash(scsi_qla_host_t *ha)
++{
++	uint32_t cnt;
++	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
++
++	if (!ha->fdt_wrt_disable)
++		goto skip_wrt_protect;
++
++	/* Enable flash write-protection and wait for completion. */
++	qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101),
++	    ha->fdt_wrt_disable);
++	for (cnt = 300; cnt &&
++	    qla24xx_read_flash_dword(ha,
++		    flash_conf_to_access_addr(0x005)) & BIT_0;
++	    cnt--) {
++		udelay(10);
++	}
++
++skip_wrt_protect:
++	/* Disable flash write. */
++	WRT_REG_DWORD(&reg->ctrl_status,
++	    RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
++	RD_REG_DWORD(&reg->ctrl_status);	/* PCI Posting. */
++}
++
++static int
++qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
++    uint32_t dwords)
++{
++	int ret;
++	uint32_t liter, miter;
++	uint32_t sec_mask, rest_addr;
++	uint32_t fdata, findex;
++	dma_addr_t optrom_dma;
++	void *optrom = NULL;
++	uint32_t *s, *d;
++
++	ret = QLA_SUCCESS;
++
++	/* Prepare burst-capable write on supported ISPs. */
++	if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
++	    dwords > OPTROM_BURST_DWORDS) {
++		optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
++		    &optrom_dma, GFP_KERNEL);
++		if (!optrom) {
++			qla_printk(KERN_DEBUG, ha,
++			    "Unable to allocate memory for optrom burst write "
++			    "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
++		}
++	}
++
++	rest_addr = (ha->fdt_block_size >> 2) - 1;
++	sec_mask = 0x80000 - (ha->fdt_block_size >> 2);
++
++	qla24xx_unprotect_flash(ha);
+ 
+ 	for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
+-		if (man_id == 0x1f) {
++		if (ha->fdt_odd_index) {
+ 			findex = faddr << 2;
+ 			fdata = findex & sec_mask;
+ 		} else {
+@@ -625,13 +720,13 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
+ 
+ 		/* Are we at the beginning of a sector? */
+ 		if ((findex & rest_addr) == 0) {
+-			/* Do sector unprotect at 4K boundry for Atmel part. */
+-			if (man_id == 0x1f)
++			/* Do sector unprotect. */
++			if (ha->fdt_unprotect_sec_cmd)
+ 				qla24xx_write_flash_dword(ha,
+-				    flash_conf_to_access_addr(0x0339),
++				    ha->fdt_unprotect_sec_cmd,
+ 				    (fdata & 0xff00) | ((fdata << 16) &
+ 				    0xff0000) | ((fdata >> 16) & 0xff));
+-			ret = qla24xx_write_flash_dword(ha, conf_addr,
++			ret = qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
+ 			    (fdata & 0xff00) |((fdata << 16) &
+ 			    0xff0000) | ((fdata >> 16) & 0xff));
+ 			if (ret != QLA_SUCCESS) {
+@@ -681,28 +776,16 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
+ 			break;
+ 		}
+ 
+-		/* Do sector protect at 4K boundry for Atmel part. */
+-		if (man_id == 0x1f &&
++		/* Do sector protect. */
++		if (ha->fdt_unprotect_sec_cmd &&
+ 		    ((faddr & rest_addr) == rest_addr))
+ 			qla24xx_write_flash_dword(ha,
+-			    flash_conf_to_access_addr(0x0336),
++			    ha->fdt_protect_sec_cmd,
+ 			    (fdata & 0xff00) | ((fdata << 16) &
+ 			    0xff0000) | ((fdata >> 16) & 0xff));
+ 	}
+ 
+-	/* Enable flash write-protection and wait for completion. */
+-	qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
+-	for (cnt = 300; cnt &&
+-	    qla24xx_read_flash_dword(ha,
+-		    flash_conf_to_access_addr(0x005)) & BIT_0;
+-	    cnt--) {
+-		udelay(10);
+-	}
+-
+-	/* Disable flash write. */
+-	WRT_REG_DWORD(&reg->ctrl_status,
+-	    RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
+-	RD_REG_DWORD(&reg->ctrl_status);	/* PCI Posting. */
++	qla24xx_protect_flash(ha);
+ 
+ 	if (optrom)
+ 		dma_free_coherent(&ha->pdev->dev,
+@@ -2221,3 +2304,107 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
+ 
+ 	return ret;
+ }
++
++static int
++qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
++{
++	uint32_t d[2], faddr;
++
++	/* Locate first empty entry. */
++	for (;;) {
++		if (ha->hw_event_ptr >=
++		    ha->hw_event_start + FA_HW_EVENT_SIZE) {
++			DEBUG2(qla_printk(KERN_WARNING, ha,
++			    "HW event -- Log Full!\n"));
++			return QLA_MEMORY_ALLOC_FAILED;
++		}
++
++		qla24xx_read_flash_data(ha, d, ha->hw_event_ptr, 2);
++		faddr = flash_data_to_access_addr(ha->hw_event_ptr);
++		ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
++		if (d[0] == __constant_cpu_to_le32(0xffffffff) &&
++		    d[1] == __constant_cpu_to_le32(0xffffffff)) {
++			qla24xx_unprotect_flash(ha);
++
++			qla24xx_write_flash_dword(ha, faddr++,
++			    cpu_to_le32(jiffies));
++			qla24xx_write_flash_dword(ha, faddr++, 0);
++			qla24xx_write_flash_dword(ha, faddr++, *fdata++);
++			qla24xx_write_flash_dword(ha, faddr++, *fdata);
++
++			qla24xx_protect_flash(ha);
++			break;
++		}
++	}
++	return QLA_SUCCESS;
++}
++
++int
++qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1,
++    uint16_t d2, uint16_t d3)
++{
++#define QMARK(a, b, c, d) \
++    cpu_to_le32(LSB(a) << 24 | LSB(b) << 16 | LSB(c) << 8 | LSB(d))
++
++	int rval;
++	uint32_t marker[2], fdata[4];
++
++	if (ha->hw_event_start == 0)
++		return QLA_FUNCTION_FAILED;
++
++	DEBUG2(qla_printk(KERN_WARNING, ha,
++	    "HW event -- code=%x, d1=%x, d2=%x, d3=%x.\n", code, d1, d2, d3));
++
++	/* If marker not already found, locate or write.  */
++	if (!ha->flags.hw_event_marker_found) {
++		/* Create marker. */
++		marker[0] = QMARK('L', ha->fw_major_version,
++		    ha->fw_minor_version, ha->fw_subminor_version);
++		marker[1] = QMARK(QLA_DRIVER_MAJOR_VER, QLA_DRIVER_MINOR_VER,
++		    QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER);
++
++		/* Locate marker. */
++		ha->hw_event_ptr = ha->hw_event_start;
++		for (;;) {
++			qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr,
++			    4);
++			if (fdata[0] == __constant_cpu_to_le32(0xffffffff) &&
++			    fdata[1] == __constant_cpu_to_le32(0xffffffff))
++				break;
++			ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
++			if (ha->hw_event_ptr >=
++			    ha->hw_event_start + FA_HW_EVENT_SIZE) {
++				DEBUG2(qla_printk(KERN_WARNING, ha,
++				    "HW event -- Log Full!\n"));
++				return QLA_MEMORY_ALLOC_FAILED;
++			}
++			if (fdata[2] == marker[0] && fdata[3] == marker[1]) {
++				ha->flags.hw_event_marker_found = 1;
++				break;
++			}
++		}
++		/* No marker, write it. */
++		if (!ha->flags.hw_event_marker_found) {
++			rval = qla2xxx_hw_event_store(ha, marker);
++			if (rval != QLA_SUCCESS) {
++				DEBUG2(qla_printk(KERN_WARNING, ha,
++				    "HW event -- Failed marker write=%x.!\n",
++				    rval));
++				return rval;
++			}
++			ha->flags.hw_event_marker_found = 1;
++		}
++	}
++
++	/* Store error.  */
++	fdata[0] = cpu_to_le32(code << 16 | d1);
++	fdata[1] = cpu_to_le32(d2 << 16 | d3);
++	rval = qla2xxx_hw_event_store(ha, fdata);
++	if (rval != QLA_SUCCESS) {
++		DEBUG2(qla_printk(KERN_WARNING, ha,
++		    "HW event -- Failed error write=%x.!\n",
++		    rval));
++	}
++
++	return rval;
++}
+diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
+index ea08a12..f42f17a 100644
+--- a/drivers/scsi/qla2xxx/qla_version.h
++++ b/drivers/scsi/qla2xxx/qla_version.h
+@@ -1,15 +1,15 @@
+ /*
+  * QLogic Fibre Channel HBA Driver
+- * Copyright (c)  2003-2005 QLogic Corporation
++ * Copyright (c)  2003-2008 QLogic Corporation
+  *
+  * See LICENSE.qla2xxx for copyright and licensing details.
+  */
+ /*
+  * Driver version
+  */
+-#define QLA2XXX_VERSION      "8.02.00-k9"
++#define QLA2XXX_VERSION      "8.02.01-k1"
+ 
+ #define QLA_DRIVER_MAJOR_VER	8
+ #define QLA_DRIVER_MINOR_VER	2
+-#define QLA_DRIVER_PATCH_VER	0
++#define QLA_DRIVER_PATCH_VER	1
+ #define QLA_DRIVER_BETA_VER	0
+diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
+index fe415ec..1b667a7 100644
+--- a/drivers/scsi/qla4xxx/ql4_fw.h
++++ b/drivers/scsi/qla4xxx/ql4_fw.h
+@@ -216,6 +216,7 @@ union external_hw_config_reg {
+ #define MBOX_CMD_ABOUT_FW			0x0009
+ #define MBOX_CMD_PING				0x000B
+ #define MBOX_CMD_LUN_RESET			0x0016
++#define MBOX_CMD_TARGET_WARM_RESET		0x0017
+ #define MBOX_CMD_GET_MANAGEMENT_DATA		0x001E
+ #define MBOX_CMD_GET_FW_STATUS			0x001F
+ #define MBOX_CMD_SET_ISNS_SERVICE		0x0021
+@@ -677,7 +678,8 @@ struct qla4_marker_entry {
+ 	uint32_t system_defined; /* 04-07 */
+ 	uint16_t target;	/* 08-09 */
+ 	uint16_t modifier;	/* 0A-0B */
+-#define MM_LUN_RESET	     0
++#define MM_LUN_RESET		0
++#define MM_TGT_WARM_RESET	1
+ 
+ 	uint16_t flags;		/* 0C-0D */
+ 	uint16_t reserved1;	/* 0E-0F */
+diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
+index a3608e0..96ebfb0 100644
+--- a/drivers/scsi/qla4xxx/ql4_glbl.h
++++ b/drivers/scsi/qla4xxx/ql4_glbl.h
+@@ -27,6 +27,8 @@ int qla4xxx_relogin_device(struct scsi_qla_host * ha,
+ 			   struct ddb_entry * ddb_entry);
+ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
+ 		      int lun);
++int qla4xxx_reset_target(struct scsi_qla_host * ha,
++			 struct ddb_entry * ddb_entry);
+ int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
+ 		      uint32_t offset, uint32_t len);
+ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
+@@ -68,6 +70,8 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
+ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
+ 				uint32_t fw_ddb_index, uint32_t state);
+ void qla4xxx_dump_buffer(void *b, uint32_t size);
++int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
++	struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
+ 
+ extern int ql4xextended_error_logging;
+ extern int ql4xdiscoverywait;
+diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
+index e4461b5..912a674 100644
+--- a/drivers/scsi/qla4xxx/ql4_iocb.c
++++ b/drivers/scsi/qla4xxx/ql4_iocb.c
+@@ -66,8 +66,8 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
+  *
+  * This routine issues a marker IOCB.
+  **/
+-static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
+-				    struct ddb_entry *ddb_entry, int lun)
++int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
++	struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod)
+ {
+ 	struct qla4_marker_entry *marker_entry;
+ 	unsigned long flags = 0;
+@@ -87,7 +87,7 @@ static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
+ 	marker_entry->hdr.entryType = ET_MARKER;
+ 	marker_entry->hdr.entryCount = 1;
+ 	marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
+-	marker_entry->modifier = cpu_to_le16(MM_LUN_RESET);
++	marker_entry->modifier = cpu_to_le16(mrkr_mod);
+ 	int_to_scsilun(lun, &marker_entry->lun);
+ 	wmb();
+ 
+@@ -210,14 +210,6 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
+ 	/* Get real lun and adapter */
+ 	ddb_entry = srb->ddb;
+ 
+-	/* Send marker(s) if needed. */
+-	if (ha->marker_needed == 1) {
+-		if (qla4xxx_send_marker_iocb(ha, ddb_entry,
+-					     cmd->device->lun) != QLA_SUCCESS)
+-			return QLA_ERROR;
+-
+-		ha->marker_needed = 0;
+-	}
+ 	tot_dsds = 0;
+ 
+ 	/* Acquire hardware specific lock */
+diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
+index fc84db4..a91a57c 100644
+--- a/drivers/scsi/qla4xxx/ql4_isr.c
++++ b/drivers/scsi/qla4xxx/ql4_isr.c
+@@ -11,28 +11,6 @@
+ #include "ql4_inline.h"
+ 
+ /**
+- * qla2x00_process_completed_request() - Process a Fast Post response.
+- * @ha: SCSI driver HA context
+- * @index: SRB index
+- **/
+-static void qla4xxx_process_completed_request(struct scsi_qla_host *ha,
+-					      uint32_t index)
+-{
+-	struct srb *srb;
+-
+-	srb = qla4xxx_del_from_active_array(ha, index);
+-	if (srb) {
+-		/* Save ISP completion status */
+-		srb->cmd->result = DID_OK << 16;
+-		qla4xxx_srb_compl(ha, srb);
+-	} else {
+-		DEBUG2(printk("scsi%ld: Invalid ISP SCSI completion handle = "
+-			      "%d\n", ha->host_no, index));
+-		set_bit(DPC_RESET_HA, &ha->dpc_flags);
+-	}
+-}
+-
+-/**
+  * qla4xxx_status_entry - processes status IOCBs
+  * @ha: Pointer to host adapter structure.
+  * @sts_entry: Pointer to status entry structure.
+@@ -47,14 +25,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ 	uint32_t residual;
+ 	uint16_t sensebytecnt;
+ 
+-	if (sts_entry->completionStatus == SCS_COMPLETE &&
+-	    sts_entry->scsiStatus == 0) {
+-		qla4xxx_process_completed_request(ha,
+-						  le32_to_cpu(sts_entry->
+-							      handle));
+-		return;
+-	}
+-
+ 	srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
+ 	if (!srb) {
+ 		/* FIXMEdg: Don't we need to reset ISP in this case??? */
+@@ -62,6 +32,9 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ 			      "handle 0x%x, sp=%p. This cmd may have already "
+ 			      "been completed.\n", ha->host_no, __func__,
+ 			      le32_to_cpu(sts_entry->handle), srb));
++		dev_warn(&ha->pdev->dev, "%s invalid status entry:"
++			" handle=0x%0x\n", __func__, sts_entry->handle);
++		set_bit(DPC_RESET_HA, &ha->dpc_flags);
+ 		return;
+ 	}
+ 
+@@ -88,10 +61,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ 	scsi_status = sts_entry->scsiStatus;
+ 	switch (sts_entry->completionStatus) {
+ 	case SCS_COMPLETE:
+-		if (scsi_status == 0) {
+-			cmd->result = DID_OK << 16;
+-			break;
+-		}
+ 
+ 		if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
+ 			cmd->result = DID_ERROR << 16;
+@@ -100,7 +69,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ 
+ 		if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) {
+ 			scsi_set_resid(cmd, residual);
+-			if ((scsi_bufflen(cmd) - residual) < cmd->underflow) {
++			if (!scsi_status && ((scsi_bufflen(cmd) - residual) <
++				cmd->underflow)) {
+ 
+ 				cmd->result = DID_ERROR << 16;
+ 
+diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
+index 35cd73c..c577d79 100644
+--- a/drivers/scsi/qla4xxx/ql4_mbx.c
++++ b/drivers/scsi/qla4xxx/ql4_mbx.c
+@@ -713,6 +713,45 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
+ 	return status;
+ }
+ 
++/**
++ * qla4xxx_reset_target - issues target Reset
++ * @ha: Pointer to host adapter structure.
++ * @db_entry: Pointer to device database entry
++ * @un_entry: Pointer to lun entry structure
++ *
++ * This routine performs a TARGET RESET on the specified target.
++ * The caller must ensure that the ddb_entry pointers
++ * are valid before calling this routine.
++ **/
++int qla4xxx_reset_target(struct scsi_qla_host *ha,
++			 struct ddb_entry *ddb_entry)
++{
++	uint32_t mbox_cmd[MBOX_REG_COUNT];
++	uint32_t mbox_sts[MBOX_REG_COUNT];
++	int status = QLA_SUCCESS;
++
++	DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
++		      ddb_entry->os_target_id));
++
++	/*
++	 * Send target reset command to ISP, so that the ISP will return all
++	 * outstanding requests with RESET status
++	 */
++	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++	memset(&mbox_sts, 0, sizeof(mbox_sts));
++
++	mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
++	mbox_cmd[1] = ddb_entry->fw_ddb_index;
++	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
++
++	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
++				&mbox_sts[0]);
++	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
++	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
++		status = QLA_ERROR;
++
++	return status;
++}
+ 
+ int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
+ 		      uint32_t offset, uint32_t len)
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 8b92f34..0c78694 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -71,6 +71,7 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
+ 				void (*done) (struct scsi_cmnd *));
+ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
++static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
+ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
+ static int qla4xxx_slave_alloc(struct scsi_device *device);
+ static int qla4xxx_slave_configure(struct scsi_device *device);
+@@ -84,6 +85,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
+ 	.queuecommand		= qla4xxx_queuecommand,
+ 
+ 	.eh_device_reset_handler = qla4xxx_eh_device_reset,
++	.eh_target_reset_handler = qla4xxx_eh_target_reset,
+ 	.eh_host_reset_handler	= qla4xxx_eh_host_reset,
+ 
+ 	.slave_configure	= qla4xxx_slave_configure,
+@@ -1482,7 +1484,7 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
+ }
+ 
+ /**
+- * qla4xxx_eh_wait_for_active_target_commands - wait for active cmds to finish.
++ * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
+  * @ha: pointer to to HBA
+  * @t: target id
+  * @l: lun id
+@@ -1490,20 +1492,22 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
+  * This function waits for all outstanding commands to a lun to complete. It
+  * returns 0 if all pending commands are returned and 1 otherwise.
+  **/
+-static int qla4xxx_eh_wait_for_active_target_commands(struct scsi_qla_host *ha,
+-						 int t, int l)
++static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
++					struct scsi_target *stgt,
++					struct scsi_device *sdev)
+ {
+ 	int cnt;
+ 	int status = 0;
+ 	struct scsi_cmnd *cmd;
+ 
+ 	/*
+-	 * Waiting for all commands for the designated target in the active
+-	 * array
++	 * Waiting for all commands for the designated target or dev
++	 * in the active array
+ 	 */
+ 	for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
+ 		cmd = scsi_host_find_tag(ha->host, cnt);
+-		if (cmd && cmd->device->id == t && cmd->device->lun == l) {
++		if (cmd && stgt == scsi_target(cmd->device) &&
++		    (!sdev || sdev == cmd->device)) {
+ 			if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
+ 				status++;
+ 				break;
+@@ -1548,24 +1552,19 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
+ 		goto eh_dev_reset_done;
+ 	}
+ 
+-	/* Send marker. */
+-	ha->marker_needed = 1;
+-
+-	/*
+-	 * If we are coming down the EH path, wait for all commands to complete
+-	 * for the device.
+-	 */
+-	if (cmd->device->host->shost_state == SHOST_RECOVERY) {
+-		if (qla4xxx_eh_wait_for_active_target_commands(ha,
+-							  cmd->device->id,
+-							  cmd->device->lun)){
+-			dev_info(&ha->pdev->dev,
+-				   "DEVICE RESET FAILED - waiting for "
+-				   "commands.\n");
+-			goto eh_dev_reset_done;
+-		}
++	if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
++					 cmd->device)) {
++		dev_info(&ha->pdev->dev,
++			   "DEVICE RESET FAILED - waiting for "
++			   "commands.\n");
++		goto eh_dev_reset_done;
+ 	}
+ 
++	/* Send marker. */
++	if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
++		MM_LUN_RESET) != QLA_SUCCESS)
++		goto eh_dev_reset_done;
++
+ 	dev_info(&ha->pdev->dev,
+ 		   "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
+ 		   ha->host_no, cmd->device->channel, cmd->device->id,
+@@ -1579,6 +1578,59 @@ eh_dev_reset_done:
+ }
+ 
+ /**
++ * qla4xxx_eh_target_reset - callback for target reset.
++ * @cmd: Pointer to Linux's SCSI command structure
++ *
++ * This routine is called by the Linux OS to reset the target.
++ **/
++static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
++{
++	struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
++	struct ddb_entry *ddb_entry = cmd->device->hostdata;
++	int stat;
++
++	if (!ddb_entry)
++		return FAILED;
++
++	starget_printk(KERN_INFO, scsi_target(cmd->device),
++		       "WARM TARGET RESET ISSUED.\n");
++
++	DEBUG2(printk(KERN_INFO
++		      "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
++		      "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
++		      ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ,
++		      ha->dpc_flags, cmd->result, cmd->allowed));
++
++	stat = qla4xxx_reset_target(ha, ddb_entry);
++	if (stat != QLA_SUCCESS) {
++		starget_printk(KERN_INFO, scsi_target(cmd->device),
++			       "WARM TARGET RESET FAILED.\n");
++		return FAILED;
++	}
++
++	if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
++					 NULL)) {
++		starget_printk(KERN_INFO, scsi_target(cmd->device),
++			       "WARM TARGET DEVICE RESET FAILED - "
++			       "waiting for commands.\n");
++		return FAILED;
++	}
++
++	/* Send marker. */
++	if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
++		MM_TGT_WARM_RESET) != QLA_SUCCESS) {
++		starget_printk(KERN_INFO, scsi_target(cmd->device),
++			       "WARM TARGET DEVICE RESET FAILED - "
++			       "marker iocb failed.\n");
++		return FAILED;
++	}
++
++	starget_printk(KERN_INFO, scsi_target(cmd->device),
++		       "WARM TARGET RESET SUCCEEDED.\n");
++	return SUCCESS;
++}
++
++/**
+  * qla4xxx_eh_host_reset - kernel callback
+  * @cmd: Pointer to Linux's SCSI command structure
+  *
+diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
+index 86e1318..913a931 100644
+--- a/drivers/scsi/raid_class.c
++++ b/drivers/scsi/raid_class.c
+@@ -24,15 +24,15 @@ struct raid_internal {
+ 	struct raid_template r;
+ 	struct raid_function_template *f;
+ 	/* The actual attributes */
+-	struct class_device_attribute private_attrs[RAID_NUM_ATTRS];
++	struct device_attribute private_attrs[RAID_NUM_ATTRS];
+ 	/* The array of null terminated pointers to attributes 
+ 	 * needed by scsi_sysfs.c */
+-	struct class_device_attribute *attrs[RAID_NUM_ATTRS + 1];
++	struct device_attribute *attrs[RAID_NUM_ATTRS + 1];
+ };
+ 
+ struct raid_component {
+ 	struct list_head node;
+-	struct class_device cdev;
++	struct device dev;
+ 	int num;
+ };
+ 
+@@ -50,9 +50,9 @@ struct raid_component {
+ 	tc_to_raid_internal(tc);					\
+ })
+ 
+-#define class_device_to_raid_internal(cdev) ({				\
++#define device_to_raid_internal(dev) ({				\
+ 	struct attribute_container *ac =				\
+-		attribute_container_classdev_to_container(cdev);	\
++		attribute_container_classdev_to_container(dev);	\
+ 	ac_to_raid_internal(ac);					\
+ })
+ 	
+@@ -76,33 +76,33 @@ static int raid_match(struct attribute_container *cont, struct device *dev)
+ }
+ 
+ static int raid_setup(struct transport_container *tc, struct device *dev,
+-		       struct class_device *cdev)
++		       struct device *cdev)
+ {
+ 	struct raid_data *rd;
+ 
+-	BUG_ON(class_get_devdata(cdev));
++	BUG_ON(dev_get_drvdata(cdev));
+ 
+ 	rd = kzalloc(sizeof(*rd), GFP_KERNEL);
+ 	if (!rd)
+ 		return -ENOMEM;
+ 
+ 	INIT_LIST_HEAD(&rd->component_list);
+-	class_set_devdata(cdev, rd);
++	dev_set_drvdata(cdev, rd);
+ 		
+ 	return 0;
+ }
+ 
+ static int raid_remove(struct transport_container *tc, struct device *dev,
+-		       struct class_device *cdev)
++		       struct device *cdev)
+ {
+-	struct raid_data *rd = class_get_devdata(cdev);
++	struct raid_data *rd = dev_get_drvdata(cdev);
+ 	struct raid_component *rc, *next;
+ 	dev_printk(KERN_ERR, dev, "RAID REMOVE\n");
+-	class_set_devdata(cdev, NULL);
++	dev_set_drvdata(cdev, NULL);
+ 	list_for_each_entry_safe(rc, next, &rd->component_list, node) {
+ 		list_del(&rc->node);
+-		dev_printk(KERN_ERR, rc->cdev.dev, "RAID COMPONENT REMOVE\n");
+-		class_device_unregister(&rc->cdev);
++		dev_printk(KERN_ERR, rc->dev.parent, "RAID COMPONENT REMOVE\n");
++		device_unregister(&rc->dev);
+ 	}
+ 	dev_printk(KERN_ERR, dev, "RAID REMOVE DONE\n");
+ 	kfree(rd);
+@@ -171,9 +171,11 @@ static const char *raid_level_name(enum raid_level level)
+ }
+ 
+ #define raid_attr_show_internal(attr, fmt, var, code)			\
+-static ssize_t raid_show_##attr(struct class_device *cdev, char *buf)	\
++static ssize_t raid_show_##attr(struct device *dev, 			\
++				struct device_attribute *attr, 		\
++				char *buf)				\
+ {									\
+-	struct raid_data *rd = class_get_devdata(cdev);			\
++	struct raid_data *rd = dev_get_drvdata(dev);			\
+ 	code								\
+ 	return snprintf(buf, 20, #fmt "\n", var);			\
+ }
+@@ -184,17 +186,17 @@ raid_attr_show_internal(attr, %s, name,					\
+ 	code								\
+ 	name = raid_##states##_name(rd->attr);				\
+ )									\
+-static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
++static DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+ 
+ 
+ #define raid_attr_ro_internal(attr, code)				\
+ raid_attr_show_internal(attr, %d, rd->attr, code)			\
+-static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
++static DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+ 
+ #define ATTR_CODE(attr)							\
+-	struct raid_internal *i = class_device_to_raid_internal(cdev);	\
++	struct raid_internal *i = device_to_raid_internal(dev);		\
+ 	if (i->f->get_##attr)						\
+-		i->f->get_##attr(cdev->dev);
++		i->f->get_##attr(dev->parent);
+ 
+ #define raid_attr_ro(attr)	raid_attr_ro_internal(attr, )
+ #define raid_attr_ro_fn(attr)	raid_attr_ro_internal(attr, ATTR_CODE(attr))
+@@ -206,23 +208,23 @@ raid_attr_ro_state(level);
+ raid_attr_ro_fn(resync);
+ raid_attr_ro_state_fn(state);
+ 
+-static void raid_component_release(struct class_device *cdev)
++static void raid_component_release(struct device *dev)
+ {
+-	struct raid_component *rc = container_of(cdev, struct raid_component,
+-						 cdev);
+-	dev_printk(KERN_ERR, rc->cdev.dev, "COMPONENT RELEASE\n");
+-	put_device(rc->cdev.dev);
++	struct raid_component *rc =
++		container_of(dev, struct raid_component, dev);
++	dev_printk(KERN_ERR, rc->dev.parent, "COMPONENT RELEASE\n");
++	put_device(rc->dev.parent);
+ 	kfree(rc);
+ }
+ 
+ int raid_component_add(struct raid_template *r,struct device *raid_dev,
+ 		       struct device *component_dev)
+ {
+-	struct class_device *cdev =
++	struct device *cdev =
+ 		attribute_container_find_class_device(&r->raid_attrs.ac,
+ 						      raid_dev);
+ 	struct raid_component *rc;
+-	struct raid_data *rd = class_get_devdata(cdev);
++	struct raid_data *rd = dev_get_drvdata(cdev);
+ 	int err;
+ 
+ 	rc = kzalloc(sizeof(*rc), GFP_KERNEL);
+@@ -230,17 +232,16 @@ int raid_component_add(struct raid_template *r,struct device *raid_dev,
+ 		return -ENOMEM;
+ 
+ 	INIT_LIST_HEAD(&rc->node);
+-	class_device_initialize(&rc->cdev);
+-	rc->cdev.release = raid_component_release;
+-	rc->cdev.dev = get_device(component_dev);
++	device_initialize(&rc->dev);
++	rc->dev.release = raid_component_release;
++	rc->dev.parent = get_device(component_dev);
+ 	rc->num = rd->component_count++;
+ 
+-	snprintf(rc->cdev.class_id, sizeof(rc->cdev.class_id),
++	snprintf(rc->dev.bus_id, sizeof(rc->dev.bus_id),
+ 		 "component-%d", rc->num);
+ 	list_add_tail(&rc->node, &rd->component_list);
+-	rc->cdev.parent = cdev;
+-	rc->cdev.class = &raid_class.class;
+-	err = class_device_add(&rc->cdev);
++	rc->dev.class = &raid_class.class;
++	err = device_add(&rc->dev);
+ 	if (err)
+ 		goto err_out;
+ 
+@@ -273,9 +274,9 @@ raid_class_attach(struct raid_function_template *ft)
+ 
+ 	attribute_container_register(&i->r.raid_attrs.ac);
+ 
+-	i->attrs[count++] = &class_device_attr_level;
+-	i->attrs[count++] = &class_device_attr_resync;
+-	i->attrs[count++] = &class_device_attr_state;
++	i->attrs[count++] = &dev_attr_level;
++	i->attrs[count++] = &dev_attr_resync;
++	i->attrs[count++] = &dev_attr_state;
+ 
+ 	i->attrs[count] = NULL;
+ 	BUG_ON(count > RAID_NUM_ATTRS);
+@@ -289,7 +290,7 @@ raid_class_release(struct raid_template *r)
+ {
+ 	struct raid_internal *i = to_raid_internal(r);
+ 
+-	attribute_container_unregister(&i->r.raid_attrs.ac);
++	BUG_ON(attribute_container_unregister(&i->r.raid_attrs.ac));
+ 
+ 	kfree(i);
+ }
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+index c78b836..12d69d7 100644
+--- a/drivers/scsi/scsi.c
++++ b/drivers/scsi/scsi.c
+@@ -166,6 +166,51 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
+ static DEFINE_MUTEX(host_cmd_pool_mutex);
+ 
+ /**
++ * scsi_pool_alloc_command - internal function to get a fully allocated command
++ * @pool:	slab pool to allocate the command from
++ * @gfp_mask:	mask for the allocation
++ *
++ * Returns a fully allocated command (with the allied sense buffer) or
++ * NULL on failure
++ */
++static struct scsi_cmnd *
++scsi_pool_alloc_command(struct scsi_host_cmd_pool *pool, gfp_t gfp_mask)
++{
++	struct scsi_cmnd *cmd;
++
++	cmd = kmem_cache_alloc(pool->cmd_slab, gfp_mask | pool->gfp_mask);
++	if (!cmd)
++		return NULL;
++
++	memset(cmd, 0, sizeof(*cmd));
++
++	cmd->sense_buffer = kmem_cache_alloc(pool->sense_slab,
++					     gfp_mask | pool->gfp_mask);
++	if (!cmd->sense_buffer) {
++		kmem_cache_free(pool->cmd_slab, cmd);
++		return NULL;
++	}
++
++	return cmd;
++}
++
++/**
++ * scsi_pool_free_command - internal function to release a command
++ * @pool:	slab pool to allocate the command from
++ * @cmd:	command to release
++ *
++ * the command must previously have been allocated by
++ * scsi_pool_alloc_command.
++ */
++static void
++scsi_pool_free_command(struct scsi_host_cmd_pool *pool,
++			 struct scsi_cmnd *cmd)
++{
++	kmem_cache_free(pool->sense_slab, cmd->sense_buffer);
++	kmem_cache_free(pool->cmd_slab, cmd);
++}
++
++/**
+  * __scsi_get_command - Allocate a struct scsi_cmnd
+  * @shost: host to transmit command
+  * @gfp_mask: allocation mask
+@@ -178,20 +223,7 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
+ 	struct scsi_cmnd *cmd;
+ 	unsigned char *buf;
+ 
+-	cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
+-			       gfp_mask | shost->cmd_pool->gfp_mask);
+-
+-	if (likely(cmd)) {
+-		buf = kmem_cache_alloc(shost->cmd_pool->sense_slab,
+-				       gfp_mask | shost->cmd_pool->gfp_mask);
+-		if (likely(buf)) {
+-			memset(cmd, 0, sizeof(*cmd));
+-			cmd->sense_buffer = buf;
+-		} else {
+-			kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+-			cmd = NULL;
+-		}
+-	}
++	cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
+ 
+ 	if (unlikely(!cmd)) {
+ 		unsigned long flags;
+@@ -268,11 +300,8 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd,
+ 	}
+ 	spin_unlock_irqrestore(&shost->free_list_lock, flags);
+ 
+-	if (likely(cmd != NULL)) {
+-		kmem_cache_free(shost->cmd_pool->sense_slab,
+-				cmd->sense_buffer);
+-		kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+-	}
++	if (likely(cmd != NULL))
++		scsi_pool_free_command(shost->cmd_pool, cmd);
+ 
+ 	put_device(dev);
+ }
+@@ -301,30 +330,16 @@ void scsi_put_command(struct scsi_cmnd *cmd)
+ }
+ EXPORT_SYMBOL(scsi_put_command);
+ 
+-/**
+- * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
+- * @shost: host to allocate the freelist for.
+- *
+- * Description: The command freelist protects against system-wide out of memory
+- * deadlock by preallocating one SCSI command structure for each host, so the
+- * system can always write to a swap file on a device associated with that host.
+- *
+- * Returns:	Nothing.
+- */
+-int scsi_setup_command_freelist(struct Scsi_Host *shost)
++static struct scsi_host_cmd_pool *scsi_get_host_cmd_pool(gfp_t gfp_mask)
+ {
+-	struct scsi_host_cmd_pool *pool;
+-	struct scsi_cmnd *cmd;
+-
+-	spin_lock_init(&shost->free_list_lock);
+-	INIT_LIST_HEAD(&shost->free_list);
+-
++	struct scsi_host_cmd_pool *retval = NULL, *pool;
+ 	/*
+ 	 * Select a command slab for this host and create it if not
+ 	 * yet existent.
+ 	 */
+ 	mutex_lock(&host_cmd_pool_mutex);
+-	pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
++	pool = (gfp_mask & __GFP_DMA) ? &scsi_cmd_dma_pool :
++		&scsi_cmd_pool;
+ 	if (!pool->users) {
+ 		pool->cmd_slab = kmem_cache_create(pool->cmd_name,
+ 						   sizeof(struct scsi_cmnd), 0,
+@@ -342,37 +357,122 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
+ 	}
+ 
+ 	pool->users++;
+-	shost->cmd_pool = pool;
++	retval = pool;
++ fail:
+ 	mutex_unlock(&host_cmd_pool_mutex);
++	return retval;
++}
++
++static void scsi_put_host_cmd_pool(gfp_t gfp_mask)
++{
++	struct scsi_host_cmd_pool *pool;
+ 
++	mutex_lock(&host_cmd_pool_mutex);
++	pool = (gfp_mask & __GFP_DMA) ? &scsi_cmd_dma_pool :
++		&scsi_cmd_pool;
+ 	/*
+-	 * Get one backup command for this host.
++	 * This may happen if a driver has a mismatched get and put
++	 * of the command pool; the driver should be implicated in
++	 * the stack trace
+ 	 */
+-	cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
+-			       GFP_KERNEL | shost->cmd_pool->gfp_mask);
+-	if (!cmd)
+-		goto fail2;
++	BUG_ON(pool->users == 0);
+ 
+-	cmd->sense_buffer = kmem_cache_alloc(shost->cmd_pool->sense_slab,
+-					     GFP_KERNEL |
+-					     shost->cmd_pool->gfp_mask);
+-	if (!cmd->sense_buffer)
+-		goto fail2;
+-
+-	list_add(&cmd->list, &shost->free_list);
+-	return 0;
+-
+- fail2:
+-	if (cmd)
+-		kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+-	mutex_lock(&host_cmd_pool_mutex);
+ 	if (!--pool->users) {
+ 		kmem_cache_destroy(pool->cmd_slab);
+ 		kmem_cache_destroy(pool->sense_slab);
+ 	}
+- fail:
+ 	mutex_unlock(&host_cmd_pool_mutex);
+-	return -ENOMEM;
++}
++
++/**
++ * scsi_allocate_command - get a fully allocated SCSI command
++ * @gfp_mask:	allocation mask
++ *
++ * This function is for use outside of the normal host based pools.
++ * It allocates the relevant command and takes an additional reference
++ * on the pool it used.  This function *must* be paired with
++ * scsi_free_command which also has the identical mask, otherwise the
++ * free pool counts will eventually go wrong and you'll trigger a bug.
++ *
++ * This function should *only* be used by drivers that need a static
++ * command allocation at start of day for internal functions.
++ */
++struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask)
++{
++	struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
++
++	if (!pool)
++		return NULL;
++
++	return scsi_pool_alloc_command(pool, gfp_mask);
++}
++EXPORT_SYMBOL(scsi_allocate_command);
++
++/**
++ * scsi_free_command - free a command allocated by scsi_allocate_command
++ * @gfp_mask:	mask used in the original allocation
++ * @cmd:	command to free
++ *
++ * Note: using the original allocation mask is vital because that's
++ * what determines which command pool we use to free the command.  Any
++ * mismatch will cause the system to BUG eventually.
++ */
++void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd)
++{
++	struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
++
++	/*
++	 * this could trigger if the mask to scsi_allocate_command
++	 * doesn't match this mask.  Otherwise we're guaranteed that this
++	 * succeeds because scsi_allocate_command must have taken a reference
++	 * on the pool
++	 */
++	BUG_ON(!pool);
++
++	scsi_pool_free_command(pool, cmd);
++	/*
++	 * scsi_put_host_cmd_pool is called twice; once to release the
++	 * reference we took above, and once to release the reference
++	 * originally taken by scsi_allocate_command
++	 */
++	scsi_put_host_cmd_pool(gfp_mask);
++	scsi_put_host_cmd_pool(gfp_mask);
++}
++EXPORT_SYMBOL(scsi_free_command);
++
++/**
++ * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
++ * @shost: host to allocate the freelist for.
++ *
++ * Description: The command freelist protects against system-wide out of memory
++ * deadlock by preallocating one SCSI command structure for each host, so the
++ * system can always write to a swap file on a device associated with that host.
++ *
++ * Returns:	Nothing.
++ */
++int scsi_setup_command_freelist(struct Scsi_Host *shost)
++{
++	struct scsi_cmnd *cmd;
++	const gfp_t gfp_mask = shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL;
++
++	spin_lock_init(&shost->free_list_lock);
++	INIT_LIST_HEAD(&shost->free_list);
++
++	shost->cmd_pool = scsi_get_host_cmd_pool(gfp_mask);
++
++	if (!shost->cmd_pool)
++		return -ENOMEM;
++
++	/*
++	 * Get one backup command for this host.
++	 */
++	cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
++	if (!cmd) {
++		scsi_put_host_cmd_pool(gfp_mask);
++		return -ENOMEM;
++	}
++	list_add(&cmd->list, &shost->free_list);
++	return 0;
+ }
+ 
+ /**
+@@ -386,17 +486,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
+ 
+ 		cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list);
+ 		list_del_init(&cmd->list);
+-		kmem_cache_free(shost->cmd_pool->sense_slab,
+-				cmd->sense_buffer);
+-		kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
++		scsi_pool_free_command(shost->cmd_pool, cmd);
+ 	}
+-
+-	mutex_lock(&host_cmd_pool_mutex);
+-	if (!--shost->cmd_pool->users) {
+-		kmem_cache_destroy(shost->cmd_pool->cmd_slab);
+-		kmem_cache_destroy(shost->cmd_pool->sense_slab);
+-	}
+-	mutex_unlock(&host_cmd_pool_mutex);
++	shost->cmd_pool = NULL;
++	scsi_put_host_cmd_pool(shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL);
+ }
+ 
+ #ifdef CONFIG_SCSI_LOGGING
+@@ -759,7 +852,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
+ 				"Notifying upper driver of completion "
+ 				"(result %x)\n", cmd->result));
+ 
+-	good_bytes = scsi_bufflen(cmd) + cmd->request->extra_len;
++	good_bytes = scsi_bufflen(cmd);
+         if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
+ 		drv = scsi_cmd_to_driver(cmd);
+ 		if (drv->done)
+diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
+index d1777a9..07103c3 100644
+--- a/drivers/scsi/scsi_debug.c
++++ b/drivers/scsi/scsi_debug.c
+@@ -39,16 +39,18 @@
+ #include <linux/vmalloc.h>
+ #include <linux/moduleparam.h>
+ #include <linux/scatterlist.h>
+-
+ #include <linux/blkdev.h>
+-#include "scsi.h"
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_device.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsicam.h>
++#include <scsi/scsi_eh.h>
+ 
+ #include <linux/stat.h>
+ 
+ #include "scsi_logging.h"
+-#include "scsi_debug.h"
+ 
+ #define SCSI_DEBUG_VERSION "1.81"
+ static const char * scsi_debug_version_date = "20070104";
+@@ -146,7 +148,6 @@ static int scsi_debug_cmnd_count = 0;
+ #define DEV_READONLY(TGT)      (0)
+ #define DEV_REMOVEABLE(TGT)    (0)
+ 
+-static unsigned int sdebug_store_size;	/* in bytes */
+ static unsigned int sdebug_store_sectors;
+ static sector_t sdebug_capacity;	/* in sectors */
+ 
+@@ -165,6 +166,9 @@ static int sdebug_sectors_per;		/* sectors per cylinder */
+ 
+ #define SDEBUG_SENSE_LEN 32
+ 
++#define SCSI_DEBUG_CANQUEUE  255
++#define SCSI_DEBUG_MAX_CMD_LEN 16
++
+ struct sdebug_dev_info {
+ 	struct list_head dev_list;
+ 	unsigned char sense_buff[SDEBUG_SENSE_LEN];	/* weak nexus */
+@@ -202,30 +206,6 @@ struct sdebug_queued_cmd {
+ };
+ static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
+ 
+-static struct scsi_host_template sdebug_driver_template = {
+-	.proc_info =		scsi_debug_proc_info,
+-	.name =			"SCSI DEBUG",
+-	.info =			scsi_debug_info,
+-	.slave_alloc =		scsi_debug_slave_alloc,
+-	.slave_configure =	scsi_debug_slave_configure,
+-	.slave_destroy =	scsi_debug_slave_destroy,
+-	.ioctl =		scsi_debug_ioctl,
+-	.queuecommand =		scsi_debug_queuecommand,
+-	.eh_abort_handler =	scsi_debug_abort,
+-	.eh_bus_reset_handler = scsi_debug_bus_reset,
+-	.eh_device_reset_handler = scsi_debug_device_reset,
+-	.eh_host_reset_handler = scsi_debug_host_reset,
+-	.bios_param =		scsi_debug_biosparam,
+-	.can_queue =		SCSI_DEBUG_CANQUEUE,
+-	.this_id =		7,
+-	.sg_tablesize =		256,
+-	.cmd_per_lun =		16,
+-	.max_sectors =		0xffff,
+-	.unchecked_isa_dma = 	0,
+-	.use_clustering = 	DISABLE_CLUSTERING,
+-	.module =		THIS_MODULE,
+-};
+-
+ static unsigned char * fake_storep;	/* ramdisk storage */
+ 
+ static int num_aborts = 0;
+@@ -238,8 +218,6 @@ static DEFINE_RWLOCK(atomic_rw);
+ 
+ static char sdebug_proc_name[] = "scsi_debug";
+ 
+-static int sdebug_driver_probe(struct device *);
+-static int sdebug_driver_remove(struct device *);
+ static struct bus_type pseudo_lld_bus;
+ 
+ static struct device_driver sdebug_driverfs_driver = {
+@@ -255,94 +233,77 @@ static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
+ static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
+ 			           0, 0, 0x0, 0x0};
+ 
+-/* function declarations */
+-static int resp_inquiry(struct scsi_cmnd * SCpnt, int target,
+-			struct sdebug_dev_info * devip);
+-static int resp_requests(struct scsi_cmnd * SCpnt,
+-			 struct sdebug_dev_info * devip);
+-static int resp_start_stop(struct scsi_cmnd * scp,
+-			   struct sdebug_dev_info * devip);
+-static int resp_report_tgtpgs(struct scsi_cmnd * scp,
+-			      struct sdebug_dev_info * devip);
+-static int resp_readcap(struct scsi_cmnd * SCpnt,
+-			struct sdebug_dev_info * devip);
+-static int resp_readcap16(struct scsi_cmnd * SCpnt,
+-			  struct sdebug_dev_info * devip);
+-static int resp_mode_sense(struct scsi_cmnd * scp, int target,
+-			   struct sdebug_dev_info * devip);
+-static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
+-			    struct sdebug_dev_info * devip);
+-static int resp_log_sense(struct scsi_cmnd * scp,
+-			  struct sdebug_dev_info * devip);
+-static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
+-		     unsigned int num, struct sdebug_dev_info * devip);
+-static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
+-		      unsigned int num, struct sdebug_dev_info * devip);
+-static int resp_report_luns(struct scsi_cmnd * SCpnt,
+-			    struct sdebug_dev_info * devip);
+-static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
+-			    unsigned int num, struct sdebug_dev_info *devip);
+-static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+-                                int arr_len);
+-static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+-                               int max_arr_len);
+-static void timer_intr_handler(unsigned long);
+-static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev);
+-static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
+-			    int asc, int asq);
+-static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
+-			   struct sdebug_dev_info * devip);
+-static int schedule_resp(struct scsi_cmnd * cmnd,
+-			 struct sdebug_dev_info * devip,
+-			 done_funct_t done, int scsi_result, int delta_jiff);
+-static void __init sdebug_build_parts(unsigned char * ramp);
+-static void __init init_all_queued(void);
+-static void stop_all_queued(void);
+-static int stop_queued_cmnd(struct scsi_cmnd * cmnd);
+-static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
+-			   int target_dev_id, int dev_id_num,
+-			   const char * dev_id_str, int dev_id_str_len);
+-static int inquiry_evpd_88(unsigned char * arr, int target_dev_id);
+-static int do_create_driverfs_files(void);
+-static void do_remove_driverfs_files(void);
+-
+ static int sdebug_add_adapter(void);
+ static void sdebug_remove_adapter(void);
+-static void sdebug_max_tgts_luns(void);
+ 
+-static struct device pseudo_primary;
+-static struct bus_type pseudo_lld_bus;
++static void sdebug_max_tgts_luns(void)
++{
++	struct sdebug_host_info *sdbg_host;
++	struct Scsi_Host *hpnt;
++
++	spin_lock(&sdebug_host_list_lock);
++	list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
++		hpnt = sdbg_host->shost;
++		if ((hpnt->this_id >= 0) &&
++		    (scsi_debug_num_tgts > hpnt->this_id))
++			hpnt->max_id = scsi_debug_num_tgts + 1;
++		else
++			hpnt->max_id = scsi_debug_num_tgts;
++		/* scsi_debug_max_luns; */
++		hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
++	}
++	spin_unlock(&sdebug_host_list_lock);
++}
++
++static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
++			    int asc, int asq)
++{
++	unsigned char *sbuff;
++
++	sbuff = devip->sense_buff;
++	memset(sbuff, 0, SDEBUG_SENSE_LEN);
++
++	scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
++
++	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
++		printk(KERN_INFO "scsi_debug:    [sense_key,asc,ascq]: "
++		      "[0x%x,0x%x,0x%x]\n", key, asc, asq);
++}
+ 
+ static void get_data_transfer_info(unsigned char *cmd,
+ 				   unsigned long long *lba, unsigned int *num)
+ {
+-	int i;
+-
+ 	switch (*cmd) {
+ 	case WRITE_16:
+ 	case READ_16:
+-		for (*lba = 0, i = 0; i < 8; ++i) {
+-			if (i > 0)
+-				*lba <<= 8;
+-			*lba += cmd[2 + i];
+-		}
+-		*num = cmd[13] + (cmd[12] << 8) +
+-			(cmd[11] << 16) + (cmd[10] << 24);
++		*lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
++			(u64)cmd[7] << 16 | (u64)cmd[6] << 24 |
++			(u64)cmd[5] << 32 | (u64)cmd[4] << 40 |
++			(u64)cmd[3] << 48 | (u64)cmd[2] << 56;
++
++		*num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 |
++			(u32)cmd[10] << 24;
+ 		break;
+ 	case WRITE_12:
+ 	case READ_12:
+-		*lba = cmd[5] + (cmd[4] << 8) +	(cmd[3] << 16) + (cmd[2] << 24);
+-		*num = cmd[9] + (cmd[8] << 8) +	(cmd[7] << 16) + (cmd[6] << 24);
++		*lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
++			(u32)cmd[2] << 24;
++
++		*num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 |
++			(u32)cmd[6] << 24;
+ 		break;
+ 	case WRITE_10:
+ 	case READ_10:
+ 	case XDWRITEREAD_10:
+-		*lba = cmd[5] + (cmd[4] << 8) +	(cmd[3] << 16) + (cmd[2] << 24);
+-		*num = cmd[8] + (cmd[7] << 8);
++		*lba = (u32)cmd[5] | (u32)cmd[4] << 8 |	(u32)cmd[3] << 16 |
++			(u32)cmd[2] << 24;
++
++		*num = (u32)cmd[8] | (u32)cmd[7] << 8;
+ 		break;
+ 	case WRITE_6:
+ 	case READ_6:
+-		*lba = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
++		*lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
++			(u32)(cmd[1] & 0x1f) << 16;
+ 		*num = (0 == cmd[4]) ? 256 : cmd[4];
+ 		break;
+ 	default:
+@@ -350,237 +311,6 @@ static void get_data_transfer_info(unsigned char *cmd,
+ 	}
+ }
+ 
+-static
+-int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
+-{
+-	unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
+-	int len, k;
+-	unsigned int num;
+-	unsigned long long lba;
+-	int errsts = 0;
+-	int target = SCpnt->device->id;
+-	struct sdebug_dev_info * devip = NULL;
+-	int inj_recovered = 0;
+-	int inj_transport = 0;
+-	int delay_override = 0;
+-
+-	if (done == NULL)
+-		return 0;	/* assume mid level reprocessing command */
+-
+-	scsi_set_resid(SCpnt, 0);
+-	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
+-		printk(KERN_INFO "scsi_debug: cmd ");
+-		for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
+-			printk("%02x ", (int)cmd[k]);
+-		printk("\n");
+-	}
+-        if(target == sdebug_driver_template.this_id) {
+-		printk(KERN_INFO "scsi_debug: initiator's id used as "
+-		       "target!\n");
+-		return schedule_resp(SCpnt, NULL, done,
+-				     DID_NO_CONNECT << 16, 0);
+-        }
+-
+-	if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
+-	    (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
+-		return schedule_resp(SCpnt, NULL, done,
+-				     DID_NO_CONNECT << 16, 0);
+-	devip = devInfoReg(SCpnt->device);
+-	if (NULL == devip)
+-		return schedule_resp(SCpnt, NULL, done,
+-				     DID_NO_CONNECT << 16, 0);
+-
+-        if ((scsi_debug_every_nth != 0) &&
+-            (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
+-                scsi_debug_cmnd_count = 0;
+-		if (scsi_debug_every_nth < -1)
+-			scsi_debug_every_nth = -1;
+-		if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
+-			return 0; /* ignore command causing timeout */
+-		else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
+-			inj_recovered = 1; /* to reads and writes below */
+-		else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
+-			inj_transport = 1; /* to reads and writes below */
+-        }
+-
+-	if (devip->wlun) {
+-		switch (*cmd) {
+-		case INQUIRY:
+-		case REQUEST_SENSE:
+-		case TEST_UNIT_READY:
+-		case REPORT_LUNS:
+-			break;  /* only allowable wlun commands */
+-		default:
+-			if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+-				printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
+-				       "not supported for wlun\n", *cmd);
+-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+-					INVALID_OPCODE, 0);
+-			errsts = check_condition_result;
+-			return schedule_resp(SCpnt, devip, done, errsts,
+-					     0);
+-		}
+-	}
+-
+-	switch (*cmd) {
+-	case INQUIRY:     /* mandatory, ignore unit attention */
+-		delay_override = 1;
+-		errsts = resp_inquiry(SCpnt, target, devip);
+-		break;
+-	case REQUEST_SENSE:	/* mandatory, ignore unit attention */
+-		delay_override = 1;
+-		errsts = resp_requests(SCpnt, devip);
+-		break;
+-	case REZERO_UNIT:	/* actually this is REWIND for SSC */
+-	case START_STOP:
+-		errsts = resp_start_stop(SCpnt, devip);
+-		break;
+-	case ALLOW_MEDIUM_REMOVAL:
+-		if ((errsts = check_readiness(SCpnt, 1, devip)))
+-			break;
+-		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+-			printk(KERN_INFO "scsi_debug: Medium removal %s\n",
+-			        cmd[4] ? "inhibited" : "enabled");
+-		break;
+-	case SEND_DIAGNOSTIC:     /* mandatory */
+-		errsts = check_readiness(SCpnt, 1, devip);
+-		break;
+-	case TEST_UNIT_READY:     /* mandatory */
+-		delay_override = 1;
+-		errsts = check_readiness(SCpnt, 0, devip);
+-		break;
+-        case RESERVE:
+-		errsts = check_readiness(SCpnt, 1, devip);
+-                break;
+-        case RESERVE_10:
+-		errsts = check_readiness(SCpnt, 1, devip);
+-                break;
+-        case RELEASE:
+-		errsts = check_readiness(SCpnt, 1, devip);
+-                break;
+-        case RELEASE_10:
+-		errsts = check_readiness(SCpnt, 1, devip);
+-                break;
+-	case READ_CAPACITY:
+-		errsts = resp_readcap(SCpnt, devip);
+-		break;
+-	case SERVICE_ACTION_IN:
+-		if (SAI_READ_CAPACITY_16 != cmd[1]) {
+-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+-					INVALID_OPCODE, 0);
+-			errsts = check_condition_result;
+-			break;
+-		}
+-		errsts = resp_readcap16(SCpnt, devip);
+-		break;
+-	case MAINTENANCE_IN:
+-		if (MI_REPORT_TARGET_PGS != cmd[1]) {
+-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+-					INVALID_OPCODE, 0);
+-			errsts = check_condition_result;
+-			break;
+-		}
+-		errsts = resp_report_tgtpgs(SCpnt, devip);
+-		break;
+-	case READ_16:
+-	case READ_12:
+-	case READ_10:
+-	case READ_6:
+-		if ((errsts = check_readiness(SCpnt, 0, devip)))
+-			break;
+-		if (scsi_debug_fake_rw)
+-			break;
+-		get_data_transfer_info(cmd, &lba, &num);
+-		errsts = resp_read(SCpnt, lba, num, devip);
+-		if (inj_recovered && (0 == errsts)) {
+-			mk_sense_buffer(devip, RECOVERED_ERROR,
+-					THRESHOLD_EXCEEDED, 0);
+-			errsts = check_condition_result;
+-		} else if (inj_transport && (0 == errsts)) {
+-                        mk_sense_buffer(devip, ABORTED_COMMAND,
+-                                        TRANSPORT_PROBLEM, ACK_NAK_TO);
+-                        errsts = check_condition_result;
+-                }
+-		break;
+-	case REPORT_LUNS:	/* mandatory, ignore unit attention */
+-		delay_override = 1;
+-		errsts = resp_report_luns(SCpnt, devip);
+-		break;
+-	case VERIFY:		/* 10 byte SBC-2 command */
+-		errsts = check_readiness(SCpnt, 0, devip);
+-		break;
+-	case WRITE_16:
+-	case WRITE_12:
+-	case WRITE_10:
+-	case WRITE_6:
+-		if ((errsts = check_readiness(SCpnt, 0, devip)))
+-			break;
+-		if (scsi_debug_fake_rw)
+-			break;
+-		get_data_transfer_info(cmd, &lba, &num);
+-		errsts = resp_write(SCpnt, lba, num, devip);
+-		if (inj_recovered && (0 == errsts)) {
+-			mk_sense_buffer(devip, RECOVERED_ERROR,
+-					THRESHOLD_EXCEEDED, 0);
+-			errsts = check_condition_result;
+-		}
+-		break;
+-	case MODE_SENSE:
+-	case MODE_SENSE_10:
+-		errsts = resp_mode_sense(SCpnt, target, devip);
+-		break;
+-	case MODE_SELECT:
+-		errsts = resp_mode_select(SCpnt, 1, devip);
+-		break;
+-	case MODE_SELECT_10:
+-		errsts = resp_mode_select(SCpnt, 0, devip);
+-		break;
+-	case LOG_SENSE:
+-		errsts = resp_log_sense(SCpnt, devip);
+-		break;
+-	case SYNCHRONIZE_CACHE:
+-		delay_override = 1;
+-		errsts = check_readiness(SCpnt, 0, devip);
+-		break;
+-	case WRITE_BUFFER:
+-		errsts = check_readiness(SCpnt, 1, devip);
+-		break;
+-	case XDWRITEREAD_10:
+-		if (!scsi_bidi_cmnd(SCpnt)) {
+-			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+-					INVALID_FIELD_IN_CDB, 0);
+-			errsts = check_condition_result;
+-			break;
+-		}
+-
+-		errsts = check_readiness(SCpnt, 0, devip);
+-		if (errsts)
+-			break;
+-		if (scsi_debug_fake_rw)
+-			break;
+-		get_data_transfer_info(cmd, &lba, &num);
+-		errsts = resp_read(SCpnt, lba, num, devip);
+-		if (errsts)
+-			break;
+-		errsts = resp_write(SCpnt, lba, num, devip);
+-		if (errsts)
+-			break;
+-		errsts = resp_xdwriteread(SCpnt, lba, num, devip);
+-		break;
+-	default:
+-		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+-			printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
+-			       "supported\n", *cmd);
+-		if ((errsts = check_readiness(SCpnt, 1, devip)))
+-			break;	/* Unit attention takes precedence */
+-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
+-		errsts = check_condition_result;
+-		break;
+-	}
+-	return schedule_resp(SCpnt, devip, done, errsts,
+-			     (delay_override ? 0 : scsi_debug_delay));
+-}
+-
+ static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
+ {
+ 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
+@@ -613,81 +343,37 @@ static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
+ }
+ 
+ /* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
+-static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
++static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
+ 				int arr_len)
+ {
+-	int k, req_len, act_len, len, active;
+-	void * kaddr;
+-	void * kaddr_off;
+-	struct scatterlist *sg;
++	int act_len;
+ 	struct scsi_data_buffer *sdb = scsi_in(scp);
+ 
+ 	if (!sdb->length)
+ 		return 0;
+-	if (!sdb->table.sgl)
+-		return (DID_ERROR << 16);
+ 	if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
+ 		return (DID_ERROR << 16);
+-	active = 1;
+-	req_len = act_len = 0;
+-	for_each_sg(sdb->table.sgl, sg, sdb->table.nents, k) {
+-		if (active) {
+-			kaddr = (unsigned char *)
+-				kmap_atomic(sg_page(sg), KM_USER0);
+-			if (NULL == kaddr)
+-				return (DID_ERROR << 16);
+-			kaddr_off = (unsigned char *)kaddr + sg->offset;
+-			len = sg->length;
+-			if ((req_len + len) > arr_len) {
+-				active = 0;
+-				len = arr_len - req_len;
+-			}
+-			memcpy(kaddr_off, arr + req_len, len);
+-			kunmap_atomic(kaddr, KM_USER0);
+-			act_len += len;
+-		}
+-		req_len += sg->length;
+-	}
++
++	act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
++				      arr, arr_len);
+ 	if (sdb->resid)
+ 		sdb->resid -= act_len;
+ 	else
+-		sdb->resid = req_len - act_len;
++		sdb->resid = scsi_bufflen(scp) - act_len;
++
+ 	return 0;
+ }
+ 
+ /* Returns number of bytes fetched into 'arr' or -1 if error. */
+-static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+-			       int max_arr_len)
++static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
++			       int arr_len)
+ {
+-	int k, req_len, len, fin;
+-	void * kaddr;
+-	void * kaddr_off;
+-	struct scatterlist * sg;
+-
+-	if (0 == scsi_bufflen(scp))
++	if (!scsi_bufflen(scp))
+ 		return 0;
+-	if (NULL == scsi_sglist(scp))
+-		return -1;
+ 	if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
+ 		return -1;
+-	req_len = fin = 0;
+-	scsi_for_each_sg(scp, sg, scsi_sg_count(scp), k) {
+-		kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
+-		if (NULL == kaddr)
+-			return -1;
+-		kaddr_off = (unsigned char *)kaddr + sg->offset;
+-		len = sg->length;
+-		if ((req_len + len) > max_arr_len) {
+-			len = max_arr_len - req_len;
+-			fin = 1;
+-		}
+-		memcpy(arr + req_len, kaddr_off, len);
+-		kunmap_atomic(kaddr, KM_USER0);
+-		if (fin)
+-			return req_len + len;
+-		req_len += sg->length;
+-	}
+-	return req_len;
++
++	return scsi_sg_copy_to_buffer(scp, arr, arr_len);
+ }
+ 
+ 
+@@ -1159,6 +845,14 @@ static int resp_start_stop(struct scsi_cmnd * scp,
+ 	return 0;
+ }
+ 
++static sector_t get_sdebug_capacity(void)
++{
++	if (scsi_debug_virtual_gb > 0)
++		return 2048 * 1024 * scsi_debug_virtual_gb;
++	else
++		return sdebug_store_sectors;
++}
++
+ #define SDEBUG_READCAP_ARR_SZ 8
+ static int resp_readcap(struct scsi_cmnd * scp,
+ 			struct sdebug_dev_info * devip)
+@@ -1170,11 +864,7 @@ static int resp_readcap(struct scsi_cmnd * scp,
+ 	if ((errsts = check_readiness(scp, 1, devip)))
+ 		return errsts;
+ 	/* following just in case virtual_gb changed */
+-	if (scsi_debug_virtual_gb > 0) {
+-		sdebug_capacity = 2048 * 1024;
+-		sdebug_capacity *= scsi_debug_virtual_gb;
+-	} else
+-		sdebug_capacity = sdebug_store_sectors;
++	sdebug_capacity = get_sdebug_capacity();
+ 	memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
+ 	if (sdebug_capacity < 0xffffffff) {
+ 		capac = (unsigned int)sdebug_capacity - 1;
+@@ -1207,11 +897,7 @@ static int resp_readcap16(struct scsi_cmnd * scp,
+ 	alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
+ 		     + cmd[13]);
+ 	/* following just in case virtual_gb changed */
+-	if (scsi_debug_virtual_gb > 0) {
+-		sdebug_capacity = 2048 * 1024;
+-		sdebug_capacity *= scsi_debug_virtual_gb;
+-	} else
+-		sdebug_capacity = sdebug_store_sectors;
++	sdebug_capacity = get_sdebug_capacity();
+ 	memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
+ 	capac = sdebug_capacity - 1;
+ 	for (k = 0; k < 8; ++k, capac >>= 8)
+@@ -1505,13 +1191,9 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
+ 		offset = 8;
+ 	}
+ 	ap = arr + offset;
+-	if ((bd_len > 0) && (0 == sdebug_capacity)) {
+-		if (scsi_debug_virtual_gb > 0) {
+-			sdebug_capacity = 2048 * 1024;
+-			sdebug_capacity *= scsi_debug_virtual_gb;
+-		} else
+-			sdebug_capacity = sdebug_store_sectors;
+-	}
++	if ((bd_len > 0) && (!sdebug_capacity))
++		sdebug_capacity = get_sdebug_capacity();
++
+ 	if (8 == bd_len) {
+ 		if (sdebug_capacity > 0xfffffffe) {
+ 			ap[0] = 0xff;
+@@ -1808,25 +1490,53 @@ static int resp_log_sense(struct scsi_cmnd * scp,
+ 		    min(len, SDEBUG_MAX_INQ_ARR_SZ));
+ }
+ 
+-static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
+-		     unsigned int num, struct sdebug_dev_info * devip)
++static int check_device_access_params(struct sdebug_dev_info *devi,
++				      unsigned long long lba, unsigned int num)
+ {
+-	unsigned long iflags;
+-	unsigned int block, from_bottom;
+-	unsigned long long u;
+-	int ret;
+-
+ 	if (lba + num > sdebug_capacity) {
+-		mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
+-				0);
++		mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
+ 		return check_condition_result;
+ 	}
+ 	/* transfer length excessive (tie in to block limits VPD page) */
+ 	if (num > sdebug_store_sectors) {
+-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+-				0);
++		mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ 		return check_condition_result;
+ 	}
++	return 0;
++}
++
++static int do_device_access(struct scsi_cmnd *scmd,
++			    struct sdebug_dev_info *devi,
++			    unsigned long long lba, unsigned int num, int write)
++{
++	int ret;
++	unsigned int block, rest = 0;
++	int (*func)(struct scsi_cmnd *, unsigned char *, int);
++
++	func = write ? fetch_to_dev_buffer : fill_from_dev_buffer;
++
++	block = do_div(lba, sdebug_store_sectors);
++	if (block + num > sdebug_store_sectors)
++		rest = block + num - sdebug_store_sectors;
++
++	ret = func(scmd, fake_storep + (block * SECT_SIZE),
++		   (num - rest) * SECT_SIZE);
++	if (!ret && rest)
++		ret = func(scmd, fake_storep, rest * SECT_SIZE);
++
++	return ret;
++}
++
++static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
++		     unsigned int num, struct sdebug_dev_info *devip)
++{
++	unsigned long iflags;
++	int ret;
++
++	ret = check_device_access_params(devip, lba, num);
++	if (ret)
++		return ret;
++
+ 	if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
+ 	    (lba <= OPT_MEDIUM_ERR_ADDR) &&
+ 	    ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
+@@ -1845,74 +1555,30 @@ static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
+ 		return check_condition_result;
+ 	}
+ 	read_lock_irqsave(&atomic_rw, iflags);
+-	if ((lba + num) <= sdebug_store_sectors)
+-		ret = fill_from_dev_buffer(SCpnt,
+-					   fake_storep + (lba * SECT_SIZE),
+-			   		   num * SECT_SIZE);
+-	else {
+-		/* modulo when one arg is 64 bits needs do_div() */
+-		u = lba;
+-		block = do_div(u, sdebug_store_sectors);
+-		from_bottom = 0;
+-		if ((block + num) > sdebug_store_sectors)
+-			from_bottom = (block + num) - sdebug_store_sectors;
+-		ret = fill_from_dev_buffer(SCpnt,
+-					   fake_storep + (block * SECT_SIZE),
+-			   		   (num - from_bottom) * SECT_SIZE);
+-		if ((0 == ret) && (from_bottom > 0))
+-			ret = fill_from_dev_buffer(SCpnt, fake_storep,
+-						   from_bottom * SECT_SIZE);
+-	}
++	ret = do_device_access(SCpnt, devip, lba, num, 0);
+ 	read_unlock_irqrestore(&atomic_rw, iflags);
+ 	return ret;
+ }
+ 
+-static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
+-		      unsigned int num, struct sdebug_dev_info * devip)
++static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
++		      unsigned int num, struct sdebug_dev_info *devip)
+ {
+ 	unsigned long iflags;
+-	unsigned int block, to_bottom;
+-	unsigned long long u;
+-	int res;
++	int ret;
+ 
+-	if (lba + num > sdebug_capacity) {
+-		mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
+-			       	0);
+-		return check_condition_result;
+-	}
+-	/* transfer length excessive (tie in to block limits VPD page) */
+-	if (num > sdebug_store_sectors) {
+-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+-				0);
+-		return check_condition_result;
+-	}
++	ret = check_device_access_params(devip, lba, num);
++	if (ret)
++		return ret;
+ 
+ 	write_lock_irqsave(&atomic_rw, iflags);
+-	if ((lba + num) <= sdebug_store_sectors)
+-		res = fetch_to_dev_buffer(SCpnt,
+-					  fake_storep + (lba * SECT_SIZE),
+-			   		  num * SECT_SIZE);
+-	else {
+-		/* modulo when one arg is 64 bits needs do_div() */
+-		u = lba;
+-		block = do_div(u, sdebug_store_sectors);
+-		to_bottom = 0;
+-		if ((block + num) > sdebug_store_sectors)
+-			to_bottom = (block + num) - sdebug_store_sectors;
+-		res = fetch_to_dev_buffer(SCpnt,
+-					  fake_storep + (block * SECT_SIZE),
+-			   		  (num - to_bottom) * SECT_SIZE);
+-		if ((0 == res) && (to_bottom > 0))
+-			res = fetch_to_dev_buffer(SCpnt, fake_storep,
+-						  to_bottom * SECT_SIZE);
+-	}
++	ret = do_device_access(SCpnt, devip, lba, num, 1);
+ 	write_unlock_irqrestore(&atomic_rw, iflags);
+-	if (-1 == res)
++	if (-1 == ret)
+ 		return (DID_ERROR << 16);
+-	else if ((res < (num * SECT_SIZE)) &&
++	else if ((ret < (num * SECT_SIZE)) &&
+ 		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+ 		printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
+-		       " IO sent=%d bytes\n", num * SECT_SIZE, res);
++		       " IO sent=%d bytes\n", num * SECT_SIZE, ret);
+ 	return 0;
+ }
+ 
+@@ -1987,16 +1653,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
+ 	if (!buf)
+ 		return ret;
+ 
+-	offset = 0;
+-	scsi_for_each_sg(scp, sg, scsi_sg_count(scp), i) {
+-		kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
+-		if (!kaddr)
+-			goto out;
+-
+-		memcpy(buf + offset, kaddr + sg->offset, sg->length);
+-		offset += sg->length;
+-		kunmap_atomic(kaddr, KM_USER0);
+-	}
++	scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
+ 
+ 	offset = 0;
+ 	for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
+@@ -2045,7 +1702,73 @@ static void timer_intr_handler(unsigned long indx)
+ 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+ }
+ 
+-static int scsi_debug_slave_alloc(struct scsi_device * sdp)
++
++static struct sdebug_dev_info *
++sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
++{
++	struct sdebug_dev_info *devip;
++
++	devip = kzalloc(sizeof(*devip), flags);
++	if (devip) {
++		devip->sdbg_host = sdbg_host;
++		list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
++	}
++	return devip;
++}
++
++static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
++{
++	struct sdebug_host_info * sdbg_host;
++	struct sdebug_dev_info * open_devip = NULL;
++	struct sdebug_dev_info * devip =
++			(struct sdebug_dev_info *)sdev->hostdata;
++
++	if (devip)
++		return devip;
++	sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
++	if (!sdbg_host) {
++                printk(KERN_ERR "Host info NULL\n");
++		return NULL;
++        }
++	list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
++		if ((devip->used) && (devip->channel == sdev->channel) &&
++                    (devip->target == sdev->id) &&
++                    (devip->lun == sdev->lun))
++                        return devip;
++		else {
++			if ((!devip->used) && (!open_devip))
++				open_devip = devip;
++		}
++	}
++	if (!open_devip) { /* try and make a new one */
++		open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
++		if (!open_devip) {
++			printk(KERN_ERR "%s: out of memory at line %d\n",
++				__FUNCTION__, __LINE__);
++			return NULL;
++		}
++	}
++
++	open_devip->channel = sdev->channel;
++	open_devip->target = sdev->id;
++	open_devip->lun = sdev->lun;
++	open_devip->sdbg_host = sdbg_host;
++	open_devip->reset = 1;
++	open_devip->used = 1;
++	memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
++	if (scsi_debug_dsense)
++		open_devip->sense_buff[0] = 0x72;
++	else {
++		open_devip->sense_buff[0] = 0x70;
++		open_devip->sense_buff[7] = 0xa;
++	}
++	if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
++		open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
++
++	return open_devip;
++}
++
++static int scsi_debug_slave_alloc(struct scsi_device *sdp)
+ {
+ 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+ 		printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
+@@ -2054,9 +1777,9 @@ static int scsi_debug_slave_alloc(struct scsi_device * sdp)
+ 	return 0;
+ }
+ 
+-static int scsi_debug_slave_configure(struct scsi_device * sdp)
++static int scsi_debug_slave_configure(struct scsi_device *sdp)
+ {
+-	struct sdebug_dev_info * devip;
++	struct sdebug_dev_info *devip;
+ 
+ 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+ 		printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n",
+@@ -2074,10 +1797,10 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp)
+ 	return 0;
+ }
+ 
+-static void scsi_debug_slave_destroy(struct scsi_device * sdp)
++static void scsi_debug_slave_destroy(struct scsi_device *sdp)
+ {
+-	struct sdebug_dev_info * devip =
+-				(struct sdebug_dev_info *)sdp->hostdata;
++	struct sdebug_dev_info *devip =
++		(struct sdebug_dev_info *)sdp->hostdata;
+ 
+ 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+ 		printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n",
+@@ -2089,84 +1812,44 @@ static void scsi_debug_slave_destroy(struct scsi_device * sdp)
+ 	}
+ }
+ 
+-static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
++/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */
++static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
+ {
+-	struct sdebug_host_info * sdbg_host;
+-	struct sdebug_dev_info * open_devip = NULL;
+-	struct sdebug_dev_info * devip =
+-			(struct sdebug_dev_info *)sdev->hostdata;
++	unsigned long iflags;
++	int k;
++	struct sdebug_queued_cmd *sqcp;
+ 
+-	if (devip)
+-		return devip;
+-	sdbg_host = *(struct sdebug_host_info **) sdev->host->hostdata;
+-        if(! sdbg_host) {
+-                printk(KERN_ERR "Host info NULL\n");
+-		return NULL;
+-        }
+-	list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
+-		if ((devip->used) && (devip->channel == sdev->channel) &&
+-                    (devip->target == sdev->id) &&
+-                    (devip->lun == sdev->lun))
+-                        return devip;
+-		else {
+-			if ((!devip->used) && (!open_devip))
+-				open_devip = devip;
++	spin_lock_irqsave(&queued_arr_lock, iflags);
++	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
++		sqcp = &queued_arr[k];
++		if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) {
++			del_timer_sync(&sqcp->cmnd_timer);
++			sqcp->in_use = 0;
++			sqcp->a_cmnd = NULL;
++			break;
+ 		}
+ 	}
+-	if (NULL == open_devip) { /* try and make a new one */
+-		open_devip = kzalloc(sizeof(*open_devip),GFP_ATOMIC);
+-		if (NULL == open_devip) {
+-			printk(KERN_ERR "%s: out of memory at line %d\n",
+-				__FUNCTION__, __LINE__);
+-			return NULL;
+-		}
+-		open_devip->sdbg_host = sdbg_host;
+-		list_add_tail(&open_devip->dev_list,
+-		&sdbg_host->dev_info_list);
+-	}
+-        if (open_devip) {
+-		open_devip->channel = sdev->channel;
+-		open_devip->target = sdev->id;
+-		open_devip->lun = sdev->lun;
+-		open_devip->sdbg_host = sdbg_host;
+-		open_devip->reset = 1;
+-		open_devip->used = 1;
+-		memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
+-		if (scsi_debug_dsense)
+-			open_devip->sense_buff[0] = 0x72;
+-		else {
+-			open_devip->sense_buff[0] = 0x70;
+-			open_devip->sense_buff[7] = 0xa;
+-		}
+-		if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
+-			open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
+-		return open_devip;
+-        }
+-        return NULL;
++	spin_unlock_irqrestore(&queued_arr_lock, iflags);
++	return (k < SCSI_DEBUG_CANQUEUE) ? 1 : 0;
+ }
+ 
+-static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
+-			    int asc, int asq)
++/* Deletes (stops) timers of all queued commands */
++static void stop_all_queued(void)
+ {
+-	unsigned char * sbuff;
++	unsigned long iflags;
++	int k;
++	struct sdebug_queued_cmd *sqcp;
+ 
+-	sbuff = devip->sense_buff;
+-	memset(sbuff, 0, SDEBUG_SENSE_LEN);
+-	if (scsi_debug_dsense) {
+-		sbuff[0] = 0x72;  /* descriptor, current */
+-		sbuff[1] = key;
+-		sbuff[2] = asc;
+-		sbuff[3] = asq;
+-	} else {
+-		sbuff[0] = 0x70;  /* fixed, current */
+-		sbuff[2] = key;
+-		sbuff[7] = 0xa;	  /* implies 18 byte sense buffer */
+-		sbuff[12] = asc;
+-		sbuff[13] = asq;
++	spin_lock_irqsave(&queued_arr_lock, iflags);
++	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
++		sqcp = &queued_arr[k];
++		if (sqcp->in_use && sqcp->a_cmnd) {
++			del_timer_sync(&sqcp->cmnd_timer);
++			sqcp->in_use = 0;
++			sqcp->a_cmnd = NULL;
++		}
+ 	}
+-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+-		printk(KERN_INFO "scsi_debug:    [sense_key,asc,ascq]: "
+-		      "[0x%x,0x%x,0x%x]\n", key, asc, asq);
++	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+ }
+ 
+ static int scsi_debug_abort(struct scsi_cmnd * SCpnt)
+@@ -2226,7 +1909,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
+ 		printk(KERN_INFO "scsi_debug: bus_reset\n");
+ 	++num_bus_resets;
+ 	if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
+-		sdbg_host = *(struct sdebug_host_info **) hp->hostdata;
++		sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
+ 		if (sdbg_host) {
+ 			list_for_each_entry(dev_info,
+                                             &sdbg_host->dev_info_list,
+@@ -2256,46 +1939,6 @@ static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
+ 	return SUCCESS;
+ }
+ 
+-/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */
+-static int stop_queued_cmnd(struct scsi_cmnd * cmnd)
+-{
+-	unsigned long iflags;
+-	int k;
+-	struct sdebug_queued_cmd * sqcp;
+-
+-	spin_lock_irqsave(&queued_arr_lock, iflags);
+-	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+-		sqcp = &queued_arr[k];
+-		if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) {
+-			del_timer_sync(&sqcp->cmnd_timer);
+-			sqcp->in_use = 0;
+-			sqcp->a_cmnd = NULL;
+-			break;
+-		}
+-	}
+-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+-	return (k < SCSI_DEBUG_CANQUEUE) ? 1 : 0;
+-}
+-
+-/* Deletes (stops) timers of all queued commands */
+-static void stop_all_queued(void)
+-{
+-	unsigned long iflags;
+-	int k;
+-	struct sdebug_queued_cmd * sqcp;
+-
+-	spin_lock_irqsave(&queued_arr_lock, iflags);
+-	for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+-		sqcp = &queued_arr[k];
+-		if (sqcp->in_use && sqcp->a_cmnd) {
+-			del_timer_sync(&sqcp->cmnd_timer);
+-			sqcp->in_use = 0;
+-			sqcp->a_cmnd = NULL;
+-		}
+-	}
+-	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+-}
+-
+ /* Initializes timers in queued array */
+ static void __init init_all_queued(void)
+ {
+@@ -2313,7 +1956,8 @@ static void __init init_all_queued(void)
+ 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
+ }
+ 
+-static void __init sdebug_build_parts(unsigned char * ramp)
++static void __init sdebug_build_parts(unsigned char *ramp,
++				      unsigned long store_size)
+ {
+ 	struct partition * pp;
+ 	int starts[SDEBUG_MAX_PARTS + 2];
+@@ -2321,7 +1965,7 @@ static void __init sdebug_build_parts(unsigned char * ramp)
+ 	int heads_by_sects, start_sec, end_sec;
+ 
+ 	/* assume partition table already zeroed */
+-	if ((scsi_debug_num_parts < 1) || (sdebug_store_size < 1048576))
++	if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
+ 		return;
+ 	if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
+ 		scsi_debug_num_parts = SDEBUG_MAX_PARTS;
+@@ -2419,7 +2063,6 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
+ 		return 0;
+ 	}
+ }
+-
+ /* Note: The following macros create attribute files in the
+    /sys/module/scsi_debug/parameters directory. Unfortunately this
+    driver is unaware of a change and cannot trigger auxiliary actions
+@@ -2736,11 +2379,9 @@ static ssize_t sdebug_virtual_gb_store(struct device_driver * ddp,
+ 
+ 	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+ 		scsi_debug_virtual_gb = n;
+-		if (scsi_debug_virtual_gb > 0) {
+-			sdebug_capacity = 2048 * 1024;
+-			sdebug_capacity *= scsi_debug_virtual_gb;
+-		} else
+-			sdebug_capacity = sdebug_store_sectors;
++
++		sdebug_capacity = get_sdebug_capacity();
++
+ 		return count;
+ 	}
+ 	return -EINVAL;
+@@ -2756,21 +2397,10 @@ static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf)
+ static ssize_t sdebug_add_host_store(struct device_driver * ddp,
+ 				     const char * buf, size_t count)
+ {
+-        int delta_hosts;
+-	char work[20];
++	int delta_hosts;
+ 
+-        if (1 != sscanf(buf, "%10s", work))
++	if (sscanf(buf, "%d", &delta_hosts) != 1)
+ 		return -EINVAL;
+-	{	/* temporary hack around sscanf() problem with -ve nums */
+-		int neg = 0;
+-
+-		if ('-' == *work)
+-			neg = 1;
+-		if (1 != sscanf(work + neg, "%d", &delta_hosts))
+-			return -EINVAL;
+-		if (neg)
+-			delta_hosts = -delta_hosts;
+-	}
+ 	if (delta_hosts > 0) {
+ 		do {
+ 			sdebug_add_adapter();
+@@ -2782,7 +2412,7 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp,
+ 	}
+ 	return count;
+ }
+-DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, 
++DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
+ 	    sdebug_add_host_store);
+ 
+ static ssize_t sdebug_vpd_use_hostno_show(struct device_driver * ddp,
+@@ -2851,22 +2481,29 @@ static void do_remove_driverfs_files(void)
+ 	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 = {
++	.bus_id		= "pseudo_0",
++	.release	= pseudo_0_release,
++};
++
+ static int __init scsi_debug_init(void)
+ {
+-	unsigned int sz;
++	unsigned long sz;
+ 	int host_to_add;
+ 	int k;
+ 	int ret;
+ 
+ 	if (scsi_debug_dev_size_mb < 1)
+ 		scsi_debug_dev_size_mb = 1;  /* force minimum 1 MB ramdisk */
+-	sdebug_store_size = (unsigned int)scsi_debug_dev_size_mb * 1048576;
+-	sdebug_store_sectors = sdebug_store_size / SECT_SIZE;
+-	if (scsi_debug_virtual_gb > 0) {
+-		sdebug_capacity = 2048 * 1024;
+-		sdebug_capacity *= scsi_debug_virtual_gb;
+-	} else
+-		sdebug_capacity = sdebug_store_sectors;
++	sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
++	sdebug_store_sectors = sz / SECT_SIZE;
++	sdebug_capacity = get_sdebug_capacity();
+ 
+ 	/* play around with geometry, don't waste too much on track 0 */
+ 	sdebug_heads = 8;
+@@ -2885,7 +2522,6 @@ static int __init scsi_debug_init(void)
+ 			       (sdebug_sectors_per * sdebug_heads);
+ 	}
+ 
+-	sz = sdebug_store_size;
+ 	fake_storep = vmalloc(sz);
+ 	if (NULL == fake_storep) {
+ 		printk(KERN_ERR "scsi_debug_init: out of memory, 1\n");
+@@ -2893,7 +2529,7 @@ static int __init scsi_debug_init(void)
+ 	}
+ 	memset(fake_storep, 0, sz);
+ 	if (scsi_debug_num_parts > 0)
+-		sdebug_build_parts(fake_storep);
++		sdebug_build_parts(fake_storep, sz);
+ 
+ 	ret = device_register(&pseudo_primary);
+ 	if (ret < 0) {
+@@ -2922,8 +2558,6 @@ static int __init scsi_debug_init(void)
+ 
+ 	init_all_queued();
+ 
+-	sdebug_driver_template.proc_name = sdebug_proc_name;
+-
+ 	host_to_add = scsi_debug_add_host;
+         scsi_debug_add_host = 0;
+ 
+@@ -2972,30 +2606,6 @@ static void __exit scsi_debug_exit(void)
+ device_initcall(scsi_debug_init);
+ module_exit(scsi_debug_exit);
+ 
+-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 = {
+-	.bus_id		= "pseudo_0",
+-	.release	= pseudo_0_release,
+-};
+-
+-static int pseudo_lld_bus_match(struct device *dev,
+-                          struct device_driver *dev_driver)
+-{
+-        return 1;
+-}
+-
+-static struct bus_type pseudo_lld_bus = {
+-        .name = "pseudo",
+-        .match = pseudo_lld_bus_match,
+-	.probe = sdebug_driver_probe,
+-	.remove = sdebug_driver_remove,
+-};
+-
+ static void sdebug_release_adapter(struct device * dev)
+ {
+         struct sdebug_host_info *sdbg_host;
+@@ -3009,8 +2619,7 @@ static int sdebug_add_adapter(void)
+ 	int k, devs_per_host;
+         int error = 0;
+         struct sdebug_host_info *sdbg_host;
+-        struct sdebug_dev_info *sdbg_devinfo;
+-        struct list_head *lh, *lh_sf;
++	struct sdebug_dev_info *sdbg_devinfo, *tmp;
+ 
+         sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
+         if (NULL == sdbg_host) {
+@@ -3023,16 +2632,13 @@ static int sdebug_add_adapter(void)
+ 
+ 	devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
+         for (k = 0; k < devs_per_host; k++) {
+-                sdbg_devinfo = kzalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
+-                if (NULL == sdbg_devinfo) {
++		sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
++		if (!sdbg_devinfo) {
+                         printk(KERN_ERR "%s: out of memory at line %d\n",
+                                __FUNCTION__, __LINE__);
+                         error = -ENOMEM;
+ 			goto clean;
+                 }
+-                sdbg_devinfo->sdbg_host = sdbg_host;
+-                list_add_tail(&sdbg_devinfo->dev_list,
+-                              &sdbg_host->dev_info_list);
+         }
+ 
+         spin_lock(&sdebug_host_list_lock);
+@@ -3053,9 +2659,8 @@ static int sdebug_add_adapter(void)
+         return error;
+ 
+ clean:
+-	list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
+-		sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
+-					  dev_list);
++	list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
++				 dev_list) {
+ 		list_del(&sdbg_devinfo->dev_list);
+ 		kfree(sdbg_devinfo);
+ 	}
+@@ -3083,6 +2688,263 @@ static void sdebug_remove_adapter(void)
+         --scsi_debug_add_host;
+ }
+ 
++static
++int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
++{
++	unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
++	int len, k;
++	unsigned int num;
++	unsigned long long lba;
++	int errsts = 0;
++	int target = SCpnt->device->id;
++	struct sdebug_dev_info *devip = NULL;
++	int inj_recovered = 0;
++	int inj_transport = 0;
++	int delay_override = 0;
++
++	scsi_set_resid(SCpnt, 0);
++	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
++		printk(KERN_INFO "scsi_debug: cmd ");
++		for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
++			printk("%02x ", (int)cmd[k]);
++		printk("\n");
++	}
++
++	if (target == SCpnt->device->host->hostt->this_id) {
++		printk(KERN_INFO "scsi_debug: initiator's id used as "
++		       "target!\n");
++		return schedule_resp(SCpnt, NULL, done,
++				     DID_NO_CONNECT << 16, 0);
++	}
++
++	if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
++	    (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
++		return schedule_resp(SCpnt, NULL, done,
++				     DID_NO_CONNECT << 16, 0);
++	devip = devInfoReg(SCpnt->device);
++	if (NULL == devip)
++		return schedule_resp(SCpnt, NULL, done,
++				     DID_NO_CONNECT << 16, 0);
++
++	if ((scsi_debug_every_nth != 0) &&
++	    (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
++		scsi_debug_cmnd_count = 0;
++		if (scsi_debug_every_nth < -1)
++			scsi_debug_every_nth = -1;
++		if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
++			return 0; /* ignore command causing timeout */
++		else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
++			inj_recovered = 1; /* to reads and writes below */
++		else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
++			inj_transport = 1; /* to reads and writes below */
++	}
++
++	if (devip->wlun) {
++		switch (*cmd) {
++		case INQUIRY:
++		case REQUEST_SENSE:
++		case TEST_UNIT_READY:
++		case REPORT_LUNS:
++			break;  /* only allowable wlun commands */
++		default:
++			if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
++				printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
++				       "not supported for wlun\n", *cmd);
++			mk_sense_buffer(devip, ILLEGAL_REQUEST,
++					INVALID_OPCODE, 0);
++			errsts = check_condition_result;
++			return schedule_resp(SCpnt, devip, done, errsts,
++					     0);
++		}
++	}
++
++	switch (*cmd) {
++	case INQUIRY:     /* mandatory, ignore unit attention */
++		delay_override = 1;
++		errsts = resp_inquiry(SCpnt, target, devip);
++		break;
++	case REQUEST_SENSE:	/* mandatory, ignore unit attention */
++		delay_override = 1;
++		errsts = resp_requests(SCpnt, devip);
++		break;
++	case REZERO_UNIT:	/* actually this is REWIND for SSC */
++	case START_STOP:
++		errsts = resp_start_stop(SCpnt, devip);
++		break;
++	case ALLOW_MEDIUM_REMOVAL:
++		errsts = check_readiness(SCpnt, 1, devip);
++		if (errsts)
++			break;
++		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
++			printk(KERN_INFO "scsi_debug: Medium removal %s\n",
++			       cmd[4] ? "inhibited" : "enabled");
++		break;
++	case SEND_DIAGNOSTIC:     /* mandatory */
++		errsts = check_readiness(SCpnt, 1, devip);
++		break;
++	case TEST_UNIT_READY:     /* mandatory */
++		delay_override = 1;
++		errsts = check_readiness(SCpnt, 0, devip);
++		break;
++	case RESERVE:
++		errsts = check_readiness(SCpnt, 1, devip);
++		break;
++	case RESERVE_10:
++		errsts = check_readiness(SCpnt, 1, devip);
++		break;
++	case RELEASE:
++		errsts = check_readiness(SCpnt, 1, devip);
++		break;
++	case RELEASE_10:
++		errsts = check_readiness(SCpnt, 1, devip);
++		break;
++	case READ_CAPACITY:
++		errsts = resp_readcap(SCpnt, devip);
++		break;
++	case SERVICE_ACTION_IN:
++		if (SAI_READ_CAPACITY_16 != cmd[1]) {
++			mk_sense_buffer(devip, ILLEGAL_REQUEST,
++					INVALID_OPCODE, 0);
++			errsts = check_condition_result;
++			break;
++		}
++		errsts = resp_readcap16(SCpnt, devip);
++		break;
++	case MAINTENANCE_IN:
++		if (MI_REPORT_TARGET_PGS != cmd[1]) {
++			mk_sense_buffer(devip, ILLEGAL_REQUEST,
++					INVALID_OPCODE, 0);
++			errsts = check_condition_result;
++			break;
++		}
++		errsts = resp_report_tgtpgs(SCpnt, devip);
++		break;
++	case READ_16:
++	case READ_12:
++	case READ_10:
++	case READ_6:
++		errsts = check_readiness(SCpnt, 0, devip);
++		if (errsts)
++			break;
++		if (scsi_debug_fake_rw)
++			break;
++		get_data_transfer_info(cmd, &lba, &num);
++		errsts = resp_read(SCpnt, lba, num, devip);
++		if (inj_recovered && (0 == errsts)) {
++			mk_sense_buffer(devip, RECOVERED_ERROR,
++					THRESHOLD_EXCEEDED, 0);
++			errsts = check_condition_result;
++		} else if (inj_transport && (0 == errsts)) {
++			mk_sense_buffer(devip, ABORTED_COMMAND,
++					TRANSPORT_PROBLEM, ACK_NAK_TO);
++			errsts = check_condition_result;
++		}
++		break;
++	case REPORT_LUNS:	/* mandatory, ignore unit attention */
++		delay_override = 1;
++		errsts = resp_report_luns(SCpnt, devip);
++		break;
++	case VERIFY:		/* 10 byte SBC-2 command */
++		errsts = check_readiness(SCpnt, 0, devip);
++		break;
++	case WRITE_16:
++	case WRITE_12:
++	case WRITE_10:
++	case WRITE_6:
++		errsts = check_readiness(SCpnt, 0, devip);
++		if (errsts)
++			break;
++		if (scsi_debug_fake_rw)
++			break;
++		get_data_transfer_info(cmd, &lba, &num);
++		errsts = resp_write(SCpnt, lba, num, devip);
++		if (inj_recovered && (0 == errsts)) {
++			mk_sense_buffer(devip, RECOVERED_ERROR,
++					THRESHOLD_EXCEEDED, 0);
++			errsts = check_condition_result;
++		}
++		break;
++	case MODE_SENSE:
++	case MODE_SENSE_10:
++		errsts = resp_mode_sense(SCpnt, target, devip);
++		break;
++	case MODE_SELECT:
++		errsts = resp_mode_select(SCpnt, 1, devip);
++		break;
++	case MODE_SELECT_10:
++		errsts = resp_mode_select(SCpnt, 0, devip);
++		break;
++	case LOG_SENSE:
++		errsts = resp_log_sense(SCpnt, devip);
++		break;
++	case SYNCHRONIZE_CACHE:
++		delay_override = 1;
++		errsts = check_readiness(SCpnt, 0, devip);
++		break;
++	case WRITE_BUFFER:
++		errsts = check_readiness(SCpnt, 1, devip);
++		break;
++	case XDWRITEREAD_10:
++		if (!scsi_bidi_cmnd(SCpnt)) {
++			mk_sense_buffer(devip, ILLEGAL_REQUEST,
++					INVALID_FIELD_IN_CDB, 0);
++			errsts = check_condition_result;
++			break;
++		}
++
++		errsts = check_readiness(SCpnt, 0, devip);
++		if (errsts)
++			break;
++		if (scsi_debug_fake_rw)
++			break;
++		get_data_transfer_info(cmd, &lba, &num);
++		errsts = resp_read(SCpnt, lba, num, devip);
++		if (errsts)
++			break;
++		errsts = resp_write(SCpnt, lba, num, devip);
++		if (errsts)
++			break;
++		errsts = resp_xdwriteread(SCpnt, lba, num, devip);
++		break;
++	default:
++		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
++			printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
++			       "supported\n", *cmd);
++		errsts = check_readiness(SCpnt, 1, devip);
++		if (errsts)
++			break;	/* Unit attention takes precedence */
++		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
++		errsts = check_condition_result;
++		break;
++	}
++	return schedule_resp(SCpnt, devip, done, errsts,
++			     (delay_override ? 0 : scsi_debug_delay));
++}
++
++static struct scsi_host_template sdebug_driver_template = {
++	.proc_info =		scsi_debug_proc_info,
++	.proc_name =		sdebug_proc_name,
++	.name =			"SCSI DEBUG",
++	.info =			scsi_debug_info,
++	.slave_alloc =		scsi_debug_slave_alloc,
++	.slave_configure =	scsi_debug_slave_configure,
++	.slave_destroy =	scsi_debug_slave_destroy,
++	.ioctl =		scsi_debug_ioctl,
++	.queuecommand =		scsi_debug_queuecommand,
++	.eh_abort_handler =	scsi_debug_abort,
++	.eh_bus_reset_handler = scsi_debug_bus_reset,
++	.eh_device_reset_handler = scsi_debug_device_reset,
++	.eh_host_reset_handler = scsi_debug_host_reset,
++	.bios_param =		scsi_debug_biosparam,
++	.can_queue =		SCSI_DEBUG_CANQUEUE,
++	.this_id =		7,
++	.sg_tablesize =		256,
++	.cmd_per_lun =		16,
++	.max_sectors =		0xffff,
++	.use_clustering = 	DISABLE_CLUSTERING,
++	.module =		THIS_MODULE,
++};
++
+ static int sdebug_driver_probe(struct device * dev)
+ {
+         int error = 0;
+@@ -3120,9 +2982,8 @@ static int sdebug_driver_probe(struct device * dev)
+ 
+ static int sdebug_driver_remove(struct device * dev)
+ {
+-        struct list_head *lh, *lh_sf;
+         struct sdebug_host_info *sdbg_host;
+-        struct sdebug_dev_info *sdbg_devinfo;
++	struct sdebug_dev_info *sdbg_devinfo, *tmp;
+ 
+ 	sdbg_host = to_sdebug_host(dev);
+ 
+@@ -3134,9 +2995,8 @@ static int sdebug_driver_remove(struct device * dev)
+ 
+         scsi_remove_host(sdbg_host->shost);
+ 
+-        list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
+-                sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
+-                                          dev_list);
++	list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
++				 dev_list) {
+                 list_del(&sdbg_devinfo->dev_list);
+                 kfree(sdbg_devinfo);
+         }
+@@ -3145,20 +3005,15 @@ static int sdebug_driver_remove(struct device * dev)
+         return 0;
+ }
+ 
+-static void sdebug_max_tgts_luns(void)
++static int pseudo_lld_bus_match(struct device *dev,
++				struct device_driver *dev_driver)
+ {
+-	struct sdebug_host_info * sdbg_host;
+-	struct Scsi_Host *hpnt;
+-
+-	spin_lock(&sdebug_host_list_lock);
+-	list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
+-		hpnt = sdbg_host->shost;
+-		if ((hpnt->this_id >= 0) &&
+-		    (scsi_debug_num_tgts > hpnt->this_id))
+-			hpnt->max_id = scsi_debug_num_tgts + 1;
+-		else
+-			hpnt->max_id = scsi_debug_num_tgts;
+-		hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* scsi_debug_max_luns; */
+-	}
+-	spin_unlock(&sdebug_host_list_lock);
++	return 1;
+ }
++
++static struct bus_type pseudo_lld_bus = {
++	.name = "pseudo",
++	.match = pseudo_lld_bus_match,
++	.probe = sdebug_driver_probe,
++	.remove = sdebug_driver_remove,
++};
+diff --git a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h
+deleted file mode 100644
+index 965dd5e..0000000
+--- a/drivers/scsi/scsi_debug.h
++++ /dev/null
+@@ -1,24 +0,0 @@
+-#ifndef _SCSI_DEBUG_H
+-
+-#include <linux/types.h>
+-
+-static int scsi_debug_slave_alloc(struct scsi_device *);
+-static int scsi_debug_slave_configure(struct scsi_device *);
+-static void scsi_debug_slave_destroy(struct scsi_device *);
+-static int scsi_debug_queuecommand(struct scsi_cmnd *,
+-				   void (*done) (struct scsi_cmnd *));
+-static int scsi_debug_ioctl(struct scsi_device *, int, void __user *);
+-static int scsi_debug_biosparam(struct scsi_device *, struct block_device *,
+-		sector_t, int[]);
+-static int scsi_debug_abort(struct scsi_cmnd *);
+-static int scsi_debug_bus_reset(struct scsi_cmnd *);
+-static int scsi_debug_device_reset(struct scsi_cmnd *);
+-static int scsi_debug_host_reset(struct scsi_cmnd *);
+-static int scsi_debug_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+-static const char * scsi_debug_info(struct Scsi_Host *);
+-
+-#define SCSI_DEBUG_CANQUEUE  255 	/* needs to be >= 1 */
+-
+-#define SCSI_DEBUG_MAX_CMD_LEN 16
+-
+-#endif
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index 045a086..221f31e 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -524,6 +524,41 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
+ 	return rtn;
+ }
+ 
++static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
++{
++	sdev->was_reset = 1;
++	sdev->expecting_cc_ua = 1;
++}
++
++/**
++ * scsi_try_target_reset - Ask host to perform a target reset
++ * @scmd:	SCSI cmd used to send a target reset
++ *
++ * Notes:
++ *    There is no timeout for this operation.  if this operation is
++ *    unreliable for a given host, then the host itself needs to put a
++ *    timer on it, and set the host back to a consistent state prior to
++ *    returning.
++ */
++static int scsi_try_target_reset(struct scsi_cmnd *scmd)
++{
++	unsigned long flags;
++	int rtn;
++
++	if (!scmd->device->host->hostt->eh_target_reset_handler)
++		return FAILED;
++
++	rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd);
++	if (rtn == SUCCESS) {
++		spin_lock_irqsave(scmd->device->host->host_lock, flags);
++		__starget_for_each_device(scsi_target(scmd->device), NULL,
++					  __scsi_report_device_reset);
++		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
++	}
++
++	return rtn;
++}
++
+ /**
+  * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
+  * @scmd:	SCSI cmd used to send BDR
+@@ -542,11 +577,8 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
+ 		return FAILED;
+ 
+ 	rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
+-	if (rtn == SUCCESS) {
+-		scmd->device->was_reset = 1;
+-		scmd->device->expecting_cc_ua = 1;
+-	}
+-
++	if (rtn == SUCCESS)
++		__scsi_report_device_reset(scmd->device, NULL);
+ 	return rtn;
+ }
+ 
+@@ -584,8 +616,9 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
+ {
+ 	if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
+ 		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
+-			if (scsi_try_bus_reset(scmd) != SUCCESS)
+-				scsi_try_host_reset(scmd);
++			if (scsi_try_target_reset(scmd) != SUCCESS)
++				if (scsi_try_bus_reset(scmd) != SUCCESS)
++					scsi_try_host_reset(scmd);
+ }
+ 
+ /**
+@@ -1060,6 +1093,56 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
+ }
+ 
+ /**
++ * scsi_eh_target_reset - send target reset if needed
++ * @shost:	scsi host being recovered.
++ * @work_q:     &list_head for pending commands.
++ * @done_q:	&list_head for processed commands.
++ *
++ * Notes:
++ *    Try a target reset.
++ */
++static int scsi_eh_target_reset(struct Scsi_Host *shost,
++				struct list_head *work_q,
++				struct list_head *done_q)
++{
++	struct scsi_cmnd *scmd, *tgtr_scmd, *next;
++	unsigned int id;
++	int rtn;
++
++	for (id = 0; id <= shost->max_id; id++) {
++		tgtr_scmd = NULL;
++		list_for_each_entry(scmd, work_q, eh_entry) {
++			if (id == scmd_id(scmd)) {
++				tgtr_scmd = scmd;
++				break;
++			}
++		}
++		if (!tgtr_scmd)
++			continue;
++
++		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
++						  "to target %d\n",
++						  current->comm, id));
++		rtn = scsi_try_target_reset(tgtr_scmd);
++		if (rtn == SUCCESS) {
++			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
++				if (id == scmd_id(scmd))
++					if (!scsi_device_online(scmd->device) ||
++					    !scsi_eh_tur(tgtr_scmd))
++						scsi_eh_finish_cmd(scmd,
++								   done_q);
++			}
++		} else
++			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset"
++							  " failed target: "
++							  "%d\n",
++							  current->comm, id));
++	}
++
++	return list_empty(work_q);
++}
++
++/**
+  * scsi_eh_bus_reset - send a bus reset 
+  * @shost:	&scsi host being recovered.
+  * @work_q:     &list_head for pending commands.
+@@ -1447,9 +1530,11 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost,
+ {
+ 	if (!scsi_eh_stu(shost, work_q, done_q))
+ 		if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
+-			if (!scsi_eh_bus_reset(shost, work_q, done_q))
+-				if (!scsi_eh_host_reset(work_q, done_q))
+-					scsi_eh_offline_sdevs(work_q, done_q);
++			if (!scsi_eh_target_reset(shost, work_q, done_q))
++				if (!scsi_eh_bus_reset(shost, work_q, done_q))
++					if (!scsi_eh_host_reset(work_q, done_q))
++						scsi_eh_offline_sdevs(work_q,
++								      done_q);
+ }
+ EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
+ 
+@@ -1619,10 +1704,8 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
+ 	struct scsi_device *sdev;
+ 
+ 	__shost_for_each_device(sdev, shost) {
+-		if (channel == sdev_channel(sdev)) {
+-			sdev->was_reset = 1;
+-			sdev->expecting_cc_ua = 1;
+-		}
++		if (channel == sdev_channel(sdev))
++			__scsi_report_device_reset(sdev, NULL);
+ 	}
+ }
+ EXPORT_SYMBOL(scsi_report_bus_reset);
+@@ -1655,10 +1738,8 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
+ 
+ 	__shost_for_each_device(sdev, shost) {
+ 		if (channel == sdev_channel(sdev) &&
+-		    target == sdev_id(sdev)) {
+-			sdev->was_reset = 1;
+-			sdev->expecting_cc_ua = 1;
+-		}
++		    target == sdev_id(sdev))
++			__scsi_report_device_reset(sdev, NULL);
+ 	}
+ }
+ EXPORT_SYMBOL(scsi_report_device_reset);
+@@ -1714,6 +1795,11 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
+ 		if (rtn == SUCCESS)
+ 			break;
+ 		/* FALLTHROUGH */
++	case SCSI_TRY_RESET_TARGET:
++		rtn = scsi_try_target_reset(scmd);
++		if (rtn == SUCCESS)
++			break;
++		/* FALLTHROUGH */
+ 	case SCSI_TRY_RESET_BUS:
+ 		rtn = scsi_try_bus_reset(scmd);
+ 		if (rtn == SUCCESS)
+@@ -1907,3 +1993,31 @@ int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
+ 	}
+ }
+ EXPORT_SYMBOL(scsi_get_sense_info_fld);
++
++/**
++ * scsi_build_sense_buffer - build sense data in a buffer
++ * @desc:	Sense format (non zero == descriptor format,
++ * 		0 == fixed format)
++ * @buf:	Where to build sense data
++ * @key:	Sense key
++ * @asc:	Additional sense code
++ * @ascq:	Additional sense code qualifier
++ *
++ **/
++void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)
++{
++	if (desc) {
++		buf[0] = 0x72;	/* descriptor, current */
++		buf[1] = key;
++		buf[2] = asc;
++		buf[3] = ascq;
++		buf[7] = 0;
++	} else {
++		buf[0] = 0x70;	/* fixed, current */
++		buf[2] = key;
++		buf[7] = 0xa;
++		buf[12] = asc;
++		buf[13] = ascq;
++	}
++}
++EXPORT_SYMBOL(scsi_build_sense_buffer);
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index f40898d..67f412b 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -784,7 +784,7 @@ EXPORT_SYMBOL(scsi_release_buffers);
+  * in req->data_len and req->next_rq->data_len. The upper-layer driver can
+  * decide what to do with this information.
+  */
+-void scsi_end_bidi_request(struct scsi_cmnd *cmd)
++static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
+ {
+ 	struct request *req = cmd->request;
+ 	unsigned int dlen = req->data_len;
+@@ -839,7 +839,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 	int this_count = scsi_bufflen(cmd);
+ 	struct request_queue *q = cmd->device->request_queue;
+ 	struct request *req = cmd->request;
+-	int clear_errors = 1;
++	int error = 0;
+ 	struct scsi_sense_hdr sshdr;
+ 	int sense_valid = 0;
+ 	int sense_deferred = 0;
+@@ -853,7 +853,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 	if (blk_pc_request(req)) { /* SG_IO ioctl from block level */
+ 		req->errors = result;
+ 		if (result) {
+-			clear_errors = 0;
+ 			if (sense_valid && req->sense) {
+ 				/*
+ 				 * SG_IO wants current and deferred errors
+@@ -865,6 +864,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 				memcpy(req->sense, cmd->sense_buffer,  len);
+ 				req->sense_len = len;
+ 			}
++			if (!sense_deferred)
++				error = -EIO;
+ 		}
+ 		if (scsi_bidi_cmnd(cmd)) {
+ 			/* will also release_buffers */
+@@ -885,14 +886,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 				      "%d bytes done.\n",
+ 				      req->nr_sectors, good_bytes));
+ 
+-	if (clear_errors)
+-		req->errors = 0;
+-
+ 	/* A number of bytes were successfully read.  If there
+ 	 * are leftovers and there is some kind of error
+ 	 * (result != 0), retry the rest.
+ 	 */
+-	if (scsi_end_request(cmd, 0, good_bytes, result == 0) == NULL)
++	if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
+ 		return;
+ 
+ 	/* good_bytes = 0, or (inclusive) there were leftovers and
+diff --git a/drivers/scsi/scsi_sas_internal.h b/drivers/scsi/scsi_sas_internal.h
+index e1edab4..998cb5b 100644
+--- a/drivers/scsi/scsi_sas_internal.h
++++ b/drivers/scsi/scsi_sas_internal.h
+@@ -13,12 +13,12 @@ struct sas_internal {
+ 	struct sas_function_template *f;
+ 	struct sas_domain_function_template *dft;
+ 
+-	struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
+-	struct class_device_attribute private_phy_attrs[SAS_PHY_ATTRS];
+-	struct class_device_attribute private_port_attrs[SAS_PORT_ATTRS];
+-	struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
+-	struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
+-	struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
++	struct device_attribute private_host_attrs[SAS_HOST_ATTRS];
++	struct device_attribute private_phy_attrs[SAS_PHY_ATTRS];
++	struct device_attribute private_port_attrs[SAS_PORT_ATTRS];
++	struct device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
++	struct device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
++	struct device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
+ 
+ 	struct transport_container phy_attr_cont;
+ 	struct transport_container port_attr_cont;
+@@ -30,12 +30,12 @@ struct sas_internal {
+ 	 * The array of null terminated pointers to attributes
+ 	 * needed by scsi_sysfs.c
+ 	 */
+-	struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
+-	struct class_device_attribute *phy_attrs[SAS_PHY_ATTRS + 1];
+-	struct class_device_attribute *port_attrs[SAS_PORT_ATTRS + 1];
+-	struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
+-	struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
+-	struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
++	struct device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
++	struct device_attribute *phy_attrs[SAS_PHY_ATTRS + 1];
++	struct device_attribute *port_attrs[SAS_PORT_ATTRS + 1];
++	struct device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
++	struct device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
++	struct device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
+ };
+ #define to_sas_internal(tmpl)	container_of(tmpl, struct sas_internal, t)
+ 
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index ed83cdb..67bb20e 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -119,9 +119,10 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str)
+  */
+ #define shost_show_function(name, field, format_string)			\
+ static ssize_t								\
+-show_##name (struct class_device *class_dev, char *buf)			\
++show_##name (struct device *dev, struct device_attribute *attr, 	\
++	     char *buf)							\
+ {									\
+-	struct Scsi_Host *shost = class_to_shost(class_dev);		\
++	struct Scsi_Host *shost = class_to_shost(dev);			\
+ 	return snprintf (buf, 20, format_string, shost->field);		\
+ }
+ 
+@@ -131,7 +132,7 @@ show_##name (struct class_device *class_dev, char *buf)			\
+  */
+ #define shost_rd_attr2(name, field, format_string)			\
+ 	shost_show_function(name, field, format_string)			\
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
++static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
+ 
+ #define shost_rd_attr(field, format_string) \
+ shost_rd_attr2(field, field, format_string)
+@@ -140,10 +141,11 @@ shost_rd_attr2(field, field, format_string)
+  * Create the actual show/store functions and data structures.
+  */
+ 
+-static ssize_t store_scan(struct class_device *class_dev, const char *buf,
+-			  size_t count)
++static ssize_t
++store_scan(struct device *dev, struct device_attribute *attr,
++	   const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	int res;
+ 
+ 	res = scsi_scan(shost, buf);
+@@ -151,13 +153,14 @@ static ssize_t store_scan(struct class_device *class_dev, const char *buf,
+ 		res = count;
+ 	return res;
+ };
+-static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
++static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
+ 
+ static ssize_t
+-store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
++store_shost_state(struct device *dev, struct device_attribute *attr,
++		  const char *buf, size_t count)
+ {
+ 	int i;
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	enum scsi_host_state state = 0;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(shost_states); i++) {
+@@ -177,9 +180,9 @@ store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
+ }
+ 
+ static ssize_t
+-show_shost_state(struct class_device *class_dev, char *buf)
++show_shost_state(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	const char *name = scsi_host_state_name(shost->shost_state);
+ 
+ 	if (!name)
+@@ -188,7 +191,9 @@ show_shost_state(struct class_device *class_dev, char *buf)
+ 	return snprintf(buf, 20, "%s\n", name);
+ }
+ 
+-static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
++/* DEVICE_ATTR(state) clashes with dev_attr_state for sdev */
++struct device_attribute dev_attr_hstate =
++	__ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
+ 
+ static ssize_t
+ show_shost_mode(unsigned int mode, char *buf)
+@@ -206,9 +211,11 @@ show_shost_mode(unsigned int mode, char *buf)
+ 	return len;
+ }
+ 
+-static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *buf)
++static ssize_t
++show_shost_supported_mode(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 	unsigned int supported_mode = shost->hostt->supported_mode;
+ 
+ 	if (supported_mode == MODE_UNKNOWN)
+@@ -218,11 +225,13 @@ static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *b
+ 	return show_shost_mode(supported_mode, buf);
+ }
+ 
+-static CLASS_DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
++static DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
+ 
+-static ssize_t show_shost_active_mode(struct class_device *class_dev, char *buf)
++static ssize_t
++show_shost_active_mode(struct device *dev,
++		       struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = class_to_shost(class_dev);
++	struct Scsi_Host *shost = class_to_shost(dev);
+ 
+ 	if (shost->active_mode == MODE_UNKNOWN)
+ 		return snprintf(buf, 20, "unknown\n");
+@@ -230,7 +239,7 @@ static ssize_t show_shost_active_mode(struct class_device *class_dev, char *buf)
+ 		return show_shost_mode(shost->active_mode, buf);
+ }
+ 
+-static CLASS_DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
++static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
+ 
+ shost_rd_attr(unique_id, "%u\n");
+ shost_rd_attr(host_busy, "%hu\n");
+@@ -240,22 +249,22 @@ shost_rd_attr(sg_tablesize, "%hu\n");
+ shost_rd_attr(unchecked_isa_dma, "%d\n");
+ shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
+ 
+-static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
+-	&class_device_attr_unique_id,
+-	&class_device_attr_host_busy,
+-	&class_device_attr_cmd_per_lun,
+-	&class_device_attr_can_queue,
+-	&class_device_attr_sg_tablesize,
+-	&class_device_attr_unchecked_isa_dma,
+-	&class_device_attr_proc_name,
+-	&class_device_attr_scan,
+-	&class_device_attr_state,
+-	&class_device_attr_supported_mode,
+-	&class_device_attr_active_mode,
++static struct device_attribute *scsi_sysfs_shost_attrs[] = {
++	&dev_attr_unique_id,
++	&dev_attr_host_busy,
++	&dev_attr_cmd_per_lun,
++	&dev_attr_can_queue,
++	&dev_attr_sg_tablesize,
++	&dev_attr_unchecked_isa_dma,
++	&dev_attr_proc_name,
++	&dev_attr_scan,
++	&dev_attr_hstate,
++	&dev_attr_supported_mode,
++	&dev_attr_active_mode,
+ 	NULL
+ };
+ 
+-static void scsi_device_cls_release(struct class_device *class_dev)
++static void scsi_device_cls_release(struct device *class_dev)
+ {
+ 	struct scsi_device *sdev;
+ 
+@@ -320,7 +329,7 @@ static void scsi_device_dev_release(struct device *dev)
+ 
+ static struct class sdev_class = {
+ 	.name		= "scsi_device",
+-	.release	= scsi_device_cls_release,
++	.dev_release	= scsi_device_cls_release,
+ };
+ 
+ /* all probing is done in the individual ->probe routines */
+@@ -424,7 +433,8 @@ void scsi_sysfs_unregister(void)
+  */
+ #define sdev_show_function(field, format_string)				\
+ static ssize_t								\
+-sdev_show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
++sdev_show_##field (struct device *dev, struct device_attribute *attr,	\
++		   char *buf)						\
+ {									\
+ 	struct scsi_device *sdev;					\
+ 	sdev = to_scsi_device(dev);					\
+@@ -448,7 +458,8 @@ static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
+ 	sdev_show_function(field, format_string)				\
+ 									\
+ static ssize_t								\
+-sdev_store_##field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
++sdev_store_##field (struct device *dev, struct device_attribute *attr,	\
++		    const char *buf, size_t count)			\
+ {									\
+ 	struct scsi_device *sdev;					\
+ 	sdev = to_scsi_device(dev);					\
+@@ -468,7 +479,8 @@ static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##fie
+ 	sdev_show_function(field, "%d\n")					\
+ 									\
+ static ssize_t								\
+-sdev_store_##field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
++sdev_store_##field (struct device *dev, struct device_attribute *attr,	\
++		    const char *buf, size_t count)			\
+ {									\
+ 	int ret;							\
+ 	struct scsi_device *sdev;					\
+@@ -519,7 +531,8 @@ sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
+ }
+ 
+ static ssize_t
+-sdev_store_timeout (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++sdev_store_timeout (struct device *dev, struct device_attribute *attr,
++		    const char *buf, size_t count)
+ {
+ 	struct scsi_device *sdev;
+ 	int timeout;
+@@ -531,7 +544,8 @@ sdev_store_timeout (struct device *dev, struct device_attribute *attr, const cha
+ static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
+ 
+ static ssize_t
+-store_rescan_field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++store_rescan_field (struct device *dev, struct device_attribute *attr,
++		    const char *buf, size_t count)
+ {
+ 	scsi_rescan_device(dev);
+ 	return count;
+@@ -543,8 +557,9 @@ static void sdev_store_delete_callback(struct device *dev)
+ 	scsi_remove_device(to_scsi_device(dev));
+ }
+ 
+-static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf,
+-				 size_t count)
++static ssize_t
++sdev_store_delete(struct device *dev, struct device_attribute *attr,
++		  const char *buf, size_t count)
+ {
+ 	int rc;
+ 
+@@ -559,7 +574,8 @@ static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *at
+ static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
+ 
+ static ssize_t
+-store_state_field(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++store_state_field(struct device *dev, struct device_attribute *attr,
++		  const char *buf, size_t count)
+ {
+ 	int i;
+ 	struct scsi_device *sdev = to_scsi_device(dev);
+@@ -596,7 +612,8 @@ show_state_field(struct device *dev, struct device_attribute *attr, char *buf)
+ static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
+ 
+ static ssize_t
+-show_queue_type_field(struct device *dev, struct device_attribute *attr, char *buf)
++show_queue_type_field(struct device *dev, struct device_attribute *attr,
++		      char *buf)
+ {
+ 	struct scsi_device *sdev = to_scsi_device(dev);
+ 	const char *name = "none";
+@@ -612,7 +629,7 @@ show_queue_type_field(struct device *dev, struct device_attribute *attr, char *b
+ static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL);
+ 
+ static ssize_t
+-show_iostat_counterbits(struct device *dev, struct device_attribute *attr, char *buf)
++show_iostat_counterbits(struct device *dev, struct device_attribute *attr, 				char *buf)
+ {
+ 	return snprintf(buf, 20, "%d\n", (int)sizeof(atomic_t) * 8);
+ }
+@@ -621,7 +638,8 @@ static DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL);
+ 
+ #define show_sdev_iostat(field)						\
+ static ssize_t								\
+-show_iostat_##field(struct device *dev, struct device_attribute *attr, char *buf)			\
++show_iostat_##field(struct device *dev, struct device_attribute *attr,	\
++		    char *buf)						\
+ {									\
+ 	struct scsi_device *sdev = to_scsi_device(dev);			\
+ 	unsigned long long count = atomic_read(&sdev->field);		\
+@@ -645,7 +663,7 @@ static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
+ #define DECLARE_EVT_SHOW(name, Cap_name)				\
+ static ssize_t								\
+ sdev_show_evt_##name(struct device *dev, struct device_attribute *attr,	\
+-				char *buf)				\
++		     char *buf)						\
+ {									\
+ 	struct scsi_device *sdev = to_scsi_device(dev);			\
+ 	int val = test_bit(SDEV_EVT_##Cap_name, sdev->supported_events);\
+@@ -654,7 +672,7 @@ sdev_show_evt_##name(struct device *dev, struct device_attribute *attr,	\
+ 
+ #define DECLARE_EVT_STORE(name, Cap_name)				\
+ static ssize_t								\
+-sdev_store_evt_##name(struct device *dev, struct device_attribute *attr, \
++sdev_store_evt_##name(struct device *dev, struct device_attribute *attr,\
+ 		      const char *buf, size_t count)			\
+ {									\
+ 	struct scsi_device *sdev = to_scsi_device(dev);			\
+@@ -707,8 +725,9 @@ static struct attribute_group *scsi_sdev_attr_groups[] = {
+ 	NULL
+ };
+ 
+-static ssize_t sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr, const char *buf,
+-					 size_t count)
++static ssize_t
++sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr,
++			  const char *buf, size_t count)
+ {
+ 	int depth, retval;
+ 	struct scsi_device *sdev = to_scsi_device(dev);
+@@ -733,8 +752,9 @@ static struct device_attribute sdev_attr_queue_depth_rw =
+ 	__ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
+ 	       sdev_store_queue_depth_rw);
+ 
+-static ssize_t sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr, const char *buf,
+-					size_t count)
++static ssize_t
++sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr,
++			 const char *buf, size_t count)
+ {
+ 	struct scsi_device *sdev = to_scsi_device(dev);
+ 	struct scsi_host_template *sht = sdev->host->hostt;
+@@ -786,13 +806,13 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ 		printk(KERN_INFO "error 1\n");
+ 		return error;
+ 	}
+-	error = class_device_add(&sdev->sdev_classdev);
++	error = device_add(&sdev->sdev_dev);
+ 	if (error) {
+ 		printk(KERN_INFO "error 2\n");
+ 		goto clean_device;
+ 	}
+ 
+-	/* take a reference for the sdev_classdev; this is
++	/* take a reference for the sdev_dev; this is
+ 	 * released by the sdev_class .release */
+ 	get_device(&sdev->sdev_gendev);
+ 
+@@ -858,7 +878,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
+ 		return;
+ 
+ 	bsg_unregister_queue(sdev->request_queue);
+-	class_device_unregister(&sdev->sdev_classdev);
++	device_unregister(&sdev->sdev_dev);
+ 	transport_remove_device(dev);
+ 	device_del(dev);
+ 	scsi_device_set_state(sdev, SDEV_DEL);
+@@ -952,9 +972,9 @@ int scsi_register_interface(struct class_interface *intf)
+ EXPORT_SYMBOL(scsi_register_interface);
+ 
+ 
+-static struct class_device_attribute *class_attr_overridden(
+-		struct class_device_attribute **attrs,
+-		struct class_device_attribute *attr)
++static struct device_attribute *class_attr_overridden(
++		struct device_attribute **attrs,
++		struct device_attribute *attr)
+ {
+ 	int i;
+ 
+@@ -966,10 +986,10 @@ static struct class_device_attribute *class_attr_overridden(
+ 	return NULL;
+ }
+ 
+-static int class_attr_add(struct class_device *classdev,
+-		struct class_device_attribute *attr)
++static int class_attr_add(struct device *classdev,
++		struct device_attribute *attr)
+ {
+-	struct class_device_attribute *base_attr;
++	struct device_attribute *base_attr;
+ 
+ 	/*
+ 	 * Spare the caller from having to copy things it's not interested in.
+@@ -986,7 +1006,7 @@ static int class_attr_add(struct class_device *classdev,
+ 			attr->store = base_attr->store;
+ 	}
+ 
+-	return class_device_create_file(classdev, attr);
++	return device_create_file(classdev, attr);
+ }
+ 
+ /**
+@@ -1000,7 +1020,7 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
+ 
+ 	if (shost->hostt->shost_attrs) {
+ 		for (i = 0; shost->hostt->shost_attrs[i]; i++) {
+-			error = class_attr_add(&shost->shost_classdev,
++			error = class_attr_add(&shost->shost_dev,
+ 					shost->hostt->shost_attrs[i]);
+ 			if (error)
+ 				return error;
+@@ -1010,7 +1030,7 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
+ 	for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
+ 		if (!class_attr_overridden(shost->hostt->shost_attrs,
+ 					scsi_sysfs_shost_attrs[i])) {
+-			error = class_device_create_file(&shost->shost_classdev,
++			error = device_create_file(&shost->shost_dev,
+ 					scsi_sysfs_shost_attrs[i]);
+ 			if (error)
+ 				return error;
+@@ -1041,10 +1061,10 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
+ 		sdev->host->host_no, sdev->channel, sdev->id,
+ 		sdev->lun);
+ 	
+-	class_device_initialize(&sdev->sdev_classdev);
+-	sdev->sdev_classdev.dev = &sdev->sdev_gendev;
+-	sdev->sdev_classdev.class = &sdev_class;
+-	snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
++	device_initialize(&sdev->sdev_dev);
++	sdev->sdev_dev.parent = &sdev->sdev_gendev;
++	sdev->sdev_dev.class = &sdev_class;
++	snprintf(sdev->sdev_dev.bus_id, BUS_ID_SIZE,
+ 		 "%d:%d:%d:%d", sdev->host->host_no,
+ 		 sdev->channel, sdev->id, sdev->lun);
+ 	sdev->scsi_level = starget->scsi_level;
+diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
+index a0f308b..ee8496a 100644
+--- a/drivers/scsi/scsi_tgt_lib.c
++++ b/drivers/scsi/scsi_tgt_lib.c
+@@ -621,9 +621,7 @@ static int __init scsi_tgt_init(void)
+ {
+ 	int err;
+ 
+-	scsi_tgt_cmd_cache = kmem_cache_create("scsi_tgt_cmd",
+-					       sizeof(struct scsi_tgt_cmd),
+-					       0, 0, NULL);
++	scsi_tgt_cmd_cache =  KMEM_CACHE(scsi_tgt_cmd, 0);
+ 	if (!scsi_tgt_cmd_cache)
+ 		return -ENOMEM;
+ 
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index b1119da..6b092a6 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -72,8 +72,8 @@ static int fc_vport_create(struct Scsi_Host *shost, int channel,
+  * Redefine so that we can have same named attributes in the
+  * sdev/starget/host objects.
+  */
+-#define FC_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store)		\
+-struct class_device_attribute class_device_attr_##_prefix##_##_name = 	\
++#define FC_DEVICE_ATTR(_prefix,_name,_mode,_show,_store)		\
++struct device_attribute device_attr_##_prefix##_##_name = 	\
+ 	__ATTR(_name,_mode,_show,_store)
+ 
+ #define fc_enum_name_search(title, table_type, table)			\
+@@ -326,26 +326,26 @@ struct fc_internal {
+ 	 * part of the midlayer. As the remote port is specific to the
+ 	 * fc transport, we must provide the attribute container.
+ 	 */
+-	struct class_device_attribute private_starget_attrs[
++	struct device_attribute private_starget_attrs[
+ 							FC_STARGET_NUM_ATTRS];
+-	struct class_device_attribute *starget_attrs[FC_STARGET_NUM_ATTRS + 1];
++	struct device_attribute *starget_attrs[FC_STARGET_NUM_ATTRS + 1];
+ 
+-	struct class_device_attribute private_host_attrs[FC_HOST_NUM_ATTRS];
+-	struct class_device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1];
++	struct device_attribute private_host_attrs[FC_HOST_NUM_ATTRS];
++	struct device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1];
+ 
+ 	struct transport_container rport_attr_cont;
+-	struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
+-	struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
++	struct device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
++	struct device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
+ 
+ 	struct transport_container vport_attr_cont;
+-	struct class_device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
+-	struct class_device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
++	struct device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
++	struct device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
+ };
+ 
+ #define to_fc_internal(tmpl)	container_of(tmpl, struct fc_internal, t)
+ 
+ static int fc_target_setup(struct transport_container *tc, struct device *dev,
+-			   struct class_device *cdev)
++			   struct device *cdev)
+ {
+ 	struct scsi_target *starget = to_scsi_target(dev);
+ 	struct fc_rport *rport = starget_to_rport(starget);
+@@ -375,7 +375,7 @@ static DECLARE_TRANSPORT_CLASS(fc_transport_class,
+ 			       NULL);
+ 
+ static int fc_host_setup(struct transport_container *tc, struct device *dev,
+-			 struct class_device *cdev)
++			 struct device *cdev)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+@@ -682,9 +682,10 @@ static void __exit fc_transport_exit(void)
+ 
+ #define fc_rport_show_function(field, format_string, sz, cast)		\
+ static ssize_t								\
+-show_fc_rport_##field (struct class_device *cdev, char *buf)		\
++show_fc_rport_##field (struct device *dev, 				\
++		       struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct fc_rport *rport = transport_class_to_rport(cdev);	\
++	struct fc_rport *rport = transport_class_to_rport(dev);		\
+ 	struct Scsi_Host *shost = rport_to_shost(rport);		\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	if ((i->f->get_rport_##field) &&				\
+@@ -697,11 +698,12 @@ show_fc_rport_##field (struct class_device *cdev, char *buf)		\
+ 
+ #define fc_rport_store_function(field)					\
+ static ssize_t								\
+-store_fc_rport_##field(struct class_device *cdev, const char *buf,	\
+-			   size_t count)				\
++store_fc_rport_##field(struct device *dev,				\
++		       struct device_attribute *attr,			\
++		       const char *buf,	size_t count)			\
+ {									\
+ 	int val;							\
+-	struct fc_rport *rport = transport_class_to_rport(cdev);	\
++	struct fc_rport *rport = transport_class_to_rport(dev);		\
+ 	struct Scsi_Host *shost = rport_to_shost(rport);		\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	char *cp;							\
+@@ -718,58 +720,60 @@ store_fc_rport_##field(struct class_device *cdev, const char *buf,	\
+ 
+ #define fc_rport_rd_attr(field, format_string, sz)			\
+ 	fc_rport_show_function(field, format_string, sz, )		\
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(rport, field, S_IRUGO,			\
+ 			 show_fc_rport_##field, NULL)
+ 
+ #define fc_rport_rd_attr_cast(field, format_string, sz, cast)		\
+ 	fc_rport_show_function(field, format_string, sz, (cast))	\
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(rport, field, S_IRUGO,			\
+ 			  show_fc_rport_##field, NULL)
+ 
+ #define fc_rport_rw_attr(field, format_string, sz)			\
+ 	fc_rport_show_function(field, format_string, sz, )		\
+ 	fc_rport_store_function(field)					\
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO | S_IWUSR,		\
++static FC_DEVICE_ATTR(rport, field, S_IRUGO | S_IWUSR,		\
+ 			show_fc_rport_##field,				\
+ 			store_fc_rport_##field)
+ 
+ 
+ #define fc_private_rport_show_function(field, format_string, sz, cast)	\
+ static ssize_t								\
+-show_fc_rport_##field (struct class_device *cdev, char *buf)		\
++show_fc_rport_##field (struct device *dev, 				\
++		       struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct fc_rport *rport = transport_class_to_rport(cdev);	\
++	struct fc_rport *rport = transport_class_to_rport(dev);		\
+ 	return snprintf(buf, sz, format_string, cast rport->field); 	\
+ }
+ 
+ #define fc_private_rport_rd_attr(field, format_string, sz)		\
+ 	fc_private_rport_show_function(field, format_string, sz, )	\
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(rport, field, S_IRUGO,			\
+ 			 show_fc_rport_##field, NULL)
+ 
+ #define fc_private_rport_rd_attr_cast(field, format_string, sz, cast)	\
+ 	fc_private_rport_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(rport, field, S_IRUGO,			\
+ 			  show_fc_rport_##field, NULL)
+ 
+ 
+ #define fc_private_rport_rd_enum_attr(title, maxlen)			\
+ static ssize_t								\
+-show_fc_rport_##title (struct class_device *cdev, char *buf)		\
++show_fc_rport_##title (struct device *dev,				\
++		       struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct fc_rport *rport = transport_class_to_rport(cdev);	\
++	struct fc_rport *rport = transport_class_to_rport(dev);		\
+ 	const char *name;						\
+ 	name = get_fc_##title##_name(rport->title);			\
+ 	if (!name)							\
+ 		return -EINVAL;						\
+ 	return snprintf(buf, maxlen, "%s\n", name);			\
+ }									\
+-static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO,			\
++static FC_DEVICE_ATTR(rport, title, S_IRUGO,			\
+ 			show_fc_rport_##title, NULL)
+ 
+ 
+ #define SETUP_RPORT_ATTRIBUTE_RD(field)					\
+-	i->private_rport_attrs[count] = class_device_attr_rport_##field; \
++	i->private_rport_attrs[count] = device_attr_rport_##field; \
+ 	i->private_rport_attrs[count].attr.mode = S_IRUGO;		\
+ 	i->private_rport_attrs[count].store = NULL;			\
+ 	i->rport_attrs[count] = &i->private_rport_attrs[count];		\
+@@ -777,14 +781,14 @@ static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO,			\
+ 		count++
+ 
+ #define SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(field)				\
+-	i->private_rport_attrs[count] = class_device_attr_rport_##field; \
++	i->private_rport_attrs[count] = device_attr_rport_##field; \
+ 	i->private_rport_attrs[count].attr.mode = S_IRUGO;		\
+ 	i->private_rport_attrs[count].store = NULL;			\
+ 	i->rport_attrs[count] = &i->private_rport_attrs[count];		\
+ 	count++
+ 
+ #define SETUP_RPORT_ATTRIBUTE_RW(field)					\
+-	i->private_rport_attrs[count] = class_device_attr_rport_##field; \
++	i->private_rport_attrs[count] = device_attr_rport_##field; \
+ 	if (!i->f->set_rport_##field) {					\
+ 		i->private_rport_attrs[count].attr.mode = S_IRUGO;	\
+ 		i->private_rport_attrs[count].store = NULL;		\
+@@ -795,7 +799,7 @@ static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO,			\
+ 
+ #define SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(field)				\
+ {									\
+-	i->private_rport_attrs[count] = class_device_attr_rport_##field; \
++	i->private_rport_attrs[count] = device_attr_rport_##field; \
+ 	i->rport_attrs[count] = &i->private_rport_attrs[count];		\
+ 	count++;							\
+ }
+@@ -808,14 +812,15 @@ static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO,			\
+ fc_private_rport_rd_attr(maxframe_size, "%u bytes\n", 20);
+ 
+ static ssize_t
+-show_fc_rport_supported_classes (struct class_device *cdev, char *buf)
++show_fc_rport_supported_classes (struct device *dev,
++				 struct device_attribute *attr, char *buf)
+ {
+-	struct fc_rport *rport = transport_class_to_rport(cdev);
++	struct fc_rport *rport = transport_class_to_rport(dev);
+ 	if (rport->supported_classes == FC_COS_UNSPECIFIED)
+ 		return snprintf(buf, 20, "unspecified\n");
+ 	return get_fc_cos_names(rport->supported_classes, buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
++static FC_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
+ 		show_fc_rport_supported_classes, NULL);
+ 
+ /* Dynamic Remote Port Attributes */
+@@ -825,11 +830,11 @@ static FC_CLASS_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
+  */
+ fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
+ static ssize_t
+-store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
+-			   size_t count)
++store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
++			    const char *buf, size_t count)
+ {
+ 	int val;
+-	struct fc_rport *rport = transport_class_to_rport(cdev);
++	struct fc_rport *rport = transport_class_to_rport(dev);
+ 	struct Scsi_Host *shost = rport_to_shost(rport);
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);
+ 	char *cp;
+@@ -844,7 +849,7 @@ store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
+ 	i->f->set_rport_dev_loss_tmo(rport, val);
+ 	return count;
+ }
+-static FC_CLASS_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
+ 		show_fc_rport_dev_loss_tmo, store_fc_rport_dev_loss_tmo);
+ 
+ 
+@@ -855,9 +860,10 @@ fc_private_rport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+ fc_private_rport_rd_attr(port_id, "0x%06x\n", 20);
+ 
+ static ssize_t
+-show_fc_rport_roles (struct class_device *cdev, char *buf)
++show_fc_rport_roles (struct device *dev, struct device_attribute *attr,
++		     char *buf)
+ {
+-	struct fc_rport *rport = transport_class_to_rport(cdev);
++	struct fc_rport *rport = transport_class_to_rport(dev);
+ 
+ 	/* identify any roles that are port_id specific */
+ 	if ((rport->port_id != -1) &&
+@@ -883,7 +889,7 @@ show_fc_rport_roles (struct class_device *cdev, char *buf)
+ 		return get_fc_port_roles_names(rport->roles, buf);
+ 	}
+ }
+-static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
++static FC_DEVICE_ATTR(rport, roles, S_IRUGO,
+ 		show_fc_rport_roles, NULL);
+ 
+ fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
+@@ -893,9 +899,10 @@ fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20);
+  * fast_io_fail_tmo attribute
+  */
+ static ssize_t
+-show_fc_rport_fast_io_fail_tmo (struct class_device *cdev, char *buf)
++show_fc_rport_fast_io_fail_tmo (struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+-	struct fc_rport *rport = transport_class_to_rport(cdev);
++	struct fc_rport *rport = transport_class_to_rport(dev);
+ 
+ 	if (rport->fast_io_fail_tmo == -1)
+ 		return snprintf(buf, 5, "off\n");
+@@ -903,12 +910,13 @@ show_fc_rport_fast_io_fail_tmo (struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-store_fc_rport_fast_io_fail_tmo(struct class_device *cdev, const char *buf,
+-			   size_t count)
++store_fc_rport_fast_io_fail_tmo(struct device *dev,
++				struct device_attribute *attr, const char *buf,
++				size_t count)
+ {
+ 	int val;
+ 	char *cp;
+-	struct fc_rport *rport = transport_class_to_rport(cdev);
++	struct fc_rport *rport = transport_class_to_rport(dev);
+ 
+ 	if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
+ 	    (rport->port_state == FC_PORTSTATE_DELETED) ||
+@@ -925,7 +933,7 @@ store_fc_rport_fast_io_fail_tmo(struct class_device *cdev, const char *buf,
+ 	}
+ 	return count;
+ }
+-static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
+ 	show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);
+ 
+ 
+@@ -941,9 +949,10 @@ static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
+  */
+ #define fc_starget_show_function(field, format_string, sz, cast)	\
+ static ssize_t								\
+-show_fc_starget_##field (struct class_device *cdev, char *buf)		\
++show_fc_starget_##field (struct device *dev, 				\
++			 struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct scsi_target *starget = transport_class_to_starget(cdev);	\
++	struct scsi_target *starget = transport_class_to_starget(dev);	\
+ 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);	\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	struct fc_rport *rport = starget_to_rport(starget);		\
+@@ -957,16 +966,16 @@ show_fc_starget_##field (struct class_device *cdev, char *buf)		\
+ 
+ #define fc_starget_rd_attr(field, format_string, sz)			\
+ 	fc_starget_show_function(field, format_string, sz, )		\
+-static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(starget, field, S_IRUGO,			\
+ 			 show_fc_starget_##field, NULL)
+ 
+ #define fc_starget_rd_attr_cast(field, format_string, sz, cast)		\
+ 	fc_starget_show_function(field, format_string, sz, (cast))	\
+-static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(starget, field, S_IRUGO,			\
+ 			  show_fc_starget_##field, NULL)
+ 
+ #define SETUP_STARGET_ATTRIBUTE_RD(field)				\
+-	i->private_starget_attrs[count] = class_device_attr_starget_##field; \
++	i->private_starget_attrs[count] = device_attr_starget_##field; \
+ 	i->private_starget_attrs[count].attr.mode = S_IRUGO;		\
+ 	i->private_starget_attrs[count].store = NULL;			\
+ 	i->starget_attrs[count] = &i->private_starget_attrs[count];	\
+@@ -974,7 +983,7 @@ static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO,			\
+ 		count++
+ 
+ #define SETUP_STARGET_ATTRIBUTE_RW(field)				\
+-	i->private_starget_attrs[count] = class_device_attr_starget_##field; \
++	i->private_starget_attrs[count] = device_attr_starget_##field; \
+ 	if (!i->f->set_starget_##field) {				\
+ 		i->private_starget_attrs[count].attr.mode = S_IRUGO;	\
+ 		i->private_starget_attrs[count].store = NULL;		\
+@@ -995,9 +1004,10 @@ fc_starget_rd_attr(port_id, "0x%06x\n", 20);
+ 
+ #define fc_vport_show_function(field, format_string, sz, cast)		\
+ static ssize_t								\
+-show_fc_vport_##field (struct class_device *cdev, char *buf)		\
++show_fc_vport_##field (struct device *dev, 				\
++		       struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct fc_vport *vport = transport_class_to_vport(cdev);	\
++	struct fc_vport *vport = transport_class_to_vport(dev);		\
+ 	struct Scsi_Host *shost = vport_to_shost(vport);		\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	if ((i->f->get_vport_##field) &&				\
+@@ -1008,11 +1018,12 @@ show_fc_vport_##field (struct class_device *cdev, char *buf)		\
+ 
+ #define fc_vport_store_function(field)					\
+ static ssize_t								\
+-store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+-			   size_t count)				\
++store_fc_vport_##field(struct device *dev,				\
++		       struct device_attribute *attr,			\
++		       const char *buf,	size_t count)			\
+ {									\
+ 	int val;							\
+-	struct fc_vport *vport = transport_class_to_vport(cdev);	\
++	struct fc_vport *vport = transport_class_to_vport(dev);		\
+ 	struct Scsi_Host *shost = vport_to_shost(vport);		\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	char *cp;							\
+@@ -1027,10 +1038,11 @@ store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+ 
+ #define fc_vport_store_str_function(field, slen)			\
+ static ssize_t								\
+-store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+-			   size_t count)				\
++store_fc_vport_##field(struct device *dev,				\
++		       struct device_attribute *attr, 			\
++		       const char *buf,	size_t count)			\
+ {									\
+-	struct fc_vport *vport = transport_class_to_vport(cdev);	\
++	struct fc_vport *vport = transport_class_to_vport(dev);		\
+ 	struct Scsi_Host *shost = vport_to_shost(vport);		\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	unsigned int cnt=count;						\
+@@ -1047,36 +1059,38 @@ store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+ 
+ #define fc_vport_rd_attr(field, format_string, sz)			\
+ 	fc_vport_show_function(field, format_string, sz, )		\
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(vport, field, S_IRUGO,			\
+ 			 show_fc_vport_##field, NULL)
+ 
+ #define fc_vport_rd_attr_cast(field, format_string, sz, cast)		\
+ 	fc_vport_show_function(field, format_string, sz, (cast))	\
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(vport, field, S_IRUGO,			\
+ 			  show_fc_vport_##field, NULL)
+ 
+ #define fc_vport_rw_attr(field, format_string, sz)			\
+ 	fc_vport_show_function(field, format_string, sz, )		\
+ 	fc_vport_store_function(field)					\
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\
++static FC_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\
+ 			show_fc_vport_##field,				\
+ 			store_fc_vport_##field)
+ 
+ #define fc_private_vport_show_function(field, format_string, sz, cast)	\
+ static ssize_t								\
+-show_fc_vport_##field (struct class_device *cdev, char *buf)		\
++show_fc_vport_##field (struct device *dev,				\
++		       struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct fc_vport *vport = transport_class_to_vport(cdev);	\
++	struct fc_vport *vport = transport_class_to_vport(dev);		\
+ 	return snprintf(buf, sz, format_string, cast vport->field); 	\
+ }
+ 
+ #define fc_private_vport_store_u32_function(field)			\
+ static ssize_t								\
+-store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+-			   size_t count)				\
++store_fc_vport_##field(struct device *dev,				\
++		       struct device_attribute *attr,			\
++		       const char *buf,	size_t count)			\
+ {									\
+ 	u32 val;							\
+-	struct fc_vport *vport = transport_class_to_vport(cdev);	\
++	struct fc_vport *vport = transport_class_to_vport(dev);		\
+ 	char *cp;							\
+ 	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))		\
+ 		return -EBUSY;						\
+@@ -1090,39 +1104,41 @@ store_fc_vport_##field(struct class_device *cdev, const char *buf,	\
+ 
+ #define fc_private_vport_rd_attr(field, format_string, sz)		\
+ 	fc_private_vport_show_function(field, format_string, sz, )	\
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(vport, field, S_IRUGO,			\
+ 			 show_fc_vport_##field, NULL)
+ 
+ #define fc_private_vport_rd_attr_cast(field, format_string, sz, cast)	\
+ 	fc_private_vport_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(vport, field, S_IRUGO,			\
+ 			  show_fc_vport_##field, NULL)
+ 
+ #define fc_private_vport_rw_u32_attr(field, format_string, sz)		\
+ 	fc_private_vport_show_function(field, format_string, sz, )	\
+ 	fc_private_vport_store_u32_function(field)			\
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\
++static FC_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR,		\
+ 			show_fc_vport_##field,				\
+ 			store_fc_vport_##field)
+ 
+ 
+ #define fc_private_vport_rd_enum_attr(title, maxlen)			\
+ static ssize_t								\
+-show_fc_vport_##title (struct class_device *cdev, char *buf)		\
++show_fc_vport_##title (struct device *dev,				\
++		       struct device_attribute *attr,			\
++		       char *buf)					\
+ {									\
+-	struct fc_vport *vport = transport_class_to_vport(cdev);	\
++	struct fc_vport *vport = transport_class_to_vport(dev);		\
+ 	const char *name;						\
+ 	name = get_fc_##title##_name(vport->title);			\
+ 	if (!name)							\
+ 		return -EINVAL;						\
+ 	return snprintf(buf, maxlen, "%s\n", name);			\
+ }									\
+-static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO,			\
++static FC_DEVICE_ATTR(vport, title, S_IRUGO,			\
+ 			show_fc_vport_##title, NULL)
+ 
+ 
+ #define SETUP_VPORT_ATTRIBUTE_RD(field)					\
+-	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++	i->private_vport_attrs[count] = device_attr_vport_##field; \
+ 	i->private_vport_attrs[count].attr.mode = S_IRUGO;		\
+ 	i->private_vport_attrs[count].store = NULL;			\
+ 	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+@@ -1131,21 +1147,21 @@ static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO,			\
+ 	/* NOTE: Above MACRO differs: checks function not show bit */
+ 
+ #define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field)				\
+-	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++	i->private_vport_attrs[count] = device_attr_vport_##field; \
+ 	i->private_vport_attrs[count].attr.mode = S_IRUGO;		\
+ 	i->private_vport_attrs[count].store = NULL;			\
+ 	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+ 	count++
+ 
+ #define SETUP_VPORT_ATTRIBUTE_WR(field)					\
+-	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++	i->private_vport_attrs[count] = device_attr_vport_##field; \
+ 	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+ 	if (i->f->field)						\
+ 		count++
+ 	/* NOTE: Above MACRO differs: checks function */
+ 
+ #define SETUP_VPORT_ATTRIBUTE_RW(field)					\
+-	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++	i->private_vport_attrs[count] = device_attr_vport_##field; \
+ 	if (!i->f->set_vport_##field) {					\
+ 		i->private_vport_attrs[count].attr.mode = S_IRUGO;	\
+ 		i->private_vport_attrs[count].store = NULL;		\
+@@ -1156,7 +1172,7 @@ static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO,			\
+ 
+ #define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field)				\
+ {									\
+-	i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++	i->private_vport_attrs[count] = device_attr_vport_##field; \
+ 	i->vport_attrs[count] = &i->private_vport_attrs[count];		\
+ 	count++;							\
+ }
+@@ -1176,35 +1192,36 @@ fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
+ fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+ 
+ static ssize_t
+-show_fc_vport_roles (struct class_device *cdev, char *buf)
++show_fc_vport_roles (struct device *dev, struct device_attribute *attr,
++		     char *buf)
+ {
+-	struct fc_vport *vport = transport_class_to_vport(cdev);
++	struct fc_vport *vport = transport_class_to_vport(dev);
+ 
+ 	if (vport->roles == FC_PORT_ROLE_UNKNOWN)
+ 		return snprintf(buf, 20, "unknown\n");
+ 	return get_fc_port_roles_names(vport->roles, buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
++static FC_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
+ 
+ fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
+ 
+ fc_private_vport_show_function(symbolic_name, "%s\n",
+ 		FC_VPORT_SYMBOLIC_NAMELEN + 1, )
+ fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)
+-static FC_CLASS_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
+ 		show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);
+ 
+ static ssize_t
+-store_fc_vport_delete(struct class_device *cdev, const char *buf,
+-			   size_t count)
++store_fc_vport_delete(struct device *dev, struct device_attribute *attr,
++		      const char *buf, size_t count)
+ {
+-	struct fc_vport *vport = transport_class_to_vport(cdev);
++	struct fc_vport *vport = transport_class_to_vport(dev);
+ 	struct Scsi_Host *shost = vport_to_shost(vport);
+ 
+ 	fc_queue_work(shost, &vport->vport_delete_work);
+ 	return count;
+ }
+-static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
++static FC_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
+ 			NULL, store_fc_vport_delete);
+ 
+ 
+@@ -1213,10 +1230,11 @@ static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
+  *  Write "1" to disable, write "0" to enable
+  */
+ static ssize_t
+-store_fc_vport_disable(struct class_device *cdev, const char *buf,
++store_fc_vport_disable(struct device *dev, struct device_attribute *attr,
++		       const char *buf,
+ 			   size_t count)
+ {
+-	struct fc_vport *vport = transport_class_to_vport(cdev);
++	struct fc_vport *vport = transport_class_to_vport(dev);
+ 	struct Scsi_Host *shost = vport_to_shost(vport);
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);
+ 	int stat;
+@@ -1236,7 +1254,7 @@ store_fc_vport_disable(struct class_device *cdev, const char *buf,
+ 	stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));
+ 	return stat ? stat : count;
+ }
+-static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
++static FC_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
+ 			NULL, store_fc_vport_disable);
+ 
+ 
+@@ -1246,9 +1264,10 @@ static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
+ 
+ #define fc_host_show_function(field, format_string, sz, cast)		\
+ static ssize_t								\
+-show_fc_host_##field (struct class_device *cdev, char *buf)		\
++show_fc_host_##field (struct device *dev,				\
++		      struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);	\
++	struct Scsi_Host *shost = transport_class_to_shost(dev);	\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	if (i->f->get_host_##field)					\
+ 		i->f->get_host_##field(shost);				\
+@@ -1257,11 +1276,12 @@ show_fc_host_##field (struct class_device *cdev, char *buf)		\
+ 
+ #define fc_host_store_function(field)					\
+ static ssize_t								\
+-store_fc_host_##field(struct class_device *cdev, const char *buf,	\
+-			   size_t count)				\
++store_fc_host_##field(struct device *dev, 				\
++		      struct device_attribute *attr,			\
++		      const char *buf,	size_t count)			\
+ {									\
+ 	int val;							\
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);	\
++	struct Scsi_Host *shost = transport_class_to_shost(dev);	\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	char *cp;							\
+ 									\
+@@ -1274,10 +1294,11 @@ store_fc_host_##field(struct class_device *cdev, const char *buf,	\
+ 
+ #define fc_host_store_str_function(field, slen)				\
+ static ssize_t								\
+-store_fc_host_##field(struct class_device *cdev, const char *buf,	\
+-			   size_t count)				\
++store_fc_host_##field(struct device *dev,				\
++		      struct device_attribute *attr,			\
++		      const char *buf, size_t count)			\
+ {									\
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);	\
++	struct Scsi_Host *shost = transport_class_to_shost(dev);	\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	unsigned int cnt=count;						\
+ 									\
+@@ -1293,26 +1314,27 @@ store_fc_host_##field(struct class_device *cdev, const char *buf,	\
+ 
+ #define fc_host_rd_attr(field, format_string, sz)			\
+ 	fc_host_show_function(field, format_string, sz, )		\
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(host, field, S_IRUGO,			\
+ 			 show_fc_host_##field, NULL)
+ 
+ #define fc_host_rd_attr_cast(field, format_string, sz, cast)		\
+ 	fc_host_show_function(field, format_string, sz, (cast))		\
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(host, field, S_IRUGO,			\
+ 			  show_fc_host_##field, NULL)
+ 
+ #define fc_host_rw_attr(field, format_string, sz)			\
+ 	fc_host_show_function(field, format_string, sz, )		\
+ 	fc_host_store_function(field)					\
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO | S_IWUSR,		\
++static FC_DEVICE_ATTR(host, field, S_IRUGO | S_IWUSR,		\
+ 			show_fc_host_##field,				\
+ 			store_fc_host_##field)
+ 
+ #define fc_host_rd_enum_attr(title, maxlen)				\
+ static ssize_t								\
+-show_fc_host_##title (struct class_device *cdev, char *buf)		\
++show_fc_host_##title (struct device *dev,				\
++		      struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);	\
++	struct Scsi_Host *shost = transport_class_to_shost(dev);	\
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);	\
+ 	const char *name;						\
+ 	if (i->f->get_host_##title)					\
+@@ -1322,10 +1344,10 @@ show_fc_host_##title (struct class_device *cdev, char *buf)		\
+ 		return -EINVAL;						\
+ 	return snprintf(buf, maxlen, "%s\n", name);			\
+ }									\
+-static FC_CLASS_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
++static FC_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
+ 
+ #define SETUP_HOST_ATTRIBUTE_RD(field)					\
+-	i->private_host_attrs[count] = class_device_attr_host_##field;	\
++	i->private_host_attrs[count] = device_attr_host_##field;	\
+ 	i->private_host_attrs[count].attr.mode = S_IRUGO;		\
+ 	i->private_host_attrs[count].store = NULL;			\
+ 	i->host_attrs[count] = &i->private_host_attrs[count];		\
+@@ -1333,14 +1355,14 @@ static FC_CLASS_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
+ 		count++
+ 
+ #define SETUP_HOST_ATTRIBUTE_RD_NS(field)				\
+-	i->private_host_attrs[count] = class_device_attr_host_##field;	\
++	i->private_host_attrs[count] = device_attr_host_##field;	\
+ 	i->private_host_attrs[count].attr.mode = S_IRUGO;		\
+ 	i->private_host_attrs[count].store = NULL;			\
+ 	i->host_attrs[count] = &i->private_host_attrs[count];		\
+ 	count++
+ 
+ #define SETUP_HOST_ATTRIBUTE_RW(field)					\
+-	i->private_host_attrs[count] = class_device_attr_host_##field;	\
++	i->private_host_attrs[count] = device_attr_host_##field;	\
+ 	if (!i->f->set_host_##field) {					\
+ 		i->private_host_attrs[count].attr.mode = S_IRUGO;	\
+ 		i->private_host_attrs[count].store = NULL;		\
+@@ -1352,24 +1374,25 @@ static FC_CLASS_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
+ 
+ #define fc_private_host_show_function(field, format_string, sz, cast)	\
+ static ssize_t								\
+-show_fc_host_##field (struct class_device *cdev, char *buf)		\
++show_fc_host_##field (struct device *dev,				\
++		      struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);	\
++	struct Scsi_Host *shost = transport_class_to_shost(dev);	\
+ 	return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \
+ }
+ 
+ #define fc_private_host_rd_attr(field, format_string, sz)		\
+ 	fc_private_host_show_function(field, format_string, sz, )	\
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(host, field, S_IRUGO,			\
+ 			 show_fc_host_##field, NULL)
+ 
+ #define fc_private_host_rd_attr_cast(field, format_string, sz, cast)	\
+ 	fc_private_host_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO,			\
++static FC_DEVICE_ATTR(host, field, S_IRUGO,			\
+ 			  show_fc_host_##field, NULL)
+ 
+ #define SETUP_PRIVATE_HOST_ATTRIBUTE_RD(field)			\
+-	i->private_host_attrs[count] = class_device_attr_host_##field;	\
++	i->private_host_attrs[count] = device_attr_host_##field;	\
+ 	i->private_host_attrs[count].attr.mode = S_IRUGO;		\
+ 	i->private_host_attrs[count].store = NULL;			\
+ 	i->host_attrs[count] = &i->private_host_attrs[count];		\
+@@ -1377,7 +1400,7 @@ static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO,			\
+ 
+ #define SETUP_PRIVATE_HOST_ATTRIBUTE_RW(field)			\
+ {									\
+-	i->private_host_attrs[count] = class_device_attr_host_##field;	\
++	i->private_host_attrs[count] = device_attr_host_##field;	\
+ 	i->host_attrs[count] = &i->private_host_attrs[count];		\
+ 	count++;							\
+ }
+@@ -1386,38 +1409,41 @@ static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO,			\
+ /* Fixed Host Attributes */
+ 
+ static ssize_t
+-show_fc_host_supported_classes (struct class_device *cdev, char *buf)
++show_fc_host_supported_classes (struct device *dev,
++			        struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 
+ 	if (fc_host_supported_classes(shost) == FC_COS_UNSPECIFIED)
+ 		return snprintf(buf, 20, "unspecified\n");
+ 
+ 	return get_fc_cos_names(fc_host_supported_classes(shost), buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(host, supported_classes, S_IRUGO,
++static FC_DEVICE_ATTR(host, supported_classes, S_IRUGO,
+ 		show_fc_host_supported_classes, NULL);
+ 
+ static ssize_t
+-show_fc_host_supported_fc4s (struct class_device *cdev, char *buf)
++show_fc_host_supported_fc4s (struct device *dev,
++			     struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	return (ssize_t)show_fc_fc4s(buf, fc_host_supported_fc4s(shost));
+ }
+-static FC_CLASS_DEVICE_ATTR(host, supported_fc4s, S_IRUGO,
++static FC_DEVICE_ATTR(host, supported_fc4s, S_IRUGO,
+ 		show_fc_host_supported_fc4s, NULL);
+ 
+ static ssize_t
+-show_fc_host_supported_speeds (struct class_device *cdev, char *buf)
++show_fc_host_supported_speeds (struct device *dev,
++			       struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 
+ 	if (fc_host_supported_speeds(shost) == FC_PORTSPEED_UNKNOWN)
+ 		return snprintf(buf, 20, "unknown\n");
+ 
+ 	return get_fc_port_speed_names(fc_host_supported_speeds(shost), buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
++static FC_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
+ 		show_fc_host_supported_speeds, NULL);
+ 
+ 
+@@ -1433,9 +1459,10 @@ fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
+ /* Dynamic Host Attributes */
+ 
+ static ssize_t
+-show_fc_host_active_fc4s (struct class_device *cdev, char *buf)
++show_fc_host_active_fc4s (struct device *dev,
++			  struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);
+ 
+ 	if (i->f->get_host_active_fc4s)
+@@ -1443,13 +1470,14 @@ show_fc_host_active_fc4s (struct class_device *cdev, char *buf)
+ 
+ 	return (ssize_t)show_fc_fc4s(buf, fc_host_active_fc4s(shost));
+ }
+-static FC_CLASS_DEVICE_ATTR(host, active_fc4s, S_IRUGO,
++static FC_DEVICE_ATTR(host, active_fc4s, S_IRUGO,
+ 		show_fc_host_active_fc4s, NULL);
+ 
+ static ssize_t
+-show_fc_host_speed (struct class_device *cdev, char *buf)
++show_fc_host_speed (struct device *dev,
++		    struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);
+ 
+ 	if (i->f->get_host_speed)
+@@ -1460,7 +1488,7 @@ show_fc_host_speed (struct class_device *cdev, char *buf)
+ 
+ 	return get_fc_port_speed_names(fc_host_speed(shost), buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(host, speed, S_IRUGO,
++static FC_DEVICE_ATTR(host, speed, S_IRUGO,
+ 		show_fc_host_speed, NULL);
+ 
+ 
+@@ -1473,16 +1501,17 @@ fc_host_rd_attr(symbolic_name, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1);
+ fc_private_host_show_function(system_hostname, "%s\n",
+ 		FC_SYMBOLIC_NAME_SIZE + 1, )
+ fc_host_store_str_function(system_hostname, FC_SYMBOLIC_NAME_SIZE)
+-static FC_CLASS_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR,
+ 		show_fc_host_system_hostname, store_fc_host_system_hostname);
+ 
+ 
+ /* Private Host Attributes */
+ 
+ static ssize_t
+-show_fc_private_host_tgtid_bind_type(struct class_device *cdev, char *buf)
++show_fc_private_host_tgtid_bind_type(struct device *dev,
++				     struct device_attribute *attr, char *buf)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	const char *name;
+ 
+ 	name = get_fc_tgtid_bind_type_name(fc_host_tgtid_bind_type(shost));
+@@ -1495,10 +1524,10 @@ show_fc_private_host_tgtid_bind_type(struct class_device *cdev, char *buf)
+ 	pos = list_entry((head)->next, typeof(*pos), member)
+ 
+ static ssize_t
+-store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
+-	const char *buf, size_t count)
++store_fc_private_host_tgtid_bind_type(struct device *dev,
++	struct device_attribute *attr, const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	struct fc_rport *rport;
+  	enum fc_tgtid_binding_type val;
+ 	unsigned long flags;
+@@ -1523,15 +1552,15 @@ store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
+ 	return count;
+ }
+ 
+-static FC_CLASS_DEVICE_ATTR(host, tgtid_bind_type, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(host, tgtid_bind_type, S_IRUGO | S_IWUSR,
+ 			show_fc_private_host_tgtid_bind_type,
+ 			store_fc_private_host_tgtid_bind_type);
+ 
+ static ssize_t
+-store_fc_private_host_issue_lip(struct class_device *cdev,
+-	const char *buf, size_t count)
++store_fc_private_host_issue_lip(struct device *dev,
++	struct device_attribute *attr, const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);
+ 	int ret;
+ 
+@@ -1544,7 +1573,7 @@ store_fc_private_host_issue_lip(struct class_device *cdev,
+ 	return -ENOENT;
+ }
+ 
+-static FC_CLASS_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
++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);
+@@ -1556,9 +1585,9 @@ fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
+ 
+ /* Show a given an attribute in the statistics group */
+ static ssize_t
+-fc_stat_show(const struct class_device *cdev, char *buf, unsigned long offset)
++fc_stat_show(const struct device *dev, char *buf, unsigned long offset)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);
+ 	struct fc_host_statistics *stats;
+ 	ssize_t ret = -ENOENT;
+@@ -1579,12 +1608,14 @@ fc_stat_show(const struct class_device *cdev, char *buf, unsigned long offset)
+ 
+ /* generate a read-only statistics attribute */
+ #define fc_host_statistic(name)						\
+-static ssize_t show_fcstat_##name(struct class_device *cd, char *buf) 	\
++static ssize_t show_fcstat_##name(struct device *cd,			\
++				  struct device_attribute *attr,	\
++				  char *buf)				\
+ {									\
+ 	return fc_stat_show(cd, buf, 					\
+ 			    offsetof(struct fc_host_statistics, name));	\
+ }									\
+-static FC_CLASS_DEVICE_ATTR(host, name, S_IRUGO, show_fcstat_##name, NULL)
++static FC_DEVICE_ATTR(host, name, S_IRUGO, show_fcstat_##name, NULL)
+ 
+ fc_host_statistic(seconds_since_last_reset);
+ fc_host_statistic(tx_frames);
+@@ -1608,10 +1639,10 @@ fc_host_statistic(fcp_input_megabytes);
+ fc_host_statistic(fcp_output_megabytes);
+ 
+ static ssize_t
+-fc_reset_statistics(struct class_device *cdev, const char *buf,
+-			   size_t count)
++fc_reset_statistics(struct device *dev, struct device_attribute *attr,
++		    const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	struct fc_internal *i = to_fc_internal(shost->transportt);
+ 
+ 	/* ignore any data value written to the attribute */
+@@ -1622,31 +1653,31 @@ fc_reset_statistics(struct class_device *cdev, const char *buf,
+ 
+ 	return -ENOENT;
+ }
+-static FC_CLASS_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
++static FC_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
+ 				fc_reset_statistics);
+ 
+ static struct attribute *fc_statistics_attrs[] = {
+-	&class_device_attr_host_seconds_since_last_reset.attr,
+-	&class_device_attr_host_tx_frames.attr,
+-	&class_device_attr_host_tx_words.attr,
+-	&class_device_attr_host_rx_frames.attr,
+-	&class_device_attr_host_rx_words.attr,
+-	&class_device_attr_host_lip_count.attr,
+-	&class_device_attr_host_nos_count.attr,
+-	&class_device_attr_host_error_frames.attr,
+-	&class_device_attr_host_dumped_frames.attr,
+-	&class_device_attr_host_link_failure_count.attr,
+-	&class_device_attr_host_loss_of_sync_count.attr,
+-	&class_device_attr_host_loss_of_signal_count.attr,
+-	&class_device_attr_host_prim_seq_protocol_err_count.attr,
+-	&class_device_attr_host_invalid_tx_word_count.attr,
+-	&class_device_attr_host_invalid_crc_count.attr,
+-	&class_device_attr_host_fcp_input_requests.attr,
+-	&class_device_attr_host_fcp_output_requests.attr,
+-	&class_device_attr_host_fcp_control_requests.attr,
+-	&class_device_attr_host_fcp_input_megabytes.attr,
+-	&class_device_attr_host_fcp_output_megabytes.attr,
+-	&class_device_attr_host_reset_statistics.attr,
++	&device_attr_host_seconds_since_last_reset.attr,
++	&device_attr_host_tx_frames.attr,
++	&device_attr_host_tx_words.attr,
++	&device_attr_host_rx_frames.attr,
++	&device_attr_host_rx_words.attr,
++	&device_attr_host_lip_count.attr,
++	&device_attr_host_nos_count.attr,
++	&device_attr_host_error_frames.attr,
++	&device_attr_host_dumped_frames.attr,
++	&device_attr_host_link_failure_count.attr,
++	&device_attr_host_loss_of_sync_count.attr,
++	&device_attr_host_loss_of_signal_count.attr,
++	&device_attr_host_prim_seq_protocol_err_count.attr,
++	&device_attr_host_invalid_tx_word_count.attr,
++	&device_attr_host_invalid_crc_count.attr,
++	&device_attr_host_fcp_input_requests.attr,
++	&device_attr_host_fcp_output_requests.attr,
++	&device_attr_host_fcp_control_requests.attr,
++	&device_attr_host_fcp_input_megabytes.attr,
++	&device_attr_host_fcp_output_megabytes.attr,
++	&device_attr_host_reset_statistics.attr,
+ 	NULL
+ };
+ 
+@@ -1695,10 +1726,10 @@ fc_parse_wwn(const char *ns, u64 *nm)
+  * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
+  */
+ static ssize_t
+-store_fc_host_vport_create(struct class_device *cdev, const char *buf,
+-			   size_t count)
++store_fc_host_vport_create(struct device *dev, struct device_attribute *attr,
++			   const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	struct fc_vport_identifiers vid;
+ 	struct fc_vport *vport;
+ 	unsigned int cnt=count;
+@@ -1731,7 +1762,7 @@ store_fc_host_vport_create(struct class_device *cdev, const char *buf,
+ 	stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
+ 	return stat ? stat : count;
+ }
+-static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
++static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
+ 			store_fc_host_vport_create);
+ 
+ 
+@@ -1742,10 +1773,10 @@ static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
+  * any prefixes (e.g. 0x, x, etc)
+  */
+ static ssize_t
+-store_fc_host_vport_delete(struct class_device *cdev, const char *buf,
+-			   size_t count)
++store_fc_host_vport_delete(struct device *dev, struct device_attribute *attr,
++			   const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ 	struct fc_vport *vport;
+ 	u64 wwpn, wwnn;
+@@ -1787,7 +1818,7 @@ store_fc_host_vport_delete(struct class_device *cdev, const char *buf,
+ 	stat = fc_vport_terminate(vport);
+ 	return stat ? stat : count;
+ }
+-static FC_CLASS_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
++static FC_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
+ 			store_fc_host_vport_delete);
+ 
+ 
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ca7bb6f..65d1737 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -40,13 +40,13 @@ struct iscsi_internal {
+ 	struct scsi_transport_template t;
+ 	struct iscsi_transport *iscsi_transport;
+ 	struct list_head list;
+-	struct class_device cdev;
++	struct device dev;
+ 
+-	struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
++	struct device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
+ 	struct transport_container conn_cont;
+-	struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
++	struct device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
+ 	struct transport_container session_cont;
+-	struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
++	struct device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
+ };
+ 
+ static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
+@@ -63,12 +63,12 @@ static DEFINE_SPINLOCK(iscsi_transport_lock);
+ #define to_iscsi_internal(tmpl) \
+ 	container_of(tmpl, struct iscsi_internal, t)
+ 
+-#define cdev_to_iscsi_internal(_cdev) \
+-	container_of(_cdev, struct iscsi_internal, cdev)
++#define dev_to_iscsi_internal(_dev) \
++	container_of(_dev, struct iscsi_internal, dev)
+ 
+-static void iscsi_transport_release(struct class_device *cdev)
++static void iscsi_transport_release(struct device *dev)
+ {
+-	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
++	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
+ 	kfree(priv);
+ }
+ 
+@@ -78,25 +78,27 @@ static void iscsi_transport_release(struct class_device *cdev)
+  */
+ static struct class iscsi_transport_class = {
+ 	.name = "iscsi_transport",
+-	.release = iscsi_transport_release,
++	.dev_release = iscsi_transport_release,
+ };
+ 
+ static ssize_t
+-show_transport_handle(struct class_device *cdev, char *buf)
++show_transport_handle(struct device *dev, struct device_attribute *attr,
++		      char *buf)
+ {
+-	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
++	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
+ 	return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
+ }
+-static CLASS_DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
++static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
+ 
+ #define show_transport_attr(name, format)				\
+ static ssize_t								\
+-show_transport_##name(struct class_device *cdev, char *buf)		\
++show_transport_##name(struct device *dev, 				\
++		      struct device_attribute *attr,char *buf)		\
+ {									\
+-	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);	\
++	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);	\
+ 	return sprintf(buf, format"\n", priv->iscsi_transport->name);	\
+ }									\
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
++static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
+ 
+ show_transport_attr(caps, "0x%x");
+ show_transport_attr(max_lun, "%d");
+@@ -104,11 +106,11 @@ show_transport_attr(max_conn, "%d");
+ show_transport_attr(max_cmd_len, "%d");
+ 
+ static struct attribute *iscsi_transport_attrs[] = {
+-	&class_device_attr_handle.attr,
+-	&class_device_attr_caps.attr,
+-	&class_device_attr_max_lun.attr,
+-	&class_device_attr_max_conn.attr,
+-	&class_device_attr_max_cmd_len.attr,
++	&dev_attr_handle.attr,
++	&dev_attr_caps.attr,
++	&dev_attr_max_lun.attr,
++	&dev_attr_max_conn.attr,
++	&dev_attr_max_cmd_len.attr,
+ 	NULL,
+ };
+ 
+@@ -119,7 +121,7 @@ static struct attribute_group iscsi_transport_group = {
+ 
+ 
+ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+-			    struct class_device *cdev)
++			    struct device *cdev)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct iscsi_host *ihost = shost->shost_data;
+@@ -139,7 +141,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ }
+ 
+ static int iscsi_remove_host(struct transport_container *tc, struct device *dev,
+-			     struct class_device *cdev)
++			     struct device *cdev)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct iscsi_host *ihost = shost->shost_data;
+@@ -1337,11 +1339,8 @@ iscsi_if_rx(struct sk_buff *skb)
+ 	mutex_unlock(&rx_queue_mutex);
+ }
+ 
+-#define iscsi_cdev_to_conn(_cdev) \
+-	iscsi_dev_to_conn(_cdev->dev)
+-
+ #define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store)		\
+-struct class_device_attribute class_device_attr_##_prefix##_##_name =	\
++struct device_attribute dev_attr_##_prefix##_##_name =	\
+ 	__ATTR(_name,_mode,_show,_store)
+ 
+ /*
+@@ -1349,9 +1348,10 @@ struct class_device_attribute class_device_attr_##_prefix##_##_name =	\
+  */
+ #define iscsi_conn_attr_show(param)					\
+ static ssize_t								\
+-show_conn_param_##param(struct class_device *cdev, char *buf)		\
++show_conn_param_##param(struct device *dev, 				\
++			struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
++	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);	\
+ 	struct iscsi_transport *t = conn->transport;			\
+ 	return t->get_conn_param(conn, param, buf);			\
+ }
+@@ -1375,17 +1375,16 @@ iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+ iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
+ iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
+ 
+-#define iscsi_cdev_to_session(_cdev) \
+-	iscsi_dev_to_session(_cdev->dev)
+-
+ /*
+  * iSCSI session attrs
+  */
+ #define iscsi_session_attr_show(param, perm)				\
+ static ssize_t								\
+-show_session_param_##param(struct class_device *cdev, char *buf)	\
++show_session_param_##param(struct device *dev,				\
++			   struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
++	struct iscsi_cls_session *session = 				\
++		iscsi_dev_to_session(dev->parent);			\
+ 	struct iscsi_transport *t = session->transport;			\
+ 									\
+ 	if (perm && !capable(CAP_SYS_ADMIN))				\
+@@ -1417,9 +1416,10 @@ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
+ 
+ static ssize_t
+-show_priv_session_state(struct class_device *cdev, char *buf)
++show_priv_session_state(struct device *dev, struct device_attribute *attr,
++			char *buf)
+ {
+-	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);
++	struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
+ 	return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
+ }
+ static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
+@@ -1427,9 +1427,11 @@ static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
+ 
+ #define iscsi_priv_session_attr_show(field, format)			\
+ static ssize_t								\
+-show_priv_session_##field(struct class_device *cdev, char *buf)		\
++show_priv_session_##field(struct device *dev, 				\
++			  struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);\
++	struct iscsi_cls_session *session = 				\
++			iscsi_dev_to_session(dev->parent);		\
+ 	return sprintf(buf, format"\n", session->field);		\
+ }
+ 
+@@ -1444,9 +1446,10 @@ iscsi_priv_session_attr(recovery_tmo, "%d");
+  */
+ #define iscsi_host_attr_show(param)					\
+ static ssize_t								\
+-show_host_param_##param(struct class_device *cdev, char *buf)		\
++show_host_param_##param(struct device *dev, 				\
++			struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);	\
++	struct Scsi_Host *shost = transport_class_to_shost(dev);	\
+ 	struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
+ 	return priv->iscsi_transport->get_host_param(shost, param, buf); \
+ }
+@@ -1463,7 +1466,7 @@ iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
+ 
+ #define SETUP_PRIV_SESSION_RD_ATTR(field)				\
+ do {									\
+-	priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
++	priv->session_attrs[count] = &dev_attr_priv_sess_##field; \
+ 	count++;							\
+ } while (0)
+ 
+@@ -1471,7 +1474,7 @@ do {									\
+ #define SETUP_SESSION_RD_ATTR(field, param_flag)			\
+ do {									\
+ 	if (tt->param_mask & param_flag) {				\
+-		priv->session_attrs[count] = &class_device_attr_sess_##field; \
++		priv->session_attrs[count] = &dev_attr_sess_##field; \
+ 		count++;						\
+ 	}								\
+ } while (0)
+@@ -1479,7 +1482,7 @@ do {									\
+ #define SETUP_CONN_RD_ATTR(field, param_flag)				\
+ do {									\
+ 	if (tt->param_mask & param_flag) {				\
+-		priv->conn_attrs[count] = &class_device_attr_conn_##field; \
++		priv->conn_attrs[count] = &dev_attr_conn_##field; \
+ 		count++;						\
+ 	}								\
+ } while (0)
+@@ -1487,7 +1490,7 @@ do {									\
+ #define SETUP_HOST_RD_ATTR(field, param_flag)				\
+ do {									\
+ 	if (tt->host_param_mask & param_flag) {				\
+-		priv->host_attrs[count] = &class_device_attr_host_##field; \
++		priv->host_attrs[count] = &dev_attr_host_##field; \
+ 		count++;						\
+ 	}								\
+ } while (0)
+@@ -1578,15 +1581,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	priv->iscsi_transport = tt;
+ 	priv->t.user_scan = iscsi_user_scan;
+ 
+-	priv->cdev.class = &iscsi_transport_class;
+-	snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+-	err = class_device_register(&priv->cdev);
++	priv->dev.class = &iscsi_transport_class;
++	snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name);
++	err = device_register(&priv->dev);
+ 	if (err)
+ 		goto free_priv;
+ 
+-	err = sysfs_create_group(&priv->cdev.kobj, &iscsi_transport_group);
++	err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
+ 	if (err)
+-		goto unregister_cdev;
++		goto unregister_dev;
+ 
+ 	/* host parameters */
+ 	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+@@ -1663,8 +1666,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ 	printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
+ 	return &priv->t;
+ 
+-unregister_cdev:
+-	class_device_unregister(&priv->cdev);
++unregister_dev:
++	device_unregister(&priv->dev);
+ free_priv:
+ 	kfree(priv);
+ 	return NULL;
+@@ -1691,8 +1694,8 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
+ 	transport_container_unregister(&priv->session_cont);
+ 	transport_container_unregister(&priv->t.host_attrs);
+ 
+-	sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+-	class_device_unregister(&priv->cdev);
++	sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
++	device_unregister(&priv->dev);
+ 	mutex_unlock(&rx_queue_mutex);
+ 
+ 	return 0;
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index 43a964d..27ec625 100644
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -53,8 +53,8 @@ struct sas_host_attrs {
+ /*
+  * Hack to allow attributes of the same name in different objects.
+  */
+-#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+-	struct class_device_attribute class_device_attr_##_prefix##_##_name = \
++#define SAS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
++	struct device_attribute dev_attr_##_prefix##_##_name = \
+ 	__ATTR(_name,_mode,_show,_store)
+ 
+ 
+@@ -261,7 +261,7 @@ static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
+  */
+ 
+ static int sas_host_setup(struct transport_container *tc, struct device *dev,
+-			  struct class_device *cdev)
++			  struct device *cdev)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+@@ -280,7 +280,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
+ }
+ 
+ static int sas_host_remove(struct transport_container *tc, struct device *dev,
+-			   struct class_device *cdev)
++			   struct device *cdev)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+ 
+@@ -356,22 +356,24 @@ EXPORT_SYMBOL(sas_remove_host);
+ 
+ #define sas_phy_show_simple(field, name, format_string, cast)		\
+ static ssize_t								\
+-show_sas_phy_##name(struct class_device *cdev, char *buf)		\
++show_sas_phy_##name(struct device *dev, 				\
++		    struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct sas_phy *phy = transport_class_to_phy(cdev);		\
++	struct sas_phy *phy = transport_class_to_phy(dev);		\
+ 									\
+ 	return snprintf(buf, 20, format_string, cast phy->field);	\
+ }
+ 
+ #define sas_phy_simple_attr(field, name, format_string, type)		\
+ 	sas_phy_show_simple(field, name, format_string, (type))	\
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
++static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+ 
+ #define sas_phy_show_protocol(field, name)				\
+ static ssize_t								\
+-show_sas_phy_##name(struct class_device *cdev, char *buf)		\
++show_sas_phy_##name(struct device *dev, 				\
++		    struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct sas_phy *phy = transport_class_to_phy(cdev);		\
++	struct sas_phy *phy = transport_class_to_phy(dev);		\
+ 									\
+ 	if (!phy->field)						\
+ 		return snprintf(buf, 20, "none\n");			\
+@@ -380,13 +382,14 @@ show_sas_phy_##name(struct class_device *cdev, char *buf)		\
+ 
+ #define sas_phy_protocol_attr(field, name)				\
+ 	sas_phy_show_protocol(field, name)				\
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
++static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+ 
+ #define sas_phy_show_linkspeed(field)					\
+ static ssize_t								\
+-show_sas_phy_##field(struct class_device *cdev, char *buf)		\
++show_sas_phy_##field(struct device *dev, 				\
++		     struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct sas_phy *phy = transport_class_to_phy(cdev);		\
++	struct sas_phy *phy = transport_class_to_phy(dev);		\
+ 									\
+ 	return get_sas_linkspeed_names(phy->field, buf);		\
+ }
+@@ -394,10 +397,11 @@ show_sas_phy_##field(struct class_device *cdev, char *buf)		\
+ /* Fudge to tell if we're minimum or maximum */
+ #define sas_phy_store_linkspeed(field)					\
+ static ssize_t								\
+-store_sas_phy_##field(struct class_device *cdev, const char *buf,	\
+-		      size_t count)					\
++store_sas_phy_##field(struct device *dev, 				\
++		      struct device_attribute *attr, 			\
++		      const char *buf,	size_t count)			\
+ {									\
+-	struct sas_phy *phy = transport_class_to_phy(cdev);		\
++	struct sas_phy *phy = transport_class_to_phy(dev);		\
+ 	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);	\
+ 	struct sas_internal *i = to_sas_internal(shost->transportt);	\
+ 	u32 value;							\
+@@ -416,19 +420,20 @@ store_sas_phy_##field(struct class_device *cdev, const char *buf,	\
+ #define sas_phy_linkspeed_rw_attr(field)				\
+ 	sas_phy_show_linkspeed(field)					\
+ 	sas_phy_store_linkspeed(field)					\
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field,		\
++static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field,		\
+ 	store_sas_phy_##field)
+ 
+ #define sas_phy_linkspeed_attr(field)					\
+ 	sas_phy_show_linkspeed(field)					\
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
++static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
+ 
+ 
+ #define sas_phy_show_linkerror(field)					\
+ static ssize_t								\
+-show_sas_phy_##field(struct class_device *cdev, char *buf)		\
++show_sas_phy_##field(struct device *dev, 				\
++		     struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct sas_phy *phy = transport_class_to_phy(cdev);		\
++	struct sas_phy *phy = transport_class_to_phy(dev);		\
+ 	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);	\
+ 	struct sas_internal *i = to_sas_internal(shost->transportt);	\
+ 	int error;							\
+@@ -441,24 +446,25 @@ show_sas_phy_##field(struct class_device *cdev, char *buf)		\
+ 
+ #define sas_phy_linkerror_attr(field)					\
+ 	sas_phy_show_linkerror(field)					\
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
++static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
+ 
+ 
+ static ssize_t
+-show_sas_device_type(struct class_device *cdev, char *buf)
++show_sas_device_type(struct device *dev,
++		     struct device_attribute *attr, char *buf)
+ {
+-	struct sas_phy *phy = transport_class_to_phy(cdev);
++	struct sas_phy *phy = transport_class_to_phy(dev);
+ 
+ 	if (!phy->identify.device_type)
+ 		return snprintf(buf, 20, "none\n");
+ 	return get_sas_device_type_names(phy->identify.device_type, buf);
+ }
+-static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
++static DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
+ 
+-static ssize_t do_sas_phy_enable(struct class_device *cdev,
++static ssize_t do_sas_phy_enable(struct device *dev,
+ 		size_t count, int enable)
+ {
+-	struct sas_phy *phy = transport_class_to_phy(cdev);
++	struct sas_phy *phy = transport_class_to_phy(dev);
+ 	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ 	struct sas_internal *i = to_sas_internal(shost->transportt);
+ 	int error;
+@@ -470,18 +476,19 @@ static ssize_t do_sas_phy_enable(struct class_device *cdev,
+ 	return count;
+ };
+ 
+-static ssize_t store_sas_phy_enable(struct class_device *cdev,
+-		const char *buf, size_t count)
++static ssize_t
++store_sas_phy_enable(struct device *dev, struct device_attribute *attr,
++		     const char *buf, size_t count)
+ {
+ 	if (count < 1)
+ 		return -EINVAL;
+ 
+ 	switch (buf[0]) {
+ 	case '0':
+-		do_sas_phy_enable(cdev, count, 0);
++		do_sas_phy_enable(dev, count, 0);
+ 		break;
+ 	case '1':
+-		do_sas_phy_enable(cdev, count, 1);
++		do_sas_phy_enable(dev, count, 1);
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -490,20 +497,22 @@ static ssize_t store_sas_phy_enable(struct class_device *cdev,
+ 	return count;
+ }
+ 
+-static ssize_t show_sas_phy_enable(struct class_device *cdev, char *buf)
++static ssize_t
++show_sas_phy_enable(struct device *dev, struct device_attribute *attr,
++		    char *buf)
+ {
+-	struct sas_phy *phy = transport_class_to_phy(cdev);
++	struct sas_phy *phy = transport_class_to_phy(dev);
+ 
+ 	return snprintf(buf, 20, "%d", phy->enabled);
+ }
+ 
+-static CLASS_DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
++static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
+ 			 store_sas_phy_enable);
+ 
+-static ssize_t do_sas_phy_reset(struct class_device *cdev,
+-		size_t count, int hard_reset)
++static ssize_t
++do_sas_phy_reset(struct device *dev, size_t count, int hard_reset)
+ {
+-	struct sas_phy *phy = transport_class_to_phy(cdev);
++	struct sas_phy *phy = transport_class_to_phy(dev);
+ 	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ 	struct sas_internal *i = to_sas_internal(shost->transportt);
+ 	int error;
+@@ -514,19 +523,21 @@ static ssize_t do_sas_phy_reset(struct class_device *cdev,
+ 	return count;
+ };
+ 
+-static ssize_t store_sas_link_reset(struct class_device *cdev,
+-		const char *buf, size_t count)
++static ssize_t
++store_sas_link_reset(struct device *dev, struct device_attribute *attr,
++		     const char *buf, size_t count)
+ {
+-	return do_sas_phy_reset(cdev, count, 0);
++	return do_sas_phy_reset(dev, count, 0);
+ }
+-static CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);
++static DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);
+ 
+-static ssize_t store_sas_hard_reset(struct class_device *cdev,
+-		const char *buf, size_t count)
++static ssize_t
++store_sas_hard_reset(struct device *dev, struct device_attribute *attr,
++		     const char *buf, size_t count)
+ {
+-	return do_sas_phy_reset(cdev, count, 1);
++	return do_sas_phy_reset(dev, count, 1);
+ }
+-static CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);
++static DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);
+ 
+ sas_phy_protocol_attr(identify.initiator_port_protocols,
+ 		initiator_port_protocols);
+@@ -695,16 +706,17 @@ EXPORT_SYMBOL(scsi_is_sas_phy);
+  */
+ #define sas_port_show_simple(field, name, format_string, cast)		\
+ static ssize_t								\
+-show_sas_port_##name(struct class_device *cdev, char *buf)		\
++show_sas_port_##name(struct device *dev, 				\
++		     struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct sas_port *port = transport_class_to_sas_port(cdev);	\
++	struct sas_port *port = transport_class_to_sas_port(dev);	\
+ 									\
+ 	return snprintf(buf, 20, format_string, cast port->field);	\
+ }
+ 
+ #define sas_port_simple_attr(field, name, format_string, type)		\
+ 	sas_port_show_simple(field, name, format_string, (type))	\
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
++static DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
+ 
+ sas_port_simple_attr(num_phys, num_phys, "%d\n", int);
+ 
+@@ -1017,23 +1029,25 @@ EXPORT_SYMBOL(sas_port_mark_backlink);
+ 
+ #define sas_rphy_show_simple(field, name, format_string, cast)		\
+ static ssize_t								\
+-show_sas_rphy_##name(struct class_device *cdev, char *buf)		\
++show_sas_rphy_##name(struct device *dev, 				\
++		     struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct sas_rphy *rphy = transport_class_to_rphy(cdev);	\
++	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\
+ 									\
+ 	return snprintf(buf, 20, format_string, cast rphy->field);	\
+ }
+ 
+ #define sas_rphy_simple_attr(field, name, format_string, type)		\
+ 	sas_rphy_show_simple(field, name, format_string, (type))	\
+-static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, 			\
++static SAS_DEVICE_ATTR(rphy, name, S_IRUGO, 			\
+ 		show_sas_rphy_##name, NULL)
+ 
+ #define sas_rphy_show_protocol(field, name)				\
+ static ssize_t								\
+-show_sas_rphy_##name(struct class_device *cdev, char *buf)		\
++show_sas_rphy_##name(struct device *dev, 				\
++		     struct device_attribute *attr, char *buf)		\
+ {									\
+-	struct sas_rphy *rphy = transport_class_to_rphy(cdev);	\
++	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\
+ 									\
+ 	if (!rphy->field)					\
+ 		return snprintf(buf, 20, "none\n");			\
+@@ -1042,13 +1056,14 @@ show_sas_rphy_##name(struct class_device *cdev, char *buf)		\
+ 
+ #define sas_rphy_protocol_attr(field, name)				\
+ 	sas_rphy_show_protocol(field, name)				\
+-static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO,			\
++static SAS_DEVICE_ATTR(rphy, name, S_IRUGO,			\
+ 		show_sas_rphy_##name, NULL)
+ 
+ static ssize_t
+-show_sas_rphy_device_type(struct class_device *cdev, char *buf)
++show_sas_rphy_device_type(struct device *dev,
++			  struct device_attribute *attr, char *buf)
+ {
+-	struct sas_rphy *rphy = transport_class_to_rphy(cdev);
++	struct sas_rphy *rphy = transport_class_to_rphy(dev);
+ 
+ 	if (!rphy->identify.device_type)
+ 		return snprintf(buf, 20, "none\n");
+@@ -1056,13 +1071,14 @@ show_sas_rphy_device_type(struct class_device *cdev, char *buf)
+ 			rphy->identify.device_type, buf);
+ }
+ 
+-static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
++static SAS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
+ 		show_sas_rphy_device_type, NULL);
+ 
+ static ssize_t
+-show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf)
++show_sas_rphy_enclosure_identifier(struct device *dev,
++				   struct device_attribute *attr, char *buf)
+ {
+-	struct sas_rphy *rphy = transport_class_to_rphy(cdev);
++	struct sas_rphy *rphy = transport_class_to_rphy(dev);
+ 	struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
+ 	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ 	struct sas_internal *i = to_sas_internal(shost->transportt);
+@@ -1082,13 +1098,14 @@ show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf)
+ 	return sprintf(buf, "0x%llx\n", (unsigned long long)identifier);
+ }
+ 
+-static SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO,
++static SAS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO,
+ 		show_sas_rphy_enclosure_identifier, NULL);
+ 
+ static ssize_t
+-show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf)
++show_sas_rphy_bay_identifier(struct device *dev,
++			     struct device_attribute *attr, char *buf)
+ {
+-	struct sas_rphy *rphy = transport_class_to_rphy(cdev);
++	struct sas_rphy *rphy = transport_class_to_rphy(dev);
+ 	struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
+ 	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ 	struct sas_internal *i = to_sas_internal(shost->transportt);
+@@ -1103,7 +1120,7 @@ show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf)
+ 	return sprintf(buf, "%d\n", val);
+ }
+ 
+-static SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO,
++static SAS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO,
+ 		show_sas_rphy_bay_identifier, NULL);
+ 
+ sas_rphy_protocol_attr(identify.initiator_port_protocols,
+@@ -1161,9 +1178,10 @@ static DECLARE_TRANSPORT_CLASS(sas_end_dev_class,
+ 
+ #define sas_end_dev_show_simple(field, name, format_string, cast)	\
+ static ssize_t								\
+-show_sas_end_dev_##name(struct class_device *cdev, char *buf)		\
++show_sas_end_dev_##name(struct device *dev, 				\
++			struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct sas_rphy *rphy = transport_class_to_rphy(cdev);		\
++	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\
+ 	struct sas_end_device *rdev = rphy_to_end_device(rphy);		\
+ 									\
+ 	return snprintf(buf, 20, format_string, cast rdev->field);	\
+@@ -1171,7 +1189,7 @@ show_sas_end_dev_##name(struct class_device *cdev, char *buf)		\
+ 
+ #define sas_end_dev_simple_attr(field, name, format_string, type)	\
+ 	sas_end_dev_show_simple(field, name, format_string, (type))	\
+-static SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, 			\
++static SAS_DEVICE_ATTR(end_dev, name, S_IRUGO, 			\
+ 		show_sas_end_dev_##name, NULL)
+ 
+ sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int);
+@@ -1185,9 +1203,10 @@ static DECLARE_TRANSPORT_CLASS(sas_expander_class,
+ 
+ #define sas_expander_show_simple(field, name, format_string, cast)	\
+ static ssize_t								\
+-show_sas_expander_##name(struct class_device *cdev, char *buf)		\
++show_sas_expander_##name(struct device *dev, 				\
++			 struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct sas_rphy *rphy = transport_class_to_rphy(cdev);		\
++	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\
+ 	struct sas_expander_device *edev = rphy_to_expander_device(rphy); \
+ 									\
+ 	return snprintf(buf, 20, format_string, cast edev->field);	\
+@@ -1195,7 +1214,7 @@ show_sas_expander_##name(struct class_device *cdev, char *buf)		\
+ 
+ #define sas_expander_simple_attr(field, name, format_string, type)	\
+ 	sas_expander_show_simple(field, name, format_string, (type))	\
+-static SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, 			\
++static SAS_DEVICE_ATTR(expander, name, S_IRUGO, 			\
+ 		show_sas_expander_##name, NULL)
+ 
+ sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *);
+@@ -1554,14 +1573,14 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+  */
+ 
+ #define SETUP_TEMPLATE(attrb, field, perm, test)			\
+-	i->private_##attrb[count] = class_device_attr_##field;		\
++	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_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm)	\
+-	i->private_##attrb[count] = class_device_attr_##field;		\
++	i->private_##attrb[count] = dev_attr_##field;		\
+ 	i->private_##attrb[count].attr.mode = perm;			\
+ 	if (ro_test) {							\
+ 		i->private_##attrb[count].attr.mode = ro_perm;		\
+diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
+index 1fb6031..bc12b5d 100644
+--- a/drivers/scsi/scsi_transport_spi.c
++++ b/drivers/scsi/scsi_transport_spi.c
+@@ -158,7 +158,7 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name)
+ }
+ 
+ static int spi_host_setup(struct transport_container *tc, struct device *dev,
+-			  struct class_device *cdev)
++			  struct device *cdev)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+ 
+@@ -169,7 +169,7 @@ static int spi_host_setup(struct transport_container *tc, struct device *dev,
+ 
+ static int spi_host_configure(struct transport_container *tc,
+ 			      struct device *dev,
+-			      struct class_device *cdev);
++			      struct device *cdev);
+ 
+ static DECLARE_TRANSPORT_CLASS(spi_host_class,
+ 			       "spi_host",
+@@ -195,11 +195,11 @@ static int spi_host_match(struct attribute_container *cont,
+ 
+ static int spi_target_configure(struct transport_container *tc,
+ 				struct device *dev,
+-				struct class_device *cdev);
++				struct device *cdev);
+ 
+ static int spi_device_configure(struct transport_container *tc,
+ 				struct device *dev,
+-				struct class_device *cdev)
++				struct device *cdev)
+ {
+ 	struct scsi_device *sdev = to_scsi_device(dev);
+ 	struct scsi_target *starget = sdev->sdev_target;
+@@ -219,7 +219,7 @@ static int spi_device_configure(struct transport_container *tc,
+ 
+ static int spi_setup_transport_attrs(struct transport_container *tc,
+ 				     struct device *dev,
+-				     struct class_device *cdev)
++				     struct device *cdev)
+ {
+ 	struct scsi_target *starget = to_scsi_target(dev);
+ 
+@@ -248,9 +248,10 @@ static int spi_setup_transport_attrs(struct transport_container *tc,
+ #define spi_transport_show_simple(field, format_string)			\
+ 									\
+ static ssize_t								\
+-show_spi_transport_##field(struct class_device *cdev, char *buf)	\
++show_spi_transport_##field(struct device *dev, 			\
++			   struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct scsi_target *starget = transport_class_to_starget(cdev);	\
++	struct scsi_target *starget = transport_class_to_starget(dev);	\
+ 	struct spi_transport_attrs *tp;					\
+ 									\
+ 	tp = (struct spi_transport_attrs *)&starget->starget_data;	\
+@@ -260,11 +261,12 @@ show_spi_transport_##field(struct class_device *cdev, char *buf)	\
+ #define spi_transport_store_simple(field, format_string)		\
+ 									\
+ static ssize_t								\
+-store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+-			    size_t count)				\
++store_spi_transport_##field(struct device *dev, 			\
++			    struct device_attribute *attr, 		\
++			    const char *buf, size_t count)		\
+ {									\
+ 	int val;							\
+-	struct scsi_target *starget = transport_class_to_starget(cdev);	\
++	struct scsi_target *starget = transport_class_to_starget(dev);	\
+ 	struct spi_transport_attrs *tp;					\
+ 									\
+ 	tp = (struct spi_transport_attrs *)&starget->starget_data;	\
+@@ -276,9 +278,10 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+ #define spi_transport_show_function(field, format_string)		\
+ 									\
+ static ssize_t								\
+-show_spi_transport_##field(struct class_device *cdev, char *buf)	\
++show_spi_transport_##field(struct device *dev, 			\
++			   struct device_attribute *attr, char *buf)	\
+ {									\
+-	struct scsi_target *starget = transport_class_to_starget(cdev);	\
++	struct scsi_target *starget = transport_class_to_starget(dev);	\
+ 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);	\
+ 	struct spi_transport_attrs *tp;					\
+ 	struct spi_internal *i = to_spi_internal(shost->transportt);	\
+@@ -290,11 +293,12 @@ show_spi_transport_##field(struct class_device *cdev, char *buf)	\
+ 
+ #define spi_transport_store_function(field, format_string)		\
+ static ssize_t								\
+-store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+-			    size_t count)				\
++store_spi_transport_##field(struct device *dev, 			\
++			    struct device_attribute *attr,		\
++			    const char *buf, size_t count)		\
+ {									\
+ 	int val;							\
+-	struct scsi_target *starget = transport_class_to_starget(cdev);	\
++	struct scsi_target *starget = transport_class_to_starget(dev);	\
+ 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);	\
+ 	struct spi_internal *i = to_spi_internal(shost->transportt);	\
+ 									\
+@@ -307,11 +311,12 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+ 
+ #define spi_transport_store_max(field, format_string)			\
+ static ssize_t								\
+-store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+-			    size_t count)				\
++store_spi_transport_##field(struct device *dev, 			\
++			    struct device_attribute *attr,		\
++			    const char *buf, size_t count)		\
+ {									\
+ 	int val;							\
+-	struct scsi_target *starget = transport_class_to_starget(cdev);	\
++	struct scsi_target *starget = transport_class_to_starget(dev);	\
+ 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);	\
+ 	struct spi_internal *i = to_spi_internal(shost->transportt);	\
+ 	struct spi_transport_attrs *tp					\
+@@ -329,24 +334,24 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+ #define spi_transport_rd_attr(field, format_string)			\
+ 	spi_transport_show_function(field, format_string)		\
+ 	spi_transport_store_function(field, format_string)		\
+-static CLASS_DEVICE_ATTR(field, S_IRUGO,				\
+-			 show_spi_transport_##field,			\
+-			 store_spi_transport_##field);
++static DEVICE_ATTR(field, S_IRUGO,				\
++		   show_spi_transport_##field,			\
++		   store_spi_transport_##field);
+ 
+ #define spi_transport_simple_attr(field, format_string)			\
+ 	spi_transport_show_simple(field, format_string)			\
+ 	spi_transport_store_simple(field, format_string)		\
+-static CLASS_DEVICE_ATTR(field, S_IRUGO,				\
+-			 show_spi_transport_##field,			\
+-			 store_spi_transport_##field);
++static DEVICE_ATTR(field, S_IRUGO,				\
++		   show_spi_transport_##field,			\
++		   store_spi_transport_##field);
+ 
+ #define spi_transport_max_attr(field, format_string)			\
+ 	spi_transport_show_function(field, format_string)		\
+ 	spi_transport_store_max(field, format_string)			\
+ 	spi_transport_simple_attr(max_##field, format_string)		\
+-static CLASS_DEVICE_ATTR(field, S_IRUGO,				\
+-			 show_spi_transport_##field,			\
+-			 store_spi_transport_##field);
++static DEVICE_ATTR(field, S_IRUGO,				\
++		   show_spi_transport_##field,			\
++		   store_spi_transport_##field);
+ 
+ /* The Parallel SCSI Tranport Attributes: */
+ spi_transport_max_attr(offset, "%d\n");
+@@ -370,14 +375,15 @@ static int child_iter(struct device *dev, void *data)
+ }
+ 
+ static ssize_t
+-store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count)
++store_spi_revalidate(struct device *dev, struct device_attribute *attr,
++		     const char *buf, size_t count)
+ {
+-	struct scsi_target *starget = transport_class_to_starget(cdev);
++	struct scsi_target *starget = transport_class_to_starget(dev);
+ 
+ 	device_for_each_child(&starget->dev, NULL, child_iter);
+ 	return count;
+ }
+-static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
++static DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
+ 
+ /* Translate the period into ns according to the current spec
+  * for SDTR/PPR messages */
+@@ -412,7 +418,7 @@ show_spi_transport_period_helper(char *buf, int period)
+ }
+ 
+ static ssize_t
+-store_spi_transport_period_helper(struct class_device *cdev, const char *buf,
++store_spi_transport_period_helper(struct device *dev, const char *buf,
+ 				  size_t count, int *periodp)
+ {
+ 	int j, picosec, period = -1;
+@@ -449,9 +455,10 @@ store_spi_transport_period_helper(struct class_device *cdev, const char *buf,
+ }
+ 
+ static ssize_t
+-show_spi_transport_period(struct class_device *cdev, char *buf)
++show_spi_transport_period(struct device *dev,
++			  struct device_attribute *attr, char *buf)
+ {
+-	struct scsi_target *starget = transport_class_to_starget(cdev);
++	struct scsi_target *starget = transport_class_to_starget(dev);
+ 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ 	struct spi_internal *i = to_spi_internal(shost->transportt);
+ 	struct spi_transport_attrs *tp =
+@@ -464,8 +471,8 @@ show_spi_transport_period(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-store_spi_transport_period(struct class_device *cdev, const char *buf,
+-			    size_t count)
++store_spi_transport_period(struct device *cdev, struct device_attribute *attr,
++			   const char *buf, size_t count)
+ {
+ 	struct scsi_target *starget = transport_class_to_starget(cdev);
+ 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+@@ -487,12 +494,13 @@ store_spi_transport_period(struct class_device *cdev, const char *buf,
+ 	return retval;
+ }
+ 
+-static CLASS_DEVICE_ATTR(period, S_IRUGO,
+-			 show_spi_transport_period,
+-			 store_spi_transport_period);
++static DEVICE_ATTR(period, S_IRUGO,
++		   show_spi_transport_period,
++		   store_spi_transport_period);
+ 
+ static ssize_t
+-show_spi_transport_min_period(struct class_device *cdev, char *buf)
++show_spi_transport_min_period(struct device *cdev,
++			      struct device_attribute *attr, char *buf)
+ {
+ 	struct scsi_target *starget = transport_class_to_starget(cdev);
+ 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+@@ -507,8 +515,9 @@ show_spi_transport_min_period(struct class_device *cdev, char *buf)
+ }
+ 
+ static ssize_t
+-store_spi_transport_min_period(struct class_device *cdev, const char *buf,
+-			    size_t count)
++store_spi_transport_min_period(struct device *cdev,
++			       struct device_attribute *attr,
++			       const char *buf, size_t count)
+ {
+ 	struct scsi_target *starget = transport_class_to_starget(cdev);
+ 	struct spi_transport_attrs *tp =
+@@ -519,12 +528,14 @@ store_spi_transport_min_period(struct class_device *cdev, const char *buf,
+ }
+ 
+ 
+-static CLASS_DEVICE_ATTR(min_period, S_IRUGO,
+-			 show_spi_transport_min_period,
+-			 store_spi_transport_min_period);
++static DEVICE_ATTR(min_period, S_IRUGO,
++		   show_spi_transport_min_period,
++		   store_spi_transport_min_period);
+ 
+ 
+-static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf)
++static ssize_t show_spi_host_signalling(struct device *cdev,
++					struct device_attribute *attr,
++					char *buf)
+ {
+ 	struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ 	struct spi_internal *i = to_spi_internal(shost->transportt);
+@@ -534,10 +545,11 @@ static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf)
+ 
+ 	return sprintf(buf, "%s\n", spi_signal_to_string(spi_signalling(shost)));
+ }
+-static ssize_t store_spi_host_signalling(struct class_device *cdev,
++static ssize_t store_spi_host_signalling(struct device *dev,
++					 struct device_attribute *attr,
+ 					 const char *buf, size_t count)
+ {
+-	struct Scsi_Host *shost = transport_class_to_shost(cdev);
++	struct Scsi_Host *shost = transport_class_to_shost(dev);
+ 	struct spi_internal *i = to_spi_internal(shost->transportt);
+ 	enum spi_signal_type type = spi_signal_to_value(buf);
+ 
+@@ -549,9 +561,9 @@ static ssize_t store_spi_host_signalling(struct class_device *cdev,
+ 
+ 	return count;
+ }
+-static CLASS_DEVICE_ATTR(signalling, S_IRUGO,
+-			 show_spi_host_signalling,
+-			 store_spi_host_signalling);
++static DEVICE_ATTR(signalling, S_IRUGO,
++		   show_spi_host_signalling,
++		   store_spi_host_signalling);
+ 
+ #define DV_SET(x, y)			\
+ 	if(i->f->set_##x)		\
+@@ -1334,7 +1346,7 @@ static DECLARE_ANON_TRANSPORT_CLASS(spi_device_class,
+ 				    spi_device_configure);
+ 
+ static struct attribute *host_attributes[] = {
+-	&class_device_attr_signalling.attr,
++	&dev_attr_signalling.attr,
+ 	NULL
+ };
+ 
+@@ -1344,12 +1356,12 @@ static struct attribute_group host_attribute_group = {
+ 
+ static int spi_host_configure(struct transport_container *tc,
+ 			      struct device *dev,
+-			      struct class_device *cdev)
++			      struct device *cdev)
+ {
+ 	struct kobject *kobj = &cdev->kobj;
+ 	struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ 	struct spi_internal *si = to_spi_internal(shost->transportt);
+-	struct attribute *attr = &class_device_attr_signalling.attr;
++	struct attribute *attr = &dev_attr_signalling.attr;
+ 	int rc = 0;
+ 
+ 	if (si->f->set_signalling)
+@@ -1368,76 +1380,75 @@ static int spi_host_configure(struct transport_container *tc,
+ static int target_attribute_is_visible(struct kobject *kobj,
+ 				       struct attribute *attr, int i)
+ {
+-	struct class_device *cdev =
+-		container_of(kobj, struct class_device, kobj);
++	struct device *cdev = container_of(kobj, struct device, kobj);
+ 	struct scsi_target *starget = transport_class_to_starget(cdev);
+ 	struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ 	struct spi_internal *si = to_spi_internal(shost->transportt);
+ 
+-	if (attr == &class_device_attr_period.attr &&
++	if (attr == &dev_attr_period.attr &&
+ 	    spi_support_sync(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(period);
+-	else if (attr == &class_device_attr_min_period.attr &&
++	else if (attr == &dev_attr_min_period.attr &&
+ 		 spi_support_sync(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(period);
+-	else if (attr == &class_device_attr_offset.attr &&
++	else if (attr == &dev_attr_offset.attr &&
+ 		 spi_support_sync(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(offset);
+-	else if (attr == &class_device_attr_max_offset.attr &&
++	else if (attr == &dev_attr_max_offset.attr &&
+ 		 spi_support_sync(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(offset);
+-	else if (attr == &class_device_attr_width.attr &&
++	else if (attr == &dev_attr_width.attr &&
+ 		 spi_support_wide(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(width);
+-	else if (attr == &class_device_attr_max_width.attr &&
++	else if (attr == &dev_attr_max_width.attr &&
+ 		 spi_support_wide(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(width);
+-	else if (attr == &class_device_attr_iu.attr &&
++	else if (attr == &dev_attr_iu.attr &&
+ 		 spi_support_ius(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(iu);
+-	else if (attr == &class_device_attr_dt.attr &&
++	else if (attr == &dev_attr_dt.attr &&
+ 		 spi_support_dt(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(dt);
+-	else if (attr == &class_device_attr_qas.attr &&
++	else if (attr == &dev_attr_qas.attr &&
+ 		 spi_support_qas(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(qas);
+-	else if (attr == &class_device_attr_wr_flow.attr &&
++	else if (attr == &dev_attr_wr_flow.attr &&
+ 		 spi_support_ius(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(wr_flow);
+-	else if (attr == &class_device_attr_rd_strm.attr &&
++	else if (attr == &dev_attr_rd_strm.attr &&
+ 		 spi_support_ius(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(rd_strm);
+-	else if (attr == &class_device_attr_rti.attr &&
++	else if (attr == &dev_attr_rti.attr &&
+ 		 spi_support_ius(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(rti);
+-	else if (attr == &class_device_attr_pcomp_en.attr &&
++	else if (attr == &dev_attr_pcomp_en.attr &&
+ 		 spi_support_ius(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(pcomp_en);
+-	else if (attr == &class_device_attr_hold_mcs.attr &&
++	else if (attr == &dev_attr_hold_mcs.attr &&
+ 		 spi_support_ius(starget))
+ 		return TARGET_ATTRIBUTE_HELPER(hold_mcs);
+-	else if (attr == &class_device_attr_revalidate.attr)
++	else if (attr == &dev_attr_revalidate.attr)
+ 		return 1;
+ 
+ 	return 0;
+ }
+ 
+ static struct attribute *target_attributes[] = {
+-	&class_device_attr_period.attr,
+-	&class_device_attr_min_period.attr,
+-	&class_device_attr_offset.attr,
+-	&class_device_attr_max_offset.attr,
+-	&class_device_attr_width.attr,
+-	&class_device_attr_max_width.attr,
+-	&class_device_attr_iu.attr,
+-	&class_device_attr_dt.attr,
+-	&class_device_attr_qas.attr,
+-	&class_device_attr_wr_flow.attr,
+-	&class_device_attr_rd_strm.attr,
+-	&class_device_attr_rti.attr,
+-	&class_device_attr_pcomp_en.attr,
+-	&class_device_attr_hold_mcs.attr,
+-	&class_device_attr_revalidate.attr,
++	&dev_attr_period.attr,
++	&dev_attr_min_period.attr,
++	&dev_attr_offset.attr,
++	&dev_attr_max_offset.attr,
++	&dev_attr_width.attr,
++	&dev_attr_max_width.attr,
++	&dev_attr_iu.attr,
++	&dev_attr_dt.attr,
++	&dev_attr_qas.attr,
++	&dev_attr_wr_flow.attr,
++	&dev_attr_rd_strm.attr,
++	&dev_attr_rti.attr,
++	&dev_attr_pcomp_en.attr,
++	&dev_attr_hold_mcs.attr,
++	&dev_attr_revalidate.attr,
+ 	NULL
+ };
+ 
+@@ -1448,7 +1459,7 @@ static struct attribute_group target_attribute_group = {
+ 
+ static int spi_target_configure(struct transport_container *tc,
+ 				struct device *dev,
+-				struct class_device *cdev)
++				struct device *cdev)
+ {
+ 	struct kobject *kobj = &cdev->kobj;
+ 	int i;
+@@ -1462,7 +1473,7 @@ static int spi_target_configure(struct transport_container *tc,
+ 		 * to ignore, sysfs also does a WARN_ON and dumps a trace,
+ 		 * which is bad, so temporarily, skip attributes that are
+ 		 * already visible (the revalidate one) */
+-		if (j && attr != &class_device_attr_revalidate.attr)
++		if (j && attr != &dev_attr_revalidate.attr)
+ 			rc = sysfs_add_file_to_group(kobj, attr,
+ 						target_attribute_group.name);
+ 		/* and make the attribute writeable if we have a set
+diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
+index 2445c98..8a7af95 100644
+--- a/drivers/scsi/scsi_transport_srp.c
++++ b/drivers/scsi/scsi_transport_srp.c
+@@ -44,20 +44,20 @@ struct srp_internal {
+ 	struct scsi_transport_template t;
+ 	struct srp_function_template *f;
+ 
+-	struct class_device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
++	struct device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
+ 
+-	struct class_device_attribute *rport_attrs[SRP_RPORT_ATTRS + 1];
+-	struct class_device_attribute private_rport_attrs[SRP_RPORT_ATTRS];
++	struct device_attribute *rport_attrs[SRP_RPORT_ATTRS + 1];
++	struct device_attribute private_rport_attrs[SRP_RPORT_ATTRS];
+ 	struct transport_container rport_attr_cont;
+ };
+ 
+ #define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t)
+ 
+ #define	dev_to_rport(d)	container_of(d, struct srp_rport, dev)
+-#define transport_class_to_srp_rport(cdev) dev_to_rport((cdev)->dev)
++#define transport_class_to_srp_rport(dev) dev_to_rport((dev)->parent)
+ 
+ static int srp_host_setup(struct transport_container *tc, struct device *dev,
+-			  struct class_device *cdev)
++			  struct device *cdev)
+ {
+ 	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct srp_host_attrs *srp_host = to_srp_host_attrs(shost);
+@@ -73,7 +73,7 @@ static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports",
+ 			       NULL, NULL, NULL);
+ 
+ #define SETUP_TEMPLATE(attrb, field, perm, test, ro_test, ro_perm)	\
+-	i->private_##attrb[count] = class_device_attr_##field;		\
++	i->private_##attrb[count] = dev_attr_##field;		\
+ 	i->private_##attrb[count].attr.mode = perm;			\
+ 	if (ro_test) {							\
+ 		i->private_##attrb[count].attr.mode = ro_perm;		\
+@@ -100,13 +100,14 @@ static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports",
+ 	"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
+ 
+ static ssize_t
+-show_srp_rport_id(struct class_device *cdev, char *buf)
++show_srp_rport_id(struct device *dev, struct device_attribute *attr,
++		  char *buf)
+ {
+-	struct srp_rport *rport = transport_class_to_srp_rport(cdev);
++	struct srp_rport *rport = transport_class_to_srp_rport(dev);
+ 	return sprintf(buf, SRP_PID_FMT "\n", SRP_PID(rport));
+ }
+ 
+-static CLASS_DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL);
++static DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL);
+ 
+ static const struct {
+ 	u32 value;
+@@ -117,9 +118,10 @@ static const struct {
+ };
+ 
+ static ssize_t
+-show_srp_rport_roles(struct class_device *cdev, char *buf)
++show_srp_rport_roles(struct device *dev, struct device_attribute *attr,
++		     char *buf)
+ {
+-	struct srp_rport *rport = transport_class_to_srp_rport(cdev);
++	struct srp_rport *rport = transport_class_to_srp_rport(dev);
+ 	int i;
+ 	char *name = NULL;
+ 
+@@ -131,7 +133,7 @@ show_srp_rport_roles(struct class_device *cdev, char *buf)
+ 	return sprintf(buf, "%s\n", name ? : "unknown");
+ }
+ 
+-static CLASS_DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);
++static DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);
+ 
+ static void srp_rport_release(struct device *dev)
+ {
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 5fe7aae..3cea17d 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -95,7 +95,7 @@ static int sd_resume(struct device *);
+ static void sd_rescan(struct device *);
+ static int sd_done(struct scsi_cmnd *);
+ static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
+-static void scsi_disk_release(struct class_device *cdev);
++static void scsi_disk_release(struct device *cdev);
+ static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
+ static void sd_print_result(struct scsi_disk *, int);
+ 
+@@ -112,11 +112,12 @@ static const char *sd_cache_types[] = {
+ 	"write back, no read (daft)"
+ };
+ 
+-static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
+-				   size_t count)
++static ssize_t
++sd_store_cache_type(struct device *dev, struct device_attribute *attr,
++		    const char *buf, size_t count)
+ {
+ 	int i, ct = -1, rcd, wce, sp;
+-	struct scsi_disk *sdkp = to_scsi_disk(cdev);
++	struct scsi_disk *sdkp = to_scsi_disk(dev);
+ 	struct scsi_device *sdp = sdkp->device;
+ 	char buffer[64];
+ 	char *buffer_data;
+@@ -163,10 +164,11 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
+ 	return count;
+ }
+ 
+-static ssize_t sd_store_manage_start_stop(struct class_device *cdev,
+-					  const char *buf, size_t count)
++static ssize_t
++sd_store_manage_start_stop(struct device *dev, struct device_attribute *attr,
++			   const char *buf, size_t count)
+ {
+-	struct scsi_disk *sdkp = to_scsi_disk(cdev);
++	struct scsi_disk *sdkp = to_scsi_disk(dev);
+ 	struct scsi_device *sdp = sdkp->device;
+ 
+ 	if (!capable(CAP_SYS_ADMIN))
+@@ -177,10 +179,11 @@ static ssize_t sd_store_manage_start_stop(struct class_device *cdev,
+ 	return count;
+ }
+ 
+-static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf,
+-				      size_t count)
++static ssize_t
++sd_store_allow_restart(struct device *dev, struct device_attribute *attr,
++		       const char *buf, size_t count)
+ {
+-	struct scsi_disk *sdkp = to_scsi_disk(cdev);
++	struct scsi_disk *sdkp = to_scsi_disk(dev);
+ 	struct scsi_device *sdp = sdkp->device;
+ 
+ 	if (!capable(CAP_SYS_ADMIN))
+@@ -194,37 +197,44 @@ static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf
+ 	return count;
+ }
+ 
+-static ssize_t sd_show_cache_type(struct class_device *cdev, char *buf)
++static ssize_t
++sd_show_cache_type(struct device *dev, struct device_attribute *attr,
++		   char *buf)
+ {
+-	struct scsi_disk *sdkp = to_scsi_disk(cdev);
++	struct scsi_disk *sdkp = to_scsi_disk(dev);
+ 	int ct = sdkp->RCD + 2*sdkp->WCE;
+ 
+ 	return snprintf(buf, 40, "%s\n", sd_cache_types[ct]);
+ }
+ 
+-static ssize_t sd_show_fua(struct class_device *cdev, char *buf)
++static ssize_t
++sd_show_fua(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct scsi_disk *sdkp = to_scsi_disk(cdev);
++	struct scsi_disk *sdkp = to_scsi_disk(dev);
+ 
+ 	return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
+ }
+ 
+-static ssize_t sd_show_manage_start_stop(struct class_device *cdev, char *buf)
++static ssize_t
++sd_show_manage_start_stop(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+-	struct scsi_disk *sdkp = to_scsi_disk(cdev);
++	struct scsi_disk *sdkp = to_scsi_disk(dev);
+ 	struct scsi_device *sdp = sdkp->device;
+ 
+ 	return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
+ }
+ 
+-static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf)
++static ssize_t
++sd_show_allow_restart(struct device *dev, struct device_attribute *attr,
++		      char *buf)
+ {
+-	struct scsi_disk *sdkp = to_scsi_disk(cdev);
++	struct scsi_disk *sdkp = to_scsi_disk(dev);
+ 
+ 	return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
+ }
+ 
+-static struct class_device_attribute sd_disk_attrs[] = {
++static struct device_attribute sd_disk_attrs[] = {
+ 	__ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
+ 	       sd_store_cache_type),
+ 	__ATTR(FUA, S_IRUGO, sd_show_fua, NULL),
+@@ -238,8 +248,8 @@ static struct class_device_attribute sd_disk_attrs[] = {
+ static struct class sd_disk_class = {
+ 	.name		= "scsi_disk",
+ 	.owner		= THIS_MODULE,
+-	.release	= scsi_disk_release,
+-	.class_dev_attrs = sd_disk_attrs,
++	.dev_release	= scsi_disk_release,
++	.dev_attrs	= sd_disk_attrs,
+ };
+ 
+ static struct scsi_driver sd_template = {
+@@ -297,7 +307,7 @@ static struct scsi_disk *__scsi_disk_get(struct gendisk *disk)
+ 	if (disk->private_data) {
+ 		sdkp = scsi_disk(disk);
+ 		if (scsi_device_get(sdkp->device) == 0)
+-			class_device_get(&sdkp->cdev);
++			get_device(&sdkp->dev);
+ 		else
+ 			sdkp = NULL;
+ 	}
+@@ -331,7 +341,7 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
+ 	struct scsi_device *sdev = sdkp->device;
+ 
+ 	mutex_lock(&sd_ref_mutex);
+-	class_device_put(&sdkp->cdev);
++	put_device(&sdkp->dev);
+ 	scsi_device_put(sdev);
+ 	mutex_unlock(&sd_ref_mutex);
+ }
+@@ -1663,12 +1673,12 @@ static int sd_probe(struct device *dev)
+ 			sdp->timeout = SD_MOD_TIMEOUT;
+ 	}
+ 
+-	class_device_initialize(&sdkp->cdev);
+-	sdkp->cdev.dev = &sdp->sdev_gendev;
+-	sdkp->cdev.class = &sd_disk_class;
+-	strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
++	device_initialize(&sdkp->dev);
++	sdkp->dev.parent = &sdp->sdev_gendev;
++	sdkp->dev.class = &sd_disk_class;
++	strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
+ 
+-	if (class_device_add(&sdkp->cdev))
++	if (device_add(&sdkp->dev))
+ 		goto out_put;
+ 
+ 	get_device(&sdp->sdev_gendev);
+@@ -1734,13 +1744,13 @@ static int sd_remove(struct device *dev)
+ {
+ 	struct scsi_disk *sdkp = dev_get_drvdata(dev);
+ 
+-	class_device_del(&sdkp->cdev);
++	device_del(&sdkp->dev);
+ 	del_gendisk(sdkp->disk);
+ 	sd_shutdown(dev);
+ 
+ 	mutex_lock(&sd_ref_mutex);
+ 	dev_set_drvdata(dev, NULL);
+-	class_device_put(&sdkp->cdev);
++	put_device(&sdkp->dev);
+ 	mutex_unlock(&sd_ref_mutex);
+ 
+ 	return 0;
+@@ -1748,16 +1758,16 @@ static int sd_remove(struct device *dev)
+ 
+ /**
+  *	scsi_disk_release - Called to free the scsi_disk structure
+- *	@cdev: pointer to embedded class device
++ *	@dev: pointer to embedded class device
+  *
+  *	sd_ref_mutex must be held entering this routine.  Because it is
+  *	called on last put, you should always use the scsi_disk_get()
+  *	scsi_disk_put() helpers which manipulate the semaphore directly
+- *	and never do a direct class_device_put().
++ *	and never do a direct put_device.
+  **/
+-static void scsi_disk_release(struct class_device *cdev)
++static void scsi_disk_release(struct device *dev)
+ {
+-	struct scsi_disk *sdkp = to_scsi_disk(cdev);
++	struct scsi_disk *sdkp = to_scsi_disk(dev);
+ 	struct gendisk *disk = sdkp->disk;
+ 	
+ 	spin_lock(&sd_index_lock);
+diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
+index a6d9669..45df83b 100644
+--- a/drivers/scsi/ses.c
++++ b/drivers/scsi/ses.c
+@@ -107,7 +107,7 @@ static int ses_set_page2_descriptor(struct enclosure_device *edev,
+ 				      unsigned char *desc)
+ {
+ 	int i, j, count = 0, descriptor = ecomp->number;
+-	struct scsi_device *sdev = to_scsi_device(edev->cdev.dev);
++	struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
+ 	struct ses_device *ses_dev = edev->scratch;
+ 	unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+ 	unsigned char *desc_ptr = ses_dev->page2 + 8;
+@@ -137,7 +137,7 @@ static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev,
+ 				      struct enclosure_component *ecomp)
+ {
+ 	int i, j, count = 0, descriptor = ecomp->number;
+-	struct scsi_device *sdev = to_scsi_device(edev->cdev.dev);
++	struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
+ 	struct ses_device *ses_dev = edev->scratch;
+ 	unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+ 	unsigned char *desc_ptr = ses_dev->page2 + 8;
+@@ -269,10 +269,10 @@ int ses_match_host(struct enclosure_device *edev, void *data)
+ 	struct ses_host_edev *sed = data;
+ 	struct scsi_device *sdev;
+ 
+-	if (!scsi_is_sdev_device(edev->cdev.dev))
++	if (!scsi_is_sdev_device(edev->edev.parent))
+ 		return 0;
+ 
+-	sdev = to_scsi_device(edev->cdev.dev);
++	sdev = to_scsi_device(edev->edev.parent);
+ 
+ 	if (sdev->host != sed->shost)
+ 		return 0;
+@@ -407,10 +407,10 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
+ 
+ #define INIT_ALLOC_SIZE 32
+ 
+-static int ses_intf_add(struct class_device *cdev,
++static int ses_intf_add(struct device *cdev,
+ 			struct class_interface *intf)
+ {
+-	struct scsi_device *sdev = to_scsi_device(cdev->dev);
++	struct scsi_device *sdev = to_scsi_device(cdev->parent);
+ 	struct scsi_device *tmp_sdev;
+ 	unsigned char *buf = NULL, *hdr_buf, *type_ptr, *desc_ptr = NULL,
+ 		*addl_desc_ptr = NULL;
+@@ -426,7 +426,7 @@ static int ses_intf_add(struct class_device *cdev,
+ 		edev = enclosure_find(&sdev->host->shost_gendev);
+ 		if (edev) {
+ 			ses_match_to_enclosure(edev, sdev);
+-			class_device_put(&edev->cdev);
++			put_device(&edev->edev);
+ 		}
+ 		return -ENODEV;
+ 	}
+@@ -515,7 +515,7 @@ static int ses_intf_add(struct class_device *cdev,
+ 	if (!scomp)
+ 		goto err_free;
+ 
+-	edev = enclosure_register(cdev->dev, sdev->sdev_gendev.bus_id,
++	edev = enclosure_register(cdev->parent, sdev->sdev_gendev.bus_id,
+ 				  components, &ses_enclosure_callbacks);
+ 	if (IS_ERR(edev)) {
+ 		err = PTR_ERR(edev);
+@@ -625,17 +625,17 @@ static int ses_remove(struct device *dev)
+ 	return 0;
+ }
+ 
+-static void ses_intf_remove(struct class_device *cdev,
++static void ses_intf_remove(struct device *cdev,
+ 			    struct class_interface *intf)
+ {
+-	struct scsi_device *sdev = to_scsi_device(cdev->dev);
++	struct scsi_device *sdev = to_scsi_device(cdev->parent);
+ 	struct enclosure_device *edev;
+ 	struct ses_device *ses_dev;
+ 
+ 	if (!scsi_device_enclosure(sdev))
+ 		return;
+ 
+-	edev = enclosure_find(cdev->dev);
++	edev = enclosure_find(cdev->parent);
+ 	if (!edev)
+ 		return;
+ 
+@@ -649,13 +649,13 @@ static void ses_intf_remove(struct class_device *cdev,
+ 
+ 	kfree(edev->component[0].scratch);
+ 
+-	class_device_put(&edev->cdev);
++	put_device(&edev->edev);
+ 	enclosure_unregister(edev);
+ }
+ 
+ static struct class_interface ses_interface = {
+-	.add	= ses_intf_add,
+-	.remove	= ses_intf_remove,
++	.add_dev	= ses_intf_add,
++	.remove_dev	= ses_intf_remove,
+ };
+ 
+ static struct scsi_driver ses_template = {
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index e5156aa..2029422 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -101,16 +101,16 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ;
+ #define SG_SECTOR_SZ 512
+ #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
+ 
+-static int sg_add(struct class_device *, struct class_interface *);
+-static void sg_remove(struct class_device *, struct class_interface *);
++static int sg_add(struct device *, struct class_interface *);
++static void sg_remove(struct device *, struct class_interface *);
+ 
+ static DEFINE_IDR(sg_index_idr);
+ static DEFINE_RWLOCK(sg_index_lock);	/* Also used to lock
+ 							   file descriptor list for device */
+ 
+ static struct class_interface sg_interface = {
+-	.add		= sg_add,
+-	.remove		= sg_remove,
++	.add_dev	= sg_add,
++	.remove_dev	= sg_remove,
+ };
+ 
+ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
+@@ -1401,9 +1401,9 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
+ }
+ 
+ static int
+-sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
++sg_add(struct device *cl_dev, struct class_interface *cl_intf)
+ {
+-	struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
++	struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
+ 	struct gendisk *disk;
+ 	Sg_device *sdp = NULL;
+ 	struct cdev * cdev = NULL;
+@@ -1439,19 +1439,19 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
+ 
+ 	sdp->cdev = cdev;
+ 	if (sg_sysfs_valid) {
+-		struct class_device * sg_class_member;
++		struct device *sg_class_member;
+ 
+-		sg_class_member = class_device_create(sg_sysfs_class, NULL,
+-				MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
+-				cl_dev->dev, "%s",
+-				disk->disk_name);
++		sg_class_member = device_create(sg_sysfs_class, cl_dev->parent,
++						MKDEV(SCSI_GENERIC_MAJOR,
++						      sdp->index),
++						"%s", disk->disk_name);
+ 		if (IS_ERR(sg_class_member)) {
+ 			printk(KERN_ERR "sg_add: "
+-			       "class_device_create failed\n");
++			       "device_create failed\n");
+ 			error = PTR_ERR(sg_class_member);
+ 			goto cdev_add_err;
+ 		}
+-		class_set_devdata(sg_class_member, sdp);
++		dev_set_drvdata(sg_class_member, sdp);
+ 		error = sysfs_create_link(&scsidp->sdev_gendev.kobj,
+ 					  &sg_class_member->kobj, "generic");
+ 		if (error)
+@@ -1464,7 +1464,7 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
+ 		    "Attached scsi generic sg%d type %d\n", sdp->index,
+ 		    scsidp->type);
+ 
+-	class_set_devdata(cl_dev, sdp);
++	dev_set_drvdata(cl_dev, sdp);
+ 
+ 	return 0;
+ 
+@@ -1482,10 +1482,10 @@ out:
+ }
+ 
+ static void
+-sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
++sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
+ {
+-	struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
+-	Sg_device *sdp = class_get_devdata(cl_dev);
++	struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
++	Sg_device *sdp = dev_get_drvdata(cl_dev);
+ 	unsigned long iflags;
+ 	Sg_fd *sfp;
+ 	Sg_fd *tsfp;
+@@ -1528,7 +1528,7 @@ sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
+ 	write_unlock_irqrestore(&sg_index_lock, iflags);
+ 
+ 	sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
+-	class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
++	device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
+ 	cdev_del(sdp->cdev);
+ 	sdp->cdev = NULL;
+ 	put_disk(sdp->disk);
+diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
+index 26cfc56..03e3596 100644
+--- a/drivers/scsi/sgiwd93.c
++++ b/drivers/scsi/sgiwd93.c
+@@ -263,10 +263,11 @@ static int __init sgiwd93_probe(struct platform_device *pdev)
+ 	regs.SASR = wdregs + 3;
+ 	regs.SCMD = wdregs + 7;
+ 
+-	wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
++	hdata->wh.no_sync = 0;
++	hdata->wh.fast = 1;
++	hdata->wh.dma_mode = CTRL_BURST;
+ 
+-	if (hdata->wh.no_sync == 0xff)
+-		hdata->wh.no_sync = 0;
++	wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
+ 
+ 	err = request_irq(irq, sgiwd93_intr, 0, "SGI WD93", host);
+ 	if (err) {
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 0a52d9d..a860c3a 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -17,7 +17,7 @@
+    Last modified: 18-JAN-1998 Richard Gooch <rgooch at atnf.csiro.au> Devfs support
+  */
+ 
+-static const char *verstr = "20080221";
++static const char *verstr = "20080224";
+ 
+ #include <linux/module.h>
+ 
+@@ -183,6 +183,7 @@ static int modes_defined;
+ 
+ static struct st_buffer *new_tape_buffer(int, int, int);
+ static int enlarge_buffer(struct st_buffer *, int, int);
++static void clear_buffer(struct st_buffer *);
+ static void normalize_buffer(struct st_buffer *);
+ static int append_to_buffer(const char __user *, struct st_buffer *, int);
+ static int from_buffer(struct st_buffer *, char __user *, int);
+@@ -442,6 +443,7 @@ static void st_sleep_done(void *data, char *sense, int result, int resid)
+ 
+ 	memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
+ 	(STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
++	(STp->buffer)->cmdstat.residual = resid;
+ 	DEB( STp->write_pending = 0; )
+ 
+ 	if (SRpnt->waiting)
+@@ -626,7 +628,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
+ 
+ 
+ /* Flush the write buffer (never need to write if variable blocksize). */
+-static int flush_write_buffer(struct scsi_tape * STp)
++static int st_flush_write_buffer(struct scsi_tape * STp)
+ {
+ 	int offset, transfer, blks;
+ 	int result;
+@@ -717,7 +719,7 @@ static int flush_buffer(struct scsi_tape *STp, int seek_next)
+ 		return 0;
+ 	STps = &(STp->ps[STp->partition]);
+ 	if (STps->rw == ST_WRITING)	/* Writing */
+-		return flush_write_buffer(STp);
++		return st_flush_write_buffer(STp);
+ 
+ 	if (STp->block_size == 0)
+ 		return 0;
+@@ -1159,6 +1161,7 @@ static int st_open(struct inode *inode, struct file *filp)
+ 		goto err_out;
+ 	}
+ 
++	(STp->buffer)->cleared = 0;
+ 	(STp->buffer)->writing = 0;
+ 	(STp->buffer)->syscall_result = 0;
+ 
+@@ -1211,7 +1214,7 @@ static int st_flush(struct file *filp, fl_owner_t id)
+ 		return 0;
+ 
+ 	if (STps->rw == ST_WRITING && !STp->pos_unknown) {
+-		result = flush_write_buffer(STp);
++		result = st_flush_write_buffer(STp);
+ 		if (result != 0 && result != (-ENOSPC))
+ 			goto out;
+ 	}
+@@ -1432,8 +1435,14 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
+ 		if (STp->block_size)
+ 			bufsize = STp->block_size > st_fixed_buffer_size ?
+ 				STp->block_size : st_fixed_buffer_size;
+-		else
++		else {
+ 			bufsize = count;
++			/* Make sure that data from previous user is not leaked even if
++			   HBA does not return correct residual */
++			if (is_read && STp->sili && !STbp->cleared)
++				clear_buffer(STbp);
++		}
++
+ 		if (bufsize > STbp->buffer_size &&
+ 		    !enlarge_buffer(STbp, bufsize, STp->restr_dma)) {
+ 			printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n",
+@@ -1783,6 +1792,8 @@ static long read_tape(struct scsi_tape *STp, long count,
+ 	memset(cmd, 0, MAX_COMMAND_SIZE);
+ 	cmd[0] = READ_6;
+ 	cmd[1] = (STp->block_size != 0);
++	if (!cmd[1] && STp->sili)
++		cmd[1] |= 2;
+ 	cmd[2] = blks >> 16;
+ 	cmd[3] = blks >> 8;
+ 	cmd[4] = blks;
+@@ -1911,8 +1922,11 @@ static long read_tape(struct scsi_tape *STp, long count,
+ 
+ 	}
+ 	/* End of error handling */ 
+-	else			/* Read successful */
++	else {			/* Read successful */
+ 		STbp->buffer_bytes = bytes;
++		if (STp->sili) /* In fixed block mode residual is always zero here */
++			STbp->buffer_bytes -= STp->buffer->cmdstat.residual;
++	}
+ 
+ 	if (STps->drv_block >= 0) {
+ 		if (STp->block_size == 0)
+@@ -2090,7 +2104,8 @@ static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char
+ 		       name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
+ 		       STp->scsi2_logical);
+ 		printk(KERN_INFO
+-		       "%s:    sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate);
++		       "%s:    sysv: %d nowait: %d sili: %d\n", name, STm->sysv, STp->immediate,
++			STp->sili);
+ 		printk(KERN_INFO "%s:    debugging: %d\n",
+ 		       name, debugging);
+ 	}
+@@ -2133,6 +2148,7 @@ static int st_set_options(struct scsi_tape *STp, long options)
+ 		STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
+ 		STp->immediate = (options & MT_ST_NOWAIT) != 0;
+ 		STm->sysv = (options & MT_ST_SYSV) != 0;
++		STp->sili = (options & MT_ST_SILI) != 0;
+ 		DEB( debugging = (options & MT_ST_DEBUGGING) != 0;
+ 		     st_log_options(STp, STm, name); )
+ 	} else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
+@@ -2164,6 +2180,8 @@ static int st_set_options(struct scsi_tape *STp, long options)
+ 			STp->immediate = value;
+ 		if ((options & MT_ST_SYSV) != 0)
+ 			STm->sysv = value;
++		if ((options & MT_ST_SILI) != 0)
++			STp->sili = value;
+                 DEB(
+ 		if ((options & MT_ST_DEBUGGING) != 0)
+ 			debugging = value;
+@@ -3655,6 +3673,8 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
+ 		STbuffer->frp_segs += 1;
+ 		got += b_size;
+ 		STbuffer->buffer_size = got;
++		if (STbuffer->cleared)
++			memset(page_address(STbuffer->frp[segs].page), 0, b_size);
+ 		segs++;
+ 	}
+ 	STbuffer->b_data = page_address(STbuffer->frp[0].page);
+@@ -3663,6 +3683,17 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
+ }
+ 
+ 
++/* Make sure that no data from previous user is in the internal buffer */
++static void clear_buffer(struct st_buffer * st_bp)
++{
++	int i;
++
++	for (i=0; i < st_bp->frp_segs; i++)
++		memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length);
++	st_bp->cleared = 1;
++}
++
++
+ /* Release the extra buffer */
+ static void normalize_buffer(struct st_buffer * STbuffer)
+ {
+@@ -3987,6 +4018,7 @@ static int st_probe(struct device *dev)
+ 	tpnt->two_fm = ST_TWO_FM;
+ 	tpnt->fast_mteom = ST_FAST_MTEOM;
+ 	tpnt->scsi2_logical = ST_SCSI2LOGICAL;
++	tpnt->sili = ST_SILI;
+ 	tpnt->immediate = ST_NOWAIT;
+ 	tpnt->default_drvbuffer = 0xff;		/* No forced buffering */
+ 	tpnt->partition = 0;
+@@ -4076,9 +4108,9 @@ out_free_tape:
+ 			if (STm->cdevs[j]) {
+ 				if (cdev == STm->cdevs[j])
+ 					cdev = NULL;
+-				class_device_destroy(st_sysfs_class,
+-						     MKDEV(SCSI_TAPE_MAJOR,
+-							   TAPE_MINOR(i, mode, j)));
++					device_destroy(st_sysfs_class,
++						       MKDEV(SCSI_TAPE_MAJOR,
++							     TAPE_MINOR(i, mode, j)));
+ 				cdev_del(STm->cdevs[j]);
+ 			}
+ 		}
+@@ -4116,9 +4148,9 @@ static int st_remove(struct device *dev)
+ 					  "tape");
+ 			for (mode = 0; mode < ST_NBR_MODES; ++mode) {
+ 				for (j=0; j < 2; j++) {
+-					class_device_destroy(st_sysfs_class,
+-							     MKDEV(SCSI_TAPE_MAJOR,
+-								   TAPE_MINOR(i, mode, j)));
++					device_destroy(st_sysfs_class,
++						       MKDEV(SCSI_TAPE_MAJOR,
++							     TAPE_MINOR(i, mode, j)));
+ 					cdev_del(tpnt->modes[mode].cdevs[j]);
+ 					tpnt->modes[mode].cdevs[j] = NULL;
+ 				}
+@@ -4287,31 +4319,34 @@ static void do_remove_sysfs_files(void)
+ 
+ 
+ /* The sysfs simple class interface */
+-static ssize_t st_defined_show(struct class_device *class_dev, char *buf)
++static ssize_t
++st_defined_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
++	struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+ 	ssize_t l = 0;
+ 
+ 	l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
++DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
+ 
+-static ssize_t st_defblk_show(struct class_device *class_dev, char *buf)
++static ssize_t
++st_defblk_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
++	struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+ 	ssize_t l = 0;
+ 
+ 	l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
++DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
+ 
+-static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf)
++static ssize_t
++st_defdensity_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
++	struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+ 	ssize_t l = 0;
+ 	char *fmt;
+ 
+@@ -4320,24 +4355,67 @@ static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf)
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
++DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
+ 
+-static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf)
++static ssize_t
++st_defcompression_show(struct device *dev, struct device_attribute *attr,
++		       char *buf)
+ {
+-	struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
++	struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+ 	ssize_t l = 0;
+ 
+ 	l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
+ 	return l;
+ }
+ 
+-CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
++DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
++
++static ssize_t
++st_options_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
++	struct scsi_tape *STp;
++	int i, j, options;
++	ssize_t l = 0;
++
++	for (i=0; i < st_dev_max; i++) {
++		for (j=0; j < ST_NBR_MODES; j++)
++			if (&scsi_tapes[i]->modes[j] == STm)
++				break;
++		if (j < ST_NBR_MODES)
++			break;
++	}
++	if (i == st_dev_max)
++		return 0;  /* should never happen */
++
++	STp = scsi_tapes[i];
++
++	options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0;
++	options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0;
++	options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0;
++	DEB( options |= debugging ? MT_ST_DEBUGGING : 0 );
++	options |= STp->two_fm ? MT_ST_TWO_FM : 0;
++	options |= STp->fast_mteom ? MT_ST_FAST_MTEOM : 0;
++	options |= STm->defaults_for_writes ? MT_ST_DEF_WRITES : 0;
++	options |= STp->can_bsr ? MT_ST_CAN_BSR : 0;
++	options |= STp->omit_blklims ? MT_ST_NO_BLKLIMS : 0;
++	options |= STp->can_partitions ? MT_ST_CAN_PARTITIONS : 0;
++	options |= STp->scsi2_logical ? MT_ST_SCSI2LOGICAL : 0;
++	options |= STm->sysv ? MT_ST_SYSV : 0;
++	options |= STp->immediate ? MT_ST_NOWAIT : 0;
++	options |= STp->sili ? MT_ST_SILI : 0;
++
++	l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options);
++	return l;
++}
++
++DEVICE_ATTR(options, S_IRUGO, st_options_show, NULL);
+ 
+ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
+ {
+ 	int i, rew, error;
+ 	char name[10];
+-	struct class_device *st_class_member;
++	struct device *st_class_member;
+ 
+ 	for (rew=0; rew < 2; rew++) {
+ 		/* Make sure that the minor numbers corresponding to the four
+@@ -4346,29 +4424,32 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
+ 		snprintf(name, 10, "%s%s%s", rew ? "n" : "",
+ 			 STp->disk->disk_name, st_formats[i]);
+ 		st_class_member =
+-			class_device_create(st_sysfs_class, NULL,
+-					    MKDEV(SCSI_TAPE_MAJOR,
+-						  TAPE_MINOR(dev_num, mode, rew)),
+-					    &STp->device->sdev_gendev, "%s", name);
++			device_create(st_sysfs_class, &STp->device->sdev_gendev,
++				      MKDEV(SCSI_TAPE_MAJOR,
++						TAPE_MINOR(dev_num, mode, rew)),
++				      "%s", name);
+ 		if (IS_ERR(st_class_member)) {
+-			printk(KERN_WARNING "st%d: class_device_create failed\n",
++			printk(KERN_WARNING "st%d: device_create failed\n",
+ 			       dev_num);
+ 			error = PTR_ERR(st_class_member);
+ 			goto out;
+ 		}
+-		class_set_devdata(st_class_member, &STp->modes[mode]);
++		dev_set_drvdata(st_class_member, &STp->modes[mode]);
+ 
+-		error = class_device_create_file(st_class_member,
+-					       &class_device_attr_defined);
++		error = device_create_file(st_class_member,
++					   &dev_attr_defined);
++		if (error) goto out;
++		error = device_create_file(st_class_member,
++					   &dev_attr_default_blksize);
+ 		if (error) goto out;
+-		error = class_device_create_file(st_class_member,
+-					    &class_device_attr_default_blksize);
++		error = device_create_file(st_class_member,
++					   &dev_attr_default_density);
+ 		if (error) goto out;
+-		error = class_device_create_file(st_class_member,
+-					    &class_device_attr_default_density);
++		error = device_create_file(st_class_member,
++					   &dev_attr_default_compression);
+ 		if (error) goto out;
+-		error = class_device_create_file(st_class_member,
+-				        &class_device_attr_default_compression);
++		error = device_create_file(st_class_member,
++					   &dev_attr_options);
+ 		if (error) goto out;
+ 
+ 		if (mode == 0 && rew == 0) {
+diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
+index 5931726..b92712f 100644
+--- a/drivers/scsi/st.h
++++ b/drivers/scsi/st.h
+@@ -12,6 +12,7 @@ struct st_cmdstatus {
+ 	int midlevel_result;
+ 	struct scsi_sense_hdr sense_hdr;
+ 	int have_sense;
++	int residual;
+ 	u64 uremainder64;
+ 	u8 flags;
+ 	u8 remainder_valid;
+@@ -34,6 +35,7 @@ struct st_request {
+ struct st_buffer {
+ 	unsigned char dma;	/* DMA-able buffer */
+ 	unsigned char do_dio;   /* direct i/o set up? */
++	unsigned char cleared;  /* internal buffer cleared after open? */
+ 	int buffer_size;
+ 	int buffer_blocks;
+ 	int buffer_bytes;
+@@ -122,6 +124,7 @@ struct scsi_tape {
+ 	unsigned char try_dio_now;		/* try direct i/o before next close? */
+ 	unsigned char c_algo;			/* compression algorithm */
+ 	unsigned char pos_unknown;			/* after reset position unknown */
++	unsigned char sili;			/* use SILI when reading in variable b mode */
+ 	int tape_type;
+ 	int long_timeout;	/* timeout for commands known to take long time */
+ 
+diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h
+index b6b5c9c..d2f9479 100644
+--- a/drivers/scsi/st_options.h
++++ b/drivers/scsi/st_options.h
+@@ -3,7 +3,7 @@
+ 
+    Copyright 1995-2003 Kai Makisara.
+ 
+-   Last modified: Mon Apr  7 22:49:18 2003 by makisara
++   Last modified: Thu Feb 21 21:47:07 2008 by kai.makisara
+ */
+ 
+ #ifndef _ST_OPTIONS_H
+@@ -94,6 +94,10 @@
+    The default is BSD semantics. */
+ #define ST_SYSV 0
+ 
++/* If ST_SILI is non-zero, the SILI bit is set when reading in variable block
++   mode and the block size is determined using the residual returned by the HBA. */
++#define ST_SILI 0
++
+ /* Time to wait for the drive to become ready if blocking open */
+ #define ST_BLOCK_SECONDS     120
+ 
+diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
+index 654430e..f308a03 100644
+--- a/drivers/scsi/stex.c
++++ b/drivers/scsi/stex.c
+@@ -33,6 +33,7 @@
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_dbg.h>
++#include <scsi/scsi_eh.h>
+ 
+ #define DRV_NAME "stex"
+ #define ST_DRIVER_VERSION "3.6.0000.1"
+@@ -362,22 +363,14 @@ static struct status_msg *stex_get_status(struct st_hba *hba)
+ 	return status;
+ }
+ 
+-static void stex_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+-{
+-	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+-
+-	cmd->sense_buffer[0] = 0x70;    /* fixed format, current */
+-	cmd->sense_buffer[2] = sk;
+-	cmd->sense_buffer[7] = 18 - 8;  /* additional sense length */
+-	cmd->sense_buffer[12] = asc;
+-	cmd->sense_buffer[13] = ascq;
+-}
+-
+ static void stex_invalid_field(struct scsi_cmnd *cmd,
+ 			       void (*done)(struct scsi_cmnd *))
+ {
++	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++
+ 	/* "Invalid field in cbd" */
+-	stex_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
++	scsi_build_sense_buffer(0, cmd->sense_buffer, ILLEGAL_REQUEST, 0x24,
++				0x0);
+ 	done(cmd);
+ }
+ 
+@@ -426,49 +419,13 @@ static int stex_map_sg(struct st_hba *hba,
+ 	return 0;
+ }
+ 
+-static void stex_internal_copy(struct scsi_cmnd *cmd,
+-	const void *src, size_t *count, int sg_count, int direction)
+-{
+-	size_t lcount;
+-	size_t len;
+-	void *s, *d, *base = NULL;
+-	size_t offset;
+-
+-	if (*count > scsi_bufflen(cmd))
+-		*count = scsi_bufflen(cmd);
+-	lcount = *count;
+-	while (lcount) {
+-		len = lcount;
+-		s = (void *)src;
+-
+-		offset = *count - lcount;
+-		s += offset;
+-		base = scsi_kmap_atomic_sg(scsi_sglist(cmd),
+-					   sg_count, &offset, &len);
+-		if (!base) {
+-			*count -= lcount;
+-			return;
+-		}
+-		d = base + offset;
+-
+-		if (direction == ST_TO_CMD)
+-			memcpy(d, s, len);
+-		else
+-			memcpy(s, d, len);
+-
+-		lcount -= len;
+-		scsi_kunmap_atomic_sg(base);
+-	}
+-}
+-
+ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
+ {
+ 	struct st_frame *p;
+ 	size_t count = sizeof(struct st_frame);
+ 
+ 	p = hba->copy_buffer;
+-	stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
+-			   ST_FROM_CMD);
++	count = scsi_sg_copy_to_buffer(ccb->cmd, p, count);
+ 	memset(p->base, 0, sizeof(u32)*6);
+ 	*(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
+ 	p->rom_addr = 0;
+@@ -486,8 +443,7 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
+ 	p->subid =
+ 		hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
+ 
+-	stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
+-			   ST_TO_CMD);
++	count = scsi_sg_copy_from_buffer(ccb->cmd, p, count);
+ }
+ 
+ static void
+@@ -554,10 +510,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
+ 		unsigned char page;
+ 		page = cmd->cmnd[2] & 0x3f;
+ 		if (page == 0x8 || page == 0x3f) {
+-			size_t cp_len = sizeof(ms10_caching_page);
+-			stex_internal_copy(cmd, ms10_caching_page,
+-					   &cp_len, scsi_sg_count(cmd),
+-					   ST_TO_CMD);
++			scsi_sg_copy_from_buffer(cmd, ms10_caching_page,
++						 sizeof(ms10_caching_page));
+ 			cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ 			done(cmd);
+ 		} else
+@@ -586,10 +540,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
+ 		if (id != host->max_id - 1)
+ 			break;
+ 		if (lun == 0 && (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
+-			size_t cp_len = sizeof(console_inq_page);
+-			stex_internal_copy(cmd, console_inq_page,
+-					   &cp_len, scsi_sg_count(cmd),
+-					   ST_TO_CMD);
++			scsi_sg_copy_from_buffer(cmd, (void *)console_inq_page,
++						 sizeof(console_inq_page));
+ 			cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ 			done(cmd);
+ 		} else
+@@ -606,8 +558,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
+ 			ver.signature[0] = PASSTHRU_SIGNATURE;
+ 			ver.console_id = host->max_id - 1;
+ 			ver.host_no = hba->host->host_no;
+-			stex_internal_copy(cmd, &ver, &cp_len,
+-					   scsi_sg_count(cmd), ST_TO_CMD);
++			cp_len = scsi_sg_copy_from_buffer(cmd, &ver, cp_len);
+ 			cmd->result = sizeof(ver) == cp_len ?
+ 				DID_OK << 16 | COMMAND_COMPLETE << 8 :
+ 				DID_ERROR << 16 | COMMAND_COMPLETE << 8;
+@@ -700,15 +651,12 @@ static void stex_copy_data(struct st_ccb *ccb,
+ 
+ 	if (ccb->cmd == NULL)
+ 		return;
+-	stex_internal_copy(ccb->cmd,
+-		resp->variable, &count, scsi_sg_count(ccb->cmd), ST_TO_CMD);
++	count = scsi_sg_copy_from_buffer(ccb->cmd, resp->variable, count);
+ }
+ 
+ static void stex_ys_commands(struct st_hba *hba,
+ 	struct st_ccb *ccb, struct status_msg *resp)
+ {
+-	size_t count;
+-
+ 	if (ccb->cmd->cmnd[0] == MGT_CMD &&
+ 		resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
+ 		scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) -
+@@ -724,9 +672,8 @@ static void stex_ys_commands(struct st_hba *hba,
+ 		resp->scsi_status == SAM_STAT_GOOD) {
+ 		ST_INQ *inq_data;
+ 
+-		count = STEX_EXTRA_SIZE;
+-		stex_internal_copy(ccb->cmd, hba->copy_buffer,
+-			&count, scsi_sg_count(ccb->cmd), ST_FROM_CMD);
++		scsi_sg_copy_to_buffer(ccb->cmd, hba->copy_buffer,
++				       STEX_EXTRA_SIZE);
+ 		inq_data = (ST_INQ *)hba->copy_buffer;
+ 		if (inq_data->DeviceTypeQualifier != 0)
+ 			ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
+diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
+index 02d9727..aaa4fd0 100644
+--- a/drivers/scsi/sun3_scsi_vme.c
++++ b/drivers/scsi/sun3_scsi_vme.c
+@@ -582,3 +582,4 @@ static struct scsi_host_template driver_template = {
+ 
+ #include "scsi_module.c"
+ 
++MODULE_LICENSE("GPL");
+diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
+index f286c37..5fda881 100644
+--- a/drivers/scsi/wd33c93.c
++++ b/drivers/scsi/wd33c93.c
+@@ -1973,10 +1973,7 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
+ 	hostdata->incoming_ptr = 0;
+ 	hostdata->outgoing_len = 0;
+ 	hostdata->default_sx_per = DEFAULT_SX_PER;
+-	hostdata->no_sync = 0xff;	/* sync defaults to off */
+ 	hostdata->no_dma = 0;	/* default is DMA enabled */
+-	hostdata->fast = 0;	/* default is Fast SCSI transfers disabled */
+-	hostdata->dma_mode = CTRL_DMA;	/* default is Single Byte DMA */
+ 
+ #ifdef PROC_INTERFACE
+ 	hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
+diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
+index 77f7a7f..96a585e 100644
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -1740,6 +1740,60 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
+ 	}
+ }
+ 
++#ifdef CONFIG_CONSOLE_POLL
++/*
++ * Console polling routines for writing and reading from the uart while
++ * in an interrupt or debug context.
++ */
++
++static int serial8250_get_poll_char(struct uart_port *port)
++{
++	struct uart_8250_port *up = (struct uart_8250_port *)port;
++	unsigned char lsr = serial_inp(up, UART_LSR);
++
++	while (!(lsr & UART_LSR_DR))
++		lsr = serial_inp(up, UART_LSR);
++
++	return serial_inp(up, UART_RX);
++}
++
++
++static void serial8250_put_poll_char(struct uart_port *port,
++			 unsigned char c)
++{
++	unsigned int ier;
++	struct uart_8250_port *up = (struct uart_8250_port *)port;
++
++	/*
++	 *	First save the IER then disable the interrupts
++	 */
++	ier = serial_in(up, UART_IER);
++	if (up->capabilities & UART_CAP_UUE)
++		serial_out(up, UART_IER, UART_IER_UUE);
++	else
++		serial_out(up, UART_IER, 0);
++
++	wait_for_xmitr(up, BOTH_EMPTY);
++	/*
++	 *	Send the character out.
++	 *	If a LF, also do CR...
++	 */
++	serial_out(up, UART_TX, c);
++	if (c == 10) {
++		wait_for_xmitr(up, BOTH_EMPTY);
++		serial_out(up, UART_TX, 13);
++	}
++
++	/*
++	 *	Finally, wait for transmitter to become empty
++	 *	and restore the IER
++	 */
++	wait_for_xmitr(up, BOTH_EMPTY);
++	serial_out(up, UART_IER, ier);
++}
++
++#endif /* CONFIG_CONSOLE_POLL */
++
+ static int serial8250_startup(struct uart_port *port)
+ {
+ 	struct uart_8250_port *up = (struct uart_8250_port *)port;
+@@ -2386,6 +2440,10 @@ static struct uart_ops serial8250_pops = {
+ 	.request_port	= serial8250_request_port,
+ 	.config_port	= serial8250_config_port,
+ 	.verify_port	= serial8250_verify_port,
++#ifdef CONFIG_CONSOLE_POLL
++	.poll_get_char = serial8250_get_poll_char,
++	.poll_put_char = serial8250_put_poll_char,
++#endif
+ };
+ 
+ static struct uart_8250_port serial8250_ports[UART_NR];
+diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
+index cf627cd..f7cd950 100644
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -961,6 +961,9 @@ config SERIAL_CORE
+ config SERIAL_CORE_CONSOLE
+ 	bool
+ 
++config CONSOLE_POLL
++	bool
++
+ config SERIAL_68328
+ 	bool "68328 serial support"
+ 	depends on M68328 || M68EZ328 || M68VZ328
+diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
+index 640cfe4..3cbea54 100644
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -66,4 +66,5 @@ obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
+ obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
+ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
+ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
++obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
+ obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
+diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
+index 40604a0..08adc1d 100644
+--- a/drivers/serial/amba-pl011.c
++++ b/drivers/serial/amba-pl011.c
+@@ -314,6 +314,32 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
+ 	spin_unlock_irqrestore(&uap->port.lock, flags);
+ }
+ 
++#ifdef CONFIG_CONSOLE_POLL
++static int pl010_get_poll_char(struct uart_port *port)
++{
++	struct uart_amba_port *uap = (struct uart_amba_port *)port;
++	unsigned int status;
++
++	do {
++		status = readw(uap->port.membase + UART01x_FR);
++	} while (status & UART01x_FR_RXFE);
++
++	return readw(uap->port.membase + UART01x_DR);
++}
++
++static void pl010_put_poll_char(struct uart_port *port,
++			 unsigned char ch)
++{
++	struct uart_amba_port *uap = (struct uart_amba_port *)port;
++
++	while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
++		barrier();
++
++	writew(ch, uap->port.membase + UART01x_DR);
++}
++
++#endif /* CONFIG_CONSOLE_POLL */
++
+ static int pl011_startup(struct uart_port *port)
+ {
+ 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
+@@ -572,6 +598,10 @@ static struct uart_ops amba_pl011_pops = {
+ 	.request_port	= pl010_request_port,
+ 	.config_port	= pl010_config_port,
+ 	.verify_port	= pl010_verify_port,
++#ifdef CONFIG_CONSOLE_POLL
++	.poll_get_char = pl010_get_poll_char,
++	.poll_put_char = pl010_put_poll_char,
++#endif
+ };
+ 
+ static struct uart_amba_port *amba_ports[UART_NR];
+diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
+index 46bb47f..5f55534 100644
+--- a/drivers/serial/bfin_5xx.c
++++ b/drivers/serial/bfin_5xx.c
+@@ -151,7 +151,8 @@ void kgdb_put_debug_char(int chr)
+ {
+ 	struct bfin_serial_port *uart;
+ 	
+-	if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
++	if (CONFIG_KGDB_UART_PORT < 0
++		|| CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
+ 		uart = &bfin_serial_ports[0];
+ 	else
+ 		uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+@@ -173,7 +174,8 @@ int kgdb_get_debug_char(void)
+ 	struct bfin_serial_port *uart;
+ 	unsigned char chr;
+ 
+-	if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
++	if (CONFIG_KGDB_UART_PORT < 0
++		|| CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
+ 		uart = &bfin_serial_ports[0];
+ 	else
+ 		uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+@@ -192,7 +194,7 @@ int kgdb_get_debug_char(void)
+ }
+ #endif
+ 
+-#if ANOMALY_05000230 && defined(CONFIG_SERIAL_BFIN_PIO)
++#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
+ # define UART_GET_ANOMALY_THRESHOLD(uart)    ((uart)->anomaly_threshold)
+ # define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
+ #else
+@@ -237,7 +239,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
+ 	}
+ #endif
+ 
+-	if (ANOMALY_05000230) {
++	if (ANOMALY_05000363) {
+ 		/* The BF533 (and BF561) family of processors have a nice anomaly
+ 		 * where they continuously generate characters for a "single" break.
+ 		 * We have to basically ignore this flood until the "next" valid
+@@ -249,9 +251,6 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
+ 		 * timeout was picked as it must absolutely be larger than 1
+ 		 * character time +/- some percent.  So 1.5 sounds good.  All other
+ 		 * Blackfin families operate properly.  Woo.
+-		 * Note: While Anomaly 05000230 does not directly address this,
+-		 *       the changes that went in for it also fixed this issue.
+-		 *       That anomaly was fixed in 0.5+ silicon.  I like bunnies.
+ 		 */
+ 		if (anomaly_start.tv_sec) {
+ 			struct timeval curr;
+@@ -285,7 +284,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
+ 	}
+ 
+ 	if (status & BI) {
+-		if (ANOMALY_05000230)
++		if (ANOMALY_05000363)
+ 			if (bfin_revid() < 5)
+ 				do_gettimeofday(&anomaly_start);
+ 		uart->port.icount.brk++;
+@@ -507,8 +506,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
+ 		uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
+ 	}
+ 
+-	uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
+-	add_timer(&(uart->rx_dma_timer));
++	mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
+ }
+ 
+ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
+@@ -551,9 +549,7 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
+ 	clear_dma_irqstat(uart->rx_dma_channel);
+ 	spin_unlock(&uart->port.lock);
+ 
+-	del_timer(&(uart->rx_dma_timer));
+-	uart->rx_dma_timer.expires = jiffies;
+-	add_timer(&(uart->rx_dma_timer));
++	mod_timer(&(uart->rx_dma_timer), jiffies);
+ 
+ 	return IRQ_HANDLED;
+ }
+@@ -749,7 +745,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
+ 	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+ 	unsigned long flags;
+ 	unsigned int baud, quot;
+-	unsigned short val, ier, lsr, lcr = 0;
++	unsigned short val, ier, lcr = 0;
+ 
+ 	switch (termios->c_cflag & CSIZE) {
+ 	case CS8:
+@@ -806,10 +802,6 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
+ 
+ 	UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
+ 
+-	do {
+-		lsr = UART_GET_LSR(uart);
+-	} while (!(lsr & TEMT));
+-
+ 	/* Disable UART */
+ 	ier = UART_GET_IER(uart);
+ #ifdef CONFIG_BF54x
+@@ -900,6 +892,31 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
+ 	return 0;
+ }
+ 
++/*
++ * Enable the IrDA function if tty->ldisc.num is N_IRDA.
++ * In other cases, disable IrDA function.
++ */
++static void bfin_set_ldisc(struct tty_struct *tty)
++{
++	int line = tty->index;
++	unsigned short val;
++
++	if (line >= tty->driver->num)
++		return;
++
++	switch (tty->ldisc.num) {
++	case N_IRDA:
++		val = UART_GET_GCTL(&bfin_serial_ports[line]);
++		val |= (IREN | RPOLC);
++		UART_PUT_GCTL(&bfin_serial_ports[line], val);
++		break;
++	default:
++		val = UART_GET_GCTL(&bfin_serial_ports[line]);
++		val &= ~(IREN | RPOLC);
++		UART_PUT_GCTL(&bfin_serial_ports[line], val);
++	}
++}
++
+ static struct uart_ops bfin_serial_pops = {
+ 	.tx_empty	= bfin_serial_tx_empty,
+ 	.set_mctrl	= bfin_serial_set_mctrl,
+@@ -1172,7 +1189,7 @@ static struct uart_driver bfin_serial_reg = {
+ 	.dev_name		= BFIN_SERIAL_NAME,
+ 	.major			= BFIN_SERIAL_MAJOR,
+ 	.minor			= BFIN_SERIAL_MINOR,
+-	.nr			= NR_PORTS,
++	.nr			= BFIN_UART_NR_PORTS,
+ 	.cons			= BFIN_SERIAL_CONSOLE,
+ };
+ 
+@@ -1261,6 +1278,7 @@ static int __init bfin_serial_init(void)
+ 
+ 	ret = uart_register_driver(&bfin_serial_reg);
+ 	if (ret == 0) {
++		bfin_serial_reg.tty_driver->set_ldisc = bfin_set_ldisc;
+ 		ret = platform_driver_register(&bfin_serial_driver);
+ 		if (ret) {
+ 			pr_debug("uart register failed\n");
+diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
+index 32b9737..0cc39f8 100644
+--- a/drivers/serial/cpm_uart/cpm_uart.h
++++ b/drivers/serial/cpm_uart/cpm_uart.h
+@@ -92,6 +92,9 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR];
+ 
+ /* these are located in their respective files */
+ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd);
++void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
++				struct device_node *np);
++void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram);
+ int cpm_uart_init_portdesc(void);
+ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
+ void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
+diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
+index 236af9d..a638ba0 100644
+--- a/drivers/serial/cpm_uart/cpm_uart_core.c
++++ b/drivers/serial/cpm_uart/cpm_uart_core.c
+@@ -966,24 +966,23 @@ static int cpm_uart_init_port(struct device_node *np,
+ 	if (!mem)
+ 		return -ENOMEM;
+ 
+-	pram = of_iomap(np, 1);
+-	if (!pram) {
+-		ret = -ENOMEM;
+-		goto out_mem;
+-	}
+-
+ 	if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") ||
+ 	    of_device_is_compatible(np, "fsl,cpm2-scc-uart")) {
+ 		pinfo->sccp = mem;
+-		pinfo->sccup = pram;
++		pinfo->sccup = pram = cpm_uart_map_pram(pinfo, np);
+ 	} else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") ||
+ 	           of_device_is_compatible(np, "fsl,cpm2-smc-uart")) {
+ 		pinfo->flags |= FLAG_SMC;
+ 		pinfo->smcp = mem;
+-		pinfo->smcup = pram;
++		pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np);
+ 	} else {
+ 		ret = -ENODEV;
+-		goto out_pram;
++		goto out_mem;
++	}
++
++	if (!pram) {
++		ret = -ENOMEM;
++		goto out_mem;
+ 	}
+ 
+ 	pinfo->tx_nrfifos = TX_NUM_FIFO;
+@@ -1007,7 +1006,7 @@ static int cpm_uart_init_port(struct device_node *np,
+ 	return cpm_uart_request_port(&pinfo->port);
+ 
+ out_pram:
+-	iounmap(pram);
++	cpm_uart_unmap_pram(pinfo, pram);
+ out_mem:
+ 	iounmap(mem);
+ 	return ret;
+diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+index 6ea0366..74f1432 100644
+--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
++++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+@@ -45,6 +45,8 @@
+ #include <linux/serial_core.h>
+ #include <linux/kernel.h>
+ 
++#include <linux/of.h>
++
+ #include "cpm_uart.h"
+ 
+ /**************************************************************/
+@@ -54,6 +56,18 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+ 	cpm_command(port->command, cmd);
+ }
++
++void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
++				struct device_node *np)
++{
++	return of_iomap(np, 1);
++}
++
++void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
++{
++	iounmap(pram);
++}
++
+ #else
+ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+index d9af06a..bb862e2 100644
+--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
++++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+@@ -41,6 +41,9 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/fs_pd.h>
++#ifdef CONFIG_PPC_CPM_NEW_BINDING
++#include <asm/prom.h>
++#endif
+ 
+ #include <linux/serial_core.h>
+ #include <linux/kernel.h>
+@@ -54,6 +57,55 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+ 	cpm_command(port->command, cmd);
+ }
++
++void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
++				struct device_node *np)
++{
++	void __iomem *pram;
++	unsigned long offset;
++	struct resource res;
++	unsigned long len;
++
++	/* Don't remap parameter RAM if it has already been initialized
++	 * during console setup.
++	 */
++	if (IS_SMC(port) && port->smcup)
++		return port->smcup;
++	else if (!IS_SMC(port) && port->sccup)
++		return port->sccup;
++
++	if (of_address_to_resource(np, 1, &res))
++		return NULL;
++
++	len = 1 + res.end - res.start;
++	pram = ioremap(res.start, len);
++	if (!pram)
++		return NULL;
++
++	if (!IS_SMC(port))
++		return pram;
++
++	if (len != 2) {
++		printk(KERN_WARNING "cpm_uart[%d]: device tree references "
++			"SMC pram, using boot loader/wrapper pram mapping. "
++			"Please fix your device tree to reference the pram "
++			"base register instead.\n",
++			port->port.line);
++		return pram;
++	}
++
++	offset = cpm_dpalloc(PROFF_SMC_SIZE, 64);
++	out_be16(pram, offset);
++	iounmap(pram);
++	return cpm_muram_addr(offset);
++}
++
++void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
++{
++	if (!IS_SMC(port))
++		iounmap(pram);
++}
++
+ #else
+ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
+index 16ba9ac..5a375bf 100644
+--- a/drivers/serial/imx.c
++++ b/drivers/serial/imx.c
+@@ -166,15 +166,6 @@
+ #define SERIAL_IMX_MAJOR	204
+ #define MINOR_START		41
+ 
+-#define NR_PORTS		2
+-
+-#define IMX_ISR_PASS_LIMIT	256
+-
+-/*
+- * This is the size of our serial port register set.
+- */
+-#define UART_PORT_SIZE	0x100
+-
+ /*
+  * This determines how often we check the modem status signals
+  * for any change.  They generally aren't connected to an IRQ
+@@ -358,66 +349,60 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
+ 	struct tty_struct *tty = sport->port.info->tty;
+ 	unsigned long flags, temp;
+ 
+-	rx = readl(sport->port.membase + URXD0);
+ 	spin_lock_irqsave(&sport->port.lock,flags);
+ 
+-	do {
++	while (readl(sport->port.membase + USR2) & USR2_RDR) {
+ 		flg = TTY_NORMAL;
+ 		sport->port.icount.rx++;
+ 
++		rx = readl(sport->port.membase + URXD0);
++
+ 		temp = readl(sport->port.membase + USR2);
+-		if( temp & USR2_BRCD ) {
++		if (temp & USR2_BRCD) {
+ 			writel(temp | USR2_BRCD, sport->port.membase + USR2);
+-			if(uart_handle_break(&sport->port))
+-				goto ignore_char;
++			if (uart_handle_break(&sport->port))
++				continue;
+ 		}
+ 
+ 		if (uart_handle_sysrq_char
+ 		            (&sport->port, (unsigned char)rx))
+-			goto ignore_char;
++			continue;
++
++		if (rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) ) {
++			if (rx & URXD_PRERR)
++				sport->port.icount.parity++;
++			else if (rx & URXD_FRMERR)
++				sport->port.icount.frame++;
++			if (rx & URXD_OVRRUN)
++				sport->port.icount.overrun++;
++
++			if (rx & sport->port.ignore_status_mask) {
++				if (++ignored > 100)
++					goto out;
++				continue;
++			}
++
++			rx &= sport->port.read_status_mask;
++
++			if (rx & URXD_PRERR)
++				flg = TTY_PARITY;
++			else if (rx & URXD_FRMERR)
++				flg = TTY_FRAME;
++			if (rx & URXD_OVRRUN)
++				flg = TTY_OVERRUN;
+ 
+-		if( rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) )
+-			goto handle_error;
++#ifdef SUPPORT_SYSRQ
++			sport->port.sysrq = 0;
++#endif
++		}
+ 
+-	error_return:
+ 		tty_insert_flip_char(tty, rx, flg);
+-
+-	ignore_char:
+-		rx = readl(sport->port.membase + URXD0);
+-	} while(rx & URXD_CHARRDY);
++	}
+ 
+ out:
+ 	spin_unlock_irqrestore(&sport->port.lock,flags);
+ 	tty_flip_buffer_push(tty);
+ 	return IRQ_HANDLED;
+-
+-handle_error:
+-	if (rx & URXD_PRERR)
+-		sport->port.icount.parity++;
+-	else if (rx & URXD_FRMERR)
+-		sport->port.icount.frame++;
+-	if (rx & URXD_OVRRUN)
+-		sport->port.icount.overrun++;
+-
+-	if (rx & sport->port.ignore_status_mask) {
+-		if (++ignored > 100)
+-			goto out;
+-		goto ignore_char;
+-	}
+-
+-	rx &= sport->port.read_status_mask;
+-
+-	if (rx & URXD_PRERR)
+-		flg = TTY_PARITY;
+-	else if (rx & URXD_FRMERR)
+-		flg = TTY_FRAME;
+-	if (rx & URXD_OVRRUN)
+-		flg = TTY_OVERRUN;
+-
+-#ifdef SUPPORT_SYSRQ
+-	sport->port.sysrq = 0;
+-#endif
+-	goto error_return;
+ }
+ 
+ /*
+@@ -546,7 +531,7 @@ static int imx_startup(struct uart_port *port)
+ 	writel(USR1_RTSD, sport->port.membase + USR1);
+ 
+ 	temp = readl(sport->port.membase + UCR1);
+-	temp |= (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
++	temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
+ 	writel(temp, sport->port.membase + UCR1);
+ 
+ 	temp = readl(sport->port.membase + UCR2);
+@@ -731,9 +716,11 @@ static const char *imx_type(struct uart_port *port)
+  */
+ static void imx_release_port(struct uart_port *port)
+ {
+-	struct imx_port *sport = (struct imx_port *)port;
++	struct platform_device *pdev = to_platform_device(port->dev);
++	struct resource *mmres;
+ 
+-	release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
++	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	release_mem_region(mmres->start, mmres->end - mmres->start + 1);
+ }
+ 
+ /*
+@@ -741,10 +728,18 @@ static void imx_release_port(struct uart_port *port)
+  */
+ static int imx_request_port(struct uart_port *port)
+ {
+-	struct imx_port *sport = (struct imx_port *)port;
++	struct platform_device *pdev = to_platform_device(port->dev);
++	struct resource *mmres;
++	void *ret;
++
++	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!mmres)
++		return -ENODEV;
++
++	ret = request_mem_region(mmres->start, mmres->end - mmres->start + 1,
++			"imx-uart");
+ 
+-	return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
+-			"imx-uart") != NULL ? 0 : -EBUSY;
++	return  ret ? 0 : -EBUSY;
+ }
+ 
+ /*
+@@ -815,7 +810,7 @@ static struct imx_port imx_ports[] = {
+ 		.type		= PORT_IMX,
+ 		.iotype		= UPIO_MEM,
+ 		.membase	= (void *)IMX_UART1_BASE,
+-		.mapbase	= IMX_UART1_BASE, /* FIXME */
++		.mapbase	= 0x00206000,
+ 		.irq		= UART1_MINT_RX,
+ 		.uartclk	= 16000000,
+ 		.fifosize	= 32,
+@@ -831,7 +826,7 @@ static struct imx_port imx_ports[] = {
+ 		.type		= PORT_IMX,
+ 		.iotype		= UPIO_MEM,
+ 		.membase	= (void *)IMX_UART2_BASE,
+-		.mapbase	= IMX_UART2_BASE, /* FIXME */
++		.mapbase	= 0x00207000,
+ 		.irq		= UART2_MINT_RX,
+ 		.uartclk	= 16000000,
+ 		.fifosize	= 32,
+diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
+new file mode 100644
+index 0000000..9cf0332
+--- /dev/null
++++ b/drivers/serial/kgdboc.c
+@@ -0,0 +1,168 @@
++/*
++ * Based on the same principle as kgdboe using the NETPOLL api, this
++ * driver uses a console polling api to implement a gdb serial inteface
++ * which is multiplexed on a console port.
++ *
++ * Maintainer: Jason Wessel <jason.wessel at windriver.com>
++ *
++ * 2007-2008 (c) Jason Wessel - Wind River Systems, 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.
++ */
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++#include <linux/kgdb.h>
++#include <linux/tty.h>
++
++#define MAX_CONFIG_LEN		40
++
++static struct kgdb_io		kgdboc_io_ops;
++
++/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
++static int configured		= -1;
++
++static char config[MAX_CONFIG_LEN];
++static struct kparam_string kps = {
++	.string			= config,
++	.maxlen			= MAX_CONFIG_LEN,
++};
++
++static struct tty_driver	*kgdb_tty_driver;
++static int			kgdb_tty_line;
++
++static int kgdboc_option_setup(char *opt)
++{
++	if (strlen(opt) > MAX_CONFIG_LEN) {
++		printk(KERN_ERR "kgdboc: config string too long\n");
++		return -ENOSPC;
++	}
++	strcpy(config, opt);
++
++	return 0;
++}
++
++__setup("kgdboc=", kgdboc_option_setup);
++
++static int configure_kgdboc(void)
++{
++	struct tty_driver *p;
++	int tty_line = 0;
++	int err;
++
++	err = kgdboc_option_setup(config);
++	if (err || !strlen(config) || isspace(config[0]))
++		goto noconfig;
++
++	err = -ENODEV;
++
++	p = tty_find_polling_driver(config, &tty_line);
++	if (!p)
++		goto noconfig;
++
++	kgdb_tty_driver = p;
++	kgdb_tty_line = tty_line;
++
++	err = kgdb_register_io_module(&kgdboc_io_ops);
++	if (err)
++		goto noconfig;
++
++	configured = 1;
++
++	return 0;
++
++noconfig:
++	config[0] = 0;
++	configured = 0;
++
++	return err;
++}
++
++static int __init init_kgdboc(void)
++{
++	/* Already configured? */
++	if (configured == 1)
++		return 0;
++
++	return configure_kgdboc();
++}
++
++static void cleanup_kgdboc(void)
++{
++	if (configured == 1)
++		kgdb_unregister_io_module(&kgdboc_io_ops);
++}
++
++static int kgdboc_get_char(void)
++{
++	return kgdb_tty_driver->poll_get_char(kgdb_tty_driver, kgdb_tty_line);
++}
++
++static void kgdboc_put_char(u8 chr)
++{
++	kgdb_tty_driver->poll_put_char(kgdb_tty_driver, kgdb_tty_line, chr);
++}
++
++static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
++{
++	int len = strlen(kmessage);
++
++	if (len >= MAX_CONFIG_LEN) {
++		printk(KERN_ERR "kgdboc: config string too long\n");
++		return -ENOSPC;
++	}
++
++	/* Only copy in the string if the init function has not run yet */
++	if (configured < 0) {
++		strcpy(config, kmessage);
++		return 0;
++	}
++
++	if (kgdb_connected) {
++		printk(KERN_ERR
++		       "kgdboc: Cannot reconfigure while KGDB is connected.\n");
++
++		return -EBUSY;
++	}
++
++	strcpy(config, kmessage);
++	/* Chop out \n char as a result of echo */
++	if (config[len - 1] == '\n')
++		config[len - 1] = '\0';
++
++	if (configured == 1)
++		cleanup_kgdboc();
++
++	/* Go and configure with the new params. */
++	return configure_kgdboc();
++}
++
++static void kgdboc_pre_exp_handler(void)
++{
++	/* Increment the module count when the debugger is active */
++	if (!kgdb_connected)
++		try_module_get(THIS_MODULE);
++}
++
++static void kgdboc_post_exp_handler(void)
++{
++	/* decrement the module count when the debugger detaches */
++	if (!kgdb_connected)
++		module_put(THIS_MODULE);
++}
++
++static struct kgdb_io kgdboc_io_ops = {
++	.name			= "kgdboc",
++	.read_char		= kgdboc_get_char,
++	.write_char		= kgdboc_put_char,
++	.pre_exception		= kgdboc_pre_exp_handler,
++	.post_exception		= kgdboc_post_exp_handler,
++};
++
++module_init(init_kgdboc);
++module_exit(cleanup_kgdboc);
++module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
++MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
++MODULE_DESCRIPTION("KGDB Console TTY Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
+index 99af084..ddd3aa5 100644
+--- a/drivers/serial/mcfserial.c
++++ b/drivers/serial/mcfserial.c
+@@ -40,7 +40,6 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/system.h>
+-#include <asm/semaphore.h>
+ #include <asm/delay.h>
+ #include <asm/coldfire.h>
+ #include <asm/mcfsim.h>
+diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
+index c0e50a4..25029c7 100644
+--- a/drivers/serial/of_serial.c
++++ b/drivers/serial/of_serial.c
+@@ -31,7 +31,8 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
+ 	struct resource resource;
+ 	struct device_node *np = ofdev->node;
+ 	const unsigned int *clk, *spd;
+-	int ret;
++	const u32 *prop;
++	int ret, prop_size;
+ 
+ 	memset(port, 0, sizeof *port);
+ 	spd = of_get_property(np, "current-speed", NULL);
+@@ -49,6 +50,17 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
+ 
+ 	spin_lock_init(&port->lock);
+ 	port->mapbase = resource.start;
++
++	/* Check for shifted address mapping */
++	prop = of_get_property(np, "reg-offset", &prop_size);
++	if (prop && (prop_size == sizeof(u32)))
++		port->mapbase += *prop;
++
++	/* Check for registers offset within the devices address range */
++	prop = of_get_property(np, "reg-shift", &prop_size);
++	if (prop && (prop_size == sizeof(u32)))
++		port->regshift = *prop;
++
+ 	port->irq = irq_of_parse_and_map(np, 0);
+ 	port->iotype = UPIO_MEM;
+ 	port->type = type;
+@@ -56,7 +68,9 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
+ 	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
+ 		| UPF_FIXED_PORT;
+ 	port->dev = &ofdev->dev;
+-	port->custom_divisor = *clk / (16 * (*spd));
++	/* If current-speed was set, then try not to change it. */
++	if (spd)
++		port->custom_divisor = *clk / (16 * (*spd));
+ 
+ 	return 0;
+ }
+diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
+index 0f5a179..a9ca03e 100644
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -1771,7 +1771,7 @@ static int uart_read_proc(char *page, char **start, off_t off,
+ }
+ #endif
+ 
+-#ifdef CONFIG_SERIAL_CORE_CONSOLE
++#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
+ /*
+  *	uart_console_write - write a console message to a serial port
+  *	@port: the port to write the message
+@@ -1827,7 +1827,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
+  *	options.  The format of the string is <baud><parity><bits><flow>,
+  *	eg: 115200n8r
+  */
+-void __init
++void
+ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
+ {
+ 	char *s = options;
+@@ -1842,6 +1842,7 @@ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
+ 	if (*s)
+ 		*flow = *s;
+ }
++EXPORT_SYMBOL_GPL(uart_parse_options);
+ 
+ struct baud_rates {
+ 	unsigned int rate;
+@@ -1872,7 +1873,7 @@ static const struct baud_rates baud_rates[] = {
+  *	@bits: number of data bits
+  *	@flow: flow control character - 'r' (rts)
+  */
+-int __init
++int
+ uart_set_options(struct uart_port *port, struct console *co,
+ 		 int baud, int parity, int bits, int flow)
+ {
+@@ -1924,10 +1925,16 @@ uart_set_options(struct uart_port *port, struct console *co,
+ 	port->mctrl |= TIOCM_DTR;
+ 
+ 	port->ops->set_termios(port, &termios, &dummy);
+-	co->cflag = termios.c_cflag;
++	/*
++	 * Allow the setting of the UART parameters with a NULL console
++	 * too:
++	 */
++	if (co)
++		co->cflag = termios.c_cflag;
+ 
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(uart_set_options);
+ #endif /* CONFIG_SERIAL_CORE_CONSOLE */
+ 
+ static void uart_change_pm(struct uart_state *state, int pm_state)
+@@ -2182,6 +2189,60 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+ 	}
+ }
+ 
++#ifdef CONFIG_CONSOLE_POLL
++
++static int uart_poll_init(struct tty_driver *driver, int line, char *options)
++{
++	struct uart_driver *drv = driver->driver_state;
++	struct uart_state *state = drv->state + line;
++	struct uart_port *port;
++	int baud = 9600;
++	int bits = 8;
++	int parity = 'n';
++	int flow = 'n';
++
++	if (!state || !state->port)
++		return -1;
++
++	port = state->port;
++	if (!(port->ops->poll_get_char && port->ops->poll_put_char))
++		return -1;
++
++	if (options) {
++		uart_parse_options(options, &baud, &parity, &bits, &flow);
++		return uart_set_options(port, NULL, baud, parity, bits, flow);
++	}
++
++	return 0;
++}
++
++static int uart_poll_get_char(struct tty_driver *driver, int line)
++{
++	struct uart_driver *drv = driver->driver_state;
++	struct uart_state *state = drv->state + line;
++	struct uart_port *port;
++
++	if (!state || !state->port)
++		return -1;
++
++	port = state->port;
++	return port->ops->poll_get_char(port);
++}
++
++static void uart_poll_put_char(struct tty_driver *driver, int line, char ch)
++{
++	struct uart_driver *drv = driver->driver_state;
++	struct uart_state *state = drv->state + line;
++	struct uart_port *port;
++
++	if (!state || !state->port)
++		return;
++
++	port = state->port;
++	port->ops->poll_put_char(port, ch);
++}
++#endif
++
+ static const struct tty_operations uart_ops = {
+ 	.open		= uart_open,
+ 	.close		= uart_close,
+@@ -2206,6 +2267,11 @@ static const struct tty_operations uart_ops = {
+ #endif
+ 	.tiocmget	= uart_tiocmget,
+ 	.tiocmset	= uart_tiocmset,
++#ifdef CONFIG_CONSOLE_POLL
++	.poll_init	= uart_poll_init,
++	.poll_get_char	= uart_poll_get_char,
++	.poll_put_char	= uart_poll_put_char,
++#endif
+ };
+ 
+ /**
+@@ -2356,7 +2422,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
+ 	 */
+ 	tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev);
+ 	if (likely(!IS_ERR(tty_dev))) {
+-		device_can_wakeup(tty_dev) = 1;
++		device_init_wakeup(tty_dev, 1);
+ 		device_set_wakeup_enable(tty_dev, 0);
+ 	} else
+ 		printk(KERN_ERR "Cannot register tty device on line %d\n",
+diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
+index eff5930..c2ea5d4 100644
+--- a/drivers/serial/sh-sci.c
++++ b/drivers/serial/sh-sci.c
+@@ -333,7 +333,6 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+ 	}
+ 	sci_out(port, SCFCR, fcr_val);
+ }
+-
+ #elif defined(CONFIG_CPU_SH3)
+ /* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
+ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+@@ -384,6 +383,12 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+ 
+ 	sci_out(port, SCFCR, fcr_val);
+ }
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
++{
++	/* Nothing to do here.. */
++	sci_out(port, SCFCR, 0);
++}
+ #else
+ /* For SH7750 */
+ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
+index 01a9dd7..fa8700a 100644
+--- a/drivers/serial/sh-sci.h
++++ b/drivers/serial/sh-sci.h
+@@ -1,20 +1,5 @@
+-/* $Id: sh-sci.h,v 1.4 2004/02/19 16:43:56 lethal Exp $
+- *
+- *  linux/drivers/serial/sh-sci.h
+- *
+- *  SuperH on-chip serial module support.  (SCI with no FIFO / with FIFO)
+- *  Copyright (C) 1999, 2000  Niibe Yutaka
+- *  Copyright (C) 2000  Greg Banks
+- *  Copyright (C) 2002, 2003  Paul Mundt
+- *  Modified to support multiple serial ports. Stuart Menefy (May 2000).
+- *  Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003).
+- *  Modified to support H8/300 Series Yoshinori Sato (Feb 2004).
+- *  Removed SH7300 support (Jul 2007).
+- *  Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Aug 2007).
+- */
+ #include <linux/serial_core.h>
+ #include <asm/io.h>
+-
+ #include <asm/gpio.h>
+ 
+ #if defined(CONFIG_H83007) || defined(CONFIG_H83068)
+@@ -102,6 +87,15 @@
+ # define SCSPTR0		SCPDR0
+ # define SCIF_ORER		0x0001  /* overrun error bit */
+ # define SCSCR_INIT(port)	0x0038  /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++# define SCSPTR0                0xa4050160
++# define SCSPTR1                0xa405013e
++# define SCSPTR2                0xa4050160
++# define SCSPTR3                0xa405013e
++# define SCSPTR4                0xa4050128
++# define SCSPTR5                0xa4050128
++# define SCIF_ORER              0x0001  /* overrun error bit */
++# define SCSCR_INIT(port)       0x0038  /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+ # define SCIF_ONLY
+ #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
+ # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
+@@ -395,6 +389,11 @@
+                  h8_sci_offset, h8_sci_size) \
+   CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size)
+ #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size)
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++        #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \
++                CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size)
++        #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
++                CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
+ #else
+ #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
+ 		 sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
+@@ -419,6 +418,18 @@ SCIF_FNS(SCFDR,  0x1c, 16)
+ SCIF_FNS(SCxTDR, 0x20,  8)
+ SCIF_FNS(SCxRDR, 0x24,  8)
+ SCIF_FNS(SCLSR,  0x24, 16)
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++SCIx_FNS(SCSMR,  0x00, 16, 0x00, 16)
++SCIx_FNS(SCBRR,  0x04,  8, 0x04,  8)
++SCIx_FNS(SCSCR,  0x08, 16, 0x08, 16)
++SCIx_FNS(SCxTDR, 0x20,  8, 0x0c,  8)
++SCIx_FNS(SCxSR,  0x14, 16, 0x10, 16)
++SCIx_FNS(SCxRDR, 0x24,  8, 0x14,  8)
++SCIF_FNS(SCTDSR, 0x0c,  8)
++SCIF_FNS(SCFER,  0x10, 16)
++SCIF_FNS(SCFCR,  0x18, 16)
++SCIF_FNS(SCFDR,  0x1c, 16)
++SCIF_FNS(SCLSR,  0x24, 16)
+ #else
+ /*      reg      SCI/SH3   SCI/SH4  SCIF/SH3   SCIF/SH4  SCI/H8*/
+ /*      name     off  sz   off  sz   off  sz   off  sz   off  sz*/
+@@ -589,6 +600,23 @@ static inline int sci_rxd_in(struct uart_port *port)
+ 		return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
+ 	return 1;
+ }
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++static inline int sci_rxd_in(struct uart_port *port)
++{
++        if (port->mapbase == 0xffe00000)
++                return ctrl_inb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */
++        if (port->mapbase == 0xffe10000)
++                return ctrl_inb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */
++        if (port->mapbase == 0xffe20000)
++                return ctrl_inb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */
++        if (port->mapbase == 0xa4e30000)
++                return ctrl_inb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */
++        if (port->mapbase == 0xa4e40000)
++                return ctrl_inb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */
++        if (port->mapbase == 0xa4e50000)
++                return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */
++        return 1;
++}
+ #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
+ static inline int sci_rxd_in(struct uart_port *port)
+ {
+@@ -727,6 +755,8 @@ static inline int sci_rxd_in(struct uart_port *port)
+       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
+       defined(CONFIG_CPU_SUBTYPE_SH7721)
+ #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(16*bps)-1)
+ #elif defined(__H8300H__) || defined(__H8300S__)
+ #define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1)
+ #elif defined(CONFIG_SUPERH64)
+diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
+index cb2e405..3271379 100644
+--- a/drivers/serial/sunzilog.c
++++ b/drivers/serial/sunzilog.c
+@@ -1015,6 +1015,7 @@ static struct uart_ops sunzilog_pops = {
+ 	.verify_port	=	sunzilog_verify_port,
+ };
+ 
++static int uart_chip_count;
+ static struct uart_sunzilog_port *sunzilog_port_table;
+ static struct zilog_layout __iomem **sunzilog_chip_regs;
+ 
+@@ -1350,16 +1351,22 @@ static int zilog_irq = -1;
+ 
+ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match)
+ {
+-	static int inst;
++	static int kbm_inst, uart_inst;
++	int inst;
+ 	struct uart_sunzilog_port *up;
+ 	struct zilog_layout __iomem *rp;
+-	int keyboard_mouse;
++	int keyboard_mouse = 0;
+ 	int err;
+ 
+-	keyboard_mouse = 0;
+ 	if (of_find_property(op->node, "keyboard", NULL))
+ 		keyboard_mouse = 1;
+ 
++	/* uarts must come before keyboards/mice */
++	if (keyboard_mouse)
++		inst = uart_chip_count + kbm_inst;
++	else
++		inst = uart_inst;
++
+ 	sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
+ 					      sizeof(struct zilog_layout),
+ 					      "zs");
+@@ -1427,6 +1434,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
+ 				   rp, sizeof(struct zilog_layout));
+ 			return err;
+ 		}
++		uart_inst++;
+ 	} else {
+ 		printk(KERN_INFO "%s: Keyboard at MMIO 0x%llx (irq = %d) "
+ 		       "is a %s\n",
+@@ -1438,12 +1446,11 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
+ 		       op->dev.bus_id,
+ 		       (unsigned long long) up[1].port.mapbase,
+ 		       op->irqs[0], sunzilog_type(&up[1].port));
++		kbm_inst++;
+ 	}
+ 
+ 	dev_set_drvdata(&op->dev, &up[0]);
+ 
+-	inst++;
+-
+ 	return 0;
+ }
+ 
+@@ -1491,28 +1498,25 @@ static struct of_platform_driver zs_driver = {
+ static int __init sunzilog_init(void)
+ {
+ 	struct device_node *dp;
+-	int err, uart_count;
+-	int num_keybms;
++	int err;
++	int num_keybms = 0;
+ 	int num_sunzilog = 0;
+ 
+-	num_keybms = 0;
+ 	for_each_node_by_name(dp, "zs") {
+ 		num_sunzilog++;
+ 		if (of_find_property(dp, "keyboard", NULL))
+ 			num_keybms++;
+ 	}
+ 
+-	uart_count = 0;
+ 	if (num_sunzilog) {
+-		int uart_count;
+-
+ 		err = sunzilog_alloc_tables(num_sunzilog);
+ 		if (err)
+ 			goto out;
+ 
+-		uart_count = (num_sunzilog * 2) - (2 * num_keybms);
++		uart_chip_count = num_sunzilog - num_keybms;
+ 
+-		err = sunserial_register_minors(&sunzilog_reg, uart_count);
++		err = sunserial_register_minors(&sunzilog_reg,
++						uart_chip_count * 2);
+ 		if (err)
+ 			goto out_free_tables;
+ 	}
+diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
+index e0994f0..5e4310c 100644
+--- a/drivers/serial/ucc_uart.c
++++ b/drivers/serial/ucc_uart.c
+@@ -1270,10 +1270,18 @@ static int ucc_uart_probe(struct of_device *ofdev,
+ 
+ 	/* Get the UCC number (device ID) */
+ 	/* UCCs are numbered 1-7 */
+-	iprop = of_get_property(np, "device-id", NULL);
+-	if (!iprop || (*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
+-		dev_err(&ofdev->dev,
+-			"missing or invalid UCC specified in device tree\n");
++	iprop = of_get_property(np, "cell-index", NULL);
++	if (!iprop) {
++		iprop = of_get_property(np, "device-id", NULL);
++		if (!iprop) {
++			dev_err(&ofdev->dev, "UCC is unspecified in "
++				"device tree\n");
++			return -EINVAL;
++		}
++	}
++
++	if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
++		dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop);
+ 		kfree(qe_port);
+ 		return -ENODEV;
+ 	}
+diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
+index adea792..cd845b8 100644
+--- a/drivers/ssb/Kconfig
++++ b/drivers/ssb/Kconfig
+@@ -20,6 +20,15 @@ config SSB
+ 
+ 	  If unsure, say N.
+ 
++# Common SPROM support routines
++config SSB_SPROM
++	bool
++
++# Support for Block-I/O. SELECT this from the driver that needs it.
++config SSB_BLOCKIO
++	bool
++	depends on SSB
++
+ config SSB_PCIHOST_POSSIBLE
+ 	bool
+ 	depends on SSB && (PCI = y || PCI = SSB)
+@@ -28,6 +37,7 @@ config SSB_PCIHOST_POSSIBLE
+ config SSB_PCIHOST
+ 	bool "Support for SSB on PCI-bus host"
+ 	depends on SSB_PCIHOST_POSSIBLE
++	select SSB_SPROM
+ 	default y
+ 	help
+ 	  Support for a Sonics Silicon Backplane on top
+@@ -48,6 +58,7 @@ config SSB_PCMCIAHOST_POSSIBLE
+ config SSB_PCMCIAHOST
+ 	bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)"
+ 	depends on SSB_PCMCIAHOST_POSSIBLE
++	select SSB_SPROM
+ 	help
+ 	  Support for a Sonics Silicon Backplane on top
+ 	  of a PCMCIA device.
+@@ -125,4 +136,13 @@ config SSB_DRIVER_EXTIF
+ 
+ 	  If unsure, say N
+ 
++config SSB_DRIVER_GIGE
++	bool "SSB Broadcom Gigabit Ethernet driver"
++	depends on SSB_PCIHOST_POSSIBLE && SSB_EMBEDDED && MIPS
++	help
++	  Driver for the Sonics Silicon Backplane attached
++	  Broadcom Gigabit Ethernet.
++
++	  If unsure, say N
++
+ endmenu
+diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
+index de94c2e..6f255e9 100644
+--- a/drivers/ssb/Makefile
++++ b/drivers/ssb/Makefile
+@@ -1,6 +1,7 @@
+ # core
+ ssb-y					+= main.o scan.o
+ ssb-$(CONFIG_SSB_EMBEDDED)		+= embedded.o
++ssb-$(CONFIG_SSB_SPROM)			+= sprom.o
+ 
+ # host support
+ ssb-$(CONFIG_SSB_PCIHOST)		+= pci.o pcihost_wrapper.o
+@@ -11,6 +12,7 @@ ssb-y					+= driver_chipcommon.o
+ ssb-$(CONFIG_SSB_DRIVER_MIPS)		+= driver_mipscore.o
+ ssb-$(CONFIG_SSB_DRIVER_EXTIF)		+= driver_extif.o
+ ssb-$(CONFIG_SSB_DRIVER_PCICORE)	+= driver_pcicore.o
++ssb-$(CONFIG_SSB_DRIVER_GIGE)		+= driver_gige.o
+ 
+ # b43 pci-ssb-bridge driver
+ # Not strictly a part of SSB, but kept here for convenience
+diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
+index e586321..571f4fd 100644
+--- a/drivers/ssb/driver_chipcommon.c
++++ b/drivers/ssb/driver_chipcommon.c
+@@ -251,7 +251,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
+ 	calc_fast_powerup_delay(cc);
+ }
+ 
+-void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state)
++void ssb_chipco_suspend(struct ssb_chipcommon *cc)
+ {
+ 	if (!cc->dev)
+ 		return;
+@@ -353,6 +353,16 @@ void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
+ 	chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
+ }
+ 
++void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
++{
++	chipco_write32_masked(cc, SSB_CHIPCO_IRQMASK, mask, value);
++}
++
++u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask)
++{
++	return chipco_read32(cc, SSB_CHIPCO_IRQSTAT) & mask;
++}
++
+ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
+ {
+ 	return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
+diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c
+new file mode 100644
+index 0000000..172f904
+--- /dev/null
++++ b/drivers/ssb/driver_gige.c
+@@ -0,0 +1,294 @@
++/*
++ * Sonics Silicon Backplane
++ * Broadcom Gigabit Ethernet core driver
++ *
++ * Copyright 2008, Broadcom Corporation
++ * Copyright 2008, Michael Buesch <mb at bu3sch.de>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/ssb/ssb.h>
++#include <linux/ssb/ssb_driver_gige.h>
++#include <linux/pci.h>
++#include <linux/pci_regs.h>
++
++
++/*
++MODULE_DESCRIPTION("SSB Broadcom Gigabit Ethernet driver");
++MODULE_AUTHOR("Michael Buesch");
++MODULE_LICENSE("GPL");
++*/
++
++static const struct ssb_device_id ssb_gige_tbl[] = {
++	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV),
++	SSB_DEVTABLE_END
++};
++/* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */
++
++
++static inline u8 gige_read8(struct ssb_gige *dev, u16 offset)
++{
++	return ssb_read8(dev->dev, offset);
++}
++
++static inline u16 gige_read16(struct ssb_gige *dev, u16 offset)
++{
++	return ssb_read16(dev->dev, offset);
++}
++
++static inline u32 gige_read32(struct ssb_gige *dev, u16 offset)
++{
++	return ssb_read32(dev->dev, offset);
++}
++
++static inline void gige_write8(struct ssb_gige *dev,
++			       u16 offset, u8 value)
++{
++	ssb_write8(dev->dev, offset, value);
++}
++
++static inline void gige_write16(struct ssb_gige *dev,
++				u16 offset, u16 value)
++{
++	ssb_write16(dev->dev, offset, value);
++}
++
++static inline void gige_write32(struct ssb_gige *dev,
++				u16 offset, u32 value)
++{
++	ssb_write32(dev->dev, offset, value);
++}
++
++static inline
++u8 gige_pcicfg_read8(struct ssb_gige *dev, unsigned int offset)
++{
++	BUG_ON(offset >= 256);
++	return gige_read8(dev, SSB_GIGE_PCICFG + offset);
++}
++
++static inline
++u16 gige_pcicfg_read16(struct ssb_gige *dev, unsigned int offset)
++{
++	BUG_ON(offset >= 256);
++	return gige_read16(dev, SSB_GIGE_PCICFG + offset);
++}
++
++static inline
++u32 gige_pcicfg_read32(struct ssb_gige *dev, unsigned int offset)
++{
++	BUG_ON(offset >= 256);
++	return gige_read32(dev, SSB_GIGE_PCICFG + offset);
++}
++
++static inline
++void gige_pcicfg_write8(struct ssb_gige *dev,
++			unsigned int offset, u8 value)
++{
++	BUG_ON(offset >= 256);
++	gige_write8(dev, SSB_GIGE_PCICFG + offset, value);
++}
++
++static inline
++void gige_pcicfg_write16(struct ssb_gige *dev,
++			 unsigned int offset, u16 value)
++{
++	BUG_ON(offset >= 256);
++	gige_write16(dev, SSB_GIGE_PCICFG + offset, value);
++}
++
++static inline
++void gige_pcicfg_write32(struct ssb_gige *dev,
++			 unsigned int offset, u32 value)
++{
++	BUG_ON(offset >= 256);
++	gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
++}
++
++static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
++				    int reg, int size, u32 *val)
++{
++	struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
++	unsigned long flags;
++
++	if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	if (reg >= 256)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	spin_lock_irqsave(&dev->lock, flags);
++	switch (size) {
++	case 1:
++		*val = gige_pcicfg_read8(dev, reg);
++		break;
++	case 2:
++		*val = gige_pcicfg_read16(dev, reg);
++		break;
++	case 4:
++		*val = gige_pcicfg_read32(dev, reg);
++		break;
++	default:
++		WARN_ON(1);
++	}
++	spin_unlock_irqrestore(&dev->lock, flags);
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
++				     int reg, int size, u32 val)
++{
++	struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
++	unsigned long flags;
++
++	if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	if (reg >= 256)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	spin_lock_irqsave(&dev->lock, flags);
++	switch (size) {
++	case 1:
++		gige_pcicfg_write8(dev, reg, val);
++		break;
++	case 2:
++		gige_pcicfg_write16(dev, reg, val);
++		break;
++	case 4:
++		gige_pcicfg_write32(dev, reg, val);
++		break;
++	default:
++		WARN_ON(1);
++	}
++	spin_unlock_irqrestore(&dev->lock, flags);
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
++{
++	struct ssb_gige *dev;
++	u32 base, tmslow, tmshigh;
++
++	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++	if (!dev)
++		return -ENOMEM;
++	dev->dev = sdev;
++
++	spin_lock_init(&dev->lock);
++	dev->pci_controller.pci_ops = &dev->pci_ops;
++	dev->pci_controller.io_resource = &dev->io_resource;
++	dev->pci_controller.mem_resource = &dev->mem_resource;
++	dev->pci_controller.io_map_base = 0x800;
++	dev->pci_ops.read = ssb_gige_pci_read_config;
++	dev->pci_ops.write = ssb_gige_pci_write_config;
++
++	dev->io_resource.name = SSB_GIGE_IO_RES_NAME;
++	dev->io_resource.start = 0x800;
++	dev->io_resource.end = 0x8FF;
++	dev->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
++
++	if (!ssb_device_is_enabled(sdev))
++		ssb_device_enable(sdev, 0);
++
++	/* Setup BAR0. This is a 64k MMIO region. */
++	base = ssb_admatch_base(ssb_read32(sdev, SSB_ADMATCH1));
++	gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_0, base);
++	gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_1, 0);
++
++	dev->mem_resource.name = SSB_GIGE_MEM_RES_NAME;
++	dev->mem_resource.start = base;
++	dev->mem_resource.end = base + 0x10000 - 1;
++	dev->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
++
++	/* Enable the memory region. */
++	gige_pcicfg_write16(dev, PCI_COMMAND,
++			    gige_pcicfg_read16(dev, PCI_COMMAND)
++			    | PCI_COMMAND_MEMORY);
++
++	/* Write flushing is controlled by the Flush Status Control register.
++	 * We want to flush every register write with a timeout and we want
++	 * to disable the IRQ mask while flushing to avoid concurrency.
++	 * Note that automatic write flushing does _not_ work from
++	 * an IRQ handler. The driver must flush manually by reading a register.
++	 */
++	gige_write32(dev, SSB_GIGE_SHIM_FLUSHSTAT, 0x00000068);
++
++	/* Check if we have an RGMII or GMII PHY-bus.
++	 * On RGMII do not bypass the DLLs */
++	tmslow = ssb_read32(sdev, SSB_TMSLOW);
++	tmshigh = ssb_read32(sdev, SSB_TMSHIGH);
++	if (tmshigh & SSB_GIGE_TMSHIGH_RGMII) {
++		tmslow &= ~SSB_GIGE_TMSLOW_TXBYPASS;
++		tmslow &= ~SSB_GIGE_TMSLOW_RXBYPASS;
++		dev->has_rgmii = 1;
++	} else {
++		tmslow |= SSB_GIGE_TMSLOW_TXBYPASS;
++		tmslow |= SSB_GIGE_TMSLOW_RXBYPASS;
++		dev->has_rgmii = 0;
++	}
++	tmslow |= SSB_GIGE_TMSLOW_DLLEN;
++	ssb_write32(sdev, SSB_TMSLOW, tmslow);
++
++	ssb_set_drvdata(sdev, dev);
++	register_pci_controller(&dev->pci_controller);
++
++	return 0;
++}
++
++bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
++{
++	if (!pdev->resource[0].name)
++		return 0;
++	return (strcmp(pdev->resource[0].name, SSB_GIGE_MEM_RES_NAME) == 0);
++}
++EXPORT_SYMBOL(pdev_is_ssb_gige_core);
++
++int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
++				   struct pci_dev *pdev)
++{
++	struct ssb_gige *dev = ssb_get_drvdata(sdev);
++	struct resource *res;
++
++	if (pdev->bus->ops != &dev->pci_ops) {
++		/* The PCI device is not on this SSB GigE bridge device. */
++		return -ENODEV;
++	}
++
++	/* Fixup the PCI resources. */
++	res = &(pdev->resource[0]);
++	res->flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
++	res->name = dev->mem_resource.name;
++	res->start = dev->mem_resource.start;
++	res->end = dev->mem_resource.end;
++
++	/* Fixup interrupt lines. */
++	pdev->irq = ssb_mips_irq(sdev) + 2;
++	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
++
++	return 0;
++}
++
++int ssb_gige_map_irq(struct ssb_device *sdev,
++		     const struct pci_dev *pdev)
++{
++	struct ssb_gige *dev = ssb_get_drvdata(sdev);
++
++	if (pdev->bus->ops != &dev->pci_ops) {
++		/* The PCI device is not on this SSB GigE bridge device. */
++		return -ENODEV;
++	}
++
++	return ssb_mips_irq(sdev) + 2;
++}
++
++static struct ssb_driver ssb_gige_driver = {
++	.name		= "BCM-GigE",
++	.id_table	= ssb_gige_tbl,
++	.probe		= ssb_gige_probe,
++};
++
++int ssb_gige_init(void)
++{
++	return ssb_driver_register(&ssb_gige_driver);
++}
+diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
+index a9e7eb4..3fd3e3b 100644
+--- a/drivers/ssb/driver_mipscore.c
++++ b/drivers/ssb/driver_mipscore.c
+@@ -210,6 +210,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
+ 			/* fallthrough */
+ 		case SSB_DEV_PCI:
+ 		case SSB_DEV_ETHERNET:
++		case SSB_DEV_ETHERNET_GBIT:
+ 		case SSB_DEV_80211:
+ 		case SSB_DEV_USB20_HOST:
+ 			/* These devices get their own IRQ line if available, the rest goes on IRQ0 */
+diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
+index 5d777f2..75def13 100644
+--- a/drivers/ssb/driver_pcicore.c
++++ b/drivers/ssb/driver_pcicore.c
+@@ -60,77 +60,6 @@ static DEFINE_SPINLOCK(cfgspace_lock);
+ /* Core to access the external PCI config space. Can only have one. */
+ static struct ssb_pcicore *extpci_core;
+ 
+-static u32 ssb_pcicore_pcibus_iobase = 0x100;
+-static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
+-
+-int pcibios_plat_dev_init(struct pci_dev *d)
+-{
+-	struct resource *res;
+-	int pos, size;
+-	u32 *base;
+-
+-	ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
+-		   pci_name(d));
+-
+-	/* Fix up resource bases */
+-	for (pos = 0; pos < 6; pos++) {
+-		res = &d->resource[pos];
+-		if (res->flags & IORESOURCE_IO)
+-			base = &ssb_pcicore_pcibus_iobase;
+-		else
+-			base = &ssb_pcicore_pcibus_membase;
+-		res->flags |= IORESOURCE_PCI_FIXED;
+-		if (res->end) {
+-			size = res->end - res->start + 1;
+-			if (*base & (size - 1))
+-				*base = (*base + size) & ~(size - 1);
+-			res->start = *base;
+-			res->end = res->start + size - 1;
+-			*base += size;
+-			pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
+-		}
+-		/* Fix up PCI bridge BAR0 only */
+-		if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0)
+-			break;
+-	}
+-	/* Fix up interrupt lines */
+-	d->irq = ssb_mips_irq(extpci_core->dev) + 2;
+-	pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
+-
+-	return 0;
+-}
+-
+-static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
+-{
+-	u8 lat;
+-
+-	if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
+-		return;
+-
+-	ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
+-
+-	/* Enable PCI bridge bus mastering and memory space */
+-	pci_set_master(dev);
+-	if (pcibios_enable_device(dev, ~0) < 0) {
+-		ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
+-		return;
+-	}
+-
+-	/* Enable PCI bridge BAR1 prefetch and burst */
+-	pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
+-
+-	/* Make sure our latency is high enough to handle the devices behind us */
+-	lat = 168;
+-	ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
+-		   pci_name(dev), lat);
+-	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+-}
+-DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge);
+-
+-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+-{
+-	return ssb_mips_irq(extpci_core->dev) + 2;
+-}
+ 
+ static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
+ 			     unsigned int bus, unsigned int dev,
+@@ -320,6 +249,95 @@ static struct pci_controller ssb_pcicore_controller = {
+ 	.mem_offset	= 0x24000000,
+ };
+ 
++static u32 ssb_pcicore_pcibus_iobase = 0x100;
++static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
++
++/* This function is called when doing a pci_enable_device().
++ * We must first check if the device is a device on the PCI-core bridge. */
++int ssb_pcicore_plat_dev_init(struct pci_dev *d)
++{
++	struct resource *res;
++	int pos, size;
++	u32 *base;
++
++	if (d->bus->ops != &ssb_pcicore_pciops) {
++		/* This is not a device on the PCI-core bridge. */
++		return -ENODEV;
++	}
++
++	ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
++		   pci_name(d));
++
++	/* Fix up resource bases */
++	for (pos = 0; pos < 6; pos++) {
++		res = &d->resource[pos];
++		if (res->flags & IORESOURCE_IO)
++			base = &ssb_pcicore_pcibus_iobase;
++		else
++			base = &ssb_pcicore_pcibus_membase;
++		res->flags |= IORESOURCE_PCI_FIXED;
++		if (res->end) {
++			size = res->end - res->start + 1;
++			if (*base & (size - 1))
++				*base = (*base + size) & ~(size - 1);
++			res->start = *base;
++			res->end = res->start + size - 1;
++			*base += size;
++			pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
++		}
++		/* Fix up PCI bridge BAR0 only */
++		if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0)
++			break;
++	}
++	/* Fix up interrupt lines */
++	d->irq = ssb_mips_irq(extpci_core->dev) + 2;
++	pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
++
++	return 0;
++}
++
++/* Early PCI fixup for a device on the PCI-core bridge. */
++static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
++{
++	u8 lat;
++
++	if (dev->bus->ops != &ssb_pcicore_pciops) {
++		/* This is not a device on the PCI-core bridge. */
++		return;
++	}
++	if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
++		return;
++
++	ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
++
++	/* Enable PCI bridge bus mastering and memory space */
++	pci_set_master(dev);
++	if (pcibios_enable_device(dev, ~0) < 0) {
++		ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
++		return;
++	}
++
++	/* Enable PCI bridge BAR1 prefetch and burst */
++	pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
++
++	/* Make sure our latency is high enough to handle the devices behind us */
++	lat = 168;
++	ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
++		   pci_name(dev), lat);
++	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge);
++
++/* PCI device IRQ mapping. */
++int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++	if (dev->bus->ops != &ssb_pcicore_pciops) {
++		/* This is not a device on the PCI-core bridge. */
++		return -ENODEV;
++	}
++	return ssb_mips_irq(extpci_core->dev) + 2;
++}
++
+ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
+ {
+ 	u32 val;
+@@ -544,15 +562,9 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
+ 		u32 intvec;
+ 
+ 		intvec = ssb_read32(pdev, SSB_INTVEC);
+-		if ((bus->chip_id & 0xFF00) == 0x4400) {
+-			/* Workaround: On the BCM44XX the BPFLAG routing
+-			 * bit is wrong. Use a hardcoded constant. */
+-			intvec |= 0x00000002;
+-		} else {
+-			tmp = ssb_read32(dev, SSB_TPSFLAG);
+-			tmp &= SSB_TPSFLAG_BPFLAG;
+-			intvec |= (1 << tmp);
+-		}
++		tmp = ssb_read32(dev, SSB_TPSFLAG);
++		tmp &= SSB_TPSFLAG_BPFLAG;
++		intvec |= (1 << tmp);
+ 		ssb_write32(pdev, SSB_INTVEC, intvec);
+ 	}
+ 
+diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
+index d3ade82..7dc3a6b 100644
+--- a/drivers/ssb/embedded.c
++++ b/drivers/ssb/embedded.c
+@@ -10,6 +10,9 @@
+ 
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_embedded.h>
++#include <linux/ssb/ssb_driver_pci.h>
++#include <linux/ssb/ssb_driver_gige.h>
++#include <linux/pci.h>
+ 
+ #include "ssb_private.h"
+ 
+@@ -130,3 +133,90 @@ u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
+ 	return res;
+ }
+ EXPORT_SYMBOL(ssb_gpio_polarity);
++
++#ifdef CONFIG_SSB_DRIVER_GIGE
++static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
++{
++	struct pci_dev *pdev = (struct pci_dev *)data;
++	struct ssb_device *dev;
++	unsigned int i;
++	int res;
++
++	for (i = 0; i < bus->nr_devices; i++) {
++		dev = &(bus->devices[i]);
++		if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
++			continue;
++		if (!dev->dev ||
++		    !dev->dev->driver ||
++		    !device_is_registered(dev->dev))
++			continue;
++		res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
++		if (res >= 0)
++			return res;
++	}
++
++	return -ENODEV;
++}
++#endif /* CONFIG_SSB_DRIVER_GIGE */
++
++int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
++{
++	int err;
++
++	err = ssb_pcicore_plat_dev_init(dev);
++	if (!err)
++		return 0;
++#ifdef CONFIG_SSB_DRIVER_GIGE
++	err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
++	if (err >= 0)
++		return err;
++#endif
++	/* This is not a PCI device on any SSB device. */
++
++	return -ENODEV;
++}
++
++#ifdef CONFIG_SSB_DRIVER_GIGE
++static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
++{
++	const struct pci_dev *pdev = (const struct pci_dev *)data;
++	struct ssb_device *dev;
++	unsigned int i;
++	int res;
++
++	for (i = 0; i < bus->nr_devices; i++) {
++		dev = &(bus->devices[i]);
++		if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
++			continue;
++		if (!dev->dev ||
++		    !dev->dev->driver ||
++		    !device_is_registered(dev->dev))
++			continue;
++		res = ssb_gige_map_irq(dev, pdev);
++		if (res >= 0)
++			return res;
++	}
++
++	return -ENODEV;
++}
++#endif /* CONFIG_SSB_DRIVER_GIGE */
++
++int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++	int res;
++
++	/* Check if this PCI device is a device on a SSB bus or device
++	 * and return the IRQ number for it. */
++
++	res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
++	if (res >= 0)
++		return res;
++#ifdef CONFIG_SSB_DRIVER_GIGE
++	res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
++	if (res >= 0)
++		return res;
++#endif
++	/* This is not a PCI device on any SSB device. */
++
++	return -ENODEV;
++}
+diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
+index 8003a9e..7cf8851 100644
+--- a/drivers/ssb/main.c
++++ b/drivers/ssb/main.c
+@@ -14,6 +14,7 @@
+ #include <linux/io.h>
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_regs.h>
++#include <linux/ssb/ssb_driver_gige.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/pci.h>
+ 
+@@ -68,6 +69,44 @@ found:
+ }
+ #endif /* CONFIG_SSB_PCIHOST */
+ 
++#ifdef CONFIG_SSB_PCMCIAHOST
++struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev)
++{
++	struct ssb_bus *bus;
++
++	ssb_buses_lock();
++	list_for_each_entry(bus, &buses, list) {
++		if (bus->bustype == SSB_BUSTYPE_PCMCIA &&
++		    bus->host_pcmcia == pdev)
++			goto found;
++	}
++	bus = NULL;
++found:
++	ssb_buses_unlock();
++
++	return bus;
++}
++#endif /* CONFIG_SSB_PCMCIAHOST */
++
++int ssb_for_each_bus_call(unsigned long data,
++			  int (*func)(struct ssb_bus *bus, unsigned long data))
++{
++	struct ssb_bus *bus;
++	int res;
++
++	ssb_buses_lock();
++	list_for_each_entry(bus, &buses, list) {
++		res = func(bus, data);
++		if (res >= 0) {
++			ssb_buses_unlock();
++			return res;
++		}
++	}
++	ssb_buses_unlock();
++
++	return -ENODEV;
++}
++
+ static struct ssb_device *ssb_device_get(struct ssb_device *dev)
+ {
+ 	if (dev)
+@@ -81,35 +120,12 @@ static void ssb_device_put(struct ssb_device *dev)
+ 		put_device(dev->dev);
+ }
+ 
+-static int ssb_bus_resume(struct ssb_bus *bus)
+-{
+-	int err;
+-
+-	ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
+-	err = ssb_pcmcia_init(bus);
+-	if (err) {
+-		/* No need to disable XTAL, as we don't have one on PCMCIA. */
+-		return err;
+-	}
+-	ssb_chipco_resume(&bus->chipco);
+-
+-	return 0;
+-}
+-
+ static int ssb_device_resume(struct device *dev)
+ {
+ 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
+ 	struct ssb_driver *ssb_drv;
+-	struct ssb_bus *bus;
+ 	int err = 0;
+ 
+-	bus = ssb_dev->bus;
+-	if (bus->suspend_cnt == bus->nr_devices) {
+-		err = ssb_bus_resume(bus);
+-		if (err)
+-			return err;
+-	}
+-	bus->suspend_cnt--;
+ 	if (dev->driver) {
+ 		ssb_drv = drv_to_ssb_drv(dev->driver);
+ 		if (ssb_drv && ssb_drv->resume)
+@@ -121,27 +137,10 @@ out:
+ 	return err;
+ }
+ 
+-static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state)
+-{
+-	ssb_chipco_suspend(&bus->chipco, state);
+-	ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
+-
+-	/* Reset HW state information in memory, so that HW is
+-	 * completely reinitialized on resume. */
+-	bus->mapped_device = NULL;
+-#ifdef CONFIG_SSB_DRIVER_PCICORE
+-	bus->pcicore.setup_done = 0;
+-#endif
+-#ifdef CONFIG_SSB_DEBUG
+-	bus->powered_up = 0;
+-#endif
+-}
+-
+ static int ssb_device_suspend(struct device *dev, pm_message_t state)
+ {
+ 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
+ 	struct ssb_driver *ssb_drv;
+-	struct ssb_bus *bus;
+ 	int err = 0;
+ 
+ 	if (dev->driver) {
+@@ -151,19 +150,46 @@ static int ssb_device_suspend(struct device *dev, pm_message_t state)
+ 		if (err)
+ 			goto out;
+ 	}
++out:
++	return err;
++}
++
++int ssb_bus_resume(struct ssb_bus *bus)
++{
++	int err;
++
++	/* Reset HW state information in memory, so that HW is
++	 * completely reinitialized. */
++	bus->mapped_device = NULL;
++#ifdef CONFIG_SSB_DRIVER_PCICORE
++	bus->pcicore.setup_done = 0;
++#endif
+ 
+-	bus = ssb_dev->bus;
+-	bus->suspend_cnt++;
+-	if (bus->suspend_cnt == bus->nr_devices) {
+-		/* All devices suspended. Shutdown the bus. */
+-		ssb_bus_suspend(bus, state);
++	err = ssb_bus_powerup(bus, 0);
++	if (err)
++		return err;
++	err = ssb_pcmcia_hardware_setup(bus);
++	if (err) {
++		ssb_bus_may_powerdown(bus);
++		return err;
+ 	}
++	ssb_chipco_resume(&bus->chipco);
++	ssb_bus_may_powerdown(bus);
+ 
+-out:
+-	return err;
++	return 0;
+ }
++EXPORT_SYMBOL(ssb_bus_resume);
+ 
+-#ifdef CONFIG_SSB_PCIHOST
++int ssb_bus_suspend(struct ssb_bus *bus)
++{
++	ssb_chipco_suspend(&bus->chipco);
++	ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
++
++	return 0;
++}
++EXPORT_SYMBOL(ssb_bus_suspend);
++
++#ifdef CONFIG_SSB_SPROM
+ int ssb_devices_freeze(struct ssb_bus *bus)
+ {
+ 	struct ssb_device *dev;
+@@ -249,7 +275,7 @@ int ssb_devices_thaw(struct ssb_bus *bus)
+ 
+ 	return 0;
+ }
+-#endif /* CONFIG_SSB_PCIHOST */
++#endif /* CONFIG_SSB_SPROM */
+ 
+ static void ssb_device_shutdown(struct device *dev)
+ {
+@@ -378,7 +404,7 @@ void ssb_bus_unregister(struct ssb_bus *bus)
+ 	list_del(&bus->list);
+ 	ssb_buses_unlock();
+ 
+-	/* ssb_pcmcia_exit(bus); */
++	ssb_pcmcia_exit(bus);
+ 	ssb_pci_exit(bus);
+ 	ssb_iounmap(bus);
+ }
+@@ -508,6 +534,14 @@ error:
+ 	return err;
+ }
+ 
++static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	return readb(bus->mmio + offset);
++}
++
+ static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
+ {
+ 	struct ssb_bus *bus = dev->bus;
+@@ -524,6 +558,63 @@ static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
+ 	return readl(bus->mmio + offset);
+ }
+ 
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
++			       size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	void __iomem *addr;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	addr = bus->mmio + offset;
++
++	switch (reg_width) {
++	case sizeof(u8): {
++		u8 *buf = buffer;
++
++		while (count) {
++			*buf = __raw_readb(addr);
++			buf++;
++			count--;
++		}
++		break;
++	}
++	case sizeof(u16): {
++		__le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 1);
++		while (count) {
++			*buf = (__force __le16)__raw_readw(addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		__le32 *buf = buffer;
++
++		SSB_WARN_ON(count & 3);
++		while (count) {
++			*buf = (__force __le32)__raw_readl(addr);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		SSB_WARN_ON(1);
++	}
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	writeb(value, bus->mmio + offset);
++}
++
+ static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
+ {
+ 	struct ssb_bus *bus = dev->bus;
+@@ -540,12 +631,67 @@ static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
+ 	writel(value, bus->mmio + offset);
+ }
+ 
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
++				size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	void __iomem *addr;
++
++	offset += dev->core_index * SSB_CORE_SIZE;
++	addr = bus->mmio + offset;
++
++	switch (reg_width) {
++	case sizeof(u8): {
++		const u8 *buf = buffer;
++
++		while (count) {
++			__raw_writeb(*buf, addr);
++			buf++;
++			count--;
++		}
++		break;
++	}
++	case sizeof(u16): {
++		const __le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 1);
++		while (count) {
++			__raw_writew((__force u16)(*buf), addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		const __le32 *buf = buffer;
++
++		SSB_WARN_ON(count & 3);
++		while (count) {
++			__raw_writel((__force u32)(*buf), addr);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		SSB_WARN_ON(1);
++	}
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
+ /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
+ static const struct ssb_bus_ops ssb_ssb_ops = {
++	.read8		= ssb_ssb_read8,
+ 	.read16		= ssb_ssb_read16,
+ 	.read32		= ssb_ssb_read32,
++	.write8		= ssb_ssb_write8,
+ 	.write16	= ssb_ssb_write16,
+ 	.write32	= ssb_ssb_write32,
++#ifdef CONFIG_SSB_BLOCKIO
++	.block_read	= ssb_ssb_block_read,
++	.block_write	= ssb_ssb_block_write,
++#endif
+ };
+ 
+ static int ssb_fetch_invariants(struct ssb_bus *bus,
+@@ -628,7 +774,7 @@ out:
+ err_dequeue:
+ 	list_del(&bus->list);
+ err_pcmcia_exit:
+-/*	ssb_pcmcia_exit(bus); */
++	ssb_pcmcia_exit(bus);
+ err_pci_exit:
+ 	ssb_pci_exit(bus);
+ err_unmap:
+@@ -1010,9 +1156,9 @@ u32 ssb_dma_translation(struct ssb_device *dev)
+ {
+ 	switch (dev->bus->bustype) {
+ 	case SSB_BUSTYPE_SSB:
++	case SSB_BUSTYPE_PCMCIA:
+ 		return 0;
+ 	case SSB_BUSTYPE_PCI:
+-	case SSB_BUSTYPE_PCMCIA:
+ 		return SSB_PCI_DMA;
+ 	}
+ 	return 0;
+@@ -1161,7 +1307,14 @@ static int __init ssb_modinit(void)
+ 	err = b43_pci_ssb_bridge_init();
+ 	if (err) {
+ 		ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge "
+-			   "initialization failed");
++			   "initialization failed\n");
++		/* don't fail SSB init because of this */
++		err = 0;
++	}
++	err = ssb_gige_init();
++	if (err) {
++		ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet "
++			   "driver initialization failed\n");
+ 		/* don't fail SSB init because of this */
+ 		err = 0;
+ 	}
+@@ -1175,6 +1328,7 @@ fs_initcall(ssb_modinit);
+ 
+ static void __exit ssb_modexit(void)
+ {
++	ssb_gige_exit();
+ 	b43_pci_ssb_bridge_exit();
+ 	bus_unregister(&ssb_bustype);
+ }
+diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
+index b434df7..57c4ccf 100644
+--- a/drivers/ssb/pci.c
++++ b/drivers/ssb/pci.c
+@@ -227,7 +227,7 @@ static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
+ 	return crc;
+ }
+ 
+-static int sprom_check_crc(const u16 *sprom, u16 size)
++static int sprom_check_crc(const u16 *sprom, size_t size)
+ {
+ 	u8 crc;
+ 	u8 expected_crc;
+@@ -242,12 +242,14 @@ static int sprom_check_crc(const u16 *sprom, u16 size)
+ 	return 0;
+ }
+ 
+-static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
++static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < bus->sprom_size; i++)
+ 		sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
++
++	return 0;
+ }
+ 
+ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
+@@ -482,6 +484,11 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
+ 			goto unsupported;
+ 	}
+ 
++	if (out->boardflags_lo == 0xFFFF)
++		out->boardflags_lo = 0;  /* per specs */
++	if (out->boardflags_hi == 0xFFFF)
++		out->boardflags_hi = 0;  /* per specs */
++
+ 	return 0;
+ unsupported:
+ 	ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
+@@ -572,6 +579,19 @@ static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
+ }
+ #endif /* DEBUG */
+ 
++static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	if (unlikely(ssb_pci_assert_buspower(bus)))
++		return 0xFF;
++	if (unlikely(bus->mapped_device != dev)) {
++		if (unlikely(ssb_pci_switch_core(bus, dev)))
++			return 0xFF;
++	}
++	return ioread8(bus->mmio + offset);
++}
++
+ static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
+ {
+ 	struct ssb_bus *bus = dev->bus;
+@@ -598,6 +618,54 @@ static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
+ 	return ioread32(bus->mmio + offset);
+ }
+ 
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
++			       size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	void __iomem *addr = bus->mmio + offset;
++
++	if (unlikely(ssb_pci_assert_buspower(bus)))
++		goto error;
++	if (unlikely(bus->mapped_device != dev)) {
++		if (unlikely(ssb_pci_switch_core(bus, dev)))
++			goto error;
++	}
++	switch (reg_width) {
++	case sizeof(u8):
++		ioread8_rep(addr, buffer, count);
++		break;
++	case sizeof(u16):
++		SSB_WARN_ON(count & 1);
++		ioread16_rep(addr, buffer, count >> 1);
++		break;
++	case sizeof(u32):
++		SSB_WARN_ON(count & 3);
++		ioread32_rep(addr, buffer, count >> 2);
++		break;
++	default:
++		SSB_WARN_ON(1);
++	}
++
++	return;
++error:
++	memset(buffer, 0xFF, count);
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++	struct ssb_bus *bus = dev->bus;
++
++	if (unlikely(ssb_pci_assert_buspower(bus)))
++		return;
++	if (unlikely(bus->mapped_device != dev)) {
++		if (unlikely(ssb_pci_switch_core(bus, dev)))
++			return;
++	}
++	iowrite8(value, bus->mmio + offset);
++}
++
+ static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
+ {
+ 	struct ssb_bus *bus = dev->bus;
+@@ -624,79 +692,63 @@ static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
+ 	iowrite32(value, bus->mmio + offset);
+ }
+ 
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
++				size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	void __iomem *addr = bus->mmio + offset;
++
++	if (unlikely(ssb_pci_assert_buspower(bus)))
++		return;
++	if (unlikely(bus->mapped_device != dev)) {
++		if (unlikely(ssb_pci_switch_core(bus, dev)))
++			return;
++	}
++	switch (reg_width) {
++	case sizeof(u8):
++		iowrite8_rep(addr, buffer, count);
++		break;
++	case sizeof(u16):
++		SSB_WARN_ON(count & 1);
++		iowrite16_rep(addr, buffer, count >> 1);
++		break;
++	case sizeof(u32):
++		SSB_WARN_ON(count & 3);
++		iowrite32_rep(addr, buffer, count >> 2);
++		break;
++	default:
++		SSB_WARN_ON(1);
++	}
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
+ /* Not "static", as it's used in main.c */
+ const struct ssb_bus_ops ssb_pci_ops = {
++	.read8		= ssb_pci_read8,
+ 	.read16		= ssb_pci_read16,
+ 	.read32		= ssb_pci_read32,
++	.write8		= ssb_pci_write8,
+ 	.write16	= ssb_pci_write16,
+ 	.write32	= ssb_pci_write32,
++#ifdef CONFIG_SSB_BLOCKIO
++	.block_read	= ssb_pci_block_read,
++	.block_write	= ssb_pci_block_write,
++#endif
+ };
+ 
+-static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
+-{
+-	int i, pos = 0;
+-
+-	for (i = 0; i < size; i++)
+-		pos += snprintf(buf + pos, buf_len - pos - 1,
+-				"%04X", swab16(sprom[i]) & 0xFFFF);
+-	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
+-
+-	return pos + 1;
+-}
+-
+-static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size)
+-{
+-	char tmp[5] = { 0 };
+-	int cnt = 0;
+-	unsigned long parsed;
+-
+-	if (len < size * 2)
+-		return -EINVAL;
+-
+-	while (cnt < size) {
+-		memcpy(tmp, dump, 4);
+-		dump += 4;
+-		parsed = simple_strtoul(tmp, NULL, 16);
+-		sprom[cnt++] = swab16((u16)parsed);
+-	}
+-
+-	return 0;
+-}
+-
+ static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
+ 				       struct device_attribute *attr,
+ 				       char *buf)
+ {
+ 	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
+ 	struct ssb_bus *bus;
+-	u16 *sprom;
+-	int err = -ENODEV;
+-	ssize_t count = 0;
+ 
+ 	bus = ssb_pci_dev_to_bus(pdev);
+ 	if (!bus)
+-		goto out;
+-	err = -ENOMEM;
+-	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
+-	if (!sprom)
+-		goto out;
++		return -ENODEV;
+ 
+-	/* Use interruptible locking, as the SPROM write might
+-	 * be holding the lock for several seconds. So allow userspace
+-	 * to cancel operation. */
+-	err = -ERESTARTSYS;
+-	if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
+-		goto out_kfree;
+-	sprom_do_read(bus, sprom);
+-	mutex_unlock(&bus->pci_sprom_mutex);
+-
+-	count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size);
+-	err = 0;
+-
+-out_kfree:
+-	kfree(sprom);
+-out:
+-	return err ? err : count;
++	return ssb_attr_sprom_show(bus, buf, sprom_do_read);
+ }
+ 
+ static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
+@@ -705,55 +757,13 @@ static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
+ {
+ 	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
+ 	struct ssb_bus *bus;
+-	u16 *sprom;
+-	int res = 0, err = -ENODEV;
+ 
+ 	bus = ssb_pci_dev_to_bus(pdev);
+ 	if (!bus)
+-		goto out;
+-	err = -ENOMEM;
+-	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
+-	if (!sprom)
+-		goto out;
+-	err = hex2sprom(sprom, buf, count, bus->sprom_size);
+-	if (err) {
+-		err = -EINVAL;
+-		goto out_kfree;
+-	}
+-	err = sprom_check_crc(sprom, bus->sprom_size);
+-	if (err) {
+-		err = -EINVAL;
+-		goto out_kfree;
+-	}
++		return -ENODEV;
+ 
+-	/* Use interruptible locking, as the SPROM write might
+-	 * be holding the lock for several seconds. So allow userspace
+-	 * to cancel operation. */
+-	err = -ERESTARTSYS;
+-	if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
+-		goto out_kfree;
+-	err = ssb_devices_freeze(bus);
+-	if (err == -EOPNOTSUPP) {
+-		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
+-			   "No suspend support. Is CONFIG_PM enabled?\n");
+-		goto out_unlock;
+-	}
+-	if (err) {
+-		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
+-		goto out_unlock;
+-	}
+-	res = sprom_do_write(bus, sprom);
+-	err = ssb_devices_thaw(bus);
+-	if (err)
+-		ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
+-out_unlock:
+-	mutex_unlock(&bus->pci_sprom_mutex);
+-out_kfree:
+-	kfree(sprom);
+-out:
+-	if (res)
+-		return res;
+-	return err ? err : count;
++	return ssb_attr_sprom_store(bus, buf, count,
++				    sprom_check_crc, sprom_do_write);
+ }
+ 
+ static DEVICE_ATTR(ssb_sprom, 0600,
+@@ -780,7 +790,7 @@ int ssb_pci_init(struct ssb_bus *bus)
+ 		return 0;
+ 
+ 	pdev = bus->host_pci;
+-	mutex_init(&bus->pci_sprom_mutex);
++	mutex_init(&bus->sprom_mutex);
+ 	err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
+ 	if (err)
+ 		goto out;
+diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
+index 82a10ab..e82db4a 100644
+--- a/drivers/ssb/pcihost_wrapper.c
++++ b/drivers/ssb/pcihost_wrapper.c
+@@ -18,6 +18,12 @@
+ #ifdef CONFIG_PM
+ static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
+ {
++	struct ssb_bus *ssb = pci_get_drvdata(dev);
++	int err;
++
++	err = ssb_bus_suspend(ssb);
++	if (err)
++		return err;
+ 	pci_save_state(dev);
+ 	pci_disable_device(dev);
+ 	pci_set_power_state(dev, pci_choose_state(dev, state));
+@@ -27,6 +33,7 @@ static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
+ 
+ static int ssb_pcihost_resume(struct pci_dev *dev)
+ {
++	struct ssb_bus *ssb = pci_get_drvdata(dev);
+ 	int err;
+ 
+ 	pci_set_power_state(dev, 0);
+@@ -34,6 +41,9 @@ static int ssb_pcihost_resume(struct pci_dev *dev)
+ 	if (err)
+ 		return err;
+ 	pci_restore_state(dev);
++	err = ssb_bus_resume(ssb);
++	if (err)
++		return err;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
+index 46816cd..24c2a46 100644
+--- a/drivers/ssb/pcmcia.c
++++ b/drivers/ssb/pcmcia.c
+@@ -3,7 +3,7 @@
+  * PCMCIA-Hostbus related functions
+  *
+  * Copyright 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Copyright 2007 Michael Buesch <mb at bu3sch.de>
++ * Copyright 2007-2008 Michael Buesch <mb at bu3sch.de>
+  *
+  * Licensed under the GNU/GPL. See COPYING for details.
+  */
+@@ -11,6 +11,7 @@
+ #include <linux/ssb/ssb.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
++#include <linux/etherdevice.h>
+ 
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cs.h>
+@@ -26,59 +27,127 @@
+ #define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG		0
+ 
+ 
++/* PCMCIA configuration registers */
++#define SSB_PCMCIA_ADDRESS0		0x2E
++#define SSB_PCMCIA_ADDRESS1		0x30
++#define SSB_PCMCIA_ADDRESS2		0x32
++#define SSB_PCMCIA_MEMSEG		0x34
++#define SSB_PCMCIA_SPROMCTL		0x36
++#define  SSB_PCMCIA_SPROMCTL_IDLE	0
++#define  SSB_PCMCIA_SPROMCTL_WRITE	1
++#define  SSB_PCMCIA_SPROMCTL_READ	2
++#define  SSB_PCMCIA_SPROMCTL_WRITEEN	4
++#define  SSB_PCMCIA_SPROMCTL_WRITEDIS	7
++#define  SSB_PCMCIA_SPROMCTL_DONE	8
++#define SSB_PCMCIA_SPROM_DATALO		0x38
++#define SSB_PCMCIA_SPROM_DATAHI		0x3A
++#define SSB_PCMCIA_SPROM_ADDRLO		0x3C
++#define SSB_PCMCIA_SPROM_ADDRHI		0x3E
++
++/* Hardware invariants CIS tuples */
++#define SSB_PCMCIA_CIS			0x80
++#define  SSB_PCMCIA_CIS_ID		0x01
++#define  SSB_PCMCIA_CIS_BOARDREV	0x02
++#define  SSB_PCMCIA_CIS_PA		0x03
++#define   SSB_PCMCIA_CIS_PA_PA0B0_LO	0
++#define   SSB_PCMCIA_CIS_PA_PA0B0_HI	1
++#define   SSB_PCMCIA_CIS_PA_PA0B1_LO	2
++#define   SSB_PCMCIA_CIS_PA_PA0B1_HI	3
++#define   SSB_PCMCIA_CIS_PA_PA0B2_LO	4
++#define   SSB_PCMCIA_CIS_PA_PA0B2_HI	5
++#define   SSB_PCMCIA_CIS_PA_ITSSI	6
++#define   SSB_PCMCIA_CIS_PA_MAXPOW	7
++#define  SSB_PCMCIA_CIS_OEMNAME		0x04
++#define  SSB_PCMCIA_CIS_CCODE		0x05
++#define  SSB_PCMCIA_CIS_ANTENNA		0x06
++#define  SSB_PCMCIA_CIS_ANTGAIN		0x07
++#define  SSB_PCMCIA_CIS_BFLAGS		0x08
++#define  SSB_PCMCIA_CIS_LEDS		0x09
++
++/* PCMCIA SPROM size. */
++#define SSB_PCMCIA_SPROM_SIZE		256
++#define SSB_PCMCIA_SPROM_SIZE_BYTES	(SSB_PCMCIA_SPROM_SIZE * sizeof(u16))
++
++
++/* Write to a PCMCIA configuration register. */
++static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
++{
++	conf_reg_t reg;
++	int res;
++
++	memset(&reg, 0, sizeof(reg));
++	reg.Offset = offset;
++	reg.Action = CS_WRITE;
++	reg.Value = value;
++	res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
++	if (unlikely(res != CS_SUCCESS))
++		return -EBUSY;
++
++	return 0;
++}
++
++/* Read from a PCMCIA configuration register. */
++static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
++{
++	conf_reg_t reg;
++	int res;
++
++	memset(&reg, 0, sizeof(reg));
++	reg.Offset = offset;
++	reg.Action = CS_READ;
++	res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
++	if (unlikely(res != CS_SUCCESS))
++		return -EBUSY;
++	*value = reg.Value;
++
++	return 0;
++}
++
+ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
+ 			      u8 coreidx)
+ {
+-	struct pcmcia_device *pdev = bus->host_pcmcia;
+ 	int err;
+ 	int attempts = 0;
+ 	u32 cur_core;
+-	conf_reg_t reg;
+ 	u32 addr;
+ 	u32 read_addr;
++	u8 val;
+ 
+ 	addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
+ 	while (1) {
+-		reg.Action = CS_WRITE;
+-		reg.Offset = 0x2E;
+-		reg.Value = (addr & 0x0000F000) >> 12;
+-		err = pcmcia_access_configuration_register(pdev, &reg);
+-		if (err != CS_SUCCESS)
++		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS0,
++					   (addr & 0x0000F000) >> 12);
++		if (err)
+ 			goto error;
+-		reg.Offset = 0x30;
+-		reg.Value = (addr & 0x00FF0000) >> 16;
+-		err = pcmcia_access_configuration_register(pdev, &reg);
+-		if (err != CS_SUCCESS)
++		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS1,
++					   (addr & 0x00FF0000) >> 16);
++		if (err)
+ 			goto error;
+-		reg.Offset = 0x32;
+-		reg.Value = (addr & 0xFF000000) >> 24;
+-		err = pcmcia_access_configuration_register(pdev, &reg);
+-		if (err != CS_SUCCESS)
++		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS2,
++					   (addr & 0xFF000000) >> 24);
++		if (err)
+ 			goto error;
+ 
+ 		read_addr = 0;
+ 
+-		reg.Action = CS_READ;
+-		reg.Offset = 0x2E;
+-		err = pcmcia_access_configuration_register(pdev, &reg);
+-		if (err != CS_SUCCESS)
++		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS0, &val);
++		if (err)
+ 			goto error;
+-		read_addr |= ((u32)(reg.Value & 0x0F)) << 12;
+-		reg.Offset = 0x30;
+-		err = pcmcia_access_configuration_register(pdev, &reg);
+-		if (err != CS_SUCCESS)
++		read_addr |= ((u32)(val & 0x0F)) << 12;
++		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS1, &val);
++		if (err)
+ 			goto error;
+-		read_addr |= ((u32)reg.Value) << 16;
+-		reg.Offset = 0x32;
+-		err = pcmcia_access_configuration_register(pdev, &reg);
+-		if (err != CS_SUCCESS)
++		read_addr |= ((u32)val) << 16;
++		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS2, &val);
++		if (err)
+ 			goto error;
+-		read_addr |= ((u32)reg.Value) << 24;
++		read_addr |= ((u32)val) << 24;
+ 
+ 		cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
+ 		if (cur_core == coreidx)
+ 			break;
+ 
++		err = -ETIMEDOUT;
+ 		if (attempts++ > SSB_BAR0_MAX_RETRIES)
+ 			goto error;
+ 		udelay(10);
+@@ -87,7 +156,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
+ 	return 0;
+ error:
+ 	ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
+-	return -ENODEV;
++	return err;
+ }
+ 
+ int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+@@ -112,27 +181,21 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
+ {
+ 	int attempts = 0;
+-	conf_reg_t reg;
+-	int res;
++	int err;
++	u8 val;
+ 
+ 	SSB_WARN_ON((seg != 0) && (seg != 1));
+-	reg.Offset = 0x34;
+-	reg.Function = 0;
+ 	while (1) {
+-		reg.Action = CS_WRITE;
+-		reg.Value = seg;
+-		res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
+-		if (unlikely(res != CS_SUCCESS))
++		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_MEMSEG, seg);
++		if (err)
+ 			goto error;
+-		reg.Value = 0xFF;
+-		reg.Action = CS_READ;
+-		res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
+-		if (unlikely(res != CS_SUCCESS))
++		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_MEMSEG, &val);
++		if (err)
+ 			goto error;
+-
+-		if (reg.Value == seg)
++		if (val == seg)
+ 			break;
+ 
++		err = -ETIMEDOUT;
+ 		if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES))
+ 			goto error;
+ 		udelay(10);
+@@ -142,7 +205,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
+ 	return 0;
+ error:
+ 	ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n");
+-	return -ENODEV;
++	return err;
+ }
+ 
+ static int select_core_and_segment(struct ssb_device *dev,
+@@ -172,6 +235,22 @@ static int select_core_and_segment(struct ssb_device *dev,
+ 	return 0;
+ }
+ 
++static u8 ssb_pcmcia_read8(struct ssb_device *dev, u16 offset)
++{
++	struct ssb_bus *bus = dev->bus;
++	unsigned long flags;
++	int err;
++	u8 value = 0xFF;
++
++	spin_lock_irqsave(&bus->bar_lock, flags);
++	err = select_core_and_segment(dev, &offset);
++	if (likely(!err))
++		value = readb(bus->mmio + offset);
++	spin_unlock_irqrestore(&bus->bar_lock, flags);
++
++	return value;
++}
++
+ static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
+ {
+ 	struct ssb_bus *bus = dev->bus;
+@@ -206,6 +285,78 @@ static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
+ 	return (lo | (hi << 16));
+ }
+ 
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer,
++				  size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	unsigned long flags;
++	void __iomem *addr = bus->mmio + offset;
++	int err;
++
++	spin_lock_irqsave(&bus->bar_lock, flags);
++	err = select_core_and_segment(dev, &offset);
++	if (unlikely(err)) {
++		memset(buffer, 0xFF, count);
++		goto unlock;
++	}
++	switch (reg_width) {
++	case sizeof(u8): {
++		u8 *buf = buffer;
++
++		while (count) {
++			*buf = __raw_readb(addr);
++			buf++;
++			count--;
++		}
++		break;
++	}
++	case sizeof(u16): {
++		__le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 1);
++		while (count) {
++			*buf = (__force __le16)__raw_readw(addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		__le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 3);
++		while (count) {
++			*buf = (__force __le16)__raw_readw(addr);
++			buf++;
++			*buf = (__force __le16)__raw_readw(addr + 2);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		SSB_WARN_ON(1);
++	}
++unlock:
++	spin_unlock_irqrestore(&bus->bar_lock, flags);
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++	struct ssb_bus *bus = dev->bus;
++	unsigned long flags;
++	int err;
++
++	spin_lock_irqsave(&bus->bar_lock, flags);
++	err = select_core_and_segment(dev, &offset);
++	if (likely(!err))
++		writeb(value, bus->mmio + offset);
++	mmiowb();
++	spin_unlock_irqrestore(&bus->bar_lock, flags);
++}
++
+ static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
+ {
+ 	struct ssb_bus *bus = dev->bus;
+@@ -236,26 +387,425 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
+ 	spin_unlock_irqrestore(&bus->bar_lock, flags);
+ }
+ 
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,
++				   size_t count, u16 offset, u8 reg_width)
++{
++	struct ssb_bus *bus = dev->bus;
++	unsigned long flags;
++	void __iomem *addr = bus->mmio + offset;
++	int err;
++
++	spin_lock_irqsave(&bus->bar_lock, flags);
++	err = select_core_and_segment(dev, &offset);
++	if (unlikely(err))
++		goto unlock;
++	switch (reg_width) {
++	case sizeof(u8): {
++		const u8 *buf = buffer;
++
++		while (count) {
++			__raw_writeb(*buf, addr);
++			buf++;
++			count--;
++		}
++		break;
++	}
++	case sizeof(u16): {
++		const __le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 1);
++		while (count) {
++			__raw_writew((__force u16)(*buf), addr);
++			buf++;
++			count -= 2;
++		}
++		break;
++	}
++	case sizeof(u32): {
++		const __le16 *buf = buffer;
++
++		SSB_WARN_ON(count & 3);
++		while (count) {
++			__raw_writew((__force u16)(*buf), addr);
++			buf++;
++			__raw_writew((__force u16)(*buf), addr + 2);
++			buf++;
++			count -= 4;
++		}
++		break;
++	}
++	default:
++		SSB_WARN_ON(1);
++	}
++unlock:
++	mmiowb();
++	spin_unlock_irqrestore(&bus->bar_lock, flags);
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
+ /* Not "static", as it's used in main.c */
+ const struct ssb_bus_ops ssb_pcmcia_ops = {
++	.read8		= ssb_pcmcia_read8,
+ 	.read16		= ssb_pcmcia_read16,
+ 	.read32		= ssb_pcmcia_read32,
++	.write8		= ssb_pcmcia_write8,
+ 	.write16	= ssb_pcmcia_write16,
+ 	.write32	= ssb_pcmcia_write32,
++#ifdef CONFIG_SSB_BLOCKIO
++	.block_read	= ssb_pcmcia_block_read,
++	.block_write	= ssb_pcmcia_block_write,
++#endif
+ };
+ 
+-#include <linux/etherdevice.h>
++static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
++{
++	unsigned int i;
++	int err;
++	u8 value;
++
++	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);
++	if (err)
++		return err;
++	for (i = 0; i < 1000; i++) {
++		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);
++		if (err)
++			return err;
++		if (value & SSB_PCMCIA_SPROMCTL_DONE)
++			return 0;
++		udelay(10);
++	}
++
++	return -ETIMEDOUT;
++}
++
++/* offset is the 16bit word offset */
++static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
++{
++	int err;
++	u8 lo, hi;
++
++	offset *= 2; /* Make byte offset */
++
++	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
++				   (offset & 0x00FF));
++	if (err)
++		return err;
++	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
++				   (offset & 0xFF00) >> 8);
++	if (err)
++		return err;
++	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);
++	if (err)
++		return err;
++	err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);
++	if (err)
++		return err;
++	err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);
++	if (err)
++		return err;
++	*value = (lo | (((u16)hi) << 8));
++
++	return 0;
++}
++
++/* offset is the 16bit word offset */
++static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)
++{
++	int err;
++
++	offset *= 2; /* Make byte offset */
++
++	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
++				   (offset & 0x00FF));
++	if (err)
++		return err;
++	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
++				   (offset & 0xFF00) >> 8);
++	if (err)
++		return err;
++	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,
++				   (value & 0x00FF));
++	if (err)
++		return err;
++	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,
++				   (value & 0xFF00) >> 8);
++	if (err)
++		return err;
++	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);
++	if (err)
++		return err;
++	msleep(20);
++
++	return 0;
++}
++
++/* Read the SPROM image. bufsize is in 16bit words. */
++static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)
++{
++	int err, i;
++
++	for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {
++		err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);
++		if (err)
++			return err;
++	}
++
++	return 0;
++}
++
++/* Write the SPROM image. size is in 16bit words. */
++static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
++{
++	int i, err;
++	bool failed = 0;
++	size_t size = SSB_PCMCIA_SPROM_SIZE;
++
++	ssb_printk(KERN_NOTICE PFX
++		   "Writing SPROM. Do NOT turn off the power! "
++		   "Please stand by...\n");
++	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
++	if (err) {
++		ssb_printk(KERN_NOTICE PFX
++			   "Could not enable SPROM write access.\n");
++		return -EBUSY;
++	}
++	ssb_printk(KERN_NOTICE PFX "[ 0%%");
++	msleep(500);
++	for (i = 0; i < size; i++) {
++		if (i == size / 4)
++			ssb_printk("25%%");
++		else if (i == size / 2)
++			ssb_printk("50%%");
++		else if (i == (size * 3) / 4)
++			ssb_printk("75%%");
++		else if (i % 2)
++			ssb_printk(".");
++		err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
++		if (err) {
++			ssb_printk("\n" KERN_NOTICE PFX
++				   "Failed to write to SPROM.\n");
++			failed = 1;
++			break;
++		}
++	}
++	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
++	if (err) {
++		ssb_printk("\n" KERN_NOTICE PFX
++			   "Could not disable SPROM write access.\n");
++		failed = 1;
++	}
++	msleep(500);
++	if (!failed) {
++		ssb_printk("100%% ]\n");
++		ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
++	}
++
++	return failed ? -EBUSY : 0;
++}
++
++static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
++{
++	//TODO
++	return 0;
++}
++
++#define GOTO_ERROR_ON(condition, description) do {	\
++	if (unlikely(condition)) {			\
++		error_description = description;	\
++		goto error;				\
++	}						\
++  } while (0)
++
+ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
+ 			      struct ssb_init_invariants *iv)
+ {
+-	//TODO
+-	random_ether_addr(iv->sprom.il0mac);
++	tuple_t tuple;
++	int res;
++	unsigned char buf[32];
++	struct ssb_sprom *sprom = &iv->sprom;
++	struct ssb_boardinfo *bi = &iv->boardinfo;
++	const char *error_description;
++
++	memset(sprom, 0xFF, sizeof(*sprom));
++	sprom->revision = 1;
++	sprom->boardflags_lo = 0;
++	sprom->boardflags_hi = 0;
++
++	/* First fetch the MAC address. */
++	memset(&tuple, 0, sizeof(tuple));
++	tuple.DesiredTuple = CISTPL_FUNCE;
++	tuple.TupleData = buf;
++	tuple.TupleDataMax = sizeof(buf);
++	res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
++	GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl");
++	res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
++	GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl data");
++	while (1) {
++		GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1");
++		if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID)
++			break;
++		res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
++		GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl");
++		res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
++		GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl data");
++	}
++	GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size");
++	memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN);
++
++	/* Fetch the vendor specific tuples. */
++	memset(&tuple, 0, sizeof(tuple));
++	tuple.DesiredTuple = SSB_PCMCIA_CIS;
++	tuple.TupleData = buf;
++	tuple.TupleDataMax = sizeof(buf);
++	res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
++	GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl");
++	res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
++	GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl data");
++	while (1) {
++		GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1");
++		switch (tuple.TupleData[0]) {
++		case SSB_PCMCIA_CIS_ID:
++			GOTO_ERROR_ON((tuple.TupleDataLen != 5) &&
++				      (tuple.TupleDataLen != 7),
++				      "id tpl size");
++			bi->vendor = tuple.TupleData[1] |
++			       ((u16)tuple.TupleData[2] << 8);
++			break;
++		case SSB_PCMCIA_CIS_BOARDREV:
++			GOTO_ERROR_ON(tuple.TupleDataLen != 2,
++				      "boardrev tpl size");
++			sprom->board_rev = tuple.TupleData[1];
++			break;
++		case SSB_PCMCIA_CIS_PA:
++			GOTO_ERROR_ON(tuple.TupleDataLen != 9,
++				      "pa tpl size");
++			sprom->pa0b0 = tuple.TupleData[1] |
++				 ((u16)tuple.TupleData[2] << 8);
++			sprom->pa0b1 = tuple.TupleData[3] |
++				 ((u16)tuple.TupleData[4] << 8);
++			sprom->pa0b2 = tuple.TupleData[5] |
++				 ((u16)tuple.TupleData[6] << 8);
++			sprom->itssi_a = tuple.TupleData[7];
++			sprom->itssi_bg = tuple.TupleData[7];
++			sprom->maxpwr_a = tuple.TupleData[8];
++			sprom->maxpwr_bg = tuple.TupleData[8];
++			break;
++		case SSB_PCMCIA_CIS_OEMNAME:
++			/* We ignore this. */
++			break;
++		case SSB_PCMCIA_CIS_CCODE:
++			GOTO_ERROR_ON(tuple.TupleDataLen != 2,
++				      "ccode tpl size");
++			sprom->country_code = tuple.TupleData[1];
++			break;
++		case SSB_PCMCIA_CIS_ANTENNA:
++			GOTO_ERROR_ON(tuple.TupleDataLen != 2,
++				      "ant tpl size");
++			sprom->ant_available_a = tuple.TupleData[1];
++			sprom->ant_available_bg = tuple.TupleData[1];
++			break;
++		case SSB_PCMCIA_CIS_ANTGAIN:
++			GOTO_ERROR_ON(tuple.TupleDataLen != 2,
++				      "antg tpl size");
++			sprom->antenna_gain.ghz24.a0 = tuple.TupleData[1];
++			sprom->antenna_gain.ghz24.a1 = tuple.TupleData[1];
++			sprom->antenna_gain.ghz24.a2 = tuple.TupleData[1];
++			sprom->antenna_gain.ghz24.a3 = tuple.TupleData[1];
++			sprom->antenna_gain.ghz5.a0 = tuple.TupleData[1];
++			sprom->antenna_gain.ghz5.a1 = tuple.TupleData[1];
++			sprom->antenna_gain.ghz5.a2 = tuple.TupleData[1];
++			sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1];
++			break;
++		case SSB_PCMCIA_CIS_BFLAGS:
++			GOTO_ERROR_ON(tuple.TupleDataLen != 3,
++				      "bfl tpl size");
++			sprom->boardflags_lo = tuple.TupleData[1] |
++					 ((u16)tuple.TupleData[2] << 8);
++			break;
++		case SSB_PCMCIA_CIS_LEDS:
++			GOTO_ERROR_ON(tuple.TupleDataLen != 5,
++				      "leds tpl size");
++			sprom->gpio0 = tuple.TupleData[1];
++			sprom->gpio1 = tuple.TupleData[2];
++			sprom->gpio2 = tuple.TupleData[3];
++			sprom->gpio3 = tuple.TupleData[4];
++			break;
++		}
++		res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
++		if (res == CS_NO_MORE_ITEMS)
++			break;
++		GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl");
++		res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
++		GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl data");
++	}
++
+ 	return 0;
++error:
++	ssb_printk(KERN_ERR PFX
++		   "PCMCIA: Failed to fetch device invariants: %s\n",
++		   error_description);
++	return -ENODEV;
+ }
+ 
+-int ssb_pcmcia_init(struct ssb_bus *bus)
++static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev,
++					  struct device_attribute *attr,
++					  char *buf)
++{
++	struct pcmcia_device *pdev =
++		container_of(pcmciadev, struct pcmcia_device, dev);
++	struct ssb_bus *bus;
++
++	bus = ssb_pcmcia_dev_to_bus(pdev);
++	if (!bus)
++		return -ENODEV;
++
++	return ssb_attr_sprom_show(bus, buf,
++				   ssb_pcmcia_sprom_read_all);
++}
++
++static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev,
++					   struct device_attribute *attr,
++					   const char *buf, size_t count)
++{
++	struct pcmcia_device *pdev =
++		container_of(pcmciadev, struct pcmcia_device, dev);
++	struct ssb_bus *bus;
++
++	bus = ssb_pcmcia_dev_to_bus(pdev);
++	if (!bus)
++		return -ENODEV;
++
++	return ssb_attr_sprom_store(bus, buf, count,
++				    ssb_pcmcia_sprom_check_crc,
++				    ssb_pcmcia_sprom_write_all);
++}
++
++static DEVICE_ATTR(ssb_sprom, 0600,
++		   ssb_pcmcia_attr_sprom_show,
++		   ssb_pcmcia_attr_sprom_store);
++
++static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)
++{
++	u8 val;
++	int err;
++
++	err = ssb_pcmcia_cfg_read(bus, cor, &val);
++	if (err)
++		return err;
++	val &= ~COR_SOFT_RESET;
++	val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;
++	err = ssb_pcmcia_cfg_write(bus, cor, val);
++	if (err)
++		return err;
++	msleep(40);
++
++	return 0;
++}
++
++/* Initialize the PCMCIA hardware. This is called on Init and Resume. */
++int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
+ {
+-	conf_reg_t reg;
+ 	int err;
+ 
+ 	if (bus->bustype != SSB_BUSTYPE_PCMCIA)
+@@ -264,24 +814,45 @@ int ssb_pcmcia_init(struct ssb_bus *bus)
+ 	/* Switch segment to a known state and sync
+ 	 * bus->mapped_pcmcia_seg with hardware state. */
+ 	ssb_pcmcia_switch_segment(bus, 0);
++	/* Init the COR register. */
++	err = ssb_pcmcia_cor_setup(bus, CISREG_COR);
++	if (err)
++		return err;
++	/* Some cards also need this register to get poked. */
++	err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);
++	if (err)
++		return err;
+ 
+-	/* Init IRQ routing */
+-	reg.Action = CS_READ;
+-	reg.Function = 0;
+-	if (bus->chip_id == 0x4306)
+-		reg.Offset = 0x00;
+-	else
+-		reg.Offset = 0x80;
+-	err = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
+-	if (err != CS_SUCCESS)
++	return 0;
++}
++
++void ssb_pcmcia_exit(struct ssb_bus *bus)
++{
++	if (bus->bustype != SSB_BUSTYPE_PCMCIA)
++		return;
++
++	device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
++}
++
++int ssb_pcmcia_init(struct ssb_bus *bus)
++{
++	int err;
++
++	if (bus->bustype != SSB_BUSTYPE_PCMCIA)
++		return 0;
++
++	err = ssb_pcmcia_hardware_setup(bus);
++	if (err)
+ 		goto error;
+-	reg.Action = CS_WRITE;
+-	reg.Value |= 0x04 | 0x01;
+-	err = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
+-	if (err != CS_SUCCESS)
++
++	bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;
++	mutex_init(&bus->sprom_mutex);
++	err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
++	if (err)
+ 		goto error;
+ 
+ 	return 0;
+ error:
+-	return -ENODEV;
++	ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
++	return err;
+ }
+diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
+new file mode 100644
+index 0000000..3668edb
+--- /dev/null
++++ b/drivers/ssb/sprom.c
+@@ -0,0 +1,133 @@
++/*
++ * Sonics Silicon Backplane
++ * Common SPROM support routines
++ *
++ * Copyright (C) 2005-2008 Michael Buesch <mb at bu3sch.de>
++ * Copyright (C) 2005 Martin Langer <martin-langer at gmx.de>
++ * Copyright (C) 2005 Stefano Brivio <st3 at riseup.net>
++ * Copyright (C) 2005 Danny van Dyk <kugelfang at gentoo.org>
++ * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi at waterwave.ch>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include "ssb_private.h"
++
++
++static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
++		     size_t sprom_size_words)
++{
++	int i, pos = 0;
++
++	for (i = 0; i < sprom_size_words; i++)
++		pos += snprintf(buf + pos, buf_len - pos - 1,
++				"%04X", swab16(sprom[i]) & 0xFFFF);
++	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
++
++	return pos + 1;
++}
++
++static int hex2sprom(u16 *sprom, const char *dump, size_t len,
++		     size_t sprom_size_words)
++{
++	char tmp[5] = { 0 };
++	int cnt = 0;
++	unsigned long parsed;
++
++	if (len < sprom_size_words * 2)
++		return -EINVAL;
++
++	while (cnt < sprom_size_words) {
++		memcpy(tmp, dump, 4);
++		dump += 4;
++		parsed = simple_strtoul(tmp, NULL, 16);
++		sprom[cnt++] = swab16((u16)parsed);
++	}
++
++	return 0;
++}
++
++/* Common sprom device-attribute show-handler */
++ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf,
++			    int (*sprom_read)(struct ssb_bus *bus, u16 *sprom))
++{
++	u16 *sprom;
++	int err = -ENOMEM;
++	ssize_t count = 0;
++	size_t sprom_size_words = bus->sprom_size;
++
++	sprom = kcalloc(sprom_size_words, sizeof(u16), GFP_KERNEL);
++	if (!sprom)
++		goto out;
++
++	/* Use interruptible locking, as the SPROM write might
++	 * be holding the lock for several seconds. So allow userspace
++	 * to cancel operation. */
++	err = -ERESTARTSYS;
++	if (mutex_lock_interruptible(&bus->sprom_mutex))
++		goto out_kfree;
++	err = sprom_read(bus, sprom);
++	mutex_unlock(&bus->sprom_mutex);
++
++	if (!err)
++		count = sprom2hex(sprom, buf, PAGE_SIZE, sprom_size_words);
++
++out_kfree:
++	kfree(sprom);
++out:
++	return err ? err : count;
++}
++
++/* Common sprom device-attribute store-handler */
++ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
++			     const char *buf, size_t count,
++			     int (*sprom_check_crc)(const u16 *sprom, size_t size),
++			     int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom))
++{
++	u16 *sprom;
++	int res = 0, err = -ENOMEM;
++	size_t sprom_size_words = bus->sprom_size;
++
++	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
++	if (!sprom)
++		goto out;
++	err = hex2sprom(sprom, buf, count, sprom_size_words);
++	if (err) {
++		err = -EINVAL;
++		goto out_kfree;
++	}
++	err = sprom_check_crc(sprom, sprom_size_words);
++	if (err) {
++		err = -EINVAL;
++		goto out_kfree;
++	}
++
++	/* Use interruptible locking, as the SPROM write might
++	 * be holding the lock for several seconds. So allow userspace
++	 * to cancel operation. */
++	err = -ERESTARTSYS;
++	if (mutex_lock_interruptible(&bus->sprom_mutex))
++		goto out_kfree;
++	err = ssb_devices_freeze(bus);
++	if (err == -EOPNOTSUPP) {
++		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
++			   "No suspend support. Is CONFIG_PM enabled?\n");
++		goto out_unlock;
++	}
++	if (err) {
++		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
++		goto out_unlock;
++	}
++	res = sprom_write(bus, sprom);
++	err = ssb_devices_thaw(bus);
++	if (err)
++		ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
++out_unlock:
++	mutex_unlock(&bus->sprom_mutex);
++out_kfree:
++	kfree(sprom);
++out:
++	if (res)
++		return res;
++	return err ? err : count;
++}
+diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
+index 21eca2b..ebc32d8 100644
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -81,6 +81,8 @@ extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
+ 				     u8 seg);
+ extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
+ 				     struct ssb_init_invariants *iv);
++extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
++extern void ssb_pcmcia_exit(struct ssb_bus *bus);
+ extern int ssb_pcmcia_init(struct ssb_bus *bus);
+ extern const struct ssb_bus_ops ssb_pcmcia_ops;
+ #else /* CONFIG_SSB_PCMCIAHOST */
+@@ -99,6 +101,13 @@ static inline int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
+ {
+ 	return 0;
+ }
++static inline int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
++{
++	return 0;
++}
++static inline void ssb_pcmcia_exit(struct ssb_bus *bus)
++{
++}
+ static inline int ssb_pcmcia_init(struct ssb_bus *bus)
+ {
+ 	return 0;
+@@ -113,11 +122,26 @@ extern int ssb_bus_scan(struct ssb_bus *bus,
+ extern void ssb_iounmap(struct ssb_bus *ssb);
+ 
+ 
++/* sprom.c */
++extern
++ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf,
++			    int (*sprom_read)(struct ssb_bus *bus, u16 *sprom));
++extern
++ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
++			     const char *buf, size_t count,
++			     int (*sprom_check_crc)(const u16 *sprom, size_t size),
++			     int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom));
++
++
+ /* core.c */
+ extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m);
+ extern int ssb_devices_freeze(struct ssb_bus *bus);
+ extern int ssb_devices_thaw(struct ssb_bus *bus);
+ extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev);
++int ssb_for_each_bus_call(unsigned long data,
++			  int (*func)(struct ssb_bus *bus, unsigned long data));
++extern struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev);
++
+ 
+ /* b43_pci_bridge.c */
+ #ifdef CONFIG_SSB_B43_PCI_BRIDGE
+diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
+index b778ed7..a4aaab9 100644
+--- a/drivers/uio/Kconfig
++++ b/drivers/uio/Kconfig
+@@ -1,8 +1,6 @@
+-menu "Userspace I/O"
+-	depends on !S390
+-
+-config UIO
++menuconfig UIO
+ 	tristate "Userspace I/O drivers"
++	depends on !S390
+ 	default n
+ 	help
+ 	  Enable this to allow the userspace driver core code to be
+@@ -13,6 +11,8 @@ config UIO
+ 
+ 	  If you don't know what to do here, say N.
+ 
++if UIO
++
+ config UIO_CIF
+ 	tristate "generic Hilscher CIF Card driver"
+ 	depends on UIO && PCI
+@@ -26,4 +26,17 @@ config UIO_CIF
+ 	  To compile this driver as a module, choose M here: the module
+ 	  will be called uio_cif.
+ 
+-endmenu
++config UIO_SMX
++	tristate "SMX cryptengine UIO interface"
++	depends on UIO
++	default n
++	help
++	  Userspace IO interface to the Cryptography engine found on the
++	  Nias Digital SMX boards.  These will be available from Q4 2008
++	  from http://www.niasdigital.com.  The userspace part of this
++	  driver will be released under the GPL at the same time as the
++	  hardware and will be able to be downloaded from the same site.
++
++	  If you compile this as a module, it will be called uio_smx.
++
++endif
+diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
+index 7fecfb4..18c4566 100644
+--- a/drivers/uio/Makefile
++++ b/drivers/uio/Makefile
+@@ -1,2 +1,3 @@
+ obj-$(CONFIG_UIO)	+= uio.o
+ obj-$(CONFIG_UIO_CIF)	+= uio_cif.o
++obj-$(CONFIG_UIO_SMX)	+= uio_smx.o
+diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
+index 1175908..55cc7b8 100644
+--- a/drivers/uio/uio.c
++++ b/drivers/uio/uio.c
+@@ -301,23 +301,33 @@ static int uio_open(struct inode *inode, struct file *filep)
+ 	if (!idev)
+ 		return -ENODEV;
+ 
++	if (!try_module_get(idev->owner))
++		return -ENODEV;
++
+ 	listener = kmalloc(sizeof(*listener), GFP_KERNEL);
+-	if (!listener)
+-		return -ENOMEM;
++	if (!listener) {
++		ret = -ENOMEM;
++		goto err_alloc_listener;
++	}
+ 
+ 	listener->dev = idev;
+ 	listener->event_count = atomic_read(&idev->event);
+ 	filep->private_data = listener;
+ 
+ 	if (idev->info->open) {
+-		if (!try_module_get(idev->owner))
+-			return -ENODEV;
+ 		ret = idev->info->open(idev->info, inode);
+-		module_put(idev->owner);
++		if (ret)
++			goto err_infoopen;
+ 	}
+ 
+-	if (ret)
+-		kfree(listener);
++	return 0;
++
++err_infoopen:
++
++	kfree(listener);
++err_alloc_listener:
++
++	module_put(idev->owner);
+ 
+ 	return ret;
+ }
+@@ -336,12 +346,11 @@ static int uio_release(struct inode *inode, struct file *filep)
+ 	struct uio_listener *listener = filep->private_data;
+ 	struct uio_device *idev = listener->dev;
+ 
+-	if (idev->info->release) {
+-		if (!try_module_get(idev->owner))
+-			return -ENODEV;
++	if (idev->info->release)
+ 		ret = idev->info->release(idev->info, inode);
+-		module_put(idev->owner);
+-	}
++
++	module_put(idev->owner);
++
+ 	if (filep->f_flags & FASYNC)
+ 		ret = uio_fasync(-1, filep, 0);
+ 	kfree(listener);
+@@ -510,10 +519,7 @@ static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
+ 		return -EINVAL;
+ 
+ 	if (idev->info->mmap) {
+-		if (!try_module_get(idev->owner))
+-			return -ENODEV;
+ 		ret = idev->info->mmap(idev->info, vma);
+-		module_put(idev->owner);
+ 		return ret;
+ 	}
+ 
+diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
+index 838bae4..5737606 100644
+--- a/drivers/uio/uio_cif.c
++++ b/drivers/uio/uio_cif.c
+@@ -15,10 +15,6 @@
+ 
+ #include <asm/io.h>
+ 
+-#ifndef PCI_DEVICE_ID_PLX_9030
+-#define PCI_DEVICE_ID_PLX_9030	0x9030
+-#endif
+-
+ #define PLX9030_INTCSR		0x4C
+ #define INTSCR_INT1_ENABLE	0x01
+ #define INTSCR_INT1_STATUS	0x04
+@@ -116,7 +112,7 @@ static void hilscher_pci_remove(struct pci_dev *dev)
+ 	kfree (info);
+ }
+ 
+-static struct pci_device_id hilscher_pci_ids[] = {
++static struct pci_device_id hilscher_pci_ids[] __devinitdata = {
+ 	{
+ 		.vendor =	PCI_VENDOR_ID_PLX,
+ 		.device =	PCI_DEVICE_ID_PLX_9030,
+diff --git a/drivers/uio/uio_smx.c b/drivers/uio/uio_smx.c
+new file mode 100644
+index 0000000..44054a6
+--- /dev/null
++++ b/drivers/uio/uio_smx.c
+@@ -0,0 +1,140 @@
++/*
++ * UIO SMX Cryptengine driver.
++ *
++ * (C) 2008 Nias Digital P/L <bn at niasdigital.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/uio_driver.h>
++#include <linux/io.h>
++
++#define DRV_NAME "smx-ce"
++#define DRV_VERSION "0.03"
++
++#define SMX_CSR  0x00000000
++#define SMX_EnD  0x00000001
++#define SMX_RUN  0x00000002
++#define SMX_DRDY 0x00000004
++#define SMX_ERR  0x00000008
++
++static irqreturn_t smx_handler(int irq, struct uio_info *dev_info)
++{
++	void __iomem *csr = dev_info->mem[0].internal_addr + SMX_CSR;
++
++	u32 status = ioread32(csr);
++
++	if (!(status & SMX_DRDY))
++		return IRQ_NONE;
++
++	/* Disable interrupt */
++	iowrite32(status & ~SMX_DRDY, csr);
++	return IRQ_HANDLED;
++}
++
++static int __devinit smx_ce_probe(struct platform_device *dev)
++{
++
++	int ret = -ENODEV;
++	struct uio_info *info;
++	struct resource *regs;
++
++	info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
++	if (!info)
++		return -ENOMEM;
++
++	regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
++	if (!regs) {
++		dev_err(&dev->dev, "No memory resource specified\n");
++		goto out_free;
++	}
++
++	info->mem[0].addr = regs->start;
++	if (!info->mem[0].addr) {
++		dev_err(&dev->dev, "Invalid memory resource\n");
++		goto out_free;
++	}
++
++	info->mem[0].size = regs->end - regs->start + 1;
++	info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size);
++
++	if (!info->mem[0].internal_addr) {
++		dev_err(&dev->dev, "Can't remap memory address range\n");
++		goto out_free;
++	}
++
++	info->mem[0].memtype = UIO_MEM_PHYS;
++
++	info->name = "smx-ce";
++	info->version = "0.03";
++
++	info->irq = platform_get_irq(dev, 0);
++	if (info->irq < 0) {
++		ret = info->irq;
++		dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n");
++		goto out_unmap;
++	}
++
++	info->irq_flags = IRQF_SHARED;
++	info->handler = smx_handler;
++
++	platform_set_drvdata(dev, info);
++
++	ret = uio_register_device(&dev->dev, info);
++
++	if (ret)
++		goto out_unmap;
++
++	return 0;
++
++out_unmap:
++	iounmap(info->mem[0].internal_addr);
++out_free:
++	kfree(info);
++
++	return ret;
++}
++
++static int __devexit smx_ce_remove(struct platform_device *dev)
++{
++	struct uio_info *info = platform_get_drvdata(dev);
++
++	uio_unregister_device(info);
++	platform_set_drvdata(dev, NULL);
++	iounmap(info->mem[0].internal_addr);
++
++	kfree(info);
++
++	return 0;
++}
++
++static struct platform_driver smx_ce_driver = {
++	.probe		= smx_ce_probe,
++	.remove		= __devexit_p(smx_ce_remove),
++	.driver		= {
++		.name	= DRV_NAME,
++		.owner	= THIS_MODULE,
++	},
++};
++
++static int __init smx_ce_init_module(void)
++{
++	return platform_driver_register(&smx_ce_driver);
++}
++module_init(smx_ce_init_module);
++
++static void __exit smx_ce_exit_module(void)
++{
++	platform_driver_unregister(&smx_ce_driver);
++}
++module_exit(smx_ce_exit_module);
++
++MODULE_LICENSE("GPL v2");
++MODULE_VERSION(DRV_VERSION);
++MODULE_AUTHOR("Ben Nizette <bn at niasdigital.com>");
+diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
+index a51eeed..d470c72 100644
+--- a/drivers/usb/atm/cxacru.c
++++ b/drivers/usb/atm/cxacru.c
+@@ -444,7 +444,7 @@ CXACRU_ALL_FILES(INIT);
+ /* the following three functions are stolen from drivers/usb/core/message.c */
+ static void cxacru_blocking_completion(struct urb *urb)
+ {
+-	complete((struct completion *)urb->context);
++	complete(urb->context);
+ }
+ 
+ static void cxacru_timeout_kill(unsigned long data)
+diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
+index c5ec1a5..abb7d74 100644
+--- a/drivers/usb/atm/ueagle-atm.c
++++ b/drivers/usb/atm/ueagle-atm.c
+@@ -83,7 +83,7 @@
+ 		if (debug >= 1) \
+ 			dev_dbg(&(usb_dev)->dev, \
+ 				"[ueagle-atm dbg] %s: " format, \
+-					__FUNCTION__, ##args); \
++					__func__, ##args); \
+ 	} while (0)
+ 
+ #define uea_vdbg(usb_dev, format, args...)	\
+@@ -94,10 +94,10 @@
+ 	} while (0)
+ 
+ #define uea_enters(usb_dev) \
+-	uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
++	uea_vdbg(usb_dev, "entering %s\n", __func__)
+ 
+ #define uea_leaves(usb_dev) \
+-	uea_vdbg(usb_dev, "leaving  %s\n", __FUNCTION__)
++	uea_vdbg(usb_dev, "leaving  %s\n", __func__)
+ 
+ #define uea_err(usb_dev, format,args...) \
+ 	dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
+diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
+index e717f5b..0722872 100644
+--- a/drivers/usb/atm/usbatm.c
++++ b/drivers/usb/atm/usbatm.c
+@@ -80,6 +80,7 @@
+ #include <linux/stat.h>
+ #include <linux/timer.h>
+ #include <linux/wait.h>
++#include <linux/kthread.h>
+ 
+ #ifdef VERBOSE_DEBUG
+ static int usbatm_print_packet(const unsigned char *data, int len);
+@@ -1014,10 +1015,7 @@ static int usbatm_do_heavy_init(void *arg)
+ 	struct usbatm_data *instance = arg;
+ 	int ret;
+ 
+-	daemonize(instance->driver->driver_name);
+ 	allow_signal(SIGTERM);
+-	instance->thread_pid = current->pid;
+-
+ 	complete(&instance->thread_started);
+ 
+ 	ret = instance->driver->heavy_init(instance, instance->usb_intf);
+@@ -1026,7 +1024,7 @@ static int usbatm_do_heavy_init(void *arg)
+ 		ret = usbatm_atm_init(instance);
+ 
+ 	mutex_lock(&instance->serialize);
+-	instance->thread_pid = -1;
++	instance->thread = NULL;
+ 	mutex_unlock(&instance->serialize);
+ 
+ 	complete_and_exit(&instance->thread_exited, ret);
+@@ -1034,13 +1032,18 @@ static int usbatm_do_heavy_init(void *arg)
+ 
+ static int usbatm_heavy_init(struct usbatm_data *instance)
+ {
+-	int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_FS | CLONE_FILES);
+-
+-	if (ret < 0) {
+-		usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
+-		return ret;
++	struct task_struct *t;
++
++	t = kthread_create(usbatm_do_heavy_init, instance,
++			instance->driver->driver_name);
++	if (IS_ERR(t)) {
++		usb_err(instance, "%s: failed to create kernel_thread (%ld)!\n",
++				__func__, PTR_ERR(t));
++		return PTR_ERR(t);
+ 	}
+ 
++	instance->thread = t;
++	wake_up_process(t);
+ 	wait_for_completion(&instance->thread_started);
+ 
+ 	return 0;
+@@ -1124,7 +1127,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
+ 	kref_init(&instance->refcount);		/* dropped in usbatm_usb_disconnect */
+ 	mutex_init(&instance->serialize);
+ 
+-	instance->thread_pid = -1;
++	instance->thread = NULL;
+ 	init_completion(&instance->thread_started);
+ 	init_completion(&instance->thread_exited);
+ 
+@@ -1287,8 +1290,8 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
+ 
+ 	mutex_lock(&instance->serialize);
+ 	instance->disconnected = 1;
+-	if (instance->thread_pid >= 0)
+-		kill_proc(instance->thread_pid, SIGTERM, 1);
++	if (instance->thread != NULL)
++		send_sig(SIGTERM, instance->thread, 1);
+ 	mutex_unlock(&instance->serialize);
+ 
+ 	wait_for_completion(&instance->thread_exited);
+diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
+index ff8551e..e6887c6 100644
+--- a/drivers/usb/atm/usbatm.h
++++ b/drivers/usb/atm/usbatm.h
+@@ -24,7 +24,6 @@
+ #ifndef	_USBATM_H_
+ #define	_USBATM_H_
+ 
+-#include <asm/semaphore.h>
+ #include <linux/atm.h>
+ #include <linux/atmdev.h>
+ #include <linux/completion.h>
+@@ -176,7 +175,7 @@ struct usbatm_data {
+ 	int disconnected;
+ 
+ 	/* heavy init */
+-	int thread_pid;
++	struct task_struct *thread;
+ 	struct completion thread_started;
+ 	struct completion thread_exited;
+ 
+diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
+index 0147ea3..7b572e7 100644
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -31,6 +31,7 @@
+  *	v0.23 - use softirq for rx processing, as needed by tty layer
+  *	v0.24 - change probe method to evaluate CDC union descriptor
+  *	v0.25 - downstream tasks paralelized to maximize throughput
++ *	v0.26 - multiple write urbs, writesize increased
+  */
+ 
+ /*
+@@ -72,7 +73,7 @@
+ /*
+  * Version Information
+  */
+-#define DRIVER_VERSION "v0.25"
++#define DRIVER_VERSION "v0.26"
+ #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek"
+ #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
+ 
+@@ -118,7 +119,7 @@ static int acm_wb_alloc(struct acm *acm)
+ 	int i, wbn;
+ 	struct acm_wb *wb;
+ 
+-	wbn = acm->write_current;
++	wbn = 0;
+ 	i = 0;
+ 	for (;;) {
+ 		wb = &acm->wb[wbn];
+@@ -132,11 +133,6 @@ static int acm_wb_alloc(struct acm *acm)
+ 	}
+ }
+ 
+-static void acm_wb_free(struct acm *acm, int wbn)
+-{
+-	acm->wb[wbn].use = 0;
+-}
+-
+ static int acm_wb_is_avail(struct acm *acm)
+ {
+ 	int i, n;
+@@ -156,26 +152,22 @@ static inline int acm_wb_is_used(struct acm *acm, int wbn)
+ /*
+  * Finish write.
+  */
+-static void acm_write_done(struct acm *acm)
++static void acm_write_done(struct acm *acm, struct acm_wb *wb)
+ {
+ 	unsigned long flags;
+-	int wbn;
+ 
+ 	spin_lock_irqsave(&acm->write_lock, flags);
+ 	acm->write_ready = 1;
+-	wbn = acm->write_current;
+-	acm_wb_free(acm, wbn);
+-	acm->write_current = (wbn + 1) % ACM_NW;
++	wb->use = 0;
+ 	spin_unlock_irqrestore(&acm->write_lock, flags);
+ }
+ 
+ /*
+  * Poke write.
+  */
+-static int acm_write_start(struct acm *acm)
++static int acm_write_start(struct acm *acm, int wbn)
+ {
+ 	unsigned long flags;
+-	int wbn;
+ 	struct acm_wb *wb;
+ 	int rc;
+ 
+@@ -190,24 +182,24 @@ static int acm_write_start(struct acm *acm)
+ 		return 0;	/* A white lie */
+ 	}
+ 
+-	wbn = acm->write_current;
+ 	if (!acm_wb_is_used(acm, wbn)) {
+ 		spin_unlock_irqrestore(&acm->write_lock, flags);
+ 		return 0;
+ 	}
+ 	wb = &acm->wb[wbn];
+ 
+-	acm->write_ready = 0;
++	if(acm_wb_is_avail(acm) <= 1)
++		acm->write_ready = 0;
+ 	spin_unlock_irqrestore(&acm->write_lock, flags);
+ 
+-	acm->writeurb->transfer_buffer = wb->buf;
+-	acm->writeurb->transfer_dma = wb->dmah;
+-	acm->writeurb->transfer_buffer_length = wb->len;
+-	acm->writeurb->dev = acm->dev;
++	wb->urb->transfer_buffer = wb->buf;
++	wb->urb->transfer_dma = wb->dmah;
++	wb->urb->transfer_buffer_length = wb->len;
++	wb->urb->dev = acm->dev;
+ 
+-	if ((rc = usb_submit_urb(acm->writeurb, GFP_ATOMIC)) < 0) {
++	if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
+ 		dbg("usb_submit_urb(write bulk) failed: %d", rc);
+-		acm_write_done(acm);
++		acm_write_done(acm, wb);
+ 	}
+ 	return rc;
+ }
+@@ -268,10 +260,10 @@ static void acm_ctrl_irq(struct urb *urb)
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, status);
++		dbg("%s - urb shutting down with status: %d", __func__, status);
+ 		return;
+ 	default:
+-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, status);
++		dbg("%s - nonzero urb status received: %d", __func__, status);
+ 		goto exit;
+ 	}
+ 
+@@ -315,7 +307,7 @@ exit:
+ 	retval = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (retval)
+ 		err ("%s - usb_submit_urb failed with result %d",
+-		     __FUNCTION__, retval);
++		     __func__, retval);
+ }
+ 
+ /* data interface returns incoming bytes, or we got unthrottled */
+@@ -450,12 +442,13 @@ urbs:
+ /* data interface wrote those outgoing bytes */
+ static void acm_write_bulk(struct urb *urb)
+ {
+-	struct acm *acm = (struct acm *)urb->context;
++	struct acm *acm;
++	struct acm_wb *wb = urb->context;
+ 
+ 	dbg("Entering acm_write_bulk with status %d", urb->status);
+ 
+-	acm_write_done(acm);
+-	acm_write_start(acm);
++	acm = wb->instance;
++	acm_write_done(acm, wb);
+ 	if (ACM_READY(acm))
+ 		schedule_work(&acm->work);
+ }
+@@ -489,6 +482,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
+ 	else
+ 		rv = 0;
+ 
++	set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
+ 	tty->driver_data = acm;
+ 	acm->tty = tty;
+ 
+@@ -556,7 +550,8 @@ static void acm_tty_unregister(struct acm *acm)
+ 	usb_put_intf(acm->control);
+ 	acm_table[acm->minor] = NULL;
+ 	usb_free_urb(acm->ctrlurb);
+-	usb_free_urb(acm->writeurb);
++	for (i = 0; i < ACM_NW; i++)
++		usb_free_urb(acm->wb[i].urb);
+ 	for (i = 0; i < nr; i++)
+ 		usb_free_urb(acm->ru[i].urb);
+ 	kfree(acm->country_codes);
+@@ -577,7 +572,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
+ 		if (acm->dev) {
+ 			acm_set_control(acm, acm->ctrlout = 0);
+ 			usb_kill_urb(acm->ctrlurb);
+-			usb_kill_urb(acm->writeurb);
++			for (i = 0; i < ACM_NW; i++)
++				usb_kill_urb(acm->wb[i].urb);
+ 			for (i = 0; i < nr; i++)
+ 				usb_kill_urb(acm->ru[i].urb);
+ 			usb_autopm_put_interface(acm->control);
+@@ -605,7 +601,6 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
+ 	spin_lock_irqsave(&acm->write_lock, flags);
+ 	if ((wbn = acm_wb_alloc(acm)) < 0) {
+ 		spin_unlock_irqrestore(&acm->write_lock, flags);
+-		acm_write_start(acm);
+ 		return 0;
+ 	}
+ 	wb = &acm->wb[wbn];
+@@ -616,7 +611,7 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
+ 	wb->len = count;
+ 	spin_unlock_irqrestore(&acm->write_lock, flags);
+ 
+-	if ((stat = acm_write_start(acm)) < 0)
++	if ((stat = acm_write_start(acm, wbn)) < 0)
+ 		return stat;
+ 	return count;
+ }
+@@ -809,7 +804,7 @@ static int acm_probe (struct usb_interface *intf,
+ {
+ 	struct usb_cdc_union_desc *union_header = NULL;
+ 	struct usb_cdc_country_functional_desc *cfd = NULL;
+-	char *buffer = intf->altsetting->extra;
++	unsigned char *buffer = intf->altsetting->extra;
+ 	int buflen = intf->altsetting->extralen;
+ 	struct usb_interface *control_interface;
+ 	struct usb_interface *data_interface;
+@@ -886,9 +881,13 @@ static int acm_probe (struct usb_interface *intf,
+ 				if ((call_management_function & 3) != 3)
+ 					err("This device cannot do calls on its own. It is no modem.");
+ 				break;
+-				
+ 			default:
+-				err("Ignoring extra header, type %d, length %d", buffer[2], buffer[0]);
++				/* there are LOTS more CDC descriptors that
++				 * could legitimately be found here.
++				 */
++				dev_dbg(&intf->dev, "Ignoring descriptor: "
++						"type %02x, length %d\n",
++						buffer[2], buffer[0]);
+ 				break;
+ 			}
+ next_desc:
+@@ -976,7 +975,7 @@ skip_normal_probe:
+ 
+ 	ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
+ 	readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2);
+-	acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
++	acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20;
+ 	acm->control = control_interface;
+ 	acm->data = data_interface;
+ 	acm->minor = minor;
+@@ -1031,10 +1030,19 @@ skip_normal_probe:
+ 			goto alloc_fail7;
+ 		}
+ 	}
+-	acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
+-	if (!acm->writeurb) {
+-		dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
+-		goto alloc_fail7;
++	for(i = 0; i < ACM_NW; i++)
++	{
++		struct acm_wb *snd = &(acm->wb[i]);
++
++		if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) {
++			dev_dbg(&intf->dev, "out of memory (write urbs usb_alloc_urb)");
++			goto alloc_fail7;
++		}
++
++		usb_fill_bulk_urb(snd->urb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
++				NULL, acm->writesize, acm_write_bulk, snd);
++		snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
++		snd->instance = acm;
+ 	}
+ 
+ 	usb_set_intfdata (intf, acm);
+@@ -1070,10 +1078,6 @@ skip_countries:
+ 	acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ 	acm->ctrlurb->transfer_dma = acm->ctrl_dma;
+ 
+-	usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+-			  NULL, acm->writesize, acm_write_bulk, acm);
+-	acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
+-
+ 	dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
+ 
+ 	acm_set_control(acm, acm->ctrlout);
+@@ -1091,7 +1095,8 @@ skip_countries:
+ 
+ 	return 0;
+ alloc_fail8:
+-	usb_free_urb(acm->writeurb);
++	for (i = 0; i < ACM_NW; i++)
++		usb_free_urb(acm->wb[i].urb);
+ alloc_fail7:
+ 	for (i = 0; i < num_rx_buf; i++)
+ 		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+@@ -1115,7 +1120,8 @@ static void stop_data_traffic(struct acm *acm)
+ 	tasklet_disable(&acm->urb_task);
+ 
+ 	usb_kill_urb(acm->ctrlurb);
+-	usb_kill_urb(acm->writeurb);
++	for(i = 0; i < ACM_NW; i++)
++		usb_kill_urb(acm->wb[i].urb);
+ 	for (i = 0; i < acm->rx_buflimit; i++)
+ 		usb_kill_urb(acm->ru[i].urb);
+ 
+diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
+index 8df6a57..046e064 100644
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -59,7 +59,7 @@
+  * when processing onlcr, so we only need 2 buffers. These values must be
+  * powers of 2.
+  */
+-#define ACM_NW  2
++#define ACM_NW  16
+ #define ACM_NR  16
+ 
+ struct acm_wb {
+@@ -67,6 +67,8 @@ struct acm_wb {
+ 	dma_addr_t dmah;
+ 	int len;
+ 	int use;
++	struct urb		*urb;
++	struct acm		*instance;
+ };
+ 
+ struct acm_rb {
+@@ -88,7 +90,7 @@ struct acm {
+ 	struct usb_interface *control;			/* control interface */
+ 	struct usb_interface *data;			/* data interface */
+ 	struct tty_struct *tty;				/* the corresponding tty */
+-	struct urb *ctrlurb, *writeurb;			/* urbs */
++	struct urb *ctrlurb;			/* urbs */
+ 	u8 *ctrl_buffer;				/* buffers of urbs */
+ 	dma_addr_t ctrl_dma;				/* dma handles of buffers */
+ 	u8 *country_codes;				/* country codes from device */
+@@ -103,7 +105,6 @@ struct acm {
+ 	struct list_head spare_read_urbs;
+ 	struct list_head spare_read_bufs;
+ 	struct list_head filled_read_bufs;
+-	int write_current;				/* current write buffer */
+ 	int write_used;					/* number of non-empty write buffers */
+ 	int write_ready;				/* write urb is not running */
+ 	spinlock_t write_lock;
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index a2b0aa4..cc9f397 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -76,8 +76,8 @@ config USB_DEVICE_CLASS
+ 	    NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644"
+ 
+ config USB_DYNAMIC_MINORS
+-	bool "Dynamic USB minor allocation (EXPERIMENTAL)"
+-	depends on USB && EXPERIMENTAL
++	bool "Dynamic USB minor allocation"
++	depends on USB
+ 	help
+ 	  If you say Y here, the USB subsystem will use dynamic minor
+ 	  allocation for any device that uses the USB major number.
+@@ -102,31 +102,6 @@ config USB_SUSPEND
+ 
+ 	  If you are unsure about this, say N here.
+ 
+-config USB_PERSIST
+-	bool "USB device persistence during system suspend (DANGEROUS)"
+-	depends on USB && PM && EXPERIMENTAL
+-	default n
+-	help
+-
+-	  If you say Y here and enable the "power/persist" attribute
+-	  for a USB device, the device's data structures will remain
+-	  persistent across system suspend, even if the USB bus loses
+-	  power.  (This includes hibernation, also known as swsusp or
+-	  suspend-to-disk.)  The devices will reappear as if by magic
+-	  when the system wakes up, with no need to unmount USB
+-	  filesystems, rmmod host-controller drivers, or do anything
+-	  else.
+-
+-	  	WARNING: This option can be dangerous!
+-
+-	  If a USB device is replaced by another of the same type while
+-	  the system is asleep, there's a good chance the kernel won't
+-	  detect the change.  Likewise if the media in a USB storage
+-	  device is replaced.  When this happens it's almost certain to
+-	  cause data corruption and maybe even crash your system.
+-
+-	  If you are unsure, say N here.
+-
+ config USB_OTG
+ 	bool
+ 	depends on USB && EXPERIMENTAL
+@@ -136,14 +111,16 @@ config USB_OTG
+ 
+ config USB_OTG_WHITELIST
+ 	bool "Rely on OTG Targeted Peripherals List"
+-	depends on USB_OTG
+-	default y
++	depends on USB_OTG || EMBEDDED
++	default y if USB_OTG
++	default n if EMBEDDED
+ 	help
+ 	  If you say Y here, the "otg_whitelist.h" file will be used as a
+ 	  product whitelist, so USB peripherals not listed there will be
+ 	  rejected during enumeration.  This behavior is required by the
+ 	  USB OTG specification for all devices not on your product's
+-	  "Targeted Peripherals List".
++	  "Targeted Peripherals List".  "Embedded Hosts" are likewise
++	  allowed to support only a limited number of peripherals.
+ 
+ 	  Otherwise, peripherals not listed there will only generate a
+ 	  warning and enumeration will continue.  That's more like what
+@@ -152,9 +129,10 @@ config USB_OTG_WHITELIST
+ 
+ config USB_OTG_BLACKLIST_HUB
+ 	bool "Disable external hubs"
+-	depends on USB_OTG
++	depends on USB_OTG || EMBEDDED
+ 	help
+ 	  If you say Y here, then Linux will refuse to enumerate
+ 	  external hubs.  OTG hosts are allowed to reduce hardware
+-	  and software costs by not supporting external hubs.
++	  and software costs by not supporting external hubs.  So
++	  are "Emedded Hosts" that don't offer OTG support.
+ 
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index a92122a..568244c 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -145,6 +145,23 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ 			endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
+ 	}
+ 
++	/*
++	 * Some buggy high speed devices have bulk endpoints using
++	 * maxpacket sizes other than 512.  High speed HCDs may not
++	 * be able to handle that particular bug, so let's warn...
++	 */
++	if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
++			&& usb_endpoint_xfer_bulk(d)) {
++		unsigned maxp;
++
++		maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff;
++		if (maxp != 512)
++			dev_warn(ddev, "config %d interface %d altsetting %d "
++				"bulk endpoint 0x%X has invalid maxpacket %d\n",
++				cfgno, inum, asnum, d->bEndpointAddress,
++				maxp);
++	}
++
+ 	/* Skip over any Class Specific or Vendor Specific descriptors;
+ 	 * find the next endpoint or interface descriptor */
+ 	endpoint->extra = buffer;
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index ae94176..de17738 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -647,6 +647,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 	struct usbdevfs_ctrltransfer ctrl;
+ 	unsigned int tmo;
+ 	unsigned char *tbuf;
++	unsigned wLength;
+ 	int i, j, ret;
+ 
+ 	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+@@ -654,7 +655,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ 	ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex);
+ 	if (ret)
+ 		return ret;
+-	if (ctrl.wLength > PAGE_SIZE)
++	wLength = ctrl.wLength;		/* To suppress 64k PAGE_SIZE warning */
++	if (wLength > PAGE_SIZE)
+ 		return -EINVAL;
+ 	tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+ 	if (!tbuf)
+@@ -946,8 +948,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	int ret, ifnum = -1;
+ 	int is_in;
+ 
+-	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
+-			   URB_NO_FSBR|URB_ZERO_PACKET))
++	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
++				USBDEVFS_URB_SHORT_NOT_OK |
++				USBDEVFS_URB_NO_FSBR |
++				USBDEVFS_URB_ZERO_PACKET |
++				USBDEVFS_URB_NO_INTERRUPT))
+ 		return -EINVAL;
+ 	if (!uurb->buffer)
+ 		return -EINVAL;
+@@ -1102,8 +1107,24 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ 	as->urb->pipe = (uurb->type << 30) |
+ 			__create_pipe(ps->dev, uurb->endpoint & 0xf) |
+ 			(uurb->endpoint & USB_DIR_IN);
+-	as->urb->transfer_flags = uurb->flags |
+-			(is_in ? URB_DIR_IN : URB_DIR_OUT);
++
++	/* This tedious sequence is necessary because the URB_* flags
++	 * are internal to the kernel and subject to change, whereas
++	 * the USBDEVFS_URB_* flags are a user API and must not be changed.
++	 */
++	u = (is_in ? URB_DIR_IN : URB_DIR_OUT);
++	if (uurb->flags & USBDEVFS_URB_ISO_ASAP)
++		u |= URB_ISO_ASAP;
++	if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
++		u |= URB_SHORT_NOT_OK;
++	if (uurb->flags & USBDEVFS_URB_NO_FSBR)
++		u |= URB_NO_FSBR;
++	if (uurb->flags & USBDEVFS_URB_ZERO_PACKET)
++		u |= URB_ZERO_PACKET;
++	if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT)
++		u |= URB_NO_INTERRUPT;
++	as->urb->transfer_flags = u;
++
+ 	as->urb->transfer_buffer_length = uurb->buffer_length;
+ 	as->urb->setup_packet = (unsigned char *)dr;
+ 	as->urb->start_frame = uurb->start_frame;
+@@ -1509,60 +1530,60 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
+ 
+ 	switch (cmd) {
+ 	case USBDEVFS_CONTROL:
+-		snoop(&dev->dev, "%s: CONTROL\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: CONTROL\n", __func__);
+ 		ret = proc_control(ps, p);
+ 		if (ret >= 0)
+ 			inode->i_mtime = CURRENT_TIME;
+ 		break;
+ 
+ 	case USBDEVFS_BULK:
+-		snoop(&dev->dev, "%s: BULK\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: BULK\n", __func__);
+ 		ret = proc_bulk(ps, p);
+ 		if (ret >= 0)
+ 			inode->i_mtime = CURRENT_TIME;
+ 		break;
+ 
+ 	case USBDEVFS_RESETEP:
+-		snoop(&dev->dev, "%s: RESETEP\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: RESETEP\n", __func__);
+ 		ret = proc_resetep(ps, p);
+ 		if (ret >= 0)
+ 			inode->i_mtime = CURRENT_TIME;
+ 		break;
+ 
+ 	case USBDEVFS_RESET:
+-		snoop(&dev->dev, "%s: RESET\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: RESET\n", __func__);
+ 		ret = proc_resetdevice(ps);
+ 		break;
+ 
+ 	case USBDEVFS_CLEAR_HALT:
+-		snoop(&dev->dev, "%s: CLEAR_HALT\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__);
+ 		ret = proc_clearhalt(ps, p);
+ 		if (ret >= 0)
+ 			inode->i_mtime = CURRENT_TIME;
+ 		break;
+ 
+ 	case USBDEVFS_GETDRIVER:
+-		snoop(&dev->dev, "%s: GETDRIVER\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: GETDRIVER\n", __func__);
+ 		ret = proc_getdriver(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_CONNECTINFO:
+-		snoop(&dev->dev, "%s: CONNECTINFO\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: CONNECTINFO\n", __func__);
+ 		ret = proc_connectinfo(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_SETINTERFACE:
+-		snoop(&dev->dev, "%s: SETINTERFACE\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: SETINTERFACE\n", __func__);
+ 		ret = proc_setintf(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_SETCONFIGURATION:
+-		snoop(&dev->dev, "%s: SETCONFIGURATION\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: SETCONFIGURATION\n", __func__);
+ 		ret = proc_setconfig(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_SUBMITURB:
+-		snoop(&dev->dev, "%s: SUBMITURB\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: SUBMITURB\n", __func__);
+ 		ret = proc_submiturb(ps, p);
+ 		if (ret >= 0)
+ 			inode->i_mtime = CURRENT_TIME;
+@@ -1571,60 +1592,60 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
+ #ifdef CONFIG_COMPAT
+ 
+ 	case USBDEVFS_SUBMITURB32:
+-		snoop(&dev->dev, "%s: SUBMITURB32\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: SUBMITURB32\n", __func__);
+ 		ret = proc_submiturb_compat(ps, p);
+ 		if (ret >= 0)
+ 			inode->i_mtime = CURRENT_TIME;
+ 		break;
+ 
+ 	case USBDEVFS_REAPURB32:
+-		snoop(&dev->dev, "%s: REAPURB32\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: REAPURB32\n", __func__);
+ 		ret = proc_reapurb_compat(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_REAPURBNDELAY32:
+-		snoop(&dev->dev, "%s: REAPURBDELAY32\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__);
+ 		ret = proc_reapurbnonblock_compat(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_IOCTL32:
+-		snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: IOCTL\n", __func__);
+ 		ret = proc_ioctl_compat(ps, ptr_to_compat(p));
+ 		break;
+ #endif
+ 
+ 	case USBDEVFS_DISCARDURB:
+-		snoop(&dev->dev, "%s: DISCARDURB\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: DISCARDURB\n", __func__);
+ 		ret = proc_unlinkurb(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_REAPURB:
+-		snoop(&dev->dev, "%s: REAPURB\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: REAPURB\n", __func__);
+ 		ret = proc_reapurb(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_REAPURBNDELAY:
+-		snoop(&dev->dev, "%s: REAPURBDELAY\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: REAPURBDELAY\n", __func__);
+ 		ret = proc_reapurbnonblock(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_DISCSIGNAL:
+-		snoop(&dev->dev, "%s: DISCSIGNAL\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__);
+ 		ret = proc_disconnectsignal(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_CLAIMINTERFACE:
+-		snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __func__);
+ 		ret = proc_claiminterface(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_RELEASEINTERFACE:
+-		snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __func__);
+ 		ret = proc_releaseinterface(ps, p);
+ 		break;
+ 
+ 	case USBDEVFS_IOCTL:
+-		snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
++		snoop(&dev->dev, "%s: IOCTL\n", __func__);
+ 		ret = proc_ioctl_default(ps, p);
+ 		break;
+ 	}
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 801b6f1..1e56f1c 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -157,7 +157,7 @@ static int usb_probe_device(struct device *dev)
+ 	struct usb_device *udev;
+ 	int error = -ENODEV;
+ 
+-	dev_dbg(dev, "%s\n", __FUNCTION__);
++	dev_dbg(dev, "%s\n", __func__);
+ 
+ 	if (!is_usb_device(dev))	/* Sanity check */
+ 		return error;
+@@ -194,7 +194,7 @@ static int usb_probe_interface(struct device *dev)
+ 	const struct usb_device_id *id;
+ 	int error = -ENODEV;
+ 
+-	dev_dbg(dev, "%s\n", __FUNCTION__);
++	dev_dbg(dev, "%s\n", __func__);
+ 
+ 	if (is_usb_device(dev))		/* Sanity check */
+ 		return error;
+@@ -211,7 +211,7 @@ static int usb_probe_interface(struct device *dev)
+ 	if (!id)
+ 		id = usb_match_dynamic_id(intf, driver);
+ 	if (id) {
+-		dev_dbg(dev, "%s - got id\n", __FUNCTION__);
++		dev_dbg(dev, "%s - got id\n", __func__);
+ 
+ 		error = usb_autoresume_device(udev);
+ 		if (error)
+@@ -793,9 +793,7 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
+ 	status = udriver->suspend(udev, msg);
+ 
+  done:
+-	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+-	if (status == 0)
+-		udev->dev.power.power_state.event = msg.event;
++	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+ 	return status;
+ }
+ 
+@@ -823,11 +821,9 @@ static int usb_resume_device(struct usb_device *udev)
+ 	status = udriver->resume(udev);
+ 
+  done:
+-	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+-	if (status == 0) {
++	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
++	if (status == 0)
+ 		udev->autoresume_disabled = 0;
+-		udev->dev.power.power_state.event = PM_EVENT_ON;
+-	}
+ 	return status;
+ }
+ 
+@@ -864,7 +860,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ 	}
+ 
+  done:
+-	dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
++	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
+ 	return status;
+ }
+ 
+@@ -914,7 +910,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ 	}
+ 
+ done:
+-	dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
++	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
+ 	if (status == 0)
+ 		mark_active(intf);
+ 
+@@ -936,7 +932,6 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
+ 	 * is disabled.  Also fail if any interfaces require remote wakeup
+ 	 * but it isn't available.
+ 	 */
+-	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ 	if (udev->pm_usage_cnt > 0)
+ 		return -EBUSY;
+ 	if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
+@@ -1098,7 +1093,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ 	}
+ 
+  done:
+-	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
++	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+ 	return status;
+ }
+ 
+@@ -1180,8 +1175,7 @@ static int usb_resume_both(struct usb_device *udev)
+ 		}
+ 	} else {
+ 
+-		/* Needed for setting udev->dev.power.power_state.event,
+-		 * for possible debugging message, and for reset_resume. */
++		/* Needed for reset-resume */
+ 		status = usb_resume_device(udev);
+ 	}
+ 
+@@ -1193,8 +1187,9 @@ static int usb_resume_both(struct usb_device *udev)
+ 	}
+ 
+  done:
+-	dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+-	udev->reset_resume = 0;
++	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
++	if (!status)
++		udev->reset_resume = 0;
+ 	return status;
+ }
+ 
+@@ -1262,7 +1257,7 @@ void usb_autosuspend_device(struct usb_device *udev)
+ 
+ 	status = usb_autopm_do_device(udev, -1);
+ 	dev_vdbg(&udev->dev, "%s: cnt %d\n",
+-			__FUNCTION__, udev->pm_usage_cnt);
++			__func__, udev->pm_usage_cnt);
+ }
+ 
+ /**
+@@ -1282,7 +1277,7 @@ void usb_try_autosuspend_device(struct usb_device *udev)
+ {
+ 	usb_autopm_do_device(udev, 0);
+ 	dev_vdbg(&udev->dev, "%s: cnt %d\n",
+-			__FUNCTION__, udev->pm_usage_cnt);
++			__func__, udev->pm_usage_cnt);
+ }
+ 
+ /**
+@@ -1310,7 +1305,7 @@ int usb_autoresume_device(struct usb_device *udev)
+ 
+ 	status = usb_autopm_do_device(udev, 1);
+ 	dev_vdbg(&udev->dev, "%s: status %d cnt %d\n",
+-			__FUNCTION__, status, udev->pm_usage_cnt);
++			__func__, status, udev->pm_usage_cnt);
+ 	return status;
+ }
+ 
+@@ -1382,7 +1377,7 @@ void usb_autopm_put_interface(struct usb_interface *intf)
+ 
+ 	status = usb_autopm_do_interface(intf, -1);
+ 	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__FUNCTION__, status, intf->pm_usage_cnt);
++			__func__, status, intf->pm_usage_cnt);
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+ 
+@@ -1426,7 +1421,7 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+ 
+ 	status = usb_autopm_do_interface(intf, 1);
+ 	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__FUNCTION__, status, intf->pm_usage_cnt);
++			__func__, status, intf->pm_usage_cnt);
+ 	return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+@@ -1448,7 +1443,7 @@ int usb_autopm_set_interface(struct usb_interface *intf)
+ 
+ 	status = usb_autopm_do_interface(intf, 0);
+ 	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+-			__FUNCTION__, status, intf->pm_usage_cnt);
++			__func__, status, intf->pm_usage_cnt);
+ 	return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
+@@ -1523,9 +1518,14 @@ static int usb_suspend(struct device *dev, pm_message_t message)
+ 	udev = to_usb_device(dev);
+ 
+ 	/* If udev is already suspended, we can skip this suspend and
+-	 * we should also skip the upcoming system resume. */
++	 * we should also skip the upcoming system resume.  High-speed
++	 * root hubs are an exception; they need to resume whenever the
++	 * system wakes up in order for USB-PERSIST port handover to work
++	 * properly.
++	 */
+ 	if (udev->state == USB_STATE_SUSPENDED) {
+-		udev->skip_sys_resume = 1;
++		if (udev->parent || udev->speed != USB_SPEED_HIGH)
++			udev->skip_sys_resume = 1;
+ 		return 0;
+ 	}
+ 
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 84760dd..5b87ae7 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -73,7 +73,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	if (pci_enable_device(dev) < 0)
+ 		return -ENODEV;
+ 	dev->current_state = PCI_D0;
+-	dev->dev.power.power_state = PMSG_ON;
+ 
+ 	if (!dev->irq) {
+ 		dev_err(&dev->dev,
+@@ -216,9 +215,9 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ 			hcd->state == HC_STATE_HALT))
+ 		return -EBUSY;
+ 
+-	if (hcd->driver->suspend) {
+-		retval = hcd->driver->suspend(hcd, message);
+-		suspend_report_result(hcd->driver->suspend, retval);
++	if (hcd->driver->pci_suspend) {
++		retval = hcd->driver->pci_suspend(hcd, message);
++		suspend_report_result(hcd->driver->pci_suspend, retval);
+ 		if (retval)
+ 			goto done;
+ 	}
+@@ -302,8 +301,6 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ 
+ done:
+ 	if (retval == 0) {
+-		dev->dev.power.power_state = PMSG_SUSPEND;
+-
+ #ifdef CONFIG_PPC_PMAC
+ 		/* Disable ASIC clocks for USB */
+ 		if (machine_is(powermac)) {
+@@ -406,12 +403,10 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
+ 	pci_set_master(dev);
+ 	pci_restore_state(dev);
+ 
+-	dev->dev.power.power_state = PMSG_ON;
+-
+ 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ 
+-	if (hcd->driver->resume) {
+-		retval = hcd->driver->resume(hcd);
++	if (hcd->driver->pci_resume) {
++		retval = hcd->driver->pci_resume(hcd);
+ 		if (retval) {
+ 			dev_err(hcd->self.controller,
+ 				"PCI post-resume error %d!\n", retval);
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index e52ed16..bf10e9c 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -129,7 +129,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {
+ 
+ 	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
+ 	0x00,	    /*  __u8  bDeviceSubClass; */
+-	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
++	0x00,       /*  __u8  bDeviceProtocol; [ usb 2.0 no TT ] */
+ 	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
+ 
+ 	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
+@@ -291,7 +291,6 @@ static int ascii2utf (char *s, u8 *utf, int utfmax)
+  * rh_string - provides manufacturer, product and serial strings for root hub
+  * @id: the string ID number (1: serial number, 2: product, 3: vendor)
+  * @hcd: the host controller for this root hub
+- * @type: string describing our driver 
+  * @data: return packet in UTF-16 LE
+  * @len: length of the return packet
+  *
+@@ -355,9 +354,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 		__attribute__((aligned(4)));
+ 	const u8	*bufp = tbuf;
+ 	int		len = 0;
+-	int		patch_wakeup = 0;
+ 	int		status;
+ 	int		n;
++	u8		patch_wakeup = 0;
++	u8		patch_protocol = 0;
+ 
+ 	might_sleep();
+ 
+@@ -434,6 +434,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ 			else
+ 				goto error;
+ 			len = 18;
++			if (hcd->has_tt)
++				patch_protocol = 1;
+ 			break;
+ 		case USB_DT_CONFIG << 8:
+ 			if (hcd->driver->flags & HCD_USB2) {
+@@ -528,6 +530,13 @@ error:
+ 						bmAttributes))
+ 			((struct usb_config_descriptor *)ubuf)->bmAttributes
+ 				|= USB_CONFIG_ATT_WAKEUP;
++
++		/* report whether RH hardware has an integrated TT */
++		if (patch_protocol &&
++				len > offsetof(struct usb_device_descriptor,
++						bDeviceProtocol))
++			((struct usb_device_descriptor *) ubuf)->
++					bDeviceProtocol = 1;
+ 	}
+ 
+ 	/* any errors get returned through the urb completion */
+@@ -915,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd)
+ 	return retval;
+ }
+ 
+-void usb_enable_root_hub_irq (struct usb_bus *bus)
+-{
+-	struct usb_hcd *hcd;
+-
+-	hcd = container_of (bus, struct usb_hcd, self);
+-	if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
+-		hcd->driver->hub_irq_enable (hcd);
+-}
+-
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -1677,7 +1677,6 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
+  * usb_hcd_irq - hook IRQs to HCD framework (bus glue)
+  * @irq: the IRQ being raised
+  * @__hcd: pointer to the HCD whose IRQ is being signaled
+- * @r: saved hardware registers
+  *
+  * If the controller isn't HALTed, calls the driver's irq handler.
+  * Checks whether the controller is now dead.
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 2d1c3d5..1e4b81e 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -28,7 +28,7 @@
+ /*
+  * USB Packet IDs (PIDs)
+  */
+-#define USB_PID_UNDEF_0			0xf0
++#define USB_PID_EXT			0xf0	/* USB 2.0 LPM ECN */
+ #define USB_PID_OUT			0xe1
+ #define USB_PID_ACK			0xd2
+ #define USB_PID_DATA0			0xc3
+@@ -99,6 +99,7 @@ struct usb_hcd {
+ 	unsigned		poll_pending:1;	/* status has changed? */
+ 	unsigned		wireless:1;	/* Wireless USB HCD */
+ 	unsigned		authorized_default:1;
++	unsigned		has_tt:1;	/* Integrated TT in root hub */
+ 
+ 	int			irq;		/* irq allocated */
+ 	void __iomem		*regs;		/* device memory/io */
+@@ -177,10 +178,10 @@ struct hc_driver {
+ 	 * a whole, not just the root hub; they're for PCI bus glue.
+ 	 */
+ 	/* called after suspending the hub, before entering D3 etc */
+-	int	(*suspend) (struct usb_hcd *hcd, pm_message_t message);
++	int	(*pci_suspend) (struct usb_hcd *hcd, pm_message_t message);
+ 
+ 	/* called after entering D0 (etc), before resuming the hub */
+-	int	(*resume) (struct usb_hcd *hcd);
++	int	(*pci_resume) (struct usb_hcd *hcd);
+ 
+ 	/* cleanly make HCD stop writing memory and doing I/O */
+ 	void	(*stop) (struct usb_hcd *hcd);
+@@ -209,8 +210,6 @@ struct hc_driver {
+ 	int	(*bus_suspend)(struct usb_hcd *);
+ 	int	(*bus_resume)(struct usb_hcd *);
+ 	int	(*start_port_reset)(struct usb_hcd *, unsigned port_num);
+-	void	(*hub_irq_enable)(struct usb_hcd *);
+-		/* Needed only if port-change IRQs are level-triggered */
+ 
+ 		/* force handover of high-speed port to full-speed companion */
+ 	void	(*relinquish_port)(struct usb_hcd *, int);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 68fc521..eb57fcc 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -23,7 +23,6 @@
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+ 
+@@ -31,12 +30,6 @@
+ #include "hcd.h"
+ #include "hub.h"
+ 
+-#ifdef	CONFIG_USB_PERSIST
+-#define	USB_PERSIST	1
+-#else
+-#define	USB_PERSIST	0
+-#endif
+-
+ /* if we are in debug mode, always announce new devices */
+ #ifdef DEBUG
+ #ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
+@@ -334,6 +327,27 @@ static int get_port_status(struct usb_device *hdev, int port1,
+ 	return status;
+ }
+ 
++static int hub_port_status(struct usb_hub *hub, int port1,
++		u16 *status, u16 *change)
++{
++	int ret;
++
++	mutex_lock(&hub->status_mutex);
++	ret = get_port_status(hub->hdev, port1, &hub->status->port);
++	if (ret < 4) {
++		dev_err(hub->intfdev,
++			"%s failed (err = %d)\n", __func__, ret);
++		if (ret >= 0)
++			ret = -EIO;
++	} else {
++		*status = le16_to_cpu(hub->status->port.wPortStatus);
++		*change = le16_to_cpu(hub->status->port.wPortChange);
++		ret = 0;
++	}
++	mutex_unlock(&hub->status_mutex);
++	return ret;
++}
++
+ static void kick_khubd(struct usb_hub *hub)
+ {
+ 	unsigned long	flags;
+@@ -561,7 +575,7 @@ static int hub_hub_status(struct usb_hub *hub,
+ 	ret = get_hub_status(hub->hdev, &hub->status->hub);
+ 	if (ret < 0)
+ 		dev_err (hub->intfdev,
+-			"%s failed (err = %d)\n", __FUNCTION__, ret);
++			"%s failed (err = %d)\n", __func__, ret);
+ 	else {
+ 		*status = le16_to_cpu(hub->status->hub.wHubStatus);
+ 		*change = le16_to_cpu(hub->status->hub.wHubChange); 
+@@ -611,9 +625,8 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+ }
+ 
+ /* caller has locked the hub device */
+-static int hub_pre_reset(struct usb_interface *intf)
++static void hub_stop(struct usb_hub *hub)
+ {
+-	struct usb_hub *hub = usb_get_intfdata(intf);
+ 	struct usb_device *hdev = hub->hdev;
+ 	int i;
+ 
+@@ -623,6 +636,89 @@ static int hub_pre_reset(struct usb_interface *intf)
+ 			usb_disconnect(&hdev->children[i]);
+ 	}
+ 	hub_quiesce(hub);
++}
++
++#define HUB_RESET		1
++#define HUB_RESUME		2
++#define HUB_RESET_RESUME	3
++
++#ifdef CONFIG_PM
++
++static void hub_restart(struct usb_hub *hub, int type)
++{
++	struct usb_device *hdev = hub->hdev;
++	int port1;
++
++	/* Check each of the children to see if they require
++	 * USB-PERSIST handling or disconnection.  Also check
++	 * each unoccupied port to make sure it is still disabled.
++	 */
++	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
++		struct usb_device *udev = hdev->children[port1-1];
++		int status = 0;
++		u16 portstatus, portchange;
++
++		if (!udev || udev->state == USB_STATE_NOTATTACHED) {
++			if (type != HUB_RESET) {
++				status = hub_port_status(hub, port1,
++						&portstatus, &portchange);
++				if (status == 0 && (portstatus &
++						USB_PORT_STAT_ENABLE))
++					clear_port_feature(hdev, port1,
++							USB_PORT_FEAT_ENABLE);
++			}
++			continue;
++		}
++
++		/* Was the power session lost while we were suspended? */
++		switch (type) {
++		case HUB_RESET_RESUME:
++			portstatus = 0;
++			portchange = USB_PORT_STAT_C_CONNECTION;
++			break;
++
++		case HUB_RESET:
++		case HUB_RESUME:
++			status = hub_port_status(hub, port1,
++					&portstatus, &portchange);
++			break;
++		}
++
++		/* For "USB_PERSIST"-enabled children we must
++		 * mark the child device for reset-resume and
++		 * turn off the various status changes to prevent
++		 * khubd from disconnecting it later.
++		 */
++		if (udev->persist_enabled && status == 0 &&
++				!(portstatus & USB_PORT_STAT_ENABLE)) {
++			if (portchange & USB_PORT_STAT_C_ENABLE)
++				clear_port_feature(hub->hdev, port1,
++						USB_PORT_FEAT_C_ENABLE);
++			if (portchange & USB_PORT_STAT_C_CONNECTION)
++				clear_port_feature(hub->hdev, port1,
++						USB_PORT_FEAT_C_CONNECTION);
++			udev->reset_resume = 1;
++		}
++
++		/* Otherwise for a reset_resume we must disconnect the child,
++		 * but as we may not lock the child device here
++		 * we have to do a "logical" disconnect.
++		 */
++		else if (type == HUB_RESET_RESUME)
++			hub_port_logical_disconnect(hub, port1);
++	}
++
++	hub_activate(hub);
++}
++
++#endif	/* CONFIG_PM */
++
++/* caller has locked the hub device */
++static int hub_pre_reset(struct usb_interface *intf)
++{
++	struct usb_hub *hub = usb_get_intfdata(intf);
++
++	hub_stop(hub);
+ 	return 0;
+ }
+ 
+@@ -911,7 +1007,7 @@ static void hub_disconnect(struct usb_interface *intf)
+ 
+ 	/* Disconnect all children and quiesce the hub */
+ 	hub->error = 0;
+-	hub_pre_reset(intf);
++	hub_stop(hub);
+ 
+ 	usb_set_intfdata (intf, NULL);
+ 
+@@ -1099,21 +1195,42 @@ void usb_set_device_state(struct usb_device *udev,
+ 	spin_unlock_irqrestore(&device_state_lock, flags);
+ }
+ 
++/*
++ * WUSB devices are simple: they have no hubs behind, so the mapping
++ * device <-> virtual port number becomes 1:1. Why? to simplify the
++ * life of the device connection logic in
++ * drivers/usb/wusbcore/devconnect.c. When we do the initial secret
++ * handshake we need to assign a temporary address in the unauthorized
++ * space. For simplicity we use the first virtual port number found to
++ * be free [drivers/usb/wusbcore/devconnect.c:wusbhc_devconnect_ack()]
++ * and that becomes it's address [X < 128] or its unauthorized address
++ * [X | 0x80].
++ *
++ * We add 1 as an offset to the one-based USB-stack port number
++ * (zero-based wusb virtual port index) for two reasons: (a) dev addr
++ * 0 is reserved by USB for default address; (b) Linux's USB stack
++ * uses always #1 for the root hub of the controller. So USB stack's
++ * port #1, which is wusb virtual-port #0 has address #2.
++ */
+ static void choose_address(struct usb_device *udev)
+ {
+ 	int		devnum;
+ 	struct usb_bus	*bus = udev->bus;
+ 
+ 	/* If khubd ever becomes multithreaded, this will need a lock */
+-
+-	/* Try to allocate the next devnum beginning at bus->devnum_next. */
+-	devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
+-			bus->devnum_next);
+-	if (devnum >= 128)
+-		devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);
+-
+-	bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
+-
++	if (udev->wusb) {
++		devnum = udev->portnum + 1;
++		BUG_ON(test_bit(devnum, bus->devmap.devicemap));
++	} else {
++		/* Try to allocate the next devnum beginning at
++		 * bus->devnum_next. */
++		devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
++					    bus->devnum_next);
++		if (devnum >= 128)
++			devnum = find_next_zero_bit(bus->devmap.devicemap,
++						    128, 1);
++		bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
++	}
+ 	if (devnum < 128) {
+ 		set_bit(devnum, bus->devmap.devicemap);
+ 		udev->devnum = devnum;
+@@ -1128,6 +1245,13 @@ static void release_address(struct usb_device *udev)
+ 	}
+ }
+ 
++static void update_address(struct usb_device *udev, int devnum)
++{
++	/* The address for a WUSB device is managed by wusbcore. */
++	if (!udev->wusb)
++		udev->devnum = devnum;
++}
++
+ #ifdef	CONFIG_USB_SUSPEND
+ 
+ static void usb_stop_pm(struct usb_device *udev)
+@@ -1174,7 +1298,7 @@ void usb_disconnect(struct usb_device **pdev)
+ 	int			i;
+ 
+ 	if (!udev) {
+-		pr_debug ("%s nodev\n", __FUNCTION__);
++		pr_debug ("%s nodev\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -1511,28 +1635,6 @@ out_authorized:
+ }
+ 
+ 
+-static int hub_port_status(struct usb_hub *hub, int port1,
+-			       u16 *status, u16 *change)
+-{
+-	int ret;
+-
+-	mutex_lock(&hub->status_mutex);
+-	ret = get_port_status(hub->hdev, port1, &hub->status->port);
+-	if (ret < 4) {
+-		dev_err (hub->intfdev,
+-			"%s failed (err = %d)\n", __FUNCTION__, ret);
+-		if (ret >= 0)
+-			ret = -EIO;
+-	} else {
+-		*status = le16_to_cpu(hub->status->port.wPortStatus);
+-		*change = le16_to_cpu(hub->status->port.wPortChange); 
+-		ret = 0;
+-	}
+-	mutex_unlock(&hub->status_mutex);
+-	return ret;
+-}
+-
+-
+ /* Returns 1 if @hub is a WUSB root hub, 0 otherwise */
+ static unsigned hub_is_wusb(struct usb_hub *hub)
+ {
+@@ -1638,7 +1740,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ 		case 0:
+ 			/* TRSTRCY = 10 ms; plus some extra */
+ 			msleep(10 + 40);
+-		  	udev->devnum = 0;	/* Device now at address 0 */
++			update_address(udev, 0);
+ 			/* FALL THROUGH */
+ 		case -ENOTCONN:
+ 		case -ENODEV:
+@@ -1843,9 +1945,8 @@ static int finish_port_resume(struct usb_device *udev)
+  * the host and the device is the same as it was when the device
+  * suspended.
+  *
+- * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this
+- * routine won't check that the port is still enabled.  Furthermore,
+- * if @udev->reset_resume is set then finish_port_resume() above will
++ * If @udev->reset_resume is set then this routine won't check that the
++ * port is still enabled.  Furthermore, finish_port_resume() above will
+  * reset @udev.  The end result is that a broken power session can be
+  * recovered and @udev will appear to persist across a loss of VBUS power.
+  *
+@@ -1857,8 +1958,8 @@ static int finish_port_resume(struct usb_device *udev)
+  * to it will be lost.  Using the USB_PERSIST facility, the device can be
+  * made to appear as if it had not disconnected.
+  *
+- * This facility is inherently dangerous.  Although usb_reset_device()
+- * makes every effort to insure that the same device is present after the
++ * This facility can be dangerous.  Although usb_reset_device() makes
++ * every effort to insure that the same device is present after the
+  * reset as before, it cannot provide a 100% guarantee.  Furthermore it's
+  * quite possible for a device to remain unaltered but its media to be
+  * changed.  If the user replaces a flash memory card while the system is
+@@ -1903,7 +2004,7 @@ int usb_port_resume(struct usb_device *udev)
+ 		status = hub_port_status(hub, port1, &portstatus, &portchange);
+ 
+  SuspendCleared:
+-		if (USB_PERSIST && udev->reset_resume)
++		if (udev->reset_resume)
+ 			want_flags = USB_PORT_STAT_POWER
+ 					| USB_PORT_STAT_CONNECTION;
+ 		else
+@@ -1928,8 +2029,6 @@ int usb_port_resume(struct usb_device *udev)
+ 	}
+ 
+ 	clear_bit(port1, hub->busy_bits);
+-	if (!hub->hdev->parent && !hub->busy_bits[0])
+-		usb_enable_root_hub_irq(hub->hdev->bus);
+ 
+ 	if (status == 0)
+ 		status = finish_port_resume(udev);
+@@ -2001,7 +2100,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 		}
+ 	}
+ 
+-	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
++	dev_dbg(&intf->dev, "%s\n", __func__);
+ 
+ 	/* stop khubd and related activity */
+ 	hub_quiesce(hub);
+@@ -2010,49 +2109,20 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ 
+ static int hub_resume(struct usb_interface *intf)
+ {
+-	struct usb_hub		*hub = usb_get_intfdata (intf);
+-
+-	dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
++	struct usb_hub *hub = usb_get_intfdata(intf);
+ 
+-	/* tell khubd to look for changes on this hub */
+-	hub_activate(hub);
++	dev_dbg(&intf->dev, "%s\n", __func__);
++	hub_restart(hub, HUB_RESUME);
+ 	return 0;
+ }
+ 
+ static int hub_reset_resume(struct usb_interface *intf)
+ {
+ 	struct usb_hub *hub = usb_get_intfdata(intf);
+-	struct usb_device *hdev = hub->hdev;
+-	int port1;
+ 
++	dev_dbg(&intf->dev, "%s\n", __func__);
+ 	hub_power_on(hub);
+-
+-	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+-		struct usb_device *child = hdev->children[port1-1];
+-
+-		if (child) {
+-
+-			/* For "USB_PERSIST"-enabled children we must
+-			 * mark the child device for reset-resume and
+-			 * turn off the connect-change status to prevent
+-			 * khubd from disconnecting it later.
+-			 */
+-			if (USB_PERSIST && child->persist_enabled) {
+-				child->reset_resume = 1;
+-				clear_port_feature(hdev, port1,
+-						USB_PORT_FEAT_C_CONNECTION);
+-
+-			/* Otherwise we must disconnect the child,
+-			 * but as we may not lock the child device here
+-			 * we have to do a "logical" disconnect.
+-			 */
+-			} else {
+-				hub_port_logical_disconnect(hub, port1);
+-			}
+-		}
+-	}
+-
+-	hub_activate(hub);
++	hub_restart(hub, HUB_RESET_RESUME);
+ 	return 0;
+ }
+ 
+@@ -2062,10 +2132,10 @@ static int hub_reset_resume(struct usb_interface *intf)
+  *
+  * The USB host controller driver calls this function when its root hub
+  * is resumed and Vbus power has been interrupted or the controller
+- * has been reset.  The routine marks @rhdev as having lost power.  When
+- * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
+- * is enabled then it will carry out power-session recovery, otherwise
+- * it will disconnect all the child devices.
++ * has been reset.  The routine marks @rhdev as having lost power.
++ * When the hub driver is resumed it will take notice and carry out
++ * power-session recovery for all the "USB-PERSIST"-enabled child devices;
++ * the others will be disconnected.
+  */
+ void usb_root_hub_lost_power(struct usb_device *rhdev)
+ {
+@@ -2148,12 +2218,13 @@ static int hub_port_debounce(struct usb_hub *hub, int port1)
+ 	return portstatus;
+ }
+ 
+-static void ep0_reinit(struct usb_device *udev)
++void usb_ep0_reinit(struct usb_device *udev)
+ {
+ 	usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+ 	usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
+ 	usb_enable_endpoint(udev, &udev->ep0);
+ }
++EXPORT_SYMBOL_GPL(usb_ep0_reinit);
+ 
+ #define usb_sndaddr0pipe()	(PIPE_CONTROL << 30)
+ #define usb_rcvaddr0pipe()	((PIPE_CONTROL << 30) | USB_DIR_IN)
+@@ -2172,9 +2243,10 @@ static int hub_set_address(struct usb_device *udev, int devnum)
+ 		USB_REQ_SET_ADDRESS, 0, devnum, 0,
+ 		NULL, 0, USB_CTRL_SET_TIMEOUT);
+ 	if (retval == 0) {
+-		udev->devnum = devnum;	/* Device now using proper address */
++		/* Device now using proper address. */
++		update_address(udev, devnum);
+ 		usb_set_device_state(udev, USB_STATE_ADDRESS);
+-		ep0_reinit(udev);
++		usb_ep0_reinit(udev);
+ 	}
+ 	return retval;
+ }
+@@ -2356,26 +2428,33 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ #undef GET_DESCRIPTOR_BUFSIZE
+ 		}
+ 
+-		for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
+-			retval = hub_set_address(udev, devnum);
+-			if (retval >= 0)
++ 		/*
++ 		 * If device is WUSB, we already assigned an
++ 		 * unauthorized address in the Connect Ack sequence;
++ 		 * authorization will assign the final address.
++ 		 */
++ 		if (udev->wusb == 0) {
++			for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
++				retval = hub_set_address(udev, devnum);
++				if (retval >= 0)
++					break;
++				msleep(200);
++			}
++			if (retval < 0) {
++				dev_err(&udev->dev,
++					"device not accepting address %d, error %d\n",
++					devnum, retval);
++				goto fail;
++			}
++
++			/* cope with hardware quirkiness:
++			 *  - let SET_ADDRESS settle, some device hardware wants it
++			 *  - read ep0 maxpacket even for high and low speed,
++			 */
++			msleep(10);
++			if (USE_NEW_SCHEME(retry_counter))
+ 				break;
+-			msleep(200);
+-		}
+-		if (retval < 0) {
+-			dev_err(&udev->dev,
+-				"device not accepting address %d, error %d\n",
+-				devnum, retval);
+-			goto fail;
+-		}
+- 
+-		/* cope with hardware quirkiness:
+-		 *  - let SET_ADDRESS settle, some device hardware wants it
+-		 *  - read ep0 maxpacket even for high and low speed,
+-  		 */
+-		msleep(10);
+-		if (USE_NEW_SCHEME(retry_counter))
+-			break;
++  		}
+ 
+ 		retval = usb_get_device_descriptor(udev, 8);
+ 		if (retval < 8) {
+@@ -2392,7 +2471,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 	if (retval)
+ 		goto fail;
+ 
+-	i = udev->descriptor.bMaxPacketSize0 == 0xff?
++	i = udev->descriptor.bMaxPacketSize0 == 0xff?	/* wusb device? */
+ 	    512 : udev->descriptor.bMaxPacketSize0;
+ 	if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
+ 		if (udev->speed != USB_SPEED_FULL ||
+@@ -2403,7 +2482,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ 		}
+ 		dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+ 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
+-		ep0_reinit(udev);
++		usb_ep0_reinit(udev);
+ 	}
+   
+ 	retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
+@@ -2420,7 +2499,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ fail:
+ 	if (retval) {
+ 		hub_port_disable(hub, port1, 0);
+-		udev->devnum = devnum;	/* for disconnect processing */
++		update_address(udev, devnum);	/* for disconnect processing */
+ 	}
+ 	mutex_unlock(&usb_address0_mutex);
+ 	return retval;
+@@ -2569,6 +2648,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ 		udev->speed = USB_SPEED_UNKNOWN;
+  		udev->bus_mA = hub->mA_per_port;
+ 		udev->level = hdev->level + 1;
++		udev->wusb = hub_is_wusb(hub);
+ 
+ 		/* set the address */
+ 		choose_address(udev);
+@@ -2658,12 +2738,13 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ loop_disable:
+ 		hub_port_disable(hub, port1, 1);
+ loop:
+-		ep0_reinit(udev);
++		usb_ep0_reinit(udev);
+ 		release_address(udev);
+ 		usb_put_dev(udev);
+ 		if ((status == -ENOTCONN) || (status == -ENOTSUPP))
+ 			break;
+ 	}
++	dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1);
+  
+ done:
+ 	hub_port_disable(hub, port1, 1);
+@@ -2727,7 +2808,7 @@ static void hub_events(void)
+ 		/* If the hub has died, clean up after it */
+ 		if (hdev->state == USB_STATE_NOTATTACHED) {
+ 			hub->error = -ENODEV;
+-			hub_pre_reset(intf);
++			hub_stop(hub);
+ 			goto loop;
+ 		}
+ 
+@@ -2873,11 +2954,6 @@ static void hub_events(void)
+ 
+ 		hub->activating = 0;
+ 
+-		/* If this is a root hub, tell the HCD it's okay to
+-		 * re-enable port-change interrupts now. */
+-		if (!hdev->parent && !hub->busy_bits[0])
+-			usb_enable_root_hub_irq(hdev->bus);
+-
+ loop_autopm:
+ 		/* Allow autosuspend if we're not going to run again */
+ 		if (list_empty(&hub->event_list))
+@@ -2891,7 +2967,13 @@ loop:
+ 
+ static int hub_thread(void *__unused)
+ {
++	/* khubd needs to be freezable to avoid intefering with USB-PERSIST
++	 * port handover.  Otherwise it might see that a full-speed device
++	 * was gone before the EHCI controller had handed its port over to
++	 * the companion full-speed controller.
++	 */
+ 	set_freezable();
++
+ 	do {
+ 		hub_events();
+ 		wait_event_freezable(khubd_wait,
+@@ -2960,16 +3042,36 @@ void usb_hub_cleanup(void)
+ 	usb_deregister(&hub_driver);
+ } /* usb_hub_cleanup() */
+ 
+-static int config_descriptors_changed(struct usb_device *udev)
++static int descriptors_changed(struct usb_device *udev,
++		struct usb_device_descriptor *old_device_descriptor)
+ {
+-	unsigned			index;
+-	unsigned			len = 0;
+-	struct usb_config_descriptor	*buf;
++	int		changed = 0;
++	unsigned	index;
++	unsigned	serial_len = 0;
++	unsigned	len;
++	unsigned	old_length;
++	int		length;
++	char		*buf;
++
++	if (memcmp(&udev->descriptor, old_device_descriptor,
++			sizeof(*old_device_descriptor)) != 0)
++		return 1;
+ 
++	/* Since the idVendor, idProduct, and bcdDevice values in the
++	 * device descriptor haven't changed, we will assume the
++	 * Manufacturer and Product strings haven't changed either.
++	 * But the SerialNumber string could be different (e.g., a
++	 * different flash card of the same brand).
++	 */
++	if (udev->serial)
++		serial_len = strlen(udev->serial) + 1;
++
++	len = serial_len;
+ 	for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
+-		if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
+-			len = le16_to_cpu(udev->config[index].desc.wTotalLength);
++		old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
++		len = max(len, old_length);
+ 	}
++
+ 	buf = kmalloc(len, GFP_NOIO);
+ 	if (buf == NULL) {
+ 		dev_err(&udev->dev, "no mem to re-read configs after reset\n");
+@@ -2977,25 +3079,41 @@ static int config_descriptors_changed(struct usb_device *udev)
+ 		return 1;
+ 	}
+ 	for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
+-		int length;
+-		int old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
+-
++		old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
+ 		length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf,
+ 				old_length);
+-		if (length < old_length) {
++		if (length != old_length) {
+ 			dev_dbg(&udev->dev, "config index %d, error %d\n",
+ 					index, length);
++			changed = 1;
+ 			break;
+ 		}
+ 		if (memcmp (buf, udev->rawdescriptors[index], old_length)
+ 				!= 0) {
+ 			dev_dbg(&udev->dev, "config index %d changed (#%d)\n",
+-				index, buf->bConfigurationValue);
++				index,
++				((struct usb_config_descriptor *) buf)->
++					bConfigurationValue);
++			changed = 1;
+ 			break;
+ 		}
+ 	}
++
++	if (!changed && serial_len) {
++		length = usb_string(udev, udev->descriptor.iSerialNumber,
++				buf, serial_len);
++		if (length + 1 != serial_len) {
++			dev_dbg(&udev->dev, "serial string error %d\n",
++					length);
++			changed = 1;
++		} else if (memcmp(buf, udev->serial, length) != 0) {
++			dev_dbg(&udev->dev, "serial string changed\n");
++			changed = 1;
++		}
++	}
++
+ 	kfree(buf);
+-	return index != udev->descriptor.bNumConfigurations;
++	return changed;
+ }
+ 
+ /**
+@@ -3045,7 +3163,7 @@ int usb_reset_device(struct usb_device *udev)
+ 
+ 	if (!parent_hdev) {
+ 		/* this requires hcd-specific logic; see OHCI hc_restart() */
+-		dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__);
++		dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
+ 		return -EISDIR;
+ 	}
+ 	parent_hub = hdev_to_hub(parent_hdev);
+@@ -3055,21 +3173,18 @@ int usb_reset_device(struct usb_device *udev)
+ 
+ 		/* ep0 maxpacket size may change; let the HCD know about it.
+ 		 * Other endpoints will be handled by re-enumeration. */
+-		ep0_reinit(udev);
++		usb_ep0_reinit(udev);
+ 		ret = hub_port_init(parent_hub, udev, port1, i);
+ 		if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
+ 			break;
+ 	}
+ 	clear_bit(port1, parent_hub->busy_bits);
+-	if (!parent_hdev->parent && !parent_hub->busy_bits[0])
+-		usb_enable_root_hub_irq(parent_hdev->bus);
+ 
+ 	if (ret < 0)
+ 		goto re_enumerate;
+  
+ 	/* Device might have changed firmware (DFU or similar) */
+-	if (memcmp(&udev->descriptor, &descriptor, sizeof descriptor)
+-			|| config_descriptors_changed (udev)) {
++	if (descriptors_changed(udev, &descriptor)) {
+ 		dev_info(&udev->dev, "device firmware changed\n");
+ 		udev->descriptor = descriptor;	/* for disconnect() calls */
+ 		goto re_enumerate;
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index 1551aed..2a116ce 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -41,9 +41,10 @@
+  */
+ #define USB_PORT_FEAT_CONNECTION	0
+ #define USB_PORT_FEAT_ENABLE		1
+-#define USB_PORT_FEAT_SUSPEND		2
++#define USB_PORT_FEAT_SUSPEND		2	/* L2 suspend */
+ #define USB_PORT_FEAT_OVER_CURRENT	3
+ #define USB_PORT_FEAT_RESET		4
++#define USB_PORT_FEAT_L1		5	/* L1 suspend */
+ #define USB_PORT_FEAT_POWER		8
+ #define USB_PORT_FEAT_LOWSPEED		9
+ #define USB_PORT_FEAT_HIGHSPEED		10
+@@ -54,6 +55,7 @@
+ #define USB_PORT_FEAT_C_RESET		20
+ #define USB_PORT_FEAT_TEST              21
+ #define USB_PORT_FEAT_INDICATOR         22
++#define USB_PORT_FEAT_C_PORT_L1         23
+ 
+ /*
+  * Hub Status and Hub Change results
+@@ -73,7 +75,8 @@ struct usb_port_status {
+ #define USB_PORT_STAT_SUSPEND		0x0004
+ #define USB_PORT_STAT_OVERCURRENT	0x0008
+ #define USB_PORT_STAT_RESET		0x0010
+-/* bits 5 to 7 are reserved */
++#define USB_PORT_STAT_L1		0x0020
++/* bits 6 to 7 are reserved */
+ #define USB_PORT_STAT_POWER		0x0100
+ #define USB_PORT_STAT_LOW_SPEED		0x0200
+ #define USB_PORT_STAT_HIGH_SPEED        0x0400
+@@ -91,6 +94,7 @@ struct usb_port_status {
+ #define USB_PORT_STAT_C_SUSPEND		0x0004
+ #define USB_PORT_STAT_C_OVERCURRENT	0x0008
+ #define USB_PORT_STAT_C_RESET		0x0010
++#define USB_PORT_STAT_C_L1		0x0020
+ 
+ /*
+  * wHubCharacteristics (masks)
+@@ -191,5 +195,6 @@ struct usb_tt_clear {
+ };
+ 
+ extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
++extern void usb_ep0_reinit(struct usb_device *);
+ 
+ #endif /* __LINUX_HUB_H */
+diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
+index 83a373e..8607846 100644
+--- a/drivers/usb/core/inode.c
++++ b/drivers/usb/core/inode.c
+@@ -463,13 +463,13 @@ static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
+ 	inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
+ 
+ 	if (!inode) {
+-		dbg("%s: could not get inode!",__FUNCTION__);
++		dbg("%s: could not get inode!",__func__);
+ 		return -ENOMEM;
+ 	}
+ 
+ 	root = d_alloc_root(inode);
+ 	if (!root) {
+-		dbg("%s: could not get root dentry!",__FUNCTION__);
++		dbg("%s: could not get root dentry!",__func__);
+ 		iput(inode);
+ 		return -ENOMEM;
+ 	}
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index c311f67..e819e53 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -312,7 +312,7 @@ static void sg_complete(struct urb *urb)
+ 				    retval != -EBUSY)
+ 					dev_err(&io->dev->dev,
+ 						"%s, unlink --> %d\n",
+-						__FUNCTION__, retval);
++						__func__, retval);
+ 			} else if (urb == io->urbs [i])
+ 				found = 1;
+ 		}
+@@ -550,7 +550,7 @@ void usb_sg_wait(struct usb_sg_request *io)
+ 			io->urbs[i]->dev = NULL;
+ 			io->urbs[i]->status = retval;
+ 			dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
+-				__FUNCTION__, retval);
++				__func__, retval);
+ 			usb_sg_cancel(io);
+ 		}
+ 		spin_lock_irq(&io->lock);
+@@ -600,7 +600,7 @@ void usb_sg_cancel(struct usb_sg_request *io)
+ 			retval = usb_unlink_urb(io->urbs [i]);
+ 			if (retval != -EINPROGRESS && retval != -EBUSY)
+ 				dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
+-					__FUNCTION__, retval);
++					__func__, retval);
+ 		}
+ 		spin_lock(&io->lock);
+ 	}
+@@ -784,7 +784,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+ 	if (size <= 0 || !buf || !index)
+ 		return -EINVAL;
+ 	buf[0] = 0;
+-	tbuf = kmalloc(256, GFP_KERNEL);
++	tbuf = kmalloc(256, GFP_NOIO);
+ 	if (!tbuf)
+ 		return -ENOMEM;
+ 
+@@ -1068,7 +1068,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ {
+ 	int i;
+ 
+-	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,
++	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);
+@@ -1089,8 +1089,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ 				continue;
+ 			dev_dbg(&dev->dev, "unregistering interface %s\n",
+ 				interface->dev.bus_id);
+-			usb_remove_sysfs_intf_files(interface);
+ 			device_del(&interface->dev);
++			usb_remove_sysfs_intf_files(interface);
+ 		}
+ 
+ 		/* Now that the interfaces are unbound, nobody should
+@@ -1231,7 +1231,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ 	 */
+ 
+ 	/* prevent submissions using previous endpoint settings */
+-	if (iface->cur_altsetting != alt && device_is_registered(&iface->dev))
++	if (iface->cur_altsetting != alt)
+ 		usb_remove_sysfs_intf_files(iface);
+ 	usb_disable_interface(dev, iface);
+ 
+@@ -1330,8 +1330,7 @@ int usb_reset_configuration(struct usb_device *dev)
+ 		struct usb_interface *intf = config->interface[i];
+ 		struct usb_host_interface *alt;
+ 
+-		if (device_is_registered(&intf->dev))
+-			usb_remove_sysfs_intf_files(intf);
++		usb_remove_sysfs_intf_files(intf);
+ 		alt = usb_altnum_to_altsetting(intf, 0);
+ 
+ 		/* No altsetting 0?  We'll assume the first altsetting.
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index dfc5418..2e20193 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -97,4 +97,18 @@ void usb_detect_quirks(struct usb_device *udev)
+ 	if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
+ 		udev->autosuspend_disabled = 1;
+ #endif
++
++	/* For the present, all devices default to USB-PERSIST enabled */
++#if 0		/* was: #ifdef CONFIG_PM */
++	/* Hubs are automatically enabled for USB-PERSIST */
++	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
++		udev->persist_enabled = 1;
++
++#else
++	/* In the absence of PM, we can safely enable USB-PERSIST
++	 * for all devices.  It will affect things like hub resets
++	 * and EMF-related port disables.
++	 */
++	udev->persist_enabled = 1;
++#endif	/* CONFIG_PM */
+ }
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index a37ccbd..5b20a60 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -180,11 +180,9 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
+ static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
+ 
+ 
+-#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
+-static const char power_group[] = "power";
+-#endif
++#ifdef	CONFIG_PM
+ 
+-#ifdef	CONFIG_USB_PERSIST
++static const char power_group[] = "power";
+ 
+ static ssize_t
+ show_persist(struct device *dev, struct device_attribute *attr, char *buf)
+@@ -222,12 +220,13 @@ static int add_persist_attributes(struct device *dev)
+ 	if (is_usb_device(dev)) {
+ 		struct usb_device *udev = to_usb_device(dev);
+ 
+-		/* Hubs are automatically enabled for USB_PERSIST */
+-		if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+-			udev->persist_enabled = 1;
+-		rc = sysfs_add_file_to_group(&dev->kobj,
+-				&dev_attr_persist.attr,
+-				power_group);
++		/* Hubs are automatically enabled for USB_PERSIST,
++		 * no point in creating the attribute file.
++		 */
++		if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
++			rc = sysfs_add_file_to_group(&dev->kobj,
++					&dev_attr_persist.attr,
++					power_group);
+ 	}
+ 	return rc;
+ }
+@@ -238,13 +237,12 @@ static void remove_persist_attributes(struct device *dev)
+ 			&dev_attr_persist.attr,
+ 			power_group);
+ }
+-
+ #else
+ 
+ #define add_persist_attributes(dev)	0
+ #define remove_persist_attributes(dev)	do {} while (0)
+ 
+-#endif	/* CONFIG_USB_PERSIST */
++#endif	/* CONFIG_PM */
+ 
+ #ifdef	CONFIG_USB_SUSPEND
+ 
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 9d7e632..c0b1ae2 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -334,7 +334,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ 		dev_dbg(&dev->dev,
+ 			"bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
+ 			usb_endpoint_num(&ep->desc), is_out ? "out" : "in",
+-			__FUNCTION__, max);
++			__func__, max);
+ 		return -EMSGSIZE;
+ 	}
+ 
+@@ -590,6 +590,30 @@ void usb_kill_anchored_urbs(struct usb_anchor *anchor)
+ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
+ 
+ /**
++ * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
++ * @anchor: anchor the requests are bound to
++ *
++ * this allows all outstanding URBs to be unlinked starting
++ * from the back of the queue. This function is asynchronous.
++ * The unlinking is just tiggered. It may happen after this
++ * function has returned.
++ */
++void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
++{
++	struct urb *victim;
++
++	spin_lock_irq(&anchor->lock);
++	while (!list_empty(&anchor->urb_list)) {
++		victim = list_entry(anchor->urb_list.prev, struct urb,
++				    anchor_list);
++		/* this will unanchor the URB */
++		usb_unlink_urb(victim);
++	}
++	spin_unlock_irq(&anchor->lock);
++}
++EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
++
++/**
+  * usb_wait_anchor_empty_timeout - wait for an anchor to be unused
+  * @anchor: the anchor you want to become unused
+  * @timeout: how long you are willing to wait in milliseconds
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 2375194..1bf8ccb 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -114,13 +114,11 @@ static inline int is_usb_device_driver(struct device_driver *drv)
+ static inline void mark_active(struct usb_interface *f)
+ {
+ 	f->is_active = 1;
+-	f->dev.power.power_state.event = PM_EVENT_ON;
+ }
+ 
+ static inline void mark_quiesced(struct usb_interface *f)
+ {
+ 	f->is_active = 0;
+-	f->dev.power.power_state.event = PM_EVENT_SUSPEND;
+ }
+ 
+ static inline int is_active(const struct usb_interface *f)
+diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
+index 6f45dd6..f7b5465 100644
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -44,8 +44,8 @@ menuconfig USB_GADGET
+ if USB_GADGET
+ 
+ config USB_GADGET_DEBUG
+-	boolean "Debugging messages"
+-	depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
++	boolean "Debugging messages (DEVELOPMENT)"
++	depends on USB_GADGET && DEBUG_KERNEL
+ 	help
+ 	   Many controller and gadget drivers will print some debugging
+ 	   messages if you use this option to ask for those messages.
+@@ -58,7 +58,7 @@ config USB_GADGET_DEBUG
+ 	   production build.
+ 
+ config USB_GADGET_DEBUG_FILES
+-	boolean "Debugging information files"
++	boolean "Debugging information files (DEVELOPMENT)"
+ 	depends on USB_GADGET && PROC_FS
+ 	help
+ 	   Some of the drivers in the "gadget" framework can expose
+@@ -69,7 +69,7 @@ config USB_GADGET_DEBUG_FILES
+ 	   here.  If in doubt, or to conserve kernel memory, say "N".
+ 
+ config USB_GADGET_DEBUG_FS
+-	boolean "Debugging information files in debugfs"
++	boolean "Debugging information files in debugfs (DEVELOPMENT)"
+ 	depends on USB_GADGET && DEBUG_FS
+ 	help
+ 	   Some of the drivers in the "gadget" framework can expose
+@@ -118,10 +118,10 @@ config USB_AMD5536UDC
+ config USB_GADGET_ATMEL_USBA
+ 	boolean "Atmel USBA"
+ 	select USB_GADGET_DUALSPEED
+-	depends on AVR32
++	depends on AVR32 || ARCH_AT91CAP9
+ 	help
+ 	  USBA is the integrated high-speed USB Device controller on
+-	  the AT32AP700x processors from Atmel.
++	  the AT32AP700x and AT91CAP9 processors from Atmel.
+ 
+ config USB_ATMEL_USBA
+ 	tristate
+@@ -337,7 +337,7 @@ config USB_AT91
+ 
+ config USB_GADGET_DUMMY_HCD
+ 	boolean "Dummy HCD (DEVELOPMENT)"
+-	depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
++	depends on USB=y || (USB=m && USB_GADGET=m)
+ 	select USB_GADGET_DUALSPEED
+ 	help
+ 	  This host controller driver emulates USB, looping all data transfer
+@@ -404,7 +404,6 @@ choice
+ 
+ config USB_ZERO
+ 	tristate "Gadget Zero (DEVELOPMENT)"
+-	depends on EXPERIMENTAL
+ 	help
+ 	  Gadget Zero is a two-configuration device.  It either sinks and
+ 	  sources bulk data; or it loops back a configurable number of
+@@ -468,8 +467,8 @@ config USB_ETH
+ 	  dynamically linked module called "g_ether".
+ 
+ config USB_ETH_RNDIS
+-	bool "RNDIS support (EXPERIMENTAL)"
+-	depends on USB_ETH && EXPERIMENTAL
++	bool "RNDIS support"
++	depends on USB_ETH
+ 	default y
+ 	help
+ 	   Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
+@@ -495,6 +494,9 @@ config USB_GADGETFS
+ 	  All endpoints, transfer speeds, and transfer types supported by
+ 	  the hardware are available, through read() and write() calls.
+ 
++	  Currently, this option is still labelled as EXPERIMENTAL because
++	  of existing race conditions in the underlying in-kernel AIO core.
++
+ 	  Say "y" to link the driver statically, or "m" to build a
+ 	  dynamically linked module called "gadgetfs".
+ 
+diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
+index b663f23..fc6f348 100644
+--- a/drivers/usb/gadget/amd5536udc.c
++++ b/drivers/usb/gadget/amd5536udc.c
+@@ -3248,6 +3248,8 @@ static int udc_pci_probe(
+ 
+ 	/* pci setup */
+ 	if (pci_enable_device(pdev) < 0) {
++		kfree(dev);
++		dev = 0;
+ 		retval = -ENODEV;
+ 		goto finished;
+ 	}
+@@ -3259,6 +3261,8 @@ static int udc_pci_probe(
+ 
+ 	if (!request_mem_region(resource, len, name)) {
+ 		dev_dbg(&pdev->dev, "pci device used already\n");
++		kfree(dev);
++		dev = 0;
+ 		retval = -EBUSY;
+ 		goto finished;
+ 	}
+@@ -3267,18 +3271,24 @@ static int udc_pci_probe(
+ 	dev->virt_addr = ioremap_nocache(resource, len);
+ 	if (dev->virt_addr == NULL) {
+ 		dev_dbg(&pdev->dev, "start address cannot be mapped\n");
++		kfree(dev);
++		dev = 0;
+ 		retval = -EFAULT;
+ 		goto finished;
+ 	}
+ 
+ 	if (!pdev->irq) {
+ 		dev_err(&dev->pdev->dev, "irq not set\n");
++		kfree(dev);
++		dev = 0;
+ 		retval = -ENODEV;
+ 		goto finished;
+ 	}
+ 
+ 	if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
+ 		dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
++		kfree(dev);
++		dev = 0;
+ 		retval = -EBUSY;
+ 		goto finished;
+ 	}
+diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
+index fd15ced..9b913af 100644
+--- a/drivers/usb/gadget/at91_udc.c
++++ b/drivers/usb/gadget/at91_udc.c
+@@ -389,6 +389,7 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+ 	u32		csr = __raw_readl(creg);
+ 	u8 __iomem	*dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+ 	unsigned	total, count, is_last;
++	u8		*buf;
+ 
+ 	/*
+ 	 * TODO: allow for writing two packets to the fifo ... that'll
+@@ -413,6 +414,8 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+ 			return 0;
+ 	}
+ 
++	buf = req->req.buf + req->req.actual;
++	prefetch(buf);
+ 	total = req->req.length - req->req.actual;
+ 	if (ep->ep.maxpacket < total) {
+ 		count = ep->ep.maxpacket;
+@@ -435,7 +438,7 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+ 	 * recover when the actual bytecount matters (e.g. for USB Test
+ 	 * and Measurement Class devices).
+ 	 */
+-	__raw_writesb(dreg, req->req.buf + req->req.actual, count);
++	__raw_writesb(dreg, buf, count);
+ 	csr &= ~SET_FX;
+ 	csr |= CLR_FX | AT91_UDP_TXPKTRDY;
+ 	__raw_writel(csr, creg);
+@@ -457,7 +460,7 @@ static void nuke(struct at91_ep *ep, int status)
+ 	if (list_empty(&ep->queue))
+ 		return;
+ 
+-	VDBG("%s %s\n", __FUNCTION__, ep->ep.name);
++	VDBG("%s %s\n", __func__, ep->ep.name);
+ 	while (!list_empty(&ep->queue)) {
+ 		req = list_entry(ep->queue.next, struct at91_request, queue);
+ 		done(ep, req, status);
+@@ -792,7 +795,7 @@ static int at91_wakeup(struct usb_gadget *gadget)
+ 	int		status = -EINVAL;
+ 	unsigned long	flags;
+ 
+-	DBG("%s\n", __FUNCTION__ );
++	DBG("%s\n", __func__ );
+ 	local_irq_save(flags);
+ 
+ 	if (!udc->clocked || !udc->suspended)
+diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
+index b0db4c3..e756023 100644
+--- a/drivers/usb/gadget/atmel_usba_udc.c
++++ b/drivers/usb/gadget/atmel_usba_udc.c
+@@ -18,6 +18,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/usb/ch9.h>
+ #include <linux/usb/gadget.h>
++#include <linux/usb/atmel_usba_udc.h>
+ #include <linux/delay.h>
+ 
+ #include <asm/gpio.h>
+@@ -27,6 +28,7 @@
+ 
+ 
+ static struct usba_udc the_udc;
++static struct usba_ep *usba_ep;
+ 
+ #ifdef CONFIG_USB_GADGET_DEBUG_FS
+ #include <linux/debugfs.h>
+@@ -324,53 +326,28 @@ static int vbus_is_present(struct usba_udc *udc)
+ 	return 1;
+ }
+ 
+-static void copy_to_fifo(void __iomem *fifo, const void *buf, int len)
++#if defined(CONFIG_AVR32)
++
++static void toggle_bias(int is_on)
+ {
+-	unsigned long tmp;
+-
+-	DBG(DBG_FIFO, "copy to FIFO (len %d):\n", len);
+-	for (; len > 0; len -= 4, buf += 4, fifo += 4) {
+-		tmp = *(unsigned long *)buf;
+-		if (len >= 4) {
+-			DBG(DBG_FIFO, "  -> %08lx\n", tmp);
+-			__raw_writel(tmp, fifo);
+-		} else {
+-			do {
+-				DBG(DBG_FIFO, "  -> %02lx\n", tmp >> 24);
+-				__raw_writeb(tmp >> 24, fifo);
+-				fifo++;
+-				tmp <<= 8;
+-			} while (--len);
+-			break;
+-		}
+-	}
+ }
+ 
+-static void copy_from_fifo(void *buf, void __iomem *fifo, int len)
++#elif defined(CONFIG_ARCH_AT91)
++
++#include <asm/arch/at91_pmc.h>
++
++static void toggle_bias(int is_on)
+ {
+-	union {
+-		unsigned long *w;
+-		unsigned char *b;
+-	} p;
+-	unsigned long tmp;
+-
+-	DBG(DBG_FIFO, "copy from FIFO (len %d):\n", len);
+-	for (p.w = buf; len > 0; len -= 4, p.w++, fifo += 4) {
+-		if (len >= 4) {
+-			tmp = __raw_readl(fifo);
+-			*p.w = tmp;
+-			DBG(DBG_FIFO, "  -> %08lx\n", tmp);
+-		} else {
+-			do {
+-				tmp = __raw_readb(fifo);
+-				*p.b = tmp;
+-				DBG(DBG_FIFO, " -> %02lx\n", tmp);
+-				fifo++, p.b++;
+-			} while (--len);
+-		}
+-	}
++	unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
++
++	if (is_on)
++		at91_sys_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
++	else
++		at91_sys_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
+ }
+ 
++#endif /* CONFIG_ARCH_AT91 */
++
+ static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
+ {
+ 	unsigned int transaction_len;
+@@ -387,7 +364,7 @@ static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
+ 		ep->ep.name, req, transaction_len,
+ 		req->last_transaction ? ", done" : "");
+ 
+-	copy_to_fifo(ep->fifo, req->req.buf + req->req.actual, transaction_len);
++	memcpy_toio(ep->fifo, req->req.buf + req->req.actual, transaction_len);
+ 	usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+ 	req->req.actual += transaction_len;
+ }
+@@ -476,7 +453,7 @@ static void receive_data(struct usba_ep *ep)
+ 			bytecount = req->req.length - req->req.actual;
+ 		}
+ 
+-		copy_from_fifo(req->req.buf + req->req.actual,
++		memcpy_fromio(req->req.buf + req->req.actual,
+ 				ep->fifo, bytecount);
+ 		req->req.actual += bytecount;
+ 
+@@ -1029,33 +1006,6 @@ static const struct usb_gadget_ops usba_udc_ops = {
+ 	.set_selfpowered	= usba_udc_set_selfpowered,
+ };
+ 
+-#define EP(nam, idx, maxpkt, maxbk, dma, isoc)			\
+-{								\
+-	.ep	= {						\
+-		.ops		= &usba_ep_ops,			\
+-		.name		= nam,				\
+-		.maxpacket	= maxpkt,			\
+-	},							\
+-	.udc		= &the_udc,				\
+-	.queue		= LIST_HEAD_INIT(usba_ep[idx].queue),	\
+-	.fifo_size	= maxpkt,				\
+-	.nr_banks	= maxbk,				\
+-	.index		= idx,					\
+-	.can_dma	= dma,					\
+-	.can_isoc	= isoc,					\
+-}
+-
+-static struct usba_ep usba_ep[] = {
+-	EP("ep0", 0, 64, 1, 0, 0),
+-	EP("ep1in-bulk", 1, 512, 2, 1, 1),
+-	EP("ep2out-bulk", 2, 512, 2, 1, 1),
+-	EP("ep3in-int", 3, 64, 3, 1, 0),
+-	EP("ep4out-int", 4, 64, 3, 1, 0),
+-	EP("ep5in-iso", 5, 1024, 3, 1, 1),
+-	EP("ep6out-iso", 6, 1024, 3, 1, 1),
+-};
+-#undef EP
+-
+ static struct usb_endpoint_descriptor usba_ep0_desc = {
+ 	.bLength = USB_DT_ENDPOINT_SIZE,
+ 	.bDescriptorType = USB_DT_ENDPOINT,
+@@ -1074,7 +1024,6 @@ static void nop_release(struct device *dev)
+ static struct usba_udc the_udc = {
+ 	.gadget	= {
+ 		.ops		= &usba_udc_ops,
+-		.ep0		= &usba_ep[0].ep,
+ 		.ep_list	= LIST_HEAD_INIT(the_udc.gadget.ep_list),
+ 		.is_dualspeed	= 1,
+ 		.name		= "atmel_usba_udc",
+@@ -1231,7 +1180,7 @@ static int do_test_mode(struct usba_udc *udc)
+ 		} else {
+ 			usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+ 			usba_writel(udc, TST, USBA_TST_PKT_MODE);
+-			copy_to_fifo(ep->fifo, test_packet_buffer,
++			memcpy_toio(ep->fifo, test_packet_buffer,
+ 					sizeof(test_packet_buffer));
+ 			usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+ 			dev_info(dev, "Entering Test_Packet mode...\n");
+@@ -1530,13 +1479,13 @@ restart:
+ 		DBG(DBG_HW, "Packet length: %u\n", pkt_len);
+ 		if (pkt_len != sizeof(crq)) {
+ 			pr_warning("udc: Invalid packet length %u "
+-				"(expected %lu)\n", pkt_len, sizeof(crq));
++				"(expected %zu)\n", pkt_len, sizeof(crq));
+ 			set_protocol_stall(udc, ep);
+ 			return;
+ 		}
+ 
+ 		DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo);
+-		copy_from_fifo(crq.data, ep->fifo, sizeof(crq));
++		memcpy_fromio(crq.data, ep->fifo, sizeof(crq));
+ 
+ 		/* Free up one bank in the FIFO so that we can
+ 		 * generate or receive a reply right away. */
+@@ -1688,6 +1637,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
+ 	DBG(DBG_INT, "irq, status=%#08x\n", status);
+ 
+ 	if (status & USBA_DET_SUSPEND) {
++		toggle_bias(0);
+ 		usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
+ 		DBG(DBG_BUS, "Suspend detected\n");
+ 		if (udc->gadget.speed != USB_SPEED_UNKNOWN
+@@ -1699,6 +1649,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
+ 	}
+ 
+ 	if (status & USBA_WAKE_UP) {
++		toggle_bias(1);
+ 		usba_writel(udc, INT_CLR, USBA_WAKE_UP);
+ 		DBG(DBG_BUS, "Wake Up CPU detected\n");
+ 	}
+@@ -1792,12 +1743,14 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
+ 	vbus = gpio_get_value(udc->vbus_pin);
+ 	if (vbus != udc->vbus_prev) {
+ 		if (vbus) {
+-			usba_writel(udc, CTRL, USBA_EN_USBA);
++			toggle_bias(1);
++			usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+ 			usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+ 		} else {
+ 			udc->gadget.speed = USB_SPEED_UNKNOWN;
+ 			reset_all_endpoints(udc);
+-			usba_writel(udc, CTRL, 0);
++			toggle_bias(0);
++			usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+ 			spin_unlock(&udc->lock);
+ 			udc->driver->disconnect(&udc->gadget);
+ 			spin_lock(&udc->lock);
+@@ -1850,7 +1803,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+ 	/* If Vbus is present, enable the controller and wait for reset */
+ 	spin_lock_irqsave(&udc->lock, flags);
+ 	if (vbus_is_present(udc) && udc->vbus_prev == 0) {
+-		usba_writel(udc, CTRL, USBA_EN_USBA);
++		toggle_bias(1);
++		usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+ 		usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+ 	}
+ 	spin_unlock_irqrestore(&udc->lock, flags);
+@@ -1883,7 +1837,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+ 	spin_unlock_irqrestore(&udc->lock, flags);
+ 
+ 	/* This will also disable the DP pullup */
+-	usba_writel(udc, CTRL, 0);
++	toggle_bias(0);
++	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+ 
+ 	driver->unbind(&udc->gadget);
+ 	udc->gadget.dev.driver = NULL;
+@@ -1908,7 +1863,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+ 
+ 	regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID);
+ 	fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID);
+-	if (!regs || !fifo)
++	if (!regs || !fifo || !pdata)
+ 		return -ENXIO;
+ 
+ 	irq = platform_get_irq(pdev, 0);
+@@ -1953,19 +1908,48 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+ 
+ 	/* Make sure we start from a clean slate */
+ 	clk_enable(pclk);
+-	usba_writel(udc, CTRL, 0);
++	toggle_bias(0);
++	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+ 	clk_disable(pclk);
+ 
++	usba_ep = kmalloc(sizeof(struct usba_ep) * pdata->num_ep,
++			  GFP_KERNEL);
++	if (!usba_ep)
++		goto err_alloc_ep;
++
++	the_udc.gadget.ep0 = &usba_ep[0].ep;
++
+ 	INIT_LIST_HEAD(&usba_ep[0].ep.ep_list);
+ 	usba_ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0);
+ 	usba_ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0);
+ 	usba_ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0);
+-	for (i = 1; i < ARRAY_SIZE(usba_ep); i++) {
++	usba_ep[0].ep.ops = &usba_ep_ops;
++	usba_ep[0].ep.name = pdata->ep[0].name;
++	usba_ep[0].ep.maxpacket = pdata->ep[0].fifo_size;
++	usba_ep[0].udc = &the_udc;
++	INIT_LIST_HEAD(&usba_ep[0].queue);
++	usba_ep[0].fifo_size = pdata->ep[0].fifo_size;
++	usba_ep[0].nr_banks = pdata->ep[0].nr_banks;
++	usba_ep[0].index = pdata->ep[0].index;
++	usba_ep[0].can_dma = pdata->ep[0].can_dma;
++	usba_ep[0].can_isoc = pdata->ep[0].can_isoc;
++
++	for (i = 1; i < pdata->num_ep; i++) {
+ 		struct usba_ep *ep = &usba_ep[i];
+ 
+ 		ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
+ 		ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
+ 		ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
++		ep->ep.ops = &usba_ep_ops;
++		ep->ep.name = pdata->ep[i].name;
++		ep->ep.maxpacket = pdata->ep[i].fifo_size;
++		ep->udc = &the_udc;
++		INIT_LIST_HEAD(&ep->queue);
++		ep->fifo_size = pdata->ep[i].fifo_size;
++		ep->nr_banks = pdata->ep[i].nr_banks;
++		ep->index = pdata->ep[i].index;
++		ep->can_dma = pdata->ep[i].can_dma;
++		ep->can_isoc = pdata->ep[i].can_isoc;
+ 
+ 		list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+ 	}
+@@ -1984,7 +1968,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+ 		goto err_device_add;
+ 	}
+ 
+-	if (pdata && pdata->vbus_pin != GPIO_PIN_NONE) {
++	if (pdata->vbus_pin >= 0) {
+ 		if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
+ 			udc->vbus_pin = pdata->vbus_pin;
+ 
+@@ -2004,7 +1988,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	usba_init_debugfs(udc);
+-	for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
++	for (i = 1; i < pdata->num_ep; i++)
+ 		usba_ep_init_debugfs(udc, &usba_ep[i]);
+ 
+ 	return 0;
+@@ -2012,6 +1996,8 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+ err_device_add:
+ 	free_irq(irq, udc);
+ err_request_irq:
++	kfree(usba_ep);
++err_alloc_ep:
+ 	iounmap(udc->fifo);
+ err_map_fifo:
+ 	iounmap(udc->regs);
+@@ -2029,10 +2015,11 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
+ {
+ 	struct usba_udc *udc;
+ 	int i;
++	struct usba_platform_data *pdata = pdev->dev.platform_data;
+ 
+ 	udc = platform_get_drvdata(pdev);
+ 
+-	for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
++	for (i = 1; i < pdata->num_ep; i++)
+ 		usba_ep_cleanup_debugfs(&usba_ep[i]);
+ 	usba_cleanup_debugfs(udc);
+ 
+@@ -2040,6 +2027,7 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
+ 		gpio_free(udc->vbus_pin);
+ 
+ 	free_irq(udc->irq, udc);
++	kfree(usba_ep);
+ 	iounmap(udc->fifo);
+ 	iounmap(udc->regs);
+ 	clk_put(udc->hclk);
+diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
+index 08bf6f9..f7baea3 100644
+--- a/drivers/usb/gadget/atmel_usba_udc.h
++++ b/drivers/usb/gadget/atmel_usba_udc.h
+@@ -41,6 +41,15 @@
+ #define USBA_EN_USBA				(1 <<  8)
+ #define USBA_DETACH				(1 <<  9)
+ #define USBA_REMOTE_WAKE_UP			(1 << 10)
++#define USBA_PULLD_DIS				(1 << 11)
++
++#if defined(CONFIG_AVR32)
++#define USBA_ENABLE_MASK			USBA_EN_USBA
++#define USBA_DISABLE_MASK			0
++#elif defined(CONFIG_ARCH_AT91)
++#define USBA_ENABLE_MASK			(USBA_EN_USBA | USBA_PULLD_DIS)
++#define USBA_DISABLE_MASK			USBA_DETACH
++#endif /* CONFIG_ARCH_AT91 */
+ 
+ /* Bitfields in FNUM */
+ #define USBA_MICRO_FRAME_NUM_OFFSET		0
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index cbe4453..6629310 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -365,16 +365,14 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+ 		case USB_SPEED_HIGH:
+ 			if (max == 512)
+ 				break;
+-			/* conserve return statements */
+-		default:
+-			switch (max) {
+-			case 8: case 16: case 32: case 64:
++			goto done;
++		case USB_SPEED_FULL:
++			if (max == 8 || max == 16 || max == 32 || max == 64)
+ 				/* we'll fake any legal size */
+ 				break;
+-			default:
+-		case USB_SPEED_LOW:
+-				goto done;
+-			}
++			/* save a return statement */
++		default:
++			goto done;
+ 		}
+ 		break;
+ 	case USB_ENDPOINT_XFER_INT:
+@@ -894,13 +892,12 @@ static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
+ {
+ 	struct dummy	*dum = platform_get_drvdata(pdev);
+ 
+-	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++	dev_dbg (&pdev->dev, "%s\n", __func__);
+ 	spin_lock_irq (&dum->lock);
+ 	dum->udc_suspended = 1;
+ 	set_link_state (dum);
+ 	spin_unlock_irq (&dum->lock);
+ 
+-	pdev->dev.power.power_state = state;
+ 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+ }
+@@ -909,13 +906,12 @@ static int dummy_udc_resume (struct platform_device *pdev)
+ {
+ 	struct dummy	*dum = platform_get_drvdata(pdev);
+ 
+-	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++	dev_dbg (&pdev->dev, "%s\n", __func__);
+ 	spin_lock_irq (&dum->lock);
+ 	dum->udc_suspended = 0;
+ 	set_link_state (dum);
+ 	spin_unlock_irq (&dum->lock);
+ 
+-	pdev->dev.power.power_state = PMSG_ON;
+ 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ 	return 0;
+ }
+@@ -1711,7 +1707,7 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct dummy *dum = hcd_to_dummy (hcd);
+ 
+-	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
++	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+ 
+ 	spin_lock_irq (&dum->lock);
+ 	dum->rh_state = DUMMY_RH_SUSPENDED;
+@@ -1726,7 +1722,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
+ 	struct dummy *dum = hcd_to_dummy (hcd);
+ 	int rc = 0;
+ 
+-	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
++	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+ 
+ 	spin_lock_irq (&dum->lock);
+ 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+@@ -1900,7 +1896,7 @@ static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
+ 	struct dummy		*dum;
+ 	int			rc = 0;
+ 
+-	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++	dev_dbg (&pdev->dev, "%s\n", __func__);
+ 
+ 	hcd = platform_get_drvdata (pdev);
+ 	dum = hcd_to_dummy (hcd);
+@@ -1916,7 +1912,7 @@ static int dummy_hcd_resume (struct platform_device *pdev)
+ {
+ 	struct usb_hcd		*hcd;
+ 
+-	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++	dev_dbg (&pdev->dev, "%s\n", __func__);
+ 
+ 	hcd = platform_get_drvdata (pdev);
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+@@ -1937,69 +1933,57 @@ static struct platform_driver dummy_hcd_driver = {
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* These don't need to do anything because the pdev structures are
+- * statically allocated. */
+-static void
+-dummy_udc_release (struct device *dev) {}
+-
+-static void
+-dummy_hcd_release (struct device *dev) {}
+-
+-static struct platform_device		the_udc_pdev = {
+-	.name		= (char *) gadget_name,
+-	.id		= -1,
+-	.dev		= {
+-		.release	= dummy_udc_release,
+-	},
+-};
+-
+-static struct platform_device		the_hcd_pdev = {
+-	.name		= (char *) driver_name,
+-	.id		= -1,
+-	.dev		= {
+-		.release	= dummy_hcd_release,
+-	},
+-};
++static struct platform_device *the_udc_pdev;
++static struct platform_device *the_hcd_pdev;
+ 
+ static int __init init (void)
+ {
+-	int	retval;
++	int	retval = -ENOMEM;
+ 
+ 	if (usb_disabled ())
+ 		return -ENODEV;
+ 
+-	retval = platform_driver_register (&dummy_hcd_driver);
+-	if (retval < 0)
++	the_hcd_pdev = platform_device_alloc(driver_name, -1);
++	if (!the_hcd_pdev)
+ 		return retval;
++	the_udc_pdev = platform_device_alloc(gadget_name, -1);
++	if (!the_udc_pdev)
++		goto err_alloc_udc;
+ 
+-	retval = platform_driver_register (&dummy_udc_driver);
++	retval = platform_driver_register(&dummy_hcd_driver);
++	if (retval < 0)
++		goto err_register_hcd_driver;
++	retval = platform_driver_register(&dummy_udc_driver);
+ 	if (retval < 0)
+ 		goto err_register_udc_driver;
+ 
+-	retval = platform_device_register (&the_hcd_pdev);
++	retval = platform_device_add(the_hcd_pdev);
+ 	if (retval < 0)
+-		goto err_register_hcd;
+-
+-	retval = platform_device_register (&the_udc_pdev);
++		goto err_add_hcd;
++	retval = platform_device_add(the_udc_pdev);
+ 	if (retval < 0)
+-		goto err_register_udc;
++		goto err_add_udc;
+ 	return retval;
+ 
+-err_register_udc:
+-	platform_device_unregister (&the_hcd_pdev);
+-err_register_hcd:
+-	platform_driver_unregister (&dummy_udc_driver);
++err_add_udc:
++	platform_device_del(the_hcd_pdev);
++err_add_hcd:
++	platform_driver_unregister(&dummy_udc_driver);
+ err_register_udc_driver:
+-	platform_driver_unregister (&dummy_hcd_driver);
++	platform_driver_unregister(&dummy_hcd_driver);
++err_register_hcd_driver:
++	platform_device_put(the_udc_pdev);
++err_alloc_udc:
++	platform_device_put(the_hcd_pdev);
+ 	return retval;
+ }
+ module_init (init);
+ 
+ static void __exit cleanup (void)
+ {
+-	platform_device_unregister (&the_udc_pdev);
+-	platform_device_unregister (&the_hcd_pdev);
+-	platform_driver_unregister (&dummy_udc_driver);
+-	platform_driver_unregister (&dummy_hcd_driver);
++	platform_device_unregister(the_udc_pdev);
++	platform_device_unregister(the_hcd_pdev);
++	platform_driver_unregister(&dummy_udc_driver);
++	platform_driver_unregister(&dummy_hcd_driver);
+ }
+ module_exit (cleanup);
+diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
+index f9d0710..8bdad22 100644
+--- a/drivers/usb/gadget/epautoconf.c
++++ b/drivers/usb/gadget/epautoconf.c
+@@ -34,12 +34,12 @@
+ 
+ 
+ /* we must assign addresses for configurable endpoints (like net2280) */
+-static __devinitdata unsigned epnum;
++static __initdata unsigned epnum;
+ 
+ // #define MANY_ENDPOINTS
+ #ifdef MANY_ENDPOINTS
+ /* more than 15 configurable endpoints */
+-static __devinitdata unsigned in_epnum;
++static __initdata unsigned in_epnum;
+ #endif
+ 
+ 
+@@ -59,7 +59,7 @@ static __devinitdata unsigned in_epnum;
+  * NOTE:  each endpoint is unidirectional, as specified by its USB
+  * descriptor; and isn't specific to a configuration or altsetting.
+  */
+-static int __devinit
++static int __init
+ ep_matches (
+ 	struct usb_gadget		*gadget,
+ 	struct usb_ep			*ep,
+@@ -186,7 +186,7 @@ ep_matches (
+ 	return 1;
+ }
+ 
+-static struct usb_ep * __devinit
++static struct usb_ep * __init
+ find_ep (struct usb_gadget *gadget, const char *name)
+ {
+ 	struct usb_ep	*ep;
+@@ -228,7 +228,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
+  *
+  * On failure, this returns a null endpoint descriptor.
+  */
+-struct usb_ep * __devinit usb_ep_autoconfig (
++struct usb_ep * __init usb_ep_autoconfig (
+ 	struct usb_gadget		*gadget,
+ 	struct usb_endpoint_descriptor	*desc
+ )
+@@ -295,7 +295,7 @@ struct usb_ep * __devinit usb_ep_autoconfig (
+  * state such as ep->driver_data and the record of assigned endpoints
+  * used by usb_ep_autoconfig().
+  */
+-void __devinit usb_ep_autoconfig_reset (struct usb_gadget *gadget)
++void __init usb_ep_autoconfig_reset (struct usb_gadget *gadget)
+ {
+ 	struct usb_ep	*ep;
+ 
+diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
+index e998723..bb93bdd 100644
+--- a/drivers/usb/gadget/ether.c
++++ b/drivers/usb/gadget/ether.c
+@@ -1102,7 +1102,7 @@ static void eth_reset_config (struct eth_dev *dev)
+ 	if (dev->config == 0)
+ 		return;
+ 
+-	DEBUG (dev, "%s\n", __FUNCTION__);
++	DEBUG (dev, "%s\n", __func__);
+ 
+ 	netif_stop_queue (dev->net);
+ 	netif_carrier_off (dev->net);
+@@ -1263,7 +1263,7 @@ static void issue_start_status (struct eth_dev *dev)
+ 	struct usb_cdc_notification	*event;
+ 	int				value;
+ 
+-	DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
++	DEBUG (dev, "%s, flush old status first\n", __func__);
+ 
+ 	/* flush old status
+ 	 *
+@@ -1329,7 +1329,7 @@ static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
+ 	spin_lock(&dev->lock);
+ 	status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
+ 	if (status < 0)
+-		ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
++		ERROR(dev, "%s: rndis parse error %d\n", __func__, status);
+ 	spin_unlock(&dev->lock);
+ }
+ 
+@@ -2113,7 +2113,7 @@ static int rndis_control_ack (struct net_device *net)
+ 
+ static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
+ {
+-	DEBUG (dev, "%s\n", __FUNCTION__);
++	DEBUG (dev, "%s\n", __func__);
+ 
+ 	/* fill the rx queue */
+ 	rx_fill (dev, gfp_flags);
+@@ -2133,7 +2133,7 @@ static int eth_open (struct net_device *net)
+ {
+ 	struct eth_dev		*dev = netdev_priv(net);
+ 
+-	DEBUG (dev, "%s\n", __FUNCTION__);
++	DEBUG (dev, "%s\n", __func__);
+ 	if (netif_carrier_ok (dev->net))
+ 		eth_start (dev, GFP_KERNEL);
+ 	return 0;
+@@ -2143,7 +2143,7 @@ static int eth_stop (struct net_device *net)
+ {
+ 	struct eth_dev		*dev = netdev_priv(net);
+ 
+-	VDEBUG (dev, "%s\n", __FUNCTION__);
++	VDEBUG (dev, "%s\n", __func__);
+ 	netif_stop_queue (net);
+ 
+ 	DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
+@@ -2229,7 +2229,7 @@ eth_unbind (struct usb_gadget *gadget)
+ 	set_gadget_data (gadget, NULL);
+ }
+ 
+-static u8 __devinit nibble (unsigned char c)
++static u8 __init nibble (unsigned char c)
+ {
+ 	if (likely (isdigit (c)))
+ 		return c - '0';
+@@ -2239,7 +2239,7 @@ static u8 __devinit nibble (unsigned char c)
+ 	return 0;
+ }
+ 
+-static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
++static int __init get_ether_addr(const char *str, u8 *dev_addr)
+ {
+ 	if (str) {
+ 		unsigned	i;
+@@ -2260,7 +2260,7 @@ static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
+ 	return 1;
+ }
+ 
+-static int __devinit
++static int __init
+ eth_bind (struct usb_gadget *gadget)
+ {
+ 	struct eth_dev		*dev;
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 017a196..bf3f946 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -644,7 +644,7 @@ struct fsg_dev {
+ 
+ 	unsigned long		atomic_bitflags;
+ #define REGISTERED		0
+-#define CLEAR_BULK_HALTS	1
++#define IGNORE_BULK_OUT		1
+ #define SUSPENDED		2
+ 
+ 	struct usb_ep		*bulk_in;
+@@ -1104,7 +1104,7 @@ static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
+ 	if (req->actual > 0)
+ 		dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
+ 	if (req->status || req->actual != req->length)
+-		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
++		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+ 				req->status, req->actual, req->length);
+ 	if (req->status == -ECONNRESET)		// Request was cancelled
+ 		usb_ep_fifo_flush(ep);
+@@ -1125,7 +1125,7 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
+ 	struct fsg_buffhd	*bh = req->context;
+ 
+ 	if (req->status || req->actual != req->length)
+-		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
++		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+ 				req->status, req->actual, req->length);
+ 	if (req->status == -ECONNRESET)		// Request was cancelled
+ 		usb_ep_fifo_flush(ep);
+@@ -1146,7 +1146,7 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
+ 
+ 	dump_msg(fsg, "bulk-out", req->buf, req->actual);
+ 	if (req->status || req->actual != bh->bulk_out_intended_length)
+-		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
++		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+ 				req->status, req->actual,
+ 				bh->bulk_out_intended_length);
+ 	if (req->status == -ECONNRESET)		// Request was cancelled
+@@ -1169,7 +1169,7 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
+ 	struct fsg_buffhd	*bh = req->context;
+ 
+ 	if (req->status || req->actual != req->length)
+-		DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
++		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+ 				req->status, req->actual, req->length);
+ 	if (req->status == -ECONNRESET)		// Request was cancelled
+ 		usb_ep_fifo_flush(ep);
+@@ -2936,8 +2936,8 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 	struct usb_request	*req = bh->outreq;
+ 	struct bulk_cb_wrap	*cbw = req->buf;
+ 
+-	/* Was this a real packet? */
+-	if (req->status)
++	/* Was this a real packet?  Should it be ignored? */
++	if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+ 		return -EINVAL;
+ 
+ 	/* Is the CBW valid? */
+@@ -2948,13 +2948,17 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ 				req->actual,
+ 				le32_to_cpu(cbw->Signature));
+ 
+-		/* The Bulk-only spec says we MUST stall the bulk pipes!
+-		 * If we want to avoid stalls, set a flag so that we will
+-		 * clear the endpoint halts at the next reset. */
+-		if (!mod_data.can_stall)
+-			set_bit(CLEAR_BULK_HALTS, &fsg->atomic_bitflags);
+-		fsg_set_halt(fsg, fsg->bulk_out);
++		/* The Bulk-only spec says we MUST stall the IN endpoint
++		 * (6.6.1), so it's unavoidable.  It also says we must
++		 * retain this state until the next reset, but there's
++		 * no way to tell the controller driver it should ignore
++		 * Clear-Feature(HALT) requests.
++		 *
++		 * We aren't required to halt the OUT endpoint; instead
++		 * we can simply accept and discard any data received
++		 * until the next reset. */
+ 		halt_bulk_in_endpoint(fsg);
++		set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -3140,6 +3144,7 @@ reset:
+ 		goto reset;
+ 	fsg->bulk_out_enabled = 1;
+ 	fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
++	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+ 
+ 	if (transport_is_cbi()) {
+ 		d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc);
+@@ -3321,11 +3326,8 @@ static void handle_exception(struct fsg_dev *fsg)
+ 		/* In case we were forced against our will to halt a
+ 		 * bulk endpoint, clear the halt now.  (The SuperH UDC
+ 		 * requires this.) */
+-		if (test_and_clear_bit(CLEAR_BULK_HALTS,
+-				&fsg->atomic_bitflags)) {
++		if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+ 			usb_ep_clear_halt(fsg->bulk_in);
+-			usb_ep_clear_halt(fsg->bulk_out);
+-		}
+ 
+ 		if (transport_is_bbb()) {
+ 			if (fsg->ep0_req_tag == exception_req_tag)
+diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
+index 254012a..651b827 100644
+--- a/drivers/usb/gadget/fsl_usb2_udc.c
++++ b/drivers/usb/gadget/fsl_usb2_udc.c
+@@ -773,11 +773,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ 	/* catch various bogus parameters */
+ 	if (!_req || !req->req.complete || !req->req.buf
+ 			|| !list_empty(&req->queue)) {
+-		VDBG("%s, bad params\n", __FUNCTION__);
++		VDBG("%s, bad params\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (unlikely(!_ep || !ep->desc)) {
+-		VDBG("%s, bad ep\n", __FUNCTION__);
++		VDBG("%s, bad ep\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
+index 9fb0b1e..98b1483 100644
+--- a/drivers/usb/gadget/fsl_usb2_udc.h
++++ b/drivers/usb/gadget/fsl_usb2_udc.h
+@@ -512,7 +512,7 @@ struct fsl_udc {
+ 
+ #ifdef DEBUG
+ #define DBG(fmt, args...) 	printk(KERN_DEBUG "[%s]  " fmt "\n", \
+-				__FUNCTION__, ## args)
++				__func__, ## args)
+ #else
+ #define DBG(fmt, args...)	do{}while(0)
+ #endif
+diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
+index 5b42ccd..ff3a851 100644
+--- a/drivers/usb/gadget/gmidi.c
++++ b/drivers/usb/gadget/gmidi.c
+@@ -1149,7 +1149,7 @@ fail:
+ /*
+  * Creates an output endpoint, and initializes output ports.
+  */
+-static int __devinit 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;
+diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
+index d3e7025..64a592c 100644
+--- a/drivers/usb/gadget/goku_udc.c
++++ b/drivers/usb/gadget/goku_udc.c
+@@ -692,7 +692,7 @@ static void abort_dma(struct goku_ep *ep, int status)
+ 	req->req.actual = (curr - req->req.dma) + 1;
+ 	req->req.status = status;
+ 
+-	VDBG(ep->dev, "%s %s %s %d/%d\n", __FUNCTION__, ep->ep.name,
++	VDBG(ep->dev, "%s %s %s %d/%d\n", __func__, ep->ep.name,
+ 		ep->is_in ? "IN" : "OUT",
+ 		req->req.actual, req->req.length);
+ 
+@@ -826,7 +826,7 @@ static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+ 	if (dev->ep0state == EP0_SUSPEND)
+ 		return -EBUSY;
+ 
+-	VDBG(dev, "%s %s %s %s %p\n", __FUNCTION__, _ep->name,
++	VDBG(dev, "%s %s %s %s %p\n", __func__, _ep->name,
+ 		ep->is_in ? "IN" : "OUT",
+ 		ep->dma ? "dma" : "pio",
+ 		_req);
+@@ -898,7 +898,7 @@ static int goku_set_halt(struct usb_ep *_ep, int value)
+ 
+ 	/* don't change EPxSTATUS_EP_INVALID to READY */
+ 	} else if (!ep->desc) {
+-		DBG(ep->dev, "%s %s inactive?\n", __FUNCTION__, ep->ep.name);
++		DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -940,7 +940,7 @@ static int goku_fifo_status(struct usb_ep *_ep)
+ 	regs = ep->dev->regs;
+ 	size = readl(&regs->EPxSizeLA[ep->num]) & DATASIZE;
+ 	size += readl(&regs->EPxSizeLB[ep->num]) & DATASIZE;
+-	VDBG(ep->dev, "%s %s %u\n", __FUNCTION__, ep->ep.name, size);
++	VDBG(ep->dev, "%s %s %u\n", __func__, ep->ep.name, size);
+ 	return size;
+ }
+ 
+@@ -953,11 +953,11 @@ static void goku_fifo_flush(struct usb_ep *_ep)
+ 	if (!_ep)
+ 		return;
+ 	ep = container_of(_ep, struct goku_ep, ep);
+-	VDBG(ep->dev, "%s %s\n", __FUNCTION__, ep->ep.name);
++	VDBG(ep->dev, "%s %s\n", __func__, ep->ep.name);
+ 
+ 	/* don't change EPxSTATUS_EP_INVALID to READY */
+ 	if (!ep->desc && ep->num != 0) {
+-		DBG(ep->dev, "%s %s inactive?\n", __FUNCTION__, ep->ep.name);
++		DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
+ 		return;
+ 	}
+ 
+@@ -1286,7 +1286,7 @@ static void ep0_start(struct goku_udc *dev)
+ 	struct goku_udc_regs __iomem	*regs = dev->regs;
+ 	unsigned			i;
+ 
+-	VDBG(dev, "%s\n", __FUNCTION__);
++	VDBG(dev, "%s\n", __func__);
+ 
+ 	udc_reset(dev);
+ 	udc_reinit (dev);
+@@ -1322,7 +1322,7 @@ static void udc_enable(struct goku_udc *dev)
+ 	if (readl(&dev->regs->power_detect) & PW_DETECT)
+ 		ep0_start(dev);
+ 	else {
+-		DBG(dev, "%s\n", __FUNCTION__);
++		DBG(dev, "%s\n", __func__);
+ 		dev->int_enable = INT_PWRDETECT;
+ 		writel(dev->int_enable, &dev->regs->int_enable);
+ 	}
+@@ -1387,7 +1387,7 @@ stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
+ {
+ 	unsigned	i;
+ 
+-	DBG (dev, "%s\n", __FUNCTION__);
++	DBG (dev, "%s\n", __func__);
+ 
+ 	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+ 		driver = NULL;
+@@ -1726,7 +1726,7 @@ static void goku_remove(struct pci_dev *pdev)
+ {
+ 	struct goku_udc		*dev = pci_get_drvdata(pdev);
+ 
+-	DBG(dev, "%s\n", __FUNCTION__);
++	DBG(dev, "%s\n", __func__);
+ 
+ 	BUG_ON(dev->driver);
+ 
+diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
+index 0a6feaf..69b0a27 100644
+--- a/drivers/usb/gadget/inode.c
++++ b/drivers/usb/gadget/inode.c
+@@ -1107,13 +1107,13 @@ scan:
+ 
+ 	switch (state) {
+ 	default:
+-		DBG (dev, "fail %s, state %d\n", __FUNCTION__, state);
++		DBG (dev, "fail %s, state %d\n", __func__, state);
+ 		retval = -ESRCH;
+ 		break;
+ 	case STATE_DEV_UNCONNECTED:
+ 	case STATE_DEV_CONNECTED:
+ 		spin_unlock_irq (&dev->lock);
+-		DBG (dev, "%s wait\n", __FUNCTION__);
++		DBG (dev, "%s wait\n", __func__);
+ 
+ 		/* wait for events */
+ 		retval = wait_event_interruptible (dev->wait,
+@@ -1222,7 +1222,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 			DBG(dev, "bogus ep0out stall!\n");
+ 		}
+ 	} else
+-		DBG (dev, "fail %s, state %d\n", __FUNCTION__, dev->state);
++		DBG (dev, "fail %s, state %d\n", __func__, dev->state);
+ 
+ 	spin_unlock_irq (&dev->lock);
+ 	return retval;
+@@ -1233,7 +1233,7 @@ ep0_fasync (int f, struct file *fd, int on)
+ {
+ 	struct dev_data		*dev = fd->private_data;
+ 	// caller must F_SETOWN before signal delivery happens
+-	VDEBUG (dev, "%s %s\n", __FUNCTION__, on ? "on" : "off");
++	VDEBUG (dev, "%s %s\n", __func__, on ? "on" : "off");
+ 	return fasync_helper (f, fd, on, &dev->fasync);
+ }
+ 
+@@ -1575,7 +1575,7 @@ static void destroy_ep_files (struct dev_data *dev)
+ {
+ 	struct list_head	*entry, *tmp;
+ 
+-	DBG (dev, "%s %d\n", __FUNCTION__, dev->state);
++	DBG (dev, "%s %d\n", __func__, dev->state);
+ 
+ 	/* dev->state must prevent interference */
+ restart:
+@@ -1662,7 +1662,7 @@ enomem1:
+ 	put_dev (dev);
+ 	kfree (data);
+ enomem0:
+-	DBG (dev, "%s enomem\n", __FUNCTION__);
++	DBG (dev, "%s enomem\n", __func__);
+ 	destroy_ep_files (dev);
+ 	return -ENOMEM;
+ }
+@@ -1672,7 +1672,7 @@ gadgetfs_unbind (struct usb_gadget *gadget)
+ {
+ 	struct dev_data		*dev = get_gadget_data (gadget);
+ 
+-	DBG (dev, "%s\n", __FUNCTION__);
++	DBG (dev, "%s\n", __func__);
+ 
+ 	spin_lock_irq (&dev->lock);
+ 	dev->state = STATE_DEV_UNBOUND;
+@@ -1685,7 +1685,7 @@ gadgetfs_unbind (struct usb_gadget *gadget)
+ 	/* we've already been disconnected ... no i/o is active */
+ 	if (dev->req)
+ 		usb_ep_free_request (gadget->ep0, dev->req);
+-	DBG (dev, "%s done\n", __FUNCTION__);
++	DBG (dev, "%s done\n", __func__);
+ 	put_dev (dev);
+ }
+ 
+@@ -1933,7 +1933,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 
+ fail:
+ 	spin_unlock_irq (&dev->lock);
+-	pr_debug ("%s: %s fail %Zd, %p\n", shortname, __FUNCTION__, value, dev);
++	pr_debug ("%s: %s fail %Zd, %p\n", shortname, __func__, value, dev);
+ 	kfree (dev->buf);
+ 	dev->buf = NULL;
+ 	return value;
+diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
+index 078f724..825abd2 100644
+--- a/drivers/usb/gadget/lh7a40x_udc.c
++++ b/drivers/usb/gadget/lh7a40x_udc.c
+@@ -253,7 +253,7 @@ udc_proc_read(char *page, char **start, off_t off, int count,
+  */
+ static void udc_disable(struct lh7a40x_udc *dev)
+ {
+-	DEBUG("%s, %p\n", __FUNCTION__, dev);
++	DEBUG("%s, %p\n", __func__, dev);
+ 
+ 	udc_set_address(dev, 0);
+ 
+@@ -285,7 +285,7 @@ static void udc_reinit(struct lh7a40x_udc *dev)
+ {
+ 	u32 i;
+ 
+-	DEBUG("%s, %p\n", __FUNCTION__, dev);
++	DEBUG("%s, %p\n", __func__, dev);
+ 
+ 	/* device/ep0 records init */
+ 	INIT_LIST_HEAD(&dev->gadget.ep_list);
+@@ -318,7 +318,7 @@ static void udc_enable(struct lh7a40x_udc *dev)
+ {
+ 	int ep;
+ 
+-	DEBUG("%s, %p\n", __FUNCTION__, dev);
++	DEBUG("%s, %p\n", __func__, dev);
+ 
+ 	dev->gadget.speed = USB_SPEED_UNKNOWN;
+ 
+@@ -412,7 +412,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+ 	struct lh7a40x_udc *dev = the_controller;
+ 	int retval;
+ 
+-	DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
++	DEBUG("%s: %s\n", __func__, driver->driver.name);
+ 
+ 	if (!driver
+ 			|| driver->speed != USB_SPEED_FULL
+@@ -521,7 +521,7 @@ static int write_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ 			is_short = unlikely(max < ep_maxpacket(ep));
+ 		}
+ 
+-		DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__,
++		DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __func__,
+ 		      ep->ep.name, count,
+ 		      is_last ? "/L" : "", is_short ? "/S" : "",
+ 		      req->req.length - req->req.actual, req);
+@@ -555,7 +555,7 @@ static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ 	/* make sure there's a packet in the FIFO. */
+ 	csr = usb_read(ep->csr1);
+ 	if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY)) {
+-		DEBUG("%s: Packet NOT ready!\n", __FUNCTION__);
++		DEBUG("%s: Packet NOT ready!\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -614,7 +614,7 @@ static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
+ 	unsigned int stopped = ep->stopped;
+ 	u32 index;
+ 
+-	DEBUG("%s, %p\n", __FUNCTION__, ep);
++	DEBUG("%s, %p\n", __func__, ep);
+ 	list_del_init(&req->queue);
+ 
+ 	if (likely(req->req.status == -EINPROGRESS))
+@@ -644,7 +644,7 @@ static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
+ /** Enable EP interrupt */
+ static void pio_irq_enable(int ep)
+ {
+-	DEBUG("%s: %d\n", __FUNCTION__, ep);
++	DEBUG("%s: %d\n", __func__, ep);
+ 
+ 	switch (ep) {
+ 	case 1:
+@@ -665,7 +665,7 @@ static void pio_irq_enable(int ep)
+ /** Disable EP interrupt */
+ static void pio_irq_disable(int ep)
+ {
+-	DEBUG("%s: %d\n", __FUNCTION__, ep);
++	DEBUG("%s: %d\n", __func__, ep);
+ 
+ 	switch (ep) {
+ 	case 1:
+@@ -690,7 +690,7 @@ void nuke(struct lh7a40x_ep *ep, int status)
+ {
+ 	struct lh7a40x_request *req;
+ 
+-	DEBUG("%s, %p\n", __FUNCTION__, ep);
++	DEBUG("%s, %p\n", __func__, ep);
+ 
+ 	/* Flush FIFO */
+ 	flush(ep);
+@@ -734,7 +734,7 @@ static void flush_all(struct lh7a40x_udc *dev)
+  */
+ static void flush(struct lh7a40x_ep *ep)
+ {
+-	DEBUG("%s, %p\n", __FUNCTION__, ep);
++	DEBUG("%s, %p\n", __func__, ep);
+ 
+ 	switch (ep->ep_type) {
+ 	case ep_control:
+@@ -766,7 +766,7 @@ static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ 	usb_set_index(ep_idx);
+ 
+ 	csr = usb_read(ep->csr1);
+-	DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr);
++	DEBUG("%s: %d, csr %x\n", __func__, ep_idx, csr);
+ 
+ 	if (csr & USB_IN_CSR1_SENT_STALL) {
+ 		DEBUG("USB_IN_CSR1_SENT_STALL\n");
+@@ -776,7 +776,7 @@ static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ 	}
+ 
+ 	if (!ep->desc) {
+-		DEBUG("%s: NO EP DESC\n", __FUNCTION__);
++		DEBUG("%s: NO EP DESC\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -802,7 +802,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ 	struct lh7a40x_ep *ep = &dev->ep[ep_idx];
+ 	struct lh7a40x_request *req;
+ 
+-	DEBUG("%s: %d\n", __FUNCTION__, ep_idx);
++	DEBUG("%s: %d\n", __func__, ep_idx);
+ 
+ 	usb_set_index(ep_idx);
+ 
+@@ -814,11 +814,11 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ 			usb_read(ep->
+ 				 csr1)) & (USB_OUT_CSR1_OUT_PKT_RDY |
+ 					   USB_OUT_CSR1_SENT_STALL)) {
+-			DEBUG("%s: %x\n", __FUNCTION__, csr);
++			DEBUG("%s: %x\n", __func__, csr);
+ 
+ 			if (csr & USB_OUT_CSR1_SENT_STALL) {
+ 				DEBUG("%s: stall sent, flush fifo\n",
+-				      __FUNCTION__);
++				      __func__);
+ 				/* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */
+ 				flush(ep);
+ 			} else if (csr & USB_OUT_CSR1_OUT_PKT_RDY) {
+@@ -832,7 +832,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ 
+ 				if (!req) {
+ 					printk("%s: NULL REQ %d\n",
+-					       __FUNCTION__, ep_idx);
++					       __func__, ep_idx);
+ 					flush(ep);
+ 					break;
+ 				} else {
+@@ -844,7 +844,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ 
+ 	} else {
+ 		/* Throw packet away.. */
+-		printk("%s: No descriptor?!?\n", __FUNCTION__);
++		printk("%s: No descriptor?!?\n", __func__);
+ 		flush(ep);
+ 	}
+ }
+@@ -886,7 +886,7 @@ static void lh7a40x_reset_intr(struct lh7a40x_udc *dev)
+ #if 0				/* def CONFIG_ARCH_LH7A404 */
+ 	/* Does not work always... */
+ 
+-	DEBUG("%s: %d\n", __FUNCTION__, dev->usb_address);
++	DEBUG("%s: %d\n", __func__, dev->usb_address);
+ 
+ 	if (!dev->usb_address) {
+ 		/*usb_set(USB_RESET_IO, USB_RESET);
+@@ -936,7 +936,7 @@ static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev)
+ 		if (!intr_out && !intr_in && !intr_int)
+ 			break;
+ 
+-		DEBUG("%s (on state %s)\n", __FUNCTION__,
++		DEBUG("%s (on state %s)\n", __func__,
+ 		      state_names[dev->ep0state]);
+ 		DEBUG("intr_out = %x\n", intr_out);
+ 		DEBUG("intr_in  = %x\n", intr_in);
+@@ -1016,14 +1016,14 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
+ 	struct lh7a40x_udc *dev;
+ 	unsigned long flags;
+ 
+-	DEBUG("%s, %p\n", __FUNCTION__, _ep);
++	DEBUG("%s, %p\n", __func__, _ep);
+ 
+ 	ep = container_of(_ep, struct lh7a40x_ep, ep);
+ 	if (!_ep || !desc || ep->desc || _ep->name == ep0name
+ 	    || desc->bDescriptorType != USB_DT_ENDPOINT
+ 	    || ep->bEndpointAddress != desc->bEndpointAddress
+ 	    || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) {
+-		DEBUG("%s, bad ep or descriptor\n", __FUNCTION__);
++		DEBUG("%s, bad ep or descriptor\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -1031,7 +1031,7 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
+ 	if (ep->bmAttributes != desc->bmAttributes
+ 	    && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+ 	    && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+-		DEBUG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
++		DEBUG("%s, %s type mismatch\n", __func__, _ep->name);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -1039,13 +1039,13 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
+ 	if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+ 	     && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep))
+ 	    || !desc->wMaxPacketSize) {
+-		DEBUG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
++		DEBUG("%s, bad %s maxpacket\n", __func__, _ep->name);
+ 		return -ERANGE;
+ 	}
+ 
+ 	dev = ep->dev;
+ 	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+-		DEBUG("%s, bogus device state\n", __FUNCTION__);
++		DEBUG("%s, bogus device state\n", __func__);
+ 		return -ESHUTDOWN;
+ 	}
+ 
+@@ -1061,7 +1061,7 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
+ 	/* Reset halt state (does flush) */
+ 	lh7a40x_set_halt(_ep, 0);
+ 
+-	DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name);
++	DEBUG("%s: enabled %s\n", __func__, _ep->name);
+ 	return 0;
+ }
+ 
+@@ -1073,11 +1073,11 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
+ 	struct lh7a40x_ep *ep;
+ 	unsigned long flags;
+ 
+-	DEBUG("%s, %p\n", __FUNCTION__, _ep);
++	DEBUG("%s, %p\n", __func__, _ep);
+ 
+ 	ep = container_of(_ep, struct lh7a40x_ep, ep);
+ 	if (!_ep || !ep->desc) {
+-		DEBUG("%s, %s not enabled\n", __FUNCTION__,
++		DEBUG("%s, %s not enabled\n", __func__,
+ 		      _ep ? ep->ep.name : NULL);
+ 		return -EINVAL;
+ 	}
+@@ -1097,7 +1097,7 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
+ 
+ 	spin_unlock_irqrestore(&ep->dev->lock, flags);
+ 
+-	DEBUG("%s: disabled %s\n", __FUNCTION__, _ep->name);
++	DEBUG("%s: disabled %s\n", __func__, _ep->name);
+ 	return 0;
+ }
+ 
+@@ -1106,7 +1106,7 @@ static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
+ {
+ 	struct lh7a40x_request *req;
+ 
+-	DEBUG("%s, %p\n", __FUNCTION__, ep);
++	DEBUG("%s, %p\n", __func__, ep);
+ 
+ 	req = kzalloc(sizeof(*req), gfp_flags);
+ 	if (!req)
+@@ -1121,7 +1121,7 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
+ {
+ 	struct lh7a40x_request *req;
+ 
+-	DEBUG("%s, %p\n", __FUNCTION__, ep);
++	DEBUG("%s, %p\n", __func__, ep);
+ 
+ 	req = container_of(_req, struct lh7a40x_request, req);
+ 	WARN_ON(!list_empty(&req->queue));
+@@ -1140,25 +1140,25 @@ static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
+ 	struct lh7a40x_udc *dev;
+ 	unsigned long flags;
+ 
+-	DEBUG("\n\n\n%s, %p\n", __FUNCTION__, _ep);
++	DEBUG("\n\n\n%s, %p\n", __func__, _ep);
+ 
+ 	req = container_of(_req, struct lh7a40x_request, req);
+ 	if (unlikely
+ 	    (!_req || !_req->complete || !_req->buf
+ 	     || !list_empty(&req->queue))) {
+-		DEBUG("%s, bad params\n", __FUNCTION__);
++		DEBUG("%s, bad params\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	ep = container_of(_ep, struct lh7a40x_ep, ep);
+ 	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+-		DEBUG("%s, bad ep\n", __FUNCTION__);
++		DEBUG("%s, bad ep\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	dev = ep->dev;
+ 	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+-		DEBUG("%s, bogus device state %p\n", __FUNCTION__, dev->driver);
++		DEBUG("%s, bogus device state %p\n", __func__, dev->driver);
+ 		return -ESHUTDOWN;
+ 	}
+ 
+@@ -1218,7 +1218,7 @@ static int lh7a40x_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+ 	struct lh7a40x_request *req;
+ 	unsigned long flags;
+ 
+-	DEBUG("%s, %p\n", __FUNCTION__, _ep);
++	DEBUG("%s, %p\n", __func__, _ep);
+ 
+ 	ep = container_of(_ep, struct lh7a40x_ep, ep);
+ 	if (!_ep || ep->ep.name == ep0name)
+@@ -1253,13 +1253,13 @@ static int lh7a40x_set_halt(struct usb_ep *_ep, int value)
+ 
+ 	ep = container_of(_ep, struct lh7a40x_ep, ep);
+ 	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+-		DEBUG("%s, bad ep\n", __FUNCTION__);
++		DEBUG("%s, bad ep\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	usb_set_index(ep_index(ep));
+ 
+-	DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value);
++	DEBUG("%s, ep %d, val %d\n", __func__, ep_index(ep), value);
+ 
+ 	spin_lock_irqsave(&ep->dev->lock, flags);
+ 
+@@ -1325,11 +1325,11 @@ static int lh7a40x_fifo_status(struct usb_ep *_ep)
+ 
+ 	ep = container_of(_ep, struct lh7a40x_ep, ep);
+ 	if (!_ep) {
+-		DEBUG("%s, bad ep\n", __FUNCTION__);
++		DEBUG("%s, bad ep\n", __func__);
+ 		return -ENODEV;
+ 	}
+ 
+-	DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep));
++	DEBUG("%s, %d\n", __func__, ep_index(ep));
+ 
+ 	/* LPD can't report unclaimed bytes from IN fifos */
+ 	if (ep_is_in(ep))
+@@ -1355,7 +1355,7 @@ static void lh7a40x_fifo_flush(struct usb_ep *_ep)
+ 
+ 	ep = container_of(_ep, struct lh7a40x_ep, ep);
+ 	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+-		DEBUG("%s, bad ep\n", __FUNCTION__);
++		DEBUG("%s, bad ep\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -1376,7 +1376,7 @@ static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ 
+ 	max = ep_maxpacket(ep);
+ 
+-	DEBUG_EP0("%s\n", __FUNCTION__);
++	DEBUG_EP0("%s\n", __func__);
+ 
+ 	count = write_packet(ep, req, max);
+ 
+@@ -1390,7 +1390,7 @@ static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ 			is_last = 1;
+ 	}
+ 
+-	DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__,
++	DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __func__,
+ 		  ep->ep.name, count,
+ 		  is_last ? "/L" : "", req->req.length - req->req.actual, req);
+ 
+@@ -1434,7 +1434,7 @@ static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ 	unsigned bufferspace, count, is_short;
+ 	volatile u32 *fifo = (volatile u32 *)ep->fifo;
+ 
+-	DEBUG_EP0("%s\n", __FUNCTION__);
++	DEBUG_EP0("%s\n", __func__);
+ 
+ 	csr = usb_read(USB_EP0_CSR);
+ 	if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY))
+@@ -1492,7 +1492,7 @@ static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+  */
+ static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address)
+ {
+-	DEBUG_EP0("%s: %d\n", __FUNCTION__, address);
++	DEBUG_EP0("%s: %d\n", __func__, address);
+ 	/* c.f. 15.1.2.2 Table 15-4 address will be used after DATA_END is set */
+ 	dev->usb_address = address;
+ 	usb_set((address & USB_FA_FUNCTION_ADDR), USB_FA);
+@@ -1514,7 +1514,7 @@ static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr)
+ 	struct lh7a40x_ep *ep = &dev->ep[0];
+ 	int ret;
+ 
+-	DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
++	DEBUG_EP0("%s: %x\n", __func__, csr);
+ 
+ 	if (list_empty(&ep->queue))
+ 		req = 0;
+@@ -1533,13 +1533,13 @@ static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr)
+ 		if (ret) {
+ 			/* Done! */
+ 			DEBUG_EP0("%s: finished, waiting for status\n",
+-				  __FUNCTION__);
++				  __func__);
+ 
+ 			usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
+ 			dev->ep0state = WAIT_FOR_SETUP;
+ 		} else {
+ 			/* Not done yet.. */
+-			DEBUG_EP0("%s: not finished\n", __FUNCTION__);
++			DEBUG_EP0("%s: not finished\n", __func__);
+ 			usb_set(EP0_CLR_OUT, USB_EP0_CSR);
+ 		}
+ 	} else {
+@@ -1556,7 +1556,7 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
+ 	struct lh7a40x_ep *ep = &dev->ep[0];
+ 	int ret, need_zlp = 0;
+ 
+-	DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
++	DEBUG_EP0("%s: %x\n", __func__, csr);
+ 
+ 	if (list_empty(&ep->queue))
+ 		req = 0;
+@@ -1564,7 +1564,7 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
+ 		req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+ 
+ 	if (!req) {
+-		DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__);
++		DEBUG_EP0("%s: NULL REQ\n", __func__);
+ 		return 0;
+ 	}
+ 
+@@ -1585,17 +1585,17 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
+ 
+ 	if (ret == 1 && !need_zlp) {
+ 		/* Last packet */
+-		DEBUG_EP0("%s: finished, waiting for status\n", __FUNCTION__);
++		DEBUG_EP0("%s: finished, waiting for status\n", __func__);
+ 
+ 		usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+ 		dev->ep0state = WAIT_FOR_SETUP;
+ 	} else {
+-		DEBUG_EP0("%s: not finished\n", __FUNCTION__);
++		DEBUG_EP0("%s: not finished\n", __func__);
+ 		usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
+ 	}
+ 
+ 	if (need_zlp) {
+-		DEBUG_EP0("%s: Need ZLP!\n", __FUNCTION__);
++		DEBUG_EP0("%s: Need ZLP!\n", __func__);
+ 		usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
+ 		dev->ep0state = DATA_STATE_NEED_ZLP;
+ 	}
+@@ -1694,7 +1694,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
+ 	struct usb_ctrlrequest ctrl;
+ 	int i, bytes, is_in;
+ 
+-	DEBUG_SETUP("%s: %x\n", __FUNCTION__, csr);
++	DEBUG_SETUP("%s: %x\n", __func__, csr);
+ 
+ 	/* Nuke all previous transfers */
+ 	nuke(ep, -EPROTO);
+@@ -1799,7 +1799,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
+  */
+ static void lh7a40x_ep0_in_zlp(struct lh7a40x_udc *dev, u32 csr)
+ {
+-	DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
++	DEBUG_EP0("%s: %x\n", __func__, csr);
+ 
+ 	/* c.f. Table 15-14 */
+ 	usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+@@ -1818,7 +1818,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ 	usb_set_index(0);
+  	csr = usb_read(USB_EP0_CSR);
+ 
+-	DEBUG_EP0("%s: csr = %x\n", __FUNCTION__, csr);
++	DEBUG_EP0("%s: csr = %x\n", __func__, csr);
+ 
+ 	/*
+ 	 * For overview of what we should be doing see c.f. Chapter 18.1.2.4
+@@ -1832,7 +1832,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ 	 *      - clear the SENT_STALL bit
+ 	 */
+ 	if (csr & EP0_SENT_STALL) {
+-		DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __FUNCTION__, csr);
++		DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __func__, csr);
+ 		usb_clear((EP0_SENT_STALL | EP0_SEND_STALL), USB_EP0_CSR);
+ 		nuke(ep, -ECONNABORTED);
+ 		dev->ep0state = WAIT_FOR_SETUP;
+@@ -1849,7 +1849,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ 	 */
+ 	if (!(csr & (EP0_IN_PKT_RDY | EP0_OUT_PKT_RDY))) {
+ 		DEBUG_EP0("%s: IN_PKT_RDY and OUT_PKT_RDY are clear\n",
+-			  __FUNCTION__);
++			  __func__);
+ 
+ 		switch (dev->ep0state) {
+ 		case DATA_STATE_XMIT:
+@@ -1877,7 +1877,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ 	 *      - set SERVICED_SETUP_END_BIT
+ 	 */
+ 	if (csr & EP0_SETUP_END) {
+-		DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __FUNCTION__, csr);
++		DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __func__, csr);
+ 
+ 		usb_set(EP0_CLR_SETUP_END, USB_EP0_CSR);
+ 
+@@ -1896,7 +1896,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ 	 */
+ 	if (csr & EP0_OUT_PKT_RDY) {
+ 
+-		DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __FUNCTION__,
++		DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __func__,
+ 			  csr);
+ 
+ 		switch (dev->ep0state) {
+@@ -1926,7 +1926,7 @@ static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep)
+ 	usb_set_index(0);
+ 	csr = usb_read(USB_EP0_CSR);
+ 
+-	DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
++	DEBUG_EP0("%s: %x\n", __func__, csr);
+ 
+ 	/* Clear "out packet ready" */
+ 	usb_set(EP0_CLR_OUT, USB_EP0_CSR);
+@@ -1949,7 +1949,7 @@ static int lh7a40x_udc_get_frame(struct usb_gadget *_gadget)
+ {
+ 	u32 frame1 = usb_read(USB_FRM_NUM1);	/* Least significant 8 bits */
+ 	u32 frame2 = usb_read(USB_FRM_NUM2);	/* Most significant 3 bits */
+-	DEBUG("%s, %p\n", __FUNCTION__, _gadget);
++	DEBUG("%s, %p\n", __func__, _gadget);
+ 	return ((frame2 & 0x07) << 8) | (frame1 & 0xff);
+ }
+ 
+@@ -1970,7 +1970,7 @@ static const struct usb_gadget_ops lh7a40x_udc_ops = {
+ 
+ static void nop_release(struct device *dev)
+ {
+-	DEBUG("%s %s\n", __FUNCTION__, dev->bus_id);
++	DEBUG("%s %s\n", __func__, dev->bus_id);
+ }
+ 
+ static struct lh7a40x_udc memory = {
+@@ -2065,7 +2065,7 @@ static int lh7a40x_udc_probe(struct platform_device *pdev)
+ 	struct lh7a40x_udc *dev = &memory;
+ 	int retval;
+ 
+-	DEBUG("%s: %p\n", __FUNCTION__, pdev);
++	DEBUG("%s: %p\n", __func__, pdev);
+ 
+ 	spin_lock_init(&dev->lock);
+ 	dev->dev = &pdev->dev;
+@@ -2098,7 +2098,7 @@ static int lh7a40x_udc_remove(struct platform_device *pdev)
+ {
+ 	struct lh7a40x_udc *dev = platform_get_drvdata(pdev);
+ 
+-	DEBUG("%s: %p\n", __FUNCTION__, pdev);
++	DEBUG("%s: %p\n", __func__, pdev);
+ 
+ 	if (dev->driver)
+ 		return -EBUSY;
+@@ -2131,7 +2131,7 @@ static struct platform_driver udc_driver = {
+ 
+ static int __init udc_init(void)
+ {
+-	DEBUG("%s: %s version %s\n", __FUNCTION__, driver_name, DRIVER_VERSION);
++	DEBUG("%s: %s version %s\n", __func__, driver_name, DRIVER_VERSION);
+ 	return platform_driver_register(&udc_driver);
+ }
+ 
+diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
+index 17b792b..be0a4c1 100644
+--- a/drivers/usb/gadget/m66592-udc.h
++++ b/drivers/usb/gadget/m66592-udc.h
+@@ -486,10 +486,10 @@ struct m66592 {
+ 
+ 	struct usb_request	*ep0_req;	/* for internal request */
+ 	u16			ep0_data;	/* for internal request */
++	u16			old_vbus;
+ 
+ 	struct timer_list	timer;
+ 
+-	u16			old_vbus;
+ 	int			scount;
+ 
+ 	int			old_dvsq;
+diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
+index 44ca139..1f2af39 100644
+--- a/drivers/usb/gadget/net2280.h
++++ b/drivers/usb/gadget/net2280.h
+@@ -299,7 +299,7 @@ static inline void assert_out_naking (struct net2280_ep *ep, const char *where)
+ 			&ep->regs->ep_rsp);
+ 	}
+ }
+-#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__FUNCTION__)
++#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__func__)
+ #else
+ #define ASSERT_OUT_NAKING(ep) do {} while (0)
+ #endif
+diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
+index ee1e9a3..95f7662 100644
+--- a/drivers/usb/gadget/omap_udc.c
++++ b/drivers/usb/gadget/omap_udc.c
+@@ -163,7 +163,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
+ 			|| ep->bEndpointAddress != desc->bEndpointAddress
+ 			|| ep->maxpacket < le16_to_cpu
+ 						(desc->wMaxPacketSize)) {
+-		DBG("%s, bad ep or descriptor\n", __FUNCTION__);
++		DBG("%s, bad ep or descriptor\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 	maxp = le16_to_cpu (desc->wMaxPacketSize);
+@@ -171,7 +171,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
+ 				&& maxp != ep->maxpacket)
+ 			|| le16_to_cpu(desc->wMaxPacketSize) > ep->maxpacket
+ 			|| !desc->wMaxPacketSize) {
+-		DBG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
++		DBG("%s, bad %s maxpacket\n", __func__, _ep->name);
+ 		return -ERANGE;
+ 	}
+ 
+@@ -194,13 +194,13 @@ static int omap_ep_enable(struct usb_ep *_ep,
+ 	if (ep->bmAttributes != desc->bmAttributes
+ 			&& ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+ 			&& desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+-		DBG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
++		DBG("%s, %s type mismatch\n", __func__, _ep->name);
+ 		return -EINVAL;
+ 	}
+ 
+ 	udc = ep->udc;
+ 	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+-		DBG("%s, bogus device state\n", __FUNCTION__);
++		DBG("%s, bogus device state\n", __func__);
+ 		return -ESHUTDOWN;
+ 	}
+ 
+@@ -249,7 +249,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
+ 	unsigned long	flags;
+ 
+ 	if (!_ep || !ep->desc) {
+-		DBG("%s, %s not enabled\n", __FUNCTION__,
++		DBG("%s, %s not enabled\n", __func__,
+ 			_ep ? ep->ep.name : NULL);
+ 		return -EINVAL;
+ 	}
+@@ -936,11 +936,11 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ 	/* catch various bogus parameters */
+ 	if (!_req || !req->req.complete || !req->req.buf
+ 			|| !list_empty(&req->queue)) {
+-		DBG("%s, bad params\n", __FUNCTION__);
++		DBG("%s, bad params\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (!_ep || (!ep->desc && ep->bEndpointAddress)) {
+-		DBG("%s, bad ep\n", __FUNCTION__);
++		DBG("%s, bad ep\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+@@ -959,7 +959,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ 			&& (ep->bEndpointAddress & USB_DIR_IN) == 0
+ 			&& !cpu_class_is_omap2()
+ 			&& (req->req.length % ep->ep.maxpacket) != 0) {
+-		DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
++		DBG("%s, no partial packet OUT reads\n", __func__);
+ 		return -EMSGSIZE;
+ 	}
+ 
+@@ -1265,8 +1265,6 @@ static int can_pullup(struct omap_udc *udc)
+ 
+ static void pullup_enable(struct omap_udc *udc)
+ {
+-	udc->gadget.dev.parent->power.power_state = PMSG_ON;
+-	udc->gadget.dev.power.power_state = PMSG_ON;
+ 	UDC_SYSCON1_REG |= UDC_PULLUP_EN;
+ 	if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
+ 		OTG_CTRL_REG |= OTG_BSESSVLD;
+@@ -3061,8 +3059,6 @@ static int omap_udc_suspend(struct platform_device *dev, pm_message_t message)
+ 		omap_pullup(&udc->gadget, 0);
+ 	}
+ 
+-	udc->gadget.dev.power.power_state = PMSG_SUSPEND;
+-	udc->gadget.dev.parent->power.power_state = PMSG_SUSPEND;
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
+index 2c32bd0..76be75e 100644
+--- a/drivers/usb/gadget/printer.c
++++ b/drivers/usb/gadget/printer.c
+@@ -390,9 +390,12 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+ 
+ 	/* normal completion */
+ 	case 0:
+-		list_add_tail(&req->list, &dev->rx_buffers);
+-		wake_up_interruptible(&dev->rx_wait);
+-		DBG(dev, "G_Printer : rx length %d\n", req->actual);
++		if (req->actual > 0) {
++			list_add_tail(&req->list, &dev->rx_buffers);
++			DBG(dev, "G_Printer : rx length %d\n", req->actual);
++		} else {
++			list_add(&req->list, &dev->rx_reqs);
++		}
+ 		break;
+ 
+ 	/* software-driven interface shutdown */
+@@ -417,6 +420,8 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+ 		list_add(&req->list, &dev->rx_reqs);
+ 		break;
+ 	}
++
++	wake_up_interruptible(&dev->rx_wait);
+ 	spin_unlock_irqrestore(&dev->lock, flags);
+ }
+ 
+@@ -494,6 +499,39 @@ printer_close(struct inode *inode, struct file *fd)
+ 	return 0;
+ }
+ 
++/* This function must be called with interrupts turned off. */
++static void
++setup_rx_reqs(struct printer_dev *dev)
++{
++	struct usb_request              *req;
++
++	while (likely(!list_empty(&dev->rx_reqs))) {
++		int error;
++
++		req = container_of(dev->rx_reqs.next,
++				struct usb_request, list);
++		list_del_init(&req->list);
++
++		/* The USB Host sends us whatever amount of data it wants to
++		 * so we always set the length field to the full USB_BUFSIZE.
++		 * If the amount of data is more than the read() caller asked
++		 * for it will be stored in the request buffer until it is
++		 * asked for by read().
++		 */
++		req->length = USB_BUFSIZE;
++		req->complete = rx_complete;
++
++		error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
++		if (error) {
++			DBG(dev, "rx submit --> %d\n", error);
++			list_add(&req->list, &dev->rx_reqs);
++			break;
++		} else {
++			list_add(&req->list, &dev->rx_reqs_active);
++		}
++	}
++}
++
+ static ssize_t
+ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+ {
+@@ -522,31 +560,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+ 	 */
+ 	dev->reset_printer = 0;
+ 
+-	while (likely(!list_empty(&dev->rx_reqs))) {
+-		int error;
+-
+-		req = container_of(dev->rx_reqs.next,
+-				struct usb_request, list);
+-		list_del_init(&req->list);
+-
+-		/* The USB Host sends us whatever amount of data it wants to
+-		 * so we always set the length field to the full USB_BUFSIZE.
+-		 * If the amount of data is more than the read() caller asked
+-		 * for it will be stored in the request buffer until it is
+-		 * asked for by read().
+-		 */
+-		req->length = USB_BUFSIZE;
+-		req->complete = rx_complete;
+-
+-		error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
+-		if (error) {
+-			DBG(dev, "rx submit --> %d\n", error);
+-			list_add(&req->list, &dev->rx_reqs);
+-			break;
+-		} else {
+-			list_add(&req->list, &dev->rx_reqs_active);
+-		}
+-	}
++	setup_rx_reqs(dev);
+ 
+ 	bytes_copied = 0;
+ 	current_rx_req = dev->current_rx_req;
+@@ -615,9 +629,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+ 
+ 		spin_lock_irqsave(&dev->lock, flags);
+ 
+-		/* We've disconnected or reset free the req and buffer */
++		/* We've disconnected or reset so return. */
+ 		if (dev->reset_printer) {
+-			printer_req_free(dev->out_ep, current_rx_req);
++			list_add(&current_rx_req->list, &dev->rx_reqs);
+ 			spin_unlock_irqrestore(&dev->lock, flags);
+ 			spin_unlock(&dev->lock_printer_io);
+ 			return -EAGAIN;
+@@ -735,7 +749,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ 
+ 		/* We've disconnected or reset so free the req and buffer */
+ 		if (dev->reset_printer) {
+-			printer_req_free(dev->in_ep, req);
++			list_add(&req->list, &dev->tx_reqs);
+ 			spin_unlock_irqrestore(&dev->lock, flags);
+ 			spin_unlock(&dev->lock_printer_io);
+ 			return -EAGAIN;
+@@ -791,6 +805,12 @@ printer_poll(struct file *fd, poll_table *wait)
+ 	unsigned long		flags;
+ 	int			status = 0;
+ 
++	spin_lock(&dev->lock_printer_io);
++	spin_lock_irqsave(&dev->lock, flags);
++	setup_rx_reqs(dev);
++	spin_unlock_irqrestore(&dev->lock, flags);
++	spin_unlock(&dev->lock_printer_io);
++
+ 	poll_wait(fd, &dev->rx_wait, wait);
+ 	poll_wait(fd, &dev->tx_wait, wait);
+ 
+@@ -798,7 +818,8 @@ printer_poll(struct file *fd, poll_table *wait)
+ 	if (likely(!list_empty(&dev->tx_reqs)))
+ 		status |= POLLOUT | POLLWRNORM;
+ 
+-	if (likely(!list_empty(&dev->rx_buffers)))
++	if (likely(dev->current_rx_bytes) ||
++			likely(!list_empty(&dev->rx_buffers)))
+ 		status |= POLLIN | POLLRDNORM;
+ 
+ 	spin_unlock_irqrestore(&dev->lock, flags);
+@@ -894,7 +915,7 @@ static void printer_reset_interface(struct printer_dev *dev)
+ 	if (dev->interface < 0)
+ 		return;
+ 
+-	DBG(dev, "%s\n", __FUNCTION__);
++	DBG(dev, "%s\n", __func__);
+ 
+ 	if (dev->in)
+ 		usb_ep_disable(dev->in_ep);
+@@ -1084,6 +1105,7 @@ static void printer_soft_reset(struct printer_dev *dev)
+ 	if (usb_ep_enable(dev->out_ep, dev->out))
+ 		DBG(dev, "Failed to enable USB out_ep\n");
+ 
++	wake_up_interruptible(&dev->rx_wait);
+ 	wake_up_interruptible(&dev->tx_wait);
+ 	wake_up_interruptible(&dev->tx_flush_wait);
+ }
+@@ -1262,7 +1284,7 @@ printer_disconnect(struct usb_gadget *gadget)
+ 	struct printer_dev	*dev = get_gadget_data(gadget);
+ 	unsigned long		flags;
+ 
+-	DBG(dev, "%s\n", __FUNCTION__);
++	DBG(dev, "%s\n", __func__);
+ 
+ 	spin_lock_irqsave(&dev->lock, flags);
+ 
+@@ -1278,7 +1300,7 @@ printer_unbind(struct usb_gadget *gadget)
+ 	struct usb_request	*req;
+ 
+ 
+-	DBG(dev, "%s\n", __FUNCTION__);
++	DBG(dev, "%s\n", __func__);
+ 
+ 	/* Remove sysfs files */
+ 	device_destroy(usb_gadget_class, g_printer_devno);
+diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
+index c00cd8b..08f699b 100644
+--- a/drivers/usb/gadget/pxa2xx_udc.c
++++ b/drivers/usb/gadget/pxa2xx_udc.c
+@@ -235,7 +235,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
+ 			|| ep->bEndpointAddress != desc->bEndpointAddress
+ 			|| ep->fifo_size < le16_to_cpu
+ 						(desc->wMaxPacketSize)) {
+-		DMSG("%s, bad ep or descriptor\n", __FUNCTION__);
++		DMSG("%s, bad ep or descriptor\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -243,7 +243,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
+ 	if (ep->bmAttributes != desc->bmAttributes
+ 			&& ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+ 			&& desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+-		DMSG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
++		DMSG("%s, %s type mismatch\n", __func__, _ep->name);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -252,13 +252,13 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
+ 				&& le16_to_cpu (desc->wMaxPacketSize)
+ 						!= BULK_FIFO_SIZE)
+ 			|| !desc->wMaxPacketSize) {
+-		DMSG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
++		DMSG("%s, bad %s maxpacket\n", __func__, _ep->name);
+ 		return -ERANGE;
+ 	}
+ 
+ 	dev = ep->dev;
+ 	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+-		DMSG("%s, bogus device state\n", __FUNCTION__);
++		DMSG("%s, bogus device state\n", __func__);
+ 		return -ESHUTDOWN;
+ 	}
+ 
+@@ -283,7 +283,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
+ 
+ 	ep = container_of (_ep, struct pxa2xx_ep, ep);
+ 	if (!_ep || !ep->desc) {
+-		DMSG("%s, %s not enabled\n", __FUNCTION__,
++		DMSG("%s, %s not enabled\n", __func__,
+ 			_ep ? ep->ep.name : NULL);
+ 		return -EINVAL;
+ 	}
+@@ -461,7 +461,7 @@ void ep0start(struct pxa2xx_udc *dev, u32 flags, const char *tag)
+ 	USIR0 = USIR0_IR0;
+ 	dev->req_pending = 0;
+ 	DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
+-		__FUNCTION__, tag, UDCCS0, flags);
++		__func__, tag, UDCCS0, flags);
+ }
+ 
+ static int
+@@ -651,20 +651,20 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ 	req = container_of(_req, struct pxa2xx_request, req);
+ 	if (unlikely (!_req || !_req->complete || !_req->buf
+ 			|| !list_empty(&req->queue))) {
+-		DMSG("%s, bad params\n", __FUNCTION__);
++		DMSG("%s, bad params\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	ep = container_of(_ep, struct pxa2xx_ep, ep);
+ 	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+-		DMSG("%s, bad ep\n", __FUNCTION__);
++		DMSG("%s, bad ep\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	dev = ep->dev;
+ 	if (unlikely (!dev->driver
+ 			|| dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+-		DMSG("%s, bogus device state\n", __FUNCTION__);
++		DMSG("%s, bogus device state\n", __func__);
+ 		return -ESHUTDOWN;
+ 	}
+ 
+@@ -807,7 +807,7 @@ static int pxa2xx_ep_set_halt(struct usb_ep *_ep, int value)
+ 	if (unlikely (!_ep
+ 			|| (!ep->desc && ep->ep.name != ep0name))
+ 			|| ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+-		DMSG("%s, bad ep\n", __FUNCTION__);
++		DMSG("%s, bad ep\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (value == 0) {
+@@ -859,7 +859,7 @@ static int pxa2xx_ep_fifo_status(struct usb_ep *_ep)
+ 
+ 	ep = container_of(_ep, struct pxa2xx_ep, ep);
+ 	if (!_ep) {
+-		DMSG("%s, bad ep\n", __FUNCTION__);
++		DMSG("%s, bad ep\n", __func__);
+ 		return -ENODEV;
+ 	}
+ 	/* pxa can't report unclaimed bytes from IN fifos */
+@@ -878,7 +878,7 @@ static void pxa2xx_ep_fifo_flush(struct usb_ep *_ep)
+ 
+ 	ep = container_of(_ep, struct pxa2xx_ep, ep);
+ 	if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
+-		DMSG("%s, bad ep\n", __FUNCTION__);
++		DMSG("%s, bad ep\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -1813,7 +1813,7 @@ pxa2xx_udc_irq(int irq, void *_dev)
+ 
+ static void nop_release (struct device *dev)
+ {
+-	DMSG("%s %s\n", __FUNCTION__, dev->bus_id);
++	DMSG("%s %s\n", __func__, dev->bus_id);
+ }
+ 
+ /* this uses load-time allocation and initialization (instead of
+diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
+index 3d03664..bd58dd5 100644
+--- a/drivers/usb/gadget/rndis.c
++++ b/drivers/usb/gadget/rndis.c
+@@ -204,7 +204,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_SUPPORTED_LIST:
+-		DBG("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
++		DBG("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
+ 		length = sizeof (oid_supported_list);
+ 		count  = length / sizeof (u32);
+ 		for (i = 0; i < count; i++)
+@@ -214,7 +214,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_HARDWARE_STATUS:
+-		DBG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
++		DBG("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
+ 		/* Bogus question!
+ 		 * Hardware must be ready to receive high level protocols.
+ 		 * BTW:
+@@ -227,14 +227,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_MEDIA_SUPPORTED:
+-		DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
++		DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
+ 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
+ 		retval = 0;
+ 		break;
+ 
+ 	/* mandatory */
+ 	case OID_GEN_MEDIA_IN_USE:
+-		DBG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
++		DBG("%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);
+ 		retval = 0;
+@@ -242,7 +242,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_MAXIMUM_FRAME_SIZE:
+-		DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
++		DBG("%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);
+@@ -253,7 +253,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 	/* mandatory */
+ 	case OID_GEN_LINK_SPEED:
+ 		if (rndis_debug > 1)
+-			DBG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
++			DBG("%s: OID_GEN_LINK_SPEED\n", __func__);
+ 		if (rndis_per_dev_params [configNr].media_state
+ 				== NDIS_MEDIA_STATE_DISCONNECTED)
+ 			*outbuf = __constant_cpu_to_le32 (0);
+@@ -265,7 +265,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_TRANSMIT_BLOCK_SIZE:
+-		DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
++		DBG("%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);
+@@ -275,7 +275,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_RECEIVE_BLOCK_SIZE:
+-		DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
++		DBG("%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);
+@@ -285,7 +285,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_VENDOR_ID:
+-		DBG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
++		DBG("%s: OID_GEN_VENDOR_ID\n", __func__);
+ 		*outbuf = cpu_to_le32 (
+ 			rndis_per_dev_params [configNr].vendorID);
+ 		retval = 0;
+@@ -293,7 +293,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_VENDOR_DESCRIPTION:
+-		DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
++		DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
+ 		length = strlen (rndis_per_dev_params [configNr].vendorDescr);
+ 		memcpy (outbuf,
+ 			rndis_per_dev_params [configNr].vendorDescr, length);
+@@ -301,7 +301,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_VENDOR_DRIVER_VERSION:
+-		DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
++		DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
+ 		/* Created as LE */
+ 		*outbuf = rndis_driver_version;
+ 		retval = 0;
+@@ -309,14 +309,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_CURRENT_PACKET_FILTER:
+-		DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
++		DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
+ 		*outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
+ 		retval = 0;
+ 		break;
+ 
+ 	/* mandatory */
+ 	case OID_GEN_MAXIMUM_TOTAL_SIZE:
+-		DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
++		DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
+ 		*outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
+ 		retval = 0;
+ 		break;
+@@ -324,14 +324,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 	/* mandatory */
+ 	case OID_GEN_MEDIA_CONNECT_STATUS:
+ 		if (rndis_debug > 1)
+-			DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
++			DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
+ 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 						.media_state);
+ 		retval = 0;
+ 		break;
+ 
+ 	case OID_GEN_PHYSICAL_MEDIUM:
+-		DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
++		DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
+ 		*outbuf = __constant_cpu_to_le32 (0);
+ 		retval = 0;
+ 		break;
+@@ -341,7 +341,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 	 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
+ 	 */
+ 	case OID_GEN_MAC_OPTIONS:		/* from WinME */
+-		DBG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
++		DBG("%s: OID_GEN_MAC_OPTIONS\n", __func__);
+ 		*outbuf = __constant_cpu_to_le32(
+ 			  NDIS_MAC_OPTION_RECEIVE_SERIALIZED
+ 			| NDIS_MAC_OPTION_FULL_DUPLEX);
+@@ -353,7 +353,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 	/* mandatory */
+ 	case OID_GEN_XMIT_OK:
+ 		if (rndis_debug > 1)
+-			DBG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
++			DBG("%s: OID_GEN_XMIT_OK\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (
+ 			    rndis_per_dev_params [configNr].stats->tx_packets -
+@@ -366,7 +366,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 	/* mandatory */
+ 	case OID_GEN_RCV_OK:
+ 		if (rndis_debug > 1)
+-			DBG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
++			DBG("%s: OID_GEN_RCV_OK\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (
+ 			    rndis_per_dev_params [configNr].stats->rx_packets -
+@@ -379,7 +379,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 	/* mandatory */
+ 	case OID_GEN_XMIT_ERROR:
+ 		if (rndis_debug > 1)
+-			DBG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
++			DBG("%s: OID_GEN_XMIT_ERROR\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->tx_errors);
+@@ -390,7 +390,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 	/* mandatory */
+ 	case OID_GEN_RCV_ERROR:
+ 		if (rndis_debug > 1)
+-			DBG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
++			DBG("%s: OID_GEN_RCV_ERROR\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->rx_errors);
+@@ -400,7 +400,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_GEN_RCV_NO_BUFFER:
+-		DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
++		DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->rx_dropped);
+@@ -410,7 +410,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ #ifdef	RNDIS_OPTIONAL_STATS
+ 	case OID_GEN_DIRECTED_BYTES_XMIT:
+-		DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
++		DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
+ 		/*
+ 		 * Aunt Tilly's size of shoes
+ 		 * minus antarctica count of penguins
+@@ -430,7 +430,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_DIRECTED_FRAMES_XMIT:
+-		DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
++		DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
+ 		/* dito */
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (
+@@ -446,7 +446,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_MULTICAST_BYTES_XMIT:
+-		DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
++		DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->multicast*1234);
+@@ -455,7 +455,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_MULTICAST_FRAMES_XMIT:
+-		DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
++		DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->multicast);
+@@ -464,7 +464,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_BROADCAST_BYTES_XMIT:
+-		DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
++		DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->tx_packets/42*255);
+@@ -473,7 +473,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_BROADCAST_FRAMES_XMIT:
+-		DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
++		DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->tx_packets/42);
+@@ -482,19 +482,19 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_DIRECTED_BYTES_RCV:
+-		DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
++		DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
+ 		*outbuf = __constant_cpu_to_le32 (0);
+ 		retval = 0;
+ 		break;
+ 
+ 	case OID_GEN_DIRECTED_FRAMES_RCV:
+-		DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
++		DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
+ 		*outbuf = __constant_cpu_to_le32 (0);
+ 		retval = 0;
+ 		break;
+ 
+ 	case OID_GEN_MULTICAST_BYTES_RCV:
+-		DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
++		DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->multicast * 1111);
+@@ -503,7 +503,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_MULTICAST_FRAMES_RCV:
+-		DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
++		DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->multicast);
+@@ -512,7 +512,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_BROADCAST_BYTES_RCV:
+-		DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
++		DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->rx_packets/42*255);
+@@ -521,7 +521,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_BROADCAST_FRAMES_RCV:
+-		DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
++		DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->rx_packets/42);
+@@ -530,7 +530,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_RCV_CRC_ERROR:
+-		DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
++		DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->rx_crc_errors);
+@@ -539,7 +539,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		break;
+ 
+ 	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+-		DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
++		DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
+ 		*outbuf = __constant_cpu_to_le32 (0);
+ 		retval = 0;
+ 		break;
+@@ -549,7 +549,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_802_3_PERMANENT_ADDRESS:
+-		DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
++		DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
+ 		if (rndis_per_dev_params [configNr].dev) {
+ 			length = ETH_ALEN;
+ 			memcpy (outbuf,
+@@ -561,7 +561,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_802_3_CURRENT_ADDRESS:
+-		DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
++		DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
+ 		if (rndis_per_dev_params [configNr].dev) {
+ 			length = ETH_ALEN;
+ 			memcpy (outbuf,
+@@ -573,7 +573,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_802_3_MULTICAST_LIST:
+-		DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
++		DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+ 		/* Multicast base address only */
+ 		*outbuf = __constant_cpu_to_le32 (0xE0000000);
+ 		retval = 0;
+@@ -581,21 +581,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_802_3_MAXIMUM_LIST_SIZE:
+-		DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
++		DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
+ 		/* Multicast base address only */
+ 		*outbuf = __constant_cpu_to_le32 (1);
+ 		retval = 0;
+ 		break;
+ 
+ 	case OID_802_3_MAC_OPTIONS:
+-		DBG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
++		DBG("%s: OID_802_3_MAC_OPTIONS\n", __func__);
+ 		break;
+ 
+ 	/* ieee802.3 statistics OIDs (table 4-4) */
+ 
+ 	/* mandatory */
+ 	case OID_802_3_RCV_ERROR_ALIGNMENT:
+-		DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
++		DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
+ 		if (rndis_per_dev_params [configNr].stats) {
+ 			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ 					.stats->rx_frame_errors);
+@@ -605,51 +605,51 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	/* mandatory */
+ 	case OID_802_3_XMIT_ONE_COLLISION:
+-		DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
++		DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
+ 		*outbuf = __constant_cpu_to_le32 (0);
+ 		retval = 0;
+ 		break;
+ 
+ 	/* mandatory */
+ 	case OID_802_3_XMIT_MORE_COLLISIONS:
+-		DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
++		DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
+ 		*outbuf = __constant_cpu_to_le32 (0);
+ 		retval = 0;
+ 		break;
+ 
+ #ifdef	RNDIS_OPTIONAL_STATS
+ 	case OID_802_3_XMIT_DEFERRED:
+-		DBG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
++		DBG("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
+ 		/* TODO */
+ 		break;
+ 
+ 	case OID_802_3_XMIT_MAX_COLLISIONS:
+-		DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
++		DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
+ 		/* TODO */
+ 		break;
+ 
+ 	case OID_802_3_RCV_OVERRUN:
+-		DBG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
++		DBG("%s: OID_802_3_RCV_OVERRUN\n", __func__);
+ 		/* TODO */
+ 		break;
+ 
+ 	case OID_802_3_XMIT_UNDERRUN:
+-		DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
++		DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
+ 		/* TODO */
+ 		break;
+ 
+ 	case OID_802_3_XMIT_HEARTBEAT_FAILURE:
+-		DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
++		DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
+ 		/* TODO */
+ 		break;
+ 
+ 	case OID_802_3_XMIT_TIMES_CRS_LOST:
+-		DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
++		DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
+ 		/* TODO */
+ 		break;
+ 
+ 	case OID_802_3_XMIT_LATE_COLLISIONS:
+-		DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
++		DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
+ 		/* TODO */
+ 		break;
+ #endif	/* RNDIS_OPTIONAL_STATS */
+@@ -657,7 +657,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ #ifdef	RNDIS_PM
+ 	/* power management OIDs (table 4-5) */
+ 	case OID_PNP_CAPABILITIES:
+-		DBG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
++		DBG("%s: OID_PNP_CAPABILITIES\n", __func__);
+ 
+ 		/* for now, no wakeup capabilities */
+ 		length = sizeof (struct NDIS_PNP_CAPABILITIES);
+@@ -665,7 +665,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 		retval = 0;
+ 		break;
+ 	case OID_PNP_QUERY_POWER:
+-		DBG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
++		DBG("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
+ 				le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
+ 		/* only suspend is a real power state, and
+ 		 * it can't be entered by OID_PNP_SET_POWER...
+@@ -677,7 +677,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ 
+ 	default:
+ 		pr_warning("%s: query unknown OID 0x%08X\n",
+-			 __FUNCTION__, OID);
++			 __func__, OID);
+ 	}
+ 	if (retval < 0)
+ 		length = 0;
+@@ -729,7 +729,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
+ 		*params->filter = (u16) le32_to_cpu(get_unaligned(
+ 				(__le32 *)buf));
+ 		DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+-			__FUNCTION__, *params->filter);
++			__func__, *params->filter);
+ 
+ 		/* this call has a significant side effect:  it's
+ 		 * what makes the packet flow start and stop, like
+@@ -753,7 +753,7 @@ update_linkstate:
+ 
+ 	case OID_802_3_MULTICAST_LIST:
+ 		/* I think we can ignore this */
+-		DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
++		DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+ 		retval = 0;
+ 		break;
+ #if 0
+@@ -762,7 +762,7 @@ update_linkstate:
+ 		struct rndis_config_parameter	*param;
+ 		param = (struct rndis_config_parameter *) buf;
+ 		DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
+-			__FUNCTION__,
++			__func__,
+ 			min(cpu_to_le32(param->ParameterNameLength),80),
+ 			buf + param->ParameterNameOffset);
+ 		retval = 0;
+@@ -778,7 +778,7 @@ update_linkstate:
+ 		 * FIXME ... then things go batty; Windows wedges itself.
+ 		 */
+ 		i = le32_to_cpu(get_unaligned((__le32 *)buf));
+-		DBG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
++		DBG("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
+ 		switch (i) {
+ 		case NdisDeviceStateD0:
+ 			*params->filter = params->saved_filter;
+@@ -802,7 +802,7 @@ update_linkstate:
+ 
+ 	default:
+ 		pr_warning("%s: set unknown OID 0x%08X, size %d\n",
+-			 __FUNCTION__, OID, buf_len);
++			 __func__, OID, buf_len);
+ 	}
+ 
+ 	return retval;
+@@ -855,7 +855,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
+ 	rndis_query_cmplt_type *resp;
+ 	rndis_resp_t            *r;
+ 
+-	// DBG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
++	// DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
+ 	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+ 
+ 	/*
+@@ -908,9 +908,9 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
+ 	BufOffset = le32_to_cpu (buf->InformationBufferOffset);
+ 
+ #ifdef	VERBOSE
+-	DBG("%s: Length: %d\n", __FUNCTION__, BufLength);
+-	DBG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
+-	DBG("%s: InfoBuffer: ", __FUNCTION__);
++	DBG("%s: Length: %d\n", __func__, BufLength);
++	DBG("%s: Offset: %d\n", __func__, BufOffset);
++	DBG("%s: InfoBuffer: ", __func__);
+ 
+ 	for (i = 0; i < BufLength; i++) {
+ 		DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+@@ -1080,14 +1080,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
+ 	switch (MsgType) {
+ 	case REMOTE_NDIS_INITIALIZE_MSG:
+ 		DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
+-			__FUNCTION__ );
++			__func__ );
+ 		params->state = RNDIS_INITIALIZED;
+ 		return  rndis_init_response (configNr,
+ 					(rndis_init_msg_type *) buf);
+ 
+ 	case REMOTE_NDIS_HALT_MSG:
+ 		DBG("%s: REMOTE_NDIS_HALT_MSG\n",
+-			__FUNCTION__ );
++			__func__ );
+ 		params->state = RNDIS_UNINITIALIZED;
+ 		if (params->dev) {
+ 			netif_carrier_off (params->dev);
+@@ -1105,7 +1105,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
+ 
+ 	case REMOTE_NDIS_RESET_MSG:
+ 		DBG("%s: REMOTE_NDIS_RESET_MSG\n",
+-			__FUNCTION__ );
++			__func__ );
+ 		return rndis_reset_response (configNr,
+ 					(rndis_reset_msg_type *) buf);
+ 
+@@ -1113,7 +1113,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
+ 		/* For USB: host does this every 5 seconds */
+ 		if (rndis_debug > 1)
+ 			DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
+-				__FUNCTION__ );
++				__func__ );
+ 		return rndis_keepalive_response (configNr,
+ 						 (rndis_keepalive_msg_type *)
+ 						 buf);
+@@ -1124,7 +1124,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
+ 		 * suspending itself.
+ 		 */
+ 		pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
+-			__FUNCTION__ , MsgType, MsgLength);
++			__func__ , MsgType, MsgLength);
+ 		{
+ 			unsigned i;
+ 			for (i = 0; i < MsgLength; i += 16) {
+@@ -1159,7 +1159,7 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *))
+ 		if (!rndis_per_dev_params [i].used) {
+ 			rndis_per_dev_params [i].used = 1;
+ 			rndis_per_dev_params [i].ack = rndis_control_ack;
+-			DBG("%s: configNr = %d\n", __FUNCTION__, i);
++			DBG("%s: configNr = %d\n", __func__, i);
+ 			return i;
+ 		}
+ 	}
+@@ -1170,7 +1170,7 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *))
+ 
+ void rndis_deregister (int configNr)
+ {
+-	DBG("%s: \n", __FUNCTION__ );
++	DBG("%s: \n", __func__ );
+ 
+ 	if (configNr >= RNDIS_MAX_CONFIGS) return;
+ 	rndis_per_dev_params [configNr].used = 0;
+@@ -1182,7 +1182,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
+ 			 struct net_device_stats *stats,
+ 			 u16 *cdc_filter)
+ {
+-	DBG("%s:\n", __FUNCTION__ );
++	DBG("%s:\n", __func__ );
+ 	if (!dev || !stats) return -1;
+ 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+ 
+@@ -1195,7 +1195,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
+ 
+ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
+ {
+-	DBG("%s:\n", __FUNCTION__ );
++	DBG("%s:\n", __func__ );
+ 	if (!vendorDescr) return -1;
+ 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+ 
+@@ -1207,7 +1207,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
+ 
+ int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
+ {
+-	DBG("%s: %u %u\n", __FUNCTION__, medium, speed);
++	DBG("%s: %u %u\n", __func__, medium, speed);
+ 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+ 
+ 	rndis_per_dev_params [configNr].medium = medium;
+@@ -1403,7 +1403,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
+ #endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
+ 
+ 
+-int __devinit rndis_init (void)
++int __init rndis_init (void)
+ {
+ 	u8 i;
+ 
+@@ -1415,7 +1415,7 @@ int __devinit rndis_init (void)
+ 		if (!(rndis_connect_state [i]
+ 				= create_proc_entry (name, 0660, NULL)))
+ 		{
+-			DBG("%s :remove entries", __FUNCTION__);
++			DBG("%s :remove entries", __func__);
+ 			while (i) {
+ 				sprintf (name, NAME_TEMPLATE, --i);
+ 				remove_proc_entry (name, NULL);
+diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
+index f5c3896..433b3f4 100644
+--- a/drivers/usb/gadget/serial.c
++++ b/drivers/usb/gadget/serial.c
+@@ -2163,8 +2163,7 @@ static void gs_free_ports(struct gs_dev *dev)
+ 				port->port_dev = NULL;
+ 				wake_up_interruptible(&port->port_write_wait);
+ 				if (port->port_tty) {
+-					wake_up_interruptible(&port->port_tty->read_wait);
+-					wake_up_interruptible(&port->port_tty->write_wait);
++					tty_hangup(port->port_tty);
+ 				}
+ 				spin_unlock_irqrestore(&port->port_lock, flags);
+ 			} else {
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index bf8be2a..0b87480 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -30,8 +30,8 @@ config USB_EHCI_HCD
+ 	  module will be called ehci-hcd.
+ 
+ config USB_EHCI_ROOT_HUB_TT
+-	bool "Root Hub Transaction Translators (EXPERIMENTAL)"
+-	depends on USB_EHCI_HCD && EXPERIMENTAL
++	bool "Root Hub Transaction Translators"
++	depends on USB_EHCI_HCD
+ 	---help---
+ 	  Some EHCI chips have vendor-specific extensions to integrate
+ 	  transaction translators, so that no OHCI or UHCI companion
+@@ -260,3 +260,9 @@ config USB_R8A66597_HCD
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called r8a66597-hcd.
+ 
++config SUPERH_ON_CHIP_R8A66597
++	boolean "Enable SuperH on-chip USB like the R8A66597"
++	depends on USB_R8A66597_HCD && CPU_SUBTYPE_SH7366
++	help
++	   Renesas SuperH processor has USB like the R8A66597.
++	   This driver supported processor is SH7366.
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index da7532d..8b5f991 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -237,6 +237,7 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
+ 	if (usb_disabled())
+ 		return -ENODEV;
+ 
++	/* FIXME we only want one one probe() not two */
+ 	ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev);
+ 	return ret;
+ }
+@@ -245,6 +246,7 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 
++	/* FIXME we only want one one remove() not two */
+ 	usb_ehci_au1xxx_remove(hcd, pdev);
+ 	return 0;
+ }
+@@ -265,7 +267,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
+ 	return 0;
+ }
+ */
+-MODULE_ALIAS("au1xxx-ehci");
++MODULE_ALIAS("platform:au1xxx-ehci");
+ static struct platform_driver ehci_hcd_au1xxx_driver = {
+ 	.probe = ehci_hcd_au1xxx_drv_probe,
+ 	.remove = ehci_hcd_au1xxx_drv_remove,
+@@ -274,6 +276,5 @@ static struct platform_driver ehci_hcd_au1xxx_driver = {
+ 	/*.resume       = ehci_hcd_au1xxx_drv_resume, */
+ 	.driver = {
+ 		.name = "au1xxx-ehci",
+-		.bus = &platform_bus_type
+ 	}
+ };
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 64ebfc5..4af90df 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -27,7 +27,7 @@
+ #define ehci_warn(ehci, fmt, args...) \
+ 	dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
+ 
+-#ifdef EHCI_VERBOSE_DEBUG
++#ifdef VERBOSE_DEBUG
+ #	define vdbg dbg
+ #	define ehci_vdbg ehci_dbg
+ #else
+@@ -670,7 +670,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 
+ 	spin_lock_irqsave (&ehci->lock, flags);
+ 
+-	if (buf->bus->controller->power.power_state.event) {
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ 		size = scnprintf (next, size,
+ 			"bus %s, device %s (driver " DRIVER_VERSION ")\n"
+ 			"%s\n"
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index adb0def..6d9bed6 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -1,5 +1,4 @@
+ /*
+- * (C) Copyright David Brownell 2000-2002
+  * Copyright (c) 2005 MontaVista Software
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -28,7 +27,6 @@
+ /* FIXME: Power Management is un-ported so temporarily disable it */
+ #undef CONFIG_PM
+ 
+-/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
+ 
+ /* configure so an HC device and id are always provided */
+ /* always called with process context; sleeping is OK */
+@@ -331,6 +329,7 @@ static int ehci_fsl_drv_probe(struct platform_device *pdev)
+ 	if (usb_disabled())
+ 		return -ENODEV;
+ 
++	/* FIXME we only want one one probe() not two */
+ 	return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev);
+ }
+ 
+@@ -338,12 +337,12 @@ static int ehci_fsl_drv_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 
++	/* FIXME we only want one one remove() not two */
+ 	usb_hcd_fsl_remove(hcd, pdev);
+-
+ 	return 0;
+ }
+ 
+-MODULE_ALIAS("fsl-ehci");
++MODULE_ALIAS("platform:fsl-ehci");
+ 
+ static struct platform_driver ehci_fsl_driver = {
+ 	.probe = ehci_fsl_drv_probe,
+@@ -351,5 +350,5 @@ static struct platform_driver ehci_fsl_driver = {
+ 	.shutdown = usb_hcd_platform_shutdown,
+ 	.driver = {
+ 		   .name = "fsl-ehci",
+-		   },
++	},
+ };
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 46ee7f4..369a8a5 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -57,35 +57,6 @@
+  * Special thanks to Intel and VIA for providing host controllers to
+  * test this driver on, and Cypress (including In-System Design) for
+  * providing early devices for those host controllers to talk to!
+- *
+- * HISTORY:
+- *
+- * 2004-05-10 Root hub and PCI suspend/resume support; remote wakeup. (db)
+- * 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena at plexity.net)
+- * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka,
+- *	<sojkam at centrum.cz>, updates by DB).
+- *
+- * 2002-11-29	Correct handling for hw async_next register.
+- * 2002-08-06	Handling for bulk and interrupt transfers is mostly shared;
+- *	only scheduling is different, no arbitrary limitations.
+- * 2002-07-25	Sanity check PCI reads, mostly for better cardbus support,
+- *	clean up HC run state handshaking.
+- * 2002-05-24	Preliminary FS/LS interrupts, using scheduling shortcuts
+- * 2002-05-11	Clear TT errors for FS/LS ctrl/bulk.  Fill in some other
+- *	missing pieces:  enabling 64bit dma, handoff from BIOS/SMM.
+- * 2002-05-07	Some error path cleanups to report better errors; wmb();
+- *	use non-CVS version id; better iso bandwidth claim.
+- * 2002-04-19	Control/bulk/interrupt submit no longer uses giveback() on
+- *	errors in submit path.  Bugfixes to interrupt scheduling/processing.
+- * 2002-03-05	Initial high-speed ISO support; reduce ITD memory; shift
+- *	more checking to generic hcd framework (db).  Make it work with
+- *	Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt).
+- * 2002-01-14	Minor cleanup; version synch.
+- * 2002-01-08	Fix roothub handoff of FS/LS to companion controllers.
+- * 2002-01-04	Control/Bulk queuing behaves.
+- *
+- * 2001-12-12	Initial patch version for Linux 2.5.1 kernel.
+- * 2001-June	Works with usb-storage and NEC EHCI on 2.4
+  */
+ 
+ #define DRIVER_VERSION "10 Dec 2004"
+@@ -95,7 +66,7 @@
+ static const char	hcd_name [] = "ehci_hcd";
+ 
+ 
+-#undef EHCI_VERBOSE_DEBUG
++#undef VERBOSE_DEBUG
+ #undef EHCI_URB_TRACE
+ 
+ #ifdef DEBUG
+@@ -174,6 +145,16 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
+ 	return -ETIMEDOUT;
+ }
+ 
++static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
++				       u32 mask, u32 done, int usec)
++{
++	int error = handshake(ehci, ptr, mask, done, usec);
++	if (error)
++		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++
++	return error;
++}
++
+ /* force HC to halt state from unknown (EHCI spec section 2.3) */
+ static int ehci_halt (struct ehci_hcd *ehci)
+ {
+@@ -246,11 +227,9 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ 	/* wait for any schedule enables/disables to take effect */
+ 	temp = ehci_readl(ehci, &ehci->regs->command) << 10;
+ 	temp &= STS_ASS | STS_PSS;
+-	if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
+-				temp, 16 * 125) != 0) {
+-		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++	if (handshake_on_error_set_halt(ehci, &ehci->regs->status,
++					STS_ASS | STS_PSS, temp, 16 * 125))
+ 		return;
+-	}
+ 
+ 	/* then disable anything that's still active */
+ 	temp = ehci_readl(ehci, &ehci->regs->command);
+@@ -258,11 +237,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ 	ehci_writel(ehci, temp, &ehci->regs->command);
+ 
+ 	/* hardware can take 16 microframes to turn off ... */
+-	if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
+-				0, 16 * 125) != 0) {
+-		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+-		return;
+-	}
++	handshake_on_error_set_halt(ehci, &ehci->regs->status,
++				    STS_ASS | STS_PSS, 0, 16 * 125);
+ }
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -355,17 +331,13 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
+ 				&ehci->regs->port_status[port]);
+ }
+ 
+-/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
+- * This forcibly disables dma and IRQs, helping kexec and other cases
+- * where the next system software may expect clean state.
++/*
++ * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
++ * Should be called with ehci->lock held.
+  */
+-static void
+-ehci_shutdown (struct usb_hcd *hcd)
++static void ehci_silence_controller(struct ehci_hcd *ehci)
+ {
+-	struct ehci_hcd	*ehci;
+-
+-	ehci = hcd_to_ehci (hcd);
+-	(void) ehci_halt (ehci);
++	ehci_halt(ehci);
+ 	ehci_turn_off_all_ports(ehci);
+ 
+ 	/* make BIOS/etc use companion controller during reboot */
+@@ -375,6 +347,22 @@ ehci_shutdown (struct usb_hcd *hcd)
+ 	ehci_readl(ehci, &ehci->regs->configured_flag);
+ }
+ 
++/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
++ * This forcibly disables dma and IRQs, helping kexec and other cases
++ * where the next system software may expect clean state.
++ */
++static void ehci_shutdown(struct usb_hcd *hcd)
++{
++	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
++
++	del_timer_sync(&ehci->watchdog);
++	del_timer_sync(&ehci->iaa_watchdog);
++
++	spin_lock_irq(&ehci->lock);
++	ehci_silence_controller(ehci);
++	spin_unlock_irq(&ehci->lock);
++}
++
+ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
+ {
+ 	unsigned port;
+@@ -425,15 +413,15 @@ static void ehci_work (struct ehci_hcd *ehci)
+ 		timer_action (ehci, TIMER_IO_WATCHDOG);
+ }
+ 
++/*
++ * Called when the ehci_hcd module is removed.
++ */
+ static void ehci_stop (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+ 
+ 	ehci_dbg (ehci, "stop\n");
+ 
+-	/* Turn off port power on all root hub ports. */
+-	ehci_port_power (ehci, 0);
+-
+ 	/* no more interrupts ... */
+ 	del_timer_sync (&ehci->watchdog);
+ 	del_timer_sync(&ehci->iaa_watchdog);
+@@ -442,13 +430,10 @@ static void ehci_stop (struct usb_hcd *hcd)
+ 	if (HC_IS_RUNNING (hcd->state))
+ 		ehci_quiesce (ehci);
+ 
++	ehci_silence_controller(ehci);
+ 	ehci_reset (ehci);
+-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ 	spin_unlock_irq(&ehci->lock);
+ 
+-	/* let companion controllers work when we aren't */
+-	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+-
+ 	remove_companion_file(ehci);
+ 	remove_debug_files (ehci);
+ 
+@@ -676,7 +661,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 	cmd = ehci_readl(ehci, &ehci->regs->command);
+ 	bh = 0;
+ 
+-#ifdef	EHCI_VERBOSE_DEBUG
++#ifdef	VERBOSE_DEBUG
+ 	/* unrequested/ignored: Frame List Rollover */
+ 	dbg_status (ehci, "irq", status);
+ #endif
+@@ -710,6 +695,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 	/* remote wakeup [4.3.1] */
+ 	if (status & STS_PCD) {
+ 		unsigned	i = HCS_N_PORTS (ehci->hcs_params);
++
++		/* kick root hub later */
+ 		pcd_status = status;
+ 
+ 		/* resume root hub? */
+@@ -738,8 +725,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ 
+ 	/* PCI errors [4.15.2.4] */
+ 	if (unlikely ((status & STS_FATAL) != 0)) {
+-		/* bogus "fatal" IRQs appear on some chips... why?  */
+-		status = ehci_readl(ehci, &ehci->regs->status);
+ 		dbg_cmd (ehci, "fatal", ehci_readl(ehci,
+ 						   &ehci->regs->command));
+ 		dbg_status (ehci, "fatal", status);
+@@ -758,7 +743,7 @@ dead:
+ 	if (bh)
+ 		ehci_work (ehci);
+ 	spin_unlock (&ehci->lock);
+-	if (pcd_status & STS_PCD)
++	if (pcd_status)
+ 		usb_hcd_poll_rh_status(hcd);
+ 	return IRQ_HANDLED;
+ }
+@@ -788,8 +773,14 @@ static int ehci_urb_enqueue (
+ 	INIT_LIST_HEAD (&qtd_list);
+ 
+ 	switch (usb_pipetype (urb->pipe)) {
+-	// case PIPE_CONTROL:
+-	// case PIPE_BULK:
++	case PIPE_CONTROL:
++		/* qh_completions() code doesn't handle all the fault cases
++		 * in multi-TD control transfers.  Even 1KB is rare anyway.
++		 */
++		if (urb->transfer_buffer_length > (16 * 1024))
++			return -EMSGSIZE;
++		/* FALLTHROUGH */
++	/* case PIPE_BULK: */
+ 	default:
+ 		if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
+ 			return -ENOMEM;
+@@ -1033,7 +1024,7 @@ MODULE_LICENSE ("GPL");
+ #define OF_PLATFORM_DRIVER	ehci_hcd_ppc_of_driver
+ #endif
+ 
+-#ifdef CONFIG_ARCH_ORION
++#ifdef CONFIG_PLAT_ORION
+ #include "ehci-orion.c"
+ #define	PLATFORM_DRIVER		ehci_orion_driver
+ #endif
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 4e065e5..efffef6 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -28,7 +28,9 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#ifdef	CONFIG_USB_PERSIST
++#define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
++
++#ifdef	CONFIG_PM
+ 
+ static int ehci_hub_control(
+ 	struct usb_hcd	*hcd,
+@@ -104,15 +106,6 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ 	ehci->owned_ports = 0;
+ }
+ 
+-#else	/* CONFIG_USB_PERSIST */
+-
+-static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+-{ }
+-
+-#endif
+-
+-#ifdef	CONFIG_PM
+-
+ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ {
+ 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+@@ -158,10 +151,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 		}
+ 
+ 		/* enable remote wakeup on all ports */
+-		if (device_may_wakeup(&hcd->self.root_hub->dev))
+-			t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
++		if (hcd->self.root_hub->do_remote_wakeup)
++			t2 |= PORT_WAKE_BITS;
+ 		else
+-			t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
++			t2 &= ~PORT_WAKE_BITS;
+ 
+ 		if (t1 != t2) {
+ 			ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
+@@ -183,7 +176,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ 
+ 	/* allow remote wakeup */
+ 	mask = INTR_MASK;
+-	if (!device_may_wakeup(&hcd->self.root_hub->dev))
++	if (!hcd->self.root_hub->do_remote_wakeup)
+ 		mask &= ~STS_PCD;
+ 	ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ 	ehci_readl(ehci, &ehci->regs->intr_enable);
+@@ -241,8 +234,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	i = HCS_N_PORTS (ehci->hcs_params);
+ 	while (i--) {
+ 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+-		temp &= ~(PORT_RWC_BITS
+-			| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
++		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ 		if (test_bit(i, &ehci->bus_suspended) &&
+ 				(temp & PORT_SUSPEND)) {
+ 			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
+@@ -281,9 +273,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ 	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+ 
+ 	spin_unlock_irq (&ehci->lock);
+-
+-	if (!power_okay)
+-		ehci_handover_companion_ports(ehci);
++	ehci_handover_companion_ports(ehci);
+ 	return 0;
+ }
+ 
+@@ -545,8 +535,6 @@ ehci_hub_descriptor (
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-#define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+-
+ static int ehci_hub_control (
+ 	struct usb_hcd	*hcd,
+ 	u16		typeReq,
+@@ -778,7 +766,7 @@ static int ehci_hub_control (
+ 		if (temp & PORT_POWER)
+ 			status |= 1 << USB_PORT_FEAT_POWER;
+ 
+-#ifndef	EHCI_VERBOSE_DEBUG
++#ifndef	VERBOSE_DEBUG
+ 	if (status & ~0xffff)	/* only if wPortChange is interesting */
+ #endif
+ 		dbg_port (ehci, "GetStatus", wIndex + 1, temp);
+@@ -812,8 +800,6 @@ static int ehci_hub_control (
+ 			if ((temp & PORT_PE) == 0
+ 					|| (temp & PORT_RESET) != 0)
+ 				goto error;
+-			if (device_may_wakeup(&hcd->self.root_hub->dev))
+-				temp |= PORT_WAKE_BITS;
+ 			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
+ 			break;
+ 		case USB_PORT_FEAT_POWER:
+diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
+index 3041d8f..601c879 100644
+--- a/drivers/usb/host/ehci-ixp4xx.c
++++ b/drivers/usb/host/ehci-ixp4xx.c
+@@ -140,13 +140,12 @@ static int ixp4xx_ehci_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-MODULE_ALIAS("ixp4xx-ehci");
++MODULE_ALIAS("platform:ixp4xx-ehci");
+ 
+ static struct platform_driver ixp4xx_ehci_driver = {
+ 	.probe = ixp4xx_ehci_probe,
+ 	.remove = ixp4xx_ehci_remove,
+ 	.driver = {
+ 		.name = "ixp4xx-ehci",
+-		.bus = &platform_bus_type
+ 	},
+ };
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index e129981..d187d03 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -11,15 +11,18 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+-#include <asm/arch/orion.h>
++#include <linux/mbus.h>
++#include <asm/plat-orion/ehci-orion.h>
+ 
+ #define rdl(off)	__raw_readl(hcd->regs + (off))
+ #define wrl(off, val)	__raw_writel((val), hcd->regs + (off))
+ 
+-#define USB_CAUSE		0x310
+-#define USB_MASK		0x314
+ #define USB_CMD			0x140
+ #define USB_MODE		0x1a8
++#define USB_CAUSE		0x310
++#define USB_MASK		0x314
++#define USB_WINDOW_CTRL(i)	(0x320 + ((i) << 4))
++#define USB_WINDOW_BASE(i)	(0x324 + ((i) << 4))
+ #define USB_IPG			0x360
+ #define USB_PHY_PWR_CTRL	0x400
+ #define USB_PHY_TX_CTRL		0x420
+@@ -162,8 +165,30 @@ static const struct hc_driver ehci_orion_hc_driver = {
+ 	.bus_resume = ehci_bus_resume,
+ };
+ 
++static void __init
++ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
++				struct mbus_dram_target_info *dram)
++{
++	int i;
++
++	for (i = 0; i < 4; i++) {
++		wrl(USB_WINDOW_CTRL(i), 0);
++		wrl(USB_WINDOW_BASE(i), 0);
++	}
++
++	for (i = 0; i < dram->num_cs; i++) {
++		struct mbus_dram_window *cs = dram->cs + i;
++
++		wrl(USB_WINDOW_CTRL(i), ((cs->size - 1) & 0xffff0000) |
++					(cs->mbus_attr << 8) |
++					(dram->mbus_dram_target_id << 4) | 1);
++		wrl(USB_WINDOW_BASE(i), cs->base);
++	}
++}
++
+ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
+ {
++	struct orion_ehci_data *pd = pdev->dev.platform_data;
+ 	struct resource *res;
+ 	struct usb_hcd *hcd;
+ 	struct ehci_hcd *ehci;
+@@ -227,6 +252,12 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
+ 	ehci->sbrn = 0x20;
+ 
+ 	/*
++	 * (Re-)program MBUS remapping windows if we are asked to.
++	 */
++	if (pd != NULL && pd->dram != NULL)
++		ehci_orion_conf_mbus_windows(hcd, pd->dram);
++
++	/*
+ 	 * setup Orion USB controller
+ 	 */
+ 	orion_usb_setup(hcd);
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 72ccd56..5bb7f6b 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -130,6 +130,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 	case PCI_VENDOR_ID_TDI:
+ 		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+ 			ehci->is_tdi_rh_tt = 1;
++			hcd->has_tt = 1;
+ 			tdi_reset(ehci);
+ 		}
+ 		break;
+@@ -221,6 +222,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ 		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
+ #endif
+ 
++	ehci_port_power(ehci, 1);
+ 	retval = ehci_pci_reinit(ehci, pdev);
+ done:
+ 	return retval;
+@@ -299,7 +301,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+ 		int	mask = INTR_MASK;
+ 
+-		if (!device_may_wakeup(&hcd->self.root_hub->dev))
++		if (!hcd->self.root_hub->do_remote_wakeup)
+ 			mask &= ~STS_PCD;
+ 		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ 		ehci_readl(ehci, &ehci->regs->intr_enable);
+@@ -329,7 +331,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ 
+ 	/* here we "know" root ports should always stay powered */
+ 	ehci_port_power(ehci, 1);
+-	ehci_handover_companion_ports(ehci);
+ 
+ 	hcd->state = HC_STATE_SUSPENDED;
+ 	return 0;
+@@ -353,8 +354,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
+ 	.reset =		ehci_pci_setup,
+ 	.start =		ehci_run,
+ #ifdef	CONFIG_PM
+-	.suspend =		ehci_pci_suspend,
+-	.resume =		ehci_pci_resume,
++	.pci_suspend =		ehci_pci_suspend,
++	.pci_resume =		ehci_pci_resume,
+ #endif
+ 	.stop =			ehci_stop,
+ 	.shutdown =		ehci_shutdown,
+diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
+index a324907..6c76036 100644
+--- a/drivers/usb/host/ehci-ppc-soc.c
++++ b/drivers/usb/host/ehci-ppc-soc.c
+@@ -175,6 +175,7 @@ static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
+ 	if (usb_disabled())
+ 		return -ENODEV;
+ 
++	/* FIXME we only want one one probe() not two */
+ 	ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev);
+ 	return ret;
+ }
+@@ -183,17 +184,17 @@ static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
+ {
+ 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ 
++	/* FIXME we only want one one remove() not two */
+ 	usb_ehci_ppc_soc_remove(hcd, pdev);
+ 	return 0;
+ }
+ 
+-MODULE_ALIAS("ppc-soc-ehci");
++MODULE_ALIAS("platform:ppc-soc-ehci");
+ static struct platform_driver ehci_ppc_soc_driver = {
+ 	.probe = ehci_hcd_ppc_soc_drv_probe,
+ 	.remove = ehci_hcd_ppc_soc_drv_remove,
+ 	.shutdown = usb_hcd_platform_shutdown,
+ 	.driver = {
+ 		.name = "ppc-soc-ehci",
+-		.bus = &platform_bus_type
+ 	}
+ };
+diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
+index bbda58e..6978222 100644
+--- a/drivers/usb/host/ehci-ps3.c
++++ b/drivers/usb/host/ehci-ps3.c
+@@ -125,7 +125,6 @@ static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
+ 		goto fail_irq;
+ 	}
+ 
+-	dev->core.power.power_state = PMSG_ON;
+ 	dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
+ 
+ 	hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev->core.bus_id);
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 2e49de8..5ae6891 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -242,7 +242,8 @@ __acquires(ehci->lock)
+ 	if (unlikely(urb->unlinked)) {
+ 		COUNT(ehci->stats.unlink);
+ 	} else {
+-		if (likely(status == -EINPROGRESS))
++		/* report non-error and short read status as zero */
++		if (status == -EINPROGRESS || status == -EREMOTEIO)
+ 			status = 0;
+ 		COUNT(ehci->stats.complete);
+ 	}
+@@ -250,7 +251,7 @@ __acquires(ehci->lock)
+ #ifdef EHCI_URB_TRACE
+ 	ehci_dbg (ehci,
+ 		"%s %s urb %p ep%d%s status %d len %d/%d\n",
+-		__FUNCTION__, urb->dev->devpath, urb,
++		__func__, urb->dev->devpath, urb,
+ 		usb_pipeendpoint (urb->pipe),
+ 		usb_pipein (urb->pipe) ? "in" : "out",
+ 		status,
+@@ -283,7 +284,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 	int			last_status = -EINPROGRESS;
+ 	int			stopped;
+ 	unsigned		count = 0;
+-	int			do_status = 0;
+ 	u8			state;
+ 	u32			halt = HALT_BIT(ehci);
+ 
+@@ -309,7 +309,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		struct ehci_qtd	*qtd;
+ 		struct urb	*urb;
+ 		u32		token = 0;
+-		int		qtd_status;
+ 
+ 		qtd = list_entry (entry, struct ehci_qtd, qtd_list);
+ 		urb = qtd->urb;
+@@ -336,11 +335,20 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 		/* always clean up qtds the hc de-activated */
+ 		if ((token & QTD_STS_ACTIVE) == 0) {
+ 
++			/* on STALL, error, and short reads this urb must
++			 * complete and all its qtds must be recycled.
++			 */
+ 			if ((token & QTD_STS_HALT) != 0) {
+ 				stopped = 1;
+ 
+ 			/* magic dummy for some short reads; qh won't advance.
+ 			 * that silicon quirk can kick in with this dummy too.
++			 *
++			 * other short reads won't stop the queue, including
++			 * control transfers (status stage handles that) or
++			 * most other single-qtd reads ... the queue stops if
++			 * URB_SHORT_NOT_OK was set so the driver submitting
++			 * the urbs could clean it up.
+ 			 */
+ 			} else if (IS_SHORT_READ (token)
+ 					&& !(qtd->hw_alt_next
+@@ -354,28 +362,21 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ 				&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
+ 			break;
+ 
++		/* scan the whole queue for unlinks whenever it stops */
+ 		} else {
+ 			stopped = 1;
+ 
+-			if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)))
++			/* cancel everything if we halt, suspend, etc */
++			if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
+ 				last_status = -ESHUTDOWN;
+ 
+-			/* ignore active urbs unless some previous qtd
+-			 * for the urb faulted (including short read) or
+-			 * its urb was canceled.  we may patch qh or qtds.
++			/* this qtd is active; skip it unless a previous qtd
++			 * for its urb faulted, or its urb was canceled.
+ 			 */
+-			if (likely(last_status == -EINPROGRESS &&
+-					!urb->unlinked))
+-				continue;
+-
+-			/* issue status after short control reads */
+-			if (unlikely (do_status != 0)
+-					&& QTD_PID (token) == 0 /* OUT */) {
+-				do_status = 0;
++			else if (last_status == -EINPROGRESS && !urb->unlinked)
+ 				continue;
+-			}
+ 
+-			/* token in overlay may be most current */
++			/* qh unlinked; token in overlay may be most current */
+ 			if (state == QH_STATE_IDLE
+ 					&& cpu_to_hc32(ehci, qtd->qtd_dma)
+ 						== qh->hw_current)
+@@ -392,21 +393,32 @@ halt:
+ 			}
+ 		}
+ 
+-		/* remove it from the queue */
+-		qtd_status = qtd_copy_status(ehci, urb, qtd->length, token);
+-		if (unlikely(qtd_status == -EREMOTEIO)) {
+-			do_status = (!urb->unlinked &&
+-					usb_pipecontrol(urb->pipe));
+-			qtd_status = 0;
++		/* unless we already know the urb's status, collect qtd status
++		 * and update count of bytes transferred.  in common short read
++		 * cases with only one data qtd (including control transfers),
++		 * queue processing won't halt.  but with two or more qtds (for
++		 * example, with a 32 KB transfer), when the first qtd gets a
++		 * short read the second must be removed by hand.
++		 */
++		if (last_status == -EINPROGRESS) {
++			last_status = qtd_copy_status(ehci, urb,
++					qtd->length, token);
++			if (last_status == -EREMOTEIO
++					&& (qtd->hw_alt_next
++						& EHCI_LIST_END(ehci)))
++				last_status = -EINPROGRESS;
+ 		}
+-		if (likely(last_status == -EINPROGRESS))
+-			last_status = qtd_status;
+ 
++		/* if we're removing something not at the queue head,
++		 * patch the hardware queue pointer.
++		 */
+ 		if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
+ 			last = list_entry (qtd->qtd_list.prev,
+ 					struct ehci_qtd, qtd_list);
+ 			last->hw_next = qtd->hw_next;
+ 		}
++
++		/* remove qtd; it's recycled after possible urb completion */
+ 		list_del (&qtd->qtd_list);
+ 		last = qtd;
+ 	}
+@@ -431,7 +443,15 @@ halt:
+ 			qh_refresh(ehci, qh);
+ 			break;
+ 		case QH_STATE_LINKED:
+-			/* should be rare for periodic transfers,
++			/* We won't refresh a QH that's linked (after the HC
++			 * stopped the queue).  That avoids a race:
++			 *  - HC reads first part of QH;
++			 *  - CPU updates that first part and the token;
++			 *  - HC reads rest of that QH, including token
++			 * Result:  HC gets an inconsistent image, and then
++			 * DMAs to/from the wrong memory (corrupting it).
++			 *
++			 * That should be rare for interrupt transfers,
+ 			 * except maybe high bandwidth ...
+ 			 */
+ 			if ((cpu_to_hc32(ehci, QH_SMASK)
+@@ -549,6 +569,12 @@ qh_urb_transaction (
+ 		this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket);
+ 		len -= this_qtd_len;
+ 		buf += this_qtd_len;
++
++		/*
++		 * short reads advance to a "magic" dummy instead of the next
++		 * qtd ... that forces the queue to stop, for manual cleanup.
++		 * (this will usually be overridden later.)
++		 */
+ 		if (is_input)
+ 			qtd->hw_alt_next = ehci->async->hw_alt_next;
+ 
+@@ -568,8 +594,10 @@ qh_urb_transaction (
+ 		list_add_tail (&qtd->qtd_list, head);
+ 	}
+ 
+-	/* unless the bulk/interrupt caller wants a chance to clean
+-	 * up after short reads, hc should advance qh past this urb
++	/*
++	 * unless the caller requires manual cleanup after short reads,
++	 * have the alt_next mechanism keep the queue running after the
++	 * last data qtd (the only one, for control and most other cases).
+ 	 */
+ 	if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
+ 				|| usb_pipecontrol (urb->pipe)))
+@@ -657,6 +685,14 @@ qh_make (
+ 	type = usb_pipetype (urb->pipe);
+ 	maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input);
+ 
++	/* 1024 byte maxpacket is a hardware ceiling.  High bandwidth
++	 * acts like up to 3KB, but is built from smaller packets.
++	 */
++	if (max_packet(maxp) > 1024) {
++		ehci_dbg(ehci, "bogus qh maxpacket %d\n", max_packet(maxp));
++		goto done;
++	}
++
+ 	/* Compute interrupt scheduling parameters just once, and save.
+ 	 * - allowing for high bandwidth, how many nsec/uframe are used?
+ 	 * - split transactions need a second CSPLIT uframe; same question
+@@ -757,7 +793,13 @@ qh_make (
+ 			info2 |= (EHCI_TUNE_MULT_HS << 30);
+ 		} else if (type == PIPE_BULK) {
+ 			info1 |= (EHCI_TUNE_RL_HS << 28);
+-			info1 |= 512 << 16;	/* usb2 fixed maxpacket */
++			/* The USB spec says that high speed bulk endpoints
++			 * always use 512 byte maxpacket.  But some device
++			 * vendors decided to ignore that, and MSFT is happy
++			 * to help them do so.  So now people expect to use
++			 * such nonconformant devices with Linux too; sigh.
++			 */
++			info1 |= max_packet(maxp) << 16;
+ 			info2 |= (EHCI_TUNE_MULT_HS << 30);
+ 		} else {		/* PIPE_INTERRUPT */
+ 			info1 |= max_packet (maxp) << 16;
+@@ -932,7 +974,7 @@ submit_async (
+ #ifdef EHCI_URB_TRACE
+ 	ehci_dbg (ehci,
+ 		"%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+-		__FUNCTION__, urb->dev->devpath, urb,
++		__func__, urb->dev->devpath, urb,
+ 		epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
+ 		urb->transfer_buffer_length,
+ 		qtd, urb->ep->hcpriv);
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 8a8e08a..be575e4 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -440,11 +440,10 @@ static int enable_periodic (struct ehci_hcd *ehci)
+ 	/* did clearing PSE did take effect yet?
+ 	 * takes effect only at frame boundaries...
+ 	 */
+-	status = handshake(ehci, &ehci->regs->status, STS_PSS, 0, 9 * 125);
+-	if (status != 0) {
+-		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
++					     STS_PSS, 0, 9 * 125);
++	if (status)
+ 		return status;
+-	}
+ 
+ 	cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
+ 	ehci_writel(ehci, cmd, &ehci->regs->command);
+@@ -465,11 +464,10 @@ static int disable_periodic (struct ehci_hcd *ehci)
+ 	/* did setting PSE not take effect yet?
+ 	 * takes effect only at frame boundaries...
+ 	 */
+-	status = handshake(ehci, &ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
+-	if (status != 0) {
+-		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++	status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
++					     STS_PSS, STS_PSS, 9 * 125);
++	if (status)
+ 		return status;
+-	}
+ 
+ 	cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
+ 	ehci_writel(ehci, cmd, &ehci->regs->command);
+@@ -1183,21 +1181,18 @@ itd_urb_transaction (
+ 					struct ehci_itd, itd_list);
+ 			list_del (&itd->itd_list);
+ 			itd_dma = itd->itd_dma;
+-		} else
+-			itd = NULL;
+-
+-		if (!itd) {
++		} else {
+ 			spin_unlock_irqrestore (&ehci->lock, flags);
+ 			itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
+ 					&itd_dma);
+ 			spin_lock_irqsave (&ehci->lock, flags);
++			if (!itd) {
++				iso_sched_free(stream, sched);
++				spin_unlock_irqrestore(&ehci->lock, flags);
++				return -ENOMEM;
++			}
+ 		}
+ 
+-		if (unlikely (NULL == itd)) {
+-			iso_sched_free (stream, sched);
+-			spin_unlock_irqrestore (&ehci->lock, flags);
+-			return -ENOMEM;
+-		}
+ 		memset (itd, 0, sizeof *itd);
+ 		itd->itd_dma = itd_dma;
+ 		list_add (&itd->itd_list, &sched->td_list);
+@@ -1682,7 +1677,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ #ifdef EHCI_URB_TRACE
+ 	ehci_dbg (ehci,
+ 		"%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n",
+-		__FUNCTION__, urb->dev->devpath, urb,
++		__func__, urb->dev->devpath, urb,
+ 		usb_pipeendpoint (urb->pipe),
+ 		usb_pipein (urb->pipe) ? "in" : "out",
+ 		urb->transfer_buffer_length,
+@@ -1816,21 +1811,18 @@ sitd_urb_transaction (
+ 					 struct ehci_sitd, sitd_list);
+ 			list_del (&sitd->sitd_list);
+ 			sitd_dma = sitd->sitd_dma;
+-		} else
+-			sitd = NULL;
+-
+-		if (!sitd) {
++		} else {
+ 			spin_unlock_irqrestore (&ehci->lock, flags);
+ 			sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags,
+ 					&sitd_dma);
+ 			spin_lock_irqsave (&ehci->lock, flags);
++			if (!sitd) {
++				iso_sched_free(stream, iso_sched);
++				spin_unlock_irqrestore(&ehci->lock, flags);
++				return -ENOMEM;
++			}
+ 		}
+ 
+-		if (!sitd) {
+-			iso_sched_free (stream, iso_sched);
+-			spin_unlock_irqrestore (&ehci->lock, flags);
+-			return -ENOMEM;
+-		}
+ 		memset (sitd, 0, sizeof *sitd);
+ 		sitd->sitd_dma = sitd_dma;
+ 		list_add (&sitd->sitd_list, &iso_sched->td_list);
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 203a335..20b9a0d 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -1400,7 +1400,7 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd)
+ 		spin_unlock_irqrestore(&isp116x->lock, flags);
+ 		val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
+ 		val |= HCCONTROL_USB_SUSPEND;
+-		if (device_may_wakeup(&hcd->self.root_hub->dev))
++		if (hcd->self.root_hub->do_remote_wakeup)
+ 			val |= HCCONTROL_RWE;
+ 		/* Wait for usb transfers to finish */
+ 		msleep(2);
+@@ -1442,11 +1442,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
+ 		break;
+ 	case HCCONTROL_USB_OPER:
+ 		spin_unlock_irq(&isp116x->lock);
+-		/* Without setting power_state here the
+-		   SUSPENDED state won't be removed from
+-		   sysfs/usbN/power.state as a response to remote
+-		   wakeup. Maybe in the future. */
+-		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ 		return 0;
+ 	default:
+ 		/* HCCONTROL_USB_RESET: this may happen, when during
+@@ -1460,7 +1455,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
+ 		if ((isp116x->rhdesca & RH_A_NDP) == 2)
+ 			isp116x_hub_control(hcd, SetPortFeature,
+ 					    USB_PORT_FEAT_POWER, 2, NULL, 0);
+-		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ 		return 0;
+ 	}
+ 
+@@ -1486,8 +1480,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
+ 	isp116x_write_reg32(isp116x, HCCONTROL,
+ 			    (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
+ 	spin_unlock_irq(&isp116x->lock);
+-	/* see analogous comment above */
+-	hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ 	hcd->state = HC_STATE_RUNNING;
+ 
+ 	return 0;
+@@ -1663,7 +1655,6 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
+ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ 	VDBG("%s: state %x\n", __func__, state.event);
+-	dev->dev.power.power_state = state;
+ 	return 0;
+ }
+ 
+@@ -1672,8 +1663,7 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
+ */
+ static int isp116x_resume(struct platform_device *dev)
+ {
+-	VDBG("%s:  state %x\n", __func__, dev->power.power_state.event);
+-	dev->dev.power.power_state = PMSG_ON;
++	VDBG("%s\n", __func__);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index d72dc07..c96db11 100644
+--- a/drivers/usb/host/ohci-at91.c
++++ b/drivers/usb/host/ohci-at91.c
+@@ -261,7 +261,6 @@ static const struct hc_driver ohci_at91_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+@@ -348,6 +347,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
+ 	if (!clocked)
+ 		at91_start_clock();
+ 
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ #else
+diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
+index f90fe0c..1b9abdb 100644
+--- a/drivers/usb/host/ohci-au1xxx.c
++++ b/drivers/usb/host/ohci-au1xxx.c
+@@ -288,7 +288,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index a22c30a..e06bfae 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -655,7 +655,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ 		hcd->product_desc,
+ 		hcd_name);
+ 
+-	if (bus->controller->power.power_state.event) {
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ 		size -= scnprintf (next, size,
+ 			"SUSPENDED (no register access)\n");
+ 		goto done;
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+index 156e93a..06aadfb 100644
+--- a/drivers/usb/host/ohci-ep93xx.c
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -135,7 +135,6 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
+ 	.get_frame_number	= ohci_get_frame,
+ 	.hub_status_data	= ohci_hub_status_data,
+ 	.hub_control		= ohci_hub_control,
+-	.hub_irq_enable		= ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ 	.bus_suspend		= ohci_bus_suspend,
+ 	.bus_resume		= ohci_bus_resume,
+@@ -177,7 +176,6 @@ static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_
+ 
+ 	ep93xx_stop_hc(&pdev->dev);
+ 	hcd->state = HC_STATE_SUSPENDED;
+-	pdev->dev.power.power_state = PMSG_SUSPEND;
+ 
+ 	return 0;
+ }
+@@ -193,9 +191,8 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
+ 	ohci->next_statechange = jiffies;
+ 
+ 	ep93xx_start_hc(&pdev->dev);
+-	pdev->dev.power.power_state = PMSG_ON;
+-	usb_hcd_resume_root_hub(hcd);
+ 
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 48e4b11..5be3bb3 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -36,18 +36,6 @@
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* hcd->hub_irq_enable() */
+-static void ohci_rhsc_enable (struct usb_hcd *hcd)
+-{
+-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+-
+-	spin_lock_irq(&ohci->lock);
+-	if (!ohci->autostop)
+-		del_timer(&hcd->rh_timer);	/* Prevent next poll */
+-	ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+-	spin_unlock_irq(&ohci->lock);
+-}
+-
+ #define OHCI_SCHED_ENABLES \
+ 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
+ 
+@@ -103,11 +91,11 @@ __acquires(ohci->lock)
+ 	finish_unlinks (ohci, ohci_frame_no(ohci));
+ 
+ 	/* maybe resume can wake root hub */
+-	if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
+-			autostop)
++	if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
+ 		ohci->hc_control |= OHCI_CTRL_RWE;
+-	else {
+-		ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
++	} else {
++		ohci_writel(ohci, OHCI_INTR_RHSC | OHCI_INTR_RD,
++				&ohci->regs->intrdisable);
+ 		ohci->hc_control &= ~OHCI_CTRL_RWE;
+ 	}
+ 
+@@ -326,23 +314,76 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ 	return rc;
+ }
+ 
++/* Carry out the final steps of resuming the controller device */
++static void ohci_finish_controller_resume(struct usb_hcd *hcd)
++{
++	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
++	int			port;
++	bool			need_reinit = false;
++
++	/* See if the controller is already running or has been reset */
++	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
++	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
++		need_reinit = true;
++	} else {
++		switch (ohci->hc_control & OHCI_CTRL_HCFS) {
++		case OHCI_USB_OPER:
++		case OHCI_USB_RESET:
++			need_reinit = true;
++		}
++	}
++
++	/* If needed, reinitialize and suspend the root hub */
++	if (need_reinit) {
++		spin_lock_irq(&ohci->lock);
++		hcd->state = HC_STATE_RESUMING;
++		ohci_rh_resume(ohci);
++		hcd->state = HC_STATE_QUIESCING;
++		ohci_rh_suspend(ohci, 0);
++		hcd->state = HC_STATE_SUSPENDED;
++		spin_unlock_irq(&ohci->lock);
++	}
++
++	/* Normally just turn on port power and enable interrupts */
++	else {
++		ohci_dbg(ohci, "powerup ports\n");
++		for (port = 0; port < ohci->num_ports; port++)
++			ohci_writel(ohci, RH_PS_PPS,
++					&ohci->regs->roothub.portstatus[port]);
++
++		ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
++		ohci_readl(ohci, &ohci->regs->intrenable);
++		msleep(20);
++	}
++}
++
+ /* Carry out polling-, autostop-, and autoresume-related state changes */
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 		int any_connected)
+ {
+ 	int	poll_rh = 1;
++	int	rhsc;
+ 
++	rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
+ 	switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+ 
+ 	case OHCI_USB_OPER:
+-		/* keep on polling until we know a device is connected
+-		 * and RHSC is enabled */
++		/* If no status changes are pending, enable status-change
++		 * interrupts.
++		 */
++		if (!rhsc && !changed) {
++			rhsc = OHCI_INTR_RHSC;
++			ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
++		}
++
++		/* Keep on polling until we know a device is connected
++		 * and RHSC is enabled, or until we autostop.
++		 */
+ 		if (!ohci->autostop) {
+ 			if (any_connected ||
+ 					!device_may_wakeup(&ohci_to_hcd(ohci)
+ 						->self.root_hub->dev)) {
+-				if (ohci_readl(ohci, &ohci->regs->intrenable) &
+-						OHCI_INTR_RHSC)
++				if (rhsc)
+ 					poll_rh = 0;
+ 			} else {
+ 				ohci->autostop = 1;
+@@ -355,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 				ohci->autostop = 0;
+ 				ohci->next_statechange = jiffies +
+ 						STATECHANGE_DELAY;
+-			} else if (time_after_eq(jiffies,
++			} else if (rhsc && time_after_eq(jiffies,
+ 						ohci->next_statechange)
+ 					&& !ohci->ed_rm_list
+ 					&& !(ohci->hc_control &
+ 						OHCI_SCHED_ENABLES)) {
+ 				ohci_rh_suspend(ohci, 1);
++				poll_rh = 0;
+ 			}
+ 		}
+ 		break;
+@@ -374,6 +416,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 			else
+ 				usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
+ 		} else {
++			if (!rhsc && (ohci->autostop ||
++					ohci_to_hcd(ohci)->self.root_hub->
++						do_remote_wakeup))
++				ohci_writel(ohci, OHCI_INTR_RHSC,
++						&ohci->regs->intrenable);
++
+ 			/* everything is idle, no need for polling */
+ 			poll_rh = 0;
+ 		}
+@@ -395,12 +443,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ 		int any_connected)
+ {
+-	int	poll_rh = 1;
+-
+-	/* keep on polling until RHSC is enabled */
++	/* If RHSC is enabled, don't poll */
+ 	if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+-		poll_rh = 0;
+-	return poll_rh;
++		return 0;
++
++	/* If no status changes are pending, enable status-change interrupts */
++	if (!changed) {
++		ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
++		return 0;
++	}
++	return 1;
+ }
+ 
+ #endif	/* CONFIG_PM */
+@@ -564,14 +616,18 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
+ 	u32	temp;
+ 	u16	now = ohci_readl(ohci, &ohci->regs->fmnumber);
+ 	u16	reset_done = now + PORT_RESET_MSEC;
++	int	limit_1 = DIV_ROUND_UP(PORT_RESET_MSEC, PORT_RESET_HW_MSEC);
+ 
+ 	/* build a "continuous enough" reset signal, with up to
+ 	 * 3msec gap between pulses.  scheduler HZ==100 must work;
+ 	 * this might need to be deadline-scheduled.
+ 	 */
+ 	do {
++		int limit_2;
++
+ 		/* spin until any current reset finishes */
+-		for (;;) {
++		limit_2 = PORT_RESET_HW_MSEC * 2;
++		while (--limit_2 >= 0) {
+ 			temp = ohci_readl (ohci, portstat);
+ 			/* handle e.g. CardBus eject */
+ 			if (temp == ~(u32)0)
+@@ -581,6 +637,17 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
+ 			udelay (500);
+ 		}
+ 
++		/* timeout (a hardware error) has been observed when
++		 * EHCI sets CF while this driver is resetting a port;
++		 * presumably other disconnect paths might do it too.
++		 */
++		if (limit_2 < 0) {
++			ohci_dbg(ohci,
++				"port[%d] reset timeout, stat %08x\n",
++				port, temp);
++			break;
++		}
++
+ 		if (!(temp & RH_PS_CCS))
+ 			break;
+ 		if (temp & RH_PS_PRSC)
+@@ -590,8 +657,11 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
+ 		ohci_writel (ohci, RH_PS_PRS, portstat);
+ 		msleep(PORT_RESET_HW_MSEC);
+ 		now = ohci_readl(ohci, &ohci->regs->fmnumber);
+-	} while (tick_before(now, reset_done));
+-	/* caller synchronizes using PRSC */
++	} while (tick_before(now, reset_done) && --limit_1 >= 0);
++
++	/* caller synchronizes using PRSC ... and handles PRS
++	 * still being set when this returns.
++	 */
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
+index 13c12ed..96d14fa 100644
+--- a/drivers/usb/host/ohci-lh7a404.c
++++ b/drivers/usb/host/ohci-lh7a404.c
+@@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index 7bfca1e..6859fb5 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -466,7 +466,6 @@ static const struct hc_driver ohci_omap_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+@@ -505,21 +504,20 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
+ 
+ 	omap_ohci_clock_power(0);
+ 	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+-	dev->dev.power.power_state = PMSG_SUSPEND;
+ 	return 0;
+ }
+ 
+ static int ohci_omap_resume(struct platform_device *dev)
+ {
+-	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(dev));
++	struct usb_hcd	*hcd = platform_get_drvdata(dev);
++	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+ 
+ 	if (time_before(jiffies, ohci->next_statechange))
+ 		msleep(5);
+ 	ohci->next_statechange = jiffies;
+ 
+ 	omap_ohci_clock_power(1);
+-	dev->dev.power.power_state = PMSG_ON;
+-	usb_hcd_resume_root_hub(platform_get_drvdata(dev));
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index d0360f6..3bf175d 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -238,42 +238,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+ 	return ret;
+ }
+ 
+-#if	defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \
+-		defined(CONFIG_USB_EHCI_HCD_MODULE))
+-
+-/* Following a power loss, we must prepare to regain control of the ports
+- * we used to own.  This means turning on the port power before ehci-hcd
+- * tries to switch ownership.
+- *
+- * This isn't a 100% perfect solution.  On most systems the OHCI controllers
+- * lie at lower PCI addresses than the EHCI controller, so they will be
+- * discovered (and hence resumed) first.  But there is no guarantee things
+- * will always work this way.  If the EHCI controller is resumed first and
+- * the OHCI ports are unpowered, then the handover will fail.
+- */
+-static void prepare_for_handover(struct usb_hcd *hcd)
+-{
+-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+-	int		port;
+-
+-	/* Here we "know" root ports should always stay powered */
+-	ohci_dbg(ohci, "powerup ports\n");
+-	for (port = 0; port < ohci->num_ports; port++)
+-		ohci_writel(ohci, RH_PS_PPS,
+-				&ohci->regs->roothub.portstatus[port]);
+-
+-	/* Flush those writes */
+-	ohci_readl(ohci, &ohci->regs->control);
+-	msleep(20);
+-}
+-
+-#else
+-
+-static inline void prepare_for_handover(struct usb_hcd *hcd)
+-{ }
+-
+-#endif	/* CONFIG_USB_PERSIST etc. */
+-
+ #ifdef	CONFIG_PM
+ 
+ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+@@ -313,10 +277,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+ static int ohci_pci_resume (struct usb_hcd *hcd)
+ {
+ 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+-	/* FIXME: we should try to detect loss of VBUS power here */
+-	prepare_for_handover(hcd);
+-
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ 
+@@ -345,9 +306,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
+ 	.shutdown =		ohci_shutdown,
+ 
+ #ifdef	CONFIG_PM
+-	/* these suspend/resume entries are for upstream PCI glue ONLY */
+-	.suspend =		ohci_pci_suspend,
+-	.resume =		ohci_pci_resume,
++	.pci_suspend =		ohci_pci_suspend,
++	.pci_resume =		ohci_pci_resume,
+ #endif
+ 
+ 	/*
+@@ -367,7 +327,6 @@ static const struct hc_driver ohci_pci_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
+index 28b458f..664f07e 100644
+--- a/drivers/usb/host/ohci-pnx4008.c
++++ b/drivers/usb/host/ohci-pnx4008.c
+@@ -280,7 +280,6 @@ static const struct hc_driver ohci_pnx4008_hc_driver = {
+ 	 */
+ 	.hub_status_data = ohci_hub_status_data,
+ 	.hub_control = ohci_hub_control,
+-	.hub_irq_enable = ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend = ohci_bus_suspend,
+ 	.bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
+index 605d59c..28467e2 100644
+--- a/drivers/usb/host/ohci-pnx8550.c
++++ b/drivers/usb/host/ohci-pnx8550.c
+@@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx8550_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
+index a672527..50e55db 100644
+--- a/drivers/usb/host/ohci-ppc-of.c
++++ b/drivers/usb/host/ohci-ppc-of.c
+@@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
+index 523c301..cd3398b 100644
+--- a/drivers/usb/host/ohci-ppc-soc.c
++++ b/drivers/usb/host/ohci-ppc-soc.c
+@@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
+index 01a0cae..bfdeb0d 100644
+--- a/drivers/usb/host/ohci-ps3.c
++++ b/drivers/usb/host/ohci-ps3.c
+@@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_hc_driver = {
+ 	.get_frame_number	= ohci_get_frame,
+ 	.hub_status_data	= ohci_hub_status_data,
+ 	.hub_control		= ohci_hub_control,
+-	.hub_irq_enable		= ohci_rhsc_enable,
+ 	.start_port_reset	= ohci_start_port_reset,
+ #if defined(CONFIG_PM)
+ 	.bus_suspend 		= ohci_bus_suspend,
+@@ -127,7 +126,6 @@ static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
+ 		goto fail_irq;
+ 	}
+ 
+-	dev->core.power.power_state = PMSG_ON;
+ 	dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
+ 
+ 	hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id);
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index 8ad9b3b..70b0d4b 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef  CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+@@ -339,7 +338,6 @@ static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_
+ 
+ 	pxa27x_stop_hc(&pdev->dev);
+ 	hcd->state = HC_STATE_SUSPENDED;
+-	pdev->dev.power.power_state = PMSG_SUSPEND;
+ 
+ 	return 0;
+ }
+@@ -357,9 +355,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
+ 	if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
+ 		return status;
+ 
+-	pdev->dev.power.power_state = PMSG_ON;
+-	usb_hcd_resume_root_hub(hcd);
+-
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index ead4772..a73d2ff 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_s3c2410_hub_status_data,
+ 	.hub_control =		ohci_s3c2410_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
+index 0f48f2d..99438c6 100644
+--- a/drivers/usb/host/ohci-sa1111.c
++++ b/drivers/usb/host/ohci-sa1111.c
+@@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
+index e7ee607..60f03cc 100644
+--- a/drivers/usb/host/ohci-sh.c
++++ b/drivers/usb/host/ohci-sh.c
+@@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
+index 4ea9276..77204f0 100644
+--- a/drivers/usb/host/ohci-sm501.c
++++ b/drivers/usb/host/ohci-sm501.c
+@@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501_hc_driver = {
+ 	 */
+ 	.hub_status_data =	ohci_hub_status_data,
+ 	.hub_control =		ohci_hub_control,
+-	.hub_irq_enable =	ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend =		ohci_bus_suspend,
+ 	.bus_resume =		ohci_bus_resume,
+@@ -199,7 +198,8 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
+ 	usb_put_hcd(hcd);
+ 	dma_release_declared_memory(&pdev->dev);
+ 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+-	release_mem_region(mem->start, mem->end - mem->start + 1);
++	if (mem)
++		release_mem_region(mem->start, mem->end - mem->start + 1);
+ 
+ 	/* mask interrupts and disable power */
+ 
+@@ -224,24 +224,26 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
+ 
+ 	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
+ 	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+-	dev->power.power_state = PMSG_SUSPEND;
+ 	return 0;
+ }
+ 
+ static int ohci_sm501_resume(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+-	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(pdev));
++	struct usb_hcd	*hcd = platform_get_drvdata(pdev);
++	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+ 
+ 	if (time_before(jiffies, ohci->next_statechange))
+ 		msleep(5);
+ 	ohci->next_statechange = jiffies;
+ 
+ 	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
+-	dev->power.power_state = PMSG_ON;
+-	usb_hcd_resume_root_hub(platform_get_drvdata(pdev));
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
++#else
++#define ohci_sm501_suspend NULL
++#define ohci_sm501_resume NULL
+ #endif
+ 
+ /*-------------------------------------------------------------------------*/
+@@ -253,10 +255,8 @@ static struct platform_driver ohci_hcd_sm501_driver = {
+ 	.probe		= ohci_hcd_sm501_drv_probe,
+ 	.remove		= ohci_hcd_sm501_drv_remove,
+ 	.shutdown	= usb_hcd_platform_shutdown,
+-#ifdef	CONFIG_PM
+ 	.suspend	= ohci_sm501_suspend,
+ 	.resume		= ohci_sm501_resume,
+-#endif
+ 	.driver		= {
+ 		.owner	= THIS_MODULE,
+ 		.name	= "sm501-usb",
+diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
+index 6e9c2d6..c4265ca 100644
+--- a/drivers/usb/host/ohci-ssb.c
++++ b/drivers/usb/host/ohci-ssb.c
+@@ -60,36 +60,6 @@ static int ssb_ohci_start(struct usb_hcd *hcd)
+ 	return err;
+ }
+ 
+-#ifdef CONFIG_PM
+-static int ssb_ohci_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
+-{
+-	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+-	struct ohci_hcd *ohci = &ohcidev->ohci;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ohci->lock, flags);
+-
+-	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+-	ohci_readl(ohci, &ohci->regs->intrdisable); /* commit write */
+-
+-	/* make sure snapshot being resumed re-enumerates everything */
+-	if (message.event == PM_EVENT_PRETHAW)
+-		ohci_usb_reset(ohci);
+-
+-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+-	spin_unlock_irqrestore(&ohci->lock, flags);
+-	return 0;
+-}
+-
+-static int ssb_ohci_hcd_resume(struct usb_hcd *hcd)
+-{
+-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-	usb_hcd_resume_root_hub(hcd);
+-	return 0;
+-}
+-#endif /* CONFIG_PM */
+-
+ static const struct hc_driver ssb_ohci_hc_driver = {
+ 	.description		= "ssb-usb-ohci",
+ 	.product_desc		= "SSB OHCI Controller",
+@@ -103,11 +73,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
+ 	.stop			= ohci_stop,
+ 	.shutdown		= ohci_shutdown,
+ 
+-#ifdef CONFIG_PM
+-	.suspend		= ssb_ohci_hcd_suspend,
+-	.resume			= ssb_ohci_hcd_resume,
+-#endif
+-
+ 	.urb_enqueue		= ohci_urb_enqueue,
+ 	.urb_dequeue		= ohci_urb_dequeue,
+ 	.endpoint_disable	= ohci_endpoint_disable,
+@@ -116,7 +81,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
+ 
+ 	.hub_status_data	= ohci_hub_status_data,
+ 	.hub_control		= ohci_hub_control,
+-	.hub_irq_enable		= ohci_rhsc_enable,
+ #ifdef	CONFIG_PM
+ 	.bus_suspend		= ohci_bus_suspend,
+ 	.bus_resume		= ohci_bus_resume,
+@@ -224,6 +188,7 @@ static int ssb_ohci_resume(struct ssb_device *dev)
+ 
+ 	ssb_device_enable(dev, ohcidev->enable_flags);
+ 
++	ohci_finish_controller_resume(hcd);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 0ee694f..ae6e70e 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -106,7 +106,7 @@ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
+ 	pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup);
+ 	if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
+ 		dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n",
+-				__FUNCTION__, legsup);
++				__func__, legsup);
+ 		goto reset_needed;
+ 	}
+ 
+@@ -114,14 +114,14 @@ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
+ 	if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) ||
+ 			!(cmd & UHCI_USBCMD_EGSM)) {
+ 		dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n",
+-				__FUNCTION__, cmd);
++				__func__, cmd);
+ 		goto reset_needed;
+ 	}
+ 
+ 	intr = inw(base + UHCI_USBINTR);
+ 	if (intr & (~UHCI_USBINTR_RESUME)) {
+ 		dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n",
+-				__FUNCTION__, intr);
++				__func__, intr);
+ 		goto reset_needed;
+ 	}
+ 	return 0;
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index 9f80e52..f4fa93d 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -46,15 +46,17 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Yoshihiro Shimoda");
+ MODULE_ALIAS("platform:r8a66597_hcd");
+ 
+-#define DRIVER_VERSION	"29 May 2007"
++#define DRIVER_VERSION	"10 Apr 2008"
+ 
+ static const char hcd_name[] = "r8a66597_hcd";
+ 
+ /* module parameters */
++#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+ static unsigned short clock = XTAL12;
+ module_param(clock, ushort, 0644);
+ MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
+ 		"(default=0)");
++#endif
+ 
+ static unsigned short vif = LDRV;
+ module_param(vif, ushort, 0644);
+@@ -106,11 +108,22 @@ static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address,
+ 	r8a66597_write(r8a66597, val, devadd_reg);
+ }
+ 
+-static int enable_controller(struct r8a66597 *r8a66597)
++static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
+ {
+ 	u16 tmp;
+ 	int i = 0;
+ 
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++	do {
++		r8a66597_write(r8a66597, SCKE, SYSCFG0);
++		tmp = r8a66597_read(r8a66597, SYSCFG0);
++		if (i++ > 1000) {
++			err("register access fail.");
++			return -ENXIO;
++		}
++	} while ((tmp & SCKE) != SCKE);
++	r8a66597_write(r8a66597, 0x04, 0x02);
++#else
+ 	do {
+ 		r8a66597_write(r8a66597, USBE, SYSCFG0);
+ 		tmp = r8a66597_read(r8a66597, SYSCFG0);
+@@ -132,13 +145,63 @@ static int enable_controller(struct r8a66597 *r8a66597)
+ 			return -ENXIO;
+ 		}
+ 	} while ((tmp & SCKE) != SCKE);
++#endif	/* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
++
++	return 0;
++}
++
++static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
++{
++	r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
++	udelay(1);
++#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++	r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
++	r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
++	r8a66597_bclr(r8a66597, USBE, SYSCFG0);
++#endif
++}
++
++static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
++{
++	u16 val;
++
++	val = port ? DRPD : DCFM | DRPD;
++	r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
++	r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
++
++	r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port));
++	r8a66597_bclr(r8a66597, DTCHE, get_intenb_reg(port));
++	r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
++}
+ 
+-	r8a66597_bset(r8a66597, DCFM | DRPD, SYSCFG0);
+-	r8a66597_bset(r8a66597, DRPD, SYSCFG1);
++static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port)
++{
++	u16 val, tmp;
++
++	r8a66597_write(r8a66597, 0, get_intenb_reg(port));
++	r8a66597_write(r8a66597, 0, get_intsts_reg(port));
++
++	r8a66597_port_power(r8a66597, port, 0);
++
++	do {
++		tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
++		udelay(640);
++	} while (tmp == EDGESTS);
++
++	val = port ? DRPD : DCFM | DRPD;
++	r8a66597_bclr(r8a66597, val, get_syscfg_reg(port));
++	r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
++}
++
++static int enable_controller(struct r8a66597 *r8a66597)
++{
++	int ret, port;
++
++	ret = r8a66597_clock_enable(r8a66597);
++	if (ret < 0)
++		return ret;
+ 
+ 	r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+-	r8a66597_bset(r8a66597, HSE, SYSCFG0);
+-	r8a66597_bset(r8a66597, HSE, SYSCFG1);
+ 	r8a66597_bset(r8a66597, USBE, SYSCFG0);
+ 
+ 	r8a66597_bset(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+@@ -146,53 +209,30 @@ static int enable_controller(struct r8a66597 *r8a66597)
+ 	r8a66597_bset(r8a66597, BRDY0, BRDYENB);
+ 	r8a66597_bset(r8a66597, BEMP0, BEMPENB);
+ 
+-	r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA0CFG);
+-	r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA1CFG);
+-
+ 	r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
+ 	r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
+ 	r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
+-
+ 	r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
+ 
+ 	r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1);
+-	r8a66597_bclr(r8a66597, DTCHE, INTENB1);
+-	r8a66597_bset(r8a66597, ATTCHE, INTENB1);
+-	r8a66597_bclr(r8a66597, DTCHE, INTENB2);
+-	r8a66597_bset(r8a66597, ATTCHE, INTENB2);
++
++	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
++		r8a66597_enable_port(r8a66597, port);
+ 
+ 	return 0;
+ }
+ 
+ static void disable_controller(struct r8a66597 *r8a66597)
+ {
+-	u16 tmp;
++	int port;
+ 
+ 	r8a66597_write(r8a66597, 0, INTENB0);
+-	r8a66597_write(r8a66597, 0, INTENB1);
+-	r8a66597_write(r8a66597, 0, INTENB2);
+ 	r8a66597_write(r8a66597, 0, INTSTS0);
+-	r8a66597_write(r8a66597, 0, INTSTS1);
+-	r8a66597_write(r8a66597, 0, INTSTS2);
+-
+-	r8a66597_port_power(r8a66597, 0, 0);
+-	r8a66597_port_power(r8a66597, 1, 0);
+-
+-	do {
+-		tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+-		udelay(640);
+-	} while (tmp == EDGESTS);
+ 
+-	r8a66597_bclr(r8a66597, DCFM | DRPD, SYSCFG0);
+-	r8a66597_bclr(r8a66597, DRPD, SYSCFG1);
+-	r8a66597_bclr(r8a66597, HSE, SYSCFG0);
+-	r8a66597_bclr(r8a66597, HSE, SYSCFG1);
++	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
++		r8a66597_disable_port(r8a66597, port);
+ 
+-	r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+-	udelay(1);
+-	r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+-	r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+-	r8a66597_bclr(r8a66597, USBE, SYSCFG0);
++	r8a66597_clock_disable(r8a66597);
+ }
+ 
+ static int get_parent_r8a66597_address(struct r8a66597 *r8a66597,
+@@ -577,13 +617,9 @@ static void pipe_buffer_setting(struct r8a66597 *r8a66597,
+ 		       PIPEBUF);
+ 	r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket,
+ 		       PIPEMAXP);
+-	if (info->interval)
+-		info->interval--;
+ 	r8a66597_write(r8a66597, info->interval, PIPEPERI);
+ }
+ 
+-
+-
+ /* this function must be called with interrupt disabled */
+ static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+ {
+@@ -715,6 +751,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
+ 				     struct r8a66597_pipe *pipe,
+ 				     struct urb *urb)
+ {
++#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+ 	int i;
+ 	struct r8a66597_pipe_info *info = &pipe->info;
+ 
+@@ -742,6 +779,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
+ 			break;
+ 		}
+ 	}
++#endif	/* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
+ }
+ 
+ /* this function must be called with interrupt disabled */
+@@ -825,6 +863,25 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
+ 	dev->dma_map = 0;
+ }
+ 
++static unsigned long get_timer_interval(struct urb *urb, __u8 interval)
++{
++	__u8 i;
++	unsigned long time = 1;
++
++	if (usb_pipeisoc(urb->pipe))
++		return 0;
++
++	if (get_r8a66597_usb_speed(urb->dev->speed) == HSMODE) {
++		for (i = 0; i < (interval - 1); i++)
++			time *= 2;
++		time = time * 125 / 1000;	/* uSOF -> msec */
++	} else {
++		time = interval;
++	}
++
++	return time;
++}
++
+ /* this function must be called with interrupt disabled */
+ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
+ 			   struct usb_host_endpoint *hep,
+@@ -840,7 +897,16 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
+ 				      & USB_ENDPOINT_XFERTYPE_MASK);
+ 	info.bufnum = get_bufnum(info.pipenum);
+ 	info.buf_bsize = get_buf_bsize(info.pipenum);
+-	info.interval = ep->bInterval;
++	if (info.type == R8A66597_BULK) {
++		info.interval = 0;
++		info.timer_interval = 0;
++	} else {
++		if (ep->bInterval > IITV)
++			info.interval = IITV;
++		else
++			info.interval = ep->bInterval ? ep->bInterval - 1 : 0;
++		info.timer_interval = get_timer_interval(urb, ep->bInterval);
++	}
+ 	if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ 		info.dir_in = 1;
+ 	else
+@@ -876,10 +942,19 @@ static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
+ }
+ 
+ /* this function must be called with interrupt disabled */
+-static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port)
++static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
++					u16 syssts)
+ {
+-	r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
+-					 | (1 << USB_PORT_FEAT_C_CONNECTION);
++	if (syssts == SE0) {
++		r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
++		return;
++	}
++
++	if (syssts == FS_JSTS)
++		r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
++	else if (syssts == LS_JSTS)
++		r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
++
+ 	r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
+ 	r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
+ }
+@@ -960,9 +1035,9 @@ static void prepare_packet_read(struct r8a66597 *r8a66597,
+ 				r8a66597_write(r8a66597, TRCLR,
+ 						td->pipe->pipetre);
+ 				r8a66597_write(r8a66597,
+-						(urb->transfer_buffer_length
+-						+ td->maxpacket - 1)
+-						/ td->maxpacket,
++						DIV_ROUND_UP
++						  (urb->transfer_buffer_length,
++						   td->maxpacket),
+ 						td->pipe->pipetrn);
+ 				r8a66597_bset(r8a66597, TRENB,
+ 						td->pipe->pipetre);
+@@ -1021,8 +1096,7 @@ static void prepare_status_packet(struct r8a66597 *r8a66597,
+ 		r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+ 		r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+ 		r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+-		r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+-		r8a66597_write(r8a66597, BVAL, CFIFOCTR);
++		r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR);
+ 		enable_irq_empty(r8a66597, 0);
+ 	} else {
+ 		r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+@@ -1454,13 +1528,21 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
+ 	}
+ }
+ 
++static void r8a66597_root_hub_start_polling(struct r8a66597 *r8a66597)
++{
++	mod_timer(&r8a66597->rh_timer,
++			jiffies + msecs_to_jiffies(R8A66597_RH_POLL_TIME));
++}
++
+ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port)
+ {
+ 	struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+ 
+ 	rh->old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+ 	rh->scount = R8A66597_MAX_SAMPLING;
+-	mod_timer(&r8a66597->rh_timer, jiffies + msecs_to_jiffies(50));
++	r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
++					 | (1 << USB_PORT_FEAT_C_CONNECTION);
++	r8a66597_root_hub_start_polling(r8a66597);
+ }
+ 
+ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
+@@ -1547,41 +1629,55 @@ static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
+ 		if ((tmp & USBRST) == USBRST) {
+ 			r8a66597_mdfy(r8a66597, UACT, USBRST | UACT,
+ 				      dvstctr_reg);
+-			mod_timer(&r8a66597->rh_timer,
+-				  jiffies + msecs_to_jiffies(50));
++			r8a66597_root_hub_start_polling(r8a66597);
+ 		} else
+ 			r8a66597_usb_connect(r8a66597, port);
+ 	}
+ 
++	if (!(rh->port & (1 << USB_PORT_FEAT_CONNECTION))) {
++		r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
++		r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
++	}
++
+ 	if (rh->scount > 0) {
+ 		tmp = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+ 		if (tmp == rh->old_syssts) {
+ 			rh->scount--;
+-			if (rh->scount == 0) {
+-				if (tmp == FS_JSTS) {
+-					r8a66597_bset(r8a66597, HSE,
+-						      get_syscfg_reg(port));
+-					r8a66597_usb_preconnect(r8a66597, port);
+-				} else if (tmp == LS_JSTS) {
+-					r8a66597_bclr(r8a66597, HSE,
+-						      get_syscfg_reg(port));
+-					r8a66597_usb_preconnect(r8a66597, port);
+-				} else if (tmp == SE0)
+-					r8a66597_bset(r8a66597, ATTCHE,
+-						      get_intenb_reg(port));
+-			} else {
+-				mod_timer(&r8a66597->rh_timer,
+-					  jiffies + msecs_to_jiffies(50));
+-			}
++			if (rh->scount == 0)
++				r8a66597_check_syssts(r8a66597, port, tmp);
++			else
++				r8a66597_root_hub_start_polling(r8a66597);
+ 		} else {
+ 			rh->scount = R8A66597_MAX_SAMPLING;
+ 			rh->old_syssts = tmp;
+-			mod_timer(&r8a66597->rh_timer,
+-				  jiffies + msecs_to_jiffies(50));
++			r8a66597_root_hub_start_polling(r8a66597);
+ 		}
+ 	}
+ }
+ 
++static void r8a66597_interval_timer(unsigned long _r8a66597)
++{
++	struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
++	unsigned long flags;
++	u16 pipenum;
++	struct r8a66597_td *td;
++
++	spin_lock_irqsave(&r8a66597->lock, flags);
++
++	for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
++		if (!(r8a66597->interval_map & (1 << pipenum)))
++			continue;
++		if (timer_pending(&r8a66597->interval_timer[pipenum]))
++			continue;
++
++		td = r8a66597_get_td(r8a66597, pipenum);
++		if (td)
++			start_transfer(r8a66597, td);
++	}
++
++	spin_unlock_irqrestore(&r8a66597->lock, flags);
++}
++
+ static void r8a66597_td_timer(unsigned long _r8a66597)
+ {
+ 	struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+@@ -1763,10 +1859,17 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
+ 	urb->hcpriv = td;
+ 
+ 	if (request) {
+-		ret = start_transfer(r8a66597, td);
+-		if (ret < 0) {
+-			list_del(&td->queue);
+-			kfree(td);
++		if (td->pipe->info.timer_interval) {
++			r8a66597->interval_map |= 1 << td->pipenum;
++			mod_timer(&r8a66597->interval_timer[td->pipenum],
++				  jiffies + msecs_to_jiffies(
++					td->pipe->info.timer_interval));
++		} else {
++			ret = start_transfer(r8a66597, td);
++			if (ret < 0) {
++				list_del(&td->queue);
++				kfree(td);
++			}
+ 		}
+ 	} else
+ 		set_td_timer(r8a66597, td);
+@@ -2107,13 +2210,11 @@ static struct hc_driver r8a66597_hc_driver = {
+ #if defined(CONFIG_PM)
+ static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+-	pdev->dev.power.power_state = state;
+ 	return 0;
+ }
+ 
+ static int r8a66597_resume(struct platform_device *pdev)
+ {
+-	pdev->dev.power.power_state = PMSG_ON;
+ 	return 0;
+ }
+ #else	/* if defined(CONFIG_PM) */
+@@ -2194,6 +2295,9 @@ static int __init r8a66597_probe(struct platform_device *pdev)
+ 		init_timer(&r8a66597->td_timer[i]);
+ 		r8a66597->td_timer[i].function = r8a66597_td_timer;
+ 		r8a66597->td_timer[i].data = (unsigned long)r8a66597;
++		setup_timer(&r8a66597->interval_timer[i],
++				r8a66597_interval_timer,
++				(unsigned long)r8a66597);
+ 	}
+ 	INIT_LIST_HEAD(&r8a66597->child_device);
+ 
+diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
+index 5738825..84ee014 100644
+--- a/drivers/usb/host/r8a66597.h
++++ b/drivers/usb/host/r8a66597.h
+@@ -187,7 +187,11 @@
+ #define	REW		0x4000	/* b14: Buffer rewind */
+ #define	DCLRM		0x2000	/* b13: DMA buffer clear mode */
+ #define	DREQE		0x1000	/* b12: DREQ output enable */
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++#define	MBW		0x0800
++#else
+ #define	MBW		0x0400	/* b10: Maximum bit width for FIFO access */
++#endif
+ #define	  MBW_8		 0x0000	  /*  8bit */
+ #define	  MBW_16	 0x0400	  /* 16bit */
+ #define	BIGEND		0x0100	/* b8: Big endian mode */
+@@ -395,8 +399,13 @@
+ #define R8A66597_MAX_NUM_PIPE		10
+ #define R8A66597_BUF_BSIZE		8
+ #define R8A66597_MAX_DEVICE		10
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++#define R8A66597_MAX_ROOT_HUB		1
++#else
+ #define R8A66597_MAX_ROOT_HUB		2
+-#define R8A66597_MAX_SAMPLING		10
++#endif
++#define R8A66597_MAX_SAMPLING		5
++#define R8A66597_RH_POLL_TIME		10
+ #define R8A66597_MAX_DMA_CHANNEL	2
+ #define R8A66597_PIPE_NO_DMA		R8A66597_MAX_DMA_CHANNEL
+ #define check_bulk_or_isoc(pipenum)	((pipenum >= 1 && pipenum <= 5))
+@@ -404,6 +413,7 @@
+ #define make_devsel(addr)		(addr << 12)
+ 
+ struct r8a66597_pipe_info {
++	unsigned long timer_interval;
+ 	u16 pipenum;
+ 	u16 address;	/* R8A66597 HCD usb address */
+ 	u16 epnum;
+@@ -478,9 +488,11 @@ struct r8a66597 {
+ 
+ 	struct timer_list rh_timer;
+ 	struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
++	struct timer_list interval_timer[R8A66597_MAX_NUM_PIPE];
+ 
+ 	unsigned short address_map;
+ 	unsigned short timeout_map;
++	unsigned short interval_map;
+ 	unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
+ 	unsigned char dma_map;
+ 
+@@ -526,8 +538,21 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+ 				      unsigned long offset, u16 *buf,
+ 				      int len)
+ {
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++	unsigned long fifoaddr = r8a66597->reg + offset;
++	unsigned long count;
++
++	count = len / 4;
++	insl(fifoaddr, buf, count);
++
++	if (len & 0x00000003) {
++		unsigned long tmp = inl(fifoaddr);
++		memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
++	}
++#else
+ 	len = (len + 1) / 2;
+ 	insw(r8a66597->reg + offset, buf, len);
++#endif
+ }
+ 
+ static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+@@ -541,6 +566,24 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+ 				       int len)
+ {
+ 	unsigned long fifoaddr = r8a66597->reg + offset;
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++	unsigned long count;
++	unsigned char *pb;
++	int i;
++
++	count = len / 4;
++	outsl(fifoaddr, buf, count);
++
++	if (len & 0x00000003) {
++		pb = (unsigned char *)buf + count * 4;
++		for (i = 0; i < (len & 0x00000003); i++) {
++			if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
++				outb(pb[i], fifoaddr + i);
++			else
++				outb(pb[i], fifoaddr + 3 - i);
++		}
++	}
++#else
+ 	int odd = len & 0x0001;
+ 
+ 	len = len / 2;
+@@ -549,6 +592,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+ 		buf = &buf[len];
+ 		outb((unsigned char)*buf, fifoaddr);
+ 	}
++#endif
+ }
+ 
+ static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+@@ -581,6 +625,11 @@ static inline unsigned long get_dvstctr_reg(int port)
+ 	return port == 0 ? DVSTCTR0 : DVSTCTR1;
+ }
+ 
++static inline unsigned long get_dmacfg_reg(int port)
++{
++	return port == 0 ? DMA0CFG : DMA1CFG;
++}
++
+ static inline unsigned long get_intenb_reg(int port)
+ {
+ 	return port == 0 ? INTENB1 : INTENB2;
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 629bca0..274276c 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -94,12 +94,10 @@ static void port_power(struct sl811 *sl811, int is_on)
+ 
+ 		sl811->port1 = (1 << USB_PORT_FEAT_POWER);
+ 		sl811->irq_enable = SL11H_INTMASK_INSRMV;
+-		hcd->self.controller->power.power_state = PMSG_ON;
+ 	} else {
+ 		sl811->port1 = 0;
+ 		sl811->irq_enable = 0;
+ 		hcd->state = HC_STATE_HALT;
+-		hcd->self.controller->power.power_state = PMSG_SUSPEND;
+ 	}
+ 	sl811->ctrl1 = 0;
+ 	sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
+@@ -1337,7 +1335,7 @@ static int
+ sl811h_bus_suspend(struct usb_hcd *hcd)
+ {
+ 	// SOFs off
+-	DBG("%s\n", __FUNCTION__);
++	DBG("%s\n", __func__);
+ 	return 0;
+ }
+ 
+@@ -1345,7 +1343,7 @@ static int
+ sl811h_bus_resume(struct usb_hcd *hcd)
+ {
+ 	// SOFs on
+-	DBG("%s\n", __FUNCTION__);
++	DBG("%s\n", __func__);
+ 	return 0;
+ }
+ 
+@@ -1772,8 +1770,6 @@ sl811h_suspend(struct platform_device *dev, pm_message_t state)
+ 		port_power(sl811, 0);
+ 		break;
+ 	}
+-	if (retval == 0)
+-		dev->dev.power.power_state = state;
+ 	return retval;
+ }
+ 
+@@ -1786,15 +1782,13 @@ sl811h_resume(struct platform_device *dev)
+ 	/* with no "check to see if VBUS is still powered" board hook,
+ 	 * let's assume it'd only be powered to enable remote wakeup.
+ 	 */
+-	if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND
+-			|| !device_can_wakeup(&hcd->self.root_hub->dev)) {
++	if (!sl811->port1 || !device_can_wakeup(&hcd->self.root_hub->dev)) {
+ 		sl811->port1 = 0;
+ 		port_power(sl811, 1);
+ 		usb_root_hub_lost_power(hcd->self.root_hub);
+ 		return 0;
+ 	}
+ 
+-	dev->dev.power.power_state = PMSG_ON;
+ 	return sl811h_bus_resume(hcd);
+ }
+ 
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 8e117a7..f293074 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -67,7 +67,7 @@
+ #include "ohci.h"
+ #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
+ #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
+-        OHCI_INTR_WDH)
++	OHCI_INTR_WDH)
+ MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
+ MODULE_DESCRIPTION("U132 USB Host Controller Driver");
+ MODULE_LICENSE("GPL");
+@@ -77,15 +77,15 @@ INT_MODULE_PARM(testing, 0);
+ static int distrust_firmware = 1;
+ module_param(distrust_firmware, bool, 0);
+ MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
+-        "t setup");
++	"t setup");
+ static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
+ /*
+ * u132_module_lock exists to protect access to global variables
+ *
+ */
+ static struct mutex u132_module_lock;
+-static int u132_exiting = 0;
+-static int u132_instances = 0;
++static int u132_exiting;
++static int u132_instances;
+ static struct list_head u132_static_list;
+ /*
+ * end of the global variables protected by u132_module_lock
+@@ -97,115 +97,115 @@ static struct workqueue_struct *workqueue;
+ #define MAX_U132_ENDPS 100
+ #define MAX_U132_RINGS 4
+ static const char *cc_to_text[16] = {
+-        "No Error ",
+-        "CRC Error ",
+-        "Bit Stuff ",
+-        "Data Togg ",
+-        "Stall ",
+-        "DevNotResp ",
+-        "PIDCheck ",
+-        "UnExpPID ",
+-        "DataOver ",
+-        "DataUnder ",
+-        "(for hw) ",
+-        "(for hw) ",
+-        "BufferOver ",
+-        "BuffUnder ",
+-        "(for HCD) ",
+-        "(for HCD) "
++	"No Error ",
++	"CRC Error ",
++	"Bit Stuff ",
++	"Data Togg ",
++	"Stall ",
++	"DevNotResp ",
++	"PIDCheck ",
++	"UnExpPID ",
++	"DataOver ",
++	"DataUnder ",
++	"(for hw) ",
++	"(for hw) ",
++	"BufferOver ",
++	"BuffUnder ",
++	"(for HCD) ",
++	"(for HCD) "
+ };
+ struct u132_port {
+-        struct u132 *u132;
+-        int reset;
+-        int enable;
+-        int power;
+-        int Status;
++	struct u132 *u132;
++	int reset;
++	int enable;
++	int power;
++	int Status;
+ };
+ struct u132_addr {
+-        u8 address;
++	u8 address;
+ };
+ struct u132_udev {
+-        struct kref kref;
+-        struct usb_device *usb_device;
+-        u8 enumeration;
+-        u8 udev_number;
+-        u8 usb_addr;
+-        u8 portnumber;
+-        u8 endp_number_in[16];
+-        u8 endp_number_out[16];
++	struct kref kref;
++	struct usb_device *usb_device;
++	u8 enumeration;
++	u8 udev_number;
++	u8 usb_addr;
++	u8 portnumber;
++	u8 endp_number_in[16];
++	u8 endp_number_out[16];
+ };
+ #define ENDP_QUEUE_SHIFT 3
+ #define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
+ #define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
+ struct u132_urbq {
+-        struct list_head urb_more;
+-        struct urb *urb;
++	struct list_head urb_more;
++	struct urb *urb;
+ };
+ struct u132_spin {
+-        spinlock_t slock;
++	spinlock_t slock;
+ };
+ struct u132_endp {
+-        struct kref kref;
+-        u8 udev_number;
+-        u8 endp_number;
+-        u8 usb_addr;
+-        u8 usb_endp;
+-        struct u132 *u132;
+-        struct list_head endp_ring;
+-        struct u132_ring *ring;
+-        unsigned toggle_bits:2;
+-        unsigned active:1;
+-        unsigned delayed:1;
+-        unsigned input:1;
+-        unsigned output:1;
+-        unsigned pipetype:2;
+-        unsigned dequeueing:1;
+-        unsigned edset_flush:1;
+-        unsigned spare_bits:14;
+-        unsigned long jiffies;
+-        struct usb_host_endpoint *hep;
+-        struct u132_spin queue_lock;
+-        u16 queue_size;
+-        u16 queue_last;
+-        u16 queue_next;
+-        struct urb *urb_list[ENDP_QUEUE_SIZE];
+-        struct list_head urb_more;
+-        struct delayed_work scheduler;
++	struct kref kref;
++	u8 udev_number;
++	u8 endp_number;
++	u8 usb_addr;
++	u8 usb_endp;
++	struct u132 *u132;
++	struct list_head endp_ring;
++	struct u132_ring *ring;
++	unsigned toggle_bits:2;
++	unsigned active:1;
++	unsigned delayed:1;
++	unsigned input:1;
++	unsigned output:1;
++	unsigned pipetype:2;
++	unsigned dequeueing:1;
++	unsigned edset_flush:1;
++	unsigned spare_bits:14;
++	unsigned long jiffies;
++	struct usb_host_endpoint *hep;
++	struct u132_spin queue_lock;
++	u16 queue_size;
++	u16 queue_last;
++	u16 queue_next;
++	struct urb *urb_list[ENDP_QUEUE_SIZE];
++	struct list_head urb_more;
++	struct delayed_work scheduler;
+ };
+ struct u132_ring {
+-        unsigned in_use:1;
+-        unsigned length:7;
+-        u8 number;
+-        struct u132 *u132;
+-        struct u132_endp *curr_endp;
+-        struct delayed_work scheduler;
++	unsigned in_use:1;
++	unsigned length:7;
++	u8 number;
++	struct u132 *u132;
++	struct u132_endp *curr_endp;
++	struct delayed_work scheduler;
+ };
+ struct u132 {
+-        struct kref kref;
+-        struct list_head u132_list;
+-        struct mutex sw_lock;
+-        struct semaphore scheduler_lock;
+-        struct u132_platform_data *board;
+-        struct platform_device *platform_dev;
+-        struct u132_ring ring[MAX_U132_RINGS];
+-        int sequence_num;
+-        int going;
+-        int power;
+-        int reset;
+-        int num_ports;
+-        u32 hc_control;
+-        u32 hc_fminterval;
+-        u32 hc_roothub_status;
+-        u32 hc_roothub_a;
+-        u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
+-        int flags;
+-        unsigned long next_statechange;
+-        struct delayed_work monitor;
+-        int num_endpoints;
+-        struct u132_addr addr[MAX_U132_ADDRS];
+-        struct u132_udev udev[MAX_U132_UDEVS];
+-        struct u132_port port[MAX_U132_PORTS];
+-        struct u132_endp *endp[MAX_U132_ENDPS];
++	struct kref kref;
++	struct list_head u132_list;
++	struct mutex sw_lock;
++	struct mutex scheduler_lock;
++	struct u132_platform_data *board;
++	struct platform_device *platform_dev;
++	struct u132_ring ring[MAX_U132_RINGS];
++	int sequence_num;
++	int going;
++	int power;
++	int reset;
++	int num_ports;
++	u32 hc_control;
++	u32 hc_fminterval;
++	u32 hc_roothub_status;
++	u32 hc_roothub_a;
++	u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
++	int flags;
++	unsigned long next_statechange;
++	struct delayed_work monitor;
++	int num_endpoints;
++	struct u132_addr addr[MAX_U132_ADDRS];
++	struct u132_udev udev[MAX_U132_UDEVS];
++	struct u132_port port[MAX_U132_PORTS];
++	struct u132_endp *endp[MAX_U132_ENDPS];
+ };
+ 
+ /*
+@@ -213,34 +213,34 @@ struct u132 {
+ * Does anyone have a better way?????
+ */
+ #define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
+-        offsetof(struct ohci_regs, member), 0, data);
++	offsetof(struct ohci_regs, member), 0, data);
+ #define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
+-        offsetof(struct ohci_regs, member), 0, data);
++	offsetof(struct ohci_regs, member), 0, data);
+ #define u132_read_pcimem(u132, member, data) \
+-        usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
+-        ohci_regs, member), 0, data);
++	usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
++	ohci_regs, member), 0, data);
+ #define u132_write_pcimem(u132, member, data) \
+-        usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+-        ohci_regs, member), 0, data);
++	usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
++	ohci_regs, member), 0, data);
+ static inline struct u132 *udev_to_u132(struct u132_udev *udev)
+ {
+-        u8 udev_number = udev->udev_number;
+-        return container_of(udev, struct u132, udev[udev_number]);
++	u8 udev_number = udev->udev_number;
++	return container_of(udev, struct u132, udev[udev_number]);
+ }
+ 
+ static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
+ {
+-        return (struct u132 *)(hcd->hcd_priv);
++	return (struct u132 *)(hcd->hcd_priv);
+ }
+ 
+ static inline struct usb_hcd *u132_to_hcd(struct u132 *u132)
+ {
+-        return container_of((void *)u132, struct usb_hcd, hcd_priv);
++	return container_of((void *)u132, struct usb_hcd, hcd_priv);
+ }
+ 
+ static inline void u132_disable(struct u132 *u132)
+ {
+-        u132_to_hcd(u132)->state = HC_STATE_HALT;
++	u132_to_hcd(u132)->state = HC_STATE_HALT;
+ }
+ 
+ 
+@@ -250,147 +250,147 @@ static inline void u132_disable(struct u132 *u132)
+ #include "../misc/usb_u132.h"
+ static const char hcd_name[] = "u132_hcd";
+ #define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \
+-        USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
+-        USB_PORT_STAT_C_RESET) << 16)
++	USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
++	USB_PORT_STAT_C_RESET) << 16)
+ static void u132_hcd_delete(struct kref *kref)
+ {
+-        struct u132 *u132 = kref_to_u132(kref);
+-        struct platform_device *pdev = u132->platform_dev;
+-        struct usb_hcd *hcd = u132_to_hcd(u132);
+-        u132->going += 1;
+-        mutex_lock(&u132_module_lock);
+-        list_del_init(&u132->u132_list);
+-        u132_instances -= 1;
+-        mutex_unlock(&u132_module_lock);
+-        dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
+-                "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
+-        usb_put_hcd(hcd);
++	struct u132 *u132 = kref_to_u132(kref);
++	struct platform_device *pdev = u132->platform_dev;
++	struct usb_hcd *hcd = u132_to_hcd(u132);
++	u132->going += 1;
++	mutex_lock(&u132_module_lock);
++	list_del_init(&u132->u132_list);
++	u132_instances -= 1;
++	mutex_unlock(&u132_module_lock);
++	dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
++		"2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
++	usb_put_hcd(hcd);
+ }
+ 
+ static inline void u132_u132_put_kref(struct u132 *u132)
+ {
+-        kref_put(&u132->kref, u132_hcd_delete);
++	kref_put(&u132->kref, u132_hcd_delete);
+ }
+ 
+ static inline void u132_u132_init_kref(struct u132 *u132)
+ {
+-        kref_init(&u132->kref);
++	kref_init(&u132->kref);
+ }
+ 
+ static void u132_udev_delete(struct kref *kref)
+ {
+-        struct u132_udev *udev = kref_to_u132_udev(kref);
+-        udev->udev_number = 0;
+-        udev->usb_device = NULL;
+-        udev->usb_addr = 0;
+-        udev->enumeration = 0;
++	struct u132_udev *udev = kref_to_u132_udev(kref);
++	udev->udev_number = 0;
++	udev->usb_device = NULL;
++	udev->usb_addr = 0;
++	udev->enumeration = 0;
+ }
+ 
+ static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev)
+ {
+-        kref_put(&udev->kref, u132_udev_delete);
++	kref_put(&udev->kref, u132_udev_delete);
+ }
+ 
+ static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
+ {
+-        kref_get(&udev->kref);
++	kref_get(&udev->kref);
+ }
+ 
+ static inline void u132_udev_init_kref(struct u132 *u132,
+-        struct u132_udev *udev)
++	struct u132_udev *udev)
+ {
+-        kref_init(&udev->kref);
++	kref_init(&udev->kref);
+ }
+ 
+ static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring)
+ {
+-        kref_put(&u132->kref, u132_hcd_delete);
++	kref_put(&u132->kref, u132_hcd_delete);
+ }
+ 
+ static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
+-        unsigned int delta)
++	unsigned int delta)
+ {
+-        if (delta > 0) {
+-                if (queue_delayed_work(workqueue, &ring->scheduler, delta))
+-                        return;
+-        } else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
+-                return;
+-        kref_put(&u132->kref, u132_hcd_delete);
+-        return;
++	if (delta > 0) {
++		if (queue_delayed_work(workqueue, &ring->scheduler, delta))
++			return;
++	} else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
++		return;
++	kref_put(&u132->kref, u132_hcd_delete);
++	return;
+ }
+ 
+ static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,
+-        unsigned int delta)
++	unsigned int delta)
+ {
+-        kref_get(&u132->kref);
+-        u132_ring_requeue_work(u132, ring, delta);
+-        return;
++	kref_get(&u132->kref);
++	u132_ring_requeue_work(u132, ring, delta);
++	return;
+ }
+ 
+ static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring)
+ {
+-        if (cancel_delayed_work(&ring->scheduler)) {
+-                kref_put(&u132->kref, u132_hcd_delete);
+-        }
++	if (cancel_delayed_work(&ring->scheduler))
++		kref_put(&u132->kref, u132_hcd_delete);
+ }
+ 
+ static void u132_endp_delete(struct kref *kref)
+ {
+-        struct u132_endp *endp = kref_to_u132_endp(kref);
+-        struct u132 *u132 = endp->u132;
+-        u8 usb_addr = endp->usb_addr;
+-        u8 usb_endp = endp->usb_endp;
+-        u8 address = u132->addr[usb_addr].address;
+-        struct u132_udev *udev = &u132->udev[address];
+-        u8 endp_number = endp->endp_number;
+-        struct usb_host_endpoint *hep = endp->hep;
+-        struct u132_ring *ring = endp->ring;
+-        struct list_head *head = &endp->endp_ring;
+-        ring->length -= 1;
+-        if (endp == ring->curr_endp) {
+-                if (list_empty(head)) {
+-                        ring->curr_endp = NULL;
+-                        list_del(head);
+-                } else {
+-                        struct u132_endp *next_endp = list_entry(head->next,
+-                                struct u132_endp, endp_ring);
+-                        ring->curr_endp = next_endp;
+-                        list_del(head);
+-        }} else
+-                list_del(head);
+-        if (endp->input) {
+-                udev->endp_number_in[usb_endp] = 0;
+-                u132_udev_put_kref(u132, udev);
+-        }
+-        if (endp->output) {
+-                udev->endp_number_out[usb_endp] = 0;
+-                u132_udev_put_kref(u132, udev);
+-        }
+-        u132->endp[endp_number - 1] = NULL;
+-        hep->hcpriv = NULL;
+-        kfree(endp);
+-        u132_u132_put_kref(u132);
++	struct u132_endp *endp = kref_to_u132_endp(kref);
++	struct u132 *u132 = endp->u132;
++	u8 usb_addr = endp->usb_addr;
++	u8 usb_endp = endp->usb_endp;
++	u8 address = u132->addr[usb_addr].address;
++	struct u132_udev *udev = &u132->udev[address];
++	u8 endp_number = endp->endp_number;
++	struct usb_host_endpoint *hep = endp->hep;
++	struct u132_ring *ring = endp->ring;
++	struct list_head *head = &endp->endp_ring;
++	ring->length -= 1;
++	if (endp == ring->curr_endp) {
++		if (list_empty(head)) {
++			ring->curr_endp = NULL;
++			list_del(head);
++		} else {
++			struct u132_endp *next_endp = list_entry(head->next,
++				struct u132_endp, endp_ring);
++			ring->curr_endp = next_endp;
++			list_del(head);
++		}
++	} else
++		list_del(head);
++	if (endp->input) {
++		udev->endp_number_in[usb_endp] = 0;
++		u132_udev_put_kref(u132, udev);
++	}
++	if (endp->output) {
++		udev->endp_number_out[usb_endp] = 0;
++		u132_udev_put_kref(u132, udev);
++	}
++	u132->endp[endp_number - 1] = NULL;
++	hep->hcpriv = NULL;
++	kfree(endp);
++	u132_u132_put_kref(u132);
+ }
+ 
+ static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp)
+ {
+-        kref_put(&endp->kref, u132_endp_delete);
++	kref_put(&endp->kref, u132_endp_delete);
+ }
+ 
+ static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
+ {
+-        kref_get(&endp->kref);
++	kref_get(&endp->kref);
+ }
+ 
+ static inline void u132_endp_init_kref(struct u132 *u132,
+-        struct u132_endp *endp)
++	struct u132_endp *endp)
+ {
+-        kref_init(&endp->kref);
+-        kref_get(&u132->kref);
++	kref_init(&endp->kref);
++	kref_get(&u132->kref);
+ }
+ 
+ static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
+-        unsigned int delta)
++	unsigned int delta)
+ {
+ 	if (queue_delayed_work(workqueue, &endp->scheduler, delta))
+ 		kref_get(&endp->kref);
+@@ -398,13 +398,13 @@ static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
+ 
+ static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
+ {
+-        if (cancel_delayed_work(&endp->scheduler))
+-                kref_put(&endp->kref, u132_endp_delete);
++	if (cancel_delayed_work(&endp->scheduler))
++		kref_put(&endp->kref, u132_endp_delete);
+ }
+ 
+ static inline void u132_monitor_put_kref(struct u132 *u132)
+ {
+-        kref_put(&u132->kref, u132_hcd_delete);
++	kref_put(&u132->kref, u132_hcd_delete);
+ }
+ 
+ static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta)
+@@ -421,200 +421,201 @@ static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta)
+ 
+ static void u132_monitor_cancel_work(struct u132 *u132)
+ {
+-        if (cancel_delayed_work(&u132->monitor))
+-                kref_put(&u132->kref, u132_hcd_delete);
++	if (cancel_delayed_work(&u132->monitor))
++		kref_put(&u132->kref, u132_hcd_delete);
+ }
+ 
+ static int read_roothub_info(struct u132 *u132)
+ {
+-        u32 revision;
+-        int retval;
+-        retval = u132_read_pcimem(u132, revision, &revision);
+-        if (retval) {
+-                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+-                        "ntrol\n", retval);
+-                return retval;
+-        } else if ((revision & 0xFF) == 0x10) {
+-        } else if ((revision & 0xFF) == 0x11) {
+-        } else {
+-                dev_err(&u132->platform_dev->dev, "device revision is not valid"
+-                        " %08X\n", revision);
+-                return -ENODEV;
+-        }
+-        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+-        if (retval) {
+-                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+-                        "ntrol\n", retval);
+-                return retval;
+-        }
+-        retval = u132_read_pcimem(u132, roothub.status,
+-                &u132->hc_roothub_status);
+-        if (retval) {
+-                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+-                        "g roothub.status\n", retval);
+-                return retval;
+-        }
+-        retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
+-        if (retval) {
+-                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+-                        "g roothub.a\n", retval);
+-                return retval;
+-        }
+-        {
+-                int I = u132->num_ports;
+-                int i = 0;
+-                while (I-- > 0) {
+-                        retval = u132_read_pcimem(u132, roothub.portstatus[i],
+-                                &u132->hc_roothub_portstatus[i]);
+-                        if (retval) {
+-                                dev_err(&u132->platform_dev->dev, "error %d acc"
+-                                        "essing device roothub.portstatus[%d]\n"
+-                                        , retval, i);
+-                                return retval;
+-                        } else
+-                                i += 1;
+-                }
+-        }
+-        return 0;
++	u32 revision;
++	int retval;
++	retval = u132_read_pcimem(u132, revision, &revision);
++	if (retval) {
++		dev_err(&u132->platform_dev->dev, "error %d accessing device co"
++			"ntrol\n", retval);
++		return retval;
++	} else if ((revision & 0xFF) == 0x10) {
++	} else if ((revision & 0xFF) == 0x11) {
++	} else {
++		dev_err(&u132->platform_dev->dev, "device revision is not valid"
++			" %08X\n", revision);
++		return -ENODEV;
++	}
++	retval = u132_read_pcimem(u132, control, &u132->hc_control);
++	if (retval) {
++		dev_err(&u132->platform_dev->dev, "error %d accessing device co"
++			"ntrol\n", retval);
++		return retval;
++	}
++	retval = u132_read_pcimem(u132, roothub.status,
++		&u132->hc_roothub_status);
++	if (retval) {
++		dev_err(&u132->platform_dev->dev, "error %d accessing device re"
++			"g roothub.status\n", retval);
++		return retval;
++	}
++	retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
++	if (retval) {
++		dev_err(&u132->platform_dev->dev, "error %d accessing device re"
++			"g roothub.a\n", retval);
++		return retval;
++	}
++	{
++		int I = u132->num_ports;
++		int i = 0;
++		while (I-- > 0) {
++			retval = u132_read_pcimem(u132, roothub.portstatus[i],
++				&u132->hc_roothub_portstatus[i]);
++			if (retval) {
++				dev_err(&u132->platform_dev->dev, "error %d acc"
++					"essing device roothub.portstatus[%d]\n"
++					, retval, i);
++				return retval;
++			} else
++				i += 1;
++		}
++	}
++	return 0;
+ }
+ 
+ static void u132_hcd_monitor_work(struct work_struct *work)
+ {
+-        struct u132 *u132 = container_of(work, struct u132, monitor.work);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                u132_monitor_put_kref(u132);
+-                return;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                u132_monitor_put_kref(u132);
+-                return;
+-        } else {
+-                int retval;
+-                mutex_lock(&u132->sw_lock);
+-                retval = read_roothub_info(u132);
+-                if (retval) {
+-                        struct usb_hcd *hcd = u132_to_hcd(u132);
+-                        u132_disable(u132);
+-                        u132->going = 1;
+-                        mutex_unlock(&u132->sw_lock);
+-                        usb_hc_died(hcd);
+-                        ftdi_elan_gone_away(u132->platform_dev);
+-                        u132_monitor_put_kref(u132);
+-                        return;
+-                } else {
+-                        u132_monitor_requeue_work(u132, 500);
+-                        mutex_unlock(&u132->sw_lock);
+-                        return;
+-                }
+-        }
++	struct u132 *u132 = container_of(work, struct u132, monitor.work);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		u132_monitor_put_kref(u132);
++		return;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		u132_monitor_put_kref(u132);
++		return;
++	} else {
++		int retval;
++		mutex_lock(&u132->sw_lock);
++		retval = read_roothub_info(u132);
++		if (retval) {
++			struct usb_hcd *hcd = u132_to_hcd(u132);
++			u132_disable(u132);
++			u132->going = 1;
++			mutex_unlock(&u132->sw_lock);
++			usb_hc_died(hcd);
++			ftdi_elan_gone_away(u132->platform_dev);
++			u132_monitor_put_kref(u132);
++			return;
++		} else {
++			u132_monitor_requeue_work(u132, 500);
++			mutex_unlock(&u132->sw_lock);
++			return;
++		}
++	}
+ }
+ 
+ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
+-        struct urb *urb, int status)
++	struct urb *urb, int status)
+ {
+-        struct u132_ring *ring;
+-        unsigned long irqs;
+-        struct usb_hcd *hcd = u132_to_hcd(u132);
+-        urb->error_count = 0;
+-        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++	struct u132_ring *ring;
++	unsigned long irqs;
++	struct usb_hcd *hcd = u132_to_hcd(u132);
++	urb->error_count = 0;
++	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ 	usb_hcd_unlink_urb_from_ep(hcd, urb);
+-        endp->queue_next += 1;
+-        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+-                endp->active = 0;
+-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-        } else {
+-                struct list_head *next = endp->urb_more.next;
+-                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+-                        urb_more);
+-                list_del(next);
+-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+-                        urbq->urb;
+-                endp->active = 0;
+-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                kfree(urbq);
+-        } down(&u132->scheduler_lock);
+-        ring = endp->ring;
+-        ring->in_use = 0;
+-        u132_ring_cancel_work(u132, ring);
+-        u132_ring_queue_work(u132, ring, 0);
+-        up(&u132->scheduler_lock);
+-        u132_endp_put_kref(u132, endp);
++	endp->queue_next += 1;
++	if (ENDP_QUEUE_SIZE > --endp->queue_size) {
++		endp->active = 0;
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++	} else {
++		struct list_head *next = endp->urb_more.next;
++		struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
++			urb_more);
++		list_del(next);
++		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
++			urbq->urb;
++		endp->active = 0;
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++		kfree(urbq);
++	}
++	mutex_lock(&u132->scheduler_lock);
++	ring = endp->ring;
++	ring->in_use = 0;
++	u132_ring_cancel_work(u132, ring);
++	u132_ring_queue_work(u132, ring, 0);
++	mutex_unlock(&u132->scheduler_lock);
++	u132_endp_put_kref(u132, endp);
+ 	usb_hcd_giveback_urb(hcd, urb, status);
+-        return;
++	return;
+ }
+ 
+ static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,
+-        struct urb *urb, int status)
++	struct urb *urb, int status)
+ {
+-        u132_endp_put_kref(u132, endp);
++	u132_endp_put_kref(u132, endp);
+ }
+ 
+ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
+-        struct urb *urb, int status)
++	struct urb *urb, int status)
+ {
+-        unsigned long irqs;
+-        struct usb_hcd *hcd = u132_to_hcd(u132);
+-        urb->error_count = 0;
+-        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++	unsigned long irqs;
++	struct usb_hcd *hcd = u132_to_hcd(u132);
++	urb->error_count = 0;
++	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ 	usb_hcd_unlink_urb_from_ep(hcd, urb);
+-        endp->queue_next += 1;
+-        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+-                endp->active = 0;
+-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-        } else {
+-                struct list_head *next = endp->urb_more.next;
+-                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+-                        urb_more);
+-                list_del(next);
+-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+-                        urbq->urb;
+-                endp->active = 0;
+-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                kfree(urbq);
++	endp->queue_next += 1;
++	if (ENDP_QUEUE_SIZE > --endp->queue_size) {
++		endp->active = 0;
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++	} else {
++		struct list_head *next = endp->urb_more.next;
++		struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
++			urb_more);
++		list_del(next);
++		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
++			urbq->urb;
++		endp->active = 0;
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++		kfree(urbq);
+ 	} usb_hcd_giveback_urb(hcd, urb, status);
+-        return;
++	return;
+ }
+ 
+ static inline int edset_input(struct u132 *u132, struct u132_ring *ring,
+-        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+-        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+-        int toggle_bits, int error_count, int condition_code, int repeat_number,
+-         int halted, int skipped, int actual, int non_null))
++	struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
++	void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
++	int toggle_bits, int error_count, int condition_code, int repeat_number,
++	 int halted, int skipped, int actual, int non_null))
+ {
+-        return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
+-                 urb, address, endp->usb_endp, toggle_bits, callback);
++	return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
++		 urb, address, endp->usb_endp, toggle_bits, callback);
+ }
+ 
+ static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,
+-        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+-        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+-        int toggle_bits, int error_count, int condition_code, int repeat_number,
+-         int halted, int skipped, int actual, int non_null))
++	struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
++	void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
++	int toggle_bits, int error_count, int condition_code, int repeat_number,
++	 int halted, int skipped, int actual, int non_null))
+ {
+-        return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
+-                 urb, address, endp->usb_endp, toggle_bits, callback);
++	return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
++		 urb, address, endp->usb_endp, toggle_bits, callback);
+ }
+ 
+ static inline int edset_single(struct u132 *u132, struct u132_ring *ring,
+-        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+-        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+-        int toggle_bits, int error_count, int condition_code, int repeat_number,
+-         int halted, int skipped, int actual, int non_null))
++	struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
++	void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
++	int toggle_bits, int error_count, int condition_code, int repeat_number,
++	 int halted, int skipped, int actual, int non_null))
+ {
+-        return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
+-                endp, urb, address, endp->usb_endp, toggle_bits, callback);
++	return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
++		endp, urb, address, endp->usb_endp, toggle_bits, callback);
+ }
+ 
+ static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
+-        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+-        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+-        int toggle_bits, int error_count, int condition_code, int repeat_number,
+-         int halted, int skipped, int actual, int non_null))
++	struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
++	void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
++	int toggle_bits, int error_count, int condition_code, int repeat_number,
++	 int halted, int skipped, int actual, int non_null))
+ {
+-        return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
+-                endp, urb, address, endp->usb_endp, toggle_bits, callback);
++	return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
++		endp, urb, address, endp->usb_endp, toggle_bits, callback);
+ }
+ 
+ 
+@@ -623,683 +624,678 @@ static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
+ *
+ */
+ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        u8 address = u132->addr[endp->usb_addr].address;
+-        struct u132_udev *udev = &u132->udev[address];
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	u8 address = u132->addr[endp->usb_addr].address;
++	struct u132_udev *udev = &u132->udev[address];
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                struct u132_ring *ring = endp->ring;
+-                u8 *u = urb->transfer_buffer + urb->actual_length;
+-                u8 *b = buf;
+-                int L = len;
+-                while (L-- > 0) {
+-                        *u++ = *b++;
+-                }
+-                urb->actual_length += len;
+-                if ((condition_code == TD_CC_NOERROR) &&
+-                        (urb->transfer_buffer_length > urb->actual_length)) {
+-                        endp->toggle_bits = toggle_bits;
+-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+-                                1 & toggle_bits);
+-                        if (urb->actual_length > 0) {
+-                                int retval;
+-                                up(&u132->scheduler_lock);
+-                                retval = edset_single(u132, ring, endp, urb,
+-                                        address, endp->toggle_bits,
+-                                        u132_hcd_interrupt_recv);
+-                                if (retval == 0) {
+-                                } else
+-                                        u132_hcd_giveback_urb(u132, endp, urb,
+-                                                retval);
+-                        } else {
+-                                ring->in_use = 0;
+-                                endp->active = 0;
+-                                endp->jiffies = jiffies +
+-                                        msecs_to_jiffies(urb->interval);
+-                                u132_ring_cancel_work(u132, ring);
+-                                u132_ring_queue_work(u132, ring, 0);
+-                                up(&u132->scheduler_lock);
+-                                u132_endp_put_kref(u132, endp);
+-                        }
+-                        return;
+-                } else if ((condition_code == TD_DATAUNDERRUN) &&
+-                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+-                        endp->toggle_bits = toggle_bits;
+-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+-                                1 & toggle_bits);
+-                        up(&u132->scheduler_lock);
+-                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                        return;
+-                } else {
+-                        if (condition_code == TD_CC_NOERROR) {
+-                                endp->toggle_bits = toggle_bits;
+-                                usb_settoggle(udev->usb_device, endp->usb_endp,
+-                                        0, 1 & toggle_bits);
+-                        } else if (condition_code == TD_CC_STALL) {
+-                                endp->toggle_bits = 0x2;
+-                                usb_settoggle(udev->usb_device, endp->usb_endp,
+-                                        0, 0);
+-                        } else {
+-                                endp->toggle_bits = 0x2;
+-                                usb_settoggle(udev->usb_device, endp->usb_endp,
+-                                        0, 0);
+-                                dev_err(&u132->platform_dev->dev, "urb=%p givin"
+-                                        "g back INTERRUPT %s\n", urb,
+-                                        cc_to_text[condition_code]);
+-                        }
+-                        up(&u132->scheduler_lock);
+-                        u132_hcd_giveback_urb(u132, endp, urb,
+-                                cc_to_error[condition_code]);
+-                        return;
+-                }
+-        } else {
++		struct u132_ring *ring = endp->ring;
++		u8 *u = urb->transfer_buffer + urb->actual_length;
++		u8 *b = buf;
++		int L = len;
++
++		while (L-- > 0)
++			*u++ = *b++;
++
++		urb->actual_length += len;
++		if ((condition_code == TD_CC_NOERROR) &&
++			(urb->transfer_buffer_length > urb->actual_length)) {
++			endp->toggle_bits = toggle_bits;
++			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++				1 & toggle_bits);
++			if (urb->actual_length > 0) {
++				int retval;
++				mutex_unlock(&u132->scheduler_lock);
++				retval = edset_single(u132, ring, endp, urb,
++					address, endp->toggle_bits,
++					u132_hcd_interrupt_recv);
++				if (retval != 0)
++					u132_hcd_giveback_urb(u132, endp, urb,
++						retval);
++			} else {
++				ring->in_use = 0;
++				endp->active = 0;
++				endp->jiffies = jiffies +
++					msecs_to_jiffies(urb->interval);
++				u132_ring_cancel_work(u132, ring);
++				u132_ring_queue_work(u132, ring, 0);
++				mutex_unlock(&u132->scheduler_lock);
++				u132_endp_put_kref(u132, endp);
++			}
++			return;
++		} else if ((condition_code == TD_DATAUNDERRUN) &&
++			((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
++			endp->toggle_bits = toggle_bits;
++			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++				1 & toggle_bits);
++			mutex_unlock(&u132->scheduler_lock);
++			u132_hcd_giveback_urb(u132, endp, urb, 0);
++			return;
++		} else {
++			if (condition_code == TD_CC_NOERROR) {
++				endp->toggle_bits = toggle_bits;
++				usb_settoggle(udev->usb_device, endp->usb_endp,
++					0, 1 & toggle_bits);
++			} else if (condition_code == TD_CC_STALL) {
++				endp->toggle_bits = 0x2;
++				usb_settoggle(udev->usb_device, endp->usb_endp,
++					0, 0);
++			} else {
++				endp->toggle_bits = 0x2;
++				usb_settoggle(udev->usb_device, endp->usb_endp,
++					0, 0);
++				dev_err(&u132->platform_dev->dev, "urb=%p givin"
++					"g back INTERRUPT %s\n", urb,
++					cc_to_text[condition_code]);
++			}
++			mutex_unlock(&u132->scheduler_lock);
++			u132_hcd_giveback_urb(u132, endp, urb,
++				cc_to_error[condition_code]);
++			return;
++		}
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        u8 address = u132->addr[endp->usb_addr].address;
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	u8 address = u132->addr[endp->usb_addr].address;
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                struct u132_ring *ring = endp->ring;
+-                urb->actual_length += len;
+-                endp->toggle_bits = toggle_bits;
+-                if (urb->transfer_buffer_length > urb->actual_length) {
+-                        int retval;
+-                        up(&u132->scheduler_lock);
+-                        retval = edset_output(u132, ring, endp, urb, address,
+-                                endp->toggle_bits, u132_hcd_bulk_output_sent);
+-                        if (retval == 0) {
+-                        } else
+-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                        return;
+-                } else {
+-                        up(&u132->scheduler_lock);
+-                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                        return;
+-                }
+-        } else {
++		struct u132_ring *ring = endp->ring;
++		urb->actual_length += len;
++		endp->toggle_bits = toggle_bits;
++		if (urb->transfer_buffer_length > urb->actual_length) {
++			int retval;
++			mutex_unlock(&u132->scheduler_lock);
++			retval = edset_output(u132, ring, endp, urb, address,
++				endp->toggle_bits, u132_hcd_bulk_output_sent);
++			if (retval != 0)
++				u132_hcd_giveback_urb(u132, endp, urb, retval);
++			return;
++		} else {
++			mutex_unlock(&u132->scheduler_lock);
++			u132_hcd_giveback_urb(u132, endp, urb, 0);
++			return;
++		}
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        u8 address = u132->addr[endp->usb_addr].address;
+-        struct u132_udev *udev = &u132->udev[address];
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	u8 address = u132->addr[endp->usb_addr].address;
++	struct u132_udev *udev = &u132->udev[address];
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                struct u132_ring *ring = endp->ring;
+-                u8 *u = urb->transfer_buffer + urb->actual_length;
+-                u8 *b = buf;
+-                int L = len;
+-                while (L-- > 0) {
+-                        *u++ = *b++;
+-                }
+-                urb->actual_length += len;
+-                if ((condition_code == TD_CC_NOERROR) &&
+-                        (urb->transfer_buffer_length > urb->actual_length)) {
+-                        int retval;
+-                        endp->toggle_bits = toggle_bits;
+-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+-                                1 & toggle_bits);
+-                        up(&u132->scheduler_lock);
+-                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+-                                ring->number, endp, urb, address,
+-                                endp->usb_endp, endp->toggle_bits,
+-                                u132_hcd_bulk_input_recv);
+-                        if (retval == 0) {
+-                        } else
+-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                        return;
+-                } else if (condition_code == TD_CC_NOERROR) {
+-                        endp->toggle_bits = toggle_bits;
+-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+-                                1 & toggle_bits);
+-                        up(&u132->scheduler_lock);
+-                        u132_hcd_giveback_urb(u132, endp, urb,
+-                                cc_to_error[condition_code]);
+-                        return;
+-                } else if ((condition_code == TD_DATAUNDERRUN) &&
+-                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+-                        endp->toggle_bits = toggle_bits;
+-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+-                                1 & toggle_bits);
+-                        up(&u132->scheduler_lock);
+-                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                        return;
+-                } else if (condition_code == TD_DATAUNDERRUN) {
+-                        endp->toggle_bits = toggle_bits;
+-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+-                                1 & toggle_bits);
+-                        dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
+-                                ") giving back BULK IN %s\n", urb,
+-                                cc_to_text[condition_code]);
+-                        up(&u132->scheduler_lock);
+-                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                        return;
+-                } else if (condition_code == TD_CC_STALL) {
+-                        endp->toggle_bits = 0x2;
+-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+-                        up(&u132->scheduler_lock);
+-                        u132_hcd_giveback_urb(u132, endp, urb,
+-                                cc_to_error[condition_code]);
+-                        return;
+-                } else {
+-                        endp->toggle_bits = 0x2;
+-                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+-                        dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
+-                                "ULK IN code=%d %s\n", urb, condition_code,
+-                                cc_to_text[condition_code]);
+-                        up(&u132->scheduler_lock);
+-                        u132_hcd_giveback_urb(u132, endp, urb,
+-                                cc_to_error[condition_code]);
+-                        return;
+-                }
+-        } else {
++		struct u132_ring *ring = endp->ring;
++		u8 *u = urb->transfer_buffer + urb->actual_length;
++		u8 *b = buf;
++		int L = len;
++
++		while (L-- > 0)
++			*u++ = *b++;
++
++		urb->actual_length += len;
++		if ((condition_code == TD_CC_NOERROR) &&
++			(urb->transfer_buffer_length > urb->actual_length)) {
++			int retval;
++			endp->toggle_bits = toggle_bits;
++			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++				1 & toggle_bits);
++			mutex_unlock(&u132->scheduler_lock);
++			retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++				ring->number, endp, urb, address,
++				endp->usb_endp, endp->toggle_bits,
++				u132_hcd_bulk_input_recv);
++			if (retval != 0)
++				u132_hcd_giveback_urb(u132, endp, urb, retval);
++			return;
++		} else if (condition_code == TD_CC_NOERROR) {
++			endp->toggle_bits = toggle_bits;
++			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++				1 & toggle_bits);
++			mutex_unlock(&u132->scheduler_lock);
++			u132_hcd_giveback_urb(u132, endp, urb,
++				cc_to_error[condition_code]);
++			return;
++		} else if ((condition_code == TD_DATAUNDERRUN) &&
++			((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
++			endp->toggle_bits = toggle_bits;
++			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++				1 & toggle_bits);
++			mutex_unlock(&u132->scheduler_lock);
++			u132_hcd_giveback_urb(u132, endp, urb, 0);
++			return;
++		} else if (condition_code == TD_DATAUNDERRUN) {
++			endp->toggle_bits = toggle_bits;
++			usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++				1 & toggle_bits);
++			dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
++				") giving back BULK IN %s\n", urb,
++				cc_to_text[condition_code]);
++			mutex_unlock(&u132->scheduler_lock);
++			u132_hcd_giveback_urb(u132, endp, urb, 0);
++			return;
++		} else if (condition_code == TD_CC_STALL) {
++			endp->toggle_bits = 0x2;
++			usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
++			mutex_unlock(&u132->scheduler_lock);
++			u132_hcd_giveback_urb(u132, endp, urb,
++				cc_to_error[condition_code]);
++			return;
++		} else {
++			endp->toggle_bits = 0x2;
++			usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
++			dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
++				"ULK IN code=%d %s\n", urb, condition_code,
++				cc_to_text[condition_code]);
++			mutex_unlock(&u132->scheduler_lock);
++			u132_hcd_giveback_urb(u132, endp, urb,
++				cc_to_error[condition_code]);
++			return;
++		}
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        } else {
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
++		return;
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        u8 address = u132->addr[endp->usb_addr].address;
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	u8 address = u132->addr[endp->usb_addr].address;
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                struct u132_ring *ring = endp->ring;
+-                u8 *u = urb->transfer_buffer;
+-                u8 *b = buf;
+-                int L = len;
+-                while (L-- > 0) {
+-                        *u++ = *b++;
+-                }
+-                urb->actual_length = len;
+-                if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
+-                        TD_DATAUNDERRUN) && ((urb->transfer_flags &
+-                        URB_SHORT_NOT_OK) == 0))) {
+-                        int retval;
+-                        up(&u132->scheduler_lock);
+-                        retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+-                                ring->number, endp, urb, address,
+-                                endp->usb_endp, 0x3,
+-                                u132_hcd_configure_empty_sent);
+-                        if (retval == 0) {
+-                        } else
+-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                        return;
+-                } else if (condition_code == TD_CC_STALL) {
+-                        up(&u132->scheduler_lock);
+-                        dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
+-                                "NPUT STALL urb %p\n", urb);
+-                        u132_hcd_giveback_urb(u132, endp, urb,
+-                                cc_to_error[condition_code]);
+-                        return;
+-                } else {
+-                        up(&u132->scheduler_lock);
+-                        dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
+-                                "PUT %s urb %p\n", cc_to_text[condition_code],
+-                                urb);
+-                        u132_hcd_giveback_urb(u132, endp, urb,
+-                                cc_to_error[condition_code]);
+-                        return;
+-                }
+-        } else {
++		struct u132_ring *ring = endp->ring;
++		u8 *u = urb->transfer_buffer;
++		u8 *b = buf;
++		int L = len;
++
++		while (L-- > 0)
++			*u++ = *b++;
++
++		urb->actual_length = len;
++		if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
++			TD_DATAUNDERRUN) && ((urb->transfer_flags &
++			URB_SHORT_NOT_OK) == 0))) {
++			int retval;
++			mutex_unlock(&u132->scheduler_lock);
++			retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
++				ring->number, endp, urb, address,
++				endp->usb_endp, 0x3,
++				u132_hcd_configure_empty_sent);
++			if (retval != 0)
++				u132_hcd_giveback_urb(u132, endp, urb, retval);
++			return;
++		} else if (condition_code == TD_CC_STALL) {
++			mutex_unlock(&u132->scheduler_lock);
++			dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
++				"NPUT STALL urb %p\n", urb);
++			u132_hcd_giveback_urb(u132, endp, urb,
++				cc_to_error[condition_code]);
++			return;
++		} else {
++			mutex_unlock(&u132->scheduler_lock);
++			dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
++				"PUT %s urb %p\n", cc_to_text[condition_code],
++				urb);
++			u132_hcd_giveback_urb(u132, endp, urb,
++				cc_to_error[condition_code]);
++			return;
++		}
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        } else {
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
++		return;
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        u8 address = u132->addr[endp->usb_addr].address;
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	u8 address = u132->addr[endp->usb_addr].address;
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                if (usb_pipein(urb->pipe)) {
+-                        int retval;
+-                        struct u132_ring *ring = endp->ring;
+-                        up(&u132->scheduler_lock);
+-                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+-                                ring->number, endp, urb, address,
+-                                endp->usb_endp, 0,
+-                                u132_hcd_configure_input_recv);
+-                        if (retval == 0) {
+-                        } else
+-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                        return;
+-                } else {
+-                        int retval;
+-                        struct u132_ring *ring = endp->ring;
+-                        up(&u132->scheduler_lock);
+-                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+-                                ring->number, endp, urb, address,
+-                                endp->usb_endp, 0,
+-                                u132_hcd_configure_empty_recv);
+-                        if (retval == 0) {
+-                        } else
+-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                        return;
+-                }
+-        } else {
++		if (usb_pipein(urb->pipe)) {
++			int retval;
++			struct u132_ring *ring = endp->ring;
++			mutex_unlock(&u132->scheduler_lock);
++			retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++				ring->number, endp, urb, address,
++				endp->usb_endp, 0,
++				u132_hcd_configure_input_recv);
++			if (retval != 0)
++				u132_hcd_giveback_urb(u132, endp, urb, retval);
++			return;
++		} else {
++			int retval;
++			struct u132_ring *ring = endp->ring;
++			mutex_unlock(&u132->scheduler_lock);
++			retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++				ring->number, endp, urb, address,
++				endp->usb_endp, 0,
++				u132_hcd_configure_empty_recv);
++			if (retval != 0)
++				u132_hcd_giveback_urb(u132, endp, urb, retval);
++			return;
++		}
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
+-        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        u8 address = u132->addr[endp->usb_addr].address;
+-        struct u132_udev *udev = &u132->udev[address];
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	u8 address = u132->addr[endp->usb_addr].address;
++	struct u132_udev *udev = &u132->udev[address];
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                u132->addr[0].address = 0;
+-                endp->usb_addr = udev->usb_addr;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        } else {
++		u132->addr[0].address = 0;
++		endp->usb_addr = udev->usb_addr;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
++		return;
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
+-        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                int retval;
+-                struct u132_ring *ring = endp->ring;
+-                up(&u132->scheduler_lock);
+-                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+-                        ring->number, endp, urb, 0, endp->usb_endp, 0,
+-                        u132_hcd_enumeration_empty_recv);
+-                if (retval == 0) {
+-                } else
+-                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                return;
+-        } else {
++		int retval;
++		struct u132_ring *ring = endp->ring;
++		mutex_unlock(&u132->scheduler_lock);
++		retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++			ring->number, endp, urb, 0, endp->usb_endp, 0,
++			u132_hcd_enumeration_empty_recv);
++		if (retval != 0)
++			u132_hcd_giveback_urb(u132, endp, urb, retval);
++		return;
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        } else {
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, 0);
++		return;
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        u8 address = u132->addr[endp->usb_addr].address;
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	u8 address = u132->addr[endp->usb_addr].address;
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                int retval;
+-                struct u132_ring *ring = endp->ring;
+-                u8 *u = urb->transfer_buffer;
+-                u8 *b = buf;
+-                int L = len;
+-                while (L-- > 0) {
+-                        *u++ = *b++;
+-                }
+-                urb->actual_length = len;
+-                up(&u132->scheduler_lock);
+-                retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+-                        ring->number, endp, urb, address, endp->usb_endp, 0x3,
+-                        u132_hcd_initial_empty_sent);
+-                if (retval == 0) {
+-                } else
+-                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                return;
+-        } else {
++		int retval;
++		struct u132_ring *ring = endp->ring;
++		u8 *u = urb->transfer_buffer;
++		u8 *b = buf;
++		int L = len;
++
++		while (L-- > 0)
++			*u++ = *b++;
++
++		urb->actual_length = len;
++		mutex_unlock(&u132->scheduler_lock);
++		retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
++			ring->number, endp, urb, address, endp->usb_endp, 0x3,
++			u132_hcd_initial_empty_sent);
++		if (retval != 0)
++			u132_hcd_giveback_urb(u132, endp, urb, retval);
++		return;
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+-        int len, int toggle_bits, int error_count, int condition_code,
+-        int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+-        struct u132_endp *endp = data;
+-        struct u132 *u132 = endp->u132;
+-        u8 address = u132->addr[endp->usb_addr].address;
+-        down(&u132->scheduler_lock);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+-                return;
+-        } else if (endp->dequeueing) {
+-                endp->dequeueing = 0;
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+-                return;
+-        } else if (u132->going > 0) {
++	int len, int toggle_bits, int error_count, int condition_code,
++	int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++	struct u132_endp *endp = data;
++	struct u132 *u132 = endp->u132;
++	u8 address = u132->addr[endp->usb_addr].address;
++	mutex_lock(&u132->scheduler_lock);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++		return;
++	} else if (endp->dequeueing) {
++		endp->dequeueing = 0;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++		return;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                up(&u132->scheduler_lock);
+-                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+-                return;
++		mutex_unlock(&u132->scheduler_lock);
++		u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++		return;
+ 	} else if (!urb->unlinked) {
+-                int retval;
+-                struct u132_ring *ring = endp->ring;
+-                up(&u132->scheduler_lock);
+-                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+-                        ring->number, endp, urb, address, endp->usb_endp, 0,
+-                        u132_hcd_initial_input_recv);
+-                if (retval == 0) {
+-                } else
+-                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                return;
+-        } else {
++		int retval;
++		struct u132_ring *ring = endp->ring;
++		mutex_unlock(&u132->scheduler_lock);
++		retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++			ring->number, endp, urb, address, endp->usb_endp, 0,
++			u132_hcd_initial_input_recv);
++		if (retval != 0)
++			u132_hcd_giveback_urb(u132, endp, urb, retval);
++		return;
++	} else {
+ 		dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ 				"unlinked=%d\n", urb, urb->unlinked);
+-                up(&u132->scheduler_lock);
++		mutex_unlock(&u132->scheduler_lock);
+ 		u132_hcd_giveback_urb(u132, endp, urb, 0);
+-                return;
+-        }
++		return;
++	}
+ }
+ 
+ /*
+@@ -1308,302 +1304,296 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+ */
+ static void u132_hcd_ring_work_scheduler(struct work_struct *work)
+ {
+-        struct u132_ring *ring =
++	struct u132_ring *ring =
+ 		container_of(work, struct u132_ring, scheduler.work);
+-        struct u132 *u132 = ring->u132;
+-        down(&u132->scheduler_lock);
+-        if (ring->in_use) {
+-                up(&u132->scheduler_lock);
+-                u132_ring_put_kref(u132, ring);
+-                return;
+-        } else if (ring->curr_endp) {
+-                struct u132_endp *last_endp = ring->curr_endp;
+-                struct list_head *scan;
+-                struct list_head *head = &last_endp->endp_ring;
+-                unsigned long wakeup = 0;
+-                list_for_each(scan, head) {
+-                        struct u132_endp *endp = list_entry(scan,
+-                                struct u132_endp, endp_ring);
+-                        if (endp->queue_next == endp->queue_last) {
+-                        } else if ((endp->delayed == 0)
+-                                || time_after_eq(jiffies, endp->jiffies)) {
+-                                ring->curr_endp = endp;
+-                                u132_endp_cancel_work(u132, last_endp);
+-                                u132_endp_queue_work(u132, last_endp, 0);
+-                                up(&u132->scheduler_lock);
+-                                u132_ring_put_kref(u132, ring);
+-                                return;
+-                        } else {
+-                                unsigned long delta = endp->jiffies - jiffies;
+-                                if (delta > wakeup)
+-                                        wakeup = delta;
+-                        }
+-                }
+-                if (last_endp->queue_next == last_endp->queue_last) {
+-                } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
+-                        last_endp->jiffies)) {
+-                        u132_endp_cancel_work(u132, last_endp);
+-                        u132_endp_queue_work(u132, last_endp, 0);
+-                        up(&u132->scheduler_lock);
+-                        u132_ring_put_kref(u132, ring);
+-                        return;
+-                } else {
+-                        unsigned long delta = last_endp->jiffies - jiffies;
+-                        if (delta > wakeup)
+-                                wakeup = delta;
+-                }
+-                if (wakeup > 0) {
+-                        u132_ring_requeue_work(u132, ring, wakeup);
+-                        up(&u132->scheduler_lock);
+-                        return;
+-                } else {
+-                        up(&u132->scheduler_lock);
+-                        u132_ring_put_kref(u132, ring);
+-                        return;
+-                }
+-        } else {
+-                up(&u132->scheduler_lock);
+-                u132_ring_put_kref(u132, ring);
+-                return;
+-        }
++	struct u132 *u132 = ring->u132;
++	mutex_lock(&u132->scheduler_lock);
++	if (ring->in_use) {
++		mutex_unlock(&u132->scheduler_lock);
++		u132_ring_put_kref(u132, ring);
++		return;
++	} else if (ring->curr_endp) {
++		struct u132_endp *last_endp = ring->curr_endp;
++		struct list_head *scan;
++		struct list_head *head = &last_endp->endp_ring;
++		unsigned long wakeup = 0;
++		list_for_each(scan, head) {
++			struct u132_endp *endp = list_entry(scan,
++				struct u132_endp, endp_ring);
++			if (endp->queue_next == endp->queue_last) {
++			} else if ((endp->delayed == 0)
++				|| time_after_eq(jiffies, endp->jiffies)) {
++				ring->curr_endp = endp;
++				u132_endp_cancel_work(u132, last_endp);
++				u132_endp_queue_work(u132, last_endp, 0);
++				mutex_unlock(&u132->scheduler_lock);
++				u132_ring_put_kref(u132, ring);
++				return;
++			} else {
++				unsigned long delta = endp->jiffies - jiffies;
++				if (delta > wakeup)
++					wakeup = delta;
++			}
++		}
++		if (last_endp->queue_next == last_endp->queue_last) {
++		} else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
++			last_endp->jiffies)) {
++			u132_endp_cancel_work(u132, last_endp);
++			u132_endp_queue_work(u132, last_endp, 0);
++			mutex_unlock(&u132->scheduler_lock);
++			u132_ring_put_kref(u132, ring);
++			return;
++		} else {
++			unsigned long delta = last_endp->jiffies - jiffies;
++			if (delta > wakeup)
++				wakeup = delta;
++		}
++		if (wakeup > 0) {
++			u132_ring_requeue_work(u132, ring, wakeup);
++			mutex_unlock(&u132->scheduler_lock);
++			return;
++		} else {
++			mutex_unlock(&u132->scheduler_lock);
++			u132_ring_put_kref(u132, ring);
++			return;
++		}
++	} else {
++		mutex_unlock(&u132->scheduler_lock);
++		u132_ring_put_kref(u132, ring);
++		return;
++	}
+ }
+ 
+ static void u132_hcd_endp_work_scheduler(struct work_struct *work)
+ {
+-        struct u132_ring *ring;
+-        struct u132_endp *endp =
++	struct u132_ring *ring;
++	struct u132_endp *endp =
+ 		container_of(work, struct u132_endp, scheduler.work);
+-        struct u132 *u132 = endp->u132;
+-        down(&u132->scheduler_lock);
+-        ring = endp->ring;
+-        if (endp->edset_flush) {
+-                endp->edset_flush = 0;
+-                if (endp->dequeueing)
+-                        usb_ftdi_elan_edset_flush(u132->platform_dev,
+-                                ring->number, endp);
+-                up(&u132->scheduler_lock);
+-                u132_endp_put_kref(u132, endp);
+-                return;
+-        } else if (endp->active) {
+-                up(&u132->scheduler_lock);
+-                u132_endp_put_kref(u132, endp);
+-                return;
+-        } else if (ring->in_use) {
+-                up(&u132->scheduler_lock);
+-                u132_endp_put_kref(u132, endp);
+-                return;
+-        } else if (endp->queue_next == endp->queue_last) {
+-                up(&u132->scheduler_lock);
+-                u132_endp_put_kref(u132, endp);
+-                return;
+-        } else if (endp->pipetype == PIPE_INTERRUPT) {
+-                u8 address = u132->addr[endp->usb_addr].address;
+-                if (ring->in_use) {
+-                        up(&u132->scheduler_lock);
+-                        u132_endp_put_kref(u132, endp);
+-                        return;
+-                } else {
+-                        int retval;
+-                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+-                                endp->queue_next];
+-                        endp->active = 1;
+-                        ring->curr_endp = endp;
+-                        ring->in_use = 1;
+-                        up(&u132->scheduler_lock);
+-                        retval = edset_single(u132, ring, endp, urb, address,
+-                                endp->toggle_bits, u132_hcd_interrupt_recv);
+-                        if (retval == 0) {
+-                        } else
+-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                        return;
+-                }
+-        } else if (endp->pipetype == PIPE_CONTROL) {
+-                u8 address = u132->addr[endp->usb_addr].address;
+-                if (ring->in_use) {
+-                        up(&u132->scheduler_lock);
+-                        u132_endp_put_kref(u132, endp);
+-                        return;
+-                } else if (address == 0) {
+-                        int retval;
+-                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+-                                endp->queue_next];
+-                        endp->active = 1;
+-                        ring->curr_endp = endp;
+-                        ring->in_use = 1;
+-                        up(&u132->scheduler_lock);
+-                        retval = edset_setup(u132, ring, endp, urb, address,
+-                                0x2, u132_hcd_initial_setup_sent);
+-                        if (retval == 0) {
+-                        } else
+-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                        return;
+-                } else if (endp->usb_addr == 0) {
+-                        int retval;
+-                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+-                                endp->queue_next];
+-                        endp->active = 1;
+-                        ring->curr_endp = endp;
+-                        ring->in_use = 1;
+-                        up(&u132->scheduler_lock);
+-                        retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
+-                                u132_hcd_enumeration_address_sent);
+-                        if (retval == 0) {
+-                        } else
+-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                        return;
+-                } else {
+-                        int retval;
+-                        u8 address = u132->addr[endp->usb_addr].address;
+-                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+-                                endp->queue_next];
+-                        endp->active = 1;
+-                        ring->curr_endp = endp;
+-                        ring->in_use = 1;
+-                        up(&u132->scheduler_lock);
+-                        retval = edset_setup(u132, ring, endp, urb, address,
+-                                0x2, u132_hcd_configure_setup_sent);
+-                        if (retval == 0) {
+-                        } else
+-                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+-                        return;
+-                }
+-        } else {
+-                if (endp->input) {
+-                        u8 address = u132->addr[endp->usb_addr].address;
+-                        if (ring->in_use) {
+-                                up(&u132->scheduler_lock);
+-                                u132_endp_put_kref(u132, endp);
+-                                return;
+-                        } else {
+-                                int retval;
+-                                struct urb *urb = endp->urb_list[
+-                                        ENDP_QUEUE_MASK & endp->queue_next];
+-                                endp->active = 1;
+-                                ring->curr_endp = endp;
+-                                ring->in_use = 1;
+-                                up(&u132->scheduler_lock);
+-                                retval = edset_input(u132, ring, endp, urb,
+-                                        address, endp->toggle_bits,
+-                                        u132_hcd_bulk_input_recv);
+-                                if (retval == 0) {
+-                                } else
+-                                        u132_hcd_giveback_urb(u132, endp, urb,
+-                                                retval);
+-                                return;
+-                        }
+-                } else {        /* output pipe */
+-                        u8 address = u132->addr[endp->usb_addr].address;
+-                        if (ring->in_use) {
+-                                up(&u132->scheduler_lock);
+-                                u132_endp_put_kref(u132, endp);
+-                                return;
+-                        } else {
+-                                int retval;
+-                                struct urb *urb = endp->urb_list[
+-                                        ENDP_QUEUE_MASK & endp->queue_next];
+-                                endp->active = 1;
+-                                ring->curr_endp = endp;
+-                                ring->in_use = 1;
+-                                up(&u132->scheduler_lock);
+-                                retval = edset_output(u132, ring, endp, urb,
+-                                        address, endp->toggle_bits,
+-                                        u132_hcd_bulk_output_sent);
+-                                if (retval == 0) {
+-                                } else
+-                                        u132_hcd_giveback_urb(u132, endp, urb,
+-                                                retval);
+-                                return;
+-                        }
+-                }
+-        }
++	struct u132 *u132 = endp->u132;
++	mutex_lock(&u132->scheduler_lock);
++	ring = endp->ring;
++	if (endp->edset_flush) {
++		endp->edset_flush = 0;
++		if (endp->dequeueing)
++			usb_ftdi_elan_edset_flush(u132->platform_dev,
++				ring->number, endp);
++		mutex_unlock(&u132->scheduler_lock);
++		u132_endp_put_kref(u132, endp);
++		return;
++	} else if (endp->active) {
++		mutex_unlock(&u132->scheduler_lock);
++		u132_endp_put_kref(u132, endp);
++		return;
++	} else if (ring->in_use) {
++		mutex_unlock(&u132->scheduler_lock);
++		u132_endp_put_kref(u132, endp);
++		return;
++	} else if (endp->queue_next == endp->queue_last) {
++		mutex_unlock(&u132->scheduler_lock);
++		u132_endp_put_kref(u132, endp);
++		return;
++	} else if (endp->pipetype == PIPE_INTERRUPT) {
++		u8 address = u132->addr[endp->usb_addr].address;
++		if (ring->in_use) {
++			mutex_unlock(&u132->scheduler_lock);
++			u132_endp_put_kref(u132, endp);
++			return;
++		} else {
++			int retval;
++			struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
++				endp->queue_next];
++			endp->active = 1;
++			ring->curr_endp = endp;
++			ring->in_use = 1;
++			mutex_unlock(&u132->scheduler_lock);
++			retval = edset_single(u132, ring, endp, urb, address,
++				endp->toggle_bits, u132_hcd_interrupt_recv);
++			if (retval != 0)
++				u132_hcd_giveback_urb(u132, endp, urb, retval);
++			return;
++		}
++	} else if (endp->pipetype == PIPE_CONTROL) {
++		u8 address = u132->addr[endp->usb_addr].address;
++		if (ring->in_use) {
++			mutex_unlock(&u132->scheduler_lock);
++			u132_endp_put_kref(u132, endp);
++			return;
++		} else if (address == 0) {
++			int retval;
++			struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
++				endp->queue_next];
++			endp->active = 1;
++			ring->curr_endp = endp;
++			ring->in_use = 1;
++			mutex_unlock(&u132->scheduler_lock);
++			retval = edset_setup(u132, ring, endp, urb, address,
++				0x2, u132_hcd_initial_setup_sent);
++			if (retval != 0)
++				u132_hcd_giveback_urb(u132, endp, urb, retval);
++			return;
++		} else if (endp->usb_addr == 0) {
++			int retval;
++			struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
++				endp->queue_next];
++			endp->active = 1;
++			ring->curr_endp = endp;
++			ring->in_use = 1;
++			mutex_unlock(&u132->scheduler_lock);
++			retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
++				u132_hcd_enumeration_address_sent);
++			if (retval != 0)
++				u132_hcd_giveback_urb(u132, endp, urb, retval);
++			return;
++		} else {
++			int retval;
++			u8 address = u132->addr[endp->usb_addr].address;
++			struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
++				endp->queue_next];
++			endp->active = 1;
++			ring->curr_endp = endp;
++			ring->in_use = 1;
++			mutex_unlock(&u132->scheduler_lock);
++			retval = edset_setup(u132, ring, endp, urb, address,
++				0x2, u132_hcd_configure_setup_sent);
++			if (retval != 0)
++				u132_hcd_giveback_urb(u132, endp, urb, retval);
++			return;
++		}
++	} else {
++		if (endp->input) {
++			u8 address = u132->addr[endp->usb_addr].address;
++			if (ring->in_use) {
++				mutex_unlock(&u132->scheduler_lock);
++				u132_endp_put_kref(u132, endp);
++				return;
++			} else {
++				int retval;
++				struct urb *urb = endp->urb_list[
++					ENDP_QUEUE_MASK & endp->queue_next];
++				endp->active = 1;
++				ring->curr_endp = endp;
++				ring->in_use = 1;
++				mutex_unlock(&u132->scheduler_lock);
++				retval = edset_input(u132, ring, endp, urb,
++					address, endp->toggle_bits,
++					u132_hcd_bulk_input_recv);
++				if (retval == 0) {
++				} else
++					u132_hcd_giveback_urb(u132, endp, urb,
++						retval);
++				return;
++			}
++		} else {	/* output pipe */
++			u8 address = u132->addr[endp->usb_addr].address;
++			if (ring->in_use) {
++				mutex_unlock(&u132->scheduler_lock);
++				u132_endp_put_kref(u132, endp);
++				return;
++			} else {
++				int retval;
++				struct urb *urb = endp->urb_list[
++					ENDP_QUEUE_MASK & endp->queue_next];
++				endp->active = 1;
++				ring->curr_endp = endp;
++				ring->in_use = 1;
++				mutex_unlock(&u132->scheduler_lock);
++				retval = edset_output(u132, ring, endp, urb,
++					address, endp->toggle_bits,
++					u132_hcd_bulk_output_sent);
++				if (retval == 0) {
++				} else
++					u132_hcd_giveback_urb(u132, endp, urb,
++						retval);
++				return;
++			}
++		}
++	}
+ }
+ #ifdef CONFIG_PM
+ 
+ static void port_power(struct u132 *u132, int pn, int is_on)
+ {
+-        u132->port[pn].power = is_on;
++	u132->port[pn].power = is_on;
+ }
+ 
+ #endif
+ 
+ static void u132_power(struct u132 *u132, int is_on)
+ {
+-        struct usb_hcd *hcd = u132_to_hcd(u132)
+-                ;        /* hub is inactive unless the port is powered */
+-        if (is_on) {
+-                if (u132->power)
+-                        return;
+-                u132->power = 1;
+-                hcd->self.controller->power.power_state = PMSG_ON;
+-        } else {
+-                u132->power = 0;
+-                hcd->state = HC_STATE_HALT;
+-                hcd->self.controller->power.power_state = PMSG_SUSPEND;
+-        }
++	struct usb_hcd *hcd = u132_to_hcd(u132)
++		;	/* hub is inactive unless the port is powered */
++	if (is_on) {
++		if (u132->power)
++			return;
++		u132->power = 1;
++	} else {
++		u132->power = 0;
++		hcd->state = HC_STATE_HALT;
++	}
+ }
+ 
+ static int u132_periodic_reinit(struct u132 *u132)
+ {
+-        int retval;
+-        u32 fi = u132->hc_fminterval & 0x03fff;
+-        u32 fit;
+-        u32 fminterval;
+-        retval = u132_read_pcimem(u132, fminterval, &fminterval);
+-        if (retval)
+-                return retval;
+-        fit = fminterval & FIT;
+-        retval = u132_write_pcimem(u132, fminterval,
+-                (fit ^ FIT) | u132->hc_fminterval);
+-        if (retval)
+-                return retval;
+-        retval = u132_write_pcimem(u132, periodicstart,
+-                ((9 *fi) / 10) & 0x3fff);
+-        if (retval)
+-                return retval;
+-        return 0;
++	int retval;
++	u32 fi = u132->hc_fminterval & 0x03fff;
++	u32 fit;
++	u32 fminterval;
++	retval = u132_read_pcimem(u132, fminterval, &fminterval);
++	if (retval)
++		return retval;
++	fit = fminterval & FIT;
++	retval = u132_write_pcimem(u132, fminterval,
++		(fit ^ FIT) | u132->hc_fminterval);
++	if (retval)
++		return retval;
++	retval = u132_write_pcimem(u132, periodicstart,
++		((9 * fi) / 10) & 0x3fff);
++	if (retval)
++		return retval;
++	return 0;
+ }
+ 
+ static char *hcfs2string(int state)
+ {
+-        switch (state) {
+-        case OHCI_USB_RESET:
+-                return "reset";
+-        case OHCI_USB_RESUME:
+-                return "resume";
+-        case OHCI_USB_OPER:
+-                return "operational";
+-        case OHCI_USB_SUSPEND:
+-                return "suspend";
+-        }
+-        return "?";
++	switch (state) {
++	case OHCI_USB_RESET:
++		return "reset";
++	case OHCI_USB_RESUME:
++		return "resume";
++	case OHCI_USB_OPER:
++		return "operational";
++	case OHCI_USB_SUSPEND:
++		return "suspend";
++	}
++	return "?";
+ }
+ 
+ static int u132_init(struct u132 *u132)
+ {
+-        int retval;
+-        u32 control;
+-        u132_disable(u132);
+-        u132->next_statechange = jiffies;
+-        retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
+-        if (retval)
+-                return retval;
+-        retval = u132_read_pcimem(u132, control, &control);
+-        if (retval)
+-                return retval;
+-        if (u132->num_ports == 0) {
+-                u32 rh_a = -1;
+-                retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+-                if (retval)
+-                        return retval;
+-                u132->num_ports = rh_a & RH_A_NDP;
+-                retval = read_roothub_info(u132);
+-                if (retval)
+-                        return retval;
+-        }
+-        if (u132->num_ports > MAX_U132_PORTS) {
+-                return -EINVAL;
+-        }
+-        return 0;
++	int retval;
++	u32 control;
++	u132_disable(u132);
++	u132->next_statechange = jiffies;
++	retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
++	if (retval)
++		return retval;
++	retval = u132_read_pcimem(u132, control, &control);
++	if (retval)
++		return retval;
++	if (u132->num_ports == 0) {
++		u32 rh_a = -1;
++		retval = u132_read_pcimem(u132, roothub.a, &rh_a);
++		if (retval)
++			return retval;
++		u132->num_ports = rh_a & RH_A_NDP;
++		retval = read_roothub_info(u132);
++		if (retval)
++			return retval;
++	}
++	if (u132->num_ports > MAX_U132_PORTS)
++		return -EINVAL;
++
++	return 0;
+ }
+ 
+ 
+@@ -1613,280 +1603,278 @@ static int u132_init(struct u132 *u132)
+ */
+ static int u132_run(struct u132 *u132)
+ {
+-        int retval;
+-        u32 control;
+-        u32 status;
+-        u32 fminterval;
+-        u32 periodicstart;
+-        u32 cmdstatus;
+-        u32 roothub_a;
+-        int mask = OHCI_INTR_INIT;
+-        int first = u132->hc_fminterval == 0;
+-        int sleep_time = 0;
+-        int reset_timeout = 30;        /* ... allow extra time */
+-        u132_disable(u132);
+-        if (first) {
+-                u32 temp;
+-                retval = u132_read_pcimem(u132, fminterval, &temp);
+-                if (retval)
+-                        return retval;
+-                u132->hc_fminterval = temp & 0x3fff;
+-                if (u132->hc_fminterval != FI) {
+-                }
+-                u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
+-        }
+-        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+-        if (retval)
+-                return retval;
+-        dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
+-                "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
+-                u132->hc_control);
+-        switch (u132->hc_control & OHCI_CTRL_HCFS) {
+-        case OHCI_USB_OPER:
+-                sleep_time = 0;
+-                break;
+-        case OHCI_USB_SUSPEND:
+-        case OHCI_USB_RESUME:
+-                u132->hc_control &= OHCI_CTRL_RWC;
+-                u132->hc_control |= OHCI_USB_RESUME;
+-                sleep_time = 10;
+-                break;
+-        default:
+-                u132->hc_control &= OHCI_CTRL_RWC;
+-                u132->hc_control |= OHCI_USB_RESET;
+-                sleep_time = 50;
+-                break;
+-        }
+-        retval = u132_write_pcimem(u132, control, u132->hc_control);
+-        if (retval)
+-                return retval;
+-        retval = u132_read_pcimem(u132, control, &control);
+-        if (retval)
+-                return retval;
+-        msleep(sleep_time);
+-        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+-        if (retval)
+-                return retval;
+-        if (!(roothub_a & RH_A_NPS)) {
+-                int temp;        /* power down each port */
+-                for (temp = 0; temp < u132->num_ports; temp++) {
+-                        retval = u132_write_pcimem(u132,
+-                                roothub.portstatus[temp], RH_PS_LSDA);
+-                        if (retval)
+-                                return retval;
+-                }
+-        }
+-        retval = u132_read_pcimem(u132, control, &control);
+-        if (retval)
+-                return retval;
+-      retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
+-        if (retval)
+-                return retval;
+-        retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
+-        if (retval)
+-                return retval;
+-      extra:{
+-                retval = u132_read_pcimem(u132, cmdstatus, &status);
+-                if (retval)
+-                        return retval;
+-                if (0 != (status & OHCI_HCR)) {
+-                        if (--reset_timeout == 0) {
+-                                dev_err(&u132->platform_dev->dev, "USB HC reset"
+-                                        " timed out!\n");
+-                                return -ENODEV;
+-                        } else {
+-                                msleep(5);
+-                                goto extra;
+-                        }
+-                }
+-        }
+-        if (u132->flags & OHCI_QUIRK_INITRESET) {
+-                retval = u132_write_pcimem(u132, control, u132->hc_control);
+-                if (retval)
+-                        return retval;
+-                retval = u132_read_pcimem(u132, control, &control);
+-                if (retval)
+-                        return retval;
+-        }
+-        retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
+-        if (retval)
+-                return retval;
+-        retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
+-        if (retval)
+-                return retval;
+-        retval = u132_write_pcimem(u132, hcca, 0x00000000);
+-        if (retval)
+-                return retval;
+-        retval = u132_periodic_reinit(u132);
+-        if (retval)
+-                return retval;
+-        retval = u132_read_pcimem(u132, fminterval, &fminterval);
+-        if (retval)
+-                return retval;
+-        retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
+-        if (retval)
+-                return retval;
+-        if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
+-                if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
+-                        u132->flags |= OHCI_QUIRK_INITRESET;
+-                        goto retry;
+-                } else
+-                        dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
+-                                "\n", fminterval, periodicstart);
+-        }                        /* start controller operations */
+-        u132->hc_control &= OHCI_CTRL_RWC;
+-        u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
+-        retval = u132_write_pcimem(u132, control, u132->hc_control);
+-        if (retval)
+-                return retval;
+-        retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
+-        if (retval)
+-                return retval;
+-        retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
+-        if (retval)
+-                return retval;
+-        retval = u132_read_pcimem(u132, control, &control);
+-        if (retval)
+-                return retval;
+-        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+-        retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
+-        if (retval)
+-                return retval;
+-        retval = u132_write_pcimem(u132, intrstatus, mask);
+-        if (retval)
+-                return retval;
+-        retval = u132_write_pcimem(u132, intrdisable,
+-                OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
+-                OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
+-                OHCI_INTR_SO);
+-        if (retval)
+-                return retval;        /* handle root hub init quirks ... */
+-        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+-        if (retval)
+-                return retval;
+-        roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
+-        if (u132->flags & OHCI_QUIRK_SUPERIO) {
+-                roothub_a |= RH_A_NOCP;
+-                roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
+-                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+-                if (retval)
+-                        return retval;
+-        } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
+-                roothub_a |= RH_A_NPS;
+-                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+-                if (retval)
+-                        return retval;
+-        }
+-        retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
+-        if (retval)
+-                return retval;
+-        retval = u132_write_pcimem(u132, roothub.b,
+-                (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
+-        if (retval)
+-                return retval;
+-        retval = u132_read_pcimem(u132, control, &control);
+-        if (retval)
+-                return retval;
+-        mdelay((roothub_a >> 23) & 0x1fe);
+-        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+-        return 0;
++	int retval;
++	u32 control;
++	u32 status;
++	u32 fminterval;
++	u32 periodicstart;
++	u32 cmdstatus;
++	u32 roothub_a;
++	int mask = OHCI_INTR_INIT;
++	int first = u132->hc_fminterval == 0;
++	int sleep_time = 0;
++	int reset_timeout = 30;	/* ... allow extra time */
++	u132_disable(u132);
++	if (first) {
++		u32 temp;
++		retval = u132_read_pcimem(u132, fminterval, &temp);
++		if (retval)
++			return retval;
++		u132->hc_fminterval = temp & 0x3fff;
++		u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
++	}
++	retval = u132_read_pcimem(u132, control, &u132->hc_control);
++	if (retval)
++		return retval;
++	dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
++		"= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
++		u132->hc_control);
++	switch (u132->hc_control & OHCI_CTRL_HCFS) {
++	case OHCI_USB_OPER:
++		sleep_time = 0;
++		break;
++	case OHCI_USB_SUSPEND:
++	case OHCI_USB_RESUME:
++		u132->hc_control &= OHCI_CTRL_RWC;
++		u132->hc_control |= OHCI_USB_RESUME;
++		sleep_time = 10;
++		break;
++	default:
++		u132->hc_control &= OHCI_CTRL_RWC;
++		u132->hc_control |= OHCI_USB_RESET;
++		sleep_time = 50;
++		break;
++	}
++	retval = u132_write_pcimem(u132, control, u132->hc_control);
++	if (retval)
++		return retval;
++	retval = u132_read_pcimem(u132, control, &control);
++	if (retval)
++		return retval;
++	msleep(sleep_time);
++	retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
++	if (retval)
++		return retval;
++	if (!(roothub_a & RH_A_NPS)) {
++		int temp;	/* power down each port */
++		for (temp = 0; temp < u132->num_ports; temp++) {
++			retval = u132_write_pcimem(u132,
++				roothub.portstatus[temp], RH_PS_LSDA);
++			if (retval)
++				return retval;
++		}
++	}
++	retval = u132_read_pcimem(u132, control, &control);
++	if (retval)
++		return retval;
++retry:
++	retval = u132_read_pcimem(u132, cmdstatus, &status);
++	if (retval)
++		return retval;
++	retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
++	if (retval)
++		return retval;
++extra:	{
++		retval = u132_read_pcimem(u132, cmdstatus, &status);
++		if (retval)
++			return retval;
++		if (0 != (status & OHCI_HCR)) {
++			if (--reset_timeout == 0) {
++				dev_err(&u132->platform_dev->dev, "USB HC reset"
++					" timed out!\n");
++				return -ENODEV;
++			} else {
++				msleep(5);
++				goto extra;
++			}
++		}
++	}
++	if (u132->flags & OHCI_QUIRK_INITRESET) {
++		retval = u132_write_pcimem(u132, control, u132->hc_control);
++		if (retval)
++			return retval;
++		retval = u132_read_pcimem(u132, control, &control);
++		if (retval)
++			return retval;
++	}
++	retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
++	if (retval)
++		return retval;
++	retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
++	if (retval)
++		return retval;
++	retval = u132_write_pcimem(u132, hcca, 0x00000000);
++	if (retval)
++		return retval;
++	retval = u132_periodic_reinit(u132);
++	if (retval)
++		return retval;
++	retval = u132_read_pcimem(u132, fminterval, &fminterval);
++	if (retval)
++		return retval;
++	retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
++	if (retval)
++		return retval;
++	if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
++		if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
++			u132->flags |= OHCI_QUIRK_INITRESET;
++			goto retry;
++		} else
++			dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
++				"\n", fminterval, periodicstart);
++	}			/* start controller operations */
++	u132->hc_control &= OHCI_CTRL_RWC;
++	u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
++	retval = u132_write_pcimem(u132, control, u132->hc_control);
++	if (retval)
++		return retval;
++	retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
++	if (retval)
++		return retval;
++	retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
++	if (retval)
++		return retval;
++	retval = u132_read_pcimem(u132, control, &control);
++	if (retval)
++		return retval;
++	u132_to_hcd(u132)->state = HC_STATE_RUNNING;
++	retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
++	if (retval)
++		return retval;
++	retval = u132_write_pcimem(u132, intrstatus, mask);
++	if (retval)
++		return retval;
++	retval = u132_write_pcimem(u132, intrdisable,
++		OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
++		OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
++		OHCI_INTR_SO);
++	if (retval)
++		return retval;	/* handle root hub init quirks ... */
++	retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
++	if (retval)
++		return retval;
++	roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
++	if (u132->flags & OHCI_QUIRK_SUPERIO) {
++		roothub_a |= RH_A_NOCP;
++		roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
++		retval = u132_write_pcimem(u132, roothub.a, roothub_a);
++		if (retval)
++			return retval;
++	} else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
++		roothub_a |= RH_A_NPS;
++		retval = u132_write_pcimem(u132, roothub.a, roothub_a);
++		if (retval)
++			return retval;
++	}
++	retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
++	if (retval)
++		return retval;
++	retval = u132_write_pcimem(u132, roothub.b,
++		(roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
++	if (retval)
++		return retval;
++	retval = u132_read_pcimem(u132, control, &control);
++	if (retval)
++		return retval;
++	mdelay((roothub_a >> 23) & 0x1fe);
++	u132_to_hcd(u132)->state = HC_STATE_RUNNING;
++	return 0;
+ }
+ 
+ static void u132_hcd_stop(struct usb_hcd *hcd)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
+-                        "een removed %d\n", u132, hcd, u132->going);
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+-                        "ed\n", hcd);
+-        } else {
+-                mutex_lock(&u132->sw_lock);
+-                msleep(100);
+-                u132_power(u132, 0);
+-                mutex_unlock(&u132->sw_lock);
+-        }
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
++			"een removed %d\n", u132, hcd, u132->going);
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
++			"ed\n", hcd);
++	} else {
++		mutex_lock(&u132->sw_lock);
++		msleep(100);
++		u132_power(u132, 0);
++		mutex_unlock(&u132->sw_lock);
++	}
+ }
+ 
+ static int u132_hcd_start(struct usb_hcd *hcd)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else if (hcd->self.controller) {
+-                int retval;
+-                struct platform_device *pdev =
+-                        to_platform_device(hcd->self.controller);
+-                u16 vendor = ((struct u132_platform_data *)
+-                        (pdev->dev.platform_data))->vendor;
+-                u16 device = ((struct u132_platform_data *)
+-                        (pdev->dev.platform_data))->device;
+-                mutex_lock(&u132->sw_lock);
+-                msleep(10);
+-                if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
+-                        u132->flags = OHCI_QUIRK_AMD756;
+-                } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
+-                        dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
+-                                "ounds unavailable\n");
+-                } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
+-                        u132->flags |= OHCI_QUIRK_ZFMICRO;
+-                retval = u132_run(u132);
+-                if (retval) {
+-                        u132_disable(u132);
+-                        u132->going = 1;
+-                }
+-                msleep(100);
+-                mutex_unlock(&u132->sw_lock);
+-                return retval;
+-        } else {
+-                dev_err(&u132->platform_dev->dev, "platform_device missing\n");
+-                return -ENODEV;
+-        }
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		return -ESHUTDOWN;
++	} else if (hcd->self.controller) {
++		int retval;
++		struct platform_device *pdev =
++			to_platform_device(hcd->self.controller);
++		u16 vendor = ((struct u132_platform_data *)
++			(pdev->dev.platform_data))->vendor;
++		u16 device = ((struct u132_platform_data *)
++			(pdev->dev.platform_data))->device;
++		mutex_lock(&u132->sw_lock);
++		msleep(10);
++		if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
++			u132->flags = OHCI_QUIRK_AMD756;
++		} else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
++			dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
++				"ounds unavailable\n");
++		} else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
++			u132->flags |= OHCI_QUIRK_ZFMICRO;
++		retval = u132_run(u132);
++		if (retval) {
++			u132_disable(u132);
++			u132->going = 1;
++		}
++		msleep(100);
++		mutex_unlock(&u132->sw_lock);
++		return retval;
++	} else {
++		dev_err(&u132->platform_dev->dev, "platform_device missing\n");
++		return -ENODEV;
++	}
+ }
+ 
+ static int u132_hcd_reset(struct usb_hcd *hcd)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else {
+-                int retval;
+-                mutex_lock(&u132->sw_lock);
+-                retval = u132_init(u132);
+-                if (retval) {
+-                        u132_disable(u132);
+-                        u132->going = 1;
+-                }
+-                mutex_unlock(&u132->sw_lock);
+-                return retval;
+-        }
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		return -ESHUTDOWN;
++	} else {
++		int retval;
++		mutex_lock(&u132->sw_lock);
++		retval = u132_init(u132);
++		if (retval) {
++			u132_disable(u132);
++			u132->going = 1;
++		}
++		mutex_unlock(&u132->sw_lock);
++		return retval;
++	}
+ }
+ 
+ static int create_endpoint_and_queue_int(struct u132 *u132,
+ 	struct u132_udev *udev, struct urb *urb,
+-        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+-        gfp_t mem_flags)
++	struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
++	gfp_t mem_flags)
+ {
+-        struct u132_ring *ring;
+-        unsigned long irqs;
++	struct u132_ring *ring;
++	unsigned long irqs;
+ 	int rc;
+ 	u8 endp_number;
+ 	struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
+ 
+-        if (!endp) {
+-                return -ENOMEM;
+-        }
++	if (!endp)
++		return -ENOMEM;
+ 
+ 	spin_lock_init(&endp->queue_lock.slock);
+ 	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+@@ -1899,94 +1887,93 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
+ 
+ 	endp_number = ++u132->num_endpoints;
+ 	urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
+-        INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+-        INIT_LIST_HEAD(&endp->urb_more);
+-        ring = endp->ring = &u132->ring[0];
+-        if (ring->curr_endp) {
+-                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+-        } else {
+-                INIT_LIST_HEAD(&endp->endp_ring);
+-                ring->curr_endp = endp;
+-        }
+-        ring->length += 1;
+-        endp->dequeueing = 0;
+-        endp->edset_flush = 0;
+-        endp->active = 0;
+-        endp->delayed = 0;
+-        endp->endp_number = endp_number;
+-        endp->u132 = u132;
++	INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
++	INIT_LIST_HEAD(&endp->urb_more);
++	ring = endp->ring = &u132->ring[0];
++	if (ring->curr_endp) {
++		list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
++	} else {
++		INIT_LIST_HEAD(&endp->endp_ring);
++		ring->curr_endp = endp;
++	}
++	ring->length += 1;
++	endp->dequeueing = 0;
++	endp->edset_flush = 0;
++	endp->active = 0;
++	endp->delayed = 0;
++	endp->endp_number = endp_number;
++	endp->u132 = u132;
+ 	endp->hep = urb->ep;
+-        endp->pipetype = usb_pipetype(urb->pipe);
+-        u132_endp_init_kref(u132, endp);
+-        if (usb_pipein(urb->pipe)) {
+-                endp->toggle_bits = 0x2;
+-                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+-                endp->input = 1;
+-                endp->output = 0;
+-                udev->endp_number_in[usb_endp] = endp_number;
+-                u132_udev_get_kref(u132, udev);
+-        } else {
+-                endp->toggle_bits = 0x2;
+-                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+-                endp->input = 0;
+-                endp->output = 1;
+-                udev->endp_number_out[usb_endp] = endp_number;
+-                u132_udev_get_kref(u132, udev);
+-        }
+-        urb->hcpriv = u132;
+-        endp->delayed = 1;
+-        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+-        endp->udev_number = address;
+-        endp->usb_addr = usb_addr;
+-        endp->usb_endp = usb_endp;
+-        endp->queue_size = 1;
+-        endp->queue_last = 0;
+-        endp->queue_next = 0;
+-        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+-        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-        u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
+-        return 0;
++	endp->pipetype = usb_pipetype(urb->pipe);
++	u132_endp_init_kref(u132, endp);
++	if (usb_pipein(urb->pipe)) {
++		endp->toggle_bits = 0x2;
++		usb_settoggle(udev->usb_device, usb_endp, 0, 0);
++		endp->input = 1;
++		endp->output = 0;
++		udev->endp_number_in[usb_endp] = endp_number;
++		u132_udev_get_kref(u132, udev);
++	} else {
++		endp->toggle_bits = 0x2;
++		usb_settoggle(udev->usb_device, usb_endp, 1, 0);
++		endp->input = 0;
++		endp->output = 1;
++		udev->endp_number_out[usb_endp] = endp_number;
++		u132_udev_get_kref(u132, udev);
++	}
++	urb->hcpriv = u132;
++	endp->delayed = 1;
++	endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
++	endp->udev_number = address;
++	endp->usb_addr = usb_addr;
++	endp->usb_endp = usb_endp;
++	endp->queue_size = 1;
++	endp->queue_last = 0;
++	endp->queue_next = 0;
++	endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++	spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++	u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
++	return 0;
+ }
+ 
+ static int queue_int_on_old_endpoint(struct u132 *u132,
+ 	struct u132_udev *udev, struct urb *urb,
+-        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+-        u8 usb_endp, u8 address)
+-{
+-        urb->hcpriv = u132;
+-        endp->delayed = 1;
+-        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+-        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+-        } else {
+-                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+-                        GFP_ATOMIC);
+-                if (urbq == NULL) {
+-                        endp->queue_size -= 1;
+-                        return -ENOMEM;
+-                } else {
+-                        list_add_tail(&urbq->urb_more, &endp->urb_more);
+-                        urbq->urb = urb;
+-                }
+-        }
+-        return 0;
++	struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
++	u8 usb_endp, u8 address)
++{
++	urb->hcpriv = u132;
++	endp->delayed = 1;
++	endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
++	if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++	} else {
++		struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
++			GFP_ATOMIC);
++		if (urbq == NULL) {
++			endp->queue_size -= 1;
++			return -ENOMEM;
++		} else {
++			list_add_tail(&urbq->urb_more, &endp->urb_more);
++			urbq->urb = urb;
++		}
++	}
++	return 0;
+ }
+ 
+ static int create_endpoint_and_queue_bulk(struct u132 *u132,
+ 	struct u132_udev *udev, struct urb *urb,
+-        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+-        gfp_t mem_flags)
++	struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
++	gfp_t mem_flags)
+ {
+-        int ring_number;
+-        struct u132_ring *ring;
+-        unsigned long irqs;
++	int ring_number;
++	struct u132_ring *ring;
++	unsigned long irqs;
+ 	int rc;
+ 	u8 endp_number;
+ 	struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
+ 
+-        if (!endp) {
+-                return -ENOMEM;
+-        }
++	if (!endp)
++		return -ENOMEM;
+ 
+ 	spin_lock_init(&endp->queue_lock.slock);
+ 	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+@@ -1999,91 +1986,90 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
+ 
+ 	endp_number = ++u132->num_endpoints;
+ 	urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
+-        INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+-        INIT_LIST_HEAD(&endp->urb_more);
+-        endp->dequeueing = 0;
+-        endp->edset_flush = 0;
+-        endp->active = 0;
+-        endp->delayed = 0;
+-        endp->endp_number = endp_number;
+-        endp->u132 = u132;
++	INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
++	INIT_LIST_HEAD(&endp->urb_more);
++	endp->dequeueing = 0;
++	endp->edset_flush = 0;
++	endp->active = 0;
++	endp->delayed = 0;
++	endp->endp_number = endp_number;
++	endp->u132 = u132;
+ 	endp->hep = urb->ep;
+-        endp->pipetype = usb_pipetype(urb->pipe);
+-        u132_endp_init_kref(u132, endp);
+-        if (usb_pipein(urb->pipe)) {
+-                endp->toggle_bits = 0x2;
+-                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+-                ring_number = 3;
+-                endp->input = 1;
+-                endp->output = 0;
+-                udev->endp_number_in[usb_endp] = endp_number;
+-                u132_udev_get_kref(u132, udev);
+-        } else {
+-                endp->toggle_bits = 0x2;
+-                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+-                ring_number = 2;
+-                endp->input = 0;
+-                endp->output = 1;
+-                udev->endp_number_out[usb_endp] = endp_number;
+-                u132_udev_get_kref(u132, udev);
+-        }
+-        ring = endp->ring = &u132->ring[ring_number - 1];
+-        if (ring->curr_endp) {
+-                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+-        } else {
+-                INIT_LIST_HEAD(&endp->endp_ring);
+-                ring->curr_endp = endp;
+-        }
+-        ring->length += 1;
+-        urb->hcpriv = u132;
+-        endp->udev_number = address;
+-        endp->usb_addr = usb_addr;
+-        endp->usb_endp = usb_endp;
+-        endp->queue_size = 1;
+-        endp->queue_last = 0;
+-        endp->queue_next = 0;
+-        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+-        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-        u132_endp_queue_work(u132, endp, 0);
+-        return 0;
++	endp->pipetype = usb_pipetype(urb->pipe);
++	u132_endp_init_kref(u132, endp);
++	if (usb_pipein(urb->pipe)) {
++		endp->toggle_bits = 0x2;
++		usb_settoggle(udev->usb_device, usb_endp, 0, 0);
++		ring_number = 3;
++		endp->input = 1;
++		endp->output = 0;
++		udev->endp_number_in[usb_endp] = endp_number;
++		u132_udev_get_kref(u132, udev);
++	} else {
++		endp->toggle_bits = 0x2;
++		usb_settoggle(udev->usb_device, usb_endp, 1, 0);
++		ring_number = 2;
++		endp->input = 0;
++		endp->output = 1;
++		udev->endp_number_out[usb_endp] = endp_number;
++		u132_udev_get_kref(u132, udev);
++	}
++	ring = endp->ring = &u132->ring[ring_number - 1];
++	if (ring->curr_endp) {
++		list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
++	} else {
++		INIT_LIST_HEAD(&endp->endp_ring);
++		ring->curr_endp = endp;
++	}
++	ring->length += 1;
++	urb->hcpriv = u132;
++	endp->udev_number = address;
++	endp->usb_addr = usb_addr;
++	endp->usb_endp = usb_endp;
++	endp->queue_size = 1;
++	endp->queue_last = 0;
++	endp->queue_next = 0;
++	endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++	spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++	u132_endp_queue_work(u132, endp, 0);
++	return 0;
+ }
+ 
+ static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+ 	struct urb *urb,
+-        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+-        u8 usb_endp, u8 address)
+-{
+-        urb->hcpriv = u132;
+-        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+-        } else {
+-                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+-                        GFP_ATOMIC);
+-                if (urbq == NULL) {
+-                        endp->queue_size -= 1;
+-                        return -ENOMEM;
+-                } else {
+-                        list_add_tail(&urbq->urb_more, &endp->urb_more);
+-                        urbq->urb = urb;
+-                }
+-        }
+-        return 0;
++	struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
++	u8 usb_endp, u8 address)
++{
++	urb->hcpriv = u132;
++	if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++	} else {
++		struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
++			GFP_ATOMIC);
++		if (urbq == NULL) {
++			endp->queue_size -= 1;
++			return -ENOMEM;
++		} else {
++			list_add_tail(&urbq->urb_more, &endp->urb_more);
++			urbq->urb = urb;
++		}
++	}
++	return 0;
+ }
+ 
+ static int create_endpoint_and_queue_control(struct u132 *u132,
+ 	struct urb *urb,
+-        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
+-        gfp_t mem_flags)
++	struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
++	gfp_t mem_flags)
+ {
+-        struct u132_ring *ring;
++	struct u132_ring *ring;
+ 	unsigned long irqs;
+ 	int rc;
+ 	u8 endp_number;
+ 	struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
+ 
+-        if (!endp) {
+-                return -ENOMEM;
+-        }
++	if (!endp)
++		return -ENOMEM;
+ 
+ 	spin_lock_init(&endp->queue_lock.slock);
+ 	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+@@ -2096,204 +2082,203 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
+ 
+ 	endp_number = ++u132->num_endpoints;
+ 	urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
+-        INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+-        INIT_LIST_HEAD(&endp->urb_more);
+-        ring = endp->ring = &u132->ring[0];
+-        if (ring->curr_endp) {
+-                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+-        } else {
+-                INIT_LIST_HEAD(&endp->endp_ring);
+-                ring->curr_endp = endp;
+-        }
+-        ring->length += 1;
+-        endp->dequeueing = 0;
+-        endp->edset_flush = 0;
+-        endp->active = 0;
+-        endp->delayed = 0;
+-        endp->endp_number = endp_number;
+-        endp->u132 = u132;
++	INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
++	INIT_LIST_HEAD(&endp->urb_more);
++	ring = endp->ring = &u132->ring[0];
++	if (ring->curr_endp) {
++		list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
++	} else {
++		INIT_LIST_HEAD(&endp->endp_ring);
++		ring->curr_endp = endp;
++	}
++	ring->length += 1;
++	endp->dequeueing = 0;
++	endp->edset_flush = 0;
++	endp->active = 0;
++	endp->delayed = 0;
++	endp->endp_number = endp_number;
++	endp->u132 = u132;
+ 	endp->hep = urb->ep;
+-        u132_endp_init_kref(u132, endp);
+-        u132_endp_get_kref(u132, endp);
+-        if (usb_addr == 0) {
+-                u8 address = u132->addr[usb_addr].address;
+-                struct u132_udev *udev = &u132->udev[address];
+-                endp->udev_number = address;
+-                endp->usb_addr = usb_addr;
+-                endp->usb_endp = usb_endp;
+-                endp->input = 1;
+-                endp->output = 1;
+-                endp->pipetype = usb_pipetype(urb->pipe);
+-                u132_udev_init_kref(u132, udev);
+-                u132_udev_get_kref(u132, udev);
+-                udev->endp_number_in[usb_endp] = endp_number;
+-                udev->endp_number_out[usb_endp] = endp_number;
+-                urb->hcpriv = u132;
+-                endp->queue_size = 1;
+-                endp->queue_last = 0;
+-                endp->queue_next = 0;
+-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                u132_endp_queue_work(u132, endp, 0);
+-                return 0;
+-        } else {                /*(usb_addr > 0) */
+-                u8 address = u132->addr[usb_addr].address;
+-                struct u132_udev *udev = &u132->udev[address];
+-                endp->udev_number = address;
+-                endp->usb_addr = usb_addr;
+-                endp->usb_endp = usb_endp;
+-                endp->input = 1;
+-                endp->output = 1;
+-                endp->pipetype = usb_pipetype(urb->pipe);
+-                u132_udev_get_kref(u132, udev);
+-                udev->enumeration = 2;
+-                udev->endp_number_in[usb_endp] = endp_number;
+-                udev->endp_number_out[usb_endp] = endp_number;
+-                urb->hcpriv = u132;
+-                endp->queue_size = 1;
+-                endp->queue_last = 0;
+-                endp->queue_next = 0;
+-                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                u132_endp_queue_work(u132, endp, 0);
+-                return 0;
+-        }
++	u132_endp_init_kref(u132, endp);
++	u132_endp_get_kref(u132, endp);
++	if (usb_addr == 0) {
++		u8 address = u132->addr[usb_addr].address;
++		struct u132_udev *udev = &u132->udev[address];
++		endp->udev_number = address;
++		endp->usb_addr = usb_addr;
++		endp->usb_endp = usb_endp;
++		endp->input = 1;
++		endp->output = 1;
++		endp->pipetype = usb_pipetype(urb->pipe);
++		u132_udev_init_kref(u132, udev);
++		u132_udev_get_kref(u132, udev);
++		udev->endp_number_in[usb_endp] = endp_number;
++		udev->endp_number_out[usb_endp] = endp_number;
++		urb->hcpriv = u132;
++		endp->queue_size = 1;
++		endp->queue_last = 0;
++		endp->queue_next = 0;
++		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++		u132_endp_queue_work(u132, endp, 0);
++		return 0;
++	} else {		/*(usb_addr > 0) */
++		u8 address = u132->addr[usb_addr].address;
++		struct u132_udev *udev = &u132->udev[address];
++		endp->udev_number = address;
++		endp->usb_addr = usb_addr;
++		endp->usb_endp = usb_endp;
++		endp->input = 1;
++		endp->output = 1;
++		endp->pipetype = usb_pipetype(urb->pipe);
++		u132_udev_get_kref(u132, udev);
++		udev->enumeration = 2;
++		udev->endp_number_in[usb_endp] = endp_number;
++		udev->endp_number_out[usb_endp] = endp_number;
++		urb->hcpriv = u132;
++		endp->queue_size = 1;
++		endp->queue_last = 0;
++		endp->queue_next = 0;
++		endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++		u132_endp_queue_work(u132, endp, 0);
++		return 0;
++	}
+ }
+ 
+ static int queue_control_on_old_endpoint(struct u132 *u132,
+ 	struct urb *urb,
+-        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+-        u8 usb_endp)
+-{
+-        if (usb_addr == 0) {
+-                if (usb_pipein(urb->pipe)) {
+-                        urb->hcpriv = u132;
+-                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+-                                endp->urb_list[ENDP_QUEUE_MASK &
+-                                        endp->queue_last++] = urb;
+-                        } else {
+-                                struct u132_urbq *urbq =
+-                                        kmalloc(sizeof(struct u132_urbq),
+-                                        GFP_ATOMIC);
+-                                if (urbq == NULL) {
+-                                        endp->queue_size -= 1;
+-                                        return -ENOMEM;
+-                                } else {
+-                                        list_add_tail(&urbq->urb_more,
+-                                                &endp->urb_more);
+-                                        urbq->urb = urb;
+-                                }
+-                        }
+-                        return 0;
+-                } else {        /* usb_pipeout(urb->pipe) */
+-                        struct u132_addr *addr = &u132->addr[usb_dev->devnum];
+-                        int I = MAX_U132_UDEVS;
+-                        int i = 0;
+-                        while (--I > 0) {
+-                                struct u132_udev *udev = &u132->udev[++i];
+-                                if (udev->usb_device) {
+-                                        continue;
+-                                } else {
+-                                        udev->enumeration = 1;
+-                                        u132->addr[0].address = i;
+-                                        endp->udev_number = i;
+-                                        udev->udev_number = i;
+-                                        udev->usb_addr = usb_dev->devnum;
+-                                        u132_udev_init_kref(u132, udev);
+-                                        udev->endp_number_in[usb_endp] =
+-                                                endp->endp_number;
+-                                        u132_udev_get_kref(u132, udev);
+-                                        udev->endp_number_out[usb_endp] =
+-                                                endp->endp_number;
+-                                        udev->usb_device = usb_dev;
+-                                        ((u8 *) (urb->setup_packet))[2] =
+-                                                addr->address = i;
+-                                        u132_udev_get_kref(u132, udev);
+-                                        break;
+-                                }
+-                        }
+-                        if (I == 0) {
+-                                dev_err(&u132->platform_dev->dev, "run out of d"
+-                                        "evice space\n");
+-                                return -EINVAL;
+-                        }
+-                        urb->hcpriv = u132;
+-                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+-                                endp->urb_list[ENDP_QUEUE_MASK &
+-                                        endp->queue_last++] = urb;
+-                        } else {
+-                                struct u132_urbq *urbq =
+-                                        kmalloc(sizeof(struct u132_urbq),
+-                                        GFP_ATOMIC);
+-                                if (urbq == NULL) {
+-                                        endp->queue_size -= 1;
+-                                        return -ENOMEM;
+-                                } else {
+-                                        list_add_tail(&urbq->urb_more,
+-                                                &endp->urb_more);
+-                                        urbq->urb = urb;
+-                                }
+-                        }
+-                        return 0;
+-                }
+-        } else {                /*(usb_addr > 0) */
+-                u8 address = u132->addr[usb_addr].address;
+-                struct u132_udev *udev = &u132->udev[address];
+-                urb->hcpriv = u132;
+-                if (udev->enumeration == 2) {
+-                } else
+-                        udev->enumeration = 2;
+-                if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+-                        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+-                                urb;
+-                } else {
+-                        struct u132_urbq *urbq =
+-                                kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
+-                        if (urbq == NULL) {
+-                                endp->queue_size -= 1;
+-                                return -ENOMEM;
+-                        } else {
+-                                list_add_tail(&urbq->urb_more, &endp->urb_more);
+-                                urbq->urb = urb;
+-                        }
+-                }
+-                return 0;
+-        }
++	struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
++	u8 usb_endp)
++{
++	if (usb_addr == 0) {
++		if (usb_pipein(urb->pipe)) {
++			urb->hcpriv = u132;
++			if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++				endp->urb_list[ENDP_QUEUE_MASK &
++					endp->queue_last++] = urb;
++			} else {
++				struct u132_urbq *urbq =
++					kmalloc(sizeof(struct u132_urbq),
++					GFP_ATOMIC);
++				if (urbq == NULL) {
++					endp->queue_size -= 1;
++					return -ENOMEM;
++				} else {
++					list_add_tail(&urbq->urb_more,
++						&endp->urb_more);
++					urbq->urb = urb;
++				}
++			}
++			return 0;
++		} else {	/* usb_pipeout(urb->pipe) */
++			struct u132_addr *addr = &u132->addr[usb_dev->devnum];
++			int I = MAX_U132_UDEVS;
++			int i = 0;
++			while (--I > 0) {
++				struct u132_udev *udev = &u132->udev[++i];
++				if (udev->usb_device) {
++					continue;
++				} else {
++					udev->enumeration = 1;
++					u132->addr[0].address = i;
++					endp->udev_number = i;
++					udev->udev_number = i;
++					udev->usb_addr = usb_dev->devnum;
++					u132_udev_init_kref(u132, udev);
++					udev->endp_number_in[usb_endp] =
++						endp->endp_number;
++					u132_udev_get_kref(u132, udev);
++					udev->endp_number_out[usb_endp] =
++						endp->endp_number;
++					udev->usb_device = usb_dev;
++					((u8 *) (urb->setup_packet))[2] =
++						addr->address = i;
++					u132_udev_get_kref(u132, udev);
++					break;
++				}
++			}
++			if (I == 0) {
++				dev_err(&u132->platform_dev->dev, "run out of d"
++					"evice space\n");
++				return -EINVAL;
++			}
++			urb->hcpriv = u132;
++			if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++				endp->urb_list[ENDP_QUEUE_MASK &
++					endp->queue_last++] = urb;
++			} else {
++				struct u132_urbq *urbq =
++					kmalloc(sizeof(struct u132_urbq),
++					GFP_ATOMIC);
++				if (urbq == NULL) {
++					endp->queue_size -= 1;
++					return -ENOMEM;
++				} else {
++					list_add_tail(&urbq->urb_more,
++						&endp->urb_more);
++					urbq->urb = urb;
++				}
++			}
++			return 0;
++		}
++	} else {		/*(usb_addr > 0) */
++		u8 address = u132->addr[usb_addr].address;
++		struct u132_udev *udev = &u132->udev[address];
++		urb->hcpriv = u132;
++		if (udev->enumeration != 2)
++			udev->enumeration = 2;
++		if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++			endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
++				urb;
++		} else {
++			struct u132_urbq *urbq =
++				kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
++			if (urbq == NULL) {
++				endp->queue_size -= 1;
++				return -ENOMEM;
++			} else {
++				list_add_tail(&urbq->urb_more, &endp->urb_more);
++				urbq->urb = urb;
++			}
++		}
++		return 0;
++	}
+ }
+ 
+ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ 		gfp_t mem_flags)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (irqs_disabled()) {
+-                if (__GFP_WAIT & mem_flags) {
+-                        printk(KERN_ERR "invalid context for function that migh"
+-                                "t sleep\n");
+-                        return -EINVAL;
+-                }
+-        }
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (irqs_disabled()) {
++		if (__GFP_WAIT & mem_flags) {
++			printk(KERN_ERR "invalid context for function that migh"
++				"t sleep\n");
++			return -EINVAL;
++		}
++	}
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
+ 		dev_err(&u132->platform_dev->dev, "device is being removed "
+ 				"urb=%p\n", urb);
+-                return -ESHUTDOWN;
+-        } else {
+-                u8 usb_addr = usb_pipedevice(urb->pipe);
+-                u8 usb_endp = usb_pipeendpoint(urb->pipe);
+-                struct usb_device *usb_dev = urb->dev;
+-                if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+-                        u8 address = u132->addr[usb_addr].address;
+-                        struct u132_udev *udev = &u132->udev[address];
+-                        struct u132_endp *endp = urb->ep->hcpriv;
+-                        urb->actual_length = 0;
+-                        if (endp) {
+-                                unsigned long irqs;
+-                                int retval;
+-                                spin_lock_irqsave(&endp->queue_lock.slock,
+-                                        irqs);
++		return -ESHUTDOWN;
++	} else {
++		u8 usb_addr = usb_pipedevice(urb->pipe);
++		u8 usb_endp = usb_pipeendpoint(urb->pipe);
++		struct usb_device *usb_dev = urb->dev;
++		if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
++			u8 address = u132->addr[usb_addr].address;
++			struct u132_udev *udev = &u132->udev[address];
++			struct u132_endp *endp = urb->ep->hcpriv;
++			urb->actual_length = 0;
++			if (endp) {
++				unsigned long irqs;
++				int retval;
++				spin_lock_irqsave(&endp->queue_lock.slock,
++					irqs);
+ 				retval = usb_hcd_link_urb_to_ep(hcd, urb);
+ 				if (retval == 0) {
+ 					retval = queue_int_on_old_endpoint(
+@@ -2303,39 +2288,39 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ 							address);
+ 					if (retval)
+ 						usb_hcd_unlink_urb_from_ep(
+-								hcd, urb);
++	hcd, urb);
+ 				}
+-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+-                                        irqs);
+-                                if (retval) {
+-                                        return retval;
+-                                } else {
+-                                        u132_endp_queue_work(u132, endp,
+-                                                msecs_to_jiffies(urb->interval))
+-                                                ;
+-                                        return 0;
+-                                }
+-                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+-                                return -EINVAL;
+-                        } else {        /*(endp == NULL) */
+-                                return create_endpoint_and_queue_int(u132, udev,
++				spin_unlock_irqrestore(&endp->queue_lock.slock,
++					irqs);
++				if (retval) {
++					return retval;
++				} else {
++					u132_endp_queue_work(u132, endp,
++						msecs_to_jiffies(urb->interval))
++						;
++					return 0;
++				}
++			} else if (u132->num_endpoints == MAX_U132_ENDPS) {
++				return -EINVAL;
++			} else {	/*(endp == NULL) */
++				return create_endpoint_and_queue_int(u132, udev,
+ 						urb, usb_dev, usb_addr,
+ 						usb_endp, address, mem_flags);
+-                        }
+-                } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+-                        dev_err(&u132->platform_dev->dev, "the hardware does no"
+-                                "t support PIPE_ISOCHRONOUS\n");
+-                        return -EINVAL;
+-                } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
+-                        u8 address = u132->addr[usb_addr].address;
+-                        struct u132_udev *udev = &u132->udev[address];
+-                        struct u132_endp *endp = urb->ep->hcpriv;
+-                        urb->actual_length = 0;
+-                        if (endp) {
+-                                unsigned long irqs;
+-                                int retval;
+-                                spin_lock_irqsave(&endp->queue_lock.slock,
+-                                        irqs);
++			}
++		} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
++			dev_err(&u132->platform_dev->dev, "the hardware does no"
++				"t support PIPE_ISOCHRONOUS\n");
++			return -EINVAL;
++		} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
++			u8 address = u132->addr[usb_addr].address;
++			struct u132_udev *udev = &u132->udev[address];
++			struct u132_endp *endp = urb->ep->hcpriv;
++			urb->actual_length = 0;
++			if (endp) {
++				unsigned long irqs;
++				int retval;
++				spin_lock_irqsave(&endp->queue_lock.slock,
++					irqs);
+ 				retval = usb_hcd_link_urb_to_ep(hcd, urb);
+ 				if (retval == 0) {
+ 					retval = queue_bulk_on_old_endpoint(
+@@ -2345,46 +2330,46 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ 							address);
+ 					if (retval)
+ 						usb_hcd_unlink_urb_from_ep(
+-								hcd, urb);
++	hcd, urb);
++				}
++				spin_unlock_irqrestore(&endp->queue_lock.slock,
++					irqs);
++				if (retval) {
++					return retval;
++				} else {
++					u132_endp_queue_work(u132, endp, 0);
++					return 0;
+ 				}
+-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+-                                        irqs);
+-                                if (retval) {
+-                                        return retval;
+-                                } else {
+-                                        u132_endp_queue_work(u132, endp, 0);
+-                                        return 0;
+-                                }
+-                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+-                                return -EINVAL;
+-                        } else
+-                                return create_endpoint_and_queue_bulk(u132,
++			} else if (u132->num_endpoints == MAX_U132_ENDPS) {
++				return -EINVAL;
++			} else
++				return create_endpoint_and_queue_bulk(u132,
+ 					udev, urb, usb_dev, usb_addr,
+-                                        usb_endp, address, mem_flags);
+-                } else {
+-                        struct u132_endp *endp = urb->ep->hcpriv;
+-                        u16 urb_size = 8;
+-                        u8 *b = urb->setup_packet;
+-                        int i = 0;
+-                        char data[30 *3 + 4];
+-                        char *d = data;
+-                        int m = (sizeof(data) - 1) / 3;
+-                        int l = 0;
+-                        data[0] = 0;
+-                        while (urb_size-- > 0) {
+-                                if (i > m) {
+-                                } else if (i++ < m) {
+-                                        int w = sprintf(d, " %02X", *b++);
+-                                        d += w;
+-                                        l += w;
+-                                } else
+-                                        d += sprintf(d, " ..");
+-                        }
+-                        if (endp) {
+-                                unsigned long irqs;
+-                                int retval;
+-                                spin_lock_irqsave(&endp->queue_lock.slock,
+-                                        irqs);
++					usb_endp, address, mem_flags);
++		} else {
++			struct u132_endp *endp = urb->ep->hcpriv;
++			u16 urb_size = 8;
++			u8 *b = urb->setup_packet;
++			int i = 0;
++			char data[30 * 3 + 4];
++			char *d = data;
++			int m = (sizeof(data) - 1) / 3;
++			int l = 0;
++			data[0] = 0;
++			while (urb_size-- > 0) {
++				if (i > m) {
++				} else if (i++ < m) {
++					int w = sprintf(d, " %02X", *b++);
++					d += w;
++					l += w;
++				} else
++					d += sprintf(d, " ..");
++			}
++			if (endp) {
++				unsigned long irqs;
++				int retval;
++				spin_lock_irqsave(&endp->queue_lock.slock,
++					irqs);
+ 				retval = usb_hcd_link_urb_to_ep(hcd, urb);
+ 				if (retval == 0) {
+ 					retval = queue_control_on_old_endpoint(
+@@ -2395,267 +2380,267 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ 						usb_hcd_unlink_urb_from_ep(
+ 								hcd, urb);
+ 				}
+-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+-                                        irqs);
+-                                if (retval) {
+-                                        return retval;
+-                                } else {
+-                                        u132_endp_queue_work(u132, endp, 0);
+-                                        return 0;
+-                                }
+-                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+-                                return -EINVAL;
+-                        } else
+-                                return create_endpoint_and_queue_control(u132,
++				spin_unlock_irqrestore(&endp->queue_lock.slock,
++					irqs);
++				if (retval) {
++					return retval;
++				} else {
++					u132_endp_queue_work(u132, endp, 0);
++					return 0;
++				}
++			} else if (u132->num_endpoints == MAX_U132_ENDPS) {
++				return -EINVAL;
++			} else
++				return create_endpoint_and_queue_control(u132,
+ 					urb, usb_dev, usb_addr, usb_endp,
+-                                        mem_flags);
+-                }
+-        }
++					mem_flags);
++		}
++	}
+ }
+ 
+ static int dequeue_from_overflow_chain(struct u132 *u132,
+-        struct u132_endp *endp, struct urb *urb)
+-{
+-        struct list_head *scan;
+-        struct list_head *head = &endp->urb_more;
+-        list_for_each(scan, head) {
+-                struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
+-                        urb_more);
+-                if (urbq->urb == urb) {
+-                        struct usb_hcd *hcd = u132_to_hcd(u132);
+-                        list_del(scan);
+-                        endp->queue_size -= 1;
+-                        urb->error_count = 0;
++	struct u132_endp *endp, struct urb *urb)
++{
++	struct list_head *scan;
++	struct list_head *head = &endp->urb_more;
++	list_for_each(scan, head) {
++		struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
++			urb_more);
++		if (urbq->urb == urb) {
++			struct usb_hcd *hcd = u132_to_hcd(u132);
++			list_del(scan);
++			endp->queue_size -= 1;
++			urb->error_count = 0;
+ 			usb_hcd_giveback_urb(hcd, urb, 0);
+-                        return 0;
+-                } else
+-                        continue;
+-        }
+-        dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
+-                "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
+-                "\n", urb, endp->endp_number, endp, endp->ring->number,
+-                endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+-                endp->usb_endp, endp->usb_addr, endp->queue_size,
+-                endp->queue_next, endp->queue_last);
+-        return -EINVAL;
++			return 0;
++		} else
++			continue;
++	}
++	dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
++		"[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
++		"\n", urb, endp->endp_number, endp, endp->ring->number,
++		endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
++		endp->usb_endp, endp->usb_addr, endp->queue_size,
++		endp->queue_next, endp->queue_last);
++	return -EINVAL;
+ }
+ 
+ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+ 		struct urb *urb, int status)
+ {
+-        unsigned long irqs;
++	unsigned long irqs;
+ 	int rc;
+ 
+-        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++	spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ 	rc = usb_hcd_check_unlink_urb(u132_to_hcd(u132), urb, status);
+ 	if (rc) {
+ 		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+ 		return rc;
+ 	}
+-        if (endp->queue_size == 0) {
+-                dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
+-                        "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
+-                        endp->endp_number, endp, endp->ring->number,
+-                        endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+-                        endp->usb_endp, endp->usb_addr);
+-                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                return -EINVAL;
+-        }
+-        if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
+-                if (endp->active) {
+-                        endp->dequeueing = 1;
+-                        endp->edset_flush = 1;
+-                        u132_endp_queue_work(u132, endp, 0);
+-                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                        return 0;
+-                } else {
+-                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++	if (endp->queue_size == 0) {
++		dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
++			"=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
++			endp->endp_number, endp, endp->ring->number,
++			endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
++			endp->usb_endp, endp->usb_addr);
++		spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++		return -EINVAL;
++	}
++	if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
++		if (endp->active) {
++			endp->dequeueing = 1;
++			endp->edset_flush = 1;
++			u132_endp_queue_work(u132, endp, 0);
++			spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++			return 0;
++		} else {
++			spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+ 			u132_hcd_abandon_urb(u132, endp, urb, status);
+-                        return 0;
+-                }
+-        } else {
+-                u16 queue_list = 0;
+-                u16 queue_size = endp->queue_size;
+-                u16 queue_scan = endp->queue_next;
+-                struct urb **urb_slot = NULL;
+-                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+-                        if (urb == endp->urb_list[ENDP_QUEUE_MASK &
+-                                ++queue_scan]) {
+-                                urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+-                                        queue_scan];
+-                                break;
+-                        } else
+-                                continue;
+-                }
+-                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+-                        *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
+-                                ++queue_scan];
+-                        urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+-                                queue_scan];
+-                }
+-                if (urb_slot) {
+-                        struct usb_hcd *hcd = u132_to_hcd(u132);
++			return 0;
++		}
++	} else {
++		u16 queue_list = 0;
++		u16 queue_size = endp->queue_size;
++		u16 queue_scan = endp->queue_next;
++		struct urb **urb_slot = NULL;
++		while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
++			if (urb == endp->urb_list[ENDP_QUEUE_MASK &
++				++queue_scan]) {
++				urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
++					queue_scan];
++				break;
++			} else
++				continue;
++		}
++		while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
++			*urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
++				++queue_scan];
++			urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
++				queue_scan];
++		}
++		if (urb_slot) {
++			struct usb_hcd *hcd = u132_to_hcd(u132);
+ 
+ 			usb_hcd_unlink_urb_from_ep(hcd, urb);
+-                        endp->queue_size -= 1;
+-                        if (list_empty(&endp->urb_more)) {
+-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+-                                        irqs);
+-                        } else {
+-                                struct list_head *next = endp->urb_more.next;
+-                                struct u132_urbq *urbq = list_entry(next,
+-                                        struct u132_urbq, urb_more);
+-                                list_del(next);
+-                                *urb_slot = urbq->urb;
+-                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+-                                        irqs);
+-                                kfree(urbq);
+-                        } urb->error_count = 0;
++			endp->queue_size -= 1;
++			if (list_empty(&endp->urb_more)) {
++				spin_unlock_irqrestore(&endp->queue_lock.slock,
++					irqs);
++			} else {
++				struct list_head *next = endp->urb_more.next;
++				struct u132_urbq *urbq = list_entry(next,
++					struct u132_urbq, urb_more);
++				list_del(next);
++				*urb_slot = urbq->urb;
++				spin_unlock_irqrestore(&endp->queue_lock.slock,
++					irqs);
++				kfree(urbq);
++			} urb->error_count = 0;
+ 			usb_hcd_giveback_urb(hcd, urb, status);
+-                        return 0;
+-                } else if (list_empty(&endp->urb_more)) {
+-                        dev_err(&u132->platform_dev->dev, "urb=%p not found in "
+-                                "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
+-                                "=%d size=%d next=%04X last=%04X\n", urb,
+-                                endp->endp_number, endp, endp->ring->number,
+-                                endp->input ? 'I' : ' ',
+-                                endp->output ? 'O' : ' ', endp->usb_endp,
+-                                endp->usb_addr, endp->queue_size,
+-                                endp->queue_next, endp->queue_last);
+-                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                        return -EINVAL;
+-                } else {
++			return 0;
++		} else if (list_empty(&endp->urb_more)) {
++			dev_err(&u132->platform_dev->dev, "urb=%p not found in "
++				"endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
++				"=%d size=%d next=%04X last=%04X\n", urb,
++				endp->endp_number, endp, endp->ring->number,
++				endp->input ? 'I' : ' ',
++				endp->output ? 'O' : ' ', endp->usb_endp,
++				endp->usb_addr, endp->queue_size,
++				endp->queue_next, endp->queue_last);
++			spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++			return -EINVAL;
++		} else {
+ 			int retval;
+ 
+ 			usb_hcd_unlink_urb_from_ep(u132_to_hcd(u132), urb);
+ 			retval = dequeue_from_overflow_chain(u132, endp,
+-                                urb);
+-                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+-                        return retval;
+-                }
+-        }
++				urb);
++			spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++			return retval;
++		}
++	}
+ }
+ 
+ static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 2) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else {
+-                u8 usb_addr = usb_pipedevice(urb->pipe);
+-                u8 usb_endp = usb_pipeendpoint(urb->pipe);
+-                u8 address = u132->addr[usb_addr].address;
+-                struct u132_udev *udev = &u132->udev[address];
+-                if (usb_pipein(urb->pipe)) {
+-                        u8 endp_number = udev->endp_number_in[usb_endp];
+-                        struct u132_endp *endp = u132->endp[endp_number - 1];
+-                        return u132_endp_urb_dequeue(u132, endp, urb, status);
+-                } else {
+-                        u8 endp_number = udev->endp_number_out[usb_endp];
+-                        struct u132_endp *endp = u132->endp[endp_number - 1];
+-                        return u132_endp_urb_dequeue(u132, endp, urb, status);
+-                }
+-        }
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 2) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else {
++		u8 usb_addr = usb_pipedevice(urb->pipe);
++		u8 usb_endp = usb_pipeendpoint(urb->pipe);
++		u8 address = u132->addr[usb_addr].address;
++		struct u132_udev *udev = &u132->udev[address];
++		if (usb_pipein(urb->pipe)) {
++			u8 endp_number = udev->endp_number_in[usb_endp];
++			struct u132_endp *endp = u132->endp[endp_number - 1];
++			return u132_endp_urb_dequeue(u132, endp, urb, status);
++		} else {
++			u8 endp_number = udev->endp_number_out[usb_endp];
++			struct u132_endp *endp = u132->endp[endp_number - 1];
++			return u132_endp_urb_dequeue(u132, endp, urb, status);
++		}
++	}
+ }
+ 
+ static void u132_endpoint_disable(struct usb_hcd *hcd,
+-        struct usb_host_endpoint *hep)
+-{
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 2) {
+-                dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
+-                        ") has been removed %d\n", u132, hcd, hep,
+-                        u132->going);
+-        } else {
+-                struct u132_endp *endp = hep->hcpriv;
+-                if (endp)
+-                        u132_endp_put_kref(u132, endp);
+-        }
++	struct usb_host_endpoint *hep)
++{
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 2) {
++		dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
++			") has been removed %d\n", u132, hcd, hep,
++			u132->going);
++	} else {
++		struct u132_endp *endp = hep->hcpriv;
++		if (endp)
++			u132_endp_put_kref(u132, endp);
++	}
+ }
+ 
+ static int u132_get_frame(struct usb_hcd *hcd)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else {
+-                int frame = 0;
+-                dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
+-                msleep(100);
+-                return frame;
+-        }
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		return -ESHUTDOWN;
++	} else {
++		int frame = 0;
++		dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
++		msleep(100);
++		return frame;
++	}
+ }
+ 
+ static int u132_roothub_descriptor(struct u132 *u132,
+-        struct usb_hub_descriptor *desc)
+-{
+-        int retval;
+-        u16 temp;
+-        u32 rh_a = -1;
+-        u32 rh_b = -1;
+-        retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+-        if (retval)
+-                return retval;
+-        desc->bDescriptorType = 0x29;
+-        desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
+-        desc->bHubContrCurrent = 0;
+-        desc->bNbrPorts = u132->num_ports;
+-        temp = 1 + (u132->num_ports / 8);
+-        desc->bDescLength = 7 + 2 *temp;
+-        temp = 0;
+-        if (rh_a & RH_A_NPS)
+-                temp |= 0x0002;
+-        if (rh_a & RH_A_PSM)
+-                temp |= 0x0001;
+-        if (rh_a & RH_A_NOCP) {
+-                temp |= 0x0010;
+-        } else if (rh_a & RH_A_OCPM)
+-                temp |= 0x0008;
+-        desc->wHubCharacteristics = cpu_to_le16(temp);
+-        retval = u132_read_pcimem(u132, roothub.b, &rh_b);
+-        if (retval)
+-                return retval;
+-        memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
+-        desc->bitmap[0] = rh_b & RH_B_DR;
+-        if (u132->num_ports > 7) {
+-                desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
+-                desc->bitmap[2] = 0xff;
+-        } else
+-                desc->bitmap[1] = 0xff;
+-        return 0;
++	struct usb_hub_descriptor *desc)
++{
++	int retval;
++	u16 temp;
++	u32 rh_a = -1;
++	u32 rh_b = -1;
++	retval = u132_read_pcimem(u132, roothub.a, &rh_a);
++	if (retval)
++		return retval;
++	desc->bDescriptorType = 0x29;
++	desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
++	desc->bHubContrCurrent = 0;
++	desc->bNbrPorts = u132->num_ports;
++	temp = 1 + (u132->num_ports / 8);
++	desc->bDescLength = 7 + 2 * temp;
++	temp = 0;
++	if (rh_a & RH_A_NPS)
++		temp |= 0x0002;
++	if (rh_a & RH_A_PSM)
++		temp |= 0x0001;
++	if (rh_a & RH_A_NOCP)
++		temp |= 0x0010;
++	else if (rh_a & RH_A_OCPM)
++		temp |= 0x0008;
++	desc->wHubCharacteristics = cpu_to_le16(temp);
++	retval = u132_read_pcimem(u132, roothub.b, &rh_b);
++	if (retval)
++		return retval;
++	memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
++	desc->bitmap[0] = rh_b & RH_B_DR;
++	if (u132->num_ports > 7) {
++		desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
++		desc->bitmap[2] = 0xff;
++	} else
++		desc->bitmap[1] = 0xff;
++	return 0;
+ }
+ 
+ static int u132_roothub_status(struct u132 *u132, __le32 *desc)
+ {
+-        u32 rh_status = -1;
+-        int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
+-        *desc = cpu_to_le32(rh_status);
+-        return ret_status;
++	u32 rh_status = -1;
++	int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
++	*desc = cpu_to_le32(rh_status);
++	return ret_status;
+ }
+ 
+ static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
+ {
+-        if (wIndex == 0 || wIndex > u132->num_ports) {
+-                return -EINVAL;
+-        } else {
+-                int port = wIndex - 1;
+-                u32 rh_portstatus = -1;
+-                int ret_portstatus = u132_read_pcimem(u132,
+-                        roothub.portstatus[port], &rh_portstatus);
+-                *desc = cpu_to_le32(rh_portstatus);
+-                if (*(u16 *) (desc + 2)) {
+-                        dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
+-                                "ge = %08X\n", port, *desc);
+-                }
+-                return ret_portstatus;
+-        }
++	if (wIndex == 0 || wIndex > u132->num_ports) {
++		return -EINVAL;
++	} else {
++		int port = wIndex - 1;
++		u32 rh_portstatus = -1;
++		int ret_portstatus = u132_read_pcimem(u132,
++			roothub.portstatus[port], &rh_portstatus);
++		*desc = cpu_to_le32(rh_portstatus);
++		if (*(u16 *) (desc + 2)) {
++			dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
++				"ge = %08X\n", port, *desc);
++		}
++		return ret_portstatus;
++	}
+ }
+ 
+ 
+@@ -2666,381 +2651,340 @@ static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
+ #define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
+ static int u132_roothub_portreset(struct u132 *u132, int port_index)
+ {
+-        int retval;
+-        u32 fmnumber;
+-        u16 now;
+-        u16 reset_done;
+-        retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+-        if (retval)
+-                return retval;
+-        now = fmnumber;
+-        reset_done = now + PORT_RESET_MSEC;
+-        do {
+-                u32 portstat;
+-                do {
+-                        retval = u132_read_pcimem(u132,
+-                                roothub.portstatus[port_index], &portstat);
+-                        if (retval)
+-                                return retval;
+-                        if (RH_PS_PRS & portstat) {
+-                                continue;
+-                        } else
+-                                break;
+-                } while (tick_before(now, reset_done));
+-                if (RH_PS_PRS & portstat)
+-                        return -ENODEV;
+-                if (RH_PS_CCS & portstat) {
+-                        if (RH_PS_PRSC & portstat) {
+-                                retval = u132_write_pcimem(u132,
+-                                        roothub.portstatus[port_index],
+-                                        RH_PS_PRSC);
+-                                if (retval)
+-                                        return retval;
+-                        }
+-                } else
+-                        break;        /* start the next reset,
+-                                sleep till it's probably done */
+-                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+-                         RH_PS_PRS);
+-                if (retval)
+-                        return retval;
+-                msleep(PORT_RESET_HW_MSEC);
+-                retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+-                if (retval)
+-                        return retval;
+-                now = fmnumber;
+-        } while (tick_before(now, reset_done));
+-        return 0;
++	int retval;
++	u32 fmnumber;
++	u16 now;
++	u16 reset_done;
++	retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
++	if (retval)
++		return retval;
++	now = fmnumber;
++	reset_done = now + PORT_RESET_MSEC;
++	do {
++		u32 portstat;
++		do {
++			retval = u132_read_pcimem(u132,
++				roothub.portstatus[port_index], &portstat);
++			if (retval)
++				return retval;
++			if (RH_PS_PRS & portstat)
++				continue;
++			else
++				break;
++		} while (tick_before(now, reset_done));
++		if (RH_PS_PRS & portstat)
++			return -ENODEV;
++		if (RH_PS_CCS & portstat) {
++			if (RH_PS_PRSC & portstat) {
++				retval = u132_write_pcimem(u132,
++					roothub.portstatus[port_index],
++					RH_PS_PRSC);
++				if (retval)
++					return retval;
++			}
++		} else
++			break;	/* start the next reset,
++				sleep till it's probably done */
++		retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
++			 RH_PS_PRS);
++		if (retval)
++			return retval;
++		msleep(PORT_RESET_HW_MSEC);
++		retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
++		if (retval)
++			return retval;
++		now = fmnumber;
++	} while (tick_before(now, reset_done));
++	return 0;
+ }
+ 
+ static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
+-        u16 wIndex)
+-{
+-        if (wIndex == 0 || wIndex > u132->num_ports) {
+-                return -EINVAL;
+-        } else {
+-                int retval;
+-                int port_index = wIndex - 1;
+-                struct u132_port *port = &u132->port[port_index];
+-                port->Status &= ~(1 << wValue);
+-                switch (wValue) {
+-                case USB_PORT_FEAT_SUSPEND:
+-                        retval = u132_write_pcimem(u132,
+-                                roothub.portstatus[port_index], RH_PS_PSS);
+-                        if (retval)
+-                                return retval;
+-                        return 0;
+-                case USB_PORT_FEAT_POWER:
+-                        retval = u132_write_pcimem(u132,
+-                                roothub.portstatus[port_index], RH_PS_PPS);
+-                        if (retval)
+-                                return retval;
+-                        return 0;
+-                case USB_PORT_FEAT_RESET:
+-                        retval = u132_roothub_portreset(u132, port_index);
+-                        if (retval)
+-                                return retval;
+-                        return 0;
+-                default:
+-                        return -EPIPE;
+-                }
+-        }
++	u16 wIndex)
++{
++	if (wIndex == 0 || wIndex > u132->num_ports) {
++		return -EINVAL;
++	} else {
++		int retval;
++		int port_index = wIndex - 1;
++		struct u132_port *port = &u132->port[port_index];
++		port->Status &= ~(1 << wValue);
++		switch (wValue) {
++		case USB_PORT_FEAT_SUSPEND:
++			retval = u132_write_pcimem(u132,
++				roothub.portstatus[port_index], RH_PS_PSS);
++			if (retval)
++				return retval;
++			return 0;
++		case USB_PORT_FEAT_POWER:
++			retval = u132_write_pcimem(u132,
++				roothub.portstatus[port_index], RH_PS_PPS);
++			if (retval)
++				return retval;
++			return 0;
++		case USB_PORT_FEAT_RESET:
++			retval = u132_roothub_portreset(u132, port_index);
++			if (retval)
++				return retval;
++			return 0;
++		default:
++			return -EPIPE;
++		}
++	}
+ }
+ 
+ static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
+-        u16 wIndex)
+-{
+-        if (wIndex == 0 || wIndex > u132->num_ports) {
+-                return -EINVAL;
+-        } else {
+-                int port_index = wIndex - 1;
+-                u32 temp;
+-                int retval;
+-                struct u132_port *port = &u132->port[port_index];
+-                port->Status &= ~(1 << wValue);
+-                switch (wValue) {
+-                case USB_PORT_FEAT_ENABLE:
+-                        temp = RH_PS_CCS;
+-                        break;
+-                case USB_PORT_FEAT_C_ENABLE:
+-                        temp = RH_PS_PESC;
+-                        break;
+-                case USB_PORT_FEAT_SUSPEND:
+-                        temp = RH_PS_POCI;
+-                        if ((u132->hc_control & OHCI_CTRL_HCFS)
+-                                != OHCI_USB_OPER) {
+-                                dev_err(&u132->platform_dev->dev, "TODO resume_"
+-                                        "root_hub\n");
+-                        }
+-                        break;
+-                case USB_PORT_FEAT_C_SUSPEND:
+-                        temp = RH_PS_PSSC;
+-                        break;
+-                case USB_PORT_FEAT_POWER:
+-                        temp = RH_PS_LSDA;
+-                        break;
+-                case USB_PORT_FEAT_C_CONNECTION:
+-                        temp = RH_PS_CSC;
+-                        break;
+-                case USB_PORT_FEAT_C_OVER_CURRENT:
+-                        temp = RH_PS_OCIC;
+-                        break;
+-                case USB_PORT_FEAT_C_RESET:
+-                        temp = RH_PS_PRSC;
+-                        break;
+-                default:
+-                        return -EPIPE;
+-                }
+-                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+-                         temp);
+-                if (retval)
+-                        return retval;
+-                return 0;
+-        }
++	u16 wIndex)
++{
++	if (wIndex == 0 || wIndex > u132->num_ports) {
++		return -EINVAL;
++	} else {
++		int port_index = wIndex - 1;
++		u32 temp;
++		int retval;
++		struct u132_port *port = &u132->port[port_index];
++		port->Status &= ~(1 << wValue);
++		switch (wValue) {
++		case USB_PORT_FEAT_ENABLE:
++			temp = RH_PS_CCS;
++			break;
++		case USB_PORT_FEAT_C_ENABLE:
++			temp = RH_PS_PESC;
++			break;
++		case USB_PORT_FEAT_SUSPEND:
++			temp = RH_PS_POCI;
++			if ((u132->hc_control & OHCI_CTRL_HCFS)
++				!= OHCI_USB_OPER) {
++				dev_err(&u132->platform_dev->dev, "TODO resume_"
++					"root_hub\n");
++			}
++			break;
++		case USB_PORT_FEAT_C_SUSPEND:
++			temp = RH_PS_PSSC;
++			break;
++		case USB_PORT_FEAT_POWER:
++			temp = RH_PS_LSDA;
++			break;
++		case USB_PORT_FEAT_C_CONNECTION:
++			temp = RH_PS_CSC;
++			break;
++		case USB_PORT_FEAT_C_OVER_CURRENT:
++			temp = RH_PS_OCIC;
++			break;
++		case USB_PORT_FEAT_C_RESET:
++			temp = RH_PS_PRSC;
++			break;
++		default:
++			return -EPIPE;
++		}
++		retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
++			 temp);
++		if (retval)
++			return retval;
++		return 0;
++	}
+ }
+ 
+ 
+ /* the virtual root hub timer IRQ checks for hub status*/
+ static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
+-                        "ed %d\n", hcd, u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+-                        "ed\n", hcd);
+-                return -ESHUTDOWN;
+-        } else {
+-                int i, changed = 0, length = 1;
+-                if (u132->flags & OHCI_QUIRK_AMD756) {
+-                        if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
+-                                dev_err(&u132->platform_dev->dev, "bogus NDP, r"
+-                                        "ereads as NDP=%d\n",
+-                                        u132->hc_roothub_a & RH_A_NDP);
+-                                goto done;
+-                        }
+-                }
+-                if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) {
+-                        buf[0] = changed = 1;
+-                } else
+-                        buf[0] = 0;
+-                if (u132->num_ports > 7) {
+-                        buf[1] = 0;
+-                        length++;
+-                }
+-                for (i = 0; i < u132->num_ports; i++) {
+-                        if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
+-                                RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
+-                                RH_PS_PRSC)) {
+-                                changed = 1;
+-                                if (i < 7) {
+-                                        buf[0] |= 1 << (i + 1);
+-                                } else
+-                                        buf[1] |= 1 << (i - 7);
+-                                continue;
+-                        }
+-                        if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) {
+-                                continue;
+-                        }
+-                        if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) {
+-                                continue;
+-                        }
+-                }
+-              done:return changed ? length : 0;
+-        }
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
++			"ed %d\n", hcd, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
++			"ed\n", hcd);
++		return -ESHUTDOWN;
++	} else {
++		int i, changed = 0, length = 1;
++		if (u132->flags & OHCI_QUIRK_AMD756) {
++			if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
++				dev_err(&u132->platform_dev->dev, "bogus NDP, r"
++					"ereads as NDP=%d\n",
++					u132->hc_roothub_a & RH_A_NDP);
++				goto done;
++			}
++		}
++		if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC))
++			buf[0] = changed = 1;
++		else
++			buf[0] = 0;
++		if (u132->num_ports > 7) {
++			buf[1] = 0;
++			length++;
++		}
++		for (i = 0; i < u132->num_ports; i++) {
++			if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
++				RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
++				RH_PS_PRSC)) {
++				changed = 1;
++				if (i < 7)
++					buf[0] |= 1 << (i + 1);
++				else
++					buf[1] |= 1 << (i - 7);
++				continue;
++			}
++			if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS))
++				continue;
++
++			if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS))
++				continue;
++		}
++done:
++		return changed ? length : 0;
++	}
+ }
+ 
+ static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+-        u16 wIndex, char *buf, u16 wLength)
+-{
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else {
+-                int retval = 0;
+-                mutex_lock(&u132->sw_lock);
+-                switch (typeReq) {
+-                case ClearHubFeature:
+-                        switch (wValue) {
+-                        case C_HUB_OVER_CURRENT:
+-                        case C_HUB_LOCAL_POWER:
+-                                break;
+-                        default:
+-                                goto stall;
+-                        }
+-                        break;
+-                case SetHubFeature:
+-                        switch (wValue) {
+-                        case C_HUB_OVER_CURRENT:
+-                        case C_HUB_LOCAL_POWER:
+-                                break;
+-                        default:
+-                                goto stall;
+-                        }
+-                        break;
+-                case ClearPortFeature:{
+-                                retval = u132_roothub_clearportfeature(u132,
+-                                        wValue, wIndex);
+-                                if (retval)
+-                                        goto error;
+-                                break;
+-                        }
+-                case GetHubDescriptor:{
+-                                retval = u132_roothub_descriptor(u132,
+-                                        (struct usb_hub_descriptor *)buf);
+-                                if (retval)
+-                                        goto error;
+-                                break;
+-                        }
+-                case GetHubStatus:{
+-                                retval = u132_roothub_status(u132,
+-                                        (__le32 *) buf);
+-                                if (retval)
+-                                        goto error;
+-                                break;
+-                        }
+-                case GetPortStatus:{
+-                                retval = u132_roothub_portstatus(u132,
+-                                        (__le32 *) buf, wIndex);
+-                                if (retval)
+-                                        goto error;
+-                                break;
+-                        }
+-                case SetPortFeature:{
+-                                retval = u132_roothub_setportfeature(u132,
+-                                        wValue, wIndex);
+-                                if (retval)
+-                                        goto error;
+-                                break;
+-                        }
+-                default:
+-                        goto stall;
+-                      error:u132_disable(u132);
+-                        u132->going = 1;
+-                        break;
+-                      stall:retval = -EPIPE;
+-                        break;
+-                }
+-                mutex_unlock(&u132->sw_lock);
+-                return retval;
+-        }
++	u16 wIndex, char *buf, u16 wLength)
++{
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		return -ESHUTDOWN;
++	} else {
++		int retval = 0;
++		mutex_lock(&u132->sw_lock);
++		switch (typeReq) {
++		case ClearHubFeature:
++			switch (wValue) {
++			case C_HUB_OVER_CURRENT:
++			case C_HUB_LOCAL_POWER:
++				break;
++			default:
++				goto stall;
++			}
++			break;
++		case SetHubFeature:
++			switch (wValue) {
++			case C_HUB_OVER_CURRENT:
++			case C_HUB_LOCAL_POWER:
++				break;
++			default:
++				goto stall;
++			}
++			break;
++		case ClearPortFeature:{
++				retval = u132_roothub_clearportfeature(u132,
++					wValue, wIndex);
++				if (retval)
++					goto error;
++				break;
++			}
++		case GetHubDescriptor:{
++				retval = u132_roothub_descriptor(u132,
++					(struct usb_hub_descriptor *)buf);
++				if (retval)
++					goto error;
++				break;
++			}
++		case GetHubStatus:{
++				retval = u132_roothub_status(u132,
++					(__le32 *) buf);
++				if (retval)
++					goto error;
++				break;
++			}
++		case GetPortStatus:{
++				retval = u132_roothub_portstatus(u132,
++					(__le32 *) buf, wIndex);
++				if (retval)
++					goto error;
++				break;
++			}
++		case SetPortFeature:{
++				retval = u132_roothub_setportfeature(u132,
++					wValue, wIndex);
++				if (retval)
++					goto error;
++				break;
++			}
++		default:
++			goto stall;
++		error:
++			u132_disable(u132);
++			u132->going = 1;
++			break;
++		stall:
++			retval = -EPIPE;
++			break;
++		}
++		mutex_unlock(&u132->sw_lock);
++		return retval;
++	}
+ }
+ 
+ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else
+-                return 0;
+-}
+-
+-static void u132_hub_irq_enable(struct usb_hcd *hcd)
+-{
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-        } else if (u132->going > 0)
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		return -ESHUTDOWN;
++	} else
++		return 0;
+ }
+ 
+ 
+ #ifdef CONFIG_PM
+-static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
+-{
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else
+-                return 0;
+-}
+-
+-static int u132_hcd_resume(struct usb_hcd *hcd)
+-{
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else
+-                return 0;
+-}
+-
+ static int u132_bus_suspend(struct usb_hcd *hcd)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else
+-                return 0;
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		return -ESHUTDOWN;
++	} else
++		return 0;
+ }
+ 
+ static int u132_bus_resume(struct usb_hcd *hcd)
+ {
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else
+-                return 0;
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		return -ESHUTDOWN;
++	} else
++		return 0;
+ }
+ 
+ #else
+-#define u132_hcd_suspend NULL
+-#define u132_hcd_resume NULL
+ #define u132_bus_suspend NULL
+ #define u132_bus_resume NULL
+ #endif
+ static struct hc_driver u132_hc_driver = {
+-        .description = hcd_name,
+-        .hcd_priv_size = sizeof(struct u132),
+-        .irq = NULL,
+-        .flags = HCD_USB11 | HCD_MEMORY,
+-        .reset = u132_hcd_reset,
+-        .start = u132_hcd_start,
+-        .suspend = u132_hcd_suspend,
+-        .resume = u132_hcd_resume,
+-        .stop = u132_hcd_stop,
+-        .urb_enqueue = u132_urb_enqueue,
+-        .urb_dequeue = u132_urb_dequeue,
+-        .endpoint_disable = u132_endpoint_disable,
+-        .get_frame_number = u132_get_frame,
+-        .hub_status_data = u132_hub_status_data,
+-        .hub_control = u132_hub_control,
+-        .bus_suspend = u132_bus_suspend,
+-        .bus_resume = u132_bus_resume,
+-        .start_port_reset = u132_start_port_reset,
+-        .hub_irq_enable = u132_hub_irq_enable,
++	.description = hcd_name,
++	.hcd_priv_size = sizeof(struct u132),
++	.irq = NULL,
++	.flags = HCD_USB11 | HCD_MEMORY,
++	.reset = u132_hcd_reset,
++	.start = u132_hcd_start,
++	.stop = u132_hcd_stop,
++	.urb_enqueue = u132_urb_enqueue,
++	.urb_dequeue = u132_urb_dequeue,
++	.endpoint_disable = u132_endpoint_disable,
++	.get_frame_number = u132_get_frame,
++	.hub_status_data = u132_hub_status_data,
++	.hub_control = u132_hub_control,
++	.bus_suspend = u132_bus_suspend,
++	.bus_resume = u132_bus_resume,
++	.start_port_reset = u132_start_port_reset,
+ };
+ 
+ /*
+@@ -3051,148 +2995,152 @@ static struct hc_driver u132_hc_driver = {
+ */
+ static int __devexit u132_remove(struct platform_device *pdev)
+ {
+-        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+-        if (hcd) {
+-                struct u132 *u132 = hcd_to_u132(hcd);
+-                if (u132->going++ > 1) {
+-                        dev_err(&u132->platform_dev->dev, "already being remove"
++	struct usb_hcd *hcd = platform_get_drvdata(pdev);
++	if (hcd) {
++		struct u132 *u132 = hcd_to_u132(hcd);
++		if (u132->going++ > 1) {
++			dev_err(&u132->platform_dev->dev, "already being remove"
+ 				"d\n");
+-                        return -ENODEV;
+-                } else {
+-                        int rings = MAX_U132_RINGS;
+-                        int endps = MAX_U132_ENDPS;
+-                        dev_err(&u132->platform_dev->dev, "removing device u132"
++			return -ENODEV;
++		} else {
++			int rings = MAX_U132_RINGS;
++			int endps = MAX_U132_ENDPS;
++			dev_err(&u132->platform_dev->dev, "removing device u132"
+ 				".%d\n", u132->sequence_num);
+-                        msleep(100);
+-                        mutex_lock(&u132->sw_lock);
+-                        u132_monitor_cancel_work(u132);
+-                        while (rings-- > 0) {
+-                                struct u132_ring *ring = &u132->ring[rings];
+-                                u132_ring_cancel_work(u132, ring);
+-                        } while (endps-- > 0) {
+-                                struct u132_endp *endp = u132->endp[endps];
+-                                if (endp)
+-                                        u132_endp_cancel_work(u132, endp);
+-                        }
+-                        u132->going += 1;
+-                        printk(KERN_INFO "removing device u132.%d\n",
+-                                u132->sequence_num);
+-                        mutex_unlock(&u132->sw_lock);
+-                        usb_remove_hcd(hcd);
+-                        u132_u132_put_kref(u132);
+-                        return 0;
+-                }
+-        } else
+-                return 0;
++			msleep(100);
++			mutex_lock(&u132->sw_lock);
++			u132_monitor_cancel_work(u132);
++			while (rings-- > 0) {
++				struct u132_ring *ring = &u132->ring[rings];
++				u132_ring_cancel_work(u132, ring);
++			} while (endps-- > 0) {
++				struct u132_endp *endp = u132->endp[endps];
++				if (endp)
++					u132_endp_cancel_work(u132, endp);
++			}
++			u132->going += 1;
++			printk(KERN_INFO "removing device u132.%d\n",
++				u132->sequence_num);
++			mutex_unlock(&u132->sw_lock);
++			usb_remove_hcd(hcd);
++			u132_u132_put_kref(u132);
++			return 0;
++		}
++	} else
++		return 0;
+ }
+ 
+ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
+ {
+-        int rings = MAX_U132_RINGS;
+-        int ports = MAX_U132_PORTS;
+-        int addrs = MAX_U132_ADDRS;
+-        int udevs = MAX_U132_UDEVS;
+-        int endps = MAX_U132_ENDPS;
+-        u132->board = pdev->dev.platform_data;
+-        u132->platform_dev = pdev;
+-        u132->power = 0;
+-        u132->reset = 0;
+-        mutex_init(&u132->sw_lock);
+-        init_MUTEX(&u132->scheduler_lock);
+-        while (rings-- > 0) {
+-                struct u132_ring *ring = &u132->ring[rings];
+-                ring->u132 = u132;
+-                ring->number = rings + 1;
+-                ring->length = 0;
+-                ring->curr_endp = NULL;
+-                INIT_DELAYED_WORK(&ring->scheduler,
++	int rings = MAX_U132_RINGS;
++	int ports = MAX_U132_PORTS;
++	int addrs = MAX_U132_ADDRS;
++	int udevs = MAX_U132_UDEVS;
++	int endps = MAX_U132_ENDPS;
++	u132->board = pdev->dev.platform_data;
++	u132->platform_dev = pdev;
++	u132->power = 0;
++	u132->reset = 0;
++	mutex_init(&u132->sw_lock);
++	mutex_init(&u132->scheduler_lock);
++	while (rings-- > 0) {
++		struct u132_ring *ring = &u132->ring[rings];
++		ring->u132 = u132;
++		ring->number = rings + 1;
++		ring->length = 0;
++		ring->curr_endp = NULL;
++		INIT_DELAYED_WORK(&ring->scheduler,
+ 				  u132_hcd_ring_work_scheduler);
+-        } mutex_lock(&u132->sw_lock);
+-        INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
+-        while (ports-- > 0) {
+-                struct u132_port *port = &u132->port[ports];
+-                port->u132 = u132;
+-                port->reset = 0;
+-                port->enable = 0;
+-                port->power = 0;
+-                port->Status = 0;
+-        } while (addrs-- > 0) {
+-                struct u132_addr *addr = &u132->addr[addrs];
+-                addr->address = 0;
+-        } while (udevs-- > 0) {
+-                struct u132_udev *udev = &u132->udev[udevs];
+-                int i = ARRAY_SIZE(udev->endp_number_in);
+-                int o = ARRAY_SIZE(udev->endp_number_out);
+-                udev->usb_device = NULL;
+-                udev->udev_number = 0;
+-                udev->usb_addr = 0;
+-                udev->portnumber = 0;
+-                while (i-- > 0) {
+-                        udev->endp_number_in[i] = 0;
+-                }
+-                while (o-- > 0) {
+-                        udev->endp_number_out[o] = 0;
+-                }
+-        }
+-        while (endps-- > 0) {
+-                u132->endp[endps] = NULL;
+-        }
+-        mutex_unlock(&u132->sw_lock);
+-        return;
++	}
++	mutex_lock(&u132->sw_lock);
++	INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
++	while (ports-- > 0) {
++		struct u132_port *port = &u132->port[ports];
++		port->u132 = u132;
++		port->reset = 0;
++		port->enable = 0;
++		port->power = 0;
++		port->Status = 0;
++	}
++	while (addrs-- > 0) {
++		struct u132_addr *addr = &u132->addr[addrs];
++		addr->address = 0;
++	}
++	while (udevs-- > 0) {
++		struct u132_udev *udev = &u132->udev[udevs];
++		int i = ARRAY_SIZE(udev->endp_number_in);
++		int o = ARRAY_SIZE(udev->endp_number_out);
++		udev->usb_device = NULL;
++		udev->udev_number = 0;
++		udev->usb_addr = 0;
++		udev->portnumber = 0;
++		while (i-- > 0)
++			udev->endp_number_in[i] = 0;
++
++		while (o-- > 0)
++			udev->endp_number_out[o] = 0;
++
++	}
++	while (endps-- > 0)
++		u132->endp[endps] = NULL;
++
++	mutex_unlock(&u132->sw_lock);
++	return;
+ }
+ 
+ static int __devinit u132_probe(struct platform_device *pdev)
+ {
+-        struct usb_hcd *hcd;
+-        int retval;
+-        u32 control;
+-        u32 rh_a = -1;
+-        u32 num_ports;
+-        msleep(100);
+-        if (u132_exiting > 0) {
+-                return -ENODEV;
+-        }
+-        retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
+-        if (retval)
+-                return retval;
+-        retval = ftdi_read_pcimem(pdev, control, &control);
+-        if (retval)
+-                return retval;
+-        retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
+-        if (retval)
+-                return retval;
+-        num_ports = rh_a & RH_A_NDP;        /* refuse to confuse usbcore */
+-        if (pdev->dev.dma_mask) {
+-                return -EINVAL;
+-        }
+-        hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
+-        if (!hcd) {
+-                printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
+-                        );
+-                ftdi_elan_gone_away(pdev);
+-                return -ENOMEM;
+-        } else {
+-                int retval = 0;
+-                struct u132 *u132 = hcd_to_u132(hcd);
+-                hcd->rsrc_start = 0;
+-                mutex_lock(&u132_module_lock);
+-                list_add_tail(&u132->u132_list, &u132_static_list);
+-                u132->sequence_num = ++u132_instances;
+-                mutex_unlock(&u132_module_lock);
+-                u132_u132_init_kref(u132);
+-                u132_initialise(u132, pdev);
+-                hcd->product_desc = "ELAN U132 Host Controller";
+-                retval = usb_add_hcd(hcd, 0, 0);
+-                if (retval != 0) {
+-                        dev_err(&u132->platform_dev->dev, "init error %d\n",
+-                                retval);
+-                        u132_u132_put_kref(u132);
+-                        return retval;
+-                } else {
+-                        u132_monitor_queue_work(u132, 100);
+-                        return 0;
+-                }
+-        }
++	struct usb_hcd *hcd;
++	int retval;
++	u32 control;
++	u32 rh_a = -1;
++	u32 num_ports;
++
++	msleep(100);
++	if (u132_exiting > 0)
++		return -ENODEV;
++
++	retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
++	if (retval)
++		return retval;
++	retval = ftdi_read_pcimem(pdev, control, &control);
++	if (retval)
++		return retval;
++	retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
++	if (retval)
++		return retval;
++	num_ports = rh_a & RH_A_NDP;	/* refuse to confuse usbcore */
++	if (pdev->dev.dma_mask)
++		return -EINVAL;
++
++	hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
++	if (!hcd) {
++		printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
++			);
++		ftdi_elan_gone_away(pdev);
++		return -ENOMEM;
++	} else {
++		int retval = 0;
++		struct u132 *u132 = hcd_to_u132(hcd);
++		hcd->rsrc_start = 0;
++		mutex_lock(&u132_module_lock);
++		list_add_tail(&u132->u132_list, &u132_static_list);
++		u132->sequence_num = ++u132_instances;
++		mutex_unlock(&u132_module_lock);
++		u132_u132_init_kref(u132);
++		u132_initialise(u132, pdev);
++		hcd->product_desc = "ELAN U132 Host Controller";
++		retval = usb_add_hcd(hcd, 0, 0);
++		if (retval != 0) {
++			dev_err(&u132->platform_dev->dev, "init error %d\n",
++				retval);
++			u132_u132_put_kref(u132);
++			return retval;
++		} else {
++			u132_monitor_queue_work(u132, 100);
++			return 0;
++		}
++	}
+ }
+ 
+ 
+@@ -3203,61 +3151,58 @@ static int __devinit u132_probe(struct platform_device *pdev)
+ */
+ static int u132_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+-        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else {
++	struct usb_hcd *hcd = platform_get_drvdata(pdev);
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		return -ESHUTDOWN;
++	} else {
+ 		int retval = 0, ports;
+ 
+ 		switch (state.event) {
+ 		case PM_EVENT_FREEZE:
+-                        retval = u132_bus_suspend(hcd);
++			retval = u132_bus_suspend(hcd);
+ 			break;
+ 		case PM_EVENT_SUSPEND:
+ 		case PM_EVENT_HIBERNATE:
+ 			ports = MAX_U132_PORTS;
+-                        while (ports-- > 0) {
+-                                port_power(u132, ports, 0);
+-                        }
++			while (ports-- > 0) {
++				port_power(u132, ports, 0);
++			}
+ 			break;
+ 		}
+-                if (retval == 0)
+-                        pdev->dev.power.power_state = state;
+-                return retval;
+-        }
++		return retval;
++	}
+ }
+ 
+ static int u132_resume(struct platform_device *pdev)
+ {
+-        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+-        struct u132 *u132 = hcd_to_u132(hcd);
+-        if (u132->going > 1) {
+-                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+-                        , u132->going);
+-                return -ENODEV;
+-        } else if (u132->going > 0) {
+-                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+-                return -ESHUTDOWN;
+-        } else {
+-                int retval = 0;
+-                if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+-                        int ports = MAX_U132_PORTS;
+-                        while (ports-- > 0) {
+-                                port_power(u132, ports, 1);
+-                        }
+-                        retval = 0;
+-                } else {
+-                        pdev->dev.power.power_state = PMSG_ON;
+-                        retval = u132_bus_resume(hcd);
+-                }
+-                return retval;
+-        }
++	struct usb_hcd *hcd = platform_get_drvdata(pdev);
++	struct u132 *u132 = hcd_to_u132(hcd);
++	if (u132->going > 1) {
++		dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++			, u132->going);
++		return -ENODEV;
++	} else if (u132->going > 0) {
++		dev_err(&u132->platform_dev->dev, "device is being removed\n");
++		return -ESHUTDOWN;
++	} else {
++		int retval = 0;
++		if (!u132->port[0].power) {
++			int ports = MAX_U132_PORTS;
++			while (ports-- > 0) {
++				port_power(u132, ports, 1);
++			}
++			retval = 0;
++		} else {
++			retval = u132_bus_resume(hcd);
++		}
++		return retval;
++	}
+ }
+ 
+ #else
+@@ -3270,47 +3215,48 @@ static int u132_resume(struct platform_device *pdev)
+ * the platform_driver struct is static because it is per type of module
+ */
+ static struct platform_driver u132_platform_driver = {
+-        .probe = u132_probe,
+-        .remove = __devexit_p(u132_remove),
+-        .suspend = u132_suspend,
+-        .resume = u132_resume,
+-        .driver = {
+-                   .name = (char *)hcd_name,
+-                   .owner = THIS_MODULE,
+-                   },
++	.probe = u132_probe,
++	.remove = __devexit_p(u132_remove),
++	.suspend = u132_suspend,
++	.resume = u132_resume,
++	.driver = {
++		   .name = (char *)hcd_name,
++		   .owner = THIS_MODULE,
++		   },
+ };
+ static int __init u132_hcd_init(void)
+ {
+-        int retval;
+-        INIT_LIST_HEAD(&u132_static_list);
+-        u132_instances = 0;
+-        u132_exiting = 0;
+-        mutex_init(&u132_module_lock);
+-        if (usb_disabled())
+-                return -ENODEV;
+-        printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
+-                __DATE__);
+-        workqueue = create_singlethread_workqueue("u132");
+-        retval = platform_driver_register(&u132_platform_driver);
+-        return retval;
++	int retval;
++	INIT_LIST_HEAD(&u132_static_list);
++	u132_instances = 0;
++	u132_exiting = 0;
++	mutex_init(&u132_module_lock);
++	if (usb_disabled())
++		return -ENODEV;
++	printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
++		__DATE__);
++	workqueue = create_singlethread_workqueue("u132");
++	retval = platform_driver_register(&u132_platform_driver);
++	return retval;
+ }
+ 
+ 
+ module_init(u132_hcd_init);
+ static void __exit u132_hcd_exit(void)
+ {
+-        struct u132 *u132;
+-        struct u132 *temp;
+-        mutex_lock(&u132_module_lock);
+-        u132_exiting += 1;
+-        mutex_unlock(&u132_module_lock);
+-        list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
+-                platform_device_unregister(u132->platform_dev);
+-        } platform_driver_unregister(&u132_platform_driver);
+-        printk(KERN_INFO "u132-hcd driver deregistered\n");
+-        wait_event(u132_hcd_wait, u132_instances == 0);
+-        flush_workqueue(workqueue);
+-        destroy_workqueue(workqueue);
++	struct u132 *u132;
++	struct u132 *temp;
++	mutex_lock(&u132_module_lock);
++	u132_exiting += 1;
++	mutex_unlock(&u132_module_lock);
++	list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
++		platform_device_unregister(u132->platform_dev);
++	}
++	platform_driver_unregister(&u132_platform_driver);
++	printk(KERN_INFO "u132-hcd driver deregistered\n");
++	wait_event(u132_hcd_wait, u132_instances == 0);
++	flush_workqueue(workqueue);
++	destroy_workqueue(workqueue);
+ }
+ 
+ 
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index ec98789..d3e0d8a 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -262,20 +262,12 @@ __acquires(uhci->lock)
+ {
+ 	int auto_stop;
+ 	int int_enable, egsm_enable;
++	struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
+ 
+ 	auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
+-	dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
+-			"%s%s\n", __FUNCTION__,
++	dev_dbg(&rhdev->dev, "%s%s\n", __func__,
+ 			(auto_stop ? " (auto-stop)" : ""));
+ 
+-	/* If we get a suspend request when we're already auto-stopped
+-	 * then there's nothing to do.
+-	 */
+-	if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) {
+-		uhci->rh_state = new_state;
+-		return;
+-	}
+-
+ 	/* Enable resume-detect interrupts if they work.
+ 	 * Then enter Global Suspend mode if _it_ works, still configured.
+ 	 */
+@@ -285,8 +277,10 @@ __acquires(uhci->lock)
+ 	if (remote_wakeup_is_broken(uhci))
+ 		egsm_enable = 0;
+ 	if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
+-			!device_may_wakeup(
+-				&uhci_to_hcd(uhci)->self.root_hub->dev))
++#ifdef CONFIG_PM
++			(!auto_stop && !rhdev->do_remote_wakeup) ||
++#endif
++			(auto_stop && !device_may_wakeup(&rhdev->dev)))
+ 		uhci->working_RD = int_enable = 0;
+ 
+ 	outw(int_enable, uhci->io_addr + USBINTR);
+@@ -308,8 +302,7 @@ __acquires(uhci->lock)
+ 			return;
+ 	}
+ 	if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
+-		dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev,
+-			"Controller not stopped yet!\n");
++		dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
+ 
+ 	uhci_get_current_frame_number(uhci);
+ 
+@@ -342,7 +335,7 @@ __releases(uhci->lock)
+ __acquires(uhci->lock)
+ {
+ 	dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
+-			"%s%s\n", __FUNCTION__,
++			"%s%s\n", __func__,
+ 			uhci->rh_state == UHCI_RH_AUTO_STOPPED ?
+ 				" (auto-start)" : "");
+ 
+@@ -737,12 +730,12 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ 	return rc;
+ }
+ 
+-static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
++static int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 	int rc = 0;
+ 
+-	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
++	dev_dbg(uhci_dev(uhci), "%s\n", __func__);
+ 
+ 	spin_lock_irq(&uhci->lock);
+ 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
+@@ -774,11 +767,11 @@ done:
+ 	return rc;
+ }
+ 
+-static int uhci_resume(struct usb_hcd *hcd)
++static int uhci_pci_resume(struct usb_hcd *hcd)
+ {
+ 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ 
+-	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
++	dev_dbg(uhci_dev(uhci), "%s\n", __func__);
+ 
+ 	/* Since we aren't in D3 any more, it's safe to set this flag
+ 	 * even if the controller was dead.
+@@ -872,8 +865,8 @@ static const struct hc_driver uhci_driver = {
+ 	.reset =		uhci_init,
+ 	.start =		uhci_start,
+ #ifdef CONFIG_PM
+-	.suspend =		uhci_suspend,
+-	.resume =		uhci_resume,
++	.pci_suspend =		uhci_pci_suspend,
++	.pci_resume =		uhci_pci_resume,
+ 	.bus_suspend =		uhci_rh_suspend,
+ 	.bus_resume =		uhci_rh_resume,
+ #endif
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 60379b1..db64593 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1171,7 +1171,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ 				/* Some debugging code */
+ 				dev_dbg(&urb->dev->dev,
+ 						"%s: failed with status %x\n",
+-						__FUNCTION__, status);
++						__func__, status);
+ 
+ 				if (debug > 1 && errbuf) {
+ 					/* Print the chain for debugging */
+diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
+index 7595dfb..33350f9 100644
+--- a/drivers/usb/image/Kconfig
++++ b/drivers/usb/image/Kconfig
+@@ -5,8 +5,8 @@ comment "USB Imaging devices"
+ 	depends on USB
+ 
+ config USB_MDC800
+-	tristate "USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)"
+-	depends on USB && EXPERIMENTAL
++	tristate "USB Mustek MDC800 Digital Camera support"
++	depends on USB
+ 	---help---
+ 	  Say Y here if you want to connect this type of still camera to
+ 	  your computer's USB port. This driver can be used with gphoto 0.4.3
+diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
+index bc207e3..885867a 100644
+--- a/drivers/usb/image/microtek.c
++++ b/drivers/usb/image/microtek.c
+@@ -185,7 +185,7 @@ static struct usb_driver mts_usb_driver = {
+ 	printk( KERN_DEBUG MTS_NAME x )
+ 
+ #define MTS_DEBUG_GOT_HERE() \
+-	MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ )
++	MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __func__ )
+ #define MTS_DEBUG_INT() \
+ 	do { MTS_DEBUG_GOT_HERE(); \
+ 	     MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \
+@@ -794,7 +794,6 @@ static int mts_usb_probe(struct usb_interface *intf,
+ 
+ 	new_desc->usb_dev = dev;
+ 	new_desc->usb_intf = intf;
+-	init_MUTEX(&new_desc->lock);
+ 
+ 	/* endpoints */
+ 	new_desc->ep_out = ep_out;
+diff --git a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h
+index d5d62a9..ccce318 100644
+--- a/drivers/usb/image/microtek.h
++++ b/drivers/usb/image/microtek.h
+@@ -39,7 +39,6 @@ struct mts_desc {
+ 	u8 ep_image;
+ 
+ 	struct Scsi_Host * host;
+-	struct semaphore lock;
+ 
+ 	struct urb *urb;
+ 	struct mts_transfer_context context;
+diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
+index 9c7eb61..a53db1d 100644
+--- a/drivers/usb/misc/Kconfig
++++ b/drivers/usb/misc/Kconfig
+@@ -33,8 +33,8 @@ config USB_EMI26
+ 	  module will be called emi26.
+ 
+ config USB_ADUTUX
+-	tristate "ADU devices from Ontrak Control Systems (EXPERIMENTAL)"
+-	depends on USB && EXPERIMENTAL
++	tristate "ADU devices from Ontrak Control Systems"
++	depends on USB
+ 	help
+ 	  Say Y if you want to use an ADU device from Ontrak Control
+ 	  Systems.
+@@ -43,8 +43,8 @@ config USB_ADUTUX
+ 	  will be called adutux.
+ 
+ config USB_AUERSWALD
+-	tristate "USB Auerswald ISDN support (EXPERIMENTAL)"
+-	depends on USB && EXPERIMENTAL
++	tristate "USB Auerswald ISDN support"
++	depends on USB
+ 	help
+ 	  Say Y here if you want to connect an Auerswald USB ISDN Device
+ 	  to your computer's USB port.
+@@ -53,8 +53,8 @@ config USB_AUERSWALD
+ 	  module will be called auerswald.
+ 
+ config USB_RIO500
+-	tristate "USB Diamond Rio500 support (EXPERIMENTAL)"
+-	depends on USB && EXPERIMENTAL
++	tristate "USB Diamond Rio500 support"
++	depends on USB
+ 	help
+ 	  Say Y here if you want to connect a USB Rio500 mp3 player to your
+ 	  computer's USB port. Please read <file:Documentation/usb/rio.txt>
+@@ -64,8 +64,8 @@ config USB_RIO500
+ 	  module will be called rio500.
+ 
+ config USB_LEGOTOWER
+-	tristate "USB Lego Infrared Tower support (EXPERIMENTAL)"
+-	depends on USB && EXPERIMENTAL
++	tristate "USB Lego Infrared Tower support"
++	depends on USB
+ 	help
+ 	  Say Y here if you want to connect a USB Lego Infrared Tower to your
+ 	  computer's USB port.
+@@ -259,8 +259,8 @@ config USB_IOWARRIOR
+ 	  module will be called iowarrior.
+ 
+ config USB_TEST
+-	tristate "USB testing driver (DEVELOPMENT)"
+-	depends on USB && USB_DEVICEFS && EXPERIMENTAL
++	tristate "USB testing driver"
++	depends on USB && USB_DEVICEFS
+ 	help
+ 	  This driver is for testing host controller software.  It is used
+ 	  with specialized device firmware for regression and stress testing,
+diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
+index 5a2c44e..965f6ea 100644
+--- a/drivers/usb/misc/adutux.c
++++ b/drivers/usb/misc/adutux.c
+@@ -147,10 +147,10 @@ static void adu_abort_transfers(struct adu_device *dev)
+ {
+ 	unsigned long flags;
+ 
+-	dbg(2," %s : enter", __FUNCTION__);
++	dbg(2," %s : enter", __func__);
+ 
+ 	if (dev->udev == NULL) {
+-		dbg(1," %s : udev is null", __FUNCTION__);
++		dbg(1," %s : udev is null", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -172,12 +172,12 @@ static void adu_abort_transfers(struct adu_device *dev)
+ 		spin_unlock_irqrestore(&dev->buflock, flags);
+ 
+ exit:
+-	dbg(2," %s : leave", __FUNCTION__);
++	dbg(2," %s : leave", __func__);
+ }
+ 
+ static void adu_delete(struct adu_device *dev)
+ {
+-	dbg(2, "%s enter", __FUNCTION__);
++	dbg(2, "%s enter", __func__);
+ 
+ 	/* free data structures */
+ 	usb_free_urb(dev->interrupt_in_urb);
+@@ -188,7 +188,7 @@ static void adu_delete(struct adu_device *dev)
+ 	kfree(dev->interrupt_out_buffer);
+ 	kfree(dev);
+ 
+-	dbg(2, "%s : leave", __FUNCTION__);
++	dbg(2, "%s : leave", __func__);
+ }
+ 
+ static void adu_interrupt_in_callback(struct urb *urb)
+@@ -196,8 +196,8 @@ static void adu_interrupt_in_callback(struct urb *urb)
+ 	struct adu_device *dev = urb->context;
+ 	int status = urb->status;
+ 
+-	dbg(4," %s : enter, status %d", __FUNCTION__, status);
+-	adu_debug_data(5, __FUNCTION__, urb->actual_length,
++	dbg(4," %s : enter, status %d", __func__, status);
++	adu_debug_data(5, __func__, urb->actual_length,
+ 		       urb->transfer_buffer);
+ 
+ 	spin_lock(&dev->buflock);
+@@ -206,7 +206,7 @@ static void adu_interrupt_in_callback(struct urb *urb)
+ 		if ((status != -ENOENT) && (status != -ECONNRESET) &&
+ 			(status != -ESHUTDOWN)) {
+ 			dbg(1," %s : nonzero status received: %d",
+-			    __FUNCTION__, status);
++			    __func__, status);
+ 		}
+ 		goto exit;
+ 	}
+@@ -220,10 +220,10 @@ static void adu_interrupt_in_callback(struct urb *urb)
+ 				dev->interrupt_in_buffer, urb->actual_length);
+ 
+ 			dev->read_buffer_length += urb->actual_length;
+-			dbg(2," %s reading  %d ", __FUNCTION__,
++			dbg(2," %s reading  %d ", __func__,
+ 			    urb->actual_length);
+ 		} else {
+-			dbg(1," %s : read_buffer overflow", __FUNCTION__);
++			dbg(1," %s : read_buffer overflow", __func__);
+ 		}
+ 	}
+ 
+@@ -232,9 +232,9 @@ exit:
+ 	spin_unlock(&dev->buflock);
+ 	/* always wake up so we recover from errors */
+ 	wake_up_interruptible(&dev->read_wait);
+-	adu_debug_data(5, __FUNCTION__, urb->actual_length,
++	adu_debug_data(5, __func__, urb->actual_length,
+ 		       urb->transfer_buffer);
+-	dbg(4," %s : leave, status %d", __FUNCTION__, status);
++	dbg(4," %s : leave, status %d", __func__, status);
+ }
+ 
+ static void adu_interrupt_out_callback(struct urb *urb)
+@@ -242,14 +242,14 @@ static void adu_interrupt_out_callback(struct urb *urb)
+ 	struct adu_device *dev = urb->context;
+ 	int status = urb->status;
+ 
+-	dbg(4," %s : enter, status %d", __FUNCTION__, status);
+-	adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer);
++	dbg(4," %s : enter, status %d", __func__, status);
++	adu_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer);
+ 
+ 	if (status != 0) {
+ 		if ((status != -ENOENT) &&
+ 		    (status != -ECONNRESET)) {
+ 			dbg(1, " %s :nonzero status received: %d",
+-			    __FUNCTION__, status);
++			    __func__, status);
+ 		}
+ 		goto exit;
+ 	}
+@@ -260,9 +260,9 @@ static void adu_interrupt_out_callback(struct urb *urb)
+ 	spin_unlock(&dev->buflock);
+ exit:
+ 
+-	adu_debug_data(5, __FUNCTION__, urb->actual_length,
++	adu_debug_data(5, __func__, urb->actual_length,
+ 		       urb->transfer_buffer);
+-	dbg(4," %s : leave, status %d", __FUNCTION__, status);
++	dbg(4," %s : leave, status %d", __func__, status);
+ }
+ 
+ static int adu_open(struct inode *inode, struct file *file)
+@@ -272,19 +272,19 @@ static int adu_open(struct inode *inode, struct file *file)
+ 	int subminor;
+ 	int retval;
+ 
+-	dbg(2,"%s : enter", __FUNCTION__);
++	dbg(2,"%s : enter", __func__);
+ 
+ 	subminor = iminor(inode);
+ 
+ 	if ((retval = mutex_lock_interruptible(&adutux_mutex))) {
+-		dbg(2, "%s : mutex lock failed", __FUNCTION__);
++		dbg(2, "%s : mutex lock failed", __func__);
+ 		goto exit_no_lock;
+ 	}
+ 
+ 	interface = usb_find_interface(&adu_driver, subminor);
+ 	if (!interface) {
+ 		err("%s - error, can't find device for minor %d",
+-		    __FUNCTION__, subminor);
++		    __func__, subminor);
+ 		retval = -ENODEV;
+ 		goto exit_no_device;
+ 	}
+@@ -302,7 +302,7 @@ static int adu_open(struct inode *inode, struct file *file)
+ 	}
+ 
+ 	++dev->open_count;
+-	dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
++	dbg(2,"%s : open count %d", __func__, dev->open_count);
+ 
+ 	/* save device in the file's private structure */
+ 	file->private_data = dev;
+@@ -332,23 +332,23 @@ static int adu_open(struct inode *inode, struct file *file)
+ exit_no_device:
+ 	mutex_unlock(&adutux_mutex);
+ exit_no_lock:
+-	dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
++	dbg(2,"%s : leave, return value %d ", __func__, retval);
+ 	return retval;
+ }
+ 
+ static void adu_release_internal(struct adu_device *dev)
+ {
+-	dbg(2," %s : enter", __FUNCTION__);
++	dbg(2," %s : enter", __func__);
+ 
+ 	/* decrement our usage count for the device */
+ 	--dev->open_count;
+-	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
++	dbg(2," %s : open count %d", __func__, dev->open_count);
+ 	if (dev->open_count <= 0) {
+ 		adu_abort_transfers(dev);
+ 		dev->open_count = 0;
+ 	}
+ 
+-	dbg(2," %s : leave", __FUNCTION__);
++	dbg(2," %s : leave", __func__);
+ }
+ 
+ static int adu_release(struct inode *inode, struct file *file)
+@@ -356,17 +356,17 @@ static int adu_release(struct inode *inode, struct file *file)
+ 	struct adu_device *dev;
+ 	int retval = 0;
+ 
+-	dbg(2," %s : enter", __FUNCTION__);
++	dbg(2," %s : enter", __func__);
+ 
+ 	if (file == NULL) {
+- 		dbg(1," %s : file is NULL", __FUNCTION__);
++ 		dbg(1," %s : file is NULL", __func__);
+ 		retval = -ENODEV;
+ 		goto exit;
+ 	}
+ 
+ 	dev = file->private_data;
+ 	if (dev == NULL) {
+- 		dbg(1," %s : object is NULL", __FUNCTION__);
++ 		dbg(1," %s : object is NULL", __func__);
+ 		retval = -ENODEV;
+ 		goto exit;
+ 	}
+@@ -374,7 +374,7 @@ static int adu_release(struct inode *inode, struct file *file)
+ 	mutex_lock(&adutux_mutex); /* not interruptible */
+ 
+ 	if (dev->open_count <= 0) {
+-		dbg(1," %s : device not opened", __FUNCTION__);
++		dbg(1," %s : device not opened", __func__);
+ 		retval = -ENODEV;
+ 		goto exit;
+ 	}
+@@ -388,7 +388,7 @@ static int adu_release(struct inode *inode, struct file *file)
+ 
+ exit:
+ 	mutex_unlock(&adutux_mutex);
+-	dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
++	dbg(2," %s : leave, return value %d", __func__, retval);
+ 	return retval;
+ }
+ 
+@@ -405,10 +405,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ 	unsigned long flags;
+ 	DECLARE_WAITQUEUE(wait, current);
+ 
+-	dbg(2," %s : enter, count = %Zd, file=%p", __FUNCTION__, count, file);
++	dbg(2," %s : enter, count = %Zd, file=%p", __func__, count, file);
+ 
+ 	dev = file->private_data;
+-	dbg(2," %s : dev=%p", __FUNCTION__, dev);
++	dbg(2," %s : dev=%p", __func__, dev);
+ 
+ 	if (mutex_lock_interruptible(&dev->mtx))
+ 		return -ERESTARTSYS;
+@@ -422,16 +422,16 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ 
+ 	/* verify that some data was requested */
+ 	if (count == 0) {
+-		dbg(1," %s : read request of 0 bytes", __FUNCTION__);
++		dbg(1," %s : read request of 0 bytes", __func__);
+ 		goto exit;
+ 	}
+ 
+ 	timeout = COMMAND_TIMEOUT;
+-	dbg(2," %s : about to start looping", __FUNCTION__);
++	dbg(2," %s : about to start looping", __func__);
+ 	while (bytes_to_read) {
+ 		int data_in_secondary = dev->secondary_tail - dev->secondary_head;
+ 		dbg(2," %s : while, data_in_secondary=%d, status=%d",
+-		    __FUNCTION__, data_in_secondary,
++		    __func__, data_in_secondary,
+ 		    dev->interrupt_in_urb->status);
+ 
+ 		if (data_in_secondary) {
+@@ -456,7 +456,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ 				/* we secure access to the primary */
+ 				char *tmp;
+ 				dbg(2," %s : swap, read_buffer_length = %d",
+-				    __FUNCTION__, dev->read_buffer_length);
++				    __func__, dev->read_buffer_length);
+ 				tmp = dev->read_buffer_secondary;
+ 				dev->read_buffer_secondary = dev->read_buffer_primary;
+ 				dev->read_buffer_primary = tmp;
+@@ -471,10 +471,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ 				if (!dev->read_urb_finished) {
+ 					/* somebody is doing IO */
+ 					spin_unlock_irqrestore(&dev->buflock, flags);
+-					dbg(2," %s : submitted already", __FUNCTION__);
++					dbg(2," %s : submitted already", __func__);
+ 				} else {
+ 					/* we must initiate input */
+-					dbg(2," %s : initiate input", __FUNCTION__);
++					dbg(2," %s : initiate input", __func__);
+ 					dev->read_urb_finished = 0;
+ 					spin_unlock_irqrestore(&dev->buflock, flags);
+ 
+@@ -492,7 +492,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ 						if (retval == -ENOMEM) {
+ 							retval = bytes_read ? bytes_read : -ENOMEM;
+ 						}
+-						dbg(2," %s : submit failed", __FUNCTION__);
++						dbg(2," %s : submit failed", __func__);
+ 						goto exit;
+ 					}
+ 				}
+@@ -511,13 +511,13 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ 				remove_wait_queue(&dev->read_wait, &wait);
+ 
+ 				if (timeout <= 0) {
+-					dbg(2," %s : timeout", __FUNCTION__);
++					dbg(2," %s : timeout", __func__);
+ 					retval = bytes_read ? bytes_read : -ETIMEDOUT;
+ 					goto exit;
+ 				}
+ 
+ 				if (signal_pending(current)) {
+-					dbg(2," %s : signal pending", __FUNCTION__);
++					dbg(2," %s : signal pending", __func__);
+ 					retval = bytes_read ? bytes_read : -EINTR;
+ 					goto exit;
+ 				}
+@@ -550,7 +550,7 @@ exit:
+ 	/* unlock the device */
+ 	mutex_unlock(&dev->mtx);
+ 
+-	dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
++	dbg(2," %s : leave, return value %d", __func__, retval);
+ 	return retval;
+ }
+ 
+@@ -565,7 +565,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ 	unsigned long flags;
+ 	int retval;
+ 
+-	dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
++	dbg(2," %s : enter, count = %Zd", __func__, count);
+ 
+ 	dev = file->private_data;
+ 
+@@ -582,7 +582,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ 
+ 	/* verify that we actually have some data to write */
+ 	if (count == 0) {
+-		dbg(1," %s : write request of 0 bytes", __FUNCTION__);
++		dbg(1," %s : write request of 0 bytes", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -595,13 +595,13 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ 
+ 			mutex_unlock(&dev->mtx);
+ 			if (signal_pending(current)) {
+-				dbg(1," %s : interrupted", __FUNCTION__);
++				dbg(1," %s : interrupted", __func__);
+ 				set_current_state(TASK_RUNNING);
+ 				retval = -EINTR;
+ 				goto exit_onqueue;
+ 			}
+ 			if (schedule_timeout(COMMAND_TIMEOUT) == 0) {
+-				dbg(1, "%s - command timed out.", __FUNCTION__);
++				dbg(1, "%s - command timed out.", __func__);
+ 				retval = -ETIMEDOUT;
+ 				goto exit_onqueue;
+ 			}
+@@ -612,18 +612,18 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ 				goto exit_nolock;
+ 			}
+ 
+-			dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count);
++			dbg(4," %s : in progress, count = %Zd", __func__, count);
+ 		} else {
+ 			spin_unlock_irqrestore(&dev->buflock, flags);
+ 			set_current_state(TASK_RUNNING);
+ 			remove_wait_queue(&dev->write_wait, &waita);
+-			dbg(4," %s : sending, count = %Zd", __FUNCTION__, count);
++			dbg(4," %s : sending, count = %Zd", __func__, count);
+ 
+ 			/* write the data into interrupt_out_buffer from userspace */
+ 			buffer_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize);
+ 			bytes_to_write = count > buffer_size ? buffer_size : count;
+ 			dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd",
+-			    __FUNCTION__, buffer_size, count, bytes_to_write);
++			    __func__, buffer_size, count, bytes_to_write);
+ 
+ 			if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
+ 				retval = -EFAULT;
+@@ -661,7 +661,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ exit:
+ 	mutex_unlock(&dev->mtx);
+ exit_nolock:
+-	dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
++	dbg(2," %s : leave, return value %d", __func__, retval);
+ 	return retval;
+ 
+ exit_onqueue:
+@@ -706,7 +706,7 @@ static int adu_probe(struct usb_interface *interface,
+ 	int out_end_size;
+ 	int i;
+ 
+-	dbg(2," %s : enter", __FUNCTION__);
++	dbg(2," %s : enter", __func__);
+ 
+ 	if (udev == NULL) {
+ 		dev_err(&interface->dev, "udev is NULL.\n");
+@@ -807,7 +807,7 @@ static int adu_probe(struct usb_interface *interface,
+ 		dev_err(&interface->dev, "Could not retrieve serial number\n");
+ 		goto error;
+ 	}
+-	dbg(2," %s : serial_number=%s", __FUNCTION__, dev->serial_number);
++	dbg(2," %s : serial_number=%s", __func__, dev->serial_number);
+ 
+ 	/* we can register the device now, as it is ready */
+ 	usb_set_intfdata(interface, dev);
+@@ -828,7 +828,7 @@ static int adu_probe(struct usb_interface *interface,
+ 		 udev->descriptor.idProduct, dev->serial_number,
+ 		 (dev->minor - ADU_MINOR_BASE));
+ exit:
+-	dbg(2," %s : leave, return value %p (dev)", __FUNCTION__, dev);
++	dbg(2," %s : leave, return value %p (dev)", __func__, dev);
+ 
+ 	return retval;
+ 
+@@ -847,7 +847,7 @@ static void adu_disconnect(struct usb_interface *interface)
+ 	struct adu_device *dev;
+ 	int minor;
+ 
+-	dbg(2," %s : enter", __FUNCTION__);
++	dbg(2," %s : enter", __func__);
+ 
+ 	dev = usb_get_intfdata(interface);
+ 
+@@ -861,7 +861,7 @@ static void adu_disconnect(struct usb_interface *interface)
+ 	usb_set_intfdata(interface, NULL);
+ 
+ 	/* if the device is not opened, then we clean up right now */
+-	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
++	dbg(2," %s : open count %d", __func__, dev->open_count);
+ 	if (!dev->open_count)
+ 		adu_delete(dev);
+ 
+@@ -870,7 +870,7 @@ static void adu_disconnect(struct usb_interface *interface)
+ 	dev_info(&interface->dev, "ADU device adutux%d now disconnected\n",
+ 		 (minor - ADU_MINOR_BASE));
+ 
+-	dbg(2," %s : leave", __FUNCTION__);
++	dbg(2," %s : leave", __func__);
+ }
+ 
+ /* usb specific object needed to register this driver with the usb subsystem */
+@@ -885,7 +885,7 @@ static int __init adu_init(void)
+ {
+ 	int result;
+ 
+-	dbg(2," %s : enter", __FUNCTION__);
++	dbg(2," %s : enter", __func__);
+ 
+ 	/* register this driver with the USB subsystem */
+ 	result = usb_register(&adu_driver);
+@@ -899,17 +899,17 @@ static int __init adu_init(void)
+ 	info("adutux is an experimental driver. Use at your own risk");
+ 
+ exit:
+-	dbg(2," %s : leave, return value %d", __FUNCTION__, result);
++	dbg(2," %s : leave, return value %d", __func__, result);
+ 
+ 	return result;
+ }
+ 
+ static void __exit adu_exit(void)
+ {
+-	dbg(2," %s : enter", __FUNCTION__);
++	dbg(2," %s : enter", __func__);
+ 	/* deregister this driver with the USB subsystem */
+ 	usb_deregister(&adu_driver);
+-	dbg(2," %s : leave", __FUNCTION__);
++	dbg(2," %s : leave", __func__);
+ }
+ 
+ module_init(adu_init);
+diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
+index 1cb56f2..a076c24 100644
+--- a/drivers/usb/misc/appledisplay.c
++++ b/drivers/usb/misc/appledisplay.c
+@@ -29,7 +29,6 @@
+ #include <linux/timer.h>
+ #include <linux/workqueue.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ 
+ #define APPLE_VENDOR_ID		0x05AC
+ 
+@@ -104,11 +103,11 @@ static void appledisplay_complete(struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* This urb is terminated, clean up */
+ 		dbg("%s - urb shuttingdown with status: %d",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		return;
+ 	default:
+ 		dbg("%s - nonzero urb status received: %d",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		goto exit;
+ 	}
+ 
+@@ -132,7 +131,7 @@ exit:
+ 	retval = usb_submit_urb(pdata->urb, GFP_ATOMIC);
+ 	if (retval) {
+ 		err("%s - usb_submit_urb failed with result %d",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ 	}
+ }
+ 
+diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
+index df7e1ec..0939386 100644
+--- a/drivers/usb/misc/auerswald.c
++++ b/drivers/usb/misc/auerswald.c
+@@ -31,6 +31,7 @@
+ #include <linux/init.h>
+ #include <linux/wait.h>
+ #include <linux/usb.h>
++#include <linux/mutex.h>
+ 
+ /*-------------------------------------------------------------------*/
+ /* Debug support 						     */
+@@ -232,7 +233,7 @@ typedef struct auerscon
+ /* USB device context */
+ typedef struct
+ {
+-	struct semaphore 	mutex;         	    /* protection in user context */
++	struct mutex 	mutex;         	    /* protection in user context */
+ 	char 			name[20];	    /* name of the /dev/usb entry */
+ 	unsigned int		dtindex;	    /* index in the device table */
+ 	struct usb_device *	usbdev;      	    /* USB device handle */
+@@ -253,12 +254,12 @@ typedef struct
+ /* character device context */
+ typedef struct
+ {
+-	struct semaphore mutex;         /* protection in user context */
++	struct mutex mutex;		/* protection in user context */
+ 	pauerswald_t auerdev;           /* context pointer of assigned device */
+         auerbufctl_t bufctl;            /* controls the buffer chain */
+         auerscon_t scontext;            /* service context */
+ 	wait_queue_head_t readwait;     /* for synchronous reading */
+-	struct semaphore readmutex;     /* protection against multiple reads */
++	struct mutex readmutex;		/* protection against multiple reads */
+ 	pauerbuf_t readbuf;		/* buffer held for partial reading */
+ 	unsigned int readoffset;	/* current offset in readbuf */
+ 	unsigned int removed;		/* is != 0 if device is removed */
+@@ -283,7 +284,7 @@ static void auerchain_complete (struct urb * urb)
+         int result;
+ 
+         /* get pointer to element and to chain */
+-        pauerchainelement_t acep = (pauerchainelement_t) urb->context;
++	pauerchainelement_t acep = urb->context;
+         pauerchain_t         acp = acep->chain;
+ 
+         /* restore original entries in urb */
+@@ -593,7 +594,7 @@ ac_fail:/* free the elements */
+ /* completion handler for synchronous chained URBs */
+ static void auerchain_blocking_completion (struct urb *urb)
+ {
+-	pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context;
++	pauerchain_chs_t pchs = urb->context;
+ 	pchs->done = 1;
+ 	wmb();
+ 	wake_up (&pchs->wqh);
+@@ -846,7 +847,7 @@ static int auerswald_status_retry (int status)
+ /* Completion of asynchronous write block */
+ static void auerchar_ctrlwrite_complete (struct urb * urb)
+ {
+-	pauerbuf_t bp = (pauerbuf_t) urb->context;
++	pauerbuf_t bp =  urb->context;
+ 	pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
+ 	dbg ("auerchar_ctrlwrite_complete called");
+ 
+@@ -859,7 +860,7 @@ static void auerchar_ctrlwrite_complete (struct urb * urb)
+ /* Completion handler for dummy retry packet */
+ static void auerswald_ctrlread_wretcomplete (struct urb * urb)
+ {
+-        pauerbuf_t bp = (pauerbuf_t) urb->context;
++	pauerbuf_t bp = urb->context;
+         pauerswald_t cp;
+ 	int ret;
+ 	int status = urb->status;
+@@ -903,7 +904,7 @@ static void auerswald_ctrlread_complete (struct urb * urb)
+         unsigned int  serviceid;
+         pauerswald_t  cp;
+         pauerscon_t   scp;
+-        pauerbuf_t    bp  = (pauerbuf_t) urb->context;
++	pauerbuf_t bp = urb->context;
+ 	int status = urb->status;
+ 	int ret;
+ 
+@@ -980,9 +981,9 @@ static void auerswald_int_complete (struct urb * urb)
+         int ret;
+ 	int status = urb->status;
+         pauerbuf_t   bp = NULL;
+-        pauerswald_t cp = (pauerswald_t) urb->context;
++	pauerswald_t cp = urb->context;
+ 
+-        dbg ("%s called", __FUNCTION__);
++        dbg ("%s called", __func__);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -992,10 +993,10 @@ static void auerswald_int_complete (struct urb * urb)
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, status);
++		dbg("%s - urb shutting down with status: %d", __func__, status);
+ 		return;
+ 	default:
+-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, status);
++		dbg("%s - nonzero urb status received: %d", __func__, status);
+ 		goto exit;
+ 	}
+ 
+@@ -1080,7 +1081,7 @@ exit:
+ 	ret = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (ret)
+ 		err ("%s - usb_submit_urb failed with result %d",
+-		     __FUNCTION__, ret);
++		     __func__, ret);
+ }
+ 
+ /* int memory deallocation
+@@ -1376,7 +1377,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
+ 	if (cp == NULL) {
+ 		return -ENODEV;
+ 	}
+-	if (down_interruptible (&cp->mutex)) {
++	if (mutex_lock_interruptible(&cp->mutex)) {
+ 		return -ERESTARTSYS;
+ 	}
+ 
+@@ -1389,8 +1390,8 @@ static int auerchar_open (struct inode *inode, struct file *file)
+ 	}
+ 
+ 	/* Initialize device descriptor */
+-	init_MUTEX( &ccp->mutex);
+-	init_MUTEX( &ccp->readmutex);
++	mutex_init(&ccp->mutex);
++	mutex_init(&ccp->readmutex);
+         auerbuf_init (&ccp->bufctl);
+         ccp->scontext.id = AUH_UNASSIGNED;
+         ccp->scontext.dispatch = auerchar_ctrlread_dispatch;
+@@ -1405,7 +1406,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
+ 	cp->open_count++;
+ 	ccp->auerdev = cp;
+ 	dbg("open %s as /dev/%s", cp->dev_desc, cp->name);
+-	up (&cp->mutex);
++	mutex_unlock(&cp->mutex);
+ 
+ 	/* file IO stuff */
+ 	file->f_pos = 0;
+@@ -1413,7 +1414,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
+ 	return nonseekable_open(inode, file);
+ 
+ 	/* Error exit */
+-ofail:	up (&cp->mutex);
++ofail:	mutex_unlock(&cp->mutex);
+ 	auerchar_delete (ccp);
+ 	return ret;
+ }
+@@ -1432,23 +1433,23 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int
+         dbg ("ioctl");
+ 
+ 	/* get the mutexes */
+-	if (down_interruptible (&ccp->mutex)) {
++	if (mutex_lock_interruptible(&ccp->mutex)) {
+ 		return -ERESTARTSYS;
+ 	}
+ 	cp = ccp->auerdev;
+ 	if (!cp) {
+-		up (&ccp->mutex);
++		mutex_unlock(&ccp->mutex);
+                 return -ENODEV;
+ 	}
+-	if (down_interruptible (&cp->mutex)) {
+-		up(&ccp->mutex);
++	if (mutex_lock_interruptible(&cp->mutex)) {
++		mutex_unlock(&ccp->mutex);
+ 		return -ERESTARTSYS;
+ 	}
+ 
+ 	/* Check for removal */
+ 	if (!cp->usbdev) {
+-		up(&cp->mutex);
+-		up(&ccp->mutex);
++		mutex_unlock(&cp->mutex);
++		mutex_unlock(&ccp->mutex);
+                 return -ENODEV;
+ 	}
+ 
+@@ -1550,8 +1551,8 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int
+ 		break;
+         }
+ 	/* release the mutexes */
+-	up(&cp->mutex);
+-	up(&ccp->mutex);
++	mutex_unlock(&cp->mutex);
++	mutex_unlock(&ccp->mutex);
+ 	return ret;
+ }
+ 
+@@ -1574,18 +1575,18 @@ static ssize_t auerchar_read (struct file *file, char __user *buf, size_t count,
+ 		return 0;
+ 
+ 	/* get the mutex */
+-	if (down_interruptible (&ccp->mutex))
++	if (mutex_lock_interruptible(&ccp->mutex))
+ 		return -ERESTARTSYS;
+ 
+ 	/* Can we expect to read something? */
+ 	if (ccp->scontext.id == AUH_UNASSIGNED) {
+-		up (&ccp->mutex);
++		mutex_unlock(&ccp->mutex);
+                 return -EIO;
+ 	}
+ 
+ 	/* only one reader per device allowed */
+-	if (down_interruptible (&ccp->readmutex)) {
+-		up (&ccp->mutex);
++	if (mutex_lock_interruptible(&ccp->readmutex)) {
++		mutex_unlock(&ccp->mutex);
+ 		return -ERESTARTSYS;
+ 	}
+ 
+@@ -1602,8 +1603,8 @@ doreadbuf:
+ 		if (count) {
+ 			if (copy_to_user (buf, bp->bufp+ccp->readoffset, count)) {
+ 				dbg ("auerswald_read: copy_to_user failed");
+-				up (&ccp->readmutex);
+-				up (&ccp->mutex);
++				mutex_unlock(&ccp->readmutex);
++				mutex_unlock(&ccp->mutex);
+ 				return -EFAULT;
+ 			}
+ 		}
+@@ -1617,8 +1618,8 @@ doreadbuf:
+ 		}
+ 		/* return with number of bytes read */
+ 		if (count) {
+-			up (&ccp->readmutex);
+-			up (&ccp->mutex);
++			mutex_unlock(&ccp->readmutex);
++			mutex_unlock(&ccp->mutex);
+ 			return count;
+ 		}
+ 	}
+@@ -1654,29 +1655,29 @@ doreadlist:
+                 dbg ("No read buffer available, returning -EAGAIN");
+ 		set_current_state (TASK_RUNNING);
+ 		remove_wait_queue (&ccp->readwait, &wait);
+-		up (&ccp->readmutex);
+-		up (&ccp->mutex);
++		mutex_unlock(&ccp->readmutex);
++		mutex_unlock(&ccp->mutex);
+ 		return -EAGAIN;  /* nonblocking, no data available */
+         }
+ 
+ 	/* yes, we should wait! */
+-	up (&ccp->mutex); /* allow other operations while we wait */
++	mutex_unlock(&ccp->mutex); /* allow other operations while we wait */
+ 	schedule();
+ 	remove_wait_queue (&ccp->readwait, &wait);
+ 	if (signal_pending (current)) {
+ 		/* waked up by a signal */
+-		up (&ccp->readmutex);
++		mutex_unlock(&ccp->readmutex);
+ 		return -ERESTARTSYS;
+ 	}
+ 
+ 	/* Anything left to read? */
+ 	if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
+-		up (&ccp->readmutex);
++		mutex_unlock(&ccp->readmutex);
+ 		return -EIO;
+ 	}
+ 
+-	if (down_interruptible (&ccp->mutex)) {
+-		up (&ccp->readmutex);
++	if (mutex_lock_interruptible(&ccp->mutex)) {
++		mutex_unlock(&ccp->readmutex);
+ 		return -ERESTARTSYS;
+ 	}
+ 
+@@ -1707,27 +1708,27 @@ static ssize_t auerchar_write (struct file *file, const char __user *buf, size_t
+ 
+ write_again:
+ 	/* get the mutex */
+-	if (down_interruptible (&ccp->mutex))
++	if (mutex_lock_interruptible(&ccp->mutex))
+ 		return -ERESTARTSYS;
+ 
+ 	/* Can we expect to write something? */
+ 	if (ccp->scontext.id == AUH_UNASSIGNED) {
+-		up (&ccp->mutex);
++		mutex_unlock(&ccp->mutex);
+                 return -EIO;
+ 	}
+ 
+ 	cp = ccp->auerdev;
+ 	if (!cp) {
+-		up (&ccp->mutex);
++		mutex_unlock(&ccp->mutex);
+ 		return -ERESTARTSYS;
+ 	}
+-	if (down_interruptible (&cp->mutex)) {
+-		up (&ccp->mutex);
++	if (mutex_lock_interruptible(&cp->mutex)) {
++		mutex_unlock(&ccp->mutex);
+ 		return -ERESTARTSYS;
+ 	}
+ 	if (!cp->usbdev) {
+-		up (&cp->mutex);
+-		up (&ccp->mutex);
++		mutex_unlock(&cp->mutex);
++		mutex_unlock(&ccp->mutex);
+ 		return -EIO;
+ 	}
+ 	/* Prepare for sleep */
+@@ -1750,8 +1751,8 @@ write_again:
+ 
+ 	/* are there any buffers left? */
+ 	if (!bp) {
+-		up (&cp->mutex);
+-		up (&ccp->mutex);
++		mutex_unlock(&cp->mutex);
++		mutex_unlock(&ccp->mutex);
+ 
+ 		/* NONBLOCK: don't wait */
+ 		if (file->f_flags & O_NONBLOCK) {
+@@ -1783,8 +1784,8 @@ write_again:
+ 		auerbuf_releasebuf (bp);
+ 		/* Wake up all processes waiting for a buffer */
+ 		wake_up (&cp->bufferwait);
+-		up (&cp->mutex);
+-		up (&ccp->mutex);
++		mutex_unlock(&cp->mutex);
++		mutex_unlock(&ccp->mutex);
+ 		return -EFAULT;
+ 	}
+ 
+@@ -1803,18 +1804,18 @@ write_again:
+ 		    auerchar_ctrlwrite_complete, bp);
+ 	/* up we go */
+ 	ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);
+-	up (&cp->mutex);
++	mutex_unlock(&cp->mutex);
+ 	if (ret) {
+ 		dbg ("auerchar_write: nonzero result of auerchain_submit_urb %d", ret);
+ 		auerbuf_releasebuf (bp);
+ 		/* Wake up all processes waiting for a buffer */
+ 		wake_up (&cp->bufferwait);
+-		up (&ccp->mutex);
++		mutex_unlock(&ccp->mutex);
+ 		return -EIO;
+ 	}
+ 	else {
+ 		dbg ("auerchar_write: Write OK");
+-		up (&ccp->mutex);
++		mutex_unlock(&ccp->mutex);
+ 		return len;
+ 	}
+ }
+@@ -1827,24 +1828,24 @@ static int auerchar_release (struct inode *inode, struct file *file)
+ 	pauerswald_t cp;
+ 	dbg("release");
+ 
+-	down(&ccp->mutex);
++	mutex_lock(&ccp->mutex);
+ 	cp = ccp->auerdev;
+ 	if (cp) {
+-		down(&cp->mutex);
++		mutex_lock(&cp->mutex);
+ 		/* remove an open service */
+ 		auerswald_removeservice (cp, &ccp->scontext);
+ 		/* detach from device */
+ 		if ((--cp->open_count <= 0) && (cp->usbdev == NULL)) {
+ 			/* usb device waits for removal */
+-			up (&cp->mutex);
++			mutex_unlock(&cp->mutex);
+ 			auerswald_delete (cp);
+ 		} else {
+-			up (&cp->mutex);
++			mutex_unlock(&cp->mutex);
+ 		}
+ 		cp = NULL;
+ 		ccp->auerdev = NULL;
+ 	}
+-	up (&ccp->mutex);
++	mutex_unlock(&ccp->mutex);
+ 	auerchar_delete (ccp);
+ 
+ 	return 0;
+@@ -1917,7 +1918,7 @@ static int auerswald_probe (struct usb_interface *intf,
+ 	}
+ 
+ 	/* Initialize device descriptor */
+-	init_MUTEX (&cp->mutex);
++	mutex_init(&cp->mutex);
+ 	cp->usbdev = usbdev;
+ 	auerchain_init (&cp->controlchain);
+         auerbuf_init (&cp->bufctl);
+@@ -2042,7 +2043,7 @@ static void auerswald_disconnect (struct usb_interface *intf)
+ 	/* give back our USB minor number */
+ 	usb_deregister_dev(intf, &auerswald_class);
+ 
+-	down (&cp->mutex);
++	mutex_lock(&cp->mutex);
+ 	info ("device /dev/%s now disconnecting", cp->name);
+ 
+ 	/* Stop the interrupt endpoint */
+@@ -2057,16 +2058,18 @@ static void auerswald_disconnect (struct usb_interface *intf)
+ 
+ 	if (cp->open_count == 0) {
+ 		/* nobody is using this device. So we can clean up now */
+-		up (&cp->mutex);/* up() is possible here because no other task
+-				   can open the device (see above). I don't want
+-				   to kfree() a locked mutex. */
++		mutex_unlock(&cp->mutex);
++		/* mutex_unlock() is possible here because no other task
++		   can open the device (see above). I don't want
++		   to kfree() a locked mutex. */
++
+ 		auerswald_delete (cp);
+ 	} else {
+ 		/* device is used. Remove the pointer to the
+ 		   usb device (it's not valid any more). The last
+ 		   release() will do the clean up */
+ 		cp->usbdev = NULL;
+-		up (&cp->mutex);
++		mutex_unlock(&cp->mutex);
+ 		/* Terminate waiting writers */
+ 		wake_up (&cp->bufferwait);
+ 		/* Inform all waiting readers */
+diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
+index 148b7fe..ec88b3b 100644
+--- a/drivers/usb/misc/ftdi-elan.c
++++ b/drivers/usb/misc/ftdi-elan.c
+@@ -746,7 +746,7 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
+ 
+ static void ftdi_elan_write_bulk_callback(struct urb *urb)
+ {
+-        struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
++	struct usb_ftdi *ftdi = urb->context;
+ 	int status = urb->status;
+ 
+ 	if (status && !(status == -ENOENT || status == -ECONNRESET ||
+diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
+index 8010705..1cb54a2 100644
+--- a/drivers/usb/misc/iowarrior.c
++++ b/drivers/usb/misc/iowarrior.c
+@@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(usb, iowarrior_ids);
+  */
+ static void iowarrior_callback(struct urb *urb)
+ {
+-	struct iowarrior *dev = (struct iowarrior *)urb->context;
++	struct iowarrior *dev = urb->context;
+ 	int intr_idx;
+ 	int read_idx;
+ 	int aux_idx;
+@@ -218,7 +218,7 @@ exit:
+ 	retval = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if (retval)
+ 		dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d\n",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ 
+ }
+ 
+@@ -230,7 +230,7 @@ static void iowarrior_write_callback(struct urb *urb)
+ 	struct iowarrior *dev;
+ 	int status = urb->status;
+ 
+-	dev = (struct iowarrior *)urb->context;
++	dev = urb->context;
+ 	/* sync/async unlink faults aren't errors */
+ 	if (status &&
+ 	    !(status == -ENOENT ||
+@@ -453,7 +453,7 @@ static ssize_t iowarrior_write(struct file *file,
+ 	default:
+ 		/* what do we have here ? An unsupported Product-ID ? */
+ 		dev_err(&dev->interface->dev, "%s - not supported for product=0x%x\n",
+-			__FUNCTION__, dev->product_id);
++			__func__, dev->product_id);
+ 		retval = -EFAULT;
+ 		goto exit;
+ 		break;
+@@ -604,7 +604,7 @@ static int iowarrior_open(struct inode *inode, struct file *file)
+ 
+ 	interface = usb_find_interface(&iowarrior_driver, subminor);
+ 	if (!interface) {
+-		err("%s - error, can't find device for minor %d", __FUNCTION__,
++		err("%s - error, can't find device for minor %d", __func__,
+ 		    subminor);
+ 		return -ENODEV;
+ 	}
+diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
+index c730d20..11580e8 100644
+--- a/drivers/usb/misc/ldusb.c
++++ b/drivers/usb/misc/ldusb.c
+@@ -231,7 +231,7 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
+ 			goto exit;
+ 		} else {
+ 			dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
+-				 __FUNCTION__, status);
++				 __func__, status);
+ 			spin_lock(&dev->rbsl);
+ 			goto resubmit; /* maybe we can recover */
+ 		}
+@@ -247,7 +247,7 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
+ 			memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length);
+ 			dev->ring_head = next_ring_head;
+ 			dbg_info(&dev->intf->dev, "%s: received %d bytes\n",
+-				 __FUNCTION__, urb->actual_length);
++				 __func__, urb->actual_length);
+ 		} else {
+ 			dev_warn(&dev->intf->dev,
+ 				 "Ring buffer overflow, %d bytes dropped\n",
+@@ -286,7 +286,7 @@ static void ld_usb_interrupt_out_callback(struct urb *urb)
+ 			status == -ESHUTDOWN))
+ 		dbg_info(&dev->intf->dev,
+ 			 "%s - nonzero write interrupt status received: %d\n",
+-			 __FUNCTION__, status);
++			 __func__, status);
+ 
+ 	dev->interrupt_out_busy = 0;
+ 	wake_up_interruptible(&dev->write_wait);
+@@ -309,7 +309,7 @@ static int ld_usb_open(struct inode *inode, struct file *file)
+ 
+ 	if (!interface) {
+ 		err("%s - error, can't find device for minor %d\n",
+-		     __FUNCTION__, subminor);
++		     __func__, subminor);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -556,7 +556,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
+ 	bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
+ 	if (bytes_to_write < count)
+ 		dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write);
+-	dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __FUNCTION__, count, bytes_to_write);
++	dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write);
+ 
+ 	if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
+ 		retval = -EFAULT;
+diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
+index 6664043..9370326 100644
+--- a/drivers/usb/misc/legousbtower.c
++++ b/drivers/usb/misc/legousbtower.c
+@@ -31,7 +31,7 @@
+  *   - imported into lejos project
+  *   - changed wake_up to wake_up_interruptible
+  *   - changed to use lego0 rather than tower0
+- *   - changed dbg() to use __func__ rather than deprecated __FUNCTION__
++ *   - changed dbg() to use __func__ rather than deprecated __func__
+  * 2003-01-12 - 0.53 david (david at csse.uwa.edu.au)
+  *   - changed read and write to write everything or
+  *     timeout (from a patch by Chris Riesen and Brett Thaeler driver)
+@@ -49,7 +49,7 @@
+  *   - added poll
+  *   - forbid seeking
+  *   - added nonblocking I/O
+- *   - changed back __func__ to __FUNCTION__
++ *   - changed back __func__ to __func__
+  *   - read and log tower firmware version
+  *   - reset tower on probe, avoids failure of first write
+  * 2004-03-09 - 0.7 Juergen Stuber <starblue at users.sourceforge.net>
+@@ -309,7 +309,7 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i
+  */
+ static inline void tower_delete (struct lego_usb_tower *dev)
+ {
+-	dbg(2, "%s: enter", __FUNCTION__);
++	dbg(2, "%s: enter", __func__);
+ 
+ 	tower_abort_transfers (dev);
+ 
+@@ -321,7 +321,7 @@ static inline void tower_delete (struct lego_usb_tower *dev)
+ 	kfree (dev->interrupt_out_buffer);
+ 	kfree (dev);
+ 
+-	dbg(2, "%s: leave", __FUNCTION__);
++	dbg(2, "%s: leave", __func__);
+ }
+ 
+ 
+@@ -337,7 +337,7 @@ static int tower_open (struct inode *inode, struct file *file)
+ 	struct tower_reset_reply reset_reply;
+ 	int result;
+ 
+-	dbg(2, "%s: enter", __FUNCTION__);
++	dbg(2, "%s: enter", __func__);
+ 
+ 	nonseekable_open(inode, file);
+ 	subminor = iminor(inode);
+@@ -346,7 +346,7 @@ static int tower_open (struct inode *inode, struct file *file)
+ 
+ 	if (!interface) {
+ 		err ("%s - error, can't find device for minor %d",
+-		     __FUNCTION__, subminor);
++		     __func__, subminor);
+ 		retval = -ENODEV;
+ 		goto exit;
+ 	}
+@@ -424,7 +424,7 @@ unlock_exit:
+ 	mutex_unlock(&dev->lock);
+ 
+ exit:
+-	dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
++	dbg(2, "%s: leave, return value %d ", __func__, retval);
+ 
+ 	return retval;
+ }
+@@ -437,12 +437,12 @@ static int tower_release (struct inode *inode, struct file *file)
+ 	struct lego_usb_tower *dev;
+ 	int retval = 0;
+ 
+-	dbg(2, "%s: enter", __FUNCTION__);
++	dbg(2, "%s: enter", __func__);
+ 
+ 	dev = (struct lego_usb_tower *)file->private_data;
+ 
+ 	if (dev == NULL) {
+-		dbg(1, "%s: object is NULL", __FUNCTION__);
++		dbg(1, "%s: object is NULL", __func__);
+ 		retval = -ENODEV;
+ 		goto exit_nolock;
+ 	}
+@@ -454,7 +454,7 @@ static int tower_release (struct inode *inode, struct file *file)
+ 	}
+ 
+ 	if (dev->open_count != 1) {
+-		dbg(1, "%s: device not opened exactly once", __FUNCTION__);
++		dbg(1, "%s: device not opened exactly once", __func__);
+ 		retval = -ENODEV;
+ 		goto unlock_exit;
+ 	}
+@@ -480,7 +480,7 @@ unlock_exit:
+ exit:
+ 	mutex_unlock(&open_disc_mutex);
+ exit_nolock:
+-	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
++	dbg(2, "%s: leave, return value %d", __func__, retval);
+ 	return retval;
+ }
+ 
+@@ -491,10 +491,10 @@ exit_nolock:
+  */
+ static void tower_abort_transfers (struct lego_usb_tower *dev)
+ {
+-	dbg(2, "%s: enter", __FUNCTION__);
++	dbg(2, "%s: enter", __func__);
+ 
+ 	if (dev == NULL) {
+-		dbg(1, "%s: dev is null", __FUNCTION__);
++		dbg(1, "%s: dev is null", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -509,7 +509,7 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
+ 		usb_kill_urb(dev->interrupt_out_urb);
+ 
+ exit:
+-	dbg(2, "%s: leave", __FUNCTION__);
++	dbg(2, "%s: leave", __func__);
+ }
+ 
+ 
+@@ -542,7 +542,7 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
+ 	struct lego_usb_tower *dev;
+ 	unsigned int mask = 0;
+ 
+-	dbg(2, "%s: enter", __FUNCTION__);
++	dbg(2, "%s: enter", __func__);
+ 
+ 	dev = file->private_data;
+ 
+@@ -557,7 +557,7 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
+ 		mask |= POLLOUT | POLLWRNORM;
+ 	}
+ 
+-	dbg(2, "%s: leave, mask = %d", __FUNCTION__, mask);
++	dbg(2, "%s: leave, mask = %d", __func__, mask);
+ 
+ 	return mask;
+ }
+@@ -583,7 +583,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
+ 	int retval = 0;
+ 	unsigned long timeout = 0;
+ 
+-	dbg(2, "%s: enter, count = %Zd", __FUNCTION__, count);
++	dbg(2, "%s: enter, count = %Zd", __func__, count);
+ 
+ 	dev = (struct lego_usb_tower *)file->private_data;
+ 
+@@ -602,7 +602,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
+ 
+ 	/* verify that we actually have some data to read */
+ 	if (count == 0) {
+-		dbg(1, "%s: read request of 0 bytes", __FUNCTION__);
++		dbg(1, "%s: read request of 0 bytes", __func__);
+ 		goto unlock_exit;
+ 	}
+ 
+@@ -658,7 +658,7 @@ unlock_exit:
+ 	mutex_unlock(&dev->lock);
+ 
+ exit:
+-	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
++	dbg(2, "%s: leave, return value %d", __func__, retval);
+ 	return retval;
+ }
+ 
+@@ -672,7 +672,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
+ 	size_t bytes_to_write;
+ 	int retval = 0;
+ 
+-	dbg(2, "%s: enter, count = %Zd", __FUNCTION__, count);
++	dbg(2, "%s: enter, count = %Zd", __func__, count);
+ 
+ 	dev = (struct lego_usb_tower *)file->private_data;
+ 
+@@ -691,7 +691,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
+ 
+ 	/* verify that we actually have some data to write */
+ 	if (count == 0) {
+-		dbg(1, "%s: write request of 0 bytes", __FUNCTION__);
++		dbg(1, "%s: write request of 0 bytes", __func__);
+ 		goto unlock_exit;
+ 	}
+ 
+@@ -709,7 +709,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
+ 
+ 	/* write the data into interrupt_out_buffer from userspace */
+ 	bytes_to_write = min_t(int, count, write_buffer_size);
+-	dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __FUNCTION__, count, bytes_to_write);
++	dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __func__, count, bytes_to_write);
+ 
+ 	if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
+ 		retval = -EFAULT;
+@@ -742,7 +742,7 @@ unlock_exit:
+ 	mutex_unlock(&dev->lock);
+ 
+ exit:
+-	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
++	dbg(2, "%s: leave, return value %d", __func__, retval);
+ 
+ 	return retval;
+ }
+@@ -753,13 +753,13 @@ exit:
+  */
+ static void tower_interrupt_in_callback (struct urb *urb)
+ {
+-	struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
++	struct lego_usb_tower *dev = urb->context;
+ 	int status = urb->status;
+ 	int retval;
+ 
+-	dbg(4, "%s: enter, status %d", __FUNCTION__, status);
++	dbg(4, "%s: enter, status %d", __func__, status);
+ 
+-	lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
++	lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
+ 
+ 	if (status) {
+ 		if (status == -ENOENT ||
+@@ -767,7 +767,7 @@ static void tower_interrupt_in_callback (struct urb *urb)
+ 		    status == -ESHUTDOWN) {
+ 			goto exit;
+ 		} else {
+-			dbg(1, "%s: nonzero status received: %d", __FUNCTION__, status);
++			dbg(1, "%s: nonzero status received: %d", __func__, status);
+ 			goto resubmit; /* maybe we can recover */
+ 		}
+ 	}
+@@ -780,9 +780,9 @@ static void tower_interrupt_in_callback (struct urb *urb)
+ 				urb->actual_length);
+ 			dev->read_buffer_length += urb->actual_length;
+ 			dev->read_last_arrival = jiffies;
+-			dbg(3, "%s: received %d bytes", __FUNCTION__, urb->actual_length);
++			dbg(3, "%s: received %d bytes", __func__, urb->actual_length);
+ 		} else {
+-			printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __FUNCTION__, urb->actual_length);
++			printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __func__, urb->actual_length);
+ 		}
+ 		spin_unlock (&dev->read_buffer_lock);
+ 	}
+@@ -792,7 +792,7 @@ resubmit:
+ 	if (dev->interrupt_in_running && dev->udev) {
+ 		retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC);
+ 		if (retval) {
+-			err("%s: usb_submit_urb failed (%d)", __FUNCTION__, retval);
++			err("%s: usb_submit_urb failed (%d)", __func__, retval);
+ 		}
+ 	}
+ 
+@@ -800,8 +800,8 @@ exit:
+ 	dev->interrupt_in_done = 1;
+ 	wake_up_interruptible (&dev->read_wait);
+ 
+-	lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+-	dbg(4, "%s: leave, status %d", __FUNCTION__, status);
++	lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
++	dbg(4, "%s: leave, status %d", __func__, status);
+ }
+ 
+ 
+@@ -810,25 +810,25 @@ exit:
+  */
+ static void tower_interrupt_out_callback (struct urb *urb)
+ {
+-	struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
++	struct lego_usb_tower *dev = urb->context;
+ 	int status = urb->status;
+ 
+-	dbg(4, "%s: enter, status %d", __FUNCTION__, status);
+-	lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
++	dbg(4, "%s: enter, status %d", __func__, status);
++	lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
+ 
+ 	/* sync/async unlink faults aren't errors */
+ 	if (status && !(status == -ENOENT ||
+ 			status == -ECONNRESET ||
+ 			status == -ESHUTDOWN)) {
+ 		dbg(1, "%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 	}
+ 
+ 	dev->interrupt_out_busy = 0;
+ 	wake_up_interruptible(&dev->write_wait);
+ 
+-	lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+-	dbg(4, "%s: leave, status %d", __FUNCTION__, status);
++	lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
++	dbg(4, "%s: leave, status %d", __func__, status);
+ }
+ 
+ 
+@@ -849,7 +849,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
+ 	int retval = -ENOMEM;
+ 	int result;
+ 
+-	dbg(2, "%s: enter", __FUNCTION__);
++	dbg(2, "%s: enter", __func__);
+ 
+ 	if (udev == NULL) {
+ 		info ("udev is NULL.");
+@@ -978,7 +978,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
+ 
+ 
+ exit:
+-	dbg(2, "%s: leave, return value 0x%.8lx (dev)", __FUNCTION__, (long) dev);
++	dbg(2, "%s: leave, return value 0x%.8lx (dev)", __func__, (long) dev);
+ 
+ 	return retval;
+ 
+@@ -998,7 +998,7 @@ static void tower_disconnect (struct usb_interface *interface)
+ 	struct lego_usb_tower *dev;
+ 	int minor;
+ 
+-	dbg(2, "%s: enter", __FUNCTION__);
++	dbg(2, "%s: enter", __func__);
+ 
+ 	dev = usb_get_intfdata (interface);
+ 	mutex_lock(&open_disc_mutex);
+@@ -1023,7 +1023,7 @@ static void tower_disconnect (struct usb_interface *interface)
+ 
+ 	info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
+ 
+-	dbg(2, "%s: leave", __FUNCTION__);
++	dbg(2, "%s: leave", __func__);
+ }
+ 
+ 
+@@ -1036,7 +1036,7 @@ static int __init lego_usb_tower_init(void)
+ 	int result;
+ 	int retval = 0;
+ 
+-	dbg(2, "%s: enter", __FUNCTION__);
++	dbg(2, "%s: enter", __func__);
+ 
+ 	/* register this driver with the USB subsystem */
+ 	result = usb_register(&tower_driver);
+@@ -1049,7 +1049,7 @@ static int __init lego_usb_tower_init(void)
+ 	info(DRIVER_DESC " " DRIVER_VERSION);
+ 
+ exit:
+-	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
++	dbg(2, "%s: leave, return value %d", __func__, retval);
+ 
+ 	return retval;
+ }
+@@ -1060,12 +1060,12 @@ exit:
+  */
+ static void __exit lego_usb_tower_exit(void)
+ {
+-	dbg(2, "%s: enter", __FUNCTION__);
++	dbg(2, "%s: enter", __func__);
+ 
+ 	/* deregister this driver with the USB subsystem */
+ 	usb_deregister (&tower_driver);
+ 
+-	dbg(2, "%s: leave", __FUNCTION__);
++	dbg(2, "%s: leave", __func__);
+ }
+ 
+ module_init (lego_usb_tower_init);
+diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
+index aa9bcce..24230c6 100644
+--- a/drivers/usb/misc/phidgetkit.c
++++ b/drivers/usb/misc/phidgetkit.c
+@@ -113,7 +113,7 @@ static int set_outputs(struct interfacekit *kit)
+ 
+ 	buffer = kzalloc(4, GFP_KERNEL);
+ 	if (!buffer) {
+-		dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	buffer[0] = (u8)kit->outputs;
+@@ -146,7 +146,7 @@ static int change_string(struct interfacekit *kit, const char *display, unsigned
+ 	buffer = kmalloc(8, GFP_KERNEL);
+ 	form_buffer = kmalloc(30, GFP_KERNEL);
+ 	if ((!buffer) || (!form_buffer)) {
+-		dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -216,7 +216,7 @@ static ssize_t set_backlight(struct device *dev, struct device_attribute *attr,
+ 	
+ 	buffer = kzalloc(8, GFP_KERNEL);
+ 	if (!buffer) {
+-		dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
+ 		goto exit;
+ 	}
+ 
+diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
+index 2ad09b1..f0113c1 100644
+--- a/drivers/usb/misc/phidgetmotorcontrol.c
++++ b/drivers/usb/misc/phidgetmotorcontrol.c
+@@ -61,7 +61,7 @@ static int set_motor(struct motorcontrol *mc, int motor)
+ 
+ 	buffer = kzalloc(8, GFP_KERNEL);
+ 	if (!buffer) {
+-		dev_err(&mc->intf->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&mc->intf->dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
+index 0d9de2f..7d590c0 100644
+--- a/drivers/usb/misc/phidgetservo.c
++++ b/drivers/usb/misc/phidgetservo.c
+@@ -89,7 +89,7 @@ change_position_v30(struct phidget_servo *servo, int servo_no, int degrees,
+ 	buffer = kmalloc(6, GFP_KERNEL);
+ 	if (!buffer) {
+ 		dev_err(&servo->udev->dev, "%s - out of memory\n",
+-			__FUNCTION__);
++			__func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -162,7 +162,7 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
+ 	buffer = kmalloc(2, GFP_KERNEL);
+ 	if (!buffer) {
+ 		dev_err(&servo->udev->dev, "%s - out of memory\n",
+-			__FUNCTION__);
++			__func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -259,7 +259,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
+ 
+ 	dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL);
+ 	if (dev == NULL) {
+-		dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&interface->dev, "%s - out of memory\n", __func__);
+ 		rc = -ENOMEM;
+ 		goto out;
+ 	}
+diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
+index 20777d0..7f7021e 100644
+--- a/drivers/usb/misc/usblcd.c
++++ b/drivers/usb/misc/usblcd.c
+@@ -78,7 +78,7 @@ static int lcd_open(struct inode *inode, struct file *file)
+ 	interface = usb_find_interface(&lcd_driver, subminor);
+ 	if (!interface) {
+ 		err ("USBLCD: %s - error, can't find device for minor %d",
+-		     __FUNCTION__, subminor);
++		     __func__, subminor);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -185,7 +185,7 @@ static void lcd_write_bulk_callback(struct urb *urb)
+ 	struct usb_lcd *dev;
+ 	int status = urb->status;
+ 
+-	dev = (struct usb_lcd *)urb->context;
++	dev = urb->context;
+ 
+ 	/* sync/async unlink faults aren't errors */
+ 	if (status &&
+@@ -193,7 +193,7 @@ static void lcd_write_bulk_callback(struct urb *urb)
+ 	      status == -ECONNRESET ||
+               status == -ESHUTDOWN)) {
+ 		dbg("USBLCD: %s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 	}
+ 
+ 	/* free up our allocated buffer */
+@@ -248,7 +248,7 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
+ 	/* send the data out the bulk port */
+ 	retval = usb_submit_urb(urb, GFP_KERNEL);
+ 	if (retval) {
+-		err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval);
++		err("USBLCD: %s - failed submitting write urb, error %d", __func__, retval);
+ 		goto error_unanchor;
+ 	}
+ 	
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index b6b5b2a..a519838 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -201,7 +201,7 @@ found:
+ 
+ static void simple_callback (struct urb *urb)
+ {
+-	complete ((struct completion *) urb->context);
++	complete(urb->context);
+ }
+ 
+ static struct urb *simple_alloc_urb (
+@@ -1046,7 +1046,7 @@ static void unlink1_callback (struct urb *urb)
+ 		status = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (status) {
+ 		urb->status = status;
+-		complete ((struct completion *) urb->context);
++		complete(urb->context);
+ 	}
+ }
+ 
+@@ -1136,7 +1136,7 @@ static int verify_not_halted (int ep, struct urb *urb)
+ 		dbg ("ep %02x bogus status: %04x != 0", ep, status);
+ 		return -EINVAL;
+ 	}
+-	retval = simple_io (urb, 1, 0, 0, __FUNCTION__);
++	retval = simple_io (urb, 1, 0, 0, __func__);
+ 	if (retval != 0)
+ 		return -EINVAL;
+ 	return 0;
+@@ -1158,7 +1158,7 @@ static int verify_halted (int ep, struct urb *urb)
+ 		dbg ("ep %02x bogus status: %04x != 1", ep, status);
+ 		return -EINVAL;
+ 	}
+-	retval = simple_io (urb, 1, 0, -EPIPE, __FUNCTION__);
++	retval = simple_io (urb, 1, 0, -EPIPE, __func__);
+ 	if (retval != -EPIPE)
+ 		return -EINVAL;
+ 	retval = simple_io (urb, 1, 0, -EPIPE, "verify_still_halted");
+@@ -1404,7 +1404,7 @@ static struct urb *iso_alloc_urb (
+ 		return NULL;
+ 	maxp = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
+ 	maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11));
+-	packets = (bytes + maxp - 1) / maxp;
++	packets = DIV_ROUND_UP(bytes, maxp);
+ 
+ 	urb = usb_alloc_urb (packets, GFP_KERNEL);
+ 	if (!urb)
+@@ -1564,7 +1564,8 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
+ 	if (mutex_lock_interruptible(&dev->lock))
+ 		return -ERESTARTSYS;
+ 
+-	if (intf->dev.power.power_state.event != PM_EVENT_ON) {
++	/* FIXME: What if a system sleep starts while a test is running? */
++	if (!intf->is_active) {
+ 		mutex_unlock(&dev->lock);
+ 		return -EHOSTUNREACH;
+ 	}
+diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
+index 90c5953..0f76ed5 100644
+--- a/drivers/usb/mon/Makefile
++++ b/drivers/usb/mon/Makefile
+@@ -1,5 +1,5 @@
+ #
+-# Makefile for USB Core files and filesystem
++# Makefile for USB monitor
+ #
+ 
+ usbmon-objs	:= mon_main.o mon_stat.o mon_text.o mon_bin.o mon_dma.o
+diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
+index 1774ba5..4914553 100644
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -1026,8 +1026,6 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
+ 	return mask;
+ }
+ 
+-#if 0
+-
+ /*
+  * open and close: just keep track of how many times the device is
+  * mapped, to use the proper memory allocation function.
+@@ -1063,13 +1061,13 @@ static int mon_bin_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 	return 0;
+ }
+ 
+-struct vm_operations_struct mon_bin_vm_ops = {
++static struct vm_operations_struct mon_bin_vm_ops = {
+ 	.open =     mon_bin_vma_open,
+ 	.close =    mon_bin_vma_close,
+ 	.fault =    mon_bin_vma_fault,
+ };
+ 
+-int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
++static int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+ 	/* don't do anything here: "fault" will set up page table entries */
+ 	vma->vm_ops = &mon_bin_vm_ops;
+@@ -1079,8 +1077,6 @@ int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
+ 	return 0;
+ }
+ 
+-#endif  /*  0  */
+-
+ static const struct file_operations mon_fops_binary = {
+ 	.owner =	THIS_MODULE,
+ 	.open =		mon_bin_open,
+@@ -1090,6 +1086,7 @@ static const struct file_operations mon_fops_binary = {
+ 	.poll =		mon_bin_poll,
+ 	.ioctl =	mon_bin_ioctl,
+ 	.release =	mon_bin_release,
++	.mmap =		mon_bin_mmap,
+ };
+ 
+ static int mon_bin_wait_event(struct file *file, struct mon_reader_bin *rp)
+diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
+index b371ffd..442d807 100644
+--- a/drivers/usb/mon/mon_main.c
++++ b/drivers/usb/mon/mon_main.c
+@@ -129,8 +129,7 @@ static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
+ 
+ /*
+  */
+-static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb,
+-		int status)
++static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb, int status)
+ {
+ 	unsigned long flags;
+ 	struct list_head *pos;
+diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
+index f6d1491..c7a595c 100644
+--- a/drivers/usb/mon/mon_stat.c
++++ b/drivers/usb/mon/mon_stat.c
+@@ -59,6 +59,9 @@ static ssize_t mon_stat_read(struct file *file, char __user *buf,
+ 
+ static int mon_stat_release(struct inode *inode, struct file *file)
+ {
++	struct snap *sp = file->private_data;
++	file->private_data = NULL;
++	kfree(sp);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
+index c1e65df..2cffec8 100644
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -20,8 +20,8 @@ menuconfig USB_SERIAL
+ if USB_SERIAL
+ 
+ config USB_SERIAL_CONSOLE
+-	bool "USB Serial Console device support (EXPERIMENTAL)"
+-	depends on USB_SERIAL=y && EXPERIMENTAL
++	bool "USB Serial Console device support"
++	depends on USB_SERIAL=y
+ 	---help---
+ 	  If you say Y here, it will be possible to use a USB to serial
+ 	  converter port as the system console (the system console is the
+@@ -44,13 +44,11 @@ config USB_SERIAL_CONSOLE
+ 
+ config USB_EZUSB
+ 	bool "Functions for loading firmware on EZUSB chips"
+-	depends on USB_SERIAL
+ 	help
+ 	    Say Y here if you need EZUSB device support.
+ 
+ config USB_SERIAL_GENERIC
+ 	bool "USB Generic Serial Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to use the generic USB serial driver.  Please
+ 	  read <file:Documentation/usb/usb-serial.txt> for more information on
+@@ -59,8 +57,7 @@ config USB_SERIAL_GENERIC
+ 	  properly.
+ 
+ config USB_SERIAL_AIRCABLE
+-	tristate "USB AIRcable Bluetooth Dongle Driver (EXPERIMENTAL)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++	tristate "USB AIRcable Bluetooth Dongle Driver"
+ 	help
+ 	    Say Y here if you want to use USB AIRcable Bluetooth Dongle.
+ 
+@@ -69,7 +66,6 @@ config USB_SERIAL_AIRCABLE
+ 
+ config USB_SERIAL_AIRPRIME
+ 	tristate "USB AirPrime CDMA Wireless Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to use a AirPrime CDMA Wireless PC card.
+ 
+@@ -77,8 +73,7 @@ config USB_SERIAL_AIRPRIME
+ 	  module will be called airprime.
+ 
+ config USB_SERIAL_ARK3116
+-	tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++	tristate "USB ARK Micro 3116 USB Serial Driver"
+ 	help
+ 	  Say Y here if you want to use a ARK Micro 3116 USB to Serial
+ 	  device.
+@@ -88,7 +83,6 @@ config USB_SERIAL_ARK3116
+ 
+ config USB_SERIAL_BELKIN
+ 	tristate "USB Belkin and Peracom Single Port Serial Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to use a Belkin USB Serial single port
+ 	  adaptor (F5U103 is one of the model numbers) or the Peracom single
+@@ -99,7 +93,6 @@ config USB_SERIAL_BELKIN
+ 
+ config USB_SERIAL_CH341
+ 	tristate "USB Winchiphead CH341 Single Port Serial Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to use a Winchiphead CH341 single port
+ 	  USB to serial adapter.
+@@ -109,7 +102,6 @@ config USB_SERIAL_CH341
+ 
+ config USB_SERIAL_WHITEHEAT
+ 	tristate "USB ConnectTech WhiteHEAT Serial Driver"
+-	depends on USB_SERIAL
+ 	select USB_EZUSB
+ 	help
+ 	  Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
+@@ -120,7 +112,6 @@ config USB_SERIAL_WHITEHEAT
+ 
+ config USB_SERIAL_DIGI_ACCELEPORT
+ 	tristate "USB Digi International AccelePort USB Serial Driver"
+-	depends on USB_SERIAL
+ 	---help---
+ 	  Say Y here if you want to use Digi AccelePort USB 2 or 4 devices,
+ 	  2 port (plus parallel port) and 4 port USB serial converters.  The
+@@ -135,7 +126,6 @@ config USB_SERIAL_DIGI_ACCELEPORT
+ 
+ config USB_SERIAL_CP2101
+ 	tristate "USB CP2101 UART Bridge Controller"
+-	depends on USB_SERIAL && EXPERIMENTAL
+ 	help
+ 	  Say Y here if you want to use a CP2101/CP2102 based USB to RS232
+ 	  converter.
+@@ -145,7 +135,6 @@ config USB_SERIAL_CP2101
+ 
+ config USB_SERIAL_CYPRESS_M8
+ 	tristate "USB Cypress M8 USB Serial Driver"
+-	depends on USB_SERIAL && EXPERIMENTAL
+ 	help
+ 	  Say Y here if you want to use a device that contains the Cypress
+ 	  USB to Serial microcontroller, such as the DeLorme Earthmate GPS.
+@@ -160,7 +149,6 @@ config USB_SERIAL_CYPRESS_M8
+ 
+ config USB_SERIAL_EMPEG
+ 	tristate "USB Empeg empeg-car Mark I/II Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to connect to your Empeg empeg-car Mark I/II
+ 	  mp3 player via USB.  The driver uses a single ttyUSB{0,1,2,...}
+@@ -171,8 +159,7 @@ config USB_SERIAL_EMPEG
+ 	  module will be called empeg.
+ 
+ config USB_SERIAL_FTDI_SIO
+-	tristate "USB FTDI Single Port Serial Driver (EXPERIMENTAL)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++	tristate "USB FTDI Single Port Serial Driver"
+ 	---help---
+ 	  Say Y here if you want to use a FTDI SIO single port USB to serial
+ 	  converter device. The implementation I have is called the USC-1000.
+@@ -186,7 +173,6 @@ config USB_SERIAL_FTDI_SIO
+ 
+ config USB_SERIAL_FUNSOFT
+ 	tristate "USB Fundamental Software Dongle Driver"
+-	depends on USB_SERIAL
+ 	---help---
+ 	  Say Y here if you want to use the Fundamental Software dongle.
+ 
+@@ -195,7 +181,6 @@ config USB_SERIAL_FUNSOFT
+ 
+ config USB_SERIAL_VISOR
+ 	tristate "USB Handspring Visor / Palm m50x / Sony Clie Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to connect to your HandSpring Visor, Palm
+ 	  m500 or m505 through its USB docking station. See
+@@ -207,7 +192,6 @@ config USB_SERIAL_VISOR
+ 
+ config USB_SERIAL_IPAQ
+ 	tristate "USB PocketPC PDA Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to connect to your Compaq iPAQ, HP Jornada
+ 	  or any other PDA running Windows CE 3.0 or PocketPC 2002
+@@ -218,8 +202,7 @@ config USB_SERIAL_IPAQ
+ 	  module will be called ipaq.
+ 
+ config USB_SERIAL_IR
+-	tristate "USB IR Dongle Serial Driver (EXPERIMENTAL)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++	tristate "USB IR Dongle Serial Driver"
+ 	help
+ 	  Say Y here if you want to enable simple serial support for USB IrDA
+ 	  devices.  This is useful if you do not want to use the full IrDA
+@@ -230,7 +213,6 @@ config USB_SERIAL_IR
+ 
+ config USB_SERIAL_EDGEPORT
+ 	tristate "USB Inside Out Edgeport Serial Driver"
+-	depends on USB_SERIAL
+ 	---help---
+ 	  Say Y here if you want to use any of the following devices from
+ 	  Inside Out Networks (Digi):
+@@ -256,7 +238,6 @@ config USB_SERIAL_EDGEPORT
+ 
+ config USB_SERIAL_EDGEPORT_TI
+ 	tristate "USB Inside Out Edgeport Serial Driver (TI devices)"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to use any of the devices from Inside Out
+ 	  Networks (Digi) that are not supported by the io_edgeport driver.
+@@ -267,7 +248,6 @@ config USB_SERIAL_EDGEPORT_TI
+ 
+ config USB_SERIAL_GARMIN
+        tristate "USB Garmin GPS driver"
+-       depends on USB_SERIAL
+        help
+          Say Y here if you want to connect to your Garmin GPS.
+          Should work with most Garmin GPS devices which have a native USB port.
+@@ -279,8 +259,7 @@ config USB_SERIAL_GARMIN
+          module will be called garmin_gps.
+ 
+ config USB_SERIAL_IPW
+-        tristate "USB IPWireless (3G UMTS TDD) Driver (EXPERIMENTAL)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++        tristate "USB IPWireless (3G UMTS TDD) Driver"
+ 	help
+ 	  Say Y here if you want to use a IPWireless USB modem such as
+ 	  the ones supplied by Axity3G/Sentech South Africa.
+@@ -289,8 +268,7 @@ config USB_SERIAL_IPW
+ 	  module will be called ipw.
+ 
+ config USB_SERIAL_IUU
+-	tristate "USB Infinity USB Unlimited Phoenix Driver (Experimental)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++	tristate "USB Infinity USB Unlimited Phoenix Driver"
+ 	help
+ 	  Say Y here if you want to use a IUU in phoenix mode and get
+ 	  an extra ttyUSBx device. More information available on
+@@ -301,7 +279,6 @@ config USB_SERIAL_IUU
+ 
+ config USB_SERIAL_KEYSPAN_PDA
+ 	tristate "USB Keyspan PDA Single Port Serial Driver"
+-	depends on USB_SERIAL
+ 	select USB_EZUSB
+ 	help
+ 	  Say Y here if you want to use a Keyspan PDA single port USB to
+@@ -405,8 +381,7 @@ config USB_SERIAL_KEYSPAN_USA49WLC
+ 	  Say Y here to include firmware for the USA-49WLC converter.
+ 
+ config USB_SERIAL_KLSI
+-	tristate "USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++	tristate "USB KL5KUSB105 (Palmconnect) Driver"
+ 	---help---
+ 	  Say Y here if you want to use a KL5KUSB105 - based single port
+ 	  serial adapter. The most widely known -- and currently the only
+@@ -422,7 +397,6 @@ config USB_SERIAL_KLSI
+ 
+ config USB_SERIAL_KOBIL_SCT
+         tristate "USB KOBIL chipcard reader"
+-        depends on USB_SERIAL
+         ---help---
+           Say Y here if you want to use one of the following KOBIL USB chipcard
+           readers:
+@@ -440,7 +414,6 @@ config USB_SERIAL_KOBIL_SCT
+ 
+ config USB_SERIAL_MCT_U232
+ 	tristate "USB MCT Single Port Serial Driver"
+-	depends on USB_SERIAL
+ 	---help---
+ 	  Say Y here if you want to use a USB Serial single port adapter from
+ 	  Magic Control Technology Corp. (U232 is one of the model numbers).
+@@ -453,7 +426,6 @@ config USB_SERIAL_MCT_U232
+ 
+ config USB_SERIAL_MOS7720
+ 	tristate "USB Moschip 7720 Serial Driver"
+-	depends on USB_SERIAL
+ 	---help---
+ 	  Say Y here if you want to use USB Serial single and double
+ 	  port adapters from Moschip Semiconductor Tech.
+@@ -463,7 +435,6 @@ config USB_SERIAL_MOS7720
+ 
+ config USB_SERIAL_MOS7840
+ 	tristate "USB Moschip 7840/7820 USB Serial Driver"
+-	depends on USB_SERIAL
+ 	---help---
+ 	  Say Y here if you want to use a MCS7840 Quad-Serial or MCS7820
+ 	  Dual-Serial port device from MosChip Semiconductor.
+@@ -478,14 +449,12 @@ config USB_SERIAL_MOS7840
+ 
+ config USB_SERIAL_NAVMAN
+ 	tristate "USB Navman GPS device"
+-	depends on USB_SERIAL
+ 	help
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called navman.
+ 
+ config USB_SERIAL_PL2303
+ 	tristate "USB Prolific 2303 Single Port Serial Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to use the PL2303 USB Serial single port
+ 	  adapter from Prolific.
+@@ -494,8 +463,7 @@ config USB_SERIAL_PL2303
+ 	  module will be called pl2303.
+ 
+ config USB_SERIAL_OTI6858
+-	tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller (EXPERIMENTAL)"
+-	depends on USB_SERIAL
++	tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller"
+ 	help
+ 	  Say Y here if you want to use the OTi-6858 single port USB to serial
+           converter device.
+@@ -503,9 +471,17 @@ config USB_SERIAL_OTI6858
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called oti6858.
+ 
++config USB_SERIAL_SPCP8X5
++	tristate "USB SPCP8x5 USB To Serial Driver"
++	help
++	  Say Y here if you want to use the spcp8x5 converter chip.  This is
++	  commonly found in some Z-Wave USB devices.
++
++	  To compile this driver as a module, choose M here: the
++	  module will be called spcp8x5.
++
+ config USB_SERIAL_HP4X
+         tristate "USB HP4x Calculators support"
+-        depends on USB_SERIAL
+         help
+           Say Y here if you want to use an Hewlett-Packard 4x Calculator.
+ 
+@@ -513,8 +489,7 @@ config USB_SERIAL_HP4X
+           module will be called hp4x.
+ 
+ config USB_SERIAL_SAFE
+-	tristate "USB Safe Serial (Encapsulated) Driver (EXPERIMENTAL)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++	tristate "USB Safe Serial (Encapsulated) Driver"
+ 
+ config USB_SERIAL_SAFE_PADDED
+ 	bool "USB Secure Encapsulated Driver - Padded"
+@@ -522,7 +497,6 @@ config USB_SERIAL_SAFE_PADDED
+ 
+ config USB_SERIAL_SIERRAWIRELESS
+ 	tristate "USB Sierra Wireless Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say M here if you want to use a Sierra Wireless device (if
+ 	  using an PC 5220 or AC580 please use the Airprime driver
+@@ -533,7 +507,6 @@ config USB_SERIAL_SIERRAWIRELESS
+ 
+ config USB_SERIAL_TI
+ 	tristate "USB TI 3410/5052 Serial Driver"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you want to use the TI USB 3410 or 5052
+ 	  serial devices.
+@@ -542,8 +515,7 @@ config USB_SERIAL_TI
+ 	  module will be called ti_usb_3410_5052.
+ 
+ config USB_SERIAL_CYBERJACK
+-	tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++	tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader"
+ 	---help---
+ 	  Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard
+ 	  reader. This is an interface to ISO 7816 compatible contact-based
+@@ -556,7 +528,6 @@ config USB_SERIAL_CYBERJACK
+ 
+ config USB_SERIAL_XIRCOM
+ 	tristate "USB Xircom / Entregra Single Port Serial Driver"
+-	depends on USB_SERIAL
+ 	select USB_EZUSB
+ 	help
+ 	  Say Y here if you want to use a Xircom or Entregra single port USB to
+@@ -568,7 +539,6 @@ config USB_SERIAL_XIRCOM
+ 
+ config USB_SERIAL_OPTION
+ 	tristate "USB driver for GSM and CDMA modems"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you have a GSM or CDMA modem that's connected to USB.
+ 
+@@ -586,8 +556,7 @@ config USB_SERIAL_OPTION
+ 	  it might be accessible via the FTDI_SIO driver.
+ 
+ config USB_SERIAL_OMNINET
+-	tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)"
+-	depends on USB_SERIAL && EXPERIMENTAL
++	tristate "USB ZyXEL omni.net LCD Plus Driver"
+ 	help
+ 	  Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA.
+ 
+@@ -596,7 +565,6 @@ config USB_SERIAL_OMNINET
+ 
+ config USB_SERIAL_DEBUG
+ 	tristate "USB Debugging Device"
+-	depends on USB_SERIAL
+ 	help
+ 	  Say Y here if you have a USB debugging device used to receive
+ 	  debugging data from another machine.  The most common of these
+diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
+index 0db109a..7568595 100644
+--- a/drivers/usb/serial/Makefile
++++ b/drivers/usb/serial/Makefile
+@@ -30,8 +30,8 @@ obj-$(CONFIG_USB_SERIAL_GARMIN)			+= garmin_gps.o
+ obj-$(CONFIG_USB_SERIAL_HP4X)			+= hp4x.o
+ obj-$(CONFIG_USB_SERIAL_IPAQ)			+= ipaq.o
+ obj-$(CONFIG_USB_SERIAL_IPW)			+= ipw.o
+-obj-$(CONFIG_USB_SERIAL_IUU)			+= iuu_phoenix.o
+ obj-$(CONFIG_USB_SERIAL_IR)			+= ir-usb.o
++obj-$(CONFIG_USB_SERIAL_IUU)			+= iuu_phoenix.o
+ obj-$(CONFIG_USB_SERIAL_KEYSPAN)		+= keyspan.o
+ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)		+= keyspan_pda.o
+ obj-$(CONFIG_USB_SERIAL_KLSI)			+= kl5kusb105.o
+@@ -46,6 +46,7 @@ obj-$(CONFIG_USB_SERIAL_OTI6858)		+= oti6858.o
+ obj-$(CONFIG_USB_SERIAL_PL2303)			+= pl2303.o
+ obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
+ obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS)		+= sierra.o
++obj-$(CONFIG_USB_SERIAL_SPCP8X5)		+= spcp8x5.o
+ obj-$(CONFIG_USB_SERIAL_TI)			+= ti_usb_3410_5052.o
+ obj-$(CONFIG_USB_SERIAL_VISOR)			+= visor.o
+ obj-$(CONFIG_USB_SERIAL_WHITEHEAT)		+= whiteheat.o
+diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
+index 1cd29cd..a238817 100644
+--- a/drivers/usb/serial/aircable.c
++++ b/drivers/usb/serial/aircable.c
+@@ -210,7 +210,7 @@ static void aircable_send(struct usb_serial_port *port)
+ 	struct aircable_private *priv = usb_get_serial_port_data(port);
+ 	unsigned char* buf;
+ 	u16 *dbuf;
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	if (port->write_urb_busy)
+ 		return;
+ 
+@@ -220,7 +220,7 @@ static void aircable_send(struct usb_serial_port *port)
+ 
+ 	buf = kzalloc(count + HCI_HEADER_LENGTH, GFP_ATOMIC);
+ 	if (!buf) {
+-		err("%s- kzalloc(%d) failed.", __FUNCTION__,
++		err("%s- kzalloc(%d) failed.", __func__,
+ 		    count + HCI_HEADER_LENGTH);
+ 		return;
+ 	}
+@@ -236,7 +236,7 @@ static void aircable_send(struct usb_serial_port *port)
+ 
+ 	kfree(buf);
+ 	port->write_urb_busy = 1;
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++	usb_serial_debug_data(debug, &port->dev, __func__,
+ 			      count + HCI_HEADER_LENGTH,
+ 			      port->write_urb->transfer_buffer);
+ 	port->write_urb->transfer_buffer_length = count + HCI_HEADER_LENGTH;
+@@ -246,7 +246,7 @@ static void aircable_send(struct usb_serial_port *port)
+ 	if (result) {
+ 		dev_err(&port->dev,
+ 			"%s - failed submitting write urb, error %d\n",
+-			__FUNCTION__, result);
++			__func__, result);
+ 		port->write_urb_busy = 0;
+ 	}
+ 
+@@ -275,7 +275,7 @@ static void aircable_read(struct work_struct *work)
+ 
+ 	if (!tty) {
+ 		schedule_work(&priv->rx_work);
+-		err("%s - No tty available", __FUNCTION__);
++		err("%s - No tty available", __func__);
+ 		return ;
+ 	}
+ 
+@@ -286,7 +286,7 @@ static void aircable_read(struct work_struct *work)
+ 
+ 	tty_prepare_flip_string(tty, &data, count);
+ 	if (!data){
+-		err("%s- kzalloc(%d) failed.", __FUNCTION__, count);
++		err("%s- kzalloc(%d) failed.", __func__, count);
+ 		return;
+ 	}
+ 
+@@ -332,7 +332,7 @@ static int aircable_attach (struct usb_serial *serial)
+ 
+ 	priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
+ 	if (!priv){
+-		err("%s- kmalloc(%Zd) failed.", __FUNCTION__,
++		err("%s- kmalloc(%Zd) failed.", __func__,
+ 			sizeof(struct aircable_private));
+ 		return -ENOMEM;
+ 	}
+@@ -366,7 +366,7 @@ static void aircable_shutdown(struct usb_serial *serial)
+ 	struct usb_serial_port *port = serial->port[0];
+ 	struct aircable_private *priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (priv) {
+ 		serial_buf_free(priv->tx_buf);
+@@ -388,12 +388,12 @@ static int aircable_write(struct usb_serial_port *port,
+ 	struct aircable_private *priv = usb_get_serial_port_data(port);
+ 	int temp;
+ 
+-	dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
++	dbg("%s - port %d, %d bytes", __func__, port->number, count);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, source);
+ 
+ 	if (!count){
+-		dbg("%s - write request of 0 bytes", __FUNCTION__);
++		dbg("%s - write request of 0 bytes", __func__);
+ 		return count;
+ 	}
+ 
+@@ -414,7 +414,7 @@ static void aircable_write_bulk_callback(struct urb *urb)
+ 	int status = urb->status;
+ 	int result;
+ 
+-	dbg("%s - urb status: %d", __FUNCTION__ , status);
++	dbg("%s - urb status: %d", __func__ , status);
+ 
+ 	/* This has been taken from cypress_m8.c cypress_write_int_callback */
+ 	switch (status) {
+@@ -426,21 +426,21 @@ static void aircable_write_bulk_callback(struct urb *urb)
+ 		case -ESHUTDOWN:
+ 			/* this urb is terminated, clean up */
+ 			dbg("%s - urb shutting down with status: %d",
+-			    __FUNCTION__, status);
++			    __func__, status);
+ 			port->write_urb_busy = 0;
+ 			return;
+ 		default:
+ 			/* error in the urb, so we have to resubmit it */
+-			dbg("%s - Overflow in write", __FUNCTION__);
++			dbg("%s - Overflow in write", __func__);
+ 			dbg("%s - nonzero write bulk status received: %d",
+-			    __FUNCTION__, status);
++			    __func__, status);
+ 			port->write_urb->transfer_buffer_length = 1;
+ 			port->write_urb->dev = port->serial->dev;
+ 			result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 			if (result)
+ 				dev_err(&urb->dev->dev,
+ 					"%s - failed resubmitting write urb, error %d\n",
+-					__FUNCTION__, result);
++					__func__, result);
+ 			else
+ 				return;
+ 	}
+@@ -460,17 +460,17 @@ static void aircable_read_bulk_callback(struct urb *urb)
+ 	unsigned char *temp;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+-		dbg("%s - urb status = %d", __FUNCTION__, status);
++		dbg("%s - urb status = %d", __func__, status);
+ 		if (!port->open_count) {
+-			dbg("%s - port is closed, exiting.", __FUNCTION__);
++			dbg("%s - port is closed, exiting.", __func__);
+ 			return;
+ 		}
+ 		if (status == -EPROTO) {
+ 			dbg("%s - caught -EPROTO, resubmitting the urb",
+-			    __FUNCTION__);
++			    __func__);
+ 			usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ 					  usb_rcvbulkpipe(port->serial->dev,
+ 					  		  port->bulk_in_endpointAddress),
+@@ -482,14 +482,14 @@ static void aircable_read_bulk_callback(struct urb *urb)
+ 			if (result)
+ 				dev_err(&urb->dev->dev,
+ 					"%s - failed resubmitting read urb, error %d\n",
+-					__FUNCTION__, result);
++					__func__, result);
+ 			return;
+ 		}
+-		dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
++		dbg("%s - unable to handle the error, exiting.", __func__);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++	usb_serial_debug_data(debug, &port->dev, __func__,
+ 				urb->actual_length,urb->transfer_buffer);
+ 
+ 	tty = port->tty;
+@@ -538,7 +538,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
+ 		if (result)
+ 			dev_err(&urb->dev->dev,
+ 				"%s - failed resubmitting read urb, error %d\n",
+-				__FUNCTION__, result);
++				__func__, result);
+ 	}
+ 
+ 	return;
+@@ -550,7 +550,7 @@ static void aircable_throttle(struct usb_serial_port *port)
+ 	struct aircable_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->rx_lock, flags);
+ 	priv->rx_flags |= THROTTLED;
+@@ -564,7 +564,7 @@ static void aircable_unthrottle(struct usb_serial_port *port)
+ 	int actually_throttled;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->rx_lock, flags);
+ 	actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
+diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
+index f156dba..725b6b9 100644
+--- a/drivers/usb/serial/airprime.c
++++ b/drivers/usb/serial/airprime.c
+@@ -53,7 +53,7 @@ static int airprime_send_setup(struct usb_serial_port *port)
+ 	struct usb_serial *serial = port->serial;
+ 	struct airprime_private *priv;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (port->number != 0)
+ 		return 0;
+@@ -83,14 +83,14 @@ static void airprime_read_bulk_callback(struct urb *urb)
+ 	int result;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	tty = port->tty;
+ 	if (tty && urb->actual_length) {
+@@ -101,7 +101,7 @@ static void airprime_read_bulk_callback(struct urb *urb)
+ 	result = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (result)
+ 		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+-			__FUNCTION__, result);
++			__func__, result);
+ 	return;
+ }
+ 
+@@ -112,14 +112,14 @@ static void airprime_write_bulk_callback(struct urb *urb)
+ 	int status = urb->status;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* free up the transfer buffer, as usb_free_urb() does not do this */
+ 	kfree (urb->transfer_buffer);
+ 
+ 	if (status)
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	--priv->outstanding_urbs;
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+@@ -136,7 +136,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
+ 	int i;
+ 	int result = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* initialize our private data structure if it isn't already created */
+ 	if (!priv) {
+@@ -157,7 +157,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
+ 		buffer = kmalloc(buffer_size, GFP_KERNEL);
+ 		if (!buffer) {
+ 			dev_err(&port->dev, "%s - out of memory.\n",
+-				__FUNCTION__);
++				__func__);
+ 			result = -ENOMEM;
+ 			goto errout;
+ 		}
+@@ -165,7 +165,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
+ 		if (!urb) {
+ 			kfree(buffer);
+ 			dev_err(&port->dev, "%s - no more urbs?\n",
+-				__FUNCTION__);
++				__func__);
+ 			result = -ENOMEM;
+ 			goto errout;
+ 		}
+@@ -180,7 +180,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
+ 			kfree(buffer);
+ 			dev_err(&port->dev,
+ 				"%s - failed submitting read urb %d for port %d, error %d\n",
+-				__FUNCTION__, i, port->number, result);
++				__func__, i, port->number, result);
+ 			goto errout;
+ 		}
+ 		/* remember this urb so we can kill it when the port is closed */
+@@ -212,7 +212,7 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
+ 	struct airprime_private *priv = usb_get_serial_port_data(port);
+ 	int i;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	priv->rts_state = 0;
+ 	priv->dtr_state = 0;
+@@ -242,12 +242,12 @@ static int airprime_write(struct usb_serial_port *port,
+ 	unsigned char *buffer;
+ 	unsigned long flags;
+ 	int status;
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (priv->outstanding_urbs > NUM_WRITE_URBS) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+-		dbg("%s - write limit hit\n", __FUNCTION__);
++		dbg("%s - write limit hit\n", __func__);
+ 		return 0;
+ 	}
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+@@ -264,7 +264,7 @@ static int airprime_write(struct usb_serial_port *port,
+ 	}
+ 	memcpy (buffer, buf, count);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+ 
+ 	usb_fill_bulk_urb(urb, serial->dev,
+ 			  usb_sndbulkpipe(serial->dev,
+@@ -277,7 +277,7 @@ static int airprime_write(struct usb_serial_port *port,
+ 	if (status) {
+ 		dev_err(&port->dev,
+ 			"%s - usb_submit_urb(write bulk) failed with status = %d\n",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		count = status;
+ 		kfree (buffer);
+ 	} else {
+@@ -306,9 +306,6 @@ static struct usb_serial_driver airprime_device = {
+ 	},
+ 	.usb_driver =		&airprime_driver,
+ 	.id_table =		id_table,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.open =			airprime_open,
+ 	.close =		airprime_close,
+ 	.write =		airprime_write,
+@@ -331,7 +328,7 @@ static int __init airprime_init(void)
+ 
+ static void __exit airprime_exit(void)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	usb_deregister(&airprime_driver);
+ 	usb_serial_deregister(&airprime_device);
+diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
+index fe2bfd6..599ab2e 100644
+--- a/drivers/usb/serial/ark3116.c
++++ b/drivers/usb/serial/ark3116.c
+@@ -173,7 +173,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
+ 
+ 	config = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (!priv->termios_initialized) {
+@@ -192,6 +192,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
+ 	buf = kmalloc(1, GFP_KERNEL);
+ 	if (!buf) {
+ 		dbg("error kmalloc");
++		*port->tty->termios = *old_termios;
+ 		return;
+ 	}
+ 
+@@ -323,7 +324,7 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
+ 	char *buf;
+ 	int result = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	buf = kmalloc(1, GFP_KERNEL);
+ 	if (!buf) {
+@@ -395,7 +396,7 @@ static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
+ 			return -EFAULT;
+ 		return 0;
+ 	default:
+-		dbg("%s cmd 0x%04x not supported", __FUNCTION__, cmd);
++		dbg("%s cmd 0x%04x not supported", __func__, cmd);
+ 		break;
+ 	}
+ 
+@@ -447,9 +448,6 @@ static struct usb_serial_driver ark3116_device = {
+ 	},
+ 	.id_table =		id_table,
+ 	.usb_driver =		&ark3116_driver,
+-	.num_interrupt_in =	1,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.attach =		ark3116_attach,
+ 	.set_termios =		ark3116_set_termios,
+diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
+index df0a2b3..0a322fc 100644
+--- a/drivers/usb/serial/belkin_sa.c
++++ b/drivers/usb/serial/belkin_sa.c
+@@ -128,9 +128,6 @@ static struct usb_serial_driver belkin_device = {
+ 	.description =		"Belkin / Peracom / GoHubs USB Serial Adapter",
+ 	.usb_driver =		&belkin_driver,
+ 	.id_table =		id_table_combined,
+-	.num_interrupt_in =	1,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.open =			belkin_sa_open,
+ 	.close =		belkin_sa_close,
+@@ -198,7 +195,7 @@ static void belkin_sa_shutdown (struct usb_serial *serial)
+ 	struct belkin_sa_private *priv;
+ 	int i;
+ 	
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	/* stop reads and writes on all ports */
+ 	for (i=0; i < serial->num_ports; ++i) {
+@@ -213,7 +210,7 @@ static int  belkin_sa_open (struct usb_serial_port *port, struct file *filp)
+ {
+ 	int retval = 0;
+ 
+-	dbg("%s port %d", __FUNCTION__, port->number);
++	dbg("%s port %d", __func__, port->number);
+ 
+ 	/*Start reading from the device*/
+ 	/* TODO: Look at possibility of submitting multiple URBs to device to
+@@ -240,7 +237,7 @@ exit:
+ 
+ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
+ {
+-	dbg("%s port %d", __FUNCTION__, port->number);
++	dbg("%s port %d", __func__, port->number);
+ 
+ 	/* shutdown our bulk reads and writes */
+ 	usb_kill_urb(port->write_urb);
+@@ -251,7 +248,7 @@ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
+ 
+ static void belkin_sa_read_int_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct belkin_sa_private *priv;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int retval;
+@@ -267,15 +264,15 @@ static void belkin_sa_read_int_callback (struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	default:
+ 		dbg("%s - nonzero urb status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		goto exit;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	/* Handle known interrupt data */
+ 	/* ignore data[0] and data[1] */
+@@ -334,7 +331,7 @@ exit:
+ 	retval = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (retval)
+ 		err ("%s - usb_submit_urb failed with result %d",
+-		     __FUNCTION__, retval);
++		     __func__, retval);
+ }
+ 
+ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+@@ -481,7 +478,7 @@ static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file)
+ 	unsigned long control_state;
+ 	unsigned long flags;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	control_state = priv->control_state;
+@@ -502,7 +499,7 @@ static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
+ 	int rts = 0;
+ 	int dtr = 0;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	control_state = priv->control_state;
+diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
+index 42582d4..d947d95 100644
+--- a/drivers/usb/serial/ch341.c
++++ b/drivers/usb/serial/ch341.c
+@@ -318,9 +318,6 @@ static struct usb_serial_driver ch341_device = {
+ 	},
+ 	.id_table         = id_table,
+ 	.usb_driver       = &ch341_driver,
+-	.num_interrupt_in = NUM_DONT_CARE,
+-	.num_bulk_in      = 1,
+-	.num_bulk_out     = 1,
+ 	.num_ports        = 1,
+ 	.open             = ch341_open,
+ 	.set_termios      = ch341_set_termios,
+diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
+index 66ce30c..201184c 100644
+--- a/drivers/usb/serial/console.c
++++ b/drivers/usb/serial/console.c
+@@ -67,7 +67,7 @@ static int usb_console_setup(struct console *co, char *options)
+ 	struct tty_struct *tty = NULL;
+ 	struct ktermios *termios = NULL, dummy;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	if (options) {
+ 		baud = simple_strtoul(options, NULL, 10);
+@@ -225,10 +225,10 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
+ 	if (count == 0)
+ 		return;
+ 
+-	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
++	dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
+ 
+ 	if (!port->open_count) {
+-		dbg ("%s - port not opened", __FUNCTION__);
++		dbg ("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+@@ -248,7 +248,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
+ 			retval = serial->type->write(port, buf, i);
+ 		else
+ 			retval = usb_serial_generic_write(port, buf, i);
+-		dbg("%s - return value : %d", __FUNCTION__, retval);
++		dbg("%s - return value : %d", __func__, retval);
+ 		if (lf) {
+ 			/* append CR after LF */
+ 			unsigned char cr = 13;
+@@ -256,7 +256,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
+ 				retval = serial->type->write(port, &cr, 1);
+ 			else
+ 				retval = usb_serial_generic_write(port, &cr, 1);
+-			dbg("%s - return value : %d", __FUNCTION__, retval);
++			dbg("%s - return value : %d", __func__, retval);
+ 		}
+ 		buf += i;
+ 		count -= i;
+diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
+index 324bb61..dc0ea08 100644
+--- a/drivers/usb/serial/cp2101.c
++++ b/drivers/usb/serial/cp2101.c
+@@ -53,9 +53,11 @@ static void cp2101_shutdown(struct usb_serial*);
+ static int debug;
+ 
+ static struct usb_device_id id_table [] = {
++	{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
+ 	{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
+ 	{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
+ 	{ USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
++	{ USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
+ 	{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
+ 	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
+ 	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
+@@ -71,6 +73,7 @@ static struct usb_device_id id_table [] = {
+ 	{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
+ 	{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+ 	{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
++	{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
+ 	{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
+ 	{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
+ 	{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
+@@ -106,9 +109,6 @@ static struct usb_serial_driver cp2101_device = {
+ 	},
+ 	.usb_driver		= &cp2101_driver,
+ 	.id_table		= id_table,
+-	.num_interrupt_in	= 0,
+-	.num_bulk_in		= NUM_DONT_CARE,
+-	.num_bulk_out		= NUM_DONT_CARE,
+ 	.num_ports		= 1,
+ 	.open			= cp2101_open,
+ 	.close			= cp2101_close,
+@@ -193,7 +193,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
+ 
+ 	buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
+ 	if (!buf) {
+-		dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
++		dev_err(&port->dev, "%s - out of memory.\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -214,7 +214,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
+ 	if (result != size) {
+ 		dev_err(&port->dev, "%s - Unable to send config request, "
+ 				"request=0x%x size=%d result=%d\n",
+-				__FUNCTION__, request, size, result);
++				__func__, request, size, result);
+ 		return -EPROTO;
+ 	}
+ 
+@@ -240,7 +240,7 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
+ 	buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
+ 	if (!buf) {
+ 		dev_err(&port->dev, "%s - out of memory.\n",
+-				__FUNCTION__);
++				__func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -265,7 +265,7 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
+ 	if ((size > 2 && result != size) || result < 0) {
+ 		dev_err(&port->dev, "%s - Unable to send request, "
+ 				"request=0x%x size=%d result=%d\n",
+-				__FUNCTION__, request, size, result);
++				__func__, request, size, result);
+ 		return -EPROTO;
+ 	}
+ 
+@@ -293,11 +293,11 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+ 	struct usb_serial *serial = port->serial;
+ 	int result;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) {
+ 		dev_err(&port->dev, "%s - Unable to enable UART\n",
+-				__FUNCTION__);
++				__func__);
+ 		return -EPROTO;
+ 	}
+ 
+@@ -312,7 +312,7 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+ 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (result) {
+ 		dev_err(&port->dev, "%s - failed resubmitting read urb, "
+-				"error %d\n", __FUNCTION__, result);
++				"error %d\n", __func__, result);
+ 		return result;
+ 	}
+ 
+@@ -329,7 +329,7 @@ static void cp2101_cleanup (struct usb_serial_port *port)
+ {
+ 	struct usb_serial *serial = port->serial;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (serial->dev) {
+ 		/* shutdown any bulk reads that might be going on */
+@@ -342,10 +342,10 @@ static void cp2101_cleanup (struct usb_serial_port *port)
+ 
+ static void cp2101_close (struct usb_serial_port *port, struct file * filp)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* shutdown our urbs */
+-	dbg("%s - shutting down urbs", __FUNCTION__);
++	dbg("%s - shutting down urbs", __func__);
+ 	usb_kill_urb(port->write_urb);
+ 	usb_kill_urb(port->read_urb);
+ 
+@@ -367,10 +367,10 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ 	int baud;
+ 	int bits;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->tty || !port->tty->termios) {
+-		dbg("%s - no tty structures", __FUNCTION__);
++		dbg("%s - no tty structures", __func__);
+ 		return;
+ 	}
+ 
+@@ -379,7 +379,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ 	if (baud)
+ 		baud = BAUD_RATE_GEN_FREQ / baud;
+ 
+-	dbg("%s - baud rate = %d", __FUNCTION__, baud);
++	dbg("%s - baud rate = %d", __func__, baud);
+ 
+ 	tty_encode_baud_rate(port->tty, baud, baud);
+ 	cflag = port->tty->termios->c_cflag;
+@@ -388,24 +388,24 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ 	cflag &= ~CSIZE;
+ 	switch(bits & BITS_DATA_MASK) {
+ 		case BITS_DATA_5:
+-			dbg("%s - data bits = 5", __FUNCTION__);
++			dbg("%s - data bits = 5", __func__);
+ 			cflag |= CS5;
+ 			break;
+ 		case BITS_DATA_6:
+-			dbg("%s - data bits = 6", __FUNCTION__);
++			dbg("%s - data bits = 6", __func__);
+ 			cflag |= CS6;
+ 			break;
+ 		case BITS_DATA_7:
+-			dbg("%s - data bits = 7", __FUNCTION__);
++			dbg("%s - data bits = 7", __func__);
+ 			cflag |= CS7;
+ 			break;
+ 		case BITS_DATA_8:
+-			dbg("%s - data bits = 8", __FUNCTION__);
++			dbg("%s - data bits = 8", __func__);
+ 			cflag |= CS8;
+ 			break;
+ 		case BITS_DATA_9:
+ 			dbg("%s - data bits = 9 (not supported, "
+-					"using 8 data bits)", __FUNCTION__);
++					"using 8 data bits)", __func__);
+ 			cflag |= CS8;
+ 			bits &= ~BITS_DATA_MASK;
+ 			bits |= BITS_DATA_8;
+@@ -413,7 +413,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ 			break;
+ 		default:
+ 			dbg("%s - Unknown number of data bits, "
+-					"using 8", __FUNCTION__);
++					"using 8", __func__);
+ 			cflag |= CS8;
+ 			bits &= ~BITS_DATA_MASK;
+ 			bits |= BITS_DATA_8;
+@@ -423,35 +423,35 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ 
+ 	switch(bits & BITS_PARITY_MASK) {
+ 		case BITS_PARITY_NONE:
+-			dbg("%s - parity = NONE", __FUNCTION__);
++			dbg("%s - parity = NONE", __func__);
+ 			cflag &= ~PARENB;
+ 			break;
+ 		case BITS_PARITY_ODD:
+-			dbg("%s - parity = ODD", __FUNCTION__);
++			dbg("%s - parity = ODD", __func__);
+ 			cflag |= (PARENB|PARODD);
+ 			break;
+ 		case BITS_PARITY_EVEN:
+-			dbg("%s - parity = EVEN", __FUNCTION__);
++			dbg("%s - parity = EVEN", __func__);
+ 			cflag &= ~PARODD;
+ 			cflag |= PARENB;
+ 			break;
+ 		case BITS_PARITY_MARK:
+ 			dbg("%s - parity = MARK (not supported, "
+-					"disabling parity)", __FUNCTION__);
++					"disabling parity)", __func__);
+ 			cflag &= ~PARENB;
+ 			bits &= ~BITS_PARITY_MASK;
+ 			cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ 			break;
+ 		case BITS_PARITY_SPACE:
+ 			dbg("%s - parity = SPACE (not supported, "
+-					"disabling parity)", __FUNCTION__);
++					"disabling parity)", __func__);
+ 			cflag &= ~PARENB;
+ 			bits &= ~BITS_PARITY_MASK;
+ 			cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ 			break;
+ 		default:
+ 			dbg("%s - Unknown parity mode, "
+-					"disabling parity", __FUNCTION__);
++					"disabling parity", __func__);
+ 			cflag &= ~PARENB;
+ 			bits &= ~BITS_PARITY_MASK;
+ 			cp2101_set_config(port, CP2101_BITS, &bits, 2);
+@@ -461,21 +461,21 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ 	cflag &= ~CSTOPB;
+ 	switch(bits & BITS_STOP_MASK) {
+ 		case BITS_STOP_1:
+-			dbg("%s - stop bits = 1", __FUNCTION__);
++			dbg("%s - stop bits = 1", __func__);
+ 			break;
+ 		case BITS_STOP_1_5:
+ 			dbg("%s - stop bits = 1.5 (not supported, "
+-					"using 1 stop bit)", __FUNCTION__);
++					"using 1 stop bit)", __func__);
+ 			bits &= ~BITS_STOP_MASK;
+ 			cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ 			break;
+ 		case BITS_STOP_2:
+-			dbg("%s - stop bits = 2", __FUNCTION__);
++			dbg("%s - stop bits = 2", __func__);
+ 			cflag |= CSTOPB;
+ 			break;
+ 		default:
+ 			dbg("%s - Unknown number of stop bits, "
+-					"using 1 stop bit", __FUNCTION__);
++					"using 1 stop bit", __func__);
+ 			bits &= ~BITS_STOP_MASK;
+ 			cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ 			break;
+@@ -483,10 +483,10 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ 
+ 	cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+ 	if (modem_ctl[0] & 0x0008) {
+-		dbg("%s - flow control = CRTSCTS", __FUNCTION__);
++		dbg("%s - flow control = CRTSCTS", __func__);
+ 		cflag |= CRTSCTS;
+ 	} else {
+-		dbg("%s - flow control = NONE", __FUNCTION__);
++		dbg("%s - flow control = NONE", __func__);
+ 		cflag &= ~CRTSCTS;
+ 	}
+ 
+@@ -500,10 +500,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ 	int baud=0, bits;
+ 	unsigned int modem_ctl[4];
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->tty || !port->tty->termios) {
+-		dbg("%s - no tty structures", __FUNCTION__);
++		dbg("%s - no tty structures", __func__);
+ 		return;
+ 	}
+ 	port->tty->termios->c_cflag &= ~CMSPAR;
+@@ -542,7 +542,7 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ 		}
+ 
+ 		if (baud) {
+-			dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
++			dbg("%s - Setting baud rate to %d baud", __func__,
+ 					baud);
+ 			if (cp2101_set_config_single(port, CP2101_BAUDRATE,
+ 						(BAUD_RATE_GEN_FREQ / baud))) {
+@@ -562,23 +562,23 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ 		switch (cflag & CSIZE) {
+ 			case CS5:
+ 				bits |= BITS_DATA_5;
+-				dbg("%s - data bits = 5", __FUNCTION__);
++				dbg("%s - data bits = 5", __func__);
+ 				break;
+ 			case CS6:
+ 				bits |= BITS_DATA_6;
+-				dbg("%s - data bits = 6", __FUNCTION__);
++				dbg("%s - data bits = 6", __func__);
+ 				break;
+ 			case CS7:
+ 				bits |= BITS_DATA_7;
+-				dbg("%s - data bits = 7", __FUNCTION__);
++				dbg("%s - data bits = 7", __func__);
+ 				break;
+ 			case CS8:
+ 				bits |= BITS_DATA_8;
+-				dbg("%s - data bits = 8", __FUNCTION__);
++				dbg("%s - data bits = 8", __func__);
+ 				break;
+ 			/*case CS9:
+ 			 	bits |= BITS_DATA_9;
+-				dbg("%s - data bits = 9", __FUNCTION__);
++				dbg("%s - data bits = 9", __func__);
+ 				break;*/
+ 			default:
+ 				dev_err(&port->dev, "cp2101 driver does not "
+@@ -598,10 +598,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ 		if (cflag & PARENB) {
+ 			if (cflag & PARODD) {
+ 				bits |= BITS_PARITY_ODD;
+-				dbg("%s - parity = ODD", __FUNCTION__);
++				dbg("%s - parity = ODD", __func__);
+ 			} else {
+ 				bits |= BITS_PARITY_EVEN;
+-				dbg("%s - parity = EVEN", __FUNCTION__);
++				dbg("%s - parity = EVEN", __func__);
+ 			}
+ 		}
+ 		if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
+@@ -614,10 +614,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ 		bits &= ~BITS_STOP_MASK;
+ 		if (cflag & CSTOPB) {
+ 			bits |= BITS_STOP_2;
+-			dbg("%s - stop bits = 2", __FUNCTION__);
++			dbg("%s - stop bits = 2", __func__);
+ 		} else {
+ 			bits |= BITS_STOP_1;
+-			dbg("%s - stop bits = 1", __FUNCTION__);
++			dbg("%s - stop bits = 1", __func__);
+ 		}
+ 		if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
+ 			dev_err(&port->dev, "Number of stop bits requested "
+@@ -627,23 +627,23 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ 	if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
+ 		cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+ 		dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
+-				__FUNCTION__, modem_ctl[0], modem_ctl[1],
++				__func__, modem_ctl[0], modem_ctl[1],
+ 				modem_ctl[2], modem_ctl[3]);
+ 
+ 		if (cflag & CRTSCTS) {
+ 			modem_ctl[0] &= ~0x7B;
+ 			modem_ctl[0] |= 0x09;
+ 			modem_ctl[1] = 0x80;
+-			dbg("%s - flow control = CRTSCTS", __FUNCTION__);
++			dbg("%s - flow control = CRTSCTS", __func__);
+ 		} else {
+ 			modem_ctl[0] &= ~0x7B;
+ 			modem_ctl[0] |= 0x01;
+ 			modem_ctl[1] |= 0x40;
+-			dbg("%s - flow control = NONE", __FUNCTION__);
++			dbg("%s - flow control = NONE", __func__);
+ 		}
+ 
+ 		dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
+-				__FUNCTION__, modem_ctl[0], modem_ctl[1],
++				__func__, modem_ctl[0], modem_ctl[1],
+ 				modem_ctl[2], modem_ctl[3]);
+ 		cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+ 	}
+@@ -655,7 +655,7 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
+ {
+ 	int control = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (set & TIOCM_RTS) {
+ 		control |= CONTROL_RTS;
+@@ -674,7 +674,7 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
+ 		control |= CONTROL_WRITE_DTR;
+ 	}
+ 
+-	dbg("%s - control = 0x%.4x", __FUNCTION__, control);
++	dbg("%s - control = 0x%.4x", __func__, control);
+ 
+ 	return cp2101_set_config(port, CP2101_CONTROL, &control, 2);
+ 
+@@ -684,7 +684,7 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
+ {
+ 	int control, result;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	cp2101_get_config(port, CP2101_CONTROL, &control, 1);
+ 
+@@ -695,7 +695,7 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
+ 		|((control & CONTROL_RING)? TIOCM_RI  : 0)
+ 		|((control & CONTROL_DCD) ? TIOCM_CD  : 0);
+ 
+-	dbg("%s - control = 0x%.2x", __FUNCTION__, control);
++	dbg("%s - control = 0x%.2x", __func__, control);
+ 
+ 	return result;
+ }
+@@ -704,12 +704,12 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
+ {
+ 	int state;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	if (break_state == 0)
+ 		state = BREAK_OFF;
+ 	else
+ 		state = BREAK_ON;
+-	dbg("%s - turning break %s", __FUNCTION__,
++	dbg("%s - turning break %s", __func__,
+ 			state==BREAK_OFF ? "off" : "on");
+ 	cp2101_set_config(port, CP2101_BREAK, &state, 2);
+ }
+@@ -725,7 +725,7 @@ static void cp2101_shutdown (struct usb_serial *serial)
+ {
+ 	int i;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* Stop reads and writes on all ports */
+ 	for (i=0; i < serial->num_ports; ++i) {
+diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
+index 8d9b045..c164e2c 100644
+--- a/drivers/usb/serial/cyberjack.c
++++ b/drivers/usb/serial/cyberjack.c
+@@ -90,9 +90,6 @@ static struct usb_serial_driver cyberjack_device = {
+ 	.description =		"Reiner SCT Cyberjack USB card reader",
+ 	.usb_driver = 		&cyberjack_driver,
+ 	.id_table =		id_table,
+-	.num_interrupt_in =	1,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.attach =		cyberjack_startup,
+ 	.shutdown =		cyberjack_shutdown,
+@@ -119,7 +116,7 @@ static int cyberjack_startup (struct usb_serial *serial)
+ 	struct cyberjack_private *priv;
+ 	int i;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* allocate the private data structure */
+ 	priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
+@@ -142,7 +139,7 @@ static int cyberjack_startup (struct usb_serial *serial)
+ 					GFP_KERNEL);
+ 		if (result)
+ 			err(" usb_submit_urb(read int) failed");
+-		dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
++		dbg("%s - usb_submit_urb(int urb)", __func__);
+ 	}
+ 
+ 	return( 0 );
+@@ -152,9 +149,9 @@ static void cyberjack_shutdown (struct usb_serial *serial)
+ {
+ 	int i;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+-	for (i=0; i < serial->num_ports; ++i) {
++	for (i = 0; i < serial->num_ports; ++i) {
+ 		usb_kill_urb(serial->port[i]->interrupt_in_urb);
+ 		/* My special items, the standard routines free my urbs */
+ 		kfree(usb_get_serial_port_data(serial->port[i]));
+@@ -168,9 +165,9 @@ static int  cyberjack_open (struct usb_serial_port *port, struct file *filp)
+ 	unsigned long flags;
+ 	int result = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+-	dbg("%s - usb_clear_halt", __FUNCTION__ );
++	dbg("%s - usb_clear_halt", __func__ );
+ 	usb_clear_halt(port->serial->dev, port->write_urb->pipe);
+ 
+ 	/* force low_latency on so that our tty_push actually forces
+@@ -191,7 +188,7 @@ static int  cyberjack_open (struct usb_serial_port *port, struct file *filp)
+ 
+ static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (port->serial->dev) {
+ 		/* shutdown any bulk reads that might be going on */
+@@ -208,17 +205,17 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+ 	int result;
+ 	int wrexpected;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (count == 0) {
+-		dbg("%s - write request of 0 bytes", __FUNCTION__);
+-		return (0);
++		dbg("%s - write request of 0 bytes", __func__);
++		return 0;
+ 	}
+ 
+ 	spin_lock_bh(&port->lock);
+ 	if (port->write_urb_busy) {
+ 		spin_unlock_bh(&port->lock);
+-		dbg("%s - already writing", __FUNCTION__);
++		dbg("%s - already writing", __func__);
+ 		return 0;
+ 	}
+ 	port->write_urb_busy = 1;
+@@ -226,24 +223,24 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+-	if( (count+priv->wrfilled)>sizeof(priv->wrbuf) ) {
++	if( (count+priv->wrfilled) > sizeof(priv->wrbuf) ) {
+ 		/* To much data for buffer. Reset buffer. */
+-		priv->wrfilled=0;
+-		spin_unlock_irqrestore(&priv->lock, flags);
++		priv->wrfilled = 0;
+ 		port->write_urb_busy = 0;
+-		return (0);
++		spin_unlock_irqrestore(&priv->lock, flags);
++		return 0;
+ 	}
+ 
+ 	/* Copy data */
+ 	memcpy (priv->wrbuf+priv->wrfilled, buf, count);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
++	usb_serial_debug_data(debug, &port->dev, __func__, count,
+ 		priv->wrbuf+priv->wrfilled);
+ 	priv->wrfilled += count;
+ 
+ 	if( priv->wrfilled >= 3 ) {
+ 		wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
+-		dbg("%s - expected data: %d", __FUNCTION__, wrexpected);
++		dbg("%s - expected data: %d", __func__, wrexpected);
+ 	} else {
+ 		wrexpected = sizeof(priv->wrbuf);
+ 	}
+@@ -252,7 +249,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+ 		/* We have enough data to begin transmission */
+ 		int length;
+ 
+-		dbg("%s - transmitting data (frame 1)", __FUNCTION__);
++		dbg("%s - transmitting data (frame 1)", __func__);
+ 		length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected;
+ 
+ 		memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length );
+@@ -270,23 +267,23 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+ 		/* send the data out the bulk port */
+ 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 		if (result) {
+-			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++			err("%s - failed submitting write urb, error %d", __func__, result);
+ 			/* Throw away data. No better idea what to do with it. */
+-			priv->wrfilled=0;
+-			priv->wrsent=0;
++			priv->wrfilled = 0;
++			priv->wrsent = 0;
+ 			spin_unlock_irqrestore(&priv->lock, flags);
+ 			port->write_urb_busy = 0;
+ 			return 0;
+ 		}
+ 
+-		dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent);
+-		dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled);
++		dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
++		dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+ 
+ 		if( priv->wrsent>=priv->wrfilled ) {
+-			dbg("%s - buffer cleaned", __FUNCTION__);
++			dbg("%s - buffer cleaned", __func__);
+ 			memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+-			priv->wrfilled=0;
+-			priv->wrsent=0;
++			priv->wrfilled = 0;
++			priv->wrsent = 0;
+ 		}
+ 	}
+ 
+@@ -297,27 +294,28 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+ 
+ static int cyberjack_write_room( struct usb_serial_port *port )
+ {
++	/* FIXME: .... */
+ 	return CYBERJACK_LOCAL_BUF_SIZE;
+ }
+ 
+ static void cyberjack_read_int_callback( struct urb *urb )
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int status = urb->status;
+ 	int result;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* the urb might have been killed. */
+ 	if (status)
+ 		return;
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	/* React only to interrupts signaling a bulk_in transfer */
+-	if( (urb->actual_length==4) && (data[0]==0x01) ) {
++	if( (urb->actual_length == 4) && (data[0] == 0x01) ) {
+ 		short old_rdtodo;
+ 
+ 		/* This is a announcement of coming bulk_ins. */
+@@ -336,7 +334,7 @@ static void cyberjack_read_int_callback( struct urb *urb )
+ 		/* "+=" is probably more fault tollerant than "=" */
+ 		priv->rdtodo += size;
+ 
+-		dbg("%s - rdtodo: %d", __FUNCTION__, priv->rdtodo);
++		dbg("%s - rdtodo: %d", __func__, priv->rdtodo);
+ 
+ 		spin_unlock(&priv->lock);
+ 
+@@ -344,8 +342,8 @@ static void cyberjack_read_int_callback( struct urb *urb )
+ 			port->read_urb->dev = port->serial->dev;
+ 			result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 			if( result )
+-				err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+-			dbg("%s - usb_submit_urb(read urb)", __FUNCTION__);
++				err("%s - failed resubmitting read urb, error %d", __func__, result);
++			dbg("%s - usb_submit_urb(read urb)", __func__);
+ 		}
+ 	}
+ 
+@@ -354,12 +352,12 @@ resubmit:
+ 	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ 	if (result)
+ 		err(" usb_submit_urb(read int) failed");
+-	dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
++	dbg("%s - usb_submit_urb(int urb)", __func__);
+ }
+ 
+ static void cyberjack_read_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
+ 	struct tty_struct *tty;
+ 	unsigned char *data = urb->transfer_buffer;
+@@ -367,18 +365,18 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
+ 	int result;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - ignoring since device not open\n", __FUNCTION__);
++		dbg("%s - ignoring since device not open\n", __func__);
+ 		return;
+ 	}
+ 	if (urb->actual_length) {
+@@ -397,30 +395,30 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
+ 
+ 	spin_unlock(&priv->lock);
+ 
+-	dbg("%s - rdtodo: %d", __FUNCTION__, todo);
++	dbg("%s - rdtodo: %d", __func__, todo);
+ 
+ 	/* Continue to read if we have still urbs to do. */
+ 	if( todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
+ 		port->read_urb->dev = port->serial->dev;
+ 		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 		if (result)
+-			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+-		dbg("%s - usb_submit_urb(read urb)", __FUNCTION__);
++			err("%s - failed resubmitting read urb, error %d", __func__, result);
++		dbg("%s - usb_submit_urb(read urb)", __func__);
+ 	}
+ }
+ 
+ static void cyberjack_write_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	port->write_urb_busy = 0;
+ 	if (status) {
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+@@ -430,7 +428,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
+ 	if( priv->wrfilled ) {
+ 		int length, blksize, result;
+ 
+-		dbg("%s - transmitting data (frame n)", __FUNCTION__);
++		dbg("%s - transmitting data (frame n)", __func__);
+ 
+ 		length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
+ 			port->bulk_out_size : (priv->wrfilled - priv->wrsent);
+@@ -451,23 +449,23 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
+ 		/* send the data out the bulk port */
+ 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 		if (result) {
+-			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++			err("%s - failed submitting write urb, error %d", __func__, result);
+ 			/* Throw away data. No better idea what to do with it. */
+-			priv->wrfilled=0;
+-			priv->wrsent=0;
++			priv->wrfilled = 0;
++			priv->wrsent = 0;
+ 			goto exit;
+ 		}
+ 
+-		dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent);
+-		dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled);
++		dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
++		dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+ 
+ 		blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
+ 
+ 		if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) {
+-			dbg("%s - buffer cleaned", __FUNCTION__);
++			dbg("%s - buffer cleaned", __func__);
+ 			memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+-			priv->wrfilled=0;
+-			priv->wrsent=0;
++			priv->wrfilled = 0;
++			priv->wrsent = 0;
+ 		}
+ 	}
+ 
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 779d078..3212179 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -122,6 +122,11 @@ static struct usb_driver cypress_driver = {
+ 	.no_dynamic_id = 	1,
+ };
+ 
++enum packet_format {
++	packet_format_1,  /* b0:status, b1:payload count */
++	packet_format_2   /* b0[7:3]:status, b0[2:0]:payload count */
++};
++
+ struct cypress_private {
+ 	spinlock_t lock;		   /* private lock */
+ 	int chiptype;			   /* identifier of device, for quirks/etc */
+@@ -139,8 +144,9 @@ struct cypress_private {
+ 	__u8 current_status;	   	   /* received from last read - info on dsr,cts,cd,ri,etc */
+ 	__u8 current_config;	   	   /* stores the current configuration byte */
+ 	__u8 rx_flags;			   /* throttling - used from whiteheat/ftdi_sio */
++	enum packet_format pkt_fmt;	   /* format to use for packet send / receive */
++	int get_cfg_unsafe;		   /* If true, the CYPRESS_GET_CONFIG is unsafe */
+ 	int baud_rate;			   /* stores current baud rate in integer form */
+-	int cbr_mask;			   /* stores current baud rate in masked form */
+ 	int isthrottled;		   /* if throttled, discard reads */
+ 	wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
+ 	char prev_status, diff_status;	   /* used for TIOCMIWAIT */
+@@ -176,9 +182,6 @@ static void cypress_unthrottle		(struct usb_serial_port *port);
+ static void cypress_set_dead		(struct usb_serial_port *port);
+ static void cypress_read_int_callback	(struct urb *urb);
+ static void cypress_write_int_callback	(struct urb *urb);
+-/* baud helper functions */
+-static int	 mask_to_rate		(unsigned mask);
+-static unsigned  rate_to_mask		(int rate);
+ /* write buffer functions */
+ static struct cypress_buf *cypress_buf_alloc(unsigned int size);
+ static void 		  cypress_buf_free(struct cypress_buf *cb);
+@@ -197,10 +200,6 @@ static struct usb_serial_driver cypress_earthmate_device = {
+ 	.description =			"DeLorme Earthmate USB",
+ 	.usb_driver = 			&cypress_driver,
+ 	.id_table =			id_table_earthmate,
+-	.num_interrupt_in = 		1,
+-	.num_interrupt_out =		1,
+-	.num_bulk_in =			NUM_DONT_CARE,
+-	.num_bulk_out =			NUM_DONT_CARE,
+ 	.num_ports =			1,
+ 	.attach =			cypress_earthmate_startup,
+ 	.shutdown =			cypress_shutdown,
+@@ -227,10 +226,6 @@ static struct usb_serial_driver cypress_hidcom_device = {
+ 	.description =			"HID->COM RS232 Adapter",
+ 	.usb_driver = 			&cypress_driver,
+ 	.id_table =			id_table_cyphidcomrs232,
+-	.num_interrupt_in =		1,
+-	.num_interrupt_out =		1,
+-	.num_bulk_in =			NUM_DONT_CARE,
+-	.num_bulk_out =			NUM_DONT_CARE,
+ 	.num_ports =			1,
+ 	.attach =			cypress_hidcom_startup,
+ 	.shutdown =			cypress_shutdown,
+@@ -257,10 +252,6 @@ static struct usb_serial_driver cypress_ca42v2_device = {
+ 	.description =			"Nokia CA-42 V2 Adapter",
+ 	.usb_driver = 			&cypress_driver,
+ 	.id_table =			id_table_nokiaca42v2,
+-	.num_interrupt_in =		1,
+-	.num_interrupt_out =		1,
+-	.num_bulk_in =			NUM_DONT_CARE,
+-	.num_bulk_out =			NUM_DONT_CARE,
+ 	.num_ports =			1,
+ 	.attach =			cypress_ca42v2_startup,
+ 	.shutdown =			cypress_shutdown,
+@@ -284,16 +275,62 @@ static struct usb_serial_driver cypress_ca42v2_device = {
+  *****************************************************************************/
+ 
+ 
++static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
++{
++	struct cypress_private *priv;
++	priv = usb_get_serial_port_data(port);
++
++	/*
++	 * The general purpose firmware for the Cypress M8 allows for
++	 * a maximum speed of 57600bps (I have no idea whether DeLorme
++	 * chose to use the general purpose firmware or not), if you
++	 * need to modify this speed setting for your own project
++	 * please add your own chiptype and modify the code likewise.
++	 * The Cypress HID->COM device will work successfully up to
++	 * 115200bps (but the actual throughput is around 3kBps).
++	 */
++	if (port->serial->dev->speed == USB_SPEED_LOW) {
++		/*
++		 * Mike Isely <isely at pobox.com> 2-Feb-2008: The
++		 * Cypress app note that describes this mechanism
++		 * states the the low-speed part can't handle more
++		 * than 800 bytes/sec, in which case 4800 baud is the
++		 * safest speed for a part like that.
++		 */
++		if (new_rate > 4800) {
++			dbg("%s - failed setting baud rate, device incapable "
++			    "speed %d", __func__, new_rate);
++			return -1;
++		}
++	}
++	switch (priv->chiptype) {
++	case CT_EARTHMATE:
++		if (new_rate <= 600) {
++			/* 300 and 600 baud rates are supported under
++			 * the generic firmware, but are not used with
++			 * NMEA and SiRF protocols */
++			dbg("%s - failed setting baud rate, unsupported speed "
++			    "of %d on Earthmate GPS", __func__, new_rate);
++			return -1;
++		}
++		break;
++	default:
++		break;
++	}
++	return new_rate;
++}
++
++
+ /* This function can either set or retrieve the current serial line settings */
+-static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits,
++static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits,
+ 				   int parity_enable, int parity_type, int reset, int cypress_request_type)
+ {
+ 	int new_baudrate = 0, retval = 0, tries = 0;
+ 	struct cypress_private *priv;
+-	__u8 feature_buffer[8];
++	__u8 feature_buffer[5];
+ 	unsigned long flags;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	
+ 	priv = usb_get_serial_port_data(port);
+ 
+@@ -302,58 +339,23 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
+ 
+ 	switch(cypress_request_type) {
+ 		case CYPRESS_SET_CONFIG:
+-
+-			/*
+-			 * The general purpose firmware for the Cypress M8 allows for a maximum speed
+- 			 * of 57600bps (I have no idea whether DeLorme chose to use the general purpose
+-			 * firmware or not), if you need to modify this speed setting for your own
+-			 * project please add your own chiptype and modify the code likewise.  The
+-			 * Cypress HID->COM device will work successfully up to 115200bps (but the
+-			 * actual throughput is around 3kBps).
+-			 */
+-			if (baud_mask != priv->cbr_mask) {
+-				dbg("%s - baud rate is changing", __FUNCTION__);
+-				if ( priv->chiptype == CT_EARTHMATE ) {
+-					/* 300 and 600 baud rates are supported under the generic firmware,
+-					 * but are not used with NMEA and SiRF protocols */
+-					
+-					if ( (baud_mask == B300) || (baud_mask == B600) ) {
+-						err("%s - failed setting baud rate, unsupported speed",
+-						    __FUNCTION__);
+-						new_baudrate = priv->baud_rate;
+-					} else if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+-						err("%s - failed setting baud rate, unsupported speed",
+-						    __FUNCTION__);
+-						new_baudrate = priv->baud_rate;
+-					}
+-				} else if (priv->chiptype == CT_CYPHIDCOM) {
+-					if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+-						err("%s - failed setting baud rate, unsupported speed",
+-						    __FUNCTION__);
+-						new_baudrate = priv->baud_rate;
+-					}
+-				} else if (priv->chiptype == CT_CA42V2) {
+-					if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+-						err("%s - failed setting baud rate, unsupported speed",
+-						    __FUNCTION__);
+-						new_baudrate = priv->baud_rate;
+-					}
+-				} else if (priv->chiptype == CT_GENERIC) {
+-					if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+-						err("%s - failed setting baud rate, unsupported speed",
+-						    __FUNCTION__);
+-						new_baudrate = priv->baud_rate;
+-					}
+-				} else {
+-					info("%s - please define your chiptype", __FUNCTION__);
+-					new_baudrate = priv->baud_rate;
+-				}
+-			} else {  /* baud rate not changing, keep the old */
++			new_baudrate = priv->baud_rate;
++			/* 0 means 'Hang up' so doesn't change the true bit rate */
++			if (baud_rate == 0)
+ 				new_baudrate = priv->baud_rate;
++			/* Change of speed ? */
++			else if (baud_rate != priv->baud_rate) {
++				dbg("%s - baud rate is changing", __func__);
++				retval = analyze_baud_rate(port, baud_rate);
++				if (retval >=  0) {
++					new_baudrate = retval;
++					dbg("%s - New baud rate set to %d",
++					    __func__, new_baudrate);
++				}
+ 			}
+-			dbg("%s - baud rate is being sent as %d", __FUNCTION__, new_baudrate);
++			dbg("%s - baud rate is being sent as %d", __func__, new_baudrate);
+ 			
+-			memset(feature_buffer, 0, 8);
++			memset(feature_buffer, 0, sizeof(feature_buffer));
+ 			/* fill the feature_buffer with new configuration */
+ 			*((u_int32_t *)feature_buffer) = new_baudrate;
+ 
+@@ -365,48 +367,65 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
+ 			/* 1 bit gap */
+ 			feature_buffer[4] |= (reset << 7);   /* assign reset at end of byte, 1 bit space */
+ 				
+-			dbg("%s - device is being sent this feature report:", __FUNCTION__);
+-			dbg("%s - %02X - %02X - %02X - %02X - %02X", __FUNCTION__, feature_buffer[0], feature_buffer[1],
++			dbg("%s - device is being sent this feature report:", __func__);
++			dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, feature_buffer[0], feature_buffer[1],
+ 		            feature_buffer[2], feature_buffer[3], feature_buffer[4]);
+ 			
+ 			do {
+-			retval = usb_control_msg (port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
+-					  	  HID_REQ_SET_REPORT, USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+-						  	  0x0300, 0, feature_buffer, 8, 500);
++				retval = usb_control_msg(port->serial->dev,
++						usb_sndctrlpipe(port->serial->dev, 0),
++						HID_REQ_SET_REPORT,
++						USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
++						0x0300, 0, feature_buffer,
++						sizeof(feature_buffer), 500);
+ 
+ 				if (tries++ >= 3)
+ 					break;
+ 
+-			} while (retval != 8 && retval != -ENODEV);
++			} while (retval != sizeof(feature_buffer) &&
++				 retval != -ENODEV);
+ 
+-			if (retval != 8) {
+-				err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
++			if (retval != sizeof(feature_buffer)) {
++				err("%s - failed sending serial line settings - %d", __func__, retval);
+ 				cypress_set_dead(port);
+ 			} else {
+ 				spin_lock_irqsave(&priv->lock, flags);
+ 				priv->baud_rate = new_baudrate;
+-				priv->cbr_mask = baud_mask;
+ 				priv->current_config = feature_buffer[4];
+ 				spin_unlock_irqrestore(&priv->lock, flags);
++				/* If we asked for a speed change encode it */
++				if (baud_rate)
++					tty_encode_baud_rate(port->tty,
++							new_baudrate, new_baudrate);
+ 			}
+ 		break;
+ 		case CYPRESS_GET_CONFIG:
+-			dbg("%s - retreiving serial line settings", __FUNCTION__);
++			if (priv->get_cfg_unsafe) {
++				/* Not implemented for this device,
++				   and if we try to do it we're likely
++				   to crash the hardware. */
++				return -ENOTTY;
++			}
++			dbg("%s - retreiving serial line settings", __func__);
+ 			/* set initial values in feature buffer */
+-			memset(feature_buffer, 0, 8);
++			memset(feature_buffer, 0, sizeof(feature_buffer));
+ 
+ 			do {
+-			retval = usb_control_msg (port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
+-						  HID_REQ_GET_REPORT, USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+-							  0x0300, 0, feature_buffer, 8, 500);
+-				
++				retval = usb_control_msg(port->serial->dev,
++						usb_rcvctrlpipe(port->serial->dev, 0),
++						HID_REQ_GET_REPORT,
++						USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
++						0x0300, 0, feature_buffer,
++						sizeof(feature_buffer), 500);
++
+ 				if (tries++ >= 3)
+ 					break;
+ 
+-			} while (retval != 5 && retval != -ENODEV);
++			} while (retval != sizeof(feature_buffer) &&
++				 retval != -ENODEV);
+ 
+-			if (retval != 5) {
+-				err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval);
++			if (retval != sizeof(feature_buffer)) {
++				err("%s - failed to retrieve serial line settings - %d", __func__, retval);
+ 				cypress_set_dead(port);
+ 				return retval;
+ 			} else {
+@@ -415,9 +434,6 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
+ 				/* store the config in one byte, and later use bit masks to check values */
+ 				priv->current_config = feature_buffer[4];
+ 				priv->baud_rate = *((u_int32_t *)feature_buffer);
+-				
+-				if ( (priv->cbr_mask = rate_to_mask(priv->baud_rate)) == 0x40)
+-					dbg("%s - failed setting the baud mask (not defined)", __FUNCTION__);
+ 				spin_unlock_irqrestore(&priv->lock, flags);
+ 			}
+ 	}
+@@ -447,51 +463,6 @@ static void cypress_set_dead(struct usb_serial_port *port)
+ }
+ 
+ 
+-/* given a baud mask, it will return integer baud on success */
+-static int mask_to_rate (unsigned mask)
+-{
+-	int rate;
+-
+-	switch (mask) {
+-		case B0: rate = 0; break;
+-		case B300: rate = 300; break;
+-		case B600: rate = 600; break;
+-		case B1200: rate = 1200; break;
+-		case B2400: rate = 2400; break;
+-		case B4800: rate = 4800; break;
+-		case B9600: rate = 9600; break;
+-		case B19200: rate = 19200; break;
+-		case B38400: rate = 38400; break;
+-		case B57600: rate = 57600; break;
+-		case B115200: rate = 115200; break;
+-		default: rate = -1;
+-	}
+-
+-	return rate;
+-}
+-
+-
+-static unsigned rate_to_mask (int rate)
+-{
+-	unsigned mask;
+-
+-	switch (rate) {
+-		case 0: mask = B0; break;
+-		case 300: mask = B300; break;
+-		case 600: mask = B600; break;
+-		case 1200: mask = B1200; break;
+-		case 2400: mask = B2400; break;
+-		case 4800: mask = B4800; break;
+-		case 9600: mask = B9600; break;
+-		case 19200: mask = B19200; break;
+-		case 38400: mask = B38400; break;
+-		case 57600: mask = B57600; break;
+-		case 115200: mask = B115200; break;
+-		default: mask = 0x40;
+-	}
+-
+-	return mask;
+-}
+ /*****************************************************************************
+  * Cypress serial driver functions
+  *****************************************************************************/
+@@ -502,7 +473,7 @@ static int generic_startup (struct usb_serial *serial)
+ 	struct cypress_private *priv;
+ 	struct usb_serial_port *port = serial->port[0];
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
+ 	if (!priv)
+@@ -523,17 +494,27 @@ static int generic_startup (struct usb_serial *serial)
+ 	priv->line_control = 0;
+ 	priv->termios_initialized = 0;
+ 	priv->rx_flags = 0;
+-	priv->cbr_mask = B300;
++	/* Default packet format setting is determined by packet size.
++	   Anything with a size larger then 9 must have a separate
++	   count field since the 3 bit count field is otherwise too
++	   small.  Otherwise we can use the slightly more compact
++	   format.  This is in accordance with the cypress_m8 serial
++	   converter app note. */
++	if (port->interrupt_out_size > 9) {
++		priv->pkt_fmt = packet_format_1;
++	} else {
++		priv->pkt_fmt = packet_format_2;
++	}
+ 	if (interval > 0) {
+ 		priv->write_urb_interval = interval;
+ 		priv->read_urb_interval = interval;
+ 		dbg("%s - port %d read & write intervals forced to %d",
+-		    __FUNCTION__,port->number,interval);
++		    __func__,port->number,interval);
+ 	} else {
+ 		priv->write_urb_interval = port->interrupt_out_urb->interval;
+ 		priv->read_urb_interval = port->interrupt_in_urb->interval;
+ 		dbg("%s - port %d intervals: read=%d write=%d",
+-		    __FUNCTION__,port->number,
++		    __func__,port->number,
+ 		    priv->read_urb_interval,priv->write_urb_interval);
+ 	}
+ 	usb_set_serial_port_data(port, priv);
+@@ -545,17 +526,30 @@ static int generic_startup (struct usb_serial *serial)
+ static int cypress_earthmate_startup (struct usb_serial *serial)
+ {
+ 	struct cypress_private *priv;
++	struct usb_serial_port *port = serial->port[0];
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (generic_startup(serial)) {
+-		dbg("%s - Failed setting up port %d", __FUNCTION__,
+-				serial->port[0]->number);
++		dbg("%s - Failed setting up port %d", __func__,
++				port->number);
+ 		return 1;
+ 	}
+ 
+-	priv = usb_get_serial_port_data(serial->port[0]);
++	priv = usb_get_serial_port_data(port);
+ 	priv->chiptype = CT_EARTHMATE;
++	/* All Earthmate devices use the separated-count packet
++	   format!  Idiotic. */
++	priv->pkt_fmt = packet_format_1;
++	if (serial->dev->descriptor.idProduct != PRODUCT_ID_EARTHMATEUSB) {
++		/* The old original USB Earthmate seemed able to
++		   handle GET_CONFIG requests; everything they've
++		   produced since that time crashes if this command is
++		   attempted :-( */
++		dbg("%s - Marking this device as unsafe for GET_CONFIG "
++		    "commands", __func__);
++		priv->get_cfg_unsafe = !0;
++	}
+ 
+ 	return 0;
+ } /* cypress_earthmate_startup */
+@@ -565,10 +559,10 @@ static int cypress_hidcom_startup (struct usb_serial *serial)
+ {
+ 	struct cypress_private *priv;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (generic_startup(serial)) {
+-		dbg("%s - Failed setting up port %d", __FUNCTION__,
++		dbg("%s - Failed setting up port %d", __func__,
+ 				serial->port[0]->number);
+ 		return 1;
+ 	}
+@@ -584,10 +578,10 @@ static int cypress_ca42v2_startup (struct usb_serial *serial)
+ {
+ 	struct cypress_private *priv;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (generic_startup(serial)) {
+-		dbg("%s - Failed setting up port %d", __FUNCTION__,
++		dbg("%s - Failed setting up port %d", __func__,
+ 				serial->port[0]->number);
+ 		return 1;
+ 	}
+@@ -603,7 +597,7 @@ static void cypress_shutdown (struct usb_serial *serial)
+ {
+ 	struct cypress_private *priv;
+ 
+-	dbg ("%s - port %d", __FUNCTION__, serial->port[0]->number);
++	dbg ("%s - port %d", __func__, serial->port[0]->number);
+ 
+ 	/* all open ports are closed at this point */
+ 
+@@ -624,7 +618,7 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
+ 	unsigned long flags;
+ 	int result = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!priv->comm_is_ok)
+ 		return -EIO;
+@@ -652,16 +646,16 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
+ 	result = cypress_write(port, NULL, 0);
+ 
+ 	if (result) {
+-		dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __func__, result);
+ 		return result;
+ 	} else
+-		dbg("%s - success setting the control lines", __FUNCTION__);	
++		dbg("%s - success setting the control lines", __func__);
+ 
+ 	cypress_set_termios(port, &priv->tmp_termios);
+ 
+ 	/* setup the port and start reading from the device */
+ 	if(!port->interrupt_in_urb){
+-		err("%s - interrupt_in_urb is empty!", __FUNCTION__);
++		err("%s - interrupt_in_urb is empty!", __func__);
+ 		return(-1);
+ 	}
+ 
+@@ -672,7 +666,7 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
+ 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ 
+ 	if (result){
+-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ 		cypress_set_dead(port);
+ 	}
+ 
+@@ -688,7 +682,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
+ 	long timeout;
+ 	wait_queue_t wait;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* wait for data to drain from buffer */
+ 	spin_lock_irq(&priv->lock);
+@@ -726,7 +720,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
+ 		timeout = 2*HZ;
+ 	schedule_timeout_interruptible(timeout);
+ 
+-	dbg("%s - stopping urbs", __FUNCTION__);
++	dbg("%s - stopping urbs", __func__);
+ 	usb_kill_urb (port->interrupt_in_urb);
+ 	usb_kill_urb (port->interrupt_out_urb);
+ 
+@@ -755,7 +749,7 @@ static int cypress_write(struct usb_serial_port *port, const unsigned char *buf,
+ 	struct cypress_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 	
+-	dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
++	dbg("%s - port %d, %d bytes", __func__, port->number, count);
+ 
+ 	/* line control commands, which need to be executed immediately,
+ 	   are not put into the buffer for obvious reasons.
+@@ -788,12 +782,12 @@ static void cypress_send(struct usb_serial_port *port)
+ 	if (!priv->comm_is_ok)
+ 		return;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
+-	dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);
++	dbg("%s - port %d", __func__, port->number);
++	dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size);
+ 	
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (priv->write_urb_in_use) {
+-		dbg("%s - can't write, urb in use", __FUNCTION__);
++		dbg("%s - can't write, urb in use", __func__);
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		return;
+ 	}
+@@ -803,21 +797,18 @@ static void cypress_send(struct usb_serial_port *port)
+ 	memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	switch (port->interrupt_out_size) {
+-		case 32:
+-			/* this is for the CY7C64013... */
+-			offset = 2;
+-			port->interrupt_out_buffer[0] = priv->line_control;
+-			break;
+-		case 8:
+-			/* this is for the CY7C63743... */
+-			offset = 1;
+-			port->interrupt_out_buffer[0] = priv->line_control;
+-			break;
+-		default:
+-			dbg("%s - wrong packet size", __FUNCTION__);
+-			spin_unlock_irqrestore(&priv->lock, flags);
+-			return;
++	switch (priv->pkt_fmt) {
++	default:
++	case packet_format_1:
++		/* this is for the CY7C64013... */
++		offset = 2;
++		port->interrupt_out_buffer[0] = priv->line_control;
++		break;
++	case packet_format_2:
++		/* this is for the CY7C63743... */
++		offset = 1;
++		port->interrupt_out_buffer[0] = priv->line_control;
++		break;
+ 	}
+ 
+ 	if (priv->line_control & CONTROL_RESET)
+@@ -825,7 +816,7 @@ static void cypress_send(struct usb_serial_port *port)
+ 
+ 	if (priv->cmd_ctrl) {
+ 		priv->cmd_count++;
+-		dbg("%s - line control command being issued", __FUNCTION__);
++		dbg("%s - line control command being issued", __func__);
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		goto send;
+ 	} else
+@@ -838,15 +829,16 @@ static void cypress_send(struct usb_serial_port *port)
+ 		return;
+ 	}
+ 
+-	switch (port->interrupt_out_size) {
+-		case 32:
+-			port->interrupt_out_buffer[1] = count;
+-			break;
+-		case 8:
+-			port->interrupt_out_buffer[0] |= count;
++	switch (priv->pkt_fmt) {
++	default:
++	case packet_format_1:
++		port->interrupt_out_buffer[1] = count;
++		break;
++	case packet_format_2:
++		port->interrupt_out_buffer[0] |= count;
+ 	}
+ 
+-	dbg("%s - count is %d", __FUNCTION__, count);
++	dbg("%s - count is %d", __func__, count);
+ 
+ send:
+ 	spin_lock_irqsave(&priv->lock, flags);
+@@ -856,9 +848,10 @@ send:
+ 	if (priv->cmd_ctrl)
+ 		actual_size = 1;
+ 	else
+-		actual_size = count + (port->interrupt_out_size == 32 ? 2 : 1);
+-	
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size,
++		actual_size = count +
++			      (priv->pkt_fmt == packet_format_1 ? 2 : 1);
++
++	usb_serial_debug_data(debug, &port->dev, __func__, port->interrupt_out_size,
+ 			      port->interrupt_out_urb->transfer_buffer);
+ 
+ 	usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
+@@ -867,7 +860,7 @@ send:
+ 		cypress_write_int_callback, port, priv->write_urb_interval);
+ 	result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
+ 	if (result) {
+-		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,
++		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__,
+ 			result);
+ 		priv->write_urb_in_use = 0;
+ 		cypress_set_dead(port);
+@@ -891,13 +884,13 @@ static int cypress_write_room(struct usb_serial_port *port)
+ 	int room = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	room = cypress_buf_space_avail(priv->buf);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 	return room;
+ }
+ 
+@@ -909,7 +902,7 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
+ 	unsigned int result = 0;
+ 	unsigned long flags;
+ 	
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	control = priv->line_control;
+@@ -923,7 +916,7 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
+ 		| ((status & UART_RI)         ? TIOCM_RI  : 0)
+ 		| ((status & UART_CD)         ? TIOCM_CD  : 0);
+ 
+-	dbg("%s - result = %x", __FUNCTION__, result);
++	dbg("%s - result = %x", __func__, result);
+ 
+ 	return result;
+ }
+@@ -935,7 +928,7 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
+ 	struct cypress_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 	
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (set & TIOCM_RTS)
+@@ -946,9 +939,9 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
+ 		priv->line_control &= ~CONTROL_RTS;
+ 	if (clear & TIOCM_DTR)
+ 		priv->line_control &= ~CONTROL_DTR;
++	priv->cmd_ctrl = 1;
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	priv->cmd_ctrl = 1;
+ 	return cypress_write(port, NULL, 0);
+ }
+ 
+@@ -957,23 +950,9 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
+ {
+ 	struct cypress_private *priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+ 
+ 	switch (cmd) {
+-		case TIOCGSERIAL:
+-			if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) {
+-				return -EFAULT;
+-			}
+-			return (0);
+-			break;
+-		case TIOCSSERIAL:
+-			if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) {
+-				return -EFAULT;
+-			}
+-			/* here we need to call cypress_set_termios to invoke the new settings */
+-			cypress_set_termios(port, &priv->tmp_termios);
+-			return (0);
+-			break;
+ 		/* This code comes from drivers/char/serial.c and ftdi_sio.c */
+ 		case TIOCMIWAIT:
+ 			while (priv != NULL) {
+@@ -1009,7 +988,7 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
+ 			break;
+ 	}
+ 
+-	dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __FUNCTION__, cmd);
++	dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd);
+ 
+ 	return -ENOIOCTLCMD;
+ } /* cypress_ioctl */
+@@ -1021,18 +1000,14 @@ static void cypress_set_termios (struct usb_serial_port *port,
+ 	struct cypress_private *priv = usb_get_serial_port_data(port);
+ 	struct tty_struct *tty;
+ 	int data_bits, stop_bits, parity_type, parity_enable;
+-	unsigned cflag, iflag, baud_mask;
++	unsigned cflag, iflag;
+ 	unsigned long flags;
+ 	__u8 oldlines;
+ 	int linechange = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	tty = port->tty;
+-	if ((!tty) || (!tty->termios)) {
+-		dbg("%s - no tty structures", __FUNCTION__);
+-		return;
+-	}
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (!priv->termios_initialized) {
+@@ -1040,40 +1015,37 @@ static void cypress_set_termios (struct usb_serial_port *port,
+ 			*(tty->termios) = tty_std_termios;
+ 			tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL |
+ 				CLOCAL;
++			tty->termios->c_ispeed = 4800;
++			tty->termios->c_ospeed = 4800;
+ 		} else if (priv->chiptype == CT_CYPHIDCOM) {
+ 			*(tty->termios) = tty_std_termios;
+ 			tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ 				CLOCAL;
++			tty->termios->c_ispeed = 9600;
++			tty->termios->c_ospeed = 9600;
+ 		} else if (priv->chiptype == CT_CA42V2) {
+ 			*(tty->termios) = tty_std_termios;
+ 			tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ 				CLOCAL;
++			tty->termios->c_ispeed = 9600;
++			tty->termios->c_ospeed = 9600;
+ 		}
+ 		priv->termios_initialized = 1;
+ 	}
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
++	/* Unsupported features need clearing */
++	tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS);
++
+ 	cflag = tty->termios->c_cflag;
+ 	iflag = tty->termios->c_iflag;
+ 
+ 	/* check if there are new settings */
+ 	if (old_termios) {
+-		if ((cflag != old_termios->c_cflag) ||
+-			(RELEVANT_IFLAG(iflag) !=
+-			 RELEVANT_IFLAG(old_termios->c_iflag))) {
+-			dbg("%s - attempting to set new termios settings",
+-					__FUNCTION__);
+-			/* should make a copy of this in case something goes
+-			 * wrong in the function, we can restore it */
+-			spin_lock_irqsave(&priv->lock, flags);
+-			priv->tmp_termios = *(tty->termios);
+-			spin_unlock_irqrestore(&priv->lock, flags);
+-		} else {
+-			dbg("%s - nothing to do, exiting", __FUNCTION__);
+-			return;
+-		}
+-	} else
+-		return;
++		spin_lock_irqsave(&priv->lock, flags);
++		priv->tmp_termios = *(tty->termios);
++		spin_unlock_irqrestore(&priv->lock, flags);
++	}
+ 
+ 	/* set number of data bits, parity, stop bits */
+ 	/* when parity is disabled the parity type bit is ignored */
+@@ -1104,7 +1076,7 @@ static void cypress_set_termios (struct usb_serial_port *port,
+ 				break;
+ 			default:
+ 				err("%s - CSIZE was set, but not CS5-CS8",
+-						__FUNCTION__);
++						__func__);
+ 				data_bits = 3;
+ 		}
+ 	} else
+@@ -1114,54 +1086,17 @@ static void cypress_set_termios (struct usb_serial_port *port,
+ 	oldlines = priv->line_control;
+ 	if ((cflag & CBAUD) == B0) {
+ 		/* drop dtr and rts */
+-		dbg("%s - dropping the lines, baud rate 0bps", __FUNCTION__);
+-		baud_mask = B0;
++		dbg("%s - dropping the lines, baud rate 0bps", __func__);
+ 		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+-	} else {
+-		baud_mask = (cflag & CBAUD);
+-		switch(baud_mask) {
+-			case B300:
+-				dbg("%s - setting baud 300bps", __FUNCTION__);
+-				break;
+-			case B600:
+-				dbg("%s - setting baud 600bps", __FUNCTION__);
+-				break;
+-			case B1200:
+-				dbg("%s - setting baud 1200bps", __FUNCTION__);
+-				break;
+-			case B2400:
+-				dbg("%s - setting baud 2400bps", __FUNCTION__);
+-				break;
+-			case B4800:
+-				dbg("%s - setting baud 4800bps", __FUNCTION__);
+-				break;
+-			case B9600:
+-				dbg("%s - setting baud 9600bps", __FUNCTION__);
+-				break;
+-			case B19200:
+-				dbg("%s - setting baud 19200bps", __FUNCTION__);
+-				break;
+-			case B38400:
+-				dbg("%s - setting baud 38400bps", __FUNCTION__);
+-				break;
+-			case B57600:
+-				dbg("%s - setting baud 57600bps", __FUNCTION__);
+-				break;
+-			case B115200:
+-				dbg("%s - setting baud 115200bps", __FUNCTION__);
+-				break;
+-			default:
+-				dbg("%s - unknown masked baud rate", __FUNCTION__);
+-		}
++	} else
+ 		priv->line_control = (CONTROL_DTR | CONTROL_RTS);
+-	}
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+ 	dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, "
+-			"%d data_bits (+5)", __FUNCTION__, stop_bits,
++			"%d data_bits (+5)", __func__, stop_bits,
+ 			parity_enable, parity_type, data_bits);
+ 
+-	cypress_serial_control(port, baud_mask, data_bits, stop_bits,
++	cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits,
+ 			parity_enable, parity_type, 0, CYPRESS_SET_CONFIG);
+ 
+ 	/* we perform a CYPRESS_GET_CONFIG so that the current settings are
+@@ -1219,13 +1154,13 @@ static int cypress_chars_in_buffer(struct usb_serial_port *port)
+ 	int chars = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	chars = cypress_buf_data_avail(priv->buf);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, chars);
++	dbg("%s - returns %d", __func__, chars);
+ 	return chars;
+ }
+ 
+@@ -1235,7 +1170,7 @@ static void cypress_throttle (struct usb_serial_port *port)
+ 	struct cypress_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	priv->rx_flags = THROTTLED;
+@@ -1249,7 +1184,7 @@ static void cypress_unthrottle (struct usb_serial_port *port)
+ 	int actually_throttled, result;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
+@@ -1265,7 +1200,7 @@ static void cypress_unthrottle (struct usb_serial_port *port)
+ 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ 		if (result) {
+ 			dev_err(&port->dev, "%s - failed submitting read urb, "
+-					"error %d\n", __FUNCTION__, result);
++					"error %d\n", __func__, result);
+ 			cypress_set_dead(port);
+ 		}
+ 	}
+@@ -1274,7 +1209,7 @@ static void cypress_unthrottle (struct usb_serial_port *port)
+ 
+ static void cypress_read_int_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct cypress_private *priv = usb_get_serial_port_data(port);
+ 	struct tty_struct *tty;
+ 	unsigned char *data = urb->transfer_buffer;
+@@ -1286,7 +1221,7 @@ static void cypress_read_int_callback(struct urb *urb)
+ 	int i = 0;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	switch (status) {
+ 	case 0: /* success */
+@@ -1302,14 +1237,14 @@ static void cypress_read_int_callback(struct urb *urb)
+ 	default:
+ 		/* something ugly is going on... */
+ 		dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		cypress_set_dead(port);
+ 		return;
+ 	}
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (priv->rx_flags & THROTTLED) {
+-		dbg("%s - now throttling", __FUNCTION__);
++		dbg("%s - now throttling", __func__);
+ 		priv->rx_flags |= ACTUALLY_THROTTLED;
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		return;
+@@ -1318,48 +1253,48 @@ static void cypress_read_int_callback(struct urb *urb)
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - bad tty pointer - exiting", __FUNCTION__);
++		dbg("%s - bad tty pointer - exiting", __func__);
+ 		return;
+ 	}
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+-	switch(urb->actual_length) {
+-		case 32:
+-			/* This is for the CY7C64013... */
+-			priv->current_status = data[0] & 0xF8;
+-			bytes = data[1] + 2;
+-			i = 2;
+-			if (bytes > 2)
+-				havedata = 1;
+-			break;
+-		case 8:
+-			/* This is for the CY7C63743... */
+-			priv->current_status = data[0] & 0xF8;
+-			bytes = (data[0] & 0x07) + 1;
+-			i = 1;
+-			if (bytes > 1)
+-				havedata = 1;
+-			break;
+-		default:
+-			dbg("%s - wrong packet size - received %d bytes",
+-					__FUNCTION__, urb->actual_length);
+-			spin_unlock_irqrestore(&priv->lock, flags);
+-			goto continue_read;
++	result = urb->actual_length;
++	switch (priv->pkt_fmt) {
++	default:
++	case packet_format_1:
++		/* This is for the CY7C64013... */
++		priv->current_status = data[0] & 0xF8;
++		bytes = data[1] + 2;
++		i = 2;
++		if (bytes > 2)
++			havedata = 1;
++		break;
++	case packet_format_2:
++		/* This is for the CY7C63743... */
++		priv->current_status = data[0] & 0xF8;
++		bytes = (data[0] & 0x07) + 1;
++		i = 1;
++		if (bytes > 1)
++			havedata = 1;
++		break;
+ 	}
+ 	spin_unlock_irqrestore(&priv->lock, flags);
++	if (result < bytes) {
++		dbg("%s - wrong packet size - received %d bytes but packet "
++		    "said %d bytes", __func__, result, bytes);
++		goto continue_read;
++	}
+ 
+-	usb_serial_debug_data (debug, &port->dev, __FUNCTION__,
++	usb_serial_debug_data (debug, &port->dev, __func__,
+ 			urb->actual_length, data);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	/* check to see if status has changed */
+-	if (priv != NULL) {
+-		if (priv->current_status != priv->prev_status) {
+-			priv->diff_status |= priv->current_status ^
+-				priv->prev_status;
+-			wake_up_interruptible(&priv->delta_msr_wait);
+-			priv->prev_status = priv->current_status;
+-		}
++	if (priv->current_status != priv->prev_status) {
++		priv->diff_status |= priv->current_status ^
++			priv->prev_status;
++		wake_up_interruptible(&priv->delta_msr_wait);
++		priv->prev_status = priv->current_status;
+ 	}
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+@@ -1367,7 +1302,7 @@ static void cypress_read_int_callback(struct urb *urb)
+ 	 * though */
+ 	if (tty && !(tty->termios->c_cflag & CLOCAL) &&
+ 			!(priv->current_status & UART_CD)) {
+-		dbg("%s - calling hangup", __FUNCTION__);
++		dbg("%s - calling hangup", __func__);
+ 		tty_hangup(tty);
+ 		goto continue_read;
+ 	}
+@@ -1380,7 +1315,7 @@ static void cypress_read_int_callback(struct urb *urb)
+ 	if (priv->current_status & CYP_ERROR) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 		tty_flag = TTY_PARITY;
+-		dbg("%s - Parity Error detected", __FUNCTION__);
++		dbg("%s - Parity Error detected", __func__);
+ 	} else
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+ 
+@@ -1414,7 +1349,7 @@ continue_read:
+ 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ 		if (result) {
+ 			dev_err(&urb->dev->dev, "%s - failed resubmitting "
+-					"read urb, error %d\n", __FUNCTION__,
++					"read urb, error %d\n", __func__,
+ 					result);
+ 			cypress_set_dead(port);
+ 		}
+@@ -1426,12 +1361,12 @@ continue_read:
+ 
+ static void cypress_write_int_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct cypress_private *priv = usb_get_serial_port_data(port);
+ 	int result;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	switch (status) {
+ 		case 0:
+@@ -1442,7 +1377,7 @@ static void cypress_write_int_callback(struct urb *urb)
+ 		case -ESHUTDOWN:
+ 			/* this urb is terminated, clean up */
+ 			dbg("%s - urb shutting down with status: %d",
+-			    __FUNCTION__, status);
++			    __func__, status);
+ 			priv->write_urb_in_use = 0;
+ 			return;
+ 		case -EPIPE: /* no break needed; clear halt and resubmit */
+@@ -1451,19 +1386,19 @@ static void cypress_write_int_callback(struct urb *urb)
+ 			usb_clear_halt(port->serial->dev, 0x02);
+ 			/* error in the urb, so we have to resubmit it */
+ 			dbg("%s - nonzero write bulk status received: %d",
+-			    __FUNCTION__, status);
++			    __func__, status);
+ 			port->interrupt_out_urb->transfer_buffer_length = 1;
+ 			port->interrupt_out_urb->dev = port->serial->dev;
+ 			result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
+ 			if (!result)
+ 				return;
+ 			dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
+-				__FUNCTION__, result);
++				__func__, result);
+ 			cypress_set_dead(port);
+ 			break;
+ 		default:
+ 			dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
+-				__FUNCTION__, status);
++				__func__, status);
+ 			cypress_set_dead(port);
+ 			break;
+ 	}
+@@ -1668,7 +1603,7 @@ static int __init cypress_init(void)
+ {
+ 	int retval;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	
+ 	retval = usb_serial_register(&cypress_earthmate_device);
+ 	if (retval)
+@@ -1699,7 +1634,7 @@ failed_em_register:
+ 
+ static void __exit cypress_exit (void)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	usb_deregister (&cypress_driver);
+ 	usb_serial_deregister (&cypress_earthmate_device);
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index 5f9c6e4..d17d164 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -508,9 +508,6 @@ static struct usb_serial_driver digi_acceleport_2_device = {
+ 	.description =			"Digi 2 port USB adapter",
+ 	.usb_driver = 			&digi_driver,
+ 	.id_table =			id_table_2,
+-	.num_interrupt_in =		0,
+-	.num_bulk_in =			4,
+-	.num_bulk_out =			4,
+ 	.num_ports =			3,
+ 	.open =				digi_open,
+ 	.close =			digi_close,
+@@ -538,9 +535,6 @@ static struct usb_serial_driver digi_acceleport_4_device = {
+ 	.description =			"Digi 4 port USB adapter",
+ 	.usb_driver = 			&digi_driver,
+ 	.id_table =			id_table_4,
+-	.num_interrupt_in =		0,
+-	.num_bulk_in =			5,
+-	.num_bulk_out =			5,
+ 	.num_ports =			4,
+ 	.open =				digi_open,
+ 	.close =			digi_close,
+@@ -665,7 +659,7 @@ static int digi_write_oob_command(struct usb_serial_port *port,
+ 	}
+ 	spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
+ 	if (ret)
+-		err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret);
++		err("%s: usb_submit_urb failed, ret=%d", __func__, ret);
+ 	return ret;
+ 
+ }
+@@ -746,7 +740,7 @@ static int digi_write_inb_command(struct usb_serial_port *port,
+ 
+ 	if (ret)
+ 		err("%s: usb_submit_urb failed, ret=%d, port=%d",
+-			__FUNCTION__, ret, priv->dp_port_num);
++			__func__, ret, priv->dp_port_num);
+ 	return ret;
+ }
+ 
+@@ -810,7 +804,7 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
+ 	spin_unlock(&port_priv->dp_port_lock);
+ 	spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
+ 	if (ret)
+-		err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret);
++		err("%s: usb_submit_urb failed, ret=%d", __func__, ret);
+ 	return ret;
+ }
+ 
+@@ -903,7 +897,7 @@ static void digi_rx_unthrottle(struct usb_serial_port *port)
+ 
+ 	if (ret)
+ 		err("%s: usb_submit_urb failed, ret=%d, port=%d",
+-			__FUNCTION__, ret, priv->dp_port_num);
++			__func__, ret, priv->dp_port_num);
+ }
+ 
+ 
+@@ -1113,7 +1107,7 @@ static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
+ 	unsigned int val;
+ 	unsigned long flags;
+ 
+-	dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
++	dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
+ 
+ 	spin_lock_irqsave(&priv->dp_port_lock, flags);
+ 	val = priv->dp_modem_signals;
+@@ -1129,7 +1123,7 @@ static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
+ 	unsigned int val;
+ 	unsigned long flags;
+ 
+-	dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
++	dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
+ 
+ 	spin_lock_irqsave(&priv->dp_port_lock, flags);
+ 	val = (priv->dp_modem_signals & ~clear) | set;
+@@ -1224,7 +1218,7 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
+ 	spin_unlock_irqrestore(&priv->dp_port_lock, flags);
+ 	if (ret < 0)
+ 		err("%s: usb_submit_urb failed, ret=%d, port=%d",
+-			__FUNCTION__, ret, priv->dp_port_num);
++			__func__, ret, priv->dp_port_num);
+ 	dbg("digi_write: returning %d", ret);
+ 	return ret;
+ 
+@@ -1233,7 +1227,7 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
+ static void digi_write_bulk_callback(struct urb *urb)
+ {
+ 
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct usb_serial *serial;
+ 	struct digi_port *priv;
+ 	struct digi_serial *serial_priv;
+@@ -1245,13 +1239,13 @@ static void digi_write_bulk_callback(struct urb *urb)
+ 	/* port and serial sanity check */
+ 	if (port == NULL || (priv=usb_get_serial_port_data(port)) == NULL) {
+ 		err("%s: port or port->private is NULL, status=%d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 	serial = port->serial;
+ 	if (serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL) {
+ 		err("%s: serial or serial->private is NULL, status=%d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+@@ -1292,7 +1286,7 @@ static void digi_write_bulk_callback(struct urb *urb)
+ 	spin_unlock(&priv->dp_port_lock);
+ 	if (ret)
+ 		err("%s: usb_submit_urb failed, ret=%d, port=%d",
+-			__FUNCTION__, ret, priv->dp_port_num);
++			__func__, ret, priv->dp_port_num);
+ }
+ 
+ static int digi_write_room(struct usb_serial_port *port)
+@@ -1521,7 +1515,7 @@ static int digi_startup_device(struct usb_serial *serial)
+ 		port->write_urb->dev = port->serial->dev;
+ 		if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) {
+ 			err("%s: usb_submit_urb failed, ret=%d, port=%d",
+-					__FUNCTION__, ret, i);
++					__func__, ret, i);
+ 			break;
+ 		}
+ 	}
+@@ -1611,7 +1605,7 @@ static void digi_shutdown(struct usb_serial *serial)
+ 
+ static void digi_read_bulk_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct digi_port *priv;
+ 	struct digi_serial *serial_priv;
+ 	int ret;
+@@ -1622,20 +1616,20 @@ static void digi_read_bulk_callback(struct urb *urb)
+ 	/* port sanity check, do not resubmit if port is not valid */
+ 	if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
+ 		err("%s: port or port->private is NULL, status=%d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 	if (port->serial == NULL ||
+ 		(serial_priv=usb_get_serial_data(port->serial)) == NULL) {
+ 		err("%s: serial is bad or serial->private is NULL, status=%d",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		return;
+ 	}
+ 
+ 	/* do not resubmit urb if it has any status error */
+ 	if (status) {
+ 		err("%s: nonzero read bulk status: status=%d, port=%d",
+-		    __FUNCTION__, status, priv->dp_port_num);
++		    __func__, status, priv->dp_port_num);
+ 		return;
+ 	}
+ 
+@@ -1652,7 +1646,7 @@ static void digi_read_bulk_callback(struct urb *urb)
+ 	urb->dev = port->serial->dev;
+ 	if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ 		err("%s: failed resubmitting urb, ret=%d, port=%d",
+-		    __FUNCTION__, ret, priv->dp_port_num);
++		    __func__, ret, priv->dp_port_num);
+ 	}
+ 
+ }
+@@ -1670,7 +1664,7 @@ static void digi_read_bulk_callback(struct urb *urb)
+ static int digi_read_inb_callback(struct urb *urb)
+ {
+ 
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct tty_struct *tty = port->tty;
+ 	struct digi_port *priv = usb_get_serial_port_data(port);
+ 	int opcode = ((unsigned char *)urb->transfer_buffer)[0];
+@@ -1690,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb)
+ 	if (urb->actual_length != len + 2) {
+      		err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
+ 		    "port=%d, opcode=%d, len=%d, actual_length=%d, "
+-		    "status=%d", __FUNCTION__, status, priv->dp_port_num,
++		    "status=%d", __func__, status, priv->dp_port_num,
+ 		    opcode, len, urb->actual_length, port_status);
+ 		return -1;
+ 	}
+@@ -1739,9 +1733,9 @@ static int digi_read_inb_callback(struct urb *urb)
+ 	spin_unlock(&priv->dp_port_lock);
+ 
+ 	if (opcode == DIGI_CMD_RECEIVE_DISABLE)
+-		dbg("%s: got RECEIVE_DISABLE", __FUNCTION__);
++		dbg("%s: got RECEIVE_DISABLE", __func__);
+ 	else if (opcode != DIGI_CMD_RECEIVE_DATA)
+-		dbg("%s: unknown opcode: %d", __FUNCTION__, opcode);
++		dbg("%s: unknown opcode: %d", __func__, opcode);
+ 
+ 	return(throttled ? 1 : 0);
+ 
+@@ -1760,7 +1754,7 @@ static int digi_read_inb_callback(struct urb *urb)
+ static int digi_read_oob_callback(struct urb *urb)
+ {
+ 
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct usb_serial *serial = port->serial;
+ 	struct digi_port *priv = usb_get_serial_port_data(port);
+ 	int opcode, line, status, val;
+diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
+index a5c8e1e..c5ec309 100644
+--- a/drivers/usb/serial/empeg.c
++++ b/drivers/usb/serial/empeg.c
+@@ -118,9 +118,6 @@ static struct usb_serial_driver empeg_device = {
+ 	},
+ 	.id_table =		id_table,
+ 	.usb_driver = 		&empeg_driver,
+-	.num_interrupt_in =	0,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.open =			empeg_open,
+ 	.close =		empeg_close,
+@@ -153,7 +150,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
+ 	struct usb_serial *serial = port->serial;
+ 	int result = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* Force default termio settings */
+ 	empeg_set_termios (port, NULL) ;
+@@ -175,7 +172,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
+ 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 
+ 	if (result)
+-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ 
+ 	return result;
+ }
+@@ -183,7 +180,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
+ 
+ static void empeg_close (struct usb_serial_port *port, struct file * filp)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* shutdown our bulk read */
+ 	usb_kill_urb(port->read_urb);
+@@ -203,7 +200,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
+ 	int bytes_sent = 0;
+ 	int transfer_size;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	while (count > 0) {
+ 
+@@ -222,14 +219,14 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
+ 		spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+ 
+ 		if (urb == NULL) {
+-			dbg("%s - no more free urbs", __FUNCTION__);
++			dbg("%s - no more free urbs", __func__);
+ 			goto exit;
+ 		}
+ 
+ 		if (urb->transfer_buffer == NULL) {
+ 			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+ 			if (urb->transfer_buffer == NULL) {
+-				dev_err(&port->dev, "%s no more kernel memory...\n", __FUNCTION__);
++				dev_err(&port->dev, "%s no more kernel memory...\n", __func__);
+ 				goto exit;
+ 			}
+ 		}
+@@ -238,7 +235,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
+ 
+ 		memcpy (urb->transfer_buffer, current_position, transfer_size);
+ 
+-		usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, urb->transfer_buffer);
++		usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, urb->transfer_buffer);
+ 
+ 		/* build up our urb */
+ 		usb_fill_bulk_urb (
+@@ -254,7 +251,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
+ 		/* send it down the pipe */
+ 		status = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (status) {
+-			dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __FUNCTION__, status);
++			dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status);
+ 			bytes_sent = status;
+ 			break;
+ 		}
+@@ -278,7 +275,7 @@ static int empeg_write_room (struct usb_serial_port *port)
+ 	int i;
+ 	int room = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave (&write_urb_pool_lock, flags);
+ 
+@@ -291,7 +288,7 @@ static int empeg_write_room (struct usb_serial_port *port)
+ 
+ 	spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 
+ 	return (room);
+ 
+@@ -304,7 +301,7 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
+ 	int i;
+ 	int chars = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave (&write_urb_pool_lock, flags);
+ 
+@@ -317,7 +314,7 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
+ 
+ 	spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, chars);
++	dbg("%s - returns %d", __func__, chars);
+ 
+ 	return (chars);
+ 
+@@ -329,11 +326,11 @@ static void empeg_write_bulk_callback (struct urb *urb)
+ 	struct usb_serial_port *port = urb->context;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+@@ -343,21 +340,21 @@ static void empeg_write_bulk_callback (struct urb *urb)
+ 
+ static void empeg_read_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct tty_struct *tty;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int result;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	tty = port->tty;
+ 
+@@ -382,7 +379,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
+ 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 
+ 	if (result)
+-		dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++		dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ 
+ 	return;
+ 
+@@ -391,7 +388,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
+ 
+ static void empeg_throttle (struct usb_serial_port *port)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	usb_kill_urb(port->read_urb);
+ }
+ 
+@@ -400,14 +397,14 @@ static void empeg_unthrottle (struct usb_serial_port *port)
+ {
+ 	int result;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	port->read_urb->dev = port->serial->dev;
+ 
+ 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 
+ 	if (result)
+-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ 
+ 	return;
+ }
+@@ -417,14 +414,14 @@ static int  empeg_startup (struct usb_serial *serial)
+ {
+ 	int r;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
+ 		err("active config #%d != 1 ??",
+ 			serial->dev->actconfig->desc.bConfigurationValue);
+ 		return -ENODEV;
+ 	}
+-	dbg("%s - reset config", __FUNCTION__);
++	dbg("%s - reset config", __func__);
+ 	r = usb_reset_configuration (serial->dev);
+ 
+ 	/* continue on with initialization */
+@@ -435,13 +432,13 @@ static int  empeg_startup (struct usb_serial *serial)
+ 
+ static void empeg_shutdown (struct usb_serial *serial)
+ {
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ }
+ 
+ 
+ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+ {
+-	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+ 
+ 	return -ENOIOCTLCMD;
+ }
+@@ -450,7 +447,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign
+ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+ {
+ 	struct ktermios *termios = port->tty->termios;
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/*
+          * The empeg-car player wants these particular tty settings.
+@@ -517,7 +514,7 @@ static int __init empeg_init (void)
+ 		urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ 		if (!urb->transfer_buffer) {
+ 			err("%s - out of memory for urb buffers.", 
+-			    __FUNCTION__);
++			    __func__);
+ 			continue;
+ 		}
+ 	}
+diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
+index 3f698ba..cc4fbd9 100644
+--- a/drivers/usb/serial/ezusb.c
++++ b/drivers/usb/serial/ezusb.c
+@@ -27,13 +27,13 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
+ 
+ 	/* dbg("ezusb_writememory %x, %d", address, length); */
+ 	if (!serial->dev) {
+-		err("%s - no physical device present, failing.", __FUNCTION__);
++		err("%s - no physical device present, failing.", __func__);
+ 		return -ENODEV;
+ 	}
+ 
+ 	transfer_buffer = kmemdup(data, length, GFP_KERNEL);
+ 	if (!transfer_buffer) {
+-		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length);
++		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, length);
+ 		return -ENOMEM;
+ 	}
+ 	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
+@@ -45,10 +45,10 @@ int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+ {
+ 	int response;
+ 
+-	/* dbg("%s - %d", __FUNCTION__, reset_bit); */
++	/* dbg("%s - %d", __func__, reset_bit); */
+ 	response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+ 	if (response < 0)
+-		dev_err(&serial->dev->dev, "%s- %d failed\n", __FUNCTION__, reset_bit);
++		dev_err(&serial->dev->dev, "%s- %d failed\n", __func__, reset_bit);
+ 	return response;
+ }
+ 
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index 3abb3c8..23f51a4 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -439,9 +439,6 @@ static struct usb_serial_driver ftdi_sio_device = {
+ 	.description =		"FTDI USB Serial Device",
+ 	.usb_driver = 		&ftdi_driver ,
+ 	.id_table =		id_table_combined,
+-	.num_interrupt_in =	0,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.probe =		ftdi_sio_probe,
+ 	.port_probe =		ftdi_sio_port_probe,
+@@ -528,14 +525,13 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned
+ 	int rv;
+ 
+ 	if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
+-		dbg("%s - DTR|RTS not being set|cleared", __FUNCTION__);
++		dbg("%s - DTR|RTS not being set|cleared", __func__);
+ 		return 0;	/* no change */
+ 	}
+ 
+ 	buf = kmalloc(1, GFP_NOIO);
+-	if (!buf) {
++	if (!buf)
+ 		return -ENOMEM;
+-	}
+ 
+ 	clear &= ~set;	/* 'set' takes precedence over 'clear' */
+ 	urb_value = 0;
+@@ -557,17 +553,18 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned
+ 	kfree(buf);
+ 	if (rv < 0) {
+ 		err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
+-				__FUNCTION__,
++				__func__,
+ 				(set & TIOCM_DTR) ? "HIGH" :
+ 				(clear & TIOCM_DTR) ? "LOW" : "unchanged",
+ 				(set & TIOCM_RTS) ? "HIGH" :
+ 				(clear & TIOCM_RTS) ? "LOW" : "unchanged");
+ 	} else {
+-		dbg("%s - DTR %s, RTS %s", __FUNCTION__,
++		dbg("%s - DTR %s, RTS %s", __func__,
+ 				(set & TIOCM_DTR) ? "HIGH" :
+ 				(clear & TIOCM_DTR) ? "LOW" : "unchanged",
+ 				(set & TIOCM_RTS) ? "HIGH" :
+ 				(clear & TIOCM_RTS) ? "LOW" : "unchanged");
++		/* FIXME: locking on last_dtr_rts */
+ 		priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set;
+ 	}
+ 	return rv;
+@@ -642,7 +639,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ 	/* 1. Get the baud rate from the tty settings, this observes alt_speed hack */
+ 
+ 	baud = tty_get_baud_rate(port->tty);
+-	dbg("%s - tty_get_baud_rate reports speed %d", __FUNCTION__, baud);
++	dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud);
+ 
+ 	/* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
+ 
+@@ -650,7 +647,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ 	    ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
+ 	     (priv->custom_divisor)) {
+ 		baud = priv->baud_base / priv->custom_divisor;
+-		dbg("%s - custom divisor %d sets baud rate to %d", __FUNCTION__, priv->custom_divisor, baud);
++		dbg("%s - custom divisor %d sets baud rate to %d", __func__, priv->custom_divisor, baud);
+ 	}
+ 
+ 	/* 3. Convert baudrate to device-specific divisor */
+@@ -671,7 +668,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ 		case 115200: div_value = ftdi_sio_b115200; break;
+ 		} /* baud */
+ 		if (div_value == 0) {
+-			dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__,  baud);
++			dbg("%s - Baudrate (%d) requested is not supported", __func__,  baud);
+ 			div_value = ftdi_sio_b9600;
+ 			baud = 9600;
+ 			div_okay = 0;
+@@ -681,7 +678,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ 		if (baud <= 3000000) {
+ 			div_value = ftdi_232am_baud_to_divisor(baud);
+ 		} else {
+-	                dbg("%s - Baud rate too high!", __FUNCTION__);
++	                dbg("%s - Baud rate too high!", __func__);
+ 			baud = 9600;
+ 			div_value = ftdi_232am_baud_to_divisor(9600);
+ 			div_okay = 0;
+@@ -693,7 +690,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ 		if (baud <= 3000000) {
+ 			div_value = ftdi_232bm_baud_to_divisor(baud);
+ 		} else {
+-	                dbg("%s - Baud rate too high!", __FUNCTION__);
++	                dbg("%s - Baud rate too high!", __func__);
+ 			div_value = ftdi_232bm_baud_to_divisor(9600);
+ 			div_okay = 0;
+ 			baud = 9600;
+@@ -703,7 +700,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ 
+ 	if (div_okay) {
+ 		dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
+-			__FUNCTION__, baud, (unsigned long)div_value,
++			__func__, baud, (unsigned long)div_value,
+ 			ftdi_chip_name[priv->chip_type]);
+ 	}
+ 
+@@ -804,7 +801,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
+ 
+ 	version = le16_to_cpu(udev->descriptor.bcdDevice);
+ 	interfaces = udev->actconfig->desc.bNumInterfaces;
+-	dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __FUNCTION__,
++	dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __func__,
+ 			version, interfaces);
+ 	if (interfaces > 1) {
+ 		int inter;
+@@ -822,7 +819,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
+ 		 * to 0x200 when iSerialNumber is 0.  */
+ 		if (version < 0x500) {
+ 			dbg("%s: something fishy - bcdDevice too low for multi-interface device",
+-					__FUNCTION__);
++					__func__);
+ 		}
+ 	} else if (version < 0x200) {
+ 		/* Old device.  Assume its the original SIO. */
+@@ -860,7 +857,7 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
+ 	int rv = 0;
+ 
+ 
+-	dbg("%s",__FUNCTION__);
++	dbg("%s",__func__);
+ 
+ 	rv = usb_control_msg(udev,
+ 			     usb_rcvctrlpipe(udev, 0),
+@@ -887,7 +884,7 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
+ 	int v = simple_strtoul(valbuf, NULL, 10);
+ 	int rv = 0;
+ 
+-	dbg("%s: setting latency timer = %i", __FUNCTION__, v);
++	dbg("%s: setting latency timer = %i", __func__, v);
+ 
+ 	rv = usb_control_msg(udev,
+ 			     usb_sndctrlpipe(udev, 0),
+@@ -916,7 +913,7 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
+ 	int v = simple_strtoul(valbuf, NULL, 10);
+ 	int rv = 0;
+ 
+-	dbg("%s: setting event char = %i", __FUNCTION__, v);
++	dbg("%s: setting event char = %i", __func__, v);
+ 
+ 	rv = usb_control_msg(udev,
+ 			     usb_sndctrlpipe(udev, 0),
+@@ -941,7 +938,7 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
+ 	struct ftdi_private *priv = usb_get_serial_port_data(port);
+ 	int retval = 0;
+ 
+-	dbg("%s",__FUNCTION__);
++	dbg("%s",__func__);
+ 
+ 	/* XXX I've no idea if the original SIO supports the event_char
+ 	 * sysfs parameter, so I'm playing it safe.  */
+@@ -963,7 +960,7 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
+ {
+ 	struct ftdi_private *priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s",__FUNCTION__);
++	dbg("%s",__func__);
+ 
+ 	/* XXX see create_sysfs_attrs */
+ 	if (priv->chip_type != SIO) {
+@@ -1005,11 +1002,11 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
+ 	struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
+ 
+ 
+-	dbg("%s",__FUNCTION__);
++	dbg("%s",__func__);
+ 
+ 	priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+ 	if (!priv){
+-		err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
++		err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct ftdi_private));
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -1058,7 +1055,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
+ /* Called from usbserial:serial_probe */
+ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
+ {
+-	dbg("%s",__FUNCTION__);
++	dbg("%s",__func__);
+ 
+ 	priv->flags |= ASYNC_SPD_CUST;
+ 	priv->custom_divisor = 77;
+@@ -1069,7 +1066,7 @@ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
+  * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled.  */
+ static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
+ {
+-	dbg("%s",__FUNCTION__);
++	dbg("%s",__func__);
+ 
+ 	priv->flags |= ASYNC_SPD_CUST;
+ 	priv->custom_divisor = 240;
+@@ -1087,7 +1084,7 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
+ 	struct usb_device *udev = serial->dev;
+ 	struct usb_interface *interface = serial->interface;
+ 
+-	dbg("%s",__FUNCTION__);
++	dbg("%s",__func__);
+ 
+ 	if (interface == udev->actconfig->interface[0]) {
+ 		info("Ignoring serial port reserved for JTAG");
+@@ -1123,14 +1120,14 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
+  */
+ static void ftdi_shutdown (struct usb_serial *serial)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ }
+ 
+ static int ftdi_sio_port_remove(struct usb_serial_port *port)
+ {
+ 	struct ftdi_private *priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	remove_sysfs_attrs(port);
+ 
+@@ -1155,7 +1152,7 @@ static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
+ 	int result = 0;
+ 	char buf[1]; /* Needed for the usb_control_msg I think */
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	spin_lock_irqsave(&priv->tx_lock, flags);
+ 	priv->tx_bytes = 0;
+@@ -1200,7 +1197,7 @@ static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
+ 		      ftdi_read_bulk_callback, port);
+ 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (result)
+-		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
++		err("%s - failed submitting read urb, error %d", __func__, result);
+ 
+ 
+ 	return result;
+@@ -1222,7 +1219,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
+ 	struct ftdi_private *priv = usb_get_serial_port_data(port);
+ 	char buf[1];
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	mutex_lock(&port->serial->disc_mutex);
+ 	if (c_cflag & HUPCL && !port->serial->disconnected){
+@@ -1269,7 +1266,7 @@ static int ftdi_write (struct usb_serial_port *port,
+ 	int transfer_size;
+ 	unsigned long flags;
+ 
+-	dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
++	dbg("%s port %d, %d bytes", __func__, port->number, count);
+ 
+ 	if (count == 0) {
+ 		dbg("write request of 0 bytes");
+@@ -1278,7 +1275,7 @@ static int ftdi_write (struct usb_serial_port *port,
+ 	spin_lock_irqsave(&priv->tx_lock, flags);
+ 	if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) {
+ 		spin_unlock_irqrestore(&priv->tx_lock, flags);
+-		dbg("%s - write limit hit\n", __FUNCTION__);
++		dbg("%s - write limit hit\n", __func__);
+ 		return 0;
+ 	}
+ 	priv->tx_outstanding_urbs++;
+@@ -1298,14 +1295,14 @@ static int ftdi_write (struct usb_serial_port *port,
+ 
+ 	buffer = kmalloc (transfer_size, GFP_ATOMIC);
+ 	if (!buffer) {
+-		err("%s ran out of kernel memory for urb ...", __FUNCTION__);
++		err("%s ran out of kernel memory for urb ...", __func__);
+ 		count = -ENOMEM;
+ 		goto error_no_buffer;
+ 	}
+ 
+ 	urb = usb_alloc_urb(0, GFP_ATOMIC);
+ 	if (!urb) {
+-		err("%s - no more free urbs", __FUNCTION__);
++		err("%s - no more free urbs", __func__);
+ 		count = -ENOMEM;
+ 		goto error_no_urb;
+ 	}
+@@ -1337,7 +1334,7 @@ static int ftdi_write (struct usb_serial_port *port,
+ 		memcpy (buffer, buf, count);
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer);
++	usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer);
+ 
+ 	/* fill the buffer and send it */
+ 	usb_fill_bulk_urb(urb, port->serial->dev,
+@@ -1347,7 +1344,7 @@ static int ftdi_write (struct usb_serial_port *port,
+ 
+ 	status = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if (status) {
+-		err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
++		err("%s - failed submitting write urb, error %d", __func__, status);
+ 		count = status;
+ 		goto error;
+ 	} else {
+@@ -1361,7 +1358,7 @@ static int ftdi_write (struct usb_serial_port *port,
+ 	 * really free it when it is finished with it */
+ 	usb_free_urb(urb);
+ 
+-	dbg("%s write returning: %d", __FUNCTION__, count);
++	dbg("%s write returning: %d", __func__, count);
+ 	return count;
+ error:
+ 	usb_free_urb(urb);
+@@ -1380,7 +1377,7 @@ error_no_buffer:
+ static void ftdi_write_bulk_callback (struct urb *urb)
+ {
+ 	unsigned long flags;
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct ftdi_private *priv;
+ 	int data_offset;       /* will be 1 for the SIO and 0 otherwise */
+ 	unsigned long countback;
+@@ -1389,7 +1386,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
+ 	/* free up the transfer buffer, as usb_free_urb() does not do this */
+ 	kfree (urb->transfer_buffer);
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("nonzero write bulk status received: %d", status);
+@@ -1398,7 +1395,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
+ 
+ 	priv = usb_get_serial_port_data(port);
+ 	if (!priv) {
+-		dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
++		dbg("%s - bad port private data pointer - exiting", __func__);
+ 		return;
+ 	}
+ 	/* account for transferred data */
+@@ -1406,7 +1403,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
+ 	data_offset = priv->write_offset;
+ 	if (data_offset > 0) {
+ 		/* Subtract the control bytes */
+-		countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ));
++		countback -= (data_offset * DIV_ROUND_UP(countback, PKTSZ));
+ 	}
+ 	spin_lock_irqsave(&priv->tx_lock, flags);
+ 	--priv->tx_outstanding_urbs;
+@@ -1423,7 +1420,7 @@ static int ftdi_write_room( struct usb_serial_port *port )
+ 	int room;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->tx_lock, flags);
+ 	if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) {
+@@ -1447,13 +1444,13 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port)
+ 	int buffered;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->tx_lock, flags);
+ 	buffered = (int)priv->tx_outstanding_bytes;
+ 	spin_unlock_irqrestore(&priv->tx_lock, flags);
+ 	if (buffered < 0) {
+-		err("%s outstanding tx bytes is negative!", __FUNCTION__);
++		err("%s outstanding tx bytes is negative!", __func__);
+ 		buffered = 0;
+ 	}
+ 	return buffered;
+@@ -1463,7 +1460,7 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port)
+ 
+ static void ftdi_read_bulk_callback (struct urb *urb)
+ { /* ftdi_read_bulk_callback */
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct tty_struct *tty;
+ 	struct ftdi_private *priv;
+ 	unsigned long countread;
+@@ -1471,30 +1468,30 @@ static void ftdi_read_bulk_callback (struct urb *urb)
+ 	int status = urb->status;
+ 
+ 	if (urb->number_of_packets > 0) {
+-		err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
++		err("%s transfer_buffer_length %d actual_length %d number of packets %d",__func__,
+ 		    urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets );
+-		err("%s transfer_flags %x ", __FUNCTION__,urb->transfer_flags );
++		err("%s transfer_flags %x ", __func__,urb->transfer_flags );
+ 	}
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (port->open_count <= 0)
+ 		return;
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - bad tty pointer - exiting",__FUNCTION__);
++		dbg("%s - bad tty pointer - exiting",__func__);
+ 		return;
+ 	}
+ 
+ 	priv = usb_get_serial_port_data(port);
+ 	if (!priv) {
+-		dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
++		dbg("%s - bad port private data pointer - exiting", __func__);
+ 		return;
+ 	}
+ 
+ 	if (urb != port->read_urb) {
+-		err("%s - Not my urb!", __FUNCTION__);
++		err("%s - Not my urb!", __func__);
+ 	}
+ 
+ 	if (status) {
+@@ -1506,7 +1503,7 @@ static void ftdi_read_bulk_callback (struct urb *urb)
+ 
+ 	/* count data bytes, but not status bytes */
+ 	countread = urb->actual_length;
+-	countread -= 2 * ((countread + (PKTSZ - 1)) / PKTSZ);
++	countread -= 2 * DIV_ROUND_UP(countread, PKTSZ);
+ 	spin_lock_irqsave(&priv->rx_lock, flags);
+ 	priv->rx_bytes += countread;
+ 	spin_unlock_irqrestore(&priv->rx_lock, flags);
+@@ -1532,39 +1529,39 @@ static void ftdi_process_read (struct work_struct *work)
+ 	int packet_offset;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (port->open_count <= 0)
+ 		return;
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - bad tty pointer - exiting",__FUNCTION__);
++		dbg("%s - bad tty pointer - exiting",__func__);
+ 		return;
+ 	}
+ 
+ 	priv = usb_get_serial_port_data(port);
+ 	if (!priv) {
+-		dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
++		dbg("%s - bad port private data pointer - exiting", __func__);
+ 		return;
+ 	}
+ 
+ 	urb = port->read_urb;
+ 	if (!urb) {
+-		dbg("%s - bad read_urb pointer - exiting", __FUNCTION__);
++		dbg("%s - bad read_urb pointer - exiting", __func__);
+ 		return;
+ 	}
+ 
+ 	data = urb->transfer_buffer;
+ 
+ 	if (priv->rx_processed) {
+-		dbg("%s - already processed: %d bytes, %d remain", __FUNCTION__,
++		dbg("%s - already processed: %d bytes, %d remain", __func__,
+ 				priv->rx_processed,
+ 				urb->actual_length - priv->rx_processed);
+ 	} else {
+ 		/* The first two bytes of every read packet are status */
+ 		if (urb->actual_length > 2) {
+-			usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++			usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 		} else {
+ 			dbg("Status only: %03oo %03oo",data[0],data[1]);
+ 		}
+@@ -1594,17 +1591,17 @@ static void ftdi_process_read (struct work_struct *work)
+ 
+ 		length = min(PKTSZ, urb->actual_length-packet_offset)-2;
+ 		if (length < 0) {
+-			err("%s - bad packet length: %d", __FUNCTION__, length+2);
++			err("%s - bad packet length: %d", __func__, length+2);
+ 			length = 0;
+ 		}
+ 
+ 		if (priv->rx_flags & THROTTLED) {
+-			dbg("%s - throttled", __FUNCTION__);
++			dbg("%s - throttled", __func__);
+ 			break;
+ 		}
+ 		if (tty_buffer_request_room(tty, length) < length) {
+ 			/* break out & wait for throttling/unthrottling to happen */
+-			dbg("%s - receive room low", __FUNCTION__);
++			dbg("%s - receive room low", __func__);
+ 			break;
+ 		}
+ 
+@@ -1672,7 +1669,7 @@ static void ftdi_process_read (struct work_struct *work)
+ 		/* not completely processed - record progress */
+ 		priv->rx_processed = packet_offset;
+ 		dbg("%s - incomplete, %d bytes processed, %d remain",
+-				__FUNCTION__, packet_offset,
++				__func__, packet_offset,
+ 				urb->actual_length - packet_offset);
+ 		/* check if we were throttled while processing */
+ 		spin_lock_irqsave(&priv->rx_lock, flags);
+@@ -1680,7 +1677,7 @@ static void ftdi_process_read (struct work_struct *work)
+ 			priv->rx_flags |= ACTUALLY_THROTTLED;
+ 			spin_unlock_irqrestore(&priv->rx_lock, flags);
+ 			dbg("%s - deferring remainder until unthrottled",
+-					__FUNCTION__);
++					__func__);
+ 			return;
+ 		}
+ 		spin_unlock_irqrestore(&priv->rx_lock, flags);
+@@ -1689,7 +1686,7 @@ static void ftdi_process_read (struct work_struct *work)
+ 			/* delay processing of remainder */
+ 			schedule_delayed_work(&priv->rx_work, 1);
+ 		} else {
+-			dbg("%s - port is closed", __FUNCTION__);
++			dbg("%s - port is closed", __func__);
+ 		}
+ 		return;
+ 	}
+@@ -1707,7 +1704,7 @@ static void ftdi_process_read (struct work_struct *work)
+ 
+ 		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 		if (result)
+-			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++			err("%s - failed resubmitting read urb, error %d", __func__, result);
+ 	}
+ 
+ 	return;
+@@ -1736,10 +1733,10 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
+ 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
+ 			    urb_value , priv->interface,
+ 			    buf, 0, WDR_TIMEOUT) < 0) {
+-		err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state);
++		err("%s FAILED to enable/disable break state (state was %d)", __func__,break_state);
+ 	}
+ 
+-	dbg("%s break state is %d - urb is %d", __FUNCTION__,break_state, urb_value);
++	dbg("%s break state is %d - urb is %d", __func__,break_state, urb_value);
+ 
+ }
+ 
+@@ -1763,18 +1760,18 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ 	unsigned char vstop;
+ 	unsigned char vstart;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* Force baud rate if this device requires it, unless it is set to B0. */
+ 	if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) {
+-		dbg("%s: forcing baud rate for this device", __FUNCTION__);
++		dbg("%s: forcing baud rate for this device", __func__);
+ 		tty_encode_baud_rate(port->tty, priv->force_baud,
+ 					priv->force_baud);
+ 	}
+ 
+ 	/* Force RTS-CTS if this device requires it. */
+ 	if (priv->force_rtscts) {
+-		dbg("%s: forcing rtscts for this device", __FUNCTION__);
++		dbg("%s: forcing rtscts for this device", __func__);
+ 		termios->c_cflag |= CRTSCTS;
+ 	}
+ 
+@@ -1818,7 +1815,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
+ 			    urb_value , priv->interface,
+ 			    buf, 0, WDR_SHORT_TIMEOUT) < 0) {
+-		err("%s FAILED to set databits/stopbits/parity", __FUNCTION__);
++		err("%s FAILED to set databits/stopbits/parity", __func__);
+ 	}
+ 
+ 	/* Now do the baudrate */
+@@ -1829,14 +1826,14 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+ 				    0, priv->interface,
+ 				    buf, 0, WDR_TIMEOUT) < 0) {
+-			err("%s error from disable flowcontrol urb", __FUNCTION__);
++			err("%s error from disable flowcontrol urb", __func__);
+ 		}
+ 		/* Drop RTS and DTR */
+ 		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ 	} else {
+ 		/* set the baudrate determined before */
+ 		if (change_speed(port)) {
+-			err("%s urb failed to set baudrate", __FUNCTION__);
++			err("%s urb failed to set baudrate", __func__);
+ 		}
+ 		/* Ensure RTS and DTR are raised when baudrate changed from 0 */
+ 		if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) {
+@@ -1847,7 +1844,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ 	/* Set flow control */
+ 	/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
+ 	if (cflag & CRTSCTS) {
+-		dbg("%s Setting to CRTSCTS flow control", __FUNCTION__);
++		dbg("%s Setting to CRTSCTS flow control", __func__);
+ 		if (usb_control_msg(dev,
+ 				    usb_sndctrlpipe(dev, 0),
+ 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+@@ -1865,7 +1862,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ 		 * if IXOFF is not set, the pre-xon/xoff code is executed.
+ 		*/
+ 		if (iflag & IXOFF) {
+-			dbg("%s  request to enable xonxoff iflag=%04x",__FUNCTION__,iflag);
++			dbg("%s  request to enable xonxoff iflag=%04x",__func__,iflag);
+ 			// Try to enable the XON/XOFF on the ftdi_sio
+ 			// Set the vstart and vstop -- could have been done up above where
+ 			// a lot of other dereferencing is done but that would be very
+@@ -1886,7 +1883,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ 		} else {
+ 			/* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */
+ 			/* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
+-			dbg("%s Turning off hardware flow control", __FUNCTION__);
++			dbg("%s Turning off hardware flow control", __func__);
+ 			if (usb_control_msg(dev,
+ 					    usb_sndctrlpipe(dev, 0),
+ 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+@@ -1908,7 +1905,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+ 	unsigned char buf[2];
+ 	int ret;
+ 
+-	dbg("%s TIOCMGET", __FUNCTION__);
++	dbg("%s TIOCMGET", __func__);
+ 	switch (priv->chip_type) {
+ 	case SIO:
+ 		/* Request the status from the device */
+@@ -1918,7 +1915,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+ 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 					   0, 0,
+ 					   buf, 1, WDR_TIMEOUT)) < 0 ) {
+-			err("%s Could not get modem status of device - err: %d", __FUNCTION__,
++			err("%s Could not get modem status of device - err: %d", __func__,
+ 			    ret);
+ 			return(ret);
+ 		}
+@@ -1935,7 +1932,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+ 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 					   0, priv->interface,
+ 					   buf, 2, WDR_TIMEOUT)) < 0 ) {
+-			err("%s Could not get modem status of device - err: %d", __FUNCTION__,
++			err("%s Could not get modem status of device - err: %d", __func__,
+ 			    ret);
+ 			return(ret);
+ 		}
+@@ -1954,7 +1951,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+ 
+ static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
+ {
+-	dbg("%s TIOCMSET", __FUNCTION__);
++	dbg("%s TIOCMSET", __func__);
+ 	return update_mctrl(port, set, clear);
+ }
+ 
+@@ -1963,7 +1960,7 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
+ {
+ 	struct ftdi_private *priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
++	dbg("%s cmd 0x%04x", __func__, cmd);
+ 
+ 	/* Based on code from acm.c and others */
+ 	switch (cmd) {
+@@ -2022,7 +2019,7 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
+ 	/* This is not necessarily an error - turns out the higher layers will do
+ 	 *  some ioctls itself (see comment above)
+ 	 */
+-	dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __FUNCTION__, cmd);
++	dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd);
+ 
+ 	return(-ENOIOCTLCMD);
+ } /* ftdi_ioctl */
+@@ -2033,7 +2030,7 @@ static void ftdi_throttle (struct usb_serial_port *port)
+ 	struct ftdi_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->rx_lock, flags);
+ 	priv->rx_flags |= THROTTLED;
+@@ -2047,7 +2044,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
+ 	int actually_throttled;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->rx_lock, flags);
+ 	actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
+@@ -2062,7 +2059,7 @@ static int __init ftdi_init (void)
+ {
+ 	int retval;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	if (vendor > 0 && product > 0) {
+ 		/* Add user specified VID/PID to reserved element of table. */
+ 		int i;
+@@ -2091,7 +2088,7 @@ failed_sio_register:
+ static void __exit ftdi_exit (void)
+ {
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	usb_deregister (&ftdi_driver);
+ 	usb_serial_deregister (&ftdi_sio_device);
+diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
+index b5194dc..e8ba2cb 100644
+--- a/drivers/usb/serial/funsoft.c
++++ b/drivers/usb/serial/funsoft.c
+@@ -39,9 +39,6 @@ static struct usb_serial_driver funsoft_device = {
+ 	},
+ 	.id_table =		id_table,
+ 	.usb_driver = 		&funsoft_driver,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		1,
+ };
+ 
+diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
+index d74e43d..8ce5a56 100644
+--- a/drivers/usb/serial/garmin_gps.c
++++ b/drivers/usb/serial/garmin_gps.c
+@@ -280,7 +280,7 @@ static void send_to_tty(struct usb_serial_port *port,
+ 	if (tty && actual_length) {
+ 
+ 		usb_serial_debug_data(debug, &port->dev, 
+-					__FUNCTION__, actual_length, data);
++					__func__, actual_length, data);
+ 
+ 		tty_buffer_request_room(tty, actual_length);
+ 		tty_insert_flip_string(tty, data, actual_length);
+@@ -355,7 +355,7 @@ static void pkt_clear(struct garmin_data * garmin_data_p)
+ 	unsigned long flags;
+ 	struct garmin_packet *result = NULL;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	spin_lock_irqsave(&garmin_data_p->lock, flags);
+ 	while (!list_empty(&garmin_data_p->pktlist)) {
+@@ -379,7 +379,7 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
+ 	__u8 *ptr = pkt;
+ 	unsigned  l = 0;
+ 
+-	dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
++	dbg("%s - pkt-id: 0x%X.", __func__, 0xFF & pkt_id);
+ 
+ 	*ptr++ = DLE;
+ 	*ptr++ = ACK;
+@@ -429,11 +429,11 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+ 	int size = recpkt[1];
+ 
+ 	usb_serial_debug_data(debug, &garmin_data_p->port->dev,
+-			       __FUNCTION__, count-GSP_INITIAL_OFFSET, recpkt);
++			       __func__, count-GSP_INITIAL_OFFSET, recpkt);
+ 
+ 	if (size != (count-GSP_INITIAL_OFFSET-3)) {
+ 		dbg("%s - invalid size, expected %d bytes, got %d",
+-			__FUNCTION__, size, (count-GSP_INITIAL_OFFSET-3));
++			__func__, size, (count-GSP_INITIAL_OFFSET-3));
+ 		return -EINVPKT;
+ 	}
+ 
+@@ -443,7 +443,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+ 	// sanity check, remove after test ...
+ 	if ((__u8*)&(usbdata[3]) != recpkt) {
+ 		dbg("%s - ptr mismatch %p - %p",
+-			__FUNCTION__, &(usbdata[4]), recpkt);
++			__func__, &(usbdata[4]), recpkt);
+ 		return -EINVPKT;
+ 	}
+ 
+@@ -454,7 +454,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+ 
+ 	if ((0xff & (cksum + *recpkt)) != 0) {
+ 		dbg("%s - invalid checksum, expected %02x, got %02x",
+-			__FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
++			__func__, 0xff & -cksum, 0xff & *recpkt);
+ 		return -EINVPKT;
+ 	}
+ 
+@@ -519,7 +519,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
+ 	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ 
+ 	dbg("%s - dle=%d skip=%d size=%d count=%d",
+-		__FUNCTION__, dleSeen, skip, size, count);
++		__func__, dleSeen, skip, size, count);
+ 
+ 	if (size == 0) {
+ 		size = GSP_INITIAL_OFFSET;
+@@ -578,7 +578,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
+ 		}
+ 
+ 		if (size >= GPS_IN_BUFSIZ) {
+-			dbg("%s - packet too large.", __FUNCTION__);
++			dbg("%s - packet too large.", __func__);
+ 			skip = 1;
+ 			size = GSP_INITIAL_OFFSET;
+ 			dleSeen = 0;
+@@ -634,7 +634,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
+ 	int i=0;
+ 	int k;
+ 
+-	dbg("%s - state %d - %d bytes.", __FUNCTION__,
++	dbg("%s - state %d - %d bytes.", __func__,
+ 	         garmin_data_p->state, count);
+ 
+ 	k = garmin_data_p->outsize;
+@@ -658,13 +658,13 @@ static int gsp_send(struct garmin_data * garmin_data_p,
+ 		return 0;
+ 	}
+ 
+-	dbg("%s - %d bytes in buffer, %d bytes in pkt.", __FUNCTION__,
++	dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__,
+ 	         k, i);
+ 
+ 	/* garmin_data_p->outbuffer now contains a complete packet */
+ 
+ 	usb_serial_debug_data(debug, &garmin_data_p->port->dev,
+-		                   __FUNCTION__, k, garmin_data_p->outbuffer);
++		                   __func__, k, garmin_data_p->outbuffer);
+ 
+ 	garmin_data_p->outsize = 0;
+ 
+@@ -749,7 +749,7 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
+ 	struct garmin_packet *pkt = NULL;
+ 
+ 	while ((pkt = pkt_pop(garmin_data_p)) != NULL) {
+-		dbg("%s - next pkt: %d", __FUNCTION__, pkt->seq);
++		dbg("%s - next pkt: %d", __func__, pkt->seq);
+ 		if (gsp_send(garmin_data_p, pkt->data, pkt->size) > 0) {
+ 			kfree(pkt);
+ 			return;
+@@ -794,7 +794,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
+ 		if (len >= GPS_IN_BUFSIZ) {
+ 			/* seem to be an invalid packet, ignore rest of input */
+ 			dbg("%s - packet size too large: %d",
+-			        __FUNCTION__, len);
++			        __func__, len);
+ 			garmin_data_p->insize = 0;
+ 			count = 0;
+ 			result = -EINVPKT;
+@@ -873,11 +873,11 @@ static int process_resetdev_request(struct usb_serial_port *port)
+ 	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ 
+ 	usb_kill_urb (port->interrupt_in_urb);
+-	dbg("%s - usb_reset_device", __FUNCTION__ );
++	dbg("%s - usb_reset_device", __func__ );
+ 	status = usb_reset_device(port->serial->dev);
+ 	if (status)
+ 		dbg("%s - usb_reset_device failed: %d",
+-			__FUNCTION__, status);
++			__func__, status);
+ 	return status;
+ }
+ 
+@@ -926,18 +926,18 @@ static int garmin_init_session(struct usb_serial_port *port)
+ 	if (status == 0) {
+ 		usb_kill_urb (port->interrupt_in_urb);
+ 
+-		dbg("%s - adding interrupt input", __FUNCTION__);
++		dbg("%s - adding interrupt input", __func__);
+ 		port->interrupt_in_urb->dev = serial->dev;
+ 		status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ 		if (status)
+ 			dev_err(&serial->dev->dev,
+ 			        "%s - failed submitting interrupt urb,"
+ 				" error %d\n",
+-			        __FUNCTION__, status);
++			        __func__, status);
+ 	}
+ 
+ 	if (status == 0) {
+-		dbg("%s - starting session ...", __FUNCTION__);
++		dbg("%s - starting session ...", __func__);
+ 		garmin_data_p->state = STATE_ACTIVE;
+ 		status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
+ 		                           sizeof(GARMIN_START_SESSION_REQ),
+@@ -976,7 +976,7 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
+ 	int status = 0;
+ 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/*
+ 	 * Force low_latency on so that our tty_push actually forces the data
+@@ -1013,7 +1013,7 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
+ 	struct usb_serial *serial = port->serial;
+ 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ 
+-	dbg("%s - port %d - mode=%d state=%d flags=0x%X", __FUNCTION__,
++	dbg("%s - port %d - mode=%d state=%d flags=0x%X", __func__,
+ 		port->number, garmin_data_p->mode,
+ 		garmin_data_p->state, garmin_data_p->flags);
+ 
+@@ -1046,13 +1046,13 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
+ static void garmin_write_bulk_callback (struct urb *urb)
+ {
+ 	unsigned long flags;
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int status = urb->status;
+ 
+ 	if (port) {
+ 		struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ 
+-		dbg("%s - port %d", __FUNCTION__, port->number);
++		dbg("%s - port %d", __func__, port->number);
+ 
+ 		if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)
+ 		    && (garmin_data_p->mode == MODE_GARMIN_SERIAL))  {
+@@ -1061,7 +1061,7 @@ static void garmin_write_bulk_callback (struct urb *urb)
+ 
+ 		if (status) {
+ 			dbg("%s - nonzero write bulk status received: %d",
+-			    __FUNCTION__, urb->status);
++			    __func__, urb->status);
+ 			spin_lock_irqsave(&garmin_data_p->lock, flags);
+ 			garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
+ 			spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+@@ -1088,7 +1088,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
+ 	unsigned char *buffer;
+ 	int status;
+ 
+-	dbg("%s - port %d, state %d", __FUNCTION__, port->number,
++	dbg("%s - port %d, state %d", __func__, port->number,
+ 		garmin_data_p->state);
+ 
+ 	spin_lock_irqsave(&garmin_data_p->lock, flags);
+@@ -1110,7 +1110,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
+ 
+ 	memcpy (buffer, buf, count);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+ 
+ 	usb_fill_bulk_urb (urb, serial->dev,
+ 			 	usb_sndbulkpipe (serial->dev,
+@@ -1134,7 +1134,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
+ 		dev_err(&port->dev,
+ 		        "%s - usb_submit_urb(write bulk) "
+ 		        "failed with status = %d\n",
+-				__FUNCTION__, status);
++				__func__, status);
+ 		count = status;
+ 	}
+ 
+@@ -1154,7 +1154,7 @@ static int garmin_write (struct usb_serial_port *port,
+ 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ 	__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buf);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, buf);
+ 
+ 	/* check for our private packets */
+ 	if (count >= GARMIN_PKTHDR_LENGTH) {
+@@ -1172,7 +1172,7 @@ static int garmin_write (struct usb_serial_port *port,
+ 		    && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) {
+ 
+ 			dbg("%s - processing private request %d",
+-				__FUNCTION__, pktid);
++				__func__, pktid);
+ 
+ 			// drop all unfinished transfers
+ 			garmin_clear(garmin_data_p);
+@@ -1184,7 +1184,7 @@ static int garmin_write (struct usb_serial_port *port,
+ 					return -EINVPKT;
+ 				debug = __le32_to_cpu(privpkt[3]);
+ 				dbg("%s - debug level set to 0x%X",
+-					__FUNCTION__, debug);
++					__func__, debug);
+ 				break;
+ 
+ 			case PRIV_PKTID_SET_MODE:
+@@ -1192,7 +1192,7 @@ static int garmin_write (struct usb_serial_port *port,
+ 					return -EINVPKT;
+ 				garmin_data_p->mode = __le32_to_cpu(privpkt[3]);
+ 				dbg("%s - mode set to %d",
+-					__FUNCTION__, garmin_data_p->mode);
++					__func__, garmin_data_p->mode);
+ 				break;
+ 
+ 			case PRIV_PKTID_INFO_REQ:
+@@ -1208,7 +1208,7 @@ static int garmin_write (struct usb_serial_port *port,
+ 					return -EINVPKT;
+ 				initial_mode = __le32_to_cpu(privpkt[3]);
+ 				dbg("%s - initial_mode set to %d",
+-					__FUNCTION__,
++					__func__,
+ 					garmin_data_p->mode);
+ 				break;
+ 			}
+@@ -1255,7 +1255,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
+ {
+ 	if (garmin_data_p->flags & FLAGS_DROP_DATA) {
+ 		/* abort-transfer cmd is actice */
+-		dbg("%s - pkt dropped", __FUNCTION__);
++		dbg("%s - pkt dropped", __func__);
+ 	} else if (garmin_data_p->state != STATE_DISCONNECTED &&
+ 	           garmin_data_p->state != STATE_RESET ) {
+ 
+@@ -1286,28 +1286,28 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
+ static void garmin_read_bulk_callback (struct urb *urb)
+ {
+ 	unsigned long flags;
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct usb_serial *serial =  port->serial;
+ 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int status = urb->status;
+ 	int retval;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!serial) {
+-		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
++		dbg("%s - bad serial pointer, exiting", __func__);
+ 		return;
+ 	}
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		return;
+ 	}
+ 
+ 	usb_serial_debug_data(debug, &port->dev, 
+-				__FUNCTION__, urb->actual_length, data);
++				__func__, urb->actual_length, data);
+ 
+ 	garmin_read_process(garmin_data_p, data, urb->actual_length);
+ 
+@@ -1320,7 +1320,7 @@ static void garmin_read_bulk_callback (struct urb *urb)
+ 		if (retval)
+ 			dev_err(&port->dev,
+ 				"%s - failed resubmitting read urb, error %d\n",
+-				__FUNCTION__, retval);
++				__func__, retval);
+ 	} else if (urb->actual_length > 0) {
+ 		/* Continue trying to read until nothing more is received  */
+ 		if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
+@@ -1328,10 +1328,10 @@ static void garmin_read_bulk_callback (struct urb *urb)
+ 			if (retval)
+ 				dev_err(&port->dev,
+ 					"%s - failed resubmitting read urb, "
+-					"error %d\n", __FUNCTION__, retval);
++					"error %d\n", __func__, retval);
+ 		}
+ 	} else {
+-		dbg("%s - end of bulk data", __FUNCTION__);
++		dbg("%s - end of bulk data", __func__);
+ 		spin_lock_irqsave(&garmin_data_p->lock, flags);
+ 		garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE;
+ 		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+@@ -1344,7 +1344,7 @@ static void garmin_read_int_callback (struct urb *urb)
+ {
+ 	unsigned long flags;
+ 	int retval;
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct usb_serial *serial = port->serial;
+ 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ 	unsigned char *data = urb->transfer_buffer;
+@@ -1359,22 +1359,22 @@ static void garmin_read_int_callback (struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		return;
+ 	default:
+ 		dbg("%s - nonzero urb status received: %d",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, 
++	usb_serial_debug_data(debug, &port->dev, __func__,
+ 				urb->actual_length, urb->transfer_buffer);
+ 
+ 	if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) &&
+ 	    0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY,
+ 		        sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
+ 
+-		dbg("%s - bulk data available.", __FUNCTION__);
++		dbg("%s - bulk data available.", __func__);
+ 
+ 		if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
+ 
+@@ -1389,7 +1389,7 @@ static void garmin_read_int_callback (struct urb *urb)
+ 			if (retval) {
+ 				dev_err(&port->dev,
+ 					"%s - failed submitting read urb, error %d\n",
+-				__FUNCTION__, retval);
++				__func__, retval);
+ 			} else {
+ 				spin_lock_irqsave(&garmin_data_p->lock, flags);
+ 				garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
+@@ -1417,14 +1417,14 @@ static void garmin_read_int_callback (struct urb *urb)
+ 			= __le32_to_cpup((__le32*)(data+GARMIN_PKTHDR_LENGTH));
+ 
+ 		dbg("%s - start-of-session reply seen - serial %u.",
+-			__FUNCTION__, garmin_data_p->serial_num);
++			__func__, garmin_data_p->serial_num);
+ 	}
+ 
+ 	if (garmin_data_p->ignorePkts) {
+ 		/* this reply belongs to a request generated by the driver,
+ 		   ignore it. */
+ 		dbg("%s - pkt ignored (%d)",
+-			__FUNCTION__, garmin_data_p->ignorePkts);
++			__func__, garmin_data_p->ignorePkts);
+ 		spin_lock_irqsave(&garmin_data_p->lock, flags);
+ 		garmin_data_p->ignorePkts--;
+ 		spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+@@ -1437,7 +1437,7 @@ static void garmin_read_int_callback (struct urb *urb)
+ 	if (retval)
+ 		dev_err(&urb->dev->dev,
+ 			"%s - Error %d submitting interrupt urb\n",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ }
+ 
+ 
+@@ -1473,7 +1473,7 @@ static void garmin_throttle (struct usb_serial_port *port)
+ 	unsigned long flags;
+ 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	/* set flag, data received will be put into a queue
+ 	   for later processing */
+ 	spin_lock_irqsave(&garmin_data_p->lock, flags);
+@@ -1488,7 +1488,7 @@ static void garmin_unthrottle (struct usb_serial_port *port)
+ 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	spin_lock_irqsave(&garmin_data_p->lock, flags);
+ 	garmin_data_p->flags &= ~FLAGS_THROTTLED;
+ 	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+@@ -1503,7 +1503,7 @@ static void garmin_unthrottle (struct usb_serial_port *port)
+ 		if (status)
+ 			dev_err(&port->dev,
+ 				"%s - failed resubmitting read urb, error %d\n",
+-				__FUNCTION__, status);
++				__func__, status);
+ 	}
+ }
+ 
+@@ -1532,11 +1532,11 @@ static int garmin_attach (struct usb_serial *serial)
+ 	struct usb_serial_port *port = serial->port[0];
+ 	struct garmin_data * garmin_data_p = NULL;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
+ 	if (garmin_data_p == NULL) {
+-		dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
++		dev_err(&port->dev, "%s - Out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	init_timer(&garmin_data_p->timer);
+@@ -1561,7 +1561,7 @@ static void garmin_shutdown (struct usb_serial *serial)
+ 	struct usb_serial_port *port = serial->port[0];
+ 	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	usb_kill_urb (port->interrupt_in_urb);
+ 	del_timer_sync(&garmin_data_p->timer);
+@@ -1579,9 +1579,6 @@ static struct usb_serial_driver garmin_device = {
+ 	.description         = "Garmin GPS usb/tty",
+ 	.usb_driver          = &garmin_driver,
+ 	.id_table            = id_table,
+-	.num_interrupt_in    = 1,
+-	.num_bulk_in         = 1,
+-	.num_bulk_out        = 1,
+ 	.num_ports           = 1,
+ 	.open                = garmin_open,
+ 	.close               = garmin_close,
+diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
+index 7cfce9d..537f12a 100644
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -62,9 +62,6 @@ struct usb_serial_driver usb_serial_generic_device = {
+ 	},
+ 	.id_table =		generic_device_ids,
+ 	.usb_driver = 		&generic_driver,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		1,
+ 	.shutdown =		usb_serial_generic_shutdown,
+ 	.throttle =		usb_serial_generic_throttle,
+@@ -121,7 +118,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
+ 	int result = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* force low_latency on so that our tty_push actually forces the data through, 
+ 	   otherwise it is scheduled, and with high data rates (like with OHCI) data
+@@ -148,7 +145,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
+ 				   port);
+ 		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 		if (result)
+-			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ 	}
+ 
+ 	return result;
+@@ -159,7 +156,7 @@ static void generic_cleanup (struct usb_serial_port *port)
+ {
+ 	struct usb_serial *serial = port->serial;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (serial->dev) {
+ 		/* shutdown any bulk reads that might be going on */
+@@ -197,7 +194,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
+ 
+ void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	generic_cleanup (port);
+ }
+ 
+@@ -207,10 +204,10 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
+ 	int result;
+ 	unsigned char *data;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (count == 0) {
+-		dbg("%s - write request of 0 bytes", __FUNCTION__);
++		dbg("%s - write request of 0 bytes", __func__);
+ 		return (0);
+ 	}
+ 
+@@ -220,7 +217,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
+ 		spin_lock_irqsave(&port->lock, flags);
+ 		if (port->write_urb_busy) {
+ 			spin_unlock_irqrestore(&port->lock, flags);
+-			dbg("%s - already writing", __FUNCTION__);
++			dbg("%s - already writing", __func__);
+ 			return 0;
+ 		}
+ 		port->write_urb_busy = 1;
+@@ -230,7 +227,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
+ 
+ 		memcpy (port->write_urb->transfer_buffer, buf, count);
+ 		data = port->write_urb->transfer_buffer;
+-		usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, data);
++		usb_serial_debug_data(debug, &port->dev, __func__, count, data);
+ 
+ 		/* set up our urb */
+ 		usb_fill_bulk_urb (port->write_urb, serial->dev,
+@@ -245,7 +242,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
+ 		port->write_urb_busy = 1;
+ 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 		if (result) {
+-			dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
++			dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ 			/* don't have to grab the lock here, as we will retry if != 0 */
+ 			port->write_urb_busy = 0;
+ 		} else
+@@ -263,15 +260,16 @@ int usb_serial_generic_write_room (struct usb_serial_port *port)
+ 	struct usb_serial *serial = port->serial;
+ 	int room = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
++	/* FIXME: Locking */
+ 	if (serial->num_bulk_out) {
+ 		if (!(port->write_urb_busy))
+ 			room = port->bulk_out_size;
+ 	}
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
+-	return (room);
++	dbg("%s - returns %d", __func__, room);
++	return room;
+ }
+ 
+ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
+@@ -279,14 +277,15 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
+ 	struct usb_serial *serial = port->serial;
+ 	int chars = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
++	/* FIXME: Locking */
+ 	if (serial->num_bulk_out) {
+ 		if (port->write_urb_busy)
+ 			chars = port->write_urb->transfer_buffer_length;
+ 	}
+ 
+-	dbg("%s - returns %d", __FUNCTION__, chars);
++	dbg("%s - returns %d", __func__, chars);
+ 	return (chars);
+ }
+ 
+@@ -308,7 +307,7 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
+ 			     usb_serial_generic_read_bulk_callback), port);
+ 	result = usb_submit_urb(urb, mem_flags);
+ 	if (result)
+-		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ }
+ 
+ /* Push data to tty layer and resubmit the bulk read URB */
+@@ -332,20 +331,20 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+ 
+ void usb_serial_generic_read_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int status = urb->status;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (unlikely(status != 0)) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	/* Throttle the device if requested by tty */
+ 	spin_lock_irqsave(&port->lock, flags);
+@@ -360,18 +359,17 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
+ 
+ void usb_serial_generic_write_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	port->write_urb_busy = 0;
+ 	if (status) {
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+-
+ 	usb_serial_port_softint(port);
+ }
+ EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
+@@ -380,7 +378,7 @@ void usb_serial_generic_throttle (struct usb_serial_port *port)
+ {
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* Set the throttle request flag. It will be picked up
+ 	 * by usb_serial_generic_read_bulk_callback(). */
+@@ -394,7 +392,7 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port)
+ 	int was_throttled;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* Clear the throttle flags */
+ 	spin_lock_irqsave(&port->lock, flags);
+@@ -412,7 +410,7 @@ void usb_serial_generic_shutdown (struct usb_serial *serial)
+ {
+ 	int i;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* stop reads and writes on all ports */
+ 	for (i=0; i < serial->num_ports; ++i) {
+diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
+index 6c6ebae..75b88b3 100644
+--- a/drivers/usb/serial/hp4x.c
++++ b/drivers/usb/serial/hp4x.c
+@@ -50,9 +50,6 @@ static struct usb_serial_driver hp49gp_device = {
+ 	},
+ 	.id_table =		id_table,
+ 	.usb_driver = 		&hp49gp_driver,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		1,
+ };
+ 
+diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
+index 3428ccc..ce2e487 100644
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -371,7 +371,7 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
+ 	struct usb_string_descriptor StringDesc;
+ 	struct usb_string_descriptor *pStringDesc;
+ 
+-	dbg("%s - USB String ID = %d", __FUNCTION__, Id );
++	dbg("%s - USB String ID = %d", __func__, Id );
+ 
+ 	if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+ 		return 0;
+@@ -391,7 +391,7 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
+ 	unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2);
+ 
+ 	kfree(pStringDesc);
+-	dbg("%s - USB String %s", __FUNCTION__, string);
++	dbg("%s - USB String %s", __func__, string);
+ 	return strlen(string);
+ }
+ 
+@@ -407,7 +407,7 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de
+ 	struct usb_string_descriptor StringDesc;
+ 	struct usb_string_descriptor *pStringDesc;
+ 
+-	dbg("%s - USB String ID = %d", __FUNCTION__, Id );
++	dbg("%s - USB String ID = %d", __func__, Id );
+ 
+ 	if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+ 		return 0;
+@@ -537,7 +537,7 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
+ 				 sizeof(struct edge_compatibility_descriptor),
+ 				 300);
+ 
+-	dbg("%s result = %d", __FUNCTION__, result);
++	dbg("%s result = %d", __func__, result);
+ 
+ 	if (result > 0) {
+ 		ep->is_epic = 1;
+@@ -589,7 +589,7 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
+  *****************************************************************************/
+ static void edge_interrupt_callback (struct urb *urb)
+ {
+-	struct edgeport_serial	*edge_serial = (struct edgeport_serial *)urb->context;
++	struct edgeport_serial	*edge_serial = urb->context;
+ 	struct edgeport_port *edge_port;
+ 	struct usb_serial_port *port;
+ 	unsigned char *data = urb->transfer_buffer;
+@@ -601,7 +601,7 @@ static void edge_interrupt_callback (struct urb *urb)
+ 	int result;
+ 	int status = urb->status;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -612,35 +612,35 @@ static void edge_interrupt_callback (struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	default:
+ 		dbg("%s - nonzero urb status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		goto exit;
+ 	}
+ 
+ 	// process this interrupt-read even if there are no ports open
+ 	if (length) {
+-		usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data);
++		usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
+ 
+ 		if (length > 1) {
+ 			bytes_avail = data[0] | (data[1] << 8);
+ 			if (bytes_avail) {
+ 				spin_lock(&edge_serial->es_lock);
+ 				edge_serial->rxBytesAvail += bytes_avail;
+-				dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __FUNCTION__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress);
++				dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __func__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress);
+ 
+ 				if (edge_serial->rxBytesAvail > 0 &&
+ 				    !edge_serial->read_in_progress) {
+-					dbg("%s - posting a read", __FUNCTION__);
++					dbg("%s - posting a read", __func__);
+ 					edge_serial->read_in_progress = true;
+ 
+ 					/* we have pending bytes on the bulk in pipe, send a request */
+ 					edge_serial->read_urb->dev = edge_serial->serial->dev;
+ 					result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
+ 					if (result) {
+-						dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __FUNCTION__, result);
++						dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __func__, result);
+ 						edge_serial->read_in_progress = false;
+ 					}
+ 				}
+@@ -659,7 +659,7 @@ static void edge_interrupt_callback (struct urb *urb)
+ 					spin_lock(&edge_port->ep_lock);
+ 					edge_port->txCredits += txCredits;
+ 					spin_unlock(&edge_port->ep_lock);
+-					dbg("%s - txcredits for port%d = %d", __FUNCTION__, portNumber, edge_port->txCredits);
++					dbg("%s - txcredits for port%d = %d", __func__, portNumber, edge_port->txCredits);
+ 
+ 					/* tell the tty driver that something has changed */
+ 					if (edge_port->port->tty)
+@@ -677,7 +677,7 @@ static void edge_interrupt_callback (struct urb *urb)
+ exit:
+ 	result = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (result) {
+-		dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, result);
++		dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __func__, result);
+ 	}
+ }
+ 
+@@ -689,49 +689,49 @@ exit:
+  *****************************************************************************/
+ static void edge_bulk_in_callback (struct urb *urb)
+ {
+-	struct edgeport_serial	*edge_serial = (struct edgeport_serial *)urb->context;
++	struct edgeport_serial	*edge_serial = urb->context;
+ 	unsigned char		*data = urb->transfer_buffer;
+ 	int			retval;
+ 	__u16			raw_data_length;
+ 	int status = urb->status;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		edge_serial->read_in_progress = false;
+ 		return;
+ 	}
+ 
+ 	if (urb->actual_length == 0) {
+-		dbg("%s - read bulk callback with no data", __FUNCTION__);
++		dbg("%s - read bulk callback with no data", __func__);
+ 		edge_serial->read_in_progress = false;
+ 		return;
+ 	}
+ 
+ 	raw_data_length = urb->actual_length;
+ 
+-	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, raw_data_length, data);
++	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, raw_data_length, data);
+ 
+ 	spin_lock(&edge_serial->es_lock);
+ 
+ 	/* decrement our rxBytes available by the number that we just got */
+ 	edge_serial->rxBytesAvail -= raw_data_length;
+ 
+-	dbg("%s - Received = %d, rxBytesAvail %d", __FUNCTION__, raw_data_length, edge_serial->rxBytesAvail);
++	dbg("%s - Received = %d, rxBytesAvail %d", __func__, raw_data_length, edge_serial->rxBytesAvail);
+ 
+ 	process_rcvd_data (edge_serial, data, urb->actual_length);
+ 
+ 	/* check to see if there's any more data for us to read */
+ 	if (edge_serial->rxBytesAvail > 0) {
+-		dbg("%s - posting a read", __FUNCTION__);
++		dbg("%s - posting a read", __func__);
+ 		edge_serial->read_urb->dev = edge_serial->serial->dev;
+ 		retval = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
+ 		if (retval) {
+ 			dev_err(&urb->dev->dev,
+ 				"%s - usb_submit_urb(read bulk) failed, "
+-				"retval = %d\n", __FUNCTION__, retval);
++				"retval = %d\n", __func__, retval);
+ 			edge_serial->read_in_progress = false;
+ 		}
+ 	} else {
+@@ -749,15 +749,15 @@ static void edge_bulk_in_callback (struct urb *urb)
+  *****************************************************************************/
+ static void edge_bulk_out_data_callback (struct urb *urb)
+ {
+-	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
++	struct edgeport_port *edge_port = urb->context;
+ 	struct tty_struct *tty;
+ 	int status = urb->status;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 	}
+ 
+ 	tty = edge_port->port->tty;
+@@ -782,14 +782,14 @@ static void edge_bulk_out_data_callback (struct urb *urb)
+  *****************************************************************************/
+ static void edge_bulk_out_cmd_callback (struct urb *urb)
+ {
+-	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
++	struct edgeport_port *edge_port = urb->context;
+ 	struct tty_struct *tty;
+ 	int status = urb->status;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	atomic_dec(&CmdUrbs);
+-	dbg("%s - FREE URB %p (outstanding %d)", __FUNCTION__, urb, atomic_read(&CmdUrbs));
++	dbg("%s - FREE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+ 
+ 
+ 	/* clean up the transfer buffer */
+@@ -799,7 +799,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb)
+ 	usb_free_urb (urb);
+ 
+ 	if (status) {
+-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, status);
++		dbg("%s - nonzero write bulk status received: %d", __func__, status);
+ 		return;
+ 	}
+ 
+@@ -833,7 +833,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 	struct edgeport_serial *edge_serial;
+ 	int response;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return -ENODEV;
+@@ -883,7 +883,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 		 * this interrupt will continue as long as the edgeport is connected */
+ 		response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
+ 		if (response) {
+-			dev_err(&port->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, response);
++			dev_err(&port->dev, "%s - Error %d submitting control urb\n", __func__, response);
+ 		}
+ 	}
+ 	
+@@ -907,7 +907,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 	response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
+ 
+ 	if (response < 0) {
+-		dev_err(&port->dev, "%s - error sending open port command\n", __FUNCTION__);
++		dev_err(&port->dev, "%s - error sending open port command\n", __func__);
+ 		edge_port->openPending = false;
+ 		return -ENODEV;
+ 	}
+@@ -917,7 +917,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 
+ 	if (!edge_port->open) {
+ 		/* open timed out */
+-		dbg("%s - open timedout", __FUNCTION__);
++		dbg("%s - open timedout", __func__);
+ 		edge_port->openPending = false;
+ 		return -ENODEV;
+ 	}
+@@ -930,7 +930,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 	edge_port->txfifo.fifo	= kmalloc (edge_port->maxTxCredits, GFP_KERNEL);
+ 
+ 	if (!edge_port->txfifo.fifo) {
+-		dbg("%s - no memory", __FUNCTION__);
++		dbg("%s - no memory", __func__);
+ 		edge_close (port, filp);
+ 		return -ENOMEM;
+ 	}
+@@ -940,14 +940,14 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 	edge_port->write_in_progress = false;
+ 
+ 	if (!edge_port->write_urb) {
+-		dbg("%s - no memory", __FUNCTION__);
++		dbg("%s - no memory", __func__);
+ 		edge_close (port, filp);
+ 		return -ENOMEM;
+ 	}
+ 
+-	dbg("%s(%d) - Initialize TX fifo to %d bytes", __FUNCTION__, port->number, edge_port->maxTxCredits);
++	dbg("%s(%d) - Initialize TX fifo to %d bytes", __func__, port->number, edge_port->maxTxCredits);
+ 
+-	dbg("%s exited", __FUNCTION__);
++	dbg("%s exited", __func__);
+ 
+ 	return 0;
+ }
+@@ -976,11 +976,11 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
+ 
+ 		// Did we get our Chase response
+ 		if (!edge_port->chaseResponsePending) {
+-			dbg("%s - Got Chase Response", __FUNCTION__);
++			dbg("%s - Got Chase Response", __func__);
+ 
+ 			// did we get all of our credit back?
+ 			if (edge_port->txCredits == edge_port->maxTxCredits ) {
+-				dbg("%s - Got all credits", __FUNCTION__);
++				dbg("%s - Got all credits", __func__);
+ 				return;
+ 			}
+ 		}
+@@ -995,12 +995,12 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
+ 			loop--;
+ 			if (loop == 0) {
+ 				edge_port->chaseResponsePending = false;
+-				dbg("%s - Chase TIMEOUT", __FUNCTION__);
++				dbg("%s - Chase TIMEOUT", __func__);
+ 				return;
+ 			}
+ 		} else {
+ 			// Reset timeout value back to 10 seconds
+-			dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits);
++			dbg("%s - Last %d, Current %d", __func__, lastCredits, edge_port->txCredits);
+ 			loop = 10;
+ 		}
+ 	}
+@@ -1031,7 +1031,7 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
+ 
+ 		// Is the Edgeport Buffer empty?
+ 		if (lastCount == 0) {
+-			dbg("%s - TX Buffer Empty", __FUNCTION__);
++			dbg("%s - TX Buffer Empty", __func__);
+ 			return;
+ 		}
+ 
+@@ -1040,13 +1040,13 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
+ 		schedule_timeout(timeout);
+ 		finish_wait(&edge_port->wait_chase, &wait);
+ 
+-		dbg("%s wait", __FUNCTION__);
++		dbg("%s wait", __func__);
+ 
+ 		if (lastCount == fifo->count) {
+ 			// No activity.. count down.
+ 			loop--;
+ 			if (loop == 0) {
+-				dbg("%s - TIMEOUT", __FUNCTION__);
++				dbg("%s - TIMEOUT", __func__);
+ 				return;
+ 			}
+ 		} else {
+@@ -1067,7 +1067,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
+ 	struct edgeport_port *edge_port;
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 			 
+ 	edge_serial = usb_get_serial_data(port->serial);
+ 	edge_port = usb_get_serial_port_data(port);
+@@ -1085,7 +1085,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
+ 		/* flush and chase */
+ 		edge_port->chaseResponsePending = true;
+ 
+-		dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
++		dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
+ 		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+ 		if (status == 0) {
+ 			// block until chase finished
+@@ -1099,7 +1099,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
+ 	    ((edge_serial->is_epic) &&
+ 	     (edge_serial->epic_descriptor.Supports.IOSPClose))) {
+ 	       /* close the port */
+-		dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__);
++		dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __func__);
+ 		send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+ 	}
+ 
+@@ -1119,7 +1119,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
+ 	kfree(edge_port->txfifo.fifo);
+ 	edge_port->txfifo.fifo = NULL;
+ 
+-	dbg("%s exited", __FUNCTION__);
++	dbg("%s exited", __func__);
+ }   
+ 
+ /*****************************************************************************
+@@ -1139,7 +1139,7 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ 	int secondhalf;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return -ENODEV;
+@@ -1152,12 +1152,12 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ 	// calculate number of bytes to put in fifo
+ 	copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count));
+ 
+-	dbg("%s(%d) of %d byte(s) Fifo room  %d -- will copy %d bytes", __FUNCTION__, 
++	dbg("%s(%d) of %d byte(s) Fifo room  %d -- will copy %d bytes", __func__,
+ 	    port->number, count, edge_port->txCredits - fifo->count, copySize);
+ 
+ 	/* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */
+ 	if (copySize == 0) {
+-		dbg("%s - copySize = Zero", __FUNCTION__);
++		dbg("%s - copySize = Zero", __func__);
+ 		goto finish_write;
+ 	}
+ 
+@@ -1169,11 +1169,11 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ 
+ 	bytesleft = fifo->size - fifo->head;
+ 	firsthalf = min (bytesleft, copySize);
+-	dbg("%s - copy %d bytes of %d into fifo ", __FUNCTION__, firsthalf, bytesleft);
++	dbg("%s - copy %d bytes of %d into fifo ", __func__, firsthalf, bytesleft);
+ 
+ 	/* now copy our data */
+ 	memcpy(&fifo->fifo[fifo->head], data, firsthalf);
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, firsthalf, &fifo->fifo[fifo->head]);
++	usb_serial_debug_data(debug, &port->dev, __func__, firsthalf, &fifo->fifo[fifo->head]);
+ 
+ 	// update the index and size
+ 	fifo->head  += firsthalf;
+@@ -1187,9 +1187,9 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ 	secondhalf = copySize-firsthalf;
+ 
+ 	if (secondhalf) {
+-		dbg("%s - copy rest of data %d", __FUNCTION__, secondhalf);
++		dbg("%s - copy rest of data %d", __func__, secondhalf);
+ 		memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
+-		usb_serial_debug_data(debug, &port->dev, __FUNCTION__, secondhalf, &fifo->fifo[fifo->head]);
++		usb_serial_debug_data(debug, &port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]);
+ 		// update the index and size
+ 		fifo->count += secondhalf;
+ 		fifo->head  += secondhalf;
+@@ -1201,7 +1201,7 @@ finish_write:
+ 
+ 	send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port);
+ 
+-	dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __FUNCTION__, copySize, edge_port->txCredits, fifo->count);
++	dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__, copySize, edge_port->txCredits, fifo->count);
+ 
+ 	return copySize;   
+ }
+@@ -1232,14 +1232,14 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ 	int		secondhalf;
+ 	unsigned long	flags;
+ 
+-	dbg("%s(%d)", __FUNCTION__, edge_port->port->number);
++	dbg("%s(%d)", __func__, edge_port->port->number);
+ 
+ 	spin_lock_irqsave(&edge_port->ep_lock, flags);
+ 
+ 	if (edge_port->write_in_progress ||
+ 	    !edge_port->open             ||
+ 	    (fifo->count == 0)) {
+-		dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->write_in_progress);
++		dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __func__, edge_port->port->number, fifo->count, edge_port->write_in_progress);
+ 		goto exit_send;
+ 	}
+ 
+@@ -1251,7 +1251,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ 	//	it's better to wait for more credits so we can do a larger
+ 	//	write.
+ 	if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) {
+-		dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->txCredits );
++		dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __func__, edge_port->port->number, fifo->count, edge_port->txCredits );
+ 		goto exit_send;
+ 	}
+ 
+@@ -1269,7 +1269,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ 	count = fifo->count;
+ 	buffer = kmalloc (count+2, GFP_ATOMIC);
+ 	if (buffer == NULL) {
+-		dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __FUNCTION__);
++		dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __func__);
+ 		edge_port->write_in_progress = false;
+ 		goto exit_send;
+ 	}
+@@ -1294,7 +1294,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ 	}
+ 
+ 	if (count)
+-		usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, count, &buffer[2]);
++		usb_serial_debug_data(debug, &edge_port->port->dev, __func__, count, &buffer[2]);
+ 
+ 	/* fill up the urb with all of our data and submit it */
+ 	usb_fill_bulk_urb (urb, edge_serial->serial->dev, 
+@@ -1309,14 +1309,14 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ 	status = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if (status) {
+ 		/* something went wrong */
+-		dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __FUNCTION__, status);
++		dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __func__, status);
+ 		edge_port->write_in_progress = false;
+ 
+ 		/* revert the credits as something bad happened. */
+ 		edge_port->txCredits += count;
+ 		edge_port->icount.tx -= count;
+ 	}
+-	dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __FUNCTION__, count, edge_port->txCredits, fifo->count);
++	dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __func__, count, edge_port->txCredits, fifo->count);
+ 
+ exit_send:
+ 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+@@ -1337,17 +1337,17 @@ static int edge_write_room (struct usb_serial_port *port)
+ 	int room;
+ 	unsigned long flags;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (edge_port == NULL)
+ 		return -ENODEV;
+ 	if (edge_port->closePending)
+ 		return -ENODEV;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!edge_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -1356,7 +1356,7 @@ static int edge_write_room (struct usb_serial_port *port)
+ 	room = edge_port->txCredits - edge_port->txfifo.count;
+ 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 	return room;
+ }
+ 
+@@ -1376,7 +1376,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ 	int num_chars;
+ 	unsigned long flags;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (edge_port == NULL)
+ 		return -ENODEV;
+@@ -1384,7 +1384,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ 		return -ENODEV;
+ 
+ 	if (!edge_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -1392,7 +1392,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ 	num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count;
+ 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ 	if (num_chars) {
+-		dbg("%s(port %d) - returns %d", __FUNCTION__, port->number, num_chars);
++		dbg("%s(port %d) - returns %d", __func__, port->number, num_chars);
+ 	}
+ 
+ 	return num_chars;
+@@ -1410,19 +1410,19 @@ static void edge_throttle (struct usb_serial_port *port)
+ 	struct tty_struct *tty;
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return;
+ 
+ 	if (!edge_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg ("%s - no tty available", __FUNCTION__);
++		dbg ("%s - no tty available", __func__);
+ 		return;
+ 	}
+ 
+@@ -1459,19 +1459,19 @@ static void edge_unthrottle (struct usb_serial_port *port)
+ 	struct tty_struct *tty;
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return;
+ 
+ 	if (!edge_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg ("%s - no tty available", __FUNCTION__);
++		dbg ("%s - no tty available", __func__);
+ 		return;
+ 	}
+ 
+@@ -1509,18 +1509,18 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
+ 	unsigned int cflag;
+ 
+ 	cflag = tty->termios->c_cflag;
+-	dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
++	dbg("%s - clfag %08x iflag %08x", __func__,
+ 	    tty->termios->c_cflag, tty->termios->c_iflag);
+-	dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
++	dbg("%s - old clfag %08x old iflag %08x", __func__,
+ 	    old_termios->c_cflag, old_termios->c_iflag);
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return;
+ 
+ 	if (!edge_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+@@ -1549,7 +1549,7 @@ static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *va
+ 	spin_lock_irqsave(&edge_port->ep_lock, flags);
+ 	if (edge_port->maxTxCredits == edge_port->txCredits &&
+ 	    edge_port->txfifo.count == 0) {
+-		dbg("%s -- Empty", __FUNCTION__);
++		dbg("%s -- Empty", __func__);
+ 		result = TIOCSER_TEMT;
+ 	}
+ 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+@@ -1569,7 +1569,7 @@ static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int
+ 
+ 	result = tty->read_cnt;
+ 
+-	dbg("%s(%d) = %d", __FUNCTION__,  edge_port->port->number, result);
++	dbg("%s(%d) = %d", __func__,  edge_port->port->number, result);
+ 	if (copy_to_user(value, &result, sizeof(int)))
+ 		return -EFAULT;
+ 	//return 0;
+@@ -1581,7 +1581,7 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
+ 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ 	unsigned int mcr;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	mcr = edge_port->shadowMCR;
+ 	if (set & TIOCM_RTS)
+@@ -1612,7 +1612,7 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+ 	unsigned int msr;
+ 	unsigned int mcr;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	msr = edge_port->shadowMSR;
+ 	mcr = edge_port->shadowMCR;
+@@ -1624,7 +1624,7 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+ 		  | ((msr & EDGEPORT_MSR_DSR)	? TIOCM_DSR: 0);  /* 0x100 */
+ 
+ 
+-	dbg("%s -- %x", __FUNCTION__, result);
++	dbg("%s -- %x", __func__, result);
+ 
+ 	return result;
+ }
+@@ -1670,30 +1670,30 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
+ 	struct async_icount cprev;
+ 	struct serial_icounter_struct icount;
+ 
+-	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+ 
+ 	switch (cmd) {
+ 		// return number of bytes available
+ 		case TIOCINQ:
+-			dbg("%s (%d) TIOCINQ", __FUNCTION__,  port->number);
++			dbg("%s (%d) TIOCINQ", __func__,  port->number);
+ 			return get_number_bytes_avail(edge_port, (unsigned int __user *) arg);
+ 			break;
+ 
+ 		case TIOCSERGETLSR:
+-			dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__,  port->number);
++			dbg("%s (%d) TIOCSERGETLSR", __func__,  port->number);
+ 			return get_lsr_info(edge_port, (unsigned int __user *) arg);
+ 			return 0;
+ 
+ 		case TIOCGSERIAL:
+-			dbg("%s (%d) TIOCGSERIAL", __FUNCTION__,  port->number);
++			dbg("%s (%d) TIOCGSERIAL", __func__,  port->number);
+ 			return get_serial_info(edge_port, (struct serial_struct __user *) arg);
+ 
+ 		case TIOCSSERIAL:
+-			dbg("%s (%d) TIOCSSERIAL", __FUNCTION__,  port->number);
++			dbg("%s (%d) TIOCSSERIAL", __func__,  port->number);
+ 			break;
+ 
+ 		case TIOCMIWAIT:
+-			dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
++			dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
+ 			cprev = edge_port->icount;
+ 			while (1) {
+ 				prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
+@@ -1732,7 +1732,7 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
+ 			icount.brk = cnow.brk;
+ 			icount.buf_overrun = cnow.buf_overrun;
+ 
+-			dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,  port->number, icount.rx, icount.tx );
++			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;
+@@ -1758,7 +1758,7 @@ static void edge_break (struct usb_serial_port *port, int break_state)
+ 		/* flush and chase */
+ 		edge_port->chaseResponsePending = true;
+ 
+-		dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
++		dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
+ 		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+ 		if (status == 0) {
+ 			// block until chase finished
+@@ -1772,14 +1772,14 @@ static void edge_break (struct usb_serial_port *port, int break_state)
+ 	    ((edge_serial->is_epic) &&
+ 	     (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) {
+ 		if (break_state == -1) {
+-			dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__);
++			dbg("%s - Sending IOSP_CMD_SET_BREAK", __func__);
+ 			status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
+ 		} else {
+-			dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__);
++			dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __func__);
+ 			status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);
+ 		}
+ 		if (status) {
+-			dbg("%s - error sending break set/clear command.", __FUNCTION__);
++			dbg("%s - error sending break set/clear command.", __func__);
+ 		}
+ 	}
+ 
+@@ -1799,14 +1799,14 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
+ 	__u16 lastBufferLength;
+ 	__u16 rxLen;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	lastBufferLength = bufferLength + 1;
+ 
+ 	while (bufferLength > 0) {
+ 		/* failsafe incase we get a message that we don't understand */
+ 		if (lastBufferLength == bufferLength) {
+-			dbg("%s - stuck in loop, exiting it.", __FUNCTION__);
++			dbg("%s - stuck in loop, exiting it.", __func__);
+ 			break;
+ 		}
+ 		lastBufferLength = bufferLength;
+@@ -1828,7 +1828,7 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
+ 				++buffer;
+ 				--bufferLength;
+ 
+-				dbg("%s - Hdr1=%02X Hdr2=%02X", __FUNCTION__, edge_serial->rxHeader1, edge_serial->rxHeader2);
++				dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, edge_serial->rxHeader1, edge_serial->rxHeader2);
+ 
+ 				// Process depending on whether this header is
+ 				// data or status
+@@ -1858,7 +1858,7 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
+ 					edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+ 					edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2);
+ 
+-					dbg("%s - Data for Port %u Len %u", __FUNCTION__, edge_serial->rxPort, edge_serial->rxBytesRemaining);
++					dbg("%s - Data for Port %u Len %u", __func__, edge_serial->rxPort, edge_serial->rxBytesRemaining);
+ 
+ 					//ASSERT( DevExt->RxPort < DevExt->NumPorts );
+ 					//ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH );
+@@ -1891,7 +1891,7 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
+ 					if (edge_port->open) {
+ 						tty = edge_port->port->tty;
+ 						if (tty) {
+-							dbg("%s - Sending %d bytes to TTY for port %d", __FUNCTION__, rxLen, edge_serial->rxPort);
++							dbg("%s - Sending %d bytes to TTY for port %d", __func__, rxLen, edge_serial->rxPort);
+ 							edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
+ 						}
+ 						edge_port->icount.rx += rxLen;
+@@ -1930,17 +1930,17 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ 	port = edge_serial->serial->port[edge_serial->rxPort];
+ 	edge_port = usb_get_serial_port_data(port);
+ 	if (edge_port == NULL) {
+-		dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __FUNCTION__, edge_serial->rxPort);
++		dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __func__, edge_serial->rxPort);
+ 		return;
+ 	}
+ 
+-	dbg("%s - port %d", __FUNCTION__, edge_serial->rxPort);
++	dbg("%s - port %d", __func__, edge_serial->rxPort);
+ 
+ 	if (code == IOSP_EXT_STATUS) {
+ 		switch (byte2) {
+ 			case IOSP_EXT_STATUS_CHASE_RSP:
+ 				// we want to do EXT status regardless of port open/closed 
+-				dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __FUNCTION__, edge_serial->rxPort, byte3 );
++				dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __func__, edge_serial->rxPort, byte3 );
+ 				// Currently, the only EXT_STATUS is Chase, so process here instead of one more call
+ 				// to one more subroutine. If/when more EXT_STATUS, there'll be more work to do.
+ 				// Also, we currently clear flag and close the port regardless of content of above's Byte3.
+@@ -1951,7 +1951,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ 				return;
+ 
+ 			case IOSP_EXT_STATUS_RX_CHECK_RSP:
+-				dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __FUNCTION__, edge_serial->rxPort, byte3 );
++				dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3 );
+ 				//Port->RxCheckRsp = true;
+ 				return;
+ 		}
+@@ -1960,7 +1960,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ 	if (code == IOSP_STATUS_OPEN_RSP) {
+ 		edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);
+ 		edge_port->maxTxCredits = edge_port->txCredits;
+-		dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __FUNCTION__, edge_serial->rxPort, byte2, edge_port->txCredits);
++		dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits);
+ 		handle_new_msr (edge_port, byte2);
+ 
+ 		/* send the current line settings to the port so we are in sync with any further termios calls */
+@@ -1984,23 +1984,23 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ 	switch (code) {
+ 		// Not currently sent by Edgeport
+ 		case IOSP_STATUS_LSR:
+-			dbg("%s - Port %u LSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2);
++			dbg("%s - Port %u LSR Status = %02x", __func__, edge_serial->rxPort, byte2);
+ 			handle_new_lsr(edge_port, false, byte2, 0);
+ 			break;
+ 
+ 		case IOSP_STATUS_LSR_DATA:
+-			dbg("%s - Port %u LSR Status = %02x, Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3);
++			dbg("%s - Port %u LSR Status = %02x, Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
+ 			// byte2 is LSR Register
+ 			// byte3 is broken data byte
+ 			handle_new_lsr(edge_port, true, byte2, byte3);
+ 			break;
+ 			//
+ 			//	case IOSP_EXT_4_STATUS:
+-			//		dbg("%s - Port %u LSR Status = %02x Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3);
++			//		dbg("%s - Port %u LSR Status = %02x Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
+ 			//		break;
+ 			//
+ 		case IOSP_STATUS_MSR:
+-			dbg("%s - Port %u MSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2);
++			dbg("%s - Port %u MSR Status = %02x", __func__, edge_serial->rxPort, byte2);
+ 
+ 			// Process this new modem status and generate appropriate
+ 			// events, etc, based on the new status. This routine
+@@ -2009,7 +2009,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ 			break;
+ 
+ 		default:
+-			dbg("%s - Unrecognized IOSP status code %u\n", __FUNCTION__, code);
++			dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
+ 			break;
+ 	}
+ 
+@@ -2029,7 +2029,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
+ 		cnt = tty_buffer_request_room(tty, length);
+ 		if (cnt < length) {
+ 			dev_err(dev, "%s - dropping data, %d bytes lost\n",
+-					__FUNCTION__, length - cnt);
++					__func__, length - cnt);
+ 			if(cnt == 0)
+ 				break;
+ 		}
+@@ -2050,7 +2050,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
+ {
+ 	struct  async_icount *icount;
+ 
+-	dbg("%s %02x", __FUNCTION__, newMsr);
++	dbg("%s %02x", __func__, newMsr);
+ 
+ 	if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
+ 		icount = &edge_port->icount;
+@@ -2087,7 +2087,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 l
+ 	__u8    newLsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+ 	struct  async_icount *icount;
+ 
+-	dbg("%s - %02x", __FUNCTION__, newLsr);
++	dbg("%s - %02x", __func__, newLsr);
+ 
+ 	edge_port->shadowLSR = lsr;
+ 
+@@ -2136,11 +2136,11 @@ static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u
+ 	__u16 current_length;
+ 	unsigned char *transfer_buffer;
+ 
+-	dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
++	dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+ 
+ 	transfer_buffer =  kmalloc (64, GFP_KERNEL);
+ 	if (!transfer_buffer) {
+-		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
++		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -2152,7 +2152,7 @@ static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u
+ 		} else {
+ 			current_length = length;
+ 		}
+-//		dbg("%s - writing %x, %x, %d", __FUNCTION__, extAddr, addr, current_length);
++//		dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
+ 		memcpy (transfer_buffer, data, current_length);
+ 		result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_RAM, 
+ 					  0x40, addr, extAddr, transfer_buffer, current_length, 300);
+@@ -2181,11 +2181,11 @@ static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
+ 	__u16 current_length;
+ 	unsigned char *transfer_buffer;
+ 
+-//	dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
++//	dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+ 
+ 	transfer_buffer =  kmalloc (64, GFP_KERNEL);
+ 	if (!transfer_buffer) {
+-		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
++		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -2197,7 +2197,7 @@ static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
+ 		} else {
+ 			current_length = length;
+ 		}
+-//		dbg("%s - writing %x, %x, %d", __FUNCTION__, extAddr, addr, current_length);
++//		dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
+ 		memcpy (transfer_buffer, data, current_length);
+ 		result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_ROM, 
+ 					  0x40, addr, extAddr, transfer_buffer, current_length, 300);
+@@ -2226,11 +2226,11 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
+ 	__u16 current_length;
+ 	unsigned char *transfer_buffer;
+ 
+-	dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
++	dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+ 
+ 	transfer_buffer =  kmalloc (64, GFP_KERNEL);
+ 	if (!transfer_buffer) {
+-		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
++		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -2242,7 +2242,7 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
+ 		} else {
+ 			current_length = length;
+ 		}
+-//		dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, current_length);
++//		dbg("%s - %x, %x, %d", __func__, extAddr, addr, current_length);
+ 		result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM, 
+ 					  0xC0, addr, extAddr, transfer_buffer, current_length, 300);
+ 		if (result < 0)
+@@ -2269,11 +2269,11 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
+ 	int             length = 0;
+ 	int             status = 0;
+ 
+-	dbg("%s - %d, %d", __FUNCTION__, command, param);
++	dbg("%s - %d, %d", __func__, command, param);
+ 
+ 	buffer =  kmalloc (10, GFP_ATOMIC);
+ 	if (!buffer) {
+-		dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 10);
++		dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 10);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -2304,7 +2304,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
+ 	struct urb *urb;
+ 	int timeout;
+ 
+-	usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, length, buffer);
++	usb_serial_debug_data(debug, &edge_port->port->dev, __func__, length, buffer);
+ 
+ 	/* Allocate our next urb */
+ 	urb = usb_alloc_urb (0, GFP_ATOMIC);
+@@ -2312,7 +2312,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
+ 		return -ENOMEM;
+ 
+ 	atomic_inc(&CmdUrbs);
+-	dbg("%s - ALLOCATE URB %p (outstanding %d)", __FUNCTION__, urb, atomic_read(&CmdUrbs));
++	dbg("%s - ALLOCATE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+ 
+ 	usb_fill_bulk_urb (urb, edge_serial->serial->dev, 
+ 		       usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
+@@ -2323,7 +2323,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
+ 
+ 	if (status) {
+ 		/* something went wrong */
+-		dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __FUNCTION__, status);
++		dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __func__, status);
+ 		usb_kill_urb(urb);
+ 		usb_free_urb(urb);
+ 		atomic_dec(&CmdUrbs);
+@@ -2337,7 +2337,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
+ 
+ 	if (edge_port->commandPending) {
+ 		/* command timed out */
+-		dbg("%s - command timed out", __FUNCTION__);
++		dbg("%s - command timed out", __func__);
+ 		status = -EINVAL;
+ 	}
+ #endif
+@@ -2367,18 +2367,18 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
+ 		return 0;
+ 	}
+ 
+-	dbg("%s - port = %d, baud = %d", __FUNCTION__, edge_port->port->number, baudRate);
++	dbg("%s - port = %d, baud = %d", __func__, edge_port->port->number, baudRate);
+ 
+ 	status = calc_baud_rate_divisor (baudRate, &divisor);
+ 	if (status) {
+-		dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __FUNCTION__);
++		dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __func__);
+ 		return status;
+ 	}
+ 
+ 	// Alloc memory for the string of commands.
+ 	cmdBuffer =  kmalloc (0x100, GFP_ATOMIC);
+ 	if (!cmdBuffer) {
+-		dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 0x100);
++		dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 0x100);
+ 		return -ENOMEM;
+ 	}
+ 	currCmd = cmdBuffer;
+@@ -2414,7 +2414,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
+ 	__u16 custom;
+ 
+ 
+-	dbg("%s - %d", __FUNCTION__, baudrate);
++	dbg("%s - %d", __func__, baudrate);
+ 
+ 	for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
+ 		if ( divisor_table[i].BaudRate == baudrate ) {
+@@ -2432,7 +2432,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
+ 
+ 		*divisor = custom;
+ 
+-		dbg("%s - Baud %d = %d\n", __FUNCTION__, baudrate, custom);
++		dbg("%s - Baud %d = %d\n", __func__, baudrate, custom);
+ 		return 0;
+ 	}
+ 
+@@ -2452,7 +2452,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
+ 	unsigned long cmdLen = 0;
+ 	int status;
+ 
+-	dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue);
++	dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
+ 
+ 	if (edge_serial->is_epic &&
+ 	    !edge_serial->epic_descriptor.Supports.IOSPWriteMCR &&
+@@ -2513,29 +2513,29 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 	__u8 txFlow;
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
++	dbg("%s - port %d", __func__, edge_port->port->number);
+ 
+ 	if (!edge_port->open &&
+ 	    !edge_port->openPending) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+ 	tty = edge_port->port->tty;
+ 	if ((!tty) ||
+ 	    (!tty->termios)) {
+-		dbg("%s - no tty structures", __FUNCTION__);
++		dbg("%s - no tty structures", __func__);
+ 		return;
+ 	}
+ 
+ 	cflag = tty->termios->c_cflag;
+ 
+ 	switch (cflag & CSIZE) {
+-		case CS5:   lData = LCR_BITS_5; mask = 0x1f;    dbg("%s - data bits = 5", __FUNCTION__);   break;
+-		case CS6:   lData = LCR_BITS_6; mask = 0x3f;    dbg("%s - data bits = 6", __FUNCTION__);   break;
+-		case CS7:   lData = LCR_BITS_7; mask = 0x7f;    dbg("%s - data bits = 7", __FUNCTION__);   break;
++		case CS5:   lData = LCR_BITS_5; mask = 0x1f;    dbg("%s - data bits = 5", __func__);   break;
++		case CS6:   lData = LCR_BITS_6; mask = 0x3f;    dbg("%s - data bits = 6", __func__);   break;
++		case CS7:   lData = LCR_BITS_7; mask = 0x7f;    dbg("%s - data bits = 7", __func__);   break;
+ 		default:
+-		case CS8:   lData = LCR_BITS_8;                 dbg("%s - data bits = 8", __FUNCTION__);   break;
++		case CS8:   lData = LCR_BITS_8;                 dbg("%s - data bits = 8", __func__);   break;
+ 	}
+ 
+ 	lParity = LCR_PAR_NONE;
+@@ -2543,28 +2543,28 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 		if (cflag & CMSPAR) {
+ 			if (cflag & PARODD) {
+ 				lParity = LCR_PAR_MARK;
+-				dbg("%s - parity = mark", __FUNCTION__);
++				dbg("%s - parity = mark", __func__);
+ 			} else {
+ 				lParity = LCR_PAR_SPACE;
+-				dbg("%s - parity = space", __FUNCTION__);
++				dbg("%s - parity = space", __func__);
+ 			}
+ 		} else if (cflag & PARODD) {
+ 			lParity = LCR_PAR_ODD;
+-			dbg("%s - parity = odd", __FUNCTION__);
++			dbg("%s - parity = odd", __func__);
+ 		} else {
+ 			lParity = LCR_PAR_EVEN;
+-			dbg("%s - parity = even", __FUNCTION__);
++			dbg("%s - parity = even", __func__);
+ 		}
+ 	} else {
+-		dbg("%s - parity = none", __FUNCTION__);
++		dbg("%s - parity = none", __func__);
+ 	}
+ 
+ 	if (cflag & CSTOPB) {
+ 		lStop = LCR_STOP_2;
+-		dbg("%s - stop bits = 2", __FUNCTION__);
++		dbg("%s - stop bits = 2", __func__);
+ 	} else {
+ 		lStop = LCR_STOP_1;
+-		dbg("%s - stop bits = 1", __FUNCTION__);
++		dbg("%s - stop bits = 1", __func__);
+ 	}
+ 
+ 	/* figure out the flow control settings */
+@@ -2572,9 +2572,9 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 	if (cflag & CRTSCTS) {
+ 		rxFlow |= IOSP_RX_FLOW_RTS;
+ 		txFlow |= IOSP_TX_FLOW_CTS;
+-		dbg("%s - RTS/CTS is enabled", __FUNCTION__);
++		dbg("%s - RTS/CTS is enabled", __func__);
+ 	} else {
+-		dbg("%s - RTS/CTS is disabled", __FUNCTION__);
++		dbg("%s - RTS/CTS is disabled", __func__);
+ 	}
+ 
+ 	/* if we are implementing XON/XOFF, set the start and stop character in the device */
+@@ -2592,17 +2592,17 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 		/* if we are implementing INBOUND XON/XOFF */
+ 		if (I_IXOFF(tty)) {
+ 			rxFlow |= IOSP_RX_FLOW_XON_XOFF;
+-			dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __FUNCTION__, start_char, stop_char);
++			dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+ 		} else {
+-			dbg("%s - INBOUND XON/XOFF is disabled", __FUNCTION__);
++			dbg("%s - INBOUND XON/XOFF is disabled", __func__);
+ 		}
+ 
+ 		/* if we are implementing OUTBOUND XON/XOFF */
+ 		if (I_IXON(tty)) {
+ 			txFlow |= IOSP_TX_FLOW_XON_XOFF;
+-			dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __FUNCTION__, start_char, stop_char);
++			dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+ 		} else {
+-			dbg("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__);
++			dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
+ 		}
+ 	}
+ 
+@@ -2645,7 +2645,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 		baud = 9600;
+ 	}
+ 
+-	dbg("%s - baud rate = %d", __FUNCTION__, baud);
++	dbg("%s - baud rate = %d", __func__, baud);
+ 	status = send_cmd_write_baud_rate (edge_port, baud);
+ 	if (status == -1) {
+ 		/* Speed change was not possible - put back the old speed */
+@@ -2843,7 +2843,7 @@ static int edge_startup (struct usb_serial *serial)
+ 	/* create our private serial structure */
+ 	edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
+ 	if (edge_serial == NULL) {
+-		dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++		dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	spin_lock_init(&edge_serial->es_lock);
+@@ -2885,19 +2885,19 @@ static int edge_startup (struct usb_serial *serial)
+ 			 serial->num_ports);
+ 	}
+ 
+-	dbg("%s - time 1 %ld", __FUNCTION__, jiffies);
++	dbg("%s - time 1 %ld", __func__, jiffies);
+ 
+ 	/* If not an EPiC device */
+ 	if (!edge_serial->is_epic) {
+ 		/* now load the application firmware into this device */
+ 		load_application_firmware (edge_serial);
+ 
+-		dbg("%s - time 2 %ld", __FUNCTION__, jiffies);
++		dbg("%s - time 2 %ld", __func__, jiffies);
+ 
+ 		/* Check current Edgeport EEPROM and update if necessary */
+ 		update_edgeport_E2PROM (edge_serial);
+ 
+-		dbg("%s - time 3 %ld", __FUNCTION__, jiffies);
++		dbg("%s - time 3 %ld", __func__, jiffies);
+ 
+ 		/* set the configuration to use #1 */
+ //		dbg("set_configuration 1");
+@@ -2911,7 +2911,7 @@ static int edge_startup (struct usb_serial *serial)
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
+ 		if (edge_port == NULL) {
+-			dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++			dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ 			for (j = 0; j < i; ++j) {
+ 				kfree (usb_get_serial_port_data(serial->port[j]));
+ 				usb_set_serial_port_data(serial->port[j],  NULL);
+@@ -3017,7 +3017,7 @@ static int edge_startup (struct usb_serial *serial)
+ 		 * continue as long as the edgeport is connected */
+ 		response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL);
+ 		if (response)
+-			err("%s - Error %d submitting control urb", __FUNCTION__, response);
++			err("%s - Error %d submitting control urb", __func__, response);
+ 	}
+ 	return response;
+ }
+@@ -3032,7 +3032,7 @@ static void edge_shutdown (struct usb_serial *serial)
+ 	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+ 	int i;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* stop reads and writes on all ports */
+ 	for (i=0; i < serial->num_ports; ++i) {
+diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
+index 6d30087..2ec8589 100644
+--- a/drivers/usb/serial/io_tables.h
++++ b/drivers/usb/serial/io_tables.h
+@@ -111,9 +111,6 @@ static struct usb_serial_driver edgeport_2port_device = {
+ 	.description		= "Edgeport 2 port adapter",
+ 	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_2port_id_table,
+-	.num_interrupt_in	= 1,
+-	.num_bulk_in		= 1,
+-	.num_bulk_out		= 1,
+ 	.num_ports		= 2,
+ 	.open			= edge_open,
+ 	.close			= edge_close,
+@@ -142,9 +139,6 @@ static struct usb_serial_driver edgeport_4port_device = {
+ 	.description		= "Edgeport 4 port adapter",
+ 	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_4port_id_table,
+-	.num_interrupt_in	= 1,
+-	.num_bulk_in		= 1,
+-	.num_bulk_out		= 1,
+ 	.num_ports		= 4,
+ 	.open			= edge_open,
+ 	.close			= edge_close,
+@@ -173,9 +167,6 @@ static struct usb_serial_driver edgeport_8port_device = {
+ 	.description		= "Edgeport 8 port adapter",
+ 	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_8port_id_table,
+-	.num_interrupt_in	= 1,
+-	.num_bulk_in		= 1,
+-	.num_bulk_out		= 1,
+ 	.num_ports		= 8,
+ 	.open			= edge_open,
+ 	.close			= edge_close,
+@@ -203,9 +194,6 @@ static struct usb_serial_driver epic_device = {
+ 	},
+ 	.description		= "EPiC device",
+ 	.id_table		= Epic_port_id_table,
+-	.num_interrupt_in	= 1,
+-	.num_bulk_in		= 1,
+-	.num_bulk_out		= 1,
+ 	.num_ports		= 1,
+ 	.open			= edge_open,
+ 	.close			= edge_close,
+diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
+index cd34059..05e4fa7 100644
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -38,7 +38,6 @@
+ #include <linux/serial.h>
+ #include <linux/ioctl.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
+ 
+@@ -291,7 +290,7 @@ static int TIReadVendorRequestSync (struct usb_device *dev,
+ 		return status;
+ 	if (status != size) {
+ 		dbg ("%s - wanted to write %d, but only wrote %d",
+-		     __FUNCTION__, size, status);
++		     __func__, size, status);
+ 		return -ECOMM;
+ 	}
+ 	return 0;
+@@ -321,7 +320,7 @@ static int TISendVendorRequestSync (struct usb_device *dev,
+ 		return status;
+ 	if (status != size) {
+ 		dbg ("%s - wanted to write %d, but only wrote %d",
+-		     __FUNCTION__, size, status);
++		     __func__, size, status);
+ 		return -ECOMM;
+ 	}
+ 	return 0;
+@@ -345,7 +344,7 @@ static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask)
+ {
+ 	int port_number = port->number - port->serial->minor;
+ 
+-	dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask);
++	dbg ("%s - port %d, mask %x", __func__, port_number, mask);
+ 
+ 	return TIWriteCommandSync (port->serial->dev,
+ 					UMPC_PURGE_PORT,
+@@ -370,7 +369,7 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
+ 	__u8 read_length;
+ 	__be16 be_start_address;
+ 	
+-	dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length);
++	dbg ("%s - @ %x for %d", __func__, start_address, length);
+ 
+ 	/* Read in blocks of 64 bytes
+ 	 * (TI firmware can't handle more than 64 byte reads)
+@@ -382,7 +381,7 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
+ 			read_length = (__u8)length;
+ 
+ 		if (read_length > 1) {
+-			dbg ("%s - @ %x for %d", __FUNCTION__, 
++			dbg ("%s - @ %x for %d", __func__,
+ 			     start_address, read_length);
+ 		}
+ 		be_start_address = cpu_to_be16 (start_address);
+@@ -394,12 +393,12 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
+ 						  read_length);	// TransferBufferLength
+ 
+ 		if (status) {
+-			dbg ("%s - ERROR %x", __FUNCTION__, status);
++			dbg ("%s - ERROR %x", __func__, status);
+ 			return status;
+ 		}
+ 
+ 		if (read_length > 1) {
+-			usb_serial_debug_data(debug, &dev->dev, __FUNCTION__,
++			usb_serial_debug_data(debug, &dev->dev, __func__,
+ 					      read_length, buffer);
+ 		}
+ 
+@@ -435,13 +434,13 @@ static int TIReadBootMemory (struct edgeport_serial *serial, int start_address,
+ 					&buffer[i],			// TransferBuffer
+ 					0x01);				// TransferBufferLength
+ 		if (status) {
+-			dbg ("%s - ERROR %x", __FUNCTION__, status);
++			dbg ("%s - ERROR %x", __func__, status);
+ 			return status;
+ 		}
+ 	}
+ 
+-	dbg ("%s - start_address = %x, length = %d", __FUNCTION__, start_address, length);
+-	usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer);
++	dbg ("%s - start_address = %x, length = %d", __func__, start_address, length);
++	usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
+ 
+ 	serial->TiReadI2C = 1;
+ 
+@@ -473,8 +472,8 @@ static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address,
+ 			return status;
+ 	}
+ 
+-  	dbg ("%s - start_sddr = %x, length = %d", __FUNCTION__, start_address, length);
+-	usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer);
++  	dbg ("%s - start_sddr = %x, length = %d", __func__, start_address, length);
++	usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
+ 
+ 	return status;
+ }
+@@ -495,8 +494,8 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ 	if (write_length > length)
+ 		write_length = length;
+ 
+-	dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
+-	usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer);
++	dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __func__, start_address, write_length);
++	usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
+ 
+ 	/* Write first page */
+ 	be_start_address = cpu_to_be16 (start_address);
+@@ -507,7 +506,7 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ 					buffer,			// TransferBuffer
+ 					write_length);
+ 	if (status) {
+-		dbg ("%s - ERROR %d", __FUNCTION__, status);
++		dbg ("%s - ERROR %d", __func__, status);
+ 		return status;
+ 	}
+ 
+@@ -522,8 +521,8 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ 		else
+ 			write_length = length;
+ 
+-		dbg ("%s - Page Write Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
+-		usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer);
++		dbg ("%s - Page Write Addr = %x, length = %d", __func__, start_address, write_length);
++		usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
+ 
+ 		/* Write next page */
+ 		be_start_address = cpu_to_be16 (start_address);
+@@ -534,7 +533,7 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ 						buffer,	  		// TransferBuffer
+ 						write_length);		// TransferBufferLength
+ 		if (status) {
+-			dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __FUNCTION__, status);
++			dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __func__, status);
+ 			return status;
+ 		}
+ 		
+@@ -560,7 +559,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+ 
+ 	oedb = kmalloc (sizeof (* oedb), GFP_KERNEL);
+ 	if (!oedb) {
+-		dev_err (&port->port->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err (&port->port->dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -580,7 +579,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+ 	if (status)
+ 		goto exit_is_tx_active;
+ 
+-	dbg ("%s - XByteCount    0x%X", __FUNCTION__, oedb->XByteCount);
++	dbg ("%s - XByteCount    0x%X", __func__, oedb->XByteCount);
+ 
+ 	/* and the LSR */
+ 	status = TIReadRam (port->port->serial->dev, 
+@@ -590,7 +589,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+ 
+ 	if (status)
+ 		goto exit_is_tx_active;
+-	dbg ("%s - LSR = 0x%X", __FUNCTION__, *lsr);
++	dbg ("%s - LSR = 0x%X", __func__, *lsr);
+ 	
+ 	/* If either buffer has data or we are transmitting then return TRUE */
+ 	if ((oedb->XByteCount & 0x80 ) != 0 )
+@@ -601,7 +600,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+ 
+ 	/* We return Not Active if we get any kind of error */
+ exit_is_tx_active:
+-	dbg ("%s - return %d", __FUNCTION__, bytes_left );
++	dbg ("%s - return %d", __func__, bytes_left );
+ 
+ 	kfree(lsr);
+ 	kfree(oedb);
+@@ -655,7 +654,7 @@ static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int f
+ 	/* (TIIsTxActive doesn't seem to wait for the last byte) */
+ 	if ((baud_rate=port->baud_rate) == 0)
+ 		baud_rate = 50;
+-	msleep(max(1,(10000+baud_rate-1)/baud_rate));
++	msleep(max(1, DIV_ROUND_UP(10000, baud_rate)));
+ }
+ 
+ static int TIChooseConfiguration (struct usb_device *dev)
+@@ -665,11 +664,11 @@ static int TIChooseConfiguration (struct usb_device *dev)
+ 	// we want. However, we just support one config at this point,
+ 	// configuration # 1, which is Config Descriptor 0.
+ 
+-	dbg ("%s - Number of Interfaces = %d", __FUNCTION__, dev->config->desc.bNumInterfaces);
+-	dbg ("%s - MAX Power            = %d", __FUNCTION__, dev->config->desc.bMaxPower*2);
++	dbg ("%s - Number of Interfaces = %d", __func__, dev->config->desc.bNumInterfaces);
++	dbg ("%s - MAX Power            = %d", __func__, dev->config->desc.bMaxPower*2);
+ 
+ 	if (dev->config->desc.bNumInterfaces != 1) {
+-		dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __FUNCTION__);
++		dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __func__);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -752,7 +751,7 @@ static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
+ 		cs = (__u8)(cs + buffer[i]);
+ 	}
+ 	if (cs != rom_desc->CheckSum) {
+-		dbg ("%s - Mismatch %x - %x", __FUNCTION__, rom_desc->CheckSum, cs);
++		dbg ("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
+ 		return -EINVAL;
+ 	}
+ 	return 0;
+@@ -770,12 +769,12 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
+ 
+ 	rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ 	if (!rom_desc) {
+-		dev_err (dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err (dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL);
+ 	if (!buffer) {
+-		dev_err (dev, "%s - out of memory when allocating buffer\n", __FUNCTION__);
++		dev_err (dev, "%s - out of memory when allocating buffer\n", __func__);
+ 		kfree (rom_desc);
+ 		return -ENOMEM;
+ 	}
+@@ -786,7 +785,7 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
+ 		goto ExitTiValidateI2cImage; 
+ 
+ 	if (*buffer != UMP5152 && *buffer != UMP3410) {
+-		dev_err (dev, "%s - invalid buffer signature\n", __FUNCTION__);
++		dev_err (dev, "%s - invalid buffer signature\n", __func__);
+ 		status = -ENODEV;
+ 		goto ExitTiValidateI2cImage;
+ 	}
+@@ -802,11 +801,11 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
+ 
+ 		if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) {
+ 			status = -ENODEV;
+-			dbg ("%s - structure too big, erroring out.", __FUNCTION__);
++			dbg ("%s - structure too big, erroring out.", __func__);
+ 			break;
+ 		}
+ 
+-		dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type);
++		dbg ("%s Type = 0x%x", __func__, rom_desc->Type);
+ 
+ 		// Skip type 2 record
+ 		ttype = rom_desc->Type & 0x0f;
+@@ -846,13 +845,13 @@ static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
+ 
+ 	rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ 	if (!rom_desc) {
+-		dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc);
+ 
+ 	if (!start_address) {
+-		dbg ("%s - Edge Descriptor not found in I2C", __FUNCTION__);
++		dbg ("%s - Edge Descriptor not found in I2C", __func__);
+ 		status = -ENODEV;
+ 		goto exit;
+ 	}
+@@ -868,12 +867,12 @@ static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
+ 	status = ValidChecksum(rom_desc, buffer);
+ 	
+ 	desc = (struct edge_ti_manuf_descriptor *)buffer;
+-	dbg ( "%s - IonConfig      0x%x", __FUNCTION__, desc->IonConfig 	);
+-	dbg ( "%s - Version          %d", __FUNCTION__, desc->Version	  	);
+-	dbg ( "%s - Cpu/Board      0x%x", __FUNCTION__, desc->CpuRev_BoardRev	);
+-	dbg ( "%s - NumPorts         %d", __FUNCTION__, desc->NumPorts  	);	
+-	dbg ( "%s - NumVirtualPorts  %d", __FUNCTION__, desc->NumVirtualPorts	);	
+-	dbg ( "%s - TotalPorts       %d", __FUNCTION__, desc->TotalPorts  	);	
++	dbg ( "%s - IonConfig      0x%x", __func__, desc->IonConfig 	);
++	dbg ( "%s - Version          %d", __func__, desc->Version	  	);
++	dbg ( "%s - Cpu/Board      0x%x", __func__, desc->CpuRev_BoardRev	);
++	dbg ( "%s - NumPorts         %d", __func__, desc->NumPorts  	);
++	dbg ( "%s - NumVirtualPorts  %d", __func__, desc->NumVirtualPorts	);
++	dbg ( "%s - TotalPorts       %d", __func__, desc->TotalPorts  	);
+ 
+ exit:
+ 	kfree (rom_desc);
+@@ -903,7 +902,7 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
+ 
+ 	buffer = kmalloc (buffer_size, GFP_KERNEL);
+ 	if (!buffer) {
+-		dev_err (dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err (dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	
+@@ -956,11 +955,11 @@ static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
+ 					&data,				// TransferBuffer
+ 					0x01);				// TransferBufferLength
+ 	if (status)
+-		dbg ("%s - read 2 status error = %d", __FUNCTION__, status);
++		dbg ("%s - read 2 status error = %d", __func__, status);
+ 	else
+-		dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
++		dbg ("%s - read 2 data = 0x%x", __func__, data);
+ 	if ((!status) && (data == UMP5152 || data == UMP3410)) {
+-		dbg ("%s - ROM_TYPE_II", __FUNCTION__);
++		dbg ("%s - ROM_TYPE_II", __func__);
+ 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+ 		return 0;
+ 	}
+@@ -973,16 +972,16 @@ static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
+ 					&data,				// TransferBuffer
+ 					0x01);				// TransferBufferLength
+ 	if (status)
+-		dbg ("%s - read 3 status error = %d", __FUNCTION__, status);
++		dbg ("%s - read 3 status error = %d", __func__, status);
+ 	else
+-		dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
++		dbg ("%s - read 2 data = 0x%x", __func__, data);
+ 	if ((!status) && (data == UMP5152 || data == UMP3410)) {
+-		dbg ("%s - ROM_TYPE_III", __FUNCTION__);
++		dbg ("%s - ROM_TYPE_III", __func__);
+ 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
+ 		return 0;
+ 	}
+ 
+-	dbg ("%s - Unknown", __FUNCTION__);
++	dbg ("%s - Unknown", __func__);
+ 	serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+ 	return -ENODEV;
+ }
+@@ -1064,7 +1063,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 
+ 	interface = &serial->serial->interface->cur_altsetting->desc;
+ 	if (!interface) {
+-		dev_err (dev, "%s - no interface set, error!\n", __FUNCTION__);
++		dev_err (dev, "%s - no interface set, error!\n", __func__);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -1087,12 +1086,11 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 	if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
+ 		struct ti_i2c_desc *rom_desc;
+ 
+-		dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__);
++		dbg("%s - RUNNING IN DOWNLOAD MODE", __func__);
+ 
+ 		status = TiValidateI2cImage (serial);
+ 		if (status) {
+-			dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>",
+-			     __FUNCTION__);
++			dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__);
+ 			return status;
+ 		}
+ 		
+@@ -1101,7 +1099,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 		 */
+ 		ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+ 		if (!ti_manuf_desc) {
+-			dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++			dev_err (dev, "%s - out of memory.\n", __func__);
+ 			return -ENOMEM;
+ 		}
+ 		status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+@@ -1112,7 +1110,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 
+ 		// Check version number of ION descriptor
+ 		if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
+-			dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__, 
++			dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __func__,
+ 			     TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
+ 			kfree (ti_manuf_desc);
+ 		   	return -EINVAL;
+@@ -1120,7 +1118,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 
+ 		rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ 		if (!rom_desc) {
+-			dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++			dev_err (dev, "%s - out of memory.\n", __func__);
+ 			kfree (ti_manuf_desc);
+ 			return -ENOMEM;
+ 		}
+@@ -1130,11 +1128,11 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 			struct ti_i2c_firmware_rec *firmware_version;
+ 			__u8 record;
+ 
+-			dbg ("%s - Found Type FIRMWARE (Type 2) record", __FUNCTION__);
++			dbg ("%s - Found Type FIRMWARE (Type 2) record", __func__);
+ 
+ 			firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL);
+ 			if (!firmware_version) {
+-				dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++				dev_err (dev, "%s - out of memory.\n", __func__);
+ 				kfree (rom_desc);
+ 				kfree (ti_manuf_desc);
+ 				return -ENOMEM;
+@@ -1160,7 +1158,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 					   (OperationalCodeImageVersion.MinorVersion);
+ 
+ 			dbg ("%s - >>>Firmware Versions Device %d.%d  Driver %d.%d",
+-			     __FUNCTION__,
++			     __func__,
+ 			     firmware_version->Ver_Major,
+ 			     firmware_version->Ver_Minor,
+ 			     OperationalCodeImageVersion.MajorVersion,
+@@ -1169,7 +1167,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 			// Check if we have an old version in the I2C and update if necessary
+ 			if (download_cur_ver != download_new_ver) {
+ 				dbg ("%s - Update I2C Download from %d.%d to %d.%d",
+-				     __FUNCTION__,
++				     __func__,
+ 				     firmware_version->Ver_Major,
+ 				     firmware_version->Ver_Minor,
+ 				     OperationalCodeImageVersion.MajorVersion,
+@@ -1211,14 +1209,14 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 				}
+ 
+ 				if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
+-					dev_err (dev, "%s - error resetting device\n", __FUNCTION__);
++					dev_err (dev, "%s - error resetting device\n", __func__);
+ 					kfree (firmware_version);
+ 					kfree (rom_desc);
+ 					kfree (ti_manuf_desc);
+ 					return -ENODEV;
+ 				}
+ 
+-				dbg ("%s - HARDWARE RESET", __FUNCTION__);
++				dbg ("%s - HARDWARE RESET", __func__);
+ 
+ 				// Reset UMP -- Back to BOOT MODE
+ 				status = TISendVendorRequestSync (serial->serial->dev,
+@@ -1228,7 +1226,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 								NULL,			// TransferBuffer
+ 								0);			// TransferBufferLength
+ 
+-				dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status);
++				dbg ( "%s - HARDWARE RESET return %d", __func__, status);
+ 
+ 				/* return an error on purpose. */
+ 				kfree (firmware_version);
+@@ -1246,7 +1244,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 
+ 			header  = kmalloc (HEADER_SIZE, GFP_KERNEL);
+ 			if (!header) {
+-				dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++				dev_err (dev, "%s - out of memory.\n", __func__);
+ 				kfree (rom_desc);
+ 				kfree (ti_manuf_desc);
+ 				return -ENOMEM;
+@@ -1254,14 +1252,14 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 				
+ 			vheader = kmalloc (HEADER_SIZE, GFP_KERNEL);
+ 			if (!vheader) {
+-				dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++				dev_err (dev, "%s - out of memory.\n", __func__);
+ 				kfree (header);
+ 				kfree (rom_desc);
+ 				kfree (ti_manuf_desc);
+ 				return -ENOMEM;
+ 			}
+ 			
+-			dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __FUNCTION__);
++			dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __func__);
+ 
+ 			// In order to update the I2C firmware we must change the type 2 record to type 0xF2.
+ 			// This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver 
+@@ -1299,7 +1297,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 						vheader);
+ 
+ 			if (status) {
+-				dbg ("%s - can't read header back", __FUNCTION__);
++				dbg ("%s - can't read header back", __func__);
+ 				kfree (vheader);
+ 				kfree (header);
+ 				kfree (rom_desc);
+@@ -1307,7 +1305,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 				return status;
+ 			}
+ 			if (memcmp(vheader, header, HEADER_SIZE)) {
+-				dbg ("%s - write download record failed", __FUNCTION__);
++				dbg ("%s - write download record failed", __func__);
+ 				kfree (vheader);
+ 				kfree (header);
+ 				kfree (rom_desc);
+@@ -1318,7 +1316,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 			kfree (vheader);
+ 			kfree (header);
+ 
+-			dbg ("%s - Start firmware update", __FUNCTION__);
++			dbg ("%s - Start firmware update", __func__);
+ 
+ 			// Tell firmware to copy download image into I2C 
+ 			status = TISendVendorRequestSync (serial->serial->dev,
+@@ -1328,9 +1326,9 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 						NULL,			// TransferBuffer
+ 						0);			// TransferBufferLength
+ 
+-		  	dbg ("%s - Update complete 0x%x", __FUNCTION__, status);
++		  	dbg ("%s - Update complete 0x%x", __func__, status);
+ 			if (status) {
+-				dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __FUNCTION__);
++				dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __func__);
+ 				kfree (rom_desc);
+ 				kfree (ti_manuf_desc);
+ 				return status;
+@@ -1346,8 +1344,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 	/********************************************************************/
+ 	/* Boot Mode */
+ 	/********************************************************************/
+-	dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>",
+-	     __FUNCTION__);
++	dbg("%s - RUNNING IN BOOT MODE", __func__);
+ 
+ 	// Configure the TI device so we can use the BULK pipes for download
+ 	status = TIConfigureBootDevice (serial->serial->dev);
+@@ -1355,7 +1352,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 		return status;
+ 
+ 	if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) {
+-		dbg ("%s - VID = 0x%x", __FUNCTION__,
++		dbg ("%s - VID = 0x%x", __func__,
+ 		     le16_to_cpu(serial->serial->dev->descriptor.idVendor));
+ 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+ 		goto StayInBootMode;
+@@ -1369,7 +1366,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 
+ 	// Registry variable set?
+ 	if (TIStayInBootMode) {
+-		dbg ("%s - TIStayInBootMode", __FUNCTION__);
++		dbg ("%s - TIStayInBootMode", __func__);
+ 		goto StayInBootMode;
+ 	}
+ 
+@@ -1386,7 +1383,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 		 */
+ 		ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+ 		if (!ti_manuf_desc) {
+-			dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++			dev_err (dev, "%s - out of memory.\n", __func__);
+ 			return -ENOMEM;
+ 		}
+ 		status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+@@ -1397,7 +1394,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 
+ 		// Check for version 2
+ 		if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
+-			dbg ("%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__,
++			dbg ("%s - Wrong CPU Rev %d (Must be 2)", __func__,
+ 			     TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
+ 			kfree (ti_manuf_desc);
+ 			goto StayInBootMode;
+@@ -1421,7 +1418,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 		buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header));
+ 		buffer = kmalloc (buffer_size, GFP_KERNEL);
+ 		if (!buffer) {
+-			dev_err (dev, "%s - out of memory\n", __FUNCTION__);
++			dev_err (dev, "%s - out of memory\n", __func__);
+ 			return -ENOMEM;
+ 		}
+ 		
+@@ -1441,20 +1438,20 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 		header->CheckSum = cs;
+ 
+ 		// Download the operational code 
+-		dbg ("%s - Downloading operational code image (TI UMP)", __FUNCTION__);
++		dbg ("%s - Downloading operational code image (TI UMP)", __func__);
+ 		status = TIDownloadCodeImage (serial, buffer, buffer_size);
+ 
+ 		kfree (buffer);
+ 
+ 		if (status) {
+-	  		dbg ("%s - Error downloading operational code image", __FUNCTION__);
++	  		dbg ("%s - Error downloading operational code image", __func__);
+ 			return status;
+ 		}
+ 
+ 		// Device will reboot
+ 		serial->product_info.TiMode = TI_MODE_TRANSITIONING;
+ 
+-  		dbg ("%s - Download successful -- Device rebooting...", __FUNCTION__);
++  		dbg ("%s - Download successful -- Device rebooting...", __func__);
+ 
+ 		/* return an error on purpose */
+ 		return -ENODEV;
+@@ -1462,7 +1459,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ 
+ StayInBootMode:
+ 	// Eprom is invalid or blank stay in boot mode
+-	dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__);
++	dbg("%s - STAYING IN BOOT MODE", __func__);
+ 	serial->product_info.TiMode = TI_MODE_BOOT;
+ 
+ 	return 0;
+@@ -1473,7 +1470,7 @@ static int TISetDtr (struct edgeport_port *port)
+ {
+ 	int port_number = port->port->number - port->port->serial->minor;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 	port->shadow_mcr |= MCR_DTR;
+ 
+ 	return TIWriteCommandSync (port->port->serial->dev,
+@@ -1488,7 +1485,7 @@ static int TIClearDtr (struct edgeport_port *port)
+ {
+ 	int port_number = port->port->number - port->port->serial->minor;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 	port->shadow_mcr &= ~MCR_DTR;
+ 
+ 	return TIWriteCommandSync (port->port->serial->dev,
+@@ -1503,7 +1500,7 @@ static int TISetRts (struct edgeport_port *port)
+ {
+ 	int port_number = port->port->number - port->port->serial->minor;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 	port->shadow_mcr |= MCR_RTS;
+ 
+ 	return TIWriteCommandSync (port->port->serial->dev,
+@@ -1518,7 +1515,7 @@ static int TIClearRts (struct edgeport_port *port)
+ {
+ 	int port_number = port->port->number - port->port->serial->minor;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 	port->shadow_mcr &= ~MCR_RTS;
+ 
+ 	return TIWriteCommandSync (port->port->serial->dev,
+@@ -1533,7 +1530,7 @@ static int TISetLoopBack (struct edgeport_port *port)
+ {
+ 	int port_number = port->port->number - port->port->serial->minor;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	return TIWriteCommandSync (port->port->serial->dev,
+ 				UMPC_SET_CLR_LOOPBACK,
+@@ -1547,7 +1544,7 @@ static int TIClearLoopBack (struct edgeport_port *port)
+ {
+ 	int port_number = port->port->number - port->port->serial->minor;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	return TIWriteCommandSync (port->port->serial->dev,
+ 				UMPC_SET_CLR_LOOPBACK,
+@@ -1561,7 +1558,7 @@ static int TISetBreak (struct edgeport_port *port)
+ {
+ 	int port_number = port->port->number - port->port->serial->minor;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	return TIWriteCommandSync (port->port->serial->dev,
+ 				UMPC_SET_CLR_BREAK,
+@@ -1575,7 +1572,7 @@ static int TIClearBreak (struct edgeport_port *port)
+ {
+ 	int port_number = port->port->number - port->port->serial->minor;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	return TIWriteCommandSync (port->port->serial->dev,
+ 				UMPC_SET_CLR_BREAK,
+@@ -1589,7 +1586,7 @@ static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr)
+ {
+ 	int status = 0;
+ 
+-	dbg ("%s - %x", __FUNCTION__, mcr);
++	dbg ("%s - %x", __func__, mcr);
+ 
+ 	if (mcr & MCR_DTR)
+ 		status = TISetDtr (port);
+@@ -1643,7 +1640,7 @@ static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr)
+ 	struct async_icount *icount;
+ 	struct tty_struct *tty;
+ 
+-	dbg ("%s - %02x", __FUNCTION__, msr);
++	dbg ("%s - %02x", __func__, msr);
+ 
+ 	if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
+ 		icount = &edge_port->icount;
+@@ -1682,7 +1679,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8
+ 	struct async_icount *icount;
+ 	__u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+ 
+-	dbg ("%s - %02x", __FUNCTION__, new_lsr);
++	dbg ("%s - %02x", __func__, new_lsr);
+ 
+ 	edge_port->shadow_lsr = lsr;
+ 
+@@ -1713,7 +1710,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8
+ 
+ static void edge_interrupt_callback (struct urb *urb)
+ {
+-	struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
++	struct edgeport_serial *edge_serial = urb->context;
+ 	struct usb_serial_port *port;
+ 	struct edgeport_port *edge_port;
+ 	unsigned char *data = urb->transfer_buffer;
+@@ -1725,7 +1722,7 @@ static void edge_interrupt_callback (struct urb *urb)
+ 	__u8 msr;
+ 	int status = urb->status;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -1736,34 +1733,34 @@ static void edge_interrupt_callback (struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	default:
+ 		dev_err(&urb->dev->dev, "%s - nonzero urb status received: "
+-			"%d\n", __FUNCTION__, status);
++			"%d\n", __func__, status);
+ 		goto exit;
+ 	}
+ 
+ 	if (!length) {
+-		dbg ("%s - no data in urb", __FUNCTION__);
++		dbg ("%s - no data in urb", __func__);
+ 		goto exit;
+ 	}
+ 		
+-	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data);
++	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
+ 		
+ 	if (length != 2) {
+-		dbg ("%s - expecting packet of size 2, got %d", __FUNCTION__, length);
++		dbg ("%s - expecting packet of size 2, got %d", __func__, length);
+ 		goto exit;
+ 	}
+ 
+ 	port_number = TIUMP_GET_PORT_FROM_CODE (data[0]);
+ 	function    = TIUMP_GET_FUNC_FROM_CODE (data[0]);
+ 	dbg ("%s - port_number %d, function %d, info 0x%x",
+-	     __FUNCTION__, port_number, function, data[1]);
++	     __func__, port_number, function, data[1]);
+ 	port = edge_serial->serial->port[port_number];
+ 	edge_port = usb_get_serial_port_data(port);
+ 	if (!edge_port) {
+-		dbg ("%s - edge_port not found", __FUNCTION__);
++		dbg ("%s - edge_port not found", __func__);
+ 		return;
+ 	}
+ 	switch (function) {
+@@ -1772,12 +1769,12 @@ static void edge_interrupt_callback (struct urb *urb)
+ 		if (lsr & UMP_UART_LSR_DATA_MASK) {
+ 			/* Save the LSR event for bulk read completion routine */
+ 			dbg ("%s - LSR Event Port %u LSR Status = %02x",
+-			     __FUNCTION__, port_number, lsr);
++			     __func__, port_number, lsr);
+ 			edge_port->lsr_event = 1;
+ 			edge_port->lsr_mask = lsr;
+ 		} else {
+ 			dbg ("%s - ===== Port %d LSR Status = %02x ======",
+-			     __FUNCTION__, port_number, lsr);
++			     __func__, port_number, lsr);
+ 			handle_new_lsr (edge_port, 0, lsr, 0);
+ 		}
+ 		break;
+@@ -1786,13 +1783,13 @@ static void edge_interrupt_callback (struct urb *urb)
+ 		/* Copy MSR from UMP */
+ 		msr = data[1];
+ 		dbg ("%s - ===== Port %u MSR Status = %02x ======\n",
+-		     __FUNCTION__, port_number, msr);
++		     __func__, port_number, msr);
+ 		handle_new_msr (edge_port, msr);
+ 		break;
+ 
+ 	default:
+ 		dev_err (&urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n",
+-			 __FUNCTION__, data[1]);
++			 __func__, data[1]);
+ 		break;
+ 		
+ 	}
+@@ -1801,19 +1798,19 @@ exit:
+ 	retval = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (retval)
+ 		dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+-			 __FUNCTION__, retval);
++			 __func__, retval);
+ }
+ 
+ static void edge_bulk_in_callback (struct urb *urb)
+ {
+-	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
++	struct edgeport_port *edge_port = urb->context;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	struct tty_struct *tty;
+ 	int retval = 0;
+ 	int port_number;
+ 	int status = urb->status;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -1824,18 +1821,18 @@ static void edge_bulk_in_callback (struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	default:
+ 		dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
+-		     __FUNCTION__, status);
++		     __func__, status);
+ 	}
+ 
+ 	if (status == -EPIPE)
+ 		goto exit;
+ 
+ 	if (status) {
+-		dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__);
++		dev_err(&urb->dev->dev,"%s - stopping read!\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -1844,7 +1841,7 @@ static void edge_bulk_in_callback (struct urb *urb)
+ 	if (edge_port->lsr_event) {
+ 		edge_port->lsr_event = 0;
+ 		dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
+-		     __FUNCTION__, port_number, edge_port->lsr_mask, *data);
++		     __func__, port_number, edge_port->lsr_mask, *data);
+ 		handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data);
+ 		/* Adjust buffer length/pointer */
+ 		--urb->actual_length;
+@@ -1853,10 +1850,10 @@ static void edge_bulk_in_callback (struct urb *urb)
+ 
+ 	tty = edge_port->port->tty;
+ 	if (tty && urb->actual_length) {
+-		usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, urb->actual_length, data);
++		usb_serial_debug_data(debug, &edge_port->port->dev, __func__, urb->actual_length, data);
+ 
+ 		if (edge_port->close_pending) {
+-			dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__);
++			dbg ("%s - close is pending, dropping data on the floor.", __func__);
+ 		} else {
+ 			edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length);
+ 		}
+@@ -1875,7 +1872,7 @@ exit:
+ 	spin_unlock(&edge_port->ep_lock);
+ 	if (retval)
+ 		dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+-			 __FUNCTION__, retval);
++			 __func__, retval);
+ }
+ 
+ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
+@@ -1886,7 +1883,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
+ 		cnt = tty_buffer_request_room(tty, length);
+ 		if (cnt < length) {
+ 			dev_err(dev, "%s - dropping data, %d bytes lost\n",
+-				__FUNCTION__, length - cnt);
++				__func__, length - cnt);
+ 			if(cnt == 0)
+ 				break;
+ 		}
+@@ -1900,11 +1897,11 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
+ 
+ static void edge_bulk_out_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ 	int status = urb->status;
+ 
+-	dbg ("%s - port %d", __FUNCTION__, port->number);
++	dbg ("%s - port %d", __func__, port->number);
+ 
+ 	edge_port->ep_write_urb_in_use = 0;
+ 
+@@ -1917,11 +1914,11 @@ static void edge_bulk_out_callback (struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	default:
+ 		dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
+-			"received: %d\n", __FUNCTION__, status);
++			"received: %d\n", __func__, status);
+ 	}
+ 
+ 	/* send any buffered data */
+@@ -1939,13 +1936,12 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 	u16 open_settings;
+ 	u8 transaction_timeout;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return -ENODEV;
+ 
+-	if (port->tty)
+-		port->tty->low_latency = low_latency;
++	port->tty->low_latency = low_latency;
+ 
+ 	port_number = port->number - port->serial->minor;
+ 	switch (port_number) {
+@@ -1963,7 +1959,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 	}
+ 
+ 	dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
+-	     __FUNCTION__, port_number, edge_port->uart_base, edge_port->dma_address);
++	     __func__, port_number, edge_port->uart_base, edge_port->dma_address);
+ 
+ 	dev = port->serial->dev;
+ 
+@@ -1974,7 +1970,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 	status = TIClearLoopBack (edge_port);
+ 	if (status) {
+ 		dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		return status;
+ 	}
+ 	
+@@ -1993,7 +1989,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 			     UMP_PIPE_TRANS_TIMEOUT_ENA | 
+ 			     (transaction_timeout << 2));
+ 
+-	dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__);
++	dbg ("%s - Sending UMPC_OPEN_PORT", __func__);
+ 
+ 	/* Tell TI to open and start the port */
+ 	status = TIWriteCommandSync (dev,
+@@ -2003,7 +1999,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 					NULL,
+ 					0);
+ 	if (status) {
+-		dev_err(&port->dev,"%s - cannot send open command, %d\n", __FUNCTION__, status);
++		dev_err(&port->dev,"%s - cannot send open command, %d\n", __func__, status);
+ 		return status;
+ 	}
+ 
+@@ -2015,14 +2011,14 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 					NULL,
+ 					0);
+ 	if (status) {
+-		dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __FUNCTION__, status);
++		dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __func__, status);
+ 		return status;
+ 	}
+ 
+ 	/* Clear TX and RX buffers in UMP */
+ 	status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN);
+ 	if (status) {
+-		dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __FUNCTION__, status);
++		dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __func__, status);
+ 		return status;
+ 	}
+ 
+@@ -2034,7 +2030,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 					&edge_port->shadow_msr,			// TransferBuffer
+ 					1);					// TransferBufferLength
+ 	if (status) {
+- 		dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __FUNCTION__, status);
++ 		dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __func__, status);
+ 		return status;
+ 	}
+ 
+@@ -2051,7 +2047,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 		/* we are the first port to be opened, let's post the interrupt urb */
+ 		urb = edge_serial->serial->port[0]->interrupt_in_urb;
+ 		if (!urb) {
+-			dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__);
++			dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __func__);
+ 			status = -EINVAL;
+ 			goto release_es_lock;
+ 		}
+@@ -2060,7 +2056,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 		urb->dev = dev;
+ 		status = usb_submit_urb (urb, GFP_KERNEL);
+ 		if (status) {
+-			dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status);
++			dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __func__, status);
+ 			goto release_es_lock;
+ 		}
+ 	}
+@@ -2075,7 +2071,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 	/* start up our bulk read urb */
+ 	urb = port->read_urb;
+ 	if (!urb) {
+-		dev_err (&port->dev, "%s - no read urb present, exiting\n", __FUNCTION__);
++		dev_err (&port->dev, "%s - no read urb present, exiting\n", __func__);
+ 		status = -EINVAL;
+ 		goto unlink_int_urb;
+ 	}
+@@ -2085,13 +2081,13 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ 	urb->dev = dev;
+ 	status = usb_submit_urb (urb, GFP_KERNEL);
+ 	if (status) {
+-		dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status);
++		dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
+ 		goto unlink_int_urb;
+ 	}
+ 
+ 	++edge_serial->num_ports_open;
+ 
+-	dbg("%s - exited", __FUNCTION__);
++	dbg("%s - exited", __func__);
+ 
+ 	goto release_es_lock;
+ 
+@@ -2110,7 +2106,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
+ 	int port_number;
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 			 
+ 	edge_serial = usb_get_serial_data(port->serial);
+ 	edge_port = usb_get_serial_port_data(port);
+@@ -2130,7 +2126,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
+ 
+ 	/* assuming we can still talk to the device,
+ 	 * send a close port command to it */
+-	dbg("%s - send umpc_close_port", __FUNCTION__);
++	dbg("%s - send umpc_close_port", __func__);
+ 	port_number = port->number - port->serial->minor;
+ 	status = TIWriteCommandSync (port->serial->dev,
+ 				     UMPC_CLOSE_PORT,
+@@ -2148,7 +2144,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
+ 	mutex_unlock(&edge_serial->es_lock);
+ 	edge_port->close_pending = 0;
+ 
+-	dbg("%s - exited", __FUNCTION__);
++	dbg("%s - exited", __func__);
+ }
+ 
+ static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count)
+@@ -2156,10 +2152,10 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (count == 0) {
+-		dbg("%s - write request of 0 bytes", __FUNCTION__);
++		dbg("%s - write request of 0 bytes", __func__);
+ 		return 0;
+ 	}
+ 
+@@ -2185,7 +2181,7 @@ static void edge_send(struct usb_serial_port *port)
+ 	unsigned long flags;
+ 
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&edge_port->ep_lock, flags);
+ 
+@@ -2207,7 +2203,7 @@ static void edge_send(struct usb_serial_port *port)
+ 
+ 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+ 
+ 	/* set up our urb */
+ 	usb_fill_bulk_urb (port->write_urb, port->serial->dev,
+@@ -2220,7 +2216,7 @@ static void edge_send(struct usb_serial_port *port)
+ 	/* send the data out the bulk port */
+ 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 	if (result) {
+-		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ 		edge_port->ep_write_urb_in_use = 0;
+ 		// TODO: reschedule edge_send
+ 	} else {
+@@ -2241,7 +2237,7 @@ static int edge_write_room (struct usb_serial_port *port)
+ 	int room = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return -ENODEV;
+@@ -2252,7 +2248,7 @@ static int edge_write_room (struct usb_serial_port *port)
+ 	room = edge_buf_space_avail(edge_port->ep_out_buf);
+ 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 	return room;
+ }
+ 
+@@ -2262,7 +2258,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ 	int chars = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return -ENODEV;
+@@ -2273,7 +2269,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ 	chars = edge_buf_data_avail(edge_port->ep_out_buf);
+ 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ 
+-	dbg ("%s - returns %d", __FUNCTION__, chars);
++	dbg ("%s - returns %d", __func__, chars);
+ 	return chars;
+ }
+ 
+@@ -2283,14 +2279,14 @@ static void edge_throttle (struct usb_serial_port *port)
+ 	struct tty_struct *tty;
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return;
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg ("%s - no tty available", __FUNCTION__);
++		dbg ("%s - no tty available", __func__);
+ 		return;
+ 	}
+ 
+@@ -2299,7 +2295,7 @@ static void edge_throttle (struct usb_serial_port *port)
+ 		unsigned char stop_char = STOP_CHAR(tty);
+ 		status = edge_write (port, &stop_char, 1);
+ 		if (status <= 0) {
+-			dev_err(&port->dev, "%s - failed to write stop character, %d\n", __FUNCTION__, status);
++			dev_err(&port->dev, "%s - failed to write stop character, %d\n", __func__, status);
+ 		}
+ 	}
+ 
+@@ -2316,14 +2312,14 @@ static void edge_unthrottle (struct usb_serial_port *port)
+ 	struct tty_struct *tty;
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return;
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg ("%s - no tty available", __FUNCTION__);
++		dbg ("%s - no tty available", __func__);
+ 		return;
+ 	}
+ 
+@@ -2332,7 +2328,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
+ 		unsigned char start_char = START_CHAR(tty);
+ 		status = edge_write (port, &start_char, 1);
+ 		if (status <= 0) {
+-			dev_err(&port->dev, "%s - failed to write start character, %d\n", __FUNCTION__, status);
++			dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
+ 		}
+ 	}
+ 
+@@ -2341,7 +2337,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
+ 	if (C_CRTSCTS(tty)) {
+ 		status = restart_read(edge_port);
+ 		if (status)
+-			dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status);
++			dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
+ 	}
+ 
+ }
+@@ -2391,13 +2387,13 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 	int status;
+ 	int port_number = edge_port->port->number - edge_port->port->serial->minor;
+ 
+-	dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
++	dbg("%s - port %d", __func__, edge_port->port->number);
+ 
+ 	tty = edge_port->port->tty;
+ 
+ 	config = kmalloc (sizeof (*config), GFP_KERNEL);
+ 	if (!config) {
+-		dev_err (&edge_port->port->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err (&edge_port->port->dev, "%s - out of memory\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -2413,20 +2409,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 	switch (cflag & CSIZE) {
+ 		case CS5:
+ 			    config->bDataBits = UMP_UART_CHAR5BITS;
+-			    dbg ("%s - data bits = 5", __FUNCTION__);
++			    dbg ("%s - data bits = 5", __func__);
+ 			    break;
+ 		case CS6:
+ 			    config->bDataBits = UMP_UART_CHAR6BITS;
+-			    dbg ("%s - data bits = 6", __FUNCTION__);
++			    dbg ("%s - data bits = 6", __func__);
+ 			    break;
+ 		case CS7:
+ 			    config->bDataBits = UMP_UART_CHAR7BITS;
+-			    dbg ("%s - data bits = 7", __FUNCTION__);
++			    dbg ("%s - data bits = 7", __func__);
+ 			    break;
+ 		default:
+ 		case CS8:
+ 			    config->bDataBits = UMP_UART_CHAR8BITS;
+-			    dbg ("%s - data bits = 8", __FUNCTION__);
++			    dbg ("%s - data bits = 8", __func__);
+ 			    break;
+ 	}
+ 
+@@ -2434,32 +2430,32 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 		if (cflag & PARODD) {
+ 			config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
+ 			config->bParity = UMP_UART_ODDPARITY;
+-			dbg("%s - parity = odd", __FUNCTION__);
++			dbg("%s - parity = odd", __func__);
+ 		} else {
+ 			config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
+ 			config->bParity = UMP_UART_EVENPARITY;
+-			dbg("%s - parity = even", __FUNCTION__);
++			dbg("%s - parity = even", __func__);
+ 		}
+ 	} else {
+ 		config->bParity = UMP_UART_NOPARITY; 	
+-		dbg("%s - parity = none", __FUNCTION__);
++		dbg("%s - parity = none", __func__);
+ 	}
+ 
+ 	if (cflag & CSTOPB) {
+ 		config->bStopBits = UMP_UART_STOPBIT2;
+-		dbg("%s - stop bits = 2", __FUNCTION__);
++		dbg("%s - stop bits = 2", __func__);
+ 	} else {
+ 		config->bStopBits = UMP_UART_STOPBIT1;
+-		dbg("%s - stop bits = 1", __FUNCTION__);
++		dbg("%s - stop bits = 1", __func__);
+ 	}
+ 
+ 	/* figure out the flow control settings */
+ 	if (cflag & CRTSCTS) {
+ 		config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW;
+ 		config->wFlags |= UMP_MASK_UART_FLAGS_RTS_FLOW;
+-		dbg("%s - RTS/CTS is enabled", __FUNCTION__);
++		dbg("%s - RTS/CTS is enabled", __func__);
+ 	} else {
+-		dbg("%s - RTS/CTS is disabled", __FUNCTION__);
++		dbg("%s - RTS/CTS is disabled", __func__);
+ 		tty->hw_stopped = 0;
+ 		restart_read(edge_port);
+ 	}
+@@ -2473,18 +2469,18 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 		if (I_IXOFF(tty)) {
+ 			config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
+ 			dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+-			     __FUNCTION__, config->cXon, config->cXoff);
++			     __func__, config->cXon, config->cXoff);
+ 		} else {
+-			dbg ("%s - INBOUND XON/XOFF is disabled", __FUNCTION__);
++			dbg ("%s - INBOUND XON/XOFF is disabled", __func__);
+ 		}
+ 
+ 		/* if we are implementing OUTBOUND XON/XOFF */
+ 		if (I_IXON(tty)) {
+ 			config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
+ 			dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+-			     __FUNCTION__, config->cXon, config->cXoff);
++			     __func__, config->cXon, config->cXoff);
+ 		} else {
+-			dbg ("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__);
++			dbg ("%s - OUTBOUND XON/XOFF is disabled", __func__);
+ 		}
+ 	}
+ 
+@@ -2503,7 +2499,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 
+ 	/* FIXME: Recompute actual baud from divisor here */
+ 
+-	dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate);
++	dbg ("%s - baud rate = %d, wBaudRate = %d", __func__, baud, config->wBaudRate);
+ 
+ 	dbg ("wBaudRate:   %d", (int)(461550L / config->wBaudRate));
+ 	dbg ("wFlags:    0x%x", config->wFlags);
+@@ -2526,7 +2522,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ 				sizeof(*config));
+ 	if (status) {
+ 		dbg ("%s - error %d when trying to write config to device",
+-		     __FUNCTION__, status);
++		     __func__, status);
+ 	}
+ 
+ 	kfree (config);
+@@ -2542,12 +2538,12 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
+ 
+ 	cflag = tty->termios->c_cflag;
+ 
+-	dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
++	dbg("%s - clfag %08x iflag %08x", __func__,
+ 	    tty->termios->c_cflag, tty->termios->c_iflag);
+-	dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
++	dbg("%s - old clfag %08x old iflag %08x", __func__,
+ 	    old_termios->c_cflag, old_termios->c_iflag);
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (edge_port == NULL)
+ 		return;
+@@ -2562,9 +2558,11 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
+ {
+ 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ 	unsigned int mcr;
++	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
++	spin_lock_irqsave(&edge_port->ep_lock, flags);
+ 	mcr = edge_port->shadow_mcr;
+ 	if (set & TIOCM_RTS)
+ 		mcr |= MCR_RTS;
+@@ -2581,6 +2579,7 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
+ 		mcr &= ~MCR_LOOPBACK;
+ 
+ 	edge_port->shadow_mcr = mcr;
++	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ 
+ 	TIRestoreMCR (edge_port, mcr);
+ 
+@@ -2593,8 +2592,11 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+ 	unsigned int result = 0;
+ 	unsigned int msr;
+ 	unsigned int mcr;
++	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
++
++	spin_lock_irqsave(&edge_port->ep_lock, flags);
+ 
+ 	msr = edge_port->shadow_msr;
+ 	mcr = edge_port->shadow_mcr;
+@@ -2606,7 +2608,8 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+ 		  | ((msr & EDGEPORT_MSR_DSR)	? TIOCM_DSR: 0);  /* 0x100 */
+ 
+ 
+-	dbg("%s -- %x", __FUNCTION__, result);
++	dbg("%s -- %x", __func__, result);
++	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ 
+ 	return result;
+ }
+@@ -2645,30 +2648,30 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
+ 	struct async_icount cnow;
+ 	struct async_icount cprev;
+ 
+-	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+ 
+ 	switch (cmd) {
+ 		case TIOCINQ:
+-			dbg("%s - (%d) TIOCINQ", __FUNCTION__, port->number);
++			dbg("%s - (%d) TIOCINQ", __func__, port->number);
+ //			return get_number_bytes_avail(edge_port, (unsigned int *) arg);
+ 			break;
+ 
+ 		case TIOCSERGETLSR:
+-			dbg("%s - (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
++			dbg("%s - (%d) TIOCSERGETLSR", __func__, port->number);
+ //			return get_lsr_info(edge_port, (unsigned int *) arg);
+ 			break;
+ 
+ 		case TIOCGSERIAL:
+-			dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
++			dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+ 			return get_serial_info(edge_port, (struct serial_struct __user *) arg);
+ 			break;
+ 
+ 		case TIOCSSERIAL:
+-			dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++			dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
+ 			break;
+ 
+ 		case TIOCMIWAIT:
+-			dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number);
++			dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
+ 			cprev = edge_port->icount;
+ 			while (1) {
+ 				interruptible_sleep_on(&edge_port->delta_msr_wait);
+@@ -2691,7 +2694,7 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
+ 			break;
+ 
+ 		case TIOCGICOUNT:
+-			dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
++			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;
+@@ -2706,7 +2709,7 @@ static void edge_break (struct usb_serial_port *port, int break_state)
+ 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ 	int status;
+ 
+-	dbg ("%s - state = %d", __FUNCTION__, break_state);
++	dbg ("%s - state = %d", __func__, break_state);
+ 
+ 	/* chase the port close */
+ 	TIChasePort (edge_port, 0, 0);
+@@ -2718,7 +2721,7 @@ static void edge_break (struct usb_serial_port *port, int break_state)
+ 	}
+ 	if (status) {
+ 		dbg ("%s - error %d sending break set/clear command.",
+-		     __FUNCTION__, status);
++		     __func__, status);
+ 	}
+ }
+ 
+@@ -2735,7 +2738,7 @@ static int edge_startup (struct usb_serial *serial)
+ 	/* create our private serial structure */
+ 	edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
+ 	if (edge_serial == NULL) {
+-		dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++		dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	mutex_init(&edge_serial->es_lock);
+@@ -2752,13 +2755,13 @@ static int edge_startup (struct usb_serial *serial)
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
+ 		if (edge_port == NULL) {
+-			dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++			dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ 			goto cleanup;
+ 		}
+ 		spin_lock_init(&edge_port->ep_lock);
+ 		edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE);
+ 		if (edge_port->ep_out_buf == NULL) {
+-			dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++			dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ 			kfree(edge_port);
+ 			goto cleanup;
+ 		}
+@@ -2787,7 +2790,7 @@ static void edge_shutdown (struct usb_serial *serial)
+ 	int i;
+ 	struct edgeport_port *edge_port;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		edge_port = usb_get_serial_port_data(serial->port[i]);
+@@ -2819,12 +2822,12 @@ static ssize_t store_uart_mode(struct device *dev,
+ 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ 	unsigned int v = simple_strtoul(valbuf, NULL, 0);
+ 
+-	dbg("%s: setting uart_mode = %d", __FUNCTION__, v);
++	dbg("%s: setting uart_mode = %d", __func__, v);
+ 
+ 	if (v < 256)
+ 		edge_port->bUartMode = v;
+ 	else
+-		dev_err(dev, "%s - uart_mode %d is invalid\n", __FUNCTION__, v);
++		dev_err(dev, "%s - uart_mode %d is invalid\n", __func__, v);
+ 
+ 	return count;
+ }
+@@ -3029,9 +3032,6 @@ static struct usb_serial_driver edgeport_1port_device = {
+ 	.description		= "Edgeport TI 1 port adapter",
+ 	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_1port_id_table,
+-	.num_interrupt_in	= 1,
+-	.num_bulk_in		= 1,
+-	.num_bulk_out		= 1,
+ 	.num_ports		= 1,
+ 	.open			= edge_open,
+ 	.close			= edge_close,
+@@ -3061,9 +3061,6 @@ static struct usb_serial_driver edgeport_2port_device = {
+ 	.description		= "Edgeport TI 2 port adapter",
+ 	.usb_driver		= &io_driver,
+ 	.id_table		= edgeport_2port_id_table,
+-	.num_interrupt_in	= 1,
+-	.num_bulk_in		= 2,
+-	.num_bulk_out		= 2,
+ 	.num_ports		= 2,
+ 	.open			= edge_open,
+ 	.close			= edge_close,
+diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
+index 9b38a08..ea924dc 100644
+--- a/drivers/usb/serial/ipaq.c
++++ b/drivers/usb/serial/ipaq.c
+@@ -570,10 +570,7 @@ static struct usb_serial_driver ipaq_device = {
+ 	.description =		"PocketPC PDA",
+ 	.usb_driver = 		&ipaq_driver,
+ 	.id_table =		ipaq_id_table,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+-	.num_ports =		1,
++	.num_ports =		2,
+ 	.open =			ipaq_open,
+ 	.close =		ipaq_close,
+ 	.attach =		ipaq_startup,
+@@ -597,13 +594,13 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+ 	int			i, result = 0;
+ 	int			retries = connect_retries;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	bytes_in = 0;
+ 	bytes_out = 0;
+ 	priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
+ 	if (priv == NULL) {
+-		err("%s - Out of memory", __FUNCTION__);
++		err("%s - Out of memory", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	usb_set_serial_port_data(port, priv);
+@@ -682,7 +679,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+ 	}
+ 
+ 	if (!retries && result) {
+-		err("%s - failed doing control urb, error %d", __FUNCTION__,
++		err("%s - failed doing control urb, error %d", __func__,
+ 		    result);
+ 		goto error;
+ 	}
+@@ -695,7 +692,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+ 
+ 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (result) {
+-		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
++		err("%s - failed submitting read urb, error %d", __func__, result);
+ 		goto error;
+ 	}
+ 
+@@ -703,7 +700,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+ 
+ enomem:
+ 	result = -ENOMEM;
+-	err("%s - Out of memory", __FUNCTION__);
++	err("%s - Out of memory", __func__);
+ error:
+ 	ipaq_destroy_lists(port);
+ 	kfree(priv);
+@@ -715,7 +712,7 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
+ {
+ 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 			 
+ 	/*
+ 	 * shut down bulk read and write
+@@ -732,21 +729,21 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
+ 
+ static void ipaq_read_bulk_callback(struct urb *urb)
+ {
+-	struct usb_serial_port	*port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port	*port = urb->context;
+ 	struct tty_struct	*tty;
+ 	unsigned char		*data = urb->transfer_buffer;
+ 	int			result;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	tty = port->tty;
+ 	if (tty && urb->actual_length) {
+@@ -763,7 +760,7 @@ static void ipaq_read_bulk_callback(struct urb *urb)
+ 		      ipaq_read_bulk_callback, port);
+ 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 	if (result)
+-		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++		err("%s - failed resubmitting read urb, error %d", __func__, result);
+ 	return;
+ }
+ 
+@@ -774,7 +771,7 @@ static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
+ 	int			bytes_sent = 0;
+ 	int			transfer_size;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	while (count > 0) {
+ 		transfer_size = min(count, PACKET_SIZE);
+@@ -799,7 +796,7 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
+ 	unsigned long		flags;
+ 
+ 	if (priv->free_len <= 0) {
+-		dbg("%s - we're stuffed", __FUNCTION__);
++		dbg("%s - we're stuffed", __func__);
+ 		return -EAGAIN;
+ 	}
+ 
+@@ -811,12 +808,12 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
+ 	}
+ 	spin_unlock_irqrestore(&write_list_lock, flags);
+ 	if (pkt == NULL) {
+-		dbg("%s - we're stuffed", __FUNCTION__);
++		dbg("%s - we're stuffed", __func__);
+ 		return -EAGAIN;
+ 	}
+ 
+ 	memcpy(pkt->data, buf, count);
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, pkt->data);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, pkt->data);
+ 
+ 	pkt->len = count;
+ 	pkt->written = 0;
+@@ -829,7 +826,7 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
+ 		spin_unlock_irqrestore(&write_list_lock, flags);
+ 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 		if (result) {
+-			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++			err("%s - failed submitting write urb, error %d", __func__, result);
+ 		}
+ 	} else {
+ 		spin_unlock_irqrestore(&write_list_lock, flags);
+@@ -872,17 +869,17 @@ static void ipaq_write_gather(struct usb_serial_port *port)
+ 
+ static void ipaq_write_bulk_callback(struct urb *urb)
+ {
+-	struct usb_serial_port	*port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port	*port = urb->context;
+ 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
+ 	unsigned long		flags;
+ 	int			result;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+@@ -892,7 +889,7 @@ static void ipaq_write_bulk_callback(struct urb *urb)
+ 		spin_unlock_irqrestore(&write_list_lock, flags);
+ 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 		if (result) {
+-			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++			err("%s - failed submitting write urb, error %d", __func__, result);
+ 		}
+ 	} else {
+ 		priv->active = 0;
+@@ -906,7 +903,7 @@ static int ipaq_write_room(struct usb_serial_port *port)
+ {
+ 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s - freelen %d", __FUNCTION__, priv->free_len);
++	dbg("%s - freelen %d", __func__, priv->free_len);
+ 	return priv->free_len;
+ }
+ 
+@@ -914,7 +911,7 @@ static int ipaq_chars_in_buffer(struct usb_serial_port *port)
+ {
+ 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s - queuelen %d", __FUNCTION__, priv->queue_len);
++	dbg("%s - queuelen %d", __func__, priv->queue_len);
+ 	return priv->queue_len;
+ }
+ 
+@@ -936,7 +933,7 @@ static void ipaq_destroy_lists(struct usb_serial_port *port)
+ 
+ static int ipaq_startup(struct usb_serial *serial)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
+ 		err("active config #%d != 1 ??",
+ 			serial->dev->actconfig->desc.bConfigurationValue);
+@@ -947,7 +944,7 @@ static int ipaq_startup(struct usb_serial *serial)
+ 
+ static void ipaq_shutdown(struct usb_serial *serial)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ }
+ 
+ static int __init ipaq_init(void)
+diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
+index cbe5530..bc85ca5 100644
+--- a/drivers/usb/serial/ipw.c
++++ b/drivers/usb/serial/ipw.c
+@@ -169,15 +169,15 @@ static void ipw_read_bulk_callback(struct urb *urb)
+ 	int result;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	tty = port->tty;
+ 	if (tty && urb->actual_length) {
+@@ -195,7 +195,7 @@ static void ipw_read_bulk_callback(struct urb *urb)
+ 			   ipw_read_bulk_callback, port);
+ 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 	if (result)
+-		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ 	return;
+ }
+ 
+@@ -206,7 +206,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ 	u8 *buf_flow_init;
+ 	int result;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
+ 	if (!buf_flow_init)
+@@ -217,7 +217,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ 
+ 	/* --1: Tell the modem to initialize (we think) From sniffs this is always the
+ 	 * first thing that gets sent to the modem during opening of the device */
+-	dbg("%s: Sending SIO_INIT (we guess)",__FUNCTION__);
++	dbg("%s: Sending SIO_INIT (we guess)",__func__);
+ 	result = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
+ 				 IPW_SIO_INIT,
+ 				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -234,7 +234,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ 	usb_clear_halt(dev, usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
+ 
+ 	/*--2: Start reading from the device */	
+-	dbg("%s: setting up bulk read callback",__FUNCTION__);
++	dbg("%s: setting up bulk read callback",__func__);
+ 	usb_fill_bulk_urb(port->read_urb, dev,
+ 			  usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
+ 			  port->bulk_in_buffer,
+@@ -242,10 +242,10 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ 			  ipw_read_bulk_callback, port);
+ 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (result < 0)
+-		dbg("%s - usb_submit_urb(read bulk) failed with status %d", __FUNCTION__, result);
++		dbg("%s - usb_submit_urb(read bulk) failed with status %d", __func__, result);
+ 
+ 	/*--3: Tell the modem to open the floodgates on the rx bulk channel */
+-	dbg("%s:asking modem for RxRead (RXBULK_ON)",__FUNCTION__);
++	dbg("%s:asking modem for RxRead (RXBULK_ON)",__func__);
+ 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 				 IPW_SIO_RXCTL,
+ 				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -258,7 +258,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ 		dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)\n", result);
+ 
+ 	/*--4: setup the initial flowcontrol */
+-	dbg("%s:setting init flowcontrol (%s)",__FUNCTION__,buf_flow_init);
++	dbg("%s:setting init flowcontrol (%s)",__func__,buf_flow_init);
+ 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 				 IPW_SIO_HANDFLOW,
+ 				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -272,7 +272,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ 
+ 
+ 	/*--5: raise the dtr */
+-	dbg("%s:raising dtr",__FUNCTION__);
++	dbg("%s:raising dtr",__func__);
+ 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 				 IPW_SIO_SET_PIN,
+ 				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -285,7 +285,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ 		dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
+ 
+ 	/*--6: raise the rts */
+-	dbg("%s:raising rts",__FUNCTION__);
++	dbg("%s:raising rts",__func__);
+ 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 				 IPW_SIO_SET_PIN,
+ 				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -307,12 +307,12 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
+ 	int result;
+ 
+ 	if (tty_hung_up_p(filp)) {
+-		dbg("%s: tty_hung_up_p ...", __FUNCTION__);
++		dbg("%s: tty_hung_up_p ...", __func__);
+ 		return;
+ 	}
+ 
+ 	/*--1: drop the dtr */
+-	dbg("%s:dropping dtr",__FUNCTION__);
++	dbg("%s:dropping dtr",__func__);
+ 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 				 IPW_SIO_SET_PIN,
+ 				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -325,7 +325,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
+ 		dev_err(&port->dev, "dropping dtr failed (error = %d)\n", result);
+ 
+ 	/*--2: drop the rts */
+-	dbg("%s:dropping rts",__FUNCTION__);
++	dbg("%s:dropping rts",__func__);
+ 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 				 IPW_SIO_SET_PIN, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 				 IPW_PIN_CLRRTS,
+@@ -338,7 +338,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
+ 
+ 
+ 	/*--3: purge */
+-	dbg("%s:sending purge",__FUNCTION__);
++	dbg("%s:sending purge",__func__);
+ 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 				 IPW_SIO_PURGE, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 				 0x03,
+@@ -373,13 +373,13 @@ static void ipw_write_bulk_callback(struct urb *urb)
+ 	struct usb_serial_port *port = urb->context;
+ 	int status = urb->status;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	port->write_urb_busy = 0;
+ 
+ 	if (status)
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 
+ 	usb_serial_port_softint(port);
+ }
+@@ -389,18 +389,18 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
+ 	struct usb_device *dev = port->serial->dev;
+ 	int ret;
+ 
+-	dbg("%s: TOP: count=%d, in_interrupt=%ld", __FUNCTION__,
++	dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__,
+ 		count, in_interrupt() );
+ 
+ 	if (count == 0) {
+-		dbg("%s - write request of 0 bytes", __FUNCTION__);
++		dbg("%s - write request of 0 bytes", __func__);
+ 		return 0;
+ 	}
+ 
+ 	spin_lock_bh(&port->lock);
+ 	if (port->write_urb_busy) {
+ 		spin_unlock_bh(&port->lock);
+-		dbg("%s - already writing", __FUNCTION__);
++		dbg("%s - already writing", __func__);
+ 		return 0;
+ 	}
+ 	port->write_urb_busy = 1;
+@@ -409,7 +409,7 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
+ 	count = min(count, port->bulk_out_size);
+ 	memcpy(port->bulk_out_buffer, buf, count);
+ 
+-	dbg("%s count now:%d", __FUNCTION__, count);
++	dbg("%s count now:%d", __func__, count);
+ 
+ 	usb_fill_bulk_urb(port->write_urb, dev,
+ 			  usb_sndbulkpipe(dev, port->bulk_out_endpointAddress),
+@@ -421,11 +421,11 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
+ 	ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 	if (ret != 0) {
+ 		port->write_urb_busy = 0;
+-		dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret);
++		dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __func__, ret);
+ 		return ret;
+ 	}
+ 
+-	dbg("%s returning %d", __FUNCTION__, count);
++	dbg("%s returning %d", __func__, count);
+ 	return count;
+ } 
+ 
+@@ -448,9 +448,6 @@ static struct usb_serial_driver ipw_device = {
+ 	.description =		"IPWireless converter",
+ 	.usb_driver = 		&usb_ipw_driver,
+ 	.id_table =		usb_ipw_ids,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.open =			ipw_open,
+ 	.close =		ipw_close,
+diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
+index 6b803ab..004d573 100644
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -145,9 +145,6 @@ static struct usb_serial_driver ir_device = {
+ 	.description =		"IR Dongle",
+ 	.usb_driver = 		&ir_driver,
+ 	.id_table =		id_table,
+-	.num_interrupt_in =	1,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.set_termios =		ir_set_termios,
+ 	.attach =		ir_startup,
+@@ -198,16 +195,16 @@ static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev,
+ 			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 			0, ifnum, desc, sizeof(*desc), 1000);
+ 	
+-	dbg("%s -  ret=%d", __FUNCTION__, ret);
++	dbg("%s -  ret=%d", __func__, ret);
+ 	if (ret < sizeof(*desc)) {
+ 		dbg("%s - class descriptor read %s (%d)",
+-				__FUNCTION__, 
++				__func__,
+ 				(ret<0) ? "failed" : "too short",
+ 				ret);
+ 		goto error;
+ 	}
+ 	if (desc->bDescriptorType != USB_DT_IRDA) {
+-		dbg("%s - bad class descriptor type", __FUNCTION__);
++		dbg("%s - bad class descriptor type", __func__);
+ 		goto error;
+ 	}
+ 	
+@@ -251,7 +248,7 @@ static int ir_startup (struct usb_serial *serial)
+ 	}
+ 
+ 	dbg ("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
+-		__FUNCTION__,
++		__func__,
+ 		(irda_desc->wBaudRate & 0x0001) ? " 2400"    : "",
+ 		(irda_desc->wBaudRate & 0x0002) ? " 9600"    : "",
+ 		(irda_desc->wBaudRate & 0x0004) ? " 19200"   : "",
+@@ -284,13 +281,13 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
+ 	char *buffer;
+ 	int result = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (buffer_size) {
+ 		/* override the default buffer sizes */
+ 		buffer = kmalloc (buffer_size, GFP_KERNEL);
+ 		if (!buffer) {
+-			dev_err (&port->dev, "%s - out of memory.\n", __FUNCTION__);
++			dev_err (&port->dev, "%s - out of memory.\n", __func__);
+ 			return -ENOMEM;
+ 		}
+ 		kfree (port->read_urb->transfer_buffer);
+@@ -299,7 +296,7 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
+ 
+ 		buffer = kmalloc (buffer_size, GFP_KERNEL);
+ 		if (!buffer) {
+-			dev_err (&port->dev, "%s - out of memory.\n", __FUNCTION__);
++			dev_err (&port->dev, "%s - out of memory.\n", __func__);
+ 			return -ENOMEM;
+ 		}
+ 		kfree (port->write_urb->transfer_buffer);
+@@ -319,14 +316,14 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
+ 		port);
+ 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (result)
+-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ 
+ 	return result;
+ }
+ 
+ static void ir_close (struct usb_serial_port *port, struct file * filp)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 			 
+ 	/* shutdown our bulk read */
+ 	usb_kill_urb(port->read_urb);
+@@ -338,10 +335,10 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
+ 	int result;
+ 	int transfer_size;
+ 
+-	dbg("%s - port = %d, count = %d", __FUNCTION__, port->number, count);
++	dbg("%s - port = %d, count = %d", __func__, port->number, count);
+ 
+ 	if (!port->tty) {
+-		dev_err (&port->dev, "%s - no tty???\n", __FUNCTION__);
++		dev_err (&port->dev, "%s - no tty???\n", __func__);
+ 		return 0;
+ 	}
+ 
+@@ -351,7 +348,7 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
+ 	spin_lock_bh(&port->lock);
+ 	if (port->write_urb_busy) {
+ 		spin_unlock_bh(&port->lock);
+-		dbg("%s - already writing", __FUNCTION__);
++		dbg("%s - already writing", __func__);
+ 		return 0;
+ 	}
+ 	port->write_urb_busy = 1;
+@@ -387,7 +384,7 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
+ 	result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+ 	if (result) {
+ 		port->write_urb_busy = 0;
+-		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ 	} else
+ 		result = transfer_size;
+ 
+@@ -396,22 +393,22 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
+ 
+ static void ir_write_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	port->write_urb_busy = 0;
+ 	if (status) {
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+ 	usb_serial_debug_data (
+ 		debug,
+ 		&port->dev,
+-		__FUNCTION__,
++		__func__,
+ 		urb->actual_length,
+ 		urb->transfer_buffer);
+ 
+@@ -420,16 +417,16 @@ static void ir_write_bulk_callback (struct urb *urb)
+ 
+ static void ir_read_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct tty_struct *tty;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int result;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->open_count) {
+-		dbg("%s - port closed.", __FUNCTION__);
++		dbg("%s - port closed.", __func__);
+ 		return;
+ 	}
+ 
+@@ -447,7 +444,7 @@ static void ir_read_bulk_callback (struct urb *urb)
+ 			usb_serial_debug_data (
+ 				debug,
+ 				&port->dev,
+-				__FUNCTION__,
++				__func__,
+ 				urb->actual_length,
+ 				data);
+ 
+@@ -480,13 +477,13 @@ static void ir_read_bulk_callback (struct urb *urb)
+ 			result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 			if (result)
+ 				dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+-					__FUNCTION__, result);
++					__func__, result);
+ 
+ 			break ;
+ 
+ 		default:
+ 			dbg("%s - nonzero read bulk status received: %d",
+-				__FUNCTION__, 
++				__func__,
+ 				status);
+ 			break ;
+ 
+@@ -502,7 +499,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
+ 	speed_t baud;
+ 	int ir_baud;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	baud = tty_get_baud_rate(port->tty);
+ 
+@@ -554,7 +551,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
+ 
+ 	result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ 	if (result)
+-		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ 
+ 	/* Only speed changes are supported */
+ 	tty_termios_copy_hw(port->tty->termios, old_termios);
+diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
+index fde188e..8a21764 100644
+--- a/drivers/usb/serial/iuu_phoenix.c
++++ b/drivers/usb/serial/iuu_phoenix.c
+@@ -98,10 +98,10 @@ static int iuu_alloc_buf(struct iuu_private *priv)
+ 	priv->writebuf = kzalloc(256, GFP_KERNEL);
+ 	if (!priv->buf || !priv->dbgbuf || !priv->writebuf) {
+ 		iuu_free_buf(priv);
+-		dbg("%s problem allocation buffer", __FUNCTION__);
++		dbg("%s problem allocation buffer", __func__);
+ 		return -ENOMEM;
+ 	}
+-	dbg("%s - Privates buffers allocation success", __FUNCTION__);
++	dbg("%s - Privates buffers allocation success", __func__);
+ 	return 0;
+ }
+ 
+@@ -109,7 +109,7 @@ static int iuu_startup(struct usb_serial *serial)
+ {
+ 	struct iuu_private *priv;
+ 	priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
+-	dbg("%s- priv allocation success", __FUNCTION__);
++	dbg("%s- priv allocation success", __func__);
+ 	if (!priv)
+ 		return -ENOMEM;
+ 	if (iuu_alloc_buf(priv)) {
+@@ -130,17 +130,17 @@ static void iuu_shutdown(struct usb_serial *serial)
+ 	if (!port)
+ 		return;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (priv) {
+ 		iuu_free_buf(priv);
+-		dbg("%s - I will free all", __FUNCTION__);
++		dbg("%s - I will free all", __func__);
+ 		usb_set_serial_port_data(port, NULL);
+ 
+-		dbg("%s - priv is not anymore in port structure", __FUNCTION__);
++		dbg("%s - priv is not anymore in port structure", __func__);
+ 		kfree(priv);
+ 
+-		dbg("%s priv is now kfree", __FUNCTION__);
++		dbg("%s priv is now kfree", __func__);
+ 	}
+ }
+ 
+@@ -148,20 +148,21 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+ 			unsigned int set, unsigned int clear)
+ {
+ 	struct iuu_private *priv = usb_get_serial_port_data(port);
+-	struct tty_struct *tty;
+-	tty = port->tty;
++	unsigned long flags;
+ 
+-	dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __FUNCTION__,
++	/* FIXME: locking on tiomstatus */
++	dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __func__,
+ 	    port->number, set, clear);
++
++	spin_lock_irqsave(&priv->lock, flags);
+ 	if (set & TIOCM_RTS)
+ 		priv->tiostatus = TIOCM_RTS;
+ 
+ 	if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) {
+-		dbg("%s TIOCMSET RESET called !!!", __FUNCTION__);
++		dbg("%s TIOCMSET RESET called !!!", __func__);
+ 		priv->reset = 1;
+-		return 0;
+ 	}
+-
++	spin_unlock_irqrestore(&priv->lock, flags);
+ 	return 0;
+ }
+ 
+@@ -173,17 +174,24 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+ static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
+ {
+ 	struct iuu_private *priv = usb_get_serial_port_data(port);
+-	return priv->tiostatus;
++	unsigned long flags;
++	int rc;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	rc = priv->tiostatus;
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	return rc;
+ }
+ 
+ static void iuu_rxcmd(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int result;
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	if (urb->status) {
+-		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++		dbg("%s - urb->status = %d", __func__, urb->status);
+ 		/* error stop all */
+ 		return;
+ 	}
+@@ -203,7 +211,7 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt)
+ 	struct iuu_private *priv = usb_get_serial_port_data(port);
+ 	int result;
+ 	char *buf_ptr = port->write_urb->transfer_buffer;
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	/* Prepare the reset sequence */
+ 
+@@ -232,19 +240,19 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt)
+  */
+ static void iuu_update_status_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct iuu_private *priv = usb_get_serial_port_data(port);
+ 	u8 *st;
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	if (urb->status) {
+-		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++		dbg("%s - urb->status = %d", __func__, urb->status);
+ 		/* error stop all */
+ 		return;
+ 	}
+ 
+ 	st = urb->transfer_buffer;
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 	if (urb->actual_length == 1) {
+ 		switch (st[0]) {
+ 		case 0x1:
+@@ -262,11 +270,11 @@ static void iuu_update_status_callback(struct urb *urb)
+ 
+ static void iuu_status_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int result;
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+-	dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++	dbg("%s - urb->status = %d", __func__, urb->status);
+ 	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ 			  usb_rcvbulkpipe(port->serial->dev,
+ 					  port->bulk_in_endpointAddress),
+@@ -279,7 +287,7 @@ static int iuu_status(struct usb_serial_port *port)
+ {
+ 	int result;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1);
+ 	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+@@ -298,7 +306,7 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+ 	struct usb_serial *serial = port->serial;
+ 	int actual = 0;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	/* send the data out the bulk port */
+ 
+@@ -309,9 +317,9 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+ 			 count, &actual, HZ * 1);
+ 
+ 	if (status != IUU_OPERATION_OK) {
+-		dbg("%s - error = %2x", __FUNCTION__, status);
++		dbg("%s - error = %2x", __func__, status);
+ 	} else {
+-		dbg("%s - write OK !", __FUNCTION__);
++		dbg("%s - write OK !", __func__);
+ 	}
+ 	return status;
+ }
+@@ -322,7 +330,7 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+ 	struct usb_serial *serial = port->serial;
+ 	int actual = 0;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	/* send the data out the bulk port */
+ 
+@@ -333,9 +341,9 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+ 			 count, &actual, HZ * 1);
+ 
+ 	if (status != IUU_OPERATION_OK) {
+-		dbg("%s - error = %2x", __FUNCTION__, status);
++		dbg("%s - error = %2x", __func__, status);
+ 	} else {
+-		dbg("%s - read OK !", __FUNCTION__);
++		dbg("%s - read OK !", __func__);
+ 	}
+ 
+ 	return status;
+@@ -350,7 +358,7 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
+ 	if (!buf)
+ 		return -ENOMEM;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	buf[0] = IUU_SET_LED;
+ 	buf[1] = R & 0xFF;
+@@ -363,9 +371,9 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
+ 	status = bulk_immediate(port, buf, 8);
+ 	kfree(buf);
+ 	if (status != IUU_OPERATION_OK)
+-		dbg("%s - led error status = %2x", __FUNCTION__, status);
++		dbg("%s - led error status = %2x", __func__, status);
+ 	else
+-		dbg("%s - led OK !", __FUNCTION__);
++		dbg("%s - led OK !", __func__);
+ 	return IUU_OPERATION_OK;
+ }
+ 
+@@ -384,7 +392,7 @@ static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1,
+ 
+ static void iuu_led_activity_on(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int result;
+ 	char *buf_ptr = port->write_urb->transfer_buffer;
+ 	*buf_ptr++ = IUU_SET_LED;
+@@ -405,7 +413,7 @@ static void iuu_led_activity_on(struct urb *urb)
+ 
+ static void iuu_led_activity_off(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int result;
+ 	char *buf_ptr = port->write_urb->transfer_buffer;
+ 	if (xmas == 1) {
+@@ -443,7 +451,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
+ 	unsigned int P2 = 0;
+ 	int frq = (int)dwFrq;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	if (frq == 0) {
+ 		priv->buf[Count++] = IUU_UART_WRITE_I2C;
+@@ -453,7 +461,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
+ 
+ 		status = bulk_immediate(port, (u8 *) priv->buf, Count);
+ 		if (status != 0) {
+-			dbg("%s - write error ", __FUNCTION__);
++			dbg("%s - write error ", __func__);
+ 			return status;
+ 		}
+ 	} else if (frq == 3579000) {
+@@ -562,7 +570,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
+ 
+ 	status = bulk_immediate(port, (u8 *) priv->buf, Count);
+ 	if (status != IUU_OPERATION_OK)
+-		dbg("%s - write error ", __FUNCTION__);
++		dbg("%s - write error ", __func__);
+ 	return status;
+ }
+ 
+@@ -573,7 +581,7 @@ static int iuu_uart_flush(struct usb_serial_port *port)
+ 	u8 rxcmd = IUU_UART_RX;
+ 	struct iuu_private *priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
+ 		return -EIO;
+@@ -581,50 +589,50 @@ static int iuu_uart_flush(struct usb_serial_port *port)
+ 	for (i = 0; i < 2; i++) {
+ 		status = bulk_immediate(port, &rxcmd, 1);
+ 		if (status != IUU_OPERATION_OK) {
+-			dbg("%s - uart_flush_write error", __FUNCTION__);
++			dbg("%s - uart_flush_write error", __func__);
+ 			return status;
+ 		}
+ 
+ 		status = read_immediate(port, &priv->len, 1);
+ 		if (status != IUU_OPERATION_OK) {
+-			dbg("%s - uart_flush_read error", __FUNCTION__);
++			dbg("%s - uart_flush_read error", __func__);
+ 			return status;
+ 		}
+ 
+ 		if (priv->len > 0) {
+-			dbg("%s - uart_flush datalen is : %i ", __FUNCTION__,
++			dbg("%s - uart_flush datalen is : %i ", __func__,
+ 			    priv->len);
+ 			status = read_immediate(port, priv->buf, priv->len);
+ 			if (status != IUU_OPERATION_OK) {
+-				dbg("%s - uart_flush_read error", __FUNCTION__);
++				dbg("%s - uart_flush_read error", __func__);
+ 				return status;
+ 			}
+ 		}
+ 	}
+-	dbg("%s - uart_flush_read OK!", __FUNCTION__);
++	dbg("%s - uart_flush_read OK!", __func__);
+ 	iuu_led(port, 0, 0xF000, 0, 0xFF);
+ 	return status;
+ }
+ 
+ static void read_buf_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	struct tty_struct *tty;
+-	dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++	dbg("%s - urb->status = %d", __func__, urb->status);
+ 
+ 	if (urb->status) {
+-		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++		dbg("%s - urb->status = %d", __func__, urb->status);
+ 		if (urb->status == -EPROTO) {
+ 			/* reschedule needed */
+ 		}
+ 		return;
+ 	}
+ 
+-	dbg("%s - %i chars to write", __FUNCTION__, urb->actual_length);
++	dbg("%s - %i chars to write", __func__, urb->actual_length);
+ 	tty = port->tty;
+ 	if (data == NULL)
+-		dbg("%s - data is NULL !!!", __FUNCTION__);
++		dbg("%s - data is NULL !!!", __func__);
+ 	if (tty && urb->actual_length && data) {
+ 		tty_insert_flip_string(tty, data, urb->actual_length);
+ 		tty_flip_buffer_push(tty);
+@@ -639,7 +647,7 @@ static int iuu_bulk_write(struct usb_serial_port *port)
+ 	int result;
+ 	int i;
+ 	char *buf_ptr = port->write_urb->transfer_buffer;
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	*buf_ptr++ = IUU_UART_ESC;
+ 	*buf_ptr++ = IUU_UART_TX;
+@@ -652,7 +660,7 @@ static int iuu_bulk_write(struct usb_serial_port *port)
+ 			sprintf(priv->dbgbuf + i*2 ,
+ 				"%02X", priv->writebuf[i]);
+ 		priv->dbgbuf[priv->writelen+i*2] = 0;
+-		dbg("%s - writing %i chars : %s", __FUNCTION__,
++		dbg("%s - writing %i chars : %s", __func__,
+ 		    priv->writelen, priv->dbgbuf);
+ 	}
+ 	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+@@ -671,7 +679,7 @@ static int iuu_bulk_write(struct usb_serial_port *port)
+ static int iuu_read_buf(struct usb_serial_port *port, int len)
+ {
+ 	int result;
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ 			  usb_rcvbulkpipe(port->serial->dev,
+@@ -684,7 +692,7 @@ static int iuu_read_buf(struct usb_serial_port *port, int len)
+ 
+ static void iuu_uart_read_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct iuu_private *priv = usb_get_serial_port_data(port);
+ 	unsigned int flags;
+ 	int status;
+@@ -693,21 +701,21 @@ static void iuu_uart_read_callback(struct urb *urb)
+ 	unsigned char *data = urb->transfer_buffer;
+ 	priv->poll++;
+ 
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	if (urb->status) {
+-		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++		dbg("%s - urb->status = %d", __func__, urb->status);
+ 		/* error stop all */
+ 		return;
+ 	}
+ 	if (data == NULL)
+-		dbg("%s - data is NULL !!!", __FUNCTION__);
++		dbg("%s - data is NULL !!!", __func__);
+ 
+ 	if (urb->actual_length == 1  && data != NULL)
+ 		len = (int) data[0];
+ 
+ 	if (urb->actual_length > 1) {
+-		dbg("%s - urb->actual_length = %i", __FUNCTION__,
++		dbg("%s - urb->actual_length = %i", __func__,
+ 		    urb->actual_length);
+ 		error = 1;
+ 		return;
+@@ -716,7 +724,7 @@ static void iuu_uart_read_callback(struct urb *urb)
+ 
+ 	if (len > 0 && error == 0) {
+ 		dbg("%s - call read buf - len to read is %i ",
+-			__FUNCTION__, len);
++			__func__, len);
+ 		status = iuu_read_buf(port, len);
+ 		return;
+ 	}
+@@ -742,7 +750,7 @@ static void iuu_uart_read_callback(struct urb *urb)
+ 	}
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 	/* if nothing to write call again rxcmd */
+-	dbg("%s - rxcmd recall", __FUNCTION__);
++	dbg("%s - rxcmd recall", __func__);
+ 	iuu_led_activity_off(urb);
+ 	return;
+ }
+@@ -752,7 +760,7 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
+ {
+ 	struct iuu_private *priv = usb_get_serial_port_data(port);
+ 	unsigned int flags;
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+ 	if (count > 256)
+ 		return -ENOMEM;
+@@ -773,14 +781,14 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
+ 
+ static void read_rxcmd_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int result;
+-	dbg("%s - enter", __FUNCTION__);
++	dbg("%s - enter", __func__);
+ 
+-	dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++	dbg("%s - urb->status = %d", __func__, urb->status);
+ 
+ 	if (urb->status) {
+-		dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++		dbg("%s - urb->status = %d", __func__, urb->status);
+ 		/* error stop all */
+ 		return;
+ 	}
+@@ -791,7 +799,7 @@ static void read_rxcmd_callback(struct urb *urb)
+ 			  port->read_urb->transfer_buffer, 256,
+ 			  iuu_uart_read_callback, port);
+ 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+-	dbg("%s - submit result = %d", __FUNCTION__, result);
++	dbg("%s - submit result = %d", __func__, result);
+ 	return;
+ }
+ 
+@@ -812,13 +820,13 @@ static int iuu_uart_on(struct usb_serial_port *port)
+ 
+ 	status = bulk_immediate(port, buf, 4);
+ 	if (status != IUU_OPERATION_OK) {
+-		dbg("%s - uart_on error", __FUNCTION__);
++		dbg("%s - uart_on error", __func__);
+ 		goto uart_enable_failed;
+ 	}
+ 	/*  iuu_reset() the card after iuu_uart_on() */
+ 	status = iuu_uart_flush(port);
+ 	if (status != IUU_OPERATION_OK)
+-		dbg("%s - uart_flush error", __FUNCTION__);
++		dbg("%s - uart_flush error", __func__);
+ uart_enable_failed:
+ 	kfree(buf);
+ 	return status;
+@@ -836,7 +844,7 @@ static int iuu_uart_off(struct usb_serial_port *port)
+ 
+ 	status = bulk_immediate(port, buf, 1);
+ 	if (status != IUU_OPERATION_OK)
+-		dbg("%s - uart_off error", __FUNCTION__);
++		dbg("%s - uart_off error", __func__);
+ 
+ 	kfree(buf);
+ 	return status;
+@@ -930,7 +938,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
+ 
+ 	status = bulk_immediate(port, dataout, DataCount);
+ 	if (status != IUU_OPERATION_OK)
+-		dbg("%s - uart_off error", __FUNCTION__);
++		dbg("%s - uart_off error", __func__);
+ 	kfree(dataout);
+ 	return status;
+ }
+@@ -952,7 +960,7 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
+ 	if (!serial)
+ 		return;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	iuu_uart_off(port);
+ 	if (serial->dev) {
+@@ -969,7 +977,7 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
+ 		}
+ 		/* free writebuf */
+ 		/* shutdown our urbs */
+-		dbg("%s - shutting down urbs", __FUNCTION__);
++		dbg("%s - shutting down urbs", __func__);
+ 		usb_kill_urb(port->write_urb);
+ 		usb_kill_urb(port->read_urb);
+ 		usb_kill_urb(port->interrupt_in_urb);
+@@ -990,7 +998,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
+ 	unsigned long flags;
+ 	struct iuu_private *priv = usb_get_serial_port_data(port);
+ 
+-	dbg("%s -  port %d", __FUNCTION__, port->number);
++	dbg("%s -  port %d", __func__, port->number);
+ 	usb_clear_halt(serial->dev, port->write_urb->pipe);
+ 	usb_clear_halt(serial->dev, port->read_urb->pipe);
+ 
+@@ -1127,7 +1135,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
+ 
+ 	iuu_uart_flush(port);
+ 
+-	dbg("%s - initialization done", __FUNCTION__);
++	dbg("%s - initialization done", __func__);
+ 
+ 	memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
+ 	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+@@ -1139,11 +1147,11 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
+ 
+ 	if (result) {
+ 		dev_err(&port->dev, "%s - failed submitting read urb,"
+-			" error %d\n", __FUNCTION__, result);
++			" error %d\n", __func__, result);
+ 		iuu_close(port, NULL);
+ 		return -EPROTO;
+ 	} else {
+-		dbg("%s - rxcmd OK", __FUNCTION__);
++		dbg("%s - rxcmd OK", __func__);
+ 	}
+ 	return result;
+ }
+@@ -1154,9 +1162,6 @@ static struct usb_serial_driver iuu_device = {
+ 		   .name = "iuu_phoenix",
+ 		   },
+ 	.id_table = id_table,
+-	.num_interrupt_in = NUM_DONT_CARE,
+-	.num_bulk_in = 1,
+-	.num_bulk_out = 1,
+ 	.num_ports = 1,
+ 	.open = iuu_open,
+ 	.close = iuu_close,
+diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
+index ea7bba6..3df8a66 100644
+--- a/drivers/usb/serial/keyspan.c
++++ b/drivers/usb/serial/keyspan.c
+@@ -244,13 +244,13 @@ module_exit(keyspan_exit);
+ 
+ static void keyspan_rx_throttle (struct usb_serial_port *port)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ }
+ 
+ 
+ static void keyspan_rx_unthrottle (struct usb_serial_port *port)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ }
+ 
+ 
+@@ -258,7 +258,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
+ {
+ 	struct keyspan_port_private 	*p_priv;
+ 
+- 	dbg("%s", __FUNCTION__);
++ 	dbg("%s", __func__);
+ 
+ 	p_priv = usb_get_serial_port_data(port);
+ 
+@@ -280,7 +280,7 @@ static void keyspan_set_termios (struct usb_serial_port *port,
+ 	unsigned int 			cflag;
+ 	struct tty_struct		*tty = port->tty;
+ 
+-	dbg("%s", __FUNCTION__); 
++	dbg("%s", __func__);
+ 
+ 	p_priv = usb_get_serial_port_data(port);
+ 	d_details = p_priv->device_details;
+@@ -377,7 +377,7 @@ static int keyspan_write(struct usb_serial_port *port,
+ 	}
+ 	
+ 	dbg("%s - for port %d (%d chars), flip=%d",
+-	    __FUNCTION__, port->number, count, p_priv->out_flip);
++	    __func__, port->number, count, p_priv->out_flip);
+ 
+ 	for (left = count; left > 0; left -= todo) {
+ 		todo = left;
+@@ -389,11 +389,11 @@ static int keyspan_write(struct usb_serial_port *port,
+ 		/* Check we have a valid urb/endpoint before we use it... */
+ 		if ((this_urb = p_priv->out_urbs[flip]) == NULL) {
+ 			/* no bulk out, so return 0 bytes written */
+-			dbg("%s - no output urb :(", __FUNCTION__);
++			dbg("%s - no output urb :(", __func__);
+ 			return count;
+ 		}
+ 
+-		dbg("%s - endpoint %d flip %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), flip);
++		dbg("%s - endpoint %d flip %d", __func__, usb_pipeendpoint(this_urb->pipe), flip);
+ 
+ 		if (this_urb->status == -EINPROGRESS) {
+ 			if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
+@@ -435,17 +435,17 @@ static void	usa26_indat_callback(struct urb *urb)
+ 	unsigned char 		*data = urb->transfer_buffer;
+ 	int status = urb->status;
+ 
+-	dbg ("%s", __FUNCTION__); 
++	dbg ("%s", __func__);
+ 
+ 	endpoint = usb_pipeendpoint(urb->pipe);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero status: %x on endpoint %d.",
+-		    __FUNCTION__, status, endpoint);
++		    __func__, status, endpoint);
+ 		return;
+ 	}
+ 
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 	tty = port->tty;
+ 	if (tty && urb->actual_length) {
+ 		/* 0x80 bit is error flag */
+@@ -459,7 +459,7 @@ static void	usa26_indat_callback(struct urb *urb)
+ 			}
+ 		} else {
+ 			/* some bytes had errors, every byte has status */
+-			dbg("%s - RX error!!!!", __FUNCTION__);
++			dbg("%s - RX error!!!!", __func__);
+ 			for (i = 0; i + 1 < urb->actual_length; i += 2) {
+ 				int stat = data[i], flag = 0;
+ 				if (stat & RXERROR_OVERRUN)
+@@ -479,7 +479,7 @@ static void	usa26_indat_callback(struct urb *urb)
+ 	urb->dev = port->serial->dev;
+ 	if (port->open_count)
+ 		if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+-			dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++			dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ 		}
+ 	return;
+ }
+@@ -490,9 +490,9 @@ static void	usa2x_outdat_callback(struct urb *urb)
+ 	struct usb_serial_port *port;
+ 	struct keyspan_port_private *p_priv;
+ 
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 	p_priv = usb_get_serial_port_data(port);
+-	dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); 
++	dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
+ 
+ 	if (port->open_count)
+ 		usb_serial_port_softint(port);
+@@ -500,7 +500,7 @@ static void	usa2x_outdat_callback(struct urb *urb)
+ 
+ static void	usa26_inack_callback(struct urb *urb)
+ {
+-	dbg ("%s", __FUNCTION__); 
++	dbg ("%s", __func__);
+ 	
+ }
+ 
+@@ -509,11 +509,11 @@ static void	usa26_outcont_callback(struct urb *urb)
+ 	struct usb_serial_port *port;
+ 	struct keyspan_port_private *p_priv;
+ 
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 	p_priv = usb_get_serial_port_data(port);
+ 
+ 	if (p_priv->resend_cont) {
+-		dbg ("%s - sending setup", __FUNCTION__); 
++		dbg ("%s - sending setup", __func__);
+ 		keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ 	}
+ }
+@@ -528,14 +528,14 @@ static void	usa26_instat_callback(struct urb *urb)
+ 	int old_dcd_state, err;
+ 	int status = urb->status;
+ 
+-	serial = (struct usb_serial *) urb->context;
++	serial =  urb->context;
+ 
+ 	if (status) {
+-		dbg("%s - nonzero status: %x", __FUNCTION__, status);
++		dbg("%s - nonzero status: %x", __func__, status);
+ 		return;
+ 	}
+ 	if (urb->actual_length != 9) {
+-		dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length);
++		dbg("%s - %d byte report??", __func__, urb->actual_length);
+ 		goto exit;
+ 	}
+ 
+@@ -543,7 +543,7 @@ static void	usa26_instat_callback(struct urb *urb)
+ 
+ #if 0
+ 	dbg("%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
+-	    __FUNCTION__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
++	    __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
+ 	    msg->_txXoff, msg->rxEnabled, msg->controlResponse);
+ #endif
+ 
+@@ -552,7 +552,7 @@ static void	usa26_instat_callback(struct urb *urb)
+ 
+ 	/* Check port number from message and retrieve private data */	
+ 	if (msg->port >= serial->num_ports) {
+-		dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
++		dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ 		goto exit;
+ 	}
+ 	port = serial->port[msg->port];
+@@ -576,14 +576,14 @@ static void	usa26_instat_callback(struct urb *urb)
+ 	/* Resubmit urb so we continue receiving */
+ 	urb->dev = serial->dev;
+ 	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+-		dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ 	}
+ exit: ;
+ }
+ 
+ static void	usa26_glocont_callback(struct urb *urb)
+ {
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 	
+ }
+ 
+@@ -597,9 +597,9 @@ static void usa28_indat_callback(struct urb *urb)
+ 	struct keyspan_port_private             *p_priv;
+ 	int status = urb->status;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 	p_priv = usb_get_serial_port_data(port);
+ 	data = urb->transfer_buffer;
+ 
+@@ -609,11 +609,11 @@ static void usa28_indat_callback(struct urb *urb)
+ 	do {
+ 		if (status) {
+ 			dbg("%s - nonzero status: %x on endpoint %d.",
+-			    __FUNCTION__, status, usb_pipeendpoint(urb->pipe));
++			    __func__, status, usb_pipeendpoint(urb->pipe));
+ 			return;
+ 		}
+ 
+-		port = (struct usb_serial_port *) urb->context;
++		port =  urb->context;
+ 		p_priv = usb_get_serial_port_data(port);
+ 		data = urb->transfer_buffer;
+ 
+@@ -629,7 +629,7 @@ static void usa28_indat_callback(struct urb *urb)
+ 		urb->dev = port->serial->dev;
+ 		if (port->open_count)
+ 			if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+-				dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++				dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ 			}
+ 		p_priv->in_flip ^= 1;
+ 
+@@ -639,7 +639,7 @@ static void usa28_indat_callback(struct urb *urb)
+ 
+ static void	usa28_inack_callback(struct urb *urb)
+ {
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ }
+ 
+ static void	usa28_outcont_callback(struct urb *urb)
+@@ -647,11 +647,11 @@ static void	usa28_outcont_callback(struct urb *urb)
+ 	struct usb_serial_port *port;
+ 	struct keyspan_port_private *p_priv;
+ 
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 	p_priv = usb_get_serial_port_data(port);
+ 
+ 	if (p_priv->resend_cont) {
+-		dbg ("%s - sending setup", __FUNCTION__);
++		dbg ("%s - sending setup", __func__);
+ 		keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ 	}
+ }
+@@ -667,19 +667,19 @@ static void	usa28_instat_callback(struct urb *urb)
+ 	int old_dcd_state;
+ 	int status = urb->status;
+ 
+-	serial = (struct usb_serial *) urb->context;
++	serial =  urb->context;
+ 
+ 	if (status) {
+-		dbg("%s - nonzero status: %x", __FUNCTION__, status);
++		dbg("%s - nonzero status: %x", __func__, status);
+ 		return;
+ 	}
+ 
+ 	if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
+-		dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
++		dbg("%s - bad length %d", __func__, urb->actual_length);
+ 		goto exit;
+ 	}
+ 
+-	/*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __FUNCTION__
++	/*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
+ 	    data[0], data[1], data[2], data[3], data[4], data[5],
+ 	    data[6], data[7], data[8], data[9], data[10], data[11]);*/
+ 	
+@@ -689,7 +689,7 @@ static void	usa28_instat_callback(struct urb *urb)
+ 
+ 		/* Check port number from message and retrieve private data */	
+ 	if (msg->port >= serial->num_ports) {
+-		dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
++		dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ 		goto exit;
+ 	}
+ 	port = serial->port[msg->port];
+@@ -713,14 +713,14 @@ static void	usa28_instat_callback(struct urb *urb)
+ 		/* Resubmit urb so we continue receiving */
+ 	urb->dev = serial->dev;
+ 	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+-		dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ 	}
+ exit: ;
+ }
+ 
+ static void	usa28_glocont_callback(struct urb *urb)
+ {
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ }
+ 
+ 
+@@ -731,15 +731,15 @@ static void	usa49_glocont_callback(struct urb *urb)
+ 	struct keyspan_port_private *p_priv;
+ 	int i;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+-	serial = (struct usb_serial *) urb->context;
++	serial =  urb->context;
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		port = serial->port[i];
+ 		p_priv = usb_get_serial_port_data(port);
+ 
+ 		if (p_priv->resend_cont) {
+-			dbg ("%s - sending setup", __FUNCTION__); 
++			dbg ("%s - sending setup", __func__);
+ 			keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1);
+ 			break;
+ 		}
+@@ -759,21 +759,21 @@ static void	usa49_instat_callback(struct urb *urb)
+ 	int old_dcd_state;
+ 	int status = urb->status;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+-	serial = (struct usb_serial *) urb->context;
++	serial =  urb->context;
+ 
+ 	if (status) {
+-		dbg("%s - nonzero status: %x", __FUNCTION__, status);
++		dbg("%s - nonzero status: %x", __func__, status);
+ 		return;
+ 	}
+ 
+ 	if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {
+-		dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
++		dbg("%s - bad length %d", __func__, urb->actual_length);
+ 		goto exit;
+ 	}
+ 
+-	/*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __FUNCTION__, 
++	/*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
+ 	    data[0], data[1], data[2], data[3], data[4], data[5],
+ 	    data[6], data[7], data[8], data[9], data[10]);*/
+ 	
+@@ -782,7 +782,7 @@ static void	usa49_instat_callback(struct urb *urb)
+ 
+ 		/* Check port number from message and retrieve private data */	
+ 	if (msg->portNumber >= serial->num_ports) {
+-		dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->portNumber);
++		dbg ("%s - Unexpected port number %d", __func__, msg->portNumber);
+ 		goto exit;
+ 	}
+ 	port = serial->port[msg->portNumber];
+@@ -807,14 +807,14 @@ static void	usa49_instat_callback(struct urb *urb)
+ 	urb->dev = serial->dev;
+ 
+ 	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+-		dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ 	}
+ exit:	;
+ }
+ 
+ static void	usa49_inack_callback(struct urb *urb)
+ {
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ }
+ 
+ static void	usa49_indat_callback(struct urb *urb)
+@@ -826,17 +826,17 @@ static void	usa49_indat_callback(struct urb *urb)
+ 	unsigned char 		*data = urb->transfer_buffer;
+ 	int status = urb->status;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	endpoint = usb_pipeendpoint(urb->pipe);
+ 
+ 	if (status) {
+-		dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__,
++		dbg("%s - nonzero status: %x on endpoint %d.", __func__,
+ 		    status, endpoint);
+ 		return;
+ 	}
+ 
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 	tty = port->tty;
+ 	if (tty && urb->actual_length) {
+ 		/* 0x80 bit is error flag */
+@@ -866,7 +866,7 @@ static void	usa49_indat_callback(struct urb *urb)
+ 	urb->dev = port->serial->dev;
+ 	if (port->open_count)
+ 		if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+-			dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++			dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ 		}
+ }
+ 
+@@ -879,12 +879,12 @@ static void usa49wg_indat_callback(struct urb *urb)
+ 	unsigned char 		*data = urb->transfer_buffer;
+ 	int status = urb->status;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	serial = urb->context;
+ 
+ 	if (status) {
+-		dbg("%s - nonzero status: %x", __FUNCTION__, status);
++		dbg("%s - nonzero status: %x", __func__, status);
+ 		return;
+ 	}
+ 
+@@ -898,7 +898,7 @@ static void usa49wg_indat_callback(struct urb *urb)
+ 			/* Check port number from message*/
+ 			if (data[i] >= serial->num_ports) {
+ 				dbg ("%s - Unexpected port number %d",
+-					__FUNCTION__, data[i]);
++					__func__, data[i]);
+ 				return;
+ 			}
+ 			port = serial->port[data[i++]];
+@@ -944,13 +944,13 @@ static void usa49wg_indat_callback(struct urb *urb)
+ 
+ 	err = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if (err != 0)
+-		dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ 
+ /* not used, usa-49 doesn't have per-port control endpoints */
+ static void usa49_outcont_callback(struct urb *urb)
+ {
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ }
+ 
+ static void usa90_indat_callback(struct urb *urb)
+@@ -963,17 +963,17 @@ static void usa90_indat_callback(struct urb *urb)
+ 	unsigned char 		*data = urb->transfer_buffer;
+ 	int status = urb->status;
+ 
+-	dbg ("%s", __FUNCTION__); 
++	dbg ("%s", __func__);
+ 
+ 	endpoint = usb_pipeendpoint(urb->pipe);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero status: %x on endpoint %d.",
+-		    __FUNCTION__, status, endpoint);
++		    __func__, status, endpoint);
+ 		return;
+ 	}
+ 
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 	p_priv = usb_get_serial_port_data(port);
+ 
+ 	tty = port->tty;
+@@ -1000,7 +1000,7 @@ static void usa90_indat_callback(struct urb *urb)
+ 			} 
+ 			else {
+ 			/* some bytes had errors, every byte has status */
+-				dbg("%s - RX error!!!!", __FUNCTION__);
++				dbg("%s - RX error!!!!", __func__);
+ 				for (i = 0; i + 1 < urb->actual_length; i += 2) {
+ 					int stat = data[i], flag = 0;
+ 					if (stat & RXERROR_OVERRUN)
+@@ -1021,7 +1021,7 @@ static void usa90_indat_callback(struct urb *urb)
+ 	urb->dev = port->serial->dev;
+ 	if (port->open_count)
+ 		if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+-			dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++			dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ 		}
+ 	return;
+ }
+@@ -1037,14 +1037,14 @@ static void	usa90_instat_callback(struct urb *urb)
+ 	int old_dcd_state, err;
+ 	int status = urb->status;
+ 
+-	serial = (struct usb_serial *) urb->context;
++	serial =  urb->context;
+ 
+ 	if (status) {
+-		dbg("%s - nonzero status: %x", __FUNCTION__, status);
++		dbg("%s - nonzero status: %x", __func__, status);
+ 		return;
+ 	}
+ 	if (urb->actual_length < 14) {
+-		dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length);
++		dbg("%s - %d byte report??", __func__, urb->actual_length);
+ 		goto exit;
+ 	}
+ 
+@@ -1073,7 +1073,7 @@ static void	usa90_instat_callback(struct urb *urb)
+ 	/* Resubmit urb so we continue receiving */
+ 	urb->dev = serial->dev;
+ 	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+-		dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ 	}
+ exit:
+ 	;
+@@ -1084,11 +1084,11 @@ static void	usa90_outcont_callback(struct urb *urb)
+ 	struct usb_serial_port *port;
+ 	struct keyspan_port_private *p_priv;
+ 
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 	p_priv = usb_get_serial_port_data(port);
+ 
+ 	if (p_priv->resend_cont) {
+-		dbg ("%s - sending setup", __FUNCTION__); 
++		dbg ("%s - sending setup", __func__);
+ 		keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ 	}
+ }
+@@ -1105,17 +1105,17 @@ static void	usa67_instat_callback(struct urb *urb)
+ 	int old_dcd_state;
+ 	int status = urb->status;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	serial = urb->context;
+ 
+ 	if (status) {
+-		dbg("%s - nonzero status: %x", __FUNCTION__, status);
++		dbg("%s - nonzero status: %x", __func__, status);
+ 		return;
+ 	}
+ 
+ 	if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
+-		dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
++		dbg("%s - bad length %d", __func__, urb->actual_length);
+ 		return;
+ 	}
+ 
+@@ -1125,7 +1125,7 @@ static void	usa67_instat_callback(struct urb *urb)
+ 
+ 	/* Check port number from message and retrieve private data */
+ 	if (msg->port >= serial->num_ports) {
+-		dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
++		dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ 		return;
+ 	}
+ 
+@@ -1149,7 +1149,7 @@ static void	usa67_instat_callback(struct urb *urb)
+ 	urb->dev = serial->dev;
+ 	err = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if (err != 0)
+-		dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ 
+ static void usa67_glocont_callback(struct urb *urb)
+@@ -1159,7 +1159,7 @@ static void usa67_glocont_callback(struct urb *urb)
+ 	struct keyspan_port_private *p_priv;
+ 	int i;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	serial = urb->context;
+ 	for (i = 0; i < serial->num_ports; ++i) {
+@@ -1167,7 +1167,7 @@ static void usa67_glocont_callback(struct urb *urb)
+ 		p_priv = usb_get_serial_port_data(port);
+ 
+ 		if (p_priv->resend_cont) {
+-			dbg ("%s - sending setup", __FUNCTION__);
++			dbg ("%s - sending setup", __func__);
+ 			keyspan_usa67_send_setup(serial, port,
+ 						p_priv->resend_cont - 1);
+ 			break;
+@@ -1183,10 +1183,11 @@ static int keyspan_write_room (struct usb_serial_port *port)
+ 	int				data_len;
+ 	struct urb			*this_urb;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	p_priv = usb_get_serial_port_data(port);
+ 	d_details = p_priv->device_details;
+ 
++	/* FIXME: locking */
+ 	if (d_details->msg_format == msg_usa90)
+    		data_len = 64;
+ 	else
+@@ -1203,13 +1204,13 @@ static int keyspan_write_room (struct usb_serial_port *port)
+ 			if (this_urb->status != -EINPROGRESS)
+ 				return (data_len);
+ 	}
+-	return (0);
++	return 0;
+ }
+ 
+ 
+ static int keyspan_chars_in_buffer (struct usb_serial_port *port)
+ {
+-	return (0);
++	return 0;
+ }
+ 
+ 
+@@ -1228,7 +1229,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+ 	p_priv = usb_get_serial_port_data(port);
+ 	d_details = p_priv->device_details;
+ 
+-	dbg("%s - port%d.", __FUNCTION__, port->number);
++	dbg("%s - port%d.", __func__, port->number);
+ 
+ 	/* Set some sane defaults */
+ 	p_priv->rts_state = 1;
+@@ -1253,7 +1254,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+ 		usb_clear_halt(urb->dev, urb->pipe);
+ 
+ 		if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+-			dbg("%s - submit urb %d failed (%d)", __FUNCTION__, i, err);
++			dbg("%s - submit urb %d failed (%d)", __func__, i, err);
+ 		}
+ 	}
+ 
+@@ -1289,7 +1290,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+ 	//mdelay(100);
+ 	//keyspan_set_termios(port, NULL);
+ 
+-	return (0);
++	return 0;
+ }
+ 
+ static inline void stop_urb(struct urb *urb)
+@@ -1305,7 +1306,7 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
+ 	struct keyspan_serial_private 	*s_priv;
+ 	struct keyspan_port_private 	*p_priv;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	s_priv = usb_get_serial_data(serial);
+ 	p_priv = usb_get_serial_port_data(port);
+ 	
+@@ -1320,7 +1321,7 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
+ 	}
+ 
+ 	/*while (p_priv->outcont_urb->status == -EINPROGRESS) {
+-		dbg("%s - urb in progress", __FUNCTION__);
++		dbg("%s - urb in progress", __func__);
+ 	}*/
+ 
+ 	p_priv->out_flip = 0;
+@@ -1484,10 +1485,10 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
+ 	if (endpoint == -1)
+ 		return NULL;		/* endpoint not needed */
+ 
+-	dbg ("%s - alloc for endpoint %d.", __FUNCTION__, endpoint);
++	dbg ("%s - alloc for endpoint %d.", __func__, endpoint);
+ 	urb = usb_alloc_urb(0, GFP_KERNEL);		/* No ISO */
+ 	if (urb == NULL) {
+-		dbg ("%s - alloc for endpoint %d failed.", __FUNCTION__, endpoint);
++		dbg ("%s - alloc for endpoint %d failed.", __func__, endpoint);
+ 		return NULL;
+ 	}
+ 
+@@ -1588,7 +1589,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
+ 	struct callbacks		*cback;
+ 	int				endp;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	s_priv = usb_get_serial_data(serial);
+ 	d_details = s_priv->device_details;
+@@ -1662,7 +1663,7 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ 		div,	/* divisor */	
+ 		cnt;	/* inverse of divisor (programmed into 8051) */
+ 		
+-	dbg ("%s - %d.", __FUNCTION__, baud_rate);
++	dbg ("%s - %d.", __func__, baud_rate);
+ 
+ 		/* prevent divide by zero...  */
+ 	if( (b16 = (baud_rate * 16L)) == 0) {
+@@ -1695,7 +1696,7 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ 		*rate_hi = (u8) ((cnt >> 8) & 0xff);
+ 	}
+ 	if (rate_low && rate_hi) {
+-		dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, *rate_low);
++		dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
+ 	}
+ 	
+ 	return (KEYSPAN_BAUD_RATE_OK);
+@@ -1708,7 +1709,7 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ 	u32 	b16,	/* baud rate times 16 (actual rate used internally) */
+ 			div;	/* divisor */	
+ 		
+-	dbg ("%s - %d.", __FUNCTION__, baud_rate);
++	dbg ("%s - %d.", __func__, baud_rate);
+ 
+ 		/* prevent divide by zero...  */
+ 	if( (b16 = (baud_rate * 16L)) == 0) 
+@@ -1731,7 +1732,7 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ 		*rate_hi = (u8) ((div >> 8) & 0xff);
+ 	
+ 	if (rate_low && rate_hi) 
+-		dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, *rate_low);
++		dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
+ 	
+ 	return (KEYSPAN_BAUD_RATE_OK);
+ }
+@@ -1748,7 +1749,7 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ 	u8	best_prescaler;
+ 	int	i;
+ 
+-	dbg ("%s - %d.", __FUNCTION__, baud_rate);
++	dbg ("%s - %d.", __func__, baud_rate);
+ 
+ 		/* prevent divide by zero */
+ 	if( (b16 = baud_rate * 16L) == 0) {
+@@ -1796,7 +1797,7 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ 	}
+ 	if (prescaler) {
+ 		*prescaler = best_prescaler;
+-		/*  dbg("%s - %d %d", __FUNCTION__, *prescaler, div); */
++		/*  dbg("%s - %d %d", __func__, *prescaler, div); */
+ 	}
+ 	return (KEYSPAN_BAUD_RATE_OK);
+ }
+@@ -1809,7 +1810,7 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ 		div,	/* divisor */	
+ 		cnt;	/* inverse of divisor (programmed into 8051) */
+ 
+-	dbg ("%s - %d.", __FUNCTION__, baud_rate);
++	dbg ("%s - %d.", __func__, baud_rate);
+ 
+ 		/* prevent divide by zero */
+ 	if ((b16 = baud_rate * 16L) == 0)
+@@ -1848,7 +1849,7 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ 	if (rate_hi) {
+ 		*rate_hi = (u8) ((cnt >> 8) & 0xff);
+ 	}
+-	dbg ("%s - %d OK.", __FUNCTION__, baud_rate);
++	dbg ("%s - %d OK.", __func__, baud_rate);
+ 	return (KEYSPAN_BAUD_RATE_OK);
+ }
+ 
+@@ -1864,7 +1865,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ 	struct urb				*this_urb;
+ 	int 					device_port, err;
+ 
+-	dbg ("%s reset=%d", __FUNCTION__, reset_port); 
++	dbg ("%s reset=%d", __func__, reset_port);
+ 
+ 	s_priv = usb_get_serial_data(serial);
+ 	p_priv = usb_get_serial_port_data(port);
+@@ -1874,11 +1875,11 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ 	outcont_urb = d_details->outcont_endpoints[port->number];
+ 	this_urb = p_priv->outcont_urb;
+ 
+-	dbg("%s - endpoint %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe));
++	dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
+ 
+ 		/* Make sure we have an urb then send the message */
+ 	if (this_urb == NULL) {
+-		dbg("%s - oops no urb.", __FUNCTION__);
++		dbg("%s - oops no urb.", __func__);
+ 		return -1;
+ 	}
+ 
+@@ -1887,7 +1888,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ 	if ((reset_port + 1) > p_priv->resend_cont)
+ 		p_priv->resend_cont = reset_port + 1;
+ 	if (this_urb->status == -EINPROGRESS) {
+-		/*  dbg ("%s - already writing", __FUNCTION__); */
++		/*  dbg ("%s - already writing", __func__); */
+ 		mdelay(5);
+ 		return(-1);
+ 	}
+@@ -1901,7 +1902,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ 		if (d_details->calculate_baud_rate
+ 		    (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ 		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+-			dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
++			dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
+ 			    p_priv->baud);
+ 			msg.baudLo = 0;
+ 			msg.baudHi = 125;	/* Values for 9600 baud */
+@@ -1996,17 +1997,17 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ 
+ 	this_urb->dev = serial->dev;
+ 	if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+-		dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
++		dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
+ 	}
+ #if 0
+ 	else {
+-		dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__
++		dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
+ 		    outcont_urb, this_urb->transfer_buffer_length,
+ 		    usb_pipeendpoint(this_urb->pipe));
+ 	}
+ #endif
+ 
+-	return (0);
++	return 0;
+ }
+ 
+ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+@@ -2020,7 +2021,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+ 	struct urb				*this_urb;
+ 	int 					device_port, err;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	s_priv = usb_get_serial_data(serial);
+ 	p_priv = usb_get_serial_port_data(port);
+@@ -2029,7 +2030,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+ 
+ 	/* only do something if we have a bulk out endpoint */
+ 	if ((this_urb = p_priv->outcont_urb) == NULL) {
+-		dbg("%s - oops no urb.", __FUNCTION__);
++		dbg("%s - oops no urb.", __func__);
+ 		return -1;
+ 	}
+ 
+@@ -2038,7 +2039,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+ 	if ((reset_port + 1) > p_priv->resend_cont)
+ 		p_priv->resend_cont = reset_port + 1;
+ 	if (this_urb->status == -EINPROGRESS) {
+-		dbg ("%s already writing", __FUNCTION__);
++		dbg ("%s already writing", __func__);
+ 		mdelay(5);
+ 		return(-1);
+ 	}
+@@ -2048,7 +2049,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+ 	msg.setBaudRate = 1;
+ 	if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
+ 		&msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+-		dbg("%s - Invalid baud rate requested %d.", __FUNCTION__, p_priv->baud);
++		dbg("%s - Invalid baud rate requested %d.", __func__, p_priv->baud);
+ 		msg.baudLo = 0xff;
+ 		msg.baudHi = 0xb2;	/* Values for 9600 baud */
+ 	}
+@@ -2122,16 +2123,16 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+ 
+ 	this_urb->dev = serial->dev;
+ 	if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+-		dbg("%s - usb_submit_urb(setup) failed", __FUNCTION__);
++		dbg("%s - usb_submit_urb(setup) failed", __func__);
+ 	}
+ #if 0
+ 	else {
+-		dbg("%s - usb_submit_urb(setup) OK %d bytes", __FUNCTION__,
++		dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
+ 		    this_urb->transfer_buffer_length);
+ 	}
+ #endif
+ 
+-	return (0);
++	return 0;
+ }
+ 
+ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+@@ -2146,7 +2147,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ 	struct urb				*this_urb;
+ 	int 					err, device_port;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	s_priv = usb_get_serial_data(serial);
+ 	p_priv = usb_get_serial_port_data(port);
+@@ -2157,11 +2158,11 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ 	/* Work out which port within the device is being setup */
+ 	device_port = port->number - port->serial->minor;
+ 
+-	dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
++	dbg("%s - endpoint %d port %d (%d)",__func__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
+ 
+ 		/* Make sure we have an urb then send the message */
+ 	if (this_urb == NULL) {
+-		dbg("%s - oops no urb for port %d.", __FUNCTION__, port->number);
++		dbg("%s - oops no urb for port %d.", __func__, port->number);
+ 		return -1;
+ 	}
+ 
+@@ -2171,7 +2172,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ 		p_priv->resend_cont = reset_port + 1;
+ 
+ 	if (this_urb->status == -EINPROGRESS) {
+-		/*  dbg ("%s - already writing", __FUNCTION__); */
++		/*  dbg ("%s - already writing", __func__); */
+ 		mdelay(5);
+ 		return(-1);
+ 	}
+@@ -2188,7 +2189,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ 		if (d_details->calculate_baud_rate
+ 		    (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ 		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+-			dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
++			dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
+ 			    p_priv->baud);
+ 			msg.baudLo = 0;
+ 			msg.baudHi = 125;	/* Values for 9600 baud */
+@@ -2307,17 +2308,17 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ 		this_urb->dev = serial->dev;
+ 	}
+ 	if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+-		dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
++		dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
+ 	}
+ #if 0
+ 	else {
+-		dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__,
++		dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
+ 			   outcont_urb, this_urb->transfer_buffer_length,
+ 			   usb_pipeendpoint(this_urb->pipe));
+ 	}
+ #endif
+ 
+-	return (0);
++	return 0;
+ }
+ 
+ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+@@ -2332,7 +2333,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+ 	int 					err;
+ 	u8						prescaler;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	s_priv = usb_get_serial_data(serial);
+ 	p_priv = usb_get_serial_port_data(port);
+@@ -2340,7 +2341,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+ 
+ 	/* only do something if we have a bulk out endpoint */
+ 	if ((this_urb = p_priv->outcont_urb) == NULL) {
+-		dbg("%s - oops no urb.", __FUNCTION__);
++		dbg("%s - oops no urb.", __func__);
+ 		return -1;
+ 	}
+ 
+@@ -2349,7 +2350,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+ 	if ((reset_port + 1) > p_priv->resend_cont)
+ 		p_priv->resend_cont = reset_port + 1;
+ 	if (this_urb->status == -EINPROGRESS) {
+-		dbg ("%s already writing", __FUNCTION__);
++		dbg ("%s already writing", __func__);
+ 		mdelay(5);
+ 		return(-1);
+ 	}
+@@ -2363,7 +2364,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+ 		if (d_details->calculate_baud_rate
+ 		    (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ 		     &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
+-			dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
++			dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
+ 			    p_priv->baud);
+ 			p_priv->baud = 9600;
+ 			d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk, 
+@@ -2453,9 +2454,9 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+ 
+ 	this_urb->dev = serial->dev;
+ 	if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+-		dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
++		dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
+ 	}
+-	return (0);
++	return 0;
+ }
+ 
+ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+@@ -2469,7 +2470,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+ 	struct urb				*this_urb;
+ 	int 					err, device_port;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	s_priv = usb_get_serial_data(serial);
+ 	p_priv = usb_get_serial_port_data(port);
+@@ -2482,7 +2483,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+ 
+ 	/* Make sure we have an urb then send the message */
+ 	if (this_urb == NULL) {
+-		dbg("%s - oops no urb for port %d.", __FUNCTION__,
++		dbg("%s - oops no urb for port %d.", __func__,
+ 			port->number);
+ 		return -1;
+ 	}
+@@ -2492,7 +2493,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+ 	if ((reset_port + 1) > p_priv->resend_cont)
+ 		p_priv->resend_cont = reset_port + 1;
+ 	if (this_urb->status == -EINPROGRESS) {
+-		/*  dbg ("%s - already writing", __FUNCTION__); */
++		/*  dbg ("%s - already writing", __func__); */
+ 		mdelay(5);
+ 		return(-1);
+ 	}
+@@ -2508,7 +2509,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+ 		if (d_details->calculate_baud_rate
+ 		    (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ 		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+-			dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
++			dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
+ 			    p_priv->baud);
+ 			msg.baudLo = 0;
+ 			msg.baudHi = 125;	/* Values for 9600 baud */
+@@ -2601,9 +2602,9 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+ 
+ 	err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ 	if (err != 0)
+-		dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__,
++		dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
+ 				err);
+-	return (0);
++	return 0;
+ }
+ 
+ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
+@@ -2612,7 +2613,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
+ 	struct keyspan_serial_private *s_priv;
+ 	const struct keyspan_device_details *d_details;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	s_priv = usb_get_serial_data(serial);
+ 	d_details = s_priv->device_details;
+@@ -2647,20 +2648,20 @@ static int keyspan_startup (struct usb_serial *serial)
+ 	struct keyspan_port_private	*p_priv;
+ 	const struct keyspan_device_details	*d_details;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
+ 		if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
+ 			break;
+ 	if (d_details == NULL) {
+-		dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __FUNCTION__, le16_to_cpu(serial->dev->descriptor.idProduct));
++		dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
+ 		return 1;
+ 	}
+ 
+ 	/* Setup private data for serial driver */
+ 	s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
+ 	if (!s_priv) {
+-		dbg("%s - kmalloc for keyspan_serial_private failed.", __FUNCTION__);
++		dbg("%s - kmalloc for keyspan_serial_private failed.", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -2672,7 +2673,7 @@ static int keyspan_startup (struct usb_serial *serial)
+ 		port = serial->port[i];
+ 		p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
+ 		if (!p_priv) {
+-			dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __FUNCTION__, i);
++			dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
+ 			return (1);
+ 		}
+ 		p_priv->device_details = d_details;
+@@ -2685,18 +2686,18 @@ static int keyspan_startup (struct usb_serial *serial)
+ 		s_priv->instat_urb->dev = serial->dev;
+ 		err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
+ 		if (err != 0)
+-			dbg("%s - submit instat urb failed %d", __FUNCTION__,
++			dbg("%s - submit instat urb failed %d", __func__,
+ 				err);
+ 	}
+ 	if (s_priv->indat_urb != NULL) {
+ 		s_priv->indat_urb->dev = serial->dev;
+ 		err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
+ 		if (err != 0)
+-			dbg("%s - submit indat urb failed %d", __FUNCTION__,
++			dbg("%s - submit indat urb failed %d", __func__,
+ 				err);
+ 	}
+ 			
+-	return (0);
++	return 0;
+ }
+ 
+ static void keyspan_shutdown (struct usb_serial *serial)
+@@ -2706,7 +2707,7 @@ static void keyspan_shutdown (struct usb_serial *serial)
+ 	struct keyspan_serial_private 	*s_priv;
+ 	struct keyspan_port_private	*p_priv;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	s_priv = usb_get_serial_data(serial);
+ 
+diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
+index 74ce8bc..8d6ed02 100644
+--- a/drivers/usb/serial/keyspan.h
++++ b/drivers/usb/serial/keyspan.h
+@@ -636,10 +636,6 @@ static struct usb_serial_driver keyspan_pre_device = {
+ 	},
+ 	.description		= "Keyspan - (without firmware)",
+ 	.id_table		= keyspan_pre_ids,
+-	.num_interrupt_in	= NUM_DONT_CARE,
+-	.num_interrupt_out	= NUM_DONT_CARE,
+-	.num_bulk_in		= NUM_DONT_CARE,
+-	.num_bulk_out		= NUM_DONT_CARE,
+ 	.num_ports		= 1,
+ 	.attach			= keyspan_fake_startup,
+ };
+@@ -651,10 +647,6 @@ static struct usb_serial_driver keyspan_1port_device = {
+ 	},
+ 	.description		= "Keyspan 1 port adapter",
+ 	.id_table		= keyspan_1port_ids,
+-	.num_interrupt_in	= NUM_DONT_CARE,
+-	.num_interrupt_out	= NUM_DONT_CARE,
+-	.num_bulk_in		= NUM_DONT_CARE,
+-	.num_bulk_out		= NUM_DONT_CARE,
+ 	.num_ports		= 1,
+ 	.open			= keyspan_open,
+ 	.close			= keyspan_close,
+@@ -679,10 +671,6 @@ static struct usb_serial_driver keyspan_2port_device = {
+ 	},
+ 	.description		= "Keyspan 2 port adapter",
+ 	.id_table		= keyspan_2port_ids,
+-	.num_interrupt_in	= NUM_DONT_CARE,
+-	.num_interrupt_out	= NUM_DONT_CARE,
+-	.num_bulk_in		= NUM_DONT_CARE,
+-	.num_bulk_out		= NUM_DONT_CARE,
+ 	.num_ports		= 2,
+ 	.open			= keyspan_open,
+ 	.close			= keyspan_close,
+@@ -707,10 +695,6 @@ static struct usb_serial_driver keyspan_4port_device = {
+ 	},
+ 	.description		= "Keyspan 4 port adapter",
+ 	.id_table		= keyspan_4port_ids,
+-	.num_interrupt_in	= NUM_DONT_CARE,
+-	.num_interrupt_out	= NUM_DONT_CARE,
+-	.num_bulk_in		= NUM_DONT_CARE,
+-	.num_bulk_out		= NUM_DONT_CARE,
+ 	.num_ports		= 4,
+ 	.open			= keyspan_open,
+ 	.close			= keyspan_close,
+diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
+index b1fa5a3..ff54203 100644
+--- a/drivers/usb/serial/keyspan_pda.c
++++ b/drivers/usb/serial/keyspan_pda.c
+@@ -208,13 +208,13 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
+ 				 2000);
+ 	if (result < 0)
+ 		dbg("%s - error %d from usb_control_msg", 
+-		    __FUNCTION__, result);
++		    __func__, result);
+ }
+ 
+ 
+ static void keyspan_pda_rx_interrupt (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+        	struct tty_struct *tty = port->tty;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int i;
+@@ -232,11 +232,11 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	default:
+ 		dbg("%s - nonzero urb status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		goto exit;
+ 	}
+ 
+@@ -274,7 +274,7 @@ exit:
+ 	retval = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (retval)
+ 		err ("%s - usb_submit_urb failed with result %d",
+-		     __FUNCTION__, retval);
++		     __func__, retval);
+ }
+ 
+ 
+@@ -358,7 +358,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
+ 				value, 0, NULL, 0, 2000);
+ 	if (result < 0)
+ 		dbg("%s - error %d from usb_control_msg", 
+-		    __FUNCTION__, result);
++		    __func__, result);
+ 	/* there is something funky about this.. the TCSBRK that 'cu' performs
+ 	   ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
+ 	   seconds apart, but it feels like the break sent isn't as long as it
+@@ -608,7 +608,7 @@ exit:
+ 
+ static void keyspan_pda_write_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct keyspan_pda_private *priv;
+ 
+ 	port->write_urb_busy = 0;
+@@ -636,14 +636,19 @@ static int keyspan_pda_write_room (struct usb_serial_port *port)
+ static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
+ {
+ 	struct keyspan_pda_private *priv;
++	unsigned long flags;
++	int ret = 0;
+ 
+ 	priv = usb_get_serial_port_data(port);
+ 
+ 	/* when throttled, return at least WAKEUP_CHARS to tell select() (via
+ 	   n_tty.c:normal_poll() ) that we're not writeable. */
++
++	spin_lock_irqsave(&port->lock, flags);
+ 	if (port->write_urb_busy || priv->tx_throttled)
+-		return 256;
+-	return 0;
++		ret = 256;
++	spin_unlock_irqrestore(&port->lock, flags);
++	return ret;
+ }
+ 
+ 
+@@ -665,11 +670,11 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
+ 			     1,
+ 			     2000);
+ 	if (rc < 0) {
+-		dbg("%s - roomquery failed", __FUNCTION__);
++		dbg("%s - roomquery failed", __func__);
+ 		goto error;
+ 	}
+ 	if (rc == 0) {
+-		dbg("%s - roomquery returned 0 bytes", __FUNCTION__);
++		dbg("%s - roomquery returned 0 bytes", __func__);
+ 		rc = -EIO;
+ 		goto error;
+ 	}
+@@ -688,7 +693,7 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
+ 	port->interrupt_in_urb->dev = serial->dev;
+ 	rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ 	if (rc) {
+-		dbg("%s - usb_submit_urb(read int) failed", __FUNCTION__);
++		dbg("%s - usb_submit_urb(read int) failed", __func__);
+ 		goto error;
+ 	}
+ 
+@@ -732,7 +737,7 @@ static int keyspan_pda_fake_startup (struct usb_serial *serial)
+ 		record = &xircom_pgs_firmware[0];
+ #endif
+ 	if (record == NULL) {
+-		err("%s: unknown vendor, aborting.", __FUNCTION__);
++		err("%s: unknown vendor, aborting.", __func__);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -779,7 +784,7 @@ static int keyspan_pda_startup (struct usb_serial *serial)
+ 
+ static void keyspan_pda_shutdown (struct usb_serial *serial)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	
+ 	kfree(usb_get_serial_port_data(serial->port[0]));
+ }
+@@ -793,9 +798,6 @@ static struct usb_serial_driver keyspan_pda_fake_device = {
+ 	.description =		"Keyspan PDA - (prerenumeration)",
+ 	.usb_driver = 		&keyspan_pda_driver,
+ 	.id_table =		id_table_fake,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		1,
+ 	.attach =		keyspan_pda_fake_startup,
+ };
+@@ -810,9 +812,6 @@ static struct usb_serial_driver xircom_pgs_fake_device = {
+ 	.description =		"Xircom / Entregra PGS - (prerenumeration)",
+ 	.usb_driver = 		&keyspan_pda_driver,
+ 	.id_table =		id_table_fake_xircom,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		1,
+ 	.attach =		keyspan_pda_fake_startup,
+ };
+@@ -826,9 +825,6 @@ static struct usb_serial_driver keyspan_pda_device = {
+ 	.description =		"Keyspan PDA",
+ 	.usb_driver = 		&keyspan_pda_driver,
+ 	.id_table =		id_table_std,
+-	.num_interrupt_in =	1,
+-	.num_bulk_in =		0,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.open =			keyspan_pda_open,
+ 	.close =		keyspan_pda_close,
+diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
+index 55736df..b395ac7 100644
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -126,9 +126,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
+ 	.description =	     "KL5KUSB105D / PalmConnect",
+ 	.usb_driver =	     &kl5kusb105d_driver,
+ 	.id_table =	     id_table,
+-	.num_interrupt_in =  1,
+-	.num_bulk_in =	     1,
+-	.num_bulk_out =	     1,
+ 	.num_ports =	     1,
+ 	.open =		     klsi_105_open,
+ 	.close =	     klsi_105_close,
+@@ -194,7 +191,7 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port,
+ 	if (rc < 0)
+ 		err("Change port settings failed (error = %d)", rc);
+ 	info("%s - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d",
+-	    __FUNCTION__,
++	    __func__,
+ 	    settings->pktlen,
+ 	    settings->baudrate, settings->databits,
+ 	    settings->unknown1, settings->unknown2);
+@@ -225,7 +222,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
+ 	__u8 status_buf[KLSI_STATUSBUF_LEN] = { -1,-1};
+ 	__u16 status;
+ 
+-	info("%s - sending SIO Poll request", __FUNCTION__);
++	info("%s - sending SIO Poll request", __func__);
+         rc = usb_control_msg(port->serial->dev,
+ 			     usb_rcvctrlpipe(port->serial->dev, 0),
+ 			     KL5KUSB105A_SIO_POLL,
+@@ -240,7 +237,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
+ 	else {
+ 		status = le16_to_cpu(*(u16 *)status_buf);
+ 
+-		info("%s - read status %x %x", __FUNCTION__,
++		info("%s - read status %x %x", __func__,
+ 		     status_buf[0], status_buf[1]);
+ 
+ 		*line_state_p = klsi_105_status2linestate(status);
+@@ -268,7 +265,7 @@ static int klsi_105_startup (struct usb_serial *serial)
+ 		priv = kmalloc(sizeof(struct klsi_105_private),
+ 						   GFP_KERNEL);
+ 		if (!priv) {
+-			dbg("%skmalloc for klsi_105_private failed.", __FUNCTION__);
++			dbg("%skmalloc for klsi_105_private failed.", __func__);
+ 			i--;
+ 			goto err_cleanup;
+ 		}
+@@ -298,7 +295,7 @@ static int klsi_105_startup (struct usb_serial *serial)
+ 			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE,
+ 							GFP_KERNEL);
+ 			if (!urb->transfer_buffer) {
+-				err("%s - out of memory for urb buffers.", __FUNCTION__);
++				err("%s - out of memory for urb buffers.", __func__);
+ 				goto err_cleanup;
+ 			}
+ 		}
+@@ -328,7 +325,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
+ {
+ 	int i;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* stop reads and writes on all ports */
+ 	for (i=0; i < serial->num_ports; ++i) {
+@@ -373,7 +370,7 @@ static int  klsi_105_open (struct usb_serial_port *port, struct file *filp)
+ 	struct klsi_105_port_settings cfg;
+ 	unsigned long flags;
+ 
+-	dbg("%s port %d", __FUNCTION__, port->number);
++	dbg("%s port %d", __func__, port->number);
+ 
+ 	/* force low_latency on so that our tty_push actually forces
+ 	 * the data through
+@@ -419,7 +416,7 @@ static int  klsi_105_open (struct usb_serial_port *port, struct file *filp)
+ 
+ 	rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (rc) {
+-		err("%s - failed submitting read urb, error %d", __FUNCTION__, rc);
++		err("%s - failed submitting read urb, error %d", __func__, rc);
+ 		retval = rc;
+ 		goto exit;
+ 	}
+@@ -437,14 +434,14 @@ static int  klsi_105_open (struct usb_serial_port *port, struct file *filp)
+ 		err("Enabling read failed (error = %d)", rc);
+ 		retval = rc;
+ 	} else 
+-		dbg("%s - enabled reading", __FUNCTION__);
++		dbg("%s - enabled reading", __func__);
+ 
+ 	rc = klsi_105_get_line_state(port, &line_state);
+ 	if (rc >= 0) {
+ 		spin_lock_irqsave (&priv->lock, flags);
+ 		priv->line_state = line_state;
+ 		spin_unlock_irqrestore (&priv->lock, flags);
+-		dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
++		dbg("%s - read line state 0x%lx", __func__, line_state);
+ 		retval = 0;
+ 	} else
+ 		retval = rc;
+@@ -459,7 +456,7 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
+ 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
+ 	int rc;
+ 
+-	dbg("%s port %d", __FUNCTION__, port->number);
++	dbg("%s port %d", __func__, port->number);
+ 
+ 	mutex_lock(&port->serial->disc_mutex);
+ 	if (!port->serial->disconnected) {
+@@ -502,7 +499,7 @@ static int klsi_105_write (struct usb_serial_port *port,
+ 	int result, size;
+ 	int bytes_sent=0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	while (count > 0) {
+ 		/* try to find a free urb (write 0 bytes if none) */
+@@ -514,21 +511,21 @@ static int klsi_105_write (struct usb_serial_port *port,
+ 		for (i=0; i<NUM_URBS; i++) {
+ 			if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
+ 				urb = priv->write_urb_pool[i];
+-				dbg("%s - using pool URB %d", __FUNCTION__, i);
++				dbg("%s - using pool URB %d", __func__, i);
+ 				break;
+ 			}
+ 		}
+ 		spin_unlock_irqrestore (&priv->lock, flags);
+ 
+ 		if (urb==NULL) {
+-			dbg("%s - no more free urbs", __FUNCTION__);
++			dbg("%s - no more free urbs", __func__);
+ 			goto exit;
+ 		}
+ 
+ 		if (urb->transfer_buffer == NULL) {
+ 			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+ 			if (urb->transfer_buffer == NULL) {
+-				err("%s - no more kernel memory...", __FUNCTION__);
++				err("%s - no more kernel memory...", __func__);
+ 				goto exit;
+ 			}
+ 		}
+@@ -554,7 +551,7 @@ static int klsi_105_write (struct usb_serial_port *port,
+ 		/* send the data out the bulk port */
+ 		result = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (result) {
+-			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++			err("%s - failed submitting write urb, error %d", __func__, result);
+ 			goto exit;
+ 		}
+ 		buf += size;
+@@ -570,13 +567,13 @@ exit:
+ 
+ static void klsi_105_write_bulk_callback ( struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
++		dbg("%s - nonzero write bulk status received: %d", __func__,
+ 		    status);
+ 		return;
+ 	}
+@@ -603,7 +600,7 @@ static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
+ 
+ 	spin_unlock_irqrestore (&priv->lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, chars);
++	dbg("%s - returns %d", __func__, chars);
+ 	return (chars);
+ }
+ 
+@@ -623,7 +620,7 @@ static int klsi_105_write_room (struct usb_serial_port *port)
+ 
+ 	spin_unlock_irqrestore (&priv->lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 	return (room);
+ }
+ 
+@@ -631,18 +628,18 @@ static int klsi_105_write_room (struct usb_serial_port *port)
+ 
+ static void klsi_105_read_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
+ 	struct tty_struct *tty;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int rc;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* The urb might have been killed. */
+ 	if (status) {
+-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
++		dbg("%s - nonzero read bulk status received: %d", __func__,
+ 		    status);
+ 		return;
+ 	}
+@@ -652,12 +649,12 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
+ 	 */
+ 	if (urb->actual_length == 0) {
+ 		/* empty urbs seem to happen, we ignore them */
+-		/* dbg("%s - emtpy URB", __FUNCTION__); */
++		/* dbg("%s - emtpy URB", __func__); */
+ 	       ;
+ 	} else if (urb->actual_length <= 2) {
+-		dbg("%s - size %d URB not understood", __FUNCTION__,
++		dbg("%s - size %d URB not understood", __func__,
+ 		    urb->actual_length);
+-		usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++		usb_serial_debug_data(debug, &port->dev, __func__,
+ 				      urb->actual_length, data);
+ 	} else {
+ 		int bytes_sent = ((__u8 *) data)[0] +
+@@ -669,12 +666,12 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
+ 		 * intermixed tty_flip_buffer_push()s
+ 		 * FIXME
+ 		 */ 
+-		usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++		usb_serial_debug_data(debug, &port->dev, __func__,
+ 				      urb->actual_length, data);
+ 
+ 		if (bytes_sent + 2 > urb->actual_length) {
+ 			dbg("%s - trying to read more data than available"
+-			    " (%d vs. %d)", __FUNCTION__,
++			    " (%d vs. %d)", __func__,
+ 			    bytes_sent+2, urb->actual_length);
+ 			/* cap at implied limit */
+ 			bytes_sent = urb->actual_length - 2;
+@@ -697,7 +694,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
+ 		      port);
+ 	rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 	if (rc)
+-		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, rc);
++		err("%s - failed resubmitting read urb, error %d", __func__, rc);
+ } /* klsi_105_read_bulk_callback */
+ 
+ 
+@@ -705,12 +702,14 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ 				  struct ktermios *old_termios)
+ {
+ 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
+-	unsigned int iflag = port->tty->termios->c_iflag;
++	struct tty_struct *tty = port->tty;
++	unsigned int iflag = tty->termios->c_iflag;
+ 	unsigned int old_iflag = old_termios->c_iflag;
+-	unsigned int cflag = port->tty->termios->c_cflag;
++	unsigned int cflag = tty->termios->c_cflag;
+ 	unsigned int old_cflag = old_termios->c_cflag;
+ 	struct klsi_105_port_settings cfg;
+ 	unsigned long flags;
++	speed_t baud;
+ 	
+ 	/* lock while we are modifying the settings */
+ 	spin_lock_irqsave (&priv->lock, flags);
+@@ -718,10 +717,12 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ 	/*
+ 	 * Update baud rate
+ 	 */
++	baud = tty_get_baud_rate(tty);
++
+ 	if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
+ 	        /* reassert DTR and (maybe) RTS on transition from B0 */
+ 		if( (old_cflag & CBAUD) == B0 ) {
+-			dbg("%s: baud was B0", __FUNCTION__);
++			dbg("%s: baud was B0", __func__);
+ #if 0
+ 			priv->control_state |= TIOCM_DTR;
+ 			/* don't set RTS if using hardware flow control */
+@@ -731,8 +732,8 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ 			mct_u232_set_modem_ctrl(serial, priv->control_state);
+ #endif
+ 		}
+-		
+-		switch(tty_get_baud_rate(port->tty)) {
++	}
++	switch(baud) {
+ 		case 0: /* handled below */
+ 			break;
+ 		case 1200:
+@@ -760,35 +761,36 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ 			priv->cfg.baudrate = kl5kusb105a_sio_b115200;
+ 			break;
+ 		default:
+-			err("KLSI USB->Serial converter:"
++			dbg("KLSI USB->Serial converter:"
+ 			    " unsupported baudrate request, using default"
+ 			    " of 9600");
+ 			priv->cfg.baudrate = kl5kusb105a_sio_b9600;
++			baud = 9600;
+ 			break;
+-		}
+-		if ((cflag & CBAUD) == B0 ) {
+-			dbg("%s: baud is B0", __FUNCTION__);
+-			/* Drop RTS and DTR */
+-			/* maybe this should be simulated by sending read
+-			 * disable and read enable messages?
+-			 */
+-			;
++	}
++	if ((cflag & CBAUD) == B0 ) {
++		dbg("%s: baud is B0", __func__);
++		/* Drop RTS and DTR */
++		/* maybe this should be simulated by sending read
++		 * disable and read enable messages?
++		 */
++		;
+ #if 0
+-			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+-        		mct_u232_set_modem_ctrl(serial, priv->control_state);
++		priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
++       		mct_u232_set_modem_ctrl(serial, priv->control_state);
+ #endif
+-		}
+ 	}
++	tty_encode_baud_rate(tty, baud, baud);
+ 
+ 	if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
+ 		/* set the number of data bits */
+ 		switch (cflag & CSIZE) {
+ 		case CS5:
+-			dbg("%s - 5 bits/byte not supported", __FUNCTION__);
++			dbg("%s - 5 bits/byte not supported", __func__);
+ 			spin_unlock_irqrestore (&priv->lock, flags);
+ 			return ;
+ 		case CS6:
+-			dbg("%s - 6 bits/byte not supported", __FUNCTION__);
++			dbg("%s - 6 bits/byte not supported", __func__);
+ 			spin_unlock_irqrestore (&priv->lock, flags);
+ 			return ;
+ 		case CS7:
+@@ -810,6 +812,8 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ 	if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
+ 	    || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
+ 		
++		/* Not currently supported */
++		tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB);
+ #if 0
+ 		priv->last_lcr = 0;
+ 
+@@ -837,6 +841,8 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ 	    || (iflag & IXON) != (old_iflag & IXON)
+ 	    ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
+ 		
++		/* Not currently supported */
++		tty->termios->c_cflag &= ~CRTSCTS;
+ 		/* Drop DTR/RTS if no flow control otherwise assert */
+ #if 0
+ 		if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
+@@ -862,7 +868,7 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+ 	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ 	unsigned char lcr = priv->last_lcr;
+ 
+-	dbg("%sstate=%d", __FUNCTION__, break_state);
++	dbg("%sstate=%d", __func__, break_state);
+ 
+ 	if (break_state)
+ 		lcr |= MCT_U232_SET_BREAK;
+@@ -877,7 +883,7 @@ static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
+ 	unsigned long flags;
+ 	int rc;
+ 	unsigned long line_state;
+-	dbg("%s - request, just guessing", __FUNCTION__);
++	dbg("%s - request, just guessing", __func__);
+ 
+ 	rc = klsi_105_get_line_state(port, &line_state);
+ 	if (rc < 0) {
+@@ -889,7 +895,7 @@ static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
+ 	spin_lock_irqsave (&priv->lock, flags);
+ 	priv->line_state = line_state;
+ 	spin_unlock_irqrestore (&priv->lock, flags);
+-	dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
++	dbg("%s - read line state 0x%lx", __func__, line_state);
+ 	return (int)line_state;
+ }
+ 
+@@ -898,7 +904,7 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
+ {
+ 	int retval = -EINVAL;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ /* if this ever gets implemented, it should be done something like this:
+ 	struct usb_serial *serial = port->serial;
+@@ -924,7 +930,7 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
+ 
+ static void klsi_105_throttle (struct usb_serial_port *port)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	usb_kill_urb(port->read_urb);
+ }
+ 
+@@ -932,12 +938,12 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
+ {
+ 	int result;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	port->read_urb->dev = port->serial->dev;
+ 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 	if (result)
+-		err("%s - failed submitting read urb, error %d", __FUNCTION__,
++		err("%s - failed submitting read urb, error %d", __func__,
+ 		    result);
+ }
+ 
+diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
+index 17b3bae..693f00d 100644
+--- a/drivers/usb/serial/kobil_sct.c
++++ b/drivers/usb/serial/kobil_sct.c
+@@ -113,10 +113,6 @@ static struct usb_serial_driver kobil_device = {
+ 	.description =		"KOBIL USB smart card terminal",
+ 	.usb_driver = 		&kobil_driver,
+ 	.id_table =		id_table,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_interrupt_out = 	NUM_DONT_CARE,
+-	.num_bulk_in =		0,
+-	.num_bulk_out =		0,
+ 	.num_ports =		1,
+ 	.attach =		kobil_startup,
+ 	.shutdown =		kobil_shutdown,
+@@ -139,7 +135,6 @@ struct kobil_private {
+ 	int filled;  // index of the last char in buf
+ 	int cur_pos; // index of the next char to send in buf
+ 	__u16 device_type;
+-	int line_state;
+ };
+ 
+ 
+@@ -161,7 +156,6 @@ static int kobil_startup (struct usb_serial *serial)
+ 	priv->filled = 0;
+ 	priv->cur_pos = 0;
+ 	priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);
+-	priv->line_state = 0;
+ 
+ 	switch (priv->device_type){
+ 	case KOBIL_ADAPTER_B_PRODUCT_ID:
+@@ -189,11 +183,11 @@ static int kobil_startup (struct usb_serial *serial)
+  	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+ 		endpoint = &altsetting->endpoint[i];
+ 		if (usb_endpoint_is_int_out(&endpoint->desc)) {
+-		 	dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
++		 	dbg("%s Found interrupt out endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
+ 		 	priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
+  		}
+ 		if (usb_endpoint_is_int_in(&endpoint->desc)) {
+-		 	dbg("%s Found interrupt in  endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
++		 	dbg("%s Found interrupt in  endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
+ 		 	priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
+ 	 	}
+ 	}
+@@ -204,7 +198,7 @@ static int kobil_startup (struct usb_serial *serial)
+ static void kobil_shutdown (struct usb_serial *serial)
+ {
+ 	int i;
+-	dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
++	dbg("%s - port %d", __func__, serial->port[0]->number);
+ 
+ 	for (i=0; i < serial->num_ports; ++i) {
+ 		while (serial->port[i]->open_count > 0) {
+@@ -224,9 +218,8 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ 	int transfer_buffer_length = 8;
+ 	int write_urb_transfer_buffer_length = 8;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	priv = usb_get_serial_port_data(port);
+-	priv->line_state = 0;
+ 
+ 	// someone sets the dev to 0 if the close method has been called
+ 	port->interrupt_in_urb->dev = port->serial->dev;
+@@ -252,10 +245,10 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ 	
+ 	// allocate write_urb
+ 	if (!port->write_urb) { 
+-		dbg("%s - port %d  Allocating port->write_urb", __FUNCTION__, port->number);
++		dbg("%s - port %d  Allocating port->write_urb", __func__, port->number);
+ 		port->write_urb = usb_alloc_urb(0, GFP_KERNEL);  
+ 		if (!port->write_urb) {
+-			dbg("%s - port %d usb_alloc_urb failed", __FUNCTION__, port->number);
++			dbg("%s - port %d usb_alloc_urb failed", __func__, port->number);
+ 			kfree(transfer_buffer);
+ 			return -ENOMEM;
+ 		}
+@@ -281,7 +274,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ 				  transfer_buffer_length,
+ 				  KOBIL_TIMEOUT
+ 		);
+-	dbg("%s - port %d Send get_HW_version URB returns: %i", __FUNCTION__, port->number, result);
++	dbg("%s - port %d Send get_HW_version URB returns: %i", __func__, port->number, result);
+ 	dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
+ 	
+ 	// get firmware version
+@@ -295,7 +288,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ 				  transfer_buffer_length,
+ 				  KOBIL_TIMEOUT
+ 		);
+-	dbg("%s - port %d Send get_FW_version URB returns: %i", __FUNCTION__, port->number, result);
++	dbg("%s - port %d Send get_FW_version URB returns: %i", __func__, port->number, result);
+ 	dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
+ 
+ 	if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
+@@ -310,7 +303,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ 					  0,
+ 					  KOBIL_TIMEOUT
+ 			);
+-		dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result);
++		dbg("%s - port %d Send set_baudrate URB returns: %i", __func__, port->number, result);
+ 		
+ 		// reset all queues
+ 		result = usb_control_msg( port->serial->dev, 
+@@ -323,13 +316,13 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ 					  0,
+ 					  KOBIL_TIMEOUT
+ 			);
+-		dbg("%s - port %d Send reset_all_queues URB returns: %i", __FUNCTION__, port->number, result);
++		dbg("%s - port %d Send reset_all_queues URB returns: %i", __func__, port->number, result);
+ 	}
+ 	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+ 	    priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+ 		// start reading (Adapter B 'cause PNP string)
+ 		result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC  ); 
+-		dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
++		dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ 	}
+ 
+ 	kfree(transfer_buffer);
+@@ -339,7 +332,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ 
+ static void kobil_close (struct usb_serial_port *port, struct file *filp)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (port->write_urb) {
+ 		usb_kill_urb(port->write_urb);
+@@ -359,11 +352,11 @@ static void kobil_read_int_callback(struct urb *urb)
+ 	int status = urb->status;
+ //	char *dbg_data;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("%s - port %d Read int status not zero: %d",
+-		    __FUNCTION__, port->number, status);
++		    __func__, port->number, status);
+ 		return;
+ 	}
+ 
+@@ -393,7 +386,7 @@ static void kobil_read_int_callback(struct urb *urb)
+ 	port->interrupt_in_urb->dev = port->serial->dev;
+ 
+ 	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+-	dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
++	dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ }
+ 
+ 
+@@ -411,21 +404,21 @@ static int kobil_write (struct usb_serial_port *port,
+ 	struct kobil_private * priv;
+ 
+ 	if (count == 0) {
+-		dbg("%s - port %d write request of 0 bytes", __FUNCTION__, port->number);
++		dbg("%s - port %d write request of 0 bytes", __func__, port->number);
+ 		return 0;
+ 	}
+ 
+ 	priv = usb_get_serial_port_data(port);
+ 
+ 	if (count > (KOBIL_BUF_LENGTH - priv->filled)) {
+-		dbg("%s - port %d Error: write request bigger than buffer size", __FUNCTION__, port->number);
++		dbg("%s - port %d Error: write request bigger than buffer size", __func__, port->number);
+ 		return -ENOMEM;
+ 	}
+ 
+ 	// Copy data to buffer
+ 	memcpy (priv->buf + priv->filled, buf, count);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, priv->buf + priv->filled);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled);
+ 
+ 	priv->filled = priv->filled + count;
+ 
+@@ -457,7 +450,7 @@ static int kobil_write (struct usb_serial_port *port,
+ 
+ 			priv->cur_pos = priv->cur_pos + length;
+ 			result = usb_submit_urb( port->write_urb, GFP_NOIO );
+-			dbg("%s - port %d Send write URB returns: %i", __FUNCTION__, port->number, result);
++			dbg("%s - port %d Send write URB returns: %i", __func__, port->number, result);
+ 			todo = priv->filled - priv->cur_pos;
+ 
+ 			if (todo > 0) {
+@@ -478,7 +471,7 @@ static int kobil_write (struct usb_serial_port *port,
+ 			port->interrupt_in_urb->dev = port->serial->dev;
+ 			
+ 			result = usb_submit_urb( port->interrupt_in_urb, GFP_NOIO ); 
+-			dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
++			dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ 		}
+ 	}
+ 	return count;
+@@ -487,7 +480,7 @@ static int kobil_write (struct usb_serial_port *port,
+ 
+ static int kobil_write_room (struct usb_serial_port *port)
+ {
+-	//dbg("%s - port %d", __FUNCTION__, port->number);
++	//dbg("%s - port %d", __func__, port->number);
+ 	return 8;
+ }
+ 
+@@ -522,16 +515,13 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
+ 				  KOBIL_TIMEOUT);
+ 
+ 	dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x", 
+-	    __FUNCTION__, port->number, result, transfer_buffer[0]);
+-
+-	if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) {
+-		priv->line_state |= TIOCM_DSR;
+-	} else {
+-		priv->line_state &= ~TIOCM_DSR; 
+-	}
++	    __func__, port->number, result, transfer_buffer[0]);
+ 
++	result = 0;
++	if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
++		result = TIOCM_DSR;
+ 	kfree(transfer_buffer);
+-	return priv->line_state;
++	return result;
+ }
+ 
+ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+@@ -544,6 +534,7 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+ 	unsigned char *transfer_buffer;
+ 	int transfer_buffer_length = 8;
+ 
++	/* FIXME: locking ? */
+ 	priv = usb_get_serial_port_data(port);
+ 	if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
+ 		// This device doesn't support ioctl calls
+@@ -567,9 +558,9 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+ 
+ 	if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
+ 		if (dtr != 0)
+-			dbg("%s - port %d Setting DTR", __FUNCTION__, port->number);
++			dbg("%s - port %d Setting DTR", __func__, port->number);
+ 		else
+-			dbg("%s - port %d Clearing DTR", __FUNCTION__, port->number);
++			dbg("%s - port %d Clearing DTR", __func__, port->number);
+ 		result = usb_control_msg( port->serial->dev, 
+ 					  usb_rcvctrlpipe(port->serial->dev, 0 ), 
+ 					  SUSBCRequest_SetStatusLinesOrQueues,
+@@ -581,9 +572,9 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+ 					  KOBIL_TIMEOUT);
+ 	} else {
+ 		if (rts != 0)
+-			dbg("%s - port %d Setting RTS", __FUNCTION__, port->number);
++			dbg("%s - port %d Setting RTS", __func__, port->number);
+ 		else
+-			dbg("%s - port %d Clearing RTS", __FUNCTION__, port->number);
++			dbg("%s - port %d Clearing RTS", __func__, port->number);
+ 		result = usb_control_msg( port->serial->dev, 
+ 					  usb_rcvctrlpipe(port->serial->dev, 0 ), 
+ 					  SUSBCRequest_SetStatusLinesOrQueues,
+@@ -594,7 +585,7 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+ 					  0,
+ 					  KOBIL_TIMEOUT);
+ 	}
+-	dbg("%s - port %d Send set_status_line URB returns: %i", __FUNCTION__, port->number, result);
++	dbg("%s - port %d Send set_status_line URB returns: %i", __func__, port->number, result);
+ 	kfree(transfer_buffer);
+ 	return (result < 0) ? result : 0;
+ }
+@@ -687,7 +678,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigne
+ 					  KOBIL_TIMEOUT
+ 			);
+ 		
+-		dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __FUNCTION__, port->number, result);
++		dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result);
+ 		kfree(transfer_buffer);
+ 		return (result < 0) ? -EFAULT : 0;
+ 	default:
+diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
+index fc1cea4..5fc2cef 100644
+--- a/drivers/usb/serial/mct_u232.c
++++ b/drivers/usb/serial/mct_u232.c
+@@ -143,9 +143,6 @@ static struct usb_serial_driver mct_u232_device = {
+ 	.description =	     "MCT U232",
+ 	.usb_driver = 	     &mct_u232_driver,
+ 	.id_table =	     id_table_combined,
+-	.num_interrupt_in =  2,
+-	.num_bulk_in =	     0,
+-	.num_bulk_out =	     1,
+ 	.num_ports =	     1,
+ 	.open =		     mct_u232_open,
+ 	.close =	     mct_u232_close,
+@@ -402,7 +399,7 @@ static void mct_u232_shutdown (struct usb_serial *serial)
+ 	struct mct_u232_private *priv;
+ 	int i;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	for (i=0; i < serial->num_ports; ++i) {
+ 		/* My special items, the standard routines free my urbs */
+@@ -424,7 +421,7 @@ static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
+ 	unsigned char last_lcr;
+ 	unsigned char last_msr;
+ 
+-	dbg("%s port %d", __FUNCTION__, port->number);
++	dbg("%s port %d", __func__, port->number);
+ 
+ 	/* Compensate for a hardware bug: although the Sitecom U232-P25
+ 	 * device reports a maximum output packet size of 32 bytes,
+@@ -489,7 +486,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
+ 	unsigned int c_cflag;
+ 	unsigned int control_state;
+ 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
+-	dbg("%s port %d", __FUNCTION__, port->number);
++	dbg("%s port %d", __func__, port->number);
+ 
+    	if (port->tty) {
+ 		c_cflag = port->tty->termios->c_cflag;
+@@ -517,7 +514,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
+ 
+ static void mct_u232_read_int_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
+ 	struct usb_serial *serial = port->serial;
+ 	struct tty_struct *tty;
+@@ -535,21 +532,21 @@ static void mct_u232_read_int_callback (struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	default:
+ 		dbg("%s - nonzero urb status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		goto exit;
+ 	}
+ 
+ 	if (!serial) {
+-		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
++		dbg("%s - bad serial pointer, exiting", __func__);
+ 		return;
+ 	}
+ 
+-        dbg("%s - port %d", __FUNCTION__, port->number);
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++        dbg("%s - port %d", __func__, port->number);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	/*
+ 	 * Work-a-round: handle the 'usual' bulk-in pipe here
+@@ -606,7 +603,7 @@ exit:
+ 	retval = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (retval)
+ 		err ("%s - usb_submit_urb failed with result %d",
+-		     __FUNCTION__, retval);
++		     __func__, retval);
+ } /* mct_u232_read_int_callback */
+ 
+ static void mct_u232_set_termios (struct usb_serial_port *port,
+@@ -636,7 +633,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
+ 
+         /* reassert DTR and RTS on transition from B0 */
+ 	if ((old_cflag & CBAUD) == B0) {
+-		dbg("%s: baud was B0", __FUNCTION__);
++		dbg("%s: baud was B0", __func__);
+ 		control_state |= TIOCM_DTR | TIOCM_RTS;
+ 		mct_u232_set_modem_ctrl(serial, control_state);
+ 	}
+@@ -644,7 +641,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
+ 	mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
+ 
+ 	if ((cflag & CBAUD) == B0 ) {
+-		dbg("%s: baud is B0", __FUNCTION__);
++		dbg("%s: baud is B0", __func__);
+ 		/* Drop RTS and DTR */
+ 		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+        		mct_u232_set_modem_ctrl(serial, control_state);
+@@ -699,7 +696,7 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+ 	unsigned char lcr;
+ 	unsigned long flags;
+ 
+-	dbg("%sstate=%d", __FUNCTION__, break_state);
++	dbg("%sstate=%d", __func__, break_state);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	lcr = priv->last_lcr;
+@@ -718,7 +715,7 @@ static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
+ 	unsigned int control_state;
+ 	unsigned long flags;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	control_state = priv->control_state;
+@@ -735,7 +732,7 @@ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
+ 	unsigned int control_state;
+ 	unsigned long flags;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	control_state = priv->control_state;
+@@ -757,7 +754,7 @@ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
+ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
+ 			   unsigned int cmd, unsigned long arg)
+ {
+-	dbg("%scmd=0x%x", __FUNCTION__, cmd);
++	dbg("%scmd=0x%x", __func__, cmd);
+ 
+ 	/* Based on code from acm.c and others */
+ 	switch (cmd) {
+@@ -772,7 +769,7 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
+ 		return 0;
+ 
+ 	default:
+-		dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
++		dbg("%s: arg not supported - 0x%04x", __func__,cmd);
+ 		return(-ENOIOCTLCMD);
+ 		break;
+ 	}
+@@ -787,7 +784,7 @@ static void mct_u232_throttle (struct usb_serial_port *port)
+ 	struct tty_struct *tty;
+ 
+ 	tty = port->tty;
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	priv->rx_flags |= THROTTLED;
+@@ -809,7 +806,7 @@ static void mct_u232_unthrottle (struct usb_serial_port *port)
+ 	unsigned int control_state;
+ 	struct tty_struct *tty;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	tty = port->tty;
+ 	spin_lock_irqsave(&priv->lock, flags);
+diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
+index 40f3a01..50f1fe2 100644
+--- a/drivers/usb/serial/mos7720.c
++++ b/drivers/usb/serial/mos7720.c
+@@ -118,11 +118,11 @@ static void mos7720_interrupt_callback(struct urb *urb)
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+-		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++		dbg("%s - urb shutting down with status: %d", __func__,
+ 		    status);
+ 		return;
+ 	default:
+-		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
++		dbg("%s - nonzero urb status received: %d", __func__,
+ 		    status);
+ 		goto exit;
+ 	}
+@@ -183,7 +183,7 @@ exit:
+ 	if (result)
+ 		dev_err(&urb->dev->dev,
+ 			"%s - Error %d submitting control urb\n",
+-			__FUNCTION__, result);
++			__func__, result);
+ 	return;
+ }
+ 
+@@ -214,7 +214,7 @@ static void mos7720_bulk_in_callback(struct urb *urb)
+ 
+ 	port = mos7720_port->port;
+ 
+-	dbg("Entering...%s", __FUNCTION__);
++	dbg("Entering...%s", __func__);
+ 
+ 	data = urb->transfer_buffer;
+ 
+@@ -362,7 +362,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+ 		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ 					       GFP_KERNEL);
+ 		if (!urb->transfer_buffer) {
+-			err("%s-out of memory for urb buffers.", __FUNCTION__);
++			err("%s-out of memory for urb buffers.", __func__);
+ 			usb_free_urb(mos7720_port->write_urb_pool[j]);
+ 			mos7720_port->write_urb_pool[j] = NULL;
+ 			continue;
+@@ -479,7 +479,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+ 		if (response)
+ 			dev_err(&port->dev,
+ 				"%s - Error %d submitting control urb\n",
+-				__FUNCTION__, response);
++				__func__, response);
+ 	}
+ 
+ 	/* set up our bulk in urb */
+@@ -492,7 +492,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+ 	response = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (response)
+ 		dev_err(&port->dev,
+-			"%s - Error %d submitting read urb\n", __FUNCTION__, response);
++			"%s - Error %d submitting read urb\n", __func__, response);
+ 
+ 	/* initialize our icount structure */
+ 	memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
+@@ -521,11 +521,11 @@ static int mos7720_chars_in_buffer(struct usb_serial_port *port)
+ 	int chars = 0;
+ 	struct moschip_port *mos7720_port;
+ 
+-	dbg("%s:entering ...........", __FUNCTION__);
++	dbg("%s:entering ...........", __func__);
+ 
+ 	mos7720_port = usb_get_serial_port_data(port);
+ 	if (mos7720_port == NULL) {
+-		dbg("%s:leaving ...........", __FUNCTION__);
++		dbg("%s:leaving ...........", __func__);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -533,7 +533,7 @@ static int mos7720_chars_in_buffer(struct usb_serial_port *port)
+ 		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
+ 			chars += URB_TRANSFER_BUFFER_SIZE;
+ 	}
+-	dbg("%s - returns %d", __FUNCTION__, chars);
++	dbg("%s - returns %d", __func__, chars);
+ 	return chars;
+ }
+ 
+@@ -585,7 +585,7 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp)
+ 	mutex_unlock(&serial->disc_mutex);
+ 	mos7720_port->open = 0;
+ 
+-	dbg("Leaving %s", __FUNCTION__);
++	dbg("Leaving %s", __func__);
+ }
+ 
+ static void mos7720_break(struct usb_serial_port *port, int break_state)
+@@ -594,7 +594,7 @@ static void mos7720_break(struct usb_serial_port *port, int break_state)
+ 	struct usb_serial *serial;
+ 	struct moschip_port *mos7720_port;
+ 
+-	dbg("Entering %s", __FUNCTION__);
++	dbg("Entering %s", __func__);
+ 
+ 	serial = port->serial;
+ 
+@@ -627,20 +627,21 @@ static int mos7720_write_room(struct usb_serial_port *port)
+ 	int room = 0;
+ 	int i;
+ 
+-	dbg("%s:entering ...........", __FUNCTION__);
++	dbg("%s:entering ...........", __func__);
+ 
+ 	mos7720_port = usb_get_serial_port_data(port);
+ 	if (mos7720_port == NULL) {
+-		dbg("%s:leaving ...........", __FUNCTION__);
++		dbg("%s:leaving ...........", __func__);
+ 		return -ENODEV;
+ 	}
+ 
++	/* FIXME: Locking */
+ 	for (i = 0; i < NUM_URBS; ++i) {
+ 		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
+ 			room += URB_TRANSFER_BUFFER_SIZE;
+ 	}
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 	return room;
+ }
+ 
+@@ -657,7 +658,7 @@ static int mos7720_write(struct usb_serial_port *port,
+ 	struct urb    *urb;
+ 	const unsigned char *current_position = data;
+ 
+-	dbg("%s:entering ...........", __FUNCTION__);
++	dbg("%s:entering ...........", __func__);
+ 
+ 	serial = port->serial;
+ 
+@@ -679,7 +680,7 @@ static int mos7720_write(struct usb_serial_port *port,
+ 	}
+ 
+ 	if (urb == NULL) {
+-		dbg("%s - no more free urbs", __FUNCTION__);
++		dbg("%s - no more free urbs", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -687,14 +688,14 @@ static int mos7720_write(struct usb_serial_port *port,
+ 		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ 					       GFP_KERNEL);
+ 		if (urb->transfer_buffer == NULL) {
+-			err("%s no more kernel memory...", __FUNCTION__);
++			err("%s no more kernel memory...", __func__);
+ 			goto exit;
+ 		}
+ 	}
+ 	transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
+ 
+ 	memcpy(urb->transfer_buffer, current_position, transfer_size);
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size,
++	usb_serial_debug_data(debug, &port->dev, __func__, transfer_size,
+ 			      urb->transfer_buffer);
+ 
+ 	/* fill urb with data and submit  */
+@@ -708,7 +709,7 @@ static int mos7720_write(struct usb_serial_port *port,
+ 	status = usb_submit_urb(urb,GFP_ATOMIC);
+ 	if (status) {
+ 		err("%s - usb_submit_urb(write bulk) failed with status = %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		bytes_sent = status;
+ 		goto exit;
+ 	}
+@@ -724,7 +725,7 @@ static void mos7720_throttle(struct usb_serial_port *port)
+ 	struct tty_struct *tty;
+ 	int status;
+ 
+-	dbg("%s- port %d\n", __FUNCTION__, port->number);
++	dbg("%s- port %d\n", __func__, port->number);
+ 
+ 	mos7720_port = usb_get_serial_port_data(port);
+ 
+@@ -736,11 +737,11 @@ static void mos7720_throttle(struct usb_serial_port *port)
+ 		return;
+ 	}
+ 
+-	dbg("%s: Entering ..........", __FUNCTION__);
++	dbg("%s: Entering ..........", __func__);
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - no tty available", __FUNCTION__);
++		dbg("%s - no tty available", __func__);
+ 		return;
+ 	}
+ 
+@@ -773,15 +774,15 @@ static void mos7720_unthrottle(struct usb_serial_port *port)
+ 		return;
+ 
+ 	if (!mos7720_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+-	dbg("%s: Entering ..........", __FUNCTION__);
++	dbg("%s: Entering ..........", __func__);
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - no tty available", __FUNCTION__);
++		dbg("%s - no tty available", __func__);
+ 		return;
+ 	}
+ 
+@@ -922,7 +923,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
+ 	__u16 round;
+ 
+ 
+-	dbg("%s - %d", __FUNCTION__, baudrate);
++	dbg("%s - %d", __func__, baudrate);
+ 
+ 	for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
+ 		if (divisor_table[i].baudrate == baudrate) {
+@@ -973,15 +974,15 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
+ 	port = mos7720_port->port;
+ 	serial = port->serial;
+ 
+-	dbg("%s: Entering ..........", __FUNCTION__);
++	dbg("%s: Entering ..........", __func__);
+ 
+ 	number = port->number - port->serial->minor;
+-	dbg("%s - port = %d, baud = %d", __FUNCTION__, port->number, baudrate);
++	dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate);
+ 
+         /* Calculate the Divisor */
+ 	status = calc_baud_rate_divisor(baudrate, &divisor);
+ 	if (status) {
+-		err("%s - bad baud rate", __FUNCTION__);
++		err("%s - bad baud rate", __func__);
+ 		return status;
+ 	}
+ 
+@@ -1034,16 +1035,16 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ 	serial = port->serial;
+ 	port_number = port->number - port->serial->minor;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!mos7720_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+ 	tty = mos7720_port->port->tty;
+ 
+-	dbg("%s: Entering ..........", __FUNCTION__);
++	dbg("%s: Entering ..........", __func__);
+ 
+ 	lData = UART_LCR_WLEN8;
+ 	lStop = 0x00;	/* 1 stop bit */
+@@ -1078,14 +1079,14 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ 	if (cflag & PARENB) {
+ 		if (cflag & PARODD) {
+ 			lParity = UART_LCR_PARITY;
+-			dbg("%s - parity = odd", __FUNCTION__);
++			dbg("%s - parity = odd", __func__);
+ 		} else {
+ 			lParity = (UART_LCR_EPAR | UART_LCR_PARITY);
+-			dbg("%s - parity = even", __FUNCTION__);
++			dbg("%s - parity = even", __func__);
+ 		}
+ 
+ 	} else {
+-		dbg("%s - parity = none", __FUNCTION__);
++		dbg("%s - parity = none", __func__);
+ 	}
+ 
+ 	if (cflag & CMSPAR)
+@@ -1094,10 +1095,10 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ 	/* Change the Stop bit */
+ 	if (cflag & CSTOPB) {
+ 		lStop = UART_LCR_STOP;
+-		dbg("%s - stop bits = 2", __FUNCTION__);
++		dbg("%s - stop bits = 2", __func__);
+ 	} else {
+ 		lStop = 0x00;
+-		dbg("%s - stop bits = 1", __FUNCTION__);
++		dbg("%s - stop bits = 1", __func__);
+ 	}
+ 
+ #define LCR_BITS_MASK		0x03	/* Mask for bits/char field */
+@@ -1171,7 +1172,7 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ 		return;
+ 	}
+ 
+-	dbg("%s - baud rate = %d", __FUNCTION__, baud);
++	dbg("%s - baud rate = %d", __func__, baud);
+ 	status = send_cmd_write_baud_rate(mos7720_port, baud);
+ 	/* FIXME: needs to write actual resulting baud back not just
+ 	   blindly do so */
+@@ -1217,7 +1218,7 @@ static void mos7720_set_termios(struct usb_serial_port *port,
+ 
+ 
+ 	if (!mos7720_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+@@ -1225,15 +1226,15 @@ static void mos7720_set_termios(struct usb_serial_port *port,
+ 
+ 	cflag = tty->termios->c_cflag;
+ 
+-	dbg("%s - cflag %08x iflag %08x", __FUNCTION__,
++	dbg("%s - cflag %08x iflag %08x", __func__,
+ 	    tty->termios->c_cflag,
+ 	    RELEVANT_IFLAG(tty->termios->c_iflag));
+ 
+-	dbg("%s - old cflag %08x old iflag %08x", __FUNCTION__,
++	dbg("%s - old cflag %08x old iflag %08x", __func__,
+ 	    old_termios->c_cflag,
+ 	    RELEVANT_IFLAG(old_termios->c_iflag));
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* change the port settings to the new ones specified */
+ 	change_port_settings(mos7720_port, old_termios);
+@@ -1271,7 +1272,7 @@ static int get_lsr_info(struct moschip_port *mos7720_port,
+ 
+ 	count = mos7720_chars_in_buffer(mos7720_port->port);
+ 	if (count == 0) {
+-		dbg("%s -- Empty", __FUNCTION__);
++		dbg("%s -- Empty", __func__);
+ 		result = TIOCSER_TEMT;
+ 	}
+ 
+@@ -1296,7 +1297,7 @@ static int get_number_bytes_avail(struct moschip_port *mos7720_port,
+ 
+ 	result = tty->read_cnt;
+ 
+-	dbg("%s(%d) = %d", __FUNCTION__,  mos7720_port->port->number, result);
++	dbg("%s(%d) = %d", __func__,  mos7720_port->port->number, result);
+ 	if (copy_to_user(value, &result, sizeof(int)))
+ 		return -EFAULT;
+ 
+@@ -1374,7 +1375,7 @@ static int get_modem_info(struct moschip_port *mos7720_port,
+ 		  | ((msr & UART_MSR_DSR)	? TIOCM_DSR: 0);  /* 0x100 */
+ 
+ 
+-	dbg("%s -- %x", __FUNCTION__, result);
++	dbg("%s -- %x", __func__, result);
+ 
+ 	if (copy_to_user(value, &result, sizeof(int)))
+ 		return -EFAULT;
+@@ -1418,45 +1419,45 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
+ 	if (mos7720_port == NULL)
+ 		return -ENODEV;
+ 
+-	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+ 
+ 	switch (cmd) {
+ 	case TIOCINQ:
+ 		/* return number of bytes available */
+-		dbg("%s (%d) TIOCINQ", __FUNCTION__,  port->number);
++		dbg("%s (%d) TIOCINQ", __func__,  port->number);
+ 		return get_number_bytes_avail(mos7720_port,
+ 					      (unsigned int __user *)arg);
+ 		break;
+ 
+ 	case TIOCSERGETLSR:
+-		dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__,  port->number);
++		dbg("%s (%d) TIOCSERGETLSR", __func__,  port->number);
+ 		return get_lsr_info(mos7720_port, (unsigned int __user *)arg);
+ 		return 0;
+ 
+ 	case TIOCMBIS:
+ 	case TIOCMBIC:
+ 	case TIOCMSET:
+-		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
++		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
+ 		    port->number);
+ 		return set_modem_info(mos7720_port, cmd,
+ 				      (unsigned int __user *)arg);
+ 
+ 	case TIOCMGET:
+-		dbg("%s (%d) TIOCMGET", __FUNCTION__,  port->number);
++		dbg("%s (%d) TIOCMGET", __func__,  port->number);
+ 		return get_modem_info(mos7720_port,
+ 				      (unsigned int __user *)arg);
+ 
+ 	case TIOCGSERIAL:
+-		dbg("%s (%d) TIOCGSERIAL", __FUNCTION__,  port->number);
++		dbg("%s (%d) TIOCGSERIAL", __func__,  port->number);
+ 		return get_serial_info(mos7720_port,
+ 				       (struct serial_struct __user *)arg);
+ 
+ 	case TIOCSSERIAL:
+-		dbg("%s (%d) TIOCSSERIAL", __FUNCTION__,  port->number);
++		dbg("%s (%d) TIOCSSERIAL", __func__,  port->number);
+ 		break;
+ 
+ 	case TIOCMIWAIT:
+-		dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
++		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
+ 		cprev = mos7720_port->icount;
+ 		while (1) {
+ 			if (signal_pending(current))
+@@ -1490,7 +1491,7 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
+ 		icount.brk = cnow.brk;
+ 		icount.buf_overrun = cnow.buf_overrun;
+ 
+-		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
++		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;
+@@ -1508,7 +1509,7 @@ static int mos7720_startup(struct usb_serial *serial)
+ 	int i;
+ 	char data;
+ 
+-	dbg("%s: Entering ..........", __FUNCTION__);
++	dbg("%s: Entering ..........", __func__);
+ 
+ 	if (!serial) {
+ 		dbg("Invalid Handler");
+@@ -1520,7 +1521,7 @@ static int mos7720_startup(struct usb_serial *serial)
+ 	/* create our private serial structure */
+ 	mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL);
+ 	if (mos7720_serial == NULL) {
+-		err("%s - Out of memory", __FUNCTION__);
++		err("%s - Out of memory", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -1533,7 +1534,7 @@ static int mos7720_startup(struct usb_serial *serial)
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+ 		if (mos7720_port == NULL) {
+-			err("%s - Out of memory", __FUNCTION__);
++			err("%s - Out of memory", __func__);
+ 			usb_set_serial_data(serial, NULL);
+ 			kfree(mos7720_serial);
+ 			return -ENOMEM;
+@@ -1596,9 +1597,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
+ 	.description		= "Moschip 2 port adapter",
+ 	.usb_driver		= &usb_driver,
+ 	.id_table		= moschip_port_id_table,
+-	.num_interrupt_in	= 1,
+-	.num_bulk_in		= 2,
+-	.num_bulk_out		= 2,
+ 	.num_ports		= 2,
+ 	.open			= mos7720_open,
+ 	.close			= mos7720_close,
+@@ -1620,7 +1618,7 @@ static int __init moschip7720_init(void)
+ {
+ 	int retval;
+ 
+-	dbg("%s: Entering ..........", __FUNCTION__);
++	dbg("%s: Entering ..........", __func__);
+ 
+ 	/* Register with the usb serial */
+ 	retval = usb_serial_register(&moschip7720_2port_driver);
+diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
+index aeeb9cb..6bcb82d 100644
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -403,7 +403,7 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
+ {
+ 	struct async_icount *icount;
+ 
+-	dbg("%s - %02x", __FUNCTION__, new_lsr);
++	dbg("%s - %02x", __func__, new_lsr);
+ 
+ 	if (new_lsr & SERIAL_LSR_BI) {
+ 		//
+@@ -449,7 +449,7 @@ static void mos7840_control_callback(struct urb *urb)
+ 	int result = 0;
+ 	int status = urb->status;
+ 
+-	mos7840_port = (struct moschip_port *)urb->context;
++	mos7840_port = urb->context;
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -459,21 +459,21 @@ static void mos7840_control_callback(struct urb *urb)
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+-		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++		dbg("%s - urb shutting down with status: %d", __func__,
+ 		    status);
+ 		return;
+ 	default:
+-		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
++		dbg("%s - nonzero urb status received: %d", __func__,
+ 		    status);
+ 		goto exit;
+ 	}
+ 
+-	dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);
+-	dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,
++	dbg("%s urb buffer size is %d\n", __func__, urb->actual_length);
++	dbg("%s mos7840_port->MsrLsr is %d port %d\n", __func__,
+ 	    mos7840_port->MsrLsr, mos7840_port->port_num);
+ 	data = urb->transfer_buffer;
+ 	regval = (__u8) data[0];
+-	dbg("%s data is %x\n", __FUNCTION__, regval);
++	dbg("%s data is %x\n", __func__, regval);
+ 	if (mos7840_port->MsrLsr == 0)
+ 		mos7840_handle_new_msr(mos7840_port, regval);
+ 	else if (mos7840_port->MsrLsr == 1)
+@@ -487,7 +487,7 @@ exit:
+ 	if (result) {
+ 		dev_err(&urb->dev->dev,
+ 			"%s - Error %d submitting interrupt urb\n",
+-			__FUNCTION__, result);
++			__func__, result);
+ 	}
+ }
+ 
+@@ -542,11 +542,11 @@ static void mos7840_interrupt_callback(struct urb *urb)
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+-		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++		dbg("%s - urb shutting down with status: %d", __func__,
+ 		    status);
+ 		return;
+ 	default:
+-		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
++		dbg("%s - nonzero urb status received: %d", __func__,
+ 		    status);
+ 		goto exit;
+ 	}
+@@ -554,7 +554,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
+ 	length = urb->actual_length;
+ 	data = urb->transfer_buffer;
+ 
+-	serial = (struct usb_serial *)urb->context;
++	serial = urb->context;
+ 
+ 	/* Moschip get 5 bytes
+ 	 * Byte 1 IIR Port 1 (port.number is 0)
+@@ -614,7 +614,7 @@ exit:
+ 	if (result) {
+ 		dev_err(&urb->dev->dev,
+ 			"%s - Error %d submitting interrupt urb\n",
+-			__FUNCTION__, result);
++			__func__, result);
+ 	}
+ }
+ 
+@@ -685,19 +685,19 @@ static void mos7840_bulk_in_callback(struct urb *urb)
+ 		return;
+ 	}
+ 
+-	mos7840_port = (struct moschip_port *)urb->context;
++	mos7840_port = urb->context;
+ 	if (!mos7840_port) {
+ 		dbg("%s", "NULL mos7840_port pointer \n");
+ 		return;
+ 	}
+ 
+ 	port = (struct usb_serial_port *)mos7840_port->port;
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Port Paranoia failed \n");
+ 		return;
+ 	}
+ 
+-	serial = mos7840_get_usb_serial(port, __FUNCTION__);
++	serial = mos7840_get_usb_serial(port, __func__);
+ 	if (!serial) {
+ 		dbg("%s\n", "Bad serial pointer ");
+ 		return;
+@@ -752,7 +752,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
+ 	int status = urb->status;
+ 	int i;
+ 
+-	mos7840_port = (struct moschip_port *)urb->context;
++	mos7840_port = urb->context;
+ 	spin_lock(&mos7840_port->pool_lock);
+ 	for (i = 0; i < NUM_URBS; i++) {
+ 		if (urb == mos7840_port->write_urb_pool[i]) {
+@@ -767,7 +767,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
+ 		return;
+ 	}
+ 
+-	if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(mos7840_port->port, __func__)) {
+ 		dbg("%s", "Port Paranoia failed \n");
+ 		return;
+ 	}
+@@ -815,14 +815,14 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+ 	struct moschip_port *mos7840_port;
+ 	struct moschip_port *port0;
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Port Paranoia failed \n");
+ 		return -ENODEV;
+ 	}
+ 
+ 	serial = port->serial;
+ 
+-	if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
++	if (mos7840_serial_paranoia_check(serial, __func__)) {
+ 		dbg("%s", "Serial Paranoia failed \n");
+ 		return -ENODEV;
+ 	}
+@@ -851,7 +851,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+ 		if (!urb->transfer_buffer) {
+ 			usb_free_urb(urb);
+ 			mos7840_port->write_urb_pool[j] = NULL;
+-			err("%s-out of memory for urb buffers.", __FUNCTION__);
++			err("%s-out of memory for urb buffers.", __func__);
+ 			continue;
+ 		}
+ 	}
+@@ -1039,7 +1039,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+ 					   GFP_KERNEL);
+ 			if (response) {
+ 				err("%s - Error %d submitting interrupt urb",
+-				    __FUNCTION__, response);
++				    __func__, response);
+ 			}
+ 
+ 		}
+@@ -1072,7 +1072,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+ 	    port->bulk_in_endpointAddress);
+ 	response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
+ 	if (response) {
+-		err("%s - Error %d submitting control urb", __FUNCTION__,
++		err("%s - Error %d submitting control urb", __func__,
+ 		    response);
+ 	}
+ 
+@@ -1116,7 +1116,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+ 
+ 	dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Invalid port \n");
+ 		return -1;
+ 	}
+@@ -1134,7 +1134,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+ 		}
+ 	}
+ 	spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
+-	dbg("%s - returns %d", __FUNCTION__, chars);
++	dbg("%s - returns %d", __func__, chars);
+ 	return chars;
+ 
+ }
+@@ -1171,7 +1171,7 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
+ 		/* No activity.. count down section */
+ 		wait--;
+ 		if (wait == 0) {
+-			dbg("%s - TIMEOUT", __FUNCTION__);
++			dbg("%s - TIMEOUT", __func__);
+ 			return;
+ 		} else {
+ 			/* Reset timeout value back to seconds */
+@@ -1195,12 +1195,12 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
+ 
+ 	dbg("%s\n", "mos7840_close:entering...");
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Port Paranoia failed \n");
+ 		return;
+ 	}
+ 
+-	serial = mos7840_get_usb_serial(port, __FUNCTION__);
++	serial = mos7840_get_usb_serial(port, __func__);
+ 	if (!serial) {
+ 		dbg("%s", "Serial Paranoia failed \n");
+ 		return;
+@@ -1314,7 +1314,7 @@ static void mos7840_block_until_chase_response(struct moschip_port
+ 		/* No activity.. count down section */
+ 		wait--;
+ 		if (wait == 0) {
+-			dbg("%s - TIMEOUT", __FUNCTION__);
++			dbg("%s - TIMEOUT", __func__);
+ 			return;
+ 		} else {
+ 			/* Reset timeout value back to seconds */
+@@ -1337,12 +1337,12 @@ static void mos7840_break(struct usb_serial_port *port, int break_state)
+ 	dbg("%s \n", "Entering ...........");
+ 	dbg("mos7840_break: Start\n");
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Port Paranoia failed \n");
+ 		return;
+ 	}
+ 
+-	serial = mos7840_get_usb_serial(port, __FUNCTION__);
++	serial = mos7840_get_usb_serial(port, __func__);
+ 	if (!serial) {
+ 		dbg("%s", "Serial Paranoia failed \n");
+ 		return;
+@@ -1392,7 +1392,7 @@ static int mos7840_write_room(struct usb_serial_port *port)
+ 
+ 	dbg("%s \n", " mos7840_write_room:entering ...........");
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Invalid port \n");
+ 		dbg("%s \n", " mos7840_write_room:leaving ...........");
+ 		return -1;
+@@ -1413,7 +1413,7 @@ static int mos7840_write_room(struct usb_serial_port *port)
+ 	spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
+ 
+ 	room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1;
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 	return room;
+ 
+ }
+@@ -1480,13 +1480,13 @@ static int mos7840_write(struct usb_serial_port *port,
+ 	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+ #endif
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Port Paranoia failed \n");
+ 		return -1;
+ 	}
+ 
+ 	serial = port->serial;
+-	if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
++	if (mos7840_serial_paranoia_check(serial, __func__)) {
+ 		dbg("%s", "Serial Paranoia failed \n");
+ 		return -1;
+ 	}
+@@ -1512,7 +1512,7 @@ static int mos7840_write(struct usb_serial_port *port,
+ 	spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
+ 
+ 	if (urb == NULL) {
+-		dbg("%s - no more free urbs", __FUNCTION__);
++		dbg("%s - no more free urbs", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -1521,7 +1521,7 @@ static int mos7840_write(struct usb_serial_port *port,
+ 		    kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ 
+ 		if (urb->transfer_buffer == NULL) {
+-			err("%s no more kernel memory...", __FUNCTION__);
++			err("%s no more kernel memory...", __func__);
+ 			goto exit;
+ 		}
+ 	}
+@@ -1547,7 +1547,7 @@ static int mos7840_write(struct usb_serial_port *port,
+ 	if (status) {
+ 		mos7840_port->busy[i] = 0;
+ 		err("%s - usb_submit_urb(write bulk) failed with status = %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		bytes_sent = status;
+ 		goto exit;
+ 	}
+@@ -1573,7 +1573,7 @@ static void mos7840_throttle(struct usb_serial_port *port)
+ 	struct tty_struct *tty;
+ 	int status;
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Invalid port \n");
+ 		return;
+ 	}
+@@ -1594,7 +1594,7 @@ static void mos7840_throttle(struct usb_serial_port *port)
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - no tty available", __FUNCTION__);
++		dbg("%s - no tty available", __func__);
+ 		return;
+ 	}
+ 
+@@ -1634,7 +1634,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
+ 	int status;
+ 	struct moschip_port *mos7840_port = mos7840_get_port_private(port);
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Invalid port \n");
+ 		return;
+ 	}
+@@ -1643,7 +1643,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
+ 		return;
+ 
+ 	if (!mos7840_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+@@ -1651,7 +1651,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - no tty available", __FUNCTION__);
++		dbg("%s - no tty available", __func__);
+ 		return;
+ 	}
+ 
+@@ -1688,7 +1688,7 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+ 	int status = 0;
+ 	mos7840_port = mos7840_get_port_private(port);
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (mos7840_port == NULL)
+ 		return -ENODEV;
+@@ -1703,7 +1703,7 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+ 	    | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)
+ 	    | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);
+ 
+-	dbg("%s - 0x%04X", __FUNCTION__, result);
++	dbg("%s - 0x%04X", __func__, result);
+ 
+ 	return result;
+ }
+@@ -1715,13 +1715,14 @@ static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
+ 	unsigned int mcr;
+ 	unsigned int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	mos7840_port = mos7840_get_port_private(port);
+ 
+ 	if (mos7840_port == NULL)
+ 		return -ENODEV;
+ 
++	/* FIXME: What locks the port registers ? */
+ 	mcr = mos7840_port->shadowMCR;
+ 	if (clear & TIOCM_RTS)
+ 		mcr &= ~MCR_RTS;
+@@ -1758,7 +1759,7 @@ static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
+ 					  __u16 * clk_sel_val)
+ {
+ 
+-	dbg("%s - %d", __FUNCTION__, baudRate);
++	dbg("%s - %d", __func__, baudRate);
+ 
+ 	if (baudRate <= 115200) {
+ 		*divisor = 115200 / baudRate;
+@@ -1841,12 +1842,12 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
+ 		return -1;
+ 
+ 	port = (struct usb_serial_port *)mos7840_port->port;
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Invalid port \n");
+ 		return -1;
+ 	}
+ 
+-	if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
++	if (mos7840_serial_paranoia_check(port->serial, __func__)) {
+ 		dbg("%s", "Invalid Serial \n");
+ 		return -1;
+ 	}
+@@ -1855,7 +1856,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
+ 
+ 	number = mos7840_port->port->number - mos7840_port->port->serial->minor;
+ 
+-	dbg("%s - port = %d, baud = %d", __FUNCTION__,
++	dbg("%s - port = %d, baud = %d", __func__,
+ 	    mos7840_port->port->number, baudRate);
+ 	//reset clk_uart_sel in spregOffset
+ 	if (baudRate > 115200) {
+@@ -1915,7 +1916,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
+ 		/* Calculate the Divisor */
+ 
+ 		if (status) {
+-			err("%s - bad baud rate", __FUNCTION__);
++			err("%s - bad baud rate", __func__);
+ 			dbg("%s\n", "bad baud rate");
+ 			return status;
+ 		}
+@@ -1969,22 +1970,22 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+ 
+ 	port = (struct usb_serial_port *)mos7840_port->port;
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Invalid port \n");
+ 		return;
+ 	}
+ 
+-	if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
++	if (mos7840_serial_paranoia_check(port->serial, __func__)) {
+ 		dbg("%s", "Invalid Serial \n");
+ 		return;
+ 	}
+ 
+ 	serial = port->serial;
+ 
+-	dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);
++	dbg("%s - port %d", __func__, mos7840_port->port->number);
+ 
+ 	if (!mos7840_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+@@ -2023,14 +2024,14 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+ 	if (cflag & PARENB) {
+ 		if (cflag & PARODD) {
+ 			lParity = LCR_PAR_ODD;
+-			dbg("%s - parity = odd", __FUNCTION__);
++			dbg("%s - parity = odd", __func__);
+ 		} else {
+ 			lParity = LCR_PAR_EVEN;
+-			dbg("%s - parity = even", __FUNCTION__);
++			dbg("%s - parity = even", __func__);
+ 		}
+ 
+ 	} else {
+-		dbg("%s - parity = none", __FUNCTION__);
++		dbg("%s - parity = none", __func__);
+ 	}
+ 
+ 	if (cflag & CMSPAR) {
+@@ -2040,10 +2041,10 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+ 	/* Change the Stop bit */
+ 	if (cflag & CSTOPB) {
+ 		lStop = LCR_STOP_2;
+-		dbg("%s - stop bits = 2", __FUNCTION__);
++		dbg("%s - stop bits = 2", __func__);
+ 	} else {
+ 		lStop = LCR_STOP_1;
+-		dbg("%s - stop bits = 1", __FUNCTION__);
++		dbg("%s - stop bits = 1", __func__);
+ 	}
+ 
+ 	/* Update the LCR with the correct value */
+@@ -2100,7 +2101,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+ 		baud = 9600;
+ 	}
+ 
+-	dbg("%s - baud rate = %d", __FUNCTION__, baud);
++	dbg("%s - baud rate = %d", __func__, baud);
+ 	status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
+ 
+ 	/* Enable Interrupts */
+@@ -2140,14 +2141,14 @@ static void mos7840_set_termios(struct usb_serial_port *port,
+ 	struct moschip_port *mos7840_port;
+ 	struct tty_struct *tty;
+ 	dbg("mos7840_set_termios: START\n");
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Invalid port \n");
+ 		return;
+ 	}
+ 
+ 	serial = port->serial;
+ 
+-	if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
++	if (mos7840_serial_paranoia_check(serial, __func__)) {
+ 		dbg("%s", "Invalid Serial \n");
+ 		return;
+ 	}
+@@ -2160,7 +2161,7 @@ static void mos7840_set_termios(struct usb_serial_port *port,
+ 	tty = port->tty;
+ 
+ 	if (!mos7840_port->open) {
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		return;
+ 	}
+ 
+@@ -2168,11 +2169,11 @@ static void mos7840_set_termios(struct usb_serial_port *port,
+ 
+ 	cflag = tty->termios->c_cflag;
+ 
+-	dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
++	dbg("%s - clfag %08x iflag %08x", __func__,
+ 	    tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
+-	dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
++	dbg("%s - old clfag %08x old iflag %08x", __func__,
+ 	    old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* change the port settings to the new ones specified */
+ 
+@@ -2213,7 +2214,7 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
+ 
+ 	count = mos7840_chars_in_buffer(mos7840_port->port);
+ 	if (count == 0) {
+-		dbg("%s -- Empty", __FUNCTION__);
++		dbg("%s -- Empty", __func__);
+ 		result = TIOCSER_TEMT;
+ 	}
+ 
+@@ -2240,7 +2241,7 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
+ 		return -1;
+ 
+ 	port = (struct usb_serial_port *)mos7840_port->port;
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Invalid port \n");
+ 		return -1;
+ 	}
+@@ -2314,7 +2315,7 @@ static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
+ 	    |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)	/* 0x080 */
+ 	    |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);	/* 0x100 */
+ 
+-	dbg("%s -- %x", __FUNCTION__, result);
++	dbg("%s -- %x", __func__, result);
+ 
+ 	if (copy_to_user(value, &result, sizeof(int)))
+ 		return -EFAULT;
+@@ -2371,7 +2372,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+ 	struct serial_icounter_struct icount;
+ 	int mosret = 0;
+ 
+-	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++	if (mos7840_port_paranoia_check(port, __func__)) {
+ 		dbg("%s", "Invalid port \n");
+ 		return -1;
+ 	}
+@@ -2383,39 +2384,39 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+ 
+ 	tty = mos7840_port->port->tty;
+ 
+-	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+ 
+ 	switch (cmd) {
+ 		/* return number of bytes available */
+ 
+ 	case TIOCSERGETLSR:
+-		dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
++		dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
+ 		return mos7840_get_lsr_info(mos7840_port, argp);
+ 		return 0;
+ 
+ 	case TIOCMBIS:
+ 	case TIOCMBIC:
+ 	case TIOCMSET:
+-		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
++		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
+ 		    port->number);
+ 		mosret =
+ 		    mos7840_set_modem_info(mos7840_port, cmd, argp);
+ 		return mosret;
+ 
+ 	case TIOCMGET:
+-		dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
++		dbg("%s (%d) TIOCMGET", __func__, port->number);
+ 		return mos7840_get_modem_info(mos7840_port, argp);
+ 
+ 	case TIOCGSERIAL:
+-		dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
++		dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ 		return mos7840_get_serial_info(mos7840_port, argp);
+ 
+ 	case TIOCSSERIAL:
+-		dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++		dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
+ 		break;
+ 
+ 	case TIOCMIWAIT:
+-		dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
++		dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ 		cprev = mos7840_port->icount;
+ 		while (1) {
+ 			//interruptible_sleep_on(&mos7840_port->delta_msr_wait);
+@@ -2458,7 +2459,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+ 		icount.brk = cnow.brk;
+ 		icount.buf_overrun = cnow.buf_overrun;
+ 
+-		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
++		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;
+@@ -2521,7 +2522,7 @@ static int mos7840_startup(struct usb_serial *serial)
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+ 		if (mos7840_port == NULL) {
+-			err("%s - Out of memory", __FUNCTION__);
++			err("%s - Out of memory", __func__);
+ 			status = -ENOMEM;
+ 			i--; /* don't follow NULL pointer cleaning up */
+ 			goto error;
+@@ -2799,12 +2800,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
+ 	.description = DRIVER_DESC,
+ 	.usb_driver = &io_driver,
+ 	.id_table = moschip_port_id_table,
+-	.num_interrupt_in = 1,	//NUM_DONT_CARE,//1,
+-#ifdef check
+-	.num_bulk_in = 4,
+-	.num_bulk_out = 4,
+ 	.num_ports = 4,
+-#endif
+ 	.open = mos7840_open,
+ 	.close = mos7840_close,
+ 	.write = mos7840_write,
+diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
+index 7f337c9..43c8894 100644
+--- a/drivers/usb/serial/navman.c
++++ b/drivers/usb/serial/navman.c
+@@ -6,6 +6,10 @@
+  *	This program is free software; you can redistribute it and/or
+  *	modify it under the terms of the GNU General Public License
+  *	version 2 as published by the Free Software Foundation.
++ *
++ * TODO:
++ *	Add termios method that uses copy_hw but also kills all echo
++ *	flags as the navman is rx only so cannot echo.
+  */
+ 
+ #include <linux/kernel.h>
+@@ -49,15 +53,15 @@ static void navman_read_int_callback(struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	default:
+ 		dbg("%s - nonzero urb status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		goto exit;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++	usb_serial_debug_data(debug, &port->dev, __func__,
+ 			      urb->actual_length, data);
+ 
+ 	tty = port->tty;
+@@ -72,29 +76,29 @@ exit:
+ 	if (result)
+ 		dev_err(&urb->dev->dev,
+ 			"%s - Error %d submitting interrupt urb\n",
+-			__FUNCTION__, result);
++			__func__, result);
+ }
+ 
+ static int navman_open(struct usb_serial_port *port, struct file *filp)
+ {
+ 	int result = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (port->interrupt_in_urb) {
+-		dbg("%s - adding interrupt input for treo", __FUNCTION__);
++		dbg("%s - adding interrupt input for treo", __func__);
+ 		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ 		if (result)
+ 			dev_err(&port->dev,
+ 				"%s - failed submitting interrupt urb, error %d\n",
+-				__FUNCTION__, result);
++				__func__, result);
+ 	}
+ 	return result;
+ }
+ 
+ static void navman_close(struct usb_serial_port *port, struct file *filp)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	usb_kill_urb(port->interrupt_in_urb);
+ }
+@@ -102,16 +106,12 @@ static void navman_close(struct usb_serial_port *port, struct file *filp)
+ static int navman_write(struct usb_serial_port *port,
+ 			const unsigned char *buf, int count)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/*
+ 	 * This device can't write any data, only read from the device
+-	 * so we just silently eat all data sent to us and say it was
+-	 * successfully sent.
+-	 * Evil, I know, but do you have a better idea?
+ 	 */
+-
+-	return count;
++	return -EOPNOTSUPP;
+ }
+ 
+ static struct usb_serial_driver navman_device = {
+@@ -121,9 +121,6 @@ static struct usb_serial_driver navman_device = {
+ 	},
+ 	.id_table =		id_table,
+ 	.usb_driver =		&navman_driver,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		1,
+ 	.open =			navman_open,
+ 	.close = 		navman_close,
+diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
+index ee94d96..7b7422f 100644
+--- a/drivers/usb/serial/omninet.c
++++ b/drivers/usb/serial/omninet.c
+@@ -95,9 +95,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
+ 	.description =		"ZyXEL - omni.net lcd plus usb",
+ 	.usb_driver =		&omninet_driver,
+ 	.id_table =		id_table,
+-	.num_interrupt_in =	1,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		2,
+ 	.num_ports =		1,
+ 	.attach =		omninet_attach,
+ 	.open =			omninet_open,
+@@ -153,7 +150,7 @@ static int omninet_attach (struct usb_serial *serial)
+ 
+ 	od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
+ 	if( !od ) {
+-		err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct omninet_data));
++		err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct omninet_data));
+ 		return -ENOMEM;
+ 	}
+ 	usb_set_serial_port_data(port, od);
+@@ -166,7 +163,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
+ 	struct usb_serial_port	*wport;
+ 	int			result = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	wport = serial->port[1];
+ 	wport->tty = port->tty;
+@@ -178,7 +175,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
+ 		      omninet_read_bulk_callback, port);
+ 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (result) {
+-		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
++		err("%s - failed submitting read urb, error %d", __func__, result);
+ 	}
+ 
+ 	return result;
+@@ -186,7 +183,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
+ 
+ static void omninet_close (struct usb_serial_port *port, struct file * filp)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	usb_kill_urb(port->read_urb);
+ }
+ 
+@@ -197,18 +194,18 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp)
+ 
+ static void omninet_read_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port 	*port 	= (struct usb_serial_port *)urb->context;
++	struct usb_serial_port 	*port 	= urb->context;
+ 	unsigned char 		*data 	= urb->transfer_buffer;
+ 	struct omninet_header 	*header = (struct omninet_header *) &data[0];
+ 	int status = urb->status;
+ 	int i;
+ 	int result;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+@@ -236,7 +233,7 @@ static void omninet_read_bulk_callback (struct urb *urb)
+ 		      omninet_read_bulk_callback, port);
+ 	result = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if (result)
+-		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++		err("%s - failed resubmitting read urb, error %d", __func__, result);
+ 
+ 	return;
+ }
+@@ -251,17 +248,17 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
+ 
+ 	int			result;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (count == 0) {
+-		dbg("%s - write request of 0 bytes", __FUNCTION__);
++		dbg("%s - write request of 0 bytes", __func__);
+ 		return (0);
+ 	}
+ 
+ 	spin_lock_bh(&wport->lock);
+ 	if (wport->write_urb_busy) {
+ 		spin_unlock_bh(&wport->lock);
+-		dbg("%s - already writing", __FUNCTION__);
++		dbg("%s - already writing", __func__);
+ 		return 0;
+ 	}
+ 	wport->write_urb_busy = 1;
+@@ -271,7 +268,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
+ 
+ 	memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, wport->write_urb->transfer_buffer);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, wport->write_urb->transfer_buffer);
+ 
+ 	header->oh_seq 	= od->od_outseq++;
+ 	header->oh_len 	= count;
+@@ -285,7 +282,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
+ 	result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
+ 	if (result) {
+ 		wport->write_urb_busy = 0;
+-		err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++		err("%s - failed submitting write urb, error %d", __func__, result);
+ 	} else
+ 		result = count;
+ 
+@@ -298,12 +295,13 @@ static int omninet_write_room (struct usb_serial_port *port)
+ 	struct usb_serial 	*serial = port->serial;
+ 	struct usb_serial_port 	*wport 	= serial->port[1];
+ 
+-	int room = 0; // Default: no room
++	int room = 0; /* Default: no room */
+ 
++	/* FIXME: no consistent locking for write_urb_busy */
+ 	if (wport->write_urb_busy)
+ 		room = wport->bulk_out_size - OMNINET_HEADERLEN;
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 
+ 	return (room);
+ }
+@@ -311,15 +309,15 @@ static int omninet_write_room (struct usb_serial_port *port)
+ static void omninet_write_bulk_callback (struct urb *urb)
+ {
+ /*	struct omninet_header	*header = (struct omninet_header  *) urb->transfer_buffer; */
+-	struct usb_serial_port 	*port   = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port 	*port   =  urb->context;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %0x\n", __FUNCTION__, port->number);
++	dbg("%s - port %0x\n", __func__, port->number);
+ 
+ 	port->write_urb_busy = 0;
+ 	if (status) {
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+@@ -331,7 +329,7 @@ static void omninet_shutdown (struct usb_serial *serial)
+ {
+ 	struct usb_serial_port *wport = serial->port[1];
+ 	struct usb_serial_port *port = serial->port[0];
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	usb_kill_urb(wport->write_urb);
+ 	kfree(usb_get_serial_port_data(port));
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index d101025..e4be2d4 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -28,7 +28,7 @@
+   device features.
+ */
+ 
+-#define DRIVER_VERSION "v0.7.1"
++#define DRIVER_VERSION "v0.7.2"
+ #define DRIVER_AUTHOR "Matthias Urlichs <smurf at smurf.noris.de>"
+ #define DRIVER_DESC "USB Driver for GSM modems"
+ 
+@@ -325,9 +325,6 @@ static struct usb_serial_driver option_1port_device = {
+ 	.description       = "GSM modem (1-port)",
+ 	.usb_driver        = &option_driver,
+ 	.id_table          = option_ids,
+-	.num_interrupt_in  = NUM_DONT_CARE,
+-	.num_bulk_in       = NUM_DONT_CARE,
+-	.num_bulk_out      = NUM_DONT_CARE,
+ 	.num_ports         = 1,
+ 	.open              = option_open,
+ 	.close             = option_close,
+@@ -411,24 +408,24 @@ module_exit(option_exit);
+ 
+ static void option_rx_throttle(struct usb_serial_port *port)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ }
+ 
+ static void option_rx_unthrottle(struct usb_serial_port *port)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ }
+ 
+ static void option_break_ctl(struct usb_serial_port *port, int break_state)
+ {
+ 	/* Unfortunately, I don't know how to send a break */
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ }
+ 
+ static void option_set_termios(struct usb_serial_port *port,
+ 			struct ktermios *old_termios)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	/* Doesn't support option setting */
+ 	tty_termios_copy_hw(port->tty->termios, old_termios);
+ 	option_send_setup(port);
+@@ -458,6 +455,7 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+ 
+ 	portdata = usb_get_serial_port_data(port);
+ 
++	/* FIXME: what locks portdata fields ? */
+ 	if (set & TIOCM_RTS)
+ 		portdata->rts_state = 1;
+ 	if (set & TIOCM_DTR)
+@@ -488,7 +486,7 @@ static int option_write(struct usb_serial_port *port,
+ 
+ 	portdata = usb_get_serial_port_data(port);
+ 
+-	dbg("%s: write (%d chars)", __FUNCTION__, count);
++	dbg("%s: write (%d chars)", __func__, count);
+ 
+ 	i = 0;
+ 	left = count;
+@@ -509,7 +507,7 @@ static int option_write(struct usb_serial_port *port,
+ 			dbg("usb_write %p failed (err=%d)",
+ 				this_urb, this_urb->status);
+ 
+-		dbg("%s: endpoint %d buf %d", __FUNCTION__,
++		dbg("%s: endpoint %d buf %d", __func__,
+ 			usb_pipeendpoint(this_urb->pipe), i);
+ 
+ 		/* send the data */
+@@ -531,7 +529,7 @@ static int option_write(struct usb_serial_port *port,
+ 	}
+ 
+ 	count -= left;
+-	dbg("%s: wrote (did %d)", __FUNCTION__, count);
++	dbg("%s: wrote (did %d)", __func__, count);
+ 	return count;
+ }
+ 
+@@ -544,14 +542,14 @@ static void option_indat_callback(struct urb *urb)
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int status = urb->status;
+ 
+-	dbg("%s: %p", __FUNCTION__, urb);
++	dbg("%s: %p", __func__, urb);
+ 
+ 	endpoint = usb_pipeendpoint(urb->pipe);
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 
+ 	if (status) {
+ 		dbg("%s: nonzero status: %d on endpoint %02x.",
+-		    __FUNCTION__, status, endpoint);
++		    __func__, status, endpoint);
+ 	} else {
+ 		tty = port->tty;
+ 		if (urb->actual_length) {
+@@ -559,7 +557,7 @@ static void option_indat_callback(struct urb *urb)
+ 			tty_insert_flip_string(tty, data, urb->actual_length);
+ 			tty_flip_buffer_push(tty);
+ 		} else {
+-			dbg("%s: empty read urb received", __FUNCTION__);
++			dbg("%s: empty read urb received", __func__);
+ 		}
+ 
+ 		/* Resubmit urb so we continue receiving */
+@@ -567,7 +565,7 @@ static void option_indat_callback(struct urb *urb)
+ 			err = usb_submit_urb(urb, GFP_ATOMIC);
+ 			if (err)
+ 				printk(KERN_ERR "%s: resubmit read urb failed. "
+-					"(%d)", __FUNCTION__, err);
++					"(%d)", __func__, err);
+ 		}
+ 	}
+ 	return;
+@@ -579,9 +577,9 @@ static void option_outdat_callback(struct urb *urb)
+ 	struct option_port_private *portdata;
+ 	int i;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 
+ 	usb_serial_port_softint(port);
+ 
+@@ -599,19 +597,19 @@ static void option_instat_callback(struct urb *urb)
+ {
+ 	int err;
+ 	int status = urb->status;
+-	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port *port =  urb->context;
+ 	struct option_port_private *portdata = usb_get_serial_port_data(port);
+ 	struct usb_serial *serial = port->serial;
+ 
+-	dbg("%s", __FUNCTION__);
+-	dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
++	dbg("%s", __func__);
++	dbg("%s: urb %p port %p has data %p", __func__,urb,port,portdata);
+ 
+ 	if (status == 0) {
+ 		struct usb_ctrlrequest *req_pkt =
+ 				(struct usb_ctrlrequest *)urb->transfer_buffer;
+ 
+ 		if (!req_pkt) {
+-			dbg("%s: NULL req_pkt\n", __FUNCTION__);
++			dbg("%s: NULL req_pkt\n", __func__);
+ 			return;
+ 		}
+ 		if ((req_pkt->bRequestType == 0xA1) &&
+@@ -621,7 +619,7 @@ static void option_instat_callback(struct urb *urb)
+ 					urb->transfer_buffer +
+ 					sizeof(struct usb_ctrlrequest));
+ 
+-			dbg("%s: signal x%x", __FUNCTION__, signals);
++			dbg("%s: signal x%x", __func__, signals);
+ 
+ 			old_dcd_state = portdata->dcd_state;
+ 			portdata->cts_state = 1;
+@@ -633,11 +631,11 @@ static void option_instat_callback(struct urb *urb)
+ 					old_dcd_state && !portdata->dcd_state)
+ 				tty_hangup(port->tty);
+ 		} else {
+-			dbg("%s: type %x req %x", __FUNCTION__,
++			dbg("%s: type %x req %x", __func__,
+ 				req_pkt->bRequestType,req_pkt->bRequest);
+ 		}
+ 	} else
+-		dbg("%s: error %d", __FUNCTION__, status);
++		dbg("%s: error %d", __func__, status);
+ 
+ 	/* Resubmit urb so we continue receiving IRQ data */
+ 	if (status != -ESHUTDOWN) {
+@@ -645,7 +643,7 @@ static void option_instat_callback(struct urb *urb)
+ 		err = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (err)
+ 			dbg("%s: resubmit intr urb failed. (%d)",
+-				__FUNCTION__, err);
++				__func__, err);
+ 	}
+ }
+ 
+@@ -658,13 +656,14 @@ static int option_write_room(struct usb_serial_port *port)
+ 
+ 	portdata = usb_get_serial_port_data(port);
+ 
++
+ 	for (i=0; i < N_OUT_URB; i++) {
+ 		this_urb = portdata->out_urbs[i];
+ 		if (this_urb && !test_bit(i, &portdata->out_busy))
+ 			data_len += OUT_BUFLEN;
+ 	}
+ 
+-	dbg("%s: %d", __FUNCTION__, data_len);
++	dbg("%s: %d", __func__, data_len);
+ 	return data_len;
+ }
+ 
+@@ -679,10 +678,12 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
+ 
+ 	for (i=0; i < N_OUT_URB; i++) {
+ 		this_urb = portdata->out_urbs[i];
++		/* FIXME: This locking is insufficient as this_urb may
++		   go unused during the test */
+ 		if (this_urb && test_bit(i, &portdata->out_busy))
+ 			data_len += this_urb->transfer_buffer_length;
+ 	}
+-	dbg("%s: %d", __FUNCTION__, data_len);
++	dbg("%s: %d", __func__, data_len);
+ 	return data_len;
+ }
+ 
+@@ -695,7 +696,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
+ 
+ 	portdata = usb_get_serial_port_data(port);
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* Set some sane defaults */
+ 	portdata->rts_state = 1;
+@@ -707,7 +708,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
+ 		if (! urb)
+ 			continue;
+ 		if (urb->dev != serial->dev) {
+-			dbg("%s: dev %p != %p", __FUNCTION__,
++			dbg("%s: dev %p != %p", __func__,
+ 				urb->dev, serial->dev);
+ 			continue;
+ 		}
+@@ -721,7 +722,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
+ 		err = usb_submit_urb(urb, GFP_KERNEL);
+ 		if (err) {
+ 			dbg("%s: submit urb %d failed (%d) %d",
+-				__FUNCTION__, i, err,
++				__func__, i, err,
+ 				urb->transfer_buffer_length);
+ 		}
+ 	}
+@@ -749,7 +750,7 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
+ 	struct usb_serial *serial = port->serial;
+ 	struct option_port_private *portdata;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	portdata = usb_get_serial_port_data(port);
+ 
+ 	portdata->rts_state = 0;
+@@ -782,7 +783,7 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
+ 
+ 	urb = usb_alloc_urb(0, GFP_KERNEL);		/* No ISO */
+ 	if (urb == NULL) {
+-		dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
++		dbg("%s: alloc for endpoint %d failed.", __func__, endpoint);
+ 		return NULL;
+ 	}
+ 
+@@ -801,7 +802,7 @@ static void option_setup_urbs(struct usb_serial *serial)
+ 	struct usb_serial_port *port;
+ 	struct option_port_private *portdata;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	for (i = 0; i < serial->num_ports; i++) {
+ 		port = serial->port[i];
+@@ -823,15 +824,18 @@ static void option_setup_urbs(struct usb_serial *serial)
+ 	}
+ }
+ 
++
++/** send RTS/DTR state to the port.
++ *
++ * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
++ * CDC.
++*/
+ static int option_send_setup(struct usb_serial_port *port)
+ {
+ 	struct usb_serial *serial = port->serial;
+ 	struct option_port_private *portdata;
+-
+-	dbg("%s", __FUNCTION__);
+-
+-	if (port->number != 0)
+-		return 0;
++	int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
++	dbg("%s", __func__);
+ 
+ 	portdata = usb_get_serial_port_data(port);
+ 
+@@ -844,7 +848,7 @@ static int option_send_setup(struct usb_serial_port *port)
+ 
+ 		return usb_control_msg(serial->dev,
+ 				usb_rcvctrlpipe(serial->dev, 0),
+-				0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
++				0x22,0x21,val,ifNum,NULL,0,USB_CTRL_SET_TIMEOUT);
+ 	}
+ 
+ 	return 0;
+@@ -857,7 +861,7 @@ static int option_startup(struct usb_serial *serial)
+ 	struct option_port_private *portdata;
+ 	u8 *buffer;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* Now setup per port private data */
+ 	for (i = 0; i < serial->num_ports; i++) {
+@@ -865,7 +869,7 @@ static int option_startup(struct usb_serial *serial)
+ 		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+ 		if (!portdata) {
+ 			dbg("%s: kmalloc for option_port_private (%d) failed!.",
+-					__FUNCTION__, i);
++					__func__, i);
+ 			return (1);
+ 		}
+ 
+@@ -890,7 +894,7 @@ static int option_startup(struct usb_serial *serial)
+ 		err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ 		if (err)
+ 			dbg("%s: submit irq_in urb failed %d",
+-				__FUNCTION__, err);
++				__func__, err);
+ 	}
+ 
+ 	option_setup_urbs(serial);
+@@ -914,7 +918,7 @@ static void option_shutdown(struct usb_serial *serial)
+ 	struct usb_serial_port *port;
+ 	struct option_port_private *portdata;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* Stop reading/writing urbs */
+ 	for (i = 0; i < serial->num_ports; ++i) {
+diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
+index a3847d6..d92bb65 100644
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -179,9 +179,6 @@ static struct usb_serial_driver oti6858_device = {
+ 		.name =		"oti6858",
+ 	},
+ 	.id_table =		id_table,
+-	.num_interrupt_in =	1,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.open =			oti6858_open,
+ 	.close =		oti6858_close,
+@@ -238,10 +235,10 @@ static void setup_line(struct work_struct *work)
+ 	unsigned long flags;
+ 	int result;
+ 
+-	dbg("%s(port = %d)", __FUNCTION__, port->number);
++	dbg("%s(port = %d)", __func__, port->number);
+ 
+ 	if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+-		dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
++		dev_err(&port->dev, "%s(): out of memory!\n", __func__);
+ 		/* we will try again */
+ 		schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+ 		return;
+@@ -256,7 +253,7 @@ static void setup_line(struct work_struct *work)
+ 				100);
+ 
+ 	if (result != OTI6858_CTRL_PKT_SIZE) {
+-		dev_err(&port->dev, "%s(): error reading status\n", __FUNCTION__);
++		dev_err(&port->dev, "%s(): error reading status\n", __func__);
+ 		kfree(new_setup);
+ 		/* we will try again */
+ 		schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+@@ -289,12 +286,12 @@ static void setup_line(struct work_struct *work)
+ 	priv->setup_done = 1;
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	dbg("%s(): submitting interrupt urb", __FUNCTION__);
++	dbg("%s(): submitting interrupt urb", __func__);
+ 	port->interrupt_in_urb->dev = port->serial->dev;
+ 	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ 	if (result != 0) {
+ 		dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+-				" with error %d\n", __FUNCTION__, result);
++				" with error %d\n", __func__, result);
+ 	}
+ }
+ 
+@@ -306,7 +303,7 @@ void send_data(struct work_struct *work)
+ 	unsigned long flags;
+ 	unsigned char allow;
+ 
+-	dbg("%s(port = %d)", __FUNCTION__, port->number);
++	dbg("%s(port = %d)", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (priv->flags.write_urb_in_use) {
+@@ -334,12 +331,12 @@ void send_data(struct work_struct *work)
+ 	if (count == 0) {
+ 		priv->flags.write_urb_in_use = 0;
+ 
+-		dbg("%s(): submitting interrupt urb", __FUNCTION__);
++		dbg("%s(): submitting interrupt urb", __func__);
+ 		port->interrupt_in_urb->dev = port->serial->dev;
+ 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ 		if (result != 0) {
+ 			dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+-				" with error %d\n", __FUNCTION__, result);
++				" with error %d\n", __func__, result);
+ 		}
+ 		return;
+ 	}
+@@ -353,7 +350,7 @@ void send_data(struct work_struct *work)
+ 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 	if (result != 0) {
+ 		dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+-			       " with error %d\n", __FUNCTION__, result);
++			       " with error %d\n", __func__, result);
+ 		priv->flags.write_urb_in_use = 0;
+ 	}
+ 
+@@ -404,7 +401,7 @@ static int oti6858_write(struct usb_serial_port *port,
+ 	struct oti6858_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s(port = %d, count = %d)", __FUNCTION__, port->number, count);
++	dbg("%s(port = %d, count = %d)", __func__, port->number, count);
+ 
+ 	if (!count)
+ 		return count;
+@@ -422,7 +419,7 @@ static int oti6858_write_room(struct usb_serial_port *port)
+ 	int room = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s(port = %d)", __FUNCTION__, port->number);
++	dbg("%s(port = %d)", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	room = oti6858_buf_space_avail(priv->buf);
+@@ -437,7 +434,7 @@ static int oti6858_chars_in_buffer(struct usb_serial_port *port)
+ 	int chars = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s(port = %d)", __FUNCTION__, port->number);
++	dbg("%s(port = %d)", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	chars = oti6858_buf_data_avail(priv->buf);
+@@ -456,10 +453,10 @@ static void oti6858_set_termios(struct usb_serial_port *port,
+ 	u16 divisor;
+ 	int br;
+ 
+-	dbg("%s(port = %d)", __FUNCTION__, port->number);
++	dbg("%s(port = %d)", __func__, port->number);
+ 
+ 	if (!port->tty || !port->tty->termios) {
+-		dbg("%s(): no tty structures", __FUNCTION__);
++		dbg("%s(): no tty structures", __func__);
+ 		return;
+ 	}
+ 
+@@ -575,7 +572,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+ 	unsigned long flags;
+ 	int result;
+ 
+-	dbg("%s(port = %d)", __FUNCTION__, port->number);
++	dbg("%s(port = %d)", __func__, port->number);
+ 
+ 	usb_clear_halt(serial->dev, port->write_urb->pipe);
+ 	usb_clear_halt(serial->dev, port->read_urb->pipe);
+@@ -584,7 +581,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+ 		return 0;
+ 
+ 	if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+-		dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
++		dev_err(&port->dev, "%s(): out of memory!\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -613,12 +610,12 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 	kfree(buf);
+ 
+-	dbg("%s(): submitting interrupt urb", __FUNCTION__);
++	dbg("%s(): submitting interrupt urb", __func__);
+ 	port->interrupt_in_urb->dev = serial->dev;
+ 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ 	if (result != 0) {
+ 		dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+-			       " with error %d\n", __FUNCTION__, result);
++			       " with error %d\n", __func__, result);
+ 		oti6858_close(port, NULL);
+ 		return -EPROTO;
+ 	}
+@@ -637,14 +634,14 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+ 	long timeout;
+ 	wait_queue_t wait;
+ 
+-	dbg("%s(port = %d)", __FUNCTION__, port->number);
++	dbg("%s(port = %d)", __func__, port->number);
+ 
+ 	/* wait for data to drain from the buffer */
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	timeout = 30 * HZ;	/* PL2303_CLOSING_WAIT */
+ 	init_waitqueue_entry(&wait, current);
+ 	add_wait_queue(&port->tty->write_wait, &wait);
+-	dbg("%s(): entering wait loop", __FUNCTION__);
++	dbg("%s(): entering wait loop", __func__);
+ 	for (;;) {
+ 		set_current_state(TASK_INTERRUPTIBLE);
+ 		if (oti6858_buf_data_avail(priv->buf) == 0
+@@ -657,7 +654,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+ 	}
+ 	set_current_state(TASK_RUNNING);
+ 	remove_wait_queue(&port->tty->write_wait, &wait);
+-	dbg("%s(): after wait loop", __FUNCTION__);
++	dbg("%s(): after wait loop", __func__);
+ 
+ 	/* clear out any remaining data in the buffer */
+ 	oti6858_buf_clear(priv->buf);
+@@ -678,7 +675,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+ 	*/
+ 		timeout = 2*HZ;
+ 	schedule_timeout_interruptible(timeout);
+-	dbg("%s(): after schedule_timeout_interruptible()", __FUNCTION__);
++	dbg("%s(): after schedule_timeout_interruptible()", __func__);
+ 
+ 	/* cancel scheduled setup */
+ 	cancel_delayed_work(&priv->delayed_setup_work);
+@@ -686,7 +683,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+ 	flush_scheduled_work();
+ 
+ 	/* shutdown our urbs */
+-	dbg("%s(): shutting down urbs", __FUNCTION__);
++	dbg("%s(): shutting down urbs", __func__);
+ 	usb_kill_urb(port->write_urb);
+ 	usb_kill_urb(port->read_urb);
+ 	usb_kill_urb(port->interrupt_in_urb);
+@@ -709,7 +706,7 @@ static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+ 	u8 control;
+ 
+ 	dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
+-				__FUNCTION__, port->number, set, clear);
++				__func__, port->number, set, clear);
+ 
+ 	if (!usb_get_intfdata(port->serial->interface))
+ 		return -ENODEV;
+@@ -741,7 +738,7 @@ static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+ 	unsigned pin_state;
+ 	unsigned result = 0;
+ 
+-	dbg("%s(port = %d)", __FUNCTION__, port->number);
++	dbg("%s(port = %d)", __func__, port->number);
+ 
+ 	if (!usb_get_intfdata(port->serial->interface))
+ 		return -ENODEV;
+@@ -764,7 +761,7 @@ static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+ 	if ((pin_state & PIN_DCD) != 0)
+ 		result |= TIOCM_CD;
+ 
+-	dbg("%s() = 0x%08x", __FUNCTION__, result);
++	dbg("%s() = 0x%08x", __func__, result);
+ 
+ 	return result;
+ }
+@@ -811,13 +808,9 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+ 	unsigned int x;
+ 
+ 	dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
+-				__FUNCTION__, port->number, cmd, arg);
++				__func__, port->number, cmd, arg);
+ 
+ 	switch (cmd) {
+-		case TCFLSH:
+-			/* FIXME */
+-			return 0;
+-
+ 		case TIOCMBIS:
+ 			if (copy_from_user(&x, user_arg, sizeof(x)))
+ 				return -EFAULT;
+@@ -829,11 +822,11 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+ 			return oti6858_tiocmset(port, NULL, 0, x);
+ 
+ 		case TIOCMIWAIT:
+-			dbg("%s(): TIOCMIWAIT", __FUNCTION__);
++			dbg("%s(): TIOCMIWAIT", __func__);
+ 			return wait_modem_info(port, arg);
+ 
+ 		default:
+-			dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd);
++			dbg("%s(): 0x%04x not supported", __func__, cmd);
+ 			break;
+ 	}
+ 
+@@ -844,10 +837,10 @@ static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
+ {
+ 	int state;
+ 
+-	dbg("%s(port = %d)", __FUNCTION__, port->number);
++	dbg("%s(port = %d)", __func__, port->number);
+ 
+ 	state = (break_state == 0) ? 0 : 1;
+-	dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off");
++	dbg("%s(): turning break %s", __func__, state ? "on" : "off");
+ 
+ 	/* FIXME */
+ /*
+@@ -855,7 +848,7 @@ static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
+ 				  BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+ 				  0, NULL, 0, 100);
+ 	if (result != 0)
+-		dbg("%s(): error sending break", __FUNCTION__);
++		dbg("%s(): error sending break", __func__);
+  */
+ }
+ 
+@@ -864,7 +857,7 @@ static void oti6858_shutdown(struct usb_serial *serial)
+ 	struct oti6858_private *priv;
+ 	int i;
+ 
+-	dbg("%s()", __FUNCTION__);
++	dbg("%s()", __func__);
+ 
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		priv = usb_get_serial_port_data(serial->port[i]);
+@@ -878,13 +871,13 @@ static void oti6858_shutdown(struct usb_serial *serial)
+ 
+ static void oti6858_read_int_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port *port =  urb->context;
+ 	struct oti6858_private *priv = usb_get_serial_port_data(port);
+ 	int transient = 0, can_recv = 0, resubmit = 1;
+ 	int status = urb->status;
+ 
+ 	dbg("%s(port = %d, status = %d)",
+-				__FUNCTION__, port->number, status);
++				__func__, port->number, status);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -895,11 +888,11 @@ static void oti6858_read_int_callback(struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s(): urb shutting down with status: %d",
+-					__FUNCTION__, status);
++					__func__, status);
+ 		return;
+ 	default:
+ 		dbg("%s(): nonzero urb status received: %d",
+-					__FUNCTION__, status);
++					__func__, status);
+ 		break;
+ 	}
+ 
+@@ -916,7 +909,7 @@ static void oti6858_read_int_callback(struct urb *urb)
+ 					priv->setup_done = 0;
+ 					resubmit = 0;
+ 					dbg("%s(): scheduling setup_line()",
+-					    __FUNCTION__);
++					    __func__);
+ 					schedule_delayed_work(&priv->delayed_setup_work, 0);
+ 				}
+ 			}
+@@ -931,7 +924,7 @@ static void oti6858_read_int_callback(struct urb *urb)
+ 					priv->setup_done = 0;
+ 					resubmit = 0;
+ 					dbg("%s(): scheduling setup_line()",
+-					    __FUNCTION__);
++					    __func__);
+ 					schedule_delayed_work(&priv->delayed_setup_work, 0);
+ 				}
+ 			}
+@@ -960,7 +953,7 @@ static void oti6858_read_int_callback(struct urb *urb)
+ 		if (result != 0) {
+ 			priv->flags.read_urb_in_use = 0;
+ 			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+-					" error %d\n", __FUNCTION__, result);
++					" error %d\n", __func__, result);
+ 		} else {
+ 			resubmit = 0;
+ 		}
+@@ -979,20 +972,20 @@ static void oti6858_read_int_callback(struct urb *urb)
+ 	if (resubmit) {
+ 		int result;
+ 
+-//		dbg("%s(): submitting interrupt urb", __FUNCTION__);
++//		dbg("%s(): submitting interrupt urb", __func__);
+ 		urb->dev = port->serial->dev;
+ 		result = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (result != 0) {
+ 			dev_err(&urb->dev->dev,
+ 					"%s(): usb_submit_urb() failed with"
+-					" error %d\n", __FUNCTION__, result);
++					" error %d\n", __func__, result);
+ 		}
+ 	}
+ }
+ 
+ static void oti6858_read_bulk_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port *port =  urb->context;
+ 	struct oti6858_private *priv = usb_get_serial_port_data(port);
+ 	struct tty_struct *tty;
+ 	unsigned char *data = urb->transfer_buffer;
+@@ -1001,7 +994,7 @@ static void oti6858_read_bulk_callback(struct urb *urb)
+ 	int result;
+ 
+ 	dbg("%s(port = %d, status = %d)",
+-				__FUNCTION__, port->number, status);
++				__func__, port->number, status);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	priv->flags.read_urb_in_use = 0;
+@@ -1009,20 +1002,20 @@ static void oti6858_read_bulk_callback(struct urb *urb)
+ 
+ 	if (status != 0) {
+ 		if (!port->open_count) {
+-			dbg("%s(): port is closed, exiting", __FUNCTION__);
++			dbg("%s(): port is closed, exiting", __func__);
+ 			return;
+ 		}
+ 		/*
+ 		if (status == -EPROTO) {
+ 			// PL2303 mysteriously fails with -EPROTO reschedule the read
+-			dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
++			dbg("%s - caught -EPROTO, resubmitting the urb", __func__);
+ 			result = usb_submit_urb(urb, GFP_ATOMIC);
+ 			if (result)
+-				dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++				dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ 			return;
+ 		}
+ 		*/
+-		dbg("%s(): unable to handle the error, exiting", __FUNCTION__);
++		dbg("%s(): unable to handle the error, exiting", __func__);
+ 		return;
+ 	}
+ 
+@@ -1038,20 +1031,20 @@ static void oti6858_read_bulk_callback(struct urb *urb)
+ 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ 		if (result != 0) {
+ 			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+-					" error %d\n", __FUNCTION__, result);
++					" error %d\n", __func__, result);
+ 		}
+ 	}
+ }
+ 
+ static void oti6858_write_bulk_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port *port =  urb->context;
+ 	struct oti6858_private *priv = usb_get_serial_port_data(port);
+ 	int status = urb->status;
+ 	int result;
+ 
+ 	dbg("%s(port = %d, status = %d)",
+-				__FUNCTION__, port->number, status);
++				__func__, port->number, status);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -1062,21 +1055,21 @@ static void oti6858_write_bulk_callback(struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s(): urb shutting down with status: %d",
+-					__FUNCTION__, status);
++					__func__, status);
+ 		priv->flags.write_urb_in_use = 0;
+ 		return;
+ 	default:
+ 		/* error in the urb, so we have to resubmit it */
+ 		dbg("%s(): nonzero write bulk status received: %d",
+-					__FUNCTION__, status);
+-		dbg("%s(): overflow in write", __FUNCTION__);
++					__func__, status);
++		dbg("%s(): overflow in write", __func__);
+ 
+ 		port->write_urb->transfer_buffer_length = 1;
+ 		port->write_urb->dev = port->serial->dev;
+ 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 		if (result) {
+ 			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+-					" error %d\n", __FUNCTION__, result);
++					" error %d\n", __func__, result);
+ 		} else {
+ 			return;
+ 		}
+@@ -1086,11 +1079,11 @@ static void oti6858_write_bulk_callback(struct urb *urb)
+ 
+ 	// schedule the interrupt urb if we are still open */
+ 	port->interrupt_in_urb->dev = port->serial->dev;
+-	dbg("%s(): submitting interrupt urb", __FUNCTION__);
++	dbg("%s(): submitting interrupt urb", __func__);
+ 	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ 	if (result != 0) {
+ 		dev_err(&port->dev, "%s(): failed submitting int urb,"
+-					" error %d\n", __FUNCTION__, result);
++					" error %d\n", __func__, result);
+ 	}
+ }
+ 
+diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
+index 2af7785..c605fb6 100644
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -410,7 +410,7 @@ static int set_control_lines(struct usb_device *dev, u8 value)
+ 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 				 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
+ 				 value, 0, NULL, 0, 100);
+-	dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval);
++	dbg("%s - value = %d, retval = %d", __func__, value, retval);
+ 	return retval;
+ }
+ 
+@@ -420,7 +420,7 @@ static void pl2303_send(struct usb_serial_port *port)
+ 	struct pl2303_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+@@ -441,7 +441,7 @@ static void pl2303_send(struct usb_serial_port *port)
+ 
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
++	usb_serial_debug_data(debug, &port->dev, __func__, count,
+ 			      port->write_urb->transfer_buffer);
+ 
+ 	port->write_urb->transfer_buffer_length = count;
+@@ -449,7 +449,7 @@ static void pl2303_send(struct usb_serial_port *port)
+ 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 	if (result) {
+ 		dev_err(&port->dev, "%s - failed submitting write urb,"
+-			" error %d\n", __FUNCTION__, result);
++			" error %d\n", __func__, result);
+ 		priv->write_urb_in_use = 0;
+ 		// TODO: reschedule pl2303_send
+ 	}
+@@ -463,7 +463,7 @@ static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
+ 	struct pl2303_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
++	dbg("%s - port %d, %d bytes", __func__, port->number, count);
+ 
+ 	if (!count)
+ 		return count;
+@@ -483,13 +483,13 @@ static int pl2303_write_room(struct usb_serial_port *port)
+ 	int room = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	room = pl2303_buf_space_avail(priv->buf);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 	return room;
+ }
+ 
+@@ -499,13 +499,13 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+ 	int chars = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	chars = pl2303_buf_data_avail(priv->buf);
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, chars);
++	dbg("%s - returns %d", __func__, chars);
+ 	return chars;
+ }
+ 
+@@ -521,7 +521,7 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ 	int i;
+ 	u8 control;
+ 
+-	dbg("%s -  port %d", __FUNCTION__, port->number);
++	dbg("%s -  port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (!priv->termios_initialized) {
+@@ -545,7 +545,9 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ 
+ 	buf = kzalloc(7, GFP_KERNEL);
+ 	if (!buf) {
+-		dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
++		dev_err(&port->dev, "%s - out of memory.\n", __func__);
++		/* Report back no change occurred */
++		*port->tty->termios = *old_termios;
+ 		return;
+ 	}
+ 
+@@ -563,11 +565,11 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ 			default:
+ 			case CS8:	buf[6] = 8;	break;
+ 		}
+-		dbg("%s - data bits = %d", __FUNCTION__, buf[6]);
++		dbg("%s - data bits = %d", __func__, buf[6]);
+ 	}
+ 
+ 	baud = tty_get_baud_rate(port->tty);;
+-	dbg("%s - baud = %d", __FUNCTION__, baud);
++	dbg("%s - baud = %d", __func__, baud);
+ 	if (baud) {
+ 		buf[0] = baud & 0xff;
+ 		buf[1] = (baud >> 8) & 0xff;
+@@ -580,10 +582,10 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ 	/* For reference buf[4]=2 is 2 stop bits */
+ 	if (cflag & CSTOPB) {
+ 		buf[4] = 2;
+-		dbg("%s - stop bits = 2", __FUNCTION__);
++		dbg("%s - stop bits = 2", __func__);
+ 	} else {
+ 		buf[4] = 0;
+-		dbg("%s - stop bits = 1", __FUNCTION__);
++		dbg("%s - stop bits = 1", __func__);
+ 	}
+ 
+ 	if (cflag & PARENB) {
+@@ -594,14 +596,14 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ 		/* For reference buf[5]=4 is space parity */
+ 		if (cflag & PARODD) {
+ 			buf[5] = 1;
+-			dbg("%s - parity = odd", __FUNCTION__);
++			dbg("%s - parity = odd", __func__);
+ 		} else {
+ 			buf[5] = 2;
+-			dbg("%s - parity = even", __FUNCTION__);
++			dbg("%s - parity = even", __func__);
+ 		}
+ 	} else {
+ 		buf[5] = 0;
+-		dbg("%s - parity = none", __FUNCTION__);
++		dbg("%s - parity = none", __func__);
+ 	}
+ 
+ 	i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+@@ -657,7 +659,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+ 	long timeout;
+ 	wait_queue_t wait;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* wait for data to drain from the buffer */
+ 	spin_lock_irqsave(&priv->lock, flags);
+@@ -695,7 +697,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+ 	schedule_timeout_interruptible(timeout);
+ 
+ 	/* shutdown our urbs */
+-	dbg("%s - shutting down urbs", __FUNCTION__);
++	dbg("%s - shutting down urbs", __func__);
+ 	usb_kill_urb(port->write_urb);
+ 	usb_kill_urb(port->read_urb);
+ 	usb_kill_urb(port->interrupt_in_urb);
+@@ -719,7 +721,7 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
+ 	struct pl2303_private *priv = usb_get_serial_port_data(port);
+ 	int result;
+ 
+-	dbg("%s -  port %d", __FUNCTION__, port->number);
++	dbg("%s -  port %d", __func__, port->number);
+ 
+ 	if (priv->type != HX) {
+ 		usb_clear_halt(serial->dev, port->write_urb->pipe);
+@@ -737,22 +739,22 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
+ 
+ 	//FIXME: need to assert RTS and DTR if CRTSCTS off
+ 
+-	dbg("%s - submitting read urb", __FUNCTION__);
++	dbg("%s - submitting read urb", __func__);
+ 	port->read_urb->dev = serial->dev;
+ 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (result) {
+ 		dev_err(&port->dev, "%s - failed submitting read urb,"
+-			" error %d\n", __FUNCTION__, result);
++			" error %d\n", __func__, result);
+ 		pl2303_close(port, NULL);
+ 		return -EPROTO;
+ 	}
+ 
+-	dbg("%s - submitting interrupt urb", __FUNCTION__);
++	dbg("%s - submitting interrupt urb", __func__);
+ 	port->interrupt_in_urb->dev = serial->dev;
+ 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ 	if (result) {
+ 		dev_err(&port->dev, "%s - failed submitting interrupt urb,"
+-			" error %d\n", __FUNCTION__, result);
++			" error %d\n", __func__, result);
+ 		pl2303_close(port, NULL);
+ 		return -EPROTO;
+ 	}
+@@ -792,7 +794,7 @@ static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
+ 	unsigned int status;
+ 	unsigned int result;
+ 
+-	dbg("%s (%d)", __FUNCTION__, port->number);
++	dbg("%s (%d)", __func__, port->number);
+ 
+ 	if (!usb_get_intfdata(port->serial->interface))
+ 		return -ENODEV;
+@@ -809,7 +811,7 @@ static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
+ 		  | ((status & UART_RING)	? TIOCM_RI  : 0)
+ 		  | ((status & UART_DCD)	? TIOCM_CD  : 0);
+ 
+-	dbg("%s - result = %x", __FUNCTION__, result);
++	dbg("%s - result = %x", __func__, result);
+ 
+ 	return result;
+ }
+@@ -853,15 +855,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+ static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
+ 			unsigned int cmd, unsigned long arg)
+ {
+-	dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
++	dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+ 
+ 	switch (cmd) {
+ 		case TIOCMIWAIT:
+-			dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
++			dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
+ 			return wait_modem_info(port, arg);
+ 
+ 		default:
+-			dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
++			dbg("%s not supported = 0x%04x", __func__, cmd);
+ 			break;
+ 	}
+ 
+@@ -874,19 +876,19 @@ static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
+ 	u16 state;
+ 	int result;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (break_state == 0)
+ 		state = BREAK_OFF;
+ 	else
+ 		state = BREAK_ON;
+-	dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
++	dbg("%s - turning break %s", __func__, state==BREAK_OFF ? "off" : "on");
+ 
+ 	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ 				 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+ 				 0, NULL, 0, 100);
+ 	if (result)
+-		dbg("%s - error sending break = %d", __FUNCTION__, result);
++		dbg("%s - error sending break = %d", __func__, result);
+ }
+ 
+ static void pl2303_shutdown(struct usb_serial *serial)
+@@ -894,7 +896,7 @@ static void pl2303_shutdown(struct usb_serial *serial)
+ 	int i;
+ 	struct pl2303_private *priv;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		priv = usb_get_serial_port_data(serial->port[i]);
+@@ -943,13 +945,13 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
+ 
+ static void pl2303_read_int_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port *port =  urb->context;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	unsigned int actual_length = urb->actual_length;
+ 	int status = urb->status;
+ 	int retval;
+ 
+-	dbg("%s (%d)", __FUNCTION__, port->number);
++	dbg("%s (%d)", __func__, port->number);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -959,16 +961,16 @@ static void pl2303_read_int_callback(struct urb *urb)
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+-		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++		dbg("%s - urb shutting down with status: %d", __func__,
+ 		    status);
+ 		return;
+ 	default:
+-		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
++		dbg("%s - nonzero urb status received: %d", __func__,
+ 		    status);
+ 		goto exit;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++	usb_serial_debug_data(debug, &port->dev, __func__,
+ 			      urb->actual_length, urb->transfer_buffer);
+ 
+ 	pl2303_update_line_status(port, data, actual_length);
+@@ -978,12 +980,12 @@ exit:
+ 	if (retval)
+ 		dev_err(&urb->dev->dev,
+ 			"%s - usb_submit_urb failed with result %d\n",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ }
+ 
+ static void pl2303_read_bulk_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port *port =  urb->context;
+ 	struct pl2303_private *priv = usb_get_serial_port_data(port);
+ 	struct tty_struct *tty;
+ 	unsigned char *data = urb->transfer_buffer;
+@@ -994,32 +996,32 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ 	u8 line_status;
+ 	char tty_flag;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+-		dbg("%s - urb status = %d", __FUNCTION__, status);
++		dbg("%s - urb status = %d", __func__, status);
+ 		if (!port->open_count) {
+-			dbg("%s - port is closed, exiting.", __FUNCTION__);
++			dbg("%s - port is closed, exiting.", __func__);
+ 			return;
+ 		}
+ 		if (status == -EPROTO) {
+ 			/* PL2303 mysteriously fails with -EPROTO reschedule
+ 			 * the read */
+ 			dbg("%s - caught -EPROTO, resubmitting the urb",
+-			    __FUNCTION__);
++			    __func__);
+ 			urb->dev = port->serial->dev;
+ 			result = usb_submit_urb(urb, GFP_ATOMIC);
+ 			if (result)
+ 				dev_err(&urb->dev->dev, "%s - failed"
+ 					" resubmitting read urb, error %d\n",
+-					__FUNCTION__, result);
++					__func__, result);
+ 			return;
+ 		}
+-		dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
++		dbg("%s - unable to handle the error, exiting.", __func__);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++	usb_serial_debug_data(debug, &port->dev, __func__,
+ 			      urb->actual_length, data);
+ 
+ 	/* get tty_flag from status */
+@@ -1039,7 +1041,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ 		tty_flag = TTY_PARITY;
+ 	else if (line_status & UART_FRAME_ERROR)
+ 		tty_flag = TTY_FRAME;
+-	dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
++	dbg("%s - tty_flag = %d", __func__, tty_flag);
+ 
+ 	tty = port->tty;
+ 	if (tty && urb->actual_length) {
+@@ -1058,7 +1060,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ 		result = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (result)
+ 			dev_err(&urb->dev->dev, "%s - failed resubmitting"
+-				" read urb, error %d\n", __FUNCTION__, result);
++				" read urb, error %d\n", __func__, result);
+ 	}
+ 
+ 	return;
+@@ -1066,12 +1068,12 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ 
+ static void pl2303_write_bulk_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port *port =  urb->context;
+ 	struct pl2303_private *priv = usb_get_serial_port_data(port);
+ 	int result;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -1081,21 +1083,21 @@ static void pl2303_write_bulk_callback(struct urb *urb)
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+-		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++		dbg("%s - urb shutting down with status: %d", __func__,
+ 		    status);
+ 		priv->write_urb_in_use = 0;
+ 		return;
+ 	default:
+ 		/* error in the urb, so we have to resubmit it */
+-		dbg("%s - Overflow in write", __FUNCTION__);
+-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
++		dbg("%s - Overflow in write", __func__);
++		dbg("%s - nonzero write bulk status received: %d", __func__,
+ 		    status);
+ 		port->write_urb->transfer_buffer_length = 1;
+ 		port->write_urb->dev = port->serial->dev;
+ 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 		if (result)
+ 			dev_err(&urb->dev->dev, "%s - failed resubmitting write"
+-				" urb, error %d\n", __FUNCTION__, result);
++				" urb, error %d\n", __func__, result);
+ 		else
+ 			return;
+ 	}
+@@ -1114,9 +1116,6 @@ static struct usb_serial_driver pl2303_device = {
+ 	},
+ 	.id_table =		id_table,
+ 	.usb_driver = 		&pl2303_driver,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.open =			pl2303_open,
+ 	.close =		pl2303_close,
+diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
+index 4e6dcc1..94bddf0 100644
+--- a/drivers/usb/serial/safe_serial.c
++++ b/drivers/usb/serial/safe_serial.c
+@@ -195,18 +195,17 @@ static __u16 __inline__ fcs_compute10 (unsigned char *sp, int len, __u16 fcs)
+ 
+ static void safe_read_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port *port =  urb->context;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	unsigned char length = urb->actual_length;
+-	int i;
+ 	int result;
+ 	int status = urb->status;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+@@ -227,28 +226,20 @@ static void safe_read_bulk_callback (struct urb *urb)
+ 	if (safe) {
+ 		__u16 fcs;
+ 		if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) {
+-
+ 			int actual_length = data[length - 2] >> 2;
+-
+ 			if (actual_length <= (length - 2)) {
+-
+-				info ("%s - actual: %d", __FUNCTION__, actual_length);
+-
+-				for (i = 0; i < actual_length; i++) {
+-					tty_insert_flip_char (port->tty, data[i], 0);
+-				}
++				info ("%s - actual: %d", __func__, actual_length);
++				tty_insert_flip_string(port->tty, data, actual_length);
+ 				tty_flip_buffer_push (port->tty);
+ 			} else {
+-				err ("%s - inconsistent lengths %d:%d", __FUNCTION__,
++				err ("%s - inconsistent lengths %d:%d", __func__,
+ 				     actual_length, length);
+ 			}
+ 		} else {
+-			err ("%s - bad CRC %x", __FUNCTION__, fcs);
++			err ("%s - bad CRC %x", __func__, fcs);
+ 		}
+ 	} else {
+-		for (i = 0; i < length; i++) {
+-			tty_insert_flip_char (port->tty, data[i], 0);
+-		}
++		tty_insert_flip_string(port->tty, data, length);
+ 		tty_flip_buffer_push (port->tty);
+ 	}
+ 
+@@ -259,7 +250,8 @@ static void safe_read_bulk_callback (struct urb *urb)
+ 		       safe_read_bulk_callback, port);
+ 
+ 	if ((result = usb_submit_urb (urb, GFP_ATOMIC))) {
+-		err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++		err ("%s - failed resubmitting read urb, error %d", __func__, result);
++		/* FIXME: Need a mechanism to retry later if this happens */
+ 	}
+ }
+ 
+@@ -274,25 +266,25 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
+ 	     count);
+ 
+ 	if (!port->write_urb) {
+-		dbg ("%s - write urb NULL", __FUNCTION__);
+-		return (0);
++		dbg ("%s - write urb NULL", __func__);
++		return 0;
+ 	}
+ 
+ 	dbg ("safe_write write_urb: %d transfer_buffer_length",
+ 	     port->write_urb->transfer_buffer_length);
+ 
+ 	if (!port->write_urb->transfer_buffer_length) {
+-		dbg ("%s - write urb transfer_buffer_length zero", __FUNCTION__);
+-		return (0);
++		dbg ("%s - write urb transfer_buffer_length zero", __func__);
++		return 0;
+ 	}
+ 	if (count == 0) {
+-		dbg ("%s - write request of 0 bytes", __FUNCTION__);
+-		return (0);
++		dbg ("%s - write request of 0 bytes", __func__);
++		return 0;
+ 	}
+ 	spin_lock_bh(&port->lock);
+ 	if (port->write_urb_busy) {
+ 		spin_unlock_bh(&port->lock);
+-		dbg("%s - already writing", __FUNCTION__);
++		dbg("%s - already writing", __func__);
+ 		return 0;
+ 	}
+ 	port->write_urb_busy = 1;
+@@ -332,7 +324,7 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
+ 		port->write_urb->transfer_buffer_length = count;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+ #ifdef ECHO_TX
+ 	{
+ 		int i;
+@@ -349,28 +341,31 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
+ 	port->write_urb->dev = port->serial->dev;
+ 	if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) {
+ 		port->write_urb_busy = 0;
+-		err ("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++		err ("%s - failed submitting write urb, error %d", __func__, result);
+ 		return 0;
+ 	}
+-	dbg ("%s urb: %p submitted", __FUNCTION__, port->write_urb);
++	dbg ("%s urb: %p submitted", __func__, port->write_urb);
+ 
+ 	return (count);
+ }
+ 
+ static int safe_write_room (struct usb_serial_port *port)
+ {
+-	int room = 0;		// Default: no room
++	int room = 0;		/* Default: no room */
++	unsigned long flags;
+ 
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
++	spin_lock_irqsave(&port->lock, flags);
+ 	if (port->write_urb_busy)
+ 		room = port->bulk_out_size - (safe ? 2 : 0);
++	spin_unlock_irqrestore(&port->lock, flags);
+ 
+ 	if (room) {
+ 		dbg ("safe_write_room returns %d", room);
+ 	}
+ 
+-	return (room);
++	return room;
+ }
+ 
+ static int safe_startup (struct usb_serial *serial)
+@@ -394,9 +389,6 @@ static struct usb_serial_driver safe_device = {
+ 	},
+ 	.id_table =		id_table,
+ 	.usb_driver =		&safe_driver,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		1,
+ 	.write =		safe_write,
+ 	.write_room =		safe_write_room,
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index ed67881..29074c1 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -1,7 +1,7 @@
+ /*
+   USB Driver for Sierra Wireless
+ 
+-  Copyright (C) 2006, 2007, 2008  Kevin Lloyd <linux at sierrawireless.com>
++  Copyright (C) 2006, 2007, 2008  Kevin Lloyd <klloyd at sierrawireless.com>
+ 
+   IMPORTANT DISCLAIMER: This driver is not commercially supported by
+   Sierra Wireless. Use at your own risk.
+@@ -14,8 +14,8 @@
+   Whom based his on the Keyspan driver by Hugh Blemings <hugh at blemings.org>
+ */
+ 
+-#define DRIVER_VERSION "v.1.2.8"
+-#define DRIVER_AUTHOR "Kevin Lloyd <linux at sierrawireless.com>"
++#define DRIVER_VERSION "v.1.2.9c"
++#define DRIVER_AUTHOR "Kevin Lloyd <klloyd at sierrawireless.com>"
+ #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
+ 
+ #include <linux/kernel.h>
+@@ -31,7 +31,6 @@
+ #define SWIMS_USB_REQUEST_SetPower	0x00
+ #define SWIMS_USB_REQUEST_SetNmea	0x07
+ #define SWIMS_USB_REQUEST_SetMode	0x0B
+-#define SWIMS_USB_REQUEST_TYPE_VSC_SET	0x40
+ #define SWIMS_SET_MODE_Modem		0x0001
+ 
+ /* per port private data */
+@@ -55,7 +54,7 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
+ 	dev_dbg(&udev->dev, "%s", "SET POWER STATE\n");
+ 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 			SWIMS_USB_REQUEST_SetPower,	/* __u8 request      */
+-			SWIMS_USB_REQUEST_TYPE_VSC_SET,	/* __u8 request type */
++			USB_TYPE_VENDOR,		/* __u8 request type */
+ 			swiState,			/* __u16 value       */
+ 			0,				/* __u16 index       */
+ 			NULL,				/* void *data        */
+@@ -70,7 +69,7 @@ static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
+ 	dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH\n");
+ 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 			SWIMS_USB_REQUEST_SetMode,	/* __u8 request      */
+-			SWIMS_USB_REQUEST_TYPE_VSC_SET,	/* __u8 request type */
++			USB_TYPE_VENDOR,		/* __u8 request type */
+ 			eSWocMode,			/* __u16 value       */
+ 			0x0000,				/* __u16 index       */
+ 			NULL,				/* void *data        */
+@@ -85,7 +84,7 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
+ 	dev_dbg(&udev->dev, "%s", "NMEA Enable sent\n");
+ 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 			SWIMS_USB_REQUEST_SetNmea,	/* __u8 request      */
+-			SWIMS_USB_REQUEST_TYPE_VSC_SET,	/* __u8 request type */
++			USB_TYPE_VENDOR,		/* __u8 request type */
+ 			enable,				/* __u16 value       */
+ 			0x0000,				/* __u16 index       */
+ 			NULL,				/* void *data        */
+@@ -109,6 +108,26 @@ static int sierra_calc_num_ports(struct usb_serial *serial)
+ 	return result;
+ }
+ 
++static int sierra_calc_interface(struct usb_serial *serial)
++{
++		int interface;
++		struct usb_interface *p_interface;
++		struct usb_host_interface *p_host_interface;
++
++		/* Get the interface structure pointer from the serial struct */
++		p_interface = serial->interface;
++
++		/* Get a pointer to the host interface structure */
++		p_host_interface = p_interface->cur_altsetting;
++
++		/* read the interface descriptor for this active altsetting
++		 * to find out the interface number we are on
++		*/
++		interface = p_host_interface->desc.bInterfaceNumber;
++
++		return interface;
++}
++
+ static int sierra_probe(struct usb_serial *serial,
+ 			const struct usb_device_id *id)
+ {
+@@ -124,6 +143,22 @@ static int sierra_probe(struct usb_serial *serial,
+ 	ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ 	udev = serial->dev;
+ 
++		/* Figure out the interface number from the serial structure */
++		ifnum = sierra_calc_interface(serial);
++
++		/*
++		 * If this interface supports more than 1 alternate
++		 * select the 2nd one
++		 */
++		if (serial->interface->num_altsetting == 2) {
++			dev_dbg(&udev->dev,
++				"Selecting alt setting for interface %d\n",
++				ifnum);
++
++			/* We know the alternate setting is 1 for the MC8785 */
++			usb_set_interface(udev, ifnum, 1);
++		}
++
+ 	/* Check if in installer mode */
+ 	if (truinstall && id->driver_info == DEVICE_INSTALLER) {
+ 		dev_dbg(&udev->dev, "%s", "FOUND TRU-INSTALL DEVICE(SW)\n");
+@@ -156,7 +191,7 @@ static struct usb_device_id id_table [] = {
+ 	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
+ 	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
+ 	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless USB Dongle 595U */
+-	{ USB_DEVICE(0x1199, 0x0023) },	/* Sierra Wireless AirCard */
++	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, /* Sierra Wireless C597 */
+ 
+ 	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
+ 	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 */
+@@ -164,15 +199,20 @@ static struct usb_device_id id_table [] = {
+ 	{ USB_DEVICE(0x1199, 0x6812) },	/* Sierra Wireless MC8775 & AC 875U */
+ 	{ USB_DEVICE(0x1199, 0x6813) },	/* Sierra Wireless MC8775 (Thinkpad internal) */
+ 	{ USB_DEVICE(0x1199, 0x6815) },	/* Sierra Wireless MC8775 */
++	{ USB_DEVICE(0x03f0, 0x1e1d) },	/* HP hs2300 a.k.a MC8775 */
+ 	{ USB_DEVICE(0x1199, 0x6820) },	/* Sierra Wireless AirCard 875 */
++	{ USB_DEVICE(0x1199, 0x6821) },	/* Sierra Wireless AirCard 875U */
+ 	{ USB_DEVICE(0x1199, 0x6832) },	/* Sierra Wireless MC8780*/
+ 	{ USB_DEVICE(0x1199, 0x6833) },	/* Sierra Wireless MC8781*/
++	{ USB_DEVICE(0x1199, 0x683B), .driver_info = DEVICE_1_PORT },	/* Sierra Wireless MC8785 Composite*/
+ 	{ USB_DEVICE(0x1199, 0x6850) },	/* Sierra Wireless AirCard 880 */
+ 	{ USB_DEVICE(0x1199, 0x6851) },	/* Sierra Wireless AirCard 881 */
+ 	{ USB_DEVICE(0x1199, 0x6852) },	/* Sierra Wireless AirCard 880 E */
+ 	{ USB_DEVICE(0x1199, 0x6853) },	/* Sierra Wireless AirCard 881 E */
+ 	{ USB_DEVICE(0x1199, 0x6855) },	/* Sierra Wireless AirCard 880 U */
+ 	{ USB_DEVICE(0x1199, 0x6856) },	/* Sierra Wireless AirCard 881 U */
++	{ USB_DEVICE(0x1199, 0x6859), .driver_info = DEVICE_1_PORT },	/* Sierra Wireless AirCard 885 E */
++	{ USB_DEVICE(0x1199, 0x685A), .driver_info = DEVICE_1_PORT },	/* Sierra Wireless AirCard 885 E */
+ 
+ 	{ USB_DEVICE(0x1199, 0x6468) }, /* Sierra Wireless MP3G - EVDO */
+ 	{ USB_DEVICE(0x1199, 0x6469) }, /* Sierra Wireless MP3G - UMTS/HSPA */
+@@ -216,7 +256,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
+ 	struct sierra_port_private *portdata;
+ 	__u16 interface = 0;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	portdata = usb_get_serial_port_data(port);
+ 
+@@ -246,24 +286,24 @@ static int sierra_send_setup(struct usb_serial_port *port)
+ 
+ static void sierra_rx_throttle(struct usb_serial_port *port)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ }
+ 
+ static void sierra_rx_unthrottle(struct usb_serial_port *port)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ }
+ 
+ static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
+ {
+ 	/* Unfortunately, I don't know how to send a break */
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ }
+ 
+ static void sierra_set_termios(struct usb_serial_port *port,
+ 			struct ktermios *old_termios)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	tty_termios_copy_hw(port->tty->termios, old_termios);
+ 	sierra_send_setup(port);
+ }
+@@ -317,14 +357,14 @@ static void sierra_outdat_callback(struct urb *urb)
+ 	int status = urb->status;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* free up the transfer buffer, as usb_free_urb() does not do this */
+ 	kfree(urb->transfer_buffer);
+ 
+ 	if (status)
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 
+ 	spin_lock_irqsave(&portdata->lock, flags);
+ 	--portdata->outstanding_urbs;
+@@ -346,12 +386,12 @@ static int sierra_write(struct usb_serial_port *port,
+ 
+ 	portdata = usb_get_serial_port_data(port);
+ 
+-	dbg("%s: write (%d chars)", __FUNCTION__, count);
++	dbg("%s: write (%d chars)", __func__, count);
+ 
+ 	spin_lock_irqsave(&portdata->lock, flags);
+ 	if (portdata->outstanding_urbs > N_OUT_URB) {
+ 		spin_unlock_irqrestore(&portdata->lock, flags);
+-		dbg("%s - write limit hit\n", __FUNCTION__);
++		dbg("%s - write limit hit\n", __func__);
+ 		return 0;
+ 	}
+ 	portdata->outstanding_urbs++;
+@@ -373,7 +413,7 @@ static int sierra_write(struct usb_serial_port *port,
+ 
+ 	memcpy(buffer, buf, count);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+ 
+ 	usb_fill_bulk_urb(urb, serial->dev,
+ 			  usb_sndbulkpipe(serial->dev,
+@@ -384,7 +424,7 @@ static int sierra_write(struct usb_serial_port *port,
+ 	status = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if (status) {
+ 		dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+-			"with status = %d\n", __FUNCTION__, status);
++			"with status = %d\n", __func__, status);
+ 		count = status;
+ 		goto error;
+ 	}
+@@ -414,14 +454,14 @@ static void sierra_indat_callback(struct urb *urb)
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int status = urb->status;
+ 
+-	dbg("%s: %p", __FUNCTION__, urb);
++	dbg("%s: %p", __func__, urb);
+ 
+ 	endpoint = usb_pipeendpoint(urb->pipe);
+-	port = (struct usb_serial_port *) urb->context;
++	port =  urb->context;
+ 
+ 	if (status) {
+ 		dbg("%s: nonzero status: %d on endpoint %02x.",
+-		    __FUNCTION__, status, endpoint);
++		    __func__, status, endpoint);
+ 	} else {
+ 		tty = port->tty;
+ 		if (urb->actual_length) {
+@@ -429,7 +469,7 @@ static void sierra_indat_callback(struct urb *urb)
+ 			tty_insert_flip_string(tty, data, urb->actual_length);
+ 			tty_flip_buffer_push(tty);
+ 		} else {
+-			dbg("%s: empty read urb received", __FUNCTION__);
++			dbg("%s: empty read urb received", __func__);
+ 		}
+ 
+ 		/* Resubmit urb so we continue receiving */
+@@ -447,19 +487,19 @@ static void sierra_instat_callback(struct urb *urb)
+ {
+ 	int err;
+ 	int status = urb->status;
+-	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++	struct usb_serial_port *port =  urb->context;
+ 	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ 	struct usb_serial *serial = port->serial;
+ 
+-	dbg("%s", __FUNCTION__);
+-	dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
++	dbg("%s", __func__);
++	dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
+ 
+ 	if (status == 0) {
+ 		struct usb_ctrlrequest *req_pkt =
+ 				(struct usb_ctrlrequest *)urb->transfer_buffer;
+ 
+ 		if (!req_pkt) {
+-			dbg("%s: NULL req_pkt\n", __FUNCTION__);
++			dbg("%s: NULL req_pkt\n", __func__);
+ 			return;
+ 		}
+ 		if ((req_pkt->bRequestType == 0xA1) &&
+@@ -469,7 +509,7 @@ static void sierra_instat_callback(struct urb *urb)
+ 					urb->transfer_buffer +
+ 					sizeof(struct usb_ctrlrequest));
+ 
+-			dbg("%s: signal x%x", __FUNCTION__, signals);
++			dbg("%s: signal x%x", __func__, signals);
+ 
+ 			old_dcd_state = portdata->dcd_state;
+ 			portdata->cts_state = 1;
+@@ -481,11 +521,11 @@ static void sierra_instat_callback(struct urb *urb)
+ 					old_dcd_state && !portdata->dcd_state)
+ 				tty_hangup(port->tty);
+ 		} else {
+-			dbg("%s: type %x req %x", __FUNCTION__,
+-				req_pkt->bRequestType,req_pkt->bRequest);
++			dbg("%s: type %x req %x", __func__,
++				req_pkt->bRequestType, req_pkt->bRequest);
+ 		}
+ 	} else
+-		dbg("%s: error %d", __FUNCTION__, status);
++		dbg("%s: error %d", __func__, status);
+ 
+ 	/* Resubmit urb so we continue receiving IRQ data */
+ 	if (status != -ESHUTDOWN) {
+@@ -493,7 +533,7 @@ static void sierra_instat_callback(struct urb *urb)
+ 		err = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (err)
+ 			dbg("%s: resubmit intr urb failed. (%d)",
+-				__FUNCTION__, err);
++				__func__, err);
+ 	}
+ }
+ 
+@@ -502,14 +542,14 @@ static int sierra_write_room(struct usb_serial_port *port)
+ 	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* try to give a good number back based on if we have any free urbs at
+ 	 * this point in time */
+ 	spin_lock_irqsave(&portdata->lock, flags);
+ 	if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) {
+ 		spin_unlock_irqrestore(&portdata->lock, flags);
+-		dbg("%s - write limit hit\n", __FUNCTION__);
++		dbg("%s - write limit hit\n", __func__);
+ 		return 0;
+ 	}
+ 	spin_unlock_irqrestore(&portdata->lock, flags);
+@@ -519,13 +559,15 @@ static int sierra_write_room(struct usb_serial_port *port)
+ 
+ static int sierra_chars_in_buffer(struct usb_serial_port *port)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/*
+ 	 * We can't really account for how much data we
+ 	 * have sent out, but hasn't made it through to the
+ 	 * device as we can't see the backend here, so just
+ 	 * tell the tty layer that everything is flushed.
++	 *
++	 * FIXME: should walk the outstanding urbs info
+ 	 */
+ 	return 0;
+ }
+@@ -540,7 +582,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
+ 
+ 	portdata = usb_get_serial_port_data(port);
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* Set some sane defaults */
+ 	portdata->rts_state = 1;
+@@ -552,7 +594,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
+ 		if (!urb)
+ 			continue;
+ 		if (urb->dev != serial->dev) {
+-			dbg("%s: dev %p != %p", __FUNCTION__,
++			dbg("%s: dev %p != %p", __func__,
+ 				urb->dev, serial->dev);
+ 			continue;
+ 		}
+@@ -590,7 +632,7 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
+ 	struct usb_serial *serial = port->serial;
+ 	struct sierra_port_private *portdata;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	portdata = usb_get_serial_port_data(port);
+ 
+ 	portdata->rts_state = 0;
+@@ -620,7 +662,7 @@ static int sierra_startup(struct usb_serial *serial)
+ 	int i;
+ 	int j;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* Set Device mode to D0 */
+ 	sierra_set_power_state(serial->dev, 0x0000);
+@@ -635,7 +677,7 @@ static int sierra_startup(struct usb_serial *serial)
+ 		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+ 		if (!portdata) {
+ 			dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
+-					__FUNCTION__, i);
++					__func__, i);
+ 			return -ENOMEM;
+ 		}
+ 		spin_lock_init(&portdata->lock);
+@@ -656,7 +698,7 @@ static int sierra_startup(struct usb_serial *serial)
+ 			urb = usb_alloc_urb(0, GFP_KERNEL);
+ 			if (urb == NULL) {
+ 				dbg("%s: alloc for in port failed.",
+-				    __FUNCTION__);
++				    __func__);
+ 				continue;
+ 			}
+ 			/* Fill URB using supplied data. */
+@@ -678,7 +720,7 @@ static void sierra_shutdown(struct usb_serial *serial)
+ 	struct usb_serial_port *port;
+ 	struct sierra_port_private *portdata;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		port = serial->port[i];
+@@ -706,9 +748,6 @@ static struct usb_serial_driver sierra_device = {
+ 	.description       = "Sierra USB modem",
+ 	.id_table          = id_table,
+ 	.usb_driver        = &sierra_driver,
+-	.num_interrupt_in  = NUM_DONT_CARE,
+-	.num_bulk_in       = NUM_DONT_CARE,
+-	.num_bulk_out      = NUM_DONT_CARE,
+ 	.calc_num_ports	   = sierra_calc_num_ports,
+ 	.probe		   = sierra_probe,
+ 	.open              = sierra_open,
+diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
+new file mode 100644
+index 0000000..2282d62
+--- /dev/null
++++ b/drivers/usb/serial/spcp8x5.c
+@@ -0,0 +1,1072 @@
++/*
++ * spcp8x5 USB to serial adaptor driver
++ *
++ * Copyright (C) 2006 Linxb (xubin.lin at worldplus.com.cn)
++ * Copyright (C) 2006 S1 Corp.
++ *
++ * Original driver for 2.6.10 pl2303 driver by
++ *   Greg Kroah-Hartman (greg at kroah.com)
++ * Changes for 2.6.20 by Harald Klein <hari at vt100.at>
++ *
++ *	This program is free software; you can redistribute it and/or modify
++ *	it under the terms of the GNU General Public License as published by
++ *	the Free Software Foundation; either version 2 of the License, or
++ *	(at your option) any later version.
++ *
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/tty.h>
++#include <linux/tty_driver.h>
++#include <linux/tty_flip.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/usb.h>
++#include <linux/usb/serial.h>
++
++
++/* Version Information */
++#define DRIVER_VERSION 	"v0.04"
++#define DRIVER_DESC 	"SPCP8x5 USB to serial adaptor driver"
++
++static int debug;
++
++#define SPCP8x5_007_VID		0x04FC
++#define SPCP8x5_007_PID		0x0201
++#define SPCP8x5_008_VID		0x04fc
++#define SPCP8x5_008_PID		0x0235
++#define SPCP8x5_PHILIPS_VID	0x0471
++#define SPCP8x5_PHILIPS_PID	0x081e
++#define SPCP8x5_INTERMATIC_VID	0x04FC
++#define SPCP8x5_INTERMATIC_PID	0x0204
++#define SPCP8x5_835_VID		0x04fc
++#define SPCP8x5_835_PID		0x0231
++
++static struct usb_device_id id_table [] = {
++	{ USB_DEVICE(SPCP8x5_PHILIPS_VID , SPCP8x5_PHILIPS_PID)},
++	{ USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
++	{ USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
++	{ USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
++	{ USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)},
++	{ }					/* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, id_table);
++
++struct spcp8x5_usb_ctrl_arg {
++	u8 	type;
++	u8	cmd;
++	u8	cmd_type;
++	u16	value;
++	u16	index;
++	u16	length;
++};
++
++/* wait 30s before close */
++#define SPCP8x5_CLOSING_WAIT	(30*HZ)
++
++#define SPCP8x5_BUF_SIZE	1024
++
++
++/* spcp8x5 spec register define */
++#define MCR_CONTROL_LINE_RTS		0x02
++#define MCR_CONTROL_LINE_DTR		0x01
++#define MCR_DTR				0x01
++#define MCR_RTS				0x02
++
++#define MSR_STATUS_LINE_DCD		0x80
++#define MSR_STATUS_LINE_RI		0x40
++#define MSR_STATUS_LINE_DSR		0x20
++#define MSR_STATUS_LINE_CTS		0x10
++
++/* verdor command here , we should define myself */
++#define SET_DEFAULT			0x40
++#define SET_DEFAULT_TYPE		0x20
++
++#define SET_UART_FORMAT			0x40
++#define SET_UART_FORMAT_TYPE		0x21
++#define SET_UART_FORMAT_SIZE_5		0x00
++#define SET_UART_FORMAT_SIZE_6		0x01
++#define SET_UART_FORMAT_SIZE_7		0x02
++#define SET_UART_FORMAT_SIZE_8		0x03
++#define SET_UART_FORMAT_STOP_1		0x00
++#define SET_UART_FORMAT_STOP_2		0x04
++#define SET_UART_FORMAT_PAR_NONE	0x00
++#define SET_UART_FORMAT_PAR_ODD		0x10
++#define SET_UART_FORMAT_PAR_EVEN	0x30
++#define SET_UART_FORMAT_PAR_MASK	0xD0
++#define SET_UART_FORMAT_PAR_SPACE	0x90
++
++#define GET_UART_STATUS_TYPE		0xc0
++#define GET_UART_STATUS			0x22
++#define GET_UART_STATUS_MSR		0x06
++
++#define SET_UART_STATUS			0x40
++#define SET_UART_STATUS_TYPE		0x23
++#define SET_UART_STATUS_MCR		0x0004
++#define SET_UART_STATUS_MCR_DTR		0x01
++#define SET_UART_STATUS_MCR_RTS		0x02
++#define SET_UART_STATUS_MCR_LOOP	0x10
++
++#define SET_WORKING_MODE		0x40
++#define SET_WORKING_MODE_TYPE		0x24
++#define SET_WORKING_MODE_U2C		0x00
++#define SET_WORKING_MODE_RS485		0x01
++#define SET_WORKING_MODE_PDMA		0x02
++#define SET_WORKING_MODE_SPP		0x03
++
++#define SET_FLOWCTL_CHAR		0x40
++#define SET_FLOWCTL_CHAR_TYPE		0x25
++
++#define GET_VERSION			0xc0
++#define GET_VERSION_TYPE		0x26
++
++#define SET_REGISTER			0x40
++#define SET_REGISTER_TYPE		0x27
++
++#define	GET_REGISTER			0xc0
++#define GET_REGISTER_TYPE		0x28
++
++#define SET_RAM				0x40
++#define SET_RAM_TYPE			0x31
++
++#define GET_RAM				0xc0
++#define GET_RAM_TYPE			0x32
++
++/* how come ??? */
++#define UART_STATE			0x08
++#define UART_STATE_TRANSIENT_MASK	0x74
++#define UART_DCD			0x01
++#define UART_DSR			0x02
++#define UART_BREAK_ERROR		0x04
++#define UART_RING			0x08
++#define UART_FRAME_ERROR		0x10
++#define UART_PARITY_ERROR		0x20
++#define UART_OVERRUN_ERROR		0x40
++#define UART_CTS			0x80
++
++enum spcp8x5_type {
++	SPCP825_007_TYPE,
++	SPCP825_008_TYPE,
++	SPCP825_PHILIP_TYPE,
++	SPCP825_INTERMATIC_TYPE,
++	SPCP835_TYPE,
++};
++
++/* 1st in 1st out buffer 4 driver */
++struct ringbuf {
++	unsigned int	buf_size;
++	char		*buf_buf;
++	char		*buf_get;
++	char		*buf_put;
++};
++
++/* alloc the ring buf and alloc the buffer itself */
++static inline struct ringbuf *alloc_ringbuf(unsigned int size)
++{
++	struct ringbuf *pb;
++
++	if (size == 0)
++		return NULL;
++
++	pb = kmalloc(sizeof(*pb), GFP_KERNEL);
++	if (pb == NULL)
++		return NULL;
++
++	pb->buf_buf = kmalloc(size, GFP_KERNEL);
++	if (pb->buf_buf == NULL) {
++		kfree(pb);
++		return NULL;
++	}
++
++	pb->buf_size = size;
++	pb->buf_get = pb->buf_put = pb->buf_buf;
++
++	return pb;
++}
++
++/* free the ring buf and the buffer itself */
++static inline void free_ringbuf(struct ringbuf *pb)
++{
++	if (pb != NULL) {
++		kfree(pb->buf_buf);
++		kfree(pb);
++	}
++}
++
++/* clear pipo , juest repoint the pointer here */
++static inline void clear_ringbuf(struct ringbuf *pb)
++{
++	if (pb != NULL)
++		pb->buf_get = pb->buf_put;
++}
++
++/* get the number of data in the pipo */
++static inline unsigned int ringbuf_avail_data(struct ringbuf *pb)
++{
++	if (pb == NULL)
++		return 0;
++	return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
++}
++
++/* get the number of space in the pipo */
++static inline unsigned int ringbuf_avail_space(struct ringbuf *pb)
++{
++	if (pb == NULL)
++		return 0;
++	return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
++}
++
++/* put count data into pipo */
++static unsigned int put_ringbuf(struct ringbuf *pb, const char *buf,
++				unsigned int count)
++{
++	unsigned int len;
++
++	if (pb == NULL)
++		return 0;
++
++	len  = ringbuf_avail_space(pb);
++	if (count > len)
++		count = len;
++
++	if (count == 0)
++		return 0;
++
++	len = pb->buf_buf + pb->buf_size - pb->buf_put;
++	if (count > len) {
++		memcpy(pb->buf_put, buf, len);
++		memcpy(pb->buf_buf, buf+len, count - len);
++		pb->buf_put = pb->buf_buf + count - len;
++	} else {
++		memcpy(pb->buf_put, buf, count);
++		if (count < len)
++			pb->buf_put += count;
++		else /* count == len */
++			pb->buf_put = pb->buf_buf;
++	}
++	return count;
++}
++
++/* get count data from pipo */
++static unsigned int get_ringbuf(struct ringbuf *pb, char *buf,
++				unsigned int count)
++{
++	unsigned int len;
++
++	if (pb == NULL || buf == NULL)
++		return 0;
++
++	len = ringbuf_avail_data(pb);
++	if (count > len)
++		count = len;
++
++	if (count == 0)
++		return 0;
++
++	len = pb->buf_buf + pb->buf_size - pb->buf_get;
++	if (count > len) {
++		memcpy(buf, pb->buf_get, len);
++		memcpy(buf+len, pb->buf_buf, count - len);
++		pb->buf_get = pb->buf_buf + count - len;
++	} else {
++		memcpy(buf, pb->buf_get, count);
++		if (count < len)
++			pb->buf_get += count;
++		else /* count == len */
++			pb->buf_get = pb->buf_buf;
++	}
++
++	return count;
++}
++
++static struct usb_driver spcp8x5_driver = {
++	.name =			"spcp8x5",
++	.probe =		usb_serial_probe,
++	.disconnect =		usb_serial_disconnect,
++	.id_table =		id_table,
++	.no_dynamic_id =	1,
++};
++
++
++struct spcp8x5_private {
++	spinlock_t 	lock;
++	struct ringbuf	*buf;
++	int 		write_urb_in_use;
++	enum spcp8x5_type	type;
++	wait_queue_head_t	delta_msr_wait;
++	u8 			line_control;
++	u8 			line_status;
++	u8 			termios_initialized;
++};
++
++/* desc : when device plug in,this function would be called.
++ * thanks to usb_serial subsystem,then do almost every things for us. And what
++ * we should do just alloc the buffer */
++static int spcp8x5_startup(struct usb_serial *serial)
++{
++	struct spcp8x5_private *priv;
++	int i;
++	enum spcp8x5_type type = SPCP825_007_TYPE;
++
++	if (serial->dev->descriptor.idProduct == 0x0201)
++		type = SPCP825_007_TYPE;
++	else if (serial->dev->descriptor.idProduct == 0x0231)
++		type = SPCP835_TYPE;
++	else if (serial->dev->descriptor.idProduct == 0x0235)
++		type = SPCP825_008_TYPE;
++	else if (serial->dev->descriptor.idProduct == 0x0204)
++		type = SPCP825_INTERMATIC_TYPE;
++	else if (serial->dev->descriptor.idProduct == 0x0471 &&
++		 serial->dev->descriptor.idVendor == 0x081e)
++		type = SPCP825_PHILIP_TYPE;
++	dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
++
++	for (i = 0; i < serial->num_ports; ++i) {
++		priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
++		if (!priv)
++			goto cleanup;
++
++		spin_lock_init(&priv->lock);
++		priv->buf = alloc_ringbuf(SPCP8x5_BUF_SIZE);
++		if (priv->buf == NULL)
++			goto cleanup2;
++
++		init_waitqueue_head(&priv->delta_msr_wait);
++		priv->type = type;
++		usb_set_serial_port_data(serial->port[i] , priv);
++
++	}
++
++	return 0;
++
++cleanup2:
++	kfree(priv);
++cleanup:
++	for (--i; i >= 0; --i) {
++		priv = usb_get_serial_port_data(serial->port[i]);
++		free_ringbuf(priv->buf);
++		kfree(priv);
++		usb_set_serial_port_data(serial->port[i] , NULL);
++	}
++	return -ENOMEM;
++}
++
++/* call when the device plug out. free all the memory alloced by probe */
++static void spcp8x5_shutdown(struct usb_serial *serial)
++{
++	int i;
++	struct spcp8x5_private *priv;
++
++	for (i = 0; i < serial->num_ports; i++) {
++		priv = usb_get_serial_port_data(serial->port[i]);
++		if (priv) {
++			free_ringbuf(priv->buf);
++			kfree(priv);
++			usb_set_serial_port_data(serial->port[i] , NULL);
++		}
++	}
++}
++
++/* set the modem control line of the device.
++ * NOTE spcp825-007 not supported this */
++static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value,
++				enum spcp8x5_type type)
++{
++	int retval;
++	u8 mcr = 0 ;
++
++	if (type == SPCP825_007_TYPE)
++		return -EPERM;
++
++	mcr = (unsigned short)value;
++	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++				 SET_UART_STATUS_TYPE, SET_UART_STATUS,
++				 mcr, 0x04, NULL, 0, 100);
++	if (retval != 0)
++		dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval);
++	return retval;
++}
++
++/* get the modem status register of the device
++ * NOTE spcp825-007 not supported this */
++static int spcp8x5_get_msr(struct usb_device *dev, u8 *status,
++			   enum spcp8x5_type type)
++{
++	u8 *status_buffer;
++	int ret;
++
++	/* I return Permited not support here but seem inval device
++	 * is more fix */
++	if (type == SPCP825_007_TYPE)
++		return -EPERM;
++	if (status == NULL)
++		return -EINVAL;
++
++	status_buffer = kmalloc(1, GFP_KERNEL);
++	if (!status_buffer)
++		return -ENOMEM;
++	status_buffer[0] = status[0];
++
++	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
++			      GET_UART_STATUS, GET_UART_STATUS_TYPE,
++			      0, GET_UART_STATUS_MSR, status_buffer, 1, 100);
++	if (ret < 0)
++		dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)",
++			status_buffer, ret);
++
++	dev_dbg(&dev->dev, "0xc0:0x22:0:6  %d - 0x%p ", ret, status_buffer);
++	status[0] = status_buffer[0];
++	kfree(status_buffer);
++
++	return ret;
++}
++
++/* select the work mode.
++ * NOTE this function not supported by spcp825-007 */
++static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
++				 u16 index, enum spcp8x5_type type)
++{
++	int ret;
++
++	/* I return Permited not support here but seem inval device
++	 * is more fix */
++	if (type == SPCP825_007_TYPE)
++		return;
++
++	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++			      SET_WORKING_MODE_TYPE, SET_WORKING_MODE,
++			      value, index, NULL, 0, 100);
++	dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index);
++	if (ret < 0)
++		dev_dbg(&dev->dev,
++			"RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
++}
++
++/* close the serial port. We should wait for data sending to device 1st and
++ * then kill all urb. */
++static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
++{
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	unsigned long flags;
++	unsigned int c_cflag;
++	int bps;
++	long timeout;
++	wait_queue_t wait;
++	int result;
++
++	dbg("%s - port %d", __func__, port->number);
++
++	/* wait for data to drain from the buffer */
++	spin_lock_irqsave(&priv->lock, flags);
++	timeout = SPCP8x5_CLOSING_WAIT;
++	init_waitqueue_entry(&wait, current);
++	add_wait_queue(&port->tty->write_wait, &wait);
++	for (;;) {
++		set_current_state(TASK_INTERRUPTIBLE);
++		if (ringbuf_avail_data(priv->buf) == 0 ||
++		    timeout == 0 || signal_pending(current))
++			break;
++		spin_unlock_irqrestore(&priv->lock, flags);
++		timeout = schedule_timeout(timeout);
++		spin_lock_irqsave(&priv->lock, flags);
++	}
++	set_current_state(TASK_RUNNING);
++	remove_wait_queue(&port->tty->write_wait, &wait);
++
++	/* clear out any remaining data in the buffer */
++	clear_ringbuf(priv->buf);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	/* wait for characters to drain from the device (this is long enough
++	 * for the entire all byte spcp8x5 hardware buffer to drain with no
++	 * flow control for data rates of 1200 bps or more, for lower rates we
++	 * should really know how much data is in the buffer to compute a delay
++	 * that is not unnecessarily long) */
++	bps = tty_get_baud_rate(port->tty);
++	if (bps > 1200)
++		timeout = max((HZ*2560) / bps, HZ/10);
++	else
++		timeout = 2*HZ;
++	set_current_state(TASK_INTERRUPTIBLE);
++	schedule_timeout(timeout);
++
++	/* clear control lines */
++	if (port->tty) {
++		c_cflag = port->tty->termios->c_cflag;
++		if (c_cflag & HUPCL) {
++			spin_lock_irqsave(&priv->lock, flags);
++			priv->line_control = 0;
++			spin_unlock_irqrestore(&priv->lock, flags);
++			spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type);
++		}
++	}
++
++	/* kill urb */
++	if (port->write_urb != NULL) {
++		result = usb_unlink_urb(port->write_urb);
++		if (result)
++			dev_dbg(&port->dev,
++				"usb_unlink_urb(write_urb) = %d\n", result);
++	}
++	result = usb_unlink_urb(port->read_urb);
++	if (result)
++		dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result);
++}
++
++/* set the serial param for transfer. we should check if we really need to
++ * transfer. then if be set flow contorl we should do this too. */
++static void spcp8x5_set_termios(struct usb_serial_port *port,
++				struct ktermios *old_termios)
++{
++	struct usb_serial *serial = port->serial;
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	unsigned long flags;
++	unsigned int cflag = port->tty->termios->c_cflag;
++	unsigned int old_cflag = old_termios->c_cflag;
++	unsigned short uartdata;
++	unsigned char buf[2] = {0, 0};
++	int baud;
++	int i;
++	u8 control;
++
++	if ((!port->tty) || (!port->tty->termios))
++		return;
++
++	/* for the 1st time call this function */
++	spin_lock_irqsave(&priv->lock, flags);
++	if (!priv->termios_initialized) {
++		*(port->tty->termios) = tty_std_termios;
++		port->tty->termios->c_cflag = B115200 | CS8 | CREAD |
++					      HUPCL | CLOCAL;
++		priv->termios_initialized = 1;
++	}
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	/* check that they really want us to change something */
++	if (!tty_termios_hw_change(port->tty->termios, old_termios))
++		return;
++
++	/* set DTR/RTS active */
++	spin_lock_irqsave(&priv->lock, flags);
++	control = priv->line_control;
++	if ((old_cflag & CBAUD) == B0) {
++		priv->line_control |= MCR_DTR;
++		if (!(old_cflag & CRTSCTS))
++			priv->line_control |= MCR_RTS;
++	}
++	if (control != priv->line_control) {
++		control = priv->line_control;
++		spin_unlock_irqrestore(&priv->lock, flags);
++		spcp8x5_set_ctrlLine(serial->dev, control , priv->type);
++	} else {
++		spin_unlock_irqrestore(&priv->lock, flags);
++	}
++
++	/* Set Baud Rate */
++	baud = tty_get_baud_rate(port->tty);;
++	switch (baud) {
++	case 300:	buf[0] = 0x00;	break;
++	case 600:	buf[0] = 0x01;	break;
++	case 1200:	buf[0] = 0x02;	break;
++	case 2400:	buf[0] = 0x03;	break;
++	case 4800:	buf[0] = 0x04;	break;
++	case 9600:	buf[0] = 0x05;	break;
++	case 19200:	buf[0] = 0x07;	break;
++	case 38400:	buf[0] = 0x09;	break;
++	case 57600:	buf[0] = 0x0a;	break;
++	case 115200:	buf[0] = 0x0b;	break;
++	case 230400:	buf[0] = 0x0c;	break;
++	case 460800:	buf[0] = 0x0d;	break;
++	case 921600:	buf[0] = 0x0e;	break;
++/*	case 1200000:	buf[0] = 0x0f;	break; */
++/*	case 2400000:	buf[0] = 0x10;	break; */
++	case 3000000:	buf[0] = 0x11;	break;
++/*	case 6000000:	buf[0] = 0x12;	break; */
++	case 0:
++	case 1000000:
++			buf[0] = 0x0b;	break;
++	default:
++		err("spcp825 driver does not support the baudrate "
++		    "requested, using default of 9600.");
++	}
++
++	/* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */
++	if (cflag & CSIZE) {
++		switch (cflag & CSIZE) {
++		case CS5:
++			buf[1] |= SET_UART_FORMAT_SIZE_5;
++			break;
++		case CS6:
++			buf[1] |= SET_UART_FORMAT_SIZE_6;
++			break;
++		case CS7:
++			buf[1] |= SET_UART_FORMAT_SIZE_7;
++			break;
++		default:
++		case CS8:
++			buf[1] |= SET_UART_FORMAT_SIZE_8;
++			break;
++		}
++	}
++
++	/* Set Stop bit2 : 0:1bit 1:2bit */
++	buf[1] |= (cflag & CSTOPB) ? SET_UART_FORMAT_STOP_2 :
++				     SET_UART_FORMAT_STOP_1;
++
++	/* Set Parity bit3-4 01:Odd 11:Even */
++	if (cflag & PARENB) {
++		buf[1] |= (cflag & PARODD) ?
++		SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ;
++	} else
++		buf[1] |= SET_UART_FORMAT_PAR_NONE;
++
++	uartdata = buf[0] | buf[1]<<8;
++
++	i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++			    SET_UART_FORMAT_TYPE, SET_UART_FORMAT,
++			    uartdata, 0, NULL, 0, 100);
++	if (i < 0)
++		err("Set UART format %#x failed (error = %d)", uartdata, i);
++	dbg("0x21:0x40:0:0  %d\n", i);
++
++	if (cflag & CRTSCTS) {
++		/* enable hardware flow control */
++		spcp8x5_set_workMode(serial->dev, 0x000a,
++				     SET_WORKING_MODE_U2C, priv->type);
++	}
++	return;
++}
++
++/* open the serial port. do some usb system call. set termios and get the line
++ * status of the device. then submit the read urb */
++static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
++{
++	struct ktermios tmp_termios;
++	struct usb_serial *serial = port->serial;
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	int ret;
++	unsigned long flags;
++	u8 status = 0x30;
++	/* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */
++
++	dbg("%s -  port %d", __func__, port->number);
++
++	usb_clear_halt(serial->dev, port->write_urb->pipe);
++	usb_clear_halt(serial->dev, port->read_urb->pipe);
++
++	ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++			      0x09, 0x00,
++			      0x01, 0x00, NULL, 0x00, 100);
++	if (ret)
++		return ret;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	if (port->tty->termios->c_cflag & CBAUD)
++		priv->line_control = MCR_DTR | MCR_RTS;
++	else
++		priv->line_control = 0;
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
++
++	/* Setup termios */
++	if (port->tty)
++		spcp8x5_set_termios(port, &tmp_termios);
++
++	spcp8x5_get_msr(serial->dev, &status, priv->type);
++
++	/* may be we should update uart status here but now we did not do */
++	spin_lock_irqsave(&priv->lock, flags);
++	priv->line_status = status & 0xf0 ;
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	/* FIXME: need to assert RTS and DTR if CRTSCTS off */
++
++	dbg("%s - submitting read urb", __func__);
++	port->read_urb->dev = serial->dev;
++	ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
++	if (ret) {
++		spcp8x5_close(port, NULL);
++		return -EPROTO;
++	}
++	return 0;
++}
++
++/* bulk read call back function. check the status of the urb. if transfer
++ * failed return. then update the status and the tty send data to tty subsys.
++ * submit urb again.
++ */
++static void spcp8x5_read_bulk_callback(struct urb *urb)
++{
++	struct usb_serial_port *port = urb->context;
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	struct tty_struct *tty;
++	unsigned char *data = urb->transfer_buffer;
++	unsigned long flags;
++	int i;
++	int result;
++	u8 status = 0;
++	char tty_flag;
++
++	dev_dbg(&port->dev, "start, urb->status = %d, "
++		"urb->actual_length = %d\n,", urb->status, urb->actual_length);
++
++	/* check the urb status */
++	if (urb->status) {
++		if (!port->open_count)
++			return;
++		if (urb->status == -EPROTO) {
++			/* spcp8x5 mysteriously fails with -EPROTO */
++			/* reschedule the read */
++			urb->status = 0;
++			urb->dev = port->serial->dev;
++			result = usb_submit_urb(urb , GFP_ATOMIC);
++			if (result)
++				dev_dbg(&port->dev,
++					"failed submitting read urb %d\n",
++					result);
++			return;
++		}
++		dev_dbg(&port->dev, "unable to handle the error, exiting.\n");
++		return;
++	}
++
++	/* get tty_flag from status */
++	tty_flag = TTY_NORMAL;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	status = priv->line_status;
++	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
++	spin_unlock_irqrestore(&priv->lock, flags);
++	/* wake up the wait for termios */
++	wake_up_interruptible(&priv->delta_msr_wait);
++
++	/* break takes precedence over parity, which takes precedence over
++	 * framing errors */
++	if (status & UART_BREAK_ERROR)
++		tty_flag = TTY_BREAK;
++	else if (status & UART_PARITY_ERROR)
++		tty_flag = TTY_PARITY;
++	else if (status & UART_FRAME_ERROR)
++		tty_flag = TTY_FRAME;
++	dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
++
++	tty = port->tty;
++	if (tty && urb->actual_length) {
++		tty_buffer_request_room(tty, urb->actual_length + 1);
++		/* overrun is special, not associated with a char */
++		if (status & UART_OVERRUN_ERROR)
++			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
++		for (i = 0; i < urb->actual_length; ++i)
++			tty_insert_flip_char(tty, data[i], tty_flag);
++		tty_flip_buffer_push(tty);
++	}
++
++	/* Schedule the next read _if_ we are still open */
++	if (port->open_count) {
++		urb->dev = port->serial->dev;
++		result = usb_submit_urb(urb , GFP_ATOMIC);
++		if (result)
++			dev_dbg(&port->dev, "failed submitting read urb %d\n",
++				result);
++	}
++
++	return;
++}
++
++/* get data from ring buffer and then write to usb bus */
++static void spcp8x5_send(struct usb_serial_port *port)
++{
++	int count, result;
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->lock, flags);
++
++	if (priv->write_urb_in_use) {
++		dev_dbg(&port->dev, "write urb still used\n");
++		spin_unlock_irqrestore(&priv->lock, flags);
++		return;
++	}
++
++	/* send the 1st urb for writting */
++	memset(port->write_urb->transfer_buffer , 0x00 , port->bulk_out_size);
++	count = get_ringbuf(priv->buf, port->write_urb->transfer_buffer,
++		port->bulk_out_size);
++
++	if (count == 0) {
++		spin_unlock_irqrestore(&priv->lock, flags);
++		return;
++	}
++
++	/* update the urb status */
++	priv->write_urb_in_use = 1;
++
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	port->write_urb->transfer_buffer_length = count;
++	port->write_urb->dev = port->serial->dev;
++
++	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
++	if (result) {
++		dev_dbg(&port->dev, "failed submitting write urb, error %d\n",
++			result);
++		priv->write_urb_in_use = 0;
++		/* TODO: reschedule spcp8x5_send */
++	}
++
++
++	schedule_work(&port->work);
++}
++
++/* this is the call back function for write urb. NOTE we should not sleep in
++ * this routine. check the urb return code and then submit the write urb again
++ * to hold the write loop */
++static void spcp8x5_write_bulk_callback(struct urb *urb)
++{
++	struct usb_serial_port *port = urb->context;
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	int result;
++
++	switch (urb->status) {
++	case 0:
++		/* success */
++		break;
++	case -ECONNRESET:
++	case -ENOENT:
++	case -ESHUTDOWN:
++		/* this urb is terminated, clean up */
++		dev_dbg(&port->dev, "urb shutting down with status: %d\n",
++			urb->status);
++		priv->write_urb_in_use = 0;
++		return;
++	default:
++		/* error in the urb, so we have to resubmit it */
++		dbg("%s - Overflow in write", __func__);
++		dbg("%s - nonzero write bulk status received: %d",
++			__func__, urb->status);
++		port->write_urb->transfer_buffer_length = 1;
++		port->write_urb->dev = port->serial->dev;
++		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
++		if (result)
++			dev_dbg(&port->dev,
++				"failed resubmitting write urb %d\n", result);
++		else
++			return;
++	}
++
++	priv->write_urb_in_use = 0;
++
++	/* send any buffered data */
++	spcp8x5_send(port);
++}
++
++/* write data to ring buffer. and then start the write transfer */
++static int spcp8x5_write(struct usb_serial_port *port,
++			 const unsigned char *buf, int count)
++{
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	unsigned long flags;
++
++	dev_dbg(&port->dev, "%d bytes\n", count);
++
++	if (!count)
++		return count;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	count = put_ringbuf(priv->buf, buf, count);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	spcp8x5_send(port);
++
++	return count;
++}
++
++static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
++				   unsigned int arg)
++{
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	unsigned long flags;
++	unsigned int prevstatus;
++	unsigned int status;
++	unsigned int changed;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	prevstatus = priv->line_status;
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	while (1) {
++		/* wake up in bulk read */
++		interruptible_sleep_on(&priv->delta_msr_wait);
++
++		/* see if a signal did it */
++		if (signal_pending(current))
++			return -ERESTARTSYS;
++
++		spin_lock_irqsave(&priv->lock, flags);
++		status = priv->line_status;
++		spin_unlock_irqrestore(&priv->lock, flags);
++
++		changed = prevstatus^status;
++
++		if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) ||
++		    ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) ||
++		    ((arg & TIOCM_CD)  && (changed & MSR_STATUS_LINE_DCD)) ||
++		    ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS)))
++			return 0;
++
++		prevstatus = status;
++	}
++	/* NOTREACHED */
++	return 0;
++}
++
++static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
++			 unsigned int cmd, unsigned long arg)
++{
++	dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
++
++	switch (cmd) {
++	case TIOCMIWAIT:
++		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
++		return spcp8x5_wait_modem_info(port, arg);
++
++	default:
++		dbg("%s not supported = 0x%04x", __func__, cmd);
++		break;
++	}
++
++	return -ENOIOCTLCMD;
++}
++
++static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
++			    unsigned int set, unsigned int clear)
++{
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	unsigned long flags;
++	u8 control;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	if (set & TIOCM_RTS)
++		priv->line_control |= MCR_RTS;
++	if (set & TIOCM_DTR)
++		priv->line_control |= MCR_DTR;
++	if (clear & TIOCM_RTS)
++		priv->line_control &= ~MCR_RTS;
++	if (clear & TIOCM_DTR)
++		priv->line_control &= ~MCR_DTR;
++	control = priv->line_control;
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
++}
++
++static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
++{
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	unsigned long flags;
++	unsigned int mcr;
++	unsigned int status;
++	unsigned int result;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	mcr = priv->line_control;
++	status = priv->line_status;
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	result = ((mcr & MCR_DTR)			? TIOCM_DTR : 0)
++		  | ((mcr & MCR_RTS)			? TIOCM_RTS : 0)
++		  | ((status & MSR_STATUS_LINE_CTS)	? TIOCM_CTS : 0)
++		  | ((status & MSR_STATUS_LINE_DSR)	? TIOCM_DSR : 0)
++		  | ((status & MSR_STATUS_LINE_RI)	? TIOCM_RI  : 0)
++		  | ((status & MSR_STATUS_LINE_DCD)	? TIOCM_CD  : 0);
++
++	return result;
++}
++
++/* get the avail space room in ring buffer */
++static int spcp8x5_write_room(struct usb_serial_port *port)
++{
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	int room = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	room = ringbuf_avail_space(priv->buf);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	return room;
++}
++
++/* get the number of avail data in write ring buffer */
++static int spcp8x5_chars_in_buffer(struct usb_serial_port *port)
++{
++	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++	int chars = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->lock, flags);
++	chars = ringbuf_avail_data(priv->buf);
++	spin_unlock_irqrestore(&priv->lock, flags);
++
++	return chars;
++}
++
++/* All of the device info needed for the spcp8x5 SIO serial converter */
++static struct usb_serial_driver spcp8x5_device = {
++	.driver = {
++		.owner =	THIS_MODULE,
++		.name =		"SPCP8x5",
++	},
++	.id_table		= id_table,
++	.num_ports		= 1,
++	.open 			= spcp8x5_open,
++	.close 			= spcp8x5_close,
++	.write 			= spcp8x5_write,
++	.set_termios 		= spcp8x5_set_termios,
++	.ioctl 			= spcp8x5_ioctl,
++	.tiocmget 		= spcp8x5_tiocmget,
++	.tiocmset 		= spcp8x5_tiocmset,
++	.write_room 		= spcp8x5_write_room,
++	.read_bulk_callback 	= spcp8x5_read_bulk_callback,
++	.write_bulk_callback	= spcp8x5_write_bulk_callback,
++	.chars_in_buffer 	= spcp8x5_chars_in_buffer,
++	.attach 		= spcp8x5_startup,
++	.shutdown 		= spcp8x5_shutdown,
++};
++
++static int __init spcp8x5_init(void)
++{
++	int retval;
++	retval = usb_serial_register(&spcp8x5_device);
++	if (retval)
++		goto failed_usb_serial_register;
++	retval = usb_register(&spcp8x5_driver);
++	if (retval)
++		goto failed_usb_register;
++	info(DRIVER_DESC " " DRIVER_VERSION);
++	return 0;
++failed_usb_register:
++	usb_serial_deregister(&spcp8x5_device);
++failed_usb_serial_register:
++	return retval;
++}
++
++static void __exit spcp8x5_exit(void)
++{
++	usb_deregister(&spcp8x5_driver);
++	usb_serial_deregister(&spcp8x5_device);
++}
++
++module_init(spcp8x5_init);
++module_exit(spcp8x5_exit);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_VERSION(DRIVER_VERSION);
++MODULE_LICENSE("GPL");
++
++module_param(debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Debug enabled or not");
+diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
+index e3d241f..a1c8aef 100644
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -82,7 +82,6 @@
+ #include <linux/circ_buf.h>
+ #include <linux/mutex.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
+ 
+@@ -265,9 +264,6 @@ static struct usb_serial_driver ti_1port_device = {
+ 	.description		= "TI USB 3410 1 port adapter",
+ 	.usb_driver		= &ti_usb_driver,
+ 	.id_table		= ti_id_table_3410,
+-	.num_interrupt_in	= NUM_DONT_CARE,
+-	.num_bulk_in		= NUM_DONT_CARE,
+-	.num_bulk_out		= 1,
+ 	.num_ports		= 1,
+ 	.attach			= ti_startup,
+ 	.shutdown		= ti_shutdown,
+@@ -296,9 +292,6 @@ static struct usb_serial_driver ti_2port_device = {
+ 	.description		= "TI USB 5052 2 port adapter",
+ 	.usb_driver		= &ti_usb_driver,
+ 	.id_table		= ti_id_table_5052,
+-	.num_interrupt_in	= 1,
+-	.num_bulk_in		= 2,
+-	.num_bulk_out		= 2,
+ 	.num_ports		= 2,
+ 	.attach			= ti_startup,
+ 	.shutdown		= ti_shutdown,
+@@ -415,14 +408,14 @@ static int ti_startup(struct usb_serial *serial)
+ 
+ 
+ 	dbg("%s - product 0x%4X, num configurations %d, configuration value %d",
+-	    __FUNCTION__, le16_to_cpu(dev->descriptor.idProduct),
++	    __func__, le16_to_cpu(dev->descriptor.idProduct),
+ 	    dev->descriptor.bNumConfigurations,
+ 	    dev->actconfig->desc.bConfigurationValue);
+ 
+ 	/* create device structure */
+ 	tdev = kzalloc(sizeof(struct ti_device), GFP_KERNEL);
+ 	if (tdev == NULL) {
+-		dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 	mutex_init(&tdev->td_open_close_lock);
+@@ -432,7 +425,7 @@ static int ti_startup(struct usb_serial *serial)
+ 	/* determine device type */
+ 	if (usb_match_id(serial->interface, ti_id_table_3410))
+ 		tdev->td_is_3410 = 1;
+-	dbg("%s - device type is %s", __FUNCTION__, tdev->td_is_3410 ? "3410" : "5052");
++	dbg("%s - device type is %s", __func__, tdev->td_is_3410 ? "3410" : "5052");
+ 
+ 	/* if we have only 1 configuration, download firmware */
+ 	if (dev->descriptor.bNumConfigurations == 1) {
+@@ -466,7 +459,7 @@ static int ti_startup(struct usb_serial *serial)
+ 	for (i = 0; i < serial->num_ports; ++i) {
+ 		tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
+ 		if (tport == NULL) {
+-			dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++			dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ 			status = -ENOMEM;
+ 			goto free_tports;
+ 		}
+@@ -478,7 +471,7 @@ static int ti_startup(struct usb_serial *serial)
+ 		init_waitqueue_head(&tport->tp_write_wait);
+ 		tport->tp_write_buf = ti_buf_alloc();
+ 		if (tport->tp_write_buf == NULL) {
+-			dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++			dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ 			kfree(tport);
+ 			status = -ENOMEM;
+ 			goto free_tports;
+@@ -511,7 +504,7 @@ static void ti_shutdown(struct usb_serial *serial)
+ 	struct ti_device *tdev = usb_get_serial_data(serial);
+ 	struct ti_port *tport;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	for (i=0; i < serial->num_ports; ++i) {
+ 		tport = usb_get_serial_port_data(serial->port[i]);
+@@ -539,7 +532,7 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+ 			     TI_PIPE_TIMEOUT_ENABLE | 
+ 			     (TI_TRANSFER_TIMEOUT << 2));
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (tport == NULL)
+ 		return -ENODEV;
+@@ -564,10 +557,10 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+ 
+ 	/* start interrupt urb the first time a port is opened on this device */
+ 	if (tdev->td_open_port_count == 0) {
+-		dbg("%s - start interrupt in urb", __FUNCTION__);
++		dbg("%s - start interrupt in urb", __func__);
+ 		urb = tdev->td_serial->port[0]->interrupt_in_urb;
+ 		if (!urb) {
+-			dev_err(&port->dev, "%s - no interrupt urb\n", __FUNCTION__);
++			dev_err(&port->dev, "%s - no interrupt urb\n", __func__);
+ 			status = -EINVAL;
+ 			goto release_lock;
+ 		}
+@@ -576,40 +569,40 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+ 		urb->dev = dev;
+ 		status = usb_submit_urb(urb, GFP_KERNEL);
+ 		if (status) {
+-			dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __FUNCTION__, status);
++			dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __func__, status);
+ 			goto release_lock;
+ 		}
+ 	}
+ 
+ 	ti_set_termios(port, port->tty->termios);
+ 
+-	dbg("%s - sending TI_OPEN_PORT", __FUNCTION__);
++	dbg("%s - sending TI_OPEN_PORT", __func__);
+ 	status = ti_command_out_sync(tdev, TI_OPEN_PORT,
+ 		(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
+ 	if (status) {
+-		dev_err(&port->dev, "%s - cannot send open command, %d\n", __FUNCTION__, status);
++		dev_err(&port->dev, "%s - cannot send open command, %d\n", __func__, status);
+ 		goto unlink_int_urb;
+ 	}
+ 
+-	dbg("%s - sending TI_START_PORT", __FUNCTION__);
++	dbg("%s - sending TI_START_PORT", __func__);
+ 	status = ti_command_out_sync(tdev, TI_START_PORT,
+ 		(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
+ 	if (status) {
+-		dev_err(&port->dev, "%s - cannot send start command, %d\n", __FUNCTION__, status);
++		dev_err(&port->dev, "%s - cannot send start command, %d\n", __func__, status);
+ 		goto unlink_int_urb;
+ 	}
+ 
+-	dbg("%s - sending TI_PURGE_PORT", __FUNCTION__);
++	dbg("%s - sending TI_PURGE_PORT", __func__);
+ 	status = ti_command_out_sync(tdev, TI_PURGE_PORT,
+ 		(__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0);
+ 	if (status) {
+-		dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __FUNCTION__, status);
++		dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __func__, status);
+ 		goto unlink_int_urb;
+ 	}
+ 	status = ti_command_out_sync(tdev, TI_PURGE_PORT,
+ 		(__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0);
+ 	if (status) {
+-		dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __FUNCTION__, status);
++		dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __func__, status);
+ 		goto unlink_int_urb;
+ 	}
+ 
+@@ -620,27 +613,27 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+ 
+ 	ti_set_termios(port, port->tty->termios);
+ 
+-	dbg("%s - sending TI_OPEN_PORT (2)", __FUNCTION__);
++	dbg("%s - sending TI_OPEN_PORT (2)", __func__);
+ 	status = ti_command_out_sync(tdev, TI_OPEN_PORT,
+ 		(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
+ 	if (status) {
+-		dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __FUNCTION__, status);
++		dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __func__, status);
+ 		goto unlink_int_urb;
+ 	}
+ 
+-	dbg("%s - sending TI_START_PORT (2)", __FUNCTION__);
++	dbg("%s - sending TI_START_PORT (2)", __func__);
+ 	status = ti_command_out_sync(tdev, TI_START_PORT,
+ 		(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
+ 	if (status) {
+-		dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __FUNCTION__, status);
++		dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __func__, status);
+ 		goto unlink_int_urb;
+ 	}
+ 
+ 	/* start read urb */
+-	dbg("%s - start read urb", __FUNCTION__);
++	dbg("%s - start read urb", __func__);
+ 	urb = port->read_urb;
+ 	if (!urb) {
+-		dev_err(&port->dev, "%s - no read urb\n", __FUNCTION__);
++		dev_err(&port->dev, "%s - no read urb\n", __func__);
+ 		status = -EINVAL;
+ 		goto unlink_int_urb;
+ 	}
+@@ -650,7 +643,7 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+ 	urb->dev = dev;
+ 	status = usb_submit_urb(urb, GFP_KERNEL);
+ 	if (status) {
+-		dev_err(&port->dev, "%s - submit read urb failed, %d\n", __FUNCTION__, status);
++		dev_err(&port->dev, "%s - submit read urb failed, %d\n", __func__, status);
+ 		goto unlink_int_urb;
+ 	}
+ 
+@@ -664,7 +657,7 @@ unlink_int_urb:
+ 		usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
+ release_lock:
+ 	mutex_unlock(&tdev->td_open_close_lock);
+-	dbg("%s - exit %d", __FUNCTION__, status);
++	dbg("%s - exit %d", __func__, status);
+ 	return status;
+ }
+ 
+@@ -677,7 +670,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
+ 	int status;
+ 	int do_unlock;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 			 
+ 	tdev = usb_get_serial_data(port->serial);
+ 	tport = usb_get_serial_port_data(port);
+@@ -694,11 +687,11 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
+ 
+ 	port_number = port->number - port->serial->minor;
+ 
+-	dbg("%s - sending TI_CLOSE_PORT", __FUNCTION__);
++	dbg("%s - sending TI_CLOSE_PORT", __func__);
+ 	status = ti_command_out_sync(tdev, TI_CLOSE_PORT,
+ 		     (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
+ 	if (status)
+-		dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __FUNCTION__, status);
++		dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __func__, status);
+ 
+ 	/* if mutex_lock is interrupted, continue anyway */
+ 	do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
+@@ -711,7 +704,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
+ 	if (do_unlock)
+ 		mutex_unlock(&tdev->td_open_close_lock);
+ 
+-	dbg("%s - exit", __FUNCTION__);
++	dbg("%s - exit", __func__);
+ }
+ 
+ 
+@@ -721,10 +714,10 @@ static int ti_write(struct usb_serial_port *port, const unsigned char *data,
+ 	struct ti_port *tport = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (count == 0) {
+-		dbg("%s - write request of 0 bytes", __FUNCTION__);
++		dbg("%s - write request of 0 bytes", __func__);
+ 		return 0;
+ 	}
+ 
+@@ -747,7 +740,7 @@ static int ti_write_room(struct usb_serial_port *port)
+ 	int room = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (tport == NULL)
+ 		return -ENODEV;
+@@ -756,7 +749,7 @@ static int ti_write_room(struct usb_serial_port *port)
+ 	room = ti_buf_space_avail(tport->tp_write_buf);
+ 	spin_unlock_irqrestore(&tport->tp_lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 	return room;
+ }
+ 
+@@ -767,7 +760,7 @@ static int ti_chars_in_buffer(struct usb_serial_port *port)
+ 	int chars = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (tport == NULL)
+ 		return -ENODEV;
+@@ -776,7 +769,7 @@ static int ti_chars_in_buffer(struct usb_serial_port *port)
+ 	chars = ti_buf_data_avail(tport->tp_write_buf);
+ 	spin_unlock_irqrestore(&tport->tp_lock, flags);
+ 
+-	dbg("%s - returns %d", __FUNCTION__, chars);
++	dbg("%s - returns %d", __func__, chars);
+ 	return chars;
+ }
+ 
+@@ -786,14 +779,14 @@ static void ti_throttle(struct usb_serial_port *port)
+ 	struct ti_port *tport = usb_get_serial_port_data(port);
+ 	struct tty_struct *tty;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (tport == NULL)
+ 		return;
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - no tty", __FUNCTION__);
++		dbg("%s - no tty", __func__);
+ 		return;
+ 	}
+ 
+@@ -809,21 +802,21 @@ static void ti_unthrottle(struct usb_serial_port *port)
+ 	struct tty_struct *tty;
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (tport == NULL)
+ 		return;
+ 
+ 	tty = port->tty;
+ 	if (!tty) {
+-		dbg("%s - no tty", __FUNCTION__);
++		dbg("%s - no tty", __func__);
+ 		return;
+ 	}
+ 
+ 	if (I_IXOFF(tty) || C_CRTSCTS(tty)) {
+ 		status = ti_restart_read(tport, tty);
+ 		if (status)
+-			dev_err(&port->dev, "%s - cannot restart read, %d\n", __FUNCTION__, status);
++			dev_err(&port->dev, "%s - cannot restart read, %d\n", __func__, status);
+ 	}
+ }
+ 
+@@ -835,24 +828,24 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
+ 	struct async_icount cnow;
+ 	struct async_icount cprev;
+ 
+-	dbg("%s - port %d, cmd = 0x%04X", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd = 0x%04X", __func__, port->number, cmd);
+ 
+ 	if (tport == NULL)
+ 		return -ENODEV;
+ 
+ 	switch (cmd) {
+ 		case TIOCGSERIAL:
+-			dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
++			dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+ 			return ti_get_serial_info(tport, (struct serial_struct __user *)arg);
+ 			break;
+ 
+ 		case TIOCSSERIAL:
+-			dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++			dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
+ 			return ti_set_serial_info(tport, (struct serial_struct __user *)arg);
+ 			break;
+ 
+ 		case TIOCMIWAIT:
+-			dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number);
++			dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
+ 			cprev = tport->tp_icount;
+ 			while (1) {
+ 				interruptible_sleep_on(&tport->tp_msr_wait);
+@@ -873,7 +866,7 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
+ 			break;
+ 
+ 		case TIOCGICOUNT:
+-			dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, port->number, tport->tp_icount.rx, tport->tp_icount.tx);
++			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;
+@@ -895,20 +888,20 @@ static void ti_set_termios(struct usb_serial_port *port,
+ 	int port_number = port->number - port->serial->minor;
+ 	unsigned int mcr;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	cflag = tty->termios->c_cflag;
+ 	iflag = tty->termios->c_iflag;
+ 
+-	dbg("%s - cflag %08x, iflag %08x", __FUNCTION__, cflag, iflag);
+-	dbg("%s - old clfag %08x, old iflag %08x", __FUNCTION__, old_termios->c_cflag, old_termios->c_iflag);
++	dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag);
++	dbg("%s - old clfag %08x, old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag);
+ 
+ 	if (tport == NULL)
+ 		return;
+ 
+ 	config = kmalloc(sizeof(*config), GFP_KERNEL);
+ 	if (!config) {
+-		dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&port->dev, "%s - out of memory\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -992,7 +985,7 @@ static void ti_set_termios(struct usb_serial_port *port,
+ 		tty_encode_baud_rate(tty, baud, baud);
+ 
+ 	dbg("%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d",
+-	__FUNCTION__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
++	__func__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
+ 
+ 	cpu_to_be16s(&config->wBaudRate);
+ 	cpu_to_be16s(&config->wFlags);
+@@ -1001,7 +994,7 @@ static void ti_set_termios(struct usb_serial_port *port,
+ 		(__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config,
+ 		sizeof(*config));
+ 	if (status)
+-		dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __FUNCTION__, port_number, status);
++		dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __func__, port_number, status);
+ 
+ 	/* SET_CONFIG asserts RTS and DTR, reset them correctly */
+ 	mcr = tport->tp_shadow_mcr;
+@@ -1010,7 +1003,7 @@ static void ti_set_termios(struct usb_serial_port *port,
+ 		mcr &= ~(TI_MCR_DTR | TI_MCR_RTS);
+ 	status = ti_set_mcr(tport, mcr);
+ 	if (status)
+-		dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __FUNCTION__, port_number, status);
++		dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __func__, port_number, status);
+ 
+ 	kfree(config);
+ }
+@@ -1022,14 +1015,17 @@ static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
+ 	unsigned int result;
+ 	unsigned int msr;
+ 	unsigned int mcr;
++	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (tport == NULL)
+ 		return -ENODEV;
+ 
++	spin_lock_irqsave(&tport->tp_lock, flags);
+ 	msr = tport->tp_msr;
+ 	mcr = tport->tp_shadow_mcr;
++	spin_unlock_irqrestore(&tport->tp_lock, flags);
+ 
+ 	result = ((mcr & TI_MCR_DTR) ? TIOCM_DTR : 0)
+ 		| ((mcr & TI_MCR_RTS) ? TIOCM_RTS : 0)
+@@ -1039,7 +1035,7 @@ static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
+ 		| ((msr & TI_MSR_RI) ? TIOCM_RI : 0)
+ 		| ((msr & TI_MSR_DSR) ? TIOCM_DSR : 0);
+ 
+-	dbg("%s - 0x%04X", __FUNCTION__, result);
++	dbg("%s - 0x%04X", __func__, result);
+ 
+ 	return result;
+ }
+@@ -1050,12 +1046,14 @@ static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
+ {
+ 	struct ti_port *tport = usb_get_serial_port_data(port);
+ 	unsigned int mcr;
++	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (tport == NULL)
+ 		return -ENODEV;
+ 
++	spin_lock_irqsave(&tport->tp_lock, flags);
+ 	mcr = tport->tp_shadow_mcr;
+ 
+ 	if (set & TIOCM_RTS)
+@@ -1071,6 +1069,7 @@ static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
+ 		mcr &= ~TI_MCR_DTR;
+ 	if (clear & TIOCM_LOOP)
+ 		mcr &= ~TI_MCR_LOOP;
++	spin_unlock_irqrestore(&tport->tp_lock, flags);
+ 
+ 	return ti_set_mcr(tport, mcr);
+ }
+@@ -1081,7 +1080,7 @@ static void ti_break(struct usb_serial_port *port, int break_state)
+ 	struct ti_port *tport = usb_get_serial_port_data(port);
+ 	int status;
+ 
+-	dbg("%s - state = %d", __FUNCTION__, break_state);
++	dbg("%s - state = %d", __func__, break_state);
+ 
+ 	if (tport == NULL)
+ 		return;
+@@ -1093,13 +1092,13 @@ static void ti_break(struct usb_serial_port *port, int break_state)
+ 		TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0);
+ 
+ 	if (status)
+-		dbg("%s - error setting break, %d", __FUNCTION__, status);
++		dbg("%s - error setting break, %d", __func__, status);
+ }
+ 
+ 
+ static void ti_interrupt_callback(struct urb *urb)
+ {
+-	struct ti_device *tdev = (struct ti_device *)urb->context;
++	struct ti_device *tdev = urb->context;
+ 	struct usb_serial_port *port;
+ 	struct usb_serial *serial = tdev->td_serial;
+ 	struct ti_port *tport;
+@@ -1112,7 +1111,7 @@ static void ti_interrupt_callback(struct urb *urb)
+ 	int retval;
+ 	__u8 msr;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -1120,33 +1119,33 @@ static void ti_interrupt_callback(struct urb *urb)
+ 	case -ECONNRESET:
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+-		dbg("%s - urb shutting down, %d", __FUNCTION__, status);
++		dbg("%s - urb shutting down, %d", __func__, status);
+ 		tdev->td_urb_error = 1;
+ 		return;
+ 	default:
+ 		dev_err(dev, "%s - nonzero urb status, %d\n",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		tdev->td_urb_error = 1;
+ 		goto exit;
+ 	}
+ 
+ 	if (length != 2) {
+-		dbg("%s - bad packet size, %d", __FUNCTION__, length);
++		dbg("%s - bad packet size, %d", __func__, length);
+ 		goto exit;
+ 	}
+ 
+ 	if (data[0] == TI_CODE_HARDWARE_ERROR) {
+-		dev_err(dev, "%s - hardware error, %d\n", __FUNCTION__, data[1]);
++		dev_err(dev, "%s - hardware error, %d\n", __func__, data[1]);
+ 		goto exit;
+ 	}
+ 
+ 	port_number = TI_GET_PORT_FROM_CODE(data[0]);
+ 	function = TI_GET_FUNC_FROM_CODE(data[0]);
+ 
+-	dbg("%s - port_number %d, function %d, data 0x%02X", __FUNCTION__, port_number, function, data[1]);
++	dbg("%s - port_number %d, function %d, data 0x%02X", __func__, port_number, function, data[1]);
+ 
+ 	if (port_number >= serial->num_ports) {
+-		dev_err(dev, "%s - bad port number, %d\n", __FUNCTION__, port_number);
++		dev_err(dev, "%s - bad port number, %d\n", __func__, port_number);
+ 		goto exit;
+ 	}
+ 
+@@ -1158,17 +1157,17 @@ static void ti_interrupt_callback(struct urb *urb)
+ 
+ 	switch (function) {
+ 	case TI_CODE_DATA_ERROR:
+-		dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __FUNCTION__, port_number, data[1]);
++		dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __func__, port_number, data[1]);
+ 		break;
+ 
+ 	case TI_CODE_MODEM_STATUS:
+ 		msr = data[1];
+-		dbg("%s - port %d, msr 0x%02X", __FUNCTION__, port_number, msr);
++		dbg("%s - port %d, msr 0x%02X", __func__, port_number, msr);
+ 		ti_handle_new_msr(tport, msr);
+ 		break;
+ 
+ 	default:
+-		dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __FUNCTION__, data[1]);
++		dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __func__, data[1]);
+ 		break;
+ 	}
+ 
+@@ -1176,19 +1175,19 @@ exit:
+ 	retval = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if (retval)
+ 		dev_err(dev, "%s - resubmit interrupt urb failed, %d\n",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ }
+ 
+ 
+ static void ti_bulk_in_callback(struct urb *urb)
+ {
+-	struct ti_port *tport = (struct ti_port *)urb->context;
++	struct ti_port *tport = urb->context;
+ 	struct usb_serial_port *port = tport->tp_port;
+ 	struct device *dev = &urb->dev->dev;
+ 	int status = urb->status;
+ 	int retval = 0;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	switch (status) {
+ 	case 0:
+@@ -1196,13 +1195,13 @@ static void ti_bulk_in_callback(struct urb *urb)
+ 	case -ECONNRESET:
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+-		dbg("%s - urb shutting down, %d", __FUNCTION__, status);
++		dbg("%s - urb shutting down, %d", __func__, status);
+ 		tport->tp_tdev->td_urb_error = 1;
+ 		wake_up_interruptible(&tport->tp_write_wait);
+ 		return;
+ 	default:
+ 		dev_err(dev, "%s - nonzero urb status, %d\n",
+-			__FUNCTION__, status );
++			__func__, status );
+ 		tport->tp_tdev->td_urb_error = 1;
+ 		wake_up_interruptible(&tport->tp_write_wait);
+ 	}
+@@ -1211,16 +1210,16 @@ static void ti_bulk_in_callback(struct urb *urb)
+ 		goto exit;
+ 
+ 	if (status) {
+-		dev_err(dev, "%s - stopping read!\n", __FUNCTION__);
++		dev_err(dev, "%s - stopping read!\n", __func__);
+ 		return;
+ 	}
+ 
+ 	if (port->tty && urb->actual_length) {
+-		usb_serial_debug_data(debug, dev, __FUNCTION__,
++		usb_serial_debug_data(debug, dev, __func__,
+ 			urb->actual_length, urb->transfer_buffer);
+ 
+ 		if (!tport->tp_is_open)
+-			dbg("%s - port closed, dropping data", __FUNCTION__);
++			dbg("%s - port closed, dropping data", __func__);
+ 		else
+ 			ti_recv(&urb->dev->dev, port->tty, urb->transfer_buffer,
+ 				urb->actual_length);
+@@ -1242,18 +1241,18 @@ exit:
+ 	spin_unlock(&tport->tp_lock);
+ 	if (retval)
+ 		dev_err(dev, "%s - resubmit read urb failed, %d\n",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ }
+ 
+ 
+ static void ti_bulk_out_callback(struct urb *urb)
+ {
+-	struct ti_port *tport = (struct ti_port *)urb->context;
++	struct ti_port *tport = urb->context;
+ 	struct usb_serial_port *port = tport->tp_port;
+ 	struct device *dev = &urb->dev->dev;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	tport->tp_write_urb_in_use = 0;
+ 
+@@ -1263,13 +1262,13 @@ static void ti_bulk_out_callback(struct urb *urb)
+ 	case -ECONNRESET:
+ 	case -ENOENT:
+ 	case -ESHUTDOWN:
+-		dbg("%s - urb shutting down, %d", __FUNCTION__, status);
++		dbg("%s - urb shutting down, %d", __func__, status);
+ 		tport->tp_tdev->td_urb_error = 1;
+ 		wake_up_interruptible(&tport->tp_write_wait);
+ 		return;
+ 	default:
+ 		dev_err(dev, "%s - nonzero urb status, %d\n",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		tport->tp_tdev->td_urb_error = 1;
+ 		wake_up_interruptible(&tport->tp_write_wait);
+ 	}
+@@ -1287,7 +1286,7 @@ static void ti_recv(struct device *dev, struct tty_struct *tty,
+ 	do {
+ 		cnt = tty_buffer_request_room(tty, length);
+ 		if (cnt < length) {
+-			dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length - cnt);
++			dev_err(dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt);
+ 			if(cnt == 0)
+ 				break;
+ 		}
+@@ -1308,7 +1307,7 @@ static void ti_send(struct ti_port *tport)
+ 	unsigned long flags;
+ 
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&tport->tp_lock, flags);
+ 
+@@ -1330,7 +1329,7 @@ static void ti_send(struct ti_port *tport)
+ 
+ 	spin_unlock_irqrestore(&tport->tp_lock, flags);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+ 
+ 	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ 			   usb_sndbulkpipe(port->serial->dev,
+@@ -1340,7 +1339,7 @@ static void ti_send(struct ti_port *tport)
+ 
+ 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ 	if (result) {
+-		dev_err(&port->dev, "%s - submit write urb failed, %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - submit write urb failed, %d\n", __func__, result);
+ 		tport->tp_write_urb_in_use = 0; 
+ 		/* TODO: reschedule ti_send */
+ 	} else {
+@@ -1358,14 +1357,17 @@ static void ti_send(struct ti_port *tport)
+ 
+ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
+ {
++	unsigned long flags;
+ 	int status;
+ 
+ 	status = ti_write_byte(tport->tp_tdev,
+ 		tport->tp_uart_base_addr + TI_UART_OFFSET_MCR,
+ 		TI_MCR_RTS | TI_MCR_DTR | TI_MCR_LOOP, mcr);
+ 
++	spin_lock_irqsave(&tport->tp_lock, flags);
+ 	if (!status)
+ 		tport->tp_shadow_mcr = mcr;
++	spin_unlock_irqrestore(&tport->tp_lock, flags);
+ 
+ 	return status;
+ }
+@@ -1379,23 +1381,23 @@ static int ti_get_lsr(struct ti_port *tport)
+ 	int port_number = port->number - port->serial->minor;
+ 	struct ti_port_status *data;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	size = sizeof(struct ti_port_status);
+ 	data = kmalloc(size, GFP_KERNEL);
+ 	if (!data) {
+-		dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&port->dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+ 	status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS,
+ 		(__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size);
+ 	if (status) {
+-		dev_err(&port->dev, "%s - get port status command failed, %d\n", __FUNCTION__, status);
++		dev_err(&port->dev, "%s - get port status command failed, %d\n", __func__, status);
+ 		goto free_data;
+ 	}
+ 
+-	dbg("%s - lsr 0x%02X", __FUNCTION__, data->bLSR);
++	dbg("%s - lsr 0x%02X", __func__, data->bLSR);
+ 
+ 	tport->tp_lsr = data->bLSR;
+ 
+@@ -1456,7 +1458,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
+ 	struct tty_struct *tty;
+ 	unsigned long flags;
+ 
+-	dbg("%s - msr 0x%02X", __FUNCTION__, msr);
++	dbg("%s - msr 0x%02X", __func__, msr);
+ 
+ 	if (msr & TI_MSR_DELTA_MASK) {
+ 		spin_lock_irqsave(&tport->tp_lock, flags);
+@@ -1494,7 +1496,7 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
+ 	struct usb_serial_port *port = tport->tp_port;
+ 	wait_queue_t wait;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irq(&tport->tp_lock);
+ 
+@@ -1626,12 +1628,12 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
+ 	struct ti_write_data_bytes *data;
+ 	struct device *dev = &tdev->td_serial->dev->dev;
+ 
+-	dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __FUNCTION__, addr, mask, byte);
++	dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __func__, addr, mask, byte);
+ 
+ 	size = sizeof(struct ti_write_data_bytes) + 2;
+ 	data = kmalloc(size, GFP_KERNEL);
+ 	if (!data) {
+-		dev_err(dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -1647,7 +1649,7 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
+ 		(__u8 *)data, size);
+ 
+ 	if (status < 0)
+-		dev_err(dev, "%s - failed, %d\n", __FUNCTION__, status);
++		dev_err(dev, "%s - failed, %d\n", __func__, status);
+ 
+ 	kfree(data);
+ 
+@@ -1674,7 +1676,7 @@ static int ti_download_firmware(struct ti_device *tdev,
+ 	buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
+ 	buffer = kmalloc(buffer_size, GFP_KERNEL);
+ 	if (!buffer) {
+-		dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -1688,7 +1690,7 @@ static int ti_download_firmware(struct ti_device *tdev,
+ 	header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header)));
+ 	header->bCheckSum = cs;
+ 
+-	dbg("%s - downloading firmware", __FUNCTION__);
++	dbg("%s - downloading firmware", __func__);
+ 	for (pos = 0; pos < buffer_size; pos += done) {
+ 		len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
+ 		status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000);
+@@ -1699,11 +1701,11 @@ static int ti_download_firmware(struct ti_device *tdev,
+ 	kfree(buffer);
+ 
+ 	if (status) {
+-		dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __FUNCTION__, status);
++		dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __func__, status);
+ 		return status;
+ 	}
+ 
+-	dbg("%s - download successful", __FUNCTION__);
++	dbg("%s - download successful", __func__);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 2138ba8..a9934a3 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -81,7 +81,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
+ 	unsigned int i, j;
+ 	int good_spot;
+ 
+-	dbg("%s %d", __FUNCTION__, num_ports);
++	dbg("%s %d", __func__, num_ports);
+ 
+ 	*minor = 0;
+ 	mutex_lock(&table_lock);
+@@ -101,7 +101,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
+ 
+ 		*minor = i;
+ 		j = 0;
+-		dbg("%s - minor base = %d", __FUNCTION__, *minor);
++		dbg("%s - minor base = %d", __func__, *minor);
+ 		for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
+ 			serial_table[i] = serial;
+ 			serial->port[j++]->number = i;
+@@ -117,7 +117,7 @@ static void return_serial(struct usb_serial *serial)
+ {
+ 	int i;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (serial == NULL)
+ 		return;
+@@ -135,7 +135,7 @@ static void destroy_serial(struct kref *kref)
+ 
+ 	serial = to_usb_serial(kref);
+ 
+-	dbg("%s - %s", __FUNCTION__, serial->type->description);
++	dbg("%s - %s", __func__, serial->type->description);
+ 
+ 	serial->type->shutdown(serial);
+ 
+@@ -187,7 +187,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
+ 	unsigned int portNumber;
+ 	int retval;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* get the serial object associated with this tty pointer */
+ 	serial = usb_serial_get_by_index(tty->index);
+@@ -259,7 +259,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
+ 	if (!port)
+ 		return;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	mutex_lock(&port->mutex);
+ 
+@@ -299,11 +299,11 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
+ 	if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
+ 		goto exit;
+ 
+-	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
++	dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
+ 
+ 	if (!port->open_count) {
+ 		retval = -EINVAL;
+-		dbg("%s - port not opened", __FUNCTION__);
++		dbg("%s - port not opened", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -322,10 +322,10 @@ static int serial_write_room (struct tty_struct *tty)
+ 	if (!port)
+ 		goto exit;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->open_count) {
+-		dbg("%s - port not open", __FUNCTION__);
++		dbg("%s - port not open", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -344,10 +344,10 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
+ 	if (!port)
+ 		goto exit;
+ 
+-	dbg("%s = port %d", __FUNCTION__, port->number);
++	dbg("%s = port %d", __func__, port->number);
+ 
+ 	if (!port->open_count) {
+-		dbg("%s - port not open", __FUNCTION__);
++		dbg("%s - port not open", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -365,10 +365,10 @@ static void serial_throttle (struct tty_struct * tty)
+ 	if (!port)
+ 		return;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->open_count) {
+-		dbg ("%s - port not open", __FUNCTION__);
++		dbg ("%s - port not open", __func__);
+ 		return;
+ 	}
+ 
+@@ -384,10 +384,10 @@ static void serial_unthrottle (struct tty_struct * tty)
+ 	if (!port)
+ 		return;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->open_count) {
+-		dbg("%s - port not open", __FUNCTION__);
++		dbg("%s - port not open", __func__);
+ 		return;
+ 	}
+ 
+@@ -401,13 +401,15 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
+ 	struct usb_serial_port *port = tty->driver_data;
+ 	int retval = -ENODEV;
+ 
++	lock_kernel();
+ 	if (!port)
+ 		goto exit;
+ 
+-	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+ 
++	/* Caution - port->open_count is BKL protected */
+ 	if (!port->open_count) {
+-		dbg ("%s - port not open", __FUNCTION__);
++		dbg ("%s - port not open", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -416,8 +418,8 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
+ 		retval = port->serial->type->ioctl(port, file, cmd, arg);
+ 	else
+ 		retval = -ENOIOCTLCMD;
+-
+ exit:
++	unlock_kernel();
+ 	return retval;
+ }
+ 
+@@ -428,10 +430,10 @@ static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
+ 	if (!port)
+ 		return;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->open_count) {
+-		dbg("%s - port not open", __FUNCTION__);
++		dbg("%s - port not open", __func__);
+ 		return;
+ 	}
+ 
+@@ -446,19 +448,24 @@ static void serial_break (struct tty_struct *tty, int break_state)
+ {
+ 	struct usb_serial_port *port = tty->driver_data;
+ 
+-	if (!port)
++	lock_kernel();
++	if (!port) {
++		unlock_kernel();
+ 		return;
++	}
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->open_count) {
+-		dbg("%s - port not open", __FUNCTION__);
++		dbg("%s - port not open", __func__);
++		unlock_kernel();
+ 		return;
+ 	}
+ 
+ 	/* pass on to the driver specific version of this function if it is available */
+ 	if (port->serial->type->break_ctl)
+ 		port->serial->type->break_ctl(port, break_state);
++	unlock_kernel();
+ }
+ 
+ static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
+@@ -469,7 +476,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
+ 	off_t begin = 0;
+ 	char tmp[40];
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
+ 	for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
+ 		serial = usb_serial_get_by_index(i);
+@@ -515,10 +522,10 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file)
+ 	if (!port)
+ 		return -ENODEV;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->open_count) {
+-		dbg("%s - port not open", __FUNCTION__);
++		dbg("%s - port not open", __func__);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -536,10 +543,10 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
+ 	if (!port)
+ 		return -ENODEV;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->open_count) {
+-		dbg("%s - port not open", __FUNCTION__);
++		dbg("%s - port not open", __func__);
+ 		return -ENODEV;
+ 	}
+ 
+@@ -565,7 +572,7 @@ static void usb_serial_port_work(struct work_struct *work)
+ 		container_of(work, struct usb_serial_port, work);
+ 	struct tty_struct *tty;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	
+ 	if (!port)
+ 		return;
+@@ -581,7 +588,7 @@ static void port_release(struct device *dev)
+ {
+ 	struct usb_serial_port *port = to_usb_serial_port(dev);
+ 
+-	dbg ("%s - %s", __FUNCTION__, dev->bus_id);
++	dbg ("%s - %s", __func__, dev->bus_id);
+ 	port_free(port);
+ }
+ 
+@@ -627,7 +634,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
+ 
+ 	serial = kzalloc(sizeof(*serial), GFP_KERNEL);
+ 	if (!serial) {
+-		dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ 		return NULL;
+ 	}
+ 	serial->dev = usb_get_dev(dev);
+@@ -722,7 +729,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ 	serial = create_serial (dev, interface, type);
+ 	if (!serial) {
+ 		unlock_kernel();
+-		dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
++		dev_err(&interface->dev, "%s - out of memory\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -854,22 +861,6 @@ int usb_serial_probe(struct usb_interface *interface,
+ 	serial->num_interrupt_in = num_interrupt_in;
+ 	serial->num_interrupt_out = num_interrupt_out;
+ 
+-#if 0
+-	/* check that the device meets the driver's requirements */
+-	if ((type->num_interrupt_in != NUM_DONT_CARE &&
+-				type->num_interrupt_in != num_interrupt_in)
+-			|| (type->num_interrupt_out != NUM_DONT_CARE &&
+-				type->num_interrupt_out != num_interrupt_out)
+-			|| (type->num_bulk_in != NUM_DONT_CARE &&
+-				type->num_bulk_in != num_bulk_in)
+-			|| (type->num_bulk_out != NUM_DONT_CARE &&
+-				type->num_bulk_out != num_bulk_out)) {
+-		dbg("wrong number of endpoints");
+-		kfree(serial);
+-		return -EIO;
+-	}
+-#endif
+-
+ 	/* found all that we need */
+ 	dev_info(&interface->dev, "%s converter detected\n",
+ 			type->description);
+@@ -883,7 +874,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ 	serial->num_port_pointers = max_endpoints;
+ 	unlock_kernel();
+ 
+-	dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
++	dbg("%s - setting up %d port structures for this device", __func__, max_endpoints);
+ 	for (i = 0; i < max_endpoints; ++i) {
+ 		port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
+ 		if (!port)
+@@ -1031,7 +1022,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ 		port->dev.release = &port_release;
+ 
+ 		snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
+-		dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
++		dbg ("%s - registering %s", __func__, port->dev.bus_id);
+ 		retval = device_register(&port->dev);
+ 		if (retval)
+ 			dev_err(&port->dev, "Error registering port device, "
+@@ -1090,7 +1081,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ 	struct usb_serial_port *port;
+ 
+ 	usb_serial_console_disconnect(serial);
+-	dbg ("%s", __FUNCTION__);
++	dbg ("%s", __func__);
+ 
+ 	mutex_lock(&serial->disc_mutex);
+ 	usb_set_intfdata (interface, NULL);
+@@ -1174,7 +1165,7 @@ static int __init usb_serial_init(void)
+ 
+ 	result = bus_register(&usb_serial_bus_type);
+ 	if (result) {
+-		err("%s - registering bus driver failed", __FUNCTION__);
++		err("%s - registering bus driver failed", __func__);
+ 		goto exit_bus;
+ 	}
+ 
+@@ -1188,24 +1179,26 @@ static int __init usb_serial_init(void)
+ 	usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ 	usb_serial_tty_driver->init_termios = tty_std_termios;
+ 	usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
++	usb_serial_tty_driver->init_termios.c_ispeed = 9600;
++	usb_serial_tty_driver->init_termios.c_ospeed = 9600;
+ 	tty_set_operations(usb_serial_tty_driver, &serial_ops);
+ 	result = tty_register_driver(usb_serial_tty_driver);
+ 	if (result) {
+-		err("%s - tty_register_driver failed", __FUNCTION__);
++		err("%s - tty_register_driver failed", __func__);
+ 		goto exit_reg_driver;
+ 	}
+ 
+ 	/* register the USB driver */
+ 	result = usb_register(&usb_serial_driver);
+ 	if (result < 0) {
+-		err("%s - usb_register failed", __FUNCTION__);
++		err("%s - usb_register failed", __func__);
+ 		goto exit_tty;
+ 	}
+ 
+ 	/* register the generic driver, if we should */
+ 	result = usb_serial_generic_register(debug);
+ 	if (result < 0) {
+-		err("%s - registering generic driver failed", __FUNCTION__);
++		err("%s - registering generic driver failed", __func__);
+ 		goto exit_generic;
+ 	}
+ 
+@@ -1223,7 +1216,7 @@ exit_reg_driver:
+ 	bus_unregister(&usb_serial_bus_type);
+ 
+ exit_bus:
+-	err ("%s - returning with error %d", __FUNCTION__, result);
++	err ("%s - returning with error %d", __func__, result);
+ 	put_tty_driver(usb_serial_tty_driver);
+ 	return result;
+ }
+diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
+index 257a5e4..f9fc926 100644
+--- a/drivers/usb/serial/usb_debug.c
++++ b/drivers/usb/serial/usb_debug.c
+@@ -35,9 +35,6 @@ static struct usb_serial_driver debug_device = {
+ 		.name =		"debug",
+ 	},
+ 	.id_table =		id_table,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		1,
+ };
+ 
+diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
+index c2b01f7..5fc2012 100644
+--- a/drivers/usb/serial/visor.c
++++ b/drivers/usb/serial/visor.c
+@@ -189,9 +189,6 @@ static struct usb_serial_driver handspring_device = {
+ 	.description =		"Handspring Visor / Palm OS",
+ 	.usb_driver =		&visor_driver,
+ 	.id_table =		id_table,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		2,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		2,
+ 	.open =			visor_open,
+ 	.close =		visor_close,
+@@ -219,9 +216,6 @@ static struct usb_serial_driver clie_5_device = {
+ 	.description =		"Sony Clie 5.0",
+ 	.usb_driver =		&visor_driver,
+ 	.id_table =		clie_id_5_table,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		2,
+-	.num_bulk_out =		2,
+ 	.num_ports =		2,
+ 	.open =			visor_open,
+ 	.close =		visor_close,
+@@ -249,9 +243,6 @@ static struct usb_serial_driver clie_3_5_device = {
+ 	.description =		"Sony Clie 3.5",
+ 	.usb_driver =		&visor_driver,
+ 	.id_table =		clie_id_3_5_table,
+-	.num_interrupt_in =	0,
+-	.num_bulk_in =		1,
+-	.num_bulk_out =		1,
+ 	.num_ports =		1,
+ 	.open =			visor_open,
+ 	.close =		visor_close,
+@@ -290,7 +281,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
+ 	unsigned long flags;
+ 	int result = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (!port->read_urb) {
+ 		/* this is needed for some brain dead Sony devices */
+@@ -322,16 +313,16 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
+ 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ 	if (result) {
+ 		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n",
+-			__FUNCTION__, result);
++			__func__, result);
+ 		goto exit;
+ 	}
+ 	
+ 	if (port->interrupt_in_urb) {
+-		dbg("%s - adding interrupt input for treo", __FUNCTION__);
++		dbg("%s - adding interrupt input for treo", __func__);
+ 		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ 		if (result)
+ 			dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n",
+-				__FUNCTION__, result);
++				__func__, result);
+ 	}
+ exit:	
+ 	return result;
+@@ -343,7 +334,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
+ 	struct visor_private *priv = usb_get_serial_port_data(port);
+ 	unsigned char *transfer_buffer;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 			 
+ 	/* shutdown our urbs */
+ 	usb_kill_urb(port->read_urb);
+@@ -379,12 +370,12 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
+ 	unsigned long flags;
+ 	int status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+-		dbg("%s - write limit hit\n", __FUNCTION__);
++		dbg("%s - write limit hit\n", __func__);
+ 		return 0;
+ 	}
+ 	priv->outstanding_urbs++;
+@@ -406,7 +397,7 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
+ 
+ 	memcpy (buffer, buf, count);
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+ 
+ 	usb_fill_bulk_urb (urb, serial->dev,
+ 			   usb_sndbulkpipe (serial->dev,
+@@ -418,7 +409,7 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
+ 	status = usb_submit_urb(urb, GFP_ATOMIC);
+ 	if (status) {
+ 		dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+-			__FUNCTION__, status);
++			__func__, status);
+ 		count = status;
+ 		goto error;
+ 	} else {
+@@ -449,7 +440,7 @@ static int visor_write_room (struct usb_serial_port *port)
+ 	struct visor_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/*
+ 	 * We really can take anything the user throws at us
+@@ -460,7 +451,7 @@ static int visor_write_room (struct usb_serial_port *port)
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
+ 		spin_unlock_irqrestore(&priv->lock, flags);
+-		dbg("%s - write limit hit\n", __FUNCTION__);
++		dbg("%s - write limit hit\n", __func__);
+ 		return 0;
+ 	}
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+@@ -471,13 +462,15 @@ static int visor_write_room (struct usb_serial_port *port)
+ 
+ static int visor_chars_in_buffer (struct usb_serial_port *port)
+ {
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	/* 
+ 	 * We can't really account for how much data we
+ 	 * have sent out, but hasn't made it through to the
+ 	 * device, so just tell the tty layer that everything
+ 	 * is flushed.
++	 *
++	 * FIXME: Should walk outstanding_urbs
+ 	 */
+ 	return 0;
+ }
+@@ -485,7 +478,7 @@ static int visor_chars_in_buffer (struct usb_serial_port *port)
+ 
+ static void visor_write_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct visor_private *priv = usb_get_serial_port_data(port);
+ 	int status = urb->status;
+ 	unsigned long flags;
+@@ -493,11 +486,11 @@ static void visor_write_bulk_callback (struct urb *urb)
+ 	/* free up the transfer buffer, as usb_free_urb() does not do this */
+ 	kfree (urb->transfer_buffer);
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status)
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	--priv->outstanding_urbs;
+@@ -509,7 +502,7 @@ static void visor_write_bulk_callback (struct urb *urb)
+ 
+ static void visor_read_bulk_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct visor_private *priv = usb_get_serial_port_data(port);
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int status = urb->status;
+@@ -517,15 +510,15 @@ static void visor_read_bulk_callback (struct urb *urb)
+ 	int result;
+ 	int available_room;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	tty = port->tty;
+ 	if (tty && urb->actual_length) {
+@@ -551,7 +544,7 @@ static void visor_read_bulk_callback (struct urb *urb)
+ 				   visor_read_bulk_callback, port);
+ 		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 		if (result)
+-			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ 	} else {
+ 		priv->actually_throttled = 1;
+ 	}
+@@ -560,7 +553,7 @@ static void visor_read_bulk_callback (struct urb *urb)
+ 
+ static void visor_read_int_callback (struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	int status = urb->status;
+ 	int result;
+ 
+@@ -573,11 +566,11 @@ static void visor_read_int_callback (struct urb *urb)
+ 	case -ESHUTDOWN:
+ 		/* this urb is terminated, clean up */
+ 		dbg("%s - urb shutting down with status: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	default:
+ 		dbg("%s - nonzero urb status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		goto exit;
+ 	}
+ 
+@@ -588,14 +581,14 @@ static void visor_read_int_callback (struct urb *urb)
+ 	 * Rumor has it this endpoint is used to notify when data
+ 	 * is ready to be read from the bulk ones.
+ 	 */
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++	usb_serial_debug_data(debug, &port->dev, __func__,
+ 			      urb->actual_length, urb->transfer_buffer);
+ 
+ exit:
+ 	result = usb_submit_urb (urb, GFP_ATOMIC);
+ 	if (result)
+ 		dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n",
+-			__FUNCTION__, result);
++			__func__, result);
+ }
+ 
+ static void visor_throttle (struct usb_serial_port *port)
+@@ -603,7 +596,7 @@ static void visor_throttle (struct usb_serial_port *port)
+ 	struct visor_private *priv = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	priv->throttled = 1;
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+@@ -616,7 +609,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
+ 	unsigned long flags;
+ 	int result;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 	priv->throttled = 0;
+ 	priv->actually_throttled = 0;
+@@ -625,7 +618,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
+ 	port->read_urb->dev = port->serial->dev;
+ 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ 	if (result)
+-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ }
+ 
+ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id)
+@@ -638,11 +631,11 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
+ 	int i;
+ 	int num_ports = 0;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL);
+ 	if (!transfer_buffer) {
+-		dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __FUNCTION__,
++		dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
+ 			sizeof(*connection_info));
+ 		return -ENOMEM;
+ 	}
+@@ -655,7 +648,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
+ 				  sizeof(*connection_info), 300);
+ 	if (retval < 0) {
+ 		dev_err(dev, "%s - error %d getting connection information\n",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ 		goto exit;
+ 	}
+ 
+@@ -715,7 +708,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
+ 				  0x02, 300);
+ 	if (retval < 0)
+ 		dev_err(dev, "%s - error %d getting bytes available request\n",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ 	retval = 0;
+ 
+ exit:
+@@ -731,11 +724,11 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
+ 	unsigned char *transfer_buffer;
+ 	int retval;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	transfer_buffer =  kmalloc (sizeof (*connection_info), GFP_KERNEL);
+ 	if (!transfer_buffer) {
+-		dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __FUNCTION__,
++		dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
+ 			sizeof(*connection_info));
+ 		return -ENOMEM;
+ 	}
+@@ -747,9 +740,9 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
+ 				  sizeof (*connection_info), 300);
+ 	if (retval < 0)
+ 		dev_err(dev, "%s - error %d getting connection info\n",
+-			__FUNCTION__, retval);
++			__func__, retval);
+ 	else
+-		usb_serial_debug_data(debug, &serial->dev->dev, __FUNCTION__,
++		usb_serial_debug_data(debug, &serial->dev->dev, __func__,
+ 				      retval, transfer_buffer);
+ 
+ 	kfree (transfer_buffer);
+@@ -762,7 +755,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id *i
+ 	int retval = 0;
+ 	int (*startup) (struct usb_serial *serial, const struct usb_device_id *id);
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
+ 		err("active config #%d != 1 ??",
+@@ -816,7 +809,7 @@ static int clie_3_5_startup (struct usb_serial *serial)
+ 	int result;
+ 	u8 data;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/*
+ 	 * Note that PEG-300 series devices expect the following two calls.
+@@ -827,11 +820,11 @@ static int clie_3_5_startup (struct usb_serial *serial)
+ 				  USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
+ 				  0, 0, &data, 1, 3000);
+ 	if (result < 0) {
+-		dev_err(dev, "%s: get config number failed: %d\n", __FUNCTION__, result);
++		dev_err(dev, "%s: get config number failed: %d\n", __func__, result);
+ 		return result;
+ 	}
+ 	if (result != 1) {
+-		dev_err(dev, "%s: get config number bad return length: %d\n", __FUNCTION__, result);
++		dev_err(dev, "%s: get config number bad return length: %d\n", __func__, result);
+ 		return -EIO;
+ 	}
+ 
+@@ -841,11 +834,11 @@ static int clie_3_5_startup (struct usb_serial *serial)
+ 				  USB_DIR_IN | USB_RECIP_INTERFACE,
+ 				  0, 0, &data, 1, 3000);
+ 	if (result < 0) {
+-		dev_err(dev, "%s: get interface number failed: %d\n", __FUNCTION__, result);
++		dev_err(dev, "%s: get interface number failed: %d\n", __func__, result);
+ 		return result;
+ 	}
+ 	if (result != 1) {
+-		dev_err(dev, "%s: get interface number bad return length: %d\n", __FUNCTION__, result);
++		dev_err(dev, "%s: get interface number bad return length: %d\n", __func__, result);
+ 		return -EIO;
+ 	}
+ 
+@@ -863,7 +856,7 @@ static int treo_attach (struct usb_serial *serial)
+ 	    (serial->num_interrupt_in == 0))
+ 		goto generic_startup;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/*
+ 	* It appears that Treos and Kyoceras want to use the 
+@@ -894,7 +887,7 @@ generic_startup:
+ 
+ static int clie_5_attach (struct usb_serial *serial)
+ {
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* TH55 registers 2 ports. 
+ 	   Communication in from the UX50/TH55 uses bulk_in_endpointAddress from port 0 
+@@ -918,7 +911,7 @@ static void visor_shutdown (struct usb_serial *serial)
+ 	struct visor_private *priv;
+ 	int i;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	for (i = 0; i < serial->num_ports; i++) {
+ 		priv = usb_get_serial_port_data(serial->port[i]);
+@@ -931,7 +924,7 @@ static void visor_shutdown (struct usb_serial *serial)
+ 
+ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+ {
+-	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+ 
+ 	return -ENOIOCTLCMD;
+ }
+diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
+index 38726ef..e96bf86 100644
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -164,9 +164,6 @@ static struct usb_serial_driver whiteheat_fake_device = {
+ 	.description =		"Connect Tech - WhiteHEAT - (prerenumeration)",
+ 	.usb_driver =		&whiteheat_driver,
+ 	.id_table =		id_table_prerenumeration,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		1,
+ 	.probe =		whiteheat_firmware_download,
+ 	.attach =		whiteheat_firmware_attach,
+@@ -180,9 +177,6 @@ static struct usb_serial_driver whiteheat_device = {
+ 	.description =		"Connect Tech - WhiteHEAT",
+ 	.usb_driver =		&whiteheat_driver,
+ 	.id_table =		id_table_std,
+-	.num_interrupt_in =	NUM_DONT_CARE,
+-	.num_bulk_in =		NUM_DONT_CARE,
+-	.num_bulk_out =		NUM_DONT_CARE,
+ 	.num_ports =		4,
+ 	.attach =		whiteheat_attach,
+ 	.shutdown =		whiteheat_shutdown,
+@@ -225,7 +219,7 @@ struct whiteheat_urb_wrap {
+ struct whiteheat_private {
+ 	spinlock_t		lock;
+ 	__u8			flags;
+-	__u8			mcr;
++	__u8			mcr;		/* FIXME: no locking on mcr */
+ 	struct list_head	rx_urbs_free;
+ 	struct list_head	rx_urbs_submitted;
+ 	struct list_head	rx_urb_q;
+@@ -288,7 +282,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
+ 	int response;
+ 	const struct whiteheat_hex_record *record;
+ 	
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 	
+ 	response = ezusb_set_reset (serial, 1);
+ 
+@@ -298,7 +292,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
+ 				(unsigned char *)record->data, record->data_size, 0xa0);
+ 		if (response < 0) {
+ 			err("%s - ezusb_writememory failed for loader (%d %04X %p %d)",
+-				__FUNCTION__, response, record->address, record->data, record->data_size);
++				__func__, response, record->address, record->data, record->data_size);
+ 			break;
+ 		}
+ 		++record;
+@@ -315,7 +309,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
+ 				(unsigned char *)record->data, record->data_size, 0xa3);
+ 		if (response < 0) {
+ 			err("%s - ezusb_writememory failed for first firmware step (%d %04X %p %d)", 
+-				__FUNCTION__, response, record->address, record->data, record->data_size);
++				__func__, response, record->address, record->data, record->data_size);
+ 			break;
+ 		}
+ 		++record;
+@@ -329,7 +323,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
+ 				(unsigned char *)record->data, record->data_size, 0xa0);
+ 		if (response < 0) {
+ 			err("%s - ezusb_writememory failed for second firmware step (%d %04X %p %d)", 
+-				__FUNCTION__, response, record->address, record->data, record->data_size);
++				__func__, response, record->address, record->data, record->data_size);
+ 			break;
+ 		}
+ 		++record;
+@@ -567,7 +561,7 @@ static void whiteheat_shutdown (struct usb_serial *serial)
+ 	struct list_head *tmp2;
+ 	int i;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	/* free up our private data for our command port */
+ 	command_port = serial->port[COMMAND_PORT];
+@@ -604,7 +598,7 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
+ 	int		retval = 0;
+ 	struct ktermios	old_term;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	retval = start_command_port(port->serial);
+ 	if (retval)
+@@ -637,14 +631,14 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
+ 	/* Start reading from the device */
+ 	retval = start_port_read(port);
+ 	if (retval) {
+-		err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);
++		err("%s - failed submitting read urb, error %d", __func__, retval);
+ 		firm_close(port);
+ 		stop_command_port(port->serial);
+ 		goto exit;
+ 	}
+ 
+ exit:
+-	dbg("%s - exit, retval = %d", __FUNCTION__, retval);
++	dbg("%s - exit, retval = %d", __func__, retval);
+ 	return retval;
+ }
+ 
+@@ -657,7 +651,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
+ 	struct list_head *tmp;
+ 	struct list_head *tmp2;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	mutex_lock(&port->serial->disc_mutex);
+ 	/* filp is NULL when called from usb_serial_disconnect */
+@@ -732,10 +726,10 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
+ 	unsigned long flags;
+ 	struct list_head *tmp;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (count == 0) {
+-		dbg("%s - write request of 0 bytes", __FUNCTION__);
++		dbg("%s - write request of 0 bytes", __func__);
+ 		return (0);
+ 	}
+ 
+@@ -754,13 +748,13 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
+ 		bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+ 		memcpy (urb->transfer_buffer, buf + sent, bytes);
+ 
+-		usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer);
++		usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer);
+ 
+ 		urb->dev = serial->dev;
+ 		urb->transfer_buffer_length = bytes;
+ 		result = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (result) {
+-			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++			err("%s - failed submitting write urb, error %d", __func__, result);
+ 			sent = result;
+ 			spin_lock_irqsave(&info->lock, flags);
+ 			list_add(tmp, &info->tx_urbs_free);
+@@ -786,7 +780,7 @@ static int whiteheat_write_room(struct usb_serial_port *port)
+ 	int room = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 	
+ 	spin_lock_irqsave(&info->lock, flags);
+ 	list_for_each(tmp, &info->tx_urbs_free)
+@@ -794,7 +788,7 @@ static int whiteheat_write_room(struct usb_serial_port *port)
+ 	spin_unlock_irqrestore(&info->lock, flags);
+ 	room *= port->bulk_out_size;
+ 
+-	dbg("%s - returns %d", __FUNCTION__, room);
++	dbg("%s - returns %d", __func__, room);
+ 	return (room);
+ }
+ 
+@@ -804,7 +798,7 @@ static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file)
+ 	struct whiteheat_private *info = usb_get_serial_port_data(port);
+ 	unsigned int modem_signals = 0;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	firm_get_dtr_rts(port);
+ 	if (info->mcr & UART_MCR_DTR)
+@@ -821,7 +815,7 @@ static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
+ {
+ 	struct whiteheat_private *info = usb_get_serial_port_data(port);
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	if (set & TIOCM_RTS)
+ 		info->mcr |= UART_MCR_RTS;
+@@ -844,7 +838,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
+ 	struct serial_struct serstruct;
+ 	void __user *user_arg = (void __user *)arg;
+ 
+-	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+ 
+ 	switch (cmd) {
+ 		case TIOCGSERIAL:
+@@ -886,7 +880,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
+ 
+ static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
+ {
+-	dbg("%s -port %d", __FUNCTION__, port->number);
++	dbg("%s -port %d", __func__, port->number);
+ 	firm_setup_port(port);
+ }
+ 
+@@ -904,7 +898,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
+ 	int chars = 0;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&info->lock, flags);
+ 	list_for_each(tmp, &info->tx_urbs_submitted) {
+@@ -913,7 +907,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
+ 	}
+ 	spin_unlock_irqrestore(&info->lock, flags);
+ 
+-	dbg ("%s - returns %d", __FUNCTION__, chars);
++	dbg ("%s - returns %d", __func__, chars);
+ 	return chars;
+ }
+ 
+@@ -923,7 +917,7 @@ static void whiteheat_throttle (struct usb_serial_port *port)
+ 	struct whiteheat_private *info = usb_get_serial_port_data(port);
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&info->lock, flags);
+ 	info->flags |= THROTTLED;
+@@ -939,7 +933,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
+ 	int actually_throttled;
+ 	unsigned long flags;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock_irqsave(&info->lock, flags);
+ 	actually_throttled = info->flags & ACTUALLY_THROTTLED;
+@@ -960,7 +954,7 @@ static void command_port_write_callback(struct urb *urb)
+ {
+ 	int status = urb->status;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	if (status) {
+ 		dbg("nonzero urb status: %d", status);
+@@ -971,28 +965,28 @@ static void command_port_write_callback(struct urb *urb)
+ 
+ static void command_port_read_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *command_port = urb->context;
+ 	struct whiteheat_command_private *command_info;
+ 	int status = urb->status;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	int result;
+ 
+-	dbg("%s", __FUNCTION__);
++	dbg("%s", __func__);
+ 
+ 	command_info = usb_get_serial_port_data(command_port);
+ 	if (!command_info) {
+-		dbg ("%s - command_info is NULL, exiting.", __FUNCTION__);
++		dbg ("%s - command_info is NULL, exiting.", __func__);
+ 		return;
+ 	}
+ 	if (status) {
+-		dbg("%s - nonzero urb status: %d", __FUNCTION__, status);
++		dbg("%s - nonzero urb status: %d", __func__, status);
+ 		if (status != -ENOENT)
+ 			command_info->command_finished = WHITEHEAT_CMD_FAILURE;
+ 		wake_up(&command_info->wait_command);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &command_port->dev, __func__, urb->actual_length, data);
+ 
+ 	if (data[0] == WHITEHEAT_CMD_COMPLETE) {
+ 		command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
+@@ -1002,38 +996,38 @@ static void command_port_read_callback(struct urb *urb)
+ 		wake_up(&command_info->wait_command);
+ 	} else if (data[0] == WHITEHEAT_EVENT) {
+ 		/* These are unsolicited reports from the firmware, hence no waiting command to wakeup */
+-		dbg("%s - event received", __FUNCTION__);
++		dbg("%s - event received", __func__);
+ 	} else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
+ 		memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1);
+ 		command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
+ 		wake_up(&command_info->wait_command);
+ 	} else {
+-		dbg("%s - bad reply from firmware", __FUNCTION__);
++		dbg("%s - bad reply from firmware", __func__);
+ 	}
+ 	
+ 	/* Continue trying to always read */
+ 	command_port->read_urb->dev = command_port->serial->dev;
+ 	result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
+ 	if (result)
+-		dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++		dbg("%s - failed resubmitting read urb, error %d", __func__, result);
+ }
+ 
+ 
+ static void whiteheat_read_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct whiteheat_urb_wrap *wrap;
+ 	unsigned char *data = urb->transfer_buffer;
+ 	struct whiteheat_private *info = usb_get_serial_port_data(port);
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock(&info->lock);
+ 	wrap = urb_to_wrap(urb, &info->rx_urbs_submitted);
+ 	if (!wrap) {
+ 		spin_unlock(&info->lock);
+-		err("%s - Not my urb!", __FUNCTION__);
++		err("%s - Not my urb!", __func__);
+ 		return;
+ 	}
+ 	list_del(&wrap->list);
+@@ -1041,14 +1035,14 @@ static void whiteheat_read_callback(struct urb *urb)
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero read bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		spin_lock(&info->lock);
+ 		list_add(&wrap->list, &info->rx_urbs_free);
+ 		spin_unlock(&info->lock);
+ 		return;
+ 	}
+ 
+-	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ 
+ 	spin_lock(&info->lock);
+ 	list_add_tail(&wrap->list, &info->rx_urb_q);
+@@ -1065,18 +1059,18 @@ static void whiteheat_read_callback(struct urb *urb)
+ 
+ static void whiteheat_write_callback(struct urb *urb)
+ {
+-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++	struct usb_serial_port *port = urb->context;
+ 	struct whiteheat_private *info = usb_get_serial_port_data(port);
+ 	struct whiteheat_urb_wrap *wrap;
+ 	int status = urb->status;
+ 
+-	dbg("%s - port %d", __FUNCTION__, port->number);
++	dbg("%s - port %d", __func__, port->number);
+ 
+ 	spin_lock(&info->lock);
+ 	wrap = urb_to_wrap(urb, &info->tx_urbs_submitted);
+ 	if (!wrap) {
+ 		spin_unlock(&info->lock);
+-		err("%s - Not my urb!", __FUNCTION__);
++		err("%s - Not my urb!", __func__);
+ 		return;
+ 	}
+ 	list_move(&wrap->list, &info->tx_urbs_free);
+@@ -1084,7 +1078,7 @@ static void whiteheat_write_callback(struct urb *urb)
+ 
+ 	if (status) {
+ 		dbg("%s - nonzero write bulk status received: %d",
+-		    __FUNCTION__, status);
++		    __func__, status);
+ 		return;
+ 	}
+ 
+@@ -1104,7 +1098,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
+ 	int retval = 0;
+ 	int t;
+ 
+-	dbg("%s - command %d", __FUNCTION__, command);
++	dbg("%s - command %d", __func__, command);
+ 
+ 	command_port = port->serial->port[COMMAND_PORT];
+ 	command_info = usb_get_serial_port_data(command_port);
+@@ -1118,7 +1112,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
+ 	command_port->write_urb->dev = port->serial->dev;
+ 	retval = usb_submit_urb (command_port->write_urb, GFP_NOIO);
+ 	if (retval) {
+-		dbg("%s - submit urb failed", __FUNCTION__);
++		dbg("%s - submit urb failed", __func__);
+ 		goto exit;
+ 	}
+ 
+@@ -1129,19 +1123,19 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
+ 		usb_kill_urb(command_port->write_urb);
+ 
+ 	if (command_info->command_finished == false) {
+-		dbg("%s - command timed out.", __FUNCTION__);
++		dbg("%s - command timed out.", __func__);
+ 		retval = -ETIMEDOUT;
+ 		goto exit;
+ 	}
+ 
+ 	if (command_info->command_finished == WHITEHEAT_CMD_FAILURE) {
+-		dbg("%s - command failed.", __FUNCTION__);
++		dbg("%s - command failed.", __func__);
+ 		retval = -EIO;
+ 		goto exit;
+ 	}
+ 
+ 	if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) {
+-		dbg("%s - command completed.", __FUNCTION__);
++		dbg("%s - command completed.", __func__);
+ 		switch (command) {
+ 			case WHITEHEAT_GET_DTR_RTS:
+ 				info = usb_get_serial_port_data(port);
+@@ -1186,7 +1180,7 @@ static int firm_setup_port(struct usb_serial_port *port) {
+ 		default:
+ 		case CS8:	port_settings.bits = 8;   break;
+ 	}
+-	dbg("%s - data bits = %d", __FUNCTION__, port_settings.bits);
++	dbg("%s - data bits = %d", __func__, port_settings.bits);
+ 	
+ 	/* determine the parity */
+ 	if (cflag & PARENB)
+@@ -1202,21 +1196,21 @@ static int firm_setup_port(struct usb_serial_port *port) {
+ 				port_settings.parity = WHITEHEAT_PAR_EVEN;
+ 	else
+ 		port_settings.parity = WHITEHEAT_PAR_NONE;
+-	dbg("%s - parity = %c", __FUNCTION__, port_settings.parity);
++	dbg("%s - parity = %c", __func__, port_settings.parity);
+ 
+ 	/* figure out the stop bits requested */
+ 	if (cflag & CSTOPB)
+ 		port_settings.stop = 2;
+ 	else
+ 		port_settings.stop = 1;
+-	dbg("%s - stop bits = %d", __FUNCTION__, port_settings.stop);
++	dbg("%s - stop bits = %d", __func__, port_settings.stop);
+ 
+ 	/* figure out the flow control settings */
+ 	if (cflag & CRTSCTS)
+ 		port_settings.hflow = (WHITEHEAT_HFLOW_CTS | WHITEHEAT_HFLOW_RTS);
+ 	else
+ 		port_settings.hflow = WHITEHEAT_HFLOW_NONE;
+-	dbg("%s - hardware flow control = %s %s %s %s", __FUNCTION__,
++	dbg("%s - hardware flow control = %s %s %s %s", __func__,
+ 	    (port_settings.hflow & WHITEHEAT_HFLOW_CTS) ? "CTS" : "",
+ 	    (port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "",
+ 	    (port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "",
+@@ -1227,15 +1221,15 @@ static int firm_setup_port(struct usb_serial_port *port) {
+ 		port_settings.sflow = WHITEHEAT_SFLOW_RXTX;
+ 	else
+ 		port_settings.sflow = WHITEHEAT_SFLOW_NONE;
+-	dbg("%s - software flow control = %c", __FUNCTION__, port_settings.sflow);
++	dbg("%s - software flow control = %c", __func__, port_settings.sflow);
+ 	
+ 	port_settings.xon = START_CHAR(port->tty);
+ 	port_settings.xoff = STOP_CHAR(port->tty);
+-	dbg("%s - XON = %2x, XOFF = %2x", __FUNCTION__, port_settings.xon, port_settings.xoff);
++	dbg("%s - XON = %2x, XOFF = %2x", __func__, port_settings.xon, port_settings.xoff);
+ 
+ 	/* get the baud rate wanted */
+ 	port_settings.baud = tty_get_baud_rate(port->tty);
+-	dbg("%s - baud rate = %d", __FUNCTION__, port_settings.baud);
++	dbg("%s - baud rate = %d", __func__, port_settings.baud);
+ 
+ 	/* fixme: should set validated settings */
+ 	tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud);
+@@ -1318,7 +1312,7 @@ static int start_command_port(struct usb_serial *serial)
+ 		command_port->read_urb->dev = serial->dev;
+ 		retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
+ 		if (retval) {
+-			err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);
++			err("%s - failed submitting read urb, error %d", __func__, retval);
+ 			goto exit;
+ 		}
+ 	}
+@@ -1454,7 +1448,7 @@ static void rx_data_softint(struct work_struct *work)
+ 		urb->dev = port->serial->dev;
+ 		result = usb_submit_urb(urb, GFP_ATOMIC);
+ 		if (result) {
+-			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++			err("%s - failed resubmitting read urb, error %d", __func__, result);
+ 			spin_lock_irqsave(&info->lock, flags);
+ 			list_add(tmp, &info->rx_urbs_free);
+ 			continue;
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 7e53333..0f6d234 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -32,8 +32,8 @@ config USB_STORAGE_DEBUG
+ 	  verbose debugging messages.
+ 
+ config USB_STORAGE_DATAFAB
+-	bool "Datafab Compact Flash Reader support (EXPERIMENTAL)"
+-	depends on USB_STORAGE && EXPERIMENTAL
++	bool "Datafab Compact Flash Reader support"
++	depends on USB_STORAGE
+ 	help
+ 	  Support for certain Datafab CompactFlash readers.
+ 	  Datafab has a web page at <http://www.datafabusa.com/>.
+@@ -69,8 +69,8 @@ config USB_STORAGE_DPCM
+ 	  There is a web page at <http://www.ziocorp.com/products/>.
+ 
+ config USB_STORAGE_USBAT
+-	bool "USBAT/USBAT02-based storage support (EXPERIMENTAL)"
+-	depends on USB_STORAGE && EXPERIMENTAL
++	bool "USBAT/USBAT02-based storage support"
++	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support storage devices
+ 	  based on the SCM/Shuttle USBAT/USBAT02 processors.
+@@ -90,30 +90,30 @@ config USB_STORAGE_USBAT
+ 	  - Sandisk ImageMate SDDR-05b
+ 
+ config USB_STORAGE_SDDR09
+-	bool "SanDisk SDDR-09 (and other SmartMedia) support (EXPERIMENTAL)"
+-	depends on USB_STORAGE && EXPERIMENTAL
++	bool "SanDisk SDDR-09 (and other SmartMedia) support"
++	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Sandisk SDDR-09
+ 	  SmartMedia reader in the USB Mass Storage driver.
+ 	  Also works for the Microtech Zio! SmartMedia reader.
+ 
+ config USB_STORAGE_SDDR55
+-	bool "SanDisk SDDR-55 SmartMedia support (EXPERIMENTAL)"
+-	depends on USB_STORAGE && EXPERIMENTAL
++	bool "SanDisk SDDR-55 SmartMedia support"
++	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Sandisk SDDR-55
+ 	  SmartMedia reader in the USB Mass Storage driver.
+ 
+ config USB_STORAGE_JUMPSHOT
+-	bool "Lexar Jumpshot Compact Flash Reader (EXPERIMENTAL)"
+-	depends on USB_STORAGE && EXPERIMENTAL
++	bool "Lexar Jumpshot Compact Flash Reader"
++	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Lexar Jumpshot
+ 	  USB CompactFlash reader.
+ 
+ config USB_STORAGE_ALAUDA
+-	bool "Olympus MAUSB-10/Fuji DPC-R1 support (EXPERIMENTAL)"
+-	depends on USB_STORAGE && EXPERIMENTAL
++	bool "Olympus MAUSB-10/Fuji DPC-R1 support"
++	depends on USB_STORAGE
+ 	help
+ 	  Say Y here to include additional code to support the Olympus MAUSB-10
+ 	  and Fujifilm DPC-R1 USB Card reader/writer devices.
+@@ -122,8 +122,8 @@ config USB_STORAGE_ALAUDA
+ 	  XD and SmartMedia cards.
+ 
+ config USB_STORAGE_ONETOUCH
+-	bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)"
+-	depends on USB_STORAGE && INPUT_EVDEV && EXPERIMENTAL && !PM
++	bool "Support OneTouch Button on Maxtor Hard Drives"
++	depends on USB_STORAGE && INPUT_EVDEV
+ 	help
+ 	  Say Y here to include additional code to support the Maxtor OneTouch
+ 	  USB hard drive's onetouch button.
+@@ -145,6 +145,17 @@ config USB_STORAGE_KARMA
+ 	  on the resulting scsi device node returns the Karma to normal
+ 	  operation.
+ 
++config USB_STORAGE_CYPRESS_ATACB
++	bool "SAT emulation on Cypress USB/ATA Bridge with ATACB"
++	depends on USB_STORAGE
++	---help---
++	  Say Y here if you want to use SAT (ata pass through) on devices based
++	  on the Cypress USB/ATA bridge supporting ATACB. This will allow you
++	  to use tools to tune and monitor your drive (like hdparm or smartctl).
++
++	  If you say no here your device will still work with the standard usb
++	  mass storage class.
++
+ 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 023969b..4c596c7 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -21,6 +21,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA)	+= karma.o
++usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o
+ 
+ usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
+ 			initializers.o $(usb-storage-obj-y)
+diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
+new file mode 100644
+index 0000000..d88824b
+--- /dev/null
++++ b/drivers/usb/storage/cypress_atacb.c
+@@ -0,0 +1,200 @@
++/*
++ * Support for emulating SAT (ata pass through) on devices based
++ *       on the Cypress USB/ATA bridge supporting ATACB.
++ *
++ * Copyright (c) 2008 Matthieu Castet (castet.matthieu at free.fr)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_eh.h>
++#include <linux/ata.h>
++
++#include "usb.h"
++#include "protocol.h"
++#include "scsiglue.h"
++#include "debug.h"
++
++/*
++ * ATACB is a protocol used on cypress usb<->ata bridge to
++ * send raw ATA command over mass storage
++ * There is a ATACB2 protocol that support LBA48 on newer chip.
++ * More info that be found on cy7c68310_8.pdf and cy7c68300c_8.pdf
++ * datasheet from cypress.com.
++ */
++void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
++{
++	unsigned char save_cmnd[MAX_COMMAND_SIZE];
++
++	if (likely(srb->cmnd[0] != ATA_16 && srb->cmnd[0] != ATA_12)) {
++		usb_stor_transparent_scsi_command(srb, us);
++		return;
++	}
++
++	memcpy(save_cmnd, srb->cmnd, sizeof(save_cmnd));
++	memset(srb->cmnd, 0, sizeof(srb->cmnd));
++
++	/* check if we support the command */
++	if (save_cmnd[1] >> 5) /* MULTIPLE_COUNT */
++		goto invalid_fld;
++	/* check protocol */
++	switch((save_cmnd[1] >> 1) & 0xf) {
++		case 3: /*no DATA */
++		case 4: /* PIO in */
++		case 5: /* PIO out */
++			break;
++		default:
++			goto invalid_fld;
++	}
++
++	/* first build the ATACB command */
++	srb->cmd_len = 16;
++
++	srb->cmnd[0] = 0x24; /* bVSCBSignature : vendor-specific command
++	                        this value can change, but most(all ?) manufacturers
++							keep the cypress default : 0x24 */
++	srb->cmnd[1] = 0x24; /* bVSCBSubCommand : 0x24 for ATACB */
++
++	srb->cmnd[3] = 0xff - 1; /* features, sector count, lba low, lba med
++								lba high, device, command are valid */
++	srb->cmnd[4] = 1; /* TransferBlockCount : 512 */
++
++	if (save_cmnd[0] == ATA_16) {
++		srb->cmnd[ 6] = save_cmnd[ 4]; /* features */
++		srb->cmnd[ 7] = save_cmnd[ 6]; /* sector count */
++		srb->cmnd[ 8] = save_cmnd[ 8]; /* lba low */
++		srb->cmnd[ 9] = save_cmnd[10]; /* lba med */
++		srb->cmnd[10] = save_cmnd[12]; /* lba high */
++		srb->cmnd[11] = save_cmnd[13]; /* device */
++		srb->cmnd[12] = save_cmnd[14]; /* command */
++
++		if (save_cmnd[1] & 0x01) {/* extended bit set for LBA48 */
++			/* this could be supported by atacb2 */
++			if (save_cmnd[3] || save_cmnd[5] || save_cmnd[7] || save_cmnd[9]
++					|| save_cmnd[11])
++				goto invalid_fld;
++		}
++	}
++	else { /* ATA12 */
++		srb->cmnd[ 6] = save_cmnd[3]; /* features */
++		srb->cmnd[ 7] = save_cmnd[4]; /* sector count */
++		srb->cmnd[ 8] = save_cmnd[5]; /* lba low */
++		srb->cmnd[ 9] = save_cmnd[6]; /* lba med */
++		srb->cmnd[10] = save_cmnd[7]; /* lba high */
++		srb->cmnd[11] = save_cmnd[8]; /* device */
++		srb->cmnd[12] = save_cmnd[9]; /* command */
++
++	}
++	/* Filter SET_FEATURES - XFER MODE command */
++	if ((srb->cmnd[12] == ATA_CMD_SET_FEATURES)
++			&& (srb->cmnd[6] == SETFEATURES_XFER))
++		goto invalid_fld;
++
++	if (srb->cmnd[12] == ATA_CMD_ID_ATA || srb->cmnd[12] == ATA_CMD_ID_ATAPI)
++		srb->cmnd[2] |= (1<<7); /* set  IdentifyPacketDevice for these cmds */
++
++
++	usb_stor_transparent_scsi_command(srb, us);
++
++	/* if the device doesn't support ATACB
++	 */
++	if (srb->result == SAM_STAT_CHECK_CONDITION &&
++			memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB,
++				sizeof(usb_stor_sense_invalidCDB)) == 0) {
++		US_DEBUGP("cypress atacb not supported ???\n");
++		goto end;
++	}
++
++	/* if ck_cond flags is set, and there wasn't critical error,
++	 * build the special sense
++	 */
++	if ((srb->result != (DID_ERROR << 16) &&
++				srb->result != (DID_ABORT << 16)) &&
++			save_cmnd[2] & 0x20) {
++		struct scsi_eh_save ses;
++		unsigned char regs[8];
++		unsigned char *sb = srb->sense_buffer;
++		unsigned char *desc = sb + 8;
++		int tmp_result;
++
++		/* build the command for
++		 * reading the ATA registers */
++		scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0);
++		srb->sdb.length = sizeof(regs);
++		sg_init_one(&ses.sense_sgl, regs, srb->sdb.length);
++		srb->sdb.table.sgl = &ses.sense_sgl;
++		srb->sc_data_direction = DMA_FROM_DEVICE;
++		srb->sdb.table.nents = 1;
++		/* we use the same command as before, but we set
++		 * the read taskfile bit, for not executing atacb command,
++		 * but reading register selected in srb->cmnd[4]
++		 */
++		srb->cmnd[2] = 1;
++
++		usb_stor_transparent_scsi_command(srb, us);
++		tmp_result = srb->result;
++		scsi_eh_restore_cmnd(srb, &ses);
++		/* we fail to get registers, report invalid command */
++		if (tmp_result != SAM_STAT_GOOD)
++			goto invalid_fld;
++
++		/* build the sense */
++		memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
++
++		/* set sk, asc for a good command */
++		sb[1] = RECOVERED_ERROR;
++		sb[2] = 0; /* ATA PASS THROUGH INFORMATION AVAILABLE */
++		sb[3] = 0x1D;
++
++		/* XXX we should generate sk, asc, ascq from status and error
++		 * regs
++		 * (see 11.1 Error translation ­ ATA device error to SCSI error map)
++		 * and ata_to_sense_error from libata.
++		 */
++
++		/* Sense data is current and format is descriptor. */
++		sb[0] = 0x72;
++		desc[0] = 0x09; /* ATA_RETURN_DESCRIPTOR */
++
++		/* set length of additional sense data */
++		sb[7] = 14;
++		desc[1] = 12;
++
++		/* Copy registers into sense buffer. */
++		desc[ 2] = 0x00;
++		desc[ 3] = regs[1];  /* features */
++		desc[ 5] = regs[2];  /* sector count */
++		desc[ 7] = regs[3];  /* lba low */
++		desc[ 9] = regs[4];  /* lba med */
++		desc[11] = regs[5];  /* lba high */
++		desc[12] = regs[6];  /* device */
++		desc[13] = regs[7];  /* command */
++
++		srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++	}
++	goto end;
++invalid_fld:
++	srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++
++	memcpy(srb->sense_buffer,
++			usb_stor_sense_invalidCDB,
++			sizeof(usb_stor_sense_invalidCDB));
++end:
++	memcpy(srb->cmnd, save_cmnd, sizeof(save_cmnd));
++	if (srb->cmnd[0] == ATA_12)
++		srb->cmd_len = 12;
++}
+diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/cypress_atacb.h
+new file mode 100644
+index 0000000..fbada89
+--- /dev/null
++++ b/drivers/usb/storage/cypress_atacb.h
+@@ -0,0 +1,25 @@
++/*
++ * Support for emulating SAT (ata pass through) on devices based
++ *       on the Cypress USB/ATA bridge supporting ATACB.
++ *
++ * Copyright (c) 2008 Matthieu Castet (castet.matthieu at free.fr)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef _CYPRESS_ATACB_H_
++#define _CYPRESS_ATACB_H_
++extern void cypress_atacb_passthrough(struct scsi_cmnd*, struct us_data*);
++#endif
+diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
+index 55b9520..a28d491 100644
+--- a/drivers/usb/storage/libusual.c
++++ b/drivers/usb/storage/libusual.c
+@@ -9,6 +9,7 @@
+ #include <linux/usb_usual.h>
+ #include <linux/vmalloc.h>
+ #include <linux/kthread.h>
++#include <linux/mutex.h>
+ 
+ /*
+  */
+@@ -30,7 +31,7 @@ static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS);
+ #define BIAS_NAME_SIZE  (sizeof("usb-storage"))
+ static const char *bias_names[3] = { "none", "usb-storage", "ub" };
+ 
+-static struct semaphore usu_init_notify;
++static DEFINE_MUTEX(usu_probe_mutex);
+ static DECLARE_COMPLETION(usu_end_notify);
+ static atomic_t total_threads = ATOMIC_INIT(0);
+ 
+@@ -178,10 +179,7 @@ static int usu_probe_thread(void *arg)
+ 	int rc;
+ 	unsigned long flags;
+ 
+-	/* A completion does not work here because it's counted. */
+-	down(&usu_init_notify);
+-	up(&usu_init_notify);
+-
++	mutex_lock(&usu_probe_mutex);
+ 	rc = request_module(bias_names[type]);
+ 	spin_lock_irqsave(&usu_lock, flags);
+ 	if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
+@@ -194,6 +192,7 @@ static int usu_probe_thread(void *arg)
+ 	}
+ 	st->fls &= ~USU_MOD_FL_THREAD;
+ 	spin_unlock_irqrestore(&usu_lock, flags);
++	mutex_unlock(&usu_probe_mutex);
+ 
+ 	complete_and_exit(&usu_end_notify, 0);
+ }
+@@ -204,10 +203,9 @@ static int __init usb_usual_init(void)
+ {
+ 	int rc;
+ 
+-	sema_init(&usu_init_notify, 0);
+-
++	mutex_lock(&usu_probe_mutex);
+ 	rc = usb_register(&usu_driver);
+-	up(&usu_init_notify);
++	mutex_unlock(&usu_probe_mutex);
+ 	return rc;
+ }
+ 
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 8c1e295..3fcde9f 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -73,6 +73,7 @@ static const char* host_info(struct Scsi_Host *host)
+ static int slave_alloc (struct scsi_device *sdev)
+ {
+ 	struct us_data *us = host_to_us(sdev->host);
++	struct usb_host_endpoint *bulk_in_ep;
+ 
+ 	/*
+ 	 * Set the INQUIRY transfer length to 36.  We don't use any of
+@@ -84,12 +85,13 @@ static int slave_alloc (struct scsi_device *sdev)
+ 	/* Scatter-gather buffers (all but the last) must have a length
+ 	 * divisible by the bulk maxpacket size.  Otherwise a data packet
+ 	 * would end up being short, causing a premature end to the data
+-	 * transfer.  Since high-speed bulk pipes have a maxpacket size
+-	 * of 512, we'll use that as the scsi device queue's DMA alignment
+-	 * mask.  Guaranteeing proper alignment of the first buffer will
+-	 * have the desired effect because, except at the beginning and
+-	 * the end, scatter-gather buffers follow page boundaries. */
+-	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
++	 * transfer.  We'll use the maxpacket value of the bulk-IN pipe
++	 * to set the SCSI device queue's DMA alignment mask.
++	 */
++	bulk_in_ep = us->pusb_dev->ep_in[usb_pipeendpoint(us->recv_bulk_pipe)];
++	blk_queue_update_dma_alignment(sdev->request_queue,
++			le16_to_cpu(bulk_in_ep->desc.wMaxPacketSize) - 1);
++			/* wMaxPacketSize must be a power of 2 */
+ 
+ 	/*
+ 	 * The UFI spec treates the Peripheral Qualifier bits in an
+@@ -132,7 +134,7 @@ static int slave_configure(struct scsi_device *sdev)
+ 		/* 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)
++		if (us->subclass != US_SC_SCSI && us->subclass != US_SC_CYP_ATACB)
+ 			sdev->use_10_for_ms = 1;
+ 
+ 		/* Many disks only accept MODE SENSE transfer lengths of
+@@ -226,12 +228,12 @@ static int queuecommand(struct scsi_cmnd *srb,
+ {
+ 	struct us_data *us = host_to_us(srb->device->host);
+ 
+-	US_DEBUGP("%s called\n", __FUNCTION__);
++	US_DEBUGP("%s called\n", __func__);
+ 
+ 	/* check for state-transition errors */
+ 	if (us->srb != NULL) {
+ 		printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
+-			__FUNCTION__, us->srb);
++			__func__, us->srb);
+ 		return SCSI_MLQUEUE_HOST_BUSY;
+ 	}
+ 
+@@ -260,7 +262,7 @@ static int command_abort(struct scsi_cmnd *srb)
+ {
+ 	struct us_data *us = host_to_us(srb->device->host);
+ 
+-	US_DEBUGP("%s called\n", __FUNCTION__);
++	US_DEBUGP("%s called\n", __func__);
+ 
+ 	/* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
+ 	 * bits are protected by the host lock. */
+@@ -297,7 +299,7 @@ static int device_reset(struct scsi_cmnd *srb)
+ 	struct us_data *us = host_to_us(srb->device->host);
+ 	int result;
+ 
+-	US_DEBUGP("%s called\n", __FUNCTION__);
++	US_DEBUGP("%s called\n", __func__);
+ 
+ 	/* lock the device pointers and do the reset */
+ 	mutex_lock(&(us->dev_mutex));
+@@ -313,7 +315,7 @@ static int bus_reset(struct scsi_cmnd *srb)
+ 	struct us_data *us = host_to_us(srb->device->host);
+ 	int result;
+ 
+-	US_DEBUGP("%s called\n", __FUNCTION__);
++	US_DEBUGP("%s called\n", __func__);
+ 	result = usb_stor_port_reset(us);
+ 	return result < 0 ? FAILED : SUCCESS;
+ }
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index bdd4334..6610d2d 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -110,7 +110,7 @@
+  */
+ static void usb_stor_blocking_completion(struct urb *urb)
+ {
+-	struct completion *urb_done_ptr = (struct completion *)urb->context;
++	struct completion *urb_done_ptr = urb->context;
+ 
+ 	complete(urb_done_ptr);
+ }
+@@ -198,7 +198,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
+ 	int status;
+ 
+ 	US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+-			__FUNCTION__, request, requesttype,
++			__func__, request, requesttype,
+ 			value, index, size);
+ 
+ 	/* fill in the devrequest structure */
+@@ -250,7 +250,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
+ 		usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
+ 				usb_pipeout(pipe), 0);
+ 
+-	US_DEBUGP("%s: result = %d\n", __FUNCTION__, result);
++	US_DEBUGP("%s: result = %d\n", __func__, result);
+ 	return result;
+ }
+ 
+@@ -332,7 +332,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
+ 	int result;
+ 
+ 	US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+-			__FUNCTION__, request, requesttype,
++			__func__, request, requesttype,
+ 			value, index, size);
+ 
+ 	/* fill in the devrequest structure */
+@@ -366,7 +366,7 @@ static int usb_stor_intr_transfer(struct us_data *us, void *buf,
+ 	unsigned int pipe = us->recv_intr_pipe;
+ 	unsigned int maxp;
+ 
+-	US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
++	US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+ 
+ 	/* calculate the max packet size */
+ 	maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
+@@ -393,7 +393,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
+ {
+ 	int result;
+ 
+-	US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
++	US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+ 
+ 	/* fill and submit the URB */
+ 	usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
+@@ -424,7 +424,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+ 		return USB_STOR_XFER_ERROR;
+ 
+ 	/* initialize the scatter-gather request block */
+-	US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__,
++	US_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__,
+ 			length, num_sg);
+ 	result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
+ 			sg, num_sg, length, GFP_NOIO);
+@@ -603,7 +603,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ 		scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE);
+ 
+ 		/* FIXME: we must do the protocol translation here */
+-		if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI)
++		if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI ||
++				us->subclass == US_SC_CYP_ATACB)
+ 			srb->cmd_len = 6;
+ 		else
+ 			srb->cmd_len = 12;
+@@ -700,7 +701,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ /* Stop the current URB transfer */
+ void usb_stor_stop_transport(struct us_data *us)
+ {
+-	US_DEBUGP("%s called\n", __FUNCTION__);
++	US_DEBUGP("%s called\n", __func__);
+ 
+ 	/* If the state machine is blocked waiting for an URB,
+ 	 * let's wake it up.  The test_and_clear_bit() call
+@@ -1134,7 +1135,7 @@ static int usb_stor_reset_common(struct us_data *us,
+ 
+ int usb_stor_CB_reset(struct us_data *us)
+ {
+-	US_DEBUGP("%s called\n", __FUNCTION__);
++	US_DEBUGP("%s called\n", __func__);
+ 
+ 	memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
+ 	us->iobuf[0] = SEND_DIAGNOSTIC;
+@@ -1149,7 +1150,7 @@ int usb_stor_CB_reset(struct us_data *us)
+  */
+ int usb_stor_Bulk_reset(struct us_data *us)
+ {
+-	US_DEBUGP("%s called\n", __FUNCTION__);
++	US_DEBUGP("%s called\n", __func__);
+ 
+ 	return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, 
+ 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 9125207..732bf52 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1719,6 +1719,14 @@ UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_CAPACITY_HEURISTICS),
+ 
++#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
++UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
++		"Cypress",
++		"Cypress AT2LP",
++		US_SC_CYP_ATACB, US_PR_BULK, NULL,
++		0),
++#endif
++
+ /* 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),
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index ac6114e..a856eff 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -101,6 +101,9 @@
+ #ifdef CONFIG_USB_STORAGE_KARMA
+ #include "karma.h"
+ #endif
++#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
++#include "cypress_atacb.h"
++#endif
+ 
+ /* Some informational data */
+ MODULE_AUTHOR("Matthew Dharm <mdharm-usb at one-eyed-alien.net>");
+@@ -187,7 +190,7 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+ 	/* Wait until no command is running */
+ 	mutex_lock(&us->dev_mutex);
+ 
+-	US_DEBUGP("%s\n", __FUNCTION__);
++	US_DEBUGP("%s\n", __func__);
+ 	if (us->suspend_resume_hook)
+ 		(us->suspend_resume_hook)(us, US_SUSPEND);
+ 
+@@ -204,7 +207,7 @@ static int storage_resume(struct usb_interface *iface)
+ 
+ 	mutex_lock(&us->dev_mutex);
+ 
+-	US_DEBUGP("%s\n", __FUNCTION__);
++	US_DEBUGP("%s\n", __func__);
+ 	if (us->suspend_resume_hook)
+ 		(us->suspend_resume_hook)(us, US_RESUME);
+ 
+@@ -216,7 +219,7 @@ static int storage_reset_resume(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+-	US_DEBUGP("%s\n", __FUNCTION__);
++	US_DEBUGP("%s\n", __func__);
+ 
+ 	/* Report the reset to the SCSI core */
+ 	usb_stor_report_bus_reset(us);
+@@ -237,7 +240,7 @@ static int storage_pre_reset(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+-	US_DEBUGP("%s\n", __FUNCTION__);
++	US_DEBUGP("%s\n", __func__);
+ 
+ 	/* Make sure no command runs during the reset */
+ 	mutex_lock(&us->dev_mutex);
+@@ -248,7 +251,7 @@ static int storage_post_reset(struct usb_interface *iface)
+ {
+ 	struct us_data *us = usb_get_intfdata(iface);
+ 
+-	US_DEBUGP("%s\n", __FUNCTION__);
++	US_DEBUGP("%s\n", __func__);
+ 
+ 	/* Report the reset to the SCSI core */
+ 	usb_stor_report_bus_reset(us);
+@@ -434,7 +437,7 @@ SkipForAbort:
+ /* Associate our private data with the USB device */
+ static int associate_dev(struct us_data *us, struct usb_interface *intf)
+ {
+-	US_DEBUGP("-- %s\n", __FUNCTION__);
++	US_DEBUGP("-- %s\n", __func__);
+ 
+ 	/* Fill in the device-related fields */
+ 	us->pusb_dev = interface_to_usbdev(intf);
+@@ -708,6 +711,13 @@ static int get_protocol(struct us_data *us)
+ 		break;
+ #endif
+ 
++#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
++	case US_SC_CYP_ATACB:
++		us->protocol_name = "Transparent SCSI with Cypress ATACB";
++		us->proto_handler = cypress_atacb_passthrough;
++		break;
++#endif
++
+ 	default:
+ 		return -EIO;
+ 	}
+@@ -806,7 +816,7 @@ static int usb_stor_acquire_resources(struct us_data *us)
+ /* Release all our dynamic resources */
+ static void usb_stor_release_resources(struct us_data *us)
+ {
+-	US_DEBUGP("-- %s\n", __FUNCTION__);
++	US_DEBUGP("-- %s\n", __func__);
+ 
+ 	/* Tell the control thread to exit.  The SCSI host must
+ 	 * already have been removed so it won't try to queue
+@@ -832,7 +842,7 @@ static void usb_stor_release_resources(struct us_data *us)
+ /* Dissociate from the USB device */
+ static void dissociate_dev(struct us_data *us)
+ {
+-	US_DEBUGP("-- %s\n", __FUNCTION__);
++	US_DEBUGP("-- %s\n", __func__);
+ 
+ 	kfree(us->sensebuf);
+ 
+diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
+index c815a40..be76084 100644
+--- a/drivers/usb/usb-skeleton.c
++++ b/drivers/usb/usb-skeleton.c
+@@ -88,7 +88,7 @@ static int skel_open(struct inode *inode, struct file *file)
+ 	interface = usb_find_interface(&skel_driver, subminor);
+ 	if (!interface) {
+ 		err ("%s - error, can't find device for minor %d",
+-		     __FUNCTION__, subminor);
++		     __func__, subminor);
+ 		retval = -ENODEV;
+ 		goto exit;
+ 	}
+@@ -212,7 +212,7 @@ static void skel_write_bulk_callback(struct urb *urb)
+ {
+ 	struct usb_skel *dev;
+ 
+-	dev = (struct usb_skel *)urb->context;
++	dev = urb->context;
+ 
+ 	/* sync/async unlink faults aren't errors */
+ 	if (urb->status) {
+@@ -220,7 +220,7 @@ static void skel_write_bulk_callback(struct urb *urb)
+ 		    urb->status == -ECONNRESET ||
+ 		    urb->status == -ESHUTDOWN))
+ 			err("%s - nonzero write bulk status received: %d",
+-			    __FUNCTION__, urb->status);
++			    __func__, urb->status);
+ 
+ 		spin_lock(&dev->err_lock);
+ 		dev->errors = urb->status;
+@@ -301,7 +301,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
+ 	retval = usb_submit_urb(urb, GFP_KERNEL);
+ 	mutex_unlock(&dev->io_mutex);
+ 	if (retval) {
+-		err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
++		err("%s - failed submitting write urb, error %d", __func__, retval);
+ 		goto error_unanchor;
+ 	}
+ 
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 1bd5fb3..e3dc8f8 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -1930,6 +1930,20 @@ config FB_VIRTUAL
+ 
+ 	  If unsure, say N.
+ 
++config XEN_FBDEV_FRONTEND
++	tristate "Xen virtual frame buffer support"
++	depends on FB && XEN
++	select FB_SYS_FILLRECT
++	select FB_SYS_COPYAREA
++	select FB_SYS_IMAGEBLIT
++	select FB_SYS_FOPS
++	select FB_DEFERRED_IO
++	default y
++	help
++	  This driver implements the front-end of the Xen virtual
++	  frame buffer driver.  It communicates with a back-end
++	  in another domain.
++
+ source "drivers/video/omap/Kconfig"
+ 
+ source "drivers/video/backlight/Kconfig"
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 11c0e5e..f172b9b 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -114,6 +114,7 @@ obj-$(CONFIG_FB_PS3)		  += ps3fb.o
+ obj-$(CONFIG_FB_SM501)            += sm501fb.o
+ obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
+ obj-$(CONFIG_FB_OMAP)             += omap/
++obj-$(CONFIG_XEN_FBDEV_FRONTEND)  += xen-fbfront.o
+ 
+ # Platform or fallback drivers go here
+ obj-$(CONFIG_FB_UVESA)            += uvesafb.o
+diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
+index 97facb1..7576519 100644
+--- a/drivers/video/pxafb.c
++++ b/drivers/video/pxafb.c
+@@ -45,6 +45,7 @@
+ #include <asm/irq.h>
+ #include <asm/div64.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/bitfield.h>
+ #include <asm/arch/pxafb.h>
+ 
+diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
+new file mode 100644
+index 0000000..619a6f8
+--- /dev/null
++++ b/drivers/video/xen-fbfront.c
+@@ -0,0 +1,550 @@
++/*
++ * Xen para-virtual frame buffer device
++ *
++ * Copyright (C) 2005-2006 Anthony Liguori <aliguori at us.ibm.com>
++ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
++ *
++ *  Based on linux/drivers/video/q40fb.c
++ *
++ *  This file is subject to the terms and conditions of the GNU General Public
++ *  License. See the file COPYING in the main directory of this archive for
++ *  more details.
++ */
++
++/*
++ * TODO:
++ *
++ * Switch to grant tables when they become capable of dealing with the
++ * frame buffer.
++ */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/fb.h>
++#include <linux/module.h>
++#include <linux/vmalloc.h>
++#include <linux/mm.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/events.h>
++#include <xen/page.h>
++#include <xen/interface/io/fbif.h>
++#include <xen/interface/io/protocols.h>
++#include <xen/xenbus.h>
++
++struct xenfb_info {
++	unsigned char		*fb;
++	struct fb_info		*fb_info;
++	int			x1, y1, x2, y2;	/* dirty rectangle,
++						   protected by dirty_lock */
++	spinlock_t		dirty_lock;
++	int			nr_pages;
++	int			irq;
++	struct xenfb_page	*page;
++	unsigned long 		*mfns;
++	int			update_wanted; /* XENFB_TYPE_UPDATE wanted */
++
++	struct xenbus_device	*xbdev;
++};
++
++static u32 xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
++
++static int xenfb_remove(struct xenbus_device *);
++static void xenfb_init_shared_page(struct xenfb_info *);
++static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
++static void xenfb_disconnect_backend(struct xenfb_info *);
++
++static void xenfb_do_update(struct xenfb_info *info,
++			    int x, int y, int w, int h)
++{
++	union xenfb_out_event event;
++	u32 prod;
++
++	event.type = XENFB_TYPE_UPDATE;
++	event.update.x = x;
++	event.update.y = y;
++	event.update.width = w;
++	event.update.height = h;
++
++	prod = info->page->out_prod;
++	/* caller ensures !xenfb_queue_full() */
++	mb();			/* ensure ring space available */
++	XENFB_OUT_RING_REF(info->page, prod) = event;
++	wmb();			/* ensure ring contents visible */
++	info->page->out_prod = prod + 1;
++
++	notify_remote_via_irq(info->irq);
++}
++
++static int xenfb_queue_full(struct xenfb_info *info)
++{
++	u32 cons, prod;
++
++	prod = info->page->out_prod;
++	cons = info->page->out_cons;
++	return prod - cons == XENFB_OUT_RING_LEN;
++}
++
++static void xenfb_refresh(struct xenfb_info *info,
++			  int x1, int y1, int w, int h)
++{
++	unsigned long flags;
++	int y2 = y1 + h - 1;
++	int x2 = x1 + w - 1;
++
++	if (!info->update_wanted)
++		return;
++
++	spin_lock_irqsave(&info->dirty_lock, flags);
++
++	/* Combine with dirty rectangle: */
++	if (info->y1 < y1)
++		y1 = info->y1;
++	if (info->y2 > y2)
++		y2 = info->y2;
++	if (info->x1 < x1)
++		x1 = info->x1;
++	if (info->x2 > x2)
++		x2 = info->x2;
++
++	if (xenfb_queue_full(info)) {
++		/* Can't send right now, stash it in the dirty rectangle */
++		info->x1 = x1;
++		info->x2 = x2;
++		info->y1 = y1;
++		info->y2 = y2;
++		spin_unlock_irqrestore(&info->dirty_lock, flags);
++		return;
++	}
++
++	/* Clear dirty rectangle: */
++	info->x1 = info->y1 = INT_MAX;
++	info->x2 = info->y2 = 0;
++
++	spin_unlock_irqrestore(&info->dirty_lock, flags);
++
++	if (x1 <= x2 && y1 <= y2)
++		xenfb_do_update(info, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
++}
++
++static void xenfb_deferred_io(struct fb_info *fb_info,
++			      struct list_head *pagelist)
++{
++	struct xenfb_info *info = fb_info->par;
++	struct page *page;
++	unsigned long beg, end;
++	int y1, y2, miny, maxy;
++
++	miny = INT_MAX;
++	maxy = 0;
++	list_for_each_entry(page, pagelist, lru) {
++		beg = page->index << PAGE_SHIFT;
++		end = beg + PAGE_SIZE - 1;
++		y1 = beg / fb_info->fix.line_length;
++		y2 = end / fb_info->fix.line_length;
++		if (y2 >= fb_info->var.yres)
++			y2 = fb_info->var.yres - 1;
++		if (miny > y1)
++			miny = y1;
++		if (maxy < y2)
++			maxy = y2;
++	}
++	xenfb_refresh(info, 0, miny, fb_info->var.xres, maxy - miny + 1);
++}
++
++static struct fb_deferred_io xenfb_defio = {
++	.delay		= HZ / 20,
++	.deferred_io	= xenfb_deferred_io,
++};
++
++static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
++			   unsigned blue, unsigned transp,
++			   struct fb_info *info)
++{
++	u32 v;
++
++	if (regno > info->cmap.len)
++		return 1;
++
++#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
++	red = CNVT_TOHW(red, info->var.red.length);
++	green = CNVT_TOHW(green, info->var.green.length);
++	blue = CNVT_TOHW(blue, info->var.blue.length);
++	transp = CNVT_TOHW(transp, info->var.transp.length);
++#undef CNVT_TOHW
++
++	v = (red << info->var.red.offset) |
++	    (green << info->var.green.offset) |
++	    (blue << info->var.blue.offset);
++
++	switch (info->var.bits_per_pixel) {
++	case 16:
++	case 24:
++	case 32:
++		((u32 *)info->pseudo_palette)[regno] = v;
++		break;
++	}
++
++	return 0;
++}
++
++static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
++{
++	struct xenfb_info *info = p->par;
++
++	sys_fillrect(p, rect);
++	xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
++}
++
++static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
++{
++	struct xenfb_info *info = p->par;
++
++	sys_imageblit(p, image);
++	xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
++}
++
++static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
++{
++	struct xenfb_info *info = p->par;
++
++	sys_copyarea(p, area);
++	xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
++}
++
++static ssize_t xenfb_write(struct fb_info *p, const char __user *buf,
++			size_t count, loff_t *ppos)
++{
++	struct xenfb_info *info = p->par;
++	ssize_t res;
++
++	res = fb_sys_write(p, buf, count, ppos);
++	xenfb_refresh(info, 0, 0, info->page->width, info->page->height);
++	return res;
++}
++
++static struct fb_ops xenfb_fb_ops = {
++	.owner		= THIS_MODULE,
++	.fb_read	= fb_sys_read,
++	.fb_write	= xenfb_write,
++	.fb_setcolreg	= xenfb_setcolreg,
++	.fb_fillrect	= xenfb_fillrect,
++	.fb_copyarea	= xenfb_copyarea,
++	.fb_imageblit	= xenfb_imageblit,
++};
++
++static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
++{
++	/*
++	 * No in events recognized, simply ignore them all.
++	 * If you need to recognize some, see xen-kbdfront's
++	 * input_handler() for how to do that.
++	 */
++	struct xenfb_info *info = dev_id;
++	struct xenfb_page *page = info->page;
++
++	if (page->in_cons != page->in_prod) {
++		info->page->in_cons = info->page->in_prod;
++		notify_remote_via_irq(info->irq);
++	}
++
++	/* Flush dirty rectangle: */
++	xenfb_refresh(info, INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
++
++	return IRQ_HANDLED;
++}
++
++static int __devinit xenfb_probe(struct xenbus_device *dev,
++				 const struct xenbus_device_id *id)
++{
++	struct xenfb_info *info;
++	struct fb_info *fb_info;
++	int ret;
++
++	info = kzalloc(sizeof(*info), GFP_KERNEL);
++	if (info == NULL) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
++		return -ENOMEM;
++	}
++	dev->dev.driver_data = info;
++	info->xbdev = dev;
++	info->irq = -1;
++	info->x1 = info->y1 = INT_MAX;
++	spin_lock_init(&info->dirty_lock);
++
++	info->fb = vmalloc(xenfb_mem_len);
++	if (info->fb == NULL)
++		goto error_nomem;
++	memset(info->fb, 0, xenfb_mem_len);
++
++	info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++	info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
++	if (!info->mfns)
++		goto error_nomem;
++
++	/* set up shared page */
++	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
++	if (!info->page)
++		goto error_nomem;
++
++	xenfb_init_shared_page(info);
++
++	/* abusing framebuffer_alloc() to allocate pseudo_palette */
++	fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
++	if (fb_info == NULL)
++		goto error_nomem;
++
++	/* complete the abuse: */
++	fb_info->pseudo_palette = fb_info->par;
++	fb_info->par = info;
++
++	fb_info->screen_base = info->fb;
++
++	fb_info->fbops = &xenfb_fb_ops;
++	fb_info->var.xres_virtual = fb_info->var.xres = info->page->width;
++	fb_info->var.yres_virtual = fb_info->var.yres = info->page->height;
++	fb_info->var.bits_per_pixel = info->page->depth;
++
++	fb_info->var.red = (struct fb_bitfield){16, 8, 0};
++	fb_info->var.green = (struct fb_bitfield){8, 8, 0};
++	fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
++
++	fb_info->var.activate = FB_ACTIVATE_NOW;
++	fb_info->var.height = -1;
++	fb_info->var.width = -1;
++	fb_info->var.vmode = FB_VMODE_NONINTERLACED;
++
++	fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
++	fb_info->fix.line_length = info->page->line_length;
++	fb_info->fix.smem_start = 0;
++	fb_info->fix.smem_len = xenfb_mem_len;
++	strcpy(fb_info->fix.id, "xen");
++	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
++	fb_info->fix.accel = FB_ACCEL_NONE;
++
++	fb_info->flags = FBINFO_FLAG_DEFAULT;
++
++	ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
++	if (ret < 0) {
++		framebuffer_release(fb_info);
++		xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
++		goto error;
++	}
++
++	fb_info->fbdefio = &xenfb_defio;
++	fb_deferred_io_init(fb_info);
++
++	ret = register_framebuffer(fb_info);
++	if (ret) {
++		fb_deferred_io_cleanup(fb_info);
++		fb_dealloc_cmap(&fb_info->cmap);
++		framebuffer_release(fb_info);
++		xenbus_dev_fatal(dev, ret, "register_framebuffer");
++		goto error;
++	}
++	info->fb_info = fb_info;
++
++	ret = xenfb_connect_backend(dev, info);
++	if (ret < 0)
++		goto error;
++
++	return 0;
++
++ error_nomem:
++	ret = -ENOMEM;
++	xenbus_dev_fatal(dev, ret, "allocating device memory");
++ error:
++	xenfb_remove(dev);
++	return ret;
++}
++
++static int xenfb_resume(struct xenbus_device *dev)
++{
++	struct xenfb_info *info = dev->dev.driver_data;
++
++	xenfb_disconnect_backend(info);
++	xenfb_init_shared_page(info);
++	return xenfb_connect_backend(dev, info);
++}
++
++static int xenfb_remove(struct xenbus_device *dev)
++{
++	struct xenfb_info *info = dev->dev.driver_data;
++
++	xenfb_disconnect_backend(info);
++	if (info->fb_info) {
++		fb_deferred_io_cleanup(info->fb_info);
++		unregister_framebuffer(info->fb_info);
++		fb_dealloc_cmap(&info->fb_info->cmap);
++		framebuffer_release(info->fb_info);
++	}
++	free_page((unsigned long)info->page);
++	vfree(info->mfns);
++	vfree(info->fb);
++	kfree(info);
++
++	return 0;
++}
++
++static unsigned long vmalloc_to_mfn(void *address)
++{
++	return pfn_to_mfn(vmalloc_to_pfn(address));
++}
++
++static void xenfb_init_shared_page(struct xenfb_info *info)
++{
++	int i;
++
++	for (i = 0; i < info->nr_pages; i++)
++		info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
++
++	info->page->pd[0] = vmalloc_to_mfn(info->mfns);
++	info->page->pd[1] = 0;
++	info->page->width = XENFB_WIDTH;
++	info->page->height = XENFB_HEIGHT;
++	info->page->depth = XENFB_DEPTH;
++	info->page->line_length = (info->page->depth / 8) * info->page->width;
++	info->page->mem_length = xenfb_mem_len;
++	info->page->in_cons = info->page->in_prod = 0;
++	info->page->out_cons = info->page->out_prod = 0;
++}
++
++static int xenfb_connect_backend(struct xenbus_device *dev,
++				 struct xenfb_info *info)
++{
++	int ret, evtchn;
++	struct xenbus_transaction xbt;
++
++	ret = xenbus_alloc_evtchn(dev, &evtchn);
++	if (ret)
++		return ret;
++	ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
++					0, dev->devicetype, info);
++	if (ret < 0) {
++		xenbus_free_evtchn(dev, evtchn);
++		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
++		return ret;
++	}
++	info->irq = ret;
++
++ again:
++	ret = xenbus_transaction_start(&xbt);
++	if (ret) {
++		xenbus_dev_fatal(dev, ret, "starting transaction");
++		return ret;
++	}
++	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
++			    virt_to_mfn(info->page));
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++			    evtchn);
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
++			    XEN_IO_PROTO_ABI_NATIVE);
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_transaction_end(xbt, 0);
++	if (ret) {
++		if (ret == -EAGAIN)
++			goto again;
++		xenbus_dev_fatal(dev, ret, "completing transaction");
++		return ret;
++	}
++
++	xenbus_switch_state(dev, XenbusStateInitialised);
++	return 0;
++
++ error_xenbus:
++	xenbus_transaction_end(xbt, 1);
++	xenbus_dev_fatal(dev, ret, "writing xenstore");
++	return ret;
++}
++
++static void xenfb_disconnect_backend(struct xenfb_info *info)
++{
++	if (info->irq >= 0)
++		unbind_from_irqhandler(info->irq, info);
++	info->irq = -1;
++}
++
++static void xenfb_backend_changed(struct xenbus_device *dev,
++				  enum xenbus_state backend_state)
++{
++	struct xenfb_info *info = dev->dev.driver_data;
++	int val;
++
++	switch (backend_state) {
++	case XenbusStateInitialising:
++	case XenbusStateInitialised:
++	case XenbusStateUnknown:
++	case XenbusStateClosed:
++		break;
++
++	case XenbusStateInitWait:
++InitWait:
++		xenbus_switch_state(dev, XenbusStateConnected);
++		break;
++
++	case XenbusStateConnected:
++		/*
++		 * Work around xenbus race condition: If backend goes
++		 * through InitWait to Connected fast enough, we can
++		 * get Connected twice here.
++		 */
++		if (dev->state != XenbusStateConnected)
++			goto InitWait; /* no InitWait seen yet, fudge it */
++
++		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
++				 "request-update", "%d", &val) < 0)
++			val = 0;
++		if (val)
++			info->update_wanted = 1;
++		break;
++
++	case XenbusStateClosing:
++		xenbus_frontend_closed(dev);
++		break;
++	}
++}
++
++static struct xenbus_device_id xenfb_ids[] = {
++	{ "vfb" },
++	{ "" }
++};
++
++static struct xenbus_driver xenfb = {
++	.name = "vfb",
++	.owner = THIS_MODULE,
++	.ids = xenfb_ids,
++	.probe = xenfb_probe,
++	.remove = xenfb_remove,
++	.resume = xenfb_resume,
++	.otherend_changed = xenfb_backend_changed,
++};
++
++static int __init xenfb_init(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	/* Nothing to do if running in dom0. */
++	if (is_initial_xendomain())
++		return -ENODEV;
++
++	return xenbus_register_frontend(&xenfb);
++}
++
++static void __exit xenfb_cleanup(void)
++{
++	xenbus_unregister_driver(&xenfb);
++}
++
++module_init(xenfb_init);
++module_exit(xenfb_cleanup);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c
+index 32ccd7c..35cddff 100644
+--- a/drivers/watchdog/sc1200wdt.c
++++ b/drivers/watchdog/sc1200wdt.c
+@@ -38,8 +38,8 @@
+ #include <linux/init.h>
+ #include <linux/pnp.h>
+ #include <linux/fs.h>
++#include <linux/semaphore.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+ 
+diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
+new file mode 100644
+index 0000000..4b75a16
+--- /dev/null
++++ b/drivers/xen/Kconfig
+@@ -0,0 +1,19 @@
++config XEN_BALLOON
++	bool "Xen memory balloon driver"
++	depends on XEN
++	default y
++	help
++	  The balloon driver allows the Xen domain to request more memory from
++	  the system to expand the domain's memory allocation, or alternatively
++	  return unneeded memory to the system.
++
++config XEN_SCRUB_PAGES
++	bool "Scrub pages before returning them to system"
++	depends on XEN_BALLOON
++	default y
++	help
++	  Scrub pages before returning them to the system for reuse by
++	  other domains.  This makes sure that any confidential data
++	  is not accidentally visible to other domains.  Is it more
++	  secure, but slightly less efficient.
++	  If in doubt, say yes.
+diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
+index 56592f0..37af04f 100644
+--- a/drivers/xen/Makefile
++++ b/drivers/xen/Makefile
+@@ -1,2 +1,4 @@
+-obj-y	+= grant-table.o
++obj-y	+= grant-table.o features.o events.o
+ obj-y	+= xenbus/
++obj-$(CONFIG_XEN_XENCOMM)	+= xencomm.o
++obj-$(CONFIG_XEN_BALLOON)	+= balloon.o
+diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
+new file mode 100644
+index 0000000..ab25ba6
+--- /dev/null
++++ b/drivers/xen/balloon.c
+@@ -0,0 +1,712 @@
++/******************************************************************************
++ * balloon.c
++ *
++ * Xen balloon driver - enables returning/claiming memory to/from Xen.
++ *
++ * Copyright (c) 2003, B Dragovic
++ * Copyright (c) 2003-2004, M Williamson, K Fraser
++ * Copyright (c) 2005 Dan M. Smith, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/bootmem.h>
++#include <linux/pagemap.h>
++#include <linux/highmem.h>
++#include <linux/mutex.h>
++#include <linux/highmem.h>
++#include <linux/list.h>
++#include <linux/sysdev.h>
++
++#include <asm/xen/hypervisor.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
++#include <asm/tlb.h>
++
++#include <xen/interface/memory.h>
++#include <xen/balloon.h>
++#include <xen/xenbus.h>
++#include <xen/features.h>
++#include <xen/page.h>
++
++#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
++
++#define BALLOON_CLASS_NAME "memory"
++
++struct balloon_stats {
++	/* We aim for 'current allocation' == 'target allocation'. */
++	unsigned long current_pages;
++	unsigned long target_pages;
++	/* We may hit the hard limit in Xen. If we do then we remember it. */
++	unsigned long hard_limit;
++	/*
++	 * Drivers may alter the memory reservation independently, but they
++	 * must inform the balloon driver so we avoid hitting the hard limit.
++	 */
++	unsigned long driver_pages;
++	/* Number of pages in high- and low-memory balloons. */
++	unsigned long balloon_low;
++	unsigned long balloon_high;
++};
++
++static DEFINE_MUTEX(balloon_mutex);
++
++static struct sys_device balloon_sysdev;
++
++static int register_balloon(struct sys_device *sysdev);
++
++/*
++ * Protects atomic reservation decrease/increase against concurrent increases.
++ * Also protects non-atomic updates of current_pages and driver_pages, and
++ * balloon lists.
++ */
++static DEFINE_SPINLOCK(balloon_lock);
++
++static struct balloon_stats balloon_stats;
++
++/* We increase/decrease in batches which fit in a page */
++static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
++
++/* VM /proc information for memory */
++extern unsigned long totalram_pages;
++
++#ifdef CONFIG_HIGHMEM
++extern unsigned long totalhigh_pages;
++#define inc_totalhigh_pages() (totalhigh_pages++)
++#define dec_totalhigh_pages() (totalhigh_pages--)
++#else
++#define inc_totalhigh_pages() do {} while(0)
++#define dec_totalhigh_pages() do {} while(0)
++#endif
++
++/* List of ballooned pages, threaded through the mem_map array. */
++static LIST_HEAD(ballooned_pages);
++
++/* Main work function, always executed in process context. */
++static void balloon_process(struct work_struct *work);
++static DECLARE_WORK(balloon_worker, balloon_process);
++static struct timer_list balloon_timer;
++
++/* When ballooning out (allocating memory to return to Xen) we don't really
++   want the kernel to try too hard since that can trigger the oom killer. */
++#define GFP_BALLOON \
++	(GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC)
++
++static void scrub_page(struct page *page)
++{
++#ifdef CONFIG_XEN_SCRUB_PAGES
++	if (PageHighMem(page)) {
++		void *v = kmap(page);
++		clear_page(v);
++		kunmap(v);
++	} else {
++		void *v = page_address(page);
++		clear_page(v);
++	}
++#endif
++}
++
++/* balloon_append: add the given page to the balloon. */
++static void balloon_append(struct page *page)
++{
++	/* Lowmem is re-populated first, so highmem pages go at list tail. */
++	if (PageHighMem(page)) {
++		list_add_tail(&page->lru, &ballooned_pages);
++		balloon_stats.balloon_high++;
++		dec_totalhigh_pages();
++	} else {
++		list_add(&page->lru, &ballooned_pages);
++		balloon_stats.balloon_low++;
++	}
++}
++
++/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
++static struct page *balloon_retrieve(void)
++{
++	struct page *page;
++
++	if (list_empty(&ballooned_pages))
++		return NULL;
++
++	page = list_entry(ballooned_pages.next, struct page, lru);
++	list_del(&page->lru);
++
++	if (PageHighMem(page)) {
++		balloon_stats.balloon_high--;
++		inc_totalhigh_pages();
++	}
++	else
++		balloon_stats.balloon_low--;
++
++	return page;
++}
++
++static struct page *balloon_first_page(void)
++{
++	if (list_empty(&ballooned_pages))
++		return NULL;
++	return list_entry(ballooned_pages.next, struct page, lru);
++}
++
++static struct page *balloon_next_page(struct page *page)
++{
++	struct list_head *next = page->lru.next;
++	if (next == &ballooned_pages)
++		return NULL;
++	return list_entry(next, struct page, lru);
++}
++
++static void balloon_alarm(unsigned long unused)
++{
++	schedule_work(&balloon_worker);
++}
++
++static unsigned long current_target(void)
++{
++	unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit);
++
++	target = min(target,
++		     balloon_stats.current_pages +
++		     balloon_stats.balloon_low +
++		     balloon_stats.balloon_high);
++
++	return target;
++}
++
++static int increase_reservation(unsigned long nr_pages)
++{
++	unsigned long  pfn, i, flags;
++	struct page   *page;
++	long           rc;
++	struct xen_memory_reservation reservation = {
++		.address_bits = 0,
++		.extent_order = 0,
++		.domid        = DOMID_SELF
++	};
++
++	if (nr_pages > ARRAY_SIZE(frame_list))
++		nr_pages = ARRAY_SIZE(frame_list);
++
++	spin_lock_irqsave(&balloon_lock, flags);
++
++	page = balloon_first_page();
++	for (i = 0; i < nr_pages; i++) {
++		BUG_ON(page == NULL);
++		frame_list[i] = page_to_pfn(page);;
++		page = balloon_next_page(page);
++	}
++
++	reservation.extent_start = (unsigned long)frame_list;
++	reservation.nr_extents   = nr_pages;
++	rc = HYPERVISOR_memory_op(
++		XENMEM_populate_physmap, &reservation);
++	if (rc < nr_pages) {
++		if (rc > 0) {
++			int ret;
++
++			/* We hit the Xen hard limit: reprobe. */
++			reservation.nr_extents = rc;
++			ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++					&reservation);
++			BUG_ON(ret != rc);
++		}
++		if (rc >= 0)
++			balloon_stats.hard_limit = (balloon_stats.current_pages + rc -
++						    balloon_stats.driver_pages);
++		goto out;
++	}
++
++	for (i = 0; i < nr_pages; i++) {
++		page = balloon_retrieve();
++		BUG_ON(page == NULL);
++
++		pfn = page_to_pfn(page);
++		BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) &&
++		       phys_to_machine_mapping_valid(pfn));
++
++		set_phys_to_machine(pfn, frame_list[i]);
++
++		/* Link back into the page tables if not highmem. */
++		if (pfn < max_low_pfn) {
++			int ret;
++			ret = HYPERVISOR_update_va_mapping(
++				(unsigned long)__va(pfn << PAGE_SHIFT),
++				mfn_pte(frame_list[i], PAGE_KERNEL),
++				0);
++			BUG_ON(ret);
++		}
++
++		/* Relinquish the page back to the allocator. */
++		ClearPageReserved(page);
++		init_page_count(page);
++		__free_page(page);
++	}
++
++	balloon_stats.current_pages += nr_pages;
++	totalram_pages = balloon_stats.current_pages;
++
++ out:
++	spin_unlock_irqrestore(&balloon_lock, flags);
++
++	return 0;
++}
++
++static int decrease_reservation(unsigned long nr_pages)
++{
++	unsigned long  pfn, i, flags;
++	struct page   *page;
++	int            need_sleep = 0;
++	int ret;
++	struct xen_memory_reservation reservation = {
++		.address_bits = 0,
++		.extent_order = 0,
++		.domid        = DOMID_SELF
++	};
++
++	if (nr_pages > ARRAY_SIZE(frame_list))
++		nr_pages = ARRAY_SIZE(frame_list);
++
++	for (i = 0; i < nr_pages; i++) {
++		if ((page = alloc_page(GFP_BALLOON)) == NULL) {
++			nr_pages = i;
++			need_sleep = 1;
++			break;
++		}
++
++		pfn = page_to_pfn(page);
++		frame_list[i] = pfn_to_mfn(pfn);
++
++		scrub_page(page);
++	}
++
++	/* Ensure that ballooned highmem pages don't have kmaps. */
++	kmap_flush_unused();
++	flush_tlb_all();
++
++	spin_lock_irqsave(&balloon_lock, flags);
++
++	/* No more mappings: invalidate P2M and add to balloon. */
++	for (i = 0; i < nr_pages; i++) {
++		pfn = mfn_to_pfn(frame_list[i]);
++		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++		balloon_append(pfn_to_page(pfn));
++	}
++
++	reservation.extent_start = (unsigned long)frame_list;
++	reservation.nr_extents   = nr_pages;
++	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
++	BUG_ON(ret != nr_pages);
++
++	balloon_stats.current_pages -= nr_pages;
++	totalram_pages = balloon_stats.current_pages;
++
++	spin_unlock_irqrestore(&balloon_lock, flags);
++
++	return need_sleep;
++}
++
++/*
++ * We avoid multiple worker processes conflicting via the balloon mutex.
++ * We may of course race updates of the target counts (which are protected
++ * by the balloon lock), or with changes to the Xen hard limit, but we will
++ * recover from these in time.
++ */
++static void balloon_process(struct work_struct *work)
++{
++	int need_sleep = 0;
++	long credit;
++
++	mutex_lock(&balloon_mutex);
++
++	do {
++		credit = current_target() - balloon_stats.current_pages;
++		if (credit > 0)
++			need_sleep = (increase_reservation(credit) != 0);
++		if (credit < 0)
++			need_sleep = (decrease_reservation(-credit) != 0);
++
++#ifndef CONFIG_PREEMPT
++		if (need_resched())
++			schedule();
++#endif
++	} while ((credit != 0) && !need_sleep);
++
++	/* Schedule more work if there is some still to be done. */
++	if (current_target() != balloon_stats.current_pages)
++		mod_timer(&balloon_timer, jiffies + HZ);
++
++	mutex_unlock(&balloon_mutex);
++}
++
++/* Resets the Xen limit, sets new target, and kicks off processing. */
++void balloon_set_new_target(unsigned long target)
++{
++	/* No need for lock. Not read-modify-write updates. */
++	balloon_stats.hard_limit   = ~0UL;
++	balloon_stats.target_pages = target;
++	schedule_work(&balloon_worker);
++}
++
++static struct xenbus_watch target_watch =
++{
++	.node = "memory/target"
++};
++
++/* React to a change in the target key */
++static void watch_target(struct xenbus_watch *watch,
++			 const char **vec, unsigned int len)
++{
++	unsigned long long new_target;
++	int err;
++
++	err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
++	if (err != 1) {
++		/* This is ok (for domain0 at least) - so just return */
++		return;
++	}
++
++	/* The given memory/target value is in KiB, so it needs converting to
++	 * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
++	 */
++	balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
++}
++
++static int balloon_init_watcher(struct notifier_block *notifier,
++				unsigned long event,
++				void *data)
++{
++	int err;
++
++	err = register_xenbus_watch(&target_watch);
++	if (err)
++		printk(KERN_ERR "Failed to set balloon watcher\n");
++
++	return NOTIFY_DONE;
++}
++
++static struct notifier_block xenstore_notifier;
++
++static int __init balloon_init(void)
++{
++	unsigned long pfn;
++	struct page *page;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	pr_info("xen_balloon: Initialising balloon driver.\n");
++
++	balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn);
++	totalram_pages   = balloon_stats.current_pages;
++	balloon_stats.target_pages  = balloon_stats.current_pages;
++	balloon_stats.balloon_low   = 0;
++	balloon_stats.balloon_high  = 0;
++	balloon_stats.driver_pages  = 0UL;
++	balloon_stats.hard_limit    = ~0UL;
++
++	init_timer(&balloon_timer);
++	balloon_timer.data = 0;
++	balloon_timer.function = balloon_alarm;
++
++	register_balloon(&balloon_sysdev);
++
++	/* Initialise the balloon with excess memory space. */
++	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
++		page = pfn_to_page(pfn);
++		if (!PageReserved(page))
++			balloon_append(page);
++	}
++
++	target_watch.callback = watch_target;
++	xenstore_notifier.notifier_call = balloon_init_watcher;
++
++	register_xenstore_notifier(&xenstore_notifier);
++
++	return 0;
++}
++
++subsys_initcall(balloon_init);
++
++static void balloon_exit(void)
++{
++    /* XXX - release balloon here */
++    return;
++}
++
++module_exit(balloon_exit);
++
++static void balloon_update_driver_allowance(long delta)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&balloon_lock, flags);
++	balloon_stats.driver_pages += delta;
++	spin_unlock_irqrestore(&balloon_lock, flags);
++}
++
++static int dealloc_pte_fn(
++	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
++{
++	unsigned long mfn = pte_mfn(*pte);
++	int ret;
++	struct xen_memory_reservation reservation = {
++		.nr_extents   = 1,
++		.extent_order = 0,
++		.domid        = DOMID_SELF
++	};
++	reservation.extent_start = (unsigned long)&mfn;
++	set_pte_at(&init_mm, addr, pte, __pte_ma(0ull));
++	set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
++	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
++	BUG_ON(ret != 1);
++	return 0;
++}
++
++static struct page **alloc_empty_pages_and_pagevec(int nr_pages)
++{
++	unsigned long vaddr, flags;
++	struct page *page, **pagevec;
++	int i, ret;
++
++	pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
++	if (pagevec == NULL)
++		return NULL;
++
++	for (i = 0; i < nr_pages; i++) {
++		page = pagevec[i] = alloc_page(GFP_KERNEL);
++		if (page == NULL)
++			goto err;
++
++		vaddr = (unsigned long)page_address(page);
++
++		scrub_page(page);
++
++		spin_lock_irqsave(&balloon_lock, flags);
++
++		if (xen_feature(XENFEAT_auto_translated_physmap)) {
++			unsigned long gmfn = page_to_pfn(page);
++			struct xen_memory_reservation reservation = {
++				.nr_extents   = 1,
++				.extent_order = 0,
++				.domid        = DOMID_SELF
++			};
++			reservation.extent_start = (unsigned long)&gmfn;
++			ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++						   &reservation);
++			if (ret == 1)
++				ret = 0; /* success */
++		} else {
++			ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
++						  dealloc_pte_fn, NULL);
++		}
++
++		if (ret != 0) {
++			spin_unlock_irqrestore(&balloon_lock, flags);
++			__free_page(page);
++			goto err;
++		}
++
++		totalram_pages = --balloon_stats.current_pages;
++
++		spin_unlock_irqrestore(&balloon_lock, flags);
++	}
++
++ out:
++	schedule_work(&balloon_worker);
++	flush_tlb_all();
++	return pagevec;
++
++ err:
++	spin_lock_irqsave(&balloon_lock, flags);
++	while (--i >= 0)
++		balloon_append(pagevec[i]);
++	spin_unlock_irqrestore(&balloon_lock, flags);
++	kfree(pagevec);
++	pagevec = NULL;
++	goto out;
++}
++
++static void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
++{
++	unsigned long flags;
++	int i;
++
++	if (pagevec == NULL)
++		return;
++
++	spin_lock_irqsave(&balloon_lock, flags);
++	for (i = 0; i < nr_pages; i++) {
++		BUG_ON(page_count(pagevec[i]) != 1);
++		balloon_append(pagevec[i]);
++	}
++	spin_unlock_irqrestore(&balloon_lock, flags);
++
++	kfree(pagevec);
++
++	schedule_work(&balloon_worker);
++}
++
++static void balloon_release_driver_page(struct page *page)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&balloon_lock, flags);
++	balloon_append(page);
++	balloon_stats.driver_pages--;
++	spin_unlock_irqrestore(&balloon_lock, flags);
++
++	schedule_work(&balloon_worker);
++}
++
++
++#define BALLOON_SHOW(name, format, args...)			\
++	static ssize_t show_##name(struct sys_device *dev,	\
++				   char *buf)			\
++	{							\
++		return sprintf(buf, format, ##args);		\
++	}							\
++	static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
++
++BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
++BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
++BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
++BALLOON_SHOW(hard_limit_kb,
++	     (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n",
++	     (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
++BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
++
++static ssize_t show_target_kb(struct sys_device *dev, char *buf)
++{
++	return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
++}
++
++static ssize_t store_target_kb(struct sys_device *dev,
++			       const char *buf,
++			       size_t count)
++{
++	char memstring[64], *endchar;
++	unsigned long long target_bytes;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EPERM;
++
++	if (count <= 1)
++		return -EBADMSG; /* runt */
++	if (count > sizeof(memstring))
++		return -EFBIG;   /* too long */
++	strcpy(memstring, buf);
++
++	target_bytes = memparse(memstring, &endchar);
++	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
++
++	return count;
++}
++
++static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
++		   show_target_kb, store_target_kb);
++
++static struct sysdev_attribute *balloon_attrs[] = {
++	&attr_target_kb,
++};
++
++static struct attribute *balloon_info_attrs[] = {
++	&attr_current_kb.attr,
++	&attr_low_kb.attr,
++	&attr_high_kb.attr,
++	&attr_hard_limit_kb.attr,
++	&attr_driver_kb.attr,
++	NULL
++};
++
++static struct attribute_group balloon_info_group = {
++	.name = "info",
++	.attrs = balloon_info_attrs,
++};
++
++static struct sysdev_class balloon_sysdev_class = {
++	.name = BALLOON_CLASS_NAME,
++};
++
++static int register_balloon(struct sys_device *sysdev)
++{
++	int i, error;
++
++	error = sysdev_class_register(&balloon_sysdev_class);
++	if (error)
++		return error;
++
++	sysdev->id = 0;
++	sysdev->cls = &balloon_sysdev_class;
++
++	error = sysdev_register(sysdev);
++	if (error) {
++		sysdev_class_unregister(&balloon_sysdev_class);
++		return error;
++	}
++
++	for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
++		error = sysdev_create_file(sysdev, balloon_attrs[i]);
++		if (error)
++			goto fail;
++	}
++
++	error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
++	if (error)
++		goto fail;
++
++	return 0;
++
++ fail:
++	while (--i >= 0)
++		sysdev_remove_file(sysdev, balloon_attrs[i]);
++	sysdev_unregister(sysdev);
++	sysdev_class_unregister(&balloon_sysdev_class);
++	return error;
++}
++
++static void unregister_balloon(struct sys_device *sysdev)
++{
++	int i;
++
++	sysfs_remove_group(&sysdev->kobj, &balloon_info_group);
++	for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++)
++		sysdev_remove_file(sysdev, balloon_attrs[i]);
++	sysdev_unregister(sysdev);
++	sysdev_class_unregister(&balloon_sysdev_class);
++}
++
++static void balloon_sysfs_exit(void)
++{
++	unregister_balloon(&balloon_sysdev);
++}
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/xen/events.c b/drivers/xen/events.c
+new file mode 100644
+index 0000000..4f0f22b
+--- /dev/null
++++ b/drivers/xen/events.c
+@@ -0,0 +1,674 @@
++/*
++ * Xen event channels
++ *
++ * Xen models interrupts with abstract event channels.  Because each
++ * domain gets 1024 event channels, but NR_IRQ is not that large, we
++ * must dynamically map irqs<->event channels.  The event channels
++ * interface with the rest of the kernel by defining a xen interrupt
++ * chip.  When an event is recieved, it is mapped to an irq and sent
++ * through the normal interrupt processing path.
++ *
++ * There are four kinds of events which can be mapped to an event
++ * channel:
++ *
++ * 1. Inter-domain notifications.  This includes all the virtual
++ *    device events, since they're driven by front-ends in another domain
++ *    (typically dom0).
++ * 2. VIRQs, typically used for timers.  These are per-cpu events.
++ * 3. IPIs.
++ * 4. Hardware interrupts. Not supported at present.
++ *
++ * Jeremy Fitzhardinge <jeremy at xensource.com>, XenSource Inc, 2007
++ */
++
++#include <linux/linkage.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/module.h>
++#include <linux/string.h>
++
++#include <asm/ptrace.h>
++#include <asm/irq.h>
++#include <asm/sync_bitops.h>
++#include <asm/xen/hypercall.h>
++#include <asm/xen/hypervisor.h>
++
++#include <xen/xen-ops.h>
++#include <xen/events.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/event_channel.h>
++
++/*
++ * This lock protects updates to the following mapping and reference-count
++ * arrays. The lock does not need to be acquired to read the mapping tables.
++ */
++static DEFINE_SPINLOCK(irq_mapping_update_lock);
++
++/* IRQ <-> VIRQ mapping. */
++static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
++
++/* IRQ <-> IPI mapping */
++static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1};
++
++/* Packed IRQ information: binding type, sub-type index, and event channel. */
++struct packed_irq
++{
++	unsigned short evtchn;
++	unsigned char index;
++	unsigned char type;
++};
++
++static struct packed_irq irq_info[NR_IRQS];
++
++/* Binding types. */
++enum {
++	IRQT_UNBOUND,
++	IRQT_PIRQ,
++	IRQT_VIRQ,
++	IRQT_IPI,
++	IRQT_EVTCHN
++};
++
++/* Convenient shorthand for packed representation of an unbound IRQ. */
++#define IRQ_UNBOUND	mk_irq_info(IRQT_UNBOUND, 0, 0)
++
++static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
++	[0 ... NR_EVENT_CHANNELS-1] = -1
++};
++static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
++static u8 cpu_evtchn[NR_EVENT_CHANNELS];
++
++/* Reference counts for bindings to IRQs. */
++static int irq_bindcount[NR_IRQS];
++
++/* Xen will never allocate port zero for any purpose. */
++#define VALID_EVTCHN(chn)	((chn) != 0)
++
++/*
++ * Force a proper event-channel callback from Xen after clearing the
++ * callback mask. We do this in a very simple manner, by making a call
++ * down into Xen. The pending flag will be checked by Xen on return.
++ */
++void force_evtchn_callback(void)
++{
++	(void)HYPERVISOR_xen_version(0, NULL);
++}
++EXPORT_SYMBOL_GPL(force_evtchn_callback);
++
++static struct irq_chip xen_dynamic_chip;
++
++/* Constructor for packed IRQ information. */
++static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn)
++{
++	return (struct packed_irq) { evtchn, index, type };
++}
++
++/*
++ * Accessors for packed IRQ information.
++ */
++static inline unsigned int evtchn_from_irq(int irq)
++{
++	return irq_info[irq].evtchn;
++}
++
++static inline unsigned int index_from_irq(int irq)
++{
++	return irq_info[irq].index;
++}
++
++static inline unsigned int type_from_irq(int irq)
++{
++	return irq_info[irq].type;
++}
++
++static inline unsigned long active_evtchns(unsigned int cpu,
++					   struct shared_info *sh,
++					   unsigned int idx)
++{
++	return (sh->evtchn_pending[idx] &
++		cpu_evtchn_mask[cpu][idx] &
++		~sh->evtchn_mask[idx]);
++}
++
++static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
++{
++	int irq = evtchn_to_irq[chn];
++
++	BUG_ON(irq == -1);
++#ifdef CONFIG_SMP
++	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
++#endif
++
++	__clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
++	__set_bit(chn, cpu_evtchn_mask[cpu]);
++
++	cpu_evtchn[chn] = cpu;
++}
++
++static void init_evtchn_cpu_bindings(void)
++{
++#ifdef CONFIG_SMP
++	int i;
++	/* By default all event channels notify CPU#0. */
++	for (i = 0; i < NR_IRQS; i++)
++		irq_desc[i].affinity = cpumask_of_cpu(0);
++#endif
++
++	memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
++	memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
++}
++
++static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
++{
++	return cpu_evtchn[evtchn];
++}
++
++static inline void clear_evtchn(int port)
++{
++	struct shared_info *s = HYPERVISOR_shared_info;
++	sync_clear_bit(port, &s->evtchn_pending[0]);
++}
++
++static inline void set_evtchn(int port)
++{
++	struct shared_info *s = HYPERVISOR_shared_info;
++	sync_set_bit(port, &s->evtchn_pending[0]);
++}
++
++
++/**
++ * notify_remote_via_irq - send event to remote end of event channel via irq
++ * @irq: irq of event channel to send event to
++ *
++ * Unlike notify_remote_via_evtchn(), this is safe to use across
++ * save/restore. Notifications on a broken connection are silently
++ * dropped.
++ */
++void notify_remote_via_irq(int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		notify_remote_via_evtchn(evtchn);
++}
++EXPORT_SYMBOL_GPL(notify_remote_via_irq);
++
++static void mask_evtchn(int port)
++{
++	struct shared_info *s = HYPERVISOR_shared_info;
++	sync_set_bit(port, &s->evtchn_mask[0]);
++}
++
++static void unmask_evtchn(int port)
++{
++	struct shared_info *s = HYPERVISOR_shared_info;
++	unsigned int cpu = get_cpu();
++
++	BUG_ON(!irqs_disabled());
++
++	/* Slow path (hypercall) if this is a non-local port. */
++	if (unlikely(cpu != cpu_from_evtchn(port))) {
++		struct evtchn_unmask unmask = { .port = port };
++		(void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
++	} else {
++		struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
++
++		sync_clear_bit(port, &s->evtchn_mask[0]);
++
++		/*
++		 * The following is basically the equivalent of
++		 * 'hw_resend_irq'. Just like a real IO-APIC we 'lose
++		 * the interrupt edge' if the channel is masked.
++		 */
++		if (sync_test_bit(port, &s->evtchn_pending[0]) &&
++		    !sync_test_and_set_bit(port / BITS_PER_LONG,
++					   &vcpu_info->evtchn_pending_sel))
++			vcpu_info->evtchn_upcall_pending = 1;
++	}
++
++	put_cpu();
++}
++
++static int find_unbound_irq(void)
++{
++	int irq;
++
++	/* Only allocate from dynirq range */
++	for (irq = 0; irq < NR_IRQS; irq++)
++		if (irq_bindcount[irq] == 0)
++			break;
++
++	if (irq == NR_IRQS)
++		panic("No available IRQ to bind to: increase NR_IRQS!\n");
++
++	return irq;
++}
++
++int bind_evtchn_to_irq(unsigned int evtchn)
++{
++	int irq;
++
++	spin_lock(&irq_mapping_update_lock);
++
++	irq = evtchn_to_irq[evtchn];
++
++	if (irq == -1) {
++		irq = find_unbound_irq();
++
++		dynamic_irq_init(irq);
++		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
++					      handle_level_irq, "event");
++
++		evtchn_to_irq[evtchn] = irq;
++		irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
++	}
++
++	irq_bindcount[irq]++;
++
++	spin_unlock(&irq_mapping_update_lock);
++
++	return irq;
++}
++EXPORT_SYMBOL_GPL(bind_evtchn_to_irq);
++
++static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
++{
++	struct evtchn_bind_ipi bind_ipi;
++	int evtchn, irq;
++
++	spin_lock(&irq_mapping_update_lock);
++
++	irq = per_cpu(ipi_to_irq, cpu)[ipi];
++	if (irq == -1) {
++		irq = find_unbound_irq();
++		if (irq < 0)
++			goto out;
++
++		dynamic_irq_init(irq);
++		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
++					      handle_level_irq, "ipi");
++
++		bind_ipi.vcpu = cpu;
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
++						&bind_ipi) != 0)
++			BUG();
++		evtchn = bind_ipi.port;
++
++		evtchn_to_irq[evtchn] = irq;
++		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
++
++		per_cpu(ipi_to_irq, cpu)[ipi] = irq;
++
++		bind_evtchn_to_cpu(evtchn, cpu);
++	}
++
++	irq_bindcount[irq]++;
++
++ out:
++	spin_unlock(&irq_mapping_update_lock);
++	return irq;
++}
++
++
++static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
++{
++	struct evtchn_bind_virq bind_virq;
++	int evtchn, irq;
++
++	spin_lock(&irq_mapping_update_lock);
++
++	irq = per_cpu(virq_to_irq, cpu)[virq];
++
++	if (irq == -1) {
++		bind_virq.virq = virq;
++		bind_virq.vcpu = cpu;
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
++						&bind_virq) != 0)
++			BUG();
++		evtchn = bind_virq.port;
++
++		irq = find_unbound_irq();
++
++		dynamic_irq_init(irq);
++		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
++					      handle_level_irq, "virq");
++
++		evtchn_to_irq[evtchn] = irq;
++		irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++
++		per_cpu(virq_to_irq, cpu)[virq] = irq;
++
++		bind_evtchn_to_cpu(evtchn, cpu);
++	}
++
++	irq_bindcount[irq]++;
++
++	spin_unlock(&irq_mapping_update_lock);
++
++	return irq;
++}
++
++static void unbind_from_irq(unsigned int irq)
++{
++	struct evtchn_close close;
++	int evtchn = evtchn_from_irq(irq);
++
++	spin_lock(&irq_mapping_update_lock);
++
++	if (VALID_EVTCHN(evtchn) && (--irq_bindcount[irq] == 0)) {
++		close.port = evtchn;
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
++			BUG();
++
++		switch (type_from_irq(irq)) {
++		case IRQT_VIRQ:
++			per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
++				[index_from_irq(irq)] = -1;
++			break;
++		default:
++			break;
++		}
++
++		/* Closed ports are implicitly re-bound to VCPU0. */
++		bind_evtchn_to_cpu(evtchn, 0);
++
++		evtchn_to_irq[evtchn] = -1;
++		irq_info[irq] = IRQ_UNBOUND;
++
++		dynamic_irq_init(irq);
++	}
++
++	spin_unlock(&irq_mapping_update_lock);
++}
++
++int bind_evtchn_to_irqhandler(unsigned int evtchn,
++			      irq_handler_t handler,
++			      unsigned long irqflags,
++			      const char *devname, void *dev_id)
++{
++	unsigned int irq;
++	int retval;
++
++	irq = bind_evtchn_to_irq(evtchn);
++	retval = request_irq(irq, handler, irqflags, devname, dev_id);
++	if (retval != 0) {
++		unbind_from_irq(irq);
++		return retval;
++	}
++
++	return irq;
++}
++EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
++
++int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
++			    irq_handler_t handler,
++			    unsigned long irqflags, const char *devname, void *dev_id)
++{
++	unsigned int irq;
++	int retval;
++
++	irq = bind_virq_to_irq(virq, cpu);
++	retval = request_irq(irq, handler, irqflags, devname, dev_id);
++	if (retval != 0) {
++		unbind_from_irq(irq);
++		return retval;
++	}
++
++	return irq;
++}
++EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
++
++int bind_ipi_to_irqhandler(enum ipi_vector ipi,
++			   unsigned int cpu,
++			   irq_handler_t handler,
++			   unsigned long irqflags,
++			   const char *devname,
++			   void *dev_id)
++{
++	int irq, retval;
++
++	irq = bind_ipi_to_irq(ipi, cpu);
++	if (irq < 0)
++		return irq;
++
++	retval = request_irq(irq, handler, irqflags, devname, dev_id);
++	if (retval != 0) {
++		unbind_from_irq(irq);
++		return retval;
++	}
++
++	return irq;
++}
++
++void unbind_from_irqhandler(unsigned int irq, void *dev_id)
++{
++	free_irq(irq, dev_id);
++	unbind_from_irq(irq);
++}
++EXPORT_SYMBOL_GPL(unbind_from_irqhandler);
++
++void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector)
++{
++	int irq = per_cpu(ipi_to_irq, cpu)[vector];
++	BUG_ON(irq < 0);
++	notify_remote_via_irq(irq);
++}
++
++irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
++{
++	struct shared_info *sh = HYPERVISOR_shared_info;
++	int cpu = smp_processor_id();
++	int i;
++	unsigned long flags;
++	static DEFINE_SPINLOCK(debug_lock);
++
++	spin_lock_irqsave(&debug_lock, flags);
++
++	printk("vcpu %d\n  ", cpu);
++
++	for_each_online_cpu(i) {
++		struct vcpu_info *v = per_cpu(xen_vcpu, i);
++		printk("%d: masked=%d pending=%d event_sel %08lx\n  ", i,
++			(get_irq_regs() && i == cpu) ? xen_irqs_disabled(get_irq_regs()) : v->evtchn_upcall_mask,
++			v->evtchn_upcall_pending,
++			v->evtchn_pending_sel);
++	}
++	printk("pending:\n   ");
++	for(i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--)
++		printk("%08lx%s", sh->evtchn_pending[i],
++			i % 8 == 0 ? "\n   " : " ");
++	printk("\nmasks:\n   ");
++	for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
++		printk("%08lx%s", sh->evtchn_mask[i],
++			i % 8 == 0 ? "\n   " : " ");
++
++	printk("\nunmasked:\n   ");
++	for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
++		printk("%08lx%s", sh->evtchn_pending[i] & ~sh->evtchn_mask[i],
++			i % 8 == 0 ? "\n   " : " ");
++
++	printk("\npending list:\n");
++	for(i = 0; i < NR_EVENT_CHANNELS; i++) {
++		if (sync_test_bit(i, sh->evtchn_pending)) {
++			printk("  %d: event %d -> irq %d\n",
++				cpu_evtchn[i], i,
++				evtchn_to_irq[i]);
++		}
++	}
++
++	spin_unlock_irqrestore(&debug_lock, flags);
++
++	return IRQ_HANDLED;
++}
++
++
++/*
++ * Search the CPUs pending events bitmasks.  For each one found, map
++ * the event number to an irq, and feed it into do_IRQ() for
++ * handling.
++ *
++ * Xen uses a two-level bitmap to speed searching.  The first level is
++ * a bitset of words which contain pending event bits.  The second
++ * level is a bitset of pending events themselves.
++ */
++void xen_evtchn_do_upcall(struct pt_regs *regs)
++{
++	int cpu = get_cpu();
++	struct shared_info *s = HYPERVISOR_shared_info;
++	struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
++	static DEFINE_PER_CPU(unsigned, nesting_count);
++ 	unsigned count;
++
++	do {
++		unsigned long pending_words;
++
++		vcpu_info->evtchn_upcall_pending = 0;
++
++		if (__get_cpu_var(nesting_count)++)
++			goto out;
++
++#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
++		/* Clear master flag /before/ clearing selector flag. */
++		rmb();
++#endif
++		pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
++		while (pending_words != 0) {
++			unsigned long pending_bits;
++			int word_idx = __ffs(pending_words);
++			pending_words &= ~(1UL << word_idx);
++
++			while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
++				int bit_idx = __ffs(pending_bits);
++				int port = (word_idx * BITS_PER_LONG) + bit_idx;
++				int irq = evtchn_to_irq[port];
++
++				if (irq != -1)
++					xen_do_IRQ(irq, regs);
++			}
++		}
++
++		BUG_ON(!irqs_disabled());
++
++		count = __get_cpu_var(nesting_count);
++		__get_cpu_var(nesting_count) = 0;
++	} while(count != 1);
++
++out:
++	put_cpu();
++}
++
++/* Rebind an evtchn so that it gets delivered to a specific cpu */
++static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
++{
++	struct evtchn_bind_vcpu bind_vcpu;
++	int evtchn = evtchn_from_irq(irq);
++
++	if (!VALID_EVTCHN(evtchn))
++		return;
++
++	/* Send future instances of this interrupt to other vcpu. */
++	bind_vcpu.port = evtchn;
++	bind_vcpu.vcpu = tcpu;
++
++	/*
++	 * If this fails, it usually just indicates that we're dealing with a
++	 * virq or IPI channel, which don't actually need to be rebound. Ignore
++	 * it, but don't do the xenlinux-level rebind in that case.
++	 */
++	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
++		bind_evtchn_to_cpu(evtchn, tcpu);
++}
++
++
++static void set_affinity_irq(unsigned irq, cpumask_t dest)
++{
++	unsigned tcpu = first_cpu(dest);
++	rebind_irq_to_cpu(irq, tcpu);
++}
++
++int resend_irq_on_evtchn(unsigned int irq)
++{
++	int masked, evtchn = evtchn_from_irq(irq);
++	struct shared_info *s = HYPERVISOR_shared_info;
++
++	if (!VALID_EVTCHN(evtchn))
++		return 1;
++
++	masked = sync_test_and_set_bit(evtchn, s->evtchn_mask);
++	sync_set_bit(evtchn, s->evtchn_pending);
++	if (!masked)
++		unmask_evtchn(evtchn);
++
++	return 1;
++}
++
++static void enable_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		unmask_evtchn(evtchn);
++}
++
++static void disable_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		mask_evtchn(evtchn);
++}
++
++static void ack_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	move_native_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		clear_evtchn(evtchn);
++}
++
++static int retrigger_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++	struct shared_info *sh = HYPERVISOR_shared_info;
++	int ret = 0;
++
++	if (VALID_EVTCHN(evtchn)) {
++		int masked;
++
++		masked = sync_test_and_set_bit(evtchn, sh->evtchn_mask);
++		sync_set_bit(evtchn, sh->evtchn_pending);
++		if (!masked)
++			unmask_evtchn(evtchn);
++		ret = 1;
++	}
++
++	return ret;
++}
++
++static struct irq_chip xen_dynamic_chip __read_mostly = {
++	.name		= "xen-dyn",
++	.mask		= disable_dynirq,
++	.unmask		= enable_dynirq,
++	.ack		= ack_dynirq,
++	.set_affinity	= set_affinity_irq,
++	.retrigger	= retrigger_dynirq,
++};
++
++void __init xen_init_IRQ(void)
++{
++	int i;
++
++	init_evtchn_cpu_bindings();
++
++	/* No event channels are 'live' right now. */
++	for (i = 0; i < NR_EVENT_CHANNELS; i++)
++		mask_evtchn(i);
++
++	/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
++	for (i = 0; i < NR_IRQS; i++)
++		irq_bindcount[i] = 0;
++
++	irq_ctx_init(smp_processor_id());
++}
+diff --git a/drivers/xen/features.c b/drivers/xen/features.c
+new file mode 100644
+index 0000000..0707714
+--- /dev/null
++++ b/drivers/xen/features.c
+@@ -0,0 +1,29 @@
++/******************************************************************************
++ * features.c
++ *
++ * Xen feature flags.
++ *
++ * Copyright (c) 2006, Ian Campbell, XenSource Inc.
++ */
++#include <linux/types.h>
++#include <linux/cache.h>
++#include <linux/module.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/features.h>
++
++u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
++EXPORT_SYMBOL_GPL(xen_features);
++
++void xen_setup_features(void)
++{
++	struct xen_feature_info fi;
++	int i, j;
++
++	for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
++		fi.submap_idx = i;
++		if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
++			break;
++		for (j = 0; j < 32; j++)
++			xen_features[i * 32 + j] = !!(fi.submap & 1<<j);
++	}
++}
+diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
+index d85dc6d..52b6b41 100644
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -439,24 +439,6 @@ static inline unsigned int max_nr_grant_frames(void)
+ 	return xen_max;
+ }
+ 
+-static int map_pte_fn(pte_t *pte, struct page *pmd_page,
+-		      unsigned long addr, void *data)
+-{
+-	unsigned long **frames = (unsigned long **)data;
+-
+-	set_pte_at(&init_mm, addr, pte, mfn_pte((*frames)[0], PAGE_KERNEL));
+-	(*frames)++;
+-	return 0;
+-}
+-
+-static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
+-			unsigned long addr, void *data)
+-{
+-
+-	set_pte_at(&init_mm, addr, pte, __pte(0));
+-	return 0;
+-}
+-
+ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ {
+ 	struct gnttab_setup_table setup;
+@@ -470,7 +452,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ 
+ 	setup.dom        = DOMID_SELF;
+ 	setup.nr_frames  = nr_gframes;
+-	setup.frame_list = frames;
++	set_xen_guest_handle(setup.frame_list, frames);
+ 
+ 	rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ 	if (rc == -ENOSYS) {
+@@ -480,17 +462,9 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ 
+ 	BUG_ON(rc || setup.status);
+ 
+-	if (shared == NULL) {
+-		struct vm_struct *area;
+-		area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
+-		BUG_ON(area == NULL);
+-		shared = area->addr;
+-	}
+-	rc = apply_to_page_range(&init_mm, (unsigned long)shared,
+-				 PAGE_SIZE * nr_gframes,
+-				 map_pte_fn, &frames);
++	rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(),
++				    &shared);
+ 	BUG_ON(rc);
+-	frames -= nr_gframes; /* adjust after map_pte_fn() */
+ 
+ 	kfree(frames);
+ 
+@@ -506,10 +480,7 @@ static int gnttab_resume(void)
+ 
+ static int gnttab_suspend(void)
+ {
+-	apply_to_page_range(&init_mm, (unsigned long)shared,
+-			    PAGE_SIZE * nr_grant_frames,
+-			    unmap_pte_fn, NULL);
+-
++	arch_gnttab_unmap_shared(shared, nr_grant_frames);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
+index 9fd2f70..0f86b0f 100644
+--- a/drivers/xen/xenbus/xenbus_client.c
++++ b/drivers/xen/xenbus/xenbus_client.c
+@@ -399,7 +399,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
+ 
+ 	*vaddr = NULL;
+ 
+-	area = alloc_vm_area(PAGE_SIZE);
++	area = xen_alloc_vm_area(PAGE_SIZE);
+ 	if (!area)
+ 		return -ENOMEM;
+ 
+@@ -409,7 +409,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
+ 		BUG();
+ 
+ 	if (op.status != GNTST_okay) {
+-		free_vm_area(area);
++		xen_free_vm_area(area);
+ 		xenbus_dev_fatal(dev, op.status,
+ 				 "mapping in shared page %d from domain %d",
+ 				 gnt_ref, dev->otherend_id);
+@@ -508,7 +508,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
+ 		BUG();
+ 
+ 	if (op.status == GNTST_okay)
+-		free_vm_area(area);
++		xen_free_vm_area(area);
+ 	else
+ 		xenbus_dev_error(dev, op.status,
+ 				 "unmapping page at handle %d error %d",
+diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
+index 4750de3..57ceb53 100644
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -88,6 +88,16 @@ int xenbus_match(struct device *_dev, struct device_driver *_drv)
+ 	return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
+ }
+ 
++static int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env)
++{
++	struct xenbus_device *dev = to_xenbus_device(_dev);
++
++	if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype))
++		return -ENOMEM;
++
++	return 0;
++}
++
+ /* device/<type>/<id> => <type>-<id> */
+ static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
+ {
+@@ -166,6 +176,7 @@ static struct xen_bus_type xenbus_frontend = {
+ 	.bus = {
+ 		.name     = "xen",
+ 		.match    = xenbus_match,
++		.uevent   = xenbus_uevent,
+ 		.probe    = xenbus_dev_probe,
+ 		.remove   = xenbus_dev_remove,
+ 		.shutdown = xenbus_dev_shutdown,
+@@ -438,6 +449,12 @@ static ssize_t xendev_show_devtype(struct device *dev,
+ }
+ DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
+ 
++static ssize_t xendev_show_modalias(struct device *dev,
++				    struct device_attribute *attr, char *buf)
++{
++	return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
++}
++DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
+ 
+ int xenbus_probe_node(struct xen_bus_type *bus,
+ 		      const char *type,
+@@ -492,10 +509,16 @@ int xenbus_probe_node(struct xen_bus_type *bus,
+ 
+ 	err = device_create_file(&xendev->dev, &dev_attr_devtype);
+ 	if (err)
+-		goto fail_remove_file;
++		goto fail_remove_nodename;
++
++	err = device_create_file(&xendev->dev, &dev_attr_modalias);
++	if (err)
++		goto fail_remove_devtype;
+ 
+ 	return 0;
+-fail_remove_file:
++fail_remove_devtype:
++	device_remove_file(&xendev->dev, &dev_attr_devtype);
++fail_remove_nodename:
+ 	device_remove_file(&xendev->dev, &dev_attr_nodename);
+ fail_unregister:
+ 	device_unregister(&xendev->dev);
+@@ -846,6 +869,7 @@ static int is_disconnected_device(struct device *dev, void *data)
+ {
+ 	struct xenbus_device *xendev = to_xenbus_device(dev);
+ 	struct device_driver *drv = data;
++	struct xenbus_driver *xendrv;
+ 
+ 	/*
+ 	 * A device with no driver will never connect. We care only about
+@@ -858,7 +882,9 @@ static int is_disconnected_device(struct device *dev, void *data)
+ 	if (drv && (dev->driver != drv))
+ 		return 0;
+ 
+-	return (xendev->state != XenbusStateConnected);
++	xendrv = to_xenbus_driver(dev->driver);
++	return (xendev->state != XenbusStateConnected ||
++		(xendrv->is_ready && !xendrv->is_ready(xendev)));
+ }
+ 
+ static int exists_disconnected_device(struct device_driver *drv)
+diff --git a/drivers/xen/xencomm.c b/drivers/xen/xencomm.c
+new file mode 100644
+index 0000000..797cb4e
+--- /dev/null
++++ b/drivers/xen/xencomm.c
+@@ -0,0 +1,232 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public 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 Corp. 2006
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#include <linux/gfp.h>
++#include <linux/mm.h>
++#include <asm/page.h>
++#include <xen/xencomm.h>
++#include <xen/interface/xen.h>
++#ifdef __ia64__
++#include <asm/xen/xencomm.h>	/* for is_kern_addr() */
++#endif
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++static int xencomm_init(struct xencomm_desc *desc,
++			void *buffer, unsigned long bytes)
++{
++	unsigned long recorded = 0;
++	int i = 0;
++
++	while ((recorded < bytes) && (i < desc->nr_addrs)) {
++		unsigned long vaddr = (unsigned long)buffer + recorded;
++		unsigned long paddr;
++		int offset;
++		int chunksz;
++
++		offset = vaddr % PAGE_SIZE; /* handle partial pages */
++		chunksz = min(PAGE_SIZE - offset, bytes - recorded);
++
++		paddr = xencomm_vtop(vaddr);
++		if (paddr == ~0UL) {
++			printk(KERN_DEBUG "%s: couldn't translate vaddr %lx\n",
++			       __func__, vaddr);
++			return -EINVAL;
++		}
++
++		desc->address[i++] = paddr;
++		recorded += chunksz;
++	}
++
++	if (recorded < bytes) {
++		printk(KERN_DEBUG
++		       "%s: could only translate %ld of %ld bytes\n",
++		       __func__, recorded, bytes);
++		return -ENOSPC;
++	}
++
++	/* mark remaining addresses invalid (just for safety) */
++	while (i < desc->nr_addrs)
++		desc->address[i++] = XENCOMM_INVALID;
++
++	desc->magic = XENCOMM_MAGIC;
++
++	return 0;
++}
++
++static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask,
++					  void *buffer, unsigned long bytes)
++{
++	struct xencomm_desc *desc;
++	unsigned long buffer_ulong = (unsigned long)buffer;
++	unsigned long start = buffer_ulong & PAGE_MASK;
++	unsigned long end = (buffer_ulong + bytes) | ~PAGE_MASK;
++	unsigned long nr_addrs = (end - start + 1) >> PAGE_SHIFT;
++	unsigned long size = sizeof(*desc) +
++		sizeof(desc->address[0]) * nr_addrs;
++
++	/*
++	 * slab allocator returns at least sizeof(void*) aligned pointer.
++	 * When sizeof(*desc) > sizeof(void*), struct xencomm_desc might
++	 * cross page boundary.
++	 */
++	if (sizeof(*desc) > sizeof(void *)) {
++		unsigned long order = get_order(size);
++		desc = (struct xencomm_desc *)__get_free_pages(gfp_mask,
++							       order);
++		if (desc == NULL)
++			return NULL;
++
++		desc->nr_addrs =
++			((PAGE_SIZE << order) - sizeof(struct xencomm_desc)) /
++			sizeof(*desc->address);
++	} else {
++		desc = kmalloc(size, gfp_mask);
++		if (desc == NULL)
++			return NULL;
++
++		desc->nr_addrs = nr_addrs;
++	}
++	return desc;
++}
++
++void xencomm_free(struct xencomm_handle *desc)
++{
++	if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG)) {
++		struct xencomm_desc *desc__ = (struct xencomm_desc *)desc;
++		if (sizeof(*desc__) > sizeof(void *)) {
++			unsigned long size = sizeof(*desc__) +
++				sizeof(desc__->address[0]) * desc__->nr_addrs;
++			unsigned long order = get_order(size);
++			free_pages((unsigned long)__va(desc), order);
++		} else
++			kfree(__va(desc));
++	}
++}
++
++static int xencomm_create(void *buffer, unsigned long bytes,
++			  struct xencomm_desc **ret, gfp_t gfp_mask)
++{
++	struct xencomm_desc *desc;
++	int rc;
++
++	pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes);
++
++	if (bytes == 0) {
++		/* don't create a descriptor; Xen recognizes NULL. */
++		BUG_ON(buffer != NULL);
++		*ret = NULL;
++		return 0;
++	}
++
++	BUG_ON(buffer == NULL); /* 'bytes' is non-zero */
++
++	desc = xencomm_alloc(gfp_mask, buffer, bytes);
++	if (!desc) {
++		printk(KERN_DEBUG "%s failure\n", "xencomm_alloc");
++		return -ENOMEM;
++	}
++
++	rc = xencomm_init(desc, buffer, bytes);
++	if (rc) {
++		printk(KERN_DEBUG "%s failure: %d\n", "xencomm_init", rc);
++		xencomm_free((struct xencomm_handle *)__pa(desc));
++		return rc;
++	}
++
++	*ret = desc;
++	return 0;
++}
++
++/* check if memory address is within VMALLOC region  */
++static int is_phys_contiguous(unsigned long addr)
++{
++	if (!is_kernel_addr(addr))
++		return 0;
++
++	return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
++}
++
++static struct xencomm_handle *xencomm_create_inline(void *ptr)
++{
++	unsigned long paddr;
++
++	BUG_ON(!is_phys_contiguous((unsigned long)ptr));
++
++	paddr = (unsigned long)xencomm_pa(ptr);
++	BUG_ON(paddr & XENCOMM_INLINE_FLAG);
++	return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
++}
++
++/* "mini" routine, for stack-based communications: */
++static int xencomm_create_mini(void *buffer,
++	unsigned long bytes, struct xencomm_mini *xc_desc,
++	struct xencomm_desc **ret)
++{
++	int rc = 0;
++	struct xencomm_desc *desc;
++	BUG_ON(((unsigned long)xc_desc) % sizeof(*xc_desc) != 0);
++
++	desc = (void *)xc_desc;
++
++	desc->nr_addrs = XENCOMM_MINI_ADDRS;
++
++	rc = xencomm_init(desc, buffer, bytes);
++	if (!rc)
++		*ret = desc;
++
++	return rc;
++}
++
++struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes)
++{
++	int rc;
++	struct xencomm_desc *desc;
++
++	if (is_phys_contiguous((unsigned long)ptr))
++		return xencomm_create_inline(ptr);
++
++	rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
++
++	if (rc || desc == NULL)
++		return NULL;
++
++	return xencomm_pa(desc);
++}
++
++struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes,
++			struct xencomm_mini *xc_desc)
++{
++	int rc;
++	struct xencomm_desc *desc = NULL;
++
++	if (is_phys_contiguous((unsigned long)ptr))
++		return xencomm_create_inline(ptr);
++
++	rc = xencomm_create_mini(ptr, bytes, xc_desc,
++				&desc);
++
++	if (rc)
++		return NULL;
++
++	return xencomm_pa(desc);
++}
+diff --git a/fs/9p/fid.c b/fs/9p/fid.c
+index dfebdbe..3031e32 100644
+--- a/fs/9p/fid.c
++++ b/fs/9p/fid.c
+@@ -26,7 +26,6 @@
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+ #include <linux/idr.h>
+-#include <asm/semaphore.h>
+ #include <net/9p/9p.h>
+ #include <net/9p/client.h>
+ 
+diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
+index 678c02f..a452ac6 100644
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -224,12 +224,11 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
+ }
+ 
+ static void
+-v9fs_umount_begin(struct vfsmount *vfsmnt, int flags)
++v9fs_umount_begin(struct super_block *sb)
+ {
+-	struct v9fs_session_info *v9ses = vfsmnt->mnt_sb->s_fs_info;
++	struct v9fs_session_info *v9ses = sb->s_fs_info;
+ 
+-	if (flags & MNT_FORCE)
+-		v9fs_session_cancel(v9ses);
++	v9fs_session_cancel(v9ses);
+ }
+ 
+ static const struct super_operations v9fs_super_ops = {
+diff --git a/fs/Kconfig b/fs/Kconfig
+index c509123..2e43d46 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -411,7 +411,7 @@ config JFS_STATISTICS
+ 	  to be made available to the user in the /proc/fs/jfs/ directory.
+ 
+ config FS_POSIX_ACL
+-# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs)
++# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4)
+ #
+ # NOTE: you can implement Posix ACLs without these helpers (XFS does).
+ # 	Never use this symbol for ifdefs.
+@@ -444,6 +444,32 @@ config OCFS2_FS
+ 	  For more information on OCFS2, see the file
+ 	  <file:Documentation/filesystems/ocfs2.txt>.
+ 
++config OCFS2_FS_O2CB
++	tristate "O2CB Kernelspace Clustering"
++	depends on OCFS2_FS
++	default y
++	help
++	  OCFS2 includes a simple kernelspace clustering package, the OCFS2
++	  Cluster Base.  It only requires a very small userspace component
++	  to configure it. This comes with the standard ocfs2-tools package.
++	  O2CB is limited to maintaining a cluster for OCFS2 file systems.
++	  It cannot manage any other cluster applications.
++
++	  It is always safe to say Y here, as the clustering method is
++	  run-time selectable.
++
++config OCFS2_FS_USERSPACE_CLUSTER
++	tristate "OCFS2 Userspace Clustering"
++	depends on OCFS2_FS && DLM
++	default y
++	help
++	  This option will allow OCFS2 to use userspace clustering services
++	  in conjunction with the DLM in fs/dlm.  If you are using a
++	  userspace cluster manager, say Y here.
++
++	  It is safe to say Y, as the clustering method is run-time
++	  selectable.
++
+ config OCFS2_DEBUG_MASKLOG
+ 	bool "OCFS2 logging support"
+ 	depends on OCFS2_FS
+@@ -663,6 +689,7 @@ config ZISOFS
+ 
+ config UDF_FS
+ 	tristate "UDF file system support"
++	select CRC_ITU_T
+ 	help
+ 	  This is the new file system used on some CD-ROMs and DVDs. Say Y if
+ 	  you intend to mount DVD discs or CDRW's written in packet mode, or
+@@ -1637,105 +1664,86 @@ config NFS_V4
+ 
+ 	  If unsure, say N.
+ 
+-config NFS_DIRECTIO
+-	bool "Allow direct I/O on NFS files"
+-	depends on NFS_FS
+-	help
+-	  This option enables applications to perform uncached I/O on files
+-	  in NFS file systems using the O_DIRECT open() flag.  When O_DIRECT
+-	  is set for a file, its data is not cached in the system's page
+-	  cache.  Data is moved to and from user-level application buffers
+-	  directly.  Unlike local disk-based file systems, NFS O_DIRECT has
+-	  no alignment restrictions.
+-
+-	  Unless your program is designed to use O_DIRECT properly, you are
+-	  much better off allowing the NFS client to manage data caching for
+-	  you.  Misusing O_DIRECT can cause poor server performance or network
+-	  storms.  This kernel build option defaults OFF to avoid exposing
+-	  system administrators unwittingly to a potentially hazardous
+-	  feature.
+-
+-	  For more details on NFS O_DIRECT, see fs/nfs/direct.c.
+-
+-	  If unsure, say N.  This reduces the size of the NFS client, and
+-	  causes open() to return EINVAL if a file residing in NFS is
+-	  opened with the O_DIRECT flag.
+-
+ config NFSD
+ 	tristate "NFS server support"
+ 	depends on INET
+ 	select LOCKD
+ 	select SUNRPC
+ 	select EXPORTFS
+-	select NFSD_V2_ACL if NFSD_V3_ACL
+ 	select NFS_ACL_SUPPORT if NFSD_V2_ACL
+-	select NFSD_TCP if NFSD_V4
+-	select CRYPTO_MD5 if NFSD_V4
+-	select CRYPTO if NFSD_V4
+-	select FS_POSIX_ACL if NFSD_V4
+-	select PROC_FS if NFSD_V4
+-	select PROC_FS if SUNRPC_GSS
+-	help
+-	  If you want your Linux box to act as an NFS *server*, so that other
+-	  computers on your local network which support NFS can access certain
+-	  directories on your box transparently, you have two options: you can
+-	  use the self-contained user space program nfsd, in which case you
+-	  should say N here, or you can say Y and use the kernel based NFS
+-	  server. The advantage of the kernel based solution is that it is
+-	  faster.
+-
+-	  In either case, you will need support software; the respective
+-	  locations are given in the file <file:Documentation/Changes> in the
+-	  NFS section.
+-
+-	  If you say Y here, you will get support for version 2 of the NFS
+-	  protocol (NFSv2). If you also want NFSv3, say Y to the next question
+-	  as well.
+-
+-	  Please read the NFS-HOWTO, available from
+-	  <http://www.tldp.org/docs.html#howto>.
+-
+-	  To compile the NFS server support as a module, choose M here: the
+-	  module will be called nfsd.  If unsure, say N.
++	help
++	  Choose Y here if you want to allow other computers to access
++	  files residing on this system using Sun's Network File System
++	  protocol.  To compile the NFS server support as a module,
++	  choose M here: the module will be called nfsd.
++
++	  You may choose to use a user-space NFS server instead, in which
++	  case you can choose N here.
++
++	  To export local file systems using NFS, you also need to install
++	  user space programs which can be found in the Linux nfs-utils
++	  package, available from http://linux-nfs.org/.  More detail about
++	  the Linux NFS server implementation is available via the
++	  exports(5) man page.
++
++	  Below you can choose which versions of the NFS protocol are
++	  available to clients mounting the NFS server on this system.
++	  Support for NFS version 2 (RFC 1094) is always available when
++	  CONFIG_NFSD is selected.
++
++	  If unsure, say N.
+ 
+ config NFSD_V2_ACL
+ 	bool
+ 	depends on NFSD
+ 
+ config NFSD_V3
+-	bool "Provide NFSv3 server support"
++	bool "NFS server support for NFS version 3"
+ 	depends on NFSD
+ 	help
+-	  If you would like to include the NFSv3 server as well as the NFSv2
+-	  server, say Y here.  If unsure, say Y.
++	  This option enables support in your system's NFS server for
++	  version 3 of the NFS protocol (RFC 1813).
++
++	  If unsure, say Y.
+ 
+ config NFSD_V3_ACL
+-	bool "Provide server support for the NFSv3 ACL protocol extension"
++	bool "NFS server support for the NFSv3 ACL protocol extension"
+ 	depends on NFSD_V3
++	select NFSD_V2_ACL
+ 	help
+-	  Implement the NFSv3 ACL protocol extension for manipulating POSIX
+-	  Access Control Lists on exported file systems. NFS clients should
+-	  be compiled with the NFSv3 ACL protocol extension; see the
+-	  CONFIG_NFS_V3_ACL option.  If unsure, say N.
++	  Solaris NFS servers support an auxiliary NFSv3 ACL protocol that
++	  never became an official part of the NFS version 3 protocol.
++	  This protocol extension allows applications on NFS clients to
++	  manipulate POSIX Access Control Lists on files residing on NFS
++	  servers.  NFS servers enforce POSIX ACLs on local files whether
++	  this protocol is available or not.
++
++	  This option enables support in your system's NFS server for the
++	  NFSv3 ACL protocol extension allowing NFS clients to manipulate
++	  POSIX ACLs on files exported by your system's NFS server.  NFS
++	  clients which support the Solaris NFSv3 ACL protocol can then
++	  access and modify ACLs on your NFS server.
++
++	  To store ACLs on your NFS server, you also need to enable ACL-
++	  related CONFIG options for your local file systems of choice.
++
++	  If unsure, say N.
+ 
+ config NFSD_V4
+-	bool "Provide NFSv4 server support (EXPERIMENTAL)"
+-	depends on NFSD && NFSD_V3 && EXPERIMENTAL
++	bool "NFS server support for NFS version 4 (EXPERIMENTAL)"
++	depends on NFSD && PROC_FS && EXPERIMENTAL
++	select NFSD_V3
++	select FS_POSIX_ACL
+ 	select RPCSEC_GSS_KRB5
+ 	help
+-	  If you would like to include the NFSv4 server as well as the NFSv2
+-	  and NFSv3 servers, say Y here.  This feature is experimental, and
+-	  should only be used if you are interested in helping to test NFSv4.
+-	  If unsure, say N.
++	  This option enables support in your system's NFS server for
++	  version 4 of the NFS protocol (RFC 3530).
+ 
+-config NFSD_TCP
+-	bool "Provide NFS server over TCP support"
+-	depends on NFSD
+-	default y
+-	help
+-	  If you want your NFS server to support TCP connections, say Y here.
+-	  TCP connections usually perform better than the default UDP when
+-	  the network is lossy or congested.  If unsure, say Y.
++	  To export files using NFSv4, you need to install additional user
++	  space programs which can be found in the Linux nfs-utils package,
++	  available from http://linux-nfs.org/.
++
++	  If unsure, say N.
+ 
+ config ROOT_NFS
+ 	bool "Root file system on NFS"
+@@ -1781,15 +1789,33 @@ config SUNRPC_XPRT_RDMA
+ 	tristate
+ 	depends on SUNRPC && INFINIBAND && EXPERIMENTAL
+ 	default SUNRPC && INFINIBAND
++	help
++	  This option enables an RPC client transport capability that
++	  allows the NFS client to mount servers via an RDMA-enabled
++	  transport.
++
++	  To compile RPC client RDMA transport support as a module,
++	  choose M here: the module will be called xprtrdma.
++
++	  If unsure, say N.
+ 
+ config SUNRPC_BIND34
+ 	bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)"
+ 	depends on SUNRPC && EXPERIMENTAL
++	default n
+ 	help
+-	  Provides kernel support for querying rpcbind servers via versions 3
+-	  and 4 of the rpcbind protocol.  The kernel automatically falls back
+-	  to version 2 if a remote rpcbind service does not support versions
+-	  3 or 4.
++	  RPC requests over IPv6 networks require support for larger
++	  addresses when performing an RPC bind.  Sun added support for
++	  IPv6 addressing by creating two new versions of the rpcbind
++	  protocol (RFC 1833).
++
++	  This option enables support in the kernel RPC client for
++	  querying rpcbind servers via versions 3 and 4 of the rpcbind
++	  protocol.  The kernel automatically falls back to version 2
++	  if a remote rpcbind service does not support versions 3 or 4.
++	  By themselves, these new versions do not provide support for
++	  RPC over IPv6, but the new protocol versions are necessary to
++	  support it.
+ 
+ 	  If unsure, say N to get traditional behavior (version 2 rpcbind
+ 	  requests only).
+@@ -1803,12 +1829,13 @@ config RPCSEC_GSS_KRB5
+ 	select CRYPTO_DES
+ 	select CRYPTO_CBC
+ 	help
+-	  Provides for secure RPC calls by means of a gss-api
+-	  mechanism based on Kerberos V5. This is required for
+-	  NFSv4.
++	  Choose Y here to enable Secure RPC using the Kerberos version 5
++	  GSS-API mechanism (RFC 1964).
+ 
+-	  Note: Requires an auxiliary userspace daemon which may be found on
+-		http://www.citi.umich.edu/projects/nfsv4/
++	  Secure RPC calls with Kerberos require an auxiliary user-space
++	  daemon which may be found in the Linux nfs-utils package
++	  available from http://linux-nfs.org/.  In addition, user-space
++	  Kerberos support should be installed.
+ 
+ 	  If unsure, say N.
+ 
+@@ -1822,11 +1849,12 @@ config RPCSEC_GSS_SPKM3
+ 	select CRYPTO_CAST5
+ 	select CRYPTO_CBC
+ 	help
+-	  Provides for secure RPC calls by means of a gss-api
+-	  mechanism based on the SPKM3 public-key mechanism.
++	  Choose Y here to enable Secure RPC using the SPKM3 public key
++	  GSS-API mechansim (RFC 2025).
+ 
+-	  Note: Requires an auxiliary userspace daemon which may be found on
+-	  	http://www.citi.umich.edu/projects/nfsv4/
++	  Secure RPC calls with SPKM3 require an auxiliary userspace
++	  daemon which may be found in the Linux nfs-utils package
++	  available from http://linux-nfs.org/.
+ 
+ 	  If unsure, say N.
+ 
+diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
+index b5c3b61..853845a 100644
+--- a/fs/Kconfig.binfmt
++++ b/fs/Kconfig.binfmt
+@@ -62,7 +62,7 @@ config BINFMT_SHARED_FLAT
+ config BINFMT_AOUT
+ 	tristate "Kernel support for a.out and ECOFF binaries"
+ 	depends on ARCH_SUPPORTS_AOUT && \
+-		(X86_32 || ALPHA || ARM || M68K || SPARC32)
++		(X86_32 || ALPHA || ARM || M68K)
+ 	---help---
+ 	  A.out (Assembler.OUTput) is a set of formats for libraries and
+ 	  executables used in the earliest versions of UNIX.  Linux used
+diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+index 5e1a4fb..9924581 100644
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -543,7 +543,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ 	unsigned long interp_load_addr = 0;
+ 	unsigned long start_code, end_code, start_data, end_data;
+ 	unsigned long reloc_func_desc = 0;
+-	struct files_struct *files;
+ 	int executable_stack = EXSTACK_DEFAULT;
+ 	unsigned long def_flags = 0;
+ 	struct {
+@@ -593,20 +592,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ 		goto out_free_ph;
+ 	}
+ 
+-	files = current->files;	/* Refcounted so ok */
+-	retval = unshare_files();
+-	if (retval < 0)
+-		goto out_free_ph;
+-	if (files == current->files) {
+-		put_files_struct(files);
+-		files = NULL;
+-	}
+-
+-	/* exec will make our files private anyway, but for the a.out
+-	   loader stuff we need to do it earlier */
+ 	retval = get_unused_fd();
+ 	if (retval < 0)
+-		goto out_free_fh;
++		goto out_free_ph;
+ 	get_file(bprm->file);
+ 	fd_install(elf_exec_fileno = retval, bprm->file);
+ 
+@@ -728,12 +716,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ 	if (retval)
+ 		goto out_free_dentry;
+ 
+-	/* Discard our unneeded old files struct */
+-	if (files) {
+-		put_files_struct(files);
+-		files = NULL;
+-	}
+-
+ 	/* OK, This is the point of no return */
+ 	current->flags &= ~PF_FORKNOEXEC;
+ 	current->mm->def_flags = def_flags;
+@@ -1016,9 +998,6 @@ out_free_interp:
+ 	kfree(elf_interpreter);
+ out_free_file:
+ 	sys_close(elf_exec_fileno);
+-out_free_fh:
+-	if (files)
+-		reset_files_struct(current, files);
+ out_free_ph:
+ 	kfree(elf_phdata);
+ 	goto out;
+diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
+index b53c7e5..dbf0ac0 100644
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -110,7 +110,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ 	char *iname_addr = iname;
+ 	int retval;
+ 	int fd_binary = -1;
+-	struct files_struct *files = NULL;
+ 
+ 	retval = -ENOEXEC;
+ 	if (!enabled)
+@@ -133,21 +132,13 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ 
+ 	if (fmt->flags & MISC_FMT_OPEN_BINARY) {
+ 
+-		files = current->files;
+-		retval = unshare_files();
+-		if (retval < 0)
+-			goto _ret;
+-		if (files == current->files) {
+-			put_files_struct(files);
+-			files = NULL;
+-		}
+ 		/* if the binary should be opened on behalf of the
+ 		 * interpreter than keep it open and assign descriptor
+ 		 * to it */
+  		fd_binary = get_unused_fd();
+  		if (fd_binary < 0) {
+  			retval = fd_binary;
+- 			goto _unshare;
++ 			goto _ret;
+  		}
+  		fd_install(fd_binary, bprm->file);
+ 
+@@ -205,10 +196,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ 	if (retval < 0)
+ 		goto _error;
+ 
+-	if (files) {
+-		put_files_struct(files);
+-		files = NULL;
+-	}
+ _ret:
+ 	return retval;
+ _error:
+@@ -216,9 +203,6 @@ _error:
+ 		sys_close(fd_binary);
+ 	bprm->interp_flags = 0;
+ 	bprm->interp_data = 0;
+-_unshare:
+-	if (files)
+-		reset_files_struct(current, files);
+ 	goto _ret;
+ }
+ 
+diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
+index 14c6352..fdc36bf 100644
+--- a/fs/binfmt_som.c
++++ b/fs/binfmt_som.c
+@@ -194,7 +194,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+ 	unsigned long som_entry;
+ 	struct som_hdr *som_ex;
+ 	struct som_exec_auxhdr *hpuxhdr;
+-	struct files_struct *files;
+ 
+ 	/* Get the exec-header */
+ 	som_ex = (struct som_hdr *) bprm->buf;
+@@ -221,15 +220,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+ 		goto out_free;
+ 	}
+ 
+-	files = current->files; /* Refcounted so ok */
+-	retval = unshare_files();
+-	if (retval < 0)
+-		goto out_free;
+-	if (files == current->files) {
+-		put_files_struct(files);
+-		files = NULL;
+-	}
+-
+ 	retval = get_unused_fd();
+ 	if (retval < 0)
+ 		goto out_free;
+diff --git a/fs/bio.c b/fs/bio.c
+index 553b5b7..6e0b6f6 100644
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -444,22 +444,27 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
+ 
+ struct bio_map_data {
+ 	struct bio_vec *iovecs;
+-	void __user *userptr;
++	int nr_sgvecs;
++	struct sg_iovec *sgvecs;
+ };
+ 
+-static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio)
++static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio,
++			     struct sg_iovec *iov, int iov_count)
+ {
+ 	memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt);
++	memcpy(bmd->sgvecs, iov, sizeof(struct sg_iovec) * iov_count);
++	bmd->nr_sgvecs = iov_count;
+ 	bio->bi_private = bmd;
+ }
+ 
+ static void bio_free_map_data(struct bio_map_data *bmd)
+ {
+ 	kfree(bmd->iovecs);
++	kfree(bmd->sgvecs);
+ 	kfree(bmd);
+ }
+ 
+-static struct bio_map_data *bio_alloc_map_data(int nr_segs)
++static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count)
+ {
+ 	struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL);
+ 
+@@ -467,13 +472,71 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs)
+ 		return NULL;
+ 
+ 	bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL);
+-	if (bmd->iovecs)
++	if (!bmd->iovecs) {
++		kfree(bmd);
++		return NULL;
++	}
++
++	bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, GFP_KERNEL);
++	if (bmd->sgvecs)
+ 		return bmd;
+ 
++	kfree(bmd->iovecs);
+ 	kfree(bmd);
+ 	return NULL;
+ }
+ 
++static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count,
++			  int uncopy)
++{
++	int ret = 0, i;
++	struct bio_vec *bvec;
++	int iov_idx = 0;
++	unsigned int iov_off = 0;
++	int read = bio_data_dir(bio) == READ;
++
++	__bio_for_each_segment(bvec, bio, i, 0) {
++		char *bv_addr = page_address(bvec->bv_page);
++		unsigned int bv_len = bvec->bv_len;
++
++		while (bv_len && iov_idx < iov_count) {
++			unsigned int bytes;
++			char *iov_addr;
++
++			bytes = min_t(unsigned int,
++				      iov[iov_idx].iov_len - iov_off, bv_len);
++			iov_addr = iov[iov_idx].iov_base + iov_off;
++
++			if (!ret) {
++				if (!read && !uncopy)
++					ret = copy_from_user(bv_addr, iov_addr,
++							     bytes);
++				if (read && uncopy)
++					ret = copy_to_user(iov_addr, bv_addr,
++							   bytes);
++
++				if (ret)
++					ret = -EFAULT;
++			}
++
++			bv_len -= bytes;
++			bv_addr += bytes;
++			iov_addr += bytes;
++			iov_off += bytes;
++
++			if (iov[iov_idx].iov_len == iov_off) {
++				iov_idx++;
++				iov_off = 0;
++			}
++		}
++
++		if (uncopy)
++			__free_page(bvec->bv_page);
++	}
++
++	return ret;
++}
++
+ /**
+  *	bio_uncopy_user	-	finish previously mapped bio
+  *	@bio: bio being terminated
+@@ -484,55 +547,56 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs)
+ int bio_uncopy_user(struct bio *bio)
+ {
+ 	struct bio_map_data *bmd = bio->bi_private;
+-	const int read = bio_data_dir(bio) == READ;
+-	struct bio_vec *bvec;
+-	int i, ret = 0;
++	int ret;
+ 
+-	__bio_for_each_segment(bvec, bio, i, 0) {
+-		char *addr = page_address(bvec->bv_page);
+-		unsigned int len = bmd->iovecs[i].bv_len;
++	ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs, 1);
+ 
+-		if (read && !ret && copy_to_user(bmd->userptr, addr, len))
+-			ret = -EFAULT;
+-
+-		__free_page(bvec->bv_page);
+-		bmd->userptr += len;
+-	}
+ 	bio_free_map_data(bmd);
+ 	bio_put(bio);
+ 	return ret;
+ }
+ 
+ /**
+- *	bio_copy_user	-	copy user data to bio
++ *	bio_copy_user_iov	-	copy user data to bio
+  *	@q: destination block queue
+- *	@uaddr: start of user address
+- *	@len: length in bytes
++ *	@iov:	the iovec.
++ *	@iov_count: number of elements in the iovec
+  *	@write_to_vm: bool indicating writing to pages or not
+  *
+  *	Prepares and returns a bio for indirect user io, bouncing data
+  *	to/from kernel pages as necessary. Must be paired with
+  *	call bio_uncopy_user() on io completion.
+  */
+-struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr,
+-			  unsigned int len, int write_to_vm)
++struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov,
++			      int iov_count, int write_to_vm)
+ {
+-	unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+-	unsigned long start = uaddr >> PAGE_SHIFT;
+ 	struct bio_map_data *bmd;
+ 	struct bio_vec *bvec;
+ 	struct page *page;
+ 	struct bio *bio;
+ 	int i, ret;
++	int nr_pages = 0;
++	unsigned int len = 0;
+ 
+-	bmd = bio_alloc_map_data(end - start);
++	for (i = 0; i < iov_count; i++) {
++		unsigned long uaddr;
++		unsigned long end;
++		unsigned long start;
++
++		uaddr = (unsigned long)iov[i].iov_base;
++		end = (uaddr + iov[i].iov_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++		start = uaddr >> PAGE_SHIFT;
++
++		nr_pages += end - start;
++		len += iov[i].iov_len;
++	}
++
++	bmd = bio_alloc_map_data(nr_pages, iov_count);
+ 	if (!bmd)
+ 		return ERR_PTR(-ENOMEM);
+ 
+-	bmd->userptr = (void __user *) uaddr;
+-
+ 	ret = -ENOMEM;
+-	bio = bio_alloc(GFP_KERNEL, end - start);
++	bio = bio_alloc(GFP_KERNEL, nr_pages);
+ 	if (!bio)
+ 		goto out_bmd;
+ 
+@@ -564,22 +628,12 @@ struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr,
+ 	 * success
+ 	 */
+ 	if (!write_to_vm) {
+-		char __user *p = (char __user *) uaddr;
+-
+-		/*
+-		 * for a write, copy in data to kernel pages
+-		 */
+-		ret = -EFAULT;
+-		bio_for_each_segment(bvec, bio, i) {
+-			char *addr = page_address(bvec->bv_page);
+-
+-			if (copy_from_user(addr, p, bvec->bv_len))
+-				goto cleanup;
+-			p += bvec->bv_len;
+-		}
++		ret = __bio_copy_iov(bio, iov, iov_count, 0);
++		if (ret)
++			goto cleanup;
+ 	}
+ 
+-	bio_set_map_data(bmd, bio);
++	bio_set_map_data(bmd, bio, iov, iov_count);
+ 	return bio;
+ cleanup:
+ 	bio_for_each_segment(bvec, bio, i)
+@@ -591,6 +645,28 @@ out_bmd:
+ 	return ERR_PTR(ret);
+ }
+ 
++/**
++ *	bio_copy_user	-	copy user data to bio
++ *	@q: destination block queue
++ *	@uaddr: start of user address
++ *	@len: length in bytes
++ *	@write_to_vm: bool indicating writing to pages or not
++ *
++ *	Prepares and returns a bio for indirect user io, bouncing data
++ *	to/from kernel pages as necessary. Must be paired with
++ *	call bio_uncopy_user() on io completion.
++ */
++struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr,
++			  unsigned int len, int write_to_vm)
++{
++	struct sg_iovec iov;
++
++	iov.iov_base = (void __user *)uaddr;
++	iov.iov_len = len;
++
++	return bio_copy_user_iov(q, &iov, 1, write_to_vm);
++}
++
+ static struct bio *__bio_map_user_iov(struct request_queue *q,
+ 				      struct block_device *bdev,
+ 				      struct sg_iovec *iov, int iov_count,
+diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
+index dbd9146..05c9da6 100644
+--- a/fs/cifs/CHANGES
++++ b/fs/cifs/CHANGES
+@@ -8,7 +8,8 @@ of second share to disconnected server session (autoreconnect on this).
+ Add ability to modify cifs acls for handling chmod (when mounted with
+ cifsacl flag). Fix prefixpath path separator so we can handle mounts
+ with prefixpaths longer than one directory (one path component) when
+-mounted to Windows servers.
++mounted to Windows servers.  Fix slow file open when cifsacl
++enabled.
+ 
+ Version 1.51
+ ------------
+diff --git a/fs/cifs/README b/fs/cifs/README
+index 5030622..621aa1a 100644
+--- a/fs/cifs/README
++++ b/fs/cifs/README
+@@ -3,7 +3,14 @@ features such as hierarchical dfs like namespace, hardlinks, locking and more.
+ It was designed to comply with the SNIA CIFS Technical Reference (which 
+ supersedes the 1992 X/Open SMB Standard) as well as to perform best practice 
+ practical interoperability with Windows 2000, Windows XP, Samba and equivalent 
+-servers.  
++servers.  This code was developed in participation with the Protocol Freedom
++Information Foundation.
++
++Please see
++  http://protocolfreedom.org/ and
++  http://samba.org/samba/PFIF/
++for more details.
++
+ 
+ For questions or bug reports please contact:
+     sfrench at samba.org (sfrench at us.ibm.com) 
+diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
+index 56c9240..95024c0 100644
+--- a/fs/cifs/cifs_dfs_ref.c
++++ b/fs/cifs/cifs_dfs_ref.c
+@@ -23,16 +23,28 @@
+ #include "dns_resolve.h"
+ #include "cifs_debug.h"
+ 
+-LIST_HEAD(cifs_dfs_automount_list);
++static LIST_HEAD(cifs_dfs_automount_list);
+ 
+-/*
+- * DFS functions
+-*/
++static void cifs_dfs_expire_automounts(struct work_struct *work);
++static DECLARE_DELAYED_WORK(cifs_dfs_automount_task,
++			    cifs_dfs_expire_automounts);
++static int cifs_dfs_mountpoint_expiry_timeout = 500 * HZ;
++
++static void cifs_dfs_expire_automounts(struct work_struct *work)
++{
++	struct list_head *list = &cifs_dfs_automount_list;
++
++	mark_mounts_for_expiry(list);
++	if (!list_empty(list))
++		schedule_delayed_work(&cifs_dfs_automount_task,
++				      cifs_dfs_mountpoint_expiry_timeout);
++}
+ 
+-void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
++void cifs_dfs_release_automount_timer(void)
+ {
+-	mark_mounts_for_expiry(&cifs_dfs_automount_list);
+-	mark_mounts_for_expiry(&cifs_dfs_automount_list);
++	BUG_ON(!list_empty(&cifs_dfs_automount_list));
++	cancel_delayed_work(&cifs_dfs_automount_task);
++	flush_scheduled_work();
+ }
+ 
+ /**
+@@ -261,10 +273,11 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
+ 	err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist);
+ 	switch (err) {
+ 	case 0:
+-		dput(nd->path.dentry);
+-		mntput(nd->path.mnt);
++		path_put(&nd->path);
+ 		nd->path.mnt = newmnt;
+ 		nd->path.dentry = dget(newmnt->mnt_root);
++		schedule_delayed_work(&cifs_dfs_automount_task,
++				      cifs_dfs_mountpoint_expiry_timeout);
+ 		break;
+ 	case -EBUSY:
+ 		/* someone else made a mount here whilst we were busy */
+diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
+index 1cb5b0a..e99d4fa 100644
+--- a/fs/cifs/cifsacl.c
++++ b/fs/cifs/cifsacl.c
+@@ -516,7 +516,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
+ 
+ /* Convert permission bits from mode to equivalent CIFS ACL */
+ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
+-				int acl_len, struct inode *inode, __u64 nmode)
++				struct inode *inode, __u64 nmode)
+ {
+ 	int rc = 0;
+ 	__u32 dacloffset;
+@@ -692,14 +692,14 @@ void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
+ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
+ {
+ 	int rc = 0;
+-	__u32 acllen = 0;
++	__u32 secdesclen = 0;
+ 	struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
+ 	struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
+ 
+ 	cFYI(DBG2, ("set ACL from mode for %s", path));
+ 
+ 	/* Get the security descriptor */
+-	pntsd = get_cifs_acl(&acllen, inode, path, NULL);
++	pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
+ 
+ 	/* Add three ACEs for owner, group, everyone getting rid of
+ 	   other ACEs as chmod disables ACEs and set the security descriptor */
+@@ -709,20 +709,22 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
+ 		   set security descriptor request security descriptor
+ 		   parameters, and secuirty descriptor itself */
+ 
+-		pnntsd = kmalloc(acllen, GFP_KERNEL);
++		secdesclen = secdesclen < DEFSECDESCLEN ?
++					DEFSECDESCLEN : secdesclen;
++		pnntsd = kmalloc(secdesclen, GFP_KERNEL);
+ 		if (!pnntsd) {
+ 			cERROR(1, ("Unable to allocate security descriptor"));
+ 			kfree(pntsd);
+ 			return (-ENOMEM);
+ 		}
+ 
+-		rc = build_sec_desc(pntsd, pnntsd, acllen, inode, nmode);
++		rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
+ 
+ 		cFYI(DBG2, ("build_sec_desc rc: %d", rc));
+ 
+ 		if (!rc) {
+ 			/* Set the security descriptor */
+-			rc = set_cifs_acl(pnntsd, acllen, inode, path);
++			rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
+ 			cFYI(DBG2, ("set_cifs_acl rc: %d", rc));
+ 		}
+ 
+diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
+index 93a7c34..6c8096c 100644
+--- a/fs/cifs/cifsacl.h
++++ b/fs/cifs/cifsacl.h
+@@ -27,6 +27,7 @@
+ #define NUM_SUBAUTHS 5 /* number of sub authority fields */
+ #define NUM_WK_SIDS 7 /* number of well known sids */
+ #define SIDNAMELENGTH 20 /* long enough for the ones we care about */
++#define DEFSECDESCLEN 192 /* sec desc len contaiting a dacl with three aces */
+ 
+ #define READ_BIT        0x4
+ #define WRITE_BIT       0x2
+diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
+index a04b17e..39c2cbd 100644
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -466,16 +466,11 @@ static struct quotactl_ops cifs_quotactl_ops = {
+ };
+ #endif
+ 
+-static void cifs_umount_begin(struct vfsmount *vfsmnt, int flags)
++static void cifs_umount_begin(struct super_block *sb)
+ {
+-	struct cifs_sb_info *cifs_sb;
++	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ 	struct cifsTconInfo *tcon;
+ 
+-	dfs_shrink_umount_helper(vfsmnt);
+-
+-	if (!(flags & MNT_FORCE))
+-		return;
+-	cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
+ 	if (cifs_sb == NULL)
+ 		return;
+ 
+@@ -1100,6 +1095,7 @@ exit_cifs(void)
+ 	cFYI(DBG2, ("exit_cifs"));
+ 	cifs_proc_clean();
+ #ifdef CONFIG_CIFS_DFS_UPCALL
++	cifs_dfs_release_automount_timer();
+ 	unregister_key_type(&key_type_dns_resolver);
+ #endif
+ #ifdef CONFIG_CIFS_UPCALL
+diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
+index 6897830..e1dd9f3 100644
+--- a/fs/cifs/cifsfs.h
++++ b/fs/cifs/cifsfs.h
+@@ -62,11 +62,9 @@ extern int cifs_setattr(struct dentry *, struct iattr *);
+ 
+ extern const struct inode_operations cifs_file_inode_ops;
+ extern const struct inode_operations cifs_symlink_inode_ops;
+-extern struct list_head cifs_dfs_automount_list;
+ extern struct inode_operations cifs_dfs_referral_inode_operations;
+ 
+ 
+-
+ /* Functions related to files and directories */
+ extern const struct file_operations cifs_file_ops;
+ extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
+diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
+index 47f7950..9f49c2f 100644
+--- a/fs/cifs/cifspdu.h
++++ b/fs/cifs/cifspdu.h
+@@ -1,7 +1,7 @@
+ /*
+  *   fs/cifs/cifspdu.h
+  *
+- *   Copyright (c) International Business Machines  Corp., 2002,2007
++ *   Copyright (c) International Business Machines  Corp., 2002,2008
+  *   Author(s): Steve French (sfrench at us.ibm.com)
+  *
+  *   This library is free software; you can redistribute it and/or modify
+@@ -163,7 +163,10 @@
+ 						   path names in response */
+ #define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
+ #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
++#define SMBFLG2_COMPRESSED (8)
++#define SMBFLG2_SECURITY_SIGNATURE_REQUIRED (0x10)
+ #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
++#define SMBFLG2_REPARSE_PATH (0x400)
+ #define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
+ #define SMBFLG2_DFS cpu_to_le16(0x1000)
+ #define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
+@@ -305,7 +308,7 @@
+ #define FILE_SHARE_DELETE 0x00000004
+ #define FILE_SHARE_ALL    0x00000007
+ 
+-/* CreateDisposition flags */
++/* CreateDisposition flags, similar to CreateAction as well */
+ #define FILE_SUPERSEDE    0x00000000
+ #define FILE_OPEN         0x00000001
+ #define FILE_CREATE       0x00000002
+@@ -317,15 +320,25 @@
+ #define CREATE_NOT_FILE		0x00000001	/* if set must not be file */
+ #define CREATE_WRITE_THROUGH	0x00000002
+ #define CREATE_SEQUENTIAL       0x00000004
+-#define CREATE_SYNC_ALERT       0x00000010
+-#define CREATE_ASYNC_ALERT      0x00000020
++#define CREATE_NO_BUFFER        0x00000008      /* should not buffer on srv */
++#define CREATE_SYNC_ALERT       0x00000010	/* MBZ */
++#define CREATE_ASYNC_ALERT      0x00000020	/* MBZ */
+ #define CREATE_NOT_DIR		0x00000040    /* if set must not be directory */
++#define CREATE_TREE_CONNECTION  0x00000080	/* should be zero */
++#define CREATE_COMPLETE_IF_OPLK 0x00000100	/* should be zero */
+ #define CREATE_NO_EA_KNOWLEDGE  0x00000200
+-#define CREATE_EIGHT_DOT_THREE  0x00000400
++#define CREATE_EIGHT_DOT_THREE  0x00000400	/* doc says this is obsolete
++						 open for recovery flag - should
++						 be zero */
+ #define CREATE_RANDOM_ACCESS	0x00000800
+ #define CREATE_DELETE_ON_CLOSE	0x00001000
+ #define CREATE_OPEN_BY_ID       0x00002000
++#define CREATE_OPEN_BACKUP_INTN 0x00004000
++#define CREATE_NO_COMPRESSION   0x00008000
++#define CREATE_RESERVE_OPFILTER 0x00100000	/* should be zero */
+ #define OPEN_REPARSE_POINT	0x00200000
++#define OPEN_NO_RECALL          0x00400000
++#define OPEN_FREE_SPACE_QUERY   0x00800000	/* should be zero */
+ #define CREATE_OPTIONS_MASK     0x007FFFFF
+ #define CREATE_OPTION_SPECIAL   0x20000000   /* system. NB not sent over wire */
+ 
+@@ -470,7 +483,7 @@ typedef struct lanman_neg_rsp {
+ 
+ typedef struct negotiate_rsp {
+ 	struct smb_hdr hdr;	/* wct = 17 */
+-	__le16 DialectIndex;
++	__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
+ 	__u8 SecurityMode;
+ 	__le16 MaxMpxCount;
+ 	__le16 MaxNumberVcs;
+@@ -516,10 +529,11 @@ typedef struct negotiate_rsp {
+ #define CAP_INFOLEVEL_PASSTHRU 0x00002000
+ #define CAP_LARGE_READ_X       0x00004000
+ #define CAP_LARGE_WRITE_X      0x00008000
++#define CAP_LWIO               0x00010000 /* support fctl_srv_req_resume_key */
+ #define CAP_UNIX               0x00800000
+-#define CAP_RESERVED           0x02000000
+-#define CAP_BULK_TRANSFER      0x20000000
+-#define CAP_COMPRESSED_DATA    0x40000000
++#define CAP_COMPRESSED_DATA    0x02000000
++#define CAP_DYNAMIC_REAUTH     0x20000000
++#define CAP_PERSISTENT_HANDLES 0x40000000
+ #define CAP_EXTENDED_SECURITY  0x80000000
+ 
+ typedef union smb_com_session_setup_andx {
+@@ -668,9 +682,7 @@ typedef struct smb_com_tconx_req {
+ } __attribute__((packed)) TCONX_REQ;
+ 
+ typedef struct smb_com_tconx_rsp {
+-	struct smb_hdr hdr;	/* wct = 3 note that Win2000 has sent wct = 7
+-				 in some cases on responses. Four unspecified
+-				 words followed OptionalSupport */
++	struct smb_hdr hdr;	/* wct = 3 , not extended response */
+ 	__u8 AndXCommand;
+ 	__u8 AndXReserved;
+ 	__le16 AndXOffset;
+@@ -680,13 +692,48 @@ typedef struct smb_com_tconx_rsp {
+ 	/* STRING NativeFileSystem */
+ } __attribute__((packed)) TCONX_RSP;
+ 
++typedef struct smb_com_tconx_rsp_ext {
++	struct smb_hdr hdr;	/* wct = 7, extended response */
++	__u8 AndXCommand;
++	__u8 AndXReserved;
++	__le16 AndXOffset;
++	__le16 OptionalSupport;	/* see below */
++	__le32 MaximalShareAccessRights;
++	__le32 GuestMaximalShareAccessRights;
++	__u16 ByteCount;
++	unsigned char Service[1];	/* always ASCII, not Unicode */
++	/* STRING NativeFileSystem */
++} __attribute__((packed)) TCONX_RSP_EXT;
++
++
+ /* tree connect Flags */
+ #define DISCONNECT_TID          0x0001
++#define TCON_EXTENDED_SIGNATURES 0x0004
+ #define TCON_EXTENDED_SECINFO   0x0008
++
+ /* OptionalSupport bits */
+ #define SMB_SUPPORT_SEARCH_BITS 0x0001	/* "must have" directory search bits
+ 					 (exclusive searches supported) */
+ #define SMB_SHARE_IS_IN_DFS     0x0002
++#define SMB_CSC_MASK               0x000C
++/* CSC flags defined as follows */
++#define SMB_CSC_CACHE_MANUAL_REINT 0x0000
++#define SMB_CSC_CACHE_AUTO_REINT   0x0004
++#define SMB_CSC_CACHE_VDO          0x0008
++#define SMB_CSC_NO_CACHING         0x000C
++
++#define SMB_UNIQUE_FILE_NAME    0x0010
++#define SMB_EXTENDED_SIGNATURES 0x0020
++
++/* services
++ *
++ * A:       ie disk
++ * LPT1:    ie printer
++ * IPC      ie named pipe
++ * COMM
++ * ?????    ie any type
++ *
++ */
+ 
+ typedef struct smb_com_logoff_andx_req {
+ 	struct smb_hdr hdr;	/* wct = 2 */
+@@ -750,6 +797,17 @@ typedef struct smb_com_findclose_req {
+ #define COMM_DEV_TYPE		0x0004
+ #define UNKNOWN_TYPE		0xFFFF
+ 
++/* Device Type or File Status Flags */
++#define NO_EAS			0x0001
++#define NO_SUBSTREAMS		0x0002
++#define NO_REPARSETAG		0x0004
++/* following flags can apply if pipe */
++#define ICOUNT_MASK		0x00FF
++#define PIPE_READ_MODE		0x0100
++#define NAMED_PIPE_TYPE		0x0400
++#define PIPE_END_POINT		0x0800
++#define BLOCKING_NAMED_PIPE	0x8000
++
+ typedef struct smb_com_open_req {	/* also handles create */
+ 	struct smb_hdr hdr;	/* wct = 24 */
+ 	__u8 AndXCommand;
+@@ -758,7 +816,7 @@ typedef struct smb_com_open_req {	/* also handles create */
+ 	__u8 Reserved;		/* Must Be Zero */
+ 	__le16 NameLength;
+ 	__le32 OpenFlags;
+-	__le32 RootDirectoryFid;
++	__u32  RootDirectoryFid;
+ 	__le32 DesiredAccess;
+ 	__le64 AllocationSize;
+ 	__le32 FileAttributes;
+@@ -801,6 +859,32 @@ typedef struct smb_com_open_rsp {
+ 	__u16 ByteCount;	/* bct = 0 */
+ } __attribute__((packed)) OPEN_RSP;
+ 
++typedef struct smb_com_open_rsp_ext {
++	struct smb_hdr hdr;     /* wct = 42 but meaningless due to MS bug? */
++	__u8 AndXCommand;
++	__u8 AndXReserved;
++	__le16 AndXOffset;
++	__u8 OplockLevel;
++	__u16 Fid;
++	__le32 CreateAction;
++	__le64 CreationTime;
++	__le64 LastAccessTime;
++	__le64 LastWriteTime;
++	__le64 ChangeTime;
++	__le32 FileAttributes;
++	__le64 AllocationSize;
++	__le64 EndOfFile;
++	__le16 FileType;
++	__le16 DeviceState;
++	__u8 DirectoryFlag;
++	__u8 VolumeGUID[16];
++	__u64 FileId; /* note no endian conversion - is opaque UniqueID */
++	__le32 MaximalAccessRights;
++	__le32 GuestMaximalAccessRights;
++	__u16 ByteCount;        /* bct = 0 */
++} __attribute__((packed)) OPEN_RSP_EXT;
++
++
+ /* format of legacy open request */
+ typedef struct smb_com_openx_req {
+ 	struct smb_hdr	hdr;	/* wct = 15 */
+@@ -1703,6 +1787,12 @@ typedef struct smb_com_transaction2_fnext_rsp_parms {
+ #define SMB_QUERY_CIFS_UNIX_INFO    0x200
+ #define SMB_QUERY_POSIX_FS_INFO     0x201
+ #define SMB_QUERY_POSIX_WHO_AM_I    0x202
++#define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203
++#define SMB_QUERY_FS_PROXY          0x204 /* WAFS enabled. Returns structure
++					    FILE_SYSTEM__UNIX_INFO to tell
++					    whether new NTIOCTL available
++					    (0xACE) for WAN friendly SMB
++					    operations to be carried */
+ #define SMB_QUERY_LABEL_INFO        0x3ea
+ #define SMB_QUERY_FS_QUOTA_INFO     0x3ee
+ #define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
+@@ -1959,7 +2049,10 @@ typedef struct {
+ #define CIFS_UNIX_LARGE_READ_CAP        0x00000040 /* support reads >128K (up
+ 						      to 0xFFFF00 */
+ #define CIFS_UNIX_LARGE_WRITE_CAP       0x00000080
+-
++#define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x00000100 /* can do SPNEGO crypt */
++#define CIFS_UNIX_TRANPSORT_ENCRYPTION_MANDATORY_CAP  0x00000200 /* must do  */
++#define CIFS_UNIX_PROXY_CAP             0x00000400 /* Proxy cap: 0xACE ioctl and
++						      QFS PROXY call */
+ #ifdef CONFIG_CIFS_POSIX
+ /* Can not set pathnames cap yet until we send new posix create SMB since
+    otherwise server can treat such handles opened with older ntcreatex
+diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
+index 7e5e0e7..50f9fda 100644
+--- a/fs/cifs/cifsproto.h
++++ b/fs/cifs/cifsproto.h
+@@ -84,6 +84,7 @@ extern __u16 GetNextMid(struct TCP_Server_Info *server);
+ extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
+ 						 struct cifsTconInfo *);
+ extern void DeleteOplockQEntry(struct oplock_q_entry *);
++extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
+ extern struct timespec cifs_NTtimeToUnix(u64 utc_nanoseconds_since_1601);
+ extern u64 cifs_UnixTimeToNT(struct timespec);
+ extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
+@@ -103,13 +104,7 @@ extern int mode_to_acl(struct inode *inode, const char *path, __u64);
+ extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
+ 			const char *);
+ extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
+-#ifdef CONFIG_CIFS_DFS_UPCALL
+-extern void dfs_shrink_umount_helper(struct vfsmount *vfsmnt);
+-#else
+-static inline void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
+-{
+-}
+-#endif /* DFS_UPCALL */
++extern void cifs_dfs_release_automount_timer(void);
+ void cifs_proc_init(void);
+ void cifs_proc_clean(void);
+ 
+diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
+index 30bbe44..4728fa9 100644
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -165,17 +165,19 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+ 				rc = CIFSTCon(0, tcon->ses, tcon->treeName,
+ 					      tcon, nls_codepage);
+ 				up(&tcon->ses->sesSem);
+-				/* tell server which Unix caps we support */
+-				if (tcon->ses->capabilities & CAP_UNIX)
+-					reset_cifs_unix_caps(0 /* no xid */,
+-						tcon,
+-						NULL /* we do not know sb */,
+-						NULL /* no vol info */);
+ 				/* BB FIXME add code to check if wsize needs
+ 				   update due to negotiated smb buffer size
+ 				   shrinking */
+-				if (rc == 0)
++				if (rc == 0) {
+ 					atomic_inc(&tconInfoReconnectCount);
++					/* tell server Unix caps we support */
++					if (tcon->ses->capabilities & CAP_UNIX)
++						reset_cifs_unix_caps(
++						0 /* no xid */,
++						tcon,
++						NULL /* we do not know sb */,
++						NULL /* no vol info */);
++				}
+ 
+ 				cFYI(1, ("reconnect tcon rc = %d", rc));
+ 				/* Removed call to reopen open files here.
+@@ -310,17 +312,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+ 				rc = CIFSTCon(0, tcon->ses, tcon->treeName,
+ 					      tcon, nls_codepage);
+ 				up(&tcon->ses->sesSem);
+-				/* tell server which Unix caps we support */
+-				if (tcon->ses->capabilities & CAP_UNIX)
+-					reset_cifs_unix_caps(0 /* no xid */,
+-						tcon,
+-						NULL /* do not know sb */,
+-						NULL /* no vol info */);
+ 				/* BB FIXME add code to check if wsize needs
+ 				update due to negotiated smb buffer size
+ 				shrinking */
+-				if (rc == 0)
++				if (rc == 0) {
+ 					atomic_inc(&tconInfoReconnectCount);
++					/* tell server Unix caps we support */
++					if (tcon->ses->capabilities & CAP_UNIX)
++						reset_cifs_unix_caps(
++						0 /* no xid */,
++						tcon,
++						NULL /* do not know sb */,
++						NULL /* no vol info */);
++				}
+ 
+ 				cFYI(1, ("reconnect tcon rc = %d", rc));
+ 				/* Removed call to reopen open files here.
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index 8dbfa97..e171067 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -3527,6 +3527,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
+ 			FreeXid(xid);
+ 			return 0;
+ 		}
++		DeleteTconOplockQEntries(cifs_sb->tcon);
+ 		tconInfoFree(cifs_sb->tcon);
+ 		if ((ses) && (ses->server)) {
+ 			/* save off task so we do not refer to ses later */
+diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
+index bc673c8..e1031b9 100644
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -161,12 +161,14 @@ static void cifs_unix_info_to_inode(struct inode *inode,
+ 	spin_unlock(&inode->i_lock);
+ }
+ 
+-static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
+-					const char *search_path)
++static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb,
++						const char *search_path)
+ {
+ 	int tree_len;
+ 	int path_len;
++	int i;
+ 	char *tmp_path;
++	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+ 
+ 	if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS))
+ 		return search_path;
+@@ -180,6 +182,11 @@ static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
+ 		return search_path;
+ 
+ 	strncpy(tmp_path, pTcon->treeName, tree_len);
++	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
++		for (i = 0; i < tree_len; i++) {
++			if (tmp_path[i] == '\\')
++				tmp_path[i] = '/';
++		}
+ 	strncpy(tmp_path+tree_len, search_path, path_len);
+ 	tmp_path[tree_len+path_len] = 0;
+ 	return tmp_path;
+@@ -199,7 +206,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
+ 	pTcon = cifs_sb->tcon;
+ 	cFYI(1, ("Getting info on %s", search_path));
+ 
+-	full_path = cifs_get_search_path(pTcon, search_path);
++	full_path = cifs_get_search_path(cifs_sb, search_path);
+ 
+ try_again_CIFSSMBUnixQPathInfo:
+ 	/* could have done a find first instead but this returns more info */
+@@ -402,7 +409,7 @@ int cifs_get_inode_info(struct inode **pinode,
+ 			return -ENOMEM;
+ 		pfindData = (FILE_ALL_INFO *)buf;
+ 
+-		full_path = cifs_get_search_path(pTcon, search_path);
++		full_path = cifs_get_search_path(cifs_sb, search_path);
+ 
+ try_again_CIFSSMBQPathInfo:
+ 		/* could do find first instead but this returns more info */
+diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
+index 3612d6c..000ac50 100644
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -142,6 +142,24 @@ void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
+ 	kmem_cache_free(cifs_oplock_cachep, oplockEntry);
+ }
+ 
++
++void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
++{
++	struct oplock_q_entry *temp;
++
++	if (tcon == NULL)
++		return;
++
++	spin_lock(&GlobalMid_Lock);
++	list_for_each_entry(temp, &GlobalOplock_Q, qhead) {
++		if ((temp->tcon) && (temp->tcon == tcon)) {
++			list_del(&temp->qhead);
++			kmem_cache_free(cifs_oplock_cachep, temp);
++		}
++	}
++	spin_unlock(&GlobalMid_Lock);
++}
++
+ int
+ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
+ 	 unsigned int smb_buf_length, struct sockaddr *sin)
+diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
+index 350680f..0c3b618 100644
+--- a/fs/cramfs/inode.c
++++ b/fs/cramfs/inode.c
+@@ -23,7 +23,6 @@
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+ 
+ #include <asm/uaccess.h>
+ 
+diff --git a/fs/dcache.c b/fs/dcache.c
+index 4345577..3ee588d 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1746,12 +1746,21 @@ shouldnt_be_hashed:
+ 	goto shouldnt_be_hashed;
+ }
+ 
++static int prepend(char **buffer, int *buflen, const char *str,
++			  int namelen)
++{
++	*buflen -= namelen;
++	if (*buflen < 0)
++		return -ENAMETOOLONG;
++	*buffer -= namelen;
++	memcpy(*buffer, str, namelen);
++	return 0;
++}
++
+ /**
+  * d_path - return the path of a dentry
+- * @dentry: dentry to report
+- * @vfsmnt: vfsmnt to which the dentry belongs
+- * @root: root dentry
+- * @rootmnt: vfsmnt to which the root dentry belongs
++ * @path: the dentry/vfsmount to report
++ * @root: root vfsmnt/dentry (may be modified by this function)
+  * @buffer: buffer to return value in
+  * @buflen: buffer length
+  *
+@@ -1761,23 +1770,22 @@ shouldnt_be_hashed:
+  * Returns the buffer or an error code if the path was too long.
+  *
+  * "buflen" should be positive. Caller holds the dcache_lock.
++ *
++ * If path is not reachable from the supplied root, then the value of
++ * root is changed (without modifying refcounts).
+  */
+-static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+-		       struct path *root, char *buffer, int buflen)
++char *__d_path(const struct path *path, struct path *root,
++	       char *buffer, int buflen)
+ {
++	struct dentry *dentry = path->dentry;
++	struct vfsmount *vfsmnt = path->mnt;
+ 	char * end = buffer+buflen;
+ 	char * retval;
+-	int namelen;
+-
+-	*--end = '\0';
+-	buflen--;
+-	if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
+-		buflen -= 10;
+-		end -= 10;
+-		if (buflen < 0)
++
++	prepend(&end, &buflen, "\0", 1);
++	if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
++		(prepend(&end, &buflen, " (deleted)", 10) != 0))
+ 			goto Elong;
+-		memcpy(end, " (deleted)", 10);
+-	}
+ 
+ 	if (buflen < 1)
+ 		goto Elong;
+@@ -1804,13 +1812,10 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ 		}
+ 		parent = dentry->d_parent;
+ 		prefetch(parent);
+-		namelen = dentry->d_name.len;
+-		buflen -= namelen + 1;
+-		if (buflen < 0)
++		if ((prepend(&end, &buflen, dentry->d_name.name,
++				dentry->d_name.len) != 0) ||
++		    (prepend(&end, &buflen, "/", 1) != 0))
+ 			goto Elong;
+-		end -= namelen;
+-		memcpy(end, dentry->d_name.name, namelen);
+-		*--end = '/';
+ 		retval = end;
+ 		dentry = parent;
+ 	}
+@@ -1818,12 +1823,12 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ 	return retval;
+ 
+ global_root:
+-	namelen = dentry->d_name.len;
+-	buflen -= namelen;
+-	if (buflen < 0)
++	retval += 1;	/* hit the slash */
++	if (prepend(&retval, &buflen, dentry->d_name.name,
++		    dentry->d_name.len) != 0)
+ 		goto Elong;
+-	retval -= namelen-1;	/* hit the slash */
+-	memcpy(retval, dentry->d_name.name, namelen);
++	root->mnt = vfsmnt;
++	root->dentry = dentry;
+ 	return retval;
+ Elong:
+ 	return ERR_PTR(-ENAMETOOLONG);
+@@ -1846,6 +1851,7 @@ char *d_path(struct path *path, char *buf, int buflen)
+ {
+ 	char *res;
+ 	struct path root;
++	struct path tmp;
+ 
+ 	/*
+ 	 * We have various synthetic filesystems that never get mounted.  On
+@@ -1859,10 +1865,11 @@ char *d_path(struct path *path, char *buf, int buflen)
+ 
+ 	read_lock(&current->fs->lock);
+ 	root = current->fs->root;
+-	path_get(&current->fs->root);
++	path_get(&root);
+ 	read_unlock(&current->fs->lock);
+ 	spin_lock(&dcache_lock);
+-	res = __d_path(path->dentry, path->mnt, &root, buf, buflen);
++	tmp = root;
++	res = __d_path(path, &tmp, buf, buflen);
+ 	spin_unlock(&dcache_lock);
+ 	path_put(&root);
+ 	return res;
+@@ -1890,6 +1897,48 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
+ }
+ 
+ /*
++ * Write full pathname from the root of the filesystem into the buffer.
++ */
++char *dentry_path(struct dentry *dentry, char *buf, int buflen)
++{
++	char *end = buf + buflen;
++	char *retval;
++
++	spin_lock(&dcache_lock);
++	prepend(&end, &buflen, "\0", 1);
++	if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
++		(prepend(&end, &buflen, "//deleted", 9) != 0))
++			goto Elong;
++	if (buflen < 1)
++		goto Elong;
++	/* Get '/' right */
++	retval = end-1;
++	*retval = '/';
++
++	for (;;) {
++		struct dentry *parent;
++		if (IS_ROOT(dentry))
++			break;
++
++		parent = dentry->d_parent;
++		prefetch(parent);
++
++		if ((prepend(&end, &buflen, dentry->d_name.name,
++				dentry->d_name.len) != 0) ||
++		    (prepend(&end, &buflen, "/", 1) != 0))
++			goto Elong;
++
++		retval = end;
++		dentry = parent;
++	}
++	spin_unlock(&dcache_lock);
++	return retval;
++Elong:
++	spin_unlock(&dcache_lock);
++	return ERR_PTR(-ENAMETOOLONG);
++}
++
++/*
+  * NOTE! The user-level library version returns a
+  * character pointer. The kernel system call just
+  * returns the length of the buffer filled (which
+@@ -1918,9 +1967,9 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
+ 
+ 	read_lock(&current->fs->lock);
+ 	pwd = current->fs->pwd;
+-	path_get(&current->fs->pwd);
++	path_get(&pwd);
+ 	root = current->fs->root;
+-	path_get(&current->fs->root);
++	path_get(&root);
+ 	read_unlock(&current->fs->lock);
+ 
+ 	error = -ENOENT;
+@@ -1928,9 +1977,10 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
+ 	spin_lock(&dcache_lock);
+ 	if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
+ 		unsigned long len;
++		struct path tmp = root;
+ 		char * cwd;
+ 
+-		cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE);
++		cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
+ 		spin_unlock(&dcache_lock);
+ 
+ 		error = PTR_ERR(cwd);
+diff --git a/fs/dlm/Makefile b/fs/dlm/Makefile
+index d248e60..ca1c912 100644
+--- a/fs/dlm/Makefile
++++ b/fs/dlm/Makefile
+@@ -10,6 +10,7 @@ dlm-y :=			ast.o \
+ 				midcomms.o \
+ 				netlink.o \
+ 				lowcomms.o \
++				plock.o \
+ 				rcom.o \
+ 				recover.o \
+ 				recoverd.o \
+diff --git a/fs/dlm/config.c b/fs/dlm/config.c
+index c3ad1df..eac23bd 100644
+--- a/fs/dlm/config.c
++++ b/fs/dlm/config.c
+@@ -114,7 +114,7 @@ struct cluster_attribute {
+ };
+ 
+ static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field,
+-			   unsigned int *info_field, int check_zero,
++			   int *info_field, int check_zero,
+ 			   const char *buf, size_t len)
+ {
+ 	unsigned int x;
+@@ -284,6 +284,7 @@ struct node {
+ 	struct list_head list; /* space->members */
+ 	int nodeid;
+ 	int weight;
++	int new;
+ };
+ 
+ static struct configfs_group_operations clusters_ops = {
+@@ -565,6 +566,7 @@ static struct config_item *make_node(struct config_group *g, const char *name)
+ 	config_item_init_type_name(&nd->item, name, &node_type);
+ 	nd->nodeid = -1;
+ 	nd->weight = 1;  /* default weight of 1 if none is set */
++	nd->new = 1;     /* set to 0 once it's been read by dlm_nodeid_list() */
+ 
+ 	mutex_lock(&sp->members_lock);
+ 	list_add(&nd->list, &sp->members);
+@@ -805,12 +807,13 @@ static void put_comm(struct comm *cm)
+ }
+ 
+ /* caller must free mem */
+-int dlm_nodeid_list(char *lsname, int **ids_out)
++int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
++		    int **new_out, int *new_count_out)
+ {
+ 	struct space *sp;
+ 	struct node *nd;
+-	int i = 0, rv = 0;
+-	int *ids;
++	int i = 0, rv = 0, ids_count = 0, new_count = 0;
++	int *ids, *new;
+ 
+ 	sp = get_space(lsname);
+ 	if (!sp)
+@@ -818,23 +821,50 @@ int dlm_nodeid_list(char *lsname, int **ids_out)
+ 
+ 	mutex_lock(&sp->members_lock);
+ 	if (!sp->members_count) {
+-		rv = 0;
++		rv = -EINVAL;
++		printk(KERN_ERR "dlm: zero members_count\n");
+ 		goto out;
+ 	}
+ 
+-	ids = kcalloc(sp->members_count, sizeof(int), GFP_KERNEL);
++	ids_count = sp->members_count;
++
++	ids = kcalloc(ids_count, sizeof(int), GFP_KERNEL);
+ 	if (!ids) {
+ 		rv = -ENOMEM;
+ 		goto out;
+ 	}
+ 
+-	rv = sp->members_count;
+-	list_for_each_entry(nd, &sp->members, list)
++	list_for_each_entry(nd, &sp->members, list) {
+ 		ids[i++] = nd->nodeid;
++		if (nd->new)
++			new_count++;
++	}
++
++	if (ids_count != i)
++		printk(KERN_ERR "dlm: bad nodeid count %d %d\n", ids_count, i);
++
++	if (!new_count)
++		goto out_ids;
++
++	new = kcalloc(new_count, sizeof(int), GFP_KERNEL);
++	if (!new) {
++		kfree(ids);
++		rv = -ENOMEM;
++		goto out;
++	}
+ 
+-	if (rv != i)
+-		printk("bad nodeid count %d %d\n", rv, i);
++	i = 0;
++	list_for_each_entry(nd, &sp->members, list) {
++		if (nd->new) {
++			new[i++] = nd->nodeid;
++			nd->new = 0;
++		}
++	}
++	*new_count_out = new_count;
++	*new_out = new;
+ 
++ out_ids:
++	*ids_count_out = ids_count;
+ 	*ids_out = ids;
+  out:
+ 	mutex_unlock(&sp->members_lock);
+diff --git a/fs/dlm/config.h b/fs/dlm/config.h
+index a3170fe..4f1d6fc 100644
+--- a/fs/dlm/config.h
++++ b/fs/dlm/config.h
+@@ -35,7 +35,8 @@ extern struct dlm_config_info dlm_config;
+ int dlm_config_init(void);
+ void dlm_config_exit(void);
+ int dlm_node_weight(char *lsname, int nodeid);
+-int dlm_nodeid_list(char *lsname, int **ids_out);
++int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
++		    int **new_out, int *new_count_out);
+ int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
+ int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
+ int dlm_our_nodeid(void);
+diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
+index d30ea8b..5a7ac33 100644
+--- a/fs/dlm/dlm_internal.h
++++ b/fs/dlm/dlm_internal.h
+@@ -37,14 +37,11 @@
+ #include <linux/jhash.h>
+ #include <linux/miscdevice.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/dlm.h>
+ #include "config.h"
+ 
+-#define DLM_LOCKSPACE_LEN	64
+-
+ /* Size of the temp buffer midcomms allocates on the stack.
+    We try to make this large enough so most messages fit.
+    FIXME: should sctp make this unnecessary? */
+@@ -133,8 +130,10 @@ struct dlm_member {
+ 
+ struct dlm_recover {
+ 	struct list_head	list;
+-	int			*nodeids;
++	int			*nodeids;   /* nodeids of all members */
+ 	int			node_count;
++	int			*new;       /* nodeids of new members */
++	int			new_count;
+ 	uint64_t		seq;
+ };
+ 
+@@ -580,6 +579,8 @@ static inline int dlm_no_directory(struct dlm_ls *ls)
+ int dlm_netlink_init(void);
+ void dlm_netlink_exit(void);
+ void dlm_timeout_warn(struct dlm_lkb *lkb);
++int dlm_plock_init(void);
++void dlm_plock_exit(void);
+ 
+ #ifdef CONFIG_DLM_DEBUG
+ int dlm_register_debugfs(void);
+diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
+index 8f250ac..2d3d102 100644
+--- a/fs/dlm/lock.c
++++ b/fs/dlm/lock.c
+@@ -165,7 +165,7 @@ void dlm_print_lkb(struct dlm_lkb *lkb)
+ 	       lkb->lkb_grmode, lkb->lkb_wait_type, lkb->lkb_ast_type);
+ }
+ 
+-void dlm_print_rsb(struct dlm_rsb *r)
++static void dlm_print_rsb(struct dlm_rsb *r)
+ {
+ 	printk(KERN_ERR "rsb: nodeid %d flags %lx first %x rlc %d name %s\n",
+ 	       r->res_nodeid, r->res_flags, r->res_first_lkid,
+@@ -1956,8 +1956,7 @@ static void confirm_master(struct dlm_rsb *r, int error)
+ 			list_del_init(&lkb->lkb_rsb_lookup);
+ 			r->res_first_lkid = lkb->lkb_id;
+ 			_request_lock(r, lkb);
+-		} else
+-			r->res_nodeid = -1;
++		}
+ 		break;
+ 
+ 	default:
+diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
+index 05d9c82..88e93c8 100644
+--- a/fs/dlm/lock.h
++++ b/fs/dlm/lock.h
+@@ -13,7 +13,6 @@
+ #ifndef __LOCK_DOT_H__
+ #define __LOCK_DOT_H__
+ 
+-void dlm_print_rsb(struct dlm_rsb *r);
+ void dlm_dump_rsb(struct dlm_rsb *r);
+ void dlm_print_lkb(struct dlm_lkb *lkb);
+ void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms);
+diff --git a/fs/dlm/main.c b/fs/dlm/main.c
+index 58487fb..b80e0aa 100644
+--- a/fs/dlm/main.c
++++ b/fs/dlm/main.c
+@@ -46,10 +46,16 @@ static int __init init_dlm(void)
+ 	if (error)
+ 		goto out_user;
+ 
++	error = dlm_plock_init();
++	if (error)
++		goto out_netlink;
++
+ 	printk("DLM (built %s %s) installed\n", __DATE__, __TIME__);
+ 
+ 	return 0;
+ 
++ out_netlink:
++	dlm_netlink_exit();
+  out_user:
+ 	dlm_user_exit();
+  out_debug:
+@@ -66,6 +72,7 @@ static int __init init_dlm(void)
+ 
+ static void __exit exit_dlm(void)
+ {
++	dlm_plock_exit();
+ 	dlm_netlink_exit();
+ 	dlm_user_exit();
+ 	dlm_config_exit();
+diff --git a/fs/dlm/member.c b/fs/dlm/member.c
+index fa17f5a..26133f0 100644
+--- a/fs/dlm/member.c
++++ b/fs/dlm/member.c
+@@ -210,6 +210,23 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
+ 		}
+ 	}
+ 
++	/* Add an entry to ls_nodes_gone for members that were removed and
++	   then added again, so that previous state for these nodes will be
++	   cleared during recovery. */
++
++	for (i = 0; i < rv->new_count; i++) {
++		if (!dlm_is_member(ls, rv->new[i]))
++			continue;
++		log_debug(ls, "new nodeid %d is a re-added member", rv->new[i]);
++
++		memb = kzalloc(sizeof(struct dlm_member), GFP_KERNEL);
++		if (!memb)
++			return -ENOMEM;
++		memb->nodeid = rv->new[i];
++		list_add_tail(&memb->list, &ls->ls_nodes_gone);
++		neg++;
++	}
++
+ 	/* add new members to ls_nodes */
+ 
+ 	for (i = 0; i < rv->node_count; i++) {
+@@ -314,15 +331,16 @@ int dlm_ls_stop(struct dlm_ls *ls)
+ int dlm_ls_start(struct dlm_ls *ls)
+ {
+ 	struct dlm_recover *rv = NULL, *rv_old;
+-	int *ids = NULL;
+-	int error, count;
++	int *ids = NULL, *new = NULL;
++	int error, ids_count = 0, new_count = 0;
+ 
+ 	rv = kzalloc(sizeof(struct dlm_recover), GFP_KERNEL);
+ 	if (!rv)
+ 		return -ENOMEM;
+ 
+-	error = count = dlm_nodeid_list(ls->ls_name, &ids);
+-	if (error <= 0)
++	error = dlm_nodeid_list(ls->ls_name, &ids, &ids_count,
++				&new, &new_count);
++	if (error < 0)
+ 		goto fail;
+ 
+ 	spin_lock(&ls->ls_recover_lock);
+@@ -337,14 +355,19 @@ int dlm_ls_start(struct dlm_ls *ls)
+ 	}
+ 
+ 	rv->nodeids = ids;
+-	rv->node_count = count;
++	rv->node_count = ids_count;
++	rv->new = new;
++	rv->new_count = new_count;
+ 	rv->seq = ++ls->ls_recover_seq;
+ 	rv_old = ls->ls_recover_args;
+ 	ls->ls_recover_args = rv;
+ 	spin_unlock(&ls->ls_recover_lock);
+ 
+ 	if (rv_old) {
++		log_error(ls, "unused recovery %llx %d",
++			  (unsigned long long)rv_old->seq, rv_old->node_count);
+ 		kfree(rv_old->nodeids);
++		kfree(rv_old->new);
+ 		kfree(rv_old);
+ 	}
+ 
+@@ -354,6 +377,7 @@ int dlm_ls_start(struct dlm_ls *ls)
+  fail:
+ 	kfree(rv);
+ 	kfree(ids);
++	kfree(new);
+ 	return error;
+ }
+ 
+diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
+new file mode 100644
+index 0000000..d6d6e37
+--- /dev/null
++++ b/fs/dlm/plock.c
+@@ -0,0 +1,439 @@
++/*
++ * Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU General Public License version 2.
++ */
++
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/poll.h>
++#include <linux/dlm.h>
++#include <linux/dlm_plock.h>
++
++#include "dlm_internal.h"
++#include "lockspace.h"
++
++static spinlock_t ops_lock;
++static struct list_head send_list;
++static struct list_head recv_list;
++static wait_queue_head_t send_wq;
++static wait_queue_head_t recv_wq;
++
++struct plock_op {
++	struct list_head list;
++	int done;
++	struct dlm_plock_info info;
++};
++
++struct plock_xop {
++	struct plock_op xop;
++	void *callback;
++	void *fl;
++	void *file;
++	struct file_lock flc;
++};
++
++
++static inline void set_version(struct dlm_plock_info *info)
++{
++	info->version[0] = DLM_PLOCK_VERSION_MAJOR;
++	info->version[1] = DLM_PLOCK_VERSION_MINOR;
++	info->version[2] = DLM_PLOCK_VERSION_PATCH;
++}
++
++static int check_version(struct dlm_plock_info *info)
++{
++	if ((DLM_PLOCK_VERSION_MAJOR != info->version[0]) ||
++	    (DLM_PLOCK_VERSION_MINOR < info->version[1])) {
++		log_print("plock device version mismatch: "
++			  "kernel (%u.%u.%u), user (%u.%u.%u)",
++			  DLM_PLOCK_VERSION_MAJOR,
++			  DLM_PLOCK_VERSION_MINOR,
++			  DLM_PLOCK_VERSION_PATCH,
++			  info->version[0],
++			  info->version[1],
++			  info->version[2]);
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static void send_op(struct plock_op *op)
++{
++	set_version(&op->info);
++	INIT_LIST_HEAD(&op->list);
++	spin_lock(&ops_lock);
++	list_add_tail(&op->list, &send_list);
++	spin_unlock(&ops_lock);
++	wake_up(&send_wq);
++}
++
++int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++		   int cmd, struct file_lock *fl)
++{
++	struct dlm_ls *ls;
++	struct plock_op *op;
++	struct plock_xop *xop;
++	int rv;
++
++	ls = dlm_find_lockspace_local(lockspace);
++	if (!ls)
++		return -EINVAL;
++
++	xop = kzalloc(sizeof(*xop), GFP_KERNEL);
++	if (!xop) {
++		rv = -ENOMEM;
++		goto out;
++	}
++
++	op = &xop->xop;
++	op->info.optype		= DLM_PLOCK_OP_LOCK;
++	op->info.pid		= fl->fl_pid;
++	op->info.ex		= (fl->fl_type == F_WRLCK);
++	op->info.wait		= IS_SETLKW(cmd);
++	op->info.fsid		= ls->ls_global_id;
++	op->info.number		= number;
++	op->info.start		= fl->fl_start;
++	op->info.end		= fl->fl_end;
++	if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
++		/* fl_owner is lockd which doesn't distinguish
++		   processes on the nfs client */
++		op->info.owner	= (__u64) fl->fl_pid;
++		xop->callback	= fl->fl_lmops->fl_grant;
++		locks_init_lock(&xop->flc);
++		locks_copy_lock(&xop->flc, fl);
++		xop->fl		= fl;
++		xop->file	= file;
++	} else {
++		op->info.owner	= (__u64)(long) fl->fl_owner;
++		xop->callback	= NULL;
++	}
++
++	send_op(op);
++
++	if (xop->callback == NULL)
++		wait_event(recv_wq, (op->done != 0));
++	else {
++		rv = -EINPROGRESS;
++		goto out;
++	}
++
++	spin_lock(&ops_lock);
++	if (!list_empty(&op->list)) {
++		log_error(ls, "dlm_posix_lock: op on list %llx",
++			  (unsigned long long)number);
++		list_del(&op->list);
++	}
++	spin_unlock(&ops_lock);
++
++	rv = op->info.rv;
++
++	if (!rv) {
++		if (posix_lock_file_wait(file, fl) < 0)
++			log_error(ls, "dlm_posix_lock: vfs lock error %llx",
++				  (unsigned long long)number);
++	}
++
++	kfree(xop);
++out:
++	dlm_put_lockspace(ls);
++	return rv;
++}
++EXPORT_SYMBOL_GPL(dlm_posix_lock);
++
++/* Returns failure iff a succesful lock operation should be canceled */
++static int dlm_plock_callback(struct plock_op *op)
++{
++	struct file *file;
++	struct file_lock *fl;
++	struct file_lock *flc;
++	int (*notify)(void *, void *, int) = NULL;
++	struct plock_xop *xop = (struct plock_xop *)op;
++	int rv = 0;
++
++	spin_lock(&ops_lock);
++	if (!list_empty(&op->list)) {
++		log_print("dlm_plock_callback: op on list %llx",
++			  (unsigned long long)op->info.number);
++		list_del(&op->list);
++	}
++	spin_unlock(&ops_lock);
++
++	/* check if the following 2 are still valid or make a copy */
++	file = xop->file;
++	flc = &xop->flc;
++	fl = xop->fl;
++	notify = xop->callback;
++
++	if (op->info.rv) {
++		notify(flc, NULL, op->info.rv);
++		goto out;
++	}
++
++	/* got fs lock; bookkeep locally as well: */
++	flc->fl_flags &= ~FL_SLEEP;
++	if (posix_lock_file(file, flc, NULL)) {
++		/*
++		 * This can only happen in the case of kmalloc() failure.
++		 * The filesystem's own lock is the authoritative lock,
++		 * so a failure to get the lock locally is not a disaster.
++		 * As long as the fs cannot reliably cancel locks (especially
++		 * in a low-memory situation), we're better off ignoring
++		 * this failure than trying to recover.
++		 */
++		log_print("dlm_plock_callback: vfs lock error %llx file %p fl %p",
++			  (unsigned long long)op->info.number, file, fl);
++	}
++
++	rv = notify(flc, NULL, 0);
++	if (rv) {
++		/* XXX: We need to cancel the fs lock here: */
++		log_print("dlm_plock_callback: lock granted after lock request "
++			  "failed; dangling lock!\n");
++		goto out;
++	}
++
++out:
++	kfree(xop);
++	return rv;
++}
++
++int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++		     struct file_lock *fl)
++{
++	struct dlm_ls *ls;
++	struct plock_op *op;
++	int rv;
++
++	ls = dlm_find_lockspace_local(lockspace);
++	if (!ls)
++		return -EINVAL;
++
++	op = kzalloc(sizeof(*op), GFP_KERNEL);
++	if (!op) {
++		rv = -ENOMEM;
++		goto out;
++	}
++
++	if (posix_lock_file_wait(file, fl) < 0)
++		log_error(ls, "dlm_posix_unlock: vfs unlock error %llx",
++			  (unsigned long long)number);
++
++	op->info.optype		= DLM_PLOCK_OP_UNLOCK;
++	op->info.pid		= fl->fl_pid;
++	op->info.fsid		= ls->ls_global_id;
++	op->info.number		= number;
++	op->info.start		= fl->fl_start;
++	op->info.end		= fl->fl_end;
++	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
++		op->info.owner	= (__u64) fl->fl_pid;
++	else
++		op->info.owner	= (__u64)(long) fl->fl_owner;
++
++	send_op(op);
++	wait_event(recv_wq, (op->done != 0));
++
++	spin_lock(&ops_lock);
++	if (!list_empty(&op->list)) {
++		log_error(ls, "dlm_posix_unlock: op on list %llx",
++			  (unsigned long long)number);
++		list_del(&op->list);
++	}
++	spin_unlock(&ops_lock);
++
++	rv = op->info.rv;
++
++	if (rv == -ENOENT)
++		rv = 0;
++
++	kfree(op);
++out:
++	dlm_put_lockspace(ls);
++	return rv;
++}
++EXPORT_SYMBOL_GPL(dlm_posix_unlock);
++
++int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++		  struct file_lock *fl)
++{
++	struct dlm_ls *ls;
++	struct plock_op *op;
++	int rv;
++
++	ls = dlm_find_lockspace_local(lockspace);
++	if (!ls)
++		return -EINVAL;
++
++	op = kzalloc(sizeof(*op), GFP_KERNEL);
++	if (!op) {
++		rv = -ENOMEM;
++		goto out;
++	}
++
++	op->info.optype		= DLM_PLOCK_OP_GET;
++	op->info.pid		= fl->fl_pid;
++	op->info.ex		= (fl->fl_type == F_WRLCK);
++	op->info.fsid		= ls->ls_global_id;
++	op->info.number		= number;
++	op->info.start		= fl->fl_start;
++	op->info.end		= fl->fl_end;
++	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
++		op->info.owner	= (__u64) fl->fl_pid;
++	else
++		op->info.owner	= (__u64)(long) fl->fl_owner;
++
++	send_op(op);
++	wait_event(recv_wq, (op->done != 0));
++
++	spin_lock(&ops_lock);
++	if (!list_empty(&op->list)) {
++		log_error(ls, "dlm_posix_get: op on list %llx",
++			  (unsigned long long)number);
++		list_del(&op->list);
++	}
++	spin_unlock(&ops_lock);
++
++	/* info.rv from userspace is 1 for conflict, 0 for no-conflict,
++	   -ENOENT if there are no locks on the file */
++
++	rv = op->info.rv;
++
++	fl->fl_type = F_UNLCK;
++	if (rv == -ENOENT)
++		rv = 0;
++	else if (rv > 0) {
++		fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
++		fl->fl_pid = op->info.pid;
++		fl->fl_start = op->info.start;
++		fl->fl_end = op->info.end;
++		rv = 0;
++	}
++
++	kfree(op);
++out:
++	dlm_put_lockspace(ls);
++	return rv;
++}
++EXPORT_SYMBOL_GPL(dlm_posix_get);
++
++/* a read copies out one plock request from the send list */
++static ssize_t dev_read(struct file *file, char __user *u, size_t count,
++			loff_t *ppos)
++{
++	struct dlm_plock_info info;
++	struct plock_op *op = NULL;
++
++	if (count < sizeof(info))
++		return -EINVAL;
++
++	spin_lock(&ops_lock);
++	if (!list_empty(&send_list)) {
++		op = list_entry(send_list.next, struct plock_op, list);
++		list_move(&op->list, &recv_list);
++		memcpy(&info, &op->info, sizeof(info));
++	}
++	spin_unlock(&ops_lock);
++
++	if (!op)
++		return -EAGAIN;
++
++	if (copy_to_user(u, &info, sizeof(info)))
++		return -EFAULT;
++	return sizeof(info);
++}
++
++/* a write copies in one plock result that should match a plock_op
++   on the recv list */
++static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
++			 loff_t *ppos)
++{
++	struct dlm_plock_info info;
++	struct plock_op *op;
++	int found = 0;
++
++	if (count != sizeof(info))
++		return -EINVAL;
++
++	if (copy_from_user(&info, u, sizeof(info)))
++		return -EFAULT;
++
++	if (check_version(&info))
++		return -EINVAL;
++
++	spin_lock(&ops_lock);
++	list_for_each_entry(op, &recv_list, list) {
++		if (op->info.fsid == info.fsid && op->info.number == info.number &&
++		    op->info.owner == info.owner) {
++			list_del_init(&op->list);
++			found = 1;
++			op->done = 1;
++			memcpy(&op->info, &info, sizeof(info));
++			break;
++		}
++	}
++	spin_unlock(&ops_lock);
++
++	if (found) {
++		struct plock_xop *xop;
++		xop = (struct plock_xop *)op;
++		if (xop->callback)
++			count = dlm_plock_callback(op);
++		else
++			wake_up(&recv_wq);
++	} else
++		log_print("dev_write no op %x %llx", info.fsid,
++			  (unsigned long long)info.number);
++	return count;
++}
++
++static unsigned int dev_poll(struct file *file, poll_table *wait)
++{
++	unsigned int mask = 0;
++
++	poll_wait(file, &send_wq, wait);
++
++	spin_lock(&ops_lock);
++	if (!list_empty(&send_list))
++		mask = POLLIN | POLLRDNORM;
++	spin_unlock(&ops_lock);
++
++	return mask;
++}
++
++static const struct file_operations dev_fops = {
++	.read    = dev_read,
++	.write   = dev_write,
++	.poll    = dev_poll,
++	.owner   = THIS_MODULE
++};
++
++static struct miscdevice plock_dev_misc = {
++	.minor = MISC_DYNAMIC_MINOR,
++	.name = DLM_PLOCK_MISC_NAME,
++	.fops = &dev_fops
++};
++
++int dlm_plock_init(void)
++{
++	int rv;
++
++	spin_lock_init(&ops_lock);
++	INIT_LIST_HEAD(&send_list);
++	INIT_LIST_HEAD(&recv_list);
++	init_waitqueue_head(&send_wq);
++	init_waitqueue_head(&recv_wq);
++
++	rv = misc_register(&plock_dev_misc);
++	if (rv)
++		log_print("dlm_plock_init: misc_register failed %d", rv);
++	return rv;
++}
++
++void dlm_plock_exit(void)
++{
++	if (misc_deregister(&plock_dev_misc) < 0)
++		log_print("dlm_plock_exit: misc_deregister failed");
++}
++
+diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
+index 997f953..fd677c8 100644
+--- a/fs/dlm/recoverd.c
++++ b/fs/dlm/recoverd.c
+@@ -257,6 +257,7 @@ static void do_ls_recovery(struct dlm_ls *ls)
+ 	if (rv) {
+ 		ls_recover(ls, rv);
+ 		kfree(rv->nodeids);
++		kfree(rv->new);
+ 		kfree(rv);
+ 	}
+ }
+diff --git a/fs/exec.c b/fs/exec.c
+index 54a0a55..b152029 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -953,7 +953,6 @@ int flush_old_exec(struct linux_binprm * bprm)
+ {
+ 	char * name;
+ 	int i, ch, retval;
+-	struct files_struct *files;
+ 	char tcomm[sizeof(current->comm)];
+ 
+ 	/*
+@@ -965,26 +964,15 @@ int flush_old_exec(struct linux_binprm * bprm)
+ 		goto out;
+ 
+ 	/*
+-	 * Make sure we have private file handles. Ask the
+-	 * fork helper to do the work for us and the exit
+-	 * helper to do the cleanup of the old one.
+-	 */
+-	files = current->files;		/* refcounted so safe to hold */
+-	retval = unshare_files();
+-	if (retval)
+-		goto out;
+-	/*
+ 	 * Release all of the old mmap stuff
+ 	 */
+ 	retval = exec_mmap(bprm->mm);
+ 	if (retval)
+-		goto mmap_failed;
++		goto out;
+ 
+ 	bprm->mm = NULL;		/* We're using it now */
+ 
+ 	/* This is the point of no return */
+-	put_files_struct(files);
+-
+ 	current->sas_ss_sp = current->sas_ss_size = 0;
+ 
+ 	if (current->euid == current->uid && current->egid == current->gid)
+@@ -1034,8 +1022,6 @@ int flush_old_exec(struct linux_binprm * bprm)
+ 
+ 	return 0;
+ 
+-mmap_failed:
+-	reset_files_struct(current, files);
+ out:
+ 	return retval;
+ }
+@@ -1283,12 +1269,17 @@ int do_execve(char * filename,
+ 	struct linux_binprm *bprm;
+ 	struct file *file;
+ 	unsigned long env_p;
++	struct files_struct *displaced;
+ 	int retval;
+ 
++	retval = unshare_files(&displaced);
++	if (retval)
++		goto out_ret;
++
+ 	retval = -ENOMEM;
+ 	bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
+ 	if (!bprm)
+-		goto out_ret;
++		goto out_files;
+ 
+ 	file = open_exec(filename);
+ 	retval = PTR_ERR(file);
+@@ -1343,6 +1334,8 @@ int do_execve(char * filename,
+ 		security_bprm_free(bprm);
+ 		acct_update_integrals(current);
+ 		kfree(bprm);
++		if (displaced)
++			put_files_struct(displaced);
+ 		return retval;
+ 	}
+ 
+@@ -1363,6 +1356,9 @@ out_file:
+ out_kfree:
+ 	kfree(bprm);
+ 
++out_files:
++	if (displaced)
++		reset_files_struct(displaced);
+ out_ret:
+ 	return retval;
+ }
+diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
+index 5deb8b7..08f647d 100644
+--- a/fs/ext2/ialloc.c
++++ b/fs/ext2/ialloc.c
+@@ -253,7 +253,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
+  * it has too few free inodes left (min_inodes) or 
+  * it has too few free blocks left (min_blocks) or 
+  * it's already running too large debt (max_debt). 
+- * Parent's group is prefered, if it doesn't satisfy these 
++ * Parent's group is preferred, if it doesn't satisfy these 
+  * conditions we search cyclically through the rest. If none 
+  * of the groups look good we just look for a group with more 
+  * free inodes than average (starting at parent's group). 
+diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
+index c620068..b8a2990 100644
+--- a/fs/ext2/inode.c
++++ b/fs/ext2/inode.c
+@@ -239,7 +239,7 @@ no_block:
+  *	@inode: owner
+  *	@ind: descriptor of indirect block.
+  *
+- *	This function returns the prefered place for block allocation.
++ *	This function returns the preferred place for block allocation.
+  *	It is used when heuristic for sequential allocation fails.
+  *	Rules are:
+  *	  + if there is a block to the left of our position - allocate near it.
+@@ -283,7 +283,7 @@ static unsigned long ext2_find_near(struct inode *inode, Indirect *ind)
+ }
+ 
+ /**
+- *	ext2_find_goal - find a prefered place for allocation.
++ *	ext2_find_goal - find a preferred place for allocation.
+  *	@inode: owner
+  *	@block:  block we want
+  *	@partial: pointer to the last triple within a chain
+diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
+index b8ea11f..de876fa 100644
+--- a/fs/ext2/ioctl.c
++++ b/fs/ext2/ioctl.c
+@@ -12,6 +12,7 @@
+ #include <linux/time.h>
+ #include <linux/sched.h>
+ #include <linux/compat.h>
++#include <linux/mount.h>
+ #include <linux/smp_lock.h>
+ #include <asm/current.h>
+ #include <asm/uaccess.h>
+@@ -23,6 +24,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	struct ext2_inode_info *ei = EXT2_I(inode);
+ 	unsigned int flags;
+ 	unsigned short rsv_window_size;
++	int ret;
+ 
+ 	ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
+ 
+@@ -34,14 +36,19 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 	case EXT2_IOC_SETFLAGS: {
+ 		unsigned int oldflags;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
++		ret = mnt_want_write(filp->f_path.mnt);
++		if (ret)
++			return ret;
+ 
+-		if (!is_owner_or_cap(inode))
+-			return -EACCES;
++		if (!is_owner_or_cap(inode)) {
++			ret = -EACCES;
++			goto setflags_out;
++		}
+ 
+-		if (get_user(flags, (int __user *) arg))
+-			return -EFAULT;
++		if (get_user(flags, (int __user *) arg)) {
++			ret = -EFAULT;
++			goto setflags_out;
++		}
+ 
+ 		if (!S_ISDIR(inode->i_mode))
+ 			flags &= ~EXT2_DIRSYNC_FL;
+@@ -50,7 +57,8 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		/* Is it quota file? Do not allow user to mess with it */
+ 		if (IS_NOQUOTA(inode)) {
+ 			mutex_unlock(&inode->i_mutex);
+-			return -EPERM;
++			ret = -EPERM;
++			goto setflags_out;
+ 		}
+ 		oldflags = ei->i_flags;
+ 
+@@ -63,7 +71,8 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
+ 			if (!capable(CAP_LINUX_IMMUTABLE)) {
+ 				mutex_unlock(&inode->i_mutex);
+-				return -EPERM;
++				ret = -EPERM;
++				goto setflags_out;
+ 			}
+ 		}
+ 
+@@ -75,20 +84,26 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		ext2_set_inode_flags(inode);
+ 		inode->i_ctime = CURRENT_TIME_SEC;
+ 		mark_inode_dirty(inode);
+-		return 0;
++setflags_out:
++		mnt_drop_write(filp->f_path.mnt);
++		return ret;
+ 	}
+ 	case EXT2_IOC_GETVERSION:
+ 		return put_user(inode->i_generation, (int __user *) arg);
+ 	case EXT2_IOC_SETVERSION:
+ 		if (!is_owner_or_cap(inode))
+ 			return -EPERM;
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-		if (get_user(inode->i_generation, (int __user *) arg))
+-			return -EFAULT;	
+-		inode->i_ctime = CURRENT_TIME_SEC;
+-		mark_inode_dirty(inode);
+-		return 0;
++		ret = mnt_want_write(filp->f_path.mnt);
++		if (ret)
++			return ret;
++		if (get_user(inode->i_generation, (int __user *) arg)) {
++			ret = -EFAULT;
++		} else {
++			inode->i_ctime = CURRENT_TIME_SEC;
++			mark_inode_dirty(inode);
++		}
++		mnt_drop_write(filp->f_path.mnt);
++		return ret;
+ 	case EXT2_IOC_GETRSVSZ:
+ 		if (test_opt(inode->i_sb, RESERVATION)
+ 			&& S_ISREG(inode->i_mode)
+@@ -102,15 +117,16 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
+ 			return -ENOTTY;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-
+-		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
++		if (!is_owner_or_cap(inode))
+ 			return -EACCES;
+ 
+ 		if (get_user(rsv_window_size, (int __user *)arg))
+ 			return -EFAULT;
+ 
++		ret = mnt_want_write(filp->f_path.mnt);
++		if (ret)
++			return ret;
++
+ 		if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS)
+ 			rsv_window_size = EXT2_MAX_RESERVE_BLOCKS;
+ 
+@@ -131,6 +147,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 			rsv->rsv_goal_size = rsv_window_size;
+ 		}
+ 		mutex_unlock(&ei->truncate_mutex);
++		mnt_drop_write(filp->f_path.mnt);
+ 		return 0;
+ 	}
+ 	default:
+diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
+index 4f4020c..96dd557 100644
+--- a/fs/ext3/ialloc.c
++++ b/fs/ext3/ialloc.c
+@@ -239,7 +239,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
+  * it has too few free inodes left (min_inodes) or
+  * it has too few free blocks left (min_blocks) or
+  * it's already running too large debt (max_debt).
+- * Parent's group is prefered, if it doesn't satisfy these
++ * Parent's group is preferred, if it doesn't satisfy these
+  * conditions we search cyclically through the rest. If none
+  * of the groups look good we just look for a group with more
+  * free inodes than average (starting at parent's group).
+diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
+index eb95670..c683609 100644
+--- a/fs/ext3/inode.c
++++ b/fs/ext3/inode.c
+@@ -392,7 +392,7 @@ no_block:
+  *	@inode: owner
+  *	@ind: descriptor of indirect block.
+  *
+- *	This function returns the prefered place for block allocation.
++ *	This function returns the preferred place for block allocation.
+  *	It is used when heuristic for sequential allocation fails.
+  *	Rules are:
+  *	  + if there is a block to the left of our position - allocate near it.
+@@ -436,12 +436,12 @@ static ext3_fsblk_t ext3_find_near(struct inode *inode, Indirect *ind)
+ }
+ 
+ /**
+- *	ext3_find_goal - find a prefered place for allocation.
++ *	ext3_find_goal - find a preferred place for allocation.
+  *	@inode: owner
+  *	@block:  block we want
+  *	@partial: pointer to the last triple within a chain
+  *
+- *	Normally this function find the prefered place for block allocation,
++ *	Normally this function find the preferred place for block allocation,
+  *	returns it.
+  */
+ 
+diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
+index 023a070..0d0c701 100644
+--- a/fs/ext3/ioctl.c
++++ b/fs/ext3/ioctl.c
+@@ -12,6 +12,7 @@
+ #include <linux/capability.h>
+ #include <linux/ext3_fs.h>
+ #include <linux/ext3_jbd.h>
++#include <linux/mount.h>
+ #include <linux/time.h>
+ #include <linux/compat.h>
+ #include <linux/smp_lock.h>
+@@ -38,14 +39,19 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ 		unsigned int oldflags;
+ 		unsigned int jflag;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
+ 
+-		if (!is_owner_or_cap(inode))
+-			return -EACCES;
++		if (!is_owner_or_cap(inode)) {
++			err = -EACCES;
++			goto flags_out;
++		}
+ 
+-		if (get_user(flags, (int __user *) arg))
+-			return -EFAULT;
++		if (get_user(flags, (int __user *) arg)) {
++			err = -EFAULT;
++			goto flags_out;
++		}
+ 
+ 		if (!S_ISDIR(inode->i_mode))
+ 			flags &= ~EXT3_DIRSYNC_FL;
+@@ -54,7 +60,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ 		/* Is it quota file? Do not allow user to mess with it */
+ 		if (IS_NOQUOTA(inode)) {
+ 			mutex_unlock(&inode->i_mutex);
+-			return -EPERM;
++			err = -EPERM;
++			goto flags_out;
+ 		}
+ 		oldflags = ei->i_flags;
+ 
+@@ -70,7 +77,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ 		if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
+ 			if (!capable(CAP_LINUX_IMMUTABLE)) {
+ 				mutex_unlock(&inode->i_mutex);
+-				return -EPERM;
++				err = -EPERM;
++				goto flags_out;
+ 			}
+ 		}
+ 
+@@ -81,7 +89,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ 		if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
+ 			if (!capable(CAP_SYS_RESOURCE)) {
+ 				mutex_unlock(&inode->i_mutex);
+-				return -EPERM;
++				err = -EPERM;
++				goto flags_out;
+ 			}
+ 		}
+ 
+@@ -89,7 +98,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ 		handle = ext3_journal_start(inode, 1);
+ 		if (IS_ERR(handle)) {
+ 			mutex_unlock(&inode->i_mutex);
+-			return PTR_ERR(handle);
++			err = PTR_ERR(handle);
++			goto flags_out;
+ 		}
+ 		if (IS_SYNC(inode))
+ 			handle->h_sync = 1;
+@@ -115,6 +125,8 @@ flags_err:
+ 		if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
+ 			err = ext3_change_inode_journal_flag(inode, jflag);
+ 		mutex_unlock(&inode->i_mutex);
++flags_out:
++		mnt_drop_write(filp->f_path.mnt);
+ 		return err;
+ 	}
+ 	case EXT3_IOC_GETVERSION:
+@@ -129,14 +141,18 @@ flags_err:
+ 
+ 		if (!is_owner_or_cap(inode))
+ 			return -EPERM;
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-		if (get_user(generation, (int __user *) arg))
+-			return -EFAULT;
+-
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
++		if (get_user(generation, (int __user *) arg)) {
++			err = -EFAULT;
++			goto setversion_out;
++		}
+ 		handle = ext3_journal_start(inode, 1);
+-		if (IS_ERR(handle))
+-			return PTR_ERR(handle);
++		if (IS_ERR(handle)) {
++			err = PTR_ERR(handle);
++			goto setversion_out;
++		}
+ 		err = ext3_reserve_inode_write(handle, inode, &iloc);
+ 		if (err == 0) {
+ 			inode->i_ctime = CURRENT_TIME_SEC;
+@@ -144,6 +160,8 @@ flags_err:
+ 			err = ext3_mark_iloc_dirty(handle, inode, &iloc);
+ 		}
+ 		ext3_journal_stop(handle);
++setversion_out:
++		mnt_drop_write(filp->f_path.mnt);
+ 		return err;
+ 	}
+ #ifdef CONFIG_JBD_DEBUG
+@@ -179,18 +197,24 @@ flags_err:
+ 		}
+ 		return -ENOTTY;
+ 	case EXT3_IOC_SETRSVSZ: {
++		int err;
+ 
+ 		if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
+ 			return -ENOTTY;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
+ 
+-		if (!is_owner_or_cap(inode))
+-			return -EACCES;
++		if (!is_owner_or_cap(inode)) {
++			err = -EACCES;
++			goto setrsvsz_out;
++		}
+ 
+-		if (get_user(rsv_window_size, (int __user *)arg))
+-			return -EFAULT;
++		if (get_user(rsv_window_size, (int __user *)arg)) {
++			err = -EFAULT;
++			goto setrsvsz_out;
++		}
+ 
+ 		if (rsv_window_size > EXT3_MAX_RESERVE_BLOCKS)
+ 			rsv_window_size = EXT3_MAX_RESERVE_BLOCKS;
+@@ -208,7 +232,9 @@ flags_err:
+ 			rsv->rsv_goal_size = rsv_window_size;
+ 		}
+ 		mutex_unlock(&ei->truncate_mutex);
+-		return 0;
++setrsvsz_out:
++		mnt_drop_write(filp->f_path.mnt);
++		return err;
+ 	}
+ 	case EXT3_IOC_GROUP_EXTEND: {
+ 		ext3_fsblk_t n_blocks_count;
+@@ -218,17 +244,20 @@ flags_err:
+ 		if (!capable(CAP_SYS_RESOURCE))
+ 			return -EPERM;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-
+-		if (get_user(n_blocks_count, (__u32 __user *)arg))
+-			return -EFAULT;
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
+ 
++		if (get_user(n_blocks_count, (__u32 __user *)arg)) {
++			err = -EFAULT;
++			goto group_extend_out;
++		}
+ 		err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count);
+ 		journal_lock_updates(EXT3_SB(sb)->s_journal);
+ 		journal_flush(EXT3_SB(sb)->s_journal);
+ 		journal_unlock_updates(EXT3_SB(sb)->s_journal);
+-
++group_extend_out:
++		mnt_drop_write(filp->f_path.mnt);
+ 		return err;
+ 	}
+ 	case EXT3_IOC_GROUP_ADD: {
+@@ -239,18 +268,22 @@ flags_err:
+ 		if (!capable(CAP_SYS_RESOURCE))
+ 			return -EPERM;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
+ 
+ 		if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg,
+-				sizeof(input)))
+-			return -EFAULT;
++				sizeof(input))) {
++			err = -EFAULT;
++			goto group_add_out;
++		}
+ 
+ 		err = ext3_group_add(sb, &input);
+ 		journal_lock_updates(EXT3_SB(sb)->s_journal);
+ 		journal_flush(EXT3_SB(sb)->s_journal);
+ 		journal_unlock_updates(EXT3_SB(sb)->s_journal);
+-
++group_add_out:
++		mnt_drop_write(filp->f_path.mnt);
+ 		return err;
+ 	}
+ 
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 8036b9b..486e46a 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -305,7 +305,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent,
+  * it has too few free inodes left (min_inodes) or
+  * it has too few free blocks left (min_blocks) or
+  * it's already running too large debt (max_debt).
+- * Parent's group is prefered, if it doesn't satisfy these
++ * Parent's group is preferred, if it doesn't satisfy these
+  * conditions we search cyclically through the rest. If none
+  * of the groups look good we just look for a group with more
+  * free inodes than average (starting at parent's group).
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 945cbf6..8fab233 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -382,7 +382,7 @@ no_block:
+  *	@inode: owner
+  *	@ind: descriptor of indirect block.
+  *
+- *	This function returns the prefered place for block allocation.
++ *	This function returns the preferred place for block allocation.
+  *	It is used when heuristic for sequential allocation fails.
+  *	Rules are:
+  *	  + if there is a block to the left of our position - allocate near it.
+@@ -432,12 +432,12 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
+ }
+ 
+ /**
+- *	ext4_find_goal - find a prefered place for allocation.
++ *	ext4_find_goal - find a preferred place for allocation.
+  *	@inode: owner
+  *	@block:  block we want
+  *	@partial: pointer to the last triple within a chain
+  *
+- *	Normally this function find the prefered place for block allocation,
++ *	Normally this function find the preferred place for block allocation,
+  *	returns it.
+  */
+ static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 2ed7c37..25b13ed 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -15,6 +15,7 @@
+ #include <linux/time.h>
+ #include <linux/compat.h>
+ #include <linux/smp_lock.h>
++#include <linux/mount.h>
+ #include <asm/uaccess.h>
+ 
+ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+@@ -38,24 +39,25 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ 		unsigned int oldflags;
+ 		unsigned int jflag;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-
+ 		if (!is_owner_or_cap(inode))
+ 			return -EACCES;
+ 
+ 		if (get_user(flags, (int __user *) arg))
+ 			return -EFAULT;
+ 
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
++
+ 		if (!S_ISDIR(inode->i_mode))
+ 			flags &= ~EXT4_DIRSYNC_FL;
+ 
++		err = -EPERM;
+ 		mutex_lock(&inode->i_mutex);
+ 		/* Is it quota file? Do not allow user to mess with it */
+-		if (IS_NOQUOTA(inode)) {
+-			mutex_unlock(&inode->i_mutex);
+-			return -EPERM;
+-		}
++		if (IS_NOQUOTA(inode))
++			goto flags_out;
++
+ 		oldflags = ei->i_flags;
+ 
+ 		/* The JOURNAL_DATA flag is modifiable only by root */
+@@ -68,10 +70,8 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ 		 * This test looks nicer. Thanks to Pauline Middelink
+ 		 */
+ 		if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
+-			if (!capable(CAP_LINUX_IMMUTABLE)) {
+-				mutex_unlock(&inode->i_mutex);
+-				return -EPERM;
+-			}
++			if (!capable(CAP_LINUX_IMMUTABLE))
++				goto flags_out;
+ 		}
+ 
+ 		/*
+@@ -79,17 +79,14 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ 		 * the relevant capability.
+ 		 */
+ 		if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
+-			if (!capable(CAP_SYS_RESOURCE)) {
+-				mutex_unlock(&inode->i_mutex);
+-				return -EPERM;
+-			}
++			if (!capable(CAP_SYS_RESOURCE))
++				goto flags_out;
+ 		}
+ 
+-
+ 		handle = ext4_journal_start(inode, 1);
+ 		if (IS_ERR(handle)) {
+-			mutex_unlock(&inode->i_mutex);
+-			return PTR_ERR(handle);
++			err = PTR_ERR(handle);
++			goto flags_out;
+ 		}
+ 		if (IS_SYNC(inode))
+ 			handle->h_sync = 1;
+@@ -107,14 +104,14 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ 		err = ext4_mark_iloc_dirty(handle, inode, &iloc);
+ flags_err:
+ 		ext4_journal_stop(handle);
+-		if (err) {
+-			mutex_unlock(&inode->i_mutex);
+-			return err;
+-		}
++		if (err)
++			goto flags_out;
+ 
+ 		if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
+ 			err = ext4_change_inode_journal_flag(inode, jflag);
++flags_out:
+ 		mutex_unlock(&inode->i_mutex);
++		mnt_drop_write(filp->f_path.mnt);
+ 		return err;
+ 	}
+ 	case EXT4_IOC_GETVERSION:
+@@ -129,14 +126,20 @@ flags_err:
+ 
+ 		if (!is_owner_or_cap(inode))
+ 			return -EPERM;
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-		if (get_user(generation, (int __user *) arg))
+-			return -EFAULT;
++
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
++		if (get_user(generation, (int __user *) arg)) {
++			err = -EFAULT;
++			goto setversion_out;
++		}
+ 
+ 		handle = ext4_journal_start(inode, 1);
+-		if (IS_ERR(handle))
+-			return PTR_ERR(handle);
++		if (IS_ERR(handle)) {
++			err = PTR_ERR(handle);
++			goto setversion_out;
++		}
+ 		err = ext4_reserve_inode_write(handle, inode, &iloc);
+ 		if (err == 0) {
+ 			inode->i_ctime = ext4_current_time(inode);
+@@ -144,6 +147,8 @@ flags_err:
+ 			err = ext4_mark_iloc_dirty(handle, inode, &iloc);
+ 		}
+ 		ext4_journal_stop(handle);
++setversion_out:
++		mnt_drop_write(filp->f_path.mnt);
+ 		return err;
+ 	}
+ #ifdef CONFIG_JBD2_DEBUG
+@@ -179,19 +184,21 @@ flags_err:
+ 		}
+ 		return -ENOTTY;
+ 	case EXT4_IOC_SETRSVSZ: {
++		int err;
+ 
+ 		if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
+ 			return -ENOTTY;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-
+ 		if (!is_owner_or_cap(inode))
+ 			return -EACCES;
+ 
+ 		if (get_user(rsv_window_size, (int __user *)arg))
+ 			return -EFAULT;
+ 
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
++
+ 		if (rsv_window_size > EXT4_MAX_RESERVE_BLOCKS)
+ 			rsv_window_size = EXT4_MAX_RESERVE_BLOCKS;
+ 
+@@ -208,6 +215,7 @@ flags_err:
+ 			rsv->rsv_goal_size = rsv_window_size;
+ 		}
+ 		up_write(&ei->i_data_sem);
++		mnt_drop_write(filp->f_path.mnt);
+ 		return 0;
+ 	}
+ 	case EXT4_IOC_GROUP_EXTEND: {
+@@ -218,16 +226,18 @@ flags_err:
+ 		if (!capable(CAP_SYS_RESOURCE))
+ 			return -EPERM;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-
+ 		if (get_user(n_blocks_count, (__u32 __user *)arg))
+ 			return -EFAULT;
+ 
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
++
+ 		err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
+ 		jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
+ 		jbd2_journal_flush(EXT4_SB(sb)->s_journal);
+ 		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
++		mnt_drop_write(filp->f_path.mnt);
+ 
+ 		return err;
+ 	}
+@@ -239,17 +249,19 @@ flags_err:
+ 		if (!capable(CAP_SYS_RESOURCE))
+ 			return -EPERM;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-
+ 		if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
+ 				sizeof(input)))
+ 			return -EFAULT;
+ 
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
++
+ 		err = ext4_group_add(sb, &input);
+ 		jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
+ 		jbd2_journal_flush(EXT4_SB(sb)->s_journal);
+ 		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
++		mnt_drop_write(filp->f_path.mnt);
+ 
+ 		return err;
+ 	}
+diff --git a/fs/fat/file.c b/fs/fat/file.c
+index c614175..2a3bed9 100644
+--- a/fs/fat/file.c
++++ b/fs/fat/file.c
+@@ -8,6 +8,7 @@
+ 
+ #include <linux/capability.h>
+ #include <linux/module.h>
++#include <linux/mount.h>
+ #include <linux/time.h>
+ #include <linux/msdos_fs.h>
+ #include <linux/smp_lock.h>
+@@ -46,10 +47,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
+ 
+ 		mutex_lock(&inode->i_mutex);
+ 
+-		if (IS_RDONLY(inode)) {
+-			err = -EROFS;
+-			goto up;
+-		}
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			goto up_no_drop_write;
+ 
+ 		/*
+ 		 * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
+@@ -105,7 +105,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
+ 
+ 		MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED;
+ 		mark_inode_dirty(inode);
+-	up:
++up:
++		mnt_drop_write(filp->f_path.mnt);
++up_no_drop_write:
+ 		mutex_unlock(&inode->i_mutex);
+ 		return err;
+ 	}
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index e632da7..3f3ac63 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -55,14 +55,16 @@ static int get_close_on_exec(unsigned int fd)
+  * file_lock held for write.
+  */
+ 
+-static int locate_fd(struct files_struct *files, 
+-			    struct file *file, unsigned int orig_start)
++static int locate_fd(unsigned int orig_start, int cloexec)
+ {
++	struct files_struct *files = current->files;
+ 	unsigned int newfd;
+ 	unsigned int start;
+ 	int error;
+ 	struct fdtable *fdt;
+ 
++	spin_lock(&files->file_lock);
++
+ 	error = -EINVAL;
+ 	if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+ 		goto out;
+@@ -97,42 +99,28 @@ repeat:
+ 	if (error)
+ 		goto repeat;
+ 
+-	/*
+-	 * We reacquired files_lock, so we are safe as long as
+-	 * we reacquire the fdtable pointer and use it while holding
+-	 * the lock, no one can free it during that time.
+-	 */
+ 	if (start <= files->next_fd)
+ 		files->next_fd = newfd + 1;
+ 
++	FD_SET(newfd, fdt->open_fds);
++	if (cloexec)
++		FD_SET(newfd, fdt->close_on_exec);
++	else
++		FD_CLR(newfd, fdt->close_on_exec);
+ 	error = newfd;
+-	
++
+ out:
++	spin_unlock(&files->file_lock);
+ 	return error;
+ }
+ 
+ static int dupfd(struct file *file, unsigned int start, int cloexec)
+ {
+-	struct files_struct * files = current->files;
+-	struct fdtable *fdt;
+-	int fd;
+-
+-	spin_lock(&files->file_lock);
+-	fd = locate_fd(files, file, start);
+-	if (fd >= 0) {
+-		/* locate_fd() may have expanded fdtable, load the ptr */
+-		fdt = files_fdtable(files);
+-		FD_SET(fd, fdt->open_fds);
+-		if (cloexec)
+-			FD_SET(fd, fdt->close_on_exec);
+-		else
+-			FD_CLR(fd, fdt->close_on_exec);
+-		spin_unlock(&files->file_lock);
++	int fd = locate_fd(start, cloexec);
++	if (fd >= 0)
+ 		fd_install(fd, file);
+-	} else {
+-		spin_unlock(&files->file_lock);
++	else
+ 		fput(file);
+-	}
+ 
+ 	return fd;
+ }
+diff --git a/fs/file_table.c b/fs/file_table.c
+index 986ff4e..7a0a9b8 100644
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -42,6 +42,7 @@ static inline void file_free_rcu(struct rcu_head *head)
+ static inline void file_free(struct file *f)
+ {
+ 	percpu_counter_dec(&nr_files);
++	file_check_state(f);
+ 	call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
+ }
+ 
+@@ -199,6 +200,18 @@ int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
+ 	file->f_mapping = dentry->d_inode->i_mapping;
+ 	file->f_mode = mode;
+ 	file->f_op = fop;
++
++	/*
++	 * These mounts don't really matter in practice
++	 * for r/o bind mounts.  They aren't userspace-
++	 * visible.  We do this for consistency, and so
++	 * that we can do debugging checks at __fput()
++	 */
++	if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) {
++		file_take_write(file);
++		error = mnt_want_write(mnt);
++		WARN_ON(error);
++	}
+ 	return error;
+ }
+ EXPORT_SYMBOL(init_file);
+@@ -211,6 +224,31 @@ void fput(struct file *file)
+ 
+ EXPORT_SYMBOL(fput);
+ 
++/**
++ * drop_file_write_access - give up ability to write to a file
++ * @file: the file to which we will stop writing
++ *
++ * This is a central place which will give up the ability
++ * to write to @file, along with access to write through
++ * its vfsmount.
++ */
++void drop_file_write_access(struct file *file)
++{
++	struct vfsmount *mnt = file->f_path.mnt;
++	struct dentry *dentry = file->f_path.dentry;
++	struct inode *inode = dentry->d_inode;
++
++	put_write_access(inode);
++
++	if (special_file(inode->i_mode))
++		return;
++	if (file_check_writeable(file) != 0)
++		return;
++	mnt_drop_write(mnt);
++	file_release_write(file);
++}
++EXPORT_SYMBOL_GPL(drop_file_write_access);
++
+ /* __fput is called from task context when aio completion releases the last
+  * last use of a struct file *.  Do not use otherwise.
+  */
+@@ -236,10 +274,10 @@ void __fput(struct file *file)
+ 	if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
+ 		cdev_put(inode->i_cdev);
+ 	fops_put(file->f_op);
+-	if (file->f_mode & FMODE_WRITE)
+-		put_write_access(inode);
+ 	put_pid(file->f_owner.pid);
+ 	file_kill(file);
++	if (file->f_mode & FMODE_WRITE)
++		drop_file_write_access(file);
+ 	file->f_path.dentry = NULL;
+ 	file->f_path.mnt = NULL;
+ 	file_free(file);
+diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
+index 033f7bd..4df34da 100644
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -242,10 +242,9 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
+ 	return inode;
+ }
+ 
+-static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags)
++static void fuse_umount_begin(struct super_block *sb)
+ {
+-	if (flags & MNT_FORCE)
+-		fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb));
++	fuse_abort_conn(get_fuse_conn_super(sb));
+ }
+ 
+ static void fuse_send_destroy(struct fuse_conn *fc)
+diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
+index de8e64c..7f7947e 100644
+--- a/fs/gfs2/Kconfig
++++ b/fs/gfs2/Kconfig
+@@ -1,6 +1,6 @@
+ config GFS2_FS
+ 	tristate "GFS2 file system support"
+-	depends on EXPERIMENTAL
++	depends on EXPERIMENTAL && (64BIT || (LSF && LBD))
+ 	select FS_POSIX_ACL
+ 	select CRC32
+ 	help
+diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
+index 8fff110..e2350df 100644
+--- a/fs/gfs2/Makefile
++++ b/fs/gfs2/Makefile
+@@ -1,6 +1,6 @@
+ obj-$(CONFIG_GFS2_FS) += gfs2.o
+ gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
+-	glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \
++	glops.o inode.o log.o lops.o locking.o main.o meta_io.o \
+ 	mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
+ 	ops_fstype.o ops_inode.o ops_super.o quota.o \
+ 	recovery.o rgrp.o super.o sys.o trans.o util.o
+diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
+index 1047a8c..3e9bd46 100644
+--- a/fs/gfs2/acl.c
++++ b/fs/gfs2/acl.c
+@@ -116,7 +116,7 @@ static int acl_get(struct gfs2_inode *ip, int access, struct posix_acl **acl,
+ 		goto out;
+ 
+ 	er.er_data_len = GFS2_EA_DATA_LEN(el->el_ea);
+-	er.er_data = kmalloc(er.er_data_len, GFP_KERNEL);
++	er.er_data = kmalloc(er.er_data_len, GFP_NOFS);
+ 	error = -ENOMEM;
+ 	if (!er.er_data)
+ 		goto out;
+@@ -222,7 +222,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
+ 		return error;
+ 	}
+ 
+-	clone = posix_acl_clone(acl, GFP_KERNEL);
++	clone = posix_acl_clone(acl, GFP_NOFS);
+ 	error = -ENOMEM;
+ 	if (!clone)
+ 		goto out;
+@@ -272,7 +272,7 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
+ 	if (!acl)
+ 		return gfs2_setattr_simple(ip, attr);
+ 
+-	clone = posix_acl_clone(acl, GFP_KERNEL);
++	clone = posix_acl_clone(acl, GFP_NOFS);
+ 	error = -ENOMEM;
+ 	if (!clone)
+ 		goto out;
+diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
+index e9456eb..c19184f 100644
+--- a/fs/gfs2/bmap.c
++++ b/fs/gfs2/bmap.c
+@@ -33,6 +33,7 @@
+  * keep it small.
+  */
+ struct metapath {
++	struct buffer_head *mp_bh[GFS2_MAX_META_HEIGHT];
+ 	__u16 mp_list[GFS2_MAX_META_HEIGHT];
+ };
+ 
+@@ -135,9 +136,10 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
+ 		/* Get a free block, fill it with the stuffed data,
+ 		   and write it out to disk */
+ 
++		unsigned int n = 1;
++		block = gfs2_alloc_block(ip, &n);
+ 		if (isdir) {
+-			block = gfs2_alloc_meta(ip);
+-
++			gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1);
+ 			error = gfs2_dir_get_new_buffer(ip, block, &bh);
+ 			if (error)
+ 				goto out_brelse;
+@@ -145,8 +147,6 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
+ 					      dibh, sizeof(struct gfs2_dinode));
+ 			brelse(bh);
+ 		} else {
+-			block = gfs2_alloc_data(ip);
+-
+ 			error = gfs2_unstuffer_page(ip, dibh, block, page);
+ 			if (error)
+ 				goto out_brelse;
+@@ -161,12 +161,11 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
+ 
+ 	if (ip->i_di.di_size) {
+ 		*(__be64 *)(di + 1) = cpu_to_be64(block);
+-		ip->i_di.di_blocks++;
+-		gfs2_set_inode_blocks(&ip->i_inode);
+-		di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
++		gfs2_add_inode_blocks(&ip->i_inode, 1);
++		di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
+ 	}
+ 
+-	ip->i_di.di_height = 1;
++	ip->i_height = 1;
+ 	di->di_height = cpu_to_be16(1);
+ 
+ out_brelse:
+@@ -176,114 +175,13 @@ out:
+ 	return error;
+ }
+ 
+-/**
+- * calc_tree_height - Calculate the height of a metadata tree
+- * @ip: The GFS2 inode
+- * @size: The proposed size of the file
+- *
+- * Work out how tall a metadata tree needs to be in order to accommodate a
+- * file of a particular size. If size is less than the current size of
+- * the inode, then the current size of the inode is used instead of the
+- * supplied one.
+- *
+- * Returns: the height the tree should be
+- */
+-
+-static unsigned int calc_tree_height(struct gfs2_inode *ip, u64 size)
+-{
+-	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+-	u64 *arr;
+-	unsigned int max, height;
+-
+-	if (ip->i_di.di_size > size)
+-		size = ip->i_di.di_size;
+-
+-	if (gfs2_is_dir(ip)) {
+-		arr = sdp->sd_jheightsize;
+-		max = sdp->sd_max_jheight;
+-	} else {
+-		arr = sdp->sd_heightsize;
+-		max = sdp->sd_max_height;
+-	}
+-
+-	for (height = 0; height < max; height++)
+-		if (arr[height] >= size)
+-			break;
+-
+-	return height;
+-}
+-
+-/**
+- * build_height - Build a metadata tree of the requested height
+- * @ip: The GFS2 inode
+- * @height: The height to build to
+- *
+- *
+- * Returns: errno
+- */
+-
+-static int build_height(struct inode *inode, unsigned height)
+-{
+-	struct gfs2_inode *ip = GFS2_I(inode);
+-	unsigned new_height = height - ip->i_di.di_height;
+-	struct buffer_head *dibh;
+-	struct buffer_head *blocks[GFS2_MAX_META_HEIGHT];
+-	struct gfs2_dinode *di;
+-	int error;
+-	__be64 *bp;
+-	u64 bn;
+-	unsigned n;
+-
+-	if (height <= ip->i_di.di_height)
+-		return 0;
+-
+-	error = gfs2_meta_inode_buffer(ip, &dibh);
+-	if (error)
+-		return error;
+-
+-	for(n = 0; n < new_height; n++) {
+-		bn = gfs2_alloc_meta(ip);
+-		blocks[n] = gfs2_meta_new(ip->i_gl, bn);
+-		gfs2_trans_add_bh(ip->i_gl, blocks[n], 1);
+-	}
+-
+-	n = 0;
+-	bn = blocks[0]->b_blocknr;
+-	if (new_height > 1) {
+-		for(; n < new_height-1; n++) {
+-			gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN,
+-					  GFS2_FORMAT_IN);
+-			gfs2_buffer_clear_tail(blocks[n],
+-					       sizeof(struct gfs2_meta_header));
+-			bp = (__be64 *)(blocks[n]->b_data +
+-				     sizeof(struct gfs2_meta_header));
+-			*bp = cpu_to_be64(blocks[n+1]->b_blocknr);
+-			brelse(blocks[n]);
+-			blocks[n] = NULL;
+-		}
+-	}
+-	gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN, GFS2_FORMAT_IN);
+-	gfs2_buffer_copy_tail(blocks[n], sizeof(struct gfs2_meta_header),
+-			      dibh, sizeof(struct gfs2_dinode));
+-	brelse(blocks[n]);
+-	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+-	di = (struct gfs2_dinode *)dibh->b_data;
+-	gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
+-	*(__be64 *)(di + 1) = cpu_to_be64(bn);
+-	ip->i_di.di_height += new_height;
+-	ip->i_di.di_blocks += new_height;
+-	gfs2_set_inode_blocks(&ip->i_inode);
+-	di->di_height = cpu_to_be16(ip->i_di.di_height);
+-	di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
+-	brelse(dibh);
+-	return error;
+-}
+ 
+ /**
+  * find_metapath - Find path through the metadata tree
+- * @ip: The inode pointer
++ * @sdp: The superblock
+  * @mp: The metapath to return the result in
+  * @block: The disk block to look up
++ * @height: The pre-calculated height of the metadata tree
+  *
+  *   This routine returns a struct metapath structure that defines a path
+  *   through the metadata of inode "ip" to get to block "block".
+@@ -338,21 +236,29 @@ static int build_height(struct inode *inode, unsigned height)
+  *
+  */
+ 
+-static void find_metapath(struct gfs2_inode *ip, u64 block,
+-			  struct metapath *mp)
++static void find_metapath(const struct gfs2_sbd *sdp, u64 block,
++			  struct metapath *mp, unsigned int height)
+ {
+-	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+-	u64 b = block;
+ 	unsigned int i;
+ 
+-	for (i = ip->i_di.di_height; i--;)
+-		mp->mp_list[i] = do_div(b, sdp->sd_inptrs);
++	for (i = height; i--;)
++		mp->mp_list[i] = do_div(block, sdp->sd_inptrs);
++
++}
+ 
++static inline unsigned int zero_metapath_length(const struct metapath *mp,
++						unsigned height)
++{
++	unsigned int i;
++	for (i = 0; i < height - 1; i++) {
++		if (mp->mp_list[i] != 0)
++			return i;
++	}
++	return height;
+ }
+ 
+ /**
+  * metapointer - Return pointer to start of metadata in a buffer
+- * @bh: The buffer
+  * @height: The metadata height (0 = dinode)
+  * @mp: The metapath
+  *
+@@ -361,93 +267,302 @@ static void find_metapath(struct gfs2_inode *ip, u64 block,
+  * metadata tree.
+  */
+ 
+-static inline __be64 *metapointer(struct buffer_head *bh, int *boundary,
+-			       unsigned int height, const struct metapath *mp)
++static inline __be64 *metapointer(unsigned int height, const struct metapath *mp)
+ {
++	struct buffer_head *bh = mp->mp_bh[height];
+ 	unsigned int head_size = (height > 0) ?
+ 		sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
+-	__be64 *ptr;
+-	*boundary = 0;
+-	ptr = ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
+-	if (ptr + 1 == (__be64 *)(bh->b_data + bh->b_size))
+-		*boundary = 1;
+-	return ptr;
++	return ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
+ }
+ 
+ /**
+- * lookup_block - Get the next metadata block in metadata tree
+- * @ip: The GFS2 inode
+- * @bh: Buffer containing the pointers to metadata blocks
+- * @height: The height of the tree (0 = dinode)
++ * lookup_metapath - Walk the metadata tree to a specific point
++ * @ip: The inode
+  * @mp: The metapath
+- * @create: Non-zero if we may create a new meatdata block
+- * @new: Used to indicate if we did create a new metadata block
+- * @block: the returned disk block number
+  *
+- * Given a metatree, complete to a particular height, checks to see if the next
+- * height of the tree exists. If not the next height of the tree is created.
+- * The block number of the next height of the metadata tree is returned.
++ * Assumes that the inode's buffer has already been looked up and
++ * hooked onto mp->mp_bh[0] and that the metapath has been initialised
++ * by find_metapath().
++ *
++ * If this function encounters part of the tree which has not been
++ * allocated, it returns the current height of the tree at the point
++ * at which it found the unallocated block. Blocks which are found are
++ * added to the mp->mp_bh[] list.
+  *
++ * Returns: error or height of metadata tree
+  */
+ 
+-static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
+-			unsigned int height, struct metapath *mp, int create,
+-			int *new, u64 *block)
++static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp)
+ {
+-	int boundary;
+-	__be64 *ptr = metapointer(bh, &boundary, height, mp);
++	unsigned int end_of_metadata = ip->i_height - 1;
++	unsigned int x;
++	__be64 *ptr;
++	u64 dblock;
++	int ret;
+ 
+-	if (*ptr) {
+-		*block = be64_to_cpu(*ptr);
+-		return boundary;
+-	}
++	for (x = 0; x < end_of_metadata; x++) {
++		ptr = metapointer(x, mp);
++		dblock = be64_to_cpu(*ptr);
++		if (!dblock)
++			return x + 1;
+ 
+-	*block = 0;
++		ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, 0, &mp->mp_bh[x+1]);
++		if (ret)
++			return ret;
++	}
+ 
+-	if (!create)
+-		return 0;
++	return ip->i_height;
++}
+ 
+-	if (height == ip->i_di.di_height - 1 && !gfs2_is_dir(ip))
+-		*block = gfs2_alloc_data(ip);
+-	else
+-		*block = gfs2_alloc_meta(ip);
++static inline void release_metapath(struct metapath *mp)
++{
++	int i;
+ 
+-	gfs2_trans_add_bh(ip->i_gl, bh, 1);
++	for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) {
++		if (mp->mp_bh[i] == NULL)
++			break;
++		brelse(mp->mp_bh[i]);
++	}
++}
+ 
+-	*ptr = cpu_to_be64(*block);
+-	ip->i_di.di_blocks++;
+-	gfs2_set_inode_blocks(&ip->i_inode);
++/**
++ * gfs2_extent_length - Returns length of an extent of blocks
++ * @start: Start of the buffer
++ * @len: Length of the buffer in bytes
++ * @ptr: Current position in the buffer
++ * @limit: Max extent length to return (0 = unlimited)
++ * @eob: Set to 1 if we hit "end of block"
++ *
++ * If the first block is zero (unallocated) it will return the number of
++ * unallocated blocks in the extent, otherwise it will return the number
++ * of contiguous blocks in the extent.
++ *
++ * Returns: The length of the extent (minimum of one block)
++ */
+ 
+-	*new = 1;
+-	return 0;
++static inline unsigned int gfs2_extent_length(void *start, unsigned int len, __be64 *ptr, unsigned limit, int *eob)
++{
++	const __be64 *end = (start + len);
++	const __be64 *first = ptr;
++	u64 d = be64_to_cpu(*ptr);
++
++	*eob = 0;
++	do {
++		ptr++;
++		if (ptr >= end)
++			break;
++		if (limit && --limit == 0)
++			break;
++		if (d)
++			d++;
++	} while(be64_to_cpu(*ptr) == d);
++	if (ptr >= end)
++		*eob = 1;
++	return (ptr - first);
+ }
+ 
+-static inline void bmap_lock(struct inode *inode, int create)
++static inline void bmap_lock(struct gfs2_inode *ip, int create)
+ {
+-	struct gfs2_inode *ip = GFS2_I(inode);
+ 	if (create)
+ 		down_write(&ip->i_rw_mutex);
+ 	else
+ 		down_read(&ip->i_rw_mutex);
+ }
+ 
+-static inline void bmap_unlock(struct inode *inode, int create)
++static inline void bmap_unlock(struct gfs2_inode *ip, int create)
+ {
+-	struct gfs2_inode *ip = GFS2_I(inode);
+ 	if (create)
+ 		up_write(&ip->i_rw_mutex);
+ 	else
+ 		up_read(&ip->i_rw_mutex);
+ }
+ 
++static inline __be64 *gfs2_indirect_init(struct metapath *mp,
++					 struct gfs2_glock *gl, unsigned int i,
++					 unsigned offset, u64 bn)
++{
++	__be64 *ptr = (__be64 *)(mp->mp_bh[i - 1]->b_data +
++		       ((i > 1) ? sizeof(struct gfs2_meta_header) :
++				 sizeof(struct gfs2_dinode)));
++	BUG_ON(i < 1);
++	BUG_ON(mp->mp_bh[i] != NULL);
++	mp->mp_bh[i] = gfs2_meta_new(gl, bn);
++	gfs2_trans_add_bh(gl, mp->mp_bh[i], 1);
++	gfs2_metatype_set(mp->mp_bh[i], GFS2_METATYPE_IN, GFS2_FORMAT_IN);
++	gfs2_buffer_clear_tail(mp->mp_bh[i], sizeof(struct gfs2_meta_header));
++	ptr += offset;
++	*ptr = cpu_to_be64(bn);
++	return ptr;
++}
++
++enum alloc_state {
++	ALLOC_DATA = 0,
++	ALLOC_GROW_DEPTH = 1,
++	ALLOC_GROW_HEIGHT = 2,
++	/* ALLOC_UNSTUFF = 3,   TBD and rather complicated */
++};
++
++/**
++ * gfs2_bmap_alloc - Build a metadata tree of the requested height
++ * @inode: The GFS2 inode
++ * @lblock: The logical starting block of the extent
++ * @bh_map: This is used to return the mapping details
++ * @mp: The metapath
++ * @sheight: The starting height (i.e. whats already mapped)
++ * @height: The height to build to
++ * @maxlen: The max number of data blocks to alloc
++ *
++ * In this routine we may have to alloc:
++ *   i) Indirect blocks to grow the metadata tree height
++ *  ii) Indirect blocks to fill in lower part of the metadata tree
++ * iii) Data blocks
++ *
++ * The function is in two parts. The first part works out the total
++ * number of blocks which we need. The second part does the actual
++ * allocation asking for an extent at a time (if enough contiguous free
++ * blocks are available, there will only be one request per bmap call)
++ * and uses the state machine to initialise the blocks in order.
++ *
++ * Returns: errno on error
++ */
++
++static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
++			   struct buffer_head *bh_map, struct metapath *mp,
++			   const unsigned int sheight,
++			   const unsigned int height,
++			   const unsigned int maxlen)
++{
++	struct gfs2_inode *ip = GFS2_I(inode);
++	struct gfs2_sbd *sdp = GFS2_SB(inode);
++	struct buffer_head *dibh = mp->mp_bh[0];
++	u64 bn, dblock = 0;
++	unsigned n, i, blks, alloced = 0, iblks = 0, zmpl = 0;
++	unsigned dblks = 0;
++	unsigned ptrs_per_blk;
++	const unsigned end_of_metadata = height - 1;
++	int eob = 0;
++	enum alloc_state state;
++	__be64 *ptr;
++	__be64 zero_bn = 0;
++
++	BUG_ON(sheight < 1);
++	BUG_ON(dibh == NULL);
++
++	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
++
++	if (height == sheight) {
++		struct buffer_head *bh;
++		/* Bottom indirect block exists, find unalloced extent size */
++		ptr = metapointer(end_of_metadata, mp);
++		bh = mp->mp_bh[end_of_metadata];
++		dblks = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen,
++					   &eob);
++		BUG_ON(dblks < 1);
++		state = ALLOC_DATA;
++	} else {
++		/* Need to allocate indirect blocks */
++		ptrs_per_blk = height > 1 ? sdp->sd_inptrs : sdp->sd_diptrs;
++		dblks = min(maxlen, ptrs_per_blk - mp->mp_list[end_of_metadata]);
++		if (height == ip->i_height) {
++			/* Writing into existing tree, extend tree down */
++			iblks = height - sheight;
++			state = ALLOC_GROW_DEPTH;
++		} else {
++			/* Building up tree height */
++			state = ALLOC_GROW_HEIGHT;
++			iblks = height - ip->i_height;
++			zmpl = zero_metapath_length(mp, height);
++			iblks -= zmpl;
++			iblks += height;
++		}
++	}
++
++	/* start of the second part of the function (state machine) */
++
++	blks = dblks + iblks;
++	i = sheight;
++	do {
++		n = blks - alloced;
++		bn = gfs2_alloc_block(ip, &n);
++		alloced += n;
++		if (state != ALLOC_DATA || gfs2_is_jdata(ip))
++			gfs2_trans_add_unrevoke(sdp, bn, n);
++		switch (state) {
++		/* Growing height of tree */
++		case ALLOC_GROW_HEIGHT:
++			if (i == 1) {
++				ptr = (__be64 *)(dibh->b_data +
++						 sizeof(struct gfs2_dinode));
++				zero_bn = *ptr;
++			}
++			for (; i - 1 < height - ip->i_height && n > 0; i++, n--)
++				gfs2_indirect_init(mp, ip->i_gl, i, 0, bn++);
++			if (i - 1 == height - ip->i_height) {
++				i--;
++				gfs2_buffer_copy_tail(mp->mp_bh[i],
++						sizeof(struct gfs2_meta_header),
++						dibh, sizeof(struct gfs2_dinode));
++				gfs2_buffer_clear_tail(dibh,
++						sizeof(struct gfs2_dinode) +
++						sizeof(__be64));
++				ptr = (__be64 *)(mp->mp_bh[i]->b_data +
++					sizeof(struct gfs2_meta_header));
++				*ptr = zero_bn;
++				state = ALLOC_GROW_DEPTH;
++				for(i = zmpl; i < height; i++) {
++					if (mp->mp_bh[i] == NULL)
++						break;
++					brelse(mp->mp_bh[i]);
++					mp->mp_bh[i] = NULL;
++				}
++				i = zmpl;
++			}
++			if (n == 0)
++				break;
++		/* Branching from existing tree */
++		case ALLOC_GROW_DEPTH:
++			if (i > 1 && i < height)
++				gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i-1], 1);
++			for (; i < height && n > 0; i++, n--)
++				gfs2_indirect_init(mp, ip->i_gl, i,
++						   mp->mp_list[i-1], bn++);
++			if (i == height)
++				state = ALLOC_DATA;
++			if (n == 0)
++				break;
++		/* Tree complete, adding data blocks */
++		case ALLOC_DATA:
++			BUG_ON(n > dblks);
++			BUG_ON(mp->mp_bh[end_of_metadata] == NULL);
++			gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[end_of_metadata], 1);
++			dblks = n;
++			ptr = metapointer(end_of_metadata, mp);
++			dblock = bn;
++			while (n-- > 0)
++				*ptr++ = cpu_to_be64(bn++);
++			break;
++		}
++	} while (state != ALLOC_DATA);
++
++	ip->i_height = height;
++	gfs2_add_inode_blocks(&ip->i_inode, alloced);
++	gfs2_dinode_out(ip, mp->mp_bh[0]->b_data);
++	map_bh(bh_map, inode->i_sb, dblock);
++	bh_map->b_size = dblks << inode->i_blkbits;
++	set_buffer_new(bh_map);
++	return 0;
++}
++
+ /**
+  * gfs2_block_map - Map a block from an inode to a disk block
+  * @inode: The inode
+  * @lblock: The logical block number
+  * @bh_map: The bh to be mapped
++ * @create: True if its ok to alloc blocks to satify the request
+  *
+- * Find the block number on the current device which corresponds to an
+- * inode's block. If the block had to be created, "new" will be set.
++ * Sets buffer_mapped() if successful, sets buffer_boundary() if a
++ * read of metadata will be required before the next block can be
++ * mapped. Sets buffer_new() if new blocks were allocated.
+  *
+  * Returns: errno
+  */
+@@ -457,97 +572,78 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
+ {
+ 	struct gfs2_inode *ip = GFS2_I(inode);
+ 	struct gfs2_sbd *sdp = GFS2_SB(inode);
+-	struct buffer_head *bh;
+-	unsigned int bsize;
+-	unsigned int height;
+-	unsigned int end_of_metadata;
+-	unsigned int x;
+-	int error = 0;
+-	int new = 0;
+-	u64 dblock = 0;
+-	int boundary;
+-	unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
+-	struct metapath mp;
++	unsigned int bsize = sdp->sd_sb.sb_bsize;
++	const unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
++	const u64 *arr = sdp->sd_heightsize;
++	__be64 *ptr;
+ 	u64 size;
+-	struct buffer_head *dibh = NULL;
++	struct metapath mp;
++	int ret;
++	int eob;
++	unsigned int len;
++	struct buffer_head *bh;
++	u8 height;
+ 
+ 	BUG_ON(maxlen == 0);
+ 
+-	if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
+-		return 0;
+-
+-	bmap_lock(inode, create);
++	memset(mp.mp_bh, 0, sizeof(mp.mp_bh));
++	bmap_lock(ip, create);
+ 	clear_buffer_mapped(bh_map);
+ 	clear_buffer_new(bh_map);
+ 	clear_buffer_boundary(bh_map);
+-	bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize;
+-	size = (lblock + 1) * bsize;
+-
+-	if (size > ip->i_di.di_size) {
+-		height = calc_tree_height(ip, size);
+-		if (ip->i_di.di_height < height) {
+-			if (!create)
+-				goto out_ok;
+-	
+-			error = build_height(inode, height);
+-			if (error)
+-				goto out_fail;
+-		}
++	if (gfs2_is_dir(ip)) {
++		bsize = sdp->sd_jbsize;
++		arr = sdp->sd_jheightsize;
+ 	}
+ 
+-	find_metapath(ip, lblock, &mp);
+-	end_of_metadata = ip->i_di.di_height - 1;
+-	error = gfs2_meta_inode_buffer(ip, &bh);
+-	if (error)
+-		goto out_fail;
+-	dibh = bh;
+-	get_bh(dibh);
++	ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]);
++	if (ret)
++		goto out;
+ 
+-	for (x = 0; x < end_of_metadata; x++) {
+-		lookup_block(ip, bh, x, &mp, create, &new, &dblock);
+-		brelse(bh);
+-		if (!dblock)
+-			goto out_ok;
++	height = ip->i_height;
++	size = (lblock + 1) * bsize;
++	while (size > arr[height])
++		height++;
++	find_metapath(sdp, lblock, &mp, height);
++	ret = 1;
++	if (height > ip->i_height || gfs2_is_stuffed(ip))
++		goto do_alloc;
++	ret = lookup_metapath(ip, &mp);
++	if (ret < 0)
++		goto out;
++	if (ret != ip->i_height)
++		goto do_alloc;
++	ptr = metapointer(ip->i_height - 1, &mp);
++	if (*ptr == 0)
++		goto do_alloc;
++	map_bh(bh_map, inode->i_sb, be64_to_cpu(*ptr));
++	bh = mp.mp_bh[ip->i_height - 1];
++	len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, &eob);
++	bh_map->b_size = (len << inode->i_blkbits);
++	if (eob)
++		set_buffer_boundary(bh_map);
++	ret = 0;
++out:
++	release_metapath(&mp);
++	bmap_unlock(ip, create);
++	return ret;
+ 
+-		error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh);
+-		if (error)
+-			goto out_fail;
++do_alloc:
++	/* All allocations are done here, firstly check create flag */
++	if (!create) {
++		BUG_ON(gfs2_is_stuffed(ip));
++		ret = 0;
++		goto out;
+ 	}
+ 
+-	boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock);
+-	if (dblock) {
+-		map_bh(bh_map, inode->i_sb, dblock);
+-		if (boundary)
+-			set_buffer_boundary(bh_map);
+-		if (new) {
+-			gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+-			gfs2_dinode_out(ip, dibh->b_data);
+-			set_buffer_new(bh_map);
+-			goto out_brelse;
+-		}
+-		while(--maxlen && !buffer_boundary(bh_map)) {
+-			u64 eblock;
+-
+-			mp.mp_list[end_of_metadata]++;
+-			boundary = lookup_block(ip, bh, end_of_metadata, &mp, 0, &new, &eblock);
+-			if (eblock != ++dblock)
+-				break;
+-			bh_map->b_size += (1 << inode->i_blkbits);
+-			if (boundary)
+-				set_buffer_boundary(bh_map);
+-		}
+-	}
+-out_brelse:
+-	brelse(bh);
+-out_ok:
+-	error = 0;
+-out_fail:
+-	if (dibh)
+-		brelse(dibh);
+-	bmap_unlock(inode, create);
+-	return error;
++	/* At this point ret is the tree depth of already allocated blocks */
++	ret = gfs2_bmap_alloc(inode, lblock, bh_map, &mp, ret, height, maxlen);
++	goto out;
+ }
+ 
++/*
++ * Deprecated: do not use in new code
++ */
+ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
+ {
+ 	struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 };
+@@ -558,7 +654,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
+ 	BUG_ON(!dblock);
+ 	BUG_ON(!new);
+ 
+-	bh.b_size = 1 << (inode->i_blkbits + 5);
++	bh.b_size = 1 << (inode->i_blkbits + (create ? 0 : 5));
+ 	ret = gfs2_block_map(inode, lblock, &bh, create);
+ 	*extlen = bh.b_size >> inode->i_blkbits;
+ 	*dblock = bh.b_blocknr;
+@@ -621,7 +717,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
+ 	if (error)
+ 		goto out;
+ 
+-	if (height < ip->i_di.di_height - 1)
++	if (height < ip->i_height - 1)
+ 		for (; top < bottom; top++, first = 0) {
+ 			if (!*top)
+ 				continue;
+@@ -679,7 +775,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
+ 		sm->sm_first = 0;
+ 	}
+ 
+-	metadata = (height != ip->i_di.di_height - 1);
++	metadata = (height != ip->i_height - 1);
+ 	if (metadata)
+ 		revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
+ 
+@@ -713,7 +809,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
+ 	else
+ 		goto out; /* Nothing to do */
+ 
+-	gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
++	gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
+ 
+ 	for (x = 0; x < rlist.rl_rgrps; x++) {
+ 		struct gfs2_rgrpd *rgd;
+@@ -760,10 +856,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
+ 		}
+ 
+ 		*p = 0;
+-		if (!ip->i_di.di_blocks)
+-			gfs2_consist_inode(ip);
+-		ip->i_di.di_blocks--;
+-		gfs2_set_inode_blocks(&ip->i_inode);
++		gfs2_add_inode_blocks(&ip->i_inode, -1);
+ 	}
+ 	if (bstart) {
+ 		if (metadata)
+@@ -804,19 +897,16 @@ 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;
+-	unsigned int h;
+ 	int error;
+ 
+ 	al = gfs2_alloc_get(ip);
++	if (!al)
++		return -ENOMEM;
+ 
+-	error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++	error = gfs2_quota_lock_check(ip);
+ 	if (error)
+ 		goto out;
+ 
+-	error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
+-	if (error)
+-		goto out_gunlock_q;
+-
+ 	al->al_requested = sdp->sd_max_height + RES_DATA;
+ 
+ 	error = gfs2_inplace_reserve(ip);
+@@ -829,34 +919,25 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
+ 	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_end_trans;
+-		}
+-
+-		h = calc_tree_height(ip, size);
+-		if (ip->i_di.di_height < h) {
+-			down_write(&ip->i_rw_mutex);
+-			error = build_height(&ip->i_inode, h);
+-			up_write(&ip->i_rw_mutex);
+-			if (error)
+-				goto out_end_trans;
++				goto out_brelse;
+ 		}
+ 	}
+ 
+ 	ip->i_di.di_size = size;
+ 	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+-
+-	error = gfs2_meta_inode_buffer(ip, &dibh);
+-	if (error)
+-		goto out_end_trans;
+-
+ 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+ 	gfs2_dinode_out(ip, dibh->b_data);
+-	brelse(dibh);
+ 
++out_brelse:
++	brelse(dibh);
+ out_end_trans:
+ 	gfs2_trans_end(sdp);
+ out_ipres:
+@@ -986,7 +1067,8 @@ out:
+ 
+ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
+ {
+-	unsigned int height = ip->i_di.di_height;
++	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
++	unsigned int height = ip->i_height;
+ 	u64 lblock;
+ 	struct metapath mp;
+ 	int error;
+@@ -994,10 +1076,11 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
+ 	if (!size)
+ 		lblock = 0;
+ 	else
+-		lblock = (size - 1) >> GFS2_SB(&ip->i_inode)->sd_sb.sb_bsize_shift;
++		lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift;
+ 
+-	find_metapath(ip, lblock, &mp);
+-	gfs2_alloc_get(ip);
++	find_metapath(sdp, lblock, &mp, ip->i_height);
++	if (!gfs2_alloc_get(ip))
++		return -ENOMEM;
+ 
+ 	error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ 	if (error)
+@@ -1037,10 +1120,8 @@ static int trunc_end(struct gfs2_inode *ip)
+ 		goto out;
+ 
+ 	if (!ip->i_di.di_size) {
+-		ip->i_di.di_height = 0;
+-		ip->i_di.di_goal_meta =
+-			ip->i_di.di_goal_data =
+-			ip->i_no_addr;
++		ip->i_height = 0;
++		ip->i_goal = ip->i_no_addr;
+ 		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
+ 	}
+ 	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+@@ -1197,10 +1278,9 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
+ 			      unsigned int len, int *alloc_required)
+ {
+ 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+-	u64 lblock, lblock_stop, dblock;
+-	u32 extlen;
+-	int new = 0;
+-	int error = 0;
++	struct buffer_head bh;
++	unsigned int shift;
++	u64 lblock, lblock_stop, size;
+ 
+ 	*alloc_required = 0;
+ 
+@@ -1214,6 +1294,8 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
+ 		return 0;
+ 	}
+ 
++	*alloc_required = 1;
++	shift = sdp->sd_sb.sb_bsize_shift;
+ 	if (gfs2_is_dir(ip)) {
+ 		unsigned int bsize = sdp->sd_jbsize;
+ 		lblock = offset;
+@@ -1221,27 +1303,25 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
+ 		lblock_stop = offset + len + bsize - 1;
+ 		do_div(lblock_stop, bsize);
+ 	} else {
+-		unsigned int shift = sdp->sd_sb.sb_bsize_shift;
+ 		u64 end_of_file = (ip->i_di.di_size + 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) {
+-			*alloc_required = 1;
++		if (lblock_stop > end_of_file)
+ 			return 0;
+-		}
+ 	}
+ 
+-	for (; lblock < lblock_stop; lblock += extlen) {
+-		error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen);
+-		if (error)
+-			return error;
+-
+-		if (!dblock) {
+-			*alloc_required = 1;
++	size = (lblock_stop - lblock) << shift;
++	do {
++		bh.b_state = 0;
++		bh.b_size = size;
++		gfs2_block_map(&ip->i_inode, lblock, &bh, 0);
++		if (!buffer_mapped(&bh))
+ 			return 0;
+-		}
+-	}
++		size -= bh.b_size;
++		lblock += (bh.b_size >> ip->i_inode.i_blkbits);
++	} while(size > 0);
+ 
++	*alloc_required = 0;
+ 	return 0;
+ }
+ 
+diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
+index c347095..eed040d 100644
+--- a/fs/gfs2/dir.c
++++ b/fs/gfs2/dir.c
+@@ -159,6 +159,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
+ 	unsigned int o;
+ 	int copied = 0;
+ 	int error = 0;
++	int new = 0;
+ 
+ 	if (!size)
+ 		return 0;
+@@ -183,7 +184,6 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
+ 	while (copied < size) {
+ 		unsigned int amount;
+ 		struct buffer_head *bh;
+-		int new = 0;
+ 
+ 		amount = size - copied;
+ 		if (amount > sdp->sd_sb.sb_bsize - o)
+@@ -757,7 +757,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
+ 
+ 	if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
+ 		struct gfs2_leaf *leaf;
+-		unsigned hsize = 1 << ip->i_di.di_depth;
++		unsigned hsize = 1 << ip->i_depth;
+ 		unsigned index;
+ 		u64 ln;
+ 		if (hsize * sizeof(u64) != ip->i_di.di_size) {
+@@ -765,7 +765,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
+ 			return ERR_PTR(-EIO);
+ 		}
+ 
+-		index = name->hash >> (32 - ip->i_di.di_depth);
++		index = name->hash >> (32 - ip->i_depth);
+ 		error = get_first_leaf(ip, index, &bh);
+ 		if (error)
+ 			return ERR_PTR(error);
+@@ -803,14 +803,15 @@ got_dent:
+ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth)
+ {
+ 	struct gfs2_inode *ip = GFS2_I(inode);
+-	u64 bn = gfs2_alloc_meta(ip);
++	unsigned int n = 1;
++	u64 bn = gfs2_alloc_block(ip, &n);
+ 	struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn);
+ 	struct gfs2_leaf *leaf;
+ 	struct gfs2_dirent *dent;
+ 	struct qstr name = { .name = "", .len = 0, .hash = 0 };
+ 	if (!bh)
+ 		return NULL;
+-
++	gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, 1);
+ 	gfs2_trans_add_bh(ip->i_gl, bh, 1);
+ 	gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF);
+ 	leaf = (struct gfs2_leaf *)bh->b_data;
+@@ -905,12 +906,11 @@ static int dir_make_exhash(struct inode *inode)
+ 		*lp = cpu_to_be64(bn);
+ 
+ 	dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2;
+-	dip->i_di.di_blocks++;
+-	gfs2_set_inode_blocks(&dip->i_inode);
++	gfs2_add_inode_blocks(&dip->i_inode, 1);
+ 	dip->i_di.di_flags |= GFS2_DIF_EXHASH;
+ 
+ 	for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
+-	dip->i_di.di_depth = y;
++	dip->i_depth = y;
+ 
+ 	gfs2_dinode_out(dip, dibh->b_data);
+ 
+@@ -941,7 +941,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ 	int x, moved = 0;
+ 	int error;
+ 
+-	index = name->hash >> (32 - dip->i_di.di_depth);
++	index = name->hash >> (32 - dip->i_depth);
+ 	error = get_leaf_nr(dip, index, &leaf_no);
+ 	if (error)
+ 		return error;
+@@ -952,7 +952,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ 		return error;
+ 
+ 	oleaf = (struct gfs2_leaf *)obh->b_data;
+-	if (dip->i_di.di_depth == be16_to_cpu(oleaf->lf_depth)) {
++	if (dip->i_depth == be16_to_cpu(oleaf->lf_depth)) {
+ 		brelse(obh);
+ 		return 1; /* can't split */
+ 	}
+@@ -967,10 +967,10 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ 	bn = nbh->b_blocknr;
+ 
+ 	/*  Compute the start and len of leaf pointers in the hash table.  */
+-	len = 1 << (dip->i_di.di_depth - be16_to_cpu(oleaf->lf_depth));
++	len = 1 << (dip->i_depth - be16_to_cpu(oleaf->lf_depth));
+ 	half_len = len >> 1;
+ 	if (!half_len) {
+-		printk(KERN_WARNING "di_depth %u lf_depth %u index %u\n", dip->i_di.di_depth, be16_to_cpu(oleaf->lf_depth), index);
++		printk(KERN_WARNING "i_depth %u lf_depth %u index %u\n", dip->i_depth, be16_to_cpu(oleaf->lf_depth), index);
+ 		gfs2_consist_inode(dip);
+ 		error = -EIO;
+ 		goto fail_brelse;
+@@ -997,7 +997,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ 	kfree(lp);
+ 
+ 	/*  Compute the divider  */
+-	divider = (start + half_len) << (32 - dip->i_di.di_depth);
++	divider = (start + half_len) << (32 - dip->i_depth);
+ 
+ 	/*  Copy the entries  */
+ 	dirent_first(dip, obh, &dent);
+@@ -1021,13 +1021,13 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ 
+ 			new->de_inum = dent->de_inum; /* No endian worries */
+ 			new->de_type = dent->de_type; /* No endian worries */
+-			nleaf->lf_entries = cpu_to_be16(be16_to_cpu(nleaf->lf_entries)+1);
++			be16_add_cpu(&nleaf->lf_entries, 1);
+ 
+ 			dirent_del(dip, obh, prev, dent);
+ 
+ 			if (!oleaf->lf_entries)
+ 				gfs2_consist_inode(dip);
+-			oleaf->lf_entries = cpu_to_be16(be16_to_cpu(oleaf->lf_entries)-1);
++			be16_add_cpu(&oleaf->lf_entries, -1);
+ 
+ 			if (!prev)
+ 				prev = dent;
+@@ -1044,8 +1044,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ 	error = gfs2_meta_inode_buffer(dip, &dibh);
+ 	if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) {
+ 		gfs2_trans_add_bh(dip->i_gl, dibh, 1);
+-		dip->i_di.di_blocks++;
+-		gfs2_set_inode_blocks(&dip->i_inode);
++		gfs2_add_inode_blocks(&dip->i_inode, 1);
+ 		gfs2_dinode_out(dip, dibh->b_data);
+ 		brelse(dibh);
+ 	}
+@@ -1082,7 +1081,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
+ 	int x;
+ 	int error = 0;
+ 
+-	hsize = 1 << dip->i_di.di_depth;
++	hsize = 1 << dip->i_depth;
+ 	if (hsize * sizeof(u64) != dip->i_di.di_size) {
+ 		gfs2_consist_inode(dip);
+ 		return -EIO;
+@@ -1090,7 +1089,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
+ 
+ 	/*  Allocate both the "from" and "to" buffers in one big chunk  */
+ 
+-	buf = kcalloc(3, sdp->sd_hash_bsize, GFP_KERNEL | __GFP_NOFAIL);
++	buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS | __GFP_NOFAIL);
+ 
+ 	for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
+ 		error = gfs2_dir_read_data(dip, (char *)buf,
+@@ -1125,7 +1124,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
+ 
+ 	error = gfs2_meta_inode_buffer(dip, &dibh);
+ 	if (!gfs2_assert_withdraw(sdp, !error)) {
+-		dip->i_di.di_depth++;
++		dip->i_depth++;
+ 		gfs2_dinode_out(dip, dibh->b_data);
+ 		brelse(dibh);
+ 	}
+@@ -1370,16 +1369,16 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
+ 	int error = 0;
+ 	unsigned depth = 0;
+ 
+-	hsize = 1 << dip->i_di.di_depth;
++	hsize = 1 << dip->i_depth;
+ 	if (hsize * sizeof(u64) != dip->i_di.di_size) {
+ 		gfs2_consist_inode(dip);
+ 		return -EIO;
+ 	}
+ 
+ 	hash = gfs2_dir_offset2hash(*offset);
+-	index = hash >> (32 - dip->i_di.di_depth);
++	index = hash >> (32 - dip->i_depth);
+ 
+-	lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL);
++	lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
+ 	if (!lp)
+ 		return -ENOMEM;
+ 
+@@ -1405,7 +1404,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
+ 		if (error)
+ 			break;
+ 
+-		len = 1 << (dip->i_di.di_depth - depth);
++		len = 1 << (dip->i_depth - depth);
+ 		index = (index & ~(len - 1)) + len;
+ 	}
+ 
+@@ -1444,7 +1443,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
+ 
+ 	error = -ENOMEM;
+ 	/* 96 is max number of dirents which can be stuffed into an inode */
+-	darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_KERNEL);
++	darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_NOFS);
+ 	if (darr) {
+ 		g.pdent = darr;
+ 		g.offset = 0;
+@@ -1549,7 +1548,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
+ 	u32 index;
+ 	u64 bn;
+ 
+-	index = name->hash >> (32 - ip->i_di.di_depth);
++	index = name->hash >> (32 - ip->i_depth);
+ 	error = get_first_leaf(ip, index, &obh);
+ 	if (error)
+ 		return error;
+@@ -1579,8 +1578,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
+ 	if (error)
+ 		return error;
+ 	gfs2_trans_add_bh(ip->i_gl, bh, 1);
+-	ip->i_di.di_blocks++;
+-	gfs2_set_inode_blocks(&ip->i_inode);
++	gfs2_add_inode_blocks(&ip->i_inode, 1);
+ 	gfs2_dinode_out(ip, bh->b_data);
+ 	brelse(bh);
+ 	return 0;
+@@ -1616,7 +1614,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
+ 			dent->de_type = cpu_to_be16(type);
+ 			if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
+ 				leaf = (struct gfs2_leaf *)bh->b_data;
+-				leaf->lf_entries = cpu_to_be16(be16_to_cpu(leaf->lf_entries) + 1);
++				be16_add_cpu(&leaf->lf_entries, 1);
+ 			}
+ 			brelse(bh);
+ 			error = gfs2_meta_inode_buffer(ip, &bh);
+@@ -1641,7 +1639,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
+ 			continue;
+ 		if (error < 0)
+ 			break;
+-		if (ip->i_di.di_depth < GFS2_DIR_MAX_DEPTH) {
++		if (ip->i_depth < GFS2_DIR_MAX_DEPTH) {
+ 			error = dir_double_exhash(ip);
+ 			if (error)
+ 				break;
+@@ -1785,13 +1783,13 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
+ 	u64 leaf_no;
+ 	int error = 0;
+ 
+-	hsize = 1 << dip->i_di.di_depth;
++	hsize = 1 << dip->i_depth;
+ 	if (hsize * sizeof(u64) != dip->i_di.di_size) {
+ 		gfs2_consist_inode(dip);
+ 		return -EIO;
+ 	}
+ 
+-	lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL);
++	lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
+ 	if (!lp)
+ 		return -ENOMEM;
+ 
+@@ -1817,7 +1815,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
+ 			if (error)
+ 				goto out;
+ 			leaf = (struct gfs2_leaf *)bh->b_data;
+-			len = 1 << (dip->i_di.di_depth - be16_to_cpu(leaf->lf_depth));
++			len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth));
+ 			brelse(bh);
+ 
+ 			error = lc(dip, index, len, leaf_no, data);
+@@ -1866,15 +1864,18 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
+ 
+ 	memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
+ 
+-	ht = kzalloc(size, GFP_KERNEL);
++	ht = kzalloc(size, GFP_NOFS);
+ 	if (!ht)
+ 		return -ENOMEM;
+ 
+-	gfs2_alloc_get(dip);
++	if (!gfs2_alloc_get(dip)) {
++		error = -ENOMEM;
++		goto out;
++	}
+ 
+ 	error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ 	if (error)
+-		goto out;
++		goto out_put;
+ 
+ 	error = gfs2_rindex_hold(sdp, &dip->i_alloc->al_ri_gh);
+ 	if (error)
+@@ -1894,7 +1895,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
+ 		l_blocks++;
+ 	}
+ 
+-	gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
++	gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
+ 
+ 	for (x = 0; x < rlist.rl_rgrps; x++) {
+ 		struct gfs2_rgrpd *rgd;
+@@ -1921,11 +1922,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
+ 		brelse(bh);
+ 
+ 		gfs2_free_meta(dip, blk, 1);
+-
+-		if (!dip->i_di.di_blocks)
+-			gfs2_consist_inode(dip);
+-		dip->i_di.di_blocks--;
+-		gfs2_set_inode_blocks(&dip->i_inode);
++		gfs2_add_inode_blocks(&dip->i_inode, -1);
+ 	}
+ 
+ 	error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size);
+@@ -1952,8 +1949,9 @@ out_rlist:
+ 	gfs2_glock_dq_uninit(&dip->i_alloc->al_ri_gh);
+ out_qs:
+ 	gfs2_quota_unhold(dip);
+-out:
++out_put:
+ 	gfs2_alloc_put(dip);
++out:
+ 	kfree(ht);
+ 	return error;
+ }
+diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
+index bee9970..e3f76f4 100644
+--- a/fs/gfs2/eattr.c
++++ b/fs/gfs2/eattr.c
+@@ -277,10 +277,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
+ 		}
+ 
+ 		*dataptrs = 0;
+-		if (!ip->i_di.di_blocks)
+-			gfs2_consist_inode(ip);
+-		ip->i_di.di_blocks--;
+-		gfs2_set_inode_blocks(&ip->i_inode);
++		gfs2_add_inode_blocks(&ip->i_inode, -1);
+ 	}
+ 	if (bstart)
+ 		gfs2_free_meta(ip, bstart, blen);
+@@ -321,6 +318,8 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
+ 	int error;
+ 
+ 	al = gfs2_alloc_get(ip);
++	if (!al)
++		return -ENOMEM;
+ 
+ 	error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ 	if (error)
+@@ -449,7 +448,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
+ 	unsigned int x;
+ 	int error = 0;
+ 
+-	bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL);
++	bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
+ 	if (!bh)
+ 		return -ENOMEM;
+ 
+@@ -582,10 +581,11 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
+ {
+ 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ 	struct gfs2_ea_header *ea;
++	unsigned int n = 1;
+ 	u64 block;
+ 
+-	block = gfs2_alloc_meta(ip);
+-
++	block = gfs2_alloc_block(ip, &n);
++	gfs2_trans_add_unrevoke(sdp, block, 1);
+ 	*bhp = gfs2_meta_new(ip->i_gl, block);
+ 	gfs2_trans_add_bh(ip->i_gl, *bhp, 1);
+ 	gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA);
+@@ -597,8 +597,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
+ 	ea->ea_flags = GFS2_EAFLAG_LAST;
+ 	ea->ea_num_ptrs = 0;
+ 
+-	ip->i_di.di_blocks++;
+-	gfs2_set_inode_blocks(&ip->i_inode);
++	gfs2_add_inode_blocks(&ip->i_inode, 1);
+ 
+ 	return 0;
+ }
+@@ -642,15 +641,15 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
+ 			struct buffer_head *bh;
+ 			u64 block;
+ 			int mh_size = sizeof(struct gfs2_meta_header);
++			unsigned int n = 1;
+ 
+-			block = gfs2_alloc_meta(ip);
+-
++			block = gfs2_alloc_block(ip, &n);
++			gfs2_trans_add_unrevoke(sdp, block, 1);
+ 			bh = gfs2_meta_new(ip->i_gl, block);
+ 			gfs2_trans_add_bh(ip->i_gl, bh, 1);
+ 			gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED);
+ 
+-			ip->i_di.di_blocks++;
+-			gfs2_set_inode_blocks(&ip->i_inode);
++			gfs2_add_inode_blocks(&ip->i_inode, 1);
+ 
+ 			copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize :
+ 							   data_len;
+@@ -684,15 +683,13 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
+ 	int error;
+ 
+ 	al = gfs2_alloc_get(ip);
++	if (!al)
++		return -ENOMEM;
+ 
+-	error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++	error = gfs2_quota_lock_check(ip);
+ 	if (error)
+ 		goto out;
+ 
+-	error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
+-	if (error)
+-		goto out_gunlock_q;
+-
+ 	al->al_requested = blks;
+ 
+ 	error = gfs2_inplace_reserve(ip);
+@@ -966,9 +963,9 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
+ 		gfs2_trans_add_bh(ip->i_gl, indbh, 1);
+ 	} else {
+ 		u64 blk;
+-
+-		blk = gfs2_alloc_meta(ip);
+-
++		unsigned int n = 1;
++		blk = gfs2_alloc_block(ip, &n);
++		gfs2_trans_add_unrevoke(sdp, blk, 1);
+ 		indbh = gfs2_meta_new(ip->i_gl, blk);
+ 		gfs2_trans_add_bh(ip->i_gl, indbh, 1);
+ 		gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
+@@ -978,8 +975,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
+ 		*eablk = cpu_to_be64(ip->i_di.di_eattr);
+ 		ip->i_di.di_eattr = blk;
+ 		ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT;
+-		ip->i_di.di_blocks++;
+-		gfs2_set_inode_blocks(&ip->i_inode);
++		gfs2_add_inode_blocks(&ip->i_inode, 1);
+ 
+ 		eablk++;
+ 	}
+@@ -1210,7 +1206,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
+ 	unsigned int x;
+ 	int error;
+ 
+-	bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL);
++	bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
+ 	if (!bh)
+ 		return -ENOMEM;
+ 
+@@ -1347,7 +1343,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
+ 	else
+ 		goto out;
+ 
+-	gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
++	gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
+ 
+ 	for (x = 0; x < rlist.rl_rgrps; x++) {
+ 		struct gfs2_rgrpd *rgd;
+@@ -1387,10 +1383,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
+ 		}
+ 
+ 		*eablk = 0;
+-		if (!ip->i_di.di_blocks)
+-			gfs2_consist_inode(ip);
+-		ip->i_di.di_blocks--;
+-		gfs2_set_inode_blocks(&ip->i_inode);
++		gfs2_add_inode_blocks(&ip->i_inode, -1);
+ 	}
+ 	if (bstart)
+ 		gfs2_free_meta(ip, bstart, blen);
+@@ -1442,10 +1435,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
+ 	gfs2_free_meta(ip, ip->i_di.di_eattr, 1);
+ 
+ 	ip->i_di.di_eattr = 0;
+-	if (!ip->i_di.di_blocks)
+-		gfs2_consist_inode(ip);
+-	ip->i_di.di_blocks--;
+-	gfs2_set_inode_blocks(&ip->i_inode);
++	gfs2_add_inode_blocks(&ip->i_inode, -1);
+ 
+ 	error = gfs2_meta_inode_buffer(ip, &dibh);
+ 	if (!error) {
+@@ -1474,6 +1464,8 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip)
+ 	int error;
+ 
+ 	al = gfs2_alloc_get(ip);
++	if (!al)
++		return -ENOMEM;
+ 
+ 	error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ 	if (error)
+diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
+index 7175a4d..d636b3e 100644
+--- a/fs/gfs2/glock.c
++++ b/fs/gfs2/glock.c
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+  *
+  * This copyrighted material is made available to anyone wishing to use,
+  * modify, copy, or redistribute it subject to the terms and conditions
+@@ -35,7 +35,6 @@
+ #include "glock.h"
+ #include "glops.h"
+ #include "inode.h"
+-#include "lm.h"
+ #include "lops.h"
+ #include "meta_io.h"
+ #include "quota.h"
+@@ -183,7 +182,8 @@ static void glock_free(struct gfs2_glock *gl)
+ 	struct gfs2_sbd *sdp = gl->gl_sbd;
+ 	struct inode *aspace = gl->gl_aspace;
+ 
+-	gfs2_lm_put_lock(sdp, gl->gl_lock);
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		sdp->sd_lockstruct.ls_ops->lm_put_lock(gl->gl_lock);
+ 
+ 	if (aspace)
+ 		gfs2_aspace_put(aspace);
+@@ -197,7 +197,7 @@ static void glock_free(struct gfs2_glock *gl)
+  *
+  */
+ 
+-void gfs2_glock_hold(struct gfs2_glock *gl)
++static void gfs2_glock_hold(struct gfs2_glock *gl)
+ {
+ 	atomic_inc(&gl->gl_ref);
+ }
+@@ -293,6 +293,16 @@ static void glock_work_func(struct work_struct *work)
+ 	gfs2_glock_put(gl);
+ }
+ 
++static int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
++		     void **lockp)
++{
++	int error = -EIO;
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		error = sdp->sd_lockstruct.ls_ops->lm_get_lock(
++				sdp->sd_lockstruct.ls_lockspace, name, lockp);
++	return error;
++}
++
+ /**
+  * gfs2_glock_get() - Get a glock, or create one if one doesn't exist
+  * @sdp: The GFS2 superblock
+@@ -338,8 +348,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
+ 	gl->gl_ip = 0;
+ 	gl->gl_ops = glops;
+ 	gl->gl_req_gh = NULL;
+-	gl->gl_req_bh = NULL;
+-	gl->gl_vn = 0;
+ 	gl->gl_stamp = jiffies;
+ 	gl->gl_tchange = jiffies;
+ 	gl->gl_object = NULL;
+@@ -595,11 +603,12 @@ static void run_queue(struct gfs2_glock *gl)
+ 			blocked = rq_mutex(gh);
+ 		} else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
+ 			blocked = rq_demote(gl);
+-			if (gl->gl_waiters2 && !blocked) {
++			if (test_bit(GLF_WAITERS2, &gl->gl_flags) &&
++				     !blocked) {
+ 				set_bit(GLF_DEMOTE, &gl->gl_flags);
+ 				gl->gl_demote_state = LM_ST_UNLOCKED;
+ 			}
+-			gl->gl_waiters2 = 0;
++			clear_bit(GLF_WAITERS2, &gl->gl_flags);
+ 		} else if (!list_empty(&gl->gl_waiters3)) {
+ 			gh = list_entry(gl->gl_waiters3.next,
+ 					struct gfs2_holder, gh_list);
+@@ -710,7 +719,7 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state,
+ 	} else if (gl->gl_demote_state != LM_ST_UNLOCKED &&
+ 			gl->gl_demote_state != state) {
+ 		if (test_bit(GLF_DEMOTE_IN_PROGRESS,  &gl->gl_flags)) 
+-			gl->gl_waiters2 = 1;
++			set_bit(GLF_WAITERS2, &gl->gl_flags);
+ 		else 
+ 			gl->gl_demote_state = LM_ST_UNLOCKED;
+ 	}
+@@ -743,6 +752,43 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
+ }
+ 
+ /**
++ * drop_bh - Called after a lock module unlock completes
++ * @gl: the glock
++ * @ret: the return status
++ *
++ * Doesn't wake up the process waiting on the struct gfs2_holder (if any)
++ * Doesn't drop the reference on the glock the top half took out
++ *
++ */
++
++static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
++{
++	struct gfs2_sbd *sdp = gl->gl_sbd;
++	struct gfs2_holder *gh = gl->gl_req_gh;
++
++	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
++	gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
++	gfs2_assert_warn(sdp, !ret);
++
++	state_change(gl, LM_ST_UNLOCKED);
++
++	if (test_and_clear_bit(GLF_CONV_DEADLK, &gl->gl_flags)) {
++		spin_lock(&gl->gl_spin);
++		gh->gh_error = 0;
++		spin_unlock(&gl->gl_spin);
++		gfs2_glock_xmote_th(gl, gl->gl_req_gh);
++		gfs2_glock_put(gl);
++		return;
++	}
++
++	spin_lock(&gl->gl_spin);
++	gfs2_demote_wake(gl);
++	clear_bit(GLF_LOCK, &gl->gl_flags);
++	spin_unlock(&gl->gl_spin);
++	gfs2_glock_put(gl);
++}
++
++/**
+  * xmote_bh - Called after the lock module is done acquiring a lock
+  * @gl: The glock in question
+  * @ret: the int returned from the lock module
+@@ -754,25 +800,19 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
+ 	struct gfs2_sbd *sdp = gl->gl_sbd;
+ 	const struct gfs2_glock_operations *glops = gl->gl_ops;
+ 	struct gfs2_holder *gh = gl->gl_req_gh;
+-	int prev_state = gl->gl_state;
+ 	int op_done = 1;
+ 
++	if (!gh && (ret & LM_OUT_ST_MASK) == LM_ST_UNLOCKED) {
++		drop_bh(gl, ret);
++		return;
++	}
++
+ 	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
+ 	gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
+ 	gfs2_assert_warn(sdp, !(ret & LM_OUT_ASYNC));
+ 
+ 	state_change(gl, ret & LM_OUT_ST_MASK);
+ 
+-	if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) {
+-		if (glops->go_inval)
+-			glops->go_inval(gl, DIO_METADATA);
+-	} else if (gl->gl_state == LM_ST_DEFERRED) {
+-		/* We might not want to do this here.
+-		   Look at moving to the inode glops. */
+-		if (glops->go_inval)
+-			glops->go_inval(gl, 0);
+-	}
+-
+ 	/*  Deal with each possible exit condition  */
+ 
+ 	if (!gh) {
+@@ -782,7 +822,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
+ 		} else {
+ 			spin_lock(&gl->gl_spin);
+ 			if (gl->gl_state != gl->gl_demote_state) {
+-				gl->gl_req_bh = NULL;
+ 				spin_unlock(&gl->gl_spin);
+ 				gfs2_glock_drop_th(gl);
+ 				gfs2_glock_put(gl);
+@@ -793,6 +832,14 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
+ 		}
+ 	} else {
+ 		spin_lock(&gl->gl_spin);
++		if (ret & LM_OUT_CONV_DEADLK) {
++			gh->gh_error = 0;
++			set_bit(GLF_CONV_DEADLK, &gl->gl_flags);
++			spin_unlock(&gl->gl_spin);
++			gfs2_glock_drop_th(gl);
++			gfs2_glock_put(gl);
++			return;
++		}
+ 		list_del_init(&gh->gh_list);
+ 		gh->gh_error = -EIO;
+ 		if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) 
+@@ -824,7 +871,6 @@ out:
+ 	if (op_done) {
+ 		spin_lock(&gl->gl_spin);
+ 		gl->gl_req_gh = NULL;
+-		gl->gl_req_bh = NULL;
+ 		clear_bit(GLF_LOCK, &gl->gl_flags);
+ 		spin_unlock(&gl->gl_spin);
+ 	}
+@@ -835,6 +881,17 @@ out:
+ 		gfs2_holder_wake(gh);
+ }
+ 
++static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
++				 unsigned int cur_state, unsigned int req_state,
++				 unsigned int flags)
++{
++	int ret = 0;
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state,
++							 req_state, flags);
++	return ret;
++}
++
+ /**
+  * gfs2_glock_xmote_th - Call into the lock module to acquire or change a glock
+  * @gl: The glock in question
+@@ -856,6 +913,8 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
+ 
+ 	if (glops->go_xmote_th)
+ 		glops->go_xmote_th(gl);
++	if (state == LM_ST_DEFERRED && glops->go_inval)
++		glops->go_inval(gl, DIO_METADATA);
+ 
+ 	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
+ 	gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
+@@ -863,7 +922,6 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
+ 	gfs2_assert_warn(sdp, state != gl->gl_state);
+ 
+ 	gfs2_glock_hold(gl);
+-	gl->gl_req_bh = xmote_bh;
+ 
+ 	lck_ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, state, lck_flags);
+ 
+@@ -876,49 +934,13 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
+ 		xmote_bh(gl, lck_ret);
+ }
+ 
+-/**
+- * drop_bh - Called after a lock module unlock completes
+- * @gl: the glock
+- * @ret: the return status
+- *
+- * Doesn't wake up the process waiting on the struct gfs2_holder (if any)
+- * Doesn't drop the reference on the glock the top half took out
+- *
+- */
+-
+-static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
++static unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
++				   unsigned int cur_state)
+ {
+-	struct gfs2_sbd *sdp = gl->gl_sbd;
+-	const struct gfs2_glock_operations *glops = gl->gl_ops;
+-	struct gfs2_holder *gh = gl->gl_req_gh;
+-
+-	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
+-	gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
+-	gfs2_assert_warn(sdp, !ret);
+-
+-	state_change(gl, LM_ST_UNLOCKED);
+-
+-	if (glops->go_inval)
+-		glops->go_inval(gl, DIO_METADATA);
+-
+-	if (gh) {
+-		spin_lock(&gl->gl_spin);
+-		list_del_init(&gh->gh_list);
+-		gh->gh_error = 0;
+-		spin_unlock(&gl->gl_spin);
+-	}
+-
+-	spin_lock(&gl->gl_spin);
+-	gfs2_demote_wake(gl);
+-	gl->gl_req_gh = NULL;
+-	gl->gl_req_bh = NULL;
+-	clear_bit(GLF_LOCK, &gl->gl_flags);
+-	spin_unlock(&gl->gl_spin);
+-
+-	gfs2_glock_put(gl);
+-
+-	if (gh)
+-		gfs2_holder_wake(gh);
++	int ret = 0;
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		ret =  sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state);
++	return ret;
+ }
+ 
+ /**
+@@ -935,13 +957,14 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
+ 
+ 	if (glops->go_xmote_th)
+ 		glops->go_xmote_th(gl);
++	if (glops->go_inval)
++		glops->go_inval(gl, DIO_METADATA);
+ 
+ 	gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
+ 	gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
+ 	gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED);
+ 
+ 	gfs2_glock_hold(gl);
+-	gl->gl_req_bh = drop_bh;
+ 
+ 	ret = gfs2_lm_unlock(sdp, gl->gl_lock, gl->gl_state);
+ 
+@@ -964,16 +987,17 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
+ static void do_cancels(struct gfs2_holder *gh)
+ {
+ 	struct gfs2_glock *gl = gh->gh_gl;
++	struct gfs2_sbd *sdp = gl->gl_sbd;
+ 
+ 	spin_lock(&gl->gl_spin);
+ 
+ 	while (gl->gl_req_gh != gh &&
+ 	       !test_bit(HIF_HOLDER, &gh->gh_iflags) &&
+ 	       !list_empty(&gh->gh_list)) {
+-		if (gl->gl_req_bh && !(gl->gl_req_gh &&
+-				     (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) {
++		if (!(gl->gl_req_gh && (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) {
+ 			spin_unlock(&gl->gl_spin);
+-			gfs2_lm_cancel(gl->gl_sbd, gl->gl_lock);
++			if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++				sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock);
+ 			msleep(100);
+ 			spin_lock(&gl->gl_spin);
+ 		} else {
+@@ -1041,7 +1065,6 @@ static int glock_wait_internal(struct gfs2_holder *gh)
+ 
+ 		spin_lock(&gl->gl_spin);
+ 		gl->gl_req_gh = NULL;
+-		gl->gl_req_bh = NULL;
+ 		clear_bit(GLF_LOCK, &gl->gl_flags);
+ 		run_queue(gl);
+ 		spin_unlock(&gl->gl_spin);
+@@ -1428,6 +1451,14 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs)
+ 		gfs2_glock_dq_uninit(&ghs[x]);
+ }
+ 
++static int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp)
++{
++	int error = -EIO;
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp);
++	return error;
++}
++
+ /**
+  * gfs2_lvb_hold - attach a LVB from a glock
+  * @gl: The glock in question
+@@ -1463,12 +1494,15 @@ int gfs2_lvb_hold(struct gfs2_glock *gl)
+ 
+ void gfs2_lvb_unhold(struct gfs2_glock *gl)
+ {
++	struct gfs2_sbd *sdp = gl->gl_sbd;
++
+ 	gfs2_glock_hold(gl);
+ 	gfs2_glmutex_lock(gl);
+ 
+ 	gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0);
+ 	if (atomic_dec_and_test(&gl->gl_lvb_count)) {
+-		gfs2_lm_unhold_lvb(gl->gl_sbd, gl->gl_lock, gl->gl_lvb);
++		if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++			sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(gl->gl_lock, gl->gl_lvb);
+ 		gl->gl_lvb = NULL;
+ 		gfs2_glock_put(gl);
+ 	}
+@@ -1534,8 +1568,7 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data)
+ 		gl = gfs2_glock_find(sdp, &async->lc_name);
+ 		if (gfs2_assert_warn(sdp, gl))
+ 			return;
+-		if (!gfs2_assert_warn(sdp, gl->gl_req_bh))
+-			gl->gl_req_bh(gl, async->lc_ret);
++		xmote_bh(gl, async->lc_ret);
+ 		if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
+ 			gfs2_glock_put(gl);
+ 		up_read(&gfs2_umount_flush_sem);
+@@ -1594,10 +1627,10 @@ void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
+ 		gfs2_glock_hold(gl);
+ 		list_add(&gl->gl_reclaim, &sdp->sd_reclaim_list);
+ 		atomic_inc(&sdp->sd_reclaim_count);
+-	}
+-	spin_unlock(&sdp->sd_reclaim_lock);
+-
+-	wake_up(&sdp->sd_reclaim_wq);
++		spin_unlock(&sdp->sd_reclaim_lock);
++		wake_up(&sdp->sd_reclaim_wq);
++	} else
++		spin_unlock(&sdp->sd_reclaim_lock);
+ }
+ 
+ /**
+@@ -1897,7 +1930,6 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl)
+ 		print_dbg(gi, "  gl_owner = -1\n");
+ 	print_dbg(gi, "  gl_ip = %lu\n", gl->gl_ip);
+ 	print_dbg(gi, "  req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no");
+-	print_dbg(gi, "  req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no");
+ 	print_dbg(gi, "  lvb_count = %d\n", atomic_read(&gl->gl_lvb_count));
+ 	print_dbg(gi, "  object = %s\n", (gl->gl_object) ? "yes" : "no");
+ 	print_dbg(gi, "  reclaim = %s\n",
+diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
+index 2f9c6d1..cdad3e6 100644
+--- a/fs/gfs2/glock.h
++++ b/fs/gfs2/glock.h
+@@ -32,24 +32,23 @@
+ #define GLR_TRYFAILED		13
+ #define GLR_CANCELED		14
+ 
+-static inline int gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
++static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
+ {
+ 	struct gfs2_holder *gh;
+-	int locked = 0;
+ 	struct pid *pid;
+ 
+ 	/* Look in glock's list of holders for one with current task as owner */
+ 	spin_lock(&gl->gl_spin);
+ 	pid = task_pid(current);
+ 	list_for_each_entry(gh, &gl->gl_holders, gh_list) {
+-		if (gh->gh_owner_pid == pid) {
+-			locked = 1;
+-			break;
+-		}
++		if (gh->gh_owner_pid == pid)
++			goto out;
+ 	}
++	gh = NULL;
++out:
+ 	spin_unlock(&gl->gl_spin);
+ 
+-	return locked;
++	return gh;
+ }
+ 
+ static inline int gfs2_glock_is_held_excl(struct gfs2_glock *gl)
+@@ -79,7 +78,6 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl)
+ int gfs2_glock_get(struct gfs2_sbd *sdp,
+ 		   u64 number, const struct gfs2_glock_operations *glops,
+ 		   int create, struct gfs2_glock **glp);
+-void gfs2_glock_hold(struct gfs2_glock *gl);
+ int gfs2_glock_put(struct gfs2_glock *gl);
+ void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
+ 		      struct gfs2_holder *gh);
+diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
+index c663b7a..d31bada 100644
+--- a/fs/gfs2/glops.c
++++ b/fs/gfs2/glops.c
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+  *
+  * This copyrighted material is made available to anyone wishing to use,
+  * modify, copy, or redistribute it subject to the terms and conditions
+@@ -126,7 +126,13 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags)
+ 		return;
+ 
+ 	gfs2_meta_inval(gl);
+-	gl->gl_vn++;
++	if (gl->gl_object == GFS2_I(gl->gl_sbd->sd_rindex))
++		gl->gl_sbd->sd_rindex_uptodate = 0;
++	else if (gl->gl_ops == &gfs2_rgrp_glops && gl->gl_object) {
++		struct gfs2_rgrpd *rgd = (struct gfs2_rgrpd *)gl->gl_object;
++
++		rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
++	}
+ }
+ 
+ /**
+diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
+index 525dcae..9c2c0b9 100644
+--- a/fs/gfs2/incore.h
++++ b/fs/gfs2/incore.h
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+  *
+  * This copyrighted material is made available to anyone wishing to use,
+  * modify, copy, or redistribute it subject to the terms and conditions
+@@ -44,7 +44,6 @@ struct gfs2_log_header_host {
+ 
+ struct gfs2_log_operations {
+ 	void (*lo_add) (struct gfs2_sbd *sdp, struct gfs2_log_element *le);
+-	void (*lo_incore_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr);
+ 	void (*lo_before_commit) (struct gfs2_sbd *sdp);
+ 	void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai);
+ 	void (*lo_before_scan) (struct gfs2_jdesc *jd,
+@@ -70,7 +69,6 @@ struct gfs2_bitmap {
+ };
+ 
+ struct gfs2_rgrp_host {
+-	u32 rg_flags;
+ 	u32 rg_free;
+ 	u32 rg_dinodes;
+ 	u64 rg_igeneration;
+@@ -87,17 +85,17 @@ struct gfs2_rgrpd {
+ 	u32 rd_data;			/* num of data blocks in rgrp */
+ 	u32 rd_bitbytes;		/* number of bytes in data bitmaps */
+ 	struct gfs2_rgrp_host rd_rg;
+-	u64 rd_rg_vn;
+ 	struct gfs2_bitmap *rd_bits;
+ 	unsigned int rd_bh_count;
+ 	struct mutex rd_mutex;
+ 	u32 rd_free_clone;
+ 	struct gfs2_log_element rd_le;
+-	u32 rd_last_alloc_data;
+-	u32 rd_last_alloc_meta;
++	u32 rd_last_alloc;
+ 	struct gfs2_sbd *rd_sbd;
+-	unsigned long rd_flags;
+-#define GFS2_RDF_CHECK        0x0001          /* Need to check for unlinked inodes */
++	unsigned char rd_flags;
++#define GFS2_RDF_CHECK        0x01      /* Need to check for unlinked inodes */
++#define GFS2_RDF_NOALLOC      0x02      /* rg prohibits allocation */
++#define GFS2_RDF_UPTODATE     0x04      /* rg is up to date */
+ };
+ 
+ enum gfs2_state_bits {
+@@ -168,6 +166,8 @@ enum {
+ 	GLF_DIRTY		= 5,
+ 	GLF_DEMOTE_IN_PROGRESS	= 6,
+ 	GLF_LFLUSH		= 7,
++	GLF_WAITERS2		= 8,
++	GLF_CONV_DEADLK		= 9,
+ };
+ 
+ struct gfs2_glock {
+@@ -187,18 +187,15 @@ struct gfs2_glock {
+ 	struct list_head gl_holders;
+ 	struct list_head gl_waiters1;	/* HIF_MUTEX */
+ 	struct list_head gl_waiters3;	/* HIF_PROMOTE */
+-	int gl_waiters2;		/* GIF_DEMOTE */
+ 
+ 	const struct gfs2_glock_operations *gl_ops;
+ 
+ 	struct gfs2_holder *gl_req_gh;
+-	gfs2_glop_bh_t gl_req_bh;
+ 
+ 	void *gl_lock;
+ 	char *gl_lvb;
+ 	atomic_t gl_lvb_count;
+ 
+-	u64 gl_vn;
+ 	unsigned long gl_stamp;
+ 	unsigned long gl_tchange;
+ 	void *gl_object;
+@@ -213,6 +210,8 @@ struct gfs2_glock {
+ 	struct delayed_work gl_work;
+ };
+ 
++#define GFS2_MIN_LVB_SIZE 32	/* Min size of LVB that gfs2 supports */
++
+ struct gfs2_alloc {
+ 	/* Quota stuff */
+ 
+@@ -241,14 +240,9 @@ enum {
+ 
+ struct gfs2_dinode_host {
+ 	u64 di_size;		/* number of bytes in file */
+-	u64 di_blocks;		/* number of blocks in file */
+-	u64 di_goal_meta;	/* rgrp to alloc from next */
+-	u64 di_goal_data;	/* data block goal */
+ 	u64 di_generation;	/* generation number for NFS */
+ 	u32 di_flags;		/* GFS2_DIF_... */
+-	u16 di_height;		/* height of metadata */
+ 	/* These only apply to directories  */
+-	u16 di_depth;		/* Number of bits in the table */
+ 	u32 di_entries;		/* The number of entries in the directory */
+ 	u64 di_eattr;		/* extended attribute block number */
+ };
+@@ -265,9 +259,10 @@ struct gfs2_inode {
+ 	struct gfs2_holder i_iopen_gh;
+ 	struct gfs2_holder i_gh; /* for prepare/commit_write only */
+ 	struct gfs2_alloc *i_alloc;
+-	u64 i_last_rg_alloc;
+-
++	u64 i_goal;	/* goal block for allocations */
+ 	struct rw_semaphore i_rw_mutex;
++	u8 i_height;
++	u8 i_depth;
+ };
+ 
+ /*
+@@ -490,9 +485,9 @@ struct gfs2_sbd {
+ 	u32 sd_qc_per_block;
+ 	u32 sd_max_dirres;	/* Max blocks needed to add a directory entry */
+ 	u32 sd_max_height;	/* Max height of a file's metadata tree */
+-	u64 sd_heightsize[GFS2_MAX_META_HEIGHT];
++	u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1];
+ 	u32 sd_max_jheight; /* Max height of journaled file's meta tree */
+-	u64 sd_jheightsize[GFS2_MAX_META_HEIGHT];
++	u64 sd_jheightsize[GFS2_MAX_META_HEIGHT + 1];
+ 
+ 	struct gfs2_args sd_args;	/* Mount arguments */
+ 	struct gfs2_tune sd_tune;	/* Filesystem tuning structure */
+@@ -533,7 +528,7 @@ struct gfs2_sbd {
+ 
+ 	/* Resource group stuff */
+ 
+-	u64 sd_rindex_vn;
++	int sd_rindex_uptodate;
+ 	spinlock_t sd_rindex_spin;
+ 	struct mutex sd_rindex_mutex;
+ 	struct list_head sd_rindex_list;
+@@ -637,9 +632,6 @@ struct gfs2_sbd {
+ 
+ 	/* Counters */
+ 
+-	atomic_t sd_glock_count;
+-	atomic_t sd_glock_held_count;
+-	atomic_t sd_inode_count;
+ 	atomic_t sd_reclaimed;
+ 
+ 	char sd_fsname[GFS2_FSNAME_LEN];
+diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
+index 37725ad..3a9ef52 100644
+--- a/fs/gfs2/inode.c
++++ b/fs/gfs2/inode.c
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+  *
+  * This copyrighted material is made available to anyone wishing to use,
+  * modify, copy, or redistribute it subject to the terms and conditions
+@@ -149,7 +149,8 @@ void gfs2_set_iop(struct inode *inode)
+ 	} else if (S_ISLNK(mode)) {
+ 		inode->i_op = &gfs2_symlink_iops;
+ 	} else {
+-		inode->i_op = &gfs2_dev_iops;
++		inode->i_op = &gfs2_file_iops;
++		init_special_inode(inode, inode->i_mode, inode->i_rdev);
+ 	}
+ 
+ 	unlock_new_inode(inode);
+@@ -248,12 +249,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+ {
+ 	struct gfs2_dinode_host *di = &ip->i_di;
+ 	const struct gfs2_dinode *str = buf;
++	u16 height, depth;
+ 
+-	if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) {
+-		if (gfs2_consist_inode(ip))
+-			gfs2_dinode_print(ip);
+-		return -EIO;
+-	}
++	if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
++		goto corrupt;
+ 	ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
+ 	ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
+ 	ip->i_inode.i_rdev = 0;
+@@ -275,8 +274,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+ 	ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
+ 	di->di_size = be64_to_cpu(str->di_size);
+ 	i_size_write(&ip->i_inode, di->di_size);
+-	di->di_blocks = be64_to_cpu(str->di_blocks);
+-	gfs2_set_inode_blocks(&ip->i_inode);
++	gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
+ 	ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
+ 	ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
+ 	ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
+@@ -284,15 +282,20 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+ 	ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
+ 	ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
+ 
+-	di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
+-	di->di_goal_data = be64_to_cpu(str->di_goal_data);
++	ip->i_goal = be64_to_cpu(str->di_goal_meta);
+ 	di->di_generation = be64_to_cpu(str->di_generation);
+ 
+ 	di->di_flags = be32_to_cpu(str->di_flags);
+ 	gfs2_set_inode_flags(&ip->i_inode);
+-	di->di_height = be16_to_cpu(str->di_height);
+-
+-	di->di_depth = be16_to_cpu(str->di_depth);
++	height = be16_to_cpu(str->di_height);
++	if (unlikely(height > GFS2_MAX_META_HEIGHT))
++		goto corrupt;
++	ip->i_height = (u8)height;
++
++	depth = be16_to_cpu(str->di_depth);
++	if (unlikely(depth > GFS2_DIR_MAX_DEPTH))
++		goto corrupt;
++	ip->i_depth = (u8)depth;
+ 	di->di_entries = be32_to_cpu(str->di_entries);
+ 
+ 	di->di_eattr = be64_to_cpu(str->di_eattr);
+@@ -300,6 +303,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+ 		gfs2_set_aops(&ip->i_inode);
+ 
+ 	return 0;
++corrupt:
++	if (gfs2_consist_inode(ip))
++		gfs2_dinode_print(ip);
++	return -EIO;
+ }
+ 
+ /**
+@@ -337,13 +344,15 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
+ 	struct gfs2_rgrpd *rgd;
+ 	int error;
+ 
+-	if (ip->i_di.di_blocks != 1) {
++	if (gfs2_get_inode_blocks(&ip->i_inode) != 1) {
+ 		if (gfs2_consist_inode(ip))
+ 			gfs2_dinode_print(ip);
+ 		return -EIO;
+ 	}
+ 
+ 	al = gfs2_alloc_get(ip);
++	if (!al)
++		return -ENOMEM;
+ 
+ 	error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ 	if (error)
+@@ -487,7 +496,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
+ 		return dir;
+ 	}
+ 
+-	if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) {
++	if (gfs2_glock_is_locked_by_me(dip->i_gl) == NULL) {
+ 		error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
+ 		if (error)
+ 			return ERR_PTR(error);
+@@ -818,7 +827,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
+ 	int error;
+ 
+ 	munge_mode_uid_gid(dip, &mode, &uid, &gid);
+-	gfs2_alloc_get(dip);
++	if (!gfs2_alloc_get(dip))
++		return -ENOMEM;
+ 
+ 	error = gfs2_quota_lock(dip, uid, gid);
+ 	if (error)
+@@ -853,6 +863,8 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
+ 	int error;
+ 
+ 	al = gfs2_alloc_get(dip);
++	if (!al)
++		return -ENOMEM;
+ 
+ 	error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ 	if (error)
+@@ -1219,7 +1231,7 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
+ 
+ 	x = ip->i_di.di_size + 1;
+ 	if (x > *len) {
+-		*buf = kmalloc(x, GFP_KERNEL);
++		*buf = kmalloc(x, GFP_NOFS);
+ 		if (!*buf) {
+ 			error = -ENOMEM;
+ 			goto out_brelse;
+@@ -1391,21 +1403,21 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
+ 	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(di->di_size);
+-	str->di_blocks = cpu_to_be64(di->di_blocks);
++	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);
+ 	str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
+ 
+-	str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
+-	str->di_goal_data = cpu_to_be64(di->di_goal_data);
++	str->di_goal_meta = cpu_to_be64(ip->i_goal);
++	str->di_goal_data = cpu_to_be64(ip->i_goal);
+ 	str->di_generation = cpu_to_be64(di->di_generation);
+ 
+ 	str->di_flags = cpu_to_be32(di->di_flags);
+-	str->di_height = cpu_to_be16(di->di_height);
++	str->di_height = cpu_to_be16(ip->i_height);
+ 	str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
+ 					     !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
+ 					     GFS2_FORMAT_DE : 0);
+-	str->di_depth = cpu_to_be16(di->di_depth);
++	str->di_depth = cpu_to_be16(ip->i_depth);
+ 	str->di_entries = cpu_to_be32(di->di_entries);
+ 
+ 	str->di_eattr = cpu_to_be64(di->di_eattr);
+@@ -1423,15 +1435,13 @@ void gfs2_dinode_print(const struct gfs2_inode *ip)
+ 	printk(KERN_INFO "  no_addr = %llu\n",
+ 	       (unsigned long long)ip->i_no_addr);
+ 	printk(KERN_INFO "  di_size = %llu\n", (unsigned long long)di->di_size);
+-	printk(KERN_INFO "  di_blocks = %llu\n",
+-	       (unsigned long long)di->di_blocks);
+-	printk(KERN_INFO "  di_goal_meta = %llu\n",
+-	       (unsigned long long)di->di_goal_meta);
+-	printk(KERN_INFO "  di_goal_data = %llu\n",
+-	       (unsigned long long)di->di_goal_data);
++	printk(KERN_INFO "  blocks = %llu\n",
++	       (unsigned long long)gfs2_get_inode_blocks(&ip->i_inode));
++	printk(KERN_INFO "  i_goal = %llu\n",
++	       (unsigned long long)ip->i_goal);
+ 	printk(KERN_INFO "  di_flags = 0x%.8X\n", di->di_flags);
+-	printk(KERN_INFO "  di_height = %u\n", di->di_height);
+-	printk(KERN_INFO "  di_depth = %u\n", di->di_depth);
++	printk(KERN_INFO "  i_height = %u\n", ip->i_height);
++	printk(KERN_INFO "  i_depth = %u\n", ip->i_depth);
+ 	printk(KERN_INFO "  di_entries = %u\n", di->di_entries);
+ 	printk(KERN_INFO "  di_eattr = %llu\n",
+ 	       (unsigned long long)di->di_eattr);
+diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
+index d446506..580da45 100644
+--- a/fs/gfs2/inode.h
++++ b/fs/gfs2/inode.h
+@@ -10,9 +10,11 @@
+ #ifndef __INODE_DOT_H__
+ #define __INODE_DOT_H__
+ 
++#include "util.h"
++
+ static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
+ {
+-	return !ip->i_di.di_height;
++	return !ip->i_height;
+ }
+ 
+ static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
+@@ -37,13 +39,25 @@ static inline int gfs2_is_dir(const struct gfs2_inode *ip)
+ 	return S_ISDIR(ip->i_inode.i_mode);
+ }
+ 
+-static inline void gfs2_set_inode_blocks(struct inode *inode)
++static inline void gfs2_set_inode_blocks(struct inode *inode, u64 blocks)
++{
++	inode->i_blocks = blocks <<
++		(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
++}
++
++static inline u64 gfs2_get_inode_blocks(const struct inode *inode)
+ {
+-	struct gfs2_inode *ip = GFS2_I(inode);
+-	inode->i_blocks = ip->i_di.di_blocks <<
++	return inode->i_blocks >>
+ 		(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
+ }
+ 
++static inline void gfs2_add_inode_blocks(struct inode *inode, s64 change)
++{
++	gfs2_assert(GFS2_SB(inode), (change >= 0 || inode->i_blocks > -change));
++	change *= (GFS2_SB(inode)->sd_sb.sb_bsize/GFS2_BASIC_BLOCK);
++	inode->i_blocks += change;
++}
++
+ static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr,
+ 				  u64 no_formal_ino)
+ {
+diff --git a/fs/gfs2/lm.c b/fs/gfs2/lm.c
+deleted file mode 100644
+index cfcc39b..0000000
+--- a/fs/gfs2/lm.c
++++ /dev/null
+@@ -1,210 +0,0 @@
+-/*
+- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+- *
+- * This copyrighted material is made available to anyone wishing to use,
+- * modify, copy, or redistribute it subject to the terms and conditions
+- * of the GNU General Public License version 2.
+- */
+-
+-#include <linux/slab.h>
+-#include <linux/spinlock.h>
+-#include <linux/completion.h>
+-#include <linux/buffer_head.h>
+-#include <linux/delay.h>
+-#include <linux/gfs2_ondisk.h>
+-#include <linux/lm_interface.h>
+-
+-#include "gfs2.h"
+-#include "incore.h"
+-#include "glock.h"
+-#include "lm.h"
+-#include "super.h"
+-#include "util.h"
+-
+-/**
+- * gfs2_lm_mount - mount a locking protocol
+- * @sdp: the filesystem
+- * @args: mount arguements
+- * @silent: if 1, don't complain if the FS isn't a GFS2 fs
+- *
+- * Returns: errno
+- */
+-
+-int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
+-{
+-	char *proto = sdp->sd_proto_name;
+-	char *table = sdp->sd_table_name;
+-	int flags = 0;
+-	int error;
+-
+-	if (sdp->sd_args.ar_spectator)
+-		flags |= LM_MFLAG_SPECTATOR;
+-
+-	fs_info(sdp, "Trying to join cluster \"%s\", \"%s\"\n", proto, table);
+-
+-	error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata,
+-				     gfs2_glock_cb, sdp,
+-				     GFS2_MIN_LVB_SIZE, flags,
+-				     &sdp->sd_lockstruct, &sdp->sd_kobj);
+-	if (error) {
+-		fs_info(sdp, "can't mount proto=%s, table=%s, hostdata=%s\n",
+-			proto, table, sdp->sd_args.ar_hostdata);
+-		goto out;
+-	}
+-
+-	if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) ||
+-	    gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) ||
+-	    gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >=
+-				  GFS2_MIN_LVB_SIZE)) {
+-		gfs2_unmount_lockproto(&sdp->sd_lockstruct);
+-		goto out;
+-	}
+-
+-	if (sdp->sd_args.ar_spectator)
+-		snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.s", table);
+-	else
+-		snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.%u", table,
+-			 sdp->sd_lockstruct.ls_jid);
+-
+-	fs_info(sdp, "Joined cluster. Now mounting FS...\n");
+-
+-	if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) &&
+-	    !sdp->sd_args.ar_ignore_local_fs) {
+-		sdp->sd_args.ar_localflocks = 1;
+-		sdp->sd_args.ar_localcaching = 1;
+-	}
+-
+-out:
+-	return error;
+-}
+-
+-void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
+-{
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		sdp->sd_lockstruct.ls_ops->lm_others_may_mount(
+-					sdp->sd_lockstruct.ls_lockspace);
+-}
+-
+-void gfs2_lm_unmount(struct gfs2_sbd *sdp)
+-{
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		gfs2_unmount_lockproto(&sdp->sd_lockstruct);
+-}
+-
+-int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
+-{
+-	va_list args;
+-
+-	if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
+-		return 0;
+-
+-	va_start(args, fmt);
+-	vprintk(fmt, args);
+-	va_end(args);
+-
+-	fs_err(sdp, "about to withdraw this file system\n");
+-	BUG_ON(sdp->sd_args.ar_debug);
+-
+-	fs_err(sdp, "telling LM to withdraw\n");
+-	gfs2_withdraw_lockproto(&sdp->sd_lockstruct);
+-	fs_err(sdp, "withdrawn\n");
+-	dump_stack();
+-
+-	return -1;
+-}
+-
+-int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+-		     void **lockp)
+-{
+-	int error = -EIO;
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		error = sdp->sd_lockstruct.ls_ops->lm_get_lock(
+-				sdp->sd_lockstruct.ls_lockspace, name, lockp);
+-	return error;
+-}
+-
+-void gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock)
+-{
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		sdp->sd_lockstruct.ls_ops->lm_put_lock(lock);
+-}
+-
+-unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
+-			  unsigned int cur_state, unsigned int req_state,
+-			  unsigned int flags)
+-{
+-	int ret = 0;
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state,
+-							 req_state, flags);
+-	return ret;
+-}
+-
+-unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
+-			    unsigned int cur_state)
+-{
+-	int ret = 0;
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		ret =  sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state);
+-	return ret;
+-}
+-
+-void gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock)
+-{
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		sdp->sd_lockstruct.ls_ops->lm_cancel(lock);
+-}
+-
+-int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp)
+-{
+-	int error = -EIO;
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp);
+-	return error;
+-}
+-
+-void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb)
+-{
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(lock, lvb);
+-}
+-
+-int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name,
+-		      struct file *file, struct file_lock *fl)
+-{
+-	int error = -EIO;
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		error = sdp->sd_lockstruct.ls_ops->lm_plock_get(
+-				sdp->sd_lockstruct.ls_lockspace, name, file, fl);
+-	return error;
+-}
+-
+-int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+-		  struct file *file, int cmd, struct file_lock *fl)
+-{
+-	int error = -EIO;
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		error = sdp->sd_lockstruct.ls_ops->lm_plock(
+-				sdp->sd_lockstruct.ls_lockspace, name, file, cmd, fl);
+-	return error;
+-}
+-
+-int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+-		    struct file *file, struct file_lock *fl)
+-{
+-	int error = -EIO;
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		error = sdp->sd_lockstruct.ls_ops->lm_punlock(
+-				sdp->sd_lockstruct.ls_lockspace, name, file, fl);
+-	return error;
+-}
+-
+-void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
+-			   unsigned int message)
+-{
+-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+-		sdp->sd_lockstruct.ls_ops->lm_recovery_done(
+-			sdp->sd_lockstruct.ls_lockspace, jid, message);
+-}
+-
+diff --git a/fs/gfs2/lm.h b/fs/gfs2/lm.h
+deleted file mode 100644
+index 21cdc30..0000000
+--- a/fs/gfs2/lm.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-/*
+- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+- *
+- * This copyrighted material is made available to anyone wishing to use,
+- * modify, copy, or redistribute it subject to the terms and conditions
+- * of the GNU General Public License version 2.
+- */
+-
+-#ifndef __LM_DOT_H__
+-#define __LM_DOT_H__
+-
+-struct gfs2_sbd;
+-
+-#define GFS2_MIN_LVB_SIZE 32
+-
+-int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent);
+-void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp);
+-void gfs2_lm_unmount(struct gfs2_sbd *sdp);
+-int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
+-				__attribute__ ((format(printf, 2, 3)));
+-int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+-		     void **lockp);
+-void gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock);
+-unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
+-			 unsigned int cur_state, unsigned int req_state,
+-			 unsigned int flags);
+-unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
+-			   unsigned int cur_state);
+-void gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock);
+-int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp);
+-void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb);
+-int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name,
+-		      struct file *file, struct file_lock *fl);
+-int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+-		  struct file *file, int cmd, struct file_lock *fl);
+-int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+-		    struct file *file, struct file_lock *fl);
+-void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
+-			   unsigned int message);
+-
+-#endif /* __LM_DOT_H__ */
+diff --git a/fs/gfs2/locking/dlm/Makefile b/fs/gfs2/locking/dlm/Makefile
+index 89b93b6..2609bb6 100644
+--- a/fs/gfs2/locking/dlm/Makefile
++++ b/fs/gfs2/locking/dlm/Makefile
+@@ -1,3 +1,3 @@
+ obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o
+-lock_dlm-y := lock.o main.o mount.o sysfs.o thread.o plock.o
++lock_dlm-y := lock.o main.o mount.o sysfs.o thread.o
+ 
+diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c
+index 542a797..cf7ea8a 100644
+--- a/fs/gfs2/locking/dlm/lock.c
++++ b/fs/gfs2/locking/dlm/lock.c
+@@ -137,7 +137,8 @@ static inline unsigned int make_flags(struct gdlm_lock *lp,
+ 
+ 		/* Conversion deadlock avoidance by DLM */
+ 
+-		if (!test_bit(LFL_FORCE_PROMOTE, &lp->flags) &&
++		if (!(lp->ls->fsflags & LM_MFLAG_CONV_NODROP) &&
++		    !test_bit(LFL_FORCE_PROMOTE, &lp->flags) &&
+ 		    !(lkf & DLM_LKF_NOQUEUE) &&
+ 		    cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req)
+ 			lkf |= DLM_LKF_CONVDEADLK;
+@@ -164,7 +165,7 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
+ {
+ 	struct gdlm_lock *lp;
+ 
+-	lp = kzalloc(sizeof(struct gdlm_lock), GFP_KERNEL);
++	lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS);
+ 	if (!lp)
+ 		return -ENOMEM;
+ 
+@@ -382,7 +383,7 @@ static int gdlm_add_lvb(struct gdlm_lock *lp)
+ {
+ 	char *lvb;
+ 
+-	lvb = kzalloc(GDLM_LVB_SIZE, GFP_KERNEL);
++	lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
+ 	if (!lvb)
+ 		return -ENOMEM;
+ 
+diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h
+index 9e8265d..a243cf6 100644
+--- a/fs/gfs2/locking/dlm/lock_dlm.h
++++ b/fs/gfs2/locking/dlm/lock_dlm.h
+@@ -25,6 +25,7 @@
+ #include <net/sock.h>
+ 
+ #include <linux/dlm.h>
++#include <linux/dlm_plock.h>
+ #include <linux/lm_interface.h>
+ 
+ /*
+@@ -173,15 +174,9 @@ void gdlm_cancel(void *);
+ int gdlm_hold_lvb(void *, char **);
+ void gdlm_unhold_lvb(void *, char *);
+ 
+-/* plock.c */
++/* mount.c */
++
++extern const struct lm_lockops gdlm_ops;
+ 
+-int gdlm_plock_init(void);
+-void gdlm_plock_exit(void);
+-int gdlm_plock(void *, struct lm_lockname *, struct file *, int,
+-		struct file_lock *);
+-int gdlm_plock_get(void *, struct lm_lockname *, struct file *,
+-		struct file_lock *);
+-int gdlm_punlock(void *, struct lm_lockname *, struct file *,
+-		struct file_lock *);
+ #endif
+ 
+diff --git a/fs/gfs2/locking/dlm/main.c b/fs/gfs2/locking/dlm/main.c
+index a0e7eda..b9a03a7 100644
+--- a/fs/gfs2/locking/dlm/main.c
++++ b/fs/gfs2/locking/dlm/main.c
+@@ -11,8 +11,6 @@
+ 
+ #include "lock_dlm.h"
+ 
+-extern struct lm_lockops gdlm_ops;
+-
+ static int __init init_lock_dlm(void)
+ {
+ 	int error;
+@@ -30,13 +28,6 @@ static int __init init_lock_dlm(void)
+ 		return error;
+ 	}
+ 
+-	error = gdlm_plock_init();
+-	if (error) {
+-		gdlm_sysfs_exit();
+-		gfs2_unregister_lockproto(&gdlm_ops);
+-		return error;
+-	}
+-
+ 	printk(KERN_INFO
+ 	       "Lock_DLM (built %s %s) installed\n", __DATE__, __TIME__);
+ 	return 0;
+@@ -44,7 +35,6 @@ static int __init init_lock_dlm(void)
+ 
+ static void __exit exit_lock_dlm(void)
+ {
+-	gdlm_plock_exit();
+ 	gdlm_sysfs_exit();
+ 	gfs2_unregister_lockproto(&gdlm_ops);
+ }
+diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
+index f2efff4..470bdf6 100644
+--- a/fs/gfs2/locking/dlm/mount.c
++++ b/fs/gfs2/locking/dlm/mount.c
+@@ -236,6 +236,27 @@ static void gdlm_withdraw(void *lockspace)
+ 	gdlm_kobject_release(ls);
+ }
+ 
++static int gdlm_plock(void *lockspace, struct lm_lockname *name,
++	       struct file *file, int cmd, struct file_lock *fl)
++{
++	struct gdlm_ls *ls = lockspace;
++	return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl);
++}
++
++static int gdlm_punlock(void *lockspace, struct lm_lockname *name,
++		 struct file *file, struct file_lock *fl)
++{
++	struct gdlm_ls *ls = lockspace;
++	return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl);
++}
++
++static int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
++		   struct file *file, struct file_lock *fl)
++{
++	struct gdlm_ls *ls = lockspace;
++	return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl);
++}
++
+ const struct lm_lockops gdlm_ops = {
+ 	.lm_proto_name = "lock_dlm",
+ 	.lm_mount = gdlm_mount,
+diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
+deleted file mode 100644
+index 2ebd374..0000000
+--- a/fs/gfs2/locking/dlm/plock.c
++++ /dev/null
+@@ -1,406 +0,0 @@
+-/*
+- * Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+- *
+- * This copyrighted material is made available to anyone wishing to use,
+- * modify, copy, or redistribute it subject to the terms and conditions
+- * of the GNU General Public License version 2.
+- */
+-
+-#include <linux/miscdevice.h>
+-#include <linux/lock_dlm_plock.h>
+-#include <linux/poll.h>
+-
+-#include "lock_dlm.h"
+-
+-
+-static spinlock_t ops_lock;
+-static struct list_head send_list;
+-static struct list_head recv_list;
+-static wait_queue_head_t send_wq;
+-static wait_queue_head_t recv_wq;
+-
+-struct plock_op {
+-	struct list_head list;
+-	int done;
+-	struct gdlm_plock_info info;
+-};
+-
+-struct plock_xop {
+-	struct plock_op xop;
+-	void *callback;
+-	void *fl;
+-	void *file;
+-	struct file_lock flc;
+-};
+-
+-
+-static inline void set_version(struct gdlm_plock_info *info)
+-{
+-	info->version[0] = GDLM_PLOCK_VERSION_MAJOR;
+-	info->version[1] = GDLM_PLOCK_VERSION_MINOR;
+-	info->version[2] = GDLM_PLOCK_VERSION_PATCH;
+-}
+-
+-static int check_version(struct gdlm_plock_info *info)
+-{
+-	if ((GDLM_PLOCK_VERSION_MAJOR != info->version[0]) ||
+-	    (GDLM_PLOCK_VERSION_MINOR < info->version[1])) {
+-		log_error("plock device version mismatch: "
+-			  "kernel (%u.%u.%u), user (%u.%u.%u)",
+-			  GDLM_PLOCK_VERSION_MAJOR,
+-			  GDLM_PLOCK_VERSION_MINOR,
+-			  GDLM_PLOCK_VERSION_PATCH,
+-			  info->version[0],
+-			  info->version[1],
+-			  info->version[2]);
+-		return -EINVAL;
+-	}
+-	return 0;
+-}
+-
+-static void send_op(struct plock_op *op)
+-{
+-	set_version(&op->info);
+-	INIT_LIST_HEAD(&op->list);
+-	spin_lock(&ops_lock);
+-	list_add_tail(&op->list, &send_list);
+-	spin_unlock(&ops_lock);
+-	wake_up(&send_wq);
+-}
+-
+-int gdlm_plock(void *lockspace, struct lm_lockname *name,
+-	       struct file *file, int cmd, struct file_lock *fl)
+-{
+-	struct gdlm_ls *ls = lockspace;
+-	struct plock_op *op;
+-	struct plock_xop *xop;
+-	int rv;
+-
+-	xop = kzalloc(sizeof(*xop), GFP_KERNEL);
+-	if (!xop)
+-		return -ENOMEM;
+-
+-	op = &xop->xop;
+-	op->info.optype		= GDLM_PLOCK_OP_LOCK;
+-	op->info.pid		= fl->fl_pid;
+-	op->info.ex		= (fl->fl_type == F_WRLCK);
+-	op->info.wait		= IS_SETLKW(cmd);
+-	op->info.fsid		= ls->id;
+-	op->info.number		= name->ln_number;
+-	op->info.start		= fl->fl_start;
+-	op->info.end		= fl->fl_end;
+-	if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
+-		/* fl_owner is lockd which doesn't distinguish
+-		   processes on the nfs client */
+-		op->info.owner	= (__u64) fl->fl_pid;
+-		xop->callback	= fl->fl_lmops->fl_grant;
+-		locks_init_lock(&xop->flc);
+-		locks_copy_lock(&xop->flc, fl);
+-		xop->fl		= fl;
+-		xop->file	= file;
+-	} else {
+-		op->info.owner	= (__u64)(long) fl->fl_owner;
+-		xop->callback	= NULL;
+-	}
+-
+-	send_op(op);
+-
+-	if (xop->callback == NULL)
+-		wait_event(recv_wq, (op->done != 0));
+-	else
+-		return -EINPROGRESS;
+-
+-	spin_lock(&ops_lock);
+-	if (!list_empty(&op->list)) {
+-		printk(KERN_INFO "plock op on list\n");
+-		list_del(&op->list);
+-	}
+-	spin_unlock(&ops_lock);
+-
+-	rv = op->info.rv;
+-
+-	if (!rv) {
+-		if (posix_lock_file_wait(file, fl) < 0)
+-			log_error("gdlm_plock: vfs lock error %x,%llx",
+-				  name->ln_type,
+-				  (unsigned long long)name->ln_number);
+-	}
+-
+-	kfree(xop);
+-	return rv;
+-}
+-
+-/* Returns failure iff a succesful lock operation should be canceled */
+-static int gdlm_plock_callback(struct plock_op *op)
+-{
+-	struct file *file;
+-	struct file_lock *fl;
+-	struct file_lock *flc;
+-	int (*notify)(void *, void *, int) = NULL;
+-	struct plock_xop *xop = (struct plock_xop *)op;
+-	int rv = 0;
+-
+-	spin_lock(&ops_lock);
+-	if (!list_empty(&op->list)) {
+-		printk(KERN_INFO "plock op on list\n");
+-		list_del(&op->list);
+-	}
+-	spin_unlock(&ops_lock);
+-
+-	/* check if the following 2 are still valid or make a copy */
+-	file = xop->file;
+-	flc = &xop->flc;
+-	fl = xop->fl;
+-	notify = xop->callback;
+-
+-	if (op->info.rv) {
+-		notify(flc, NULL, op->info.rv);
+-		goto out;
+-	}
+-
+-	/* got fs lock; bookkeep locally as well: */
+-	flc->fl_flags &= ~FL_SLEEP;
+-	if (posix_lock_file(file, flc, NULL)) {
+-		/*
+-		 * This can only happen in the case of kmalloc() failure.
+-		 * The filesystem's own lock is the authoritative lock,
+-		 * so a failure to get the lock locally is not a disaster.
+-		 * As long as GFS cannot reliably cancel locks (especially
+-		 * in a low-memory situation), we're better off ignoring
+-		 * this failure than trying to recover.
+-		 */
+-		log_error("gdlm_plock: vfs lock error file %p fl %p",
+-				file, fl);
+-	}
+-
+-	rv = notify(flc, NULL, 0);
+-	if (rv) {
+-		/* XXX: We need to cancel the fs lock here: */
+-		printk("gfs2 lock granted after lock request failed;"
+-						" dangling lock!\n");
+-		goto out;
+-	}
+-
+-out:
+-	kfree(xop);
+-	return rv;
+-}
+-
+-int gdlm_punlock(void *lockspace, struct lm_lockname *name,
+-		 struct file *file, struct file_lock *fl)
+-{
+-	struct gdlm_ls *ls = lockspace;
+-	struct plock_op *op;
+-	int rv;
+-
+-	op = kzalloc(sizeof(*op), GFP_KERNEL);
+-	if (!op)
+-		return -ENOMEM;
+-
+-	if (posix_lock_file_wait(file, fl) < 0)
+-		log_error("gdlm_punlock: vfs unlock error %x,%llx",
+-			  name->ln_type, (unsigned long long)name->ln_number);
+-
+-	op->info.optype		= GDLM_PLOCK_OP_UNLOCK;
+-	op->info.pid		= fl->fl_pid;
+-	op->info.fsid		= ls->id;
+-	op->info.number		= name->ln_number;
+-	op->info.start		= fl->fl_start;
+-	op->info.end		= fl->fl_end;
+-	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
+-		op->info.owner	= (__u64) fl->fl_pid;
+-	else
+-		op->info.owner	= (__u64)(long) fl->fl_owner;
+-
+-	send_op(op);
+-	wait_event(recv_wq, (op->done != 0));
+-
+-	spin_lock(&ops_lock);
+-	if (!list_empty(&op->list)) {
+-		printk(KERN_INFO "punlock op on list\n");
+-		list_del(&op->list);
+-	}
+-	spin_unlock(&ops_lock);
+-
+-	rv = op->info.rv;
+-
+-	if (rv == -ENOENT)
+-		rv = 0;
+-
+-	kfree(op);
+-	return rv;
+-}
+-
+-int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
+-		   struct file *file, struct file_lock *fl)
+-{
+-	struct gdlm_ls *ls = lockspace;
+-	struct plock_op *op;
+-	int rv;
+-
+-	op = kzalloc(sizeof(*op), GFP_KERNEL);
+-	if (!op)
+-		return -ENOMEM;
+-
+-	op->info.optype		= GDLM_PLOCK_OP_GET;
+-	op->info.pid		= fl->fl_pid;
+-	op->info.ex		= (fl->fl_type == F_WRLCK);
+-	op->info.fsid		= ls->id;
+-	op->info.number		= name->ln_number;
+-	op->info.start		= fl->fl_start;
+-	op->info.end		= fl->fl_end;
+-	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
+-		op->info.owner	= (__u64) fl->fl_pid;
+-	else
+-		op->info.owner	= (__u64)(long) fl->fl_owner;
+-
+-	send_op(op);
+-	wait_event(recv_wq, (op->done != 0));
+-
+-	spin_lock(&ops_lock);
+-	if (!list_empty(&op->list)) {
+-		printk(KERN_INFO "plock_get op on list\n");
+-		list_del(&op->list);
+-	}
+-	spin_unlock(&ops_lock);
+-
+-	/* info.rv from userspace is 1 for conflict, 0 for no-conflict,
+-	   -ENOENT if there are no locks on the file */
+-
+-	rv = op->info.rv;
+-
+-	fl->fl_type = F_UNLCK;
+-	if (rv == -ENOENT)
+-		rv = 0;
+-	else if (rv > 0) {
+-		fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
+-		fl->fl_pid = op->info.pid;
+-		fl->fl_start = op->info.start;
+-		fl->fl_end = op->info.end;
+-		rv = 0;
+-	}
+-
+-	kfree(op);
+-	return rv;
+-}
+-
+-/* a read copies out one plock request from the send list */
+-static ssize_t dev_read(struct file *file, char __user *u, size_t count,
+-			loff_t *ppos)
+-{
+-	struct gdlm_plock_info info;
+-	struct plock_op *op = NULL;
+-
+-	if (count < sizeof(info))
+-		return -EINVAL;
+-
+-	spin_lock(&ops_lock);
+-	if (!list_empty(&send_list)) {
+-		op = list_entry(send_list.next, struct plock_op, list);
+-		list_move(&op->list, &recv_list);
+-		memcpy(&info, &op->info, sizeof(info));
+-	}
+-	spin_unlock(&ops_lock);
+-
+-	if (!op)
+-		return -EAGAIN;
+-
+-	if (copy_to_user(u, &info, sizeof(info)))
+-		return -EFAULT;
+-	return sizeof(info);
+-}
+-
+-/* a write copies in one plock result that should match a plock_op
+-   on the recv list */
+-static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
+-			 loff_t *ppos)
+-{
+-	struct gdlm_plock_info info;
+-	struct plock_op *op;
+-	int found = 0;
+-
+-	if (count != sizeof(info))
+-		return -EINVAL;
+-
+-	if (copy_from_user(&info, u, sizeof(info)))
+-		return -EFAULT;
+-
+-	if (check_version(&info))
+-		return -EINVAL;
+-
+-	spin_lock(&ops_lock);
+-	list_for_each_entry(op, &recv_list, list) {
+-		if (op->info.fsid == info.fsid && op->info.number == info.number &&
+-		    op->info.owner == info.owner) {
+-			list_del_init(&op->list);
+-			found = 1;
+-			op->done = 1;
+-			memcpy(&op->info, &info, sizeof(info));
+-			break;
+-		}
+-	}
+-	spin_unlock(&ops_lock);
+-
+-	if (found) {
+-		struct plock_xop *xop;
+-		xop = (struct plock_xop *)op;
+-		if (xop->callback)
+-			count = gdlm_plock_callback(op);
+-		else
+-			wake_up(&recv_wq);
+-	} else
+-		printk(KERN_INFO "gdlm dev_write no op %x %llx\n", info.fsid,
+-			(unsigned long long)info.number);
+-	return count;
+-}
+-
+-static unsigned int dev_poll(struct file *file, poll_table *wait)
+-{
+-	unsigned int mask = 0;
+-
+-	poll_wait(file, &send_wq, wait);
+-
+-	spin_lock(&ops_lock);
+-	if (!list_empty(&send_list))
+-		mask = POLLIN | POLLRDNORM;
+-	spin_unlock(&ops_lock);
+-
+-	return mask;
+-}
+-
+-static const struct file_operations dev_fops = {
+-	.read    = dev_read,
+-	.write   = dev_write,
+-	.poll    = dev_poll,
+-	.owner   = THIS_MODULE
+-};
+-
+-static struct miscdevice plock_dev_misc = {
+-	.minor = MISC_DYNAMIC_MINOR,
+-	.name = GDLM_PLOCK_MISC_NAME,
+-	.fops = &dev_fops
+-};
+-
+-int gdlm_plock_init(void)
+-{
+-	int rv;
+-
+-	spin_lock_init(&ops_lock);
+-	INIT_LIST_HEAD(&send_list);
+-	INIT_LIST_HEAD(&recv_list);
+-	init_waitqueue_head(&send_wq);
+-	init_waitqueue_head(&recv_wq);
+-
+-	rv = misc_register(&plock_dev_misc);
+-	if (rv)
+-		printk(KERN_INFO "gdlm_plock_init: misc_register failed %d",
+-		       rv);
+-	return rv;
+-}
+-
+-void gdlm_plock_exit(void)
+-{
+-	if (misc_deregister(&plock_dev_misc) < 0)
+-		printk(KERN_INFO "gdlm_plock_exit: misc_deregister failed");
+-}
+-
+diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c
+index a87b098..8479da4 100644
+--- a/fs/gfs2/locking/dlm/sysfs.c
++++ b/fs/gfs2/locking/dlm/sysfs.c
+@@ -12,8 +12,6 @@
+ 
+ #include "lock_dlm.h"
+ 
+-extern struct lm_lockops gdlm_ops;
+-
+ static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf)
+ {
+ 	return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name);
+diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c
+index 521694f..e53db6f 100644
+--- a/fs/gfs2/locking/dlm/thread.c
++++ b/fs/gfs2/locking/dlm/thread.c
+@@ -135,7 +135,15 @@ static void process_complete(struct gdlm_lock *lp)
+ 			 lp->lksb.sb_status, lp->lockname.ln_type,
+ 			 (unsigned long long)lp->lockname.ln_number,
+ 			 lp->flags);
+-		return;
++		if (lp->lksb.sb_status == -EDEADLOCK &&
++		    lp->ls->fsflags & LM_MFLAG_CONV_NODROP) {
++			lp->req = lp->cur;
++			acb.lc_ret |= LM_OUT_CONV_DEADLK;
++			if (lp->cur == DLM_LOCK_IV)
++				lp->lksb.sb_lkid = 0;
++			goto out;
++		} else
++			return;
+ 	}
+ 
+ 	/*
+diff --git a/fs/gfs2/locking/nolock/main.c b/fs/gfs2/locking/nolock/main.c
+index d3b8ce6..284a5ec 100644
+--- a/fs/gfs2/locking/nolock/main.c
++++ b/fs/gfs2/locking/nolock/main.c
+@@ -140,7 +140,7 @@ static int nolock_hold_lvb(void *lock, char **lvbp)
+ 	struct nolock_lockspace *nl = lock;
+ 	int error = 0;
+ 
+-	*lvbp = kzalloc(nl->nl_lvb_size, GFP_KERNEL);
++	*lvbp = kzalloc(nl->nl_lvb_size, GFP_NOFS);
+ 	if (!*lvbp)
+ 		error = -ENOMEM;
+ 
+diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
+index 161ab6f..548264b 100644
+--- a/fs/gfs2/log.c
++++ b/fs/gfs2/log.c
+@@ -769,8 +769,8 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+ 	sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
+ 	gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
+ 	reserved = calc_reserved(sdp);
++	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved);
+ 	unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
+-	gfs2_assert_withdraw(sdp, unused >= 0);
+ 	atomic_add(unused, &sdp->sd_log_blks_free);
+ 	gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
+ 			     sdp->sd_jdesc->jd_blocks);
+@@ -779,6 +779,21 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+ 	gfs2_log_unlock(sdp);
+ }
+ 
++static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
++{
++	struct list_head *head = &tr->tr_list_buf;
++	struct gfs2_bufdata *bd;
++
++	gfs2_log_lock(sdp);
++	while (!list_empty(head)) {
++		bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
++		list_del_init(&bd->bd_list_tr);
++		tr->tr_num_buf--;
++	}
++	gfs2_log_unlock(sdp);
++	gfs2_assert_warn(sdp, !tr->tr_num_buf);
++}
++
+ /**
+  * gfs2_log_commit - Commit a transaction to the log
+  * @sdp: the filesystem
+@@ -790,7 +805,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+ {
+ 	log_refund(sdp, tr);
+-	lops_incore_commit(sdp, tr);
++	buf_lo_incore_commit(sdp, tr);
+ 
+ 	sdp->sd_vfs->s_dirt = 1;
+ 	up_read(&sdp->sd_log_flush_lock);
+diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
+index fae59d6..4390f6f 100644
+--- a/fs/gfs2/lops.c
++++ b/fs/gfs2/lops.c
+@@ -152,21 +152,6 @@ out:
+ 	unlock_buffer(bd->bd_bh);
+ }
+ 
+-static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+-{
+-	struct list_head *head = &tr->tr_list_buf;
+-	struct gfs2_bufdata *bd;
+-
+-	gfs2_log_lock(sdp);
+-	while (!list_empty(head)) {
+-		bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
+-		list_del_init(&bd->bd_list_tr);
+-		tr->tr_num_buf--;
+-	}
+-	gfs2_log_unlock(sdp);
+-	gfs2_assert_warn(sdp, !tr->tr_num_buf);
+-}
+-
+ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
+ {
+ 	struct buffer_head *bh;
+@@ -419,8 +404,10 @@ static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
+ 			blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset));
+ 
+ 			error = gfs2_revoke_add(sdp, blkno, start);
+-			if (error < 0)
++			if (error < 0) {
++				brelse(bh);
+ 				return error;
++			}
+ 			else if (error)
+ 				sdp->sd_found_revokes++;
+ 
+@@ -737,7 +724,6 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
+ 
+ const struct gfs2_log_operations gfs2_buf_lops = {
+ 	.lo_add = buf_lo_add,
+-	.lo_incore_commit = buf_lo_incore_commit,
+ 	.lo_before_commit = buf_lo_before_commit,
+ 	.lo_after_commit = buf_lo_after_commit,
+ 	.lo_before_scan = buf_lo_before_scan,
+@@ -763,7 +749,6 @@ const struct gfs2_log_operations gfs2_rg_lops = {
+ 
+ const struct gfs2_log_operations gfs2_databuf_lops = {
+ 	.lo_add = databuf_lo_add,
+-	.lo_incore_commit = buf_lo_incore_commit,
+ 	.lo_before_commit = databuf_lo_before_commit,
+ 	.lo_after_commit = databuf_lo_after_commit,
+ 	.lo_scan_elements = databuf_lo_scan_elements,
+diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
+index 41a00df..3c0b273 100644
+--- a/fs/gfs2/lops.h
++++ b/fs/gfs2/lops.h
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+  *
+  * This copyrighted material is made available to anyone wishing to use,
+  * modify, copy, or redistribute it subject to the terms and conditions
+@@ -57,15 +57,6 @@ static inline void lops_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
+ 		le->le_ops->lo_add(sdp, le);
+ }
+ 
+-static inline void lops_incore_commit(struct gfs2_sbd *sdp,
+-				      struct gfs2_trans *tr)
+-{
+-	int x;
+-	for (x = 0; gfs2_log_ops[x]; x++)
+-		if (gfs2_log_ops[x]->lo_incore_commit)
+-			gfs2_log_ops[x]->lo_incore_commit(sdp, tr);
+-}
+-
+ static inline void lops_before_commit(struct gfs2_sbd *sdp)
+ {
+ 	int x;
+diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
+index 9c7765c..053e2eb 100644
+--- a/fs/gfs2/main.c
++++ b/fs/gfs2/main.c
+@@ -89,6 +89,12 @@ static int __init init_gfs2_fs(void)
+ 	if (!gfs2_bufdata_cachep)
+ 		goto fail;
+ 
++	gfs2_rgrpd_cachep = kmem_cache_create("gfs2_rgrpd",
++					      sizeof(struct gfs2_rgrpd),
++					      0, 0, NULL);
++	if (!gfs2_rgrpd_cachep)
++		goto fail;
++
+ 	error = register_filesystem(&gfs2_fs_type);
+ 	if (error)
+ 		goto fail;
+@@ -108,6 +114,9 @@ fail_unregister:
+ fail:
+ 	gfs2_glock_exit();
+ 
++	if (gfs2_rgrpd_cachep)
++		kmem_cache_destroy(gfs2_rgrpd_cachep);
++
+ 	if (gfs2_bufdata_cachep)
+ 		kmem_cache_destroy(gfs2_bufdata_cachep);
+ 
+@@ -133,6 +142,7 @@ static void __exit exit_gfs2_fs(void)
+ 	unregister_filesystem(&gfs2_fs_type);
+ 	unregister_filesystem(&gfs2meta_fs_type);
+ 
++	kmem_cache_destroy(gfs2_rgrpd_cachep);
+ 	kmem_cache_destroy(gfs2_bufdata_cachep);
+ 	kmem_cache_destroy(gfs2_inode_cachep);
+ 	kmem_cache_destroy(gfs2_glock_cachep);
+diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
+index ac772b6..90a04a6 100644
+--- a/fs/gfs2/ops_address.c
++++ b/fs/gfs2/ops_address.c
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+  *
+  * This copyrighted material is made available to anyone wishing to use,
+  * modify, copy, or redistribute it subject to the terms and conditions
+@@ -21,7 +21,6 @@
+ #include <linux/gfs2_ondisk.h>
+ #include <linux/lm_interface.h>
+ #include <linux/backing-dev.h>
+-#include <linux/pagevec.h>
+ 
+ #include "gfs2.h"
+ #include "incore.h"
+@@ -104,11 +103,9 @@ static int gfs2_writepage_common(struct page *page,
+ 	loff_t i_size = i_size_read(inode);
+ 	pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
+ 	unsigned offset;
+-	int ret = -EIO;
+ 
+ 	if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
+ 		goto out;
+-	ret = 0;
+ 	if (current->journal_info)
+ 		goto redirty;
+ 	/* Is the page fully outside i_size? (truncate in progress) */
+@@ -280,7 +277,7 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,
+ 	int i;
+ 	int ret;
+ 
+-	ret = gfs2_trans_begin(sdp, nrblocks, 0);
++	ret = gfs2_trans_begin(sdp, nrblocks, nrblocks);
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -510,23 +507,26 @@ static int __gfs2_readpage(void *file, struct page *page)
+ static int gfs2_readpage(struct file *file, struct page *page)
+ {
+ 	struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+-	struct gfs2_holder gh;
++	struct gfs2_holder *gh;
+ 	int error;
+ 
+-	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
+-	error = gfs2_glock_nq_atime(&gh);
+-	if (unlikely(error)) {
++	gh = gfs2_glock_is_locked_by_me(ip->i_gl);
++	if (!gh) {
++		gh = kmalloc(sizeof(struct gfs2_holder), GFP_NOFS);
++		if (!gh)
++			return -ENOBUFS;
++		gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, gh);
+ 		unlock_page(page);
+-		goto out;
++		error = gfs2_glock_nq_atime(gh);
++		if (likely(error != 0))
++			goto out;
++		return AOP_TRUNCATED_PAGE;
+ 	}
+ 	error = __gfs2_readpage(file, page);
+-	gfs2_glock_dq(&gh);
++	gfs2_glock_dq(gh);
+ out:
+-	gfs2_holder_uninit(&gh);
+-	if (error == GLR_TRYFAILED) {
+-		yield();
+-		return AOP_TRUNCATED_PAGE;
+-	}
++	gfs2_holder_uninit(gh);
++	kfree(gh);
+ 	return error;
+ }
+ 
+@@ -648,15 +648,15 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
+ 
+ 	if (alloc_required) {
+ 		al = gfs2_alloc_get(ip);
++		if (!al) {
++			error = -ENOMEM;
++			goto out_unlock;
++		}
+ 
+-		error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++		error = gfs2_quota_lock_check(ip);
+ 		if (error)
+ 			goto out_alloc_put;
+ 
+-		error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
+-		if (error)
+-			goto out_qunlock;
+-
+ 		al->al_requested = data_blocks + ind_blocks;
+ 		error = gfs2_inplace_reserve(ip);
+ 		if (error)
+@@ -828,7 +828,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
+ 	unsigned int to = from + len;
+ 	int ret;
+ 
+-	BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == 0);
++	BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL);
+ 
+ 	ret = gfs2_meta_inode_buffer(ip, &dibh);
+ 	if (unlikely(ret)) {
+diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
+index 793e334..4a5e676 100644
+--- a/fs/gfs2/ops_dentry.c
++++ b/fs/gfs2/ops_dentry.c
+@@ -43,7 +43,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
+ 	struct gfs2_holder d_gh;
+ 	struct gfs2_inode *ip = NULL;
+ 	int error;
+-	int had_lock=0;
++	int had_lock = 0;
+ 
+ 	if (inode) {
+ 		if (is_bad_inode(inode))
+@@ -54,7 +54,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
+ 	if (sdp->sd_args.ar_localcaching)
+ 		goto valid;
+ 
+-	had_lock = gfs2_glock_is_locked_by_me(dip->i_gl);
++	had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
+ 	if (!had_lock) {
+ 		error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
+ 		if (error)
+diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
+index 334c7f8..990d9f4 100644
+--- a/fs/gfs2/ops_export.c
++++ b/fs/gfs2/ops_export.c
+@@ -204,8 +204,6 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
+ 	inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
+ 					inum->no_addr,
+ 					0, 0);
+-	if (!inode)
+-		goto fail;
+ 	if (IS_ERR(inode)) {
+ 		error = PTR_ERR(inode);
+ 		goto fail;
+diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
+index f4842f2..e1b7d52 100644
+--- a/fs/gfs2/ops_file.c
++++ b/fs/gfs2/ops_file.c
+@@ -30,7 +30,6 @@
+ #include "glock.h"
+ #include "glops.h"
+ #include "inode.h"
+-#include "lm.h"
+ #include "log.h"
+ #include "meta_io.h"
+ #include "quota.h"
+@@ -39,6 +38,7 @@
+ #include "util.h"
+ #include "eaops.h"
+ #include "ops_address.h"
++#include "ops_inode.h"
+ 
+ /**
+  * gfs2_llseek - seek to a location in a file
+@@ -369,12 +369,9 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+ 	if (al == NULL)
+ 		goto out_unlock;
+ 
+-	ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++	ret = gfs2_quota_lock_check(ip);
+ 	if (ret)
+ 		goto out_alloc_put;
+-	ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
+-	if (ret)
+-		goto out_quota_unlock;
+ 	al->al_requested = data_blocks + ind_blocks;
+ 	ret = gfs2_inplace_reserve(ip);
+ 	if (ret)
+@@ -596,6 +593,36 @@ static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl)
+ 	return generic_setlease(file, arg, fl);
+ }
+ 
++static int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name,
++		      struct file *file, struct file_lock *fl)
++{
++	int error = -EIO;
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		error = sdp->sd_lockstruct.ls_ops->lm_plock_get(
++				sdp->sd_lockstruct.ls_lockspace, name, file, fl);
++	return error;
++}
++
++static int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name,
++		  struct file *file, int cmd, struct file_lock *fl)
++{
++	int error = -EIO;
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		error = sdp->sd_lockstruct.ls_ops->lm_plock(
++				sdp->sd_lockstruct.ls_lockspace, name, file, cmd, fl);
++	return error;
++}
++
++static int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name,
++		    struct file *file, struct file_lock *fl)
++{
++	int error = -EIO;
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		error = sdp->sd_lockstruct.ls_ops->lm_punlock(
++				sdp->sd_lockstruct.ls_lockspace, name, file, fl);
++	return error;
++}
++
+ /**
+  * gfs2_lock - acquire/release a posix lock on a file
+  * @file: the file pointer
+diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
+index 4bee6aa..ef9c6c4 100644
+--- a/fs/gfs2/ops_fstype.c
++++ b/fs/gfs2/ops_fstype.c
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+  *
+  * This copyrighted material is made available to anyone wishing to use,
+  * modify, copy, or redistribute it subject to the terms and conditions
+@@ -26,7 +26,6 @@
+ #include "glock.h"
+ #include "glops.h"
+ #include "inode.h"
+-#include "lm.h"
+ #include "mount.h"
+ #include "ops_fstype.h"
+ #include "ops_dentry.h"
+@@ -363,6 +362,13 @@ static int map_journal_extents(struct gfs2_sbd *sdp)
+ 	return rc;
+ }
+ 
++static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
++{
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		sdp->sd_lockstruct.ls_ops->lm_others_may_mount(
++					sdp->sd_lockstruct.ls_lockspace);
++}
++
+ static int init_journal(struct gfs2_sbd *sdp, int undo)
+ {
+ 	struct gfs2_holder ji_gh;
+@@ -542,7 +548,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
+ 	}
+ 	ip = GFS2_I(sdp->sd_rindex);
+ 	set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
+-	sdp->sd_rindex_vn = ip->i_gl->gl_vn - 1;
++	sdp->sd_rindex_uptodate = 0;
+ 
+ 	/* Read in the quota inode */
+ 	sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota");
+@@ -705,6 +711,69 @@ fail:
+ }
+ 
+ /**
++ * gfs2_lm_mount - mount a locking protocol
++ * @sdp: the filesystem
++ * @args: mount arguements
++ * @silent: if 1, don't complain if the FS isn't a GFS2 fs
++ *
++ * Returns: errno
++ */
++
++static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
++{
++	char *proto = sdp->sd_proto_name;
++	char *table = sdp->sd_table_name;
++	int flags = LM_MFLAG_CONV_NODROP;
++	int error;
++
++	if (sdp->sd_args.ar_spectator)
++		flags |= LM_MFLAG_SPECTATOR;
++
++	fs_info(sdp, "Trying to join cluster \"%s\", \"%s\"\n", proto, table);
++
++	error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata,
++				     gfs2_glock_cb, sdp,
++				     GFS2_MIN_LVB_SIZE, flags,
++				     &sdp->sd_lockstruct, &sdp->sd_kobj);
++	if (error) {
++		fs_info(sdp, "can't mount proto=%s, table=%s, hostdata=%s\n",
++			proto, table, sdp->sd_args.ar_hostdata);
++		goto out;
++	}
++
++	if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) ||
++	    gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) ||
++	    gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >=
++				  GFS2_MIN_LVB_SIZE)) {
++		gfs2_unmount_lockproto(&sdp->sd_lockstruct);
++		goto out;
++	}
++
++	if (sdp->sd_args.ar_spectator)
++		snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.s", table);
++	else
++		snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.%u", table,
++			 sdp->sd_lockstruct.ls_jid);
++
++	fs_info(sdp, "Joined cluster. Now mounting FS...\n");
++
++	if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) &&
++	    !sdp->sd_args.ar_ignore_local_fs) {
++		sdp->sd_args.ar_localflocks = 1;
++		sdp->sd_args.ar_localcaching = 1;
++	}
++
++out:
++	return error;
++}
++
++void gfs2_lm_unmount(struct gfs2_sbd *sdp)
++{
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		gfs2_unmount_lockproto(&sdp->sd_lockstruct);
++}
++
++/**
+  * fill_super - Read in superblock
+  * @sb: The VFS superblock
+  * @data: Mount options
+@@ -874,7 +943,6 @@ static struct super_block* get_gfs2_sb(const char *dev_name)
+ {
+ 	struct kstat stat;
+ 	struct nameidata nd;
+-	struct file_system_type *fstype;
+ 	struct super_block *sb = NULL, *s;
+ 	int error;
+ 
+@@ -886,8 +954,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name)
+ 	}
+ 	error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat);
+ 
+-	fstype = get_fs_type("gfs2");
+-	list_for_each_entry(s, &fstype->fs_supers, s_instances) {
++	list_for_each_entry(s, &gfs2_fs_type.fs_supers, s_instances) {
+ 		if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) ||
+ 		    (S_ISDIR(stat.mode) &&
+ 		     s == nd.path.dentry->d_inode->i_sb)) {
+@@ -931,7 +998,6 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags,
+ 		error = PTR_ERR(new);
+ 		goto error;
+ 	}
+-	module_put(fs_type->owner);
+ 	new->s_flags = flags;
+ 	strlcpy(new->s_id, sb->s_id, sizeof(new->s_id));
+ 	sb_set_blocksize(new, sb->s_blocksize);
+diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
+index e874129..2686ad4 100644
+--- a/fs/gfs2/ops_inode.c
++++ b/fs/gfs2/ops_inode.c
+@@ -200,15 +200,15 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
+ 
+ 	if (alloc_required) {
+ 		struct gfs2_alloc *al = gfs2_alloc_get(dip);
++		if (!al) {
++			error = -ENOMEM;
++			goto out_gunlock;
++		}
+ 
+-		error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++		error = gfs2_quota_lock_check(dip);
+ 		if (error)
+ 			goto out_alloc;
+ 
+-		error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
+-		if (error)
+-			goto out_gunlock_q;
+-
+ 		al->al_requested = sdp->sd_max_dirres;
+ 
+ 		error = gfs2_inplace_reserve(dip);
+@@ -716,15 +716,15 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
+ 
+ 	if (alloc_required) {
+ 		struct gfs2_alloc *al = gfs2_alloc_get(ndip);
++		if (!al) {
++			error = -ENOMEM;
++			goto out_gunlock;
++		}
+ 
+-		error = gfs2_quota_lock(ndip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++		error = gfs2_quota_lock_check(ndip);
+ 		if (error)
+ 			goto out_alloc;
+ 
+-		error = gfs2_quota_check(ndip, ndip->i_inode.i_uid, ndip->i_inode.i_gid);
+-		if (error)
+-			goto out_gunlock_q;
+-
+ 		al->al_requested = sdp->sd_max_dirres;
+ 
+ 		error = gfs2_inplace_reserve(ndip);
+@@ -898,7 +898,7 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
+ 	int error;
+ 	int unlock = 0;
+ 
+-	if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
++	if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
+ 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
+ 		if (error)
+ 			return error;
+@@ -953,7 +953,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
+ 	if (!(attr->ia_valid & ATTR_GID) || ogid == ngid)
+ 		ogid = ngid = NO_QUOTA_CHANGE;
+ 
+-	gfs2_alloc_get(ip);
++	if (!gfs2_alloc_get(ip))
++		return -ENOMEM;
+ 
+ 	error = gfs2_quota_lock(ip, nuid, ngid);
+ 	if (error)
+@@ -981,8 +982,9 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
+ 	brelse(dibh);
+ 
+ 	if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
+-		gfs2_quota_change(ip, -ip->i_di.di_blocks, ouid, ogid);
+-		gfs2_quota_change(ip, ip->i_di.di_blocks, nuid, ngid);
++		u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
++		gfs2_quota_change(ip, -blocks, ouid, ogid);
++		gfs2_quota_change(ip, blocks, nuid, ngid);
+ 	}
+ 
+ out_end_trans:
+@@ -1064,7 +1066,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ 	int error;
+ 	int unlock = 0;
+ 
+-	if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
++	if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
+ 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
+ 		if (error)
+ 			return error;
+@@ -1148,16 +1150,6 @@ const struct inode_operations gfs2_file_iops = {
+ 	.removexattr = gfs2_removexattr,
+ };
+ 
+-const struct inode_operations gfs2_dev_iops = {
+-	.permission = gfs2_permission,
+-	.setattr = gfs2_setattr,
+-	.getattr = gfs2_getattr,
+-	.setxattr = gfs2_setxattr,
+-	.getxattr = gfs2_getxattr,
+-	.listxattr = gfs2_listxattr,
+-	.removexattr = gfs2_removexattr,
+-};
+-
+ const struct inode_operations gfs2_dir_iops = {
+ 	.create = gfs2_create,
+ 	.lookup = gfs2_lookup,
+diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h
+index fd8cee2..14b4b79 100644
+--- a/fs/gfs2/ops_inode.h
++++ b/fs/gfs2/ops_inode.h
+@@ -15,7 +15,6 @@
+ extern const struct inode_operations gfs2_file_iops;
+ extern const struct inode_operations gfs2_dir_iops;
+ extern const struct inode_operations gfs2_symlink_iops;
+-extern const struct inode_operations gfs2_dev_iops;
+ extern const struct file_operations gfs2_file_fops;
+ extern const struct file_operations gfs2_dir_fops;
+ extern const struct file_operations gfs2_file_fops_nolock;
+diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
+index 5e52421..2278c68 100644
+--- a/fs/gfs2/ops_super.c
++++ b/fs/gfs2/ops_super.c
+@@ -25,7 +25,6 @@
+ #include "incore.h"
+ #include "glock.h"
+ #include "inode.h"
+-#include "lm.h"
+ #include "log.h"
+ #include "mount.h"
+ #include "ops_super.h"
+diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
+index a08dabd..56aaf91 100644
+--- a/fs/gfs2/quota.c
++++ b/fs/gfs2/quota.c
+@@ -94,7 +94,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
+ 	struct gfs2_quota_data *qd;
+ 	int error;
+ 
+-	qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_KERNEL);
++	qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_NOFS);
+ 	if (!qd)
+ 		return -ENOMEM;
+ 
+@@ -616,16 +616,9 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
+ 	s64 value;
+ 	int err = -EIO;
+ 
+-	if (gfs2_is_stuffed(ip)) {
+-		struct gfs2_alloc *al = NULL;
+-		al = gfs2_alloc_get(ip);
+-		/* just request 1 blk */
+-		al->al_requested = 1;
+-		gfs2_inplace_reserve(ip);
++	if (gfs2_is_stuffed(ip))
+ 		gfs2_unstuff_dinode(ip, NULL);
+-		gfs2_inplace_release(ip);
+-		gfs2_alloc_put(ip);
+-	}
++	
+ 	page = grab_cache_page(mapping, index);
+ 	if (!page)
+ 		return -ENOMEM;
+@@ -690,14 +683,14 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
+ 	unsigned int qx, x;
+ 	struct gfs2_quota_data *qd;
+ 	loff_t offset;
+-	unsigned int nalloc = 0;
++	unsigned int nalloc = 0, blocks;
+ 	struct gfs2_alloc *al = NULL;
+ 	int error;
+ 
+ 	gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
+ 			      &data_blocks, &ind_blocks);
+ 
+-	ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_KERNEL);
++	ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_NOFS);
+ 	if (!ghs)
+ 		return -ENOMEM;
+ 
+@@ -727,30 +720,33 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
+ 			nalloc++;
+ 	}
+ 
+-	if (nalloc) {
+-		al = gfs2_alloc_get(ip);
++	al = gfs2_alloc_get(ip);
++	if (!al) {
++		error = -ENOMEM;
++		goto out_gunlock;
++	}
++	/* 
++	 * 1 blk for unstuffing inode if stuffed. We add this extra
++	 * block to the reservation unconditionally. If the inode
++	 * doesn't need unstuffing, the block will be released to the 
++	 * rgrp since it won't be allocated during the transaction
++	 */
++	al->al_requested = 1;
++	/* +1 in the end for block requested above for unstuffing */
++	blocks = num_qd * data_blocks + RES_DINODE + num_qd + 1;
+ 
+-		al->al_requested = nalloc * (data_blocks + ind_blocks);
++	if (nalloc)
++		al->al_requested += nalloc * (data_blocks + ind_blocks);		
++	error = gfs2_inplace_reserve(ip);
++	if (error)
++		goto out_alloc;
+ 
+-		error = gfs2_inplace_reserve(ip);
+-		if (error)
+-			goto out_alloc;
+-
+-		error = gfs2_trans_begin(sdp,
+-					 al->al_rgd->rd_length +
+-					 num_qd * data_blocks +
+-					 nalloc * ind_blocks +
+-					 RES_DINODE + num_qd +
+-					 RES_STATFS, 0);
+-		if (error)
+-			goto out_ipres;
+-	} else {
+-		error = gfs2_trans_begin(sdp,
+-					 num_qd * data_blocks +
+-					 RES_DINODE + num_qd, 0);
+-		if (error)
+-			goto out_gunlock;
+-	}
++	if (nalloc)
++		blocks += al->al_rgd->rd_length + nalloc * ind_blocks + RES_STATFS;
++
++	error = gfs2_trans_begin(sdp, blocks, 0);
++	if (error)
++		goto out_ipres;
+ 
+ 	for (x = 0; x < num_qd; x++) {
+ 		qd = qda[x];
+@@ -769,11 +765,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
+ out_end_trans:
+ 	gfs2_trans_end(sdp);
+ out_ipres:
+-	if (nalloc)
+-		gfs2_inplace_release(ip);
++	gfs2_inplace_release(ip);
+ out_alloc:
+-	if (nalloc)
+-		gfs2_alloc_put(ip);
++	gfs2_alloc_put(ip);
+ out_gunlock:
+ 	gfs2_glock_dq_uninit(&i_gh);
+ out:
+@@ -1124,12 +1118,12 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
+ 	error = -ENOMEM;
+ 
+ 	sdp->sd_quota_bitmap = kcalloc(sdp->sd_quota_chunks,
+-				       sizeof(unsigned char *), GFP_KERNEL);
++				       sizeof(unsigned char *), GFP_NOFS);
+ 	if (!sdp->sd_quota_bitmap)
+ 		return error;
+ 
+ 	for (x = 0; x < sdp->sd_quota_chunks; x++) {
+-		sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_KERNEL);
++		sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_NOFS);
+ 		if (!sdp->sd_quota_bitmap[x])
+ 			goto fail;
+ 	}
+diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
+index a8be141..3b7f4b0 100644
+--- a/fs/gfs2/quota.h
++++ b/fs/gfs2/quota.h
+@@ -32,4 +32,21 @@ int gfs2_quota_init(struct gfs2_sbd *sdp);
+ void gfs2_quota_scan(struct gfs2_sbd *sdp);
+ void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
+ 
++static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
++{
++	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
++	int ret;
++	if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
++		return 0;
++	ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++	if (ret)
++		return ret;
++	if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
++		return 0;
++	ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
++	if (ret)
++		gfs2_quota_unlock(ip);
++	return ret;
++}
++
+ #endif /* __QUOTA_DOT_H__ */
+diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
+index 6fb07d6..2888e4b 100644
+--- a/fs/gfs2/recovery.c
++++ b/fs/gfs2/recovery.c
+@@ -20,7 +20,6 @@
+ #include "bmap.h"
+ #include "glock.h"
+ #include "glops.h"
+-#include "lm.h"
+ #include "lops.h"
+ #include "meta_io.h"
+ #include "recovery.h"
+@@ -69,7 +68,7 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)
+ 		return 0;
+ 	}
+ 
+-	rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_KERNEL);
++	rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_NOFS);
+ 	if (!rr)
+ 		return -ENOMEM;
+ 
+@@ -150,7 +149,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
+ 			  struct gfs2_log_header_host *head)
+ {
+ 	struct buffer_head *bh;
+-	struct gfs2_log_header_host lh;
++	struct gfs2_log_header_host uninitialized_var(lh);
+ 	const u32 nothing = 0;
+ 	u32 hash;
+ 	int error;
+@@ -425,6 +424,16 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea
+ 	return error;
+ }
+ 
++
++static void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
++				  unsigned int message)
++{
++	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++		sdp->sd_lockstruct.ls_ops->lm_recovery_done(
++			sdp->sd_lockstruct.ls_lockspace, jid, message);
++}
++
++
+ /**
+  * gfs2_recover_journal - recovery a given journal
+  * @jd: the struct gfs2_jdesc describing the journal
+diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
+index 3552110..7e8f0b1 100644
+--- a/fs/gfs2/rgrp.c
++++ b/fs/gfs2/rgrp.c
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+  *
+  * This copyrighted material is made available to anyone wishing to use,
+  * modify, copy, or redistribute it subject to the terms and conditions
+@@ -14,6 +14,7 @@
+ #include <linux/fs.h>
+ #include <linux/gfs2_ondisk.h>
+ #include <linux/lm_interface.h>
++#include <linux/prefetch.h>
+ 
+ #include "gfs2.h"
+ #include "incore.h"
+@@ -33,6 +34,16 @@
+ #define BFITNOENT ((u32)~0)
+ #define NO_BLOCK ((u64)~0)
+ 
++#if BITS_PER_LONG == 32
++#define LBITMASK   (0x55555555UL)
++#define LBITSKIP55 (0x55555555UL)
++#define LBITSKIP00 (0x00000000UL)
++#else
++#define LBITMASK   (0x5555555555555555UL)
++#define LBITSKIP55 (0x5555555555555555UL)
++#define LBITSKIP00 (0x0000000000000000UL)
++#endif
++
+ /*
+  * These routines are used by the resource group routines (rgrp.c)
+  * to keep track of block allocation.  Each block is represented by two
+@@ -53,7 +64,8 @@ static const char valid_change[16] = {
+ };
+ 
+ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+-                        unsigned char old_state, unsigned char new_state);
++                        unsigned char old_state, unsigned char new_state,
++			unsigned int *n);
+ 
+ /**
+  * gfs2_setbit - Set a bit in the bitmaps
+@@ -64,26 +76,32 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+  *
+  */
+ 
+-static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+-			unsigned int buflen, u32 block,
+-			unsigned char new_state)
++static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1,
++			       unsigned char *buf2, unsigned int offset,
++			       unsigned int buflen, u32 block,
++			       unsigned char new_state)
+ {
+-	unsigned char *byte, *end, cur_state;
+-	unsigned int bit;
++	unsigned char *byte1, *byte2, *end, cur_state;
++	const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
+ 
+-	byte = buffer + (block / GFS2_NBBY);
+-	bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
+-	end = buffer + buflen;
++	byte1 = buf1 + offset + (block / GFS2_NBBY);
++	end = buf1 + offset + buflen;
+ 
+-	gfs2_assert(rgd->rd_sbd, byte < end);
++	BUG_ON(byte1 >= end);
+ 
+-	cur_state = (*byte >> bit) & GFS2_BIT_MASK;
++	cur_state = (*byte1 >> bit) & GFS2_BIT_MASK;
+ 
+-	if (valid_change[new_state * 4 + cur_state]) {
+-		*byte ^= cur_state << bit;
+-		*byte |= new_state << bit;
+-	} else
++	if (unlikely(!valid_change[new_state * 4 + cur_state])) {
+ 		gfs2_consist_rgrpd(rgd);
++		return;
++	}
++	*byte1 ^= (cur_state ^ new_state) << bit;
++
++	if (buf2) {
++		byte2 = buf2 + offset + (block / GFS2_NBBY);
++		cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
++		*byte2 ^= (cur_state ^ new_state) << bit;
++	}
+ }
+ 
+ /**
+@@ -94,10 +112,12 @@ static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+  *
+  */
+ 
+-static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+-				  unsigned int buflen, u32 block)
++static inline unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd,
++					 const unsigned char *buffer,
++					 unsigned int buflen, u32 block)
+ {
+-	unsigned char *byte, *end, cur_state;
++	const unsigned char *byte, *end;
++	unsigned char cur_state;
+ 	unsigned int bit;
+ 
+ 	byte = buffer + (block / GFS2_NBBY);
+@@ -126,47 +146,66 @@ static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+  * Return: the block number (bitmap buffer scope) that was found
+  */
+ 
+-static u32 gfs2_bitfit(unsigned char *buffer, unsigned int buflen, u32 goal,
+-		       unsigned char old_state)
++static u32 gfs2_bitfit(const u8 *buffer, unsigned int buflen, u32 goal,
++		       u8 old_state)
+ {
+-	unsigned char *byte;
+-	u32 blk = goal;
+-	unsigned int bit, bitlong;
+-	unsigned long *plong, plong55;
+-
+-	byte = buffer + (goal / GFS2_NBBY);
+-	plong = (unsigned long *)(buffer + (goal / GFS2_NBBY));
+-	bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
+-	bitlong = bit;
+-#if BITS_PER_LONG == 32
+-	plong55 = 0x55555555;
+-#else
+-	plong55 = 0x5555555555555555;
+-#endif
+-	while (byte < buffer + buflen) {
+-
+-		if (bitlong == 0 && old_state == 0 && *plong == plong55) {
+-			plong++;
+-			byte += sizeof(unsigned long);
+-			blk += sizeof(unsigned long) * GFS2_NBBY;
+-			continue;
++	const u8 *byte, *start, *end;
++	int bit, startbit;
++	u32 g1, g2, misaligned;
++	unsigned long *plong;
++	unsigned long lskipval;
++
++	lskipval = (old_state & GFS2_BLKST_USED) ? LBITSKIP00 : LBITSKIP55;
++	g1 = (goal / GFS2_NBBY);
++	start = buffer + g1;
++	byte = start;
++        end = buffer + buflen;
++	g2 = ALIGN(g1, sizeof(unsigned long));
++	plong = (unsigned long *)(buffer + g2);
++	startbit = bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
++	misaligned = g2 - g1;
++	if (!misaligned)
++		goto ulong_aligned;
++/* parse the bitmap a byte at a time */
++misaligned:
++	while (byte < end) {
++		if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) {
++			return goal +
++				(((byte - start) * GFS2_NBBY) +
++				 ((bit - startbit) >> 1));
+ 		}
+-		if (((*byte >> bit) & GFS2_BIT_MASK) == old_state)
+-			return blk;
+ 		bit += GFS2_BIT_SIZE;
+-		if (bit >= 8) {
++		if (bit >= GFS2_NBBY * GFS2_BIT_SIZE) {
+ 			bit = 0;
+ 			byte++;
++			misaligned--;
++			if (!misaligned) {
++				plong = (unsigned long *)byte;
++				goto ulong_aligned;
++			}
+ 		}
+-		bitlong += GFS2_BIT_SIZE;
+-		if (bitlong >= sizeof(unsigned long) * 8) {
+-			bitlong = 0;
+-			plong++;
+-		}
+-
+-		blk++;
+ 	}
++	return BFITNOENT;
+ 
++/* parse the bitmap a unsigned long at a time */
++ulong_aligned:
++	/* Stop at "end - 1" or else prefetch can go past the end and segfault.
++	   We could "if" it but we'd lose some of the performance gained.
++	   This way will only slow down searching the very last 4/8 bytes
++	   depending on architecture.  I've experimented with several ways
++	   of writing this section such as using an else before the goto
++	   but this one seems to be the fastest. */
++	while ((unsigned char *)plong < end - 1) {
++		prefetch(plong + 1);
++		if (((*plong) & LBITMASK) != lskipval)
++			break;
++		plong++;
++	}
++	if ((unsigned char *)plong < end) {
++		byte = (const u8 *)plong;
++		misaligned += sizeof(unsigned long) - 1;
++		goto misaligned;
++	}
+ 	return BFITNOENT;
+ }
+ 
+@@ -179,14 +218,14 @@ static u32 gfs2_bitfit(unsigned char *buffer, unsigned int buflen, u32 goal,
+  * Returns: The number of bits
+  */
+ 
+-static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+-			      unsigned int buflen, unsigned char state)
++static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, const u8 *buffer,
++			 unsigned int buflen, u8 state)
+ {
+-	unsigned char *byte = buffer;
+-	unsigned char *end = buffer + buflen;
+-	unsigned char state1 = state << 2;
+-	unsigned char state2 = state << 4;
+-	unsigned char state3 = state << 6;
++	const u8 *byte = buffer;
++	const u8 *end = buffer + buflen;
++	const u8 state1 = state << 2;
++	const u8 state2 = state << 4;
++	const u8 state3 = state << 6;
+ 	u32 count = 0;
+ 
+ 	for (; byte < end; byte++) {
+@@ -353,7 +392,7 @@ static void clear_rgrpdi(struct gfs2_sbd *sdp)
+ 		}
+ 
+ 		kfree(rgd->rd_bits);
+-		kfree(rgd);
++		kmem_cache_free(gfs2_rgrpd_cachep, rgd);
+ 	}
+ }
+ 
+@@ -516,7 +555,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
+ 		return error;
+ 	}
+ 
+-	rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
++	rgd = kmem_cache_zalloc(gfs2_rgrpd_cachep, GFP_NOFS);
+ 	error = -ENOMEM;
+ 	if (!rgd)
+ 		return error;
+@@ -539,7 +578,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
+ 		return error;
+ 
+ 	rgd->rd_gl->gl_object = rgd;
+-	rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
++	rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
+ 	rgd->rd_flags |= GFS2_RDF_CHECK;
+ 	return error;
+ }
+@@ -575,7 +614,7 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
+ 		}
+ 	}
+ 
+-	sdp->sd_rindex_vn = ip->i_gl->gl_vn;
++	sdp->sd_rindex_uptodate = 1;
+ 	return 0;
+ }
+ 
+@@ -609,7 +648,7 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
+ 		}
+ 	}
+ 
+-	sdp->sd_rindex_vn = ip->i_gl->gl_vn;
++	sdp->sd_rindex_uptodate = 1;
+ 	return 0;
+ }
+ 
+@@ -642,9 +681,9 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
+ 		return error;
+ 
+ 	/* Read new copy from disk if we don't have the latest */
+-	if (sdp->sd_rindex_vn != gl->gl_vn) {
++	if (!sdp->sd_rindex_uptodate) {
+ 		mutex_lock(&sdp->sd_rindex_mutex);
+-		if (sdp->sd_rindex_vn != gl->gl_vn) {
++		if (!sdp->sd_rindex_uptodate) {
+ 			error = gfs2_ri_update(ip);
+ 			if (error)
+ 				gfs2_glock_dq_uninit(ri_gh);
+@@ -655,21 +694,31 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
+ 	return error;
+ }
+ 
+-static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
++static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf)
+ {
+ 	const struct gfs2_rgrp *str = buf;
++	struct gfs2_rgrp_host *rg = &rgd->rd_rg;
++	u32 rg_flags;
+ 
+-	rg->rg_flags = be32_to_cpu(str->rg_flags);
++	rg_flags = be32_to_cpu(str->rg_flags);
++	if (rg_flags & GFS2_RGF_NOALLOC)
++		rgd->rd_flags |= GFS2_RDF_NOALLOC;
++	else
++		rgd->rd_flags &= ~GFS2_RDF_NOALLOC;
+ 	rg->rg_free = be32_to_cpu(str->rg_free);
+ 	rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
+ 	rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
+ }
+ 
+-static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
++static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
+ {
+ 	struct gfs2_rgrp *str = buf;
++	struct gfs2_rgrp_host *rg = &rgd->rd_rg;
++	u32 rg_flags = 0;
+ 
+-	str->rg_flags = cpu_to_be32(rg->rg_flags);
++	if (rgd->rd_flags & GFS2_RDF_NOALLOC)
++		rg_flags |= GFS2_RGF_NOALLOC;
++	str->rg_flags = cpu_to_be32(rg_flags);
+ 	str->rg_free = cpu_to_be32(rg->rg_free);
+ 	str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
+ 	str->__pad = cpu_to_be32(0);
+@@ -726,9 +775,9 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
+ 		}
+ 	}
+ 
+-	if (rgd->rd_rg_vn != gl->gl_vn) {
+-		gfs2_rgrp_in(&rgd->rd_rg, (rgd->rd_bits[0].bi_bh)->b_data);
+-		rgd->rd_rg_vn = gl->gl_vn;
++	if (!(rgd->rd_flags & GFS2_RDF_UPTODATE)) {
++		gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data);
++		rgd->rd_flags |= GFS2_RDF_UPTODATE;
+ 	}
+ 
+ 	spin_lock(&sdp->sd_rindex_spin);
+@@ -840,7 +889,7 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
+ 	struct gfs2_sbd *sdp = rgd->rd_sbd;
+ 	int ret = 0;
+ 
+-	if (rgd->rd_rg.rg_flags & GFS2_RGF_NOALLOC)
++	if (rgd->rd_flags & GFS2_RDF_NOALLOC)
+ 		return 0;
+ 
+ 	spin_lock(&sdp->sd_rindex_spin);
+@@ -866,13 +915,15 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+ 	u32 goal = 0, block;
+ 	u64 no_addr;
+ 	struct gfs2_sbd *sdp = rgd->rd_sbd;
++	unsigned int n;
+ 
+ 	for(;;) {
+ 		if (goal >= rgd->rd_data)
+ 			break;
+ 		down_write(&sdp->sd_log_flush_lock);
++		n = 1;
+ 		block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
+-				     GFS2_BLKST_UNLINKED);
++				     GFS2_BLKST_UNLINKED, &n);
+ 		up_write(&sdp->sd_log_flush_lock);
+ 		if (block == BFITNOENT)
+ 			break;
+@@ -904,24 +955,20 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+ static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp,
+ 					    u64 rglast)
+ {
+-	struct gfs2_rgrpd *rgd = NULL;
++	struct gfs2_rgrpd *rgd;
+ 
+ 	spin_lock(&sdp->sd_rindex_spin);
+ 
+-	if (list_empty(&sdp->sd_rindex_recent_list))
+-		goto out;
+-
+-	if (!rglast)
+-		goto first;
+-
+-	list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
+-		if (rgd->rd_addr == rglast)
+-			goto out;
++	if (rglast) {
++		list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
++			if (rgrp_contains_block(rgd, rglast))
++				goto out;
++		}
+ 	}
+-
+-first:
+-	rgd = list_entry(sdp->sd_rindex_recent_list.next, struct gfs2_rgrpd,
+-			 rd_recent);
++	rgd = NULL;
++	if (!list_empty(&sdp->sd_rindex_recent_list))
++		rgd = list_entry(sdp->sd_rindex_recent_list.next,
++				 struct gfs2_rgrpd, rd_recent);
+ out:
+ 	spin_unlock(&sdp->sd_rindex_spin);
+ 	return rgd;
+@@ -1067,7 +1114,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
+ 
+ 	/* Try recently successful rgrps */
+ 
+-	rgd = recent_rgrp_first(sdp, ip->i_last_rg_alloc);
++	rgd = recent_rgrp_first(sdp, ip->i_goal);
+ 
+ 	while (rgd) {
+ 		rg_locked = 0;
+@@ -1151,8 +1198,6 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
+ 	}
+ 
+ out:
+-	ip->i_last_rg_alloc = rgd->rd_addr;
+-
+ 	if (begin) {
+ 		recent_rgrp_add(rgd);
+ 		rgd = gfs2_rgrpd_get_next(rgd);
+@@ -1275,6 +1320,7 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
+  * @goal: the goal block within the RG (start here to search for avail block)
+  * @old_state: GFS2_BLKST_XXX the before-allocation state to find
+  * @new_state: GFS2_BLKST_XXX the after-allocation block state
++ * @n: The extent length
+  *
+  * Walk rgrp's bitmap to find bits that represent a block in @old_state.
+  * Add the found bitmap buffer to the transaction.
+@@ -1290,13 +1336,17 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
+  */
+ 
+ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+-			unsigned char old_state, unsigned char new_state)
++			unsigned char old_state, unsigned char new_state,
++			unsigned int *n)
+ {
+ 	struct gfs2_bitmap *bi = NULL;
+-	u32 length = rgd->rd_length;
++	const u32 length = rgd->rd_length;
+ 	u32 blk = 0;
+ 	unsigned int buf, x;
++	const unsigned int elen = *n;
++	const u8 *buffer;
+ 
++	*n = 0;
+ 	/* Find bitmap block that contains bits for goal block */
+ 	for (buf = 0; buf < length; buf++) {
+ 		bi = rgd->rd_bits + buf;
+@@ -1317,12 +1367,11 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+ 	for (x = 0; x <= length; x++) {
+ 		/* The GFS2_BLKST_UNLINKED state doesn't apply to the clone
+ 		   bitmaps, so we must search the originals for that. */
++		buffer = bi->bi_bh->b_data + bi->bi_offset;
+ 		if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone)
+-			blk = gfs2_bitfit(bi->bi_clone + bi->bi_offset,
+-					  bi->bi_len, goal, old_state);
+-		else
+-			blk = gfs2_bitfit(bi->bi_bh->b_data + bi->bi_offset,
+-					  bi->bi_len, goal, old_state);
++			buffer = bi->bi_clone + bi->bi_offset;
++
++		blk = gfs2_bitfit(buffer, bi->bi_len, goal, old_state);
+ 		if (blk != BFITNOENT)
+ 			break;
+ 
+@@ -1333,12 +1382,23 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+ 	}
+ 
+ 	if (blk != BFITNOENT && old_state != new_state) {
++		*n = 1;
+ 		gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
+-		gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
++		gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset,
+ 			    bi->bi_len, blk, new_state);
+-		if (bi->bi_clone)
+-			gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+-				    bi->bi_len, blk, new_state);
++		goal = blk;
++		while (*n < elen) {
++			goal++;
++			if (goal >= (bi->bi_len * GFS2_NBBY))
++				break;
++			if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) !=
++			    GFS2_BLKST_FREE)
++				break;
++			gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone,
++				    bi->bi_offset, bi->bi_len, goal,
++				    new_state);
++			(*n)++;
++		}
+ 	}
+ 
+ 	return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk;
+@@ -1393,7 +1453,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
+ 			       bi->bi_len);
+ 		}
+ 		gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
+-		gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
++		gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset,
+ 			    bi->bi_len, buf_blk, new_state);
+ 	}
+ 
+@@ -1401,13 +1461,13 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
+ }
+ 
+ /**
+- * gfs2_alloc_data - Allocate a data block
+- * @ip: the inode to allocate the data block for
++ * gfs2_alloc_block - Allocate a block
++ * @ip: the inode to allocate the block for
+  *
+  * Returns: the allocated block
+  */
+ 
+-u64 gfs2_alloc_data(struct gfs2_inode *ip)
++u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
+ {
+ 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ 	struct gfs2_alloc *al = ip->i_alloc;
+@@ -1415,77 +1475,31 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip)
+ 	u32 goal, blk;
+ 	u64 block;
+ 
+-	if (rgrp_contains_block(rgd, ip->i_di.di_goal_data))
+-		goal = ip->i_di.di_goal_data - rgd->rd_data0;
++	if (rgrp_contains_block(rgd, ip->i_goal))
++		goal = ip->i_goal - rgd->rd_data0;
+ 	else
+-		goal = rgd->rd_last_alloc_data;
++		goal = rgd->rd_last_alloc;
+ 
+-	blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
++	blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n);
+ 	BUG_ON(blk == BFITNOENT);
+-	rgd->rd_last_alloc_data = blk;
+ 
++	rgd->rd_last_alloc = blk;
+ 	block = rgd->rd_data0 + blk;
+-	ip->i_di.di_goal_data = block;
++	ip->i_goal = block;
+ 
+-	gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
+-	rgd->rd_rg.rg_free--;
++	gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free >= *n);
++	rgd->rd_rg.rg_free -= *n;
+ 
+ 	gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+-	gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++	gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+ 
+-	al->al_alloced++;
++	al->al_alloced += *n;
+ 
+-	gfs2_statfs_change(sdp, 0, -1, 0);
+-	gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid);
++	gfs2_statfs_change(sdp, 0, -*n, 0);
++	gfs2_quota_change(ip, *n, ip->i_inode.i_uid, ip->i_inode.i_gid);
+ 
+ 	spin_lock(&sdp->sd_rindex_spin);
+-	rgd->rd_free_clone--;
+-	spin_unlock(&sdp->sd_rindex_spin);
+-
+-	return block;
+-}
+-
+-/**
+- * gfs2_alloc_meta - Allocate a metadata block
+- * @ip: the inode to allocate the metadata block for
+- *
+- * Returns: the allocated block
+- */
+-
+-u64 gfs2_alloc_meta(struct gfs2_inode *ip)
+-{
+-	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+-	struct gfs2_alloc *al = ip->i_alloc;
+-	struct gfs2_rgrpd *rgd = al->al_rgd;
+-	u32 goal, blk;
+-	u64 block;
+-
+-	if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta))
+-		goal = ip->i_di.di_goal_meta - rgd->rd_data0;
+-	else
+-		goal = rgd->rd_last_alloc_meta;
+-
+-	blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
+-	BUG_ON(blk == BFITNOENT);
+-	rgd->rd_last_alloc_meta = blk;
+-
+-	block = rgd->rd_data0 + blk;
+-	ip->i_di.di_goal_meta = block;
+-
+-	gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
+-	rgd->rd_rg.rg_free--;
+-
+-	gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+-	gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
+-
+-	al->al_alloced++;
+-
+-	gfs2_statfs_change(sdp, 0, -1, 0);
+-	gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid);
+-	gfs2_trans_add_unrevoke(sdp, block);
+-
+-	spin_lock(&sdp->sd_rindex_spin);
+-	rgd->rd_free_clone--;
++	rgd->rd_free_clone -= *n;
+ 	spin_unlock(&sdp->sd_rindex_spin);
+ 
+ 	return block;
+@@ -1505,12 +1519,13 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
+ 	struct gfs2_rgrpd *rgd = al->al_rgd;
+ 	u32 blk;
+ 	u64 block;
++	unsigned int n = 1;
+ 
+-	blk = rgblk_search(rgd, rgd->rd_last_alloc_meta,
+-			   GFS2_BLKST_FREE, GFS2_BLKST_DINODE);
++	blk = rgblk_search(rgd, rgd->rd_last_alloc,
++			   GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n);
+ 	BUG_ON(blk == BFITNOENT);
+ 
+-	rgd->rd_last_alloc_meta = blk;
++	rgd->rd_last_alloc = blk;
+ 
+ 	block = rgd->rd_data0 + blk;
+ 
+@@ -1519,12 +1534,12 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
+ 	rgd->rd_rg.rg_dinodes++;
+ 	*generation = rgd->rd_rg.rg_igeneration++;
+ 	gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+-	gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++	gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+ 
+ 	al->al_alloced++;
+ 
+ 	gfs2_statfs_change(sdp, 0, -1, +1);
+-	gfs2_trans_add_unrevoke(sdp, block);
++	gfs2_trans_add_unrevoke(sdp, block, 1);
+ 
+ 	spin_lock(&sdp->sd_rindex_spin);
+ 	rgd->rd_free_clone--;
+@@ -1553,7 +1568,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
+ 	rgd->rd_rg.rg_free += blen;
+ 
+ 	gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+-	gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++	gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+ 
+ 	gfs2_trans_add_rg(rgd);
+ 
+@@ -1581,7 +1596,7 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
+ 	rgd->rd_rg.rg_free += blen;
+ 
+ 	gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+-	gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++	gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+ 
+ 	gfs2_trans_add_rg(rgd);
+ 
+@@ -1601,7 +1616,7 @@ void gfs2_unlink_di(struct inode *inode)
+ 	if (!rgd)
+ 		return;
+ 	gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+-	gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++	gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+ 	gfs2_trans_add_rg(rgd);
+ }
+ 
+@@ -1621,7 +1636,7 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
+ 	rgd->rd_rg.rg_free++;
+ 
+ 	gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+-	gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++	gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+ 
+ 	gfs2_statfs_change(sdp, 0, +1, -1);
+ 	gfs2_trans_add_rg(rgd);
+@@ -1699,8 +1714,7 @@ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
+  *
+  */
+ 
+-void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
+-		      int flags)
++void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state)
+ {
+ 	unsigned int x;
+ 
+@@ -1708,7 +1722,7 @@ void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
+ 				GFP_NOFS | __GFP_NOFAIL);
+ 	for (x = 0; x < rlist->rl_rgrps; x++)
+ 		gfs2_holder_init(rlist->rl_rgd[x]->rd_gl,
+-				state, flags,
++				state, 0,
+ 				&rlist->rl_ghs[x]);
+ }
+ 
+diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
+index 149bb16..3181c7e 100644
+--- a/fs/gfs2/rgrp.h
++++ b/fs/gfs2/rgrp.h
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+  *
+  * This copyrighted material is made available to anyone wishing to use,
+  * modify, copy, or redistribute it subject to the terms and conditions
+@@ -46,8 +46,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip);
+ 
+ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block);
+ 
+-u64 gfs2_alloc_data(struct gfs2_inode *ip);
+-u64 gfs2_alloc_meta(struct gfs2_inode *ip);
++u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n);
+ u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation);
+ 
+ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
+@@ -64,8 +63,7 @@ struct gfs2_rgrp_list {
+ 
+ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
+ 		    u64 block);
+-void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
+-		      int flags);
++void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state);
+ void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
+ u64 gfs2_ri_total(struct gfs2_sbd *sdp);
+ 
+diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
+index ef0562c..7aeacbc 100644
+--- a/fs/gfs2/super.c
++++ b/fs/gfs2/super.c
+@@ -210,7 +210,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
+ 	struct page *page;
+ 	struct bio *bio;
+ 
+-	page = alloc_page(GFP_KERNEL);
++	page = alloc_page(GFP_NOFS);
+ 	if (unlikely(!page))
+ 		return -ENOBUFS;
+ 
+@@ -218,7 +218,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
+ 	ClearPageDirty(page);
+ 	lock_page(page);
+ 
+-	bio = bio_alloc(GFP_KERNEL, 1);
++	bio = bio_alloc(GFP_NOFS, 1);
+ 	if (unlikely(!bio)) {
+ 		__free_page(page);
+ 		return -ENOBUFS;
+@@ -316,6 +316,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
+ 		sdp->sd_heightsize[x] = space;
+ 	}
+ 	sdp->sd_max_height = x;
++	sdp->sd_heightsize[x] = ~0;
+ 	gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT);
+ 
+ 	sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize -
+@@ -334,6 +335,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
+ 		sdp->sd_jheightsize[x] = space;
+ 	}
+ 	sdp->sd_max_jheight = x;
++	sdp->sd_jheightsize[x] = ~0;
+ 	gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT);
+ 
+ 	return 0;
+diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
+index 60a870e..44361ec 100644
+--- a/fs/gfs2/super.h
++++ b/fs/gfs2/super.h
+@@ -17,6 +17,7 @@ void gfs2_tune_init(struct gfs2_tune *gt);
+ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent);
+ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
+ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector);
++void gfs2_lm_unmount(struct gfs2_sbd *sdp);
+ 
+ static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
+ {
+diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
+index eaa3b7b..9ab9fc8 100644
+--- a/fs/gfs2/sys.c
++++ b/fs/gfs2/sys.c
+@@ -20,7 +20,6 @@
+ 
+ #include "gfs2.h"
+ #include "incore.h"
+-#include "lm.h"
+ #include "sys.h"
+ #include "super.h"
+ #include "glock.h"
+@@ -328,15 +327,9 @@ static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf)                 \
+ }                                                                           \
+ static struct counters_attr counters_attr_##name = __ATTR_RO(name)
+ 
+-COUNTERS_ATTR(glock_count,      "%u\n");
+-COUNTERS_ATTR(glock_held_count, "%u\n");
+-COUNTERS_ATTR(inode_count,      "%u\n");
+ COUNTERS_ATTR(reclaimed,        "%u\n");
+ 
+ static struct attribute *counters_attrs[] = {
+-	&counters_attr_glock_count.attr,
+-	&counters_attr_glock_held_count.attr,
+-	&counters_attr_inode_count.attr,
+ 	&counters_attr_reclaimed.attr,
+ 	NULL,
+ };
+diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
+index 73e5d92..f677b8a 100644
+--- a/fs/gfs2/trans.c
++++ b/fs/gfs2/trans.c
+@@ -146,30 +146,25 @@ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
+ 	lops_add(sdp, &bd->bd_le);
+ }
+ 
+-void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno)
++void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
+ {
+-	struct gfs2_bufdata *bd;
+-	int found = 0;
++	struct gfs2_bufdata *bd, *tmp;
++	struct gfs2_trans *tr = current->journal_info;
++	unsigned int n = len;
+ 
+ 	gfs2_log_lock(sdp);
+-
+-	list_for_each_entry(bd, &sdp->sd_log_le_revoke, bd_le.le_list) {
+-		if (bd->bd_blkno == blkno) {
++	list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_le.le_list) {
++		if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) {
+ 			list_del_init(&bd->bd_le.le_list);
+ 			gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke);
+ 			sdp->sd_log_num_revoke--;
+-			found = 1;
+-			break;
++			kmem_cache_free(gfs2_bufdata_cachep, bd);
++			tr->tr_num_revoke_rm++;
++			if (--n == 0)
++				break;
+ 		}
+ 	}
+-
+ 	gfs2_log_unlock(sdp);
+-
+-	if (found) {
+-		struct gfs2_trans *tr = current->journal_info;
+-		kmem_cache_free(gfs2_bufdata_cachep, bd);
+-		tr->tr_num_revoke_rm++;
+-	}
+ }
+ 
+ void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd)
+diff --git a/fs/gfs2/trans.h b/fs/gfs2/trans.h
+index e826f0d..edf9d4b 100644
+--- a/fs/gfs2/trans.h
++++ b/fs/gfs2/trans.h
+@@ -32,7 +32,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp);
+ 
+ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta);
+ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
+-void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno);
++void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len);
+ void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd);
+ 
+ #endif /* __TRANS_DOT_H__ */
+diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
+index 424a077..d31e355 100644
+--- a/fs/gfs2/util.c
++++ b/fs/gfs2/util.c
+@@ -19,12 +19,12 @@
+ #include "gfs2.h"
+ #include "incore.h"
+ #include "glock.h"
+-#include "lm.h"
+ #include "util.h"
+ 
+ struct kmem_cache *gfs2_glock_cachep __read_mostly;
+ struct kmem_cache *gfs2_inode_cachep __read_mostly;
+ struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
++struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
+ 
+ void gfs2_assert_i(struct gfs2_sbd *sdp)
+ {
+@@ -32,6 +32,28 @@ void gfs2_assert_i(struct gfs2_sbd *sdp)
+ 	       sdp->sd_fsname);
+ }
+ 
++int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
++{
++	va_list args;
++
++	if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
++		return 0;
++
++	va_start(args, fmt);
++	vprintk(fmt, args);
++	va_end(args);
++
++	fs_err(sdp, "about to withdraw this file system\n");
++	BUG_ON(sdp->sd_args.ar_debug);
++
++	fs_err(sdp, "telling LM to withdraw\n");
++	gfs2_withdraw_lockproto(&sdp->sd_lockstruct);
++	fs_err(sdp, "withdrawn\n");
++	dump_stack();
++
++	return -1;
++}
++
+ /**
+  * gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false
+  * Returns: -1 if this call withdrew the machine,
+diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h
+index 28938a4..509c5d6 100644
+--- a/fs/gfs2/util.h
++++ b/fs/gfs2/util.h
+@@ -147,6 +147,7 @@ gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__);
+ extern struct kmem_cache *gfs2_glock_cachep;
+ extern struct kmem_cache *gfs2_inode_cachep;
+ extern struct kmem_cache *gfs2_bufdata_cachep;
++extern struct kmem_cache *gfs2_rgrpd_cachep;
+ 
+ static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt,
+ 					   unsigned int *p)
+@@ -163,6 +164,7 @@ gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field)
+ 
+ void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap,
+ 		      unsigned int bit, int new_value);
++int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...);
+ 
+ #endif /* __UTIL_DOT_H__ */
+ 
+diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
+index b60c0af..f457d2c 100644
+--- a/fs/hfsplus/ioctl.c
++++ b/fs/hfsplus/ioctl.c
+@@ -14,6 +14,7 @@
+ 
+ #include <linux/capability.h>
+ #include <linux/fs.h>
++#include <linux/mount.h>
+ #include <linux/sched.h>
+ #include <linux/xattr.h>
+ #include <asm/uaccess.h>
+@@ -35,25 +36,32 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ 			flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */
+ 		return put_user(flags, (int __user *)arg);
+ 	case HFSPLUS_IOC_EXT2_SETFLAGS: {
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-
+-		if (!is_owner_or_cap(inode))
+-			return -EACCES;
+-
+-		if (get_user(flags, (int __user *)arg))
+-			return -EFAULT;
+-
++		int err = 0;
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			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))
+-				return -EPERM;
++			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))
+-			return -EOPNOTSUPP;
+-
++		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;
+@@ -75,7 +83,9 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ 
+ 		inode->i_ctime = CURRENT_TIME_SEC;
+ 		mark_inode_dirty(inode);
+-		return 0;
++setflags_out:
++		mnt_drop_write(filp->f_path.mnt);
++		return err;
+ 	}
+ 	default:
+ 		return -ENOTTY;
+diff --git a/fs/inode.c b/fs/inode.c
+index 53245ff..27ee1af 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1199,42 +1199,37 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
+ 	struct inode *inode = dentry->d_inode;
+ 	struct timespec now;
+ 
+-	if (inode->i_flags & S_NOATIME)
++	if (mnt_want_write(mnt))
+ 		return;
++	if (inode->i_flags & S_NOATIME)
++		goto out;
+ 	if (IS_NOATIME(inode))
+-		return;
++		goto out;
+ 	if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
+-		return;
++		goto out;
+ 
+-	/*
+-	 * We may have a NULL vfsmount when coming from NFSD
+-	 */
+-	if (mnt) {
+-		if (mnt->mnt_flags & MNT_NOATIME)
+-			return;
+-		if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+-			return;
+-
+-		if (mnt->mnt_flags & MNT_RELATIME) {
+-			/*
+-			 * With relative atime, only update atime if the
+-			 * previous atime is earlier than either the ctime or
+-			 * mtime.
+-			 */
+-			if (timespec_compare(&inode->i_mtime,
+-						&inode->i_atime) < 0 &&
+-			    timespec_compare(&inode->i_ctime,
+-						&inode->i_atime) < 0)
+-				return;
+-		}
++	if (mnt->mnt_flags & MNT_NOATIME)
++		goto out;
++	if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
++		goto out;
++	if (mnt->mnt_flags & MNT_RELATIME) {
++		/*
++		 * With relative atime, only update atime if the previous
++		 * atime is earlier than either the ctime or mtime.
++		 */
++		if (timespec_compare(&inode->i_mtime, &inode->i_atime) < 0 &&
++		    timespec_compare(&inode->i_ctime, &inode->i_atime) < 0)
++			goto out;
+ 	}
+ 
+ 	now = current_fs_time(inode->i_sb);
+ 	if (timespec_equal(&inode->i_atime, &now))
+-		return;
++		goto out;
+ 
+ 	inode->i_atime = now;
+ 	mark_inode_dirty_sync(inode);
++out:
++	mnt_drop_write(mnt);
+ }
+ EXPORT_SYMBOL(touch_atime);
+ 
+@@ -1255,10 +1250,13 @@ void file_update_time(struct file *file)
+ 	struct inode *inode = file->f_path.dentry->d_inode;
+ 	struct timespec now;
+ 	int sync_it = 0;
++	int err;
+ 
+ 	if (IS_NOCMTIME(inode))
+ 		return;
+-	if (IS_RDONLY(inode))
++
++	err = mnt_want_write(file->f_path.mnt);
++	if (err)
+ 		return;
+ 
+ 	now = current_fs_time(inode->i_sb);
+@@ -1279,6 +1277,7 @@ void file_update_time(struct file *file)
+ 
+ 	if (sync_it)
+ 		mark_inode_dirty_sync(inode);
++	mnt_drop_write(file->f_path.mnt);
+ }
+ 
+ EXPORT_SYMBOL(file_update_time);
+diff --git a/fs/internal.h b/fs/internal.h
+index 392e8cc..80aa9a0 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -43,3 +43,14 @@ extern void __init chrdev_init(void);
+  * namespace.c
+  */
+ extern int copy_mount_options(const void __user *, unsigned long *);
++
++extern void free_vfsmnt(struct vfsmount *);
++extern struct vfsmount *alloc_vfsmnt(const char *);
++extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
++extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
++				struct vfsmount *);
++extern void release_mounts(struct list_head *);
++extern void umount_tree(struct vfsmount *, int, struct list_head *);
++extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
++
++extern void __init mnt_init(void);
+diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
+index d14d5a4..3ea3655 100644
+--- a/fs/jffs2/README.Locking
++++ b/fs/jffs2/README.Locking
+@@ -14,7 +14,7 @@ be fairly close.
+ 	alloc_sem
+ 	---------
+ 
+-The alloc_sem is a per-filesystem semaphore, used primarily to ensure
++The alloc_sem is a per-filesystem mutex, used primarily to ensure
+ contiguous allocation of space on the medium. It is automatically
+ obtained during space allocations (jffs2_reserve_space()) and freed
+ upon write completion (jffs2_complete_reservation()). Note that
+@@ -41,10 +41,10 @@ if the wbuf is currently holding any data is permitted, though.
+ Ordering constraints: See f->sem.
+ 
+ 
+-	File Semaphore f->sem
++	File Mutex f->sem
+ 	---------------------
+ 
+-This is the JFFS2-internal equivalent of the inode semaphore i->i_sem.
++This is the JFFS2-internal equivalent of the inode mutex i->i_sem.
+ It protects the contents of the jffs2_inode_info private inode data,
+ including the linked list of node fragments (but see the notes below on
+ erase_completion_lock), etc.
+@@ -60,14 +60,14 @@ lead to deadlock, unless we played games with unlocking the i_sem
+ before calling the space allocation functions.
+ 
+ Instead of playing such games, we just have an extra internal
+-semaphore, which is obtained by the garbage collection code and also
++mutex, which is obtained by the garbage collection code and also
+ by the normal file system code _after_ allocation of space.
+ 
+ Ordering constraints: 
+ 
+ 	1. Never attempt to allocate space or lock alloc_sem with 
+ 	   any f->sem held.
+-	2. Never attempt to lock two file semaphores in one thread.
++	2. Never attempt to lock two file mutexes in one thread.
+ 	   No ordering rules have been made for doing so.
+ 
+ 
+@@ -86,8 +86,8 @@ a simple spin_lock() rather than spin_lock_bh().
+ 
+ Note that the per-inode list of physical nodes (f->nodes) is a special
+ case. Any changes to _valid_ nodes (i.e. ->flash_offset & 1 == 0) in
+-the list are protected by the file semaphore f->sem. But the erase
+-code may remove _obsolete_ nodes from the list while holding only the
++the list are protected by the file mutex f->sem. But the erase code
++may remove _obsolete_ nodes from the list while holding only the
+ erase_completion_lock. So you can walk the list only while holding the
+ erase_completion_lock, and can drop the lock temporarily mid-walk as
+ long as the pointer you're holding is to a _valid_ node, not an
+@@ -124,10 +124,10 @@ Ordering constraints:
+ 	erase_free_sem
+ 	--------------
+ 
+-This semaphore is only used by the erase code which frees obsolete
+-node references and the jffs2_garbage_collect_deletion_dirent()
+-function. The latter function on NAND flash must read _obsolete_ nodes
+-to determine whether the 'deletion dirent' under consideration can be
++This mutex is only used by the erase code which frees obsolete node
++references and the jffs2_garbage_collect_deletion_dirent() function.
++The latter function on NAND flash must read _obsolete_ nodes to
++determine whether the 'deletion dirent' under consideration can be
+ discarded or whether it is still required to show that an inode has
+ been unlinked. Because reading from the flash may sleep, the
+ erase_completion_lock cannot be held, so an alternative, more
+diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
+index 722a6b6..d58f845 100644
+--- a/fs/jffs2/build.c
++++ b/fs/jffs2/build.c
+@@ -345,6 +345,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
+ 	INIT_LIST_HEAD(&c->dirty_list);
+ 	INIT_LIST_HEAD(&c->erasable_list);
+ 	INIT_LIST_HEAD(&c->erasing_list);
++	INIT_LIST_HEAD(&c->erase_checking_list);
+ 	INIT_LIST_HEAD(&c->erase_pending_list);
+ 	INIT_LIST_HEAD(&c->erasable_pending_wbuf_list);
+ 	INIT_LIST_HEAD(&c->erase_complete_list);
+diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
+index 3a32c64..5544d31 100644
+--- a/fs/jffs2/debug.c
++++ b/fs/jffs2/debug.c
+@@ -62,9 +62,9 @@ __jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
+ void
+ __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
+ {
+-	down(&f->sem);
++	mutex_lock(&f->sem);
+ 	__jffs2_dbg_fragtree_paranoia_check_nolock(f);
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ }
+ 
+ void
+@@ -153,6 +153,139 @@ __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
+ 	kfree(buf);
+ }
+ 
++void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
++{
++	struct jffs2_eraseblock *jeb;
++	uint32_t free = 0, dirty = 0, used = 0, wasted = 0,
++		erasing = 0, bad = 0, unchecked = 0;
++	int nr_counted = 0;
++	int dump = 0;
++
++	if (c->gcblock) {
++		nr_counted++;
++		free += c->gcblock->free_size;
++		dirty += c->gcblock->dirty_size;
++		used += c->gcblock->used_size;
++		wasted += c->gcblock->wasted_size;
++		unchecked += c->gcblock->unchecked_size;
++	}
++	if (c->nextblock) {
++		nr_counted++;
++		free += c->nextblock->free_size;
++		dirty += c->nextblock->dirty_size;
++		used += c->nextblock->used_size;
++		wasted += c->nextblock->wasted_size;
++		unchecked += c->nextblock->unchecked_size;
++	}
++	list_for_each_entry(jeb, &c->clean_list, list) {
++		nr_counted++;
++		free += jeb->free_size;
++		dirty += jeb->dirty_size;
++		used += jeb->used_size;
++		wasted += jeb->wasted_size;
++		unchecked += jeb->unchecked_size;
++	}
++	list_for_each_entry(jeb, &c->very_dirty_list, list) {
++		nr_counted++;
++		free += jeb->free_size;
++		dirty += jeb->dirty_size;
++		used += jeb->used_size;
++		wasted += jeb->wasted_size;
++		unchecked += jeb->unchecked_size;
++	}
++	list_for_each_entry(jeb, &c->dirty_list, list) {
++		nr_counted++;
++		free += jeb->free_size;
++		dirty += jeb->dirty_size;
++		used += jeb->used_size;
++		wasted += jeb->wasted_size;
++		unchecked += jeb->unchecked_size;
++	}
++	list_for_each_entry(jeb, &c->erasable_list, list) {
++		nr_counted++;
++		free += jeb->free_size;
++		dirty += jeb->dirty_size;
++		used += jeb->used_size;
++		wasted += jeb->wasted_size;
++		unchecked += jeb->unchecked_size;
++	}
++	list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) {
++		nr_counted++;
++		free += jeb->free_size;
++		dirty += jeb->dirty_size;
++		used += jeb->used_size;
++		wasted += jeb->wasted_size;
++		unchecked += jeb->unchecked_size;
++	}
++	list_for_each_entry(jeb, &c->erase_pending_list, list) {
++		nr_counted++;
++		free += jeb->free_size;
++		dirty += jeb->dirty_size;
++		used += jeb->used_size;
++		wasted += jeb->wasted_size;
++		unchecked += jeb->unchecked_size;
++	}
++	list_for_each_entry(jeb, &c->free_list, list) {
++		nr_counted++;
++		free += jeb->free_size;
++		dirty += jeb->dirty_size;
++		used += jeb->used_size;
++		wasted += jeb->wasted_size;
++		unchecked += jeb->unchecked_size;
++	}
++	list_for_each_entry(jeb, &c->bad_used_list, list) {
++		nr_counted++;
++		free += jeb->free_size;
++		dirty += jeb->dirty_size;
++		used += jeb->used_size;
++		wasted += jeb->wasted_size;
++		unchecked += jeb->unchecked_size;
++	}
++
++	list_for_each_entry(jeb, &c->erasing_list, list) {
++		nr_counted++;
++		erasing += c->sector_size;
++	}
++	list_for_each_entry(jeb, &c->erase_checking_list, list) {
++		nr_counted++;
++		erasing += c->sector_size;
++	}
++	list_for_each_entry(jeb, &c->erase_complete_list, list) {
++		nr_counted++;
++		erasing += c->sector_size;
++	}
++	list_for_each_entry(jeb, &c->bad_list, list) {
++		nr_counted++;
++		bad += c->sector_size;
++	}
++
++#define check(sz) \
++	if (sz != c->sz##_size) {			\
++		printk(KERN_WARNING #sz "_size mismatch counted 0x%x, c->" #sz "_size 0x%x\n", \
++		       sz, c->sz##_size);		\
++		dump = 1;				\
++	}
++	check(free);
++	check(dirty);
++	check(used);
++	check(wasted);
++	check(unchecked);
++	check(bad);
++	check(erasing);
++#undef check
++
++	if (nr_counted != c->nr_blocks) {
++		printk(KERN_WARNING "%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
++		       __func__, nr_counted, c->nr_blocks);
++		dump = 1;
++	}
++
++	if (dump) {
++		__jffs2_dbg_dump_block_lists_nolock(c);
++		BUG();
++	}
++}
++
+ /*
+  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
+  */
+@@ -229,6 +362,9 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
+ 	}
+ #endif
+ 
++	if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
++		__jffs2_dbg_superblock_counts(c);
++
+ 	return;
+ 
+ error:
+@@ -268,7 +404,10 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
+ 
+ 	printk(JFFS2_DBG);
+ 	for (ref = jeb->first_node; ; ref = ref_next(ref)) {
+-		printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
++		printk("%#08x", ref_offset(ref));
++#ifdef TEST_TOTLEN
++		printk("(%x)", ref->__totlen);
++#endif
+ 		if (ref_next(ref))
+ 			printk("->");
+ 		else
+@@ -447,6 +586,21 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
+ 			}
+ 		}
+ 	}
++	if (list_empty(&c->erase_checking_list)) {
++		printk(JFFS2_DBG "erase_checking_list: empty\n");
++	} else {
++		struct list_head *this;
++
++		list_for_each(this, &c->erase_checking_list) {
++			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
++
++			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
++				printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
++					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
++					jeb->unchecked_size, jeb->free_size);
++			}
++		}
++	}
+ 
+ 	if (list_empty(&c->erase_pending_list)) {
+ 		printk(JFFS2_DBG "erase_pending_list: empty\n");
+@@ -532,9 +686,9 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
+ void
+ __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
+ {
+-	down(&f->sem);
++	mutex_lock(&f->sem);
+ 	jffs2_dbg_dump_fragtree_nolock(f);
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ }
+ 
+ void
+diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
+index 4130ada..9645275 100644
+--- a/fs/jffs2/debug.h
++++ b/fs/jffs2/debug.h
+@@ -38,6 +38,7 @@
+ 
+ #if CONFIG_JFFS2_FS_DEBUG > 1
+ #define JFFS2_DBG_FRAGTREE2_MESSAGES
++#define JFFS2_DBG_READINODE2_MESSAGES
+ #define JFFS2_DBG_MEMALLOC_MESSAGES
+ #endif
+ 
+@@ -115,6 +116,11 @@
+ #else
+ #define dbg_readinode(fmt, ...)
+ #endif
++#ifdef JFFS2_DBG_READINODE2_MESSAGES
++#define dbg_readinode2(fmt, ...)	JFFS2_DEBUG(fmt, ##__VA_ARGS__)
++#else
++#define dbg_readinode2(fmt, ...)
++#endif
+ 
+ /* Fragtree build debugging messages */
+ #ifdef JFFS2_DBG_FRAGTREE_MESSAGES
+diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
+index f948f7e..c63e7a9 100644
+--- a/fs/jffs2/dir.c
++++ b/fs/jffs2/dir.c
+@@ -86,7 +86,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
+ 	dir_f = JFFS2_INODE_INFO(dir_i);
+ 	c = JFFS2_SB_INFO(dir_i->i_sb);
+ 
+-	down(&dir_f->sem);
++	mutex_lock(&dir_f->sem);
+ 
+ 	/* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
+ 	for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) {
+@@ -99,7 +99,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
+ 	}
+ 	if (fd)
+ 		ino = fd->ino;
+-	up(&dir_f->sem);
++	mutex_unlock(&dir_f->sem);
+ 	if (ino) {
+ 		inode = jffs2_iget(dir_i->i_sb, ino);
+ 		if (IS_ERR(inode)) {
+@@ -146,7 +146,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 	}
+ 
+ 	curofs=1;
+-	down(&f->sem);
++	mutex_lock(&f->sem);
+ 	for (fd = f->dents; fd; fd = fd->next) {
+ 
+ 		curofs++;
+@@ -166,7 +166,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 			break;
+ 		offset++;
+ 	}
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+  out:
+ 	filp->f_pos = offset;
+ 	return 0;
+@@ -275,9 +275,9 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
+ 	ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now);
+ 
+ 	if (!ret) {
+-		down(&f->sem);
++		mutex_lock(&f->sem);
+ 		old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		d_instantiate(dentry, old_dentry->d_inode);
+ 		dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+ 		atomic_inc(&old_dentry->d_inode->i_count);
+@@ -351,7 +351,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ 
+ 	if (IS_ERR(fn)) {
+ 		/* Eeek. Wave bye bye */
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		jffs2_complete_reservation(c);
+ 		jffs2_clear_inode(inode);
+ 		return PTR_ERR(fn);
+@@ -361,7 +361,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ 	f->target = kmalloc(targetlen + 1, GFP_KERNEL);
+ 	if (!f->target) {
+ 		printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		jffs2_complete_reservation(c);
+ 		jffs2_clear_inode(inode);
+ 		return -ENOMEM;
+@@ -374,7 +374,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ 	   obsoleted by the first data write
+ 	*/
+ 	f->metadata = fn;
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ 
+ 	jffs2_complete_reservation(c);
+ 
+@@ -406,7 +406,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ 	}
+ 
+ 	dir_f = JFFS2_INODE_INFO(dir_i);
+-	down(&dir_f->sem);
++	mutex_lock(&dir_f->sem);
+ 
+ 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ 	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+@@ -429,7 +429,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ 		   as if it were the final unlink() */
+ 		jffs2_complete_reservation(c);
+ 		jffs2_free_raw_dirent(rd);
+-		up(&dir_f->sem);
++		mutex_unlock(&dir_f->sem);
+ 		jffs2_clear_inode(inode);
+ 		return PTR_ERR(fd);
+ 	}
+@@ -442,7 +442,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ 	   one if necessary. */
+ 	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+ 
+-	up(&dir_f->sem);
++	mutex_unlock(&dir_f->sem);
+ 	jffs2_complete_reservation(c);
+ 
+ 	d_instantiate(dentry, inode);
+@@ -507,7 +507,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+ 
+ 	if (IS_ERR(fn)) {
+ 		/* Eeek. Wave bye bye */
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		jffs2_complete_reservation(c);
+ 		jffs2_clear_inode(inode);
+ 		return PTR_ERR(fn);
+@@ -516,7 +516,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+ 	   obsoleted by the first data write
+ 	*/
+ 	f->metadata = fn;
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ 
+ 	jffs2_complete_reservation(c);
+ 
+@@ -548,7 +548,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+ 	}
+ 
+ 	dir_f = JFFS2_INODE_INFO(dir_i);
+-	down(&dir_f->sem);
++	mutex_lock(&dir_f->sem);
+ 
+ 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ 	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+@@ -571,7 +571,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+ 		   as if it were the final unlink() */
+ 		jffs2_complete_reservation(c);
+ 		jffs2_free_raw_dirent(rd);
+-		up(&dir_f->sem);
++		mutex_unlock(&dir_f->sem);
+ 		jffs2_clear_inode(inode);
+ 		return PTR_ERR(fd);
+ 	}
+@@ -585,7 +585,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+ 	   one if necessary. */
+ 	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+ 
+-	up(&dir_f->sem);
++	mutex_unlock(&dir_f->sem);
+ 	jffs2_complete_reservation(c);
+ 
+ 	d_instantiate(dentry, inode);
+@@ -673,7 +673,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+ 
+ 	if (IS_ERR(fn)) {
+ 		/* Eeek. Wave bye bye */
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		jffs2_complete_reservation(c);
+ 		jffs2_clear_inode(inode);
+ 		return PTR_ERR(fn);
+@@ -682,7 +682,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+ 	   obsoleted by the first data write
+ 	*/
+ 	f->metadata = fn;
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ 
+ 	jffs2_complete_reservation(c);
+ 
+@@ -714,7 +714,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+ 	}
+ 
+ 	dir_f = JFFS2_INODE_INFO(dir_i);
+-	down(&dir_f->sem);
++	mutex_lock(&dir_f->sem);
+ 
+ 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ 	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+@@ -740,7 +740,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+ 		   as if it were the final unlink() */
+ 		jffs2_complete_reservation(c);
+ 		jffs2_free_raw_dirent(rd);
+-		up(&dir_f->sem);
++		mutex_unlock(&dir_f->sem);
+ 		jffs2_clear_inode(inode);
+ 		return PTR_ERR(fd);
+ 	}
+@@ -753,7 +753,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+ 	   one if necessary. */
+ 	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+ 
+-	up(&dir_f->sem);
++	mutex_unlock(&dir_f->sem);
+ 	jffs2_complete_reservation(c);
+ 
+ 	d_instantiate(dentry, inode);
+@@ -780,14 +780,14 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
+ 		if (S_ISDIR(new_dentry->d_inode->i_mode)) {
+ 			struct jffs2_full_dirent *fd;
+ 
+-			down(&victim_f->sem);
++			mutex_lock(&victim_f->sem);
+ 			for (fd = victim_f->dents; fd; fd = fd->next) {
+ 				if (fd->ino) {
+-					up(&victim_f->sem);
++					mutex_unlock(&victim_f->sem);
+ 					return -ENOTEMPTY;
+ 				}
+ 			}
+-			up(&victim_f->sem);
++			mutex_unlock(&victim_f->sem);
+ 		}
+ 	}
+ 
+@@ -816,9 +816,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
+ 		/* Don't oops if the victim was a dirent pointing to an
+ 		   inode which didn't exist. */
+ 		if (victim_f->inocache) {
+-			down(&victim_f->sem);
++			mutex_lock(&victim_f->sem);
+ 			victim_f->inocache->nlink--;
+-			up(&victim_f->sem);
++			mutex_unlock(&victim_f->sem);
+ 		}
+ 	}
+ 
+@@ -836,11 +836,11 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
+ 	if (ret) {
+ 		/* Oh shit. We really ought to make a single node which can do both atomically */
+ 		struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
+-		down(&f->sem);
++		mutex_lock(&f->sem);
+ 		inc_nlink(old_dentry->d_inode);
+ 		if (f->inocache)
+ 			f->inocache->nlink++;
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 
+ 		printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
+ 		/* Might as well let the VFS know */
+diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
+index a1db918..25a640e 100644
+--- a/fs/jffs2/erase.c
++++ b/fs/jffs2/erase.c
+@@ -50,14 +50,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
+ 	instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
+ 	if (!instr) {
+ 		printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
+-		down(&c->erase_free_sem);
++		mutex_lock(&c->erase_free_sem);
+ 		spin_lock(&c->erase_completion_lock);
+ 		list_move(&jeb->list, &c->erase_pending_list);
+ 		c->erasing_size -= c->sector_size;
+ 		c->dirty_size += c->sector_size;
+ 		jeb->dirty_size = c->sector_size;
+ 		spin_unlock(&c->erase_completion_lock);
+-		up(&c->erase_free_sem);
++		mutex_unlock(&c->erase_free_sem);
+ 		return;
+ 	}
+ 
+@@ -84,14 +84,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
+ 	if (ret == -ENOMEM || ret == -EAGAIN) {
+ 		/* Erase failed immediately. Refile it on the list */
+ 		D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
+-		down(&c->erase_free_sem);
++		mutex_lock(&c->erase_free_sem);
+ 		spin_lock(&c->erase_completion_lock);
+ 		list_move(&jeb->list, &c->erase_pending_list);
+ 		c->erasing_size -= c->sector_size;
+ 		c->dirty_size += c->sector_size;
+ 		jeb->dirty_size = c->sector_size;
+ 		spin_unlock(&c->erase_completion_lock);
+-		up(&c->erase_free_sem);
++		mutex_unlock(&c->erase_free_sem);
+ 		return;
+ 	}
+ 
+@@ -107,7 +107,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+ {
+ 	struct jffs2_eraseblock *jeb;
+ 
+-	down(&c->erase_free_sem);
++	mutex_lock(&c->erase_free_sem);
+ 
+ 	spin_lock(&c->erase_completion_lock);
+ 
+@@ -116,9 +116,9 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+ 
+ 		if (!list_empty(&c->erase_complete_list)) {
+ 			jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
+-			list_del(&jeb->list);
++			list_move(&jeb->list, &c->erase_checking_list);
+ 			spin_unlock(&c->erase_completion_lock);
+-			up(&c->erase_free_sem);
++			mutex_unlock(&c->erase_free_sem);
+ 			jffs2_mark_erased_block(c, jeb);
+ 
+ 			if (!--count) {
+@@ -139,7 +139,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+ 			jffs2_free_jeb_node_refs(c, jeb);
+ 			list_add(&jeb->list, &c->erasing_list);
+ 			spin_unlock(&c->erase_completion_lock);
+-			up(&c->erase_free_sem);
++			mutex_unlock(&c->erase_free_sem);
+ 
+ 			jffs2_erase_block(c, jeb);
+ 
+@@ -149,12 +149,12 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+ 
+ 		/* Be nice */
+ 		yield();
+-		down(&c->erase_free_sem);
++		mutex_lock(&c->erase_free_sem);
+ 		spin_lock(&c->erase_completion_lock);
+ 	}
+ 
+ 	spin_unlock(&c->erase_completion_lock);
+-	up(&c->erase_free_sem);
++	mutex_unlock(&c->erase_free_sem);
+  done:
+ 	D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
+ }
+@@ -162,11 +162,11 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+ {
+ 	D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
+-	down(&c->erase_free_sem);
++	mutex_lock(&c->erase_free_sem);
+ 	spin_lock(&c->erase_completion_lock);
+ 	list_move_tail(&jeb->list, &c->erase_complete_list);
+ 	spin_unlock(&c->erase_completion_lock);
+-	up(&c->erase_free_sem);
++	mutex_unlock(&c->erase_free_sem);
+ 	/* Ensure that kupdated calls us again to mark them clean */
+ 	jffs2_erase_pending_trigger(c);
+ }
+@@ -180,26 +180,26 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock
+ 		   failed too many times. */
+ 		if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
+ 			/* We'd like to give this block another try. */
+-			down(&c->erase_free_sem);
++			mutex_lock(&c->erase_free_sem);
+ 			spin_lock(&c->erase_completion_lock);
+ 			list_move(&jeb->list, &c->erase_pending_list);
+ 			c->erasing_size -= c->sector_size;
+ 			c->dirty_size += c->sector_size;
+ 			jeb->dirty_size = c->sector_size;
+ 			spin_unlock(&c->erase_completion_lock);
+-			up(&c->erase_free_sem);
++			mutex_unlock(&c->erase_free_sem);
+ 			return;
+ 		}
+ 	}
+ 
+-	down(&c->erase_free_sem);
++	mutex_lock(&c->erase_free_sem);
+ 	spin_lock(&c->erase_completion_lock);
+ 	c->erasing_size -= c->sector_size;
+ 	c->bad_size += c->sector_size;
+ 	list_move(&jeb->list, &c->bad_list);
+ 	c->nr_erasing_blocks--;
+ 	spin_unlock(&c->erase_completion_lock);
+-	up(&c->erase_free_sem);
++	mutex_unlock(&c->erase_free_sem);
+ 	wake_up(&c->erase_wait);
+ }
+ 
+@@ -350,9 +350,11 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
+ 			   break;
+ 		} while(--retlen);
+ 		c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
+-		if (retlen)
++		if (retlen) {
+ 			printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
+ 			       *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
++			return -EIO;
++		}
+ 		return 0;
+ 	}
+  do_flash_read:
+@@ -373,10 +375,12 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
+ 		ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf);
+ 		if (ret) {
+ 			printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret);
++			ret = -EIO;
+ 			goto fail;
+ 		}
+ 		if (retlen != readlen) {
+ 			printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen);
++			ret = -EIO;
+ 			goto fail;
+ 		}
+ 		for (i=0; i<readlen; i += sizeof(unsigned long)) {
+@@ -385,6 +389,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
+ 			if (*datum + 1) {
+ 				*bad_offset += i;
+ 				printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", *datum, *bad_offset);
++				ret = -EIO;
+ 				goto fail;
+ 			}
+ 		}
+@@ -419,9 +424,6 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
+ 			if (jffs2_write_nand_cleanmarker(c, jeb))
+ 				goto filebad;
+ 		}
+-
+-		/* Everything else got zeroed before the erase */
+-		jeb->free_size = c->sector_size;
+ 	} else {
+ 
+ 		struct kvec vecs[1];
+@@ -449,48 +451,50 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
+ 
+ 			goto filebad;
+ 		}
+-
+-		/* Everything else got zeroed before the erase */
+-		jeb->free_size = c->sector_size;
+-		/* FIXME Special case for cleanmarker in empty block */
+-		jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
+ 	}
++	/* Everything else got zeroed before the erase */
++	jeb->free_size = c->sector_size;
+ 
+-	down(&c->erase_free_sem);
++	mutex_lock(&c->erase_free_sem);
+ 	spin_lock(&c->erase_completion_lock);
++
+ 	c->erasing_size -= c->sector_size;
+-	c->free_size += jeb->free_size;
+-	c->used_size += jeb->used_size;
++	c->free_size += c->sector_size;
+ 
+-	jffs2_dbg_acct_sanity_check_nolock(c,jeb);
+-	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
++	/* Account for cleanmarker now, if it's in-band */
++	if (c->cleanmarker_size && !jffs2_cleanmarker_oob(c))
++		jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
+ 
+-	list_add_tail(&jeb->list, &c->free_list);
++	list_move_tail(&jeb->list, &c->free_list);
+ 	c->nr_erasing_blocks--;
+ 	c->nr_free_blocks++;
++
++	jffs2_dbg_acct_sanity_check_nolock(c, jeb);
++	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
++
+ 	spin_unlock(&c->erase_completion_lock);
+-	up(&c->erase_free_sem);
++	mutex_unlock(&c->erase_free_sem);
+ 	wake_up(&c->erase_wait);
+ 	return;
+ 
+ filebad:
+-	down(&c->erase_free_sem);
++	mutex_lock(&c->erase_free_sem);
+ 	spin_lock(&c->erase_completion_lock);
+ 	/* Stick it on a list (any list) so erase_failed can take it
+ 	   right off again.  Silly, but shouldn't happen often. */
+-	list_add(&jeb->list, &c->erasing_list);
++	list_move(&jeb->list, &c->erasing_list);
+ 	spin_unlock(&c->erase_completion_lock);
+-	up(&c->erase_free_sem);
++	mutex_unlock(&c->erase_free_sem);
+ 	jffs2_erase_failed(c, jeb, bad_offset);
+ 	return;
+ 
+ refile:
+ 	/* Stick it back on the list from whence it came and come back later */
+ 	jffs2_erase_pending_trigger(c);
+-	down(&c->erase_free_sem);
++	mutex_lock(&c->erase_free_sem);
+ 	spin_lock(&c->erase_completion_lock);
+-	list_add(&jeb->list, &c->erase_complete_list);
++	list_move(&jeb->list, &c->erase_complete_list);
+ 	spin_unlock(&c->erase_completion_lock);
+-	up(&c->erase_free_sem);
++	mutex_unlock(&c->erase_free_sem);
+ 	return;
+ }
+diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
+index dcc2734..5e92034 100644
+--- a/fs/jffs2/file.c
++++ b/fs/jffs2/file.c
+@@ -115,9 +115,9 @@ static int jffs2_readpage (struct file *filp, struct page *pg)
+ 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host);
+ 	int ret;
+ 
+-	down(&f->sem);
++	mutex_lock(&f->sem);
+ 	ret = jffs2_do_readpage_unlock(pg->mapping->host, pg);
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ 	return ret;
+ }
+ 
+@@ -154,7 +154,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ 		if (ret)
+ 			goto out_page;
+ 
+-		down(&f->sem);
++		mutex_lock(&f->sem);
+ 		memset(&ri, 0, sizeof(ri));
+ 
+ 		ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -181,7 +181,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ 		if (IS_ERR(fn)) {
+ 			ret = PTR_ERR(fn);
+ 			jffs2_complete_reservation(c);
+-			up(&f->sem);
++			mutex_unlock(&f->sem);
+ 			goto out_page;
+ 		}
+ 		ret = jffs2_add_full_dnode_to_inode(c, f, fn);
+@@ -195,12 +195,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ 			jffs2_mark_node_obsolete(c, fn->raw);
+ 			jffs2_free_full_dnode(fn);
+ 			jffs2_complete_reservation(c);
+-			up(&f->sem);
++			mutex_unlock(&f->sem);
+ 			goto out_page;
+ 		}
+ 		jffs2_complete_reservation(c);
+ 		inode->i_size = pageofs;
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 	}
+ 
+ 	/*
+@@ -209,9 +209,9 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ 	 * case of a short-copy.
+ 	 */
+ 	if (!PageUptodate(pg)) {
+-		down(&f->sem);
++		mutex_lock(&f->sem);
+ 		ret = jffs2_do_readpage_nolock(inode, pg);
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		if (ret)
+ 			goto out_page;
+ 	}
+diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
+index e26ea78..3eb1c84 100644
+--- a/fs/jffs2/fs.c
++++ b/fs/jffs2/fs.c
+@@ -36,6 +36,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ 	unsigned int ivalid;
+ 	uint32_t alloclen;
+ 	int ret;
++	int alloc_type = ALLOC_NORMAL;
+ 
+ 	D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
+ 
+@@ -50,20 +51,20 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ 		mdata = (char *)&dev;
+ 		D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
+ 	} else if (S_ISLNK(inode->i_mode)) {
+-		down(&f->sem);
++		mutex_lock(&f->sem);
+ 		mdatalen = f->metadata->size;
+ 		mdata = kmalloc(f->metadata->size, GFP_USER);
+ 		if (!mdata) {
+-			up(&f->sem);
++			mutex_unlock(&f->sem);
+ 			return -ENOMEM;
+ 		}
+ 		ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
+ 		if (ret) {
+-			up(&f->sem);
++			mutex_unlock(&f->sem);
+ 			kfree(mdata);
+ 			return ret;
+ 		}
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
+ 	}
+ 
+@@ -82,7 +83,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ 			 kfree(mdata);
+ 		return ret;
+ 	}
+-	down(&f->sem);
++	mutex_lock(&f->sem);
+ 	ivalid = iattr->ia_valid;
+ 
+ 	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -115,6 +116,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ 		ri->compr = JFFS2_COMPR_ZERO;
+ 		ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
+ 		ri->offset = cpu_to_je32(inode->i_size);
++	} else if (ivalid & ATTR_SIZE && !iattr->ia_size) {
++		/* For truncate-to-zero, treat it as deletion because
++		   it'll always be obsoleting all previous nodes */
++		alloc_type = ALLOC_DELETION;
+ 	}
+ 	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
+ 	if (mdatalen)
+@@ -122,14 +127,14 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ 	else
+ 		ri->data_crc = cpu_to_je32(0);
+ 
+-	new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL);
++	new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
+ 	if (S_ISLNK(inode->i_mode))
+ 		kfree(mdata);
+ 
+ 	if (IS_ERR(new_metadata)) {
+ 		jffs2_complete_reservation(c);
+ 		jffs2_free_raw_inode(ri);
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		return PTR_ERR(new_metadata);
+ 	}
+ 	/* It worked. Update the inode */
+@@ -149,6 +154,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ 	if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
+ 		jffs2_add_full_dnode_to_inode(c, f, new_metadata);
+ 		inode->i_size = iattr->ia_size;
++		inode->i_blocks = (inode->i_size + 511) >> 9;
+ 		f->metadata = NULL;
+ 	} else {
+ 		f->metadata = new_metadata;
+@@ -159,7 +165,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ 	}
+ 	jffs2_free_raw_inode(ri);
+ 
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ 	jffs2_complete_reservation(c);
+ 
+ 	/* We have to do the vmtruncate() without f->sem held, since
+@@ -167,8 +173,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ 	   We are protected from a simultaneous write() extending i_size
+ 	   back past iattr->ia_size, because do_truncate() holds the
+ 	   generic inode semaphore. */
+-	if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)
+-		vmtruncate(inode, iattr->ia_size);
++	if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
++		vmtruncate(inode, iattr->ia_size);	
++		inode->i_blocks = (inode->i_size + 511) >> 9;
++	}	
+ 
+ 	return 0;
+ }
+@@ -248,12 +256,12 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
+ 	c = JFFS2_SB_INFO(inode->i_sb);
+ 
+ 	jffs2_init_inode_info(f);
+-	down(&f->sem);
++	mutex_lock(&f->sem);
+ 
+ 	ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
+ 
+ 	if (ret) {
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		iget_failed(inode);
+ 		return ERR_PTR(ret);
+ 	}
+@@ -330,7 +338,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
+ 		printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino);
+ 	}
+ 
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ 
+ 	D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
+ 	unlock_new_inode(inode);
+@@ -339,7 +347,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
+ error_io:
+ 	ret = -EIO;
+ error:
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ 	jffs2_do_clear_inode(c, f);
+ 	iget_failed(inode);
+ 	return ERR_PTR(ret);
+@@ -380,9 +388,9 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
+ 	   Flush the writebuffer, if neccecary, else we loose it */
+ 	if (!(sb->s_flags & MS_RDONLY)) {
+ 		jffs2_stop_garbage_collect_thread(c);
+-		down(&c->alloc_sem);
++		mutex_lock(&c->alloc_sem);
+ 		jffs2_flush_wbuf_pad(c);
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 	}
+ 
+ 	if (!(*flags & MS_RDONLY))
+@@ -429,7 +437,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
+ 
+ 	f = JFFS2_INODE_INFO(inode);
+ 	jffs2_init_inode_info(f);
+-	down(&f->sem);
++	mutex_lock(&f->sem);
+ 
+ 	memset(ri, 0, sizeof(*ri));
+ 	/* Set OS-specific defaults for new inodes */
+diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
+index 32ff037..bad0056 100644
+--- a/fs/jffs2/gc.c
++++ b/fs/jffs2/gc.c
+@@ -126,7 +126,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 	int ret = 0, inum, nlink;
+ 	int xattr = 0;
+ 
+-	if (down_interruptible(&c->alloc_sem))
++	if (mutex_lock_interruptible(&c->alloc_sem))
+ 		return -EINTR;
+ 
+ 	for (;;) {
+@@ -143,7 +143,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 			       c->unchecked_size);
+ 			jffs2_dbg_dump_block_lists_nolock(c);
+ 			spin_unlock(&c->erase_completion_lock);
+-			up(&c->alloc_sem);
++			mutex_unlock(&c->alloc_sem);
+ 			return -ENOSPC;
+ 		}
+ 
+@@ -190,7 +190,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 			 made no progress in this case, but that should be OK */
+ 			c->checked_ino--;
+ 
+-			up(&c->alloc_sem);
++			mutex_unlock(&c->alloc_sem);
+ 			sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
+ 			return 0;
+ 
+@@ -210,7 +210,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 			printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino);
+ 
+ 		jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT);
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 		return ret;
+ 	}
+ 
+@@ -221,9 +221,15 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 		jeb = jffs2_find_gc_block(c);
+ 
+ 	if (!jeb) {
+-		D1 (printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"));
++		/* Couldn't find a free block. But maybe we can just erase one and make 'progress'? */
++		if (!list_empty(&c->erase_pending_list)) {
++			spin_unlock(&c->erase_completion_lock);
++			mutex_unlock(&c->alloc_sem);
++			return -EAGAIN;
++		}
++		D1(printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"));
+ 		spin_unlock(&c->erase_completion_lock);
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 		return -EIO;
+ 	}
+ 
+@@ -232,7 +238,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 	   printk(KERN_DEBUG "Nextblock at  %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size));
+ 
+ 	if (!jeb->used_size) {
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 		goto eraseit;
+ 	}
+ 
+@@ -248,7 +254,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 			       jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size);
+ 			jeb->gc_node = raw;
+ 			spin_unlock(&c->erase_completion_lock);
+-			up(&c->alloc_sem);
++			mutex_unlock(&c->alloc_sem);
+ 			BUG();
+ 		}
+ 	}
+@@ -266,7 +272,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 			/* Just mark it obsolete */
+ 			jffs2_mark_node_obsolete(c, raw);
+ 		}
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 		goto eraseit_lock;
+ 	}
+ 
+@@ -334,7 +340,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 		*/
+ 		printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n",
+ 		       ic->ino, ic->state);
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 		spin_unlock(&c->inocache_lock);
+ 		BUG();
+ 
+@@ -345,7 +351,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 		   the alloc_sem() (for marking nodes invalid) so we must
+ 		   drop the alloc_sem before sleeping. */
+ 
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 		D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n",
+ 			  ic->ino, ic->state));
+ 		sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
+@@ -416,7 +422,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ 		ret = -ENOSPC;
+ 	}
+  release_sem:
+-	up(&c->alloc_sem);
++	mutex_unlock(&c->alloc_sem);
+ 
+  eraseit_lock:
+ 	/* If we've finished this block, start it erasing */
+@@ -445,7 +451,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c,  struct jffs2_era
+ 	uint32_t start = 0, end = 0, nrfrags = 0;
+ 	int ret = 0;
+ 
+-	down(&f->sem);
++	mutex_lock(&f->sem);
+ 
+ 	/* Now we have the lock for this inode. Check that it's still the one at the head
+ 	   of the list. */
+@@ -525,7 +531,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c,  struct jffs2_era
+ 		}
+ 	}
+  upnout:
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ 
+ 	return ret;
+ }
+@@ -846,7 +852,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
+ 		/* Prevent the erase code from nicking the obsolete node refs while
+ 		   we're looking at them. I really don't like this extra lock but
+ 		   can't see any alternative. Suggestions on a postcard to... */
+-		down(&c->erase_free_sem);
++		mutex_lock(&c->erase_free_sem);
+ 
+ 		for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
+ 
+@@ -899,7 +905,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
+ 			/* OK. The name really does match. There really is still an older node on
+ 			   the flash which our deletion dirent obsoletes. So we have to write out
+ 			   a new deletion dirent to replace it */
+-			up(&c->erase_free_sem);
++			mutex_unlock(&c->erase_free_sem);
+ 
+ 			D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n",
+ 				  ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino)));
+@@ -908,7 +914,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
+ 			return jffs2_garbage_collect_dirent(c, jeb, f, fd);
+ 		}
+ 
+-		up(&c->erase_free_sem);
++		mutex_unlock(&c->erase_free_sem);
+ 		kfree(rd);
+ 	}
+ 
+@@ -1081,7 +1087,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
+ 	return 0;
+ }
+ 
+-static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
++static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *orig_jeb,
+ 				       struct jffs2_inode_info *f, struct jffs2_full_dnode *fn,
+ 				       uint32_t start, uint32_t end)
+ {
+diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c
+index f4d525b..e217721 100644
+--- a/fs/jffs2/ioctl.c
++++ b/fs/jffs2/ioctl.c
+@@ -10,6 +10,7 @@
+  */
+ 
+ #include <linux/fs.h>
++#include "nodelist.h"
+ 
+ int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ 		unsigned long arg)
+diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h
+index 0b78fdc..31559f4 100644
+--- a/fs/jffs2/jffs2_fs_i.h
++++ b/fs/jffs2/jffs2_fs_i.h
+@@ -15,7 +15,7 @@
+ #include <linux/version.h>
+ #include <linux/rbtree.h>
+ #include <linux/posix_acl.h>
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
+ 
+ struct jffs2_inode_info {
+ 	/* We need an internal mutex similar to inode->i_mutex.
+@@ -24,7 +24,7 @@ struct jffs2_inode_info {
+ 	   before letting GC proceed. Or we'd have to put ugliness
+ 	   into the GC code so it didn't attempt to obtain the i_mutex
+ 	   for the inode(s) which are already locked */
+-	struct semaphore sem;
++	struct mutex sem;
+ 
+ 	/* The highest (datanode) version number used for this ino */
+ 	uint32_t highest_version;
+diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
+index 3a2197f..85ef6db 100644
+--- a/fs/jffs2/jffs2_fs_sb.h
++++ b/fs/jffs2/jffs2_fs_sb.h
+@@ -16,7 +16,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/workqueue.h>
+ #include <linux/completion.h>
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
+ #include <linux/timer.h>
+ #include <linux/wait.h>
+ #include <linux/list.h>
+@@ -44,7 +44,7 @@ struct jffs2_sb_info {
+ 	struct completion gc_thread_start; /* GC thread start completion */
+ 	struct completion gc_thread_exit; /* GC thread exit completion port */
+ 
+-	struct semaphore alloc_sem;	/* Used to protect all the following
++	struct mutex alloc_sem;		/* Used to protect all the following
+ 					   fields, and also to protect against
+ 					   out-of-order writing of nodes. And GC. */
+ 	uint32_t cleanmarker_size;	/* Size of an _inline_ CLEANMARKER
+@@ -87,6 +87,7 @@ struct jffs2_sb_info {
+ 	struct list_head erasable_list;		/* Blocks which are completely dirty, and need erasing */
+ 	struct list_head erasable_pending_wbuf_list;	/* Blocks which need erasing but only after the current wbuf is flushed */
+ 	struct list_head erasing_list;		/* Blocks which are currently erasing */
++	struct list_head erase_checking_list;	/* Blocks which are being checked and marked */
+ 	struct list_head erase_pending_list;	/* Blocks which need erasing now */
+ 	struct list_head erase_complete_list;	/* Blocks which are erased and need the clean marker written to them */
+ 	struct list_head free_list;		/* Blocks which are free and ready to be used */
+@@ -104,7 +105,7 @@ struct jffs2_sb_info {
+ 	/* Sem to allow jffs2_garbage_collect_deletion_dirent to
+ 	   drop the erase_completion_lock while it's holding a pointer
+ 	   to an obsoleted node. I don't like this. Alternatives welcomed. */
+-	struct semaphore erase_free_sem;
++	struct mutex erase_free_sem;
+ 
+ 	uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
+ 
+diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
+index ec1aae9..8219df6 100644
+--- a/fs/jffs2/nodelist.h
++++ b/fs/jffs2/nodelist.h
+@@ -87,7 +87,7 @@ struct jffs2_raw_node_ref
+ 		xattr_ref or xattr_datum instead. The common part of those structures
+ 		has NULL in the first word. See jffs2_raw_ref_to_ic() below */
+ 	uint32_t flash_offset;
+-#define TEST_TOTLEN
++#undef TEST_TOTLEN
+ #ifdef TEST_TOTLEN
+ 	uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
+ #endif
+diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
+index a0313fa..9df8f3e 100644
+--- a/fs/jffs2/nodemgmt.c
++++ b/fs/jffs2/nodemgmt.c
+@@ -48,7 +48,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ 	minsize = PAD(minsize);
+ 
+ 	D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize));
+-	down(&c->alloc_sem);
++	mutex_lock(&c->alloc_sem);
+ 
+ 	D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n"));
+ 
+@@ -57,7 +57,6 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ 	/* this needs a little more thought (true <tglx> :)) */
+ 	while(ret == -EAGAIN) {
+ 		while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
+-			int ret;
+ 			uint32_t dirty, avail;
+ 
+ 			/* calculate real dirty size
+@@ -82,7 +81,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ 					  dirty, c->unchecked_size, c->sector_size));
+ 
+ 				spin_unlock(&c->erase_completion_lock);
+-				up(&c->alloc_sem);
++				mutex_unlock(&c->alloc_sem);
+ 				return -ENOSPC;
+ 			}
+ 
+@@ -105,11 +104,11 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ 				D1(printk(KERN_DEBUG "max. available size 0x%08x  < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
+ 					  avail, blocksneeded * c->sector_size));
+ 				spin_unlock(&c->erase_completion_lock);
+-				up(&c->alloc_sem);
++				mutex_unlock(&c->alloc_sem);
+ 				return -ENOSPC;
+ 			}
+ 
+-			up(&c->alloc_sem);
++			mutex_unlock(&c->alloc_sem);
+ 
+ 			D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n",
+ 				  c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size,
+@@ -117,7 +116,10 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ 			spin_unlock(&c->erase_completion_lock);
+ 
+ 			ret = jffs2_garbage_collect_pass(c);
+-			if (ret)
++
++			if (ret == -EAGAIN)
++				jffs2_erase_pending_blocks(c, 1);
++			else if (ret)
+ 				return ret;
+ 
+ 			cond_resched();
+@@ -125,7 +127,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ 			if (signal_pending(current))
+ 				return -EINTR;
+ 
+-			down(&c->alloc_sem);
++			mutex_lock(&c->alloc_sem);
+ 			spin_lock(&c->erase_completion_lock);
+ 		}
+ 
+@@ -138,7 +140,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ 	if (!ret)
+ 		ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+ 	if (ret)
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 	return ret;
+ }
+ 
+@@ -463,7 +465,7 @@ void jffs2_complete_reservation(struct jffs2_sb_info *c)
+ {
+ 	D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n"));
+ 	jffs2_garbage_collect_trigger(c);
+-	up(&c->alloc_sem);
++	mutex_unlock(&c->alloc_sem);
+ }
+ 
+ static inline int on_list(struct list_head *obj, struct list_head *head)
+@@ -512,7 +514,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
+ 		   any jffs2_raw_node_refs. So we don't need to stop erases from
+ 		   happening, or protect against people holding an obsolete
+ 		   jffs2_raw_node_ref without the erase_completion_lock. */
+-		down(&c->erase_free_sem);
++		mutex_lock(&c->erase_free_sem);
+ 	}
+ 
+ 	spin_lock(&c->erase_completion_lock);
+@@ -715,7 +717,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
+ 	}
+ 
+  out_erase_sem:
+-	up(&c->erase_free_sem);
++	mutex_unlock(&c->erase_free_sem);
+ }
+ 
+ int jffs2_thread_should_wake(struct jffs2_sb_info *c)
+diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
+index e512a93..4cb4d76 100644
+--- a/fs/jffs2/readinode.c
++++ b/fs/jffs2/readinode.c
+@@ -825,8 +825,9 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
+ 	else // normal case...
+ 		tn->fn->size = je32_to_cpu(rd->dsize);
+ 
+-	dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
+-		  ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
++	dbg_readinode2("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
++		       ref_offset(ref), je32_to_cpu(rd->version),
++		       je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
+ 
+ 	ret = jffs2_add_tn_to_tree(c, rii, tn);
+ 
+@@ -836,13 +837,13 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
+ 		jffs2_free_tmp_dnode_info(tn);
+ 		return ret;
+ 	}
+-#ifdef JFFS2_DBG_READINODE_MESSAGES
+-	dbg_readinode("After adding ver %d:\n", je32_to_cpu(rd->version));
++#ifdef JFFS2_DBG_READINODE2_MESSAGES
++	dbg_readinode2("After adding ver %d:\n", je32_to_cpu(rd->version));
+ 	tn = tn_first(&rii->tn_root);
+ 	while (tn) {
+-		dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n",
+-			     tn, tn->version, tn->fn->ofs,
+-			     tn->fn->ofs+tn->fn->size, tn->overlapped);
++		dbg_readinode2("%p: v %d r 0x%x-0x%x ov %d\n",
++			       tn, tn->version, tn->fn->ofs,
++			       tn->fn->ofs+tn->fn->size, tn->overlapped);
+ 		tn = tn_next(tn);
+ 	}
+ #endif
+@@ -1193,7 +1194,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ 		JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
+ 			ret, retlen, sizeof(*latest_node));
+ 		/* FIXME: If this fails, there seems to be a memory leak. Find it. */
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		jffs2_do_clear_inode(c, f);
+ 		return ret?ret:-EIO;
+ 	}
+@@ -1202,7 +1203,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ 	if (crc != je32_to_cpu(latest_node->node_crc)) {
+ 		JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
+ 			f->inocache->ino, ref_offset(rii.latest_ref));
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		jffs2_do_clear_inode(c, f);
+ 		return -EIO;
+ 	}
+@@ -1242,7 +1243,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ 			f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);
+ 			if (!f->target) {
+ 				JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize));
+-				up(&f->sem);
++				mutex_unlock(&f->sem);
+ 				jffs2_do_clear_inode(c, f);
+ 				return -ENOMEM;
+ 			}
+@@ -1255,7 +1256,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ 					ret = -EIO;
+ 				kfree(f->target);
+ 				f->target = NULL;
+-				up(&f->sem);
++				mutex_unlock(&f->sem);
+ 				jffs2_do_clear_inode(c, f);
+ 				return -ret;
+ 			}
+@@ -1273,14 +1274,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ 		if (f->metadata) {
+ 			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
+ 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
+-			up(&f->sem);
++			mutex_unlock(&f->sem);
+ 			jffs2_do_clear_inode(c, f);
+ 			return -EIO;
+ 		}
+ 		if (!frag_first(&f->fragtree)) {
+ 			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
+ 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
+-			up(&f->sem);
++			mutex_unlock(&f->sem);
+ 			jffs2_do_clear_inode(c, f);
+ 			return -EIO;
+ 		}
+@@ -1289,7 +1290,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ 			JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
+ 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
+ 			/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
+-			up(&f->sem);
++			mutex_unlock(&f->sem);
+ 			jffs2_do_clear_inode(c, f);
+ 			return -EIO;
+ 		}
+@@ -1379,12 +1380,13 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
+ 	if (!f)
+ 		return -ENOMEM;
+ 
+-	init_MUTEX_LOCKED(&f->sem);
++	mutex_init(&f->sem);
++	mutex_lock(&f->sem);
+ 	f->inocache = ic;
+ 
+ 	ret = jffs2_do_read_inode_internal(c, f, &n);
+ 	if (!ret) {
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		jffs2_do_clear_inode(c, f);
+ 	}
+ 	kfree (f);
+@@ -1398,7 +1400,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
+ 
+ 	jffs2_clear_acl(f);
+ 	jffs2_xattr_delete_inode(c, f->inocache);
+-	down(&f->sem);
++	mutex_lock(&f->sem);
+ 	deleted = f->inocache && !f->inocache->nlink;
+ 
+ 	if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
+@@ -1430,5 +1432,5 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
+ 			jffs2_del_ino_cache(c, f->inocache);
+ 	}
+ 
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ }
+diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
+index 4677355..f3353df 100644
+--- a/fs/jffs2/super.c
++++ b/fs/jffs2/super.c
+@@ -47,7 +47,7 @@ static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
+ {
+ 	struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
+ 
+-	init_MUTEX(&ei->sem);
++	mutex_init(&ei->sem);
+ 	inode_init_once(&ei->vfs_inode);
+ }
+ 
+@@ -55,9 +55,9 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
+ {
+ 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+ 
+-	down(&c->alloc_sem);
++	mutex_lock(&c->alloc_sem);
+ 	jffs2_flush_wbuf_pad(c);
+-	up(&c->alloc_sem);
++	mutex_unlock(&c->alloc_sem);
+ 	return 0;
+ }
+ 
+@@ -95,8 +95,8 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
+ 
+ 	/* Initialize JFFS2 superblock locks, the further initialization will
+ 	 * be done later */
+-	init_MUTEX(&c->alloc_sem);
+-	init_MUTEX(&c->erase_free_sem);
++	mutex_init(&c->alloc_sem);
++	mutex_init(&c->erase_free_sem);
+ 	init_waitqueue_head(&c->erase_wait);
+ 	init_waitqueue_head(&c->inocache_wq);
+ 	spin_lock_init(&c->erase_completion_lock);
+@@ -125,9 +125,9 @@ static void jffs2_put_super (struct super_block *sb)
+ 
+ 	D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
+ 
+-	down(&c->alloc_sem);
++	mutex_lock(&c->alloc_sem);
+ 	jffs2_flush_wbuf_pad(c);
+-	up(&c->alloc_sem);
++	mutex_unlock(&c->alloc_sem);
+ 
+ 	jffs2_sum_exit(c);
+ 
+diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
+index d1d4f27..8de52b6 100644
+--- a/fs/jffs2/wbuf.c
++++ b/fs/jffs2/wbuf.c
+@@ -578,8 +578,8 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
+ 	if (!jffs2_is_writebuffered(c))
+ 		return 0;
+ 
+-	if (!down_trylock(&c->alloc_sem)) {
+-		up(&c->alloc_sem);
++	if (mutex_trylock(&c->alloc_sem)) {
++		mutex_unlock(&c->alloc_sem);
+ 		printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
+ 		BUG();
+ 	}
+@@ -702,10 +702,10 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
+ 	if (!c->wbuf)
+ 		return 0;
+ 
+-	down(&c->alloc_sem);
++	mutex_lock(&c->alloc_sem);
+ 	if (!jffs2_wbuf_pending_for_ino(c, ino)) {
+ 		D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino));
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 		return 0;
+ 	}
+ 
+@@ -725,14 +725,14 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
+ 	} else while (old_wbuf_len &&
+ 		      old_wbuf_ofs == c->wbuf_ofs) {
+ 
+-		up(&c->alloc_sem);
++		mutex_unlock(&c->alloc_sem);
+ 
+ 		D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() calls gc pass\n"));
+ 
+ 		ret = jffs2_garbage_collect_pass(c);
+ 		if (ret) {
+ 			/* GC failed. Flush it with padding instead */
+-			down(&c->alloc_sem);
++			mutex_lock(&c->alloc_sem);
+ 			down_write(&c->wbuf_sem);
+ 			ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
+ 			/* retry flushing wbuf in case jffs2_wbuf_recover
+@@ -742,12 +742,12 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
+ 			up_write(&c->wbuf_sem);
+ 			break;
+ 		}
+-		down(&c->alloc_sem);
++		mutex_lock(&c->alloc_sem);
+ 	}
+ 
+ 	D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() ends...\n"));
+ 
+-	up(&c->alloc_sem);
++	mutex_unlock(&c->alloc_sem);
+ 	return ret;
+ }
+ 
+@@ -1236,12 +1236,24 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
+ 	if (!c->wbuf)
+ 		return -ENOMEM;
+ 
++#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
++	c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
++	if (!c->wbuf_verify) {
++		kfree(c->oobbuf);
++		kfree(c->wbuf);
++		return -ENOMEM;
++	}
++#endif
++
+ 	printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size);
+ 
+ 	return 0;
+ }
+ 
+ void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {
++#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
++	kfree(c->wbuf_verify);
++#endif
+ 	kfree(c->wbuf);
+ }
+ 
+diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
+index 776f13c..665fce9 100644
+--- a/fs/jffs2/write.c
++++ b/fs/jffs2/write.c
+@@ -137,12 +137,12 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
+ 							     JFFS2_SUMMARY_INODE_SIZE);
+ 			} else {
+ 				/* Locking pain */
+-				up(&f->sem);
++				mutex_unlock(&f->sem);
+ 				jffs2_complete_reservation(c);
+ 
+ 				ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
+ 							  alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
+-				down(&f->sem);
++				mutex_lock(&f->sem);
+ 			}
+ 
+ 			if (!ret) {
+@@ -285,12 +285,12 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
+ 							     JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+ 			} else {
+ 				/* Locking pain */
+-				up(&f->sem);
++				mutex_unlock(&f->sem);
+ 				jffs2_complete_reservation(c);
+ 
+ 				ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
+ 							  alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+-				down(&f->sem);
++				mutex_lock(&f->sem);
+ 			}
+ 
+ 			if (!ret) {
+@@ -353,7 +353,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+ 			D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
+ 			break;
+ 		}
+-		down(&f->sem);
++		mutex_lock(&f->sem);
+ 		datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1)));
+ 		cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);
+ 
+@@ -381,7 +381,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+ 
+ 		if (IS_ERR(fn)) {
+ 			ret = PTR_ERR(fn);
+-			up(&f->sem);
++			mutex_unlock(&f->sem);
+ 			jffs2_complete_reservation(c);
+ 			if (!retried) {
+ 				/* Write error to be retried */
+@@ -403,11 +403,11 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+ 			jffs2_mark_node_obsolete(c, fn->raw);
+ 			jffs2_free_full_dnode(fn);
+ 
+-			up(&f->sem);
++			mutex_unlock(&f->sem);
+ 			jffs2_complete_reservation(c);
+ 			break;
+ 		}
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		jffs2_complete_reservation(c);
+ 		if (!datalen) {
+ 			printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n");
+@@ -439,7 +439,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ 				JFFS2_SUMMARY_INODE_SIZE);
+ 	D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
+ 	if (ret) {
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		return ret;
+ 	}
+ 
+@@ -454,7 +454,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ 	if (IS_ERR(fn)) {
+ 		D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n"));
+ 		/* Eeek. Wave bye bye */
+-		up(&f->sem);
++		mutex_unlock(&f->sem);
+ 		jffs2_complete_reservation(c);
+ 		return PTR_ERR(fn);
+ 	}
+@@ -463,7 +463,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ 	*/
+ 	f->metadata = fn;
+ 
+-	up(&f->sem);
++	mutex_unlock(&f->sem);
+ 	jffs2_complete_reservation(c);
+ 
+ 	ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode);
+@@ -489,7 +489,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ 		return -ENOMEM;
+ 	}
+ 
+-	down(&dir_f->sem);
++	mutex_lock(&dir_f->sem);
+ 
+ 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ 	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+@@ -513,7 +513,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ 		/* dirent failed to write. Delete the inode normally
+ 		   as if it were the final unlink() */
+ 		jffs2_complete_reservation(c);
+-		up(&dir_f->sem);
++		mutex_unlock(&dir_f->sem);
+ 		return PTR_ERR(fd);
+ 	}
+ 
+@@ -522,7 +522,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ 	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+ 
+ 	jffs2_complete_reservation(c);
+-	up(&dir_f->sem);
++	mutex_unlock(&dir_f->sem);
+ 
+ 	return 0;
+ }
+@@ -551,7 +551,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+ 			return ret;
+ 		}
+ 
+-		down(&dir_f->sem);
++		mutex_lock(&dir_f->sem);
+ 
+ 		/* Build a deletion node */
+ 		rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -574,21 +574,21 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+ 
+ 		if (IS_ERR(fd)) {
+ 			jffs2_complete_reservation(c);
+-			up(&dir_f->sem);
++			mutex_unlock(&dir_f->sem);
+ 			return PTR_ERR(fd);
+ 		}
+ 
+ 		/* File it. This will mark the old one obsolete. */
+ 		jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+-		up(&dir_f->sem);
++		mutex_unlock(&dir_f->sem);
+ 	} else {
+-		struct jffs2_full_dirent *fd = dir_f->dents;
+ 		uint32_t nhash = full_name_hash(name, namelen);
+ 
++		fd = dir_f->dents;
+ 		/* We don't actually want to reserve any space, but we do
+ 		   want to be holding the alloc_sem when we write to flash */
+-		down(&c->alloc_sem);
+-		down(&dir_f->sem);
++		mutex_lock(&c->alloc_sem);
++		mutex_lock(&dir_f->sem);
+ 
+ 		for (fd = dir_f->dents; fd; fd = fd->next) {
+ 			if (fd->nhash == nhash &&
+@@ -607,7 +607,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+ 				break;
+ 			}
+ 		}
+-		up(&dir_f->sem);
++		mutex_unlock(&dir_f->sem);
+ 	}
+ 
+ 	/* dead_f is NULL if this was a rename not a real unlink */
+@@ -615,7 +615,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+ 	   pointing to an inode which didn't exist. */
+ 	if (dead_f && dead_f->inocache) {
+ 
+-		down(&dead_f->sem);
++		mutex_lock(&dead_f->sem);
+ 
+ 		if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {
+ 			while (dead_f->dents) {
+@@ -639,7 +639,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+ 
+ 		dead_f->inocache->nlink--;
+ 		/* NB: Caller must set inode nlink if appropriate */
+-		up(&dead_f->sem);
++		mutex_unlock(&dead_f->sem);
+ 	}
+ 
+ 	jffs2_complete_reservation(c);
+@@ -666,7 +666,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
+ 		return ret;
+ 	}
+ 
+-	down(&dir_f->sem);
++	mutex_lock(&dir_f->sem);
+ 
+ 	/* Build a deletion node */
+ 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -691,7 +691,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
+ 
+ 	if (IS_ERR(fd)) {
+ 		jffs2_complete_reservation(c);
+-		up(&dir_f->sem);
++		mutex_unlock(&dir_f->sem);
+ 		return PTR_ERR(fd);
+ 	}
+ 
+@@ -699,7 +699,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
+ 	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+ 
+ 	jffs2_complete_reservation(c);
+-	up(&dir_f->sem);
++	mutex_unlock(&dir_f->sem);
+ 
+ 	return 0;
+ }
+diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
+index a1f8e37..afe222b 100644
+--- a/fs/jfs/ioctl.c
++++ b/fs/jfs/ioctl.c
+@@ -8,6 +8,7 @@
+ #include <linux/fs.h>
+ #include <linux/ctype.h>
+ #include <linux/capability.h>
++#include <linux/mount.h>
+ #include <linux/time.h>
+ #include <linux/sched.h>
+ #include <asm/current.h>
+@@ -65,23 +66,30 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		return put_user(flags, (int __user *) arg);
+ 	case JFS_IOC_SETFLAGS: {
+ 		unsigned int oldflags;
++		int err;
+ 
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
+ 
+-		if (!is_owner_or_cap(inode))
+-			return -EACCES;
+-
+-		if (get_user(flags, (int __user *) arg))
+-			return -EFAULT;
++		if (!is_owner_or_cap(inode)) {
++			err = -EACCES;
++			goto setflags_out;
++		}
++		if (get_user(flags, (int __user *) arg)) {
++			err = -EFAULT;
++			goto setflags_out;
++		}
+ 
+ 		flags = jfs_map_ext2(flags, 1);
+ 		if (!S_ISDIR(inode->i_mode))
+ 			flags &= ~JFS_DIRSYNC_FL;
+ 
+ 		/* Is it quota file? Do not allow user to mess with it */
+-		if (IS_NOQUOTA(inode))
+-			return -EPERM;
++		if (IS_NOQUOTA(inode)) {
++			err = -EPERM;
++			goto setflags_out;
++		}
+ 
+ 		/* Lock against other parallel changes of flags */
+ 		mutex_lock(&inode->i_mutex);
+@@ -98,7 +106,8 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 			(JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
+ 			if (!capable(CAP_LINUX_IMMUTABLE)) {
+ 				mutex_unlock(&inode->i_mutex);
+-				return -EPERM;
++				err = -EPERM;
++				goto setflags_out;
+ 			}
+ 		}
+ 
+@@ -110,7 +119,9 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ 		mutex_unlock(&inode->i_mutex);
+ 		inode->i_ctime = CURRENT_TIME_SEC;
+ 		mark_inode_dirty(inode);
+-		return 0;
++setflags_out:
++		mnt_drop_write(filp->f_path.mnt);
++		return err;
+ 	}
+ 	default:
+ 		return -ENOTTY;
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index e198506..2bc7d8a 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -2172,7 +2172,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
+ 	}
+ 
+ 	/* update the free count for this dmap */
+-	dp->nfree = cpu_to_le32(le32_to_cpu(dp->nfree) - nblocks);
++	le32_add_cpu(&dp->nfree, -nblocks);
+ 
+ 	BMAP_LOCK(bmp);
+ 
+@@ -2316,7 +2316,7 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
+ 
+ 	/* update the free count for this dmap.
+ 	 */
+-	dp->nfree = cpu_to_le32(le32_to_cpu(dp->nfree) + nblocks);
++	le32_add_cpu(&dp->nfree, nblocks);
+ 
+ 	BMAP_LOCK(bmp);
+ 
+@@ -3226,7 +3226,7 @@ static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
+ 	}
+ 
+ 	/* update the free count for this dmap */
+-	dp->nfree = cpu_to_le32(le32_to_cpu(dp->nfree) - nblocks);
++	le32_add_cpu(&dp->nfree, -nblocks);
+ 
+ 	/* reconstruct summary tree */
+ 	dbInitDmapTree(dp);
+@@ -3660,9 +3660,8 @@ static int dbInitDmap(struct dmap * dp, s64 Blkno, int nblocks)
+ 			goto initTree;
+ 		}
+ 	} else {
+-		dp->nblocks =
+-		    cpu_to_le32(le32_to_cpu(dp->nblocks) + nblocks);
+-		dp->nfree = cpu_to_le32(le32_to_cpu(dp->nfree) + nblocks);
++		le32_add_cpu(&dp->nblocks, nblocks);
++		le32_add_cpu(&dp->nfree, nblocks);
+ 	}
+ 
+ 	/* word number containing start block number */
+diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h
+index 11e6d47..1a6eb41 100644
+--- a/fs/jfs/jfs_dmap.h
++++ b/fs/jfs/jfs_dmap.h
+@@ -61,7 +61,7 @@
+  * determine the maximum free string for four (lower level) nodes
+  * of the tree.
+  */
+-static __inline signed char TREEMAX(signed char *cp)
++static inline signed char TREEMAX(signed char *cp)
+ {
+ 	signed char tmp1, tmp2;
+ 
+diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
+index 9bf29f7..734ec91 100644
+--- a/fs/jfs/jfs_imap.c
++++ b/fs/jfs/jfs_imap.c
+@@ -1019,8 +1019,7 @@ int diFree(struct inode *ip)
+ 		/* update the free inode counts at the iag, ag and
+ 		 * map level.
+ 		 */
+-		iagp->nfreeinos =
+-		    cpu_to_le32(le32_to_cpu(iagp->nfreeinos) + 1);
++		le32_add_cpu(&iagp->nfreeinos, 1);
+ 		imap->im_agctl[agno].numfree += 1;
+ 		atomic_inc(&imap->im_numfree);
+ 
+@@ -1219,9 +1218,8 @@ int diFree(struct inode *ip)
+ 	/* update the number of free inodes and number of free extents
+ 	 * for the iag.
+ 	 */
+-	iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) -
+-				      (INOSPEREXT - 1));
+-	iagp->nfreeexts = cpu_to_le32(le32_to_cpu(iagp->nfreeexts) + 1);
++	le32_add_cpu(&iagp->nfreeinos, -(INOSPEREXT - 1));
++	le32_add_cpu(&iagp->nfreeexts, 1);
+ 
+ 	/* update the number of free inodes and backed inodes
+ 	 * at the ag and inode map level.
+@@ -2124,7 +2122,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
+ 	/* update the free inode count at the iag, ag, inode
+ 	 * map levels.
+ 	 */
+-	iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) - 1);
++	le32_add_cpu(&iagp->nfreeinos, -1);
+ 	imap->im_agctl[agno].numfree -= 1;
+ 	atomic_dec(&imap->im_numfree);
+ 
+@@ -2378,9 +2376,8 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
+ 	/* update the free inode and free extent counts for the
+ 	 * iag.
+ 	 */
+-	iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) +
+-				      (INOSPEREXT - 1));
+-	iagp->nfreeexts = cpu_to_le32(le32_to_cpu(iagp->nfreeexts) - 1);
++	le32_add_cpu(&iagp->nfreeinos, (INOSPEREXT - 1));
++	le32_add_cpu(&iagp->nfreeexts, -1);
+ 
+ 	/* update the free and backed inode counts for the ag.
+ 	 */
+diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
+index a000aaa..5a61ebf 100644
+--- a/fs/jfs/jfs_xtree.c
++++ b/fs/jfs/jfs_xtree.c
+@@ -905,8 +905,7 @@ int xtInsert(tid_t tid,		/* transaction id */
+ 	XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
+ 
+ 	/* advance next available entry index */
+-	p->header.nextindex =
+-	    cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
++	le16_add_cpu(&p->header.nextindex, 1);
+ 
+ 	/* Don't log it if there are no links to the file */
+ 	if (!test_cflag(COMMIT_Nolink, ip)) {
+@@ -997,8 +996,7 @@ xtSplitUp(tid_t tid,
+ 			    split->addr);
+ 
+ 		/* advance next available entry index */
+-		sp->header.nextindex =
+-		    cpu_to_le16(le16_to_cpu(sp->header.nextindex) + 1);
++		le16_add_cpu(&sp->header.nextindex, 1);
+ 
+ 		/* Don't log it if there are no links to the file */
+ 		if (!test_cflag(COMMIT_Nolink, ip)) {
+@@ -1167,9 +1165,7 @@ xtSplitUp(tid_t tid,
+ 				    JFS_SBI(ip->i_sb)->nbperpage, rcbn);
+ 
+ 			/* advance next available entry index. */
+-			sp->header.nextindex =
+-			    cpu_to_le16(le16_to_cpu(sp->header.nextindex) +
+-					1);
++			le16_add_cpu(&sp->header.nextindex, 1);
+ 
+ 			/* Don't log it if there are no links to the file */
+ 			if (!test_cflag(COMMIT_Nolink, ip)) {
+@@ -1738,8 +1734,7 @@ int xtExtend(tid_t tid,		/* transaction id */
+ 		XT_PUTENTRY(xad, XAD_NEW, xoff, len, xaddr);
+ 
+ 		/* advance next available entry index */
+-		p->header.nextindex =
+-		    cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
++		le16_add_cpu(&p->header.nextindex, 1);
+ 	}
+ 
+ 	/* get back old entry */
+@@ -1905,8 +1900,7 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
+ 		XT_PUTENTRY(xad, XAD_NEW, xoff, xlen, xaddr);
+ 
+ 		/* advance next available entry index */
+-		p->header.nextindex =
+-		    cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
++		le16_add_cpu(&p->header.nextindex, 1);
+ 	}
+ 
+ 	/* get back old XAD */
+@@ -2567,8 +2561,7 @@ int xtAppend(tid_t tid,		/* transaction id */
+ 	XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
+ 
+ 	/* advance next available entry index */
+-	p->header.nextindex =
+-	    cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
++	le16_add_cpu(&p->header.nextindex, 1);
+ 
+ 	xtlck->lwm.offset =
+ 	    (xtlck->lwm.offset) ? min(index,(int) xtlck->lwm.offset) : index;
+@@ -2631,8 +2624,7 @@ int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag)
+ 	 * delete the entry from the leaf page
+ 	 */
+ 	nextindex = le16_to_cpu(p->header.nextindex);
+-	p->header.nextindex =
+-	    cpu_to_le16(le16_to_cpu(p->header.nextindex) - 1);
++	le16_add_cpu(&p->header.nextindex, -1);
+ 
+ 	/*
+ 	 * if the leaf page bocome empty, free the page
+@@ -2795,9 +2787,7 @@ xtDeleteUp(tid_t tid, struct inode *ip,
+ 					(nextindex - index -
+ 					 1) << L2XTSLOTSIZE);
+ 
+-			p->header.nextindex =
+-			    cpu_to_le16(le16_to_cpu(p->header.nextindex) -
+-					1);
++			le16_add_cpu(&p->header.nextindex, -1);
+ 			jfs_info("xtDeleteUp(entry): 0x%lx[%d]",
+ 				 (ulong) parent->bn, index);
+ 		}
+diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
+index b6b74a6..40b16f2 100644
+--- a/fs/lockd/clntproc.c
++++ b/fs/lockd/clntproc.c
+@@ -155,8 +155,6 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
+ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
+ {
+ 	struct nlm_rqst		*call;
+-	sigset_t		oldset;
+-	unsigned long		flags;
+ 	int			status;
+ 
+ 	nlm_get_host(host);
+@@ -168,22 +166,6 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
+ 	/* Set up the argument struct */
+ 	nlmclnt_setlockargs(call, fl);
+ 
+-	/* Keep the old signal mask */
+-	spin_lock_irqsave(&current->sighand->siglock, flags);
+-	oldset = current->blocked;
+-
+-	/* If we're cleaning up locks because the process is exiting,
+-	 * perform the RPC call asynchronously. */
+-	if ((IS_SETLK(cmd) || IS_SETLKW(cmd))
+-	    && fl->fl_type == F_UNLCK
+-	    && (current->flags & PF_EXITING)) {
+-		sigfillset(&current->blocked);	/* Mask all signals */
+-		recalc_sigpending();
+-
+-		call->a_flags = RPC_TASK_ASYNC;
+-	}
+-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+-
+ 	if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
+ 		if (fl->fl_type != F_UNLCK) {
+ 			call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
+@@ -198,11 +180,6 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
+ 	fl->fl_ops->fl_release_private(fl);
+ 	fl->fl_ops = NULL;
+ 
+-	spin_lock_irqsave(&current->sighand->siglock, flags);
+-	current->blocked = oldset;
+-	recalc_sigpending();
+-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+-
+ 	dprintk("lockd: clnt proc returns %d\n", status);
+ 	return status;
+ }
+@@ -221,6 +198,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
+ 	for(;;) {
+ 		call = kzalloc(sizeof(*call), GFP_KERNEL);
+ 		if (call != NULL) {
++			atomic_set(&call->a_count, 1);
+ 			locks_init_lock(&call->a_args.lock.fl);
+ 			locks_init_lock(&call->a_res.lock.fl);
+ 			call->a_host = host;
+@@ -237,6 +215,8 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
+ 
+ void nlm_release_call(struct nlm_rqst *call)
+ {
++	if (!atomic_dec_and_test(&call->a_count))
++		return;
+ 	nlm_release_host(call->a_host);
+ 	nlmclnt_release_lockargs(call);
+ 	kfree(call);
+@@ -267,7 +247,7 @@ static int nlm_wait_on_grace(wait_queue_head_t *queue)
+  * Generic NLM call
+  */
+ static int
+-nlmclnt_call(struct nlm_rqst *req, u32 proc)
++nlmclnt_call(struct rpc_cred *cred, struct nlm_rqst *req, u32 proc)
+ {
+ 	struct nlm_host	*host = req->a_host;
+ 	struct rpc_clnt	*clnt;
+@@ -276,6 +256,7 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
+ 	struct rpc_message msg = {
+ 		.rpc_argp	= argp,
+ 		.rpc_resp	= resp,
++		.rpc_cred	= cred,
+ 	};
+ 	int		status;
+ 
+@@ -343,10 +324,16 @@ in_grace_period:
+ /*
+  * Generic NLM call, async version.
+  */
+-static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
++static struct rpc_task *__nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
+ {
+ 	struct nlm_host	*host = req->a_host;
+ 	struct rpc_clnt	*clnt;
++	struct rpc_task_setup task_setup_data = {
++		.rpc_message = msg,
++		.callback_ops = tk_ops,
++		.callback_data = req,
++		.flags = RPC_TASK_ASYNC,
++	};
+ 
+ 	dprintk("lockd: call procedure %d on %s (async)\n",
+ 			(int)proc, host->h_name);
+@@ -356,21 +343,36 @@ static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *
+ 	if (clnt == NULL)
+ 		goto out_err;
+ 	msg->rpc_proc = &clnt->cl_procinfo[proc];
++	task_setup_data.rpc_client = clnt;
+ 
+         /* bootstrap and kick off the async RPC call */
+-        return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req);
++	return rpc_run_task(&task_setup_data);
+ out_err:
+ 	tk_ops->rpc_release(req);
+-	return -ENOLCK;
++	return ERR_PTR(-ENOLCK);
+ }
+ 
++static int nlm_do_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
++{
++	struct rpc_task *task;
++
++	task = __nlm_async_call(req, proc, msg, tk_ops);
++	if (IS_ERR(task))
++		return PTR_ERR(task);
++	rpc_put_task(task);
++	return 0;
++}
++
++/*
++ * NLM asynchronous call.
++ */
+ int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
+ {
+ 	struct rpc_message msg = {
+ 		.rpc_argp	= &req->a_args,
+ 		.rpc_resp	= &req->a_res,
+ 	};
+-	return __nlm_async_call(req, proc, &msg, tk_ops);
++	return nlm_do_async_call(req, proc, &msg, tk_ops);
+ }
+ 
+ int nlm_async_reply(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
+@@ -378,7 +380,33 @@ int nlm_async_reply(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *t
+ 	struct rpc_message msg = {
+ 		.rpc_argp	= &req->a_res,
+ 	};
+-	return __nlm_async_call(req, proc, &msg, tk_ops);
++	return nlm_do_async_call(req, proc, &msg, tk_ops);
++}
++
++/*
++ * NLM client asynchronous call.
++ *
++ * Note that although the calls are asynchronous, and are therefore
++ *      guaranteed to complete, we still always attempt to wait for
++ *      completion in order to be able to correctly track the lock
++ *      state.
++ */
++static int nlmclnt_async_call(struct rpc_cred *cred, struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
++{
++	struct rpc_message msg = {
++		.rpc_argp	= &req->a_args,
++		.rpc_resp	= &req->a_res,
++		.rpc_cred	= cred,
++	};
++	struct rpc_task *task;
++	int err;
++
++	task = __nlm_async_call(req, proc, &msg, tk_ops);
++	if (IS_ERR(task))
++		return PTR_ERR(task);
++	err = rpc_wait_for_completion_task(task);
++	rpc_put_task(task);
++	return err;
+ }
+ 
+ /*
+@@ -389,7 +417,7 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
+ {
+ 	int	status;
+ 
+-	status = nlmclnt_call(req, NLMPROC_TEST);
++	status = nlmclnt_call(nfs_file_cred(fl->fl_file), req, NLMPROC_TEST);
+ 	if (status < 0)
+ 		goto out;
+ 
+@@ -480,10 +508,12 @@ static int do_vfs_lock(struct file_lock *fl)
+ static int
+ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
+ {
++	struct rpc_cred *cred = nfs_file_cred(fl->fl_file);
+ 	struct nlm_host	*host = req->a_host;
+ 	struct nlm_res	*resp = &req->a_res;
+ 	struct nlm_wait *block = NULL;
+ 	unsigned char fl_flags = fl->fl_flags;
++	unsigned char fl_type;
+ 	int status = -ENOLCK;
+ 
+ 	if (nsm_monitor(host) < 0) {
+@@ -493,18 +523,22 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
+ 	}
+ 	fl->fl_flags |= FL_ACCESS;
+ 	status = do_vfs_lock(fl);
++	fl->fl_flags = fl_flags;
+ 	if (status < 0)
+ 		goto out;
+ 
+ 	block = nlmclnt_prepare_block(host, fl);
+ again:
++	/*
++	 * Initialise resp->status to a valid non-zero value,
++	 * since 0 == nlm_lck_granted
++	 */
++	resp->status = nlm_lck_blocked;
+ 	for(;;) {
+ 		/* Reboot protection */
+ 		fl->fl_u.nfs_fl.state = host->h_state;
+-		status = nlmclnt_call(req, NLMPROC_LOCK);
++		status = nlmclnt_call(cred, req, NLMPROC_LOCK);
+ 		if (status < 0)
+-			goto out_unblock;
+-		if (!req->a_args.block)
+ 			break;
+ 		/* Did a reclaimer thread notify us of a server reboot? */
+ 		if (resp->status ==  nlm_lck_denied_grace_period)
+@@ -513,15 +547,22 @@ again:
+ 			break;
+ 		/* Wait on an NLM blocking lock */
+ 		status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT);
+-		/* if we were interrupted. Send a CANCEL request to the server
+-		 * and exit
+-		 */
+ 		if (status < 0)
+-			goto out_unblock;
++			break;
+ 		if (resp->status != nlm_lck_blocked)
+ 			break;
+ 	}
+ 
++	/* if we were interrupted while blocking, then cancel the lock request
++	 * and exit
++	 */
++	if (resp->status == nlm_lck_blocked) {
++		if (!req->a_args.block)
++			goto out_unlock;
++		if (nlmclnt_cancel(host, req->a_args.block, fl) == 0)
++			goto out_unblock;
++	}
++
+ 	if (resp->status == nlm_granted) {
+ 		down_read(&host->h_rwsem);
+ 		/* Check whether or not the server has rebooted */
+@@ -530,20 +571,34 @@ again:
+ 			goto again;
+ 		}
+ 		/* Ensure the resulting lock will get added to granted list */
+-		fl->fl_flags = fl_flags | FL_SLEEP;
++		fl->fl_flags |= FL_SLEEP;
+ 		if (do_vfs_lock(fl) < 0)
+ 			printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
+ 		up_read(&host->h_rwsem);
++		fl->fl_flags = fl_flags;
++		status = 0;
+ 	}
++	if (status < 0)
++		goto out_unlock;
+ 	status = nlm_stat_to_errno(resp->status);
+ out_unblock:
+ 	nlmclnt_finish_block(block);
+-	/* Cancel the blocked request if it is still pending */
+-	if (resp->status == nlm_lck_blocked)
+-		nlmclnt_cancel(host, req->a_args.block, fl);
+ out:
+ 	nlm_release_call(req);
++	return status;
++out_unlock:
++	/* Fatal error: ensure that we remove the lock altogether */
++	dprintk("lockd: lock attempt ended in fatal error.\n"
++		"       Attempting to unlock.\n");
++	nlmclnt_finish_block(block);
++	fl_type = fl->fl_type;
++	fl->fl_type = F_UNLCK;
++	down_read(&host->h_rwsem);
++	do_vfs_lock(fl);
++	up_read(&host->h_rwsem);
++	fl->fl_type = fl_type;
+ 	fl->fl_flags = fl_flags;
++	nlmclnt_async_call(cred, req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
+ 	return status;
+ }
+ 
+@@ -567,8 +622,8 @@ nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl)
+ 	nlmclnt_setlockargs(req, fl);
+ 	req->a_args.reclaim = 1;
+ 
+-	if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0
+-	 && req->a_res.status == nlm_granted)
++	status = nlmclnt_call(nfs_file_cred(fl->fl_file), req, NLMPROC_LOCK);
++	if (status >= 0 && req->a_res.status == nlm_granted)
+ 		return 0;
+ 
+ 	printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d "
+@@ -598,7 +653,8 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
+ {
+ 	struct nlm_host	*host = req->a_host;
+ 	struct nlm_res	*resp = &req->a_res;
+-	int status = 0;
++	int status;
++	unsigned char fl_flags = fl->fl_flags;
+ 
+ 	/*
+ 	 * Note: the server is supposed to either grant us the unlock
+@@ -607,16 +663,17 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
+ 	 */
+ 	fl->fl_flags |= FL_EXISTS;
+ 	down_read(&host->h_rwsem);
+-	if (do_vfs_lock(fl) == -ENOENT) {
+-		up_read(&host->h_rwsem);
++	status = do_vfs_lock(fl);
++	up_read(&host->h_rwsem);
++	fl->fl_flags = fl_flags;
++	if (status == -ENOENT) {
++		status = 0;
+ 		goto out;
+ 	}
+-	up_read(&host->h_rwsem);
+-
+-	if (req->a_flags & RPC_TASK_ASYNC)
+-		return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
+ 
+-	status = nlmclnt_call(req, NLMPROC_UNLOCK);
++	atomic_inc(&req->a_count);
++	status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
++			NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
+ 	if (status < 0)
+ 		goto out;
+ 
+@@ -671,16 +728,10 @@ static const struct rpc_call_ops nlmclnt_unlock_ops = {
+ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl)
+ {
+ 	struct nlm_rqst	*req;
+-	unsigned long	flags;
+-	sigset_t	oldset;
+-	int		status;
++	int status;
+ 
+-	/* Block all signals while setting up call */
+-	spin_lock_irqsave(&current->sighand->siglock, flags);
+-	oldset = current->blocked;
+-	sigfillset(&current->blocked);
+-	recalc_sigpending();
+-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
++	dprintk("lockd: blocking lock attempt was interrupted by a signal.\n"
++		"       Attempting to cancel lock.\n");
+ 
+ 	req = nlm_alloc_call(nlm_get_host(host));
+ 	if (!req)
+@@ -690,13 +741,12 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl
+ 	nlmclnt_setlockargs(req, fl);
+ 	req->a_args.block = block;
+ 
+-	status = nlm_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops);
+-
+-	spin_lock_irqsave(&current->sighand->siglock, flags);
+-	current->blocked = oldset;
+-	recalc_sigpending();
+-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+-
++	atomic_inc(&req->a_count);
++	status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
++			NLMPROC_CANCEL, &nlmclnt_cancel_ops);
++	if (status == 0 && req->a_res.status == nlm_lck_denied)
++		status = -ENOLCK;
++	nlm_release_call(req);
+ 	return status;
+ }
+ 
+diff --git a/fs/lockd/host.c b/fs/lockd/host.c
+index f1ef49f..a17664c 100644
+--- a/fs/lockd/host.c
++++ b/fs/lockd/host.c
+@@ -19,12 +19,11 @@
+ 
+ 
+ #define NLMDBG_FACILITY		NLMDBG_HOSTCACHE
+-#define NLM_HOST_MAX		64
+ #define NLM_HOST_NRHASH		32
+ #define NLM_ADDRHASH(addr)	(ntohl(addr) & (NLM_HOST_NRHASH-1))
+ #define NLM_HOST_REBIND		(60 * HZ)
+-#define NLM_HOST_EXPIRE		((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
+-#define NLM_HOST_COLLECT	((nrhosts > NLM_HOST_MAX)? 120 * HZ :  60 * HZ)
++#define NLM_HOST_EXPIRE		(300 * HZ)
++#define NLM_HOST_COLLECT	(120 * HZ)
+ 
+ static struct hlist_head	nlm_hosts[NLM_HOST_NRHASH];
+ static unsigned long		next_gc;
+@@ -42,11 +41,12 @@ static struct nsm_handle *	nsm_find(const struct sockaddr_in *sin,
+ /*
+  * Common host lookup routine for server & client
+  */
+-static struct nlm_host *
+-nlm_lookup_host(int server, const struct sockaddr_in *sin,
+-		int proto, int version, const char *hostname,
+-		unsigned int hostname_len,
+-		const struct sockaddr_in *ssin)
++static struct nlm_host *nlm_lookup_host(int server,
++					const struct sockaddr_in *sin,
++					int proto, u32 version,
++					const char *hostname,
++					unsigned int hostname_len,
++					const struct sockaddr_in *ssin)
+ {
+ 	struct hlist_head *chain;
+ 	struct hlist_node *pos;
+@@ -55,7 +55,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
+ 	int		hash;
+ 
+ 	dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
+-			", p=%d, v=%d, my role=%s, name=%.*s)\n",
++			", p=%d, v=%u, my role=%s, name=%.*s)\n",
+ 			NIPQUAD(ssin->sin_addr.s_addr),
+ 			NIPQUAD(sin->sin_addr.s_addr), proto, version,
+ 			server? "server" : "client",
+@@ -142,9 +142,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
+ 	INIT_LIST_HEAD(&host->h_granted);
+ 	INIT_LIST_HEAD(&host->h_reclaim);
+ 
+-	if (++nrhosts > NLM_HOST_MAX)
+-		next_gc = 0;
+-
++	nrhosts++;
+ out:
+ 	mutex_unlock(&nlm_host_mutex);
+ 	return host;
+@@ -175,9 +173,10 @@ nlm_destroy_host(struct nlm_host *host)
+ /*
+  * Find an NLM server handle in the cache. If there is none, create it.
+  */
+-struct nlm_host *
+-nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
+-			const char *hostname, unsigned int hostname_len)
++struct nlm_host *nlmclnt_lookup_host(const struct sockaddr_in *sin,
++				     int proto, u32 version,
++				     const char *hostname,
++				     unsigned int hostname_len)
+ {
+ 	struct sockaddr_in ssin = {0};
+ 
+@@ -460,7 +459,7 @@ nlm_gc_hosts(void)
+  * Manage NSM handles
+  */
+ static LIST_HEAD(nsm_handles);
+-static DEFINE_MUTEX(nsm_mutex);
++static DEFINE_SPINLOCK(nsm_lock);
+ 
+ static struct nsm_handle *
+ __nsm_find(const struct sockaddr_in *sin,
+@@ -468,7 +467,7 @@ __nsm_find(const struct sockaddr_in *sin,
+ 		int create)
+ {
+ 	struct nsm_handle *nsm = NULL;
+-	struct list_head *pos;
++	struct nsm_handle *pos;
+ 
+ 	if (!sin)
+ 		return NULL;
+@@ -482,38 +481,43 @@ __nsm_find(const struct sockaddr_in *sin,
+ 		return NULL;
+ 	}
+ 
+-	mutex_lock(&nsm_mutex);
+-	list_for_each(pos, &nsm_handles) {
+-		nsm = list_entry(pos, struct nsm_handle, sm_link);
++retry:
++	spin_lock(&nsm_lock);
++	list_for_each_entry(pos, &nsm_handles, sm_link) {
+ 
+ 		if (hostname && nsm_use_hostnames) {
+-			if (strlen(nsm->sm_name) != hostname_len
+-			 || memcmp(nsm->sm_name, hostname, hostname_len))
++			if (strlen(pos->sm_name) != hostname_len
++			 || memcmp(pos->sm_name, hostname, hostname_len))
+ 				continue;
+-		} else if (!nlm_cmp_addr(&nsm->sm_addr, sin))
++		} else if (!nlm_cmp_addr(&pos->sm_addr, sin))
+ 			continue;
+-		atomic_inc(&nsm->sm_count);
+-		goto out;
++		atomic_inc(&pos->sm_count);
++		kfree(nsm);
++		nsm = pos;
++		goto found;
+ 	}
+-
+-	if (!create) {
+-		nsm = NULL;
+-		goto out;
++	if (nsm) {
++		list_add(&nsm->sm_link, &nsm_handles);
++		goto found;
+ 	}
++	spin_unlock(&nsm_lock);
++
++	if (!create)
++		return NULL;
+ 
+ 	nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
+-	if (nsm != NULL) {
+-		nsm->sm_addr = *sin;
+-		nsm->sm_name = (char *) (nsm + 1);
+-		memcpy(nsm->sm_name, hostname, hostname_len);
+-		nsm->sm_name[hostname_len] = '\0';
+-		atomic_set(&nsm->sm_count, 1);
++	if (nsm == NULL)
++		return NULL;
+ 
+-		list_add(&nsm->sm_link, &nsm_handles);
+-	}
++	nsm->sm_addr = *sin;
++	nsm->sm_name = (char *) (nsm + 1);
++	memcpy(nsm->sm_name, hostname, hostname_len);
++	nsm->sm_name[hostname_len] = '\0';
++	atomic_set(&nsm->sm_count, 1);
++	goto retry;
+ 
+-out:
+-	mutex_unlock(&nsm_mutex);
++found:
++	spin_unlock(&nsm_lock);
+ 	return nsm;
+ }
+ 
+@@ -532,12 +536,9 @@ nsm_release(struct nsm_handle *nsm)
+ {
+ 	if (!nsm)
+ 		return;
+-	if (atomic_dec_and_test(&nsm->sm_count)) {
+-		mutex_lock(&nsm_mutex);
+-		if (atomic_read(&nsm->sm_count) == 0) {
+-			list_del(&nsm->sm_link);
+-			kfree(nsm);
+-		}
+-		mutex_unlock(&nsm_mutex);
++	if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
++		list_del(&nsm->sm_link);
++		spin_unlock(&nsm_lock);
++		kfree(nsm);
+ 	}
+ }
+diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
+index 908b23f..e4d5635 100644
+--- a/fs/lockd/mon.c
++++ b/fs/lockd/mon.c
+@@ -18,6 +18,8 @@
+ 
+ #define NLMDBG_FACILITY		NLMDBG_MONITOR
+ 
++#define XDR_ADDRBUF_LEN		(20)
++
+ static struct rpc_clnt *	nsm_create(void);
+ 
+ static struct rpc_program	nsm_program;
+@@ -147,28 +149,55 @@ nsm_create(void)
+ 
+ /*
+  * XDR functions for NSM.
++ *
++ * See http://www.opengroup.org/ for details on the Network
++ * Status Monitor wire protocol.
+  */
+ 
+-static __be32 *
+-xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
++static __be32 *xdr_encode_nsm_string(__be32 *p, char *string)
+ {
+-	char	buffer[20], *name;
+-
+-	/*
+-	 * Use the dotted-quad IP address of the remote host as
+-	 * identifier. Linux statd always looks up the canonical
+-	 * hostname first for whatever remote hostname it receives,
+-	 * so this works alright.
+-	 */
+-	if (nsm_use_hostnames) {
+-		name = argp->mon_name;
+-	} else {
+-		sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr));
++	size_t len = strlen(string);
++
++	if (len > SM_MAXSTRLEN)
++		len = SM_MAXSTRLEN;
++	return xdr_encode_opaque(p, string, len);
++}
++
++/*
++ * "mon_name" specifies the host to be monitored.
++ *
++ * Linux uses a text version of the IP address of the remote
++ * host as the host identifier (the "mon_name" argument).
++ *
++ * Linux statd always looks up the canonical hostname first for
++ * whatever remote hostname it receives, so this works alright.
++ */
++static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp)
++{
++	char	buffer[XDR_ADDRBUF_LEN + 1];
++	char	*name = argp->mon_name;
++
++	if (!nsm_use_hostnames) {
++		snprintf(buffer, XDR_ADDRBUF_LEN,
++			 NIPQUAD_FMT, NIPQUAD(argp->addr));
+ 		name = buffer;
+ 	}
+-	if (!(p = xdr_encode_string(p, name))
+-	 || !(p = xdr_encode_string(p, utsname()->nodename)))
++
++	return xdr_encode_nsm_string(p, name);
++}
++
++/*
++ * The "my_id" argument specifies the hostname and RPC procedure
++ * to be called when the status manager receives notification
++ * (via the SM_NOTIFY call) that the state of host "mon_name"
++ * has changed.
++ */
++static __be32 *xdr_encode_my_id(__be32 *p, struct nsm_args *argp)
++{
++	p = xdr_encode_nsm_string(p, utsname()->nodename);
++	if (!p)
+ 		return ERR_PTR(-EIO);
++
+ 	*p++ = htonl(argp->prog);
+ 	*p++ = htonl(argp->vers);
+ 	*p++ = htonl(argp->proc);
+@@ -176,18 +205,48 @@ xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
+ 	return p;
+ }
+ 
+-static int
+-xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
++/*
++ * The "mon_id" argument specifies the non-private arguments
++ * of an SM_MON or SM_UNMON call.
++ */
++static __be32 *xdr_encode_mon_id(__be32 *p, struct nsm_args *argp)
+ {
+-	p = xdr_encode_common(rqstp, p, argp);
+-	if (IS_ERR(p))
+-		return PTR_ERR(p);
++	p = xdr_encode_mon_name(p, argp);
++	if (!p)
++		return ERR_PTR(-EIO);
+ 
+-	/* Surprise - there may even be room for an IPv6 address now */
++	return xdr_encode_my_id(p, argp);
++}
++
++/*
++ * The "priv" argument may contain private information required
++ * by the SM_MON call. This information will be supplied in the
++ * SM_NOTIFY call.
++ *
++ * Linux provides the raw IP address of the monitored host,
++ * left in network byte order.
++ */
++static __be32 *xdr_encode_priv(__be32 *p, struct nsm_args *argp)
++{
+ 	*p++ = argp->addr;
+ 	*p++ = 0;
+ 	*p++ = 0;
+ 	*p++ = 0;
++
++	return p;
++}
++
++static int
++xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
++{
++	p = xdr_encode_mon_id(p, argp);
++	if (IS_ERR(p))
++		return PTR_ERR(p);
++
++	p = xdr_encode_priv(p, argp);
++	if (IS_ERR(p))
++		return PTR_ERR(p);
++
+ 	rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
+ 	return 0;
+ }
+@@ -195,7 +254,7 @@ xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
+ static int
+ xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
+ {
+-	p = xdr_encode_common(rqstp, p, argp);
++	p = xdr_encode_mon_id(p, argp);
+ 	if (IS_ERR(p))
+ 		return PTR_ERR(p);
+ 	rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
+@@ -220,9 +279,11 @@ xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
+ }
+ 
+ #define SM_my_name_sz	(1+XDR_QUADLEN(SM_MAXSTRLEN))
+-#define SM_my_id_sz	(3+1+SM_my_name_sz)
+-#define SM_mon_id_sz	(1+XDR_QUADLEN(20)+SM_my_id_sz)
+-#define SM_mon_sz	(SM_mon_id_sz+4)
++#define SM_my_id_sz	(SM_my_name_sz+3)
++#define SM_mon_name_sz	(1+XDR_QUADLEN(SM_MAXSTRLEN))
++#define SM_mon_id_sz	(SM_mon_name_sz+SM_my_id_sz)
++#define SM_priv_sz	(XDR_QUADLEN(SM_PRIV_SIZE))
++#define SM_mon_sz	(SM_mon_id_sz+SM_priv_sz)
+ #define SM_monres_sz	2
+ #define SM_unmonres_sz	1
+ 
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index 1ed8bd4..2169af4 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -25,6 +25,7 @@
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+ #include <linux/mutex.h>
++#include <linux/kthread.h>
+ #include <linux/freezer.h>
+ 
+ #include <linux/sunrpc/types.h>
+@@ -48,14 +49,11 @@ EXPORT_SYMBOL(nlmsvc_ops);
+ 
+ static DEFINE_MUTEX(nlmsvc_mutex);
+ static unsigned int		nlmsvc_users;
+-static pid_t			nlmsvc_pid;
++static struct task_struct	*nlmsvc_task;
+ static struct svc_serv		*nlmsvc_serv;
+ int				nlmsvc_grace_period;
+ unsigned long			nlmsvc_timeout;
+ 
+-static DECLARE_COMPLETION(lockd_start_done);
+-static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
+-
+ /*
+  * These can be set at insmod time (useful for NFS as root filesystem),
+  * and also changed through the sysctl interface.  -- Jamie Lokier, Aug 2003
+@@ -74,7 +72,9 @@ static const unsigned long	nlm_timeout_min = 3;
+ static const unsigned long	nlm_timeout_max = 20;
+ static const int		nlm_port_min = 0, nlm_port_max = 65535;
+ 
++#ifdef CONFIG_SYSCTL
+ static struct ctl_table_header * nlm_sysctl_table;
++#endif
+ 
+ static unsigned long get_lockd_grace_period(void)
+ {
+@@ -111,35 +111,30 @@ static inline void clear_grace_period(void)
+ /*
+  * This is the lockd kernel thread
+  */
+-static void
+-lockd(struct svc_rqst *rqstp)
++static int
++lockd(void *vrqstp)
+ {
+-	int		err = 0;
++	int		err = 0, preverr = 0;
++	struct svc_rqst *rqstp = vrqstp;
+ 	unsigned long grace_period_expire;
+ 
+-	/* Lock module and set up kernel thread */
+-	/* lockd_up is waiting for us to startup, so will
+-	 * be holding a reference to this module, so it
+-	 * is safe to just claim another reference
+-	 */
+-	__module_get(THIS_MODULE);
+-	lock_kernel();
+-
+-	/*
+-	 * Let our maker know we're running.
+-	 */
+-	nlmsvc_pid = current->pid;
+-	nlmsvc_serv = rqstp->rq_server;
+-	complete(&lockd_start_done);
+-
+-	daemonize("lockd");
++	/* try_to_freeze() is called from svc_recv() */
+ 	set_freezable();
+ 
+-	/* Process request with signals blocked, but allow SIGKILL.  */
++	/* Allow SIGKILL to tell lockd to drop all of its locks */
+ 	allow_signal(SIGKILL);
+ 
+ 	dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
+ 
++	/*
++	 * FIXME: it would be nice if lockd didn't spend its entire life
++	 * running under the BKL. At the very least, it would be good to
++	 * have someone clarify what it's intended to protect here. I've
++	 * seen some handwavy posts about posix locking needing to be
++	 * done under the BKL, but it's far from clear.
++	 */
++	lock_kernel();
++
+ 	if (!nlm_timeout)
+ 		nlm_timeout = LOCKD_DFLT_TIMEO;
+ 	nlmsvc_timeout = nlm_timeout * HZ;
+@@ -148,10 +143,9 @@ lockd(struct svc_rqst *rqstp)
+ 
+ 	/*
+ 	 * The main request loop. We don't terminate until the last
+-	 * NFS mount or NFS daemon has gone away, and we've been sent a
+-	 * signal, or else another process has taken over our job.
++	 * NFS mount or NFS daemon has gone away.
+ 	 */
+-	while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
++	while (!kthread_should_stop()) {
+ 		long timeout = MAX_SCHEDULE_TIMEOUT;
+ 		RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
+ 
+@@ -161,6 +155,7 @@ lockd(struct svc_rqst *rqstp)
+ 				nlmsvc_invalidate_all();
+ 				grace_period_expire = set_grace_period();
+ 			}
++			continue;
+ 		}
+ 
+ 		/*
+@@ -179,14 +174,20 @@ lockd(struct svc_rqst *rqstp)
+ 		 * recvfrom routine.
+ 		 */
+ 		err = svc_recv(rqstp, timeout);
+-		if (err == -EAGAIN || err == -EINTR)
++		if (err == -EAGAIN || err == -EINTR) {
++			preverr = err;
+ 			continue;
++		}
+ 		if (err < 0) {
+-			printk(KERN_WARNING
+-			       "lockd: terminating on error %d\n",
+-			       -err);
+-			break;
++			if (err != preverr) {
++				printk(KERN_WARNING "%s: unexpected error "
++					"from svc_recv (%d)\n", __func__, err);
++				preverr = err;
++			}
++			schedule_timeout_interruptible(HZ);
++			continue;
+ 		}
++		preverr = err;
+ 
+ 		dprintk("lockd: request from %s\n",
+ 				svc_print_addr(rqstp, buf, sizeof(buf)));
+@@ -195,28 +196,19 @@ lockd(struct svc_rqst *rqstp)
+ 	}
+ 
+ 	flush_signals(current);
++	if (nlmsvc_ops)
++		nlmsvc_invalidate_all();
++	nlm_shutdown_hosts();
+ 
+-	/*
+-	 * Check whether there's a new lockd process before
+-	 * shutting down the hosts and clearing the slot.
+-	 */
+-	if (!nlmsvc_pid || current->pid == nlmsvc_pid) {
+-		if (nlmsvc_ops)
+-			nlmsvc_invalidate_all();
+-		nlm_shutdown_hosts();
+-		nlmsvc_pid = 0;
+-		nlmsvc_serv = NULL;
+-	} else
+-		printk(KERN_DEBUG
+-			"lockd: new process, skipping host shutdown\n");
+-	wake_up(&lockd_exit);
++	unlock_kernel();
++
++	nlmsvc_task = NULL;
++	nlmsvc_serv = NULL;
+ 
+ 	/* Exit the RPC thread */
+ 	svc_exit_thread(rqstp);
+ 
+-	/* Release module */
+-	unlock_kernel();
+-	module_put_and_exit(0);
++	return 0;
+ }
+ 
+ /*
+@@ -261,14 +253,15 @@ static int make_socks(struct svc_serv *serv, int proto)
+ int
+ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
+ {
+-	struct svc_serv *	serv;
+-	int			error = 0;
++	struct svc_serv *serv;
++	struct svc_rqst *rqstp;
++	int		error = 0;
+ 
+ 	mutex_lock(&nlmsvc_mutex);
+ 	/*
+ 	 * Check whether we're already up and running.
+ 	 */
+-	if (nlmsvc_pid) {
++	if (nlmsvc_serv) {
+ 		if (proto)
+ 			error = make_socks(nlmsvc_serv, proto);
+ 		goto out;
+@@ -295,13 +288,28 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
+ 	/*
+ 	 * Create the kernel thread and wait for it to start.
+ 	 */
+-	error = svc_create_thread(lockd, serv);
+-	if (error) {
++	rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
++	if (IS_ERR(rqstp)) {
++		error = PTR_ERR(rqstp);
++		printk(KERN_WARNING
++			"lockd_up: svc_rqst allocation failed, error=%d\n",
++			error);
++		goto destroy_and_out;
++	}
++
++	svc_sock_update_bufs(serv);
++	nlmsvc_serv = rqstp->rq_server;
++
++	nlmsvc_task = kthread_run(lockd, rqstp, serv->sv_name);
++	if (IS_ERR(nlmsvc_task)) {
++		error = PTR_ERR(nlmsvc_task);
++		nlmsvc_task = NULL;
++		nlmsvc_serv = NULL;
+ 		printk(KERN_WARNING
+-			"lockd_up: create thread failed, error=%d\n", error);
++			"lockd_up: kthread_run failed, error=%d\n", error);
++		svc_exit_thread(rqstp);
+ 		goto destroy_and_out;
+ 	}
+-	wait_for_completion(&lockd_start_done);
+ 
+ 	/*
+ 	 * Note: svc_serv structures have an initial use count of 1,
+@@ -323,42 +331,28 @@ EXPORT_SYMBOL(lockd_up);
+ void
+ lockd_down(void)
+ {
+-	static int warned;
+-
+ 	mutex_lock(&nlmsvc_mutex);
+ 	if (nlmsvc_users) {
+ 		if (--nlmsvc_users)
+ 			goto out;
+-	} else
+-		printk(KERN_WARNING "lockd_down: no users! pid=%d\n", nlmsvc_pid);
+-
+-	if (!nlmsvc_pid) {
+-		if (warned++ == 0)
+-			printk(KERN_WARNING "lockd_down: no lockd running.\n"); 
+-		goto out;
++	} else {
++		printk(KERN_ERR "lockd_down: no users! task=%p\n",
++			nlmsvc_task);
++		BUG();
+ 	}
+-	warned = 0;
+ 
+-	kill_proc(nlmsvc_pid, SIGKILL, 1);
+-	/*
+-	 * Wait for the lockd process to exit, but since we're holding
+-	 * the lockd semaphore, we can't wait around forever ...
+-	 */
+-	clear_thread_flag(TIF_SIGPENDING);
+-	interruptible_sleep_on_timeout(&lockd_exit, HZ);
+-	if (nlmsvc_pid) {
+-		printk(KERN_WARNING 
+-			"lockd_down: lockd failed to exit, clearing pid\n");
+-		nlmsvc_pid = 0;
++	if (!nlmsvc_task) {
++		printk(KERN_ERR "lockd_down: no lockd running.\n");
++		BUG();
+ 	}
+-	spin_lock_irq(&current->sighand->siglock);
+-	recalc_sigpending();
+-	spin_unlock_irq(&current->sighand->siglock);
++	kthread_stop(nlmsvc_task);
+ out:
+ 	mutex_unlock(&nlmsvc_mutex);
+ }
+ EXPORT_SYMBOL(lockd_down);
+ 
++#ifdef CONFIG_SYSCTL
++
+ /*
+  * Sysctl parameters (same as module parameters, different interface).
+  */
+@@ -443,6 +437,8 @@ static ctl_table nlm_sysctl_root[] = {
+ 	{ .ctl_name = 0 }
+ };
+ 
++#endif	/* CONFIG_SYSCTL */
++
+ /*
+  * Module (and sysfs) parameters.
+  */
+@@ -516,15 +512,21 @@ module_param(nsm_use_hostnames, bool, 0644);
+ 
+ static int __init init_nlm(void)
+ {
++#ifdef CONFIG_SYSCTL
+ 	nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
+ 	return nlm_sysctl_table ? 0 : -ENOMEM;
++#else
++	return 0;
++#endif
+ }
+ 
+ static void __exit exit_nlm(void)
+ {
+ 	/* FIXME: delete all NLM clients */
+ 	nlm_shutdown_hosts();
++#ifdef CONFIG_SYSCTL
+ 	unregister_sysctl_table(nlm_sysctl_table);
++#endif
+ }
+ 
+ module_init(init_nlm);
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index fe9bdb4..4d81553 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -29,6 +29,7 @@
+ #include <linux/sunrpc/svc.h>
+ #include <linux/lockd/nlm.h>
+ #include <linux/lockd/lockd.h>
++#include <linux/kthread.h>
+ 
+ #define NLMDBG_FACILITY		NLMDBG_SVCLOCK
+ 
+@@ -226,8 +227,7 @@ failed:
+ }
+ 
+ /*
+- * Delete a block. If the lock was cancelled or the grant callback
+- * failed, unlock is set to 1.
++ * Delete a block.
+  * It is the caller's responsibility to check whether the file
+  * can be closed hereafter.
+  */
+@@ -632,7 +632,7 @@ nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf,
+ 		block->b_flags |= B_TIMED_OUT;
+ 	if (conf) {
+ 		if (block->b_fl)
+-			locks_copy_lock(block->b_fl, conf);
++			__locks_copy_lock(block->b_fl, conf);
+ 	}
+ }
+ 
+@@ -887,7 +887,7 @@ nlmsvc_retry_blocked(void)
+ 	unsigned long	timeout = MAX_SCHEDULE_TIMEOUT;
+ 	struct nlm_block *block;
+ 
+-	while (!list_empty(&nlm_blocked)) {
++	while (!list_empty(&nlm_blocked) && !kthread_should_stop()) {
+ 		block = list_entry(nlm_blocked.next, struct nlm_block, b_list);
+ 
+ 		if (block->b_when == NLM_NEVER)
+diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c
+index 068886d..b0ae070 100644
+--- a/fs/lockd/svcshare.c
++++ b/fs/lockd/svcshare.c
+@@ -71,7 +71,8 @@ nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
+ 	struct nlm_share	*share, **shpp;
+ 	struct xdr_netobj	*oh = &argp->lock.oh;
+ 
+-	for (shpp = &file->f_shares; (share = *shpp) != 0; shpp = &share->s_next) {
++	for (shpp = &file->f_shares; (share = *shpp) != NULL;
++					shpp = &share->s_next) {
+ 		if (share->s_host == host && nlm_cmp_owner(share, oh)) {
+ 			*shpp = share->s_next;
+ 			kfree(share);
+diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
+index dbbefbc..d1c48b5 100644
+--- a/fs/lockd/svcsubs.c
++++ b/fs/lockd/svcsubs.c
+@@ -18,6 +18,8 @@
+ #include <linux/lockd/lockd.h>
+ #include <linux/lockd/share.h>
+ #include <linux/lockd/sm_inter.h>
++#include <linux/module.h>
++#include <linux/mount.h>
+ 
+ #define NLMDBG_FACILITY		NLMDBG_SVCSUBS
+ 
+@@ -194,6 +196,12 @@ again:
+ 	return 0;
+ }
+ 
++static int
++nlmsvc_always_match(void *dummy1, struct nlm_host *dummy2)
++{
++	return 1;
++}
++
+ /*
+  * Inspect a single file
+  */
+@@ -230,7 +238,8 @@ nlm_file_inuse(struct nlm_file *file)
+  * Loop over all files in the file table.
+  */
+ static int
+-nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
++nlm_traverse_files(void *data, nlm_host_match_fn_t match,
++		int (*is_failover_file)(void *data, struct nlm_file *file))
+ {
+ 	struct hlist_node *pos, *next;
+ 	struct nlm_file	*file;
+@@ -239,12 +248,14 @@ nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
+ 	mutex_lock(&nlm_file_mutex);
+ 	for (i = 0; i < FILE_NRHASH; i++) {
+ 		hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) {
++			if (is_failover_file && !is_failover_file(data, file))
++				continue;
+ 			file->f_count++;
+ 			mutex_unlock(&nlm_file_mutex);
+ 
+ 			/* Traverse locks, blocks and shares of this file
+ 			 * and update file->f_locks count */
+-			if (nlm_inspect_file(host, file, match))
++			if (nlm_inspect_file(data, file, match))
+ 				ret = 1;
+ 
+ 			mutex_lock(&nlm_file_mutex);
+@@ -303,21 +314,27 @@ nlm_release_file(struct nlm_file *file)
+  *	Used by nlmsvc_invalidate_all
+  */
+ static int
+-nlmsvc_mark_host(struct nlm_host *host, struct nlm_host *dummy)
++nlmsvc_mark_host(void *data, struct nlm_host *dummy)
+ {
++	struct nlm_host *host = data;
++
+ 	host->h_inuse = 1;
+ 	return 0;
+ }
+ 
+ static int
+-nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other)
++nlmsvc_same_host(void *data, struct nlm_host *other)
+ {
++	struct nlm_host *host = data;
++
+ 	return host == other;
+ }
+ 
+ static int
+-nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy)
++nlmsvc_is_client(void *data, struct nlm_host *dummy)
+ {
++	struct nlm_host *host = data;
++
+ 	if (host->h_server) {
+ 		/* we are destroying locks even though the client
+ 		 * hasn't asked us too, so don't unmonitor the
+@@ -337,7 +354,7 @@ void
+ nlmsvc_mark_resources(void)
+ {
+ 	dprintk("lockd: nlmsvc_mark_resources\n");
+-	nlm_traverse_files(NULL, nlmsvc_mark_host);
++	nlm_traverse_files(NULL, nlmsvc_mark_host, NULL);
+ }
+ 
+ /*
+@@ -348,7 +365,7 @@ nlmsvc_free_host_resources(struct nlm_host *host)
+ {
+ 	dprintk("lockd: nlmsvc_free_host_resources\n");
+ 
+-	if (nlm_traverse_files(host, nlmsvc_same_host)) {
++	if (nlm_traverse_files(host, nlmsvc_same_host, NULL)) {
+ 		printk(KERN_WARNING
+ 			"lockd: couldn't remove all locks held by %s\n",
+ 			host->h_name);
+@@ -368,5 +385,41 @@ nlmsvc_invalidate_all(void)
+ 	 * turn, which is about as inefficient as it gets.
+ 	 * Now we just do it once in nlm_traverse_files.
+ 	 */
+-	nlm_traverse_files(NULL, nlmsvc_is_client);
++	nlm_traverse_files(NULL, nlmsvc_is_client, NULL);
++}
++
++static int
++nlmsvc_match_sb(void *datap, struct nlm_file *file)
++{
++	struct super_block *sb = datap;
++
++	return sb == file->f_file->f_path.mnt->mnt_sb;
++}
++
++int
++nlmsvc_unlock_all_by_sb(struct super_block *sb)
++{
++	int ret;
++
++	ret = nlm_traverse_files(sb, nlmsvc_always_match, nlmsvc_match_sb);
++	return ret ? -EIO : 0;
++}
++EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
++
++static int
++nlmsvc_match_ip(void *datap, struct nlm_host *host)
++{
++	__be32 *server_addr = datap;
++
++	return host->h_saddr.sin_addr.s_addr == *server_addr;
++}
++
++int
++nlmsvc_unlock_all_by_ip(__be32 server_addr)
++{
++	int ret;
++	ret = nlm_traverse_files(&server_addr, nlmsvc_match_ip, NULL);
++	return ret ? -EIO : 0;
++
+ }
++EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_ip);
+diff --git a/fs/locks.c b/fs/locks.c
+index 43c0af2..44d9a6a 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -127,7 +127,6 @@
+ #include <linux/rcupdate.h>
+ #include <linux/pid_namespace.h>
+ 
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ #define IS_POSIX(fl)	(fl->fl_flags & FL_POSIX)
+@@ -225,7 +224,7 @@ static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
+ /*
+  * Initialize a new lock from an existing file_lock structure.
+  */
+-static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
++void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
+ {
+ 	new->fl_owner = fl->fl_owner;
+ 	new->fl_pid = fl->fl_pid;
+@@ -237,6 +236,7 @@ static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
+ 	new->fl_ops = NULL;
+ 	new->fl_lmops = NULL;
+ }
++EXPORT_SYMBOL(__locks_copy_lock);
+ 
+ void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
+ {
+@@ -834,7 +834,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
+ 			if (!posix_locks_conflict(request, fl))
+ 				continue;
+ 			if (conflock)
+-				locks_copy_lock(conflock, fl);
++				__locks_copy_lock(conflock, fl);
+ 			error = -EAGAIN;
+ 			if (!(request->fl_flags & FL_SLEEP))
+ 				goto out;
+@@ -1368,18 +1368,20 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
+ 
+ 	lease = *flp;
+ 
+-	error = -EAGAIN;
+-	if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+-		goto out;
+-	if ((arg == F_WRLCK)
+-	    && ((atomic_read(&dentry->d_count) > 1)
+-		|| (atomic_read(&inode->i_count) > 1)))
+-		goto out;
++	if (arg != F_UNLCK) {
++		error = -ENOMEM;
++		new_fl = locks_alloc_lock();
++		if (new_fl == NULL)
++			goto out;
+ 
+-	error = -ENOMEM;
+-	new_fl = locks_alloc_lock();
+-	if (new_fl == NULL)
+-		goto out;
++		error = -EAGAIN;
++		if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
++			goto out;
++		if ((arg == F_WRLCK)
++		    && ((atomic_read(&dentry->d_count) > 1)
++			|| (atomic_read(&inode->i_count) > 1)))
++			goto out;
++	}
+ 
+ 	/*
+ 	 * At this point, we know that if there is an exclusive
+@@ -1405,6 +1407,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
+ 			rdlease_count++;
+ 	}
+ 
++	error = -EAGAIN;
+ 	if ((arg == F_RDLCK && (wrlease_count > 0)) ||
+ 	    (arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0)))
+ 		goto out;
+@@ -1491,8 +1494,7 @@ EXPORT_SYMBOL_GPL(vfs_setlease);
+ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
+ {
+ 	struct file_lock fl, *flp = &fl;
+-	struct dentry *dentry = filp->f_path.dentry;
+-	struct inode *inode = dentry->d_inode;
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	int error;
+ 
+ 	locks_init_lock(&fl);
+diff --git a/fs/namei.c b/fs/namei.c
+index 8cf9bb9..e179f71 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1623,8 +1623,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
+ 			return -EACCES;
+ 
+ 		flag &= ~O_TRUNC;
+-	} else if (IS_RDONLY(inode) && (acc_mode & MAY_WRITE))
+-		return -EROFS;
++	}
+ 
+ 	error = vfs_permission(nd, acc_mode);
+ 	if (error)
+@@ -1677,7 +1676,12 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
+ 	return 0;
+ }
+ 
+-static int open_namei_create(struct nameidata *nd, struct path *path,
++/*
++ * Be careful about ever adding any more callers of this
++ * function.  Its flags must be in the namei format, not
++ * what get passed to sys_open().
++ */
++static int __open_namei_create(struct nameidata *nd, struct path *path,
+ 				int flag, int mode)
+ {
+ 	int error;
+@@ -1696,26 +1700,56 @@ static int open_namei_create(struct nameidata *nd, struct path *path,
+ }
+ 
+ /*
+- *	open_namei()
++ * Note that while the flag value (low two bits) for sys_open means:
++ *	00 - read-only
++ *	01 - write-only
++ *	10 - read-write
++ *	11 - special
++ * it is changed into
++ *	00 - no permissions needed
++ *	01 - read-permission
++ *	10 - write-permission
++ *	11 - read-write
++ * for the internal routines (ie open_namei()/follow_link() etc)
++ * This is more logical, and also allows the 00 "no perm needed"
++ * to be used for symlinks (where the permissions are checked
++ * later).
+  *
+- * namei for open - this is in fact almost the whole open-routine.
+- *
+- * Note that the low bits of "flag" aren't the same as in the open
+- * system call - they are 00 - no permissions needed
+- *			  01 - read permission needed
+- *			  10 - write permission needed
+- *			  11 - read/write permissions needed
+- * which is a lot more logical, and also allows the "no perm" needed
+- * for symlinks (where the permissions are checked later).
+- * SMP-safe
++*/
++static inline int open_to_namei_flags(int flag)
++{
++	if ((flag+1) & O_ACCMODE)
++		flag++;
++	return flag;
++}
++
++static int open_will_write_to_fs(int flag, struct inode *inode)
++{
++	/*
++	 * We'll never write to the fs underlying
++	 * a device file.
++	 */
++	if (special_file(inode->i_mode))
++		return 0;
++	return (flag & O_TRUNC);
++}
++
++/*
++ * Note that the low bits of the passed in "open_flag"
++ * are not the same as in the local variable "flag". See
++ * open_to_namei_flags() for more details.
+  */
+-int open_namei(int dfd, const char *pathname, int flag,
+-		int mode, struct nameidata *nd)
++struct file *do_filp_open(int dfd, const char *pathname,
++		int open_flag, int mode)
+ {
++	struct file *filp;
++	struct nameidata nd;
+ 	int acc_mode, error;
+ 	struct path path;
+ 	struct dentry *dir;
+ 	int count = 0;
++	int will_write;
++	int flag = open_to_namei_flags(open_flag);
+ 
+ 	acc_mode = ACC_MODE(flag);
+ 
+@@ -1733,18 +1767,19 @@ int open_namei(int dfd, const char *pathname, int flag,
+ 	 */
+ 	if (!(flag & O_CREAT)) {
+ 		error = path_lookup_open(dfd, pathname, lookup_flags(flag),
+-					 nd, flag);
++					 &nd, flag);
+ 		if (error)
+-			return error;
++			return ERR_PTR(error);
+ 		goto ok;
+ 	}
+ 
+ 	/*
+ 	 * Create - we need to know the parent.
+ 	 */
+-	error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
++	error = path_lookup_create(dfd, pathname, LOOKUP_PARENT,
++				   &nd, flag, mode);
+ 	if (error)
+-		return error;
++		return ERR_PTR(error);
+ 
+ 	/*
+ 	 * We have the parent and last component. First of all, check
+@@ -1752,14 +1787,14 @@ int open_namei(int dfd, const char *pathname, int flag,
+ 	 * will not do.
+ 	 */
+ 	error = -EISDIR;
+-	if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len])
++	if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len])
+ 		goto exit;
+ 
+-	dir = nd->path.dentry;
+-	nd->flags &= ~LOOKUP_PARENT;
++	dir = nd.path.dentry;
++	nd.flags &= ~LOOKUP_PARENT;
+ 	mutex_lock(&dir->d_inode->i_mutex);
+-	path.dentry = lookup_hash(nd);
+-	path.mnt = nd->path.mnt;
++	path.dentry = lookup_hash(&nd);
++	path.mnt = nd.path.mnt;
+ 
+ do_last:
+ 	error = PTR_ERR(path.dentry);
+@@ -1768,18 +1803,31 @@ do_last:
+ 		goto exit;
+ 	}
+ 
+-	if (IS_ERR(nd->intent.open.file)) {
+-		mutex_unlock(&dir->d_inode->i_mutex);
+-		error = PTR_ERR(nd->intent.open.file);
+-		goto exit_dput;
++	if (IS_ERR(nd.intent.open.file)) {
++		error = PTR_ERR(nd.intent.open.file);
++		goto exit_mutex_unlock;
+ 	}
+ 
+ 	/* Negative dentry, just create the file */
+ 	if (!path.dentry->d_inode) {
+-		error = open_namei_create(nd, &path, flag, mode);
++		/*
++		 * This write is needed to ensure that a
++		 * ro->rw transition does not occur between
++		 * the time when the file is created and when
++		 * a permanent write count is taken through
++		 * the 'struct file' in nameidata_to_filp().
++		 */
++		error = mnt_want_write(nd.path.mnt);
+ 		if (error)
++			goto exit_mutex_unlock;
++		error = __open_namei_create(&nd, &path, flag, mode);
++		if (error) {
++			mnt_drop_write(nd.path.mnt);
+ 			goto exit;
+-		return 0;
++		}
++		filp = nameidata_to_filp(&nd, open_flag);
++		mnt_drop_write(nd.path.mnt);
++		return filp;
+ 	}
+ 
+ 	/*
+@@ -1804,23 +1852,52 @@ do_last:
+ 	if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
+ 		goto do_link;
+ 
+-	path_to_nameidata(&path, nd);
++	path_to_nameidata(&path, &nd);
+ 	error = -EISDIR;
+ 	if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
+ 		goto exit;
+ ok:
+-	error = may_open(nd, acc_mode, flag);
+-	if (error)
++	/*
++	 * Consider:
++	 * 1. may_open() truncates a file
++	 * 2. a rw->ro mount transition occurs
++	 * 3. nameidata_to_filp() fails due to
++	 *    the ro mount.
++	 * That would be inconsistent, and should
++	 * be avoided. Taking this mnt write here
++	 * ensures that (2) can not occur.
++	 */
++	will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode);
++	if (will_write) {
++		error = mnt_want_write(nd.path.mnt);
++		if (error)
++			goto exit;
++	}
++	error = may_open(&nd, acc_mode, flag);
++	if (error) {
++		if (will_write)
++			mnt_drop_write(nd.path.mnt);
+ 		goto exit;
+-	return 0;
++	}
++	filp = nameidata_to_filp(&nd, open_flag);
++	/*
++	 * It is now safe to drop the mnt write
++	 * because the filp has had a write taken
++	 * on its behalf.
++	 */
++	if (will_write)
++		mnt_drop_write(nd.path.mnt);
++	return filp;
+ 
++exit_mutex_unlock:
++	mutex_unlock(&dir->d_inode->i_mutex);
+ exit_dput:
+-	path_put_conditional(&path, nd);
++	path_put_conditional(&path, &nd);
+ exit:
+-	if (!IS_ERR(nd->intent.open.file))
+-		release_open_intent(nd);
+-	path_put(&nd->path);
+-	return error;
++	if (!IS_ERR(nd.intent.open.file))
++		release_open_intent(&nd);
++	path_put(&nd.path);
++	return ERR_PTR(error);
+ 
+ do_link:
+ 	error = -ELOOP;
+@@ -1836,43 +1913,60 @@ do_link:
+ 	 * stored in nd->last.name and we will have to putname() it when we
+ 	 * are done. Procfs-like symlinks just set LAST_BIND.
+ 	 */
+-	nd->flags |= LOOKUP_PARENT;
+-	error = security_inode_follow_link(path.dentry, nd);
++	nd.flags |= LOOKUP_PARENT;
++	error = security_inode_follow_link(path.dentry, &nd);
+ 	if (error)
+ 		goto exit_dput;
+-	error = __do_follow_link(&path, nd);
++	error = __do_follow_link(&path, &nd);
+ 	if (error) {
+ 		/* Does someone understand code flow here? Or it is only
+ 		 * me so stupid? Anathema to whoever designed this non-sense
+ 		 * with "intent.open".
+ 		 */
+-		release_open_intent(nd);
+-		return error;
++		release_open_intent(&nd);
++		return ERR_PTR(error);
+ 	}
+-	nd->flags &= ~LOOKUP_PARENT;
+-	if (nd->last_type == LAST_BIND)
++	nd.flags &= ~LOOKUP_PARENT;
++	if (nd.last_type == LAST_BIND)
+ 		goto ok;
+ 	error = -EISDIR;
+-	if (nd->last_type != LAST_NORM)
++	if (nd.last_type != LAST_NORM)
+ 		goto exit;
+-	if (nd->last.name[nd->last.len]) {
+-		__putname(nd->last.name);
++	if (nd.last.name[nd.last.len]) {
++		__putname(nd.last.name);
+ 		goto exit;
+ 	}
+ 	error = -ELOOP;
+ 	if (count++==32) {
+-		__putname(nd->last.name);
++		__putname(nd.last.name);
+ 		goto exit;
+ 	}
+-	dir = nd->path.dentry;
++	dir = nd.path.dentry;
+ 	mutex_lock(&dir->d_inode->i_mutex);
+-	path.dentry = lookup_hash(nd);
+-	path.mnt = nd->path.mnt;
+-	__putname(nd->last.name);
++	path.dentry = lookup_hash(&nd);
++	path.mnt = nd.path.mnt;
++	__putname(nd.last.name);
+ 	goto do_last;
+ }
+ 
+ /**
++ * filp_open - open file and return file pointer
++ *
++ * @filename:	path to open
++ * @flags:	open flags as per the open(2) second argument
++ * @mode:	mode for the new file if O_CREAT is set, else ignored
++ *
++ * This is the helper to open a file from kernelspace if you really
++ * have to.  But in generally you should not do this, so please move
++ * along, nothing to see here..
++ */
++struct file *filp_open(const char *filename, int flags, int mode)
++{
++	return do_filp_open(AT_FDCWD, filename, flags, mode);
++}
++EXPORT_SYMBOL(filp_open);
++
++/**
+  * lookup_create - lookup a dentry, creating it if it doesn't exist
+  * @nd: nameidata info
+  * @is_dir: directory flag
+@@ -1945,6 +2039,23 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+ 	return error;
+ }
+ 
++static int may_mknod(mode_t mode)
++{
++	switch (mode & S_IFMT) {
++	case S_IFREG:
++	case S_IFCHR:
++	case S_IFBLK:
++	case S_IFIFO:
++	case S_IFSOCK:
++	case 0: /* zero mode translates to S_IFREG */
++		return 0;
++	case S_IFDIR:
++		return -EPERM;
++	default:
++		return -EINVAL;
++	}
++}
++
+ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
+ 				unsigned dev)
+ {
+@@ -1963,12 +2074,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
+ 	if (error)
+ 		goto out;
+ 	dentry = lookup_create(&nd, 0);
+-	error = PTR_ERR(dentry);
+-
++	if (IS_ERR(dentry)) {
++		error = PTR_ERR(dentry);
++		goto out_unlock;
++	}
+ 	if (!IS_POSIXACL(nd.path.dentry->d_inode))
+ 		mode &= ~current->fs->umask;
+-	if (!IS_ERR(dentry)) {
+-		switch (mode & S_IFMT) {
++	error = may_mknod(mode);
++	if (error)
++		goto out_dput;
++	error = mnt_want_write(nd.path.mnt);
++	if (error)
++		goto out_dput;
++	switch (mode & S_IFMT) {
+ 		case 0: case S_IFREG:
+ 			error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
+ 			break;
+@@ -1979,14 +2097,11 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
+ 		case S_IFIFO: case S_IFSOCK:
+ 			error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
+ 			break;
+-		case S_IFDIR:
+-			error = -EPERM;
+-			break;
+-		default:
+-			error = -EINVAL;
+-		}
+-		dput(dentry);
+ 	}
++	mnt_drop_write(nd.path.mnt);
++out_dput:
++	dput(dentry);
++out_unlock:
+ 	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+ 	path_put(&nd.path);
+ out:
+@@ -2044,7 +2159,12 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
+ 
+ 	if (!IS_POSIXACL(nd.path.dentry->d_inode))
+ 		mode &= ~current->fs->umask;
++	error = mnt_want_write(nd.path.mnt);
++	if (error)
++		goto out_dput;
+ 	error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
++	mnt_drop_write(nd.path.mnt);
++out_dput:
+ 	dput(dentry);
+ out_unlock:
+ 	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -2151,7 +2271,12 @@ static long do_rmdir(int dfd, const char __user *pathname)
+ 	error = PTR_ERR(dentry);
+ 	if (IS_ERR(dentry))
+ 		goto exit2;
++	error = mnt_want_write(nd.path.mnt);
++	if (error)
++		goto exit3;
+ 	error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
++	mnt_drop_write(nd.path.mnt);
++exit3:
+ 	dput(dentry);
+ exit2:
+ 	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -2232,7 +2357,11 @@ static long do_unlinkat(int dfd, const char __user *pathname)
+ 		inode = dentry->d_inode;
+ 		if (inode)
+ 			atomic_inc(&inode->i_count);
++		error = mnt_want_write(nd.path.mnt);
++		if (error)
++			goto exit2;
+ 		error = vfs_unlink(nd.path.dentry->d_inode, dentry);
++		mnt_drop_write(nd.path.mnt);
+ 	exit2:
+ 		dput(dentry);
+ 	}
+@@ -2313,7 +2442,12 @@ asmlinkage long sys_symlinkat(const char __user *oldname,
+ 	if (IS_ERR(dentry))
+ 		goto out_unlock;
+ 
++	error = mnt_want_write(nd.path.mnt);
++	if (error)
++		goto out_dput;
+ 	error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO);
++	mnt_drop_write(nd.path.mnt);
++out_dput:
+ 	dput(dentry);
+ out_unlock:
+ 	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -2408,7 +2542,12 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
+ 	error = PTR_ERR(new_dentry);
+ 	if (IS_ERR(new_dentry))
+ 		goto out_unlock;
++	error = mnt_want_write(nd.path.mnt);
++	if (error)
++		goto out_dput;
+ 	error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry);
++	mnt_drop_write(nd.path.mnt);
++out_dput:
+ 	dput(new_dentry);
+ out_unlock:
+ 	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -2634,8 +2773,12 @@ static int do_rename(int olddfd, const char *oldname,
+ 	if (new_dentry == trap)
+ 		goto exit5;
+ 
++	error = mnt_want_write(oldnd.path.mnt);
++	if (error)
++		goto exit5;
+ 	error = vfs_rename(old_dir->d_inode, old_dentry,
+ 				   new_dir->d_inode, new_dentry);
++	mnt_drop_write(oldnd.path.mnt);
+ exit5:
+ 	dput(new_dentry);
+ exit4:
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 94f026e..f48f981 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -17,6 +17,7 @@
+ #include <linux/quotaops.h>
+ #include <linux/acct.h>
+ #include <linux/capability.h>
++#include <linux/cpumask.h>
+ #include <linux/module.h>
+ #include <linux/sysfs.h>
+ #include <linux/seq_file.h>
+@@ -26,6 +27,7 @@
+ #include <linux/mount.h>
+ #include <linux/ramfs.h>
+ #include <linux/log2.h>
++#include <linux/idr.h>
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
+ #include "pnode.h"
+@@ -38,6 +40,8 @@
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
+ 
+ static int event;
++static DEFINE_IDA(mnt_id_ida);
++static DEFINE_IDA(mnt_group_ida);
+ 
+ static struct list_head *mount_hashtable __read_mostly;
+ static struct kmem_cache *mnt_cache __read_mostly;
+@@ -55,10 +59,65 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
+ 	return tmp & (HASH_SIZE - 1);
+ }
+ 
++#define MNT_WRITER_UNDERFLOW_LIMIT -(1<<16)
++
++/* allocation is serialized by namespace_sem */
++static int mnt_alloc_id(struct vfsmount *mnt)
++{
++	int res;
++
++retry:
++	ida_pre_get(&mnt_id_ida, GFP_KERNEL);
++	spin_lock(&vfsmount_lock);
++	res = ida_get_new(&mnt_id_ida, &mnt->mnt_id);
++	spin_unlock(&vfsmount_lock);
++	if (res == -EAGAIN)
++		goto retry;
++
++	return res;
++}
++
++static void mnt_free_id(struct vfsmount *mnt)
++{
++	spin_lock(&vfsmount_lock);
++	ida_remove(&mnt_id_ida, mnt->mnt_id);
++	spin_unlock(&vfsmount_lock);
++}
++
++/*
++ * Allocate a new peer group ID
++ *
++ * mnt_group_ida is protected by namespace_sem
++ */
++static int mnt_alloc_group_id(struct vfsmount *mnt)
++{
++	if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL))
++		return -ENOMEM;
++
++	return ida_get_new_above(&mnt_group_ida, 1, &mnt->mnt_group_id);
++}
++
++/*
++ * Release a peer group ID
++ */
++void mnt_release_group_id(struct vfsmount *mnt)
++{
++	ida_remove(&mnt_group_ida, mnt->mnt_group_id);
++	mnt->mnt_group_id = 0;
++}
++
+ struct vfsmount *alloc_vfsmnt(const char *name)
+ {
+ 	struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
+ 	if (mnt) {
++		int err;
++
++		err = mnt_alloc_id(mnt);
++		if (err) {
++			kmem_cache_free(mnt_cache, mnt);
++			return NULL;
++		}
++
+ 		atomic_set(&mnt->mnt_count, 1);
+ 		INIT_LIST_HEAD(&mnt->mnt_hash);
+ 		INIT_LIST_HEAD(&mnt->mnt_child);
+@@ -68,6 +127,7 @@ struct vfsmount *alloc_vfsmnt(const char *name)
+ 		INIT_LIST_HEAD(&mnt->mnt_share);
+ 		INIT_LIST_HEAD(&mnt->mnt_slave_list);
+ 		INIT_LIST_HEAD(&mnt->mnt_slave);
++		atomic_set(&mnt->__mnt_writers, 0);
+ 		if (name) {
+ 			int size = strlen(name) + 1;
+ 			char *newname = kmalloc(size, GFP_KERNEL);
+@@ -80,6 +140,263 @@ struct vfsmount *alloc_vfsmnt(const char *name)
+ 	return mnt;
+ }
+ 
++/*
++ * Most r/o checks on a fs are for operations that take
++ * discrete amounts of time, like a write() or unlink().
++ * We must keep track of when those operations start
++ * (for permission checks) and when they end, so that
++ * we can determine when writes are able to occur to
++ * a filesystem.
++ */
++/*
++ * __mnt_is_readonly: check whether a mount is read-only
++ * @mnt: the mount to check for its write status
++ *
++ * This shouldn't be used directly ouside of the VFS.
++ * It does not guarantee that the filesystem will stay
++ * r/w, just that it is right *now*.  This can not and
++ * should not be used in place of IS_RDONLY(inode).
++ * mnt_want/drop_write() will _keep_ the filesystem
++ * r/w.
++ */
++int __mnt_is_readonly(struct vfsmount *mnt)
++{
++	if (mnt->mnt_flags & MNT_READONLY)
++		return 1;
++	if (mnt->mnt_sb->s_flags & MS_RDONLY)
++		return 1;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(__mnt_is_readonly);
++
++struct mnt_writer {
++	/*
++	 * If holding multiple instances of this lock, they
++	 * must be ordered by cpu number.
++	 */
++	spinlock_t lock;
++	struct lock_class_key lock_class; /* compiles out with !lockdep */
++	unsigned long count;
++	struct vfsmount *mnt;
++} ____cacheline_aligned_in_smp;
++static DEFINE_PER_CPU(struct mnt_writer, mnt_writers);
++
++static int __init init_mnt_writers(void)
++{
++	int cpu;
++	for_each_possible_cpu(cpu) {
++		struct mnt_writer *writer = &per_cpu(mnt_writers, cpu);
++		spin_lock_init(&writer->lock);
++		lockdep_set_class(&writer->lock, &writer->lock_class);
++		writer->count = 0;
++	}
++	return 0;
++}
++fs_initcall(init_mnt_writers);
++
++static void unlock_mnt_writers(void)
++{
++	int cpu;
++	struct mnt_writer *cpu_writer;
++
++	for_each_possible_cpu(cpu) {
++		cpu_writer = &per_cpu(mnt_writers, cpu);
++		spin_unlock(&cpu_writer->lock);
++	}
++}
++
++static inline void __clear_mnt_count(struct mnt_writer *cpu_writer)
++{
++	if (!cpu_writer->mnt)
++		return;
++	/*
++	 * This is in case anyone ever leaves an invalid,
++	 * old ->mnt and a count of 0.
++	 */
++	if (!cpu_writer->count)
++		return;
++	atomic_add(cpu_writer->count, &cpu_writer->mnt->__mnt_writers);
++	cpu_writer->count = 0;
++}
++ /*
++ * must hold cpu_writer->lock
++ */
++static inline void use_cpu_writer_for_mount(struct mnt_writer *cpu_writer,
++					  struct vfsmount *mnt)
++{
++	if (cpu_writer->mnt == mnt)
++		return;
++	__clear_mnt_count(cpu_writer);
++	cpu_writer->mnt = mnt;
++}
++
++/*
++ * Most r/o checks on a fs are for operations that take
++ * discrete amounts of time, like a write() or unlink().
++ * We must keep track of when those operations start
++ * (for permission checks) and when they end, so that
++ * we can determine when writes are able to occur to
++ * a filesystem.
++ */
++/**
++ * mnt_want_write - get write access to a mount
++ * @mnt: the mount on which to take a write
++ *
++ * This tells the low-level filesystem that a write is
++ * about to be performed to it, and makes sure that
++ * writes are allowed before returning success.  When
++ * the write operation is finished, mnt_drop_write()
++ * must be called.  This is effectively a refcount.
++ */
++int mnt_want_write(struct vfsmount *mnt)
++{
++	int ret = 0;
++	struct mnt_writer *cpu_writer;
++
++	cpu_writer = &get_cpu_var(mnt_writers);
++	spin_lock(&cpu_writer->lock);
++	if (__mnt_is_readonly(mnt)) {
++		ret = -EROFS;
++		goto out;
++	}
++	use_cpu_writer_for_mount(cpu_writer, mnt);
++	cpu_writer->count++;
++out:
++	spin_unlock(&cpu_writer->lock);
++	put_cpu_var(mnt_writers);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(mnt_want_write);
++
++static void lock_mnt_writers(void)
++{
++	int cpu;
++	struct mnt_writer *cpu_writer;
++
++	for_each_possible_cpu(cpu) {
++		cpu_writer = &per_cpu(mnt_writers, cpu);
++		spin_lock(&cpu_writer->lock);
++		__clear_mnt_count(cpu_writer);
++		cpu_writer->mnt = NULL;
++	}
++}
++
++/*
++ * These per-cpu write counts are not guaranteed to have
++ * matched increments and decrements on any given cpu.
++ * A file open()ed for write on one cpu and close()d on
++ * another cpu will imbalance this count.  Make sure it
++ * does not get too far out of whack.
++ */
++static void handle_write_count_underflow(struct vfsmount *mnt)
++{
++	if (atomic_read(&mnt->__mnt_writers) >=
++	    MNT_WRITER_UNDERFLOW_LIMIT)
++		return;
++	/*
++	 * It isn't necessary to hold all of the locks
++	 * at the same time, but doing it this way makes
++	 * us share a lot more code.
++	 */
++	lock_mnt_writers();
++	/*
++	 * vfsmount_lock is for mnt_flags.
++	 */
++	spin_lock(&vfsmount_lock);
++	/*
++	 * If coalescing the per-cpu writer counts did not
++	 * get us back to a positive writer count, we have
++	 * a bug.
++	 */
++	if ((atomic_read(&mnt->__mnt_writers) < 0) &&
++	    !(mnt->mnt_flags & MNT_IMBALANCED_WRITE_COUNT)) {
++		printk(KERN_DEBUG "leak detected on mount(%p) writers "
++				"count: %d\n",
++			mnt, atomic_read(&mnt->__mnt_writers));
++		WARN_ON(1);
++		/* use the flag to keep the dmesg spam down */
++		mnt->mnt_flags |= MNT_IMBALANCED_WRITE_COUNT;
++	}
++	spin_unlock(&vfsmount_lock);
++	unlock_mnt_writers();
++}
++
++/**
++ * mnt_drop_write - give up write access to a mount
++ * @mnt: the mount on which to give up write access
++ *
++ * Tells the low-level filesystem that we are done
++ * performing writes to it.  Must be matched with
++ * mnt_want_write() call above.
++ */
++void mnt_drop_write(struct vfsmount *mnt)
++{
++	int must_check_underflow = 0;
++	struct mnt_writer *cpu_writer;
++
++	cpu_writer = &get_cpu_var(mnt_writers);
++	spin_lock(&cpu_writer->lock);
++
++	use_cpu_writer_for_mount(cpu_writer, mnt);
++	if (cpu_writer->count > 0) {
++		cpu_writer->count--;
++	} else {
++		must_check_underflow = 1;
++		atomic_dec(&mnt->__mnt_writers);
++	}
++
++	spin_unlock(&cpu_writer->lock);
++	/*
++	 * Logically, we could call this each time,
++	 * but the __mnt_writers cacheline tends to
++	 * be cold, and makes this expensive.
++	 */
++	if (must_check_underflow)
++		handle_write_count_underflow(mnt);
++	/*
++	 * This could be done right after the spinlock
++	 * is taken because the spinlock keeps us on
++	 * the cpu, and disables preemption.  However,
++	 * putting it here bounds the amount that
++	 * __mnt_writers can underflow.  Without it,
++	 * we could theoretically wrap __mnt_writers.
++	 */
++	put_cpu_var(mnt_writers);
++}
++EXPORT_SYMBOL_GPL(mnt_drop_write);
++
++static int mnt_make_readonly(struct vfsmount *mnt)
++{
++	int ret = 0;
++
++	lock_mnt_writers();
++	/*
++	 * With all the locks held, this value is stable
++	 */
++	if (atomic_read(&mnt->__mnt_writers) > 0) {
++		ret = -EBUSY;
++		goto out;
++	}
++	/*
++	 * nobody can do a successful mnt_want_write() with all
++	 * of the counts in MNT_DENIED_WRITE and the locks held.
++	 */
++	spin_lock(&vfsmount_lock);
++	if (!ret)
++		mnt->mnt_flags |= MNT_READONLY;
++	spin_unlock(&vfsmount_lock);
++out:
++	unlock_mnt_writers();
++	return ret;
++}
++
++static void __mnt_unmake_readonly(struct vfsmount *mnt)
++{
++	spin_lock(&vfsmount_lock);
++	mnt->mnt_flags &= ~MNT_READONLY;
++	spin_unlock(&vfsmount_lock);
++}
++
+ int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
+ {
+ 	mnt->mnt_sb = sb;
+@@ -92,6 +409,7 @@ EXPORT_SYMBOL(simple_set_mnt);
+ void free_vfsmnt(struct vfsmount *mnt)
+ {
+ 	kfree(mnt->mnt_devname);
++	mnt_free_id(mnt);
+ 	kmem_cache_free(mnt_cache, mnt);
+ }
+ 
+@@ -238,6 +556,17 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
+ 	struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname);
+ 
+ 	if (mnt) {
++		if (flag & (CL_SLAVE | CL_PRIVATE))
++			mnt->mnt_group_id = 0; /* not a peer of original */
++		else
++			mnt->mnt_group_id = old->mnt_group_id;
++
++		if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) {
++			int err = mnt_alloc_group_id(mnt);
++			if (err)
++				goto out_free;
++		}
++
+ 		mnt->mnt_flags = old->mnt_flags;
+ 		atomic_inc(&sb->s_active);
+ 		mnt->mnt_sb = sb;
+@@ -267,11 +596,44 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
+ 		}
+ 	}
+ 	return mnt;
++
++ out_free:
++	free_vfsmnt(mnt);
++	return NULL;
+ }
+ 
+ static inline void __mntput(struct vfsmount *mnt)
+ {
++	int cpu;
+ 	struct super_block *sb = mnt->mnt_sb;
++	/*
++	 * We don't have to hold all of the locks at the
++	 * same time here because we know that we're the
++	 * last reference to mnt and that no new writers
++	 * can come in.
++	 */
++	for_each_possible_cpu(cpu) {
++		struct mnt_writer *cpu_writer = &per_cpu(mnt_writers, cpu);
++		if (cpu_writer->mnt != mnt)
++			continue;
++		spin_lock(&cpu_writer->lock);
++		atomic_add(cpu_writer->count, &mnt->__mnt_writers);
++		cpu_writer->count = 0;
++		/*
++		 * Might as well do this so that no one
++		 * ever sees the pointer and expects
++		 * it to be valid.
++		 */
++		cpu_writer->mnt = NULL;
++		spin_unlock(&cpu_writer->lock);
++	}
++	/*
++	 * This probably indicates that somebody messed
++	 * up a mnt_want/drop_write() pair.  If this
++	 * happens, the filesystem was probably unable
++	 * to make r/w->r/o transitions.
++	 */
++	WARN_ON(atomic_read(&mnt->__mnt_writers));
+ 	dput(mnt->mnt_root);
+ 	free_vfsmnt(mnt);
+ 	deactivate_super(sb);
+@@ -362,20 +724,21 @@ void save_mount_options(struct super_block *sb, char *options)
+ }
+ EXPORT_SYMBOL(save_mount_options);
+ 
++#ifdef CONFIG_PROC_FS
+ /* iterator */
+ static void *m_start(struct seq_file *m, loff_t *pos)
+ {
+-	struct mnt_namespace *n = m->private;
++	struct proc_mounts *p = m->private;
+ 
+ 	down_read(&namespace_sem);
+-	return seq_list_start(&n->list, *pos);
++	return seq_list_start(&p->ns->list, *pos);
+ }
+ 
+ static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+ {
+-	struct mnt_namespace *n = m->private;
++	struct proc_mounts *p = m->private;
+ 
+-	return seq_list_next(v, &n->list, pos);
++	return seq_list_next(v, &p->ns->list, pos);
+ }
+ 
+ static void m_stop(struct seq_file *m, void *v)
+@@ -383,20 +746,30 @@ static void m_stop(struct seq_file *m, void *v)
+ 	up_read(&namespace_sem);
+ }
+ 
+-static int show_vfsmnt(struct seq_file *m, void *v)
++struct proc_fs_info {
++	int flag;
++	const char *str;
++};
++
++static void show_sb_opts(struct seq_file *m, struct super_block *sb)
+ {
+-	struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
+-	int err = 0;
+-	static struct proc_fs_info {
+-		int flag;
+-		char *str;
+-	} fs_info[] = {
++	static const struct proc_fs_info fs_info[] = {
+ 		{ MS_SYNCHRONOUS, ",sync" },
+ 		{ MS_DIRSYNC, ",dirsync" },
+ 		{ MS_MANDLOCK, ",mand" },
+ 		{ 0, NULL }
+ 	};
+-	static struct proc_fs_info mnt_info[] = {
++	const struct proc_fs_info *fs_infop;
++
++	for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
++		if (sb->s_flags & fs_infop->flag)
++			seq_puts(m, fs_infop->str);
++	}
++}
++
++static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt)
++{
++	static const struct proc_fs_info mnt_info[] = {
+ 		{ MNT_NOSUID, ",nosuid" },
+ 		{ MNT_NODEV, ",nodev" },
+ 		{ MNT_NOEXEC, ",noexec" },
+@@ -405,40 +778,108 @@ static int show_vfsmnt(struct seq_file *m, void *v)
+ 		{ MNT_RELATIME, ",relatime" },
+ 		{ 0, NULL }
+ 	};
+-	struct proc_fs_info *fs_infop;
++	const struct proc_fs_info *fs_infop;
++
++	for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) {
++		if (mnt->mnt_flags & fs_infop->flag)
++			seq_puts(m, fs_infop->str);
++	}
++}
++
++static void show_type(struct seq_file *m, struct super_block *sb)
++{
++	mangle(m, sb->s_type->name);
++	if (sb->s_subtype && sb->s_subtype[0]) {
++		seq_putc(m, '.');
++		mangle(m, sb->s_subtype);
++	}
++}
++
++static int show_vfsmnt(struct seq_file *m, void *v)
++{
++	struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
++	int err = 0;
+ 	struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
+ 
+ 	mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+ 	seq_putc(m, ' ');
+ 	seq_path(m, &mnt_path, " \t\n\\");
+ 	seq_putc(m, ' ');
+-	mangle(m, mnt->mnt_sb->s_type->name);
+-	if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) {
+-		seq_putc(m, '.');
+-		mangle(m, mnt->mnt_sb->s_subtype);
+-	}
+-	seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
+-	for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
+-		if (mnt->mnt_sb->s_flags & fs_infop->flag)
+-			seq_puts(m, fs_infop->str);
+-	}
+-	for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) {
+-		if (mnt->mnt_flags & fs_infop->flag)
+-			seq_puts(m, fs_infop->str);
+-	}
++	show_type(m, mnt->mnt_sb);
++	seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
++	show_sb_opts(m, mnt->mnt_sb);
++	show_mnt_opts(m, mnt);
+ 	if (mnt->mnt_sb->s_op->show_options)
+ 		err = mnt->mnt_sb->s_op->show_options(m, mnt);
+ 	seq_puts(m, " 0 0\n");
+ 	return err;
+ }
+ 
+-struct seq_operations mounts_op = {
++const struct seq_operations mounts_op = {
+ 	.start	= m_start,
+ 	.next	= m_next,
+ 	.stop	= m_stop,
+ 	.show	= show_vfsmnt
+ };
+ 
++static int show_mountinfo(struct seq_file *m, void *v)
++{
++	struct proc_mounts *p = m->private;
++	struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
++	struct super_block *sb = mnt->mnt_sb;
++	struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
++	struct path root = p->root;
++	int err = 0;
++
++	seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id,
++		   MAJOR(sb->s_dev), MINOR(sb->s_dev));
++	seq_dentry(m, mnt->mnt_root, " \t\n\\");
++	seq_putc(m, ' ');
++	seq_path_root(m, &mnt_path, &root, " \t\n\\");
++	if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) {
++		/*
++		 * Mountpoint is outside root, discard that one.  Ugly,
++		 * but less so than trying to do that in iterator in a
++		 * race-free way (due to renames).
++		 */
++		return SEQ_SKIP;
++	}
++	seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw");
++	show_mnt_opts(m, mnt);
++
++	/* Tagged fields ("foo:X" or "bar") */
++	if (IS_MNT_SHARED(mnt))
++		seq_printf(m, " shared:%i", mnt->mnt_group_id);
++	if (IS_MNT_SLAVE(mnt)) {
++		int master = mnt->mnt_master->mnt_group_id;
++		int dom = get_dominating_id(mnt, &p->root);
++		seq_printf(m, " master:%i", master);
++		if (dom && dom != master)
++			seq_printf(m, " propagate_from:%i", dom);
++	}
++	if (IS_MNT_UNBINDABLE(mnt))
++		seq_puts(m, " unbindable");
++
++	/* Filesystem specific data */
++	seq_puts(m, " - ");
++	show_type(m, sb);
++	seq_putc(m, ' ');
++	mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
++	seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw");
++	show_sb_opts(m, sb);
++	if (sb->s_op->show_options)
++		err = sb->s_op->show_options(m, mnt);
++	seq_putc(m, '\n');
++	return err;
++}
++
++const struct seq_operations mountinfo_op = {
++	.start	= m_start,
++	.next	= m_next,
++	.stop	= m_stop,
++	.show	= show_mountinfo,
++};
++
+ static int show_vfsstat(struct seq_file *m, void *v)
+ {
+ 	struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
+@@ -459,7 +900,7 @@ static int show_vfsstat(struct seq_file *m, void *v)
+ 
+ 	/* file system type */
+ 	seq_puts(m, "with fstype ");
+-	mangle(m, mnt->mnt_sb->s_type->name);
++	show_type(m, mnt->mnt_sb);
+ 
+ 	/* optional statistics */
+ 	if (mnt->mnt_sb->s_op->show_stats) {
+@@ -471,12 +912,13 @@ static int show_vfsstat(struct seq_file *m, void *v)
+ 	return err;
+ }
+ 
+-struct seq_operations mountstats_op = {
++const struct seq_operations mountstats_op = {
+ 	.start	= m_start,
+ 	.next	= m_next,
+ 	.stop	= m_stop,
+ 	.show	= show_vfsstat,
+ };
++#endif  /* CONFIG_PROC_FS */
+ 
+ /**
+  * may_umount_tree - check if a mount tree is busy
+@@ -619,10 +1061,11 @@ static int do_umount(struct vfsmount *mnt, int flags)
+ 	 * about for the moment.
+ 	 */
+ 
+-	lock_kernel();
+-	if (sb->s_op->umount_begin)
+-		sb->s_op->umount_begin(mnt, flags);
+-	unlock_kernel();
++	if (flags & MNT_FORCE && sb->s_op->umount_begin) {
++		lock_kernel();
++		sb->s_op->umount_begin(sb);
++		unlock_kernel();
++	}
+ 
+ 	/*
+ 	 * No sense to grab the lock for this test, but test itself looks
+@@ -801,23 +1244,50 @@ Enomem:
+ struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry)
+ {
+ 	struct vfsmount *tree;
+-	down_read(&namespace_sem);
++	down_write(&namespace_sem);
+ 	tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE);
+-	up_read(&namespace_sem);
++	up_write(&namespace_sem);
+ 	return tree;
+ }
+ 
+ void drop_collected_mounts(struct vfsmount *mnt)
+ {
+ 	LIST_HEAD(umount_list);
+-	down_read(&namespace_sem);
++	down_write(&namespace_sem);
+ 	spin_lock(&vfsmount_lock);
+ 	umount_tree(mnt, 0, &umount_list);
+ 	spin_unlock(&vfsmount_lock);
+-	up_read(&namespace_sem);
++	up_write(&namespace_sem);
+ 	release_mounts(&umount_list);
+ }
+ 
++static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
++{
++	struct vfsmount *p;
++
++	for (p = mnt; p != end; p = next_mnt(p, mnt)) {
++		if (p->mnt_group_id && !IS_MNT_SHARED(p))
++			mnt_release_group_id(p);
++	}
++}
++
++static int invent_group_ids(struct vfsmount *mnt, bool recurse)
++{
++	struct vfsmount *p;
++
++	for (p = mnt; p; p = recurse ? next_mnt(p, mnt) : NULL) {
++		if (!p->mnt_group_id && !IS_MNT_SHARED(p)) {
++			int err = mnt_alloc_group_id(p);
++			if (err) {
++				cleanup_group_ids(mnt, p);
++				return err;
++			}
++		}
++	}
++
++	return 0;
++}
++
+ /*
+  *  @source_mnt : mount tree to be attached
+  *  @nd         : place the mount tree @source_mnt is attached
+@@ -888,9 +1358,16 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
+ 	struct vfsmount *dest_mnt = path->mnt;
+ 	struct dentry *dest_dentry = path->dentry;
+ 	struct vfsmount *child, *p;
++	int err;
+ 
+-	if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list))
+-		return -EINVAL;
++	if (IS_MNT_SHARED(dest_mnt)) {
++		err = invent_group_ids(source_mnt, true);
++		if (err)
++			goto out;
++	}
++	err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list);
++	if (err)
++		goto out_cleanup_ids;
+ 
+ 	if (IS_MNT_SHARED(dest_mnt)) {
+ 		for (p = source_mnt; p; p = next_mnt(p, source_mnt))
+@@ -913,34 +1390,40 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
+ 	}
+ 	spin_unlock(&vfsmount_lock);
+ 	return 0;
++
++ out_cleanup_ids:
++	if (IS_MNT_SHARED(dest_mnt))
++		cleanup_group_ids(source_mnt, NULL);
++ out:
++	return err;
+ }
+ 
+-static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
++static int graft_tree(struct vfsmount *mnt, struct path *path)
+ {
+ 	int err;
+ 	if (mnt->mnt_sb->s_flags & MS_NOUSER)
+ 		return -EINVAL;
+ 
+-	if (S_ISDIR(nd->path.dentry->d_inode->i_mode) !=
++	if (S_ISDIR(path->dentry->d_inode->i_mode) !=
+ 	      S_ISDIR(mnt->mnt_root->d_inode->i_mode))
+ 		return -ENOTDIR;
+ 
+ 	err = -ENOENT;
+-	mutex_lock(&nd->path.dentry->d_inode->i_mutex);
+-	if (IS_DEADDIR(nd->path.dentry->d_inode))
++	mutex_lock(&path->dentry->d_inode->i_mutex);
++	if (IS_DEADDIR(path->dentry->d_inode))
+ 		goto out_unlock;
+ 
+-	err = security_sb_check_sb(mnt, nd);
++	err = security_sb_check_sb(mnt, path);
+ 	if (err)
+ 		goto out_unlock;
+ 
+ 	err = -ENOENT;
+-	if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry))
+-		err = attach_recursive_mnt(mnt, &nd->path, NULL);
++	if (IS_ROOT(path->dentry) || !d_unhashed(path->dentry))
++		err = attach_recursive_mnt(mnt, path, NULL);
+ out_unlock:
+-	mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
++	mutex_unlock(&path->dentry->d_inode->i_mutex);
+ 	if (!err)
+-		security_sb_post_addmount(mnt, nd);
++		security_sb_post_addmount(mnt, path);
+ 	return err;
+ }
+ 
+@@ -953,6 +1436,7 @@ static noinline int do_change_type(struct nameidata *nd, int flag)
+ 	struct vfsmount *m, *mnt = nd->path.mnt;
+ 	int recurse = flag & MS_REC;
+ 	int type = flag & ~MS_REC;
++	int err = 0;
+ 
+ 	if (!capable(CAP_SYS_ADMIN))
+ 		return -EPERM;
+@@ -961,12 +1445,20 @@ static noinline int do_change_type(struct nameidata *nd, int flag)
+ 		return -EINVAL;
+ 
+ 	down_write(&namespace_sem);
++	if (type == MS_SHARED) {
++		err = invent_group_ids(mnt, recurse);
++		if (err)
++			goto out_unlock;
++	}
++
+ 	spin_lock(&vfsmount_lock);
+ 	for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
+ 		change_mnt_propagation(m, type);
+ 	spin_unlock(&vfsmount_lock);
++
++ out_unlock:
+ 	up_write(&namespace_sem);
+-	return 0;
++	return err;
+ }
+ 
+ /*
+@@ -1004,7 +1496,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name,
+ 	if (!mnt)
+ 		goto out;
+ 
+-	err = graft_tree(mnt, nd);
++	err = graft_tree(mnt, &nd->path);
+ 	if (err) {
+ 		LIST_HEAD(umount_list);
+ 		spin_lock(&vfsmount_lock);
+@@ -1019,6 +1511,23 @@ out:
+ 	return err;
+ }
+ 
++static int change_mount_flags(struct vfsmount *mnt, int ms_flags)
++{
++	int error = 0;
++	int readonly_request = 0;
++
++	if (ms_flags & MS_RDONLY)
++		readonly_request = 1;
++	if (readonly_request == __mnt_is_readonly(mnt))
++		return 0;
++
++	if (readonly_request)
++		error = mnt_make_readonly(mnt);
++	else
++		__mnt_unmake_readonly(mnt);
++	return error;
++}
++
+ /*
+  * change filesystem flags. dir should be a physical root of filesystem.
+  * If you've mounted a non-root directory somewhere and want to do remount
+@@ -1041,7 +1550,10 @@ static noinline int do_remount(struct nameidata *nd, int flags, int mnt_flags,
+ 		return -EINVAL;
+ 
+ 	down_write(&sb->s_umount);
+-	err = do_remount_sb(sb, flags, data, 0);
++	if (flags & MS_BIND)
++		err = change_mount_flags(nd->path.mnt, flags);
++	else
++		err = do_remount_sb(sb, flags, data, 0);
+ 	if (!err)
+ 		nd->path.mnt->mnt_flags = mnt_flags;
+ 	up_write(&sb->s_umount);
+@@ -1191,7 +1703,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
+ 		goto unlock;
+ 
+ 	newmnt->mnt_flags = mnt_flags;
+-	if ((err = graft_tree(newmnt, nd)))
++	if ((err = graft_tree(newmnt, &nd->path)))
+ 		goto unlock;
+ 
+ 	if (fslist) /* add to the specified expiration list */
+@@ -1425,6 +1937,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
+ 		mnt_flags |= MNT_NODIRATIME;
+ 	if (flags & MS_RELATIME)
+ 		mnt_flags |= MNT_RELATIME;
++	if (flags & MS_RDONLY)
++		mnt_flags |= MNT_READONLY;
+ 
+ 	flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
+ 		   MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT);
+@@ -1434,7 +1948,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
+ 	if (retval)
+ 		return retval;
+ 
+-	retval = security_sb_mount(dev_name, &nd, type_page, flags, data_page);
++	retval = security_sb_mount(dev_name, &nd.path,
++				   type_page, flags, data_page);
+ 	if (retval)
+ 		goto dput_out;
+ 
+@@ -1674,15 +2189,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ 			       const char __user * put_old)
+ {
+ 	struct vfsmount *tmp;
+-	struct nameidata new_nd, old_nd, user_nd;
+-	struct path parent_path, root_parent;
++	struct nameidata new_nd, old_nd;
++	struct path parent_path, root_parent, root;
+ 	int error;
+ 
+ 	if (!capable(CAP_SYS_ADMIN))
+ 		return -EPERM;
+ 
+-	lock_kernel();
+-
+ 	error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
+ 			    &new_nd);
+ 	if (error)
+@@ -1695,14 +2208,14 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ 	if (error)
+ 		goto out1;
+ 
+-	error = security_sb_pivotroot(&old_nd, &new_nd);
++	error = security_sb_pivotroot(&old_nd.path, &new_nd.path);
+ 	if (error) {
+ 		path_put(&old_nd.path);
+ 		goto out1;
+ 	}
+ 
+ 	read_lock(&current->fs->lock);
+-	user_nd.path = current->fs->root;
++	root = current->fs->root;
+ 	path_get(&current->fs->root);
+ 	read_unlock(&current->fs->lock);
+ 	down_write(&namespace_sem);
+@@ -1710,9 +2223,9 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ 	error = -EINVAL;
+ 	if (IS_MNT_SHARED(old_nd.path.mnt) ||
+ 		IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) ||
+-		IS_MNT_SHARED(user_nd.path.mnt->mnt_parent))
++		IS_MNT_SHARED(root.mnt->mnt_parent))
+ 		goto out2;
+-	if (!check_mnt(user_nd.path.mnt))
++	if (!check_mnt(root.mnt))
+ 		goto out2;
+ 	error = -ENOENT;
+ 	if (IS_DEADDIR(new_nd.path.dentry->d_inode))
+@@ -1722,13 +2235,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ 	if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry))
+ 		goto out2;
+ 	error = -EBUSY;
+-	if (new_nd.path.mnt == user_nd.path.mnt ||
+-	    old_nd.path.mnt == user_nd.path.mnt)
++	if (new_nd.path.mnt == root.mnt ||
++	    old_nd.path.mnt == root.mnt)
+ 		goto out2; /* loop, on the same file system  */
+ 	error = -EINVAL;
+-	if (user_nd.path.mnt->mnt_root != user_nd.path.dentry)
++	if (root.mnt->mnt_root != root.dentry)
+ 		goto out2; /* not a mountpoint */
+-	if (user_nd.path.mnt->mnt_parent == user_nd.path.mnt)
++	if (root.mnt->mnt_parent == root.mnt)
+ 		goto out2; /* not attached */
+ 	if (new_nd.path.mnt->mnt_root != new_nd.path.dentry)
+ 		goto out2; /* not a mountpoint */
+@@ -1750,27 +2263,26 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ 	} else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry))
+ 		goto out3;
+ 	detach_mnt(new_nd.path.mnt, &parent_path);
+-	detach_mnt(user_nd.path.mnt, &root_parent);
++	detach_mnt(root.mnt, &root_parent);
+ 	/* mount old root on put_old */
+-	attach_mnt(user_nd.path.mnt, &old_nd.path);
++	attach_mnt(root.mnt, &old_nd.path);
+ 	/* mount new_root on / */
+ 	attach_mnt(new_nd.path.mnt, &root_parent);
+ 	touch_mnt_namespace(current->nsproxy->mnt_ns);
+ 	spin_unlock(&vfsmount_lock);
+-	chroot_fs_refs(&user_nd.path, &new_nd.path);
+-	security_sb_post_pivotroot(&user_nd, &new_nd);
++	chroot_fs_refs(&root, &new_nd.path);
++	security_sb_post_pivotroot(&root, &new_nd.path);
+ 	error = 0;
+ 	path_put(&root_parent);
+ 	path_put(&parent_path);
+ out2:
+ 	mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex);
+ 	up_write(&namespace_sem);
+-	path_put(&user_nd.path);
++	path_put(&root);
+ 	path_put(&old_nd.path);
+ out1:
+ 	path_put(&new_nd.path);
+ out0:
+-	unlock_kernel();
+ 	return error;
+ out3:
+ 	spin_unlock(&vfsmount_lock);
+diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
+index c67b4bd..ad8f167 100644
+--- a/fs/ncpfs/ioctl.c
++++ b/fs/ncpfs/ioctl.c
+@@ -14,6 +14,7 @@
+ #include <linux/ioctl.h>
+ #include <linux/time.h>
+ #include <linux/mm.h>
++#include <linux/mount.h>
+ #include <linux/highuid.h>
+ #include <linux/smp_lock.h>
+ #include <linux/vmalloc.h>
+@@ -261,7 +262,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
+ }
+ #endif /* CONFIG_NCPFS_NLS */
+ 
+-int ncp_ioctl(struct inode *inode, struct file *filp,
++static int __ncp_ioctl(struct inode *inode, struct file *filp,
+ 	      unsigned int cmd, unsigned long arg)
+ {
+ 	struct ncp_server *server = NCP_SERVER(inode);
+@@ -822,6 +823,57 @@ outrel:
+ 	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:
++		/* unkown IOCTL command, assume write */
++		return 1;
++	}
++}
++
++int ncp_ioctl(struct inode *inode, struct file *filp,
++	      unsigned int cmd, unsigned long arg)
++{
++	int ret;
++
++	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))
++			return -EACCES;
++	}
++	ret = __ncp_ioctl(inode, filp, cmd, arg);
++	if (ncp_ioctl_need_write(cmd))
++		mnt_drop_write(filp->f_path.mnt);
++	return ret;
++}
++
+ #ifdef CONFIG_COMPAT
+ long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
+index df0f41e..ac6170c 100644
+--- a/fs/nfs/Makefile
++++ b/fs/nfs/Makefile
+@@ -5,7 +5,7 @@
+ obj-$(CONFIG_NFS_FS) += nfs.o
+ 
+ nfs-y 			:= client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
+-			   pagelist.o proc.o read.o symlink.o unlink.o \
++			   direct.o pagelist.o proc.o read.o symlink.o unlink.o \
+ 			   write.o namespace.o mount_clnt.o
+ nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o
+ nfs-$(CONFIG_NFS_V3)	+= nfs3proc.o nfs3xdr.o
+@@ -14,5 +14,4 @@ nfs-$(CONFIG_NFS_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
+ 			   delegation.o idmap.o \
+ 			   callback.o callback_xdr.o callback_proc.o \
+ 			   nfs4namespace.o
+-nfs-$(CONFIG_NFS_DIRECTIO) += direct.o
+ nfs-$(CONFIG_SYSCTL) += sysctl.o
+diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
+index 66648dd..5606ae3 100644
+--- a/fs/nfs/callback.c
++++ b/fs/nfs/callback.c
+@@ -15,6 +15,7 @@
+ #include <linux/nfs_fs.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
++#include <linux/kthread.h>
+ 
+ #include <net/inet_sock.h>
+ 
+@@ -27,9 +28,7 @@
+ struct nfs_callback_data {
+ 	unsigned int users;
+ 	struct svc_serv *serv;
+-	pid_t pid;
+-	struct completion started;
+-	struct completion stopped;
++	struct task_struct *task;
+ };
+ 
+ static struct nfs_callback_data nfs_callback_info;
+@@ -57,48 +56,44 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
+ /*
+  * This is the callback kernel thread.
+  */
+-static void nfs_callback_svc(struct svc_rqst *rqstp)
++static int
++nfs_callback_svc(void *vrqstp)
+ {
+-	int err;
++	int err, preverr = 0;
++	struct svc_rqst *rqstp = vrqstp;
+ 
+-	__module_get(THIS_MODULE);
+-	lock_kernel();
+-
+-	nfs_callback_info.pid = current->pid;
+-	daemonize("nfsv4-svc");
+-	/* Process request with signals blocked, but allow SIGKILL.  */
+-	allow_signal(SIGKILL);
+ 	set_freezable();
+ 
+-	complete(&nfs_callback_info.started);
+-
+-	for(;;) {
+-		if (signalled()) {
+-			if (nfs_callback_info.users == 0)
+-				break;
+-			flush_signals(current);
+-		}
++	/*
++	 * FIXME: do we really need to run this under the BKL? If so, please
++	 * add a comment about what it's intended to protect.
++	 */
++	lock_kernel();
++	while (!kthread_should_stop()) {
+ 		/*
+ 		 * Listen for a request on the socket
+ 		 */
+ 		err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
+-		if (err == -EAGAIN || err == -EINTR)
++		if (err == -EAGAIN || err == -EINTR) {
++			preverr = err;
+ 			continue;
++		}
+ 		if (err < 0) {
+-			printk(KERN_WARNING
+-					"%s: terminating on error %d\n",
+-					__FUNCTION__, -err);
+-			break;
++			if (err != preverr) {
++				printk(KERN_WARNING "%s: unexpected error "
++					"from svc_recv (%d)\n", __func__, err);
++				preverr = err;
++			}
++			schedule_timeout_uninterruptible(HZ);
++			continue;
+ 		}
++		preverr = err;
+ 		svc_process(rqstp);
+ 	}
+-
+-	flush_signals(current);
+-	svc_exit_thread(rqstp);
+-	nfs_callback_info.pid = 0;
+-	complete(&nfs_callback_info.stopped);
+ 	unlock_kernel();
+-	module_put_and_exit(0);
++	nfs_callback_info.task = NULL;
++	svc_exit_thread(rqstp);
++	return 0;
+ }
+ 
+ /*
+@@ -107,14 +102,13 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
+ int nfs_callback_up(void)
+ {
+ 	struct svc_serv *serv = NULL;
++	struct svc_rqst *rqstp;
+ 	int ret = 0;
+ 
+ 	lock_kernel();
+ 	mutex_lock(&nfs_callback_mutex);
+-	if (nfs_callback_info.users++ || nfs_callback_info.pid != 0)
++	if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
+ 		goto out;
+-	init_completion(&nfs_callback_info.started);
+-	init_completion(&nfs_callback_info.stopped);
+ 	serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
+ 	ret = -ENOMEM;
+ 	if (!serv)
+@@ -127,15 +121,28 @@ int nfs_callback_up(void)
+ 	nfs_callback_tcpport = ret;
+ 	dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
+ 
+-	ret = svc_create_thread(nfs_callback_svc, serv);
+-	if (ret < 0)
++	rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
++	if (IS_ERR(rqstp)) {
++		ret = PTR_ERR(rqstp);
+ 		goto out_err;
++	}
++
++	svc_sock_update_bufs(serv);
+ 	nfs_callback_info.serv = serv;
+-	wait_for_completion(&nfs_callback_info.started);
++
++	nfs_callback_info.task = kthread_run(nfs_callback_svc, rqstp,
++					     "nfsv4-svc");
++	if (IS_ERR(nfs_callback_info.task)) {
++		ret = PTR_ERR(nfs_callback_info.task);
++		nfs_callback_info.serv = NULL;
++		nfs_callback_info.task = NULL;
++		svc_exit_thread(rqstp);
++		goto out_err;
++	}
+ out:
+ 	/*
+ 	 * svc_create creates the svc_serv with sv_nrthreads == 1, and then
+-	 * svc_create_thread increments that. So we need to call svc_destroy
++	 * svc_prepare_thread increments that. So we need to call svc_destroy
+ 	 * on both success and failure so that the refcount is 1 when the
+ 	 * thread exits.
+ 	 */
+@@ -152,19 +159,15 @@ out_err:
+ }
+ 
+ /*
+- * Kill the server process if it is not already up.
++ * Kill the server process if it is not already down.
+  */
+ void nfs_callback_down(void)
+ {
+ 	lock_kernel();
+ 	mutex_lock(&nfs_callback_mutex);
+ 	nfs_callback_info.users--;
+-	do {
+-		if (nfs_callback_info.users != 0 || nfs_callback_info.pid == 0)
+-			break;
+-		if (kill_proc(nfs_callback_info.pid, SIGKILL, 1) < 0)
+-			break;
+-	} while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0);
++	if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL)
++		kthread_stop(nfs_callback_info.task);
+ 	mutex_unlock(&nfs_callback_mutex);
+ 	unlock_kernel();
+ }
+diff --git a/fs/nfs/client.c b/fs/nfs/client.c
+index c5c0175..f2f3b28 100644
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -112,6 +112,7 @@ struct nfs_client_initdata {
+ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
+ {
+ 	struct nfs_client *clp;
++	struct rpc_cred *cred;
+ 
+ 	if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
+ 		goto error_0;
+@@ -150,6 +151,9 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
+ 	clp->cl_boot_time = CURRENT_TIME;
+ 	clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+ #endif
++	cred = rpc_lookup_machine_cred();
++	if (!IS_ERR(cred))
++		clp->cl_machine_cred = cred;
+ 
+ 	return clp;
+ 
+@@ -170,6 +174,8 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
+ 	BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
+ 	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+ 		nfs_idmap_delete(clp);
++
++	rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+ #endif
+ }
+ 
+@@ -189,6 +195,9 @@ static void nfs_free_client(struct nfs_client *clp)
+ 	if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+ 		nfs_callback_down();
+ 
++	if (clp->cl_machine_cred != NULL)
++		put_rpccred(clp->cl_machine_cred);
++
+ 	kfree(clp->cl_hostname);
+ 	kfree(clp);
+ 
+@@ -680,10 +689,22 @@ static int nfs_init_server(struct nfs_server *server,
+ 	if (error < 0)
+ 		goto error;
+ 
++	server->port = data->nfs_server.port;
++
+ 	error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
+ 	if (error < 0)
+ 		goto error;
+ 
++	/* Preserve the values of mount_server-related mount options */
++	if (data->mount_server.addrlen) {
++		memcpy(&server->mountd_address, &data->mount_server.address,
++			data->mount_server.addrlen);
++		server->mountd_addrlen = data->mount_server.addrlen;
++	}
++	server->mountd_version = data->mount_server.version;
++	server->mountd_port = data->mount_server.port;
++	server->mountd_protocol = data->mount_server.protocol;
++
+ 	server->namelen  = data->namlen;
+ 	/* Create a client RPC handle for the NFSv3 ACL management interface */
+ 	nfs_init_server_aclclient(server);
+@@ -1062,6 +1083,8 @@ static int nfs4_init_server(struct nfs_server *server,
+ 	server->acdirmin = data->acdirmin * HZ;
+ 	server->acdirmax = data->acdirmax * HZ;
+ 
++	server->port = data->nfs_server.port;
++
+ 	error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
+ 
+ error:
+diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
+index 6cea747..f288b3e 100644
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -967,7 +967,8 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd)
+ 	if (nd->flags & LOOKUP_DIRECTORY)
+ 		return 0;
+ 	/* Are we trying to write to a read only partition? */
+-	if (IS_RDONLY(dir) && (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
++	if (__mnt_is_readonly(nd->path.mnt) &&
++	    (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
+ 		return 0;
+ 	return 1;
+ }
+@@ -1966,7 +1967,7 @@ force_lookup:
+ 	if (!NFS_PROTO(inode)->access)
+ 		goto out_notsup;
+ 
+-	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
++	cred = rpc_lookup_cred();
+ 	if (!IS_ERR(cred)) {
+ 		res = nfs_do_access(inode, cred, mask);
+ 		put_rpccred(cred);
+diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
+index 16844f9..4757a2b 100644
+--- a/fs/nfs/direct.c
++++ b/fs/nfs/direct.c
+@@ -229,14 +229,20 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
+ static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs_read_data *data = calldata;
+-	struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+ 
+-	if (nfs_readpage_result(task, data) != 0)
+-		return;
++	nfs_readpage_result(task, data);
++}
++
++static void nfs_direct_read_release(void *calldata)
++{
++
++	struct nfs_read_data *data = calldata;
++	struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
++	int status = data->task.tk_status;
+ 
+ 	spin_lock(&dreq->lock);
+-	if (unlikely(task->tk_status < 0)) {
+-		dreq->error = task->tk_status;
++	if (unlikely(status < 0)) {
++		dreq->error = status;
+ 		spin_unlock(&dreq->lock);
+ 	} else {
+ 		dreq->count += data->res.count;
+@@ -249,11 +255,12 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
+ 
+ 	if (put_dreq(dreq))
+ 		nfs_direct_complete(dreq);
++	nfs_readdata_release(calldata);
+ }
+ 
+ static const struct rpc_call_ops nfs_read_direct_ops = {
+ 	.rpc_call_done = nfs_direct_read_result,
+-	.rpc_release = nfs_readdata_release,
++	.rpc_release = nfs_direct_read_release,
+ };
+ 
+ /*
+@@ -280,6 +287,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
+ 		.rpc_client = NFS_CLIENT(inode),
+ 		.rpc_message = &msg,
+ 		.callback_ops = &nfs_read_direct_ops,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC,
+ 	};
+ 	unsigned int pgbase;
+@@ -323,7 +331,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
+ 		data->inode = inode;
+ 		data->cred = msg.rpc_cred;
+ 		data->args.fh = NFS_FH(inode);
+-		data->args.context = ctx;
++		data->args.context = get_nfs_open_context(ctx);
+ 		data->args.offset = pos;
+ 		data->args.pgbase = pgbase;
+ 		data->args.pages = data->pagevec;
+@@ -339,8 +347,9 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
+ 		NFS_PROTO(inode)->read_setup(data, &msg);
+ 
+ 		task = rpc_run_task(&task_setup_data);
+-		if (!IS_ERR(task))
+-			rpc_put_task(task);
++		if (IS_ERR(task))
++			break;
++		rpc_put_task(task);
+ 
+ 		dprintk("NFS: %5u initiated direct read call "
+ 			"(req %s/%Ld, %zu bytes @ offset %Lu)\n",
+@@ -446,6 +455,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
+ 	struct rpc_task_setup task_setup_data = {
+ 		.rpc_client = NFS_CLIENT(inode),
+ 		.callback_ops = &nfs_write_direct_ops,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC,
+ 	};
+ 
+@@ -499,27 +509,34 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
+ static void nfs_direct_commit_result(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs_write_data *data = calldata;
+-	struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+ 
+ 	/* Call the NFS version-specific code */
+-	if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
+-		return;
+-	if (unlikely(task->tk_status < 0)) {
++	NFS_PROTO(data->inode)->commit_done(task, data);
++}
++
++static void nfs_direct_commit_release(void *calldata)
++{
++	struct nfs_write_data *data = calldata;
++	struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
++	int status = data->task.tk_status;
++
++	if (status < 0) {
+ 		dprintk("NFS: %5u commit failed with error %d.\n",
+-				task->tk_pid, task->tk_status);
++				data->task.tk_pid, status);
+ 		dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+ 	} else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) {
+-		dprintk("NFS: %5u commit verify failed\n", task->tk_pid);
++		dprintk("NFS: %5u commit verify failed\n", data->task.tk_pid);
+ 		dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+ 	}
+ 
+-	dprintk("NFS: %5u commit returned %d\n", task->tk_pid, task->tk_status);
++	dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status);
+ 	nfs_direct_write_complete(dreq, data->inode);
++	nfs_commitdata_release(calldata);
+ }
+ 
+ static const struct rpc_call_ops nfs_commit_direct_ops = {
+ 	.rpc_call_done = nfs_direct_commit_result,
+-	.rpc_release = nfs_commit_release,
++	.rpc_release = nfs_direct_commit_release,
+ };
+ 
+ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
+@@ -537,6 +554,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
+ 		.rpc_message = &msg,
+ 		.callback_ops = &nfs_commit_direct_ops,
+ 		.callback_data = data,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC,
+ 	};
+ 
+@@ -546,6 +564,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
+ 	data->args.fh = NFS_FH(data->inode);
+ 	data->args.offset = 0;
+ 	data->args.count = 0;
++	data->args.context = get_nfs_open_context(dreq->ctx);
+ 	data->res.count = 0;
+ 	data->res.fattr = &data->fattr;
+ 	data->res.verf = &data->verf;
+@@ -585,7 +604,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
+ 
+ static void nfs_alloc_commit_data(struct nfs_direct_req *dreq)
+ {
+-	dreq->commit_data = nfs_commit_alloc();
++	dreq->commit_data = nfs_commitdata_alloc();
+ 	if (dreq->commit_data != NULL)
+ 		dreq->commit_data->req = (struct nfs_page *) dreq;
+ }
+@@ -606,11 +625,20 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
+ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs_write_data *data = calldata;
+-	struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+-	int status = task->tk_status;
+ 
+ 	if (nfs_writeback_done(task, data) != 0)
+ 		return;
++}
++
++/*
++ * NB: Return the value of the first error return code.  Subsequent
++ *     errors after the first one are ignored.
++ */
++static void nfs_direct_write_release(void *calldata)
++{
++	struct nfs_write_data *data = calldata;
++	struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
++	int status = data->task.tk_status;
+ 
+ 	spin_lock(&dreq->lock);
+ 
+@@ -632,23 +660,13 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
+ 				break;
+ 			case NFS_ODIRECT_DO_COMMIT:
+ 				if (memcmp(&dreq->verf, &data->verf, sizeof(dreq->verf))) {
+-					dprintk("NFS: %5u write verify failed\n", task->tk_pid);
++					dprintk("NFS: %5u write verify failed\n", data->task.tk_pid);
+ 					dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+ 				}
+ 		}
+ 	}
+ out_unlock:
+ 	spin_unlock(&dreq->lock);
+-}
+-
+-/*
+- * NB: Return the value of the first error return code.  Subsequent
+- *     errors after the first one are ignored.
+- */
+-static void nfs_direct_write_release(void *calldata)
+-{
+-	struct nfs_write_data *data = calldata;
+-	struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+ 
+ 	if (put_dreq(dreq))
+ 		nfs_direct_write_complete(dreq, data->inode);
+@@ -682,6 +700,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
+ 		.rpc_client = NFS_CLIENT(inode),
+ 		.rpc_message = &msg,
+ 		.callback_ops = &nfs_write_direct_ops,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC,
+ 	};
+ 	size_t wsize = NFS_SERVER(inode)->wsize;
+@@ -728,7 +747,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
+ 		data->inode = inode;
+ 		data->cred = msg.rpc_cred;
+ 		data->args.fh = NFS_FH(inode);
+-		data->args.context = ctx;
++		data->args.context = get_nfs_open_context(ctx);
+ 		data->args.offset = pos;
+ 		data->args.pgbase = pgbase;
+ 		data->args.pages = data->pagevec;
+@@ -745,8 +764,9 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
+ 		NFS_PROTO(inode)->write_setup(data, &msg);
+ 
+ 		task = rpc_run_task(&task_setup_data);
+-		if (!IS_ERR(task))
+-			rpc_put_task(task);
++		if (IS_ERR(task))
++			break;
++		rpc_put_task(task);
+ 
+ 		dprintk("NFS: %5u initiated direct write call "
+ 			"(req %s/%Ld, %zu bytes @ offset %Lu)\n",
+diff --git a/fs/nfs/file.c b/fs/nfs/file.c
+index 5d2e9d9..3536b01 100644
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -238,10 +238,8 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
+ 	ssize_t result;
+ 	size_t count = iov_length(iov, nr_segs);
+ 
+-#ifdef CONFIG_NFS_DIRECTIO
+ 	if (iocb->ki_filp->f_flags & O_DIRECT)
+ 		return nfs_file_direct_read(iocb, iov, nr_segs, pos);
+-#endif
+ 
+ 	dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
+ 		dentry->d_parent->d_name.name, dentry->d_name.name,
+@@ -387,9 +385,7 @@ const struct address_space_operations nfs_file_aops = {
+ 	.write_end = nfs_write_end,
+ 	.invalidatepage = nfs_invalidate_page,
+ 	.releasepage = nfs_release_page,
+-#ifdef CONFIG_NFS_DIRECTIO
+ 	.direct_IO = nfs_direct_IO,
+-#endif
+ 	.launder_page = nfs_launder_page,
+ };
+ 
+@@ -447,10 +443,8 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
+ 	ssize_t result;
+ 	size_t count = iov_length(iov, nr_segs);
+ 
+-#ifdef CONFIG_NFS_DIRECTIO
+ 	if (iocb->ki_filp->f_flags & O_DIRECT)
+ 		return nfs_file_direct_write(iocb, iov, nr_segs, pos);
+-#endif
+ 
+ 	dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%Ld)\n",
+ 		dentry->d_parent->d_name.name, dentry->d_name.name,
+@@ -576,17 +570,9 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
+ 
+ 	lock_kernel();
+ 	/* Use local locking if mounted with "-onolock" */
+-	if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) {
++	if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
+ 		status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+-		/* If we were signalled we still need to ensure that
+-		 * we clean up any state on the server. We therefore
+-		 * record the lock call as having succeeded in order to
+-		 * ensure that locks_remove_posix() cleans it out when
+-		 * the process exits.
+-		 */
+-		if (status == -EINTR || status == -ERESTARTSYS)
+-			do_vfs_lock(filp, fl);
+-	} else
++	else
+ 		status = do_vfs_lock(filp, fl);
+ 	unlock_kernel();
+ 	if (status < 0)
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 6f88d7c..5cb3345 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -523,8 +523,12 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
+ 
+ static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait)
+ {
+-	struct inode *inode = ctx->path.dentry->d_inode;
++	struct inode *inode;
+ 
++	if (ctx == NULL)
++		return;
++
++	inode = ctx->path.dentry->d_inode;
+ 	if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock))
+ 		return;
+ 	list_del(&ctx->list);
+@@ -610,7 +614,7 @@ int nfs_open(struct inode *inode, struct file *filp)
+ 	struct nfs_open_context *ctx;
+ 	struct rpc_cred *cred;
+ 
+-	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
++	cred = rpc_lookup_cred();
+ 	if (IS_ERR(cred))
+ 		return PTR_ERR(cred);
+ 	ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
+@@ -1218,6 +1222,36 @@ static void nfs_destroy_inodecache(void)
+ 	kmem_cache_destroy(nfs_inode_cachep);
+ }
+ 
++struct workqueue_struct *nfsiod_workqueue;
++
++/*
++ * start up the nfsiod workqueue
++ */
++static int nfsiod_start(void)
++{
++	struct workqueue_struct *wq;
++	dprintk("RPC:       creating workqueue nfsiod\n");
++	wq = create_singlethread_workqueue("nfsiod");
++	if (wq == NULL)
++		return -ENOMEM;
++	nfsiod_workqueue = wq;
++	return 0;
++}
++
++/*
++ * Destroy the nfsiod workqueue
++ */
++static void nfsiod_stop(void)
++{
++	struct workqueue_struct *wq;
++
++	wq = nfsiod_workqueue;
++	if (wq == NULL)
++		return;
++	nfsiod_workqueue = NULL;
++	destroy_workqueue(wq);
++}
++
+ /*
+  * Initialize NFS
+  */
+@@ -1225,6 +1259,10 @@ static int __init init_nfs_fs(void)
+ {
+ 	int err;
+ 
++	err = nfsiod_start();
++	if (err)
++		goto out6;
++
+ 	err = nfs_fs_proc_init();
+ 	if (err)
+ 		goto out5;
+@@ -1271,6 +1309,8 @@ out3:
+ out4:
+ 	nfs_fs_proc_exit();
+ out5:
++	nfsiod_stop();
++out6:
+ 	return err;
+ }
+ 
+@@ -1286,6 +1326,7 @@ static void __exit exit_nfs_fs(void)
+ #endif
+ 	unregister_nfs_fs();
+ 	nfs_fs_proc_exit();
++	nfsiod_stop();
+ }
+ 
+ /* Not quite true; I just maintain it */
+diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
+index 9319927..04ae867 100644
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -46,9 +46,9 @@ struct nfs_parsed_mount_data {
+ 		struct sockaddr_storage	address;
+ 		size_t			addrlen;
+ 		char			*hostname;
+-		unsigned int		version;
++		u32			version;
+ 		unsigned short		port;
+-		int			protocol;
++		unsigned short		protocol;
+ 	} mount_server;
+ 
+ 	struct {
+@@ -56,7 +56,8 @@ struct nfs_parsed_mount_data {
+ 		size_t			addrlen;
+ 		char			*hostname;
+ 		char			*export_path;
+-		int			protocol;
++		unsigned short		port;
++		unsigned short		protocol;
+ 	} nfs_server;
+ 
+ 	struct security_mnt_opts lsm_opts;
+@@ -115,13 +116,8 @@ extern void nfs_destroy_readpagecache(void);
+ extern int __init nfs_init_writepagecache(void);
+ extern void nfs_destroy_writepagecache(void);
+ 
+-#ifdef CONFIG_NFS_DIRECTIO
+ extern int __init nfs_init_directcache(void);
+ extern void nfs_destroy_directcache(void);
+-#else
+-#define nfs_init_directcache() (0)
+-#define nfs_destroy_directcache() do {} while(0)
+-#endif
+ 
+ /* nfs2xdr.c */
+ extern int nfs_stat_to_errno(int);
+@@ -146,6 +142,7 @@ extern struct rpc_procinfo nfs4_procedures[];
+ extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
+ 
+ /* inode.c */
++extern struct workqueue_struct *nfsiod_workqueue;
+ extern struct inode *nfs_alloc_inode(struct super_block *sb);
+ extern void nfs_destroy_inode(struct inode *);
+ extern int nfs_write_inode(struct inode *,int);
+diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
+index 607f6eb..af4d0f1 100644
+--- a/fs/nfs/namespace.c
++++ b/fs/nfs/namespace.c
+@@ -20,7 +20,7 @@
+ 
+ static void nfs_expire_automounts(struct work_struct *work);
+ 
+-LIST_HEAD(nfs_automount_list);
++static LIST_HEAD(nfs_automount_list);
+ static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
+ int nfs_mountpoint_expiry_timeout = 500 * HZ;
+ 
+diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
+index 1f7ea67..28bab67 100644
+--- a/fs/nfs/nfs2xdr.c
++++ b/fs/nfs/nfs2xdr.c
+@@ -267,7 +267,7 @@ nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
+ 	int status;
+ 
+ 	if ((status = ntohl(*p++)))
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	p = xdr_decode_fattr(p, res->fattr);
+ 
+ 	count = ntohl(*p++);
+@@ -428,11 +428,11 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
+ 	size_t hdrlen;
+ 	unsigned int pglen, recvd;
+ 	u32 len;
+-	int status, nr;
++	int status, nr = 0;
+ 	__be32 *end, *entry, *kaddr;
+ 
+ 	if ((status = ntohl(*p++)))
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 
+ 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
+ 	if (iov->iov_len < hdrlen) {
+@@ -452,7 +452,12 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
+ 	kaddr = p = kmap_atomic(*page, KM_USER0);
+ 	end = (__be32 *)((char *)p + pglen);
+ 	entry = p;
+-	for (nr = 0; *p++; nr++) {
++
++	/* Make sure the packet actually has a value_follows and EOF entry */
++	if ((entry + 1) > end)
++		goto short_pkt;
++
++	for (; *p++; nr++) {
+ 		if (p + 2 > end)
+ 			goto short_pkt;
+ 		p++; /* fileid */
+@@ -467,18 +472,32 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
+ 			goto short_pkt;
+ 		entry = p;
+ 	}
+-	if (!nr && (entry[0] != 0 || entry[1] == 0))
+-		goto short_pkt;
++
++	/*
++	 * Apparently some server sends responses that are a valid size, but
++	 * contain no entries, and have value_follows==0 and EOF==0. For
++	 * those, just set the EOF marker.
++	 */
++	if (!nr && entry[1] == 0) {
++		dprintk("NFS: readdir reply truncated!\n");
++		entry[1] = 1;
++	}
+  out:
+ 	kunmap_atomic(kaddr, KM_USER0);
+ 	return nr;
+  short_pkt:
++	/*
++	 * When we get a short packet there are 2 possibilities. We can
++	 * return an error, or fix up the response to look like a valid
++	 * response and return what we have so far. If there are no
++	 * entries and the packet was short, then return -EIO. If there
++	 * are valid entries in the response, return them and pretend that
++	 * the call was successful, but incomplete. The caller can retry the
++	 * readdir starting at the last cookie.
++	 */
+ 	entry[0] = entry[1] = 0;
+-	/* truncate listing ? */
+-	if (!nr) {
+-		dprintk("NFS: readdir reply truncated!\n");
+-		entry[1] = 1;
+-	}
++	if (!nr)
++		nr = -errno_NFSERR_IO;
+ 	goto out;
+ err_unmap:
+ 	nr = -errno_NFSERR_IO;
+@@ -518,7 +537,7 @@ nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++)) != 0)
+-		status = -nfs_stat_to_errno(status);
++		status = nfs_stat_to_errno(status);
+ 	return status;
+ }
+ 
+@@ -532,7 +551,7 @@ nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++)))
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	xdr_decode_fattr(p, fattr);
+ 	return 0;
+ }
+@@ -547,7 +566,7 @@ nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++)))
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	p = xdr_decode_fhandle(p, res->fh);
+ 	xdr_decode_fattr(p, res->fattr);
+ 	return 0;
+@@ -585,7 +604,7 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++)))
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	/* Convert length of symlink */
+ 	len = ntohl(*p++);
+ 	if (len >= rcvbuf->page_len) {
+@@ -634,7 +653,7 @@ nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++)))
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 
+ 	res->tsize  = ntohl(*p++);
+ 	res->bsize  = ntohl(*p++);
+@@ -653,39 +672,39 @@ static struct {
+ 	int errno;
+ } nfs_errtbl[] = {
+ 	{ NFS_OK,		0		},
+-	{ NFSERR_PERM,		EPERM		},
+-	{ NFSERR_NOENT,		ENOENT		},
+-	{ NFSERR_IO,		errno_NFSERR_IO	},
+-	{ NFSERR_NXIO,		ENXIO		},
+-/*	{ NFSERR_EAGAIN,	EAGAIN		}, */
+-	{ NFSERR_ACCES,		EACCES		},
+-	{ NFSERR_EXIST,		EEXIST		},
+-	{ NFSERR_XDEV,		EXDEV		},
+-	{ NFSERR_NODEV,		ENODEV		},
+-	{ NFSERR_NOTDIR,	ENOTDIR		},
+-	{ NFSERR_ISDIR,		EISDIR		},
+-	{ NFSERR_INVAL,		EINVAL		},
+-	{ NFSERR_FBIG,		EFBIG		},
+-	{ NFSERR_NOSPC,		ENOSPC		},
+-	{ NFSERR_ROFS,		EROFS		},
+-	{ NFSERR_MLINK,		EMLINK		},
+-	{ NFSERR_NAMETOOLONG,	ENAMETOOLONG	},
+-	{ NFSERR_NOTEMPTY,	ENOTEMPTY	},
+-	{ NFSERR_DQUOT,		EDQUOT		},
+-	{ NFSERR_STALE,		ESTALE		},
+-	{ NFSERR_REMOTE,	EREMOTE		},
++	{ NFSERR_PERM,		-EPERM		},
++	{ NFSERR_NOENT,		-ENOENT		},
++	{ NFSERR_IO,		-errno_NFSERR_IO},
++	{ NFSERR_NXIO,		-ENXIO		},
++/*	{ NFSERR_EAGAIN,	-EAGAIN		}, */
++	{ NFSERR_ACCES,		-EACCES		},
++	{ NFSERR_EXIST,		-EEXIST		},
++	{ NFSERR_XDEV,		-EXDEV		},
++	{ NFSERR_NODEV,		-ENODEV		},
++	{ NFSERR_NOTDIR,	-ENOTDIR	},
++	{ NFSERR_ISDIR,		-EISDIR		},
++	{ NFSERR_INVAL,		-EINVAL		},
++	{ NFSERR_FBIG,		-EFBIG		},
++	{ NFSERR_NOSPC,		-ENOSPC		},
++	{ NFSERR_ROFS,		-EROFS		},
++	{ NFSERR_MLINK,		-EMLINK		},
++	{ NFSERR_NAMETOOLONG,	-ENAMETOOLONG	},
++	{ NFSERR_NOTEMPTY,	-ENOTEMPTY	},
++	{ NFSERR_DQUOT,		-EDQUOT		},
++	{ NFSERR_STALE,		-ESTALE		},
++	{ NFSERR_REMOTE,	-EREMOTE	},
+ #ifdef EWFLUSH
+-	{ NFSERR_WFLUSH,	EWFLUSH		},
++	{ NFSERR_WFLUSH,	-EWFLUSH	},
+ #endif
+-	{ NFSERR_BADHANDLE,	EBADHANDLE	},
+-	{ NFSERR_NOT_SYNC,	ENOTSYNC	},
+-	{ NFSERR_BAD_COOKIE,	EBADCOOKIE	},
+-	{ NFSERR_NOTSUPP,	ENOTSUPP	},
+-	{ NFSERR_TOOSMALL,	ETOOSMALL	},
+-	{ NFSERR_SERVERFAULT,	ESERVERFAULT	},
+-	{ NFSERR_BADTYPE,	EBADTYPE	},
+-	{ NFSERR_JUKEBOX,	EJUKEBOX	},
+-	{ -1,			EIO		}
++	{ NFSERR_BADHANDLE,	-EBADHANDLE	},
++	{ NFSERR_NOT_SYNC,	-ENOTSYNC	},
++	{ NFSERR_BAD_COOKIE,	-EBADCOOKIE	},
++	{ NFSERR_NOTSUPP,	-ENOTSUPP	},
++	{ NFSERR_TOOSMALL,	-ETOOSMALL	},
++	{ NFSERR_SERVERFAULT,	-ESERVERFAULT	},
++	{ NFSERR_BADTYPE,	-EBADTYPE	},
++	{ NFSERR_JUKEBOX,	-EJUKEBOX	},
++	{ -1,			-EIO		}
+ };
+ 
+ /*
+diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
+index 3917e2f..11cddde 100644
+--- a/fs/nfs/nfs3xdr.c
++++ b/fs/nfs/nfs3xdr.c
+@@ -508,14 +508,14 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
+ 	struct page **page;
+ 	size_t hdrlen;
+ 	u32 len, recvd, pglen;
+-	int status, nr;
++	int status, nr = 0;
+ 	__be32 *entry, *end, *kaddr;
+ 
+ 	status = ntohl(*p++);
+ 	/* Decode post_op_attrs */
+ 	p = xdr_decode_post_op_attr(p, res->dir_attr);
+ 	if (status)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	/* Decode verifier cookie */
+ 	if (res->verf) {
+ 		res->verf[0] = *p++;
+@@ -542,7 +542,12 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
+ 	kaddr = p = kmap_atomic(*page, KM_USER0);
+ 	end = (__be32 *)((char *)p + pglen);
+ 	entry = p;
+-	for (nr = 0; *p++; nr++) {
++
++	/* Make sure the packet actually has a value_follows and EOF entry */
++	if ((entry + 1) > end)
++		goto short_pkt;
++
++	for (; *p++; nr++) {
+ 		if (p + 3 > end)
+ 			goto short_pkt;
+ 		p += 2;				/* inode # */
+@@ -581,18 +586,32 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
+ 			goto short_pkt;
+ 		entry = p;
+ 	}
+-	if (!nr && (entry[0] != 0 || entry[1] == 0))
+-		goto short_pkt;
++
++	/*
++	 * Apparently some server sends responses that are a valid size, but
++	 * contain no entries, and have value_follows==0 and EOF==0. For
++	 * those, just set the EOF marker.
++	 */
++	if (!nr && entry[1] == 0) {
++		dprintk("NFS: readdir reply truncated!\n");
++		entry[1] = 1;
++	}
+  out:
+ 	kunmap_atomic(kaddr, KM_USER0);
+ 	return nr;
+  short_pkt:
++	/*
++	 * When we get a short packet there are 2 possibilities. We can
++	 * return an error, or fix up the response to look like a valid
++	 * response and return what we have so far. If there are no
++	 * entries and the packet was short, then return -EIO. If there
++	 * are valid entries in the response, return them and pretend that
++	 * the call was successful, but incomplete. The caller can retry the
++	 * readdir starting at the last cookie.
++	 */
+ 	entry[0] = entry[1] = 0;
+-	/* truncate listing ? */
+-	if (!nr) {
+-		dprintk("NFS: readdir reply truncated!\n");
+-		entry[1] = 1;
+-	}
++	if (!nr)
++		nr = -errno_NFSERR_IO;
+ 	goto out;
+ err_unmap:
+ 	nr = -errno_NFSERR_IO;
+@@ -732,7 +751,7 @@ nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++)))
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	xdr_decode_fattr(p, fattr);
+ 	return 0;
+ }
+@@ -747,7 +766,7 @@ nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++)))
+-		status = -nfs_stat_to_errno(status);
++		status = nfs_stat_to_errno(status);
+ 	xdr_decode_wcc_data(p, fattr);
+ 	return status;
+ }
+@@ -767,7 +786,7 @@ nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++))) {
+-		status = -nfs_stat_to_errno(status);
++		status = nfs_stat_to_errno(status);
+ 	} else {
+ 		if (!(p = xdr_decode_fhandle(p, res->fh)))
+ 			return -errno_NFSERR_IO;
+@@ -787,7 +806,7 @@ nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
+ 
+ 	p = xdr_decode_post_op_attr(p, res->fattr);
+ 	if (status)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	res->access = ntohl(*p++);
+ 	return 0;
+ }
+@@ -824,7 +843,7 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ 	p = xdr_decode_post_op_attr(p, fattr);
+ 
+ 	if (status != 0)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 
+ 	/* Convert length of symlink */
+ 	len = ntohl(*p++);
+@@ -872,7 +891,7 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
+ 	p = xdr_decode_post_op_attr(p, res->fattr);
+ 
+ 	if (status != 0)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 
+ 	/* Decode reply count and EOF flag. NFSv3 is somewhat redundant
+ 	 * in that it puts the count both in the res struct and in the
+@@ -922,7 +941,7 @@ nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
+ 	p = xdr_decode_wcc_data(p, res->fattr);
+ 
+ 	if (status != 0)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 
+ 	res->count = ntohl(*p++);
+ 	res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
+@@ -953,7 +972,7 @@ nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
+ 			res->fattr->valid = 0;
+ 		}
+ 	} else {
+-		status = -nfs_stat_to_errno(status);
++		status = nfs_stat_to_errno(status);
+ 	}
+ 	p = xdr_decode_wcc_data(p, res->dir_attr);
+ 	return status;
+@@ -968,7 +987,7 @@ nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++)) != 0)
+-		status = -nfs_stat_to_errno(status);
++		status = nfs_stat_to_errno(status);
+ 	p = xdr_decode_wcc_data(p, res->fromattr);
+ 	p = xdr_decode_wcc_data(p, res->toattr);
+ 	return status;
+@@ -983,7 +1002,7 @@ nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
+ 	int	status;
+ 
+ 	if ((status = ntohl(*p++)) != 0)
+-		status = -nfs_stat_to_errno(status);
++		status = nfs_stat_to_errno(status);
+ 	p = xdr_decode_post_op_attr(p, res->fattr);
+ 	p = xdr_decode_wcc_data(p, res->dir_attr);
+ 	return status;
+@@ -1001,7 +1020,7 @@ nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
+ 
+ 	p = xdr_decode_post_op_attr(p, res->fattr);
+ 	if (status != 0)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 
+ 	p = xdr_decode_hyper(p, &res->tbytes);
+ 	p = xdr_decode_hyper(p, &res->fbytes);
+@@ -1026,7 +1045,7 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
+ 
+ 	p = xdr_decode_post_op_attr(p, res->fattr);
+ 	if (status != 0)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 
+ 	res->rtmax  = ntohl(*p++);
+ 	res->rtpref = ntohl(*p++);
+@@ -1054,7 +1073,7 @@ nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
+ 
+ 	p = xdr_decode_post_op_attr(p, res->fattr);
+ 	if (status != 0)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	res->max_link = ntohl(*p++);
+ 	res->max_namelen = ntohl(*p++);
+ 
+@@ -1073,7 +1092,7 @@ nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
+ 	status = ntohl(*p++);
+ 	p = xdr_decode_wcc_data(p, res->fattr);
+ 	if (status != 0)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 
+ 	res->verf->verifier[0] = *p++;
+ 	res->verf->verifier[1] = *p++;
+@@ -1095,7 +1114,7 @@ nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
+ 	int err, base;
+ 
+ 	if (status != 0)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	p = xdr_decode_post_op_attr(p, res->fattr);
+ 	res->mask = ntohl(*p++);
+ 	if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+@@ -1122,7 +1141,7 @@ nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ 	int status = ntohl(*p++);
+ 
+ 	if (status)
+-		return -nfs_stat_to_errno(status);
++		return nfs_stat_to_errno(status);
+ 	xdr_decode_post_op_attr(p, fattr);
+ 	return 0;
+ }
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 7ce0786..dbc0927 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -51,6 +51,7 @@
+ 
+ #include "nfs4_fs.h"
+ #include "delegation.h"
++#include "internal.h"
+ #include "iostat.h"
+ 
+ #define NFSDBG_FACILITY		NFSDBG_PROC
+@@ -239,6 +240,8 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
+ {
+ 	p->o_res.f_attr = &p->f_attr;
+ 	p->o_res.dir_attr = &p->dir_attr;
++	p->o_res.seqid = p->o_arg.seqid;
++	p->c_res.seqid = p->c_arg.seqid;
+ 	p->o_res.server = p->o_arg.server;
+ 	nfs_fattr_init(&p->f_attr);
+ 	nfs_fattr_init(&p->dir_attr);
+@@ -729,7 +732,6 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
+ 		renew_lease(data->o_res.server, data->timestamp);
+ 		data->rpc_done = 1;
+ 	}
+-	nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
+ }
+ 
+ static void nfs4_open_confirm_release(void *calldata)
+@@ -773,6 +775,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
+ 		.rpc_message = &msg,
+ 		.callback_ops = &nfs4_open_confirm_ops,
+ 		.callback_data = data,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC,
+ 	};
+ 	int status;
+@@ -858,7 +861,6 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
+ 		if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
+ 			nfs_confirm_seqid(&data->owner->so_seqid, 0);
+ 	}
+-	nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid);
+ 	data->rpc_done = 1;
+ }
+ 
+@@ -910,6 +912,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
+ 		.rpc_message = &msg,
+ 		.callback_ops = &nfs4_open_ops,
+ 		.callback_data = data,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC,
+ 	};
+ 	int status;
+@@ -979,11 +982,8 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
+ 	if (IS_ERR(opendata))
+ 		return PTR_ERR(opendata);
+ 	ret = nfs4_open_recover(opendata, state);
+-	if (ret == -ESTALE) {
+-		/* Invalidate the state owner so we don't ever use it again */
+-		nfs4_drop_state_owner(state->owner);
++	if (ret == -ESTALE)
+ 		d_drop(ctx->path.dentry);
+-	}
+ 	nfs4_opendata_put(opendata);
+ 	return ret;
+ }
+@@ -1226,7 +1226,6 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
+         /* hmm. we are done with the inode, and in the process of freeing
+ 	 * the state_owner. we keep this around to process errors
+ 	 */
+-	nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
+ 	switch (task->tk_status) {
+ 		case 0:
+ 			nfs_set_open_stateid(state, &calldata->res.stateid, 0);
+@@ -1315,6 +1314,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
+ 		.rpc_client = server->client,
+ 		.rpc_message = &msg,
+ 		.callback_ops = &nfs4_close_ops,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC,
+ 	};
+ 	int status = -ENOMEM;
+@@ -1332,6 +1332,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
+ 		goto out_free_calldata;
+ 	calldata->arg.bitmask = server->attr_bitmask;
+ 	calldata->res.fattr = &calldata->fattr;
++	calldata->res.seqid = calldata->arg.seqid;
+ 	calldata->res.server = server;
+ 	calldata->path.mnt = mntget(path->mnt);
+ 	calldata->path.dentry = dget(path->dentry);
+@@ -1404,7 +1405,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+ 		BUG_ON(nd->intent.open.flags & O_CREAT);
+ 	}
+ 
+-	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
++	cred = rpc_lookup_cred();
+ 	if (IS_ERR(cred))
+ 		return (struct dentry *)cred;
+ 	parent = dentry->d_parent;
+@@ -1439,7 +1440,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
+ 	struct rpc_cred *cred;
+ 	struct nfs4_state *state;
+ 
+-	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
++	cred = rpc_lookup_cred();
+ 	if (IS_ERR(cred))
+ 		return PTR_ERR(cred);
+ 	state = nfs4_do_open(dir, &path, openflags, NULL, cred);
+@@ -1656,7 +1657,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
+ 
+ 	nfs_fattr_init(fattr);
+ 	
+-	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
++	cred = rpc_lookup_cred();
+ 	if (IS_ERR(cred))
+ 		return PTR_ERR(cred);
+ 
+@@ -1892,7 +1893,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ 	struct rpc_cred *cred;
+ 	int status = 0;
+ 
+-	cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
++	cred = rpc_lookup_cred();
+ 	if (IS_ERR(cred)) {
+ 		status = PTR_ERR(cred);
+ 		goto out;
+@@ -2761,10 +2762,10 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
+ 		case -NFS4ERR_STALE_CLIENTID:
+ 		case -NFS4ERR_STALE_STATEID:
+ 		case -NFS4ERR_EXPIRED:
+-			rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
++			rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
+ 			nfs4_schedule_state_recovery(clp);
+ 			if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
+-				rpc_wake_up_task(task);
++				rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
+ 			task->tk_status = 0;
+ 			return -EAGAIN;
+ 		case -NFS4ERR_DELAY:
+@@ -2884,7 +2885,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
+ 							RPC_DISPLAY_ADDR),
+ 				rpc_peeraddr2str(clp->cl_rpcclient,
+ 							RPC_DISPLAY_PROTO),
+-				cred->cr_ops->cr_name,
++				clp->cl_rpcclient->cl_auth->au_ops->au_name,
+ 				clp->cl_id_uniquifier);
+ 		setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
+ 				sizeof(setclientid.sc_netid),
+@@ -3158,6 +3159,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
+ 	p->arg.fh = NFS_FH(inode);
+ 	p->arg.fl = &p->fl;
+ 	p->arg.seqid = seqid;
++	p->res.seqid = seqid;
+ 	p->arg.stateid = &lsp->ls_stateid;
+ 	p->lsp = lsp;
+ 	atomic_inc(&lsp->ls_count);
+@@ -3183,7 +3185,6 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
+ 
+ 	if (RPC_ASSASSINATED(task))
+ 		return;
+-	nfs_increment_lock_seqid(task->tk_status, calldata->arg.seqid);
+ 	switch (task->tk_status) {
+ 		case 0:
+ 			memcpy(calldata->lsp->ls_stateid.data,
+@@ -3235,6 +3236,7 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
+ 		.rpc_client = NFS_CLIENT(lsp->ls_state->inode),
+ 		.rpc_message = &msg,
+ 		.callback_ops = &nfs4_locku_ops,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC,
+ 	};
+ 
+@@ -3261,6 +3263,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
+ 	struct nfs4_lock_state *lsp;
+ 	struct rpc_task *task;
+ 	int status = 0;
++	unsigned char fl_flags = request->fl_flags;
+ 
+ 	status = nfs4_set_lock_state(state, request);
+ 	/* Unlock _before_ we do the RPC call */
+@@ -3284,6 +3287,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
+ 	status = nfs4_wait_for_completion_rpc_task(task);
+ 	rpc_put_task(task);
+ out:
++	request->fl_flags = fl_flags;
+ 	return status;
+ }
+ 
+@@ -3320,6 +3324,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
+ 	p->arg.lock_stateid = &lsp->ls_stateid;
+ 	p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
+ 	p->arg.lock_owner.id = lsp->ls_id.id;
++	p->res.lock_seqid = p->arg.lock_seqid;
+ 	p->lsp = lsp;
+ 	atomic_inc(&lsp->ls_count);
+ 	p->ctx = get_nfs_open_context(ctx);
+@@ -3346,6 +3351,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
+ 			return;
+ 		data->arg.open_stateid = &state->stateid;
+ 		data->arg.new_lock_owner = 1;
++		data->res.open_seqid = data->arg.open_seqid;
+ 	} else
+ 		data->arg.new_lock_owner = 0;
+ 	data->timestamp = jiffies;
+@@ -3363,7 +3369,6 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
+ 	if (RPC_ASSASSINATED(task))
+ 		goto out;
+ 	if (data->arg.new_lock_owner != 0) {
+-		nfs_increment_open_seqid(data->rpc_status, data->arg.open_seqid);
+ 		if (data->rpc_status == 0)
+ 			nfs_confirm_seqid(&data->lsp->ls_seqid, 0);
+ 		else
+@@ -3375,7 +3380,6 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
+ 		data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+ 		renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp);
+ 	}
+-	nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid);
+ out:
+ 	dprintk("%s: done, ret = %d!\n", __FUNCTION__, data->rpc_status);
+ }
+@@ -3419,6 +3423,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
+ 		.rpc_client = NFS_CLIENT(state->inode),
+ 		.rpc_message = &msg,
+ 		.callback_ops = &nfs4_lock_ops,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC,
+ 	};
+ 	int ret;
+diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
+index b962397..46eb624 100644
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -71,6 +71,29 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
+ 	return status;
+ }
+ 
++static struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp)
++{
++	struct rpc_cred *cred = NULL;
++
++	spin_lock(&clp->cl_lock);
++	if (clp->cl_machine_cred != NULL)
++		cred = get_rpccred(clp->cl_machine_cred);
++	spin_unlock(&clp->cl_lock);
++	return cred;
++}
++
++static void nfs4_clear_machine_cred(struct nfs_client *clp)
++{
++	struct rpc_cred *cred;
++
++	spin_lock(&clp->cl_lock);
++	cred = clp->cl_machine_cred;
++	clp->cl_machine_cred = NULL;
++	spin_unlock(&clp->cl_lock);
++	if (cred != NULL)
++		put_rpccred(cred);
++}
++
+ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
+ {
+ 	struct nfs4_state_owner *sp;
+@@ -91,13 +114,18 @@ static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
+ {
+ 	struct nfs4_state_owner *sp;
+ 	struct rb_node *pos;
++	struct rpc_cred *cred;
+ 
++	cred = nfs4_get_machine_cred(clp);
++	if (cred != NULL)
++		goto out;
+ 	pos = rb_first(&clp->cl_state_owners);
+ 	if (pos != NULL) {
+ 		sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
+-		return get_rpccred(sp->so_cred);
++		cred = get_rpccred(sp->so_cred);
+ 	}
+-	return NULL;
++out:
++	return cred;
+ }
+ 
+ static void nfs_alloc_unique_id(struct rb_root *root, struct nfs_unique_id *new,
+@@ -292,8 +320,10 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
+ 	spin_unlock(&clp->cl_lock);
+ 	if (sp == new)
+ 		get_rpccred(cred);
+-	else
++	else {
++		rpc_destroy_wait_queue(&new->so_sequence.wait);
+ 		kfree(new);
++	}
+ 	return sp;
+ }
+ 
+@@ -310,6 +340,7 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
+ 		return;
+ 	nfs4_remove_state_owner(clp, sp);
+ 	spin_unlock(&clp->cl_lock);
++	rpc_destroy_wait_queue(&sp->so_sequence.wait);
+ 	put_rpccred(cred);
+ 	kfree(sp);
+ }
+@@ -529,6 +560,7 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
+ 	spin_lock(&clp->cl_lock);
+ 	nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id);
+ 	spin_unlock(&clp->cl_lock);
++	rpc_destroy_wait_queue(&lsp->ls_sequence.wait);
+ 	kfree(lsp);
+ }
+ 
+@@ -731,7 +763,7 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
+ 		list_add_tail(&seqid->list, &sequence->list);
+ 	if (list_first_entry(&sequence->list, struct nfs_seqid, list) == seqid)
+ 		goto unlock;
+-	rpc_sleep_on(&sequence->wait, task, NULL, NULL);
++	rpc_sleep_on(&sequence->wait, task, NULL);
+ 	status = -EAGAIN;
+ unlock:
+ 	spin_unlock(&sequence->lock);
+@@ -920,10 +952,10 @@ restart_loop:
+ 	if (cred != NULL) {
+ 		/* Yes there are: try to renew the old lease */
+ 		status = nfs4_proc_renew(clp, cred);
++		put_rpccred(cred);
+ 		switch (status) {
+ 			case 0:
+ 			case -NFS4ERR_CB_PATH_DOWN:
+-				put_rpccred(cred);
+ 				goto out;
+ 			case -NFS4ERR_STALE_CLIENTID:
+ 			case -NFS4ERR_LEASE_MOVED:
+@@ -932,14 +964,19 @@ restart_loop:
+ 	} else {
+ 		/* "reboot" to ensure we clear all state on the server */
+ 		clp->cl_boot_time = CURRENT_TIME;
+-		cred = nfs4_get_setclientid_cred(clp);
+ 	}
+ 	/* We're going to have to re-establish a clientid */
+ 	nfs4_state_mark_reclaim(clp);
+ 	status = -ENOENT;
++	cred = nfs4_get_setclientid_cred(clp);
+ 	if (cred != NULL) {
+ 		status = nfs4_init_client(clp, cred);
+ 		put_rpccred(cred);
++		/* Handle case where the user hasn't set up machine creds */
++		if (status == -EACCES && cred == clp->cl_machine_cred) {
++			nfs4_clear_machine_cred(clp);
++			goto restart_loop;
++		}
+ 	}
+ 	if (status)
+ 		goto out_error;
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index db1ed9c..5a2d649 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -110,7 +110,7 @@ static int nfs4_stat_to_errno(int);
+ #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
+ #define encode_restorefh_maxsz  (op_encode_hdr_maxsz)
+ #define decode_restorefh_maxsz  (op_decode_hdr_maxsz)
+-#define encode_fsinfo_maxsz	(op_encode_hdr_maxsz + 2)
++#define encode_fsinfo_maxsz	(encode_getattr_maxsz)
+ #define decode_fsinfo_maxsz	(op_decode_hdr_maxsz + 11)
+ #define encode_renew_maxsz	(op_encode_hdr_maxsz + 3)
+ #define decode_renew_maxsz	(op_decode_hdr_maxsz)
+@@ -1191,8 +1191,8 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
+ 		attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+ 	WRITE32(attrs[0] & readdir->bitmask[0]);
+ 	WRITE32(attrs[1] & readdir->bitmask[1]);
+-	dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n",
+-			__FUNCTION__,
++	dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
++			__func__,
+ 			(unsigned long long)readdir->cookie,
+ 			((u32 *)readdir->verifier.data)[0],
+ 			((u32 *)readdir->verifier.data)[1],
+@@ -2241,7 +2241,7 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
+ 	}
+ 	READ32(nfserr);
+ 	if (nfserr != NFS_OK)
+-		return -nfs4_stat_to_errno(nfserr);
++		return nfs4_stat_to_errno(nfserr);
+ 	return 0;
+ }
+ 
+@@ -2291,7 +2291,7 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3
+ 		bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
+ 	} else
+ 		bitmask[0] = bitmask[1] = 0;
+-	dprintk("%s: bitmask=0x%x%x\n", __FUNCTION__, bitmask[0], bitmask[1]);
++	dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
+ 	return 0;
+ }
+ 
+@@ -3005,6 +3005,8 @@ static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
+ 	int status;
+ 
+ 	status = decode_op_hdr(xdr, OP_CLOSE);
++	if (status != -EIO)
++		nfs_increment_open_seqid(status, res->seqid);
+ 	if (status)
+ 		return status;
+ 	READ_BUF(NFS4_STATEID_SIZE);
+@@ -3296,11 +3298,17 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
+ 	int status;
+ 
+ 	status = decode_op_hdr(xdr, OP_LOCK);
++	if (status == -EIO)
++		goto out;
+ 	if (status == 0) {
+ 		READ_BUF(NFS4_STATEID_SIZE);
+ 		COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
+ 	} else if (status == -NFS4ERR_DENIED)
+-		return decode_lock_denied(xdr, NULL);
++		status = decode_lock_denied(xdr, NULL);
++	if (res->open_seqid != NULL)
++		nfs_increment_open_seqid(status, res->open_seqid);
++	nfs_increment_lock_seqid(status, res->lock_seqid);
++out:
+ 	return status;
+ }
+ 
+@@ -3319,6 +3327,8 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
+ 	int status;
+ 
+ 	status = decode_op_hdr(xdr, OP_LOCKU);
++	if (status != -EIO)
++		nfs_increment_lock_seqid(status, res->seqid);
+ 	if (status == 0) {
+ 		READ_BUF(NFS4_STATEID_SIZE);
+ 		COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
+@@ -3384,6 +3394,8 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
+         int status;
+ 
+         status = decode_op_hdr(xdr, OP_OPEN);
++	if (status != -EIO)
++		nfs_increment_open_seqid(status, res->seqid);
+         if (status)
+                 return status;
+         READ_BUF(NFS4_STATEID_SIZE);
+@@ -3416,6 +3428,8 @@ static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmre
+ 	int status;
+ 
+         status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
++	if (status != -EIO)
++		nfs_increment_open_seqid(status, res->seqid);
+         if (status)
+                 return status;
+         READ_BUF(NFS4_STATEID_SIZE);
+@@ -3429,6 +3443,8 @@ static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *re
+ 	int status;
+ 
+ 	status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
++	if (status != -EIO)
++		nfs_increment_open_seqid(status, res->seqid);
+ 	if (status)
+ 		return status;
+ 	READ_BUF(NFS4_STATEID_SIZE);
+@@ -3481,7 +3497,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
+ 	size_t		hdrlen;
+ 	u32		recvd, pglen = rcvbuf->page_len;
+ 	__be32		*end, *entry, *p, *kaddr;
+-	unsigned int	nr;
++	unsigned int	nr = 0;
+ 	int		status;
+ 
+ 	status = decode_op_hdr(xdr, OP_READDIR);
+@@ -3489,8 +3505,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
+ 		return status;
+ 	READ_BUF(8);
+ 	COPYMEM(readdir->verifier.data, 8);
+-	dprintk("%s: verifier = 0x%x%x\n",
+-			__FUNCTION__,
++	dprintk("%s: verifier = %08x:%08x\n",
++			__func__,
+ 			((u32 *)readdir->verifier.data)[0],
+ 			((u32 *)readdir->verifier.data)[1]);
+ 
+@@ -3505,7 +3521,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
+ 	kaddr = p = kmap_atomic(page, KM_USER0);
+ 	end = p + ((pglen + readdir->pgbase) >> 2);
+ 	entry = p;
+-	for (nr = 0; *p++; nr++) {
++
++	/* Make sure the packet actually has a value_follows and EOF entry */
++	if ((entry + 1) > end)
++		goto short_pkt;
++
++	for (; *p++; nr++) {
+ 		u32 len, attrlen, xlen;
+ 		if (end - p < 3)
+ 			goto short_pkt;
+@@ -3532,20 +3553,32 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
+ 		p += attrlen;		/* attributes */
+ 		entry = p;
+ 	}
+-	if (!nr && (entry[0] != 0 || entry[1] == 0))
+-		goto short_pkt;
++	/*
++	 * Apparently some server sends responses that are a valid size, but
++	 * contain no entries, and have value_follows==0 and EOF==0. For
++	 * those, just set the EOF marker.
++	 */
++	if (!nr && entry[1] == 0) {
++		dprintk("NFS: readdir reply truncated!\n");
++		entry[1] = 1;
++	}
+ out:	
+ 	kunmap_atomic(kaddr, KM_USER0);
+ 	return 0;
+ short_pkt:
++	/*
++	 * When we get a short packet there are 2 possibilities. We can
++	 * return an error, or fix up the response to look like a valid
++	 * response and return what we have so far. If there are no
++	 * entries and the packet was short, then return -EIO. If there
++	 * are valid entries in the response, return them and pretend that
++	 * the call was successful, but incomplete. The caller can retry the
++	 * readdir starting at the last cookie.
++	 */
+ 	dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr);
+ 	entry[0] = entry[1] = 0;
+-	/* truncate listing ? */
+-	if (!nr) {
+-		dprintk("NFS: readdir reply truncated!\n");
+-		entry[1] = 1;
+-	}
+-	goto out;
++	if (nr)
++		goto out;
+ err_unmap:
+ 	kunmap_atomic(kaddr, KM_USER0);
+ 	return -errno_NFSERR_IO;
+@@ -3727,7 +3760,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp)
+ 		READ_BUF(len);
+ 		return -NFSERR_CLID_INUSE;
+ 	} else
+-		return -nfs4_stat_to_errno(nfserr);
++		return nfs4_stat_to_errno(nfserr);
+ 
+ 	return 0;
+ }
+@@ -4389,7 +4422,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
+ 	if (!status)
+ 		status = decode_fsinfo(&xdr, fsinfo);
+ 	if (!status)
+-		status = -nfs4_stat_to_errno(hdr.status);
++		status = nfs4_stat_to_errno(hdr.status);
+ 	return status;
+ }
+ 
+@@ -4479,7 +4512,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
+ 	if (!status)
+ 		status = decode_setclientid(&xdr, clp);
+ 	if (!status)
+-		status = -nfs4_stat_to_errno(hdr.status);
++		status = nfs4_stat_to_errno(hdr.status);
+ 	return status;
+ }
+ 
+@@ -4501,7 +4534,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
+ 	if (!status)
+ 		status = decode_fsinfo(&xdr, fsinfo);
+ 	if (!status)
+-		status = -nfs4_stat_to_errno(hdr.status);
++		status = nfs4_stat_to_errno(hdr.status);
+ 	return status;
+ }
+ 
+@@ -4611,42 +4644,42 @@ static struct {
+ 	int errno;
+ } nfs_errtbl[] = {
+ 	{ NFS4_OK,		0		},
+-	{ NFS4ERR_PERM,		EPERM		},
+-	{ NFS4ERR_NOENT,	ENOENT		},
+-	{ NFS4ERR_IO,		errno_NFSERR_IO	},
+-	{ NFS4ERR_NXIO,		ENXIO		},
+-	{ NFS4ERR_ACCESS,	EACCES		},
+-	{ NFS4ERR_EXIST,	EEXIST		},
+-	{ NFS4ERR_XDEV,		EXDEV		},
+-	{ NFS4ERR_NOTDIR,	ENOTDIR		},
+-	{ NFS4ERR_ISDIR,	EISDIR		},
+-	{ NFS4ERR_INVAL,	EINVAL		},
+-	{ NFS4ERR_FBIG,		EFBIG		},
+-	{ NFS4ERR_NOSPC,	ENOSPC		},
+-	{ NFS4ERR_ROFS,		EROFS		},
+-	{ NFS4ERR_MLINK,	EMLINK		},
+-	{ NFS4ERR_NAMETOOLONG,	ENAMETOOLONG	},
+-	{ NFS4ERR_NOTEMPTY,	ENOTEMPTY	},
+-	{ NFS4ERR_DQUOT,	EDQUOT		},
+-	{ NFS4ERR_STALE,	ESTALE		},
+-	{ NFS4ERR_BADHANDLE,	EBADHANDLE	},
+-	{ NFS4ERR_BADOWNER,	EINVAL		},
+-	{ NFS4ERR_BADNAME,	EINVAL		},
+-	{ NFS4ERR_BAD_COOKIE,	EBADCOOKIE	},
+-	{ NFS4ERR_NOTSUPP,	ENOTSUPP	},
+-	{ NFS4ERR_TOOSMALL,	ETOOSMALL	},
+-	{ NFS4ERR_SERVERFAULT,	ESERVERFAULT	},
+-	{ NFS4ERR_BADTYPE,	EBADTYPE	},
+-	{ NFS4ERR_LOCKED,	EAGAIN		},
+-	{ NFS4ERR_RESOURCE,	EREMOTEIO	},
+-	{ NFS4ERR_SYMLINK,	ELOOP		},
+-	{ NFS4ERR_OP_ILLEGAL,	EOPNOTSUPP	},
+-	{ NFS4ERR_DEADLOCK,	EDEADLK		},
+-	{ NFS4ERR_WRONGSEC,	EPERM		}, /* FIXME: this needs
++	{ NFS4ERR_PERM,		-EPERM		},
++	{ NFS4ERR_NOENT,	-ENOENT		},
++	{ NFS4ERR_IO,		-errno_NFSERR_IO},
++	{ NFS4ERR_NXIO,		-ENXIO		},
++	{ NFS4ERR_ACCESS,	-EACCES		},
++	{ NFS4ERR_EXIST,	-EEXIST		},
++	{ NFS4ERR_XDEV,		-EXDEV		},
++	{ NFS4ERR_NOTDIR,	-ENOTDIR	},
++	{ NFS4ERR_ISDIR,	-EISDIR		},
++	{ NFS4ERR_INVAL,	-EINVAL		},
++	{ NFS4ERR_FBIG,		-EFBIG		},
++	{ NFS4ERR_NOSPC,	-ENOSPC		},
++	{ NFS4ERR_ROFS,		-EROFS		},
++	{ NFS4ERR_MLINK,	-EMLINK		},
++	{ NFS4ERR_NAMETOOLONG,	-ENAMETOOLONG	},
++	{ NFS4ERR_NOTEMPTY,	-ENOTEMPTY	},
++	{ NFS4ERR_DQUOT,	-EDQUOT		},
++	{ NFS4ERR_STALE,	-ESTALE		},
++	{ NFS4ERR_BADHANDLE,	-EBADHANDLE	},
++	{ NFS4ERR_BADOWNER,	-EINVAL		},
++	{ NFS4ERR_BADNAME,	-EINVAL		},
++	{ NFS4ERR_BAD_COOKIE,	-EBADCOOKIE	},
++	{ NFS4ERR_NOTSUPP,	-ENOTSUPP	},
++	{ NFS4ERR_TOOSMALL,	-ETOOSMALL	},
++	{ NFS4ERR_SERVERFAULT,	-ESERVERFAULT	},
++	{ NFS4ERR_BADTYPE,	-EBADTYPE	},
++	{ NFS4ERR_LOCKED,	-EAGAIN		},
++	{ NFS4ERR_RESOURCE,	-EREMOTEIO	},
++	{ NFS4ERR_SYMLINK,	-ELOOP		},
++	{ NFS4ERR_OP_ILLEGAL,	-EOPNOTSUPP	},
++	{ NFS4ERR_DEADLOCK,	-EDEADLK	},
++	{ NFS4ERR_WRONGSEC,	-EPERM		}, /* FIXME: this needs
+ 						    * to be handled by a
+ 						    * middle-layer.
+ 						    */
+-	{ -1,			EIO		}
++	{ -1,			-EIO		}
+ };
+ 
+ /*
+@@ -4663,14 +4696,14 @@ nfs4_stat_to_errno(int stat)
+ 	}
+ 	if (stat <= 10000 || stat > 10100) {
+ 		/* The server is looney tunes. */
+-		return ESERVERFAULT;
++		return -ESERVERFAULT;
+ 	}
+ 	/* If we cannot translate the error, the recovery routines should
+ 	 * handle it.
+ 	 * Note: remaining NFSv4 error codes have values > 10000, so should
+ 	 * not conflict with native Linux error codes.
+ 	 */
+-	return stat;
++	return -stat;
+ }
+ 
+ #define PROC(proc, argtype, restype)				\
+diff --git a/fs/nfs/read.c b/fs/nfs/read.c
+index 5a70be5..16f57e0 100644
+--- a/fs/nfs/read.c
++++ b/fs/nfs/read.c
+@@ -58,22 +58,19 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
+ 	return p;
+ }
+ 
+-static void nfs_readdata_rcu_free(struct rcu_head *head)
++static void nfs_readdata_free(struct nfs_read_data *p)
+ {
+-	struct nfs_read_data *p = container_of(head, struct nfs_read_data, task.u.tk_rcu);
+ 	if (p && (p->pagevec != &p->page_array[0]))
+ 		kfree(p->pagevec);
+ 	mempool_free(p, nfs_rdata_mempool);
+ }
+ 
+-static void nfs_readdata_free(struct nfs_read_data *rdata)
+-{
+-	call_rcu_bh(&rdata->task.u.tk_rcu, nfs_readdata_rcu_free);
+-}
+-
+ void nfs_readdata_release(void *data)
+ {
+-        nfs_readdata_free(data);
++	struct nfs_read_data *rdata = data;
++
++	put_nfs_open_context(rdata->args.context);
++	nfs_readdata_free(rdata);
+ }
+ 
+ static
+@@ -156,7 +153,7 @@ static void nfs_readpage_release(struct nfs_page *req)
+ /*
+  * Set up the NFS read request struct
+  */
+-static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
++static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+ 		const struct rpc_call_ops *call_ops,
+ 		unsigned int count, unsigned int offset)
+ {
+@@ -174,6 +171,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+ 		.rpc_message = &msg,
+ 		.callback_ops = call_ops,
+ 		.callback_data = data,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = RPC_TASK_ASYNC | swap_flags,
+ 	};
+ 
+@@ -186,7 +184,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+ 	data->args.pgbase = req->wb_pgbase + offset;
+ 	data->args.pages  = data->pagevec;
+ 	data->args.count  = count;
+-	data->args.context = req->wb_context;
++	data->args.context = get_nfs_open_context(req->wb_context);
+ 
+ 	data->res.fattr   = &data->fattr;
+ 	data->res.count   = count;
+@@ -204,8 +202,10 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+ 			(unsigned long long)data->args.offset);
+ 
+ 	task = rpc_run_task(&task_setup_data);
+-	if (!IS_ERR(task))
+-		rpc_put_task(task);
++	if (IS_ERR(task))
++		return PTR_ERR(task);
++	rpc_put_task(task);
++	return 0;
+ }
+ 
+ static void
+@@ -242,6 +242,7 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
+ 	size_t rsize = NFS_SERVER(inode)->rsize, nbytes;
+ 	unsigned int offset;
+ 	int requests = 0;
++	int ret = 0;
+ 	LIST_HEAD(list);
+ 
+ 	nfs_list_remove_request(req);
+@@ -253,7 +254,6 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
+ 		data = nfs_readdata_alloc(1);
+ 		if (!data)
+ 			goto out_bad;
+-		INIT_LIST_HEAD(&data->pages);
+ 		list_add(&data->pages, &list);
+ 		requests++;
+ 		nbytes -= len;
+@@ -264,6 +264,8 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
+ 	offset = 0;
+ 	nbytes = count;
+ 	do {
++		int ret2;
++
+ 		data = list_entry(list.next, struct nfs_read_data, pages);
+ 		list_del_init(&data->pages);
+ 
+@@ -271,13 +273,15 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
+ 
+ 		if (nbytes < rsize)
+ 			rsize = nbytes;
+-		nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
++		ret2 = nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
+ 				  rsize, offset);
++		if (ret == 0)
++			ret = ret2;
+ 		offset += rsize;
+ 		nbytes -= rsize;
+ 	} while (nbytes != 0);
+ 
+-	return 0;
++	return ret;
+ 
+ out_bad:
+ 	while (!list_empty(&list)) {
+@@ -295,12 +299,12 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
+ 	struct nfs_page		*req;
+ 	struct page		**pages;
+ 	struct nfs_read_data	*data;
++	int ret = -ENOMEM;
+ 
+ 	data = nfs_readdata_alloc(npages);
+ 	if (!data)
+ 		goto out_bad;
+ 
+-	INIT_LIST_HEAD(&data->pages);
+ 	pages = data->pagevec;
+ 	while (!list_empty(head)) {
+ 		req = nfs_list_entry(head->next);
+@@ -311,11 +315,10 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
+ 	}
+ 	req = nfs_list_entry(data->pages.next);
+ 
+-	nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
+-	return 0;
++	return nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
+ out_bad:
+ 	nfs_async_read_error(head);
+-	return -ENOMEM;
++	return ret;
+ }
+ 
+ /*
+@@ -342,26 +345,25 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
+ 	return 0;
+ }
+ 
+-static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
++static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
+ {
+ 	struct nfs_readargs *argp = &data->args;
+ 	struct nfs_readres *resp = &data->res;
+ 
+ 	if (resp->eof || resp->count == argp->count)
+-		return 0;
++		return;
+ 
+ 	/* This is a short read! */
+ 	nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
+ 	/* Has the server at least made some progress? */
+ 	if (resp->count == 0)
+-		return 0;
++		return;
+ 
+ 	/* Yes, so retry the read at the end of the data */
+ 	argp->offset += resp->count;
+ 	argp->pgbase += resp->count;
+ 	argp->count -= resp->count;
+ 	rpc_restart_call(task);
+-	return -EAGAIN;
+ }
+ 
+ /*
+@@ -370,29 +372,37 @@ static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
+ static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs_read_data *data = calldata;
+-	struct nfs_page *req = data->req;
+-	struct page *page = req->wb_page;
+  
+ 	if (nfs_readpage_result(task, data) != 0)
+ 		return;
++	if (task->tk_status < 0)
++		return;
+ 
+-	if (likely(task->tk_status >= 0)) {
+-		nfs_readpage_truncate_uninitialised_page(data);
+-		if (nfs_readpage_retry(task, data) != 0)
+-			return;
+-	}
+-	if (unlikely(task->tk_status < 0))
++	nfs_readpage_truncate_uninitialised_page(data);
++	nfs_readpage_retry(task, data);
++}
++
++static void nfs_readpage_release_partial(void *calldata)
++{
++	struct nfs_read_data *data = calldata;
++	struct nfs_page *req = data->req;
++	struct page *page = req->wb_page;
++	int status = data->task.tk_status;
++
++	if (status < 0)
+ 		SetPageError(page);
++
+ 	if (atomic_dec_and_test(&req->wb_complete)) {
+ 		if (!PageError(page))
+ 			SetPageUptodate(page);
+ 		nfs_readpage_release(req);
+ 	}
++	nfs_readdata_release(calldata);
+ }
+ 
+ static const struct rpc_call_ops nfs_read_partial_ops = {
+ 	.rpc_call_done = nfs_readpage_result_partial,
+-	.rpc_release = nfs_readdata_release,
++	.rpc_release = nfs_readpage_release_partial,
+ };
+ 
+ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data)
+@@ -427,29 +437,35 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
+ 
+ 	if (nfs_readpage_result(task, data) != 0)
+ 		return;
++	if (task->tk_status < 0)
++		return;
+ 	/*
+ 	 * Note: nfs_readpage_retry may change the values of
+ 	 * data->args. In the multi-page case, we therefore need
+ 	 * to ensure that we call nfs_readpage_set_pages_uptodate()
+ 	 * first.
+ 	 */
+-	if (likely(task->tk_status >= 0)) {
+-		nfs_readpage_truncate_uninitialised_page(data);
+-		nfs_readpage_set_pages_uptodate(data);
+-		if (nfs_readpage_retry(task, data) != 0)
+-			return;
+-	}
++	nfs_readpage_truncate_uninitialised_page(data);
++	nfs_readpage_set_pages_uptodate(data);
++	nfs_readpage_retry(task, data);
++}
++
++static void nfs_readpage_release_full(void *calldata)
++{
++	struct nfs_read_data *data = calldata;
++
+ 	while (!list_empty(&data->pages)) {
+ 		struct nfs_page *req = nfs_list_entry(data->pages.next);
+ 
+ 		nfs_list_remove_request(req);
+ 		nfs_readpage_release(req);
+ 	}
++	nfs_readdata_release(calldata);
+ }
+ 
+ static const struct rpc_call_ops nfs_read_full_ops = {
+ 	.rpc_call_done = nfs_readpage_result_full,
+-	.rpc_release = nfs_readdata_release,
++	.rpc_release = nfs_readpage_release_full,
+ };
+ 
+ /*
+diff --git a/fs/nfs/super.c b/fs/nfs/super.c
+index f921902..fa220dc 100644
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -198,7 +198,7 @@ static match_table_t nfs_secflavor_tokens = {
+ };
+ 
+ 
+-static void nfs_umount_begin(struct vfsmount *, int);
++static void nfs_umount_begin(struct super_block *);
+ static int  nfs_statfs(struct dentry *, struct kstatfs *);
+ static int  nfs_show_options(struct seq_file *, struct vfsmount *);
+ static int  nfs_show_stats(struct seq_file *, struct vfsmount *);
+@@ -441,10 +441,52 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
+ 	return sec_flavours[i].str;
+ }
+ 
++static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
++				    int showdefaults)
++{
++	struct sockaddr *sap = (struct sockaddr *)&nfss->mountd_address;
++
++	switch (sap->sa_family) {
++	case AF_INET: {
++		struct sockaddr_in *sin = (struct sockaddr_in *)sap;
++		seq_printf(m, ",mountaddr=" NIPQUAD_FMT,
++				NIPQUAD(sin->sin_addr.s_addr));
++		break;
++	}
++	case AF_INET6: {
++		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
++		seq_printf(m, ",mountaddr=" NIP6_FMT,
++				NIP6(sin6->sin6_addr));
++		break;
++	}
++	default:
++		if (showdefaults)
++			seq_printf(m, ",mountaddr=unspecified");
++	}
++
++	if (nfss->mountd_version || showdefaults)
++		seq_printf(m, ",mountvers=%u", nfss->mountd_version);
++	if (nfss->mountd_port || showdefaults)
++		seq_printf(m, ",mountport=%u", nfss->mountd_port);
++
++	switch (nfss->mountd_protocol) {
++	case IPPROTO_UDP:
++		seq_printf(m, ",mountproto=udp");
++		break;
++	case IPPROTO_TCP:
++		seq_printf(m, ",mountproto=tcp");
++		break;
++	default:
++		if (showdefaults)
++			seq_printf(m, ",mountproto=auto");
++	}
++}
++
+ /*
+  * Describe the mount options in force on this server representation
+  */
+-static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
++static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
++				   int showdefaults)
+ {
+ 	static const struct proc_nfs_info {
+ 		int flag;
+@@ -452,6 +494,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
+ 		const char *nostr;
+ 	} nfs_info[] = {
+ 		{ NFS_MOUNT_SOFT, ",soft", ",hard" },
++		{ NFS_MOUNT_INTR, ",intr", ",nointr" },
++		{ NFS_MOUNT_POSIX, ",posix", "" },
+ 		{ NFS_MOUNT_NOCTO, ",nocto", "" },
+ 		{ NFS_MOUNT_NOAC, ",noac", "" },
+ 		{ NFS_MOUNT_NONLM, ",nolock", "" },
+@@ -462,18 +506,22 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
+ 	};
+ 	const struct proc_nfs_info *nfs_infop;
+ 	struct nfs_client *clp = nfss->nfs_client;
+-
+-	seq_printf(m, ",vers=%d", clp->rpc_ops->version);
+-	seq_printf(m, ",rsize=%d", nfss->rsize);
+-	seq_printf(m, ",wsize=%d", nfss->wsize);
++	u32 version = clp->rpc_ops->version;
++
++	seq_printf(m, ",vers=%u", version);
++	seq_printf(m, ",rsize=%u", nfss->rsize);
++	seq_printf(m, ",wsize=%u", nfss->wsize);
++	if (nfss->bsize != 0)
++		seq_printf(m, ",bsize=%u", nfss->bsize);
++	seq_printf(m, ",namlen=%u", nfss->namelen);
+ 	if (nfss->acregmin != 3*HZ || showdefaults)
+-		seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
++		seq_printf(m, ",acregmin=%u", nfss->acregmin/HZ);
+ 	if (nfss->acregmax != 60*HZ || showdefaults)
+-		seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
++		seq_printf(m, ",acregmax=%u", nfss->acregmax/HZ);
+ 	if (nfss->acdirmin != 30*HZ || showdefaults)
+-		seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
++		seq_printf(m, ",acdirmin=%u", nfss->acdirmin/HZ);
+ 	if (nfss->acdirmax != 60*HZ || showdefaults)
+-		seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
++		seq_printf(m, ",acdirmax=%u", nfss->acdirmax/HZ);
+ 	for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
+ 		if (nfss->flags & nfs_infop->flag)
+ 			seq_puts(m, nfs_infop->str);
+@@ -482,9 +530,24 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
+ 	}
+ 	seq_printf(m, ",proto=%s",
+ 		   rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO));
++	if (version == 4) {
++		if (nfss->port != NFS_PORT)
++			seq_printf(m, ",port=%u", nfss->port);
++	} else
++		if (nfss->port)
++			seq_printf(m, ",port=%u", nfss->port);
++
+ 	seq_printf(m, ",timeo=%lu", 10U * nfss->client->cl_timeout->to_initval / HZ);
+ 	seq_printf(m, ",retrans=%u", nfss->client->cl_timeout->to_retries);
+ 	seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
++
++	if (version != 4)
++		nfs_show_mountd_options(m, nfss, showdefaults);
++
++#ifdef CONFIG_NFS_V4
++	if (clp->rpc_ops->version == 4)
++		seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
++#endif
+ }
+ 
+ /*
+@@ -529,10 +592,10 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+ 
+ 	seq_printf(m, "\n\tcaps:\t");
+ 	seq_printf(m, "caps=0x%x", nfss->caps);
+-	seq_printf(m, ",wtmult=%d", nfss->wtmult);
+-	seq_printf(m, ",dtsize=%d", nfss->dtsize);
+-	seq_printf(m, ",bsize=%d", nfss->bsize);
+-	seq_printf(m, ",namelen=%d", nfss->namelen);
++	seq_printf(m, ",wtmult=%u", nfss->wtmult);
++	seq_printf(m, ",dtsize=%u", nfss->dtsize);
++	seq_printf(m, ",bsize=%u", nfss->bsize);
++	seq_printf(m, ",namlen=%u", nfss->namelen);
+ 
+ #ifdef CONFIG_NFS_V4
+ 	if (nfss->nfs_client->rpc_ops->version == 4) {
+@@ -546,9 +609,9 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+ 	/*
+ 	 * Display security flavor in effect for this mount
+ 	 */
+-	seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
++	seq_printf(m, "\n\tsec:\tflavor=%u", auth->au_ops->au_flavor);
+ 	if (auth->au_flavor)
+-		seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
++		seq_printf(m, ",pseudoflavor=%u", auth->au_flavor);
+ 
+ 	/*
+ 	 * Display superblock I/O counters
+@@ -584,13 +647,11 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+  * Begin unmount by attempting to remove all automounted mountpoints we added
+  * in response to xdev traversals and referrals
+  */
+-static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
++static void nfs_umount_begin(struct super_block *sb)
+ {
+-	struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
++	struct nfs_server *server = NFS_SB(sb);
+ 	struct rpc_clnt *rpc;
+ 
+-	if (!(flags & MNT_FORCE))
+-		return;
+ 	/* -EIO all pending I/O */
+ 	rpc = server->client_acl;
+ 	if (!IS_ERR(rpc))
+@@ -683,7 +744,6 @@ static int nfs_parse_mount_options(char *raw,
+ 				   struct nfs_parsed_mount_data *mnt)
+ {
+ 	char *p, *string, *secdata;
+-	unsigned short port = 0;
+ 	int rc;
+ 
+ 	if (!raw) {
+@@ -798,7 +858,7 @@ static int nfs_parse_mount_options(char *raw,
+ 				return 0;
+ 			if (option < 0 || option > 65535)
+ 				return 0;
+-			port = option;
++			mnt->nfs_server.port = option;
+ 			break;
+ 		case Opt_rsize:
+ 			if (match_int(args, &mnt->rsize))
+@@ -1048,7 +1108,8 @@ static int nfs_parse_mount_options(char *raw,
+ 		}
+ 	}
+ 
+-	nfs_set_port((struct sockaddr *)&mnt->nfs_server.address, port);
++	nfs_set_port((struct sockaddr *)&mnt->nfs_server.address,
++				mnt->nfs_server.port);
+ 
+ 	return 1;
+ 
+@@ -1169,7 +1230,9 @@ static int nfs_validate_mount_data(void *options,
+ 	args->acregmax		= 60;
+ 	args->acdirmin		= 30;
+ 	args->acdirmax		= 60;
++	args->mount_server.port	= 0;	/* autobind unless user sets port */
+ 	args->mount_server.protocol = XPRT_TRANSPORT_UDP;
++	args->nfs_server.port	= 0;	/* autobind unless user sets port */
+ 	args->nfs_server.protocol = XPRT_TRANSPORT_TCP;
+ 
+ 	switch (data->version) {
+@@ -1208,7 +1271,6 @@ static int nfs_validate_mount_data(void *options,
+ 		args->flags		= data->flags;
+ 		args->rsize		= data->rsize;
+ 		args->wsize		= data->wsize;
+-		args->flags		= data->flags;
+ 		args->timeo		= data->timeo;
+ 		args->retrans		= data->retrans;
+ 		args->acregmin		= data->acregmin;
+@@ -1230,6 +1292,8 @@ static int nfs_validate_mount_data(void *options,
+ 		args->namlen		= data->namlen;
+ 		args->bsize		= data->bsize;
+ 		args->auth_flavors[0]	= data->pseudoflavor;
++		if (!args->nfs_server.hostname)
++			goto out_nomem;
+ 
+ 		/*
+ 		 * The legacy version 6 binary mount data from userspace has a
+@@ -1276,6 +1340,8 @@ static int nfs_validate_mount_data(void *options,
+ 		len = c - dev_name;
+ 		/* N.B. caller will free nfs_server.hostname in all cases */
+ 		args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL);
++		if (!args->nfs_server.hostname)
++			goto out_nomem;
+ 
+ 		c++;
+ 		if (strlen(c) > NFS_MAXPATHLEN)
+@@ -1319,6 +1385,10 @@ out_v3_not_compiled:
+ 	return -EPROTONOSUPPORT;
+ #endif /* !CONFIG_NFS_V3 */
+ 
++out_nomem:
++	dfprintk(MOUNT, "NFS: not enough memory to handle mount options\n");
++	return -ENOMEM;
++
+ out_no_address:
+ 	dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n");
+ 	return -EINVAL;
+@@ -1706,28 +1776,6 @@ static void nfs4_fill_super(struct super_block *sb)
+ }
+ 
+ /*
+- * If the user didn't specify a port, set the port number to
+- * the NFS version 4 default port.
+- */
+-static void nfs4_default_port(struct sockaddr *sap)
+-{
+-	switch (sap->sa_family) {
+-	case AF_INET: {
+-		struct sockaddr_in *ap = (struct sockaddr_in *)sap;
+-		if (ap->sin_port == 0)
+-			ap->sin_port = htons(NFS_PORT);
+-		break;
+-	}
+-	case AF_INET6: {
+-		struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
+-		if (ap->sin6_port == 0)
+-			ap->sin6_port = htons(NFS_PORT);
+-		break;
+-	}
+-	}
+-}
+-
+-/*
+  * Validate NFSv4 mount options
+  */
+ static int nfs4_validate_mount_data(void *options,
+@@ -1751,6 +1799,7 @@ static int nfs4_validate_mount_data(void *options,
+ 	args->acregmax		= 60;
+ 	args->acdirmin		= 30;
+ 	args->acdirmax		= 60;
++	args->nfs_server.port	= NFS_PORT; /* 2049 unless user set port= */
+ 	args->nfs_server.protocol = XPRT_TRANSPORT_TCP;
+ 
+ 	switch (data->version) {
+@@ -1767,9 +1816,6 @@ static int nfs4_validate_mount_data(void *options,
+ 						&args->nfs_server.address))
+ 			goto out_no_address;
+ 
+-		nfs4_default_port((struct sockaddr *)
+-				  &args->nfs_server.address);
+-
+ 		switch (data->auth_flavourlen) {
+ 		case 0:
+ 			args->auth_flavors[0] = RPC_AUTH_UNIX;
+@@ -1827,9 +1873,6 @@ static int nfs4_validate_mount_data(void *options,
+ 						&args->nfs_server.address))
+ 			return -EINVAL;
+ 
+-		nfs4_default_port((struct sockaddr *)
+-				  &args->nfs_server.address);
+-
+ 		switch (args->auth_flavor_len) {
+ 		case 0:
+ 			args->auth_flavors[0] = RPC_AUTH_UNIX;
+@@ -1852,12 +1895,16 @@ static int nfs4_validate_mount_data(void *options,
+ 			return -ENAMETOOLONG;
+ 		/* N.B. caller will free nfs_server.hostname in all cases */
+ 		args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL);
++		if (!args->nfs_server.hostname)
++			goto out_nomem;
+ 
+ 		c++;			/* step over the ':' */
+ 		len = strlen(c);
+ 		if (len > NFS4_MAXPATHLEN)
+ 			return -ENAMETOOLONG;
+ 		args->nfs_server.export_path = kstrndup(c, len, GFP_KERNEL);
++		if (!args->nfs_server.export_path)
++			goto out_nomem;
+ 
+ 		dprintk("NFS: MNTPATH: '%s'\n", args->nfs_server.export_path);
+ 
+@@ -1879,6 +1926,10 @@ out_inval_auth:
+ 		 data->auth_flavourlen);
+ 	return -EINVAL;
+ 
++out_nomem:
++	dfprintk(MOUNT, "NFS4: not enough memory to handle mount options\n");
++	return -ENOMEM;
++
+ out_no_address:
+ 	dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
+ 	return -EINVAL;
+diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
+index 83e865a..412738d 100644
+--- a/fs/nfs/symlink.c
++++ b/fs/nfs/symlink.c
+@@ -10,7 +10,6 @@
+  *  nfs symlink handling code
+  */
+ 
+-#define NFS_NEED_XDR_TYPES
+ #include <linux/time.h>
+ #include <linux/errno.h>
+ #include <linux/sunrpc/clnt.h>
+diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
+index 7574153..3adf8b2 100644
+--- a/fs/nfs/unlink.c
++++ b/fs/nfs/unlink.c
+@@ -234,7 +234,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
+ 	if (data == NULL)
+ 		goto out;
+ 
+-	data->cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
++	data->cred = rpc_lookup_cred();
+ 	if (IS_ERR(data->cred)) {
+ 		status = PTR_ERR(data->cred);
+ 		goto out_free;
+diff --git a/fs/nfs/write.c b/fs/nfs/write.c
+index bed6341..1ade11d 100644
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -48,7 +48,7 @@ static struct kmem_cache *nfs_wdata_cachep;
+ static mempool_t *nfs_wdata_mempool;
+ static mempool_t *nfs_commit_mempool;
+ 
+-struct nfs_write_data *nfs_commit_alloc(void)
++struct nfs_write_data *nfs_commitdata_alloc(void)
+ {
+ 	struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS);
+ 
+@@ -59,19 +59,13 @@ struct nfs_write_data *nfs_commit_alloc(void)
+ 	return p;
+ }
+ 
+-static void nfs_commit_rcu_free(struct rcu_head *head)
++void nfs_commit_free(struct nfs_write_data *p)
+ {
+-	struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
+ 	if (p && (p->pagevec != &p->page_array[0]))
+ 		kfree(p->pagevec);
+ 	mempool_free(p, nfs_commit_mempool);
+ }
+ 
+-void nfs_commit_free(struct nfs_write_data *wdata)
+-{
+-	call_rcu_bh(&wdata->task.u.tk_rcu, nfs_commit_rcu_free);
+-}
+-
+ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
+ {
+ 	struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS);
+@@ -93,21 +87,18 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
+ 	return p;
+ }
+ 
+-static void nfs_writedata_rcu_free(struct rcu_head *head)
++static void nfs_writedata_free(struct nfs_write_data *p)
+ {
+-	struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
+ 	if (p && (p->pagevec != &p->page_array[0]))
+ 		kfree(p->pagevec);
+ 	mempool_free(p, nfs_wdata_mempool);
+ }
+ 
+-static void nfs_writedata_free(struct nfs_write_data *wdata)
++void nfs_writedata_release(void *data)
+ {
+-	call_rcu_bh(&wdata->task.u.tk_rcu, nfs_writedata_rcu_free);
+-}
++	struct nfs_write_data *wdata = data;
+ 
+-void nfs_writedata_release(void *wdata)
+-{
++	put_nfs_open_context(wdata->args.context);
+ 	nfs_writedata_free(wdata);
+ }
+ 
+@@ -291,8 +282,6 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
+ 	spin_unlock(&inode->i_lock);
+ 	if (!nfs_pageio_add_request(pgio, req)) {
+ 		nfs_redirty_request(req);
+-		nfs_end_page_writeback(page);
+-		nfs_clear_page_tag_locked(req);
+ 		return pgio->pg_error;
+ 	}
+ 	return 0;
+@@ -366,15 +355,13 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
+ /*
+  * Insert a write request into an inode
+  */
+-static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
++static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
+ {
+ 	struct nfs_inode *nfsi = NFS_I(inode);
+ 	int error;
+ 
+ 	error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req);
+-	BUG_ON(error == -EEXIST);
+-	if (error)
+-		return error;
++	BUG_ON(error);
+ 	if (!nfsi->npages) {
+ 		igrab(inode);
+ 		if (nfs_have_delegation(inode, FMODE_WRITE))
+@@ -384,8 +371,8 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
+ 	set_page_private(req->wb_page, (unsigned long)req);
+ 	nfsi->npages++;
+ 	kref_get(&req->wb_kref);
+-	radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
+-	return 0;
++	radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
++				NFS_PAGE_TAG_LOCKED);
+ }
+ 
+ /*
+@@ -413,7 +400,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
+ }
+ 
+ static void
+-nfs_redirty_request(struct nfs_page *req)
++nfs_mark_request_dirty(struct nfs_page *req)
+ {
+ 	__set_page_dirty_nobuffers(req->wb_page);
+ }
+@@ -467,7 +454,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req)
+ 		return 1;
+ 	}
+ 	if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) {
+-		nfs_redirty_request(req);
++		nfs_mark_request_dirty(req);
+ 		return 1;
+ 	}
+ 	return 0;
+@@ -597,6 +584,13 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
+ 		/* Loop over all inode entries and see if we find
+ 		 * A request for the page we wish to update
+ 		 */
++		if (new) {
++			if (radix_tree_preload(GFP_NOFS)) {
++				nfs_release_request(new);
++				return ERR_PTR(-ENOMEM);
++			}
++		}
++
+ 		spin_lock(&inode->i_lock);
+ 		req = nfs_page_find_request_locked(page);
+ 		if (req) {
+@@ -607,28 +601,27 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
+ 				error = nfs_wait_on_request(req);
+ 				nfs_release_request(req);
+ 				if (error < 0) {
+-					if (new)
++					if (new) {
++						radix_tree_preload_end();
+ 						nfs_release_request(new);
++					}
+ 					return ERR_PTR(error);
+ 				}
+ 				continue;
+ 			}
+ 			spin_unlock(&inode->i_lock);
+-			if (new)
++			if (new) {
++				radix_tree_preload_end();
+ 				nfs_release_request(new);
++			}
+ 			break;
+ 		}
+ 
+ 		if (new) {
+-			int error;
+ 			nfs_lock_request_dontget(new);
+-			error = nfs_inode_add_request(inode, new);
+-			if (error) {
+-				spin_unlock(&inode->i_lock);
+-				nfs_unlock_request(new);
+-				return ERR_PTR(error);
+-			}
++			nfs_inode_add_request(inode, new);
+ 			spin_unlock(&inode->i_lock);
++			radix_tree_preload_end();
+ 			req = new;
+ 			goto zero_page;
+ 		}
+@@ -785,7 +778,7 @@ static int flush_task_priority(int how)
+ /*
+  * Set up the argument/result storage required for the RPC call.
+  */
+-static void nfs_write_rpcsetup(struct nfs_page *req,
++static int nfs_write_rpcsetup(struct nfs_page *req,
+ 		struct nfs_write_data *data,
+ 		const struct rpc_call_ops *call_ops,
+ 		unsigned int count, unsigned int offset,
+@@ -806,6 +799,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+ 		.rpc_message = &msg,
+ 		.callback_ops = call_ops,
+ 		.callback_data = data,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = flags,
+ 		.priority = priority,
+ 	};
+@@ -822,7 +816,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+ 	data->args.pgbase = req->wb_pgbase + offset;
+ 	data->args.pages  = data->pagevec;
+ 	data->args.count  = count;
+-	data->args.context = req->wb_context;
++	data->args.context = get_nfs_open_context(req->wb_context);
+ 	data->args.stable  = NFS_UNSTABLE;
+ 	if (how & FLUSH_STABLE) {
+ 		data->args.stable = NFS_DATA_SYNC;
+@@ -847,8 +841,21 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+ 		(unsigned long long)data->args.offset);
+ 
+ 	task = rpc_run_task(&task_setup_data);
+-	if (!IS_ERR(task))
+-		rpc_put_task(task);
++	if (IS_ERR(task))
++		return PTR_ERR(task);
++	rpc_put_task(task);
++	return 0;
++}
++
++/* If a nfs_flush_* function fails, it should remove reqs from @head and
++ * call this on each, which will prepare them to be retried on next
++ * writeback using standard nfs.
++ */
++static void nfs_redirty_request(struct nfs_page *req)
++{
++	nfs_mark_request_dirty(req);
++	nfs_end_page_writeback(req->wb_page);
++	nfs_clear_page_tag_locked(req);
+ }
+ 
+ /*
+@@ -863,6 +870,7 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
+ 	size_t wsize = NFS_SERVER(inode)->wsize, nbytes;
+ 	unsigned int offset;
+ 	int requests = 0;
++	int ret = 0;
+ 	LIST_HEAD(list);
+ 
+ 	nfs_list_remove_request(req);
+@@ -884,6 +892,8 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
+ 	offset = 0;
+ 	nbytes = count;
+ 	do {
++		int ret2;
++
+ 		data = list_entry(list.next, struct nfs_write_data, pages);
+ 		list_del_init(&data->pages);
+ 
+@@ -891,13 +901,15 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
+ 
+ 		if (nbytes < wsize)
+ 			wsize = nbytes;
+-		nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
++		ret2 = nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
+ 				   wsize, offset, how);
++		if (ret == 0)
++			ret = ret2;
+ 		offset += wsize;
+ 		nbytes -= wsize;
+ 	} while (nbytes != 0);
+ 
+-	return 0;
++	return ret;
+ 
+ out_bad:
+ 	while (!list_empty(&list)) {
+@@ -906,8 +918,6 @@ out_bad:
+ 		nfs_writedata_release(data);
+ 	}
+ 	nfs_redirty_request(req);
+-	nfs_end_page_writeback(req->wb_page);
+-	nfs_clear_page_tag_locked(req);
+ 	return -ENOMEM;
+ }
+ 
+@@ -940,16 +950,12 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
+ 	req = nfs_list_entry(data->pages.next);
+ 
+ 	/* Set up the argument struct */
+-	nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
+-
+-	return 0;
++	return nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
+  out_bad:
+ 	while (!list_empty(head)) {
+ 		req = nfs_list_entry(head->next);
+ 		nfs_list_remove_request(req);
+ 		nfs_redirty_request(req);
+-		nfs_end_page_writeback(req->wb_page);
+-		nfs_clear_page_tag_locked(req);
+ 	}
+ 	return -ENOMEM;
+ }
+@@ -972,7 +978,6 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs_write_data	*data = calldata;
+ 	struct nfs_page		*req = data->req;
+-	struct page		*page = req->wb_page;
+ 
+ 	dprintk("NFS: write (%s/%Ld %d@%Ld)",
+ 		req->wb_context->path.dentry->d_inode->i_sb->s_id,
+@@ -980,13 +985,20 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
+ 		req->wb_bytes,
+ 		(long long)req_offset(req));
+ 
+-	if (nfs_writeback_done(task, data) != 0)
+-		return;
++	nfs_writeback_done(task, data);
++}
+ 
+-	if (task->tk_status < 0) {
++static void nfs_writeback_release_partial(void *calldata)
++{
++	struct nfs_write_data	*data = calldata;
++	struct nfs_page		*req = data->req;
++	struct page		*page = req->wb_page;
++	int status = data->task.tk_status;
++
++	if (status < 0) {
+ 		nfs_set_pageerror(page);
+-		nfs_context_set_write_error(req->wb_context, task->tk_status);
+-		dprintk(", error = %d\n", task->tk_status);
++		nfs_context_set_write_error(req->wb_context, status);
++		dprintk(", error = %d\n", status);
+ 		goto out;
+ 	}
+ 
+@@ -1011,11 +1023,12 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
+ out:
+ 	if (atomic_dec_and_test(&req->wb_complete))
+ 		nfs_writepage_release(req);
++	nfs_writedata_release(calldata);
+ }
+ 
+ static const struct rpc_call_ops nfs_write_partial_ops = {
+ 	.rpc_call_done = nfs_writeback_done_partial,
+-	.rpc_release = nfs_writedata_release,
++	.rpc_release = nfs_writeback_release_partial,
+ };
+ 
+ /*
+@@ -1028,17 +1041,21 @@ static const struct rpc_call_ops nfs_write_partial_ops = {
+ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs_write_data	*data = calldata;
+-	struct nfs_page		*req;
+-	struct page		*page;
+ 
+-	if (nfs_writeback_done(task, data) != 0)
+-		return;
++	nfs_writeback_done(task, data);
++}
++
++static void nfs_writeback_release_full(void *calldata)
++{
++	struct nfs_write_data	*data = calldata;
++	int status = data->task.tk_status;
+ 
+ 	/* Update attributes as result of writeback. */
+ 	while (!list_empty(&data->pages)) {
+-		req = nfs_list_entry(data->pages.next);
++		struct nfs_page *req = nfs_list_entry(data->pages.next);
++		struct page *page = req->wb_page;
++
+ 		nfs_list_remove_request(req);
+-		page = req->wb_page;
+ 
+ 		dprintk("NFS: write (%s/%Ld %d@%Ld)",
+ 			req->wb_context->path.dentry->d_inode->i_sb->s_id,
+@@ -1046,10 +1063,10 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
+ 			req->wb_bytes,
+ 			(long long)req_offset(req));
+ 
+-		if (task->tk_status < 0) {
++		if (status < 0) {
+ 			nfs_set_pageerror(page);
+-			nfs_context_set_write_error(req->wb_context, task->tk_status);
+-			dprintk(", error = %d\n", task->tk_status);
++			nfs_context_set_write_error(req->wb_context, status);
++			dprintk(", error = %d\n", status);
+ 			goto remove_request;
+ 		}
+ 
+@@ -1069,11 +1086,12 @@ remove_request:
+ 	next:
+ 		nfs_clear_page_tag_locked(req);
+ 	}
++	nfs_writedata_release(calldata);
+ }
+ 
+ static const struct rpc_call_ops nfs_write_full_ops = {
+ 	.rpc_call_done = nfs_writeback_done_full,
+-	.rpc_release = nfs_writedata_release,
++	.rpc_release = nfs_writeback_release_full,
+ };
+ 
+ 
+@@ -1159,15 +1177,18 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
+ 
+ 
+ #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+-void nfs_commit_release(void *wdata)
++void nfs_commitdata_release(void *data)
+ {
++	struct nfs_write_data *wdata = data;
++
++	put_nfs_open_context(wdata->args.context);
+ 	nfs_commit_free(wdata);
+ }
+ 
+ /*
+  * Set up the argument/result storage required for the RPC call.
+  */
+-static void nfs_commit_rpcsetup(struct list_head *head,
++static int nfs_commit_rpcsetup(struct list_head *head,
+ 		struct nfs_write_data *data,
+ 		int how)
+ {
+@@ -1187,6 +1208,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
+ 		.rpc_message = &msg,
+ 		.callback_ops = &nfs_commit_ops,
+ 		.callback_data = data,
++		.workqueue = nfsiod_workqueue,
+ 		.flags = flags,
+ 		.priority = priority,
+ 	};
+@@ -1203,6 +1225,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
+ 	/* Note: we always request a commit of the entire inode */
+ 	data->args.offset = 0;
+ 	data->args.count  = 0;
++	data->args.context = get_nfs_open_context(first->wb_context);
+ 	data->res.count   = 0;
+ 	data->res.fattr   = &data->fattr;
+ 	data->res.verf    = &data->verf;
+@@ -1214,8 +1237,10 @@ static void nfs_commit_rpcsetup(struct list_head *head,
+ 	dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
+ 
+ 	task = rpc_run_task(&task_setup_data);
+-	if (!IS_ERR(task))
+-		rpc_put_task(task);
++	if (IS_ERR(task))
++		return PTR_ERR(task);
++	rpc_put_task(task);
++	return 0;
+ }
+ 
+ /*
+@@ -1227,15 +1252,13 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+ 	struct nfs_write_data	*data;
+ 	struct nfs_page         *req;
+ 
+-	data = nfs_commit_alloc();
++	data = nfs_commitdata_alloc();
+ 
+ 	if (!data)
+ 		goto out_bad;
+ 
+ 	/* Set up the argument struct */
+-	nfs_commit_rpcsetup(head, data, how);
+-
+-	return 0;
++	return nfs_commit_rpcsetup(head, data, how);
+  out_bad:
+ 	while (!list_empty(head)) {
+ 		req = nfs_list_entry(head->next);
+@@ -1255,7 +1278,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+ static void nfs_commit_done(struct rpc_task *task, void *calldata)
+ {
+ 	struct nfs_write_data	*data = calldata;
+-	struct nfs_page		*req;
+ 
+         dprintk("NFS: %5u nfs_commit_done (status %d)\n",
+                                 task->tk_pid, task->tk_status);
+@@ -1263,6 +1285,13 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
+ 	/* Call the NFS version-specific code */
+ 	if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
+ 		return;
++}
++
++static void nfs_commit_release(void *calldata)
++{
++	struct nfs_write_data	*data = calldata;
++	struct nfs_page		*req;
++	int status = data->task.tk_status;
+ 
+ 	while (!list_empty(&data->pages)) {
+ 		req = nfs_list_entry(data->pages.next);
+@@ -1277,10 +1306,10 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
+ 			(long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
+ 			req->wb_bytes,
+ 			(long long)req_offset(req));
+-		if (task->tk_status < 0) {
+-			nfs_context_set_write_error(req->wb_context, task->tk_status);
++		if (status < 0) {
++			nfs_context_set_write_error(req->wb_context, status);
+ 			nfs_inode_remove_request(req);
+-			dprintk(", error = %d\n", task->tk_status);
++			dprintk(", error = %d\n", status);
+ 			goto next;
+ 		}
+ 
+@@ -1297,10 +1326,11 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
+ 		}
+ 		/* We have a mismatch. Write the page again */
+ 		dprintk(" mismatch\n");
+-		nfs_redirty_request(req);
++		nfs_mark_request_dirty(req);
+ 	next:
+ 		nfs_clear_page_tag_locked(req);
+ 	}
++	nfs_commitdata_release(calldata);
+ }
+ 
+ static const struct rpc_call_ops nfs_commit_ops = {
+@@ -1487,18 +1517,19 @@ static int nfs_wb_page_priority(struct inode *inode, struct page *page,
+ 	};
+ 	int ret;
+ 
+-	BUG_ON(!PageLocked(page));
+-	if (clear_page_dirty_for_io(page)) {
+-		ret = nfs_writepage_locked(page, &wbc);
++	do {
++		if (clear_page_dirty_for_io(page)) {
++			ret = nfs_writepage_locked(page, &wbc);
++			if (ret < 0)
++				goto out_error;
++		} else if (!PagePrivate(page))
++			break;
++		ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
+ 		if (ret < 0)
+-			goto out;
+-	}
+-	if (!PagePrivate(page))
+-		return 0;
+-	ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
+-	if (ret >= 0)
+-		return 0;
+-out:
++			goto out_error;
++	} while (PagePrivate(page));
++	return 0;
++out_error:
+ 	__mark_inode_dirty(inode, I_DIRTY_PAGES);
+ 	return ret;
+ }
+diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
+index d13403e..294992e 100644
+--- a/fs/nfsd/auth.c
++++ b/fs/nfsd/auth.c
+@@ -10,6 +10,7 @@
+ #include <linux/sunrpc/svcauth.h>
+ #include <linux/nfsd/nfsd.h>
+ #include <linux/nfsd/export.h>
++#include "auth.h"
+ 
+ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
+ {
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 8a6f7c9..33bfcf0 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -35,6 +35,7 @@
+ #include <linux/lockd/bind.h>
+ #include <linux/sunrpc/msg_prot.h>
+ #include <linux/sunrpc/gss_api.h>
++#include <net/ipv6.h>
+ 
+ #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
+ 
+@@ -1548,6 +1549,7 @@ exp_addclient(struct nfsctl_client *ncp)
+ {
+ 	struct auth_domain	*dom;
+ 	int			i, err;
++	struct in6_addr addr6;
+ 
+ 	/* First, consistency check. */
+ 	err = -EINVAL;
+@@ -1566,9 +1568,10 @@ exp_addclient(struct nfsctl_client *ncp)
+ 		goto out_unlock;
+ 
+ 	/* Insert client into hashtable. */
+-	for (i = 0; i < ncp->cl_naddr; i++)
+-		auth_unix_add_addr(ncp->cl_addrlist[i], dom);
+-
++	for (i = 0; i < ncp->cl_naddr; i++) {
++		ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
++		auth_unix_add_addr(&addr6, dom);
++	}
+ 	auth_unix_forget_old(dom);
+ 	auth_domain_put(dom);
+ 
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index aae2b29..562abf3 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -344,6 +344,21 @@ static struct rpc_version *	nfs_cb_version[] = {
+ 	&nfs_cb_version4,
+ };
+ 
++static struct rpc_program cb_program;
++
++static struct rpc_stat cb_stats = {
++		.program	= &cb_program
++};
++
++#define NFS4_CALLBACK 0x40000000
++static struct rpc_program cb_program = {
++		.name 		= "nfs4_cb",
++		.number		= NFS4_CALLBACK,
++		.nrvers		= ARRAY_SIZE(nfs_cb_version),
++		.version	= nfs_cb_version,
++		.stats		= &cb_stats,
++};
++
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+  * And why is cb_set an atomic? */
+ 
+@@ -358,13 +373,12 @@ static int do_probe_callback(void *data)
+ 		.to_maxval	= (NFSD_LEASE_TIME/2) * HZ,
+ 		.to_exponential	= 1,
+ 	};
+-	struct rpc_program *	program = &cb->cb_program;
+ 	struct rpc_create_args args = {
+ 		.protocol	= IPPROTO_TCP,
+ 		.address	= (struct sockaddr *)&addr,
+ 		.addrsize	= sizeof(addr),
+ 		.timeout	= &timeparms,
+-		.program	= program,
++		.program	= &cb_program,
+ 		.version	= nfs_cb_version[1]->number,
+ 		.authflavor	= RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
+ 		.flags		= (RPC_CLNT_CREATE_NOPING),
+@@ -382,16 +396,8 @@ static int do_probe_callback(void *data)
+ 	addr.sin_port = htons(cb->cb_port);
+ 	addr.sin_addr.s_addr = htonl(cb->cb_addr);
+ 
+-	/* Initialize rpc_program */
+-	program->name = "nfs4_cb";
+-	program->number = cb->cb_prog;
+-	program->nrvers = ARRAY_SIZE(nfs_cb_version);
+-	program->version = nfs_cb_version;
+-	program->stats = &cb->cb_stat;
+-
+ 	/* Initialize rpc_stat */
+-	memset(program->stats, 0, sizeof(cb->cb_stat));
+-	program->stats->program = program;
++	memset(args.program->stats, 0, sizeof(struct rpc_stat));
+ 
+ 	/* Create RPC client */
+ 	client = rpc_create(&args);
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index 996bd88..5b39842 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -202,7 +202,7 @@ static struct cache_detail idtoname_cache = {
+ 	.alloc		= ent_alloc,
+ };
+ 
+-int
++static int
+ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
+ {
+ 	struct ent ent, *res;
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index c593db0..c309c88 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -658,14 +658,19 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 			return status;
+ 		}
+ 	}
++	status = mnt_want_write(cstate->current_fh.fh_export->ex_path.mnt);
++	if (status)
++		return status;
+ 	status = nfs_ok;
+ 	if (setattr->sa_acl != NULL)
+ 		status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
+ 					    setattr->sa_acl);
+ 	if (status)
+-		return status;
++		goto out;
+ 	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
+ 				0, (time_t)0);
++out:
++	mnt_drop_write(cstate->current_fh.fh_export->ex_path.mnt);
+ 	return status;
+ }
+ 
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 1ff9062..145b3c8 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -46,6 +46,7 @@
+ #include <linux/scatterlist.h>
+ #include <linux/crypto.h>
+ #include <linux/sched.h>
++#include <linux/mount.h>
+ 
+ #define NFSDDBG_FACILITY                NFSDDBG_PROC
+ 
+@@ -154,7 +155,11 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
+ 		dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
+ 		goto out_put;
+ 	}
++	status = mnt_want_write(rec_dir.path.mnt);
++	if (status)
++		goto out_put;
+ 	status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU);
++	mnt_drop_write(rec_dir.path.mnt);
+ out_put:
+ 	dput(dentry);
+ out_unlock:
+@@ -313,12 +318,17 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
+ 	if (!rec_dir_init || !clp->cl_firststate)
+ 		return;
+ 
++	status = mnt_want_write(rec_dir.path.mnt);
++	if (status)
++		goto out;
+ 	clp->cl_firststate = 0;
+ 	nfs4_save_user(&uid, &gid);
+ 	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
+ 	nfs4_reset_user(uid, gid);
+ 	if (status == 0)
+ 		nfsd4_sync_rec_dir();
++	mnt_drop_write(rec_dir.path.mnt);
++out:
+ 	if (status)
+ 		printk("NFSD: Failed to remove expired client state directory"
+ 				" %.*s\n", HEXDIR_LEN, clp->cl_recdir);
+@@ -347,13 +357,17 @@ nfsd4_recdir_purge_old(void) {
+ 
+ 	if (!rec_dir_init)
+ 		return;
++	status = mnt_want_write(rec_dir.path.mnt);
++	if (status)
++		goto out;
+ 	status = nfsd4_list_rec_dir(rec_dir.path.dentry, purge_old);
+ 	if (status == 0)
+ 		nfsd4_sync_rec_dir();
++	mnt_drop_write(rec_dir.path.mnt);
++out:
+ 	if (status)
+ 		printk("nfsd4: failed to purge old clients from recovery"
+ 			" directory %s\n", rec_dir.path.dentry->d_name.name);
+-	return;
+ }
+ 
+ static int
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index bcb97d8..8799b87 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -41,6 +41,7 @@
+ #include <linux/sunrpc/svc.h>
+ #include <linux/nfsd/nfsd.h>
+ #include <linux/nfsd/cache.h>
++#include <linux/file.h>
+ #include <linux/mount.h>
+ #include <linux/workqueue.h>
+ #include <linux/smp_lock.h>
+@@ -1239,7 +1240,7 @@ static inline void
+ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
+ {
+ 	if (share_access & NFS4_SHARE_ACCESS_WRITE) {
+-		put_write_access(filp->f_path.dentry->d_inode);
++		drop_file_write_access(filp);
+ 		filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
+ 	}
+ }
+@@ -1638,6 +1639,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 	locks_init_lock(&fl);
+ 	fl.fl_lmops = &nfsd_lease_mng_ops;
+ 	fl.fl_flags = FL_LEASE;
++	fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
+ 	fl.fl_end = OFFSET_MAX;
+ 	fl.fl_owner =  (fl_owner_t)dp;
+ 	fl.fl_file = stp->st_vfs_file;
+@@ -1646,8 +1648,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ 	/* vfs_setlease checks to see if delegation should be handed out.
+ 	 * the lock_manager callbacks fl_mylease and fl_change are used
+ 	 */
+-	if ((status = vfs_setlease(stp->st_vfs_file,
+-		flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
++	if ((status = vfs_setlease(stp->st_vfs_file, fl.fl_type, &flp))) {
+ 		dprintk("NFSD: setlease failed [%d], no delegation\n", status);
+ 		unhash_delegation(dp);
+ 		flag = NFS4_OPEN_DELEGATE_NONE;
+@@ -1762,10 +1763,6 @@ out:
+ 	return status;
+ }
+ 
+-static struct workqueue_struct *laundry_wq;
+-static void laundromat_main(struct work_struct *);
+-static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
+-
+ __be32
+ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	    clientid_t *clid)
+@@ -1873,7 +1870,11 @@ nfs4_laundromat(void)
+ 	return clientid_val;
+ }
+ 
+-void
++static struct workqueue_struct *laundry_wq;
++static void laundromat_main(struct work_struct *);
++static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
++
++static void
+ laundromat_main(struct work_struct *not_used)
+ {
+ 	time_t t;
+@@ -1974,6 +1975,26 @@ io_during_grace_disallowed(struct inode *inode, int flags)
+ 		&& mandatory_lock(inode);
+ }
+ 
++static int check_stateid_generation(stateid_t *in, stateid_t *ref)
++{
++	/* If the client sends us a stateid from the future, it's buggy: */
++	if (in->si_generation > ref->si_generation)
++		return nfserr_bad_stateid;
++	/*
++	 * The following, however, can happen.  For example, if the
++	 * client sends an open and some IO at the same time, the open
++	 * may bump si_generation while the IO is still in flight.
++	 * Thanks to hard links and renames, the client never knows what
++	 * file an open will affect.  So it could avoid that situation
++	 * only by serializing all opens and IO from the same open
++	 * owner.  To recover from the old_stateid error, the client
++	 * will just have to retry the IO:
++	 */
++	if (in->si_generation < ref->si_generation)
++		return nfserr_old_stateid;
++	return nfs_ok;
++}
++
+ /*
+ * Checks for stateid operations
+ */
+@@ -2022,12 +2043,8 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 			goto out;
+ 		stidp = &stp->st_stateid;
+ 	}
+-	if (stateid->si_generation > stidp->si_generation)
+-		goto out;
+-
+-	/* OLD STATEID */
+-	status = nfserr_old_stateid;
+-	if (stateid->si_generation < stidp->si_generation)
++	status = check_stateid_generation(stateid, stidp);
++	if (status)
+ 		goto out;
+ 	if (stp) {
+ 		if ((status = nfs4_check_openmode(stp,flags)))
+@@ -2035,7 +2052,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ 		renew_client(stp->st_stateowner->so_client);
+ 		if (filpp)
+ 			*filpp = stp->st_vfs_file;
+-	} else if (dp) {
++	} else {
+ 		if ((status = nfs4_check_delegmode(dp, flags)))
+ 			goto out;
+ 		renew_client(dp->dl_client);
+@@ -2064,6 +2081,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ {
+ 	struct nfs4_stateid *stp;
+ 	struct nfs4_stateowner *sop;
++	__be32 status;
+ 
+ 	dprintk("NFSD: preprocess_seqid_op: seqid=%d " 
+ 			"stateid = (%08x/%08x/%08x/%08x)\n", seqid,
+@@ -2126,7 +2144,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+                }
+ 	}
+ 
+-	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
++	if (nfs4_check_fh(current_fh, stp)) {
+ 		dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
+ 		return nfserr_bad_stateid;
+ 	}
+@@ -2149,15 +2167,9 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ 				" confirmed yet!\n");
+ 		return nfserr_bad_stateid;
+ 	}
+-	if (stateid->si_generation > stp->st_stateid.si_generation) {
+-		dprintk("NFSD: preprocess_seqid_op: future stateid?!\n");
+-		return nfserr_bad_stateid;
+-	}
+-
+-	if (stateid->si_generation < stp->st_stateid.si_generation) {
+-		dprintk("NFSD: preprocess_seqid_op: old stateid!\n");
+-		return nfserr_old_stateid;
+-	}
++	status = check_stateid_generation(stateid, &stp->st_stateid);
++	if (status)
++		return status;
+ 	renew_client(sop->so_client);
+ 	return nfs_ok;
+ 
+@@ -2193,7 +2205,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 
+ 	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 					oc->oc_seqid, &oc->oc_req_stateid,
+-					CHECK_FH | CONFIRM | OPEN_STATE,
++					CONFIRM | OPEN_STATE,
+ 					&oc->oc_stateowner, &stp, NULL)))
+ 		goto out; 
+ 
+@@ -2264,7 +2276,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
+ 	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 					od->od_seqid,
+ 					&od->od_stateid, 
+-					CHECK_FH | OPEN_STATE, 
++					OPEN_STATE,
+ 					&od->od_stateowner, &stp, NULL)))
+ 		goto out; 
+ 
+@@ -2317,7 +2329,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 					close->cl_seqid,
+ 					&close->cl_stateid, 
+-					CHECK_FH | OPEN_STATE | CLOSE_STATE,
++					OPEN_STATE | CLOSE_STATE,
+ 					&close->cl_stateowner, &stp, NULL)))
+ 		goto out; 
+ 	status = nfs_ok;
+@@ -2622,7 +2634,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 				        lock->lk_new_open_seqid,
+ 		                        &lock->lk_new_open_stateid,
+-		                        CHECK_FH | OPEN_STATE,
++					OPEN_STATE,
+ 		                        &lock->lk_replay_owner, &open_stp,
+ 					lock);
+ 		if (status)
+@@ -2649,7 +2661,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 		status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 				       lock->lk_old_lock_seqid, 
+ 				       &lock->lk_old_lock_stateid, 
+-				       CHECK_FH | LOCK_STATE, 
++				       LOCK_STATE,
+ 				       &lock->lk_replay_owner, &lock_stp, lock);
+ 		if (status)
+ 			goto out;
+@@ -2700,9 +2712,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	* Note: locks.c uses the BKL to protect the inode's lock list.
+ 	*/
+ 
+-	/* XXX?: Just to divert the locks_release_private at the start of
+-	 * locks_copy_lock: */
+-	locks_init_lock(&conflock);
+ 	err = vfs_lock_file(filp, cmd, &file_lock, &conflock);
+ 	switch (-err) {
+ 	case 0: /* success! */
+@@ -2846,7 +2855,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ 	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ 					locku->lu_seqid, 
+ 					&locku->lu_stateid, 
+-					CHECK_FH | LOCK_STATE, 
++					LOCK_STATE,
+ 					&locku->lu_stateowner, &stp, NULL)))
+ 		goto out;
+ 
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 0e6a179..c513bbd 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -376,20 +376,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
+ 			goto xdr_error;
+ 		}
+ 	}
+-	if (bmval[1] & FATTR4_WORD1_TIME_METADATA) {
+-		/* We require the high 32 bits of 'seconds' to be 0, and we ignore
+-		   all 32 bits of 'nseconds'. */
+-		READ_BUF(12);
+-		len += 12;
+-		READ32(dummy32);
+-		if (dummy32)
+-			return nfserr_inval;
+-		READ32(iattr->ia_ctime.tv_sec);
+-		READ32(iattr->ia_ctime.tv_nsec);
+-		if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
+-			return nfserr_inval;
+-		iattr->ia_valid |= ATTR_CTIME;
+-	}
+ 	if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
+ 		READ_BUF(4);
+ 		len += 4;
+@@ -1867,6 +1853,15 @@ out_serverfault:
+ 	goto out;
+ }
+ 
++static inline int attributes_need_mount(u32 *bmval)
++{
++	if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME))
++		return 1;
++	if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID)
++		return 1;
++	return 0;
++}
++
+ static __be32
+ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ 		const char *name, int namlen, __be32 *p, int *buflen)
+@@ -1888,9 +1883,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ 	 * we will not follow the cross mount and will fill the attribtutes
+ 	 * directly from the mountpoint dentry.
+ 	 */
+-	if (d_mountpoint(dentry) &&
+-	    (cd->rd_bmval[0] & ~FATTR4_WORD0_RDATTR_ERROR) == 0 &&
+-	    (cd->rd_bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID) == 0)
++	if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
+ 		ignore_crossmnt = 1;
+ 	else if (d_mountpoint(dentry)) {
+ 		int err;
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 8516137..42f3820 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -22,6 +22,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/pagemap.h>
+ #include <linux/init.h>
++#include <linux/inet.h>
+ #include <linux/string.h>
+ #include <linux/smp_lock.h>
+ #include <linux/ctype.h>
+@@ -35,8 +36,10 @@
+ #include <linux/nfsd/cache.h>
+ #include <linux/nfsd/xdr.h>
+ #include <linux/nfsd/syscall.h>
++#include <linux/lockd/lockd.h>
+ 
+ #include <asm/uaccess.h>
++#include <net/ipv6.h>
+ 
+ /*
+  *	We have a single directory with 9 nodes in it.
+@@ -52,6 +55,8 @@ enum {
+ 	NFSD_Getfs,
+ 	NFSD_List,
+ 	NFSD_Fh,
++	NFSD_FO_UnlockIP,
++	NFSD_FO_UnlockFS,
+ 	NFSD_Threads,
+ 	NFSD_Pool_Threads,
+ 	NFSD_Versions,
+@@ -88,6 +93,9 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
+ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
+ #endif
+ 
++static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size);
++static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size);
++
+ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 	[NFSD_Svc] = write_svc,
+ 	[NFSD_Add] = write_add,
+@@ -97,6 +105,8 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 	[NFSD_Getfd] = write_getfd,
+ 	[NFSD_Getfs] = write_getfs,
+ 	[NFSD_Fh] = write_filehandle,
++	[NFSD_FO_UnlockIP] = failover_unlock_ip,
++	[NFSD_FO_UnlockFS] = failover_unlock_fs,
+ 	[NFSD_Threads] = write_threads,
+ 	[NFSD_Pool_Threads] = write_pool_threads,
+ 	[NFSD_Versions] = write_versions,
+@@ -149,7 +159,6 @@ static const struct file_operations transaction_ops = {
+ 	.release	= simple_transaction_release,
+ };
+ 
+-extern struct seq_operations nfs_exports_op;
+ static int exports_open(struct inode *inode, struct file *file)
+ {
+ 	return seq_open(file, &nfs_exports_op);
+@@ -222,6 +231,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
+ 	struct auth_domain *clp;
+ 	int err = 0;
+ 	struct knfsd_fh *res;
++	struct in6_addr in6;
+ 
+ 	if (size < sizeof(*data))
+ 		return -EINVAL;
+@@ -236,7 +246,11 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
+ 	res = (struct knfsd_fh*)buf;
+ 
+ 	exp_readlock();
+-	if (!(clp = auth_unix_lookup(sin->sin_addr)))
++
++	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
++
++	clp = auth_unix_lookup(&in6);
++	if (!clp)
+ 		err = -EPERM;
+ 	else {
+ 		err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
+@@ -257,6 +271,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
+ 	int err = 0;
+ 	struct knfsd_fh fh;
+ 	char *res;
++	struct in6_addr in6;
+ 
+ 	if (size < sizeof(*data))
+ 		return -EINVAL;
+@@ -271,7 +286,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
+ 	res = buf;
+ 	sin = (struct sockaddr_in *)&data->gd_addr;
+ 	exp_readlock();
+-	if (!(clp = auth_unix_lookup(sin->sin_addr)))
++
++	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
++
++	clp = auth_unix_lookup(&in6);
++	if (!clp)
+ 		err = -EPERM;
+ 	else {
+ 		err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
+@@ -288,6 +307,58 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
+ 	return err;
+ }
+ 
++static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
++{
++	__be32 server_ip;
++	char *fo_path, c;
++	int b1, b2, b3, b4;
++
++	/* sanity check */
++	if (size == 0)
++		return -EINVAL;
++
++	if (buf[size-1] != '\n')
++		return -EINVAL;
++
++	fo_path = buf;
++	if (qword_get(&buf, fo_path, size) < 0)
++		return -EINVAL;
++
++	/* get ipv4 address */
++	if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
++		return -EINVAL;
++	server_ip = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
++
++	return nlmsvc_unlock_all_by_ip(server_ip);
++}
++
++static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
++{
++	struct nameidata nd;
++	char *fo_path;
++	int error;
++
++	/* sanity check */
++	if (size == 0)
++		return -EINVAL;
++
++	if (buf[size-1] != '\n')
++		return -EINVAL;
++
++	fo_path = buf;
++	if (qword_get(&buf, fo_path, size) < 0)
++		return -EINVAL;
++
++	error = path_lookup(fo_path, 0, &nd);
++	if (error)
++		return error;
++
++	error = nlmsvc_unlock_all_by_sb(nd.path.mnt->mnt_sb);
++
++	path_put(&nd.path);
++	return error;
++}
++
+ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
+ {
+ 	/* request is:
+@@ -347,8 +418,6 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
+ 	return mesg - buf;	
+ }
+ 
+-extern int nfsd_nrthreads(void);
+-
+ static ssize_t write_threads(struct file *file, char *buf, size_t size)
+ {
+ 	/* if size > 0, look for a number of threads and call nfsd_svc
+@@ -371,10 +440,6 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
+ 	return strlen(buf);
+ }
+ 
+-extern int nfsd_nrpools(void);
+-extern int nfsd_get_nrthreads(int n, int *);
+-extern int nfsd_set_nrthreads(int n, int *);
+-
+ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
+ {
+ 	/* if size > 0, look for an array of number of threads per node
+@@ -696,6 +761,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
+ 		[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
++		[NFSD_FO_UnlockIP] = {"unlock_ip",
++					&transaction_ops, S_IWUSR|S_IRUSR},
++		[NFSD_FO_UnlockFS] = {"unlock_filesystem",
++					&transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
+ 		[NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 3e6b3f4..100ae56 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -113,6 +113,124 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ }
+ 
+ /*
++ * Use the given filehandle to look up the corresponding export and
++ * dentry.  On success, the results are used to set fh_export and
++ * fh_dentry.
++ */
++static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
++{
++	struct knfsd_fh	*fh = &fhp->fh_handle;
++	struct fid *fid = NULL, sfid;
++	struct svc_export *exp;
++	struct dentry *dentry;
++	int fileid_type;
++	int data_left = fh->fh_size/4;
++	__be32 error;
++
++	error = nfserr_stale;
++	if (rqstp->rq_vers > 2)
++		error = nfserr_badhandle;
++	if (rqstp->rq_vers == 4 && fh->fh_size == 0)
++		return nfserr_nofilehandle;
++
++	if (fh->fh_version == 1) {
++		int len;
++
++		if (--data_left < 0)
++			return error;
++		if (fh->fh_auth_type != 0)
++			return error;
++		len = key_len(fh->fh_fsid_type) / 4;
++		if (len == 0)
++			return error;
++		if  (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
++			/* deprecated, convert to type 3 */
++			len = key_len(FSID_ENCODE_DEV)/4;
++			fh->fh_fsid_type = FSID_ENCODE_DEV;
++			fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
++			fh->fh_fsid[1] = fh->fh_fsid[2];
++		}
++		data_left -= len;
++		if (data_left < 0)
++			return error;
++		exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_auth);
++		fid = (struct fid *)(fh->fh_auth + len);
++	} else {
++		__u32 tfh[2];
++		dev_t xdev;
++		ino_t xino;
++
++		if (fh->fh_size != NFS_FHSIZE)
++			return error;
++		/* assume old filehandle format */
++		xdev = old_decode_dev(fh->ofh_xdev);
++		xino = u32_to_ino_t(fh->ofh_xino);
++		mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
++		exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
++	}
++
++	error = nfserr_stale;
++	if (PTR_ERR(exp) == -ENOENT)
++		return error;
++
++	if (IS_ERR(exp))
++		return nfserrno(PTR_ERR(exp));
++
++	error = nfsd_setuser_and_check_port(rqstp, exp);
++	if (error)
++		goto out;
++
++	/*
++	 * Look up the dentry using the NFS file handle.
++	 */
++	error = nfserr_stale;
++	if (rqstp->rq_vers > 2)
++		error = nfserr_badhandle;
++
++	if (fh->fh_version != 1) {
++		sfid.i32.ino = fh->ofh_ino;
++		sfid.i32.gen = fh->ofh_generation;
++		sfid.i32.parent_ino = fh->ofh_dirino;
++		fid = &sfid;
++		data_left = 3;
++		if (fh->ofh_dirino == 0)
++			fileid_type = FILEID_INO32_GEN;
++		else
++			fileid_type = FILEID_INO32_GEN_PARENT;
++	} else
++		fileid_type = fh->fh_fileid_type;
++
++	if (fileid_type == FILEID_ROOT)
++		dentry = dget(exp->ex_path.dentry);
++	else {
++		dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
++				data_left, fileid_type,
++				nfsd_acceptable, exp);
++	}
++	if (dentry == NULL)
++		goto out;
++	if (IS_ERR(dentry)) {
++		if (PTR_ERR(dentry) != -EINVAL)
++			error = nfserrno(PTR_ERR(dentry));
++		goto out;
++	}
++
++	if (S_ISDIR(dentry->d_inode->i_mode) &&
++			(dentry->d_flags & DCACHE_DISCONNECTED)) {
++		printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
++				dentry->d_parent->d_name.name, dentry->d_name.name);
++	}
++
++	fhp->fh_dentry = dentry;
++	fhp->fh_export = exp;
++	nfsd_nr_verified++;
++	return 0;
++out:
++	exp_put(exp);
++	return error;
++}
++
++/*
+  * Perform sanity checks on the dentry in a client's file handle.
+  *
+  * Note that the file handle dentry may need to be freed even after
+@@ -124,115 +242,18 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ __be32
+ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ {
+-	struct knfsd_fh	*fh = &fhp->fh_handle;
+-	struct svc_export *exp = NULL;
++	struct svc_export *exp;
+ 	struct dentry	*dentry;
+-	__be32		error = 0;
++	__be32		error;
+ 
+ 	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
+ 
+ 	if (!fhp->fh_dentry) {
+-		struct fid *fid = NULL, sfid;
+-		int fileid_type;
+-		int data_left = fh->fh_size/4;
+-
+-		error = nfserr_stale;
+-		if (rqstp->rq_vers > 2)
+-			error = nfserr_badhandle;
+-		if (rqstp->rq_vers == 4 && fh->fh_size == 0)
+-			return nfserr_nofilehandle;
+-
+-		if (fh->fh_version == 1) {
+-			int len;
+-			if (--data_left<0) goto out;
+-			switch (fh->fh_auth_type) {
+-			case 0: break;
+-			default: goto out;
+-			}
+-			len = key_len(fh->fh_fsid_type) / 4;
+-			if (len == 0) goto out;
+-			if  (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
+-				/* deprecated, convert to type 3 */
+-				len = key_len(FSID_ENCODE_DEV)/4;
+-				fh->fh_fsid_type = FSID_ENCODE_DEV;
+-				fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
+-				fh->fh_fsid[1] = fh->fh_fsid[2];
+-			}
+-			if ((data_left -= len)<0) goto out;
+-			exp = rqst_exp_find(rqstp, fh->fh_fsid_type,
+-					    fh->fh_auth);
+-			fid = (struct fid *)(fh->fh_auth + len);
+-		} else {
+-			__u32 tfh[2];
+-			dev_t xdev;
+-			ino_t xino;
+-			if (fh->fh_size != NFS_FHSIZE)
+-				goto out;
+-			/* assume old filehandle format */
+-			xdev = old_decode_dev(fh->ofh_xdev);
+-			xino = u32_to_ino_t(fh->ofh_xino);
+-			mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
+-			exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
+-		}
+-
+-		error = nfserr_stale;
+-		if (PTR_ERR(exp) == -ENOENT)
+-			goto out;
+-
+-		if (IS_ERR(exp)) {
+-			error = nfserrno(PTR_ERR(exp));
+-			goto out;
+-		}
+-
+-		error = nfsd_setuser_and_check_port(rqstp, exp);
++		error = nfsd_set_fh_dentry(rqstp, fhp);
+ 		if (error)
+ 			goto out;
+-
+-		/*
+-		 * Look up the dentry using the NFS file handle.
+-		 */
+-		error = nfserr_stale;
+-		if (rqstp->rq_vers > 2)
+-			error = nfserr_badhandle;
+-
+-		if (fh->fh_version != 1) {
+-			sfid.i32.ino = fh->ofh_ino;
+-			sfid.i32.gen = fh->ofh_generation;
+-			sfid.i32.parent_ino = fh->ofh_dirino;
+-			fid = &sfid;
+-			data_left = 3;
+-			if (fh->ofh_dirino == 0)
+-				fileid_type = FILEID_INO32_GEN;
+-			else
+-				fileid_type = FILEID_INO32_GEN_PARENT;
+-		} else
+-			fileid_type = fh->fh_fileid_type;
+-
+-		if (fileid_type == FILEID_ROOT)
+-			dentry = dget(exp->ex_path.dentry);
+-		else {
+-			dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
+-					data_left, fileid_type,
+-					nfsd_acceptable, exp);
+-		}
+-		if (dentry == NULL)
+-			goto out;
+-		if (IS_ERR(dentry)) {
+-			if (PTR_ERR(dentry) != -EINVAL)
+-				error = nfserrno(PTR_ERR(dentry));
+-			goto out;
+-		}
+-
+-		if (S_ISDIR(dentry->d_inode->i_mode) &&
+-		    (dentry->d_flags & DCACHE_DISCONNECTED)) {
+-			printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
+-			       dentry->d_parent->d_name.name, dentry->d_name.name);
+-		}
+-
+-		fhp->fh_dentry = dentry;
+-		fhp->fh_export = exp;
+-		nfsd_nr_verified++;
+-		cache_get(&exp->h);
++		dentry = fhp->fh_dentry;
++		exp = fhp->fh_export;
+ 	} else {
+ 		/*
+ 		 * just rechecking permissions
+@@ -242,7 +263,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 		dprintk("nfsd: fh_verify - just checking\n");
+ 		dentry = fhp->fh_dentry;
+ 		exp = fhp->fh_export;
+-		cache_get(&exp->h);
+ 		/*
+ 		 * Set user creds for this exportpoint; necessary even
+ 		 * in the "just checking" case because this may be a
+@@ -281,8 +301,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ 			access, ntohl(error));
+ 	}
+ out:
+-	if (exp && !IS_ERR(exp))
+-		exp_put(exp);
+ 	if (error == nfserr_stale)
+ 		nfsdstats.fh_stale++;
+ 	return error;
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 9647b0f..941041f 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -244,7 +244,6 @@ static int nfsd_init_socks(int port)
+ 	if (error < 0)
+ 		return error;
+ 
+-#ifdef CONFIG_NFSD_TCP
+ 	error = lockd_up(IPPROTO_TCP);
+ 	if (error >= 0) {
+ 		error = svc_create_xprt(nfsd_serv, "tcp", port,
+@@ -254,7 +253,6 @@ static int nfsd_init_socks(int port)
+ 	}
+ 	if (error < 0)
+ 		return error;
+-#endif
+ 	return 0;
+ }
+ 
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 46f59d5..a3a291f 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -264,7 +264,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
+ 	struct inode	*inode;
+ 	int		accmode = MAY_SATTR;
+ 	int		ftype = 0;
+-	int		imode;
+ 	__be32		err;
+ 	int		host_err;
+ 	int		size_change = 0;
+@@ -360,25 +359,25 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
+ 		DQUOT_INIT(inode);
+ 	}
+ 
+-	imode = inode->i_mode;
++	/* sanitize the mode change */
+ 	if (iap->ia_valid & ATTR_MODE) {
+ 		iap->ia_mode &= S_IALLUGO;
+-		imode = iap->ia_mode |= (imode & ~S_IALLUGO);
+-		/* if changing uid/gid revoke setuid/setgid in mode */
+-		if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) {
+-			iap->ia_valid |= ATTR_KILL_PRIV;
++		iap->ia_mode |= (inode->i_mode & ~S_IALLUGO);
++	}
++
++	/* Revoke setuid/setgid on chown */
++	if (((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) ||
++	    ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)) {
++		iap->ia_valid |= ATTR_KILL_PRIV;
++		if (iap->ia_valid & ATTR_MODE) {
++			/* we're setting mode too, just clear the s*id bits */
+ 			iap->ia_mode &= ~S_ISUID;
++			if (iap->ia_mode & S_IXGRP)
++				iap->ia_mode &= ~S_ISGID;
++		} else {
++			/* set ATTR_KILL_* bits and let VFS handle it */
++			iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID);
+ 		}
+-		if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
+-			iap->ia_mode &= ~S_ISGID;
+-	} else {
+-		/*
+-		 * Revoke setuid/setgid bit on chown/chgrp
+-		 */
+-		if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
+-			iap->ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV;
+-		if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
+-			iap->ia_valid |= ATTR_KILL_SGID;
+ 	}
+ 
+ 	/* Change the attributes. */
+@@ -988,7 +987,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ 	 * flushing the data to disk is handled separately below.
+ 	 */
+ 
+-	if (file->f_op->fsync == 0) {/* COMMIT3 cannot work */
++	if (!file->f_op->fsync) {/* COMMIT3 cannot work */
+ 	       stable = 2;
+ 	       *stablep = 2; /* FILE_SYNC */
+ 	}
+@@ -1152,7 +1151,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ }
+ #endif /* CONFIG_NFSD_V3 */
+ 
+-__be32
++static __be32
+ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,
+ 			struct iattr *iap)
+ {
+@@ -1255,23 +1254,35 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 	err = 0;
+ 	switch (type) {
+ 	case S_IFREG:
++		host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++		if (host_err)
++			goto out_nfserr;
+ 		host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+ 		break;
+ 	case S_IFDIR:
++		host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++		if (host_err)
++			goto out_nfserr;
+ 		host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
+ 		break;
+ 	case S_IFCHR:
+ 	case S_IFBLK:
+ 	case S_IFIFO:
+ 	case S_IFSOCK:
++		host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++		if (host_err)
++			goto out_nfserr;
+ 		host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
+ 		break;
+ 	default:
+ 	        printk("nfsd: bad file type %o in nfsd_create\n", type);
+ 		host_err = -EINVAL;
++		goto out_nfserr;
+ 	}
+-	if (host_err < 0)
++	if (host_err < 0) {
++		mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ 		goto out_nfserr;
++	}
+ 
+ 	if (EX_ISSYNC(fhp->fh_export)) {
+ 		err = nfserrno(nfsd_sync_dir(dentry));
+@@ -1282,6 +1293,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 	err2 = nfsd_create_setattr(rqstp, resfhp, iap);
+ 	if (err2)
+ 		err = err2;
++	mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ 	/*
+ 	 * Update the file handle to get the new inode info.
+ 	 */
+@@ -1359,6 +1371,9 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 		v_atime = verifier[1]&0x7fffffff;
+ 	}
+ 	
++	host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++	if (host_err)
++		goto out_nfserr;
+ 	if (dchild->d_inode) {
+ 		err = 0;
+ 
+@@ -1390,12 +1405,15 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 		case NFS3_CREATE_GUARDED:
+ 			err = nfserr_exist;
+ 		}
++		mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ 		goto out;
+ 	}
+ 
+ 	host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+-	if (host_err < 0)
++	if (host_err < 0) {
++		mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ 		goto out_nfserr;
++	}
+ 	if (created)
+ 		*created = 1;
+ 
+@@ -1420,6 +1438,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 	if (err2)
+ 		err = err2;
+ 
++	mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ 	/*
+ 	 * Update the filehandle to get the new inode info.
+ 	 */
+@@ -1522,6 +1541,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 	if (iap && (iap->ia_valid & ATTR_MODE))
+ 		mode = iap->ia_mode & S_IALLUGO;
+ 
++	host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++	if (host_err)
++		goto out_nfserr;
++
+ 	if (unlikely(path[plen] != 0)) {
+ 		char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
+ 		if (path_alloced == NULL)
+@@ -1542,6 +1565,8 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ 	err = nfserrno(host_err);
+ 	fh_unlock(fhp);
+ 
++	mnt_drop_write(fhp->fh_export->ex_path.mnt);
++
+ 	cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
+ 	dput(dnew);
+ 	if (err==0) err = cerr;
+@@ -1592,6 +1617,11 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
+ 	dold = tfhp->fh_dentry;
+ 	dest = dold->d_inode;
+ 
++	host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt);
++	if (host_err) {
++		err = nfserrno(host_err);
++		goto out_dput;
++	}
+ 	host_err = vfs_link(dold, dirp, dnew);
+ 	if (!host_err) {
+ 		if (EX_ISSYNC(ffhp->fh_export)) {
+@@ -1605,7 +1635,8 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
+ 		else
+ 			err = nfserrno(host_err);
+ 	}
+-
++	mnt_drop_write(tfhp->fh_export->ex_path.mnt);
++out_dput:
+ 	dput(dnew);
+ out_unlock:
+ 	fh_unlock(ffhp);
+@@ -1678,13 +1709,20 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
+ 	if (ndentry == trap)
+ 		goto out_dput_new;
+ 
+-#ifdef MSNFS
+-	if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
++	if (svc_msnfs(ffhp) &&
+ 		((atomic_read(&odentry->d_count) > 1)
+ 		 || (atomic_read(&ndentry->d_count) > 1))) {
+ 			host_err = -EPERM;
+-	} else
+-#endif
++			goto out_dput_new;
++	}
++
++	host_err = -EXDEV;
++	if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt)
++		goto out_dput_new;
++	host_err = mnt_want_write(ffhp->fh_export->ex_path.mnt);
++	if (host_err)
++		goto out_dput_new;
++
+ 	host_err = vfs_rename(fdir, odentry, tdir, ndentry);
+ 	if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
+ 		host_err = nfsd_sync_dir(tdentry);
+@@ -1692,6 +1730,8 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
+ 			host_err = nfsd_sync_dir(fdentry);
+ 	}
+ 
++	mnt_drop_write(ffhp->fh_export->ex_path.mnt);
++
+  out_dput_new:
+ 	dput(ndentry);
+  out_dput_old:
+@@ -1750,6 +1790,10 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
+ 	if (!type)
+ 		type = rdentry->d_inode->i_mode & S_IFMT;
+ 
++	host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++	if (host_err)
++		goto out_nfserr;
++
+ 	if (type != S_IFDIR) { /* It's UNLINK */
+ #ifdef MSNFS
+ 		if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
+@@ -1765,10 +1809,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
+ 	dput(rdentry);
+ 
+ 	if (host_err)
+-		goto out_nfserr;
++		goto out_drop;
+ 	if (EX_ISSYNC(fhp->fh_export))
+ 		host_err = nfsd_sync_dir(dentry);
+ 
++out_drop:
++	mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ out_nfserr:
+ 	err = nfserrno(host_err);
+ out:
+@@ -1865,7 +1911,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
+ 		inode->i_mode,
+ 		IS_IMMUTABLE(inode)?	" immut" : "",
+ 		IS_APPEND(inode)?	" append" : "",
+-		IS_RDONLY(inode)?	" ro" : "");
++		__mnt_is_readonly(exp->ex_path.mnt)?	" ro" : "");
+ 	dprintk("      owner %d/%d user %d/%d\n",
+ 		inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
+ #endif
+@@ -1876,7 +1922,8 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
+ 	 */
+ 	if (!(acc & MAY_LOCAL_ACCESS))
+ 		if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
+-			if (exp_rdonly(rqstp, exp) || IS_RDONLY(inode))
++			if (exp_rdonly(rqstp, exp) ||
++			    __mnt_is_readonly(exp->ex_path.mnt))
+ 				return nfserr_rofs;
+ 			if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
+ 				return nfserr_perm;
+@@ -2039,6 +2086,9 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
+ 	} else
+ 		size = 0;
+ 
++	error = mnt_want_write(fhp->fh_export->ex_path.mnt);
++	if (error)
++		goto getout;
+ 	if (size)
+ 		error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
+ 	else {
+@@ -2050,6 +2100,7 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
+ 				error = 0;
+ 		}
+ 	}
++	mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ 
+ getout:
+ 	kfree(value);
+diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
+index 4d4ce48..f6956de 100644
+--- a/fs/ocfs2/Makefile
++++ b/fs/ocfs2/Makefile
+@@ -2,7 +2,12 @@ EXTRA_CFLAGS += -Ifs/ocfs2
+ 
+ EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES
+ 
+-obj-$(CONFIG_OCFS2_FS) += ocfs2.o
++obj-$(CONFIG_OCFS2_FS) += 	\
++	ocfs2.o			\
++	ocfs2_stackglue.o
++
++obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_stack_o2cb.o
++obj-$(CONFIG_OCFS2_FS_USERSPACE_CLUSTER) += ocfs2_stack_user.o
+ 
+ ocfs2-objs := \
+ 	alloc.o 		\
+@@ -31,5 +36,10 @@ ocfs2-objs := \
+ 	uptodate.o		\
+ 	ver.o
+ 
++ocfs2_stackglue-objs := stackglue.o
++ocfs2_stack_o2cb-objs := stack_o2cb.o
++ocfs2_stack_user-objs := stack_user.o
++
++# cluster/ is always needed when OCFS2_FS for masklog support
+ obj-$(CONFIG_OCFS2_FS) += cluster/
+-obj-$(CONFIG_OCFS2_FS) += dlm/
++obj-$(CONFIG_OCFS2_FS_O2CB) += dlm/
+diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
+index 447206e..41f84c9 100644
+--- a/fs/ocfs2/alloc.c
++++ b/fs/ocfs2/alloc.c
+@@ -1029,8 +1029,7 @@ static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el,
+ 	BUG_ON(!next_free);
+ 
+ 	/* The tree code before us didn't allow enough room in the leaf. */
+-	if (el->l_next_free_rec == el->l_count && !has_empty)
+-		BUG();
++	BUG_ON(el->l_next_free_rec == el->l_count && !has_empty);
+ 
+ 	/*
+ 	 * The easiest way to approach this is to just remove the
+@@ -1450,6 +1449,8 @@ static void ocfs2_adjust_root_records(struct ocfs2_extent_list *root_el,
+  *   - When our insert into the right path leaf is at the leftmost edge
+  *     and requires an update of the path immediately to it's left. This
+  *     can occur at the end of some types of rotation and appending inserts.
++ *   - When we've adjusted the last extent record in the left path leaf and the
++ *     1st extent record in the right path leaf during cross extent block merge.
+  */
+ static void ocfs2_complete_edge_insert(struct inode *inode, handle_t *handle,
+ 				       struct ocfs2_path *left_path,
+@@ -2712,24 +2713,147 @@ static void ocfs2_cleanup_merge(struct ocfs2_extent_list *el,
+ 	}
+ }
+ 
++static int ocfs2_get_right_path(struct inode *inode,
++				struct ocfs2_path *left_path,
++				struct ocfs2_path **ret_right_path)
++{
++	int ret;
++	u32 right_cpos;
++	struct ocfs2_path *right_path = NULL;
++	struct ocfs2_extent_list *left_el;
++
++	*ret_right_path = NULL;
++
++	/* This function shouldn't be called for non-trees. */
++	BUG_ON(left_path->p_tree_depth == 0);
++
++	left_el = path_leaf_el(left_path);
++	BUG_ON(left_el->l_next_free_rec != left_el->l_count);
++
++	ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,
++					     &right_cpos);
++	if (ret) {
++		mlog_errno(ret);
++		goto out;
++	}
++
++	/* This function shouldn't be called for the rightmost leaf. */
++	BUG_ON(right_cpos == 0);
++
++	right_path = ocfs2_new_path(path_root_bh(left_path),
++				    path_root_el(left_path));
++	if (!right_path) {
++		ret = -ENOMEM;
++		mlog_errno(ret);
++		goto out;
++	}
++
++	ret = ocfs2_find_path(inode, right_path, right_cpos);
++	if (ret) {
++		mlog_errno(ret);
++		goto out;
++	}
++
++	*ret_right_path = right_path;
++out:
++	if (ret)
++		ocfs2_free_path(right_path);
++	return ret;
++}
++
+ /*
+  * Remove split_rec clusters from the record at index and merge them
+- * onto the beginning of the record at index + 1.
++ * onto the beginning of the record "next" to it.
++ * For index < l_count - 1, the next means the extent rec at index + 1.
++ * For index == l_count - 1, the "next" means the 1st extent rec of the
++ * next extent block.
+  */
+-static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh,
+-				handle_t *handle,
+-				struct ocfs2_extent_rec *split_rec,
+-				struct ocfs2_extent_list *el, int index)
++static int ocfs2_merge_rec_right(struct inode *inode,
++				 struct ocfs2_path *left_path,
++				 handle_t *handle,
++				 struct ocfs2_extent_rec *split_rec,
++				 int index)
+ {
+-	int ret;
++	int ret, next_free, i;
+ 	unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+ 	struct ocfs2_extent_rec *left_rec;
+ 	struct ocfs2_extent_rec *right_rec;
++	struct ocfs2_extent_list *right_el;
++	struct ocfs2_path *right_path = NULL;
++	int subtree_index = 0;
++	struct ocfs2_extent_list *el = path_leaf_el(left_path);
++	struct buffer_head *bh = path_leaf_bh(left_path);
++	struct buffer_head *root_bh = NULL;
+ 
+ 	BUG_ON(index >= le16_to_cpu(el->l_next_free_rec));
+-
+ 	left_rec = &el->l_recs[index];
+-	right_rec = &el->l_recs[index + 1];
++
++	if (index == le16_to_cpu(el->l_next_free_rec - 1) &&
++	    le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count)) {
++		/* we meet with a cross extent block merge. */
++		ret = ocfs2_get_right_path(inode, left_path, &right_path);
++		if (ret) {
++			mlog_errno(ret);
++			goto out;
++		}
++
++		right_el = path_leaf_el(right_path);
++		next_free = le16_to_cpu(right_el->l_next_free_rec);
++		BUG_ON(next_free <= 0);
++		right_rec = &right_el->l_recs[0];
++		if (ocfs2_is_empty_extent(right_rec)) {
++			BUG_ON(le16_to_cpu(next_free) <= 1);
++			right_rec = &right_el->l_recs[1];
++		}
++
++		BUG_ON(le32_to_cpu(left_rec->e_cpos) +
++		       le16_to_cpu(left_rec->e_leaf_clusters) !=
++		       le32_to_cpu(right_rec->e_cpos));
++
++		subtree_index = ocfs2_find_subtree_root(inode,
++							left_path, right_path);
++
++		ret = ocfs2_extend_rotate_transaction(handle, subtree_index,
++						      handle->h_buffer_credits,
++						      right_path);
++		if (ret) {
++			mlog_errno(ret);
++			goto out;
++		}
++
++		root_bh = left_path->p_node[subtree_index].bh;
++		BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
++
++		ret = ocfs2_journal_access(handle, inode, root_bh,
++					   OCFS2_JOURNAL_ACCESS_WRITE);
++		if (ret) {
++			mlog_errno(ret);
++			goto out;
++		}
++
++		for (i = subtree_index + 1;
++		     i < path_num_items(right_path); i++) {
++			ret = ocfs2_journal_access(handle, inode,
++						   right_path->p_node[i].bh,
++						   OCFS2_JOURNAL_ACCESS_WRITE);
++			if (ret) {
++				mlog_errno(ret);
++				goto out;
++			}
++
++			ret = ocfs2_journal_access(handle, inode,
++						   left_path->p_node[i].bh,
++						   OCFS2_JOURNAL_ACCESS_WRITE);
++			if (ret) {
++				mlog_errno(ret);
++				goto out;
++			}
++		}
++
++	} else {
++		BUG_ON(index == le16_to_cpu(el->l_next_free_rec) - 1);
++		right_rec = &el->l_recs[index + 1];
++	}
+ 
+ 	ret = ocfs2_journal_access(handle, inode, bh,
+ 				   OCFS2_JOURNAL_ACCESS_WRITE);
+@@ -2751,30 +2875,156 @@ static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh,
+ 	if (ret)
+ 		mlog_errno(ret);
+ 
++	if (right_path) {
++		ret = ocfs2_journal_dirty(handle, path_leaf_bh(right_path));
++		if (ret)
++			mlog_errno(ret);
++
++		ocfs2_complete_edge_insert(inode, handle, left_path,
++					   right_path, subtree_index);
++	}
++out:
++	if (right_path)
++		ocfs2_free_path(right_path);
++	return ret;
++}
++
++static int ocfs2_get_left_path(struct inode *inode,
++			       struct ocfs2_path *right_path,
++			       struct ocfs2_path **ret_left_path)
++{
++	int ret;
++	u32 left_cpos;
++	struct ocfs2_path *left_path = NULL;
++
++	*ret_left_path = NULL;
++
++	/* This function shouldn't be called for non-trees. */
++	BUG_ON(right_path->p_tree_depth == 0);
++
++	ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb,
++					    right_path, &left_cpos);
++	if (ret) {
++		mlog_errno(ret);
++		goto out;
++	}
++
++	/* This function shouldn't be called for the leftmost leaf. */
++	BUG_ON(left_cpos == 0);
++
++	left_path = ocfs2_new_path(path_root_bh(right_path),
++				   path_root_el(right_path));
++	if (!left_path) {
++		ret = -ENOMEM;
++		mlog_errno(ret);
++		goto out;
++	}
++
++	ret = ocfs2_find_path(inode, left_path, left_cpos);
++	if (ret) {
++		mlog_errno(ret);
++		goto out;
++	}
++
++	*ret_left_path = left_path;
+ out:
++	if (ret)
++		ocfs2_free_path(left_path);
+ 	return ret;
+ }
+ 
+ /*
+  * Remove split_rec clusters from the record at index and merge them
+- * onto the tail of the record at index - 1.
++ * onto the tail of the record "before" it.
++ * For index > 0, the "before" means the extent rec at index - 1.
++ *
++ * For index == 0, the "before" means the last record of the previous
++ * extent block. And there is also a situation that we may need to
++ * remove the rightmost leaf extent block in the right_path and change
++ * the right path to indicate the new rightmost path.
+  */
+-static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
++static int ocfs2_merge_rec_left(struct inode *inode,
++				struct ocfs2_path *right_path,
+ 				handle_t *handle,
+ 				struct ocfs2_extent_rec *split_rec,
+-				struct ocfs2_extent_list *el, int index)
++				struct ocfs2_cached_dealloc_ctxt *dealloc,
++				int index)
+ {
+-	int ret, has_empty_extent = 0;
++	int ret, i, subtree_index = 0, has_empty_extent = 0;
+ 	unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+ 	struct ocfs2_extent_rec *left_rec;
+ 	struct ocfs2_extent_rec *right_rec;
++	struct ocfs2_extent_list *el = path_leaf_el(right_path);
++	struct buffer_head *bh = path_leaf_bh(right_path);
++	struct buffer_head *root_bh = NULL;
++	struct ocfs2_path *left_path = NULL;
++	struct ocfs2_extent_list *left_el;
+ 
+-	BUG_ON(index <= 0);
++	BUG_ON(index < 0);
+ 
+-	left_rec = &el->l_recs[index - 1];
+ 	right_rec = &el->l_recs[index];
+-	if (ocfs2_is_empty_extent(&el->l_recs[0]))
+-		has_empty_extent = 1;
++	if (index == 0) {
++		/* we meet with a cross extent block merge. */
++		ret = ocfs2_get_left_path(inode, right_path, &left_path);
++		if (ret) {
++			mlog_errno(ret);
++			goto out;
++		}
++
++		left_el = path_leaf_el(left_path);
++		BUG_ON(le16_to_cpu(left_el->l_next_free_rec) !=
++		       le16_to_cpu(left_el->l_count));
++
++		left_rec = &left_el->l_recs[
++				le16_to_cpu(left_el->l_next_free_rec) - 1];
++		BUG_ON(le32_to_cpu(left_rec->e_cpos) +
++		       le16_to_cpu(left_rec->e_leaf_clusters) !=
++		       le32_to_cpu(split_rec->e_cpos));
++
++		subtree_index = ocfs2_find_subtree_root(inode,
++							left_path, right_path);
++
++		ret = ocfs2_extend_rotate_transaction(handle, subtree_index,
++						      handle->h_buffer_credits,
++						      left_path);
++		if (ret) {
++			mlog_errno(ret);
++			goto out;
++		}
++
++		root_bh = left_path->p_node[subtree_index].bh;
++		BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
++
++		ret = ocfs2_journal_access(handle, inode, root_bh,
++					   OCFS2_JOURNAL_ACCESS_WRITE);
++		if (ret) {
++			mlog_errno(ret);
++			goto out;
++		}
++
++		for (i = subtree_index + 1;
++		     i < path_num_items(right_path); i++) {
++			ret = ocfs2_journal_access(handle, inode,
++						   right_path->p_node[i].bh,
++						   OCFS2_JOURNAL_ACCESS_WRITE);
++			if (ret) {
++				mlog_errno(ret);
++				goto out;
++			}
++
++			ret = ocfs2_journal_access(handle, inode,
++						   left_path->p_node[i].bh,
++						   OCFS2_JOURNAL_ACCESS_WRITE);
++			if (ret) {
++				mlog_errno(ret);
++				goto out;
++			}
++		}
++	} else {
++		left_rec = &el->l_recs[index - 1];
++		if (ocfs2_is_empty_extent(&el->l_recs[0]))
++			has_empty_extent = 1;
++	}
+ 
+ 	ret = ocfs2_journal_access(handle, inode, bh,
+ 				   OCFS2_JOURNAL_ACCESS_WRITE);
+@@ -2790,9 +3040,8 @@ static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
+ 		*left_rec = *split_rec;
+ 
+ 		has_empty_extent = 0;
+-	} else {
++	} else
+ 		le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters);
+-	}
+ 
+ 	le32_add_cpu(&right_rec->e_cpos, split_clusters);
+ 	le64_add_cpu(&right_rec->e_blkno,
+@@ -2805,13 +3054,44 @@ static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
+ 	if (ret)
+ 		mlog_errno(ret);
+ 
++	if (left_path) {
++		ret = ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
++		if (ret)
++			mlog_errno(ret);
++
++		/*
++		 * In the situation that the right_rec is empty and the extent
++		 * block is empty also,  ocfs2_complete_edge_insert can't handle
++		 * it and we need to delete the right extent block.
++		 */
++		if (le16_to_cpu(right_rec->e_leaf_clusters) == 0 &&
++		    le16_to_cpu(el->l_next_free_rec) == 1) {
++
++			ret = ocfs2_remove_rightmost_path(inode, handle,
++							  right_path, dealloc);
++			if (ret) {
++				mlog_errno(ret);
++				goto out;
++			}
++
++			/* Now the rightmost extent block has been deleted.
++			 * So we use the new rightmost path.
++			 */
++			ocfs2_mv_path(right_path, left_path);
++			left_path = NULL;
++		} else
++			ocfs2_complete_edge_insert(inode, handle, left_path,
++						   right_path, subtree_index);
++	}
+ out:
++	if (left_path)
++		ocfs2_free_path(left_path);
+ 	return ret;
+ }
+ 
+ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ 				     handle_t *handle,
+-				     struct ocfs2_path *left_path,
++				     struct ocfs2_path *path,
+ 				     int split_index,
+ 				     struct ocfs2_extent_rec *split_rec,
+ 				     struct ocfs2_cached_dealloc_ctxt *dealloc,
+@@ -2819,7 +3099,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ 
+ {
+ 	int ret = 0;
+-	struct ocfs2_extent_list *el = path_leaf_el(left_path);
++	struct ocfs2_extent_list *el = path_leaf_el(path);
+ 	struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+ 
+ 	BUG_ON(ctxt->c_contig_type == CONTIG_NONE);
+@@ -2832,7 +3112,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ 		 * extents - having more than one in a leaf is
+ 		 * illegal.
+ 		 */
+-		ret = ocfs2_rotate_tree_left(inode, handle, left_path,
++		ret = ocfs2_rotate_tree_left(inode, handle, path,
+ 					     dealloc);
+ 		if (ret) {
+ 			mlog_errno(ret);
+@@ -2847,7 +3127,6 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ 		 * Left-right contig implies this.
+ 		 */
+ 		BUG_ON(!ctxt->c_split_covers_rec);
+-		BUG_ON(split_index == 0);
+ 
+ 		/*
+ 		 * Since the leftright insert always covers the entire
+@@ -2858,9 +3137,14 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ 		 * Since the adding of an empty extent shifts
+ 		 * everything back to the right, there's no need to
+ 		 * update split_index here.
++		 *
++		 * When the split_index is zero, we need to merge it to the
++		 * prevoius extent block. It is more efficient and easier
++		 * if we do merge_right first and merge_left later.
+ 		 */
+-		ret = ocfs2_merge_rec_left(inode, path_leaf_bh(left_path),
+-					   handle, split_rec, el, split_index);
++		ret = ocfs2_merge_rec_right(inode, path,
++					    handle, split_rec,
++					    split_index);
+ 		if (ret) {
+ 			mlog_errno(ret);
+ 			goto out;
+@@ -2871,32 +3155,30 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ 		 */
+ 		BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+ 
+-		/*
+-		 * The left merge left us with an empty extent, remove
+-		 * it.
+-		 */
+-		ret = ocfs2_rotate_tree_left(inode, handle, left_path, dealloc);
++		/* The merge left us with an empty extent, remove it. */
++		ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+ 		if (ret) {
+ 			mlog_errno(ret);
+ 			goto out;
+ 		}
+-		split_index--;
++
+ 		rec = &el->l_recs[split_index];
+ 
+ 		/*
+ 		 * Note that we don't pass split_rec here on purpose -
+-		 * we've merged it into the left side.
++		 * we've merged it into the rec already.
+ 		 */
+-		ret = ocfs2_merge_rec_right(inode, path_leaf_bh(left_path),
+-					    handle, rec, el, split_index);
++		ret = ocfs2_merge_rec_left(inode, path,
++					   handle, rec,
++					   dealloc,
++					   split_index);
++
+ 		if (ret) {
+ 			mlog_errno(ret);
+ 			goto out;
+ 		}
+ 
+-		BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+-
+-		ret = ocfs2_rotate_tree_left(inode, handle, left_path,
++		ret = ocfs2_rotate_tree_left(inode, handle, path,
+ 					     dealloc);
+ 		/*
+ 		 * Error from this last rotate is not critical, so
+@@ -2915,8 +3197,9 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ 		 */
+ 		if (ctxt->c_contig_type == CONTIG_RIGHT) {
+ 			ret = ocfs2_merge_rec_left(inode,
+-						   path_leaf_bh(left_path),
+-						   handle, split_rec, el,
++						   path,
++						   handle, split_rec,
++						   dealloc,
+ 						   split_index);
+ 			if (ret) {
+ 				mlog_errno(ret);
+@@ -2924,8 +3207,8 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ 			}
+ 		} else {
+ 			ret = ocfs2_merge_rec_right(inode,
+-						    path_leaf_bh(left_path),
+-						    handle, split_rec, el,
++						    path,
++						    handle, split_rec,
+ 						    split_index);
+ 			if (ret) {
+ 				mlog_errno(ret);
+@@ -2938,7 +3221,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ 			 * The merge may have left an empty extent in
+ 			 * our leaf. Try to rotate it away.
+ 			 */
+-			ret = ocfs2_rotate_tree_left(inode, handle, left_path,
++			ret = ocfs2_rotate_tree_left(inode, handle, path,
+ 						     dealloc);
+ 			if (ret)
+ 				mlog_errno(ret);
+@@ -3498,20 +3781,57 @@ out:
+ }
+ 
+ static enum ocfs2_contig_type
+-ocfs2_figure_merge_contig_type(struct inode *inode,
++ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
+ 			       struct ocfs2_extent_list *el, int index,
+ 			       struct ocfs2_extent_rec *split_rec)
+ {
+-	struct ocfs2_extent_rec *rec;
++	int status;
+ 	enum ocfs2_contig_type ret = CONTIG_NONE;
++	u32 left_cpos, right_cpos;
++	struct ocfs2_extent_rec *rec = NULL;
++	struct ocfs2_extent_list *new_el;
++	struct ocfs2_path *left_path = NULL, *right_path = NULL;
++	struct buffer_head *bh;
++	struct ocfs2_extent_block *eb;
++
++	if (index > 0) {
++		rec = &el->l_recs[index - 1];
++	} else if (path->p_tree_depth > 0) {
++		status = ocfs2_find_cpos_for_left_leaf(inode->i_sb,
++						       path, &left_cpos);
++		if (status)
++			goto out;
++
++		if (left_cpos != 0) {
++			left_path = ocfs2_new_path(path_root_bh(path),
++						   path_root_el(path));
++			if (!left_path)
++				goto out;
++
++			status = ocfs2_find_path(inode, left_path, left_cpos);
++			if (status)
++				goto out;
++
++			new_el = path_leaf_el(left_path);
++
++			if (le16_to_cpu(new_el->l_next_free_rec) !=
++			    le16_to_cpu(new_el->l_count)) {
++				bh = path_leaf_bh(left_path);
++				eb = (struct ocfs2_extent_block *)bh->b_data;
++				OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
++								 eb);
++				goto out;
++			}
++			rec = &new_el->l_recs[
++				le16_to_cpu(new_el->l_next_free_rec) - 1];
++		}
++	}
+ 
+ 	/*
+ 	 * We're careful to check for an empty extent record here -
+ 	 * the merge code will know what to do if it sees one.
+ 	 */
+-
+-	if (index > 0) {
+-		rec = &el->l_recs[index - 1];
++	if (rec) {
+ 		if (index == 1 && ocfs2_is_empty_extent(rec)) {
+ 			if (split_rec->e_cpos == el->l_recs[index].e_cpos)
+ 				ret = CONTIG_RIGHT;
+@@ -3520,10 +3840,45 @@ ocfs2_figure_merge_contig_type(struct inode *inode,
+ 		}
+ 	}
+ 
+-	if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) {
++	rec = NULL;
++	if (index < (le16_to_cpu(el->l_next_free_rec) - 1))
++		rec = &el->l_recs[index + 1];
++	else if (le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count) &&
++		 path->p_tree_depth > 0) {
++		status = ocfs2_find_cpos_for_right_leaf(inode->i_sb,
++							path, &right_cpos);
++		if (status)
++			goto out;
++
++		if (right_cpos == 0)
++			goto out;
++
++		right_path = ocfs2_new_path(path_root_bh(path),
++					    path_root_el(path));
++		if (!right_path)
++			goto out;
++
++		status = ocfs2_find_path(inode, right_path, right_cpos);
++		if (status)
++			goto out;
++
++		new_el = path_leaf_el(right_path);
++		rec = &new_el->l_recs[0];
++		if (ocfs2_is_empty_extent(rec)) {
++			if (le16_to_cpu(new_el->l_next_free_rec) <= 1) {
++				bh = path_leaf_bh(right_path);
++				eb = (struct ocfs2_extent_block *)bh->b_data;
++				OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
++								 eb);
++				goto out;
++			}
++			rec = &new_el->l_recs[1];
++		}
++	}
++
++	if (rec) {
+ 		enum ocfs2_contig_type contig_type;
+ 
+-		rec = &el->l_recs[index + 1];
+ 		contig_type = ocfs2_extent_contig(inode, rec, split_rec);
+ 
+ 		if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
+@@ -3532,6 +3887,12 @@ ocfs2_figure_merge_contig_type(struct inode *inode,
+ 			ret = contig_type;
+ 	}
+ 
++out:
++	if (left_path)
++		ocfs2_free_path(left_path);
++	if (right_path)
++		ocfs2_free_path(right_path);
++
+ 	return ret;
+ }
+ 
+@@ -3994,7 +4355,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
+ 		goto out;
+ 	}
+ 
+-	ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el,
++	ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, path, el,
+ 							    split_index,
+ 							    split_rec);
+ 
+@@ -4788,6 +5149,8 @@ static void ocfs2_truncate_log_worker(struct work_struct *work)
+ 	status = ocfs2_flush_truncate_log(osb);
+ 	if (status < 0)
+ 		mlog_errno(status);
++	else
++		ocfs2_init_inode_steal_slot(osb);
+ 
+ 	mlog_exit(status);
+ }
+diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
+index 90383ed..17964c0 100644
+--- a/fs/ocfs2/aops.c
++++ b/fs/ocfs2/aops.c
+@@ -467,11 +467,11 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
+ 							 unsigned to)
+ {
+ 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+-	handle_t *handle = NULL;
++	handle_t *handle;
+ 	int ret = 0;
+ 
+ 	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+-	if (!handle) {
++	if (IS_ERR(handle)) {
+ 		ret = -ENOMEM;
+ 		mlog_errno(ret);
+ 		goto out;
+@@ -487,7 +487,7 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
+ 	}
+ out:
+ 	if (ret) {
+-		if (handle)
++		if (!IS_ERR(handle))
+ 			ocfs2_commit_trans(osb, handle);
+ 		handle = ERR_PTR(ret);
+ 	}
+diff --git a/fs/ocfs2/cluster/Makefile b/fs/ocfs2/cluster/Makefile
+index cdd162f..bc8c5e7 100644
+--- a/fs/ocfs2/cluster/Makefile
++++ b/fs/ocfs2/cluster/Makefile
+@@ -1,4 +1,4 @@
+ obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o
+ 
+ ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \
+-	quorum.o tcp.o ver.o
++	quorum.o tcp.o netdebug.o ver.o
+diff --git a/fs/ocfs2/cluster/netdebug.c b/fs/ocfs2/cluster/netdebug.c
+new file mode 100644
+index 0000000..7bf3c0e
+--- /dev/null
++++ b/fs/ocfs2/cluster/netdebug.c
+@@ -0,0 +1,441 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * netdebug.c
++ *
++ * debug functionality for o2net
++ *
++ * Copyright (C) 2005, 2008 Oracle.  All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public
++ * License along with this program; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 021110-1307, USA.
++ *
++ */
++
++#ifdef CONFIG_DEBUG_FS
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/idr.h>
++#include <linux/kref.h>
++#include <linux/seq_file.h>
++#include <linux/debugfs.h>
++
++#include <linux/uaccess.h>
++
++#include "tcp.h"
++#include "nodemanager.h"
++#define MLOG_MASK_PREFIX ML_TCP
++#include "masklog.h"
++
++#include "tcp_internal.h"
++
++#define O2NET_DEBUG_DIR		"o2net"
++#define SC_DEBUG_NAME		"sock_containers"
++#define NST_DEBUG_NAME		"send_tracking"
++
++static struct dentry *o2net_dentry;
++static struct dentry *sc_dentry;
++static struct dentry *nst_dentry;
++
++static DEFINE_SPINLOCK(o2net_debug_lock);
++
++static LIST_HEAD(sock_containers);
++static LIST_HEAD(send_tracking);
++
++void o2net_debug_add_nst(struct o2net_send_tracking *nst)
++{
++	spin_lock(&o2net_debug_lock);
++	list_add(&nst->st_net_debug_item, &send_tracking);
++	spin_unlock(&o2net_debug_lock);
++}
++
++void o2net_debug_del_nst(struct o2net_send_tracking *nst)
++{
++	spin_lock(&o2net_debug_lock);
++	if (!list_empty(&nst->st_net_debug_item))
++		list_del_init(&nst->st_net_debug_item);
++	spin_unlock(&o2net_debug_lock);
++}
++
++static struct o2net_send_tracking
++			*next_nst(struct o2net_send_tracking *nst_start)
++{
++	struct o2net_send_tracking *nst, *ret = NULL;
++
++	assert_spin_locked(&o2net_debug_lock);
++
++	list_for_each_entry(nst, &nst_start->st_net_debug_item,
++			    st_net_debug_item) {
++		/* discover the head of the list */
++		if (&nst->st_net_debug_item == &send_tracking)
++			break;
++
++		/* use st_task to detect real nsts in the list */
++		if (nst->st_task != NULL) {
++			ret = nst;
++			break;
++		}
++	}
++
++	return ret;
++}
++
++static void *nst_seq_start(struct seq_file *seq, loff_t *pos)
++{
++	struct o2net_send_tracking *nst, *dummy_nst = seq->private;
++
++	spin_lock(&o2net_debug_lock);
++	nst = next_nst(dummy_nst);
++	spin_unlock(&o2net_debug_lock);
++
++	return nst;
++}
++
++static void *nst_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++	struct o2net_send_tracking *nst, *dummy_nst = seq->private;
++
++	spin_lock(&o2net_debug_lock);
++	nst = next_nst(dummy_nst);
++	list_del_init(&dummy_nst->st_net_debug_item);
++	if (nst)
++		list_add(&dummy_nst->st_net_debug_item,
++			 &nst->st_net_debug_item);
++	spin_unlock(&o2net_debug_lock);
++
++	return nst; /* unused, just needs to be null when done */
++}
++
++static int nst_seq_show(struct seq_file *seq, void *v)
++{
++	struct o2net_send_tracking *nst, *dummy_nst = seq->private;
++
++	spin_lock(&o2net_debug_lock);
++	nst = next_nst(dummy_nst);
++
++	if (nst != NULL) {
++		/* get_task_comm isn't exported.  oh well. */
++		seq_printf(seq, "%p:\n"
++			   "  pid:          %lu\n"
++			   "  tgid:         %lu\n"
++			   "  process name: %s\n"
++			   "  node:         %u\n"
++			   "  sc:           %p\n"
++			   "  message id:   %d\n"
++			   "  message type: %u\n"
++			   "  message key:  0x%08x\n"
++			   "  sock acquiry: %lu.%lu\n"
++			   "  send start:   %lu.%lu\n"
++			   "  wait start:   %lu.%lu\n",
++			   nst, (unsigned long)nst->st_task->pid,
++			   (unsigned long)nst->st_task->tgid,
++			   nst->st_task->comm, nst->st_node,
++			   nst->st_sc, nst->st_id, nst->st_msg_type,
++			   nst->st_msg_key,
++			   nst->st_sock_time.tv_sec, nst->st_sock_time.tv_usec,
++			   nst->st_send_time.tv_sec, nst->st_send_time.tv_usec,
++			   nst->st_status_time.tv_sec,
++			   nst->st_status_time.tv_usec);
++	}
++
++	spin_unlock(&o2net_debug_lock);
++
++	return 0;
++}
++
++static void nst_seq_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations nst_seq_ops = {
++	.start = nst_seq_start,
++	.next = nst_seq_next,
++	.stop = nst_seq_stop,
++	.show = nst_seq_show,
++};
++
++static int nst_fop_open(struct inode *inode, struct file *file)
++{
++	struct o2net_send_tracking *dummy_nst;
++	struct seq_file *seq;
++	int ret;
++
++	dummy_nst = kmalloc(sizeof(struct o2net_send_tracking), GFP_KERNEL);
++	if (dummy_nst == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++	dummy_nst->st_task = NULL;
++
++	ret = seq_open(file, &nst_seq_ops);
++	if (ret)
++		goto out;
++
++	seq = file->private_data;
++	seq->private = dummy_nst;
++	o2net_debug_add_nst(dummy_nst);
++
++	dummy_nst = NULL;
++
++out:
++	kfree(dummy_nst);
++	return ret;
++}
++
++static int nst_fop_release(struct inode *inode, struct file *file)
++{
++	struct seq_file *seq = file->private_data;
++	struct o2net_send_tracking *dummy_nst = seq->private;
++
++	o2net_debug_del_nst(dummy_nst);
++	return seq_release_private(inode, file);
++}
++
++static struct file_operations nst_seq_fops = {
++	.open = nst_fop_open,
++	.read = seq_read,
++	.llseek = seq_lseek,
++	.release = nst_fop_release,
++};
++
++void o2net_debug_add_sc(struct o2net_sock_container *sc)
++{
++	spin_lock(&o2net_debug_lock);
++	list_add(&sc->sc_net_debug_item, &sock_containers);
++	spin_unlock(&o2net_debug_lock);
++}
++
++void o2net_debug_del_sc(struct o2net_sock_container *sc)
++{
++	spin_lock(&o2net_debug_lock);
++	list_del_init(&sc->sc_net_debug_item);
++	spin_unlock(&o2net_debug_lock);
++}
++
++static struct o2net_sock_container
++			*next_sc(struct o2net_sock_container *sc_start)
++{
++	struct o2net_sock_container *sc, *ret = NULL;
++
++	assert_spin_locked(&o2net_debug_lock);
++
++	list_for_each_entry(sc, &sc_start->sc_net_debug_item,
++			    sc_net_debug_item) {
++		/* discover the head of the list miscast as a sc */
++		if (&sc->sc_net_debug_item == &sock_containers)
++			break;
++
++		/* use sc_page to detect real scs in the list */
++		if (sc->sc_page != NULL) {
++			ret = sc;
++			break;
++		}
++	}
++
++	return ret;
++}
++
++static void *sc_seq_start(struct seq_file *seq, loff_t *pos)
++{
++	struct o2net_sock_container *sc, *dummy_sc = seq->private;
++
++	spin_lock(&o2net_debug_lock);
++	sc = next_sc(dummy_sc);
++	spin_unlock(&o2net_debug_lock);
++
++	return sc;
++}
++
++static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++	struct o2net_sock_container *sc, *dummy_sc = seq->private;
++
++	spin_lock(&o2net_debug_lock);
++	sc = next_sc(dummy_sc);
++	list_del_init(&dummy_sc->sc_net_debug_item);
++	if (sc)
++		list_add(&dummy_sc->sc_net_debug_item, &sc->sc_net_debug_item);
++	spin_unlock(&o2net_debug_lock);
++
++	return sc; /* unused, just needs to be null when done */
++}
++
++#define TV_SEC_USEC(TV) TV.tv_sec, TV.tv_usec
++
++static int sc_seq_show(struct seq_file *seq, void *v)
++{
++	struct o2net_sock_container *sc, *dummy_sc = seq->private;
++
++	spin_lock(&o2net_debug_lock);
++	sc = next_sc(dummy_sc);
++
++	if (sc != NULL) {
++		struct inet_sock *inet = NULL;
++
++		__be32 saddr = 0, daddr = 0;
++		__be16 sport = 0, dport = 0;
++
++		if (sc->sc_sock) {
++			inet = inet_sk(sc->sc_sock->sk);
++			/* the stack's structs aren't sparse endian clean */
++			saddr = (__force __be32)inet->saddr;
++			daddr = (__force __be32)inet->daddr;
++			sport = (__force __be16)inet->sport;
++			dport = (__force __be16)inet->dport;
++		}
++
++		/* XXX sigh, inet-> doesn't have sparse annotation so any
++		 * use of it here generates a warning with -Wbitwise */
++		seq_printf(seq, "%p:\n"
++			   "  krefs:           %d\n"
++			   "  sock:            %u.%u.%u.%u:%u -> "
++					      "%u.%u.%u.%u:%u\n"
++			   "  remote node:     %s\n"
++			   "  page off:        %zu\n"
++			   "  handshake ok:    %u\n"
++			   "  timer:           %lu.%lu\n"
++			   "  data ready:      %lu.%lu\n"
++			   "  advance start:   %lu.%lu\n"
++			   "  advance stop:    %lu.%lu\n"
++			   "  func start:      %lu.%lu\n"
++			   "  func stop:       %lu.%lu\n"
++			   "  func key:        %u\n"
++			   "  func type:       %u\n",
++			   sc,
++			   atomic_read(&sc->sc_kref.refcount),
++			   NIPQUAD(saddr), inet ? ntohs(sport) : 0,
++			   NIPQUAD(daddr), inet ? ntohs(dport) : 0,
++			   sc->sc_node->nd_name,
++			   sc->sc_page_off,
++			   sc->sc_handshake_ok,
++			   TV_SEC_USEC(sc->sc_tv_timer),
++			   TV_SEC_USEC(sc->sc_tv_data_ready),
++			   TV_SEC_USEC(sc->sc_tv_advance_start),
++			   TV_SEC_USEC(sc->sc_tv_advance_stop),
++			   TV_SEC_USEC(sc->sc_tv_func_start),
++			   TV_SEC_USEC(sc->sc_tv_func_stop),
++			   sc->sc_msg_key,
++			   sc->sc_msg_type);
++	}
++
++
++	spin_unlock(&o2net_debug_lock);
++
++	return 0;
++}
++
++static void sc_seq_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations sc_seq_ops = {
++	.start = sc_seq_start,
++	.next = sc_seq_next,
++	.stop = sc_seq_stop,
++	.show = sc_seq_show,
++};
++
++static int sc_fop_open(struct inode *inode, struct file *file)
++{
++	struct o2net_sock_container *dummy_sc;
++	struct seq_file *seq;
++	int ret;
++
++	dummy_sc = kmalloc(sizeof(struct o2net_sock_container), GFP_KERNEL);
++	if (dummy_sc == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++	dummy_sc->sc_page = NULL;
++
++	ret = seq_open(file, &sc_seq_ops);
++	if (ret)
++		goto out;
++
++	seq = file->private_data;
++	seq->private = dummy_sc;
++	o2net_debug_add_sc(dummy_sc);
++
++	dummy_sc = NULL;
++
++out:
++	kfree(dummy_sc);
++	return ret;
++}
++
++static int sc_fop_release(struct inode *inode, struct file *file)
++{
++	struct seq_file *seq = file->private_data;
++	struct o2net_sock_container *dummy_sc = seq->private;
++
++	o2net_debug_del_sc(dummy_sc);
++	return seq_release_private(inode, file);
++}
++
++static struct file_operations sc_seq_fops = {
++	.open = sc_fop_open,
++	.read = seq_read,
++	.llseek = seq_lseek,
++	.release = sc_fop_release,
++};
++
++int o2net_debugfs_init(void)
++{
++	o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL);
++	if (!o2net_dentry) {
++		mlog_errno(-ENOMEM);
++		goto bail;
++	}
++
++	nst_dentry = debugfs_create_file(NST_DEBUG_NAME, S_IFREG|S_IRUSR,
++					 o2net_dentry, NULL,
++					 &nst_seq_fops);
++	if (!nst_dentry) {
++		mlog_errno(-ENOMEM);
++		goto bail;
++	}
++
++	sc_dentry = debugfs_create_file(SC_DEBUG_NAME, S_IFREG|S_IRUSR,
++					o2net_dentry, NULL,
++					&sc_seq_fops);
++	if (!sc_dentry) {
++		mlog_errno(-ENOMEM);
++		goto bail;
++	}
++
++	return 0;
++bail:
++	if (sc_dentry)
++		debugfs_remove(sc_dentry);
++	if (nst_dentry)
++		debugfs_remove(nst_dentry);
++	if (o2net_dentry)
++		debugfs_remove(o2net_dentry);
++	return -ENOMEM;
++}
++
++void o2net_debugfs_exit(void)
++{
++	if (sc_dentry)
++		debugfs_remove(sc_dentry);
++	if (nst_dentry)
++		debugfs_remove(nst_dentry);
++	if (o2net_dentry)
++		debugfs_remove(o2net_dentry);
++}
++
++#endif	/* CONFIG_DEBUG_FS */
+diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
+index 709fba2..cf9401e 100644
+--- a/fs/ocfs2/cluster/nodemanager.c
++++ b/fs/ocfs2/cluster/nodemanager.c
+@@ -959,7 +959,10 @@ static int __init init_o2nm(void)
+ 	cluster_print_version();
+ 
+ 	o2hb_init();
+-	o2net_init();
++
++	ret = o2net_init();
++	if (ret)
++		goto out;
+ 
+ 	ocfs2_table_header = register_sysctl_table(ocfs2_root_table);
+ 	if (!ocfs2_table_header) {
+diff --git a/fs/ocfs2/cluster/sys.c b/fs/ocfs2/cluster/sys.c
+index 0c095ce..98429fd 100644
+--- a/fs/ocfs2/cluster/sys.c
++++ b/fs/ocfs2/cluster/sys.c
+@@ -57,6 +57,7 @@ static struct kset *o2cb_kset;
+ void o2cb_sys_shutdown(void)
+ {
+ 	mlog_sys_shutdown();
++	sysfs_remove_link(NULL, "o2cb");
+ 	kset_unregister(o2cb_kset);
+ }
+ 
+@@ -68,6 +69,14 @@ int o2cb_sys_init(void)
+ 	if (!o2cb_kset)
+ 		return -ENOMEM;
+ 
++	/*
++	 * Create this symlink for backwards compatibility with old
++	 * versions of ocfs2-tools which look for things in /sys/o2cb.
++	 */
++	ret = sysfs_create_link(NULL, &o2cb_kset->kobj, "o2cb");
++	if (ret)
++		goto error;
++
+ 	ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group);
+ 	if (ret)
+ 		goto error;
+diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
+index b8057c5..1e44ad1 100644
+--- a/fs/ocfs2/cluster/tcp.c
++++ b/fs/ocfs2/cluster/tcp.c
+@@ -142,23 +142,65 @@ static void o2net_idle_timer(unsigned long data);
+ static void o2net_sc_postpone_idle(struct o2net_sock_container *sc);
+ static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc);
+ 
+-/*
+- * FIXME: These should use to_o2nm_cluster_from_node(), but we end up
+- * losing our parent link to the cluster during shutdown. This can be
+- * solved by adding a pre-removal callback to configfs, or passing
+- * around the cluster with the node. -jeffm
+- */
+-static inline int o2net_reconnect_delay(struct o2nm_node *node)
++static void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype,
++			   u32 msgkey, struct task_struct *task, u8 node)
++{
++#ifdef CONFIG_DEBUG_FS
++	INIT_LIST_HEAD(&nst->st_net_debug_item);
++	nst->st_task = task;
++	nst->st_msg_type = msgtype;
++	nst->st_msg_key = msgkey;
++	nst->st_node = node;
++#endif
++}
++
++static void o2net_set_nst_sock_time(struct o2net_send_tracking *nst)
++{
++#ifdef CONFIG_DEBUG_FS
++	do_gettimeofday(&nst->st_sock_time);
++#endif
++}
++
++static void o2net_set_nst_send_time(struct o2net_send_tracking *nst)
++{
++#ifdef CONFIG_DEBUG_FS
++	do_gettimeofday(&nst->st_send_time);
++#endif
++}
++
++static void o2net_set_nst_status_time(struct o2net_send_tracking *nst)
++{
++#ifdef CONFIG_DEBUG_FS
++	do_gettimeofday(&nst->st_status_time);
++#endif
++}
++
++static void o2net_set_nst_sock_container(struct o2net_send_tracking *nst,
++					 struct o2net_sock_container *sc)
++{
++#ifdef CONFIG_DEBUG_FS
++	nst->st_sc = sc;
++#endif
++}
++
++static void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, u32 msg_id)
++{
++#ifdef CONFIG_DEBUG_FS
++	nst->st_id = msg_id;
++#endif
++}
++
++static inline int o2net_reconnect_delay(void)
+ {
+ 	return o2nm_single_cluster->cl_reconnect_delay_ms;
+ }
+ 
+-static inline int o2net_keepalive_delay(struct o2nm_node *node)
++static inline int o2net_keepalive_delay(void)
+ {
+ 	return o2nm_single_cluster->cl_keepalive_delay_ms;
+ }
+ 
+-static inline int o2net_idle_timeout(struct o2nm_node *node)
++static inline int o2net_idle_timeout(void)
+ {
+ 	return o2nm_single_cluster->cl_idle_timeout_ms;
+ }
+@@ -296,6 +338,7 @@ static void sc_kref_release(struct kref *kref)
+ 	o2nm_node_put(sc->sc_node);
+ 	sc->sc_node = NULL;
+ 
++	o2net_debug_del_sc(sc);
+ 	kfree(sc);
+ }
+ 
+@@ -336,6 +379,7 @@ static struct o2net_sock_container *sc_alloc(struct o2nm_node *node)
+ 
+ 	ret = sc;
+ 	sc->sc_page = page;
++	o2net_debug_add_sc(sc);
+ 	sc = NULL;
+ 	page = NULL;
+ 
+@@ -399,8 +443,6 @@ static void o2net_set_nn_state(struct o2net_node *nn,
+ 	mlog_bug_on_msg(err && valid, "err %d valid %u\n", err, valid);
+ 	mlog_bug_on_msg(valid && !sc, "valid %u sc %p\n", valid, sc);
+ 
+-	/* we won't reconnect after our valid conn goes away for
+-	 * this hb iteration.. here so it shows up in the logs */
+ 	if (was_valid && !valid && err == 0)
+ 		err = -ENOTCONN;
+ 
+@@ -430,11 +472,6 @@ static void o2net_set_nn_state(struct o2net_node *nn,
+ 
+ 	if (!was_valid && valid) {
+ 		o2quo_conn_up(o2net_num_from_nn(nn));
+-		/* this is a bit of a hack.  we only try reconnecting
+-		 * when heartbeating starts until we get a connection.
+-		 * if that connection then dies we don't try reconnecting.
+-		 * the only way to start connecting again is to down
+-		 * heartbeat and bring it back up. */
+ 		cancel_delayed_work(&nn->nn_connect_expired);
+ 		printk(KERN_INFO "o2net: %s " SC_NODEF_FMT "\n",
+ 		       o2nm_this_node() > sc->sc_node->nd_num ?
+@@ -451,12 +488,24 @@ static void o2net_set_nn_state(struct o2net_node *nn,
+ 		/* delay if we're withing a RECONNECT_DELAY of the
+ 		 * last attempt */
+ 		delay = (nn->nn_last_connect_attempt +
+-			 msecs_to_jiffies(o2net_reconnect_delay(NULL)))
++			 msecs_to_jiffies(o2net_reconnect_delay()))
+ 			- jiffies;
+-		if (delay > msecs_to_jiffies(o2net_reconnect_delay(NULL)))
++		if (delay > msecs_to_jiffies(o2net_reconnect_delay()))
+ 			delay = 0;
+ 		mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay);
+ 		queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay);
++
++		/*
++		 * Delay the expired work after idle timeout.
++		 *
++		 * We might have lots of failed connection attempts that run
++		 * through here but we only cancel the connect_expired work when
++		 * a connection attempt succeeds.  So only the first enqueue of
++		 * the connect_expired work will do anything.  The rest will see
++		 * that it's already queued and do nothing.
++		 */
++		delay += msecs_to_jiffies(o2net_idle_timeout());
++		queue_delayed_work(o2net_wq, &nn->nn_connect_expired, delay);
+ 	}
+ 
+ 	/* keep track of the nn's sc ref for the caller */
+@@ -914,6 +963,9 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ 	struct o2net_status_wait nsw = {
+ 		.ns_node_item = LIST_HEAD_INIT(nsw.ns_node_item),
+ 	};
++	struct o2net_send_tracking nst;
++
++	o2net_init_nst(&nst, msg_type, key, current, target_node);
+ 
+ 	if (o2net_wq == NULL) {
+ 		mlog(0, "attempt to tx without o2netd running\n");
+@@ -939,6 +991,10 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ 		goto out;
+ 	}
+ 
++	o2net_debug_add_nst(&nst);
++
++	o2net_set_nst_sock_time(&nst);
++
+ 	ret = wait_event_interruptible(nn->nn_sc_wq,
+ 				       o2net_tx_can_proceed(nn, &sc, &error));
+ 	if (!ret && error)
+@@ -946,6 +1002,8 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ 	if (ret)
+ 		goto out;
+ 
++	o2net_set_nst_sock_container(&nst, sc);
++
+ 	veclen = caller_veclen + 1;
+ 	vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC);
+ 	if (vec == NULL) {
+@@ -972,6 +1030,9 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ 		goto out;
+ 
+ 	msg->msg_num = cpu_to_be32(nsw.ns_id);
++	o2net_set_nst_msg_id(&nst, nsw.ns_id);
++
++	o2net_set_nst_send_time(&nst);
+ 
+ 	/* finally, convert the message header to network byte-order
+ 	 * and send */
+@@ -986,6 +1047,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ 	}
+ 
+ 	/* wait on other node's handler */
++	o2net_set_nst_status_time(&nst);
+ 	wait_event(nsw.ns_wq, o2net_nsw_completed(nn, &nsw));
+ 
+ 	/* Note that we avoid overwriting the callers status return
+@@ -998,6 +1060,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ 	mlog(0, "woken, returning system status %d, user status %d\n",
+ 	     ret, nsw.ns_status);
+ out:
++	o2net_debug_del_nst(&nst); /* must be before dropping sc and node */
+ 	if (sc)
+ 		sc_put(sc);
+ 	if (vec)
+@@ -1154,23 +1217,23 @@ static int o2net_check_handshake(struct o2net_sock_container *sc)
+ 	 * but isn't. This can ultimately cause corruption.
+ 	 */
+ 	if (be32_to_cpu(hand->o2net_idle_timeout_ms) !=
+-				o2net_idle_timeout(sc->sc_node)) {
++				o2net_idle_timeout()) {
+ 		mlog(ML_NOTICE, SC_NODEF_FMT " uses a network idle timeout of "
+ 		     "%u ms, but we use %u ms locally.  disconnecting\n",
+ 		     SC_NODEF_ARGS(sc),
+ 		     be32_to_cpu(hand->o2net_idle_timeout_ms),
+-		     o2net_idle_timeout(sc->sc_node));
++		     o2net_idle_timeout());
+ 		o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+ 		return -1;
+ 	}
+ 
+ 	if (be32_to_cpu(hand->o2net_keepalive_delay_ms) !=
+-			o2net_keepalive_delay(sc->sc_node)) {
++			o2net_keepalive_delay()) {
+ 		mlog(ML_NOTICE, SC_NODEF_FMT " uses a keepalive delay of "
+ 		     "%u ms, but we use %u ms locally.  disconnecting\n",
+ 		     SC_NODEF_ARGS(sc),
+ 		     be32_to_cpu(hand->o2net_keepalive_delay_ms),
+-		     o2net_keepalive_delay(sc->sc_node));
++		     o2net_keepalive_delay());
+ 		o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+ 		return -1;
+ 	}
+@@ -1193,6 +1256,7 @@ static int o2net_check_handshake(struct o2net_sock_container *sc)
+ 	 * shut down already */
+ 	if (nn->nn_sc == sc) {
+ 		o2net_sc_reset_idle_timer(sc);
++		atomic_set(&nn->nn_timeout, 0);
+ 		o2net_set_nn_state(nn, sc, 1, 0);
+ 	}
+ 	spin_unlock(&nn->nn_lock);
+@@ -1347,12 +1411,11 @@ static void o2net_initialize_handshake(void)
+ {
+ 	o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32(
+ 		O2HB_MAX_WRITE_TIMEOUT_MS);
+-	o2net_hand->o2net_idle_timeout_ms = cpu_to_be32(
+-		o2net_idle_timeout(NULL));
++	o2net_hand->o2net_idle_timeout_ms = cpu_to_be32(o2net_idle_timeout());
+ 	o2net_hand->o2net_keepalive_delay_ms = cpu_to_be32(
+-		o2net_keepalive_delay(NULL));
++		o2net_keepalive_delay());
+ 	o2net_hand->o2net_reconnect_delay_ms = cpu_to_be32(
+-		o2net_reconnect_delay(NULL));
++		o2net_reconnect_delay());
+ }
+ 
+ /* ------------------------------------------------------------ */
+@@ -1391,14 +1454,15 @@ static void o2net_sc_send_keep_req(struct work_struct *work)
+ static void o2net_idle_timer(unsigned long data)
+ {
+ 	struct o2net_sock_container *sc = (struct o2net_sock_container *)data;
++	struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
+ 	struct timeval now;
+ 
+ 	do_gettimeofday(&now);
+ 
+ 	printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u "
+ 	     "seconds, shutting it down.\n", SC_NODEF_ARGS(sc),
+-		     o2net_idle_timeout(sc->sc_node) / 1000,
+-		     o2net_idle_timeout(sc->sc_node) % 1000);
++		     o2net_idle_timeout() / 1000,
++		     o2net_idle_timeout() % 1000);
+ 	mlog(ML_NOTICE, "here are some times that might help debug the "
+ 	     "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv "
+ 	     "%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n",
+@@ -1413,6 +1477,12 @@ static void o2net_idle_timer(unsigned long data)
+ 	     sc->sc_tv_func_start.tv_sec, (long) sc->sc_tv_func_start.tv_usec,
+ 	     sc->sc_tv_func_stop.tv_sec, (long) sc->sc_tv_func_stop.tv_usec);
+ 
++	/*
++	 * Initialize the nn_timeout so that the next connection attempt
++	 * will continue in o2net_start_connect.
++	 */
++	atomic_set(&nn->nn_timeout, 1);
++
+ 	o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
+ }
+ 
+@@ -1420,10 +1490,10 @@ static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc)
+ {
+ 	o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work);
+ 	o2net_sc_queue_delayed_work(sc, &sc->sc_keepalive_work,
+-		      msecs_to_jiffies(o2net_keepalive_delay(sc->sc_node)));
++		      msecs_to_jiffies(o2net_keepalive_delay()));
+ 	do_gettimeofday(&sc->sc_tv_timer);
+ 	mod_timer(&sc->sc_idle_timeout,
+-	       jiffies + msecs_to_jiffies(o2net_idle_timeout(sc->sc_node)));
++	       jiffies + msecs_to_jiffies(o2net_idle_timeout()));
+ }
+ 
+ static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)
+@@ -1447,6 +1517,7 @@ static void o2net_start_connect(struct work_struct *work)
+ 	struct socket *sock = NULL;
+ 	struct sockaddr_in myaddr = {0, }, remoteaddr = {0, };
+ 	int ret = 0, stop;
++	unsigned int timeout;
+ 
+ 	/* if we're greater we initiate tx, otherwise we accept */
+ 	if (o2nm_this_node() <= o2net_num_from_nn(nn))
+@@ -1466,8 +1537,17 @@ static void o2net_start_connect(struct work_struct *work)
+ 	}
+ 
+ 	spin_lock(&nn->nn_lock);
+-	/* see if we already have one pending or have given up */
+-	stop = (nn->nn_sc || nn->nn_persistent_error);
++	/*
++	 * see if we already have one pending or have given up.
++	 * For nn_timeout, it is set when we close the connection
++	 * because of the idle time out. So it means that we have
++	 * at least connected to that node successfully once,
++	 * now try to connect to it again.
++	 */
++	timeout = atomic_read(&nn->nn_timeout);
++	stop = (nn->nn_sc ||
++		(nn->nn_persistent_error &&
++		(nn->nn_persistent_error != -ENOTCONN || timeout == 0)));
+ 	spin_unlock(&nn->nn_lock);
+ 	if (stop)
+ 		goto out;
+@@ -1555,8 +1635,8 @@ static void o2net_connect_expired(struct work_struct *work)
+ 		mlog(ML_ERROR, "no connection established with node %u after "
+ 		     "%u.%u seconds, giving up and returning errors.\n",
+ 		     o2net_num_from_nn(nn),
+-		     o2net_idle_timeout(NULL) / 1000,
+-		     o2net_idle_timeout(NULL) % 1000);
++		     o2net_idle_timeout() / 1000,
++		     o2net_idle_timeout() % 1000);
+ 
+ 		o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
+ 	}
+@@ -1579,6 +1659,7 @@ void o2net_disconnect_node(struct o2nm_node *node)
+ 
+ 	/* don't reconnect until it's heartbeating again */
+ 	spin_lock(&nn->nn_lock);
++	atomic_set(&nn->nn_timeout, 0);
+ 	o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
+ 	spin_unlock(&nn->nn_lock);
+ 
+@@ -1610,20 +1691,15 @@ static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num,
+ 
+ 	/* ensure an immediate connect attempt */
+ 	nn->nn_last_connect_attempt = jiffies -
+-		(msecs_to_jiffies(o2net_reconnect_delay(node)) + 1);
++		(msecs_to_jiffies(o2net_reconnect_delay()) + 1);
+ 
+ 	if (node_num != o2nm_this_node()) {
+-		/* heartbeat doesn't work unless a local node number is
+-		 * configured and doing so brings up the o2net_wq, so we can
+-		 * use it.. */
+-		queue_delayed_work(o2net_wq, &nn->nn_connect_expired,
+-		                   msecs_to_jiffies(o2net_idle_timeout(node)));
+-
+ 		/* believe it or not, accept and node hearbeating testing
+ 		 * can succeed for this node before we got here.. so
+ 		 * only use set_nn_state to clear the persistent error
+ 		 * if that hasn't already happened */
+ 		spin_lock(&nn->nn_lock);
++		atomic_set(&nn->nn_timeout, 0);
+ 		if (nn->nn_persistent_error)
+ 			o2net_set_nn_state(nn, NULL, 0, 0);
+ 		spin_unlock(&nn->nn_lock);
+@@ -1747,6 +1823,7 @@ static int o2net_accept_one(struct socket *sock)
+ 	new_sock = NULL;
+ 
+ 	spin_lock(&nn->nn_lock);
++	atomic_set(&nn->nn_timeout, 0);
+ 	o2net_set_nn_state(nn, sc, 0, 0);
+ 	spin_unlock(&nn->nn_lock);
+ 
+@@ -1922,6 +1999,9 @@ int o2net_init(void)
+ 
+ 	o2quo_init();
+ 
++	if (o2net_debugfs_init())
++		return -ENOMEM;
++
+ 	o2net_hand = kzalloc(sizeof(struct o2net_handshake), GFP_KERNEL);
+ 	o2net_keep_req = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
+ 	o2net_keep_resp = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
+@@ -1941,6 +2021,7 @@ int o2net_init(void)
+ 	for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) {
+ 		struct o2net_node *nn = o2net_nn_from_num(i);
+ 
++		atomic_set(&nn->nn_timeout, 0);
+ 		spin_lock_init(&nn->nn_lock);
+ 		INIT_DELAYED_WORK(&nn->nn_connect_work, o2net_start_connect);
+ 		INIT_DELAYED_WORK(&nn->nn_connect_expired,
+@@ -1962,4 +2043,5 @@ void o2net_exit(void)
+ 	kfree(o2net_hand);
+ 	kfree(o2net_keep_req);
+ 	kfree(o2net_keep_resp);
++	o2net_debugfs_exit();
+ }
+diff --git a/fs/ocfs2/cluster/tcp.h b/fs/ocfs2/cluster/tcp.h
+index f36f66a..a705d5d 100644
+--- a/fs/ocfs2/cluster/tcp.h
++++ b/fs/ocfs2/cluster/tcp.h
+@@ -117,4 +117,36 @@ int o2net_num_connected_peers(void);
+ int o2net_init(void);
+ void o2net_exit(void);
+ 
++struct o2net_send_tracking;
++struct o2net_sock_container;
++
++#ifdef CONFIG_DEBUG_FS
++int o2net_debugfs_init(void);
++void o2net_debugfs_exit(void);
++void o2net_debug_add_nst(struct o2net_send_tracking *nst);
++void o2net_debug_del_nst(struct o2net_send_tracking *nst);
++void o2net_debug_add_sc(struct o2net_sock_container *sc);
++void o2net_debug_del_sc(struct o2net_sock_container *sc);
++#else
++static int o2net_debugfs_init(void)
++{
++	return 0;
++}
++static void o2net_debugfs_exit(void)
++{
++}
++static void o2net_debug_add_nst(struct o2net_send_tracking *nst)
++{
++}
++static void o2net_debug_del_nst(struct o2net_send_tracking *nst)
++{
++}
++static void o2net_debug_add_sc(struct o2net_sock_container *sc)
++{
++}
++static void o2net_debug_del_sc(struct o2net_sock_container *sc)
++{
++}
++#endif	/* CONFIG_DEBUG_FS */
++
+ #endif /* O2CLUSTER_TCP_H */
+diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h
+index d25b9af..8d58cfe 100644
+--- a/fs/ocfs2/cluster/tcp_internal.h
++++ b/fs/ocfs2/cluster/tcp_internal.h
+@@ -95,6 +95,8 @@ struct o2net_node {
+ 	unsigned			nn_sc_valid:1;
+ 	/* if this is set tx just returns it */
+ 	int				nn_persistent_error;
++	/* It is only set to 1 after the idle time out. */
++	atomic_t			nn_timeout;
+ 
+ 	/* threads waiting for an sc to arrive wait on the wq for generation
+ 	 * to increase.  it is increased when a connecting socket succeeds
+@@ -164,7 +166,9 @@ struct o2net_sock_container {
+ 	/* original handlers for the sockets */
+ 	void			(*sc_state_change)(struct sock *sk);
+ 	void			(*sc_data_ready)(struct sock *sk, int bytes);
+-
++#ifdef CONFIG_DEBUG_FS
++	struct list_head        sc_net_debug_item;
++#endif
+ 	struct timeval 		sc_tv_timer;
+ 	struct timeval 		sc_tv_data_ready;
+ 	struct timeval 		sc_tv_advance_start;
+@@ -206,4 +210,24 @@ struct o2net_status_wait {
+ 	struct list_head	ns_node_item;
+ };
+ 
++#ifdef CONFIG_DEBUG_FS
++/* just for state dumps */
++struct o2net_send_tracking {
++	struct list_head		st_net_debug_item;
++	struct task_struct		*st_task;
++	struct o2net_sock_container	*st_sc;
++	u32				st_id;
++	u32				st_msg_type;
++	u32				st_msg_key;
++	u8				st_node;
++	struct timeval			st_sock_time;
++	struct timeval			st_send_time;
++	struct timeval			st_status_time;
++};
++#else
++struct o2net_send_tracking {
++	u32	dummy;
++};
++#endif	/* CONFIG_DEBUG_FS */
++
+ #endif /* O2CLUSTER_TCP_INTERNAL_H */
+diff --git a/fs/ocfs2/dlm/Makefile b/fs/ocfs2/dlm/Makefile
+index ce3f7c2..1903613 100644
+--- a/fs/ocfs2/dlm/Makefile
++++ b/fs/ocfs2/dlm/Makefile
+@@ -1,6 +1,6 @@
+ EXTRA_CFLAGS += -Ifs/ocfs2
+ 
+-obj-$(CONFIG_OCFS2_FS) += ocfs2_dlm.o ocfs2_dlmfs.o
++obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o ocfs2_dlmfs.o
+ 
+ ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \
+ 	dlmmaster.o dlmast.o dlmconvert.o dlmlock.o dlmunlock.o dlmver.o
+diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
+index dc8ea66..d5a86fb 100644
+--- a/fs/ocfs2/dlm/dlmcommon.h
++++ b/fs/ocfs2/dlm/dlmcommon.h
+@@ -49,6 +49,41 @@
+ /* Intended to make it easier for us to switch out hash functions */
+ #define dlm_lockid_hash(_n, _l) full_name_hash(_n, _l)
+ 
++enum dlm_mle_type {
++	DLM_MLE_BLOCK,
++	DLM_MLE_MASTER,
++	DLM_MLE_MIGRATION
++};
++
++struct dlm_lock_name {
++	u8 len;
++	u8 name[DLM_LOCKID_NAME_MAX];
++};
++
++struct dlm_master_list_entry {
++	struct list_head list;
++	struct list_head hb_events;
++	struct dlm_ctxt *dlm;
++	spinlock_t spinlock;
++	wait_queue_head_t wq;
++	atomic_t woken;
++	struct kref mle_refs;
++	int inuse;
++	unsigned long maybe_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
++	unsigned long vote_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
++	unsigned long response_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
++	unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
++	u8 master;
++	u8 new_master;
++	enum dlm_mle_type type;
++	struct o2hb_callback_func mle_hb_up;
++	struct o2hb_callback_func mle_hb_down;
++	union {
++		struct dlm_lock_resource *res;
++		struct dlm_lock_name name;
++	} u;
++};
++
+ enum dlm_ast_type {
+ 	DLM_AST = 0,
+ 	DLM_BAST,
+@@ -101,6 +136,7 @@ struct dlm_ctxt
+ 	struct list_head purge_list;
+ 	struct list_head pending_asts;
+ 	struct list_head pending_basts;
++	struct list_head tracking_list;
+ 	unsigned int purge_count;
+ 	spinlock_t spinlock;
+ 	spinlock_t ast_lock;
+@@ -122,6 +158,9 @@ struct dlm_ctxt
+ 	atomic_t remote_resources;
+ 	atomic_t unknown_resources;
+ 
++	struct dlm_debug_ctxt *dlm_debug_ctxt;
++	struct dentry *dlm_debugfs_subroot;
++
+ 	/* NOTE: Next three are protected by dlm_domain_lock */
+ 	struct kref dlm_refs;
+ 	enum dlm_ctxt_state dlm_state;
+@@ -270,6 +309,9 @@ struct dlm_lock_resource
+ 	struct list_head dirty;
+ 	struct list_head recovering; // dlm_recovery_ctxt.resources list
+ 
++	/* Added during init and removed during release */
++	struct list_head tracking;	/* dlm->tracking_list */
++
+ 	/* unused lock resources have their last_used stamped and are
+ 	 * put on a list for the dlm thread to run. */
+ 	unsigned long    last_used;
+@@ -963,9 +1005,16 @@ static inline void __dlm_wait_on_lockres(struct dlm_lock_resource *res)
+ 					  DLM_LOCK_RES_MIGRATING));
+ }
+ 
++/* create/destroy slab caches */
++int dlm_init_master_caches(void);
++void dlm_destroy_master_caches(void);
++
++int dlm_init_lock_cache(void);
++void dlm_destroy_lock_cache(void);
+ 
+ int dlm_init_mle_cache(void);
+ void dlm_destroy_mle_cache(void);
++
+ void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up);
+ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm,
+ 			 struct dlm_lock_resource *res);
+diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
+index 64239b3..5f6d858 100644
+--- a/fs/ocfs2/dlm/dlmdebug.c
++++ b/fs/ocfs2/dlm/dlmdebug.c
+@@ -5,7 +5,7 @@
+  *
+  * debug functionality for the dlm
+  *
+- * Copyright (C) 2004 Oracle.  All rights reserved.
++ * Copyright (C) 2004, 2008 Oracle.  All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public
+@@ -30,6 +30,7 @@
+ #include <linux/utsname.h>
+ #include <linux/sysctl.h>
+ #include <linux/spinlock.h>
++#include <linux/debugfs.h>
+ 
+ #include "cluster/heartbeat.h"
+ #include "cluster/nodemanager.h"
+@@ -37,17 +38,16 @@
+ 
+ #include "dlmapi.h"
+ #include "dlmcommon.h"
+-
+ #include "dlmdomain.h"
++#include "dlmdebug.h"
+ 
+ #define MLOG_MASK_PREFIX ML_DLM
+ #include "cluster/masklog.h"
+ 
++int stringify_lockname(const char *lockname, int locklen, char *buf, int len);
++
+ void dlm_print_one_lock_resource(struct dlm_lock_resource *res)
+ {
+-	mlog(ML_NOTICE, "lockres: %.*s, owner=%u, state=%u\n",
+-	       res->lockname.len, res->lockname.name,
+-	       res->owner, res->state);
+ 	spin_lock(&res->spinlock);
+ 	__dlm_print_one_lock_resource(res);
+ 	spin_unlock(&res->spinlock);
+@@ -58,7 +58,7 @@ static void dlm_print_lockres_refmap(struct dlm_lock_resource *res)
+ 	int bit;
+ 	assert_spin_locked(&res->spinlock);
+ 
+-	mlog(ML_NOTICE, "  refmap nodes: [ ");
++	printk("  refmap nodes: [ ");
+ 	bit = 0;
+ 	while (1) {
+ 		bit = find_next_bit(res->refmap, O2NM_MAX_NODES, bit);
+@@ -70,63 +70,66 @@ static void dlm_print_lockres_refmap(struct dlm_lock_resource *res)
+ 	printk("], inflight=%u\n", res->inflight_locks);
+ }
+ 
++static void __dlm_print_lock(struct dlm_lock *lock)
++{
++	spin_lock(&lock->spinlock);
++
++	printk("    type=%d, conv=%d, node=%u, cookie=%u:%llu, "
++	       "ref=%u, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c), "
++	       "pending=(conv=%c,lock=%c,cancel=%c,unlock=%c)\n",
++	       lock->ml.type, lock->ml.convert_type, lock->ml.node,
++	       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
++	       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
++	       atomic_read(&lock->lock_refs.refcount),
++	       (list_empty(&lock->ast_list) ? 'y' : 'n'),
++	       (lock->ast_pending ? 'y' : 'n'),
++	       (list_empty(&lock->bast_list) ? 'y' : 'n'),
++	       (lock->bast_pending ? 'y' : 'n'),
++	       (lock->convert_pending ? 'y' : 'n'),
++	       (lock->lock_pending ? 'y' : 'n'),
++	       (lock->cancel_pending ? 'y' : 'n'),
++	       (lock->unlock_pending ? 'y' : 'n'));
++
++	spin_unlock(&lock->spinlock);
++}
++
+ void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
+ {
+ 	struct list_head *iter2;
+ 	struct dlm_lock *lock;
++	char buf[DLM_LOCKID_NAME_MAX];
+ 
+ 	assert_spin_locked(&res->spinlock);
+ 
+-	mlog(ML_NOTICE, "lockres: %.*s, owner=%u, state=%u\n",
+-	       res->lockname.len, res->lockname.name,
+-	       res->owner, res->state);
+-	mlog(ML_NOTICE, "  last used: %lu, on purge list: %s\n",
+-	     res->last_used, list_empty(&res->purge) ? "no" : "yes");
++	stringify_lockname(res->lockname.name, res->lockname.len,
++			   buf, sizeof(buf) - 1);
++	printk("lockres: %s, owner=%u, state=%u\n",
++	       buf, res->owner, res->state);
++	printk("  last used: %lu, refcnt: %u, on purge list: %s\n",
++	       res->last_used, atomic_read(&res->refs.refcount),
++	       list_empty(&res->purge) ? "no" : "yes");
++	printk("  on dirty list: %s, on reco list: %s, "
++	       "migrating pending: %s\n",
++	       list_empty(&res->dirty) ? "no" : "yes",
++	       list_empty(&res->recovering) ? "no" : "yes",
++	       res->migration_pending ? "yes" : "no");
++	printk("  inflight locks: %d, asts reserved: %d\n",
++	       res->inflight_locks, atomic_read(&res->asts_reserved));
+ 	dlm_print_lockres_refmap(res);
+-	mlog(ML_NOTICE, "  granted queue: \n");
++	printk("  granted queue:\n");
+ 	list_for_each(iter2, &res->granted) {
+ 		lock = list_entry(iter2, struct dlm_lock, list);
+-		spin_lock(&lock->spinlock);
+-		mlog(ML_NOTICE, "    type=%d, conv=%d, node=%u, "
+-		       "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n", 
+-		       lock->ml.type, lock->ml.convert_type, lock->ml.node, 
+-		     dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
+-		     dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
+-		       list_empty(&lock->ast_list) ? 'y' : 'n',
+-		       lock->ast_pending ? 'y' : 'n',
+-		       list_empty(&lock->bast_list) ? 'y' : 'n',
+-		       lock->bast_pending ? 'y' : 'n');
+-		spin_unlock(&lock->spinlock);
++		__dlm_print_lock(lock);
+ 	}
+-	mlog(ML_NOTICE, "  converting queue: \n");
++	printk("  converting queue:\n");
+ 	list_for_each(iter2, &res->converting) {
+ 		lock = list_entry(iter2, struct dlm_lock, list);
+-		spin_lock(&lock->spinlock);
+-		mlog(ML_NOTICE, "    type=%d, conv=%d, node=%u, "
+-		       "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n", 
+-		       lock->ml.type, lock->ml.convert_type, lock->ml.node, 
+-		     dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
+-		     dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
+-		       list_empty(&lock->ast_list) ? 'y' : 'n',
+-		       lock->ast_pending ? 'y' : 'n',
+-		       list_empty(&lock->bast_list) ? 'y' : 'n',
+-		       lock->bast_pending ? 'y' : 'n');
+-		spin_unlock(&lock->spinlock);
++		__dlm_print_lock(lock);
+ 	}
+-	mlog(ML_NOTICE, "  blocked queue: \n");
++	printk("  blocked queue:\n");
+ 	list_for_each(iter2, &res->blocked) {
+ 		lock = list_entry(iter2, struct dlm_lock, list);
+-		spin_lock(&lock->spinlock);
+-		mlog(ML_NOTICE, "    type=%d, conv=%d, node=%u, "
+-		       "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n", 
+-		       lock->ml.type, lock->ml.convert_type, lock->ml.node, 
+-		     dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
+-		     dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
+-		       list_empty(&lock->ast_list) ? 'y' : 'n',
+-		       lock->ast_pending ? 'y' : 'n',
+-		       list_empty(&lock->bast_list) ? 'y' : 'n',
+-		       lock->bast_pending ? 'y' : 'n');
+-		spin_unlock(&lock->spinlock);
++		__dlm_print_lock(lock);
+ 	}
+ }
+ 
+@@ -136,31 +139,6 @@ void dlm_print_one_lock(struct dlm_lock *lockid)
+ }
+ EXPORT_SYMBOL_GPL(dlm_print_one_lock);
+ 
+-#if 0
+-void dlm_dump_lock_resources(struct dlm_ctxt *dlm)
+-{
+-	struct dlm_lock_resource *res;
+-	struct hlist_node *iter;
+-	struct hlist_head *bucket;
+-	int i;
+-
+-	mlog(ML_NOTICE, "struct dlm_ctxt: %s, node=%u, key=%u\n",
+-		  dlm->name, dlm->node_num, dlm->key);
+-	if (!dlm || !dlm->name) {
+-		mlog(ML_ERROR, "dlm=%p\n", dlm);
+-		return;
+-	}
+-
+-	spin_lock(&dlm->spinlock);
+-	for (i=0; i<DLM_HASH_BUCKETS; i++) {
+-		bucket = dlm_lockres_hash(dlm, i);
+-		hlist_for_each_entry(res, iter, bucket, hash_node)
+-			dlm_print_one_lock_resource(res);
+-	}
+-	spin_unlock(&dlm->spinlock);
+-}
+-#endif  /*  0  */
+-
+ static const char *dlm_errnames[] = {
+ 	[DLM_NORMAL] =			"DLM_NORMAL",
+ 	[DLM_GRANTED] =			"DLM_GRANTED",
+@@ -266,3 +244,792 @@ const char *dlm_errname(enum dlm_status err)
+ 	return dlm_errnames[err];
+ }
+ EXPORT_SYMBOL_GPL(dlm_errname);
++
++/* NOTE: This function converts a lockname into a string. It uses knowledge
++ * of the format of the lockname that should be outside the purview of the dlm.
++ * We are adding only to make dlm debugging slightly easier.
++ *
++ * For more on lockname formats, please refer to dlmglue.c and ocfs2_lockid.h.
++ */
++int stringify_lockname(const char *lockname, int locklen, char *buf, int len)
++{
++	int out = 0;
++	__be64 inode_blkno_be;
++
++#define OCFS2_DENTRY_LOCK_INO_START	18
++	if (*lockname == 'N') {
++		memcpy((__be64 *)&inode_blkno_be,
++		       (char *)&lockname[OCFS2_DENTRY_LOCK_INO_START],
++		       sizeof(__be64));
++		out += snprintf(buf + out, len - out, "%.*s%08x",
++				OCFS2_DENTRY_LOCK_INO_START - 1, lockname,
++				(unsigned int)be64_to_cpu(inode_blkno_be));
++	} else
++		out += snprintf(buf + out, len - out, "%.*s",
++				locklen, lockname);
++	return out;
++}
++
++static int stringify_nodemap(unsigned long *nodemap, int maxnodes,
++			     char *buf, int len)
++{
++	int out = 0;
++	int i = -1;
++
++	while ((i = find_next_bit(nodemap, maxnodes, i + 1)) < maxnodes)
++		out += snprintf(buf + out, len - out, "%d ", i);
++
++	return out;
++}
++
++static int dump_mle(struct dlm_master_list_entry *mle, char *buf, int len)
++{
++	int out = 0;
++	unsigned int namelen;
++	const char *name;
++	char *mle_type;
++
++	if (mle->type != DLM_MLE_MASTER) {
++		namelen = mle->u.name.len;
++		name = mle->u.name.name;
++	} else {
++		namelen = mle->u.res->lockname.len;
++		name = mle->u.res->lockname.name;
++	}
++
++	if (mle->type == DLM_MLE_BLOCK)
++		mle_type = "BLK";
++	else if (mle->type == DLM_MLE_MASTER)
++		mle_type = "MAS";
++	else
++		mle_type = "MIG";
++
++	out += stringify_lockname(name, namelen, buf + out, len - out);
++	out += snprintf(buf + out, len - out,
++			"\t%3s\tmas=%3u\tnew=%3u\tevt=%1d\tuse=%1d\tref=%3d\n",
++			mle_type, mle->master, mle->new_master,
++			!list_empty(&mle->hb_events),
++			!!mle->inuse,
++			atomic_read(&mle->mle_refs.refcount));
++
++	out += snprintf(buf + out, len - out, "Maybe=");
++	out += stringify_nodemap(mle->maybe_map, O2NM_MAX_NODES,
++				 buf + out, len - out);
++	out += snprintf(buf + out, len - out, "\n");
++
++	out += snprintf(buf + out, len - out, "Vote=");
++	out += stringify_nodemap(mle->vote_map, O2NM_MAX_NODES,
++				 buf + out, len - out);
++	out += snprintf(buf + out, len - out, "\n");
++
++	out += snprintf(buf + out, len - out, "Response=");
++	out += stringify_nodemap(mle->response_map, O2NM_MAX_NODES,
++				 buf + out, len - out);
++	out += snprintf(buf + out, len - out, "\n");
++
++	out += snprintf(buf + out, len - out, "Node=");
++	out += stringify_nodemap(mle->node_map, O2NM_MAX_NODES,
++				 buf + out, len - out);
++	out += snprintf(buf + out, len - out, "\n");
++
++	out += snprintf(buf + out, len - out, "\n");
++
++	return out;
++}
++
++void dlm_print_one_mle(struct dlm_master_list_entry *mle)
++{
++	char *buf;
++
++	buf = (char *) get_zeroed_page(GFP_NOFS);
++	if (buf) {
++		dump_mle(mle, buf, PAGE_SIZE - 1);
++		free_page((unsigned long)buf);
++	}
++}
++
++#ifdef CONFIG_DEBUG_FS
++
++static struct dentry *dlm_debugfs_root = NULL;
++
++#define DLM_DEBUGFS_DIR				"o2dlm"
++#define DLM_DEBUGFS_DLM_STATE			"dlm_state"
++#define DLM_DEBUGFS_LOCKING_STATE		"locking_state"
++#define DLM_DEBUGFS_MLE_STATE			"mle_state"
++#define DLM_DEBUGFS_PURGE_LIST			"purge_list"
++
++/* begin - utils funcs */
++static void dlm_debug_free(struct kref *kref)
++{
++	struct dlm_debug_ctxt *dc;
++
++	dc = container_of(kref, struct dlm_debug_ctxt, debug_refcnt);
++
++	kfree(dc);
++}
++
++void dlm_debug_put(struct dlm_debug_ctxt *dc)
++{
++	if (dc)
++		kref_put(&dc->debug_refcnt, dlm_debug_free);
++}
++
++static void dlm_debug_get(struct dlm_debug_ctxt *dc)
++{
++	kref_get(&dc->debug_refcnt);
++}
++
++static struct debug_buffer *debug_buffer_allocate(void)
++{
++	struct debug_buffer *db = NULL;
++
++	db = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
++	if (!db)
++		goto bail;
++
++	db->len = PAGE_SIZE;
++	db->buf = kmalloc(db->len, GFP_KERNEL);
++	if (!db->buf)
++		goto bail;
++
++	return db;
++bail:
++	kfree(db);
++	return NULL;
++}
++
++static ssize_t debug_buffer_read(struct file *file, char __user *buf,
++				 size_t nbytes, loff_t *ppos)
++{
++	struct debug_buffer *db = file->private_data;
++
++	return simple_read_from_buffer(buf, nbytes, ppos, db->buf, db->len);
++}
++
++static loff_t debug_buffer_llseek(struct file *file, loff_t off, int whence)
++{
++	struct debug_buffer *db = file->private_data;
++	loff_t new = -1;
++
++	switch (whence) {
++	case 0:
++		new = off;
++		break;
++	case 1:
++		new = file->f_pos + off;
++		break;
++	}
++
++	if (new < 0 || new > db->len)
++		return -EINVAL;
++
++	return (file->f_pos = new);
++}
++
++static int debug_buffer_release(struct inode *inode, struct file *file)
++{
++	struct debug_buffer *db = (struct debug_buffer *)file->private_data;
++
++	if (db)
++		kfree(db->buf);
++	kfree(db);
++
++	return 0;
++}
++/* end - util funcs */
++
++/* begin - purge list funcs */
++static int debug_purgelist_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
++{
++	struct dlm_lock_resource *res;
++	int out = 0;
++	unsigned long total = 0;
++
++	out += snprintf(db->buf + out, db->len - out,
++			"Dumping Purgelist for Domain: %s\n", dlm->name);
++
++	spin_lock(&dlm->spinlock);
++	list_for_each_entry(res, &dlm->purge_list, purge) {
++		++total;
++		if (db->len - out < 100)
++			continue;
++		spin_lock(&res->spinlock);
++		out += stringify_lockname(res->lockname.name,
++					  res->lockname.len,
++					  db->buf + out, db->len - out);
++		out += snprintf(db->buf + out, db->len - out, "\t%ld\n",
++				(jiffies - res->last_used)/HZ);
++		spin_unlock(&res->spinlock);
++	}
++	spin_unlock(&dlm->spinlock);
++
++	out += snprintf(db->buf + out, db->len - out,
++			"Total on list: %ld\n", total);
++
++	return out;
++}
++
++static int debug_purgelist_open(struct inode *inode, struct file *file)
++{
++	struct dlm_ctxt *dlm = inode->i_private;
++	struct debug_buffer *db;
++
++	db = debug_buffer_allocate();
++	if (!db)
++		goto bail;
++
++	db->len = debug_purgelist_print(dlm, db);
++
++	file->private_data = db;
++
++	return 0;
++bail:
++	return -ENOMEM;
++}
++
++static struct file_operations debug_purgelist_fops = {
++	.open =		debug_purgelist_open,
++	.release =	debug_buffer_release,
++	.read =		debug_buffer_read,
++	.llseek =	debug_buffer_llseek,
++};
++/* end - purge list funcs */
++
++/* begin - debug mle funcs */
++static int debug_mle_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
++{
++	struct dlm_master_list_entry *mle;
++	int out = 0;
++	unsigned long total = 0;
++
++	out += snprintf(db->buf + out, db->len - out,
++			"Dumping MLEs for Domain: %s\n", dlm->name);
++
++	spin_lock(&dlm->master_lock);
++	list_for_each_entry(mle, &dlm->master_list, list) {
++		++total;
++		if (db->len - out < 200)
++			continue;
++		out += dump_mle(mle, db->buf + out, db->len - out);
++	}
++	spin_unlock(&dlm->master_lock);
++
++	out += snprintf(db->buf + out, db->len - out,
++			"Total on list: %ld\n", total);
++	return out;
++}
++
++static int debug_mle_open(struct inode *inode, struct file *file)
++{
++	struct dlm_ctxt *dlm = inode->i_private;
++	struct debug_buffer *db;
++
++	db = debug_buffer_allocate();
++	if (!db)
++		goto bail;
++
++	db->len = debug_mle_print(dlm, db);
++
++	file->private_data = db;
++
++	return 0;
++bail:
++	return -ENOMEM;
++}
++
++static struct file_operations debug_mle_fops = {
++	.open =		debug_mle_open,
++	.release =	debug_buffer_release,
++	.read =		debug_buffer_read,
++	.llseek =	debug_buffer_llseek,
++};
++
++/* end - debug mle funcs */
++
++/* begin - debug lockres funcs */
++static int dump_lock(struct dlm_lock *lock, int list_type, char *buf, int len)
++{
++	int out;
++
++#define DEBUG_LOCK_VERSION	1
++	spin_lock(&lock->spinlock);
++	out = snprintf(buf, len, "LOCK:%d,%d,%d,%d,%d,%d:%lld,%d,%d,%d,%d,%d,"
++		       "%d,%d,%d,%d\n",
++		       DEBUG_LOCK_VERSION,
++		       list_type, lock->ml.type, lock->ml.convert_type,
++		       lock->ml.node,
++		       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
++		       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
++		       !list_empty(&lock->ast_list),
++		       !list_empty(&lock->bast_list),
++		       lock->ast_pending, lock->bast_pending,
++		       lock->convert_pending, lock->lock_pending,
++		       lock->cancel_pending, lock->unlock_pending,
++		       atomic_read(&lock->lock_refs.refcount));
++	spin_unlock(&lock->spinlock);
++
++	return out;
++}
++
++static int dump_lockres(struct dlm_lock_resource *res, char *buf, int len)
++{
++	struct dlm_lock *lock;
++	int i;
++	int out = 0;
++
++	out += snprintf(buf + out, len - out, "NAME:");
++	out += stringify_lockname(res->lockname.name, res->lockname.len,
++				  buf + out, len - out);
++	out += snprintf(buf + out, len - out, "\n");
++
++#define DEBUG_LRES_VERSION	1
++	out += snprintf(buf + out, len - out,
++			"LRES:%d,%d,%d,%ld,%d,%d,%d,%d,%d,%d,%d\n",
++			DEBUG_LRES_VERSION,
++			res->owner, res->state, res->last_used,
++			!list_empty(&res->purge),
++			!list_empty(&res->dirty),
++			!list_empty(&res->recovering),
++			res->inflight_locks, res->migration_pending,
++			atomic_read(&res->asts_reserved),
++			atomic_read(&res->refs.refcount));
++
++	/* refmap */
++	out += snprintf(buf + out, len - out, "RMAP:");
++	out += stringify_nodemap(res->refmap, O2NM_MAX_NODES,
++				 buf + out, len - out);
++	out += snprintf(buf + out, len - out, "\n");
++
++	/* lvb */
++	out += snprintf(buf + out, len - out, "LVBX:");
++	for (i = 0; i < DLM_LVB_LEN; i++)
++		out += snprintf(buf + out, len - out,
++					"%02x", (unsigned char)res->lvb[i]);
++	out += snprintf(buf + out, len - out, "\n");
++
++	/* granted */
++	list_for_each_entry(lock, &res->granted, list)
++		out += dump_lock(lock, 0, buf + out, len - out);
++
++	/* converting */
++	list_for_each_entry(lock, &res->converting, list)
++		out += dump_lock(lock, 1, buf + out, len - out);
++
++	/* blocked */
++	list_for_each_entry(lock, &res->blocked, list)
++		out += dump_lock(lock, 2, buf + out, len - out);
++
++	out += snprintf(buf + out, len - out, "\n");
++
++	return out;
++}
++
++static void *lockres_seq_start(struct seq_file *m, loff_t *pos)
++{
++	struct debug_lockres *dl = m->private;
++	struct dlm_ctxt *dlm = dl->dl_ctxt;
++	struct dlm_lock_resource *res = NULL;
++
++	spin_lock(&dlm->spinlock);
++
++	if (dl->dl_res) {
++		list_for_each_entry(res, &dl->dl_res->tracking, tracking) {
++			if (dl->dl_res) {
++				dlm_lockres_put(dl->dl_res);
++				dl->dl_res = NULL;
++			}
++			if (&res->tracking == &dlm->tracking_list) {
++				mlog(0, "End of list found, %p\n", res);
++				dl = NULL;
++				break;
++			}
++			dlm_lockres_get(res);
++			dl->dl_res = res;
++			break;
++		}
++	} else {
++		if (!list_empty(&dlm->tracking_list)) {
++			list_for_each_entry(res, &dlm->tracking_list, tracking)
++				break;
++			dlm_lockres_get(res);
++			dl->dl_res = res;
++		} else
++			dl = NULL;
++	}
++
++	if (dl) {
++		spin_lock(&dl->dl_res->spinlock);
++		dump_lockres(dl->dl_res, dl->dl_buf, dl->dl_len - 1);
++		spin_unlock(&dl->dl_res->spinlock);
++	}
++
++	spin_unlock(&dlm->spinlock);
++
++	return dl;
++}
++
++static void lockres_seq_stop(struct seq_file *m, void *v)
++{
++}
++
++static void *lockres_seq_next(struct seq_file *m, void *v, loff_t *pos)
++{
++	return NULL;
++}
++
++static int lockres_seq_show(struct seq_file *s, void *v)
++{
++	struct debug_lockres *dl = (struct debug_lockres *)v;
++
++	seq_printf(s, "%s", dl->dl_buf);
++
++	return 0;
++}
++
++static struct seq_operations debug_lockres_ops = {
++	.start =	lockres_seq_start,
++	.stop =		lockres_seq_stop,
++	.next =		lockres_seq_next,
++	.show =		lockres_seq_show,
++};
++
++static int debug_lockres_open(struct inode *inode, struct file *file)
++{
++	struct dlm_ctxt *dlm = inode->i_private;
++	int ret = -ENOMEM;
++	struct seq_file *seq;
++	struct debug_lockres *dl = NULL;
++
++	dl = kzalloc(sizeof(struct debug_lockres), GFP_KERNEL);
++	if (!dl) {
++		mlog_errno(ret);
++		goto bail;
++	}
++
++	dl->dl_len = PAGE_SIZE;
++	dl->dl_buf = kmalloc(dl->dl_len, GFP_KERNEL);
++	if (!dl->dl_buf) {
++		mlog_errno(ret);
++		goto bail;
++	}
++
++	ret = seq_open(file, &debug_lockres_ops);
++	if (ret) {
++		mlog_errno(ret);
++		goto bail;
++	}
++
++	seq = (struct seq_file *) file->private_data;
++	seq->private = dl;
++
++	dlm_grab(dlm);
++	dl->dl_ctxt = dlm;
++
++	return 0;
++bail:
++	if (dl)
++		kfree(dl->dl_buf);
++	kfree(dl);
++	return ret;
++}
++
++static int debug_lockres_release(struct inode *inode, struct file *file)
++{
++	struct seq_file *seq = (struct seq_file *)file->private_data;
++	struct debug_lockres *dl = (struct debug_lockres *)seq->private;
++
++	if (dl->dl_res)
++		dlm_lockres_put(dl->dl_res);
++	dlm_put(dl->dl_ctxt);
++	kfree(dl->dl_buf);
++	return seq_release_private(inode, file);
++}
++
++static struct file_operations debug_lockres_fops = {
++	.open =		debug_lockres_open,
++	.release =	debug_lockres_release,
++	.read =		seq_read,
++	.llseek =	seq_lseek,
++};
++/* end - debug lockres funcs */
++
++/* begin - debug state funcs */
++static int debug_state_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
++{
++	int out = 0;
++	struct dlm_reco_node_data *node;
++	char *state;
++	int lres, rres, ures, tres;
++
++	lres = atomic_read(&dlm->local_resources);
++	rres = atomic_read(&dlm->remote_resources);
++	ures = atomic_read(&dlm->unknown_resources);
++	tres = lres + rres + ures;
++
++	spin_lock(&dlm->spinlock);
++
++	switch (dlm->dlm_state) {
++	case DLM_CTXT_NEW:
++		state = "NEW"; break;
++	case DLM_CTXT_JOINED:
++		state = "JOINED"; break;
++	case DLM_CTXT_IN_SHUTDOWN:
++		state = "SHUTDOWN"; break;
++	case DLM_CTXT_LEAVING:
++		state = "LEAVING"; break;
++	default:
++		state = "UNKNOWN"; break;
++	}
++
++	/* Domain: xxxxxxxxxx  Key: 0xdfbac769 */
++	out += snprintf(db->buf + out, db->len - out,
++			"Domain: %s  Key: 0x%08x\n", dlm->name, dlm->key);
++
++	/* Thread Pid: xxx  Node: xxx  State: xxxxx */
++	out += snprintf(db->buf + out, db->len - out,
++			"Thread Pid: %d  Node: %d  State: %s\n",
++			dlm->dlm_thread_task->pid, dlm->node_num, state);
++
++	/* Number of Joins: xxx  Joining Node: xxx */
++	out += snprintf(db->buf + out, db->len - out,
++			"Number of Joins: %d  Joining Node: %d\n",
++			dlm->num_joins, dlm->joining_node);
++
++	/* Domain Map: xx xx xx */
++	out += snprintf(db->buf + out, db->len - out, "Domain Map: ");
++	out += stringify_nodemap(dlm->domain_map, O2NM_MAX_NODES,
++				 db->buf + out, db->len - out);
++	out += snprintf(db->buf + out, db->len - out, "\n");
++
++	/* Live Map: xx xx xx */
++	out += snprintf(db->buf + out, db->len - out, "Live Map: ");
++	out += stringify_nodemap(dlm->live_nodes_map, O2NM_MAX_NODES,
++				 db->buf + out, db->len - out);
++	out += snprintf(db->buf + out, db->len - out, "\n");
++
++	/* Mastered Resources Total: xxx  Locally: xxx  Remotely: ... */
++	out += snprintf(db->buf + out, db->len - out,
++			"Mastered Resources Total: %d  Locally: %d  "
++			"Remotely: %d  Unknown: %d\n",
++			tres, lres, rres, ures);
++
++	/* Lists: Dirty=Empty  Purge=InUse  PendingASTs=Empty  ... */
++	out += snprintf(db->buf + out, db->len - out,
++			"Lists: Dirty=%s  Purge=%s  PendingASTs=%s  "
++			"PendingBASTs=%s  Master=%s\n",
++			(list_empty(&dlm->dirty_list) ? "Empty" : "InUse"),
++			(list_empty(&dlm->purge_list) ? "Empty" : "InUse"),
++			(list_empty(&dlm->pending_asts) ? "Empty" : "InUse"),
++			(list_empty(&dlm->pending_basts) ? "Empty" : "InUse"),
++			(list_empty(&dlm->master_list) ? "Empty" : "InUse"));
++
++	/* Purge Count: xxx  Refs: xxx */
++	out += snprintf(db->buf + out, db->len - out,
++			"Purge Count: %d  Refs: %d\n", dlm->purge_count,
++			atomic_read(&dlm->dlm_refs.refcount));
++
++	/* Dead Node: xxx */
++	out += snprintf(db->buf + out, db->len - out,
++			"Dead Node: %d\n", dlm->reco.dead_node);
++
++	/* What about DLM_RECO_STATE_FINALIZE? */
++	if (dlm->reco.state == DLM_RECO_STATE_ACTIVE)
++		state = "ACTIVE";
++	else
++		state = "INACTIVE";
++
++	/* Recovery Pid: xxxx  Master: xxx  State: xxxx */
++	out += snprintf(db->buf + out, db->len - out,
++			"Recovery Pid: %d  Master: %d  State: %s\n",
++			dlm->dlm_reco_thread_task->pid,
++			dlm->reco.new_master, state);
++
++	/* Recovery Map: xx xx */
++	out += snprintf(db->buf + out, db->len - out, "Recovery Map: ");
++	out += stringify_nodemap(dlm->recovery_map, O2NM_MAX_NODES,
++				 db->buf + out, db->len - out);
++	out += snprintf(db->buf + out, db->len - out, "\n");
++
++	/* Recovery Node State: */
++	out += snprintf(db->buf + out, db->len - out, "Recovery Node State:\n");
++	list_for_each_entry(node, &dlm->reco.node_data, list) {
++		switch (node->state) {
++		case DLM_RECO_NODE_DATA_INIT:
++			state = "INIT";
++			break;
++		case DLM_RECO_NODE_DATA_REQUESTING:
++			state = "REQUESTING";
++			break;
++		case DLM_RECO_NODE_DATA_DEAD:
++			state = "DEAD";
++			break;
++		case DLM_RECO_NODE_DATA_RECEIVING:
++			state = "RECEIVING";
++			break;
++		case DLM_RECO_NODE_DATA_REQUESTED:
++			state = "REQUESTED";
++			break;
++		case DLM_RECO_NODE_DATA_DONE:
++			state = "DONE";
++			break;
++		case DLM_RECO_NODE_DATA_FINALIZE_SENT:
++			state = "FINALIZE-SENT";
++			break;
++		default:
++			state = "BAD";
++			break;
++		}
++		out += snprintf(db->buf + out, db->len - out, "\t%u - %s\n",
++				node->node_num, state);
++	}
++
++	spin_unlock(&dlm->spinlock);
++
++	return out;
++}
++
++static int debug_state_open(struct inode *inode, struct file *file)
++{
++	struct dlm_ctxt *dlm = inode->i_private;
++	struct debug_buffer *db = NULL;
++
++	db = debug_buffer_allocate();
++	if (!db)
++		goto bail;
++
++	db->len = debug_state_print(dlm, db);
++
++	file->private_data = db;
++
++	return 0;
++bail:
++	return -ENOMEM;
++}
++
++static struct file_operations debug_state_fops = {
++	.open =		debug_state_open,
++	.release =	debug_buffer_release,
++	.read =		debug_buffer_read,
++	.llseek =	debug_buffer_llseek,
++};
++/* end  - debug state funcs */
++
++/* files in subroot */
++int dlm_debug_init(struct dlm_ctxt *dlm)
++{
++	struct dlm_debug_ctxt *dc = dlm->dlm_debug_ctxt;
++
++	/* for dumping dlm_ctxt */
++	dc->debug_state_dentry = debugfs_create_file(DLM_DEBUGFS_DLM_STATE,
++						     S_IFREG|S_IRUSR,
++						     dlm->dlm_debugfs_subroot,
++						     dlm, &debug_state_fops);
++	if (!dc->debug_state_dentry) {
++		mlog_errno(-ENOMEM);
++		goto bail;
++	}
++
++	/* for dumping lockres */
++	dc->debug_lockres_dentry =
++			debugfs_create_file(DLM_DEBUGFS_LOCKING_STATE,
++					    S_IFREG|S_IRUSR,
++					    dlm->dlm_debugfs_subroot,
++					    dlm, &debug_lockres_fops);
++	if (!dc->debug_lockres_dentry) {
++		mlog_errno(-ENOMEM);
++		goto bail;
++	}
++
++	/* for dumping mles */
++	dc->debug_mle_dentry = debugfs_create_file(DLM_DEBUGFS_MLE_STATE,
++						   S_IFREG|S_IRUSR,
++						   dlm->dlm_debugfs_subroot,
++						   dlm, &debug_mle_fops);
++	if (!dc->debug_mle_dentry) {
++		mlog_errno(-ENOMEM);
++		goto bail;
++	}
++
++	/* for dumping lockres on the purge list */
++	dc->debug_purgelist_dentry =
++			debugfs_create_file(DLM_DEBUGFS_PURGE_LIST,
++					    S_IFREG|S_IRUSR,
++					    dlm->dlm_debugfs_subroot,
++					    dlm, &debug_purgelist_fops);
++	if (!dc->debug_purgelist_dentry) {
++		mlog_errno(-ENOMEM);
++		goto bail;
++	}
++
++	dlm_debug_get(dc);
++	return 0;
++
++bail:
++	dlm_debug_shutdown(dlm);
++	return -ENOMEM;
++}
++
++void dlm_debug_shutdown(struct dlm_ctxt *dlm)
++{
++	struct dlm_debug_ctxt *dc = dlm->dlm_debug_ctxt;
++
++	if (dc) {
++		if (dc->debug_purgelist_dentry)
++			debugfs_remove(dc->debug_purgelist_dentry);
++		if (dc->debug_mle_dentry)
++			debugfs_remove(dc->debug_mle_dentry);
++		if (dc->debug_lockres_dentry)
++			debugfs_remove(dc->debug_lockres_dentry);
++		if (dc->debug_state_dentry)
++			debugfs_remove(dc->debug_state_dentry);
++		dlm_debug_put(dc);
++	}
++}
++
++/* subroot - domain dir */
++int dlm_create_debugfs_subroot(struct dlm_ctxt *dlm)
++{
++	dlm->dlm_debugfs_subroot = debugfs_create_dir(dlm->name,
++						      dlm_debugfs_root);
++	if (!dlm->dlm_debugfs_subroot) {
++		mlog_errno(-ENOMEM);
++		goto bail;
++	}
++
++	dlm->dlm_debug_ctxt = kzalloc(sizeof(struct dlm_debug_ctxt),
++				      GFP_KERNEL);
++	if (!dlm->dlm_debug_ctxt) {
++		mlog_errno(-ENOMEM);
++		goto bail;
++	}
++	kref_init(&dlm->dlm_debug_ctxt->debug_refcnt);
++
++	return 0;
++bail:
++	dlm_destroy_debugfs_subroot(dlm);
++	return -ENOMEM;
++}
++
++void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm)
++{
++	if (dlm->dlm_debugfs_subroot)
++		debugfs_remove(dlm->dlm_debugfs_subroot);
++}
++
++/* debugfs root */
++int dlm_create_debugfs_root(void)
++{
++	dlm_debugfs_root = debugfs_create_dir(DLM_DEBUGFS_DIR, NULL);
++	if (!dlm_debugfs_root) {
++		mlog_errno(-ENOMEM);
++		return -ENOMEM;
++	}
++	return 0;
++}
++
++void dlm_destroy_debugfs_root(void)
++{
++	if (dlm_debugfs_root)
++		debugfs_remove(dlm_debugfs_root);
++}
++#endif	/* CONFIG_DEBUG_FS */
+diff --git a/fs/ocfs2/dlm/dlmdebug.h b/fs/ocfs2/dlm/dlmdebug.h
+new file mode 100644
+index 0000000..d34a62a
+--- /dev/null
++++ b/fs/ocfs2/dlm/dlmdebug.h
+@@ -0,0 +1,86 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * dlmdebug.h
++ *
++ * Copyright (C) 2008 Oracle.  All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public
++ * License along with this program; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 021110-1307, USA.
++ *
++ */
++
++#ifndef DLMDEBUG_H
++#define DLMDEBUG_H
++
++void dlm_print_one_mle(struct dlm_master_list_entry *mle);
++
++#ifdef CONFIG_DEBUG_FS
++
++struct dlm_debug_ctxt {
++	struct kref debug_refcnt;
++	struct dentry *debug_state_dentry;
++	struct dentry *debug_lockres_dentry;
++	struct dentry *debug_mle_dentry;
++	struct dentry *debug_purgelist_dentry;
++};
++
++struct debug_buffer {
++	int len;
++	char *buf;
++};
++
++struct debug_lockres {
++	int dl_len;
++	char *dl_buf;
++	struct dlm_ctxt *dl_ctxt;
++	struct dlm_lock_resource *dl_res;
++};
++
++int dlm_debug_init(struct dlm_ctxt *dlm);
++void dlm_debug_shutdown(struct dlm_ctxt *dlm);
++
++int dlm_create_debugfs_subroot(struct dlm_ctxt *dlm);
++void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm);
++
++int dlm_create_debugfs_root(void);
++void dlm_destroy_debugfs_root(void);
++
++#else
++
++static int dlm_debug_init(struct dlm_ctxt *dlm)
++{
++	return 0;
++}
++static void dlm_debug_shutdown(struct dlm_ctxt *dlm)
++{
++}
++static int dlm_create_debugfs_subroot(struct dlm_ctxt *dlm)
++{
++	return 0;
++}
++static void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm)
++{
++}
++static int dlm_create_debugfs_root(void)
++{
++	return 0;
++}
++static void dlm_destroy_debugfs_root(void)
++{
++}
++
++#endif	/* CONFIG_DEBUG_FS */
++#endif	/* DLMDEBUG_H */
+diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
+index 0879d86..63f8125 100644
+--- a/fs/ocfs2/dlm/dlmdomain.c
++++ b/fs/ocfs2/dlm/dlmdomain.c
+@@ -33,6 +33,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/delay.h>
+ #include <linux/err.h>
++#include <linux/debugfs.h>
+ 
+ #include "cluster/heartbeat.h"
+ #include "cluster/nodemanager.h"
+@@ -40,8 +41,8 @@
+ 
+ #include "dlmapi.h"
+ #include "dlmcommon.h"
+-
+ #include "dlmdomain.h"
++#include "dlmdebug.h"
+ 
+ #include "dlmver.h"
+ 
+@@ -298,6 +299,8 @@ static int dlm_wait_on_domain_helper(const char *domain)
+ 
+ static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm)
+ {
++	dlm_destroy_debugfs_subroot(dlm);
++
+ 	if (dlm->lockres_hash)
+ 		dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES);
+ 
+@@ -395,6 +398,7 @@ static void dlm_destroy_dlm_worker(struct dlm_ctxt *dlm)
+ static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm)
+ {
+ 	dlm_unregister_domain_handlers(dlm);
++	dlm_debug_shutdown(dlm);
+ 	dlm_complete_thread(dlm);
+ 	dlm_complete_recovery_thread(dlm);
+ 	dlm_destroy_dlm_worker(dlm);
+@@ -644,6 +648,7 @@ int dlm_shutting_down(struct dlm_ctxt *dlm)
+ void dlm_unregister_domain(struct dlm_ctxt *dlm)
+ {
+ 	int leave = 0;
++	struct dlm_lock_resource *res;
+ 
+ 	spin_lock(&dlm_domain_lock);
+ 	BUG_ON(dlm->dlm_state != DLM_CTXT_JOINED);
+@@ -673,6 +678,15 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm)
+ 			msleep(500);
+ 			mlog(0, "%s: more migration to do\n", dlm->name);
+ 		}
++
++		/* This list should be empty. If not, print remaining lockres */
++		if (!list_empty(&dlm->tracking_list)) {
++			mlog(ML_ERROR, "Following lockres' are still on the "
++			     "tracking list:\n");
++			list_for_each_entry(res, &dlm->tracking_list, tracking)
++				dlm_print_one_lock_resource(res);
++		}
++
+ 		dlm_mark_domain_leaving(dlm);
+ 		dlm_leave_domain(dlm);
+ 		dlm_complete_dlm_shutdown(dlm);
+@@ -1405,6 +1419,12 @@ static int dlm_join_domain(struct dlm_ctxt *dlm)
+ 		goto bail;
+ 	}
+ 
++	status = dlm_debug_init(dlm);
++	if (status < 0) {
++		mlog_errno(status);
++		goto bail;
++	}
++
+ 	status = dlm_launch_thread(dlm);
+ 	if (status < 0) {
+ 		mlog_errno(status);
+@@ -1472,6 +1492,7 @@ bail:
+ 
+ 	if (status) {
+ 		dlm_unregister_domain_handlers(dlm);
++		dlm_debug_shutdown(dlm);
+ 		dlm_complete_thread(dlm);
+ 		dlm_complete_recovery_thread(dlm);
+ 		dlm_destroy_dlm_worker(dlm);
+@@ -1484,6 +1505,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
+ 				u32 key)
+ {
+ 	int i;
++	int ret;
+ 	struct dlm_ctxt *dlm = NULL;
+ 
+ 	dlm = kzalloc(sizeof(*dlm), GFP_KERNEL);
+@@ -1516,6 +1538,15 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
+ 	dlm->key = key;
+ 	dlm->node_num = o2nm_this_node();
+ 
++	ret = dlm_create_debugfs_subroot(dlm);
++	if (ret < 0) {
++		dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES);
++		kfree(dlm->name);
++		kfree(dlm);
++		dlm = NULL;
++		goto leave;
++	}
++
+ 	spin_lock_init(&dlm->spinlock);
+ 	spin_lock_init(&dlm->master_lock);
+ 	spin_lock_init(&dlm->ast_lock);
+@@ -1526,6 +1557,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
+ 	INIT_LIST_HEAD(&dlm->reco.node_data);
+ 	INIT_LIST_HEAD(&dlm->purge_list);
+ 	INIT_LIST_HEAD(&dlm->dlm_domain_handlers);
++	INIT_LIST_HEAD(&dlm->tracking_list);
+ 	dlm->reco.state = 0;
+ 
+ 	INIT_LIST_HEAD(&dlm->pending_asts);
+@@ -1816,21 +1848,49 @@ static int __init dlm_init(void)
+ 	dlm_print_version();
+ 
+ 	status = dlm_init_mle_cache();
+-	if (status)
+-		return -1;
++	if (status) {
++		mlog(ML_ERROR, "Could not create o2dlm_mle slabcache\n");
++		goto error;
++	}
++
++	status = dlm_init_master_caches();
++	if (status) {
++		mlog(ML_ERROR, "Could not create o2dlm_lockres and "
++		     "o2dlm_lockname slabcaches\n");
++		goto error;
++	}
++
++	status = dlm_init_lock_cache();
++	if (status) {
++		mlog(ML_ERROR, "Count not create o2dlm_lock slabcache\n");
++		goto error;
++	}
+ 
+ 	status = dlm_register_net_handlers();
+ 	if (status) {
+-		dlm_destroy_mle_cache();
+-		return -1;
++		mlog(ML_ERROR, "Unable to register network handlers\n");
++		goto error;
+ 	}
+ 
++	status = dlm_create_debugfs_root();
++	if (status)
++		goto error;
++
+ 	return 0;
++error:
++	dlm_unregister_net_handlers();
++	dlm_destroy_lock_cache();
++	dlm_destroy_master_caches();
++	dlm_destroy_mle_cache();
++	return -1;
+ }
+ 
+ static void __exit dlm_exit (void)
+ {
++	dlm_destroy_debugfs_root();
+ 	dlm_unregister_net_handlers();
++	dlm_destroy_lock_cache();
++	dlm_destroy_master_caches();
+ 	dlm_destroy_mle_cache();
+ }
+ 
+diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
+index 52578d9..83a9f29 100644
+--- a/fs/ocfs2/dlm/dlmlock.c
++++ b/fs/ocfs2/dlm/dlmlock.c
+@@ -53,6 +53,8 @@
+ #define MLOG_MASK_PREFIX ML_DLM
+ #include "cluster/masklog.h"
+ 
++static struct kmem_cache *dlm_lock_cache = NULL;
++
+ static DEFINE_SPINLOCK(dlm_cookie_lock);
+ static u64 dlm_next_cookie = 1;
+ 
+@@ -64,6 +66,22 @@ static void dlm_init_lock(struct dlm_lock *newlock, int type,
+ static void dlm_lock_release(struct kref *kref);
+ static void dlm_lock_detach_lockres(struct dlm_lock *lock);
+ 
++int dlm_init_lock_cache(void)
++{
++	dlm_lock_cache = kmem_cache_create("o2dlm_lock",
++					   sizeof(struct dlm_lock),
++					   0, SLAB_HWCACHE_ALIGN, NULL);
++	if (dlm_lock_cache == NULL)
++		return -ENOMEM;
++	return 0;
++}
++
++void dlm_destroy_lock_cache(void)
++{
++	if (dlm_lock_cache)
++		kmem_cache_destroy(dlm_lock_cache);
++}
++
+ /* Tell us whether we can grant a new lock request.
+  * locking:
+  *   caller needs:  res->spinlock
+@@ -353,7 +371,7 @@ static void dlm_lock_release(struct kref *kref)
+ 		mlog(0, "freeing kernel-allocated lksb\n");
+ 		kfree(lock->lksb);
+ 	}
+-	kfree(lock);
++	kmem_cache_free(dlm_lock_cache, lock);
+ }
+ 
+ /* associate a lock with it's lockres, getting a ref on the lockres */
+@@ -412,7 +430,7 @@ struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
+ 	struct dlm_lock *lock;
+ 	int kernel_allocated = 0;
+ 
+-	lock = kzalloc(sizeof(*lock), GFP_NOFS);
++	lock = (struct dlm_lock *) kmem_cache_zalloc(dlm_lock_cache, GFP_NOFS);
+ 	if (!lock)
+ 		return NULL;
+ 
+diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
+index ea6b895..efc015c 100644
+--- a/fs/ocfs2/dlm/dlmmaster.c
++++ b/fs/ocfs2/dlm/dlmmaster.c
+@@ -48,47 +48,11 @@
+ #include "dlmapi.h"
+ #include "dlmcommon.h"
+ #include "dlmdomain.h"
++#include "dlmdebug.h"
+ 
+ #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_MASTER)
+ #include "cluster/masklog.h"
+ 
+-enum dlm_mle_type {
+-	DLM_MLE_BLOCK,
+-	DLM_MLE_MASTER,
+-	DLM_MLE_MIGRATION
+-};
+-
+-struct dlm_lock_name
+-{
+-	u8 len;
+-	u8 name[DLM_LOCKID_NAME_MAX];
+-};
+-
+-struct dlm_master_list_entry
+-{
+-	struct list_head list;
+-	struct list_head hb_events;
+-	struct dlm_ctxt *dlm;
+-	spinlock_t spinlock;
+-	wait_queue_head_t wq;
+-	atomic_t woken;
+-	struct kref mle_refs;
+-	int inuse;
+-	unsigned long maybe_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+-	unsigned long vote_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+-	unsigned long response_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+-	unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+-	u8 master;
+-	u8 new_master;
+-	enum dlm_mle_type type;
+-	struct o2hb_callback_func mle_hb_up;
+-	struct o2hb_callback_func mle_hb_down;
+-	union {
+-		struct dlm_lock_resource *res;
+-		struct dlm_lock_name name;
+-	} u;
+-};
+-
+ static void dlm_mle_node_down(struct dlm_ctxt *dlm,
+ 			      struct dlm_master_list_entry *mle,
+ 			      struct o2nm_node *node,
+@@ -128,98 +92,10 @@ static inline int dlm_mle_equal(struct dlm_ctxt *dlm,
+ 	return 1;
+ }
+ 
+-#define dlm_print_nodemap(m)  _dlm_print_nodemap(m,#m)
+-static void _dlm_print_nodemap(unsigned long *map, const char *mapname)
+-{
+-	int i;
+-	printk("%s=[ ", mapname);
+-	for (i=0; i<O2NM_MAX_NODES; i++)
+-		if (test_bit(i, map))
+-			printk("%d ", i);
+-	printk("]");
+-}
+-
+-static void dlm_print_one_mle(struct dlm_master_list_entry *mle)
+-{
+-	int refs;
+-	char *type;
+-	char attached;
+-	u8 master;
+-	unsigned int namelen;
+-	const char *name;
+-	struct kref *k;
+-	unsigned long *maybe = mle->maybe_map,
+-		      *vote = mle->vote_map,
+-		      *resp = mle->response_map,
+-		      *node = mle->node_map;
+-
+-	k = &mle->mle_refs;
+-	if (mle->type == DLM_MLE_BLOCK)
+-		type = "BLK";
+-	else if (mle->type == DLM_MLE_MASTER)
+-		type = "MAS";
+-	else
+-		type = "MIG";
+-	refs = atomic_read(&k->refcount);
+-	master = mle->master;
+-	attached = (list_empty(&mle->hb_events) ? 'N' : 'Y');
+-
+-	if (mle->type != DLM_MLE_MASTER) {
+-		namelen = mle->u.name.len;
+-		name = mle->u.name.name;
+-	} else {
+-		namelen = mle->u.res->lockname.len;
+-		name = mle->u.res->lockname.name;
+-	}
+-
+-	mlog(ML_NOTICE, "%.*s: %3s refs=%3d mas=%3u new=%3u evt=%c inuse=%d ",
+-		  namelen, name, type, refs, master, mle->new_master, attached,
+-		  mle->inuse);
+-	dlm_print_nodemap(maybe);
+-	printk(", ");
+-	dlm_print_nodemap(vote);
+-	printk(", ");
+-	dlm_print_nodemap(resp);
+-	printk(", ");
+-	dlm_print_nodemap(node);
+-	printk(", ");
+-	printk("\n");
+-}
+-
+-#if 0
+-/* Code here is included but defined out as it aids debugging */
+-
+-static void dlm_dump_mles(struct dlm_ctxt *dlm)
+-{
+-	struct dlm_master_list_entry *mle;
+-	
+-	mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
+-	spin_lock(&dlm->master_lock);
+-	list_for_each_entry(mle, &dlm->master_list, list)
+-		dlm_print_one_mle(mle);
+-	spin_unlock(&dlm->master_lock);
+-}
+-
+-int dlm_dump_all_mles(const char __user *data, unsigned int len)
+-{
+-	struct dlm_ctxt *dlm;
+-
+-	spin_lock(&dlm_domain_lock);
+-	list_for_each_entry(dlm, &dlm_domains, list) {
+-		mlog(ML_NOTICE, "found dlm: %p, name=%s\n", dlm, dlm->name);
+-		dlm_dump_mles(dlm);
+-	}
+-	spin_unlock(&dlm_domain_lock);
+-	return len;
+-}
+-EXPORT_SYMBOL_GPL(dlm_dump_all_mles);
+-
+-#endif  /*  0  */
+-
+-
++static struct kmem_cache *dlm_lockres_cache = NULL;
++static struct kmem_cache *dlm_lockname_cache = NULL;
+ static struct kmem_cache *dlm_mle_cache = NULL;
+ 
+-
+ static void dlm_mle_release(struct kref *kref);
+ static void dlm_init_mle(struct dlm_master_list_entry *mle,
+ 			enum dlm_mle_type type,
+@@ -507,7 +383,7 @@ static void dlm_mle_node_up(struct dlm_ctxt *dlm,
+ 
+ int dlm_init_mle_cache(void)
+ {
+-	dlm_mle_cache = kmem_cache_create("dlm_mle_cache",
++	dlm_mle_cache = kmem_cache_create("o2dlm_mle",
+ 					  sizeof(struct dlm_master_list_entry),
+ 					  0, SLAB_HWCACHE_ALIGN,
+ 					  NULL);
+@@ -560,6 +436,35 @@ static void dlm_mle_release(struct kref *kref)
+  * LOCK RESOURCE FUNCTIONS
+  */
+ 
++int dlm_init_master_caches(void)
++{
++	dlm_lockres_cache = kmem_cache_create("o2dlm_lockres",
++					      sizeof(struct dlm_lock_resource),
++					      0, SLAB_HWCACHE_ALIGN, NULL);
++	if (!dlm_lockres_cache)
++		goto bail;
++
++	dlm_lockname_cache = kmem_cache_create("o2dlm_lockname",
++					       DLM_LOCKID_NAME_MAX, 0,
++					       SLAB_HWCACHE_ALIGN, NULL);
++	if (!dlm_lockname_cache)
++		goto bail;
++
++	return 0;
++bail:
++	dlm_destroy_master_caches();
++	return -ENOMEM;
++}
++
++void dlm_destroy_master_caches(void)
++{
++	if (dlm_lockname_cache)
++		kmem_cache_destroy(dlm_lockname_cache);
++
++	if (dlm_lockres_cache)
++		kmem_cache_destroy(dlm_lockres_cache);
++}
++
+ static void dlm_set_lockres_owner(struct dlm_ctxt *dlm,
+ 				  struct dlm_lock_resource *res,
+ 				  u8 owner)
+@@ -610,6 +515,14 @@ static void dlm_lockres_release(struct kref *kref)
+ 	mlog(0, "destroying lockres %.*s\n", res->lockname.len,
+ 	     res->lockname.name);
+ 
++	if (!list_empty(&res->tracking))
++		list_del_init(&res->tracking);
++	else {
++		mlog(ML_ERROR, "Resource %.*s not on the Tracking list\n",
++		     res->lockname.len, res->lockname.name);
++		dlm_print_one_lock_resource(res);
++	}
++
+ 	if (!hlist_unhashed(&res->hash_node) ||
+ 	    !list_empty(&res->granted) ||
+ 	    !list_empty(&res->converting) ||
+@@ -642,9 +555,9 @@ static void dlm_lockres_release(struct kref *kref)
+ 	BUG_ON(!list_empty(&res->recovering));
+ 	BUG_ON(!list_empty(&res->purge));
+ 
+-	kfree(res->lockname.name);
++	kmem_cache_free(dlm_lockname_cache, (void *)res->lockname.name);
+ 
+-	kfree(res);
++	kmem_cache_free(dlm_lockres_cache, res);
+ }
+ 
+ void dlm_lockres_put(struct dlm_lock_resource *res)
+@@ -677,6 +590,7 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
+ 	INIT_LIST_HEAD(&res->dirty);
+ 	INIT_LIST_HEAD(&res->recovering);
+ 	INIT_LIST_HEAD(&res->purge);
++	INIT_LIST_HEAD(&res->tracking);
+ 	atomic_set(&res->asts_reserved, 0);
+ 	res->migration_pending = 0;
+ 	res->inflight_locks = 0;
+@@ -692,6 +606,8 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
+ 
+ 	res->last_used = 0;
+ 
++	list_add_tail(&res->tracking, &dlm->tracking_list);
++
+ 	memset(res->lvb, 0, DLM_LVB_LEN);
+ 	memset(res->refmap, 0, sizeof(res->refmap));
+ }
+@@ -700,20 +616,28 @@ struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm,
+ 				   const char *name,
+ 				   unsigned int namelen)
+ {
+-	struct dlm_lock_resource *res;
++	struct dlm_lock_resource *res = NULL;
+ 
+-	res = kmalloc(sizeof(struct dlm_lock_resource), GFP_NOFS);
++	res = (struct dlm_lock_resource *)
++				kmem_cache_zalloc(dlm_lockres_cache, GFP_NOFS);
+ 	if (!res)
+-		return NULL;
++		goto error;
+ 
+-	res->lockname.name = kmalloc(namelen, GFP_NOFS);
+-	if (!res->lockname.name) {
+-		kfree(res);
+-		return NULL;
+-	}
++	res->lockname.name = (char *)
++				kmem_cache_zalloc(dlm_lockname_cache, GFP_NOFS);
++	if (!res->lockname.name)
++		goto error;
+ 
+ 	dlm_init_lockres(dlm, res, name, namelen);
+ 	return res;
++
++error:
++	if (res && res->lockname.name)
++		kmem_cache_free(dlm_lockname_cache, (void *)res->lockname.name);
++
++	if (res)
++		kmem_cache_free(dlm_lockres_cache, res);
++	return NULL;
+ }
+ 
+ void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
+diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
+index 1f1873b..394d25a 100644
+--- a/fs/ocfs2/dlmglue.c
++++ b/fs/ocfs2/dlmglue.c
+@@ -27,18 +27,11 @@
+ #include <linux/slab.h>
+ #include <linux/highmem.h>
+ #include <linux/mm.h>
+-#include <linux/crc32.h>
+ #include <linux/kthread.h>
+ #include <linux/pagemap.h>
+ #include <linux/debugfs.h>
+ #include <linux/seq_file.h>
+ 
+-#include <cluster/heartbeat.h>
+-#include <cluster/nodemanager.h>
+-#include <cluster/tcp.h>
+-
+-#include <dlm/dlmapi.h>
+-
+ #define MLOG_MASK_PREFIX ML_DLM_GLUE
+ #include <cluster/masklog.h>
+ 
+@@ -53,6 +46,7 @@
+ #include "heartbeat.h"
+ #include "inode.h"
+ #include "journal.h"
++#include "stackglue.h"
+ #include "slot_map.h"
+ #include "super.h"
+ #include "uptodate.h"
+@@ -113,7 +107,8 @@ static void ocfs2_dump_meta_lvb_info(u64 level,
+ 				     unsigned int line,
+ 				     struct ocfs2_lock_res *lockres)
+ {
+-	struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
++	struct ocfs2_meta_lvb *lvb =
++		(struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+ 
+ 	mlog(level, "LVB information for %s (called from %s:%u):\n",
+ 	     lockres->l_name, function, line);
+@@ -259,31 +254,6 @@ static struct ocfs2_lock_res_ops ocfs2_flock_lops = {
+ 	.flags		= 0,
+ };
+ 
+-/*
+- * This is the filesystem locking protocol version.
+- *
+- * Whenever the filesystem does new things with locks (adds or removes a
+- * lock, orders them differently, does different things underneath a lock),
+- * the version must be changed.  The protocol is negotiated when joining
+- * the dlm domain.  A node may join the domain if its major version is
+- * identical to all other nodes and its minor version is greater than
+- * or equal to all other nodes.  When its minor version is greater than
+- * the other nodes, it will run at the minor version specified by the
+- * other nodes.
+- *
+- * If a locking change is made that will not be compatible with older
+- * versions, the major number must be increased and the minor version set
+- * to zero.  If a change merely adds a behavior that can be disabled when
+- * speaking to older versions, the minor version must be increased.  If a
+- * change adds a fully backwards compatible change (eg, LVB changes that
+- * are just ignored by older versions), the version does not need to be
+- * updated.
+- */
+-const struct dlm_protocol_version ocfs2_locking_protocol = {
+-	.pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR,
+-	.pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
+-};
+-
+ static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
+ {
+ 	return lockres->l_type == OCFS2_LOCK_TYPE_META ||
+@@ -316,7 +286,7 @@ static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *l
+ static int ocfs2_lock_create(struct ocfs2_super *osb,
+ 			     struct ocfs2_lock_res *lockres,
+ 			     int level,
+-			     int dlm_flags);
++			     u32 dlm_flags);
+ static inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres,
+ 						     int wanted);
+ static void ocfs2_cluster_unlock(struct ocfs2_super *osb,
+@@ -330,10 +300,9 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
+ 					struct ocfs2_lock_res *lockres);
+ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
+ 						int convert);
+-#define ocfs2_log_dlm_error(_func, _stat, _lockres) do {	\
+-	mlog(ML_ERROR, "Dlm error \"%s\" while calling %s on "	\
+-		"resource %s: %s\n", dlm_errname(_stat), _func,	\
+-		_lockres->l_name, dlm_errmsg(_stat));		\
++#define ocfs2_log_dlm_error(_func, _err, _lockres) do {			\
++	mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n", \
++	     _err, _func, _lockres->l_name);				\
+ } while (0)
+ static int ocfs2_downconvert_thread(void *arg);
+ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
+@@ -342,12 +311,13 @@ static int ocfs2_inode_lock_update(struct inode *inode,
+ 				  struct buffer_head **bh);
+ static void ocfs2_drop_osb_locks(struct ocfs2_super *osb);
+ static inline int ocfs2_highest_compat_lock_level(int level);
+-static void ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
+-				      int new_level);
++static unsigned int ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
++					      int new_level);
+ static int ocfs2_downconvert_lock(struct ocfs2_super *osb,
+ 				  struct ocfs2_lock_res *lockres,
+ 				  int new_level,
+-				  int lvb);
++				  int lvb,
++				  unsigned int generation);
+ static int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb,
+ 				        struct ocfs2_lock_res *lockres);
+ static int ocfs2_cancel_convert(struct ocfs2_super *osb,
+@@ -406,9 +376,9 @@ static void ocfs2_lock_res_init_common(struct ocfs2_super *osb,
+ 	res->l_ops           = ops;
+ 	res->l_priv          = priv;
+ 
+-	res->l_level         = LKM_IVMODE;
+-	res->l_requested     = LKM_IVMODE;
+-	res->l_blocking      = LKM_IVMODE;
++	res->l_level         = DLM_LOCK_IV;
++	res->l_requested     = DLM_LOCK_IV;
++	res->l_blocking      = DLM_LOCK_IV;
+ 	res->l_action        = OCFS2_AST_INVALID;
+ 	res->l_unlock_action = OCFS2_UNLOCK_INVALID;
+ 
+@@ -604,10 +574,10 @@ static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres,
+ 	BUG_ON(!lockres);
+ 
+ 	switch(level) {
+-	case LKM_EXMODE:
++	case DLM_LOCK_EX:
+ 		lockres->l_ex_holders++;
+ 		break;
+-	case LKM_PRMODE:
++	case DLM_LOCK_PR:
+ 		lockres->l_ro_holders++;
+ 		break;
+ 	default:
+@@ -625,11 +595,11 @@ static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres,
+ 	BUG_ON(!lockres);
+ 
+ 	switch(level) {
+-	case LKM_EXMODE:
++	case DLM_LOCK_EX:
+ 		BUG_ON(!lockres->l_ex_holders);
+ 		lockres->l_ex_holders--;
+ 		break;
+-	case LKM_PRMODE:
++	case DLM_LOCK_PR:
+ 		BUG_ON(!lockres->l_ro_holders);
+ 		lockres->l_ro_holders--;
+ 		break;
+@@ -644,12 +614,12 @@ static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres,
+  * lock types are added. */
+ static inline int ocfs2_highest_compat_lock_level(int level)
+ {
+-	int new_level = LKM_EXMODE;
++	int new_level = DLM_LOCK_EX;
+ 
+-	if (level == LKM_EXMODE)
+-		new_level = LKM_NLMODE;
+-	else if (level == LKM_PRMODE)
+-		new_level = LKM_PRMODE;
++	if (level == DLM_LOCK_EX)
++		new_level = DLM_LOCK_NL;
++	else if (level == DLM_LOCK_PR)
++		new_level = DLM_LOCK_PR;
+ 	return new_level;
+ }
+ 
+@@ -688,12 +658,12 @@ static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res
+ 	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
+ 	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));
+ 	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
+-	BUG_ON(lockres->l_blocking <= LKM_NLMODE);
++	BUG_ON(lockres->l_blocking <= DLM_LOCK_NL);
+ 
+ 	lockres->l_level = lockres->l_requested;
+ 	if (lockres->l_level <=
+ 	    ocfs2_highest_compat_lock_level(lockres->l_blocking)) {
+-		lockres->l_blocking = LKM_NLMODE;
++		lockres->l_blocking = DLM_LOCK_NL;
+ 		lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED);
+ 	}
+ 	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+@@ -712,7 +682,7 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo
+ 	 * information is already up to data. Convert from NL to
+ 	 * *anything* however should mark ourselves as needing an
+ 	 * update */
+-	if (lockres->l_level == LKM_NLMODE &&
++	if (lockres->l_level == DLM_LOCK_NL &&
+ 	    lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)
+ 		lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
+ 
+@@ -729,7 +699,7 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc
+ 	BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY)));
+ 	BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
+ 
+-	if (lockres->l_requested > LKM_NLMODE &&
++	if (lockres->l_requested > DLM_LOCK_NL &&
+ 	    !(lockres->l_flags & OCFS2_LOCK_LOCAL) &&
+ 	    lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)
+ 		lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
+@@ -767,6 +737,113 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres,
+ 	return needs_downconvert;
+ }
+ 
++/*
++ * OCFS2_LOCK_PENDING and l_pending_gen.
++ *
++ * Why does OCFS2_LOCK_PENDING exist?  To close a race between setting
++ * OCFS2_LOCK_BUSY and calling ocfs2_dlm_lock().  See ocfs2_unblock_lock()
++ * for more details on the race.
++ *
++ * OCFS2_LOCK_PENDING closes the race quite nicely.  However, it introduces
++ * a race on itself.  In o2dlm, we can get the ast before ocfs2_dlm_lock()
++ * returns.  The ast clears OCFS2_LOCK_BUSY, and must therefore clear
++ * OCFS2_LOCK_PENDING at the same time.  When ocfs2_dlm_lock() returns,
++ * the caller is going to try to clear PENDING again.  If nothing else is
++ * happening, __lockres_clear_pending() sees PENDING is unset and does
++ * nothing.
++ *
++ * But what if another path (eg downconvert thread) has just started a
++ * new locking action?  The other path has re-set PENDING.  Our path
++ * cannot clear PENDING, because that will re-open the original race
++ * window.
++ *
++ * [Example]
++ *
++ * ocfs2_meta_lock()
++ *  ocfs2_cluster_lock()
++ *   set BUSY
++ *   set PENDING
++ *   drop l_lock
++ *   ocfs2_dlm_lock()
++ *    ocfs2_locking_ast()		ocfs2_downconvert_thread()
++ *     clear PENDING			 ocfs2_unblock_lock()
++ *					  take_l_lock
++ *					  !BUSY
++ *					  ocfs2_prepare_downconvert()
++ *					   set BUSY
++ *					   set PENDING
++ *					  drop l_lock
++ *   take l_lock
++ *   clear PENDING
++ *   drop l_lock
++ *			<window>
++ *					  ocfs2_dlm_lock()
++ *
++ * So as you can see, we now have a window where l_lock is not held,
++ * PENDING is not set, and ocfs2_dlm_lock() has not been called.
++ *
++ * The core problem is that ocfs2_cluster_lock() has cleared the PENDING
++ * set by ocfs2_prepare_downconvert().  That wasn't nice.
++ *
++ * To solve this we introduce l_pending_gen.  A call to
++ * lockres_clear_pending() will only do so when it is passed a generation
++ * number that matches the lockres.  lockres_set_pending() will return the
++ * current generation number.  When ocfs2_cluster_lock() goes to clear
++ * PENDING, it passes the generation it got from set_pending().  In our
++ * example above, the generation numbers will *not* match.  Thus,
++ * ocfs2_cluster_lock() will not clear the PENDING set by
++ * ocfs2_prepare_downconvert().
++ */
++
++/* Unlocked version for ocfs2_locking_ast() */
++static void __lockres_clear_pending(struct ocfs2_lock_res *lockres,
++				    unsigned int generation,
++				    struct ocfs2_super *osb)
++{
++	assert_spin_locked(&lockres->l_lock);
++
++	/*
++	 * The ast and locking functions can race us here.  The winner
++	 * will clear pending, the loser will not.
++	 */
++	if (!(lockres->l_flags & OCFS2_LOCK_PENDING) ||
++	    (lockres->l_pending_gen != generation))
++		return;
++
++	lockres_clear_flags(lockres, OCFS2_LOCK_PENDING);
++	lockres->l_pending_gen++;
++
++	/*
++	 * The downconvert thread may have skipped us because we
++	 * were PENDING.  Wake it up.
++	 */
++	if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
++		ocfs2_wake_downconvert_thread(osb);
++}
++
++/* Locked version for callers of ocfs2_dlm_lock() */
++static void lockres_clear_pending(struct ocfs2_lock_res *lockres,
++				  unsigned int generation,
++				  struct ocfs2_super *osb)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&lockres->l_lock, flags);
++	__lockres_clear_pending(lockres, generation, osb);
++	spin_unlock_irqrestore(&lockres->l_lock, flags);
++}
++
++static unsigned int lockres_set_pending(struct ocfs2_lock_res *lockres)
++{
++	assert_spin_locked(&lockres->l_lock);
++	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
++
++	lockres_or_flags(lockres, OCFS2_LOCK_PENDING);
++
++	return lockres->l_pending_gen;
++}
++
++
+ static void ocfs2_blocking_ast(void *opaque, int level)
+ {
+ 	struct ocfs2_lock_res *lockres = opaque;
+@@ -774,7 +851,7 @@ static void ocfs2_blocking_ast(void *opaque, int level)
+ 	int needs_downconvert;
+ 	unsigned long flags;
+ 
+-	BUG_ON(level <= LKM_NLMODE);
++	BUG_ON(level <= DLM_LOCK_NL);
+ 
+ 	mlog(0, "BAST fired for lockres %s, blocking %d, level %d type %s\n",
+ 	     lockres->l_name, level, lockres->l_level,
+@@ -801,14 +878,22 @@ static void ocfs2_blocking_ast(void *opaque, int level)
+ static void ocfs2_locking_ast(void *opaque)
+ {
+ 	struct ocfs2_lock_res *lockres = opaque;
+-	struct dlm_lockstatus *lksb = &lockres->l_lksb;
++	struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres);
+ 	unsigned long flags;
++	int status;
+ 
+ 	spin_lock_irqsave(&lockres->l_lock, flags);
+ 
+-	if (lksb->status != DLM_NORMAL) {
+-		mlog(ML_ERROR, "lockres %s: lksb status value of %u!\n",
+-		     lockres->l_name, lksb->status);
++	status = ocfs2_dlm_lock_status(&lockres->l_lksb);
++
++	if (status == -EAGAIN) {
++		lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
++		goto out;
++	}
++
++	if (status) {
++		mlog(ML_ERROR, "lockres %s: lksb status value of %d!\n",
++		     lockres->l_name, status);
+ 		spin_unlock_irqrestore(&lockres->l_lock, flags);
+ 		return;
+ 	}
+@@ -831,11 +916,23 @@ static void ocfs2_locking_ast(void *opaque)
+ 		     lockres->l_unlock_action);
+ 		BUG();
+ 	}
+-
++out:
+ 	/* set it to something invalid so if we get called again we
+ 	 * can catch it. */
+ 	lockres->l_action = OCFS2_AST_INVALID;
+ 
++	/* Did we try to cancel this lock?  Clear that state */
++	if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT)
++		lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
++
++	/*
++	 * We may have beaten the locking functions here.  We certainly
++	 * know that dlm_lock() has been called :-)
++	 * Because we can't have two lock calls in flight at once, we
++	 * can use lockres->l_pending_gen.
++	 */
++	__lockres_clear_pending(lockres, lockres->l_pending_gen,  osb);
++
+ 	wake_up(&lockres->l_event);
+ 	spin_unlock_irqrestore(&lockres->l_lock, flags);
+ }
+@@ -865,15 +962,15 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
+ static int ocfs2_lock_create(struct ocfs2_super *osb,
+ 			     struct ocfs2_lock_res *lockres,
+ 			     int level,
+-			     int dlm_flags)
++			     u32 dlm_flags)
+ {
+ 	int ret = 0;
+-	enum dlm_status status = DLM_NORMAL;
+ 	unsigned long flags;
++	unsigned int gen;
+ 
+ 	mlog_entry_void();
+ 
+-	mlog(0, "lock %s, level = %d, flags = %d\n", lockres->l_name, level,
++	mlog(0, "lock %s, level = %d, flags = %u\n", lockres->l_name, level,
+ 	     dlm_flags);
+ 
+ 	spin_lock_irqsave(&lockres->l_lock, flags);
+@@ -886,24 +983,23 @@ static int ocfs2_lock_create(struct ocfs2_super *osb,
+ 	lockres->l_action = OCFS2_AST_ATTACH;
+ 	lockres->l_requested = level;
+ 	lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
++	gen = lockres_set_pending(lockres);
+ 	spin_unlock_irqrestore(&lockres->l_lock, flags);
+ 
+-	status = dlmlock(osb->dlm,
+-			 level,
+-			 &lockres->l_lksb,
+-			 dlm_flags,
+-			 lockres->l_name,
+-			 OCFS2_LOCK_ID_MAX_LEN - 1,
+-			 ocfs2_locking_ast,
+-			 lockres,
+-			 ocfs2_blocking_ast);
+-	if (status != DLM_NORMAL) {
+-		ocfs2_log_dlm_error("dlmlock", status, lockres);
+-		ret = -EINVAL;
++	ret = ocfs2_dlm_lock(osb->cconn,
++			     level,
++			     &lockres->l_lksb,
++			     dlm_flags,
++			     lockres->l_name,
++			     OCFS2_LOCK_ID_MAX_LEN - 1,
++			     lockres);
++	lockres_clear_pending(lockres, gen, osb);
++	if (ret) {
++		ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
+ 		ocfs2_recover_from_dlm_error(lockres, 1);
+ 	}
+ 
+-	mlog(0, "lock %s, successfull return from dlmlock\n", lockres->l_name);
++	mlog(0, "lock %s, return from ocfs2_dlm_lock\n", lockres->l_name);
+ 
+ bail:
+ 	mlog_exit(ret);
+@@ -1016,21 +1112,22 @@ static int ocfs2_wait_for_mask_interruptible(struct ocfs2_mask_waiter *mw,
+ static int ocfs2_cluster_lock(struct ocfs2_super *osb,
+ 			      struct ocfs2_lock_res *lockres,
+ 			      int level,
+-			      int lkm_flags,
++			      u32 lkm_flags,
+ 			      int arg_flags)
+ {
+ 	struct ocfs2_mask_waiter mw;
+-	enum dlm_status status;
+ 	int wait, catch_signals = !(osb->s_mount_opt & OCFS2_MOUNT_NOINTR);
+ 	int ret = 0; /* gcc doesn't realize wait = 1 guarantees ret is set */
+ 	unsigned long flags;
++	unsigned int gen;
++	int noqueue_attempted = 0;
+ 
+ 	mlog_entry_void();
+ 
+ 	ocfs2_init_mask_waiter(&mw);
+ 
+ 	if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
+-		lkm_flags |= LKM_VALBLK;
++		lkm_flags |= DLM_LKF_VALBLK;
+ 
+ again:
+ 	wait = 0;
+@@ -1068,52 +1165,56 @@ again:
+ 	}
+ 
+ 	if (level > lockres->l_level) {
++		if (noqueue_attempted > 0) {
++			ret = -EAGAIN;
++			goto unlock;
++		}
++		if (lkm_flags & DLM_LKF_NOQUEUE)
++			noqueue_attempted = 1;
++
+ 		if (lockres->l_action != OCFS2_AST_INVALID)
+ 			mlog(ML_ERROR, "lockres %s has action %u pending\n",
+ 			     lockres->l_name, lockres->l_action);
+ 
+ 		if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
+ 			lockres->l_action = OCFS2_AST_ATTACH;
+-			lkm_flags &= ~LKM_CONVERT;
++			lkm_flags &= ~DLM_LKF_CONVERT;
+ 		} else {
+ 			lockres->l_action = OCFS2_AST_CONVERT;
+-			lkm_flags |= LKM_CONVERT;
++			lkm_flags |= DLM_LKF_CONVERT;
+ 		}
+ 
+ 		lockres->l_requested = level;
+ 		lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
++		gen = lockres_set_pending(lockres);
+ 		spin_unlock_irqrestore(&lockres->l_lock, flags);
+ 
+-		BUG_ON(level == LKM_IVMODE);
+-		BUG_ON(level == LKM_NLMODE);
++		BUG_ON(level == DLM_LOCK_IV);
++		BUG_ON(level == DLM_LOCK_NL);
+ 
+ 		mlog(0, "lock %s, convert from %d to level = %d\n",
+ 		     lockres->l_name, lockres->l_level, level);
+ 
+ 		/* call dlm_lock to upgrade lock now */
+-		status = dlmlock(osb->dlm,
+-				 level,
+-				 &lockres->l_lksb,
+-				 lkm_flags,
+-				 lockres->l_name,
+-				 OCFS2_LOCK_ID_MAX_LEN - 1,
+-				 ocfs2_locking_ast,
+-				 lockres,
+-				 ocfs2_blocking_ast);
+-		if (status != DLM_NORMAL) {
+-			if ((lkm_flags & LKM_NOQUEUE) &&
+-			    (status == DLM_NOTQUEUED))
+-				ret = -EAGAIN;
+-			else {
+-				ocfs2_log_dlm_error("dlmlock", status,
+-						    lockres);
+-				ret = -EINVAL;
++		ret = ocfs2_dlm_lock(osb->cconn,
++				     level,
++				     &lockres->l_lksb,
++				     lkm_flags,
++				     lockres->l_name,
++				     OCFS2_LOCK_ID_MAX_LEN - 1,
++				     lockres);
++		lockres_clear_pending(lockres, gen, osb);
++		if (ret) {
++			if (!(lkm_flags & DLM_LKF_NOQUEUE) ||
++			    (ret != -EAGAIN)) {
++				ocfs2_log_dlm_error("ocfs2_dlm_lock",
++						    ret, lockres);
+ 			}
+ 			ocfs2_recover_from_dlm_error(lockres, 1);
+ 			goto out;
+ 		}
+ 
+-		mlog(0, "lock %s, successfull return from dlmlock\n",
++		mlog(0, "lock %s, successfull return from ocfs2_dlm_lock\n",
+ 		     lockres->l_name);
+ 
+ 		/* At this point we've gone inside the dlm and need to
+@@ -1177,9 +1278,9 @@ static int ocfs2_create_new_lock(struct ocfs2_super *osb,
+ 				 int ex,
+ 				 int local)
+ {
+-	int level =  ex ? LKM_EXMODE : LKM_PRMODE;
++	int level =  ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 	unsigned long flags;
+-	int lkm_flags = local ? LKM_LOCAL : 0;
++	u32 lkm_flags = local ? DLM_LKF_LOCAL : 0;
+ 
+ 	spin_lock_irqsave(&lockres->l_lock, flags);
+ 	BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
+@@ -1222,7 +1323,7 @@ int ocfs2_create_new_inode_locks(struct inode *inode)
+ 	}
+ 
+ 	/*
+-	 * We don't want to use LKM_LOCAL on a meta data lock as they
++	 * We don't want to use DLM_LKF_LOCAL on a meta data lock as they
+ 	 * don't use a generation in their lock names.
+ 	 */
+ 	ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_inode_lockres, 1, 0);
+@@ -1261,7 +1362,7 @@ int ocfs2_rw_lock(struct inode *inode, int write)
+ 
+ 	lockres = &OCFS2_I(inode)->ip_rw_lockres;
+ 
+-	level = write ? LKM_EXMODE : LKM_PRMODE;
++	level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 
+ 	status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres, level, 0,
+ 				    0);
+@@ -1274,7 +1375,7 @@ int ocfs2_rw_lock(struct inode *inode, int write)
+ 
+ void ocfs2_rw_unlock(struct inode *inode, int write)
+ {
+-	int level = write ? LKM_EXMODE : LKM_PRMODE;
++	int level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 	struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
+ 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ 
+@@ -1312,7 +1413,7 @@ int ocfs2_open_lock(struct inode *inode)
+ 	lockres = &OCFS2_I(inode)->ip_open_lockres;
+ 
+ 	status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres,
+-				    LKM_PRMODE, 0, 0);
++				    DLM_LOCK_PR, 0, 0);
+ 	if (status < 0)
+ 		mlog_errno(status);
+ 
+@@ -1340,16 +1441,16 @@ int ocfs2_try_open_lock(struct inode *inode, int write)
+ 
+ 	lockres = &OCFS2_I(inode)->ip_open_lockres;
+ 
+-	level = write ? LKM_EXMODE : LKM_PRMODE;
++	level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 
+ 	/*
+ 	 * The file system may already holding a PRMODE/EXMODE open lock.
+-	 * Since we pass LKM_NOQUEUE, the request won't block waiting on
++	 * Since we pass DLM_LKF_NOQUEUE, the request won't block waiting on
+ 	 * other nodes and the -EAGAIN will indicate to the caller that
+ 	 * this inode is still in use.
+ 	 */
+ 	status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres,
+-				    level, LKM_NOQUEUE, 0);
++				    level, DLM_LKF_NOQUEUE, 0);
+ 
+ out:
+ 	mlog_exit(status);
+@@ -1374,10 +1475,10 @@ void ocfs2_open_unlock(struct inode *inode)
+ 
+ 	if(lockres->l_ro_holders)
+ 		ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres,
+-				     LKM_PRMODE);
++				     DLM_LOCK_PR);
+ 	if(lockres->l_ex_holders)
+ 		ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres,
+-				     LKM_EXMODE);
++				     DLM_LOCK_EX);
+ 
+ out:
+ 	mlog_exit_void();
+@@ -1464,7 +1565,7 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock)
+ 	ocfs2_init_mask_waiter(&mw);
+ 
+ 	if ((lockres->l_flags & OCFS2_LOCK_BUSY) ||
+-	    (lockres->l_level > LKM_NLMODE)) {
++	    (lockres->l_level > DLM_LOCK_NL)) {
+ 		mlog(ML_ERROR,
+ 		     "File lock \"%s\" has busy or locked state: flags: 0x%lx, "
+ 		     "level: %u\n", lockres->l_name, lockres->l_flags,
+@@ -1503,14 +1604,12 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock)
+ 	lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
+ 	spin_unlock_irqrestore(&lockres->l_lock, flags);
+ 
+-	ret = dlmlock(osb->dlm, level, &lockres->l_lksb, lkm_flags,
+-		      lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1,
+-		      ocfs2_locking_ast, lockres, ocfs2_blocking_ast);
+-	if (ret != DLM_NORMAL) {
+-		if (trylock && ret == DLM_NOTQUEUED)
+-			ret = -EAGAIN;
+-		else {
+-			ocfs2_log_dlm_error("dlmlock", ret, lockres);
++	ret = ocfs2_dlm_lock(osb->cconn, level, &lockres->l_lksb, lkm_flags,
++			     lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1,
++			     lockres);
++	if (ret) {
++		if (!trylock || (ret != -EAGAIN)) {
++			ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
+ 			ret = -EINVAL;
+ 		}
+ 
+@@ -1537,6 +1636,10 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock)
+ 		 * to just bubble sucess back up to the user.
+ 		 */
+ 		ret = ocfs2_flock_handle_signal(lockres, level);
++	} else if (!ret && (level > lockres->l_level)) {
++		/* Trylock failed asynchronously */
++		BUG_ON(!trylock);
++		ret = -EAGAIN;
+ 	}
+ 
+ out:
+@@ -1549,6 +1652,7 @@ out:
+ void ocfs2_file_unlock(struct file *file)
+ {
+ 	int ret;
++	unsigned int gen;
+ 	unsigned long flags;
+ 	struct ocfs2_file_private *fp = file->private_data;
+ 	struct ocfs2_lock_res *lockres = &fp->fp_flock;
+@@ -1572,13 +1676,13 @@ void ocfs2_file_unlock(struct file *file)
+ 	 * Fake a blocking ast for the downconvert code.
+ 	 */
+ 	lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
+-	lockres->l_blocking = LKM_EXMODE;
++	lockres->l_blocking = DLM_LOCK_EX;
+ 
+-	ocfs2_prepare_downconvert(lockres, LKM_NLMODE);
++	gen = ocfs2_prepare_downconvert(lockres, LKM_NLMODE);
+ 	lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
+ 	spin_unlock_irqrestore(&lockres->l_lock, flags);
+ 
+-	ret = ocfs2_downconvert_lock(osb, lockres, LKM_NLMODE, 0);
++	ret = ocfs2_downconvert_lock(osb, lockres, LKM_NLMODE, 0, gen);
+ 	if (ret) {
+ 		mlog_errno(ret);
+ 		return;
+@@ -1601,11 +1705,11 @@ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
+ 	 * condition. */
+ 	if (lockres->l_flags & OCFS2_LOCK_BLOCKED) {
+ 		switch(lockres->l_blocking) {
+-		case LKM_EXMODE:
++		case DLM_LOCK_EX:
+ 			if (!lockres->l_ex_holders && !lockres->l_ro_holders)
+ 				kick = 1;
+ 			break;
+-		case LKM_PRMODE:
++		case DLM_LOCK_PR:
+ 			if (!lockres->l_ex_holders)
+ 				kick = 1;
+ 			break;
+@@ -1648,7 +1752,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
+ 
+ 	mlog_entry_void();
+ 
+-	lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
++	lvb = (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+ 
+ 	/*
+ 	 * Invalidate the LVB of a deleted inode - this way other
+@@ -1700,7 +1804,7 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
+ 
+ 	mlog_meta_lvb(0, lockres);
+ 
+-	lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
++	lvb = (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+ 
+ 	/* We're safe here without the lockres lock... */
+ 	spin_lock(&oi->ip_lock);
+@@ -1735,7 +1839,8 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
+ static inline int ocfs2_meta_lvb_is_trustable(struct inode *inode,
+ 					      struct ocfs2_lock_res *lockres)
+ {
+-	struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
++	struct ocfs2_meta_lvb *lvb =
++		(struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+ 
+ 	if (lvb->lvb_version == OCFS2_LVB_VERSION
+ 	    && be32_to_cpu(lvb->lvb_igeneration) == inode->i_generation)
+@@ -1923,7 +2028,8 @@ int ocfs2_inode_lock_full(struct inode *inode,
+ 			 int ex,
+ 			 int arg_flags)
+ {
+-	int status, level, dlm_flags, acquired;
++	int status, level, acquired;
++	u32 dlm_flags;
+ 	struct ocfs2_lock_res *lockres = NULL;
+ 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ 	struct buffer_head *local_bh = NULL;
+@@ -1950,14 +2056,13 @@ int ocfs2_inode_lock_full(struct inode *inode,
+ 		goto local;
+ 
+ 	if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
+-		wait_event(osb->recovery_event,
+-			   ocfs2_node_map_is_empty(osb, &osb->recovery_map));
++		ocfs2_wait_for_recovery(osb);
+ 
+ 	lockres = &OCFS2_I(inode)->ip_inode_lockres;
+-	level = ex ? LKM_EXMODE : LKM_PRMODE;
++	level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 	dlm_flags = 0;
+ 	if (arg_flags & OCFS2_META_LOCK_NOQUEUE)
+-		dlm_flags |= LKM_NOQUEUE;
++		dlm_flags |= DLM_LKF_NOQUEUE;
+ 
+ 	status = ocfs2_cluster_lock(osb, lockres, level, dlm_flags, arg_flags);
+ 	if (status < 0) {
+@@ -1974,8 +2079,7 @@ int ocfs2_inode_lock_full(struct inode *inode,
+ 	 * committed to owning this lock so we don't allow signals to
+ 	 * abort the operation. */
+ 	if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
+-		wait_event(osb->recovery_event,
+-			   ocfs2_node_map_is_empty(osb, &osb->recovery_map));
++		ocfs2_wait_for_recovery(osb);
+ 
+ local:
+ 	/*
+@@ -2109,7 +2213,7 @@ int ocfs2_inode_lock_atime(struct inode *inode,
+ void ocfs2_inode_unlock(struct inode *inode,
+ 		       int ex)
+ {
+-	int level = ex ? LKM_EXMODE : LKM_PRMODE;
++	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 	struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_inode_lockres;
+ 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ 
+@@ -2130,10 +2234,8 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
+ 		     int ex)
+ {
+ 	int status = 0;
+-	int level = ex ? LKM_EXMODE : LKM_PRMODE;
++	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 	struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
+-	struct buffer_head *bh;
+-	struct ocfs2_slot_info *si = osb->slot_info;
+ 
+ 	mlog_entry_void();
+ 
+@@ -2159,11 +2261,7 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
+ 		goto bail;
+ 	}
+ 	if (status) {
+-		bh = si->si_bh;
+-		status = ocfs2_read_block(osb, bh->b_blocknr, &bh, 0,
+-					  si->si_inode);
+-		if (status == 0)
+-			ocfs2_update_slot_info(si);
++		status = ocfs2_refresh_slot_info(osb);
+ 
+ 		ocfs2_complete_lock_res_refresh(lockres, status);
+ 
+@@ -2178,7 +2276,7 @@ bail:
+ void ocfs2_super_unlock(struct ocfs2_super *osb,
+ 			int ex)
+ {
+-	int level = ex ? LKM_EXMODE : LKM_PRMODE;
++	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 	struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
+ 
+ 	if (!ocfs2_mount_local(osb))
+@@ -2196,7 +2294,7 @@ int ocfs2_rename_lock(struct ocfs2_super *osb)
+ 	if (ocfs2_mount_local(osb))
+ 		return 0;
+ 
+-	status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0);
++	status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX, 0, 0);
+ 	if (status < 0)
+ 		mlog_errno(status);
+ 
+@@ -2208,13 +2306,13 @@ void ocfs2_rename_unlock(struct ocfs2_super *osb)
+ 	struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
+ 
+ 	if (!ocfs2_mount_local(osb))
+-		ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
++		ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
+ }
+ 
+ int ocfs2_dentry_lock(struct dentry *dentry, int ex)
+ {
+ 	int ret;
+-	int level = ex ? LKM_EXMODE : LKM_PRMODE;
++	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
+ 	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+ 
+@@ -2235,7 +2333,7 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex)
+ 
+ void ocfs2_dentry_unlock(struct dentry *dentry, int ex)
+ {
+-	int level = ex ? LKM_EXMODE : LKM_PRMODE;
++	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ 	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
+ 	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+ 
+@@ -2400,7 +2498,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
+ 		   lockres->l_blocking);
+ 
+ 	/* Dump the raw LVB */
+-	lvb = lockres->l_lksb.lvb;
++	lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
+ 	for(i = 0; i < DLM_LVB_LEN; i++)
+ 		seq_printf(m, "0x%x\t", lvb[i]);
+ 
+@@ -2504,13 +2602,14 @@ static void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb)
+ int ocfs2_dlm_init(struct ocfs2_super *osb)
+ {
+ 	int status = 0;
+-	u32 dlm_key;
+-	struct dlm_ctxt *dlm = NULL;
++	struct ocfs2_cluster_connection *conn = NULL;
+ 
+ 	mlog_entry_void();
+ 
+-	if (ocfs2_mount_local(osb))
++	if (ocfs2_mount_local(osb)) {
++		osb->node_num = 0;
+ 		goto local;
++	}
+ 
+ 	status = ocfs2_dlm_init_debug(osb);
+ 	if (status < 0) {
+@@ -2527,26 +2626,31 @@ int ocfs2_dlm_init(struct ocfs2_super *osb)
+ 		goto bail;
+ 	}
+ 
+-	/* used by the dlm code to make message headers unique, each
+-	 * node in this domain must agree on this. */
+-	dlm_key = crc32_le(0, osb->uuid_str, strlen(osb->uuid_str));
+-
+ 	/* for now, uuid == domain */
+-	dlm = dlm_register_domain(osb->uuid_str, dlm_key,
+-				  &osb->osb_locking_proto);
+-	if (IS_ERR(dlm)) {
+-		status = PTR_ERR(dlm);
++	status = ocfs2_cluster_connect(osb->osb_cluster_stack,
++				       osb->uuid_str,
++				       strlen(osb->uuid_str),
++				       ocfs2_do_node_down, osb,
++				       &conn);
++	if (status) {
+ 		mlog_errno(status);
+ 		goto bail;
+ 	}
+ 
+-	dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
++	status = ocfs2_cluster_this_node(&osb->node_num);
++	if (status < 0) {
++		mlog_errno(status);
++		mlog(ML_ERROR,
++		     "could not find this host's node number\n");
++		ocfs2_cluster_disconnect(conn, 0);
++		goto bail;
++	}
+ 
+ local:
+ 	ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
+ 	ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
+ 
+-	osb->dlm = dlm;
++	osb->cconn = conn;
+ 
+ 	status = 0;
+ bail:
+@@ -2560,14 +2664,19 @@ bail:
+ 	return status;
+ }
+ 
+-void ocfs2_dlm_shutdown(struct ocfs2_super *osb)
++void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
++			int hangup_pending)
+ {
+ 	mlog_entry_void();
+ 
+-	dlm_unregister_eviction_cb(&osb->osb_eviction_cb);
+-
+ 	ocfs2_drop_osb_locks(osb);
+ 
++	/*
++	 * Now that we have dropped all locks and ocfs2_dismount_volume()
++	 * has disabled recovery, the DLM won't be talking to us.  It's
++	 * safe to tear things down before disconnecting the cluster.
++	 */
++
+ 	if (osb->dc_task) {
+ 		kthread_stop(osb->dc_task);
+ 		osb->dc_task = NULL;
+@@ -2576,15 +2685,15 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb)
+ 	ocfs2_lock_res_free(&osb->osb_super_lockres);
+ 	ocfs2_lock_res_free(&osb->osb_rename_lockres);
+ 
+-	dlm_unregister_domain(osb->dlm);
+-	osb->dlm = NULL;
++	ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
++	osb->cconn = NULL;
+ 
+ 	ocfs2_dlm_shutdown_debug(osb);
+ 
+ 	mlog_exit_void();
+ }
+ 
+-static void ocfs2_unlock_ast(void *opaque, enum dlm_status status)
++static void ocfs2_unlock_ast(void *opaque, int error)
+ {
+ 	struct ocfs2_lock_res *lockres = opaque;
+ 	unsigned long flags;
+@@ -2595,24 +2704,9 @@ static void ocfs2_unlock_ast(void *opaque, enum dlm_status status)
+ 	     lockres->l_unlock_action);
+ 
+ 	spin_lock_irqsave(&lockres->l_lock, flags);
+-	/* We tried to cancel a convert request, but it was already
+-	 * granted. All we want to do here is clear our unlock
+-	 * state. The wake_up call done at the bottom is redundant
+-	 * (ocfs2_prepare_cancel_convert doesn't sleep on this) but doesn't
+-	 * hurt anything anyway */
+-	if (status == DLM_CANCELGRANT &&
+-	    lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
+-		mlog(0, "Got cancelgrant for %s\n", lockres->l_name);
+-
+-		/* We don't clear the busy flag in this case as it
+-		 * should have been cleared by the ast which the dlm
+-		 * has called. */
+-		goto complete_unlock;
+-	}
+-
+-	if (status != DLM_NORMAL) {
+-		mlog(ML_ERROR, "Dlm passes status %d for lock %s, "
+-		     "unlock_action %d\n", status, lockres->l_name,
++	if (error) {
++		mlog(ML_ERROR, "Dlm passes error %d for lock %s, "
++		     "unlock_action %d\n", error, lockres->l_name,
+ 		     lockres->l_unlock_action);
+ 		spin_unlock_irqrestore(&lockres->l_lock, flags);
+ 		return;
+@@ -2624,14 +2718,13 @@ static void ocfs2_unlock_ast(void *opaque, enum dlm_status status)
+ 		lockres->l_action = OCFS2_AST_INVALID;
+ 		break;
+ 	case OCFS2_UNLOCK_DROP_LOCK:
+-		lockres->l_level = LKM_IVMODE;
++		lockres->l_level = DLM_LOCK_IV;
+ 		break;
+ 	default:
+ 		BUG();
+ 	}
+ 
+ 	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+-complete_unlock:
+ 	lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
+ 	spin_unlock_irqrestore(&lockres->l_lock, flags);
+ 
+@@ -2643,16 +2736,16 @@ complete_unlock:
+ static int ocfs2_drop_lock(struct ocfs2_super *osb,
+ 			   struct ocfs2_lock_res *lockres)
+ {
+-	enum dlm_status status;
++	int ret;
+ 	unsigned long flags;
+-	int lkm_flags = 0;
++	u32 lkm_flags = 0;
+ 
+ 	/* We didn't get anywhere near actually using this lockres. */
+ 	if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED))
+ 		goto out;
+ 
+ 	if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
+-		lkm_flags |= LKM_VALBLK;
++		lkm_flags |= DLM_LKF_VALBLK;
+ 
+ 	spin_lock_irqsave(&lockres->l_lock, flags);
+ 
+@@ -2678,7 +2771,7 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb,
+ 
+ 	if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) {
+ 		if (lockres->l_flags & OCFS2_LOCK_ATTACHED &&
+-		    lockres->l_level == LKM_EXMODE &&
++		    lockres->l_level == DLM_LOCK_EX &&
+ 		    !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH))
+ 			lockres->l_ops->set_lvb(lockres);
+ 	}
+@@ -2707,15 +2800,15 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb,
+ 
+ 	mlog(0, "lock %s\n", lockres->l_name);
+ 
+-	status = dlmunlock(osb->dlm, &lockres->l_lksb, lkm_flags,
+-			   ocfs2_unlock_ast, lockres);
+-	if (status != DLM_NORMAL) {
+-		ocfs2_log_dlm_error("dlmunlock", status, lockres);
++	ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb, lkm_flags,
++			       lockres);
++	if (ret) {
++		ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres);
+ 		mlog(ML_ERROR, "lockres flags: %lu\n", lockres->l_flags);
+-		dlm_print_one_lock(lockres->l_lksb.lockid);
++		ocfs2_dlm_dump_lksb(&lockres->l_lksb);
+ 		BUG();
+ 	}
+-	mlog(0, "lock %s, successfull return from dlmunlock\n",
++	mlog(0, "lock %s, successfull return from ocfs2_dlm_unlock\n",
+ 	     lockres->l_name);
+ 
+ 	ocfs2_wait_on_busy_lock(lockres);
+@@ -2806,15 +2899,15 @@ int ocfs2_drop_inode_locks(struct inode *inode)
+ 	return status;
+ }
+ 
+-static void ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
+-				      int new_level)
++static unsigned int ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
++					      int new_level)
+ {
+ 	assert_spin_locked(&lockres->l_lock);
+ 
+-	BUG_ON(lockres->l_blocking <= LKM_NLMODE);
++	BUG_ON(lockres->l_blocking <= DLM_LOCK_NL);
+ 
+ 	if (lockres->l_level <= new_level) {
+-		mlog(ML_ERROR, "lockres->l_level (%u) <= new_level (%u)\n",
++		mlog(ML_ERROR, "lockres->l_level (%d) <= new_level (%d)\n",
+ 		     lockres->l_level, new_level);
+ 		BUG();
+ 	}
+@@ -2825,33 +2918,33 @@ static void ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
+ 	lockres->l_action = OCFS2_AST_DOWNCONVERT;
+ 	lockres->l_requested = new_level;
+ 	lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
++	return lockres_set_pending(lockres);
+ }
+ 
+ static int ocfs2_downconvert_lock(struct ocfs2_super *osb,
+ 				  struct ocfs2_lock_res *lockres,
+ 				  int new_level,
+-				  int lvb)
++				  int lvb,
++				  unsigned int generation)
+ {
+-	int ret, dlm_flags = LKM_CONVERT;
+-	enum dlm_status status;
++	int ret;
++	u32 dlm_flags = DLM_LKF_CONVERT;
+ 
+ 	mlog_entry_void();
+ 
+ 	if (lvb)
+-		dlm_flags |= LKM_VALBLK;
+-
+-	status = dlmlock(osb->dlm,
+-			 new_level,
+-			 &lockres->l_lksb,
+-			 dlm_flags,
+-			 lockres->l_name,
+-			 OCFS2_LOCK_ID_MAX_LEN - 1,
+-			 ocfs2_locking_ast,
+-			 lockres,
+-			 ocfs2_blocking_ast);
+-	if (status != DLM_NORMAL) {
+-		ocfs2_log_dlm_error("dlmlock", status, lockres);
+-		ret = -EINVAL;
++		dlm_flags |= DLM_LKF_VALBLK;
++
++	ret = ocfs2_dlm_lock(osb->cconn,
++			     new_level,
++			     &lockres->l_lksb,
++			     dlm_flags,
++			     lockres->l_name,
++			     OCFS2_LOCK_ID_MAX_LEN - 1,
++			     lockres);
++	lockres_clear_pending(lockres, generation, osb);
++	if (ret) {
++		ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
+ 		ocfs2_recover_from_dlm_error(lockres, 1);
+ 		goto bail;
+ 	}
+@@ -2862,7 +2955,7 @@ bail:
+ 	return ret;
+ }
+ 
+-/* returns 1 when the caller should unlock and call dlmunlock */
++/* returns 1 when the caller should unlock and call ocfs2_dlm_unlock */
+ static int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb,
+ 				        struct ocfs2_lock_res *lockres)
+ {
+@@ -2898,24 +2991,18 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb,
+ 				struct ocfs2_lock_res *lockres)
+ {
+ 	int ret;
+-	enum dlm_status status;
+ 
+ 	mlog_entry_void();
+ 	mlog(0, "lock %s\n", lockres->l_name);
+ 
+-	ret = 0;
+-	status = dlmunlock(osb->dlm,
+-			   &lockres->l_lksb,
+-			   LKM_CANCEL,
+-			   ocfs2_unlock_ast,
+-			   lockres);
+-	if (status != DLM_NORMAL) {
+-		ocfs2_log_dlm_error("dlmunlock", status, lockres);
+-		ret = -EINVAL;
++	ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb,
++			       DLM_LKF_CANCEL, lockres);
++	if (ret) {
++		ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres);
+ 		ocfs2_recover_from_dlm_error(lockres, 0);
+ 	}
+ 
+-	mlog(0, "lock %s return from dlmunlock\n", lockres->l_name);
++	mlog(0, "lock %s return from ocfs2_dlm_unlock\n", lockres->l_name);
+ 
+ 	mlog_exit(ret);
+ 	return ret;
+@@ -2930,6 +3017,7 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
+ 	int new_level;
+ 	int ret = 0;
+ 	int set_lvb = 0;
++	unsigned int gen;
+ 
+ 	mlog_entry_void();
+ 
+@@ -2939,6 +3027,32 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
+ 
+ recheck:
+ 	if (lockres->l_flags & OCFS2_LOCK_BUSY) {
++		/* XXX
++		 * This is a *big* race.  The OCFS2_LOCK_PENDING flag
++		 * exists entirely for one reason - another thread has set
++		 * OCFS2_LOCK_BUSY, but has *NOT* yet called dlm_lock().
++		 *
++		 * If we do ocfs2_cancel_convert() before the other thread
++		 * calls dlm_lock(), our cancel will do nothing.  We will
++		 * get no ast, and we will have no way of knowing the
++		 * cancel failed.  Meanwhile, the other thread will call
++		 * into dlm_lock() and wait...forever.
++		 *
++		 * Why forever?  Because another node has asked for the
++		 * lock first; that's why we're here in unblock_lock().
++		 *
++		 * The solution is OCFS2_LOCK_PENDING.  When PENDING is
++		 * set, we just requeue the unblock.  Only when the other
++		 * thread has called dlm_lock() and cleared PENDING will
++		 * we then cancel their request.
++		 *
++		 * All callers of dlm_lock() must set OCFS2_DLM_PENDING
++		 * at the same time they set OCFS2_DLM_BUSY.  They must
++		 * clear OCFS2_DLM_PENDING after dlm_lock() returns.
++		 */
++		if (lockres->l_flags & OCFS2_LOCK_PENDING)
++			goto leave_requeue;
++
+ 		ctl->requeue = 1;
+ 		ret = ocfs2_prepare_cancel_convert(osb, lockres);
+ 		spin_unlock_irqrestore(&lockres->l_lock, flags);
+@@ -2952,13 +3066,13 @@ recheck:
+ 
+ 	/* if we're blocking an exclusive and we have *any* holders,
+ 	 * then requeue. */
+-	if ((lockres->l_blocking == LKM_EXMODE)
++	if ((lockres->l_blocking == DLM_LOCK_EX)
+ 	    && (lockres->l_ex_holders || lockres->l_ro_holders))
+ 		goto leave_requeue;
+ 
+ 	/* If it's a PR we're blocking, then only
+ 	 * requeue if we've got any EX holders */
+-	if (lockres->l_blocking == LKM_PRMODE &&
++	if (lockres->l_blocking == DLM_LOCK_PR &&
+ 	    lockres->l_ex_holders)
+ 		goto leave_requeue;
+ 
+@@ -3005,7 +3119,7 @@ downconvert:
+ 	ctl->requeue = 0;
+ 
+ 	if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) {
+-		if (lockres->l_level == LKM_EXMODE)
++		if (lockres->l_level == DLM_LOCK_EX)
+ 			set_lvb = 1;
+ 
+ 		/*
+@@ -3018,9 +3132,11 @@ downconvert:
+ 			lockres->l_ops->set_lvb(lockres);
+ 	}
+ 
+-	ocfs2_prepare_downconvert(lockres, new_level);
++	gen = ocfs2_prepare_downconvert(lockres, new_level);
+ 	spin_unlock_irqrestore(&lockres->l_lock, flags);
+-	ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb);
++	ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb,
++				     gen);
++
+ leave:
+ 	mlog_exit(ret);
+ 	return ret;
+@@ -3059,7 +3175,7 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
+ 		     (unsigned long long)OCFS2_I(inode)->ip_blkno);
+ 	}
+ 	sync_mapping_buffers(mapping);
+-	if (blocking == LKM_EXMODE) {
++	if (blocking == DLM_LOCK_EX) {
+ 		truncate_inode_pages(mapping, 0);
+ 	} else {
+ 		/* We only need to wait on the I/O if we're not also
+@@ -3080,8 +3196,8 @@ static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
+ 	struct inode *inode = ocfs2_lock_res_inode(lockres);
+ 	int checkpointed = ocfs2_inode_fully_checkpointed(inode);
+ 
+-	BUG_ON(new_level != LKM_NLMODE && new_level != LKM_PRMODE);
+-	BUG_ON(lockres->l_level != LKM_EXMODE && !checkpointed);
++	BUG_ON(new_level != DLM_LOCK_NL && new_level != DLM_LOCK_PR);
++	BUG_ON(lockres->l_level != DLM_LOCK_EX && !checkpointed);
+ 
+ 	if (checkpointed)
+ 		return 1;
+@@ -3145,7 +3261,7 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
+ 	 * valid. The downconvert code will retain a PR for this node,
+ 	 * so there's no further work to do.
+ 	 */
+-	if (blocking == LKM_PRMODE)
++	if (blocking == DLM_LOCK_PR)
+ 		return UNBLOCK_CONTINUE;
+ 
+ 	/*
+@@ -3219,6 +3335,45 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
+ 	return UNBLOCK_CONTINUE_POST;
+ }
+ 
++/*
++ * This is the filesystem locking protocol.  It provides the lock handling
++ * hooks for the underlying DLM.  It has a maximum version number.
++ * The version number allows interoperability with systems running at
++ * the same major number and an equal or smaller minor number.
++ *
++ * Whenever the filesystem does new things with locks (adds or removes a
++ * lock, orders them differently, does different things underneath a lock),
++ * the version must be changed.  The protocol is negotiated when joining
++ * the dlm domain.  A node may join the domain if its major version is
++ * identical to all other nodes and its minor version is greater than
++ * or equal to all other nodes.  When its minor version is greater than
++ * the other nodes, it will run at the minor version specified by the
++ * other nodes.
++ *
++ * If a locking change is made that will not be compatible with older
++ * versions, the major number must be increased and the minor version set
++ * to zero.  If a change merely adds a behavior that can be disabled when
++ * speaking to older versions, the minor version must be increased.  If a
++ * change adds a fully backwards compatible change (eg, LVB changes that
++ * are just ignored by older versions), the version does not need to be
++ * updated.
++ */
++static struct ocfs2_locking_protocol lproto = {
++	.lp_max_version = {
++		.pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR,
++		.pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
++	},
++	.lp_lock_ast		= ocfs2_locking_ast,
++	.lp_blocking_ast	= ocfs2_blocking_ast,
++	.lp_unlock_ast		= ocfs2_unlock_ast,
++};
++
++void ocfs2_set_locking_protocol(void)
++{
++	ocfs2_stack_glue_set_locking_protocol(&lproto);
++}
++
++
+ static void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
+ 				       struct ocfs2_lock_res *lockres)
+ {
+diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
+index e3cf902..2bb01f0 100644
+--- a/fs/ocfs2/dlmglue.h
++++ b/fs/ocfs2/dlmglue.h
+@@ -58,7 +58,7 @@ struct ocfs2_meta_lvb {
+ #define OCFS2_LOCK_NONBLOCK		(0x04)
+ 
+ int ocfs2_dlm_init(struct ocfs2_super *osb);
+-void ocfs2_dlm_shutdown(struct ocfs2_super *osb);
++void ocfs2_dlm_shutdown(struct ocfs2_super *osb, int hangup_pending);
+ void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res);
+ void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
+ 			       enum ocfs2_lock_type type,
+@@ -114,5 +114,6 @@ void ocfs2_wake_downconvert_thread(struct ocfs2_super *osb);
+ struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void);
+ void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug);
+ 
+-extern const struct dlm_protocol_version ocfs2_locking_protocol;
++/* To set the locking protocol on module initialization */
++void ocfs2_set_locking_protocol(void);
+ #endif	/* DLMGLUE_H */
+diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
+index ed5d523..9154c82 100644
+--- a/fs/ocfs2/file.c
++++ b/fs/ocfs2/file.c
+@@ -2242,7 +2242,7 @@ const struct file_operations ocfs2_fops = {
+ 	.open		= ocfs2_file_open,
+ 	.aio_read	= ocfs2_file_aio_read,
+ 	.aio_write	= ocfs2_file_aio_write,
+-	.ioctl		= ocfs2_ioctl,
++	.unlocked_ioctl	= ocfs2_ioctl,
+ #ifdef CONFIG_COMPAT
+ 	.compat_ioctl   = ocfs2_compat_ioctl,
+ #endif
+@@ -2258,7 +2258,7 @@ const struct file_operations ocfs2_dops = {
+ 	.fsync		= ocfs2_sync_file,
+ 	.release	= ocfs2_dir_release,
+ 	.open		= ocfs2_dir_open,
+-	.ioctl		= ocfs2_ioctl,
++	.unlocked_ioctl	= ocfs2_ioctl,
+ #ifdef CONFIG_COMPAT
+ 	.compat_ioctl   = ocfs2_compat_ioctl,
+ #endif
+diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c
+index 0758daf..c6e7213 100644
+--- a/fs/ocfs2/heartbeat.c
++++ b/fs/ocfs2/heartbeat.c
+@@ -28,9 +28,6 @@
+ #include <linux/types.h>
+ #include <linux/slab.h>
+ #include <linux/highmem.h>
+-#include <linux/kmod.h>
+-
+-#include <dlm/dlmapi.h>
+ 
+ #define MLOG_MASK_PREFIX ML_SUPER
+ #include <cluster/masklog.h>
+@@ -48,7 +45,6 @@ static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map,
+ 					    int bit);
+ static inline void __ocfs2_node_map_clear_bit(struct ocfs2_node_map *map,
+ 					      int bit);
+-static inline int __ocfs2_node_map_is_empty(struct ocfs2_node_map *map);
+ 
+ /* special case -1 for now
+  * TODO: should *really* make sure the calling func never passes -1!!  */
+@@ -62,23 +58,23 @@ static void ocfs2_node_map_init(struct ocfs2_node_map *map)
+ void ocfs2_init_node_maps(struct ocfs2_super *osb)
+ {
+ 	spin_lock_init(&osb->node_map_lock);
+-	ocfs2_node_map_init(&osb->recovery_map);
+ 	ocfs2_node_map_init(&osb->osb_recovering_orphan_dirs);
+ }
+ 
+-static void ocfs2_do_node_down(int node_num,
+-			       struct ocfs2_super *osb)
++void ocfs2_do_node_down(int node_num, void *data)
+ {
++	struct ocfs2_super *osb = data;
++
+ 	BUG_ON(osb->node_num == node_num);
+ 
+ 	mlog(0, "ocfs2: node down event for %d\n", node_num);
+ 
+-	if (!osb->dlm) {
++	if (!osb->cconn) {
+ 		/*
+-		 * No DLM means we're not even ready to participate yet.
+-		 * We check the slots after the DLM comes up, so we will
+-		 * notice the node death then.  We can safely ignore it
+-		 * here.
++		 * No cluster connection means we're not even ready to
++		 * participate yet.  We check the slots after the cluster
++		 * comes up, so we will notice the node death then.  We
++		 * can safely ignore it here.
+ 		 */
+ 		return;
+ 	}
+@@ -86,61 +82,6 @@ static void ocfs2_do_node_down(int node_num,
+ 	ocfs2_recovery_thread(osb, node_num);
+ }
+ 
+-/* Called from the dlm when it's about to evict a node. We may also
+- * get a heartbeat callback later. */
+-static void ocfs2_dlm_eviction_cb(int node_num,
+-				  void *data)
+-{
+-	struct ocfs2_super *osb = (struct ocfs2_super *) data;
+-	struct super_block *sb = osb->sb;
+-
+-	mlog(ML_NOTICE, "device (%u,%u): dlm has evicted node %d\n",
+-	     MAJOR(sb->s_dev), MINOR(sb->s_dev), node_num);
+-
+-	ocfs2_do_node_down(node_num, osb);
+-}
+-
+-void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb)
+-{
+-	/* Not exactly a heartbeat callback, but leads to essentially
+-	 * the same path so we set it up here. */
+-	dlm_setup_eviction_cb(&osb->osb_eviction_cb,
+-			      ocfs2_dlm_eviction_cb,
+-			      osb);
+-}
+-
+-void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
+-{
+-	int ret;
+-	char *argv[5], *envp[3];
+-
+-	if (ocfs2_mount_local(osb))
+-		return;
+-
+-	if (!osb->uuid_str) {
+-		/* This can happen if we don't get far enough in mount... */
+-		mlog(0, "No UUID with which to stop heartbeat!\n\n");
+-		return;
+-	}
+-
+-	argv[0] = (char *)o2nm_get_hb_ctl_path();
+-	argv[1] = "-K";
+-	argv[2] = "-u";
+-	argv[3] = osb->uuid_str;
+-	argv[4] = NULL;
+-
+-	mlog(0, "Run: %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
+-
+-	/* minimal command environment taken from cpu_run_sbin_hotplug */
+-	envp[0] = "HOME=/";
+-	envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+-	envp[2] = NULL;
+-
+-	ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
+-	if (ret < 0)
+-		mlog_errno(ret);
+-}
+-
+ static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map,
+ 					    int bit)
+ {
+@@ -192,112 +133,3 @@ int ocfs2_node_map_test_bit(struct ocfs2_super *osb,
+ 	return ret;
+ }
+ 
+-static inline int __ocfs2_node_map_is_empty(struct ocfs2_node_map *map)
+-{
+-	int bit;
+-	bit = find_next_bit(map->map, map->num_nodes, 0);
+-	if (bit < map->num_nodes)
+-		return 0;
+-	return 1;
+-}
+-
+-int ocfs2_node_map_is_empty(struct ocfs2_super *osb,
+-			    struct ocfs2_node_map *map)
+-{
+-	int ret;
+-	BUG_ON(map->num_nodes == 0);
+-	spin_lock(&osb->node_map_lock);
+-	ret = __ocfs2_node_map_is_empty(map);
+-	spin_unlock(&osb->node_map_lock);
+-	return ret;
+-}
+-
+-#if 0
+-
+-static void __ocfs2_node_map_dup(struct ocfs2_node_map *target,
+-				 struct ocfs2_node_map *from)
+-{
+-	BUG_ON(from->num_nodes == 0);
+-	ocfs2_node_map_init(target);
+-	__ocfs2_node_map_set(target, from);
+-}
+-
+-/* returns 1 if bit is the only bit set in target, 0 otherwise */
+-int ocfs2_node_map_is_only(struct ocfs2_super *osb,
+-			   struct ocfs2_node_map *target,
+-			   int bit)
+-{
+-	struct ocfs2_node_map temp;
+-	int ret;
+-
+-	spin_lock(&osb->node_map_lock);
+-	__ocfs2_node_map_dup(&temp, target);
+-	__ocfs2_node_map_clear_bit(&temp, bit);
+-	ret = __ocfs2_node_map_is_empty(&temp);
+-	spin_unlock(&osb->node_map_lock);
+-
+-	return ret;
+-}
+-
+-static void __ocfs2_node_map_set(struct ocfs2_node_map *target,
+-				 struct ocfs2_node_map *from)
+-{
+-	int num_longs, i;
+-
+-	BUG_ON(target->num_nodes != from->num_nodes);
+-	BUG_ON(target->num_nodes == 0);
+-
+-	num_longs = BITS_TO_LONGS(target->num_nodes);
+-	for (i = 0; i < num_longs; i++)
+-		target->map[i] = from->map[i];
+-}
+-
+-#endif  /*  0  */
+-
+-/* Returns whether the recovery bit was actually set - it may not be
+- * if a node is still marked as needing recovery */
+-int ocfs2_recovery_map_set(struct ocfs2_super *osb,
+-			   int num)
+-{
+-	int set = 0;
+-
+-	spin_lock(&osb->node_map_lock);
+-
+-	if (!test_bit(num, osb->recovery_map.map)) {
+-	    __ocfs2_node_map_set_bit(&osb->recovery_map, num);
+-	    set = 1;
+-	}
+-
+-	spin_unlock(&osb->node_map_lock);
+-
+-	return set;
+-}
+-
+-void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
+-			      int num)
+-{
+-	ocfs2_node_map_clear_bit(osb, &osb->recovery_map, num);
+-}
+-
+-int ocfs2_node_map_iterate(struct ocfs2_super *osb,
+-			   struct ocfs2_node_map *map,
+-			   int idx)
+-{
+-	int i = idx;
+-
+-	idx = O2NM_INVALID_NODE_NUM;
+-	spin_lock(&osb->node_map_lock);
+-	if ((i != O2NM_INVALID_NODE_NUM) &&
+-	    (i >= 0) &&
+-	    (i < map->num_nodes)) {
+-		while(i < map->num_nodes) {
+-			if (test_bit(i, map->map)) {
+-				idx = i;
+-				break;
+-			}
+-			i++;
+-		}
+-	}
+-	spin_unlock(&osb->node_map_lock);
+-	return idx;
+-}
+diff --git a/fs/ocfs2/heartbeat.h b/fs/ocfs2/heartbeat.h
+index eac63ae..74b9c5d 100644
+--- a/fs/ocfs2/heartbeat.h
++++ b/fs/ocfs2/heartbeat.h
+@@ -28,13 +28,10 @@
+ 
+ void ocfs2_init_node_maps(struct ocfs2_super *osb);
+ 
+-void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb);
+-void ocfs2_stop_heartbeat(struct ocfs2_super *osb);
++void ocfs2_do_node_down(int node_num, void *data);
+ 
+ /* node map functions - used to keep track of mounted and in-recovery
+  * nodes. */
+-int ocfs2_node_map_is_empty(struct ocfs2_super *osb,
+-			    struct ocfs2_node_map *map);
+ void ocfs2_node_map_set_bit(struct ocfs2_super *osb,
+ 			    struct ocfs2_node_map *map,
+ 			    int bit);
+@@ -44,17 +41,5 @@ void ocfs2_node_map_clear_bit(struct ocfs2_super *osb,
+ int ocfs2_node_map_test_bit(struct ocfs2_super *osb,
+ 			    struct ocfs2_node_map *map,
+ 			    int bit);
+-int ocfs2_node_map_iterate(struct ocfs2_super *osb,
+-			   struct ocfs2_node_map *map,
+-			   int idx);
+-static inline int ocfs2_node_map_first_set_bit(struct ocfs2_super *osb,
+-					       struct ocfs2_node_map *map)
+-{
+-	return ocfs2_node_map_iterate(osb, map, 0);
+-}
+-int ocfs2_recovery_map_set(struct ocfs2_super *osb,
+-			   int num);
+-void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
+-			      int num);
+ 
+ #endif /* OCFS2_HEARTBEAT_H */
+diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
+index 5177fba..7b142f0 100644
+--- a/fs/ocfs2/ioctl.c
++++ b/fs/ocfs2/ioctl.c
+@@ -7,6 +7,7 @@
+ 
+ #include <linux/fs.h>
+ #include <linux/mount.h>
++#include <linux/smp_lock.h>
+ 
+ #define MLOG_MASK_PREFIX ML_INODE
+ #include <cluster/masklog.h>
+@@ -59,10 +60,6 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
+ 		goto bail;
+ 	}
+ 
+-	status = -EROFS;
+-	if (IS_RDONLY(inode))
+-		goto bail_unlock;
+-
+ 	status = -EACCES;
+ 	if (!is_owner_or_cap(inode))
+ 		goto bail_unlock;
+@@ -112,9 +109,9 @@ bail:
+ 	return status;
+ }
+ 
+-int ocfs2_ioctl(struct inode * inode, struct file * filp,
+-	unsigned int cmd, unsigned long arg)
++long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
++	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	unsigned int flags;
+ 	int new_clusters;
+ 	int status;
+@@ -133,8 +130,13 @@ int ocfs2_ioctl(struct inode * inode, struct file * filp,
+ 		if (get_user(flags, (int __user *) arg))
+ 			return -EFAULT;
+ 
+-		return ocfs2_set_inode_attr(inode, flags,
++		status = mnt_want_write(filp->f_path.mnt);
++		if (status)
++			return status;
++		status = ocfs2_set_inode_attr(inode, flags,
+ 			OCFS2_FL_MODIFIABLE);
++		mnt_drop_write(filp->f_path.mnt);
++		return status;
+ 	case OCFS2_IOC_RESVSP:
+ 	case OCFS2_IOC_RESVSP64:
+ 	case OCFS2_IOC_UNRESVSP:
+@@ -168,9 +170,6 @@ int ocfs2_ioctl(struct inode * inode, struct file * filp,
+ #ifdef CONFIG_COMPAT
+ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+ {
+-	struct inode *inode = file->f_path.dentry->d_inode;
+-	int ret;
+-
+ 	switch (cmd) {
+ 	case OCFS2_IOC32_GETFLAGS:
+ 		cmd = OCFS2_IOC_GETFLAGS;
+@@ -190,9 +189,6 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+ 		return -ENOIOCTLCMD;
+ 	}
+ 
+-	lock_kernel();
+-	ret = ocfs2_ioctl(inode, file, cmd, arg);
+-	unlock_kernel();
+-	return ret;
++	return ocfs2_ioctl(file, cmd, arg);
+ }
+ #endif
+diff --git a/fs/ocfs2/ioctl.h b/fs/ocfs2/ioctl.h
+index 4d6c4f4..cf9a5ee 100644
+--- a/fs/ocfs2/ioctl.h
++++ b/fs/ocfs2/ioctl.h
+@@ -10,8 +10,7 @@
+ #ifndef OCFS2_IOCTL_H
+ #define OCFS2_IOCTL_H
+ 
+-int ocfs2_ioctl(struct inode * inode, struct file * filp,
+-	unsigned int cmd, unsigned long arg);
++long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg);
+ 
+ #endif /* OCFS2_IOCTL_H */
+diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
+index f31c7e8..9698338 100644
+--- a/fs/ocfs2/journal.c
++++ b/fs/ocfs2/journal.c
+@@ -64,6 +64,137 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
+ 				 int slot);
+ static int ocfs2_commit_thread(void *arg);
+ 
++
++/*
++ * The recovery_list is a simple linked list of node numbers to recover.
++ * It is protected by the recovery_lock.
++ */
++
++struct ocfs2_recovery_map {
++	unsigned int rm_used;
++	unsigned int *rm_entries;
++};
++
++int ocfs2_recovery_init(struct ocfs2_super *osb)
++{
++	struct ocfs2_recovery_map *rm;
++
++	mutex_init(&osb->recovery_lock);
++	osb->disable_recovery = 0;
++	osb->recovery_thread_task = NULL;
++	init_waitqueue_head(&osb->recovery_event);
++
++	rm = kzalloc(sizeof(struct ocfs2_recovery_map) +
++		     osb->max_slots * sizeof(unsigned int),
++		     GFP_KERNEL);
++	if (!rm) {
++		mlog_errno(-ENOMEM);
++		return -ENOMEM;
++	}
++
++	rm->rm_entries = (unsigned int *)((char *)rm +
++					  sizeof(struct ocfs2_recovery_map));
++	osb->recovery_map = rm;
++
++	return 0;
++}
++
++/* we can't grab the goofy sem lock from inside wait_event, so we use
++ * memory barriers to make sure that we'll see the null task before
++ * being woken up */
++static int ocfs2_recovery_thread_running(struct ocfs2_super *osb)
++{
++	mb();
++	return osb->recovery_thread_task != NULL;
++}
++
++void ocfs2_recovery_exit(struct ocfs2_super *osb)
++{
++	struct ocfs2_recovery_map *rm;
++
++	/* disable any new recovery threads and wait for any currently
++	 * running ones to exit. Do this before setting the vol_state. */
++	mutex_lock(&osb->recovery_lock);
++	osb->disable_recovery = 1;
++	mutex_unlock(&osb->recovery_lock);
++	wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb));
++
++	/* At this point, we know that no more recovery threads can be
++	 * launched, so wait for any recovery completion work to
++	 * complete. */
++	flush_workqueue(ocfs2_wq);
++
++	/*
++	 * Now that recovery is shut down, and the osb is about to be
++	 * freed,  the osb_lock is not taken here.
++	 */
++	rm = osb->recovery_map;
++	/* XXX: Should we bug if there are dirty entries? */
++
++	kfree(rm);
++}
++
++static int __ocfs2_recovery_map_test(struct ocfs2_super *osb,
++				     unsigned int node_num)
++{
++	int i;
++	struct ocfs2_recovery_map *rm = osb->recovery_map;
++
++	assert_spin_locked(&osb->osb_lock);
++
++	for (i = 0; i < rm->rm_used; i++) {
++		if (rm->rm_entries[i] == node_num)
++			return 1;
++	}
++
++	return 0;
++}
++
++/* Behaves like test-and-set.  Returns the previous value */
++static int ocfs2_recovery_map_set(struct ocfs2_super *osb,
++				  unsigned int node_num)
++{
++	struct ocfs2_recovery_map *rm = osb->recovery_map;
++
++	spin_lock(&osb->osb_lock);
++	if (__ocfs2_recovery_map_test(osb, node_num)) {
++		spin_unlock(&osb->osb_lock);
++		return 1;
++	}
++
++	/* XXX: Can this be exploited? Not from o2dlm... */
++	BUG_ON(rm->rm_used >= osb->max_slots);
++
++	rm->rm_entries[rm->rm_used] = node_num;
++	rm->rm_used++;
++	spin_unlock(&osb->osb_lock);
++
++	return 0;
++}
++
++static void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
++				     unsigned int node_num)
++{
++	int i;
++	struct ocfs2_recovery_map *rm = osb->recovery_map;
++
++	spin_lock(&osb->osb_lock);
++
++	for (i = 0; i < rm->rm_used; i++) {
++		if (rm->rm_entries[i] == node_num)
++			break;
++	}
++
++	if (i < rm->rm_used) {
++		/* XXX: be careful with the pointer math */
++		memmove(&(rm->rm_entries[i]), &(rm->rm_entries[i + 1]),
++			(rm->rm_used - i - 1) * sizeof(unsigned int));
++		rm->rm_used--;
++	}
++
++	spin_unlock(&osb->osb_lock);
++}
++
+ static int ocfs2_commit_cache(struct ocfs2_super *osb)
+ {
+ 	int status = 0;
+@@ -586,8 +717,7 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local)
+ 
+ 	mlog_entry_void();
+ 
+-	if (!journal)
+-		BUG();
++	BUG_ON(!journal);
+ 
+ 	osb = journal->j_osb;
+ 
+@@ -650,6 +780,23 @@ bail:
+ 	return status;
+ }
+ 
++static int ocfs2_recovery_completed(struct ocfs2_super *osb)
++{
++	int empty;
++	struct ocfs2_recovery_map *rm = osb->recovery_map;
++
++	spin_lock(&osb->osb_lock);
++	empty = (rm->rm_used == 0);
++	spin_unlock(&osb->osb_lock);
++
++	return empty;
++}
++
++void ocfs2_wait_for_recovery(struct ocfs2_super *osb)
++{
++	wait_event(osb->recovery_event, ocfs2_recovery_completed(osb));
++}
++
+ /*
+  * JBD Might read a cached version of another nodes journal file. We
+  * don't want this as this file changes often and we get no
+@@ -848,6 +995,7 @@ static int __ocfs2_recovery_thread(void *arg)
+ {
+ 	int status, node_num;
+ 	struct ocfs2_super *osb = arg;
++	struct ocfs2_recovery_map *rm = osb->recovery_map;
+ 
+ 	mlog_entry_void();
+ 
+@@ -863,26 +1011,29 @@ restart:
+ 		goto bail;
+ 	}
+ 
+-	while(!ocfs2_node_map_is_empty(osb, &osb->recovery_map)) {
+-		node_num = ocfs2_node_map_first_set_bit(osb,
+-							&osb->recovery_map);
+-		if (node_num == O2NM_INVALID_NODE_NUM) {
+-			mlog(0, "Out of nodes to recover.\n");
+-			break;
+-		}
++	spin_lock(&osb->osb_lock);
++	while (rm->rm_used) {
++		/* It's always safe to remove entry zero, as we won't
++		 * clear it until ocfs2_recover_node() has succeeded. */
++		node_num = rm->rm_entries[0];
++		spin_unlock(&osb->osb_lock);
+ 
+ 		status = ocfs2_recover_node(osb, node_num);
+-		if (status < 0) {
++		if (!status) {
++			ocfs2_recovery_map_clear(osb, node_num);
++		} else {
+ 			mlog(ML_ERROR,
+ 			     "Error %d recovering node %d on device (%u,%u)!\n",
+ 			     status, node_num,
+ 			     MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+ 			mlog(ML_ERROR, "Volume requires unmount.\n");
+-			continue;
+ 		}
+ 
+-		ocfs2_recovery_map_clear(osb, node_num);
++		spin_lock(&osb->osb_lock);
+ 	}
++	spin_unlock(&osb->osb_lock);
++	mlog(0, "All nodes recovered\n");
++
+ 	ocfs2_super_unlock(osb, 1);
+ 
+ 	/* We always run recovery on our own orphan dir - the dead
+@@ -893,8 +1044,7 @@ restart:
+ 
+ bail:
+ 	mutex_lock(&osb->recovery_lock);
+-	if (!status &&
+-	    !ocfs2_node_map_is_empty(osb, &osb->recovery_map)) {
++	if (!status && !ocfs2_recovery_completed(osb)) {
+ 		mutex_unlock(&osb->recovery_lock);
+ 		goto restart;
+ 	}
+@@ -924,8 +1074,8 @@ void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num)
+ 
+ 	/* People waiting on recovery will wait on
+ 	 * the recovery map to empty. */
+-	if (!ocfs2_recovery_map_set(osb, node_num))
+-		mlog(0, "node %d already be in recovery.\n", node_num);
++	if (ocfs2_recovery_map_set(osb, node_num))
++		mlog(0, "node %d already in recovery map.\n", node_num);
+ 
+ 	mlog(0, "starting recovery thread...\n");
+ 
+@@ -1079,7 +1229,6 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
+ {
+ 	int status = 0;
+ 	int slot_num;
+-	struct ocfs2_slot_info *si = osb->slot_info;
+ 	struct ocfs2_dinode *la_copy = NULL;
+ 	struct ocfs2_dinode *tl_copy = NULL;
+ 
+@@ -1092,8 +1241,8 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
+ 	 * case we should've called ocfs2_journal_load instead. */
+ 	BUG_ON(osb->node_num == node_num);
+ 
+-	slot_num = ocfs2_node_num_to_slot(si, node_num);
+-	if (slot_num == OCFS2_INVALID_SLOT) {
++	slot_num = ocfs2_node_num_to_slot(osb, node_num);
++	if (slot_num == -ENOENT) {
+ 		status = 0;
+ 		mlog(0, "no slot for this node, so no recovery required.\n");
+ 		goto done;
+@@ -1123,8 +1272,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
+ 
+ 	/* Likewise, this would be a strange but ultimately not so
+ 	 * harmful place to get an error... */
+-	ocfs2_clear_slot(si, slot_num);
+-	status = ocfs2_update_disk_slots(osb, si);
++	status = ocfs2_clear_slot(osb, slot_num);
+ 	if (status < 0)
+ 		mlog_errno(status);
+ 
+@@ -1184,23 +1332,24 @@ bail:
+  * slot info struct has been updated from disk. */
+ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
+ {
+-	int status, i, node_num;
+-	struct ocfs2_slot_info *si = osb->slot_info;
++	unsigned int node_num;
++	int status, i;
+ 
+ 	/* This is called with the super block cluster lock, so we
+ 	 * know that the slot map can't change underneath us. */
+ 
+-	spin_lock(&si->si_lock);
+-	for(i = 0; i < si->si_num_slots; i++) {
++	spin_lock(&osb->osb_lock);
++	for (i = 0; i < osb->max_slots; i++) {
+ 		if (i == osb->slot_num)
+ 			continue;
+-		if (ocfs2_is_empty_slot(si, i))
++
++		status = ocfs2_slot_to_node_num_locked(osb, i, &node_num);
++		if (status == -ENOENT)
+ 			continue;
+ 
+-		node_num = si->si_global_node_nums[i];
+-		if (ocfs2_node_map_test_bit(osb, &osb->recovery_map, node_num))
++		if (__ocfs2_recovery_map_test(osb, node_num))
+ 			continue;
+-		spin_unlock(&si->si_lock);
++		spin_unlock(&osb->osb_lock);
+ 
+ 		/* Ok, we have a slot occupied by another node which
+ 		 * is not in the recovery map. We trylock his journal
+@@ -1216,9 +1365,9 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
+ 			goto bail;
+ 		}
+ 
+-		spin_lock(&si->si_lock);
++		spin_lock(&osb->osb_lock);
+ 	}
+-	spin_unlock(&si->si_lock);
++	spin_unlock(&osb->osb_lock);
+ 
+ 	status = 0;
+ bail:
+diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
+index 220f3e8..db82be2 100644
+--- a/fs/ocfs2/journal.h
++++ b/fs/ocfs2/journal.h
+@@ -134,6 +134,10 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
+ 
+ /* Exported only for the journal struct init code in super.c. Do not call. */
+ void ocfs2_complete_recovery(struct work_struct *work);
++void ocfs2_wait_for_recovery(struct ocfs2_super *osb);
++
++int ocfs2_recovery_init(struct ocfs2_super *osb);
++void ocfs2_recovery_exit(struct ocfs2_super *osb);
+ 
+ /*
+  *  Journal Control:
+diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
+index ab83fd5..ce0dc14 100644
+--- a/fs/ocfs2/localalloc.c
++++ b/fs/ocfs2/localalloc.c
+@@ -447,6 +447,8 @@ out_mutex:
+ 	iput(main_bm_inode);
+ 
+ out:
++	if (!status)
++		ocfs2_init_inode_steal_slot(osb);
+ 	mlog_exit(status);
+ 	return status;
+ }
+@@ -523,6 +525,8 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
+ 	}
+ 
+ 	ac->ac_inode = local_alloc_inode;
++	/* We should never use localalloc from another slot */
++	ac->ac_alloc_slot = osb->slot_num;
+ 	ac->ac_which = OCFS2_AC_USE_LOCAL;
+ 	get_bh(osb->local_alloc_bh);
+ 	ac->ac_bh = osb->local_alloc_bh;
+diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
+index ae9ad95..d5d808f 100644
+--- a/fs/ocfs2/namei.c
++++ b/fs/ocfs2/namei.c
+@@ -424,7 +424,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
+ 	fe->i_fs_generation = cpu_to_le32(osb->fs_generation);
+ 	fe->i_blkno = cpu_to_le64(fe_blkno);
+ 	fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
+-	fe->i_suballoc_slot = cpu_to_le16(osb->slot_num);
++	fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
+ 	fe->i_uid = cpu_to_le32(current->fsuid);
+ 	if (dir->i_mode & S_ISGID) {
+ 		fe->i_gid = cpu_to_le32(dir->i_gid);
+@@ -997,7 +997,7 @@ static int ocfs2_rename(struct inode *old_dir,
+ 	 *
+ 	 * And that's why, just like the VFS, we need a file system
+ 	 * rename lock. */
+-	if (old_dentry != new_dentry) {
++	if (old_dir != new_dir && S_ISDIR(old_inode->i_mode)) {
+ 		status = ocfs2_rename_lock(osb);
+ 		if (status < 0) {
+ 			mlog_errno(status);
+diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
+index 6546cef..3169237 100644
+--- a/fs/ocfs2/ocfs2.h
++++ b/fs/ocfs2/ocfs2.h
+@@ -36,11 +36,8 @@
+ #include <linux/mutex.h>
+ #include <linux/jbd.h>
+ 
+-#include "cluster/nodemanager.h"
+-#include "cluster/heartbeat.h"
+-#include "cluster/tcp.h"
+-
+-#include "dlm/dlmapi.h"
++/* For union ocfs2_dlm_lksb */
++#include "stackglue.h"
+ 
+ #include "ocfs2_fs.h"
+ #include "ocfs2_lockid.h"
+@@ -101,6 +98,9 @@ enum ocfs2_unlock_action {
+ 					       * dropped. */
+ #define OCFS2_LOCK_QUEUED        (0x00000100) /* queued for downconvert */
+ #define OCFS2_LOCK_NOCACHE       (0x00000200) /* don't use a holder count */
++#define OCFS2_LOCK_PENDING       (0x00000400) /* This lockres is pending a
++						 call to dlm_lock.  Only
++						 exists with BUSY set. */
+ 
+ struct ocfs2_lock_res_ops;
+ 
+@@ -120,13 +120,14 @@ struct ocfs2_lock_res {
+ 	int                      l_level;
+ 	unsigned int             l_ro_holders;
+ 	unsigned int             l_ex_holders;
+-	struct dlm_lockstatus    l_lksb;
++	union ocfs2_dlm_lksb     l_lksb;
+ 
+ 	/* used from AST/BAST funcs. */
+ 	enum ocfs2_ast_action    l_action;
+ 	enum ocfs2_unlock_action l_unlock_action;
+ 	int                      l_requested;
+ 	int                      l_blocking;
++	unsigned int             l_pending_gen;
+ 
+ 	wait_queue_head_t        l_event;
+ 
+@@ -179,6 +180,8 @@ enum ocfs2_mount_options
+ #define OCFS2_DEFAULT_ATIME_QUANTUM	60
+ 
+ struct ocfs2_journal;
++struct ocfs2_slot_info;
++struct ocfs2_recovery_map;
+ struct ocfs2_super
+ {
+ 	struct task_struct *commit_task;
+@@ -190,7 +193,6 @@ struct ocfs2_super
+ 	struct ocfs2_slot_info *slot_info;
+ 
+ 	spinlock_t node_map_lock;
+-	struct ocfs2_node_map recovery_map;
+ 
+ 	u64 root_blkno;
+ 	u64 system_dir_blkno;
+@@ -206,25 +208,29 @@ struct ocfs2_super
+ 	u32 s_feature_incompat;
+ 	u32 s_feature_ro_compat;
+ 
+-	/* Protects s_next_generaion, osb_flags. Could protect more on
+-	 * osb as it's very short lived. */
++	/* Protects s_next_generation, osb_flags and s_inode_steal_slot.
++	 * Could protect more on osb as it's very short lived.
++	 */
+ 	spinlock_t osb_lock;
+ 	u32 s_next_generation;
+ 	unsigned long osb_flags;
++	s16 s_inode_steal_slot;
++	atomic_t s_num_inodes_stolen;
+ 
+ 	unsigned long s_mount_opt;
+ 	unsigned int s_atime_quantum;
+ 
+-	u16 max_slots;
+-	s16 node_num;
+-	s16 slot_num;
+-	s16 preferred_slot;
++	unsigned int max_slots;
++	unsigned int node_num;
++	int slot_num;
++	int preferred_slot;
+ 	int s_sectsize_bits;
+ 	int s_clustersize;
+ 	int s_clustersize_bits;
+ 
+ 	atomic_t vol_state;
+ 	struct mutex recovery_lock;
++	struct ocfs2_recovery_map *recovery_map;
+ 	struct task_struct *recovery_thread_task;
+ 	int disable_recovery;
+ 	wait_queue_head_t checkpoint_event;
+@@ -245,12 +251,11 @@ struct ocfs2_super
+ 	struct ocfs2_alloc_stats alloc_stats;
+ 	char dev_str[20];		/* "major,minor" of the device */
+ 
+-	struct dlm_ctxt *dlm;
++	char osb_cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
++	struct ocfs2_cluster_connection *cconn;
+ 	struct ocfs2_lock_res osb_super_lockres;
+ 	struct ocfs2_lock_res osb_rename_lockres;
+-	struct dlm_eviction_cb osb_eviction_cb;
+ 	struct ocfs2_dlm_debug *osb_dlm_debug;
+-	struct dlm_protocol_version osb_locking_proto;
+ 
+ 	struct dentry *osb_debug_root;
+ 
+@@ -367,11 +372,24 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
+ 	return ret;
+ }
+ 
++static inline int ocfs2_userspace_stack(struct ocfs2_super *osb)
++{
++	return (osb->s_feature_incompat &
++		OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK);
++}
++
+ static inline int ocfs2_mount_local(struct ocfs2_super *osb)
+ {
+ 	return (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT);
+ }
+ 
++static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super *osb)
++{
++	return (osb->s_feature_incompat &
++		OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP);
++}
++
++
+ #define OCFS2_IS_VALID_DINODE(ptr)					\
+ 	(!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
+ 
+@@ -522,6 +540,33 @@ static inline unsigned int ocfs2_pages_per_cluster(struct super_block *sb)
+ 	return pages_per_cluster;
+ }
+ 
++static inline void ocfs2_init_inode_steal_slot(struct ocfs2_super *osb)
++{
++	spin_lock(&osb->osb_lock);
++	osb->s_inode_steal_slot = OCFS2_INVALID_SLOT;
++	spin_unlock(&osb->osb_lock);
++	atomic_set(&osb->s_num_inodes_stolen, 0);
++}
++
++static inline void ocfs2_set_inode_steal_slot(struct ocfs2_super *osb,
++					      s16 slot)
++{
++	spin_lock(&osb->osb_lock);
++	osb->s_inode_steal_slot = slot;
++	spin_unlock(&osb->osb_lock);
++}
++
++static inline s16 ocfs2_get_inode_steal_slot(struct ocfs2_super *osb)
++{
++	s16 slot;
++
++	spin_lock(&osb->osb_lock);
++	slot = osb->s_inode_steal_slot;
++	spin_unlock(&osb->osb_lock);
++
++	return slot;
++}
++
+ #define ocfs2_set_bit ext2_set_bit
+ #define ocfs2_clear_bit ext2_clear_bit
+ #define ocfs2_test_bit ext2_test_bit
+diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
+index 3633edd..52c4266 100644
+--- a/fs/ocfs2/ocfs2_fs.h
++++ b/fs/ocfs2/ocfs2_fs.h
+@@ -88,7 +88,9 @@
+ #define OCFS2_FEATURE_COMPAT_SUPP	OCFS2_FEATURE_COMPAT_BACKUP_SB
+ #define OCFS2_FEATURE_INCOMPAT_SUPP	(OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
+ 					 | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \
+-					 | OCFS2_FEATURE_INCOMPAT_INLINE_DATA)
++					 | OCFS2_FEATURE_INCOMPAT_INLINE_DATA \
++					 | OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP \
++					 | OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK)
+ #define OCFS2_FEATURE_RO_COMPAT_SUPP	OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
+ 
+ /*
+@@ -125,6 +127,21 @@
+ /* Support for data packed into inode blocks */
+ #define OCFS2_FEATURE_INCOMPAT_INLINE_DATA	0x0040
+ 
++/* Support for the extended slot map */
++#define OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP 0x100
++
++
++/*
++ * Support for alternate, userspace cluster stacks.  If set, the superblock
++ * field s_cluster_info contains a tag for the alternate stack in use as
++ * well as the name of the cluster being joined.
++ * mount.ocfs2 must pass in a matching stack name.
++ *
++ * If not set, the classic stack will be used.  This is compatbile with
++ * all older versions.
++ */
++#define OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK	0x0080
++
+ /*
+  * backup superblock flag is used to indicate that this volume
+  * has backup superblocks.
+@@ -267,6 +284,10 @@ struct ocfs2_new_group_input {
+ #define OCFS2_VOL_UUID_LEN		16
+ #define OCFS2_MAX_VOL_LABEL_LEN		64
+ 
++/* The alternate, userspace stack fields */
++#define OCFS2_STACK_LABEL_LEN		4
++#define OCFS2_CLUSTER_NAME_LEN		16
++
+ /* Journal limits (in bytes) */
+ #define OCFS2_MIN_JOURNAL_SIZE		(4 * 1024 * 1024)
+ 
+@@ -475,6 +496,47 @@ struct ocfs2_extent_block
+ };
+ 
+ /*
++ * On disk slot map for OCFS2.  This defines the contents of the "slot_map"
++ * system file.  A slot is valid if it contains a node number >= 0.  The
++ * value -1 (0xFFFF) is OCFS2_INVALID_SLOT.  This marks a slot empty.
++ */
++struct ocfs2_slot_map {
++/*00*/	__le16 sm_slots[0];
++/*
++ * Actual on-disk size is one block.  OCFS2_MAX_SLOTS is 255,
++ * 255 * sizeof(__le16) == 512B, within the 512B block minimum blocksize.
++ */
++};
++
++struct ocfs2_extended_slot {
++/*00*/	__u8	es_valid;
++	__u8	es_reserved1[3];
++	__le32	es_node_num;
++/*10*/
++};
++
++/*
++ * The extended slot map, used when OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP
++ * is set.  It separates out the valid marker from the node number, and
++ * has room to grow.  Unlike the old slot map, this format is defined by
++ * i_size.
++ */
++struct ocfs2_slot_map_extended {
++/*00*/	struct ocfs2_extended_slot se_slots[0];
++/*
++ * Actual size is i_size of the slot_map system file.  It should
++ * match s_max_slots * sizeof(struct ocfs2_extended_slot)
++ */
++};
++
++struct ocfs2_cluster_info {
++/*00*/	__u8   ci_stack[OCFS2_STACK_LABEL_LEN];
++	__le32 ci_reserved;
++/*08*/	__u8   ci_cluster[OCFS2_CLUSTER_NAME_LEN];
++/*18*/
++};
++
++/*
+  * On disk superblock for OCFS2
+  * Note that it is contained inside an ocfs2_dinode, so all offsets
+  * are relative to the start of ocfs2_dinode.id2.
+@@ -506,7 +568,20 @@ struct ocfs2_super_block {
+ 					 * 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*/
++/*A0*/  struct ocfs2_cluster_info s_cluster_info; /* Selected userspace
++						     stack.  Only valid
++						     with INCOMPAT flag. */
++/*B8*/  __le64 s_reserved2[17];		/* Fill out superblock */
++/*140*/
++
++	/*
++	 * NOTE: As stated above, all offsets are relative to
++	 * ocfs2_dinode.id2, which is at 0xC0 in the inode.
++	 * 0xC0 + 0x140 = 0x200 or 512 bytes.  A superblock must fit within
++	 * our smallest blocksize, which is 512 bytes.  To ensure this,
++	 * we reserve the space in s_reserved2.  Anything past s_reserved2
++	 * will not be available on the smallest blocksize.
++	 */
+ };
+ 
+ /*
+diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
+index 86f3e37..82c200f 100644
+--- a/fs/ocfs2/ocfs2_lockid.h
++++ b/fs/ocfs2/ocfs2_lockid.h
+@@ -100,7 +100,7 @@ static char *ocfs2_lock_type_strings[] = {
+ static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
+ {
+ #ifdef __KERNEL__
+-	mlog_bug_on_msg(type >= OCFS2_NUM_LOCK_TYPES, "%d\n", type);
++	BUG_ON(type >= OCFS2_NUM_LOCK_TYPES);
+ #endif
+ 	return ocfs2_lock_type_strings[type];
+ }
+diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
+index 3a50ce5..bb5ff89 100644
+--- a/fs/ocfs2/slot_map.c
++++ b/fs/ocfs2/slot_map.c
+@@ -42,81 +42,244 @@
+ 
+ #include "buffer_head_io.h"
+ 
+-static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+-				    s16 global);
+-static void __ocfs2_fill_slot(struct ocfs2_slot_info *si,
+-			      s16 slot_num,
+-			      s16 node_num);
+-
+-/* post the slot information on disk into our slot_info struct. */
+-void ocfs2_update_slot_info(struct ocfs2_slot_info *si)
++
++struct ocfs2_slot {
++	int sl_valid;
++	unsigned int sl_node_num;
++};
++
++struct ocfs2_slot_info {
++	int si_extended;
++	int si_slots_per_block;
++	struct inode *si_inode;
++	unsigned int si_blocks;
++	struct buffer_head **si_bh;
++	unsigned int si_num_slots;
++	struct ocfs2_slot *si_slots;
++};
++
++
++static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
++				    unsigned int node_num);
++
++static void ocfs2_invalidate_slot(struct ocfs2_slot_info *si,
++				  int slot_num)
++{
++	BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots));
++	si->si_slots[slot_num].sl_valid = 0;
++}
++
++static void ocfs2_set_slot(struct ocfs2_slot_info *si,
++			   int slot_num, unsigned int node_num)
++{
++	BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots));
++
++	si->si_slots[slot_num].sl_valid = 1;
++	si->si_slots[slot_num].sl_node_num = node_num;
++}
++
++/* This version is for the extended slot map */
++static void ocfs2_update_slot_info_extended(struct ocfs2_slot_info *si)
++{
++	int b, i, slotno;
++	struct ocfs2_slot_map_extended *se;
++
++	slotno = 0;
++	for (b = 0; b < si->si_blocks; b++) {
++		se = (struct ocfs2_slot_map_extended *)si->si_bh[b]->b_data;
++		for (i = 0;
++		     (i < si->si_slots_per_block) &&
++		     (slotno < si->si_num_slots);
++		     i++, slotno++) {
++			if (se->se_slots[i].es_valid)
++				ocfs2_set_slot(si, slotno,
++					       le32_to_cpu(se->se_slots[i].es_node_num));
++			else
++				ocfs2_invalidate_slot(si, slotno);
++		}
++	}
++}
++
++/*
++ * Post the slot information on disk into our slot_info struct.
++ * Must be protected by osb_lock.
++ */
++static void ocfs2_update_slot_info_old(struct ocfs2_slot_info *si)
+ {
+ 	int i;
+-	__le16 *disk_info;
++	struct ocfs2_slot_map *sm;
+ 
+-	/* we don't read the slot block here as ocfs2_super_lock
+-	 * should've made sure we have the most recent copy. */
+-	spin_lock(&si->si_lock);
+-	disk_info = (__le16 *) si->si_bh->b_data;
++	sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data;
+ 
+-	for (i = 0; i < si->si_size; i++)
+-		si->si_global_node_nums[i] = le16_to_cpu(disk_info[i]);
++	for (i = 0; i < si->si_num_slots; i++) {
++		if (le16_to_cpu(sm->sm_slots[i]) == (u16)OCFS2_INVALID_SLOT)
++			ocfs2_invalidate_slot(si, i);
++		else
++			ocfs2_set_slot(si, i, le16_to_cpu(sm->sm_slots[i]));
++	}
++}
+ 
+-	spin_unlock(&si->si_lock);
++static void ocfs2_update_slot_info(struct ocfs2_slot_info *si)
++{
++	/*
++	 * The slot data will have been refreshed when ocfs2_super_lock
++	 * was taken.
++	 */
++	if (si->si_extended)
++		ocfs2_update_slot_info_extended(si);
++	else
++		ocfs2_update_slot_info_old(si);
++}
++
++int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
++{
++	int ret;
++	struct ocfs2_slot_info *si = osb->slot_info;
++
++	if (si == NULL)
++		return 0;
++
++	BUG_ON(si->si_blocks == 0);
++	BUG_ON(si->si_bh == NULL);
++
++	mlog(0, "Refreshing slot map, reading %u block(s)\n",
++	     si->si_blocks);
++
++	/*
++	 * We pass -1 as blocknr because we expect all of si->si_bh to
++	 * be !NULL.  Thus, ocfs2_read_blocks() will ignore blocknr.  If
++	 * this is not true, the read of -1 (UINT64_MAX) will fail.
++	 */
++	ret = ocfs2_read_blocks(osb, -1, si->si_blocks, si->si_bh, 0,
++				si->si_inode);
++	if (ret == 0) {
++		spin_lock(&osb->osb_lock);
++		ocfs2_update_slot_info(si);
++		spin_unlock(&osb->osb_lock);
++	}
++
++	return ret;
+ }
+ 
+ /* post the our slot info stuff into it's destination bh and write it
+  * out. */
+-int ocfs2_update_disk_slots(struct ocfs2_super *osb,
+-			    struct ocfs2_slot_info *si)
++static void ocfs2_update_disk_slot_extended(struct ocfs2_slot_info *si,
++					    int slot_num,
++					    struct buffer_head **bh)
+ {
+-	int status, i;
+-	__le16 *disk_info = (__le16 *) si->si_bh->b_data;
++	int blkind = slot_num / si->si_slots_per_block;
++	int slotno = slot_num % si->si_slots_per_block;
++	struct ocfs2_slot_map_extended *se;
++
++	BUG_ON(blkind >= si->si_blocks);
++
++	se = (struct ocfs2_slot_map_extended *)si->si_bh[blkind]->b_data;
++	se->se_slots[slotno].es_valid = si->si_slots[slot_num].sl_valid;
++	if (si->si_slots[slot_num].sl_valid)
++		se->se_slots[slotno].es_node_num =
++			cpu_to_le32(si->si_slots[slot_num].sl_node_num);
++	*bh = si->si_bh[blkind];
++}
+ 
+-	spin_lock(&si->si_lock);
+-	for (i = 0; i < si->si_size; i++)
+-		disk_info[i] = cpu_to_le16(si->si_global_node_nums[i]);
+-	spin_unlock(&si->si_lock);
++static void ocfs2_update_disk_slot_old(struct ocfs2_slot_info *si,
++				       int slot_num,
++				       struct buffer_head **bh)
++{
++	int i;
++	struct ocfs2_slot_map *sm;
++
++	sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data;
++	for (i = 0; i < si->si_num_slots; i++) {
++		if (si->si_slots[i].sl_valid)
++			sm->sm_slots[i] =
++				cpu_to_le16(si->si_slots[i].sl_node_num);
++		else
++			sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT);
++	}
++	*bh = si->si_bh[0];
++}
++
++static int ocfs2_update_disk_slot(struct ocfs2_super *osb,
++				  struct ocfs2_slot_info *si,
++				  int slot_num)
++{
++	int status;
++	struct buffer_head *bh;
++
++	spin_lock(&osb->osb_lock);
++	if (si->si_extended)
++		ocfs2_update_disk_slot_extended(si, slot_num, &bh);
++	else
++		ocfs2_update_disk_slot_old(si, slot_num, &bh);
++	spin_unlock(&osb->osb_lock);
+ 
+-	status = ocfs2_write_block(osb, si->si_bh, si->si_inode);
++	status = ocfs2_write_block(osb, bh, si->si_inode);
+ 	if (status < 0)
+ 		mlog_errno(status);
+ 
+ 	return status;
+ }
+ 
+-/* try to find global node in the slot info. Returns
+- * OCFS2_INVALID_SLOT if nothing is found. */
+-static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+-				    s16 global)
++/*
++ * Calculate how many bytes are needed by the slot map.  Returns
++ * an error if the slot map file is too small.
++ */
++static int ocfs2_slot_map_physical_size(struct ocfs2_super *osb,
++					struct inode *inode,
++					unsigned long long *bytes)
+ {
+-	int i;
+-	s16 ret = OCFS2_INVALID_SLOT;
++	unsigned long long bytes_needed;
++
++	if (ocfs2_uses_extended_slot_map(osb)) {
++		bytes_needed = osb->max_slots *
++			sizeof(struct ocfs2_extended_slot);
++	} else {
++		bytes_needed = osb->max_slots * sizeof(__le16);
++	}
++	if (bytes_needed > i_size_read(inode)) {
++		mlog(ML_ERROR,
++		     "Slot map file is too small!  (size %llu, needed %llu)\n",
++		     i_size_read(inode), bytes_needed);
++		return -ENOSPC;
++	}
++
++	*bytes = bytes_needed;
++	return 0;
++}
++
++/* try to find global node in the slot info. Returns -ENOENT
++ * if nothing is found. */
++static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
++				    unsigned int node_num)
++{
++	int i, ret = -ENOENT;
+ 
+ 	for(i = 0; i < si->si_num_slots; i++) {
+-		if (global == si->si_global_node_nums[i]) {
+-			ret = (s16) i;
++		if (si->si_slots[i].sl_valid &&
++		    (node_num == si->si_slots[i].sl_node_num)) {
++			ret = i;
+ 			break;
+ 		}
+ 	}
++
+ 	return ret;
+ }
+ 
+-static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, s16 preferred)
++static int __ocfs2_find_empty_slot(struct ocfs2_slot_info *si,
++				   int preferred)
+ {
+-	int i;
+-	s16 ret = OCFS2_INVALID_SLOT;
++	int i, ret = -ENOSPC;
+ 
+-	if (preferred >= 0 && preferred < si->si_num_slots) {
+-		if (OCFS2_INVALID_SLOT == si->si_global_node_nums[preferred]) {
++	if ((preferred >= 0) && (preferred < si->si_num_slots)) {
++		if (!si->si_slots[preferred].sl_valid) {
+ 			ret = preferred;
+ 			goto out;
+ 		}
+ 	}
+ 
+ 	for(i = 0; i < si->si_num_slots; i++) {
+-		if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) {
+-			ret = (s16) i;
++		if (!si->si_slots[i].sl_valid) {
++			ret = i;
+ 			break;
+ 		}
+ 	}
+@@ -124,58 +287,155 @@ out:
+ 	return ret;
+ }
+ 
+-s16 ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+-			   s16 global)
++int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num)
+ {
+-	s16 ret;
++	int slot;
++	struct ocfs2_slot_info *si = osb->slot_info;
+ 
+-	spin_lock(&si->si_lock);
+-	ret = __ocfs2_node_num_to_slot(si, global);
+-	spin_unlock(&si->si_lock);
+-	return ret;
++	spin_lock(&osb->osb_lock);
++	slot = __ocfs2_node_num_to_slot(si, node_num);
++	spin_unlock(&osb->osb_lock);
++
++	return slot;
++}
++
++int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num,
++				  unsigned int *node_num)
++{
++	struct ocfs2_slot_info *si = osb->slot_info;
++
++	assert_spin_locked(&osb->osb_lock);
++
++	BUG_ON(slot_num < 0);
++	BUG_ON(slot_num > osb->max_slots);
++
++	if (!si->si_slots[slot_num].sl_valid)
++		return -ENOENT;
++
++	*node_num = si->si_slots[slot_num].sl_node_num;
++	return 0;
+ }
+ 
+-static void __ocfs2_fill_slot(struct ocfs2_slot_info *si,
+-			      s16 slot_num,
+-			      s16 node_num)
++static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si)
+ {
+-	BUG_ON(slot_num == OCFS2_INVALID_SLOT);
+-	BUG_ON(slot_num >= si->si_num_slots);
+-	BUG_ON((node_num != O2NM_INVALID_NODE_NUM) &&
+-	       (node_num >= O2NM_MAX_NODES));
++	unsigned int i;
++
++	if (si == NULL)
++		return;
++
++	if (si->si_inode)
++		iput(si->si_inode);
++	if (si->si_bh) {
++		for (i = 0; i < si->si_blocks; i++) {
++			if (si->si_bh[i]) {
++				brelse(si->si_bh[i]);
++				si->si_bh[i] = NULL;
++			}
++		}
++		kfree(si->si_bh);
++	}
+ 
+-	si->si_global_node_nums[slot_num] = node_num;
++	kfree(si);
+ }
+ 
+-void ocfs2_clear_slot(struct ocfs2_slot_info *si,
+-		      s16 slot_num)
++int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num)
+ {
+-	spin_lock(&si->si_lock);
+-	__ocfs2_fill_slot(si, slot_num, OCFS2_INVALID_SLOT);
+-	spin_unlock(&si->si_lock);
++	struct ocfs2_slot_info *si = osb->slot_info;
++
++	if (si == NULL)
++		return 0;
++
++	spin_lock(&osb->osb_lock);
++	ocfs2_invalidate_slot(si, slot_num);
++	spin_unlock(&osb->osb_lock);
++
++	return ocfs2_update_disk_slot(osb, osb->slot_info, slot_num);
+ }
+ 
+-int ocfs2_init_slot_info(struct ocfs2_super *osb)
++static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
++				  struct ocfs2_slot_info *si)
+ {
+-	int status, i;
++	int status = 0;
+ 	u64 blkno;
++	unsigned long long blocks, bytes;
++	unsigned int i;
++	struct buffer_head *bh;
++
++	status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes);
++	if (status)
++		goto bail;
++
++	blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes);
++	BUG_ON(blocks > UINT_MAX);
++	si->si_blocks = blocks;
++	if (!si->si_blocks)
++		goto bail;
++
++	if (si->si_extended)
++		si->si_slots_per_block =
++			(osb->sb->s_blocksize /
++			 sizeof(struct ocfs2_extended_slot));
++	else
++		si->si_slots_per_block = osb->sb->s_blocksize / sizeof(__le16);
++
++	/* The size checks above should ensure this */
++	BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks);
++
++	mlog(0, "Slot map needs %u buffers for %llu bytes\n",
++	     si->si_blocks, bytes);
++
++	si->si_bh = kzalloc(sizeof(struct buffer_head *) * si->si_blocks,
++			    GFP_KERNEL);
++	if (!si->si_bh) {
++		status = -ENOMEM;
++		mlog_errno(status);
++		goto bail;
++	}
++
++	for (i = 0; i < si->si_blocks; i++) {
++		status = ocfs2_extent_map_get_blocks(si->si_inode, i,
++						     &blkno, NULL, NULL);
++		if (status < 0) {
++			mlog_errno(status);
++			goto bail;
++		}
++
++		mlog(0, "Reading slot map block %u at %llu\n", i,
++		     (unsigned long long)blkno);
++
++		bh = NULL;  /* Acquire a fresh bh */
++		status = ocfs2_read_block(osb, blkno, &bh, 0, si->si_inode);
++		if (status < 0) {
++			mlog_errno(status);
++			goto bail;
++		}
++
++		si->si_bh[i] = bh;
++	}
++
++bail:
++	return status;
++}
++
++int ocfs2_init_slot_info(struct ocfs2_super *osb)
++{
++	int status;
+ 	struct inode *inode = NULL;
+-	struct buffer_head *bh = NULL;
+ 	struct ocfs2_slot_info *si;
+ 
+-	si = kzalloc(sizeof(struct ocfs2_slot_info), GFP_KERNEL);
++	si = kzalloc(sizeof(struct ocfs2_slot_info) +
++		     (sizeof(struct ocfs2_slot) * osb->max_slots),
++		     GFP_KERNEL);
+ 	if (!si) {
+ 		status = -ENOMEM;
+ 		mlog_errno(status);
+ 		goto bail;
+ 	}
+ 
+-	spin_lock_init(&si->si_lock);
++	si->si_extended = ocfs2_uses_extended_slot_map(osb);
+ 	si->si_num_slots = osb->max_slots;
+-	si->si_size = OCFS2_MAX_SLOTS;
+-
+-	for(i = 0; i < si->si_num_slots; i++)
+-		si->si_global_node_nums[i] = OCFS2_INVALID_SLOT;
++	si->si_slots = (struct ocfs2_slot *)((char *)si +
++					     sizeof(struct ocfs2_slot_info));
+ 
+ 	inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE,
+ 					    OCFS2_INVALID_SLOT);
+@@ -185,61 +445,53 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb)
+ 		goto bail;
+ 	}
+ 
+-	status = ocfs2_extent_map_get_blocks(inode, 0ULL, &blkno, NULL, NULL);
+-	if (status < 0) {
+-		mlog_errno(status);
+-		goto bail;
+-	}
+-
+-	status = ocfs2_read_block(osb, blkno, &bh, 0, inode);
++	si->si_inode = inode;
++	status = ocfs2_map_slot_buffers(osb, si);
+ 	if (status < 0) {
+ 		mlog_errno(status);
+ 		goto bail;
+ 	}
+ 
+-	si->si_inode = inode;
+-	si->si_bh = bh;
+-	osb->slot_info = si;
++	osb->slot_info = (struct ocfs2_slot_info *)si;
+ bail:
+ 	if (status < 0 && si)
+-		ocfs2_free_slot_info(si);
++		__ocfs2_free_slot_info(si);
+ 
+ 	return status;
+ }
+ 
+-void ocfs2_free_slot_info(struct ocfs2_slot_info *si)
++void ocfs2_free_slot_info(struct ocfs2_super *osb)
+ {
+-	if (si->si_inode)
+-		iput(si->si_inode);
+-	if (si->si_bh)
+-		brelse(si->si_bh);
+-	kfree(si);
++	struct ocfs2_slot_info *si = osb->slot_info;
++
++	osb->slot_info = NULL;
++	__ocfs2_free_slot_info(si);
+ }
+ 
+ int ocfs2_find_slot(struct ocfs2_super *osb)
+ {
+ 	int status;
+-	s16 slot;
++	int slot;
+ 	struct ocfs2_slot_info *si;
+ 
+ 	mlog_entry_void();
+ 
+ 	si = osb->slot_info;
+ 
++	spin_lock(&osb->osb_lock);
+ 	ocfs2_update_slot_info(si);
+ 
+-	spin_lock(&si->si_lock);
+ 	/* search for ourselves first and take the slot if it already
+ 	 * exists. Perhaps we need to mark this in a variable for our
+ 	 * own journal recovery? Possibly not, though we certainly
+ 	 * need to warn to the user */
+ 	slot = __ocfs2_node_num_to_slot(si, osb->node_num);
+-	if (slot == OCFS2_INVALID_SLOT) {
++	if (slot < 0) {
+ 		/* if no slot yet, then just take 1st available
+ 		 * one. */
+ 		slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
+-		if (slot == OCFS2_INVALID_SLOT) {
+-			spin_unlock(&si->si_lock);
++		if (slot < 0) {
++			spin_unlock(&osb->osb_lock);
+ 			mlog(ML_ERROR, "no free slots available!\n");
+ 			status = -EINVAL;
+ 			goto bail;
+@@ -248,13 +500,13 @@ int ocfs2_find_slot(struct ocfs2_super *osb)
+ 		mlog(ML_NOTICE, "slot %d is already allocated to this node!\n",
+ 		     slot);
+ 
+-	__ocfs2_fill_slot(si, slot, osb->node_num);
++	ocfs2_set_slot(si, slot, osb->node_num);
+ 	osb->slot_num = slot;
+-	spin_unlock(&si->si_lock);
++	spin_unlock(&osb->osb_lock);
+ 
+ 	mlog(0, "taking node slot %d\n", osb->slot_num);
+ 
+-	status = ocfs2_update_disk_slots(osb, si);
++	status = ocfs2_update_disk_slot(osb, si, osb->slot_num);
+ 	if (status < 0)
+ 		mlog_errno(status);
+ 
+@@ -265,27 +517,27 @@ bail:
+ 
+ void ocfs2_put_slot(struct ocfs2_super *osb)
+ {
+-	int status;
++	int status, slot_num;
+ 	struct ocfs2_slot_info *si = osb->slot_info;
+ 
+ 	if (!si)
+ 		return;
+ 
++	spin_lock(&osb->osb_lock);
+ 	ocfs2_update_slot_info(si);
+ 
+-	spin_lock(&si->si_lock);
+-	__ocfs2_fill_slot(si, osb->slot_num, OCFS2_INVALID_SLOT);
++	slot_num = osb->slot_num;
++	ocfs2_invalidate_slot(si, osb->slot_num);
+ 	osb->slot_num = OCFS2_INVALID_SLOT;
+-	spin_unlock(&si->si_lock);
++	spin_unlock(&osb->osb_lock);
+ 
+-	status = ocfs2_update_disk_slots(osb, si);
++	status = ocfs2_update_disk_slot(osb, si, slot_num);
+ 	if (status < 0) {
+ 		mlog_errno(status);
+ 		goto bail;
+ 	}
+ 
+ bail:
+-	osb->slot_info = NULL;
+-	ocfs2_free_slot_info(si);
++	ocfs2_free_slot_info(osb);
+ }
+ 
+diff --git a/fs/ocfs2/slot_map.h b/fs/ocfs2/slot_map.h
+index 1025872..601c95f 100644
+--- a/fs/ocfs2/slot_map.h
++++ b/fs/ocfs2/slot_map.h
+@@ -27,38 +27,18 @@
+ #ifndef SLOTMAP_H
+ #define SLOTMAP_H
+ 
+-struct ocfs2_slot_info {
+-	spinlock_t si_lock;
+-
+-       	struct inode *si_inode;
+-	struct buffer_head *si_bh;
+-	unsigned int si_num_slots;
+-	unsigned int si_size;
+-	s16 si_global_node_nums[OCFS2_MAX_SLOTS];
+-};
+-
+ int ocfs2_init_slot_info(struct ocfs2_super *osb);
+-void ocfs2_free_slot_info(struct ocfs2_slot_info *si);
++void ocfs2_free_slot_info(struct ocfs2_super *osb);
+ 
+ int ocfs2_find_slot(struct ocfs2_super *osb);
+ void ocfs2_put_slot(struct ocfs2_super *osb);
+ 
+-void ocfs2_update_slot_info(struct ocfs2_slot_info *si);
+-int ocfs2_update_disk_slots(struct ocfs2_super *osb,
+-			    struct ocfs2_slot_info *si);
+-
+-s16 ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+-			   s16 global);
+-void ocfs2_clear_slot(struct ocfs2_slot_info *si,
+-		      s16 slot_num);
++int ocfs2_refresh_slot_info(struct ocfs2_super *osb);
+ 
+-static inline int ocfs2_is_empty_slot(struct ocfs2_slot_info *si,
+-				      int slot_num)
+-{
+-	BUG_ON(slot_num == OCFS2_INVALID_SLOT);
+-	assert_spin_locked(&si->si_lock);
++int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num);
++int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num,
++				  unsigned int *node_num);
+ 
+-	return si->si_global_node_nums[slot_num] == OCFS2_INVALID_SLOT;
+-}
++int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num);
+ 
+ #endif
+diff --git a/fs/ocfs2/stack_o2cb.c b/fs/ocfs2/stack_o2cb.c
+new file mode 100644
+index 0000000..ac1d74c
+--- /dev/null
++++ b/fs/ocfs2/stack_o2cb.c
+@@ -0,0 +1,420 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * stack_o2cb.c
++ *
++ * Code which interfaces ocfs2 with the o2cb stack.
++ *
++ * Copyright (C) 2007 Oracle.  All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public
++ * License as published by the Free Software Foundation, version 2.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/crc32.h>
++#include <linux/module.h>
++
++/* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */
++#include <linux/fs.h>
++
++#include "cluster/masklog.h"
++#include "cluster/nodemanager.h"
++#include "cluster/heartbeat.h"
++
++#include "stackglue.h"
++
++struct o2dlm_private {
++	struct dlm_eviction_cb op_eviction_cb;
++};
++
++static struct ocfs2_stack_plugin o2cb_stack;
++
++/* These should be identical */
++#if (DLM_LOCK_IV != LKM_IVMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_NL != LKM_NLMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_CR != LKM_CRMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_CW != LKM_CWMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_PR != LKM_PRMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_PW != LKM_PWMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_EX != LKM_EXMODE)
++# error Lock modes do not match
++#endif
++static inline int mode_to_o2dlm(int mode)
++{
++	BUG_ON(mode > LKM_MAXMODE);
++
++	return mode;
++}
++
++#define map_flag(_generic, _o2dlm)		\
++	if (flags & (_generic)) {		\
++		flags &= ~(_generic);		\
++		o2dlm_flags |= (_o2dlm);	\
++	}
++static int flags_to_o2dlm(u32 flags)
++{
++	int o2dlm_flags = 0;
++
++	map_flag(DLM_LKF_NOQUEUE, LKM_NOQUEUE);
++	map_flag(DLM_LKF_CANCEL, LKM_CANCEL);
++	map_flag(DLM_LKF_CONVERT, LKM_CONVERT);
++	map_flag(DLM_LKF_VALBLK, LKM_VALBLK);
++	map_flag(DLM_LKF_IVVALBLK, LKM_INVVALBLK);
++	map_flag(DLM_LKF_ORPHAN, LKM_ORPHAN);
++	map_flag(DLM_LKF_FORCEUNLOCK, LKM_FORCE);
++	map_flag(DLM_LKF_TIMEOUT, LKM_TIMEOUT);
++	map_flag(DLM_LKF_LOCAL, LKM_LOCAL);
++
++	/* map_flag() should have cleared every flag passed in */
++	BUG_ON(flags != 0);
++
++	return o2dlm_flags;
++}
++#undef map_flag
++
++/*
++ * Map an o2dlm status to standard errno values.
++ *
++ * o2dlm only uses a handful of these, and returns even fewer to the
++ * caller. Still, we try to assign sane values to each error.
++ *
++ * The following value pairs have special meanings to dlmglue, thus
++ * the right hand side needs to stay unique - never duplicate the
++ * mapping elsewhere in the table!
++ *
++ * DLM_NORMAL:		0
++ * DLM_NOTQUEUED:	-EAGAIN
++ * DLM_CANCELGRANT:	-EBUSY
++ * DLM_CANCEL:		-DLM_ECANCEL
++ */
++/* Keep in sync with dlmapi.h */
++static int status_map[] = {
++	[DLM_NORMAL]			= 0,		/* Success */
++	[DLM_GRANTED]			= -EINVAL,
++	[DLM_DENIED]			= -EACCES,
++	[DLM_DENIED_NOLOCKS]		= -EACCES,
++	[DLM_WORKING]			= -EACCES,
++	[DLM_BLOCKED]			= -EINVAL,
++	[DLM_BLOCKED_ORPHAN]		= -EINVAL,
++	[DLM_DENIED_GRACE_PERIOD]	= -EACCES,
++	[DLM_SYSERR]			= -ENOMEM,	/* It is what it is */
++	[DLM_NOSUPPORT]			= -EPROTO,
++	[DLM_CANCELGRANT]		= -EBUSY,	/* Cancel after grant */
++	[DLM_IVLOCKID]			= -EINVAL,
++	[DLM_SYNC]			= -EINVAL,
++	[DLM_BADTYPE]			= -EINVAL,
++	[DLM_BADRESOURCE]		= -EINVAL,
++	[DLM_MAXHANDLES]		= -ENOMEM,
++	[DLM_NOCLINFO]			= -EINVAL,
++	[DLM_NOLOCKMGR]			= -EINVAL,
++	[DLM_NOPURGED]			= -EINVAL,
++	[DLM_BADARGS]			= -EINVAL,
++	[DLM_VOID]			= -EINVAL,
++	[DLM_NOTQUEUED]			= -EAGAIN,	/* Trylock failed */
++	[DLM_IVBUFLEN]			= -EINVAL,
++	[DLM_CVTUNGRANT]		= -EPERM,
++	[DLM_BADPARAM]			= -EINVAL,
++	[DLM_VALNOTVALID]		= -EINVAL,
++	[DLM_REJECTED]			= -EPERM,
++	[DLM_ABORT]			= -EINVAL,
++	[DLM_CANCEL]			= -DLM_ECANCEL,	/* Successful cancel */
++	[DLM_IVRESHANDLE]		= -EINVAL,
++	[DLM_DEADLOCK]			= -EDEADLK,
++	[DLM_DENIED_NOASTS]		= -EINVAL,
++	[DLM_FORWARD]			= -EINVAL,
++	[DLM_TIMEOUT]			= -ETIMEDOUT,
++	[DLM_IVGROUPID]			= -EINVAL,
++	[DLM_VERS_CONFLICT]		= -EOPNOTSUPP,
++	[DLM_BAD_DEVICE_PATH]		= -ENOENT,
++	[DLM_NO_DEVICE_PERMISSION]	= -EPERM,
++	[DLM_NO_CONTROL_DEVICE]		= -ENOENT,
++	[DLM_RECOVERING]		= -ENOTCONN,
++	[DLM_MIGRATING]			= -ERESTART,
++	[DLM_MAXSTATS]			= -EINVAL,
++};
++
++static int dlm_status_to_errno(enum dlm_status status)
++{
++	BUG_ON(status > (sizeof(status_map) / sizeof(status_map[0])));
++
++	return status_map[status];
++}
++
++static void o2dlm_lock_ast_wrapper(void *astarg)
++{
++	BUG_ON(o2cb_stack.sp_proto == NULL);
++
++	o2cb_stack.sp_proto->lp_lock_ast(astarg);
++}
++
++static void o2dlm_blocking_ast_wrapper(void *astarg, int level)
++{
++	BUG_ON(o2cb_stack.sp_proto == NULL);
++
++	o2cb_stack.sp_proto->lp_blocking_ast(astarg, level);
++}
++
++static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status)
++{
++	int error = dlm_status_to_errno(status);
++
++	BUG_ON(o2cb_stack.sp_proto == NULL);
++
++	/*
++	 * In o2dlm, you can get both the lock_ast() for the lock being
++	 * granted and the unlock_ast() for the CANCEL failing.  A
++	 * successful cancel sends DLM_NORMAL here.  If the
++	 * lock grant happened before the cancel arrived, you get
++	 * DLM_CANCELGRANT.
++	 *
++	 * There's no need for the double-ast.  If we see DLM_CANCELGRANT,
++	 * we just ignore it.  We expect the lock_ast() to handle the
++	 * granted lock.
++	 */
++	if (status == DLM_CANCELGRANT)
++		return;
++
++	o2cb_stack.sp_proto->lp_unlock_ast(astarg, error);
++}
++
++static int o2cb_dlm_lock(struct ocfs2_cluster_connection *conn,
++			 int mode,
++			 union ocfs2_dlm_lksb *lksb,
++			 u32 flags,
++			 void *name,
++			 unsigned int namelen,
++			 void *astarg)
++{
++	enum dlm_status status;
++	int o2dlm_mode = mode_to_o2dlm(mode);
++	int o2dlm_flags = flags_to_o2dlm(flags);
++	int ret;
++
++	status = dlmlock(conn->cc_lockspace, o2dlm_mode, &lksb->lksb_o2dlm,
++			 o2dlm_flags, name, namelen,
++			 o2dlm_lock_ast_wrapper, astarg,
++			 o2dlm_blocking_ast_wrapper);
++	ret = dlm_status_to_errno(status);
++	return ret;
++}
++
++static int o2cb_dlm_unlock(struct ocfs2_cluster_connection *conn,
++			   union ocfs2_dlm_lksb *lksb,
++			   u32 flags,
++			   void *astarg)
++{
++	enum dlm_status status;
++	int o2dlm_flags = flags_to_o2dlm(flags);
++	int ret;
++
++	status = dlmunlock(conn->cc_lockspace, &lksb->lksb_o2dlm,
++			   o2dlm_flags, o2dlm_unlock_ast_wrapper, astarg);
++	ret = dlm_status_to_errno(status);
++	return ret;
++}
++
++static int o2cb_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
++{
++	return dlm_status_to_errno(lksb->lksb_o2dlm.status);
++}
++
++static void *o2cb_dlm_lvb(union ocfs2_dlm_lksb *lksb)
++{
++	return (void *)(lksb->lksb_o2dlm.lvb);
++}
++
++static void o2cb_dump_lksb(union ocfs2_dlm_lksb *lksb)
++{
++	dlm_print_one_lock(lksb->lksb_o2dlm.lockid);
++}
++
++/*
++ * Called from the dlm when it's about to evict a node. This is how the
++ * classic stack signals node death.
++ */
++static void o2dlm_eviction_cb(int node_num, void *data)
++{
++	struct ocfs2_cluster_connection *conn = data;
++
++	mlog(ML_NOTICE, "o2dlm has evicted node %d from group %.*s\n",
++	     node_num, conn->cc_namelen, conn->cc_name);
++
++	conn->cc_recovery_handler(node_num, conn->cc_recovery_data);
++}
++
++static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn)
++{
++	int rc = 0;
++	u32 dlm_key;
++	struct dlm_ctxt *dlm;
++	struct o2dlm_private *priv;
++	struct dlm_protocol_version dlm_version;
++
++	BUG_ON(conn == NULL);
++	BUG_ON(o2cb_stack.sp_proto == NULL);
++
++	/* for now we only have one cluster/node, make sure we see it
++	 * in the heartbeat universe */
++	if (!o2hb_check_local_node_heartbeating()) {
++		rc = -EINVAL;
++		goto out;
++	}
++
++	priv = kzalloc(sizeof(struct o2dlm_private), GFP_KERNEL);
++	if (!priv) {
++		rc = -ENOMEM;
++		goto out_free;
++	}
++
++	/* This just fills the structure in.  It is safe to pass conn. */
++	dlm_setup_eviction_cb(&priv->op_eviction_cb, o2dlm_eviction_cb,
++			      conn);
++
++	conn->cc_private = priv;
++
++	/* used by the dlm code to make message headers unique, each
++	 * node in this domain must agree on this. */
++	dlm_key = crc32_le(0, conn->cc_name, conn->cc_namelen);
++	dlm_version.pv_major = conn->cc_version.pv_major;
++	dlm_version.pv_minor = conn->cc_version.pv_minor;
++
++	dlm = dlm_register_domain(conn->cc_name, dlm_key, &dlm_version);
++	if (IS_ERR(dlm)) {
++		rc = PTR_ERR(dlm);
++		mlog_errno(rc);
++		goto out_free;
++	}
++
++	conn->cc_version.pv_major = dlm_version.pv_major;
++	conn->cc_version.pv_minor = dlm_version.pv_minor;
++	conn->cc_lockspace = dlm;
++
++	dlm_register_eviction_cb(dlm, &priv->op_eviction_cb);
++
++out_free:
++	if (rc && conn->cc_private)
++		kfree(conn->cc_private);
++
++out:
++	return rc;
++}
++
++static int o2cb_cluster_disconnect(struct ocfs2_cluster_connection *conn,
++				   int hangup_pending)
++{
++	struct dlm_ctxt *dlm = conn->cc_lockspace;
++	struct o2dlm_private *priv = conn->cc_private;
++
++	dlm_unregister_eviction_cb(&priv->op_eviction_cb);
++	conn->cc_private = NULL;
++	kfree(priv);
++
++	dlm_unregister_domain(dlm);
++	conn->cc_lockspace = NULL;
++
++	return 0;
++}
++
++static void o2hb_stop(const char *group)
++{
++	int ret;
++	char *argv[5], *envp[3];
++
++	argv[0] = (char *)o2nm_get_hb_ctl_path();
++	argv[1] = "-K";
++	argv[2] = "-u";
++	argv[3] = (char *)group;
++	argv[4] = NULL;
++
++	mlog(0, "Run: %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
++
++	/* minimal command environment taken from cpu_run_sbin_hotplug */
++	envp[0] = "HOME=/";
++	envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
++	envp[2] = NULL;
++
++	ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
++	if (ret < 0)
++		mlog_errno(ret);
++}
++
++/*
++ * Hangup is a hack for tools compatibility.  Older ocfs2-tools software
++ * expects the filesystem to call "ocfs2_hb_ctl" during unmount.  This
++ * happens regardless of whether the DLM got started, so we can't do it
++ * in ocfs2_cluster_disconnect().  We bring the o2hb_stop() function into
++ * the glue and provide a "hangup" API for super.c to call.
++ *
++ * Other stacks will eventually provide a NULL ->hangup() pointer.
++ */
++static void o2cb_cluster_hangup(const char *group, int grouplen)
++{
++	o2hb_stop(group);
++}
++
++static int o2cb_cluster_this_node(unsigned int *node)
++{
++	int node_num;
++
++	node_num = o2nm_this_node();
++	if (node_num == O2NM_INVALID_NODE_NUM)
++		return -ENOENT;
++
++	if (node_num >= O2NM_MAX_NODES)
++		return -EOVERFLOW;
++
++	*node = node_num;
++	return 0;
++}
++
++struct ocfs2_stack_operations o2cb_stack_ops = {
++	.connect	= o2cb_cluster_connect,
++	.disconnect	= o2cb_cluster_disconnect,
++	.hangup		= o2cb_cluster_hangup,
++	.this_node	= o2cb_cluster_this_node,
++	.dlm_lock	= o2cb_dlm_lock,
++	.dlm_unlock	= o2cb_dlm_unlock,
++	.lock_status	= o2cb_dlm_lock_status,
++	.lock_lvb	= o2cb_dlm_lvb,
++	.dump_lksb	= o2cb_dump_lksb,
++};
++
++static struct ocfs2_stack_plugin o2cb_stack = {
++	.sp_name	= "o2cb",
++	.sp_ops		= &o2cb_stack_ops,
++	.sp_owner	= THIS_MODULE,
++};
++
++static int __init o2cb_stack_init(void)
++{
++	return ocfs2_stack_glue_register(&o2cb_stack);
++}
++
++static void __exit o2cb_stack_exit(void)
++{
++	ocfs2_stack_glue_unregister(&o2cb_stack);
++}
++
++MODULE_AUTHOR("Oracle");
++MODULE_DESCRIPTION("ocfs2 driver for the classic o2cb stack");
++MODULE_LICENSE("GPL");
++module_init(o2cb_stack_init);
++module_exit(o2cb_stack_exit);
+diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
+new file mode 100644
+index 0000000..7428663
+--- /dev/null
++++ b/fs/ocfs2/stack_user.c
+@@ -0,0 +1,883 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * stack_user.c
++ *
++ * Code which interfaces ocfs2 with fs/dlm and a userspace stack.
++ *
++ * Copyright (C) 2007 Oracle.  All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public
++ * License as published by the Free Software Foundation, version 2.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/mutex.h>
++#include <linux/reboot.h>
++#include <asm/uaccess.h>
++
++#include "ocfs2.h"  /* For struct ocfs2_lock_res */
++#include "stackglue.h"
++
++
++/*
++ * The control protocol starts with a handshake.  Until the handshake
++ * is complete, the control device will fail all write(2)s.
++ *
++ * The handshake is simple.  First, the client reads until EOF.  Each line
++ * of output is a supported protocol tag.  All protocol tags are a single
++ * character followed by a two hex digit version number.  Currently the
++ * only things supported is T01, for "Text-base version 0x01".  Next, the
++ * client writes the version they would like to use, including the newline.
++ * Thus, the protocol tag is 'T01\n'.  If the version tag written is
++ * unknown, -EINVAL is returned.  Once the negotiation is complete, the
++ * client can start sending messages.
++ *
++ * The T01 protocol has three messages.  First is the "SETN" message.
++ * It has the following syntax:
++ *
++ *  SETN<space><8-char-hex-nodenum><newline>
++ *
++ * This is 14 characters.
++ *
++ * The "SETN" message must be the first message following the protocol.
++ * It tells ocfs2_control the local node number.
++ *
++ * Next comes the "SETV" message.  It has the following syntax:
++ *
++ *  SETV<space><2-char-hex-major><space><2-char-hex-minor><newline>
++ *
++ * This is 11 characters.
++ *
++ * The "SETV" message sets the filesystem locking protocol version as
++ * negotiated by the client.  The client negotiates based on the maximum
++ * version advertised in /sys/fs/ocfs2/max_locking_protocol.  The major
++ * number from the "SETV" message must match
++ * user_stack.sp_proto->lp_max_version.pv_major, and the minor number
++ * must be less than or equal to ...->lp_max_version.pv_minor.
++ *
++ * Once this information has been set, mounts will be allowed.  From this
++ * point on, the "DOWN" message can be sent for node down notification.
++ * It has the following syntax:
++ *
++ *  DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline>
++ *
++ * eg:
++ *
++ *  DOWN 632A924FDD844190BDA93C0DF6B94899 00000001\n
++ *
++ * This is 47 characters.
++ */
++
++/*
++ * Whether or not the client has done the handshake.
++ * For now, we have just one protocol version.
++ */
++#define OCFS2_CONTROL_PROTO			"T01\n"
++#define OCFS2_CONTROL_PROTO_LEN			4
++
++/* Handshake states */
++#define OCFS2_CONTROL_HANDSHAKE_INVALID		(0)
++#define OCFS2_CONTROL_HANDSHAKE_READ		(1)
++#define OCFS2_CONTROL_HANDSHAKE_PROTOCOL	(2)
++#define OCFS2_CONTROL_HANDSHAKE_VALID		(3)
++
++/* Messages */
++#define OCFS2_CONTROL_MESSAGE_OP_LEN		4
++#define OCFS2_CONTROL_MESSAGE_SETNODE_OP	"SETN"
++#define OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN	14
++#define OCFS2_CONTROL_MESSAGE_SETVERSION_OP	"SETV"
++#define OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN	11
++#define OCFS2_CONTROL_MESSAGE_DOWN_OP		"DOWN"
++#define OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN	47
++#define OCFS2_TEXT_UUID_LEN			32
++#define OCFS2_CONTROL_MESSAGE_VERNUM_LEN	2
++#define OCFS2_CONTROL_MESSAGE_NODENUM_LEN	8
++
++/*
++ * ocfs2_live_connection is refcounted because the filesystem and
++ * miscdevice sides can detach in different order.  Let's just be safe.
++ */
++struct ocfs2_live_connection {
++	struct list_head		oc_list;
++	struct ocfs2_cluster_connection	*oc_conn;
++};
++
++struct ocfs2_control_private {
++	struct list_head op_list;
++	int op_state;
++	int op_this_node;
++	struct ocfs2_protocol_version op_proto;
++};
++
++/* SETN<space><8-char-hex-nodenum><newline> */
++struct ocfs2_control_message_setn {
++	char	tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
++	char	space;
++	char	nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
++	char	newline;
++};
++
++/* SETV<space><2-char-hex-major><space><2-char-hex-minor><newline> */
++struct ocfs2_control_message_setv {
++	char	tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
++	char	space1;
++	char	major[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
++	char	space2;
++	char	minor[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
++	char	newline;
++};
++
++/* DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline> */
++struct ocfs2_control_message_down {
++	char	tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
++	char	space1;
++	char	uuid[OCFS2_TEXT_UUID_LEN];
++	char	space2;
++	char	nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
++	char	newline;
++};
++
++union ocfs2_control_message {
++	char					tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
++	struct ocfs2_control_message_setn	u_setn;
++	struct ocfs2_control_message_setv	u_setv;
++	struct ocfs2_control_message_down	u_down;
++};
++
++static struct ocfs2_stack_plugin user_stack;
++
++static atomic_t ocfs2_control_opened;
++static int ocfs2_control_this_node = -1;
++static struct ocfs2_protocol_version running_proto;
++
++static LIST_HEAD(ocfs2_live_connection_list);
++static LIST_HEAD(ocfs2_control_private_list);
++static DEFINE_MUTEX(ocfs2_control_lock);
++
++static inline void ocfs2_control_set_handshake_state(struct file *file,
++						     int state)
++{
++	struct ocfs2_control_private *p = file->private_data;
++	p->op_state = state;
++}
++
++static inline int ocfs2_control_get_handshake_state(struct file *file)
++{
++	struct ocfs2_control_private *p = file->private_data;
++	return p->op_state;
++}
++
++static struct ocfs2_live_connection *ocfs2_connection_find(const char *name)
++{
++	size_t len = strlen(name);
++	struct ocfs2_live_connection *c;
++
++	BUG_ON(!mutex_is_locked(&ocfs2_control_lock));
++
++	list_for_each_entry(c, &ocfs2_live_connection_list, oc_list) {
++		if ((c->oc_conn->cc_namelen == len) &&
++		    !strncmp(c->oc_conn->cc_name, name, len))
++			return c;
++	}
++
++	return c;
++}
++
++/*
++ * ocfs2_live_connection structures are created underneath the ocfs2
++ * mount path.  Since the VFS prevents multiple calls to
++ * fill_super(), we can't get dupes here.
++ */
++static int ocfs2_live_connection_new(struct ocfs2_cluster_connection *conn,
++				     struct ocfs2_live_connection **c_ret)
++{
++	int rc = 0;
++	struct ocfs2_live_connection *c;
++
++	c = kzalloc(sizeof(struct ocfs2_live_connection), GFP_KERNEL);
++	if (!c)
++		return -ENOMEM;
++
++	mutex_lock(&ocfs2_control_lock);
++	c->oc_conn = conn;
++
++	if (atomic_read(&ocfs2_control_opened))
++		list_add(&c->oc_list, &ocfs2_live_connection_list);
++	else {
++		printk(KERN_ERR
++		       "ocfs2: Userspace control daemon is not present\n");
++		rc = -ESRCH;
++	}
++
++	mutex_unlock(&ocfs2_control_lock);
++
++	if (!rc)
++		*c_ret = c;
++	else
++		kfree(c);
++
++	return rc;
++}
++
++/*
++ * This function disconnects the cluster connection from ocfs2_control.
++ * Afterwards, userspace can't affect the cluster connection.
++ */
++static void ocfs2_live_connection_drop(struct ocfs2_live_connection *c)
++{
++	mutex_lock(&ocfs2_control_lock);
++	list_del_init(&c->oc_list);
++	c->oc_conn = NULL;
++	mutex_unlock(&ocfs2_control_lock);
++
++	kfree(c);
++}
++
++static int ocfs2_control_cfu(void *target, size_t target_len,
++			     const char __user *buf, size_t count)
++{
++	/* The T01 expects write(2) calls to have exactly one command */
++	if ((count != target_len) ||
++	    (count > sizeof(union ocfs2_control_message)))
++		return -EINVAL;
++
++	if (copy_from_user(target, buf, target_len))
++		return -EFAULT;
++
++	return 0;
++}
++
++static ssize_t ocfs2_control_validate_protocol(struct file *file,
++					       const char __user *buf,
++					       size_t count)
++{
++	ssize_t ret;
++	char kbuf[OCFS2_CONTROL_PROTO_LEN];
++
++	ret = ocfs2_control_cfu(kbuf, OCFS2_CONTROL_PROTO_LEN,
++				buf, count);
++	if (ret)
++		return ret;
++
++	if (strncmp(kbuf, OCFS2_CONTROL_PROTO, OCFS2_CONTROL_PROTO_LEN))
++		return -EINVAL;
++
++	ocfs2_control_set_handshake_state(file,
++					  OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
++
++	return count;
++}
++
++static void ocfs2_control_send_down(const char *uuid,
++				    int nodenum)
++{
++	struct ocfs2_live_connection *c;
++
++	mutex_lock(&ocfs2_control_lock);
++
++	c = ocfs2_connection_find(uuid);
++	if (c) {
++		BUG_ON(c->oc_conn == NULL);
++		c->oc_conn->cc_recovery_handler(nodenum,
++						c->oc_conn->cc_recovery_data);
++	}
++
++	mutex_unlock(&ocfs2_control_lock);
++}
++
++/*
++ * Called whenever configuration elements are sent to /dev/ocfs2_control.
++ * If all configuration elements are present, try to set the global
++ * values.  If there is a problem, return an error.  Skip any missing
++ * elements, and only bump ocfs2_control_opened when we have all elements
++ * and are successful.
++ */
++static int ocfs2_control_install_private(struct file *file)
++{
++	int rc = 0;
++	int set_p = 1;
++	struct ocfs2_control_private *p = file->private_data;
++
++	BUG_ON(p->op_state != OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
++
++	mutex_lock(&ocfs2_control_lock);
++
++	if (p->op_this_node < 0) {
++		set_p = 0;
++	} else if ((ocfs2_control_this_node >= 0) &&
++		   (ocfs2_control_this_node != p->op_this_node)) {
++		rc = -EINVAL;
++		goto out_unlock;
++	}
++
++	if (!p->op_proto.pv_major) {
++		set_p = 0;
++	} else if (!list_empty(&ocfs2_live_connection_list) &&
++		   ((running_proto.pv_major != p->op_proto.pv_major) ||
++		    (running_proto.pv_minor != p->op_proto.pv_minor))) {
++		rc = -EINVAL;
++		goto out_unlock;
++	}
++
++	if (set_p) {
++		ocfs2_control_this_node = p->op_this_node;
++		running_proto.pv_major = p->op_proto.pv_major;
++		running_proto.pv_minor = p->op_proto.pv_minor;
++	}
++
++out_unlock:
++	mutex_unlock(&ocfs2_control_lock);
++
++	if (!rc && set_p) {
++		/* We set the global values successfully */
++		atomic_inc(&ocfs2_control_opened);
++		ocfs2_control_set_handshake_state(file,
++					OCFS2_CONTROL_HANDSHAKE_VALID);
++	}
++
++	return rc;
++}
++
++static int ocfs2_control_get_this_node(void)
++{
++	int rc;
++
++	mutex_lock(&ocfs2_control_lock);
++	if (ocfs2_control_this_node < 0)
++		rc = -EINVAL;
++	else
++		rc = ocfs2_control_this_node;
++	mutex_unlock(&ocfs2_control_lock);
++
++	return rc;
++}
++
++static int ocfs2_control_do_setnode_msg(struct file *file,
++					struct ocfs2_control_message_setn *msg)
++{
++	long nodenum;
++	char *ptr = NULL;
++	struct ocfs2_control_private *p = file->private_data;
++
++	if (ocfs2_control_get_handshake_state(file) !=
++	    OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
++		return -EINVAL;
++
++	if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
++		    OCFS2_CONTROL_MESSAGE_OP_LEN))
++		return -EINVAL;
++
++	if ((msg->space != ' ') || (msg->newline != '\n'))
++		return -EINVAL;
++	msg->space = msg->newline = '\0';
++
++	nodenum = simple_strtol(msg->nodestr, &ptr, 16);
++	if (!ptr || *ptr)
++		return -EINVAL;
++
++	if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
++	    (nodenum > INT_MAX) || (nodenum < 0))
++		return -ERANGE;
++	p->op_this_node = nodenum;
++
++	return ocfs2_control_install_private(file);
++}
++
++static int ocfs2_control_do_setversion_msg(struct file *file,
++					   struct ocfs2_control_message_setv *msg)
++ {
++	long major, minor;
++	char *ptr = NULL;
++	struct ocfs2_control_private *p = file->private_data;
++	struct ocfs2_protocol_version *max =
++		&user_stack.sp_proto->lp_max_version;
++
++	if (ocfs2_control_get_handshake_state(file) !=
++	    OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
++		return -EINVAL;
++
++	if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
++		    OCFS2_CONTROL_MESSAGE_OP_LEN))
++		return -EINVAL;
++
++	if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
++	    (msg->newline != '\n'))
++		return -EINVAL;
++	msg->space1 = msg->space2 = msg->newline = '\0';
++
++	major = simple_strtol(msg->major, &ptr, 16);
++	if (!ptr || *ptr)
++		return -EINVAL;
++	minor = simple_strtol(msg->minor, &ptr, 16);
++	if (!ptr || *ptr)
++		return -EINVAL;
++
++	/*
++	 * The major must be between 1 and 255, inclusive.  The minor
++	 * must be between 0 and 255, inclusive.  The version passed in
++	 * must be within the maximum version supported by the filesystem.
++	 */
++	if ((major == LONG_MIN) || (major == LONG_MAX) ||
++	    (major > (u8)-1) || (major < 1))
++		return -ERANGE;
++	if ((minor == LONG_MIN) || (minor == LONG_MAX) ||
++	    (minor > (u8)-1) || (minor < 0))
++		return -ERANGE;
++	if ((major != max->pv_major) ||
++	    (minor > max->pv_minor))
++		return -EINVAL;
++
++	p->op_proto.pv_major = major;
++	p->op_proto.pv_minor = minor;
++
++	return ocfs2_control_install_private(file);
++}
++
++static int ocfs2_control_do_down_msg(struct file *file,
++				     struct ocfs2_control_message_down *msg)
++{
++	long nodenum;
++	char *p = NULL;
++
++	if (ocfs2_control_get_handshake_state(file) !=
++	    OCFS2_CONTROL_HANDSHAKE_VALID)
++		return -EINVAL;
++
++	if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
++		    OCFS2_CONTROL_MESSAGE_OP_LEN))
++		return -EINVAL;
++
++	if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
++	    (msg->newline != '\n'))
++		return -EINVAL;
++	msg->space1 = msg->space2 = msg->newline = '\0';
++
++	nodenum = simple_strtol(msg->nodestr, &p, 16);
++	if (!p || *p)
++		return -EINVAL;
++
++	if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
++	    (nodenum > INT_MAX) || (nodenum < 0))
++		return -ERANGE;
++
++	ocfs2_control_send_down(msg->uuid, nodenum);
++
++	return 0;
++}
++
++static ssize_t ocfs2_control_message(struct file *file,
++				     const char __user *buf,
++				     size_t count)
++{
++	ssize_t ret;
++	union ocfs2_control_message msg;
++
++	/* Try to catch padding issues */
++	WARN_ON(offsetof(struct ocfs2_control_message_down, uuid) !=
++		(sizeof(msg.u_down.tag) + sizeof(msg.u_down.space1)));
++
++	memset(&msg, 0, sizeof(union ocfs2_control_message));
++	ret = ocfs2_control_cfu(&msg, count, buf, count);
++	if (ret)
++		goto out;
++
++	if ((count == OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN) &&
++	    !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
++		     OCFS2_CONTROL_MESSAGE_OP_LEN))
++		ret = ocfs2_control_do_setnode_msg(file, &msg.u_setn);
++	else if ((count == OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN) &&
++		 !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
++			  OCFS2_CONTROL_MESSAGE_OP_LEN))
++		ret = ocfs2_control_do_setversion_msg(file, &msg.u_setv);
++	else if ((count == OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN) &&
++		 !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
++			  OCFS2_CONTROL_MESSAGE_OP_LEN))
++		ret = ocfs2_control_do_down_msg(file, &msg.u_down);
++	else
++		ret = -EINVAL;
++
++out:
++	return ret ? ret : count;
++}
++
++static ssize_t ocfs2_control_write(struct file *file,
++				   const char __user *buf,
++				   size_t count,
++				   loff_t *ppos)
++{
++	ssize_t ret;
++
++	switch (ocfs2_control_get_handshake_state(file)) {
++		case OCFS2_CONTROL_HANDSHAKE_INVALID:
++			ret = -EINVAL;
++			break;
++
++		case OCFS2_CONTROL_HANDSHAKE_READ:
++			ret = ocfs2_control_validate_protocol(file, buf,
++							      count);
++			break;
++
++		case OCFS2_CONTROL_HANDSHAKE_PROTOCOL:
++		case OCFS2_CONTROL_HANDSHAKE_VALID:
++			ret = ocfs2_control_message(file, buf, count);
++			break;
++
++		default:
++			BUG();
++			ret = -EIO;
++			break;
++	}
++
++	return ret;
++}
++
++/*
++ * This is a naive version.  If we ever have a new protocol, we'll expand
++ * it.  Probably using seq_file.
++ */
++static ssize_t ocfs2_control_read(struct file *file,
++				  char __user *buf,
++				  size_t count,
++				  loff_t *ppos)
++{
++	char *proto_string = OCFS2_CONTROL_PROTO;
++	size_t to_write = 0;
++
++	if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
++		return 0;
++
++	to_write = OCFS2_CONTROL_PROTO_LEN - *ppos;
++	if (to_write > count)
++		to_write = count;
++	if (copy_to_user(buf, proto_string + *ppos, to_write))
++		return -EFAULT;
++
++	*ppos += to_write;
++
++	/* Have we read the whole protocol list? */
++	if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
++		ocfs2_control_set_handshake_state(file,
++						  OCFS2_CONTROL_HANDSHAKE_READ);
++
++	return to_write;
++}
++
++static int ocfs2_control_release(struct inode *inode, struct file *file)
++{
++	struct ocfs2_control_private *p = file->private_data;
++
++	mutex_lock(&ocfs2_control_lock);
++
++	if (ocfs2_control_get_handshake_state(file) !=
++	    OCFS2_CONTROL_HANDSHAKE_VALID)
++		goto out;
++
++	if (atomic_dec_and_test(&ocfs2_control_opened)) {
++		if (!list_empty(&ocfs2_live_connection_list)) {
++			/* XXX: Do bad things! */
++			printk(KERN_ERR
++			       "ocfs2: Unexpected release of ocfs2_control!\n"
++			       "       Loss of cluster connection requires "
++			       "an emergency restart!\n");
++			emergency_restart();
++		}
++		/*
++		 * Last valid close clears the node number and resets
++		 * the locking protocol version
++		 */
++		ocfs2_control_this_node = -1;
++		running_proto.pv_major = 0;
++		running_proto.pv_major = 0;
++	}
++
++out:
++	list_del_init(&p->op_list);
++	file->private_data = NULL;
++
++	mutex_unlock(&ocfs2_control_lock);
++
++	kfree(p);
++
++	return 0;
++}
++
++static int ocfs2_control_open(struct inode *inode, struct file *file)
++{
++	struct ocfs2_control_private *p;
++
++	p = kzalloc(sizeof(struct ocfs2_control_private), GFP_KERNEL);
++	if (!p)
++		return -ENOMEM;
++	p->op_this_node = -1;
++
++	mutex_lock(&ocfs2_control_lock);
++	file->private_data = p;
++	list_add(&p->op_list, &ocfs2_control_private_list);
++	mutex_unlock(&ocfs2_control_lock);
++
++	return 0;
++}
++
++static const struct file_operations ocfs2_control_fops = {
++	.open    = ocfs2_control_open,
++	.release = ocfs2_control_release,
++	.read    = ocfs2_control_read,
++	.write   = ocfs2_control_write,
++	.owner   = THIS_MODULE,
++};
++
++struct miscdevice ocfs2_control_device = {
++	.minor		= MISC_DYNAMIC_MINOR,
++	.name		= "ocfs2_control",
++	.fops		= &ocfs2_control_fops,
++};
++
++static int ocfs2_control_init(void)
++{
++	int rc;
++
++	atomic_set(&ocfs2_control_opened, 0);
++
++	rc = misc_register(&ocfs2_control_device);
++	if (rc)
++		printk(KERN_ERR
++		       "ocfs2: Unable to register ocfs2_control device "
++		       "(errno %d)\n",
++		       -rc);
++
++	return rc;
++}
++
++static void ocfs2_control_exit(void)
++{
++	int rc;
++
++	rc = misc_deregister(&ocfs2_control_device);
++	if (rc)
++		printk(KERN_ERR
++		       "ocfs2: Unable to deregister ocfs2_control device "
++		       "(errno %d)\n",
++		       -rc);
++}
++
++static struct dlm_lksb *fsdlm_astarg_to_lksb(void *astarg)
++{
++	struct ocfs2_lock_res *res = astarg;
++	return &res->l_lksb.lksb_fsdlm;
++}
++
++static void fsdlm_lock_ast_wrapper(void *astarg)
++{
++	struct dlm_lksb *lksb = fsdlm_astarg_to_lksb(astarg);
++	int status = lksb->sb_status;
++
++	BUG_ON(user_stack.sp_proto == NULL);
++
++	/*
++	 * For now we're punting on the issue of other non-standard errors
++	 * where we can't tell if the unlock_ast or lock_ast should be called.
++	 * The main "other error" that's possible is EINVAL which means the
++	 * function was called with invalid args, which shouldn't be possible
++	 * since the caller here is under our control.  Other non-standard
++	 * errors probably fall into the same category, or otherwise are fatal
++	 * which means we can't carry on anyway.
++	 */
++
++	if (status == -DLM_EUNLOCK || status == -DLM_ECANCEL)
++		user_stack.sp_proto->lp_unlock_ast(astarg, 0);
++	else
++		user_stack.sp_proto->lp_lock_ast(astarg);
++}
++
++static void fsdlm_blocking_ast_wrapper(void *astarg, int level)
++{
++	BUG_ON(user_stack.sp_proto == NULL);
++
++	user_stack.sp_proto->lp_blocking_ast(astarg, level);
++}
++
++static int user_dlm_lock(struct ocfs2_cluster_connection *conn,
++			 int mode,
++			 union ocfs2_dlm_lksb *lksb,
++			 u32 flags,
++			 void *name,
++			 unsigned int namelen,
++			 void *astarg)
++{
++	int ret;
++
++	if (!lksb->lksb_fsdlm.sb_lvbptr)
++		lksb->lksb_fsdlm.sb_lvbptr = (char *)lksb +
++					     sizeof(struct dlm_lksb);
++
++	ret = dlm_lock(conn->cc_lockspace, mode, &lksb->lksb_fsdlm,
++		       flags|DLM_LKF_NODLCKWT, name, namelen, 0,
++		       fsdlm_lock_ast_wrapper, astarg,
++		       fsdlm_blocking_ast_wrapper);
++	return ret;
++}
++
++static int user_dlm_unlock(struct ocfs2_cluster_connection *conn,
++			   union ocfs2_dlm_lksb *lksb,
++			   u32 flags,
++			   void *astarg)
++{
++	int ret;
++
++	ret = dlm_unlock(conn->cc_lockspace, lksb->lksb_fsdlm.sb_lkid,
++			 flags, &lksb->lksb_fsdlm, astarg);
++	return ret;
++}
++
++static int user_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
++{
++	return lksb->lksb_fsdlm.sb_status;
++}
++
++static void *user_dlm_lvb(union ocfs2_dlm_lksb *lksb)
++{
++	return (void *)(lksb->lksb_fsdlm.sb_lvbptr);
++}
++
++static void user_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
++{
++}
++
++/*
++ * Compare a requested locking protocol version against the current one.
++ *
++ * If the major numbers are different, they are incompatible.
++ * If the current minor is greater than the request, they are incompatible.
++ * If the current minor is less than or equal to the request, they are
++ * compatible, and the requester should run at the current minor version.
++ */
++static int fs_protocol_compare(struct ocfs2_protocol_version *existing,
++			       struct ocfs2_protocol_version *request)
++{
++	if (existing->pv_major != request->pv_major)
++		return 1;
++
++	if (existing->pv_minor > request->pv_minor)
++		return 1;
++
++	if (existing->pv_minor < request->pv_minor)
++		request->pv_minor = existing->pv_minor;
++
++	return 0;
++}
++
++static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
++{
++	dlm_lockspace_t *fsdlm;
++	struct ocfs2_live_connection *control;
++	int rc = 0;
++
++	BUG_ON(conn == NULL);
++
++	rc = ocfs2_live_connection_new(conn, &control);
++	if (rc)
++		goto out;
++
++	/*
++	 * running_proto must have been set before we allowed any mounts
++	 * to proceed.
++	 */
++	if (fs_protocol_compare(&running_proto, &conn->cc_version)) {
++		printk(KERN_ERR
++		       "Unable to mount with fs locking protocol version "
++		       "%u.%u because the userspace control daemon has "
++		       "negotiated %u.%u\n",
++		       conn->cc_version.pv_major, conn->cc_version.pv_minor,
++		       running_proto.pv_major, running_proto.pv_minor);
++		rc = -EPROTO;
++		ocfs2_live_connection_drop(control);
++		goto out;
++	}
++
++	rc = dlm_new_lockspace(conn->cc_name, strlen(conn->cc_name),
++			       &fsdlm, DLM_LSFL_FS, DLM_LVB_LEN);
++	if (rc) {
++		ocfs2_live_connection_drop(control);
++		goto out;
++	}
++
++	conn->cc_private = control;
++	conn->cc_lockspace = fsdlm;
++out:
++	return rc;
++}
++
++static int user_cluster_disconnect(struct ocfs2_cluster_connection *conn,
++				   int hangup_pending)
++{
++	dlm_release_lockspace(conn->cc_lockspace, 2);
++	conn->cc_lockspace = NULL;
++	ocfs2_live_connection_drop(conn->cc_private);
++	conn->cc_private = NULL;
++	return 0;
++}
++
++static int user_cluster_this_node(unsigned int *this_node)
++{
++	int rc;
++
++	rc = ocfs2_control_get_this_node();
++	if (rc < 0)
++		return rc;
++
++	*this_node = rc;
++	return 0;
++}
++
++static struct ocfs2_stack_operations user_stack_ops = {
++	.connect	= user_cluster_connect,
++	.disconnect	= user_cluster_disconnect,
++	.this_node	= user_cluster_this_node,
++	.dlm_lock	= user_dlm_lock,
++	.dlm_unlock	= user_dlm_unlock,
++	.lock_status	= user_dlm_lock_status,
++	.lock_lvb	= user_dlm_lvb,
++	.dump_lksb	= user_dlm_dump_lksb,
++};
++
++static struct ocfs2_stack_plugin user_stack = {
++	.sp_name	= "user",
++	.sp_ops		= &user_stack_ops,
++	.sp_owner	= THIS_MODULE,
++};
++
++
++static int __init user_stack_init(void)
++{
++	int rc;
++
++	rc = ocfs2_control_init();
++	if (!rc) {
++		rc = ocfs2_stack_glue_register(&user_stack);
++		if (rc)
++			ocfs2_control_exit();
++	}
++
++	return rc;
++}
++
++static void __exit user_stack_exit(void)
++{
++	ocfs2_stack_glue_unregister(&user_stack);
++	ocfs2_control_exit();
++}
++
++MODULE_AUTHOR("Oracle");
++MODULE_DESCRIPTION("ocfs2 driver for userspace cluster stacks");
++MODULE_LICENSE("GPL");
++module_init(user_stack_init);
++module_exit(user_stack_exit);
+diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
+new file mode 100644
+index 0000000..119f60c
+--- /dev/null
++++ b/fs/ocfs2/stackglue.c
+@@ -0,0 +1,568 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * stackglue.c
++ *
++ * Code which implements an OCFS2 specific interface to underlying
++ * cluster stacks.
++ *
++ * Copyright (C) 2007 Oracle.  All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public
++ * License as published by the Free Software Foundation, version 2.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/kmod.h>
++#include <linux/fs.h>
++#include <linux/kobject.h>
++#include <linux/sysfs.h>
++
++#include "ocfs2_fs.h"
++
++#include "stackglue.h"
++
++#define OCFS2_STACK_PLUGIN_O2CB		"o2cb"
++#define OCFS2_STACK_PLUGIN_USER		"user"
++
++static struct ocfs2_locking_protocol *lproto;
++static DEFINE_SPINLOCK(ocfs2_stack_lock);
++static LIST_HEAD(ocfs2_stack_list);
++static char cluster_stack_name[OCFS2_STACK_LABEL_LEN + 1];
++
++/*
++ * The stack currently in use.  If not null, active_stack->sp_count > 0,
++ * the module is pinned, and the locking protocol cannot be changed.
++ */
++static struct ocfs2_stack_plugin *active_stack;
++
++static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name)
++{
++	struct ocfs2_stack_plugin *p;
++
++	assert_spin_locked(&ocfs2_stack_lock);
++
++	list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
++		if (!strcmp(p->sp_name, name))
++			return p;
++	}
++
++	return NULL;
++}
++
++static int ocfs2_stack_driver_request(const char *stack_name,
++				      const char *plugin_name)
++{
++	int rc;
++	struct ocfs2_stack_plugin *p;
++
++	spin_lock(&ocfs2_stack_lock);
++
++	/*
++	 * If the stack passed by the filesystem isn't the selected one,
++	 * we can't continue.
++	 */
++	if (strcmp(stack_name, cluster_stack_name)) {
++		rc = -EBUSY;
++		goto out;
++	}
++
++	if (active_stack) {
++		/*
++		 * If the active stack isn't the one we want, it cannot
++		 * be selected right now.
++		 */
++		if (!strcmp(active_stack->sp_name, plugin_name))
++			rc = 0;
++		else
++			rc = -EBUSY;
++		goto out;
++	}
++
++	p = ocfs2_stack_lookup(plugin_name);
++	if (!p || !try_module_get(p->sp_owner)) {
++		rc = -ENOENT;
++		goto out;
++	}
++
++	/* Ok, the stack is pinned */
++	p->sp_count++;
++	active_stack = p;
++
++	rc = 0;
++
++out:
++	spin_unlock(&ocfs2_stack_lock);
++	return rc;
++}
++
++/*
++ * This function looks up the appropriate stack and makes it active.  If
++ * there is no stack, it tries to load it.  It will fail if the stack still
++ * cannot be found.  It will also fail if a different stack is in use.
++ */
++static int ocfs2_stack_driver_get(const char *stack_name)
++{
++	int rc;
++	char *plugin_name = OCFS2_STACK_PLUGIN_O2CB;
++
++	/*
++	 * Classic stack does not pass in a stack name.  This is
++	 * compatible with older tools as well.
++	 */
++	if (!stack_name || !*stack_name)
++		stack_name = OCFS2_STACK_PLUGIN_O2CB;
++
++	if (strlen(stack_name) != OCFS2_STACK_LABEL_LEN) {
++		printk(KERN_ERR
++		       "ocfs2 passed an invalid cluster stack label: \"%s\"\n",
++		       stack_name);
++		return -EINVAL;
++	}
++
++	/* Anything that isn't the classic stack is a user stack */
++	if (strcmp(stack_name, OCFS2_STACK_PLUGIN_O2CB))
++		plugin_name = OCFS2_STACK_PLUGIN_USER;
++
++	rc = ocfs2_stack_driver_request(stack_name, plugin_name);
++	if (rc == -ENOENT) {
++		request_module("ocfs2_stack_%s", plugin_name);
++		rc = ocfs2_stack_driver_request(stack_name, plugin_name);
++	}
++
++	if (rc == -ENOENT) {
++		printk(KERN_ERR
++		       "ocfs2: Cluster stack driver \"%s\" cannot be found\n",
++		       plugin_name);
++	} else if (rc == -EBUSY) {
++		printk(KERN_ERR
++		       "ocfs2: A different cluster stack is in use\n");
++	}
++
++	return rc;
++}
++
++static void ocfs2_stack_driver_put(void)
++{
++	spin_lock(&ocfs2_stack_lock);
++	BUG_ON(active_stack == NULL);
++	BUG_ON(active_stack->sp_count == 0);
++
++	active_stack->sp_count--;
++	if (!active_stack->sp_count) {
++		module_put(active_stack->sp_owner);
++		active_stack = NULL;
++	}
++	spin_unlock(&ocfs2_stack_lock);
++}
++
++int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin)
++{
++	int rc;
++
++	spin_lock(&ocfs2_stack_lock);
++	if (!ocfs2_stack_lookup(plugin->sp_name)) {
++		plugin->sp_count = 0;
++		plugin->sp_proto = lproto;
++		list_add(&plugin->sp_list, &ocfs2_stack_list);
++		printk(KERN_INFO "ocfs2: Registered cluster interface %s\n",
++		       plugin->sp_name);
++		rc = 0;
++	} else {
++		printk(KERN_ERR "ocfs2: Stack \"%s\" already registered\n",
++		       plugin->sp_name);
++		rc = -EEXIST;
++	}
++	spin_unlock(&ocfs2_stack_lock);
++
++	return rc;
++}
++EXPORT_SYMBOL_GPL(ocfs2_stack_glue_register);
++
++void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin)
++{
++	struct ocfs2_stack_plugin *p;
++
++	spin_lock(&ocfs2_stack_lock);
++	p = ocfs2_stack_lookup(plugin->sp_name);
++	if (p) {
++		BUG_ON(p != plugin);
++		BUG_ON(plugin == active_stack);
++		BUG_ON(plugin->sp_count != 0);
++		list_del_init(&plugin->sp_list);
++		printk(KERN_INFO "ocfs2: Unregistered cluster interface %s\n",
++		       plugin->sp_name);
++	} else {
++		printk(KERN_ERR "Stack \"%s\" is not registered\n",
++		       plugin->sp_name);
++	}
++	spin_unlock(&ocfs2_stack_lock);
++}
++EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister);
++
++void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto)
++{
++	struct ocfs2_stack_plugin *p;
++
++	BUG_ON(proto == NULL);
++
++	spin_lock(&ocfs2_stack_lock);
++	BUG_ON(active_stack != NULL);
++
++	lproto = proto;
++	list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
++		p->sp_proto = lproto;
++	}
++
++	spin_unlock(&ocfs2_stack_lock);
++}
++EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_locking_protocol);
++
++
++/*
++ * The ocfs2_dlm_lock() and ocfs2_dlm_unlock() functions take
++ * "struct ocfs2_lock_res *astarg" instead of "void *astarg" because the
++ * underlying stack plugins need to pilfer the lksb off of the lock_res.
++ * If some other structure needs to be passed as an astarg, the plugins
++ * will need to be given a different avenue to the lksb.
++ */
++int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
++		   int mode,
++		   union ocfs2_dlm_lksb *lksb,
++		   u32 flags,
++		   void *name,
++		   unsigned int namelen,
++		   struct ocfs2_lock_res *astarg)
++{
++	BUG_ON(lproto == NULL);
++
++	return active_stack->sp_ops->dlm_lock(conn, mode, lksb, flags,
++					      name, namelen, astarg);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_lock);
++
++int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
++		     union ocfs2_dlm_lksb *lksb,
++		     u32 flags,
++		     struct ocfs2_lock_res *astarg)
++{
++	BUG_ON(lproto == NULL);
++
++	return active_stack->sp_ops->dlm_unlock(conn, lksb, flags, astarg);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock);
++
++int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
++{
++	return active_stack->sp_ops->lock_status(lksb);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status);
++
++/*
++ * Why don't we cast to ocfs2_meta_lvb?  The "clean" answer is that we
++ * don't cast at the glue level.  The real answer is that the header
++ * ordering is nigh impossible.
++ */
++void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb)
++{
++	return active_stack->sp_ops->lock_lvb(lksb);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb);
++
++void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
++{
++	active_stack->sp_ops->dump_lksb(lksb);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb);
++
++int ocfs2_cluster_connect(const char *stack_name,
++			  const char *group,
++			  int grouplen,
++			  void (*recovery_handler)(int node_num,
++						   void *recovery_data),
++			  void *recovery_data,
++			  struct ocfs2_cluster_connection **conn)
++{
++	int rc = 0;
++	struct ocfs2_cluster_connection *new_conn;
++
++	BUG_ON(group == NULL);
++	BUG_ON(conn == NULL);
++	BUG_ON(recovery_handler == NULL);
++
++	if (grouplen > GROUP_NAME_MAX) {
++		rc = -EINVAL;
++		goto out;
++	}
++
++	new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection),
++			   GFP_KERNEL);
++	if (!new_conn) {
++		rc = -ENOMEM;
++		goto out;
++	}
++
++	memcpy(new_conn->cc_name, group, grouplen);
++	new_conn->cc_namelen = grouplen;
++	new_conn->cc_recovery_handler = recovery_handler;
++	new_conn->cc_recovery_data = recovery_data;
++
++	/* Start the new connection at our maximum compatibility level */
++	new_conn->cc_version = lproto->lp_max_version;
++
++	/* This will pin the stack driver if successful */
++	rc = ocfs2_stack_driver_get(stack_name);
++	if (rc)
++		goto out_free;
++
++	rc = active_stack->sp_ops->connect(new_conn);
++	if (rc) {
++		ocfs2_stack_driver_put();
++		goto out_free;
++	}
++
++	*conn = new_conn;
++
++out_free:
++	if (rc)
++		kfree(new_conn);
++
++out:
++	return rc;
++}
++EXPORT_SYMBOL_GPL(ocfs2_cluster_connect);
++
++/* If hangup_pending is 0, the stack driver will be dropped */
++int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
++			     int hangup_pending)
++{
++	int ret;
++
++	BUG_ON(conn == NULL);
++
++	ret = active_stack->sp_ops->disconnect(conn, hangup_pending);
++
++	/* XXX Should we free it anyway? */
++	if (!ret) {
++		kfree(conn);
++		if (!hangup_pending)
++			ocfs2_stack_driver_put();
++	}
++
++	return ret;
++}
++EXPORT_SYMBOL_GPL(ocfs2_cluster_disconnect);
++
++void ocfs2_cluster_hangup(const char *group, int grouplen)
++{
++	BUG_ON(group == NULL);
++	BUG_ON(group[grouplen] != '\0');
++
++	if (active_stack->sp_ops->hangup)
++		active_stack->sp_ops->hangup(group, grouplen);
++
++	/* cluster_disconnect() was called with hangup_pending==1 */
++	ocfs2_stack_driver_put();
++}
++EXPORT_SYMBOL_GPL(ocfs2_cluster_hangup);
++
++int ocfs2_cluster_this_node(unsigned int *node)
++{
++	return active_stack->sp_ops->this_node(node);
++}
++EXPORT_SYMBOL_GPL(ocfs2_cluster_this_node);
++
++
++/*
++ * Sysfs bits
++ */
++
++static ssize_t ocfs2_max_locking_protocol_show(struct kobject *kobj,
++					       struct kobj_attribute *attr,
++					       char *buf)
++{
++	ssize_t ret = 0;
++
++	spin_lock(&ocfs2_stack_lock);
++	if (lproto)
++		ret = snprintf(buf, PAGE_SIZE, "%u.%u\n",
++			       lproto->lp_max_version.pv_major,
++			       lproto->lp_max_version.pv_minor);
++	spin_unlock(&ocfs2_stack_lock);
++
++	return ret;
++}
++
++static struct kobj_attribute ocfs2_attr_max_locking_protocol =
++	__ATTR(max_locking_protocol, S_IFREG | S_IRUGO,
++	       ocfs2_max_locking_protocol_show, NULL);
++
++static ssize_t ocfs2_loaded_cluster_plugins_show(struct kobject *kobj,
++						 struct kobj_attribute *attr,
++						 char *buf)
++{
++	ssize_t ret = 0, total = 0, remain = PAGE_SIZE;
++	struct ocfs2_stack_plugin *p;
++
++	spin_lock(&ocfs2_stack_lock);
++	list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
++		ret = snprintf(buf, remain, "%s\n",
++			       p->sp_name);
++		if (ret < 0) {
++			total = ret;
++			break;
++		}
++		if (ret == remain) {
++			/* snprintf() didn't fit */
++			total = -E2BIG;
++			break;
++		}
++		total += ret;
++		remain -= ret;
++	}
++	spin_unlock(&ocfs2_stack_lock);
++
++	return total;
++}
++
++static struct kobj_attribute ocfs2_attr_loaded_cluster_plugins =
++	__ATTR(loaded_cluster_plugins, S_IFREG | S_IRUGO,
++	       ocfs2_loaded_cluster_plugins_show, NULL);
++
++static ssize_t ocfs2_active_cluster_plugin_show(struct kobject *kobj,
++						struct kobj_attribute *attr,
++						char *buf)
++{
++	ssize_t ret = 0;
++
++	spin_lock(&ocfs2_stack_lock);
++	if (active_stack) {
++		ret = snprintf(buf, PAGE_SIZE, "%s\n",
++			       active_stack->sp_name);
++		if (ret == PAGE_SIZE)
++			ret = -E2BIG;
++	}
++	spin_unlock(&ocfs2_stack_lock);
++
++	return ret;
++}
++
++static struct kobj_attribute ocfs2_attr_active_cluster_plugin =
++	__ATTR(active_cluster_plugin, S_IFREG | S_IRUGO,
++	       ocfs2_active_cluster_plugin_show, NULL);
++
++static ssize_t ocfs2_cluster_stack_show(struct kobject *kobj,
++					struct kobj_attribute *attr,
++					char *buf)
++{
++	ssize_t ret;
++	spin_lock(&ocfs2_stack_lock);
++	ret = snprintf(buf, PAGE_SIZE, "%s\n", cluster_stack_name);
++	spin_unlock(&ocfs2_stack_lock);
++
++	return ret;
++}
++
++static ssize_t ocfs2_cluster_stack_store(struct kobject *kobj,
++					 struct kobj_attribute *attr,
++					 const char *buf, size_t count)
++{
++	size_t len = count;
++	ssize_t ret;
++
++	if (len == 0)
++		return len;
++
++	if (buf[len - 1] == '\n')
++		len--;
++
++	if ((len != OCFS2_STACK_LABEL_LEN) ||
++	    (strnlen(buf, len) != len))
++		return -EINVAL;
++
++	spin_lock(&ocfs2_stack_lock);
++	if (active_stack) {
++		if (!strncmp(buf, cluster_stack_name, len))
++			ret = count;
++		else
++			ret = -EBUSY;
++	} else {
++		memcpy(cluster_stack_name, buf, len);
++		ret = count;
++	}
++	spin_unlock(&ocfs2_stack_lock);
++
++	return ret;
++}
++
++
++static struct kobj_attribute ocfs2_attr_cluster_stack =
++	__ATTR(cluster_stack, S_IFREG | S_IRUGO | S_IWUSR,
++	       ocfs2_cluster_stack_show,
++	       ocfs2_cluster_stack_store);
++
++static struct attribute *ocfs2_attrs[] = {
++	&ocfs2_attr_max_locking_protocol.attr,
++	&ocfs2_attr_loaded_cluster_plugins.attr,
++	&ocfs2_attr_active_cluster_plugin.attr,
++	&ocfs2_attr_cluster_stack.attr,
++	NULL,
++};
++
++static struct attribute_group ocfs2_attr_group = {
++	.attrs = ocfs2_attrs,
++};
++
++static struct kset *ocfs2_kset;
++
++static void ocfs2_sysfs_exit(void)
++{
++	kset_unregister(ocfs2_kset);
++}
++
++static int ocfs2_sysfs_init(void)
++{
++	int ret;
++
++	ocfs2_kset = kset_create_and_add("ocfs2", NULL, fs_kobj);
++	if (!ocfs2_kset)
++		return -ENOMEM;
++
++	ret = sysfs_create_group(&ocfs2_kset->kobj, &ocfs2_attr_group);
++	if (ret)
++		goto error;
++
++	return 0;
++
++error:
++	kset_unregister(ocfs2_kset);
++	return ret;
++}
++
++static int __init ocfs2_stack_glue_init(void)
++{
++	strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB);
++
++	return ocfs2_sysfs_init();
++}
++
++static void __exit ocfs2_stack_glue_exit(void)
++{
++	lproto = NULL;
++	ocfs2_sysfs_exit();
++}
++
++MODULE_AUTHOR("Oracle");
++MODULE_DESCRIPTION("ocfs2 cluter stack glue layer");
++MODULE_LICENSE("GPL");
++module_init(ocfs2_stack_glue_init);
++module_exit(ocfs2_stack_glue_exit);
+diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h
+new file mode 100644
+index 0000000..005e4f1
+--- /dev/null
++++ b/fs/ocfs2/stackglue.h
+@@ -0,0 +1,261 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * stackglue.h
++ *
++ * Glue to the underlying cluster stack.
++ *
++ * Copyright (C) 2007 Oracle.  All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public
++ * License as published by the Free Software Foundation, version 2.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ */
++
++
++#ifndef STACKGLUE_H
++#define STACKGLUE_H
++
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/dlmconstants.h>
++
++#include "dlm/dlmapi.h"
++#include <linux/dlm.h>
++
++/*
++ * dlmconstants.h does not have a LOCAL flag.  We hope to remove it
++ * some day, but right now we need it.  Let's fake it.  This value is larger
++ * than any flag in dlmconstants.h.
++ */
++#define DLM_LKF_LOCAL		0x00100000
++
++/*
++ * This shadows DLM_LOCKSPACE_LEN in fs/dlm/dlm_internal.h.  That probably
++ * wants to be in a public header.
++ */
++#define GROUP_NAME_MAX		64
++
++
++/*
++ * ocfs2_protocol_version changes when ocfs2 does something different in
++ * its inter-node behavior.  See dlmglue.c for more information.
++ */
++struct ocfs2_protocol_version {
++	u8 pv_major;
++	u8 pv_minor;
++};
++
++/*
++ * The ocfs2_locking_protocol defines the handlers called on ocfs2's behalf.
++ */
++struct ocfs2_locking_protocol {
++	struct ocfs2_protocol_version lp_max_version;
++	void (*lp_lock_ast)(void *astarg);
++	void (*lp_blocking_ast)(void *astarg, int level);
++	void (*lp_unlock_ast)(void *astarg, int error);
++};
++
++
++/*
++ * The dlm_lockstatus struct includes lvb space, but the dlm_lksb struct only
++ * has a pointer to separately allocated lvb space.  This struct exists only to
++ * include in the lksb union to make space for a combined dlm_lksb and lvb.
++ */
++struct fsdlm_lksb_plus_lvb {
++	struct dlm_lksb lksb;
++	char lvb[DLM_LVB_LEN];
++};
++
++/*
++ * A union of all lock status structures.  We define it here so that the
++ * size of the union is known.  Lock status structures are embedded in
++ * ocfs2 inodes.
++ */
++union ocfs2_dlm_lksb {
++	struct dlm_lockstatus lksb_o2dlm;
++	struct dlm_lksb lksb_fsdlm;
++	struct fsdlm_lksb_plus_lvb padding;
++};
++
++/*
++ * A cluster connection.  Mostly opaque to ocfs2, the connection holds
++ * state for the underlying stack.  ocfs2 does use cc_version to determine
++ * locking compatibility.
++ */
++struct ocfs2_cluster_connection {
++	char cc_name[GROUP_NAME_MAX];
++	int cc_namelen;
++	struct ocfs2_protocol_version cc_version;
++	void (*cc_recovery_handler)(int node_num, void *recovery_data);
++	void *cc_recovery_data;
++	void *cc_lockspace;
++	void *cc_private;
++};
++
++/*
++ * Each cluster stack implements the stack operations structure.  Not used
++ * in the ocfs2 code, the stackglue code translates generic cluster calls
++ * into stack operations.
++ */
++struct ocfs2_stack_operations {
++	/*
++	 * The fs code calls ocfs2_cluster_connect() to attach a new
++	 * filesystem to the cluster stack.  The ->connect() op is passed
++	 * an ocfs2_cluster_connection with the name and recovery field
++	 * filled in.
++	 *
++	 * The stack must set up any notification mechanisms and create
++	 * the filesystem lockspace in the DLM.  The lockspace should be
++	 * stored on cc_lockspace.  Any other information can be stored on
++	 * cc_private.
++	 *
++	 * ->connect() must not return until it is guaranteed that
++	 *
++	 *  - Node down notifications for the filesystem will be recieved
++	 *    and passed to conn->cc_recovery_handler().
++	 *  - Locking requests for the filesystem will be processed.
++	 */
++	int (*connect)(struct ocfs2_cluster_connection *conn);
++
++	/*
++	 * The fs code calls ocfs2_cluster_disconnect() when a filesystem
++	 * no longer needs cluster services.  All DLM locks have been
++	 * dropped, and recovery notification is being ignored by the
++	 * fs code.  The stack must disengage from the DLM and discontinue
++	 * recovery notification.
++	 *
++	 * Once ->disconnect() has returned, the connection structure will
++	 * be freed.  Thus, a stack must not return from ->disconnect()
++	 * until it will no longer reference the conn pointer.
++	 *
++	 * If hangup_pending is zero, ocfs2_cluster_disconnect() will also
++	 * be dropping the reference on the module.
++	 */
++	int (*disconnect)(struct ocfs2_cluster_connection *conn,
++			  int hangup_pending);
++
++	/*
++	 * ocfs2_cluster_hangup() exists for compatibility with older
++	 * ocfs2 tools.  Only the classic stack really needs it.  As such
++	 * ->hangup() is not required of all stacks.  See the comment by
++	 * ocfs2_cluster_hangup() for more details.
++	 *
++	 * Note that ocfs2_cluster_hangup() can only be called if
++	 * hangup_pending was passed to ocfs2_cluster_disconnect().
++	 */
++	void (*hangup)(const char *group, int grouplen);
++
++	/*
++	 * ->this_node() returns the cluster's unique identifier for the
++	 * local node.
++	 */
++	int (*this_node)(unsigned int *node);
++
++	/*
++	 * Call the underlying dlm lock function.  The ->dlm_lock()
++	 * callback should convert the flags and mode as appropriate.
++	 *
++	 * ast and bast functions are not part of the call because the
++	 * stack will likely want to wrap ast and bast calls before passing
++	 * them to stack->sp_proto.
++	 */
++	int (*dlm_lock)(struct ocfs2_cluster_connection *conn,
++			int mode,
++			union ocfs2_dlm_lksb *lksb,
++			u32 flags,
++			void *name,
++			unsigned int namelen,
++			void *astarg);
++
++	/*
++	 * Call the underlying dlm unlock function.  The ->dlm_unlock()
++	 * function should convert the flags as appropriate.
++	 *
++	 * The unlock ast is not passed, as the stack will want to wrap
++	 * it before calling stack->sp_proto->lp_unlock_ast().
++	 */
++	int (*dlm_unlock)(struct ocfs2_cluster_connection *conn,
++			  union ocfs2_dlm_lksb *lksb,
++			  u32 flags,
++			  void *astarg);
++
++	/*
++	 * Return the status of the current lock status block.  The fs
++	 * code should never dereference the union.  The ->lock_status()
++	 * callback pulls out the stack-specific lksb, converts the status
++	 * to a proper errno, and returns it.
++	 */
++	int (*lock_status)(union ocfs2_dlm_lksb *lksb);
++
++	/*
++	 * Pull the lvb pointer off of the stack-specific lksb.
++	 */
++	void *(*lock_lvb)(union ocfs2_dlm_lksb *lksb);
++
++	/*
++	 * This is an optoinal debugging hook.  If provided, the
++	 * stack can dump debugging information about this lock.
++	 */
++	void (*dump_lksb)(union ocfs2_dlm_lksb *lksb);
++};
++
++/*
++ * Each stack plugin must describe itself by registering a
++ * ocfs2_stack_plugin structure.  This is only seen by stackglue and the
++ * stack driver.
++ */
++struct ocfs2_stack_plugin {
++	char *sp_name;
++	struct ocfs2_stack_operations *sp_ops;
++	struct module *sp_owner;
++
++	/* These are managed by the stackglue code. */
++	struct list_head sp_list;
++	unsigned int sp_count;
++	struct ocfs2_locking_protocol *sp_proto;
++};
++
++
++/* Used by the filesystem */
++int ocfs2_cluster_connect(const char *stack_name,
++			  const char *group,
++			  int grouplen,
++			  void (*recovery_handler)(int node_num,
++						   void *recovery_data),
++			  void *recovery_data,
++			  struct ocfs2_cluster_connection **conn);
++int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
++			     int hangup_pending);
++void ocfs2_cluster_hangup(const char *group, int grouplen);
++int ocfs2_cluster_this_node(unsigned int *node);
++
++struct ocfs2_lock_res;
++int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
++		   int mode,
++		   union ocfs2_dlm_lksb *lksb,
++		   u32 flags,
++		   void *name,
++		   unsigned int namelen,
++		   struct ocfs2_lock_res *astarg);
++int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
++		     union ocfs2_dlm_lksb *lksb,
++		     u32 flags,
++		     struct ocfs2_lock_res *astarg);
++
++int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb);
++void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb);
++void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb);
++
++void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto);
++
++
++/* Used by stack plugins */
++int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin);
++void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin);
++#endif  /* STACKGLUE_H */
+diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
+index 72c198a..d2d278f 100644
+--- a/fs/ocfs2/suballoc.c
++++ b/fs/ocfs2/suballoc.c
+@@ -46,6 +46,11 @@
+ 
+ #include "buffer_head_io.h"
+ 
++#define NOT_ALLOC_NEW_GROUP		0
++#define ALLOC_NEW_GROUP			1
++
++#define OCFS2_MAX_INODES_TO_STEAL	1024
++
+ static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
+ static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
+ static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl);
+@@ -106,7 +111,7 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
+ 						u64 *bg_blkno,
+ 						u16 *bg_bit_off);
+ 
+-void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
++static void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
+ {
+ 	struct inode *inode = ac->ac_inode;
+ 
+@@ -117,9 +122,17 @@ void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
+ 		mutex_unlock(&inode->i_mutex);
+ 
+ 		iput(inode);
++		ac->ac_inode = NULL;
+ 	}
+-	if (ac->ac_bh)
++	if (ac->ac_bh) {
+ 		brelse(ac->ac_bh);
++		ac->ac_bh = NULL;
++	}
++}
++
++void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
++{
++	ocfs2_free_ac_resource(ac);
+ 	kfree(ac);
+ }
+ 
+@@ -391,7 +404,8 @@ bail:
+ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
+ 				       struct ocfs2_alloc_context *ac,
+ 				       int type,
+-				       u32 slot)
++				       u32 slot,
++				       int alloc_new_group)
+ {
+ 	int status;
+ 	u32 bits_wanted = ac->ac_bits_wanted;
+@@ -420,6 +434,7 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
+ 	}
+ 
+ 	ac->ac_inode = alloc_inode;
++	ac->ac_alloc_slot = slot;
+ 
+ 	fe = (struct ocfs2_dinode *) bh->b_data;
+ 	if (!OCFS2_IS_VALID_DINODE(fe)) {
+@@ -446,6 +461,14 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
+ 			goto bail;
+ 		}
+ 
++		if (alloc_new_group != ALLOC_NEW_GROUP) {
++			mlog(0, "Alloc File %u Full: wanted=%u, free_bits=%u, "
++			     "and we don't alloc a new group for it.\n",
++			     slot, bits_wanted, free_bits);
++			status = -ENOSPC;
++			goto bail;
++		}
++
+ 		status = ocfs2_block_group_alloc(osb, alloc_inode, bh);
+ 		if (status < 0) {
+ 			if (status != -ENOSPC)
+@@ -490,7 +513,8 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
+ 	(*ac)->ac_group_search = ocfs2_block_group_search;
+ 
+ 	status = ocfs2_reserve_suballoc_bits(osb, (*ac),
+-					     EXTENT_ALLOC_SYSTEM_INODE, slot);
++					     EXTENT_ALLOC_SYSTEM_INODE,
++					     slot, ALLOC_NEW_GROUP);
+ 	if (status < 0) {
+ 		if (status != -ENOSPC)
+ 			mlog_errno(status);
+@@ -508,10 +532,42 @@ bail:
+ 	return status;
+ }
+ 
++static int ocfs2_steal_inode_from_other_nodes(struct ocfs2_super *osb,
++					      struct ocfs2_alloc_context *ac)
++{
++	int i, status = -ENOSPC;
++	s16 slot = ocfs2_get_inode_steal_slot(osb);
++
++	/* Start to steal inodes from the first slot after ours. */
++	if (slot == OCFS2_INVALID_SLOT)
++		slot = osb->slot_num + 1;
++
++	for (i = 0; i < osb->max_slots; i++, slot++) {
++		if (slot == osb->max_slots)
++			slot = 0;
++
++		if (slot == osb->slot_num)
++			continue;
++
++		status = ocfs2_reserve_suballoc_bits(osb, ac,
++						     INODE_ALLOC_SYSTEM_INODE,
++						     slot, NOT_ALLOC_NEW_GROUP);
++		if (status >= 0) {
++			ocfs2_set_inode_steal_slot(osb, slot);
++			break;
++		}
++
++		ocfs2_free_ac_resource(ac);
++	}
++
++	return status;
++}
++
+ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
+ 			    struct ocfs2_alloc_context **ac)
+ {
+ 	int status;
++	s16 slot = ocfs2_get_inode_steal_slot(osb);
+ 
+ 	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ 	if (!(*ac)) {
+@@ -525,9 +581,43 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
+ 
+ 	(*ac)->ac_group_search = ocfs2_block_group_search;
+ 
++	/*
++	 * slot is set when we successfully steal inode from other nodes.
++	 * It is reset in 3 places:
++	 * 1. when we flush the truncate log
++	 * 2. when we complete local alloc recovery.
++	 * 3. when we successfully allocate from our own slot.
++	 * After it is set, we will go on stealing inodes until we find the
++	 * need to check our slots to see whether there is some space for us.
++	 */
++	if (slot != OCFS2_INVALID_SLOT &&
++	    atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_INODES_TO_STEAL)
++		goto inode_steal;
++
++	atomic_set(&osb->s_num_inodes_stolen, 0);
+ 	status = ocfs2_reserve_suballoc_bits(osb, *ac,
+ 					     INODE_ALLOC_SYSTEM_INODE,
+-					     osb->slot_num);
++					     osb->slot_num, ALLOC_NEW_GROUP);
++	if (status >= 0) {
++		status = 0;
++
++		/*
++		 * Some inodes must be freed by us, so try to allocate
++		 * from our own next time.
++		 */
++		if (slot != OCFS2_INVALID_SLOT)
++			ocfs2_init_inode_steal_slot(osb);
++		goto bail;
++	} else if (status < 0 && status != -ENOSPC) {
++		mlog_errno(status);
++		goto bail;
++	}
++
++	ocfs2_free_ac_resource(*ac);
++
++inode_steal:
++	status = ocfs2_steal_inode_from_other_nodes(osb, *ac);
++	atomic_inc(&osb->s_num_inodes_stolen);
+ 	if (status < 0) {
+ 		if (status != -ENOSPC)
+ 			mlog_errno(status);
+@@ -557,7 +647,8 @@ int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,
+ 
+ 	status = ocfs2_reserve_suballoc_bits(osb, ac,
+ 					     GLOBAL_BITMAP_SYSTEM_INODE,
+-					     OCFS2_INVALID_SLOT);
++					     OCFS2_INVALID_SLOT,
++					     ALLOC_NEW_GROUP);
+ 	if (status < 0 && status != -ENOSPC) {
+ 		mlog_errno(status);
+ 		goto bail;
+diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
+index 8799033..544c600 100644
+--- a/fs/ocfs2/suballoc.h
++++ b/fs/ocfs2/suballoc.h
+@@ -36,6 +36,7 @@ typedef int (group_search_t)(struct inode *,
+ struct ocfs2_alloc_context {
+ 	struct inode *ac_inode;    /* which bitmap are we allocating from? */
+ 	struct buffer_head *ac_bh; /* file entry bh */
++	u32    ac_alloc_slot;   /* which slot are we allocating from? */
+ 	u32    ac_bits_wanted;
+ 	u32    ac_bits_given;
+ #define OCFS2_AC_USE_LOCAL 1
+diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
+index bec75af..df63ba2 100644
+--- a/fs/ocfs2/super.c
++++ b/fs/ocfs2/super.c
+@@ -40,8 +40,7 @@
+ #include <linux/crc32.h>
+ #include <linux/debugfs.h>
+ #include <linux/mount.h>
+-
+-#include <cluster/nodemanager.h>
++#include <linux/seq_file.h>
+ 
+ #define MLOG_MASK_PREFIX ML_SUPER
+ #include <cluster/masklog.h>
+@@ -88,6 +87,7 @@ struct mount_options
+ 	unsigned int	atime_quantum;
+ 	signed short	slot;
+ 	unsigned int	localalloc_opt;
++	char		cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
+ };
+ 
+ static int ocfs2_parse_options(struct super_block *sb, char *options,
+@@ -109,7 +109,6 @@ static int ocfs2_sync_fs(struct super_block *sb, int wait);
+ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb);
+ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb);
+ static void ocfs2_release_system_inodes(struct ocfs2_super *osb);
+-static int ocfs2_fill_local_node_info(struct ocfs2_super *osb);
+ static int ocfs2_check_volume(struct ocfs2_super *osb);
+ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
+ 			       struct buffer_head *bh,
+@@ -154,6 +153,7 @@ enum {
+ 	Opt_commit,
+ 	Opt_localalloc,
+ 	Opt_localflocks,
++	Opt_stack,
+ 	Opt_err,
+ };
+ 
+@@ -172,6 +172,7 @@ static match_table_t tokens = {
+ 	{Opt_commit, "commit=%u"},
+ 	{Opt_localalloc, "localalloc=%d"},
+ 	{Opt_localflocks, "localflocks"},
++	{Opt_stack, "cluster_stack=%s"},
+ 	{Opt_err, NULL}
+ };
+ 
+@@ -551,8 +552,17 @@ static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
+ 		}
+ 	}
+ 
++	if (ocfs2_userspace_stack(osb)) {
++		if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
++			mlog(ML_ERROR, "Userspace stack expected, but "
++			     "o2cb heartbeat arguments passed to mount\n");
++			return -EINVAL;
++		}
++	}
++
+ 	if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+-		if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb)) {
++		if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) &&
++		    !ocfs2_userspace_stack(osb)) {
+ 			mlog(ML_ERROR, "Heartbeat has to be started to mount "
+ 			     "a read-write clustered device.\n");
+ 			return -EINVAL;
+@@ -562,6 +572,35 @@ static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
+ 	return 0;
+ }
+ 
++/*
++ * If we're using a userspace stack, mount should have passed
++ * a name that matches the disk.  If not, mount should not
++ * have passed a stack.
++ */
++static int ocfs2_verify_userspace_stack(struct ocfs2_super *osb,
++					struct mount_options *mopt)
++{
++	if (!ocfs2_userspace_stack(osb) && mopt->cluster_stack[0]) {
++		mlog(ML_ERROR,
++		     "cluster stack passed to mount, but this filesystem "
++		     "does not support it\n");
++		return -EINVAL;
++	}
++
++	if (ocfs2_userspace_stack(osb) &&
++	    strncmp(osb->osb_cluster_stack, mopt->cluster_stack,
++		    OCFS2_STACK_LABEL_LEN)) {
++		mlog(ML_ERROR,
++		     "cluster stack passed to mount (\"%s\") does not "
++		     "match the filesystem (\"%s\")\n",
++		     mopt->cluster_stack,
++		     osb->osb_cluster_stack);
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
+ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ {
+ 	struct dentry *root;
+@@ -579,15 +618,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto read_super_error;
+ 	}
+ 
+-	/* for now we only have one cluster/node, make sure we see it
+-	 * in the heartbeat universe */
+-	if (parsed_options.mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+-		if (!o2hb_check_local_node_heartbeating()) {
+-			status = -EINVAL;
+-			goto read_super_error;
+-		}
+-	}
+-
+ 	/* probe for superblock */
+ 	status = ocfs2_sb_probe(sb, &bh, &sector_size);
+ 	if (status < 0) {
+@@ -609,6 +639,10 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ 	osb->osb_commit_interval = parsed_options.commit_interval;
+ 	osb->local_alloc_size = parsed_options.localalloc_opt;
+ 
++	status = ocfs2_verify_userspace_stack(osb, &parsed_options);
++	if (status)
++		goto read_super_error;
++
+ 	sb->s_magic = OCFS2_SUPER_MAGIC;
+ 
+ 	/* Hard readonly mode only if: bdev_read_only, MS_RDONLY,
+@@ -694,7 +728,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ 	if (ocfs2_mount_local(osb))
+ 		snprintf(nodestr, sizeof(nodestr), "local");
+ 	else
+-		snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
++		snprintf(nodestr, sizeof(nodestr), "%u", osb->node_num);
+ 
+ 	printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %s, slot %d) "
+ 	       "with %s data mode.\n",
+@@ -763,6 +797,7 @@ static int ocfs2_parse_options(struct super_block *sb,
+ 	mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
+ 	mopt->slot = OCFS2_INVALID_SLOT;
+ 	mopt->localalloc_opt = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE;
++	mopt->cluster_stack[0] = '\0';
+ 
+ 	if (!options) {
+ 		status = 1;
+@@ -864,6 +899,25 @@ static int ocfs2_parse_options(struct super_block *sb,
+ 			if (!is_remount)
+ 				mopt->mount_opt |= OCFS2_MOUNT_LOCALFLOCKS;
+ 			break;
++		case Opt_stack:
++			/* Check both that the option we were passed
++			 * is of the right length and that it is a proper
++			 * string of the right length.
++			 */
++			if (((args[0].to - args[0].from) !=
++			     OCFS2_STACK_LABEL_LEN) ||
++			    (strnlen(args[0].from,
++				     OCFS2_STACK_LABEL_LEN) !=
++			     OCFS2_STACK_LABEL_LEN)) {
++				mlog(ML_ERROR,
++				     "Invalid cluster_stack option\n");
++				status = 0;
++				goto bail;
++			}
++			memcpy(mopt->cluster_stack, args[0].from,
++			       OCFS2_STACK_LABEL_LEN);
++			mopt->cluster_stack[OCFS2_STACK_LABEL_LEN] = '\0';
++			break;
+ 		default:
+ 			mlog(ML_ERROR,
+ 			     "Unrecognized mount option \"%s\" "
+@@ -922,6 +976,10 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
+ 	if (opts & OCFS2_MOUNT_LOCALFLOCKS)
+ 		seq_printf(s, ",localflocks,");
+ 
++	if (osb->osb_cluster_stack[0])
++		seq_printf(s, ",cluster_stack=%.*s", OCFS2_STACK_LABEL_LEN,
++			   osb->osb_cluster_stack);
++
+ 	return 0;
+ }
+ 
+@@ -957,6 +1015,8 @@ static int __init ocfs2_init(void)
+ 		mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n");
+ 	}
+ 
++	ocfs2_set_locking_protocol();
++
+ leave:
+ 	if (status < 0) {
+ 		ocfs2_free_mem_caches();
+@@ -1132,31 +1192,6 @@ static int ocfs2_get_sector(struct super_block *sb,
+ 	return 0;
+ }
+ 
+-/* ocfs2 1.0 only allows one cluster and node identity per kernel image. */
+-static int ocfs2_fill_local_node_info(struct ocfs2_super *osb)
+-{
+-	int status;
+-
+-	/* XXX hold a ref on the node while mounte?  easy enough, if
+-	 * desirable. */
+-	if (ocfs2_mount_local(osb))
+-		osb->node_num = 0;
+-	else
+-		osb->node_num = o2nm_this_node();
+-
+-	if (osb->node_num == O2NM_MAX_NODES) {
+-		mlog(ML_ERROR, "could not find this host's node number\n");
+-		status = -ENOENT;
+-		goto bail;
+-	}
+-
+-	mlog(0, "I am node %d\n", osb->node_num);
+-
+-	status = 0;
+-bail:
+-	return status;
+-}
+-
+ static int ocfs2_mount_volume(struct super_block *sb)
+ {
+ 	int status = 0;
+@@ -1168,12 +1203,6 @@ static int ocfs2_mount_volume(struct super_block *sb)
+ 	if (ocfs2_is_hard_readonly(osb))
+ 		goto leave;
+ 
+-	status = ocfs2_fill_local_node_info(osb);
+-	if (status < 0) {
+-		mlog_errno(status);
+-		goto leave;
+-	}
+-
+ 	status = ocfs2_dlm_init(osb);
+ 	if (status < 0) {
+ 		mlog_errno(status);
+@@ -1224,18 +1253,9 @@ leave:
+ 	return status;
+ }
+ 
+-/* we can't grab the goofy sem lock from inside wait_event, so we use
+- * memory barriers to make sure that we'll see the null task before
+- * being woken up */
+-static int ocfs2_recovery_thread_running(struct ocfs2_super *osb)
+-{
+-	mb();
+-	return osb->recovery_thread_task != NULL;
+-}
+-
+ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
+ {
+-	int tmp;
++	int tmp, hangup_needed = 0;
+ 	struct ocfs2_super *osb = NULL;
+ 	char nodestr[8];
+ 
+@@ -1249,25 +1269,16 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
+ 
+ 	ocfs2_truncate_log_shutdown(osb);
+ 
+-	/* disable any new recovery threads and wait for any currently
+-	 * running ones to exit. Do this before setting the vol_state. */
+-	mutex_lock(&osb->recovery_lock);
+-	osb->disable_recovery = 1;
+-	mutex_unlock(&osb->recovery_lock);
+-	wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb));
+-
+-	/* At this point, we know that no more recovery threads can be
+-	 * launched, so wait for any recovery completion work to
+-	 * complete. */
+-	flush_workqueue(ocfs2_wq);
++	/* This will disable recovery and flush any recovery work. */
++	ocfs2_recovery_exit(osb);
+ 
+ 	ocfs2_journal_shutdown(osb);
+ 
+ 	ocfs2_sync_blockdev(sb);
+ 
+-	/* No dlm means we've failed during mount, so skip all the
+-	 * steps which depended on that to complete. */
+-	if (osb->dlm) {
++	/* No cluster connection means we've failed during mount, so skip
++	 * all the steps which depended on that to complete. */
++	if (osb->cconn) {
+ 		tmp = ocfs2_super_lock(osb, 1);
+ 		if (tmp < 0) {
+ 			mlog_errno(tmp);
+@@ -1278,25 +1289,34 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
+ 	if (osb->slot_num != OCFS2_INVALID_SLOT)
+ 		ocfs2_put_slot(osb);
+ 
+-	if (osb->dlm)
++	if (osb->cconn)
+ 		ocfs2_super_unlock(osb, 1);
+ 
+ 	ocfs2_release_system_inodes(osb);
+ 
+-	if (osb->dlm)
+-		ocfs2_dlm_shutdown(osb);
++	/*
++	 * If we're dismounting due to mount error, mount.ocfs2 will clean
++	 * up heartbeat.  If we're a local mount, there is no heartbeat.
++	 * If we failed before we got a uuid_str yet, we can't stop
++	 * heartbeat.  Otherwise, do it.
++	 */
++	if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str)
++		hangup_needed = 1;
++
++	if (osb->cconn)
++		ocfs2_dlm_shutdown(osb, hangup_needed);
+ 
+ 	debugfs_remove(osb->osb_debug_root);
+ 
+-	if (!mnt_err)
+-		ocfs2_stop_heartbeat(osb);
++	if (hangup_needed)
++		ocfs2_cluster_hangup(osb->uuid_str, strlen(osb->uuid_str));
+ 
+ 	atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);
+ 
+ 	if (ocfs2_mount_local(osb))
+ 		snprintf(nodestr, sizeof(nodestr), "local");
+ 	else
+-		snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
++		snprintf(nodestr, sizeof(nodestr), "%u", osb->node_num);
+ 
+ 	printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %s)\n",
+ 	       osb->dev_str, nodestr);
+@@ -1355,7 +1375,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ 	sb->s_fs_info = osb;
+ 	sb->s_op = &ocfs2_sops;
+ 	sb->s_export_op = &ocfs2_export_ops;
+-	osb->osb_locking_proto = ocfs2_locking_protocol;
+ 	sb->s_time_gran = 1;
+ 	sb->s_flags |= MS_NOATIME;
+ 	/* this is needed to support O_LARGEFILE */
+@@ -1368,7 +1387,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ 	osb->s_sectsize_bits = blksize_bits(sector_size);
+ 	BUG_ON(!osb->s_sectsize_bits);
+ 
+-	init_waitqueue_head(&osb->recovery_event);
+ 	spin_lock_init(&osb->dc_task_lock);
+ 	init_waitqueue_head(&osb->dc_event);
+ 	osb->dc_work_sequence = 0;
+@@ -1376,6 +1394,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ 	INIT_LIST_HEAD(&osb->blocked_lock_list);
+ 	osb->blocked_lock_count = 0;
+ 	spin_lock_init(&osb->osb_lock);
++	ocfs2_init_inode_steal_slot(osb);
+ 
+ 	atomic_set(&osb->alloc_stats.moves, 0);
+ 	atomic_set(&osb->alloc_stats.local_data, 0);
+@@ -1388,24 +1407,23 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ 	snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
+ 		 MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+ 
+-	mutex_init(&osb->recovery_lock);
+-
+-	osb->disable_recovery = 0;
+-	osb->recovery_thread_task = NULL;
++	status = ocfs2_recovery_init(osb);
++	if (status) {
++		mlog(ML_ERROR, "Unable to initialize recovery state\n");
++		mlog_errno(status);
++		goto bail;
++	}
+ 
+ 	init_waitqueue_head(&osb->checkpoint_event);
+ 	atomic_set(&osb->needs_checkpoint, 0);
+ 
+ 	osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
+ 
+-	osb->node_num = O2NM_INVALID_NODE_NUM;
+ 	osb->slot_num = OCFS2_INVALID_SLOT;
+ 
+ 	osb->local_alloc_state = OCFS2_LA_UNUSED;
+ 	osb->local_alloc_bh = NULL;
+ 
+-	ocfs2_setup_hb_callbacks(osb);
+-
+ 	init_waitqueue_head(&osb->osb_mount_event);
+ 
+ 	osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL);
+@@ -1455,6 +1473,25 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ 		goto bail;
+ 	}
+ 
++	if (ocfs2_userspace_stack(osb)) {
++		memcpy(osb->osb_cluster_stack,
++		       OCFS2_RAW_SB(di)->s_cluster_info.ci_stack,
++		       OCFS2_STACK_LABEL_LEN);
++		osb->osb_cluster_stack[OCFS2_STACK_LABEL_LEN] = '\0';
++		if (strlen(osb->osb_cluster_stack) != OCFS2_STACK_LABEL_LEN) {
++			mlog(ML_ERROR,
++			     "couldn't mount because of an invalid "
++			     "cluster stack label (%s) \n",
++			     osb->osb_cluster_stack);
++			status = -EINVAL;
++			goto bail;
++		}
++	} else {
++		/* The empty string is identical with classic tools that
++		 * don't know about s_cluster_info. */
++		osb->osb_cluster_stack[0] = '\0';
++	}
++
+ 	get_random_bytes(&osb->s_next_generation, sizeof(u32));
+ 
+ 	/* FIXME
+@@ -1724,8 +1761,7 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb)
+ 
+ 	/* This function assumes that the caller has the main osb resource */
+ 
+-	if (osb->slot_info)
+-		ocfs2_free_slot_info(osb->slot_info);
++	ocfs2_free_slot_info(osb);
+ 
+ 	kfree(osb->osb_orphan_wipes);
+ 	/* FIXME
+diff --git a/fs/open.c b/fs/open.c
+index 3fa4e4f..b70e766 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -244,21 +244,21 @@ static long do_sys_truncate(const char __user * path, loff_t length)
+ 	if (!S_ISREG(inode->i_mode))
+ 		goto dput_and_out;
+ 
+-	error = vfs_permission(&nd, MAY_WRITE);
++	error = mnt_want_write(nd.path.mnt);
+ 	if (error)
+ 		goto dput_and_out;
+ 
+-	error = -EROFS;
+-	if (IS_RDONLY(inode))
+-		goto dput_and_out;
++	error = vfs_permission(&nd, MAY_WRITE);
++	if (error)
++		goto mnt_drop_write_and_out;
+ 
+ 	error = -EPERM;
+ 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+-		goto dput_and_out;
++		goto mnt_drop_write_and_out;
+ 
+ 	error = get_write_access(inode);
+ 	if (error)
+-		goto dput_and_out;
++		goto mnt_drop_write_and_out;
+ 
+ 	/*
+ 	 * Make sure that there are no leases.  get_write_access() protects
+@@ -276,6 +276,8 @@ static long do_sys_truncate(const char __user * path, loff_t length)
+ 
+ put_write_and_out:
+ 	put_write_access(inode);
++mnt_drop_write_and_out:
++	mnt_drop_write(nd.path.mnt);
+ dput_and_out:
+ 	path_put(&nd.path);
+ out:
+@@ -457,8 +459,17 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
+ 	if(res || !(mode & S_IWOTH) ||
+ 	   special_file(nd.path.dentry->d_inode->i_mode))
+ 		goto out_path_release;
+-
+-	if(IS_RDONLY(nd.path.dentry->d_inode))
++	/*
++	 * This is a rare case where using __mnt_is_readonly()
++	 * is OK without a mnt_want/drop_write() pair.  Since
++	 * no actual write to the fs is performed here, we do
++	 * not need to telegraph to that to anyone.
++	 *
++	 * By doing this, we accept that this access is
++	 * inherently racy and know that the fs may change
++	 * state before we even see this result.
++	 */
++	if (__mnt_is_readonly(nd.path.mnt))
+ 		res = -EROFS;
+ 
+ out_path_release:
+@@ -567,12 +578,12 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
+ 
+ 	audit_inode(NULL, dentry);
+ 
+-	err = -EROFS;
+-	if (IS_RDONLY(inode))
++	err = mnt_want_write(file->f_path.mnt);
++	if (err)
+ 		goto out_putf;
+ 	err = -EPERM;
+ 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+-		goto out_putf;
++		goto out_drop_write;
+ 	mutex_lock(&inode->i_mutex);
+ 	if (mode == (mode_t) -1)
+ 		mode = inode->i_mode;
+@@ -581,6 +592,8 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
+ 	err = notify_change(dentry, &newattrs);
+ 	mutex_unlock(&inode->i_mutex);
+ 
++out_drop_write:
++	mnt_drop_write(file->f_path.mnt);
+ out_putf:
+ 	fput(file);
+ out:
+@@ -600,13 +613,13 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
+ 		goto out;
+ 	inode = nd.path.dentry->d_inode;
+ 
+-	error = -EROFS;
+-	if (IS_RDONLY(inode))
++	error = mnt_want_write(nd.path.mnt);
++	if (error)
+ 		goto dput_and_out;
+ 
+ 	error = -EPERM;
+ 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+-		goto dput_and_out;
++		goto out_drop_write;
+ 
+ 	mutex_lock(&inode->i_mutex);
+ 	if (mode == (mode_t) -1)
+@@ -616,6 +629,8 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
+ 	error = notify_change(nd.path.dentry, &newattrs);
+ 	mutex_unlock(&inode->i_mutex);
+ 
++out_drop_write:
++	mnt_drop_write(nd.path.mnt);
+ dput_and_out:
+ 	path_put(&nd.path);
+ out:
+@@ -638,9 +653,6 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+ 		printk(KERN_ERR "chown_common: NULL inode\n");
+ 		goto out;
+ 	}
+-	error = -EROFS;
+-	if (IS_RDONLY(inode))
+-		goto out;
+ 	error = -EPERM;
+ 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ 		goto out;
+@@ -671,7 +683,12 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
+ 	error = user_path_walk(filename, &nd);
+ 	if (error)
+ 		goto out;
++	error = mnt_want_write(nd.path.mnt);
++	if (error)
++		goto out_release;
+ 	error = chown_common(nd.path.dentry, user, group);
++	mnt_drop_write(nd.path.mnt);
++out_release:
+ 	path_put(&nd.path);
+ out:
+ 	return error;
+@@ -691,7 +708,12 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
+ 	error = __user_walk_fd(dfd, filename, follow, &nd);
+ 	if (error)
+ 		goto out;
++	error = mnt_want_write(nd.path.mnt);
++	if (error)
++		goto out_release;
+ 	error = chown_common(nd.path.dentry, user, group);
++	mnt_drop_write(nd.path.mnt);
++out_release:
+ 	path_put(&nd.path);
+ out:
+ 	return error;
+@@ -705,7 +727,12 @@ asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group
+ 	error = user_path_walk_link(filename, &nd);
+ 	if (error)
+ 		goto out;
++	error = mnt_want_write(nd.path.mnt);
++	if (error)
++		goto out_release;
+ 	error = chown_common(nd.path.dentry, user, group);
++	mnt_drop_write(nd.path.mnt);
++out_release:
+ 	path_put(&nd.path);
+ out:
+ 	return error;
+@@ -722,14 +749,48 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
+ 	if (!file)
+ 		goto out;
+ 
++	error = mnt_want_write(file->f_path.mnt);
++	if (error)
++		goto out_fput;
+ 	dentry = file->f_path.dentry;
+ 	audit_inode(NULL, dentry);
+ 	error = chown_common(dentry, user, group);
++	mnt_drop_write(file->f_path.mnt);
++out_fput:
+ 	fput(file);
+ out:
+ 	return error;
+ }
+ 
++/*
++ * You have to be very careful that these write
++ * counts get cleaned up in error cases and
++ * upon __fput().  This should probably never
++ * be called outside of __dentry_open().
++ */
++static inline int __get_file_write_access(struct inode *inode,
++					  struct vfsmount *mnt)
++{
++	int error;
++	error = get_write_access(inode);
++	if (error)
++		return error;
++	/*
++	 * Do not take mount writer counts on
++	 * special files since no writes to
++	 * the mount itself will occur.
++	 */
++	if (!special_file(inode->i_mode)) {
++		/*
++		 * Balanced in __fput()
++		 */
++		error = mnt_want_write(mnt);
++		if (error)
++			put_write_access(inode);
++	}
++	return error;
++}
++
+ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ 					int flags, struct file *f,
+ 					int (*open)(struct inode *, struct file *))
+@@ -742,9 +803,11 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ 				FMODE_PREAD | FMODE_PWRITE;
+ 	inode = dentry->d_inode;
+ 	if (f->f_mode & FMODE_WRITE) {
+-		error = get_write_access(inode);
++		error = __get_file_write_access(inode, mnt);
+ 		if (error)
+ 			goto cleanup_file;
++		if (!special_file(inode->i_mode))
++			file_take_write(f);
+ 	}
+ 
+ 	f->f_mapping = inode->i_mapping;
+@@ -784,8 +847,19 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ 
+ cleanup_all:
+ 	fops_put(f->f_op);
+-	if (f->f_mode & FMODE_WRITE)
++	if (f->f_mode & FMODE_WRITE) {
+ 		put_write_access(inode);
++		if (!special_file(inode->i_mode)) {
++			/*
++			 * We don't consider this a real
++			 * mnt_want/drop_write() pair
++			 * because it all happenend right
++			 * here, so just reset the state.
++			 */
++			file_reset_write(f);
++			mnt_drop_write(mnt);
++		}
++	}
+ 	file_kill(f);
+ 	f->f_path.dentry = NULL;
+ 	f->f_path.mnt = NULL;
+@@ -796,43 +870,6 @@ cleanup_file:
+ 	return ERR_PTR(error);
+ }
+ 
+-/*
+- * Note that while the flag value (low two bits) for sys_open means:
+- *	00 - read-only
+- *	01 - write-only
+- *	10 - read-write
+- *	11 - special
+- * it is changed into
+- *	00 - no permissions needed
+- *	01 - read-permission
+- *	10 - write-permission
+- *	11 - read-write
+- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
+- * used by symlinks.
+- */
+-static struct file *do_filp_open(int dfd, const char *filename, int flags,
+-				 int mode)
+-{
+-	int namei_flags, error;
+-	struct nameidata nd;
+-
+-	namei_flags = flags;
+-	if ((namei_flags+1) & O_ACCMODE)
+-		namei_flags++;
+-
+-	error = open_namei(dfd, filename, namei_flags, mode, &nd);
+-	if (!error)
+-		return nameidata_to_filp(&nd, flags);
+-
+-	return ERR_PTR(error);
+-}
+-
+-struct file *filp_open(const char *filename, int flags, int mode)
+-{
+-	return do_filp_open(AT_FDCWD, filename, flags, mode);
+-}
+-EXPORT_SYMBOL(filp_open);
+-
+ /**
+  * lookup_instantiate_filp - instantiates the open intent filp
+  * @nd: pointer to nameidata
+diff --git a/fs/partitions/check.c b/fs/partitions/check.c
+index 03f808c..6149e4b 100644
+--- a/fs/partitions/check.c
++++ b/fs/partitions/check.c
+@@ -473,6 +473,10 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
+ 		return 0;
+ 	if (IS_ERR(state))	/* I/O error reading the partition table */
+ 		return -EIO;
++
++	/* tell userspace that the media / partition table may have changed */
++	kobject_uevent(&disk->dev.kobj, KOBJ_CHANGE);
++
+ 	for (p = 1; p < state->limit; p++) {
+ 		sector_t size = state->parts[p].size;
+ 		sector_t from = state->parts[p].from;
+diff --git a/fs/pipe.c b/fs/pipe.c
+index 8be381b..f73492b 100644
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -988,7 +988,10 @@ struct file *create_write_pipe(void)
+ 	return f;
+ 
+  err_dentry:
++	free_pipe_info(inode);
+ 	dput(dentry);
++	return ERR_PTR(err);
++
+  err_inode:
+ 	free_pipe_info(inode);
+ 	iput(inode);
+diff --git a/fs/pnode.c b/fs/pnode.c
+index 1d8f544..8d5f392 100644
+--- a/fs/pnode.c
++++ b/fs/pnode.c
+@@ -9,6 +9,7 @@
+ #include <linux/mnt_namespace.h>
+ #include <linux/mount.h>
+ #include <linux/fs.h>
++#include "internal.h"
+ #include "pnode.h"
+ 
+ /* return the next shared peer mount of @p */
+@@ -27,6 +28,57 @@ static inline struct vfsmount *next_slave(struct vfsmount *p)
+ 	return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave);
+ }
+ 
++/*
++ * Return true if path is reachable from root
++ *
++ * namespace_sem is held, and mnt is attached
++ */
++static bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry,
++			 const struct path *root)
++{
++	while (mnt != root->mnt && mnt->mnt_parent != mnt) {
++		dentry = mnt->mnt_mountpoint;
++		mnt = mnt->mnt_parent;
++	}
++	return mnt == root->mnt && is_subdir(dentry, root->dentry);
++}
++
++static struct vfsmount *get_peer_under_root(struct vfsmount *mnt,
++					    struct mnt_namespace *ns,
++					    const struct path *root)
++{
++	struct vfsmount *m = mnt;
++
++	do {
++		/* Check the namespace first for optimization */
++		if (m->mnt_ns == ns && is_path_reachable(m, m->mnt_root, root))
++			return m;
++
++		m = next_peer(m);
++	} while (m != mnt);
++
++	return NULL;
++}
++
++/*
++ * Get ID of closest dominating peer group having a representative
++ * under the given root.
++ *
++ * Caller must hold namespace_sem
++ */
++int get_dominating_id(struct vfsmount *mnt, const struct path *root)
++{
++	struct vfsmount *m;
++
++	for (m = mnt->mnt_master; m != NULL; m = m->mnt_master) {
++		struct vfsmount *d = get_peer_under_root(m, mnt->mnt_ns, root);
++		if (d)
++			return d->mnt_group_id;
++	}
++
++	return 0;
++}
++
+ static int do_make_slave(struct vfsmount *mnt)
+ {
+ 	struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master;
+@@ -45,7 +97,11 @@ static int do_make_slave(struct vfsmount *mnt)
+ 		if (peer_mnt == mnt)
+ 			peer_mnt = NULL;
+ 	}
++	if (IS_MNT_SHARED(mnt) && list_empty(&mnt->mnt_share))
++		mnt_release_group_id(mnt);
++
+ 	list_del_init(&mnt->mnt_share);
++	mnt->mnt_group_id = 0;
+ 
+ 	if (peer_mnt)
+ 		master = peer_mnt;
+@@ -67,7 +123,6 @@ static int do_make_slave(struct vfsmount *mnt)
+ 	}
+ 	mnt->mnt_master = master;
+ 	CLEAR_MNT_SHARED(mnt);
+-	INIT_LIST_HEAD(&mnt->mnt_slave_list);
+ 	return 0;
+ }
+ 
+@@ -211,8 +266,7 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
+ out:
+ 	spin_lock(&vfsmount_lock);
+ 	while (!list_empty(&tmp_list)) {
+-		child = list_entry(tmp_list.next, struct vfsmount, mnt_hash);
+-		list_del_init(&child->mnt_hash);
++		child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash);
+ 		umount_tree(child, 0, &umount_list);
+ 	}
+ 	spin_unlock(&vfsmount_lock);
+diff --git a/fs/pnode.h b/fs/pnode.h
+index f249be2..958665d 100644
+--- a/fs/pnode.h
++++ b/fs/pnode.h
+@@ -35,4 +35,6 @@ int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *,
+ 		struct list_head *);
+ int propagate_umount(struct list_head *);
+ int propagate_mount_busy(struct vfsmount *, int);
++void mnt_release_group_id(struct vfsmount *);
++int get_dominating_id(struct vfsmount *mnt, const struct path *root);
+ #endif /* _LINUX_PNODE_H */
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index 81d7d14..c5e412a 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -502,17 +502,14 @@ static const struct inode_operations proc_def_inode_operations = {
+ 	.setattr	= proc_setattr,
+ };
+ 
+-extern const struct seq_operations mounts_op;
+-struct proc_mounts {
+-	struct seq_file m;
+-	int event;
+-};
+-
+-static int mounts_open(struct inode *inode, struct file *file)
++static int mounts_open_common(struct inode *inode, struct file *file,
++			      const struct seq_operations *op)
+ {
+ 	struct task_struct *task = get_proc_task(inode);
+ 	struct nsproxy *nsp;
+ 	struct mnt_namespace *ns = NULL;
++	struct fs_struct *fs = NULL;
++	struct path root;
+ 	struct proc_mounts *p;
+ 	int ret = -EINVAL;
+ 
+@@ -525,40 +522,61 @@ static int mounts_open(struct inode *inode, struct file *file)
+ 				get_mnt_ns(ns);
+ 		}
+ 		rcu_read_unlock();
+-
++		if (ns)
++			fs = get_fs_struct(task);
+ 		put_task_struct(task);
+ 	}
+ 
+-	if (ns) {
+-		ret = -ENOMEM;
+-		p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
+-		if (p) {
+-			file->private_data = &p->m;
+-			ret = seq_open(file, &mounts_op);
+-			if (!ret) {
+-				p->m.private = ns;
+-				p->event = ns->event;
+-				return 0;
+-			}
+-			kfree(p);
+-		}
+-		put_mnt_ns(ns);
+-	}
++	if (!ns)
++		goto err;
++	if (!fs)
++		goto err_put_ns;
++
++	read_lock(&fs->lock);
++	root = fs->root;
++	path_get(&root);
++	read_unlock(&fs->lock);
++	put_fs_struct(fs);
++
++	ret = -ENOMEM;
++	p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
++	if (!p)
++		goto err_put_path;
++
++	file->private_data = &p->m;
++	ret = seq_open(file, op);
++	if (ret)
++		goto err_free;
++
++	p->m.private = p;
++	p->ns = ns;
++	p->root = root;
++	p->event = ns->event;
++
++	return 0;
++
++ err_free:
++	kfree(p);
++ err_put_path:
++	path_put(&root);
++ err_put_ns:
++	put_mnt_ns(ns);
++ err:
+ 	return ret;
+ }
+ 
+ static int mounts_release(struct inode *inode, struct file *file)
+ {
+-	struct seq_file *m = file->private_data;
+-	struct mnt_namespace *ns = m->private;
+-	put_mnt_ns(ns);
++	struct proc_mounts *p = file->private_data;
++	path_put(&p->root);
++	put_mnt_ns(p->ns);
+ 	return seq_release(inode, file);
+ }
+ 
+ static unsigned mounts_poll(struct file *file, poll_table *wait)
+ {
+ 	struct proc_mounts *p = file->private_data;
+-	struct mnt_namespace *ns = p->m.private;
++	struct mnt_namespace *ns = p->ns;
+ 	unsigned res = 0;
+ 
+ 	poll_wait(file, &ns->poll, wait);
+@@ -573,6 +591,11 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
+ 	return res;
+ }
+ 
++static int mounts_open(struct inode *inode, struct file *file)
++{
++	return mounts_open_common(inode, file, &mounts_op);
++}
++
+ static const struct file_operations proc_mounts_operations = {
+ 	.open		= mounts_open,
+ 	.read		= seq_read,
+@@ -581,38 +604,22 @@ static const struct file_operations proc_mounts_operations = {
+ 	.poll		= mounts_poll,
+ };
+ 
+-extern const struct seq_operations mountstats_op;
+-static int mountstats_open(struct inode *inode, struct file *file)
++static int mountinfo_open(struct inode *inode, struct file *file)
+ {
+-	int ret = seq_open(file, &mountstats_op);
+-
+-	if (!ret) {
+-		struct seq_file *m = file->private_data;
+-		struct nsproxy *nsp;
+-		struct mnt_namespace *mnt_ns = NULL;
+-		struct task_struct *task = get_proc_task(inode);
+-
+-		if (task) {
+-			rcu_read_lock();
+-			nsp = task_nsproxy(task);
+-			if (nsp) {
+-				mnt_ns = nsp->mnt_ns;
+-				if (mnt_ns)
+-					get_mnt_ns(mnt_ns);
+-			}
+-			rcu_read_unlock();
++	return mounts_open_common(inode, file, &mountinfo_op);
++}
+ 
+-			put_task_struct(task);
+-		}
++static const struct file_operations proc_mountinfo_operations = {
++	.open		= mountinfo_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= mounts_release,
++	.poll		= mounts_poll,
++};
+ 
+-		if (mnt_ns)
+-			m->private = mnt_ns;
+-		else {
+-			seq_release(inode, file);
+-			ret = -EINVAL;
+-		}
+-	}
+-	return ret;
++static int mountstats_open(struct inode *inode, struct file *file)
++{
++	return mounts_open_common(inode, file, &mountstats_op);
+ }
+ 
+ static const struct file_operations proc_mountstats_operations = {
+@@ -1626,7 +1633,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
+ 	unsigned int fd, ino;
+ 	int retval;
+ 	struct files_struct * files;
+-	struct fdtable *fdt;
+ 
+ 	retval = -ENOENT;
+ 	if (!p)
+@@ -1649,9 +1655,8 @@ static int proc_readfd_common(struct file * filp, void * dirent,
+ 			if (!files)
+ 				goto out;
+ 			rcu_read_lock();
+-			fdt = files_fdtable(files);
+ 			for (fd = filp->f_pos-2;
+-			     fd < fdt->max_fds;
++			     fd < files_fdtable(files)->max_fds;
+ 			     fd++, filp->f_pos++) {
+ 				char name[PROC_NUMBUF];
+ 				int len;
+@@ -2311,6 +2316,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+ 	LNK("root",       root),
+ 	LNK("exe",        exe),
+ 	REG("mounts",     S_IRUGO, mounts),
++	REG("mountinfo",  S_IRUGO, mountinfo),
+ 	REG("mountstats", S_IRUSR, mountstats),
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+ 	REG("clear_refs", S_IWUSR, clear_refs),
+@@ -2643,6 +2649,7 @@ static const struct pid_entry tid_base_stuff[] = {
+ 	LNK("root",      root),
+ 	LNK("exe",       exe),
+ 	REG("mounts",    S_IRUGO, mounts),
++	REG("mountinfo",  S_IRUGO, mountinfo),
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+ 	REG("clear_refs", S_IWUSR, clear_refs),
+ 	REG("smaps",     S_IRUGO, smaps),
+diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
+index 4caa5f7..13cd783 100644
+--- a/fs/proc/proc_net.c
++++ b/fs/proc/proc_net.c
+@@ -44,7 +44,9 @@ int seq_open_net(struct inode *ino, struct file *f,
+ 		put_net(net);
+ 		return -ENOMEM;
+ 	}
++#ifdef CONFIG_NET_NS
+ 	p->net = net;
++#endif
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(seq_open_net);
+@@ -52,12 +54,10 @@ EXPORT_SYMBOL_GPL(seq_open_net);
+ int seq_release_net(struct inode *ino, struct file *f)
+ {
+ 	struct seq_file *seq;
+-	struct seq_net_private *p;
+ 
+ 	seq = f->private_data;
+-	p = seq->private;
+ 
+-	put_net(p->net);
++	put_net(seq_file_net(seq));
+ 	seq_release_private(ino, f);
+ 	return 0;
+ }
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 49a9871..f0d1240 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -33,7 +33,7 @@ EXPORT_SYMBOL(generic_ro_fops);
+ 
+ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
+ {
+-	long long retval;
++	loff_t retval;
+ 	struct inode *inode = file->f_mapping->host;
+ 
+ 	mutex_lock(&inode->i_mutex);
+@@ -60,7 +60,7 @@ EXPORT_SYMBOL(generic_file_llseek);
+ 
+ loff_t remote_llseek(struct file *file, loff_t offset, int origin)
+ {
+-	long long retval;
++	loff_t retval;
+ 
+ 	lock_kernel();
+ 	switch (origin) {
+@@ -91,7 +91,7 @@ EXPORT_SYMBOL(no_llseek);
+ 
+ loff_t default_llseek(struct file *file, loff_t offset, int origin)
+ {
+-	long long retval;
++	loff_t retval;
+ 
+ 	lock_kernel();
+ 	switch (origin) {
+diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
+index e0f0f09..74363a7 100644
+--- a/fs/reiserfs/ioctl.c
++++ b/fs/reiserfs/ioctl.c
+@@ -4,6 +4,7 @@
+ 
+ #include <linux/capability.h>
+ #include <linux/fs.h>
++#include <linux/mount.h>
+ #include <linux/reiserfs_fs.h>
+ #include <linux/time.h>
+ #include <asm/uaccess.h>
+@@ -25,6 +26,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ 		   unsigned long arg)
+ {
+ 	unsigned int flags;
++	int err = 0;
+ 
+ 	switch (cmd) {
+ 	case REISERFS_IOC_UNPACK:
+@@ -48,50 +50,67 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ 			if (!reiserfs_attrs(inode->i_sb))
+ 				return -ENOTTY;
+ 
+-			if (IS_RDONLY(inode))
+-				return -EROFS;
++			err = mnt_want_write(filp->f_path.mnt);
++			if (err)
++				return err;
+ 
+-			if (!is_owner_or_cap(inode))
+-				return -EPERM;
+-
+-			if (get_user(flags, (int __user *)arg))
+-				return -EFAULT;
+-
+-			/* Is it quota file? Do not allow user to mess with it. */
+-			if (IS_NOQUOTA(inode))
+-				return -EPERM;
++			if (!is_owner_or_cap(inode)) {
++				err = -EPERM;
++				goto setflags_out;
++			}
++			if (get_user(flags, (int __user *)arg)) {
++				err = -EFAULT;
++				goto setflags_out;
++			}
++			/*
++			 * Is it quota file? Do not allow user to mess with it
++			 */
++			if (IS_NOQUOTA(inode)) {
++				err = -EPERM;
++				goto setflags_out;
++			}
+ 			if (((flags ^ REISERFS_I(inode)->
+ 			      i_attrs) & (REISERFS_IMMUTABLE_FL |
+ 					  REISERFS_APPEND_FL))
+-			    && !capable(CAP_LINUX_IMMUTABLE))
+-				return -EPERM;
+-
++			    && !capable(CAP_LINUX_IMMUTABLE)) {
++				err = -EPERM;
++				goto setflags_out;
++			}
+ 			if ((flags & REISERFS_NOTAIL_FL) &&
+ 			    S_ISREG(inode->i_mode)) {
+ 				int result;
+ 
+ 				result = reiserfs_unpack(inode, filp);
+-				if (result)
+-					return result;
++				if (result) {
++					err = result;
++					goto setflags_out;
++				}
+ 			}
+ 			sd_attrs_to_i_attrs(flags, inode);
+ 			REISERFS_I(inode)->i_attrs = flags;
+ 			inode->i_ctime = CURRENT_TIME_SEC;
+ 			mark_inode_dirty(inode);
+-			return 0;
++setflags_out:
++			mnt_drop_write(filp->f_path.mnt);
++			return err;
+ 		}
+ 	case REISERFS_IOC_GETVERSION:
+ 		return put_user(inode->i_generation, (int __user *)arg);
+ 	case REISERFS_IOC_SETVERSION:
+ 		if (!is_owner_or_cap(inode))
+ 			return -EPERM;
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+-		if (get_user(inode->i_generation, (int __user *)arg))
+-			return -EFAULT;
++		err = mnt_want_write(filp->f_path.mnt);
++		if (err)
++			return err;
++		if (get_user(inode->i_generation, (int __user *)arg)) {
++			err = -EFAULT;
++			goto setversion_out;
++		}
+ 		inode->i_ctime = CURRENT_TIME_SEC;
+ 		mark_inode_dirty(inode);
+-		return 0;
++setversion_out:
++		mnt_drop_write(filp->f_path.mnt);
++		return err;
+ 	default:
+ 		return -ENOTTY;
+ 	}
+diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
+index bb05a3e..060eb3f 100644
+--- a/fs/reiserfs/journal.c
++++ b/fs/reiserfs/journal.c
+@@ -38,7 +38,7 @@
+ #include <asm/system.h>
+ 
+ #include <linux/time.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ 
+ #include <linux/vmalloc.h>
+ #include <linux/reiserfs_fs.h>
+diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
+index 344b9b9..d7c4935 100644
+--- a/fs/reiserfs/xattr.c
++++ b/fs/reiserfs/xattr.c
+@@ -44,7 +44,6 @@
+ #include <net/checksum.h>
+ #include <linux/smp_lock.h>
+ #include <linux/stat.h>
+-#include <asm/semaphore.h>
+ 
+ #define FL_READONLY 128
+ #define FL_DIR_SEM_HELD 256
+diff --git a/fs/select.c b/fs/select.c
+index 5633fe9..00f58c5 100644
+--- a/fs/select.c
++++ b/fs/select.c
+@@ -260,7 +260,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
+ 		wait = NULL;
+ 		if (retval || !*timeout || signal_pending(current))
+ 			break;
+-		if(table.error) {
++		if (table.error) {
+ 			retval = table.error;
+ 			break;
+ 		}
+diff --git a/fs/seq_file.c b/fs/seq_file.c
+index 8537702..3f54dbd 100644
+--- a/fs/seq_file.c
++++ b/fs/seq_file.c
+@@ -25,6 +25,7 @@
+  *	into the buffer.  In case of error ->start() and ->next() return
+  *	ERR_PTR(error).  In the end of sequence they return %NULL. ->show()
+  *	returns 0 in case of success and negative number in case of error.
++ *	Returning SEQ_SKIP means "discard this element and move on".
+  */
+ int seq_open(struct file *file, const struct seq_operations *op)
+ {
+@@ -114,8 +115,10 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+ 		if (!p || IS_ERR(p))
+ 			break;
+ 		err = m->op->show(m, p);
+-		if (err)
++		if (err < 0)
+ 			break;
++		if (unlikely(err))
++			m->count = 0;
+ 		if (m->count < m->size)
+ 			goto Fill;
+ 		m->op->stop(m, p);
+@@ -140,9 +143,10 @@ Fill:
+ 			break;
+ 		}
+ 		err = m->op->show(m, p);
+-		if (err || m->count == m->size) {
++		if (m->count == m->size || err) {
+ 			m->count = offs;
+-			break;
++			if (likely(err <= 0))
++				break;
+ 		}
+ 		pos = next;
+ 	}
+@@ -199,8 +203,12 @@ static int traverse(struct seq_file *m, loff_t offset)
+ 		if (IS_ERR(p))
+ 			break;
+ 		error = m->op->show(m, p);
+-		if (error)
++		if (error < 0)
+ 			break;
++		if (unlikely(error)) {
++			error = 0;
++			m->count = 0;
++		}
+ 		if (m->count == m->size)
+ 			goto Eoverflow;
+ 		if (pos + m->count > offset) {
+@@ -239,7 +247,7 @@ Eoverflow:
+ loff_t seq_lseek(struct file *file, loff_t offset, int origin)
+ {
+ 	struct seq_file *m = (struct seq_file *)file->private_data;
+-	long long retval = -EINVAL;
++	loff_t retval = -EINVAL;
+ 
+ 	mutex_lock(&m->lock);
+ 	m->version = file->f_version;
+@@ -342,28 +350,40 @@ int seq_printf(struct seq_file *m, const char *f, ...)
+ }
+ EXPORT_SYMBOL(seq_printf);
+ 
++static char *mangle_path(char *s, char *p, char *esc)
++{
++	while (s <= p) {
++		char c = *p++;
++		if (!c) {
++			return s;
++		} else if (!strchr(esc, c)) {
++			*s++ = c;
++		} else if (s + 4 > p) {
++			break;
++		} else {
++			*s++ = '\\';
++			*s++ = '0' + ((c & 0300) >> 6);
++			*s++ = '0' + ((c & 070) >> 3);
++			*s++ = '0' + (c & 07);
++		}
++	}
++	return NULL;
++}
++
++/*
++ * return the absolute path of 'dentry' residing in mount 'mnt'.
++ */
+ int seq_path(struct seq_file *m, struct path *path, char *esc)
+ {
+ 	if (m->count < m->size) {
+ 		char *s = m->buf + m->count;
+ 		char *p = d_path(path, s, m->size - m->count);
+ 		if (!IS_ERR(p)) {
+-			while (s <= p) {
+-				char c = *p++;
+-				if (!c) {
+-					p = m->buf + m->count;
+-					m->count = s - m->buf;
+-					return s - p;
+-				} else if (!strchr(esc, c)) {
+-					*s++ = c;
+-				} else if (s + 4 > p) {
+-					break;
+-				} else {
+-					*s++ = '\\';
+-					*s++ = '0' + ((c & 0300) >> 6);
+-					*s++ = '0' + ((c & 070) >> 3);
+-					*s++ = '0' + (c & 07);
+-				}
++			s = mangle_path(s, p, esc);
++			if (s) {
++				p = m->buf + m->count;
++				m->count = s - m->buf;
++				return s - p;
+ 			}
+ 		}
+ 	}
+@@ -372,6 +392,57 @@ int seq_path(struct seq_file *m, struct path *path, char *esc)
+ }
+ EXPORT_SYMBOL(seq_path);
+ 
++/*
++ * Same as seq_path, but relative to supplied root.
++ *
++ * root may be changed, see __d_path().
++ */
++int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
++		  char *esc)
++{
++	int err = -ENAMETOOLONG;
++	if (m->count < m->size) {
++		char *s = m->buf + m->count;
++		char *p;
++
++		spin_lock(&dcache_lock);
++		p = __d_path(path, root, s, m->size - m->count);
++		spin_unlock(&dcache_lock);
++		err = PTR_ERR(p);
++		if (!IS_ERR(p)) {
++			s = mangle_path(s, p, esc);
++			if (s) {
++				p = m->buf + m->count;
++				m->count = s - m->buf;
++				return 0;
++			}
++		}
++	}
++	m->count = m->size;
++	return err;
++}
++
++/*
++ * returns the path of the 'dentry' from the root of its filesystem.
++ */
++int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc)
++{
++	if (m->count < m->size) {
++		char *s = m->buf + m->count;
++		char *p = dentry_path(dentry, s, m->size - m->count);
++		if (!IS_ERR(p)) {
++			s = mangle_path(s, p, esc);
++			if (s) {
++				p = m->buf + m->count;
++				m->count = s - m->buf;
++				return s - p;
++			}
++		}
++	}
++	m->count = m->size;
++	return -1;
++}
++
+ static void *single_start(struct seq_file *p, loff_t *pos)
+ {
+ 	return NULL + (*pos == 0);
+diff --git a/fs/super.c b/fs/super.c
+index 09008db..4798350 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -37,7 +37,9 @@
+ #include <linux/idr.h>
+ #include <linux/kobject.h>
+ #include <linux/mutex.h>
++#include <linux/file.h>
+ #include <asm/uaccess.h>
++#include "internal.h"
+ 
+ 
+ LIST_HEAD(super_blocks);
+@@ -567,10 +569,29 @@ static void mark_files_ro(struct super_block *sb)
+ {
+ 	struct file *f;
+ 
++retry:
+ 	file_list_lock();
+ 	list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
+-		if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f))
+-			f->f_mode &= ~FMODE_WRITE;
++		struct vfsmount *mnt;
++		if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
++		       continue;
++		if (!file_count(f))
++			continue;
++		if (!(f->f_mode & FMODE_WRITE))
++			continue;
++		f->f_mode &= ~FMODE_WRITE;
++		if (file_check_writeable(f) != 0)
++			continue;
++		file_release_write(f);
++		mnt = mntget(f->f_path.mnt);
++		file_list_unlock();
++		/*
++		 * This can sleep, so we can't hold
++		 * the file_list_lock() spinlock.
++		 */
++		mnt_drop_write(mnt);
++		mntput(mnt);
++		goto retry;
+ 	}
+ 	file_list_unlock();
+ }
+diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
+index 4948d9b..a1c3a1f 100644
+--- a/fs/sysfs/dir.c
++++ b/fs/sysfs/dir.c
+@@ -20,6 +20,7 @@
+ #include <linux/idr.h>
+ #include <linux/completion.h>
+ #include <linux/mutex.h>
++#include <linux/slab.h>
+ #include "sysfs.h"
+ 
+ DEFINE_MUTEX(sysfs_mutex);
+diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
+index baa663e..ade9a7e 100644
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -13,6 +13,7 @@
+ #include <linux/module.h>
+ #include <linux/kobject.h>
+ #include <linux/kallsyms.h>
++#include <linux/slab.h>
+ #include <linux/namei.h>
+ #include <linux/poll.h>
+ #include <linux/list.h>
+@@ -128,7 +129,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ 	ssize_t retval = 0;
+ 
+ 	mutex_lock(&buffer->mutex);
+-	if (buffer->needs_read_fill) {
++	if (buffer->needs_read_fill || *ppos == 0) {
+ 		retval = fill_read_buffer(file->f_path.dentry,buffer);
+ 		if (retval)
+ 			goto out;
+@@ -409,8 +410,7 @@ static int sysfs_release(struct inode *inode, struct file *filp)
+  * return POLLERR|POLLPRI, and select will return the fd whether
+  * it is waiting for read, write, or exceptions.
+  * Once poll/select indicates that the value has changed, you
+- * need to close and re-open the file, as simply seeking and reading
+- * again will not get new data, or reset the state of 'poll'.
++ * need to close and re-open the file, or seek to 0 and read again.
+  * Reminder: this only works for attributes which actively support
+  * it, and it is not possible to test an attribute from userspace
+  * to see if it supports poll (Neither 'poll' nor 'select' return
+diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
+index 5f66c44..817f596 100644
+--- a/fs/sysfs/symlink.c
++++ b/fs/sysfs/symlink.c
+@@ -87,7 +87,14 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
+ 
+ void sysfs_remove_link(struct kobject * kobj, const char * name)
+ {
+-	sysfs_hash_and_remove(kobj->sd, name);
++	struct sysfs_dirent *parent_sd = NULL;
++
++	if (!kobj)
++		parent_sd = &sysfs_root;
++	else
++		parent_sd = kobj->sd;
++
++	sysfs_hash_and_remove(parent_sd, name);
+ }
+ 
+ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
+diff --git a/fs/udf/Makefile b/fs/udf/Makefile
+index be845e7..0d4503f 100644
+--- a/fs/udf/Makefile
++++ b/fs/udf/Makefile
+@@ -6,4 +6,4 @@ obj-$(CONFIG_UDF_FS) += udf.o
+ 
+ udf-objs     := balloc.o dir.o file.o ialloc.o inode.o lowlevel.o namei.o \
+ 		partition.o super.o truncate.o symlink.o fsync.o \
+-		crc.o directory.o misc.o udftime.o unicode.o
++		directory.o misc.o udftime.o unicode.o
+diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
+index f855dcb..1b809bd 100644
+--- a/fs/udf/balloc.c
++++ b/fs/udf/balloc.c
+@@ -149,8 +149,7 @@ static bool udf_add_free_space(struct udf_sb_info *sbi,
+ 		return false;
+ 
+ 	lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
+-	lvid->freeSpaceTable[partition] = cpu_to_le32(le32_to_cpu(
+-					lvid->freeSpaceTable[partition]) + cnt);
++	le32_add_cpu(&lvid->freeSpaceTable[partition], cnt);
+ 	return true;
+ }
+ 
+@@ -589,10 +588,8 @@ static void udf_table_free_blocks(struct super_block *sb,
+ 					sptr = oepos.bh->b_data + epos.offset;
+ 					aed = (struct allocExtDesc *)
+ 						oepos.bh->b_data;
+-					aed->lengthAllocDescs =
+-						cpu_to_le32(le32_to_cpu(
+-							aed->lengthAllocDescs) +
+-								adsize);
++					le32_add_cpu(&aed->lengthAllocDescs,
++							adsize);
+ 				} else {
+ 					sptr = iinfo->i_ext.i_data +
+ 								epos.offset;
+@@ -645,9 +642,7 @@ static void udf_table_free_blocks(struct super_block *sb,
+ 				mark_inode_dirty(table);
+ 			} else {
+ 				aed = (struct allocExtDesc *)epos.bh->b_data;
+-				aed->lengthAllocDescs =
+-					cpu_to_le32(le32_to_cpu(
+-					    aed->lengthAllocDescs) + adsize);
++				le32_add_cpu(&aed->lengthAllocDescs, adsize);
+ 				udf_update_tag(epos.bh->b_data, epos.offset);
+ 				mark_buffer_dirty(epos.bh);
+ 			}
+diff --git a/fs/udf/crc.c b/fs/udf/crc.c
+deleted file mode 100644
+index b166129..0000000
+--- a/fs/udf/crc.c
++++ /dev/null
+@@ -1,172 +0,0 @@
+-/*
+- * crc.c
+- *
+- * PURPOSE
+- *	Routines to generate, calculate, and test a 16-bit CRC.
+- *
+- * DESCRIPTION
+- *	The CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories
+- *	and Ned W. Rhodes of Software Systems Group. It has been published in
+- *	"Design and Validation of Computer Protocols", Prentice Hall,
+- *	Englewood Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4.
+- *
+- *	Copyright is held by AT&T.
+- *
+- *	AT&T gives permission for the free use of the CRC source code.
+- *
+- * COPYRIGHT
+- *	This file is distributed under the terms of the GNU General Public
+- *	License (GPL). Copies of the GPL can be obtained from:
+- *		ftp://prep.ai.mit.edu/pub/gnu/GPL
+- *	Each contributing author retains all rights to their own work.
+- */
+-
+-#include "udfdecl.h"
+-
+-static uint16_t crc_table[256] = {
+-	0x0000U, 0x1021U, 0x2042U, 0x3063U, 0x4084U, 0x50a5U, 0x60c6U, 0x70e7U,
+-	0x8108U, 0x9129U, 0xa14aU, 0xb16bU, 0xc18cU, 0xd1adU, 0xe1ceU, 0xf1efU,
+-	0x1231U, 0x0210U, 0x3273U, 0x2252U, 0x52b5U, 0x4294U, 0x72f7U, 0x62d6U,
+-	0x9339U, 0x8318U, 0xb37bU, 0xa35aU, 0xd3bdU, 0xc39cU, 0xf3ffU, 0xe3deU,
+-	0x2462U, 0x3443U, 0x0420U, 0x1401U, 0x64e6U, 0x74c7U, 0x44a4U, 0x5485U,
+-	0xa56aU, 0xb54bU, 0x8528U, 0x9509U, 0xe5eeU, 0xf5cfU, 0xc5acU, 0xd58dU,
+-	0x3653U, 0x2672U, 0x1611U, 0x0630U, 0x76d7U, 0x66f6U, 0x5695U, 0x46b4U,
+-	0xb75bU, 0xa77aU, 0x9719U, 0x8738U, 0xf7dfU, 0xe7feU, 0xd79dU, 0xc7bcU,
+-	0x48c4U, 0x58e5U, 0x6886U, 0x78a7U, 0x0840U, 0x1861U, 0x2802U, 0x3823U,
+-	0xc9ccU, 0xd9edU, 0xe98eU, 0xf9afU, 0x8948U, 0x9969U, 0xa90aU, 0xb92bU,
+-	0x5af5U, 0x4ad4U, 0x7ab7U, 0x6a96U, 0x1a71U, 0x0a50U, 0x3a33U, 0x2a12U,
+-	0xdbfdU, 0xcbdcU, 0xfbbfU, 0xeb9eU, 0x9b79U, 0x8b58U, 0xbb3bU, 0xab1aU,
+-	0x6ca6U, 0x7c87U, 0x4ce4U, 0x5cc5U, 0x2c22U, 0x3c03U, 0x0c60U, 0x1c41U,
+-	0xedaeU, 0xfd8fU, 0xcdecU, 0xddcdU, 0xad2aU, 0xbd0bU, 0x8d68U, 0x9d49U,
+-	0x7e97U, 0x6eb6U, 0x5ed5U, 0x4ef4U, 0x3e13U, 0x2e32U, 0x1e51U, 0x0e70U,
+-	0xff9fU, 0xefbeU, 0xdfddU, 0xcffcU, 0xbf1bU, 0xaf3aU, 0x9f59U, 0x8f78U,
+-	0x9188U, 0x81a9U, 0xb1caU, 0xa1ebU, 0xd10cU, 0xc12dU, 0xf14eU, 0xe16fU,
+-	0x1080U, 0x00a1U, 0x30c2U, 0x20e3U, 0x5004U, 0x4025U, 0x7046U, 0x6067U,
+-	0x83b9U, 0x9398U, 0xa3fbU, 0xb3daU, 0xc33dU, 0xd31cU, 0xe37fU, 0xf35eU,
+-	0x02b1U, 0x1290U, 0x22f3U, 0x32d2U, 0x4235U, 0x5214U, 0x6277U, 0x7256U,
+-	0xb5eaU, 0xa5cbU, 0x95a8U, 0x8589U, 0xf56eU, 0xe54fU, 0xd52cU, 0xc50dU,
+-	0x34e2U, 0x24c3U, 0x14a0U, 0x0481U, 0x7466U, 0x6447U, 0x5424U, 0x4405U,
+-	0xa7dbU, 0xb7faU, 0x8799U, 0x97b8U, 0xe75fU, 0xf77eU, 0xc71dU, 0xd73cU,
+-	0x26d3U, 0x36f2U, 0x0691U, 0x16b0U, 0x6657U, 0x7676U, 0x4615U, 0x5634U,
+-	0xd94cU, 0xc96dU, 0xf90eU, 0xe92fU, 0x99c8U, 0x89e9U, 0xb98aU, 0xa9abU,
+-	0x5844U, 0x4865U, 0x7806U, 0x6827U, 0x18c0U, 0x08e1U, 0x3882U, 0x28a3U,
+-	0xcb7dU, 0xdb5cU, 0xeb3fU, 0xfb1eU, 0x8bf9U, 0x9bd8U, 0xabbbU, 0xbb9aU,
+-	0x4a75U, 0x5a54U, 0x6a37U, 0x7a16U, 0x0af1U, 0x1ad0U, 0x2ab3U, 0x3a92U,
+-	0xfd2eU, 0xed0fU, 0xdd6cU, 0xcd4dU, 0xbdaaU, 0xad8bU, 0x9de8U, 0x8dc9U,
+-	0x7c26U, 0x6c07U, 0x5c64U, 0x4c45U, 0x3ca2U, 0x2c83U, 0x1ce0U, 0x0cc1U,
+-	0xef1fU, 0xff3eU, 0xcf5dU, 0xdf7cU, 0xaf9bU, 0xbfbaU, 0x8fd9U, 0x9ff8U,
+-	0x6e17U, 0x7e36U, 0x4e55U, 0x5e74U, 0x2e93U, 0x3eb2U, 0x0ed1U, 0x1ef0U
+-};
+-
+-/*
+- * udf_crc
+- *
+- * PURPOSE
+- *	Calculate a 16-bit CRC checksum using ITU-T V.41 polynomial.
+- *
+- * DESCRIPTION
+- *	The OSTA-UDF(tm) 1.50 standard states that using CRCs is mandatory.
+- *	The polynomial used is:	x^16 + x^12 + x^15 + 1
+- *
+- * PRE-CONDITIONS
+- *	data		Pointer to the data block.
+- *	size		Size of the data block.
+- *
+- * POST-CONDITIONS
+- *	<return>	CRC of the data block.
+- *
+- * HISTORY
+- *	July 21, 1997 - Andrew E. Mileski
+- *	Adapted from OSTA-UDF(tm) 1.50 standard.
+- */
+-uint16_t udf_crc(uint8_t *data, uint32_t size, uint16_t crc)
+-{
+-	while (size--)
+-		crc = crc_table[(crc >> 8 ^ *(data++)) & 0xffU] ^ (crc << 8);
+-
+-	return crc;
+-}
+-
+-/****************************************************************************/
+-#if defined(TEST)
+-
+-/*
+- * PURPOSE
+- *	Test udf_crc()
+- *
+- * HISTORY
+- *	July 21, 1997 - Andrew E. Mileski
+- *	Adapted from OSTA-UDF(tm) 1.50 standard.
+- */
+-
+-unsigned char bytes[] = { 0x70U, 0x6AU, 0x77U };
+-
+-int main(void)
+-{
+-	unsigned short x;
+-
+-	x = udf_crc(bytes, sizeof bytes);
+-	printf("udf_crc: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
+-
+-	return 0;
+-}
+-
+-#endif /* defined(TEST) */
+-
+-/****************************************************************************/
+-#if defined(GENERATE)
+-
+-/*
+- * PURPOSE
+- *	Generate a table for fast 16-bit CRC calculations (any polynomial).
+- *
+- * DESCRIPTION
+- *	The ITU-T V.41 polynomial is 010041.
+- *
+- * HISTORY
+- *	July 21, 1997 - Andrew E. Mileski
+- *	Adapted from OSTA-UDF(tm) 1.50 standard.
+- */
+-
+-#include <stdio.h>
+-
+-int main(int argc, char **argv)
+-{
+-	unsigned long crc, poly;
+-	int n, i;
+-
+-	/* Get the polynomial */
+-	sscanf(argv[1], "%lo", &poly);
+-	if (poly & 0xffff0000U) {
+-		fprintf(stderr, "polynomial is too large\en");
+-		exit(1);
+-	}
+-
+-	printf("/* CRC 0%o */\n", poly);
+-
+-	/* Create a table */
+-	printf("static unsigned short crc_table[256] = {\n");
+-	for (n = 0; n < 256; n++) {
+-		if (n % 8 == 0)
+-			printf("\t");
+-		crc = n << 8;
+-		for (i = 0; i < 8; i++) {
+-			if (crc & 0x8000U)
+-				crc = (crc << 1) ^ poly;
+-			else
+-				crc <<= 1;
+-			crc &= 0xFFFFU;
+-		}
+-		if (n == 255)
+-			printf("0x%04xU ", crc);
+-		else
+-			printf("0x%04xU, ", crc);
+-		if (n % 8 == 7)
+-			printf("\n");
+-	}
+-	printf("};\n");
+-
+-	return 0;
+-}
+-
+-#endif /* defined(GENERATE) */
+diff --git a/fs/udf/dir.c b/fs/udf/dir.c
+index 8d8643a..62dc270 100644
+--- a/fs/udf/dir.c
++++ b/fs/udf/dir.c
+@@ -39,13 +39,13 @@
+ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ 			  filldir_t filldir, void *dirent)
+ {
+-	struct udf_fileident_bh fibh;
++	struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};
+ 	struct fileIdentDesc *fi = NULL;
+ 	struct fileIdentDesc cfi;
+ 	int block, iblock;
+ 	loff_t nf_pos = (filp->f_pos - 1) << 2;
+ 	int flen;
+-	char fname[UDF_NAME_LEN];
++	char *fname = NULL;
+ 	char *nameptr;
+ 	uint16_t liu;
+ 	uint8_t lfi;
+@@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ 	kernel_lb_addr eloc;
+ 	uint32_t elen;
+ 	sector_t offset;
+-	int i, num;
++	int i, num, ret = 0;
+ 	unsigned int dt_type;
+ 	struct extent_position epos = { NULL, 0, {0, 0} };
+ 	struct udf_inode_info *iinfo;
+ 
+ 	if (nf_pos >= size)
+-		return 0;
++		goto out;
++
++	fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
++	if (!fname) {
++		ret = -ENOMEM;
++		goto out;
++	}
+ 
+ 	if (nf_pos == 0)
+ 		nf_pos = udf_ext0_offset(dir);
+ 
+ 	fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
+ 	iinfo = UDF_I(dir);
+-	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
+-		fibh.sbh = fibh.ebh = NULL;
+-	} else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
+-			      &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
++	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
++		if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
++		    &epos, &eloc, &elen, &offset)
++		    != (EXT_RECORDED_ALLOCATED >> 30)) {
++			ret = -ENOENT;
++			goto out;
++		}
+ 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
+ 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
+ 			if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+@@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ 		}
+ 
+ 		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
+-			brelse(epos.bh);
+-			return -EIO;
++			ret = -EIO;
++			goto out;
+ 		}
+ 
+ 		if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) {
+@@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ 					brelse(bha[i]);
+ 			}
+ 		}
+-	} else {
+-		brelse(epos.bh);
+-		return -ENOENT;
+ 	}
+ 
+ 	while (nf_pos < size) {
+@@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ 
+ 		fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
+ 					&elen, &offset);
+-		if (!fi) {
+-			if (fibh.sbh != fibh.ebh)
+-				brelse(fibh.ebh);
+-			brelse(fibh.sbh);
+-			brelse(epos.bh);
+-			return 0;
+-		}
++		if (!fi)
++			goto out;
+ 
+ 		liu = le16_to_cpu(cfi.lengthOfImpUse);
+ 		lfi = cfi.lengthFileIdent;
+@@ -167,53 +168,23 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ 			dt_type = DT_UNKNOWN;
+ 		}
+ 
+-		if (flen) {
+-			if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) {
+-				if (fibh.sbh != fibh.ebh)
+-					brelse(fibh.ebh);
+-				brelse(fibh.sbh);
+-				brelse(epos.bh);
+-	 			return 0;
+-			}
+-		}
++		if (flen && filldir(dirent, fname, flen, filp->f_pos,
++				    iblock, dt_type) < 0)
++			goto out;
+ 	} /* end while */
+ 
+ 	filp->f_pos = (nf_pos >> 2) + 1;
+ 
++out:
+ 	if (fibh.sbh != fibh.ebh)
+ 		brelse(fibh.ebh);
+ 	brelse(fibh.sbh);
+ 	brelse(epos.bh);
++	kfree(fname);
+ 
+-	return 0;
++	return ret;
+ }
+ 
+-/*
+- * udf_readdir
+- *
+- * PURPOSE
+- *	Read a directory entry.
+- *
+- * DESCRIPTION
+- *	Optional - sys_getdents() will return -ENOTDIR if this routine is not
+- *	available.
+- *
+- *	Refer to sys_getdents() in fs/readdir.c
+- *	sys_getdents() -> .
+- *
+- * PRE-CONDITIONS
+- *	filp			Pointer to directory file.
+- *	buf			Pointer to directory entry buffer.
+- *	filldir			Pointer to filldir function.
+- *
+- * POST-CONDITIONS
+- *	<return>		>=0 on success.
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
+- */
+-
+ static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+ 	struct inode *dir = filp->f_path.dentry->d_inode;
+diff --git a/fs/udf/ecma_167.h b/fs/udf/ecma_167.h
+index 5638771..a0974df 100644
+--- a/fs/udf/ecma_167.h
++++ b/fs/udf/ecma_167.h
+@@ -70,19 +70,6 @@ typedef struct {
+ 	uint8_t		microseconds;
+ } __attribute__ ((packed)) timestamp;
+ 
+-typedef struct {
+-	uint16_t	typeAndTimezone;
+-	int16_t		year;
+-	uint8_t		month;
+-	uint8_t		day;
+-	uint8_t		hour;
+-	uint8_t		minute;
+-	uint8_t		second;
+-	uint8_t		centiseconds;
+-	uint8_t		hundredsOfMicroseconds;
+-	uint8_t		microseconds;
+-} __attribute__ ((packed)) kernel_timestamp;
+-
+ /* Type and Time Zone (ECMA 167r3 1/7.3.1) */
+ #define TIMESTAMP_TYPE_MASK		0xF000
+ #define TIMESTAMP_TYPE_CUT		0x0000
+diff --git a/fs/udf/file.c b/fs/udf/file.c
+index 97c71ae..0ed6e14 100644
+--- a/fs/udf/file.c
++++ b/fs/udf/file.c
+@@ -27,7 +27,6 @@
+ 
+ #include "udfdecl.h"
+ #include <linux/fs.h>
+-#include <linux/udf_fs.h>
+ #include <asm/uaccess.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h> /* memset */
+@@ -144,40 +143,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ 	return retval;
+ }
+ 
+-/*
+- * udf_ioctl
+- *
+- * PURPOSE
+- *	Issue an ioctl.
+- *
+- * DESCRIPTION
+- *	Optional - sys_ioctl() will return -ENOTTY if this routine is not
+- *	available, and the ioctl cannot be handled without filesystem help.
+- *
+- *	sys_ioctl() handles these ioctls that apply only to regular files:
+- *		FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD
+- *	These ioctls are also handled by sys_ioctl():
+- *		FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC
+- *	All other ioctls are passed to the filesystem.
+- *
+- *	Refer to sys_ioctl() in fs/ioctl.c
+- *	sys_ioctl() -> .
+- *
+- * PRE-CONDITIONS
+- *	inode			Pointer to inode that ioctl was issued on.
+- *	filp			Pointer to file that ioctl was issued on.
+- *	cmd			The ioctl command.
+- *	arg			The ioctl argument [can be interpreted as a
+- *				user-space pointer if desired].
+- *
+- * POST-CONDITIONS
+- *	<return>		Success (>=0) or an error code (<=0) that
+- *				sys_ioctl() will return.
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
+- */
+ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ 	      unsigned long arg)
+ {
+@@ -225,18 +190,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ 	return result;
+ }
+ 
+-/*
+- * udf_release_file
+- *
+- * PURPOSE
+- *  Called when all references to the file are closed
+- *
+- * DESCRIPTION
+- *  Discard prealloced blocks
+- *
+- * HISTORY
+- *
+- */
+ static int udf_release_file(struct inode *inode, struct file *filp)
+ {
+ 	if (filp->f_mode & FMODE_WRITE) {
+diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
+index 8436031..eb9cfa2 100644
+--- a/fs/udf/ialloc.c
++++ b/fs/udf/ialloc.c
+@@ -21,7 +21,6 @@
+ #include "udfdecl.h"
+ #include <linux/fs.h>
+ #include <linux/quotaops.h>
+-#include <linux/udf_fs.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+ 
+@@ -47,11 +46,9 @@ void udf_free_inode(struct inode *inode)
+ 		struct logicalVolIntegrityDescImpUse *lvidiu =
+ 							udf_sb_lvidiu(sbi);
+ 		if (S_ISDIR(inode->i_mode))
+-			lvidiu->numDirs =
+-				cpu_to_le32(le32_to_cpu(lvidiu->numDirs) - 1);
++			le32_add_cpu(&lvidiu->numDirs, -1);
+ 		else
+-			lvidiu->numFiles =
+-				cpu_to_le32(le32_to_cpu(lvidiu->numFiles) - 1);
++			le32_add_cpu(&lvidiu->numFiles, -1);
+ 
+ 		mark_buffer_dirty(sbi->s_lvid_bh);
+ 	}
+@@ -105,11 +102,9 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
+ 		lvhd = (struct logicalVolHeaderDesc *)
+ 				(lvid->logicalVolContentsUse);
+ 		if (S_ISDIR(mode))
+-			lvidiu->numDirs =
+-				cpu_to_le32(le32_to_cpu(lvidiu->numDirs) + 1);
++			le32_add_cpu(&lvidiu->numDirs, 1);
+ 		else
+-			lvidiu->numFiles =
+-				cpu_to_le32(le32_to_cpu(lvidiu->numFiles) + 1);
++			le32_add_cpu(&lvidiu->numFiles, 1);
+ 		iinfo->i_unique = uniqueID = le64_to_cpu(lvhd->uniqueID);
+ 		if (!(++uniqueID & 0x00000000FFFFFFFFUL))
+ 			uniqueID += 16;
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index 24cfa55..6e74b11 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -37,6 +37,7 @@
+ #include <linux/buffer_head.h>
+ #include <linux/writeback.h>
+ #include <linux/slab.h>
++#include <linux/crc-itu-t.h>
+ 
+ #include "udf_i.h"
+ #include "udf_sb.h"
+@@ -66,22 +67,7 @@ static void udf_update_extents(struct inode *,
+ 			       struct extent_position *);
+ static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
+ 
+-/*
+- * udf_delete_inode
+- *
+- * PURPOSE
+- *	Clean-up before the specified inode is destroyed.
+- *
+- * DESCRIPTION
+- *	This routine is called when the kernel destroys an inode structure
+- *	ie. when iput() finds i_count == 0.
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
+- *
+- *  Called at the last iput() if i_nlink is zero.
+- */
++
+ void udf_delete_inode(struct inode *inode)
+ {
+ 	truncate_inode_pages(&inode->i_data, 0);
+@@ -323,9 +309,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
+ 
+ 	lock_kernel();
+ 
+-	if (block < 0)
+-		goto abort_negative;
+-
+ 	iinfo = UDF_I(inode);
+ 	if (block == iinfo->i_next_alloc_block + 1) {
+ 		iinfo->i_next_alloc_block++;
+@@ -347,10 +330,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
+ abort:
+ 	unlock_kernel();
+ 	return err;
+-
+-abort_negative:
+-	udf_warning(inode->i_sb, "udf_get_block", "block < 0");
+-	goto abort;
+ }
+ 
+ static struct buffer_head *udf_getblk(struct inode *inode, long block,
+@@ -1116,42 +1095,36 @@ static void __udf_read_inode(struct inode *inode)
+ 	fe = (struct fileEntry *)bh->b_data;
+ 
+ 	if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
+-		struct buffer_head *ibh = NULL, *nbh = NULL;
+-		struct indirectEntry *ie;
++		struct buffer_head *ibh;
+ 
+ 		ibh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 1,
+ 					&ident);
+-		if (ident == TAG_IDENT_IE) {
+-			if (ibh) {
+-				kernel_lb_addr loc;
+-				ie = (struct indirectEntry *)ibh->b_data;
+-
+-				loc = lelb_to_cpu(ie->indirectICB.extLocation);
+-
+-				if (ie->indirectICB.extLength &&
+-				    (nbh = udf_read_ptagged(inode->i_sb, loc, 0,
+-							    &ident))) {
+-					if (ident == TAG_IDENT_FE ||
+-					    ident == TAG_IDENT_EFE) {
+-						memcpy(&iinfo->i_location,
+-						       &loc,
+-						       sizeof(kernel_lb_addr));
+-						brelse(bh);
+-						brelse(ibh);
+-						brelse(nbh);
+-						__udf_read_inode(inode);
+-						return;
+-					} else {
+-						brelse(nbh);
+-						brelse(ibh);
+-					}
+-				} else {
++		if (ident == TAG_IDENT_IE && ibh) {
++			struct buffer_head *nbh = NULL;
++			kernel_lb_addr loc;
++			struct indirectEntry *ie;
++
++			ie = (struct indirectEntry *)ibh->b_data;
++			loc = lelb_to_cpu(ie->indirectICB.extLocation);
++
++			if (ie->indirectICB.extLength &&
++				(nbh = udf_read_ptagged(inode->i_sb, loc, 0,
++							&ident))) {
++				if (ident == TAG_IDENT_FE ||
++					ident == TAG_IDENT_EFE) {
++					memcpy(&iinfo->i_location,
++						&loc,
++						sizeof(kernel_lb_addr));
++					brelse(bh);
+ 					brelse(ibh);
++					brelse(nbh);
++					__udf_read_inode(inode);
++					return;
+ 				}
++				brelse(nbh);
+ 			}
+-		} else {
+-			brelse(ibh);
+ 		}
++		brelse(ibh);
+ 	} else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
+ 		printk(KERN_ERR "udf: unsupported strategy type: %d\n",
+ 		       le16_to_cpu(fe->icbTag.strategyType));
+@@ -1168,8 +1141,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ {
+ 	struct fileEntry *fe;
+ 	struct extendedFileEntry *efe;
+-	time_t convtime;
+-	long convtime_usec;
+ 	int offset;
+ 	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
+ 	struct udf_inode_info *iinfo = UDF_I(inode);
+@@ -1257,29 +1228,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ 		inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
+ 			(inode->i_sb->s_blocksize_bits - 9);
+ 
+-		if (udf_stamp_to_time(&convtime, &convtime_usec,
+-				      lets_to_cpu(fe->accessTime))) {
+-			inode->i_atime.tv_sec = convtime;
+-			inode->i_atime.tv_nsec = convtime_usec * 1000;
+-		} else {
++		if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime))
+ 			inode->i_atime = sbi->s_record_time;
+-		}
+ 
+-		if (udf_stamp_to_time(&convtime, &convtime_usec,
+-				      lets_to_cpu(fe->modificationTime))) {
+-			inode->i_mtime.tv_sec = convtime;
+-			inode->i_mtime.tv_nsec = convtime_usec * 1000;
+-		} else {
++		if (!udf_disk_stamp_to_time(&inode->i_mtime,
++					    fe->modificationTime))
+ 			inode->i_mtime = sbi->s_record_time;
+-		}
+ 
+-		if (udf_stamp_to_time(&convtime, &convtime_usec,
+-				      lets_to_cpu(fe->attrTime))) {
+-			inode->i_ctime.tv_sec = convtime;
+-			inode->i_ctime.tv_nsec = convtime_usec * 1000;
+-		} else {
++		if (!udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime))
+ 			inode->i_ctime = sbi->s_record_time;
+-		}
+ 
+ 		iinfo->i_unique = le64_to_cpu(fe->uniqueID);
+ 		iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
+@@ -1289,37 +1246,18 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ 		inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
+ 		    (inode->i_sb->s_blocksize_bits - 9);
+ 
+-		if (udf_stamp_to_time(&convtime, &convtime_usec,
+-				      lets_to_cpu(efe->accessTime))) {
+-			inode->i_atime.tv_sec = convtime;
+-			inode->i_atime.tv_nsec = convtime_usec * 1000;
+-		} else {
++		if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime))
+ 			inode->i_atime = sbi->s_record_time;
+-		}
+ 
+-		if (udf_stamp_to_time(&convtime, &convtime_usec,
+-				      lets_to_cpu(efe->modificationTime))) {
+-			inode->i_mtime.tv_sec = convtime;
+-			inode->i_mtime.tv_nsec = convtime_usec * 1000;
+-		} else {
++		if (!udf_disk_stamp_to_time(&inode->i_mtime,
++					    efe->modificationTime))
+ 			inode->i_mtime = sbi->s_record_time;
+-		}
+ 
+-		if (udf_stamp_to_time(&convtime, &convtime_usec,
+-				      lets_to_cpu(efe->createTime))) {
+-			iinfo->i_crtime.tv_sec = convtime;
+-			iinfo->i_crtime.tv_nsec = convtime_usec * 1000;
+-		} else {
++		if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime))
+ 			iinfo->i_crtime = sbi->s_record_time;
+-		}
+ 
+-		if (udf_stamp_to_time(&convtime, &convtime_usec,
+-				      lets_to_cpu(efe->attrTime))) {
+-			inode->i_ctime.tv_sec = convtime;
+-			inode->i_ctime.tv_nsec = convtime_usec * 1000;
+-		} else {
++		if (!udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime))
+ 			inode->i_ctime = sbi->s_record_time;
+-		}
+ 
+ 		iinfo->i_unique = le64_to_cpu(efe->uniqueID);
+ 		iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
+@@ -1338,6 +1276,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ 	case ICBTAG_FILE_TYPE_REALTIME:
+ 	case ICBTAG_FILE_TYPE_REGULAR:
+ 	case ICBTAG_FILE_TYPE_UNDEF:
++	case ICBTAG_FILE_TYPE_VAT20:
+ 		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+ 			inode->i_data.a_ops = &udf_adinicb_aops;
+ 		else
+@@ -1363,6 +1302,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ 		inode->i_op = &page_symlink_inode_operations;
+ 		inode->i_mode = S_IFLNK | S_IRWXUGO;
+ 		break;
++	case ICBTAG_FILE_TYPE_MAIN:
++		udf_debug("METADATA FILE-----\n");
++		break;
++	case ICBTAG_FILE_TYPE_MIRROR:
++		udf_debug("METADATA MIRROR FILE-----\n");
++		break;
++	case ICBTAG_FILE_TYPE_BITMAP:
++		udf_debug("METADATA BITMAP FILE-----\n");
++		break;
+ 	default:
+ 		printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown "
+ 				"file type=%d\n", inode->i_ino,
+@@ -1416,21 +1364,6 @@ static mode_t udf_convert_permissions(struct fileEntry *fe)
+ 	return mode;
+ }
+ 
+-/*
+- * udf_write_inode
+- *
+- * PURPOSE
+- *	Write out the specified inode.
+- *
+- * DESCRIPTION
+- *	This routine is called whenever an inode is synced.
+- *	Currently this routine is just a placeholder.
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
+- */
+-
+ int udf_write_inode(struct inode *inode, int sync)
+ {
+ 	int ret;
+@@ -1455,7 +1388,6 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ 	uint32_t udfperms;
+ 	uint16_t icbflags;
+ 	uint16_t crclen;
+-	kernel_timestamp cpu_time;
+ 	int err = 0;
+ 	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
+ 	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
+@@ -1488,9 +1420,9 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ 						iinfo->i_location.
+ 							logicalBlockNum);
+ 		use->descTag.descCRCLength = cpu_to_le16(crclen);
+-		use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use +
+-							   sizeof(tag), crclen,
+-							   0));
++		use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use +
++							   sizeof(tag),
++							   crclen));
+ 		use->descTag.tagChecksum = udf_tag_checksum(&use->descTag);
+ 
+ 		mark_buffer_dirty(bh);
+@@ -1558,12 +1490,9 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ 			(inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >>
+ 			(blocksize_bits - 9));
+ 
+-		if (udf_time_to_stamp(&cpu_time, inode->i_atime))
+-			fe->accessTime = cpu_to_lets(cpu_time);
+-		if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
+-			fe->modificationTime = cpu_to_lets(cpu_time);
+-		if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
+-			fe->attrTime = cpu_to_lets(cpu_time);
++		udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime);
++		udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime);
++		udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime);
+ 		memset(&(fe->impIdent), 0, sizeof(regid));
+ 		strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
+ 		fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
+@@ -1598,14 +1527,10 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ 		     iinfo->i_crtime.tv_nsec > inode->i_ctime.tv_nsec))
+ 			iinfo->i_crtime = inode->i_ctime;
+ 
+-		if (udf_time_to_stamp(&cpu_time, inode->i_atime))
+-			efe->accessTime = cpu_to_lets(cpu_time);
+-		if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
+-			efe->modificationTime = cpu_to_lets(cpu_time);
+-		if (udf_time_to_stamp(&cpu_time, iinfo->i_crtime))
+-			efe->createTime = cpu_to_lets(cpu_time);
+-		if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
+-			efe->attrTime = cpu_to_lets(cpu_time);
++		udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime);
++		udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime);
++		udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime);
++		udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime);
+ 
+ 		memset(&(efe->impIdent), 0, sizeof(regid));
+ 		strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
+@@ -1660,8 +1585,8 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ 	crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc -
+ 								sizeof(tag);
+ 	fe->descTag.descCRCLength = cpu_to_le16(crclen);
+-	fe->descTag.descCRC = cpu_to_le16(udf_crc((char *)fe + sizeof(tag),
+-						  crclen, 0));
++	fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(tag),
++						  crclen));
+ 	fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
+ 
+ 	/* write the data blocks */
+@@ -1778,9 +1703,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
+ 
+ 			if (epos->bh) {
+ 				aed = (struct allocExtDesc *)epos->bh->b_data;
+-				aed->lengthAllocDescs =
+-					cpu_to_le32(le32_to_cpu(
+-					aed->lengthAllocDescs) + adsize);
++				le32_add_cpu(&aed->lengthAllocDescs, adsize);
+ 			} else {
+ 				iinfo->i_lenAlloc += adsize;
+ 				mark_inode_dirty(inode);
+@@ -1830,9 +1753,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
+ 		mark_inode_dirty(inode);
+ 	} else {
+ 		aed = (struct allocExtDesc *)epos->bh->b_data;
+-		aed->lengthAllocDescs =
+-			cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) +
+-				    adsize);
++		le32_add_cpu(&aed->lengthAllocDescs, adsize);
+ 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
+ 				UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
+ 			udf_update_tag(epos->bh->b_data,
+@@ -2046,9 +1967,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
+ 			mark_inode_dirty(inode);
+ 		} else {
+ 			aed = (struct allocExtDesc *)oepos.bh->b_data;
+-			aed->lengthAllocDescs =
+-				cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
+-					    (2 * adsize));
++			le32_add_cpu(&aed->lengthAllocDescs, -(2 * adsize));
+ 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
+ 			    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
+ 				udf_update_tag(oepos.bh->b_data,
+@@ -2065,9 +1984,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
+ 			mark_inode_dirty(inode);
+ 		} else {
+ 			aed = (struct allocExtDesc *)oepos.bh->b_data;
+-			aed->lengthAllocDescs =
+-				cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
+-					    adsize);
++			le32_add_cpu(&aed->lengthAllocDescs, -adsize);
+ 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
+ 			    UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
+ 				udf_update_tag(oepos.bh->b_data,
+@@ -2095,11 +2012,6 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
+ 	int8_t etype;
+ 	struct udf_inode_info *iinfo;
+ 
+-	if (block < 0) {
+-		printk(KERN_ERR "udf: inode_bmap: block < 0\n");
+-		return -1;
+-	}
+-
+ 	iinfo = UDF_I(inode);
+ 	pos->offset = 0;
+ 	pos->block = iinfo->i_location;
+diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
+index 579bae7..703843f 100644
+--- a/fs/udf/lowlevel.c
++++ b/fs/udf/lowlevel.c
+@@ -23,7 +23,6 @@
+ #include <linux/cdrom.h>
+ #include <asm/uaccess.h>
+ 
+-#include <linux/udf_fs.h>
+ #include "udf_sb.h"
+ 
+ unsigned int udf_get_last_session(struct super_block *sb)
+diff --git a/fs/udf/misc.c b/fs/udf/misc.c
+index a1d6da0..84bf0fd 100644
+--- a/fs/udf/misc.c
++++ b/fs/udf/misc.c
+@@ -23,8 +23,8 @@
+ 
+ #include <linux/fs.h>
+ #include <linux/string.h>
+-#include <linux/udf_fs.h>
+ #include <linux/buffer_head.h>
++#include <linux/crc-itu-t.h>
+ 
+ #include "udf_i.h"
+ #include "udf_sb.h"
+@@ -136,8 +136,8 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
+ 		/* rewrite CRC + checksum of eahd */
+ 		crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag);
+ 		eahd->descTag.descCRCLength = cpu_to_le16(crclen);
+-		eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd +
+-						sizeof(tag), crclen, 0));
++		eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd +
++						sizeof(tag), crclen));
+ 		eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag);
+ 		iinfo->i_lenEAttr += size;
+ 		return (struct genericFormat *)&ea[offset];
+@@ -204,16 +204,15 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
+ {
+ 	tag *tag_p;
+ 	struct buffer_head *bh = NULL;
+-	struct udf_sb_info *sbi = UDF_SB(sb);
+ 
+ 	/* Read the block */
+ 	if (block == 0xFFFFFFFF)
+ 		return NULL;
+ 
+-	bh = udf_tread(sb, block + sbi->s_session);
++	bh = udf_tread(sb, block);
+ 	if (!bh) {
+ 		udf_debug("block=%d, location=%d: read failed\n",
+-			  block + sbi->s_session, location);
++			  block, location);
+ 		return NULL;
+ 	}
+ 
+@@ -223,8 +222,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
+ 
+ 	if (location != le32_to_cpu(tag_p->tagLocation)) {
+ 		udf_debug("location mismatch block %u, tag %u != %u\n",
+-			  block + sbi->s_session,
+-			  le32_to_cpu(tag_p->tagLocation), location);
++			  block, le32_to_cpu(tag_p->tagLocation), location);
+ 		goto error_out;
+ 	}
+ 
+@@ -244,13 +242,13 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
+ 
+ 	/* Verify the descriptor CRC */
+ 	if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
+-	    le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
+-					le16_to_cpu(tag_p->descCRCLength), 0))
++	    le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
++					bh->b_data + sizeof(tag),
++					le16_to_cpu(tag_p->descCRCLength)))
+ 		return bh;
+ 
+-	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
+-		  block + sbi->s_session, le16_to_cpu(tag_p->descCRC),
+-		  le16_to_cpu(tag_p->descCRCLength));
++	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", block,
++	    le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
+ 
+ error_out:
+ 	brelse(bh);
+@@ -270,7 +268,7 @@ void udf_update_tag(char *data, int length)
+ 	length -= sizeof(tag);
+ 
+ 	tptr->descCRCLength = cpu_to_le16(length);
+-	tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0));
++	tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(tag), length));
+ 	tptr->tagChecksum = udf_tag_checksum(tptr);
+ }
+ 
+diff --git a/fs/udf/namei.c b/fs/udf/namei.c
+index 112a5fb..ba5537d 100644
+--- a/fs/udf/namei.c
++++ b/fs/udf/namei.c
+@@ -31,6 +31,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/buffer_head.h>
+ #include <linux/sched.h>
++#include <linux/crc-itu-t.h>
+ 
+ static inline int udf_match(int len1, const char *name1, int len2,
+ 			    const char *name2)
+@@ -97,25 +98,23 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
+ 		memset(fibh->ebh->b_data, 0x00, padlen + offset);
+ 	}
+ 
+-	crc = udf_crc((uint8_t *)cfi + sizeof(tag),
+-		      sizeof(struct fileIdentDesc) - sizeof(tag), 0);
++	crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(tag),
++		      sizeof(struct fileIdentDesc) - sizeof(tag));
+ 
+ 	if (fibh->sbh == fibh->ebh) {
+-		crc = udf_crc((uint8_t *)sfi->impUse,
++		crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
+ 			      crclen + sizeof(tag) -
+-			      sizeof(struct fileIdentDesc), crc);
++			      sizeof(struct fileIdentDesc));
+ 	} else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) {
+-		crc = udf_crc(fibh->ebh->b_data +
++		crc = crc_itu_t(crc, fibh->ebh->b_data +
+ 					sizeof(struct fileIdentDesc) +
+ 					fibh->soffset,
+ 			      crclen + sizeof(tag) -
+-					sizeof(struct fileIdentDesc),
+-			      crc);
++					sizeof(struct fileIdentDesc));
+ 	} else {
+-		crc = udf_crc((uint8_t *)sfi->impUse,
+-			      -fibh->soffset - sizeof(struct fileIdentDesc),
+-			      crc);
+-		crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
++		crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
++			      -fibh->soffset - sizeof(struct fileIdentDesc));
++		crc = crc_itu_t(crc, fibh->ebh->b_data, fibh->eoffset);
+ 	}
+ 
+ 	cfi->descTag.descCRC = cpu_to_le16(crc);
+@@ -149,7 +148,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
+ 	struct fileIdentDesc *fi = NULL;
+ 	loff_t f_pos;
+ 	int block, flen;
+-	char fname[UDF_NAME_LEN];
++	char *fname = NULL;
+ 	char *nameptr;
+ 	uint8_t lfi;
+ 	uint16_t liu;
+@@ -163,12 +162,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
+ 	size = udf_ext0_offset(dir) + dir->i_size;
+ 	f_pos = udf_ext0_offset(dir);
+ 
++	fibh->sbh = fibh->ebh = NULL;
+ 	fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
+-	if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+-		fibh->sbh = fibh->ebh = NULL;
+-	else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
+-			      &epos, &eloc, &elen, &offset) ==
+-					(EXT_RECORDED_ALLOCATED >> 30)) {
++	if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
++		if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
++		    &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
++			goto out_err;
+ 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
+ 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
+ 			if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+@@ -179,25 +178,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
+ 			offset = 0;
+ 
+ 		fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
+-		if (!fibh->sbh) {
+-			brelse(epos.bh);
+-			return NULL;
+-		}
+-	} else {
+-		brelse(epos.bh);
+-		return NULL;
++		if (!fibh->sbh)
++			goto out_err;
+ 	}
+ 
++	fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
++	if (!fname)
++		goto out_err;
++
+ 	while (f_pos < size) {
+ 		fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
+ 					&elen, &offset);
+-		if (!fi) {
+-			if (fibh->sbh != fibh->ebh)
+-				brelse(fibh->ebh);
+-			brelse(fibh->sbh);
+-			brelse(epos.bh);
+-			return NULL;
+-		}
++		if (!fi)
++			goto out_err;
+ 
+ 		liu = le16_to_cpu(cfi->lengthOfImpUse);
+ 		lfi = cfi->lengthFileIdent;
+@@ -237,53 +230,22 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
+ 
+ 		flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
+ 		if (flen && udf_match(flen, fname, dentry->d_name.len,
+-				      dentry->d_name.name)) {
+-			brelse(epos.bh);
+-			return fi;
+-		}
++				      dentry->d_name.name))
++			goto out_ok;
+ 	}
+ 
++out_err:
++	fi = NULL;
+ 	if (fibh->sbh != fibh->ebh)
+ 		brelse(fibh->ebh);
+ 	brelse(fibh->sbh);
++out_ok:
+ 	brelse(epos.bh);
++	kfree(fname);
+ 
+-	return NULL;
++	return fi;
+ }
+ 
+-/*
+- * udf_lookup
+- *
+- * PURPOSE
+- *	Look-up the inode for a given name.
+- *
+- * DESCRIPTION
+- *	Required - lookup_dentry() will return -ENOTDIR if this routine is not
+- *	available for a directory. The filesystem is useless if this routine is
+- *	not available for at least the filesystem's root directory.
+- *
+- *	This routine is passed an incomplete dentry - it must be completed by
+- *	calling d_add(dentry, inode). If the name does not exist, then the
+- *	specified inode must be set to null. An error should only be returned
+- *	when the lookup fails for a reason other than the name not existing.
+- *	Note that the directory inode semaphore is held during the call.
+- *
+- *	Refer to lookup_dentry() in fs/namei.c
+- *	lookup_dentry() -> lookup() -> real_lookup() -> .
+- *
+- * PRE-CONDITIONS
+- *	dir			Pointer to inode of parent directory.
+- *	dentry			Pointer to dentry to complete.
+- *	nd			Pointer to lookup nameidata
+- *
+- * POST-CONDITIONS
+- *	<return>		Zero on success.
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
+- */
+-
+ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
+ 				 struct nameidata *nd)
+ {
+@@ -336,11 +298,9 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ {
+ 	struct super_block *sb = dir->i_sb;
+ 	struct fileIdentDesc *fi = NULL;
+-	char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
++	char *name = NULL;
+ 	int namelen;
+ 	loff_t f_pos;
+-	int flen;
+-	char *nameptr;
+ 	loff_t size = udf_ext0_offset(dir) + dir->i_size;
+ 	int nfidlen;
+ 	uint8_t lfi;
+@@ -352,16 +312,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ 	struct extent_position epos = {};
+ 	struct udf_inode_info *dinfo;
+ 
++	fibh->sbh = fibh->ebh = NULL;
++	name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
++	if (!name) {
++		*err = -ENOMEM;
++		goto out_err;
++	}
++
+ 	if (dentry) {
+ 		if (!dentry->d_name.len) {
+ 			*err = -EINVAL;
+-			return NULL;
++			goto out_err;
+ 		}
+ 		namelen = udf_put_filename(sb, dentry->d_name.name, name,
+ 						 dentry->d_name.len);
+ 		if (!namelen) {
+ 			*err = -ENAMETOOLONG;
+-			return NULL;
++			goto out_err;
+ 		}
+ 	} else {
+ 		namelen = 0;
+@@ -373,11 +340,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ 
+ 	fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
+ 	dinfo = UDF_I(dir);
+-	if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+-		fibh->sbh = fibh->ebh = NULL;
+-	else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
+-			      &epos, &eloc, &elen, &offset) ==
+-					(EXT_RECORDED_ALLOCATED >> 30)) {
++	if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
++		if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
++		    &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
++			block = udf_get_lb_pblock(dir->i_sb,
++					dinfo->i_location, 0);
++			fibh->soffset = fibh->eoffset = sb->s_blocksize;
++			goto add;
++		}
+ 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
+ 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
+ 			if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+@@ -389,17 +359,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ 
+ 		fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
+ 		if (!fibh->sbh) {
+-			brelse(epos.bh);
+ 			*err = -EIO;
+-			return NULL;
++			goto out_err;
+ 		}
+ 
+ 		block = dinfo->i_location.logicalBlockNum;
+-	} else {
+-		block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0);
+-		fibh->sbh = fibh->ebh = NULL;
+-		fibh->soffset = fibh->eoffset = sb->s_blocksize;
+-		goto add;
+ 	}
+ 
+ 	while (f_pos < size) {
+@@ -407,41 +371,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ 					&elen, &offset);
+ 
+ 		if (!fi) {
+-			if (fibh->sbh != fibh->ebh)
+-				brelse(fibh->ebh);
+-			brelse(fibh->sbh);
+-			brelse(epos.bh);
+ 			*err = -EIO;
+-			return NULL;
++			goto out_err;
+ 		}
+ 
+ 		liu = le16_to_cpu(cfi->lengthOfImpUse);
+ 		lfi = cfi->lengthFileIdent;
+ 
+-		if (fibh->sbh == fibh->ebh)
+-			nameptr = fi->fileIdent + liu;
+-		else {
+-			int poffset;	/* Unpaded ending offset */
+-
+-			poffset = fibh->soffset + sizeof(struct fileIdentDesc) +
+-					liu + lfi;
+-
+-			if (poffset >= lfi)
+-				nameptr = (char *)(fibh->ebh->b_data +
+-						   poffset - lfi);
+-			else {
+-				nameptr = fname;
+-				memcpy(nameptr, fi->fileIdent + liu,
+-					lfi - poffset);
+-				memcpy(nameptr + lfi - poffset,
+-					fibh->ebh->b_data, poffset);
+-			}
+-		}
+-
+ 		if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
+ 			if (((sizeof(struct fileIdentDesc) +
+ 					liu + lfi + 3) & ~3) == nfidlen) {
+-				brelse(epos.bh);
+ 				cfi->descTag.tagSerialNum = cpu_to_le16(1);
+ 				cfi->fileVersionNum = cpu_to_le16(1);
+ 				cfi->fileCharacteristics = 0;
+@@ -449,27 +388,13 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ 				cfi->lengthOfImpUse = cpu_to_le16(0);
+ 				if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
+ 						  name))
+-					return fi;
++					goto out_ok;
+ 				else {
+ 					*err = -EIO;
+-					return NULL;
++					goto out_err;
+ 				}
+ 			}
+ 		}
+-
+-		if (!lfi || !dentry)
+-			continue;
+-
+-		flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
+-		if (flen && udf_match(flen, fname, dentry->d_name.len,
+-				      dentry->d_name.name)) {
+-			if (fibh->sbh != fibh->ebh)
+-				brelse(fibh->ebh);
+-			brelse(fibh->sbh);
+-			brelse(epos.bh);
+-			*err = -EEXIST;
+-			return NULL;
+-		}
+ 	}
+ 
+ add:
+@@ -496,7 +421,7 @@ add:
+ 		fibh->sbh = fibh->ebh =
+ 				udf_expand_dir_adinicb(dir, &block, err);
+ 		if (!fibh->sbh)
+-			return NULL;
++			goto out_err;
+ 		epos.block = dinfo->i_location;
+ 		epos.offset = udf_file_entry_alloc_offset(dir);
+ 		/* Load extent udf_expand_dir_adinicb() has created */
+@@ -537,11 +462,8 @@ add:
+ 						dir->i_sb->s_blocksize_bits);
+ 		fibh->ebh = udf_bread(dir,
+ 				f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
+-		if (!fibh->ebh) {
+-			brelse(epos.bh);
+-			brelse(fibh->sbh);
+-			return NULL;
+-		}
++		if (!fibh->ebh)
++			goto out_err;
+ 
+ 		if (!fibh->soffset) {
+ 			if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
+@@ -572,20 +494,25 @@ add:
+ 	cfi->lengthFileIdent = namelen;
+ 	cfi->lengthOfImpUse = cpu_to_le16(0);
+ 	if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
+-		brelse(epos.bh);
+ 		dir->i_size += nfidlen;
+ 		if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+ 			dinfo->i_lenAlloc += nfidlen;
+ 		mark_inode_dirty(dir);
+-		return fi;
++		goto out_ok;
+ 	} else {
+-		brelse(epos.bh);
+-		if (fibh->sbh != fibh->ebh)
+-			brelse(fibh->ebh);
+-		brelse(fibh->sbh);
+ 		*err = -EIO;
+-		return NULL;
++		goto out_err;
+ 	}
++
++out_err:
++	fi = NULL;
++	if (fibh->sbh != fibh->ebh)
++		brelse(fibh->ebh);
++	brelse(fibh->sbh);
++out_ok:
++	brelse(epos.bh);
++	kfree(name);
++	return fi;
+ }
+ 
+ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
+@@ -940,7 +867,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
+ 	char *ea;
+ 	int err;
+ 	int block;
+-	char name[UDF_NAME_LEN];
++	char *name = NULL;
+ 	int namelen;
+ 	struct buffer_head *bh;
+ 	struct udf_inode_info *iinfo;
+@@ -950,6 +877,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
+ 	if (!inode)
+ 		goto out;
+ 
++	name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
++	if (!name) {
++		err = -ENOMEM;
++		goto out_no_entry;
++	}
++
+ 	iinfo = UDF_I(inode);
+ 	inode->i_mode = S_IFLNK | S_IRWXUGO;
+ 	inode->i_data.a_ops = &udf_symlink_aops;
+@@ -1089,6 +1022,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
+ 	err = 0;
+ 
+ out:
++	kfree(name);
+ 	unlock_kernel();
+ 	return err;
+ 
+diff --git a/fs/udf/partition.c b/fs/udf/partition.c
+index fc53334..63610f0 100644
+--- a/fs/udf/partition.c
++++ b/fs/udf/partition.c
+@@ -24,7 +24,6 @@
+ 
+ #include <linux/fs.h>
+ #include <linux/string.h>
+-#include <linux/udf_fs.h>
+ #include <linux/slab.h>
+ #include <linux/buffer_head.h>
+ 
+@@ -55,11 +54,10 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
+ 	struct udf_sb_info *sbi = UDF_SB(sb);
+ 	struct udf_part_map *map;
+ 	struct udf_virtual_data *vdata;
+-	struct udf_inode_info *iinfo;
++	struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode);
+ 
+ 	map = &sbi->s_partmaps[partition];
+ 	vdata = &map->s_type_specific.s_virtual;
+-	index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
+ 
+ 	if (block > vdata->s_num_entries) {
+ 		udf_debug("Trying to access block beyond end of VAT "
+@@ -67,6 +65,12 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
+ 		return 0xFFFFFFFF;
+ 	}
+ 
++	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
++		loc = le32_to_cpu(((__le32 *)(iinfo->i_ext.i_data +
++			vdata->s_start_offset))[block]);
++		goto translate;
++	}
++	index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
+ 	if (block >= index) {
+ 		block -= index;
+ 		newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t)));
+@@ -89,7 +93,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
+ 
+ 	brelse(bh);
+ 
+-	iinfo = UDF_I(sbi->s_vat_inode);
++translate:
+ 	if (iinfo->i_location.partitionReferenceNum == partition) {
+ 		udf_debug("recursive call to udf_get_pblock!\n");
+ 		return 0xFFFFFFFF;
+@@ -263,3 +267,58 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
+ 
+ 	return 0;
+ }
++
++static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
++					uint16_t partition, uint32_t offset)
++{
++	struct super_block *sb = inode->i_sb;
++	struct udf_part_map *map;
++	kernel_lb_addr eloc;
++	uint32_t elen;
++	sector_t ext_offset;
++	struct extent_position epos = {};
++	uint32_t phyblock;
++
++	if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) !=
++						(EXT_RECORDED_ALLOCATED >> 30))
++		phyblock = 0xFFFFFFFF;
++	else {
++		map = &UDF_SB(sb)->s_partmaps[partition];
++		/* map to sparable/physical partition desc */
++		phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
++			map->s_partition_num, ext_offset + offset);
++	}
++
++	brelse(epos.bh);
++	return phyblock;
++}
++
++uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
++				uint16_t partition, uint32_t offset)
++{
++	struct udf_sb_info *sbi = UDF_SB(sb);
++	struct udf_part_map *map;
++	struct udf_meta_data *mdata;
++	uint32_t retblk;
++	struct inode *inode;
++
++	udf_debug("READING from METADATA\n");
++
++	map = &sbi->s_partmaps[partition];
++	mdata = &map->s_type_specific.s_metadata;
++	inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe;
++
++	/* We shouldn't mount such media... */
++	BUG_ON(!inode);
++	retblk = udf_try_read_meta(inode, block, partition, offset);
++	if (retblk == 0xFFFFFFFF) {
++		udf_warning(sb, __func__, "error reading from METADATA, "
++			"trying to read from MIRROR");
++		inode = mdata->s_mirror_fe;
++		if (!inode)
++			return 0xFFFFFFFF;
++		retblk = udf_try_read_meta(inode, block, partition, offset);
++	}
++
++	return retblk;
++}
+diff --git a/fs/udf/super.c b/fs/udf/super.c
+index f3ac4ab..b564fc1 100644
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -55,9 +55,10 @@
+ #include <linux/errno.h>
+ #include <linux/mount.h>
+ #include <linux/seq_file.h>
++#include <linux/bitmap.h>
++#include <linux/crc-itu-t.h>
+ #include <asm/byteorder.h>
+ 
+-#include <linux/udf_fs.h>
+ #include "udf_sb.h"
+ #include "udf_i.h"
+ 
+@@ -84,22 +85,19 @@ static void udf_write_super(struct super_block *);
+ static int udf_remount_fs(struct super_block *, int *, char *);
+ static int udf_check_valid(struct super_block *, int, int);
+ static int udf_vrs(struct super_block *sb, int silent);
+-static int udf_load_partition(struct super_block *, kernel_lb_addr *);
+-static int udf_load_logicalvol(struct super_block *, struct buffer_head *,
+-			       kernel_lb_addr *);
+ static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);
+ static void udf_find_anchor(struct super_block *);
+ static int udf_find_fileset(struct super_block *, kernel_lb_addr *,
+ 			    kernel_lb_addr *);
+-static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);
+ static void udf_load_fileset(struct super_block *, struct buffer_head *,
+ 			     kernel_lb_addr *);
+-static int udf_load_partdesc(struct super_block *, struct buffer_head *);
+ static void udf_open_lvid(struct super_block *);
+ static void udf_close_lvid(struct super_block *);
+ static unsigned int udf_count_free(struct super_block *);
+ static int udf_statfs(struct dentry *, struct kstatfs *);
+ static int udf_show_options(struct seq_file *, struct vfsmount *);
++static void udf_error(struct super_block *sb, const char *function,
++		      const char *fmt, ...);
+ 
+ struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
+ {
+@@ -587,48 +585,10 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
+ 	return 0;
+ }
+ 
+-/*
+- * udf_set_blocksize
+- *
+- * PURPOSE
+- *	Set the block size to be used in all transfers.
+- *
+- * DESCRIPTION
+- *	To allow room for a DMA transfer, it is best to guess big when unsure.
+- *	This routine picks 2048 bytes as the blocksize when guessing. This
+- *	should be adequate until devices with larger block sizes become common.
+- *
+- *	Note that the Linux kernel can currently only deal with blocksizes of
+- *	512, 1024, 2048, 4096, and 8192 bytes.
+- *
+- * PRE-CONDITIONS
+- *	sb			Pointer to _locked_ superblock.
+- *
+- * POST-CONDITIONS
+- *	sb->s_blocksize		Blocksize.
+- *	sb->s_blocksize_bits	log2 of blocksize.
+- *	<return>	0	Blocksize is valid.
+- *	<return>	1	Blocksize is invalid.
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
+- */
+-static int udf_set_blocksize(struct super_block *sb, int bsize)
+-{
+-	if (!sb_min_blocksize(sb, bsize)) {
+-		udf_debug("Bad block size (%d)\n", bsize);
+-		printk(KERN_ERR "udf: bad block size (%d)\n", bsize);
+-		return 0;
+-	}
+-
+-	return sb->s_blocksize;
+-}
+-
+ static int udf_vrs(struct super_block *sb, int silent)
+ {
+ 	struct volStructDesc *vsd = NULL;
+-	int sector = 32768;
++	loff_t sector = 32768;
+ 	int sectorsize;
+ 	struct buffer_head *bh = NULL;
+ 	int iso9660 = 0;
+@@ -649,7 +609,8 @@ static int udf_vrs(struct super_block *sb, int silent)
+ 	sector += (sbi->s_session << sb->s_blocksize_bits);
+ 
+ 	udf_debug("Starting at sector %u (%ld byte sectors)\n",
+-		  (sector >> sb->s_blocksize_bits), sb->s_blocksize);
++		  (unsigned int)(sector >> sb->s_blocksize_bits),
++		  sb->s_blocksize);
+ 	/* Process the sequence (if applicable) */
+ 	for (; !nsr02 && !nsr03; sector += sectorsize) {
+ 		/* Read a block */
+@@ -719,162 +680,140 @@ static int udf_vrs(struct super_block *sb, int silent)
+ }
+ 
+ /*
+- * udf_find_anchor
+- *
+- * PURPOSE
+- *	Find an anchor volume descriptor.
+- *
+- * PRE-CONDITIONS
+- *	sb			Pointer to _locked_ superblock.
+- *	lastblock		Last block on media.
+- *
+- * POST-CONDITIONS
+- *	<return>		1 if not found, 0 if ok
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
++ * Check whether there is an anchor block in the given block
+  */
+-static void udf_find_anchor(struct super_block *sb)
++static int udf_check_anchor_block(struct super_block *sb, sector_t block,
++					bool varconv)
+ {
+-	int lastblock;
+ 	struct buffer_head *bh = NULL;
++	tag *t;
+ 	uint16_t ident;
+ 	uint32_t location;
+-	int i;
+-	struct udf_sb_info *sbi;
+ 
+-	sbi = UDF_SB(sb);
+-	lastblock = sbi->s_last_block;
++	if (varconv) {
++		if (udf_fixed_to_variable(block) >=
++		    sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
++			return 0;
++		bh = sb_bread(sb, udf_fixed_to_variable(block));
++	}
++	else
++		bh = sb_bread(sb, block);
+ 
+-	if (lastblock) {
+-		int varlastblock = udf_variable_to_fixed(lastblock);
+-		int last[] =  { lastblock, lastblock - 2,
+-				lastblock - 150, lastblock - 152,
+-				varlastblock, varlastblock - 2,
+-				varlastblock - 150, varlastblock - 152 };
+-
+-		lastblock = 0;
+-
+-		/* Search for an anchor volume descriptor pointer */
+-
+-		/*  according to spec, anchor is in either:
+-		 *     block 256
+-		 *     lastblock-256
+-		 *     lastblock
+-		 *  however, if the disc isn't closed, it could be 512 */
+-
+-		for (i = 0; !lastblock && i < ARRAY_SIZE(last); i++) {
+-			ident = location = 0;
+-			if (last[i] >= 0) {
+-				bh = sb_bread(sb, last[i]);
+-				if (bh) {
+-					tag *t = (tag *)bh->b_data;
+-					ident = le16_to_cpu(t->tagIdent);
+-					location = le32_to_cpu(t->tagLocation);
+-					brelse(bh);
+-				}
+-			}
++	if (!bh)
++		return 0;
+ 
+-			if (ident == TAG_IDENT_AVDP) {
+-				if (location == last[i] - sbi->s_session) {
+-					lastblock = last[i] - sbi->s_session;
+-					sbi->s_anchor[0] = lastblock;
+-					sbi->s_anchor[1] = lastblock - 256;
+-				} else if (location ==
+-						udf_variable_to_fixed(last[i]) -
+-							sbi->s_session) {
+-					UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+-					lastblock =
+-						udf_variable_to_fixed(last[i]) -
+-							sbi->s_session;
+-					sbi->s_anchor[0] = lastblock;
+-					sbi->s_anchor[1] = lastblock - 256 -
+-								sbi->s_session;
+-				} else {
+-					udf_debug("Anchor found at block %d, "
+-						  "location mismatch %d.\n",
+-						  last[i], location);
+-				}
+-			} else if (ident == TAG_IDENT_FE ||
+-					ident == TAG_IDENT_EFE) {
+-				lastblock = last[i];
+-				sbi->s_anchor[3] = 512;
+-			} else {
+-				ident = location = 0;
+-				if (last[i] >= 256) {
+-					bh = sb_bread(sb, last[i] - 256);
+-					if (bh) {
+-						tag *t = (tag *)bh->b_data;
+-						ident = le16_to_cpu(
+-								t->tagIdent);
+-						location = le32_to_cpu(
+-								t->tagLocation);
+-						brelse(bh);
+-					}
+-				}
++	t = (tag *)bh->b_data;
++	ident = le16_to_cpu(t->tagIdent);
++	location = le32_to_cpu(t->tagLocation);
++	brelse(bh);
++	if (ident != TAG_IDENT_AVDP)
++		return 0;
++	return location == block;
++}
+ 
+-				if (ident == TAG_IDENT_AVDP &&
+-				    location == last[i] - 256 -
+-						sbi->s_session) {
+-					lastblock = last[i];
+-					sbi->s_anchor[1] = last[i] - 256;
+-				} else {
+-					ident = location = 0;
+-					if (last[i] >= 312 + sbi->s_session) {
+-						bh = sb_bread(sb,
+-								last[i] - 312 -
+-								sbi->s_session);
+-						if (bh) {
+-							tag *t = (tag *)
+-								 bh->b_data;
+-							ident = le16_to_cpu(
+-								t->tagIdent);
+-							location = le32_to_cpu(
+-								t->tagLocation);
+-							brelse(bh);
+-						}
+-					}
++/* Search for an anchor volume descriptor pointer */
++static sector_t udf_scan_anchors(struct super_block *sb, bool varconv,
++					sector_t lastblock)
++{
++	sector_t last[6];
++	int i;
++	struct udf_sb_info *sbi = UDF_SB(sb);
+ 
+-					if (ident == TAG_IDENT_AVDP &&
+-					    location == udf_variable_to_fixed(last[i]) - 256) {
+-						UDF_SET_FLAG(sb,
+-							     UDF_FLAG_VARCONV);
+-						lastblock = udf_variable_to_fixed(last[i]);
+-						sbi->s_anchor[1] = lastblock - 256;
+-					}
+-				}
+-			}
++	last[0] = lastblock;
++	last[1] = last[0] - 1;
++	last[2] = last[0] + 1;
++	last[3] = last[0] - 2;
++	last[4] = last[0] - 150;
++	last[5] = last[0] - 152;
++
++	/*  according to spec, anchor is in either:
++	 *     block 256
++	 *     lastblock-256
++	 *     lastblock
++	 *  however, if the disc isn't closed, it could be 512 */
++
++	for (i = 0; i < ARRAY_SIZE(last); i++) {
++		if (last[i] < 0)
++			continue;
++		if (last[i] >= sb->s_bdev->bd_inode->i_size >>
++				sb->s_blocksize_bits)
++			continue;
++
++		if (udf_check_anchor_block(sb, last[i], varconv)) {
++			sbi->s_anchor[0] = last[i];
++			sbi->s_anchor[1] = last[i] - 256;
++			return last[i];
+ 		}
+-	}
+ 
+-	if (!lastblock) {
+-		/* We haven't found the lastblock. check 312 */
+-		bh = sb_bread(sb, 312 + sbi->s_session);
+-		if (bh) {
+-			tag *t = (tag *)bh->b_data;
+-			ident = le16_to_cpu(t->tagIdent);
+-			location = le32_to_cpu(t->tagLocation);
+-			brelse(bh);
++		if (last[i] < 256)
++			continue;
+ 
+-			if (ident == TAG_IDENT_AVDP && location == 256)
+-				UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
++		if (udf_check_anchor_block(sb, last[i] - 256, varconv)) {
++			sbi->s_anchor[1] = last[i] - 256;
++			return last[i];
+ 		}
+ 	}
+ 
++	if (udf_check_anchor_block(sb, sbi->s_session + 256, varconv)) {
++		sbi->s_anchor[0] = sbi->s_session + 256;
++		return last[0];
++	}
++	if (udf_check_anchor_block(sb, sbi->s_session + 512, varconv)) {
++		sbi->s_anchor[0] = sbi->s_session + 512;
++		return last[0];
++	}
++	return 0;
++}
++
++/*
++ * Find an anchor volume descriptor. The function expects sbi->s_lastblock to
++ * be the last block on the media.
++ *
++ * Return 1 if not found, 0 if ok
++ *
++ */
++static void udf_find_anchor(struct super_block *sb)
++{
++	sector_t lastblock;
++	struct buffer_head *bh = NULL;
++	uint16_t ident;
++	int i;
++	struct udf_sb_info *sbi = UDF_SB(sb);
++
++	lastblock = udf_scan_anchors(sb, 0, sbi->s_last_block);
++	if (lastblock)
++		goto check_anchor;
++
++	/* No anchor found? Try VARCONV conversion of block numbers */
++	/* Firstly, we try to not convert number of the last block */
++	lastblock = udf_scan_anchors(sb, 1,
++				udf_variable_to_fixed(sbi->s_last_block));
++	if (lastblock) {
++		UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
++		goto check_anchor;
++	}
++
++	/* Secondly, we try with converted number of the last block */
++	lastblock = udf_scan_anchors(sb, 1, sbi->s_last_block);
++	if (lastblock)
++		UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
++
++check_anchor:
++	/*
++	 * Check located anchors and the anchor block supplied via
++	 * mount options
++	 */
+ 	for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
+-		if (sbi->s_anchor[i]) {
+-			bh = udf_read_tagged(sb, sbi->s_anchor[i],
+-					     sbi->s_anchor[i], &ident);
+-			if (!bh)
++		if (!sbi->s_anchor[i])
++			continue;
++		bh = udf_read_tagged(sb, sbi->s_anchor[i],
++					sbi->s_anchor[i], &ident);
++		if (!bh)
++			sbi->s_anchor[i] = 0;
++		else {
++			brelse(bh);
++			if (ident != TAG_IDENT_AVDP)
+ 				sbi->s_anchor[i] = 0;
+-			else {
+-				brelse(bh);
+-				if ((ident != TAG_IDENT_AVDP) &&
+-				    (i || (ident != TAG_IDENT_FE &&
+-					   ident != TAG_IDENT_EFE)))
+-					sbi->s_anchor[i] = 0;
+-			}
+ 		}
+ 	}
+ 
+@@ -971,27 +910,30 @@ static int udf_find_fileset(struct super_block *sb,
+ 	return 1;
+ }
+ 
+-static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
++static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
+ {
+ 	struct primaryVolDesc *pvoldesc;
+-	time_t recording;
+-	long recording_usec;
+ 	struct ustr instr;
+ 	struct ustr outstr;
++	struct buffer_head *bh;
++	uint16_t ident;
++
++	bh = udf_read_tagged(sb, block, block, &ident);
++	if (!bh)
++		return 1;
++	BUG_ON(ident != TAG_IDENT_PVD);
+ 
+ 	pvoldesc = (struct primaryVolDesc *)bh->b_data;
+ 
+-	if (udf_stamp_to_time(&recording, &recording_usec,
+-			      lets_to_cpu(pvoldesc->recordingDateAndTime))) {
+-		kernel_timestamp ts;
+-		ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
+-		udf_debug("recording time %ld/%ld, %04u/%02u/%02u"
++	if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time,
++			      pvoldesc->recordingDateAndTime)) {
++#ifdef UDFFS_DEBUG
++		timestamp *ts = &pvoldesc->recordingDateAndTime;
++		udf_debug("recording time %04u/%02u/%02u"
+ 			  " %02u:%02u (%x)\n",
+-			  recording, recording_usec,
+-			  ts.year, ts.month, ts.day, ts.hour,
+-			  ts.minute, ts.typeAndTimezone);
+-		UDF_SB(sb)->s_record_time.tv_sec = recording;
+-		UDF_SB(sb)->s_record_time.tv_nsec = recording_usec * 1000;
++			  le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
++			  ts->minute, le16_to_cpu(ts->typeAndTimezone));
++#endif
+ 	}
+ 
+ 	if (!udf_build_ustr(&instr, pvoldesc->volIdent, 32))
+@@ -1005,6 +947,104 @@ static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
+ 	if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128))
+ 		if (udf_CS0toUTF8(&outstr, &instr))
+ 			udf_debug("volSetIdent[] = '%s'\n", outstr.u_name);
++
++	brelse(bh);
++	return 0;
++}
++
++static int udf_load_metadata_files(struct super_block *sb, int partition)
++{
++	struct udf_sb_info *sbi = UDF_SB(sb);
++	struct udf_part_map *map;
++	struct udf_meta_data *mdata;
++	kernel_lb_addr addr;
++	int fe_error = 0;
++
++	map = &sbi->s_partmaps[partition];
++	mdata = &map->s_type_specific.s_metadata;
++
++	/* metadata address */
++	addr.logicalBlockNum =  mdata->s_meta_file_loc;
++	addr.partitionReferenceNum = map->s_partition_num;
++
++	udf_debug("Metadata file location: block = %d part = %d\n",
++			  addr.logicalBlockNum, addr.partitionReferenceNum);
++
++	mdata->s_metadata_fe = udf_iget(sb, addr);
++
++	if (mdata->s_metadata_fe == NULL) {
++		udf_warning(sb, __func__, "metadata inode efe not found, "
++				"will try mirror inode.");
++		fe_error = 1;
++	} else if (UDF_I(mdata->s_metadata_fe)->i_alloc_type !=
++		 ICBTAG_FLAG_AD_SHORT) {
++		udf_warning(sb, __func__, "metadata inode efe does not have "
++			"short allocation descriptors!");
++		fe_error = 1;
++		iput(mdata->s_metadata_fe);
++		mdata->s_metadata_fe = NULL;
++	}
++
++	/* mirror file entry */
++	addr.logicalBlockNum = mdata->s_mirror_file_loc;
++	addr.partitionReferenceNum = map->s_partition_num;
++
++	udf_debug("Mirror metadata file location: block = %d part = %d\n",
++			  addr.logicalBlockNum, addr.partitionReferenceNum);
++
++	mdata->s_mirror_fe = udf_iget(sb, addr);
++
++	if (mdata->s_mirror_fe == NULL) {
++		if (fe_error) {
++			udf_error(sb, __func__, "mirror inode efe not found "
++			"and metadata inode is missing too, exiting...");
++			goto error_exit;
++		} else
++			udf_warning(sb, __func__, "mirror inode efe not found,"
++					" but metadata inode is OK");
++	} else if (UDF_I(mdata->s_mirror_fe)->i_alloc_type !=
++		 ICBTAG_FLAG_AD_SHORT) {
++		udf_warning(sb, __func__, "mirror inode efe does not have "
++			"short allocation descriptors!");
++		iput(mdata->s_mirror_fe);
++		mdata->s_mirror_fe = NULL;
++		if (fe_error)
++			goto error_exit;
++	}
++
++	/*
++	 * bitmap file entry
++	 * Note:
++	 * Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102)
++	*/
++	if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
++		addr.logicalBlockNum = mdata->s_bitmap_file_loc;
++		addr.partitionReferenceNum = map->s_partition_num;
++
++		udf_debug("Bitmap file location: block = %d part = %d\n",
++			addr.logicalBlockNum, addr.partitionReferenceNum);
++
++		mdata->s_bitmap_fe = udf_iget(sb, addr);
++
++		if (mdata->s_bitmap_fe == NULL) {
++			if (sb->s_flags & MS_RDONLY)
++				udf_warning(sb, __func__, "bitmap inode efe "
++					"not found but it's ok since the disc"
++					" is mounted read-only");
++			else {
++				udf_error(sb, __func__, "bitmap inode efe not "
++					"found and attempted read-write mount");
++				goto error_exit;
++			}
++		}
++	}
++
++	udf_debug("udf_load_metadata_files Ok\n");
++
++	return 0;
++
++error_exit:
++	return 1;
+ }
+ 
+ static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
+@@ -1025,10 +1065,9 @@ static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
+ int udf_compute_nr_groups(struct super_block *sb, u32 partition)
+ {
+ 	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
+-	return (map->s_partition_len +
+-		(sizeof(struct spaceBitmapDesc) << 3) +
+-		(sb->s_blocksize * 8) - 1) /
+-		(sb->s_blocksize * 8);
++	return DIV_ROUND_UP(map->s_partition_len +
++			    (sizeof(struct spaceBitmapDesc) << 3),
++			    sb->s_blocksize * 8);
+ }
+ 
+ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
+@@ -1059,134 +1098,241 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
+ 	return bitmap;
+ }
+ 
+-static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
++static int udf_fill_partdesc_info(struct super_block *sb,
++		struct partitionDesc *p, int p_index)
++{
++	struct udf_part_map *map;
++	struct udf_sb_info *sbi = UDF_SB(sb);
++	struct partitionHeaderDesc *phd;
++
++	map = &sbi->s_partmaps[p_index];
++
++	map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */
++	map->s_partition_root = le32_to_cpu(p->partitionStartingLocation);
++
++	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY))
++		map->s_partition_flags |= UDF_PART_FLAG_READ_ONLY;
++	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE))
++		map->s_partition_flags |= UDF_PART_FLAG_WRITE_ONCE;
++	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE))
++		map->s_partition_flags |= UDF_PART_FLAG_REWRITABLE;
++	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
++		map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE;
++
++	udf_debug("Partition (%d type %x) starts at physical %d, "
++		  "block length %d\n", p_index,
++		  map->s_partition_type, map->s_partition_root,
++		  map->s_partition_len);
++
++	if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) &&
++	    strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03))
++		return 0;
++
++	phd = (struct partitionHeaderDesc *)p->partitionContentsUse;
++	if (phd->unallocSpaceTable.extLength) {
++		kernel_lb_addr loc = {
++			.logicalBlockNum = le32_to_cpu(
++				phd->unallocSpaceTable.extPosition),
++			.partitionReferenceNum = p_index,
++		};
++
++		map->s_uspace.s_table = udf_iget(sb, loc);
++		if (!map->s_uspace.s_table) {
++			udf_debug("cannot load unallocSpaceTable (part %d)\n",
++					p_index);
++			return 1;
++		}
++		map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
++		udf_debug("unallocSpaceTable (part %d) @ %ld\n",
++				p_index, map->s_uspace.s_table->i_ino);
++	}
++
++	if (phd->unallocSpaceBitmap.extLength) {
++		struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
++		if (!bitmap)
++			return 1;
++		map->s_uspace.s_bitmap = bitmap;
++		bitmap->s_extLength = le32_to_cpu(
++				phd->unallocSpaceBitmap.extLength);
++		bitmap->s_extPosition = le32_to_cpu(
++				phd->unallocSpaceBitmap.extPosition);
++		map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
++		udf_debug("unallocSpaceBitmap (part %d) @ %d\n", p_index,
++						bitmap->s_extPosition);
++	}
++
++	if (phd->partitionIntegrityTable.extLength)
++		udf_debug("partitionIntegrityTable (part %d)\n", p_index);
++
++	if (phd->freedSpaceTable.extLength) {
++		kernel_lb_addr loc = {
++			.logicalBlockNum = le32_to_cpu(
++				phd->freedSpaceTable.extPosition),
++			.partitionReferenceNum = p_index,
++		};
++
++		map->s_fspace.s_table = udf_iget(sb, loc);
++		if (!map->s_fspace.s_table) {
++			udf_debug("cannot load freedSpaceTable (part %d)\n",
++				p_index);
++			return 1;
++		}
++
++		map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
++		udf_debug("freedSpaceTable (part %d) @ %ld\n",
++				p_index, map->s_fspace.s_table->i_ino);
++	}
++
++	if (phd->freedSpaceBitmap.extLength) {
++		struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
++		if (!bitmap)
++			return 1;
++		map->s_fspace.s_bitmap = bitmap;
++		bitmap->s_extLength = le32_to_cpu(
++				phd->freedSpaceBitmap.extLength);
++		bitmap->s_extPosition = le32_to_cpu(
++				phd->freedSpaceBitmap.extPosition);
++		map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
++		udf_debug("freedSpaceBitmap (part %d) @ %d\n", p_index,
++					bitmap->s_extPosition);
++	}
++	return 0;
++}
++
++static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
++{
++	struct udf_sb_info *sbi = UDF_SB(sb);
++	struct udf_part_map *map = &sbi->s_partmaps[p_index];
++	kernel_lb_addr ino;
++	struct buffer_head *bh = NULL;
++	struct udf_inode_info *vati;
++	uint32_t pos;
++	struct virtualAllocationTable20 *vat20;
++
++	/* VAT file entry is in the last recorded block */
++	ino.partitionReferenceNum = type1_index;
++	ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root;
++	sbi->s_vat_inode = udf_iget(sb, ino);
++	if (!sbi->s_vat_inode)
++		return 1;
++
++	if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
++		map->s_type_specific.s_virtual.s_start_offset = 0;
++		map->s_type_specific.s_virtual.s_num_entries =
++			(sbi->s_vat_inode->i_size - 36) >> 2;
++	} else if (map->s_partition_type == UDF_VIRTUAL_MAP20) {
++		vati = UDF_I(sbi->s_vat_inode);
++		if (vati->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
++			pos = udf_block_map(sbi->s_vat_inode, 0);
++			bh = sb_bread(sb, pos);
++			if (!bh)
++				return 1;
++			vat20 = (struct virtualAllocationTable20 *)bh->b_data;
++		} else {
++			vat20 = (struct virtualAllocationTable20 *)
++							vati->i_ext.i_data;
++		}
++
++		map->s_type_specific.s_virtual.s_start_offset =
++			le16_to_cpu(vat20->lengthHeader);
++		map->s_type_specific.s_virtual.s_num_entries =
++			(sbi->s_vat_inode->i_size -
++				map->s_type_specific.s_virtual.
++					s_start_offset) >> 2;
++		brelse(bh);
++	}
++	return 0;
++}
++
++static int udf_load_partdesc(struct super_block *sb, sector_t block)
+ {
++	struct buffer_head *bh;
+ 	struct partitionDesc *p;
+-	int i;
+ 	struct udf_part_map *map;
+-	struct udf_sb_info *sbi;
++	struct udf_sb_info *sbi = UDF_SB(sb);
++	int i, type1_idx;
++	uint16_t partitionNumber;
++	uint16_t ident;
++	int ret = 0;
++
++	bh = udf_read_tagged(sb, block, block, &ident);
++	if (!bh)
++		return 1;
++	if (ident != TAG_IDENT_PD)
++		goto out_bh;
+ 
+ 	p = (struct partitionDesc *)bh->b_data;
+-	sbi = UDF_SB(sb);
++	partitionNumber = le16_to_cpu(p->partitionNumber);
+ 
++	/* First scan for TYPE1, SPARABLE and METADATA partitions */
+ 	for (i = 0; i < sbi->s_partitions; i++) {
+ 		map = &sbi->s_partmaps[i];
+ 		udf_debug("Searching map: (%d == %d)\n",
+-			  map->s_partition_num,
+-			  le16_to_cpu(p->partitionNumber));
+-		if (map->s_partition_num ==
+-				le16_to_cpu(p->partitionNumber)) {
+-			map->s_partition_len =
+-				le32_to_cpu(p->partitionLength); /* blocks */
+-			map->s_partition_root =
+-				le32_to_cpu(p->partitionStartingLocation);
+-			if (p->accessType ==
+-					cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY))
+-				map->s_partition_flags |=
+-						UDF_PART_FLAG_READ_ONLY;
+-			if (p->accessType ==
+-					cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE))
+-				map->s_partition_flags |=
+-						UDF_PART_FLAG_WRITE_ONCE;
+-			if (p->accessType ==
+-					cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE))
+-				map->s_partition_flags |=
+-						UDF_PART_FLAG_REWRITABLE;
+-			if (p->accessType ==
+-				    cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
+-				map->s_partition_flags |=
+-						UDF_PART_FLAG_OVERWRITABLE;
+-
+-			if (!strcmp(p->partitionContents.ident,
+-				    PD_PARTITION_CONTENTS_NSR02) ||
+-			    !strcmp(p->partitionContents.ident,
+-				    PD_PARTITION_CONTENTS_NSR03)) {
+-				struct partitionHeaderDesc *phd;
+-
+-				phd = (struct partitionHeaderDesc *)
+-						(p->partitionContentsUse);
+-				if (phd->unallocSpaceTable.extLength) {
+-					kernel_lb_addr loc = {
+-						.logicalBlockNum = le32_to_cpu(phd->unallocSpaceTable.extPosition),
+-						.partitionReferenceNum = i,
+-					};
+-
+-					map->s_uspace.s_table =
+-						udf_iget(sb, loc);
+-					if (!map->s_uspace.s_table) {
+-						udf_debug("cannot load unallocSpaceTable (part %d)\n", i);
+-						return 1;
+-					}
+-					map->s_partition_flags |=
+-						UDF_PART_FLAG_UNALLOC_TABLE;
+-					udf_debug("unallocSpaceTable (part %d) @ %ld\n",
+-						  i, map->s_uspace.s_table->i_ino);
+-				}
+-				if (phd->unallocSpaceBitmap.extLength) {
+-					struct udf_bitmap *bitmap =
+-						udf_sb_alloc_bitmap(sb, i);
+-					map->s_uspace.s_bitmap = bitmap;
+-					if (bitmap != NULL) {
+-						bitmap->s_extLength =
+-							le32_to_cpu(phd->unallocSpaceBitmap.extLength);
+-						bitmap->s_extPosition =
+-							le32_to_cpu(phd->unallocSpaceBitmap.extPosition);
+-						map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
+-						udf_debug("unallocSpaceBitmap (part %d) @ %d\n",
+-							  i, bitmap->s_extPosition);
+-					}
+-				}
+-				if (phd->partitionIntegrityTable.extLength)
+-					udf_debug("partitionIntegrityTable (part %d)\n", i);
+-				if (phd->freedSpaceTable.extLength) {
+-					kernel_lb_addr loc = {
+-						.logicalBlockNum = le32_to_cpu(phd->freedSpaceTable.extPosition),
+-						.partitionReferenceNum = i,
+-					};
+-
+-					map->s_fspace.s_table =
+-						udf_iget(sb, loc);
+-					if (!map->s_fspace.s_table) {
+-						udf_debug("cannot load freedSpaceTable (part %d)\n", i);
+-						return 1;
+-					}
+-					map->s_partition_flags |=
+-						UDF_PART_FLAG_FREED_TABLE;
+-					udf_debug("freedSpaceTable (part %d) @ %ld\n",
+-						  i, map->s_fspace.s_table->i_ino);
+-				}
+-				if (phd->freedSpaceBitmap.extLength) {
+-					struct udf_bitmap *bitmap =
+-						udf_sb_alloc_bitmap(sb, i);
+-					map->s_fspace.s_bitmap = bitmap;
+-					if (bitmap != NULL) {
+-						bitmap->s_extLength =
+-							le32_to_cpu(phd->freedSpaceBitmap.extLength);
+-						bitmap->s_extPosition =
+-							le32_to_cpu(phd->freedSpaceBitmap.extPosition);
+-						map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
+-						udf_debug("freedSpaceBitmap (part %d) @ %d\n",
+-							  i, bitmap->s_extPosition);
+-					}
+-				}
+-			}
++			  map->s_partition_num, partitionNumber);
++		if (map->s_partition_num == partitionNumber &&
++		    (map->s_partition_type == UDF_TYPE1_MAP15 ||
++		     map->s_partition_type == UDF_SPARABLE_MAP15))
+ 			break;
+-		}
+ 	}
+-	if (i == sbi->s_partitions)
++
++	if (i >= sbi->s_partitions) {
+ 		udf_debug("Partition (%d) not found in partition map\n",
+-			  le16_to_cpu(p->partitionNumber));
+-	else
+-		udf_debug("Partition (%d:%d type %x) starts at physical %d, "
+-			  "block length %d\n",
+-			  le16_to_cpu(p->partitionNumber), i,
+-			  map->s_partition_type,
+-			  map->s_partition_root,
+-			  map->s_partition_len);
+-	return 0;
++			  partitionNumber);
++		goto out_bh;
++	}
++
++	ret = udf_fill_partdesc_info(sb, p, i);
++
++	/*
++	 * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and
++	 * PHYSICAL partitions are already set up
++	 */
++	type1_idx = i;
++	for (i = 0; i < sbi->s_partitions; i++) {
++		map = &sbi->s_partmaps[i];
++
++		if (map->s_partition_num == partitionNumber &&
++		    (map->s_partition_type == UDF_VIRTUAL_MAP15 ||
++		     map->s_partition_type == UDF_VIRTUAL_MAP20 ||
++		     map->s_partition_type == UDF_METADATA_MAP25))
++			break;
++	}
++
++	if (i >= sbi->s_partitions)
++		goto out_bh;
++
++	ret = udf_fill_partdesc_info(sb, p, i);
++	if (ret)
++		goto out_bh;
++
++	if (map->s_partition_type == UDF_METADATA_MAP25) {
++		ret = udf_load_metadata_files(sb, i);
++		if (ret) {
++			printk(KERN_ERR "UDF-fs: error loading MetaData "
++			"partition map %d\n", i);
++			goto out_bh;
++		}
++	} else {
++		ret = udf_load_vat(sb, i, type1_idx);
++		if (ret)
++			goto out_bh;
++		/*
++		 * Mark filesystem read-only if we have a partition with
++		 * virtual map since we don't handle writing to it (we
++		 * overwrite blocks instead of relocating them).
++		 */
++		sb->s_flags |= MS_RDONLY;
++		printk(KERN_NOTICE "UDF-fs: Filesystem marked read-only "
++			"because writing to pseudooverwrite partition is "
++			"not implemented.\n");
++	}
++out_bh:
++	/* In case loading failed, we handle cleanup in udf_fill_super */
++	brelse(bh);
++	return ret;
+ }
+ 
+-static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
++static int udf_load_logicalvol(struct super_block *sb, sector_t block,
+ 			       kernel_lb_addr *fileset)
+ {
+ 	struct logicalVolDesc *lvd;
+@@ -1194,12 +1340,21 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ 	uint8_t type;
+ 	struct udf_sb_info *sbi = UDF_SB(sb);
+ 	struct genericPartitionMap *gpm;
++	uint16_t ident;
++	struct buffer_head *bh;
++	int ret = 0;
+ 
++	bh = udf_read_tagged(sb, block, block, &ident);
++	if (!bh)
++		return 1;
++	BUG_ON(ident != TAG_IDENT_LVD);
+ 	lvd = (struct logicalVolDesc *)bh->b_data;
+ 
+ 	i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
+-	if (i != 0)
+-		return i;
++	if (i != 0) {
++		ret = i;
++		goto out_bh;
++	}
+ 
+ 	for (i = 0, offset = 0;
+ 	     i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength);
+@@ -1223,12 +1378,12 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ 				u16 suf =
+ 					le16_to_cpu(((__le16 *)upm2->partIdent.
+ 							identSuffix)[0]);
+-				if (suf == 0x0150) {
++				if (suf < 0x0200) {
+ 					map->s_partition_type =
+ 							UDF_VIRTUAL_MAP15;
+ 					map->s_partition_func =
+ 							udf_get_pblock_virt15;
+-				} else if (suf == 0x0200) {
++				} else {
+ 					map->s_partition_type =
+ 							UDF_VIRTUAL_MAP20;
+ 					map->s_partition_func =
+@@ -1238,7 +1393,6 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ 						UDF_ID_SPARABLE,
+ 						strlen(UDF_ID_SPARABLE))) {
+ 				uint32_t loc;
+-				uint16_t ident;
+ 				struct sparingTable *st;
+ 				struct sparablePartitionMap *spm =
+ 					(struct sparablePartitionMap *)gpm;
+@@ -1256,22 +1410,64 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ 					map->s_type_specific.s_sparing.
+ 							s_spar_map[j] = bh2;
+ 
+-					if (bh2 != NULL) {
+-						st = (struct sparingTable *)
+-								bh2->b_data;
+-						if (ident != 0 || strncmp(
+-							st->sparingIdent.ident,
+-							UDF_ID_SPARING,
+-							strlen(UDF_ID_SPARING))) {
+-							brelse(bh2);
+-							map->s_type_specific.
+-								s_sparing.
+-								s_spar_map[j] =
+-									NULL;
+-						}
++					if (bh2 == NULL)
++						continue;
++
++					st = (struct sparingTable *)bh2->b_data;
++					if (ident != 0 || strncmp(
++						st->sparingIdent.ident,
++						UDF_ID_SPARING,
++						strlen(UDF_ID_SPARING))) {
++						brelse(bh2);
++						map->s_type_specific.s_sparing.
++							s_spar_map[j] = NULL;
+ 					}
+ 				}
+ 				map->s_partition_func = udf_get_pblock_spar15;
++			} else if (!strncmp(upm2->partIdent.ident,
++						UDF_ID_METADATA,
++						strlen(UDF_ID_METADATA))) {
++				struct udf_meta_data *mdata =
++					&map->s_type_specific.s_metadata;
++				struct metadataPartitionMap *mdm =
++						(struct metadataPartitionMap *)
++						&(lvd->partitionMaps[offset]);
++				udf_debug("Parsing Logical vol part %d "
++					"type %d  id=%s\n", i, type,
++					UDF_ID_METADATA);
++
++				map->s_partition_type = UDF_METADATA_MAP25;
++				map->s_partition_func = udf_get_pblock_meta25;
++
++				mdata->s_meta_file_loc   =
++					le32_to_cpu(mdm->metadataFileLoc);
++				mdata->s_mirror_file_loc =
++					le32_to_cpu(mdm->metadataMirrorFileLoc);
++				mdata->s_bitmap_file_loc =
++					le32_to_cpu(mdm->metadataBitmapFileLoc);
++				mdata->s_alloc_unit_size =
++					le32_to_cpu(mdm->allocUnitSize);
++				mdata->s_align_unit_size =
++					le16_to_cpu(mdm->alignUnitSize);
++				mdata->s_dup_md_flag 	 =
++					mdm->flags & 0x01;
++
++				udf_debug("Metadata Ident suffix=0x%x\n",
++					(le16_to_cpu(
++					 ((__le16 *)
++					      mdm->partIdent.identSuffix)[0])));
++				udf_debug("Metadata part num=%d\n",
++					le16_to_cpu(mdm->partitionNum));
++				udf_debug("Metadata part alloc unit size=%d\n",
++					le32_to_cpu(mdm->allocUnitSize));
++				udf_debug("Metadata file loc=%d\n",
++					le32_to_cpu(mdm->metadataFileLoc));
++				udf_debug("Mirror file loc=%d\n",
++				       le32_to_cpu(mdm->metadataMirrorFileLoc));
++				udf_debug("Bitmap file loc=%d\n",
++				       le32_to_cpu(mdm->metadataBitmapFileLoc));
++				udf_debug("Duplicate Flag: %d %d\n",
++					mdata->s_dup_md_flag, mdm->flags);
+ 			} else {
+ 				udf_debug("Unknown ident: %s\n",
+ 					  upm2->partIdent.ident);
+@@ -1296,7 +1492,9 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ 	if (lvd->integritySeqExt.extLength)
+ 		udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
+ 
+-	return 0;
++out_bh:
++	brelse(bh);
++	return ret;
+ }
+ 
+ /*
+@@ -1345,7 +1543,7 @@ static void udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc)
+  *	July 1, 1997 - Andrew E. Mileski
+  *	Written, tested, and released.
+  */
+-static int udf_process_sequence(struct super_block *sb, long block,
++static noinline int udf_process_sequence(struct super_block *sb, long block,
+ 				long lastblock, kernel_lb_addr *fileset)
+ {
+ 	struct buffer_head *bh = NULL;
+@@ -1354,19 +1552,25 @@ static int udf_process_sequence(struct super_block *sb, long block,
+ 	struct generic_desc *gd;
+ 	struct volDescPtr *vdp;
+ 	int done = 0;
+-	int i, j;
+ 	uint32_t vdsn;
+ 	uint16_t ident;
+ 	long next_s = 0, next_e = 0;
+ 
+ 	memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
+ 
+-	/* Read the main descriptor sequence */
++	/*
++	 * Read the main descriptor sequence and find which descriptors
++	 * are in it.
++	 */
+ 	for (; (!done && block <= lastblock); block++) {
+ 
+ 		bh = udf_read_tagged(sb, block, block, &ident);
+-		if (!bh)
+-			break;
++		if (!bh) {
++			printk(KERN_ERR "udf: Block %Lu of volume descriptor "
++			       "sequence is corrupted or we could not read "
++			       "it.\n", (unsigned long long)block);
++			return 1;
++		}
+ 
+ 		/* Process each descriptor (ISO 13346 3/8.3-8.4) */
+ 		gd = (struct generic_desc *)bh->b_data;
+@@ -1432,41 +1636,31 @@ static int udf_process_sequence(struct super_block *sb, long block,
+ 		}
+ 		brelse(bh);
+ 	}
+-	for (i = 0; i < VDS_POS_LENGTH; i++) {
+-		if (vds[i].block) {
+-			bh = udf_read_tagged(sb, vds[i].block, vds[i].block,
+-					     &ident);
+-
+-			if (i == VDS_POS_PRIMARY_VOL_DESC) {
+-				udf_load_pvoldesc(sb, bh);
+-			} else if (i == VDS_POS_LOGICAL_VOL_DESC) {
+-				if (udf_load_logicalvol(sb, bh, fileset)) {
+-					brelse(bh);
+-					return 1;
+-				}
+-			} else if (i == VDS_POS_PARTITION_DESC) {
+-				struct buffer_head *bh2 = NULL;
+-				if (udf_load_partdesc(sb, bh)) {
+-					brelse(bh);
+-					return 1;
+-				}
+-				for (j = vds[i].block + 1;
+-				     j <  vds[VDS_POS_TERMINATING_DESC].block;
+-				     j++) {
+-					bh2 = udf_read_tagged(sb, j, j, &ident);
+-					gd = (struct generic_desc *)bh2->b_data;
+-					if (ident == TAG_IDENT_PD)
+-						if (udf_load_partdesc(sb,
+-								      bh2)) {
+-							brelse(bh);
+-							brelse(bh2);
+-							return 1;
+-						}
+-					brelse(bh2);
+-				}
+-			}
+-			brelse(bh);
+-		}
++	/*
++	 * Now read interesting descriptors again and process them
++	 * in a suitable order
++	 */
++	if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) {
++		printk(KERN_ERR "udf: Primary Volume Descriptor not found!\n");
++		return 1;
++	}
++	if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block))
++		return 1;
++
++	if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb,
++	    vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset))
++		return 1;
++
++	if (vds[VDS_POS_PARTITION_DESC].block) {
++		/*
++		 * We rescan the whole descriptor sequence to find
++		 * partition descriptor blocks and process them.
++		 */
++		for (block = vds[VDS_POS_PARTITION_DESC].block;
++		     block < vds[VDS_POS_TERMINATING_DESC].block;
++		     block++)
++			if (udf_load_partdesc(sb, block))
++				return 1;
+ 	}
+ 
+ 	return 0;
+@@ -1478,6 +1672,7 @@ static int udf_process_sequence(struct super_block *sb, long block,
+ static int udf_check_valid(struct super_block *sb, int novrs, int silent)
+ {
+ 	long block;
++	struct udf_sb_info *sbi = UDF_SB(sb);
+ 
+ 	if (novrs) {
+ 		udf_debug("Validity check skipped because of novrs option\n");
+@@ -1485,27 +1680,22 @@ static int udf_check_valid(struct super_block *sb, int novrs, int silent)
+ 	}
+ 	/* Check that it is NSR02 compliant */
+ 	/* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */
+-	else {
+-		block = udf_vrs(sb, silent);
+-		if (block == -1) {
+-			struct udf_sb_info *sbi = UDF_SB(sb);
+-			udf_debug("Failed to read byte 32768. Assuming open "
+-				  "disc. Skipping validity check\n");
+-			if (!sbi->s_last_block)
+-				sbi->s_last_block = udf_get_last_block(sb);
+-			return 0;
+-		} else
+-			return !block;
+-	}
++	block = udf_vrs(sb, silent);
++	if (block == -1)
++		udf_debug("Failed to read byte 32768. Assuming open "
++			  "disc. Skipping validity check\n");
++	if (block && !sbi->s_last_block)
++		sbi->s_last_block = udf_get_last_block(sb);
++	return !block;
+ }
+ 
+-static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
++static int udf_load_sequence(struct super_block *sb, kernel_lb_addr *fileset)
+ {
+ 	struct anchorVolDescPtr *anchor;
+ 	uint16_t ident;
+ 	struct buffer_head *bh;
+ 	long main_s, main_e, reserve_s, reserve_e;
+-	int i, j;
++	int i;
+ 	struct udf_sb_info *sbi;
+ 
+ 	if (!sb)
+@@ -1515,6 +1705,7 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
+ 	for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
+ 		if (!sbi->s_anchor[i])
+ 			continue;
++
+ 		bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i],
+ 				     &ident);
+ 		if (!bh)
+@@ -1553,76 +1744,6 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
+ 	}
+ 	udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]);
+ 
+-	for (i = 0; i < sbi->s_partitions; i++) {
+-		kernel_lb_addr uninitialized_var(ino);
+-		struct udf_part_map *map = &sbi->s_partmaps[i];
+-		switch (map->s_partition_type) {
+-		case UDF_VIRTUAL_MAP15:
+-		case UDF_VIRTUAL_MAP20:
+-			if (!sbi->s_last_block) {
+-				sbi->s_last_block = udf_get_last_block(sb);
+-				udf_find_anchor(sb);
+-			}
+-
+-			if (!sbi->s_last_block) {
+-				udf_debug("Unable to determine Lastblock (For "
+-					  "Virtual Partition)\n");
+-				return 1;
+-			}
+-
+-			for (j = 0; j < sbi->s_partitions; j++) {
+-				struct udf_part_map *map2 = &sbi->s_partmaps[j];
+-				if (j != i &&
+-				    map->s_volumeseqnum ==
+-						map2->s_volumeseqnum &&
+-				    map->s_partition_num ==
+-						map2->s_partition_num) {
+-					ino.partitionReferenceNum = j;
+-					ino.logicalBlockNum =
+-						sbi->s_last_block -
+-							map2->s_partition_root;
+-					break;
+-				}
+-			}
+-
+-			if (j == sbi->s_partitions)
+-				return 1;
+-
+-			sbi->s_vat_inode = udf_iget(sb, ino);
+-			if (!sbi->s_vat_inode)
+-				return 1;
+-
+-			if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
+-				map->s_type_specific.s_virtual.s_start_offset =
+-					udf_ext0_offset(sbi->s_vat_inode);
+-				map->s_type_specific.s_virtual.s_num_entries =
+-					(sbi->s_vat_inode->i_size - 36) >> 2;
+-			} else if (map->s_partition_type == UDF_VIRTUAL_MAP20) {
+-				uint32_t pos;
+-				struct virtualAllocationTable20 *vat20;
+-
+-				pos = udf_block_map(sbi->s_vat_inode, 0);
+-				bh = sb_bread(sb, pos);
+-				if (!bh)
+-					return 1;
+-				vat20 = (struct virtualAllocationTable20 *)
+-					bh->b_data +
+-					udf_ext0_offset(sbi->s_vat_inode);
+-				map->s_type_specific.s_virtual.s_start_offset =
+-					le16_to_cpu(vat20->lengthHeader) +
+-					udf_ext0_offset(sbi->s_vat_inode);
+-				map->s_type_specific.s_virtual.s_num_entries =
+-					(sbi->s_vat_inode->i_size -
+-					 map->s_type_specific.s_virtual.
+-							s_start_offset) >> 2;
+-				brelse(bh);
+-			}
+-			map->s_partition_root = udf_get_pblock(sb, 0, i, 0);
+-			map->s_partition_len =
+-				sbi->s_partmaps[ino.partitionReferenceNum].
+-								s_partition_len;
+-		}
+-	}
+ 	return 0;
+ }
+ 
+@@ -1630,65 +1751,61 @@ static void udf_open_lvid(struct super_block *sb)
+ {
+ 	struct udf_sb_info *sbi = UDF_SB(sb);
+ 	struct buffer_head *bh = sbi->s_lvid_bh;
+-	if (bh) {
+-		kernel_timestamp cpu_time;
+-		struct logicalVolIntegrityDesc *lvid =
+-				(struct logicalVolIntegrityDesc *)bh->b_data;
+-		struct logicalVolIntegrityDescImpUse *lvidiu =
+-							udf_sb_lvidiu(sbi);
++	struct logicalVolIntegrityDesc *lvid;
++	struct logicalVolIntegrityDescImpUse *lvidiu;
++	if (!bh)
++		return;
+ 
+-		lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
+-		lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
+-		if (udf_time_to_stamp(&cpu_time, CURRENT_TIME))
+-			lvid->recordingDateAndTime = cpu_to_lets(cpu_time);
+-		lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN;
++	lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
++	lvidiu = udf_sb_lvidiu(sbi);
+ 
+-		lvid->descTag.descCRC = cpu_to_le16(
+-			udf_crc((char *)lvid + sizeof(tag),
+-				le16_to_cpu(lvid->descTag.descCRCLength),
+-				0));
++	lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
++	lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
++	udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
++				CURRENT_TIME);
++	lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN;
+ 
+-		lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
+-		mark_buffer_dirty(bh);
+-	}
++	lvid->descTag.descCRC = cpu_to_le16(
++		crc_itu_t(0, (char *)lvid + sizeof(tag),
++			le16_to_cpu(lvid->descTag.descCRCLength)));
++
++	lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
++	mark_buffer_dirty(bh);
+ }
+ 
+ static void udf_close_lvid(struct super_block *sb)
+ {
+-	kernel_timestamp cpu_time;
+ 	struct udf_sb_info *sbi = UDF_SB(sb);
+ 	struct buffer_head *bh = sbi->s_lvid_bh;
+ 	struct logicalVolIntegrityDesc *lvid;
++	struct logicalVolIntegrityDescImpUse *lvidiu;
+ 
+ 	if (!bh)
+ 		return;
+ 
+ 	lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
+ 
+-	if (lvid->integrityType == LVID_INTEGRITY_TYPE_OPEN) {
+-		struct logicalVolIntegrityDescImpUse *lvidiu =
+-							udf_sb_lvidiu(sbi);
+-		lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
+-		lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
+-		if (udf_time_to_stamp(&cpu_time, CURRENT_TIME))
+-			lvid->recordingDateAndTime = cpu_to_lets(cpu_time);
+-		if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev))
+-			lvidiu->maxUDFWriteRev =
+-					cpu_to_le16(UDF_MAX_WRITE_VERSION);
+-		if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev))
+-			lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev);
+-		if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev))
+-			lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev);
+-		lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
+-
+-		lvid->descTag.descCRC = cpu_to_le16(
+-			udf_crc((char *)lvid + sizeof(tag),
+-				le16_to_cpu(lvid->descTag.descCRCLength),
+-				0));
+-
+-		lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
+-		mark_buffer_dirty(bh);
+-	}
++	if (lvid->integrityType != LVID_INTEGRITY_TYPE_OPEN)
++		return;
++
++	lvidiu = udf_sb_lvidiu(sbi);
++	lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
++	lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
++	udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME);
++	if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev))
++		lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
++	if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev))
++		lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev);
++	if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev))
++		lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev);
++	lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
++
++	lvid->descTag.descCRC = cpu_to_le16(
++			crc_itu_t(0, (char *)lvid + sizeof(tag),
++				le16_to_cpu(lvid->descTag.descCRCLength)));
++
++	lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
++	mark_buffer_dirty(bh);
+ }
+ 
+ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
+@@ -1708,22 +1825,35 @@ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
+ 		vfree(bitmap);
+ }
+ 
+-/*
+- * udf_read_super
+- *
+- * PURPOSE
+- *	Complete the specified super block.
+- *
+- * PRE-CONDITIONS
+- *	sb			Pointer to superblock to complete - never NULL.
+- *	sb->s_dev		Device to read suberblock from.
+- *	options			Pointer to mount options.
+- *	silent			Silent flag.
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
+- */
++static void udf_free_partition(struct udf_part_map *map)
++{
++	int i;
++	struct udf_meta_data *mdata;
++
++	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
++		iput(map->s_uspace.s_table);
++	if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
++		iput(map->s_fspace.s_table);
++	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
++		udf_sb_free_bitmap(map->s_uspace.s_bitmap);
++	if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
++		udf_sb_free_bitmap(map->s_fspace.s_bitmap);
++	if (map->s_partition_type == UDF_SPARABLE_MAP15)
++		for (i = 0; i < 4; i++)
++			brelse(map->s_type_specific.s_sparing.s_spar_map[i]);
++	else if (map->s_partition_type == UDF_METADATA_MAP25) {
++		mdata = &map->s_type_specific.s_metadata;
++		iput(mdata->s_metadata_fe);
++		mdata->s_metadata_fe = NULL;
++
++		iput(mdata->s_mirror_fe);
++		mdata->s_mirror_fe = NULL;
++
++		iput(mdata->s_bitmap_fe);
++		mdata->s_bitmap_fe = NULL;
++	}
++}
++
+ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ {
+ 	int i;
+@@ -1776,8 +1906,11 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ 	sbi->s_nls_map = uopt.nls_map;
+ 
+ 	/* Set the block size for all transfers */
+-	if (!udf_set_blocksize(sb, uopt.blocksize))
++	if (!sb_min_blocksize(sb, uopt.blocksize)) {
++		udf_debug("Bad block size (%d)\n", uopt.blocksize);
++		printk(KERN_ERR "udf: bad block size (%d)\n", uopt.blocksize);
+ 		goto error_out;
++	}
+ 
+ 	if (uopt.session == 0xFFFFFFFF)
+ 		sbi->s_session = udf_get_last_session(sb);
+@@ -1789,7 +1922,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ 	sbi->s_last_block = uopt.lastblock;
+ 	sbi->s_anchor[0] = sbi->s_anchor[1] = 0;
+ 	sbi->s_anchor[2] = uopt.anchor;
+-	sbi->s_anchor[3] = 256;
+ 
+ 	if (udf_check_valid(sb, uopt.novrs, silent)) {
+ 		/* read volume recognition sequences */
+@@ -1806,7 +1938,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ 	sb->s_magic = UDF_SUPER_MAGIC;
+ 	sb->s_time_gran = 1000;
+ 
+-	if (udf_load_partition(sb, &fileset)) {
++	if (udf_load_sequence(sb, &fileset)) {
+ 		printk(KERN_WARNING "UDF-fs: No partition found (1)\n");
+ 		goto error_out;
+ 	}
+@@ -1856,12 +1988,12 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ 	}
+ 
+ 	if (!silent) {
+-		kernel_timestamp ts;
+-		udf_time_to_stamp(&ts, sbi->s_record_time);
++		timestamp ts;
++		udf_time_to_disk_stamp(&ts, sbi->s_record_time);
+ 		udf_info("UDF: Mounting volume '%s', "
+ 			 "timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
+-			 sbi->s_volume_ident, ts.year, ts.month, ts.day,
+-			 ts.hour, ts.minute, ts.typeAndTimezone);
++			 sbi->s_volume_ident, le16_to_cpu(ts.year), ts.month, ts.day,
++			 ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone));
+ 	}
+ 	if (!(sb->s_flags & MS_RDONLY))
+ 		udf_open_lvid(sb);
+@@ -1890,21 +2022,9 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ error_out:
+ 	if (sbi->s_vat_inode)
+ 		iput(sbi->s_vat_inode);
+-	if (sbi->s_partitions) {
+-		struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition];
+-		if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
+-			iput(map->s_uspace.s_table);
+-		if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
+-			iput(map->s_fspace.s_table);
+-		if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
+-			udf_sb_free_bitmap(map->s_uspace.s_bitmap);
+-		if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
+-			udf_sb_free_bitmap(map->s_fspace.s_bitmap);
+-		if (map->s_partition_type == UDF_SPARABLE_MAP15)
+-			for (i = 0; i < 4; i++)
+-				brelse(map->s_type_specific.s_sparing.
+-						s_spar_map[i]);
+-	}
++	if (sbi->s_partitions)
++		for (i = 0; i < sbi->s_partitions; i++)
++			udf_free_partition(&sbi->s_partmaps[i]);
+ #ifdef CONFIG_UDF_NLS
+ 	if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
+ 		unload_nls(sbi->s_nls_map);
+@@ -1920,8 +2040,8 @@ error_out:
+ 	return -EINVAL;
+ }
+ 
+-void udf_error(struct super_block *sb, const char *function,
+-	       const char *fmt, ...)
++static void udf_error(struct super_block *sb, const char *function,
++		      const char *fmt, ...)
+ {
+ 	va_list args;
+ 
+@@ -1948,19 +2068,6 @@ void udf_warning(struct super_block *sb, const char *function,
+ 	       sb->s_id, function, error_buf);
+ }
+ 
+-/*
+- * udf_put_super
+- *
+- * PURPOSE
+- *	Prepare for destruction of the superblock.
+- *
+- * DESCRIPTION
+- *	Called before the filesystem is unmounted.
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
+- */
+ static void udf_put_super(struct super_block *sb)
+ {
+ 	int i;
+@@ -1969,21 +2076,9 @@ static void udf_put_super(struct super_block *sb)
+ 	sbi = UDF_SB(sb);
+ 	if (sbi->s_vat_inode)
+ 		iput(sbi->s_vat_inode);
+-	if (sbi->s_partitions) {
+-		struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition];
+-		if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
+-			iput(map->s_uspace.s_table);
+-		if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
+-			iput(map->s_fspace.s_table);
+-		if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
+-			udf_sb_free_bitmap(map->s_uspace.s_bitmap);
+-		if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
+-			udf_sb_free_bitmap(map->s_fspace.s_bitmap);
+-		if (map->s_partition_type == UDF_SPARABLE_MAP15)
+-			for (i = 0; i < 4; i++)
+-				brelse(map->s_type_specific.s_sparing.
+-						s_spar_map[i]);
+-	}
++	if (sbi->s_partitions)
++		for (i = 0; i < sbi->s_partitions; i++)
++			udf_free_partition(&sbi->s_partmaps[i]);
+ #ifdef CONFIG_UDF_NLS
+ 	if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
+ 		unload_nls(sbi->s_nls_map);
+@@ -1996,19 +2091,6 @@ static void udf_put_super(struct super_block *sb)
+ 	sb->s_fs_info = NULL;
+ }
+ 
+-/*
+- * udf_stat_fs
+- *
+- * PURPOSE
+- *	Return info about the filesystem.
+- *
+- * DESCRIPTION
+- *	Called by sys_statfs()
+- *
+- * HISTORY
+- *	July 1, 1997 - Andrew E. Mileski
+- *	Written, tested, and released.
+- */
+ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
+ {
+ 	struct super_block *sb = dentry->d_sb;
+@@ -2035,10 +2117,6 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 	return 0;
+ }
+ 
+-static unsigned char udf_bitmap_lookup[16] = {
+-	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
+-};
+-
+ static unsigned int udf_count_free_bitmap(struct super_block *sb,
+ 					  struct udf_bitmap *bitmap)
+ {
+@@ -2048,7 +2126,6 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,
+ 	int block = 0, newblock;
+ 	kernel_lb_addr loc;
+ 	uint32_t bytes;
+-	uint8_t value;
+ 	uint8_t *ptr;
+ 	uint16_t ident;
+ 	struct spaceBitmapDesc *bm;
+@@ -2074,13 +2151,10 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,
+ 	ptr = (uint8_t *)bh->b_data;
+ 
+ 	while (bytes > 0) {
+-		while ((bytes > 0) && (index < sb->s_blocksize)) {
+-			value = ptr[index];
+-			accum += udf_bitmap_lookup[value & 0x0f];
+-			accum += udf_bitmap_lookup[value >> 4];
+-			index++;
+-			bytes--;
+-		}
++		u32 cur_bytes = min_t(u32, bytes, sb->s_blocksize - index);
++		accum += bitmap_weight((const unsigned long *)(ptr + index),
++					cur_bytes * 8);
++		bytes -= cur_bytes;
+ 		if (bytes) {
+ 			brelse(bh);
+ 			newblock = udf_get_lb_pblock(sb, loc, ++block);
+diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
+index 6ec9922..c3265e1 100644
+--- a/fs/udf/symlink.c
++++ b/fs/udf/symlink.c
+@@ -23,7 +23,6 @@
+ #include <asm/uaccess.h>
+ #include <linux/errno.h>
+ #include <linux/fs.h>
+-#include <linux/udf_fs.h>
+ #include <linux/time.h>
+ #include <linux/mm.h>
+ #include <linux/stat.h>
+diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
+index fe61be1..65e19b4 100644
+--- a/fs/udf/truncate.c
++++ b/fs/udf/truncate.c
+@@ -22,7 +22,6 @@
+ #include "udfdecl.h"
+ #include <linux/fs.h>
+ #include <linux/mm.h>
+-#include <linux/udf_fs.h>
+ #include <linux/buffer_head.h>
+ 
+ #include "udf_i.h"
+@@ -180,6 +179,24 @@ void udf_discard_prealloc(struct inode *inode)
+ 	brelse(epos.bh);
+ }
+ 
++static void udf_update_alloc_ext_desc(struct inode *inode,
++				      struct extent_position *epos,
++				      u32 lenalloc)
++{
++	struct super_block *sb = inode->i_sb;
++	struct udf_sb_info *sbi = UDF_SB(sb);
++
++	struct allocExtDesc *aed = (struct allocExtDesc *) (epos->bh->b_data);
++	int len = sizeof(struct allocExtDesc);
++
++	aed->lengthAllocDescs =	cpu_to_le32(lenalloc);
++	if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || sbi->s_udfrev >= 0x0201)
++		len += lenalloc;
++
++	udf_update_tag(epos->bh->b_data, len);
++	mark_buffer_dirty_inode(epos->bh, inode);
++}
++
+ void udf_truncate_extents(struct inode *inode)
+ {
+ 	struct extent_position epos;
+@@ -187,7 +204,6 @@ void udf_truncate_extents(struct inode *inode)
+ 	uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc;
+ 	int8_t etype;
+ 	struct super_block *sb = inode->i_sb;
+-	struct udf_sb_info *sbi = UDF_SB(sb);
+ 	sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset;
+ 	loff_t byte_offset;
+ 	int adsize;
+@@ -224,35 +240,15 @@ void udf_truncate_extents(struct inode *inode)
+ 				if (indirect_ext_len) {
+ 					/* We managed to free all extents in the
+ 					 * indirect extent - free it too */
+-					if (!epos.bh)
+-						BUG();
++					BUG_ON(!epos.bh);
+ 					udf_free_blocks(sb, inode, epos.block,
+ 							0, indirect_ext_len);
+-				} else {
+-					if (!epos.bh) {
+-						iinfo->i_lenAlloc =
+-								lenalloc;
+-						mark_inode_dirty(inode);
+-					} else {
+-						struct allocExtDesc *aed =
+-							(struct allocExtDesc *)
+-							(epos.bh->b_data);
+-						int len =
+-						    sizeof(struct allocExtDesc);
+-
+-						aed->lengthAllocDescs =
+-						    cpu_to_le32(lenalloc);
+-						if (!UDF_QUERY_FLAG(sb,
+-							UDF_FLAG_STRICT) ||
+-						    sbi->s_udfrev >= 0x0201)
+-							len += lenalloc;
+-
+-						udf_update_tag(epos.bh->b_data,
+-								len);
+-						mark_buffer_dirty_inode(
+-								epos.bh, inode);
+-					}
+-				}
++				} else if (!epos.bh) {
++					iinfo->i_lenAlloc = lenalloc;
++					mark_inode_dirty(inode);
++				} else
++					udf_update_alloc_ext_desc(inode,
++							&epos, lenalloc);
+ 				brelse(epos.bh);
+ 				epos.offset = sizeof(struct allocExtDesc);
+ 				epos.block = eloc;
+@@ -272,29 +268,14 @@ void udf_truncate_extents(struct inode *inode)
+ 		}
+ 
+ 		if (indirect_ext_len) {
+-			if (!epos.bh)
+-				BUG();
++			BUG_ON(!epos.bh);
+ 			udf_free_blocks(sb, inode, epos.block, 0,
+ 					indirect_ext_len);
+-		} else {
+-			if (!epos.bh) {
+-				iinfo->i_lenAlloc = lenalloc;
+-				mark_inode_dirty(inode);
+-			} else {
+-				struct allocExtDesc *aed =
+-				    (struct allocExtDesc *)(epos.bh->b_data);
+-				aed->lengthAllocDescs = cpu_to_le32(lenalloc);
+-				if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) ||
+-				    sbi->s_udfrev >= 0x0201)
+-					udf_update_tag(epos.bh->b_data,
+-						lenalloc +
+-						sizeof(struct allocExtDesc));
+-				else
+-					udf_update_tag(epos.bh->b_data,
+-						sizeof(struct allocExtDesc));
+-				mark_buffer_dirty_inode(epos.bh, inode);
+-			}
+-		}
++		} else if (!epos.bh) {
++			iinfo->i_lenAlloc = lenalloc;
++			mark_inode_dirty(inode);
++		} else
++			udf_update_alloc_ext_desc(inode, &epos, lenalloc);
+ 	} else if (inode->i_size) {
+ 		if (byte_offset) {
+ 			kernel_long_ad extent;
+diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h
+index ccc52f1..4f86b1d 100644
+--- a/fs/udf/udf_i.h
++++ b/fs/udf/udf_i.h
+@@ -1,10 +1,32 @@
+-#ifndef __LINUX_UDF_I_H
+-#define __LINUX_UDF_I_H
++#ifndef _UDF_I_H
++#define _UDF_I_H
++
++struct udf_inode_info {
++	struct timespec		i_crtime;
++	/* Physical address of inode */
++	kernel_lb_addr		i_location;
++	__u64			i_unique;
++	__u32			i_lenEAttr;
++	__u32			i_lenAlloc;
++	__u64			i_lenExtents;
++	__u32			i_next_alloc_block;
++	__u32			i_next_alloc_goal;
++	unsigned		i_alloc_type : 3;
++	unsigned		i_efe : 1;	/* extendedFileEntry */
++	unsigned		i_use : 1;	/* unallocSpaceEntry */
++	unsigned		i_strat4096 : 1;
++	unsigned		reserved : 26;
++	union {
++		short_ad	*i_sad;
++		long_ad		*i_lad;
++		__u8		*i_data;
++	} i_ext;
++	struct inode vfs_inode;
++};
+ 
+-#include <linux/udf_fs_i.h>
+ static inline struct udf_inode_info *UDF_I(struct inode *inode)
+ {
+ 	return list_entry(inode, struct udf_inode_info, vfs_inode);
+ }
+ 
+-#endif /* !defined(_LINUX_UDF_I_H) */
++#endif /* _UDF_I_H) */
+diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
+index 737d1c6..1c1c514 100644
+--- a/fs/udf/udf_sb.h
++++ b/fs/udf/udf_sb.h
+@@ -1,10 +1,12 @@
+ #ifndef __LINUX_UDF_SB_H
+ #define __LINUX_UDF_SB_H
+ 
++#include <linux/mutex.h>
++
+ /* Since UDF 2.01 is ISO 13346 based... */
+ #define UDF_SUPER_MAGIC			0x15013346
+ 
+-#define UDF_MAX_READ_VERSION		0x0201
++#define UDF_MAX_READ_VERSION		0x0250
+ #define UDF_MAX_WRITE_VERSION		0x0201
+ 
+ #define UDF_FLAG_USE_EXTENDED_FE	0
+@@ -38,6 +40,111 @@
+ #define UDF_PART_FLAG_REWRITABLE	0x0040
+ #define UDF_PART_FLAG_OVERWRITABLE	0x0080
+ 
++#define UDF_MAX_BLOCK_LOADED	8
++
++#define UDF_TYPE1_MAP15			0x1511U
++#define UDF_VIRTUAL_MAP15		0x1512U
++#define UDF_VIRTUAL_MAP20		0x2012U
++#define UDF_SPARABLE_MAP15		0x1522U
++#define UDF_METADATA_MAP25		0x2511U
++
++#pragma pack(1) /* XXX(hch): Why?  This file just defines in-core structures */
++
++struct udf_meta_data {
++	__u32	s_meta_file_loc;
++	__u32	s_mirror_file_loc;
++	__u32	s_bitmap_file_loc;
++	__u32	s_alloc_unit_size;
++	__u16	s_align_unit_size;
++	__u8 	s_dup_md_flag;
++	struct inode *s_metadata_fe;
++	struct inode *s_mirror_fe;
++	struct inode *s_bitmap_fe;
++};
++
++struct udf_sparing_data {
++	__u16	s_packet_len;
++	struct buffer_head *s_spar_map[4];
++};
++
++struct udf_virtual_data {
++	__u32	s_num_entries;
++	__u16	s_start_offset;
++};
++
++struct udf_bitmap {
++	__u32			s_extLength;
++	__u32			s_extPosition;
++	__u16			s_nr_groups;
++	struct buffer_head 	**s_block_bitmap;
++};
++
++struct udf_part_map {
++	union {
++		struct udf_bitmap	*s_bitmap;
++		struct inode		*s_table;
++	} s_uspace;
++	union {
++		struct udf_bitmap	*s_bitmap;
++		struct inode		*s_table;
++	} s_fspace;
++	__u32	s_partition_root;
++	__u32	s_partition_len;
++	__u16	s_partition_type;
++	__u16	s_partition_num;
++	union {
++		struct udf_sparing_data s_sparing;
++		struct udf_virtual_data s_virtual;
++		struct udf_meta_data s_metadata;
++	} s_type_specific;
++	__u32	(*s_partition_func)(struct super_block *, __u32, __u16, __u32);
++	__u16	s_volumeseqnum;
++	__u16	s_partition_flags;
++};
++
++#pragma pack()
++
++struct udf_sb_info {
++	struct udf_part_map	*s_partmaps;
++	__u8			s_volume_ident[32];
++
++	/* Overall info */
++	__u16			s_partitions;
++	__u16			s_partition;
++
++	/* Sector headers */
++	__s32			s_session;
++	__u32			s_anchor[3];
++	__u32			s_last_block;
++
++	struct buffer_head	*s_lvid_bh;
++
++	/* Default permissions */
++	mode_t			s_umask;
++	gid_t			s_gid;
++	uid_t			s_uid;
++
++	/* Root Info */
++	struct timespec		s_record_time;
++
++	/* Fileset Info */
++	__u16			s_serial_number;
++
++	/* highest UDF revision we have recorded to this media */
++	__u16			s_udfrev;
++
++	/* Miscellaneous flags */
++	__u32			s_flags;
++
++	/* Encoding info */
++	struct nls_table	*s_nls_map;
++
++	/* VAT inode */
++	struct inode		*s_vat_inode;
++
++	struct mutex		s_alloc_mutex;
++};
++
+ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
+ {
+ 	return sb->s_fs_info;
+diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
+index 681dc2b..f3f45d0 100644
+--- a/fs/udf/udfdecl.h
++++ b/fs/udf/udfdecl.h
+@@ -1,17 +1,37 @@
+ #ifndef __UDF_DECL_H
+ #define __UDF_DECL_H
+ 
+-#include <linux/udf_fs.h>
+ #include "ecma_167.h"
+ #include "osta_udf.h"
+ 
+ #include <linux/fs.h>
+ #include <linux/types.h>
+-#include <linux/udf_fs_i.h>
+-#include <linux/udf_fs_sb.h>
+ #include <linux/buffer_head.h>
++#include <linux/udf_fs_i.h>
+ 
++#include "udf_sb.h"
+ #include "udfend.h"
++#include "udf_i.h"
++
++#define UDF_PREALLOCATE
++#define UDF_DEFAULT_PREALLOC_BLOCKS	8
++
++#define UDFFS_DEBUG
++
++#ifdef UDFFS_DEBUG
++#define udf_debug(f, a...) \
++do { \
++	printk(KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
++		__FILE__, __LINE__, __func__); \
++	printk(f, ##a); \
++} while (0)
++#else
++#define udf_debug(f, a...) /**/
++#endif
++
++#define udf_info(f, a...) \
++	printk(KERN_INFO "UDF-fs INFO " f, ##a);
++
+ 
+ #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
+ #define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
+@@ -23,16 +43,24 @@
+ #define UDF_NAME_LEN		256
+ #define UDF_PATH_LEN		1023
+ 
+-#define udf_file_entry_alloc_offset(inode)\
+-	(UDF_I(inode)->i_use ?\
+-		sizeof(struct unallocSpaceEntry) :\
+-		((UDF_I(inode)->i_efe ?\
+-			sizeof(struct extendedFileEntry) :\
+-			sizeof(struct fileEntry)) + UDF_I(inode)->i_lenEAttr))
+-
+-#define udf_ext0_offset(inode)\
+-	(UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ?\
+-		udf_file_entry_alloc_offset(inode) : 0)
++static inline size_t udf_file_entry_alloc_offset(struct inode *inode)
++{
++	struct udf_inode_info *iinfo = UDF_I(inode);
++	if (iinfo->i_use)
++		return sizeof(struct unallocSpaceEntry);
++	else if (iinfo->i_efe)
++		return sizeof(struct extendedFileEntry) + iinfo->i_lenEAttr;
++	else
++		return sizeof(struct fileEntry) + iinfo->i_lenEAttr;
++}
++
++static inline size_t udf_ext0_offset(struct inode *inode)
++{
++	if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
++		return udf_file_entry_alloc_offset(inode);
++	else
++		return 0;
++}
+ 
+ #define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset))
+ 
+@@ -83,7 +111,6 @@ struct extent_position {
+ };
+ 
+ /* super.c */
+-extern void udf_error(struct super_block *, const char *, const char *, ...);
+ extern void udf_warning(struct super_block *, const char *, const char *, ...);
+ 
+ /* namei.c */
+@@ -150,6 +177,8 @@ extern uint32_t udf_get_pblock_virt20(struct super_block *, uint32_t, uint16_t,
+ 				      uint32_t);
+ extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t,
+ 				      uint32_t);
++extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t,
++					  uint32_t);
+ extern int udf_relocate_blocks(struct super_block *, long, long *);
+ 
+ /* unicode.c */
+@@ -157,7 +186,7 @@ extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int);
+ extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *,
+ 			    int);
+ extern int udf_build_ustr(struct ustr *, dstring *, int);
+-extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
++extern int udf_CS0toUTF8(struct ustr *, const struct ustr *);
+ 
+ /* ialloc.c */
+ extern void udf_free_inode(struct inode *);
+@@ -191,11 +220,9 @@ extern struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize,
+ extern long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int);
+ extern short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int);
+ 
+-/* crc.c */
+-extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
+-
+ /* udftime.c */
+-extern time_t *udf_stamp_to_time(time_t *, long *, kernel_timestamp);
+-extern kernel_timestamp *udf_time_to_stamp(kernel_timestamp *, struct timespec);
++extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest,
++						timestamp src);
++extern timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec src);
+ 
+ #endif				/* __UDF_DECL_H */
+diff --git a/fs/udf/udfend.h b/fs/udf/udfend.h
+index c4bd120..489f52f 100644
+--- a/fs/udf/udfend.h
++++ b/fs/udf/udfend.h
+@@ -24,17 +24,6 @@ static inline lb_addr cpu_to_lelb(kernel_lb_addr in)
+ 	return out;
+ }
+ 
+-static inline kernel_timestamp lets_to_cpu(timestamp in)
+-{
+-	kernel_timestamp out;
+-
+-	memcpy(&out, &in, sizeof(timestamp));
+-	out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone);
+-	out.year = le16_to_cpu(in.year);
+-
+-	return out;
+-}
+-
+ static inline short_ad lesa_to_cpu(short_ad in)
+ {
+ 	short_ad out;
+@@ -85,15 +74,4 @@ static inline kernel_extent_ad leea_to_cpu(extent_ad in)
+ 	return out;
+ }
+ 
+-static inline timestamp cpu_to_lets(kernel_timestamp in)
+-{
+-	timestamp out;
+-
+-	memcpy(&out, &in, sizeof(timestamp));
+-	out.typeAndTimezone = cpu_to_le16(in.typeAndTimezone);
+-	out.year = cpu_to_le16(in.year);
+-
+-	return out;
+-}
+-
+ #endif /* __UDF_ENDIAN_H */
+diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
+index ce59573..5f81165 100644
+--- a/fs/udf/udftime.c
++++ b/fs/udf/udftime.c
+@@ -85,39 +85,38 @@ extern struct timezone sys_tz;
+ #define SECS_PER_HOUR	(60 * 60)
+ #define SECS_PER_DAY	(SECS_PER_HOUR * 24)
+ 
+-time_t *udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src)
++struct timespec *udf_disk_stamp_to_time(struct timespec *dest, timestamp src)
+ {
+ 	int yday;
+-	uint8_t type = src.typeAndTimezone >> 12;
++	u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone);
++	u16 year = le16_to_cpu(src.year);
++	uint8_t type = typeAndTimezone >> 12;
+ 	int16_t offset;
+ 
+ 	if (type == 1) {
+-		offset = src.typeAndTimezone << 4;
++		offset = typeAndTimezone << 4;
+ 		/* sign extent offset */
+ 		offset = (offset >> 4);
+ 		if (offset == -2047) /* unspecified offset */
+ 			offset = 0;
+-	} else {
++	} else
+ 		offset = 0;
+-	}
+ 
+-	if ((src.year < EPOCH_YEAR) ||
+-	    (src.year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) {
+-		*dest = -1;
+-		*dest_usec = -1;
++	if ((year < EPOCH_YEAR) ||
++	    (year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) {
+ 		return NULL;
+ 	}
+-	*dest = year_seconds[src.year - EPOCH_YEAR];
+-	*dest -= offset * 60;
++	dest->tv_sec = year_seconds[year - EPOCH_YEAR];
++	dest->tv_sec -= offset * 60;
+ 
+-	yday = ((__mon_yday[__isleap(src.year)][src.month - 1]) + src.day - 1);
+-	*dest += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second;
+-	*dest_usec = src.centiseconds * 10000 +
+-			src.hundredsOfMicroseconds * 100 + src.microseconds;
++	yday = ((__mon_yday[__isleap(year)][src.month - 1]) + src.day - 1);
++	dest->tv_sec += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second;
++	dest->tv_nsec = 1000 * (src.centiseconds * 10000 +
++			src.hundredsOfMicroseconds * 100 + src.microseconds);
+ 	return dest;
+ }
+ 
+-kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
++timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec ts)
+ {
+ 	long int days, rem, y;
+ 	const unsigned short int *ip;
+@@ -128,7 +127,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
+ 	if (!dest)
+ 		return NULL;
+ 
+-	dest->typeAndTimezone = 0x1000 | (offset & 0x0FFF);
++	dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF));
+ 
+ 	ts.tv_sec += offset * 60;
+ 	days = ts.tv_sec / SECS_PER_DAY;
+@@ -151,7 +150,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
+ 			 - LEAPS_THRU_END_OF(y - 1));
+ 		y = yg;
+ 	}
+-	dest->year = y;
++	dest->year = cpu_to_le16(y);
+ 	ip = __mon_yday[__isleap(y)];
+ 	for (y = 11; days < (long int)ip[y]; --y)
+ 		continue;
+diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
+index e533b11..9fdf8c9 100644
+--- a/fs/udf/unicode.c
++++ b/fs/udf/unicode.c
+@@ -23,7 +23,7 @@
+ #include <linux/kernel.h>
+ #include <linux/string.h>	/* for memset */
+ #include <linux/nls.h>
+-#include <linux/udf_fs.h>
++#include <linux/crc-itu-t.h>
+ 
+ #include "udf_sb.h"
+ 
+@@ -49,14 +49,16 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
+ {
+ 	int usesize;
+ 
+-	if ((!dest) || (!ptr) || (!size))
++	if (!dest || !ptr || !size)
+ 		return -1;
++	BUG_ON(size < 2);
+ 
+-	memset(dest, 0, sizeof(struct ustr));
+-	usesize = (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size;
++	usesize = min_t(size_t, ptr[size - 1], sizeof(dest->u_name));
++	usesize = min(usesize, size - 2);
+ 	dest->u_cmpID = ptr[0];
+-	dest->u_len = ptr[size - 1];
+-	memcpy(dest->u_name, ptr + 1, usesize - 1);
++	dest->u_len = usesize;
++	memcpy(dest->u_name, ptr + 1, usesize);
++	memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize);
+ 
+ 	return 0;
+ }
+@@ -83,9 +85,6 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
+  * PURPOSE
+  *	Convert OSTA Compressed Unicode to the UTF-8 equivalent.
+  *
+- * DESCRIPTION
+- *	This routine is only called by udf_filldir().
+- *
+  * PRE-CONDITIONS
+  *	utf			Pointer to UTF-8 output buffer.
+  *	ocu			Pointer to OSTA Compressed Unicode input buffer
+@@ -99,43 +98,39 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
+  *	November 12, 1997 - Andrew E. Mileski
+  *	Written, tested, and released.
+  */
+-int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
++int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
+ {
+-	uint8_t *ocu;
+-	uint32_t c;
++	const uint8_t *ocu;
+ 	uint8_t cmp_id, ocu_len;
+ 	int i;
+ 
+-	ocu = ocu_i->u_name;
+-
+ 	ocu_len = ocu_i->u_len;
+-	cmp_id = ocu_i->u_cmpID;
+-	utf_o->u_len = 0;
+-
+ 	if (ocu_len == 0) {
+ 		memset(utf_o, 0, sizeof(struct ustr));
+-		utf_o->u_cmpID = 0;
+-		utf_o->u_len = 0;
+ 		return 0;
+ 	}
+ 
+-	if ((cmp_id != 8) && (cmp_id != 16)) {
++	cmp_id = ocu_i->u_cmpID;
++	if (cmp_id != 8 && cmp_id != 16) {
++		memset(utf_o, 0, sizeof(struct ustr));
+ 		printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
+ 		       cmp_id, ocu_i->u_name);
+ 		return 0;
+ 	}
+ 
++	ocu = ocu_i->u_name;
++	utf_o->u_len = 0;
+ 	for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) {
+ 
+ 		/* Expand OSTA compressed Unicode to Unicode */
+-		c = ocu[i++];
++		uint32_t c = ocu[i++];
+ 		if (cmp_id == 16)
+ 			c = (c << 8) | ocu[i++];
+ 
+ 		/* Compress Unicode to UTF-8 */
+-		if (c < 0x80U) {
++		if (c < 0x80U)
+ 			utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
+-		} else if (c < 0x800U) {
++		else if (c < 0x800U) {
+ 			utf_o->u_name[utf_o->u_len++] =
+ 						(uint8_t)(0xc0 | (c >> 6));
+ 			utf_o->u_name[utf_o->u_len++] =
+@@ -255,35 +250,32 @@ error_out:
+ }
+ 
+ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
+-			struct ustr *ocu_i)
++			const struct ustr *ocu_i)
+ {
+-	uint8_t *ocu;
+-	uint32_t c;
++	const uint8_t *ocu;
+ 	uint8_t cmp_id, ocu_len;
+ 	int i;
+ 
+-	ocu = ocu_i->u_name;
+ 
+ 	ocu_len = ocu_i->u_len;
+-	cmp_id = ocu_i->u_cmpID;
+-	utf_o->u_len = 0;
+-
+ 	if (ocu_len == 0) {
+ 		memset(utf_o, 0, sizeof(struct ustr));
+-		utf_o->u_cmpID = 0;
+-		utf_o->u_len = 0;
+ 		return 0;
+ 	}
+ 
+-	if ((cmp_id != 8) && (cmp_id != 16)) {
++	cmp_id = ocu_i->u_cmpID;
++	if (cmp_id != 8 && cmp_id != 16) {
++		memset(utf_o, 0, sizeof(struct ustr));
+ 		printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
+ 		       cmp_id, ocu_i->u_name);
+ 		return 0;
+ 	}
+ 
++	ocu = ocu_i->u_name;
++	utf_o->u_len = 0;
+ 	for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) {
+ 		/* Expand OSTA compressed Unicode to Unicode */
+-		c = ocu[i++];
++		uint32_t c = ocu[i++];
+ 		if (cmp_id == 16)
+ 			c = (c << 8) | ocu[i++];
+ 
+@@ -463,7 +455,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
+ 		} else if (newIndex > 250)
+ 			newIndex = 250;
+ 		newName[newIndex++] = CRC_MARK;
+-		valueCRC = udf_crc(fidName, fidNameLen, 0);
++		valueCRC = crc_itu_t(0, fidName, fidNameLen);
+ 		newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
+ 		newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
+ 		newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
+diff --git a/fs/utimes.c b/fs/utimes.c
+index b18da9c..a2bef77 100644
+--- a/fs/utimes.c
++++ b/fs/utimes.c
+@@ -2,6 +2,7 @@
+ #include <linux/file.h>
+ #include <linux/fs.h>
+ #include <linux/linkage.h>
++#include <linux/mount.h>
+ #include <linux/namei.h>
+ #include <linux/sched.h>
+ #include <linux/stat.h>
+@@ -59,6 +60,7 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
+ 	struct inode *inode;
+ 	struct iattr newattrs;
+ 	struct file *f = NULL;
++	struct vfsmount *mnt;
+ 
+ 	error = -EINVAL;
+ 	if (times && (!nsec_valid(times[0].tv_nsec) ||
+@@ -79,18 +81,20 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
+ 		if (!f)
+ 			goto out;
+ 		dentry = f->f_path.dentry;
++		mnt = f->f_path.mnt;
+ 	} else {
+ 		error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
+ 		if (error)
+ 			goto out;
+ 
+ 		dentry = nd.path.dentry;
++		mnt = nd.path.mnt;
+ 	}
+ 
+ 	inode = dentry->d_inode;
+ 
+-	error = -EROFS;
+-	if (IS_RDONLY(inode))
++	error = mnt_want_write(mnt);
++	if (error)
+ 		goto dput_and_out;
+ 
+ 	/* Don't worry, the checks are done in inode_change_ok() */
+@@ -98,7 +102,7 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
+ 	if (times) {
+ 		error = -EPERM;
+                 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+-                        goto dput_and_out;
++			goto mnt_drop_write_and_out;
+ 
+ 		if (times[0].tv_nsec == UTIME_OMIT)
+ 			newattrs.ia_valid &= ~ATTR_ATIME;
+@@ -118,22 +122,24 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
+ 	} else {
+ 		error = -EACCES;
+                 if (IS_IMMUTABLE(inode))
+-                        goto dput_and_out;
++			goto mnt_drop_write_and_out;
+ 
+ 		if (!is_owner_or_cap(inode)) {
+ 			if (f) {
+ 				if (!(f->f_mode & FMODE_WRITE))
+-					goto dput_and_out;
++					goto mnt_drop_write_and_out;
+ 			} else {
+ 				error = vfs_permission(&nd, MAY_WRITE);
+ 				if (error)
+-					goto dput_and_out;
++					goto mnt_drop_write_and_out;
+ 			}
+ 		}
+ 	}
+ 	mutex_lock(&inode->i_mutex);
+ 	error = notify_change(dentry, &newattrs);
+ 	mutex_unlock(&inode->i_mutex);
++mnt_drop_write_and_out:
++	mnt_drop_write(mnt);
+ dput_and_out:
+ 	if (f)
+ 		fput(f);
+diff --git a/fs/xattr.c b/fs/xattr.c
+index 3acab16..89a942f 100644
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -11,6 +11,7 @@
+ #include <linux/slab.h>
+ #include <linux/file.h>
+ #include <linux/xattr.h>
++#include <linux/mount.h>
+ #include <linux/namei.h>
+ #include <linux/security.h>
+ #include <linux/syscalls.h>
+@@ -32,8 +33,6 @@ xattr_permission(struct inode *inode, const char *name, int mask)
+ 	 * filesystem  or on an immutable / append-only inode.
+ 	 */
+ 	if (mask & MAY_WRITE) {
+-		if (IS_RDONLY(inode))
+-			return -EROFS;
+ 		if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ 			return -EPERM;
+ 	}
+@@ -262,7 +261,11 @@ sys_setxattr(char __user *path, char __user *name, void __user *value,
+ 	error = user_path_walk(path, &nd);
+ 	if (error)
+ 		return error;
+-	error = setxattr(nd.path.dentry, name, value, size, flags);
++	error = mnt_want_write(nd.path.mnt);
++	if (!error) {
++		error = setxattr(nd.path.dentry, name, value, size, flags);
++		mnt_drop_write(nd.path.mnt);
++	}
+ 	path_put(&nd.path);
+ 	return error;
+ }
+@@ -277,7 +280,11 @@ sys_lsetxattr(char __user *path, char __user *name, void __user *value,
+ 	error = user_path_walk_link(path, &nd);
+ 	if (error)
+ 		return error;
+-	error = setxattr(nd.path.dentry, name, value, size, flags);
++	error = mnt_want_write(nd.path.mnt);
++	if (!error) {
++		error = setxattr(nd.path.dentry, name, value, size, flags);
++		mnt_drop_write(nd.path.mnt);
++	}
+ 	path_put(&nd.path);
+ 	return error;
+ }
+@@ -295,7 +302,11 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
+ 		return error;
+ 	dentry = f->f_path.dentry;
+ 	audit_inode(NULL, dentry);
+-	error = setxattr(dentry, name, value, size, flags);
++	error = mnt_want_write(f->f_path.mnt);
++	if (!error) {
++		error = setxattr(dentry, name, value, size, flags);
++		mnt_drop_write(f->f_path.mnt);
++	}
+ 	fput(f);
+ 	return error;
+ }
+@@ -482,7 +493,11 @@ sys_removexattr(char __user *path, char __user *name)
+ 	error = user_path_walk(path, &nd);
+ 	if (error)
+ 		return error;
+-	error = removexattr(nd.path.dentry, name);
++	error = mnt_want_write(nd.path.mnt);
++	if (!error) {
++		error = removexattr(nd.path.dentry, name);
++		mnt_drop_write(nd.path.mnt);
++	}
+ 	path_put(&nd.path);
+ 	return error;
+ }
+@@ -496,7 +511,11 @@ sys_lremovexattr(char __user *path, char __user *name)
+ 	error = user_path_walk_link(path, &nd);
+ 	if (error)
+ 		return error;
+-	error = removexattr(nd.path.dentry, name);
++	error = mnt_want_write(nd.path.mnt);
++	if (!error) {
++		error = removexattr(nd.path.dentry, name);
++		mnt_drop_write(nd.path.mnt);
++	}
+ 	path_put(&nd.path);
+ 	return error;
+ }
+@@ -513,7 +532,11 @@ sys_fremovexattr(int fd, char __user *name)
+ 		return error;
+ 	dentry = f->f_path.dentry;
+ 	audit_inode(NULL, dentry);
+-	error = removexattr(dentry, name);
++	error = mnt_want_write(f->f_path.mnt);
++	if (!error) {
++		error = removexattr(dentry, name);
++		mnt_drop_write(f->f_path.mnt);
++	}
+ 	fput(f);
+ 	return error;
+ }
+diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig
+index 35115bc..524021f 100644
+--- a/fs/xfs/Kconfig
++++ b/fs/xfs/Kconfig
+@@ -35,18 +35,6 @@ config XFS_QUOTA
+ 	  with or without the generic quota support enabled (CONFIG_QUOTA) -
+ 	  they are completely independent subsystems.
+ 
+-config XFS_SECURITY
+-	bool "XFS Security Label support"
+-	depends on XFS_FS
+-	help
+-	  Security labels support alternative access control models
+-	  implemented by security modules like SELinux.  This option
+-	  enables an extended attribute namespace for inode security
+-	  labels in the XFS filesystem.
+-
+-	  If you are not using a security module that requires using
+-	  extended attributes for inode security labels, say N.
+-
+ config XFS_POSIX_ACL
+ 	bool "XFS POSIX ACL support"
+ 	depends on XFS_FS
+diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
+index e040f1c..9b1bb17 100644
+--- a/fs/xfs/linux-2.6/kmem.c
++++ b/fs/xfs/linux-2.6/kmem.c
+@@ -37,7 +37,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags)
+ #ifdef DEBUG
+ 	if (unlikely(!(flags & KM_LARGE) && (size > PAGE_SIZE))) {
+ 		printk(KERN_WARNING "Large %s attempt, size=%ld\n",
+-			__FUNCTION__, (long)size);
++			__func__, (long)size);
+ 		dump_stack();
+ 	}
+ #endif
+@@ -52,7 +52,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags)
+ 		if (!(++retries % 100))
+ 			printk(KERN_ERR "XFS: possible memory allocation "
+ 					"deadlock in %s (mode:0x%x)\n",
+-					__FUNCTION__, lflags);
++					__func__, lflags);
+ 		congestion_wait(WRITE, HZ/50);
+ 	} while (1);
+ }
+@@ -129,7 +129,7 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
+ 		if (!(++retries % 100))
+ 			printk(KERN_ERR "XFS: possible memory allocation "
+ 					"deadlock in %s (mode:0x%x)\n",
+-					__FUNCTION__, lflags);
++					__func__, lflags);
+ 		congestion_wait(WRITE, HZ/50);
+ 	} while (1);
+ }
+diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h
+index 2009e6d..3abe7e9 100644
+--- a/fs/xfs/linux-2.6/sema.h
++++ b/fs/xfs/linux-2.6/sema.h
+@@ -20,8 +20,8 @@
+ 
+ #include <linux/time.h>
+ #include <linux/wait.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ 
+ /*
+  * sema_t structure just maps to struct semaphore in Linux kernel.
+diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
+index e051952..a55c3b2 100644
+--- a/fs/xfs/linux-2.6/xfs_aops.c
++++ b/fs/xfs/linux-2.6/xfs_aops.c
+@@ -243,8 +243,12 @@ xfs_end_bio_unwritten(
+ 	size_t			size = ioend->io_size;
+ 
+ 	if (likely(!ioend->io_error)) {
+-		if (!XFS_FORCED_SHUTDOWN(ip->i_mount))
+-			xfs_iomap_write_unwritten(ip, offset, size);
++		if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
++			int error;
++			error = xfs_iomap_write_unwritten(ip, offset, size);
++			if (error)
++				ioend->io_error = error;
++		}
+ 		xfs_setfilesize(ioend);
+ 	}
+ 	xfs_destroy_ioend(ioend);
+@@ -1532,9 +1536,9 @@ xfs_vm_bmap(
+ 	struct xfs_inode	*ip = XFS_I(inode);
+ 
+ 	xfs_itrace_entry(XFS_I(inode));
+-	xfs_rwlock(ip, VRWLOCK_READ);
++	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+ 	xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
+-	xfs_rwunlock(ip, VRWLOCK_READ);
++	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ 	return generic_block_bmap(mapping, block, xfs_get_blocks);
+ }
+ 
+diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
+index e347bfd..52f6846 100644
+--- a/fs/xfs/linux-2.6/xfs_buf.c
++++ b/fs/xfs/linux-2.6/xfs_buf.c
+@@ -400,7 +400,7 @@ _xfs_buf_lookup_pages(
+ 				printk(KERN_ERR
+ 					"XFS: possible memory allocation "
+ 					"deadlock in %s (mode:0x%x)\n",
+-					__FUNCTION__, gfp_mask);
++					__func__, gfp_mask);
+ 
+ 			XFS_STATS_INC(xb_page_retries);
+ 			xfsbufd_wakeup(0, gfp_mask);
+@@ -598,7 +598,7 @@ xfs_buf_get_flags(
+ 		error = _xfs_buf_map_pages(bp, flags);
+ 		if (unlikely(error)) {
+ 			printk(KERN_WARNING "%s: failed to map pages\n",
+-					__FUNCTION__);
++					__func__);
+ 			goto no_buffer;
+ 		}
+ 	}
+@@ -778,7 +778,7 @@ xfs_buf_get_noaddr(
+ 	error = _xfs_buf_map_pages(bp, XBF_MAPPED);
+ 	if (unlikely(error)) {
+ 		printk(KERN_WARNING "%s: failed to map pages\n",
+-				__FUNCTION__);
++				__func__);
+ 		goto fail_free_mem;
+ 	}
+ 
+@@ -1060,7 +1060,7 @@ xfs_buf_iostart(
+ 		bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC);
+ 		bp->b_flags |= flags & (XBF_DELWRI | XBF_ASYNC);
+ 		xfs_buf_delwri_queue(bp, 1);
+-		return status;
++		return 0;
+ 	}
+ 
+ 	bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC | XBF_DELWRI | \
+diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
+index a3d207d..841d788 100644
+--- a/fs/xfs/linux-2.6/xfs_buf.h
++++ b/fs/xfs/linux-2.6/xfs_buf.h
+@@ -387,11 +387,15 @@ static inline int XFS_bwrite(xfs_buf_t *bp)
+ 	return error;
+ }
+ 
+-static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
++/*
++ * No error can be returned from xfs_buf_iostart for delwri
++ * buffers as they are queued and no I/O is issued.
++ */
++static inline void xfs_bdwrite(void *mp, xfs_buf_t *bp)
+ {
+ 	bp->b_strat = xfs_bdstrat_cb;
+ 	bp->b_fspriv3 = mp;
+-	return xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC);
++	(void)xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC);
+ }
+ 
+ #define XFS_bdstrat(bp) xfs_buf_iorequest(bp)
+diff --git a/fs/xfs/linux-2.6/xfs_cred.h b/fs/xfs/linux-2.6/xfs_cred.h
+index e7f3da6..652721c 100644
+--- a/fs/xfs/linux-2.6/xfs_cred.h
++++ b/fs/xfs/linux-2.6/xfs_cred.h
+@@ -30,7 +30,7 @@ typedef struct cred {
+ extern struct cred *sys_cred;
+ 
+ /* this is a hack.. (assumes sys_cred is the only cred_t in the system) */
+-static __inline int capable_cred(cred_t *cr, int cid)
++static inline int capable_cred(cred_t *cr, int cid)
+ {
+ 	return (cr == sys_cred) ? 1 : capable(cid);
+ }
+diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
+index ca4f66c..265f016 100644
+--- a/fs/xfs/linux-2.6/xfs_export.c
++++ b/fs/xfs/linux-2.6/xfs_export.c
+@@ -22,6 +22,7 @@
+ #include "xfs_trans.h"
+ #include "xfs_sb.h"
+ #include "xfs_ag.h"
++#include "xfs_dir2.h"
+ #include "xfs_dmapi.h"
+ #include "xfs_mount.h"
+ #include "xfs_export.h"
+@@ -30,8 +31,6 @@
+ #include "xfs_inode.h"
+ #include "xfs_vfsops.h"
+ 
+-static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
+-
+ /*
+  * Note that we only accept fileids which are long enough rather than allow
+  * the parent generation number to default to zero.  XFS considers zero a
+@@ -66,7 +65,7 @@ xfs_fs_encode_fh(
+ 	int			len;
+ 
+ 	/* Directories don't need their parent encoded, they have ".." */
+-	if (S_ISDIR(inode->i_mode))
++	if (S_ISDIR(inode->i_mode) || !connectable)
+ 		fileid_type = FILEID_INO32_GEN;
+ 	else
+ 		fileid_type = FILEID_INO32_GEN_PARENT;
+@@ -213,17 +212,16 @@ xfs_fs_get_parent(
+ 	struct dentry		*child)
+ {
+ 	int			error;
+-	bhv_vnode_t		*cvp;
++	struct xfs_inode	*cip;
+ 	struct dentry		*parent;
+ 
+-	cvp = NULL;
+-	error = xfs_lookup(XFS_I(child->d_inode), &dotdot, &cvp);
++	error = xfs_lookup(XFS_I(child->d_inode), &xfs_name_dotdot, &cip);
+ 	if (unlikely(error))
+ 		return ERR_PTR(-error);
+ 
+-	parent = d_alloc_anon(vn_to_inode(cvp));
++	parent = d_alloc_anon(cip->i_vnode);
+ 	if (unlikely(!parent)) {
+-		VN_RELE(cvp);
++		iput(cip->i_vnode);
+ 		return ERR_PTR(-ENOMEM);
+ 	}
+ 	return parent;
+diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
+index edab1ff..0590524 100644
+--- a/fs/xfs/linux-2.6/xfs_file.c
++++ b/fs/xfs/linux-2.6/xfs_file.c
+@@ -469,16 +469,11 @@ xfs_file_open_exec(
+ 	struct inode	*inode)
+ {
+ 	struct xfs_mount *mp = XFS_M(inode->i_sb);
++	struct xfs_inode *ip = XFS_I(inode);
+ 
+-	if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI)) {
+-		if (DM_EVENT_ENABLED(XFS_I(inode), DM_EVENT_READ)) {
+-			bhv_vnode_t *vp = vn_from_inode(inode);
+-
+-			return -XFS_SEND_DATA(mp, DM_EVENT_READ,
+-						vp, 0, 0, 0, NULL);
+-		}
+-	}
+-
++	if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI) &&
++	             DM_EVENT_ENABLED(ip, DM_EVENT_READ))
++		return -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL);
+ 	return 0;
+ }
+ #endif /* HAVE_FOP_OPEN_EXEC */
+diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
+index ac6d34c..1eefe61 100644
+--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
++++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
+@@ -17,18 +17,7 @@
+  */
+ #include "xfs.h"
+ #include "xfs_vnodeops.h"
+-
+-/*
+- * The following six includes are needed so that we can include
+- * xfs_inode.h.  What a mess..
+- */
+ #include "xfs_bmap_btree.h"
+-#include "xfs_inum.h"
+-#include "xfs_dir2.h"
+-#include "xfs_dir2_sf.h"
+-#include "xfs_attr_sf.h"
+-#include "xfs_dinode.h"
+-
+ #include "xfs_inode.h"
+ 
+ int  fs_noerr(void) { return 0; }
+@@ -42,11 +31,10 @@ xfs_tosspages(
+ 	xfs_off_t	last,
+ 	int		fiopt)
+ {
+-	bhv_vnode_t	*vp = XFS_ITOV(ip);
+-	struct inode	*inode = vn_to_inode(vp);
++	struct address_space *mapping = ip->i_vnode->i_mapping;
+ 
+-	if (VN_CACHED(vp))
+-		truncate_inode_pages(inode->i_mapping, first);
++	if (mapping->nrpages)
++		truncate_inode_pages(mapping, first);
+ }
+ 
+ int
+@@ -56,15 +44,14 @@ xfs_flushinval_pages(
+ 	xfs_off_t	last,
+ 	int		fiopt)
+ {
+-	bhv_vnode_t	*vp = XFS_ITOV(ip);
+-	struct inode	*inode = vn_to_inode(vp);
++	struct address_space *mapping = ip->i_vnode->i_mapping;
+ 	int		ret = 0;
+ 
+-	if (VN_CACHED(vp)) {
++	if (mapping->nrpages) {
+ 		xfs_iflags_clear(ip, XFS_ITRUNCATED);
+-		ret = filemap_write_and_wait(inode->i_mapping);
++		ret = filemap_write_and_wait(mapping);
+ 		if (!ret)
+-			truncate_inode_pages(inode->i_mapping, first);
++			truncate_inode_pages(mapping, first);
+ 	}
+ 	return ret;
+ }
+@@ -77,17 +64,16 @@ xfs_flush_pages(
+ 	uint64_t	flags,
+ 	int		fiopt)
+ {
+-	bhv_vnode_t	*vp = XFS_ITOV(ip);
+-	struct inode	*inode = vn_to_inode(vp);
++	struct address_space *mapping = ip->i_vnode->i_mapping;
+ 	int		ret = 0;
+ 	int		ret2;
+ 
+-	if (VN_DIRTY(vp)) {
++	if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+ 		xfs_iflags_clear(ip, XFS_ITRUNCATED);
+-		ret = filemap_fdatawrite(inode->i_mapping);
++		ret = filemap_fdatawrite(mapping);
+ 		if (flags & XFS_B_ASYNC)
+ 			return ret;
+-		ret2 = filemap_fdatawait(inode->i_mapping);
++		ret2 = filemap_fdatawait(mapping);
+ 		if (!ret)
+ 			ret = ret2;
+ 	}
+diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
+index f34bd01..4ddb86b 100644
+--- a/fs/xfs/linux-2.6/xfs_ioctl.c
++++ b/fs/xfs/linux-2.6/xfs_ioctl.c
+@@ -535,8 +535,6 @@ xfs_attrmulti_attr_set(
+ 	char			*kbuf;
+ 	int			error = EFAULT;
+ 
+-	if (IS_RDONLY(inode))
+-		return -EROFS;
+ 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ 		return EPERM;
+ 	if (len > XATTR_SIZE_MAX)
+@@ -562,8 +560,6 @@ xfs_attrmulti_attr_remove(
+ 	char			*name,
+ 	__uint32_t		flags)
+ {
+-	if (IS_RDONLY(inode))
+-		return -EROFS;
+ 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ 		return EPERM;
+ 	return xfs_attr_remove(XFS_I(inode), name, flags);
+@@ -573,6 +569,7 @@ STATIC int
+ xfs_attrmulti_by_handle(
+ 	xfs_mount_t		*mp,
+ 	void			__user *arg,
++	struct file		*parfilp,
+ 	struct inode		*parinode)
+ {
+ 	int			error;
+@@ -626,13 +623,21 @@ xfs_attrmulti_by_handle(
+ 					&ops[i].am_length, ops[i].am_flags);
+ 			break;
+ 		case ATTR_OP_SET:
++			ops[i].am_error = mnt_want_write(parfilp->f_path.mnt);
++			if (ops[i].am_error)
++				break;
+ 			ops[i].am_error = xfs_attrmulti_attr_set(inode,
+ 					attr_name, ops[i].am_attrvalue,
+ 					ops[i].am_length, ops[i].am_flags);
++			mnt_drop_write(parfilp->f_path.mnt);
+ 			break;
+ 		case ATTR_OP_REMOVE:
++			ops[i].am_error = mnt_want_write(parfilp->f_path.mnt);
++			if (ops[i].am_error)
++				break;
+ 			ops[i].am_error = xfs_attrmulti_attr_remove(inode,
+ 					attr_name, ops[i].am_flags);
++			mnt_drop_write(parfilp->f_path.mnt);
+ 			break;
+ 		default:
+ 			ops[i].am_error = EINVAL;
+@@ -651,314 +656,6 @@ xfs_attrmulti_by_handle(
+ 	return -error;
+ }
+ 
+-/* prototypes for a few of the stack-hungry cases that have
+- * their own functions.  Functions are defined after their use
+- * so gcc doesn't get fancy and inline them with -03 */
+-
+-STATIC int
+-xfs_ioc_space(
+-	struct xfs_inode	*ip,
+-	struct inode		*inode,
+-	struct file		*filp,
+-	int			flags,
+-	unsigned int		cmd,
+-	void			__user *arg);
+-
+-STATIC int
+-xfs_ioc_bulkstat(
+-	xfs_mount_t		*mp,
+-	unsigned int		cmd,
+-	void			__user *arg);
+-
+-STATIC int
+-xfs_ioc_fsgeometry_v1(
+-	xfs_mount_t		*mp,
+-	void			__user *arg);
+-
+-STATIC int
+-xfs_ioc_fsgeometry(
+-	xfs_mount_t		*mp,
+-	void			__user *arg);
+-
+-STATIC int
+-xfs_ioc_xattr(
+-	xfs_inode_t		*ip,
+-	struct file		*filp,
+-	unsigned int		cmd,
+-	void			__user *arg);
+-
+-STATIC int
+-xfs_ioc_fsgetxattr(
+-	xfs_inode_t		*ip,
+-	int			attr,
+-	void			__user *arg);
+-
+-STATIC int
+-xfs_ioc_getbmap(
+-	struct xfs_inode	*ip,
+-	int			flags,
+-	unsigned int		cmd,
+-	void			__user *arg);
+-
+-STATIC int
+-xfs_ioc_getbmapx(
+-	struct xfs_inode	*ip,
+-	void			__user *arg);
+-
+-int
+-xfs_ioctl(
+-	xfs_inode_t		*ip,
+-	struct file		*filp,
+-	int			ioflags,
+-	unsigned int		cmd,
+-	void			__user *arg)
+-{
+-	struct inode		*inode = filp->f_path.dentry->d_inode;
+-	xfs_mount_t		*mp = ip->i_mount;
+-	int			error;
+-
+-	xfs_itrace_entry(XFS_I(inode));
+-	switch (cmd) {
+-
+-	case XFS_IOC_ALLOCSP:
+-	case XFS_IOC_FREESP:
+-	case XFS_IOC_RESVSP:
+-	case XFS_IOC_UNRESVSP:
+-	case XFS_IOC_ALLOCSP64:
+-	case XFS_IOC_FREESP64:
+-	case XFS_IOC_RESVSP64:
+-	case XFS_IOC_UNRESVSP64:
+-		/*
+-		 * Only allow the sys admin to reserve space unless
+-		 * unwritten extents are enabled.
+-		 */
+-		if (!xfs_sb_version_hasextflgbit(&mp->m_sb) &&
+-		    !capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
+-
+-	case XFS_IOC_DIOINFO: {
+-		struct dioattr	da;
+-		xfs_buftarg_t	*target =
+-			XFS_IS_REALTIME_INODE(ip) ?
+-			mp->m_rtdev_targp : mp->m_ddev_targp;
+-
+-		da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
+-		da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
+-
+-		if (copy_to_user(arg, &da, sizeof(da)))
+-			return -XFS_ERROR(EFAULT);
+-		return 0;
+-	}
+-
+-	case XFS_IOC_FSBULKSTAT_SINGLE:
+-	case XFS_IOC_FSBULKSTAT:
+-	case XFS_IOC_FSINUMBERS:
+-		return xfs_ioc_bulkstat(mp, cmd, arg);
+-
+-	case XFS_IOC_FSGEOMETRY_V1:
+-		return xfs_ioc_fsgeometry_v1(mp, arg);
+-
+-	case XFS_IOC_FSGEOMETRY:
+-		return xfs_ioc_fsgeometry(mp, arg);
+-
+-	case XFS_IOC_GETVERSION:
+-		return put_user(inode->i_generation, (int __user *)arg);
+-
+-	case XFS_IOC_FSGETXATTR:
+-		return xfs_ioc_fsgetxattr(ip, 0, arg);
+-	case XFS_IOC_FSGETXATTRA:
+-		return xfs_ioc_fsgetxattr(ip, 1, arg);
+-	case XFS_IOC_GETXFLAGS:
+-	case XFS_IOC_SETXFLAGS:
+-	case XFS_IOC_FSSETXATTR:
+-		return xfs_ioc_xattr(ip, filp, cmd, arg);
+-
+-	case XFS_IOC_FSSETDM: {
+-		struct fsdmidata	dmi;
+-
+-		if (copy_from_user(&dmi, arg, sizeof(dmi)))
+-			return -XFS_ERROR(EFAULT);
+-
+-		error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
+-				dmi.fsd_dmstate);
+-		return -error;
+-	}
+-
+-	case XFS_IOC_GETBMAP:
+-	case XFS_IOC_GETBMAPA:
+-		return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
+-
+-	case XFS_IOC_GETBMAPX:
+-		return xfs_ioc_getbmapx(ip, arg);
+-
+-	case XFS_IOC_FD_TO_HANDLE:
+-	case XFS_IOC_PATH_TO_HANDLE:
+-	case XFS_IOC_PATH_TO_FSHANDLE:
+-		return xfs_find_handle(cmd, arg);
+-
+-	case XFS_IOC_OPEN_BY_HANDLE:
+-		return xfs_open_by_handle(mp, arg, filp, inode);
+-
+-	case XFS_IOC_FSSETDM_BY_HANDLE:
+-		return xfs_fssetdm_by_handle(mp, arg, inode);
+-
+-	case XFS_IOC_READLINK_BY_HANDLE:
+-		return xfs_readlink_by_handle(mp, arg, inode);
+-
+-	case XFS_IOC_ATTRLIST_BY_HANDLE:
+-		return xfs_attrlist_by_handle(mp, arg, inode);
+-
+-	case XFS_IOC_ATTRMULTI_BY_HANDLE:
+-		return xfs_attrmulti_by_handle(mp, arg, inode);
+-
+-	case XFS_IOC_SWAPEXT: {
+-		error = xfs_swapext((struct xfs_swapext __user *)arg);
+-		return -error;
+-	}
+-
+-	case XFS_IOC_FSCOUNTS: {
+-		xfs_fsop_counts_t out;
+-
+-		error = xfs_fs_counts(mp, &out);
+-		if (error)
+-			return -error;
+-
+-		if (copy_to_user(arg, &out, sizeof(out)))
+-			return -XFS_ERROR(EFAULT);
+-		return 0;
+-	}
+-
+-	case XFS_IOC_SET_RESBLKS: {
+-		xfs_fsop_resblks_t inout;
+-		__uint64_t	   in;
+-
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		if (copy_from_user(&inout, arg, sizeof(inout)))
+-			return -XFS_ERROR(EFAULT);
+-
+-		/* input parameter is passed in resblks field of structure */
+-		in = inout.resblks;
+-		error = xfs_reserve_blocks(mp, &in, &inout);
+-		if (error)
+-			return -error;
+-
+-		if (copy_to_user(arg, &inout, sizeof(inout)))
+-			return -XFS_ERROR(EFAULT);
+-		return 0;
+-	}
+-
+-	case XFS_IOC_GET_RESBLKS: {
+-		xfs_fsop_resblks_t out;
+-
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		error = xfs_reserve_blocks(mp, NULL, &out);
+-		if (error)
+-			return -error;
+-
+-		if (copy_to_user(arg, &out, sizeof(out)))
+-			return -XFS_ERROR(EFAULT);
+-
+-		return 0;
+-	}
+-
+-	case XFS_IOC_FSGROWFSDATA: {
+-		xfs_growfs_data_t in;
+-
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		if (copy_from_user(&in, arg, sizeof(in)))
+-			return -XFS_ERROR(EFAULT);
+-
+-		error = xfs_growfs_data(mp, &in);
+-		return -error;
+-	}
+-
+-	case XFS_IOC_FSGROWFSLOG: {
+-		xfs_growfs_log_t in;
+-
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		if (copy_from_user(&in, arg, sizeof(in)))
+-			return -XFS_ERROR(EFAULT);
+-
+-		error = xfs_growfs_log(mp, &in);
+-		return -error;
+-	}
+-
+-	case XFS_IOC_FSGROWFSRT: {
+-		xfs_growfs_rt_t in;
+-
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		if (copy_from_user(&in, arg, sizeof(in)))
+-			return -XFS_ERROR(EFAULT);
+-
+-		error = xfs_growfs_rt(mp, &in);
+-		return -error;
+-	}
+-
+-	case XFS_IOC_FREEZE:
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		if (inode->i_sb->s_frozen == SB_UNFROZEN)
+-			freeze_bdev(inode->i_sb->s_bdev);
+-		return 0;
+-
+-	case XFS_IOC_THAW:
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-		if (inode->i_sb->s_frozen != SB_UNFROZEN)
+-			thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
+-		return 0;
+-
+-	case XFS_IOC_GOINGDOWN: {
+-		__uint32_t in;
+-
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		if (get_user(in, (__uint32_t __user *)arg))
+-			return -XFS_ERROR(EFAULT);
+-
+-		error = xfs_fs_goingdown(mp, in);
+-		return -error;
+-	}
+-
+-	case XFS_IOC_ERROR_INJECTION: {
+-		xfs_error_injection_t in;
+-
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		if (copy_from_user(&in, arg, sizeof(in)))
+-			return -XFS_ERROR(EFAULT);
+-
+-		error = xfs_errortag_add(in.errtag, mp);
+-		return -error;
+-	}
+-
+-	case XFS_IOC_ERROR_CLEARALL:
+-		if (!capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		error = xfs_errortag_clearall(mp, 1);
+-		return -error;
+-
+-	default:
+-		return -ENOTTY;
+-	}
+-}
+-
+ STATIC int
+ xfs_ioc_space(
+ 	struct xfs_inode	*ip,
+@@ -1179,85 +876,85 @@ xfs_ioc_fsgetxattr(
+ }
+ 
+ STATIC int
+-xfs_ioc_xattr(
++xfs_ioc_fssetxattr(
+ 	xfs_inode_t		*ip,
+ 	struct file		*filp,
+-	unsigned int		cmd,
+ 	void			__user *arg)
+ {
+ 	struct fsxattr		fa;
+ 	struct bhv_vattr	*vattr;
+-	int			error = 0;
++	int			error;
+ 	int			attr_flags;
+-	unsigned int		flags;
++
++	if (copy_from_user(&fa, arg, sizeof(fa)))
++		return -EFAULT;
+ 
+ 	vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
+ 	if (unlikely(!vattr))
+ 		return -ENOMEM;
+ 
+-	switch (cmd) {
+-	case XFS_IOC_FSSETXATTR: {
+-		if (copy_from_user(&fa, arg, sizeof(fa))) {
+-			error = -EFAULT;
+-			break;
+-		}
++	attr_flags = 0;
++	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
++		attr_flags |= ATTR_NONBLOCK;
+ 
+-		attr_flags = 0;
+-		if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
+-			attr_flags |= ATTR_NONBLOCK;
++	vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
++	vattr->va_xflags  = fa.fsx_xflags;
++	vattr->va_extsize = fa.fsx_extsize;
++	vattr->va_projid  = fa.fsx_projid;
+ 
+-		vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
+-		vattr->va_xflags  = fa.fsx_xflags;
+-		vattr->va_extsize = fa.fsx_extsize;
+-		vattr->va_projid  = fa.fsx_projid;
++	error = -xfs_setattr(ip, vattr, attr_flags, NULL);
++	if (!error)
++		vn_revalidate(XFS_ITOV(ip));	/* update flags */
++	kfree(vattr);
++	return 0;
++}
+ 
+-		error = xfs_setattr(ip, vattr, attr_flags, NULL);
+-		if (likely(!error))
+-			vn_revalidate(XFS_ITOV(ip));	/* update flags */
+-		error = -error;
+-		break;
+-	}
++STATIC int
++xfs_ioc_getxflags(
++	xfs_inode_t		*ip,
++	void			__user *arg)
++{
++	unsigned int		flags;
+ 
+-	case XFS_IOC_GETXFLAGS: {
+-		flags = xfs_di2lxflags(ip->i_d.di_flags);
+-		if (copy_to_user(arg, &flags, sizeof(flags)))
+-			error = -EFAULT;
+-		break;
+-	}
++	flags = xfs_di2lxflags(ip->i_d.di_flags);
++	if (copy_to_user(arg, &flags, sizeof(flags)))
++		return -EFAULT;
++	return 0;
++}
+ 
+-	case XFS_IOC_SETXFLAGS: {
+-		if (copy_from_user(&flags, arg, sizeof(flags))) {
+-			error = -EFAULT;
+-			break;
+-		}
++STATIC int
++xfs_ioc_setxflags(
++	xfs_inode_t		*ip,
++	struct file		*filp,
++	void			__user *arg)
++{
++	struct bhv_vattr	*vattr;
++	unsigned int		flags;
++	int			attr_flags;
++	int			error;
+ 
+-		if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
+-			      FS_NOATIME_FL | FS_NODUMP_FL | \
+-			      FS_SYNC_FL)) {
+-			error = -EOPNOTSUPP;
+-			break;
+-		}
++	if (copy_from_user(&flags, arg, sizeof(flags)))
++		return -EFAULT;
+ 
+-		attr_flags = 0;
+-		if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
+-			attr_flags |= ATTR_NONBLOCK;
++	if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
++		      FS_NOATIME_FL | FS_NODUMP_FL | \
++		      FS_SYNC_FL))
++		return -EOPNOTSUPP;
+ 
+-		vattr->va_mask = XFS_AT_XFLAGS;
+-		vattr->va_xflags = xfs_merge_ioc_xflags(flags,
+-							xfs_ip2xflags(ip));
++	vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
++	if (unlikely(!vattr))
++		return -ENOMEM;
+ 
+-		error = xfs_setattr(ip, vattr, attr_flags, NULL);
+-		if (likely(!error))
+-			vn_revalidate(XFS_ITOV(ip));	/* update flags */
+-		error = -error;
+-		break;
+-	}
++	attr_flags = 0;
++	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
++		attr_flags |= ATTR_NONBLOCK;
+ 
+-	default:
+-		error = -ENOTTY;
+-		break;
+-	}
++	vattr->va_mask = XFS_AT_XFLAGS;
++	vattr->va_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
+ 
++	error = -xfs_setattr(ip, vattr, attr_flags, NULL);
++	if (likely(!error))
++		vn_revalidate(XFS_ITOV(ip));	/* update flags */
+ 	kfree(vattr);
+ 	return error;
+ }
+@@ -1332,3 +1029,259 @@ xfs_ioc_getbmapx(
+ 
+ 	return 0;
+ }
++
++int
++xfs_ioctl(
++	xfs_inode_t		*ip,
++	struct file		*filp,
++	int			ioflags,
++	unsigned int		cmd,
++	void			__user *arg)
++{
++	struct inode		*inode = filp->f_path.dentry->d_inode;
++	xfs_mount_t		*mp = ip->i_mount;
++	int			error;
++
++	xfs_itrace_entry(XFS_I(inode));
++	switch (cmd) {
++
++	case XFS_IOC_ALLOCSP:
++	case XFS_IOC_FREESP:
++	case XFS_IOC_RESVSP:
++	case XFS_IOC_UNRESVSP:
++	case XFS_IOC_ALLOCSP64:
++	case XFS_IOC_FREESP64:
++	case XFS_IOC_RESVSP64:
++	case XFS_IOC_UNRESVSP64:
++		/*
++		 * Only allow the sys admin to reserve space unless
++		 * unwritten extents are enabled.
++		 */
++		if (!xfs_sb_version_hasextflgbit(&mp->m_sb) &&
++		    !capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
++
++	case XFS_IOC_DIOINFO: {
++		struct dioattr	da;
++		xfs_buftarg_t	*target =
++			XFS_IS_REALTIME_INODE(ip) ?
++			mp->m_rtdev_targp : mp->m_ddev_targp;
++
++		da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
++		da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
++
++		if (copy_to_user(arg, &da, sizeof(da)))
++			return -XFS_ERROR(EFAULT);
++		return 0;
++	}
++
++	case XFS_IOC_FSBULKSTAT_SINGLE:
++	case XFS_IOC_FSBULKSTAT:
++	case XFS_IOC_FSINUMBERS:
++		return xfs_ioc_bulkstat(mp, cmd, arg);
++
++	case XFS_IOC_FSGEOMETRY_V1:
++		return xfs_ioc_fsgeometry_v1(mp, arg);
++
++	case XFS_IOC_FSGEOMETRY:
++		return xfs_ioc_fsgeometry(mp, arg);
++
++	case XFS_IOC_GETVERSION:
++		return put_user(inode->i_generation, (int __user *)arg);
++
++	case XFS_IOC_FSGETXATTR:
++		return xfs_ioc_fsgetxattr(ip, 0, arg);
++	case XFS_IOC_FSGETXATTRA:
++		return xfs_ioc_fsgetxattr(ip, 1, arg);
++	case XFS_IOC_FSSETXATTR:
++		return xfs_ioc_fssetxattr(ip, filp, arg);
++	case XFS_IOC_GETXFLAGS:
++		return xfs_ioc_getxflags(ip, arg);
++	case XFS_IOC_SETXFLAGS:
++		return xfs_ioc_setxflags(ip, filp, arg);
++
++	case XFS_IOC_FSSETDM: {
++		struct fsdmidata	dmi;
++
++		if (copy_from_user(&dmi, arg, sizeof(dmi)))
++			return -XFS_ERROR(EFAULT);
++
++		error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
++				dmi.fsd_dmstate);
++		return -error;
++	}
++
++	case XFS_IOC_GETBMAP:
++	case XFS_IOC_GETBMAPA:
++		return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
++
++	case XFS_IOC_GETBMAPX:
++		return xfs_ioc_getbmapx(ip, arg);
++
++	case XFS_IOC_FD_TO_HANDLE:
++	case XFS_IOC_PATH_TO_HANDLE:
++	case XFS_IOC_PATH_TO_FSHANDLE:
++		return xfs_find_handle(cmd, arg);
++
++	case XFS_IOC_OPEN_BY_HANDLE:
++		return xfs_open_by_handle(mp, arg, filp, inode);
++
++	case XFS_IOC_FSSETDM_BY_HANDLE:
++		return xfs_fssetdm_by_handle(mp, arg, inode);
++
++	case XFS_IOC_READLINK_BY_HANDLE:
++		return xfs_readlink_by_handle(mp, arg, inode);
++
++	case XFS_IOC_ATTRLIST_BY_HANDLE:
++		return xfs_attrlist_by_handle(mp, arg, inode);
++
++	case XFS_IOC_ATTRMULTI_BY_HANDLE:
++		return xfs_attrmulti_by_handle(mp, arg, filp, inode);
++
++	case XFS_IOC_SWAPEXT: {
++		error = xfs_swapext((struct xfs_swapext __user *)arg);
++		return -error;
++	}
++
++	case XFS_IOC_FSCOUNTS: {
++		xfs_fsop_counts_t out;
++
++		error = xfs_fs_counts(mp, &out);
++		if (error)
++			return -error;
++
++		if (copy_to_user(arg, &out, sizeof(out)))
++			return -XFS_ERROR(EFAULT);
++		return 0;
++	}
++
++	case XFS_IOC_SET_RESBLKS: {
++		xfs_fsop_resblks_t inout;
++		__uint64_t	   in;
++
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		if (copy_from_user(&inout, arg, sizeof(inout)))
++			return -XFS_ERROR(EFAULT);
++
++		/* input parameter is passed in resblks field of structure */
++		in = inout.resblks;
++		error = xfs_reserve_blocks(mp, &in, &inout);
++		if (error)
++			return -error;
++
++		if (copy_to_user(arg, &inout, sizeof(inout)))
++			return -XFS_ERROR(EFAULT);
++		return 0;
++	}
++
++	case XFS_IOC_GET_RESBLKS: {
++		xfs_fsop_resblks_t out;
++
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		error = xfs_reserve_blocks(mp, NULL, &out);
++		if (error)
++			return -error;
++
++		if (copy_to_user(arg, &out, sizeof(out)))
++			return -XFS_ERROR(EFAULT);
++
++		return 0;
++	}
++
++	case XFS_IOC_FSGROWFSDATA: {
++		xfs_growfs_data_t in;
++
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		if (copy_from_user(&in, arg, sizeof(in)))
++			return -XFS_ERROR(EFAULT);
++
++		error = xfs_growfs_data(mp, &in);
++		return -error;
++	}
++
++	case XFS_IOC_FSGROWFSLOG: {
++		xfs_growfs_log_t in;
++
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		if (copy_from_user(&in, arg, sizeof(in)))
++			return -XFS_ERROR(EFAULT);
++
++		error = xfs_growfs_log(mp, &in);
++		return -error;
++	}
++
++	case XFS_IOC_FSGROWFSRT: {
++		xfs_growfs_rt_t in;
++
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		if (copy_from_user(&in, arg, sizeof(in)))
++			return -XFS_ERROR(EFAULT);
++
++		error = xfs_growfs_rt(mp, &in);
++		return -error;
++	}
++
++	case XFS_IOC_FREEZE:
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		if (inode->i_sb->s_frozen == SB_UNFROZEN)
++			freeze_bdev(inode->i_sb->s_bdev);
++		return 0;
++
++	case XFS_IOC_THAW:
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++		if (inode->i_sb->s_frozen != SB_UNFROZEN)
++			thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
++		return 0;
++
++	case XFS_IOC_GOINGDOWN: {
++		__uint32_t in;
++
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		if (get_user(in, (__uint32_t __user *)arg))
++			return -XFS_ERROR(EFAULT);
++
++		error = xfs_fs_goingdown(mp, in);
++		return -error;
++	}
++
++	case XFS_IOC_ERROR_INJECTION: {
++		xfs_error_injection_t in;
++
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		if (copy_from_user(&in, arg, sizeof(in)))
++			return -XFS_ERROR(EFAULT);
++
++		error = xfs_errortag_add(in.errtag, mp);
++		return -error;
++	}
++
++	case XFS_IOC_ERROR_CLEARALL:
++		if (!capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		error = xfs_errortag_clearall(mp, 1);
++		return -error;
++
++	default:
++		return -ENOTTY;
++	}
++}
+diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
+index cc4abd3..a1237da 100644
+--- a/fs/xfs/linux-2.6/xfs_iops.c
++++ b/fs/xfs/linux-2.6/xfs_iops.c
+@@ -62,12 +62,11 @@ void
+ xfs_synchronize_atime(
+ 	xfs_inode_t	*ip)
+ {
+-	bhv_vnode_t	*vp;
++	struct inode	*inode = ip->i_vnode;
+ 
+-	vp = XFS_ITOV_NULL(ip);
+-	if (vp) {
+-		ip->i_d.di_atime.t_sec = (__int32_t)vp->i_atime.tv_sec;
+-		ip->i_d.di_atime.t_nsec = (__int32_t)vp->i_atime.tv_nsec;
++	if (inode) {
++		ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
++		ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
+ 	}
+ }
+ 
+@@ -80,11 +79,10 @@ void
+ xfs_mark_inode_dirty_sync(
+ 	xfs_inode_t	*ip)
+ {
+-	bhv_vnode_t	*vp;
++	struct inode	*inode = ip->i_vnode;
+ 
+-	vp = XFS_ITOV_NULL(ip);
+-	if (vp)
+-		mark_inode_dirty_sync(vn_to_inode(vp));
++	if (inode)
++		mark_inode_dirty_sync(inode);
+ }
+ 
+ /*
+@@ -157,13 +155,6 @@ xfs_ichgtime_fast(
+ 	 */
+ 	ASSERT((flags & XFS_ICHGTIME_ACC) == 0);
+ 
+-	/*
+-	 * We're not supposed to change timestamps in readonly-mounted
+-	 * filesystems.  Throw it away if anyone asks us.
+-	 */
+-	if (unlikely(IS_RDONLY(inode)))
+-		return;
+-
+ 	if (flags & XFS_ICHGTIME_MOD) {
+ 		tvp = &inode->i_mtime;
+ 		ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec;
+@@ -215,66 +206,62 @@ xfs_validate_fields(
+  */
+ STATIC int
+ xfs_init_security(
+-	bhv_vnode_t	*vp,
++	struct inode	*inode,
+ 	struct inode	*dir)
+ {
+-	struct inode	*ip = vn_to_inode(vp);
++	struct xfs_inode *ip = XFS_I(inode);
+ 	size_t		length;
+ 	void		*value;
+ 	char		*name;
+ 	int		error;
+ 
+-	error = security_inode_init_security(ip, dir, &name, &value, &length);
++	error = security_inode_init_security(inode, dir, &name,
++					     &value, &length);
+ 	if (error) {
+ 		if (error == -EOPNOTSUPP)
+ 			return 0;
+ 		return -error;
+ 	}
+ 
+-	error = xfs_attr_set(XFS_I(ip), name, value,
+-			length, ATTR_SECURE);
++	error = xfs_attr_set(ip, name, value, length, ATTR_SECURE);
+ 	if (!error)
+-		xfs_iflags_set(XFS_I(ip), XFS_IMODIFIED);
++		xfs_iflags_set(ip, XFS_IMODIFIED);
+ 
+ 	kfree(name);
+ 	kfree(value);
+ 	return error;
+ }
+ 
+-/*
+- * Determine whether a process has a valid fs_struct (kernel daemons
+- * like knfsd don't have an fs_struct).
+- *
+- * XXX(hch):  nfsd is broken, better fix it instead.
+- */
+-STATIC_INLINE int
+-xfs_has_fs_struct(struct task_struct *task)
++static void
++xfs_dentry_to_name(
++	struct xfs_name	*namep,
++	struct dentry	*dentry)
+ {
+-	return (task->fs != init_task.fs);
++	namep->name = dentry->d_name.name;
++	namep->len = dentry->d_name.len;
+ }
+ 
+ STATIC void
+ xfs_cleanup_inode(
+ 	struct inode	*dir,
+-	bhv_vnode_t	*vp,
++	struct inode	*inode,
+ 	struct dentry	*dentry,
+ 	int		mode)
+ {
+-	struct dentry   teardown = {};
++	struct xfs_name	teardown;
+ 
+ 	/* Oh, the horror.
+ 	 * If we can't add the ACL or we fail in
+ 	 * xfs_init_security we must back out.
+ 	 * ENOSPC can hit here, among other things.
+ 	 */
+-	teardown.d_inode = vn_to_inode(vp);
+-	teardown.d_name = dentry->d_name;
++	xfs_dentry_to_name(&teardown, dentry);
+ 
+ 	if (S_ISDIR(mode))
+-		xfs_rmdir(XFS_I(dir), &teardown);
++		xfs_rmdir(XFS_I(dir), &teardown, XFS_I(inode));
+ 	else
+-		xfs_remove(XFS_I(dir), &teardown);
+-	VN_RELE(vp);
++		xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
++	iput(inode);
+ }
+ 
+ STATIC int
+@@ -284,9 +271,10 @@ xfs_vn_mknod(
+ 	int		mode,
+ 	dev_t		rdev)
+ {
+-	struct inode	*ip;
+-	bhv_vnode_t	*vp = NULL, *dvp = vn_from_inode(dir);
++	struct inode	*inode;
++	struct xfs_inode *ip = NULL;
+ 	xfs_acl_t	*default_acl = NULL;
++	struct xfs_name	name;
+ 	attrexists_t	test_default_acl = _ACL_DEFAULT_EXISTS;
+ 	int		error;
+ 
+@@ -297,59 +285,67 @@ xfs_vn_mknod(
+ 	if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff))
+ 		return -EINVAL;
+ 
+-	if (unlikely(test_default_acl && test_default_acl(dvp))) {
++	if (test_default_acl && test_default_acl(dir)) {
+ 		if (!_ACL_ALLOC(default_acl)) {
+ 			return -ENOMEM;
+ 		}
+-		if (!_ACL_GET_DEFAULT(dvp, default_acl)) {
++		if (!_ACL_GET_DEFAULT(dir, default_acl)) {
+ 			_ACL_FREE(default_acl);
+ 			default_acl = NULL;
+ 		}
+ 	}
+ 
+-	if (IS_POSIXACL(dir) && !default_acl && xfs_has_fs_struct(current))
++	xfs_dentry_to_name(&name, dentry);
++
++	if (IS_POSIXACL(dir) && !default_acl)
+ 		mode &= ~current->fs->umask;
+ 
+ 	switch (mode & S_IFMT) {
+-	case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
++	case S_IFCHR:
++	case S_IFBLK:
++	case S_IFIFO:
++	case S_IFSOCK:
+ 		rdev = sysv_encode_dev(rdev);
+ 	case S_IFREG:
+-		error = xfs_create(XFS_I(dir), dentry, mode, rdev, &vp, NULL);
++		error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL);
+ 		break;
+ 	case S_IFDIR:
+-		error = xfs_mkdir(XFS_I(dir), dentry, mode, &vp, NULL);
++		error = xfs_mkdir(XFS_I(dir), &name, mode, &ip, NULL);
+ 		break;
+ 	default:
+ 		error = EINVAL;
+ 		break;
+ 	}
+ 
+-	if (unlikely(!error)) {
+-		error = xfs_init_security(vp, dir);
+-		if (error)
+-			xfs_cleanup_inode(dir, vp, dentry, mode);
+-	}
++	if (unlikely(error))
++		goto out_free_acl;
+ 
+-	if (unlikely(default_acl)) {
+-		if (!error) {
+-			error = _ACL_INHERIT(vp, mode, default_acl);
+-			if (!error)
+-				xfs_iflags_set(XFS_I(vp), XFS_IMODIFIED);
+-			else
+-				xfs_cleanup_inode(dir, vp, dentry, mode);
+-		}
++	inode = ip->i_vnode;
++
++	error = xfs_init_security(inode, dir);
++	if (unlikely(error))
++		goto out_cleanup_inode;
++
++	if (default_acl) {
++		error = _ACL_INHERIT(inode, mode, default_acl);
++		if (unlikely(error))
++			goto out_cleanup_inode;
++		xfs_iflags_set(ip, XFS_IMODIFIED);
+ 		_ACL_FREE(default_acl);
+ 	}
+ 
+-	if (likely(!error)) {
+-		ASSERT(vp);
+-		ip = vn_to_inode(vp);
+ 
+-		if (S_ISDIR(mode))
+-			xfs_validate_fields(ip);
+-		d_instantiate(dentry, ip);
+-		xfs_validate_fields(dir);
+-	}
++	if (S_ISDIR(mode))
++		xfs_validate_fields(inode);
++	d_instantiate(dentry, inode);
++	xfs_validate_fields(dir);
++	return -error;
++
++ out_cleanup_inode:
++	xfs_cleanup_inode(dir, inode, dentry, mode);
++ out_free_acl:
++	if (default_acl)
++		_ACL_FREE(default_acl);
+ 	return -error;
+ }
+ 
+@@ -378,13 +374,15 @@ xfs_vn_lookup(
+ 	struct dentry	*dentry,
+ 	struct nameidata *nd)
+ {
+-	bhv_vnode_t	*cvp;
++	struct xfs_inode *cip;
++	struct xfs_name	name;
+ 	int		error;
+ 
+ 	if (dentry->d_name.len >= MAXNAMELEN)
+ 		return ERR_PTR(-ENAMETOOLONG);
+ 
+-	error = xfs_lookup(XFS_I(dir), dentry, &cvp);
++	xfs_dentry_to_name(&name, dentry);
++	error = xfs_lookup(XFS_I(dir), &name, &cip);
+ 	if (unlikely(error)) {
+ 		if (unlikely(error != ENOENT))
+ 			return ERR_PTR(-error);
+@@ -392,7 +390,7 @@ xfs_vn_lookup(
+ 		return NULL;
+ 	}
+ 
+-	return d_splice_alias(vn_to_inode(cvp), dentry);
++	return d_splice_alias(cip->i_vnode, dentry);
+ }
+ 
+ STATIC int
+@@ -401,23 +399,24 @@ xfs_vn_link(
+ 	struct inode	*dir,
+ 	struct dentry	*dentry)
+ {
+-	struct inode	*ip;	/* inode of guy being linked to */
+-	bhv_vnode_t	*vp;	/* vp of name being linked */
++	struct inode	*inode;	/* inode of guy being linked to */
++	struct xfs_name	name;
+ 	int		error;
+ 
+-	ip = old_dentry->d_inode;	/* inode being linked to */
+-	vp = vn_from_inode(ip);
++	inode = old_dentry->d_inode;
++	xfs_dentry_to_name(&name, dentry);
+ 
+-	VN_HOLD(vp);
+-	error = xfs_link(XFS_I(dir), vp, dentry);
++	igrab(inode);
++	error = xfs_link(XFS_I(dir), XFS_I(inode), &name);
+ 	if (unlikely(error)) {
+-		VN_RELE(vp);
+-	} else {
+-		xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
+-		xfs_validate_fields(ip);
+-		d_instantiate(dentry, ip);
++		iput(inode);
++		return -error;
+ 	}
+-	return -error;
++
++	xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
++	xfs_validate_fields(inode);
++	d_instantiate(dentry, inode);
++	return 0;
+ }
+ 
+ STATIC int
+@@ -426,11 +425,13 @@ xfs_vn_unlink(
+ 	struct dentry	*dentry)
+ {
+ 	struct inode	*inode;
++	struct xfs_name	name;
+ 	int		error;
+ 
+ 	inode = dentry->d_inode;
++	xfs_dentry_to_name(&name, dentry);
+ 
+-	error = xfs_remove(XFS_I(dir), dentry);
++	error = xfs_remove(XFS_I(dir), &name, XFS_I(inode));
+ 	if (likely(!error)) {
+ 		xfs_validate_fields(dir);	/* size needs update */
+ 		xfs_validate_fields(inode);
+@@ -444,29 +445,34 @@ xfs_vn_symlink(
+ 	struct dentry	*dentry,
+ 	const char	*symname)
+ {
+-	struct inode	*ip;
+-	bhv_vnode_t	*cvp;	/* used to lookup symlink to put in dentry */
++	struct inode	*inode;
++	struct xfs_inode *cip = NULL;
++	struct xfs_name	name;
+ 	int		error;
+ 	mode_t		mode;
+ 
+-	cvp = NULL;
+-
+ 	mode = S_IFLNK |
+ 		(irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
++	xfs_dentry_to_name(&name, dentry);
+ 
+-	error = xfs_symlink(XFS_I(dir), dentry, (char *)symname, mode,
+-			    &cvp, NULL);
+-	if (likely(!error && cvp)) {
+-		error = xfs_init_security(cvp, dir);
+-		if (likely(!error)) {
+-			ip = vn_to_inode(cvp);
+-			d_instantiate(dentry, ip);
+-			xfs_validate_fields(dir);
+-			xfs_validate_fields(ip);
+-		} else {
+-			xfs_cleanup_inode(dir, cvp, dentry, 0);
+-		}
+-	}
++	error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL);
++	if (unlikely(error))
++		goto out;
++
++	inode = cip->i_vnode;
++
++	error = xfs_init_security(inode, dir);
++	if (unlikely(error))
++		goto out_cleanup_inode;
++
++	d_instantiate(dentry, inode);
++	xfs_validate_fields(dir);
++	xfs_validate_fields(inode);
++	return 0;
++
++ out_cleanup_inode:
++	xfs_cleanup_inode(dir, inode, dentry, 0);
++ out:
+ 	return -error;
+ }
+ 
+@@ -476,9 +482,12 @@ xfs_vn_rmdir(
+ 	struct dentry	*dentry)
+ {
+ 	struct inode	*inode = dentry->d_inode;
++	struct xfs_name	name;
+ 	int		error;
+ 
+-	error = xfs_rmdir(XFS_I(dir), dentry);
++	xfs_dentry_to_name(&name, dentry);
++
++	error = xfs_rmdir(XFS_I(dir), &name, XFS_I(inode));
+ 	if (likely(!error)) {
+ 		xfs_validate_fields(inode);
+ 		xfs_validate_fields(dir);
+@@ -494,12 +503,15 @@ xfs_vn_rename(
+ 	struct dentry	*ndentry)
+ {
+ 	struct inode	*new_inode = ndentry->d_inode;
+-	bhv_vnode_t	*tvp;	/* target directory */
++	struct xfs_name	oname;
++	struct xfs_name	nname;
+ 	int		error;
+ 
+-	tvp = vn_from_inode(ndir);
++	xfs_dentry_to_name(&oname, odentry);
++	xfs_dentry_to_name(&nname, ndentry);
+ 
+-	error = xfs_rename(XFS_I(odir), odentry, tvp, ndentry);
++	error = xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode),
++							XFS_I(ndir), &nname);
+ 	if (likely(!error)) {
+ 		if (new_inode)
+ 			xfs_validate_fields(new_inode);
+@@ -700,11 +712,19 @@ xfs_vn_setattr(
+ 	return -error;
+ }
+ 
++/*
++ * block_truncate_page can return an error, but we can't propagate it
++ * at all here. Leave a complaint + stack trace in the syslog because
++ * this could be bad. If it is bad, we need to propagate the error further.
++ */
+ STATIC void
+ xfs_vn_truncate(
+ 	struct inode	*inode)
+ {
+-	block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_blocks);
++	int	error;
++	error = block_truncate_page(inode->i_mapping, inode->i_size,
++							xfs_get_blocks);
++	WARN_ON(error);
+ }
+ 
+ STATIC int
+diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
+index 3ca39c4..e514332 100644
+--- a/fs/xfs/linux-2.6/xfs_linux.h
++++ b/fs/xfs/linux-2.6/xfs_linux.h
+@@ -99,7 +99,6 @@
+ /*
+  * Feature macros (disable/enable)
+  */
+-#undef  HAVE_REFCACHE	/* reference cache not needed for NFS in 2.6 */
+ #define HAVE_SPLICE	/* a splice(2) exists in 2.6, but not in 2.4 */
+ #ifdef CONFIG_SMP
+ #define HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
+diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
+index 1663533..1ebd800 100644
+--- a/fs/xfs/linux-2.6/xfs_lrw.c
++++ b/fs/xfs/linux-2.6/xfs_lrw.c
+@@ -51,6 +51,7 @@
+ #include "xfs_vnodeops.h"
+ 
+ #include <linux/capability.h>
++#include <linux/mount.h>
+ #include <linux/writeback.h>
+ 
+ 
+@@ -176,7 +177,6 @@ xfs_read(
+ {
+ 	struct file		*file = iocb->ki_filp;
+ 	struct inode		*inode = file->f_mapping->host;
+-	bhv_vnode_t		*vp = XFS_ITOV(ip);
+ 	xfs_mount_t		*mp = ip->i_mount;
+ 	size_t			size = 0;
+ 	ssize_t			ret = 0;
+@@ -228,11 +228,11 @@ xfs_read(
+ 	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+ 
+ 	if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
+-		bhv_vrwlock_t locktype = VRWLOCK_READ;
+ 		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
++		int iolock = XFS_IOLOCK_SHARED;
+ 
+-		ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *offset, size,
+-					dmflags, &locktype);
++		ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *offset, size,
++					dmflags, &iolock);
+ 		if (ret) {
+ 			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ 			if (unlikely(ioflags & IO_ISDIRECT))
+@@ -242,7 +242,7 @@ xfs_read(
+ 	}
+ 
+ 	if (unlikely(ioflags & IO_ISDIRECT)) {
+-		if (VN_CACHED(vp))
++		if (inode->i_mapping->nrpages)
+ 			ret = xfs_flushinval_pages(ip, (*offset & PAGE_CACHE_MASK),
+ 						    -1, FI_REMAPF_LOCKED);
+ 		mutex_unlock(&inode->i_mutex);
+@@ -276,7 +276,6 @@ xfs_splice_read(
+ 	int			flags,
+ 	int			ioflags)
+ {
+-	bhv_vnode_t		*vp = XFS_ITOV(ip);
+ 	xfs_mount_t		*mp = ip->i_mount;
+ 	ssize_t			ret;
+ 
+@@ -287,11 +286,11 @@ xfs_splice_read(
+ 	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+ 
+ 	if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
+-		bhv_vrwlock_t locktype = VRWLOCK_READ;
++		int iolock = XFS_IOLOCK_SHARED;
+ 		int error;
+ 
+-		error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *ppos, count,
+-					FILP_DELAY_FLAG(infilp), &locktype);
++		error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *ppos, count,
++					FILP_DELAY_FLAG(infilp), &iolock);
+ 		if (error) {
+ 			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ 			return -error;
+@@ -317,7 +316,6 @@ xfs_splice_write(
+ 	int			flags,
+ 	int			ioflags)
+ {
+-	bhv_vnode_t		*vp = XFS_ITOV(ip);
+ 	xfs_mount_t		*mp = ip->i_mount;
+ 	ssize_t			ret;
+ 	struct inode		*inode = outfilp->f_mapping->host;
+@@ -330,11 +328,11 @@ xfs_splice_write(
+ 	xfs_ilock(ip, XFS_IOLOCK_EXCL);
+ 
+ 	if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
+-		bhv_vrwlock_t locktype = VRWLOCK_WRITE;
++		int iolock = XFS_IOLOCK_EXCL;
+ 		int error;
+ 
+-		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp, *ppos, count,
+-					FILP_DELAY_FLAG(outfilp), &locktype);
++		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, *ppos, count,
++					FILP_DELAY_FLAG(outfilp), &iolock);
+ 		if (error) {
+ 			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ 			return -error;
+@@ -573,14 +571,12 @@ xfs_write(
+ 	struct file		*file = iocb->ki_filp;
+ 	struct address_space	*mapping = file->f_mapping;
+ 	struct inode		*inode = mapping->host;
+-	bhv_vnode_t		*vp = XFS_ITOV(xip);
+ 	unsigned long		segs = nsegs;
+ 	xfs_mount_t		*mp;
+ 	ssize_t			ret = 0, error = 0;
+ 	xfs_fsize_t		isize, new_size;
+ 	int			iolock;
+ 	int			eventsent = 0;
+-	bhv_vrwlock_t		locktype;
+ 	size_t			ocount = 0, count;
+ 	loff_t			pos;
+ 	int			need_i_mutex;
+@@ -607,11 +603,9 @@ xfs_write(
+ relock:
+ 	if (ioflags & IO_ISDIRECT) {
+ 		iolock = XFS_IOLOCK_SHARED;
+-		locktype = VRWLOCK_WRITE_DIRECT;
+ 		need_i_mutex = 0;
+ 	} else {
+ 		iolock = XFS_IOLOCK_EXCL;
+-		locktype = VRWLOCK_WRITE;
+ 		need_i_mutex = 1;
+ 		mutex_lock(&inode->i_mutex);
+ 	}
+@@ -634,9 +628,8 @@ start:
+ 			dmflags |= DM_FLAGS_IMUX;
+ 
+ 		xfs_iunlock(xip, XFS_ILOCK_EXCL);
+-		error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
+-				      pos, count,
+-				      dmflags, &locktype);
++		error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, xip,
++				      pos, count, dmflags, &iolock);
+ 		if (error) {
+ 			goto out_unlock_internal;
+ 		}
+@@ -664,10 +657,9 @@ start:
+ 			return XFS_ERROR(-EINVAL);
+ 		}
+ 
+-		if (!need_i_mutex && (VN_CACHED(vp) || pos > xip->i_size)) {
++		if (!need_i_mutex && (mapping->nrpages || pos > xip->i_size)) {
+ 			xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
+ 			iolock = XFS_IOLOCK_EXCL;
+-			locktype = VRWLOCK_WRITE;
+ 			need_i_mutex = 1;
+ 			mutex_lock(&inode->i_mutex);
+ 			xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
+@@ -679,10 +671,16 @@ start:
+ 	if (new_size > xip->i_size)
+ 		xip->i_new_size = new_size;
+ 
+-	if (likely(!(ioflags & IO_INVIS))) {
++	/*
++	 * We're not supposed to change timestamps in readonly-mounted
++	 * filesystems.  Throw it away if anyone asks us.
++	 */
++	if (likely(!(ioflags & IO_INVIS) &&
++		   !mnt_want_write(file->f_path.mnt))) {
+ 		file_update_time(file);
+ 		xfs_ichgtime_fast(xip, inode,
+ 				  XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
++		mnt_drop_write(file->f_path.mnt);
+ 	}
+ 
+ 	/*
+@@ -727,7 +725,7 @@ retry:
+ 	current->backing_dev_info = mapping->backing_dev_info;
+ 
+ 	if ((ioflags & IO_ISDIRECT)) {
+-		if (VN_CACHED(vp)) {
++		if (mapping->nrpages) {
+ 			WARN_ON(need_i_mutex == 0);
+ 			xfs_inval_cached_trace(xip, pos, -1,
+ 					(pos & PAGE_CACHE_MASK), -1);
+@@ -744,7 +742,6 @@ retry:
+ 			mutex_unlock(&inode->i_mutex);
+ 
+ 			iolock = XFS_IOLOCK_SHARED;
+-			locktype = VRWLOCK_WRITE_DIRECT;
+ 			need_i_mutex = 0;
+ 		}
+ 
+@@ -781,15 +778,15 @@ retry:
+ 
+ 	if (ret == -ENOSPC &&
+ 	    DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
+-		xfs_rwunlock(xip, locktype);
++		xfs_iunlock(xip, iolock);
+ 		if (need_i_mutex)
+ 			mutex_unlock(&inode->i_mutex);
+-		error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
+-				DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
++		error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, xip,
++				DM_RIGHT_NULL, xip, DM_RIGHT_NULL, NULL, NULL,
+ 				0, 0, 0); /* Delay flag intentionally  unused */
+ 		if (need_i_mutex)
+ 			mutex_lock(&inode->i_mutex);
+-		xfs_rwlock(xip, locktype);
++		xfs_ilock(xip, iolock);
+ 		if (error)
+ 			goto out_unlock_internal;
+ 		pos = xip->i_size;
+@@ -817,7 +814,8 @@ retry:
+ 	/* Handle various SYNC-type writes */
+ 	if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
+ 		int error2;
+-		xfs_rwunlock(xip, locktype);
++
++		xfs_iunlock(xip, iolock);
+ 		if (need_i_mutex)
+ 			mutex_unlock(&inode->i_mutex);
+ 		error2 = sync_page_range(inode, mapping, pos, ret);
+@@ -825,7 +823,7 @@ retry:
+ 			error = error2;
+ 		if (need_i_mutex)
+ 			mutex_lock(&inode->i_mutex);
+-		xfs_rwlock(xip, locktype);
++		xfs_ilock(xip, iolock);
+ 		error2 = xfs_write_sync_logforce(mp, xip);
+ 		if (!error)
+ 			error = error2;
+@@ -846,7 +844,7 @@ retry:
+ 			xip->i_d.di_size = xip->i_size;
+ 		xfs_iunlock(xip, XFS_ILOCK_EXCL);
+ 	}
+-	xfs_rwunlock(xip, locktype);
++	xfs_iunlock(xip, iolock);
+  out_unlock_mutex:
+ 	if (need_i_mutex)
+ 		mutex_unlock(&inode->i_mutex);
+@@ -884,28 +882,23 @@ xfs_bdstrat_cb(struct xfs_buf *bp)
+ }
+ 
+ /*
+- * Wrapper around bdstrat so that we can stop data
+- * from going to disk in case we are shutting down the filesystem.
+- * Typically user data goes thru this path; one of the exceptions
+- * is the superblock.
++ * Wrapper around bdstrat so that we can stop data from going to disk in case
++ * we are shutting down the filesystem.  Typically user data goes thru this
++ * path; one of the exceptions is the superblock.
+  */
+-int
++void
+ xfsbdstrat(
+ 	struct xfs_mount	*mp,
+ 	struct xfs_buf		*bp)
+ {
+ 	ASSERT(mp);
+ 	if (!XFS_FORCED_SHUTDOWN(mp)) {
+-		/* Grio redirection would go here
+-		 * if (XFS_BUF_IS_GRIO(bp)) {
+-		 */
+-
+ 		xfs_buf_iorequest(bp);
+-		return 0;
++		return;
+ 	}
+ 
+ 	xfs_buftrace("XFSBDSTRAT IOERROR", bp);
+-	return (xfs_bioerror_relse(bp));
++	xfs_bioerror_relse(bp);
+ }
+ 
+ /*
+diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
+index e200253..e1d498b 100644
+--- a/fs/xfs/linux-2.6/xfs_lrw.h
++++ b/fs/xfs/linux-2.6/xfs_lrw.h
+@@ -68,7 +68,8 @@ extern void xfs_inval_cached_trace(struct xfs_inode *,
+ #define xfs_inval_cached_trace(ip, offset, len, first, last)
+ #endif
+ 
+-extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
++/* errors from xfsbdstrat() must be extracted from the buffer */
++extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
+ extern int xfs_bdstrat_cb(struct xfs_buf *);
+ extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
+ 
+diff --git a/fs/xfs/linux-2.6/xfs_stats.h b/fs/xfs/linux-2.6/xfs_stats.h
+index 8ba7a2f..afd0b0d 100644
+--- a/fs/xfs/linux-2.6/xfs_stats.h
++++ b/fs/xfs/linux-2.6/xfs_stats.h
+@@ -144,8 +144,8 @@ extern void xfs_cleanup_procfs(void);
+ # define XFS_STATS_DEC(count)
+ # define XFS_STATS_ADD(count, inc)
+ 
+-static __inline void xfs_init_procfs(void) { };
+-static __inline void xfs_cleanup_procfs(void) { };
++static inline void xfs_init_procfs(void) { };
++static inline void xfs_cleanup_procfs(void) { };
+ 
+ #endif	/* !CONFIG_PROC_FS */
+ 
+diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
+index 8831d95..865eb70 100644
+--- a/fs/xfs/linux-2.6/xfs_super.c
++++ b/fs/xfs/linux-2.6/xfs_super.c
+@@ -896,7 +896,8 @@ xfs_fs_write_inode(
+ 	struct inode		*inode,
+ 	int			sync)
+ {
+-	int			error = 0, flags = FLUSH_INODE;
++	int			error = 0;
++	int			flags = 0;
+ 
+ 	xfs_itrace_entry(XFS_I(inode));
+ 	if (sync) {
+@@ -934,7 +935,7 @@ xfs_fs_clear_inode(
+ 		xfs_inactive(ip);
+ 		xfs_iflags_clear(ip, XFS_IMODIFIED);
+ 		if (xfs_reclaim(ip))
+-			panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, inode);
++			panic("%s: cannot reclaim 0x%p\n", __func__, inode);
+ 	}
+ 
+ 	ASSERT(XFS_I(inode) == NULL);
+@@ -1027,8 +1028,7 @@ xfs_sync_worker(
+ 	int		error;
+ 
+ 	if (!(mp->m_flags & XFS_MOUNT_RDONLY))
+-		error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR |
+-				     SYNC_REFCACHE | SYNC_SUPER);
++		error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR);
+ 	mp->m_sync_seq++;
+ 	wake_up(&mp->m_wait_single_sync_task);
+ }
+@@ -1306,7 +1306,7 @@ xfs_fs_fill_super(
+ 	void			*data,
+ 	int			silent)
+ {
+-	struct inode		*rootvp;
++	struct inode		*root;
+ 	struct xfs_mount	*mp = NULL;
+ 	struct xfs_mount_args	*args = xfs_args_allocate(sb, silent);
+ 	int			error;
+@@ -1344,19 +1344,18 @@ xfs_fs_fill_super(
+ 	sb->s_time_gran = 1;
+ 	set_posix_acl_flag(sb);
+ 
+-	rootvp = igrab(mp->m_rootip->i_vnode);
+-	if (!rootvp) {
++	root = igrab(mp->m_rootip->i_vnode);
++	if (!root) {
+ 		error = ENOENT;
+ 		goto fail_unmount;
+ 	}
+-
+-	sb->s_root = d_alloc_root(vn_to_inode(rootvp));
+-	if (!sb->s_root) {
+-		error = ENOMEM;
++	if (is_bad_inode(root)) {
++		error = EINVAL;
+ 		goto fail_vnrele;
+ 	}
+-	if (is_bad_inode(sb->s_root->d_inode)) {
+-		error = EINVAL;
++	sb->s_root = d_alloc_root(root);
++	if (!sb->s_root) {
++		error = ENOMEM;
+ 		goto fail_vnrele;
+ 	}
+ 
+@@ -1378,7 +1377,7 @@ fail_vnrele:
+ 		dput(sb->s_root);
+ 		sb->s_root = NULL;
+ 	} else {
+-		VN_RELE(rootvp);
++		iput(root);
+ 	}
+ 
+ fail_unmount:
+diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
+index 3efcf45..3efb7c6 100644
+--- a/fs/xfs/linux-2.6/xfs_super.h
++++ b/fs/xfs/linux-2.6/xfs_super.h
+@@ -50,13 +50,7 @@ extern void xfs_qm_exit(void);
+ # define set_posix_acl_flag(sb)	do { } while (0)
+ #endif
+ 
+-#ifdef CONFIG_XFS_SECURITY
+-# define XFS_SECURITY_STRING	"security attributes, "
+-# define ENOSECURITY		0
+-#else
+-# define XFS_SECURITY_STRING
+-# define ENOSECURITY		EOPNOTSUPP
+-#endif
++#define XFS_SECURITY_STRING	"security attributes, "
+ 
+ #ifdef CONFIG_XFS_RT
+ # define XFS_REALTIME_STRING	"realtime, "
+diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
+index 4da03a4..7e60c77 100644
+--- a/fs/xfs/linux-2.6/xfs_vfs.h
++++ b/fs/xfs/linux-2.6/xfs_vfs.h
+@@ -49,7 +49,6 @@ typedef struct bhv_vfs_sync_work {
+ #define SYNC_REFCACHE		0x0040  /* prune some of the nfs ref cache */
+ #define SYNC_REMOUNT		0x0080  /* remount readonly, no dummy LRs */
+ #define SYNC_IOWAIT		0x0100  /* wait for all I/O to complete */
+-#define SYNC_SUPER		0x0200  /* flush superblock to disk */
+ 
+ /*
+  * When remounting a filesystem read-only or freezing the filesystem,
+diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
+index b5ea418..8b4d63c 100644
+--- a/fs/xfs/linux-2.6/xfs_vnode.h
++++ b/fs/xfs/linux-2.6/xfs_vnode.h
+@@ -23,8 +23,6 @@ struct bhv_vattr;
+ struct xfs_iomap;
+ struct attrlist_cursor_kern;
+ 
+-typedef struct dentry	bhv_vname_t;
+-typedef __u64		bhv_vnumber_t;
+ typedef struct inode	bhv_vnode_t;
+ 
+ #define VN_ISLNK(vp)	S_ISLNK((vp)->i_mode)
+@@ -46,18 +44,6 @@ static inline struct inode *vn_to_inode(bhv_vnode_t *vnode)
+ }
+ 
+ /*
+- * Values for the vop_rwlock/rwunlock flags parameter.
+- */
+-typedef enum bhv_vrwlock {
+-	VRWLOCK_NONE,
+-	VRWLOCK_READ,
+-	VRWLOCK_WRITE,
+-	VRWLOCK_WRITE_DIRECT,
+-	VRWLOCK_TRY_READ,
+-	VRWLOCK_TRY_WRITE
+-} bhv_vrwlock_t;
+-
+-/*
+  * Return values for xfs_inactive.  A return value of
+  * VN_INACTIVE_NOCACHE implies that the file system behavior
+  * has disassociated its state and bhv_desc_t from the vnode.
+@@ -73,12 +59,9 @@ typedef enum bhv_vrwlock {
+ #define IO_INVIS	0x00020		/* don't update inode timestamps */
+ 
+ /*
+- * Flags for vop_iflush call
++ * Flags for xfs_inode_flush
+  */
+ #define FLUSH_SYNC		1	/* wait for flush to complete	*/
+-#define FLUSH_INODE		2	/* flush the inode itself	*/
+-#define FLUSH_LOG		4	/* force the last log entry for
+-					 * this inode out to disk	*/
+ 
+ /*
+  * Flush/Invalidate options for vop_toss/flush/flushinval_pages.
+@@ -226,13 +209,6 @@ static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp)
+ }
+ 
+ /*
+- * Vname handling macros.
+- */
+-#define VNAME(dentry)		((char *) (dentry)->d_name.name)
+-#define VNAMELEN(dentry)	((dentry)->d_name.len)
+-#define VNAME_TO_VNODE(dentry)	(vn_from_inode((dentry)->d_inode))
+-
+-/*
+  * Dealing with bad inodes
+  */
+ static inline int VN_BAD(bhv_vnode_t *vp)
+@@ -303,9 +279,9 @@ extern void xfs_itrace_hold(struct xfs_inode *, char *, int, inst_t *);
+ extern void _xfs_itrace_ref(struct xfs_inode *, char *, int, inst_t *);
+ extern void xfs_itrace_rele(struct xfs_inode *, char *, int, inst_t *);
+ #define xfs_itrace_entry(ip)	\
+-	_xfs_itrace_entry(ip, __FUNCTION__, (inst_t *)__return_address)
++	_xfs_itrace_entry(ip, __func__, (inst_t *)__return_address)
+ #define xfs_itrace_exit(ip)	\
+-	_xfs_itrace_exit(ip, __FUNCTION__, (inst_t *)__return_address)
++	_xfs_itrace_exit(ip, __func__, (inst_t *)__return_address)
+ #define xfs_itrace_exit_tag(ip, tag)	\
+ 	_xfs_itrace_exit(ip, tag, (inst_t *)__return_address)
+ #define xfs_itrace_ref(ip)	\
+diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
+index 665babc..631ebb3 100644
+--- a/fs/xfs/quota/xfs_dquot.c
++++ b/fs/xfs/quota/xfs_dquot.c
+@@ -1291,7 +1291,7 @@ xfs_qm_dqflush(
+ 	if (flags & XFS_QMOPT_DELWRI) {
+ 		xfs_bdwrite(mp, bp);
+ 	} else if (flags & XFS_QMOPT_ASYNC) {
+-		xfs_bawrite(mp, bp);
++		error = xfs_bawrite(mp, bp);
+ 	} else {
+ 		error = xfs_bwrite(mp, bp);
+ 	}
+@@ -1439,9 +1439,7 @@ xfs_qm_dqpurge(
+ 	uint		flags)
+ {
+ 	xfs_dqhash_t	*thishash;
+-	xfs_mount_t	*mp;
+-
+-	mp = dqp->q_mount;
++	xfs_mount_t	*mp = dqp->q_mount;
+ 
+ 	ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp));
+ 	ASSERT(XFS_DQ_IS_HASH_LOCKED(dqp->q_hash));
+@@ -1485,6 +1483,7 @@ xfs_qm_dqpurge(
+ 	 * we're unmounting, we do care, so we flush it and wait.
+ 	 */
+ 	if (XFS_DQ_IS_DIRTY(dqp)) {
++		int	error;
+ 		xfs_dqtrace_entry(dqp, "DQPURGE ->DQFLUSH: DQDIRTY");
+ 		/* dqflush unlocks dqflock */
+ 		/*
+@@ -1495,7 +1494,10 @@ xfs_qm_dqpurge(
+ 		 * We don't care about getting disk errors here. We need
+ 		 * to purge this dquot anyway, so we go ahead regardless.
+ 		 */
+-		(void) xfs_qm_dqflush(dqp, XFS_QMOPT_SYNC);
++		error = xfs_qm_dqflush(dqp, XFS_QMOPT_SYNC);
++		if (error)
++			xfs_fs_cmn_err(CE_WARN, mp,
++				"xfs_qm_dqpurge: dquot %p flush failed", dqp);
+ 		xfs_dqflock(dqp);
+ 	}
+ 	ASSERT(dqp->q_pincount == 0);
+@@ -1580,12 +1582,18 @@ xfs_qm_dqflock_pushbuf_wait(
+ 		    XFS_INCORE_TRYLOCK);
+ 	if (bp != NULL) {
+ 		if (XFS_BUF_ISDELAYWRITE(bp)) {
++			int	error;
+ 			if (XFS_BUF_ISPINNED(bp)) {
+ 				xfs_log_force(dqp->q_mount,
+ 					      (xfs_lsn_t)0,
+ 					      XFS_LOG_FORCE);
+ 			}
+-			xfs_bawrite(dqp->q_mount, bp);
++			error = xfs_bawrite(dqp->q_mount, bp);
++			if (error)
++				xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
++					"xfs_qm_dqflock_pushbuf_wait: "
++					"pushbuf error %d on dqp %p, bp %p",
++					error, dqp, bp);
+ 		} else {
+ 			xfs_buf_relse(bp);
+ 		}
+diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
+index 1800e8d..36e05ca 100644
+--- a/fs/xfs/quota/xfs_dquot_item.c
++++ b/fs/xfs/quota/xfs_dquot_item.c
+@@ -146,6 +146,7 @@ xfs_qm_dquot_logitem_push(
+ 	xfs_dq_logitem_t	*logitem)
+ {
+ 	xfs_dquot_t	*dqp;
++	int		error;
+ 
+ 	dqp = logitem->qli_dquot;
+ 
+@@ -161,7 +162,11 @@ xfs_qm_dquot_logitem_push(
+ 	 * lock without sleeping, then there must not have been
+ 	 * anyone in the process of flushing the dquot.
+ 	 */
+-	xfs_qm_dqflush(dqp, XFS_B_DELWRI);
++	error = xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++	if (error)
++		xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
++			"xfs_qm_dquot_logitem_push: push error %d on dqp %p",
++			error, dqp);
+ 	xfs_dqunlock(dqp);
+ }
+ 
+@@ -262,11 +267,16 @@ xfs_qm_dquot_logitem_pushbuf(
+ 					      XFS_LOG_FORCE);
+ 			}
+ 			if (dopush) {
++				int	error;
+ #ifdef XFSRACEDEBUG
+ 				delay_for_intr();
+ 				delay(300);
+ #endif
+-				xfs_bawrite(mp, bp);
++				error = xfs_bawrite(mp, bp);
++				if (error)
++					xfs_fs_cmn_err(CE_WARN, mp,
++	"xfs_qm_dquot_logitem_pushbuf: pushbuf error %d on qip %p, bp %p",
++							error, qip, bp);
+ 			} else {
+ 				xfs_buf_relse(bp);
+ 			}
+diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
+index 8e9c5ae..40ea564 100644
+--- a/fs/xfs/quota/xfs_qm.c
++++ b/fs/xfs/quota/xfs_qm.c
+@@ -304,8 +304,11 @@ xfs_qm_unmount_quotadestroy(
+  * necessary data structures like quotainfo.  This is also responsible for
+  * running a quotacheck as necessary.  We are guaranteed that the superblock
+  * is consistently read in at this point.
++ *
++ * If we fail here, the mount will continue with quota turned off. We don't
++ * need to inidicate success or failure at all.
+  */
+-int
++void
+ xfs_qm_mount_quotas(
+ 	xfs_mount_t	*mp,
+ 	int		mfsi_flags)
+@@ -313,7 +316,6 @@ xfs_qm_mount_quotas(
+ 	int		error = 0;
+ 	uint		sbf;
+ 
+-
+ 	/*
+ 	 * If quotas on realtime volumes is not supported, we disable
+ 	 * quotas immediately.
+@@ -332,7 +334,8 @@ xfs_qm_mount_quotas(
+ 	 * Allocate the quotainfo structure inside the mount struct, and
+ 	 * create quotainode(s), and change/rev superblock if necessary.
+ 	 */
+-	if ((error = xfs_qm_init_quotainfo(mp))) {
++	error = xfs_qm_init_quotainfo(mp);
++	if (error) {
+ 		/*
+ 		 * We must turn off quotas.
+ 		 */
+@@ -344,12 +347,11 @@ xfs_qm_mount_quotas(
+ 	 * If any of the quotas are not consistent, do a quotacheck.
+ 	 */
+ 	if (XFS_QM_NEED_QUOTACHECK(mp) &&
+-		!(mfsi_flags & XFS_MFSI_NO_QUOTACHECK)) {
+-		if ((error = xfs_qm_quotacheck(mp))) {
+-			/* Quotacheck has failed and quotas have
+-			 * been disabled.
+-			 */
+-			return XFS_ERROR(error);
++	    !(mfsi_flags & XFS_MFSI_NO_QUOTACHECK)) {
++		error = xfs_qm_quotacheck(mp);
++		if (error) {
++			/* Quotacheck failed and disabled quotas. */
++			return;
+ 		}
+ 	}
+ 	/* 
+@@ -357,12 +359,10 @@ xfs_qm_mount_quotas(
+ 	 * quotachecked status, since we won't be doing accounting for
+ 	 * that type anymore.
+ 	 */
+-	if (!XFS_IS_UQUOTA_ON(mp)) {
++	if (!XFS_IS_UQUOTA_ON(mp))
+ 		mp->m_qflags &= ~XFS_UQUOTA_CHKD;
+-	}
+-	if (!(XFS_IS_GQUOTA_ON(mp) || XFS_IS_PQUOTA_ON(mp))) {
++	if (!(XFS_IS_GQUOTA_ON(mp) || XFS_IS_PQUOTA_ON(mp)))
+ 		mp->m_qflags &= ~XFS_OQUOTA_CHKD;
+-	}
+ 
+  write_changes:
+ 	/*
+@@ -392,7 +392,7 @@ xfs_qm_mount_quotas(
+ 		xfs_fs_cmn_err(CE_WARN, mp,
+ 			"Failed to initialize disk quotas.");
+ 	}
+-	return XFS_ERROR(error);
++	return;
+ }
+ 
+ /*
+@@ -1438,7 +1438,7 @@ xfs_qm_qino_alloc(
+ }
+ 
+ 
+-STATIC int
++STATIC void
+ xfs_qm_reset_dqcounts(
+ 	xfs_mount_t	*mp,
+ 	xfs_buf_t	*bp,
+@@ -1478,8 +1478,6 @@ xfs_qm_reset_dqcounts(
+ 		ddq->d_rtbwarns = 0;
+ 		ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
+ 	}
+-
+-	return 0;
+ }
+ 
+ STATIC int
+@@ -1520,7 +1518,7 @@ xfs_qm_dqiter_bufs(
+ 		if (error)
+ 			break;
+ 
+-		(void) xfs_qm_reset_dqcounts(mp, bp, firstid, type);
++		xfs_qm_reset_dqcounts(mp, bp, firstid, type);
+ 		xfs_bdwrite(mp, bp);
+ 		/*
+ 		 * goto the next block.
+@@ -1810,7 +1808,7 @@ xfs_qm_dqusage_adjust(
+ 	 * Now release the inode. This will send it to 'inactive', and
+ 	 * possibly even free blocks.
+ 	 */
+-	VN_RELE(XFS_ITOV(ip));
++	IRELE(ip);
+ 
+ 	/*
+ 	 * Goto next inode.
+@@ -1880,6 +1878,14 @@ xfs_qm_quotacheck(
+ 	} while (! done);
+ 
+ 	/*
++	 * We've made all the changes that we need to make incore.
++	 * Flush them down to disk buffers if everything was updated
++	 * successfully.
++	 */
++	if (!error)
++		error = xfs_qm_dqflush_all(mp, XFS_QMOPT_DELWRI);
++
++	/*
+ 	 * We can get this error if we couldn't do a dquot allocation inside
+ 	 * xfs_qm_dqusage_adjust (via bulkstat). We don't care about the
+ 	 * dirty dquots that might be cached, we just want to get rid of them
+@@ -1890,11 +1896,6 @@ xfs_qm_quotacheck(
+ 		xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_QUOTAOFF);
+ 		goto error_return;
+ 	}
+-	/*
+-	 * We've made all the changes that we need to make incore.
+-	 * Now flush_them down to disk buffers.
+-	 */
+-	xfs_qm_dqflush_all(mp, XFS_QMOPT_DELWRI);
+ 
+ 	/*
+ 	 * We didn't log anything, because if we crashed, we'll have to
+@@ -1926,7 +1927,10 @@ xfs_qm_quotacheck(
+ 		ASSERT(mp->m_quotainfo != NULL);
+ 		ASSERT(xfs_Gqm != NULL);
+ 		xfs_qm_destroy_quotainfo(mp);
+-		(void)xfs_mount_reset_sbqflags(mp);
++		if (xfs_mount_reset_sbqflags(mp)) {
++			cmn_err(CE_WARN, "XFS quotacheck %s: "
++				"Failed to reset quota flags.", mp->m_fsname);
++		}
+ 	} else {
+ 		cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname);
+ 	}
+@@ -1968,7 +1972,7 @@ xfs_qm_init_quotainos(
+ 			if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
+ 					     0, 0, &gip, 0))) {
+ 				if (uip)
+-					VN_RELE(XFS_ITOV(uip));
++					IRELE(uip);
+ 				return XFS_ERROR(error);
+ 			}
+ 		}
+@@ -1999,7 +2003,7 @@ xfs_qm_init_quotainos(
+ 					  sbflags | XFS_SB_GQUOTINO, flags);
+ 		if (error) {
+ 			if (uip)
+-				VN_RELE(XFS_ITOV(uip));
++				IRELE(uip);
+ 
+ 			return XFS_ERROR(error);
+ 		}
+@@ -2093,12 +2097,17 @@ xfs_qm_shake_freelist(
+ 		 * dirty dquots.
+ 		 */
+ 		if (XFS_DQ_IS_DIRTY(dqp)) {
++			int	error;
+ 			xfs_dqtrace_entry(dqp, "DQSHAKE: DQDIRTY");
+ 			/*
+ 			 * We flush it delayed write, so don't bother
+ 			 * releasing the mplock.
+ 			 */
+-			(void) xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++			error = xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++			if (error) {
++				xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
++			"xfs_qm_dqflush_all: dquot %p flush failed", dqp);
++			}
+ 			xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
+ 			dqp = dqp->dq_flnext;
+ 			continue;
+@@ -2265,12 +2274,17 @@ xfs_qm_dqreclaim_one(void)
+ 		 * dirty dquots.
+ 		 */
+ 		if (XFS_DQ_IS_DIRTY(dqp)) {
++			int	error;
+ 			xfs_dqtrace_entry(dqp, "DQRECLAIM: DQDIRTY");
+ 			/*
+ 			 * We flush it delayed write, so don't bother
+ 			 * releasing the freelist lock.
+ 			 */
+-			(void) xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++			error = xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++			if (error) {
++				xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
++			"xfs_qm_dqreclaim: dquot %p flush failed", dqp);
++			}
+ 			xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
+ 			continue;
+ 		}
+@@ -2378,9 +2392,9 @@ xfs_qm_write_sb_changes(
+ 	}
+ 
+ 	xfs_mod_sb(tp, flags);
+-	(void) xfs_trans_commit(tp, 0);
++	error = xfs_trans_commit(tp, 0);
+ 
+-	return 0;
++	return error;
+ }
+ 
+ 
+diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
+index baf537c..cd2300e 100644
+--- a/fs/xfs/quota/xfs_qm.h
++++ b/fs/xfs/quota/xfs_qm.h
+@@ -165,7 +165,7 @@ typedef struct xfs_dquot_acct {
+ #define XFS_QM_RELE(xqm)	((xqm)->qm_nrefs--)
+ 
+ extern void		xfs_qm_destroy_quotainfo(xfs_mount_t *);
+-extern int		xfs_qm_mount_quotas(xfs_mount_t *, int);
++extern void		xfs_qm_mount_quotas(xfs_mount_t *, int);
+ extern int		xfs_qm_quotacheck(xfs_mount_t *);
+ extern void		xfs_qm_unmount_quotadestroy(xfs_mount_t *);
+ extern int		xfs_qm_unmount_quotas(xfs_mount_t *);
+diff --git a/fs/xfs/quota/xfs_qm_stats.h b/fs/xfs/quota/xfs_qm_stats.h
+index a50ffab..5b964fc 100644
+--- a/fs/xfs/quota/xfs_qm_stats.h
++++ b/fs/xfs/quota/xfs_qm_stats.h
+@@ -45,8 +45,8 @@ extern void xfs_qm_cleanup_procfs(void);
+ 
+ # define XQM_STATS_INC(count)	do { } while (0)
+ 
+-static __inline void xfs_qm_init_procfs(void) { };
+-static __inline void xfs_qm_cleanup_procfs(void) { };
++static inline void xfs_qm_init_procfs(void) { };
++static inline void xfs_qm_cleanup_procfs(void) { };
+ 
+ #endif
+ 
+diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
+index d2b8be7..8342823 100644
+--- a/fs/xfs/quota/xfs_qm_syscalls.c
++++ b/fs/xfs/quota/xfs_qm_syscalls.c
+@@ -279,9 +279,12 @@ xfs_qm_scall_quotaoff(
+ 
+ 	/*
+ 	 * Write the LI_QUOTAOFF log record, and do SB changes atomically,
+-	 * and synchronously.
++	 * and synchronously. If we fail to write, we should abort the
++	 * operation as it cannot be recovered safely if we crash.
+ 	 */
+-	xfs_qm_log_quotaoff(mp, &qoffstart, flags);
++	error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
++	if (error)
++		goto out_error;
+ 
+ 	/*
+ 	 * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
+@@ -337,7 +340,12 @@ xfs_qm_scall_quotaoff(
+ 	 * So, we have QUOTAOFF start and end logitems; the start
+ 	 * logitem won't get overwritten until the end logitem appears...
+ 	 */
+-	xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
++	error = xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
++	if (error) {
++		/* We're screwed now. Shutdown is the only option. */
++		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
++		goto out_error;
++	}
+ 
+ 	/*
+ 	 * If quotas is completely disabled, close shop.
+@@ -361,6 +369,7 @@ xfs_qm_scall_quotaoff(
+ 		XFS_PURGE_INODE(XFS_QI_GQIP(mp));
+ 		XFS_QI_GQIP(mp) = NULL;
+ 	}
++out_error:
+ 	mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
+ 
+ 	return (error);
+@@ -371,12 +380,11 @@ xfs_qm_scall_trunc_qfiles(
+ 	xfs_mount_t	*mp,
+ 	uint		flags)
+ {
+-	int		error;
++	int		error = 0, error2 = 0;
+ 	xfs_inode_t	*qip;
+ 
+ 	if (!capable(CAP_SYS_ADMIN))
+ 		return XFS_ERROR(EPERM);
+-	error = 0;
+ 	if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
+ 		qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags);
+ 		return XFS_ERROR(EINVAL);
+@@ -384,22 +392,22 @@ xfs_qm_scall_trunc_qfiles(
+ 
+ 	if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) {
+ 		error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip, 0);
+-		if (! error) {
+-			(void) xfs_truncate_file(mp, qip);
+-			VN_RELE(XFS_ITOV(qip));
++		if (!error) {
++			error = xfs_truncate_file(mp, qip);
++			IRELE(qip);
+ 		}
+ 	}
+ 
+ 	if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
+ 	    mp->m_sb.sb_gquotino != NULLFSINO) {
+-		error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
+-		if (! error) {
+-			(void) xfs_truncate_file(mp, qip);
+-			VN_RELE(XFS_ITOV(qip));
++		error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
++		if (!error2) {
++			error2 = xfs_truncate_file(mp, qip);
++			IRELE(qip);
+ 		}
+ 	}
+ 
+-	return (error);
++	return error ? error : error2;
+ }
+ 
+ 
+@@ -552,13 +560,13 @@ xfs_qm_scall_getqstat(
+ 		out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
+ 		out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
+ 		if (tempuqip)
+-			VN_RELE(XFS_ITOV(uip));
++			IRELE(uip);
+ 	}
+ 	if (gip) {
+ 		out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
+ 		out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
+ 		if (tempgqip)
+-			VN_RELE(XFS_ITOV(gip));
++			IRELE(gip);
+ 	}
+ 	if (mp->m_quotainfo) {
+ 		out->qs_incoredqs = XFS_QI_MPLNDQUOTS(mp);
+@@ -726,12 +734,12 @@ xfs_qm_scall_setqlim(
+ 	xfs_trans_log_dquot(tp, dqp);
+ 
+ 	xfs_dqtrace_entry(dqp, "Q_SETQLIM: COMMIT");
+-	xfs_trans_commit(tp, 0);
++	error = xfs_trans_commit(tp, 0);
+ 	xfs_qm_dqprint(dqp);
+ 	xfs_qm_dqrele(dqp);
+ 	mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
+ 
+-	return (0);
++	return error;
+ }
+ 
+ STATIC int
+@@ -1095,7 +1103,7 @@ again:
+ 		 * inactive code in hell.
+ 		 */
+ 		if (vnode_refd)
+-			VN_RELE(vp);
++			IRELE(ip);
+ 		XFS_MOUNT_ILOCK(mp);
+ 		/*
+ 		 * If an inode was inserted or removed, we gotta
+diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c
+index 129067c..0b75d30 100644
+--- a/fs/xfs/support/ktrace.c
++++ b/fs/xfs/support/ktrace.c
+@@ -24,7 +24,7 @@ static int          ktrace_zentries;
+ void __init
+ ktrace_init(int zentries)
+ {
+-	ktrace_zentries = zentries;
++	ktrace_zentries = roundup_pow_of_two(zentries);
+ 
+ 	ktrace_hdr_zone = kmem_zone_init(sizeof(ktrace_t),
+ 					"ktrace_hdr");
+@@ -47,13 +47,16 @@ ktrace_uninit(void)
+  * ktrace_alloc()
+  *
+  * Allocate a ktrace header and enough buffering for the given
+- * number of entries.
++ * number of entries. Round the number of entries up to a
++ * power of 2 so we can do fast masking to get the index from
++ * the atomic index counter.
+  */
+ ktrace_t *
+ ktrace_alloc(int nentries, unsigned int __nocast sleep)
+ {
+ 	ktrace_t        *ktp;
+ 	ktrace_entry_t  *ktep;
++	int		entries;
+ 
+ 	ktp = (ktrace_t*)kmem_zone_alloc(ktrace_hdr_zone, sleep);
+ 
+@@ -70,11 +73,12 @@ ktrace_alloc(int nentries, unsigned int __nocast sleep)
+ 	/*
+ 	 * Special treatment for buffers with the ktrace_zentries entries
+ 	 */
+-	if (nentries == ktrace_zentries) {
++	entries = roundup_pow_of_two(nentries);
++	if (entries == ktrace_zentries) {
+ 		ktep = (ktrace_entry_t*)kmem_zone_zalloc(ktrace_ent_zone,
+ 							    sleep);
+ 	} else {
+-		ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)),
++		ktep = (ktrace_entry_t*)kmem_zalloc((entries * sizeof(*ktep)),
+ 							    sleep | KM_LARGE);
+ 	}
+ 
+@@ -91,8 +95,10 @@ ktrace_alloc(int nentries, unsigned int __nocast sleep)
+ 	}
+ 
+ 	ktp->kt_entries  = ktep;
+-	ktp->kt_nentries = nentries;
+-	ktp->kt_index    = 0;
++	ktp->kt_nentries = entries;
++	ASSERT(is_power_of_2(entries));
++	ktp->kt_index_mask = entries - 1;
++	atomic_set(&ktp->kt_index, 0);
+ 	ktp->kt_rollover = 0;
+ 	return ktp;
+ }
+@@ -151,8 +157,6 @@ ktrace_enter(
+ 	void            *val14,
+ 	void            *val15)
+ {
+-	static DEFINE_SPINLOCK(wrap_lock);
+-	unsigned long	flags;
+ 	int             index;
+ 	ktrace_entry_t  *ktep;
+ 
+@@ -161,12 +165,8 @@ ktrace_enter(
+ 	/*
+ 	 * Grab an entry by pushing the index up to the next one.
+ 	 */
+-	spin_lock_irqsave(&wrap_lock, flags);
+-	index = ktp->kt_index;
+-	if (++ktp->kt_index == ktp->kt_nentries)
+-		ktp->kt_index = 0;
+-	spin_unlock_irqrestore(&wrap_lock, flags);
+-
++	index = atomic_add_return(1, &ktp->kt_index);
++	index = (index - 1) & ktp->kt_index_mask;
+ 	if (!ktp->kt_rollover && index == ktp->kt_nentries - 1)
+ 		ktp->kt_rollover = 1;
+ 
+@@ -199,11 +199,12 @@ int
+ ktrace_nentries(
+ 	ktrace_t        *ktp)
+ {
+-	if (ktp == NULL) {
++	int	index;
++	if (ktp == NULL)
+ 		return 0;
+-	}
+ 
+-	return (ktp->kt_rollover ? ktp->kt_nentries : ktp->kt_index);
++	index = atomic_read(&ktp->kt_index) & ktp->kt_index_mask;
++	return (ktp->kt_rollover ? ktp->kt_nentries : index);
+ }
+ 
+ /*
+@@ -228,7 +229,7 @@ ktrace_first(ktrace_t   *ktp, ktrace_snap_t     *ktsp)
+ 	int             nentries;
+ 
+ 	if (ktp->kt_rollover)
+-		index = ktp->kt_index;
++		index = atomic_read(&ktp->kt_index) & ktp->kt_index_mask;
+ 	else
+ 		index = 0;
+ 
+diff --git a/fs/xfs/support/ktrace.h b/fs/xfs/support/ktrace.h
+index 56e72b4..741d694 100644
+--- a/fs/xfs/support/ktrace.h
++++ b/fs/xfs/support/ktrace.h
+@@ -30,7 +30,8 @@ typedef struct ktrace_entry {
+  */
+ typedef struct ktrace {
+ 	int		kt_nentries;	/* number of entries in trace buf */
+-	int		kt_index;	/* current index in entries */
++	atomic_t	kt_index;	/* current index in entries */
++	unsigned int	kt_index_mask;
+ 	int		kt_rollover;
+ 	ktrace_entry_t	*kt_entries;	/* buffer of entries */
+ } ktrace_t;
+diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h
+index 540e4c9..765aaf6 100644
+--- a/fs/xfs/xfs.h
++++ b/fs/xfs/xfs.h
+@@ -22,7 +22,7 @@
+ #define STATIC
+ #define DEBUG 1
+ #define XFS_BUF_LOCK_TRACKING 1
+-/* #define QUOTADEBUG 1 */
++#define QUOTADEBUG 1
+ #endif
+ 
+ #ifdef CONFIG_XFS_TRACE
+diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
+index 7272fe3..8e130b9 100644
+--- a/fs/xfs/xfs_acl.c
++++ b/fs/xfs/xfs_acl.c
+@@ -307,12 +307,13 @@ xfs_acl_vset(
+ 
+ 	VN_HOLD(vp);
+ 	error = xfs_acl_allow_set(vp, kind);
+-	if (error)
+-		goto out;
+ 
+ 	/* Incoming ACL exists, set file mode based on its value */
+-	if (kind == _ACL_TYPE_ACCESS)
+-		xfs_acl_setmode(vp, xfs_acl, &basicperms);
++	if (!error && kind == _ACL_TYPE_ACCESS)
++		error = xfs_acl_setmode(vp, xfs_acl, &basicperms);
++
++	if (error)
++		goto out;
+ 
+ 	/*
+ 	 * If we have more than std unix permissions, set up the actual attr.
+@@ -323,7 +324,7 @@ xfs_acl_vset(
+ 	if (!basicperms) {
+ 		xfs_acl_set_attr(vp, xfs_acl, kind, &error);
+ 	} else {
+-		xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
++		error = -xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
+ 	}
+ 
+ out:
+@@ -707,7 +708,9 @@ xfs_acl_inherit(
+ 
+ 	memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
+ 	xfs_acl_filter_mode(mode, cacl);
+-	xfs_acl_setmode(vp, cacl, &basicperms);
++	error = xfs_acl_setmode(vp, cacl, &basicperms);
++	if (error)
++		goto out_error;
+ 
+ 	/*
+ 	 * Set the Default and Access ACL on the file.  The mode is already
+@@ -720,6 +723,7 @@ xfs_acl_inherit(
+ 		xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
+ 	if (!error && !basicperms)
+ 		xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
++out_error:
+ 	_ACL_FREE(cacl);
+ 	return error;
+ }
+diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
+index bdbfbbe..1956f83 100644
+--- a/fs/xfs/xfs_alloc.c
++++ b/fs/xfs/xfs_alloc.c
+@@ -45,7 +45,7 @@
+ #define	XFSA_FIXUP_BNO_OK	1
+ #define	XFSA_FIXUP_CNT_OK	2
+ 
+-STATIC int
++STATIC void
+ xfs_alloc_search_busy(xfs_trans_t *tp,
+ 		    xfs_agnumber_t agno,
+ 		    xfs_agblock_t bno,
+@@ -55,24 +55,24 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
+ ktrace_t *xfs_alloc_trace_buf;
+ 
+ #define	TRACE_ALLOC(s,a)	\
+-	xfs_alloc_trace_alloc(__FUNCTION__, s, a, __LINE__)
++	xfs_alloc_trace_alloc(__func__, s, a, __LINE__)
+ #define	TRACE_FREE(s,a,b,x,f)	\
+-	xfs_alloc_trace_free(__FUNCTION__, s, mp, a, b, x, f, __LINE__)
++	xfs_alloc_trace_free(__func__, s, mp, a, b, x, f, __LINE__)
+ #define	TRACE_MODAGF(s,a,f)	\
+-	xfs_alloc_trace_modagf(__FUNCTION__, s, mp, a, f, __LINE__)
+-#define	TRACE_BUSY(__FUNCTION__,s,ag,agb,l,sl,tp)	\
+-	xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
+-#define	TRACE_UNBUSY(__FUNCTION__,s,ag,sl,tp)	\
+-	xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
+-#define	TRACE_BUSYSEARCH(__FUNCTION__,s,ag,agb,l,sl,tp)	\
+-	xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
++	xfs_alloc_trace_modagf(__func__, s, mp, a, f, __LINE__)
++#define	TRACE_BUSY(__func__,s,ag,agb,l,sl,tp)	\
++	xfs_alloc_trace_busy(__func__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
++#define	TRACE_UNBUSY(__func__,s,ag,sl,tp)	\
++	xfs_alloc_trace_busy(__func__, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
++#define	TRACE_BUSYSEARCH(__func__,s,ag,agb,l,tp)	\
++	xfs_alloc_trace_busy(__func__, s, mp, ag, agb, l, 0, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
+ #else
+ #define	TRACE_ALLOC(s,a)
+ #define	TRACE_FREE(s,a,b,x,f)
+ #define	TRACE_MODAGF(s,a,f)
+ #define	TRACE_BUSY(s,a,ag,agb,l,sl,tp)
+ #define	TRACE_UNBUSY(fname,s,ag,sl,tp)
+-#define	TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp)
++#define	TRACE_BUSYSEARCH(fname,s,ag,agb,l,tp)
+ #endif	/* XFS_ALLOC_TRACE */
+ 
+ /*
+@@ -93,7 +93,7 @@ STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *,
+  * Compute aligned version of the found extent.
+  * Takes alignment and min length into account.
+  */
+-STATIC int				/* success (>= minlen) */
++STATIC void
+ xfs_alloc_compute_aligned(
+ 	xfs_agblock_t	foundbno,	/* starting block in found extent */
+ 	xfs_extlen_t	foundlen,	/* length in found extent */
+@@ -116,7 +116,6 @@ xfs_alloc_compute_aligned(
+ 	}
+ 	*resbno = bno;
+ 	*reslen = len;
+-	return len >= minlen;
+ }
+ 
+ /*
+@@ -837,9 +836,9 @@ xfs_alloc_ag_vextent_near(
+ 			if ((error = xfs_alloc_get_rec(cnt_cur, &ltbno, &ltlen, &i)))
+ 				goto error0;
+ 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+-			if (!xfs_alloc_compute_aligned(ltbno, ltlen,
+-					args->alignment, args->minlen,
+-					&ltbnoa, &ltlena))
++			xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment,
++					args->minlen, &ltbnoa, &ltlena);
++			if (ltlena < args->minlen)
+ 				continue;
+ 			args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
+ 			xfs_alloc_fix_len(args);
+@@ -958,9 +957,9 @@ xfs_alloc_ag_vextent_near(
+ 			if ((error = xfs_alloc_get_rec(bno_cur_lt, &ltbno, &ltlen, &i)))
+ 				goto error0;
+ 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+-			if (xfs_alloc_compute_aligned(ltbno, ltlen,
+-					args->alignment, args->minlen,
+-					&ltbnoa, &ltlena))
++			xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment,
++					args->minlen, &ltbnoa, &ltlena);
++			if (ltlena >= args->minlen)
+ 				break;
+ 			if ((error = xfs_alloc_decrement(bno_cur_lt, 0, &i)))
+ 				goto error0;
+@@ -974,9 +973,9 @@ xfs_alloc_ag_vextent_near(
+ 			if ((error = xfs_alloc_get_rec(bno_cur_gt, &gtbno, &gtlen, &i)))
+ 				goto error0;
+ 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+-			if (xfs_alloc_compute_aligned(gtbno, gtlen,
+-					args->alignment, args->minlen,
+-					&gtbnoa, &gtlena))
++			xfs_alloc_compute_aligned(gtbno, gtlen, args->alignment,
++					args->minlen, &gtbnoa, &gtlena);
++			if (gtlena >= args->minlen)
+ 				break;
+ 			if ((error = xfs_alloc_increment(bno_cur_gt, 0, &i)))
+ 				goto error0;
+@@ -2562,9 +2561,10 @@ xfs_alloc_clear_busy(xfs_trans_t *tp,
+ 
+ 
+ /*
+- * returns non-zero if any of (agno,bno):len is in a busy list
++ * If we find the extent in the busy list, force the log out to get the
++ * extent out of the busy list so the caller can use it straight away.
+  */
+-STATIC int
++STATIC void
+ xfs_alloc_search_busy(xfs_trans_t *tp,
+ 		    xfs_agnumber_t agno,
+ 		    xfs_agblock_t bno,
+@@ -2572,7 +2572,6 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
+ {
+ 	xfs_mount_t		*mp;
+ 	xfs_perag_busy_t	*bsy;
+-	int			n;
+ 	xfs_agblock_t		uend, bend;
+ 	xfs_lsn_t		lsn;
+ 	int			cnt;
+@@ -2585,21 +2584,18 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
+ 	uend = bno + len - 1;
+ 
+ 	/* search pagb_list for this slot, skipping open slots */
+-	for (bsy = mp->m_perag[agno].pagb_list, n = 0;
+-	     cnt; bsy++, n++) {
++	for (bsy = mp->m_perag[agno].pagb_list; cnt; bsy++) {
+ 
+ 		/*
+ 		 * (start1,length1) within (start2, length2)
+ 		 */
+ 		if (bsy->busy_tp != NULL) {
+ 			bend = bsy->busy_start + bsy->busy_length - 1;
+-			if ((bno > bend) ||
+-			    (uend < bsy->busy_start)) {
++			if ((bno > bend) || (uend < bsy->busy_start)) {
+ 				cnt--;
+ 			} else {
+ 				TRACE_BUSYSEARCH("xfs_alloc_search_busy",
+-						 "found1", agno, bno, len, n,
+-						 tp);
++					 "found1", agno, bno, len, tp);
+ 				break;
+ 			}
+ 		}
+@@ -2610,15 +2606,12 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
+ 	 * transaction that freed the block
+ 	 */
+ 	if (cnt) {
+-		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "found", agno, bno, len, n, tp);
++		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "found", agno, bno, len, tp);
+ 		lsn = bsy->busy_tp->t_commit_lsn;
+ 		spin_unlock(&mp->m_perag[agno].pagb_lock);
+ 		xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
+ 	} else {
+-		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "not-found", agno, bno, len, n, tp);
+-		n = -1;
++		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "not-found", agno, bno, len, tp);
+ 		spin_unlock(&mp->m_perag[agno].pagb_lock);
+ 	}
+-
+-	return n;
+ }
+diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
+index e58f321..36d781e 100644
+--- a/fs/xfs/xfs_attr.c
++++ b/fs/xfs/xfs_attr.c
+@@ -2647,14 +2647,6 @@ attr_trusted_capable(
+ }
+ 
+ STATIC int
+-attr_secure_capable(
+-	bhv_vnode_t	*vp,
+-	cred_t		*cred)
+-{
+-	return -ENOSECURITY;
+-}
+-
+-STATIC int
+ attr_system_set(
+ 	bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
+ {
+@@ -2724,7 +2716,7 @@ struct attrnames attr_secure = {
+ 	.attr_get	= attr_generic_get,
+ 	.attr_set	= attr_generic_set,
+ 	.attr_remove	= attr_generic_remove,
+-	.attr_capable	= attr_secure_capable,
++	.attr_capable	= (attrcapable_t)fs_noerr,
+ };
+ 
+ struct attrnames attr_user = {
+diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
+index 96ba6aa..303d41e 100644
+--- a/fs/xfs/xfs_attr_leaf.c
++++ b/fs/xfs/xfs_attr_leaf.c
+@@ -166,7 +166,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
+ 
+ 	if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
+ 		if (bytes <= XFS_IFORK_ASIZE(dp))
+-			return mp->m_attroffset >> 3;
++			return dp->i_d.di_forkoff;
+ 		return 0;
+ 	}
+ 
+diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
+index 2def273..eb198c0 100644
+--- a/fs/xfs/xfs_bmap.c
++++ b/fs/xfs/xfs_bmap.c
+@@ -323,13 +323,13 @@ xfs_bmap_trace_pre_update(
+ 	int		whichfork);	/* data or attr fork */
+ 
+ #define	XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)	\
+-	xfs_bmap_trace_delete(__FUNCTION__,d,ip,i,c,w)
++	xfs_bmap_trace_delete(__func__,d,ip,i,c,w)
+ #define	XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)	\
+-	xfs_bmap_trace_insert(__FUNCTION__,d,ip,i,c,r1,r2,w)
++	xfs_bmap_trace_insert(__func__,d,ip,i,c,r1,r2,w)
+ #define	XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)	\
+-	xfs_bmap_trace_post_update(__FUNCTION__,d,ip,i,w)
++	xfs_bmap_trace_post_update(__func__,d,ip,i,w)
+ #define	XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)	\
+-	xfs_bmap_trace_pre_update(__FUNCTION__,d,ip,i,w)
++	xfs_bmap_trace_pre_update(__func__,d,ip,i,w)
+ #else
+ #define	XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)
+ #define	XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)
+@@ -2402,7 +2402,7 @@ xfs_bmap_extsize_align(
+ 
+ #define XFS_ALLOC_GAP_UNITS	4
+ 
+-STATIC int
++STATIC void
+ xfs_bmap_adjacent(
+ 	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
+ {
+@@ -2548,7 +2548,6 @@ xfs_bmap_adjacent(
+ 			ap->rval = gotbno;
+ 	}
+ #undef ISVALID
+-	return 0;
+ }
+ 
+ STATIC int
+@@ -4154,16 +4153,21 @@ xfs_bmap_compute_maxlevels(
+ 	 * number of leaf entries, is controlled by the type of di_nextents
+ 	 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
+ 	 * (a signed 16-bit number, xfs_aextnum_t).
++	 *
++	 * Note that we can no longer assume that if we are in ATTR1 that
++	 * the fork offset of all the inodes will be (m_attroffset >> 3)
++	 * because we could have mounted with ATTR2 and then mounted back
++	 * with ATTR1, keeping the di_forkoff's fixed but probably at
++	 * various positions. Therefore, for both ATTR1 and ATTR2
++	 * we have to assume the worst case scenario of a minimum size
++	 * available.
+ 	 */
+ 	if (whichfork == XFS_DATA_FORK) {
+ 		maxleafents = MAXEXTNUM;
+-		sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
+-			XFS_BMDR_SPACE_CALC(MINDBTPTRS) : mp->m_attroffset;
++		sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
+ 	} else {
+ 		maxleafents = MAXAEXTNUM;
+-		sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
+-			XFS_BMDR_SPACE_CALC(MINABTPTRS) :
+-			mp->m_sb.sb_inodesize - mp->m_attroffset;
++		sz = XFS_BMDR_SPACE_CALC(MINABTPTRS);
+ 	}
+ 	maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
+ 	minleafrecs = mp->m_bmap_dmnr[0];
+@@ -5772,7 +5776,6 @@ xfs_getbmap(
+ 	int			error;		/* return value */
+ 	__int64_t		fixlen;		/* length for -1 case */
+ 	int			i;		/* extent number */
+-	bhv_vnode_t		*vp;		/* corresponding vnode */
+ 	int			lock;		/* lock state */
+ 	xfs_bmbt_irec_t		*map;		/* buffer for user's data */
+ 	xfs_mount_t		*mp;		/* file system mount point */
+@@ -5789,7 +5792,6 @@ xfs_getbmap(
+ 	int			bmapi_flags;	/* flags for xfs_bmapi */
+ 	__int32_t		oflags;		/* getbmapx bmv_oflags field */
+ 
+-	vp = XFS_ITOV(ip);
+ 	mp = ip->i_mount;
+ 
+ 	whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
+@@ -5811,7 +5813,7 @@ xfs_getbmap(
+ 	if ((interface & BMV_IF_NO_DMAPI_READ) == 0 &&
+ 	    DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
+ 	    whichfork == XFS_DATA_FORK) {
+-		error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL);
++		error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL);
+ 		if (error)
+ 			return XFS_ERROR(error);
+ 	}
+@@ -5869,6 +5871,10 @@ xfs_getbmap(
+ 		/* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
+ 		error = xfs_flush_pages(ip, (xfs_off_t)0,
+ 					       -1, 0, FI_REMAPF);
++		if (error) {
++			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
++		return error;
++		}
+ 	}
+ 
+ 	ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);
+@@ -6162,10 +6168,10 @@ xfs_check_block(
+ 			}
+ 			if (*thispa == *pp) {
+ 				cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
+-					__FUNCTION__, j, i,
++					__func__, j, i,
+ 					(unsigned long long)be64_to_cpu(*thispa));
+ 				panic("%s: ptrs are equal in node\n",
+-					__FUNCTION__);
++					__func__);
+ 			}
+ 		}
+ 	}
+@@ -6192,7 +6198,7 @@ xfs_bmap_check_leaf_extents(
+ 	xfs_mount_t		*mp;	/* file system mount structure */
+ 	__be64			*pp;	/* pointer to block address */
+ 	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
+-	xfs_bmbt_rec_t		*lastp; /* pointer to previous extent */
++	xfs_bmbt_rec_t		last = {0, 0}; /* last extent in prev block */
+ 	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
+ 	int			bp_release = 0;
+ 
+@@ -6262,7 +6268,6 @@ xfs_bmap_check_leaf_extents(
+ 	/*
+ 	 * Loop over all leaf nodes checking that all extents are in the right order.
+ 	 */
+-	lastp = NULL;
+ 	for (;;) {
+ 		xfs_fsblock_t	nextbno;
+ 		xfs_extnum_t	num_recs;
+@@ -6283,18 +6288,16 @@ xfs_bmap_check_leaf_extents(
+ 		 */
+ 
+ 		ep = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
++		if (i) {
++			xfs_btree_check_rec(XFS_BTNUM_BMAP, &last, ep);
++		}
+ 		for (j = 1; j < num_recs; j++) {
+ 			nextp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, j + 1);
+-			if (lastp) {
+-				xfs_btree_check_rec(XFS_BTNUM_BMAP,
+-					(void *)lastp, (void *)ep);
+-			}
+-			xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep,
+-				(void *)(nextp));
+-			lastp = ep;
++			xfs_btree_check_rec(XFS_BTNUM_BMAP, ep, nextp);
+ 			ep = nextp;
+ 		}
+ 
++		last = *ep;
+ 		i += num_recs;
+ 		if (bp_release) {
+ 			bp_release = 0;
+@@ -6325,13 +6328,13 @@ xfs_bmap_check_leaf_extents(
+ 	return;
+ 
+ error0:
+-	cmn_err(CE_WARN, "%s: at error0", __FUNCTION__);
++	cmn_err(CE_WARN, "%s: at error0", __func__);
+ 	if (bp_release)
+ 		xfs_trans_brelse(NULL, bp);
+ error_norelse:
+ 	cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents",
+-		__FUNCTION__, i);
+-	panic("%s: CORRUPTED BTREE OR SOMETHING", __FUNCTION__);
++		__func__, i);
++	panic("%s: CORRUPTED BTREE OR SOMETHING", __func__);
+ 	return;
+ }
+ #endif
+diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
+index 87224b7..6ff70cd 100644
+--- a/fs/xfs/xfs_bmap.h
++++ b/fs/xfs/xfs_bmap.h
+@@ -151,7 +151,7 @@ xfs_bmap_trace_exlist(
+ 	xfs_extnum_t		cnt,		/* count of entries in list */
+ 	int			whichfork);	/* data or attr fork */
+ #define	XFS_BMAP_TRACE_EXLIST(ip,c,w)	\
+-	xfs_bmap_trace_exlist(__FUNCTION__,ip,c,w)
++	xfs_bmap_trace_exlist(__func__,ip,c,w)
+ #else
+ #define	XFS_BMAP_TRACE_EXLIST(ip,c,w)
+ #endif
+diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
+index bd18987..4f0e849 100644
+--- a/fs/xfs/xfs_bmap_btree.c
++++ b/fs/xfs/xfs_bmap_btree.c
+@@ -275,21 +275,21 @@ xfs_bmbt_trace_cursor(
+ }
+ 
+ #define	XFS_BMBT_TRACE_ARGBI(c,b,i)	\
+-	xfs_bmbt_trace_argbi(__FUNCTION__, c, b, i, __LINE__)
++	xfs_bmbt_trace_argbi(__func__, c, b, i, __LINE__)
+ #define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)	\
+-	xfs_bmbt_trace_argbii(__FUNCTION__, c, b, i, j, __LINE__)
++	xfs_bmbt_trace_argbii(__func__, c, b, i, j, __LINE__)
+ #define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)	\
+-	xfs_bmbt_trace_argfffi(__FUNCTION__, c, o, b, i, j, __LINE__)
++	xfs_bmbt_trace_argfffi(__func__, c, o, b, i, j, __LINE__)
+ #define	XFS_BMBT_TRACE_ARGI(c,i)	\
+-	xfs_bmbt_trace_argi(__FUNCTION__, c, i, __LINE__)
++	xfs_bmbt_trace_argi(__func__, c, i, __LINE__)
+ #define	XFS_BMBT_TRACE_ARGIFK(c,i,f,s)	\
+-	xfs_bmbt_trace_argifk(__FUNCTION__, c, i, f, s, __LINE__)
++	xfs_bmbt_trace_argifk(__func__, c, i, f, s, __LINE__)
+ #define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)	\
+-	xfs_bmbt_trace_argifr(__FUNCTION__, c, i, f, r, __LINE__)
++	xfs_bmbt_trace_argifr(__func__, c, i, f, r, __LINE__)
+ #define	XFS_BMBT_TRACE_ARGIK(c,i,k)	\
+-	xfs_bmbt_trace_argik(__FUNCTION__, c, i, k, __LINE__)
++	xfs_bmbt_trace_argik(__func__, c, i, k, __LINE__)
+ #define	XFS_BMBT_TRACE_CURSOR(c,s)	\
+-	xfs_bmbt_trace_cursor(__FUNCTION__, c, s, __LINE__)
++	xfs_bmbt_trace_cursor(__func__, c, s, __LINE__)
+ #else
+ #define	XFS_BMBT_TRACE_ARGBI(c,b,i)
+ #define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)
+@@ -2027,6 +2027,24 @@ xfs_bmbt_increment(
+ 
+ /*
+  * Insert the current record at the point referenced by cur.
++ *
++ * A multi-level split of the tree on insert will invalidate the original
++ * cursor. It appears, however, that some callers assume that the cursor is
++ * always valid. Hence if we do a multi-level split we need to revalidate the
++ * cursor.
++ *
++ * When a split occurs, we will see a new cursor returned. Use that as a
++ * trigger to determine if we need to revalidate the original cursor. If we get
++ * a split, then use the original irec to lookup up the path of the record we
++ * just inserted.
++ *
++ * Note that the fact that the btree root is in the inode means that we can
++ * have the level of the tree change without a "split" occurring at the root
++ * level. What happens is that the root is migrated to an allocated block and
++ * the inode root is pointed to it. This means a single split can change the
++ * level of the tree (level 2 -> level 3) and invalidate the old cursor. Hence
++ * the level change should be accounted as a split so as to correctly trigger a
++ * revalidation of the old cursor.
+  */
+ int					/* error */
+ xfs_bmbt_insert(
+@@ -2039,11 +2057,14 @@ xfs_bmbt_insert(
+ 	xfs_fsblock_t	nbno;
+ 	xfs_btree_cur_t	*ncur;
+ 	xfs_bmbt_rec_t	nrec;
++	xfs_bmbt_irec_t	oirec;		/* original irec */
+ 	xfs_btree_cur_t	*pcur;
++	int		splits = 0;
+ 
+ 	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
+ 	level = 0;
+ 	nbno = NULLFSBLOCK;
++	oirec = cur->bc_rec.b;
+ 	xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
+ 	ncur = NULL;
+ 	pcur = cur;
+@@ -2052,11 +2073,13 @@ xfs_bmbt_insert(
+ 				&i))) {
+ 			if (pcur != cur)
+ 				xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
+-			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
+-			return error;
++			goto error0;
+ 		}
+ 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+ 		if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
++			/* allocating a new root is effectively a split */
++			if (cur->bc_nlevels != pcur->bc_nlevels)
++				splits++;
+ 			cur->bc_nlevels = pcur->bc_nlevels;
+ 			cur->bc_private.b.allocated +=
+ 				pcur->bc_private.b.allocated;
+@@ -2070,10 +2093,21 @@ xfs_bmbt_insert(
+ 			xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
+ 		}
+ 		if (ncur) {
++			splits++;
+ 			pcur = ncur;
+ 			ncur = NULL;
+ 		}
+ 	} while (nbno != NULLFSBLOCK);
++
++	if (splits > 1) {
++		/* revalidate the old cursor as we had a multi-level split */
++		error = xfs_bmbt_lookup_eq(cur, oirec.br_startoff,
++				oirec.br_startblock, oirec.br_blockcount, &i);
++		if (error)
++			goto error0;
++		ASSERT(i == 1);
++	}
++
+ 	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
+ 	*stat = i;
+ 	return 0;
+diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
+index 63debd1..53a71c6 100644
+--- a/fs/xfs/xfs_buf_item.c
++++ b/fs/xfs/xfs_buf_item.c
+@@ -645,7 +645,12 @@ xfs_buf_item_push(
+ 	bp = bip->bli_buf;
+ 
+ 	if (XFS_BUF_ISDELAYWRITE(bp)) {
+-		xfs_bawrite(bip->bli_item.li_mountp, bp);
++		int	error;
++		error = xfs_bawrite(bip->bli_item.li_mountp, bp);
++		if (error)
++			xfs_fs_cmn_err(CE_WARN, bip->bli_item.li_mountp,
++			"xfs_buf_item_push: pushbuf error %d on bip %p, bp %p",
++					error, bip, bp);
+ 	} else {
+ 		xfs_buf_relse(bp);
+ 	}
+diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
+index e92e73f..7cb2652 100644
+--- a/fs/xfs/xfs_dir2.c
++++ b/fs/xfs/xfs_dir2.c
+@@ -44,6 +44,7 @@
+ #include "xfs_error.h"
+ #include "xfs_vnodeops.h"
+ 
++struct xfs_name xfs_name_dotdot = {"..", 2};
+ 
+ void
+ xfs_dir_mount(
+@@ -146,8 +147,7 @@ int
+ xfs_dir_createname(
+ 	xfs_trans_t		*tp,
+ 	xfs_inode_t		*dp,
+-	char			*name,
+-	int			namelen,
++	struct xfs_name		*name,
+ 	xfs_ino_t		inum,		/* new entry inode number */
+ 	xfs_fsblock_t		*first,		/* bmap's firstblock */
+ 	xfs_bmap_free_t		*flist,		/* bmap's freeblock list */
+@@ -162,9 +162,9 @@ xfs_dir_createname(
+ 		return rval;
+ 	XFS_STATS_INC(xs_dir_create);
+ 
+-	args.name = name;
+-	args.namelen = namelen;
+-	args.hashval = xfs_da_hashname(name, namelen);
++	args.name = name->name;
++	args.namelen = name->len;
++	args.hashval = xfs_da_hashname(name->name, name->len);
+ 	args.inumber = inum;
+ 	args.dp = dp;
+ 	args.firstblock = first;
+@@ -197,8 +197,7 @@ int
+ xfs_dir_lookup(
+ 	xfs_trans_t	*tp,
+ 	xfs_inode_t	*dp,
+-	char		*name,
+-	int		namelen,
++	struct xfs_name	*name,
+ 	xfs_ino_t	*inum)		/* out: inode number */
+ {
+ 	xfs_da_args_t	args;
+@@ -207,18 +206,14 @@ xfs_dir_lookup(
+ 
+ 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+ 	XFS_STATS_INC(xs_dir_lookup);
++	memset(&args, 0, sizeof(xfs_da_args_t));
+ 
+-	args.name = name;
+-	args.namelen = namelen;
+-	args.hashval = xfs_da_hashname(name, namelen);
+-	args.inumber = 0;
++	args.name = name->name;
++	args.namelen = name->len;
++	args.hashval = xfs_da_hashname(name->name, name->len);
+ 	args.dp = dp;
+-	args.firstblock = NULL;
+-	args.flist = NULL;
+-	args.total = 0;
+ 	args.whichfork = XFS_DATA_FORK;
+ 	args.trans = tp;
+-	args.justcheck = args.addname = 0;
+ 	args.oknoent = 1;
+ 
+ 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
+@@ -247,8 +242,7 @@ int
+ xfs_dir_removename(
+ 	xfs_trans_t	*tp,
+ 	xfs_inode_t	*dp,
+-	char		*name,
+-	int		namelen,
++	struct xfs_name	*name,
+ 	xfs_ino_t	ino,
+ 	xfs_fsblock_t	*first,		/* bmap's firstblock */
+ 	xfs_bmap_free_t	*flist,		/* bmap's freeblock list */
+@@ -261,9 +255,9 @@ xfs_dir_removename(
+ 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+ 	XFS_STATS_INC(xs_dir_remove);
+ 
+-	args.name = name;
+-	args.namelen = namelen;
+-	args.hashval = xfs_da_hashname(name, namelen);
++	args.name = name->name;
++	args.namelen = name->len;
++	args.hashval = xfs_da_hashname(name->name, name->len);
+ 	args.inumber = ino;
+ 	args.dp = dp;
+ 	args.firstblock = first;
+@@ -329,8 +323,7 @@ int
+ xfs_dir_replace(
+ 	xfs_trans_t	*tp,
+ 	xfs_inode_t	*dp,
+-	char		*name,		/* name of entry to replace */
+-	int		namelen,
++	struct xfs_name	*name,		/* name of entry to replace */
+ 	xfs_ino_t	inum,		/* new inode number */
+ 	xfs_fsblock_t	*first,		/* bmap's firstblock */
+ 	xfs_bmap_free_t	*flist,		/* bmap's freeblock list */
+@@ -345,9 +338,9 @@ xfs_dir_replace(
+ 	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
+ 		return rval;
+ 
+-	args.name = name;
+-	args.namelen = namelen;
+-	args.hashval = xfs_da_hashname(name, namelen);
++	args.name = name->name;
++	args.namelen = name->len;
++	args.hashval = xfs_da_hashname(name->name, name->len);
+ 	args.inumber = inum;
+ 	args.dp = dp;
+ 	args.firstblock = first;
+@@ -374,28 +367,29 @@ xfs_dir_replace(
+ 
+ /*
+  * See if this entry can be added to the directory without allocating space.
++ * First checks that the caller couldn't reserve enough space (resblks = 0).
+  */
+ int
+ xfs_dir_canenter(
+ 	xfs_trans_t	*tp,
+ 	xfs_inode_t	*dp,
+-	char		*name,		/* name of entry to add */
+-	int		namelen)
++	struct xfs_name	*name,		/* name of entry to add */
++	uint		resblks)
+ {
+ 	xfs_da_args_t	args;
+ 	int		rval;
+ 	int		v;		/* type-checking value */
+ 
++	if (resblks)
++		return 0;
++
+ 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
++	memset(&args, 0, sizeof(xfs_da_args_t));
+ 
+-	args.name = name;
+-	args.namelen = namelen;
+-	args.hashval = xfs_da_hashname(name, namelen);
+-	args.inumber = 0;
++	args.name = name->name;
++	args.namelen = name->len;
++	args.hashval = xfs_da_hashname(name->name, name->len);
+ 	args.dp = dp;
+-	args.firstblock = NULL;
+-	args.flist = NULL;
+-	args.total = 0;
+ 	args.whichfork = XFS_DATA_FORK;
+ 	args.trans = tp;
+ 	args.justcheck = args.addname = args.oknoent = 1;
+diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
+index b265197..6392f93 100644
+--- a/fs/xfs/xfs_dir2.h
++++ b/fs/xfs/xfs_dir2.h
+@@ -59,6 +59,8 @@ typedef	__uint32_t	xfs_dir2_db_t;
+  */
+ typedef	xfs_off_t	xfs_dir2_off_t;
+ 
++extern struct xfs_name	xfs_name_dotdot;
++
+ /*
+  * Generic directory interface routines
+  */
+@@ -68,21 +70,21 @@ extern int xfs_dir_isempty(struct xfs_inode *dp);
+ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
+ 				struct xfs_inode *pdp);
+ extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
+-				char *name, int namelen, xfs_ino_t inum,
++				struct xfs_name *name, xfs_ino_t inum,
+ 				xfs_fsblock_t *first,
+ 				struct xfs_bmap_free *flist, xfs_extlen_t tot);
+ extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
+-				char *name, int namelen, xfs_ino_t *inum);
++				struct xfs_name *name, xfs_ino_t *inum);
+ extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
+-				char *name, int namelen, xfs_ino_t ino,
++				struct xfs_name *name, xfs_ino_t ino,
+ 				xfs_fsblock_t *first,
+ 				struct xfs_bmap_free *flist, xfs_extlen_t tot);
+ extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
+-				char *name, int namelen, xfs_ino_t inum,
++				struct xfs_name *name, xfs_ino_t inum,
+ 				xfs_fsblock_t *first,
+ 				struct xfs_bmap_free *flist, xfs_extlen_t tot);
+ extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
+-				char *name, int namelen);
++				struct xfs_name *name, uint resblks);
+ extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
+ 
+ /*
+diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
+index eb03eab..3f3785b 100644
+--- a/fs/xfs/xfs_filestream.c
++++ b/fs/xfs/xfs_filestream.c
+@@ -73,7 +73,7 @@ xfs_filestreams_trace(
+ #define TRACE4(mp,t,a0,a1,a2,a3)	TRACE6(mp,t,a0,a1,a2,a3,0,0)
+ #define TRACE5(mp,t,a0,a1,a2,a3,a4)	TRACE6(mp,t,a0,a1,a2,a3,a4,0)
+ #define TRACE6(mp,t,a0,a1,a2,a3,a4,a5) \
+-	xfs_filestreams_trace(mp, t, __FUNCTION__, __LINE__, \
++	xfs_filestreams_trace(mp, t, __func__, __LINE__, \
+ 				(__psunsigned_t)a0, (__psunsigned_t)a1, \
+ 				(__psunsigned_t)a2, (__psunsigned_t)a3, \
+ 				(__psunsigned_t)a4, (__psunsigned_t)a5)
+diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
+index 5a146cb..a64dfbd 100644
+--- a/fs/xfs/xfs_ialloc.c
++++ b/fs/xfs/xfs_ialloc.c
+@@ -107,6 +107,16 @@ xfs_ialloc_log_di(
+ /*
+  * Allocation group level functions.
+  */
++static inline int
++xfs_ialloc_cluster_alignment(
++	xfs_alloc_arg_t	*args)
++{
++	if (xfs_sb_version_hasalign(&args->mp->m_sb) &&
++	    args->mp->m_sb.sb_inoalignmt >=
++	     XFS_B_TO_FSBT(args->mp, XFS_INODE_CLUSTER_SIZE(args->mp)))
++		return args->mp->m_sb.sb_inoalignmt;
++	return 1;
++}
+ 
+ /*
+  * Allocate new inodes in the allocation group specified by agbp.
+@@ -167,10 +177,24 @@ xfs_ialloc_ag_alloc(
+ 		args.mod = args.total = args.wasdel = args.isfl =
+ 			args.userdata = args.minalignslop = 0;
+ 		args.prod = 1;
+-		args.alignment = 1;
++
+ 		/*
+-		 * Allow space for the inode btree to split.
++		 * We need to take into account alignment here to ensure that
++		 * we don't modify the free list if we fail to have an exact
++		 * block. If we don't have an exact match, and every oher
++		 * attempt allocation attempt fails, we'll end up cancelling
++		 * a dirty transaction and shutting down.
++		 *
++		 * For an exact allocation, alignment must be 1,
++		 * however we need to take cluster alignment into account when
++		 * fixing up the freelist. Use the minalignslop field to
++		 * indicate that extra blocks might be required for alignment,
++		 * but not to use them in the actual exact allocation.
+ 		 */
++		args.alignment = 1;
++		args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1;
++
++		/* Allow space for the inode btree to split. */
+ 		args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
+ 		if ((error = xfs_alloc_vextent(&args)))
+ 			return error;
+@@ -191,13 +215,8 @@ xfs_ialloc_ag_alloc(
+ 			ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
+ 			args.alignment = args.mp->m_dalign;
+ 			isaligned = 1;
+-		} else if (xfs_sb_version_hasalign(&args.mp->m_sb) &&
+-			   args.mp->m_sb.sb_inoalignmt >=
+-			   XFS_B_TO_FSBT(args.mp,
+-			  	XFS_INODE_CLUSTER_SIZE(args.mp)))
+-				args.alignment = args.mp->m_sb.sb_inoalignmt;
+-		else
+-			args.alignment = 1;
++		} else
++			args.alignment = xfs_ialloc_cluster_alignment(&args);
+ 		/*
+ 		 * Need to figure out where to allocate the inode blocks.
+ 		 * Ideally they should be spaced out through the a.g.
+@@ -230,12 +249,7 @@ xfs_ialloc_ag_alloc(
+ 		args.agbno = be32_to_cpu(agi->agi_root);
+ 		args.fsbno = XFS_AGB_TO_FSB(args.mp,
+ 				be32_to_cpu(agi->agi_seqno), args.agbno);
+-		if (xfs_sb_version_hasalign(&args.mp->m_sb) &&
+-			args.mp->m_sb.sb_inoalignmt >=
+-			XFS_B_TO_FSBT(args.mp, XFS_INODE_CLUSTER_SIZE(args.mp)))
+-				args.alignment = args.mp->m_sb.sb_inoalignmt;
+-		else
+-			args.alignment = 1;
++		args.alignment = xfs_ialloc_cluster_alignment(&args);
+ 		if ((error = xfs_alloc_vextent(&args)))
+ 			return error;
+ 	}
+diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
+index 8e09b71..e657c51 100644
+--- a/fs/xfs/xfs_iget.c
++++ b/fs/xfs/xfs_iget.c
+@@ -78,7 +78,6 @@ xfs_iget_core(
+ 	xfs_inode_t	*ip;
+ 	xfs_inode_t	*iq;
+ 	int		error;
+-	xfs_icluster_t	*icl, *new_icl = NULL;
+ 	unsigned long	first_index, mask;
+ 	xfs_perag_t	*pag;
+ 	xfs_agino_t	agino;
+@@ -229,11 +228,9 @@ finish_inode:
+ 	}
+ 
+ 	/*
+-	 * This is a bit messy - we preallocate everything we _might_
+-	 * need before we pick up the ici lock. That way we don't have to
+-	 * juggle locks and go all the way back to the start.
++	 * Preload the radix tree so we can insert safely under the
++	 * write spinlock.
+ 	 */
+-	new_icl = kmem_zone_alloc(xfs_icluster_zone, KM_SLEEP);
+ 	if (radix_tree_preload(GFP_KERNEL)) {
+ 		xfs_idestroy(ip);
+ 		delay(1);
+@@ -242,17 +239,6 @@ finish_inode:
+ 	mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
+ 	first_index = agino & mask;
+ 	write_lock(&pag->pag_ici_lock);
+-
+-	/*
+-	 * Find the cluster if it exists
+-	 */
+-	icl = NULL;
+-	if (radix_tree_gang_lookup(&pag->pag_ici_root, (void**)&iq,
+-							first_index, 1)) {
+-		if ((XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) == first_index)
+-			icl = iq->i_cluster;
+-	}
+-
+ 	/*
+ 	 * insert the new inode
+ 	 */
+@@ -267,30 +253,13 @@ finish_inode:
+ 	}
+ 
+ 	/*
+-	 * These values _must_ be set before releasing ihlock!
++	 * These values _must_ be set before releasing the radix tree lock!
+ 	 */
+ 	ip->i_udquot = ip->i_gdquot = NULL;
+ 	xfs_iflags_set(ip, XFS_INEW);
+ 
+-	ASSERT(ip->i_cluster == NULL);
+-
+-	if (!icl) {
+-		spin_lock_init(&new_icl->icl_lock);
+-		INIT_HLIST_HEAD(&new_icl->icl_inodes);
+-		icl = new_icl;
+-		new_icl = NULL;
+-	} else {
+-		ASSERT(!hlist_empty(&icl->icl_inodes));
+-	}
+-	spin_lock(&icl->icl_lock);
+-	hlist_add_head(&ip->i_cnode, &icl->icl_inodes);
+-	ip->i_cluster = icl;
+-	spin_unlock(&icl->icl_lock);
+-
+ 	write_unlock(&pag->pag_ici_lock);
+ 	radix_tree_preload_end();
+-	if (new_icl)
+-		kmem_zone_free(xfs_icluster_zone, new_icl);
+ 
+ 	/*
+ 	 * Link ip to its mount and thread it on the mount's inode list.
+@@ -529,18 +498,6 @@ xfs_iextract(
+ 	xfs_put_perag(mp, pag);
+ 
+ 	/*
+-	 * Remove from cluster list
+-	 */
+-	mp = ip->i_mount;
+-	spin_lock(&ip->i_cluster->icl_lock);
+-	hlist_del(&ip->i_cnode);
+-	spin_unlock(&ip->i_cluster->icl_lock);
+-
+-	/* was last inode in cluster? */
+-	if (hlist_empty(&ip->i_cluster->icl_inodes))
+-		kmem_zone_free(xfs_icluster_zone, ip->i_cluster);
+-
+-	/*
+ 	 * Remove from mount's inode list.
+ 	 */
+ 	XFS_MOUNT_ILOCK(mp);
+diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
+index f43a6e0..ca12acb 100644
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -55,7 +55,6 @@
+ 
+ kmem_zone_t *xfs_ifork_zone;
+ kmem_zone_t *xfs_inode_zone;
+-kmem_zone_t *xfs_icluster_zone;
+ 
+ /*
+  * Used in xfs_itruncate().  This is the maximum number of extents
+@@ -126,6 +125,90 @@ xfs_inobp_check(
+ #endif
+ 
+ /*
++ * Find the buffer associated with the given inode map
++ * We do basic validation checks on the buffer once it has been
++ * retrieved from disk.
++ */
++STATIC int
++xfs_imap_to_bp(
++	xfs_mount_t	*mp,
++	xfs_trans_t	*tp,
++	xfs_imap_t	*imap,
++	xfs_buf_t	**bpp,
++	uint		buf_flags,
++	uint		imap_flags)
++{
++	int		error;
++	int		i;
++	int		ni;
++	xfs_buf_t	*bp;
++
++	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno,
++				   (int)imap->im_len, buf_flags, &bp);
++	if (error) {
++		if (error != EAGAIN) {
++			cmn_err(CE_WARN,
++				"xfs_imap_to_bp: xfs_trans_read_buf()returned "
++				"an error %d on %s.  Returning error.",
++				error, mp->m_fsname);
++		} else {
++			ASSERT(buf_flags & XFS_BUF_TRYLOCK);
++		}
++		return error;
++	}
++
++	/*
++	 * Validate the magic number and version of every inode in the buffer
++	 * (if DEBUG kernel) or the first inode in the buffer, otherwise.
++	 */
++#ifdef DEBUG
++	ni = BBTOB(imap->im_len) >> mp->m_sb.sb_inodelog;
++#else	/* usual case */
++	ni = 1;
++#endif
++
++	for (i = 0; i < ni; i++) {
++		int		di_ok;
++		xfs_dinode_t	*dip;
++
++		dip = (xfs_dinode_t *)xfs_buf_offset(bp,
++					(i << mp->m_sb.sb_inodelog));
++		di_ok = be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
++			    XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
++		if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
++						XFS_ERRTAG_ITOBP_INOTOBP,
++						XFS_RANDOM_ITOBP_INOTOBP))) {
++			if (imap_flags & XFS_IMAP_BULKSTAT) {
++				xfs_trans_brelse(tp, bp);
++				return XFS_ERROR(EINVAL);
++			}
++			XFS_CORRUPTION_ERROR("xfs_imap_to_bp",
++						XFS_ERRLEVEL_HIGH, mp, dip);
++#ifdef DEBUG
++			cmn_err(CE_PANIC,
++					"Device %s - bad inode magic/vsn "
++					"daddr %lld #%d (magic=%x)",
++				XFS_BUFTARG_NAME(mp->m_ddev_targp),
++				(unsigned long long)imap->im_blkno, i,
++				be16_to_cpu(dip->di_core.di_magic));
++#endif
++			xfs_trans_brelse(tp, bp);
++			return XFS_ERROR(EFSCORRUPTED);
++		}
++	}
++
++	xfs_inobp_check(mp, bp);
++
++	/*
++	 * Mark the buffer as an inode buffer now that it looks good
++	 */
++	XFS_BUF_SET_VTYPE(bp, B_FS_INO);
++
++	*bpp = bp;
++	return 0;
++}
++
++/*
+  * This routine is called to map an inode number within a file
+  * system to the buffer containing the on-disk version of the
+  * inode.  It returns a pointer to the buffer containing the
+@@ -147,72 +230,19 @@ xfs_inotobp(
+ 	xfs_buf_t	**bpp,
+ 	int		*offset)
+ {
+-	int		di_ok;
+ 	xfs_imap_t	imap;
+ 	xfs_buf_t	*bp;
+ 	int		error;
+-	xfs_dinode_t	*dip;
+ 
+-	/*
+-	 * Call the space management code to find the location of the
+-	 * inode on disk.
+-	 */
+ 	imap.im_blkno = 0;
+ 	error = xfs_imap(mp, tp, ino, &imap, XFS_IMAP_LOOKUP);
+-	if (error != 0) {
+-		cmn_err(CE_WARN,
+-	"xfs_inotobp: xfs_imap()  returned an "
+-	"error %d on %s.  Returning error.", error, mp->m_fsname);
++	if (error)
+ 		return error;
+-	}
+ 
+-	/*
+-	 * If the inode number maps to a block outside the bounds of the
+-	 * file system then return NULL rather than calling read_buf
+-	 * and panicing when we get an error from the driver.
+-	 */
+-	if ((imap.im_blkno + imap.im_len) >
+-	    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
+-		cmn_err(CE_WARN,
+-	"xfs_inotobp: inode number (%llu + %d) maps to a block outside the bounds "
+-	"of the file system %s.  Returning EINVAL.",
+-			(unsigned long long)imap.im_blkno,
+-			imap.im_len, mp->m_fsname);
+-		return XFS_ERROR(EINVAL);
+-	}
+-
+-	/*
+-	 * Read in the buffer.  If tp is NULL, xfs_trans_read_buf() will
+-	 * default to just a read_buf() call.
+-	 */
+-	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno,
+-				   (int)imap.im_len, XFS_BUF_LOCK, &bp);
+-
+-	if (error) {
+-		cmn_err(CE_WARN,
+-	"xfs_inotobp: xfs_trans_read_buf()  returned an "
+-	"error %d on %s.  Returning error.", error, mp->m_fsname);
++	error = xfs_imap_to_bp(mp, tp, &imap, &bp, XFS_BUF_LOCK, 0);
++	if (error)
+ 		return error;
+-	}
+-	dip = (xfs_dinode_t *)xfs_buf_offset(bp, 0);
+-	di_ok =
+-		be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
+-		XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
+-	if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
+-			XFS_RANDOM_ITOBP_INOTOBP))) {
+-		XFS_CORRUPTION_ERROR("xfs_inotobp", XFS_ERRLEVEL_LOW, mp, dip);
+-		xfs_trans_brelse(tp, bp);
+-		cmn_err(CE_WARN,
+-	"xfs_inotobp: XFS_TEST_ERROR()  returned an "
+-	"error on %s.  Returning EFSCORRUPTED.",  mp->m_fsname);
+-		return XFS_ERROR(EFSCORRUPTED);
+-	}
+ 
+-	xfs_inobp_check(mp, bp);
+-
+-	/*
+-	 * Set *dipp to point to the on-disk inode in the buffer.
+-	 */
+ 	*dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
+ 	*bpp = bp;
+ 	*offset = imap.im_boffset;
+@@ -248,46 +278,21 @@ xfs_itobp(
+ 	xfs_dinode_t	**dipp,
+ 	xfs_buf_t	**bpp,
+ 	xfs_daddr_t	bno,
+-	uint		imap_flags)
++	uint		imap_flags,
++	uint		buf_flags)
+ {
+ 	xfs_imap_t	imap;
+ 	xfs_buf_t	*bp;
+ 	int		error;
+-	int		i;
+-	int		ni;
+ 
+ 	if (ip->i_blkno == (xfs_daddr_t)0) {
+-		/*
+-		 * Call the space management code to find the location of the
+-		 * inode on disk.
+-		 */
+ 		imap.im_blkno = bno;
+-		if ((error = xfs_imap(mp, tp, ip->i_ino, &imap,
+-					XFS_IMAP_LOOKUP | imap_flags)))
++		error = xfs_imap(mp, tp, ip->i_ino, &imap,
++					XFS_IMAP_LOOKUP | imap_flags);
++		if (error)
+ 			return error;
+ 
+ 		/*
+-		 * If the inode number maps to a block outside the bounds
+-		 * of the file system then return NULL rather than calling
+-		 * read_buf and panicing when we get an error from the
+-		 * driver.
+-		 */
+-		if ((imap.im_blkno + imap.im_len) >
+-		    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
+-#ifdef DEBUG
+-			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: "
+-					"(imap.im_blkno (0x%llx) "
+-					"+ imap.im_len (0x%llx)) > "
+-					" XFS_FSB_TO_BB(mp, "
+-					"mp->m_sb.sb_dblocks) (0x%llx)",
+-					(unsigned long long) imap.im_blkno,
+-					(unsigned long long) imap.im_len,
+-					XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
+-#endif /* DEBUG */
+-			return XFS_ERROR(EINVAL);
+-		}
+-
+-		/*
+ 		 * Fill in the fields in the inode that will be used to
+ 		 * map the inode to its buffer from now on.
+ 		 */
+@@ -305,76 +310,17 @@ xfs_itobp(
+ 	}
+ 	ASSERT(bno == 0 || bno == imap.im_blkno);
+ 
+-	/*
+-	 * Read in the buffer.  If tp is NULL, xfs_trans_read_buf() will
+-	 * default to just a read_buf() call.
+-	 */
+-	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno,
+-				   (int)imap.im_len, XFS_BUF_LOCK, &bp);
+-	if (error) {
+-#ifdef DEBUG
+-		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: "
+-				"xfs_trans_read_buf() returned error %d, "
+-				"imap.im_blkno 0x%llx, imap.im_len 0x%llx",
+-				error, (unsigned long long) imap.im_blkno,
+-				(unsigned long long) imap.im_len);
+-#endif /* DEBUG */
++	error = xfs_imap_to_bp(mp, tp, &imap, &bp, buf_flags, imap_flags);
++	if (error)
+ 		return error;
+-	}
+-
+-	/*
+-	 * Validate the magic number and version of every inode in the buffer
+-	 * (if DEBUG kernel) or the first inode in the buffer, otherwise.
+-	 * No validation is done here in userspace (xfs_repair).
+-	 */
+-#if !defined(__KERNEL__)
+-	ni = 0;
+-#elif defined(DEBUG)
+-	ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog;
+-#else	/* usual case */
+-	ni = 1;
+-#endif
+-
+-	for (i = 0; i < ni; i++) {
+-		int		di_ok;
+-		xfs_dinode_t	*dip;
+ 
+-		dip = (xfs_dinode_t *)xfs_buf_offset(bp,
+-					(i << mp->m_sb.sb_inodelog));
+-		di_ok = be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
+-			    XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
+-		if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
+-						XFS_ERRTAG_ITOBP_INOTOBP,
+-						XFS_RANDOM_ITOBP_INOTOBP))) {
+-			if (imap_flags & XFS_IMAP_BULKSTAT) {
+-				xfs_trans_brelse(tp, bp);
+-				return XFS_ERROR(EINVAL);
+-			}
+-#ifdef DEBUG
+-			cmn_err(CE_ALERT,
+-					"Device %s - bad inode magic/vsn "
+-					"daddr %lld #%d (magic=%x)",
+-				XFS_BUFTARG_NAME(mp->m_ddev_targp),
+-				(unsigned long long)imap.im_blkno, i,
+-				be16_to_cpu(dip->di_core.di_magic));
+-#endif
+-			XFS_CORRUPTION_ERROR("xfs_itobp", XFS_ERRLEVEL_HIGH,
+-					     mp, dip);
+-			xfs_trans_brelse(tp, bp);
+-			return XFS_ERROR(EFSCORRUPTED);
+-		}
++	if (!bp) {
++		ASSERT(buf_flags & XFS_BUF_TRYLOCK);
++		ASSERT(tp == NULL);
++		*bpp = NULL;
++		return EAGAIN;
+ 	}
+ 
+-	xfs_inobp_check(mp, bp);
+-
+-	/*
+-	 * Mark the buffer as an inode buffer now that it looks good
+-	 */
+-	XFS_BUF_SET_VTYPE(bp, B_FS_INO);
+-
+-	/*
+-	 * Set *dipp to point to the on-disk inode in the buffer.
+-	 */
+ 	*dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
+ 	*bpp = bp;
+ 	return 0;
+@@ -878,7 +824,7 @@ xfs_iread(
+ 	 * return NULL as well.  Set i_blkno to 0 so that xfs_itobp() will
+ 	 * know that this is a new incore inode.
+ 	 */
+-	error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, imap_flags);
++	error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, imap_flags, XFS_BUF_LOCK);
+ 	if (error) {
+ 		kmem_zone_free(xfs_inode_zone, ip);
+ 		return error;
+@@ -1518,51 +1464,50 @@ xfs_itruncate_start(
+ }
+ 
+ /*
+- * Shrink the file to the given new_size.  The new
+- * size must be smaller than the current size.
+- * This will free up the underlying blocks
+- * in the removed range after a call to xfs_itruncate_start()
+- * or xfs_atruncate_start().
++ * Shrink the file to the given new_size.  The new size must be smaller than
++ * the current size.  This will free up the underlying blocks in the removed
++ * range after a call to xfs_itruncate_start() or xfs_atruncate_start().
+  *
+- * The transaction passed to this routine must have made
+- * a permanent log reservation of at least XFS_ITRUNCATE_LOG_RES.
+- * This routine may commit the given transaction and
+- * start new ones, so make sure everything involved in
+- * the transaction is tidy before calling here.
+- * Some transaction will be returned to the caller to be
+- * committed.  The incoming transaction must already include
+- * the inode, and both inode locks must be held exclusively.
+- * The inode must also be "held" within the transaction.  On
+- * return the inode will be "held" within the returned transaction.
+- * This routine does NOT require any disk space to be reserved
+- * for it within the transaction.
++ * The transaction passed to this routine must have made a permanent log
++ * reservation of at least XFS_ITRUNCATE_LOG_RES.  This routine may commit the
++ * given transaction and start new ones, so make sure everything involved in
++ * the transaction is tidy before calling here.  Some transaction will be
++ * returned to the caller to be committed.  The incoming transaction must
++ * already include the inode, and both inode locks must be held exclusively.
++ * The inode must also be "held" within the transaction.  On return the inode
++ * will be "held" within the returned transaction.  This routine does NOT
++ * require any disk space to be reserved for it within the transaction.
+  *
+- * The fork parameter must be either xfs_attr_fork or xfs_data_fork,
+- * and it indicates the fork which is to be truncated.  For the
+- * attribute fork we only support truncation to size 0.
++ * The fork parameter must be either xfs_attr_fork or xfs_data_fork, and it
++ * indicates the fork which is to be truncated.  For the attribute fork we only
++ * support truncation to size 0.
+  *
+- * We use the sync parameter to indicate whether or not the first
+- * transaction we perform might have to be synchronous.  For the attr fork,
+- * it needs to be so if the unlink of the inode is not yet known to be
+- * permanent in the log.  This keeps us from freeing and reusing the
+- * blocks of the attribute fork before the unlink of the inode becomes
+- * permanent.
++ * We use the sync parameter to indicate whether or not the first transaction
++ * we perform might have to be synchronous.  For the attr fork, it needs to be
++ * so if the unlink of the inode is not yet known to be permanent in the log.
++ * This keeps us from freeing and reusing the blocks of the attribute fork
++ * before the unlink of the inode becomes permanent.
+  *
+- * For the data fork, we normally have to run synchronously if we're
+- * being called out of the inactive path or we're being called
+- * out of the create path where we're truncating an existing file.
+- * Either way, the truncate needs to be sync so blocks don't reappear
+- * in the file with altered data in case of a crash.  wsync filesystems
+- * can run the first case async because anything that shrinks the inode
+- * has to run sync so by the time we're called here from inactive, the
+- * inode size is permanently set to 0.
++ * For the data fork, we normally have to run synchronously if we're being
++ * called out of the inactive path or we're being called out of the create path
++ * where we're truncating an existing file.  Either way, the truncate needs to
++ * be sync so blocks don't reappear in the file with altered data in case of a
++ * crash.  wsync filesystems can run the first case async because anything that
++ * shrinks the inode has to run sync so by the time we're called here from
++ * inactive, the inode size is permanently set to 0.
+  *
+- * Calls from the truncate path always need to be sync unless we're
+- * in a wsync filesystem and the file has already been unlinked.
++ * Calls from the truncate path always need to be sync unless we're in a wsync
++ * filesystem and the file has already been unlinked.
+  *
+- * The caller is responsible for correctly setting the sync parameter.
+- * It gets too hard for us to guess here which path we're being called
+- * out of just based on inode state.
++ * The caller is responsible for correctly setting the sync parameter.  It gets
++ * too hard for us to guess here which path we're being called out of just
++ * based on inode state.
++ *
++ * If we get an error, we must return with the inode locked and linked into the
++ * current transaction. This keeps things simple for the higher level code,
++ * because it always knows that the inode is locked and held in the transaction
++ * that returns to it whether errors occur or not.  We don't mark the inode
++ * dirty on error so that transactions can be easily aborted if possible.
+  */
+ int
+ xfs_itruncate_finish(
+@@ -1741,65 +1686,51 @@ xfs_itruncate_finish(
+ 		 */
+ 		error = xfs_bmap_finish(tp, &free_list, &committed);
+ 		ntp = *tp;
++		if (committed) {
++			/* link the inode into the next xact in the chain */
++			xfs_trans_ijoin(ntp, ip,
++					XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
++			xfs_trans_ihold(ntp, ip);
++		}
++
+ 		if (error) {
+ 			/*
+-			 * If the bmap finish call encounters an error,
+-			 * return to the caller where the transaction
+-			 * can be properly aborted.  We just need to
+-			 * make sure we're not holding any resources
+-			 * that we were not when we came in.
++			 * If the bmap finish call encounters an error, return
++			 * to the caller where the transaction can be properly
++			 * aborted.  We just need to make sure we're not
++			 * holding any resources that we were not when we came
++			 * in.
+ 			 *
+-			 * Aborting from this point might lose some
+-			 * blocks in the file system, but oh well.
++			 * Aborting from this point might lose some blocks in
++			 * the file system, but oh well.
+ 			 */
+ 			xfs_bmap_cancel(&free_list);
+-			if (committed) {
+-				/*
+-				 * If the passed in transaction committed
+-				 * in xfs_bmap_finish(), then we want to
+-				 * add the inode to this one before returning.
+-				 * This keeps things simple for the higher
+-				 * level code, because it always knows that
+-				 * the inode is locked and held in the
+-				 * transaction that returns to it whether
+-				 * errors occur or not.  We don't mark the
+-				 * inode dirty so that this transaction can
+-				 * be easily aborted if possible.
+-				 */
+-				xfs_trans_ijoin(ntp, ip,
+-					XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+-				xfs_trans_ihold(ntp, ip);
+-			}
+ 			return error;
+ 		}
+ 
+ 		if (committed) {
+ 			/*
+-			 * The first xact was committed,
+-			 * so add the inode to the new one.
+-			 * Mark it dirty so it will be logged
+-			 * and moved forward in the log as
+-			 * part of every commit.
++			 * Mark the inode dirty so it will be logged and
++			 * moved forward in the log as part of every commit.
+ 			 */
+-			xfs_trans_ijoin(ntp, ip,
+-					XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+-			xfs_trans_ihold(ntp, ip);
+ 			xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
+ 		}
++
+ 		ntp = xfs_trans_dup(ntp);
+-		(void) xfs_trans_commit(*tp, 0);
++		error = xfs_trans_commit(*tp, 0);
+ 		*tp = ntp;
+-		error = xfs_trans_reserve(ntp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
+-					  XFS_TRANS_PERM_LOG_RES,
+-					  XFS_ITRUNCATE_LOG_COUNT);
+-		/*
+-		 * Add the inode being truncated to the next chained
+-		 * transaction.
+-		 */
++
++		/* link the inode into the next transaction in the chain */
+ 		xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+ 		xfs_trans_ihold(ntp, ip);
++
++		if (!error)
++			error = xfs_trans_reserve(ntp, 0,
++					XFS_ITRUNCATE_LOG_RES(mp), 0,
++					XFS_TRANS_PERM_LOG_RES,
++					XFS_ITRUNCATE_LOG_COUNT);
+ 		if (error)
+-			return (error);
++			return error;
+ 	}
+ 	/*
+ 	 * Only update the size in the case of the data fork, but
+@@ -1967,7 +1898,7 @@ xfs_iunlink(
+ 		 * Here we put the head pointer into our next pointer,
+ 		 * and then we fall through to point the head at us.
+ 		 */
+-		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
++		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
+ 		if (error)
+ 			return error;
+ 
+@@ -2075,7 +2006,7 @@ xfs_iunlink_remove(
+ 		 * of dealing with the buffer when there is no need to
+ 		 * change it.
+ 		 */
+-		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
++		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
+ 		if (error) {
+ 			cmn_err(CE_WARN,
+ 				"xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
+@@ -2137,7 +2068,7 @@ xfs_iunlink_remove(
+ 		 * Now last_ibp points to the buffer previous to us on
+ 		 * the unlinked list.  Pull us from the list.
+ 		 */
+-		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
++		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
+ 		if (error) {
+ 			cmn_err(CE_WARN,
+ 				"xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
+@@ -2172,13 +2103,6 @@ xfs_iunlink_remove(
+ 	return 0;
+ }
+ 
+-STATIC_INLINE int xfs_inode_clean(xfs_inode_t *ip)
+-{
+-	return (((ip->i_itemp == NULL) ||
+-		!(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
+-		(ip->i_update_core == 0));
+-}
+-
+ STATIC void
+ xfs_ifree_cluster(
+ 	xfs_inode_t	*free_ip,
+@@ -2400,7 +2324,7 @@ xfs_ifree(
+ 
+ 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+ 
+-	error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0, 0);
++	error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
+ 	if (error)
+ 		return error;
+ 
+@@ -2678,14 +2602,31 @@ xfs_imap(
+ 	fsbno = imap->im_blkno ?
+ 		XFS_DADDR_TO_FSB(mp, imap->im_blkno) : NULLFSBLOCK;
+ 	error = xfs_dilocate(mp, tp, ino, &fsbno, &len, &off, flags);
+-	if (error != 0) {
++	if (error)
+ 		return error;
+-	}
++
+ 	imap->im_blkno = XFS_FSB_TO_DADDR(mp, fsbno);
+ 	imap->im_len = XFS_FSB_TO_BB(mp, len);
+ 	imap->im_agblkno = XFS_FSB_TO_AGBNO(mp, fsbno);
+ 	imap->im_ioffset = (ushort)off;
+ 	imap->im_boffset = (ushort)(off << mp->m_sb.sb_inodelog);
++
++	/*
++	 * If the inode number maps to a block outside the bounds
++	 * of the file system then return NULL rather than calling
++	 * read_buf and panicing when we get an error from the
++	 * driver.
++	 */
++	if ((imap->im_blkno + imap->im_len) >
++	    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
++		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
++			"(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > "
++			" XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)",
++			(unsigned long long) imap->im_blkno,
++			(unsigned long long) imap->im_len,
++			XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
++		return EINVAL;
++	}
+ 	return 0;
+ }
+ 
+@@ -2826,38 +2767,41 @@ xfs_iunpin(
+ }
+ 
+ /*
+- * This is called to wait for the given inode to be unpinned.
+- * It will sleep until this happens.  The caller must have the
+- * inode locked in at least shared mode so that the buffer cannot
+- * be subsequently pinned once someone is waiting for it to be
+- * unpinned.
++ * This is called to unpin an inode. It can be directed to wait or to return
++ * immediately without waiting for the inode to be unpinned.  The caller must
++ * have the inode locked in at least shared mode so that the buffer cannot be
++ * subsequently pinned once someone is waiting for it to be unpinned.
+  */
+ STATIC void
+-xfs_iunpin_wait(
+-	xfs_inode_t	*ip)
++__xfs_iunpin_wait(
++	xfs_inode_t	*ip,
++	int		wait)
+ {
+-	xfs_inode_log_item_t	*iip;
+-	xfs_lsn_t	lsn;
++	xfs_inode_log_item_t	*iip = ip->i_itemp;
+ 
+ 	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE | MR_ACCESS));
+-
+-	if (atomic_read(&ip->i_pincount) == 0) {
++	if (atomic_read(&ip->i_pincount) == 0)
+ 		return;
+-	}
+ 
+-	iip = ip->i_itemp;
+-	if (iip && iip->ili_last_lsn) {
+-		lsn = iip->ili_last_lsn;
+-	} else {
+-		lsn = (xfs_lsn_t)0;
+-	}
++	/* Give the log a push to start the unpinning I/O */
++	xfs_log_force(ip->i_mount, (iip && iip->ili_last_lsn) ?
++				iip->ili_last_lsn : 0, XFS_LOG_FORCE);
++	if (wait)
++		wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0));
++}
+ 
+-	/*
+-	 * Give the log a push so we don't wait here too long.
+-	 */
+-	xfs_log_force(ip->i_mount, lsn, XFS_LOG_FORCE);
++static inline void
++xfs_iunpin_wait(
++	xfs_inode_t	*ip)
++{
++	__xfs_iunpin_wait(ip, 1);
++}
+ 
+-	wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0));
++static inline void
++xfs_iunpin_nowait(
++	xfs_inode_t	*ip)
++{
++	__xfs_iunpin_wait(ip, 0);
+ }
+ 
+ 
+@@ -2932,7 +2876,7 @@ xfs_iextents_copy(
+  * format indicates the current state of the fork.
+  */
+ /*ARGSUSED*/
+-STATIC int
++STATIC void
+ xfs_iflush_fork(
+ 	xfs_inode_t		*ip,
+ 	xfs_dinode_t		*dip,
+@@ -2953,16 +2897,16 @@ xfs_iflush_fork(
+ 	static const short	extflag[2] =
+ 		{ XFS_ILOG_DEXT, XFS_ILOG_AEXT };
+ 
+-	if (iip == NULL)
+-		return 0;
++	if (!iip)
++		return;
+ 	ifp = XFS_IFORK_PTR(ip, whichfork);
+ 	/*
+ 	 * This can happen if we gave up in iformat in an error path,
+ 	 * for the attribute fork.
+ 	 */
+-	if (ifp == NULL) {
++	if (!ifp) {
+ 		ASSERT(whichfork == XFS_ATTR_FORK);
+-		return 0;
++		return;
+ 	}
+ 	cp = XFS_DFORK_PTR(dip, whichfork);
+ 	mp = ip->i_mount;
+@@ -3023,8 +2967,145 @@ xfs_iflush_fork(
+ 		ASSERT(0);
+ 		break;
+ 	}
++}
++
++STATIC int
++xfs_iflush_cluster(
++	xfs_inode_t	*ip,
++	xfs_buf_t	*bp)
++{
++	xfs_mount_t		*mp = ip->i_mount;
++	xfs_perag_t		*pag = xfs_get_perag(mp, ip->i_ino);
++	unsigned long		first_index, mask;
++	int			ilist_size;
++	xfs_inode_t		**ilist;
++	xfs_inode_t		*iq;
++	int			nr_found;
++	int			clcount = 0;
++	int			bufwasdelwri;
++	int			i;
++
++	ASSERT(pag->pagi_inodeok);
++	ASSERT(pag->pag_ici_init);
++
++	ilist_size = XFS_INODE_CLUSTER_SIZE(mp) * sizeof(xfs_inode_t *);
++	ilist = kmem_alloc(ilist_size, KM_MAYFAIL);
++	if (!ilist)
++		return 0;
++
++	mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
++	first_index = XFS_INO_TO_AGINO(mp, ip->i_ino) & mask;
++	read_lock(&pag->pag_ici_lock);
++	/* really need a gang lookup range call here */
++	nr_found = radix_tree_gang_lookup(&pag->pag_ici_root, (void**)ilist,
++					first_index,
++					XFS_INODE_CLUSTER_SIZE(mp));
++	if (nr_found == 0)
++		goto out_free;
++
++	for (i = 0; i < nr_found; i++) {
++		iq = ilist[i];
++		if (iq == ip)
++			continue;
++		/* if the inode lies outside this cluster, we're done. */
++		if ((XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) != first_index)
++			break;
++		/*
++		 * Do an un-protected check to see if the inode is dirty and
++		 * is a candidate for flushing.  These checks will be repeated
++		 * later after the appropriate locks are acquired.
++		 */
++		if (xfs_inode_clean(iq) && xfs_ipincount(iq) == 0)
++			continue;
++
++		/*
++		 * Try to get locks.  If any are unavailable or it is pinned,
++		 * then this inode cannot be flushed and is skipped.
++		 */
++
++		if (!xfs_ilock_nowait(iq, XFS_ILOCK_SHARED))
++			continue;
++		if (!xfs_iflock_nowait(iq)) {
++			xfs_iunlock(iq, XFS_ILOCK_SHARED);
++			continue;
++		}
++		if (xfs_ipincount(iq)) {
++			xfs_ifunlock(iq);
++			xfs_iunlock(iq, XFS_ILOCK_SHARED);
++			continue;
++		}
++
++		/*
++		 * arriving here means that this inode can be flushed.  First
++		 * re-check that it's dirty before flushing.
++		 */
++		if (!xfs_inode_clean(iq)) {
++			int	error;
++			error = xfs_iflush_int(iq, bp);
++			if (error) {
++				xfs_iunlock(iq, XFS_ILOCK_SHARED);
++				goto cluster_corrupt_out;
++			}
++			clcount++;
++		} else {
++			xfs_ifunlock(iq);
++		}
++		xfs_iunlock(iq, XFS_ILOCK_SHARED);
++	}
++
++	if (clcount) {
++		XFS_STATS_INC(xs_icluster_flushcnt);
++		XFS_STATS_ADD(xs_icluster_flushinode, clcount);
++	}
+ 
++out_free:
++	read_unlock(&pag->pag_ici_lock);
++	kmem_free(ilist, ilist_size);
+ 	return 0;
++
++
++cluster_corrupt_out:
++	/*
++	 * Corruption detected in the clustering loop.  Invalidate the
++	 * inode buffer and shut down the filesystem.
++	 */
++	read_unlock(&pag->pag_ici_lock);
++	/*
++	 * Clean up the buffer.  If it was B_DELWRI, just release it --
++	 * brelse can handle it with no problems.  If not, shut down the
++	 * filesystem before releasing the buffer.
++	 */
++	bufwasdelwri = XFS_BUF_ISDELAYWRITE(bp);
++	if (bufwasdelwri)
++		xfs_buf_relse(bp);
++
++	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
++
++	if (!bufwasdelwri) {
++		/*
++		 * Just like incore_relse: if we have b_iodone functions,
++		 * mark the buffer as an error and call them.  Otherwise
++		 * mark it as stale and brelse.
++		 */
++		if (XFS_BUF_IODONE_FUNC(bp)) {
++			XFS_BUF_CLR_BDSTRAT_FUNC(bp);
++			XFS_BUF_UNDONE(bp);
++			XFS_BUF_STALE(bp);
++			XFS_BUF_SHUT(bp);
++			XFS_BUF_ERROR(bp,EIO);
++			xfs_biodone(bp);
++		} else {
++			XFS_BUF_STALE(bp);
++			xfs_buf_relse(bp);
++		}
++	}
++
++	/*
++	 * Unlocks the flush lock
++	 */
++	xfs_iflush_abort(iq);
++	kmem_free(ilist, ilist_size);
++	return XFS_ERROR(EFSCORRUPTED);
+ }
+ 
+ /*
+@@ -3046,11 +3127,7 @@ xfs_iflush(
+ 	xfs_dinode_t		*dip;
+ 	xfs_mount_t		*mp;
+ 	int			error;
+-	/* REFERENCED */
+-	xfs_inode_t		*iq;
+-	int			clcount;	/* count of inodes clustered */
+-	int			bufwasdelwri;
+-	struct hlist_node	*entry;
++	int			noblock = (flags == XFS_IFLUSH_ASYNC_NOBLOCK);
+ 	enum { INT_DELWRI = (1 << 0), INT_ASYNC = (1 << 1) };
+ 
+ 	XFS_STATS_INC(xs_iflush_count);
+@@ -3067,8 +3144,7 @@ xfs_iflush(
+ 	 * If the inode isn't dirty, then just release the inode
+ 	 * flush lock and do nothing.
+ 	 */
+-	if ((ip->i_update_core == 0) &&
+-	    ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL))) {
++	if (xfs_inode_clean(ip)) {
+ 		ASSERT((iip != NULL) ?
+ 			 !(iip->ili_item.li_flags & XFS_LI_IN_AIL) : 1);
+ 		xfs_ifunlock(ip);
+@@ -3076,11 +3152,21 @@ xfs_iflush(
+ 	}
+ 
+ 	/*
+-	 * We can't flush the inode until it is unpinned, so
+-	 * wait for it.  We know noone new can pin it, because
+-	 * we are holding the inode lock shared and you need
+-	 * to hold it exclusively to pin the inode.
++	 * We can't flush the inode until it is unpinned, so wait for it if we
++	 * are allowed to block.  We know noone new can pin it, because we are
++	 * holding the inode lock shared and you need to hold it exclusively to
++	 * pin the inode.
++	 *
++	 * If we are not allowed to block, force the log out asynchronously so
++	 * that when we come back the inode will be unpinned. If other inodes
++	 * in the same cluster are dirty, they will probably write the inode
++	 * out for us if they occur after the log force completes.
+ 	 */
++	if (noblock && xfs_ipincount(ip)) {
++		xfs_iunpin_nowait(ip);
++		xfs_ifunlock(ip);
++		return EAGAIN;
++	}
+ 	xfs_iunpin_wait(ip);
+ 
+ 	/*
+@@ -3097,15 +3183,6 @@ xfs_iflush(
+ 	}
+ 
+ 	/*
+-	 * Get the buffer containing the on-disk inode.
+-	 */
+-	error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0);
+-	if (error) {
+-		xfs_ifunlock(ip);
+-		return error;
+-	}
+-
+-	/*
+ 	 * Decide how buffer will be flushed out.  This is done before
+ 	 * the call to xfs_iflush_int because this field is zeroed by it.
+ 	 */
+@@ -3121,6 +3198,7 @@ xfs_iflush(
+ 		case XFS_IFLUSH_DELWRI_ELSE_SYNC:
+ 			flags = 0;
+ 			break;
++		case XFS_IFLUSH_ASYNC_NOBLOCK:
+ 		case XFS_IFLUSH_ASYNC:
+ 		case XFS_IFLUSH_DELWRI_ELSE_ASYNC:
+ 			flags = INT_ASYNC;
+@@ -3140,6 +3218,7 @@ xfs_iflush(
+ 		case XFS_IFLUSH_DELWRI:
+ 			flags = INT_DELWRI;
+ 			break;
++		case XFS_IFLUSH_ASYNC_NOBLOCK:
+ 		case XFS_IFLUSH_ASYNC:
+ 			flags = INT_ASYNC;
+ 			break;
+@@ -3154,94 +3233,41 @@ xfs_iflush(
+ 	}
+ 
+ 	/*
+-	 * First flush out the inode that xfs_iflush was called with.
++	 * Get the buffer containing the on-disk inode.
+ 	 */
+-	error = xfs_iflush_int(ip, bp);
+-	if (error) {
+-		goto corrupt_out;
++	error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0,
++				noblock ? XFS_BUF_TRYLOCK : XFS_BUF_LOCK);
++	if (error || !bp) {
++		xfs_ifunlock(ip);
++		return error;
+ 	}
+ 
+ 	/*
+-	 * inode clustering:
+-	 * see if other inodes can be gathered into this write
++	 * First flush out the inode that xfs_iflush was called with.
+ 	 */
+-	spin_lock(&ip->i_cluster->icl_lock);
+-	ip->i_cluster->icl_buf = bp;
+-
+-	clcount = 0;
+-	hlist_for_each_entry(iq, entry, &ip->i_cluster->icl_inodes, i_cnode) {
+-		if (iq == ip)
+-			continue;
+-
+-		/*
+-		 * Do an un-protected check to see if the inode is dirty and
+-		 * is a candidate for flushing.  These checks will be repeated
+-		 * later after the appropriate locks are acquired.
+-		 */
+-		iip = iq->i_itemp;
+-		if ((iq->i_update_core == 0) &&
+-		    ((iip == NULL) ||
+-		     !(iip->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
+-		      xfs_ipincount(iq) == 0) {
+-			continue;
+-		}
+-
+-		/*
+-		 * Try to get locks.  If any are unavailable,
+-		 * then this inode cannot be flushed and is skipped.
+-		 */
+-
+-		/* get inode locks (just i_lock) */
+-		if (xfs_ilock_nowait(iq, XFS_ILOCK_SHARED)) {
+-			/* get inode flush lock */
+-			if (xfs_iflock_nowait(iq)) {
+-				/* check if pinned */
+-				if (xfs_ipincount(iq) == 0) {
+-					/* arriving here means that
+-					 * this inode can be flushed.
+-					 * first re-check that it's
+-					 * dirty
+-					 */
+-					iip = iq->i_itemp;
+-					if ((iq->i_update_core != 0)||
+-					    ((iip != NULL) &&
+-					     (iip->ili_format.ilf_fields & XFS_ILOG_ALL))) {
+-						clcount++;
+-						error = xfs_iflush_int(iq, bp);
+-						if (error) {
+-							xfs_iunlock(iq,
+-								    XFS_ILOCK_SHARED);
+-							goto cluster_corrupt_out;
+-						}
+-					} else {
+-						xfs_ifunlock(iq);
+-					}
+-				} else {
+-					xfs_ifunlock(iq);
+-				}
+-			}
+-			xfs_iunlock(iq, XFS_ILOCK_SHARED);
+-		}
+-	}
+-	spin_unlock(&ip->i_cluster->icl_lock);
+-
+-	if (clcount) {
+-		XFS_STATS_INC(xs_icluster_flushcnt);
+-		XFS_STATS_ADD(xs_icluster_flushinode, clcount);
+-	}
++	error = xfs_iflush_int(ip, bp);
++	if (error)
++		goto corrupt_out;
+ 
+ 	/*
+-	 * If the buffer is pinned then push on the log so we won't
++	 * If the buffer is pinned then push on the log now so we won't
+ 	 * get stuck waiting in the write for too long.
+ 	 */
+-	if (XFS_BUF_ISPINNED(bp)){
++	if (XFS_BUF_ISPINNED(bp))
+ 		xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
+-	}
++
++	/*
++	 * inode clustering:
++	 * see if other inodes can be gathered into this write
++	 */
++	error = xfs_iflush_cluster(ip, bp);
++	if (error)
++		goto cluster_corrupt_out;
+ 
+ 	if (flags & INT_DELWRI) {
+ 		xfs_bdwrite(mp, bp);
+ 	} else if (flags & INT_ASYNC) {
+-		xfs_bawrite(mp, bp);
++		error = xfs_bawrite(mp, bp);
+ 	} else {
+ 		error = xfs_bwrite(mp, bp);
+ 	}
+@@ -3250,52 +3276,11 @@ xfs_iflush(
+ corrupt_out:
+ 	xfs_buf_relse(bp);
+ 	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+-	xfs_iflush_abort(ip);
+-	/*
+-	 * Unlocks the flush lock
+-	 */
+-	return XFS_ERROR(EFSCORRUPTED);
+-
+ cluster_corrupt_out:
+-	/* Corruption detected in the clustering loop.  Invalidate the
+-	 * inode buffer and shut down the filesystem.
+-	 */
+-	spin_unlock(&ip->i_cluster->icl_lock);
+-
+-	/*
+-	 * Clean up the buffer.  If it was B_DELWRI, just release it --
+-	 * brelse can handle it with no problems.  If not, shut down the
+-	 * filesystem before releasing the buffer.
+-	 */
+-	if ((bufwasdelwri= XFS_BUF_ISDELAYWRITE(bp))) {
+-		xfs_buf_relse(bp);
+-	}
+-
+-	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+-
+-	if(!bufwasdelwri)  {
+-		/*
+-		 * Just like incore_relse: if we have b_iodone functions,
+-		 * mark the buffer as an error and call them.  Otherwise
+-		 * mark it as stale and brelse.
+-		 */
+-		if (XFS_BUF_IODONE_FUNC(bp)) {
+-			XFS_BUF_CLR_BDSTRAT_FUNC(bp);
+-			XFS_BUF_UNDONE(bp);
+-			XFS_BUF_STALE(bp);
+-			XFS_BUF_SHUT(bp);
+-			XFS_BUF_ERROR(bp,EIO);
+-			xfs_biodone(bp);
+-		} else {
+-			XFS_BUF_STALE(bp);
+-			xfs_buf_relse(bp);
+-		}
+-	}
+-
+-	xfs_iflush_abort(iq);
+ 	/*
+ 	 * Unlocks the flush lock
+ 	 */
++	xfs_iflush_abort(ip);
+ 	return XFS_ERROR(EFSCORRUPTED);
+ }
+ 
+@@ -3325,8 +3310,7 @@ xfs_iflush_int(
+ 	 * If the inode isn't dirty, then just release the inode
+ 	 * flush lock and do nothing.
+ 	 */
+-	if ((ip->i_update_core == 0) &&
+-	    ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL))) {
++	if (xfs_inode_clean(ip)) {
+ 		xfs_ifunlock(ip);
+ 		return 0;
+ 	}
+@@ -3459,16 +3443,9 @@ xfs_iflush_int(
+ 		}
+ 	}
+ 
+-	if (xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp) == EFSCORRUPTED) {
+-		goto corrupt_out;
+-	}
+-
+-	if (XFS_IFORK_Q(ip)) {
+-		/*
+-		 * The only error from xfs_iflush_fork is on the data fork.
+-		 */
+-		(void) xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
+-	}
++	xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp);
++	if (XFS_IFORK_Q(ip))
++		xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
+ 	xfs_inobp_check(mp, bp);
+ 
+ 	/*
+diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
+index bfcd72c..93c3769 100644
+--- a/fs/xfs/xfs_inode.h
++++ b/fs/xfs/xfs_inode.h
+@@ -133,19 +133,6 @@ typedef struct dm_attrs_s {
+ } dm_attrs_t;
+ 
+ /*
+- * This is the xfs inode cluster structure.  This structure is used by
+- * xfs_iflush to find inodes that share a cluster and can be flushed to disk at
+- * the same time.
+- */
+-typedef struct xfs_icluster {
+-	struct hlist_head	icl_inodes;	/* list of inodes on cluster */
+-	xfs_daddr_t		icl_blkno;	/* starting block number of
+-						 * the cluster */
+-	struct xfs_buf		*icl_buf;	/* the inode buffer */
+-	spinlock_t		icl_lock;	/* inode list lock */
+-} xfs_icluster_t;
+-
+-/*
+  * This is the xfs in-core inode structure.
+  * Most of the on-disk inode is embedded in the i_d field.
+  *
+@@ -240,10 +227,6 @@ typedef struct xfs_inode {
+ 	atomic_t		i_pincount;	/* inode pin count */
+ 	wait_queue_head_t	i_ipin_wait;	/* inode pinning wait queue */
+ 	spinlock_t		i_flags_lock;	/* inode i_flags lock */
+-#ifdef HAVE_REFCACHE
+-	struct xfs_inode	**i_refcache;	/* ptr to entry in ref cache */
+-	struct xfs_inode	*i_release;	/* inode to unref */
+-#endif
+ 	/* Miscellaneous state. */
+ 	unsigned short		i_flags;	/* see defined flags below */
+ 	unsigned char		i_update_core;	/* timestamps/size is dirty */
+@@ -252,8 +235,6 @@ typedef struct xfs_inode {
+ 	unsigned int		i_delayed_blks;	/* count of delay alloc blks */
+ 
+ 	xfs_icdinode_t		i_d;		/* most of ondisk inode */
+-	xfs_icluster_t		*i_cluster;	/* cluster list header */
+-	struct hlist_node	i_cnode;	/* cluster link node */
+ 
+ 	xfs_fsize_t		i_size;		/* in-memory size */
+ 	xfs_fsize_t		i_new_size;	/* size when write completes */
+@@ -461,6 +442,7 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)
+ #define	XFS_IFLUSH_SYNC			3
+ #define	XFS_IFLUSH_ASYNC		4
+ #define	XFS_IFLUSH_DELWRI		5
++#define	XFS_IFLUSH_ASYNC_NOBLOCK	6
+ 
+ /*
+  * Flags for xfs_itruncate_start().
+@@ -515,7 +497,7 @@ int		xfs_finish_reclaim_all(struct xfs_mount *, int);
+  */
+ int		xfs_itobp(struct xfs_mount *, struct xfs_trans *,
+ 			  xfs_inode_t *, struct xfs_dinode **, struct xfs_buf **,
+-			  xfs_daddr_t, uint);
++			  xfs_daddr_t, uint, uint);
+ int		xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
+ 			  xfs_inode_t **, xfs_daddr_t, uint);
+ int		xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
+@@ -597,7 +579,6 @@ void		xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
+ #define	xfs_inobp_check(mp, bp)
+ #endif /* DEBUG */
+ 
+-extern struct kmem_zone	*xfs_icluster_zone;
+ extern struct kmem_zone	*xfs_ifork_zone;
+ extern struct kmem_zone	*xfs_inode_zone;
+ extern struct kmem_zone	*xfs_ili_zone;
+diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
+index 2c775b4..93b5db4 100644
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -40,6 +40,7 @@
+ #include "xfs_btree.h"
+ #include "xfs_ialloc.h"
+ #include "xfs_rw.h"
++#include "xfs_error.h"
+ 
+ 
+ kmem_zone_t	*xfs_ili_zone;		/* inode log item zone */
+@@ -813,7 +814,12 @@ xfs_inode_item_pushbuf(
+ 					      XFS_LOG_FORCE);
+ 			}
+ 			if (dopush) {
+-				xfs_bawrite(mp, bp);
++				int	error;
++				error = xfs_bawrite(mp, bp);
++				if (error)
++					xfs_fs_cmn_err(CE_WARN, mp,
++		"xfs_inode_item_pushbuf: pushbuf error %d on iip %p, bp %p",
++							error, iip, bp);
+ 			} else {
+ 				xfs_buf_relse(bp);
+ 			}
+diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
+index bfe92ea..4051307 100644
+--- a/fs/xfs/xfs_inode_item.h
++++ b/fs/xfs/xfs_inode_item.h
+@@ -168,6 +168,14 @@ static inline int xfs_ilog_fext(int w)
+ 	return (w == XFS_DATA_FORK ? XFS_ILOG_DEXT : XFS_ILOG_AEXT);
+ }
+ 
++static inline int xfs_inode_clean(xfs_inode_t *ip)
++{
++	return (!ip->i_itemp ||
++		!(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
++	       !ip->i_update_core;
++}
++
++
+ #ifdef __KERNEL__
+ 
+ extern void xfs_inode_item_init(struct xfs_inode *, struct xfs_mount *);
+diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
+index fde37f8..fb3cf11 100644
+--- a/fs/xfs/xfs_iomap.c
++++ b/fs/xfs/xfs_iomap.c
+@@ -802,8 +802,11 @@ xfs_iomap_write_allocate(
+ 			 */
+ 			nimaps = 1;
+ 			end_fsb = XFS_B_TO_FSB(mp, ip->i_size);
+-			xfs_bmap_last_offset(NULL, ip, &last_block,
+-				XFS_DATA_FORK);
++			error = xfs_bmap_last_offset(NULL, ip, &last_block,
++							XFS_DATA_FORK);
++			if (error)
++				goto trans_cancel;
++
+ 			last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
+ 			if ((map_start_fsb + count_fsb) > last_block) {
+ 				count_fsb = last_block - map_start_fsb;
+diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
+index f615e04..eb85bde 100644
+--- a/fs/xfs/xfs_itable.c
++++ b/fs/xfs/xfs_itable.c
+@@ -129,7 +129,7 @@ xfs_bulkstat_one_iget(
+ 	return error;
+ }
+ 
+-STATIC int
++STATIC void
+ xfs_bulkstat_one_dinode(
+ 	xfs_mount_t	*mp,		/* mount point for filesystem */
+ 	xfs_ino_t	ino,		/* inode number to get data for */
+@@ -198,8 +198,6 @@ xfs_bulkstat_one_dinode(
+ 		buf->bs_blocks = be64_to_cpu(dic->di_nblocks);
+ 		break;
+ 	}
+-
+-	return 0;
+ }
+ 
+ STATIC int
+@@ -614,7 +612,8 @@ xfs_bulkstat(
+ 							xfs_buf_relse(bp);
+ 						error = xfs_itobp(mp, NULL, ip,
+ 								&dip, &bp, bno,
+-								XFS_IMAP_BULKSTAT);
++								XFS_IMAP_BULKSTAT,
++								XFS_BUF_LOCK);
+ 						if (!error)
+ 							clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
+ 						kmem_zone_free(xfs_inode_zone, ip);
+diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
+index 31f2b04..afaee30 100644
+--- a/fs/xfs/xfs_log.c
++++ b/fs/xfs/xfs_log.c
+@@ -41,6 +41,7 @@
+ #include "xfs_inode.h"
+ #include "xfs_rw.h"
+ 
++kmem_zone_t	*xfs_log_ticket_zone;
+ 
+ #define xlog_write_adv_cnt(ptr, len, off, bytes) \
+ 	{ (ptr) += (bytes); \
+@@ -73,8 +74,6 @@ STATIC int  xlog_state_get_iclog_space(xlog_t		*log,
+ 				       xlog_ticket_t	*ticket,
+ 				       int		*continued_write,
+ 				       int		*logoffsetp);
+-STATIC void xlog_state_put_ticket(xlog_t	*log,
+-				  xlog_ticket_t *tic);
+ STATIC int  xlog_state_release_iclog(xlog_t		*log,
+ 				     xlog_in_core_t	*iclog);
+ STATIC void xlog_state_switch_iclogs(xlog_t		*log,
+@@ -101,7 +100,6 @@ STATIC void xlog_ungrant_log_space(xlog_t	 *log,
+ 
+ 
+ /* local ticket functions */
+-STATIC void		xlog_state_ticket_alloc(xlog_t *log);
+ STATIC xlog_ticket_t	*xlog_ticket_get(xlog_t *log,
+ 					 int	unit_bytes,
+ 					 int	count,
+@@ -330,7 +328,7 @@ xfs_log_done(xfs_mount_t	*mp,
+ 		 */
+ 		xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
+ 		xlog_ungrant_log_space(log, ticket);
+-		xlog_state_put_ticket(log, ticket);
++		xlog_ticket_put(log, ticket);
+ 	} else {
+ 		xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)");
+ 		xlog_regrant_reserve_log_space(log, ticket);
+@@ -384,7 +382,27 @@ _xfs_log_force(
+ 		return xlog_state_sync_all(log, flags, log_flushed);
+ 	else
+ 		return xlog_state_sync(log, lsn, flags, log_flushed);
+-}	/* xfs_log_force */
++}	/* _xfs_log_force */
++
++/*
++ * Wrapper for _xfs_log_force(), to be used when caller doesn't care
++ * about errors or whether the log was flushed or not. This is the normal
++ * interface to use when trying to unpin items or move the log forward.
++ */
++void
++xfs_log_force(
++	xfs_mount_t	*mp,
++	xfs_lsn_t	lsn,
++	uint		flags)
++{
++	int	error;
++	error = _xfs_log_force(mp, lsn, flags, NULL);
++	if (error) {
++		xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
++			"error %d returned.", error);
++	}
++}
++
+ 
+ /*
+  * Attaches a new iclog I/O completion callback routine during
+@@ -397,12 +415,10 @@ xfs_log_notify(xfs_mount_t	  *mp,		/* mount of partition */
+ 	       void		  *iclog_hndl,	/* iclog to hang callback off */
+ 	       xfs_log_callback_t *cb)
+ {
+-	xlog_t *log = mp->m_log;
+ 	xlog_in_core_t	  *iclog = (xlog_in_core_t *)iclog_hndl;
+ 	int	abortflg;
+ 
+-	cb->cb_next = NULL;
+-	spin_lock(&log->l_icloglock);
++	spin_lock(&iclog->ic_callback_lock);
+ 	abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
+ 	if (!abortflg) {
+ 		ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) ||
+@@ -411,7 +427,7 @@ xfs_log_notify(xfs_mount_t	  *mp,		/* mount of partition */
+ 		*(iclog->ic_callback_tail) = cb;
+ 		iclog->ic_callback_tail = &(cb->cb_next);
+ 	}
+-	spin_unlock(&log->l_icloglock);
++	spin_unlock(&iclog->ic_callback_lock);
+ 	return abortflg;
+ }	/* xfs_log_notify */
+ 
+@@ -471,6 +487,8 @@ xfs_log_reserve(xfs_mount_t	 *mp,
+ 		/* may sleep if need to allocate more tickets */
+ 		internal_ticket = xlog_ticket_get(log, unit_bytes, cnt,
+ 						  client, flags);
++		if (!internal_ticket)
++			return XFS_ERROR(ENOMEM);
+ 		internal_ticket->t_trans_type = t_type;
+ 		*ticket = internal_ticket;
+ 		xlog_trace_loggrant(log, internal_ticket, 
+@@ -636,7 +654,8 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ 	if (mp->m_flags & XFS_MOUNT_RDONLY)
+ 		return 0;
+ 
+-	xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
++	error = _xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC, NULL);
++	ASSERT(error || !(XLOG_FORCED_SHUTDOWN(log)));
+ 
+ #ifdef DEBUG
+ 	first_iclog = iclog = log->l_iclog;
+@@ -675,10 +694,10 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ 
+ 		spin_lock(&log->l_icloglock);
+ 		iclog = log->l_iclog;
+-		iclog->ic_refcnt++;
++		atomic_inc(&iclog->ic_refcnt);
+ 		spin_unlock(&log->l_icloglock);
+ 		xlog_state_want_sync(log, iclog);
+-		(void) xlog_state_release_iclog(log, iclog);
++		error = xlog_state_release_iclog(log, iclog);
+ 
+ 		spin_lock(&log->l_icloglock);
+ 		if (!(iclog->ic_state == XLOG_STATE_ACTIVE ||
+@@ -695,7 +714,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ 		if (tic) {
+ 			xlog_trace_loggrant(log, tic, "unmount rec");
+ 			xlog_ungrant_log_space(log, tic);
+-			xlog_state_put_ticket(log, tic);
++			xlog_ticket_put(log, tic);
+ 		}
+ 	} else {
+ 		/*
+@@ -713,11 +732,11 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ 		 */
+ 		spin_lock(&log->l_icloglock);
+ 		iclog = log->l_iclog;
+-		iclog->ic_refcnt++;
++		atomic_inc(&iclog->ic_refcnt);
+ 		spin_unlock(&log->l_icloglock);
+ 
+ 		xlog_state_want_sync(log, iclog);
+-		(void) xlog_state_release_iclog(log, iclog);
++		error =  xlog_state_release_iclog(log, iclog);
+ 
+ 		spin_lock(&log->l_icloglock);
+ 
+@@ -732,7 +751,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ 		}
+ 	}
+ 
+-	return 0;
++	return error;
+ }	/* xfs_log_unmount_write */
+ 
+ /*
+@@ -1210,7 +1229,6 @@ xlog_alloc_log(xfs_mount_t	*mp,
+ 	spin_lock_init(&log->l_icloglock);
+ 	spin_lock_init(&log->l_grant_lock);
+ 	initnsema(&log->l_flushsema, 0, "ic-flush");
+-	xlog_state_ticket_alloc(log);  /* wait until after icloglock inited */
+ 
+ 	/* log record size must be multiple of BBSIZE; see xlog_rec_header_t */
+ 	ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0);
+@@ -1240,9 +1258,9 @@ xlog_alloc_log(xfs_mount_t	*mp,
+ 		XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
+ 		iclog->ic_bp = bp;
+ 		iclog->hic_data = bp->b_addr;
+-
++#ifdef DEBUG
+ 		log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
+-
++#endif
+ 		head = &iclog->ic_header;
+ 		memset(head, 0, sizeof(xlog_rec_header_t));
+ 		head->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
+@@ -1253,10 +1271,11 @@ xlog_alloc_log(xfs_mount_t	*mp,
+ 		head->h_fmt = cpu_to_be32(XLOG_FMT);
+ 		memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
+ 
+-
+ 		iclog->ic_size = XFS_BUF_SIZE(bp) - log->l_iclog_hsize;
+ 		iclog->ic_state = XLOG_STATE_ACTIVE;
+ 		iclog->ic_log = log;
++		atomic_set(&iclog->ic_refcnt, 0);
++		spin_lock_init(&iclog->ic_callback_lock);
+ 		iclog->ic_callback_tail = &(iclog->ic_callback);
+ 		iclog->ic_datap = (char *)iclog->hic_data + log->l_iclog_hsize;
+ 
+@@ -1405,7 +1424,7 @@ xlog_sync(xlog_t		*log,
+ 	int		v2 = xfs_sb_version_haslogv2(&log->l_mp->m_sb);
+ 
+ 	XFS_STATS_INC(xs_log_writes);
+-	ASSERT(iclog->ic_refcnt == 0);
++	ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
+ 
+ 	/* Add for LR header */
+ 	count_init = log->l_iclog_hsize + iclog->ic_offset;
+@@ -1538,7 +1557,6 @@ STATIC void
+ xlog_dealloc_log(xlog_t *log)
+ {
+ 	xlog_in_core_t	*iclog, *next_iclog;
+-	xlog_ticket_t	*tic, *next_tic;
+ 	int		i;
+ 
+ 	iclog = log->l_iclog;
+@@ -1559,22 +1577,6 @@ xlog_dealloc_log(xlog_t *log)
+ 	spinlock_destroy(&log->l_icloglock);
+ 	spinlock_destroy(&log->l_grant_lock);
+ 
+-	/* XXXsup take a look at this again. */
+-	if ((log->l_ticket_cnt != log->l_ticket_tcnt)  &&
+-	    !XLOG_FORCED_SHUTDOWN(log)) {
+-		xfs_fs_cmn_err(CE_WARN, log->l_mp,
+-			"xlog_dealloc_log: (cnt: %d, total: %d)",
+-			log->l_ticket_cnt, log->l_ticket_tcnt);
+-		/* ASSERT(log->l_ticket_cnt == log->l_ticket_tcnt); */
+-
+-	} else {
+-		tic = log->l_unmount_free;
+-		while (tic) {
+-			next_tic = tic->t_next;
+-			kmem_free(tic, PAGE_SIZE);
+-			tic = next_tic;
+-		}
+-	}
+ 	xfs_buf_free(log->l_xbuf);
+ #ifdef XFS_LOG_TRACE
+ 	if (log->l_trace != NULL) {
+@@ -1987,7 +1989,7 @@ xlog_state_clean_log(xlog_t *log)
+ 		if (iclog->ic_state == XLOG_STATE_DIRTY) {
+ 			iclog->ic_state	= XLOG_STATE_ACTIVE;
+ 			iclog->ic_offset       = 0;
+-			iclog->ic_callback	= NULL;   /* don't need to free */
++			ASSERT(iclog->ic_callback == NULL);
+ 			/*
+ 			 * If the number of ops in this iclog indicate it just
+ 			 * contains the dummy transaction, we can
+@@ -2190,37 +2192,40 @@ xlog_state_do_callback(
+ 					be64_to_cpu(iclog->ic_header.h_lsn);
+ 				spin_unlock(&log->l_grant_lock);
+ 
+-				/*
+-				 * Keep processing entries in the callback list
+-				 * until we come around and it is empty.  We
+-				 * need to atomically see that the list is
+-				 * empty and change the state to DIRTY so that
+-				 * we don't miss any more callbacks being added.
+-				 */
+-				spin_lock(&log->l_icloglock);
+ 			} else {
++				spin_unlock(&log->l_icloglock);
+ 				ioerrors++;
+ 			}
+-			cb = iclog->ic_callback;
+ 
++			/*
++			 * Keep processing entries in the callback list until
++			 * we come around and it is empty.  We need to
++			 * atomically see that the list is empty and change the
++			 * state to DIRTY so that we don't miss any more
++			 * callbacks being added.
++			 */
++			spin_lock(&iclog->ic_callback_lock);
++			cb = iclog->ic_callback;
+ 			while (cb) {
+ 				iclog->ic_callback_tail = &(iclog->ic_callback);
+ 				iclog->ic_callback = NULL;
+-				spin_unlock(&log->l_icloglock);
++				spin_unlock(&iclog->ic_callback_lock);
+ 
+ 				/* perform callbacks in the order given */
+ 				for (; cb; cb = cb_next) {
+ 					cb_next = cb->cb_next;
+ 					cb->cb_func(cb->cb_arg, aborted);
+ 				}
+-				spin_lock(&log->l_icloglock);
++				spin_lock(&iclog->ic_callback_lock);
+ 				cb = iclog->ic_callback;
+ 			}
+ 
+ 			loopdidcallbacks++;
+ 			funcdidcallbacks++;
+ 
++			spin_lock(&log->l_icloglock);
+ 			ASSERT(iclog->ic_callback == NULL);
++			spin_unlock(&iclog->ic_callback_lock);
+ 			if (!(iclog->ic_state & XLOG_STATE_IOERROR))
+ 				iclog->ic_state = XLOG_STATE_DIRTY;
+ 
+@@ -2241,7 +2246,7 @@ xlog_state_do_callback(
+ 			repeats = 0;
+ 			xfs_fs_cmn_err(CE_WARN, log->l_mp,
+ 				"%s: possible infinite loop (%d iterations)",
+-				__FUNCTION__, flushcnt);
++				__func__, flushcnt);
+ 		}
+ 	} while (!ioerrors && loopdidcallbacks);
+ 
+@@ -2309,7 +2314,7 @@ xlog_state_done_syncing(
+ 
+ 	ASSERT(iclog->ic_state == XLOG_STATE_SYNCING ||
+ 	       iclog->ic_state == XLOG_STATE_IOERROR);
+-	ASSERT(iclog->ic_refcnt == 0);
++	ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
+ 	ASSERT(iclog->ic_bwritecnt == 1 || iclog->ic_bwritecnt == 2);
+ 
+ 
+@@ -2391,7 +2396,7 @@ restart:
+ 	ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE);
+ 	head = &iclog->ic_header;
+ 
+-	iclog->ic_refcnt++;			/* prevents sync */
++	atomic_inc(&iclog->ic_refcnt);	/* prevents sync */
+ 	log_offset = iclog->ic_offset;
+ 
+ 	/* On the 1st write to an iclog, figure out lsn.  This works
+@@ -2423,12 +2428,12 @@ restart:
+ 		xlog_state_switch_iclogs(log, iclog, iclog->ic_size);
+ 
+ 		/* If I'm the only one writing to this iclog, sync it to disk */
+-		if (iclog->ic_refcnt == 1) {
++		if (atomic_read(&iclog->ic_refcnt) == 1) {
+ 			spin_unlock(&log->l_icloglock);
+ 			if ((error = xlog_state_release_iclog(log, iclog)))
+ 				return error;
+ 		} else {
+-			iclog->ic_refcnt--;
++			atomic_dec(&iclog->ic_refcnt);
+ 			spin_unlock(&log->l_icloglock);
+ 		}
+ 		goto restart;
+@@ -2792,18 +2797,6 @@ xlog_ungrant_log_space(xlog_t	     *log,
+ 
+ 
+ /*
+- * Atomically put back used ticket.
+- */
+-STATIC void
+-xlog_state_put_ticket(xlog_t	    *log,
+-		      xlog_ticket_t *tic)
+-{
+-	spin_lock(&log->l_icloglock);
+-	xlog_ticket_put(log, tic);
+-	spin_unlock(&log->l_icloglock);
+-}	/* xlog_state_put_ticket */
+-
+-/*
+  * Flush iclog to disk if this is the last reference to the given iclog and
+  * the WANT_SYNC bit is set.
+  *
+@@ -2813,33 +2806,35 @@ xlog_state_put_ticket(xlog_t	    *log,
+  *
+  */
+ STATIC int
+-xlog_state_release_iclog(xlog_t		*log,
+-			 xlog_in_core_t	*iclog)
++xlog_state_release_iclog(
++	xlog_t		*log,
++	xlog_in_core_t	*iclog)
+ {
+ 	int		sync = 0;	/* do we sync? */
+ 
+-	xlog_assign_tail_lsn(log->l_mp);
++	if (iclog->ic_state & XLOG_STATE_IOERROR)
++		return XFS_ERROR(EIO);
+ 
+-	spin_lock(&log->l_icloglock);
++	ASSERT(atomic_read(&iclog->ic_refcnt) > 0);
++	if (!atomic_dec_and_lock(&iclog->ic_refcnt, &log->l_icloglock))
++		return 0;
+ 
+ 	if (iclog->ic_state & XLOG_STATE_IOERROR) {
+ 		spin_unlock(&log->l_icloglock);
+ 		return XFS_ERROR(EIO);
+ 	}
+-
+-	ASSERT(iclog->ic_refcnt > 0);
+ 	ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE ||
+ 	       iclog->ic_state == XLOG_STATE_WANT_SYNC);
+ 
+-	if (--iclog->ic_refcnt == 0 &&
+-	    iclog->ic_state == XLOG_STATE_WANT_SYNC) {
++	if (iclog->ic_state == XLOG_STATE_WANT_SYNC) {
++		/* update tail before writing to iclog */
++		xlog_assign_tail_lsn(log->l_mp);
+ 		sync++;
+ 		iclog->ic_state = XLOG_STATE_SYNCING;
+ 		iclog->ic_header.h_tail_lsn = cpu_to_be64(log->l_tail_lsn);
+ 		xlog_verify_tail_lsn(log, iclog, log->l_tail_lsn);
+ 		/* cycle incremented when incrementing curr_block */
+ 	}
+-
+ 	spin_unlock(&log->l_icloglock);
+ 
+ 	/*
+@@ -2849,11 +2844,9 @@ xlog_state_release_iclog(xlog_t		*log,
+ 	 * this iclog has consistent data, so we ignore IOERROR
+ 	 * flags after this point.
+ 	 */
+-	if (sync) {
++	if (sync)
+ 		return xlog_sync(log, iclog);
+-	}
+ 	return 0;
+-
+ }	/* xlog_state_release_iclog */
+ 
+ 
+@@ -2953,7 +2946,8 @@ xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed)
+ 		 * previous iclog and go to sleep.
+ 		 */
+ 		if (iclog->ic_state == XLOG_STATE_DIRTY ||
+-		    (iclog->ic_refcnt == 0 && iclog->ic_offset == 0)) {
++		    (atomic_read(&iclog->ic_refcnt) == 0
++		     && iclog->ic_offset == 0)) {
+ 			iclog = iclog->ic_prev;
+ 			if (iclog->ic_state == XLOG_STATE_ACTIVE ||
+ 			    iclog->ic_state == XLOG_STATE_DIRTY)
+@@ -2961,14 +2955,14 @@ xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed)
+ 			else
+ 				goto maybe_sleep;
+ 		} else {
+-			if (iclog->ic_refcnt == 0) {
++			if (atomic_read(&iclog->ic_refcnt) == 0) {
+ 				/* We are the only one with access to this
+ 				 * iclog.  Flush it out now.  There should
+ 				 * be a roundoff of zero to show that someone
+ 				 * has already taken care of the roundoff from
+ 				 * the previous sync.
+ 				 */
+-				iclog->ic_refcnt++;
++				atomic_inc(&iclog->ic_refcnt);
+ 				lsn = be64_to_cpu(iclog->ic_header.h_lsn);
+ 				xlog_state_switch_iclogs(log, iclog, 0);
+ 				spin_unlock(&log->l_icloglock);
+@@ -3100,7 +3094,7 @@ try_again:
+ 			already_slept = 1;
+ 			goto try_again;
+ 		} else {
+-			iclog->ic_refcnt++;
++			atomic_inc(&iclog->ic_refcnt);
+ 			xlog_state_switch_iclogs(log, iclog, 0);
+ 			spin_unlock(&log->l_icloglock);
+ 			if (xlog_state_release_iclog(log, iclog))
+@@ -3172,92 +3166,19 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
+  */
+ 
+ /*
+- *	Algorithm doesn't take into account page size. ;-(
+- */
+-STATIC void
+-xlog_state_ticket_alloc(xlog_t *log)
+-{
+-	xlog_ticket_t	*t_list;
+-	xlog_ticket_t	*next;
+-	xfs_caddr_t	buf;
+-	uint		i = (PAGE_SIZE / sizeof(xlog_ticket_t)) - 2;
+-
+-	/*
+-	 * The kmem_zalloc may sleep, so we shouldn't be holding the
+-	 * global lock.  XXXmiken: may want to use zone allocator.
+-	 */
+-	buf = (xfs_caddr_t) kmem_zalloc(PAGE_SIZE, KM_SLEEP);
+-
+-	spin_lock(&log->l_icloglock);
+-
+-	/* Attach 1st ticket to Q, so we can keep track of allocated memory */
+-	t_list = (xlog_ticket_t *)buf;
+-	t_list->t_next = log->l_unmount_free;
+-	log->l_unmount_free = t_list++;
+-	log->l_ticket_cnt++;
+-	log->l_ticket_tcnt++;
+-
+-	/* Next ticket becomes first ticket attached to ticket free list */
+-	if (log->l_freelist != NULL) {
+-		ASSERT(log->l_tail != NULL);
+-		log->l_tail->t_next = t_list;
+-	} else {
+-		log->l_freelist = t_list;
+-	}
+-	log->l_ticket_cnt++;
+-	log->l_ticket_tcnt++;
+-
+-	/* Cycle through rest of alloc'ed memory, building up free Q */
+-	for ( ; i > 0; i--) {
+-		next = t_list + 1;
+-		t_list->t_next = next;
+-		t_list = next;
+-		log->l_ticket_cnt++;
+-		log->l_ticket_tcnt++;
+-	}
+-	t_list->t_next = NULL;
+-	log->l_tail = t_list;
+-	spin_unlock(&log->l_icloglock);
+-}	/* xlog_state_ticket_alloc */
+-
+-
+-/*
+- * Put ticket into free list
+- *
+- * Assumption: log lock is held around this call.
++ * Free a used ticket.
+  */
+ STATIC void
+ xlog_ticket_put(xlog_t		*log,
+ 		xlog_ticket_t	*ticket)
+ {
+ 	sv_destroy(&ticket->t_sema);
+-
+-	/*
+-	 * Don't think caching will make that much difference.  It's
+-	 * more important to make debug easier.
+-	 */
+-#if 0
+-	/* real code will want to use LIFO for caching */
+-	ticket->t_next = log->l_freelist;
+-	log->l_freelist = ticket;
+-	/* no need to clear fields */
+-#else
+-	/* When we debug, it is easier if tickets are cycled */
+-	ticket->t_next     = NULL;
+-	if (log->l_tail) {
+-		log->l_tail->t_next = ticket;
+-	} else {
+-		ASSERT(log->l_freelist == NULL);
+-		log->l_freelist = ticket;
+-	}
+-	log->l_tail	    = ticket;
+-#endif /* DEBUG */
+-	log->l_ticket_cnt++;
++	kmem_zone_free(xfs_log_ticket_zone, ticket);
+ }	/* xlog_ticket_put */
+ 
+ 
+ /*
+- * Grab ticket off freelist or allocation some more
++ * Allocate and initialise a new log ticket.
+  */
+ STATIC xlog_ticket_t *
+ xlog_ticket_get(xlog_t		*log,
+@@ -3269,21 +3190,9 @@ xlog_ticket_get(xlog_t		*log,
+ 	xlog_ticket_t	*tic;
+ 	uint		num_headers;
+ 
+- alloc:
+-	if (log->l_freelist == NULL)
+-		xlog_state_ticket_alloc(log);		/* potentially sleep */
+-
+-	spin_lock(&log->l_icloglock);
+-	if (log->l_freelist == NULL) {
+-		spin_unlock(&log->l_icloglock);
+-		goto alloc;
+-	}
+-	tic		= log->l_freelist;
+-	log->l_freelist	= tic->t_next;
+-	if (log->l_freelist == NULL)
+-		log->l_tail = NULL;
+-	log->l_ticket_cnt--;
+-	spin_unlock(&log->l_icloglock);
++	tic = kmem_zone_zalloc(xfs_log_ticket_zone, KM_SLEEP|KM_MAYFAIL);
++	if (!tic)
++		return NULL;
+ 
+ 	/*
+ 	 * Permanent reservations have up to 'cnt'-1 active log operations
+@@ -3611,8 +3520,8 @@ xfs_log_force_umount(
+ 	 * before we mark the filesystem SHUTDOWN and wake
+ 	 * everybody up to tell the bad news.
+ 	 */
+-	spin_lock(&log->l_grant_lock);
+ 	spin_lock(&log->l_icloglock);
++	spin_lock(&log->l_grant_lock);
+ 	mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
+ 	XFS_BUF_DONE(mp->m_sb_bp);
+ 	/*
+diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
+index 4cdac04..d1d678e 100644
+--- a/fs/xfs/xfs_log.h
++++ b/fs/xfs/xfs_log.h
+@@ -142,8 +142,9 @@ int	  _xfs_log_force(struct xfs_mount *mp,
+ 			 xfs_lsn_t	lsn,
+ 			 uint		flags,
+ 			 int		*log_forced);
+-#define xfs_log_force(mp, lsn, flags) \
+-	_xfs_log_force(mp, lsn, flags, NULL);
++void	  xfs_log_force(struct xfs_mount	*mp,
++			xfs_lsn_t		lsn,
++			uint			flags);
+ int	  xfs_log_mount(struct xfs_mount	*mp,
+ 			struct xfs_buftarg	*log_target,
+ 			xfs_daddr_t		start_block,
+diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
+index c6244cc..8952a39 100644
+--- a/fs/xfs/xfs_log_priv.h
++++ b/fs/xfs/xfs_log_priv.h
+@@ -242,7 +242,7 @@ typedef struct xlog_res {
+ 
+ typedef struct xlog_ticket {
+ 	sv_t		   t_sema;	 /* sleep on this semaphore      : 20 */
+- 	struct xlog_ticket *t_next;	 /*			         :4|8 */
++	struct xlog_ticket *t_next;	 /*			         :4|8 */
+ 	struct xlog_ticket *t_prev;	 /*				 :4|8 */
+ 	xlog_tid_t	   t_tid;	 /* transaction identifier	 : 4  */
+ 	int		   t_curr_res;	 /* current reservation in bytes : 4  */
+@@ -324,6 +324,19 @@ typedef struct xlog_rec_ext_header {
+  * - ic_offset is the current number of bytes written to in this iclog.
+  * - ic_refcnt is bumped when someone is writing to the log.
+  * - ic_state is the state of the iclog.
++ *
++ * Because of cacheline contention on large machines, we need to separate
++ * various resources onto different cachelines. To start with, make the
++ * structure cacheline aligned. The following fields can be contended on
++ * by independent processes:
++ *
++ *	- ic_callback_*
++ *	- ic_refcnt
++ *	- fields protected by the global l_icloglock
++ *
++ * so we need to ensure that these fields are located in separate cachelines.
++ * We'll put all the read-only and l_icloglock fields in the first cacheline,
++ * and move everything else out to subsequent cachelines.
+  */
+ typedef struct xlog_iclog_fields {
+ 	sv_t			ic_forcesema;
+@@ -332,17 +345,22 @@ typedef struct xlog_iclog_fields {
+ 	struct xlog_in_core	*ic_prev;
+ 	struct xfs_buf		*ic_bp;
+ 	struct log		*ic_log;
+-	xfs_log_callback_t	*ic_callback;
+-	xfs_log_callback_t	**ic_callback_tail;
+-#ifdef XFS_LOG_TRACE
+-	struct ktrace		*ic_trace;
+-#endif
+ 	int			ic_size;
+ 	int			ic_offset;
+-	int			ic_refcnt;
+ 	int			ic_bwritecnt;
+ 	ushort_t		ic_state;
+ 	char			*ic_datap;	/* pointer to iclog data */
++#ifdef XFS_LOG_TRACE
++	struct ktrace		*ic_trace;
++#endif
++
++	/* Callback structures need their own cacheline */
++	spinlock_t		ic_callback_lock ____cacheline_aligned_in_smp;
++	xfs_log_callback_t	*ic_callback;
++	xfs_log_callback_t	**ic_callback_tail;
++
++	/* reference counts need their own cacheline */
++	atomic_t		ic_refcnt ____cacheline_aligned_in_smp;
+ } xlog_iclog_fields_t;
+ 
+ typedef union xlog_in_core2 {
+@@ -366,6 +384,7 @@ typedef struct xlog_in_core {
+ #define	ic_bp		hic_fields.ic_bp
+ #define	ic_log		hic_fields.ic_log
+ #define	ic_callback	hic_fields.ic_callback
++#define	ic_callback_lock hic_fields.ic_callback_lock
+ #define	ic_callback_tail hic_fields.ic_callback_tail
+ #define	ic_trace	hic_fields.ic_trace
+ #define	ic_size		hic_fields.ic_size
+@@ -383,43 +402,46 @@ typedef struct xlog_in_core {
+  * that round off problems won't occur when releasing partial reservations.
+  */
+ typedef struct log {
++	/* The following fields don't need locking */
++	struct xfs_mount	*l_mp;	        /* mount point */
++	struct xfs_buf		*l_xbuf;        /* extra buffer for log
++						 * wrapping */
++	struct xfs_buftarg	*l_targ;        /* buftarg of log */
++	uint			l_flags;
++	uint			l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
++	struct xfs_buf_cancel	**l_buf_cancel_table;
++	int			l_iclog_hsize;  /* size of iclog header */
++	int			l_iclog_heads;  /* # of iclog header sectors */
++	uint			l_sectbb_log;   /* log2 of sector size in BBs */
++	uint			l_sectbb_mask;  /* sector size (in BBs)
++						 * alignment mask */
++	int			l_iclog_size;	/* size of log in bytes */
++	int			l_iclog_size_log; /* log power size of log */
++	int			l_iclog_bufs;	/* number of iclog buffers */
++	xfs_daddr_t		l_logBBstart;   /* start block of log */
++	int			l_logsize;      /* size of log in bytes */
++	int			l_logBBsize;    /* size of log in BB chunks */
++
+ 	/* The following block of fields are changed while holding icloglock */
+-	sema_t			l_flushsema;    /* iclog flushing semaphore */
++	sema_t			l_flushsema ____cacheline_aligned_in_smp;
++						/* iclog flushing semaphore */
+ 	int			l_flushcnt;	/* # of procs waiting on this
+ 						 * sema */
+-	int			l_ticket_cnt;	/* free ticket count */
+-	int			l_ticket_tcnt;	/* total ticket count */
+ 	int			l_covered_state;/* state of "covering disk
+ 						 * log entries" */
+-	xlog_ticket_t		*l_freelist;    /* free list of tickets */
+-	xlog_ticket_t		*l_unmount_free;/* kmem_free these addresses */
+-	xlog_ticket_t		*l_tail;        /* free list of tickets */
+ 	xlog_in_core_t		*l_iclog;       /* head log queue	*/
+ 	spinlock_t		l_icloglock;    /* grab to change iclog state */
+ 	xfs_lsn_t		l_tail_lsn;     /* lsn of 1st LR with unflushed
+ 						 * buffers */
+ 	xfs_lsn_t		l_last_sync_lsn;/* lsn of last LR on disk */
+-	struct xfs_mount	*l_mp;	        /* mount point */
+-	struct xfs_buf		*l_xbuf;        /* extra buffer for log
+-						 * wrapping */
+-	struct xfs_buftarg	*l_targ;        /* buftarg of log */
+-	xfs_daddr_t		l_logBBstart;   /* start block of log */
+-	int			l_logsize;      /* size of log in bytes */
+-	int			l_logBBsize;    /* size of log in BB chunks */
+ 	int			l_curr_cycle;   /* Cycle number of log writes */
+ 	int			l_prev_cycle;   /* Cycle number before last
+ 						 * block increment */
+ 	int			l_curr_block;   /* current logical log block */
+ 	int			l_prev_block;   /* previous logical log block */
+-	int			l_iclog_size;	/* size of log in bytes */
+-	int			l_iclog_size_log; /* log power size of log */
+-	int			l_iclog_bufs;	/* number of iclog buffers */
+-
+-	/* The following field are used for debugging; need to hold icloglock */
+-	char			*l_iclog_bak[XLOG_MAX_ICLOGS];
+ 
+ 	/* The following block of fields are changed while holding grant_lock */
+-	spinlock_t		l_grant_lock;
++	spinlock_t		l_grant_lock ____cacheline_aligned_in_smp;
+ 	xlog_ticket_t		*l_reserve_headq;
+ 	xlog_ticket_t		*l_write_headq;
+ 	int			l_grant_reserve_cycle;
+@@ -427,19 +449,16 @@ typedef struct log {
+ 	int			l_grant_write_cycle;
+ 	int			l_grant_write_bytes;
+ 
+-	/* The following fields don't need locking */
+ #ifdef XFS_LOG_TRACE
+ 	struct ktrace		*l_trace;
+ 	struct ktrace		*l_grant_trace;
+ #endif
+-	uint			l_flags;
+-	uint			l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
+-	struct xfs_buf_cancel	**l_buf_cancel_table;
+-	int			l_iclog_hsize;  /* size of iclog header */
+-	int			l_iclog_heads;  /* # of iclog header sectors */
+-	uint			l_sectbb_log;   /* log2 of sector size in BBs */
+-	uint			l_sectbb_mask;  /* sector size (in BBs)
+-						 * alignment mask */
++
++	/* The following field are used for debugging; need to hold icloglock */
++#ifdef DEBUG
++	char			*l_iclog_bak[XLOG_MAX_ICLOGS];
++#endif
++
+ } xlog_t;
+ 
+ #define XLOG_FORCED_SHUTDOWN(log)	((log)->l_flags & XLOG_IO_ERROR)
+@@ -459,6 +478,8 @@ extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
+ extern void	 xlog_put_bp(struct xfs_buf *);
+ extern int	 xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
+ 
++extern kmem_zone_t	*xfs_log_ticket_zone;
++
+ /* iclog tracing */
+ #define XLOG_TRACE_GRAB_FLUSH  1
+ #define XLOG_TRACE_REL_FLUSH   2
+diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
+index b2b70eb..e65ab4a 100644
+--- a/fs/xfs/xfs_log_recover.c
++++ b/fs/xfs/xfs_log_recover.c
+@@ -46,6 +46,7 @@
+ #include "xfs_trans_priv.h"
+ #include "xfs_quota.h"
+ #include "xfs_rw.h"
++#include "xfs_utils.h"
+ 
+ STATIC int	xlog_find_zeroed(xlog_t *, xfs_daddr_t *);
+ STATIC int	xlog_clear_stale_blocks(xlog_t *, xfs_lsn_t);
+@@ -120,7 +121,8 @@ xlog_bread(
+ 	XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
+ 
+ 	xfsbdstrat(log->l_mp, bp);
+-	if ((error = xfs_iowait(bp)))
++	error = xfs_iowait(bp);
++	if (error)
+ 		xfs_ioerror_alert("xlog_bread", log->l_mp,
+ 				  bp, XFS_BUF_ADDR(bp));
+ 	return error;
+@@ -191,7 +193,7 @@ xlog_header_check_dump(
+ {
+ 	int			b;
+ 
+-	cmn_err(CE_DEBUG, "%s:  SB : uuid = ", __FUNCTION__);
++	cmn_err(CE_DEBUG, "%s:  SB : uuid = ", __func__);
+ 	for (b = 0; b < 16; b++)
+ 		cmn_err(CE_DEBUG, "%02x", ((uchar_t *)&mp->m_sb.sb_uuid)[b]);
+ 	cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT);
+@@ -1160,10 +1162,14 @@ xlog_write_log_records(
+ 		if (j == 0 && (start_block + endcount > ealign)) {
+ 			offset = XFS_BUF_PTR(bp);
+ 			balign = BBTOB(ealign - start_block);
+-			XFS_BUF_SET_PTR(bp, offset + balign, BBTOB(sectbb));
+-			if ((error = xlog_bread(log, ealign, sectbb, bp)))
++			error = XFS_BUF_SET_PTR(bp, offset + balign,
++						BBTOB(sectbb));
++			if (!error)
++				error = xlog_bread(log, ealign, sectbb, bp);
++			if (!error)
++				error = XFS_BUF_SET_PTR(bp, offset, bufblks);
++			if (error)
+ 				break;
+-			XFS_BUF_SET_PTR(bp, offset, bufblks);
+ 		}
+ 
+ 		offset = xlog_align(log, start_block, endcount, bp);
+@@ -2280,7 +2286,9 @@ xlog_recover_do_inode_trans(
+ 		 * invalidate the buffer when we write it out below.
+ 		 */
+ 		imap.im_blkno = 0;
+-		xfs_imap(log->l_mp, NULL, ino, &imap, 0);
++		error = xfs_imap(log->l_mp, NULL, ino, &imap, 0);
++		if (error)
++			goto error;
+ 	}
+ 
+ 	/*
+@@ -2964,7 +2972,7 @@ xlog_recover_process_data(
+  * Process an extent free intent item that was recovered from
+  * the log.  We need to free the extents that it describes.
+  */
+-STATIC void
++STATIC int
+ xlog_recover_process_efi(
+ 	xfs_mount_t		*mp,
+ 	xfs_efi_log_item_t	*efip)
+@@ -2972,6 +2980,7 @@ xlog_recover_process_efi(
+ 	xfs_efd_log_item_t	*efdp;
+ 	xfs_trans_t		*tp;
+ 	int			i;
++	int			error = 0;
+ 	xfs_extent_t		*extp;
+ 	xfs_fsblock_t		startblock_fsb;
+ 
+@@ -2995,23 +3004,32 @@ xlog_recover_process_efi(
+ 			 * free the memory associated with it.
+ 			 */
+ 			xfs_efi_release(efip, efip->efi_format.efi_nextents);
+-			return;
++			return XFS_ERROR(EIO);
+ 		}
+ 	}
+ 
+ 	tp = xfs_trans_alloc(mp, 0);
+-	xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 0, 0);
++	error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 0, 0);
++	if (error)
++		goto abort_error;
+ 	efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
+ 
+ 	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
+ 		extp = &(efip->efi_format.efi_extents[i]);
+-		xfs_free_extent(tp, extp->ext_start, extp->ext_len);
++		error = xfs_free_extent(tp, extp->ext_start, extp->ext_len);
++		if (error)
++			goto abort_error;
+ 		xfs_trans_log_efd_extent(tp, efdp, extp->ext_start,
+ 					 extp->ext_len);
+ 	}
+ 
+ 	efip->efi_flags |= XFS_EFI_RECOVERED;
+-	xfs_trans_commit(tp, 0);
++	error = xfs_trans_commit(tp, 0);
++	return error;
++
++abort_error:
++	xfs_trans_cancel(tp, XFS_TRANS_ABORT);
++	return error;
+ }
+ 
+ /*
+@@ -3059,7 +3077,7 @@ xlog_recover_check_ail(
+  * everything already in the AIL, we stop processing as soon as
+  * we see something other than an EFI in the AIL.
+  */
+-STATIC void
++STATIC int
+ xlog_recover_process_efis(
+ 	xlog_t			*log)
+ {
+@@ -3067,6 +3085,7 @@ xlog_recover_process_efis(
+ 	xfs_efi_log_item_t	*efip;
+ 	int			gen;
+ 	xfs_mount_t		*mp;
++	int			error = 0;
+ 
+ 	mp = log->l_mp;
+ 	spin_lock(&mp->m_ail_lock);
+@@ -3091,11 +3110,14 @@ xlog_recover_process_efis(
+ 		}
+ 
+ 		spin_unlock(&mp->m_ail_lock);
+-		xlog_recover_process_efi(mp, efip);
++		error = xlog_recover_process_efi(mp, efip);
++		if (error)
++			return error;
+ 		spin_lock(&mp->m_ail_lock);
+ 		lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
+ 	}
+ 	spin_unlock(&mp->m_ail_lock);
++	return error;
+ }
+ 
+ /*
+@@ -3115,21 +3137,18 @@ xlog_recover_clear_agi_bucket(
+ 	int		error;
+ 
+ 	tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET);
+-	xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0);
+-
+-	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
++	error = xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0);
++	if (!error)
++		error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
+ 				   XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
+ 				   XFS_FSS_TO_BB(mp, 1), 0, &agibp);
+-	if (error) {
+-		xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+-		return;
+-	}
++	if (error)
++		goto out_abort;
+ 
++	error = EINVAL;
+ 	agi = XFS_BUF_TO_AGI(agibp);
+-	if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) {
+-		xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+-		return;
+-	}
++	if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC)
++		goto out_abort;
+ 
+ 	agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
+ 	offset = offsetof(xfs_agi_t, agi_unlinked) +
+@@ -3137,7 +3156,17 @@ xlog_recover_clear_agi_bucket(
+ 	xfs_trans_log_buf(tp, agibp, offset,
+ 			  (offset + sizeof(xfs_agino_t) - 1));
+ 
+-	(void) xfs_trans_commit(tp, 0);
++	error = xfs_trans_commit(tp, 0);
++	if (error)
++		goto out_error;
++	return;
++
++out_abort:
++	xfs_trans_cancel(tp, XFS_TRANS_ABORT);
++out_error:
++	xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: "
++			"failed to clear agi %d. Continuing.", agno);
++	return;
+ }
+ 
+ /*
+@@ -3214,7 +3243,8 @@ xlog_recover_process_iunlinks(
+ 					 * next inode in the bucket.
+ 					 */
+ 					error = xfs_itobp(mp, NULL, ip, &dip,
+-							&ibp, 0, 0);
++							&ibp, 0, 0,
++							XFS_BUF_LOCK);
+ 					ASSERT(error || (dip != NULL));
+ 				}
+ 
+@@ -3247,7 +3277,7 @@ xlog_recover_process_iunlinks(
+ 					if (ip->i_d.di_mode == 0)
+ 						xfs_iput_new(ip, 0);
+ 					else
+-						VN_RELE(XFS_ITOV(ip));
++						IRELE(ip);
+ 				} else {
+ 					/*
+ 					 * We can't read in the inode
+@@ -3445,7 +3475,7 @@ xlog_valid_rec_header(
+ 	    (!rhead->h_version ||
+ 	    (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) {
+ 		xlog_warn("XFS: %s: unrecognised log version (%d).",
+-			__FUNCTION__, be32_to_cpu(rhead->h_version));
++			__func__, be32_to_cpu(rhead->h_version));
+ 		return XFS_ERROR(EIO);
+ 	}
+ 
+@@ -3604,15 +3634,19 @@ xlog_do_recovery_pass(
+ 				 *   _first_, then the log start (LR header end)
+ 				 *   - order is important.
+ 				 */
++				wrapped_hblks = hblks - split_hblks;
+ 				bufaddr = XFS_BUF_PTR(hbp);
+-				XFS_BUF_SET_PTR(hbp,
++				error = XFS_BUF_SET_PTR(hbp,
+ 						bufaddr + BBTOB(split_hblks),
+ 						BBTOB(hblks - split_hblks));
+-				wrapped_hblks = hblks - split_hblks;
+-				error = xlog_bread(log, 0, wrapped_hblks, hbp);
++				if (!error)
++					error = xlog_bread(log, 0,
++							wrapped_hblks, hbp);
++				if (!error)
++					error = XFS_BUF_SET_PTR(hbp, bufaddr,
++							BBTOB(hblks));
+ 				if (error)
+ 					goto bread_err2;
+-				XFS_BUF_SET_PTR(hbp, bufaddr, BBTOB(hblks));
+ 				if (!offset)
+ 					offset = xlog_align(log, 0,
+ 							wrapped_hblks, hbp);
+@@ -3664,13 +3698,18 @@ xlog_do_recovery_pass(
+ 				 *   - order is important.
+ 				 */
+ 				bufaddr = XFS_BUF_PTR(dbp);
+-				XFS_BUF_SET_PTR(dbp,
++				error = XFS_BUF_SET_PTR(dbp,
+ 						bufaddr + BBTOB(split_bblks),
+ 						BBTOB(bblks - split_bblks));
+-				if ((error = xlog_bread(log, wrapped_hblks,
+-						bblks - split_bblks, dbp)))
++				if (!error)
++					error = xlog_bread(log, wrapped_hblks,
++							bblks - split_bblks,
++							dbp);
++				if (!error)
++					error = XFS_BUF_SET_PTR(dbp, bufaddr,
++							h_size);
++				if (error)
+ 					goto bread_err2;
+-				XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
+ 				if (!offset)
+ 					offset = xlog_align(log, wrapped_hblks,
+ 						bblks - split_bblks, dbp);
+@@ -3826,7 +3865,8 @@ xlog_do_recover(
+ 	XFS_BUF_READ(bp);
+ 	XFS_BUF_UNASYNC(bp);
+ 	xfsbdstrat(log->l_mp, bp);
+-	if ((error = xfs_iowait(bp))) {
++	error = xfs_iowait(bp);
++	if (error) {
+ 		xfs_ioerror_alert("xlog_do_recover",
+ 				  log->l_mp, bp, XFS_BUF_ADDR(bp));
+ 		ASSERT(0);
+@@ -3917,7 +3957,14 @@ xlog_recover_finish(
+ 	 * rather than accepting new requests.
+ 	 */
+ 	if (log->l_flags & XLOG_RECOVERY_NEEDED) {
+-		xlog_recover_process_efis(log);
++		int	error;
++		error = xlog_recover_process_efis(log);
++		if (error) {
++			cmn_err(CE_ALERT,
++				"Failed to recover EFIs on filesystem: %s",
++				log->l_mp->m_fsname);
++			return error;
++		}
+ 		/*
+ 		 * Sync the log to get all the EFIs out of the AIL.
+ 		 * This isn't absolutely necessary, but it helps in
+diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
+index 8ed164e..2fec452 100644
+--- a/fs/xfs/xfs_mount.c
++++ b/fs/xfs/xfs_mount.c
+@@ -43,8 +43,9 @@
+ #include "xfs_rw.h"
+ #include "xfs_quota.h"
+ #include "xfs_fsops.h"
++#include "xfs_utils.h"
+ 
+-STATIC void	xfs_mount_log_sb(xfs_mount_t *, __int64_t);
++STATIC int	xfs_mount_log_sb(xfs_mount_t *, __int64_t);
+ STATIC int	xfs_uuid_mount(xfs_mount_t *);
+ STATIC void	xfs_uuid_unmount(xfs_mount_t *mp);
+ STATIC void	xfs_unmountfs_wait(xfs_mount_t *);
+@@ -57,7 +58,7 @@ STATIC void	xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
+ STATIC void	xfs_icsb_sync_counters(xfs_mount_t *);
+ STATIC int	xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t,
+ 						int64_t, int);
+-STATIC int	xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
++STATIC void	xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
+ 
+ #else
+ 
+@@ -956,7 +957,6 @@ xfs_mountfs(
+ {
+ 	xfs_sb_t	*sbp = &(mp->m_sb);
+ 	xfs_inode_t	*rip;
+-	bhv_vnode_t	*rvp = NULL;
+ 	__uint64_t	resblks;
+ 	__int64_t	update_flags = 0LL;
+ 	uint		quotamount, quotaflags;
+@@ -964,11 +964,6 @@ xfs_mountfs(
+ 	int		uuid_mounted = 0;
+ 	int		error = 0;
+ 
+-	if (mp->m_sb_bp == NULL) {
+-		error = xfs_readsb(mp, mfsi_flags);
+-		if (error)
+-			return error;
+-	}
+ 	xfs_mount_common(mp, sbp);
+ 
+ 	/*
+@@ -1163,7 +1158,6 @@ xfs_mountfs(
+ 	}
+ 
+ 	ASSERT(rip != NULL);
+-	rvp = XFS_ITOV(rip);
+ 
+ 	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
+ 		cmn_err(CE_WARN, "XFS: corrupted root inode");
+@@ -1195,8 +1189,13 @@ xfs_mountfs(
+ 	/*
+ 	 * If fs is not mounted readonly, then update the superblock changes.
+ 	 */
+-	if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY))
+-		xfs_mount_log_sb(mp, update_flags);
++	if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
++		error = xfs_mount_log_sb(mp, update_flags);
++		if (error) {
++			cmn_err(CE_WARN, "XFS: failed to write sb changes");
++			goto error4;
++		}
++	}
+ 
+ 	/*
+ 	 * Initialise the XFS quota management subsystem for this mount
+@@ -1233,12 +1232,15 @@ xfs_mountfs(
+ 	 *
+ 	 * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
+ 	 * This may drive us straight to ENOSPC on mount, but that implies
+-	 * we were already there on the last unmount.
++	 * we were already there on the last unmount. Warn if this occurs.
+ 	 */
+ 	resblks = mp->m_sb.sb_dblocks;
+ 	do_div(resblks, 20);
+ 	resblks = min_t(__uint64_t, resblks, 1024);
+-	xfs_reserve_blocks(mp, &resblks, NULL);
++	error = xfs_reserve_blocks(mp, &resblks, NULL);
++	if (error)
++		cmn_err(CE_WARN, "XFS: Unable to allocate reserve blocks. "
++				"Continuing without a reserve pool.");
+ 
+ 	return 0;
+ 
+@@ -1246,7 +1248,7 @@ xfs_mountfs(
+ 	/*
+ 	 * Free up the root inode.
+ 	 */
+-	VN_RELE(rvp);
++	IRELE(rip);
+  error3:
+ 	xfs_log_unmount_dealloc(mp);
+  error2:
+@@ -1274,6 +1276,7 @@ int
+ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
+ {
+ 	__uint64_t	resblks;
++	int		error = 0;
+ 
+ 	/*
+ 	 * We can potentially deadlock here if we have an inode cluster
+@@ -1317,9 +1320,15 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
+ 	 * value does not matter....
+ 	 */
+ 	resblks = 0;
+-	xfs_reserve_blocks(mp, &resblks, NULL);
++	error = xfs_reserve_blocks(mp, &resblks, NULL);
++	if (error)
++		cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. "
++				"Freespace may not be correct on next mount.");
+ 
+-	xfs_log_sbcount(mp, 1);
++	error = xfs_log_sbcount(mp, 1);
++	if (error)
++		cmn_err(CE_WARN, "XFS: Unable to update superblock counters. "
++				"Freespace may not be correct on next mount.");
+ 	xfs_unmountfs_writesb(mp);
+ 	xfs_unmountfs_wait(mp); 		/* wait for async bufs */
+ 	xfs_log_unmount(mp);			/* Done! No more fs ops. */
+@@ -1411,9 +1420,8 @@ xfs_log_sbcount(
+ 	xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
+ 	if (sync)
+ 		xfs_trans_set_sync(tp);
+-	xfs_trans_commit(tp, 0);
+-
+-	return 0;
++	error = xfs_trans_commit(tp, 0);
++	return error;
+ }
+ 
+ STATIC void
+@@ -1462,7 +1470,6 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
+ 		XFS_BUF_UNASYNC(sbp);
+ 		ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp);
+ 		xfsbdstrat(mp, sbp);
+-		/* Nevermind errors we might get here. */
+ 		error = xfs_iowait(sbp);
+ 		if (error)
+ 			xfs_ioerror_alert("xfs_unmountfs_writesb",
+@@ -1911,24 +1918,27 @@ xfs_uuid_unmount(
+  * be altered by the mount options, as well as any potential sb_features2
+  * fixup. Only the first superblock is updated.
+  */
+-STATIC void
++STATIC int
+ xfs_mount_log_sb(
+ 	xfs_mount_t	*mp,
+ 	__int64_t	fields)
+ {
+ 	xfs_trans_t	*tp;
++	int		error;
+ 
+ 	ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
+ 			 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2));
+ 
+ 	tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
+-	if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
+-				XFS_DEFAULT_LOG_COUNT)) {
++	error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
++				XFS_DEFAULT_LOG_COUNT);
++	if (error) {
+ 		xfs_trans_cancel(tp, 0);
+-		return;
++		return error;
+ 	}
+ 	xfs_mod_sb(tp, fields);
+-	xfs_trans_commit(tp, 0);
++	error = xfs_trans_commit(tp, 0);
++	return error;
+ }
+ 
+ 
+@@ -2189,7 +2199,7 @@ xfs_icsb_counter_disabled(
+ 	return test_bit(field, &mp->m_icsb_counters);
+ }
+ 
+-STATIC int
++STATIC void
+ xfs_icsb_disable_counter(
+ 	xfs_mount_t	*mp,
+ 	xfs_sb_field_t	field)
+@@ -2207,7 +2217,7 @@ xfs_icsb_disable_counter(
+ 	 * the m_icsb_mutex.
+ 	 */
+ 	if (xfs_icsb_counter_disabled(mp, field))
+-		return 0;
++		return;
+ 
+ 	xfs_icsb_lock_all_counters(mp);
+ 	if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
+@@ -2230,8 +2240,6 @@ xfs_icsb_disable_counter(
+ 	}
+ 
+ 	xfs_icsb_unlock_all_counters(mp);
+-
+-	return 0;
+ }
+ 
+ STATIC void
+diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
+index 1d8a472..1ed5751 100644
+--- a/fs/xfs/xfs_mount.h
++++ b/fs/xfs/xfs_mount.h
+@@ -66,17 +66,17 @@ struct xfs_mru_cache;
+  * Prototypes and functions for the Data Migration subsystem.
+  */
+ 
+-typedef int	(*xfs_send_data_t)(int, bhv_vnode_t *,
+-			xfs_off_t, size_t, int, bhv_vrwlock_t *);
++typedef int	(*xfs_send_data_t)(int, struct xfs_inode *,
++			xfs_off_t, size_t, int, int *);
+ typedef int	(*xfs_send_mmap_t)(struct vm_area_struct *, uint);
+-typedef int	(*xfs_send_destroy_t)(bhv_vnode_t *, dm_right_t);
++typedef int	(*xfs_send_destroy_t)(struct xfs_inode *, dm_right_t);
+ typedef int	(*xfs_send_namesp_t)(dm_eventtype_t, struct xfs_mount *,
+-			bhv_vnode_t *,
+-			dm_right_t, bhv_vnode_t *, dm_right_t,
+-			char *, char *, mode_t, int, int);
++			struct xfs_inode *, dm_right_t,
++			struct xfs_inode *, dm_right_t,
++			const char *, const char *, mode_t, int, int);
+ typedef int	(*xfs_send_mount_t)(struct xfs_mount *, dm_right_t,
+ 			char *, char *);
+-typedef void	(*xfs_send_unmount_t)(struct xfs_mount *, bhv_vnode_t *,
++typedef void	(*xfs_send_unmount_t)(struct xfs_mount *, struct xfs_inode *,
+ 			dm_right_t, mode_t, int, int);
+ 
+ typedef struct xfs_dmops {
+@@ -88,20 +88,20 @@ typedef struct xfs_dmops {
+ 	xfs_send_unmount_t	xfs_send_unmount;
+ } xfs_dmops_t;
+ 
+-#define XFS_SEND_DATA(mp, ev,vp,off,len,fl,lock) \
+-	(*(mp)->m_dm_ops->xfs_send_data)(ev,vp,off,len,fl,lock)
++#define XFS_SEND_DATA(mp, ev,ip,off,len,fl,lock) \
++	(*(mp)->m_dm_ops->xfs_send_data)(ev,ip,off,len,fl,lock)
+ #define XFS_SEND_MMAP(mp, vma,fl) \
+ 	(*(mp)->m_dm_ops->xfs_send_mmap)(vma,fl)
+-#define XFS_SEND_DESTROY(mp, vp,right) \
+-	(*(mp)->m_dm_ops->xfs_send_destroy)(vp,right)
++#define XFS_SEND_DESTROY(mp, ip,right) \
++	(*(mp)->m_dm_ops->xfs_send_destroy)(ip,right)
+ #define XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
+ 	(*(mp)->m_dm_ops->xfs_send_namesp)(ev,NULL,b1,r1,b2,r2,n1,n2,mode,rval,fl)
+ #define XFS_SEND_PREUNMOUNT(mp,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
+ 	(*(mp)->m_dm_ops->xfs_send_namesp)(DM_EVENT_PREUNMOUNT,mp,b1,r1,b2,r2,n1,n2,mode,rval,fl)
+ #define XFS_SEND_MOUNT(mp,right,path,name) \
+ 	(*(mp)->m_dm_ops->xfs_send_mount)(mp,right,path,name)
+-#define XFS_SEND_UNMOUNT(mp, vp,right,mode,rval,fl) \
+-	(*(mp)->m_dm_ops->xfs_send_unmount)(mp,vp,right,mode,rval,fl)
++#define XFS_SEND_UNMOUNT(mp, ip,right,mode,rval,fl) \
++	(*(mp)->m_dm_ops->xfs_send_unmount)(mp,ip,right,mode,rval,fl)
+ 
+ 
+ /*
+@@ -220,7 +220,7 @@ extern void	xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
+ #endif
+ 
+ typedef struct xfs_ail {
+-	xfs_ail_entry_t		xa_ail;
++	struct list_head	xa_ail;
+ 	uint			xa_gen;
+ 	struct task_struct	*xa_task;
+ 	xfs_lsn_t		xa_target;
+@@ -401,7 +401,7 @@ typedef struct xfs_mount {
+ 
+ /*
+  * Allow large block sizes to be reported to userspace programs if the
+- * "largeio" mount option is used. 
++ * "largeio" mount option is used.
+  *
+  * If compatibility mode is specified, simply return the basic unit of caching
+  * so that we don't get inefficient read/modify/write I/O from user apps.
+diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
+index 7eb157a..ee37189 100644
+--- a/fs/xfs/xfs_rename.c
++++ b/fs/xfs/xfs_rename.c
+@@ -36,7 +36,6 @@
+ #include "xfs_bmap.h"
+ #include "xfs_error.h"
+ #include "xfs_quota.h"
+-#include "xfs_refcache.h"
+ #include "xfs_utils.h"
+ #include "xfs_trans_space.h"
+ #include "xfs_vnodeops.h"
+@@ -84,25 +83,23 @@ int xfs_rename_skip, xfs_rename_nskip;
+  */
+ STATIC int
+ xfs_lock_for_rename(
+-	xfs_inode_t	*dp1,	/* old (source) directory inode */
+-	xfs_inode_t	*dp2,	/* new (target) directory inode */
+-	bhv_vname_t	*vname1,/* old entry name */
+-	bhv_vname_t	*vname2,/* new entry name */
+-	xfs_inode_t	**ipp1,	/* inode of old entry */
+-	xfs_inode_t	**ipp2,	/* inode of new entry, if it
++	xfs_inode_t	*dp1,	/* in: old (source) directory inode */
++	xfs_inode_t	*dp2,	/* in: new (target) directory inode */
++	xfs_inode_t	*ip1,	/* in: inode of old entry */
++	struct xfs_name	*name2,	/* in: new entry name */
++	xfs_inode_t	**ipp2,	/* out: inode of new entry, if it
+ 				   already exists, NULL otherwise. */
+-	xfs_inode_t	**i_tab,/* array of inode returned, sorted */
+-	int		*num_inodes)  /* number of inodes in array */
++	xfs_inode_t	**i_tab,/* out: array of inode returned, sorted */
++	int		*num_inodes)  /* out: number of inodes in array */
+ {
+-	xfs_inode_t		*ip1, *ip2, *temp;
++	xfs_inode_t		*ip2 = NULL;
++	xfs_inode_t		*temp;
+ 	xfs_ino_t		inum1, inum2;
+ 	int			error;
+ 	int			i, j;
+ 	uint			lock_mode;
+ 	int			diff_dirs = (dp1 != dp2);
+ 
+-	ip2 = NULL;
+-
+ 	/*
+ 	 * First, find out the current inums of the entries so that we
+ 	 * can determine the initial locking order.  We'll have to
+@@ -110,27 +107,20 @@ xfs_lock_for_rename(
+ 	 * to see if we still have the right inodes, directories, etc.
+ 	 */
+ 	lock_mode = xfs_ilock_map_shared(dp1);
+-	error = xfs_get_dir_entry(vname1, &ip1);
+-	if (error) {
+-		xfs_iunlock_map_shared(dp1, lock_mode);
+-		return error;
+-	}
++	IHOLD(ip1);
++	xfs_itrace_ref(ip1);
+ 
+ 	inum1 = ip1->i_ino;
+ 
+-	ASSERT(ip1);
+-	xfs_itrace_ref(ip1);
+-
+ 	/*
+ 	 * Unlock dp1 and lock dp2 if they are different.
+ 	 */
+-
+ 	if (diff_dirs) {
+ 		xfs_iunlock_map_shared(dp1, lock_mode);
+ 		lock_mode = xfs_ilock_map_shared(dp2);
+ 	}
+ 
+-	error = xfs_dir_lookup_int(dp2, lock_mode, vname2, &inum2, &ip2);
++	error = xfs_dir_lookup_int(dp2, lock_mode, name2, &inum2, &ip2);
+ 	if (error == ENOENT) {		/* target does not need to exist. */
+ 		inum2 = 0;
+ 	} else if (error) {
+@@ -162,6 +152,7 @@ xfs_lock_for_rename(
+ 		*num_inodes = 4;
+ 		i_tab[3] = ip2;
+ 	}
++	*ipp2 = i_tab[3];
+ 
+ 	/*
+ 	 * Sort the elements via bubble sort.  (Remember, there are at
+@@ -199,21 +190,6 @@ xfs_lock_for_rename(
+ 		xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED);
+ 	}
+ 
+-	/*
+-	 * Set the return value. Null out any unused entries in i_tab.
+-	 */
+-	*ipp1 = *ipp2 = NULL;
+-	for (i=0; i < *num_inodes; i++) {
+-		if (i_tab[i]->i_ino == inum1) {
+-			*ipp1 = i_tab[i];
+-		}
+-		if (i_tab[i]->i_ino == inum2) {
+-			*ipp2 = i_tab[i];
+-		}
+-	}
+-	for (;i < 4; i++) {
+-		i_tab[i] = NULL;
+-	}
+ 	return 0;
+ }
+ 
+@@ -223,13 +199,13 @@ xfs_lock_for_rename(
+ int
+ xfs_rename(
+ 	xfs_inode_t	*src_dp,
+-	bhv_vname_t	*src_vname,
+-	bhv_vnode_t	*target_dir_vp,
+-	bhv_vname_t	*target_vname)
++	struct xfs_name	*src_name,
++	xfs_inode_t	*src_ip,
++	xfs_inode_t	*target_dp,
++	struct xfs_name	*target_name)
+ {
+-	bhv_vnode_t	*src_dir_vp = XFS_ITOV(src_dp);
+ 	xfs_trans_t	*tp;
+-	xfs_inode_t	*target_dp, *src_ip, *target_ip;
++	xfs_inode_t	*target_ip;
+ 	xfs_mount_t	*mp = src_dp->i_mount;
+ 	int		new_parent;		/* moving to a new dir */
+ 	int		src_is_directory;	/* src_name is a directory */
+@@ -243,29 +219,16 @@ xfs_rename(
+ 	int		spaceres;
+ 	int		target_link_zero = 0;
+ 	int		num_inodes;
+-	char		*src_name = VNAME(src_vname);
+-	char		*target_name = VNAME(target_vname);
+-	int		src_namelen = VNAMELEN(src_vname);
+-	int		target_namelen = VNAMELEN(target_vname);
+ 
+ 	xfs_itrace_entry(src_dp);
+-	xfs_itrace_entry(xfs_vtoi(target_dir_vp));
+-
+-	/*
+-	 * Find the XFS behavior descriptor for the target directory
+-	 * vnode since it was not handed to us.
+-	 */
+-	target_dp = xfs_vtoi(target_dir_vp);
+-	if (target_dp == NULL) {
+-		return XFS_ERROR(EXDEV);
+-	}
++	xfs_itrace_entry(target_dp);
+ 
+ 	if (DM_EVENT_ENABLED(src_dp, DM_EVENT_RENAME) ||
+ 	    DM_EVENT_ENABLED(target_dp, DM_EVENT_RENAME)) {
+ 		error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME,
+-					src_dir_vp, DM_RIGHT_NULL,
+-					target_dir_vp, DM_RIGHT_NULL,
+-					src_name, target_name,
++					src_dp, DM_RIGHT_NULL,
++					target_dp, DM_RIGHT_NULL,
++					src_name->name, target_name->name,
+ 					0, 0, 0);
+ 		if (error) {
+ 			return error;
+@@ -282,10 +245,8 @@ xfs_rename(
+ 	 * does not exist in the source directory.
+ 	 */
+ 	tp = NULL;
+-	error = xfs_lock_for_rename(src_dp, target_dp, src_vname,
+-			target_vname, &src_ip, &target_ip, inodes,
+-			&num_inodes);
+-
++	error = xfs_lock_for_rename(src_dp, target_dp, src_ip, target_name,
++					&target_ip, inodes, &num_inodes);
+ 	if (error) {
+ 		/*
+ 		 * We have nothing locked, no inode references, and
+@@ -331,7 +292,7 @@ xfs_rename(
+ 	XFS_BMAP_INIT(&free_list, &first_block);
+ 	tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME);
+ 	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+-	spaceres = XFS_RENAME_SPACE_RES(mp, target_namelen);
++	spaceres = XFS_RENAME_SPACE_RES(mp, target_name->len);
+ 	error = xfs_trans_reserve(tp, spaceres, XFS_RENAME_LOG_RES(mp), 0,
+ 			XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT);
+ 	if (error == ENOSPC) {
+@@ -365,10 +326,10 @@ xfs_rename(
+ 	 * them when they unlock the inodes.  Also, we need to be careful
+ 	 * not to add an inode to the transaction more than once.
+ 	 */
+-	VN_HOLD(src_dir_vp);
++	IHOLD(src_dp);
+ 	xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL);
+ 	if (new_parent) {
+-		VN_HOLD(target_dir_vp);
++		IHOLD(target_dp);
+ 		xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL);
+ 	}
+ 	if ((src_ip != src_dp) && (src_ip != target_dp)) {
+@@ -389,9 +350,8 @@ xfs_rename(
+ 		 * If there's no space reservation, check the entry will
+ 		 * fit before actually inserting it.
+ 		 */
+-		if (spaceres == 0 &&
+-		    (error = xfs_dir_canenter(tp, target_dp, target_name,
+-						target_namelen)))
++		error = xfs_dir_canenter(tp, target_dp, target_name, spaceres);
++		if (error)
+ 			goto error_return;
+ 		/*
+ 		 * If target does not exist and the rename crosses
+@@ -399,8 +359,8 @@ xfs_rename(
+ 		 * to account for the ".." reference from the new entry.
+ 		 */
+ 		error = xfs_dir_createname(tp, target_dp, target_name,
+-					   target_namelen, src_ip->i_ino,
+-					   &first_block, &free_list, spaceres);
++						src_ip->i_ino, &first_block,
++						&free_list, spaceres);
+ 		if (error == ENOSPC)
+ 			goto error_return;
+ 		if (error)
+@@ -439,7 +399,7 @@ xfs_rename(
+ 		 * name at the destination directory, remove it first.
+ 		 */
+ 		error = xfs_dir_replace(tp, target_dp, target_name,
+-					target_namelen, src_ip->i_ino,
++					src_ip->i_ino,
+ 					&first_block, &free_list, spaceres);
+ 		if (error)
+ 			goto abort_return;
+@@ -476,7 +436,8 @@ xfs_rename(
+ 		 * Rewrite the ".." entry to point to the new
+ 		 * directory.
+ 		 */
+-		error = xfs_dir_replace(tp, src_ip, "..", 2, target_dp->i_ino,
++		error = xfs_dir_replace(tp, src_ip, &xfs_name_dotdot,
++					target_dp->i_ino,
+ 					&first_block, &free_list, spaceres);
+ 		ASSERT(error != EEXIST);
+ 		if (error)
+@@ -512,8 +473,8 @@ xfs_rename(
+ 			goto abort_return;
+ 	}
+ 
+-	error = xfs_dir_removename(tp, src_dp, src_name, src_namelen,
+-			src_ip->i_ino, &first_block, &free_list, spaceres);
++	error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino,
++					&first_block, &free_list, spaceres);
+ 	if (error)
+ 		goto abort_return;
+ 	xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+@@ -580,10 +541,8 @@ xfs_rename(
+ 	 * the vnode references.
+ 	 */
+ 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+-	if (target_ip != NULL) {
+-		xfs_refcache_purge_ip(target_ip);
++	if (target_ip != NULL)
+ 		IRELE(target_ip);
+-	}
+ 	/*
+ 	 * Let interposed file systems know about removed links.
+ 	 */
+@@ -598,9 +557,9 @@ std_return:
+ 	if (DM_EVENT_ENABLED(src_dp, DM_EVENT_POSTRENAME) ||
+ 	    DM_EVENT_ENABLED(target_dp, DM_EVENT_POSTRENAME)) {
+ 		(void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME,
+-					src_dir_vp, DM_RIGHT_NULL,
+-					target_dir_vp, DM_RIGHT_NULL,
+-					src_name, target_name,
++					src_dp, DM_RIGHT_NULL,
++					target_dp, DM_RIGHT_NULL,
++					src_name->name, target_name->name,
+ 					0, error, 0);
+ 	}
+ 	return error;
+diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
+index 47082c0..a0dc6e5 100644
+--- a/fs/xfs/xfs_rtalloc.c
++++ b/fs/xfs/xfs_rtalloc.c
+@@ -44,6 +44,7 @@
+ #include "xfs_rw.h"
+ #include "xfs_inode_item.h"
+ #include "xfs_trans_space.h"
++#include "xfs_utils.h"
+ 
+ 
+ /*
+@@ -123,14 +124,14 @@ xfs_growfs_rt_alloc(
+ 				XFS_GROWRTALLOC_LOG_RES(mp), 0,
+ 				XFS_TRANS_PERM_LOG_RES,
+ 				XFS_DEFAULT_PERM_LOG_COUNT)))
+-			goto error_exit;
++			goto error_cancel;
+ 		cancelflags = XFS_TRANS_RELEASE_LOG_RES;
+ 		/*
+ 		 * Lock the inode.
+ 		 */
+ 		if ((error = xfs_trans_iget(mp, tp, ino, 0,
+ 						XFS_ILOCK_EXCL, &ip)))
+-			goto error_exit;
++			goto error_cancel;
+ 		XFS_BMAP_INIT(&flist, &firstblock);
+ 		/*
+ 		 * Allocate blocks to the bitmap file.
+@@ -143,14 +144,16 @@ xfs_growfs_rt_alloc(
+ 		if (!error && nmap < 1)
+ 			error = XFS_ERROR(ENOSPC);
+ 		if (error)
+-			goto error_exit;
++			goto error_cancel;
+ 		/*
+ 		 * Free any blocks freed up in the transaction, then commit.
+ 		 */
+ 		error = xfs_bmap_finish(&tp, &flist, &committed);
+ 		if (error)
+-			goto error_exit;
+-		xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++			goto error_cancel;
++		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++		if (error)
++			goto error;
+ 		/*
+ 		 * Now we need to clear the allocated blocks.
+ 		 * Do this one block per transaction, to keep it simple.
+@@ -165,13 +168,13 @@ xfs_growfs_rt_alloc(
+ 			 */
+ 			if ((error = xfs_trans_reserve(tp, 0,
+ 					XFS_GROWRTZERO_LOG_RES(mp), 0, 0, 0)))
+-				goto error_exit;
++				goto error_cancel;
+ 			/*
+ 			 * Lock the bitmap inode.
+ 			 */
+ 			if ((error = xfs_trans_iget(mp, tp, ino, 0,
+ 							XFS_ILOCK_EXCL, &ip)))
+-				goto error_exit;
++				goto error_cancel;
+ 			/*
+ 			 * Get a buffer for the block.
+ 			 */
+@@ -180,14 +183,16 @@ xfs_growfs_rt_alloc(
+ 				mp->m_bsize, 0);
+ 			if (bp == NULL) {
+ 				error = XFS_ERROR(EIO);
+-				goto error_exit;
++				goto error_cancel;
+ 			}
+ 			memset(XFS_BUF_PTR(bp), 0, mp->m_sb.sb_blocksize);
+ 			xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
+ 			/*
+ 			 * Commit the transaction.
+ 			 */
+-			xfs_trans_commit(tp, 0);
++			error = xfs_trans_commit(tp, 0);
++			if (error)
++				goto error;
+ 		}
+ 		/*
+ 		 * Go on to the next extent, if any.
+@@ -195,8 +200,9 @@ xfs_growfs_rt_alloc(
+ 		oblocks = map.br_startoff + map.br_blockcount;
+ 	}
+ 	return 0;
+-error_exit:
++error_cancel:
+ 	xfs_trans_cancel(tp, cancelflags);
++error:
+ 	return error;
+ }
+ 
+@@ -1875,6 +1881,7 @@ xfs_growfs_rt(
+ 	xfs_trans_t	*tp;		/* transaction pointer */
+ 
+ 	sbp = &mp->m_sb;
++	cancelflags = 0;
+ 	/*
+ 	 * Initial error checking.
+ 	 */
+@@ -2041,13 +2048,15 @@ xfs_growfs_rt(
+ 		 */
+ 		mp->m_rsumlevels = nrsumlevels;
+ 		mp->m_rsumsize = nrsumsize;
+-		/*
+-		 * Commit the transaction.
+-		 */
+-		xfs_trans_commit(tp, 0);
++
++		error = xfs_trans_commit(tp, 0);
++		if (error) {
++			tp = NULL;
++			break;
++		}
+ 	}
+ 
+-	if (error)
++	if (error && tp)
+ 		xfs_trans_cancel(tp, cancelflags);
+ 
+ 	/*
+@@ -2278,7 +2287,7 @@ xfs_rtmount_inodes(
+ 	ASSERT(sbp->sb_rsumino != NULLFSINO);
+ 	error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0);
+ 	if (error) {
+-		VN_RELE(XFS_ITOV(mp->m_rbmip));
++		IRELE(mp->m_rbmip);
+ 		return error;
+ 	}
+ 	ASSERT(mp->m_rsumip != NULL);
+diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
+index cd3ece6..b0f31c0 100644
+--- a/fs/xfs/xfs_rw.c
++++ b/fs/xfs/xfs_rw.c
+@@ -126,11 +126,11 @@ xfs_write_sync_logforce(
+ 		 * when we return.
+ 		 */
+ 		if (iip && iip->ili_last_lsn) {
+-			xfs_log_force(mp, iip->ili_last_lsn,
+-					XFS_LOG_FORCE | XFS_LOG_SYNC);
++			error = _xfs_log_force(mp, iip->ili_last_lsn,
++					XFS_LOG_FORCE | XFS_LOG_SYNC, NULL);
+ 		} else if (xfs_ipincount(ip) > 0) {
+-			xfs_log_force(mp, (xfs_lsn_t)0,
+-					XFS_LOG_FORCE | XFS_LOG_SYNC);
++			error = _xfs_log_force(mp, (xfs_lsn_t)0,
++					XFS_LOG_FORCE | XFS_LOG_SYNC, NULL);
+ 		}
+ 
+ 	} else {
+diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
+index 7f40628..0804207 100644
+--- a/fs/xfs/xfs_trans.h
++++ b/fs/xfs/xfs_trans.h
+@@ -113,13 +113,8 @@ struct xfs_mount;
+ struct xfs_trans;
+ struct xfs_dquot_acct;
+ 
+-typedef struct xfs_ail_entry {
+-	struct xfs_log_item	*ail_forw;	/* AIL forw pointer */
+-	struct xfs_log_item	*ail_back;	/* AIL back pointer */
+-} xfs_ail_entry_t;
+-
+ typedef struct xfs_log_item {
+-	xfs_ail_entry_t			li_ail;		/* AIL pointers */
++	struct list_head		li_ail;		/* AIL pointers */
+ 	xfs_lsn_t			li_lsn;		/* last on-disk lsn */
+ 	struct xfs_log_item_desc	*li_desc;	/* ptr to current desc*/
+ 	struct xfs_mount		*li_mountp;	/* ptr to fs mount */
+@@ -341,7 +336,6 @@ typedef struct xfs_trans {
+ 	unsigned int		t_rtx_res;	/* # of rt extents resvd */
+ 	unsigned int		t_rtx_res_used;	/* # of resvd rt extents used */
+ 	xfs_log_ticket_t	t_ticket;	/* log mgr ticket */
+-	sema_t			t_sema;		/* sema for commit completion */
+ 	xfs_lsn_t		t_lsn;		/* log seq num of start of
+ 						 * transaction. */
+ 	xfs_lsn_t		t_commit_lsn;	/* log seq num of end of
+diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
+index 76d470d..1f77c00 100644
+--- a/fs/xfs/xfs_trans_ail.c
++++ b/fs/xfs/xfs_trans_ail.c
+@@ -28,13 +28,13 @@
+ #include "xfs_trans_priv.h"
+ #include "xfs_error.h"
+ 
+-STATIC void xfs_ail_insert(xfs_ail_entry_t *, xfs_log_item_t *);
+-STATIC xfs_log_item_t * xfs_ail_delete(xfs_ail_entry_t *, xfs_log_item_t *);
+-STATIC xfs_log_item_t * xfs_ail_min(xfs_ail_entry_t *);
+-STATIC xfs_log_item_t * xfs_ail_next(xfs_ail_entry_t *, xfs_log_item_t *);
++STATIC void xfs_ail_insert(xfs_ail_t *, xfs_log_item_t *);
++STATIC xfs_log_item_t * xfs_ail_delete(xfs_ail_t *, xfs_log_item_t *);
++STATIC xfs_log_item_t * xfs_ail_min(xfs_ail_t *);
++STATIC xfs_log_item_t * xfs_ail_next(xfs_ail_t *, xfs_log_item_t *);
+ 
+ #ifdef DEBUG
+-STATIC void xfs_ail_check(xfs_ail_entry_t *, xfs_log_item_t *);
++STATIC void xfs_ail_check(xfs_ail_t *, xfs_log_item_t *);
+ #else
+ #define	xfs_ail_check(a,l)
+ #endif /* DEBUG */
+@@ -57,7 +57,7 @@ xfs_trans_tail_ail(
+ 	xfs_log_item_t	*lip;
+ 
+ 	spin_lock(&mp->m_ail_lock);
+-	lip = xfs_ail_min(&(mp->m_ail.xa_ail));
++	lip = xfs_ail_min(&mp->m_ail);
+ 	if (lip == NULL) {
+ 		lsn = (xfs_lsn_t)0;
+ 	} else {
+@@ -91,7 +91,7 @@ xfs_trans_push_ail(
+ {
+ 	xfs_log_item_t		*lip;
+ 
+-	lip = xfs_ail_min(&mp->m_ail.xa_ail);
++	lip = xfs_ail_min(&mp->m_ail);
+ 	if (lip && !XFS_FORCED_SHUTDOWN(mp)) {
+ 		if (XFS_LSN_CMP(threshold_lsn, mp->m_ail.xa_target) > 0)
+ 			xfsaild_wakeup(mp, threshold_lsn);
+@@ -111,15 +111,17 @@ xfs_trans_first_push_ail(
+ {
+ 	xfs_log_item_t	*lip;
+ 
+-	lip = xfs_ail_min(&(mp->m_ail.xa_ail));
++	lip = xfs_ail_min(&mp->m_ail);
+ 	*gen = (int)mp->m_ail.xa_gen;
+ 	if (lsn == 0)
+ 		return lip;
+ 
+-	while (lip && (XFS_LSN_CMP(lip->li_lsn, lsn) < 0))
+-		lip = lip->li_ail.ail_forw;
++	list_for_each_entry(lip, &mp->m_ail.xa_ail, li_ail) {
++		if (XFS_LSN_CMP(lip->li_lsn, lsn) >= 0)
++			return lip;
++	}
+ 
+-	return lip;
++	return NULL;
+ }
+ 
+ /*
+@@ -329,7 +331,7 @@ xfs_trans_unlocked_item(
+ 	 * the call to xfs_log_move_tail() doesn't do anything if there's
+ 	 * not enough free space to wake people up so we're safe calling it.
+ 	 */
+-	min_lip = xfs_ail_min(&mp->m_ail.xa_ail);
++	min_lip = xfs_ail_min(&mp->m_ail);
+ 
+ 	if (min_lip == lip)
+ 		xfs_log_move_tail(mp, 1);
+@@ -357,15 +359,13 @@ xfs_trans_update_ail(
+ 	xfs_log_item_t	*lip,
+ 	xfs_lsn_t	lsn) __releases(mp->m_ail_lock)
+ {
+-	xfs_ail_entry_t		*ailp;
+ 	xfs_log_item_t		*dlip=NULL;
+ 	xfs_log_item_t		*mlip;	/* ptr to minimum lip */
+ 
+-	ailp = &(mp->m_ail.xa_ail);
+-	mlip = xfs_ail_min(ailp);
++	mlip = xfs_ail_min(&mp->m_ail);
+ 
+ 	if (lip->li_flags & XFS_LI_IN_AIL) {
+-		dlip = xfs_ail_delete(ailp, lip);
++		dlip = xfs_ail_delete(&mp->m_ail, lip);
+ 		ASSERT(dlip == lip);
+ 	} else {
+ 		lip->li_flags |= XFS_LI_IN_AIL;
+@@ -373,11 +373,11 @@ xfs_trans_update_ail(
+ 
+ 	lip->li_lsn = lsn;
+ 
+-	xfs_ail_insert(ailp, lip);
++	xfs_ail_insert(&mp->m_ail, lip);
+ 	mp->m_ail.xa_gen++;
+ 
+ 	if (mlip == dlip) {
+-		mlip = xfs_ail_min(&(mp->m_ail.xa_ail));
++		mlip = xfs_ail_min(&mp->m_ail);
+ 		spin_unlock(&mp->m_ail_lock);
+ 		xfs_log_move_tail(mp, mlip->li_lsn);
+ 	} else {
+@@ -407,14 +407,12 @@ xfs_trans_delete_ail(
+ 	xfs_mount_t	*mp,
+ 	xfs_log_item_t	*lip) __releases(mp->m_ail_lock)
+ {
+-	xfs_ail_entry_t		*ailp;
+ 	xfs_log_item_t		*dlip;
+ 	xfs_log_item_t		*mlip;
+ 
+ 	if (lip->li_flags & XFS_LI_IN_AIL) {
+-		ailp = &(mp->m_ail.xa_ail);
+-		mlip = xfs_ail_min(ailp);
+-		dlip = xfs_ail_delete(ailp, lip);
++		mlip = xfs_ail_min(&mp->m_ail);
++		dlip = xfs_ail_delete(&mp->m_ail, lip);
+ 		ASSERT(dlip == lip);
+ 
+ 
+@@ -423,7 +421,7 @@ xfs_trans_delete_ail(
+ 		mp->m_ail.xa_gen++;
+ 
+ 		if (mlip == dlip) {
+-			mlip = xfs_ail_min(&(mp->m_ail.xa_ail));
++			mlip = xfs_ail_min(&mp->m_ail);
+ 			spin_unlock(&mp->m_ail_lock);
+ 			xfs_log_move_tail(mp, (mlip ? mlip->li_lsn : 0));
+ 		} else {
+@@ -440,7 +438,7 @@ xfs_trans_delete_ail(
+ 		else {
+ 			xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
+ 		"%s: attempting to delete a log item that is not in the AIL",
+-					__FUNCTION__);
++					__func__);
+ 			spin_unlock(&mp->m_ail_lock);
+ 			xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+ 		}
+@@ -461,7 +459,7 @@ xfs_trans_first_ail(
+ {
+ 	xfs_log_item_t	*lip;
+ 
+-	lip = xfs_ail_min(&(mp->m_ail.xa_ail));
++	lip = xfs_ail_min(&mp->m_ail);
+ 	*gen = (int)mp->m_ail.xa_gen;
+ 
+ 	return lip;
+@@ -485,9 +483,9 @@ xfs_trans_next_ail(
+ 
+ 	ASSERT(mp && lip && gen);
+ 	if (mp->m_ail.xa_gen == *gen) {
+-		nlip = xfs_ail_next(&(mp->m_ail.xa_ail), lip);
++		nlip = xfs_ail_next(&mp->m_ail, lip);
+ 	} else {
+-		nlip = xfs_ail_min(&(mp->m_ail).xa_ail);
++		nlip = xfs_ail_min(&mp->m_ail);
+ 		*gen = (int)mp->m_ail.xa_gen;
+ 		if (restarts != NULL) {
+ 			XFS_STATS_INC(xs_push_ail_restarts);
+@@ -517,8 +515,7 @@ int
+ xfs_trans_ail_init(
+ 	xfs_mount_t	*mp)
+ {
+-	mp->m_ail.xa_ail.ail_forw = (xfs_log_item_t*)&mp->m_ail.xa_ail;
+-	mp->m_ail.xa_ail.ail_back = (xfs_log_item_t*)&mp->m_ail.xa_ail;
++	INIT_LIST_HEAD(&mp->m_ail.xa_ail);
+ 	return xfsaild_start(mp);
+ }
+ 
+@@ -537,7 +534,7 @@ xfs_trans_ail_destroy(
+  */
+ STATIC void
+ xfs_ail_insert(
+-	xfs_ail_entry_t	*base,
++	xfs_ail_t	*ailp,
+ 	xfs_log_item_t	*lip)
+ /* ARGSUSED */
+ {
+@@ -546,27 +543,22 @@ xfs_ail_insert(
+ 	/*
+ 	 * If the list is empty, just insert the item.
+ 	 */
+-	if (base->ail_back == (xfs_log_item_t*)base) {
+-		base->ail_forw = lip;
+-		base->ail_back = lip;
+-		lip->li_ail.ail_forw = (xfs_log_item_t*)base;
+-		lip->li_ail.ail_back = (xfs_log_item_t*)base;
++	if (list_empty(&ailp->xa_ail)) {
++		list_add(&lip->li_ail, &ailp->xa_ail);
+ 		return;
+ 	}
+ 
+-	next_lip = base->ail_back;
+-	while ((next_lip != (xfs_log_item_t*)base) &&
+-	       (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) > 0)) {
+-		next_lip = next_lip->li_ail.ail_back;
++	list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) {
++		if (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0)
++			break;
+ 	}
+-	ASSERT((next_lip == (xfs_log_item_t*)base) ||
++
++	ASSERT((&next_lip->li_ail == &ailp->xa_ail) ||
+ 	       (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0));
+-	lip->li_ail.ail_forw = next_lip->li_ail.ail_forw;
+-	lip->li_ail.ail_back = next_lip;
+-	next_lip->li_ail.ail_forw = lip;
+-	lip->li_ail.ail_forw->li_ail.ail_back = lip;
+ 
+-	xfs_ail_check(base, lip);
++	list_add(&lip->li_ail, &next_lip->li_ail);
++
++	xfs_ail_check(ailp, lip);
+ 	return;
+ }
+ 
+@@ -576,15 +568,13 @@ xfs_ail_insert(
+ /*ARGSUSED*/
+ STATIC xfs_log_item_t *
+ xfs_ail_delete(
+-	xfs_ail_entry_t	*base,
++	xfs_ail_t	*ailp,
+ 	xfs_log_item_t	*lip)
+ /* ARGSUSED */
+ {
+-	xfs_ail_check(base, lip);
+-	lip->li_ail.ail_forw->li_ail.ail_back = lip->li_ail.ail_back;
+-	lip->li_ail.ail_back->li_ail.ail_forw = lip->li_ail.ail_forw;
+-	lip->li_ail.ail_forw = NULL;
+-	lip->li_ail.ail_back = NULL;
++	xfs_ail_check(ailp, lip);
++
++	list_del(&lip->li_ail);
+ 
+ 	return lip;
+ }
+@@ -595,14 +585,13 @@ xfs_ail_delete(
+  */
+ STATIC xfs_log_item_t *
+ xfs_ail_min(
+-	xfs_ail_entry_t	*base)
++	xfs_ail_t	*ailp)
+ /* ARGSUSED */
+ {
+-	register xfs_log_item_t *forw = base->ail_forw;
+-	if (forw == (xfs_log_item_t*)base) {
++	if (list_empty(&ailp->xa_ail))
+ 		return NULL;
+-	}
+-	return forw;
++
++	return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
+ }
+ 
+ /*
+@@ -612,15 +601,14 @@ xfs_ail_min(
+  */
+ STATIC xfs_log_item_t *
+ xfs_ail_next(
+-	xfs_ail_entry_t	*base,
++	xfs_ail_t	*ailp,
+ 	xfs_log_item_t	*lip)
+ /* ARGSUSED */
+ {
+-	if (lip->li_ail.ail_forw == (xfs_log_item_t*)base) {
++	if (lip->li_ail.next == &ailp->xa_ail)
+ 		return NULL;
+-	}
+-	return lip->li_ail.ail_forw;
+ 
++	return list_first_entry(&lip->li_ail, xfs_log_item_t, li_ail);
+ }
+ 
+ #ifdef DEBUG
+@@ -629,57 +617,40 @@ xfs_ail_next(
+  */
+ STATIC void
+ xfs_ail_check(
+-	xfs_ail_entry_t *base,
++	xfs_ail_t 	*ailp,
+ 	xfs_log_item_t	*lip)
+ {
+ 	xfs_log_item_t	*prev_lip;
+ 
+-	prev_lip = base->ail_forw;
+-	if (prev_lip == (xfs_log_item_t*)base) {
+-		/*
+-		 * Make sure the pointers are correct when the list
+-		 * is empty.
+-		 */
+-		ASSERT(base->ail_back == (xfs_log_item_t*)base);
++	if (list_empty(&ailp->xa_ail))
+ 		return;
+-	}
+ 
+ 	/*
+ 	 * Check the next and previous entries are valid.
+ 	 */
+ 	ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
+-	prev_lip = lip->li_ail.ail_back;
+-	if (prev_lip != (xfs_log_item_t*)base) {
+-		ASSERT(prev_lip->li_ail.ail_forw == lip);
++	prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail);
++	if (&prev_lip->li_ail != &ailp->xa_ail)
+ 		ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
+-	}
+-	prev_lip = lip->li_ail.ail_forw;
+-	if (prev_lip != (xfs_log_item_t*)base) {
+-		ASSERT(prev_lip->li_ail.ail_back == lip);
++
++	prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail);
++	if (&prev_lip->li_ail != &ailp->xa_ail)
+ 		ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0);
+-	}
+ 
+ 
+ #ifdef XFS_TRANS_DEBUG
+ 	/*
+-	 * Walk the list checking forward and backward pointers,
+-	 * lsn ordering, and that every entry has the XFS_LI_IN_AIL
+-	 * flag set. This is really expensive, so only do it when
+-	 * specifically debugging the transaction subsystem.
++	 * Walk the list checking lsn ordering, and that every entry has the
++	 * XFS_LI_IN_AIL flag set. This is really expensive, so only do it
++	 * when specifically debugging the transaction subsystem.
+ 	 */
+-	prev_lip = (xfs_log_item_t*)base;
+-	while (lip != (xfs_log_item_t*)base) {
+-		if (prev_lip != (xfs_log_item_t*)base) {
+-			ASSERT(prev_lip->li_ail.ail_forw == lip);
++	prev_lip = list_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
++	list_for_each_entry(lip, &ailp->xa_ail, li_ail) {
++		if (&prev_lip->li_ail != &ailp->xa_ail)
+ 			ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
+-		}
+-		ASSERT(lip->li_ail.ail_back == prev_lip);
+ 		ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
+ 		prev_lip = lip;
+-		lip = lip->li_ail.ail_forw;
+ 	}
+-	ASSERT(lip == (xfs_log_item_t*)base);
+-	ASSERT(base->ail_back == prev_lip);
+ #endif /* XFS_TRANS_DEBUG */
+ }
+ #endif /* DEBUG */
+diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
+index 60b6b89..cb0c583 100644
+--- a/fs/xfs/xfs_trans_buf.c
++++ b/fs/xfs/xfs_trans_buf.c
+@@ -304,7 +304,8 @@ xfs_trans_read_buf(
+ 	if (tp == NULL) {
+ 		bp = xfs_buf_read_flags(target, blkno, len, flags | BUF_BUSY);
+ 		if (!bp)
+-			return XFS_ERROR(ENOMEM);
++			return (flags & XFS_BUF_TRYLOCK) ?
++					EAGAIN : XFS_ERROR(ENOMEM);
+ 
+ 		if ((bp != NULL) && (XFS_BUF_GETERROR(bp) != 0)) {
+ 			xfs_ioerror_alert("xfs_trans_read_buf", mp,
+@@ -353,17 +354,15 @@ xfs_trans_read_buf(
+ 			ASSERT(!XFS_BUF_ISASYNC(bp));
+ 			XFS_BUF_READ(bp);
+ 			xfsbdstrat(tp->t_mountp, bp);
+-			xfs_iowait(bp);
+-			if (XFS_BUF_GETERROR(bp) != 0) {
++			error = xfs_iowait(bp);
++			if (error) {
+ 				xfs_ioerror_alert("xfs_trans_read_buf", mp,
+ 						  bp, blkno);
+-				error = XFS_BUF_GETERROR(bp);
+ 				xfs_buf_relse(bp);
+ 				/*
+-				 * We can gracefully recover from most
+-				 * read errors. Ones we can't are those
+-				 * that happen after the transaction's
+-				 * already dirty.
++				 * We can gracefully recover from most read
++				 * errors. Ones we can't are those that happen
++				 * after the transaction's already dirty.
+ 				 */
+ 				if (tp->t_flags & XFS_TRANS_DIRTY)
+ 					xfs_force_shutdown(tp->t_mountp,
+diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
+index 5c89be4..0f51916 100644
+--- a/fs/xfs/xfs_types.h
++++ b/fs/xfs/xfs_types.h
+@@ -160,4 +160,9 @@ typedef enum {
+ 	XFS_BTNUM_MAX
+ } xfs_btnum_t;
+ 
++struct xfs_name {
++	const char	*name;
++	int		len;
++};
++
+ #endif	/* __XFS_TYPES_H__ */
+diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
+index 18a85e7..2b8dc7e 100644
+--- a/fs/xfs/xfs_utils.c
++++ b/fs/xfs/xfs_utils.c
+@@ -40,34 +40,12 @@
+ #include "xfs_itable.h"
+ #include "xfs_utils.h"
+ 
+-/*
+- * xfs_get_dir_entry is used to get a reference to an inode given
+- * its parent directory inode and the name of the file.	 It does
+- * not lock the child inode, and it unlocks the directory before
+- * returning.  The directory's generation number is returned for
+- * use by a later call to xfs_lock_dir_and_entry.
+- */
+-int
+-xfs_get_dir_entry(
+-	bhv_vname_t	*dentry,
+-	xfs_inode_t	**ipp)
+-{
+-	bhv_vnode_t	*vp;
+-
+-	vp = VNAME_TO_VNODE(dentry);
+-
+-	*ipp = xfs_vtoi(vp);
+-	if (!*ipp)
+-		return XFS_ERROR(ENOENT);
+-	VN_HOLD(vp);
+-	return 0;
+-}
+ 
+ int
+ xfs_dir_lookup_int(
+ 	xfs_inode_t	*dp,
+ 	uint		lock_mode,
+-	bhv_vname_t	*dentry,
++	struct xfs_name	*name,
+ 	xfs_ino_t	*inum,
+ 	xfs_inode_t	**ipp)
+ {
+@@ -75,7 +53,7 @@ xfs_dir_lookup_int(
+ 
+ 	xfs_itrace_entry(dp);
+ 
+-	error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum);
++	error = xfs_dir_lookup(NULL, dp, name, inum);
+ 	if (!error) {
+ 		/*
+ 		 * Unlock the directory. We do this because we can't
+diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
+index f857fcc..175b126 100644
+--- a/fs/xfs/xfs_utils.h
++++ b/fs/xfs/xfs_utils.h
+@@ -21,15 +21,14 @@
+ #define IRELE(ip)	VN_RELE(XFS_ITOV(ip))
+ #define IHOLD(ip)	VN_HOLD(XFS_ITOV(ip))
+ 
+-extern int xfs_get_dir_entry (bhv_vname_t *, xfs_inode_t **);
+-extern int xfs_dir_lookup_int (xfs_inode_t *, uint, bhv_vname_t *, xfs_ino_t *,
+-				xfs_inode_t **);
+-extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
+-extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
++extern int xfs_dir_lookup_int(xfs_inode_t *, uint, struct xfs_name *,
++				xfs_ino_t *, xfs_inode_t **);
++extern int xfs_truncate_file(xfs_mount_t *, xfs_inode_t *);
++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 *);
+-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 *);
++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 *);
+ 
+ #endif	/* __XFS_UTILS_H__ */
+diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
+index 7094caf..fc48158 100644
+--- a/fs/xfs/xfs_vfsops.c
++++ b/fs/xfs/xfs_vfsops.c
+@@ -43,7 +43,6 @@
+ #include "xfs_error.h"
+ #include "xfs_bmap.h"
+ #include "xfs_rw.h"
+-#include "xfs_refcache.h"
+ #include "xfs_buf_item.h"
+ #include "xfs_log_priv.h"
+ #include "xfs_dir2_trace.h"
+@@ -56,6 +55,7 @@
+ #include "xfs_fsops.h"
+ #include "xfs_vnodeops.h"
+ #include "xfs_vfsops.h"
++#include "xfs_utils.h"
+ 
+ 
+ int __init
+@@ -69,15 +69,17 @@ xfs_init(void)
+ 	/*
+ 	 * Initialize all of the zone allocators we use.
+ 	 */
++	xfs_log_ticket_zone = kmem_zone_init(sizeof(xlog_ticket_t),
++						"xfs_log_ticket");
+ 	xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t),
+-						 "xfs_bmap_free_item");
++						"xfs_bmap_free_item");
+ 	xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t),
+-					    "xfs_btree_cur");
+-	xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
+-	xfs_da_state_zone =
+-		kmem_zone_init(sizeof(xfs_da_state_t), "xfs_da_state");
++						"xfs_btree_cur");
++	xfs_da_state_zone = kmem_zone_init(sizeof(xfs_da_state_t),
++						"xfs_da_state");
+ 	xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
+ 	xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
++	xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
+ 	xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
+ 	xfs_mru_cache_init();
+ 	xfs_filestream_init();
+@@ -113,9 +115,6 @@ xfs_init(void)
+ 	xfs_ili_zone =
+ 		kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili",
+ 					KM_ZONE_SPREAD, NULL);
+-	xfs_icluster_zone =
+-		kmem_zone_init_flags(sizeof(xfs_icluster_t), "xfs_icluster",
+-					KM_ZONE_SPREAD, NULL);
+ 
+ 	/*
+ 	 * Allocate global trace buffers.
+@@ -153,11 +152,9 @@ xfs_cleanup(void)
+ 	extern kmem_zone_t	*xfs_inode_zone;
+ 	extern kmem_zone_t	*xfs_efd_zone;
+ 	extern kmem_zone_t	*xfs_efi_zone;
+-	extern kmem_zone_t	*xfs_icluster_zone;
+ 
+ 	xfs_cleanup_procfs();
+ 	xfs_sysctl_unregister();
+-	xfs_refcache_destroy();
+ 	xfs_filestream_uninit();
+ 	xfs_mru_cache_uninit();
+ 	xfs_acl_zone_destroy(xfs_acl_zone);
+@@ -189,7 +186,6 @@ xfs_cleanup(void)
+ 	kmem_zone_destroy(xfs_efi_zone);
+ 	kmem_zone_destroy(xfs_ifork_zone);
+ 	kmem_zone_destroy(xfs_ili_zone);
+-	kmem_zone_destroy(xfs_icluster_zone);
+ }
+ 
+ /*
+@@ -573,7 +569,7 @@ xfs_unmount(
+ #ifdef HAVE_DMAPI
+ 	if (mp->m_flags & XFS_MOUNT_DMAPI) {
+ 		error = XFS_SEND_PREUNMOUNT(mp,
+-				rvp, DM_RIGHT_NULL, rvp, DM_RIGHT_NULL,
++				rip, DM_RIGHT_NULL, rip, DM_RIGHT_NULL,
+ 				NULL, NULL, 0, 0,
+ 				(mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?
+ 					0:DM_FLAGS_UNWANTED);
+@@ -584,11 +580,6 @@ xfs_unmount(
+ 					0 : DM_FLAGS_UNWANTED;
+ 	}
+ #endif
+-	/*
+-	 * First blow any referenced inode from this file system
+-	 * out of the reference cache, and delete the timer.
+-	 */
+-	xfs_refcache_purge_mp(mp);
+ 
+ 	/*
+ 	 * Blow away any referenced inode in the filestreams cache.
+@@ -607,7 +598,7 @@ xfs_unmount(
+ 	/*
+ 	 * Drop the reference count
+ 	 */
+-	VN_RELE(rvp);
++	IRELE(rip);
+ 
+ 	/*
+ 	 * If we're forcing a shutdown, typically because of a media error,
+@@ -629,7 +620,7 @@ out:
+ 		/* Note: mp structure must still exist for
+ 		 * XFS_SEND_UNMOUNT() call.
+ 		 */
+-		XFS_SEND_UNMOUNT(mp, error == 0 ? rvp : NULL,
++		XFS_SEND_UNMOUNT(mp, error == 0 ? rip : NULL,
+ 			DM_RIGHT_NULL, 0, error, unmount_event_flags);
+ 	}
+ 	if (xfs_unmountfs_needed) {
+@@ -646,13 +637,12 @@ out:
+ 	return XFS_ERROR(error);
+ }
+ 
+-STATIC int
++STATIC void
+ xfs_quiesce_fs(
+ 	xfs_mount_t		*mp)
+ {
+ 	int			count = 0, pincount;
+ 
+-	xfs_refcache_purge_mp(mp);
+ 	xfs_flush_buftarg(mp->m_ddev_targp, 0);
+ 	xfs_finish_reclaim_all(mp, 0);
+ 
+@@ -671,8 +661,6 @@ xfs_quiesce_fs(
+ 			count++;
+ 		}
+ 	} while (count < 2);
+-
+-	return 0;
+ }
+ 
+ /*
+@@ -684,6 +672,8 @@ void
+ xfs_attr_quiesce(
+ 	xfs_mount_t	*mp)
+ {
++	int	error = 0;
++
+ 	/* wait for all modifications to complete */
+ 	while (atomic_read(&mp->m_active_trans) > 0)
+ 		delay(100);
+@@ -694,7 +684,11 @@ xfs_attr_quiesce(
+ 	ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
+ 
+ 	/* Push the superblock and write an unmount record */
+-	xfs_log_sbcount(mp, 1);
++	error = xfs_log_sbcount(mp, 1);
++	if (error)
++		xfs_fs_cmn_err(CE_WARN, mp,
++				"xfs_attr_quiesce: failed to log sb changes. "
++				"Frozen image may not be consistent.");
+ 	xfs_log_unmount_write(mp);
+ 	xfs_unmountfs_writesb(mp);
+ }
+@@ -790,8 +784,8 @@ xfs_unmount_flush(
+ 		goto fscorrupt_out2;
+ 
+ 	if (rbmip) {
+-		VN_RELE(XFS_ITOV(rbmip));
+-		VN_RELE(XFS_ITOV(rsumip));
++		IRELE(rbmip);
++		IRELE(rsumip);
+ 	}
+ 
+ 	xfs_iunlock(rip, XFS_ILOCK_EXCL);
+@@ -1169,10 +1163,10 @@ xfs_sync_inodes(
+ 			 * above, then wait until after we've unlocked
+ 			 * the inode to release the reference.  This is
+ 			 * because we can be already holding the inode
+-			 * lock when VN_RELE() calls xfs_inactive().
++			 * lock when IRELE() calls xfs_inactive().
+ 			 *
+ 			 * Make sure to drop the mount lock before calling
+-			 * VN_RELE() so that we don't trip over ourselves if
++			 * IRELE() so that we don't trip over ourselves if
+ 			 * we have to go for the mount lock again in the
+ 			 * inactive code.
+ 			 */
+@@ -1180,7 +1174,7 @@ xfs_sync_inodes(
+ 				IPOINTER_INSERT(ip, mp);
+ 			}
+ 
+-			VN_RELE(vp);
++			IRELE(ip);
+ 
+ 			vnode_refed = B_FALSE;
+ 		}
+@@ -1323,30 +1317,8 @@ xfs_syncsub(
+ 	}
+ 
+ 	/*
+-	 * If this is the periodic sync, then kick some entries out of
+-	 * the reference cache.  This ensures that idle entries are
+-	 * eventually kicked out of the cache.
+-	 */
+-	if (flags & SYNC_REFCACHE) {
+-		if (flags & SYNC_WAIT)
+-			xfs_refcache_purge_mp(mp);
+-		else
+-			xfs_refcache_purge_some(mp);
+-	}
+-
+-	/*
+-	 * If asked, update the disk superblock with incore counter values if we
+-	 * are using non-persistent counters so that they don't get too far out
+-	 * of sync if we crash or get a forced shutdown. We don't want to force
+-	 * this to disk, just get a transaction into the iclogs....
+-	 */
+-	if (flags & SYNC_SUPER)
+-		xfs_log_sbcount(mp, 0);
+-
+-	/*
+ 	 * Now check to see if the log needs a "dummy" transaction.
+ 	 */
+-
+ 	if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {
+ 		xfs_trans_t *tp;
+ 		xfs_inode_t *ip;
+diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
+index 64c5953..6650601 100644
+--- a/fs/xfs/xfs_vnodeops.c
++++ b/fs/xfs/xfs_vnodeops.c
+@@ -48,7 +48,6 @@
+ #include "xfs_quota.h"
+ #include "xfs_utils.h"
+ #include "xfs_rtalloc.h"
+-#include "xfs_refcache.h"
+ #include "xfs_trans_space.h"
+ #include "xfs_log_priv.h"
+ #include "xfs_filestream.h"
+@@ -327,7 +326,7 @@ xfs_setattr(
+ 		if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) &&
+ 		    !(flags & ATTR_DMI)) {
+ 			int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
+-			code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, vp,
++			code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, ip,
+ 				vap->va_size, 0, dmflags, NULL);
+ 			if (code) {
+ 				lock_flags = 0;
+@@ -634,6 +633,15 @@ xfs_setattr(
+ 	 * Truncate file.  Must have write permission and not be a directory.
+ 	 */
+ 	if (mask & XFS_AT_SIZE) {
++		/*
++		 * Only change the c/mtime if we are changing the size
++		 * or we are explicitly asked to change it. This handles
++		 * the semantic difference between truncate() and ftruncate()
++		 * as implemented in the VFS.
++		 */
++		if (vap->va_size != ip->i_size || (mask & XFS_AT_CTIME))
++			timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
++
+ 		if (vap->va_size > ip->i_size) {
+ 			xfs_igrow_finish(tp, ip, vap->va_size,
+ 			    !(flags & ATTR_DMI));
+@@ -662,10 +670,6 @@ xfs_setattr(
+ 			 */
+ 			xfs_iflags_set(ip, XFS_ITRUNCATED);
+ 		}
+-		/*
+-		 * Have to do this even if the file's size doesn't change.
+-		 */
+-		timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
+ 	}
+ 
+ 	/*
+@@ -877,7 +881,7 @@ xfs_setattr(
+ 
+ 	if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) &&
+ 	    !(flags & ATTR_DMI)) {
+-		(void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, vp, DM_RIGHT_NULL,
++		(void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL,
+ 					NULL, DM_RIGHT_NULL, NULL, NULL,
+ 					0, 0, AT_DELAY_FLAG(flags));
+ 	}
+@@ -1443,28 +1447,22 @@ xfs_inactive_attrs(
+ 	tp = *tpp;
+ 	mp = ip->i_mount;
+ 	ASSERT(ip->i_d.di_forkoff != 0);
+-	xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+ 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
++	if (error)
++		goto error_unlock;
+ 
+ 	error = xfs_attr_inactive(ip);
+-	if (error) {
+-		*tpp = NULL;
+-		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+-		return error; /* goto out */
+-	}
++	if (error)
++		goto error_unlock;
+ 
+ 	tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
+ 	error = xfs_trans_reserve(tp, 0,
+ 				  XFS_IFREE_LOG_RES(mp),
+ 				  0, XFS_TRANS_PERM_LOG_RES,
+ 				  XFS_INACTIVE_LOG_COUNT);
+-	if (error) {
+-		ASSERT(XFS_FORCED_SHUTDOWN(mp));
+-		xfs_trans_cancel(tp, 0);
+-		*tpp = NULL;
+-		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+-		return error;
+-	}
++	if (error)
++		goto error_cancel;
+ 
+ 	xfs_ilock(ip, XFS_ILOCK_EXCL);
+ 	xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
+@@ -1475,6 +1473,14 @@ xfs_inactive_attrs(
+ 
+ 	*tpp = tp;
+ 	return 0;
++
++error_cancel:
++	ASSERT(XFS_FORCED_SHUTDOWN(mp));
++	xfs_trans_cancel(tp, 0);
++error_unlock:
++	*tpp = NULL;
++	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
++	return error;
+ }
+ 
+ int
+@@ -1520,12 +1526,6 @@ xfs_release(
+ 			xfs_flush_pages(ip, 0, -1, XFS_B_ASYNC, FI_NONE);
+ 	}
+ 
+-#ifdef HAVE_REFCACHE
+-	/* If we are in the NFS reference cache then don't do this now */
+-	if (ip->i_refcache)
+-		return 0;
+-#endif
+-
+ 	if (ip->i_d.di_nlink != 0) {
+ 		if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
+ 		     ((ip->i_size > 0) || (VN_CACHED(vp) > 0 ||
+@@ -1588,9 +1588,8 @@ xfs_inactive(
+ 
+ 	mp = ip->i_mount;
+ 
+-	if (ip->i_d.di_nlink == 0 && DM_EVENT_ENABLED(ip, DM_EVENT_DESTROY)) {
+-		(void) XFS_SEND_DESTROY(mp, vp, DM_RIGHT_NULL);
+-	}
++	if (ip->i_d.di_nlink == 0 && DM_EVENT_ENABLED(ip, DM_EVENT_DESTROY))
++		XFS_SEND_DESTROY(mp, ip, DM_RIGHT_NULL);
+ 
+ 	error = 0;
+ 
+@@ -1744,11 +1743,18 @@ xfs_inactive(
+ 		XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
+ 
+ 		/*
+-		 * Just ignore errors at this point.  There is
+-		 * nothing we can do except to try to keep going.
++		 * Just ignore errors at this point.  There is nothing we can
++		 * do except to try to keep going. Make sure it's not a silent
++		 * error.
+ 		 */
+-		(void) xfs_bmap_finish(&tp,  &free_list, &committed);
+-		(void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++		error = xfs_bmap_finish(&tp,  &free_list, &committed);
++		if (error)
++			xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: "
++				"xfs_bmap_finish() returned error %d", error);
++		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++		if (error)
++			xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: "
++				"xfs_trans_commit() returned error %d", error);
+ 	}
+ 	/*
+ 	 * Release the dquots held by inode, if any.
+@@ -1765,8 +1771,8 @@ xfs_inactive(
+ int
+ xfs_lookup(
+ 	xfs_inode_t		*dp,
+-	bhv_vname_t		*dentry,
+-	bhv_vnode_t		**vpp)
++	struct xfs_name		*name,
++	xfs_inode_t		**ipp)
+ {
+ 	xfs_inode_t		*ip;
+ 	xfs_ino_t		e_inum;
+@@ -1779,9 +1785,9 @@ xfs_lookup(
+ 		return XFS_ERROR(EIO);
+ 
+ 	lock_mode = xfs_ilock_map_shared(dp);
+-	error = xfs_dir_lookup_int(dp, lock_mode, dentry, &e_inum, &ip);
++	error = xfs_dir_lookup_int(dp, lock_mode, name, &e_inum, &ip);
+ 	if (!error) {
+-		*vpp = XFS_ITOV(ip);
++		*ipp = ip;
+ 		xfs_itrace_ref(ip);
+ 	}
+ 	xfs_iunlock_map_shared(dp, lock_mode);
+@@ -1791,19 +1797,16 @@ xfs_lookup(
+ int
+ xfs_create(
+ 	xfs_inode_t		*dp,
+-	bhv_vname_t		*dentry,
++	struct xfs_name		*name,
+ 	mode_t			mode,
+ 	xfs_dev_t		rdev,
+-	bhv_vnode_t		**vpp,
++	xfs_inode_t		**ipp,
+ 	cred_t			*credp)
+ {
+-	char			*name = VNAME(dentry);
+-	xfs_mount_t	        *mp = dp->i_mount;
+-	bhv_vnode_t		*dir_vp = XFS_ITOV(dp);
++	xfs_mount_t		*mp = dp->i_mount;
+ 	xfs_inode_t		*ip;
+-	bhv_vnode_t	        *vp = NULL;
+ 	xfs_trans_t		*tp;
+-	int                     error;
++	int			error;
+ 	xfs_bmap_free_t		free_list;
+ 	xfs_fsblock_t		first_block;
+ 	boolean_t		unlock_dp_on_error = B_FALSE;
+@@ -1813,17 +1816,14 @@ xfs_create(
+ 	xfs_prid_t		prid;
+ 	struct xfs_dquot	*udqp, *gdqp;
+ 	uint			resblks;
+-	int			namelen;
+ 
+-	ASSERT(!*vpp);
++	ASSERT(!*ipp);
+ 	xfs_itrace_entry(dp);
+ 
+-	namelen = VNAMELEN(dentry);
+-
+ 	if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) {
+ 		error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
+-				dir_vp, DM_RIGHT_NULL, NULL,
+-				DM_RIGHT_NULL, name, NULL,
++				dp, DM_RIGHT_NULL, NULL,
++				DM_RIGHT_NULL, name->name, NULL,
+ 				mode, 0, 0);
+ 
+ 		if (error)
+@@ -1855,7 +1855,7 @@ xfs_create(
+ 
+ 	tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
+ 	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+-	resblks = XFS_CREATE_SPACE_RES(mp, namelen);
++	resblks = XFS_CREATE_SPACE_RES(mp, name->len);
+ 	/*
+ 	 * Initially assume that the file does not exist and
+ 	 * reserve the resources for that case.  If that is not
+@@ -1888,7 +1888,8 @@ xfs_create(
+ 	if (error)
+ 		goto error_return;
+ 
+-	if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen)))
++	error = xfs_dir_canenter(tp, dp, name, resblks);
++	if (error)
+ 		goto error_return;
+ 	error = xfs_dir_ialloc(&tp, dp, mode, 1,
+ 			rdev, credp, prid, resblks > 0,
+@@ -1914,11 +1915,11 @@ xfs_create(
+ 	 * the transaction cancel unlocking dp so don't do it explicitly in the
+ 	 * error path.
+ 	 */
+-	VN_HOLD(dir_vp);
++	IHOLD(dp);
+ 	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+ 	unlock_dp_on_error = B_FALSE;
+ 
+-	error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino,
++	error = xfs_dir_createname(tp, dp, name, ip->i_ino,
+ 					&first_block, &free_list, resblks ?
+ 					resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
+ 	if (error) {
+@@ -1952,7 +1953,6 @@ xfs_create(
+ 	 * vnode to the caller, we bump the vnode ref count now.
+ 	 */
+ 	IHOLD(ip);
+-	vp = XFS_ITOV(ip);
+ 
+ 	error = xfs_bmap_finish(&tp, &free_list, &committed);
+ 	if (error) {
+@@ -1970,17 +1970,17 @@ xfs_create(
+ 	XFS_QM_DQRELE(mp, udqp);
+ 	XFS_QM_DQRELE(mp, gdqp);
+ 
+-	*vpp = vp;
++	*ipp = ip;
+ 
+ 	/* Fallthrough to std_return with error = 0  */
+ 
+ std_return:
+-	if ((*vpp || (error != 0 && dm_event_sent != 0)) &&
++	if ((*ipp || (error != 0 && dm_event_sent != 0)) &&
+ 	    DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) {
+ 		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE,
+-			dir_vp, DM_RIGHT_NULL,
+-			*vpp ? vp:NULL,
+-			DM_RIGHT_NULL, name, NULL,
++			dp, DM_RIGHT_NULL,
++			*ipp ? ip : NULL,
++			DM_RIGHT_NULL, name->name, NULL,
+ 			mode, error, 0);
+ 	}
+ 	return error;
+@@ -2272,46 +2272,32 @@ int remove_which_error_return = 0;
+ int
+ xfs_remove(
+ 	xfs_inode_t             *dp,
+-	bhv_vname_t		*dentry)
++	struct xfs_name		*name,
++	xfs_inode_t		*ip)
+ {
+-	bhv_vnode_t		*dir_vp = XFS_ITOV(dp);
+-	char			*name = VNAME(dentry);
+ 	xfs_mount_t		*mp = dp->i_mount;
+-	xfs_inode_t             *ip;
+ 	xfs_trans_t             *tp = NULL;
+ 	int                     error = 0;
+ 	xfs_bmap_free_t         free_list;
+ 	xfs_fsblock_t           first_block;
+ 	int			cancel_flags;
+ 	int			committed;
+-	int			dm_di_mode = 0;
+ 	int			link_zero;
+ 	uint			resblks;
+-	int			namelen;
+ 
+ 	xfs_itrace_entry(dp);
+ 
+ 	if (XFS_FORCED_SHUTDOWN(mp))
+ 		return XFS_ERROR(EIO);
+ 
+-	namelen = VNAMELEN(dentry);
+-
+-	if (!xfs_get_dir_entry(dentry, &ip)) {
+-	        dm_di_mode = ip->i_d.di_mode;
+-		IRELE(ip);
+-	}
+-
+ 	if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
+-		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_vp,
+-					DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
+-					name, NULL, dm_di_mode, 0, 0);
++		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dp, DM_RIGHT_NULL,
++					NULL, DM_RIGHT_NULL, name->name, NULL,
++					ip->i_d.di_mode, 0, 0);
+ 		if (error)
+ 			return error;
+ 	}
+ 
+-	/* From this point on, return through std_return */
+-	ip = NULL;
+-
+ 	/*
+ 	 * We need to get a reference to ip before we get our log
+ 	 * reservation. The reason for this is that we cannot call
+@@ -2324,13 +2310,7 @@ xfs_remove(
+ 	 * when we call xfs_iget.  Instead we get an unlocked reference
+ 	 * to the inode before getting our log reservation.
+ 	 */
+-	error = xfs_get_dir_entry(dentry, &ip);
+-	if (error) {
+-		REMOVE_DEBUG_TRACE(__LINE__);
+-		goto std_return;
+-	}
+-
+-	dm_di_mode = ip->i_d.di_mode;
++	IHOLD(ip);
+ 
+ 	xfs_itrace_entry(ip);
+ 	xfs_itrace_ref(ip);
+@@ -2398,7 +2378,7 @@ xfs_remove(
+ 	 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
+ 	 */
+ 	XFS_BMAP_INIT(&free_list, &first_block);
+-	error = xfs_dir_removename(tp, dp, name, namelen, ip->i_ino,
++	error = xfs_dir_removename(tp, dp, name, ip->i_ino,
+ 					&first_block, &free_list, 0);
+ 	if (error) {
+ 		ASSERT(error != ENOENT);
+@@ -2449,14 +2429,6 @@ xfs_remove(
+ 	}
+ 
+ 	/*
+-	 * Before we drop our extra reference to the inode, purge it
+-	 * from the refcache if it is there.  By waiting until afterwards
+-	 * to do the IRELE, we ensure that we won't go inactive in the
+-	 * xfs_refcache_purge_ip routine (although that would be OK).
+-	 */
+-	xfs_refcache_purge_ip(ip);
+-
+-	/*
+ 	 * If we are using filestreams, kill the stream association.
+ 	 * If the file is still open it may get a new one but that
+ 	 * will get killed on last close in xfs_close() so we don't
+@@ -2472,9 +2444,9 @@ xfs_remove(
+  std_return:
+ 	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
+ 		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
+-				dir_vp, DM_RIGHT_NULL,
++				dp, DM_RIGHT_NULL,
+ 				NULL, DM_RIGHT_NULL,
+-				name, NULL, dm_di_mode, error, 0);
++				name->name, NULL, ip->i_d.di_mode, error, 0);
+ 	}
+ 	return error;
+ 
+@@ -2495,14 +2467,6 @@ xfs_remove(
+ 	cancel_flags |= XFS_TRANS_ABORT;
+ 	xfs_trans_cancel(tp, cancel_flags);
+ 
+-	/*
+-	 * Before we drop our extra reference to the inode, purge it
+-	 * from the refcache if it is there.  By waiting until afterwards
+-	 * to do the IRELE, we ensure that we won't go inactive in the
+-	 * xfs_refcache_purge_ip routine (although that would be OK).
+-	 */
+-	xfs_refcache_purge_ip(ip);
+-
+ 	IRELE(ip);
+ 
+ 	goto std_return;
+@@ -2511,12 +2475,10 @@ xfs_remove(
+ int
+ xfs_link(
+ 	xfs_inode_t		*tdp,
+-	bhv_vnode_t		*src_vp,
+-	bhv_vname_t		*dentry)
++	xfs_inode_t		*sip,
++	struct xfs_name		*target_name)
+ {
+-	bhv_vnode_t		*target_dir_vp = XFS_ITOV(tdp);
+ 	xfs_mount_t		*mp = tdp->i_mount;
+-	xfs_inode_t		*sip = xfs_vtoi(src_vp);
+ 	xfs_trans_t		*tp;
+ 	xfs_inode_t		*ips[2];
+ 	int			error;
+@@ -2525,23 +2487,20 @@ xfs_link(
+ 	int			cancel_flags;
+ 	int			committed;
+ 	int			resblks;
+-	char			*target_name = VNAME(dentry);
+-	int			target_namelen;
+ 
+ 	xfs_itrace_entry(tdp);
+-	xfs_itrace_entry(xfs_vtoi(src_vp));
++	xfs_itrace_entry(sip);
+ 
+-	target_namelen = VNAMELEN(dentry);
+-	ASSERT(!VN_ISDIR(src_vp));
++	ASSERT(!S_ISDIR(sip->i_d.di_mode));
+ 
+ 	if (XFS_FORCED_SHUTDOWN(mp))
+ 		return XFS_ERROR(EIO);
+ 
+ 	if (DM_EVENT_ENABLED(tdp, DM_EVENT_LINK)) {
+ 		error = XFS_SEND_NAMESP(mp, DM_EVENT_LINK,
+-					target_dir_vp, DM_RIGHT_NULL,
+-					src_vp, DM_RIGHT_NULL,
+-					target_name, NULL, 0, 0, 0);
++					tdp, DM_RIGHT_NULL,
++					sip, DM_RIGHT_NULL,
++					target_name->name, NULL, 0, 0, 0);
+ 		if (error)
+ 			return error;
+ 	}
+@@ -2556,7 +2515,7 @@ xfs_link(
+ 
+ 	tp = xfs_trans_alloc(mp, XFS_TRANS_LINK);
+ 	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+-	resblks = XFS_LINK_SPACE_RES(mp, target_namelen);
++	resblks = XFS_LINK_SPACE_RES(mp, target_name->len);
+ 	error = xfs_trans_reserve(tp, resblks, XFS_LINK_LOG_RES(mp), 0,
+ 			XFS_TRANS_PERM_LOG_RES, XFS_LINK_LOG_COUNT);
+ 	if (error == ENOSPC) {
+@@ -2584,8 +2543,8 @@ xfs_link(
+ 	 * xfs_trans_cancel will both unlock the inodes and
+ 	 * decrement the associated ref counts.
+ 	 */
+-	VN_HOLD(src_vp);
+-	VN_HOLD(target_dir_vp);
++	IHOLD(sip);
++	IHOLD(tdp);
+ 	xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL);
+ 	xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL);
+ 
+@@ -2608,15 +2567,14 @@ xfs_link(
+ 		goto error_return;
+ 	}
+ 
+-	if (resblks == 0 &&
+-	    (error = xfs_dir_canenter(tp, tdp, target_name, target_namelen)))
++	error = xfs_dir_canenter(tp, tdp, target_name, resblks);
++	if (error)
+ 		goto error_return;
+ 
+ 	XFS_BMAP_INIT(&free_list, &first_block);
+ 
+-	error = xfs_dir_createname(tp, tdp, target_name, target_namelen,
+-				   sip->i_ino, &first_block, &free_list,
+-				   resblks);
++	error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
++					&first_block, &free_list, resblks);
+ 	if (error)
+ 		goto abort_return;
+ 	xfs_ichgtime(tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+@@ -2650,9 +2608,9 @@ xfs_link(
+ std_return:
+ 	if (DM_EVENT_ENABLED(sip, DM_EVENT_POSTLINK)) {
+ 		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTLINK,
+-				target_dir_vp, DM_RIGHT_NULL,
+-				src_vp, DM_RIGHT_NULL,
+-				target_name, NULL, 0, error, 0);
++				tdp, DM_RIGHT_NULL,
++				sip, DM_RIGHT_NULL,
++				target_name->name, NULL, 0, error, 0);
+ 	}
+ 	return error;
+ 
+@@ -2669,17 +2627,13 @@ std_return:
+ int
+ xfs_mkdir(
+ 	xfs_inode_t             *dp,
+-	bhv_vname_t		*dentry,
++	struct xfs_name		*dir_name,
+ 	mode_t			mode,
+-	bhv_vnode_t		**vpp,
++	xfs_inode_t		**ipp,
+ 	cred_t			*credp)
+ {
+-	bhv_vnode_t		*dir_vp = XFS_ITOV(dp);
+-	char			*dir_name = VNAME(dentry);
+-	int			dir_namelen = VNAMELEN(dentry);
+ 	xfs_mount_t		*mp = dp->i_mount;
+ 	xfs_inode_t		*cdp;	/* inode of created dir */
+-	bhv_vnode_t		*cvp;	/* vnode of created dir */
+ 	xfs_trans_t		*tp;
+ 	int			cancel_flags;
+ 	int			error;
+@@ -2700,8 +2654,8 @@ xfs_mkdir(
+ 
+ 	if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) {
+ 		error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
+-					dir_vp, DM_RIGHT_NULL, NULL,
+-					DM_RIGHT_NULL, dir_name, NULL,
++					dp, DM_RIGHT_NULL, NULL,
++					DM_RIGHT_NULL, dir_name->name, NULL,
+ 					mode, 0, 0);
+ 		if (error)
+ 			return error;
+@@ -2730,7 +2684,7 @@ xfs_mkdir(
+ 
+ 	tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
+ 	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+-	resblks = XFS_MKDIR_SPACE_RES(mp, dir_namelen);
++	resblks = XFS_MKDIR_SPACE_RES(mp, dir_name->len);
+ 	error = xfs_trans_reserve(tp, resblks, XFS_MKDIR_LOG_RES(mp), 0,
+ 				  XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT);
+ 	if (error == ENOSPC) {
+@@ -2762,8 +2716,8 @@ xfs_mkdir(
+ 	if (error)
+ 		goto error_return;
+ 
+-	if (resblks == 0 &&
+-	    (error = xfs_dir_canenter(tp, dp, dir_name, dir_namelen)))
++	error = xfs_dir_canenter(tp, dp, dir_name, resblks);
++	if (error)
+ 		goto error_return;
+ 	/*
+ 	 * create the directory inode.
+@@ -2786,15 +2740,15 @@ xfs_mkdir(
+ 	 * from here on will result in the transaction cancel
+ 	 * unlocking dp so don't do it explicitly in the error path.
+ 	 */
+-	VN_HOLD(dir_vp);
++	IHOLD(dp);
+ 	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+ 	unlock_dp_on_error = B_FALSE;
+ 
+ 	XFS_BMAP_INIT(&free_list, &first_block);
+ 
+-	error = xfs_dir_createname(tp, dp, dir_name, dir_namelen, cdp->i_ino,
+-				   &first_block, &free_list, resblks ?
+-				   resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
++	error = xfs_dir_createname(tp, dp, dir_name, cdp->i_ino,
++					&first_block, &free_list, resblks ?
++					resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
+ 	if (error) {
+ 		ASSERT(error != ENOSPC);
+ 		goto error1;
+@@ -2817,11 +2771,9 @@ xfs_mkdir(
+ 	if (error)
+ 		goto error2;
+ 
+-	cvp = XFS_ITOV(cdp);
+-
+ 	created = B_TRUE;
+ 
+-	*vpp = cvp;
++	*ipp = cdp;
+ 	IHOLD(cdp);
+ 
+ 	/*
+@@ -2858,10 +2810,10 @@ std_return:
+ 	if ((created || (error != 0 && dm_event_sent != 0)) &&
+ 	    DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) {
+ 		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE,
+-					dir_vp, DM_RIGHT_NULL,
+-					created ? XFS_ITOV(cdp):NULL,
++					dp, DM_RIGHT_NULL,
++					created ? cdp : NULL,
+ 					DM_RIGHT_NULL,
+-					dir_name, NULL,
++					dir_name->name, NULL,
+ 					mode, error, 0);
+ 	}
+ 	return error;
+@@ -2885,20 +2837,17 @@ std_return:
+ int
+ xfs_rmdir(
+ 	xfs_inode_t             *dp,
+-	bhv_vname_t		*dentry)
++	struct xfs_name		*name,
++	xfs_inode_t		*cdp)
+ {
+ 	bhv_vnode_t		*dir_vp = XFS_ITOV(dp);
+-	char			*name = VNAME(dentry);
+-	int			namelen = VNAMELEN(dentry);
+ 	xfs_mount_t		*mp = dp->i_mount;
+-  	xfs_inode_t             *cdp;   /* child directory */
+ 	xfs_trans_t             *tp;
+ 	int                     error;
+ 	xfs_bmap_free_t         free_list;
+ 	xfs_fsblock_t           first_block;
+ 	int			cancel_flags;
+ 	int			committed;
+-	int			dm_di_mode = S_IFDIR;
+ 	int			last_cdp_link;
+ 	uint			resblks;
+ 
+@@ -2907,24 +2856,15 @@ xfs_rmdir(
+ 	if (XFS_FORCED_SHUTDOWN(mp))
+ 		return XFS_ERROR(EIO);
+ 
+-	if (!xfs_get_dir_entry(dentry, &cdp)) {
+-	        dm_di_mode = cdp->i_d.di_mode;
+-		IRELE(cdp);
+-	}
+-
+ 	if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
+ 		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
+-					dir_vp, DM_RIGHT_NULL,
+-					NULL, DM_RIGHT_NULL,
+-					name, NULL, dm_di_mode, 0, 0);
++					dp, DM_RIGHT_NULL,
++					NULL, DM_RIGHT_NULL, name->name,
++					NULL, cdp->i_d.di_mode, 0, 0);
+ 		if (error)
+ 			return XFS_ERROR(error);
+ 	}
+ 
+-	/* Return through std_return after this point. */
+-
+-	cdp = NULL;
+-
+ 	/*
+ 	 * We need to get a reference to cdp before we get our log
+ 	 * reservation.  The reason for this is that we cannot call
+@@ -2937,13 +2877,7 @@ xfs_rmdir(
+ 	 * when we call xfs_iget.  Instead we get an unlocked reference
+ 	 * to the inode before getting our log reservation.
+ 	 */
+-	error = xfs_get_dir_entry(dentry, &cdp);
+-	if (error) {
+-		REMOVE_DEBUG_TRACE(__LINE__);
+-		goto std_return;
+-	}
+-	mp = dp->i_mount;
+-	dm_di_mode = cdp->i_d.di_mode;
++	IHOLD(cdp);
+ 
+ 	/*
+ 	 * Get the dquots for the inodes.
+@@ -3020,7 +2954,7 @@ xfs_rmdir(
+ 		goto error_return;
+ 	}
+ 
+-	error = xfs_dir_removename(tp, dp, name, namelen, cdp->i_ino,
++	error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
+ 					&first_block, &free_list, resblks);
+ 	if (error)
+ 		goto error1;
+@@ -3098,9 +3032,9 @@ xfs_rmdir(
+  std_return:
+ 	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
+ 		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
+-					dir_vp, DM_RIGHT_NULL,
++					dp, DM_RIGHT_NULL,
+ 					NULL, DM_RIGHT_NULL,
+-					name, NULL, dm_di_mode,
++					name->name, NULL, cdp->i_d.di_mode,
+ 					error, 0);
+ 	}
+ 	return error;
+@@ -3118,13 +3052,12 @@ xfs_rmdir(
+ int
+ xfs_symlink(
+ 	xfs_inode_t		*dp,
+-	bhv_vname_t		*dentry,
+-	char			*target_path,
++	struct xfs_name		*link_name,
++	const char		*target_path,
+ 	mode_t			mode,
+-	bhv_vnode_t		**vpp,
++	xfs_inode_t		**ipp,
+ 	cred_t			*credp)
+ {
+-	bhv_vnode_t		*dir_vp = XFS_ITOV(dp);
+ 	xfs_mount_t		*mp = dp->i_mount;
+ 	xfs_trans_t		*tp;
+ 	xfs_inode_t		*ip;
+@@ -3140,17 +3073,15 @@ xfs_symlink(
+ 	int			nmaps;
+ 	xfs_bmbt_irec_t		mval[SYMLINK_MAPS];
+ 	xfs_daddr_t		d;
+-	char			*cur_chunk;
++	const char		*cur_chunk;
+ 	int			byte_cnt;
+ 	int			n;
+ 	xfs_buf_t		*bp;
+ 	xfs_prid_t		prid;
+ 	struct xfs_dquot	*udqp, *gdqp;
+ 	uint			resblks;
+-	char			*link_name = VNAME(dentry);
+-	int			link_namelen;
+ 
+-	*vpp = NULL;
++	*ipp = NULL;
+ 	error = 0;
+ 	ip = NULL;
+ 	tp = NULL;
+@@ -3160,44 +3091,17 @@ xfs_symlink(
+ 	if (XFS_FORCED_SHUTDOWN(mp))
+ 		return XFS_ERROR(EIO);
+ 
+-	link_namelen = VNAMELEN(dentry);
+-
+ 	/*
+ 	 * Check component lengths of the target path name.
+ 	 */
+ 	pathlen = strlen(target_path);
+ 	if (pathlen >= MAXPATHLEN)      /* total string too long */
+ 		return XFS_ERROR(ENAMETOOLONG);
+-	if (pathlen >= MAXNAMELEN) {    /* is any component too long? */
+-		int len, total;
+-		char *path;
+-
+-		for (total = 0, path = target_path; total < pathlen;) {
+-			/*
+-			 * Skip any slashes.
+-			 */
+-			while(*path == '/') {
+-				total++;
+-				path++;
+-			}
+-
+-			/*
+-			 * Count up to the next slash or end of path.
+-			 * Error out if the component is bigger than MAXNAMELEN.
+-			 */
+-			for(len = 0; *path != '/' && total < pathlen;total++, path++) {
+-				if (++len >= MAXNAMELEN) {
+-					error = ENAMETOOLONG;
+-					return error;
+-				}
+-			}
+-		}
+-	}
+ 
+ 	if (DM_EVENT_ENABLED(dp, DM_EVENT_SYMLINK)) {
+-		error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dir_vp,
++		error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dp,
+ 					DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
+-					link_name, target_path, 0, 0, 0);
++					link_name->name, target_path, 0, 0, 0);
+ 		if (error)
+ 			return error;
+ 	}
+@@ -3229,7 +3133,7 @@ xfs_symlink(
+ 		fs_blocks = 0;
+ 	else
+ 		fs_blocks = XFS_B_TO_FSB(mp, pathlen);
+-	resblks = XFS_SYMLINK_SPACE_RES(mp, link_namelen, fs_blocks);
++	resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
+ 	error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0,
+ 			XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
+ 	if (error == ENOSPC && fs_blocks == 0) {
+@@ -3263,8 +3167,8 @@ xfs_symlink(
+ 	/*
+ 	 * Check for ability to enter directory entry, if no space reserved.
+ 	 */
+-	if (resblks == 0 &&
+-	    (error = xfs_dir_canenter(tp, dp, link_name, link_namelen)))
++	error = xfs_dir_canenter(tp, dp, link_name, resblks);
++	if (error)
+ 		goto error_return;
+ 	/*
+ 	 * Initialize the bmap freelist prior to calling either
+@@ -3289,7 +3193,7 @@ xfs_symlink(
+ 	 * transaction cancel unlocking dp so don't do it explicitly in the
+ 	 * error path.
+ 	 */
+-	VN_HOLD(dir_vp);
++	IHOLD(dp);
+ 	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+ 	unlock_dp_on_error = B_FALSE;
+ 
+@@ -3356,8 +3260,8 @@ xfs_symlink(
+ 	/*
+ 	 * Create the directory entry for the symlink.
+ 	 */
+-	error = xfs_dir_createname(tp, dp, link_name, link_namelen, ip->i_ino,
+-				   &first_block, &free_list, resblks);
++	error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
++					&first_block, &free_list, resblks);
+ 	if (error)
+ 		goto error1;
+ 	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+@@ -3399,19 +3303,14 @@ xfs_symlink(
+ std_return:
+ 	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTSYMLINK)) {
+ 		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTSYMLINK,
+-					dir_vp, DM_RIGHT_NULL,
+-					error ? NULL : XFS_ITOV(ip),
+-					DM_RIGHT_NULL, link_name, target_path,
+-					0, error, 0);
++					dp, DM_RIGHT_NULL,
++					error ? NULL : ip,
++					DM_RIGHT_NULL, link_name->name,
++					target_path, 0, error, 0);
+ 	}
+ 
+-	if (!error) {
+-		bhv_vnode_t *vp;
+-
+-		ASSERT(ip);
+-		vp = XFS_ITOV(ip);
+-		*vpp = vp;
+-	}
++	if (!error)
++		*ipp = ip;
+ 	return error;
+ 
+  error2:
+@@ -3431,60 +3330,11 @@ std_return:
+ }
+ 
+ int
+-xfs_rwlock(
+-	xfs_inode_t	*ip,
+-	bhv_vrwlock_t	locktype)
+-{
+-	if (S_ISDIR(ip->i_d.di_mode))
+-		return 1;
+-	if (locktype == VRWLOCK_WRITE) {
+-		xfs_ilock(ip, XFS_IOLOCK_EXCL);
+-	} else if (locktype == VRWLOCK_TRY_READ) {
+-		return xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED);
+-	} else if (locktype == VRWLOCK_TRY_WRITE) {
+-		return xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL);
+-	} else {
+-		ASSERT((locktype == VRWLOCK_READ) ||
+-		       (locktype == VRWLOCK_WRITE_DIRECT));
+-		xfs_ilock(ip, XFS_IOLOCK_SHARED);
+-	}
+-
+-	return 1;
+-}
+-
+-
+-void
+-xfs_rwunlock(
+-	xfs_inode_t     *ip,
+-	bhv_vrwlock_t	locktype)
+-{
+- 	if (S_ISDIR(ip->i_d.di_mode))
+-  		return;
+-	if (locktype == VRWLOCK_WRITE) {
+-		/*
+-		 * In the write case, we may have added a new entry to
+-		 * the reference cache.  This might store a pointer to
+-		 * an inode to be released in this inode.  If it is there,
+-		 * clear the pointer and release the inode after unlocking
+-		 * this one.
+-		 */
+-		xfs_refcache_iunlock(ip, XFS_IOLOCK_EXCL);
+-	} else {
+-		ASSERT((locktype == VRWLOCK_READ) ||
+-		       (locktype == VRWLOCK_WRITE_DIRECT));
+-		xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+-	}
+-	return;
+-}
+-
+-
+-int
+ xfs_inode_flush(
+ 	xfs_inode_t	*ip,
+ 	int		flags)
+ {
+ 	xfs_mount_t	*mp = ip->i_mount;
+-	xfs_inode_log_item_t *iip = ip->i_itemp;
+ 	int		error = 0;
+ 
+ 	if (XFS_FORCED_SHUTDOWN(mp))
+@@ -3494,33 +3344,9 @@ xfs_inode_flush(
+ 	 * Bypass inodes which have already been cleaned by
+ 	 * the inode flush clustering code inside xfs_iflush
+ 	 */
+-	if ((ip->i_update_core == 0) &&
+-	    ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL)))
++	if (xfs_inode_clean(ip))
+ 		return 0;
+ 
+-	if (flags & FLUSH_LOG) {
+-		if (iip && iip->ili_last_lsn) {
+-			xlog_t		*log = mp->m_log;
+-			xfs_lsn_t	sync_lsn;
+-			int		log_flags = XFS_LOG_FORCE;
+-
+-			spin_lock(&log->l_grant_lock);
+-			sync_lsn = log->l_last_sync_lsn;
+-			spin_unlock(&log->l_grant_lock);
+-
+-			if ((XFS_LSN_CMP(iip->ili_last_lsn, sync_lsn) > 0)) {
+-				if (flags & FLUSH_SYNC)
+-					log_flags |= XFS_LOG_SYNC;
+-				error = xfs_log_force(mp, iip->ili_last_lsn, log_flags);
+-				if (error)
+-					return error;
+-			}
+-
+-			if (ip->i_update_core == 0)
+-				return 0;
+-		}
+-	}
+-
+ 	/*
+ 	 * We make this non-blocking if the inode is contended,
+ 	 * return EAGAIN to indicate to the caller that they
+@@ -3528,30 +3354,22 @@ xfs_inode_flush(
+ 	 * blocking on inodes inside another operation right
+ 	 * now, they get caught later by xfs_sync.
+ 	 */
+-	if (flags & FLUSH_INODE) {
+-		int	flush_flags;
+-
+-		if (flags & FLUSH_SYNC) {
+-			xfs_ilock(ip, XFS_ILOCK_SHARED);
+-			xfs_iflock(ip);
+-		} else if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
+-			if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) {
+-				xfs_iunlock(ip, XFS_ILOCK_SHARED);
+-				return EAGAIN;
+-			}
+-		} else {
++	if (flags & FLUSH_SYNC) {
++		xfs_ilock(ip, XFS_ILOCK_SHARED);
++		xfs_iflock(ip);
++	} else if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
++		if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) {
++			xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ 			return EAGAIN;
+ 		}
+-
+-		if (flags & FLUSH_SYNC)
+-			flush_flags = XFS_IFLUSH_SYNC;
+-		else
+-			flush_flags = XFS_IFLUSH_ASYNC;
+-
+-		error = xfs_iflush(ip, flush_flags);
+-		xfs_iunlock(ip, XFS_ILOCK_SHARED);
++	} else {
++		return EAGAIN;
+ 	}
+ 
++	error = xfs_iflush(ip, (flags & FLUSH_SYNC) ? XFS_IFLUSH_SYNC
++						    : XFS_IFLUSH_ASYNC_NOBLOCK);
++	xfs_iunlock(ip, XFS_ILOCK_SHARED);
++
+ 	return error;
+ }
+ 
+@@ -3694,12 +3512,12 @@ xfs_finish_reclaim(
+ 	 * We get the flush lock regardless, though, just to make sure
+ 	 * we don't free it while it is being flushed.
+ 	 */
+-	if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+-		if (!locked) {
+-			xfs_ilock(ip, XFS_ILOCK_EXCL);
+-			xfs_iflock(ip);
+-		}
++	if (!locked) {
++		xfs_ilock(ip, XFS_ILOCK_EXCL);
++		xfs_iflock(ip);
++	}
+ 
++	if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+ 		if (ip->i_update_core ||
+ 		    ((ip->i_itemp != NULL) &&
+ 		     (ip->i_itemp->ili_format.ilf_fields != 0))) {
+@@ -3719,17 +3537,11 @@ xfs_finish_reclaim(
+ 		ASSERT(ip->i_update_core == 0);
+ 		ASSERT(ip->i_itemp == NULL ||
+ 		       ip->i_itemp->ili_format.ilf_fields == 0);
+-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+-	} else if (locked) {
+-		/*
+-		 * We are not interested in doing an iflush if we're
+-		 * in the process of shutting down the filesystem forcibly.
+-		 * So, just reclaim the inode.
+-		 */
+-		xfs_ifunlock(ip);
+-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ 	}
+ 
++	xfs_ifunlock(ip);
++	xfs_iunlock(ip, XFS_ILOCK_EXCL);
++
+  reclaim:
+ 	xfs_ireclaim(ip);
+ 	return 0;
+@@ -3845,9 +3657,8 @@ xfs_alloc_file_space(
+ 		end_dmi_offset = offset+len;
+ 		if (end_dmi_offset > ip->i_size)
+ 			end_dmi_offset = ip->i_size;
+-		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
+-			offset, end_dmi_offset - offset,
+-			0, NULL);
++		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, offset,
++				      end_dmi_offset - offset, 0, NULL);
+ 		if (error)
+ 			return error;
+ 	}
+@@ -3956,8 +3767,8 @@ dmapi_enospc_check:
+ 	if (error == ENOSPC && (attr_flags & ATTR_DMI) == 0 &&
+ 	    DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE)) {
+ 		error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE,
+-				XFS_ITOV(ip), DM_RIGHT_NULL,
+-				XFS_ITOV(ip), DM_RIGHT_NULL,
++				ip, DM_RIGHT_NULL,
++				ip, DM_RIGHT_NULL,
+ 				NULL, NULL, 0, 0, 0); /* Delay flag intentionally unused */
+ 		if (error == 0)
+ 			goto retry;	/* Maybe DMAPI app. has made space */
+@@ -4021,7 +3832,8 @@ xfs_zero_remaining_bytes(
+ 		XFS_BUF_READ(bp);
+ 		XFS_BUF_SET_ADDR(bp, XFS_FSB_TO_DB(ip, imap.br_startblock));
+ 		xfsbdstrat(mp, bp);
+-		if ((error = xfs_iowait(bp))) {
++		error = xfs_iowait(bp);
++		if (error) {
+ 			xfs_ioerror_alert("xfs_zero_remaining_bytes(read)",
+ 					  mp, bp, XFS_BUF_ADDR(bp));
+ 			break;
+@@ -4033,7 +3845,8 @@ xfs_zero_remaining_bytes(
+ 		XFS_BUF_UNREAD(bp);
+ 		XFS_BUF_WRITE(bp);
+ 		xfsbdstrat(mp, bp);
+-		if ((error = xfs_iowait(bp))) {
++		error = xfs_iowait(bp);
++		if (error) {
+ 			xfs_ioerror_alert("xfs_zero_remaining_bytes(write)",
+ 					  mp, bp, XFS_BUF_ADDR(bp));
+ 			break;
+@@ -4102,7 +3915,7 @@ xfs_free_file_space(
+ 	    DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
+ 		if (end_dmi_offset > ip->i_size)
+ 			end_dmi_offset = ip->i_size;
+-		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
++		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip,
+ 				offset, end_dmi_offset - offset,
+ 				AT_DELAY_FLAG(attr_flags), NULL);
+ 		if (error)
+diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
+index 4e3970f..24c5392 100644
+--- a/fs/xfs/xfs_vnodeops.h
++++ b/fs/xfs/xfs_vnodeops.h
+@@ -23,31 +23,32 @@ int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start,
+ 		xfs_off_t stop);
+ int xfs_release(struct xfs_inode *ip);
+ int xfs_inactive(struct xfs_inode *ip);
+-int xfs_lookup(struct xfs_inode *dp, bhv_vname_t *dentry,
+-		bhv_vnode_t **vpp);
+-int xfs_create(struct xfs_inode *dp, bhv_vname_t *dentry, mode_t mode,
+-		xfs_dev_t rdev, bhv_vnode_t **vpp, struct cred *credp);
+-int xfs_remove(struct xfs_inode *dp, bhv_vname_t	*dentry);
+-int xfs_link(struct xfs_inode *tdp, bhv_vnode_t *src_vp,
+-		bhv_vname_t *dentry);
+-int xfs_mkdir(struct xfs_inode *dp, bhv_vname_t *dentry,
+-		mode_t mode, bhv_vnode_t **vpp, struct cred *credp);
+-int xfs_rmdir(struct xfs_inode *dp, bhv_vname_t *dentry);
++int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
++		struct xfs_inode **ipp);
++int xfs_create(struct xfs_inode *dp, struct xfs_name *name, mode_t mode,
++		xfs_dev_t rdev, struct xfs_inode **ipp, struct cred *credp);
++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,
++		struct xfs_name *target_name);
++int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
++		mode_t mode, struct xfs_inode **ipp, struct cred *credp);
++int xfs_rmdir(struct xfs_inode *dp, struct xfs_name *name,
++		struct xfs_inode *cdp);
+ 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, bhv_vname_t *dentry,
+-		char *target_path, mode_t mode, bhv_vnode_t **vpp,
++int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
++		const char *target_path, mode_t mode, struct xfs_inode **ipp,
+ 		struct cred *credp);
+-int xfs_rwlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
+-void xfs_rwunlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
+ int xfs_inode_flush(struct xfs_inode *ip, int flags);
+ int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
+ int xfs_reclaim(struct xfs_inode *ip);
+ int xfs_change_file_space(struct xfs_inode *ip, int cmd,
+ 		xfs_flock64_t *bf, xfs_off_t offset,
+ 		struct cred *credp, int	attr_flags);
+-int xfs_rename(struct xfs_inode *src_dp, bhv_vname_t *src_vname,
+-		bhv_vnode_t *target_dir_vp, bhv_vname_t *target_vname);
++int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name,
++		struct xfs_inode *src_ip, struct xfs_inode *target_dp,
++		struct xfs_name *target_name);
+ int xfs_attr_get(struct xfs_inode *ip, const char *name, char *value,
+ 		int *valuelenp, int flags, cred_t *cred);
+ int xfs_attr_set(struct xfs_inode *dp, const char *name, char *value,
+diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h
+index b7bf68d..f44129a 100644
+--- a/include/asm-alpha/ide.h
++++ b/include/asm-alpha/ide.h
+@@ -13,9 +13,6 @@
+ 
+ #ifdef __KERNEL__
+ 
+-
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static inline int ide_default_irq(unsigned long base)
+ {
+ 	switch (base) {
+@@ -40,14 +37,6 @@ static inline unsigned long ide_default_io_base(int index)
+ 	}
+ }
+ 
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_PCI
+-#define ide_init_default_irq(base)	(0)
+-#else
+-#define ide_init_default_irq(base)	ide_default_irq(base)
+-#endif
+-
+ #include <asm-generic/ide_iops.h>
+ 
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h
+index f1e9278..d9b2034 100644
+--- a/include/asm-alpha/semaphore.h
++++ b/include/asm-alpha/semaphore.h
+@@ -1,149 +1 @@
+-#ifndef _ALPHA_SEMAPHORE_H
+-#define _ALPHA_SEMAPHORE_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- * (C) Copyright 1996, 2000 Richard Henderson
+- */
+-
+-#include <asm/current.h>
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <linux/compiler.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)			\
+-{								\
+-	.count	= ATOMIC_INIT(n),				\
+-  	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count)		\
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+-	/*
+-	 * Logically, 
+-	 *   *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+-	 * except that gcc produces better initializing by parts yet.
+-	 */
+-
+-	atomic_set(&sem->count, val);
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-extern void down(struct semaphore *);
+-extern void __down_failed(struct semaphore *);
+-extern int  down_interruptible(struct semaphore *);
+-extern int  __down_failed_interruptible(struct semaphore *);
+-extern int  down_trylock(struct semaphore *);
+-extern void up(struct semaphore *);
+-extern void __up_wakeup(struct semaphore *);
+-
+-/*
+- * Hidden out of line code is fun, but extremely messy.  Rely on newer
+- * compilers to do a respectable job with this.  The contention cases
+- * are handled out of line in arch/alpha/kernel/semaphore.c.
+- */
+-
+-static inline void __down(struct semaphore *sem)
+-{
+-	long count;
+-	might_sleep();
+-	count = atomic_dec_return(&sem->count);
+-	if (unlikely(count < 0))
+-		__down_failed(sem);
+-}
+-
+-static inline int __down_interruptible(struct semaphore *sem)
+-{
+-	long count;
+-	might_sleep();
+-	count = atomic_dec_return(&sem->count);
+-	if (unlikely(count < 0))
+-		return __down_failed_interruptible(sem);
+-	return 0;
+-}
+-
+-/*
+- * down_trylock returns 0 on success, 1 if we failed to get the lock.
+- */
+-
+-static inline int __down_trylock(struct semaphore *sem)
+-{
+-	long ret;
+-
+-	/* "Equivalent" C:
+-
+-	   do {
+-		ret = ldl_l;
+-		--ret;
+-		if (ret < 0)
+-			break;
+-		ret = stl_c = ret;
+-	   } while (ret == 0);
+-	*/
+-	__asm__ __volatile__(
+-		"1:	ldl_l	%0,%1\n"
+-		"	subl	%0,1,%0\n"
+-		"	blt	%0,2f\n"
+-		"	stl_c	%0,%1\n"
+-		"	beq	%0,3f\n"
+-		"	mb\n"
+-		"2:\n"
+-		".subsection 2\n"
+-		"3:	br	1b\n"
+-		".previous"
+-		: "=&r" (ret), "=m" (sem->count)
+-		: "m" (sem->count));
+-
+-	return ret < 0;
+-}
+-
+-static inline void __up(struct semaphore *sem)
+-{
+-	if (unlikely(atomic_inc_return(&sem->count) <= 0))
+-		__up_wakeup(sem);
+-}
+-
+-#if !defined(CONFIG_DEBUG_SEMAPHORE)
+-extern inline void down(struct semaphore *sem)
+-{
+-	__down(sem);
+-}
+-extern inline int down_interruptible(struct semaphore *sem)
+-{
+-	return __down_interruptible(sem);
+-}
+-extern inline int down_trylock(struct semaphore *sem)
+-{
+-	return __down_trylock(sem);
+-}
+-extern inline void up(struct semaphore *sem)
+-{
+-	__up(sem);
+-}
+-#endif
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-alpha/topology.h b/include/asm-alpha/topology.h
+index 420ccde..149532e 100644
+--- a/include/asm-alpha/topology.h
++++ b/include/asm-alpha/topology.h
+@@ -41,8 +41,7 @@ static inline cpumask_t node_to_cpumask(int node)
+ 
+ #define pcibus_to_cpumask(bus)	(cpu_online_map)
+ 
+-#else /* CONFIG_NUMA */
+-# include <asm-generic/topology.h>
+ #endif /* !CONFIG_NUMA */
++# include <asm-generic/topology.h>
+ 
+ #endif /* _ASM_ALPHA_TOPOLOGY_H */
+diff --git a/include/asm-arm/arch-at91/at91_ecc.h b/include/asm-arm/arch-at91/at91_ecc.h
+index ff93df5..1e5a8ca 100644
+--- a/include/asm-arm/arch-at91/at91_ecc.h
++++ b/include/asm-arm/arch-at91/at91_ecc.h
+@@ -13,26 +13,26 @@
+ #ifndef AT91_ECC_H
+ #define AT91_ECC_H
+ 
+-#define AT91_ECC_CR		(AT91_ECC + 0x00)	/* Control register */
++#define AT91_ECC_CR		0x00			/* Control register */
+ #define		AT91_ECC_RST		(1 << 0)		/* Reset parity */
+ 
+-#define AT91_ECC_MR		(AT91_ECC + 0x04)	/* Mode register */
++#define AT91_ECC_MR		0x04			/* Mode register */
+ #define		AT91_ECC_PAGESIZE	(3 << 0)		/* Page Size */
+ #define			AT91_ECC_PAGESIZE_528		(0)
+ #define			AT91_ECC_PAGESIZE_1056		(1)
+ #define			AT91_ECC_PAGESIZE_2112		(2)
+ #define			AT91_ECC_PAGESIZE_4224		(3)
+ 
+-#define AT91_ECC_SR		(AT91_ECC + 0x08)	/* Status register */
++#define AT91_ECC_SR		0x08			/* Status register */
+ #define		AT91_ECC_RECERR		(1 << 0)		/* Recoverable Error */
+ #define		AT91_ECC_ECCERR		(1 << 1)		/* ECC Single Bit Error */
+ #define		AT91_ECC_MULERR		(1 << 2)		/* Multiple Errors */
+ 
+-#define AT91_ECC_PR		(AT91_ECC + 0x0c)	/* Parity register */
++#define AT91_ECC_PR		0x0c			/* Parity register */
+ #define		AT91_ECC_BITADDR	(0xf << 0)		/* Bit Error Address */
+ #define		AT91_ECC_WORDADDR	(0xfff << 4)		/* Word Error Address */
+ 
+-#define AT91_ECC_NPR		(AT91_ECC + 0x10)	/* NParity register */
++#define AT91_ECC_NPR		0x10			/* NParity register */
+ #define		AT91_ECC_NPARITY	(0xffff << 0)		/* NParity */
+ 
+ #endif
+diff --git a/include/asm-arm/arch-at91/at91_pmc.h b/include/asm-arm/arch-at91/at91_pmc.h
+index 52cd8e5..c2b13c2 100644
+--- a/include/asm-arm/arch-at91/at91_pmc.h
++++ b/include/asm-arm/arch-at91/at91_pmc.h
+@@ -76,10 +76,17 @@
+ #define			AT91_PMC_PRES_32		(5 << 2)
+ #define			AT91_PMC_PRES_64		(6 << 2)
+ #define		AT91_PMC_MDIV		(3 <<  8)		/* Master Clock Division */
+-#define			AT91_PMC_MDIV_1			(0 << 8)
+-#define			AT91_PMC_MDIV_2			(1 << 8)
+-#define			AT91_PMC_MDIV_3			(2 << 8)
+-#define			AT91_PMC_MDIV_4			(3 << 8)
++#define			AT91RM9200_PMC_MDIV_1		(0 << 8)	/* [AT91RM9200 only] */
++#define			AT91RM9200_PMC_MDIV_2		(1 << 8)
++#define			AT91RM9200_PMC_MDIV_3		(2 << 8)
++#define			AT91RM9200_PMC_MDIV_4		(3 << 8)
++#define			AT91SAM9_PMC_MDIV_1		(0 << 8)	/* [SAM9,CAP9 only] */
++#define			AT91SAM9_PMC_MDIV_2		(1 << 8)
++#define			AT91SAM9_PMC_MDIV_4		(2 << 8)
++#define			AT91SAM9_PMC_MDIV_6		(3 << 8)
++#define		AT91_PMC_PDIV		(1 << 12)		/* Processor Clock Division [some SAM9 only] */
++#define			AT91_PMC_PDIV_1			(0 << 12)
++#define			AT91_PMC_PDIV_2			(1 << 12)
+ 
+ #define	AT91_PMC_PCKR(n)	(AT91_PMC + 0x40 + ((n) * 4))	/* Programmable Clock 0-3 Registers */
+ 
+diff --git a/include/asm-arm/arch-at91/at91_shdwc.h b/include/asm-arm/arch-at91/at91_shdwc.h
+index 01b433d..581fa41 100644
+--- a/include/asm-arm/arch-at91/at91_shdwc.h
++++ b/include/asm-arm/arch-at91/at91_shdwc.h
+@@ -24,10 +24,12 @@
+ #define			AT91_SHDW_WKMODE0_LOW		2
+ #define			AT91_SHDW_WKMODE0_ANYLEVEL	3
+ #define		AT91_SHDW_CPTWK0	(0xf << 4)		/* Counter On Wake Up 0 */
++#define			AT91_SHDW_CPTWK0_(x)	((x) << 4)
+ #define		AT91_SHDW_RTTWKEN	(1   << 16)		/* Real Time Timer Wake-up Enable */
+ 
+ #define AT91_SHDW_SR		(AT91_SHDWC + 0x08)	/* Shut Down Status Register */
+ #define		AT91_SHDW_WAKEUP0	(1 <<  0)		/* Wake-up 0 Status */
+ #define		AT91_SHDW_RTTWK		(1 << 16)		/* Real-time Timer Wake-up */
++#define		AT91_SHDW_RTCWK		(1 << 17)		/* Real-time Clock Wake-up [SAM9RL] */
+ 
+ #endif
+diff --git a/include/asm-arm/arch-at91/at91cap9_ddrsdr.h b/include/asm-arm/arch-at91/at91cap9_ddrsdr.h
+new file mode 100644
+index 0000000..efdb23a
+--- /dev/null
++++ b/include/asm-arm/arch-at91/at91cap9_ddrsdr.h
+@@ -0,0 +1,100 @@
++/*
++ * include/asm-arm/arch-at91/at91cap9_ddrsdr.h
++ *
++ * DDR/SDR Controller (DDRSDRC) - System peripherals registers.
++ * Based on AT91CAP9 datasheet revision B.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the 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 AT91CAP9_DDRSDR_H
++#define AT91CAP9_DDRSDR_H
++
++#define AT91_DDRSDRC_MR		(AT91_DDRSDRC + 0x00)	/* Mode Register */
++#define		AT91_DDRSDRC_MODE	(0xf << 0)		/* Command Mode */
++#define			AT91_DDRSDRC_MODE_NORMAL		0
++#define			AT91_DDRSDRC_MODE_NOP		1
++#define			AT91_DDRSDRC_MODE_PRECHARGE	2
++#define			AT91_DDRSDRC_MODE_LMR		3
++#define			AT91_DDRSDRC_MODE_REFRESH	4
++#define			AT91_DDRSDRC_MODE_EXT_LMR	5
++#define			AT91_DDRSDRC_MODE_DEEP		6
++
++#define AT91_DDRSDRC_RTR	(AT91_DDRSDRC + 0x04)	/* Refresh Timer Register */
++#define		AT91_DDRSDRC_COUNT	(0xfff << 0)		/* Refresh Timer Counter */
++
++#define AT91_DDRSDRC_CR		(AT91_DDRSDRC + 0x08)	/* Configuration Register */
++#define		AT91_DDRSDRC_NC		(3 << 0)		/* Number of Column Bits */
++#define			AT91_DDRSDRC_NC_SDR8	(0 << 0)
++#define			AT91_DDRSDRC_NC_SDR9	(1 << 0)
++#define			AT91_DDRSDRC_NC_SDR10	(2 << 0)
++#define			AT91_DDRSDRC_NC_SDR11	(3 << 0)
++#define			AT91_DDRSDRC_NC_DDR9	(0 << 0)
++#define			AT91_DDRSDRC_NC_DDR10	(1 << 0)
++#define			AT91_DDRSDRC_NC_DDR11	(2 << 0)
++#define			AT91_DDRSDRC_NC_DDR12	(3 << 0)
++#define		AT91_DDRSDRC_NR		(3 << 2)		/* Number of Row Bits */
++#define			AT91_DDRSDRC_NR_11	(0 << 2)
++#define			AT91_DDRSDRC_NR_12	(1 << 2)
++#define			AT91_DDRSDRC_NR_13	(2 << 2)
++#define		AT91_DDRSDRC_CAS	(7 << 4)		/* CAS Latency */
++#define			AT91_DDRSDRC_CAS_2	(2 << 4)
++#define			AT91_DDRSDRC_CAS_3	(3 << 4)
++#define			AT91_DDRSDRC_CAS_25	(6 << 4)
++#define		AT91_DDRSDRC_DLL	(1 << 7)		/* Reset DLL */
++#define		AT91_DDRSDRC_DICDS	(1 << 8)		/* Output impedance control */
++
++#define AT91_DDRSDRC_T0PR	(AT91_DDRSDRC + 0x0C)	/* Timing 0 Register */
++#define		AT91_DDRSDRC_TRAS	(0xf <<  0)		/* Active to Precharge delay */
++#define		AT91_DDRSDRC_TRCD	(0xf <<  4)		/* Row to Column delay */
++#define		AT91_DDRSDRC_TWR	(0xf <<  8)		/* Write recovery delay */
++#define		AT91_DDRSDRC_TRC	(0xf << 12)		/* Row cycle delay */
++#define		AT91_DDRSDRC_TRP	(0xf << 16)		/* Row precharge delay */
++#define		AT91_DDRSDRC_TRRD	(0xf << 20)		/* Active BankA to BankB */
++#define		AT91_DDRSDRC_TWTR	(1   << 24)		/* Internal Write to Read delay */
++#define		AT91_DDRSDRC_TMRD	(0xf << 28)		/* Load mode to active/refresh delay */
++
++#define AT91_DDRSDRC_T1PR	(AT91_DDRSDRC + 0x10)	/* Timing 1 Register */
++#define		AT91_DDRSDRC_TRFC	(0x1f << 0)		/* Row Cycle Delay */
++#define		AT91_DDRSDRC_TXSNR	(0xff << 8)		/* Exit self-refresh to non-read */
++#define		AT91_DDRSDRC_TXSRD	(0xff << 16)		/* Exit self-refresh to read */
++#define		AT91_DDRSDRC_TXP	(0xf  << 24)		/* Exit power-down delay */
++
++#define AT91_DDRSDRC_LPR	(AT91_DDRSDRC + 0x18)	/* Low Power Register */
++#define		AT91_DDRSDRC_LPCB		(3 << 0)	/* Low-power Configurations */
++#define			AT91_DDRSDRC_LPCB_DISABLE		0
++#define			AT91_DDRSDRC_LPCB_SELF_REFRESH		1
++#define			AT91_DDRSDRC_LPCB_POWER_DOWN		2
++#define			AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN	3
++#define		AT91_DDRSDRC_CLKFR		(1 << 2)	/* Clock Frozen */
++#define		AT91_DDRSDRC_PASR		(7 << 4)	/* Partial Array Self Refresh */
++#define		AT91_DDRSDRC_TCSR		(3 << 8)	/* Temperature Compensated Self Refresh */
++#define		AT91_DDRSDRC_DS			(3 << 10)	/* Drive Strength */
++#define		AT91_DDRSDRC_TIMEOUT		(3 << 12)	/* Time to define when Low Power Mode is enabled */
++#define			AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES	(0 << 12)
++#define			AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES	(1 << 12)
++#define			AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES	(2 << 12)
++
++#define AT91_DDRSDRC_MDR	(AT91_DDRSDRC + 0x1C)	/* Memory Device Register */
++#define		AT91_DDRSDRC_MD		(3 << 0)		/* Memory Device Type */
++#define			AT91_DDRSDRC_MD_SDR		0
++#define			AT91_DDRSDRC_MD_LOW_POWER_SDR	1
++#define			AT91_DDRSDRC_MD_DDR		2
++#define			AT91_DDRSDRC_MD_LOW_POWER_DDR	3
++
++#define AT91_DDRSDRC_DLLR	(AT91_DDRSDRC + 0x20)	/* DLL Information Register */
++#define		AT91_DDRSDRC_MDINC	(1 << 0)		/* Master Delay increment */
++#define		AT91_DDRSDRC_MDDEC	(1 << 1)		/* Master Delay decrement */
++#define		AT91_DDRSDRC_MDOVF	(1 << 2)		/* Master Delay Overflow */
++#define		AT91_DDRSDRC_SDCOVF	(1 << 3)		/* Slave Delay Correction Overflow */
++#define		AT91_DDRSDRC_SDCUDF	(1 << 4)		/* Slave Delay Correction Underflow */
++#define		AT91_DDRSDRC_SDERF	(1 << 5)		/* Slave Delay Correction error */
++#define		AT91_DDRSDRC_MDVAL	(0xff <<  8)		/* Master Delay value */
++#define		AT91_DDRSDRC_SDVAL	(0xff << 16)		/* Slave Delay value */
++#define		AT91_DDRSDRC_SDCVAL	(0xff << 24)		/* Slave Delay Correction value */
++
++
++#endif
+diff --git a/include/asm-arm/arch-at91/at91sam926x_mc.h b/include/asm-arm/arch-at91/at91sam926x_mc.h
+deleted file mode 100644
+index d82631c..0000000
+--- a/include/asm-arm/arch-at91/at91sam926x_mc.h
++++ /dev/null
+@@ -1,141 +0,0 @@
+-/*
+- * include/asm-arm/arch-at91/at91sam926x_mc.h
+- *
+- * Memory Controllers (SMC, SDRAMC) - System peripherals registers.
+- * Based on AT91SAM9261 datasheet revision D.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the 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 AT91SAM926x_MC_H
+-#define AT91SAM926x_MC_H
+-
+-/* SDRAM Controller (SDRAMC) registers */
+-#define AT91_SDRAMC_MR		(AT91_SDRAMC + 0x00)	/* SDRAM Controller Mode Register */
+-#define		AT91_SDRAMC_MODE	(0xf << 0)		/* Command Mode */
+-#define			AT91_SDRAMC_MODE_NORMAL		0
+-#define			AT91_SDRAMC_MODE_NOP		1
+-#define			AT91_SDRAMC_MODE_PRECHARGE	2
+-#define			AT91_SDRAMC_MODE_LMR		3
+-#define			AT91_SDRAMC_MODE_REFRESH	4
+-#define			AT91_SDRAMC_MODE_EXT_LMR	5
+-#define			AT91_SDRAMC_MODE_DEEP		6
+-
+-#define AT91_SDRAMC_TR		(AT91_SDRAMC + 0x04)	/* SDRAM Controller Refresh Timer Register */
+-#define		AT91_SDRAMC_COUNT	(0xfff << 0)		/* Refresh Timer Counter */
+-
+-#define AT91_SDRAMC_CR		(AT91_SDRAMC + 0x08)	/* SDRAM Controller Configuration Register */
+-#define		AT91_SDRAMC_NC		(3 << 0)		/* Number of Column Bits */
+-#define			AT91_SDRAMC_NC_8	(0 << 0)
+-#define			AT91_SDRAMC_NC_9	(1 << 0)
+-#define			AT91_SDRAMC_NC_10	(2 << 0)
+-#define			AT91_SDRAMC_NC_11	(3 << 0)
+-#define		AT91_SDRAMC_NR		(3 << 2)		/* Number of Row Bits */
+-#define			AT91_SDRAMC_NR_11	(0 << 2)
+-#define			AT91_SDRAMC_NR_12	(1 << 2)
+-#define			AT91_SDRAMC_NR_13	(2 << 2)
+-#define		AT91_SDRAMC_NB		(1 << 4)		/* Number of Banks */
+-#define			AT91_SDRAMC_NB_2	(0 << 4)
+-#define			AT91_SDRAMC_NB_4	(1 << 4)
+-#define		AT91_SDRAMC_CAS		(3 << 5)		/* CAS Latency */
+-#define			AT91_SDRAMC_CAS_1	(1 << 5)
+-#define			AT91_SDRAMC_CAS_2	(2 << 5)
+-#define			AT91_SDRAMC_CAS_3	(3 << 5)
+-#define		AT91_SDRAMC_DBW		(1 << 7)		/* Data Bus Width */
+-#define			AT91_SDRAMC_DBW_32	(0 << 7)
+-#define			AT91_SDRAMC_DBW_16	(1 << 7)
+-#define		AT91_SDRAMC_TWR		(0xf <<  8)		/* Write Recovery Delay */
+-#define		AT91_SDRAMC_TRC		(0xf << 12)		/* Row Cycle Delay */
+-#define		AT91_SDRAMC_TRP		(0xf << 16)		/* Row Precharge Delay */
+-#define		AT91_SDRAMC_TRCD	(0xf << 20)		/* Row to Column Delay */
+-#define		AT91_SDRAMC_TRAS	(0xf << 24)		/* Active to Precharge Delay */
+-#define		AT91_SDRAMC_TXSR	(0xf << 28)		/* Exit Self Refresh to Active Delay */
+-
+-#define AT91_SDRAMC_LPR		(AT91_SDRAMC + 0x10)	/* SDRAM Controller Low Power Register */
+-#define		AT91_SDRAMC_LPCB		(3 << 0)	/* Low-power Configurations */
+-#define			AT91_SDRAMC_LPCB_DISABLE		0
+-#define			AT91_SDRAMC_LPCB_SELF_REFRESH		1
+-#define			AT91_SDRAMC_LPCB_POWER_DOWN		2
+-#define			AT91_SDRAMC_LPCB_DEEP_POWER_DOWN	3
+-#define		AT91_SDRAMC_PASR		(7 << 4)	/* Partial Array Self Refresh */
+-#define		AT91_SDRAMC_TCSR		(3 << 8)	/* Temperature Compensated Self Refresh */
+-#define		AT91_SDRAMC_DS			(3 << 10)	/* Drive Strenght */
+-#define		AT91_SDRAMC_TIMEOUT		(3 << 12)	/* Time to define when Low Power Mode is enabled */
+-#define			AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES	(0 << 12)
+-#define			AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES	(1 << 12)
+-#define			AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES	(2 << 12)
+-
+-#define AT91_SDRAMC_IER		(AT91_SDRAMC + 0x14)	/* SDRAM Controller Interrupt Enable Register */
+-#define AT91_SDRAMC_IDR		(AT91_SDRAMC + 0x18)	/* SDRAM Controller Interrupt Disable Register */
+-#define AT91_SDRAMC_IMR		(AT91_SDRAMC + 0x1C)	/* SDRAM Controller Interrupt Mask Register */
+-#define AT91_SDRAMC_ISR		(AT91_SDRAMC + 0x20)	/* SDRAM Controller Interrupt Status Register */
+-#define		AT91_SDRAMC_RES		(1 << 0)		/* Refresh Error Status */
+-
+-#define AT91_SDRAMC_MDR		(AT91_SDRAMC + 0x24)	/* SDRAM Memory Device Register */
+-#define		AT91_SDRAMC_MD		(3 << 0)		/* Memory Device Type */
+-#define			AT91_SDRAMC_MD_SDRAM		0
+-#define			AT91_SDRAMC_MD_LOW_POWER_SDRAM	1
+-
+-
+-/* Static Memory Controller (SMC) registers */
+-#define AT91_SMC_SETUP(n)	(AT91_SMC + 0x00 + ((n)*0x10))	/* Setup Register for CS n */
+-#define		AT91_SMC_NWESETUP	(0x3f << 0)			/* NWE Setup Length */
+-#define			AT91_SMC_NWESETUP_(x)	((x) << 0)
+-#define		AT91_SMC_NCS_WRSETUP	(0x3f << 8)			/* NCS Setup Length in Write Access */
+-#define			AT91_SMC_NCS_WRSETUP_(x)	((x) << 8)
+-#define		AT91_SMC_NRDSETUP	(0x3f << 16)			/* NRD Setup Length */
+-#define			AT91_SMC_NRDSETUP_(x)	((x) << 16)
+-#define		AT91_SMC_NCS_RDSETUP	(0x3f << 24)			/* NCS Setup Length in Read Access */
+-#define			AT91_SMC_NCS_RDSETUP_(x)	((x) << 24)
+-
+-#define AT91_SMC_PULSE(n)	(AT91_SMC + 0x04 + ((n)*0x10))	/* Pulse Register for CS n */
+-#define		AT91_SMC_NWEPULSE	(0x7f <<  0)			/* NWE Pulse Length */
+-#define			AT91_SMC_NWEPULSE_(x)	((x) << 0)
+-#define		AT91_SMC_NCS_WRPULSE	(0x7f <<  8)			/* NCS Pulse Length in Write Access */
+-#define			AT91_SMC_NCS_WRPULSE_(x)((x) << 8)
+-#define		AT91_SMC_NRDPULSE	(0x7f << 16)			/* NRD Pulse Length */
+-#define			AT91_SMC_NRDPULSE_(x)	((x) << 16)
+-#define		AT91_SMC_NCS_RDPULSE	(0x7f << 24)			/* NCS Pulse Length in Read Access */
+-#define			AT91_SMC_NCS_RDPULSE_(x)((x) << 24)
+-
+-#define AT91_SMC_CYCLE(n)	(AT91_SMC + 0x08 + ((n)*0x10))	/* Cycle Register for CS n */
+-#define		AT91_SMC_NWECYCLE	(0x1ff << 0 )			/* Total Write Cycle Length */
+-#define			AT91_SMC_NWECYCLE_(x)	((x) << 0)
+-#define		AT91_SMC_NRDCYCLE	(0x1ff << 16)			/* Total Read Cycle Length */
+-#define			AT91_SMC_NRDCYCLE_(x)	((x) << 16)
+-
+-#define AT91_SMC_MODE(n)	(AT91_SMC + 0x0c + ((n)*0x10))	/* Mode Register for CS n */
+-#define		AT91_SMC_READMODE	(1 <<  0)			/* Read Mode */
+-#define		AT91_SMC_WRITEMODE	(1 <<  1)			/* Write Mode */
+-#define		AT91_SMC_EXNWMODE	(3 <<  4)			/* NWAIT Mode */
+-#define			AT91_SMC_EXNWMODE_DISABLE	(0 << 4)
+-#define			AT91_SMC_EXNWMODE_FROZEN	(2 << 4)
+-#define			AT91_SMC_EXNWMODE_READY		(3 << 4)
+-#define		AT91_SMC_BAT		(1 <<  8)			/* Byte Access Type */
+-#define			AT91_SMC_BAT_SELECT		(0 << 8)
+-#define			AT91_SMC_BAT_WRITE		(1 << 8)
+-#define		AT91_SMC_DBW		(3 << 12)			/* Data Bus Width */
+-#define			AT91_SMC_DBW_8			(0 << 12)
+-#define			AT91_SMC_DBW_16			(1 << 12)
+-#define			AT91_SMC_DBW_32			(2 << 12)
+-#define		AT91_SMC_TDF		(0xf << 16)			/* Data Float Time. */
+-#define			AT91_SMC_TDF_(x)		((x) << 16)
+-#define		AT91_SMC_TDFMODE	(1 << 20)			/* TDF Optimization - Enabled */
+-#define		AT91_SMC_PMEN		(1 << 24)			/* Page Mode Enabled */
+-#define		AT91_SMC_PS		(3 << 28)			/* Page Size */
+-#define			AT91_SMC_PS_4			(0 << 28)
+-#define			AT91_SMC_PS_8			(1 << 28)
+-#define			AT91_SMC_PS_16			(2 << 28)
+-#define			AT91_SMC_PS_32			(3 << 28)
+-
+-#if defined(AT91_SMC1)		/* The AT91SAM9263 has 2 Static Memory contollers */
+-#define AT91_SMC1_SETUP(n)	(AT91_SMC1 + 0x00 + ((n)*0x10))	/* Setup Register for CS n */
+-#define AT91_SMC1_PULSE(n)	(AT91_SMC1 + 0x04 + ((n)*0x10))	/* Pulse Register for CS n */
+-#define AT91_SMC1_CYCLE(n)	(AT91_SMC1 + 0x08 + ((n)*0x10))	/* Cycle Register for CS n */
+-#define AT91_SMC1_MODE(n)	(AT91_SMC1 + 0x0c + ((n)*0x10))	/* Mode Register for CS n */
+-#endif
+-
+-#endif
+diff --git a/include/asm-arm/arch-at91/at91sam9_sdramc.h b/include/asm-arm/arch-at91/at91sam9_sdramc.h
+new file mode 100644
+index 0000000..d3b8b3d
+--- /dev/null
++++ b/include/asm-arm/arch-at91/at91sam9_sdramc.h
+@@ -0,0 +1,83 @@
++/*
++ * include/asm-arm/arch-at91/at91sam9_sdramc.h
++ *
++ * SDRAM Controllers (SDRAMC) - System peripherals registers.
++ * Based on AT91SAM9261 datasheet revision D.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the 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 AT91SAM9_SDRAMC_H
++#define AT91SAM9_SDRAMC_H
++
++/* SDRAM Controller (SDRAMC) registers */
++#define AT91_SDRAMC_MR		(AT91_SDRAMC + 0x00)	/* SDRAM Controller Mode Register */
++#define		AT91_SDRAMC_MODE	(0xf << 0)		/* Command Mode */
++#define			AT91_SDRAMC_MODE_NORMAL		0
++#define			AT91_SDRAMC_MODE_NOP		1
++#define			AT91_SDRAMC_MODE_PRECHARGE	2
++#define			AT91_SDRAMC_MODE_LMR		3
++#define			AT91_SDRAMC_MODE_REFRESH	4
++#define			AT91_SDRAMC_MODE_EXT_LMR	5
++#define			AT91_SDRAMC_MODE_DEEP		6
++
++#define AT91_SDRAMC_TR		(AT91_SDRAMC + 0x04)	/* SDRAM Controller Refresh Timer Register */
++#define		AT91_SDRAMC_COUNT	(0xfff << 0)		/* Refresh Timer Counter */
++
++#define AT91_SDRAMC_CR		(AT91_SDRAMC + 0x08)	/* SDRAM Controller Configuration Register */
++#define		AT91_SDRAMC_NC		(3 << 0)		/* Number of Column Bits */
++#define			AT91_SDRAMC_NC_8	(0 << 0)
++#define			AT91_SDRAMC_NC_9	(1 << 0)
++#define			AT91_SDRAMC_NC_10	(2 << 0)
++#define			AT91_SDRAMC_NC_11	(3 << 0)
++#define		AT91_SDRAMC_NR		(3 << 2)		/* Number of Row Bits */
++#define			AT91_SDRAMC_NR_11	(0 << 2)
++#define			AT91_SDRAMC_NR_12	(1 << 2)
++#define			AT91_SDRAMC_NR_13	(2 << 2)
++#define		AT91_SDRAMC_NB		(1 << 4)		/* Number of Banks */
++#define			AT91_SDRAMC_NB_2	(0 << 4)
++#define			AT91_SDRAMC_NB_4	(1 << 4)
++#define		AT91_SDRAMC_CAS		(3 << 5)		/* CAS Latency */
++#define			AT91_SDRAMC_CAS_1	(1 << 5)
++#define			AT91_SDRAMC_CAS_2	(2 << 5)
++#define			AT91_SDRAMC_CAS_3	(3 << 5)
++#define		AT91_SDRAMC_DBW		(1 << 7)		/* Data Bus Width */
++#define			AT91_SDRAMC_DBW_32	(0 << 7)
++#define			AT91_SDRAMC_DBW_16	(1 << 7)
++#define		AT91_SDRAMC_TWR		(0xf <<  8)		/* Write Recovery Delay */
++#define		AT91_SDRAMC_TRC		(0xf << 12)		/* Row Cycle Delay */
++#define		AT91_SDRAMC_TRP		(0xf << 16)		/* Row Precharge Delay */
++#define		AT91_SDRAMC_TRCD	(0xf << 20)		/* Row to Column Delay */
++#define		AT91_SDRAMC_TRAS	(0xf << 24)		/* Active to Precharge Delay */
++#define		AT91_SDRAMC_TXSR	(0xf << 28)		/* Exit Self Refresh to Active Delay */
++
++#define AT91_SDRAMC_LPR		(AT91_SDRAMC + 0x10)	/* SDRAM Controller Low Power Register */
++#define		AT91_SDRAMC_LPCB		(3 << 0)	/* Low-power Configurations */
++#define			AT91_SDRAMC_LPCB_DISABLE		0
++#define			AT91_SDRAMC_LPCB_SELF_REFRESH		1
++#define			AT91_SDRAMC_LPCB_POWER_DOWN		2
++#define			AT91_SDRAMC_LPCB_DEEP_POWER_DOWN	3
++#define		AT91_SDRAMC_PASR		(7 << 4)	/* Partial Array Self Refresh */
++#define		AT91_SDRAMC_TCSR		(3 << 8)	/* Temperature Compensated Self Refresh */
++#define		AT91_SDRAMC_DS			(3 << 10)	/* Drive Strength */
++#define		AT91_SDRAMC_TIMEOUT		(3 << 12)	/* Time to define when Low Power Mode is enabled */
++#define			AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES	(0 << 12)
++#define			AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES	(1 << 12)
++#define			AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES	(2 << 12)
++
++#define AT91_SDRAMC_IER		(AT91_SDRAMC + 0x14)	/* SDRAM Controller Interrupt Enable Register */
++#define AT91_SDRAMC_IDR		(AT91_SDRAMC + 0x18)	/* SDRAM Controller Interrupt Disable Register */
++#define AT91_SDRAMC_IMR		(AT91_SDRAMC + 0x1C)	/* SDRAM Controller Interrupt Mask Register */
++#define AT91_SDRAMC_ISR		(AT91_SDRAMC + 0x20)	/* SDRAM Controller Interrupt Status Register */
++#define		AT91_SDRAMC_RES		(1 << 0)		/* Refresh Error Status */
++
++#define AT91_SDRAMC_MDR		(AT91_SDRAMC + 0x24)	/* SDRAM Memory Device Register */
++#define		AT91_SDRAMC_MD		(3 << 0)		/* Memory Device Type */
++#define			AT91_SDRAMC_MD_SDRAM		0
++#define			AT91_SDRAMC_MD_LOW_POWER_SDRAM	1
++
++
++#endif
+diff --git a/include/asm-arm/arch-at91/at91sam9_smc.h b/include/asm-arm/arch-at91/at91sam9_smc.h
+new file mode 100644
+index 0000000..9e49eed
+--- /dev/null
++++ b/include/asm-arm/arch-at91/at91sam9_smc.h
+@@ -0,0 +1,73 @@
++/*
++ * include/asm-arm/arch-at91/at91sam9_smc.h
++ *
++ * Static Memory Controllers (SMC) - System peripherals registers.
++ * Based on AT91SAM9261 datasheet revision D.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the 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 AT91SAM9_SMC_H
++#define AT91SAM9_SMC_H
++
++#define AT91_SMC_SETUP(n)	(AT91_SMC + 0x00 + ((n)*0x10))	/* Setup Register for CS n */
++#define		AT91_SMC_NWESETUP	(0x3f << 0)			/* NWE Setup Length */
++#define			AT91_SMC_NWESETUP_(x)	((x) << 0)
++#define		AT91_SMC_NCS_WRSETUP	(0x3f << 8)			/* NCS Setup Length in Write Access */
++#define			AT91_SMC_NCS_WRSETUP_(x)	((x) << 8)
++#define		AT91_SMC_NRDSETUP	(0x3f << 16)			/* NRD Setup Length */
++#define			AT91_SMC_NRDSETUP_(x)	((x) << 16)
++#define		AT91_SMC_NCS_RDSETUP	(0x3f << 24)			/* NCS Setup Length in Read Access */
++#define			AT91_SMC_NCS_RDSETUP_(x)	((x) << 24)
++
++#define AT91_SMC_PULSE(n)	(AT91_SMC + 0x04 + ((n)*0x10))	/* Pulse Register for CS n */
++#define		AT91_SMC_NWEPULSE	(0x7f <<  0)			/* NWE Pulse Length */
++#define			AT91_SMC_NWEPULSE_(x)	((x) << 0)
++#define		AT91_SMC_NCS_WRPULSE	(0x7f <<  8)			/* NCS Pulse Length in Write Access */
++#define			AT91_SMC_NCS_WRPULSE_(x)((x) << 8)
++#define		AT91_SMC_NRDPULSE	(0x7f << 16)			/* NRD Pulse Length */
++#define			AT91_SMC_NRDPULSE_(x)	((x) << 16)
++#define		AT91_SMC_NCS_RDPULSE	(0x7f << 24)			/* NCS Pulse Length in Read Access */
++#define			AT91_SMC_NCS_RDPULSE_(x)((x) << 24)
++
++#define AT91_SMC_CYCLE(n)	(AT91_SMC + 0x08 + ((n)*0x10))	/* Cycle Register for CS n */
++#define		AT91_SMC_NWECYCLE	(0x1ff << 0 )			/* Total Write Cycle Length */
++#define			AT91_SMC_NWECYCLE_(x)	((x) << 0)
++#define		AT91_SMC_NRDCYCLE	(0x1ff << 16)			/* Total Read Cycle Length */
++#define			AT91_SMC_NRDCYCLE_(x)	((x) << 16)
++
++#define AT91_SMC_MODE(n)	(AT91_SMC + 0x0c + ((n)*0x10))	/* Mode Register for CS n */
++#define		AT91_SMC_READMODE	(1 <<  0)			/* Read Mode */
++#define		AT91_SMC_WRITEMODE	(1 <<  1)			/* Write Mode */
++#define		AT91_SMC_EXNWMODE	(3 <<  4)			/* NWAIT Mode */
++#define			AT91_SMC_EXNWMODE_DISABLE	(0 << 4)
++#define			AT91_SMC_EXNWMODE_FROZEN	(2 << 4)
++#define			AT91_SMC_EXNWMODE_READY		(3 << 4)
++#define		AT91_SMC_BAT		(1 <<  8)			/* Byte Access Type */
++#define			AT91_SMC_BAT_SELECT		(0 << 8)
++#define			AT91_SMC_BAT_WRITE		(1 << 8)
++#define		AT91_SMC_DBW		(3 << 12)			/* Data Bus Width */
++#define			AT91_SMC_DBW_8			(0 << 12)
++#define			AT91_SMC_DBW_16			(1 << 12)
++#define			AT91_SMC_DBW_32			(2 << 12)
++#define		AT91_SMC_TDF		(0xf << 16)			/* Data Float Time. */
++#define			AT91_SMC_TDF_(x)		((x) << 16)
++#define		AT91_SMC_TDFMODE	(1 << 20)			/* TDF Optimization - Enabled */
++#define		AT91_SMC_PMEN		(1 << 24)			/* Page Mode Enabled */
++#define		AT91_SMC_PS		(3 << 28)			/* Page Size */
++#define			AT91_SMC_PS_4			(0 << 28)
++#define			AT91_SMC_PS_8			(1 << 28)
++#define			AT91_SMC_PS_16			(2 << 28)
++#define			AT91_SMC_PS_32			(3 << 28)
++
++#if defined(AT91_SMC1)		/* The AT91SAM9263 has 2 Static Memory contollers */
++#define AT91_SMC1_SETUP(n)	(AT91_SMC1 + 0x00 + ((n)*0x10))	/* Setup Register for CS n */
++#define AT91_SMC1_PULSE(n)	(AT91_SMC1 + 0x04 + ((n)*0x10))	/* Pulse Register for CS n */
++#define AT91_SMC1_CYCLE(n)	(AT91_SMC1 + 0x08 + ((n)*0x10))	/* Cycle Register for CS n */
++#define AT91_SMC1_MODE(n)	(AT91_SMC1 + 0x0c + ((n)*0x10))	/* Mode Register for CS n */
++#endif
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/gpio.h b/include/asm-arm/arch-ep93xx/gpio.h
+index 9b1864b..186e7c7 100644
+--- a/include/asm-arm/arch-ep93xx/gpio.h
++++ b/include/asm-arm/arch-ep93xx/gpio.h
+@@ -101,30 +101,17 @@
+ 
+ /* new generic GPIO API - see Documentation/gpio.txt */
+ 
+-static inline int gpio_request(unsigned gpio, const char *label)
+-{
+-	if (gpio > EP93XX_GPIO_LINE_MAX)
+-		return -EINVAL;
+-	return 0;
+-}
++#include <asm-generic/gpio.h>
+ 
+-static inline void gpio_free(unsigned gpio)
+-{
+-}
+-
+-int gpio_direction_input(unsigned gpio);
+-int gpio_direction_output(unsigned gpio, int value);
+-int gpio_get_value(unsigned gpio);
+-void gpio_set_value(unsigned gpio, int value);
+-
+-#include <asm-generic/gpio.h> /* cansleep wrappers */
++#define gpio_get_value	__gpio_get_value
++#define gpio_set_value	__gpio_set_value
++#define gpio_cansleep	__gpio_cansleep
+ 
+ /*
+  * Map GPIO A0..A7  (0..7)  to irq 64..71,
+  *          B0..B7  (7..15) to irq 72..79, and
+  *          F0..F7 (16..24) to irq 80..87.
+  */
+-
+ static inline int gpio_to_irq(unsigned gpio)
+ {
+ 	if (gpio <= EP93XX_GPIO_LINE_MAX_IRQ)
+diff --git a/include/asm-arm/arch-iop13xx/adma.h b/include/asm-arm/arch-iop13xx/adma.h
+index efd9a5e..90d14ee 100644
+--- a/include/asm-arm/arch-iop13xx/adma.h
++++ b/include/asm-arm/arch-iop13xx/adma.h
+@@ -454,11 +454,6 @@ static inline void iop_chan_append(struct iop_adma_chan *chan)
+ 	__raw_writel(adma_accr, ADMA_ACCR(chan));
+ }
+ 
+-static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+-{
+-	do { } while (0);
+-}
+-
+ static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+ {
+ 	return __raw_readl(ADMA_ACSR(chan));
+diff --git a/include/asm-arm/arch-ks8695/devices.h b/include/asm-arm/arch-ks8695/devices.h
+index b0364dc..7ad2c65 100644
+--- a/include/asm-arm/arch-ks8695/devices.h
++++ b/include/asm-arm/arch-ks8695/devices.h
+@@ -18,6 +18,11 @@ extern void __init ks8695_add_device_wan(void);
+ extern void __init ks8695_add_device_lan(void);
+ extern void __init ks8695_add_device_hpna(void);
+ 
++ /* LEDs */
++extern short ks8695_leds_cpu;
++extern short ks8695_leds_timer;
++extern void __init ks8695_init_leds(u8 cpu_led, u8 timer_led);
++
+  /* PCI */
+ #define KS8695_MODE_PCI		0
+ #define KS8695_MODE_MINIPCI	1
+diff --git a/include/asm-arm/arch-mxc/board-mx31ads.h b/include/asm-arm/arch-mxc/board-mx31ads.h
+index be29b83..8590127 100644
+--- a/include/asm-arm/arch-mxc/board-mx31ads.h
++++ b/include/asm-arm/arch-mxc/board-mx31ads.h
+@@ -11,107 +11,77 @@
+ #ifndef __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+ #define __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+ 
+-/*!
+- * @name PBC Controller parameters
+- */
+-/*! @{ */
+-/*!
+- * Base address of PBC controller
+- */
++/* Base address of PBC controller */
+ #define PBC_BASE_ADDRESS        IO_ADDRESS(CS4_BASE_ADDR)
+ /* Offsets for the PBC Controller register */
+-/*!
+- * PBC Board status register offset
+- */
++
++/* PBC Board status register offset */
+ #define PBC_BSTAT               0x000002
+-/*!
+- * PBC Board control register 1 set address.
+- */
++
++/* PBC Board control register 1 set address */
+ #define PBC_BCTRL1_SET          0x000004
+-/*!
+- * PBC Board control register 1 clear address.
+- */
++
++/* PBC Board control register 1 clear address */
+ #define PBC_BCTRL1_CLEAR        0x000006
+-/*!
+- * PBC Board control register 2 set address.
+- */
++
++/* PBC Board control register 2 set address */
+ #define PBC_BCTRL2_SET          0x000008
+-/*!
+- * PBC Board control register 2 clear address.
+- */
++
++/* PBC Board control register 2 clear address */
+ #define PBC_BCTRL2_CLEAR        0x00000A
+-/*!
+- * PBC Board control register 3 set address.
+- */
++
++/* PBC Board control register 3 set address */
+ #define PBC_BCTRL3_SET          0x00000C
+-/*!
+- * PBC Board control register 3 clear address.
+- */
++
++/* PBC Board control register 3 clear address */
+ #define PBC_BCTRL3_CLEAR        0x00000E
+-/*!
+- * PBC Board control register 4 set address.
+- */
++
++/* PBC Board control register 4 set address */
+ #define PBC_BCTRL4_SET          0x000010
+-/*!
+- * PBC Board control register 4 clear address.
+- */
++
++/* PBC Board control register 4 clear address */
+ #define PBC_BCTRL4_CLEAR        0x000012
+-/*!
+- * PBC Board status register 1.
+- */
++
++/* PBC Board status register 1 */
+ #define PBC_BSTAT1              0x000014
+-/*!
+- * PBC Board interrupt status register.
+- */
++
++/* PBC Board interrupt status register */
+ #define PBC_INTSTATUS           0x000016
+-/*!
+- * PBC Board interrupt current status register.
+- */
++
++/* PBC Board interrupt current status register */
+ #define PBC_INTCURR_STATUS      0x000018
+-/*!
+- * PBC Interrupt mask register set address.
+- */
++
++/* PBC Interrupt mask register set address */
+ #define PBC_INTMASK_SET         0x00001A
+-/*!
+- * PBC Interrupt mask register clear address.
+- */
++
++/* PBC Interrupt mask register clear address */
+ #define PBC_INTMASK_CLEAR       0x00001C
+ 
+-/*!
+- * External UART A.
+- */
++/* External UART A */
+ #define PBC_SC16C652_UARTA      0x010000
+-/*!
+- * External UART B.
+- */
++
++/* External UART B */
+ #define PBC_SC16C652_UARTB      0x010010
+-/*!
+- * Ethernet Controller IO base address.
+- */
++
++/* Ethernet Controller IO base address */
+ #define PBC_CS8900A_IOBASE      0x020000
+-/*!
+- * Ethernet Controller Memory base address.
+- */
++
++/* Ethernet Controller Memory base address */
+ #define PBC_CS8900A_MEMBASE     0x021000
+-/*!
+- * Ethernet Controller DMA base address.
+- */
++
++/* Ethernet Controller DMA base address */
+ #define PBC_CS8900A_DMABASE     0x022000
+-/*!
+- * External chip select 0.
+- */
++
++/* External chip select 0 */
+ #define PBC_XCS0                0x040000
+-/*!
+- * LCD Display enable.
+- */
++
++/* LCD Display enable */
+ #define PBC_LCD_EN_B            0x060000
+-/*!
+- * Code test debug enable.
+- */
++
++/* Code test debug enable */
+ #define PBC_CODE_B              0x070000
+-/*!
+- * PSRAM memory select.
+- */
++
++/* PSRAM memory select */
+ #define PBC_PSRAM_B             0x5000000
+ 
+ #define PBC_INTSTATUS_REG	(PBC_INTSTATUS + PBC_BASE_ADDRESS)
+@@ -139,4 +109,4 @@
+ 
+ #define MXC_MAX_EXP_IO_LINES	16
+ 
+-#endif				/* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */
++#endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */
+diff --git a/include/asm-arm/arch-mxc/dma.h b/include/asm-arm/arch-mxc/dma.h
+index 65e639d..c822d56 100644
+--- a/include/asm-arm/arch-mxc/dma.h
++++ b/include/asm-arm/arch-mxc/dma.h
+@@ -11,11 +11,4 @@
+ #ifndef __ASM_ARCH_MXC_DMA_H__
+ #define __ASM_ARCH_MXC_DMA_H__
+ 
+-/*!
+- * @file dma.h
+- * @brief This file contains Unified DMA API for all MXC platforms.
+- * The API is platform independent.
+- *
+- * @ingroup SDMA
+- */
+ #endif
+diff --git a/include/asm-arm/arch-mxc/hardware.h b/include/asm-arm/arch-mxc/hardware.h
+index 3c09b92..e87ff06 100644
+--- a/include/asm-arm/arch-mxc/hardware.h
++++ b/include/asm-arm/arch-mxc/hardware.h
+@@ -8,45 +8,24 @@
+  * published by the Free Software Foundation.
+  */
+ 
+-/*!
+- * @file hardware.h
+- * @brief This file contains the hardware definitions of the board.
+- *
+- * @ingroup System
+- */
+ #ifndef __ASM_ARCH_MXC_HARDWARE_H__
+ #define __ASM_ARCH_MXC_HARDWARE_H__
+ 
+ #include <asm/sizes.h>
+ 
+-#include <asm/arch/mx31.h>
++#ifdef CONFIG_ARCH_MX3
++# include <asm/arch/mx31.h>
++#endif
+ 
+ #include <asm/arch/mxc.h>
+ 
+-#define MXC_MAX_GPIO_LINES      (GPIO_NUM_PIN * GPIO_PORT_NUM)
+-
+ /*
+  * ---------------------------------------------------------------------------
+  * Board specific defines
+  * ---------------------------------------------------------------------------
+  */
+-#define MXC_EXP_IO_BASE         (MXC_GPIO_INT_BASE + MXC_MAX_GPIO_LINES)
+-
+-#include <asm/arch/board-mx31ads.h>
+-
+-#ifndef MXC_MAX_EXP_IO_LINES
+-#define MXC_MAX_EXP_IO_LINES 0
++#ifdef CONFIG_MACH_MX31ADS
++# include <asm/arch/board-mx31ads.h>
+ #endif
+ 
+-#define MXC_MAX_VIRTUAL_INTS	16
+-#define MXC_VIRTUAL_INTS_BASE	(MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES)
+-#define MXC_SDIO1_CARD_IRQ	MXC_VIRTUAL_INTS_BASE
+-#define MXC_SDIO2_CARD_IRQ	(MXC_VIRTUAL_INTS_BASE + 1)
+-#define MXC_SDIO3_CARD_IRQ	(MXC_VIRTUAL_INTS_BASE + 2)
+-
+-#define MXC_MAX_INTS            (MXC_MAX_INT_LINES + \
+-                                MXC_MAX_GPIO_LINES + \
+-                                MXC_MAX_EXP_IO_LINES + \
+-                                MXC_MAX_VIRTUAL_INTS)
+-
+-#endif				/* __ASM_ARCH_MXC_HARDWARE_H__ */
++#endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
+diff --git a/include/asm-arm/arch-mxc/io.h b/include/asm-arm/arch-mxc/io.h
+index cf6c83a..65b6810 100644
+--- a/include/asm-arm/arch-mxc/io.h
++++ b/include/asm-arm/arch-mxc/io.h
+@@ -8,24 +8,13 @@
+  * published by the Free Software Foundation.
+  */
+ 
+-/*!
+- * @file io.h
+- * @brief This file contains some memory mapping macros.
+- * @note There is no real ISA or PCI buses. But have to define these macros
+- * for some drivers to compile.
+- *
+- * @ingroup System
+- */
+-
+ #ifndef __ASM_ARCH_MXC_IO_H__
+ #define __ASM_ARCH_MXC_IO_H__
+ 
+-/*! Allow IO space to be anywhere in the memory */
++/* Allow IO space to be anywhere in the memory */
+ #define IO_SPACE_LIMIT 0xffffffff
+ 
+-/*!
+- * io address mapping macro
+- */
++/* io address mapping macro */
+ #define __io(a)			((void __iomem *)(a))
+ 
+ #define __mem_pci(a)		(a)
+diff --git a/include/asm-arm/arch-mxc/irqs.h b/include/asm-arm/arch-mxc/irqs.h
+index e4686c6..b2c5205 100644
+--- a/include/asm-arm/arch-mxc/irqs.h
++++ b/include/asm-arm/arch-mxc/irqs.h
+@@ -13,26 +13,17 @@
+ 
+ #include <asm/hardware.h>
+ 
+-/*!
+- * @file irqs.h
+- * @brief This file defines the number of normal interrupts and fast interrupts
+- *
+- * @ingroup Interrupt
+- */
+-
+ #define MXC_IRQ_TO_EXPIO(irq)	((irq) - MXC_EXP_IO_BASE)
+ 
+ #define MXC_IRQ_TO_GPIO(irq)	((irq) - MXC_GPIO_INT_BASE)
+ #define MXC_GPIO_TO_IRQ(x)	(MXC_GPIO_INT_BASE + x)
+ 
+-/*!
+- * Number of normal interrupts
+- */
+-#define NR_IRQS		MXC_MAX_INTS
++/* Number of normal interrupts */
++#define NR_IRQS		(MXC_MAX_INT_LINES + \
++			MXC_MAX_GPIO_LINES + \
++			MXC_MAX_VIRTUAL_INTS)
+ 
+-/*!
+- * Number of fast interrupts
+- */
++/* Number of fast interrupts */
+ #define NR_FIQS		MXC_MAX_INTS
+ 
+-#endif				/* __ASM_ARCH_MXC_IRQS_H__ */
++#endif /* __ASM_ARCH_MXC_IRQS_H__ */
+diff --git a/include/asm-arm/arch-mxc/memory.h b/include/asm-arm/arch-mxc/memory.h
+index c89aac8..059f830 100644
+--- a/include/asm-arm/arch-mxc/memory.h
++++ b/include/asm-arm/arch-mxc/memory.h
+@@ -13,24 +13,17 @@
+ 
+ #include <asm/hardware.h>
+ 
+-/*!
+- * @file memory.h
+- * @brief This file contains macros needed by the Linux kernel and drivers.
+- *
+- * @ingroup Memory
+- */
+-
+-/*!
++/*
+  * Virtual view <-> DMA view memory address translations
+  * This macro is used to translate the virtual address to an address
+  * suitable to be passed to set_dma_addr()
+  */
+ #define __virt_to_bus(a)	__virt_to_phys(a)
+ 
+-/*!
++/*
+  * Used to convert an address for DMA operations to an address that the
+  * kernel can use.
+  */
+ #define __bus_to_virt(a)	__phys_to_virt(a)
+ 
+-#endif				/* __ASM_ARCH_MXC_MEMORY_H__ */
++#endif /* __ASM_ARCH_MXC_MEMORY_H__ */
+diff --git a/include/asm-arm/arch-mxc/mx31.h b/include/asm-arm/arch-mxc/mx31.h
+index 85c49c9..36a1af4 100644
+--- a/include/asm-arm/arch-mxc/mx31.h
++++ b/include/asm-arm/arch-mxc/mx31.h
+@@ -317,6 +317,8 @@
+ #define MXC_MAX_INT_LINES	64
+ 
+ #define MXC_GPIO_INT_BASE	MXC_MAX_INT_LINES
++#define MXC_MAX_GPIO_LINES      (GPIO_NUM_PIN * GPIO_PORT_NUM)
++#define MXC_MAX_VIRTUAL_INTS	16
+ 
+ /*!
+  * Number of GPIO port as defined in the IC Spec
+@@ -329,7 +331,33 @@
+ 
+ #define PROD_SIGNATURE		0x1	/* For MX31 */
+ 
++/* silicon revisions specific to i.MX31 */
++#define CHIP_REV_1_0		0x10
++#define CHIP_REV_1_1		0x11
++#define CHIP_REV_1_2		0x12
++#define CHIP_REV_1_3		0x13
++#define CHIP_REV_2_0		0x20
++#define CHIP_REV_2_1		0x21
++#define CHIP_REV_2_2		0x22
++#define CHIP_REV_2_3		0x23
++#define CHIP_REV_3_0		0x30
++#define CHIP_REV_3_1		0x31
++#define CHIP_REV_3_2		0x32
++
+ #define SYSTEM_REV_MIN		CHIP_REV_1_0
+ #define SYSTEM_REV_NUM		3
+ 
+-#endif			/*  __ASM_ARCH_MXC_MX31_H__ */
++#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
++
++/* this is a i.MX31 CPU */
++#define cpu_is_mx31()		(1)
++
++extern unsigned int system_rev;
++
++static inline int mx31_revision(void)
++{
++	return system_rev;
++}
++#endif
++
++#endif /*  __ASM_ARCH_MXC_MX31_H__ */
+diff --git a/include/asm-arm/arch-mxc/mxc.h b/include/asm-arm/arch-mxc/mxc.h
+index 0837f1f..146d3f6 100644
+--- a/include/asm-arm/arch-mxc/mxc.h
++++ b/include/asm-arm/arch-mxc/mxc.h
+@@ -15,6 +15,11 @@
+ #error "Do not include directly."
+ #endif
+ 
++/* clean up all things that are not used */
++#ifndef CONFIG_ARCH_MX3
++# define cpu_is_mx31() (0)
++#endif
++
+ /*
+  *****************************************
+  * GPT  Register definitions             *
+@@ -31,9 +36,7 @@
+ #define MXC_GPT_GPTICR2		IO_ADDRESS(GPT1_BASE_ADDR + 0x20)
+ #define MXC_GPT_GPTCNT		IO_ADDRESS(GPT1_BASE_ADDR + 0x24)
+ 
+-/*!
+- * GPT Control register bit definitions
+- */
++/* GPT Control register bit definitions */
+ #define GPTCR_FO3			(1 << 31)
+ #define GPTCR_FO2			(1 << 30)
+ #define GPTCR_FO1			(1 << 29)
+@@ -146,4 +149,4 @@
+ #define IIM_PROD_REV_SH		3
+ #define IIM_PROD_REV_LEN	5
+ 
+-#endif				/*  __ASM_ARCH_MXC_H__ */
++#endif /*  __ASM_ARCH_MXC_H__ */
+diff --git a/include/asm-arm/arch-mxc/system.h b/include/asm-arm/arch-mxc/system.h
+index 109956b..bbfc374 100644
+--- a/include/asm-arm/arch-mxc/system.h
++++ b/include/asm-arm/arch-mxc/system.h
+@@ -21,30 +21,14 @@
+ #ifndef __ASM_ARCH_MXC_SYSTEM_H__
+ #define __ASM_ARCH_MXC_SYSTEM_H__
+ 
+-/*!
+- * @file system.h
+- * @brief This file contains idle and reset functions.
+- *
+- * @ingroup System
+- */
+-
+-/*!
+- * This function puts the CPU into idle mode. It is called by default_idle()
+- * in process.c file.
+- */
+ static inline void arch_idle(void)
+ {
+ 	cpu_do_idle();
+ }
+ 
+-/*
+- * This function resets the system. It is called by machine_restart().
+- *
+- * @param  mode         indicates different kinds of resets
+- */
+ static inline void arch_reset(char mode)
+ {
+ 	cpu_reset(0);
+ }
+ 
+-#endif				/* __ASM_ARCH_MXC_SYSTEM_H__ */
++#endif /* __ASM_ARCH_MXC_SYSTEM_H__ */
+diff --git a/include/asm-arm/arch-mxc/vmalloc.h b/include/asm-arm/arch-mxc/vmalloc.h
+index 83a73da..62d9762 100644
+--- a/include/asm-arm/arch-mxc/vmalloc.h
++++ b/include/asm-arm/arch-mxc/vmalloc.h
+@@ -20,17 +20,7 @@
+ #ifndef __ASM_ARCH_MXC_VMALLOC_H__
+ #define __ASM_ARCH_MXC_VMALLOC_H__
+ 
+-/*!
+- * @file vmalloc.h
+- *
+- * @brief This file contains platform specific macros for vmalloc.
+- *
+- * @ingroup System
+- */
+-
+-/*!
+- * vmalloc ending address
+- */
++/* vmalloc ending address */
+ #define VMALLOC_END       0xF4000000
+ 
+-#endif				/* __ASM_ARCH_MXC_VMALLOC_H__ */
++#endif /* __ASM_ARCH_MXC_VMALLOC_H__ */
+diff --git a/include/asm-arm/arch-ns9xxx/board.h b/include/asm-arm/arch-ns9xxx/board.h
+index 716f34f..e57443b 100644
+--- a/include/asm-arm/arch-ns9xxx/board.h
++++ b/include/asm-arm/arch-ns9xxx/board.h
+@@ -1,7 +1,7 @@
+ /*
+  * include/asm-arm/arch-ns9xxx/board.h
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -13,8 +13,30 @@
+ 
+ #include <asm/mach-types.h>
+ 
+-#define board_is_a9m9750dev()	(machine_is_cc9p9360dev())
++#define board_is_a9m9750dev()	(0			\
++		|| machine_is_cc9p9360dev()		\
++		|| machine_is_cc9p9750dev()		\
++		)
+ 
+-#define board_is_jscc9p9360()	(machine_is_cc9p9360js())
++#define board_is_a9mvali()	(0			\
++		|| machine_is_cc9p9360val() 		\
++		|| machine_is_cc9p9750val()		\
++		)
++
++#define board_is_jscc9p9210()	(0			\
++		|| machine_is_cc9p9210js()		\
++		)
++
++#define board_is_jscc9p9215()	(0			\
++		|| machine_is_cc9p9215js()		\
++		)
++
++#define board_is_jscc9p9360()	(0			\
++		|| machine_is_cc9p9360js()		\
++		)
++
++#define board_is_uncbas()	(0			\
++		|| machine_is_cc7ucamry()		\
++		)
+ 
+ #endif /* ifndef __ASM_ARCH_BOARD_H */
+diff --git a/include/asm-arm/arch-ns9xxx/clock.h b/include/asm-arm/arch-ns9xxx/clock.h
+deleted file mode 100644
+index b943d3a..0000000
+--- a/include/asm-arm/arch-ns9xxx/clock.h
++++ /dev/null
+@@ -1,71 +0,0 @@
+-/*
+- * include/asm-arm/arch-ns9xxx/clock.h
+- *
+- * Copyright (C) 2007 by Digi International Inc.
+- * All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License version 2 as published by
+- * the Free Software Foundation.
+- */
+-#ifndef __ASM_ARCH_CLOCK_H
+-#define __ASM_ARCH_CLOCK_H
+-
+-#include <asm/arch-ns9xxx/regs-sys.h>
+-
+-#define CRYSTAL 29491200 /* Hz */
+-
+-/* The HRM calls this value f_vco */
+-static inline u32 ns9xxx_systemclock(void) __attribute__((const));
+-static inline u32 ns9xxx_systemclock(void)
+-{
+-	u32 pll = __raw_readl(SYS_PLL);
+-
+-	/*
+-	 * The system clock should be a multiple of HZ * TIMERCLOCKSELECT (in
+-	 * time.c).
+-	 *
+-	 * The following values are given:
+-	 *   - TIMERCLOCKSELECT == 2^i for an i in {0 .. 6}
+-	 *   - CRYSTAL == 29491200 == 2^17 * 3^2 * 5^2
+-	 *   - ND in {0 .. 31}
+-	 *   - FS in {0 .. 3}
+-	 *
+-	 * Assuming the worst, we consider:
+-	 *   - TIMERCLOCKSELECT == 64
+-	 *   - ND == 0
+-	 *   - FS == 3
+-	 *
+-	 * So HZ should be a divisor of:
+-	 *      (CRYSTAL * (ND + 1) >> FS) / TIMERCLOCKSELECT
+-	 *   == (2^17 * 3^2 * 5^2 * 1 >> 3) / 64
+-	 *   == 2^8 * 3^2 * 5^2
+-	 *   == 57600
+-	 *
+-	 * Currently HZ is defined to be 100 for this platform.
+-	 *
+-	 * Fine.
+-	 */
+-	return CRYSTAL * (REGGETIM(pll, SYS_PLL, ND) + 1)
+-		>> REGGETIM(pll, SYS_PLL, FS);
+-}
+-
+-static inline u32 ns9xxx_cpuclock(void) __attribute__((const));
+-static inline u32 ns9xxx_cpuclock(void)
+-{
+-	return ns9xxx_systemclock() / 2;
+-}
+-
+-static inline u32 ns9xxx_ahbclock(void) __attribute__((const));
+-static inline u32 ns9xxx_ahbclock(void)
+-{
+-	return ns9xxx_systemclock() / 4;
+-}
+-
+-static inline u32 ns9xxx_bbusclock(void) __attribute__((const));
+-static inline u32 ns9xxx_bbusclock(void)
+-{
+-	return ns9xxx_systemclock() / 8;
+-}
+-
+-#endif /* ifndef __ASM_ARCH_CLOCK_H */
+diff --git a/include/asm-arm/arch-ns9xxx/entry-macro.S b/include/asm-arm/arch-ns9xxx/entry-macro.S
+index 86aec87..89a21c5 100644
+--- a/include/asm-arm/arch-ns9xxx/entry-macro.S
++++ b/include/asm-arm/arch-ns9xxx/entry-macro.S
+@@ -1,7 +1,7 @@
+ /*
+  * include/asm-arm/arch-ns9xxx/entry-macro.S
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -9,16 +9,16 @@
+  * the Free Software Foundation.
+  */
+ #include <asm/hardware.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
++#include <asm/arch-ns9xxx/regs-sys-common.h>
+ 
+ 		.macro	get_irqnr_preamble, base, tmp
++		ldr	\base, =SYS_ISRADDR
+ 		.endm
+ 
+ 		.macro	arch_ret_to_user, tmp1, tmp2
+ 		.endm
+ 
+ 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+-		ldr	\base, =SYS_ISRADDR
+ 		ldr	\irqstat, [\base, #(SYS_ISA - SYS_ISRADDR)]
+ 		cmp	\irqstat, #0
+ 		ldrne	\irqnr, [\base]
+diff --git a/include/asm-arm/arch-ns9xxx/irqs.h b/include/asm-arm/arch-ns9xxx/irqs.h
+index 25d8d28..e83d48e 100644
+--- a/include/asm-arm/arch-ns9xxx/irqs.h
++++ b/include/asm-arm/arch-ns9xxx/irqs.h
+@@ -1,7 +1,7 @@
+ /*
+  * include/asm-arm/arch-ns9xxx/irqs.h
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -11,38 +11,39 @@
+ #ifndef __ASM_ARCH_IRQS_H
+ #define __ASM_ARCH_IRQS_H
+ 
+-#define IRQ_WATCHDOG	0
+-#define IRQ_AHBBUSERR	1
+-#define IRQ_BBUSAGG	2
++/* NetSilicon 9360 */
++#define IRQ_NS9XXX_WATCHDOG	0
++#define IRQ_NS9XXX_AHBBUSERR	1
++#define IRQ_NS9360_BBUSAGG	2
+ /* irq 3 is reserved for NS9360 */
+-#define IRQ_ETHRX	4
+-#define IRQ_ETHTX	5
+-#define IRQ_ETHPHY	6
+-#define IRQ_LCD		7
+-#define IRQ_SERBRX	8
+-#define IRQ_SERBTX	9
+-#define IRQ_SERARX	10
+-#define IRQ_SERATX	11
+-#define IRQ_SERCRX	12
+-#define IRQ_SERCTX	13
+-#define IRQ_I2C		14
+-#define IRQ_BBUSDMA	15
+-#define IRQ_TIMER0	16
+-#define IRQ_TIMER1	17
+-#define IRQ_TIMER2	18
+-#define IRQ_TIMER3	19
+-#define IRQ_TIMER4	20
+-#define IRQ_TIMER5	21
+-#define IRQ_TIMER6	22
+-#define IRQ_TIMER7	23
+-#define IRQ_RTC		24
+-#define IRQ_USBHOST	25
+-#define IRQ_USBDEVICE	26
+-#define IRQ_IEEE1284	27
+-#define IRQ_EXT0	28
+-#define IRQ_EXT1	29
+-#define IRQ_EXT2	30
+-#define IRQ_EXT3	31
++#define IRQ_NS9XXX_ETHRX	4
++#define IRQ_NS9XXX_ETHTX	5
++#define IRQ_NS9XXX_ETHPHY	6
++#define IRQ_NS9360_LCD		7
++#define IRQ_NS9360_SERBRX	8
++#define IRQ_NS9360_SERBTX	9
++#define IRQ_NS9360_SERARX	10
++#define IRQ_NS9360_SERATX	11
++#define IRQ_NS9360_SERCRX	12
++#define IRQ_NS9360_SERCTX	13
++#define IRQ_NS9360_I2C		14
++#define IRQ_NS9360_BBUSDMA	15
++#define IRQ_NS9360_TIMER0	16
++#define IRQ_NS9360_TIMER1	17
++#define IRQ_NS9360_TIMER2	18
++#define IRQ_NS9360_TIMER3	19
++#define IRQ_NS9360_TIMER4	20
++#define IRQ_NS9360_TIMER5	21
++#define IRQ_NS9360_TIMER6	22
++#define IRQ_NS9360_TIMER7	23
++#define IRQ_NS9360_RTC		24
++#define IRQ_NS9360_USBHOST	25
++#define IRQ_NS9360_USBDEVICE	26
++#define IRQ_NS9360_IEEE1284	27
++#define IRQ_NS9XXX_EXT0		28
++#define IRQ_NS9XXX_EXT1		29
++#define IRQ_NS9XXX_EXT2		30
++#define IRQ_NS9XXX_EXT3		31
+ 
+ #define BBUS_IRQ(irq)	(32 + irq)
+ 
+@@ -67,7 +68,7 @@
+ /*
+  * these Interrupts are specific for the a9m9750dev board.
+  * They are generated by an FPGA that interrupts the CPU on
+- * IRQ_EXT2
++ * IRQ_NS9360_EXT2
+  */
+ #define FPGA_IRQ(irq)	(64 + irq)
+ 
+diff --git a/include/asm-arm/arch-ns9xxx/module.h b/include/asm-arm/arch-ns9xxx/module.h
+new file mode 100644
+index 0000000..ac08a31
+--- /dev/null
++++ b/include/asm-arm/arch-ns9xxx/module.h
+@@ -0,0 +1,60 @@
++/*
++ * include/asm-arm/arch-ns9xxx/module.h
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#ifndef __ASM_ARCH_MODULE_H
++#define __ASM_ARCH_MODULE_H
++
++#include <asm/mach-types.h>
++
++#define module_is_cc7ucamry()	(0			\
++		|| machine_is_cc7ucamry()		\
++		)
++
++#define module_is_cc9c()	(0			\
++		|| machine_is_cc9c()			\
++		)
++
++#define module_is_cc9p9210()	(0			\
++		|| machine_is_cc9p9210()		\
++		|| machine_is_cc9p9210js()		\
++		)
++
++#define module_is_cc9p9215()	(0			\
++		|| machine_is_cc9p9215()		\
++		|| machine_is_cc9p9215js()		\
++		)
++
++#define module_is_cc9p9360()	(0			\
++		|| machine_is_a9m9360()			\
++		|| machine_is_cc9p9360dev()		\
++		|| machine_is_cc9p9360js()		\
++		|| machine_is_cc9p9360val()		\
++		)
++
++#define module_is_cc9p9750()	(0			\
++		|| machine_is_a9m9750()			\
++		|| machine_is_cc9p9750dev()		\
++		|| machine_is_cc9p9750js()		\
++		|| machine_is_cc9p9750val()		\
++		)
++
++#define module_is_ccw9c()	(0			\
++		|| machine_is_ccw9c()			\
++		)
++
++#define module_is_inc20otter()	(0			\
++		|| machine_is_inc20otter()		\
++		)
++
++#define module_is_otter()	(0			\
++		|| machine_is_otter()			\
++		)
++
++#endif /* ifndef __ASM_ARCH_MODULE_H */
+diff --git a/include/asm-arm/arch-ns9xxx/processor-ns9360.h b/include/asm-arm/arch-ns9xxx/processor-ns9360.h
+new file mode 100644
+index 0000000..f3aa6c5
+--- /dev/null
++++ b/include/asm-arm/arch-ns9xxx/processor-ns9360.h
+@@ -0,0 +1,32 @@
++/*
++ * include/asm-arm/arch-ns9xxx/processor-ns9360.h
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#ifndef __ASM_ARCH_PROCESSORNS9360_H
++#define __ASM_ARCH_PROCESSORNS9360_H
++
++#include <linux/init.h>
++
++void ns9360_reset(char mode);
++
++unsigned long ns9360_systemclock(void) __attribute__((const));
++
++static inline unsigned long ns9360_cpuclock(void) __attribute__((const));
++static inline unsigned long ns9360_cpuclock(void)
++{
++	return ns9360_systemclock() / 2;
++}
++
++void __init ns9360_map_io(void);
++
++extern struct sys_timer ns9360_timer;
++
++int ns9360_gpio_configure(unsigned gpio, int inv, int func);
++
++#endif /* ifndef __ASM_ARCH_PROCESSORNS9360_H */
+diff --git a/include/asm-arm/arch-ns9xxx/processor.h b/include/asm-arm/arch-ns9xxx/processor.h
+index 223e51b..f7b53b6 100644
+--- a/include/asm-arm/arch-ns9xxx/processor.h
++++ b/include/asm-arm/arch-ns9xxx/processor.h
+@@ -1,7 +1,7 @@
+ /*
+  * include/asm-arm/arch-ns9xxx/processor.h
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -11,9 +11,32 @@
+ #ifndef __ASM_ARCH_PROCESSOR_H
+ #define __ASM_ARCH_PROCESSOR_H
+ 
+-#include <asm/mach-types.h>
++#include <asm/arch-ns9xxx/module.h>
+ 
+-#define processor_is_ns9360()	(machine_is_cc9p9360dev()		\
+-		|| machine_is_cc9p9360js())
++#define processor_is_ns9210()	(0			\
++		|| module_is_cc7ucamry()		\
++		|| module_is_cc9p9210()			\
++		|| module_is_inc20otter()		\
++		|| module_is_otter()			\
++		)
++
++#define processor_is_ns9215()	(0			\
++		|| module_is_cc9p9215()			\
++		)
++
++#define processor_is_ns9360()	(0			\
++		|| module_is_cc9p9360()			\
++		|| module_is_cc9c()			\
++		|| module_is_ccw9c()			\
++		)
++
++#define processor_is_ns9750()	(0			\
++		|| module_is_cc9p9750()			\
++		)
++
++#define processor_is_ns921x()	(0			\
++		|| processor_is_ns9210()		\
++		|| processor_is_ns9215()		\
++		)
+ 
+ #endif /* ifndef __ASM_ARCH_PROCESSOR_H */
+diff --git a/include/asm-arm/arch-ns9xxx/regs-sys-common.h b/include/asm-arm/arch-ns9xxx/regs-sys-common.h
+new file mode 100644
+index 0000000..956c57c
+--- /dev/null
++++ b/include/asm-arm/arch-ns9xxx/regs-sys-common.h
+@@ -0,0 +1,31 @@
++/*
++ * include/asm-arm/arch-ns9xxx/regs-sys-common.h
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++
++#ifndef __ASM_ARCH_REGSSYSCOMMON_H
++#define __ASM_ARCH_REGSSYSCOMMON_H
++#include <asm/hardware.h>
++
++/* Interrupt Vector Address Register Level x */
++#define SYS_IVA(x)	__REG2(0xa09000c4, (x))
++
++/* Interrupt Configuration registers */
++#define SYS_IC(x)	__REG2(0xa0900144, (x))
++
++/* ISRADDR */
++#define SYS_ISRADDR     __REG(0xa0900164)
++
++/* Interrupt Status Active */
++#define SYS_ISA		__REG(0xa0900168)
++
++/* Interrupt Status Raw */
++#define SYS_ISR		__REG(0xa090016c)
++
++#endif /* ifndef __ASM_ARCH_REGSSYSCOMMON_H */
+diff --git a/include/asm-arm/arch-ns9xxx/regs-sys-ns9360.h b/include/asm-arm/arch-ns9xxx/regs-sys-ns9360.h
+new file mode 100644
+index 0000000..318b694
+--- /dev/null
++++ b/include/asm-arm/arch-ns9xxx/regs-sys-ns9360.h
+@@ -0,0 +1,148 @@
++/*
++ * include/asm-arm/arch-ns9xxx/regs-sys-ns9360.h
++ *
++ * Copyright (C) 2006,2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#ifndef __ASM_ARCH_REGSSYSNS9360_H
++#define __ASM_ARCH_REGSSYSNS9360_H
++
++#include <asm/hardware.h>
++
++/* System Control Module */
++
++/* AHB Arbiter Gen Configuration */
++#define SYS_AHBAGENCONF	__REG(0xa0900000)
++
++/* BRC */
++#define SYS_BRC(x)	__REG2(0xa0900004, (x))
++
++/* Timer x Reload Count register */
++#define SYS_TRC(x)	__REG2(0xa0900044, (x))
++
++/* Timer x Read register */
++#define SYS_TR(x)	__REG2(0xa0900084, (x))
++
++/* Timer Interrupt Status register */
++#define SYS_TIS		__REG(0xa0900170)
++
++/* PLL Configuration register */
++#define SYS_PLL		__REG(0xa0900188)
++
++/* PLL FS status */
++#define SYS_PLL_FS		__REGBITS(24, 23)
++
++/* PLL ND status */
++#define SYS_PLL_ND		__REGBITS(20, 16)
++
++/* PLL Configuration register: PLL SW change */
++#define SYS_PLL_SWC		__REGBIT(15)
++#define SYS_PLL_SWC_NO			__REGVAL(SYS_PLL_SWC, 0)
++#define SYS_PLL_SWC_YES			__REGVAL(SYS_PLL_SWC, 1)
++
++/* Timer x Control register */
++#define SYS_TC(x)	__REG2(0xa0900190, (x))
++
++/* Timer x Control register: Timer enable */
++#define SYS_TCx_TEN		__REGBIT(15)
++#define SYS_TCx_TEN_DIS			__REGVAL(SYS_TCx_TEN, 0)
++#define SYS_TCx_TEN_EN			__REGVAL(SYS_TCx_TEN, 1)
++
++/* Timer x Control register: CPU debug mode */
++#define SYS_TCx_TDBG		__REGBIT(10)
++#define SYS_TCx_TDBG_CONT		__REGVAL(SYS_TCx_TDBG, 0)
++#define SYS_TCx_TDBG_STOP		__REGVAL(SYS_TCx_TDBG, 1)
++
++/* Timer x Control register: Interrupt clear */
++#define SYS_TCx_INTC		__REGBIT(9)
++#define SYS_TCx_INTC_UNSET		__REGVAL(SYS_TCx_INTC, 0)
++#define SYS_TCx_INTC_SET		__REGVAL(SYS_TCx_INTC, 1)
++
++/* Timer x Control register: Timer clock select */
++#define SYS_TCx_TLCS		__REGBITS(8, 6)
++#define SYS_TCx_TLCS_CPU		__REGVAL(SYS_TCx_TLCS, 0)	/* CPU clock */
++#define SYS_TCx_TLCS_DIV2		__REGVAL(SYS_TCx_TLCS, 1)	/* CPU clock / 2 */
++#define SYS_TCx_TLCS_DIV4		__REGVAL(SYS_TCx_TLCS, 2)	/* CPU clock / 4 */
++#define SYS_TCx_TLCS_DIV8		__REGVAL(SYS_TCx_TLCS, 3)	/* CPU clock / 8 */
++#define SYS_TCx_TLCS_DIV16		__REGVAL(SYS_TCx_TLCS, 4)	/* CPU clock / 16 */
++#define SYS_TCx_TLCS_DIV32		__REGVAL(SYS_TCx_TLCS, 5)	/* CPU clock / 32 */
++#define SYS_TCx_TLCS_DIV64		__REGVAL(SYS_TCx_TLCS, 6)	/* CPU clock / 64 */
++#define SYS_TCx_TLCS_EXT		__REGVAL(SYS_TCx_TLCS, 7)
++
++/* Timer x Control register: Timer mode */
++#define SYS_TCx_TM		__REGBITS(5, 4)
++#define SYS_TCx_TM_IEE			__REGVAL(SYS_TCx_TM, 0)		/* Internal timer or external event */
++#define SYS_TCx_TM_ELL			__REGVAL(SYS_TCx_TM, 1)		/* External low-level, gated timer */
++#define SYS_TCx_TM_EHL			__REGVAL(SYS_TCx_TM, 2)		/* External high-level, gated timer */
++#define SYS_TCx_TM_CONCAT		__REGVAL(SYS_TCx_TM, 3)		/* Concatenate the lower timer. */
++
++/* Timer x Control register: Interrupt select */
++#define SYS_TCx_INTS		__REGBIT(3)
++#define SYS_TCx_INTS_DIS		__REGVAL(SYS_TCx_INTS, 0)
++#define SYS_TCx_INTS_EN			__REGVAL(SYS_TCx_INTS, 1)
++
++/* Timer x Control register: Up/down select */
++#define SYS_TCx_UDS		__REGBIT(2)
++#define SYS_TCx_UDS_UP			__REGVAL(SYS_TCx_UDS, 0)
++#define SYS_TCx_UDS_DOWN		__REGVAL(SYS_TCx_UDS, 1)
++
++/* Timer x Control register: 32- or 16-bit timer */
++#define SYS_TCx_TSZ		__REGBIT(1)
++#define SYS_TCx_TSZ_16			__REGVAL(SYS_TCx_TSZ, 0)
++#define SYS_TCx_TSZ_32			__REGVAL(SYS_TCx_TSZ, 1)
++
++/* Timer x Control register: Reload enable */
++#define SYS_TCx_REN		__REGBIT(0)
++#define SYS_TCx_REN_DIS			__REGVAL(SYS_TCx_REN, 0)
++#define SYS_TCx_REN_EN			__REGVAL(SYS_TCx_REN, 1)
++
++/* System Memory Chip Select x Dynamic Memory Base */
++#define SYS_SMCSDMB(x)	__REG2(0xa09001d0, (x) << 1)
++
++/* System Memory Chip Select x Dynamic Memory Mask */
++#define SYS_SMCSDMM(x)	__REG2(0xa09001d4, (x) << 1)
++
++/* System Memory Chip Select x Static Memory Base */
++#define SYS_SMCSSMB(x)	__REG2(0xa09001f0, (x) << 1)
++
++/* System Memory Chip Select x Static Memory Base: Chip select x base */
++#define SYS_SMCSSMB_CSxB	__REGBITS(31, 12)
++
++/* System Memory Chip Select x Static Memory Mask */
++#define SYS_SMCSSMM(x)	__REG2(0xa09001f4, (x) << 1)
++
++/* System Memory Chip Select x Static Memory Mask: Chip select x mask */
++#define SYS_SMCSSMM_CSxM	__REGBITS(31, 12)
++
++/* System Memory Chip Select x Static Memory Mask: Chip select x enable */
++#define SYS_SMCSSMM_CSEx	__REGBIT(0)
++#define SYS_SMCSSMM_CSEx_DIS		__REGVAL(SYS_SMCSSMM_CSEx, 0)
++#define SYS_SMCSSMM_CSEx_EN		__REGVAL(SYS_SMCSSMM_CSEx, 1)
++
++/* General purpose, user-defined ID register */
++#define SYS_GENID	__REG(0xa0900210)
++
++/* External Interrupt x Control register */
++#define SYS_EIC(x)	__REG2(0xa0900214, (x))
++
++/* External Interrupt x Control register: Status */
++#define SYS_EIC_STS		__REGBIT(3)
++
++/* External Interrupt x Control register: Clear */
++#define SYS_EIC_CLR		__REGBIT(2)
++
++/* External Interrupt x Control register: Polarity */
++#define SYS_EIC_PLTY		__REGBIT(1)
++#define SYS_EIC_PLTY_AH			__REGVAL(SYS_EIC_PLTY, 0)
++#define SYS_EIC_PLTY_AL			__REGVAL(SYS_EIC_PLTY, 1)
++
++/* External Interrupt x Control register: Level edge */
++#define SYS_EIC_LVEDG		__REGBIT(0)
++#define SYS_EIC_LVEDG_LEVEL		__REGVAL(SYS_EIC_LVEDG, 0)
++#define SYS_EIC_LVEDG_EDGE		__REGVAL(SYS_EIC_LVEDG, 1)
++
++#endif /* ifndef __ASM_ARCH_REGSSYSNS9360_H */
+diff --git a/include/asm-arm/arch-ns9xxx/regs-sys.h b/include/asm-arm/arch-ns9xxx/regs-sys.h
+deleted file mode 100644
+index 749262f..0000000
+--- a/include/asm-arm/arch-ns9xxx/regs-sys.h
++++ /dev/null
+@@ -1,163 +0,0 @@
+-/*
+- * include/asm-arm/arch-ns9xxx/regs-sys.h
+- *
+- * Copyright (C) 2006 by Digi International Inc.
+- * All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License version 2 as published by
+- * the Free Software Foundation.
+- */
+-#ifndef __ASM_ARCH_REGSSYS_H
+-#define __ASM_ARCH_REGSSYS_H
+-
+-#include <asm/hardware.h>
+-
+-/* System Control Module */
+-
+-/* AHB Arbiter Gen Configuration */
+-#define SYS_AHBAGENCONF	__REG(0xa0900000)
+-
+-/* BRC */
+-#define SYS_BRC(x)	__REG2(0xa0900004, (x))
+-
+-/* Timer x Reload Count register */
+-#define SYS_TRC(x)	__REG2(0xa0900044, (x))
+-
+-/* Timer x Read register */
+-#define SYS_TR(x)	__REG2(0xa0900084, (x))
+-
+-/* Interrupt Vector Address Register Level x */
+-#define SYS_IVA(x)	__REG2(0xa09000c4, (x))
+-
+-/* Interrupt Configuration registers */
+-#define SYS_IC(x)	__REG2(0xa0900144, (x))
+-
+-/* ISRADDR */
+-#define SYS_ISRADDR	__REG(0xa0900164)
+-
+-/* Interrupt Status Active */
+-#define SYS_ISA		__REG(0xa0900168)
+-
+-/* Interrupt Status Raw */
+-#define SYS_ISR		__REG(0xa090016c)
+-
+-/* Timer Interrupt Status register */
+-#define SYS_TIS		__REG(0xa0900170)
+-
+-/* PLL Configuration register */
+-#define SYS_PLL		__REG(0xa0900188)
+-
+-/* PLL FS status */
+-#define SYS_PLL_FS		__REGBITS(24, 23)
+-
+-/* PLL ND status */
+-#define SYS_PLL_ND		__REGBITS(20, 16)
+-
+-/* PLL Configuration register: PLL SW change */
+-#define SYS_PLL_SWC		__REGBIT(15)
+-#define SYS_PLL_SWC_NO			__REGVAL(SYS_PLL_SWC, 0)
+-#define SYS_PLL_SWC_YES			__REGVAL(SYS_PLL_SWC, 1)
+-
+-/* Timer x Control register */
+-#define SYS_TC(x)	__REG2(0xa0900190, (x))
+-
+-/* Timer x Control register: Timer enable */
+-#define SYS_TCx_TEN		__REGBIT(15)
+-#define SYS_TCx_TEN_DIS			__REGVAL(SYS_TCx_TEN, 0)
+-#define SYS_TCx_TEN_EN			__REGVAL(SYS_TCx_TEN, 1)
+-
+-/* Timer x Control register: CPU debug mode */
+-#define SYS_TCx_TDBG		__REGBIT(10)
+-#define SYS_TCx_TDBG_CONT		__REGVAL(SYS_TCx_TDBG, 0)
+-#define SYS_TCx_TDBG_STOP		__REGVAL(SYS_TCx_TDBG, 1)
+-
+-/* Timer x Control register: Interrupt clear */
+-#define SYS_TCx_INTC		__REGBIT(9)
+-#define SYS_TCx_INTC_UNSET		__REGVAL(SYS_TCx_INTC, 0)
+-#define SYS_TCx_INTC_SET		__REGVAL(SYS_TCx_INTC, 1)
+-
+-/* Timer x Control register: Timer clock select */
+-#define SYS_TCx_TLCS		__REGBITS(8, 6)
+-#define SYS_TCx_TLCS_CPU		__REGVAL(SYS_TCx_TLCS, 0)	/* CPU clock */
+-#define SYS_TCx_TLCS_DIV2		__REGVAL(SYS_TCx_TLCS, 1)	/* CPU clock / 2 */
+-#define SYS_TCx_TLCS_DIV4		__REGVAL(SYS_TCx_TLCS, 2)	/* CPU clock / 4 */
+-#define SYS_TCx_TLCS_DIV8		__REGVAL(SYS_TCx_TLCS, 3)	/* CPU clock / 8 */
+-#define SYS_TCx_TLCS_DIV16		__REGVAL(SYS_TCx_TLCS, 4)	/* CPU clock / 16 */
+-#define SYS_TCx_TLCS_DIV32		__REGVAL(SYS_TCx_TLCS, 5)	/* CPU clock / 32 */
+-#define SYS_TCx_TLCS_DIV64		__REGVAL(SYS_TCx_TLCS, 6)	/* CPU clock / 64 */
+-#define SYS_TCx_TLCS_EXT		__REGVAL(SYS_TCx_TLCS, 7)
+-
+-/* Timer x Control register: Timer mode */
+-#define SYS_TCx_TM		__REGBITS(5, 4)
+-#define SYS_TCx_TM_IEE			__REGVAL(SYS_TCx_TM, 0)		/* Internal timer or external event */
+-#define SYS_TCx_TM_ELL			__REGVAL(SYS_TCx_TM, 1)		/* External low-level, gated timer */
+-#define SYS_TCx_TM_EHL			__REGVAL(SYS_TCx_TM, 2)		/* External high-level, gated timer */
+-#define SYS_TCx_TM_CONCAT		__REGVAL(SYS_TCx_TM, 3)		/* Concatenate the lower timer. */
+-
+-/* Timer x Control register: Interrupt select */
+-#define SYS_TCx_INTS		__REGBIT(3)
+-#define SYS_TCx_INTS_DIS		__REGVAL(SYS_TCx_INTS, 0)
+-#define SYS_TCx_INTS_EN			__REGVAL(SYS_TCx_INTS, 1)
+-
+-/* Timer x Control register: Up/down select */
+-#define SYS_TCx_UDS		__REGBIT(2)
+-#define SYS_TCx_UDS_UP			__REGVAL(SYS_TCx_UDS, 0)
+-#define SYS_TCx_UDS_DOWN		__REGVAL(SYS_TCx_UDS, 1)
+-
+-/* Timer x Control register: 32- or 16-bit timer */
+-#define SYS_TCx_TSZ		__REGBIT(1)
+-#define SYS_TCx_TSZ_16			__REGVAL(SYS_TCx_TSZ, 0)
+-#define SYS_TCx_TSZ_32			__REGVAL(SYS_TCx_TSZ, 1)
+-
+-/* Timer x Control register: Reload enable */
+-#define SYS_TCx_REN		__REGBIT(0)
+-#define SYS_TCx_REN_DIS			__REGVAL(SYS_TCx_REN, 0)
+-#define SYS_TCx_REN_EN			__REGVAL(SYS_TCx_REN, 1)
+-
+-/* System Memory Chip Select x Dynamic Memory Base */
+-#define SYS_SMCSDMB(x)	__REG2(0xa09001d0, (x) << 1)
+-
+-/* System Memory Chip Select x Dynamic Memory Mask */
+-#define SYS_SMCSDMM(x)	__REG2(0xa09001d4, (x) << 1)
+-
+-/* System Memory Chip Select x Static Memory Base */
+-#define SYS_SMCSSMB(x)	__REG2(0xa09001f0, (x) << 1)
+-
+-/* System Memory Chip Select x Static Memory Base: Chip select x base */
+-#define SYS_SMCSSMB_CSxB	__REGBITS(31, 12)
+-
+-/* System Memory Chip Select x Static Memory Mask */
+-#define SYS_SMCSSMM(x)	__REG2(0xa09001f4, (x) << 1)
+-
+-/* System Memory Chip Select x Static Memory Mask: Chip select x mask */
+-#define SYS_SMCSSMM_CSxM	__REGBITS(31, 12)
+-
+-/* System Memory Chip Select x Static Memory Mask: Chip select x enable */
+-#define SYS_SMCSSMM_CSEx	__REGBIT(0)
+-#define SYS_SMCSSMM_CSEx_DIS		__REGVAL(SYS_SMCSSMM_CSEx, 0)
+-#define SYS_SMCSSMM_CSEx_EN		__REGVAL(SYS_SMCSSMM_CSEx, 1)
+-
+-/* General purpose, user-defined ID register */
+-#define SYS_GENID	__REG(0xa0900210)
+-
+-/* External Interrupt x Control register */
+-#define SYS_EIC(x)	__REG2(0xa0900214, (x))
+-
+-/* External Interrupt x Control register: Status */
+-#define SYS_EIC_STS		__REGBIT(3)
+-
+-/* External Interrupt x Control register: Clear */
+-#define SYS_EIC_CLR		__REGBIT(2)
+-
+-/* External Interrupt x Control register: Polarity */
+-#define SYS_EIC_PLTY		__REGBIT(1)
+-#define SYS_EIC_PLTY_AH			__REGVAL(SYS_EIC_PLTY, 0)
+-#define SYS_EIC_PLTY_AL			__REGVAL(SYS_EIC_PLTY, 1)
+-
+-/* External Interrupt x Control register: Level edge */
+-#define SYS_EIC_LVEDG		__REGBIT(0)
+-#define SYS_EIC_LVEDG_LEVEL		__REGVAL(SYS_EIC_LVEDG, 0)
+-#define SYS_EIC_LVEDG_EDGE		__REGVAL(SYS_EIC_LVEDG, 1)
+-
+-#endif /* ifndef __ASM_ARCH_REGSSYS_H */
+diff --git a/include/asm-arm/arch-ns9xxx/system.h b/include/asm-arm/arch-ns9xxx/system.h
+index c1082bd..1348073 100644
+--- a/include/asm-arm/arch-ns9xxx/system.h
++++ b/include/asm-arm/arch-ns9xxx/system.h
+@@ -1,7 +1,7 @@
+ /*
+  * include/asm-arm/arch-ns9xxx/system.h
+  *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+  * All rights reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+@@ -12,8 +12,8 @@
+ #define __ASM_ARCH_SYSTEM_H
+ 
+ #include <asm/proc-fns.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
+-#include <asm/mach-types.h>
++#include <asm/arch-ns9xxx/processor.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
+ 
+ static inline void arch_idle(void)
+ {
+@@ -22,11 +22,12 @@ static inline void arch_idle(void)
+ 
+ static inline void arch_reset(char mode)
+ {
+-	u32 reg;
+-
+-	reg = __raw_readl(SYS_PLL) >> 16;
+-	REGSET(reg, SYS_PLL, SWC, YES);
+-	__raw_writel(reg, SYS_PLL);
++#ifdef CONFIG_PROCESSOR_NS9360
++	if (processor_is_ns9360())
++		ns9360_reset(mode);
++	else
++#endif
++		BUG();
+ 
+ 	BUG();
+ }
+diff --git a/include/asm-arm/arch-ns9xxx/uncompress.h b/include/asm-arm/arch-ns9xxx/uncompress.h
+index 961ca7d..71066ba 100644
+--- a/include/asm-arm/arch-ns9xxx/uncompress.h
++++ b/include/asm-arm/arch-ns9xxx/uncompress.h
+@@ -11,20 +11,149 @@
+ #ifndef __ASM_ARCH_UNCOMPRESS_H
+ #define __ASM_ARCH_UNCOMPRESS_H
+ 
+-static void putc(char c)
++#include <asm/io.h>
++
++#define __REG(x)	((void __iomem __force *)(x))
++
++static void putc_dummy(char c, void __iomem *base)
+ {
+-	volatile u8 *base = (volatile u8 *)0x40000000;
+-	int t = 0x10000;
++	/* nothing */
++}
+ 
++static void putc_ns9360(char c, void __iomem *base)
++{
++	static int t = 0x10000;
++	do {
++		if (t)
++			--t;
++
++		if (__raw_readl(base + 8) & (1 << 3)) {
++			__raw_writeb(c, base + 16);
++			t = 0x10000;
++			break;
++		}
++	} while (t);
++}
++
++static void putc_a9m9750dev(char c, void __iomem *base)
++{
++	static int t = 0x10000;
++	do {
++		if (t)
++			--t;
++
++		if (__raw_readb(base + 5) & (1 << 5)) {
++			__raw_writeb(c, base);
++			t = 0x10000;
++			break;
++		}
++	} while (t);
++
++}
++
++static void putc_ns921x(char c, void __iomem *base)
++{
++	static int t = 0x10000;
+ 	do {
+-		if (base[5] & 0x20) {
+-			base[0] = c;
++		if (t)
++			--t;
++
++		if (!(__raw_readl(base) & (1 << 11))) {
++			__raw_writeb(c, base + 0x0028);
++			t = 0x10000;
+ 			break;
+ 		}
+-	} while (--t);
++	} while (t);
+ }
+ 
+-#define arch_decomp_setup()
++#define MSCS __REG(0xA0900184)
++
++#define NS9360_UARTA	__REG(0x90200040)
++#define NS9360_UARTB	__REG(0x90200000)
++#define NS9360_UARTC	__REG(0x90300000)
++#define NS9360_UARTD	__REG(0x90300040)
++
++#define NS9360_UART_ENABLED(base)					\
++		(__raw_readl(NS9360_UARTA) & (1 << 31))
++
++#define A9M9750DEV_UARTA	__REG(0x40000000)
++
++#define NS921XSYS_CLOCK	__REG(0xa090017c)
++#define NS921X_UARTA	__REG(0x90010000)
++#define NS921X_UARTB	__REG(0x90018000)
++#define NS921X_UARTC	__REG(0x90020000)
++#define NS921X_UARTD	__REG(0x90028000)
++
++#define NS921X_UART_ENABLED(base)					\
++		(__raw_readl((base) + 0x1000) & (1 << 29))
++
++static void autodetect(void (**putc)(char, void __iomem *), void __iomem **base)
++{
++	if (((__raw_readl(MSCS) >> 16) & 0xfe) == 0x00) {
++		/* ns9360 or ns9750 */
++		if (NS9360_UART_ENABLED(NS9360_UARTA)) {
++			*putc = putc_ns9360;
++			*base = NS9360_UARTA;
++			return;
++		} else if (NS9360_UART_ENABLED(NS9360_UARTB)) {
++			*putc = putc_ns9360;
++			*base = NS9360_UARTB;
++			return;
++		} else if (NS9360_UART_ENABLED(NS9360_UARTC)) {
++			*putc = putc_ns9360;
++			*base = NS9360_UARTC;
++			return;
++		} else if (NS9360_UART_ENABLED(NS9360_UARTD)) {
++			*putc = putc_ns9360;
++			*base = NS9360_UARTD;
++			return;
++		} else if (__raw_readl(__REG(0xa09001f4)) == 0xfffff001) {
++			*putc = putc_a9m9750dev;
++			*base = A9M9750DEV_UARTA;
++			return;
++		}
++	} else if (((__raw_readl(MSCS) >> 16) & 0xfe) == 0x02) {
++		/* ns921x */
++		u32 clock = __raw_readl(NS921XSYS_CLOCK);
++
++		if ((clock & (1 << 1)) &&
++				NS921X_UART_ENABLED(NS921X_UARTA)) {
++			*putc = putc_ns921x;
++			*base = NS921X_UARTA;
++			return;
++		} else if ((clock & (1 << 2)) &&
++				NS921X_UART_ENABLED(NS921X_UARTB)) {
++			*putc = putc_ns921x;
++			*base = NS921X_UARTB;
++			return;
++		} else if ((clock & (1 << 3)) &&
++				NS921X_UART_ENABLED(NS921X_UARTC)) {
++			*putc = putc_ns921x;
++			*base = NS921X_UARTC;
++			return;
++		} else if ((clock & (1 << 4)) &&
++				NS921X_UART_ENABLED(NS921X_UARTD)) {
++			*putc = putc_ns921x;
++			*base = NS921X_UARTD;
++			return;
++		}
++	}
++
++	*putc = putc_dummy;
++}
++
++void (*myputc)(char, void __iomem *);
++void __iomem *base;
++
++static void putc(char c)
++{
++	myputc(c, base);
++}
++
++static void arch_decomp_setup(void)
++{
++	autodetect(&myputc, &base);
++}
+ #define arch_decomp_wdog()
+ 
+ static void flush(void)
+diff --git a/include/asm-arm/arch-omap/board-osk.h b/include/asm-arm/arch-omap/board-osk.h
+index 2b1a8a4..9492609 100644
+--- a/include/asm-arm/arch-omap/board-osk.h
++++ b/include/asm-arm/arch-omap/board-osk.h
+@@ -32,5 +32,16 @@
+ /* At OMAP5912 OSK the Ethernet is directly connected to CS1 */
+ #define OMAP_OSK_ETHR_START		0x04800300
+ 
++/* TPS65010 has four GPIOs.  nPG and LED2 can be treated like GPIOs with
++ * alternate pin configurations for hardware-controlled blinking.
++ */
++#define OSK_TPS_GPIO_BASE		(OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
++#	define OSK_TPS_GPIO_USB_PWR_EN	(OSK_TPS_GPIO_BASE + 0)
++#	define OSK_TPS_GPIO_LED_D3	(OSK_TPS_GPIO_BASE + 1)
++#	define OSK_TPS_GPIO_LAN_RESET	(OSK_TPS_GPIO_BASE + 2)
++#	define OSK_TPS_GPIO_DSP_PWR_EN	(OSK_TPS_GPIO_BASE + 3)
++#	define OSK_TPS_GPIO_LED_D9	(OSK_TPS_GPIO_BASE + 4)
++#	define OSK_TPS_GPIO_LED_D2	(OSK_TPS_GPIO_BASE + 5)
++
+ #endif /*  __ASM_ARCH_OMAP_OSK_H */
+ 
+diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
+index fa68810..57523bd 100644
+--- a/include/asm-arm/arch-omap/clock.h
++++ b/include/asm-arm/arch-omap/clock.h
+@@ -14,6 +14,35 @@
+ #define __ARCH_ARM_OMAP_CLOCK_H
+ 
+ struct module;
++struct clk;
++
++#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
++
++struct clksel_rate {
++	u8			div;
++	u32			val;
++	u8			flags;
++};
++
++struct clksel {
++	struct clk		 *parent;
++	const struct clksel_rate *rates;
++};
++
++struct dpll_data {
++	void __iomem		*mult_div1_reg;
++	u32			mult_mask;
++	u32			div1_mask;
++#  if defined(CONFIG_ARCH_OMAP3)
++	void __iomem		*control_reg;
++	u32			enable_mask;
++	u8			auto_recal_bit;
++	u8			recal_en_bit;
++	u8			recal_st_bit;
++#  endif
++};
++
++#endif
+ 
+ struct clk {
+ 	struct list_head	node;
+@@ -25,8 +54,6 @@ struct clk {
+ 	__u32			flags;
+ 	void __iomem		*enable_reg;
+ 	__u8			enable_bit;
+-	__u8			rate_offset;
+-	__u8			src_offset;
+ 	__s8			usecount;
+ 	void			(*recalc)(struct clk *);
+ 	int			(*set_rate)(struct clk *, unsigned long);
+@@ -34,6 +61,16 @@ struct clk {
+ 	void			(*init)(struct clk *);
+ 	int			(*enable)(struct clk *);
+ 	void			(*disable)(struct clk *);
++#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
++	u8			fixed_div;
++	void __iomem		*clksel_reg;
++	u32			clksel_mask;
++	const struct clksel	*clksel;
++	const struct dpll_data	*dpll_data;
++#else
++	__u8			rate_offset;
++	__u8			src_offset;
++#endif
+ };
+ 
+ struct clk_functions {
+@@ -54,10 +91,12 @@ extern int clk_init(struct clk_functions * custom_clocks);
+ extern int clk_register(struct clk *clk);
+ extern void clk_unregister(struct clk *clk);
+ extern void propagate_rate(struct clk *clk);
++extern void recalculate_root_clocks(void);
+ extern void followparent_recalc(struct clk * clk);
+ extern void clk_allow_idle(struct clk *clk);
+ extern void clk_deny_idle(struct clk *clk);
+ extern int clk_get_usecount(struct clk *clk);
++extern void clk_enable_init_clocks(void);
+ 
+ /* Clock flags */
+ #define RATE_CKCTL		(1 << 0)	/* Main fixed ratio clocks */
+@@ -71,21 +110,33 @@ extern int clk_get_usecount(struct clk *clk);
+ #define CLOCK_NO_IDLE_PARENT	(1 << 8)
+ #define DELAYED_APP		(1 << 9)	/* Delay application of clock */
+ #define CONFIG_PARTICIPANT	(1 << 10)	/* Fundamental clock */
+-#define CM_MPU_SEL1		(1 << 11)	/* Domain divider/source */
+-#define CM_DSP_SEL1		(1 << 12)
+-#define CM_GFX_SEL1		(1 << 13)
+-#define CM_MODEM_SEL1		(1 << 14)
+-#define CM_CORE_SEL1		(1 << 15)	/* Sets divider for many */
+-#define CM_CORE_SEL2		(1 << 16)	/* sets parent for GPT */
+-#define CM_WKUP_SEL1		(1 << 17)
+-#define CM_PLL_SEL1		(1 << 18)
+-#define CM_PLL_SEL2		(1 << 19)
+-#define CM_SYSCLKOUT_SEL1	(1 << 20)
++#define ENABLE_ON_INIT		(1 << 11)	/* Enable upon framework init */
++#define INVERT_ENABLE           (1 << 12)       /* 0 enables, 1 disables */
++/* bits 13-20 are currently free */
+ #define CLOCK_IN_OMAP310	(1 << 21)
+ #define CLOCK_IN_OMAP730	(1 << 22)
+ #define CLOCK_IN_OMAP1510	(1 << 23)
+ #define CLOCK_IN_OMAP16XX	(1 << 24)
+ #define CLOCK_IN_OMAP242X	(1 << 25)
+ #define CLOCK_IN_OMAP243X	(1 << 26)
++#define CLOCK_IN_OMAP343X	(1 << 27)	/* clocks common to all 343X */
++#define PARENT_CONTROLS_CLOCK	(1 << 28)
++#define CLOCK_IN_OMAP3430ES1	(1 << 29)	/* 3430ES1 clocks only */
++#define CLOCK_IN_OMAP3430ES2	(1 << 30)	/* 3430ES2 clocks only */
++
++/* Clksel_rate flags */
++#define DEFAULT_RATE		(1 << 0)
++#define RATE_IN_242X		(1 << 1)
++#define RATE_IN_243X		(1 << 2)
++#define RATE_IN_343X		(1 << 3)	/* rates common to all 343X */
++#define RATE_IN_3430ES2		(1 << 4)	/* 3430ES2 rates only */
++
++#define RATE_IN_24XX		(RATE_IN_242X | RATE_IN_243X)
++
++
++/* CM_CLKSEL2_PLL.CORE_CLK_SRC options (24XX) */
++#define CORE_CLK_SRC_32K		0
++#define CORE_CLK_SRC_DPLL		1
++#define CORE_CLK_SRC_DPLL_X2		2
+ 
+ #endif
+diff --git a/include/asm-arm/arch-omap/control.h b/include/asm-arm/arch-omap/control.h
+new file mode 100644
+index 0000000..9944bb5
+--- /dev/null
++++ b/include/asm-arm/arch-omap/control.h
+@@ -0,0 +1,191 @@
++#ifndef __ASM_ARCH_CONTROL_H
++#define __ASM_ARCH_CONTROL_H
++
++/*
++ * include/asm-arm/arch-omap/control.h
++ *
++ * OMAP2/3 System Control Module definitions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation.
++ */
++
++#include <asm/arch/io.h>
++
++#define OMAP242X_CTRL_REGADDR(reg)					\
++	(void __iomem *)IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
++#define OMAP243X_CTRL_REGADDR(reg)					\
++	(void __iomem *)IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
++#define OMAP343X_CTRL_REGADDR(reg)					\
++	(void __iomem *)IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
++
++/*
++ * As elsewhere, the "OMAP2_" prefix indicates that the macro is valid for
++ * OMAP24XX and OMAP34XX.
++ */
++
++/* Control submodule offsets */
++
++#define OMAP2_CONTROL_INTERFACE		0x000
++#define OMAP2_CONTROL_PADCONFS		0x030
++#define OMAP2_CONTROL_GENERAL		0x270
++#define OMAP343X_CONTROL_MEM_WKUP	0x600
++#define OMAP343X_CONTROL_PADCONFS_WKUP	0xa00
++#define OMAP343X_CONTROL_GENERAL_WKUP	0xa60
++
++/* Control register offsets - read/write with omap_ctrl_{read,write}{bwl}() */
++
++#define OMAP2_CONTROL_SYSCONFIG		(OMAP2_CONTROL_INTERFACE + 0x10)
++
++/* CONTROL_GENERAL register offsets common to OMAP2 & 3 */
++#define OMAP2_CONTROL_DEVCONF0		(OMAP2_CONTROL_GENERAL + 0x0004)
++#define OMAP2_CONTROL_MSUSPENDMUX_0	(OMAP2_CONTROL_GENERAL + 0x0020)
++#define OMAP2_CONTROL_MSUSPENDMUX_1	(OMAP2_CONTROL_GENERAL + 0x0024)
++#define OMAP2_CONTROL_MSUSPENDMUX_2	(OMAP2_CONTROL_GENERAL + 0x0028)
++#define OMAP2_CONTROL_MSUSPENDMUX_3	(OMAP2_CONTROL_GENERAL + 0x002c)
++#define OMAP2_CONTROL_MSUSPENDMUX_4	(OMAP2_CONTROL_GENERAL + 0x0030)
++#define OMAP2_CONTROL_MSUSPENDMUX_5	(OMAP2_CONTROL_GENERAL + 0x0034)
++#define OMAP2_CONTROL_SEC_CTRL		(OMAP2_CONTROL_GENERAL + 0x0040)
++#define OMAP2_CONTROL_RPUB_KEY_H_0	(OMAP2_CONTROL_GENERAL + 0x0090)
++#define OMAP2_CONTROL_RPUB_KEY_H_1	(OMAP2_CONTROL_GENERAL + 0x0094)
++#define OMAP2_CONTROL_RPUB_KEY_H_2	(OMAP2_CONTROL_GENERAL + 0x0098)
++#define OMAP2_CONTROL_RPUB_KEY_H_3	(OMAP2_CONTROL_GENERAL + 0x009c)
++
++/* 242x-only CONTROL_GENERAL register offsets */
++#define OMAP242X_CONTROL_DEVCONF	OMAP2_CONTROL_DEVCONF0 /* match TRM */
++#define OMAP242X_CONTROL_OCM_RAM_PERM	(OMAP2_CONTROL_GENERAL + 0x0068)
++
++/* 243x-only CONTROL_GENERAL register offsets */
++/* CONTROL_IVA2_BOOT{ADDR,MOD} are at the same place on 343x - noted below */
++#define OMAP243X_CONTROL_DEVCONF1	(OMAP2_CONTROL_GENERAL + 0x0078)
++#define OMAP243X_CONTROL_CSIRXFE	(OMAP2_CONTROL_GENERAL + 0x007c)
++#define OMAP243X_CONTROL_IVA2_BOOTADDR	(OMAP2_CONTROL_GENERAL + 0x0190)
++#define OMAP243X_CONTROL_IVA2_BOOTMOD	(OMAP2_CONTROL_GENERAL + 0x0194)
++#define OMAP243X_CONTROL_IVA2_GEMCFG	(OMAP2_CONTROL_GENERAL + 0x0198)
++
++/* 24xx-only CONTROL_GENERAL register offsets */
++#define OMAP24XX_CONTROL_DEBOBS		(OMAP2_CONTROL_GENERAL + 0x0000)
++#define OMAP24XX_CONTROL_EMU_SUPPORT	(OMAP2_CONTROL_GENERAL + 0x0008)
++#define OMAP24XX_CONTROL_SEC_TEST	(OMAP2_CONTROL_GENERAL + 0x0044)
++#define OMAP24XX_CONTROL_PSA_CTRL	(OMAP2_CONTROL_GENERAL + 0x0048)
++#define OMAP24XX_CONTROL_PSA_CMD	(OMAP2_CONTROL_GENERAL + 0x004c)
++#define OMAP24XX_CONTROL_PSA_VALUE	(OMAP2_CONTROL_GENERAL + 0x0050)
++#define OMAP24XX_CONTROL_SEC_EMU	(OMAP2_CONTROL_GENERAL + 0x0060)
++#define OMAP24XX_CONTROL_SEC_TAP	(OMAP2_CONTROL_GENERAL + 0x0064)
++#define OMAP24XX_CONTROL_OCM_PUB_RAM_ADD	(OMAP2_CONTROL_GENERAL + 0x006c)
++#define OMAP24XX_CONTROL_EXT_SEC_RAM_START_ADD	(OMAP2_CONTROL_GENERAL + 0x0070)
++#define OMAP24XX_CONTROL_EXT_SEC_RAM_STOP_ADD	(OMAP2_CONTROL_GENERAL + 0x0074
++#define OMAP24XX_CONTROL_SEC_STATUS		(OMAP2_CONTROL_GENERAL + 0x0080)
++#define OMAP24XX_CONTROL_SEC_ERR_STATUS		(OMAP2_CONTROL_GENERAL + 0x0084)
++#define OMAP24XX_CONTROL_STATUS			(OMAP2_CONTROL_GENERAL + 0x0088)
++#define OMAP24XX_CONTROL_GENERAL_PURPOSE_STATUS	(OMAP2_CONTROL_GENERAL + 0x008c)
++#define OMAP24XX_CONTROL_RAND_KEY_0	(OMAP2_CONTROL_GENERAL + 0x00a0)
++#define OMAP24XX_CONTROL_RAND_KEY_1	(OMAP2_CONTROL_GENERAL + 0x00a4)
++#define OMAP24XX_CONTROL_RAND_KEY_2	(OMAP2_CONTROL_GENERAL + 0x00a8)
++#define OMAP24XX_CONTROL_RAND_KEY_3	(OMAP2_CONTROL_GENERAL + 0x00ac)
++#define OMAP24XX_CONTROL_CUST_KEY_0	(OMAP2_CONTROL_GENERAL + 0x00b0)
++#define OMAP24XX_CONTROL_CUST_KEY_1	(OMAP2_CONTROL_GENERAL + 0x00b4)
++#define OMAP24XX_CONTROL_TEST_KEY_0	(OMAP2_CONTROL_GENERAL + 0x00c0)
++#define OMAP24XX_CONTROL_TEST_KEY_1	(OMAP2_CONTROL_GENERAL + 0x00c4)
++#define OMAP24XX_CONTROL_TEST_KEY_2	(OMAP2_CONTROL_GENERAL + 0x00c8)
++#define OMAP24XX_CONTROL_TEST_KEY_3	(OMAP2_CONTROL_GENERAL + 0x00cc)
++#define OMAP24XX_CONTROL_TEST_KEY_4	(OMAP2_CONTROL_GENERAL + 0x00d0)
++#define OMAP24XX_CONTROL_TEST_KEY_5	(OMAP2_CONTROL_GENERAL + 0x00d4)
++#define OMAP24XX_CONTROL_TEST_KEY_6	(OMAP2_CONTROL_GENERAL + 0x00d8)
++#define OMAP24XX_CONTROL_TEST_KEY_7	(OMAP2_CONTROL_GENERAL + 0x00dc)
++#define OMAP24XX_CONTROL_TEST_KEY_8	(OMAP2_CONTROL_GENERAL + 0x00e0)
++#define OMAP24XX_CONTROL_TEST_KEY_9	(OMAP2_CONTROL_GENERAL + 0x00e4)
++
++/* 34xx-only CONTROL_GENERAL register offsets */
++#define OMAP343X_CONTROL_PADCONF_OFF	(OMAP2_CONTROL_GENERAL + 0x0000)
++#define OMAP343X_CONTROL_MEM_DFTRW0	(OMAP2_CONTROL_GENERAL + 0x0008)
++#define OMAP343X_CONTROL_MEM_DFTRW1	(OMAP2_CONTROL_GENERAL + 0x000c)
++#define OMAP343X_CONTROL_DEVCONF1	(OMAP2_CONTROL_GENERAL + 0x0068)
++#define OMAP343X_CONTROL_CSIRXFE		(OMAP2_CONTROL_GENERAL + 0x006c)
++#define OMAP343X_CONTROL_SEC_STATUS		(OMAP2_CONTROL_GENERAL + 0x0070)
++#define OMAP343X_CONTROL_SEC_ERR_STATUS		(OMAP2_CONTROL_GENERAL + 0x0074)
++#define OMAP343X_CONTROL_SEC_ERR_STATUS_DEBUG	(OMAP2_CONTROL_GENERAL + 0x0078)
++#define OMAP343X_CONTROL_STATUS			(OMAP2_CONTROL_GENERAL + 0x0080)
++#define OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS	(OMAP2_CONTROL_GENERAL + 0x0084)
++#define OMAP343X_CONTROL_RPUB_KEY_H_4	(OMAP2_CONTROL_GENERAL + 0x00a0)
++#define OMAP343X_CONTROL_RAND_KEY_0	(OMAP2_CONTROL_GENERAL + 0x00a8)
++#define OMAP343X_CONTROL_RAND_KEY_1	(OMAP2_CONTROL_GENERAL + 0x00ac)
++#define OMAP343X_CONTROL_RAND_KEY_2	(OMAP2_CONTROL_GENERAL + 0x00b0)
++#define OMAP343X_CONTROL_RAND_KEY_3	(OMAP2_CONTROL_GENERAL + 0x00b4)
++#define OMAP343X_CONTROL_TEST_KEY_0	(OMAP2_CONTROL_GENERAL + 0x00c8)
++#define OMAP343X_CONTROL_TEST_KEY_1	(OMAP2_CONTROL_GENERAL + 0x00cc)
++#define OMAP343X_CONTROL_TEST_KEY_2	(OMAP2_CONTROL_GENERAL + 0x00d0)
++#define OMAP343X_CONTROL_TEST_KEY_3	(OMAP2_CONTROL_GENERAL + 0x00d4)
++#define OMAP343X_CONTROL_TEST_KEY_4	(OMAP2_CONTROL_GENERAL + 0x00d8)
++#define OMAP343X_CONTROL_TEST_KEY_5	(OMAP2_CONTROL_GENERAL + 0x00dc)
++#define OMAP343X_CONTROL_TEST_KEY_6	(OMAP2_CONTROL_GENERAL + 0x00e0)
++#define OMAP343X_CONTROL_TEST_KEY_7	(OMAP2_CONTROL_GENERAL + 0x00e4)
++#define OMAP343X_CONTROL_TEST_KEY_8	(OMAP2_CONTROL_GENERAL + 0x00e8)
++#define OMAP343X_CONTROL_TEST_KEY_9	(OMAP2_CONTROL_GENERAL + 0x00ec)
++#define OMAP343X_CONTROL_TEST_KEY_10	(OMAP2_CONTROL_GENERAL + 0x00f0)
++#define OMAP343X_CONTROL_TEST_KEY_11	(OMAP2_CONTROL_GENERAL + 0x00f4)
++#define OMAP343X_CONTROL_TEST_KEY_12	(OMAP2_CONTROL_GENERAL + 0x00f8)
++#define OMAP343X_CONTROL_TEST_KEY_13	(OMAP2_CONTROL_GENERAL + 0x00fc)
++#define OMAP343X_CONTROL_IVA2_BOOTADDR	(OMAP2_CONTROL_GENERAL + 0x0190)
++#define OMAP343X_CONTROL_IVA2_BOOTMOD	(OMAP2_CONTROL_GENERAL + 0x0194)
++
++/*
++ * REVISIT: This list of registers is not comprehensive - there are more
++ * that should be added.
++ */
++
++/*
++ * Control module register bit defines - these should eventually go into
++ * their own regbits file.  Some of these will be complicated, depending
++ * on the device type (general-purpose, emulator, test, secure, bad, other)
++ * and the security mode (secure, non-secure, don't care)
++ */
++/* CONTROL_DEVCONF0 bits */
++#define OMAP24XX_USBSTANDBYCTRL		(1 << 15)
++#define OMAP2_MCBSP2_CLKS_MASK		(1 << 6)
++#define OMAP2_MCBSP1_CLKS_MASK		(1 << 2)
++
++/* CONTROL_DEVCONF1 bits */
++#define OMAP2_MCBSP5_CLKS_MASK		(1 << 4) /* > 242x */
++#define OMAP2_MCBSP4_CLKS_MASK		(1 << 2) /* > 242x */
++#define OMAP2_MCBSP3_CLKS_MASK		(1 << 0) /* > 242x */
++
++/* CONTROL_STATUS bits */
++#define OMAP2_DEVICETYPE_MASK		(0x7 << 8)
++#define OMAP2_SYSBOOT_5_MASK		(1 << 5)
++#define OMAP2_SYSBOOT_4_MASK		(1 << 4)
++#define OMAP2_SYSBOOT_3_MASK		(1 << 3)
++#define OMAP2_SYSBOOT_2_MASK		(1 << 2)
++#define OMAP2_SYSBOOT_1_MASK		(1 << 1)
++#define OMAP2_SYSBOOT_0_MASK		(1 << 0)
++
++#ifndef __ASSEMBLY__
++#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
++extern void omap_ctrl_base_set(u32 base);
++extern u32 omap_ctrl_base_get(void);
++extern u8 omap_ctrl_readb(u16 offset);
++extern u16 omap_ctrl_readw(u16 offset);
++extern u32 omap_ctrl_readl(u16 offset);
++extern void omap_ctrl_writeb(u8 val, u16 offset);
++extern void omap_ctrl_writew(u16 val, u16 offset);
++extern void omap_ctrl_writel(u32 val, u16 offset);
++#else
++#define omap_ctrl_base_set(x)		WARN_ON(1)
++#define omap_ctrl_base_get()		0
++#define omap_ctrl_readb(x)		0
++#define omap_ctrl_readw(x)		0
++#define omap_ctrl_readl(x)		0
++#define omap_ctrl_writeb(x, y)		WARN_ON(1)
++#define omap_ctrl_writew(x, y)		WARN_ON(1)
++#define omap_ctrl_writel(x, y)		WARN_ON(1)
++#endif
++#endif	/* __ASSEMBLY__ */
++
++#endif /* __ASM_ARCH_CONTROL_H */
++
+diff --git a/include/asm-arm/arch-omap/entry-macro.S b/include/asm-arm/arch-omap/entry-macro.S
+index f6967c8..74cd572 100644
+--- a/include/asm-arm/arch-omap/entry-macro.S
++++ b/include/asm-arm/arch-omap/entry-macro.S
+@@ -68,7 +68,7 @@
+ 		.endm
+ 
+ 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+-		ldr	\base, =VA_IC_BASE
++		ldr	\base, =OMAP2_VA_IC_BASE
+ 		ldr	\irqnr, [\base, #0x98] /* IRQ pending reg 1 */
+ 		cmp	\irqnr, #0x0
+ 		bne	2222f
+diff --git a/include/asm-arm/arch-omap/gpio.h b/include/asm-arm/arch-omap/gpio.h
+index 164da09..86621a0 100644
+--- a/include/asm-arm/arch-omap/gpio.h
++++ b/include/asm-arm/arch-omap/gpio.h
+@@ -82,62 +82,35 @@ extern void omap_set_gpio_debounce_time(int gpio, int enable);
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-/* wrappers for "new style" GPIO calls. the old OMAP-specfic ones should
+- * eventually be removed (along with this errno.h inclusion), and maybe
+- * gpios should put MPUIOs last too.
++/* Wrappers for "new style" GPIO calls, using the new infrastructure
++ * which lets us plug in FPGA, I2C, and other implementations.
++ * *
++ * The original OMAP-specfic calls should eventually be removed.
+  */
+ 
+-#include <asm/errno.h>
+-
+-static inline int gpio_request(unsigned gpio, const char *label)
+-{
+-	return omap_request_gpio(gpio);
+-}
+-
+-static inline void gpio_free(unsigned gpio)
+-{
+-	omap_free_gpio(gpio);
+-}
+-
+-static inline int __gpio_set_direction(unsigned gpio, int is_input)
+-{
+-	if (cpu_class_is_omap2()) {
+-		if (gpio > OMAP_MAX_GPIO_LINES)
+-			return -EINVAL;
+-	} else {
+-		if (gpio > (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */))
+-			return -EINVAL;
+-	}
+-	omap_set_gpio_direction(gpio, is_input);
+-	return 0;
+-}
+-
+-static inline int gpio_direction_input(unsigned gpio)
+-{
+-	return __gpio_set_direction(gpio, 1);
+-}
+-
+-static inline int gpio_direction_output(unsigned gpio, int value)
+-{
+-	omap_set_gpio_dataout(gpio, value);
+-	return __gpio_set_direction(gpio, 0);
+-}
++#include <linux/errno.h>
++#include <asm-generic/gpio.h>
+ 
+ static inline int gpio_get_value(unsigned gpio)
+ {
+-	return omap_get_gpio_datain(gpio);
++	return __gpio_get_value(gpio);
+ }
+ 
+ static inline void gpio_set_value(unsigned gpio, int value)
+ {
+-	omap_set_gpio_dataout(gpio, value);
++	__gpio_set_value(gpio, value);
+ }
+ 
+-#include <asm-generic/gpio.h>		/* cansleep wrappers */
++static inline int gpio_cansleep(unsigned gpio)
++{
++	return __gpio_cansleep(gpio);
++}
+ 
+ static inline int gpio_to_irq(unsigned gpio)
+ {
+-	return OMAP_GPIO_IRQ(gpio);
++	if (gpio < (OMAP_MAX_GPIO_LINES + 16))
++		return OMAP_GPIO_IRQ(gpio);
++	return -EINVAL;
+ }
+ 
+ static inline int irq_to_gpio(unsigned irq)
+diff --git a/include/asm-arm/arch-omap/io.h b/include/asm-arm/arch-omap/io.h
+index 289082d..160578e 100644
+--- a/include/asm-arm/arch-omap/io.h
++++ b/include/asm-arm/arch-omap/io.h
+@@ -80,6 +80,13 @@
+ #define OMAP243X_GPMC_PHYS	OMAP243X_GPMC_BASE	/* 0x49000000 */
+ #define OMAP243X_GPMC_VIRT	0xFE000000
+ #define OMAP243X_GPMC_SIZE	SZ_1M
++#define OMAP243X_SDRC_PHYS	OMAP243X_SDRC_BASE
++#define OMAP243X_SDRC_VIRT	0xFD000000
++#define OMAP243X_SDRC_SIZE	SZ_1M
++#define OMAP243X_SMS_PHYS	OMAP243X_SMS_BASE
++#define OMAP243X_SMS_VIRT	0xFC000000
++#define OMAP243X_SMS_SIZE	SZ_1M
++
+ #endif
+ 
+ #define IO_OFFSET	0x90000000
+@@ -88,16 +95,73 @@
+ #define io_v2p(va)	((va) - IO_OFFSET)	/* Works for L3 and L4 */
+ 
+ /* DSP */
+-#define DSP_MEM_24XX_PHYS	OMAP24XX_DSP_MEM_BASE	/* 0x58000000 */
++#define DSP_MEM_24XX_PHYS	OMAP2420_DSP_MEM_BASE	/* 0x58000000 */
+ #define DSP_MEM_24XX_VIRT	0xe0000000
+ #define DSP_MEM_24XX_SIZE	0x28000
+-#define DSP_IPI_24XX_PHYS	OMAP24XX_DSP_IPI_BASE	/* 0x59000000 */
++#define DSP_IPI_24XX_PHYS	OMAP2420_DSP_IPI_BASE	/* 0x59000000 */
+ #define DSP_IPI_24XX_VIRT	0xe1000000
+ #define DSP_IPI_24XX_SIZE	SZ_4K
+-#define DSP_MMU_24XX_PHYS	OMAP24XX_DSP_MMU_BASE	/* 0x5a000000 */
++#define DSP_MMU_24XX_PHYS	OMAP2420_DSP_MMU_BASE	/* 0x5a000000 */
+ #define DSP_MMU_24XX_VIRT	0xe2000000
+ #define DSP_MMU_24XX_SIZE	SZ_4K
+ 
++#elif defined(CONFIG_ARCH_OMAP3)
++
++/* We map both L3 and L4 on OMAP3 */
++#define L3_34XX_PHYS		L3_34XX_BASE	/* 0x68000000 */
++#define L3_34XX_VIRT		0xf8000000
++#define L3_34XX_SIZE		SZ_1M   /* 44kB of 128MB used, want 1MB sect */
++
++#define L4_34XX_PHYS		L4_34XX_BASE	/* 0x48000000 */
++#define L4_34XX_VIRT		0xd8000000
++#define L4_34XX_SIZE		SZ_4M   /* 1MB of 128MB used, want 1MB sect */
++
++/*
++ * Need to look at the Size 4M for L4.
++ * VPOM3430 was not working for Int controller
++ */
++
++#define L4_WK_34XX_PHYS		L4_WK_34XX_BASE /* 0x48300000 */
++#define L4_WK_34XX_VIRT		0xd8300000
++#define L4_WK_34XX_SIZE		SZ_1M
++
++#define L4_PER_34XX_PHYS	L4_PER_34XX_BASE /* 0x49000000 */
++#define L4_PER_34XX_VIRT	0xd9000000
++#define L4_PER_34XX_SIZE	SZ_1M
++
++#define L4_EMU_34XX_PHYS	L4_EMU_34XX_BASE /* 0x54000000 */
++#define L4_EMU_34XX_VIRT	0xe4000000
++#define L4_EMU_34XX_SIZE	SZ_64M
++
++#define OMAP34XX_GPMC_PHYS	OMAP34XX_GPMC_BASE /* 0x6E000000 */
++#define OMAP34XX_GPMC_VIRT	0xFE000000
++#define OMAP34XX_GPMC_SIZE	SZ_1M
++
++#define OMAP343X_SMS_PHYS	OMAP343X_SMS_BASE /* 0x6C000000 */
++#define OMAP343X_SMS_VIRT	0xFC000000
++#define OMAP343X_SMS_SIZE	SZ_1M
++
++#define OMAP343X_SDRC_PHYS	OMAP343X_SDRC_BASE /* 0x6D000000 */
++#define OMAP343X_SDRC_VIRT	0xFD000000
++#define OMAP343X_SDRC_SIZE	SZ_1M
++
++
++#define IO_OFFSET		0x90000000
++#define IO_ADDRESS(pa)		((pa) + IO_OFFSET)/* Works for L3 and L4 */
++#define io_p2v(pa)		((pa) + IO_OFFSET)/* Works for L3 and L4 */
++#define io_v2p(va)		((va) - IO_OFFSET)/* Works for L3 and L4 */
++
++/* DSP */
++#define DSP_MEM_34XX_PHYS	OMAP34XX_DSP_MEM_BASE	/* 0x58000000 */
++#define DSP_MEM_34XX_VIRT	0xe0000000
++#define DSP_MEM_34XX_SIZE	0x28000
++#define DSP_IPI_34XX_PHYS	OMAP34XX_DSP_IPI_BASE	/* 0x59000000 */
++#define DSP_IPI_34XX_VIRT	0xe1000000
++#define DSP_IPI_34XX_SIZE	SZ_4K
++#define DSP_MMU_34XX_PHYS	OMAP34XX_DSP_MMU_BASE	/* 0x5a000000 */
++#define DSP_MMU_34XX_VIRT	0xe2000000
++#define DSP_MMU_34XX_SIZE	SZ_4K
++
+ #endif
+ 
+ #ifndef __ASSEMBLER__
+diff --git a/include/asm-arm/arch-omap/mmc.h b/include/asm-arm/arch-omap/mmc.h
+index b70e37b..c9588f4 100644
+--- a/include/asm-arm/arch-omap/mmc.h
++++ b/include/asm-arm/arch-omap/mmc.h
+@@ -18,6 +18,8 @@
+ #define OMAP_MMC_MAX_SLOTS	2
+ 
+ struct omap_mmc_platform_data {
++	struct omap_mmc_conf	conf;
++
+ 	unsigned enabled:1;
+ 	/* number of slots on board */
+ 	unsigned nr_slots:2;
+diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
+index b8fff50..ff9a5b5 100644
+--- a/include/asm-arm/arch-omap/mux.h
++++ b/include/asm-arm/arch-omap/mux.h
+@@ -4,9 +4,10 @@
+  * Table of the Omap register configurations for the FUNC_MUX and
+  * PULL_DWN combinations.
+  *
+- * Copyright (C) 2003 - 2005 Nokia Corporation
++ * Copyright (C) 2004 - 2008 Texas Instruments Inc.
++ * Copyright (C) 2003 - 2008 Nokia Corporation
+  *
+- * Written by Tony Lindgren <tony.lindgren at nokia.com>
++ * Written by Tony Lindgren
+  *
+  * This 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,14 +28,6 @@
+  *	 - W8	     = ball
+  *	 - 1610	     = 1510 or 1610, none if common for both 1510 and 1610
+  *	 - MMC2_DAT0 = function
+- *
+- * Change log:
+- *   Added entry for the I2C interface. (02Feb 2004)
+- *   Copyright (C) 2004 Texas Instruments
+- *
+- *   Added entry for the keypad and uwire CS1. (09Mar 2004)
+- *   Copyright (C) 2004 Texas Instruments
+- *
+  */
+ 
+ #ifndef __ASM_ARCH_MUX_H
+@@ -469,7 +462,12 @@ enum omap24xx_index {
+ 	AA8_242X_GPIO58,
+ 	Y20_24XX_GPIO60,
+ 	W4__24XX_GPIO74,
++	N15_24XX_GPIO85,
+ 	M15_24XX_GPIO92,
++	P20_24XX_GPIO93,
++	P18_24XX_GPIO95,
++	M18_24XX_GPIO96,
++	L14_24XX_GPIO97,
+ 	J15_24XX_GPIO99,
+ 	V14_24XX_GPIO117,
+ 	P14_24XX_GPIO125,
+@@ -494,8 +492,6 @@ enum omap24xx_index {
+ 	D3_242X_DMAREQ4,
+ 	E3_242X_DMAREQ5,
+ 
+-	P20_24XX_TSC_IRQ,
+-
+ 	/* UART3 */
+ 	K15_24XX_UART3_TX,
+ 	K14_24XX_UART3_RX,
+@@ -557,13 +553,57 @@ enum omap24xx_index {
+ 	B3__24XX_KBR5,
+ 	AA4_24XX_KBC2,
+ 	B13_24XX_KBC6,
++
++	/* 2430 USB */
++	AD9_2430_USB0_PUEN,
++	Y11_2430_USB0_VP,
++	AD7_2430_USB0_VM,
++	AE7_2430_USB0_RCV,
++	AD4_2430_USB0_TXEN,
++	AF9_2430_USB0_SE0,
++	AE6_2430_USB0_DAT,
++	AD24_2430_USB1_SE0,
++	AB24_2430_USB1_RCV,
++	Y25_2430_USB1_TXEN,
++	AA26_2430_USB1_DAT,
++
++	/* 2430 HS-USB */
++	AD9_2430_USB0HS_DATA3,
++	Y11_2430_USB0HS_DATA4,
++	AD7_2430_USB0HS_DATA5,
++	AE7_2430_USB0HS_DATA6,
++	AD4_2430_USB0HS_DATA2,
++	AF9_2430_USB0HS_DATA0,
++	AE6_2430_USB0HS_DATA1,
++	AE8_2430_USB0HS_CLK,
++	AD8_2430_USB0HS_DIR,
++	AE5_2430_USB0HS_STP,
++	AE9_2430_USB0HS_NXT,
++	AC7_2430_USB0HS_DATA7,
++
++	/* 2430 McBSP */
++	AC10_2430_MCBSP2_FSX,
++	AD16_2430_MCBSP2_CLX,
++	AE13_2430_MCBSP2_DX,
++	AD13_2430_MCBSP2_DR,
++	AC10_2430_MCBSP2_FSX_OFF,
++	AD16_2430_MCBSP2_CLX_OFF,
++	AE13_2430_MCBSP2_DX_OFF,
++	AD13_2430_MCBSP2_DR_OFF,
++
++};
++
++struct omap_mux_cfg {
++	struct pin_config	*pins;
++	unsigned long		size;
++	int			(*cfg_reg)(const struct pin_config *cfg);
+ };
+ 
+ #ifdef	CONFIG_OMAP_MUX
+ /* setup pin muxing in Linux */
+ extern int omap1_mux_init(void);
+ extern int omap2_mux_init(void);
+-extern int omap_mux_register(struct pin_config * pins, unsigned long size);
++extern int omap_mux_register(struct omap_mux_cfg *);
+ extern int omap_cfg_reg(unsigned long reg_cfg);
+ #else
+ /* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */
+diff --git a/include/asm-arm/arch-omap/omap24xx.h b/include/asm-arm/arch-omap/omap24xx.h
+index 14c0f94..b9fcaae 100644
+--- a/include/asm-arm/arch-omap/omap24xx.h
++++ b/include/asm-arm/arch-omap/omap24xx.h
+@@ -1,3 +1,28 @@
++/*
++ * include/asm-arm/arch-omap/omap24xx.h
++ *
++ * This file contains the processor specific definitions
++ * of the TI OMAP24XX.
++ *
++ * Copyright (C) 2007 Texas Instruments.
++ * Copyright (C) 2007 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ */
++
+ #ifndef __ASM_ARCH_OMAP24XX_H
+ #define __ASM_ARCH_OMAP24XX_H
+ 
+@@ -13,33 +38,70 @@
+ 
+ /* interrupt controller */
+ #define OMAP24XX_IC_BASE	(L4_24XX_BASE + 0xfe000)
+-#define VA_IC_BASE		IO_ADDRESS(OMAP24XX_IC_BASE)
+ #define OMAP24XX_IVA_INTC_BASE	0x40000000
+ #define IRQ_SIR_IRQ		0x0040
+ 
+-#ifdef CONFIG_ARCH_OMAP2420
+-#define OMAP24XX_32KSYNCT_BASE	(L4_24XX_BASE + 0x4000)
+-#define OMAP24XX_PRCM_BASE	(L4_24XX_BASE + 0x8000)
+-#define OMAP24XX_SDRC_BASE	(L3_24XX_BASE + 0x9000)
+-#define OMAP242X_CONTROL_STATUS	(L4_24XX_BASE + 0x2f8)
+-#endif
++#define OMAP2420_CTRL_BASE	L4_24XX_BASE
++#define OMAP2420_32KSYNCT_BASE	(L4_24XX_BASE + 0x4000)
++#define OMAP2420_PRCM_BASE	(L4_24XX_BASE + 0x8000)
++#define OMAP2420_CM_BASE	(L4_24XX_BASE + 0x8000)
++#define OMAP2420_PRM_BASE	OMAP2420_CM_BASE
++#define OMAP2420_SDRC_BASE	(L3_24XX_BASE + 0x9000)
++#define OMAP2420_SMS_BASE	0x68008000
+ 
+-#ifdef CONFIG_ARCH_OMAP2430
+-#define OMAP24XX_32KSYNCT_BASE	(L4_WK_243X_BASE + 0x20000)
+-#define OMAP24XX_PRCM_BASE	(L4_WK_243X_BASE + 0x6000)
+-#define OMAP24XX_SDRC_BASE	(0x6D000000)
+-#define OMAP242X_CONTROL_STATUS	(L4_24XX_BASE + 0x2f8)
++#define OMAP2430_32KSYNCT_BASE	(L4_WK_243X_BASE + 0x20000)
++#define OMAP2430_PRCM_BASE	(L4_WK_243X_BASE + 0x6000)
++#define OMAP2430_CM_BASE	(L4_WK_243X_BASE + 0x6000)
++#define OMAP2430_PRM_BASE	OMAP2430_CM_BASE
++
++#define OMAP243X_SMS_BASE	0x6C000000
++#define OMAP243X_SDRC_BASE	0x6D000000
+ #define OMAP243X_GPMC_BASE	0x6E000000
+-#endif
++#define OMAP243X_SCM_BASE	(L4_WK_243X_BASE + 0x2000)
++#define OMAP243X_CTRL_BASE	OMAP243X_SCM_BASE
++#define OMAP243X_HS_BASE	(L4_24XX_BASE + 0x000ac000)
+ 
+ /* DSP SS */
+-#define OMAP24XX_DSP_BASE	0x58000000
+-#define OMAP24XX_DSP_MEM_BASE	(OMAP24XX_DSP_BASE + 0x0)
+-#define OMAP24XX_DSP_IPI_BASE	(OMAP24XX_DSP_BASE + 0x1000000)
+-#define OMAP24XX_DSP_MMU_BASE	(OMAP24XX_DSP_BASE + 0x2000000)
++#define OMAP2420_DSP_BASE	0x58000000
++#define OMAP2420_DSP_MEM_BASE	(OMAP2420_DSP_BASE + 0x0)
++#define OMAP2420_DSP_IPI_BASE	(OMAP2420_DSP_BASE + 0x1000000)
++#define OMAP2420_DSP_MMU_BASE	(OMAP2420_DSP_BASE + 0x2000000)
++
++#define OMAP243X_DSP_BASE	0x5C000000
++#define OMAP243X_DSP_MEM_BASE	(OMAP243X_DSP_BASE + 0x0)
++#define OMAP243X_DSP_MMU_BASE	(OMAP243X_DSP_BASE + 0x1000000)
+ 
+ /* Mailbox */
+ #define OMAP24XX_MAILBOX_BASE	(L4_24XX_BASE + 0x94000)
+ 
++/* Camera */
++#define OMAP24XX_CAMERA_BASE	(L4_24XX_BASE + 0x52000)
++
++/* Security */
++#define OMAP24XX_SEC_BASE	(L4_24XX_BASE + 0xA0000)
++#define OMAP24XX_SEC_RNG_BASE	(OMAP24XX_SEC_BASE + 0x0000)
++#define OMAP24XX_SEC_DES_BASE	(OMAP24XX_SEC_BASE + 0x2000)
++#define OMAP24XX_SEC_SHA1MD5_BASE (OMAP24XX_SEC_BASE + 0x4000)
++#define OMAP24XX_SEC_AES_BASE	(OMAP24XX_SEC_BASE + 0x6000)
++#define OMAP24XX_SEC_PKA_BASE	(OMAP24XX_SEC_BASE + 0x8000)
++
++#if defined(CONFIG_ARCH_OMAP2420)
++
++#define OMAP2_32KSYNCT_BASE	OMAP2420_32KSYNCT_BASE
++#define OMAP2_PRCM_BASE		OMAP2420_PRCM_BASE
++#define OMAP2_CM_BASE		OMAP2420_CM_BASE
++#define OMAP2_PRM_BASE		OMAP2420_PRM_BASE
++#define OMAP2_VA_IC_BASE	IO_ADDRESS(OMAP24XX_IC_BASE)
++
++#elif defined(CONFIG_ARCH_OMAP2430)
++
++#define OMAP2_32KSYNCT_BASE	OMAP2430_32KSYNCT_BASE
++#define OMAP2_PRCM_BASE		OMAP2430_PRCM_BASE
++#define OMAP2_CM_BASE		OMAP2430_CM_BASE
++#define OMAP2_PRM_BASE		OMAP2430_PRM_BASE
++#define OMAP2_VA_IC_BASE	IO_ADDRESS(OMAP24XX_IC_BASE)
++
++#endif
++
+ #endif /* __ASM_ARCH_OMAP24XX_H */
+ 
+diff --git a/include/asm-arm/arch-omap/sdrc.h b/include/asm-arm/arch-omap/sdrc.h
+new file mode 100644
+index 0000000..673b396
+--- /dev/null
++++ b/include/asm-arm/arch-omap/sdrc.h
+@@ -0,0 +1,75 @@
++#ifndef ____ASM_ARCH_SDRC_H
++#define ____ASM_ARCH_SDRC_H
++
++/*
++ * OMAP2/3 SDRC/SMS register definitions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <asm/arch/io.h>
++
++/* SDRC register offsets - read/write with sdrc_{read,write}_reg() */
++
++#define SDRC_SYSCONFIG		0x010
++#define SDRC_DLLA_CTRL		0x060
++#define SDRC_DLLA_STATUS	0x064
++#define SDRC_DLLB_CTRL		0x068
++#define SDRC_DLLB_STATUS	0x06C
++#define SDRC_POWER		0x070
++#define SDRC_MR_0		0x084
++#define SDRC_RFR_CTRL_0		0x0a4
++
++/*
++ * These values represent the number of memory clock cycles between
++ * autorefresh initiation.  They assume 1 refresh per 64 ms (JEDEC), 8192
++ * rows per device, and include a subtraction of a 50 cycle window in the
++ * event that the autorefresh command is delayed due to other SDRC activity.
++ * The '| 1' sets the ARE field to send one autorefresh when the autorefresh
++ * counter reaches 0.
++ *
++ * These represent optimal values for common parts, it won't work for all.
++ * As long as you scale down, most parameters are still work, they just
++ * become sub-optimal. The RFR value goes in the opposite direction. If you
++ * don't adjust it down as your clock period increases the refresh interval
++ * will not be met. Setting all parameters for complete worst case may work,
++ * but may cut memory performance by 2x. Due to errata the DLLs need to be
++ * unlocked and their value needs run time calibration.	A dynamic call is
++ * need for that as no single right value exists acorss production samples.
++ *
++ * Only the FULL speed values are given. Current code is such that rate
++ * changes must be made at DPLLoutx2. The actual value adjustment for low
++ * frequency operation will be handled by omap_set_performance()
++ *
++ * By having the boot loader boot up in the fastest L4 speed available likely
++ * will result in something which you can switch between.
++ */
++#define SDRC_RFR_CTRL_165MHz	(0x00044c00 | 1)
++#define SDRC_RFR_CTRL_133MHz	(0x0003de00 | 1)
++#define SDRC_RFR_CTRL_100MHz	(0x0002da01 | 1)
++#define SDRC_RFR_CTRL_110MHz	(0x0002da01 | 1) /* Need to calc */
++#define SDRC_RFR_CTRL_BYPASS	(0x00005000 | 1) /* Need to calc */
++
++
++/*
++ * SMS register access
++ */
++
++
++#define OMAP242X_SMS_REGADDR(reg)	(void __iomem *)IO_ADDRESS(OMAP2420_SMS_BASE + reg)
++#define OMAP243X_SMS_REGADDR(reg)	(void __iomem *)IO_ADDRESS(OMAP243X_SMS_BASE + reg)
++#define OMAP343X_SMS_REGADDR(reg)	(void __iomem *)IO_ADDRESS(OMAP343X_SMS_BASE + reg)
++
++/* SMS register offsets - read/write with sms_{read,write}_reg() */
++
++#define SMS_SYSCONFIG		0x010
++/* REVISIT: fill in other SMS registers here */
++
++#endif
+diff --git a/include/asm-arm/arch-omap/usb.h b/include/asm-arm/arch-omap/usb.h
+index 99ae9ea..2147d18 100644
+--- a/include/asm-arm/arch-omap/usb.h
++++ b/include/asm-arm/arch-omap/usb.h
+@@ -132,14 +132,11 @@
+ #	define	CONF_USB_PWRDN_DP_R	(1 << 1)
+ 
+ /* OMAP2 */
+-#define	CONTROL_DEVCONF_REG		__REG32(L4_24XX_BASE + 0x0274)
+ #	define	USB_UNIDIR			0x0
+ #	define	USB_UNIDIR_TLL			0x1
+ #	define	USB_BIDIR			0x2
+ #	define	USB_BIDIR_TLL			0x3
+-#	define	USBT0WRMODEI(x)		((x) << 22)
+-#	define	USBT1WRMODEI(x)		((x) << 20)
+-#	define	USBT2WRMODEI(x)		((x) << 18)
++#	define	USBTXWRMODEI(port, x)	((x) << (22 - (port * 2)))
+ #	define	USBT2TLL5PI		(1 << 17)
+ #	define	USB0PUENACTLOI		(1 << 16)
+ #	define	USBSTANDBYCTRL		(1 << 15)
+diff --git a/include/asm-arm/arch-orion/debug-macro.S b/include/asm-arm/arch-orion/debug-macro.S
+deleted file mode 100644
+index 2746220..0000000
+--- a/include/asm-arm/arch-orion/debug-macro.S
++++ /dev/null
+@@ -1,22 +0,0 @@
+-/*
+- * linux/include/asm-arm/arch-orion/debug-macro.S
+- *
+- * Debugging macro include header
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+-*/
+-
+-#include <asm/arch/orion.h>
+-
+-	.macro  addruart,rx
+-	mrc	p15, 0, \rx, c1, c0
+-	tst	\rx, #1					@ MMU enabled?
+-	ldreq	\rx, =ORION_REGS_PHYS_BASE
+-	ldrne	\rx, =ORION_REGS_VIRT_BASE
+-	orr	\rx, \rx, #0x00012000
+-	.endm
+-
+-#define UART_SHIFT	2
+-#include <asm/hardware/debug-8250.S>
+diff --git a/include/asm-arm/arch-orion/dma.h b/include/asm-arm/arch-orion/dma.h
+deleted file mode 100644
+index 40a8c17..0000000
+--- a/include/asm-arm/arch-orion/dma.h
++++ /dev/null
+@@ -1 +0,0 @@
+-/* empty */
+diff --git a/include/asm-arm/arch-orion/entry-macro.S b/include/asm-arm/arch-orion/entry-macro.S
+deleted file mode 100644
+index cda096b..0000000
+--- a/include/asm-arm/arch-orion/entry-macro.S
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/entry-macro.S
+- *
+- * Low-level IRQ helper macros for Orion platforms
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2.  This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <asm/arch/orion.h>
+-
+-	.macro  disable_fiq
+-	.endm
+-
+-	.macro  arch_ret_to_user, tmp1, tmp2
+-	.endm
+-
+-	.macro  get_irqnr_preamble, base, tmp
+-	ldr	\base, =MAIN_IRQ_CAUSE
+-	.endm
+-
+-	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+-	ldr	\irqstat, [\base, #0]		@ main cause
+-	ldr	\tmp, [\base, #(MAIN_IRQ_MASK - MAIN_IRQ_CAUSE)] @ main mask
+-	mov	\irqnr, #0			@ default irqnr
+-	@ find cause bits that are unmasked
+-	ands	\irqstat, \irqstat, \tmp	@ clear Z flag if any
+-	clzne	\irqnr,	\irqstat		@ calc irqnr
+-	rsbne	\irqnr, \irqnr, #31
+-	.endm
+diff --git a/include/asm-arm/arch-orion/gpio.h b/include/asm-arm/arch-orion/gpio.h
+deleted file mode 100644
+index d66284f..0000000
+--- a/include/asm-arm/arch-orion/gpio.h
++++ /dev/null
+@@ -1,28 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/gpio.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.
+- */
+-
+-extern int gpio_request(unsigned pin, const char *label);
+-extern void gpio_free(unsigned pin);
+-extern int gpio_direction_input(unsigned pin);
+-extern int gpio_direction_output(unsigned pin, int value);
+-extern int gpio_get_value(unsigned pin);
+-extern void gpio_set_value(unsigned pin, int value);
+-extern void orion_gpio_set_blink(unsigned pin, int blink);
+-extern void gpio_display(void);		/* debug */
+-
+-static inline int gpio_to_irq(int pin)
+-{
+-	return pin + IRQ_ORION_GPIO_START;
+-}
+-
+-static inline int irq_to_gpio(int irq)
+-{
+-	return irq - IRQ_ORION_GPIO_START;
+-}
+-
+-#include <asm-generic/gpio.h>		/* cansleep wrappers */
+diff --git a/include/asm-arm/arch-orion/hardware.h b/include/asm-arm/arch-orion/hardware.h
+deleted file mode 100644
+index 65da374..0000000
+--- a/include/asm-arm/arch-orion/hardware.h
++++ /dev/null
+@@ -1,21 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/hardware.h
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#ifndef __ASM_ARCH_HARDWARE_H__
+-#define __ASM_ARCH_HARDWARE_H__
+-
+-#include "orion.h"
+-
+-#define pcibios_assign_all_busses()	1
+-
+-#define PCIBIOS_MIN_IO		0x00001000
+-#define PCIBIOS_MIN_MEM		0x01000000
+-#define PCIMEM_BASE		ORION_PCIE_MEM_PHYS_BASE
+-
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/io.h b/include/asm-arm/arch-orion/io.h
+deleted file mode 100644
+index e0b8c39..0000000
+--- a/include/asm-arm/arch-orion/io.h
++++ /dev/null
+@@ -1,27 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/io.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under  the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARM_ARCH_IO_H
+-#define __ASM_ARM_ARCH_IO_H
+-
+-#include "orion.h"
+-
+-#define IO_SPACE_LIMIT		0xffffffff
+-#define IO_SPACE_REMAP		ORION_PCI_SYS_IO_BASE
+-
+-static inline void __iomem *__io(unsigned long addr)
+-{
+-	return (void __iomem *)addr;
+-}
+-
+-#define __io(a)			__io(a)
+-#define __mem_pci(a)		(a)
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/irqs.h b/include/asm-arm/arch-orion/irqs.h
+deleted file mode 100644
+index eea65ca..0000000
+--- a/include/asm-arm/arch-orion/irqs.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/irqs.h
+- *
+- * IRQ definitions for Orion SoC
+- *
+- *  Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- *  This file is licensed under the terms of the GNU General Public
+- *  License version 2. This program is licensed "as is" without any
+- *  warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARCH_IRQS_H__
+-#define __ASM_ARCH_IRQS_H__
+-
+-#include "orion.h"	/* need GPIO_MAX */
+-
+-/*
+- * Orion Main Interrupt Controller
+- */
+-#define IRQ_ORION_BRIDGE	0
+-#define IRQ_ORION_DOORBELL_H2C	1
+-#define IRQ_ORION_DOORBELL_C2H	2
+-#define IRQ_ORION_UART0		3
+-#define IRQ_ORION_UART1		4
+-#define IRQ_ORION_I2C		5
+-#define IRQ_ORION_GPIO_0_7	6
+-#define IRQ_ORION_GPIO_8_15	7
+-#define IRQ_ORION_GPIO_16_23	8
+-#define IRQ_ORION_GPIO_24_31	9
+-#define IRQ_ORION_PCIE0_ERR	10
+-#define IRQ_ORION_PCIE0_INT	11
+-#define IRQ_ORION_USB1_CTRL	12
+-#define IRQ_ORION_DEV_BUS_ERR	14
+-#define IRQ_ORION_PCI_ERR	15
+-#define IRQ_ORION_USB_BR_ERR	16
+-#define IRQ_ORION_USB0_CTRL	17
+-#define IRQ_ORION_ETH_RX	18
+-#define IRQ_ORION_ETH_TX	19
+-#define IRQ_ORION_ETH_MISC	20
+-#define IRQ_ORION_ETH_SUM	21
+-#define IRQ_ORION_ETH_ERR	22
+-#define IRQ_ORION_IDMA_ERR	23
+-#define IRQ_ORION_IDMA_0	24
+-#define IRQ_ORION_IDMA_1	25
+-#define IRQ_ORION_IDMA_2	26
+-#define IRQ_ORION_IDMA_3	27
+-#define IRQ_ORION_CESA		28
+-#define IRQ_ORION_SATA		29
+-#define IRQ_ORION_XOR0		30
+-#define IRQ_ORION_XOR1		31
+-
+-/*
+- * Orion General Purpose Pins
+- */
+-#define IRQ_ORION_GPIO_START	32
+-#define NR_GPIO_IRQS		GPIO_MAX
+-
+-#define NR_IRQS			(IRQ_ORION_GPIO_START + NR_GPIO_IRQS)
+-
+-#endif /* __ASM_ARCH_IRQS_H__ */
+diff --git a/include/asm-arm/arch-orion/memory.h b/include/asm-arm/arch-orion/memory.h
+deleted file mode 100644
+index d954dba..0000000
+--- a/include/asm-arm/arch-orion/memory.h
++++ /dev/null
+@@ -1,15 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/memory.h
+- *
+- * Marvell Orion memory definitions
+- */
+-
+-#ifndef __ASM_ARCH_MMU_H
+-#define __ASM_ARCH_MMU_H
+-
+-#define PHYS_OFFSET	UL(0x00000000)
+-
+-#define __virt_to_bus(x)	__virt_to_phys(x)
+-#define __bus_to_virt(x)	__phys_to_virt(x)
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/orion.h b/include/asm-arm/arch-orion/orion.h
+deleted file mode 100644
+index 673a418..0000000
+--- a/include/asm-arm/arch-orion/orion.h
++++ /dev/null
+@@ -1,165 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/orion.h
+- *
+- * Generic definitions of Orion SoC flavors:
+- *  Orion-1, Orion-NAS, Orion-VoIP, and Orion-2.
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARCH_ORION_H__
+-#define __ASM_ARCH_ORION_H__
+-
+-/*****************************************************************************
+- * Orion Address Map
+- *
+- * virt		phys		size
+- * fdd00000	f1000000	1M	on-chip peripheral registers
+- * fde00000	f2000000	1M	PCIe I/O space
+- * fdf00000	f2100000	1M	PCI I/O space
+- * fe000000	f0000000	16M	PCIe WA space (Orion-NAS only)
+- ****************************************************************************/
+-#define ORION_REGS_PHYS_BASE	0xf1000000
+-#define ORION_REGS_VIRT_BASE	0xfdd00000
+-#define ORION_REGS_SIZE		SZ_1M
+-
+-#define ORION_PCIE_IO_PHYS_BASE	0xf2000000
+-#define ORION_PCIE_IO_VIRT_BASE	0xfde00000
+-#define ORION_PCIE_IO_BUS_BASE	0x00000000
+-#define ORION_PCIE_IO_SIZE	SZ_1M
+-
+-#define ORION_PCI_IO_PHYS_BASE	0xf2100000
+-#define ORION_PCI_IO_VIRT_BASE	0xfdf00000
+-#define ORION_PCI_IO_BUS_BASE	0x00100000
+-#define ORION_PCI_IO_SIZE	SZ_1M
+-
+-/* Relevant only for Orion-NAS */
+-#define ORION_PCIE_WA_PHYS_BASE	0xf0000000
+-#define ORION_PCIE_WA_VIRT_BASE	0xfe000000
+-#define ORION_PCIE_WA_SIZE	SZ_16M
+-
+-#define ORION_PCIE_MEM_PHYS_BASE	0xe0000000
+-#define ORION_PCIE_MEM_SIZE		SZ_128M
+-
+-#define ORION_PCI_MEM_PHYS_BASE		0xe8000000
+-#define ORION_PCI_MEM_SIZE		SZ_128M
+-
+-/*******************************************************************************
+- * Supported Devices & Revisions
+- ******************************************************************************/
+-/* Orion-1 (88F5181) */
+-#define MV88F5181_DEV_ID	0x5181
+-#define MV88F5181_REV_B1	3
+-/* Orion-NAS (88F5182) */
+-#define MV88F5182_DEV_ID	0x5182
+-#define MV88F5182_REV_A2	2
+-/* Orion-2 (88F5281) */
+-#define MV88F5281_DEV_ID	0x5281
+-#define MV88F5281_REV_D1	5
+-#define MV88F5281_REV_D2	6
+-
+-/*******************************************************************************
+- * Orion Registers Map
+- ******************************************************************************/
+-#define ORION_DDR_VIRT_BASE		(ORION_REGS_VIRT_BASE | 0x00000)
+-#define ORION_DDR_REG(x)		(ORION_DDR_VIRT_BASE | (x))
+-
+-#define ORION_DEV_BUS_PHYS_BASE		(ORION_REGS_PHYS_BASE | 0x10000)
+-#define ORION_DEV_BUS_VIRT_BASE		(ORION_REGS_VIRT_BASE | 0x10000)
+-#define ORION_DEV_BUS_REG(x)		(ORION_DEV_BUS_VIRT_BASE | (x))
+-#define  I2C_PHYS_BASE			(ORION_DEV_BUS_PHYS_BASE | 0x1000)
+-#define  UART0_PHYS_BASE		(ORION_DEV_BUS_PHYS_BASE | 0x2000)
+-#define  UART0_VIRT_BASE		(ORION_DEV_BUS_VIRT_BASE | 0x2000)
+-#define  UART1_PHYS_BASE		(ORION_DEV_BUS_PHYS_BASE | 0x2100)
+-#define  UART1_VIRT_BASE		(ORION_DEV_BUS_VIRT_BASE | 0x2100)
+-
+-#define ORION_BRIDGE_VIRT_BASE		(ORION_REGS_VIRT_BASE | 0x20000)
+-#define ORION_BRIDGE_REG(x)		(ORION_BRIDGE_VIRT_BASE | (x))
+-
+-#define ORION_PCI_VIRT_BASE		(ORION_REGS_VIRT_BASE | 0x30000)
+-#define ORION_PCI_REG(x)		(ORION_PCI_VIRT_BASE | (x))
+-
+-#define ORION_PCIE_VIRT_BASE		(ORION_REGS_VIRT_BASE | 0x40000)
+-#define ORION_PCIE_REG(x)		(ORION_PCIE_VIRT_BASE | (x))
+-
+-#define ORION_USB0_PHYS_BASE		(ORION_REGS_PHYS_BASE | 0x50000)
+-#define ORION_USB0_VIRT_BASE		(ORION_REGS_VIRT_BASE | 0x50000)
+-#define ORION_USB0_REG(x)		(ORION_USB0_VIRT_BASE | (x))
+-
+-#define ORION_ETH_PHYS_BASE		(ORION_REGS_PHYS_BASE | 0x70000)
+-#define ORION_ETH_VIRT_BASE		(ORION_REGS_VIRT_BASE | 0x70000)
+-#define ORION_ETH_REG(x)		(ORION_ETH_VIRT_BASE | (x))
+-
+-#define ORION_SATA_PHYS_BASE		(ORION_REGS_PHYS_BASE | 0x80000)
+-#define ORION_SATA_VIRT_BASE		(ORION_REGS_VIRT_BASE | 0x80000)
+-#define ORION_SATA_REG(x)		(ORION_SATA_VIRT_BASE | (x))
+-
+-#define ORION_USB1_PHYS_BASE		(ORION_REGS_PHYS_BASE | 0xa0000)
+-#define ORION_USB1_VIRT_BASE		(ORION_REGS_VIRT_BASE | 0xa0000)
+-#define ORION_USB1_REG(x)		(ORION_USB1_VIRT_BASE | (x))
+-
+-/*******************************************************************************
+- * Device Bus Registers
+- ******************************************************************************/
+-#define MPP_0_7_CTRL		ORION_DEV_BUS_REG(0x000)
+-#define MPP_8_15_CTRL		ORION_DEV_BUS_REG(0x004)
+-#define MPP_16_19_CTRL		ORION_DEV_BUS_REG(0x050)
+-#define MPP_DEV_CTRL		ORION_DEV_BUS_REG(0x008)
+-#define MPP_RESET_SAMPLE	ORION_DEV_BUS_REG(0x010)
+-#define GPIO_OUT		ORION_DEV_BUS_REG(0x100)
+-#define GPIO_IO_CONF		ORION_DEV_BUS_REG(0x104)
+-#define GPIO_BLINK_EN		ORION_DEV_BUS_REG(0x108)
+-#define GPIO_IN_POL		ORION_DEV_BUS_REG(0x10c)
+-#define GPIO_DATA_IN		ORION_DEV_BUS_REG(0x110)
+-#define GPIO_EDGE_CAUSE		ORION_DEV_BUS_REG(0x114)
+-#define GPIO_EDGE_MASK		ORION_DEV_BUS_REG(0x118)
+-#define GPIO_LEVEL_MASK		ORION_DEV_BUS_REG(0x11c)
+-#define DEV_BANK_0_PARAM	ORION_DEV_BUS_REG(0x45c)
+-#define DEV_BANK_1_PARAM	ORION_DEV_BUS_REG(0x460)
+-#define DEV_BANK_2_PARAM	ORION_DEV_BUS_REG(0x464)
+-#define DEV_BANK_BOOT_PARAM	ORION_DEV_BUS_REG(0x46c)
+-#define DEV_BUS_CTRL		ORION_DEV_BUS_REG(0x4c0)
+-#define DEV_BUS_INT_CAUSE	ORION_DEV_BUS_REG(0x4d0)
+-#define DEV_BUS_INT_MASK	ORION_DEV_BUS_REG(0x4d4)
+-#define GPIO_MAX		32
+-
+-/***************************************************************************
+- * Orion CPU Bridge Registers
+- **************************************************************************/
+-#define CPU_CONF		ORION_BRIDGE_REG(0x100)
+-#define CPU_CTRL		ORION_BRIDGE_REG(0x104)
+-#define CPU_RESET_MASK		ORION_BRIDGE_REG(0x108)
+-#define CPU_SOFT_RESET		ORION_BRIDGE_REG(0x10c)
+-#define POWER_MNG_CTRL_REG	ORION_BRIDGE_REG(0x11C)
+-#define BRIDGE_CAUSE		ORION_BRIDGE_REG(0x110)
+-#define BRIDGE_MASK		ORION_BRIDGE_REG(0x114)
+-#define MAIN_IRQ_CAUSE		ORION_BRIDGE_REG(0x200)
+-#define MAIN_IRQ_MASK		ORION_BRIDGE_REG(0x204)
+-#define TIMER_CTRL		ORION_BRIDGE_REG(0x300)
+-#define TIMER_VAL(x)		ORION_BRIDGE_REG(0x314 + ((x) * 8))
+-#define TIMER_VAL_RELOAD(x)	ORION_BRIDGE_REG(0x310 + ((x) * 8))
+-
+-#ifndef __ASSEMBLY__
+-
+-/*******************************************************************************
+- * Helpers to access Orion registers
+- ******************************************************************************/
+-#include <asm/types.h>
+-#include <asm/io.h>
+-
+-#define orion_read(r)		__raw_readl(r)
+-#define orion_write(r, val)	__raw_writel(val, r)
+-
+-/*
+- * These are not preempt safe. Locks, if needed, must be taken care by caller.
+- */
+-#define orion_setbits(r, mask)	orion_write((r), orion_read(r) | (mask))
+-#define orion_clrbits(r, mask)	orion_write((r), orion_read(r) & ~(mask))
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif /* __ASM_ARCH_ORION_H__ */
+diff --git a/include/asm-arm/arch-orion/platform.h b/include/asm-arm/arch-orion/platform.h
+deleted file mode 100644
+index 143c38e..0000000
+--- a/include/asm-arm/arch-orion/platform.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/*
+- * asm-arm/arch-orion/platform.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARCH_PLATFORM_H__
+-#define __ASM_ARCH_PLATFORM_H__
+-
+-/*
+- * Device bus NAND private data
+- */
+-struct orion_nand_data {
+-	struct mtd_partition *parts;
+-	u32 nr_parts;
+-	u8 ale;		/* address line number connected to ALE */
+-	u8 cle;		/* address line number connected to CLE */
+-	u8 width;	/* buswidth */
+-};
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/system.h b/include/asm-arm/arch-orion/system.h
+deleted file mode 100644
+index 17704c6..0000000
+--- a/include/asm-arm/arch-orion/system.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/system.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under  the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARCH_SYSTEM_H
+-#define __ASM_ARCH_SYSTEM_H
+-
+-#include <asm/arch/hardware.h>
+-#include <asm/arch/orion.h>
+-
+-static inline void arch_idle(void)
+-{
+-	cpu_do_idle();
+-}
+-
+-static inline void arch_reset(char mode)
+-{
+-	/*
+-	 * Enable and issue soft reset
+-	 */
+-	orion_setbits(CPU_RESET_MASK, (1 << 2));
+-	orion_setbits(CPU_SOFT_RESET, 1);
+-}
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/timex.h b/include/asm-arm/arch-orion/timex.h
+deleted file mode 100644
+index 26c2c91..0000000
+--- a/include/asm-arm/arch-orion/timex.h
++++ /dev/null
+@@ -1,12 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/timex.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under  the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#define ORION_TCLK		166666667
+-#define CLOCK_TICK_RATE		ORION_TCLK
+diff --git a/include/asm-arm/arch-orion/uncompress.h b/include/asm-arm/arch-orion/uncompress.h
+deleted file mode 100644
+index 59f4403..0000000
+--- a/include/asm-arm/arch-orion/uncompress.h
++++ /dev/null
+@@ -1,34 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/uncompress.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.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 <asm/arch/orion.h>
+-
+-#define MV_UART_THR	((volatile unsigned char *)(UART0_PHYS_BASE + 0x0))
+-#define MV_UART_LSR 	((volatile unsigned char *)(UART0_PHYS_BASE + 0x14))
+-
+-#define LSR_THRE	0x20
+-
+-static void putc(const char c)
+-{
+-	int j = 0x1000;
+-	while (--j && !(*MV_UART_LSR & LSR_THRE))
+-		barrier();
+-	*MV_UART_THR = c;
+-}
+-
+-static void flush(void)
+-{
+-}
+-
+-/*
+- * nothing to do
+- */
+-#define arch_decomp_setup()
+-#define arch_decomp_wdog()
+diff --git a/include/asm-arm/arch-orion/vmalloc.h b/include/asm-arm/arch-orion/vmalloc.h
+deleted file mode 100644
+index 9d58027..0000000
+--- a/include/asm-arm/arch-orion/vmalloc.h
++++ /dev/null
+@@ -1,5 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/vmalloc.h
+- */
+-
+-#define VMALLOC_END       0xfd800000
+diff --git a/include/asm-arm/arch-orion5x/debug-macro.S b/include/asm-arm/arch-orion5x/debug-macro.S
+new file mode 100644
+index 0000000..4f98f3b
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/debug-macro.S
+@@ -0,0 +1,22 @@
++/*
++ * include/asm-arm/arch-orion5x/debug-macro.S
++ *
++ * Debugging macro include header
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++*/
++
++#include <asm/arch/orion5x.h>
++
++	.macro  addruart,rx
++	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
++	.endm
++
++#define UART_SHIFT	2
++#include <asm/hardware/debug-8250.S>
+diff --git a/include/asm-arm/arch-orion5x/dma.h b/include/asm-arm/arch-orion5x/dma.h
+new file mode 100644
+index 0000000..40a8c17
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/dma.h
+@@ -0,0 +1 @@
++/* empty */
+diff --git a/include/asm-arm/arch-orion5x/entry-macro.S b/include/asm-arm/arch-orion5x/entry-macro.S
+new file mode 100644
+index 0000000..d8ef54c
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/entry-macro.S
+@@ -0,0 +1,31 @@
++/*
++ * include/asm-arm/arch-orion5x/entry-macro.S
++ *
++ * Low-level IRQ helper macros for Orion platforms
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <asm/arch/orion5x.h>
++
++	.macro  disable_fiq
++	.endm
++
++	.macro  arch_ret_to_user, tmp1, tmp2
++	.endm
++
++	.macro  get_irqnr_preamble, base, tmp
++	ldr	\base, =MAIN_IRQ_CAUSE
++	.endm
++
++	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
++	ldr	\irqstat, [\base, #0]		@ main cause
++	ldr	\tmp, [\base, #(MAIN_IRQ_MASK - MAIN_IRQ_CAUSE)] @ main mask
++	mov	\irqnr, #0			@ default irqnr
++	@ find cause bits that are unmasked
++	ands	\irqstat, \irqstat, \tmp	@ clear Z flag if any
++	clzne	\irqnr,	\irqstat		@ calc irqnr
++	rsbne	\irqnr, \irqnr, #31
++	.endm
+diff --git a/include/asm-arm/arch-orion5x/gpio.h b/include/asm-arm/arch-orion5x/gpio.h
+new file mode 100644
+index 0000000..c85e498
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/gpio.h
+@@ -0,0 +1,28 @@
++/*
++ * include/asm-arm/arch-orion5x/gpio.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.
++ */
++
++extern int gpio_request(unsigned pin, const char *label);
++extern void gpio_free(unsigned pin);
++extern int gpio_direction_input(unsigned pin);
++extern int gpio_direction_output(unsigned pin, int value);
++extern int gpio_get_value(unsigned pin);
++extern void gpio_set_value(unsigned pin, int value);
++extern void orion5x_gpio_set_blink(unsigned pin, int blink);
++extern void gpio_display(void);		/* debug */
++
++static inline int gpio_to_irq(int pin)
++{
++	return pin + IRQ_ORION5X_GPIO_START;
++}
++
++static inline int irq_to_gpio(int irq)
++{
++	return irq - IRQ_ORION5X_GPIO_START;
++}
++
++#include <asm-generic/gpio.h>		/* cansleep wrappers */
+diff --git a/include/asm-arm/arch-orion5x/hardware.h b/include/asm-arm/arch-orion5x/hardware.h
+new file mode 100644
+index 0000000..5d2d8e0
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/hardware.h
+@@ -0,0 +1,21 @@
++/*
++ * include/asm-arm/arch-orion5x/hardware.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __ASM_ARCH_HARDWARE_H
++#define __ASM_ARCH_HARDWARE_H
++
++#include "orion5x.h"
++
++#define pcibios_assign_all_busses()	1
++
++#define PCIBIOS_MIN_IO		0x00001000
++#define PCIBIOS_MIN_MEM		0x01000000
++#define PCIMEM_BASE		ORION5X_PCIE_MEM_PHYS_BASE
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/io.h b/include/asm-arm/arch-orion5x/io.h
+new file mode 100644
+index 0000000..5148ab7
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/io.h
+@@ -0,0 +1,68 @@
++/*
++ * include/asm-arm/arch-orion5x/io.h
++ *
++ * Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_ARCH_IO_H
++#define __ASM_ARCH_IO_H
++
++#include "orion5x.h"
++
++#define IO_SPACE_LIMIT		0xffffffff
++#define IO_SPACE_REMAP		ORION5X_PCI_SYS_IO_BASE
++
++static inline void __iomem *
++__arch_ioremap(unsigned long paddr, size_t size, unsigned int mtype)
++{
++	void __iomem *retval;
++
++	if (mtype == MT_DEVICE && size && paddr >= ORION5X_REGS_PHYS_BASE &&
++	    paddr + size <= ORION5X_REGS_PHYS_BASE + ORION5X_REGS_SIZE) {
++		retval = (void __iomem *)ORION5X_REGS_VIRT_BASE +
++				(paddr - ORION5X_REGS_PHYS_BASE);
++	} else {
++		retval = __arm_ioremap(paddr, size, mtype);
++	}
++
++	return retval;
++}
++
++static inline void
++__arch_iounmap(void __iomem *addr)
++{
++	if (addr < (void __iomem *)ORION5X_REGS_VIRT_BASE ||
++	    addr >= (void __iomem *)(ORION5X_REGS_VIRT_BASE + ORION5X_REGS_SIZE))
++		__iounmap(addr);
++}
++
++static inline void __iomem *__io(unsigned long addr)
++{
++	return (void __iomem *)addr;
++}
++
++#define __arch_ioremap(p, s, m)	__arch_ioremap(p, s, m)
++#define __arch_iounmap(a)	__arch_iounmap(a)
++#define __io(a)			__io(a)
++#define __mem_pci(a)		(a)
++
++
++/*****************************************************************************
++ * Helpers to access Orion registers
++ ****************************************************************************/
++#define orion5x_read(r)		__raw_readl(r)
++#define orion5x_write(r, val)	__raw_writel(val, r)
++
++/*
++ * These are not preempt-safe.  Locks, if needed, must be taken
++ * care of by the caller.
++ */
++#define orion5x_setbits(r, mask)	orion5x_write((r), orion5x_read(r) | (mask))
++#define orion5x_clrbits(r, mask)	orion5x_write((r), orion5x_read(r) & ~(mask))
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/irqs.h b/include/asm-arm/arch-orion5x/irqs.h
+new file mode 100644
+index 0000000..abdd61a
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/irqs.h
+@@ -0,0 +1,62 @@
++/*
++ * include/asm-arm/arch-orion5x/irqs.h
++ *
++ * IRQ definitions for Orion SoC
++ *
++ *  Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ *  This file is licensed under the terms of the GNU General Public
++ *  License version 2. This program is licensed "as is" without any
++ *  warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_ARCH_IRQS_H
++#define __ASM_ARCH_IRQS_H
++
++#include "orion5x.h"	/* need GPIO_MAX */
++
++/*
++ * Orion Main Interrupt Controller
++ */
++#define IRQ_ORION5X_BRIDGE		0
++#define IRQ_ORION5X_DOORBELL_H2C	1
++#define IRQ_ORION5X_DOORBELL_C2H	2
++#define IRQ_ORION5X_UART0		3
++#define IRQ_ORION5X_UART1		4
++#define IRQ_ORION5X_I2C			5
++#define IRQ_ORION5X_GPIO_0_7		6
++#define IRQ_ORION5X_GPIO_8_15		7
++#define IRQ_ORION5X_GPIO_16_23		8
++#define IRQ_ORION5X_GPIO_24_31		9
++#define IRQ_ORION5X_PCIE0_ERR		10
++#define IRQ_ORION5X_PCIE0_INT		11
++#define IRQ_ORION5X_USB1_CTRL		12
++#define IRQ_ORION5X_DEV_BUS_ERR		14
++#define IRQ_ORION5X_PCI_ERR		15
++#define IRQ_ORION5X_USB_BR_ERR		16
++#define IRQ_ORION5X_USB0_CTRL		17
++#define IRQ_ORION5X_ETH_RX		18
++#define IRQ_ORION5X_ETH_TX		19
++#define IRQ_ORION5X_ETH_MISC		20
++#define IRQ_ORION5X_ETH_SUM		21
++#define IRQ_ORION5X_ETH_ERR		22
++#define IRQ_ORION5X_IDMA_ERR		23
++#define IRQ_ORION5X_IDMA_0		24
++#define IRQ_ORION5X_IDMA_1		25
++#define IRQ_ORION5X_IDMA_2		26
++#define IRQ_ORION5X_IDMA_3		27
++#define IRQ_ORION5X_CESA		28
++#define IRQ_ORION5X_SATA		29
++#define IRQ_ORION5X_XOR0		30
++#define IRQ_ORION5X_XOR1		31
++
++/*
++ * Orion General Purpose Pins
++ */
++#define IRQ_ORION5X_GPIO_START	32
++#define NR_GPIO_IRQS		GPIO_MAX
++
++#define NR_IRQS			(IRQ_ORION5X_GPIO_START + NR_GPIO_IRQS)
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/memory.h b/include/asm-arm/arch-orion5x/memory.h
+new file mode 100644
+index 0000000..80053a7
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/memory.h
+@@ -0,0 +1,16 @@
++/*
++ * include/asm-arm/arch-orion5x/memory.h
++ *
++ * Marvell Orion memory definitions
++ */
++
++#ifndef __ASM_ARCH_MEMORY_H
++#define __ASM_ARCH_MEMORY_H
++
++#define PHYS_OFFSET	UL(0x00000000)
++
++#define __virt_to_bus(x)	__virt_to_phys(x)
++#define __bus_to_virt(x)	__phys_to_virt(x)
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/orion5x.h b/include/asm-arm/arch-orion5x/orion5x.h
+new file mode 100644
+index 0000000..206ddd7
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/orion5x.h
+@@ -0,0 +1,159 @@
++/*
++ * include/asm-arm/arch-orion5x/orion5x.h
++ *
++ * Generic definitions of Orion SoC flavors:
++ *  Orion-1, Orion-NAS, Orion-VoIP, and Orion-2.
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_ARCH_ORION5X_H
++#define __ASM_ARCH_ORION5X_H
++
++/*****************************************************************************
++ * Orion Address Maps
++ *
++ * phys
++ * e0000000	PCIe MEM space
++ * e8000000	PCI MEM space
++ * f0000000	PCIe WA space (Orion-1/Orion-NAS only)
++ * f1000000	on-chip peripheral registers
++ * f2000000	PCIe I/O space
++ * f2100000	PCI I/O space
++ * f4000000	device bus mappings (boot)
++ * fa000000	device bus mappings (cs0)
++ * fa800000	device bus mappings (cs2)
++ * fc000000	device bus mappings (cs0/cs1)
++ *
++ * virt		phys		size
++ * fdd00000	f1000000	1M	on-chip peripheral registers
++ * fde00000	f2000000	1M	PCIe I/O space
++ * fdf00000	f2100000	1M	PCI I/O space
++ * fe000000	f0000000	16M	PCIe WA space (Orion-1/Orion-NAS only)
++ ****************************************************************************/
++#define ORION5X_REGS_PHYS_BASE		0xf1000000
++#define ORION5X_REGS_VIRT_BASE		0xfdd00000
++#define ORION5X_REGS_SIZE		SZ_1M
++
++#define ORION5X_PCIE_IO_PHYS_BASE	0xf2000000
++#define ORION5X_PCIE_IO_VIRT_BASE	0xfde00000
++#define ORION5X_PCIE_IO_BUS_BASE	0x00000000
++#define ORION5X_PCIE_IO_SIZE		SZ_1M
++
++#define ORION5X_PCI_IO_PHYS_BASE	0xf2100000
++#define ORION5X_PCI_IO_VIRT_BASE	0xfdf00000
++#define ORION5X_PCI_IO_BUS_BASE		0x00100000
++#define ORION5X_PCI_IO_SIZE		SZ_1M
++
++/* Relevant only for Orion-1/Orion-NAS */
++#define ORION5X_PCIE_WA_PHYS_BASE	0xf0000000
++#define ORION5X_PCIE_WA_VIRT_BASE	0xfe000000
++#define ORION5X_PCIE_WA_SIZE		SZ_16M
++
++#define ORION5X_PCIE_MEM_PHYS_BASE	0xe0000000
++#define ORION5X_PCIE_MEM_SIZE		SZ_128M
++
++#define ORION5X_PCI_MEM_PHYS_BASE	0xe8000000
++#define ORION5X_PCI_MEM_SIZE		SZ_128M
++
++/*******************************************************************************
++ * Supported Devices & Revisions
++ ******************************************************************************/
++/* Orion-1 (88F5181) */
++#define MV88F5181_DEV_ID	0x5181
++#define MV88F5181_REV_B1	3
++/* Orion-NAS (88F5182) */
++#define MV88F5182_DEV_ID	0x5182
++#define MV88F5182_REV_A2	2
++/* Orion-2 (88F5281) */
++#define MV88F5281_DEV_ID	0x5281
++#define MV88F5281_REV_D1	5
++#define MV88F5281_REV_D2	6
++
++/*******************************************************************************
++ * Orion Registers Map
++ ******************************************************************************/
++#define ORION5X_DDR_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x00000)
++#define ORION5X_DDR_REG(x)		(ORION5X_DDR_VIRT_BASE | (x))
++
++#define ORION5X_DEV_BUS_PHYS_BASE	(ORION5X_REGS_PHYS_BASE | 0x10000)
++#define ORION5X_DEV_BUS_VIRT_BASE	(ORION5X_REGS_VIRT_BASE | 0x10000)
++#define ORION5X_DEV_BUS_REG(x)		(ORION5X_DEV_BUS_VIRT_BASE | (x))
++#define  I2C_PHYS_BASE			(ORION5X_DEV_BUS_PHYS_BASE | 0x1000)
++#define  UART0_PHYS_BASE		(ORION5X_DEV_BUS_PHYS_BASE | 0x2000)
++#define  UART0_VIRT_BASE		(ORION5X_DEV_BUS_VIRT_BASE | 0x2000)
++#define  UART1_PHYS_BASE		(ORION5X_DEV_BUS_PHYS_BASE | 0x2100)
++#define  UART1_VIRT_BASE		(ORION5X_DEV_BUS_VIRT_BASE | 0x2100)
++
++#define ORION5X_BRIDGE_VIRT_BASE	(ORION5X_REGS_VIRT_BASE | 0x20000)
++#define ORION5X_BRIDGE_REG(x)		(ORION5X_BRIDGE_VIRT_BASE | (x))
++#define  TIMER_VIRT_BASE		(ORION5X_BRIDGE_VIRT_BASE | 0x300)
++
++#define ORION5X_PCI_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x30000)
++#define ORION5X_PCI_REG(x)		(ORION5X_PCI_VIRT_BASE | (x))
++
++#define ORION5X_PCIE_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x40000)
++#define ORION5X_PCIE_REG(x)		(ORION5X_PCIE_VIRT_BASE | (x))
++
++#define ORION5X_USB0_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0x50000)
++#define ORION5X_USB0_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x50000)
++#define ORION5X_USB0_REG(x)		(ORION5X_USB0_VIRT_BASE | (x))
++
++#define ORION5X_ETH_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0x70000)
++#define ORION5X_ETH_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x70000)
++#define ORION5X_ETH_REG(x)		(ORION5X_ETH_VIRT_BASE | (x))
++
++#define ORION5X_SATA_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0x80000)
++#define ORION5X_SATA_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x80000)
++#define ORION5X_SATA_REG(x)		(ORION5X_SATA_VIRT_BASE | (x))
++
++#define ORION5X_USB1_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0xa0000)
++#define ORION5X_USB1_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0xa0000)
++#define ORION5X_USB1_REG(x)		(ORION5X_USB1_VIRT_BASE | (x))
++
++/*******************************************************************************
++ * Device Bus Registers
++ ******************************************************************************/
++#define MPP_0_7_CTRL		ORION5X_DEV_BUS_REG(0x000)
++#define MPP_8_15_CTRL		ORION5X_DEV_BUS_REG(0x004)
++#define MPP_16_19_CTRL		ORION5X_DEV_BUS_REG(0x050)
++#define MPP_DEV_CTRL		ORION5X_DEV_BUS_REG(0x008)
++#define MPP_RESET_SAMPLE	ORION5X_DEV_BUS_REG(0x010)
++#define GPIO_OUT		ORION5X_DEV_BUS_REG(0x100)
++#define GPIO_IO_CONF		ORION5X_DEV_BUS_REG(0x104)
++#define GPIO_BLINK_EN		ORION5X_DEV_BUS_REG(0x108)
++#define GPIO_IN_POL		ORION5X_DEV_BUS_REG(0x10c)
++#define GPIO_DATA_IN		ORION5X_DEV_BUS_REG(0x110)
++#define GPIO_EDGE_CAUSE		ORION5X_DEV_BUS_REG(0x114)
++#define GPIO_EDGE_MASK		ORION5X_DEV_BUS_REG(0x118)
++#define GPIO_LEVEL_MASK		ORION5X_DEV_BUS_REG(0x11c)
++#define DEV_BANK_0_PARAM	ORION5X_DEV_BUS_REG(0x45c)
++#define DEV_BANK_1_PARAM	ORION5X_DEV_BUS_REG(0x460)
++#define DEV_BANK_2_PARAM	ORION5X_DEV_BUS_REG(0x464)
++#define DEV_BANK_BOOT_PARAM	ORION5X_DEV_BUS_REG(0x46c)
++#define DEV_BUS_CTRL		ORION5X_DEV_BUS_REG(0x4c0)
++#define DEV_BUS_INT_CAUSE	ORION5X_DEV_BUS_REG(0x4d0)
++#define DEV_BUS_INT_MASK	ORION5X_DEV_BUS_REG(0x4d4)
++#define GPIO_MAX		32
++
++/***************************************************************************
++ * Orion CPU Bridge Registers
++ **************************************************************************/
++#define CPU_CONF		ORION5X_BRIDGE_REG(0x100)
++#define CPU_CTRL		ORION5X_BRIDGE_REG(0x104)
++#define CPU_RESET_MASK		ORION5X_BRIDGE_REG(0x108)
++#define CPU_SOFT_RESET		ORION5X_BRIDGE_REG(0x10c)
++#define POWER_MNG_CTRL_REG	ORION5X_BRIDGE_REG(0x11C)
++#define BRIDGE_CAUSE		ORION5X_BRIDGE_REG(0x110)
++#define BRIDGE_MASK		ORION5X_BRIDGE_REG(0x114)
++#define  BRIDGE_INT_TIMER0	0x0002
++#define  BRIDGE_INT_TIMER1	0x0004
++#define MAIN_IRQ_CAUSE		ORION5X_BRIDGE_REG(0x200)
++#define MAIN_IRQ_MASK		ORION5X_BRIDGE_REG(0x204)
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/system.h b/include/asm-arm/arch-orion5x/system.h
+new file mode 100644
+index 0000000..3f1d1e2
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/system.h
+@@ -0,0 +1,32 @@
++/*
++ * include/asm-arm/arch-orion5x/system.h
++ *
++ * Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_ARCH_SYSTEM_H
++#define __ASM_ARCH_SYSTEM_H
++
++#include <asm/arch/hardware.h>
++#include <asm/arch/orion5x.h>
++
++static inline void arch_idle(void)
++{
++	cpu_do_idle();
++}
++
++static inline void arch_reset(char mode)
++{
++	/*
++	 * Enable and issue soft reset
++	 */
++	orion5x_setbits(CPU_RESET_MASK, (1 << 2));
++	orion5x_setbits(CPU_SOFT_RESET, 1);
++}
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/timex.h b/include/asm-arm/arch-orion5x/timex.h
+new file mode 100644
+index 0000000..31c568e
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/timex.h
+@@ -0,0 +1,13 @@
++/*
++ * include/asm-arm/arch-orion5x/timex.h
++ *
++ * Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#define CLOCK_TICK_RATE		(100 * HZ)
++
++#define ORION5X_TCLK		166666667
+diff --git a/include/asm-arm/arch-orion5x/uncompress.h b/include/asm-arm/arch-orion5x/uncompress.h
+new file mode 100644
+index 0000000..5c13d4f
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/uncompress.h
+@@ -0,0 +1,34 @@
++/*
++ * include/asm-arm/arch-orion5x/uncompress.h
++ *
++ * Tzachi Perelstein <tzachi at marvell.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 <asm/arch/orion5x.h>
++
++#define MV_UART_THR	((volatile unsigned char *)(UART0_PHYS_BASE + 0x0))
++#define MV_UART_LSR 	((volatile unsigned char *)(UART0_PHYS_BASE + 0x14))
++
++#define LSR_THRE	0x20
++
++static void putc(const char c)
++{
++	int j = 0x1000;
++	while (--j && !(*MV_UART_LSR & LSR_THRE))
++		barrier();
++	*MV_UART_THR = c;
++}
++
++static void flush(void)
++{
++}
++
++/*
++ * nothing to do
++ */
++#define arch_decomp_setup()
++#define arch_decomp_wdog()
+diff --git a/include/asm-arm/arch-orion5x/vmalloc.h b/include/asm-arm/arch-orion5x/vmalloc.h
+new file mode 100644
+index 0000000..2b3061e
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/vmalloc.h
+@@ -0,0 +1,5 @@
++/*
++ * include/asm-arm/arch-orion5x/vmalloc.h
++ */
++
++#define VMALLOC_END       0xfd800000
+diff --git a/include/asm-arm/arch-pxa/camera.h b/include/asm-arm/arch-pxa/camera.h
+new file mode 100644
+index 0000000..39516ce
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/camera.h
+@@ -0,0 +1,48 @@
++/*
++    camera.h - PXA camera driver header file
++
++    Copyright (C) 2003, Intel Corporation
++    Copyright (C) 2008, Guennadi Liakhovetski <kernel at 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++*/
++
++#ifndef __ASM_ARCH_CAMERA_H_
++#define __ASM_ARCH_CAMERA_H_
++
++#define PXA_CAMERA_MASTER	1
++#define PXA_CAMERA_DATAWIDTH_4	2
++#define PXA_CAMERA_DATAWIDTH_5	4
++#define PXA_CAMERA_DATAWIDTH_8	8
++#define PXA_CAMERA_DATAWIDTH_9	0x10
++#define PXA_CAMERA_DATAWIDTH_10	0x20
++#define PXA_CAMERA_PCLK_EN	0x40
++#define PXA_CAMERA_MCLK_EN	0x80
++#define PXA_CAMERA_PCP		0x100
++#define PXA_CAMERA_HSP		0x200
++#define PXA_CAMERA_VSP		0x400
++
++struct pxacamera_platform_data {
++	int (*init)(struct device *);
++	int (*power)(struct device *, int);
++	int (*reset)(struct device *, int);
++
++	unsigned long flags;
++	unsigned long mclk_10khz;
++};
++
++extern void pxa_set_camera_info(struct pxacamera_platform_data *);
++
++#endif /* __ASM_ARCH_CAMERA_H_ */
+diff --git a/include/asm-arm/arch-pxa/gumstix.h b/include/asm-arm/arch-pxa/gumstix.h
+new file mode 100644
+index 0000000..6fa85c4
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/gumstix.h
+@@ -0,0 +1,96 @@
++/*
++ *  linux/include/asm-arm/arch-pxa/gumstix.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.
++ */
++
++
++/* BTRESET - Reset line to Bluetooth module, active low signal. */
++#define GPIO_GUMSTIX_BTRESET          7
++#define GPIO_GUMSTIX_BTRESET_MD		(GPIO_GUMSTIX_BTRESET | GPIO_OUT)
++
++
++/*
++GPIOn - Input from MAX823 (or equiv), normalizing USB +5V into a clean
++interrupt signal for determining cable presence. On the original gumstix,
++this is GPIO81, and GPIO83 needs to be defined as well. On the gumstix F,
++this moves to GPIO17 and GPIO37. */
++
++/* GPIOx - Connects to USB D+ and used as a pull-up after GPIOn
++has detected a cable insertion; driven low otherwise. */
++
++#ifdef CONFIG_ARCH_GUMSTIX_ORIG
++
++#define GPIO_GUMSTIX_USB_GPIOn		81
++#define GPIO_GUMSTIX_USB_GPIOx		83
++
++#else
++
++#define GPIO_GUMSTIX_USB_GPIOn		35
++#define GPIO_GUMSTIX_USB_GPIOx		41
++
++#endif
++
++/* usb state change */
++#define GUMSTIX_USB_INTR_IRQ		IRQ_GPIO(GPIO_GUMSTIX_USB_GPIOn)
++
++#define GPIO_GUMSTIX_USB_GPIOn_MD	(GPIO_GUMSTIX_USB_GPIOn | GPIO_IN)
++#define GPIO_GUMSTIX_USB_GPIOx_CON_MD	(GPIO_GUMSTIX_USB_GPIOx | GPIO_OUT)
++#define GPIO_GUMSTIX_USB_GPIOx_DIS_MD	(GPIO_GUMSTIX_USB_GPIOx | GPIO_IN)
++
++/*
++ * SD/MMC definitions
++ */
++#define GUMSTIX_GPIO_nSD_WP		22 /* SD Write Protect */
++#define GUMSTIX_GPIO_nSD_DETECT		11 /* MMC/SD Card Detect */
++#define GUMSTIX_IRQ_GPIO_nSD_DETECT	IRQ_GPIO(GUMSTIX_GPIO_nSD_DETECT)
++
++/*
++ * SMC Ethernet definitions
++ * ETH_RST provides a hardware reset line to the ethernet chip
++ * ETH is the IRQ line in from the ethernet chip to the PXA
++ */
++#define GPIO_GUMSTIX_ETH0_RST		80
++#define GPIO_GUMSTIX_ETH0_RST_MD	(GPIO_GUMSTIX_ETH0_RST | GPIO_OUT)
++#define GPIO_GUMSTIX_ETH1_RST		52
++#define GPIO_GUMSTIX_ETH1_RST_MD	(GPIO_GUMSTIX_ETH1_RST | GPIO_OUT)
++
++#define GPIO_GUMSTIX_ETH0		36
++#define GPIO_GUMSTIX_ETH0_MD		(GPIO_GUMSTIX_ETH0 | GPIO_IN)
++#define GUMSTIX_ETH0_IRQ		IRQ_GPIO(GPIO_GUMSTIX_ETH0)
++#define GPIO_GUMSTIX_ETH1		27
++#define GPIO_GUMSTIX_ETH1_MD		(GPIO_GUMSTIX_ETH1 | GPIO_IN)
++#define GUMSTIX_ETH1_IRQ		IRQ_GPIO(GPIO_GUMSTIX_ETH1)
++
++
++/* CF reset line */
++#define GPIO8_RESET			8
++
++/* CF slot 0 */
++#define GPIO4_nBVD1			4
++#define GPIO4_nSTSCHG			GPIO4_nBVD1
++#define GPIO11_nCD			11
++#define GPIO26_PRDY_nBSY		26
++#define GUMSTIX_S0_nSTSCHG_IRQ		IRQ_GPIO(GPIO4_nSTSCHG)
++#define GUMSTIX_S0_nCD_IRQ		IRQ_GPIO(GPIO11_nCD)
++#define GUMSTIX_S0_PRDY_nBSY_IRQ	IRQ_GPIO(GPIO26_PRDY_nBSY)
++
++/* CF slot 1 */
++#define GPIO18_nBVD1			18
++#define GPIO18_nSTSCHG			GPIO18_nBVD1
++#define GPIO36_nCD			36
++#define GPIO27_PRDY_nBSY		27
++#define GUMSTIX_S1_nSTSCHG_IRQ		IRQ_GPIO(GPIO18_nSTSCHG)
++#define GUMSTIX_S1_nCD_IRQ		IRQ_GPIO(GPIO36_nCD)
++#define GUMSTIX_S1_PRDY_nBSY_IRQ	IRQ_GPIO(GPIO27_PRDY_nBSY)
++
++/* CF GPIO line modes */
++#define GPIO4_nSTSCHG_MD		(GPIO4_nSTSCHG | GPIO_IN)
++#define GPIO8_RESET_MD			(GPIO8_RESET | GPIO_OUT)
++#define GPIO11_nCD_MD			(GPIO11_nCD | GPIO_IN)
++#define GPIO18_nSTSCHG_MD		(GPIO18_nSTSCHG | GPIO_IN)
++#define GPIO26_PRDY_nBSY_MD		(GPIO26_PRDY_nBSY | GPIO_IN)
++#define GPIO27_PRDY_nBSY_MD		(GPIO27_PRDY_nBSY | GPIO_IN)
++#define GPIO36_nCD_MD			(GPIO36_nCD | GPIO_IN)
+diff --git a/include/asm-arm/arch-pxa/irda.h b/include/asm-arm/arch-pxa/irda.h
+index 748406f..99f4f42 100644
+--- a/include/asm-arm/arch-pxa/irda.h
++++ b/include/asm-arm/arch-pxa/irda.h
+@@ -10,6 +10,8 @@
+ struct pxaficp_platform_data {
+ 	int transceiver_cap;
+ 	void (*transceiver_mode)(struct device *dev, int mode);
++	int (*startup)(struct device *dev);
++	void (*shutdown)(struct device *dev);
+ };
+ 
+ extern void pxa_set_ficp_info(struct pxaficp_platform_data *info);
+diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
+index c562b97..50c77ea 100644
+--- a/include/asm-arm/arch-pxa/irqs.h
++++ b/include/asm-arm/arch-pxa/irqs.h
+@@ -181,7 +181,8 @@
+ #elif defined(CONFIG_ARCH_LUBBOCK) || \
+       defined(CONFIG_MACH_LOGICPD_PXA270) || \
+       defined(CONFIG_MACH_MAINSTONE) || \
+-      defined(CONFIG_MACH_PCM027)
++      defined(CONFIG_MACH_PCM027) || \
++      defined(CONFIG_MACH_MAGICIAN)
+ #define NR_IRQS			(IRQ_BOARD_END)
+ #else
+ #define NR_IRQS			(IRQ_BOARD_START)
+diff --git a/include/asm-arm/arch-pxa/magician.h b/include/asm-arm/arch-pxa/magician.h
+index 337f51f..b34fd56 100644
+--- a/include/asm-arm/arch-pxa/magician.h
++++ b/include/asm-arm/arch-pxa/magician.h
+@@ -12,7 +12,8 @@
+ #ifndef _MAGICIAN_H_
+ #define _MAGICIAN_H_
+ 
+-#include <asm/arch/pxa-regs.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ 
+ /*
+  * PXA GPIOs
+@@ -34,6 +35,7 @@
+ #define GPIO48_MAGICIAN_UNKNOWN			48
+ #define GPIO56_MAGICIAN_UNKNOWN			56
+ #define GPIO57_MAGICIAN_CAM_RESET		57
++#define GPIO75_MAGICIAN_SAMSUNG_POWER		75
+ #define GPIO83_MAGICIAN_nIR_EN			83
+ #define GPIO86_MAGICIAN_GSM_RESET		86
+ #define GPIO87_MAGICIAN_GSM_SELECT		87
+@@ -81,6 +83,7 @@
+ #define GPIO48_MAGICIAN_UNKNOWN_MD		(48 | GPIO_OUT)
+ #define GPIO56_MAGICIAN_UNKNOWN_MD		(56 | GPIO_OUT)
+ #define GPIO57_MAGICIAN_CAM_RESET_MD		(57 | GPIO_OUT)
++#define GPIO75_MAGICIAN_SAMSUNG_POWER_MD	(75 | GPIO_OUT)
+ #define GPIO83_MAGICIAN_nIR_EN_MD		(83 | GPIO_OUT)
+ #define GPIO86_MAGICIAN_GSM_RESET_MD		(86 | GPIO_OUT)
+ #define GPIO87_MAGICIAN_GSM_SELECT_MD		(87 | GPIO_OUT)
+@@ -108,4 +111,56 @@
+ #define GPIO119_MAGICIAN_UNKNOWN_MD		(119 | GPIO_OUT)
+ #define GPIO120_MAGICIAN_UNKNOWN_MD		(120 | GPIO_OUT)
+ 
++/*
++ * CPLD IRQs
++ */
++
++#define IRQ_MAGICIAN_SD		(IRQ_BOARD_START + 0)
++#define IRQ_MAGICIAN_EP		(IRQ_BOARD_START + 1)
++#define IRQ_MAGICIAN_BT		(IRQ_BOARD_START + 2)
++#define IRQ_MAGICIAN_AC		(IRQ_BOARD_START + 3)
++
++/*
++ * CPLD EGPIOs
++ */
++
++#define MAGICIAN_EGPIO_BASE			0x80 /* GPIO_BOARD_START */
++#define MAGICIAN_EGPIO(reg,bit) \
++	(MAGICIAN_EGPIO_BASE + 8*reg + bit)
++
++/* output */
++
++#define EGPIO_MAGICIAN_TOPPOLY_POWER		MAGICIAN_EGPIO(0, 2)
++#define EGPIO_MAGICIAN_LED_POWER		MAGICIAN_EGPIO(0, 5)
++#define EGPIO_MAGICIAN_GSM_RESET		MAGICIAN_EGPIO(0, 6)
++#define EGPIO_MAGICIAN_LCD_POWER		MAGICIAN_EGPIO(0, 7)
++#define EGPIO_MAGICIAN_SPK_POWER		MAGICIAN_EGPIO(1, 0)
++#define EGPIO_MAGICIAN_EP_POWER			MAGICIAN_EGPIO(1, 1)
++#define EGPIO_MAGICIAN_IN_SEL0			MAGICIAN_EGPIO(1, 2)
++#define EGPIO_MAGICIAN_IN_SEL1			MAGICIAN_EGPIO(1, 3)
++#define EGPIO_MAGICIAN_MIC_POWER		MAGICIAN_EGPIO(1, 4)
++#define EGPIO_MAGICIAN_CODEC_RESET		MAGICIAN_EGPIO(1, 5)
++#define EGPIO_MAGICIAN_CODEC_POWER		MAGICIAN_EGPIO(1, 6)
++#define EGPIO_MAGICIAN_BL_POWER			MAGICIAN_EGPIO(1, 7)
++#define EGPIO_MAGICIAN_SD_POWER			MAGICIAN_EGPIO(2, 0)
++#define EGPIO_MAGICIAN_CARKIT_MIC		MAGICIAN_EGPIO(2, 1)
++#define EGPIO_MAGICIAN_UNKNOWN_WAVEDEV_DLL	MAGICIAN_EGPIO(2, 2)
++#define EGPIO_MAGICIAN_FLASH_VPP		MAGICIAN_EGPIO(2, 3)
++#define EGPIO_MAGICIAN_BL_POWER2		MAGICIAN_EGPIO(2, 4)
++#define EGPIO_MAGICIAN_CHARGE_EN		MAGICIAN_EGPIO(2, 5)
++#define EGPIO_MAGICIAN_GSM_POWER		MAGICIAN_EGPIO(2, 7)
++
++/* input */
++
++#define EGPIO_MAGICIAN_CABLE_STATE_AC		MAGICIAN_EGPIO(4, 0)
++#define EGPIO_MAGICIAN_CABLE_STATE_USB		MAGICIAN_EGPIO(4, 1)
++
++#define EGPIO_MAGICIAN_BOARD_ID0		MAGICIAN_EGPIO(5, 0)
++#define EGPIO_MAGICIAN_BOARD_ID1		MAGICIAN_EGPIO(5, 1)
++#define EGPIO_MAGICIAN_BOARD_ID2		MAGICIAN_EGPIO(5, 2)
++#define EGPIO_MAGICIAN_LCD_SELECT		MAGICIAN_EGPIO(5, 3)
++#define EGPIO_MAGICIAN_nSD_READONLY		MAGICIAN_EGPIO(5, 4)
++
++#define EGPIO_MAGICIAN_EP_INSERT		MAGICIAN_EGPIO(6, 1)
++
+ #endif /* _MAGICIAN_H_ */
+diff --git a/include/asm-arm/arch-pxa/mfp-pxa25x.h b/include/asm-arm/arch-pxa/mfp-pxa25x.h
+new file mode 100644
+index 0000000..0499323
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/mfp-pxa25x.h
+@@ -0,0 +1,161 @@
++#ifndef __ASM_ARCH_MFP_PXA25X_H
++#define __ASM_ARCH_MFP_PXA25X_H
++
++#include <asm/arch/mfp.h>
++#include <asm/arch/mfp-pxa2xx.h>
++
++/* GPIO */
++#define GPIO2_GPIO		MFP_CFG_IN(GPIO2, AF0)
++#define GPIO3_GPIO		MFP_CFG_IN(GPIO3, AF0)
++#define GPIO4_GPIO		MFP_CFG_IN(GPIO4, AF0)
++#define GPIO5_GPIO		MFP_CFG_IN(GPIO5, AF0)
++#define GPIO6_GPIO		MFP_CFG_IN(GPIO6, AF0)
++#define GPIO7_GPIO		MFP_CFG_IN(GPIO7, AF0)
++#define GPIO8_GPIO		MFP_CFG_IN(GPIO8, AF0)
++
++#define GPIO1_RST		MFP_CFG_IN(GPIO1, AF1)
++
++/* Crystal and Clock Signals */
++#define GPIO10_RTCCLK		MFP_CFG_OUT(GPIO10, AF1, DRIVE_LOW)
++#define GPIO70_RTC_CLK		MFP_CFG_OUT(GPIO70, AF1, DRIVE_LOW)
++#define GPIO7_48MHz		MFP_CFG_OUT(GPIO7,  AF1, DRIVE_LOW)
++#define GPIO11_3_6MHz		MFP_CFG_OUT(GPIO11, AF1, DRIVE_LOW)
++#define GPIO71_3_6MHz		MFP_CFG_OUT(GPIO71, AF1, DRIVE_LOW)
++#define GPIO12_32KHz		MFP_CFG_OUT(GPIO12, AF1, DRIVE_LOW)
++#define GPIO72_32kHz		MFP_CFG_OUT(GPIO72, AF1, DRIVE_LOW)
++
++/* SDRAM and Static Memory I/O Signals */
++#define GPIO15_nCS_1		MFP_CFG_OUT(GPIO15, AF2, DRIVE_HIGH)
++#define GPIO78_nCS_2		MFP_CFG_OUT(GPIO78, AF2, DRIVE_HIGH)
++#define GPIO79_nCS_3		MFP_CFG_OUT(GPIO79, AF2, DRIVE_HIGH)
++#define GPIO80_nCS_4		MFP_CFG_OUT(GPIO80, AF2, DRIVE_HIGH)
++#define GPIO33_nCS_5		MFP_CFG_OUT(GPIO33, AF2, DRIVE_HIGH)
++
++/* Miscellaneous I/O and DMA Signals */
++#define GPIO18_RDY		MFP_CFG_IN(GPIO18, AF1)
++#define GPIO20_DREQ_0		MFP_CFG_IN(GPIO20, AF1)
++#define GPIO19_DREQ_1		MFP_CFG_IN(GPIO19, AF1)
++
++/* Alternate Bus Master Mode I/O Signals */
++#define GPIO13_MBGNT		MFP_CFG_OUT(GPIO13, AF2, DRIVE_LOW)
++#define GPIO73_MBGNT		MFP_CFG_OUT(GPIO73, AF1, DRIVE_LOW)
++#define GPIO14_MBREQ		MFP_CFG_IN(GPIO14, AF1)
++#define GPIO66_MBREQ		MFP_CFG_IN(GPIO66, AF1)
++
++/* PC CARD */
++#define GPIO52_nPCE_1		MFP_CFG_OUT(GPIO52, AF2, DRIVE_HIGH)
++#define GPIO53_nPCE_2		MFP_CFG_OUT(GPIO53, AF2, DRIVE_HIGH)
++#define GPIO55_nPREG		MFP_CFG_OUT(GPIO55, AF2, DRIVE_HIGH)
++#define GPIO50_nPIOR		MFP_CFG_OUT(GPIO50, AF2, DRIVE_HIGH)
++#define GPIO51_nPIOW		MFP_CFG_OUT(GPIO51, AF2, DRIVE_HIGH)
++#define GPIO49_nPWE		MFP_CFG_OUT(GPIO49, AF2, DRIVE_HIGH)
++#define GPIO48_nPOE		MFP_CFG_OUT(GPIO48, AF2, DRIVE_HIGH)
++#define GPIO57_nIOIS16		MFP_CFG_IN(GPIO57, AF1)
++#define GPIO56_nPWAIT		MFP_CFG_IN(GPIO56, AF1)
++#define GPIO54_nPSKTSEL		MFP_CFG_OUT(GPIO54, AF2, DRIVE_HIGH)
++
++/* FFUART */
++#define GPIO34_FFUART_RXD	MFP_CFG_IN(GPIO34, AF1)
++#define GPIO35_FFUART_CTS	MFP_CFG_IN(GPIO35, AF1)
++#define GPIO36_FFUART_DCD	MFP_CFG_IN(GPIO36, AF1)
++#define GPIO37_FFUART_DSR	MFP_CFG_IN(GPIO37, AF1)
++#define GPIO38_FFUART_RI	MFP_CFG_IN(GPIO38, AF1)
++#define GPIO39_FFUART_TXD	MFP_CFG_OUT(GPIO39, AF2, DRIVE_HIGH)
++#define GPIO40_FFUART_DTR	MFP_CFG_OUT(GPIO40, AF2, DRIVE_HIGH)
++#define GPIO41_FFUART_RTS	MFP_CFG_OUT(GPIO41, AF2, DRIVE_HIGH)
++
++/* BTUART */
++#define GPIO42_BTUART_RXD	MFP_CFG_IN(GPIO42, AF1)
++#define GPIO43_BTUART_TXD	MFP_CFG_OUT(GPIO43, AF2, DRIVE_HIGH)
++#define GPIO44_BTUART_CTS	MFP_CFG_IN(GPIO44, AF1)
++#define GPIO45_BTUART_RTS	MFP_CFG_OUT(GPIO45, AF2, DRIVE_HIGH)
++
++/* STUART */
++#define GPIO46_STUART_RXD	MFP_CFG_IN(GPIO46, AF2)
++#define GPIO47_STUART_TXD	MFP_CFG_OUT(GPIO47, AF1, DRIVE_HIGH)
++
++/* HWUART */
++#define GPIO42_HWUART_RXD	MFP_CFG_IN(GPIO42, AF3)
++#define GPIO43_HWUART_TXD	MFP_CFG_OUT(GPIO43, AF3, DRIVE_HIGH)
++#define GPIO44_HWUART_CTS	MFP_CFG_IN(GPIO44, AF3)
++#define GPIO45_HWUART_RTS	MFP_CFG_OUT(GPIO45, AF3, DRIVE_HIGH)
++#define GPIO48_HWUART_TXD	MFP_CFG_OUT(GPIO48, AF1, DRIVE_HIGH)
++#define GPIO49_HWUART_RXD	MFP_CFG_IN(GPIO49, AF1)
++#define GPIO50_HWUART_CTS	MFP_CFG_IN(GPIO50, AF1)
++#define GPIO51_HWUART_RTS	MFP_CFG_OUT(GPIO51, AF1, DRIVE_HIGH)
++
++/* FICP */
++#define GPIO46_FICP_RXD		MFP_CFG_IN(GPIO46, AF1)
++#define GPIO47_FICP_TXD		MFP_CFG_OUT(GPIO47, AF2, DRIVE_HIGH)
++
++/* PWM 0/1 */
++#define GPIO16_PWM0_OUT		MFP_CFG_OUT(GPIO16, AF2, DRIVE_LOW)
++#define GPIO17_PWM1_OUT		MFP_CFG_OUT(GPIO17, AF2, DRIVE_LOW)
++
++/* AC97 */
++#define GPIO28_AC97_BITCLK	MFP_CFG_IN(GPIO28, AF1)
++#define GPIO29_AC97_SDATA_IN_0	MFP_CFG_IN(GPIO29, AF1)
++#define GPIO30_AC97_SDATA_OUT	MFP_CFG_OUT(GPIO30, AF2, DRIVE_LOW)
++#define GPIO31_AC97_SYNC	MFP_CFG_OUT(GPIO31, AF2, DRIVE_LOW)
++#define GPIO32_AC97_SDATA_IN_1	MFP_CFG_IN(GPIO32, AF1)
++
++/* I2S */
++#define GPIO28_I2S_BITCLK_IN	MFP_CFG_IN(GPIO28, AF2)
++#define GPIO28_I2S_BITCLK_OUT	MFP_CFG_OUT(GPIO28, AF1, DRIVE_LOW)
++#define GPIO29_I2S_SDATA_IN	MFP_CFG_IN(GPIO29, AF2)
++#define GPIO30_I2S_SDATA_OUT	MFP_CFG_OUT(GPIO30, AF1, DRIVE_LOW)
++#define GPIO31_I2S_SYNC		MFP_CFG_OUT(GPIO31, AF1, DRIVE_LOW)
++#define GPIO32_I2S_SYSCLK	MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW)
++
++/* SSP 1 */
++#define GPIO23_SSP1_SCLK	MFP_CFG_OUT(GPIO23, AF2, DRIVE_LOW)
++#define GPIO24_SSP1_SFRM	MFP_CFG_OUT(GPIO24, AF2, DRIVE_LOW)
++#define GPIO25_SSP1_TXD		MFP_CFG_OUT(GPIO25, AF2, DRIVE_LOW)
++#define GPIO26_SSP1_RXD		MFP_CFG_IN(GPIO26, AF1)
++#define GPIO27_SSP1_EXTCLK	MFP_CFG_IN(GPIO27, AF1)
++
++/* SSP 2 - NSSP */
++#define GPIO81_SSP2_CLK_OUT 	MFP_CFG_OUT(GPIO81, AF1, DRIVE_LOW)
++#define GPIO81_SSP2_CLK_IN  	MFP_CFG_IN(GPIO81, AF1)
++#define GPIO82_SSP2_FRM_OUT 	MFP_CFG_OUT(GPIO82, AF1, DRIVE_LOW)
++#define GPIO82_SSP2_FRM_IN  	MFP_CFG_IN(GPIO82, AF1)
++#define GPIO83_SSP2_TXD      	MFP_CFG_OUT(GPIO83, AF1, DRIVE_LOW)
++#define GPIO83_SSP2_RXD      	MFP_CFG_IN(GPIO83, AF2)
++#define GPIO84_SSP2_TXD      	MFP_CFG_OUT(GPIO84, AF1, DRIVE_LOW)
++#define GPIO84_SSP2_RXD      	MFP_CFG_IN(GPIO84, AF2)
++
++/* MMC */
++#define GPIO6_MMC_CLK		MFP_CFG_OUT(GPIO6, AF1, DRIVE_LOW)
++#define GPIO8_MMC_CS0		MFP_CFG_OUT(GPIO8, AF1, DRIVE_LOW)
++#define GPIO9_MMC_CS1		MFP_CFG_OUT(GPIO9, AF1, DRIVE_LOW)
++#define GPIO34_MMC_CS0		MFP_CFG_OUT(GPIO34, AF2, DRIVE_LOW)
++#define GPIO39_MMC_CS1		MFP_CFG_OUT(GPIO39, AF1, DRIVE_LOW)
++#define GPIO53_MMC_CLK		MFP_CFG_OUT(GPIO53, AF1, DRIVE_LOW)
++#define GPIO54_MMC_CLK		MFP_CFG_OUT(GPIO54, AF1, DRIVE_LOW)
++#define GPIO69_MMC_CLK		MFP_CFG_OUT(GPIO69, AF1, DRIVE_LOW)
++#define GPIO67_MMC_CS0		MFP_CFG_OUT(GPIO67, AF1, DRIVE_LOW)
++#define GPIO68_MMC_CS1		MFP_CFG_OUT(GPIO68, AF1, DRIVE_LOW)
++
++/* LCD */
++#define GPIO58_LCD_LDD_0	MFP_CFG_OUT(GPIO58, AF2, DRIVE_LOW)
++#define GPIO59_LCD_LDD_1	MFP_CFG_OUT(GPIO59, AF2, DRIVE_LOW)
++#define GPIO60_LCD_LDD_2	MFP_CFG_OUT(GPIO60, AF2, DRIVE_LOW)
++#define GPIO61_LCD_LDD_3	MFP_CFG_OUT(GPIO61, AF2, DRIVE_LOW)
++#define GPIO62_LCD_LDD_4	MFP_CFG_OUT(GPIO62, AF2, DRIVE_LOW)
++#define GPIO63_LCD_LDD_5	MFP_CFG_OUT(GPIO63, AF2, DRIVE_LOW)
++#define GPIO64_LCD_LDD_6	MFP_CFG_OUT(GPIO64, AF2, DRIVE_LOW)
++#define GPIO65_LCD_LDD_7	MFP_CFG_OUT(GPIO65, AF2, DRIVE_LOW)
++#define GPIO66_LCD_LDD_8	MFP_CFG_OUT(GPIO66, AF2, DRIVE_LOW)
++#define GPIO67_LCD_LDD_9	MFP_CFG_OUT(GPIO67, AF2, DRIVE_LOW)
++#define GPIO68_LCD_LDD_10	MFP_CFG_OUT(GPIO68, AF2, DRIVE_LOW)
++#define GPIO69_LCD_LDD_11	MFP_CFG_OUT(GPIO69, AF2, DRIVE_LOW)
++#define GPIO70_LCD_LDD_12	MFP_CFG_OUT(GPIO70, AF2, DRIVE_LOW)
++#define GPIO71_LCD_LDD_13	MFP_CFG_OUT(GPIO71, AF2, DRIVE_LOW)
++#define GPIO72_LCD_LDD_14	MFP_CFG_OUT(GPIO72, AF2, DRIVE_LOW)
++#define GPIO73_LCD_LDD_15	MFP_CFG_OUT(GPIO73, AF2, DRIVE_LOW)
++#define GPIO74_LCD_FCLK		MFP_CFG_OUT(GPIO74, AF2, DRIVE_LOW)
++#define GPIO75_LCD_LCLK		MFP_CFG_OUT(GPIO75, AF2, DRIVE_LOW)
++#define GPIO76_LCD_PCLK		MFP_CFG_OUT(GPIO76, AF2, DRIVE_LOW)
++#define GPIO77_LCD_ACBIAS	MFP_CFG_OUT(GPIO77, AF2, DRIVE_LOW)
++
++#endif /* __ASM_ARCH_MFP_PXA25X_H */
+diff --git a/include/asm-arm/arch-pxa/mfp-pxa27x.h b/include/asm-arm/arch-pxa/mfp-pxa27x.h
+new file mode 100644
+index 0000000..eb6eaa1
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/mfp-pxa27x.h
+@@ -0,0 +1,432 @@
++#ifndef __ASM_ARCH_MFP_PXA27X_H
++#define __ASM_ARCH_MFP_PXA27X_H
++
++/*
++ * NOTE:  for those special-function bidirectional GPIOs, as described
++ * in the "PXA27x Developer's Manual" Section 24.4.2.1, only its input
++ * alternative is preserved, the direction is actually selected by the
++ * specific controller, and this should work in most cases.
++ */
++
++#include <asm/arch/mfp.h>
++#include <asm/arch/mfp-pxa2xx.h>
++
++/* GPIO */
++#define GPIO85_GPIO		MFP_CFG_IN(GPIO85, AF0)
++#define GPIO86_GPIO		MFP_CFG_IN(GPIO86, AF0)
++#define GPIO87_GPIO		MFP_CFG_IN(GPIO87, AF0)
++#define GPIO88_GPIO		MFP_CFG_IN(GPIO88, AF0)
++#define GPIO89_GPIO		MFP_CFG_IN(GPIO89, AF0)
++#define GPIO90_GPIO		MFP_CFG_IN(GPIO90, AF0)
++#define GPIO91_GPIO		MFP_CFG_IN(GPIO91, AF0)
++#define GPIO92_GPIO		MFP_CFG_IN(GPIO92, AF0)
++#define GPIO93_GPIO		MFP_CFG_IN(GPIO93, AF0)
++#define GPIO94_GPIO		MFP_CFG_IN(GPIO94, AF0)
++#define GPIO95_GPIO		MFP_CFG_IN(GPIO95, AF0)
++#define GPIO96_GPIO		MFP_CFG_IN(GPIO96, AF0)
++#define GPIO97_GPIO		MFP_CFG_IN(GPIO97, AF0)
++#define GPIO98_GPIO		MFP_CFG_IN(GPIO98, AF0)
++#define GPIO99_GPIO		MFP_CFG_IN(GPIO99, AF0)
++#define GPIO100_GPIO		MFP_CFG_IN(GPIO100, AF0)
++#define GPIO101_GPIO		MFP_CFG_IN(GPIO101, AF0)
++#define GPIO102_GPIO		MFP_CFG_IN(GPIO102, AF0)
++#define GPIO103_GPIO		MFP_CFG_IN(GPIO103, AF0)
++#define GPIO104_GPIO		MFP_CFG_IN(GPIO104, AF0)
++#define GPIO105_GPIO		MFP_CFG_IN(GPIO105, AF0)
++#define GPIO106_GPIO		MFP_CFG_IN(GPIO106, AF0)
++#define GPIO107_GPIO		MFP_CFG_IN(GPIO107, AF0)
++#define GPIO108_GPIO		MFP_CFG_IN(GPIO108, AF0)
++#define GPIO109_GPIO		MFP_CFG_IN(GPIO109, AF0)
++#define GPIO110_GPIO		MFP_CFG_IN(GPIO110, AF0)
++#define GPIO111_GPIO		MFP_CFG_IN(GPIO111, AF0)
++#define GPIO112_GPIO		MFP_CFG_IN(GPIO112, AF0)
++#define GPIO113_GPIO		MFP_CFG_IN(GPIO113, AF0)
++#define GPIO114_GPIO		MFP_CFG_IN(GPIO114, AF0)
++#define GPIO115_GPIO		MFP_CFG_IN(GPIO115, AF0)
++#define GPIO116_GPIO		MFP_CFG_IN(GPIO116, AF0)
++#define GPIO117_GPIO		MFP_CFG_IN(GPIO117, AF0)
++#define GPIO118_GPIO		MFP_CFG_IN(GPIO118, AF0)
++#define GPIO119_GPIO		MFP_CFG_IN(GPIO119, AF0)
++#define GPIO120_GPIO		MFP_CFG_IN(GPIO120, AF0)
++
++/* Crystal and Clock Signals */
++#define GPIO9_HZ_CLK		MFP_CFG_OUT(GPIO9,  AF1, DRIVE_LOW)
++#define GPIO10_HZ_CLK		MFP_CFG_OUT(GPIO10, AF1, DRIVE_LOW)
++#define GPIO11_48_MHz		MFP_CFG_OUT(GPIO11, AF3, DRIVE_LOW)
++#define GPIO12_48_MHz		MFP_CFG_OUT(GPIO12, AF3, DRIVE_LOW)
++#define GPIO13_CLK_EXT		MFP_CFG_IN(GPIO13, AF1)
++
++/* OS Timer Signals */
++#define GPIO11_EXT_SYNC_0	MFP_CFG_IN(GPIO11, AF1)
++#define GPIO12_EXT_SYNC_1	MFP_CFG_IN(GPIO12, AF1)
++#define GPIO9_CHOUT_0		MFP_CFG_OUT(GPIO9,  AF3, DRIVE_LOW)
++#define GPIO10_CHOUT_1		MFP_CFG_OUT(GPIO10, AF3, DRIVE_LOW)
++#define GPIO11_CHOUT_0		MFP_CFG_OUT(GPIO11, AF1, DRIVE_LOW)
++#define GPIO12_CHOUT_1		MFP_CFG_OUT(GPIO12, AF1, DRIVE_LOW)
++
++/* SDRAM and Static Memory I/O Signals */
++#define GPIO20_nSDCS_2		MFP_CFG_OUT(GPIO20, AF1, DRIVE_HIGH)
++#define GPIO21_nSDCS_3		MFP_CFG_OUT(GPIO21, AF1, DRIVE_HIGH)
++#define GPIO15_nCS_1		MFP_CFG_OUT(GPIO15, AF2, DRIVE_HIGH)
++#define GPIO78_nCS_2		MFP_CFG_OUT(GPIO78, AF2, DRIVE_HIGH)
++#define GPIO79_nCS_3		MFP_CFG_OUT(GPIO79, AF2, DRIVE_HIGH)
++#define GPIO80_nCS_4		MFP_CFG_OUT(GPIO80, AF2, DRIVE_HIGH)
++#define GPIO33_nCS_5		MFP_CFG_OUT(GPIO33, AF2, DRIVE_HIGH)
++
++/* Miscellaneous I/O and DMA Signals */
++#define GPIO21_DVAL_0		MFP_CFG_OUT(GPIO21, AF2, DRIVE_HIGH)
++#define GPIO116_DVAL_0		MFP_CFG_OUT(GPIO116, AF1, DRIVE_HIGH)
++#define GPIO33_DVAL_1		MFP_CFG_OUT(GPIO33, AF1, DRIVE_HIGH)
++#define GPIO96_DVAL_1		MFP_CFG_OUT(GPIO96, AF2, DRIVE_HIGH)
++#define GPIO18_RDY		MFP_CFG_IN(GPIO18, AF1)
++#define GPIO20_DREQ_0		MFP_CFG_IN(GPIO20, AF1)
++#define GPIO115_DREQ_0		MFP_CFG_IN(GPIO115, AF1)
++#define GPIO80_DREQ_1		MFP_CFG_IN(GPIO80, AF1)
++#define GPIO97_DREQ_1		MFP_CFG_IN(GPIO97, AF2)
++#define GPIO85_DREQ_2		MFP_CFG_IN(GPIO85, AF2)
++#define GPIO100_DREQ_2		MFP_CFG_IN(GPIO100, AF2)
++
++/* Alternate Bus Master Mode I/O Signals */
++#define GPIO20_MBREQ		MFP_CFG_IN(GPIO20, AF2)
++#define GPIO80_MBREQ		MFP_CFG_IN(GPIO80, AF2)
++#define GPIO96_MBREQ		MFP_CFG_IN(GPIO96, AF2)
++#define GPIO115_MBREQ		MFP_CFG_IN(GPIO115, AF3)
++#define GPIO21_MBGNT		MFP_CFG_OUT(GPIO21, AF3, DRIVE_LOW)
++#define GPIO33_MBGNT		MFP_CFG_OUT(GPIO33, AF3, DRIVE_LOW)
++#define GPIO97_MBGNT		MFP_CFG_OUT(GPIO97, AF2, DRIVE_LOW)
++#define GPIO116_MBGNT		MFP_CFG_OUT(GPIO116, AF3, DRIVE_LOW)
++
++/* PC CARD */
++#define GPIO15_nPCE_1		MFP_CFG_OUT(GPIO15, AF1, DRIVE_HIGH)
++#define GPIO85_nPCE_1		MFP_CFG_OUT(GPIO85, AF1, DRIVE_HIGH)
++#define GPIO86_nPCE_1		MFP_CFG_OUT(GPIO86, AF1, DRIVE_HIGH)
++#define GPIO102_nPCE_1		MFP_CFG_OUT(GPIO102, AF1, DRIVE_HIGH)
++#define GPIO54_nPCE_2		MFP_CFG_OUT(GPIO54, AF2, DRIVE_HIGH)
++#define GPIO78_nPCE_2		MFP_CFG_OUT(GPIO78, AF1, DRIVE_HIGH)
++#define GPIO87_nPCE_2		MFP_CFG_IN(GPIO87, AF1)
++#define GPIO55_nPREG		MFP_CFG_OUT(GPIO55, AF2, DRIVE_HIGH)
++#define GPIO50_nPIOR		MFP_CFG_OUT(GPIO50, AF2, DRIVE_HIGH)
++#define GPIO51_nPIOW		MFP_CFG_OUT(GPIO51, AF2, DRIVE_HIGH)
++#define GPIO49_nPWE		MFP_CFG_OUT(GPIO49, AF2, DRIVE_HIGH)
++#define GPIO48_nPOE		MFP_CFG_OUT(GPIO48, AF2, DRIVE_HIGH)
++#define GPIO57_nIOIS16		MFP_CFG_IN(GPIO57, AF1)
++#define GPIO56_nPWAIT		MFP_CFG_IN(GPIO56, AF1)
++#define GPIO79_PSKTSEL		MFP_CFG_OUT(GPIO79, AF1, DRIVE_HIGH)
++
++/* I2C */
++#define GPIO117_I2C_SCL		MFP_CFG_IN(GPIO117, AF1)
++#define GPIO118_I2C_SDA		MFP_CFG_IN(GPIO118, AF1)
++
++/* FFUART */
++#define GPIO9_FFUART_CTS	MFP_CFG_IN(GPIO9, AF3)
++#define GPIO26_FFUART_CTS	MFP_CFG_IN(GPIO26, AF3)
++#define GPIO35_FFUART_CTS	MFP_CFG_IN(GPIO35, AF1)
++#define GPIO100_FFUART_CTS	MFP_CFG_IN(GPIO100, AF3)
++#define GPIO10_FFUART_DCD	MFP_CFG_IN(GPIO10, AF1)
++#define GPIO36_FFUART_DCD	MFP_CFG_IN(GPIO36, AF1)
++#define GPIO33_FFUART_DSR	MFP_CFG_IN(GPIO33, AF2)
++#define GPIO37_FFUART_DSR	MFP_CFG_IN(GPIO37, AF1)
++#define GPIO38_FFUART_RI	MFP_CFG_IN(GPIO38, AF1)
++#define GPIO89_FFUART_RI	MFP_CFG_IN(GPIO89, AF3)
++#define GPIO19_FFUART_RXD	MFP_CFG_IN(GPIO19, AF3)
++#define GPIO33_FFUART_RXD	MFP_CFG_IN(GPIO33, AF1)
++#define GPIO34_FFUART_RXD	MFP_CFG_IN(GPIO34, AF1)
++#define GPIO41_FFUART_RXD	MFP_CFG_IN(GPIO41, AF1)
++#define GPIO53_FFUART_RXD	MFP_CFG_IN(GPIO53, AF1)
++#define GPIO85_FFUART_RXD	MFP_CFG_IN(GPIO85, AF1)
++#define GPIO96_FFUART_RXD	MFP_CFG_IN(GPIO96, AF3)
++#define GPIO102_FFUART_RXD	MFP_CFG_IN(GPIO102, AF3)
++#define GPIO16_FFUART_TXD	MFP_CFG_OUT(GPIO16, AF3, DRIVE_HIGH)
++#define GPIO37_FFUART_TXD	MFP_CFG_OUT(GPIO37, AF3, DRIVE_HIGH)
++#define GPIO39_FFUART_TXD	MFP_CFG_OUT(GPIO39, AF2, DRIVE_HIGH)
++#define GPIO83_FFUART_TXD	MFP_CFG_OUT(GPIO83, AF2, DRIVE_HIGH)
++#define GPIO99_FFUART_TXD	MFP_CFG_OUT(GPIO99, AF3, DRIVE_HIGH)
++#define GPIO27_FFUART_RTS	MFP_CFG_OUT(GPIO27, AF3, DRIVE_HIGH)
++#define GPIO41_FFUART_RTS	MFP_CFG_OUT(GPIO41, AF2, DRIVE_HIGH)
++#define GPIO83_FFUART_RTS	MFP_CFG_OUT(GPIO83, AF3, DRIVE_HIGH)
++#define GPIO98_FFUART_RTS	MFP_CFG_OUT(GPIO98, AF3, DRIVE_HIGH)
++#define GPIO40_FFUART_DTR	MFP_CFG_OUT(GPIO40, AF2, DRIVE_HIGH)
++#define GPIO82_FFUART_DTR	MFP_CFG_OUT(GPIO82, AF3, DRIVE_HIGH)
++
++/* BTUART */
++#define GPIO44_BTUART_CTS	MFP_CFG_IN(GPIO44, AF1)
++#define GPIO42_BTUART_RXD	MFP_CFG_IN(GPIO42, AF1)
++#define GPIO45_BTUART_RTS	MFP_CFG_OUT(GPIO45, AF2, DRIVE_HIGH)
++#define GPIO43_BTUART_TXD	MFP_CFG_OUT(GPIO43, AF2, DRIVE_HIGH)
++
++/* STUART */
++#define GPIO46_STUART_RXD	MFP_CFG_IN(GPIO46, AF2)
++#define GPIO47_STUART_TXD	MFP_CFG_OUT(GPIO47, AF1, DRIVE_HIGH)
++
++/* FICP */
++#define GPIO42_FICP_RXD		MFP_CFG_IN(GPIO42, AF2)
++#define GPIO46_FICP_RXD		MFP_CFG_IN(GPIO46, AF1)
++#define GPIO43_FICP_TXD		MFP_CFG_OUT(GPIO43, AF1, DRIVE_HIGH)
++#define GPIO47_FICP_TXD		MFP_CFG_OUT(GPIO47, AF2, DRIVE_HIGH)
++
++/* PWM 0/1/2/3 */
++#define GPIO11_PWM2_OUT		MFP_CFG_OUT(GPIO11, AF2, DRIVE_LOW)
++#define GPIO12_PWM3_OUT		MFP_CFG_OUT(GPIO12, AF2, DRIVE_LOW)
++#define GPIO16_PWM0_OUT		MFP_CFG_OUT(GPIO16, AF2, DRIVE_LOW)
++#define GPIO17_PWM1_OUT		MFP_CFG_OUT(GPIO17, AF2, DRIVE_LOW)
++#define GPIO38_PWM1_OUT		MFP_CFG_OUT(GPIO38, AF3, DRIVE_LOW)
++#define GPIO46_PWM2_OUT		MFP_CFG_OUT(GPIO46, AF2, DRIVE_LOW)
++#define GPIO47_PWM3_OUT		MFP_CFG_OUT(GPIO47, AF3, DRIVE_LOW)
++#define GPIO79_PWM2_OUT		MFP_CFG_OUT(GPIO79, AF3, DRIVE_LOW)
++#define GPIO80_PWM3_OUT		MFP_CFG_OUT(GPIO80, AF3, DRIVE_LOW)
++#define GPIO115_PWM1_OUT	MFP_CFG_OUT(GPIO115, AF3, DRIVE_LOW)
++
++/* AC97 */
++#define GPIO31_AC97_SYNC	MFP_CFG_OUT(GPIO31, AF2, DRIVE_LOW)
++#define GPIO94_AC97_SYNC	MFP_CFG_OUT(GPIO94, AF1, DRIVE_LOW)
++#define GPIO30_AC97_SDATA_OUT	MFP_CFG_OUT(GPIO30, AF2, DRIVE_LOW)
++#define GPIO93_AC97_SDATA_OUT	MFP_CFG_OUT(GPIO93, AF1, DRIVE_LOW)
++#define GPIO45_AC97_SYSCLK	MFP_CFG_OUT(GPIO45, AF1, DRIVE_LOW)
++#define GPIO89_AC97_SYSCLK	MFP_CFG_OUT(GPIO89, AF1, DRIVE_LOW)
++#define GPIO98_AC97_SYSCLK	MFP_CFG_OUT(GPIO98, AF1, DRIVE_LOW)
++#define GPIO95_AC97_nRESET	MFP_CFG_OUT(GPIO95, AF1, DRIVE_LOW)
++#define GPIO113_AC97_nRESET	MFP_CFG_OUT(GPIO113, AF2, DRIVE_LOW)
++#define GPIO28_AC97_BITCLK	MFP_CFG_IN(GPIO28, AF1)
++#define GPIO29_AC97_SDATA_IN_0	MFP_CFG_IN(GPIO29, AF1)
++#define GPIO116_AC97_SDATA_IN_0	MFP_CFG_IN(GPIO116, AF2)
++#define GPIO99_AC97_SDATA_IN_1	MFP_CFG_IN(GPIO99, AF2)
++
++/* I2S */
++#define GPIO28_I2S_BITCLK_IN	MFP_CFG_IN(GPIO28, AF2)
++#define GPIO28_I2S_BITCLK_OUT	MFP_CFG_OUT(GPIO28, AF1, DRIVE_LOW)
++#define GPIO29_I2S_SDATA_IN	MFP_CFG_IN(GPIO29, AF2)
++#define GPIO30_I2S_SDATA_OUT	MFP_CFG_OUT(GPIO30, AF1, DRIVE_LOW)
++#define GPIO31_I2S_SYNC		MFP_CFG_OUT(GPIO31, AF1, DRIVE_LOW)
++#define GPIO113_I2S_SYSCLK	MFP_CFG_OUT(GPIO113, AF1, DRIVE_LOW)
++
++/* SSP 1 */
++#define GPIO23_SSP1_SCLK	MFP_CFG_OUT(GPIO23, AF2, DRIVE_LOW)
++#define GPIO29_SSP1_SCLK	MFP_CFG_IN(GPIO29, AF3)
++#define GPIO27_SSP1_SYSCLK	MFP_CFG_OUT(GPIO27, AF1, DRIVE_LOW)
++#define GPIO53_SSP1_SYSCLK	MFP_CFG_OUT(GPIO53, AF3, DRIVE_LOW)
++#define GPIO24_SSP1_SFRM	MFP_CFG_IN(GPIO24, AF2)
++#define GPIO28_SSP1_SFRM	MFP_CFG_IN(GPIO28, AF3)
++#define GPIO25_SSP1_TXD		MFP_CFG_OUT(GPIO25, AF2, DRIVE_LOW)
++#define GPIO57_SSP1_TXD		MFP_CFG_OUT(GPIO57, AF3, DRIVE_LOW)
++#define GPIO26_SSP1_RXD		MFP_CFG_IN(GPIO26, AF1)
++#define GPIO27_SSP1_SCLKEN	MFP_CFG_IN(GPIO27, AF2)
++
++/* SSP 2 */
++#define GPIO19_SSP2_SCLK	MFP_CFG_IN(GPIO19, AF1)
++#define GPIO22_SSP2_SCLK	MFP_CFG_IN(GPIO22, AF3)
++#define GPIO29_SSP2_SCLK	MFP_CFG_OUT(GPIO29, AF3, DRIVE_LOW)
++#define GPIO36_SSP2_SCLK	MFP_CFG_IN(GPIO36, AF2)
++#define GPIO50_SSP2_SCLK	MFP_CFG_IN(GPIO50, AF3)
++#define GPIO22_SSP2_SYSCLK	MFP_CFG_OUT(GPIO22, AF2, DRIVE_LOW)
++#define GPIO14_SSP2_SFRM	MFP_CFG_IN(GPIO14, AF2)
++#define GPIO37_SSP2_SFRM	MFP_CFG_IN(GPIO37, AF2)
++#define GPIO87_SSP2_SFRM	MFP_CFG_OUT(GPIO87, AF3, DRIVE_LOW)
++#define GPIO88_SSP2_SFRM	MFP_CFG_IN(GPIO88, AF3)
++#define GPIO13_SSP2_TXD		MFP_CFG_OUT(GPIO13, AF1, DRIVE_LOW)
++#define GPIO38_SSP2_TXD		MFP_CFG_OUT(GPIO38, AF2, DRIVE_LOW)
++#define GPIO87_SSP2_TXD		MFP_CFG_OUT(GPIO87, AF1, DRIVE_LOW)
++#define GPIO89_SSP2_TXD		MFP_CFG_OUT(GPIO89, AF3, DRIVE_LOW)
++#define GPIO11_SSP2_RXD		MFP_CFG_IN(GPIO11, AF2)
++#define GPIO29_SSP2_RXD		MFP_CFG_OUT(GPIO29, AF1, DRIVE_LOW)
++#define GPIO40_SSP2_RXD		MFP_CFG_IN(GPIO40, AF1)
++#define GPIO86_SSP2_RXD		MFP_CFG_IN(GPIO86, AF1)
++#define GPIO88_SSP2_RXD		MFP_CFG_IN(GPIO88, AF2)
++#define GPIO22_SSP2_EXTCLK	MFP_CFG_IN(GPIO22, AF1)
++#define GPIO27_SSP2_EXTCLK	MFP_CFG_IN(GPIO27, AF1)
++#define GPIO22_SSP2_SCLKEN	MFP_CFG_IN(GPIO22, AF2)
++#define GPIO23_SSP2_SCLKEN	MFP_CFG_IN(GPIO23, AF2)
++
++/* SSP 3 */
++#define GPIO34_SSP3_SCLK	MFP_CFG_IN(GPIO34, AF3)
++#define GPIO40_SSP3_SCLK	MFP_CFG_OUT(GPIO40, AF3, DRIVE_LOW)
++#define GPIO52_SSP3_SCLK	MFP_CFG_IN(GPIO52, AF2)
++#define GPIO84_SSP3_SCLK	MFP_CFG_IN(GPIO84, AF1)
++#define GPIO45_SSP3_SYSCLK	MFP_CFG_OUT(GPIO45, AF3, DRIVE_LOW)
++#define GPIO35_SSP3_SFRM	MFP_CFG_IN(GPIO35, AF3)
++#define GPIO39_SSP3_SFRM	MFP_CFG_IN(GPIO39, AF3)
++#define GPIO83_SSP3_SFRM	MFP_CFG_IN(GPIO83, AF1)
++#define GPIO35_SSP3_TXD		MFP_CFG_OUT(GPIO35, AF3, DRIVE_LOW)
++#define GPIO38_SSP3_TXD		MFP_CFG_OUT(GPIO38, AF1, DRIVE_LOW)
++#define GPIO81_SSP3_TXD		MFP_CFG_OUT(GPIO81, AF1, DRIVE_LOW)
++#define GPIO41_SSP3_RXD		MFP_CFG_IN(GPIO41, AF3)
++#define GPIO82_SSP3_RXD		MFP_CFG_IN(GPIO82, AF1)
++#define GPIO89_SSP3_RXD		MFP_CFG_IN(GPIO89, AF1)
++
++/* MMC */
++#define GPIO32_MMC_CLK		MFP_CFG_OUT(GPIO32, AF2, DRIVE_LOW)
++#define GPIO92_MMC_DAT_0	MFP_CFG_IN(GPIO92, AF1)
++#define GPIO109_MMC_DAT_1	MFP_CFG_IN(GPIO109, AF1)
++#define GPIO110_MMC_DAT_2	MFP_CFG_IN(GPIO110, AF1)
++#define GPIO111_MMC_DAT_3	MFP_CFG_IN(GPIO111, AF1)
++#define GPIO112_MMC_CMD		MFP_CFG_IN(GPIO112, AF1)
++
++/* LCD */
++#define GPIO58_LCD_LDD_0	MFP_CFG_OUT(GPIO58, AF2, DRIVE_LOW)
++#define GPIO59_LCD_LDD_1	MFP_CFG_OUT(GPIO59, AF2, DRIVE_LOW)
++#define GPIO60_LCD_LDD_2	MFP_CFG_OUT(GPIO60, AF2, DRIVE_LOW)
++#define GPIO61_LCD_LDD_3	MFP_CFG_OUT(GPIO61, AF2, DRIVE_LOW)
++#define GPIO62_LCD_LDD_4	MFP_CFG_OUT(GPIO62, AF2, DRIVE_LOW)
++#define GPIO63_LCD_LDD_5	MFP_CFG_OUT(GPIO63, AF2, DRIVE_LOW)
++#define GPIO64_LCD_LDD_6	MFP_CFG_OUT(GPIO64, AF2, DRIVE_LOW)
++#define GPIO65_LCD_LDD_7	MFP_CFG_OUT(GPIO65, AF2, DRIVE_LOW)
++#define GPIO66_LCD_LDD_8	MFP_CFG_OUT(GPIO66, AF2, DRIVE_LOW)
++#define GPIO67_LCD_LDD_9	MFP_CFG_OUT(GPIO67, AF2, DRIVE_LOW)
++#define GPIO68_LCD_LDD_10	MFP_CFG_OUT(GPIO68, AF2, DRIVE_LOW)
++#define GPIO69_LCD_LDD_11	MFP_CFG_OUT(GPIO69, AF2, DRIVE_LOW)
++#define GPIO70_LCD_LDD_12	MFP_CFG_OUT(GPIO70, AF2, DRIVE_LOW)
++#define GPIO71_LCD_LDD_13	MFP_CFG_OUT(GPIO71, AF2, DRIVE_LOW)
++#define GPIO72_LCD_LDD_14	MFP_CFG_OUT(GPIO72, AF2, DRIVE_LOW)
++#define GPIO73_LCD_LDD_15	MFP_CFG_OUT(GPIO73, AF2, DRIVE_LOW)
++#define GPIO86_LCD_LDD_16	MFP_CFG_OUT(GPIO86, AF2, DRIVE_LOW)
++#define GPIO87_LCD_LDD_17	MFP_CFG_OUT(GPIO87, AF2, DRIVE_LOW)
++#define GPIO74_LCD_FCLK		MFP_CFG_OUT(GPIO74, AF2, DRIVE_LOW)
++#define GPIO75_LCD_LCLK		MFP_CFG_OUT(GPIO75, AF2, DRIVE_LOW)
++#define GPIO76_LCD_PCLK		MFP_CFG_OUT(GPIO76, AF2, DRIVE_LOW)
++#define GPIO77_LCD_BIAS		MFP_CFG_OUT(GPIO77, AF2, DRIVE_LOW)
++#define GPIO14_LCD_VSYNC	MFP_CFG_IN(GPIO14, AF1)
++#define GPIO19_LCD_CS		MFP_CFG_OUT(GPIO19, AF2, DRIVE_LOW)
++
++/* Keypad */
++#define GPIO93_KP_DKIN_0	MFP_CFG_IN(GPIO93, AF1)
++#define GPIO94_KP_DKIN_1	MFP_CFG_IN(GPIO94, AF1)
++#define GPIO95_KP_DKIN_2	MFP_CFG_IN(GPIO95, AF1)
++#define GPIO96_KP_DKIN_3	MFP_CFG_IN(GPIO96, AF1)
++#define GPIO97_KP_DKIN_4	MFP_CFG_IN(GPIO97, AF1)
++#define GPIO98_KP_DKIN_5	MFP_CFG_IN(GPIO98, AF1)
++#define GPIO99_KP_DKIN_6	MFP_CFG_IN(GPIO99, AF1)
++#define GPIO13_KP_KDIN_7	MFP_CFG_IN(GPIO13, AF2)
++#define GPIO100_KP_MKIN_0	MFP_CFG_IN(GPIO100, AF1)
++#define GPIO101_KP_MKIN_1	MFP_CFG_IN(GPIO101, AF1)
++#define GPIO102_KP_MKIN_2	MFP_CFG_IN(GPIO102, AF1)
++#define GPIO34_KP_MKIN_3	MFP_CFG_IN(GPIO34, AF2)
++#define GPIO37_KP_MKIN_3	MFP_CFG_IN(GPIO37, AF3)
++#define GPIO97_KP_MKIN_3	MFP_CFG_IN(GPIO97, AF3)
++#define GPIO98_KP_MKIN_4	MFP_CFG_IN(GPIO98, AF3)
++#define GPIO38_KP_MKIN_4	MFP_CFG_IN(GPIO38, AF2)
++#define GPIO39_KP_MKIN_4	MFP_CFG_IN(GPIO39, AF1)
++#define GPIO16_KP_MKIN_5	MFP_CFG_IN(GPIO16, AF1)
++#define GPIO90_KP_MKIN_5	MFP_CFG_IN(GPIO90, AF1)
++#define GPIO99_KP_MKIN_5	MFP_CFG_IN(GPIO99, AF3)
++#define GPIO17_KP_MKIN_6	MFP_CFG_IN(GPIO17, AF1)
++#define GPIO91_KP_MKIN_6	MFP_CFG_IN(GPIO91, AF1)
++#define GPIO95_KP_MKIN_6	MFP_CFG_IN(GPIO95, AF3)
++#define GPIO13_KP_MKIN_7	MFP_CFG_IN(GPIO13, AF3)
++#define GPIO36_KP_MKIN_7	MFP_CFG_IN(GPIO36, AF3)
++#define GPIO103_KP_MKOUT_0	MFP_CFG_OUT(GPIO103, AF2, DRIVE_HIGH)
++#define GPIO104_KP_MKOUT_1	MFP_CFG_OUT(GPIO104, AF2, DRIVE_HIGH)
++#define GPIO105_KP_MKOUT_2	MFP_CFG_OUT(GPIO105, AF2, DRIVE_HIGH)
++#define GPIO106_KP_MKOUT_3	MFP_CFG_OUT(GPIO106, AF2, DRIVE_HIGH)
++#define GPIO107_KP_MKOUT_4	MFP_CFG_OUT(GPIO107, AF2, DRIVE_HIGH)
++#define GPIO108_KP_MKOUT_5	MFP_CFG_OUT(GPIO108, AF2, DRIVE_HIGH)
++#define GPIO35_KP_MKOUT_6	MFP_CFG_OUT(GPIO35, AF2, DRIVE_HIGH)
++#define GPIO22_KP_MKOUT_7	MFP_CFG_OUT(GPIO22, AF1, DRIVE_HIGH)
++#define GPIO40_KP_MKOUT_6	MFP_CFG_OUT(GPIO40, AF1, DRIVE_HIGH)
++#define GPIO41_KP_MKOUT_7	MFP_CFG_OUT(GPIO41, AF1, DRIVE_HIGH)
++#define GPIO96_KP_MKOUT_6	MFP_CFG_OUT(GPIO96, AF3, DRIVE_HIGH)
++
++/* USB P3 */
++#define GPIO10_USB_P3_5		MFP_CFG_IN(GPIO10, AF3)
++#define GPIO11_USB_P3_1		MFP_CFG_IN(GPIO11, AF3)
++#define GPIO30_USB_P3_2		MFP_CFG_OUT(GPIO30, AF3, DRIVE_LOW)
++#define GPIO31_USB_P3_6		MFP_CFG_OUT(GPIO31, AF3, DRIVE_LOW)
++#define GPIO56_USB_P3_4		MFP_CFG_OUT(GPIO56, AF1, DRIVE_LOW)
++#define GPIO86_USB_P3_5		MFP_CFG_IN(GPIO86, AF3)
++#define GPIO87_USB_P3_1		MFP_CFG_IN(GPIO87, AF3)
++#define GPIO90_USB_P3_5		MFP_CFG_IN(GPIO90, AF2)
++#define GPIO91_USB_P3_1		MFP_CFG_IN(GPIO91, AF2)
++#define GPIO113_USB_P3_3	MFP_CFG_IN(GPIO113, AF3)
++
++/* USB P2 */
++#define GPIO34_USB_P2_2		MFP_CFG_OUT(GPIO34, AF1, DRIVE_LOW)
++#define GPIO35_USB_P2_1		MFP_CFG_IN(GPIO35, AF2)
++#define GPIO36_USB_P2_4		MFP_CFG_OUT(GPIO36, AF1, DRIVE_LOW)
++#define GPIO37_USB_P2_8		MFP_CFG_OUT(GPIO37, AF1, DRIVE_LOW)
++#define GPIO38_USB_P2_3		MFP_CFG_IN(GPIO38, AF3)
++#define GPIO39_USB_P2_6		MFP_CFG_OUT(GPIO39, AF1, DRIVE_LOW)
++#define GPIO40_USB_P2_5		MFP_CFG_IN(GPIO40, AF3)
++#define GPIO41_USB_P2_7		MFP_CFG_IN(GPIO41, AF2)
++#define GPIO53_USB_P2_3		MFP_CFG_IN(GPIO53, AF2)
++
++/* USB Host Port 1/2 */
++#define GPIO88_USBH1_PWR	MFP_CFG_IN(GPIO88, AF1)
++#define GPIO89_USBH1_PEN	MFP_CFG_OUT(GPIO89, AF2, DRIVE_LOW)
++#define GPIO119_USBH2_PWR	MFP_CFG_IN(GPIO119, AF1)
++#define GPIO120_USBH2_PEN	MFP_CFG_OUT(GPIO120, AF2, DRIVE_LOW)
++
++/* QCI - default to Master Mode: CIF_FV/CIF_LV Direction In */
++#define GPIO115_CIF_DD_3	MFP_CFG_IN(GPIO115, AF2)
++#define GPIO116_CIF_DD_2	MFP_CFG_IN(GPIO116, AF1)
++#define GPIO12_CIF_DD_7		MFP_CFG_IN(GPIO12, AF2)
++#define GPIO17_CIF_DD_6		MFP_CFG_IN(GPIO17, AF2)
++#define GPIO23_CIF_MCLK		MFP_CFG_OUT(GPIO23, AF1, DRIVE_LOW)
++#define GPIO24_CIF_FV		MFP_CFG_IN(GPIO24, AF1)
++#define GPIO25_CIF_LV		MFP_CFG_IN(GPIO25, AF1)
++#define GPIO26_CIF_PCLK		MFP_CFG_IN(GPIO26, AF2)
++#define GPIO27_CIF_DD_0		MFP_CFG_IN(GPIO27, AF3)
++#define GPIO42_CIF_MCLK		MFP_CFG_OUT(GPIO42, AF3, DRIVE_LOW)
++#define GPIO43_CIF_FV		MFP_CFG_IN(GPIO43, AF3)
++#define GPIO44_CIF_LV		MFP_CFG_IN(GPIO44, AF3)
++#define GPIO45_CIF_PCLK		MFP_CFG_IN(GPIO45, AF3)
++#define GPIO47_CIF_DD_0		MFP_CFG_IN(GPIO47, AF1)
++#define GPIO48_CIF_DD_5		MFP_CFG_IN(GPIO48, AF1)
++#define GPIO50_CIF_DD_3		MFP_CFG_IN(GPIO50, AF1)
++#define GPIO51_CIF_DD_2		MFP_CFG_IN(GPIO51, AF1)
++#define GPIO52_CIF_DD_4		MFP_CFG_IN(GPIO52, AF1)
++#define GPIO53_CIF_MCLK		MFP_CFG_OUT(GPIO53, AF2, DRIVE_LOW)
++#define GPIO54_CIF_PCLK		MFP_CFG_IN(GPIO54, AF3)
++#define GPIO55_CIF_DD_1		MFP_CFG_IN(GPIO55, AF1)
++#define GPIO81_CIF_DD_0		MFP_CFG_IN(GPIO81, AF2)
++#define GPIO82_CIF_DD_5		MFP_CFG_IN(GPIO82, AF3)
++#define GPIO83_CIF_DD_4		MFP_CFG_IN(GPIO83, AF3)
++#define GPIO84_CIF_FV		MFP_CFG_IN(GPIO84, AF3)
++#define GPIO85_CIF_LV		MFP_CFG_IN(GPIO85, AF3)
++#define GPIO90_CIF_DD_4		MFP_CFG_IN(GPIO90, AF3)
++#define GPIO91_CIF_DD_5		MFP_CFG_IN(GPIO91, AF3)
++#define GPIO93_CIF_DD_6		MFP_CFG_IN(GPIO93, AF2)
++#define GPIO94_CIF_DD_5		MFP_CFG_IN(GPIO94, AF2)
++#define GPIO95_CIF_DD_4		MFP_CFG_IN(GPIO95, AF2)
++#define GPIO98_CIF_DD_0		MFP_CFG_IN(GPIO98, AF2)
++#define GPIO103_CIF_DD_3	MFP_CFG_IN(GPIO103, AF1)
++#define GPIO104_CIF_DD_2	MFP_CFG_IN(GPIO104, AF1)
++#define GPIO105_CIF_DD_1	MFP_CFG_IN(GPIO105, AF1)
++#define GPIO106_CIF_DD_9	MFP_CFG_IN(GPIO106, AF1)
++#define GPIO107_CIF_DD_8	MFP_CFG_IN(GPIO107, AF1)
++#define GPIO108_CIF_DD_7	MFP_CFG_IN(GPIO108, AF1)
++#define GPIO114_CIF_DD_1	MFP_CFG_IN(GPIO114, AF1)
++
++/* Universal Subscriber ID Interface */
++#define GPIO114_UVS0		MFP_CFG_OUT(GPIO114, AF2, DRIVE_LOW)
++#define GPIO115_nUVS1		MFP_CFG_OUT(GPIO115, AF2, DRIVE_LOW)
++#define GPIO116_nUVS2		MFP_CFG_OUT(GPIO116, AF2, DRIVE_LOW)
++#define GPIO14_UCLK		MFP_CFG_OUT(GPIO14, AF3, DRIVE_LOW)
++#define GPIO91_UCLK		MFP_CFG_OUT(GPIO91, AF2, DRIVE_LOW)
++#define GPIO19_nURST		MFP_CFG_OUT(GPIO19, AF3, DRIVE_LOW)
++#define GPIO90_nURST		MFP_CFG_OUT(GPIO90, AF2, DRIVE_LOW)
++#define GPIO116_UDET		MFP_CFG_IN(GPIO116, AF3)
++#define GPIO114_UEN		MFP_CFG_OUT(GPIO114, AF1, DRIVE_LOW)
++#define GPIO115_UEN		MFP_CFG_OUT(GPIO115, AF1, DRIVE_LOW)
++
++/* Mobile Scalable Link (MSL) Interface */
++#define GPIO81_BB_OB_DAT_0	MFP_CFG_OUT(GPIO81, AF2, DRIVE_LOW)
++#define GPIO48_BB_OB_DAT_1	MFP_CFG_OUT(GPIO48, AF1, DRIVE_LOW)
++#define GPIO50_BB_OB_DAT_2	MFP_CFG_OUT(GPIO50, AF1, DRIVE_LOW)
++#define GPIO51_BB_OB_DAT_3	MFP_CFG_OUT(GPIO51, AF1, DRIVE_LOW)
++#define GPIO52_BB_OB_CLK	MFP_CFG_OUT(GPIO52, AF1, DRIVE_LOW)
++#define GPIO53_BB_OB_STB	MFP_CFG_OUT(GPIO53, AF1, DRIVE_LOW)
++#define GPIO54_BB_OB_WAIT	MFP_CFG_IN(GPIO54, AF2)
++#define GPIO82_BB_IB_DAT_0	MFP_CFG_IN(GPIO82, AF2)
++#define GPIO55_BB_IB_DAT_1	MFP_CFG_IN(GPIO55, AF2)
++#define GPIO56_BB_IB_DAT_2	MFP_CFG_IN(GPIO56, AF2)
++#define GPIO57_BB_IB_DAT_3	MFP_CFG_IN(GPIO57, AF2)
++#define GPIO83_BB_IB_CLK	MFP_CFG_IN(GPIO83, AF2)
++#define GPIO84_BB_IB_STB	MFP_CFG_IN(GPIO84, AF2)
++#define GPIO85_BB_IB_WAIT	MFP_CFG_OUT(GPIO85, AF2, DRIVE_LOW)
++
++/* Memory Stick Host Controller */
++#define GPIO92_MSBS		MFP_CFG_OUT(GPIO92, AF2, DRIVE_LOW)
++#define GPIO109_MSSDIO		MFP_CFG_IN(GPIO109, AF2)
++#define GPIO112_nMSINS		MFP_CFG_IN(GPIO112, AF2)
++#define GPIO32_MSSCLK		MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW)
++
++extern int keypad_set_wake(unsigned int on);
++#endif /* __ASM_ARCH_MFP_PXA27X_H */
+diff --git a/include/asm-arm/arch-pxa/mfp-pxa2xx.h b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
+new file mode 100644
+index 0000000..db8d890
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
+@@ -0,0 +1,132 @@
++#ifndef __ASM_ARCH_MFP_PXA2XX_H
++#define __ASM_ARCH_MFP_PXA2XX_H
++
++#include <asm/arch/mfp.h>
++
++/*
++ * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx:
++ *
++ *  MFP_PIN(x)
++ *  MFP_AFx
++ *  MFP_LPM_DRIVE_{LOW, HIGH}
++ *  MFP_LPM_EDGE_x
++ *
++ * other MFP_x bit definitions will be ignored
++ *
++ * and adds the below two bits specifically for pxa2xx:
++ *
++ * bit     23 - Input/Output (PXA2xx specific)
++ * bit     24 - Wakeup Enable(PXA2xx specific)
++ */
++
++#define MFP_DIR_IN		(0x0 << 23)
++#define MFP_DIR_OUT		(0x1 << 23)
++#define MFP_DIR_MASK		(0x1 << 23)
++#define MFP_DIR(x)		(((x) >> 23) & 0x1)
++
++#define MFP_LPM_CAN_WAKEUP	(0x1 << 24)
++#define WAKEUP_ON_EDGE_RISE	(MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE)
++#define WAKEUP_ON_EDGE_FALL	(MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_FALL)
++#define WAKEUP_ON_EDGE_BOTH	(MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_BOTH)
++
++/* specifically for enabling wakeup on keypad GPIOs */
++#define WAKEUP_ON_LEVEL_HIGH	(MFP_LPM_CAN_WAKEUP)
++
++#define MFP_CFG_IN(pin, af)		\
++	((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK)) |\
++	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DIR_IN))
++
++/* NOTE:  pins configured as output _must_ provide a low power state,
++ * and this state should help to minimize the power dissipation.
++ */
++#define MFP_CFG_OUT(pin, af, state)	\
++	((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK | MFP_LPM_STATE_MASK)) |\
++	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DIR_OUT | MFP_LPM_##state))
++
++/* Common configurations for pxa25x and pxa27x
++ *
++ * Note: pins configured as GPIO are always initialized to input
++ * so not to cause any side effect
++ */
++#define GPIO0_GPIO	MFP_CFG_IN(GPIO0, AF0)
++#define GPIO1_GPIO	MFP_CFG_IN(GPIO1, AF0)
++#define GPIO9_GPIO	MFP_CFG_IN(GPIO9, AF0)
++#define GPIO10_GPIO	MFP_CFG_IN(GPIO10, AF0)
++#define GPIO11_GPIO	MFP_CFG_IN(GPIO11, AF0)
++#define GPIO12_GPIO	MFP_CFG_IN(GPIO12, AF0)
++#define GPIO13_GPIO	MFP_CFG_IN(GPIO13, AF0)
++#define GPIO14_GPIO	MFP_CFG_IN(GPIO14, AF0)
++#define GPIO15_GPIO	MFP_CFG_IN(GPIO15, AF0)
++#define GPIO16_GPIO	MFP_CFG_IN(GPIO16, AF0)
++#define GPIO17_GPIO	MFP_CFG_IN(GPIO17, AF0)
++#define GPIO18_GPIO	MFP_CFG_IN(GPIO18, AF0)
++#define GPIO19_GPIO	MFP_CFG_IN(GPIO19, AF0)
++#define GPIO20_GPIO	MFP_CFG_IN(GPIO20, AF0)
++#define GPIO21_GPIO	MFP_CFG_IN(GPIO21, AF0)
++#define GPIO22_GPIO	MFP_CFG_IN(GPIO22, AF0)
++#define GPIO23_GPIO	MFP_CFG_IN(GPIO23, AF0)
++#define GPIO24_GPIO	MFP_CFG_IN(GPIO24, AF0)
++#define GPIO25_GPIO	MFP_CFG_IN(GPIO25, AF0)
++#define GPIO26_GPIO	MFP_CFG_IN(GPIO26, AF0)
++#define GPIO27_GPIO	MFP_CFG_IN(GPIO27, AF0)
++#define GPIO28_GPIO	MFP_CFG_IN(GPIO28, AF0)
++#define GPIO29_GPIO	MFP_CFG_IN(GPIO29, AF0)
++#define GPIO30_GPIO	MFP_CFG_IN(GPIO30, AF0)
++#define GPIO31_GPIO	MFP_CFG_IN(GPIO31, AF0)
++#define GPIO32_GPIO	MFP_CFG_IN(GPIO32, AF0)
++#define GPIO33_GPIO	MFP_CFG_IN(GPIO33, AF0)
++#define GPIO34_GPIO	MFP_CFG_IN(GPIO34, AF0)
++#define GPIO35_GPIO	MFP_CFG_IN(GPIO35, AF0)
++#define GPIO36_GPIO	MFP_CFG_IN(GPIO36, AF0)
++#define GPIO37_GPIO	MFP_CFG_IN(GPIO37, AF0)
++#define GPIO38_GPIO	MFP_CFG_IN(GPIO38, AF0)
++#define GPIO39_GPIO	MFP_CFG_IN(GPIO39, AF0)
++#define GPIO40_GPIO	MFP_CFG_IN(GPIO40, AF0)
++#define GPIO41_GPIO	MFP_CFG_IN(GPIO41, AF0)
++#define GPIO42_GPIO	MFP_CFG_IN(GPIO42, AF0)
++#define GPIO43_GPIO	MFP_CFG_IN(GPIO43, AF0)
++#define GPIO44_GPIO	MFP_CFG_IN(GPIO44, AF0)
++#define GPIO45_GPIO	MFP_CFG_IN(GPIO45, AF0)
++#define GPIO46_GPIO	MFP_CFG_IN(GPIO46, AF0)
++#define GPIO47_GPIO	MFP_CFG_IN(GPIO47, AF0)
++#define GPIO48_GPIO	MFP_CFG_IN(GPIO48, AF0)
++#define GPIO49_GPIO	MFP_CFG_IN(GPIO49, AF0)
++#define GPIO50_GPIO	MFP_CFG_IN(GPIO50, AF0)
++#define GPIO51_GPIO	MFP_CFG_IN(GPIO51, AF0)
++#define GPIO52_GPIO	MFP_CFG_IN(GPIO52, AF0)
++#define GPIO53_GPIO	MFP_CFG_IN(GPIO53, AF0)
++#define GPIO54_GPIO	MFP_CFG_IN(GPIO54, AF0)
++#define GPIO55_GPIO	MFP_CFG_IN(GPIO55, AF0)
++#define GPIO56_GPIO	MFP_CFG_IN(GPIO56, AF0)
++#define GPIO57_GPIO	MFP_CFG_IN(GPIO57, AF0)
++#define GPIO58_GPIO	MFP_CFG_IN(GPIO58, AF0)
++#define GPIO59_GPIO	MFP_CFG_IN(GPIO59, AF0)
++#define GPIO60_GPIO	MFP_CFG_IN(GPIO60, AF0)
++#define GPIO61_GPIO	MFP_CFG_IN(GPIO61, AF0)
++#define GPIO62_GPIO	MFP_CFG_IN(GPIO62, AF0)
++#define GPIO63_GPIO	MFP_CFG_IN(GPIO63, AF0)
++#define GPIO64_GPIO	MFP_CFG_IN(GPIO64, AF0)
++#define GPIO65_GPIO	MFP_CFG_IN(GPIO65, AF0)
++#define GPIO66_GPIO	MFP_CFG_IN(GPIO66, AF0)
++#define GPIO67_GPIO	MFP_CFG_IN(GPIO67, AF0)
++#define GPIO68_GPIO	MFP_CFG_IN(GPIO68, AF0)
++#define GPIO69_GPIO	MFP_CFG_IN(GPIO69, AF0)
++#define GPIO70_GPIO	MFP_CFG_IN(GPIO70, AF0)
++#define GPIO71_GPIO	MFP_CFG_IN(GPIO71, AF0)
++#define GPIO72_GPIO	MFP_CFG_IN(GPIO72, AF0)
++#define GPIO73_GPIO	MFP_CFG_IN(GPIO73, AF0)
++#define GPIO74_GPIO	MFP_CFG_IN(GPIO74, AF0)
++#define GPIO75_GPIO	MFP_CFG_IN(GPIO75, AF0)
++#define GPIO76_GPIO	MFP_CFG_IN(GPIO76, AF0)
++#define GPIO77_GPIO	MFP_CFG_IN(GPIO77, AF0)
++#define GPIO78_GPIO	MFP_CFG_IN(GPIO78, AF0)
++#define GPIO79_GPIO	MFP_CFG_IN(GPIO79, AF0)
++#define GPIO80_GPIO	MFP_CFG_IN(GPIO80, AF0)
++#define GPIO81_GPIO	MFP_CFG_IN(GPIO81, AF0)
++#define GPIO82_GPIO	MFP_CFG_IN(GPIO82, AF0)
++#define GPIO83_GPIO	MFP_CFG_IN(GPIO83, AF0)
++#define GPIO84_GPIO	MFP_CFG_IN(GPIO84, AF0)
++
++extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num);
++extern int gpio_set_wake(unsigned int gpio, unsigned int on);
++#endif /* __ASM_ARCH_MFP_PXA2XX_H */
+diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
+index 2357a73..a322012 100644
+--- a/include/asm-arm/arch-pxa/pxa-regs.h
++++ b/include/asm-arm/arch-pxa/pxa-regs.h
+@@ -1129,6 +1129,11 @@
+ #define ICPR		__REG(0x40D00010)  /* Interrupt Controller Pending Register */
+ #define ICCR		__REG(0x40D00014)  /* Interrupt Controller Control Register */
+ 
++#define ICIP2		__REG(0x40D0009C)  /* Interrupt Controller IRQ Pending Register 2 */
++#define ICMR2		__REG(0x40D000A0)  /* Interrupt Controller Mask Register 2 */
++#define ICLR2		__REG(0x40D000A4)  /* Interrupt Controller Level Register 2 */
++#define ICFP2		__REG(0x40D000A8)  /* Interrupt Controller FIQ Pending Register 2 */
++#define ICPR2		__REG(0x40D000AC)  /* Interrupt Controller Pending Register 2 */
+ 
+ /*
+  * General Purpose I/O
+@@ -1200,12 +1205,6 @@
+ 
+ /* Interrupt Controller */
+ 
+-#define ICIP2		__REG(0x40D0009C)  /* Interrupt Controller IRQ Pending Register 2 */
+-#define ICMR2		__REG(0x40D000A0)  /* Interrupt Controller Mask Register 2 */
+-#define ICLR2		__REG(0x40D000A4)  /* Interrupt Controller Level Register 2 */
+-#define ICFP2		__REG(0x40D000A8)  /* Interrupt Controller FIQ Pending Register 2 */
+-#define ICPR2		__REG(0x40D000AC)  /* Interrupt Controller Pending Register 2 */
+-
+ #define _GPLR(x)	__REG2(0x40E00000, ((x) & 0x60) >> 3)
+ #define _GPDR(x)	__REG2(0x40E0000C, ((x) & 0x60) >> 3)
+ #define _GPSR(x)	__REG2(0x40E00018, ((x) & 0x60) >> 3)
+@@ -1237,267 +1236,6 @@
+ 
+ #endif
+ 
+-
+-/* GPIO alternate function assignments */
+-
+-#define GPIO1_RST		1	/* reset */
+-#define GPIO6_MMCCLK		6	/* MMC Clock */
+-#define GPIO7_48MHz		7	/* 48 MHz clock output */
+-#define GPIO8_MMCCS0		8	/* MMC Chip Select 0 */
+-#define GPIO9_MMCCS1		9	/* MMC Chip Select 1 */
+-#define GPIO10_RTCCLK		10	/* real time clock (1 Hz) */
+-#define GPIO11_3_6MHz		11	/* 3.6 MHz oscillator out */
+-#define GPIO12_32KHz		12	/* 32 kHz out */
+-#define GPIO13_MBGNT		13	/* memory controller grant */
+-#define GPIO14_MBREQ		14	/* alternate bus master request */
+-#define GPIO15_nCS_1		15	/* chip select 1 */
+-#define GPIO16_PWM0		16	/* PWM0 output */
+-#define GPIO17_PWM1		17	/* PWM1 output */
+-#define GPIO18_RDY		18	/* Ext. Bus Ready */
+-#define GPIO19_DREQ1		19	/* External DMA Request */
+-#define GPIO20_DREQ0		20	/* External DMA Request */
+-#define GPIO23_SCLK		23	/* SSP clock */
+-#define GPIO24_SFRM		24	/* SSP Frame */
+-#define GPIO25_STXD		25	/* SSP transmit */
+-#define GPIO26_SRXD		26	/* SSP receive */
+-#define GPIO27_SEXTCLK		27	/* SSP ext_clk */
+-#define GPIO28_BITCLK		28	/* AC97/I2S bit_clk */
+-#define GPIO29_SDATA_IN		29	/* AC97 Sdata_in0 / I2S Sdata_in */
+-#define GPIO30_SDATA_OUT	30	/* AC97/I2S Sdata_out */
+-#define GPIO31_SYNC		31	/* AC97/I2S sync */
+-#define GPIO32_SDATA_IN1	32	/* AC97 Sdata_in1 */
+-#define GPIO32_SYSCLK		32	/* I2S System Clock */
+-#define GPIO32_MMCCLK		32	/* MMC Clock (PXA270) */
+-#define GPIO33_nCS_5		33	/* chip select 5 */
+-#define GPIO34_FFRXD		34	/* FFUART receive */
+-#define GPIO34_MMCCS0		34	/* MMC Chip Select 0 */
+-#define GPIO35_FFCTS		35	/* FFUART Clear to send */
+-#define GPIO36_FFDCD		36	/* FFUART Data carrier detect */
+-#define GPIO37_FFDSR		37	/* FFUART data set ready */
+-#define GPIO38_FFRI		38	/* FFUART Ring Indicator */
+-#define GPIO39_MMCCS1		39	/* MMC Chip Select 1 */
+-#define GPIO39_FFTXD		39	/* FFUART transmit data */
+-#define GPIO40_FFDTR		40	/* FFUART data terminal Ready */
+-#define GPIO41_FFRTS		41	/* FFUART request to send */
+-#define GPIO42_BTRXD		42	/* BTUART receive data */
+-#define GPIO42_HWRXD		42	/* HWUART receive data */
+-#define GPIO43_BTTXD		43	/* BTUART transmit data */
+-#define GPIO43_HWTXD		43	/* HWUART transmit data */
+-#define GPIO44_BTCTS		44	/* BTUART clear to send */
+-#define GPIO44_HWCTS		44	/* HWUART clear to send */
+-#define GPIO45_BTRTS		45	/* BTUART request to send */
+-#define GPIO45_HWRTS		45	/* HWUART request to send */
+-#define GPIO45_AC97_SYSCLK	45	/* AC97 System Clock */
+-#define GPIO46_ICPRXD		46	/* ICP receive data */
+-#define GPIO46_STRXD		46	/* STD_UART receive data */
+-#define GPIO47_ICPTXD		47	/* ICP transmit data */
+-#define GPIO47_STTXD		47	/* STD_UART transmit data */
+-#define GPIO48_nPOE		48	/* Output Enable for Card Space */
+-#define GPIO49_nPWE		49	/* Write Enable for Card Space */
+-#define GPIO50_nPIOR		50	/* I/O Read for Card Space */
+-#define GPIO51_nPIOW		51	/* I/O Write for Card Space */
+-#define GPIO52_nPCE_1		52	/* Card Enable for Card Space */
+-#define GPIO53_nPCE_2		53	/* Card Enable for Card Space */
+-#define GPIO53_MMCCLK		53	/* MMC Clock */
+-#define GPIO54_MMCCLK		54	/* MMC Clock */
+-#define GPIO54_pSKTSEL		54	/* Socket Select for Card Space */
+-#define GPIO54_nPCE_2		54	/* Card Enable for Card Space (PXA27x) */
+-#define GPIO55_nPREG		55	/* Card Address bit 26 */
+-#define GPIO56_nPWAIT		56	/* Wait signal for Card Space */
+-#define GPIO57_nIOIS16		57	/* Bus Width select for I/O Card Space */
+-#define GPIO58_LDD_0		58	/* LCD data pin 0 */
+-#define GPIO59_LDD_1		59	/* LCD data pin 1 */
+-#define GPIO60_LDD_2		60	/* LCD data pin 2 */
+-#define GPIO61_LDD_3		61	/* LCD data pin 3 */
+-#define GPIO62_LDD_4		62	/* LCD data pin 4 */
+-#define GPIO63_LDD_5		63	/* LCD data pin 5 */
+-#define GPIO64_LDD_6		64	/* LCD data pin 6 */
+-#define GPIO65_LDD_7		65	/* LCD data pin 7 */
+-#define GPIO66_LDD_8		66	/* LCD data pin 8 */
+-#define GPIO66_MBREQ		66	/* alternate bus master req */
+-#define GPIO67_LDD_9		67	/* LCD data pin 9 */
+-#define GPIO67_MMCCS0		67	/* MMC Chip Select 0 */
+-#define GPIO68_LDD_10		68	/* LCD data pin 10 */
+-#define GPIO68_MMCCS1		68	/* MMC Chip Select 1 */
+-#define GPIO69_LDD_11		69	/* LCD data pin 11 */
+-#define GPIO69_MMCCLK		69	/* MMC_CLK */
+-#define GPIO70_LDD_12		70	/* LCD data pin 12 */
+-#define GPIO70_RTCCLK		70	/* Real Time clock (1 Hz) */
+-#define GPIO71_LDD_13		71	/* LCD data pin 13 */
+-#define GPIO71_3_6MHz		71	/* 3.6 MHz Oscillator clock */
+-#define GPIO72_LDD_14		72	/* LCD data pin 14 */
+-#define GPIO72_32kHz		72	/* 32 kHz clock */
+-#define GPIO73_LDD_15		73	/* LCD data pin 15 */
+-#define GPIO73_MBGNT		73	/* Memory controller grant */
+-#define GPIO74_LCD_FCLK		74	/* LCD Frame clock */
+-#define GPIO75_LCD_LCLK		75	/* LCD line clock */
+-#define GPIO76_LCD_PCLK		76	/* LCD Pixel clock */
+-#define GPIO77_LCD_ACBIAS	77	/* LCD AC Bias */
+-#define GPIO78_nCS_2		78	/* chip select 2 */
+-#define GPIO79_nCS_3		79	/* chip select 3 */
+-#define GPIO80_nCS_4		80	/* chip select 4 */
+-#define GPIO81_NSCLK		81	/* NSSP clock */
+-#define GPIO82_NSFRM		82	/* NSSP Frame */
+-#define GPIO83_NSTXD		83	/* NSSP transmit */
+-#define GPIO84_NSRXD		84	/* NSSP receive */
+-#define GPIO85_nPCE_1		85	/* Card Enable for Card Space (PXA27x) */
+-#define GPIO92_MMCDAT0		92	/* MMC DAT0 (PXA27x) */
+-#define GPIO102_nPCE_1		102	/* PCMCIA (PXA27x) */
+-#define GPIO109_MMCDAT1		109	/* MMC DAT1 (PXA27x) */
+-#define GPIO110_MMCDAT2		110	/* MMC DAT2 (PXA27x) */
+-#define GPIO110_MMCCS0		110	/* MMC Chip Select 0 (PXA27x) */
+-#define GPIO111_MMCDAT3		111	/* MMC DAT3 (PXA27x) */
+-#define GPIO111_MMCCS1		111	/* MMC Chip Select 1 (PXA27x) */
+-#define GPIO112_MMCCMD		112	/* MMC CMD (PXA27x) */
+-#define GPIO113_I2S_SYSCLK	113	/* I2S System Clock (PXA27x) */
+-#define GPIO113_AC97_RESET_N	113	/* AC97 NRESET on (PXA27x) */
+-
+-/* GPIO alternate function mode & direction */
+-
+-#define GPIO_IN			0x000
+-#define GPIO_OUT		0x080
+-#define GPIO_ALT_FN_1_IN	0x100
+-#define GPIO_ALT_FN_1_OUT	0x180
+-#define GPIO_ALT_FN_2_IN	0x200
+-#define GPIO_ALT_FN_2_OUT	0x280
+-#define GPIO_ALT_FN_3_IN	0x300
+-#define GPIO_ALT_FN_3_OUT	0x380
+-#define GPIO_MD_MASK_NR		0x07f
+-#define GPIO_MD_MASK_DIR	0x080
+-#define GPIO_MD_MASK_FN		0x300
+-#define GPIO_DFLT_LOW		0x400
+-#define GPIO_DFLT_HIGH		0x800
+-
+-#define GPIO1_RTS_MD		( 1 | GPIO_ALT_FN_1_IN)
+-#define GPIO6_MMCCLK_MD		( 6 | GPIO_ALT_FN_1_OUT)
+-#define GPIO7_48MHz_MD		( 7 | GPIO_ALT_FN_1_OUT)
+-#define GPIO8_MMCCS0_MD		( 8 | GPIO_ALT_FN_1_OUT)
+-#define GPIO9_MMCCS1_MD		( 9 | GPIO_ALT_FN_1_OUT)
+-#define GPIO10_RTCCLK_MD	(10 | GPIO_ALT_FN_1_OUT)
+-#define GPIO11_3_6MHz_MD	(11 | GPIO_ALT_FN_1_OUT)
+-#define GPIO12_32KHz_MD		(12 | GPIO_ALT_FN_1_OUT)
+-#define GPIO13_MBGNT_MD		(13 | GPIO_ALT_FN_2_OUT)
+-#define GPIO14_MBREQ_MD		(14 | GPIO_ALT_FN_1_IN)
+-#define GPIO15_nCS_1_MD		(15 | GPIO_ALT_FN_2_OUT)
+-#define GPIO16_PWM0_MD		(16 | GPIO_ALT_FN_2_OUT)
+-#define GPIO17_PWM1_MD		(17 | GPIO_ALT_FN_2_OUT)
+-#define GPIO18_RDY_MD		(18 | GPIO_ALT_FN_1_IN)
+-#define GPIO19_DREQ1_MD		(19 | GPIO_ALT_FN_1_IN)
+-#define GPIO20_DREQ0_MD		(20 | GPIO_ALT_FN_1_IN)
+-#define GPIO23_SCLK_MD		(23 | GPIO_ALT_FN_2_OUT)
+-#define GPIO24_SFRM_MD		(24 | GPIO_ALT_FN_2_OUT)
+-#define GPIO25_STXD_MD		(25 | GPIO_ALT_FN_2_OUT)
+-#define GPIO26_SRXD_MD		(26 | GPIO_ALT_FN_1_IN)
+-#define GPIO27_SEXTCLK_MD	(27 | GPIO_ALT_FN_1_IN)
+-#define GPIO28_BITCLK_AC97_MD	(28 | GPIO_ALT_FN_1_IN)
+-#define GPIO28_BITCLK_IN_I2S_MD	(28 | GPIO_ALT_FN_2_IN)
+-#define GPIO28_BITCLK_OUT_I2S_MD	(28 | GPIO_ALT_FN_1_OUT)
+-#define GPIO29_SDATA_IN_AC97_MD	(29 | GPIO_ALT_FN_1_IN)
+-#define GPIO29_SDATA_IN_I2S_MD	(29 | GPIO_ALT_FN_2_IN)
+-#define GPIO30_SDATA_OUT_AC97_MD	(30 | GPIO_ALT_FN_2_OUT)
+-#define GPIO30_SDATA_OUT_I2S_MD	(30 | GPIO_ALT_FN_1_OUT)
+-#define GPIO31_SYNC_I2S_MD	(31 | GPIO_ALT_FN_1_OUT)
+-#define GPIO31_SYNC_AC97_MD	(31 | GPIO_ALT_FN_2_OUT)
+-#define GPIO32_SDATA_IN1_AC97_MD	(32 | GPIO_ALT_FN_1_IN)
+-#define GPIO32_SYSCLK_I2S_MD	(32 | GPIO_ALT_FN_1_OUT)
+-#define GPIO32_MMCCLK_MD		( 32 | GPIO_ALT_FN_2_OUT)
+-#define GPIO33_nCS_5_MD		(33 | GPIO_ALT_FN_2_OUT)
+-#define GPIO34_FFRXD_MD		(34 | GPIO_ALT_FN_1_IN)
+-#define GPIO34_MMCCS0_MD	(34 | GPIO_ALT_FN_2_OUT)
+-#define GPIO35_FFCTS_MD		(35 | GPIO_ALT_FN_1_IN)
+-#define GPIO36_FFDCD_MD		(36 | GPIO_ALT_FN_1_IN)
+-#define GPIO37_FFDSR_MD		(37 | GPIO_ALT_FN_1_IN)
+-#define GPIO38_FFRI_MD		(38 | GPIO_ALT_FN_1_IN)
+-#define GPIO39_MMCCS1_MD	(39 | GPIO_ALT_FN_1_OUT)
+-#define GPIO39_FFTXD_MD		(39 | GPIO_ALT_FN_2_OUT)
+-#define GPIO40_FFDTR_MD		(40 | GPIO_ALT_FN_2_OUT)
+-#define GPIO41_FFRTS_MD		(41 | GPIO_ALT_FN_2_OUT)
+-#define GPIO42_BTRXD_MD		(42 | GPIO_ALT_FN_1_IN)
+-#define GPIO42_HWRXD_MD		(42 | GPIO_ALT_FN_3_IN)
+-#define GPIO43_BTTXD_MD		(43 | GPIO_ALT_FN_2_OUT)
+-#define GPIO43_HWTXD_MD		(43 | GPIO_ALT_FN_3_OUT)
+-#define GPIO44_BTCTS_MD		(44 | GPIO_ALT_FN_1_IN)
+-#define GPIO44_HWCTS_MD		(44 | GPIO_ALT_FN_3_IN)
+-#define GPIO45_BTRTS_MD		(45 | GPIO_ALT_FN_2_OUT)
+-#define GPIO45_HWRTS_MD		(45 | GPIO_ALT_FN_3_OUT)
+-#define GPIO45_SYSCLK_AC97_MD		(45 | GPIO_ALT_FN_1_OUT)
+-#define GPIO46_ICPRXD_MD	(46 | GPIO_ALT_FN_1_IN)
+-#define GPIO46_STRXD_MD		(46 | GPIO_ALT_FN_2_IN)
+-#define GPIO47_ICPTXD_MD	(47 | GPIO_ALT_FN_2_OUT)
+-#define GPIO47_STTXD_MD		(47 | GPIO_ALT_FN_1_OUT)
+-#define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
+-#define GPIO48_HWTXD_MD         (48 | GPIO_ALT_FN_1_OUT)
+-#define GPIO48_nPOE_MD          (48 | GPIO_ALT_FN_2_OUT)
+-#define GPIO49_HWRXD_MD		(49 | GPIO_ALT_FN_1_IN)
+-#define GPIO49_nPWE_MD		(49 | GPIO_ALT_FN_2_OUT)
+-#define GPIO50_nPIOR_MD		(50 | GPIO_ALT_FN_2_OUT)
+-#define GPIO50_HWCTS_MD         (50 | GPIO_ALT_FN_1_IN)
+-#define GPIO51_HWRTS_MD         (51 | GPIO_ALT_FN_1_OUT)
+-#define GPIO51_nPIOW_MD		(51 | GPIO_ALT_FN_2_OUT)
+-#define GPIO52_nPCE_1_MD	(52 | GPIO_ALT_FN_2_OUT)
+-#define GPIO53_nPCE_2_MD	(53 | GPIO_ALT_FN_2_OUT)
+-#define GPIO53_MMCCLK_MD	(53 | GPIO_ALT_FN_1_OUT)
+-#define GPIO54_MMCCLK_MD	(54 | GPIO_ALT_FN_1_OUT)
+-#define GPIO54_nPCE_2_MD	(54 | GPIO_ALT_FN_2_OUT)
+-#define GPIO54_pSKTSEL_MD	(54 | GPIO_ALT_FN_2_OUT)
+-#define GPIO55_nPREG_MD		(55 | GPIO_ALT_FN_2_OUT)
+-#define GPIO56_nPWAIT_MD	(56 | GPIO_ALT_FN_1_IN)
+-#define GPIO57_nIOIS16_MD	(57 | GPIO_ALT_FN_1_IN)
+-#define GPIO58_LDD_0_MD		(58 | GPIO_ALT_FN_2_OUT)
+-#define GPIO59_LDD_1_MD		(59 | GPIO_ALT_FN_2_OUT)
+-#define GPIO60_LDD_2_MD		(60 | GPIO_ALT_FN_2_OUT)
+-#define GPIO61_LDD_3_MD		(61 | GPIO_ALT_FN_2_OUT)
+-#define GPIO62_LDD_4_MD		(62 | GPIO_ALT_FN_2_OUT)
+-#define GPIO63_LDD_5_MD		(63 | GPIO_ALT_FN_2_OUT)
+-#define GPIO64_LDD_6_MD		(64 | GPIO_ALT_FN_2_OUT)
+-#define GPIO65_LDD_7_MD		(65 | GPIO_ALT_FN_2_OUT)
+-#define GPIO66_LDD_8_MD		(66 | GPIO_ALT_FN_2_OUT)
+-#define GPIO66_MBREQ_MD		(66 | GPIO_ALT_FN_1_IN)
+-#define GPIO67_LDD_9_MD		(67 | GPIO_ALT_FN_2_OUT)
+-#define GPIO67_MMCCS0_MD	(67 | GPIO_ALT_FN_1_OUT)
+-#define GPIO68_LDD_10_MD	(68 | GPIO_ALT_FN_2_OUT)
+-#define GPIO68_MMCCS1_MD	(68 | GPIO_ALT_FN_1_OUT)
+-#define GPIO69_LDD_11_MD	(69 | GPIO_ALT_FN_2_OUT)
+-#define GPIO69_MMCCLK_MD	(69 | GPIO_ALT_FN_1_OUT)
+-#define GPIO70_LDD_12_MD	(70 | GPIO_ALT_FN_2_OUT)
+-#define GPIO70_RTCCLK_MD	(70 | GPIO_ALT_FN_1_OUT)
+-#define GPIO71_LDD_13_MD	(71 | GPIO_ALT_FN_2_OUT)
+-#define GPIO71_3_6MHz_MD	(71 | GPIO_ALT_FN_1_OUT)
+-#define GPIO72_LDD_14_MD	(72 | GPIO_ALT_FN_2_OUT)
+-#define GPIO72_32kHz_MD		(72 | GPIO_ALT_FN_1_OUT)
+-#define GPIO73_LDD_15_MD	(73 | GPIO_ALT_FN_2_OUT)
+-#define GPIO73_MBGNT_MD		(73 | GPIO_ALT_FN_1_OUT)
+-#define GPIO74_LCD_FCLK_MD	(74 | GPIO_ALT_FN_2_OUT)
+-#define GPIO75_LCD_LCLK_MD	(75 | GPIO_ALT_FN_2_OUT)
+-#define GPIO76_LCD_PCLK_MD	(76 | GPIO_ALT_FN_2_OUT)
+-#define GPIO77_LCD_ACBIAS_MD	(77 | GPIO_ALT_FN_2_OUT)
+-#define GPIO78_nCS_2_MD		(78 | GPIO_ALT_FN_2_OUT)
+-#define GPIO79_nCS_3_MD		(79 | GPIO_ALT_FN_2_OUT)
+-#define GPIO79_pSKTSEL_MD	(79 | GPIO_ALT_FN_1_OUT)
+-#define GPIO80_nCS_4_MD		(80 | GPIO_ALT_FN_2_OUT)
+-#define GPIO81_NSSP_CLK_OUT 	(81 | GPIO_ALT_FN_1_OUT)
+-#define GPIO81_NSSP_CLK_IN  	(81 | GPIO_ALT_FN_1_IN)
+-#define GPIO82_NSSP_FRM_OUT 	(82 | GPIO_ALT_FN_1_OUT)
+-#define GPIO82_NSSP_FRM_IN  	(82 | GPIO_ALT_FN_1_IN)
+-#define GPIO83_NSSP_TX      	(83 | GPIO_ALT_FN_1_OUT)
+-#define GPIO83_NSSP_RX      	(83 | GPIO_ALT_FN_2_IN)
+-#define GPIO84_NSSP_TX      	(84 | GPIO_ALT_FN_1_OUT)
+-#define GPIO84_NSSP_RX      	(84 | GPIO_ALT_FN_2_IN)
+-#define GPIO85_nPCE_1_MD	(85 | GPIO_ALT_FN_1_OUT)
+-#define GPIO92_MMCDAT0_MD	(92 | GPIO_ALT_FN_1_OUT)
+-#define GPIO102_nPCE_1_MD	(102 | GPIO_ALT_FN_1_OUT)
+-#define GPIO104_pSKTSEL_MD	(104 | GPIO_ALT_FN_1_OUT)
+-#define GPIO109_MMCDAT1_MD	(109 | GPIO_ALT_FN_1_OUT)
+-#define GPIO110_MMCDAT2_MD	(110 | GPIO_ALT_FN_1_OUT)
+-#define GPIO110_MMCCS0_MD	(110 | GPIO_ALT_FN_1_OUT)
+-#define GPIO111_MMCDAT3_MD	(111 | GPIO_ALT_FN_1_OUT)
+-#define GPIO110_MMCCS1_MD	(111 | GPIO_ALT_FN_1_OUT)
+-#define GPIO112_MMCCMD_MD	(112 | GPIO_ALT_FN_1_OUT)
+-#define GPIO113_I2S_SYSCLK_MD	(113 | GPIO_ALT_FN_1_OUT)
+-#define GPIO113_AC97_RESET_N_MD	(113 | GPIO_ALT_FN_2_OUT)
+-#define GPIO117_I2CSCL_MD	(117 | GPIO_ALT_FN_1_IN)
+-#define GPIO118_I2CSDA_MD	(118 | GPIO_ALT_FN_1_IN)
+-
+ /*
+  * Power Manager
+  */
+@@ -1866,62 +1604,6 @@
+ 
+ #ifdef CONFIG_PXA27x
+ 
+-/*
+- * Keypad
+- */
+-#define KPC             __REG(0x41500000) /* Keypad Interface Control register */
+-#define KPDK            __REG(0x41500008) /* Keypad Interface Direct Key register */
+-#define KPREC           __REG(0x41500010) /* Keypad Interface Rotary Encoder register */
+-#define KPMK            __REG(0x41500018) /* Keypad Interface Matrix Key register */
+-#define KPAS            __REG(0x41500020) /* Keypad Interface Automatic Scan register */
+-#define KPASMKP0        __REG(0x41500028) /* Keypad Interface Automatic Scan Multiple Key Presser register 0 */
+-#define KPASMKP1        __REG(0x41500030) /* Keypad Interface Automatic Scan Multiple Key Presser register 1 */
+-#define KPASMKP2        __REG(0x41500038) /* Keypad Interface Automatic Scan Multiple Key Presser register 2 */
+-#define KPASMKP3        __REG(0x41500040) /* Keypad Interface Automatic Scan Multiple Key Presser register 3 */
+-#define KPKDI           __REG(0x41500048) /* Keypad Interface Key Debounce Interval register */
+-
+-#define KPC_AS          (0x1 << 30)  /* Automatic Scan bit */
+-#define KPC_ASACT       (0x1 << 29)  /* Automatic Scan on Activity */
+-#define KPC_MI          (0x1 << 22)  /* Matrix interrupt bit */
+-#define KPC_IMKP        (0x1 << 21)  /* Ignore Multiple Key Press */
+-#define KPC_MS7         (0x1 << 20)  /* Matrix scan line 7 */
+-#define KPC_MS6         (0x1 << 19)  /* Matrix scan line 6 */
+-#define KPC_MS5         (0x1 << 18)  /* Matrix scan line 5 */
+-#define KPC_MS4         (0x1 << 17)  /* Matrix scan line 4 */
+-#define KPC_MS3         (0x1 << 16)  /* Matrix scan line 3 */
+-#define KPC_MS2         (0x1 << 15)  /* Matrix scan line 2 */
+-#define KPC_MS1         (0x1 << 14)  /* Matrix scan line 1 */
+-#define KPC_MS0         (0x1 << 13)  /* Matrix scan line 0 */
+-#define KPC_MS_ALL      (KPC_MS0 | KPC_MS1 | KPC_MS2 | KPC_MS3 | KPC_MS4 | KPC_MS5 | KPC_MS6 | KPC_MS7)
+-#define KPC_ME          (0x1 << 12)  /* Matrix Keypad Enable */
+-#define KPC_MIE         (0x1 << 11)  /* Matrix Interrupt Enable */
+-#define KPC_DK_DEB_SEL	(0x1 <<  9)  /* Direct Keypad Debounce Select */
+-#define KPC_DI          (0x1 <<  5)  /* Direct key interrupt bit */
+-#define KPC_RE_ZERO_DEB (0x1 <<  4)  /* Rotary Encoder Zero Debounce */
+-#define KPC_REE1        (0x1 <<  3)  /* Rotary Encoder1 Enable */
+-#define KPC_REE0        (0x1 <<  2)  /* Rotary Encoder0 Enable */
+-#define KPC_DE          (0x1 <<  1)  /* Direct Keypad Enable */
+-#define KPC_DIE         (0x1 <<  0)  /* Direct Keypad interrupt Enable */
+-
+-#define KPDK_DKP        (0x1 << 31)
+-#define KPDK_DK7        (0x1 <<  7)
+-#define KPDK_DK6        (0x1 <<  6)
+-#define KPDK_DK5        (0x1 <<  5)
+-#define KPDK_DK4        (0x1 <<  4)
+-#define KPDK_DK3        (0x1 <<  3)
+-#define KPDK_DK2        (0x1 <<  2)
+-#define KPDK_DK1        (0x1 <<  1)
+-#define KPDK_DK0        (0x1 <<  0)
+-
+-#define KPREC_OF1       (0x1 << 31)
+-#define kPREC_UF1       (0x1 << 30)
+-#define KPREC_OF0       (0x1 << 15)
+-#define KPREC_UF0       (0x1 << 14)
+-
+-#define KPMK_MKP        (0x1 << 31)
+-#define KPAS_SO         (0x1 << 31)
+-#define KPASMKPx_SO     (0x1 << 31)
+-
+ /* Camera Interface */
+ #define CICR0		__REG(0x50000000)
+ #define CICR1		__REG(0x50000004)
+@@ -1953,7 +1635,7 @@
+ #define CICR0_FOM	(1 << 0)	/* FIFO-overrun mask */
+ 
+ #define CICR1_TBIT	(1 << 31)	/* Transparency bit */
+-#define CICR1_RGBT_CONV	(0x3 << 30)	/* RGBT conversion mask */
++#define CICR1_RGBT_CONV	(0x3 << 29)	/* RGBT conversion mask */
+ #define CICR1_PPL	(0x7ff << 15)	/* Pixels per line mask */
+ #define CICR1_RGB_CONV	(0x7 << 12)	/* RGB conversion mask */
+ #define CICR1_RGB_F	(1 << 11)	/* RGB format */
+diff --git a/include/asm-arm/arch-pxa/pxa27x_keypad.h b/include/asm-arm/arch-pxa/pxa27x_keypad.h
+index 644f760..d5a48a9 100644
+--- a/include/asm-arm/arch-pxa/pxa27x_keypad.h
++++ b/include/asm-arm/arch-pxa/pxa27x_keypad.h
+@@ -53,4 +53,6 @@ struct pxa27x_keypad_platform_data {
+ 
+ #define KEY(row, col, val)	(((row) << 28) | ((col) << 24) | (val))
+ 
++extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info);
++
+ #endif /* __ASM_ARCH_PXA27x_KEYPAD_H */
+diff --git a/include/asm-arm/arch-pxa/pxa2xx-gpio.h b/include/asm-arm/arch-pxa/pxa2xx-gpio.h
+new file mode 100644
+index 0000000..763313c
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/pxa2xx-gpio.h
+@@ -0,0 +1,357 @@
++#ifndef __ASM_ARCH_PXA2XX_GPIO_H
++#define __ASM_ARCH_PXA2XX_GPIO_H
++
++/* GPIO alternate function assignments */
++
++#define GPIO1_RST		1	/* reset */
++#define GPIO6_MMCCLK		6	/* MMC Clock */
++#define GPIO7_48MHz		7	/* 48 MHz clock output */
++#define GPIO8_MMCCS0		8	/* MMC Chip Select 0 */
++#define GPIO9_MMCCS1		9	/* MMC Chip Select 1 */
++#define GPIO10_RTCCLK		10	/* real time clock (1 Hz) */
++#define GPIO11_3_6MHz		11	/* 3.6 MHz oscillator out */
++#define GPIO12_32KHz		12	/* 32 kHz out */
++#define GPIO12_CIF_DD_7		12	/* Camera data pin 7 */
++#define GPIO13_MBGNT		13	/* memory controller grant */
++#define GPIO14_MBREQ		14	/* alternate bus master request */
++#define GPIO15_nCS_1		15	/* chip select 1 */
++#define GPIO16_PWM0		16	/* PWM0 output */
++#define GPIO17_PWM1		17	/* PWM1 output */
++#define GPIO17_CIF_DD_6		17	/* Camera data pin 6 */
++#define GPIO18_RDY		18	/* Ext. Bus Ready */
++#define GPIO19_DREQ1		19	/* External DMA Request */
++#define GPIO20_DREQ0		20	/* External DMA Request */
++#define GPIO23_SCLK		23	/* SSP clock */
++#define GPIO23_CIF_MCLK		23	/* Camera Master Clock */
++#define GPIO24_SFRM		24	/* SSP Frame */
++#define GPIO24_CIF_FV		24	/* Camera frame start signal */
++#define GPIO25_STXD		25	/* SSP transmit */
++#define GPIO25_CIF_LV		25	/* Camera line start signal */
++#define GPIO26_SRXD		26	/* SSP receive */
++#define GPIO26_CIF_PCLK		26	/* Camera Pixel Clock */
++#define GPIO27_SEXTCLK		27	/* SSP ext_clk */
++#define GPIO27_CIF_DD_0		27	/* Camera data pin 0 */
++#define GPIO28_BITCLK		28	/* AC97/I2S bit_clk */
++#define GPIO29_SDATA_IN		29	/* AC97 Sdata_in0 / I2S Sdata_in */
++#define GPIO30_SDATA_OUT	30	/* AC97/I2S Sdata_out */
++#define GPIO31_SYNC		31	/* AC97/I2S sync */
++#define GPIO32_SDATA_IN1	32	/* AC97 Sdata_in1 */
++#define GPIO32_SYSCLK		32	/* I2S System Clock */
++#define GPIO32_MMCCLK		32	/* MMC Clock (PXA270) */
++#define GPIO33_nCS_5		33	/* chip select 5 */
++#define GPIO34_FFRXD		34	/* FFUART receive */
++#define GPIO34_MMCCS0		34	/* MMC Chip Select 0 */
++#define GPIO35_FFCTS		35	/* FFUART Clear to send */
++#define GPIO36_FFDCD		36	/* FFUART Data carrier detect */
++#define GPIO37_FFDSR		37	/* FFUART data set ready */
++#define GPIO38_FFRI		38	/* FFUART Ring Indicator */
++#define GPIO39_MMCCS1		39	/* MMC Chip Select 1 */
++#define GPIO39_FFTXD		39	/* FFUART transmit data */
++#define GPIO40_FFDTR		40	/* FFUART data terminal Ready */
++#define GPIO41_FFRTS		41	/* FFUART request to send */
++#define GPIO42_BTRXD		42	/* BTUART receive data */
++#define GPIO42_HWRXD		42	/* HWUART receive data */
++#define GPIO42_CIF_MCLK		42	/* Camera Master Clock */
++#define GPIO43_BTTXD		43	/* BTUART transmit data */
++#define GPIO43_HWTXD		43	/* HWUART transmit data */
++#define GPIO43_CIF_FV		43	/* Camera frame start signal */
++#define GPIO44_BTCTS		44	/* BTUART clear to send */
++#define GPIO44_HWCTS		44	/* HWUART clear to send */
++#define GPIO44_CIF_LV		44	/* Camera line start signal */
++#define GPIO45_BTRTS		45	/* BTUART request to send */
++#define GPIO45_HWRTS		45	/* HWUART request to send */
++#define GPIO45_AC97_SYSCLK	45	/* AC97 System Clock */
++#define GPIO45_CIF_PCLK		45	/* Camera Pixel Clock */
++#define GPIO46_ICPRXD		46	/* ICP receive data */
++#define GPIO46_STRXD		46	/* STD_UART receive data */
++#define GPIO47_ICPTXD		47	/* ICP transmit data */
++#define GPIO47_STTXD		47	/* STD_UART transmit data */
++#define GPIO47_CIF_DD_0		47	/* Camera data pin 0 */
++#define GPIO48_nPOE		48	/* Output Enable for Card Space */
++#define GPIO48_CIF_DD_5		48	/* Camera data pin 5 */
++#define GPIO49_nPWE		49	/* Write Enable for Card Space */
++#define GPIO50_nPIOR		50	/* I/O Read for Card Space */
++#define GPIO50_CIF_DD_3		50	/* Camera data pin 3 */
++#define GPIO51_nPIOW		51	/* I/O Write for Card Space */
++#define GPIO51_CIF_DD_2		51	/* Camera data pin 2 */
++#define GPIO52_nPCE_1		52	/* Card Enable for Card Space */
++#define GPIO52_CIF_DD_4		52	/* Camera data pin 4 */
++#define GPIO53_nPCE_2		53	/* Card Enable for Card Space */
++#define GPIO53_MMCCLK		53	/* MMC Clock */
++#define GPIO53_CIF_MCLK		53	/* Camera Master Clock */
++#define GPIO54_MMCCLK		54	/* MMC Clock */
++#define GPIO54_pSKTSEL		54	/* Socket Select for Card Space */
++#define GPIO54_nPCE_2		54	/* Card Enable for Card Space (PXA27x) */
++#define GPIO54_CIF_PCLK		54	/* Camera Pixel Clock */
++#define GPIO55_nPREG		55	/* Card Address bit 26 */
++#define GPIO55_CIF_DD_1		55	/* Camera data pin 1 */
++#define GPIO56_nPWAIT		56	/* Wait signal for Card Space */
++#define GPIO57_nIOIS16		57	/* Bus Width select for I/O Card Space */
++#define GPIO58_LDD_0		58	/* LCD data pin 0 */
++#define GPIO59_LDD_1		59	/* LCD data pin 1 */
++#define GPIO60_LDD_2		60	/* LCD data pin 2 */
++#define GPIO61_LDD_3		61	/* LCD data pin 3 */
++#define GPIO62_LDD_4		62	/* LCD data pin 4 */
++#define GPIO63_LDD_5		63	/* LCD data pin 5 */
++#define GPIO64_LDD_6		64	/* LCD data pin 6 */
++#define GPIO65_LDD_7		65	/* LCD data pin 7 */
++#define GPIO66_LDD_8		66	/* LCD data pin 8 */
++#define GPIO66_MBREQ		66	/* alternate bus master req */
++#define GPIO67_LDD_9		67	/* LCD data pin 9 */
++#define GPIO67_MMCCS0		67	/* MMC Chip Select 0 */
++#define GPIO68_LDD_10		68	/* LCD data pin 10 */
++#define GPIO68_MMCCS1		68	/* MMC Chip Select 1 */
++#define GPIO69_LDD_11		69	/* LCD data pin 11 */
++#define GPIO69_MMCCLK		69	/* MMC_CLK */
++#define GPIO70_LDD_12		70	/* LCD data pin 12 */
++#define GPIO70_RTCCLK		70	/* Real Time clock (1 Hz) */
++#define GPIO71_LDD_13		71	/* LCD data pin 13 */
++#define GPIO71_3_6MHz		71	/* 3.6 MHz Oscillator clock */
++#define GPIO72_LDD_14		72	/* LCD data pin 14 */
++#define GPIO72_32kHz		72	/* 32 kHz clock */
++#define GPIO73_LDD_15		73	/* LCD data pin 15 */
++#define GPIO73_MBGNT		73	/* Memory controller grant */
++#define GPIO74_LCD_FCLK		74	/* LCD Frame clock */
++#define GPIO75_LCD_LCLK		75	/* LCD line clock */
++#define GPIO76_LCD_PCLK		76	/* LCD Pixel clock */
++#define GPIO77_LCD_ACBIAS	77	/* LCD AC Bias */
++#define GPIO78_nCS_2		78	/* chip select 2 */
++#define GPIO79_nCS_3		79	/* chip select 3 */
++#define GPIO80_nCS_4		80	/* chip select 4 */
++#define GPIO81_NSCLK		81	/* NSSP clock */
++#define GPIO81_CIF_DD_0		81	/* Camera data pin 0 */
++#define GPIO82_NSFRM		82	/* NSSP Frame */
++#define GPIO82_CIF_DD_5		82	/* Camera data pin 5 */
++#define GPIO83_NSTXD		83	/* NSSP transmit */
++#define GPIO83_CIF_DD_4		83	/* Camera data pin 4 */
++#define GPIO84_NSRXD		84	/* NSSP receive */
++#define GPIO84_CIF_FV		84	/* Camera frame start signal */
++#define GPIO85_nPCE_1		85	/* Card Enable for Card Space (PXA27x) */
++#define GPIO85_CIF_LV		85	/* Camera line start signal */
++#define GPIO90_CIF_DD_4		90	/* Camera data pin 4 */
++#define GPIO91_CIF_DD_5		91	/* Camera data pin 5 */
++#define GPIO92_MMCDAT0		92	/* MMC DAT0 (PXA27x) */
++#define GPIO93_CIF_DD_6		93	/* Camera data pin 6 */
++#define GPIO94_CIF_DD_5		94	/* Camera data pin 5 */
++#define GPIO95_CIF_DD_4		95	/* Camera data pin 4 */
++#define GPIO98_CIF_DD_0		98	/* Camera data pin 0 */
++#define GPIO102_nPCE_1		102	/* PCMCIA (PXA27x) */
++#define GPIO103_CIF_DD_3	103	/* Camera data pin 3 */
++#define GPIO104_CIF_DD_2	104	/* Camera data pin 2 */
++#define GPIO105_CIF_DD_1	105	/* Camera data pin 1 */
++#define GPIO106_CIF_DD_9	106	/* Camera data pin 9 */
++#define GPIO107_CIF_DD_8	107	/* Camera data pin 8 */
++#define GPIO108_CIF_DD_7	108	/* Camera data pin 7 */
++#define GPIO109_MMCDAT1		109	/* MMC DAT1 (PXA27x) */
++#define GPIO110_MMCDAT2		110	/* MMC DAT2 (PXA27x) */
++#define GPIO110_MMCCS0		110	/* MMC Chip Select 0 (PXA27x) */
++#define GPIO111_MMCDAT3		111	/* MMC DAT3 (PXA27x) */
++#define GPIO111_MMCCS1		111	/* MMC Chip Select 1 (PXA27x) */
++#define GPIO112_MMCCMD		112	/* MMC CMD (PXA27x) */
++#define GPIO113_I2S_SYSCLK	113	/* I2S System Clock (PXA27x) */
++#define GPIO113_AC97_RESET_N	113	/* AC97 NRESET on (PXA27x) */
++#define GPIO114_CIF_DD_1	114	/* Camera data pin 1 */
++#define GPIO115_CIF_DD_3	115	/* Camera data pin 3 */
++#define GPIO116_CIF_DD_2	116	/* Camera data pin 2 */
++
++/* GPIO alternate function mode & direction */
++
++#define GPIO_IN			0x000
++#define GPIO_OUT		0x080
++#define GPIO_ALT_FN_1_IN	0x100
++#define GPIO_ALT_FN_1_OUT	0x180
++#define GPIO_ALT_FN_2_IN	0x200
++#define GPIO_ALT_FN_2_OUT	0x280
++#define GPIO_ALT_FN_3_IN	0x300
++#define GPIO_ALT_FN_3_OUT	0x380
++#define GPIO_MD_MASK_NR		0x07f
++#define GPIO_MD_MASK_DIR	0x080
++#define GPIO_MD_MASK_FN		0x300
++#define GPIO_DFLT_LOW		0x400
++#define GPIO_DFLT_HIGH		0x800
++
++#define GPIO1_RTS_MD		( 1 | GPIO_ALT_FN_1_IN)
++#define GPIO6_MMCCLK_MD		( 6 | GPIO_ALT_FN_1_OUT)
++#define GPIO7_48MHz_MD		( 7 | GPIO_ALT_FN_1_OUT)
++#define GPIO8_MMCCS0_MD		( 8 | GPIO_ALT_FN_1_OUT)
++#define GPIO9_MMCCS1_MD		( 9 | GPIO_ALT_FN_1_OUT)
++#define GPIO10_RTCCLK_MD	(10 | GPIO_ALT_FN_1_OUT)
++#define GPIO11_3_6MHz_MD	(11 | GPIO_ALT_FN_1_OUT)
++#define GPIO12_32KHz_MD		(12 | GPIO_ALT_FN_1_OUT)
++#define GPIO12_CIF_DD_7_MD	(12 | GPIO_ALT_FN_2_IN)
++#define GPIO13_MBGNT_MD		(13 | GPIO_ALT_FN_2_OUT)
++#define GPIO14_MBREQ_MD		(14 | GPIO_ALT_FN_1_IN)
++#define GPIO15_nCS_1_MD		(15 | GPIO_ALT_FN_2_OUT)
++#define GPIO16_PWM0_MD		(16 | GPIO_ALT_FN_2_OUT)
++#define GPIO17_PWM1_MD		(17 | GPIO_ALT_FN_2_OUT)
++#define GPIO17_CIF_DD_6_MD	(17 | GPIO_ALT_FN_2_IN)
++#define GPIO18_RDY_MD		(18 | GPIO_ALT_FN_1_IN)
++#define GPIO19_DREQ1_MD		(19 | GPIO_ALT_FN_1_IN)
++#define GPIO20_DREQ0_MD		(20 | GPIO_ALT_FN_1_IN)
++#define GPIO23_CIF_MCLK_MD	(23 | GPIO_ALT_FN_1_OUT)
++#define GPIO23_SCLK_MD		(23 | GPIO_ALT_FN_2_OUT)
++#define GPIO24_CIF_FV_MD	(24 | GPIO_ALT_FN_1_OUT)
++#define GPIO24_SFRM_MD		(24 | GPIO_ALT_FN_2_OUT)
++#define GPIO25_CIF_LV_MD	(25 | GPIO_ALT_FN_1_OUT)
++#define GPIO25_STXD_MD		(25 | GPIO_ALT_FN_2_OUT)
++#define GPIO26_SRXD_MD		(26 | GPIO_ALT_FN_1_IN)
++#define GPIO26_CIF_PCLK_MD	(26 | GPIO_ALT_FN_2_IN)
++#define GPIO27_SEXTCLK_MD	(27 | GPIO_ALT_FN_1_IN)
++#define GPIO27_CIF_DD_0_MD	(27 | GPIO_ALT_FN_3_IN)
++#define GPIO28_BITCLK_AC97_MD	(28 | GPIO_ALT_FN_1_IN)
++#define GPIO28_BITCLK_IN_I2S_MD	(28 | GPIO_ALT_FN_2_IN)
++#define GPIO28_BITCLK_OUT_I2S_MD	(28 | GPIO_ALT_FN_1_OUT)
++#define GPIO29_SDATA_IN_AC97_MD	(29 | GPIO_ALT_FN_1_IN)
++#define GPIO29_SDATA_IN_I2S_MD	(29 | GPIO_ALT_FN_2_IN)
++#define GPIO30_SDATA_OUT_AC97_MD	(30 | GPIO_ALT_FN_2_OUT)
++#define GPIO30_SDATA_OUT_I2S_MD	(30 | GPIO_ALT_FN_1_OUT)
++#define GPIO31_SYNC_I2S_MD	(31 | GPIO_ALT_FN_1_OUT)
++#define GPIO31_SYNC_AC97_MD	(31 | GPIO_ALT_FN_2_OUT)
++#define GPIO32_SDATA_IN1_AC97_MD	(32 | GPIO_ALT_FN_1_IN)
++#define GPIO32_SYSCLK_I2S_MD	(32 | GPIO_ALT_FN_1_OUT)
++#define GPIO32_MMCCLK_MD	(32 | GPIO_ALT_FN_2_OUT)
++#define GPIO33_nCS_5_MD		(33 | GPIO_ALT_FN_2_OUT)
++#define GPIO34_FFRXD_MD		(34 | GPIO_ALT_FN_1_IN)
++#define GPIO34_MMCCS0_MD	(34 | GPIO_ALT_FN_2_OUT)
++#define GPIO35_FFCTS_MD		(35 | GPIO_ALT_FN_1_IN)
++#define GPIO35_KP_MKOUT6_MD	(35 | GPIO_ALT_FN_2_OUT)
++#define GPIO36_FFDCD_MD		(36 | GPIO_ALT_FN_1_IN)
++#define GPIO37_FFDSR_MD		(37 | GPIO_ALT_FN_1_IN)
++#define GPIO38_FFRI_MD		(38 | GPIO_ALT_FN_1_IN)
++#define GPIO39_MMCCS1_MD	(39 | GPIO_ALT_FN_1_OUT)
++#define GPIO39_FFTXD_MD		(39 | GPIO_ALT_FN_2_OUT)
++#define GPIO40_FFDTR_MD		(40 | GPIO_ALT_FN_2_OUT)
++#define GPIO41_FFRTS_MD		(41 | GPIO_ALT_FN_2_OUT)
++#define GPIO41_KP_MKOUT7_MD	(41 | GPIO_ALT_FN_1_OUT)
++#define GPIO42_BTRXD_MD		(42 | GPIO_ALT_FN_1_IN)
++#define GPIO42_HWRXD_MD		(42 | GPIO_ALT_FN_3_IN)
++#define GPIO42_CIF_MCLK_MD	(42 | GPIO_ALT_FN_3_OUT)
++#define GPIO43_BTTXD_MD		(43 | GPIO_ALT_FN_2_OUT)
++#define GPIO43_HWTXD_MD		(43 | GPIO_ALT_FN_3_OUT)
++#define GPIO43_CIF_FV_MD	(43 | GPIO_ALT_FN_3_OUT)
++#define GPIO44_BTCTS_MD		(44 | GPIO_ALT_FN_1_IN)
++#define GPIO44_HWCTS_MD		(44 | GPIO_ALT_FN_3_IN)
++#define GPIO44_CIF_LV_MD	(44 | GPIO_ALT_FN_3_OUT)
++#define GPIO45_CIF_PCLK_MD	(45 | GPIO_ALT_FN_3_IN)
++#define GPIO45_BTRTS_MD		(45 | GPIO_ALT_FN_2_OUT)
++#define GPIO45_HWRTS_MD		(45 | GPIO_ALT_FN_3_OUT)
++#define GPIO45_SYSCLK_AC97_MD	(45 | GPIO_ALT_FN_1_OUT)
++#define GPIO46_ICPRXD_MD	(46 | GPIO_ALT_FN_1_IN)
++#define GPIO46_STRXD_MD		(46 | GPIO_ALT_FN_2_IN)
++#define GPIO47_CIF_DD_0_MD	(47 | GPIO_ALT_FN_1_IN)
++#define GPIO47_ICPTXD_MD	(47 | GPIO_ALT_FN_2_OUT)
++#define GPIO47_STTXD_MD		(47 | GPIO_ALT_FN_1_OUT)
++#define GPIO48_CIF_DD_5_MD	(48 | GPIO_ALT_FN_1_IN)
++#define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
++#define GPIO48_HWTXD_MD		(48 | GPIO_ALT_FN_1_OUT)
++#define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
++#define GPIO49_HWRXD_MD		(49 | GPIO_ALT_FN_1_IN)
++#define GPIO49_nPWE_MD		(49 | GPIO_ALT_FN_2_OUT)
++#define GPIO50_CIF_DD_3_MD	(50 | GPIO_ALT_FN_1_IN)
++#define GPIO50_nPIOR_MD		(50 | GPIO_ALT_FN_2_OUT)
++#define GPIO50_HWCTS_MD		(50 | GPIO_ALT_FN_1_IN)
++#define GPIO50_CIF_DD_3_MD	(50 | GPIO_ALT_FN_1_IN)
++#define GPIO51_CIF_DD_2_MD	(51 | GPIO_ALT_FN_1_IN)
++#define GPIO51_nPIOW_MD		(51 | GPIO_ALT_FN_2_OUT)
++#define GPIO51_HWRTS_MD		(51 | GPIO_ALT_FN_1_OUT)
++#define GPIO51_CIF_DD_2_MD	(51 | GPIO_ALT_FN_1_IN)
++#define GPIO52_nPCE_1_MD	(52 | GPIO_ALT_FN_2_OUT)
++#define GPIO52_CIF_DD_4_MD	(52 | GPIO_ALT_FN_1_IN)
++#define GPIO53_nPCE_2_MD	(53 | GPIO_ALT_FN_2_OUT)
++#define GPIO53_MMCCLK_MD	(53 | GPIO_ALT_FN_1_OUT)
++#define GPIO53_CIF_MCLK_MD	(53 | GPIO_ALT_FN_2_OUT)
++#define GPIO54_MMCCLK_MD	(54 | GPIO_ALT_FN_1_OUT)
++#define GPIO54_nPCE_2_MD	(54 | GPIO_ALT_FN_2_OUT)
++#define GPIO54_pSKTSEL_MD	(54 | GPIO_ALT_FN_2_OUT)
++#define GPIO54_CIF_PCLK_MD	(54 | GPIO_ALT_FN_3_IN)
++#define GPIO55_nPREG_MD		(55 | GPIO_ALT_FN_2_OUT)
++#define GPIO55_CIF_DD_1_MD	(55 | GPIO_ALT_FN_1_IN)
++#define GPIO56_nPWAIT_MD	(56 | GPIO_ALT_FN_1_IN)
++#define GPIO57_nIOIS16_MD	(57 | GPIO_ALT_FN_1_IN)
++#define GPIO58_LDD_0_MD		(58 | GPIO_ALT_FN_2_OUT)
++#define GPIO59_LDD_1_MD		(59 | GPIO_ALT_FN_2_OUT)
++#define GPIO60_LDD_2_MD		(60 | GPIO_ALT_FN_2_OUT)
++#define GPIO61_LDD_3_MD		(61 | GPIO_ALT_FN_2_OUT)
++#define GPIO62_LDD_4_MD		(62 | GPIO_ALT_FN_2_OUT)
++#define GPIO63_LDD_5_MD		(63 | GPIO_ALT_FN_2_OUT)
++#define GPIO64_LDD_6_MD		(64 | GPIO_ALT_FN_2_OUT)
++#define GPIO65_LDD_7_MD		(65 | GPIO_ALT_FN_2_OUT)
++#define GPIO66_LDD_8_MD		(66 | GPIO_ALT_FN_2_OUT)
++#define GPIO66_MBREQ_MD		(66 | GPIO_ALT_FN_1_IN)
++#define GPIO67_LDD_9_MD		(67 | GPIO_ALT_FN_2_OUT)
++#define GPIO67_MMCCS0_MD	(67 | GPIO_ALT_FN_1_OUT)
++#define GPIO68_LDD_10_MD	(68 | GPIO_ALT_FN_2_OUT)
++#define GPIO68_MMCCS1_MD	(68 | GPIO_ALT_FN_1_OUT)
++#define GPIO69_LDD_11_MD	(69 | GPIO_ALT_FN_2_OUT)
++#define GPIO69_MMCCLK_MD	(69 | GPIO_ALT_FN_1_OUT)
++#define GPIO70_LDD_12_MD	(70 | GPIO_ALT_FN_2_OUT)
++#define GPIO70_RTCCLK_MD	(70 | GPIO_ALT_FN_1_OUT)
++#define GPIO71_LDD_13_MD	(71 | GPIO_ALT_FN_2_OUT)
++#define GPIO71_3_6MHz_MD	(71 | GPIO_ALT_FN_1_OUT)
++#define GPIO72_LDD_14_MD	(72 | GPIO_ALT_FN_2_OUT)
++#define GPIO72_32kHz_MD		(72 | GPIO_ALT_FN_1_OUT)
++#define GPIO73_LDD_15_MD	(73 | GPIO_ALT_FN_2_OUT)
++#define GPIO73_MBGNT_MD		(73 | GPIO_ALT_FN_1_OUT)
++#define GPIO74_LCD_FCLK_MD	(74 | GPIO_ALT_FN_2_OUT)
++#define GPIO75_LCD_LCLK_MD	(75 | GPIO_ALT_FN_2_OUT)
++#define GPIO76_LCD_PCLK_MD	(76 | GPIO_ALT_FN_2_OUT)
++#define GPIO77_LCD_ACBIAS_MD	(77 | GPIO_ALT_FN_2_OUT)
++#define GPIO78_nCS_2_MD		(78 | GPIO_ALT_FN_2_OUT)
++#define GPIO78_nPCE_2_MD	(78 | GPIO_ALT_FN_1_OUT)
++#define GPIO79_nCS_3_MD		(79 | GPIO_ALT_FN_2_OUT)
++#define GPIO79_pSKTSEL_MD	(79 | GPIO_ALT_FN_1_OUT)
++#define GPIO80_nCS_4_MD		(80 | GPIO_ALT_FN_2_OUT)
++#define GPIO81_NSSP_CLK_OUT	(81 | GPIO_ALT_FN_1_OUT)
++#define GPIO81_NSSP_CLK_IN	(81 | GPIO_ALT_FN_1_IN)
++#define GPIO81_CIF_DD_0_MD	(81 | GPIO_ALT_FN_2_IN)
++#define GPIO82_NSSP_FRM_OUT	(82 | GPIO_ALT_FN_1_OUT)
++#define GPIO82_NSSP_FRM_IN	(82 | GPIO_ALT_FN_1_IN)
++#define GPIO82_CIF_DD_5_MD	(82 | GPIO_ALT_FN_3_IN)
++#define GPIO83_NSSP_TX		(83 | GPIO_ALT_FN_1_OUT)
++#define GPIO83_NSSP_RX		(83 | GPIO_ALT_FN_2_IN)
++#define GPIO83_CIF_DD_4_MD	(83 | GPIO_ALT_FN_3_IN)
++#define GPIO84_NSSP_TX		(84 | GPIO_ALT_FN_1_OUT)
++#define GPIO84_NSSP_RX		(84 | GPIO_ALT_FN_2_IN)
++#define GPIO84_CIF_FV_MD	(84 | GPIO_ALT_FN_3_IN)
++#define GPIO85_nPCE_1_MD	(85 | GPIO_ALT_FN_1_OUT)
++#define GPIO85_CIF_LV_MD	(85 | GPIO_ALT_FN_3_IN)
++#define GPIO86_nPCE_1_MD	(86 | GPIO_ALT_FN_1_OUT)
++#define GPIO90_CIF_DD_4_MD	(90 | GPIO_ALT_FN_3_IN)
++#define GPIO91_CIF_DD_5_MD	(91 | GPIO_ALT_FN_3_IN)
++#define GPIO92_MMCDAT0_MD	(92 | GPIO_ALT_FN_1_OUT)
++#define GPIO93_CIF_DD_6_MD	(93 | GPIO_ALT_FN_2_IN)
++#define GPIO94_CIF_DD_5_MD	(94 | GPIO_ALT_FN_2_IN)
++#define GPIO95_CIF_DD_4_MD	(95 | GPIO_ALT_FN_2_IN)
++#define GPIO95_KP_MKIN6_MD	(95 | GPIO_ALT_FN_3_IN)
++#define GPIO96_KP_DKIN3_MD	(96 | GPIO_ALT_FN_1_IN)
++#define GPIO97_KP_MKIN3_MD	(97 | GPIO_ALT_FN_3_IN)
++#define GPIO98_CIF_DD_0_MD	(98 | GPIO_ALT_FN_2_IN)
++#define GPIO100_KP_MKIN0_MD	(100 | GPIO_ALT_FN_1_IN)
++#define GPIO101_KP_MKIN1_MD	(101 | GPIO_ALT_FN_1_IN)
++#define GPIO102_nPCE_1_MD	(102 | GPIO_ALT_FN_1_OUT)
++#define GPIO102_KP_MKIN2_MD	(102 | GPIO_ALT_FN_1_IN)
++#define GPIO103_CIF_DD_3_MD	(103 | GPIO_ALT_FN_1_IN)
++#define GPIO103_KP_MKOUT0_MD	(103 | GPIO_ALT_FN_2_OUT)
++#define GPIO104_CIF_DD_2_MD	(104 | GPIO_ALT_FN_1_IN)
++#define GPIO104_pSKTSEL_MD	(104 | GPIO_ALT_FN_1_OUT)
++#define GPIO104_KP_MKOUT1_MD	(104 | GPIO_ALT_FN_2_OUT)
++#define GPIO105_CIF_DD_1_MD	(105 | GPIO_ALT_FN_1_IN)
++#define GPIO105_KP_MKOUT2_MD	(105 | GPIO_ALT_FN_2_OUT)
++#define GPIO106_CIF_DD_9_MD	(106 | GPIO_ALT_FN_1_IN)
++#define GPIO106_KP_MKOUT3_MD	(106 | GPIO_ALT_FN_2_OUT)
++#define GPIO107_CIF_DD_8_MD	(107 | GPIO_ALT_FN_1_IN)
++#define GPIO107_KP_MKOUT4_MD	(107 | GPIO_ALT_FN_2_OUT)
++#define GPIO108_CIF_DD_7_MD	(108 | GPIO_ALT_FN_1_IN)
++#define GPIO108_KP_MKOUT5_MD	(108 | GPIO_ALT_FN_2_OUT)
++#define GPIO109_MMCDAT1_MD	(109 | GPIO_ALT_FN_1_OUT)
++#define GPIO110_MMCDAT2_MD	(110 | GPIO_ALT_FN_1_OUT)
++#define GPIO110_MMCCS0_MD	(110 | GPIO_ALT_FN_1_OUT)
++#define GPIO111_MMCDAT3_MD	(111 | GPIO_ALT_FN_1_OUT)
++#define GPIO110_MMCCS1_MD	(111 | GPIO_ALT_FN_1_OUT)
++#define GPIO112_MMCCMD_MD	(112 | GPIO_ALT_FN_1_OUT)
++#define GPIO113_I2S_SYSCLK_MD	(113 | GPIO_ALT_FN_1_OUT)
++#define GPIO113_AC97_RESET_N_MD	(113 | GPIO_ALT_FN_2_OUT)
++#define GPIO117_I2CSCL_MD	(117 | GPIO_ALT_FN_1_IN)
++#define GPIO118_I2CSDA_MD	(118 | GPIO_ALT_FN_1_IN)
++
++#endif /* __ASM_ARCH_PXA2XX_GPIO_H */
+diff --git a/include/asm-arm/arch-pxa/pxa3xx-regs.h b/include/asm-arm/arch-pxa/pxa3xx-regs.h
+index 8e1b3ea..fe9364c 100644
+--- a/include/asm-arm/arch-pxa/pxa3xx-regs.h
++++ b/include/asm-arm/arch-pxa/pxa3xx-regs.h
+@@ -12,6 +12,15 @@
+ 
+ #ifndef __ASM_ARCH_PXA3XX_REGS_H
+ #define __ASM_ARCH_PXA3XX_REGS_H
++
++/*
++ * Oscillator Configuration Register (OSCC)
++ */
++#define OSCC           __REG(0x41350000)  /* Oscillator Configuration Register */
++
++#define OSCC_PEN       (1 << 11)       /* 13MHz POUT */
++
++
+ /*
+  * Service Power Management Unit (MPMU)
+  */
+diff --git a/include/asm-arm/arch-pxa/pxa3xx_nand.h b/include/asm-arm/arch-pxa/pxa3xx_nand.h
+new file mode 100644
+index 0000000..81a8937
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/pxa3xx_nand.h
+@@ -0,0 +1,18 @@
++#ifndef __ASM_ARCH_PXA3XX_NAND_H
++#define __ASM_ARCH_PXA3XX_NAND_H
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++
++struct pxa3xx_nand_platform_data {
++
++	/* the data flash bus is shared between the Static Memory
++	 * Controller and the Data Flash Controller,  the arbiter
++	 * controls the ownership of the bus
++	 */
++	int	enable_arbiter;
++
++	struct mtd_partition *parts;
++	unsigned int	nr_parts;
++};
++#endif /* __ASM_ARCH_PXA3XX_NAND_H */
+diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h
+index c05e4fa..c5b6fde 100644
+--- a/include/asm-arm/arch-pxa/tosa.h
++++ b/include/asm-arm/arch-pxa/tosa.h
+@@ -23,11 +23,12 @@
+ /*
+  * SCOOP2 internal GPIOs
+  */
++#define TOSA_SCOOP_GPIO_BASE		NR_BUILTIN_GPIO
+ #define TOSA_SCOOP_PXA_VCORE1		SCOOP_GPCR_PA11
+ #define TOSA_SCOOP_TC6393_REST_IN	SCOOP_GPCR_PA12
+-#define TOSA_SCOOP_IR_POWERDWN		SCOOP_GPCR_PA13
+-#define TOSA_SCOOP_SD_WP		SCOOP_GPCR_PA14
+-#define TOSA_SCOOP_PWR_ON		SCOOP_GPCR_PA15
++#define TOSA_GPIO_IR_POWERDWN		(TOSA_SCOOP_GPIO_BASE + 2)
++#define TOSA_GPIO_SD_WP			(TOSA_SCOOP_GPIO_BASE + 3)
++#define TOSA_GPIO_PWR_ON		(TOSA_SCOOP_GPIO_BASE + 4)
+ #define TOSA_SCOOP_AUD_PWR_ON		SCOOP_GPCR_PA16
+ #define TOSA_SCOOP_BT_RESET		SCOOP_GPCR_PA17
+ #define TOSA_SCOOP_BT_PWR_EN		SCOOP_GPCR_PA18
+@@ -35,7 +36,7 @@
+ 
+ /* GPIO Direction   1 : output mode / 0:input mode */
+ #define TOSA_SCOOP_IO_DIR     ( TOSA_SCOOP_PXA_VCORE1 | TOSA_SCOOP_TC6393_REST_IN | \
+-		TOSA_SCOOP_IR_POWERDWN | TOSA_SCOOP_PWR_ON | TOSA_SCOOP_AUD_PWR_ON |\
++		TOSA_SCOOP_AUD_PWR_ON |\
+ 		TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN )
+ /* GPIO out put level when init   1: Hi */
+ #define TOSA_SCOOP_IO_OUT     ( TOSA_SCOOP_TC6393_REST_IN )
+@@ -43,23 +44,21 @@
+ /*
+  * SCOOP2 jacket GPIOs
+  */
+-#define TOSA_SCOOP_JC_BT_LED		SCOOP_GPCR_PA11
+-#define TOSA_SCOOP_JC_NOTE_LED		SCOOP_GPCR_PA12
+-#define TOSA_SCOOP_JC_CHRG_ERR_LED	SCOOP_GPCR_PA13
+-#define TOSA_SCOOP_JC_USB_PULLUP	SCOOP_GPCR_PA14
++#define TOSA_SCOOP_JC_GPIO_BASE		(NR_BUILTIN_GPIO + 12)
++#define TOSA_GPIO_BT_LED		(TOSA_SCOOP_JC_GPIO_BASE + 0)
++#define TOSA_GPIO_NOTE_LED		(TOSA_SCOOP_JC_GPIO_BASE + 1)
++#define TOSA_GPIO_CHRG_ERR_LED		(TOSA_SCOOP_JC_GPIO_BASE + 2)
++#define TOSA_GPIO_USB_PULLUP		(TOSA_SCOOP_JC_GPIO_BASE + 3)
+ #define TOSA_SCOOP_JC_TC6393_SUSPEND	SCOOP_GPCR_PA15
+ #define TOSA_SCOOP_JC_TC3693_L3V_ON	SCOOP_GPCR_PA16
+ #define TOSA_SCOOP_JC_WLAN_DETECT	SCOOP_GPCR_PA17
+-#define TOSA_SCOOP_JC_WLAN_LED		SCOOP_GPCR_PA18
++#define TOSA_GPIO_WLAN_LED		(TOSA_SCOOP_JC_GPIO_BASE + 7)
+ #define TOSA_SCOOP_JC_CARD_LIMIT_SEL	SCOOP_GPCR_PA19
+ 
+ /* GPIO Direction   1 : output mode / 0:input mode */
+-#define TOSA_SCOOP_JC_IO_DIR ( TOSA_SCOOP_JC_BT_LED | TOSA_SCOOP_JC_NOTE_LED | \
+-		TOSA_SCOOP_JC_CHRG_ERR_LED | TOSA_SCOOP_JC_USB_PULLUP | \
++#define TOSA_SCOOP_JC_IO_DIR ( \
+ 		TOSA_SCOOP_JC_TC6393_SUSPEND | TOSA_SCOOP_JC_TC3693_L3V_ON | \
+-		TOSA_SCOOP_JC_WLAN_LED | TOSA_SCOOP_JC_CARD_LIMIT_SEL )
+-/* GPIO out put level when init   1: Hi */
+-#define TOSA_SCOOP_JC_IO_OUT ( 0 )
++		TOSA_SCOOP_JC_CARD_LIMIT_SEL )
+ 
+ /*
+  * Timing Generator
+@@ -74,15 +73,6 @@
+ #define TG_HPOSCTL 			0x07
+ 
+ /*
+- * LED
+- */
+-#define TOSA_SCOOP_LED_BLUE   		TOSA_SCOOP_GPCR_PA11
+-#define TOSA_SCOOP_LED_GREEN  		TOSA_SCOOP_GPCR_PA12
+-#define TOSA_SCOOP_LED_ORANGE		TOSA_SCOOP_GPCR_PA13
+-#define TOSA_SCOOP_LED_WLAN		TOSA_SCOOP_GPCR_PA18
+-
+-
+-/*
+  * PXA GPIOs
+  */
+ #define TOSA_GPIO_POWERON		(0)
+@@ -161,12 +151,8 @@
+ 
+ #define TOSA_IRQ_GPIO_MAIN_BAT_LOW 	IRQ_GPIO(TOSA_GPIO_MAIN_BAT_LOW)
+ 
+-extern struct platform_device tosascoop_jc_device;
+-extern struct platform_device tosascoop_device;
+-
+ #define TOSA_KEY_SYNC		KEY_102ND /* ??? */
+ 
+-
+ #ifndef CONFIG_KEYBOARD_TOSA_USE_EXT_KEYCODES
+ #define TOSA_KEY_RECORD		KEY_YEN
+ #define TOSA_KEY_ADDRESSBOOK	KEY_KATAKANA
+diff --git a/include/asm-arm/arch-pxa/zylonite.h b/include/asm-arm/arch-pxa/zylonite.h
+index 5f717d6..4881b80 100644
+--- a/include/asm-arm/arch-pxa/zylonite.h
++++ b/include/asm-arm/arch-pxa/zylonite.h
+@@ -18,6 +18,8 @@ extern struct platform_mmc_slot zylonite_mmc_slot[];
+ extern int gpio_backlight;
+ extern int gpio_eth_irq;
+ 
++extern int wm9713_irq;
++
+ extern int lcd_id;
+ extern int lcd_orientation;
+ 
+diff --git a/include/asm-arm/arch-realview/board-eb.h b/include/asm-arm/arch-realview/board-eb.h
+index 3e437b7..206f7a7 100644
+--- a/include/asm-arm/arch-realview/board-eb.h
++++ b/include/asm-arm/arch-realview/board-eb.h
+@@ -26,6 +26,26 @@
+ /*
+  * RealView EB + ARM11MPCore peripheral addresses
+  */
++#define REALVIEW_EB_UART0_BASE		0x10009000	/* UART 0 */
++#define REALVIEW_EB_UART1_BASE		0x1000A000	/* UART 1 */
++#define REALVIEW_EB_UART2_BASE		0x1000B000	/* UART 2 */
++#define REALVIEW_EB_UART3_BASE		0x1000C000	/* UART 3 */
++#define REALVIEW_EB_SSP_BASE		0x1000D000	/* Synchronous Serial Port */
++#define REALVIEW_EB_WATCHDOG_BASE	0x10010000	/* watchdog interface */
++#define REALVIEW_EB_TIMER0_1_BASE	0x10011000	/* Timer 0 and 1 */
++#define REALVIEW_EB_TIMER2_3_BASE	0x10012000	/* Timer 2 and 3 */
++#define REALVIEW_EB_GPIO0_BASE		0x10013000	/* GPIO port 0 */
++#define REALVIEW_EB_RTC_BASE		0x10017000	/* Real Time Clock */
++#define REALVIEW_EB_CLCD_BASE		0x10020000	/* CLCD */
++#define REALVIEW_EB_GIC_CPU_BASE	0x10040000	/* Generic interrupt controller CPU interface */
++#define REALVIEW_EB_GIC_DIST_BASE	0x10041000	/* Generic interrupt controller distributor */
++#define REALVIEW_EB_SMC_BASE		0x10080000	/* Static memory controller */
++
++#define REALVIEW_EB_FLASH_BASE		0x40000000
++#define REALVIEW_EB_FLASH_SIZE		SZ_64M
++#define REALVIEW_EB_ETH_BASE		0x4E000000	/* Ethernet */
++#define REALVIEW_EB_USB_BASE		0x4F000000	/* USB */
++
+ #ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
+ #define REALVIEW_EB11MP_SCU_BASE	0x10100000	/* SCU registers */
+ #define REALVIEW_EB11MP_GIC_CPU_BASE	0x10100100	/* Generic interrupt controller CPU interface */
+diff --git a/include/asm-arm/arch-realview/board-pb1176.h b/include/asm-arm/arch-realview/board-pb1176.h
+new file mode 100644
+index 0000000..48ce9c8
+--- /dev/null
++++ b/include/asm-arm/arch-realview/board-pb1176.h
+@@ -0,0 +1,152 @@
++/*
++ * include/asm-arm/arch-realview/board-pb1176.h
++ *
++ * Copyright (C) 2008 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
++ * MA 02110-1301, USA.
++ */
++
++#ifndef __ASM_ARCH_BOARD_PB1176_H
++#define __ASM_ARCH_BOARD_PB1176_H
++
++#include <asm/arch/platform.h>
++
++/*
++ * Peripheral addresses
++ */
++#define REALVIEW_PB1176_SCTL_BASE		0x10100000 /* System controller */
++#define REALVIEW_PB1176_SMC_BASE		0x10111000 /* SMC */
++#define REALVIEW_PB1176_DMC_BASE		0x10109000 /* DMC configuration */
++#define REALVIEW_PB1176_SDRAM67_BASE		0x70000000 /* SDRAM banks 6 and 7 */
++#define REALVIEW_PB1176_FLASH_BASE		0x30000000
++#define REALVIEW_PB1176_FLASH_SIZE		SZ_64M
++
++#define REALVIEW_PB1176_TIMER0_1_BASE		0x10104000 /* Timer 0 and 1 */
++#define REALVIEW_PB1176_TIMER2_3_BASE		0x10105000 /* Timer 2 and 3 */
++#define REALVIEW_PB1176_TIMER4_5_BASE		0x10106000 /* Timer 4 and 5 */
++#define REALVIEW_PB1176_WATCHDOG_BASE		0x10107000 /* watchdog interface */
++#define REALVIEW_PB1176_RTC_BASE		0x10108000 /* Real Time Clock */
++#define REALVIEW_PB1176_GPIO0_BASE		0x1010A000 /* GPIO port 0 */
++#define REALVIEW_PB1176_SSP_BASE		0x1010B000 /* Synchronous Serial Port */
++#define REALVIEW_PB1176_UART0_BASE		0x1010C000 /* UART 0 */
++#define REALVIEW_PB1176_UART1_BASE		0x1010D000 /* UART 1 */
++#define REALVIEW_PB1176_UART2_BASE		0x1010E000 /* UART 2 */
++#define REALVIEW_PB1176_UART3_BASE		0x1010F000 /* UART 3 */
++#define REALVIEW_PB1176_CLCD_BASE		0x10112000 /* CLCD */
++#define REALVIEW_PB1176_ETH_BASE		0x3A000000 /* Ethernet */
++#define REALVIEW_PB1176_USB_BASE		0x3B000000 /* USB */
++
++/*
++ * PCI regions
++ */
++#define REALVIEW_PB1176_PCI_BASE		0x60000000 /* PCI self config */
++#define REALVIEW_PB1176_PCI_CFG_BASE		0x61000000 /* PCI config */
++#define REALVIEW_PB1176_PCI_IO_BASE0		0x62000000 /* PCI IO region */
++#define REALVIEW_PB1176_PCI_MEM_BASE0		0x63000000 /* Memory region 1 */
++#define REALVIEW_PB1176_PCI_MEM_BASE1		0x64000000 /* Memory region 2 */
++#define REALVIEW_PB1176_PCI_MEM_BASE2		0x68000000 /* Memory region 3 */
++
++#define REALVIEW_PB1176_PCI_BASE_SIZE		0x01000000 /* 16MB */
++#define REALVIEW_PB1176_PCI_CFG_BASE_SIZE	0x01000000 /* 16MB */
++#define REALVIEW_PB1176_PCI_IO_BASE0_SIZE	0x01000000 /* 16MB */
++#define REALVIEW_PB1176_PCI_MEM_BASE0_SIZE	0x01000000 /* 16MB */
++#define REALVIEW_PB1176_PCI_MEM_BASE1_SIZE	0x04000000 /* 64MB */
++#define REALVIEW_PB1176_PCI_MEM_BASE2_SIZE	0x08000000 /* 128MB */
++
++#define REALVIEW_DC1176_GIC_CPU_BASE		0x10120000 /* GIC CPU interface, on devchip */
++#define REALVIEW_DC1176_GIC_DIST_BASE		0x10121000 /* GIC distributor, on devchip */
++#define REALVIEW_PB1176_GIC_CPU_BASE		0x10040000 /* GIC CPU interface, on FPGA */
++#define REALVIEW_PB1176_GIC_DIST_BASE		0x10041000 /* GIC distributor, on FPGA */
++#define REALVIEW_PB1176_L220_BASE		0x10110000 /* L220 registers */
++
++/*
++ * Irqs
++ */
++#define IRQ_DC1176_GIC_START			32
++#define IRQ_PB1176_GIC_START			64
++
++/*
++ * ARM1176 DevChip interrupt sources (primary GIC)
++ */
++#define IRQ_DC1176_WATCHDOG	(IRQ_DC1176_GIC_START + 0)	/* Watchdog timer */
++#define IRQ_DC1176_SOFTINT	(IRQ_DC1176_GIC_START + 1)	/* Software interrupt */
++#define IRQ_DC1176_COMMRx	(IRQ_DC1176_GIC_START + 2)	/* Debug Comm Rx interrupt */
++#define IRQ_DC1176_COMMTx	(IRQ_DC1176_GIC_START + 3)	/* Debug Comm Tx interrupt */
++#define IRQ_DC1176_TIMER0	(IRQ_DC1176_GIC_START + 8)	/* Timer 0 */
++#define IRQ_DC1176_TIMER1	(IRQ_DC1176_GIC_START + 9)	/* Timer 1 */
++#define IRQ_DC1176_TIMER2	(IRQ_DC1176_GIC_START + 10)	/* Timer 2 */
++#define IRQ_DC1176_APC		(IRQ_DC1176_GIC_START + 11)
++#define IRQ_DC1176_IEC		(IRQ_DC1176_GIC_START + 12)
++#define IRQ_DC1176_L2CC		(IRQ_DC1176_GIC_START + 13)
++#define IRQ_DC1176_RTC		(IRQ_DC1176_GIC_START + 14)
++#define IRQ_DC1176_CLCD		(IRQ_DC1176_GIC_START + 15)	/* CLCD controller */
++#define IRQ_DC1176_UART0	(IRQ_DC1176_GIC_START + 18)	/* UART 0 on development chip */
++#define IRQ_DC1176_UART1	(IRQ_DC1176_GIC_START + 19)	/* UART 1 on development chip */
++#define IRQ_DC1176_UART2	(IRQ_DC1176_GIC_START + 20)	/* UART 2 on development chip */
++#define IRQ_DC1176_UART3	(IRQ_DC1176_GIC_START + 21)	/* UART 3 on development chip */
++
++#define IRQ_DC1176_PB_IRQ2	(IRQ_DC1176_GIC_START + 30)	/* tile GIC */
++#define IRQ_DC1176_PB_IRQ1	(IRQ_DC1176_GIC_START + 31)	/* main GIC */
++
++/*
++ * RealView PB1176 interrupt sources (secondary GIC)
++ */
++#define IRQ_PB1176_MMCI0A	(IRQ_PB1176_GIC_START + 1)	/* Multimedia Card 0A */
++#define IRQ_PB1176_MMCI0B	(IRQ_PB1176_GIC_START + 2)	/* Multimedia Card 0A */
++#define IRQ_PB1176_KMI0		(IRQ_PB1176_GIC_START + 3)	/* Keyboard/Mouse port 0 */
++#define IRQ_PB1176_KMI1		(IRQ_PB1176_GIC_START + 4)	/* Keyboard/Mouse port 1 */
++#define IRQ_PB1176_SCI		(IRQ_PB1176_GIC_START + 5)
++#define IRQ_PB1176_UART4	(IRQ_PB1176_GIC_START + 6)	/* UART 4 on baseboard */
++#define IRQ_PB1176_CHARLCD	(IRQ_PB1176_GIC_START + 7)	/* Character LCD */
++#define IRQ_PB1176_GPIO1	(IRQ_PB1176_GIC_START + 8)
++#define IRQ_PB1176_GPIO2	(IRQ_PB1176_GIC_START + 9)
++#define IRQ_PB1176_ETH		(IRQ_PB1176_GIC_START + 10)	/* Ethernet controller */
++#define IRQ_PB1176_USB		(IRQ_PB1176_GIC_START + 11)	/* USB controller */
++
++#define IRQ_PB1176_PISMO	(IRQ_PB1176_GIC_START + 16)
++
++#define IRQ_PB1176_AACI		(IRQ_PB1176_GIC_START + 19)	/* Audio Codec */
++
++#define IRQ_PB1176_TIMER0_1	(IRQ_PB1176_GIC_START + 22)
++#define IRQ_PB1176_TIMER2_3	(IRQ_PB1176_GIC_START + 23)
++#define IRQ_PB1176_DMAC		(IRQ_PB1176_GIC_START + 24)	/* DMA controller */
++#define IRQ_PB1176_RTC		(IRQ_PB1176_GIC_START + 25)	/* Real Time Clock */
++
++#define IRQ_PB1176_GPIO0	-1
++#define IRQ_PB1176_SSP		-1
++#define IRQ_PB1176_SCTL		-1
++
++#define NR_GIC_PB1176		2
++
++/*
++ * Only define NR_IRQS if less than NR_IRQS_PB1176
++ */
++#define NR_IRQS_PB1176		(IRQ_DC1176_GIC_START + 96)
++
++#if defined(CONFIG_MACH_REALVIEW_PB1176)
++
++#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PB1176)
++#undef NR_IRQS
++#define NR_IRQS			NR_IRQS_PB1176
++#endif
++
++#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PB1176)
++#undef MAX_GIC_NR
++#define MAX_GIC_NR		NR_GIC_PB1176
++#endif
++
++#endif	/* CONFIG_MACH_REALVIEW_PB1176 */
++
++#endif	/* __ASM_ARCH_BOARD_PB1176_H */
+diff --git a/include/asm-arm/arch-realview/board-pb11mp.h b/include/asm-arm/arch-realview/board-pb11mp.h
+new file mode 100644
+index 0000000..a1294d9
+--- /dev/null
++++ b/include/asm-arm/arch-realview/board-pb11mp.h
+@@ -0,0 +1,186 @@
++/*
++ * include/asm-arm/arch-realview/board-pb11mp.h
++ *
++ * Copyright (C) 2008 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
++ * MA 02110-1301, USA.
++ */
++
++#ifndef __ASM_ARCH_BOARD_PB11MP_H
++#define __ASM_ARCH_BOARD_PB11MP_H
++
++#include <asm/arch/platform.h>
++
++/*
++ * Peripheral addresses
++ */
++#define REALVIEW_PB11MP_UART0_BASE		0x10009000	/* UART 0 */
++#define REALVIEW_PB11MP_UART1_BASE		0x1000A000	/* UART 1 */
++#define REALVIEW_PB11MP_UART2_BASE		0x1000B000	/* UART 2 */
++#define REALVIEW_PB11MP_UART3_BASE		0x1000C000	/* UART 3 */
++#define REALVIEW_PB11MP_SSP_BASE		0x1000D000	/* Synchronous Serial Port */
++#define REALVIEW_PB11MP_WATCHDOG0_BASE		0x1000F000	/* Watchdog 0 */
++#define REALVIEW_PB11MP_WATCHDOG_BASE		0x10010000	/* watchdog interface */
++#define REALVIEW_PB11MP_TIMER0_1_BASE		0x10011000	/* Timer 0 and 1 */
++#define REALVIEW_PB11MP_TIMER2_3_BASE		0x10012000	/* Timer 2 and 3 */
++#define REALVIEW_PB11MP_GPIO0_BASE		0x10013000	/* GPIO port 0 */
++#define REALVIEW_PB11MP_RTC_BASE		0x10017000	/* Real Time Clock */
++#define REALVIEW_PB11MP_TIMER4_5_BASE		0x10018000	/* Timer 4/5 */
++#define REALVIEW_PB11MP_TIMER6_7_BASE		0x10019000	/* Timer 6/7 */
++#define REALVIEW_PB11MP_SCTL_BASE		0x1001A000	/* System Controller */
++#define REALVIEW_PB11MP_CLCD_BASE		0x10020000	/* CLCD */
++#define REALVIEW_PB11MP_ONB_SRAM_BASE		0x10060000	/* On-board SRAM */
++#define REALVIEW_PB11MP_DMC_BASE		0x100E0000	/* DMC configuration */
++#define REALVIEW_PB11MP_SMC_BASE		0x100E1000	/* SMC configuration */
++#define REALVIEW_PB11MP_CAN_BASE		0x100E2000	/* CAN bus */
++#define REALVIEW_PB11MP_CF_BASE			0x18000000	/* Compact flash */
++#define REALVIEW_PB11MP_CF_MEM_BASE		0x18003000	/* SMC for Compact flash */
++#define REALVIEW_PB11MP_GIC_CPU_BASE		0x1E000000	/* Generic interrupt controller CPU interface */
++#define REALVIEW_PB11MP_FLASH0_BASE		0x40000000
++#define REALVIEW_PB11MP_FLASH0_SIZE		SZ_64M
++#define REALVIEW_PB11MP_FLASH1_BASE		0x44000000
++#define REALVIEW_PB11MP_FLASH1_SIZE		SZ_64M
++#define REALVIEW_PB11MP_ETH_BASE		0x4E000000	/* Ethernet */
++#define REALVIEW_PB11MP_USB_BASE		0x4F000000	/* USB */
++#define REALVIEW_PB11MP_GIC_DIST_BASE		0x1E001000	/* Generic interrupt controller distributor */
++#define REALVIEW_PB11MP_LT_BASE			0xC0000000	/* Logic Tile expansion */
++#define REALVIEW_PB11MP_SDRAM6_BASE		0x70000000	/* SDRAM bank 6 256MB */
++#define REALVIEW_PB11MP_SDRAM7_BASE		0x80000000	/* SDRAM bank 7 256MB */
++
++#define REALVIEW_PB11MP_SYS_PLD_CTRL1		0x74
++
++/*
++ * PB11MPCore PCI regions
++ */
++#define REALVIEW_PB11MP_PCI_BASE		0x90040000	/* PCI-X Unit base */
++#define REALVIEW_PB11MP_PCI_IO_BASE		0x90050000	/* IO Region on AHB */
++#define REALVIEW_PB11MP_PCI_MEM_BASE		0xA0000000	/* MEM Region on AHB */
++
++#define REALVIEW_PB11MP_PCI_BASE_SIZE		0x10000		/* 16 Kb */
++#define REALVIEW_PB11MP_PCI_IO_SIZE		0x1000		/* 4 Kb */
++#define REALVIEW_PB11MP_PCI_MEM_SIZE		0x20000000	/* 512 MB */
++
++/*
++ * Testchip peripheral and fpga gic regions
++ */
++#define REALVIEW_TC11MP_SCU_BASE		0x1F000000	/* IRQ, Test chip */
++#define REALVIEW_TC11MP_GIC_CPU_BASE		0x1F000100	/* Test chip interrupt controller CPU interface */
++#define REALVIEW_TC11MP_TWD_BASE		0x1F000700
++#define REALVIEW_TC11MP_TWD_SIZE		0x00000100
++#define REALVIEW_TC11MP_GIC_DIST_BASE		0x1F001000	/* Test chip interrupt controller distributor */
++#define REALVIEW_TC11MP_L220_BASE		0x1F002000	/* L220 registers */
++
++/*
++ * Irqs
++ */
++#define IRQ_TC11MP_GIC_START			32
++#define IRQ_PB11MP_GIC_START			64
++
++/*
++ * ARM11MPCore test chip interrupt sources (primary GIC on the test chip)
++ */
++#define IRQ_TC11MP_AACI		(IRQ_TC11MP_GIC_START + 0)
++#define IRQ_TC11MP_TIMER0_1	(IRQ_TC11MP_GIC_START + 1)
++#define IRQ_TC11MP_TIMER2_3	(IRQ_TC11MP_GIC_START + 2)
++#define IRQ_TC11MP_USB		(IRQ_TC11MP_GIC_START + 3)
++#define IRQ_TC11MP_UART0	(IRQ_TC11MP_GIC_START + 4)
++#define IRQ_TC11MP_UART1	(IRQ_TC11MP_GIC_START + 5)
++#define IRQ_TC11MP_RTC		(IRQ_TC11MP_GIC_START + 6)
++#define IRQ_TC11MP_KMI0		(IRQ_TC11MP_GIC_START + 7)
++#define IRQ_TC11MP_KMI1		(IRQ_TC11MP_GIC_START + 8)
++#define IRQ_TC11MP_ETH		(IRQ_TC11MP_GIC_START + 9)
++#define IRQ_TC11MP_PB_IRQ1	(IRQ_TC11MP_GIC_START + 10)		/* main GIC */
++#define IRQ_TC11MP_PB_IRQ2	(IRQ_TC11MP_GIC_START + 11)		/* tile GIC */
++#define IRQ_TC11MP_PB_FIQ1	(IRQ_TC11MP_GIC_START + 12)		/* main GIC */
++#define IRQ_TC11MP_PB_FIQ2	(IRQ_TC11MP_GIC_START + 13)		/* tile GIC */
++#define IRQ_TC11MP_MMCI0A	(IRQ_TC11MP_GIC_START + 14)
++#define IRQ_TC11MP_MMCI0B	(IRQ_TC11MP_GIC_START + 15)
++
++#define IRQ_TC11MP_PMU_CPU0	(IRQ_TC11MP_GIC_START + 17)
++#define IRQ_TC11MP_PMU_CPU1	(IRQ_TC11MP_GIC_START + 18)
++#define IRQ_TC11MP_PMU_CPU2	(IRQ_TC11MP_GIC_START + 19)
++#define IRQ_TC11MP_PMU_CPU3	(IRQ_TC11MP_GIC_START + 20)
++#define IRQ_TC11MP_PMU_SCU0	(IRQ_TC11MP_GIC_START + 21)
++#define IRQ_TC11MP_PMU_SCU1	(IRQ_TC11MP_GIC_START + 22)
++#define IRQ_TC11MP_PMU_SCU2	(IRQ_TC11MP_GIC_START + 23)
++#define IRQ_TC11MP_PMU_SCU3	(IRQ_TC11MP_GIC_START + 24)
++#define IRQ_TC11MP_PMU_SCU4	(IRQ_TC11MP_GIC_START + 25)
++#define IRQ_TC11MP_PMU_SCU5	(IRQ_TC11MP_GIC_START + 26)
++#define IRQ_TC11MP_PMU_SCU6	(IRQ_TC11MP_GIC_START + 27)
++#define IRQ_TC11MP_PMU_SCU7	(IRQ_TC11MP_GIC_START + 28)
++
++#define IRQ_TC11MP_L220_EVENT	(IRQ_TC11MP_GIC_START + 29)
++#define IRQ_TC11MP_L220_SLAVE	(IRQ_TC11MP_GIC_START + 30)
++#define IRQ_TC11MP_L220_DECODE	(IRQ_TC11MP_GIC_START + 31)
++
++/*
++ * RealView PB11MPCore GIC interrupt sources (secondary GIC on the board)
++ */
++#define IRQ_PB11MP_WATCHDOG	(IRQ_PB11MP_GIC_START + 0)	/* Watchdog timer */
++#define IRQ_PB11MP_SOFT		(IRQ_PB11MP_GIC_START + 1)	/* Software interrupt */
++#define IRQ_PB11MP_COMMRx	(IRQ_PB11MP_GIC_START + 2)	/* Debug Comm Rx interrupt */
++#define IRQ_PB11MP_COMMTx	(IRQ_PB11MP_GIC_START + 3)	/* Debug Comm Tx interrupt */
++#define IRQ_PB11MP_GPIO0	(IRQ_PB11MP_GIC_START + 6)	/* GPIO 0 */
++#define IRQ_PB11MP_GPIO1	(IRQ_PB11MP_GIC_START + 7)	/* GPIO 1 */
++#define IRQ_PB11MP_GPIO2	(IRQ_PB11MP_GIC_START + 8)	/* GPIO 2 */
++								/* 9 reserved */
++#define IRQ_PB11MP_RTC_GIC1	(IRQ_PB11MP_GIC_START + 10)	/* Real Time Clock */
++#define IRQ_PB11MP_SSP		(IRQ_PB11MP_GIC_START + 11)	/* Synchronous Serial Port */
++#define IRQ_PB11MP_UART0_GIC1	(IRQ_PB11MP_GIC_START + 12)	/* UART 0 on development chip */
++#define IRQ_PB11MP_UART1_GIC1	(IRQ_PB11MP_GIC_START + 13)	/* UART 1 on development chip */
++#define IRQ_PB11MP_UART2	(IRQ_PB11MP_GIC_START + 14)	/* UART 2 on development chip */
++#define IRQ_PB11MP_UART3	(IRQ_PB11MP_GIC_START + 15)	/* UART 3 on development chip */
++#define IRQ_PB11MP_SCI		(IRQ_PB11MP_GIC_START + 16)	/* Smart Card Interface */
++#define IRQ_PB11MP_MMCI0A_GIC1	(IRQ_PB11MP_GIC_START + 17)	/* Multimedia Card 0A */
++#define IRQ_PB11MP_MMCI0B_GIC1	(IRQ_PB11MP_GIC_START + 18)	/* Multimedia Card 0B */
++#define IRQ_PB11MP_AACI_GIC1	(IRQ_PB11MP_GIC_START + 19)	/* Audio Codec */
++#define IRQ_PB11MP_KMI0_GIC1	(IRQ_PB11MP_GIC_START + 20)	/* Keyboard/Mouse port 0 */
++#define IRQ_PB11MP_KMI1_GIC1	(IRQ_PB11MP_GIC_START + 21)	/* Keyboard/Mouse port 1 */
++#define IRQ_PB11MP_CHARLCD	(IRQ_PB11MP_GIC_START + 22)	/* Character LCD */
++#define IRQ_PB11MP_CLCD		(IRQ_PB11MP_GIC_START + 23)	/* CLCD controller */
++#define IRQ_PB11MP_DMAC		(IRQ_PB11MP_GIC_START + 24)	/* DMA controller */
++#define IRQ_PB11MP_PWRFAIL	(IRQ_PB11MP_GIC_START + 25)	/* Power failure */
++#define IRQ_PB11MP_PISMO	(IRQ_PB11MP_GIC_START + 26)	/* PISMO interface */
++#define IRQ_PB11MP_DoC		(IRQ_PB11MP_GIC_START + 27)	/* Disk on Chip memory controller */
++#define IRQ_PB11MP_ETH_GIC1	(IRQ_PB11MP_GIC_START + 28)	/* Ethernet controller */
++#define IRQ_PB11MP_USB_GIC1	(IRQ_PB11MP_GIC_START + 29)	/* USB controller */
++#define IRQ_PB11MP_TSPEN	(IRQ_PB11MP_GIC_START + 30)	/* Touchscreen pen */
++#define IRQ_PB11MP_TSKPAD	(IRQ_PB11MP_GIC_START + 31)	/* Touchscreen keypad */
++
++#define IRQ_PB11MP_SMC		-1
++#define IRQ_PB11MP_SCTL		-1
++
++#define NR_GIC_PB11MP		2
++
++/*
++ * Only define NR_IRQS if less than NR_IRQS_PB11MP
++ */
++#define NR_IRQS_PB11MP		(IRQ_TC11MP_GIC_START + 96)
++
++#if defined(CONFIG_MACH_REALVIEW_PB11MP)
++
++#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PB11MP)
++#undef NR_IRQS
++#define NR_IRQS			NR_IRQS_PB11MP
++#endif
++
++#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PB11MP)
++#undef MAX_GIC_NR
++#define MAX_GIC_NR		NR_GIC_PB11MP
++#endif
++
++#endif	/* CONFIG_MACH_REALVIEW_PB11MP */
++
++#endif	/* __ASM_ARCH_BOARD_PB11MP_H */
+diff --git a/include/asm-arm/arch-realview/debug-macro.S b/include/asm-arm/arch-realview/debug-macro.S
+index f17efc6..c8c860c 100644
+--- a/include/asm-arm/arch-realview/debug-macro.S
++++ b/include/asm-arm/arch-realview/debug-macro.S
+@@ -15,7 +15,7 @@
+ 		mrc	p15, 0, \rx, c1, c0
+ 		tst	\rx, #1			@ MMU enabled?
+ 		moveq	\rx,      #0x10000000
+-		movne	\rx,      #0xf1000000	@ virtual base
++		movne	\rx,      #0xf0000000	@ virtual base
+ 		orr	\rx, \rx, #0x00009000
+ 		.endm
+ 
+diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h
+index bad8d7c..1ee8313 100644
+--- a/include/asm-arm/arch-realview/hardware.h
++++ b/include/asm-arm/arch-realview/hardware.h
+@@ -25,7 +25,7 @@
+ #include <asm/sizes.h>
+ 
+ /* macro to get at IO space when running virtually */
+-#define IO_ADDRESS(x)		((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000)
++#define IO_ADDRESS(x)		(((x) & 0x0fffffff) + 0xf0000000)
+ #define __io_address(n)		__io(IO_ADDRESS(n))
+ 
+ #endif
+diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h
+index ad0c911..ccbac59 100644
+--- a/include/asm-arm/arch-realview/irqs.h
++++ b/include/asm-arm/arch-realview/irqs.h
+@@ -23,6 +23,8 @@
+ #define __ASM_ARCH_IRQS_H
+ 
+ #include <asm/arch/board-eb.h>
++#include <asm/arch/board-pb11mp.h>
++#include <asm/arch/board-pb1176.h>
+ 
+ #define IRQ_LOCALTIMER		29
+ #define IRQ_LOCALWDOG		30
+diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h
+index 4fd351b..424c0aa 100644
+--- a/include/asm-arm/arch-realview/platform.h
++++ b/include/asm-arm/arch-realview/platform.h
+@@ -32,9 +32,6 @@
+ #define REALVIEW_SSRAM_BASE           /* REALVIEW_SSMC_BASE ? */
+ #define REALVIEW_SSRAM_SIZE           SZ_2M
+ 
+-#define REALVIEW_FLASH_BASE           0x40000000
+-#define REALVIEW_FLASH_SIZE           SZ_64M
+-
+ /* 
+  *  SDRAM
+  */
+@@ -175,42 +172,20 @@
+ #define REALVIEW_INTREG_CARDINSERT   0x03    /* Signal insertion of MMC card                   */
+ 
+ /*
+- * REALVIEW peripheral addresses
++ * RealView common peripheral addresses
+  */
+ #define REALVIEW_SCTL_BASE            0x10001000	/* System controller */
+ #define REALVIEW_I2C_BASE             0x10002000	/* I2C control */
+-	/* Reserved 0x10003000 */
+ #define REALVIEW_AACI_BASE            0x10004000	/* Audio */
+ #define REALVIEW_MMCI0_BASE           0x10005000	/* MMC interface */
+ #define REALVIEW_KMI0_BASE            0x10006000	/* KMI interface */
+ #define REALVIEW_KMI1_BASE            0x10007000	/* KMI 2nd interface */
+ #define REALVIEW_CHAR_LCD_BASE        0x10008000	/* Character LCD */
+-#define REALVIEW_UART0_BASE           0x10009000	/* UART 0 */
+-#define REALVIEW_UART1_BASE           0x1000A000	/* UART 1 */
+-#define REALVIEW_UART2_BASE           0x1000B000	/* UART 2 */
+-#define REALVIEW_UART3_BASE           0x1000C000	/* UART 3 */
+-#define REALVIEW_SSP_BASE             0x1000D000	/* Synchronous Serial Port */
+ #define REALVIEW_SCI_BASE             0x1000E000	/* Smart card controller */
+-	/* Reserved 0x1000F000 */
+-#define REALVIEW_WATCHDOG_BASE        0x10010000	/* watchdog interface */
+-#define REALVIEW_TIMER0_1_BASE        0x10011000	/* Timer 0 and 1 */
+-#define REALVIEW_TIMER2_3_BASE        0x10012000	/* Timer 2 and 3 */
+-#define REALVIEW_GPIO0_BASE           0x10013000	/* GPIO port 0 */
+ #define REALVIEW_GPIO1_BASE           0x10014000	/* GPIO port 1 */
+ #define REALVIEW_GPIO2_BASE           0x10015000	/* GPIO port 2 */
+-	/* Reserved 0x10016000 */
+-#define REALVIEW_RTC_BASE             0x10017000	/* Real Time Clock */
+ #define REALVIEW_DMC_BASE             0x10018000	/* DMC configuration */
+-#define REALVIEW_PCI_CORE_BASE        0x10019000	/* PCI configuration */
+-	/* Reserved 0x1001A000 - 0x1001FFFF */
+-#define REALVIEW_CLCD_BASE            0x10020000	/* CLCD */
+ #define REALVIEW_DMAC_BASE            0x10030000	/* DMA controller */
+-#define REALVIEW_GIC_CPU_BASE         0x10040000	/* Generic interrupt controller CPU interface */
+-#define REALVIEW_GIC_DIST_BASE        0x10041000	/* Generic interrupt controller distributor */
+-#define REALVIEW_SMC_BASE             0x10080000	/* SMC */
+-	/* Reserved 0x10090000 - 0x100EFFFF */
+-
+-#define REALVIEW_ETH_BASE             0x4E000000	/* Ethernet */
+ 
+ /* PCI space */
+ #define REALVIEW_PCI_BASE             0x41000000	/* PCI Interface */
+diff --git a/include/asm-arm/arch-realview/scu.h b/include/asm-arm/arch-realview/scu.h
+index 08b3db8..d55802d 100644
+--- a/include/asm-arm/arch-realview/scu.h
++++ b/include/asm-arm/arch-realview/scu.h
+@@ -1,8 +1,13 @@
+ #ifndef __ASMARM_ARCH_SCU_H
+ #define __ASMARM_ARCH_SCU_H
+ 
+-#include <asm/arch/board-eb.h>
+-
+-#define SCU_BASE	REALVIEW_EB11MP_SCU_BASE
++/*
++ * SCU registers
++ */
++#define SCU_CTRL		0x00
++#define SCU_CONFIG		0x04
++#define SCU_CPU_STATUS		0x08
++#define SCU_INVALIDATE		0x0c
++#define SCU_FPGA_REVISION	0x10
+ 
+ #endif
+diff --git a/include/asm-arm/arch-realview/uncompress.h b/include/asm-arm/arch-realview/uncompress.h
+index 3d5c2db..4c905d7 100644
+--- a/include/asm-arm/arch-realview/uncompress.h
++++ b/include/asm-arm/arch-realview/uncompress.h
+@@ -18,28 +18,50 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+ #include <asm/hardware.h>
++#include <asm/mach-types.h>
+ 
+-#include <asm/arch/platform.h>
++#include <asm/arch/board-eb.h>
++#include <asm/arch/board-pb11mp.h>
++#include <asm/arch/board-pb1176.h>
+ 
+-#define AMBA_UART_DR	(*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x00))
+-#define AMBA_UART_LCRH	(*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x2c))
+-#define AMBA_UART_CR	(*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x30))
+-#define AMBA_UART_FR	(*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x18))
++#define AMBA_UART_DR(base)	(*(volatile unsigned char *)((base) + 0x00))
++#define AMBA_UART_LCRH(base)	(*(volatile unsigned char *)((base) + 0x2c))
++#define AMBA_UART_CR(base)	(*(volatile unsigned char *)((base) + 0x30))
++#define AMBA_UART_FR(base)	(*(volatile unsigned char *)((base) + 0x18))
++
++/*
++ * Return the UART base address
++ */
++static inline unsigned long get_uart_base(void)
++{
++	if (machine_is_realview_eb())
++		return REALVIEW_EB_UART0_BASE;
++	else if (machine_is_realview_pb11mp())
++		return REALVIEW_PB11MP_UART0_BASE;
++	else if (machine_is_realview_pb1176())
++		return REALVIEW_PB1176_UART0_BASE;
++	else
++		return 0;
++}
+ 
+ /*
+  * This does not append a newline
+  */
+ static inline void putc(int c)
+ {
+-	while (AMBA_UART_FR & (1 << 5))
++	unsigned long base = get_uart_base();
++
++	while (AMBA_UART_FR(base) & (1 << 5))
+ 		barrier();
+ 
+-	AMBA_UART_DR = c;
++	AMBA_UART_DR(base) = c;
+ }
+ 
+ static inline void flush(void)
+ {
+-	while (AMBA_UART_FR & (1 << 3))
++	unsigned long base = get_uart_base();
++
++	while (AMBA_UART_FR(base) & (1 << 3))
+ 		barrier();
+ }
+ 
+diff --git a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
+index dba9df9..ecae9e7 100644
+--- a/include/asm-arm/arch-s3c2410/regs-clock.h
++++ b/include/asm-arm/arch-s3c2410/regs-clock.h
+@@ -137,7 +137,7 @@ s3c2410_get_pll(unsigned int pllval, unsigned int baseclk)
+ 
+ #define S3C2412_CLKDIVN_PDIVN		(1<<2)
+ #define S3C2412_CLKDIVN_HDIVN_MASK	(3<<0)
+-#define S3C2421_CLKDIVN_ARMDIVN		(1<<3)
++#define S3C2412_CLKDIVN_ARMDIVN		(1<<3)
+ #define S3C2412_CLKDIVN_DVSEN		(1<<4)
+ #define S3C2412_CLKDIVN_HALFHCLK	(1<<5)
+ #define S3C2412_CLKDIVN_USB48DIV	(1<<6)
+diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
+index 0ad75d7..497dd06 100644
+--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
++++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
+@@ -529,11 +529,13 @@
+ #define S3C2410_GPD14_INP	(0x00 << 28)
+ #define S3C2410_GPD14_OUTP	(0x01 << 28)
+ #define S3C2410_GPD14_VD22	(0x02 << 28)
++#define S3C2410_GPD14_nSS1	(0x03 << 28)
+ 
+ #define S3C2410_GPD15           S3C2410_GPIONO(S3C2410_GPIO_BANKD, 15)
+ #define S3C2410_GPD15_INP	(0x00 << 30)
+ #define S3C2410_GPD15_OUTP	(0x01 << 30)
+ #define S3C2410_GPD15_VD23	(0x02 << 30)
++#define S3C2410_GPD15_nSS0	(0x03 << 30)
+ 
+ #define S3C2410_GPD_PUPDIS(x)  (1<<(x))
+ 
+@@ -801,12 +803,14 @@
+ #define S3C2410_GPG2_INP      (0x00 << 4)
+ #define S3C2410_GPG2_OUTP     (0x01 << 4)
+ #define S3C2410_GPG2_EINT10   (0x02 << 4)
++#define S3C2410_GPG2_nSS0     (0x03 << 4)
+ #define S3C2400_GPG2_CDCLK    (0x02 << 4)
+ 
+ #define S3C2410_GPG3          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 3)
+ #define S3C2410_GPG3_INP      (0x00 << 6)
+ #define S3C2410_GPG3_OUTP     (0x01 << 6)
+ #define S3C2410_GPG3_EINT11   (0x02 << 6)
++#define S3C2410_GPG3_nSS1     (0x03 << 6)
+ #define S3C2400_GPG3_I2SSDO   (0x02 << 6)
+ #define S3C2400_GPG3_I2SSDI   (0x03 << 6)
+ 
+diff --git a/include/asm-arm/arch-s3c2410/regs-s3c2412-mem.h b/include/asm-arm/arch-s3c2410/regs-s3c2412-mem.h
+new file mode 100644
+index 0000000..c8c793e
+--- /dev/null
++++ b/include/asm-arm/arch-s3c2410/regs-s3c2412-mem.h
+@@ -0,0 +1,29 @@
++/* linux/include/asm-arm/arch-s3c2410/regs-s3c2412-mem.h
++ *
++ * Copyright (c) 2008 Simtec Electronics
++ *	Ben Dooks <ben at simtec.co.uk>
++ *	http://armlinux.simtec.co.uk/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * S3C2412 memory register definitions
++*/
++
++#ifndef __ASM_ARM_REGS_S3C2412_MEM
++#define __ASM_ARM_REGS_S3C2412_MEM
++
++#ifndef S3C2412_MEMREG
++#define S3C2412_MEMREG(x) (S3C24XX_VA_MEMCTRL + (x))
++#endif
++
++#define S3C2412_BANKCFG			S3C2412_MEMREG(0x00)
++#define S3C2412_BANKCON1		S3C2412_MEMREG(0x04)
++#define S3C2412_BANKCON2		S3C2412_MEMREG(0x08)
++#define S3C2412_BANKCON3		S3C2412_MEMREG(0x0C)
++
++#define S3C2412_REFRESH			S3C2412_MEMREG(0x10)
++#define S3C2412_TIMEOUT			S3C2412_MEMREG(0x14)
++
++#endif /*  __ASM_ARM_REGS_S3C2412_MEM */
+diff --git a/include/asm-arm/arch-s3c2410/system-reset.h b/include/asm-arm/arch-s3c2410/system-reset.h
+new file mode 100644
+index 0000000..1615bce
+--- /dev/null
++++ b/include/asm-arm/arch-s3c2410/system-reset.h
+@@ -0,0 +1,64 @@
++/* linux/include/asm-arm/arch-s3c2410/system-reset.h
++ *
++ * Copyright (c) 2008 Simtec Electronics
++ *	Ben Dooks <ben at simtec.co.uk>
++ *
++ * S3C2410 - System define for arch_reset() function
++ *
++ * This program is free software; you can redistribute 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/hardware.h>
++#include <asm/io.h>
++
++#include <asm/plat-s3c/regs-watchdog.h>
++#include <asm/arch/regs-clock.h>
++
++#include <linux/clk.h>
++#include <linux/err.h>
++
++extern void (*s3c24xx_reset_hook)(void);
++
++static void
++arch_reset(char mode)
++{
++	struct clk *wdtclk;
++
++	if (mode == 's') {
++		cpu_reset(0);
++	}
++
++	if (s3c24xx_reset_hook)
++		s3c24xx_reset_hook();
++
++	printk("arch_reset: attempting watchdog reset\n");
++
++	__raw_writel(0, S3C2410_WTCON);	  /* disable watchdog, to be safe  */
++
++	wdtclk = clk_get(NULL, "watchdog");
++	if (!IS_ERR(wdtclk)) {
++		clk_enable(wdtclk);
++	} else
++		printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
++
++	/* put initial values into count and data */
++	__raw_writel(0x80, S3C2410_WTCNT);
++	__raw_writel(0x80, S3C2410_WTDAT);
++
++	/* set the watchdog to go and reset... */
++	__raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
++		     S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
++
++	/* wait for reset to assert... */
++	mdelay(500);
++
++	printk(KERN_ERR "Watchdog reset failed to assert reset\n");
++
++	/* delay to allow the serial port to show the message */
++	mdelay(50);
++
++	/* we'll take a jump through zero as a poor second */
++	cpu_reset(0);
++}
+diff --git a/include/asm-arm/arch-s3c2410/system.h b/include/asm-arm/arch-s3c2410/system.h
+index 14de4e5..ad25808 100644
+--- a/include/asm-arm/arch-s3c2410/system.h
++++ b/include/asm-arm/arch-s3c2410/system.h
+@@ -17,12 +17,8 @@
+ #include <asm/arch/idle.h>
+ #include <asm/arch/reset.h>
+ 
+-#include <asm/plat-s3c/regs-watchdog.h>
+ #include <asm/arch/regs-clock.h>
+ 
+-#include <linux/clk.h>
+-#include <linux/err.h>
+-
+ void (*s3c24xx_idle)(void);
+ void (*s3c24xx_reset_hook)(void);
+ 
+@@ -59,44 +55,4 @@ static void arch_idle(void)
+ 		s3c24xx_default_idle();
+ }
+ 
+-static void
+-arch_reset(char mode)
+-{
+-	struct clk *wdtclk;
+-
+-	if (mode == 's') {
+-		cpu_reset(0);
+-	}
+-
+-	if (s3c24xx_reset_hook)
+-		s3c24xx_reset_hook();
+-
+-	printk("arch_reset: attempting watchdog reset\n");
+-
+-	__raw_writel(0, S3C2410_WTCON);	  /* disable watchdog, to be safe  */
+-
+-	wdtclk = clk_get(NULL, "watchdog");
+-	if (!IS_ERR(wdtclk)) {
+-		clk_enable(wdtclk);
+-	} else
+-		printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
+-
+-	/* put initial values into count and data */
+-	__raw_writel(0x80, S3C2410_WTCNT);
+-	__raw_writel(0x80, S3C2410_WTDAT);
+-
+-	/* set the watchdog to go and reset... */
+-	__raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
+-		     S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
+-
+-	/* wait for reset to assert... */
+-	mdelay(500);
+-
+-	printk(KERN_ERR "Watchdog reset failed to assert reset\n");
+-
+-	/* delay to allow the serial port to show the message */
+-	mdelay(50);
+-
+-	/* we'll take a jump through zero as a poor second */
+-	cpu_reset(0);
+-}
++#include <asm/arch/system-reset.h>
+diff --git a/include/asm-arm/arch-sa1100/gpio.h b/include/asm-arm/arch-sa1100/gpio.h
+index e7a9d26..93d3395 100644
+--- a/include/asm-arm/arch-sa1100/gpio.h
++++ b/include/asm-arm/arch-sa1100/gpio.h
+@@ -26,35 +26,28 @@
+ 
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+-
+-static inline int gpio_request(unsigned gpio, const char *label)
+-{
+-	return 0;
+-}
+-
+-static inline void gpio_free(unsigned gpio)
+-{
+-	return;
+-}
+-
+-extern int gpio_direction_input(unsigned gpio);
+-extern int gpio_direction_output(unsigned gpio, int value);
+-
++#include <asm-generic/gpio.h>
+ 
+ static inline int gpio_get_value(unsigned gpio)
+ {
+-	return GPLR & GPIO_GPIO(gpio);
++	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
++		return GPLR & GPIO_GPIO(gpio);
++	else
++		return __gpio_get_value(gpio);
+ }
+ 
+ static inline void gpio_set_value(unsigned gpio, int value)
+ {
+-	if (value)
+-		GPSR = GPIO_GPIO(gpio);
++	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
++		if (value)
++			GPSR = GPIO_GPIO(gpio);
++		else
++			GPCR = GPIO_GPIO(gpio);
+ 	else
+-		GPCR = GPIO_GPIO(gpio);
++		__gpio_set_value(gpio, value);
+ }
+ 
+-#include <asm-generic/gpio.h>			/* cansleep wrappers */
++#define gpio_cansleep	__gpio_cansleep
+ 
+ static inline unsigned gpio_to_irq(unsigned gpio)
+ {
+diff --git a/include/asm-arm/cpu-multi32.h b/include/asm-arm/cpu-multi32.h
+index 715e18a..3479de9 100644
+--- a/include/asm-arm/cpu-multi32.h
++++ b/include/asm-arm/cpu-multi32.h
+@@ -21,6 +21,10 @@ extern struct processor {
+ 	 */
+ 	void (*_data_abort)(unsigned long pc);
+ 	/*
++	 * Retrieve prefetch fault address
++	 */
++	unsigned long (*_prefetch_abort)(unsigned long lr);
++	/*
+ 	 * Set up any processor specifics
+ 	 */
+ 	void (*_proc_init)(void);
+diff --git a/include/asm-arm/glue.h b/include/asm-arm/glue.h
+index 22274ce..a97a182 100644
+--- a/include/asm-arm/glue.h
++++ b/include/asm-arm/glue.h
+@@ -40,83 +40,110 @@
+  *	  v6_early	- ARMv6 generic early abort handler
+  *	  v7_early	- ARMv7 generic early abort handler
+  */
+-#undef CPU_ABORT_HANDLER
+-#undef MULTI_ABORT
++#undef CPU_DABORT_HANDLER
++#undef MULTI_DABORT
+ 
+ #if defined(CONFIG_CPU_ARM610)
+-# ifdef CPU_ABORT_HANDLER
+-#  define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++#  define MULTI_DABORT 1
+ # else
+-#  define CPU_ABORT_HANDLER cpu_arm6_data_abort
++#  define CPU_DABORT_HANDLER cpu_arm6_data_abort
+ # endif
+ #endif
+ 
+ #if defined(CONFIG_CPU_ARM710)
+-# ifdef CPU_ABORT_HANDLER
+-#  define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++#  define MULTI_DABORT 1
+ # else
+-#  define CPU_ABORT_HANDLER cpu_arm7_data_abort
++#  define CPU_DABORT_HANDLER cpu_arm7_data_abort
+ # endif
+ #endif
+ 
+ #ifdef CONFIG_CPU_ABRT_LV4T
+-# ifdef CPU_ABORT_HANDLER
+-#  define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++#  define MULTI_DABORT 1
+ # else
+-#  define CPU_ABORT_HANDLER v4t_late_abort
++#  define CPU_DABORT_HANDLER v4t_late_abort
+ # endif
+ #endif
+ 
+ #ifdef CONFIG_CPU_ABRT_EV4
+-# ifdef CPU_ABORT_HANDLER
+-#  define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++#  define MULTI_DABORT 1
+ # else
+-#  define CPU_ABORT_HANDLER v4_early_abort
++#  define CPU_DABORT_HANDLER v4_early_abort
+ # endif
+ #endif
+ 
+ #ifdef CONFIG_CPU_ABRT_EV4T
+-# ifdef CPU_ABORT_HANDLER
+-#  define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++#  define MULTI_DABORT 1
+ # else
+-#  define CPU_ABORT_HANDLER v4t_early_abort
++#  define CPU_DABORT_HANDLER v4t_early_abort
+ # endif
+ #endif
+ 
+ #ifdef CONFIG_CPU_ABRT_EV5TJ
+-# ifdef CPU_ABORT_HANDLER
+-#  define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++#  define MULTI_DABORT 1
+ # else
+-#  define CPU_ABORT_HANDLER v5tj_early_abort
++#  define CPU_DABORT_HANDLER v5tj_early_abort
+ # endif
+ #endif
+ 
+ #ifdef CONFIG_CPU_ABRT_EV5T
+-# ifdef CPU_ABORT_HANDLER
+-#  define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++#  define MULTI_DABORT 1
+ # else
+-#  define CPU_ABORT_HANDLER v5t_early_abort
++#  define CPU_DABORT_HANDLER v5t_early_abort
+ # endif
+ #endif
+ 
+ #ifdef CONFIG_CPU_ABRT_EV6
+-# ifdef CPU_ABORT_HANDLER
+-#  define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++#  define MULTI_DABORT 1
+ # else
+-#  define CPU_ABORT_HANDLER v6_early_abort
++#  define CPU_DABORT_HANDLER v6_early_abort
+ # endif
+ #endif
+ 
+ #ifdef CONFIG_CPU_ABRT_EV7
+-# ifdef CPU_ABORT_HANDLER
+-#  define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++#  define MULTI_DABORT 1
+ # else
+-#  define CPU_ABORT_HANDLER v7_early_abort
++#  define CPU_DABORT_HANDLER v7_early_abort
+ # endif
+ #endif
+ 
+-#ifndef CPU_ABORT_HANDLER
++#ifndef CPU_DABORT_HANDLER
+ #error Unknown data abort handler type
+ #endif
+ 
++/*
++ * Prefetch abort handler.  If the CPU has an IFAR use that, otherwise
++ * use the address of the aborted instruction
++ */
++#undef CPU_PABORT_HANDLER
++#undef MULTI_PABORT
++
++#ifdef CONFIG_CPU_PABRT_IFAR
++# ifdef CPU_PABORT_HANDLER
++#  define MULTI_PABORT 1
++# else
++#  define CPU_PABORT_HANDLER(reg, insn)	mrc p15, 0, reg, cr6, cr0, 2
++# endif
++#endif
++
++#ifdef CONFIG_CPU_PABRT_NOIFAR
++# ifdef CPU_PABORT_HANDLER
++#  define MULTI_PABORT 1
++# else
++#  define CPU_PABORT_HANDLER(reg, insn)	mov reg, insn
++# endif
++#endif
++
++#ifndef CPU_PABORT_HANDLER
++#error Unknown prefetch abort handler type
++#endif
++
+ #endif
+diff --git a/include/asm-arm/hardware/arm_scu.h b/include/asm-arm/hardware/arm_scu.h
+deleted file mode 100644
+index 7d28eb5..0000000
+--- a/include/asm-arm/hardware/arm_scu.h
++++ /dev/null
+@@ -1,15 +0,0 @@
+-#ifndef ASMARM_HARDWARE_ARM_SCU_H
+-#define ASMARM_HARDWARE_ARM_SCU_H
+-
+-#include <asm/arch/scu.h>
+-
+-/*
+- * SCU registers
+- */
+-#define SCU_CTRL		0x00
+-#define SCU_CONFIG		0x04
+-#define SCU_CPU_STATUS		0x08
+-#define SCU_INVALIDATE		0x0c
+-#define SCU_FPGA_REVISION	0x10
+-
+-#endif
+diff --git a/include/asm-arm/hardware/iop3xx-adma.h b/include/asm-arm/hardware/iop3xx-adma.h
+index 5c529e6..a32b86a 100644
+--- a/include/asm-arm/hardware/iop3xx-adma.h
++++ b/include/asm-arm/hardware/iop3xx-adma.h
+@@ -260,7 +260,7 @@ static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
+ static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
+ 					int *slots_per_op)
+ {
+-	const static int slot_count_table[] = { 0,
++	static const int slot_count_table[] = { 0,
+ 						1, 1, 1, 1, /* 01 - 04 */
+ 						2, 2, 2, 2, /* 05 - 08 */
+ 						4, 4, 4, 4, /* 09 - 12 */
+@@ -369,7 +369,7 @@ static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+ /* translate the src_idx to a descriptor word index */
+ static inline int __desc_idx(int src_idx)
+ {
+-	const static int desc_idx_table[] = { 0, 0, 0, 0,
++	static const int desc_idx_table[] = { 0, 0, 0, 0,
+ 					      0, 1, 2, 3,
+ 					      5, 6, 7, 8,
+ 					      9, 10, 11, 12,
+@@ -767,20 +767,12 @@ static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+ static inline void iop_chan_append(struct iop_adma_chan *chan)
+ {
+ 	u32 dma_chan_ctrl;
+-	/* workaround dropped interrupts on 3xx */
+-	mod_timer(&chan->cleanup_watchdog, jiffies + msecs_to_jiffies(3));
+ 
+ 	dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+ 	dma_chan_ctrl |= 0x2;
+ 	__raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+ }
+ 
+-static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+-{
+-	if (!busy)
+-		del_timer(&chan->cleanup_watchdog);
+-}
+-
+ static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+ {
+ 	return __raw_readl(DMA_CSR(chan));
+diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
+index ede377e..18f6937 100644
+--- a/include/asm-arm/hardware/iop3xx.h
++++ b/include/asm-arm/hardware/iop3xx.h
+@@ -29,6 +29,7 @@ extern void gpio_line_config(int line, int direction);
+ extern int  gpio_line_get(int line);
+ extern void gpio_line_set(int line, int value);
+ extern int init_atu;
++extern int iop3xx_get_init_atu(void);
+ #endif
+ 
+ 
+@@ -112,14 +113,6 @@ extern int init_atu;
+ #define IOP3XX_INIT_ATU_DISABLE -1
+ #define IOP3XX_INIT_ATU_ENABLE	 1
+ 
+-#ifdef CONFIG_IOP3XX_ATU
+-#define iop3xx_get_init_atu(x) (init_atu == IOP3XX_INIT_ATU_DEFAULT ?\
+-				IOP3XX_INIT_ATU_ENABLE : init_atu)
+-#else
+-#define iop3xx_get_init_atu(x) (init_atu == IOP3XX_INIT_ATU_DEFAULT ?\
+-				IOP3XX_INIT_ATU_DISABLE : init_atu)
+-#endif
+-
+ /* Messaging Unit  */
+ #define IOP3XX_IMR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0310)
+ #define IOP3XX_IMR1		(volatile u32 *)IOP3XX_REG_ADDR(0x0314)
+diff --git a/include/asm-arm/hardware/iop_adma.h b/include/asm-arm/hardware/iop_adma.h
+index ca8e71f..cb7e361 100644
+--- a/include/asm-arm/hardware/iop_adma.h
++++ b/include/asm-arm/hardware/iop_adma.h
+@@ -51,7 +51,6 @@ struct iop_adma_device {
+  * @common: common dmaengine channel object members
+  * @last_used: place holder for allocation to continue from where it left off
+  * @all_slots: complete domain of slots usable by the channel
+- * @cleanup_watchdog: workaround missed interrupts on iop3xx
+  * @slots_allocated: records the actual size of the descriptor slot pool
+  * @irq_tasklet: bottom half where iop_adma_slot_cleanup runs
+  */
+@@ -65,7 +64,6 @@ struct iop_adma_chan {
+ 	struct dma_chan common;
+ 	struct iop_adma_desc_slot *last_used;
+ 	struct list_head all_slots;
+-	struct timer_list cleanup_watchdog;
+ 	int slots_allocated;
+ 	struct tasklet_struct irq_tasklet;
+ };
+diff --git a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h
+index d37bf74..dfb8330 100644
+--- a/include/asm-arm/hardware/scoop.h
++++ b/include/asm-arm/hardware/scoop.h
+@@ -40,6 +40,7 @@ struct scoop_config {
+ 	unsigned short io_dir;
+ 	unsigned short suspend_clr;
+ 	unsigned short suspend_set;
++	int gpio_base;
+ };
+ 
+ /* Structure for linking scoop devices to PCMCIA sockets */
+@@ -62,7 +63,7 @@ struct scoop_pcmcia_config {
+ extern struct scoop_pcmcia_config *platform_scoop_config;
+ 
+ void reset_scoop(struct device *dev);
+-unsigned short set_scoop_gpio(struct device *dev, unsigned short bit);
+-unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit);
++unsigned short __deprecated set_scoop_gpio(struct device *dev, unsigned short bit);
++unsigned short __deprecated reset_scoop_gpio(struct device *dev, unsigned short bit);
+ unsigned short read_scoop_reg(struct device *dev, unsigned short reg);
+ void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data);
+diff --git a/include/asm-arm/hwcap.h b/include/asm-arm/hwcap.h
+index 01a1391..81f4c89 100644
+--- a/include/asm-arm/hwcap.h
++++ b/include/asm-arm/hwcap.h
+@@ -15,6 +15,7 @@
+ #define HWCAP_JAVA	256
+ #define HWCAP_IWMMXT	512
+ #define HWCAP_CRUNCH	1024
++#define HWCAP_THUMBEE	2048
+ 
+ #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+ /*
+diff --git a/include/asm-arm/ide.h b/include/asm-arm/ide.h
+index f348fcf..88f4d23 100644
+--- a/include/asm-arm/ide.h
++++ b/include/asm-arm/ide.h
+@@ -17,14 +17,6 @@
+ #define MAX_HWIFS	4
+ #endif
+ 
+-#if !defined(CONFIG_ARCH_L7200)
+-# ifdef CONFIG_ARCH_CLPS7500
+-#  define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-# else
+-#  define ide_default_io_ctl(base)	(0)
+-# endif
+-#endif /* !ARCH_L7200 */
+-
+ #define __ide_mm_insw(port,addr,len)	readsw(port,addr,len)
+ #define __ide_mm_insl(port,addr,len)	readsl(port,addr,len)
+ #define __ide_mm_outsw(port,addr,len)	writesw(port,addr,len)
+diff --git a/include/asm-arm/mach/pci.h b/include/asm-arm/mach/pci.h
+index 24621c4..9d4f6b5 100644
+--- a/include/asm-arm/mach/pci.h
++++ b/include/asm-arm/mach/pci.h
+@@ -55,6 +55,7 @@ void pci_common_init(struct hw_pci *);
+ extern int iop3xx_pci_setup(int nr, struct pci_sys_data *);
+ extern struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *);
+ extern void iop3xx_pci_preinit(void);
++extern void iop3xx_pci_preinit_cond(void);
+ 
+ extern int dc21285_setup(int nr, struct pci_sys_data *);
+ extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
+diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
+index d9bfb39..9ba4d71 100644
+--- a/include/asm-arm/memory.h
++++ b/include/asm-arm/memory.h
+@@ -217,7 +217,10 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
+ #ifndef CONFIG_DISCONTIGMEM
+ 
+ #define ARCH_PFN_OFFSET		PHYS_PFN_OFFSET
++
++#ifndef CONFIG_SPARSEMEM
+ #define pfn_valid(pfn)		((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
++#endif
+ 
+ #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+ #define virt_addr_valid(kaddr)	((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+diff --git a/include/asm-arm/plat-orion/ehci-orion.h b/include/asm-arm/plat-orion/ehci-orion.h
+new file mode 100644
+index 0000000..7857056
+--- /dev/null
++++ b/include/asm-arm/plat-orion/ehci-orion.h
+@@ -0,0 +1,19 @@
++/*
++ * include/asm-arm/plat-orion/ehci-orion.h
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_EHCI_ORION_H
++#define __ASM_PLAT_ORION_EHCI_ORION_H
++
++#include <linux/mbus.h>
++
++struct orion_ehci_data {
++	struct mbus_dram_target_info	*dram;
++};
++
++
++#endif
+diff --git a/include/asm-arm/plat-orion/irq.h b/include/asm-arm/plat-orion/irq.h
+new file mode 100644
+index 0000000..94aeed9
+--- /dev/null
++++ b/include/asm-arm/plat-orion/irq.h
+@@ -0,0 +1,17 @@
++/*
++ * include/asm-arm/plat-orion/irq.h
++ *
++ * Marvell Orion SoC IRQ handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_IRQ_H
++#define __ASM_PLAT_ORION_IRQ_H
++
++void orion_irq_init(unsigned int irq_start, void __iomem *maskaddr);
++
++
++#endif
+diff --git a/include/asm-arm/plat-orion/orion_nand.h b/include/asm-arm/plat-orion/orion_nand.h
+new file mode 100644
+index 0000000..ffd3852
+--- /dev/null
++++ b/include/asm-arm/plat-orion/orion_nand.h
+@@ -0,0 +1,24 @@
++/*
++ * include/asm-arm/plat-orion/orion_nand.h
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_ORION_NAND_H
++#define __ASM_PLAT_ORION_ORION_NAND_H
++
++/*
++ * Device bus NAND private data
++ */
++struct orion_nand_data {
++	struct mtd_partition *parts;
++	u32 nr_parts;
++	u8 ale;		/* address line number connected to ALE */
++	u8 cle;		/* address line number connected to CLE */
++	u8 width;	/* buswidth */
++};
++
++
++#endif
+diff --git a/include/asm-arm/plat-orion/pcie.h b/include/asm-arm/plat-orion/pcie.h
+new file mode 100644
+index 0000000..6434ac6
+--- /dev/null
++++ b/include/asm-arm/plat-orion/pcie.h
+@@ -0,0 +1,31 @@
++/*
++ * include/asm-arm/plat-orion/pcie.h
++ *
++ * Marvell Orion SoC PCIe handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_PCIE_H
++#define __ASM_PLAT_ORION_PCIE_H
++
++u32 orion_pcie_dev_id(void __iomem *base);
++u32 orion_pcie_rev(void __iomem *base);
++int orion_pcie_link_up(void __iomem *base);
++int orion_pcie_get_local_bus_nr(void __iomem *base);
++void orion_pcie_set_local_bus_nr(void __iomem *base, int nr);
++void orion_pcie_setup(void __iomem *base,
++		      struct mbus_dram_target_info *dram);
++int orion_pcie_rd_conf(void __iomem *base, struct pci_bus *bus,
++		       u32 devfn, int where, int size, u32 *val);
++int orion_pcie_rd_conf_tlp(void __iomem *base, struct pci_bus *bus,
++			   u32 devfn, int where, int size, u32 *val);
++int orion_pcie_rd_conf_wa(void __iomem *wa_base, struct pci_bus *bus,
++			  u32 devfn, int where, int size, u32 *val);
++int orion_pcie_wr_conf(void __iomem *base, struct pci_bus *bus,
++		       u32 devfn, int where, int size, u32 val);
++
++
++#endif
+diff --git a/include/asm-arm/plat-orion/time.h b/include/asm-arm/plat-orion/time.h
+new file mode 100644
+index 0000000..0e85cc8
+--- /dev/null
++++ b/include/asm-arm/plat-orion/time.h
+@@ -0,0 +1,17 @@
++/*
++ * include/asm-arm/plat-orion/time.h
++ *
++ * Marvell Orion SoC time handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_TIME_H
++#define __ASM_PLAT_ORION_TIME_H
++
++void orion_time_init(unsigned int irq, unsigned int tclk);
++
++
++#endif
+diff --git a/include/asm-arm/plat-s3c/nand.h b/include/asm-arm/plat-s3c/nand.h
+index 8816f7f..ad6bbe9 100644
+--- a/include/asm-arm/plat-s3c/nand.h
++++ b/include/asm-arm/plat-s3c/nand.h
+@@ -22,11 +22,14 @@
+ */
+ 
+ struct s3c2410_nand_set {
++	unsigned int		disable_ecc : 1;
++
+ 	int			nr_chips;
+ 	int			nr_partitions;
+ 	char			*name;
+ 	int			*nr_map;
+ 	struct mtd_partition	*partitions;
++	struct nand_ecclayout	*ecc_layout;
+ };
+ 
+ struct s3c2410_platform_nand {
+@@ -36,6 +39,8 @@ struct s3c2410_platform_nand {
+ 	int	twrph0;	/* active time for nWE/nOE */
+ 	int	twrph1;	/* time for release CLE/ALE from nWE/nOE inactive */
+ 
++	unsigned int	ignore_unset_ecc : 1;
++
+ 	int			nr_sets;
+ 	struct s3c2410_nand_set *sets;
+ 
+diff --git a/include/asm-arm/semaphore-helper.h b/include/asm-arm/semaphore-helper.h
+deleted file mode 100644
+index 1d7f198..0000000
+--- a/include/asm-arm/semaphore-helper.h
++++ /dev/null
+@@ -1,84 +0,0 @@
+-#ifndef ASMARM_SEMAPHORE_HELPER_H
+-#define ASMARM_SEMAPHORE_HELPER_H
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (atomic_read(&sem->count) <= 0)
+-		sem->waking++;
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->waking > 0) {
+-		sem->waking--;
+-		ret = 1;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking non zero interruptible
+- *	1	got the lock
+- *	0	go to sleep
+- *	-EINTR	interrupted
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+-						struct task_struct *tsk)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->waking > 0) {
+-		sem->waking--;
+-		ret = 1;
+-	} else if (signal_pending(tsk)) {
+-		atomic_inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;	
+-}
+-
+-/*
+- * waking_non_zero_try_lock:
+- *	1	failed to lock
+- *	0	got the lock
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 1;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->waking <= 0)
+-		atomic_inc(&sem->count);
+-	else {
+-		sem->waking--;
+-		ret = 0;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-#endif
+diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h
+index 1c8b441..d9b2034 100644
+--- a/include/asm-arm/semaphore.h
++++ b/include/asm-arm/semaphore.h
+@@ -1,98 +1 @@
+-/*
+- * linux/include/asm-arm/semaphore.h
+- */
+-#ifndef __ASM_ARM_SEMAPHORE_H
+-#define __ASM_ARM_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-#include <linux/spinlock.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/atomic.h>
+-#include <asm/locks.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INIT(name, cnt)				\
+-{								\
+-	.count	= ATOMIC_INIT(cnt),				\
+-	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count)	\
+-	struct semaphore name = __SEMAPHORE_INIT(name,count)
+-
+-#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+-	atomic_set(&sem->count, val);
+-	sem->sleepers = 0;
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX(struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED(struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-/*
+- * special register calling convention
+- */
+-asmlinkage void __down_failed(void);
+-asmlinkage int  __down_interruptible_failed(void);
+-asmlinkage int  __down_trylock_failed(void);
+-asmlinkage void __up_wakeup(void);
+-
+-extern void __down(struct semaphore * sem);
+-extern int  __down_interruptible(struct semaphore * sem);
+-extern int  __down_trylock(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down" is the actual routine that waits...
+- */
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-	__down_op(sem, __down_failed);
+-}
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down_interruptible" is the actual routine that waits...
+- */
+-static inline int down_interruptible (struct semaphore * sem)
+-{
+-	might_sleep();
+-	return __down_op_ret(sem, __down_interruptible_failed);
+-}
+-
+-static inline int down_trylock(struct semaphore *sem)
+-{
+-	return __down_op_ret(sem, __down_trylock_failed);
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	__up_op(sem, __up_wakeup);
+-}
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-arm/sparsemem.h b/include/asm-arm/sparsemem.h
+new file mode 100644
+index 0000000..2771581
+--- /dev/null
++++ b/include/asm-arm/sparsemem.h
+@@ -0,0 +1,10 @@
++#ifndef ASMARM_SPARSEMEM_H
++#define ASMARM_SPARSEMEM_H
++
++#include <asm/memory.h>
++
++#define MAX_PHYSADDR_BITS	32
++#define MAX_PHYSMEM_BITS	32
++#define SECTION_SIZE_BITS	NODE_MEM_SIZE_BITS
++
++#endif
+diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
+index 4178435..f5a6647 100644
+--- a/include/asm-arm/thread_info.h
++++ b/include/asm-arm/thread_info.h
+@@ -62,6 +62,9 @@ struct thread_info {
+ 	struct crunch_state	crunchstate;
+ 	union fp_state		fpstate __attribute__((aligned(8)));
+ 	union vfp_state		vfpstate;
++#ifdef CONFIG_ARM_THUMBEE
++	unsigned long		thumbee_state;	/* ThumbEE Handler Base register */
++#endif
+ 	struct restart_block	restart_block;
+ };
+ 
+diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
+index 88e868b..7c57008 100644
+--- a/include/asm-arm/unistd.h
++++ b/include/asm-arm/unistd.h
+@@ -376,9 +376,11 @@
+ #define __NR_kexec_load			(__NR_SYSCALL_BASE+347)
+ #define __NR_utimensat			(__NR_SYSCALL_BASE+348)
+ #define __NR_signalfd			(__NR_SYSCALL_BASE+349)
+-#define __NR_timerfd			(__NR_SYSCALL_BASE+350)
++#define __NR_timerfd_create		(__NR_SYSCALL_BASE+350)
+ #define __NR_eventfd			(__NR_SYSCALL_BASE+351)
+ #define __NR_fallocate			(__NR_SYSCALL_BASE+352)
++#define __NR_timerfd_settime		(__NR_SYSCALL_BASE+353)
++#define __NR_timerfd_gettime		(__NR_SYSCALL_BASE+354)
+ 
+ /*
+  * The following SWIs are ARM private.
+diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
+index 7597b0b..a4e2d28 100644
+--- a/include/asm-avr32/arch-at32ap/board.h
++++ b/include/asm-avr32/arch-at32ap/board.h
+@@ -38,9 +38,7 @@ struct platform_device *
+ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
+ 		     unsigned long fbmem_start, unsigned long fbmem_len);
+ 
+-struct usba_platform_data {
+-	int vbus_pin;
+-};
++struct usba_platform_data;
+ struct platform_device *
+ at32_add_device_usba(unsigned int id, struct usba_platform_data *data);
+ 
+@@ -68,7 +66,10 @@ struct platform_device *at32_add_device_pwm(u32 mask);
+ struct platform_device *
+ at32_add_device_ssc(unsigned int id, unsigned int flags);
+ 
+-struct platform_device *at32_add_device_twi(unsigned int id);
++struct i2c_board_info;
++struct platform_device *at32_add_device_twi(unsigned int id,
++					    struct i2c_board_info *b,
++					    unsigned int n);
+ struct platform_device *at32_add_device_mci(unsigned int id);
+ struct platform_device *at32_add_device_ac97c(unsigned int id);
+ struct platform_device *at32_add_device_abdac(unsigned int id);
+diff --git a/include/asm-avr32/arch-at32ap/pm.h b/include/asm-avr32/arch-at32ap/pm.h
+new file mode 100644
+index 0000000..356e430
+--- /dev/null
++++ b/include/asm-avr32/arch-at32ap/pm.h
+@@ -0,0 +1,48 @@
++/*
++ * AVR32 AP Power Management.
++ *
++ * Copyright (C) 2008 Atmel Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_AVR32_ARCH_PM_H
++#define __ASM_AVR32_ARCH_PM_H
++
++/* Possible arguments to the "sleep" instruction */
++#define CPU_SLEEP_IDLE		0
++#define CPU_SLEEP_FROZEN	1
++#define CPU_SLEEP_STANDBY	2
++#define CPU_SLEEP_STOP		3
++#define CPU_SLEEP_STATIC	5
++
++#ifndef __ASSEMBLY__
++extern void cpu_enter_idle(void);
++
++extern bool disable_idle_sleep;
++
++static inline void cpu_disable_idle_sleep(void)
++{
++	disable_idle_sleep = true;
++}
++
++static inline void cpu_enable_idle_sleep(void)
++{
++	disable_idle_sleep = false;
++}
++
++static inline void cpu_idle_sleep(void)
++{
++	/*
++	 * If we're using the COUNT and COMPARE registers for
++	 * timekeeping, we can't use the IDLE state.
++	 */
++	if (disable_idle_sleep)
++		cpu_relax();
++	else
++		cpu_enter_idle();
++}
++#endif
++
++#endif /* __ASM_AVR32_ARCH_PM_H */
+diff --git a/include/asm-avr32/arch-at32ap/time.h b/include/asm-avr32/arch-at32ap/time.h
+deleted file mode 100644
+index cc8a434..0000000
+--- a/include/asm-avr32/arch-at32ap/time.h
++++ /dev/null
+@@ -1,112 +0,0 @@
+-/*
+- * Copyright (C) 2007 Atmel Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#ifndef _ASM_AVR32_ARCH_AT32AP_TIME_H
+-#define _ASM_AVR32_ARCH_AT32AP_TIME_H
+-
+-#include <linux/platform_device.h>
+-
+-extern struct irqaction timer_irqaction;
+-extern struct platform_device at32_systc0_device;
+-extern void local_timer_interrupt(int irq, void *dev_id);
+-
+-#define TIMER_BCR					0x000000c0
+-#define TIMER_BCR_SYNC						 0
+-#define TIMER_BMR					0x000000c4
+-#define TIMER_BMR_TC0XC0S					 0
+-#define TIMER_BMR_TC1XC1S					 2
+-#define TIMER_BMR_TC2XC2S					 4
+-#define TIMER_CCR					0x00000000
+-#define TIMER_CCR_CLKDIS					 1
+-#define TIMER_CCR_CLKEN						 0
+-#define TIMER_CCR_SWTRG						 2
+-#define TIMER_CMR					0x00000004
+-#define TIMER_CMR_ABETRG					10
+-#define TIMER_CMR_ACPA						16
+-#define TIMER_CMR_ACPC						18
+-#define TIMER_CMR_AEEVT						20
+-#define TIMER_CMR_ASWTRG					22
+-#define TIMER_CMR_BCPB						24
+-#define TIMER_CMR_BCPC						26
+-#define TIMER_CMR_BEEVT						28
+-#define TIMER_CMR_BSWTRG					30
+-#define TIMER_CMR_BURST						 4
+-#define TIMER_CMR_CLKI						 3
+-#define TIMER_CMR_CPCDIS					 7
+-#define TIMER_CMR_CPCSTOP					 6
+-#define TIMER_CMR_CPCTRG					14
+-#define TIMER_CMR_EEVT						10
+-#define TIMER_CMR_EEVTEDG					 8
+-#define TIMER_CMR_ENETRG					12
+-#define TIMER_CMR_ETRGEDG					 8
+-#define TIMER_CMR_LDBDIS					 7
+-#define TIMER_CMR_LDBSTOP					 6
+-#define TIMER_CMR_LDRA						16
+-#define TIMER_CMR_LDRB						18
+-#define TIMER_CMR_TCCLKS					 0
+-#define TIMER_CMR_WAVE						15
+-#define TIMER_CMR_WAVSEL					13
+-#define TIMER_CV					0x00000010
+-#define TIMER_CV_CV						 0
+-#define TIMER_IDR					0x00000028
+-#define TIMER_IDR_COVFS						 0
+-#define TIMER_IDR_CPAS						 2
+-#define TIMER_IDR_CPBS						 3
+-#define TIMER_IDR_CPCS						 4
+-#define TIMER_IDR_ETRGS						 7
+-#define TIMER_IDR_LDRAS						 5
+-#define TIMER_IDR_LDRBS						 6
+-#define TIMER_IDR_LOVRS						 1
+-#define TIMER_IER					0x00000024
+-#define TIMER_IER_COVFS						 0
+-#define TIMER_IER_CPAS						 2
+-#define TIMER_IER_CPBS						 3
+-#define TIMER_IER_CPCS						 4
+-#define TIMER_IER_ETRGS						 7
+-#define TIMER_IER_LDRAS						 5
+-#define TIMER_IER_LDRBS						 6
+-#define TIMER_IER_LOVRS						 1
+-#define TIMER_IMR					0x0000002c
+-#define TIMER_IMR_COVFS						 0
+-#define TIMER_IMR_CPAS						 2
+-#define TIMER_IMR_CPBS						 3
+-#define TIMER_IMR_CPCS						 4
+-#define TIMER_IMR_ETRGS						 7
+-#define TIMER_IMR_LDRAS						 5
+-#define TIMER_IMR_LDRBS						 6
+-#define TIMER_IMR_LOVRS						 1
+-#define TIMER_RA					0x00000014
+-#define TIMER_RA_RA						 0
+-#define TIMER_RB					0x00000018
+-#define TIMER_RB_RB						 0
+-#define TIMER_RC					0x0000001c
+-#define TIMER_RC_RC						 0
+-#define TIMER_SR					0x00000020
+-#define TIMER_SR_CLKSTA						16
+-#define TIMER_SR_COVFS						 0
+-#define TIMER_SR_CPAS						 2
+-#define TIMER_SR_CPBS						 3
+-#define TIMER_SR_CPCS						 4
+-#define TIMER_SR_ETRGS						 7
+-#define TIMER_SR_LDRAS						 5
+-#define TIMER_SR_LDRBS						 6
+-#define TIMER_SR_LOVRS						 1
+-#define TIMER_SR_MTIOA						17
+-#define TIMER_SR_MTIOB						18
+-
+-/* Bit manipulation macros */
+-#define TIMER_BIT(name)		(1 << TIMER_##name)
+-#define TIMER_BF(name,value)	((value) << TIMER_##name)
+-
+-/* Register access macros */
+-#define timer_read(port,instance,reg) \
+-	__raw_readl(port + (0x40 * instance) + TIMER_##reg)
+-#define timer_write(port,instance,reg,value) \
+-	__raw_writel((value), port + (0x40 * instance) + TIMER_##reg)
+-
+-#endif /* _ASM_AVR32_ARCH_AT32AP_TIME_H */
+diff --git a/include/asm-avr32/asm.h b/include/asm-avr32/asm.h
+index 515c761..a2c64f4 100644
+--- a/include/asm-avr32/asm.h
++++ b/include/asm-avr32/asm.h
+@@ -12,10 +12,10 @@
+ #include <asm/asm-offsets.h>
+ #include <asm/thread_info.h>
+ 
+-#define mask_interrupts		ssrf	SR_GM_BIT
+-#define mask_exceptions		ssrf	SR_EM_BIT
+-#define unmask_interrupts	csrf	SR_GM_BIT
+-#define unmask_exceptions	csrf	SR_EM_BIT
++#define mask_interrupts		ssrf	SYSREG_GM_OFFSET
++#define mask_exceptions		ssrf	SYSREG_EM_OFFSET
++#define unmask_interrupts	csrf	SYSREG_GM_OFFSET
++#define unmask_exceptions	csrf	SYSREG_EM_OFFSET
+ 
+ #ifdef CONFIG_FRAME_POINTER
+ 	.macro	save_fp
+diff --git a/include/asm-avr32/intc.h b/include/asm-avr32/intc.h
+deleted file mode 100644
+index 1ac9ca7..0000000
+--- a/include/asm-avr32/intc.h
++++ /dev/null
+@@ -1,128 +0,0 @@
+-#ifndef __ASM_AVR32_INTC_H
+-#define __ASM_AVR32_INTC_H
+-
+-#include <linux/sysdev.h>
+-#include <linux/interrupt.h>
+-
+-struct irq_controller;
+-struct irqaction;
+-struct pt_regs;
+-
+-struct platform_device;
+-
+-/* Information about the internal interrupt controller */
+-struct intc_device {
+-	/* ioremapped address of configuration block */
+-	void __iomem *regs;
+-
+-	/* the physical device */
+-	struct platform_device *pdev;
+-
+-	/* Number of interrupt lines per group. */
+-	unsigned int irqs_per_group;
+-
+-	/* The highest group ID + 1 */
+-	unsigned int nr_groups;
+-
+-	/*
+-	 * Bitfield indicating which groups are actually in use.  The
+-	 * size of the array is
+-	 * ceil(group_max / (8 * sizeof(unsigned int))).
+-	 */
+-	unsigned int group_mask[];
+-};
+-
+-struct irq_controller_class {
+-	/*
+-	 * A short name identifying this kind of controller.
+-	 */
+-	const char *typename;
+-	/*
+-	 * Handle the IRQ.  Must do any necessary acking and masking.
+-	 */
+-	irqreturn_t (*handle)(int irq, void *dev_id, struct pt_regs *regs);
+-	/*
+-	 * Register a new IRQ handler.
+-	 */
+-	int (*setup)(struct irq_controller *ctrl, unsigned int irq,
+-		     struct irqaction *action);
+-	/*
+-	 * Unregister a IRQ handler.
+-	 */
+-	void (*free)(struct irq_controller *ctrl, unsigned int irq,
+-		     void *dev_id);
+-	/*
+-	 * Mask the IRQ in the interrupt controller.
+-	 */
+-	void (*mask)(struct irq_controller *ctrl, unsigned int irq);
+-	/*
+-	 * Unmask the IRQ in the interrupt controller.
+-	 */
+-	void (*unmask)(struct irq_controller *ctrl, unsigned int irq);
+-	/*
+-	 * Set the type of the IRQ. See below for possible types.
+-	 * Return -EINVAL if a given type is not supported
+-	 */
+-	int (*set_type)(struct irq_controller *ctrl, unsigned int irq,
+-			unsigned int type);
+-	/*
+-	 * Return the IRQ type currently set
+-	 */
+-	unsigned int (*get_type)(struct irq_controller *ctrl, unsigned int irq);
+-};
+-
+-struct irq_controller {
+-	struct irq_controller_class *class;
+-	unsigned int irq_group;
+-	unsigned int first_irq;
+-	unsigned int nr_irqs;
+-	struct list_head list;
+-};
+-
+-struct intc_group_desc {
+-	struct irq_controller *ctrl;
+-	irqreturn_t (*handle)(int, void *, struct pt_regs *);
+-	unsigned long flags;
+-	void *dev_id;
+-	const char *devname;
+-};
+-
+-/*
+- * The internal interrupt controller.  Defined in board/part-specific
+- * devices.c.
+- * TODO: Should probably be defined per-cpu.
+- */
+-extern struct intc_device intc;
+-
+-extern int request_internal_irq(unsigned int irq,
+-				irqreturn_t (*handler)(int, void *, struct pt_regs *),
+-				unsigned long irqflags,
+-				const char *devname, void *dev_id);
+-extern void free_internal_irq(unsigned int irq);
+-
+-/* Only used by time_init() */
+-extern int setup_internal_irq(unsigned int irq, struct intc_group_desc *desc);
+-
+-/*
+- * Set interrupt priority for a given group. `group' can be found by
+- * using irq_to_group(irq). Priority can be from 0 (lowest) to 3
+- * (highest). Higher-priority interrupts will preempt lower-priority
+- * interrupts (unless interrupts are masked globally).
+- *
+- * This function does not check for conflicts within a group.
+- */
+-extern int intc_set_priority(unsigned int group,
+-			     unsigned int priority);
+-
+-/*
+- * Returns a bitmask of pending interrupts in a group.
+- */
+-extern unsigned long intc_get_pending(unsigned int group);
+-
+-/*
+- * Register a new external interrupt controller.  Returns the first
+- * external IRQ number that is assigned to the new controller.
+- */
+-extern int intc_register_controller(struct irq_controller *ctrl);
+-
+-#endif /* __ASM_AVR32_INTC_H */
+diff --git a/include/asm-avr32/irq.h b/include/asm-avr32/irq.h
+index 9315724..c563b77 100644
+--- a/include/asm-avr32/irq.h
++++ b/include/asm-avr32/irq.h
+@@ -14,6 +14,11 @@
+ #ifndef __ASSEMBLER__
+ int nmi_enable(void);
+ void nmi_disable(void);
++
++/*
++ * Returns a bitmask of pending interrupts in a group.
++ */
++extern unsigned long intc_get_pending(unsigned int group);
+ #endif
+ 
+ #endif /* __ASM_AVR32_IOCTLS_H */
+diff --git a/include/asm-avr32/page.h b/include/asm-avr32/page.h
+index 5582968..cbbc5ca 100644
+--- a/include/asm-avr32/page.h
++++ b/include/asm-avr32/page.h
+@@ -8,13 +8,11 @@
+ #ifndef __ASM_AVR32_PAGE_H
+ #define __ASM_AVR32_PAGE_H
+ 
++#include <linux/const.h>
++
+ /* PAGE_SHIFT determines the page size */
+ #define PAGE_SHIFT	12
+-#ifdef __ASSEMBLY__
+-#define PAGE_SIZE	(1 << PAGE_SHIFT)
+-#else
+-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+-#endif
++#define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
+ #define PAGE_MASK	(~(PAGE_SIZE-1))
+ #define PTE_MASK	PAGE_MASK
+ 
+diff --git a/include/asm-avr32/semaphore.h b/include/asm-avr32/semaphore.h
+index feaf1d4..d9b2034 100644
+--- a/include/asm-avr32/semaphore.h
++++ b/include/asm-avr32/semaphore.h
+@@ -1,108 +1 @@
+-/*
+- * SMP- and interrupt-safe semaphores.
+- *
+- * Copyright (C) 2006 Atmel Corporation
+- *
+- * Based on include/asm-i386/semaphore.h
+- *   Copyright (C) 1996 Linus Torvalds
+- *
+- * This program is free software; you can 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_AVR32_SEMAPHORE_H
+-#define __ASM_AVR32_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	atomic_set(&sem->count, val);
+-	sem->sleepers = 0;
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-void __down(struct semaphore * sem);
+-int  __down_interruptible(struct semaphore * sem);
+-void __up(struct semaphore * sem);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/i386/kernel/semaphore.c
+- */
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-	if (unlikely(atomic_dec_return (&sem->count) < 0))
+-		__down (sem);
+-}
+-
+-/*
+- * Interruptible try to acquire a semaphore.  If we obtained
+- * it, return zero.  If we were interrupted, returns -EINTR
+- */
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-
+-	might_sleep();
+-	if (unlikely(atomic_dec_return (&sem->count) < 0))
+-		ret = __down_interruptible (sem);
+-	return ret;
+-}
+-
+-/*
+- * Non-blockingly attempt to down() a semaphore.
+- * Returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	return atomic_dec_if_positive(&sem->count) < 0;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	if (unlikely(atomic_inc_return (&sem->count) <= 0))
+-		__up (sem);
+-}
+-
+-#endif /*__ASM_AVR32_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-avr32/serial.h b/include/asm-avr32/serial.h
+new file mode 100644
+index 0000000..5ecaebc
+--- /dev/null
++++ b/include/asm-avr32/serial.h
+@@ -0,0 +1,13 @@
++#ifndef _ASM_SERIAL_H
++#define _ASM_SERIAL_H
++
++/*
++ * This assumes you have a 1.8432 MHz clock for your UART.
++ *
++ * It'd be nice if someone built a serial card with a 24.576 MHz
++ * clock, since the 16550A is capable of handling a top speed of 1.5
++ * megabits/second; but this requires the faster clock.
++ */
++#define BASE_BAUD (1843200 / 16)
++
++#endif /* _ASM_SERIAL_H */
+diff --git a/include/asm-avr32/xor.h b/include/asm-avr32/xor.h
+new file mode 100644
+index 0000000..99c87aa
+--- /dev/null
++++ b/include/asm-avr32/xor.h
+@@ -0,0 +1,6 @@
++#ifndef _ASM_XOR_H
++#define _ASM_XOR_H
++
++#include <asm-generic/xor.h>
++
++#endif
+diff --git a/include/asm-blackfin/.gitignore b/include/asm-blackfin/.gitignore
+new file mode 100644
+index 0000000..7858564
+--- /dev/null
++++ b/include/asm-blackfin/.gitignore
+@@ -0,0 +1 @@
+++mach
+diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h
+index 5dba3a7..716df7c 100644
+--- a/include/asm-blackfin/bfin-global.h
++++ b/include/asm-blackfin/bfin-global.h
+@@ -112,20 +112,10 @@ extern void init_leds(void);
+ 
+ extern const char bfin_board_name[];
+ extern unsigned long wall_jiffies;
+-extern unsigned long ipdt_table[];
+-extern unsigned long dpdt_table[];
+-extern unsigned long icplb_table[];
+-extern unsigned long dcplb_table[];
+-
+-extern unsigned long ipdt_swapcount_table[];
+-extern unsigned long dpdt_swapcount_table[];
+-
+-extern unsigned long table_start, table_end;
+ 
+ extern unsigned long bfin_sic_iwr[];
+ extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
+ extern struct file_operations dpmc_fops;
+-extern char _start;
+ extern unsigned long _ramstart, _ramend, _rambase;
+ extern unsigned long memory_start, memory_end, physical_mem_end;
+ extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
+diff --git a/include/asm-blackfin/bug.h b/include/asm-blackfin/bug.h
+index 41e53b2..6d3e11b 100644
+--- a/include/asm-blackfin/bug.h
++++ b/include/asm-blackfin/bug.h
+@@ -1,4 +1,17 @@
+ #ifndef _BLACKFIN_BUG_H
+ #define _BLACKFIN_BUG_H
++
++#ifdef CONFIG_BUG
++#define HAVE_ARCH_BUG
++
++#define BUG() do { \
++	dump_bfin_trace_buffer(); \
++	printk(KERN_EMERG "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
++	panic("BUG!"); \
++} while (0)
++
++#endif
++
+ #include <asm-generic/bug.h>
++
+ #endif
+diff --git a/include/asm-blackfin/cplb.h b/include/asm-blackfin/cplb.h
+index 654375c..5b0da9a 100644
+--- a/include/asm-blackfin/cplb.h
++++ b/include/asm-blackfin/cplb.h
+@@ -74,32 +74,6 @@
+ #define ASYNC_MEMORY_CPLB_COVERAGE	((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
+ 				 ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M)
+ 
+-/*
+-* Number of required data CPLB switchtable entries
+-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+-* approx 16 for smaller 1MB page size CPLBs for allignment purposes
+-* 1 for L1 Data Memory
+-* possibly 1 for L2 Data Memory
+-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+-* 1 for ASYNC Memory
+-*/
+-
+-
+-#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1 \
+-				 + ASYNC_MEMORY_CPLB_COVERAGE) * 2)
+-
+-/*
+-* Number of required instruction CPLB switchtable entries
+-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+-* approx 12 for smaller 1MB page size CPLBs for allignment purposes
+-* 1 for L1 Instruction Memory
+-* possibly 1 for L2 Instruction Memory
+-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+-*/
+-
+-#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1 + 1) * 2)
+-
+-
+ #define CPLB_ENABLE_ICACHE_P	0
+ #define CPLB_ENABLE_DCACHE_P	1
+ #define CPLB_ENABLE_DCACHE2_P	2
+diff --git a/include/asm-blackfin/dma-mapping.h b/include/asm-blackfin/dma-mapping.h
+index 282fabc..1a13c2f 100644
+--- a/include/asm-blackfin/dma-mapping.h
++++ b/include/asm-blackfin/dma-mapping.h
+@@ -27,6 +27,14 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+ 				 enum dma_data_direction direction);
+ 
++static inline dma_addr_t
++dma_map_page(struct device *dev, struct page *page,
++	     unsigned long offset, size_t size,
++	     enum dma_data_direction dir)
++{
++	return dma_map_single(dev, page_address(page) + offset, size, dir);
++}
++
+ /*
+  * Unmap a single streaming mode DMA translation.  The dma_addr and size
+  * must match what was provided for in a previous pci_map_single call.  All
+@@ -38,6 +46,13 @@ extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+ extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ 			  enum dma_data_direction direction);
+ 
++static inline void
++dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
++	       enum dma_data_direction dir)
++{
++	dma_unmap_single(dev, dma_addr, size, dir);
++}
++
+ /*
+  * Map a set of buffers described by scatterlist in streaming
+  * mode for DMA.  This is the scather-gather version of the
+diff --git a/include/asm-blackfin/dma.h b/include/asm-blackfin/dma.h
+index 5abaa2c..c0d5259 100644
+--- a/include/asm-blackfin/dma.h
++++ b/include/asm-blackfin/dma.h
+@@ -33,7 +33,6 @@
+ #include <linux/slab.h>
+ #include <asm/irq.h>
+ #include <asm/signal.h>
+-#include <asm/semaphore.h>
+ 
+ #include <linux/kernel.h>
+ #include <asm/mach/dma.h>
+@@ -192,4 +191,7 @@ void clear_dma_irqstat(unsigned int channel);
+ void *dma_memcpy(void *dest, const void *src, size_t count);
+ void *safe_dma_memcpy(void *dest, const void *src, size_t count);
+ 
++extern int channel2irq(unsigned int channel);
++extern struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL];
++
+ #endif
+diff --git a/include/asm-blackfin/gptimers.h b/include/asm-blackfin/gptimers.h
+index 4f318f1..0520d2a 100644
+--- a/include/asm-blackfin/gptimers.h
++++ b/include/asm-blackfin/gptimers.h
+@@ -22,6 +22,18 @@
+ # define TIMER0_GROUP_REG      TIMER_ENABLE
+ #endif
+ /*
++ * BF54x: 11 timers (BF542: 8 timers):
++ */
++#if defined(BF548_FAMILY)
++# ifdef CONFIG_BF542
++#  define MAX_BLACKFIN_GPTIMERS 8
++# else
++#  define MAX_BLACKFIN_GPTIMERS 11
++#  define TIMER8_GROUP_REG      TIMER_ENABLE1
++# endif
++# define TIMER0_GROUP_REG       TIMER_ENABLE0
++#endif
++/*
+  * BF561: 12 timers:
+  */
+ #if defined(CONFIG_BF561)
+@@ -44,40 +56,28 @@
+ #define TIMER0bit  0x0001  /*  0001b */
+ #define TIMER1bit  0x0002  /*  0010b */
+ #define TIMER2bit  0x0004  /*  0100b */
+-
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER3bit  0x0008
+-# define TIMER4bit  0x0010
+-# define TIMER5bit  0x0020
+-# define TIMER6bit  0x0040
+-# define TIMER7bit  0x0080
+-#endif
+-
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
+-# define TIMER8bit  0x0100
+-# define TIMER9bit  0x0200
+-# define TIMER10bit 0x0400
+-# define TIMER11bit 0x0800
+-#endif
++#define TIMER3bit  0x0008
++#define TIMER4bit  0x0010
++#define TIMER5bit  0x0020
++#define TIMER6bit  0x0040
++#define TIMER7bit  0x0080
++#define TIMER8bit  0x0100
++#define TIMER9bit  0x0200
++#define TIMER10bit 0x0400
++#define TIMER11bit 0x0800
+ 
+ #define TIMER0_id   0
+ #define TIMER1_id   1
+ #define TIMER2_id   2
+-
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER3_id   3
+-# define TIMER4_id   4
+-# define TIMER5_id   5
+-# define TIMER6_id   6
+-# define TIMER7_id   7
+-#endif
+-
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
+-# define TIMER8_id   8
+-# define TIMER9_id   9
+-# define TIMER10_id 10
+-# define TIMER11_id 11
+-#endif
++#define TIMER3_id   3
++#define TIMER4_id   4
++#define TIMER5_id   5
++#define TIMER6_id   6
++#define TIMER7_id   7
++#define TIMER8_id   8
++#define TIMER9_id   9
++#define TIMER10_id 10
++#define TIMER11_id 11
+ 
+ /* associated timers for ppi framesync: */
+ 
+@@ -124,45 +124,31 @@
+ /*
+  * Timer Status Register Bits
+  */
+-#define TIMER_STATUS_TIMIL0 0x0001
+-#define TIMER_STATUS_TIMIL1 0x0002
+-#define TIMER_STATUS_TIMIL2 0x0004
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER_STATUS_TIMIL3 0x00000008
+-# define TIMER_STATUS_TIMIL4 0x00010000
+-# define TIMER_STATUS_TIMIL5 0x00020000
+-# define TIMER_STATUS_TIMIL6 0x00040000
+-# define TIMER_STATUS_TIMIL7 0x00080000
+-# if (MAX_BLACKFIN_GPTIMERS > 8)
+-#  define TIMER_STATUS_TIMIL8  0x0001
+-#  define TIMER_STATUS_TIMIL9  0x0002
+-#  define TIMER_STATUS_TIMIL10 0x0004
+-#  define TIMER_STATUS_TIMIL11 0x0008
+-# endif
+-# define TIMER_STATUS_INTR   0x000F000F
+-#else
+-# define TIMER_STATUS_INTR   0x0007	/* any timer interrupt */
+-#endif
+-
+-#define TIMER_STATUS_TOVF0  0x0010	/* timer 0 overflow error */
+-#define TIMER_STATUS_TOVF1  0x0020
+-#define TIMER_STATUS_TOVF2  0x0040
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER_STATUS_TOVF3  0x00000080
+-# define TIMER_STATUS_TOVF4  0x00100000
+-# define TIMER_STATUS_TOVF5  0x00200000
+-# define TIMER_STATUS_TOVF6  0x00400000
+-# define TIMER_STATUS_TOVF7  0x00800000
+-# if (MAX_BLACKFIN_GPTIMERS > 8)
+-#  define TIMER_STATUS_TOVF8   0x0010
+-#  define TIMER_STATUS_TOVF9   0x0020
+-#  define TIMER_STATUS_TOVF10  0x0040
+-#  define TIMER_STATUS_TOVF11  0x0080
+-# endif
+-# define TIMER_STATUS_OFLOW  0x00F000F0
+-#else
+-# define TIMER_STATUS_OFLOW  0x0070	/* any timer overflow */
+-#endif
++#define TIMER_STATUS_TIMIL0  0x0001
++#define TIMER_STATUS_TIMIL1  0x0002
++#define TIMER_STATUS_TIMIL2  0x0004
++#define TIMER_STATUS_TIMIL3  0x00000008
++#define TIMER_STATUS_TIMIL4  0x00010000
++#define TIMER_STATUS_TIMIL5  0x00020000
++#define TIMER_STATUS_TIMIL6  0x00040000
++#define TIMER_STATUS_TIMIL7  0x00080000
++#define TIMER_STATUS_TIMIL8  0x0001
++#define TIMER_STATUS_TIMIL9  0x0002
++#define TIMER_STATUS_TIMIL10 0x0004
++#define TIMER_STATUS_TIMIL11 0x0008
++
++#define TIMER_STATUS_TOVF0   0x0010	/* timer 0 overflow error */
++#define TIMER_STATUS_TOVF1   0x0020
++#define TIMER_STATUS_TOVF2   0x0040
++#define TIMER_STATUS_TOVF3   0x00000080
++#define TIMER_STATUS_TOVF4   0x00100000
++#define TIMER_STATUS_TOVF5   0x00200000
++#define TIMER_STATUS_TOVF6   0x00400000
++#define TIMER_STATUS_TOVF7   0x00800000
++#define TIMER_STATUS_TOVF8   0x0010
++#define TIMER_STATUS_TOVF9   0x0020
++#define TIMER_STATUS_TOVF10  0x0040
++#define TIMER_STATUS_TOVF11  0x0080
+ 
+ /*
+  * Timer Slave Enable Status : write 1 to clear
+@@ -170,22 +156,16 @@
+ #define TIMER_STATUS_TRUN0  0x1000
+ #define TIMER_STATUS_TRUN1  0x2000
+ #define TIMER_STATUS_TRUN2  0x4000
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER_STATUS_TRUN3  0x00008000
+-# define TIMER_STATUS_TRUN4  0x10000000
+-# define TIMER_STATUS_TRUN5  0x20000000
+-# define TIMER_STATUS_TRUN6  0x40000000
+-# define TIMER_STATUS_TRUN7  0x80000000
+-# define TIMER_STATUS_TRUN   0xF000F000
+-# if (MAX_BLACKFIN_GPTIMERS > 8)
+-#  define TIMER_STATUS_TRUN8  0x1000
+-#  define TIMER_STATUS_TRUN9  0x2000
+-#  define TIMER_STATUS_TRUN10 0x4000
+-#  define TIMER_STATUS_TRUN11 0x8000
+-# endif
+-#else
+-# define TIMER_STATUS_TRUN   0x7000
+-#endif
++#define TIMER_STATUS_TRUN3  0x00008000
++#define TIMER_STATUS_TRUN4  0x10000000
++#define TIMER_STATUS_TRUN5  0x20000000
++#define TIMER_STATUS_TRUN6  0x40000000
++#define TIMER_STATUS_TRUN7  0x80000000
++#define TIMER_STATUS_TRUN   0xF000F000
++#define TIMER_STATUS_TRUN8  0x1000
++#define TIMER_STATUS_TRUN9  0x2000
++#define TIMER_STATUS_TRUN10 0x4000
++#define TIMER_STATUS_TRUN11 0x8000
+ 
+ /* The actual gptimer API */
+ 
+diff --git a/include/asm-blackfin/ide.h b/include/asm-blackfin/ide.h
+index 121e272..5b88de1 100644
+--- a/include/asm-blackfin/ide.h
++++ b/include/asm-blackfin/ide.h
+@@ -19,10 +19,6 @@
+ 
+ #define MAX_HWIFS	1
+ 
+-/* Legacy ... BLK_DEV_IDECS */
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+-
+ #include <asm-generic/ide_iops.h>
+ 
+ /****************************************************************************/
+diff --git a/include/asm-blackfin/mach-bf527/anomaly.h b/include/asm-blackfin/mach-bf527/anomaly.h
+index a891204..735fa02 100644
+--- a/include/asm-blackfin/mach-bf527/anomaly.h
++++ b/include/asm-blackfin/mach-bf527/anomaly.h
+@@ -2,12 +2,12 @@
+  * File: include/asm-blackfin/mach-bf527/anomaly.h
+  * Bugs: Enter bugs at http://blackfin.uclinux.org/
+  *
+- * Copyright (C) 2004-2007 Analog Devices Inc.
++ * Copyright (C) 2004-2008 Analog Devices Inc.
+  * Licensed under the GPL-2 or later.
+  */
+ 
+ /* This file shoule be up to date with:
+- *  - Revision A, May 30, 2007; ADSP-BF527 Blackfin Processor Anomaly List
++ *  - Revision C, 01/25/2008; ADSP-BF527 Blackfin Processor Anomaly List
+  */
+ 
+ #ifndef _MACH_ANOMALY_H_
+@@ -15,35 +15,85 @@
+ 
+ /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
+ #define ANOMALY_05000074 (1)
+-/* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
+-#define ANOMALY_05000119 (1)
+ /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
+ #define ANOMALY_05000122 (1)
+ /* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
+ #define ANOMALY_05000245 (1)
+ /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
+ #define ANOMALY_05000265 (1)
+-/* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */
+-#define ANOMALY_05000301 (1)
+-/* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
+-#define ANOMALY_05000312 (1)
+ /* Incorrect Access of OTP_STATUS During otp_write() Function */
+ #define ANOMALY_05000328 (1)
+ /* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
+ #define ANOMALY_05000337 (1)
+-/* TWI Does Not Operate Correctly Under Certain Signal Termination Conditions */
++/* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
++#define ANOMALY_05000341 (1)
++/* TWI May Not Operate Correctly Under Certain Signal Termination Conditions */
+ #define ANOMALY_05000342 (1)
+-/* Boot ROM Kernel Incorrectly Alters Reset Value of USB Register */
++/* USB Calibration Value Is Not Initialized */
++#define ANOMALY_05000346 (1)
++/* Preboot Routine Incorrectly Alters Reset Value of USB Register */
+ #define ANOMALY_05000347 (1)
++/* Security Features Are Not Functional */
++#define ANOMALY_05000348 (__SILICON_REVISION__ < 1)
++/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
++#define ANOMALY_05000355 (1)
++/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
++#define ANOMALY_05000357 (1)
++/* Incorrect Revision Number in DSPID Register */
++#define ANOMALY_05000364 (__SILICON_REVISION__ > 0)
++/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
++#define ANOMALY_05000366 (1)
++/* New Feature: Higher Default CCLK Rate */
++#define ANOMALY_05000368 (1)
++/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
++#define ANOMALY_05000371 (1)
++/* Authentication Fails To Initiate */
++#define ANOMALY_05000376 (__SILICON_REVISION__ > 0)
++/* Data Read From L3 Memory by USB DMA May be Corrupted */
++#define ANOMALY_05000380 (1)
++/* USB Full-speed Mode not Fully Tested */
++#define ANOMALY_05000381 (1)
++/* New Feature: Boot from OTP Memory */
++#define ANOMALY_05000385 (1)
++/* New Feature: bfrom_SysControl() Routine */
++#define ANOMALY_05000386 (1)
++/* New Feature: Programmable Preboot Settings */
++#define ANOMALY_05000387 (1)
++/* Reset Vector Must Not Be in SDRAM Memory Space */
++#define ANOMALY_05000389 (1)
++/* New Feature: pTempCurrent Added to ADI_BOOT_DATA Structure */
++#define ANOMALY_05000392 (1)
++/* New Feature: dTempByteCount Value Increased in ADI_BOOT_DATA Structure */
++#define ANOMALY_05000393 (1)
++/* New Feature: Log Buffer Functionality */
++#define ANOMALY_05000394 (1)
++/* New Feature: Hook Routine Functionality */
++#define ANOMALY_05000395 (1)
++/* New Feature: Header Indirect Bit */
++#define ANOMALY_05000396 (1)
++/* New Feature: BK_ONES, BK_ZEROS, and BK_DATECODE Constants */
++#define ANOMALY_05000397 (1)
++/* New Feature: SWRESET, DFRESET and WDRESET Bits Added to SYSCR Register */
++#define ANOMALY_05000398 (1)
++/* New Feature: BCODE_NOBOOT Added to BCODE Field of SYSCR Register */
++#define ANOMALY_05000399 (1)
++/* PPI Data Signals D0 and D8 do not Tristate After Disabling PPI */
++#define ANOMALY_05000401 (1)
+ 
+ /* Anomalies that don't exist on this proc */
+-#define ANOMALY_05000323 (0)
+-#define ANOMALY_05000244 (0)
+-#define ANOMALY_05000198 (0)
+ #define ANOMALY_05000125 (0)
+ #define ANOMALY_05000158 (0)
+-#define ANOMALY_05000273 (0)
++#define ANOMALY_05000183 (0)
++#define ANOMALY_05000198 (0)
++#define ANOMALY_05000230 (0)
++#define ANOMALY_05000244 (0)
++#define ANOMALY_05000261 (0)
+ #define ANOMALY_05000263 (0)
++#define ANOMALY_05000266 (0)
++#define ANOMALY_05000273 (0)
+ #define ANOMALY_05000311 (0)
+-#define ANOMALY_05000230 (0)
++#define ANOMALY_05000312 (0)
++#define ANOMALY_05000323 (0)
++#define ANOMALY_05000363 (0)
++
+ #endif
+diff --git a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
+index c0694ec..f0ab273 100644
+--- a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file:        include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ *	blackfin serial driver head file
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs:         enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * this program is distributed in the hope that it will be useful,
++ * but without any warranty; without even the implied warranty of
++ * merchantability or fitness for a particular purpose.  see 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,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+ 
+-#define NR_PORTS		2
+-
+-#define OFFSET_THR              0x00	/* Transmit Holding register            */
+-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
+-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
+-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
+-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
+-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
+-#define OFFSET_LCR              0x0C	/* Line Control Register                */
+-#define OFFSET_MCR              0x10	/* Modem Control Register               */
+-#define OFFSET_LSR              0x14	/* Line Status Register                 */
+-#define OFFSET_MSR              0x18	/* Modem Status Register                */
+-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
+-#define OFFSET_GCTL             0x24	/* Global Control Register              */
+-
+ #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
+@@ -92,7 +108,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+ 	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+ }
+ 
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ 	unsigned long uart_base_addr;
+ 	int uart_irq;
+diff --git a/include/asm-blackfin/mach-bf527/bfin_sir.h b/include/asm-blackfin/mach-bf527/bfin_sir.h
+new file mode 100644
+index 0000000..0612d0c
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf527/bfin_sir.h
+@@ -0,0 +1,133 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER)
++#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_IIR(port)    bfin_read16((port)->membase + OFFSET_IIR)
++#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_PUT_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER), v)
++#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++	char *buf;
++	int head;
++	int tail;
++	};
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++	unsigned char __iomem   *membase;
++	unsigned int            irq;
++	unsigned int            lsr;
++	unsigned long           clk;
++	struct net_device       *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++	int                     tx_done;
++	struct dma_rx_buf       rx_dma_buf;
++	struct timer_list       rx_dma_timer;
++	int                     rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++	unsigned int            tx_dma_channel;
++	unsigned int            rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++	unsigned long   base_addr;
++	int             irq;
++	unsigned int    rx_dma_channel;
++	unsigned int    tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++	0xFFC00400,
++	IRQ_UART0_RX,
++	CH_UART0_RX,
++	CH_UART0_TX,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++	0xFFC02000,
++	IRQ_UART1_RX,
++	CH_UART1_RX,
++	CH_UART1_TX,
++	},
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++	struct bfin_sir_port    *sir_port;
++	spinlock_t              lock;
++	unsigned int            open;
++	int                     speed;
++	int                     newspeed;
++
++	struct sk_buff          *txskb;
++	struct sk_buff          *rxskb;
++	struct net_device_stats stats;
++	struct device           *dev;
++	struct irlap_cb         *irlap;
++	struct qos_info         qos;
++
++	iobuff_t                tx_buff;
++	iobuff_t                rx_buff;
++
++	struct work_struct      work;
++	int                     mtt;
++};
++
++static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
++{
++	unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
++	port->lsr |= (lsr & (BI|FE|PE|OE));
++	return lsr | port->lsr;
++}
++
++static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
++{
++	port->lsr = 0;
++	bfin_read16(port->membase + OFFSET_LSR);
++}
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++	peripheral_request(P_UART0_TX, DRIVER_NAME);
++	peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR1
++	peripheral_request(P_UART1_TX, DRIVER_NAME);
++	peripheral_request(P_UART1_RX, DRIVER_NAME);
++#endif
++	SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf527/blackfin.h b/include/asm-blackfin/mach-bf527/blackfin.h
+index 1bd07e3..2891727 100644
+--- a/include/asm-blackfin/mach-bf527/blackfin.h
++++ b/include/asm-blackfin/mach-bf527/blackfin.h
+@@ -64,6 +64,21 @@
+ #define STATUS_P1	0x02
+ #define STATUS_P0	0x01
+ 
++#define BFIN_UART_NR_PORTS	2
++
++#define OFFSET_THR              0x00	/* Transmit Holding register            */
++#define OFFSET_RBR              0x00	/* Receive Buffer register              */
++#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
++#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
++#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
++#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
++#define OFFSET_LCR              0x0C	/* Line Control Register                */
++#define OFFSET_MCR              0x10	/* Modem Control Register               */
++#define OFFSET_LSR              0x14	/* Line Status Register                 */
++#define OFFSET_MSR              0x18	/* Modem Status Register                */
++#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
++#define OFFSET_GCTL             0x24	/* Global Control Register              */
++
+ /* DPMC*/
+ #define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
+ #define bfin_write_STOPCK_OFF(val) bfin_write_STOPCK(val)
+diff --git a/include/asm-blackfin/mach-bf527/cdefBF52x_base.h b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
+index 3f4de5d..9dbdbec 100644
+--- a/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
++++ b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
+@@ -29,18 +29,71 @@
+  */
+ 
+ #ifndef _CDEF_BF52X_H
++#define _CDEF_BF52X_H
++
++#include <asm/system.h>
++#include <asm/blackfin.h>
+ 
+ #include "defBF52x_base.h"
+ 
++/* Include core specific register pointer definitions 								*/
++#include <asm/mach-common/cdef_LPBlackfin.h>
++
+ /* ==== begin from cdefBF534.h ==== */
+ 
+ /* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
+ #define bfin_read_PLL_CTL()			bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val)			bfin_write16(PLL_CTL, val)
++/* 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(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(flags);
++}
+ #define bfin_read_PLL_DIV()			bfin_read16(PLL_DIV)
+ #define bfin_write_PLL_DIV(val)			bfin_write16(PLL_DIV, val)
+ #define bfin_read_VR_CTL()			bfin_read16(VR_CTL)
+-#define bfin_write_VR_CTL(val)			bfin_write16(VR_CTL, val)
++/* 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(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(flags);
++}
+ #define bfin_read_PLL_STAT()			bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val)		bfin_write16(PLL_STAT, val)
+ #define bfin_read_PLL_LOCKCNT()			bfin_read16(PLL_LOCKCNT)
+@@ -873,39 +926,6 @@
+ 
+ 
+ /* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
+-#define bfin_read_TWI_CLKDIV()			bfin_read16(TWI_CLKDIV)
+-#define bfin_write_TWI_CLKDIV(val)		bfin_write16(TWI_CLKDIV, val)
+-#define bfin_read_TWI_CONTROL()			bfin_read16(TWI_CONTROL)
+-#define bfin_write_TWI_CONTROL(val)		bfin_write16(TWI_CONTROL, val)
+-#define bfin_read_TWI_SLAVE_CTL()		bfin_read16(TWI_SLAVE_CTL)
+-#define bfin_write_TWI_SLAVE_CTL(val)		bfin_write16(TWI_SLAVE_CTL, val)
+-#define bfin_read_TWI_SLAVE_STAT()		bfin_read16(TWI_SLAVE_STAT)
+-#define bfin_write_TWI_SLAVE_STAT(val)		bfin_write16(TWI_SLAVE_STAT, val)
+-#define bfin_read_TWI_SLAVE_ADDR()		bfin_read16(TWI_SLAVE_ADDR)
+-#define bfin_write_TWI_SLAVE_ADDR(val)		bfin_write16(TWI_SLAVE_ADDR, val)
+-#define bfin_read_TWI_MASTER_CTL()		bfin_read16(TWI_MASTER_CTL)
+-#define bfin_write_TWI_MASTER_CTL(val)		bfin_write16(TWI_MASTER_CTL, val)
+-#define bfin_read_TWI_MASTER_STAT()		bfin_read16(TWI_MASTER_STAT)
+-#define bfin_write_TWI_MASTER_STAT(val)		bfin_write16(TWI_MASTER_STAT, val)
+-#define bfin_read_TWI_MASTER_ADDR()		bfin_read16(TWI_MASTER_ADDR)
+-#define bfin_write_TWI_MASTER_ADDR(val)		bfin_write16(TWI_MASTER_ADDR, val)
+-#define bfin_read_TWI_INT_STAT()		bfin_read16(TWI_INT_STAT)
+-#define bfin_write_TWI_INT_STAT(val)		bfin_write16(TWI_INT_STAT, val)
+-#define bfin_read_TWI_INT_MASK()		bfin_read16(TWI_INT_MASK)
+-#define bfin_write_TWI_INT_MASK(val)		bfin_write16(TWI_INT_MASK, val)
+-#define bfin_read_TWI_FIFO_CTL()		bfin_read16(TWI_FIFO_CTL)
+-#define bfin_write_TWI_FIFO_CTL(val)		bfin_write16(TWI_FIFO_CTL, val)
+-#define bfin_read_TWI_FIFO_STAT()		bfin_read16(TWI_FIFO_STAT)
+-#define bfin_write_TWI_FIFO_STAT(val)		bfin_write16(TWI_FIFO_STAT, val)
+-#define bfin_read_TWI_XMT_DATA8()		bfin_read16(TWI_XMT_DATA8)
+-#define bfin_write_TWI_XMT_DATA8(val)		bfin_write16(TWI_XMT_DATA8, val)
+-#define bfin_read_TWI_XMT_DATA16()		bfin_read16(TWI_XMT_DATA16)
+-#define bfin_write_TWI_XMT_DATA16(val)		bfin_write16(TWI_XMT_DATA16, val)
+-#define bfin_read_TWI_RCV_DATA8()		bfin_read16(TWI_RCV_DATA8)
+-#define bfin_write_TWI_RCV_DATA8(val)		bfin_write16(TWI_RCV_DATA8, val)
+-#define bfin_read_TWI_RCV_DATA16()		bfin_read16(TWI_RCV_DATA16)
+-#define bfin_write_TWI_RCV_DATA16(val)		bfin_write16(TWI_RCV_DATA16, val)
+-
+ 
+ /* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)								*/
+ #define bfin_read_PORTGIO()			bfin_read16(PORTGIO)
+diff --git a/include/asm-blackfin/mach-bf527/dma.h b/include/asm-blackfin/mach-bf527/dma.h
+index 2dfee12..49dd693 100644
+--- a/include/asm-blackfin/mach-bf527/dma.h
++++ b/include/asm-blackfin/mach-bf527/dma.h
+@@ -59,7 +59,4 @@
+ #define CH_NFC			CH_EMAC_TX /* PPI receive/transmit or NFC */
+ #endif
+ 
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[];
+-
+ #endif
+diff --git a/include/asm-blackfin/mach-bf533/anomaly.h b/include/asm-blackfin/mach-bf533/anomaly.h
+index 98209d4..5a6dcc5 100644
+--- a/include/asm-blackfin/mach-bf533/anomaly.h
++++ b/include/asm-blackfin/mach-bf533/anomaly.h
+@@ -7,7 +7,7 @@
+  */
+ 
+ /* This file shoule be up to date with:
+- *  - Revision B, 12/10/2007; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
++ *  - Revision C, 02/08/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
+  */
+ 
+ #ifndef _MACH_ANOMALY_H_
+@@ -251,10 +251,18 @@
+ #define ANOMALY_05000206 (__SILICON_REVISION__ < 3)
+ /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
+ #define ANOMALY_05000357 (1)
++/* UART Break Signal Issues */
++#define ANOMALY_05000363 (__SILICON_REVISION__ < 5)
+ /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
+ #define ANOMALY_05000366 (1)
+ /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
+ #define ANOMALY_05000371 (1)
++/* PPI Does Not Start Properly In Specific Mode */
++#define ANOMALY_05000400 (__SILICON_REVISION__ == 5)
++/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
++#define ANOMALY_05000402 (__SILICON_REVISION__ == 5)
++/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
++#define ANOMALY_05000403 (1)
+ 
+ /* Anomalies that don't exist on this proc */
+ #define ANOMALY_05000266 (0)
+diff --git a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
+index b6f513b..fbe88de 100644
+--- a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file:        include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ *	blackfin serial driver head file
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs:         enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * this program is distributed in the hope that it will be useful,
++ * but without any warranty; without even the implied warranty of
++ * merchantability or fitness for a particular purpose.  see 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,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+ 
+-#define NR_PORTS                1
+-
+-#define OFFSET_THR              0x00	/* Transmit Holding register            */
+-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
+-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
+-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
+-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
+-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
+-#define OFFSET_LCR              0x0C	/* Line Control Register                */
+-#define OFFSET_MCR              0x10	/* Modem Control Register               */
+-#define OFFSET_LSR              0x14	/* Line Status Register                 */
+-#define OFFSET_MSR              0x18	/* Modem Status Register                */
+-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
+-#define OFFSET_GCTL             0x24	/* Global Control Register              */
+-
+ #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
+@@ -84,7 +100,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+ 	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+ }
+ 
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ 	unsigned long	uart_base_addr;
+ 	int		uart_irq;
+@@ -115,7 +131,7 @@ struct bfin_serial_res bfin_serial_resource[] = {
+ 
+ #define DRIVER_NAME "bfin-uart"
+ 
+-int nr_ports = NR_PORTS;
++int nr_ports = BFIN_UART_NR_PORTS;
+ static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+ {
+ 
+diff --git a/include/asm-blackfin/mach-bf533/bfin_sir.h b/include/asm-blackfin/mach-bf533/bfin_sir.h
+new file mode 100644
+index 0000000..cefcf8b
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf533/bfin_sir.h
+@@ -0,0 +1,120 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER)
++#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_IIR(port)    bfin_read16((port)->membase + OFFSET_IIR)
++#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_PUT_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER), v)
++#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++	char *buf;
++	int head;
++	int tail;
++	};
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++	unsigned char __iomem   *membase;
++	unsigned int            irq;
++	unsigned int            lsr;
++	unsigned long           clk;
++	struct net_device       *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++	int                     tx_done;
++	struct dma_rx_buf       rx_dma_buf;
++	struct timer_list       rx_dma_timer;
++	int                     rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++	unsigned int            tx_dma_channel;
++	unsigned int            rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++	unsigned long   base_addr;
++	int             irq;
++	unsigned int    rx_dma_channel;
++	unsigned int    tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++	0xFFC00400,
++	IRQ_UART_RX,
++	CH_UART_RX,
++	CH_UART_TX,
++	},
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++	struct bfin_sir_port    *sir_port;
++	spinlock_t              lock;
++	unsigned int            open;
++	int                     speed;
++	int                     newspeed;
++
++	struct sk_buff          *txskb;
++	struct sk_buff          *rxskb;
++	struct net_device_stats stats;
++	struct device           *dev;
++	struct irlap_cb         *irlap;
++	struct qos_info         qos;
++
++	iobuff_t                tx_buff;
++	iobuff_t                rx_buff;
++
++	struct work_struct      work;
++	int                     mtt;
++};
++
++static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
++{
++	unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
++	port->lsr |= (lsr & (BI|FE|PE|OE));
++	return lsr | port->lsr;
++}
++
++static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
++{
++	port->lsr = 0;
++	bfin_read16(port->membase + OFFSET_LSR);
++}
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++	peripheral_request(P_UART0_TX, DRIVER_NAME);
++	peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++	SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf533/blackfin.h b/include/asm-blackfin/mach-bf533/blackfin.h
+index f3b240a..d80971b 100644
+--- a/include/asm-blackfin/mach-bf533/blackfin.h
++++ b/include/asm-blackfin/mach-bf533/blackfin.h
+@@ -42,4 +42,19 @@
+ #include "cdefBF532.h"
+ #endif
+ 
++#define BFIN_UART_NR_PORTS      1
++
++#define OFFSET_THR              0x00	/* Transmit Holding register            */
++#define OFFSET_RBR              0x00	/* Receive Buffer register              */
++#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
++#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
++#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
++#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
++#define OFFSET_LCR              0x0C	/* Line Control Register                */
++#define OFFSET_MCR              0x10	/* Modem Control Register               */
++#define OFFSET_LSR              0x14	/* Line Status Register                 */
++#define OFFSET_MSR              0x18	/* Modem Status Register                */
++#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
++#define OFFSET_GCTL             0x24	/* Global Control Register              */
++
+ #endif				/* _MACH_BLACKFIN_H_ */
+diff --git a/include/asm-blackfin/mach-bf533/cdefBF532.h b/include/asm-blackfin/mach-bf533/cdefBF532.h
+index c803e14..1546554 100644
+--- a/include/asm-blackfin/mach-bf533/cdefBF532.h
++++ b/include/asm-blackfin/mach-bf533/cdefBF532.h
+@@ -43,7 +43,27 @@
+ 
+ /* Clock and System Control (0xFFC0 0400-0xFFC0 07FF) */
+ #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
++/* 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(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(flags);
++}
+ #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
+ #define bfin_read_PLL_LOCKCNT()              bfin_read16(PLL_LOCKCNT)
+@@ -57,6 +77,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ {
+ 	unsigned long flags, iwr;
+ 
++	if (val == bfin_read_VR_CTL())
++		return;
++
++	local_irq_save(flags);
+ 	/* Enable the PLL Wakeup bit in SIC IWR */
+ 	iwr = bfin_read32(SIC_IWR);
+ 	/* Only allow PPL Wakeup) */
+@@ -64,11 +88,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ 
+ 	bfin_write16(VR_CTL, val);
+ 	SSYNC();
+-
+-	local_irq_save(flags);
+ 	asm("IDLE;");
+-	local_irq_restore(flags);
++
+ 	bfin_write32(SIC_IWR, iwr);
++	local_irq_restore(flags);
+ }
+ 
+ /* System Interrupt Controller (0xFFC0 0C00-0xFFC0 0FFF) */
+diff --git a/include/asm-blackfin/mach-bf533/defBF532.h b/include/asm-blackfin/mach-bf533/defBF532.h
+index 37134aa..17e1548 100644
+--- a/include/asm-blackfin/mach-bf533/defBF532.h
++++ b/include/asm-blackfin/mach-bf533/defBF532.h
+@@ -88,20 +88,25 @@
+ #define RTC_PREN			0xFFC00314	/* RTC Prescaler Enable Register (alternate macro) */
+ 
+ /* UART Controller (0xFFC00400 - 0xFFC004FF) */
+-#define UART_THR             		 0xFFC00400	/* Transmit Holding register */
+-#define UART_RBR             		 0xFFC00400	/* Receive Buffer register */
+-#define UART_DLL              		 0xFFC00400	/* Divisor Latch (Low-Byte) */
+-#define UART_IER              		 0xFFC00404	/* Interrupt Enable Register */
+-#define UART_DLH              		 0xFFC00404	/* Divisor Latch (High-Byte) */
+-#define UART_IIR              		 0xFFC00408	/* Interrupt Identification Register */
+-#define UART_LCR              		 0xFFC0040C	/* Line Control Register */
+-#define UART_MCR			 0xFFC00410	/* Modem Control Register */
+-#define UART_LSR              		 0xFFC00414	/* Line Status Register */
++
++/*
++ * Because include/linux/serial_reg.h have defined UART_*,
++ * So we define blackfin uart regs to BFIN_UART_*.
++ */
++#define BFIN_UART_THR			0xFFC00400	/* Transmit Holding register */
++#define BFIN_UART_RBR			0xFFC00400	/* Receive Buffer register */
++#define BFIN_UART_DLL			0xFFC00400	/* Divisor Latch (Low-Byte) */
++#define BFIN_UART_IER			0xFFC00404	/* Interrupt Enable Register */
++#define BFIN_UART_DLH			0xFFC00404	/* Divisor Latch (High-Byte) */
++#define BFIN_UART_IIR			0xFFC00408	/* Interrupt Identification Register */
++#define BFIN_UART_LCR			0xFFC0040C	/* Line Control Register */
++#define BFIN_UART_MCR			0xFFC00410	/* Modem Control Register */
++#define BFIN_UART_LSR			0xFFC00414	/* Line Status Register */
+ #if 0
+-#define UART_MSR            		 0xFFC00418   /* Modem Status Register (UNUSED in ADSP-BF532) */
++#define BFIN_UART_MSR			0xFFC00418	/* Modem Status Register (UNUSED in ADSP-BF532) */
+ #endif
+-#define UART_SCR              		 0xFFC0041C	/* SCR Scratch Register */
+-#define UART_GCTL      	      		 0xFFC00424	/* Global Control Register */
++#define BFIN_UART_SCR			0xFFC0041C	/* SCR Scratch Register */
++#define BFIN_UART_GCTL			0xFFC00424	/* Global Control Register */
+ 
+ /* SPI Controller (0xFFC00500 - 0xFFC005FF) */
+ #define SPI0_REGBASE          		0xFFC00500
+diff --git a/include/asm-blackfin/mach-bf533/dma.h b/include/asm-blackfin/mach-bf533/dma.h
+index 16c672c..bd9d5e9 100644
+--- a/include/asm-blackfin/mach-bf533/dma.h
++++ b/include/asm-blackfin/mach-bf533/dma.h
+@@ -51,7 +51,4 @@
+ #define CH_MEM_STREAM1_DEST     10	 /* TX */
+ #define CH_MEM_STREAM1_SRC      11	 /* RX */
+ 
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[];
+-
+ #endif
+diff --git a/include/asm-blackfin/mach-bf533/mem_init.h b/include/asm-blackfin/mach-bf533/mem_init.h
+index 1620dae..f8f3190 100644
+--- a/include/asm-blackfin/mach-bf533/mem_init.h
++++ b/include/asm-blackfin/mach-bf533/mem_init.h
+@@ -29,7 +29,8 @@
+  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+ 
+-#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_GENERIC_BOARD)
++#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || \
++     CONFIG_MEM_MT48LC32M16A2TG_75 || CONFIG_MEM_GENERIC_BOARD)
+ #if (CONFIG_SCLK_HZ > 119402985)
+ #define SDRAM_tRP       TRP_2
+ #define SDRAM_tRP_num   2
+@@ -118,6 +119,13 @@
+ #define SDRAM_CL    CL_3
+ #endif
+ 
++#if (CONFIG_MEM_MT48LC32M16A2TG_75)
++  /*SDRAM INFORMATION: */
++#define SDRAM_Tref  64		/* Refresh period in milliseconds   */
++#define SDRAM_NRA   8192	/* Number of row addresses in SDRAM */
++#define SDRAM_CL    CL_3
++#endif
++
+ #if (CONFIG_MEM_GENERIC_BOARD)
+   /*SDRAM INFORMATION: Modify this for your board */
+ #define SDRAM_Tref  64		/* Refresh period in milliseconds   */
+diff --git a/include/asm-blackfin/mach-bf537/anomaly.h b/include/asm-blackfin/mach-bf537/anomaly.h
+index 746a794..a6b08fa 100644
+--- a/include/asm-blackfin/mach-bf537/anomaly.h
++++ b/include/asm-blackfin/mach-bf537/anomaly.h
+@@ -7,7 +7,7 @@
+  */
+ 
+ /* This file shoule be up to date with:
+- *  - Revision A, 09/04/2007; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
++ *  - Revision C, 02/08/2008; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
+  */
+ 
+ #ifndef _MACH_ANOMALY_H_
+@@ -132,10 +132,24 @@
+ #define ANOMALY_05000322 (1)
+ /* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
+ #define ANOMALY_05000341 (__SILICON_REVISION__ >= 3)
++/* New Feature: UART Remains Enabled after UART Boot (Not Available on Older Silicon) */
++#define ANOMALY_05000350 (__SILICON_REVISION__ < 3)
++/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
++#define ANOMALY_05000355 (1)
+ /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
+ #define ANOMALY_05000357 (1)
+ /* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */
+ #define ANOMALY_05000359 (1)
++/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
++#define ANOMALY_05000366 (1)
++/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
++#define ANOMALY_05000371 (1)
++/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
++#define ANOMALY_05000402 (__SILICON_REVISION__ >= 3)
++/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
++#define ANOMALY_05000403 (1)
++
++
+ 
+ /* Anomalies that don't exist on this proc */
+ #define ANOMALY_05000125 (0)
+@@ -146,5 +160,6 @@
+ #define ANOMALY_05000266 (0)
+ #define ANOMALY_05000311 (0)
+ #define ANOMALY_05000323 (0)
++#define ANOMALY_05000363 (0)
+ 
+ #endif
+diff --git a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
+index 8fc672d..fd100a4 100644
+--- a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file:         include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ *	blackfin serial driver header files
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs:         enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * this program is distributed in the hope that it will be useful,
++ * but without any warranty; without even the implied warranty of
++ * merchantability or fitness for a particular purpose.  see 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,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+ 
+-#define NR_PORTS		2
+-
+-#define OFFSET_THR              0x00	/* Transmit Holding register            */
+-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
+-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
+-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
+-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
+-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
+-#define OFFSET_LCR              0x0C	/* Line Control Register                */
+-#define OFFSET_MCR              0x10	/* Modem Control Register               */
+-#define OFFSET_LSR              0x14	/* Line Status Register                 */
+-#define OFFSET_MSR              0x18	/* Modem Status Register                */
+-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
+-#define OFFSET_GCTL             0x24	/* Global Control Register              */
+-
+ #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
+@@ -92,7 +108,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+ 	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+ }
+ 
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ 	unsigned long	uart_base_addr;
+ 	int		uart_irq;
+diff --git a/include/asm-blackfin/mach-bf537/bfin_sir.h b/include/asm-blackfin/mach-bf537/bfin_sir.h
+new file mode 100644
+index 0000000..0612d0c
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf537/bfin_sir.h
+@@ -0,0 +1,133 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER)
++#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_IIR(port)    bfin_read16((port)->membase + OFFSET_IIR)
++#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_PUT_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER), v)
++#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++	char *buf;
++	int head;
++	int tail;
++	};
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++	unsigned char __iomem   *membase;
++	unsigned int            irq;
++	unsigned int            lsr;
++	unsigned long           clk;
++	struct net_device       *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++	int                     tx_done;
++	struct dma_rx_buf       rx_dma_buf;
++	struct timer_list       rx_dma_timer;
++	int                     rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++	unsigned int            tx_dma_channel;
++	unsigned int            rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++	unsigned long   base_addr;
++	int             irq;
++	unsigned int    rx_dma_channel;
++	unsigned int    tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++	0xFFC00400,
++	IRQ_UART0_RX,
++	CH_UART0_RX,
++	CH_UART0_TX,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++	0xFFC02000,
++	IRQ_UART1_RX,
++	CH_UART1_RX,
++	CH_UART1_TX,
++	},
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++	struct bfin_sir_port    *sir_port;
++	spinlock_t              lock;
++	unsigned int            open;
++	int                     speed;
++	int                     newspeed;
++
++	struct sk_buff          *txskb;
++	struct sk_buff          *rxskb;
++	struct net_device_stats stats;
++	struct device           *dev;
++	struct irlap_cb         *irlap;
++	struct qos_info         qos;
++
++	iobuff_t                tx_buff;
++	iobuff_t                rx_buff;
++
++	struct work_struct      work;
++	int                     mtt;
++};
++
++static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
++{
++	unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
++	port->lsr |= (lsr & (BI|FE|PE|OE));
++	return lsr | port->lsr;
++}
++
++static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
++{
++	port->lsr = 0;
++	bfin_read16(port->membase + OFFSET_LSR);
++}
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++	peripheral_request(P_UART0_TX, DRIVER_NAME);
++	peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR1
++	peripheral_request(P_UART1_TX, DRIVER_NAME);
++	peripheral_request(P_UART1_RX, DRIVER_NAME);
++#endif
++	SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf537/blackfin.h b/include/asm-blackfin/mach-bf537/blackfin.h
+index 53fcfa3..cffc786 100644
+--- a/include/asm-blackfin/mach-bf537/blackfin.h
++++ b/include/asm-blackfin/mach-bf537/blackfin.h
+@@ -82,8 +82,6 @@
+ #define STATUS_P1	0x02
+ #define STATUS_P0	0x01
+ 
+-/* UART 0*/
+-
+ /* DMA Channnel */
+ #define bfin_read_CH_UART_RX() bfin_read_CH_UART0_RX()
+ #define bfin_write_CH_UART_RX(val) bfin_write_CH_UART0_RX(val)
+@@ -106,37 +104,52 @@
+ /* MMR Registers*/
+ #define bfin_read_UART_THR() bfin_read_UART0_THR()
+ #define bfin_write_UART_THR(val) bfin_write_UART0_THR(val)
+-#define UART_THR UART0_THR
++#define BFIN_UART_THR UART0_THR
+ #define bfin_read_UART_RBR() bfin_read_UART0_RBR()
+ #define bfin_write_UART_RBR(val) bfin_write_UART0_RBR(val)
+-#define UART_RBR UART0_RBR
++#define BFIN_UART_RBR UART0_RBR
+ #define bfin_read_UART_DLL() bfin_read_UART0_DLL()
+ #define bfin_write_UART_DLL(val) bfin_write_UART0_DLL(val)
+-#define UART_DLL UART0_DLL
++#define BFIN_UART_DLL UART0_DLL
+ #define bfin_read_UART_IER() bfin_read_UART0_IER()
+ #define bfin_write_UART_IER(val) bfin_write_UART0_IER(val)
+-#define UART_IER UART0_IER
++#define BFIN_UART_IER UART0_IER
+ #define bfin_read_UART_DLH() bfin_read_UART0_DLH()
+ #define bfin_write_UART_DLH(val) bfin_write_UART0_DLH(val)
+-#define UART_DLH UART0_DLH
++#define BFIN_UART_DLH UART0_DLH
+ #define bfin_read_UART_IIR() bfin_read_UART0_IIR()
+ #define bfin_write_UART_IIR(val) bfin_write_UART0_IIR(val)
+-#define UART_IIR UART0_IIR
++#define BFIN_UART_IIR UART0_IIR
+ #define bfin_read_UART_LCR() bfin_read_UART0_LCR()
+ #define bfin_write_UART_LCR(val) bfin_write_UART0_LCR(val)
+-#define UART_LCR UART0_LCR
++#define BFIN_UART_LCR UART0_LCR
+ #define bfin_read_UART_MCR() bfin_read_UART0_MCR()
+ #define bfin_write_UART_MCR(val) bfin_write_UART0_MCR(val)
+-#define UART_MCR UART0_MCR
++#define BFIN_UART_MCR UART0_MCR
+ #define bfin_read_UART_LSR() bfin_read_UART0_LSR()
+ #define bfin_write_UART_LSR(val) bfin_write_UART0_LSR(val)
+-#define UART_LSR UART0_LSR
++#define BFIN_UART_LSR UART0_LSR
+ #define bfin_read_UART_SCR() bfin_read_UART0_SCR()
+ #define bfin_write_UART_SCR(val) bfin_write_UART0_SCR(val)
+-#define UART_SCR  UART0_SCR
++#define BFIN_UART_SCR  UART0_SCR
+ #define bfin_read_UART_GCTL() bfin_read_UART0_GCTL()
+ #define bfin_write_UART_GCTL(val) bfin_write_UART0_GCTL(val)
+-#define UART_GCTL UART0_GCTL
++#define BFIN_UART_GCTL UART0_GCTL
++
++#define BFIN_UART_NR_PORTS	2
++
++#define OFFSET_THR              0x00	/* Transmit Holding register            */
++#define OFFSET_RBR              0x00	/* Receive Buffer register              */
++#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
++#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
++#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
++#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
++#define OFFSET_LCR              0x0C	/* Line Control Register                */
++#define OFFSET_MCR              0x10	/* Modem Control Register               */
++#define OFFSET_LSR              0x14	/* Line Status Register                 */
++#define OFFSET_MSR              0x18	/* Modem Status Register                */
++#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
++#define OFFSET_GCTL             0x24	/* Global Control Register              */
+ 
+ /* DPMC*/
+ #define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
+diff --git a/include/asm-blackfin/mach-bf537/cdefBF534.h b/include/asm-blackfin/mach-bf537/cdefBF534.h
+index 78227bc..82de526 100644
+--- a/include/asm-blackfin/mach-bf537/cdefBF534.h
++++ b/include/asm-blackfin/mach-bf537/cdefBF534.h
+@@ -44,7 +44,27 @@
+ 
+ /* Clock and System Control	(0xFFC00000 - 0xFFC000FF)								*/
+ #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
++/* 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(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(flags);
++}
+ #define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
+ #define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
+ #define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
+@@ -53,6 +73,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ {
+ 	unsigned long flags, iwr;
+ 
++	if (val == bfin_read_VR_CTL())
++		return;
++
++	local_irq_save(flags);
+ 	/* Enable the PLL Wakeup bit in SIC IWR */
+ 	iwr = bfin_read32(SIC_IWR);
+ 	/* Only allow PPL Wakeup) */
+@@ -60,11 +84,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ 
+ 	bfin_write16(VR_CTL, val);
+ 	SSYNC();
+-
+-	local_irq_save(flags);
+ 	asm("IDLE;");
+-	local_irq_restore(flags);
++
+ 	bfin_write32(SIC_IWR, iwr);
++	local_irq_restore(flags);
+ }
+ #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
+@@ -858,39 +881,7 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_PPI_FRAME()                bfin_read16(PPI_FRAME)
+ #define bfin_write_PPI_FRAME(val)            bfin_write16(PPI_FRAME,val)
+ 
+-/* Two-Wire Interface		(0xFFC01400 - 0xFFC014FF)								*/
+-#define bfin_read_TWI_CLKDIV()               bfin_read16(TWI_CLKDIV)
+-#define bfin_write_TWI_CLKDIV(val)           bfin_write16(TWI_CLKDIV,val)
+-#define bfin_read_TWI_CONTROL()              bfin_read16(TWI_CONTROL)
+-#define bfin_write_TWI_CONTROL(val)          bfin_write16(TWI_CONTROL,val)
+-#define bfin_read_TWI_SLAVE_CTL()            bfin_read16(TWI_SLAVE_CTL)
+-#define bfin_write_TWI_SLAVE_CTL(val)        bfin_write16(TWI_SLAVE_CTL,val)
+-#define bfin_read_TWI_SLAVE_STAT()           bfin_read16(TWI_SLAVE_STAT)
+-#define bfin_write_TWI_SLAVE_STAT(val)       bfin_write16(TWI_SLAVE_STAT,val)
+-#define bfin_read_TWI_SLAVE_ADDR()           bfin_read16(TWI_SLAVE_ADDR)
+-#define bfin_write_TWI_SLAVE_ADDR(val)       bfin_write16(TWI_SLAVE_ADDR,val)
+-#define bfin_read_TWI_MASTER_CTL()           bfin_read16(TWI_MASTER_CTL)
+-#define bfin_write_TWI_MASTER_CTL(val)       bfin_write16(TWI_MASTER_CTL,val)
+-#define bfin_read_TWI_MASTER_STAT()          bfin_read16(TWI_MASTER_STAT)
+-#define bfin_write_TWI_MASTER_STAT(val)      bfin_write16(TWI_MASTER_STAT,val)
+-#define bfin_read_TWI_MASTER_ADDR()          bfin_read16(TWI_MASTER_ADDR)
+-#define bfin_write_TWI_MASTER_ADDR(val)      bfin_write16(TWI_MASTER_ADDR,val)
+-#define bfin_read_TWI_INT_STAT()             bfin_read16(TWI_INT_STAT)
+-#define bfin_write_TWI_INT_STAT(val)         bfin_write16(TWI_INT_STAT,val)
+-#define bfin_read_TWI_INT_MASK()             bfin_read16(TWI_INT_MASK)
+-#define bfin_write_TWI_INT_MASK(val)         bfin_write16(TWI_INT_MASK,val)
+-#define bfin_read_TWI_FIFO_CTL()             bfin_read16(TWI_FIFO_CTL)
+-#define bfin_write_TWI_FIFO_CTL(val)         bfin_write16(TWI_FIFO_CTL,val)
+-#define bfin_read_TWI_FIFO_STAT()            bfin_read16(TWI_FIFO_STAT)
+-#define bfin_write_TWI_FIFO_STAT(val)        bfin_write16(TWI_FIFO_STAT,val)
+-#define bfin_read_TWI_XMT_DATA8()            bfin_read16(TWI_XMT_DATA8)
+-#define bfin_write_TWI_XMT_DATA8(val)        bfin_write16(TWI_XMT_DATA8,val)
+-#define bfin_read_TWI_XMT_DATA16()           bfin_read16(TWI_XMT_DATA16)
+-#define bfin_write_TWI_XMT_DATA16(val)       bfin_write16(TWI_XMT_DATA16,val)
+-#define bfin_read_TWI_RCV_DATA8()            bfin_read16(TWI_RCV_DATA8)
+-#define bfin_write_TWI_RCV_DATA8(val)        bfin_write16(TWI_RCV_DATA8,val)
+-#define bfin_read_TWI_RCV_DATA16()           bfin_read16(TWI_RCV_DATA16)
+-#define bfin_write_TWI_RCV_DATA16(val)       bfin_write16(TWI_RCV_DATA16,val)
++/* Two-Wire Interface (0xFFC01400 - 0xFFC014FF) */
+ 
+ /* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF)								*/
+ #define bfin_read_PORTGIO()                  bfin_read16(PORTGIO)
+diff --git a/include/asm-blackfin/mach-bf537/dma.h b/include/asm-blackfin/mach-bf537/dma.h
+index 0219919..7a96404 100644
+--- a/include/asm-blackfin/mach-bf537/dma.h
++++ b/include/asm-blackfin/mach-bf537/dma.h
+@@ -52,7 +52,4 @@
+ #define CH_MEM_STREAM1_DEST	14	 /* TX */
+ #define CH_MEM_STREAM1_SRC 	15	 /* RX */
+ 
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[];
+-
+ #endif
+diff --git a/include/asm-blackfin/mach-bf548/anomaly.h b/include/asm-blackfin/mach-bf548/anomaly.h
+index 850dc12..49d3ceb 100644
+--- a/include/asm-blackfin/mach-bf548/anomaly.h
++++ b/include/asm-blackfin/mach-bf548/anomaly.h
+@@ -93,5 +93,6 @@
+ #define ANOMALY_05000273 (0)
+ #define ANOMALY_05000311 (0)
+ #define ANOMALY_05000323 (0)
++#define ANOMALY_05000363 (0)
+ 
+ #endif
+diff --git a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
+index 7e6339f..6547027 100644
+--- a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file:        include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ *	blackfin serial driver head file
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs:         enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * this program is distributed in the hope that it will be useful,
++ * but without any warranty; without even the implied warranty of
++ * merchantability or fitness for a particular purpose.  see 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,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+ 
+-#define NR_PORTS		4
+-
+-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
+-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
+-#define OFFSET_GCTL             0x08	/* Global Control Register              */
+-#define OFFSET_LCR              0x0C	/* Line Control Register                */
+-#define OFFSET_MCR              0x10	/* Modem Control Register               */
+-#define OFFSET_LSR              0x14	/* Line Status Register                 */
+-#define OFFSET_MSR              0x18	/* Modem Status Register                */
+-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
+-#define OFFSET_IER_SET          0x20	/* Set Interrupt Enable Register        */
+-#define OFFSET_IER_CLEAR        0x24	/* Clear Interrupt Enable Register      */
+-#define OFFSET_THR              0x28	/* Transmit Holding register            */
+-#define OFFSET_RBR              0x2C	/* Receive Buffer register              */
+-
+ #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_DLH(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLH))
+@@ -80,7 +96,7 @@ struct bfin_serial_port {
+ #endif
+ };
+ 
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ 	unsigned long	uart_base_addr;
+ 	int		uart_irq;
+diff --git a/include/asm-blackfin/mach-bf548/bfin_sir.h b/include/asm-blackfin/mach-bf548/bfin_sir.h
+new file mode 100644
+index 0000000..5e94271
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf548/bfin_sir.h
+@@ -0,0 +1,149 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER_SET)
++#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_LSR(port)    bfin_read16((port)->membase + OFFSET_LSR)
++#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_SET_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER_SET), v)
++#define SIR_UART_CLEAR_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER_CLEAR), v)
++#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LSR(port, v)  bfin_write16(((port)->membase + OFFSET_LSR), v)
++#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_CLEAR_LSR(port)  bfin_write16(((port)->membase + OFFSET_LSR), -1)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++	char *buf;
++	int head;
++	int tail;
++	};
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++	unsigned char __iomem   *membase;
++	unsigned int            irq;
++	unsigned int            lsr;
++	unsigned long           clk;
++	struct net_device       *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++	int                     tx_done;
++	struct dma_rx_buf       rx_dma_buf;
++	struct timer_list       rx_dma_timer;
++	int                     rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++	unsigned int            tx_dma_channel;
++	unsigned int            rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++	unsigned long   base_addr;
++	int             irq;
++	unsigned int    rx_dma_channel;
++	unsigned int    tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++	0xFFC00400,
++	IRQ_UART0_RX,
++	CH_UART0_RX,
++	CH_UART0_TX,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR1
++	{
++	0xFFC02000,
++	IRQ_UART1_RX,
++	CH_UART1_RX,
++	CH_UART1_TX,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR2
++	{
++	0xFFC02100,
++	IRQ_UART2_RX,
++	CH_UART2_RX,
++	CH_UART2_TX,
++	},
++#endif
++#ifdef CONFIG_BFIN_SIR3
++	{
++	0xFFC03100,
++	IRQ_UART3_RX,
++	CH_UART3_RX,
++	CH_UART3_TX,
++	},
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++	struct bfin_sir_port    *sir_port;
++	spinlock_t              lock;
++	unsigned int            open;
++	int                     speed;
++	int                     newspeed;
++
++	struct sk_buff          *txskb;
++	struct sk_buff          *rxskb;
++	struct net_device_stats stats;
++	struct device           *dev;
++	struct irlap_cb         *irlap;
++	struct qos_info         qos;
++
++	iobuff_t                tx_buff;
++	iobuff_t                rx_buff;
++
++	struct work_struct      work;
++	int                     mtt;
++};
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++	peripheral_request(P_UART0_TX, DRIVER_NAME);
++	peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR1
++	peripheral_request(P_UART1_TX, DRIVER_NAME);
++	peripheral_request(P_UART1_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR2
++	peripheral_request(P_UART2_TX, DRIVER_NAME);
++	peripheral_request(P_UART2_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR3
++	peripheral_request(P_UART3_TX, DRIVER_NAME);
++	peripheral_request(P_UART3_RX, DRIVER_NAME);
++#endif
++	SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf548/blackfin.h b/include/asm-blackfin/mach-bf548/blackfin.h
+index 3bd67da..d6ee74a 100644
+--- a/include/asm-blackfin/mach-bf548/blackfin.h
++++ b/include/asm-blackfin/mach-bf548/blackfin.h
+@@ -153,17 +153,33 @@
+ #define bfin_write_UART_SCR(val)	bfin_write_UART1_SCR(val)
+ #define bfin_read_UART_GCTL()		bfin_read_UART1_GCTL()
+ #define bfin_write_UART_GCTL(val)	bfin_write_UART1_GCTL(val)
+-#define UART_THR			UART1_THR
+-#define UART_RBR			UART1_RBR
+-#define UART_DLL			UART1_DLL
+-#define UART_IER			UART1_IER
+-#define UART_DLH			UART1_DLH
+-#define UART_IIR			UART1_IIR
+-#define UART_LCR			UART1_LCR
+-#define UART_MCR			UART1_MCR
+-#define UART_LSR			UART1_LSR
+-#define UART_SCR			UART1_SCR
+-#define UART_GCTL			UART1_GCTL
++
++#define BFIN_UART_THR			UART1_THR
++#define BFIN_UART_RBR			UART1_RBR
++#define BFIN_UART_DLL			UART1_DLL
++#define BFIN_UART_IER			UART1_IER
++#define BFIN_UART_DLH			UART1_DLH
++#define BFIN_UART_IIR			UART1_IIR
++#define BFIN_UART_LCR			UART1_LCR
++#define BFIN_UART_MCR			UART1_MCR
++#define BFIN_UART_LSR			UART1_LSR
++#define BFIN_UART_SCR			UART1_SCR
++#define BFIN_UART_GCTL			UART1_GCTL
++
++#define BFIN_UART_NR_PORTS	4
++
++#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
++#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
++#define OFFSET_GCTL             0x08	/* Global Control Register              */
++#define OFFSET_LCR              0x0C	/* Line Control Register                */
++#define OFFSET_MCR              0x10	/* Modem Control Register               */
++#define OFFSET_LSR              0x14	/* Line Status Register                 */
++#define OFFSET_MSR              0x18	/* Modem Status Register                */
++#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
++#define OFFSET_IER_SET          0x20	/* Set Interrupt Enable Register        */
++#define OFFSET_IER_CLEAR        0x24	/* Clear Interrupt Enable Register      */
++#define OFFSET_THR              0x28	/* Transmit Holding register            */
++#define OFFSET_RBR              0x2C	/* Receive Buffer register              */
+ 
+ /* PLL_DIV Masks */
+ #define CCLK_DIV1 CSEL_DIV1	/* CCLK = VCO / 1 */
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF542.h b/include/asm-blackfin/mach-bf548/cdefBF542.h
+index 308b33a..60b9f77 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF542.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF542.h
+@@ -123,12 +123,12 @@
+ #define bfin_write_SDH_DATA_LGTH(val)	bfin_write16(SDH_DATA_LGTH, val)
+ #define bfin_read_SDH_DATA_CTL()	bfin_read16(SDH_DATA_CTL)
+ #define bfin_write_SDH_DATA_CTL(val)	bfin_write16(SDH_DATA_CTL, val)
+-#define bfin_read_SDH_DATA_CNT()	fin_read16(SDH_DATA_CNT)
++#define bfin_read_SDH_DATA_CNT()	bfin_read16(SDH_DATA_CNT)
+ #define bfin_write_SDH_DATA_CNT(val)	bfin_write16(SDH_DATA_CNT, val)
+ #define bfin_read_SDH_STATUS()		bfin_read32(SDH_STATUS)
+ #define bfin_write_SDH_STATUS(val)	bfin_write32(SDH_STATUS, val)
+-#define bfin_read_SDH_STATUS_CLR()	fin_read16(SDH_STATUS_CLR)
+-#define bfin_write_SDH_STATUS_CLR(val)	fin_write16(SDH_STATUS_CLR, val)
++#define bfin_read_SDH_STATUS_CLR()	bfin_read16(SDH_STATUS_CLR)
++#define bfin_write_SDH_STATUS_CLR(val)	bfin_write16(SDH_STATUS_CLR, val)
+ #define bfin_read_SDH_MASK0()		bfin_read32(SDH_MASK0)
+ #define bfin_write_SDH_MASK0(val)	bfin_write32(SDH_MASK0, val)
+ #define bfin_read_SDH_MASK1()		bfin_read32(SDH_MASK1)
+@@ -184,8 +184,8 @@
+ #define bfin_write_USB_FRAME(val)	bfin_write16(USB_FRAME, val)
+ #define bfin_read_USB_INDEX()		bfin_read16(USB_INDEX)
+ #define bfin_write_USB_INDEX(val)	bfin_write16(USB_INDEX, val)
+-#define bfin_read_USB_TESTMODE()	fin_read16(USB_TESTMODE)
+-#define bfin_write_USB_TESTMODE(val)	fin_write16(USB_TESTMODE, val)
++#define bfin_read_USB_TESTMODE()	bfin_read16(USB_TESTMODE)
++#define bfin_write_USB_TESTMODE(val)	bfin_write16(USB_TESTMODE, val)
+ #define bfin_read_USB_GLOBINTR()	bfin_read16(USB_GLOBINTR)
+ #define bfin_write_USB_GLOBINTR(val)	bfin_write16(USB_GLOBINTR, val)
+ #define bfin_read_USB_GLOBAL_CTL()	bfin_read16(USB_GLOBAL_CTL)
+@@ -244,7 +244,7 @@
+ #define bfin_read_USB_OTG_DEV_CTL()		bfin_read16(USB_OTG_DEV_CTL)
+ #define bfin_write_USB_OTG_DEV_CTL(val)		bfin_write16(USB_OTG_DEV_CTL, val)
+ #define bfin_read_USB_OTG_VBUS_IRQ()		bfin_read16(USB_OTG_VBUS_IRQ)
+-#define bfin_write_USB_OTG_VBUS_IRQ(val)	fin_write16(USB_OTG_VBUS_IRQ, val)
++#define bfin_write_USB_OTG_VBUS_IRQ(val)	bfin_write16(USB_OTG_VBUS_IRQ, val)
+ #define bfin_read_USB_OTG_VBUS_MASK()		bfin_read16(USB_OTG_VBUS_MASK)
+ #define bfin_write_USB_OTG_VBUS_MASK(val)	bfin_write16(USB_OTG_VBUS_MASK, val)
+ 
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF544.h b/include/asm-blackfin/mach-bf548/cdefBF544.h
+index 7a2d177..ea9b4ab 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF544.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF544.h
+@@ -113,39 +113,6 @@
+ 
+ /* Two Wire Interface Registers (TWI1) */
+ 
+-#define bfin_read_TWI1_CLKDIV()			bfin_read16(TWI1_CLKDIV)
+-#define bfin_write_TWI1_CLKDIV(val)		bfin_write16(TWI1_CLKDIV, val)
+-#define bfin_read_TWI1_CONTROL()		bfin_read16(TWI1_CONTROL)
+-#define bfin_write_TWI1_CONTROL(val)		bfin_write16(TWI1_CONTROL, val)
+-#define bfin_read_TWI1_SLAVE_CTRL()		bfin_read16(TWI1_SLAVE_CTRL)
+-#define bfin_write_TWI1_SLAVE_CTRL(val)		bfin_write16(TWI1_SLAVE_CTRL, val)
+-#define bfin_read_TWI1_SLAVE_STAT()		bfin_read16(TWI1_SLAVE_STAT)
+-#define bfin_write_TWI1_SLAVE_STAT(val)		bfin_write16(TWI1_SLAVE_STAT, val)
+-#define bfin_read_TWI1_SLAVE_ADDR()		bfin_read16(TWI1_SLAVE_ADDR)
+-#define bfin_write_TWI1_SLAVE_ADDR(val)		bfin_write16(TWI1_SLAVE_ADDR, val)
+-#define bfin_read_TWI1_MASTER_CTRL()		bfin_read16(TWI1_MASTER_CTRL)
+-#define bfin_write_TWI1_MASTER_CTRL(val)	bfin_write16(TWI1_MASTER_CTRL, val)
+-#define bfin_read_TWI1_MASTER_STAT()		bfin_read16(TWI1_MASTER_STAT)
+-#define bfin_write_TWI1_MASTER_STAT(val)	bfin_write16(TWI1_MASTER_STAT, val)
+-#define bfin_read_TWI1_MASTER_ADDR()		bfin_read16(TWI1_MASTER_ADDR)
+-#define bfin_write_TWI1_MASTER_ADDR(val)	bfin_write16(TWI1_MASTER_ADDR, val)
+-#define bfin_read_TWI1_INT_STAT()		bfin_read16(TWI1_INT_STAT)
+-#define bfin_write_TWI1_INT_STAT(val)		bfin_write16(TWI1_INT_STAT, val)
+-#define bfin_read_TWI1_INT_MASK()		bfin_read16(TWI1_INT_MASK)
+-#define bfin_write_TWI1_INT_MASK(val)		bfin_write16(TWI1_INT_MASK, val)
+-#define bfin_read_TWI1_FIFO_CTRL()		bfin_read16(TWI1_FIFO_CTRL)
+-#define bfin_write_TWI1_FIFO_CTRL(val)		bfin_write16(TWI1_FIFO_CTRL, val)
+-#define bfin_read_TWI1_FIFO_STAT()		bfin_read16(TWI1_FIFO_STAT)
+-#define bfin_write_TWI1_FIFO_STAT(val)		bfin_write16(TWI1_FIFO_STAT, val)
+-#define bfin_read_TWI1_XMT_DATA8()		bfin_read16(TWI1_XMT_DATA8)
+-#define bfin_write_TWI1_XMT_DATA8(val)		bfin_write16(TWI1_XMT_DATA8, val)
+-#define bfin_read_TWI1_XMT_DATA16()		bfin_read16(TWI1_XMT_DATA16)
+-#define bfin_write_TWI1_XMT_DATA16(val)		bfin_write16(TWI1_XMT_DATA16, val)
+-#define bfin_read_TWI1_RCV_DATA8()		bfin_read16(TWI1_RCV_DATA8)
+-#define bfin_write_TWI1_RCV_DATA8(val)		bfin_write16(TWI1_RCV_DATA8, val)
+-#define bfin_read_TWI1_RCV_DATA16()		bfin_read16(TWI1_RCV_DATA16)
+-#define bfin_write_TWI1_RCV_DATA16(val)		bfin_write16(TWI1_RCV_DATA16, val)
+-
+ /* CAN Controller 1 Config 1 Registers */
+ 
+ #define bfin_read_CAN1_MC1()		bfin_read16(CAN1_MC1)
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF547.h b/include/asm-blackfin/mach-bf548/cdefBF547.h
+index d0a200b..ba71627 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF547.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF547.h
+@@ -185,39 +185,6 @@
+ 
+ /* Two Wire Interface Registers (TWI1) */
+ 
+-#define bfin_read_TWI1_CLKDIV()			bfin_read16(TWI1_CLKDIV)
+-#define bfin_write_TWI1_CLKDIV(val)		bfin_write16(TWI1_CLKDIV, val)
+-#define bfin_read_TWI1_CONTROL()		bfin_read16(TWI1_CONTROL)
+-#define bfin_write_TWI1_CONTROL(val)		bfin_write16(TWI1_CONTROL, val)
+-#define bfin_read_TWI1_SLAVE_CTRL()		bfin_read16(TWI1_SLAVE_CTRL)
+-#define bfin_write_TWI1_SLAVE_CTRL(val)		bfin_write16(TWI1_SLAVE_CTRL, val)
+-#define bfin_read_TWI1_SLAVE_STAT()		bfin_read16(TWI1_SLAVE_STAT)
+-#define bfin_write_TWI1_SLAVE_STAT(val)		bfin_write16(TWI1_SLAVE_STAT, val)
+-#define bfin_read_TWI1_SLAVE_ADDR()		bfin_read16(TWI1_SLAVE_ADDR)
+-#define bfin_write_TWI1_SLAVE_ADDR(val)		bfin_write16(TWI1_SLAVE_ADDR, val)
+-#define bfin_read_TWI1_MASTER_CTRL()		bfin_read16(TWI1_MASTER_CTRL)
+-#define bfin_write_TWI1_MASTER_CTRL(val)	bfin_write16(TWI1_MASTER_CTRL, val)
+-#define bfin_read_TWI1_MASTER_STAT()		bfin_read16(TWI1_MASTER_STAT)
+-#define bfin_write_TWI1_MASTER_STAT(val)	bfin_write16(TWI1_MASTER_STAT, val)
+-#define bfin_read_TWI1_MASTER_ADDR()		bfin_read16(TWI1_MASTER_ADDR)
+-#define bfin_write_TWI1_MASTER_ADDR(val)	bfin_write16(TWI1_MASTER_ADDR, val)
+-#define bfin_read_TWI1_INT_STAT()		bfin_read16(TWI1_INT_STAT)
+-#define bfin_write_TWI1_INT_STAT(val)		bfin_write16(TWI1_INT_STAT, val)
+-#define bfin_read_TWI1_INT_MASK()		bfin_read16(TWI1_INT_MASK)
+-#define bfin_write_TWI1_INT_MASK(val)		bfin_write16(TWI1_INT_MASK, val)
+-#define bfin_read_TWI1_FIFO_CTRL()		bfin_read16(TWI1_FIFO_CTRL)
+-#define bfin_write_TWI1_FIFO_CTRL(val)		bfin_write16(TWI1_FIFO_CTRL, val)
+-#define bfin_read_TWI1_FIFO_STAT()		bfin_read16(TWI1_FIFO_STAT)
+-#define bfin_write_TWI1_FIFO_STAT(val)		bfin_write16(TWI1_FIFO_STAT, val)
+-#define bfin_read_TWI1_XMT_DATA8()		bfin_read16(TWI1_XMT_DATA8)
+-#define bfin_write_TWI1_XMT_DATA8(val)		bfin_write16(TWI1_XMT_DATA8, val)
+-#define bfin_read_TWI1_XMT_DATA16()		bfin_read16(TWI1_XMT_DATA16)
+-#define bfin_write_TWI1_XMT_DATA16(val)		bfin_write16(TWI1_XMT_DATA16, val)
+-#define bfin_read_TWI1_RCV_DATA8()		bfin_read16(TWI1_RCV_DATA8)
+-#define bfin_write_TWI1_RCV_DATA8(val)		bfin_write16(TWI1_RCV_DATA8, val)
+-#define bfin_read_TWI1_RCV_DATA16()		bfin_read16(TWI1_RCV_DATA16)
+-#define bfin_write_TWI1_RCV_DATA16(val)		bfin_write16(TWI1_RCV_DATA16, val)
+-
+ /* SPI2  Registers */
+ 
+ #define bfin_read_SPI2_CTL()		bfin_read16(SPI2_CTL)
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF548.h b/include/asm-blackfin/mach-bf548/cdefBF548.h
+index 674be02..ae971eb 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF548.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF548.h
+@@ -185,39 +185,6 @@
+ 
+ /* Two Wire Interface Registers (TWI1) */
+ 
+-#define bfin_read_TWI1_CLKDIV()			bfin_read16(TWI1_CLKDIV)
+-#define bfin_write_TWI1_CLKDIV(val)		bfin_write16(TWI1_CLKDIV, val)
+-#define bfin_read_TWI1_CONTROL()		bfin_read16(TWI1_CONTROL)
+-#define bfin_write_TWI1_CONTROL(val)		bfin_write16(TWI1_CONTROL, val)
+-#define bfin_read_TWI1_SLAVE_CTRL()		bfin_read16(TWI1_SLAVE_CTRL)
+-#define bfin_write_TWI1_SLAVE_CTRL(val)		bfin_write16(TWI1_SLAVE_CTRL, val)
+-#define bfin_read_TWI1_SLAVE_STAT()		bfin_read16(TWI1_SLAVE_STAT)
+-#define bfin_write_TWI1_SLAVE_STAT(val)		bfin_write16(TWI1_SLAVE_STAT, val)
+-#define bfin_read_TWI1_SLAVE_ADDR()		bfin_read16(TWI1_SLAVE_ADDR)
+-#define bfin_write_TWI1_SLAVE_ADDR(val)		bfin_write16(TWI1_SLAVE_ADDR, val)
+-#define bfin_read_TWI1_MASTER_CTRL()		bfin_read16(TWI1_MASTER_CTRL)
+-#define bfin_write_TWI1_MASTER_CTRL(val)	bfin_write16(TWI1_MASTER_CTRL, val)
+-#define bfin_read_TWI1_MASTER_STAT()		bfin_read16(TWI1_MASTER_STAT)
+-#define bfin_write_TWI1_MASTER_STAT(val)	bfin_write16(TWI1_MASTER_STAT, val)
+-#define bfin_read_TWI1_MASTER_ADDR()		bfin_read16(TWI1_MASTER_ADDR)
+-#define bfin_write_TWI1_MASTER_ADDR(val)	bfin_write16(TWI1_MASTER_ADDR, val)
+-#define bfin_read_TWI1_INT_STAT()		bfin_read16(TWI1_INT_STAT)
+-#define bfin_write_TWI1_INT_STAT(val)		bfin_write16(TWI1_INT_STAT, val)
+-#define bfin_read_TWI1_INT_MASK()		bfin_read16(TWI1_INT_MASK)
+-#define bfin_write_TWI1_INT_MASK(val)		bfin_write16(TWI1_INT_MASK, val)
+-#define bfin_read_TWI1_FIFO_CTRL()		bfin_read16(TWI1_FIFO_CTRL)
+-#define bfin_write_TWI1_FIFO_CTRL(val)		bfin_write16(TWI1_FIFO_CTRL, val)
+-#define bfin_read_TWI1_FIFO_STAT()		bfin_read16(TWI1_FIFO_STAT)
+-#define bfin_write_TWI1_FIFO_STAT(val)		bfin_write16(TWI1_FIFO_STAT, val)
+-#define bfin_read_TWI1_XMT_DATA8()		bfin_read16(TWI1_XMT_DATA8)
+-#define bfin_write_TWI1_XMT_DATA8(val)		bfin_write16(TWI1_XMT_DATA8, val)
+-#define bfin_read_TWI1_XMT_DATA16()		bfin_read16(TWI1_XMT_DATA16)
+-#define bfin_write_TWI1_XMT_DATA16(val)		bfin_write16(TWI1_XMT_DATA16, val)
+-#define bfin_read_TWI1_RCV_DATA8()		bfin_read16(TWI1_RCV_DATA8)
+-#define bfin_write_TWI1_RCV_DATA8(val)		bfin_write16(TWI1_RCV_DATA8, val)
+-#define bfin_read_TWI1_RCV_DATA16()		bfin_read16(TWI1_RCV_DATA16)
+-#define bfin_write_TWI1_RCV_DATA16(val)		bfin_write16(TWI1_RCV_DATA16, val)
+-
+ /* SPI2  Registers */
+ 
+ #define bfin_read_SPI2_CTL()		bfin_read16(SPI2_CTL)
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF549.h b/include/asm-blackfin/mach-bf548/cdefBF549.h
+index 2ab5b7c..92d07d9 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF549.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF549.h
+@@ -185,39 +185,6 @@
+ 
+ /* Two Wire Interface Registers (TWI1) */
+ 
+-#define bfin_read_TWI1_CLKDIV()			bfin_read16(TWI1_CLKDIV)
+-#define bfin_write_TWI1_CLKDIV(val)		bfin_write16(TWI1_CLKDIV, val)
+-#define bfin_read_TWI1_CONTROL()		bfin_read16(TWI1_CONTROL)
+-#define bfin_write_TWI1_CONTROL(val)		bfin_write16(TWI1_CONTROL, val)
+-#define bfin_read_TWI1_SLAVE_CTRL()		bfin_read16(TWI1_SLAVE_CTRL)
+-#define bfin_write_TWI1_SLAVE_CTRL(val)		bfin_write16(TWI1_SLAVE_CTRL, val)
+-#define bfin_read_TWI1_SLAVE_STAT()		bfin_read16(TWI1_SLAVE_STAT)
+-#define bfin_write_TWI1_SLAVE_STAT(val)		bfin_write16(TWI1_SLAVE_STAT, val)
+-#define bfin_read_TWI1_SLAVE_ADDR()		bfin_read16(TWI1_SLAVE_ADDR)
+-#define bfin_write_TWI1_SLAVE_ADDR(val)		bfin_write16(TWI1_SLAVE_ADDR, val)
+-#define bfin_read_TWI1_MASTER_CTRL()		bfin_read16(TWI1_MASTER_CTRL)
+-#define bfin_write_TWI1_MASTER_CTRL(val)	bfin_write16(TWI1_MASTER_CTRL, val)
+-#define bfin_read_TWI1_MASTER_STAT()		bfin_read16(TWI1_MASTER_STAT)
+-#define bfin_write_TWI1_MASTER_STAT(val)	bfin_write16(TWI1_MASTER_STAT, val)
+-#define bfin_read_TWI1_MASTER_ADDR()		bfin_read16(TWI1_MASTER_ADDR)
+-#define bfin_write_TWI1_MASTER_ADDR(val)	bfin_write16(TWI1_MASTER_ADDR, val)
+-#define bfin_read_TWI1_INT_STAT()		bfin_read16(TWI1_INT_STAT)
+-#define bfin_write_TWI1_INT_STAT(val)		bfin_write16(TWI1_INT_STAT, val)
+-#define bfin_read_TWI1_INT_MASK()		bfin_read16(TWI1_INT_MASK)
+-#define bfin_write_TWI1_INT_MASK(val)		bfin_write16(TWI1_INT_MASK, val)
+-#define bfin_read_TWI1_FIFO_CTRL()		bfin_read16(TWI1_FIFO_CTRL)
+-#define bfin_write_TWI1_FIFO_CTRL(val)		bfin_write16(TWI1_FIFO_CTRL, val)
+-#define bfin_read_TWI1_FIFO_STAT()		bfin_read16(TWI1_FIFO_STAT)
+-#define bfin_write_TWI1_FIFO_STAT(val)		bfin_write16(TWI1_FIFO_STAT, val)
+-#define bfin_read_TWI1_XMT_DATA8()		bfin_read16(TWI1_XMT_DATA8)
+-#define bfin_write_TWI1_XMT_DATA8(val)		bfin_write16(TWI1_XMT_DATA8, val)
+-#define bfin_read_TWI1_XMT_DATA16()		bfin_read16(TWI1_XMT_DATA16)
+-#define bfin_write_TWI1_XMT_DATA16(val)		bfin_write16(TWI1_XMT_DATA16, val)
+-#define bfin_read_TWI1_RCV_DATA8()		bfin_read16(TWI1_RCV_DATA8)
+-#define bfin_write_TWI1_RCV_DATA8(val)		bfin_write16(TWI1_RCV_DATA8, val)
+-#define bfin_read_TWI1_RCV_DATA16()		bfin_read16(TWI1_RCV_DATA16)
+-#define bfin_write_TWI1_RCV_DATA16(val)		bfin_write16(TWI1_RCV_DATA16, val)
+-
+ /* SPI2 Registers */
+ 
+ #define bfin_read_SPI2_CTL()		bfin_read16(SPI2_CTL)
+@@ -1773,7 +1740,7 @@
+ #define bfin_read_USB_DMA5ADDRHIGH()		bfin_read16(USB_DMA5ADDRHIGH)
+ #define bfin_write_USB_DMA5ADDRHIGH(val)		bfin_write16(USB_DMA5ADDRHIGH, val)
+ #define bfin_read_USB_DMA5COUNTLOW()		bfin_read16(USB_DMA5COUNTLOW)
+-#define bfin_write_USB_DMA5COUNTLOW(val)	fin_write16(USB_DMA5COUNTLOW, val)
++#define bfin_write_USB_DMA5COUNTLOW(val)	bfin_write16(USB_DMA5COUNTLOW, val)
+ #define bfin_read_USB_DMA5COUNTHIGH()		bfin_read16(USB_DMA5COUNTHIGH)
+ #define bfin_write_USB_DMA5COUNTHIGH(val)	bfin_write16(USB_DMA5COUNTHIGH, val)
+ 
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
+index 19ddcd8..57ac8cb 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
+@@ -43,7 +43,33 @@
+ /* PLL Registers */
+ 
+ #define bfin_read_PLL_CTL()		bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val)		bfin_write16(PLL_CTL, val)
++/* 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(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(flags);
++}
+ #define bfin_read_PLL_DIV()		bfin_read16(PLL_DIV)
+ #define bfin_write_PLL_DIV(val)		bfin_write16(PLL_DIV, val)
+ #define bfin_read_VR_CTL()		bfin_read16(VR_CTL)
+@@ -52,6 +78,10 @@ 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(flags);
+ 	/* Enable the PLL Wakeup bit in SIC IWR */
+ 	iwr0 = bfin_read32(SIC_IWR0);
+ 	iwr1 = bfin_read32(SIC_IWR1);
+@@ -63,13 +93,12 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ 
+ 	bfin_write16(VR_CTL, val);
+ 	SSYNC();
+-
+-	local_irq_save(flags);
+ 	asm("IDLE;");
+-	local_irq_restore(flags);
++
+ 	bfin_write32(SIC_IWR0, iwr0);
+ 	bfin_write32(SIC_IWR1, iwr1);
+ 	bfin_write32(SIC_IWR2, iwr2);
++	local_irq_restore(flags);
+ }
+ #define bfin_read_PLL_STAT()		bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val)	bfin_write16(PLL_STAT, val)
+@@ -211,39 +240,6 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ 
+ /* Two Wire Interface Registers (TWI0) */
+ 
+-#define bfin_read_TWI0_CLKDIV()			bfin_read16(TWI0_CLKDIV)
+-#define bfin_write_TWI0_CLKDIV(val)		bfin_write16(TWI0_CLKDIV, val)
+-#define bfin_read_TWI0_CONTROL()		bfin_read16(TWI0_CONTROL)
+-#define bfin_write_TWI0_CONTROL(val)		bfin_write16(TWI0_CONTROL, val)
+-#define bfin_read_TWI0_SLAVE_CTRL()		bfin_read16(TWI0_SLAVE_CTRL)
+-#define bfin_write_TWI0_SLAVE_CTRL(val)		bfin_write16(TWI0_SLAVE_CTRL, val)
+-#define bfin_read_TWI0_SLAVE_STAT()		bfin_read16(TWI0_SLAVE_STAT)
+-#define bfin_write_TWI0_SLAVE_STAT(val)		bfin_write16(TWI0_SLAVE_STAT, val)
+-#define bfin_read_TWI0_SLAVE_ADDR()		bfin_read16(TWI0_SLAVE_ADDR)
+-#define bfin_write_TWI0_SLAVE_ADDR(val)		bfin_write16(TWI0_SLAVE_ADDR, val)
+-#define bfin_read_TWI0_MASTER_CTRL()		bfin_read16(TWI0_MASTER_CTRL)
+-#define bfin_write_TWI0_MASTER_CTRL(val)	bfin_write16(TWI0_MASTER_CTRL, val)
+-#define bfin_read_TWI0_MASTER_STAT()		bfin_read16(TWI0_MASTER_STAT)
+-#define bfin_write_TWI0_MASTER_STAT(val)	bfin_write16(TWI0_MASTER_STAT, val)
+-#define bfin_read_TWI0_MASTER_ADDR()		bfin_read16(TWI0_MASTER_ADDR)
+-#define bfin_write_TWI0_MASTER_ADDR(val)	bfin_write16(TWI0_MASTER_ADDR, val)
+-#define bfin_read_TWI0_INT_STAT()		bfin_read16(TWI0_INT_STAT)
+-#define bfin_write_TWI0_INT_STAT(val)		bfin_write16(TWI0_INT_STAT, val)
+-#define bfin_read_TWI0_INT_MASK()		bfin_read16(TWI0_INT_MASK)
+-#define bfin_write_TWI0_INT_MASK(val)		bfin_write16(TWI0_INT_MASK, val)
+-#define bfin_read_TWI0_FIFO_CTRL()		bfin_read16(TWI0_FIFO_CTRL)
+-#define bfin_write_TWI0_FIFO_CTRL(val)		bfin_write16(TWI0_FIFO_CTRL, val)
+-#define bfin_read_TWI0_FIFO_STAT()		bfin_read16(TWI0_FIFO_STAT)
+-#define bfin_write_TWI0_FIFO_STAT(val)		bfin_write16(TWI0_FIFO_STAT, val)
+-#define bfin_read_TWI0_XMT_DATA8()		bfin_read16(TWI0_XMT_DATA8)
+-#define bfin_write_TWI0_XMT_DATA8(val)		bfin_write16(TWI0_XMT_DATA8, val)
+-#define bfin_read_TWI0_XMT_DATA16()		bfin_read16(TWI0_XMT_DATA16)
+-#define bfin_write_TWI0_XMT_DATA16(val)		bfin_write16(TWI0_XMT_DATA16, val)
+-#define bfin_read_TWI0_RCV_DATA8()		bfin_read16(TWI0_RCV_DATA8)
+-#define bfin_write_TWI0_RCV_DATA8(val)		bfin_write16(TWI0_RCV_DATA8, val)
+-#define bfin_read_TWI0_RCV_DATA16()		bfin_read16(TWI0_RCV_DATA16)
+-#define bfin_write_TWI0_RCV_DATA16(val)		bfin_write16(TWI0_RCV_DATA16, val)
+-
+ /* SPORT0 is not defined in the shared file because it is not available on the ADSP-BF542 and ADSP-BF544 bfin_read_()rocessors */
+ 
+ /* SPORT1 Registers */
+@@ -323,7 +319,7 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_EBIU_DDRQUE()		bfin_read32(EBIU_DDRQUE)
+ #define bfin_write_EBIU_DDRQUE(val)	bfin_write32(EBIU_DDRQUE, val)
+ #define bfin_read_EBIU_ERRADD() 	bfin_read32(EBIU_ERRADD)
+-#define bfin_write_EBIU_ERRADD(val) 	bfin_write32(EBIU_ERRADD)
++#define bfin_write_EBIU_ERRADD(val) 	bfin_write32(EBIU_ERRADD, val)
+ #define bfin_read_EBIU_ERRMST()		bfin_read16(EBIU_ERRMST)
+ #define bfin_write_EBIU_ERRMST(val)	bfin_write16(EBIU_ERRMST, val)
+ #define bfin_read_EBIU_RSTCTL()		bfin_read16(EBIU_RSTCTL)
+@@ -392,23 +388,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 0 Registers */
+ 
+ #define bfin_read_DMA0_NEXT_DESC_PTR() 		bfin_read32(DMA0_NEXT_DESC_PTR)
+-#define bfin_write_DMA0_NEXT_DESC_PTR(val) 	bfin_write32(DMA0_NEXT_DESC_PTR)
++#define bfin_write_DMA0_NEXT_DESC_PTR(val) 	bfin_write32(DMA0_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA0_START_ADDR() 		bfin_read32(DMA0_START_ADDR)
+-#define bfin_write_DMA0_START_ADDR(val) 	bfin_write32(DMA0_START_ADDR)
++#define bfin_write_DMA0_START_ADDR(val) 	bfin_write32(DMA0_START_ADDR, val)
+ #define bfin_read_DMA0_CONFIG()			bfin_read16(DMA0_CONFIG)
+ #define bfin_write_DMA0_CONFIG(val)		bfin_write16(DMA0_CONFIG, val)
+ #define bfin_read_DMA0_X_COUNT()		bfin_read16(DMA0_X_COUNT)
+ #define bfin_write_DMA0_X_COUNT(val)		bfin_write16(DMA0_X_COUNT, val)
+ #define bfin_read_DMA0_X_MODIFY()		bfin_read16(DMA0_X_MODIFY)
+-#define bfin_write_DMA0_X_MODIFY(val) 		bfin_write16(DMA0_X_MODIFY)
++#define bfin_write_DMA0_X_MODIFY(val) 		bfin_write16(DMA0_X_MODIFY, val)
+ #define bfin_read_DMA0_Y_COUNT()		bfin_read16(DMA0_Y_COUNT)
+ #define bfin_write_DMA0_Y_COUNT(val)		bfin_write16(DMA0_Y_COUNT, val)
+ #define bfin_read_DMA0_Y_MODIFY()		bfin_read16(DMA0_Y_MODIFY)
+-#define bfin_write_DMA0_Y_MODIFY(val) 		bfin_write16(DMA0_Y_MODIFY)
++#define bfin_write_DMA0_Y_MODIFY(val) 		bfin_write16(DMA0_Y_MODIFY, val)
+ #define bfin_read_DMA0_CURR_DESC_PTR() 		bfin_read32(DMA0_CURR_DESC_PTR)
+-#define bfin_write_DMA0_CURR_DESC_PTR(val) 	bfin_write32(DMA0_CURR_DESC_PTR)
++#define bfin_write_DMA0_CURR_DESC_PTR(val) 	bfin_write32(DMA0_CURR_DESC_PTR, val)
+ #define bfin_read_DMA0_CURR_ADDR() 		bfin_read32(DMA0_CURR_ADDR)
+-#define bfin_write_DMA0_CURR_ADDR(val) 		bfin_write32(DMA0_CURR_ADDR)
++#define bfin_write_DMA0_CURR_ADDR(val) 		bfin_write32(DMA0_CURR_ADDR, val)
+ #define bfin_read_DMA0_IRQ_STATUS()		bfin_read16(DMA0_IRQ_STATUS)
+ #define bfin_write_DMA0_IRQ_STATUS(val)		bfin_write16(DMA0_IRQ_STATUS, val)
+ #define bfin_read_DMA0_PERIPHERAL_MAP()		bfin_read16(DMA0_PERIPHERAL_MAP)
+@@ -421,23 +417,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 1 Registers */
+ 
+ #define bfin_read_DMA1_NEXT_DESC_PTR() 		bfin_read32(DMA1_NEXT_DESC_PTR)
+-#define bfin_write_DMA1_NEXT_DESC_PTR(val) 	bfin_write32(DMA1_NEXT_DESC_PTR)
++#define bfin_write_DMA1_NEXT_DESC_PTR(val) 	bfin_write32(DMA1_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA1_START_ADDR() 		bfin_read32(DMA1_START_ADDR)
+-#define bfin_write_DMA1_START_ADDR(val) 	bfin_write32(DMA1_START_ADDR)
++#define bfin_write_DMA1_START_ADDR(val) 	bfin_write32(DMA1_START_ADDR, val)
+ #define bfin_read_DMA1_CONFIG()			bfin_read16(DMA1_CONFIG)
+ #define bfin_write_DMA1_CONFIG(val)		bfin_write16(DMA1_CONFIG, val)
+ #define bfin_read_DMA1_X_COUNT()		bfin_read16(DMA1_X_COUNT)
+ #define bfin_write_DMA1_X_COUNT(val)		bfin_write16(DMA1_X_COUNT, val)
+ #define bfin_read_DMA1_X_MODIFY()		bfin_read16(DMA1_X_MODIFY)
+-#define bfin_write_DMA1_X_MODIFY(val) 		bfin_write16(DMA1_X_MODIFY)
++#define bfin_write_DMA1_X_MODIFY(val) 		bfin_write16(DMA1_X_MODIFY, val)
+ #define bfin_read_DMA1_Y_COUNT()		bfin_read16(DMA1_Y_COUNT)
+ #define bfin_write_DMA1_Y_COUNT(val)		bfin_write16(DMA1_Y_COUNT, val)
+ #define bfin_read_DMA1_Y_MODIFY()		bfin_read16(DMA1_Y_MODIFY)
+-#define bfin_write_DMA1_Y_MODIFY(val) 		bfin_write16(DMA1_Y_MODIFY)
++#define bfin_write_DMA1_Y_MODIFY(val) 		bfin_write16(DMA1_Y_MODIFY, val)
+ #define bfin_read_DMA1_CURR_DESC_PTR() 		bfin_read32(DMA1_CURR_DESC_PTR)
+-#define bfin_write_DMA1_CURR_DESC_PTR(val) 	bfin_write32(DMA1_CURR_DESC_PTR)
++#define bfin_write_DMA1_CURR_DESC_PTR(val) 	bfin_write32(DMA1_CURR_DESC_PTR, val)
+ #define bfin_read_DMA1_CURR_ADDR() 		bfin_read32(DMA1_CURR_ADDR)
+-#define bfin_write_DMA1_CURR_ADDR(val) 		bfin_write32(DMA1_CURR_ADDR)
++#define bfin_write_DMA1_CURR_ADDR(val) 		bfin_write32(DMA1_CURR_ADDR, val)
+ #define bfin_read_DMA1_IRQ_STATUS()		bfin_read16(DMA1_IRQ_STATUS)
+ #define bfin_write_DMA1_IRQ_STATUS(val)		bfin_write16(DMA1_IRQ_STATUS, val)
+ #define bfin_read_DMA1_PERIPHERAL_MAP()		bfin_read16(DMA1_PERIPHERAL_MAP)
+@@ -450,23 +446,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 2 Registers */
+ 
+ #define bfin_read_DMA2_NEXT_DESC_PTR() 		bfin_read32(DMA2_NEXT_DESC_PTR)
+-#define bfin_write_DMA2_NEXT_DESC_PTR(val) 	bfin_write32(DMA2_NEXT_DESC_PTR)
++#define bfin_write_DMA2_NEXT_DESC_PTR(val) 	bfin_write32(DMA2_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA2_START_ADDR() 		bfin_read32(DMA2_START_ADDR)
+-#define bfin_write_DMA2_START_ADDR(val) 	bfin_write32(DMA2_START_ADDR)
++#define bfin_write_DMA2_START_ADDR(val) 	bfin_write32(DMA2_START_ADDR, val)
+ #define bfin_read_DMA2_CONFIG()			bfin_read16(DMA2_CONFIG)
+ #define bfin_write_DMA2_CONFIG(val)		bfin_write16(DMA2_CONFIG, val)
+ #define bfin_read_DMA2_X_COUNT()		bfin_read16(DMA2_X_COUNT)
+ #define bfin_write_DMA2_X_COUNT(val)		bfin_write16(DMA2_X_COUNT, val)
+ #define bfin_read_DMA2_X_MODIFY()		bfin_read16(DMA2_X_MODIFY)
+-#define bfin_write_DMA2_X_MODIFY(val) 		bfin_write16(DMA2_X_MODIFY)
++#define bfin_write_DMA2_X_MODIFY(val) 		bfin_write16(DMA2_X_MODIFY, val)
+ #define bfin_read_DMA2_Y_COUNT()		bfin_read16(DMA2_Y_COUNT)
+ #define bfin_write_DMA2_Y_COUNT(val)		bfin_write16(DMA2_Y_COUNT, val)
+ #define bfin_read_DMA2_Y_MODIFY()		bfin_read16(DMA2_Y_MODIFY)
+-#define bfin_write_DMA2_Y_MODIFY(val) 		bfin_write16(DMA2_Y_MODIFY)
++#define bfin_write_DMA2_Y_MODIFY(val) 		bfin_write16(DMA2_Y_MODIFY, val)
+ #define bfin_read_DMA2_CURR_DESC_PTR() 		bfin_read32(DMA2_CURR_DESC_PTR)
+-#define bfin_write_DMA2_CURR_DESC_PTR(val) 	bfin_write32(DMA2_CURR_DESC_PTR)
++#define bfin_write_DMA2_CURR_DESC_PTR(val) 	bfin_write32(DMA2_CURR_DESC_PTR, val)
+ #define bfin_read_DMA2_CURR_ADDR() 		bfin_read32(DMA2_CURR_ADDR)
+-#define bfin_write_DMA2_CURR_ADDR(val) 		bfin_write32(DMA2_CURR_ADDR)
++#define bfin_write_DMA2_CURR_ADDR(val) 		bfin_write32(DMA2_CURR_ADDR, val)
+ #define bfin_read_DMA2_IRQ_STATUS()		bfin_read16(DMA2_IRQ_STATUS)
+ #define bfin_write_DMA2_IRQ_STATUS(val)		bfin_write16(DMA2_IRQ_STATUS, val)
+ #define bfin_read_DMA2_PERIPHERAL_MAP()		bfin_read16(DMA2_PERIPHERAL_MAP)
+@@ -479,23 +475,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 3 Registers */
+ 
+ #define bfin_read_DMA3_NEXT_DESC_PTR() 		bfin_read32(DMA3_NEXT_DESC_PTR)
+-#define bfin_write_DMA3_NEXT_DESC_PTR(val) 	bfin_write32(DMA3_NEXT_DESC_PTR)
++#define bfin_write_DMA3_NEXT_DESC_PTR(val) 	bfin_write32(DMA3_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA3_START_ADDR() 		bfin_read32(DMA3_START_ADDR)
+-#define bfin_write_DMA3_START_ADDR(val) 	bfin_write32(DMA3_START_ADDR)
++#define bfin_write_DMA3_START_ADDR(val) 	bfin_write32(DMA3_START_ADDR, val)
+ #define bfin_read_DMA3_CONFIG()			bfin_read16(DMA3_CONFIG)
+ #define bfin_write_DMA3_CONFIG(val)		bfin_write16(DMA3_CONFIG, val)
+ #define bfin_read_DMA3_X_COUNT()		bfin_read16(DMA3_X_COUNT)
+ #define bfin_write_DMA3_X_COUNT(val)		bfin_write16(DMA3_X_COUNT, val)
+ #define bfin_read_DMA3_X_MODIFY()		bfin_read16(DMA3_X_MODIFY)
+-#define bfin_write_DMA3_X_MODIFY(val) 		bfin_write16(DMA3_X_MODIFY)
++#define bfin_write_DMA3_X_MODIFY(val) 		bfin_write16(DMA3_X_MODIFY, val)
+ #define bfin_read_DMA3_Y_COUNT()		bfin_read16(DMA3_Y_COUNT)
+ #define bfin_write_DMA3_Y_COUNT(val)		bfin_write16(DMA3_Y_COUNT, val)
+ #define bfin_read_DMA3_Y_MODIFY()		bfin_read16(DMA3_Y_MODIFY)
+-#define bfin_write_DMA3_Y_MODIFY(val) 		bfin_write16(DMA3_Y_MODIFY)
++#define bfin_write_DMA3_Y_MODIFY(val) 		bfin_write16(DMA3_Y_MODIFY, val)
+ #define bfin_read_DMA3_CURR_DESC_PTR() 		bfin_read32(DMA3_CURR_DESC_PTR)
+-#define bfin_write_DMA3_CURR_DESC_PTR(val) 	bfin_write32(DMA3_CURR_DESC_PTR)
++#define bfin_write_DMA3_CURR_DESC_PTR(val) 	bfin_write32(DMA3_CURR_DESC_PTR, val)
+ #define bfin_read_DMA3_CURR_ADDR() 		bfin_read32(DMA3_CURR_ADDR)
+-#define bfin_write_DMA3_CURR_ADDR(val) 		bfin_write32(DMA3_CURR_ADDR)
++#define bfin_write_DMA3_CURR_ADDR(val) 		bfin_write32(DMA3_CURR_ADDR, val)
+ #define bfin_read_DMA3_IRQ_STATUS()		bfin_read16(DMA3_IRQ_STATUS)
+ #define bfin_write_DMA3_IRQ_STATUS(val)		bfin_write16(DMA3_IRQ_STATUS, val)
+ #define bfin_read_DMA3_PERIPHERAL_MAP()		bfin_read16(DMA3_PERIPHERAL_MAP)
+@@ -508,23 +504,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 4 Registers */
+ 
+ #define bfin_read_DMA4_NEXT_DESC_PTR() 		bfin_read32(DMA4_NEXT_DESC_PTR)
+-#define bfin_write_DMA4_NEXT_DESC_PTR(val) 	bfin_write32(DMA4_NEXT_DESC_PTR)
++#define bfin_write_DMA4_NEXT_DESC_PTR(val) 	bfin_write32(DMA4_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA4_START_ADDR() 		bfin_read32(DMA4_START_ADDR)
+-#define bfin_write_DMA4_START_ADDR(val) 	bfin_write32(DMA4_START_ADDR)
++#define bfin_write_DMA4_START_ADDR(val) 	bfin_write32(DMA4_START_ADDR, val)
+ #define bfin_read_DMA4_CONFIG()			bfin_read16(DMA4_CONFIG)
+ #define bfin_write_DMA4_CONFIG(val)		bfin_write16(DMA4_CONFIG, val)
+ #define bfin_read_DMA4_X_COUNT()		bfin_read16(DMA4_X_COUNT)
+ #define bfin_write_DMA4_X_COUNT(val)		bfin_write16(DMA4_X_COUNT, val)
+ #define bfin_read_DMA4_X_MODIFY()		bfin_read16(DMA4_X_MODIFY)
+-#define bfin_write_DMA4_X_MODIFY(val) 		bfin_write16(DMA4_X_MODIFY)
++#define bfin_write_DMA4_X_MODIFY(val) 		bfin_write16(DMA4_X_MODIFY, val)
+ #define bfin_read_DMA4_Y_COUNT()		bfin_read16(DMA4_Y_COUNT)
+ #define bfin_write_DMA4_Y_COUNT(val)		bfin_write16(DMA4_Y_COUNT, val)
+ #define bfin_read_DMA4_Y_MODIFY()		bfin_read16(DMA4_Y_MODIFY)
+-#define bfin_write_DMA4_Y_MODIFY(val) 		bfin_write16(DMA4_Y_MODIFY)
++#define bfin_write_DMA4_Y_MODIFY(val) 		bfin_write16(DMA4_Y_MODIFY, val)
+ #define bfin_read_DMA4_CURR_DESC_PTR() 		bfin_read32(DMA4_CURR_DESC_PTR)
+-#define bfin_write_DMA4_CURR_DESC_PTR(val) 	bfin_write32(DMA4_CURR_DESC_PTR)
++#define bfin_write_DMA4_CURR_DESC_PTR(val) 	bfin_write32(DMA4_CURR_DESC_PTR, val)
+ #define bfin_read_DMA4_CURR_ADDR() 		bfin_read32(DMA4_CURR_ADDR)
+-#define bfin_write_DMA4_CURR_ADDR(val) 		bfin_write32(DMA4_CURR_ADDR)
++#define bfin_write_DMA4_CURR_ADDR(val) 		bfin_write32(DMA4_CURR_ADDR, val)
+ #define bfin_read_DMA4_IRQ_STATUS()		bfin_read16(DMA4_IRQ_STATUS)
+ #define bfin_write_DMA4_IRQ_STATUS(val)		bfin_write16(DMA4_IRQ_STATUS, val)
+ #define bfin_read_DMA4_PERIPHERAL_MAP()		bfin_read16(DMA4_PERIPHERAL_MAP)
+@@ -537,23 +533,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 5 Registers */
+ 
+ #define bfin_read_DMA5_NEXT_DESC_PTR() 		bfin_read32(DMA5_NEXT_DESC_PTR)
+-#define bfin_write_DMA5_NEXT_DESC_PTR(val) 	bfin_write32(DMA5_NEXT_DESC_PTR)
++#define bfin_write_DMA5_NEXT_DESC_PTR(val) 	bfin_write32(DMA5_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA5_START_ADDR() 		bfin_read32(DMA5_START_ADDR)
+-#define bfin_write_DMA5_START_ADDR(val) 	bfin_write32(DMA5_START_ADDR)
++#define bfin_write_DMA5_START_ADDR(val) 	bfin_write32(DMA5_START_ADDR, val)
+ #define bfin_read_DMA5_CONFIG()			bfin_read16(DMA5_CONFIG)
+ #define bfin_write_DMA5_CONFIG(val)		bfin_write16(DMA5_CONFIG, val)
+ #define bfin_read_DMA5_X_COUNT()		bfin_read16(DMA5_X_COUNT)
+ #define bfin_write_DMA5_X_COUNT(val)		bfin_write16(DMA5_X_COUNT, val)
+ #define bfin_read_DMA5_X_MODIFY()		bfin_read16(DMA5_X_MODIFY)
+-#define bfin_write_DMA5_X_MODIFY(val) 		bfin_write16(DMA5_X_MODIFY)
++#define bfin_write_DMA5_X_MODIFY(val) 		bfin_write16(DMA5_X_MODIFY, val)
+ #define bfin_read_DMA5_Y_COUNT()		bfin_read16(DMA5_Y_COUNT)
+ #define bfin_write_DMA5_Y_COUNT(val)		bfin_write16(DMA5_Y_COUNT, val)
+ #define bfin_read_DMA5_Y_MODIFY()		bfin_read16(DMA5_Y_MODIFY)
+-#define bfin_write_DMA5_Y_MODIFY(val) 		bfin_write16(DMA5_Y_MODIFY)
++#define bfin_write_DMA5_Y_MODIFY(val) 		bfin_write16(DMA5_Y_MODIFY, val)
+ #define bfin_read_DMA5_CURR_DESC_PTR() 		bfin_read32(DMA5_CURR_DESC_PTR)
+-#define bfin_write_DMA5_CURR_DESC_PTR(val) 	bfin_write32(DMA5_CURR_DESC_PTR)
++#define bfin_write_DMA5_CURR_DESC_PTR(val) 	bfin_write32(DMA5_CURR_DESC_PTR, val)
+ #define bfin_read_DMA5_CURR_ADDR() 		bfin_read32(DMA5_CURR_ADDR)
+-#define bfin_write_DMA5_CURR_ADDR(val) 		bfin_write32(DMA5_CURR_ADDR)
++#define bfin_write_DMA5_CURR_ADDR(val) 		bfin_write32(DMA5_CURR_ADDR, val)
+ #define bfin_read_DMA5_IRQ_STATUS()		bfin_read16(DMA5_IRQ_STATUS)
+ #define bfin_write_DMA5_IRQ_STATUS(val)		bfin_write16(DMA5_IRQ_STATUS, val)
+ #define bfin_read_DMA5_PERIPHERAL_MAP()		bfin_read16(DMA5_PERIPHERAL_MAP)
+@@ -566,23 +562,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 6 Registers */
+ 
+ #define bfin_read_DMA6_NEXT_DESC_PTR() 		bfin_read32(DMA6_NEXT_DESC_PTR)
+-#define bfin_write_DMA6_NEXT_DESC_PTR(val) 	bfin_write32(DMA6_NEXT_DESC_PTR)
++#define bfin_write_DMA6_NEXT_DESC_PTR(val) 	bfin_write32(DMA6_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA6_START_ADDR() 		bfin_read32(DMA6_START_ADDR)
+-#define bfin_write_DMA6_START_ADDR(val) 	bfin_write32(DMA6_START_ADDR)
++#define bfin_write_DMA6_START_ADDR(val) 	bfin_write32(DMA6_START_ADDR, val)
+ #define bfin_read_DMA6_CONFIG()			bfin_read16(DMA6_CONFIG)
+ #define bfin_write_DMA6_CONFIG(val)		bfin_write16(DMA6_CONFIG, val)
+ #define bfin_read_DMA6_X_COUNT()		bfin_read16(DMA6_X_COUNT)
+ #define bfin_write_DMA6_X_COUNT(val)		bfin_write16(DMA6_X_COUNT, val)
+ #define bfin_read_DMA6_X_MODIFY()		bfin_read16(DMA6_X_MODIFY)
+-#define bfin_write_DMA6_X_MODIFY(val) 		bfin_write16(DMA6_X_MODIFY)
++#define bfin_write_DMA6_X_MODIFY(val) 		bfin_write16(DMA6_X_MODIFY, val)
+ #define bfin_read_DMA6_Y_COUNT()		bfin_read16(DMA6_Y_COUNT)
+ #define bfin_write_DMA6_Y_COUNT(val)		bfin_write16(DMA6_Y_COUNT, val)
+ #define bfin_read_DMA6_Y_MODIFY()		bfin_read16(DMA6_Y_MODIFY)
+-#define bfin_write_DMA6_Y_MODIFY(val) 		bfin_write16(DMA6_Y_MODIFY)
++#define bfin_write_DMA6_Y_MODIFY(val) 		bfin_write16(DMA6_Y_MODIFY, val)
+ #define bfin_read_DMA6_CURR_DESC_PTR() 		bfin_read32(DMA6_CURR_DESC_PTR)
+-#define bfin_write_DMA6_CURR_DESC_PTR(val) 	bfin_write32(DMA6_CURR_DESC_PTR)
++#define bfin_write_DMA6_CURR_DESC_PTR(val) 	bfin_write32(DMA6_CURR_DESC_PTR, val)
+ #define bfin_read_DMA6_CURR_ADDR() 		bfin_read32(DMA6_CURR_ADDR)
+-#define bfin_write_DMA6_CURR_ADDR(val) 		bfin_write32(DMA6_CURR_ADDR)
++#define bfin_write_DMA6_CURR_ADDR(val) 		bfin_write32(DMA6_CURR_ADDR, val)
+ #define bfin_read_DMA6_IRQ_STATUS()		bfin_read16(DMA6_IRQ_STATUS)
+ #define bfin_write_DMA6_IRQ_STATUS(val)		bfin_write16(DMA6_IRQ_STATUS, val)
+ #define bfin_read_DMA6_PERIPHERAL_MAP()		bfin_read16(DMA6_PERIPHERAL_MAP)
+@@ -595,23 +591,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 7 Registers */
+ 
+ #define bfin_read_DMA7_NEXT_DESC_PTR() 		bfin_read32(DMA7_NEXT_DESC_PTR)
+-#define bfin_write_DMA7_NEXT_DESC_PTR(val) 	bfin_write32(DMA7_NEXT_DESC_PTR)
++#define bfin_write_DMA7_NEXT_DESC_PTR(val) 	bfin_write32(DMA7_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA7_START_ADDR() 		bfin_read32(DMA7_START_ADDR)
+-#define bfin_write_DMA7_START_ADDR(val) 	bfin_write32(DMA7_START_ADDR)
++#define bfin_write_DMA7_START_ADDR(val) 	bfin_write32(DMA7_START_ADDR, val)
+ #define bfin_read_DMA7_CONFIG()			bfin_read16(DMA7_CONFIG)
+ #define bfin_write_DMA7_CONFIG(val)		bfin_write16(DMA7_CONFIG, val)
+ #define bfin_read_DMA7_X_COUNT()		bfin_read16(DMA7_X_COUNT)
+ #define bfin_write_DMA7_X_COUNT(val)		bfin_write16(DMA7_X_COUNT, val)
+ #define bfin_read_DMA7_X_MODIFY()		bfin_read16(DMA7_X_MODIFY)
+-#define bfin_write_DMA7_X_MODIFY(val) 		bfin_write16(DMA7_X_MODIFY)
++#define bfin_write_DMA7_X_MODIFY(val) 		bfin_write16(DMA7_X_MODIFY, val)
+ #define bfin_read_DMA7_Y_COUNT()		bfin_read16(DMA7_Y_COUNT)
+ #define bfin_write_DMA7_Y_COUNT(val)		bfin_write16(DMA7_Y_COUNT, val)
+ #define bfin_read_DMA7_Y_MODIFY()		bfin_read16(DMA7_Y_MODIFY)
+-#define bfin_write_DMA7_Y_MODIFY(val) 		bfin_write16(DMA7_Y_MODIFY)
++#define bfin_write_DMA7_Y_MODIFY(val) 		bfin_write16(DMA7_Y_MODIFY, val)
+ #define bfin_read_DMA7_CURR_DESC_PTR() 		bfin_read32(DMA7_CURR_DESC_PTR)
+-#define bfin_write_DMA7_CURR_DESC_PTR(val) 	bfin_write32(DMA7_CURR_DESC_PTR)
++#define bfin_write_DMA7_CURR_DESC_PTR(val) 	bfin_write32(DMA7_CURR_DESC_PTR, val)
+ #define bfin_read_DMA7_CURR_ADDR() 		bfin_read32(DMA7_CURR_ADDR)
+-#define bfin_write_DMA7_CURR_ADDR(val) 		bfin_write32(DMA7_CURR_ADDR)
++#define bfin_write_DMA7_CURR_ADDR(val) 		bfin_write32(DMA7_CURR_ADDR, val)
+ #define bfin_read_DMA7_IRQ_STATUS()		bfin_read16(DMA7_IRQ_STATUS)
+ #define bfin_write_DMA7_IRQ_STATUS(val)		bfin_write16(DMA7_IRQ_STATUS, val)
+ #define bfin_read_DMA7_PERIPHERAL_MAP()		bfin_read16(DMA7_PERIPHERAL_MAP)
+@@ -624,23 +620,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 8 Registers */
+ 
+ #define bfin_read_DMA8_NEXT_DESC_PTR() 		bfin_read32(DMA8_NEXT_DESC_PTR)
+-#define bfin_write_DMA8_NEXT_DESC_PTR(val) 	bfin_write32(DMA8_NEXT_DESC_PTR)
++#define bfin_write_DMA8_NEXT_DESC_PTR(val) 	bfin_write32(DMA8_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA8_START_ADDR() 		bfin_read32(DMA8_START_ADDR)
+-#define bfin_write_DMA8_START_ADDR(val) 	bfin_write32(DMA8_START_ADDR)
++#define bfin_write_DMA8_START_ADDR(val) 	bfin_write32(DMA8_START_ADDR, val)
+ #define bfin_read_DMA8_CONFIG()			bfin_read16(DMA8_CONFIG)
+ #define bfin_write_DMA8_CONFIG(val)		bfin_write16(DMA8_CONFIG, val)
+ #define bfin_read_DMA8_X_COUNT()		bfin_read16(DMA8_X_COUNT)
+ #define bfin_write_DMA8_X_COUNT(val)		bfin_write16(DMA8_X_COUNT, val)
+ #define bfin_read_DMA8_X_MODIFY()		bfin_read16(DMA8_X_MODIFY)
+-#define bfin_write_DMA8_X_MODIFY(val) 		bfin_write16(DMA8_X_MODIFY)
++#define bfin_write_DMA8_X_MODIFY(val) 		bfin_write16(DMA8_X_MODIFY, val)
+ #define bfin_read_DMA8_Y_COUNT()		bfin_read16(DMA8_Y_COUNT)
+ #define bfin_write_DMA8_Y_COUNT(val)		bfin_write16(DMA8_Y_COUNT, val)
+ #define bfin_read_DMA8_Y_MODIFY()		bfin_read16(DMA8_Y_MODIFY)
+-#define bfin_write_DMA8_Y_MODIFY(val) 		bfin_write16(DMA8_Y_MODIFY)
++#define bfin_write_DMA8_Y_MODIFY(val) 		bfin_write16(DMA8_Y_MODIFY, val)
+ #define bfin_read_DMA8_CURR_DESC_PTR() 		bfin_read32(DMA8_CURR_DESC_PTR)
+-#define bfin_write_DMA8_CURR_DESC_PTR(val) 	bfin_write32(DMA8_CURR_DESC_PTR)
++#define bfin_write_DMA8_CURR_DESC_PTR(val) 	bfin_write32(DMA8_CURR_DESC_PTR, val)
+ #define bfin_read_DMA8_CURR_ADDR() 		bfin_read32(DMA8_CURR_ADDR)
+-#define bfin_write_DMA8_CURR_ADDR(val) 		bfin_write32(DMA8_CURR_ADDR)
++#define bfin_write_DMA8_CURR_ADDR(val) 		bfin_write32(DMA8_CURR_ADDR, val)
+ #define bfin_read_DMA8_IRQ_STATUS()		bfin_read16(DMA8_IRQ_STATUS)
+ #define bfin_write_DMA8_IRQ_STATUS(val)		bfin_write16(DMA8_IRQ_STATUS, val)
+ #define bfin_read_DMA8_PERIPHERAL_MAP()		bfin_read16(DMA8_PERIPHERAL_MAP)
+@@ -653,23 +649,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 9 Registers */
+ 
+ #define bfin_read_DMA9_NEXT_DESC_PTR() 		bfin_read32(DMA9_NEXT_DESC_PTR)
+-#define bfin_write_DMA9_NEXT_DESC_PTR(val) 	bfin_write32(DMA9_NEXT_DESC_PTR)
++#define bfin_write_DMA9_NEXT_DESC_PTR(val) 	bfin_write32(DMA9_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA9_START_ADDR() 		bfin_read32(DMA9_START_ADDR)
+-#define bfin_write_DMA9_START_ADDR(val) 	bfin_write32(DMA9_START_ADDR)
++#define bfin_write_DMA9_START_ADDR(val) 	bfin_write32(DMA9_START_ADDR, val)
+ #define bfin_read_DMA9_CONFIG()			bfin_read16(DMA9_CONFIG)
+ #define bfin_write_DMA9_CONFIG(val)		bfin_write16(DMA9_CONFIG, val)
+ #define bfin_read_DMA9_X_COUNT()		bfin_read16(DMA9_X_COUNT)
+ #define bfin_write_DMA9_X_COUNT(val)		bfin_write16(DMA9_X_COUNT, val)
+ #define bfin_read_DMA9_X_MODIFY()		bfin_read16(DMA9_X_MODIFY)
+-#define bfin_write_DMA9_X_MODIFY(val) 		bfin_write16(DMA9_X_MODIFY)
++#define bfin_write_DMA9_X_MODIFY(val) 		bfin_write16(DMA9_X_MODIFY, val)
+ #define bfin_read_DMA9_Y_COUNT()		bfin_read16(DMA9_Y_COUNT)
+ #define bfin_write_DMA9_Y_COUNT(val)		bfin_write16(DMA9_Y_COUNT, val)
+ #define bfin_read_DMA9_Y_MODIFY()		bfin_read16(DMA9_Y_MODIFY)
+-#define bfin_write_DMA9_Y_MODIFY(val) 		bfin_write16(DMA9_Y_MODIFY)
++#define bfin_write_DMA9_Y_MODIFY(val) 		bfin_write16(DMA9_Y_MODIFY, val)
+ #define bfin_read_DMA9_CURR_DESC_PTR() 		bfin_read32(DMA9_CURR_DESC_PTR)
+-#define bfin_write_DMA9_CURR_DESC_PTR(val) 	bfin_write32(DMA9_CURR_DESC_PTR)
++#define bfin_write_DMA9_CURR_DESC_PTR(val) 	bfin_write32(DMA9_CURR_DESC_PTR, val)
+ #define bfin_read_DMA9_CURR_ADDR() 		bfin_read32(DMA9_CURR_ADDR)
+-#define bfin_write_DMA9_CURR_ADDR(val) 		bfin_write32(DMA9_CURR_ADDR)
++#define bfin_write_DMA9_CURR_ADDR(val) 		bfin_write32(DMA9_CURR_ADDR, val)
+ #define bfin_read_DMA9_IRQ_STATUS()		bfin_read16(DMA9_IRQ_STATUS)
+ #define bfin_write_DMA9_IRQ_STATUS(val)		bfin_write16(DMA9_IRQ_STATUS, val)
+ #define bfin_read_DMA9_PERIPHERAL_MAP()		bfin_read16(DMA9_PERIPHERAL_MAP)
+@@ -682,23 +678,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 10 Registers */
+ 
+ #define bfin_read_DMA10_NEXT_DESC_PTR() 	bfin_read32(DMA10_NEXT_DESC_PTR)
+-#define bfin_write_DMA10_NEXT_DESC_PTR(val) 	bfin_write32(DMA10_NEXT_DESC_PTR)
++#define bfin_write_DMA10_NEXT_DESC_PTR(val) 	bfin_write32(DMA10_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA10_START_ADDR() 		bfin_read32(DMA10_START_ADDR)
+-#define bfin_write_DMA10_START_ADDR(val) 	bfin_write32(DMA10_START_ADDR)
++#define bfin_write_DMA10_START_ADDR(val) 	bfin_write32(DMA10_START_ADDR, val)
+ #define bfin_read_DMA10_CONFIG()		bfin_read16(DMA10_CONFIG)
+ #define bfin_write_DMA10_CONFIG(val)		bfin_write16(DMA10_CONFIG, val)
+ #define bfin_read_DMA10_X_COUNT()		bfin_read16(DMA10_X_COUNT)
+ #define bfin_write_DMA10_X_COUNT(val)		bfin_write16(DMA10_X_COUNT, val)
+ #define bfin_read_DMA10_X_MODIFY()		bfin_read16(DMA10_X_MODIFY)
+-#define bfin_write_DMA10_X_MODIFY(val) 		bfin_write16(DMA10_X_MODIFY)
++#define bfin_write_DMA10_X_MODIFY(val) 		bfin_write16(DMA10_X_MODIFY, val)
+ #define bfin_read_DMA10_Y_COUNT()		bfin_read16(DMA10_Y_COUNT)
+ #define bfin_write_DMA10_Y_COUNT(val)		bfin_write16(DMA10_Y_COUNT, val)
+ #define bfin_read_DMA10_Y_MODIFY()		bfin_read16(DMA10_Y_MODIFY)
+-#define bfin_write_DMA10_Y_MODIFY(val) 		bfin_write16(DMA10_Y_MODIFY)
++#define bfin_write_DMA10_Y_MODIFY(val) 		bfin_write16(DMA10_Y_MODIFY, val)
+ #define bfin_read_DMA10_CURR_DESC_PTR() 	bfin_read32(DMA10_CURR_DESC_PTR)
+-#define bfin_write_DMA10_CURR_DESC_PTR(val) 	bfin_write32(DMA10_CURR_DESC_PTR)
++#define bfin_write_DMA10_CURR_DESC_PTR(val) 	bfin_write32(DMA10_CURR_DESC_PTR, val)
+ #define bfin_read_DMA10_CURR_ADDR() 		bfin_read32(DMA10_CURR_ADDR)
+-#define bfin_write_DMA10_CURR_ADDR(val) 	bfin_write32(DMA10_CURR_ADDR)
++#define bfin_write_DMA10_CURR_ADDR(val) 	bfin_write32(DMA10_CURR_ADDR, val)
+ #define bfin_read_DMA10_IRQ_STATUS()		bfin_read16(DMA10_IRQ_STATUS)
+ #define bfin_write_DMA10_IRQ_STATUS(val)	bfin_write16(DMA10_IRQ_STATUS, val)
+ #define bfin_read_DMA10_PERIPHERAL_MAP()	bfin_read16(DMA10_PERIPHERAL_MAP)
+@@ -711,23 +707,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 11 Registers */
+ 
+ #define bfin_read_DMA11_NEXT_DESC_PTR() 	bfin_read32(DMA11_NEXT_DESC_PTR)
+-#define bfin_write_DMA11_NEXT_DESC_PTR(val) 	bfin_write32(DMA11_NEXT_DESC_PTR)
++#define bfin_write_DMA11_NEXT_DESC_PTR(val) 	bfin_write32(DMA11_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA11_START_ADDR() 		bfin_read32(DMA11_START_ADDR)
+-#define bfin_write_DMA11_START_ADDR(val) 	bfin_write32(DMA11_START_ADDR)
++#define bfin_write_DMA11_START_ADDR(val) 	bfin_write32(DMA11_START_ADDR, val)
+ #define bfin_read_DMA11_CONFIG()		bfin_read16(DMA11_CONFIG)
+ #define bfin_write_DMA11_CONFIG(val)		bfin_write16(DMA11_CONFIG, val)
+ #define bfin_read_DMA11_X_COUNT()		bfin_read16(DMA11_X_COUNT)
+ #define bfin_write_DMA11_X_COUNT(val)		bfin_write16(DMA11_X_COUNT, val)
+ #define bfin_read_DMA11_X_MODIFY()		bfin_read16(DMA11_X_MODIFY)
+-#define bfin_write_DMA11_X_MODIFY(val) 		bfin_write16(DMA11_X_MODIFY)
++#define bfin_write_DMA11_X_MODIFY(val) 		bfin_write16(DMA11_X_MODIFY, val)
+ #define bfin_read_DMA11_Y_COUNT()		bfin_read16(DMA11_Y_COUNT)
+ #define bfin_write_DMA11_Y_COUNT(val)		bfin_write16(DMA11_Y_COUNT, val)
+ #define bfin_read_DMA11_Y_MODIFY()		bfin_read16(DMA11_Y_MODIFY)
+-#define bfin_write_DMA11_Y_MODIFY(val) 		bfin_write16(DMA11_Y_MODIFY)
++#define bfin_write_DMA11_Y_MODIFY(val) 		bfin_write16(DMA11_Y_MODIFY, val)
+ #define bfin_read_DMA11_CURR_DESC_PTR() 	bfin_read32(DMA11_CURR_DESC_PTR)
+-#define bfin_write_DMA11_CURR_DESC_PTR(val) 	bfin_write32(DMA11_CURR_DESC_PTR)
++#define bfin_write_DMA11_CURR_DESC_PTR(val) 	bfin_write32(DMA11_CURR_DESC_PTR, val)
+ #define bfin_read_DMA11_CURR_ADDR() 		bfin_read32(DMA11_CURR_ADDR)
+-#define bfin_write_DMA11_CURR_ADDR(val) 	bfin_write32(DMA11_CURR_ADDR)
++#define bfin_write_DMA11_CURR_ADDR(val) 	bfin_write32(DMA11_CURR_ADDR, val)
+ #define bfin_read_DMA11_IRQ_STATUS()		bfin_read16(DMA11_IRQ_STATUS)
+ #define bfin_write_DMA11_IRQ_STATUS(val)	bfin_write16(DMA11_IRQ_STATUS, val)
+ #define bfin_read_DMA11_PERIPHERAL_MAP()	bfin_read16(DMA11_PERIPHERAL_MAP)
+@@ -740,7 +736,7 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* MDMA Stream 0 Registers */
+ 
+ #define bfin_read_MDMA_D0_NEXT_DESC_PTR() 	bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) 	bfin_write32(MDMA_D0_NEXT_DESC_PTR)
++#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) 	bfin_write32(MDMA_D0_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_D0_START_ADDR() 		bfin_read32(MDMA_D0_START_ADDR)
+ #define bfin_write_MDMA_D0_START_ADDR(val) 	bfin_write32(MDMA_D0_START_ADDR, val)
+ #define bfin_read_MDMA_D0_CONFIG()		bfin_read16(MDMA_D0_CONFIG)
+@@ -803,11 +799,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_MDMA_D1_X_COUNT()		bfin_read16(MDMA_D1_X_COUNT)
+ #define bfin_write_MDMA_D1_X_COUNT(val)		bfin_write16(MDMA_D1_X_COUNT, val)
+ #define bfin_read_MDMA_D1_X_MODIFY()		bfin_read16(MDMA_D1_X_MODIFY)
+-#define bfin_write_MDMA_D1_X_MODIFY(val) 	bfin_write16(MDMA_D1_X_MODIFY)
++#define bfin_write_MDMA_D1_X_MODIFY(val) 	bfin_write16(MDMA_D1_X_MODIFY, val)
+ #define bfin_read_MDMA_D1_Y_COUNT()		bfin_read16(MDMA_D1_Y_COUNT)
+ #define bfin_write_MDMA_D1_Y_COUNT(val)		bfin_write16(MDMA_D1_Y_COUNT, val)
+ #define bfin_read_MDMA_D1_Y_MODIFY()		bfin_read16(MDMA_D1_Y_MODIFY)
+-#define bfin_write_MDMA_D1_Y_MODIFY(val) 	bfin_write16(MDMA_D1_Y_MODIFY)
++#define bfin_write_MDMA_D1_Y_MODIFY(val) 	bfin_write16(MDMA_D1_Y_MODIFY, val)
+ #define bfin_read_MDMA_D1_CURR_DESC_PTR() 	bfin_read32(MDMA_D1_CURR_DESC_PTR)
+ #define bfin_write_MDMA_D1_CURR_DESC_PTR(val) 	bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_D1_CURR_ADDR() 		bfin_read32(MDMA_D1_CURR_ADDR)
+@@ -829,11 +825,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_MDMA_S1_X_COUNT()		bfin_read16(MDMA_S1_X_COUNT)
+ #define bfin_write_MDMA_S1_X_COUNT(val)		bfin_write16(MDMA_S1_X_COUNT, val)
+ #define bfin_read_MDMA_S1_X_MODIFY()		bfin_read16(MDMA_S1_X_MODIFY)
+-#define bfin_write_MDMA_S1_X_MODIFY(val) 	bfin_write16(MDMA_S1_X_MODIFY)
++#define bfin_write_MDMA_S1_X_MODIFY(val) 	bfin_write16(MDMA_S1_X_MODIFY, val)
+ #define bfin_read_MDMA_S1_Y_COUNT()		bfin_read16(MDMA_S1_Y_COUNT)
+ #define bfin_write_MDMA_S1_Y_COUNT(val)		bfin_write16(MDMA_S1_Y_COUNT, val)
+ #define bfin_read_MDMA_S1_Y_MODIFY()		bfin_read16(MDMA_S1_Y_MODIFY)
+-#define bfin_write_MDMA_S1_Y_MODIFY(val) 	bfin_write16(MDMA_S1_Y_MODIFY)
++#define bfin_write_MDMA_S1_Y_MODIFY(val) 	bfin_write16(MDMA_S1_Y_MODIFY, val)
+ #define bfin_read_MDMA_S1_CURR_DESC_PTR() 	bfin_read32(MDMA_S1_CURR_DESC_PTR)
+ #define bfin_write_MDMA_S1_CURR_DESC_PTR(val) 	bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_S1_CURR_ADDR() 		bfin_read32(MDMA_S1_CURR_ADDR)
+@@ -1246,23 +1242,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 12 Registers */
+ 
+ #define bfin_read_DMA12_NEXT_DESC_PTR() 	bfin_read32(DMA12_NEXT_DESC_PTR)
+-#define bfin_write_DMA12_NEXT_DESC_PTR(val) 	bfin_write32(DMA12_NEXT_DESC_PTR)
++#define bfin_write_DMA12_NEXT_DESC_PTR(val) 	bfin_write32(DMA12_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA12_START_ADDR() 		bfin_read32(DMA12_START_ADDR)
+-#define bfin_write_DMA12_START_ADDR(val) 	bfin_write32(DMA12_START_ADDR)
++#define bfin_write_DMA12_START_ADDR(val) 	bfin_write32(DMA12_START_ADDR, val)
+ #define bfin_read_DMA12_CONFIG()		bfin_read16(DMA12_CONFIG)
+ #define bfin_write_DMA12_CONFIG(val)		bfin_write16(DMA12_CONFIG, val)
+ #define bfin_read_DMA12_X_COUNT()		bfin_read16(DMA12_X_COUNT)
+ #define bfin_write_DMA12_X_COUNT(val)		bfin_write16(DMA12_X_COUNT, val)
+ #define bfin_read_DMA12_X_MODIFY()		bfin_read16(DMA12_X_MODIFY)
+-#define bfin_write_DMA12_X_MODIFY(val) 		bfin_write16(DMA12_X_MODIFY)
++#define bfin_write_DMA12_X_MODIFY(val) 		bfin_write16(DMA12_X_MODIFY, val)
+ #define bfin_read_DMA12_Y_COUNT()		bfin_read16(DMA12_Y_COUNT)
+ #define bfin_write_DMA12_Y_COUNT(val)		bfin_write16(DMA12_Y_COUNT, val)
+ #define bfin_read_DMA12_Y_MODIFY()		bfin_read16(DMA12_Y_MODIFY)
+-#define bfin_write_DMA12_Y_MODIFY(val) 		bfin_write16(DMA12_Y_MODIFY)
++#define bfin_write_DMA12_Y_MODIFY(val) 		bfin_write16(DMA12_Y_MODIFY, val)
+ #define bfin_read_DMA12_CURR_DESC_PTR() 	bfin_read32(DMA12_CURR_DESC_PTR)
+-#define bfin_write_DMA12_CURR_DESC_PTR(val) 	bfin_write32(DMA12_CURR_DESC_PTR)
++#define bfin_write_DMA12_CURR_DESC_PTR(val) 	bfin_write32(DMA12_CURR_DESC_PTR, val)
+ #define bfin_read_DMA12_CURR_ADDR() 		bfin_read32(DMA12_CURR_ADDR)
+-#define bfin_write_DMA12_CURR_ADDR(val) 	bfin_write32(DMA12_CURR_ADDR)
++#define bfin_write_DMA12_CURR_ADDR(val) 	bfin_write32(DMA12_CURR_ADDR, val)
+ #define bfin_read_DMA12_IRQ_STATUS()		bfin_read16(DMA12_IRQ_STATUS)
+ #define bfin_write_DMA12_IRQ_STATUS(val)	bfin_write16(DMA12_IRQ_STATUS, val)
+ #define bfin_read_DMA12_PERIPHERAL_MAP()	bfin_read16(DMA12_PERIPHERAL_MAP)
+@@ -1275,23 +1271,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 13 Registers */
+ 
+ #define bfin_read_DMA13_NEXT_DESC_PTR() 	bfin_read32(DMA13_NEXT_DESC_PTR)
+-#define bfin_write_DMA13_NEXT_DESC_PTR(val) 	bfin_write32(DMA13_NEXT_DESC_PTR)
++#define bfin_write_DMA13_NEXT_DESC_PTR(val) 	bfin_write32(DMA13_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA13_START_ADDR() 		bfin_read32(DMA13_START_ADDR)
+-#define bfin_write_DMA13_START_ADDR(val) 	bfin_write32(DMA13_START_ADDR)
++#define bfin_write_DMA13_START_ADDR(val) 	bfin_write32(DMA13_START_ADDR, val)
+ #define bfin_read_DMA13_CONFIG()		bfin_read16(DMA13_CONFIG)
+ #define bfin_write_DMA13_CONFIG(val)		bfin_write16(DMA13_CONFIG, val)
+ #define bfin_read_DMA13_X_COUNT()		bfin_read16(DMA13_X_COUNT)
+ #define bfin_write_DMA13_X_COUNT(val)		bfin_write16(DMA13_X_COUNT, val)
+ #define bfin_read_DMA13_X_MODIFY()		bfin_read16(DMA13_X_MODIFY)
+-#define bfin_write_DMA13_X_MODIFY(val) 		bfin_write16(DMA13_X_MODIFY)
++#define bfin_write_DMA13_X_MODIFY(val) 		bfin_write16(DMA13_X_MODIFY, val)
+ #define bfin_read_DMA13_Y_COUNT()		bfin_read16(DMA13_Y_COUNT)
+ #define bfin_write_DMA13_Y_COUNT(val)		bfin_write16(DMA13_Y_COUNT, val)
+ #define bfin_read_DMA13_Y_MODIFY()		bfin_read16(DMA13_Y_MODIFY)
+-#define bfin_write_DMA13_Y_MODIFY(val) 		bfin_write16(DMA13_Y_MODIFY)
++#define bfin_write_DMA13_Y_MODIFY(val) 		bfin_write16(DMA13_Y_MODIFY, val)
+ #define bfin_read_DMA13_CURR_DESC_PTR() 	bfin_read32(DMA13_CURR_DESC_PTR)
+-#define bfin_write_DMA13_CURR_DESC_PTR(val) 	bfin_write32(DMA13_CURR_DESC_PTR)
++#define bfin_write_DMA13_CURR_DESC_PTR(val) 	bfin_write32(DMA13_CURR_DESC_PTR, val)
+ #define bfin_read_DMA13_CURR_ADDR() 		bfin_read32(DMA13_CURR_ADDR)
+-#define bfin_write_DMA13_CURR_ADDR(val) 	bfin_write32(DMA13_CURR_ADDR)
++#define bfin_write_DMA13_CURR_ADDR(val) 	bfin_write32(DMA13_CURR_ADDR, val)
+ #define bfin_read_DMA13_IRQ_STATUS()		bfin_read16(DMA13_IRQ_STATUS)
+ #define bfin_write_DMA13_IRQ_STATUS(val)	bfin_write16(DMA13_IRQ_STATUS, val)
+ #define bfin_read_DMA13_PERIPHERAL_MAP()	bfin_read16(DMA13_PERIPHERAL_MAP)
+@@ -1304,23 +1300,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 14 Registers */
+ 
+ #define bfin_read_DMA14_NEXT_DESC_PTR() 	bfin_read32(DMA14_NEXT_DESC_PTR)
+-#define bfin_write_DMA14_NEXT_DESC_PTR(val) 	bfin_write32(DMA14_NEXT_DESC_PTR)
++#define bfin_write_DMA14_NEXT_DESC_PTR(val) 	bfin_write32(DMA14_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA14_START_ADDR() 		bfin_read32(DMA14_START_ADDR)
+-#define bfin_write_DMA14_START_ADDR(val) 	bfin_write32(DMA14_START_ADDR)
++#define bfin_write_DMA14_START_ADDR(val) 	bfin_write32(DMA14_START_ADDR, val)
+ #define bfin_read_DMA14_CONFIG()		bfin_read16(DMA14_CONFIG)
+ #define bfin_write_DMA14_CONFIG(val)		bfin_write16(DMA14_CONFIG, val)
+ #define bfin_read_DMA14_X_COUNT()		bfin_read16(DMA14_X_COUNT)
+ #define bfin_write_DMA14_X_COUNT(val)		bfin_write16(DMA14_X_COUNT, val)
+ #define bfin_read_DMA14_X_MODIFY()		bfin_read16(DMA14_X_MODIFY)
+-#define bfin_write_DMA14_X_MODIFY(val) 		bfin_write16(DMA14_X_MODIFY)
++#define bfin_write_DMA14_X_MODIFY(val) 		bfin_write16(DMA14_X_MODIFY, val)
+ #define bfin_read_DMA14_Y_COUNT()		bfin_read16(DMA14_Y_COUNT)
+ #define bfin_write_DMA14_Y_COUNT(val)		bfin_write16(DMA14_Y_COUNT, val)
+ #define bfin_read_DMA14_Y_MODIFY()		bfin_read16(DMA14_Y_MODIFY)
+-#define bfin_write_DMA14_Y_MODIFY(val) 		bfin_write16(DMA14_Y_MODIFY)
++#define bfin_write_DMA14_Y_MODIFY(val) 		bfin_write16(DMA14_Y_MODIFY, val)
+ #define bfin_read_DMA14_CURR_DESC_PTR() 	bfin_read32(DMA14_CURR_DESC_PTR)
+-#define bfin_write_DMA14_CURR_DESC_PTR(val) 	bfin_write32(DMA14_CURR_DESC_PTR)
++#define bfin_write_DMA14_CURR_DESC_PTR(val) 	bfin_write32(DMA14_CURR_DESC_PTR, val)
+ #define bfin_read_DMA14_CURR_ADDR() 		bfin_read32(DMA14_CURR_ADDR)
+-#define bfin_write_DMA14_CURR_ADDR(val) 	bfin_write32(DMA14_CURR_ADDR)
++#define bfin_write_DMA14_CURR_ADDR(val) 	bfin_write32(DMA14_CURR_ADDR, val)
+ #define bfin_read_DMA14_IRQ_STATUS()		bfin_read16(DMA14_IRQ_STATUS)
+ #define bfin_write_DMA14_IRQ_STATUS(val)	bfin_write16(DMA14_IRQ_STATUS, val)
+ #define bfin_read_DMA14_PERIPHERAL_MAP()	bfin_read16(DMA14_PERIPHERAL_MAP)
+@@ -1333,23 +1329,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 15 Registers */
+ 
+ #define bfin_read_DMA15_NEXT_DESC_PTR() 	bfin_read32(DMA15_NEXT_DESC_PTR)
+-#define bfin_write_DMA15_NEXT_DESC_PTR(val) 	bfin_write32(DMA15_NEXT_DESC_PTR)
++#define bfin_write_DMA15_NEXT_DESC_PTR(val) 	bfin_write32(DMA15_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA15_START_ADDR() 		bfin_read32(DMA15_START_ADDR)
+-#define bfin_write_DMA15_START_ADDR(val) 	bfin_write32(DMA15_START_ADDR)
++#define bfin_write_DMA15_START_ADDR(val) 	bfin_write32(DMA15_START_ADDR, val)
+ #define bfin_read_DMA15_CONFIG()		bfin_read16(DMA15_CONFIG)
+ #define bfin_write_DMA15_CONFIG(val)		bfin_write16(DMA15_CONFIG, val)
+ #define bfin_read_DMA15_X_COUNT()		bfin_read16(DMA15_X_COUNT)
+ #define bfin_write_DMA15_X_COUNT(val)		bfin_write16(DMA15_X_COUNT, val)
+ #define bfin_read_DMA15_X_MODIFY()		bfin_read16(DMA15_X_MODIFY)
+-#define bfin_write_DMA15_X_MODIFY(val) 		bfin_write16(DMA15_X_MODIFY)
++#define bfin_write_DMA15_X_MODIFY(val) 		bfin_write16(DMA15_X_MODIFY, val)
+ #define bfin_read_DMA15_Y_COUNT()		bfin_read16(DMA15_Y_COUNT)
+ #define bfin_write_DMA15_Y_COUNT(val)		bfin_write16(DMA15_Y_COUNT, val)
+ #define bfin_read_DMA15_Y_MODIFY()		bfin_read16(DMA15_Y_MODIFY)
+-#define bfin_write_DMA15_Y_MODIFY(val) 		bfin_write16(DMA15_Y_MODIFY)
++#define bfin_write_DMA15_Y_MODIFY(val) 		bfin_write16(DMA15_Y_MODIFY, val)
+ #define bfin_read_DMA15_CURR_DESC_PTR() 	bfin_read32(DMA15_CURR_DESC_PTR)
+-#define bfin_write_DMA15_CURR_DESC_PTR(val) 	bfin_write32(DMA15_CURR_DESC_PTR)
++#define bfin_write_DMA15_CURR_DESC_PTR(val) 	bfin_write32(DMA15_CURR_DESC_PTR, val)
+ #define bfin_read_DMA15_CURR_ADDR() 		bfin_read32(DMA15_CURR_ADDR)
+-#define bfin_write_DMA15_CURR_ADDR(val) 	bfin_write32(DMA15_CURR_ADDR)
++#define bfin_write_DMA15_CURR_ADDR(val) 	bfin_write32(DMA15_CURR_ADDR, val)
+ #define bfin_read_DMA15_IRQ_STATUS()		bfin_read16(DMA15_IRQ_STATUS)
+ #define bfin_write_DMA15_IRQ_STATUS(val)	bfin_write16(DMA15_IRQ_STATUS, val)
+ #define bfin_read_DMA15_PERIPHERAL_MAP()	bfin_read16(DMA15_PERIPHERAL_MAP)
+@@ -1362,23 +1358,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 16 Registers */
+ 
+ #define bfin_read_DMA16_NEXT_DESC_PTR() 	bfin_read32(DMA16_NEXT_DESC_PTR)
+-#define bfin_write_DMA16_NEXT_DESC_PTR(val) 	bfin_write32(DMA16_NEXT_DESC_PTR)
++#define bfin_write_DMA16_NEXT_DESC_PTR(val) 	bfin_write32(DMA16_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA16_START_ADDR() 		bfin_read32(DMA16_START_ADDR)
+-#define bfin_write_DMA16_START_ADDR(val) 	bfin_write32(DMA16_START_ADDR)
++#define bfin_write_DMA16_START_ADDR(val) 	bfin_write32(DMA16_START_ADDR, val)
+ #define bfin_read_DMA16_CONFIG()		bfin_read16(DMA16_CONFIG)
+ #define bfin_write_DMA16_CONFIG(val)		bfin_write16(DMA16_CONFIG, val)
+ #define bfin_read_DMA16_X_COUNT()		bfin_read16(DMA16_X_COUNT)
+ #define bfin_write_DMA16_X_COUNT(val)		bfin_write16(DMA16_X_COUNT, val)
+ #define bfin_read_DMA16_X_MODIFY()		bfin_read16(DMA16_X_MODIFY)
+-#define bfin_write_DMA16_X_MODIFY(val) 		bfin_write16(DMA16_X_MODIFY)
++#define bfin_write_DMA16_X_MODIFY(val) 		bfin_write16(DMA16_X_MODIFY, val)
+ #define bfin_read_DMA16_Y_COUNT()		bfin_read16(DMA16_Y_COUNT)
+ #define bfin_write_DMA16_Y_COUNT(val)		bfin_write16(DMA16_Y_COUNT, val)
+ #define bfin_read_DMA16_Y_MODIFY()		bfin_read16(DMA16_Y_MODIFY)
+-#define bfin_write_DMA16_Y_MODIFY(val) 		bfin_write16(DMA16_Y_MODIFY)
++#define bfin_write_DMA16_Y_MODIFY(val) 		bfin_write16(DMA16_Y_MODIFY, val)
+ #define bfin_read_DMA16_CURR_DESC_PTR() 	bfin_read32(DMA16_CURR_DESC_PTR)
+-#define bfin_write_DMA16_CURR_DESC_PTR(val) 	bfin_write32(DMA16_CURR_DESC_PTR)
++#define bfin_write_DMA16_CURR_DESC_PTR(val) 	bfin_write32(DMA16_CURR_DESC_PTR, val)
+ #define bfin_read_DMA16_CURR_ADDR() 		bfin_read32(DMA16_CURR_ADDR)
+-#define bfin_write_DMA16_CURR_ADDR(val) 	bfin_write32(DMA16_CURR_ADDR)
++#define bfin_write_DMA16_CURR_ADDR(val) 	bfin_write32(DMA16_CURR_ADDR, val)
+ #define bfin_read_DMA16_IRQ_STATUS()		bfin_read16(DMA16_IRQ_STATUS)
+ #define bfin_write_DMA16_IRQ_STATUS(val)	bfin_write16(DMA16_IRQ_STATUS, val)
+ #define bfin_read_DMA16_PERIPHERAL_MAP()	bfin_read16(DMA16_PERIPHERAL_MAP)
+@@ -1391,23 +1387,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 17 Registers */
+ 
+ #define bfin_read_DMA17_NEXT_DESC_PTR() 	bfin_read32(DMA17_NEXT_DESC_PTR)
+-#define bfin_write_DMA17_NEXT_DESC_PTR(val) 	bfin_write32(DMA17_NEXT_DESC_PTR)
++#define bfin_write_DMA17_NEXT_DESC_PTR(val) 	bfin_write32(DMA17_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA17_START_ADDR() 		bfin_read32(DMA17_START_ADDR)
+-#define bfin_write_DMA17_START_ADDR(val) 	bfin_write32(DMA17_START_ADDR)
++#define bfin_write_DMA17_START_ADDR(val) 	bfin_write32(DMA17_START_ADDR, val)
+ #define bfin_read_DMA17_CONFIG()		bfin_read16(DMA17_CONFIG)
+ #define bfin_write_DMA17_CONFIG(val)		bfin_write16(DMA17_CONFIG, val)
+ #define bfin_read_DMA17_X_COUNT()		bfin_read16(DMA17_X_COUNT)
+ #define bfin_write_DMA17_X_COUNT(val)		bfin_write16(DMA17_X_COUNT, val)
+ #define bfin_read_DMA17_X_MODIFY()		bfin_read16(DMA17_X_MODIFY)
+-#define bfin_write_DMA17_X_MODIFY(val) 		bfin_write16(DMA17_X_MODIFY)
++#define bfin_write_DMA17_X_MODIFY(val) 		bfin_write16(DMA17_X_MODIFY, val)
+ #define bfin_read_DMA17_Y_COUNT()		bfin_read16(DMA17_Y_COUNT)
+ #define bfin_write_DMA17_Y_COUNT(val)		bfin_write16(DMA17_Y_COUNT, val)
+ #define bfin_read_DMA17_Y_MODIFY()		bfin_read16(DMA17_Y_MODIFY)
+-#define bfin_write_DMA17_Y_MODIFY(val) 		bfin_write16(DMA17_Y_MODIFY)
++#define bfin_write_DMA17_Y_MODIFY(val) 		bfin_write16(DMA17_Y_MODIFY, val)
+ #define bfin_read_DMA17_CURR_DESC_PTR() 	bfin_read32(DMA17_CURR_DESC_PTR)
+-#define bfin_write_DMA17_CURR_DESC_PTR(val) 	bfin_write32(DMA17_CURR_DESC_PTR)
++#define bfin_write_DMA17_CURR_DESC_PTR(val) 	bfin_write32(DMA17_CURR_DESC_PTR, val)
+ #define bfin_read_DMA17_CURR_ADDR() 		bfin_read32(DMA17_CURR_ADDR)
+-#define bfin_write_DMA17_CURR_ADDR(val) 	bfin_write32(DMA17_CURR_ADDR)
++#define bfin_write_DMA17_CURR_ADDR(val) 	bfin_write32(DMA17_CURR_ADDR, val)
+ #define bfin_read_DMA17_IRQ_STATUS()		bfin_read16(DMA17_IRQ_STATUS)
+ #define bfin_write_DMA17_IRQ_STATUS(val)	bfin_write16(DMA17_IRQ_STATUS, val)
+ #define bfin_read_DMA17_PERIPHERAL_MAP()	bfin_read16(DMA17_PERIPHERAL_MAP)
+@@ -1420,23 +1416,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 18 Registers */
+ 
+ #define bfin_read_DMA18_NEXT_DESC_PTR() 	bfin_read32(DMA18_NEXT_DESC_PTR)
+-#define bfin_write_DMA18_NEXT_DESC_PTR(val) 	bfin_write32(DMA18_NEXT_DESC_PTR)
++#define bfin_write_DMA18_NEXT_DESC_PTR(val) 	bfin_write32(DMA18_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA18_START_ADDR() 		bfin_read32(DMA18_START_ADDR)
+-#define bfin_write_DMA18_START_ADDR(val) 	bfin_write32(DMA18_START_ADDR)
++#define bfin_write_DMA18_START_ADDR(val) 	bfin_write32(DMA18_START_ADDR, val)
+ #define bfin_read_DMA18_CONFIG()		bfin_read16(DMA18_CONFIG)
+ #define bfin_write_DMA18_CONFIG(val)		bfin_write16(DMA18_CONFIG, val)
+ #define bfin_read_DMA18_X_COUNT()		bfin_read16(DMA18_X_COUNT)
+ #define bfin_write_DMA18_X_COUNT(val)		bfin_write16(DMA18_X_COUNT, val)
+ #define bfin_read_DMA18_X_MODIFY()		bfin_read16(DMA18_X_MODIFY)
+-#define bfin_write_DMA18_X_MODIFY(val) 		bfin_write16(DMA18_X_MODIFY)
++#define bfin_write_DMA18_X_MODIFY(val) 		bfin_write16(DMA18_X_MODIFY, val)
+ #define bfin_read_DMA18_Y_COUNT()		bfin_read16(DMA18_Y_COUNT)
+ #define bfin_write_DMA18_Y_COUNT(val)		bfin_write16(DMA18_Y_COUNT, val)
+ #define bfin_read_DMA18_Y_MODIFY()		bfin_read16(DMA18_Y_MODIFY)
+-#define bfin_write_DMA18_Y_MODIFY(val) 		bfin_write16(DMA18_Y_MODIFY)
++#define bfin_write_DMA18_Y_MODIFY(val) 		bfin_write16(DMA18_Y_MODIFY, val)
+ #define bfin_read_DMA18_CURR_DESC_PTR() 	bfin_read32(DMA18_CURR_DESC_PTR)
+-#define bfin_write_DMA18_CURR_DESC_PTR(val) 	bfin_write32(DMA18_CURR_DESC_PTR)
++#define bfin_write_DMA18_CURR_DESC_PTR(val) 	bfin_write32(DMA18_CURR_DESC_PTR, val)
+ #define bfin_read_DMA18_CURR_ADDR() 		bfin_read32(DMA18_CURR_ADDR)
+-#define bfin_write_DMA18_CURR_ADDR(val) 	bfin_write32(DMA18_CURR_ADDR)
++#define bfin_write_DMA18_CURR_ADDR(val) 	bfin_write32(DMA18_CURR_ADDR, val)
+ #define bfin_read_DMA18_IRQ_STATUS()		bfin_read16(DMA18_IRQ_STATUS)
+ #define bfin_write_DMA18_IRQ_STATUS(val)	bfin_write16(DMA18_IRQ_STATUS, val)
+ #define bfin_read_DMA18_PERIPHERAL_MAP()	bfin_read16(DMA18_PERIPHERAL_MAP)
+@@ -1449,23 +1445,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 19 Registers */
+ 
+ #define bfin_read_DMA19_NEXT_DESC_PTR() 	bfin_read32(DMA19_NEXT_DESC_PTR)
+-#define bfin_write_DMA19_NEXT_DESC_PTR(val) 	bfin_write32(DMA19_NEXT_DESC_PTR)
++#define bfin_write_DMA19_NEXT_DESC_PTR(val) 	bfin_write32(DMA19_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA19_START_ADDR() 		bfin_read32(DMA19_START_ADDR)
+-#define bfin_write_DMA19_START_ADDR(val) 	bfin_write32(DMA19_START_ADDR)
++#define bfin_write_DMA19_START_ADDR(val) 	bfin_write32(DMA19_START_ADDR, val)
+ #define bfin_read_DMA19_CONFIG()		bfin_read16(DMA19_CONFIG)
+ #define bfin_write_DMA19_CONFIG(val)		bfin_write16(DMA19_CONFIG, val)
+ #define bfin_read_DMA19_X_COUNT()		bfin_read16(DMA19_X_COUNT)
+ #define bfin_write_DMA19_X_COUNT(val)		bfin_write16(DMA19_X_COUNT, val)
+ #define bfin_read_DMA19_X_MODIFY()		bfin_read16(DMA19_X_MODIFY)
+-#define bfin_write_DMA19_X_MODIFY(val) 		bfin_write16(DMA19_X_MODIFY)
++#define bfin_write_DMA19_X_MODIFY(val) 		bfin_write16(DMA19_X_MODIFY, val)
+ #define bfin_read_DMA19_Y_COUNT()		bfin_read16(DMA19_Y_COUNT)
+ #define bfin_write_DMA19_Y_COUNT(val)		bfin_write16(DMA19_Y_COUNT, val)
+ #define bfin_read_DMA19_Y_MODIFY()		bfin_read16(DMA19_Y_MODIFY)
+-#define bfin_write_DMA19_Y_MODIFY(val) 		bfin_write16(DMA19_Y_MODIFY)
++#define bfin_write_DMA19_Y_MODIFY(val) 		bfin_write16(DMA19_Y_MODIFY, val)
+ #define bfin_read_DMA19_CURR_DESC_PTR() 	bfin_read32(DMA19_CURR_DESC_PTR)
+-#define bfin_write_DMA19_CURR_DESC_PTR(val) 	bfin_write32(DMA19_CURR_DESC_PTR)
++#define bfin_write_DMA19_CURR_DESC_PTR(val) 	bfin_write32(DMA19_CURR_DESC_PTR, val)
+ #define bfin_read_DMA19_CURR_ADDR() 		bfin_read32(DMA19_CURR_ADDR)
+-#define bfin_write_DMA19_CURR_ADDR(val) 	bfin_write32(DMA19_CURR_ADDR)
++#define bfin_write_DMA19_CURR_ADDR(val) 	bfin_write32(DMA19_CURR_ADDR, val)
+ #define bfin_read_DMA19_IRQ_STATUS()		bfin_read16(DMA19_IRQ_STATUS)
+ #define bfin_write_DMA19_IRQ_STATUS(val)	bfin_write16(DMA19_IRQ_STATUS, val)
+ #define bfin_read_DMA19_PERIPHERAL_MAP()	bfin_read16(DMA19_PERIPHERAL_MAP)
+@@ -1478,23 +1474,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 20 Registers */
+ 
+ #define bfin_read_DMA20_NEXT_DESC_PTR() 	bfin_read32(DMA20_NEXT_DESC_PTR)
+-#define bfin_write_DMA20_NEXT_DESC_PTR(val) 	bfin_write32(DMA20_NEXT_DESC_PTR)
++#define bfin_write_DMA20_NEXT_DESC_PTR(val) 	bfin_write32(DMA20_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA20_START_ADDR() 		bfin_read32(DMA20_START_ADDR)
+-#define bfin_write_DMA20_START_ADDR(val) 	bfin_write32(DMA20_START_ADDR)
++#define bfin_write_DMA20_START_ADDR(val) 	bfin_write32(DMA20_START_ADDR, val)
+ #define bfin_read_DMA20_CONFIG()		bfin_read16(DMA20_CONFIG)
+ #define bfin_write_DMA20_CONFIG(val)		bfin_write16(DMA20_CONFIG, val)
+ #define bfin_read_DMA20_X_COUNT()		bfin_read16(DMA20_X_COUNT)
+ #define bfin_write_DMA20_X_COUNT(val)		bfin_write16(DMA20_X_COUNT, val)
+ #define bfin_read_DMA20_X_MODIFY()		bfin_read16(DMA20_X_MODIFY)
+-#define bfin_write_DMA20_X_MODIFY(val) 		bfin_write16(DMA20_X_MODIFY)
++#define bfin_write_DMA20_X_MODIFY(val) 		bfin_write16(DMA20_X_MODIFY, val)
+ #define bfin_read_DMA20_Y_COUNT()		bfin_read16(DMA20_Y_COUNT)
+ #define bfin_write_DMA20_Y_COUNT(val)		bfin_write16(DMA20_Y_COUNT, val)
+ #define bfin_read_DMA20_Y_MODIFY()		bfin_read16(DMA20_Y_MODIFY)
+-#define bfin_write_DMA20_Y_MODIFY(val) 		bfin_write16(DMA20_Y_MODIFY)
++#define bfin_write_DMA20_Y_MODIFY(val) 		bfin_write16(DMA20_Y_MODIFY, val)
+ #define bfin_read_DMA20_CURR_DESC_PTR() 	bfin_read32(DMA20_CURR_DESC_PTR)
+-#define bfin_write_DMA20_CURR_DESC_PTR(val) 	bfin_write32(DMA20_CURR_DESC_PTR)
++#define bfin_write_DMA20_CURR_DESC_PTR(val) 	bfin_write32(DMA20_CURR_DESC_PTR, val)
+ #define bfin_read_DMA20_CURR_ADDR() 		bfin_read32(DMA20_CURR_ADDR)
+-#define bfin_write_DMA20_CURR_ADDR(val) 	bfin_write32(DMA20_CURR_ADDR)
++#define bfin_write_DMA20_CURR_ADDR(val) 	bfin_write32(DMA20_CURR_ADDR, val)
+ #define bfin_read_DMA20_IRQ_STATUS()		bfin_read16(DMA20_IRQ_STATUS)
+ #define bfin_write_DMA20_IRQ_STATUS(val)	bfin_write16(DMA20_IRQ_STATUS, val)
+ #define bfin_read_DMA20_PERIPHERAL_MAP()	bfin_read16(DMA20_PERIPHERAL_MAP)
+@@ -1507,23 +1503,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 21 Registers */
+ 
+ #define bfin_read_DMA21_NEXT_DESC_PTR() 	bfin_read32(DMA21_NEXT_DESC_PTR)
+-#define bfin_write_DMA21_NEXT_DESC_PTR(val) 	bfin_write32(DMA21_NEXT_DESC_PTR)
++#define bfin_write_DMA21_NEXT_DESC_PTR(val) 	bfin_write32(DMA21_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA21_START_ADDR() 		bfin_read32(DMA21_START_ADDR)
+-#define bfin_write_DMA21_START_ADDR(val) 	bfin_write32(DMA21_START_ADDR)
++#define bfin_write_DMA21_START_ADDR(val) 	bfin_write32(DMA21_START_ADDR, val)
+ #define bfin_read_DMA21_CONFIG()		bfin_read16(DMA21_CONFIG)
+ #define bfin_write_DMA21_CONFIG(val)		bfin_write16(DMA21_CONFIG, val)
+ #define bfin_read_DMA21_X_COUNT()		bfin_read16(DMA21_X_COUNT)
+ #define bfin_write_DMA21_X_COUNT(val)		bfin_write16(DMA21_X_COUNT, val)
+ #define bfin_read_DMA21_X_MODIFY()		bfin_read16(DMA21_X_MODIFY)
+-#define bfin_write_DMA21_X_MODIFY(val) 		bfin_write16(DMA21_X_MODIFY)
++#define bfin_write_DMA21_X_MODIFY(val) 		bfin_write16(DMA21_X_MODIFY, val)
+ #define bfin_read_DMA21_Y_COUNT()		bfin_read16(DMA21_Y_COUNT)
+ #define bfin_write_DMA21_Y_COUNT(val)		bfin_write16(DMA21_Y_COUNT, val)
+ #define bfin_read_DMA21_Y_MODIFY()		bfin_read16(DMA21_Y_MODIFY)
+-#define bfin_write_DMA21_Y_MODIFY(val) 		bfin_write16(DMA21_Y_MODIFY)
++#define bfin_write_DMA21_Y_MODIFY(val) 		bfin_write16(DMA21_Y_MODIFY, val)
+ #define bfin_read_DMA21_CURR_DESC_PTR() 	bfin_read32(DMA21_CURR_DESC_PTR)
+-#define bfin_write_DMA21_CURR_DESC_PTR(val) 	bfin_write32(DMA21_CURR_DESC_PTR)
++#define bfin_write_DMA21_CURR_DESC_PTR(val) 	bfin_write32(DMA21_CURR_DESC_PTR, val)
+ #define bfin_read_DMA21_CURR_ADDR() 		bfin_read32(DMA21_CURR_ADDR)
+-#define bfin_write_DMA21_CURR_ADDR(val) 	bfin_write32(DMA21_CURR_ADDR)
++#define bfin_write_DMA21_CURR_ADDR(val) 	bfin_write32(DMA21_CURR_ADDR, val)
+ #define bfin_read_DMA21_IRQ_STATUS()		bfin_read16(DMA21_IRQ_STATUS)
+ #define bfin_write_DMA21_IRQ_STATUS(val)	bfin_write16(DMA21_IRQ_STATUS, val)
+ #define bfin_read_DMA21_PERIPHERAL_MAP()	bfin_read16(DMA21_PERIPHERAL_MAP)
+@@ -1536,23 +1532,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 22 Registers */
+ 
+ #define bfin_read_DMA22_NEXT_DESC_PTR() 	bfin_read32(DMA22_NEXT_DESC_PTR)
+-#define bfin_write_DMA22_NEXT_DESC_PTR(val) 	bfin_write32(DMA22_NEXT_DESC_PTR)
++#define bfin_write_DMA22_NEXT_DESC_PTR(val) 	bfin_write32(DMA22_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA22_START_ADDR() 		bfin_read32(DMA22_START_ADDR)
+-#define bfin_write_DMA22_START_ADDR(val) 	bfin_write32(DMA22_START_ADDR)
++#define bfin_write_DMA22_START_ADDR(val) 	bfin_write32(DMA22_START_ADDR, val)
+ #define bfin_read_DMA22_CONFIG()		bfin_read16(DMA22_CONFIG)
+ #define bfin_write_DMA22_CONFIG(val)		bfin_write16(DMA22_CONFIG, val)
+ #define bfin_read_DMA22_X_COUNT()		bfin_read16(DMA22_X_COUNT)
+ #define bfin_write_DMA22_X_COUNT(val)		bfin_write16(DMA22_X_COUNT, val)
+ #define bfin_read_DMA22_X_MODIFY()		bfin_read16(DMA22_X_MODIFY)
+-#define bfin_write_DMA22_X_MODIFY(val) 		bfin_write16(DMA22_X_MODIFY)
++#define bfin_write_DMA22_X_MODIFY(val) 		bfin_write16(DMA22_X_MODIFY, val)
+ #define bfin_read_DMA22_Y_COUNT()		bfin_read16(DMA22_Y_COUNT)
+ #define bfin_write_DMA22_Y_COUNT(val)		bfin_write16(DMA22_Y_COUNT, val)
+ #define bfin_read_DMA22_Y_MODIFY()		bfin_read16(DMA22_Y_MODIFY)
+-#define bfin_write_DMA22_Y_MODIFY(val) 		bfin_write16(DMA22_Y_MODIFY)
++#define bfin_write_DMA22_Y_MODIFY(val) 		bfin_write16(DMA22_Y_MODIFY, val)
+ #define bfin_read_DMA22_CURR_DESC_PTR() 	bfin_read32(DMA22_CURR_DESC_PTR)
+-#define bfin_write_DMA22_CURR_DESC_PTR(val) 	bfin_write32(DMA22_CURR_DESC_PTR)
++#define bfin_write_DMA22_CURR_DESC_PTR(val) 	bfin_write32(DMA22_CURR_DESC_PTR, val)
+ #define bfin_read_DMA22_CURR_ADDR() 		bfin_read32(DMA22_CURR_ADDR)
+-#define bfin_write_DMA22_CURR_ADDR(val) 	bfin_write32(DMA22_CURR_ADDR)
++#define bfin_write_DMA22_CURR_ADDR(val) 	bfin_write32(DMA22_CURR_ADDR, val)
+ #define bfin_read_DMA22_IRQ_STATUS()		bfin_read16(DMA22_IRQ_STATUS)
+ #define bfin_write_DMA22_IRQ_STATUS(val)	bfin_write16(DMA22_IRQ_STATUS, val)
+ #define bfin_read_DMA22_PERIPHERAL_MAP()	bfin_read16(DMA22_PERIPHERAL_MAP)
+@@ -1565,23 +1561,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 23 Registers */
+ 
+ #define bfin_read_DMA23_NEXT_DESC_PTR() 		bfin_read32(DMA23_NEXT_DESC_PTR)
+-#define bfin_write_DMA23_NEXT_DESC_PTR(val) 		bfin_write32(DMA23_NEXT_DESC_PTR)
++#define bfin_write_DMA23_NEXT_DESC_PTR(val) 		bfin_write32(DMA23_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA23_START_ADDR() 			bfin_read32(DMA23_START_ADDR)
+-#define bfin_write_DMA23_START_ADDR(val) 		bfin_write32(DMA23_START_ADDR)
++#define bfin_write_DMA23_START_ADDR(val) 		bfin_write32(DMA23_START_ADDR, val)
+ #define bfin_read_DMA23_CONFIG()			bfin_read16(DMA23_CONFIG)
+ #define bfin_write_DMA23_CONFIG(val)			bfin_write16(DMA23_CONFIG, val)
+ #define bfin_read_DMA23_X_COUNT()			bfin_read16(DMA23_X_COUNT)
+ #define bfin_write_DMA23_X_COUNT(val)			bfin_write16(DMA23_X_COUNT, val)
+ #define bfin_read_DMA23_X_MODIFY()			bfin_read16(DMA23_X_MODIFY)
+-#define bfin_write_DMA23_X_MODIFY(val) 			bfin_write16(DMA23_X_MODIFY)
++#define bfin_write_DMA23_X_MODIFY(val) 			bfin_write16(DMA23_X_MODIFY, val)
+ #define bfin_read_DMA23_Y_COUNT()			bfin_read16(DMA23_Y_COUNT)
+ #define bfin_write_DMA23_Y_COUNT(val)			bfin_write16(DMA23_Y_COUNT, val)
+ #define bfin_read_DMA23_Y_MODIFY()			bfin_read16(DMA23_Y_MODIFY)
+-#define bfin_write_DMA23_Y_MODIFY(val) 			bfin_write16(DMA23_Y_MODIFY)
++#define bfin_write_DMA23_Y_MODIFY(val) 			bfin_write16(DMA23_Y_MODIFY, val)
+ #define bfin_read_DMA23_CURR_DESC_PTR() 		bfin_read32(DMA23_CURR_DESC_PTR)
+-#define bfin_write_DMA23_CURR_DESC_PTR(val) 		bfin_write32(DMA23_CURR_DESC_PTR)
++#define bfin_write_DMA23_CURR_DESC_PTR(val) 		bfin_write32(DMA23_CURR_DESC_PTR, val)
+ #define bfin_read_DMA23_CURR_ADDR() 			bfin_read32(DMA23_CURR_ADDR)
+-#define bfin_write_DMA23_CURR_ADDR(val) 		bfin_write32(DMA23_CURR_ADDR)
++#define bfin_write_DMA23_CURR_ADDR(val) 		bfin_write32(DMA23_CURR_ADDR, val)
+ #define bfin_read_DMA23_IRQ_STATUS()			bfin_read16(DMA23_IRQ_STATUS)
+ #define bfin_write_DMA23_IRQ_STATUS(val)		bfin_write16(DMA23_IRQ_STATUS, val)
+ #define bfin_read_DMA23_PERIPHERAL_MAP()		bfin_read16(DMA23_PERIPHERAL_MAP)
+@@ -1594,23 +1590,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* MDMA Stream 2 Registers */
+ 
+ #define bfin_read_MDMA_D2_NEXT_DESC_PTR() 		bfin_read32(MDMA_D2_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_D2_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_D2_NEXT_DESC_PTR)
++#define bfin_write_MDMA_D2_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_D2_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_D2_START_ADDR() 			bfin_read32(MDMA_D2_START_ADDR)
+-#define bfin_write_MDMA_D2_START_ADDR(val) 		bfin_write32(MDMA_D2_START_ADDR)
++#define bfin_write_MDMA_D2_START_ADDR(val) 		bfin_write32(MDMA_D2_START_ADDR, val)
+ #define bfin_read_MDMA_D2_CONFIG()			bfin_read16(MDMA_D2_CONFIG)
+ #define bfin_write_MDMA_D2_CONFIG(val)			bfin_write16(MDMA_D2_CONFIG, val)
+ #define bfin_read_MDMA_D2_X_COUNT()			bfin_read16(MDMA_D2_X_COUNT)
+ #define bfin_write_MDMA_D2_X_COUNT(val)			bfin_write16(MDMA_D2_X_COUNT, val)
+ #define bfin_read_MDMA_D2_X_MODIFY()			bfin_read16(MDMA_D2_X_MODIFY)
+-#define bfin_write_MDMA_D2_X_MODIFY(val) 		bfin_write16(MDMA_D2_X_MODIFY)
++#define bfin_write_MDMA_D2_X_MODIFY(val) 		bfin_write16(MDMA_D2_X_MODIFY, val)
+ #define bfin_read_MDMA_D2_Y_COUNT()			bfin_read16(MDMA_D2_Y_COUNT)
+ #define bfin_write_MDMA_D2_Y_COUNT(val)			bfin_write16(MDMA_D2_Y_COUNT, val)
+ #define bfin_read_MDMA_D2_Y_MODIFY()			bfin_read16(MDMA_D2_Y_MODIFY)
+-#define bfin_write_MDMA_D2_Y_MODIFY(val) 		bfin_write16(MDMA_D2_Y_MODIFY)
++#define bfin_write_MDMA_D2_Y_MODIFY(val) 		bfin_write16(MDMA_D2_Y_MODIFY, val)
+ #define bfin_read_MDMA_D2_CURR_DESC_PTR() 		bfin_read32(MDMA_D2_CURR_DESC_PTR)
+-#define bfin_write_MDMA_D2_CURR_DESC_PTR(val) 		bfin_write32(MDMA_D2_CURR_DESC_PTR)
++#define bfin_write_MDMA_D2_CURR_DESC_PTR(val) 		bfin_write32(MDMA_D2_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_D2_CURR_ADDR() 			bfin_read32(MDMA_D2_CURR_ADDR)
+-#define bfin_write_MDMA_D2_CURR_ADDR(val) 		bfin_write32(MDMA_D2_CURR_ADDR)
++#define bfin_write_MDMA_D2_CURR_ADDR(val) 		bfin_write32(MDMA_D2_CURR_ADDR, val)
+ #define bfin_read_MDMA_D2_IRQ_STATUS()			bfin_read16(MDMA_D2_IRQ_STATUS)
+ #define bfin_write_MDMA_D2_IRQ_STATUS(val)		bfin_write16(MDMA_D2_IRQ_STATUS, val)
+ #define bfin_read_MDMA_D2_PERIPHERAL_MAP()		bfin_read16(MDMA_D2_PERIPHERAL_MAP)
+@@ -1620,23 +1616,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_MDMA_D2_CURR_Y_COUNT()		bfin_read16(MDMA_D2_CURR_Y_COUNT)
+ #define bfin_write_MDMA_D2_CURR_Y_COUNT(val)		bfin_write16(MDMA_D2_CURR_Y_COUNT, val)
+ #define bfin_read_MDMA_S2_NEXT_DESC_PTR() 		bfin_read32(MDMA_S2_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_S2_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_S2_NEXT_DESC_PTR)
++#define bfin_write_MDMA_S2_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_S2_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_S2_START_ADDR() 			bfin_read32(MDMA_S2_START_ADDR)
+-#define bfin_write_MDMA_S2_START_ADDR(val) 		bfin_write32(MDMA_S2_START_ADDR)
++#define bfin_write_MDMA_S2_START_ADDR(val) 		bfin_write32(MDMA_S2_START_ADDR, val)
+ #define bfin_read_MDMA_S2_CONFIG()			bfin_read16(MDMA_S2_CONFIG)
+ #define bfin_write_MDMA_S2_CONFIG(val)			bfin_write16(MDMA_S2_CONFIG, val)
+ #define bfin_read_MDMA_S2_X_COUNT()			bfin_read16(MDMA_S2_X_COUNT)
+ #define bfin_write_MDMA_S2_X_COUNT(val)			bfin_write16(MDMA_S2_X_COUNT, val)
+ #define bfin_read_MDMA_S2_X_MODIFY()			bfin_read16(MDMA_S2_X_MODIFY)
+-#define bfin_write_MDMA_S2_X_MODIFY(val) 		bfin_write16(MDMA_S2_X_MODIFY)
++#define bfin_write_MDMA_S2_X_MODIFY(val) 		bfin_write16(MDMA_S2_X_MODIFY, val)
+ #define bfin_read_MDMA_S2_Y_COUNT()			bfin_read16(MDMA_S2_Y_COUNT)
+ #define bfin_write_MDMA_S2_Y_COUNT(val)			bfin_write16(MDMA_S2_Y_COUNT, val)
+ #define bfin_read_MDMA_S2_Y_MODIFY()			bfin_read16(MDMA_S2_Y_MODIFY)
+-#define bfin_write_MDMA_S2_Y_MODIFY(val) 		bfin_write16(MDMA_S2_Y_MODIFY)
++#define bfin_write_MDMA_S2_Y_MODIFY(val) 		bfin_write16(MDMA_S2_Y_MODIFY, val)
+ #define bfin_read_MDMA_S2_CURR_DESC_PTR() 		bfin_read32(MDMA_S2_CURR_DESC_PTR)
+-#define bfin_write_MDMA_S2_CURR_DESC_PTR(val) 		bfin_write32(MDMA_S2_CURR_DESC_PTR)
++#define bfin_write_MDMA_S2_CURR_DESC_PTR(val) 		bfin_write32(MDMA_S2_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_S2_CURR_ADDR() 			bfin_read32(MDMA_S2_CURR_ADDR)
+-#define bfin_write_MDMA_S2_CURR_ADDR(val) 		bfin_write32(MDMA_S2_CURR_ADDR)
++#define bfin_write_MDMA_S2_CURR_ADDR(val) 		bfin_write32(MDMA_S2_CURR_ADDR, val)
+ #define bfin_read_MDMA_S2_IRQ_STATUS()			bfin_read16(MDMA_S2_IRQ_STATUS)
+ #define bfin_write_MDMA_S2_IRQ_STATUS(val)		bfin_write16(MDMA_S2_IRQ_STATUS, val)
+ #define bfin_read_MDMA_S2_PERIPHERAL_MAP()		bfin_read16(MDMA_S2_PERIPHERAL_MAP)
+@@ -1649,23 +1645,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* MDMA Stream 3 Registers */
+ 
+ #define bfin_read_MDMA_D3_NEXT_DESC_PTR() 		bfin_read32(MDMA_D3_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_D3_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_D3_NEXT_DESC_PTR)
++#define bfin_write_MDMA_D3_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_D3_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_D3_START_ADDR() 			bfin_read32(MDMA_D3_START_ADDR)
+-#define bfin_write_MDMA_D3_START_ADDR(val) 		bfin_write32(MDMA_D3_START_ADDR)
++#define bfin_write_MDMA_D3_START_ADDR(val) 		bfin_write32(MDMA_D3_START_ADDR, val)
+ #define bfin_read_MDMA_D3_CONFIG()			bfin_read16(MDMA_D3_CONFIG)
+ #define bfin_write_MDMA_D3_CONFIG(val)			bfin_write16(MDMA_D3_CONFIG, val)
+ #define bfin_read_MDMA_D3_X_COUNT()			bfin_read16(MDMA_D3_X_COUNT)
+ #define bfin_write_MDMA_D3_X_COUNT(val)			bfin_write16(MDMA_D3_X_COUNT, val)
+ #define bfin_read_MDMA_D3_X_MODIFY()			bfin_read16(MDMA_D3_X_MODIFY)
+-#define bfin_write_MDMA_D3_X_MODIFY(val) 		bfin_write16(MDMA_D3_X_MODIFY)
++#define bfin_write_MDMA_D3_X_MODIFY(val) 		bfin_write16(MDMA_D3_X_MODIFY, val)
+ #define bfin_read_MDMA_D3_Y_COUNT()			bfin_read16(MDMA_D3_Y_COUNT)
+ #define bfin_write_MDMA_D3_Y_COUNT(val)			bfin_write16(MDMA_D3_Y_COUNT, val)
+ #define bfin_read_MDMA_D3_Y_MODIFY()			bfin_read16(MDMA_D3_Y_MODIFY)
+-#define bfin_write_MDMA_D3_Y_MODIFY(val) 		bfin_write16(MDMA_D3_Y_MODIFY)
++#define bfin_write_MDMA_D3_Y_MODIFY(val) 		bfin_write16(MDMA_D3_Y_MODIFY, val)
+ #define bfin_read_MDMA_D3_CURR_DESC_PTR() 		bfin_read32(MDMA_D3_CURR_DESC_PTR)
+-#define bfin_write_MDMA_D3_CURR_DESC_PTR(val) 		bfin_write32(MDMA_D3_CURR_DESC_PTR)
++#define bfin_write_MDMA_D3_CURR_DESC_PTR(val) 		bfin_write32(MDMA_D3_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_D3_CURR_ADDR() 			bfin_read32(MDMA_D3_CURR_ADDR)
+-#define bfin_write_MDMA_D3_CURR_ADDR(val) 		bfin_write32(MDMA_D3_CURR_ADDR)
++#define bfin_write_MDMA_D3_CURR_ADDR(val) 		bfin_write32(MDMA_D3_CURR_ADDR, val)
+ #define bfin_read_MDMA_D3_IRQ_STATUS()			bfin_read16(MDMA_D3_IRQ_STATUS)
+ #define bfin_write_MDMA_D3_IRQ_STATUS(val)		bfin_write16(MDMA_D3_IRQ_STATUS, val)
+ #define bfin_read_MDMA_D3_PERIPHERAL_MAP()		bfin_read16(MDMA_D3_PERIPHERAL_MAP)
+@@ -1675,23 +1671,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_MDMA_D3_CURR_Y_COUNT()		bfin_read16(MDMA_D3_CURR_Y_COUNT)
+ #define bfin_write_MDMA_D3_CURR_Y_COUNT(val)		bfin_write16(MDMA_D3_CURR_Y_COUNT, val)
+ #define bfin_read_MDMA_S3_NEXT_DESC_PTR() 		bfin_read32(MDMA_S3_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_S3_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_S3_NEXT_DESC_PTR)
++#define bfin_write_MDMA_S3_NEXT_DESC_PTR(val) 		bfin_write32(MDMA_S3_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_S3_START_ADDR() 			bfin_read32(MDMA_S3_START_ADDR)
+-#define bfin_write_MDMA_S3_START_ADDR(val) 		bfin_write32(MDMA_S3_START_ADDR)
++#define bfin_write_MDMA_S3_START_ADDR(val) 		bfin_write32(MDMA_S3_START_ADDR, val)
+ #define bfin_read_MDMA_S3_CONFIG()			bfin_read16(MDMA_S3_CONFIG)
+ #define bfin_write_MDMA_S3_CONFIG(val)			bfin_write16(MDMA_S3_CONFIG, val)
+ #define bfin_read_MDMA_S3_X_COUNT()			bfin_read16(MDMA_S3_X_COUNT)
+ #define bfin_write_MDMA_S3_X_COUNT(val)			bfin_write16(MDMA_S3_X_COUNT, val)
+ #define bfin_read_MDMA_S3_X_MODIFY()			bfin_read16(MDMA_S3_X_MODIFY)
+-#define bfin_write_MDMA_S3_X_MODIFY(val) 		bfin_write16(MDMA_S3_X_MODIFY)
++#define bfin_write_MDMA_S3_X_MODIFY(val) 		bfin_write16(MDMA_S3_X_MODIFY, val)
+ #define bfin_read_MDMA_S3_Y_COUNT()			bfin_read16(MDMA_S3_Y_COUNT)
+ #define bfin_write_MDMA_S3_Y_COUNT(val)			bfin_write16(MDMA_S3_Y_COUNT, val)
+ #define bfin_read_MDMA_S3_Y_MODIFY()			bfin_read16(MDMA_S3_Y_MODIFY)
+-#define bfin_write_MDMA_S3_Y_MODIFY(val) 		bfin_write16(MDMA_S3_Y_MODIFY)
++#define bfin_write_MDMA_S3_Y_MODIFY(val) 		bfin_write16(MDMA_S3_Y_MODIFY, val)
+ #define bfin_read_MDMA_S3_CURR_DESC_PTR() 		bfin_read32(MDMA_S3_CURR_DESC_PTR)
+-#define bfin_write_MDMA_S3_CURR_DESC_PTR(val) 		bfin_write32(MDMA_S3_CURR_DESC_PTR)
++#define bfin_write_MDMA_S3_CURR_DESC_PTR(val) 		bfin_write32(MDMA_S3_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_S3_CURR_ADDR() 			bfin_read32(MDMA_S3_CURR_ADDR)
+-#define bfin_write_MDMA_S3_CURR_ADDR(val) 		bfin_write32(MDMA_S3_CURR_ADDR)
++#define bfin_write_MDMA_S3_CURR_ADDR(val) 		bfin_write32(MDMA_S3_CURR_ADDR, val)
+ #define bfin_read_MDMA_S3_IRQ_STATUS()			bfin_read16(MDMA_S3_IRQ_STATUS)
+ #define bfin_write_MDMA_S3_IRQ_STATUS(val)		bfin_write16(MDMA_S3_IRQ_STATUS, val)
+ #define bfin_read_MDMA_S3_PERIPHERAL_MAP()		bfin_read16(MDMA_S3_PERIPHERAL_MAP)
+diff --git a/include/asm-blackfin/mach-bf548/dma.h b/include/asm-blackfin/mach-bf548/dma.h
+index 46ff31f..36a2ef7 100644
+--- a/include/asm-blackfin/mach-bf548/dma.h
++++ b/include/asm-blackfin/mach-bf548/dma.h
+@@ -73,6 +73,4 @@
+ 
+ #define MAX_BLACKFIN_DMA_CHANNEL 32
+ 
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL];
+ #endif
+diff --git a/include/asm-blackfin/mach-bf548/mem_init.h b/include/asm-blackfin/mach-bf548/mem_init.h
+index befc290..ab0b863 100644
+--- a/include/asm-blackfin/mach-bf548/mem_init.h
++++ b/include/asm-blackfin/mach-bf548/mem_init.h
+@@ -29,16 +29,19 @@
+  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+ #define MIN_DDR_SCLK(x)	(x*(CONFIG_SCLK_HZ/1000/1000)/1000 + 1)
++#define MAX_DDR_SCLK(x)	(x*(CONFIG_SCLK_HZ/1000/1000)/1000)
++#define DDR_CLK_HZ(x)	(1000*1000*1000/x)
+ 
+ #if (CONFIG_MEM_MT46V32M16_6T)
+ #define DDR_SIZE	DEVSZ_512
+ #define DDR_WIDTH	DEVWD_16
++#define DDR_MAX_tCK	13
+ 
+ #define DDR_tRC		DDR_TRC(MIN_DDR_SCLK(60))
+ #define DDR_tRAS	DDR_TRAS(MIN_DDR_SCLK(42))
+ #define DDR_tRP		DDR_TRP(MIN_DDR_SCLK(15))
+ #define DDR_tRFC	DDR_TRFC(MIN_DDR_SCLK(72))
+-#define DDR_tREFI	DDR_TREFI(MIN_DDR_SCLK(7800))
++#define DDR_tREFI	DDR_TREFI(MAX_DDR_SCLK(7800))
+ 
+ #define DDR_tRCD	DDR_TRCD(MIN_DDR_SCLK(15))
+ #define DDR_tWTR	DDR_TWTR(1)
+@@ -49,12 +52,13 @@
+ #if (CONFIG_MEM_MT46V32M16_5B)
+ #define DDR_SIZE	DEVSZ_512
+ #define DDR_WIDTH	DEVWD_16
++#define DDR_MAX_tCK	13
+ 
+ #define DDR_tRC		DDR_TRC(MIN_DDR_SCLK(55))
+ #define DDR_tRAS	DDR_TRAS(MIN_DDR_SCLK(40))
+ #define DDR_tRP		DDR_TRP(MIN_DDR_SCLK(15))
+ #define DDR_tRFC	DDR_TRFC(MIN_DDR_SCLK(70))
+-#define DDR_tREFI	DDR_TREFI(MIN_DDR_SCLK(7800))
++#define DDR_tREFI	DDR_TREFI(MAX_DDR_SCLK(7800))
+ 
+ #define DDR_tRCD	DDR_TRCD(MIN_DDR_SCLK(15))
+ #define DDR_tWTR	DDR_TWTR(2)
+@@ -65,6 +69,7 @@
+ #if (CONFIG_MEM_GENERIC_BOARD)
+ #define DDR_SIZE	DEVSZ_512
+ #define DDR_WIDTH	DEVWD_16
++#define DDR_MAX_tCK	13
+ 
+ #define DDR_tRCD	DDR_TRCD(3)
+ #define DDR_tWTR	DDR_TWTR(2)
+@@ -77,14 +82,15 @@
+ #define DDR_tREFI	DDR_TREFI(1288)
+ #endif
+ 
+-#if (CONFIG_SCLK_HZ <= 133333333)
+-#define	DDR_CL		CL_2
+-#elif (CONFIG_SCLK_HZ <= 166666666)
+-#define	DDR_CL		CL_2_5
++#if (CONFIG_SCLK_HZ < DDR_CLK_HZ(DDR_MAX_tCK))
++# error "CONFIG_SCLK_HZ is too small (<DDR_CLK_HZ(DDR_MAX_tCK) Hz)."
++#elif(CONFIG_SCLK_HZ <= 133333333)
++# define	DDR_CL		CL_2
+ #else
+-#define	DDR_CL		CL_3
++# error "CONFIG_SCLK_HZ is too large (>133333333 Hz)."
+ #endif
+ 
++
+ #define mem_DDRCTL0	(DDR_tRP | DDR_tRAS | DDR_tRC | DDR_tRFC | DDR_tREFI)
+ #define mem_DDRCTL1	(DDR_DATWIDTH | EXTBANK_1 | DDR_SIZE | DDR_WIDTH | DDR_tWTR \
+ 			| DDR_tMRD | DDR_tWR | DDR_tRCD)
+diff --git a/include/asm-blackfin/mach-bf561/anomaly.h b/include/asm-blackfin/mach-bf561/anomaly.h
+index 0c1d461..82157ca 100644
+--- a/include/asm-blackfin/mach-bf561/anomaly.h
++++ b/include/asm-blackfin/mach-bf561/anomaly.h
+@@ -7,7 +7,7 @@
+  */
+ 
+ /* This file shoule be up to date with:
+- *  - Revision O, 11/15/2007; ADSP-BF561 Blackfin Processor Anomaly List
++ *  - Revision P, 02/08/2008; ADSP-BF561 Blackfin Processor Anomaly List
+  */
+ 
+ #ifndef _MACH_ANOMALY_H_
+@@ -256,10 +256,14 @@
+ #define ANOMALY_05000357 (1)
+ /* Conflicting Column Address Widths Causes SDRAM Errors */
+ #define ANOMALY_05000362 (1)
++/* UART Break Signal Issues */
++#define ANOMALY_05000363 (__SILICON_REVISION__ < 5)
+ /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
+ #define ANOMALY_05000366 (1)
+ /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
+ #define ANOMALY_05000371 (1)
++/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
++#define ANOMALY_05000403 (1)
+ 
+ /* Anomalies that don't exist on this proc */
+ #define ANOMALY_05000158 (0)
+diff --git a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
+index b6f513b..8a4e66d 100644
+--- a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file:        include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ *	blackfin serial driver head file
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs:         enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * this program is distributed in the hope that it will be useful,
++ * but without any warranty; without even the implied warranty of
++ * merchantability or fitness for a particular purpose.  see 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,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+ 
+-#define NR_PORTS                1
+-
+-#define OFFSET_THR              0x00	/* Transmit Holding register            */
+-#define OFFSET_RBR              0x00	/* Receive Buffer register              */
+-#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
+-#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
+-#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
+-#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
+-#define OFFSET_LCR              0x0C	/* Line Control Register                */
+-#define OFFSET_MCR              0x10	/* Modem Control Register               */
+-#define OFFSET_LSR              0x14	/* Line Status Register                 */
+-#define OFFSET_MSR              0x18	/* Modem Status Register                */
+-#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
+-#define OFFSET_GCTL             0x24	/* Global Control Register              */
+-
+ #define UART_GET_CHAR(uart)     bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart)	bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_IER(uart)      bfin_read16(((uart)->port.membase + OFFSET_IER))
+@@ -84,7 +100,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+ 	bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+ }
+ 
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ 	unsigned long	uart_base_addr;
+ 	int		uart_irq;
+@@ -115,7 +131,7 @@ struct bfin_serial_res bfin_serial_resource[] = {
+ 
+ #define DRIVER_NAME "bfin-uart"
+ 
+-int nr_ports = NR_PORTS;
++int nr_ports = BFIN_UART_NR_PORTS;
+ static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+ {
+ 
+diff --git a/include/asm-blackfin/mach-bf561/bfin_sir.h b/include/asm-blackfin/mach-bf561/bfin_sir.h
+new file mode 100644
+index 0000000..cefcf8b
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf561/bfin_sir.h
+@@ -0,0 +1,120 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port)   bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port)    bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port)    bfin_read16((port)->membase + OFFSET_IER)
++#define SIR_UART_GET_DLH(port)    bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_IIR(port)    bfin_read16((port)->membase + OFFSET_IIR)
++#define SIR_UART_GET_LCR(port)    bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_GCTL(port)   bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_PUT_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER), v)
++#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++	char *buf;
++	int head;
++	int tail;
++	};
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++	unsigned char __iomem   *membase;
++	unsigned int            irq;
++	unsigned int            lsr;
++	unsigned long           clk;
++	struct net_device       *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++	int                     tx_done;
++	struct dma_rx_buf       rx_dma_buf;
++	struct timer_list       rx_dma_timer;
++	int                     rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++	unsigned int            tx_dma_channel;
++	unsigned int            rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++	unsigned long   base_addr;
++	int             irq;
++	unsigned int    rx_dma_channel;
++	unsigned int    tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++	{
++	0xFFC00400,
++	IRQ_UART_RX,
++	CH_UART_RX,
++	CH_UART_TX,
++	},
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++	struct bfin_sir_port    *sir_port;
++	spinlock_t              lock;
++	unsigned int            open;
++	int                     speed;
++	int                     newspeed;
++
++	struct sk_buff          *txskb;
++	struct sk_buff          *rxskb;
++	struct net_device_stats stats;
++	struct device           *dev;
++	struct irlap_cb         *irlap;
++	struct qos_info         qos;
++
++	iobuff_t                tx_buff;
++	iobuff_t                rx_buff;
++
++	struct work_struct      work;
++	int                     mtt;
++};
++
++static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
++{
++	unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
++	port->lsr |= (lsr & (BI|FE|PE|OE));
++	return lsr | port->lsr;
++}
++
++static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
++{
++	port->lsr = 0;
++	bfin_read16(port->membase + OFFSET_LSR);
++}
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++	peripheral_request(P_UART0_TX, DRIVER_NAME);
++	peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++	SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf561/blackfin.h b/include/asm-blackfin/mach-bf561/blackfin.h
+index 3a16df2..0ea8666 100644
+--- a/include/asm-blackfin/mach-bf561/blackfin.h
++++ b/include/asm-blackfin/mach-bf561/blackfin.h
+@@ -69,5 +69,19 @@
+ #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_UART_NR_PORTS      1
++
++#define OFFSET_THR              0x00	/* Transmit Holding register            */
++#define OFFSET_RBR              0x00	/* Receive Buffer register              */
++#define OFFSET_DLL              0x00	/* Divisor Latch (Low-Byte)             */
++#define OFFSET_IER              0x04	/* Interrupt Enable Register            */
++#define OFFSET_DLH              0x04	/* Divisor Latch (High-Byte)            */
++#define OFFSET_IIR              0x08	/* Interrupt Identification Register    */
++#define OFFSET_LCR              0x0C	/* Line Control Register                */
++#define OFFSET_MCR              0x10	/* Modem Control Register               */
++#define OFFSET_LSR              0x14	/* Line Status Register                 */
++#define OFFSET_MSR              0x18	/* Modem Status Register                */
++#define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
++#define OFFSET_GCTL             0x24	/* Global Control Register              */
+ 
+ #endif				/* _MACH_BLACKFIN_H_ */
+diff --git a/include/asm-blackfin/mach-bf561/cdefBF561.h b/include/asm-blackfin/mach-bf561/cdefBF561.h
+index 1bc8d2f..b07ffcc 100644
+--- a/include/asm-blackfin/mach-bf561/cdefBF561.h
++++ b/include/asm-blackfin/mach-bf561/cdefBF561.h
+@@ -47,7 +47,30 @@
+ 
+ /* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
+ #define bfin_read_PLL_CTL()                  bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val)              bfin_write16(PLL_CTL,val)
++/* 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(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(flags);
++}
+ #define bfin_read_PLL_DIV()                  bfin_read16(PLL_DIV)
+ #define bfin_write_PLL_DIV(val)              bfin_write16(PLL_DIV,val)
+ #define bfin_read_VR_CTL()                   bfin_read16(VR_CTL)
+@@ -56,6 +79,10 @@ 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(flags);
+ 	/* Enable the PLL Wakeup bit in SIC IWR */
+ 	iwr0 = bfin_read32(SICA_IWR0);
+ 	iwr1 = bfin_read32(SICA_IWR1);
+@@ -65,12 +92,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ 
+ 	bfin_write16(VR_CTL, val);
+ 	SSYNC();
+-
+-	local_irq_save(flags);
+ 	asm("IDLE;");
+-	local_irq_restore(flags);
++
+ 	bfin_write32(SICA_IWR0, iwr0);
+ 	bfin_write32(SICA_IWR1, iwr1);
++	local_irq_restore(flags);
+ }
+ #define bfin_read_PLL_STAT()                 bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val)             bfin_write16(PLL_STAT,val)
+diff --git a/include/asm-blackfin/mach-bf561/defBF561.h b/include/asm-blackfin/mach-bf561/defBF561.h
+index c3c0eb1..366c9b9 100644
+--- a/include/asm-blackfin/mach-bf561/defBF561.h
++++ b/include/asm-blackfin/mach-bf561/defBF561.h
+@@ -110,18 +110,23 @@
+ #define WDOGB_STAT 				0xFFC01208	/* Watchdog Status register */
+ 
+ /* UART Controller (0xFFC00400 - 0xFFC004FF) */
+-#define UART_THR             	0xFFC00400	/* Transmit Holding register */
+-#define UART_RBR             	0xFFC00400	/* Receive Buffer register */
+-#define UART_DLL              	0xFFC00400	/* Divisor Latch (Low-Byte) */
+-#define UART_IER              	0xFFC00404	/* Interrupt Enable Register */
+-#define UART_DLH              	0xFFC00404	/* Divisor Latch (High-Byte) */
+-#define UART_IIR              	0xFFC00408	/* Interrupt Identification Register */
+-#define UART_LCR              	0xFFC0040C	/* Line Control Register */
+-#define UART_MCR			 	0xFFC00410	/* Modem Control Register */
+-#define UART_LSR              	0xFFC00414	/* Line Status Register */
+-#define UART_MSR            	0xFFC00418	/* Modem Status Register */
+-#define UART_SCR              	0xFFC0041C	/* SCR Scratch Register */
+-#define UART_GCTL      	      	0xFFC00424	/* Global Control Register */
++
++/*
++ * Because include/linux/serial_reg.h have defined UART_*,
++ * So we define blackfin uart regs to BFIN_UART0_*.
++ */
++#define BFIN_UART_THR			0xFFC00400  /* Transmit Holding register */
++#define BFIN_UART_RBR			0xFFC00400  /* Receive Buffer register */
++#define BFIN_UART_DLL			0xFFC00400  /* Divisor Latch (Low-Byte) */
++#define BFIN_UART_IER			0xFFC00404  /* Interrupt Enable Register */
++#define BFIN_UART_DLH			0xFFC00404  /* Divisor Latch (High-Byte) */
++#define BFIN_UART_IIR			0xFFC00408  /* Interrupt Identification Register */
++#define BFIN_UART_LCR			0xFFC0040C  /* Line Control Register */
++#define BFIN_UART_MCR			0xFFC00410  /* Modem Control Register */
++#define BFIN_UART_LSR			0xFFC00414  /* Line Status Register */
++#define BFIN_UART_MSR			0xFFC00418  /* Modem Status Register */
++#define BFIN_UART_SCR			0xFFC0041C  /* SCR Scratch Register */
++#define BFIN_UART_GCTL			0xFFC00424  /* Global Control Register */
+ 
+ /* SPI Controller (0xFFC00500 - 0xFFC005FF) */
+ #define SPI0_REGBASE          		0xFFC00500
+@@ -866,6 +871,8 @@
+ /* PLL_DIV Masks */
+ #define SCLK_DIV(x)  (x)	/* SCLK = VCO / x */
+ 
++#define CSEL			0x30		/* Core Select */
++#define SSEL			0xf		/* System Select */
+ #define CCLK_DIV1              0x00000000	/* CCLK = VCO / 1 */
+ #define CCLK_DIV2              0x00000010	/* CCLK = VCO / 2 */
+ #define CCLK_DIV4              0x00000020	/* CCLK = VCO / 4 */
+diff --git a/include/asm-blackfin/mach-bf561/dma.h b/include/asm-blackfin/mach-bf561/dma.h
+index 766334b..21d9820 100644
+--- a/include/asm-blackfin/mach-bf561/dma.h
++++ b/include/asm-blackfin/mach-bf561/dma.h
+@@ -32,7 +32,4 @@
+ #define CH_IMEM_STREAM1_SRC	34
+ #define CH_IMEM_STREAM1_DEST	35
+ 
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[];
+-
+ #endif
+diff --git a/include/asm-blackfin/portmux.h b/include/asm-blackfin/portmux.h
+index 0d3f650..0807b28 100644
+--- a/include/asm-blackfin/portmux.h
++++ b/include/asm-blackfin/portmux.h
+@@ -17,8 +17,8 @@
+ 
+ int peripheral_request(unsigned short per, const char *label);
+ void peripheral_free(unsigned short per);
+-int peripheral_request_list(unsigned short per[], const char *label);
+-void peripheral_free_list(unsigned short per[]);
++int peripheral_request_list(const unsigned short per[], const char *label);
++void peripheral_free_list(const unsigned short per[]);
+ 
+ #include <asm/gpio.h>
+ #include <asm/mach/portmux.h>
+diff --git a/include/asm-blackfin/processor.h b/include/asm-blackfin/processor.h
+index 1033e5c..1c00407 100644
+--- a/include/asm-blackfin/processor.h
++++ b/include/asm-blackfin/processor.h
+@@ -26,9 +26,10 @@ static inline void wrusp(unsigned long usp)
+ 
+ /*
+  * User space process size: 1st byte beyond user address space.
++ * Fairly meaningless on nommu.  Parts of user programs can be scattered
++ * in a lot of places, so just disable this by setting it to 0xFFFFFFFF.
+  */
+-extern unsigned long memory_end;
+-#define TASK_SIZE	(memory_end)
++#define TASK_SIZE	0xFFFFFFFF
+ 
+ #ifdef __KERNEL__
+ #define STACK_TOP	TASK_SIZE
+diff --git a/include/asm-blackfin/semaphore-helper.h b/include/asm-blackfin/semaphore-helper.h
+deleted file mode 100644
+index 9082b0d..0000000
+--- a/include/asm-blackfin/semaphore-helper.h
++++ /dev/null
+@@ -1,82 +0,0 @@
+-/* Based on M68K version,	Lineo Inc.	May 2001 */
+-
+-#ifndef _BFIN_SEMAPHORE_HELPER_H
+-#define _BFIN_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- */
+-
+-#include <asm/errno.h>
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore *sem)
+-{
+-	atomic_inc(&sem->waking);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+-	int ret;
+-	unsigned long flags = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 0;
+-	if (atomic_read(&sem->waking) > 0) {
+-		atomic_dec(&sem->waking);
+-		ret = 1;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- *	1	got the lock
+- *	0	go to sleep
+- *	-EINTR	interrupted
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+-						struct task_struct *tsk)
+-{
+-	int ret = 0;
+-	unsigned long flags = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (atomic_read(&sem->waking) > 0) {
+-		atomic_dec(&sem->waking);
+-		ret = 1;
+-	} else if (signal_pending(tsk)) {
+-		atomic_inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- *	1	failed to lock
+- *	0	got the lock
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+-	int ret = 1;
+-	unsigned long flags = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (atomic_read(&sem->waking) > 0) {
+-		atomic_dec(&sem->waking);
+-		ret = 0;
+-	} else
+-		atomic_inc(&sem->count);
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-#endif				/* _BFIN_SEMAPHORE_HELPER_H */
+diff --git a/include/asm-blackfin/semaphore.h b/include/asm-blackfin/semaphore.h
+index 533f90f..d9b2034 100644
+--- a/include/asm-blackfin/semaphore.h
++++ b/include/asm-blackfin/semaphore.h
+@@ -1,105 +1 @@
+-#ifndef _BFIN_SEMAPHORE_H
+-#define _BFIN_SEMAPHORE_H
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * BFIN version by akbar hussain Lineo Inc  April 2001
+- *
+- */
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.sleepers	= 0,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX(struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED(struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down(struct semaphore *sem);
+-asmlinkage int __down_interruptible(struct semaphore *sem);
+-asmlinkage int __down_trylock(struct semaphore *sem);
+-asmlinkage void __up(struct semaphore *sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "down_failed" is a special asm handler that calls the C
+- * routine that actually waits.
+- */
+-static inline void down(struct semaphore *sem)
+-{
+-	might_sleep();
+-	if (atomic_dec_return(&sem->count) < 0)
+-		__down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore *sem)
+-{
+-	int ret = 0;
+-
+-	might_sleep();
+-	if (atomic_dec_return(&sem->count) < 0)
+-		ret = __down_interruptible(sem);
+-	return (ret);
+-}
+-
+-static inline int down_trylock(struct semaphore *sem)
+-{
+-	int ret = 0;
+-
+-	if (atomic_dec_return(&sem->count) < 0)
+-		ret = __down_trylock(sem);
+-	return ret;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore *sem)
+-{
+-	if (atomic_inc_return(&sem->count) <= 0)
+-		__up(sem);
+-}
+-
+-#endif				/* __ASSEMBLY__ */
+-#endif				/* _BFIN_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-blackfin/signal.h b/include/asm-blackfin/signal.h
+index 0250429..87951d2 100644
+--- a/include/asm-blackfin/signal.h
++++ b/include/asm-blackfin/signal.h
+@@ -143,7 +143,7 @@ struct sigaction {
+ #endif				/* __KERNEL__ */
+ 
+ typedef struct sigaltstack {
+-	void *ss_sp;
++	void __user *ss_sp;
+ 	int ss_flags;
+ 	size_t ss_size;
+ } stack_t;
+diff --git a/include/asm-blackfin/thread_info.h b/include/asm-blackfin/thread_info.h
+index 15b99cf..bc2fe5a 100644
+--- a/include/asm-blackfin/thread_info.h
++++ b/include/asm-blackfin/thread_info.h
+@@ -81,14 +81,11 @@ struct thread_info {
+ #define init_thread_info	(init_thread_union.thread_info)
+ #define init_stack		(init_thread_union.stack)
+ 
+-/* How to get the thread information struct from C */
+-
+-static inline struct thread_info *current_thread_info(void)
+-    __attribute__ ((__const__));
+-
+-/* Given a task stack pointer, you can find it's task structure
+- * just by masking it to the 8K boundary.
++/* Given a task stack pointer, you can find its corresponding
++ * thread_info structure just by masking it to the THREAD_SIZE
++ * boundary (currently 8K as you can see above).
+  */
++__attribute_const__
+ static inline struct thread_info *current_thread_info(void)
+ {
+ 	struct thread_info *ti;
+diff --git a/include/asm-blackfin/time.h b/include/asm-blackfin/time.h
+new file mode 100644
+index 0000000..6e5859b
+--- /dev/null
++++ b/include/asm-blackfin/time.h
+@@ -0,0 +1,36 @@
++/*
++ * asm-blackfin/time.h:
++ *
++ * Copyright 2004-2008 Analog Devices Inc.
++ *
++ * Licensed under the GPL-2 or later.
++ */
++
++#ifndef _ASM_BLACKFIN_TIME_H
++#define _ASM_BLACKFIN_TIME_H
++
++/*
++ * The way that the Blackfin core timer works is:
++ *  - CCLK is divided by a programmable 8-bit pre-scaler (TSCALE)
++ *  - Every time TSCALE ticks, a 32bit is counted down (TCOUNT)
++ *
++ * If you take the fastest clock (1ns, or 1GHz to make the math work easier)
++ *    10ms is 10,000,000 clock ticks, which fits easy into a 32-bit counter
++ *    (32 bit counter is 4,294,967,296ns or 4.2 seconds) so, we don't need
++ *    to use TSCALE, and program it to zero (which is pass CCLK through).
++ *    If you feel like using it, try to keep HZ * TIMESCALE to some
++ *    value that divides easy (like power of 2).
++ */
++
++#ifndef CONFIG_CPU_FREQ
++#define TIME_SCALE 1
++#else
++/*
++ * Blackfin CPU frequency scaling supports max Core Clock 1, 1/2 and 1/4 .
++ * Whenever we change the Core Clock frequency changes we immediately
++ * adjust the Core Timer Presale Register. This way we don't lose time.
++ */
++#define TIME_SCALE 4
++#endif
++
++#endif
+diff --git a/include/asm-blackfin/timex.h b/include/asm-blackfin/timex.h
+index 8285901..22b0806 100644
+--- a/include/asm-blackfin/timex.h
++++ b/include/asm-blackfin/timex.h
+@@ -1,18 +1,23 @@
+-/* blackfin architecture timex specifications: Lineo Inc. 2001
++/*
++ * asm-blackfin/timex.h: cpu cycles!
+  *
+- * Based on: include/asm-m68knommu/timex.h
++ * Copyright 2004-2008 Analog Devices Inc.
++ *
++ * Licensed under the GPL-2 or later.
+  */
+ 
+-#ifndef _ASMBLACKFIN_TIMEX_H
+-#define _ASMBLACKFIN_TIMEX_H
++#ifndef _ASM_BLACKFIN_TIMEX_H
++#define _ASM_BLACKFIN_TIMEX_H
+ 
+ #define CLOCK_TICK_RATE	1000000	/* Underlying HZ */
+ 
+-typedef unsigned long cycles_t;
++typedef unsigned long long cycles_t;
+ 
+ static inline cycles_t get_cycles(void)
+ {
+-	return 0;
++	unsigned long tmp, tmp2;
++	__asm__("%0 = cycles; %1 = cycles2;" : "=d"(tmp), "=d"(tmp2));
++	return tmp | ((cycles_t)tmp2 << 32);
+ }
+ 
+ #endif
+diff --git a/include/asm-blackfin/trace.h b/include/asm-blackfin/trace.h
+index ef18afb..312b596 100644
+--- a/include/asm-blackfin/trace.h
++++ b/include/asm-blackfin/trace.h
+@@ -62,14 +62,14 @@ extern unsigned long software_trace_buff[];
+ 	preg.L = LO(TBUFCTL); \
+ 	preg.H = HI(TBUFCTL); \
+ 	dreg = [preg]; \
+-	[sp++] = dreg; \
++	[--sp] = dreg; \
+ 	dreg = 0x1; \
+ 	[preg] = dreg;
+ 
+ #define trace_buffer_restore(preg, dreg) \
+ 	preg.L = LO(TBUFCTL); \
+ 	preg.H = HI(TBUFCTL); \
+-	dreg = [sp--]; \
++	dreg = [sp++]; \
+ 	[preg] = dreg;
+ 
+ #else /* CONFIG_DEBUG_BFIN_HWTRACE_ON */
+diff --git a/include/asm-blackfin/uaccess.h b/include/asm-blackfin/uaccess.h
+index 22a410b..d928b80 100644
+--- a/include/asm-blackfin/uaccess.h
++++ b/include/asm-blackfin/uaccess.h
+@@ -133,7 +133,7 @@ static inline int bad_user_access_length(void)
+ }
+ 
+ #define __put_user_bad() (printk(KERN_INFO "put_user_bad %s:%d %s\n",\
+-                           __FILE__, __LINE__, __FUNCTION__),\
++                           __FILE__, __LINE__, __func__),\
+                            bad_user_access_length(), (-EFAULT))
+ 
+ /*
+@@ -177,7 +177,7 @@ static inline int bad_user_access_length(void)
+ 		default:						\
+ 			x = 0;						\
+ 			printk(KERN_INFO "get_user_bad: %s:%d %s\n",    \
+-			       __FILE__, __LINE__, __FUNCTION__);	\
++			       __FILE__, __LINE__, __func__);	\
+ 			_err = __get_user_bad();			\
+ 			break;						\
+ 		}							\
+diff --git a/include/asm-blackfin/unistd.h b/include/asm-blackfin/unistd.h
+index c18a399..42955d0 100644
+--- a/include/asm-blackfin/unistd.h
++++ b/include/asm-blackfin/unistd.h
+@@ -265,14 +265,14 @@
+ 				/* 258 __NR_remap_file_pages */
+ #define __NR_set_tid_address	259
+ #define __NR_timer_create	260
+-#define __NR_timer_settime	(__NR_timer_create+1)
+-#define __NR_timer_gettime	(__NR_timer_create+2)
+-#define __NR_timer_getoverrun	(__NR_timer_create+3)
+-#define __NR_timer_delete	(__NR_timer_create+4)
+-#define __NR_clock_settime	(__NR_timer_create+5)
+-#define __NR_clock_gettime	(__NR_timer_create+6)
+-#define __NR_clock_getres	(__NR_timer_create+7)
+-#define __NR_clock_nanosleep	(__NR_timer_create+8)
++#define __NR_timer_settime	261
++#define __NR_timer_gettime	262
++#define __NR_timer_getoverrun	263
++#define __NR_timer_delete	264
++#define __NR_clock_settime	265
++#define __NR_clock_gettime	266
++#define __NR_clock_getres	267
++#define __NR_clock_nanosleep	268
+ #define __NR_statfs64		269
+ #define __NR_fstatfs64		270
+ #define __NR_tgkill		271
+@@ -283,11 +283,11 @@
+ 				/* 276 __NR_get_mempolicy */
+ 				/* 277 __NR_set_mempolicy */
+ #define __NR_mq_open 		278
+-#define __NR_mq_unlink		(__NR_mq_open+1)
+-#define __NR_mq_timedsend	(__NR_mq_open+2)
+-#define __NR_mq_timedreceive	(__NR_mq_open+3)
+-#define __NR_mq_notify		(__NR_mq_open+4)
+-#define __NR_mq_getsetattr	(__NR_mq_open+5)
++#define __NR_mq_unlink		279
++#define __NR_mq_timedsend	280
++#define __NR_mq_timedreceive	281
++#define __NR_mq_notify		282
++#define __NR_mq_getsetattr	283
+ #define __NR_kexec_load		284
+ #define __NR_waitid		285
+ #define __NR_add_key		286
+diff --git a/include/asm-cris/semaphore-helper.h b/include/asm-cris/semaphore-helper.h
+deleted file mode 100644
+index 27bfeca..0000000
+--- a/include/asm-cris/semaphore-helper.h
++++ /dev/null
+@@ -1,78 +0,0 @@
+-/* $Id: semaphore-helper.h,v 1.3 2001/03/26 15:00:33 orjanf Exp $
+- *
+- * SMP- and interrupt-safe semaphores helper functions. Generic versions, no
+- * optimizations whatsoever... 
+- *
+- */
+-
+-#ifndef _ASM_SEMAPHORE_HELPER_H
+-#define _ASM_SEMAPHORE_HELPER_H
+-
+-#include <asm/atomic.h>
+-#include <linux/errno.h>
+-
+-#define read(a) ((a)->counter)
+-#define inc(a) (((a)->counter)++)
+-#define dec(a) (((a)->counter)--)
+-
+-#define count_inc(a) ((*(a))++)
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+-	atomic_inc(&sem->waking);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-	local_irq_save(flags);
+-	if (read(&sem->waking) > 0) {
+-		dec(&sem->waking);
+-		ret = 1;
+-	}
+-	local_irq_restore(flags);
+-	return ret;
+-}
+-
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+-						struct task_struct *tsk)
+-{
+-	int ret = 0;
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	if (read(&sem->waking) > 0) {
+-		dec(&sem->waking);
+-		ret = 1;
+-	} else if (signal_pending(tsk)) {
+-		inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-	local_irq_restore(flags);
+-	return ret;
+-}
+-
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+-        int ret = 1;
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	if (read(&sem->waking) <= 0)
+-		inc(&sem->count);
+-	else {
+-		dec(&sem->waking);
+-		ret = 0;
+-	}
+-	local_irq_restore(flags);
+-	return ret;
+-}
+-
+-#endif /* _ASM_SEMAPHORE_HELPER_H */
+-
+-
+diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
+index 31a4ac4..d9b2034 100644
+--- a/include/asm-cris/semaphore.h
++++ b/include/asm-cris/semaphore.h
+@@ -1,133 +1 @@
+-/* $Id: semaphore.h,v 1.3 2001/05/08 13:54:09 bjornw Exp $ */
+-
+-/* On the i386 these are coded in asm, perhaps we should as well. Later.. */
+-
+-#ifndef _CRIS_SEMAPHORE_H
+-#define _CRIS_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS             0x01000000
+-
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * CRIS semaphores, implemented in C-only so far. 
+- */
+-
+-struct semaphore {
+-	atomic_t count;
+-	atomic_t waking;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.waking		= ATOMIC_INIT(0),				\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-        struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-        sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-        sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int __down_interruptible(struct semaphore * sem);
+-extern int __down_trylock(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-/* notice - we probably can do cli/sti here instead of saving */
+-
+-static inline void down(struct semaphore * sem)
+-{
+-	unsigned long flags;
+-	int failed;
+-
+-	might_sleep();
+-
+-	/* atomically decrement the semaphores count, and if its negative, we wait */
+-	cris_atomic_save(sem, flags);
+-	failed = --(sem->count.counter) < 0;
+-	cris_atomic_restore(sem, flags);
+-	if(failed) {
+-		__down(sem);
+-	}
+-}
+-
+-/*
+- * This version waits in interruptible state so that the waiting
+- * process can be killed.  The down_interruptible routine
+- * returns negative for signalled and zero for semaphore acquired.
+- */
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	unsigned long flags;
+-	int failed;
+-
+-	might_sleep();
+-
+-	/* atomically decrement the semaphores count, and if its negative, we wait */
+-	cris_atomic_save(sem, flags);
+-	failed = --(sem->count.counter) < 0;
+-	cris_atomic_restore(sem, flags);
+-	if(failed)
+-		failed = __down_interruptible(sem);
+-	return(failed);
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	unsigned long flags;
+-	int failed;
+-
+-	cris_atomic_save(sem, flags);
+-	failed = --(sem->count.counter) < 0;
+-	cris_atomic_restore(sem, flags);
+-	if(failed)
+-		failed = __down_trylock(sem);
+-	return(failed);
+-
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{  
+-	unsigned long flags;
+-	int wakeup;
+-
+-	/* atomically increment the semaphores count, and if it was negative, we wake people */
+-	cris_atomic_save(sem, flags);
+-	wakeup = ++(sem->count.counter) <= 0;
+-	cris_atomic_restore(sem, flags);
+-	if(wakeup) {
+-		__up(sem);
+-	}
+-}
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-frv/semaphore.h b/include/asm-frv/semaphore.h
+index d7aaa19..d9b2034 100644
+--- a/include/asm-frv/semaphore.h
++++ b/include/asm-frv/semaphore.h
+@@ -1,155 +1 @@
+-/* semaphore.h: semaphores for the FR-V
+- *
+- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.com)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-#ifndef _ASM_SEMAPHORE_H
+-#define _ASM_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS		 0x01000000
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-/*
+- * the semaphore definition
+- * - if counter is >0 then there are tokens available on the semaphore for down to collect
+- * - if counter is <=0 then there are no spare tokens, and anyone that wants one must wait
+- * - if wait_list is not empty, then there are processes waiting for the semaphore
+- */
+-struct semaphore {
+-	unsigned		counter;
+-	spinlock_t		wait_lock;
+-	struct list_head	wait_list;
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	unsigned		__magic;
+-#endif
+-};
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-# define __SEM_DEBUG_INIT(name) , (long)&(name).__magic
+-#else
+-# define __SEM_DEBUG_INIT(name)
+-#endif
+-
+-
+-#define __SEMAPHORE_INITIALIZER(name,count) \
+-{ count, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) __SEM_DEBUG_INIT(name) }
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore *sem, unsigned long flags);
+-extern int  __down_interruptible(struct semaphore *sem, unsigned long flags);
+-extern void __up(struct semaphore *sem);
+-
+-static inline void down(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-	if (likely(sem->counter > 0)) {
+-		sem->counter--;
+-		spin_unlock_irqrestore(&sem->wait_lock, flags);
+-	}
+-	else {
+-		__down(sem, flags);
+-	}
+-}
+-
+-static inline int down_interruptible(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-	if (likely(sem->counter > 0)) {
+-		sem->counter--;
+-		spin_unlock_irqrestore(&sem->wait_lock, flags);
+-	}
+-	else {
+-		ret = __down_interruptible(sem, flags);
+-	}
+-	return ret;
+-}
+-
+-/*
+- * non-blockingly attempt to down() a semaphore.
+- * - returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int success = 0;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-	if (sem->counter > 0) {
+-		sem->counter--;
+-		success = 1;
+-	}
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-	return !success;
+-}
+-
+-static inline void up(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-	if (!list_empty(&sem->wait_list))
+-		__up(sem);
+-	else
+-		sem->counter++;
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-}
+-
+-static inline int sem_getcount(struct semaphore *sem)
+-{
+-	return sem->counter;
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
+index 30a67a9..cb307f8 100644
+--- a/include/asm-frv/system.h
++++ b/include/asm-frv/system.h
+@@ -197,11 +197,6 @@ do {							\
+ 	do { var = (value); barrier(); } while (0)
+ #endif
+ 
+-#define HARD_RESET_NOW()			\
+-do {						\
+-	cli();					\
+-} while(1)
+-
+ extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
+ extern void free_initmem(void);
+ 
+diff --git a/include/asm-frv/topology.h b/include/asm-frv/topology.h
+index abe7298..9427243 100644
+--- a/include/asm-frv/topology.h
++++ b/include/asm-frv/topology.h
+@@ -5,10 +5,8 @@
+ 
+ #error NUMA not supported yet
+ 
+-#else /* !CONFIG_NUMA */
++#endif /* CONFIG_NUMA */
+ 
+ #include <asm-generic/topology.h>
+ 
+-#endif /* CONFIG_NUMA */
+-
+ #endif /* _ASM_TOPOLOGY_H */
+diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
+index 67dc84c..76b0cc5 100644
+--- a/include/asm-generic/iomap.h
++++ b/include/asm-generic/iomap.h
+@@ -60,6 +60,10 @@ extern void iowrite32_rep(void __iomem *port, const void *buf, unsigned long cou
+ extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+ extern void ioport_unmap(void __iomem *);
+ 
++#ifndef ARCH_HAS_IOREMAP_WC
++#define ioremap_wc ioremap_nocache
++#endif
++
+ /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+ struct pci_dev;
+ extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h
+index 342a2a0..a6aea79 100644
+--- a/include/asm-generic/topology.h
++++ b/include/asm-generic/topology.h
+@@ -27,6 +27,8 @@
+ #ifndef _ASM_GENERIC_TOPOLOGY_H
+ #define _ASM_GENERIC_TOPOLOGY_H
+ 
++#ifndef	CONFIG_NUMA
++
+ /* Other architectures wishing to use this simple topology API should fill
+    in the below functions as appropriate in their own <asm/topology.h> file. */
+ #ifndef cpu_to_node
+@@ -52,4 +54,16 @@
+ 				)
+ #endif
+ 
++#endif	/* CONFIG_NUMA */
++
++/* returns pointer to cpumask for specified node */
++#ifndef node_to_cpumask_ptr
++
++#define	node_to_cpumask_ptr(v, node) 					\
++		cpumask_t _##v = node_to_cpumask(node), *v = &_##v
++
++#define node_to_cpumask_ptr_next(v, node)				\
++			  _##v = node_to_cpumask(node)
++#endif
++
+ #endif /* _ASM_GENERIC_TOPOLOGY_H */
+diff --git a/include/asm-h8300/semaphore-helper.h b/include/asm-h8300/semaphore-helper.h
+deleted file mode 100644
+index 4fea36b..0000000
+--- a/include/asm-h8300/semaphore-helper.h
++++ /dev/null
+@@ -1,85 +0,0 @@
+-#ifndef _H8300_SEMAPHORE_HELPER_H
+-#define _H8300_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * based on
+- * m68k version by Andreas Schwab
+- */
+-
+-#include <linux/errno.h>
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+-	atomic_inc((atomic_t *)&sem->sleepers);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+-	int ret;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 0;
+-	if (sem->sleepers > 0) {
+-		sem->sleepers--;
+-		ret = 1;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- *	1	got the lock
+- *	0	go to sleep
+- *	-EINTR	interrupted
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+-						struct task_struct *tsk)
+-{
+-	int ret;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 0;
+-	if (sem->sleepers > 0) {
+-		sem->sleepers--;
+-		ret = 1;
+-	} else if (signal_pending(tsk)) {
+-		atomic_inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- *	1	failed to lock
+- *	0	got the lock
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+-	int ret;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 1;
+-	if (sem->sleepers <= 0)
+-		atomic_inc(&sem->count);
+-	else {
+-		sem->sleepers--;
+-		ret = 0;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-#endif
+diff --git a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h
+index f3ffff8..d9b2034 100644
+--- a/include/asm-h8300/semaphore.h
++++ b/include/asm-h8300/semaphore.h
+@@ -1,190 +1 @@
+-#ifndef _H8300_SEMAPHORE_H
+-#define _H8300_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS		 0x01000000
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * H8/300 version by Yoshinori Sato
+- */
+-
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.sleepers	= 0,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+-asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int  __down_interruptible(struct semaphore * sem);
+-asmlinkage int  __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/m68k/lib/semaphore.S
+- */
+-static inline void down(struct semaphore * sem)
+-{
+-	register atomic_t *count asm("er0");
+-
+-	might_sleep();
+-
+-	count = &(sem->count);
+-	__asm__ __volatile__(
+-		"stc ccr,r3l\n\t"
+-		"orc #0x80,ccr\n\t"
+-		"mov.l %2, er1\n\t"
+-		"dec.l #1,er1\n\t"
+-		"mov.l er1,%0\n\t"
+-		"bpl 1f\n\t"
+-		"ldc r3l,ccr\n\t"
+-		"mov.l %1,er0\n\t"
+-		"jsr @___down\n\t"
+-		"bra 2f\n"
+-		"1:\n\t"
+-		"ldc r3l,ccr\n"
+-		"2:"
+-		: "=m"(*count)
+-		: "g"(sem),"m"(*count)
+-		: "cc",  "er1", "er2", "er3");
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	register atomic_t *count asm("er0");
+-
+-	might_sleep();
+-
+-	count = &(sem->count);
+-	__asm__ __volatile__(
+-		"stc ccr,r1l\n\t"
+-		"orc #0x80,ccr\n\t"
+-		"mov.l %3, er2\n\t"
+-		"dec.l #1,er2\n\t"
+-		"mov.l er2,%1\n\t"
+-		"bpl 1f\n\t"
+-		"ldc r1l,ccr\n\t"
+-		"mov.l %2,er0\n\t"
+-		"jsr @___down_interruptible\n\t"
+-		"bra 2f\n"
+-		"1:\n\t"
+-		"ldc r1l,ccr\n\t"
+-		"sub.l %0,%0\n\t"
+-		"2:\n\t"
+-		: "=r" (count),"=m" (*count)
+-		: "g"(sem),"m"(*count)
+-		: "cc", "er1", "er2", "er3");
+-	return (int)count;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	register atomic_t *count asm("er0");
+-
+-	count = &(sem->count);
+-	__asm__ __volatile__(
+-		"stc ccr,r3l\n\t"
+-		"orc #0x80,ccr\n\t"
+-		"mov.l %3,er2\n\t"
+-		"dec.l #1,er2\n\t"
+-		"mov.l er2,%0\n\t"
+-		"bpl 1f\n\t"
+-		"ldc r3l,ccr\n\t"
+-		"jmp @3f\n\t"
+-		LOCK_SECTION_START(".align 2\n\t")
+-		"3:\n\t"
+-		"mov.l %2,er0\n\t"
+-		"jsr @___down_trylock\n\t"
+-		"jmp @2f\n\t"
+-		LOCK_SECTION_END
+-		"1:\n\t"
+-		"ldc r3l,ccr\n\t"
+-		"sub.l %1,%1\n"
+-		"2:"
+-		: "=m" (*count),"=r"(count)
+-		: "g"(sem),"m"(*count)
+-		: "cc", "er1","er2", "er3");
+-	return (int)count;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	register atomic_t *count asm("er0");
+-
+-	count = &(sem->count);
+-	__asm__ __volatile__(
+-		"stc ccr,r3l\n\t"
+-		"orc #0x80,ccr\n\t"
+-		"mov.l %2,er1\n\t"
+-		"inc.l #1,er1\n\t"
+-		"mov.l er1,%0\n\t"
+-		"ldc r3l,ccr\n\t"
+-		"sub.l er2,er2\n\t"
+-		"cmp.l er2,er1\n\t"
+-		"bgt 1f\n\t"
+-		"mov.l %1,er0\n\t"
+-		"jsr @___up\n"
+-		"1:"
+-		: "=m"(*count)
+-		: "g"(sem),"m"(*count)
+-		: "cc", "er1", "er2", "er3");
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
+index cd1cc39..fcfad32 100644
+--- a/include/asm-ia64/acpi.h
++++ b/include/asm-ia64/acpi.h
+@@ -35,6 +35,7 @@
+ #include <linux/init.h>
+ #include <linux/numa.h>
+ #include <asm/system.h>
++#include <asm/numa.h>
+ 
+ #define COMPILER_DEPENDENT_INT64	long
+ #define COMPILER_DEPENDENT_UINT64	unsigned long
+@@ -115,7 +116,11 @@ extern unsigned int is_cpu_cpei_target(unsigned int cpu);
+ extern void set_cpei_target_cpu(unsigned int cpu);
+ extern unsigned int get_cpei_target_cpu(void);
+ extern void prefill_possible_map(void);
++#ifdef CONFIG_ACPI_HOTPLUG_CPU
+ extern int additional_cpus;
++#else
++#define additional_cpus 0
++#endif
+ 
+ #ifdef CONFIG_ACPI_NUMA
+ #if MAX_NUMNODES > 256
+@@ -129,6 +134,34 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
+ 
+ #define acpi_unlazy_tlb(x)
+ 
++#ifdef CONFIG_ACPI_NUMA
++extern cpumask_t early_cpu_possible_map;
++#define for_each_possible_early_cpu(cpu)  \
++	for_each_cpu_mask((cpu), early_cpu_possible_map)
++
++static inline void per_cpu_scan_finalize(int min_cpus, int reserve_cpus)
++{
++	int low_cpu, high_cpu;
++	int cpu;
++	int next_nid = 0;
++
++	low_cpu = cpus_weight(early_cpu_possible_map);
++
++	high_cpu = max(low_cpu, min_cpus);
++	high_cpu = min(high_cpu + reserve_cpus, NR_CPUS);
++
++	for (cpu = low_cpu; cpu < high_cpu; cpu++) {
++		cpu_set(cpu, early_cpu_possible_map);
++		if (node_cpuid[cpu].nid == NUMA_NO_NODE) {
++			node_cpuid[cpu].nid = next_nid;
++			next_nid++;
++			if (next_nid >= num_online_nodes())
++				next_nid = 0;
++		}
++	}
++}
++#endif /* CONFIG_ACPI_NUMA */
++
+ #endif /*__KERNEL__*/
+ 
+ #endif /*_ASM_ACPI_H*/
+diff --git a/include/asm-ia64/cputime.h b/include/asm-ia64/cputime.h
+index 72400a7..f9abdec 100644
+--- a/include/asm-ia64/cputime.h
++++ b/include/asm-ia64/cputime.h
+@@ -1,6 +1,110 @@
++/*
++ * include/asm-ia64/cputime.h:
++ *		Definitions for measuring cputime on ia64 machines.
++ *
++ * Based on <asm-powerpc/cputime.h>.
++ *
++ * Copyright (C) 2007 FUJITSU LIMITED
++ * Copyright (C) 2007 Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.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.
++ *
++ * If we have CONFIG_VIRT_CPU_ACCOUNTING, we measure cpu time in nsec.
++ * Otherwise we measure cpu time in jiffies using the generic definitions.
++ */
++
+ #ifndef __IA64_CPUTIME_H
+ #define __IA64_CPUTIME_H
+ 
++#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+ #include <asm-generic/cputime.h>
++#else
++
++#include <linux/time.h>
++#include <linux/jiffies.h>
++#include <asm/processor.h>
++
++typedef u64 cputime_t;
++typedef u64 cputime64_t;
++
++#define cputime_zero			((cputime_t)0)
++#define cputime_max			((~((cputime_t)0) >> 1) - 1)
++#define cputime_add(__a, __b)		((__a) +  (__b))
++#define cputime_sub(__a, __b)		((__a) -  (__b))
++#define cputime_div(__a, __n)		((__a) /  (__n))
++#define cputime_halve(__a)		((__a) >> 1)
++#define cputime_eq(__a, __b)		((__a) == (__b))
++#define cputime_gt(__a, __b)		((__a) >  (__b))
++#define cputime_ge(__a, __b)		((__a) >= (__b))
++#define cputime_lt(__a, __b)		((__a) <  (__b))
++#define cputime_le(__a, __b)		((__a) <= (__b))
++
++#define cputime64_zero			((cputime64_t)0)
++#define cputime64_add(__a, __b)		((__a) + (__b))
++#define cputime64_sub(__a, __b)		((__a) - (__b))
++#define cputime_to_cputime64(__ct)	(__ct)
++
++/*
++ * Convert cputime <-> jiffies (HZ)
++ */
++#define cputime_to_jiffies(__ct)	((__ct) / (NSEC_PER_SEC / HZ))
++#define jiffies_to_cputime(__jif)	((__jif) * (NSEC_PER_SEC / HZ))
++#define cputime64_to_jiffies64(__ct)	((__ct) / (NSEC_PER_SEC / HZ))
++#define jiffies64_to_cputime64(__jif)	((__jif) * (NSEC_PER_SEC / HZ))
++
++/*
++ * Convert cputime <-> milliseconds
++ */
++#define cputime_to_msecs(__ct)		((__ct) / NSEC_PER_MSEC)
++#define msecs_to_cputime(__msecs)	((__msecs) * NSEC_PER_MSEC)
++
++/*
++ * Convert cputime <-> seconds
++ */
++#define cputime_to_secs(__ct)		((__ct) / NSEC_PER_SEC)
++#define secs_to_cputime(__secs)		((__secs) * NSEC_PER_SEC)
++
++/*
++ * Convert cputime <-> timespec (nsec)
++ */
++static inline cputime_t timespec_to_cputime(const struct timespec *val)
++{
++	cputime_t ret = val->tv_sec * NSEC_PER_SEC;
++	return (ret + val->tv_nsec);
++}
++static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val)
++{
++	val->tv_sec  = ct / NSEC_PER_SEC;
++	val->tv_nsec = ct % NSEC_PER_SEC;
++}
++
++/*
++ * Convert cputime <-> timeval (msec)
++ */
++static inline cputime_t timeval_to_cputime(struct timeval *val)
++{
++	cputime_t ret = val->tv_sec * NSEC_PER_SEC;
++	return (ret + val->tv_usec * NSEC_PER_USEC);
++}
++static inline void cputime_to_timeval(const cputime_t ct, struct timeval *val)
++{
++	val->tv_sec = ct / NSEC_PER_SEC;
++	val->tv_usec = (ct % NSEC_PER_SEC) / NSEC_PER_USEC;
++}
++
++/*
++ * Convert cputime <-> clock (USER_HZ)
++ */
++#define cputime_to_clock_t(__ct)	((__ct) / (NSEC_PER_SEC / USER_HZ))
++#define clock_t_to_cputime(__x)		((__x) * (NSEC_PER_SEC / USER_HZ))
++
++/*
++ * Convert cputime64 to clock.
++ */
++#define cputime64_to_clock_t(__ct)      cputime_to_clock_t((cputime_t)__ct)
+ 
++#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+ #endif /* __IA64_CPUTIME_H */
+diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
+index f8e83ec..5e0c1a6 100644
+--- a/include/asm-ia64/elf.h
++++ b/include/asm-ia64/elf.h
+@@ -26,6 +26,7 @@
+ #define ELF_ARCH	EM_IA_64
+ 
+ #define USE_ELF_CORE_DUMP
++#define CORE_DUMP_USE_REGSET
+ 
+ /* Least-significant four bits of ELF header's e_flags are OS-specific.  The bits are
+    interpreted as follows by Linux: */
+@@ -154,6 +155,30 @@ extern void ia64_init_addr_space (void);
+ #define ELF_NGREG	128	/* we really need just 72 but let's leave some headroom... */
+ #define ELF_NFPREG	128	/* f0 and f1 could be omitted, but so what... */
+ 
++/* elf_gregset_t register offsets */
++#define ELF_GR_0_OFFSET     0
++#define ELF_NAT_OFFSET     (32 * sizeof(elf_greg_t))
++#define ELF_PR_OFFSET      (33 * sizeof(elf_greg_t))
++#define ELF_BR_0_OFFSET    (34 * sizeof(elf_greg_t))
++#define ELF_CR_IIP_OFFSET  (42 * sizeof(elf_greg_t))
++#define ELF_CFM_OFFSET     (43 * sizeof(elf_greg_t))
++#define ELF_CR_IPSR_OFFSET (44 * sizeof(elf_greg_t))
++#define ELF_GR_OFFSET(i)   (ELF_GR_0_OFFSET + i * sizeof(elf_greg_t))
++#define ELF_BR_OFFSET(i)   (ELF_BR_0_OFFSET + i * sizeof(elf_greg_t))
++#define ELF_AR_RSC_OFFSET  (45 * sizeof(elf_greg_t))
++#define ELF_AR_BSP_OFFSET  (46 * sizeof(elf_greg_t))
++#define ELF_AR_BSPSTORE_OFFSET (47 * sizeof(elf_greg_t))
++#define ELF_AR_RNAT_OFFSET (48 * sizeof(elf_greg_t))
++#define ELF_AR_CCV_OFFSET  (49 * sizeof(elf_greg_t))
++#define ELF_AR_UNAT_OFFSET (50 * sizeof(elf_greg_t))
++#define ELF_AR_FPSR_OFFSET (51 * sizeof(elf_greg_t))
++#define ELF_AR_PFS_OFFSET  (52 * sizeof(elf_greg_t))
++#define ELF_AR_LC_OFFSET   (53 * sizeof(elf_greg_t))
++#define ELF_AR_EC_OFFSET   (54 * sizeof(elf_greg_t))
++#define ELF_AR_CSD_OFFSET  (55 * sizeof(elf_greg_t))
++#define ELF_AR_SSD_OFFSET  (56 * sizeof(elf_greg_t))
++#define ELF_AR_END_OFFSET  (57 * sizeof(elf_greg_t))
++
+ typedef unsigned long elf_fpxregset_t;
+ 
+ typedef unsigned long elf_greg_t;
+@@ -183,12 +208,6 @@ extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst);
+ 
+ struct task_struct;
+ 
+-extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
+-extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
+-
+-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_gregs) dump_task_regs(tsk, elf_gregs)
+-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+-
+ #define GATE_EHDR	((const struct elfhdr *) GATE_ADDR)
+ 
+ /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
+diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
+index 1ccf238..8fa3f8c 100644
+--- a/include/asm-ia64/ide.h
++++ b/include/asm-ia64/ide.h
+@@ -16,8 +16,6 @@
+ 
+ #include <linux/irq.h>
+ 
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static inline int ide_default_irq(unsigned long base)
+ {
+ 	switch (base) {
+@@ -46,14 +44,6 @@ static inline unsigned long ide_default_io_base(int index)
+ 	}
+ }
+ 
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_PCI
+-#define ide_init_default_irq(base)	(0)
+-#else
+-#define ide_init_default_irq(base)	ide_default_irq(base)
+-#endif
+-
+ #include <asm-generic/ide_iops.h>
+ 
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
+index d03bf9f..ef71b57 100644
+--- a/include/asm-ia64/kprobes.h
++++ b/include/asm-ia64/kprobes.h
+@@ -30,8 +30,12 @@
+ #include <asm/break.h>
+ 
+ #define __ARCH_WANT_KPROBES_INSN_SLOT
+-#define MAX_INSN_SIZE   1
++#define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
+ #define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
++#define NOP_M_INST	(long)(1<<27)
++#define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
++				(0x1L << 12) |	/* many */ \
++				(((i1) & 1) << 36) | ((i2) << 13))) /* imm */
+ 
+ typedef union cmp_inst {
+ 	struct {
+@@ -112,6 +116,7 @@ struct arch_specific_insn {
+  #define INST_FLAG_FIX_RELATIVE_IP_ADDR		1
+  #define INST_FLAG_FIX_BRANCH_REG		2
+  #define INST_FLAG_BREAK_INST			4
++ #define INST_FLAG_BOOSTABLE			8
+  	unsigned long inst_flag;
+  	unsigned short target_br_reg;
+ 	unsigned short slot;
+diff --git a/include/asm-ia64/kregs.h b/include/asm-ia64/kregs.h
+index 7e55a58..aefcdfe 100644
+--- a/include/asm-ia64/kregs.h
++++ b/include/asm-ia64/kregs.h
+@@ -31,6 +31,9 @@
+ #define IA64_TR_PALCODE		1	/* itr1: maps PALcode as required by EFI */
+ #define IA64_TR_CURRENT_STACK	1	/* dtr1: maps kernel's memory- & register-stacks */
+ 
++#define IA64_TR_ALLOC_BASE	2 	/* itr&dtr: Base of dynamic TR resource*/
++#define IA64_TR_ALLOC_MAX	32 	/* Max number for dynamic use*/
++
+ /* Processor status register bits: */
+ #define IA64_PSR_BE_BIT		1
+ #define IA64_PSR_UP_BIT		2
+diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
+index f1663aa..18a4321 100644
+--- a/include/asm-ia64/mca.h
++++ b/include/asm-ia64/mca.h
+@@ -157,6 +157,7 @@ extern void ia64_mca_printk(const char * fmt, ...)
+ struct ia64_mca_notify_die {
+ 	struct ia64_sal_os_state *sos;
+ 	int *monarch_cpu;
++	int *data;
+ };
+ 
+ DECLARE_PER_CPU(u64, ia64_mca_pal_base);
+diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
+index f93308f..7245a57 100644
+--- a/include/asm-ia64/meminit.h
++++ b/include/asm-ia64/meminit.h
+@@ -35,6 +35,7 @@ extern void find_memory (void);
+ extern void reserve_memory (void);
+ extern void find_initrd (void);
+ extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
++extern int filter_memory (unsigned long start, unsigned long end, void *arg);
+ extern unsigned long efi_memmap_init(unsigned long *s, unsigned long *e);
+ extern int find_max_min_low_pfn (unsigned long , unsigned long, void *);
+ 
+@@ -56,7 +57,7 @@ extern int reserve_elfcorehdr(unsigned long *start, unsigned long *end);
+ 
+ #define IGNORE_PFN0	1	/* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
+ 
+-extern int register_active_ranges(u64 start, u64 end, void *arg);
++extern int register_active_ranges(u64 start, u64 len, int nid);
+ 
+ #ifdef CONFIG_VIRTUAL_MEM_MAP
+ # define LARGE_GAP	0x40000000 /* Use virtual mem map if hole is > than this */
+diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
+index 6a8a27c..3499ff5 100644
+--- a/include/asm-ia64/numa.h
++++ b/include/asm-ia64/numa.h
+@@ -22,6 +22,8 @@
+ 
+ #include <asm/mmzone.h>
+ 
++#define NUMA_NO_NODE	-1
++
+ extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+ extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+ extern pg_data_t *pgdat_list[MAX_NUMNODES];
+diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
+index 8a695d3..67b0290 100644
+--- a/include/asm-ia64/pal.h
++++ b/include/asm-ia64/pal.h
+@@ -13,6 +13,7 @@
+  * Copyright (C) 1999 VA Linux Systems
+  * Copyright (C) 1999 Walt Drummond <drummond at valinux.com>
+  * Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad at sprasad.engr.sgi.com>
++ * Copyright (C) 2008 Silicon Graphics, Inc. (SGI)
+  *
+  * 99/10/01	davidm	Make sure we pass zero for reserved parameters.
+  * 00/03/07	davidm	Updated pal_cache_flush() to be in sync with PAL v2.6.
+@@ -73,6 +74,8 @@
+ #define PAL_CACHE_SHARED_INFO	43	/* returns information on caches shared by logical processor */
+ #define PAL_GET_HW_POLICY	48	/* Get current hardware resource sharing policy */
+ #define PAL_SET_HW_POLICY	49	/* Set current hardware resource sharing policy */
++#define PAL_VP_INFO		50	/* Information about virtual processor features */
++#define PAL_MC_HW_TRACKING	51	/* Hardware tracking status */
+ 
+ #define PAL_COPY_PAL		256	/* relocate PAL procedures and PAL PMI */
+ #define PAL_HALT_INFO		257	/* return the low power capabilities of processor */
+@@ -504,7 +507,8 @@ typedef struct pal_cache_check_info_s {
+ 			wiv		: 1,	/* Way field valid */
+ 			reserved2	: 1,
+ 			dp		: 1,	/* Data poisoned on MBE */
+-			reserved3	: 8,
++			reserved3	: 6,
++			hlth		: 2,	/* Health indicator */
+ 
+ 			index		: 20,	/* Cache line index */
+ 			reserved4	: 2,
+@@ -542,7 +546,9 @@ typedef struct pal_tlb_check_info_s {
+ 			dtc		: 1,	/* Fail in data TC */
+ 			itc		: 1,	/* Fail in inst. TC */
+ 			op		: 4,	/* Cache operation */
+-			reserved3	: 30,
++			reserved3	: 6,
++			hlth		: 2,	/* Health indicator */
++			reserved4	: 22,
+ 
+ 			is		: 1,	/* instruction set (1 == ia32) */
+ 			iv		: 1,	/* instruction set field valid */
+@@ -633,7 +639,8 @@ typedef struct pal_uarch_check_info_s {
+ 			way		: 6,	/* Way of structure */
+ 			wv		: 1,	/* way valid */
+ 			xv		: 1,	/* index valid */
+-			reserved1	: 8,
++			reserved1	: 6,
++			hlth		: 2,	/* Health indicator */
+ 			index		: 8,	/* Index or set of the uarch
+ 						 * structure that failed.
+ 						 */
+@@ -1213,14 +1220,12 @@ ia64_pal_mc_drain (void)
+ 
+ /* Return the machine check dynamic processor state */
+ static inline s64
+-ia64_pal_mc_dynamic_state (u64 offset, u64 *size, u64 *pds)
++ia64_pal_mc_dynamic_state (u64 info_type, u64 dy_buffer, u64 *size)
+ {
+ 	struct ia64_pal_retval iprv;
+-	PAL_CALL(iprv, PAL_MC_DYNAMIC_STATE, offset, 0, 0);
++	PAL_CALL(iprv, PAL_MC_DYNAMIC_STATE, info_type, dy_buffer, 0);
+ 	if (size)
+ 		*size = iprv.v0;
+-	if (pds)
+-		*pds = iprv.v1;
+ 	return iprv.status;
+ }
+ 
+@@ -1281,15 +1286,41 @@ ia64_pal_mc_expected (u64 expected, u64 *previous)
+ 	return iprv.status;
+ }
+ 
++typedef union pal_hw_tracking_u {
++	u64			pht_data;
++	struct {
++		u64		itc	:4,	/* Instruction cache tracking */
++				dct	:4,	/* Date cache tracking */
++				itt	:4,	/* Instruction TLB tracking */
++				ddt	:4,	/* Data TLB tracking */
++				reserved:48;
++	} pal_hw_tracking_s;
++} pal_hw_tracking_u_t;
++
++/*
++ * Hardware tracking status.
++ */
++static inline s64
++ia64_pal_mc_hw_tracking (u64 *status)
++{
++	struct ia64_pal_retval iprv;
++	PAL_CALL(iprv, PAL_MC_HW_TRACKING, 0, 0, 0);
++	if (status)
++		*status = iprv.v0;
++	return iprv.status;
++}
++
+ /* Register a platform dependent location with PAL to which it can save
+  * minimal processor state in the event of a machine check or initialization
+  * event.
+  */
+ static inline s64
+-ia64_pal_mc_register_mem (u64 physical_addr)
++ia64_pal_mc_register_mem (u64 physical_addr, u64 size, u64 *req_size)
+ {
+ 	struct ia64_pal_retval iprv;
+-	PAL_CALL(iprv, PAL_MC_REGISTER_MEM, physical_addr, 0, 0);
++	PAL_CALL(iprv, PAL_MC_REGISTER_MEM, physical_addr, size, 0);
++	if (req_size)
++		*req_size = iprv.v0;
+ 	return iprv.status;
+ }
+ 
+@@ -1631,6 +1662,29 @@ ia64_pal_vm_summary (pal_vm_info_1_u_t *vm_info_1, pal_vm_info_2_u_t *vm_info_2)
+ 	return iprv.status;
+ }
+ 
++typedef union pal_vp_info_u {
++	u64			pvi_val;
++	struct {
++		u64		index:		48,	/* virtual feature set info */
++				vmm_id:		16;	/* feature set id */
++	} pal_vp_info_s;
++} pal_vp_info_u_t;
++
++/*
++ * Returns infomation about virtual processor features
++ */
++static inline s64
++ia64_pal_vp_info (u64 feature_set, u64 vp_buffer, u64 *vp_info, u64 *vmm_id)
++{
++	struct ia64_pal_retval iprv;
++	PAL_CALL(iprv, PAL_VP_INFO, feature_set, vp_buffer, 0);
++	if (vp_info)
++		*vp_info = iprv.v0;
++	if (vmm_id)
++		*vmm_id = iprv.v1;
++	return iprv.status;
++}
++
+ typedef union pal_itr_valid_u {
+ 	u64			piv_val;
+ 	struct {
+diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
+index e6204f1..ed70862 100644
+--- a/include/asm-ia64/pgtable.h
++++ b/include/asm-ia64/pgtable.h
+@@ -371,7 +371,7 @@ pgd_index (unsigned long address)
+ /* The offset in the 1-level directory is given by the 3 region bits
+    (61..63) and the level-1 bits.  */
+ static inline pgd_t*
+-pgd_offset (struct mm_struct *mm, unsigned long address)
++pgd_offset (const struct mm_struct *mm, unsigned long address)
+ {
+ 	return mm->pgd + pgd_index(address);
+ }
+diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
+index f4904db..89594b4 100644
+--- a/include/asm-ia64/sal.h
++++ b/include/asm-ia64/sal.h
+@@ -296,6 +296,9 @@ enum {
+     EFI_GUID(0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
+ #define SAL_PLAT_BUS_ERR_SECT_GUID  \
+     EFI_GUID(0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
++#define PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID \
++    EFI_GUID(0x6cb0a200, 0x893a, 0x11da, 0x96, 0xd2, 0x0, 0x10, 0x83, 0xff, \
++		0xca, 0x4d)
+ 
+ #define MAX_CACHE_ERRORS	6
+ #define MAX_TLB_ERRORS		6
+@@ -879,6 +882,24 @@ extern void ia64_jump_to_sal(struct sal_to_os_boot *);
+ 
+ extern void ia64_sal_handler_init(void *entry_point, void *gpval);
+ 
++#define PALO_MAX_TLB_PURGES	0xFFFF
++#define PALO_SIG	"PALO"
++
++struct palo_table {
++	u8  signature[4];	/* Should be "PALO" */
++	u32 length;
++	u8  minor_revision;
++	u8  major_revision;
++	u8  checksum;
++	u8  reserved1[5];
++	u16 max_tlb_purges;
++	u8  reserved2[6];
++};
++
++#define NPTCG_FROM_PAL			0
++#define NPTCG_FROM_PALO			1
++#define NPTCG_FROM_KERNEL_PARAMETER	2
++
+ #endif /* __ASSEMBLY__ */
+ 
+ #endif /* _ASM_IA64_SAL_H */
+diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h
+index d8393d1..d9b2034 100644
+--- a/include/asm-ia64/semaphore.h
++++ b/include/asm-ia64/semaphore.h
+@@ -1,99 +1 @@
+-#ifndef _ASM_IA64_SEMAPHORE_H
+-#define _ASM_IA64_SEMAPHORE_H
+-
+-/*
+- * Copyright (C) 1998-2000 Hewlett-Packard Co
+- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm at hpl.hp.com>
+- */
+-
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/atomic.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.sleepers	= 0,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count)					\
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
+-
+-#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name, 1)
+-
+-static inline void
+-sema_init (struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void
+-init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void
+-init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-extern void __down (struct semaphore * sem);
+-extern int  __down_interruptible (struct semaphore * sem);
+-extern int  __down_trylock (struct semaphore * sem);
+-extern void __up (struct semaphore * sem);
+-
+-/*
+- * Atomically decrement the semaphore's count.  If it goes negative,
+- * block the calling thread in the TASK_UNINTERRUPTIBLE state.
+- */
+-static inline void
+-down (struct semaphore *sem)
+-{
+-	might_sleep();
+-	if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
+-		__down(sem);
+-}
+-
+-/*
+- * Atomically decrement the semaphore's count.  If it goes negative,
+- * block the calling thread in the TASK_INTERRUPTIBLE state.
+- */
+-static inline int
+-down_interruptible (struct semaphore * sem)
+-{
+-	int ret = 0;
+-
+-	might_sleep();
+-	if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
+-		ret = __down_interruptible(sem);
+-	return ret;
+-}
+-
+-static inline int
+-down_trylock (struct semaphore *sem)
+-{
+-	int ret = 0;
+-
+-	if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
+-		ret = __down_trylock(sem);
+-	return ret;
+-}
+-
+-static inline void
+-up (struct semaphore * sem)
+-{
+-	if (ia64_fetchadd(1, &sem->count.counter, rel) <= -1)
+-		__up(sem);
+-}
+-
+-#endif /* _ASM_IA64_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
+index 4fa733d..ec5f355 100644
+--- a/include/asm-ia64/smp.h
++++ b/include/asm-ia64/smp.h
+@@ -38,6 +38,9 @@ ia64_get_lid (void)
+ 	return lid.f.id << 8 | lid.f.eid;
+ }
+ 
++extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
++				  void *info, int wait);
++
+ #define hard_smp_processor_id()		ia64_get_lid()
+ 
+ #ifdef CONFIG_SMP
+diff --git a/include/asm-ia64/sn/nodepda.h b/include/asm-ia64/sn/nodepda.h
+index 6f6d69e..ee118b9 100644
+--- a/include/asm-ia64/sn/nodepda.h
++++ b/include/asm-ia64/sn/nodepda.h
+@@ -9,7 +9,6 @@
+ #define _ASM_IA64_SN_NODEPDA_H
+ 
+ 
+-#include <asm/semaphore.h>
+ #include <asm/irq.h>
+ #include <asm/sn/arch.h>
+ #include <asm/sn/intr.h>
+diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
+deleted file mode 100644
+index f7711b3..0000000
+--- a/include/asm-ia64/sn/xp.h
++++ /dev/null
+@@ -1,485 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 2004-2005 Silicon Graphics, Inc. All rights reserved.
+- */
+-
+-
+-/*
+- * External Cross Partition (XP) structures and defines.
+- */
+-
+-
+-#ifndef _ASM_IA64_SN_XP_H
+-#define _ASM_IA64_SN_XP_H
+-
+-
+-#include <linux/cache.h>
+-#include <linux/hardirq.h>
+-#include <linux/mutex.h>
+-#include <asm/sn/types.h>
+-#include <asm/sn/bte.h>
+-
+-
+-#ifdef USE_DBUG_ON
+-#define DBUG_ON(condition)	BUG_ON(condition)
+-#else
+-#define DBUG_ON(condition)
+-#endif
+-
+-
+-/*
+- * Define the maximum number of logically defined partitions the system
+- * can support. It is constrained by the maximum number of hardware
+- * partitionable regions. The term 'region' in this context refers to the
+- * minimum number of nodes that can comprise an access protection grouping.
+- * The access protection is in regards to memory, IPI and IOI.
+- *
+- * The maximum number of hardware partitionable regions is equal to the
+- * maximum number of nodes in the entire system divided by the minimum number
+- * of nodes that comprise an access protection grouping.
+- */
+-#define XP_MAX_PARTITIONS	64
+-
+-
+-/*
+- * Define the number of u64s required to represent all the C-brick nasids
+- * as a bitmap.  The cross-partition kernel modules deal only with
+- * C-brick nasids, thus the need for bitmaps which don't account for
+- * odd-numbered (non C-brick) nasids.
+- */
+-#define XP_MAX_PHYSNODE_ID	(MAX_NUMALINK_NODES / 2)
+-#define XP_NASID_MASK_BYTES	((XP_MAX_PHYSNODE_ID + 7) / 8)
+-#define XP_NASID_MASK_WORDS	((XP_MAX_PHYSNODE_ID + 63) / 64)
+-
+-
+-/*
+- * Wrapper for bte_copy() that should it return a failure status will retry
+- * the bte_copy() once in the hope that the failure was due to a temporary
+- * aberration (i.e., the link going down temporarily).
+- *
+- * 	src - physical address of the source of the transfer.
+- *	vdst - virtual address of the destination of the transfer.
+- *	len - number of bytes to transfer from source to destination.
+- *	mode - see bte_copy() for definition.
+- *	notification - see bte_copy() for definition.
+- *
+- * Note: xp_bte_copy() should never be called while holding a spinlock.
+- */
+-static inline bte_result_t
+-xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification)
+-{
+-	bte_result_t ret;
+-	u64 pdst = ia64_tpa(vdst);
+-
+-
+-	/*
+-	 * Ensure that the physically mapped memory is contiguous.
+-	 *
+-	 * We do this by ensuring that the memory is from region 7 only.
+-	 * If the need should arise to use memory from one of the other
+-	 * regions, then modify the BUG_ON() statement to ensure that the
+-	 * memory from that region is always physically contiguous.
+-	 */
+-	BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL);
+-
+-	ret = bte_copy(src, pdst, len, mode, notification);
+-	if ((ret != BTE_SUCCESS) && BTE_ERROR_RETRY(ret)) {
+-		if (!in_interrupt()) {
+-			cond_resched();
+-		}
+-		ret = bte_copy(src, pdst, len, mode, notification);
+-	}
+-
+-	return ret;
+-}
+-
+-
+-/*
+- * XPC establishes channel connections between the local partition and any
+- * other partition that is currently up. Over these channels, kernel-level
+- * `users' can communicate with their counterparts on the other partitions.
+- *
+- * The maxinum number of channels is limited to eight. For performance reasons,
+- * the internal cross partition structures require sixteen bytes per channel,
+- * and eight allows all of this interface-shared info to fit in one cache line.
+- *
+- * XPC_NCHANNELS reflects the total number of channels currently defined.
+- * If the need for additional channels arises, one can simply increase
+- * XPC_NCHANNELS accordingly. If the day should come where that number
+- * exceeds the MAXIMUM number of channels allowed (eight), then one will need
+- * to make changes to the XPC code to allow for this.
+- */
+-#define XPC_MEM_CHANNEL		0	/* memory channel number */
+-#define	XPC_NET_CHANNEL		1	/* network channel number */
+-
+-#define	XPC_NCHANNELS		2	/* #of defined channels */
+-#define XPC_MAX_NCHANNELS	8	/* max #of channels allowed */
+-
+-#if XPC_NCHANNELS > XPC_MAX_NCHANNELS
+-#error	XPC_NCHANNELS exceeds MAXIMUM allowed.
+-#endif
+-
+-
+-/*
+- * The format of an XPC message is as follows:
+- *
+- *      +-------+--------------------------------+
+- *      | flags |////////////////////////////////|
+- *      +-------+--------------------------------+
+- *      |             message #                  |
+- *      +----------------------------------------+
+- *      |     payload (user-defined message)     |
+- *      |                                        |
+- *         		:
+- *      |                                        |
+- *      +----------------------------------------+
+- *
+- * The size of the payload is defined by the user via xpc_connect(). A user-
+- * defined message resides in the payload area.
+- *
+- * The user should have no dealings with the message header, but only the
+- * message's payload. When a message entry is allocated (via xpc_allocate())
+- * a pointer to the payload area is returned and not the actual beginning of
+- * the XPC message. The user then constructs a message in the payload area
+- * and passes that pointer as an argument on xpc_send() or xpc_send_notify().
+- *
+- * The size of a message entry (within a message queue) must be a cacheline
+- * sized multiple in order to facilitate the BTE transfer of messages from one
+- * message queue to another. A macro, XPC_MSG_SIZE(), is provided for the user
+- * that wants to fit as many msg entries as possible in a given memory size
+- * (e.g. a memory page).
+- */
+-struct xpc_msg {
+-	u8 flags;		/* FOR XPC INTERNAL USE ONLY */
+-	u8 reserved[7];		/* FOR XPC INTERNAL USE ONLY */
+-	s64 number;		/* FOR XPC INTERNAL USE ONLY */
+-
+-	u64 payload;		/* user defined portion of message */
+-};
+-
+-
+-#define XPC_MSG_PAYLOAD_OFFSET	(u64) (&((struct xpc_msg *)0)->payload)
+-#define XPC_MSG_SIZE(_payload_size) \
+-		L1_CACHE_ALIGN(XPC_MSG_PAYLOAD_OFFSET + (_payload_size))
+-
+-
+-/*
+- * Define the return values and values passed to user's callout functions.
+- * (It is important to add new value codes at the end just preceding
+- * xpcUnknownReason, which must have the highest numerical value.)
+- */
+-enum xpc_retval {
+-	xpcSuccess = 0,
+-
+-	xpcNotConnected,	/*  1: channel is not connected */
+-	xpcConnected,		/*  2: channel connected (opened) */
+-	xpcRETIRED1,		/*  3: (formerly xpcDisconnected) */
+-
+-	xpcMsgReceived,		/*  4: message received */
+-	xpcMsgDelivered,	/*  5: message delivered and acknowledged */
+-
+-	xpcRETIRED2,		/*  6: (formerly xpcTransferFailed) */
+-
+-	xpcNoWait,		/*  7: operation would require wait */
+-	xpcRetry,		/*  8: retry operation */
+-	xpcTimeout,		/*  9: timeout in xpc_allocate_msg_wait() */
+-	xpcInterrupted,		/* 10: interrupted wait */
+-
+-	xpcUnequalMsgSizes,	/* 11: message size disparity between sides */
+-	xpcInvalidAddress,	/* 12: invalid address */
+-
+-	xpcNoMemory,		/* 13: no memory available for XPC structures */
+-	xpcLackOfResources,	/* 14: insufficient resources for operation */
+-	xpcUnregistered,	/* 15: channel is not registered */
+-	xpcAlreadyRegistered,	/* 16: channel is already registered */
+-
+-	xpcPartitionDown,	/* 17: remote partition is down */
+-	xpcNotLoaded,		/* 18: XPC module is not loaded */
+-	xpcUnloading,		/* 19: this side is unloading XPC module */
+-
+-	xpcBadMagic,		/* 20: XPC MAGIC string not found */
+-
+-	xpcReactivating,	/* 21: remote partition was reactivated */
+-
+-	xpcUnregistering,	/* 22: this side is unregistering channel */
+-	xpcOtherUnregistering,	/* 23: other side is unregistering channel */
+-
+-	xpcCloneKThread,	/* 24: cloning kernel thread */
+-	xpcCloneKThreadFailed,	/* 25: cloning kernel thread failed */
+-
+-	xpcNoHeartbeat,		/* 26: remote partition has no heartbeat */
+-
+-	xpcPioReadError,	/* 27: PIO read error */
+-	xpcPhysAddrRegFailed,	/* 28: registration of phys addr range failed */
+-
+-	xpcBteDirectoryError,	/* 29: maps to BTEFAIL_DIR */
+-	xpcBtePoisonError,	/* 30: maps to BTEFAIL_POISON */
+-	xpcBteWriteError,	/* 31: maps to BTEFAIL_WERR */
+-	xpcBteAccessError,	/* 32: maps to BTEFAIL_ACCESS */
+-	xpcBtePWriteError,	/* 33: maps to BTEFAIL_PWERR */
+-	xpcBtePReadError,	/* 34: maps to BTEFAIL_PRERR */
+-	xpcBteTimeOutError,	/* 35: maps to BTEFAIL_TOUT */
+-	xpcBteXtalkError,	/* 36: maps to BTEFAIL_XTERR */
+-	xpcBteNotAvailable,	/* 37: maps to BTEFAIL_NOTAVAIL */
+-	xpcBteUnmappedError,	/* 38: unmapped BTEFAIL_ error */
+-
+-	xpcBadVersion,		/* 39: bad version number */
+-	xpcVarsNotSet,		/* 40: the XPC variables are not set up */
+-	xpcNoRsvdPageAddr,	/* 41: unable to get rsvd page's phys addr */
+-	xpcInvalidPartid,	/* 42: invalid partition ID */
+-	xpcLocalPartid,		/* 43: local partition ID */
+-
+-	xpcOtherGoingDown,	/* 44: other side going down, reason unknown */
+-	xpcSystemGoingDown,	/* 45: system is going down, reason unknown */
+-	xpcSystemHalt,		/* 46: system is being halted */
+-	xpcSystemReboot,	/* 47: system is being rebooted */
+-	xpcSystemPoweroff,	/* 48: system is being powered off */
+-
+-	xpcDisconnecting,	/* 49: channel disconnecting (closing) */
+-
+-	xpcOpenCloseError,	/* 50: channel open/close protocol error */
+-
+-	xpcDisconnected,	/* 51: channel disconnected (closed) */
+-
+-	xpcBteSh2Start,		/* 52: BTE CRB timeout */
+-
+-				/* 53: 0x1 BTE Error Response Short */
+-	xpcBteSh2RspShort = xpcBteSh2Start + BTEFAIL_SH2_RESP_SHORT,
+-
+-				/* 54: 0x2 BTE Error Response Long */
+-	xpcBteSh2RspLong = xpcBteSh2Start + BTEFAIL_SH2_RESP_LONG,
+-
+-				/* 56: 0x4 BTE Error Response DSB */
+-	xpcBteSh2RspDSB = xpcBteSh2Start + BTEFAIL_SH2_RESP_DSP,
+-
+-				/* 60: 0x8 BTE Error Response Access */
+-	xpcBteSh2RspAccess = xpcBteSh2Start + BTEFAIL_SH2_RESP_ACCESS,
+-
+-				/* 68: 0x10 BTE Error CRB timeout */
+-	xpcBteSh2CRBTO = xpcBteSh2Start + BTEFAIL_SH2_CRB_TO,
+-
+-				/* 84: 0x20 BTE Error NACK limit */
+-	xpcBteSh2NACKLimit = xpcBteSh2Start + BTEFAIL_SH2_NACK_LIMIT,
+-
+-				/* 115: BTE end */
+-	xpcBteSh2End = xpcBteSh2Start + BTEFAIL_SH2_ALL,
+-
+-	xpcUnknownReason	/* 116: unknown reason -- must be last in list */
+-};
+-
+-
+-/*
+- * Define the callout function types used by XPC to update the user on
+- * connection activity and state changes (via the user function registered by
+- * xpc_connect()) and to notify them of messages received and delivered (via
+- * the user function registered by xpc_send_notify()).
+- *
+- * The two function types are xpc_channel_func and xpc_notify_func and
+- * both share the following arguments, with the exception of "data", which
+- * only xpc_channel_func has.
+- *
+- * Arguments:
+- *
+- *	reason - reason code. (See following table.)
+- *	partid - partition ID associated with condition.
+- *	ch_number - channel # associated with condition.
+- *	data - pointer to optional data. (See following table.)
+- *	key - pointer to optional user-defined value provided as the "key"
+- *	      argument to xpc_connect() or xpc_send_notify().
+- *
+- * In the following table the "Optional Data" column applies to callouts made
+- * to functions registered by xpc_connect(). A "NA" in that column indicates
+- * that this reason code can be passed to functions registered by
+- * xpc_send_notify() (i.e. they don't have data arguments).
+- *
+- * Also, the first three reason codes in the following table indicate
+- * success, whereas the others indicate failure. When a failure reason code
+- * is received, one can assume that the channel is not connected.
+- *
+- *
+- * Reason Code          | Cause                          | Optional Data
+- * =====================+================================+=====================
+- * xpcConnected         | connection has been established| max #of entries
+- *                      | to the specified partition on  | allowed in message
+- *                      | the specified channel          | queue
+- * ---------------------+--------------------------------+---------------------
+- * xpcMsgReceived       | an XPC message arrived from    | address of payload
+- *                      | the specified partition on the |
+- *                      | specified channel              | [the user must call
+- *                      |                                | xpc_received() when
+- *                      |                                | finished with the
+- *                      |                                | payload]
+- * ---------------------+--------------------------------+---------------------
+- * xpcMsgDelivered      | notification that the message  | NA
+- *                      | was delivered to the intended  |
+- *                      | recipient and that they have   |
+- *                      | acknowledged its receipt by    |
+- *                      | calling xpc_received()         |
+- * =====================+================================+=====================
+- * xpcUnequalMsgSizes   | can't connect to the specified | NULL
+- *                      | partition on the specified     |
+- *                      | channel because of mismatched  |
+- *                      | message sizes                  |
+- * ---------------------+--------------------------------+---------------------
+- * xpcNoMemory          | insufficient memory avaiable   | NULL
+- *                      | to allocate message queue      |
+- * ---------------------+--------------------------------+---------------------
+- * xpcLackOfResources   | lack of resources to create    | NULL
+- *                      | the necessary kthreads to      |
+- *                      | support the channel            |
+- * ---------------------+--------------------------------+---------------------
+- * xpcUnregistering     | this side's user has           | NULL or NA
+- *                      | unregistered by calling        |
+- *                      | xpc_disconnect()               |
+- * ---------------------+--------------------------------+---------------------
+- * xpcOtherUnregistering| the other side's user has      | NULL or NA
+- *                      | unregistered by calling        |
+- *                      | xpc_disconnect()               |
+- * ---------------------+--------------------------------+---------------------
+- * xpcNoHeartbeat       | the other side's XPC is no     | NULL or NA
+- *                      | longer heartbeating            |
+- *                      |                                |
+- * ---------------------+--------------------------------+---------------------
+- * xpcUnloading         | this side's XPC module is      | NULL or NA
+- *                      | being unloaded                 |
+- *                      |                                |
+- * ---------------------+--------------------------------+---------------------
+- * xpcOtherUnloading    | the other side's XPC module is | NULL or NA
+- *                      | is being unloaded              |
+- *                      |                                |
+- * ---------------------+--------------------------------+---------------------
+- * xpcPioReadError      | xp_nofault_PIOR() returned an  | NULL or NA
+- *                      | error while sending an IPI     |
+- *                      |                                |
+- * ---------------------+--------------------------------+---------------------
+- * xpcInvalidAddress    | the address either received or | NULL or NA
+- *                      | sent by the specified partition|
+- *                      | is invalid                     |
+- * ---------------------+--------------------------------+---------------------
+- * xpcBteNotAvailable   | attempt to pull data from the  | NULL or NA
+- * xpcBtePoisonError    | specified partition over the   |
+- * xpcBteWriteError     | specified channel via a        |
+- * xpcBteAccessError    | bte_copy() failed              |
+- * xpcBteTimeOutError   |                                |
+- * xpcBteXtalkError     |                                |
+- * xpcBteDirectoryError |                                |
+- * xpcBteGenericError   |                                |
+- * xpcBteUnmappedError  |                                |
+- * ---------------------+--------------------------------+---------------------
+- * xpcUnknownReason     | the specified channel to the   | NULL or NA
+- *                      | specified partition was        |
+- *                      | unavailable for unknown reasons|
+- * =====================+================================+=====================
+- */
+-
+-typedef void (*xpc_channel_func)(enum xpc_retval reason, partid_t partid,
+-		int ch_number, void *data, void *key);
+-
+-typedef void (*xpc_notify_func)(enum xpc_retval reason, partid_t partid,
+-		int ch_number, void *key);
+-
+-
+-/*
+- * The following is a registration entry. There is a global array of these,
+- * one per channel. It is used to record the connection registration made
+- * by the users of XPC. As long as a registration entry exists, for any
+- * partition that comes up, XPC will attempt to establish a connection on
+- * that channel. Notification that a connection has been made will occur via
+- * the xpc_channel_func function.
+- *
+- * The 'func' field points to the function to call when aynchronous
+- * notification is required for such events as: a connection established/lost,
+- * or an incoming message received, or an error condition encountered. A
+- * non-NULL 'func' field indicates that there is an active registration for
+- * the channel.
+- */
+-struct xpc_registration {
+-	struct mutex mutex;
+-	xpc_channel_func func;		/* function to call */
+-	void *key;			/* pointer to user's key */
+-	u16 nentries;			/* #of msg entries in local msg queue */
+-	u16 msg_size;			/* message queue's message size */
+-	u32 assigned_limit;		/* limit on #of assigned kthreads */
+-	u32 idle_limit;			/* limit on #of idle kthreads */
+-} ____cacheline_aligned;
+-
+-
+-#define XPC_CHANNEL_REGISTERED(_c)	(xpc_registrations[_c].func != NULL)
+-
+-
+-/* the following are valid xpc_allocate() flags */
+-#define XPC_WAIT	0		/* wait flag */
+-#define XPC_NOWAIT	1		/* no wait flag */
+-
+-
+-struct xpc_interface {
+-	void (*connect)(int);
+-	void (*disconnect)(int);
+-	enum xpc_retval (*allocate)(partid_t, int, u32, void **);
+-	enum xpc_retval (*send)(partid_t, int, void *);
+-	enum xpc_retval (*send_notify)(partid_t, int, void *,
+-						xpc_notify_func, void *);
+-	void (*received)(partid_t, int, void *);
+-	enum xpc_retval (*partid_to_nasids)(partid_t, void *);
+-};
+-
+-
+-extern struct xpc_interface xpc_interface;
+-
+-extern void xpc_set_interface(void (*)(int),
+-		void (*)(int),
+-		enum xpc_retval (*)(partid_t, int, u32, void **),
+-		enum xpc_retval (*)(partid_t, int, void *),
+-		enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func,
+-								void *),
+-		void (*)(partid_t, int, void *),
+-		enum xpc_retval (*)(partid_t, void *));
+-extern void xpc_clear_interface(void);
+-
+-
+-extern enum xpc_retval xpc_connect(int, xpc_channel_func, void *, u16,
+-						u16, u32, u32);
+-extern void xpc_disconnect(int);
+-
+-static inline enum xpc_retval
+-xpc_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
+-{
+-	return xpc_interface.allocate(partid, ch_number, flags, payload);
+-}
+-
+-static inline enum xpc_retval
+-xpc_send(partid_t partid, int ch_number, void *payload)
+-{
+-	return xpc_interface.send(partid, ch_number, payload);
+-}
+-
+-static inline enum xpc_retval
+-xpc_send_notify(partid_t partid, int ch_number, void *payload,
+-			xpc_notify_func func, void *key)
+-{
+-	return xpc_interface.send_notify(partid, ch_number, payload, func, key);
+-}
+-
+-static inline void
+-xpc_received(partid_t partid, int ch_number, void *payload)
+-{
+-	return xpc_interface.received(partid, ch_number, payload);
+-}
+-
+-static inline enum xpc_retval
+-xpc_partid_to_nasids(partid_t partid, void *nasids)
+-{
+-	return xpc_interface.partid_to_nasids(partid, nasids);
+-}
+-
+-
+-extern u64 xp_nofault_PIOR_target;
+-extern int xp_nofault_PIOR(void *);
+-extern int xp_error_PIOR(void);
+-
+-
+-#endif /* _ASM_IA64_SN_XP_H */
+-
+diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
+deleted file mode 100644
+index 3c0900a..0000000
+--- a/include/asm-ia64/sn/xpc.h
++++ /dev/null
+@@ -1,1267 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2007 Silicon Graphics, Inc.  All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Communication (XPC) structures and macros.
+- */
+-
+-#ifndef _ASM_IA64_SN_XPC_H
+-#define _ASM_IA64_SN_XPC_H
+-
+-
+-#include <linux/interrupt.h>
+-#include <linux/sysctl.h>
+-#include <linux/device.h>
+-#include <linux/mutex.h>
+-#include <linux/completion.h>
+-#include <asm/pgtable.h>
+-#include <asm/processor.h>
+-#include <asm/sn/bte.h>
+-#include <asm/sn/clksupport.h>
+-#include <asm/sn/addrs.h>
+-#include <asm/sn/mspec.h>
+-#include <asm/sn/shub_mmr.h>
+-#include <asm/sn/xp.h>
+-
+-
+-/*
+- * XPC Version numbers consist of a major and minor number. XPC can always
+- * talk to versions with same major #, and never talk to versions with a
+- * different major #.
+- */
+-#define _XPC_VERSION(_maj, _min)	(((_maj) << 4) | ((_min) & 0xf))
+-#define XPC_VERSION_MAJOR(_v)		((_v) >> 4)
+-#define XPC_VERSION_MINOR(_v)		((_v) & 0xf)
+-
+-
+-/*
+- * The next macros define word or bit representations for given
+- * C-brick nasid in either the SAL provided bit array representing
+- * nasids in the partition/machine or the AMO_t array used for
+- * inter-partition initiation communications.
+- *
+- * For SN2 machines, C-Bricks are alway even numbered NASIDs.  As
+- * such, some space will be saved by insisting that nasid information
+- * passed from SAL always be packed for C-Bricks and the
+- * cross-partition interrupts use the same packing scheme.
+- */
+-#define XPC_NASID_W_INDEX(_n)	(((_n) / 64) / 2)
+-#define XPC_NASID_B_INDEX(_n)	(((_n) / 2) & (64 - 1))
+-#define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \
+-				    (1UL << XPC_NASID_B_INDEX(_n)))
+-#define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
+-
+-#define XPC_HB_DEFAULT_INTERVAL		5	/* incr HB every x secs */
+-#define XPC_HB_CHECK_DEFAULT_INTERVAL	20	/* check HB every x secs */
+-
+-/* define the process name of HB checker and the CPU it is pinned to */
+-#define XPC_HB_CHECK_THREAD_NAME	"xpc_hb"
+-#define XPC_HB_CHECK_CPU		0
+-
+-/* define the process name of the discovery thread */
+-#define XPC_DISCOVERY_THREAD_NAME	"xpc_discovery"
+-
+-
+-/*
+- * the reserved page
+- *
+- *   SAL reserves one page of memory per partition for XPC. Though a full page
+- *   in length (16384 bytes), its starting address is not page aligned, but it
+- *   is cacheline aligned. The reserved page consists of the following:
+- *
+- *   reserved page header
+- *
+- *     The first cacheline of the reserved page contains the header
+- *     (struct xpc_rsvd_page). Before SAL initialization has completed,
+- *     SAL has set up the following fields of the reserved page header:
+- *     SAL_signature, SAL_version, partid, and nasids_size. The other
+- *     fields are set up by XPC. (xpc_rsvd_page points to the local
+- *     partition's reserved page.)
+- *
+- *   part_nasids mask
+- *   mach_nasids mask
+- *
+- *     SAL also sets up two bitmaps (or masks), one that reflects the actual
+- *     nasids in this partition (part_nasids), and the other that reflects
+- *     the actual nasids in the entire machine (mach_nasids). We're only
+- *     interested in the even numbered nasids (which contain the processors
+- *     and/or memory), so we only need half as many bits to represent the
+- *     nasids. The part_nasids mask is located starting at the first cacheline
+- *     following the reserved page header. The mach_nasids mask follows right
+- *     after the part_nasids mask. The size in bytes of each mask is reflected
+- *     by the reserved page header field 'nasids_size'. (Local partition's
+- *     mask pointers are xpc_part_nasids and xpc_mach_nasids.)
+- *
+- *   vars
+- *   vars part
+- *
+- *     Immediately following the mach_nasids mask are the XPC variables
+- *     required by other partitions. First are those that are generic to all
+- *     partitions (vars), followed on the next available cacheline by those
+- *     which are partition specific (vars part). These are setup by XPC.
+- *     (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
+- *
+- * Note: Until vars_pa is set, the partition XPC code has not been initialized.
+- */
+-struct xpc_rsvd_page {
+-	u64 SAL_signature;	/* SAL: unique signature */
+-	u64 SAL_version;	/* SAL: version */
+-	u8 partid;		/* SAL: partition ID */
+-	u8 version;
+-	u8 pad1[6];		/* align to next u64 in cacheline */
+-	volatile u64 vars_pa;
+-	struct timespec stamp;	/* time when reserved page was setup by XPC */
+-	u64 pad2[9];		/* align to last u64 in cacheline */
+-	u64 nasids_size;	/* SAL: size of each nasid mask in bytes */
+-};
+-
+-#define XPC_RP_VERSION _XPC_VERSION(1,1) /* version 1.1 of the reserved page */
+-
+-#define XPC_SUPPORTS_RP_STAMP(_version) \
+-			(_version >= _XPC_VERSION(1,1))
+-
+-/*
+- * compare stamps - the return value is:
+- *
+- *	< 0,	if stamp1 < stamp2
+- *	= 0,	if stamp1 == stamp2
+- *	> 0,	if stamp1 > stamp2
+- */
+-static inline int
+-xpc_compare_stamps(struct timespec *stamp1, struct timespec *stamp2)
+-{
+-	int ret;
+-
+-
+-	if ((ret = stamp1->tv_sec - stamp2->tv_sec) == 0) {
+-		ret = stamp1->tv_nsec - stamp2->tv_nsec;
+-	}
+-	return ret;
+-}
+-
+-
+-/*
+- * Define the structures by which XPC variables can be exported to other
+- * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
+- */
+-
+-/*
+- * The following structure describes the partition generic variables
+- * needed by other partitions in order to properly initialize.
+- *
+- * struct xpc_vars version number also applies to struct xpc_vars_part.
+- * Changes to either structure and/or related functionality should be
+- * reflected by incrementing either the major or minor version numbers
+- * of struct xpc_vars.
+- */
+-struct xpc_vars {
+-	u8 version;
+-	u64 heartbeat;
+-	u64 heartbeating_to_mask;
+-	u64 heartbeat_offline;	/* if 0, heartbeat should be changing */
+-	int act_nasid;
+-	int act_phys_cpuid;
+-	u64 vars_part_pa;
+-	u64 amos_page_pa;	/* paddr of page of AMOs from MSPEC driver */
+-	AMO_t *amos_page;	/* vaddr of page of AMOs from MSPEC driver */
+-};
+-
+-#define XPC_V_VERSION _XPC_VERSION(3,1) /* version 3.1 of the cross vars */
+-
+-#define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \
+-			(_version >= _XPC_VERSION(3,1))
+-
+-
+-static inline int
+-xpc_hb_allowed(partid_t partid, struct xpc_vars *vars)
+-{
+-	return ((vars->heartbeating_to_mask & (1UL << partid)) != 0);
+-}
+-
+-static inline void
+-xpc_allow_hb(partid_t partid, struct xpc_vars *vars)
+-{
+-	u64 old_mask, new_mask;
+-
+-	do {
+-		old_mask = vars->heartbeating_to_mask;
+-		new_mask = (old_mask | (1UL << partid));
+-	} while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
+-							old_mask);
+-}
+-
+-static inline void
+-xpc_disallow_hb(partid_t partid, struct xpc_vars *vars)
+-{
+-	u64 old_mask, new_mask;
+-
+-	do {
+-		old_mask = vars->heartbeating_to_mask;
+-		new_mask = (old_mask & ~(1UL << partid));
+-	} while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
+-							old_mask);
+-}
+-
+-
+-/*
+- * The AMOs page consists of a number of AMO variables which are divided into
+- * four groups, The first two groups are used to identify an IRQ's sender.
+- * These two groups consist of 64 and 128 AMO variables respectively. The last
+- * two groups, consisting of just one AMO variable each, are used to identify
+- * the remote partitions that are currently engaged (from the viewpoint of
+- * the XPC running on the remote partition).
+- */
+-#define XPC_NOTIFY_IRQ_AMOS	   0
+-#define XPC_ACTIVATE_IRQ_AMOS	   (XPC_NOTIFY_IRQ_AMOS + XP_MAX_PARTITIONS)
+-#define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS)
+-#define XPC_DISENGAGE_REQUEST_AMO  (XPC_ENGAGED_PARTITIONS_AMO + 1)
+-
+-
+-/*
+- * The following structure describes the per partition specific variables.
+- *
+- * An array of these structures, one per partition, will be defined. As a
+- * partition becomes active XPC will copy the array entry corresponding to
+- * itself from that partition. It is desirable that the size of this
+- * structure evenly divide into a cacheline, such that none of the entries
+- * in this array crosses a cacheline boundary. As it is now, each entry
+- * occupies half a cacheline.
+- */
+-struct xpc_vars_part {
+-	volatile u64 magic;
+-
+-	u64 openclose_args_pa;	/* physical address of open and close args */
+-	u64 GPs_pa;		/* physical address of Get/Put values */
+-
+-	u64 IPI_amo_pa;		/* physical address of IPI AMO_t structure */
+-	int IPI_nasid;		/* nasid of where to send IPIs */
+-	int IPI_phys_cpuid;	/* physical CPU ID of where to send IPIs */
+-
+-	u8 nchannels;		/* #of defined channels supported */
+-
+-	u8 reserved[23];	/* pad to a full 64 bytes */
+-};
+-
+-/*
+- * The vars_part MAGIC numbers play a part in the first contact protocol.
+- *
+- * MAGIC1 indicates that the per partition specific variables for a remote
+- * partition have been initialized by this partition.
+- *
+- * MAGIC2 indicates that this partition has pulled the remote partititions
+- * per partition variables that pertain to this partition.
+- */
+-#define XPC_VP_MAGIC1	0x0053524156435058L  /* 'XPCVARS\0'L (little endian) */
+-#define XPC_VP_MAGIC2	0x0073726176435058L  /* 'XPCvars\0'L (little endian) */
+-
+-
+-/* the reserved page sizes and offsets */
+-
+-#define XPC_RP_HEADER_SIZE	L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
+-#define XPC_RP_VARS_SIZE 	L1_CACHE_ALIGN(sizeof(struct xpc_vars))
+-
+-#define XPC_RP_PART_NASIDS(_rp) (u64 *) ((u8 *) _rp + XPC_RP_HEADER_SIZE)
+-#define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words)
+-#define XPC_RP_VARS(_rp)	((struct xpc_vars *) XPC_RP_MACH_NASIDS(_rp) + xp_nasid_mask_words)
+-#define XPC_RP_VARS_PART(_rp)	(struct xpc_vars_part *) ((u8 *) XPC_RP_VARS(rp) + XPC_RP_VARS_SIZE)
+-
+-
+-/*
+- * Functions registered by add_timer() or called by kernel_thread() only
+- * allow for a single 64-bit argument. The following macros can be used to
+- * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
+- * the passed argument.
+- */
+-#define XPC_PACK_ARGS(_arg1, _arg2) \
+-			((((u64) _arg1) & 0xffffffff) | \
+-			((((u64) _arg2) & 0xffffffff) << 32))
+-
+-#define XPC_UNPACK_ARG1(_args)	(((u64) _args) & 0xffffffff)
+-#define XPC_UNPACK_ARG2(_args)	((((u64) _args) >> 32) & 0xffffffff)
+-
+-
+-
+-/*
+- * Define a Get/Put value pair (pointers) used with a message queue.
+- */
+-struct xpc_gp {
+-	volatile s64 get;	/* Get value */
+-	volatile s64 put;	/* Put value */
+-};
+-
+-#define XPC_GP_SIZE \
+-		L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_NCHANNELS)
+-
+-
+-
+-/*
+- * Define a structure that contains arguments associated with opening and
+- * closing a channel.
+- */
+-struct xpc_openclose_args {
+-	u16 reason;		/* reason why channel is closing */
+-	u16 msg_size;		/* sizeof each message entry */
+-	u16 remote_nentries;	/* #of message entries in remote msg queue */
+-	u16 local_nentries;	/* #of message entries in local msg queue */
+-	u64 local_msgqueue_pa;	/* physical address of local message queue */
+-};
+-
+-#define XPC_OPENCLOSE_ARGS_SIZE \
+-	      L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * XPC_NCHANNELS)
+-
+-
+-
+-/* struct xpc_msg flags */
+-
+-#define	XPC_M_DONE		0x01	/* msg has been received/consumed */
+-#define	XPC_M_READY		0x02	/* msg is ready to be sent */
+-#define	XPC_M_INTERRUPT		0x04	/* send interrupt when msg consumed */
+-
+-
+-#define XPC_MSG_ADDRESS(_payload) \
+-		((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))
+-
+-
+-
+-/*
+- * Defines notify entry.
+- *
+- * This is used to notify a message's sender that their message was received
+- * and consumed by the intended recipient.
+- */
+-struct xpc_notify {
+-	volatile u8 type;		/* type of notification */
+-
+-	/* the following two fields are only used if type == XPC_N_CALL */
+-	xpc_notify_func func;		/* user's notify function */
+-	void *key;			/* pointer to user's key */
+-};
+-
+-/* struct xpc_notify type of notification */
+-
+-#define	XPC_N_CALL		0x01	/* notify function provided by user */
+-
+-
+-
+-/*
+- * Define the structure that manages all the stuff required by a channel. In
+- * particular, they are used to manage the messages sent across the channel.
+- *
+- * This structure is private to a partition, and is NOT shared across the
+- * partition boundary.
+- *
+- * There is an array of these structures for each remote partition. It is
+- * allocated at the time a partition becomes active. The array contains one
+- * of these structures for each potential channel connection to that partition.
+- *
+- * Each of these structures manages two message queues (circular buffers).
+- * They are allocated at the time a channel connection is made. One of
+- * these message queues (local_msgqueue) holds the locally created messages
+- * that are destined for the remote partition. The other of these message
+- * queues (remote_msgqueue) is a locally cached copy of the remote partition's
+- * own local_msgqueue.
+- *
+- * The following is a description of the Get/Put pointers used to manage these
+- * two message queues. Consider the local_msgqueue to be on one partition
+- * and the remote_msgqueue to be its cached copy on another partition. A
+- * description of what each of the lettered areas contains is included.
+- *
+- *
+- *                     local_msgqueue      remote_msgqueue
+- *
+- *                        |/////////|      |/////////|
+- *    w_remote_GP.get --> +---------+      |/////////|
+- *                        |    F    |      |/////////|
+- *     remote_GP.get  --> +---------+      +---------+ <-- local_GP->get
+- *                        |         |      |         |
+- *                        |         |      |    E    |
+- *                        |         |      |         |
+- *                        |         |      +---------+ <-- w_local_GP.get
+- *                        |    B    |      |/////////|
+- *                        |         |      |////D////|
+- *                        |         |      |/////////|
+- *                        |         |      +---------+ <-- w_remote_GP.put
+- *                        |         |      |////C////|
+- *      local_GP->put --> +---------+      +---------+ <-- remote_GP.put
+- *                        |         |      |/////////|
+- *                        |    A    |      |/////////|
+- *                        |         |      |/////////|
+- *     w_local_GP.put --> +---------+      |/////////|
+- *                        |/////////|      |/////////|
+- *
+- *
+- *	    ( remote_GP.[get|put] are cached copies of the remote
+- *	      partition's local_GP->[get|put], and thus their values can
+- *	      lag behind their counterparts on the remote partition. )
+- *
+- *
+- *  A - Messages that have been allocated, but have not yet been sent to the
+- *	remote partition.
+- *
+- *  B - Messages that have been sent, but have not yet been acknowledged by the
+- *      remote partition as having been received.
+- *
+- *  C - Area that needs to be prepared for the copying of sent messages, by
+- *	the clearing of the message flags of any previously received messages.
+- *
+- *  D - Area into which sent messages are to be copied from the remote
+- *	partition's local_msgqueue and then delivered to their intended
+- *	recipients. [ To allow for a multi-message copy, another pointer
+- *	(next_msg_to_pull) has been added to keep track of the next message
+- *	number needing to be copied (pulled). It chases after w_remote_GP.put.
+- *	Any messages lying between w_local_GP.get and next_msg_to_pull have
+- *	been copied and are ready to be delivered. ]
+- *
+- *  E - Messages that have been copied and delivered, but have not yet been
+- *	acknowledged by the recipient as having been received.
+- *
+- *  F - Messages that have been acknowledged, but XPC has not yet notified the
+- *	sender that the message was received by its intended recipient.
+- *	This is also an area that needs to be prepared for the allocating of
+- *	new messages, by the clearing of the message flags of the acknowledged
+- *	messages.
+- */
+-struct xpc_channel {
+-	partid_t partid;		/* ID of remote partition connected */
+-	spinlock_t lock;		/* lock for updating this structure */
+-	u32 flags;			/* general flags */
+-
+-	enum xpc_retval reason;		/* reason why channel is disconnect'g */
+-	int reason_line;		/* line# disconnect initiated from */
+-
+-	u16 number;			/* channel # */
+-
+-	u16 msg_size;			/* sizeof each msg entry */
+-	u16 local_nentries;		/* #of msg entries in local msg queue */
+-	u16 remote_nentries;		/* #of msg entries in remote msg queue*/
+-
+-	void *local_msgqueue_base;	/* base address of kmalloc'd space */
+-	struct xpc_msg *local_msgqueue;	/* local message queue */
+-	void *remote_msgqueue_base;	/* base address of kmalloc'd space */
+-	struct xpc_msg *remote_msgqueue;/* cached copy of remote partition's */
+-					/* local message queue */
+-	u64 remote_msgqueue_pa;		/* phys addr of remote partition's */
+-					/* local message queue */
+-
+-	atomic_t references;		/* #of external references to queues */
+-
+-	atomic_t n_on_msg_allocate_wq;   /* #on msg allocation wait queue */
+-	wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */
+-
+-	u8 delayed_IPI_flags;		/* IPI flags received, but delayed */
+-					/* action until channel disconnected */
+-
+-	/* queue of msg senders who want to be notified when msg received */
+-
+-	atomic_t n_to_notify;		/* #of msg senders to notify */
+-	struct xpc_notify *notify_queue;/* notify queue for messages sent */
+-
+-	xpc_channel_func func;		/* user's channel function */
+-	void *key;			/* pointer to user's key */
+-
+-	struct mutex msg_to_pull_mutex;	/* next msg to pull serialization */
+-	struct completion wdisconnect_wait; /* wait for channel disconnect */
+-
+-	struct xpc_openclose_args *local_openclose_args; /* args passed on */
+-					/* opening or closing of channel */
+-
+-	/* various flavors of local and remote Get/Put values */
+-
+-	struct xpc_gp *local_GP;	/* local Get/Put values */
+-	struct xpc_gp remote_GP;	/* remote Get/Put values */
+-	struct xpc_gp w_local_GP;	/* working local Get/Put values */
+-	struct xpc_gp w_remote_GP;	/* working remote Get/Put values */
+-	s64 next_msg_to_pull;		/* Put value of next msg to pull */
+-
+-	/* kthread management related fields */
+-
+-// >>> rethink having kthreads_assigned_limit and kthreads_idle_limit; perhaps
+-// >>> allow the assigned limit be unbounded and let the idle limit be dynamic
+-// >>> dependent on activity over the last interval of time
+-	atomic_t kthreads_assigned;	/* #of kthreads assigned to channel */
+-	u32 kthreads_assigned_limit; 	/* limit on #of kthreads assigned */
+-	atomic_t kthreads_idle;		/* #of kthreads idle waiting for work */
+-	u32 kthreads_idle_limit;	/* limit on #of kthreads idle */
+-	atomic_t kthreads_active;	/* #of kthreads actively working */
+-	// >>> following field is temporary
+-	u32 kthreads_created;		/* total #of kthreads created */
+-
+-	wait_queue_head_t idle_wq;	/* idle kthread wait queue */
+-
+-} ____cacheline_aligned;
+-
+-
+-/* struct xpc_channel flags */
+-
+-#define	XPC_C_WASCONNECTED	0x00000001 /* channel was connected */
+-
+-#define	XPC_C_ROPENREPLY	0x00000002 /* remote open channel reply */
+-#define	XPC_C_OPENREPLY		0x00000004 /* local open channel reply */
+-#define	XPC_C_ROPENREQUEST	0x00000008 /* remote open channel request */
+-#define	XPC_C_OPENREQUEST	0x00000010 /* local open channel request */
+-
+-#define	XPC_C_SETUP		0x00000020 /* channel's msgqueues are alloc'd */
+-#define	XPC_C_CONNECTEDCALLOUT	0x00000040 /* connected callout initiated */
+-#define	XPC_C_CONNECTEDCALLOUT_MADE \
+-				0x00000080 /* connected callout completed */
+-#define	XPC_C_CONNECTED		0x00000100 /* local channel is connected */
+-#define	XPC_C_CONNECTING	0x00000200 /* channel is being connected */
+-
+-#define	XPC_C_RCLOSEREPLY	0x00000400 /* remote close channel reply */
+-#define	XPC_C_CLOSEREPLY	0x00000800 /* local close channel reply */
+-#define	XPC_C_RCLOSEREQUEST	0x00001000 /* remote close channel request */
+-#define	XPC_C_CLOSEREQUEST	0x00002000 /* local close channel request */
+-
+-#define	XPC_C_DISCONNECTED	0x00004000 /* channel is disconnected */
+-#define	XPC_C_DISCONNECTING	0x00008000 /* channel is being disconnected */
+-#define	XPC_C_DISCONNECTINGCALLOUT \
+-				0x00010000 /* disconnecting callout initiated */
+-#define	XPC_C_DISCONNECTINGCALLOUT_MADE \
+-				0x00020000 /* disconnecting callout completed */
+-#define	XPC_C_WDISCONNECT	0x00040000 /* waiting for channel disconnect */
+-
+-
+-
+-/*
+- * Manages channels on a partition basis. There is one of these structures
+- * for each partition (a partition will never utilize the structure that
+- * represents itself).
+- */
+-struct xpc_partition {
+-
+-	/* XPC HB infrastructure */
+-
+-	u8 remote_rp_version;		/* version# of partition's rsvd pg */
+-	struct timespec remote_rp_stamp;/* time when rsvd pg was initialized */
+-	u64 remote_rp_pa;		/* phys addr of partition's rsvd pg */
+-	u64 remote_vars_pa;		/* phys addr of partition's vars */
+-	u64 remote_vars_part_pa;	/* phys addr of partition's vars part */
+-	u64 last_heartbeat;		/* HB at last read */
+-	u64 remote_amos_page_pa;	/* phys addr of partition's amos page */
+-	int remote_act_nasid;		/* active part's act/deact nasid */
+-	int remote_act_phys_cpuid;	/* active part's act/deact phys cpuid */
+-	u32 act_IRQ_rcvd;		/* IRQs since activation */
+-	spinlock_t act_lock;		/* protect updating of act_state */
+-	u8 act_state;			/* from XPC HB viewpoint */
+-	u8 remote_vars_version;		/* version# of partition's vars */
+-	enum xpc_retval reason;		/* reason partition is deactivating */
+-	int reason_line;		/* line# deactivation initiated from */
+-	int reactivate_nasid;		/* nasid in partition to reactivate */
+-
+-	unsigned long disengage_request_timeout; /* timeout in jiffies */
+-	struct timer_list disengage_request_timer;
+-
+-
+-	/* XPC infrastructure referencing and teardown control */
+-
+-	volatile u8 setup_state;	/* infrastructure setup state */
+-	wait_queue_head_t teardown_wq;	/* kthread waiting to teardown infra */
+-	atomic_t references;		/* #of references to infrastructure */
+-
+-
+-	/*
+-	 * NONE OF THE PRECEDING FIELDS OF THIS STRUCTURE WILL BE CLEARED WHEN
+-	 * XPC SETS UP THE NECESSARY INFRASTRUCTURE TO SUPPORT CROSS PARTITION
+-	 * COMMUNICATION. ALL OF THE FOLLOWING FIELDS WILL BE CLEARED. (THE
+-	 * 'nchannels' FIELD MUST BE THE FIRST OF THE FIELDS TO BE CLEARED.)
+-	 */
+-
+-
+-	u8 nchannels;		   /* #of defined channels supported */
+-	atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */
+-	atomic_t nchannels_engaged;/* #of channels engaged with remote part */
+-	struct xpc_channel *channels;/* array of channel structures */
+-
+-	void *local_GPs_base;	  /* base address of kmalloc'd space */
+-	struct xpc_gp *local_GPs; /* local Get/Put values */
+-	void *remote_GPs_base;    /* base address of kmalloc'd space */
+-	struct xpc_gp *remote_GPs;/* copy of remote partition's local Get/Put */
+-				  /* values */
+-	u64 remote_GPs_pa;	  /* phys address of remote partition's local */
+-				  /* Get/Put values */
+-
+-
+-	/* fields used to pass args when opening or closing a channel */
+-
+-	void *local_openclose_args_base;  /* base address of kmalloc'd space */
+-	struct xpc_openclose_args *local_openclose_args;  /* local's args */
+-	void *remote_openclose_args_base; /* base address of kmalloc'd space */
+-	struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
+-					  /* args */
+-	u64 remote_openclose_args_pa;	  /* phys addr of remote's args */
+-
+-
+-	/* IPI sending, receiving and handling related fields */
+-
+-	int remote_IPI_nasid;	    /* nasid of where to send IPIs */
+-	int remote_IPI_phys_cpuid;  /* phys CPU ID of where to send IPIs */
+-	AMO_t *remote_IPI_amo_va;   /* address of remote IPI AMO_t structure */
+-
+-	AMO_t *local_IPI_amo_va;    /* address of IPI AMO_t structure */
+-	u64 local_IPI_amo;	    /* IPI amo flags yet to be handled */
+-	char IPI_owner[8];	    /* IPI owner's name */
+-	struct timer_list dropped_IPI_timer; /* dropped IPI timer */
+-
+-	spinlock_t IPI_lock;	    /* IPI handler lock */
+-
+-
+-	/* channel manager related fields */
+-
+-	atomic_t channel_mgr_requests;	/* #of requests to activate chan mgr */
+-	wait_queue_head_t channel_mgr_wq; /* channel mgr's wait queue */
+-
+-} ____cacheline_aligned;
+-
+-
+-/* struct xpc_partition act_state values (for XPC HB) */
+-
+-#define	XPC_P_INACTIVE		0x00	/* partition is not active */
+-#define XPC_P_ACTIVATION_REQ	0x01	/* created thread to activate */
+-#define XPC_P_ACTIVATING	0x02	/* activation thread started */
+-#define XPC_P_ACTIVE		0x03	/* xpc_partition_up() was called */
+-#define XPC_P_DEACTIVATING	0x04	/* partition deactivation initiated */
+-
+-
+-#define XPC_DEACTIVATE_PARTITION(_p, _reason) \
+-			xpc_deactivate_partition(__LINE__, (_p), (_reason))
+-
+-
+-/* struct xpc_partition setup_state values */
+-
+-#define XPC_P_UNSET		0x00	/* infrastructure was never setup */
+-#define XPC_P_SETUP		0x01	/* infrastructure is setup */
+-#define XPC_P_WTEARDOWN		0x02	/* waiting to teardown infrastructure */
+-#define XPC_P_TORNDOWN		0x03	/* infrastructure is torndown */
+-
+-
+-
+-/*
+- * struct xpc_partition IPI_timer #of seconds to wait before checking for
+- * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
+- * after the IPI was received.
+- */
+-#define XPC_P_DROPPED_IPI_WAIT	(0.25 * HZ)
+-
+-
+-/* number of seconds to wait for other partitions to disengage */
+-#define XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT	90
+-
+-/* interval in seconds to print 'waiting disengagement' messages */
+-#define XPC_DISENGAGE_PRINTMSG_INTERVAL		10
+-
+-
+-#define XPC_PARTID(_p)	((partid_t) ((_p) - &xpc_partitions[0]))
+-
+-
+-
+-/* found in xp_main.c */
+-extern struct xpc_registration xpc_registrations[];
+-
+-
+-/* found in xpc_main.c */
+-extern struct device *xpc_part;
+-extern struct device *xpc_chan;
+-extern int xpc_disengage_request_timelimit;
+-extern int xpc_disengage_request_timedout;
+-extern irqreturn_t xpc_notify_IRQ_handler(int, void *);
+-extern void xpc_dropped_IPI_check(struct xpc_partition *);
+-extern void xpc_activate_partition(struct xpc_partition *);
+-extern void xpc_activate_kthreads(struct xpc_channel *, int);
+-extern void xpc_create_kthreads(struct xpc_channel *, int, int);
+-extern void xpc_disconnect_wait(int);
+-
+-
+-/* found in xpc_partition.c */
+-extern int xpc_exiting;
+-extern struct xpc_vars *xpc_vars;
+-extern struct xpc_rsvd_page *xpc_rsvd_page;
+-extern struct xpc_vars_part *xpc_vars_part;
+-extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
+-extern char *xpc_remote_copy_buffer;
+-extern void *xpc_remote_copy_buffer_base;
+-extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
+-extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
+-extern void xpc_allow_IPI_ops(void);
+-extern void xpc_restrict_IPI_ops(void);
+-extern int xpc_identify_act_IRQ_sender(void);
+-extern int xpc_partition_disengaged(struct xpc_partition *);
+-extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);
+-extern void xpc_mark_partition_inactive(struct xpc_partition *);
+-extern void xpc_discovery(void);
+-extern void xpc_check_remote_hb(void);
+-extern void xpc_deactivate_partition(const int, struct xpc_partition *,
+-						enum xpc_retval);
+-extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *);
+-
+-
+-/* found in xpc_channel.c */
+-extern void xpc_initiate_connect(int);
+-extern void xpc_initiate_disconnect(int);
+-extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **);
+-extern enum xpc_retval xpc_initiate_send(partid_t, int, void *);
+-extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *,
+-						xpc_notify_func, void *);
+-extern void xpc_initiate_received(partid_t, int, void *);
+-extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *);
+-extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *);
+-extern void xpc_process_channel_activity(struct xpc_partition *);
+-extern void xpc_connected_callout(struct xpc_channel *);
+-extern void xpc_deliver_msg(struct xpc_channel *);
+-extern void xpc_disconnect_channel(const int, struct xpc_channel *,
+-					enum xpc_retval, unsigned long *);
+-extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval);
+-extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval);
+-extern void xpc_teardown_infrastructure(struct xpc_partition *);
+-
+-
+-
+-static inline void
+-xpc_wakeup_channel_mgr(struct xpc_partition *part)
+-{
+-	if (atomic_inc_return(&part->channel_mgr_requests) == 1) {
+-		wake_up(&part->channel_mgr_wq);
+-	}
+-}
+-
+-
+-
+-/*
+- * These next two inlines are used to keep us from tearing down a channel's
+- * msg queues while a thread may be referencing them.
+- */
+-static inline void
+-xpc_msgqueue_ref(struct xpc_channel *ch)
+-{
+-	atomic_inc(&ch->references);
+-}
+-
+-static inline void
+-xpc_msgqueue_deref(struct xpc_channel *ch)
+-{
+-	s32 refs = atomic_dec_return(&ch->references);
+-
+-	DBUG_ON(refs < 0);
+-	if (refs == 0) {
+-		xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
+-	}
+-}
+-
+-
+-
+-#define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
+-		xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
+-
+-
+-/*
+- * These two inlines are used to keep us from tearing down a partition's
+- * setup infrastructure while a thread may be referencing it.
+- */
+-static inline void
+-xpc_part_deref(struct xpc_partition *part)
+-{
+-	s32 refs = atomic_dec_return(&part->references);
+-
+-
+-	DBUG_ON(refs < 0);
+-	if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN) {
+-		wake_up(&part->teardown_wq);
+-	}
+-}
+-
+-static inline int
+-xpc_part_ref(struct xpc_partition *part)
+-{
+-	int setup;
+-
+-
+-	atomic_inc(&part->references);
+-	setup = (part->setup_state == XPC_P_SETUP);
+-	if (!setup) {
+-		xpc_part_deref(part);
+-	}
+-	return setup;
+-}
+-
+-
+-
+-/*
+- * The following macro is to be used for the setting of the reason and
+- * reason_line fields in both the struct xpc_channel and struct xpc_partition
+- * structures.
+- */
+-#define XPC_SET_REASON(_p, _reason, _line) \
+-	{ \
+-		(_p)->reason = _reason; \
+-		(_p)->reason_line = _line; \
+-	}
+-
+-
+-
+-/*
+- * This next set of inlines are used to keep track of when a partition is
+- * potentially engaged in accessing memory belonging to another partition.
+- */
+-
+-static inline void
+-xpc_mark_partition_engaged(struct xpc_partition *part)
+-{
+-	unsigned long irq_flags;
+-	AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+-				(XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
+-
+-
+-	local_irq_save(irq_flags);
+-
+-	/* set bit corresponding to our partid in remote partition's AMO */
+-	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
+-						(1UL << sn_partition_id));
+-	/*
+-	 * We must always use the nofault function regardless of whether we
+-	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+-	 * didn't, we'd never know that the other partition is down and would
+-	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+-	 */
+-	(void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+-				variable), xp_nofault_PIOR_target));
+-
+-	local_irq_restore(irq_flags);
+-}
+-
+-static inline void
+-xpc_mark_partition_disengaged(struct xpc_partition *part)
+-{
+-	unsigned long irq_flags;
+-	AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+-				(XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
+-
+-
+-	local_irq_save(irq_flags);
+-
+-	/* clear bit corresponding to our partid in remote partition's AMO */
+-	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+-						~(1UL << sn_partition_id));
+-	/*
+-	 * We must always use the nofault function regardless of whether we
+-	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+-	 * didn't, we'd never know that the other partition is down and would
+-	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+-	 */
+-	(void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+-				variable), xp_nofault_PIOR_target));
+-
+-	local_irq_restore(irq_flags);
+-}
+-
+-static inline void
+-xpc_request_partition_disengage(struct xpc_partition *part)
+-{
+-	unsigned long irq_flags;
+-	AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+-				(XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
+-
+-
+-	local_irq_save(irq_flags);
+-
+-	/* set bit corresponding to our partid in remote partition's AMO */
+-	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
+-						(1UL << sn_partition_id));
+-	/*
+-	 * We must always use the nofault function regardless of whether we
+-	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+-	 * didn't, we'd never know that the other partition is down and would
+-	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+-	 */
+-	(void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+-				variable), xp_nofault_PIOR_target));
+-
+-	local_irq_restore(irq_flags);
+-}
+-
+-static inline void
+-xpc_cancel_partition_disengage_request(struct xpc_partition *part)
+-{
+-	unsigned long irq_flags;
+-	AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+-				(XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
+-
+-
+-	local_irq_save(irq_flags);
+-
+-	/* clear bit corresponding to our partid in remote partition's AMO */
+-	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+-						~(1UL << sn_partition_id));
+-	/*
+-	 * We must always use the nofault function regardless of whether we
+-	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+-	 * didn't, we'd never know that the other partition is down and would
+-	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+-	 */
+-	(void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+-				variable), xp_nofault_PIOR_target));
+-
+-	local_irq_restore(irq_flags);
+-}
+-
+-static inline u64
+-xpc_partition_engaged(u64 partid_mask)
+-{
+-	AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
+-
+-
+-	/* return our partition's AMO variable ANDed with partid_mask */
+-	return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
+-								partid_mask);
+-}
+-
+-static inline u64
+-xpc_partition_disengage_requested(u64 partid_mask)
+-{
+-	AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
+-
+-
+-	/* return our partition's AMO variable ANDed with partid_mask */
+-	return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
+-								partid_mask);
+-}
+-
+-static inline void
+-xpc_clear_partition_engaged(u64 partid_mask)
+-{
+-	AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
+-
+-
+-	/* clear bit(s) based on partid_mask in our partition's AMO */
+-	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+-								~partid_mask);
+-}
+-
+-static inline void
+-xpc_clear_partition_disengage_request(u64 partid_mask)
+-{
+-	AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
+-
+-
+-	/* clear bit(s) based on partid_mask in our partition's AMO */
+-	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+-								~partid_mask);
+-}
+-
+-
+-
+-/*
+- * The following set of macros and inlines are used for the sending and
+- * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
+- * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
+- * the other that is associated with channel activity (SGI_XPC_NOTIFY).
+- */
+-
+-static inline u64
+-xpc_IPI_receive(AMO_t *amo)
+-{
+-	return FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_CLEAR);
+-}
+-
+-
+-static inline enum xpc_retval
+-xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
+-{
+-	int ret = 0;
+-	unsigned long irq_flags;
+-
+-
+-	local_irq_save(irq_flags);
+-
+-	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR, flag);
+-	sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
+-
+-	/*
+-	 * We must always use the nofault function regardless of whether we
+-	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+-	 * didn't, we'd never know that the other partition is down and would
+-	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+-	 */
+-	ret = xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
+-				xp_nofault_PIOR_target));
+-
+-	local_irq_restore(irq_flags);
+-
+-	return ((ret == 0) ? xpcSuccess : xpcPioReadError);
+-}
+-
+-
+-/*
+- * IPIs associated with SGI_XPC_ACTIVATE IRQ.
+- */
+-
+-/*
+- * Flag the appropriate AMO variable and send an IPI to the specified node.
+- */
+-static inline void
+-xpc_activate_IRQ_send(u64 amos_page_pa, int from_nasid, int to_nasid,
+-			int to_phys_cpuid)
+-{
+-	int w_index = XPC_NASID_W_INDEX(from_nasid);
+-	int b_index = XPC_NASID_B_INDEX(from_nasid);
+-	AMO_t *amos = (AMO_t *) __va(amos_page_pa +
+-				(XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
+-
+-
+-	(void) xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,
+-				to_phys_cpuid, SGI_XPC_ACTIVATE);
+-}
+-
+-static inline void
+-xpc_IPI_send_activate(struct xpc_vars *vars)
+-{
+-	xpc_activate_IRQ_send(vars->amos_page_pa, cnodeid_to_nasid(0),
+-				vars->act_nasid, vars->act_phys_cpuid);
+-}
+-
+-static inline void
+-xpc_IPI_send_activated(struct xpc_partition *part)
+-{
+-	xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
+-			part->remote_act_nasid, part->remote_act_phys_cpuid);
+-}
+-
+-static inline void
+-xpc_IPI_send_reactivate(struct xpc_partition *part)
+-{
+-	xpc_activate_IRQ_send(xpc_vars->amos_page_pa, part->reactivate_nasid,
+-				xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);
+-}
+-
+-static inline void
+-xpc_IPI_send_disengage(struct xpc_partition *part)
+-{
+-	xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
+-			part->remote_act_nasid, part->remote_act_phys_cpuid);
+-}
+-
+-
+-/*
+- * IPIs associated with SGI_XPC_NOTIFY IRQ.
+- */
+-
+-/*
+- * Send an IPI to the remote partition that is associated with the
+- * specified channel.
+- */
+-#define XPC_NOTIFY_IRQ_SEND(_ch, _ipi_f, _irq_f) \
+-		xpc_notify_IRQ_send(_ch, _ipi_f, #_ipi_f, _irq_f)
+-
+-static inline void
+-xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string,
+-			unsigned long *irq_flags)
+-{
+-	struct xpc_partition *part = &xpc_partitions[ch->partid];
+-	enum xpc_retval ret;
+-
+-
+-	if (likely(part->act_state != XPC_P_DEACTIVATING)) {
+-		ret = xpc_IPI_send(part->remote_IPI_amo_va,
+-					(u64) ipi_flag << (ch->number * 8),
+-					part->remote_IPI_nasid,
+-					part->remote_IPI_phys_cpuid,
+-					SGI_XPC_NOTIFY);
+-		dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
+-			ipi_flag_string, ch->partid, ch->number, ret);
+-		if (unlikely(ret != xpcSuccess)) {
+-			if (irq_flags != NULL) {
+-				spin_unlock_irqrestore(&ch->lock, *irq_flags);
+-			}
+-			XPC_DEACTIVATE_PARTITION(part, ret);
+-			if (irq_flags != NULL) {
+-				spin_lock_irqsave(&ch->lock, *irq_flags);
+-			}
+-		}
+-	}
+-}
+-
+-
+-/*
+- * Make it look like the remote partition, which is associated with the
+- * specified channel, sent us an IPI. This faked IPI will be handled
+- * by xpc_dropped_IPI_check().
+- */
+-#define XPC_NOTIFY_IRQ_SEND_LOCAL(_ch, _ipi_f) \
+-		xpc_notify_IRQ_send_local(_ch, _ipi_f, #_ipi_f)
+-
+-static inline void
+-xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag,
+-				char *ipi_flag_string)
+-{
+-	struct xpc_partition *part = &xpc_partitions[ch->partid];
+-
+-
+-	FETCHOP_STORE_OP(TO_AMO((u64) &part->local_IPI_amo_va->variable),
+-			FETCHOP_OR, ((u64) ipi_flag << (ch->number * 8)));
+-	dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
+-		ipi_flag_string, ch->partid, ch->number);
+-}
+-
+-
+-/*
+- * The sending and receiving of IPIs includes the setting of an AMO variable
+- * to indicate the reason the IPI was sent. The 64-bit variable is divided
+- * up into eight bytes, ordered from right to left. Byte zero pertains to
+- * channel 0, byte one to channel 1, and so on. Each byte is described by
+- * the following IPI flags.
+- */
+-
+-#define	XPC_IPI_CLOSEREQUEST	0x01
+-#define	XPC_IPI_CLOSEREPLY	0x02
+-#define	XPC_IPI_OPENREQUEST	0x04
+-#define	XPC_IPI_OPENREPLY	0x08
+-#define	XPC_IPI_MSGREQUEST	0x10
+-
+-
+-/* given an AMO variable and a channel#, get its associated IPI flags */
+-#define XPC_GET_IPI_FLAGS(_amo, _c)	((u8) (((_amo) >> ((_c) * 8)) & 0xff))
+-#define XPC_SET_IPI_FLAGS(_amo, _c, _f)	(_amo) |= ((u64) (_f) << ((_c) * 8))
+-
+-#define	XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & __IA64_UL_CONST(0x0f0f0f0f0f0f0f0f))
+-#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & __IA64_UL_CONST(0x1010101010101010))
+-
+-
+-static inline void
+-xpc_IPI_send_closerequest(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+-	struct xpc_openclose_args *args = ch->local_openclose_args;
+-
+-
+-	args->reason = ch->reason;
+-
+-	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREQUEST, irq_flags);
+-}
+-
+-static inline void
+-xpc_IPI_send_closereply(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+-	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREPLY, irq_flags);
+-}
+-
+-static inline void
+-xpc_IPI_send_openrequest(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+-	struct xpc_openclose_args *args = ch->local_openclose_args;
+-
+-
+-	args->msg_size = ch->msg_size;
+-	args->local_nentries = ch->local_nentries;
+-
+-	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREQUEST, irq_flags);
+-}
+-
+-static inline void
+-xpc_IPI_send_openreply(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+-	struct xpc_openclose_args *args = ch->local_openclose_args;
+-
+-
+-	args->remote_nentries = ch->remote_nentries;
+-	args->local_nentries = ch->local_nentries;
+-	args->local_msgqueue_pa = __pa(ch->local_msgqueue);
+-
+-	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREPLY, irq_flags);
+-}
+-
+-static inline void
+-xpc_IPI_send_msgrequest(struct xpc_channel *ch)
+-{
+-	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_MSGREQUEST, NULL);
+-}
+-
+-static inline void
+-xpc_IPI_send_local_msgrequest(struct xpc_channel *ch)
+-{
+-	XPC_NOTIFY_IRQ_SEND_LOCAL(ch, XPC_IPI_MSGREQUEST);
+-}
+-
+-
+-/*
+- * Memory for XPC's AMO variables is allocated by the MSPEC driver. These
+- * pages are located in the lowest granule. The lowest granule uses 4k pages
+- * for cached references and an alternate TLB handler to never provide a
+- * cacheable mapping for the entire region. This will prevent speculative
+- * reading of cached copies of our lines from being issued which will cause
+- * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
+- * AMO variables (based on XP_MAX_PARTITIONS) for message notification and an
+- * additional 128 AMO variables (based on XP_NASID_MASK_WORDS) for partition
+- * activation and 2 AMO variables for partition deactivation.
+- */
+-static inline AMO_t *
+-xpc_IPI_init(int index)
+-{
+-	AMO_t *amo = xpc_vars->amos_page + index;
+-
+-
+-	(void) xpc_IPI_receive(amo);	/* clear AMO variable */
+-	return amo;
+-}
+-
+-
+-
+-static inline enum xpc_retval
+-xpc_map_bte_errors(bte_result_t error)
+-{
+-	if (error == BTE_SUCCESS)
+-		return xpcSuccess;
+-
+-	if (is_shub2()) {
+-		if (BTE_VALID_SH2_ERROR(error))
+-			return xpcBteSh2Start + error;
+-		return xpcBteUnmappedError;
+-	}
+-	switch (error) {
+-	case BTE_SUCCESS:	return xpcSuccess;
+-	case BTEFAIL_DIR:	return xpcBteDirectoryError;
+-	case BTEFAIL_POISON:	return xpcBtePoisonError;
+-	case BTEFAIL_WERR:	return xpcBteWriteError;
+-	case BTEFAIL_ACCESS:	return xpcBteAccessError;
+-	case BTEFAIL_PWERR:	return xpcBtePWriteError;
+-	case BTEFAIL_PRERR:	return xpcBtePReadError;
+-	case BTEFAIL_TOUT:	return xpcBteTimeOutError;
+-	case BTEFAIL_XTERR:	return xpcBteXtalkError;
+-	case BTEFAIL_NOTAVAIL:	return xpcBteNotAvailable;
+-	default:		return xpcBteUnmappedError;
+-	}
+-}
+-
+-
+-
+-/*
+- * Check to see if there is any channel activity to/from the specified
+- * partition.
+- */
+-static inline void
+-xpc_check_for_channel_activity(struct xpc_partition *part)
+-{
+-	u64 IPI_amo;
+-	unsigned long irq_flags;
+-
+-
+-	IPI_amo = xpc_IPI_receive(part->local_IPI_amo_va);
+-	if (IPI_amo == 0) {
+-		return;
+-	}
+-
+-	spin_lock_irqsave(&part->IPI_lock, irq_flags);
+-	part->local_IPI_amo |= IPI_amo;
+-	spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
+-
+-	dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n",
+-		XPC_PARTID(part), IPI_amo);
+-
+-	xpc_wakeup_channel_mgr(part);
+-}
+-
+-
+-#endif /* _ASM_IA64_SN_XPC_H */
+-
+diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
+index 595112b..dff8128 100644
+--- a/include/asm-ia64/system.h
++++ b/include/asm-ia64/system.h
+@@ -210,6 +210,13 @@ struct task_struct;
+ extern void ia64_save_extra (struct task_struct *task);
+ extern void ia64_load_extra (struct task_struct *task);
+ 
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next);
++# define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n)
++#else
++# define IA64_ACCOUNT_ON_SWITCH(p,n)
++#endif
++
+ #ifdef CONFIG_PERFMON
+   DECLARE_PER_CPU(unsigned long, pfm_syst_info);
+ # define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1)
+@@ -222,6 +229,7 @@ extern void ia64_load_extra (struct task_struct *task);
+ 	 || IS_IA32_PROCESS(task_pt_regs(t)) || PERFMON_IS_SYSWIDE())
+ 
+ #define __switch_to(prev,next,last) do {							 \
++	IA64_ACCOUNT_ON_SWITCH(prev, next);							 \
+ 	if (IA64_HAS_EXTRA_STATE(prev))								 \
+ 		ia64_save_extra(prev);								 \
+ 	if (IA64_HAS_EXTRA_STATE(next))								 \
+@@ -266,6 +274,10 @@ void cpu_idle_wait(void);
+ 
+ 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/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
+index 93d83cb..6da8069 100644
+--- a/include/asm-ia64/thread_info.h
++++ b/include/asm-ia64/thread_info.h
+@@ -31,6 +31,12 @@ struct thread_info {
+ 	mm_segment_t addr_limit;	/* user-level address space limit */
+ 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+ 	struct restart_block restart_block;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++	__u64 ac_stamp;
++	__u64 ac_leave;
++	__u64 ac_stime;
++	__u64 ac_utime;
++#endif
+ };
+ 
+ #define THREAD_SIZE			KERNEL_STACK_SIZE
+@@ -62,9 +68,17 @@ struct thread_info {
+ #define task_stack_page(tsk)	((void *)(tsk))
+ 
+ #define __HAVE_THREAD_FUNCTIONS
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++#define setup_thread_stack(p, org)			\
++	*task_thread_info(p) = *task_thread_info(org);	\
++	task_thread_info(p)->ac_stime = 0;		\
++	task_thread_info(p)->ac_utime = 0;		\
++	task_thread_info(p)->task = (p);
++#else
+ #define setup_thread_stack(p, org) \
+ 	*task_thread_info(p) = *task_thread_info(org); \
+ 	task_thread_info(p)->task = (p);
++#endif
+ #define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
+ 
+ #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
+diff --git a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
+index 26edcb7..20d8a39 100644
+--- a/include/asm-ia64/tlb.h
++++ b/include/asm-ia64/tlb.h
+@@ -64,6 +64,32 @@ struct mmu_gather {
+ 	struct page 		*pages[FREE_PTE_NR];
+ };
+ 
++struct ia64_tr_entry {
++	u64 ifa;
++	u64 itir;
++	u64 pte;
++	u64 rr;
++}; /*Record for tr entry!*/
++
++extern int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size);
++extern void ia64_ptr_entry(u64 target_mask, int slot);
++
++extern struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX];
++
++/*
++ region register macros
++*/
++#define RR_TO_VE(val)   (((val) >> 0) & 0x0000000000000001)
++#define RR_VE(val)	(((val) & 0x0000000000000001) << 0)
++#define RR_VE_MASK	0x0000000000000001L
++#define RR_VE_SHIFT	0
++#define RR_TO_PS(val)	(((val) >> 2) & 0x000000000000003f)
++#define RR_PS(val)	(((val) & 0x000000000000003f) << 2)
++#define RR_PS_MASK	0x00000000000000fcL
++#define RR_PS_SHIFT	2
++#define RR_RID_MASK	0x00000000ffffff00L
++#define RR_TO_RID(val) 	((val >> 8) & 0xffffff)
++
+ /* Users of the generic TLB shootdown code must declare this storage space. */
+ DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
+ 
+diff --git a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h
+index 7774a1c..3be25df 100644
+--- a/include/asm-ia64/tlbflush.h
++++ b/include/asm-ia64/tlbflush.h
+@@ -17,6 +17,7 @@
+  * Now for some TLB flushing routines.  This is the kind of stuff that
+  * can be very expensive, so try to avoid them whenever possible.
+  */
++extern void setup_ptcg_sem(int max_purges, int from_palo);
+ 
+ /*
+  * Flush everything (kernel mapping may also have changed due to
+diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
+index 2d67b72..f2f72ef 100644
+--- a/include/asm-ia64/topology.h
++++ b/include/asm-ia64/topology.h
+@@ -93,7 +93,7 @@ void build_cpu_to_node_map(void);
+ 	.cache_nice_tries	= 2,			\
+ 	.busy_idx		= 3,			\
+ 	.idle_idx		= 2,			\
+-	.newidle_idx		= 0, /* unused */	\
++	.newidle_idx		= 2,			\
+ 	.wake_idx		= 1,			\
+ 	.forkexec_idx		= 1,			\
+ 	.flags			= SD_LOAD_BALANCE	\
+@@ -116,6 +116,11 @@ void build_cpu_to_node_map(void);
+ #define smt_capable() 				(smp_num_siblings > 1)
+ #endif
+ 
++#define pcibus_to_cpumask(bus)	(pcibus_to_node(bus) == -1 ? \
++					CPU_MASK_ALL : \
++					node_to_cpumask(pcibus_to_node(bus)) \
++				)
++
+ #include <asm-generic/topology.h>
+ 
+ #endif /* _ASM_IA64_TOPOLOGY_H */
+diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
+index 5d2044e..1e7f647 100644
+--- a/include/asm-m32r/ide.h
++++ b/include/asm-m32r/ide.h
+@@ -23,8 +23,6 @@
+ # endif
+ #endif
+ 
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static __inline__ int ide_default_irq(unsigned long base)
+ {
+ 	switch (base) {
+@@ -65,14 +63,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
+ 	}
+ }
+ 
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-#define ide_init_default_irq(base)     (0)
+-#else
+-#define ide_init_default_irq(base)     ide_default_irq(base)
+-#endif
+-
+ #include <asm-generic/ide_iops.h>
+ 
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
+index b5bf95a..d9b2034 100644
+--- a/include/asm-m32r/semaphore.h
++++ b/include/asm-m32r/semaphore.h
+@@ -1,144 +1 @@
+-#ifndef _ASM_M32R_SEMAPHORE_H
+-#define _ASM_M32R_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#ifdef __KERNEL__
+-
+-/*
+- * SMP- and interrupt-safe semaphores..
+- *
+- * Copyright (C) 1996  Linus Torvalds
+- * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+- */
+-
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-#include <asm/assembler.h>
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.sleepers	= 0,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-/*
+- *	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+- *
+- * i'd rather use the more flexible initialization above, but sadly
+- * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+- */
+-	atomic_set(&sem->count, val);
+-	sem->sleepers = 0;
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+-asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int  __down_interruptible(struct semaphore * sem);
+-asmlinkage int  __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-/*
+- * Atomically decrement the semaphore's count.  If it goes negative,
+- * block the calling thread in the TASK_UNINTERRUPTIBLE state.
+- */
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-	if (unlikely(atomic_dec_return(&sem->count) < 0))
+-		__down(sem);
+-}
+-
+-/*
+- * Interruptible try to acquire a semaphore.  If we obtained
+- * it, return zero.  If we were interrupted, returns -EINTR
+- */
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int result = 0;
+-
+-	might_sleep();
+-	if (unlikely(atomic_dec_return(&sem->count) < 0))
+-		result = __down_interruptible(sem);
+-
+-	return result;
+-}
+-
+-/*
+- * Non-blockingly attempt to down() a semaphore.
+- * Returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	unsigned long flags;
+-	long count;
+-	int result = 0;
+-
+-	local_irq_save(flags);
+-	__asm__ __volatile__ (
+-		"# down_trylock			\n\t"
+-		DCACHE_CLEAR("%0", "r4", "%1")
+-		M32R_LOCK" %0, @%1;		\n\t"
+-		"addi	%0, #-1;		\n\t"
+-		M32R_UNLOCK" %0, @%1;		\n\t"
+-		: "=&r" (count)
+-		: "r" (&sem->count)
+-		: "memory"
+-#ifdef CONFIG_CHIP_M32700_TS1
+-		, "r4"
+-#endif	/* CONFIG_CHIP_M32700_TS1 */
+-	);
+-	local_irq_restore(flags);
+-
+-	if (unlikely(count < 0))
+-		result = __down_trylock(sem);
+-
+-	return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	if (unlikely(atomic_inc_return(&sem->count) <= 0))
+-		__up(sem);
+-}
+-
+-#endif  /* __KERNEL__ */
+-
+-#endif  /* _ASM_M32R_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-m68k/semaphore-helper.h b/include/asm-m68k/semaphore-helper.h
+deleted file mode 100644
+index eef30ba..0000000
+--- a/include/asm-m68k/semaphore-helper.h
++++ /dev/null
+@@ -1,142 +0,0 @@
+-#ifndef _M68K_SEMAPHORE_HELPER_H
+-#define _M68K_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- */
+-
+-#include <linux/errno.h>
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+-	atomic_inc(&sem->waking);
+-}
+-
+-#ifndef CONFIG_RMW_INSNS
+-extern spinlock_t semaphore_wake_lock;
+-#endif
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+-	int ret;
+-#ifndef CONFIG_RMW_INSNS
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 0;
+-	if (atomic_read(&sem->waking) > 0) {
+-		atomic_dec(&sem->waking);
+-		ret = 1;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-#else
+-	int tmp1, tmp2;
+-
+-	__asm__ __volatile__
+-	  ("1:	movel	%1,%2\n"
+-	   "    jle	2f\n"
+-	   "	subql	#1,%2\n"
+-	   "	casl	%1,%2,%3\n"
+-	   "	jne	1b\n"
+-	   "	moveq	#1,%0\n"
+-	   "2:"
+-	   : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
+-	   : "m" (sem->waking), "0" (0), "1" (sem->waking));
+-#endif
+-
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- *	1	got the lock
+- *	0	go to sleep
+- *	-EINTR	interrupted
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+-						struct task_struct *tsk)
+-{
+-	int ret;
+-#ifndef CONFIG_RMW_INSNS
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 0;
+-	if (atomic_read(&sem->waking) > 0) {
+-		atomic_dec(&sem->waking);
+-		ret = 1;
+-	} else if (signal_pending(tsk)) {
+-		atomic_inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-#else
+-	int tmp1, tmp2;
+-
+-	__asm__ __volatile__
+-	  ("1:	movel	%1,%2\n"
+-	   "	jle	2f\n"
+-	   "	subql	#1,%2\n"
+-	   "	casl	%1,%2,%3\n"
+-	   "	jne	1b\n"
+-	   "	moveq	#1,%0\n"
+-	   "	jra	%a4\n"
+-	   "2:"
+-	   : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
+-	   : "m" (sem->waking), "i" (&&next), "0" (0), "1" (sem->waking));
+-	if (signal_pending(tsk)) {
+-		atomic_inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-next:
+-#endif
+-
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- *	1	failed to lock
+- *	0	got the lock
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+-	int ret;
+-#ifndef CONFIG_RMW_INSNS
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 1;
+-	if (atomic_read(&sem->waking) > 0) {
+-		atomic_dec(&sem->waking);
+-		ret = 0;
+-	} else
+-		atomic_inc(&sem->count);
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-#else
+-	int tmp1, tmp2;
+-
+-	__asm__ __volatile__
+-	  ("1:	movel	%1,%2\n"
+-	   "    jle	2f\n"
+-	   "	subql	#1,%2\n"
+-	   "	casl	%1,%2,%3\n"
+-	   "	jne	1b\n"
+-	   "	moveq	#0,%0\n"
+-	   "2:"
+-	   : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
+-	   : "m" (sem->waking), "0" (1), "1" (sem->waking));
+-	if (ret)
+-		atomic_inc(&sem->count);
+-#endif
+-	return ret;
+-}
+-
+-#endif
+diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
+index 64d6b11..d9b2034 100644
+--- a/include/asm-m68k/semaphore.h
++++ b/include/asm-m68k/semaphore.h
+@@ -1,163 +1 @@
+-#ifndef _M68K_SEMAPHORE_H
+-#define _M68K_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS		 0x01000000
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-#include <linux/stringify.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- */
+-
+-
+-struct semaphore {
+-	atomic_t count;
+-	atomic_t waking;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.waking		= ATOMIC_INIT(0),				\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+-asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int  __down_interruptible(struct semaphore * sem);
+-asmlinkage int  __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/m68k/lib/semaphore.S
+- */
+-static inline void down(struct semaphore *sem)
+-{
+-	register struct semaphore *sem1 __asm__ ("%a1") = sem;
+-
+-	might_sleep();
+-	__asm__ __volatile__(
+-		"| atomic down operation\n\t"
+-		"subql #1,%0@\n\t"
+-		"jmi 2f\n\t"
+-		"1:\n"
+-		LOCK_SECTION_START(".even\n\t")
+-		"2:\tpea 1b\n\t"
+-		"jbra __down_failed\n"
+-		LOCK_SECTION_END
+-		: /* no outputs */
+-		: "a" (sem1)
+-		: "memory");
+-}
+-
+-static inline int down_interruptible(struct semaphore *sem)
+-{
+-	register struct semaphore *sem1 __asm__ ("%a1") = sem;
+-	register int result __asm__ ("%d0");
+-
+-	might_sleep();
+-	__asm__ __volatile__(
+-		"| atomic interruptible down operation\n\t"
+-		"subql #1,%1@\n\t"
+-		"jmi 2f\n\t"
+-		"clrl %0\n"
+-		"1:\n"
+-		LOCK_SECTION_START(".even\n\t")
+-		"2:\tpea 1b\n\t"
+-		"jbra __down_failed_interruptible\n"
+-		LOCK_SECTION_END
+-		: "=d" (result)
+-		: "a" (sem1)
+-		: "memory");
+-	return result;
+-}
+-
+-static inline int down_trylock(struct semaphore *sem)
+-{
+-	register struct semaphore *sem1 __asm__ ("%a1") = sem;
+-	register int result __asm__ ("%d0");
+-
+-	__asm__ __volatile__(
+-		"| atomic down trylock operation\n\t"
+-		"subql #1,%1@\n\t"
+-		"jmi 2f\n\t"
+-		"clrl %0\n"
+-		"1:\n"
+-		LOCK_SECTION_START(".even\n\t")
+-		"2:\tpea 1b\n\t"
+-		"jbra __down_failed_trylock\n"
+-		LOCK_SECTION_END
+-		: "=d" (result)
+-		: "a" (sem1)
+-		: "memory");
+-	return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore *sem)
+-{
+-	register struct semaphore *sem1 __asm__ ("%a1") = sem;
+-
+-	__asm__ __volatile__(
+-		"| atomic up operation\n\t"
+-		"addql #1,%0@\n\t"
+-		"jle 2f\n"
+-		"1:\n"
+-		LOCK_SECTION_START(".even\n\t")
+-		"2:\t"
+-		"pea 1b\n\t"
+-		"jbra __up_wakeup\n"
+-		LOCK_SECTION_END
+-		: /* no outputs */
+-		: "a" (sem1)
+-		: "memory");
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-m68knommu/semaphore-helper.h b/include/asm-m68knommu/semaphore-helper.h
+deleted file mode 100644
+index 43da7bc..0000000
+--- a/include/asm-m68knommu/semaphore-helper.h
++++ /dev/null
+@@ -1,82 +0,0 @@
+-#ifndef _M68K_SEMAPHORE_HELPER_H
+-#define _M68K_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- */
+-
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+-	atomic_inc(&sem->waking);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+-	int ret;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 0;
+-	if (atomic_read(&sem->waking) > 0) {
+-		atomic_dec(&sem->waking);
+-		ret = 1;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- *	1	got the lock
+- *	0	go to sleep
+- *	-EINTR	interrupted
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+-						struct task_struct *tsk)
+-{
+-	int ret;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 0;
+-	if (atomic_read(&sem->waking) > 0) {
+-		atomic_dec(&sem->waking);
+-		ret = 1;
+-	} else if (signal_pending(tsk)) {
+-		atomic_inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- *	1	failed to lock
+- *	0	got the lock
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+-	int ret;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	ret = 1;
+-	if (atomic_read(&sem->waking) > 0) {
+-		atomic_dec(&sem->waking);
+-		ret = 0;
+-	} else
+-		atomic_inc(&sem->count);
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-#endif
+diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
+index 5779eb6..d9b2034 100644
+--- a/include/asm-m68knommu/semaphore.h
++++ b/include/asm-m68knommu/semaphore.h
+@@ -1,153 +1 @@
+-#ifndef _M68K_SEMAPHORE_H
+-#define _M68K_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS		 0x01000000
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- */
+-
+-
+-struct semaphore {
+-	atomic_t count;
+-	atomic_t waking;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.waking		= ATOMIC_INIT(0),				\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+-asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int  __down_interruptible(struct semaphore * sem);
+-asmlinkage int  __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/m68k/lib/semaphore.S
+- */
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-	__asm__ __volatile__(
+-		"| atomic down operation\n\t"
+-		"movel	%0, %%a1\n\t"
+-		"lea	%%pc@(1f), %%a0\n\t"
+-		"subql	#1, %%a1@\n\t"
+-		"jmi __down_failed\n"
+-		"1:"
+-		: /* no outputs */
+-		: "g" (sem)
+-		: "cc", "%a0", "%a1", "memory");
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int ret;
+-
+-	might_sleep();
+-	__asm__ __volatile__(
+-		"| atomic down operation\n\t"
+-		"movel	%1, %%a1\n\t"
+-		"lea	%%pc@(1f), %%a0\n\t"
+-		"subql	#1, %%a1@\n\t"
+-		"jmi __down_failed_interruptible\n\t"
+-		"clrl	%%d0\n"
+-		"1: movel	%%d0, %0\n"
+-		: "=d" (ret)
+-		: "g" (sem)
+-		: "cc", "%d0", "%a0", "%a1", "memory");
+-	return(ret);
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	register struct semaphore *sem1 __asm__ ("%a1") = sem;
+-	register int result __asm__ ("%d0");
+-
+-	__asm__ __volatile__(
+-		"| atomic down trylock operation\n\t"
+-		"subql #1,%1@\n\t"
+-		"jmi 2f\n\t"
+-		"clrl %0\n"
+-		"1:\n"
+-		".section .text.lock,\"ax\"\n"
+-		".even\n"
+-		"2:\tpea 1b\n\t"
+-		"jbra __down_failed_trylock\n"
+-		".previous"
+-		: "=d" (result)
+-		: "a" (sem1)
+-		: "memory");
+-	return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	__asm__ __volatile__(
+-		"| atomic up operation\n\t"
+-		"movel	%0, %%a1\n\t"
+-		"lea	%%pc@(1f), %%a0\n\t"
+-		"addql	#1, %%a1@\n\t"
+-		"jle __up_wakeup\n"
+-		"1:"
+-		: /* no outputs */
+-		: "g" (sem)
+-		: "cc", "%a0", "%a1", "memory");
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
+index 4ec2b93..0f6c251 100644
+--- a/include/asm-mips/mach-generic/ide.h
++++ b/include/asm-mips/mach-generic/ide.h
+@@ -27,8 +27,6 @@
+ # endif
+ #endif
+ 
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static __inline__ int ide_probe_legacy(void)
+ {
+ #ifdef CONFIG_PCI
+@@ -98,14 +96,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
+ 	}
+ }
+ 
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-#define ide_init_default_irq(base)	(0)
+-#else
+-#define ide_init_default_irq(base)	ide_default_irq(base)
+-#endif
+-
+ /* MIPS port and memory-mapped I/O string operations.  */
+ static inline void __ide_flush_prologue(void)
+ {
+diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
+index fdf8042..d9b2034 100644
+--- a/include/asm-mips/semaphore.h
++++ b/include/asm-mips/semaphore.h
+@@ -1,108 +1 @@
+-/*
+- * 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) 1996  Linus Torvalds
+- * Copyright (C) 1998, 99, 2000, 01, 04  Ralf Baechle
+- * Copyright (C) 1999, 2000, 01  Silicon Graphics, Inc.
+- * Copyright (C) 2000, 01 MIPS Technologies, Inc.
+- *
+- * In all honesty, little of the old MIPS code left - the PPC64 variant was
+- * just looking nice and portable so I ripped it.  Credits to whoever wrote
+- * it.
+- */
+-#ifndef __ASM_SEMAPHORE_H
+-#define __ASM_SEMAPHORE_H
+-
+-/*
+- * Remove spinlock-based RW semaphores; RW semaphore definitions are
+- * now in rwsem.h and we use the generic lib/rwsem.c implementation.
+- * Rework semaphores to use atomic_dec_if_positive.
+- * -- Paul Mackerras (paulus at samba.org)
+- */
+-
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+-	/*
+-	 * Note that any negative value of count is equivalent to 0,
+-	 * but additionally indicates that some process(es) might be
+-	 * sleeping on `wait'.
+-	 */
+-	atomic_t count;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
+-
+-#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name, 1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+-	atomic_set(&sem->count, val);
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX(struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED(struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int  __down_interruptible(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-
+-	/*
+-	 * Try to get the semaphore, take the slow path if we fail.
+-	 */
+-	if (unlikely(atomic_dec_return(&sem->count) < 0))
+-		__down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-
+-	might_sleep();
+-
+-	if (unlikely(atomic_dec_return(&sem->count) < 0))
+-		ret = __down_interruptible(sem);
+-	return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	return atomic_dec_if_positive(&sem->count) < 0;
+-}
+-
+-static inline void up(struct semaphore * sem)
+-{
+-	if (unlikely(atomic_inc_return(&sem->count) <= 0))
+-		__up(sem);
+-}
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* __ASM_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-mn10300/semaphore.h b/include/asm-mn10300/semaphore.h
+index 5a9e1ad..d9b2034 100644
+--- a/include/asm-mn10300/semaphore.h
++++ b/include/asm-mn10300/semaphore.h
+@@ -1,169 +1 @@
+-/* MN10300 Semaphores
+- *
+- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at 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_SEMAPHORE_H
+-#define _ASM_SEMAPHORE_H
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-#define SEMAPHORE_DEBUG		0
+-
+-/*
+- * the semaphore definition
+- * - if count is >0 then there are tokens available on the semaphore for down
+- *   to collect
+- * - if count is <=0 then there are no spare tokens, and anyone that wants one
+- *   must wait
+- * - if wait_list is not empty, then there are processes waiting for the
+- *   semaphore
+- */
+-struct semaphore {
+-	atomic_t		count;		/* it's not really atomic, it's
+-						 * just that certain modules
+-						 * expect to be able to access
+-						 * it directly */
+-	spinlock_t		wait_lock;
+-	struct list_head	wait_list;
+-#if SEMAPHORE_DEBUG
+-	unsigned		__magic;
+-#endif
+-};
+-
+-#if SEMAPHORE_DEBUG
+-# define __SEM_DEBUG_INIT(name) , (long)&(name).__magic
+-#else
+-# define __SEM_DEBUG_INIT(name)
+-#endif
+-
+-
+-#define __SEMAPHORE_INITIALIZER(name, init_count)			\
+-{									\
+-	.count		= ATOMIC_INIT(init_count),			\
+-	.wait_lock	= __SPIN_LOCK_UNLOCKED((name).wait_lock),	\
+-	.wait_list	= LIST_HEAD_INIT((name).wait_list)		\
+-	__SEM_DEBUG_INIT(name)						\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX(struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED(struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore *sem, unsigned long flags);
+-extern int  __down_interruptible(struct semaphore *sem, unsigned long flags);
+-extern void __up(struct semaphore *sem);
+-
+-static inline void down(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int count;
+-
+-#if SEMAPHORE_DEBUG
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-	count = atomic_read(&sem->count);
+-	if (likely(count > 0)) {
+-		atomic_set(&sem->count, count - 1);
+-		spin_unlock_irqrestore(&sem->wait_lock, flags);
+-	} else {
+-		__down(sem, flags);
+-	}
+-}
+-
+-static inline int down_interruptible(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int count, ret = 0;
+-
+-#if SEMAPHORE_DEBUG
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-	count = atomic_read(&sem->count);
+-	if (likely(count > 0)) {
+-		atomic_set(&sem->count, count - 1);
+-		spin_unlock_irqrestore(&sem->wait_lock, flags);
+-	} else {
+-		ret = __down_interruptible(sem, flags);
+-	}
+-	return ret;
+-}
+-
+-/*
+- * non-blockingly attempt to down() a semaphore.
+- * - returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int count, success = 0;
+-
+-#if SEMAPHORE_DEBUG
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-	count = atomic_read(&sem->count);
+-	if (likely(count > 0)) {
+-		atomic_set(&sem->count, count - 1);
+-		success = 1;
+-	}
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-	return !success;
+-}
+-
+-static inline void up(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-
+-#if SEMAPHORE_DEBUG
+-	CHECK_MAGIC(sem->__magic);
+-#endif
+-
+-	spin_lock_irqsave(&sem->wait_lock, flags);
+-	if (!list_empty(&sem->wait_list))
+-		__up(sem);
+-	else
+-		atomic_set(&sem->count, atomic_read(&sem->count) + 1);
+-	spin_unlock_irqrestore(&sem->wait_lock, flags);
+-}
+-
+-static inline int sem_getcount(struct semaphore *sem)
+-{
+-	return atomic_read(&sem->count);
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h
+index be8760f..db0c944 100644
+--- a/include/asm-parisc/ide.h
++++ b/include/asm-parisc/ide.h
+@@ -17,8 +17,6 @@
+ #define MAX_HWIFS	2
+ #endif
+ 
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+ #define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+ #define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+ #define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
+diff --git a/include/asm-parisc/semaphore-helper.h b/include/asm-parisc/semaphore-helper.h
+deleted file mode 100644
+index 387f7c1..0000000
+--- a/include/asm-parisc/semaphore-helper.h
++++ /dev/null
+@@ -1,89 +0,0 @@
+-#ifndef _ASM_PARISC_SEMAPHORE_HELPER_H
+-#define _ASM_PARISC_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- * (C) Copyright 1999 Andrea Arcangeli
+- */
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- *
+- * This is trivially done with load_locked/store_cond,
+- * which we have.  Let the rest of the losers suck eggs.
+- */
+-static __inline__ void wake_one_more(struct semaphore * sem)
+-{
+-	atomic_inc((atomic_t *)&sem->waking);
+-}
+-
+-static __inline__ int waking_non_zero(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->waking > 0) {
+-		sem->waking--;
+-		ret = 1;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- *	1	got the lock
+- *	0	go to sleep
+- *	-EINTR	interrupted
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+-						struct task_struct *tsk)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->waking > 0) {
+-		sem->waking--;
+-		ret = 1;
+-	} else if (signal_pending(tsk)) {
+-		atomic_inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- *	1	failed to lock
+- *	0	got the lock
+- *
+- * We must undo the sem->count down_trylock() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 1;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->waking <= 0)
+-		atomic_inc(&sem->count);
+-	else {
+-		sem->waking--;
+-		ret = 0;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-#endif /* _ASM_PARISC_SEMAPHORE_HELPER_H */
+diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
+index a16271c..d9b2034 100644
+--- a/include/asm-parisc/semaphore.h
++++ b/include/asm-parisc/semaphore.h
+@@ -1,145 +1 @@
+-/*    SMP- and interrupt-safe semaphores.
+- *    PA-RISC version by Matthew Wilcox
+- *
+- *    Linux/PA-RISC Project (http://www.parisc-linux.org/)
+- *    Copyright (C) 1996 Linus Torvalds
+- *    Copyright (C) 1999-2001 Matthew Wilcox < willy at debian d0T org >
+- *    Copyright (C) 2000 Grant Grundler < grundler a debian org >
+- *
+- *    This program is free software; you can redistribute it and/or modify
+- *    it under the terms of the GNU General Public License as published by
+- *    the Free Software Foundation; either version 2 of the License, or
+- *    (at your option) any later version.
+- *
+- *    This program is distributed in the hope that it will be useful,
+- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- *    GNU General Public License for more details.
+- *
+- *    You should have received a copy of the GNU General Public License
+- *    along with this program; if not, write to the Free Software
+- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+- */
+-
+-#ifndef _ASM_PARISC_SEMAPHORE_H
+-#define _ASM_PARISC_SEMAPHORE_H
+-
+-#include <linux/spinlock.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/system.h>
+-
+-/*
+- * The `count' is initialised to the number of people who are allowed to
+- * take the lock.  (Normally we want a mutex, so this is `1').  if
+- * `count' is positive, the lock can be taken.  if it's 0, no-one is
+- * waiting on it.  if it's -1, at least one task is waiting.
+- */
+-struct semaphore {
+-	spinlock_t	sentry;
+-	int		count;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.sentry		= SPIN_LOCK_UNLOCKED,				\
+-	.count		= n,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-static inline int sem_getcount(struct semaphore *sem)
+-{
+-	return sem->count;
+-}
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int  __down_interruptible(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-/* Semaphores can be `tried' from irq context.  So we have to disable
+- * interrupts while we're messing with the semaphore.  Sorry.
+- */
+-
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-	spin_lock_irq(&sem->sentry);
+-	if (sem->count > 0) {
+-		sem->count--;
+-	} else {
+-		__down(sem);
+-	}
+-	spin_unlock_irq(&sem->sentry);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-	might_sleep();
+-	spin_lock_irq(&sem->sentry);
+-	if (sem->count > 0) {
+-		sem->count--;
+-	} else {
+-		ret = __down_interruptible(sem);
+-	}
+-	spin_unlock_irq(&sem->sentry);
+-	return ret;
+-}
+-
+-/*
+- * down_trylock returns 0 on success, 1 if we failed to get the lock.
+- * May not sleep, but must preserve irq state
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	unsigned long flags;
+-	int count;
+-
+-	spin_lock_irqsave(&sem->sentry, flags);
+-	count = sem->count - 1;
+-	if (count >= 0)
+-		sem->count = count;
+-	spin_unlock_irqrestore(&sem->sentry, flags);
+-	return (count < 0);
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&sem->sentry, flags);
+-	if (sem->count < 0) {
+-		__up(sem);
+-	} else {
+-		sem->count++;
+-	}
+-	spin_unlock_irqrestore(&sem->sentry, flags);
+-}
+-
+-#endif /* _ASM_PARISC_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
+index 5f640e5..7381916 100644
+--- a/include/asm-powerpc/Kbuild
++++ b/include/asm-powerpc/Kbuild
+@@ -1,5 +1,6 @@
+ include include/asm-generic/Kbuild.asm
+ 
++header-y += a.out.h
+ header-y += auxvec.h
+ header-y += ioctls.h
+ header-y += mman.h
+@@ -23,7 +24,6 @@ header-y += sigcontext.h
+ header-y += statfs.h
+ header-y += ps3fb.h
+ 
+-unifdef-y += a.out.h
+ unifdef-y += asm-compat.h
+ unifdef-y += bootx.h
+ unifdef-y += byteorder.h
+diff --git a/include/asm-powerpc/abs_addr.h b/include/asm-powerpc/abs_addr.h
+index 4aa2207..98324c5 100644
+--- a/include/asm-powerpc/abs_addr.h
++++ b/include/asm-powerpc/abs_addr.h
+@@ -12,10 +12,11 @@
+  * 2 of the License, or (at your option) any later version.
+  */
+ 
++#include <linux/lmb.h>
++
+ #include <asm/types.h>
+ #include <asm/page.h>
+ #include <asm/prom.h>
+-#include <asm/lmb.h>
+ #include <asm/firmware.h>
+ 
+ struct mschunks_map {
+diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
+index 220d9a7..a99a749 100644
+--- a/include/asm-powerpc/bitops.h
++++ b/include/asm-powerpc/bitops.h
+@@ -312,24 +312,26 @@ static __inline__ int fls(unsigned int x)
+ 	asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+ 	return 32 - lz;
+ }
++
++/*
++ * 64-bit can do this using one cntlzd (count leading zeroes doubleword)
++ * instruction; for 32-bit we use the generic version, which does two
++ * 32-bit fls calls.
++ */
++#ifdef __powerpc64__
++static __inline__ int fls64(__u64 x)
++{
++	int lz;
++
++	asm ("cntlzd %0,%1" : "=r" (lz) : "r" (x));
++	return 64 - lz;
++}
++#else
+ #include <asm-generic/bitops/fls64.h>
++#endif /* __powerpc64__ */
+ 
+ #include <asm-generic/bitops/hweight.h>
+-
+-#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
+-unsigned long find_next_zero_bit(const unsigned long *addr,
+-				 unsigned long size, unsigned long offset);
+-/**
+- * 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, not the number of the byte
+- * containing a bit.
+- */
+-#define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
+-unsigned long find_next_bit(const unsigned long *addr,
+-			    unsigned long size, unsigned long offset);
++#include <asm-generic/bitops/find.h>
+ 
+ /* Little-endian versions */
+ 
+diff --git a/include/asm-powerpc/cpm.h b/include/asm-powerpc/cpm.h
+index 77e39da..ede38ff 100644
+--- a/include/asm-powerpc/cpm.h
++++ b/include/asm-powerpc/cpm.h
+@@ -4,6 +4,20 @@
+ #include <linux/compiler.h>
+ #include <linux/types.h>
+ 
++/* Opcodes common to CPM1 and CPM2
++*/
++#define CPM_CR_INIT_TRX		((ushort)0x0000)
++#define CPM_CR_INIT_RX		((ushort)0x0001)
++#define CPM_CR_INIT_TX		((ushort)0x0002)
++#define CPM_CR_HUNT_MODE	((ushort)0x0003)
++#define CPM_CR_STOP_TX		((ushort)0x0004)
++#define CPM_CR_GRA_STOP_TX	((ushort)0x0005)
++#define CPM_CR_RESTART_TX	((ushort)0x0006)
++#define CPM_CR_CLOSE_RX_BD	((ushort)0x0007)
++#define CPM_CR_SET_GADDR	((ushort)0x0008)
++#define CPM_CR_SET_TIMER	((ushort)0x0008)
++#define CPM_CR_STOP_IDMA	((ushort)0x000b)
++
+ /* Buffer descriptors used by many of the CPM protocols. */
+ typedef struct cpm_buf_desc {
+ 	ushort	cbd_sc;		/* Status and Control */
+diff --git a/include/asm-powerpc/cpm1.h b/include/asm-powerpc/cpm1.h
+index b2ebd6a..3df4396 100644
+--- a/include/asm-powerpc/cpm1.h
++++ b/include/asm-powerpc/cpm1.h
+@@ -28,19 +28,6 @@
+ #define CPM_CR_CHAN	((ushort)0x00f0)
+ #define CPM_CR_FLG	((ushort)0x0001)
+ 
+-/* Some commands (there are more...later)
+-*/
+-#define CPM_CR_INIT_TRX		((ushort)0x0000)
+-#define CPM_CR_INIT_RX		((ushort)0x0001)
+-#define CPM_CR_INIT_TX		((ushort)0x0002)
+-#define CPM_CR_HUNT_MODE	((ushort)0x0003)
+-#define CPM_CR_STOP_TX		((ushort)0x0004)
+-#define CPM_CR_GRA_STOP_TX	((ushort)0x0005)
+-#define CPM_CR_RESTART_TX	((ushort)0x0006)
+-#define CPM_CR_CLOSE_RX_BD	((ushort)0x0007)
+-#define CPM_CR_SET_GADDR	((ushort)0x0008)
+-#define CPM_CR_SET_TIMER	CPM_CR_SET_GADDR
+-
+ /* Channel numbers.
+ */
+ #define CPM_CR_CH_SCC1		((ushort)0x0000)
+diff --git a/include/asm-powerpc/cpm2.h b/include/asm-powerpc/cpm2.h
+index b93a53e..4c85ed9 100644
+--- a/include/asm-powerpc/cpm2.h
++++ b/include/asm-powerpc/cpm2.h
+@@ -71,18 +71,9 @@
+ 
+ #define CPM_CR_FCC_PAGE(x)	(x + 0x04)
+ 
+-/* Some opcodes (there are more...later)
++/* CPM2-specific opcodes (see cpm.h for common opcodes)
+ */
+-#define CPM_CR_INIT_TRX		((ushort)0x0000)
+-#define CPM_CR_INIT_RX		((ushort)0x0001)
+-#define CPM_CR_INIT_TX		((ushort)0x0002)
+-#define CPM_CR_HUNT_MODE	((ushort)0x0003)
+-#define CPM_CR_STOP_TX		((ushort)0x0004)
+-#define CPM_CR_GRA_STOP_TX	((ushort)0x0005)
+-#define CPM_CR_RESTART_TX	((ushort)0x0006)
+-#define CPM_CR_SET_GADDR	((ushort)0x0008)
+ #define CPM_CR_START_IDMA	((ushort)0x0009)
+-#define CPM_CR_STOP_IDMA	((ushort)0x000b)
+ 
+ #define mk_cr_cmd(PG, SBC, MCN, OP) \
+ 	((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+diff --git a/include/asm-powerpc/cputhreads.h b/include/asm-powerpc/cputhreads.h
+index 8485c28..fb11b0c 100644
+--- a/include/asm-powerpc/cputhreads.h
++++ b/include/asm-powerpc/cputhreads.h
+@@ -35,7 +35,7 @@ static inline cpumask_t cpu_thread_mask_to_cores(cpumask_t threads)
+ 
+ 	res = CPU_MASK_NONE;
+ 	for (i = 0; i < NR_CPUS; i += threads_per_core) {
+-		cpus_shift_right(tmp, threads_core_mask, i);
++		cpus_shift_left(tmp, threads_core_mask, i);
+ 		if (cpus_intersects(threads, tmp))
+ 			cpu_set(i, res);
+ 	}
+diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
+index be6c879..f8398ce 100644
+--- a/include/asm-powerpc/dcr-native.h
++++ b/include/asm-powerpc/dcr-native.h
+@@ -82,6 +82,19 @@ static inline void __mtdcri(int base_addr, int base_data, int reg,
+ 	spin_unlock_irqrestore(&dcr_ind_lock, flags);
+ }
+ 
++static inline void __dcri_clrset(int base_addr, int base_data, int reg,
++				 unsigned clr, unsigned set)
++{
++	unsigned long flags;
++	unsigned int val;
++
++	spin_lock_irqsave(&dcr_ind_lock, flags);
++	__mtdcr(base_addr, reg);
++	val = (__mfdcr(base_data) & ~clr) | set;
++	__mtdcr(base_data, val);
++	spin_unlock_irqrestore(&dcr_ind_lock, flags);
++}
++
+ #define mfdcri(base, reg)	__mfdcri(DCRN_ ## base ## _CONFIG_ADDR,	\
+ 					 DCRN_ ## base ## _CONFIG_DATA,	\
+ 					 reg)
+@@ -90,6 +103,10 @@ static inline void __mtdcri(int base_addr, int base_data, int reg,
+ 					 DCRN_ ## base ## _CONFIG_DATA,	\
+ 					 reg, data)
+ 
++#define dcri_clrset(base, reg, clr, set)	__dcri_clrset(DCRN_ ## base ## _CONFIG_ADDR,	\
++							      DCRN_ ## base ## _CONFIG_DATA,	\
++							      reg, clr, set)
++
+ #endif /* __ASSEMBLY__ */
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_DCR_NATIVE_H */
+diff --git a/include/asm-powerpc/dcr-regs.h b/include/asm-powerpc/dcr-regs.h
+index 9f1fb98..29b0ece 100644
+--- a/include/asm-powerpc/dcr-regs.h
++++ b/include/asm-powerpc/dcr-regs.h
+@@ -68,4 +68,82 @@
+ #define SDR0_UART3		0x0123
+ #define SDR0_CUST0		0x4000
+ 
++/*
++ * All those DCR register addresses are offsets from the base address
++ * for the SRAM0 controller (e.g. 0x20 on 440GX). The base address is
++ * excluded here and configured in the device tree.
++ */
++#define DCRN_SRAM0_SB0CR	0x00
++#define DCRN_SRAM0_SB1CR	0x01
++#define DCRN_SRAM0_SB2CR	0x02
++#define DCRN_SRAM0_SB3CR	0x03
++#define  SRAM_SBCR_BU_MASK	0x00000180
++#define  SRAM_SBCR_BS_64KB	0x00000800
++#define  SRAM_SBCR_BU_RO	0x00000080
++#define  SRAM_SBCR_BU_RW	0x00000180
++#define DCRN_SRAM0_BEAR		0x04
++#define DCRN_SRAM0_BESR0	0x05
++#define DCRN_SRAM0_BESR1	0x06
++#define DCRN_SRAM0_PMEG		0x07
++#define DCRN_SRAM0_CID		0x08
++#define DCRN_SRAM0_REVID	0x09
++#define DCRN_SRAM0_DPC		0x0a
++#define  SRAM_DPC_ENABLE	0x80000000
++
++/*
++ * All those DCR register addresses are offsets from the base address
++ * for the SRAM0 controller (e.g. 0x30 on 440GX). The base address is
++ * excluded here and configured in the device tree.
++ */
++#define DCRN_L2C0_CFG		0x00
++#define  L2C_CFG_L2M		0x80000000
++#define  L2C_CFG_ICU		0x40000000
++#define  L2C_CFG_DCU		0x20000000
++#define  L2C_CFG_DCW_MASK	0x1e000000
++#define  L2C_CFG_TPC		0x01000000
++#define  L2C_CFG_CPC		0x00800000
++#define  L2C_CFG_FRAN		0x00200000
++#define  L2C_CFG_SS_MASK	0x00180000
++#define  L2C_CFG_SS_256		0x00000000
++#define  L2C_CFG_CPIM		0x00040000
++#define  L2C_CFG_TPIM		0x00020000
++#define  L2C_CFG_LIM		0x00010000
++#define  L2C_CFG_PMUX_MASK	0x00007000
++#define  L2C_CFG_PMUX_SNP	0x00000000
++#define  L2C_CFG_PMUX_IF	0x00001000
++#define  L2C_CFG_PMUX_DF	0x00002000
++#define  L2C_CFG_PMUX_DS	0x00003000
++#define  L2C_CFG_PMIM		0x00000800
++#define  L2C_CFG_TPEI		0x00000400
++#define  L2C_CFG_CPEI		0x00000200
++#define  L2C_CFG_NAM		0x00000100
++#define  L2C_CFG_SMCM		0x00000080
++#define  L2C_CFG_NBRM		0x00000040
++#define  L2C_CFG_RDBW		0x00000008	/* only 460EX/GT */
++#define DCRN_L2C0_CMD		0x01
++#define  L2C_CMD_CLR		0x80000000
++#define  L2C_CMD_DIAG		0x40000000
++#define  L2C_CMD_INV		0x20000000
++#define  L2C_CMD_CCP		0x10000000
++#define  L2C_CMD_CTE		0x08000000
++#define  L2C_CMD_STRC		0x04000000
++#define  L2C_CMD_STPC		0x02000000
++#define  L2C_CMD_RPMC		0x01000000
++#define  L2C_CMD_HCC		0x00800000
++#define DCRN_L2C0_ADDR		0x02
++#define DCRN_L2C0_DATA		0x03
++#define DCRN_L2C0_SR		0x04
++#define  L2C_SR_CC		0x80000000
++#define  L2C_SR_CPE		0x40000000
++#define  L2C_SR_TPE		0x20000000
++#define  L2C_SR_LRU		0x10000000
++#define  L2C_SR_PCS		0x08000000
++#define DCRN_L2C0_REVID		0x05
++#define DCRN_L2C0_SNP0		0x06
++#define DCRN_L2C0_SNP1		0x07
++#define  L2C_SNP_BA_MASK	0xffff0000
++#define  L2C_SNP_SSR_MASK	0x0000f000
++#define  L2C_SNP_SSR_32G	0x0000f000
++#define  L2C_SNP_ESR		0x00000800
++
+ #endif /* __DCR_REGS_H__ */
+diff --git a/include/asm-powerpc/exception.h b/include/asm-powerpc/exception.h
+index 39abdb0..329148b 100644
+--- a/include/asm-powerpc/exception.h
++++ b/include/asm-powerpc/exception.h
+@@ -228,18 +228,18 @@ label##_pSeries:							\
+ BEGIN_FW_FTR_SECTION;				\
+ 	stb	r11,PACAHARDIRQEN(r13);		\
+ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES);	\
++	TRACE_DISABLE_INTS;			\
+ BEGIN_FW_FTR_SECTION;				\
+ 	mfmsr	r10;				\
+ 	ori	r10,r10,MSR_EE;			\
+ 	mtmsrd	r10,1;				\
+ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+-
+ #else
+ #define DISABLE_INTS				\
+ 	li	r11,0;				\
+ 	stb	r11,PACASOFTIRQEN(r13);		\
+-	stb	r11,PACAHARDIRQEN(r13)
+-
++	stb	r11,PACAHARDIRQEN(r13);		\
++	TRACE_DISABLE_INTS
+ #endif /* CONFIG_PPC_ISERIES */
+ 
+ #define ENABLE_INTS				\
+diff --git a/include/asm-powerpc/fixmap.h b/include/asm-powerpc/fixmap.h
+new file mode 100644
+index 0000000..8428b38
+--- /dev/null
++++ b/include/asm-powerpc/fixmap.h
+@@ -0,0 +1,106 @@
++/*
++ * fixmap.h: compile-time virtual memory allocation
++ *
++ * 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) 1998 Ingo Molnar
++ *
++ * Copyright 2008 Freescale Semiconductor Inc.
++ *   Port to powerpc added by Kumar Gala
++ */
++
++#ifndef _ASM_FIXMAP_H
++#define _ASM_FIXMAP_H
++
++extern unsigned long FIXADDR_TOP;
++
++#ifndef __ASSEMBLY__
++#include <linux/kernel.h>
++#include <asm/page.h>
++#ifdef CONFIG_HIGHMEM
++#include <linux/threads.h>
++#include <asm/kmap_types.h>
++#endif
++
++/*
++ * Here we define all the compile-time 'special' virtual
++ * addresses. The point is to have a constant address at
++ * compile time, but to set the physical address only
++ * in the boot process. We allocate these special addresses
++ * from the end of virtual memory (0xfffff000) backwards.
++ * Also this lets us do fail-safe vmalloc(), we
++ * can guarantee that these special addresses and
++ * vmalloc()-ed addresses never overlap.
++ *
++ * these 'compile-time allocated' memory buffers are
++ * fixed-size 4k pages. (or larger if used with an increment
++ * highger than 1) use fixmap_set(idx,phys) to associate
++ * physical memory with fixmap indices.
++ *
++ * TLB entries of such buffers will not be flushed across
++ * task switches.
++ */
++enum fixed_addresses {
++	FIX_HOLE,
++#ifdef CONFIG_HIGHMEM
++	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
++	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
++#endif
++	/* FIX_PCIE_MCFG, */
++	__end_of_fixed_addresses
++};
++
++extern void __set_fixmap (enum fixed_addresses idx,
++					phys_addr_t phys, pgprot_t flags);
++
++#define set_fixmap(idx, phys) \
++		__set_fixmap(idx, phys, PAGE_KERNEL)
++/*
++ * Some hardware wants to get fixmapped without caching.
++ */
++#define set_fixmap_nocache(idx, phys) \
++		__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
++
++#define clear_fixmap(idx) \
++		__set_fixmap(idx, 0, __pgprot(0))
++
++#define __FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
++#define FIXADDR_START		(FIXADDR_TOP - __FIXADDR_SIZE)
++
++#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
++#define __virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
++
++extern void __this_fixmap_does_not_exist(void);
++
++/*
++ * 'index to address' translation. If anyone tries to use the idx
++ * directly without tranlation, we catch the bug with a NULL-deference
++ * kernel oops. Illegal ranges of incoming indices are caught too.
++ */
++static __always_inline unsigned long fix_to_virt(const unsigned int idx)
++{
++	/*
++	 * this branch gets completely eliminated after inlining,
++	 * except when someone tries to use fixaddr indices in an
++	 * illegal way. (such as mixing up address types or using
++	 * out-of-range indices).
++	 *
++	 * If it doesn't get removed, the linker will complain
++	 * loudly with a reasonably clear error message..
++	 */
++	if (idx >= __end_of_fixed_addresses)
++		__this_fixmap_does_not_exist();
++
++        return __fix_to_virt(idx);
++}
++
++static inline unsigned long virt_to_fix(const unsigned long vaddr)
++{
++	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
++	return __virt_to_fix(vaddr);
++}
++
++#endif /* !__ASSEMBLY__ */
++#endif
+diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
+new file mode 100644
+index 0000000..303f548
+--- /dev/null
++++ b/include/asm-powerpc/fsl_lbc.h
+@@ -0,0 +1,311 @@
++/* Freescale Local Bus Controller
++ *
++ * Copyright (c) 2006-2007 Freescale Semiconductor
++ *
++ * Authors: Nick Spence <nick.spence at freescale.com>,
++ *          Scott Wood <scottwood at 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef __ASM_FSL_LBC_H
++#define __ASM_FSL_LBC_H
++
++#include <linux/types.h>
++#include <linux/spinlock.h>
++#include <asm/io.h>
++
++struct fsl_lbc_bank {
++	__be32 br;             /**< Base Register  */
++#define BR_BA           0xFFFF8000
++#define BR_BA_SHIFT             15
++#define BR_PS           0x00001800
++#define BR_PS_SHIFT             11
++#define BR_PS_8         0x00000800  /* Port Size 8 bit */
++#define BR_PS_16        0x00001000  /* Port Size 16 bit */
++#define BR_PS_32        0x00001800  /* Port Size 32 bit */
++#define BR_DECC         0x00000600
++#define BR_DECC_SHIFT            9
++#define BR_DECC_OFF     0x00000000  /* HW ECC checking and generation off */
++#define BR_DECC_CHK     0x00000200  /* HW ECC checking on, generation off */
++#define BR_DECC_CHK_GEN 0x00000400  /* HW ECC checking and generation on */
++#define BR_WP           0x00000100
++#define BR_WP_SHIFT              8
++#define BR_MSEL         0x000000E0
++#define BR_MSEL_SHIFT            5
++#define BR_MS_GPCM      0x00000000  /* GPCM */
++#define BR_MS_FCM       0x00000020  /* FCM */
++#define BR_MS_SDRAM     0x00000060  /* SDRAM */
++#define BR_MS_UPMA      0x00000080  /* UPMA */
++#define BR_MS_UPMB      0x000000A0  /* UPMB */
++#define BR_MS_UPMC      0x000000C0  /* UPMC */
++#define BR_V            0x00000001
++#define BR_V_SHIFT               0
++#define BR_RES          ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
++
++	__be32 or;             /**< Base Register  */
++#define OR0 0x5004
++#define OR1 0x500C
++#define OR2 0x5014
++#define OR3 0x501C
++#define OR4 0x5024
++#define OR5 0x502C
++#define OR6 0x5034
++#define OR7 0x503C
++
++#define OR_FCM_AM               0xFFFF8000
++#define OR_FCM_AM_SHIFT                 15
++#define OR_FCM_BCTLD            0x00001000
++#define OR_FCM_BCTLD_SHIFT              12
++#define OR_FCM_PGS              0x00000400
++#define OR_FCM_PGS_SHIFT                10
++#define OR_FCM_CSCT             0x00000200
++#define OR_FCM_CSCT_SHIFT                9
++#define OR_FCM_CST              0x00000100
++#define OR_FCM_CST_SHIFT                 8
++#define OR_FCM_CHT              0x00000080
++#define OR_FCM_CHT_SHIFT                 7
++#define OR_FCM_SCY              0x00000070
++#define OR_FCM_SCY_SHIFT                 4
++#define OR_FCM_SCY_1            0x00000010
++#define OR_FCM_SCY_2            0x00000020
++#define OR_FCM_SCY_3            0x00000030
++#define OR_FCM_SCY_4            0x00000040
++#define OR_FCM_SCY_5            0x00000050
++#define OR_FCM_SCY_6            0x00000060
++#define OR_FCM_SCY_7            0x00000070
++#define OR_FCM_RST              0x00000008
++#define OR_FCM_RST_SHIFT                 3
++#define OR_FCM_TRLX             0x00000004
++#define OR_FCM_TRLX_SHIFT                2
++#define OR_FCM_EHTR             0x00000002
++#define OR_FCM_EHTR_SHIFT                1
++};
++
++struct fsl_lbc_regs {
++	struct fsl_lbc_bank bank[8];
++	u8 res0[0x28];
++	__be32 mar;             /**< UPM Address Register */
++	u8 res1[0x4];
++	__be32 mamr;            /**< UPMA Mode Register */
++#define MxMR_OP_NO	(0 << 28) /**< normal operation */
++#define MxMR_OP_WA	(1 << 28) /**< write array */
++#define MxMR_OP_RA	(2 << 28) /**< read array */
++#define MxMR_OP_RP	(3 << 28) /**< run pattern */
++#define MxMR_MAD	0x3f      /**< machine address */
++	__be32 mbmr;            /**< UPMB Mode Register */
++	__be32 mcmr;            /**< UPMC Mode Register */
++	u8 res2[0x8];
++	__be32 mrtpr;           /**< Memory Refresh Timer Prescaler Register */
++	__be32 mdr;             /**< UPM Data Register */
++	u8 res3[0x4];
++	__be32 lsor;            /**< Special Operation Initiation Register */
++	__be32 lsdmr;           /**< SDRAM Mode Register */
++	u8 res4[0x8];
++	__be32 lurt;            /**< UPM Refresh Timer */
++	__be32 lsrt;            /**< SDRAM Refresh Timer */
++	u8 res5[0x8];
++	__be32 ltesr;           /**< Transfer Error Status Register */
++#define LTESR_BM   0x80000000
++#define LTESR_FCT  0x40000000
++#define LTESR_PAR  0x20000000
++#define LTESR_WP   0x04000000
++#define LTESR_ATMW 0x00800000
++#define LTESR_ATMR 0x00400000
++#define LTESR_CS   0x00080000
++#define LTESR_CC   0x00000001
++#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
++	__be32 ltedr;           /**< Transfer Error Disable Register */
++	__be32 lteir;           /**< Transfer Error Interrupt Register */
++	__be32 lteatr;          /**< Transfer Error Attributes Register */
++	__be32 ltear;           /**< Transfer Error Address Register */
++	u8 res6[0xC];
++	__be32 lbcr;            /**< Configuration Register */
++#define LBCR_LDIS  0x80000000
++#define LBCR_LDIS_SHIFT    31
++#define LBCR_BCTLC 0x00C00000
++#define LBCR_BCTLC_SHIFT   22
++#define LBCR_AHD   0x00200000
++#define LBCR_LPBSE 0x00020000
++#define LBCR_LPBSE_SHIFT   17
++#define LBCR_EPAR  0x00010000
++#define LBCR_EPAR_SHIFT    16
++#define LBCR_BMT   0x0000FF00
++#define LBCR_BMT_SHIFT      8
++#define LBCR_INIT  0x00040000
++	__be32 lcrr;            /**< Clock Ratio Register */
++#define LCRR_DBYP    0x80000000
++#define LCRR_DBYP_SHIFT      31
++#define LCRR_BUFCMDC 0x30000000
++#define LCRR_BUFCMDC_SHIFT   28
++#define LCRR_ECL     0x03000000
++#define LCRR_ECL_SHIFT       24
++#define LCRR_EADC    0x00030000
++#define LCRR_EADC_SHIFT      16
++#define LCRR_CLKDIV  0x0000000F
++#define LCRR_CLKDIV_SHIFT     0
++	u8 res7[0x8];
++	__be32 fmr;             /**< Flash Mode Register */
++#define FMR_CWTO     0x0000F000
++#define FMR_CWTO_SHIFT       12
++#define FMR_BOOT     0x00000800
++#define FMR_ECCM     0x00000100
++#define FMR_AL       0x00000030
++#define FMR_AL_SHIFT          4
++#define FMR_OP       0x00000003
++#define FMR_OP_SHIFT          0
++	__be32 fir;             /**< Flash Instruction Register */
++#define FIR_OP0      0xF0000000
++#define FIR_OP0_SHIFT        28
++#define FIR_OP1      0x0F000000
++#define FIR_OP1_SHIFT        24
++#define FIR_OP2      0x00F00000
++#define FIR_OP2_SHIFT        20
++#define FIR_OP3      0x000F0000
++#define FIR_OP3_SHIFT        16
++#define FIR_OP4      0x0000F000
++#define FIR_OP4_SHIFT        12
++#define FIR_OP5      0x00000F00
++#define FIR_OP5_SHIFT         8
++#define FIR_OP6      0x000000F0
++#define FIR_OP6_SHIFT         4
++#define FIR_OP7      0x0000000F
++#define FIR_OP7_SHIFT         0
++#define FIR_OP_NOP   0x0	/* No operation and end of sequence */
++#define FIR_OP_CA    0x1        /* Issue current column address */
++#define FIR_OP_PA    0x2        /* Issue current block+page address */
++#define FIR_OP_UA    0x3        /* Issue user defined address */
++#define FIR_OP_CM0   0x4        /* Issue command from FCR[CMD0] */
++#define FIR_OP_CM1   0x5        /* Issue command from FCR[CMD1] */
++#define FIR_OP_CM2   0x6        /* Issue command from FCR[CMD2] */
++#define FIR_OP_CM3   0x7        /* Issue command from FCR[CMD3] */
++#define FIR_OP_WB    0x8        /* Write FBCR bytes from FCM buffer */
++#define FIR_OP_WS    0x9        /* Write 1 or 2 bytes from MDR[AS] */
++#define FIR_OP_RB    0xA        /* Read FBCR bytes to FCM buffer */
++#define FIR_OP_RS    0xB        /* Read 1 or 2 bytes to MDR[AS] */
++#define FIR_OP_CW0   0xC        /* Wait then issue FCR[CMD0] */
++#define FIR_OP_CW1   0xD        /* Wait then issue FCR[CMD1] */
++#define FIR_OP_RBW   0xE        /* Wait then read FBCR bytes */
++#define FIR_OP_RSW   0xE        /* Wait then read 1 or 2 bytes */
++	__be32 fcr;             /**< Flash Command Register */
++#define FCR_CMD0     0xFF000000
++#define FCR_CMD0_SHIFT       24
++#define FCR_CMD1     0x00FF0000
++#define FCR_CMD1_SHIFT       16
++#define FCR_CMD2     0x0000FF00
++#define FCR_CMD2_SHIFT        8
++#define FCR_CMD3     0x000000FF
++#define FCR_CMD3_SHIFT        0
++	__be32 fbar;            /**< Flash Block Address Register */
++#define FBAR_BLK     0x00FFFFFF
++	__be32 fpar;            /**< Flash Page Address Register */
++#define FPAR_SP_PI   0x00007C00
++#define FPAR_SP_PI_SHIFT     10
++#define FPAR_SP_MS   0x00000200
++#define FPAR_SP_CI   0x000001FF
++#define FPAR_SP_CI_SHIFT      0
++#define FPAR_LP_PI   0x0003F000
++#define FPAR_LP_PI_SHIFT     12
++#define FPAR_LP_MS   0x00000800
++#define FPAR_LP_CI   0x000007FF
++#define FPAR_LP_CI_SHIFT      0
++	__be32 fbcr;            /**< Flash Byte Count Register */
++#define FBCR_BC      0x00000FFF
++	u8 res11[0x8];
++	u8 res8[0xF00];
++};
++
++extern struct fsl_lbc_regs __iomem *fsl_lbc_regs;
++extern spinlock_t fsl_lbc_lock;
++
++/*
++ * FSL UPM routines
++ */
++struct fsl_upm {
++	__be32 __iomem *mxmr;
++	int width;
++};
++
++extern int fsl_lbc_find(phys_addr_t addr_base);
++extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
++
++/**
++ * fsl_upm_start_pattern - start UPM patterns execution
++ * @upm:	pointer to the fsl_upm structure obtained via fsl_upm_find
++ * @pat_offset:	UPM pattern offset for the command to be executed
++ *
++ * This routine programmes UPM so the next memory access that hits an UPM
++ * will trigger pattern execution, starting at pat_offset.
++ */
++static inline void fsl_upm_start_pattern(struct fsl_upm *upm, u8 pat_offset)
++{
++	clrsetbits_be32(upm->mxmr, MxMR_MAD, MxMR_OP_RP | pat_offset);
++}
++
++/**
++ * fsl_upm_end_pattern - end UPM patterns execution
++ * @upm:	pointer to the fsl_upm structure obtained via fsl_upm_find
++ *
++ * This routine reverts UPM to normal operation mode.
++ */
++static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
++{
++	clrbits32(upm->mxmr, MxMR_OP_RP);
++
++	while (in_be32(upm->mxmr) & MxMR_OP_RP)
++		cpu_relax();
++}
++
++/**
++ * fsl_upm_run_pattern - actually run an UPM pattern
++ * @upm:	pointer to the fsl_upm structure obtained via fsl_upm_find
++ * @io_base:	remapped pointer to where memory access should happen
++ * @mar:	MAR register content during pattern execution
++ *
++ * This function triggers dummy write to the memory specified by the io_base,
++ * thus UPM pattern actually executed. Note that mar usage depends on the
++ * pre-programmed AMX bits in the UPM RAM.
++ */
++static inline int fsl_upm_run_pattern(struct fsl_upm *upm,
++				      void __iomem *io_base, u32 mar)
++{
++	int ret = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&fsl_lbc_lock, flags);
++
++	out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
++
++	switch (upm->width) {
++	case 8:
++		out_8(io_base, 0x0);
++		break;
++	case 16:
++		out_be16(io_base, 0x0);
++		break;
++	case 32:
++		out_be32(io_base, 0x0);
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	spin_unlock_irqrestore(&fsl_lbc_lock, flags);
++
++	return ret;
++}
++
++#endif /* __ASM_FSL_LBC_H */
+diff --git a/include/asm-powerpc/gpio.h b/include/asm-powerpc/gpio.h
+new file mode 100644
+index 0000000..77ad3a8
+--- /dev/null
++++ b/include/asm-powerpc/gpio.h
+@@ -0,0 +1,56 @@
++/*
++ * Generic GPIO API implementation for PowerPC.
++ *
++ * Copyright (c) 2007-2008  MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at 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 __ASM_POWERPC_GPIO_H
++#define __ASM_POWERPC_GPIO_H
++
++#include <linux/errno.h>
++#include <asm-generic/gpio.h>
++
++#ifdef CONFIG_HAVE_GPIO_LIB
++
++/*
++ * We don't (yet) implement inlined/rapid versions for on-chip gpios.
++ * Just call gpiolib.
++ */
++static inline int gpio_get_value(unsigned int gpio)
++{
++	return __gpio_get_value(gpio);
++}
++
++static inline void gpio_set_value(unsigned int gpio, int value)
++{
++	__gpio_set_value(gpio, value);
++}
++
++static inline int gpio_cansleep(unsigned int gpio)
++{
++	return __gpio_cansleep(gpio);
++}
++
++/*
++ * Not implemented, yet.
++ */
++static inline int gpio_to_irq(unsigned int gpio)
++{
++	return -ENOSYS;
++}
++
++static inline int irq_to_gpio(unsigned int irq)
++{
++	return -EINVAL;
++}
++
++#endif /* CONFIG_HAVE_GPIO_LIB */
++
++#endif /* __ASM_POWERPC_GPIO_H */
+diff --git a/include/asm-powerpc/highmem.h b/include/asm-powerpc/highmem.h
+index f7b21ee..5d99b64 100644
+--- a/include/asm-powerpc/highmem.h
++++ b/include/asm-powerpc/highmem.h
+@@ -27,9 +27,7 @@
+ #include <asm/kmap_types.h>
+ #include <asm/tlbflush.h>
+ #include <asm/page.h>
+-
+-/* undef for production */
+-#define HIGHMEM_DEBUG 1
++#include <asm/fixmap.h>
+ 
+ extern pte_t *kmap_pte;
+ extern pgprot_t kmap_prot;
+@@ -40,14 +38,12 @@ extern pte_t *pkmap_page_table;
+  * easily, subsequent pte tables have to be allocated in one physical
+  * chunk of RAM.
+  */
+-#define PKMAP_BASE 	CONFIG_HIGHMEM_START
+ #define LAST_PKMAP 	(1 << PTE_SHIFT)
+ #define LAST_PKMAP_MASK (LAST_PKMAP-1)
++#define PKMAP_BASE	((FIXADDR_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK)
+ #define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
+ #define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+ 
+-#define KMAP_FIX_BEGIN	(PKMAP_BASE + 0x00400000UL)
+-
+ extern void *kmap_high(struct page *page);
+ extern void kunmap_high(struct page *page);
+ 
+@@ -73,7 +69,7 @@ static inline void kunmap(struct page *page)
+  * be used in IRQ contexts, so in some (very limited) cases we need
+  * it.
+  */
+-static inline void *kmap_atomic(struct page *page, enum km_type type)
++static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+ {
+ 	unsigned int idx;
+ 	unsigned long vaddr;
+@@ -84,34 +80,39 @@ static inline void *kmap_atomic(struct page *page, enum km_type type)
+ 		return page_address(page);
+ 
+ 	idx = type + KM_TYPE_NR*smp_processor_id();
+-	vaddr = KMAP_FIX_BEGIN + idx * PAGE_SIZE;
+-#ifdef HIGHMEM_DEBUG
+-	BUG_ON(!pte_none(*(kmap_pte+idx)));
++	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++#ifdef CONFIG_DEBUG_HIGHMEM
++	BUG_ON(!pte_none(*(kmap_pte-idx)));
+ #endif
+-	set_pte_at(&init_mm, vaddr, kmap_pte+idx, mk_pte(page, kmap_prot));
++	set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
+ 	flush_tlb_page(NULL, vaddr);
+ 
+ 	return (void*) vaddr;
+ }
+ 
++static inline void *kmap_atomic(struct page *page, enum km_type type)
++{
++	return kmap_atomic_prot(page, type, kmap_prot);
++}
++
+ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
+ {
+-#ifdef HIGHMEM_DEBUG
++#ifdef CONFIG_DEBUG_HIGHMEM
+ 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+-	unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
++	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+ 
+-	if (vaddr < KMAP_FIX_BEGIN) { // FIXME
++	if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
+ 		pagefault_enable();
+ 		return;
+ 	}
+ 
+-	BUG_ON(vaddr != KMAP_FIX_BEGIN + idx * PAGE_SIZE);
++	BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+ 
+ 	/*
+ 	 * force other mappings to Oops if they'll try to access
+ 	 * this pte without first remap it
+ 	 */
+-	pte_clear(&init_mm, vaddr, kmap_pte+idx);
++	pte_clear(&init_mm, vaddr, kmap_pte-idx);
+ 	flush_tlb_page(NULL, vaddr);
+ #endif
+ 	pagefault_enable();
+@@ -120,12 +121,14 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
+ static inline struct page *kmap_atomic_to_page(void *ptr)
+ {
+ 	unsigned long idx, vaddr = (unsigned long) ptr;
++	pte_t *pte;
+ 
+-	if (vaddr < KMAP_FIX_BEGIN)
++	if (vaddr < FIXADDR_START)
+ 		return virt_to_page(ptr);
+ 
+-	idx = (vaddr - KMAP_FIX_BEGIN) >> PAGE_SHIFT;
+-	return pte_page(kmap_pte[idx]);
++	idx = virt_to_fix(vaddr);
++	pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
++	return pte_page(*pte);
+ }
+ 
+ #define flush_cache_kmaps()	flush_cache_all()
+diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
+index a7b60bf..ad8c9f7 100644
+--- a/include/asm-powerpc/hw_irq.h
++++ b/include/asm-powerpc/hw_irq.h
+@@ -27,7 +27,7 @@ static inline unsigned long local_get_flags(void)
+ 	return flags;
+ }
+ 
+-static inline unsigned long local_irq_disable(void)
++static inline unsigned long raw_local_irq_disable(void)
+ {
+ 	unsigned long flags, zero;
+ 
+@@ -39,14 +39,15 @@ static inline unsigned long local_irq_disable(void)
+ 	return flags;
+ }
+ 
+-extern void local_irq_restore(unsigned long);
++extern void raw_local_irq_restore(unsigned long);
+ extern void iseries_handle_interrupts(void);
+ 
+-#define local_irq_enable()	local_irq_restore(1)
+-#define local_save_flags(flags)	((flags) = local_get_flags())
+-#define local_irq_save(flags)	((flags) = local_irq_disable())
++#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())
+ 
+-#define irqs_disabled()		(local_get_flags() == 0)
++#define raw_irqs_disabled()		(local_get_flags() == 0)
++#define raw_irqs_disabled_flags(flags)	((flags) == 0)
+ 
+ #define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
+ #define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
+diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h
+index 6d50310..3d90bf7 100644
+--- a/include/asm-powerpc/ide.h
++++ b/include/asm-powerpc/ide.h
+@@ -31,39 +31,48 @@
+ #include <linux/hdreg.h>
+ #include <linux/ioport.h>
+ 
+-struct ide_machdep_calls {
+-        int         (*default_irq)(unsigned long base);
+-        unsigned long (*default_io_base)(int index);
+-        void        (*ide_init_hwif)(hw_regs_t *hw,
+-                                     unsigned long data_port,
+-                                     unsigned long ctrl_port,
+-                                     int *irq);
+-};
+-
+-extern struct ide_machdep_calls ppc_ide_md;
+-
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
++/* FIXME: use ide_platform host driver */
+ static __inline__ int ide_default_irq(unsigned long base)
+ {
+-	if (ppc_ide_md.default_irq)
+-		return ppc_ide_md.default_irq(base);
++#ifdef CONFIG_PPLUS
++	switch (base) {
++	case 0x1f0:	return 14;
++	case 0x170:	return 15;
++	}
++#endif
++#ifdef CONFIG_PPC_PREP
++	switch (base) {
++	case 0x1f0:	return 13;
++	case 0x170:	return 13;
++	case 0x1e8:	return 11;
++	case 0x168:	return 10;
++	case 0xfff0:	return 14;	/* MCP(N)750 ide0 */
++	case 0xffe0:	return 15;	/* MCP(N)750 ide1 */
++	}
++#endif
+ 	return 0;
+ }
+ 
++/* FIXME: use ide_platform host driver */
+ static __inline__ unsigned long ide_default_io_base(int index)
+ {
+-	if (ppc_ide_md.default_io_base)
+-		return ppc_ide_md.default_io_base(index);
++#ifdef CONFIG_PPLUS
++	switch (index) {
++	case 0:		return 0x1f0;
++	case 1:		return 0x170;
++	}
++#endif
++#ifdef CONFIG_PPC_PREP
++	switch (index) {
++	case 0:		return 0x1f0;
++	case 1:		return 0x170;
++	case 2:		return 0x1e8;
++	case 3:		return 0x168;
++	}
++#endif
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_PCI
+-#define ide_init_default_irq(base)	(0)
+-#else
+-#define ide_init_default_irq(base)	ide_default_irq(base)
+-#endif
+-
+ #ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+ #define IDE_ARCH_ACK_INTR  1
+ #define ide_ack_intr(hwif) ((hwif)->ack_intr ? (hwif)->ack_intr(hwif) : 1)
+@@ -71,8 +80,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
+ 
+ #endif /* __powerpc64__ */
+ 
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+ #endif /* __KERNEL__ */
+ 
+ #endif /* _ASM_POWERPC_IDE_H */
+diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
+index 82a4526..7b6f411 100644
+--- a/include/asm-powerpc/immap_qe.h
++++ b/include/asm-powerpc/immap_qe.h
+@@ -20,6 +20,7 @@
+ #ifdef __KERNEL__
+ 
+ #include <linux/kernel.h>
++#include <asm/io.h>
+ 
+ #define QE_IMMAP_SIZE	(1024 * 1024)	/* 1MB from 1MB+IMMR */
+ 
+@@ -468,7 +469,7 @@ struct qe_immap {
+ 	u8			res18[0xC0000];	/* 0x140000 - 0x200000 */
+ } __attribute__ ((packed));
+ 
+-extern struct qe_immap *qe_immr;
++extern struct qe_immap __iomem *qe_immr;
+ extern phys_addr_t get_qe_base(void);
+ 
+ static inline unsigned long immrbar_virt_to_phys(void *address)
+diff --git a/include/asm-powerpc/io-defs.h b/include/asm-powerpc/io-defs.h
+index 03691ab..44d7927 100644
+--- a/include/asm-powerpc/io-defs.h
++++ b/include/asm-powerpc/io-defs.h
+@@ -1,59 +1,60 @@
+ /* This file is meant to be include multiple times by other headers */
++/* last 2 argments are used by platforms/cell/io-workarounds.[ch] */
+ 
+-DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readw_be, u16, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readl_be, u32, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writew_be, (u16 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writel_be, (u32 val, PCI_IO_ADDR addr), (val, addr))
++DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readw_be, u16, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readl_be, u32, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writew_be, (u16 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writel_be, (u32 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
+ 
+ #ifdef __powerpc64__
+-DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr))
++DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
+ #endif /* __powerpc64__ */
+ 
+-DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port))
+-DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port))
+-DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port))
+-DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port))
+-DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port))
+-DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port))
++DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port), pio, port)
++DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port), pio, port)
++DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port), pio, port)
++DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port), pio, port)
++DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port), pio, port)
++DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port), pio, port)
+ 
+-DEF_PCI_AC_NORET(readsb, (const PCI_IO_ADDR a, void *b, unsigned long c), \
+-		 (a, b, c))
+-DEF_PCI_AC_NORET(readsw, (const PCI_IO_ADDR a, void *b, unsigned long c), \
+-		 (a, b, c))
+-DEF_PCI_AC_NORET(readsl, (const PCI_IO_ADDR a, void *b, unsigned long c), \
+-		 (a, b, c))
+-DEF_PCI_AC_NORET(writesb, (PCI_IO_ADDR a, const void *b, unsigned long c), \
+-		 (a, b, c))
+-DEF_PCI_AC_NORET(writesw, (PCI_IO_ADDR a, const void *b, unsigned long c), \
+-		 (a, b, c))
+-DEF_PCI_AC_NORET(writesl, (PCI_IO_ADDR a, const void *b, unsigned long c), \
+-		 (a, b, c))
++DEF_PCI_AC_NORET(readsb, (const PCI_IO_ADDR a, void *b, unsigned long c),
++		 (a, b, c), mem, a)
++DEF_PCI_AC_NORET(readsw, (const PCI_IO_ADDR a, void *b, unsigned long c),
++		 (a, b, c), mem, a)
++DEF_PCI_AC_NORET(readsl, (const PCI_IO_ADDR a, void *b, unsigned long c),
++		 (a, b, c), mem, a)
++DEF_PCI_AC_NORET(writesb, (PCI_IO_ADDR a, const void *b, unsigned long c),
++		 (a, b, c), mem, a)
++DEF_PCI_AC_NORET(writesw, (PCI_IO_ADDR a, const void *b, unsigned long c),
++		 (a, b, c), mem, a)
++DEF_PCI_AC_NORET(writesl, (PCI_IO_ADDR a, const void *b, unsigned long c),
++		 (a, b, c), mem, a)
+ 
+-DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c), \
+-		 (p, b, c))
+-DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c), \
+-		 (p, b, c))
+-DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c), \
+-		 (p, b, c))
+-DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c), \
+-		 (p, b, c))
+-DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c), \
+-		 (p, b, c))
+-DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c), \
+-		 (p, b, c))
++DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c),
++		 (p, b, c), pio, p)
++DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c),
++		 (p, b, c), pio, p)
++DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c),
++		 (p, b, c), pio, p)
++DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c),
++		 (p, b, c), pio, p)
++DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c),
++		 (p, b, c), pio, p)
++DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c),
++		 (p, b, c), pio, p)
+ 
+-DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n),	   \
+-		 (a, c, n))
+-DEF_PCI_AC_NORET(memcpy_fromio,(void *d,const PCI_IO_ADDR s,unsigned long n), \
+-		 (d, s, n))
+-DEF_PCI_AC_NORET(memcpy_toio,(PCI_IO_ADDR d,const void *s,unsigned long n),   \
+-		 (d, s, n))
++DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n),
++		 (a, c, n), mem, a)
++DEF_PCI_AC_NORET(memcpy_fromio, (void *d, const PCI_IO_ADDR s, unsigned long n),
++		 (d, s, n), mem, s)
++DEF_PCI_AC_NORET(memcpy_toio, (PCI_IO_ADDR d, const void *s, unsigned long n),
++		 (d, s, n), mem, d)
+diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
+index 7be26f6..afae069 100644
+--- a/include/asm-powerpc/io.h
++++ b/include/asm-powerpc/io.h
+@@ -458,8 +458,8 @@ __do_out_asm(_rec_outl, "stwbrx")
+ /* Structure containing all the hooks */
+ extern struct ppc_pci_io {
+ 
+-#define DEF_PCI_AC_RET(name, ret, at, al)	ret (*name) at;
+-#define DEF_PCI_AC_NORET(name, at, al)		void (*name) at;
++#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)	ret (*name) at;
++#define DEF_PCI_AC_NORET(name, at, al, space, aa)	void (*name) at;
+ 
+ #include <asm/io-defs.h>
+ 
+@@ -469,7 +469,7 @@ extern struct ppc_pci_io {
+ } ppc_pci_io;
+ 
+ /* The inline wrappers */
+-#define DEF_PCI_AC_RET(name, ret, at, al)			\
++#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)		\
+ static inline ret name at					\
+ {								\
+ 	if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL)		\
+@@ -477,7 +477,7 @@ static inline ret name at					\
+ 	return __do_##name al;					\
+ }
+ 
+-#define DEF_PCI_AC_NORET(name, at, al)				\
++#define DEF_PCI_AC_NORET(name, at, al, space, aa)		\
+ static inline void name at					\
+ {								\
+ 	if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL)		\
+diff --git a/include/asm-powerpc/irqflags.h b/include/asm-powerpc/irqflags.h
+index 7970cba..cc6fdba 100644
+--- a/include/asm-powerpc/irqflags.h
++++ b/include/asm-powerpc/irqflags.h
+@@ -2,30 +2,43 @@
+  * include/asm-powerpc/irqflags.h
+  *
+  * IRQ flags handling
+- *
+- * This file gets included from lowlevel asm headers too, to provide
+- * wrapped versions of the local_irq_*() APIs, based on the
+- * raw_local_irq_*() macros from the lowlevel headers.
+  */
+ #ifndef _ASM_IRQFLAGS_H
+ #define _ASM_IRQFLAGS_H
+ 
++#ifndef __ASSEMBLY__
+ /*
+  * Get definitions for raw_local_save_flags(x), etc.
+  */
+ #include <asm-powerpc/hw_irq.h>
+ 
++#else
++#ifdef CONFIG_TRACE_IRQFLAGS
+ /*
+- * Do the CPU's IRQ-state tracing from assembly code. We call a
+- * C function, so save all the C-clobbered registers:
++ * Most of the CPU's IRQ-state tracing is done from assembly code; we
++ * have to call a C function so call a wrapper that saves all the
++ * C-clobbered registers.
+  */
+-#ifdef CONFIG_TRACE_IRQFLAGS
+-
+-#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
+-
++#define TRACE_ENABLE_INTS	bl .trace_hardirqs_on
++#define TRACE_DISABLE_INTS	bl .trace_hardirqs_off
++#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)	\
++	cmpdi	en, 0;				\
++	bne	95f;				\
++	stb	en,PACASOFTIRQEN(r13);		\
++	bl	.trace_hardirqs_off;		\
++	b	skip;				\
++95:	bl	.trace_hardirqs_on;		\
++	li	en,1;
++#define TRACE_AND_RESTORE_IRQ(en)		\
++	TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f);	\
++96:	stb	en,PACASOFTIRQEN(r13)
+ #else
+-# define TRACE_IRQS_ON
+-# define TRACE_IRQS_OFF
++#define TRACE_ENABLE_INTS
++#define TRACE_DISABLE_INTS
++#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)
++#define TRACE_AND_RESTORE_IRQ(en)		\
++	stb	en,PACASOFTIRQEN(r13)
++#endif
+ #endif
+ 
+ #endif
+diff --git a/include/asm-powerpc/iseries/alpaca.h b/include/asm-powerpc/iseries/alpaca.h
+new file mode 100644
+index 0000000..c0cce67
+--- /dev/null
++++ b/include/asm-powerpc/iseries/alpaca.h
+@@ -0,0 +1,31 @@
++/*
++ * Copyright © 2008  Stephen Rothwell IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
++ */
++#ifndef _ASM_POWERPC_ISERIES_ALPACA_H
++#define _ASM_POWERPC_ISERIES_ALPACA_H
++
++/*
++ * This is the part of the paca that the iSeries hypervisor
++ * needs to be statically initialised. Immediately after boot
++ * we switch to the normal Linux paca.
++ */
++struct alpaca {
++	struct lppaca *lppaca_ptr;	/* Pointer to LpPaca for PLIC */
++	const void *reg_save_ptr;	/* Pointer to LpRegSave for PLIC */
++};
++
++#endif /* _ASM_POWERPC_ISERIES_ALPACA_H */
+diff --git a/include/asm-powerpc/iseries/it_lp_reg_save.h b/include/asm-powerpc/iseries/it_lp_reg_save.h
+deleted file mode 100644
+index 5403b75..0000000
+--- a/include/asm-powerpc/iseries/it_lp_reg_save.h
++++ /dev/null
+@@ -1,85 +0,0 @@
+-/*
+- * Copyright (C) 2001  Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+- */
+-#ifndef _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H
+-#define _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H
+-
+-/*
+- * This control block contains the data that is shared between PLIC
+- * and the OS
+- */
+-
+-struct ItLpRegSave {
+-	u32	xDesc;		// Eye catcher  "LpRS" ebcdic	000-003
+-	u16	xSize;		// Size of this class		004-005
+-	u8	xInUse;         // Area is live                 006-007
+-	u8	xRsvd1[9];	// Reserved			007-00F
+-
+-	u8      xFixedRegSave[352]; // Fixed Register Save Area 010-16F
+-	u32	xCTRL;		// Control Register		170-173
+-	u32	xDEC;		// Decrementer			174-177
+-	u32	xFPSCR;		// FP Status and Control Reg	178-17B
+-	u32	xPVR;		// Processor Version Number	17C-17F
+-
+-	u64	xMMCR0;		// Monitor Mode Control Reg 0	180-187
+-	u32	xPMC1;		// Perf Monitor Counter 1	188-18B
+-	u32	xPMC2;		// Perf Monitor Counter 2	18C-18F
+-	u32	xPMC3;		// Perf Monitor Counter 3	190-193
+-	u32	xPMC4;		// Perf Monitor Counter 4	194-197
+-	u32	xPIR;		// Processor ID Reg		198-19B
+-
+-	u32	xMMCR1;		// Monitor Mode Control Reg 1	19C-19F
+-	u32	xMMCRA;		// Monitor Mode Control Reg A	1A0-1A3
+-	u32	xPMC5;		// Perf Monitor Counter 5	1A4-1A7
+-	u32	xPMC6;		// Perf Monitor Counter 6	1A8-1AB
+-	u32	xPMC7;		// Perf Monitor Counter 7	1AC-1AF
+-	u32	xPMC8;		// Perf Monitor Counter 8	1B0-1B3
+-	u32	xTSC;		// Thread Switch Control	1B4-1B7
+-	u32	xTST;		// Thread Switch Timeout	1B8-1BB
+-	u32	xRsvd;          // Reserved                     1BC-1BF
+-
+-	u64	xACCR;		// Address Compare Control Reg	1C0-1C7
+-	u64	xIMR;		// Instruction Match Register	1C8-1CF
+-	u64	xSDR1;		// Storage Description Reg 1	1D0-1D7
+-	u64	xSPRG0;		// Special Purpose Reg General0	1D8-1DF
+-	u64	xSPRG1;		// Special Purpose Reg General1	1E0-1E7
+-	u64	xSPRG2;		// Special Purpose Reg General2	1E8-1EF
+-	u64	xSPRG3;		// Special Purpose Reg General3	1F0-1F7
+-	u64	xTB;		// Time Base Register		1F8-1FF
+-
+-	u64	xFPR[32];	// Floating Point Registers	200-2FF
+-
+-	u64	xMSR;		// Machine State Register	300-307
+-	u64	xNIA;		// Next Instruction Address	308-30F
+-
+-	u64	xDABR;		// Data Address Breakpoint Reg	310-317
+-	u64	xIABR;		// Inst Address Breakpoint Reg	318-31F
+-
+-	u64	xHID0;		// HW Implementation Dependent0	320-327
+-
+-	u64	xHID4;		// HW Implementation Dependent4	328-32F
+-	u64	xSCOMd;		// SCON Data Reg (SPRG4)	330-337
+-	u64	xSCOMc;		// SCON Command Reg (SPRG5)	338-33F
+-	u64	xSDAR;		// Sample Data Address Register	340-347
+-	u64	xSIAR;		// Sample Inst Address Register	348-34F
+-
+-	u8	xRsvd3[176];	// Reserved			350-3FF
+-};
+-
+-extern struct ItLpRegSave iseries_reg_save[];
+-
+-#endif /* _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H */
+diff --git a/include/asm-powerpc/kdump.h b/include/asm-powerpc/kdump.h
+index 10e8eb1..f6c93c7 100644
+--- a/include/asm-powerpc/kdump.h
++++ b/include/asm-powerpc/kdump.h
+@@ -11,16 +11,11 @@
+ 
+ #ifdef CONFIG_CRASH_DUMP
+ 
+-#define PHYSICAL_START	KDUMP_KERNELBASE
+ #define KDUMP_TRAMPOLINE_START	0x0100
+ #define KDUMP_TRAMPOLINE_END	0x3000
+ 
+ #define KDUMP_MIN_TCE_ENTRIES	2048
+ 
+-#else /* !CONFIG_CRASH_DUMP */
+-
+-#define PHYSICAL_START	0x0
+-
+ #endif /* CONFIG_CRASH_DUMP */
+ 
+ #ifndef __ASSEMBLY__
+diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h
+index 5d1dc48..6f5fdf0 100644
+--- a/include/asm-powerpc/lmb.h
++++ b/include/asm-powerpc/lmb.h
+@@ -1,81 +1,15 @@
+ #ifndef _ASM_POWERPC_LMB_H
+ #define _ASM_POWERPC_LMB_H
+-#ifdef __KERNEL__
+ 
+-/*
+- * Definitions for talking to the Open Firmware PROM on
+- * Power Macintosh computers.
+- *
+- * Copyright (C) 2001 Peter Bergner, IBM Corp.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
++#include <asm/udbg.h>
+ 
+-#include <linux/init.h>
+-#include <asm/prom.h>
++#define LMB_DBG(fmt...) udbg_printf(fmt)
+ 
+-#define MAX_LMB_REGIONS 128
++#ifdef CONFIG_PPC32
++extern phys_addr_t lowmem_end_addr;
++#define LMB_REAL_LIMIT	lowmem_end_addr
++#else
++#define LMB_REAL_LIMIT	0
++#endif
+ 
+-struct lmb_property {
+-	unsigned long base;
+-	unsigned long size;
+-};
+-
+-struct lmb_region {
+-	unsigned long cnt;
+-	unsigned long size;
+-	struct lmb_property region[MAX_LMB_REGIONS+1];
+-};
+-
+-struct lmb {
+-	unsigned long debug;
+-	unsigned long rmo_size;
+-	struct lmb_region memory;
+-	struct lmb_region reserved;
+-};
+-
+-extern struct lmb lmb;
+-
+-extern void __init lmb_init(void);
+-extern void __init lmb_analyze(void);
+-extern long __init lmb_add(unsigned long base, unsigned long size);
+-extern long __init lmb_reserve(unsigned long base, unsigned long size);
+-extern unsigned long __init lmb_alloc(unsigned long size, unsigned long align);
+-extern unsigned long __init lmb_alloc_base(unsigned long size,
+-		unsigned long align, unsigned long max_addr);
+-extern unsigned long __init __lmb_alloc_base(unsigned long size,
+-		unsigned long align, unsigned long max_addr);
+-extern unsigned long __init lmb_phys_mem_size(void);
+-extern unsigned long __init lmb_end_of_DRAM(void);
+-extern void __init lmb_enforce_memory_limit(unsigned long memory_limit);
+-extern int __init lmb_is_reserved(unsigned long addr);
+-
+-extern void lmb_dump_all(void);
+-
+-static inline unsigned long
+-lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
+-{
+-	return type->region[region_nr].size;
+-}
+-static inline unsigned long
+-lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
+-{
+-	return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
+-}
+-static inline unsigned long
+-lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
+-{
+-	return type->region[region_nr].base >> PAGE_SHIFT;
+-}
+-static inline unsigned long
+-lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
+-{
+-	return lmb_start_pfn(type, region_nr) +
+-	       lmb_size_pages(type, region_nr);
+-}
+-
+-#endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_LMB_H */
+diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
+index 0872ec2..54ed64d 100644
+--- a/include/asm-powerpc/machdep.h
++++ b/include/asm-powerpc/machdep.h
+@@ -68,6 +68,8 @@ struct machdep_calls {
+ 				       unsigned long vflags,
+ 				       int psize, int ssize);
+ 	long		(*hpte_remove)(unsigned long hpte_group);
++	void            (*hpte_removebolted)(unsigned long ea,
++					     int psize, int ssize);
+ 	void		(*flush_hash_range)(unsigned long number, int local);
+ 
+ 	/* special for kexec, to be called in real mode, linar mapping is
+@@ -196,9 +198,6 @@ struct machdep_calls {
+ 	   May be NULL. */
+ 	void		(*init)(void);
+ 
+-	void		(*setup_io_mappings)(void);
+-
+-	void		(*early_serial_map)(void);
+ 	void		(*kgdb_map_scc)(void);
+ 
+ 	/*
+diff --git a/include/asm-powerpc/macio.h b/include/asm-powerpc/macio.h
+index 3a6cb1a..079c06e 100644
+--- a/include/asm-powerpc/macio.h
++++ b/include/asm-powerpc/macio.h
+@@ -2,7 +2,7 @@
+ #define __MACIO_ASIC_H__
+ #ifdef __KERNEL__
+ 
+-#include <asm/of_device.h>
++#include <linux/of_device.h>
+ 
+ extern struct bus_type macio_bus_type;
+ 
+diff --git a/include/asm-powerpc/mediabay.h b/include/asm-powerpc/mediabay.h
+index de83fe1..df111c3 100644
+--- a/include/asm-powerpc/mediabay.h
++++ b/include/asm-powerpc/mediabay.h
+@@ -22,10 +22,14 @@ int check_media_bay(struct device_node *which_bay, int what);
+ /* Number of bays in the machine or 0 */
+ extern int media_bay_count;
+ 
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
++#include <linux/ide.h>
++
+ int check_media_bay_by_base(unsigned long base, int what);
+ /* called by IDE PMAC host driver to register IDE controller for media bay */
+ int media_bay_set_ide_infos(struct device_node *which_bay, unsigned long base,
+-			    int irq, int index);
++			    int irq, ide_hwif_t *hwif);
++#endif
+ 
+ #endif /* __KERNEL__ */
+ #endif /* _PPC_MEDIABAY_H */
+diff --git a/include/asm-powerpc/mmu-40x.h b/include/asm-powerpc/mmu-40x.h
+index 7d37f77..3d10867 100644
+--- a/include/asm-powerpc/mmu-40x.h
++++ b/include/asm-powerpc/mmu-40x.h
+@@ -53,8 +53,6 @@
+ 
+ #ifndef __ASSEMBLY__
+ 
+-typedef unsigned long phys_addr_t;
+-
+ typedef struct {
+ 	unsigned long id;
+ 	unsigned long vdso_base;
+diff --git a/include/asm-powerpc/mmu-44x.h b/include/asm-powerpc/mmu-44x.h
+index 62772ae..c8b02d9 100644
+--- a/include/asm-powerpc/mmu-44x.h
++++ b/include/asm-powerpc/mmu-44x.h
+@@ -53,8 +53,6 @@
+ 
+ #ifndef __ASSEMBLY__
+ 
+-typedef unsigned long long phys_addr_t;
+-
+ typedef struct {
+ 	unsigned long id;
+ 	unsigned long vdso_base;
+diff --git a/include/asm-powerpc/mmu-8xx.h b/include/asm-powerpc/mmu-8xx.h
+index 952bd88..9db877e 100644
+--- a/include/asm-powerpc/mmu-8xx.h
++++ b/include/asm-powerpc/mmu-8xx.h
+@@ -136,8 +136,6 @@
+ #define SPRN_M_TW	799
+ 
+ #ifndef __ASSEMBLY__
+-typedef unsigned long phys_addr_t;
+-
+ typedef struct {
+ 	unsigned long id;
+ 	unsigned long vdso_base;
+diff --git a/include/asm-powerpc/mmu-fsl-booke.h b/include/asm-powerpc/mmu-fsl-booke.h
+index 3758000..925d93c 100644
+--- a/include/asm-powerpc/mmu-fsl-booke.h
++++ b/include/asm-powerpc/mmu-fsl-booke.h
+@@ -73,12 +73,6 @@
+ 
+ #ifndef __ASSEMBLY__
+ 
+-#ifndef CONFIG_PHYS_64BIT
+-typedef unsigned long phys_addr_t;
+-#else
+-typedef unsigned long long phys_addr_t;
+-#endif
+-
+ typedef struct {
+ 	unsigned long id;
+ 	unsigned long vdso_base;
+diff --git a/include/asm-powerpc/mmu-hash32.h b/include/asm-powerpc/mmu-hash32.h
+index 4bd735b..6e21ca6 100644
+--- a/include/asm-powerpc/mmu-hash32.h
++++ b/include/asm-powerpc/mmu-hash32.h
+@@ -84,8 +84,6 @@ typedef struct {
+ 	unsigned long vdso_base;
+ } mm_context_t;
+ 
+-typedef unsigned long phys_addr_t;
+-
+ #endif /* !__ASSEMBLY__ */
+ 
+ #endif /* _ASM_POWERPC_MMU_HASH32_H_ */
+diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h
+index 2864fa3..0dff767 100644
+--- a/include/asm-powerpc/mmu-hash64.h
++++ b/include/asm-powerpc/mmu-hash64.h
+@@ -469,9 +469,6 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
+ 				 VSID_MODULUS_256M)
+ #define KERNEL_VSID(ea)		VSID_SCRAMBLE(GET_ESID(ea))
+ 
+-/* Physical address used by some IO functions */
+-typedef unsigned long phys_addr_t;
+-
+ #endif /* __ASSEMBLY__ */
+ 
+ #endif /* _ASM_POWERPC_MMU_HASH64_H_ */
+diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
+index 748b35a..7b56444 100644
+--- a/include/asm-powerpc/paca.h
++++ b/include/asm-powerpc/paca.h
+@@ -42,10 +42,7 @@ struct task_struct;
+  * Defines the layout of the paca.
+  *
+  * This structure is not directly accessed by firmware or the service
+- * processor except for the first two pointers that point to the
+- * lppaca area and the ItLpRegSave area for this CPU.  The lppaca
+- * object is currently contained within the PACA but it doesn't need
+- * to be.
++ * processor.
+  */
+ struct paca_struct {
+ 	/*
+@@ -55,14 +52,7 @@ struct paca_struct {
+ 	 * avoid cacheline bouncing.
+ 	 */
+ 
+-	/*
+-	 * MAGIC: These first two pointers can't be moved - they're
+-	 * accessed by the firmware
+-	 */
+ 	struct lppaca *lppaca_ptr;	/* Pointer to LpPaca for PLIC */
+-#ifdef CONFIG_PPC_ISERIES
+-	void *reg_save_ptr; /* Pointer to LpRegSave for PLIC */
+-#endif /* CONFIG_PPC_ISERIES */
+ 
+ 	/*
+ 	 * MAGIC: the spinlock functions in arch/powerpc/lib/locks.c 
+@@ -118,6 +108,7 @@ struct paca_struct {
+ };
+ 
+ extern struct paca_struct paca[];
++extern void initialise_pacas(void);
+ 
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_PACA_H */
+diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h
+index df47bbb..cffdf0e 100644
+--- a/include/asm-powerpc/page.h
++++ b/include/asm-powerpc/page.h
+@@ -12,6 +12,7 @@
+ 
+ #include <asm/asm-compat.h>
+ #include <asm/kdump.h>
++#include <asm/types.h>
+ 
+ /*
+  * On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software
+@@ -42,8 +43,23 @@
+  *
+  * The kdump dump kernel is one example where KERNELBASE != PAGE_OFFSET.
+  *
+- * To get a physical address from a virtual one you subtract PAGE_OFFSET,
+- * _not_ KERNELBASE.
++ * PAGE_OFFSET is the virtual address of the start of lowmem.
++ *
++ * PHYSICAL_START is the physical address of the start of the kernel.
++ *
++ * MEMORY_START is the physical address of the start of lowmem.
++ *
++ * KERNELBASE, PAGE_OFFSET, and PHYSICAL_START are all configurable on
++ * ppc32 and based on how they are set we determine MEMORY_START.
++ *
++ * For the linear mapping the following equation should be true:
++ * KERNELBASE - PAGE_OFFSET = PHYSICAL_START - MEMORY_START
++ *
++ * Also, KERNELBASE >= PAGE_OFFSET and PHYSICAL_START >= MEMORY_START
++ *
++ * There are two was to determine a physical address from a virtual one:
++ * va = pa + PAGE_OFFSET - MEMORY_START
++ * va = pa + KERNELBASE - PHYSICAL_START
+  *
+  * If you want to know something's offset from the start of the kernel you
+  * should subtract KERNELBASE.
+@@ -51,19 +67,33 @@
+  * If you want to test if something's a kernel address, use is_kernel_addr().
+  */
+ 
+-#define PAGE_OFFSET     ASM_CONST(CONFIG_KERNEL_START)
+-#define KERNELBASE      (PAGE_OFFSET + PHYSICAL_START)
++#define KERNELBASE      ASM_CONST(CONFIG_KERNEL_START)
++#define PAGE_OFFSET	ASM_CONST(CONFIG_PAGE_OFFSET)
++#define LOAD_OFFSET	ASM_CONST((CONFIG_KERNEL_START-CONFIG_PHYSICAL_START))
++
++#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_FLATMEM)
++#ifndef __ASSEMBLY__
++extern phys_addr_t memstart_addr;
++extern phys_addr_t kernstart_addr;
++#endif
++#define PHYSICAL_START	kernstart_addr
++#define MEMORY_START	memstart_addr
++#else
++#define PHYSICAL_START	ASM_CONST(CONFIG_PHYSICAL_START)
++#define MEMORY_START	(PHYSICAL_START + PAGE_OFFSET - KERNELBASE)
++#endif
+ 
+ #ifdef CONFIG_FLATMEM
+-#define pfn_valid(pfn)		((pfn) < max_mapnr)
++#define ARCH_PFN_OFFSET		(MEMORY_START >> PAGE_SHIFT)
++#define pfn_valid(pfn)		((pfn) >= ARCH_PFN_OFFSET && (pfn) < (ARCH_PFN_OFFSET + max_mapnr))
+ #endif
+ 
+ #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+ #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+ #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+ 
+-#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+-#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
++#define __va(x) ((void *)((unsigned long)(x) - PHYSICAL_START + KERNELBASE))
++#define __pa(x) ((unsigned long)(x) + PHYSICAL_START - KERNELBASE)
+ 
+ /*
+  * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
+diff --git a/include/asm-powerpc/page_32.h b/include/asm-powerpc/page_32.h
+index 65ea19e..ebfae53 100644
+--- a/include/asm-powerpc/page_32.h
++++ b/include/asm-powerpc/page_32.h
+@@ -1,9 +1,13 @@
+ #ifndef _ASM_POWERPC_PAGE_32_H
+ #define _ASM_POWERPC_PAGE_32_H
+ 
+-#define VM_DATA_DEFAULT_FLAGS	VM_DATA_DEFAULT_FLAGS32
++#if defined(CONFIG_PHYSICAL_ALIGN) && (CONFIG_PHYSICAL_START != 0)
++#if (CONFIG_PHYSICAL_START % CONFIG_PHYSICAL_ALIGN) != 0
++#error "CONFIG_PHYSICAL_START must be a multiple of CONFIG_PHYSICAL_ALIGN"
++#endif
++#endif
+ 
+-#define PPC_MEMSTART	0
++#define VM_DATA_DEFAULT_FLAGS	VM_DATA_DEFAULT_FLAGS32
+ 
+ #ifdef CONFIG_NOT_COHERENT_CACHE
+ #define ARCH_KMALLOC_MINALIGN	L1_CACHE_BYTES
+diff --git a/include/asm-powerpc/pasemi_dma.h b/include/asm-powerpc/pasemi_dma.h
+index b4526ff..19fd793 100644
+--- a/include/asm-powerpc/pasemi_dma.h
++++ b/include/asm-powerpc/pasemi_dma.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2006 PA Semi, Inc
++ * Copyright (C) 2006-2008 PA Semi, Inc
+  *
+  * Hardware register layout and descriptor formats for the on-board
+  * DMA engine on PA Semi PWRficient. Used by ethernet, function and security
+@@ -40,6 +40,11 @@ enum {
+ 	PAS_DMA_COM_TXSTA = 0x104,	/* Transmit Status Register   */
+ 	PAS_DMA_COM_RXCMD = 0x108,	/* Receive Command Register   */
+ 	PAS_DMA_COM_RXSTA = 0x10c,	/* Receive Status Register    */
++	PAS_DMA_COM_CFG   = 0x114,	/* Common config reg	      */
++	PAS_DMA_TXF_SFLG0 = 0x140,	/* Set flags                  */
++	PAS_DMA_TXF_SFLG1 = 0x144,	/* Set flags                  */
++	PAS_DMA_TXF_CFLG0 = 0x148,	/* Set flags                  */
++	PAS_DMA_TXF_CFLG1 = 0x14c,	/* Set flags                  */
+ };
+ 
+ 
+@@ -123,11 +128,16 @@ enum {
+ #define    PAS_DMA_TXCHAN_TCMDSTA_DA	0x00000100
+ #define PAS_DMA_TXCHAN_CFG(c)     (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
+ #define    PAS_DMA_TXCHAN_CFG_TY_IFACE	0x00000000	/* Type = interface */
++#define    PAS_DMA_TXCHAN_CFG_TY_COPY	0x00000001	/* Type = copy only */
++#define    PAS_DMA_TXCHAN_CFG_TY_FUNC	0x00000002	/* Type = function */
++#define    PAS_DMA_TXCHAN_CFG_TY_XOR	0x00000003	/* Type = xor only */
+ #define    PAS_DMA_TXCHAN_CFG_TATTR_M	0x0000003c
+ #define    PAS_DMA_TXCHAN_CFG_TATTR_S	2
+ #define    PAS_DMA_TXCHAN_CFG_TATTR(x)	(((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
+ 					 PAS_DMA_TXCHAN_CFG_TATTR_M)
+-#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000001c0
++#define    PAS_DMA_TXCHAN_CFG_LPDQ	0x00000800
++#define    PAS_DMA_TXCHAN_CFG_LPSQ	0x00000400
++#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000003c0
+ #define    PAS_DMA_TXCHAN_CFG_WT_S	6
+ #define    PAS_DMA_TXCHAN_CFG_WT(x)	(((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
+ 					 PAS_DMA_TXCHAN_CFG_WT_M)
+@@ -394,11 +404,62 @@ enum {
+ 				 XCT_COPY_LLEN_M)
+ #define XCT_COPY_SE		0x0000000000000001ull
+ 
++/* Function descriptor fields */
++#define XCT_FUN_T		0x8000000000000000ull
++#define XCT_FUN_ST		0x4000000000000000ull
++#define XCT_FUN_RR_M		0x3000000000000000ull
++#define XCT_FUN_RR_NORES	0x0000000000000000ull
++#define XCT_FUN_RR_8BRES	0x1000000000000000ull
++#define XCT_FUN_RR_24BRES	0x2000000000000000ull
++#define XCT_FUN_RR_40BRES	0x3000000000000000ull
++#define XCT_FUN_I		0x0800000000000000ull
++#define XCT_FUN_O		0x0400000000000000ull
++#define XCT_FUN_E		0x0200000000000000ull
++#define XCT_FUN_FUN_M		0x01c0000000000000ull
++#define XCT_FUN_FUN_S		54
++#define XCT_FUN_FUN(x)		((((long)(x)) << XCT_FUN_FUN_S) & XCT_FUN_FUN_M)
++#define XCT_FUN_CRM_M		0x0038000000000000ull
++#define XCT_FUN_CRM_NOP		0x0000000000000000ull
++#define XCT_FUN_CRM_SIG		0x0008000000000000ull
++#define XCT_FUN_LLEN_M		0x0007ffff00000000ull
++#define XCT_FUN_LLEN_S		32
++#define XCT_FUN_LLEN(x)		((((long)(x)) << XCT_FUN_LLEN_S) & XCT_FUN_LLEN_M)
++#define XCT_FUN_SHL_M		0x00000000f8000000ull
++#define XCT_FUN_SHL_S		27
++#define XCT_FUN_SHL(x)		((((long)(x)) << XCT_FUN_SHL_S) & XCT_FUN_SHL_M)
++#define XCT_FUN_CHL_M		0x0000000007c00000ull
++#define XCT_FUN_HSZ_M		0x00000000003c0000ull
++#define XCT_FUN_ALG_M		0x0000000000038000ull
++#define XCT_FUN_HP		0x0000000000004000ull
++#define XCT_FUN_BCM_M		0x0000000000003800ull
++#define XCT_FUN_BCP_M		0x0000000000000600ull
++#define XCT_FUN_SIG_M		0x00000000000001f0ull
++#define XCT_FUN_SIG_TCP4	0x0000000000000140ull
++#define XCT_FUN_SIG_TCP6	0x0000000000000150ull
++#define XCT_FUN_SIG_UDP4	0x0000000000000160ull
++#define XCT_FUN_SIG_UDP6	0x0000000000000170ull
++#define XCT_FUN_A		0x0000000000000008ull
++#define XCT_FUN_C		0x0000000000000004ull
++#define XCT_FUN_AL2		0x0000000000000002ull
++#define XCT_FUN_SE		0x0000000000000001ull
++
++/* Function descriptor 8byte result fields */
++#define XCT_FUNRES_8B_CS_M	0x0000ffff00000000ull
++#define XCT_FUNRES_8B_CS_S	32
++#define XCT_FUNRES_8B_CRC_M	0x00000000ffffffffull
++#define XCT_FUNRES_8B_CRC_S	0
++
+ /* Control descriptor fields */
+ #define CTRL_CMD_T		0x8000000000000000ull
+ #define CTRL_CMD_META_EVT	0x2000000000000000ull
+ #define CTRL_CMD_O		0x0400000000000000ull
+-#define CTRL_CMD_REG_M		0x000000000000000full
++#define CTRL_CMD_ETYPE_M	0x0038000000000000ull
++#define CTRL_CMD_ETYPE_EXT	0x0000000000000000ull
++#define CTRL_CMD_ETYPE_WSET	0x0020000000000000ull
++#define CTRL_CMD_ETYPE_WCLR	0x0028000000000000ull
++#define CTRL_CMD_ETYPE_SET	0x0030000000000000ull
++#define CTRL_CMD_ETYPE_CLR	0x0038000000000000ull
++#define CTRL_CMD_REG_M		0x000000000000007full
+ #define CTRL_CMD_REG_S		0
+ #define CTRL_CMD_REG(x)		((((long)(x)) << CTRL_CMD_REG_S) & \
+ 				 CTRL_CMD_REG_M)
+@@ -461,6 +522,16 @@ extern void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
+ extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
+ 				dma_addr_t *handle);
+ 
++/* Routines to allocate flags (events) for channel syncronization */
++extern int  pasemi_dma_alloc_flag(void);
++extern void pasemi_dma_free_flag(int flag);
++extern void pasemi_dma_set_flag(int flag);
++extern void pasemi_dma_clear_flag(int flag);
++
++/* Routines to allocate function engines */
++extern int  pasemi_dma_alloc_fun(void);
++extern void pasemi_dma_free_fun(int fun);
++
+ /* Initialize the library, must be called before any other functions */
+ extern int pasemi_dma_init(void);
+ 
+diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
+index e5802c6..b95d033 100644
+--- a/include/asm-powerpc/pci-bridge.h
++++ b/include/asm-powerpc/pci-bridge.h
+@@ -117,7 +117,7 @@ struct pci_controller {
+ 
+ #ifndef CONFIG_PPC64
+ 
+-static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
++static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
+ {
+ 	return bus->sysdata;
+ }
+@@ -235,7 +235,7 @@ extern void pcibios_fixup_new_pci_devices(struct pci_bus *bus);
+ 
+ extern int pcibios_remove_root_bus(struct pci_controller *phb);
+ 
+-static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
++static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
+ {
+ 	struct device_node *busdn = bus->sysdata;
+ 
+diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
+index 2c79f55..daea769 100644
+--- a/include/asm-powerpc/pgtable-ppc32.h
++++ b/include/asm-powerpc/pgtable-ppc32.h
+@@ -98,9 +98,6 @@ extern int icache_44x_need_flush;
+ #define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
+ #define FIRST_USER_ADDRESS	0
+ 
+-#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+-#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
+-
+ #define pte_ERROR(e) \
+ 	printk("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \
+ 		(unsigned long long)pte_val(e))
+@@ -420,7 +417,8 @@ extern int icache_44x_need_flush;
+ #define _PAGE_IO	(_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED)
+ #define _PAGE_RAM	(_PAGE_KERNEL | _PAGE_HWEXEC)
+ 
+-#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH)
++#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
++	defined(CONFIG_KPROBES)
+ /* We want the debuggers to be able to set breakpoints anywhere, so
+  * don't write protect the kernel text */
+ #define _PAGE_RAM_TEXT	_PAGE_RAM
+@@ -692,7 +690,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ #define pmd_page_vaddr(pmd)	\
+ 	((unsigned long) (pmd_val(pmd) & PAGE_MASK))
+ #define pmd_page(pmd)		\
+-	(mem_map + (__pa(pmd_val(pmd)) >> PAGE_SHIFT))
++	pfn_to_page((__pa(pmd_val(pmd)) >> PAGE_SHIFT))
+ #endif
+ 
+ /* to find an entry in a kernel page-table-directory */
+diff --git a/include/asm-powerpc/phyp_dump.h b/include/asm-powerpc/phyp_dump.h
+new file mode 100644
+index 0000000..fa74c6c
+--- /dev/null
++++ b/include/asm-powerpc/phyp_dump.h
+@@ -0,0 +1,47 @@
++/*
++ * Hypervisor-assisted dump
++ *
++ * Linas Vepstas, Manish Ahuja 2008
++ * Copyright 2008 IBM Corp.
++ *
++ *      This program is free software; you can redistribute it and/or
++ *      modify it under the terms of the GNU General Public License
++ *      as published by the Free Software Foundation; either version
++ *      2 of the License, or (at your option) any later version.
++ */
++
++#ifndef _PPC64_PHYP_DUMP_H
++#define _PPC64_PHYP_DUMP_H
++
++#ifdef CONFIG_PHYP_DUMP
++
++/* The RMR region will be saved for later dumping
++ * whenever the kernel crashes. Set this to 256MB. */
++#define PHYP_DUMP_RMR_START 0x0
++#define PHYP_DUMP_RMR_END   (1UL<<28)
++
++struct phyp_dump {
++	/* Memory that is reserved during very early boot. */
++	unsigned long init_reserve_start;
++	unsigned long init_reserve_size;
++	/* cmd line options during boot */
++	unsigned long reserve_bootvar;
++	unsigned long phyp_dump_at_boot;
++	/* Check status during boot if dump supported, active & present*/
++	unsigned long phyp_dump_configured;
++	unsigned long phyp_dump_is_active;
++	/* store cpu & hpte size */
++	unsigned long cpu_state_size;
++	unsigned long hpte_region_size;
++	/* previous scratch area values */
++	unsigned long reserved_scratch_addr;
++	unsigned long reserved_scratch_size;
++};
++
++extern struct phyp_dump *phyp_dump_info;
++
++int early_init_dt_scan_phyp_dump(unsigned long node,
++		const char *uname, int depth, void *data);
++
++#endif /* CONFIG_PHYP_DUMP */
++#endif /* _PPC64_PHYP_DUMP_H */
+diff --git a/include/asm-powerpc/pmi.h b/include/asm-powerpc/pmi.h
+index 2259d4c..e1dc090 100644
+--- a/include/asm-powerpc/pmi.h
++++ b/include/asm-powerpc/pmi.h
+@@ -29,8 +29,6 @@
+ 
+ #ifdef __KERNEL__
+ 
+-#include <asm/of_device.h>
+-
+ #define PMI_TYPE_FREQ_CHANGE	0x01
+ #define PMI_READ_TYPE		0
+ #define PMI_READ_DATA0		1
+diff --git a/include/asm-powerpc/ppc4xx.h b/include/asm-powerpc/ppc4xx.h
+new file mode 100644
+index 0000000..033039a
+--- /dev/null
++++ b/include/asm-powerpc/ppc4xx.h
+@@ -0,0 +1,18 @@
++/*
++ * PPC4xx Prototypes and definitions
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ */
++
++#ifndef __ASM_POWERPC_PPC4xx_H__
++#define __ASM_POWERPC_PPC4xx_H__
++
++extern void ppc4xx_reset_system(char *cmd);
++
++#endif /* __ASM_POWERPC_PPC4xx_H__ */
+diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
+index 2b69367..9e8ed68 100644
+--- a/include/asm-powerpc/ps3.h
++++ b/include/asm-powerpc/ps3.h
+@@ -434,8 +434,11 @@ struct ps3_sys_manager_ops {
+ };
+ 
+ void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops);
+-void ps3_sys_manager_power_off(void);
+-void ps3_sys_manager_restart(void);
++void __noreturn ps3_sys_manager_power_off(void);
++void __noreturn ps3_sys_manager_restart(void);
++void __noreturn ps3_sys_manager_halt(void);
++int ps3_sys_manager_get_wol(void);
++void ps3_sys_manager_set_wol(int state);
+ 
+ struct ps3_prealloc {
+     const char *name;
+diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h
+index 891d689..39023dd 100644
+--- a/include/asm-powerpc/ptrace.h
++++ b/include/asm-powerpc/ptrace.h
+@@ -58,6 +58,11 @@ struct pt_regs {
+ #define __ARCH_WANT_COMPAT_SYS_PTRACE
+ 
+ #define STACK_FRAME_OVERHEAD	112	/* size of minimum stack frame */
++#define STACK_FRAME_LR_SAVE	2	/* Location of LR in stack frame */
++#define STACK_FRAME_REGS_MARKER	ASM_CONST(0x7265677368657265)
++#define STACK_INT_FRAME_SIZE	(sizeof(struct pt_regs) + \
++					STACK_FRAME_OVERHEAD + 288)
++#define STACK_FRAME_MARKER	12
+ 
+ /* Size of dummy stack frame allocated when calling signal handler. */
+ #define __SIGNAL_FRAMESIZE	128
+@@ -66,6 +71,10 @@ struct pt_regs {
+ #else /* __powerpc64__ */
+ 
+ #define STACK_FRAME_OVERHEAD	16	/* size of minimum stack frame */
++#define STACK_FRAME_LR_SAVE	1	/* Location of LR in stack frame */
++#define STACK_FRAME_REGS_MARKER	ASM_CONST(0x72656773)
++#define STACK_INT_FRAME_SIZE	(sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
++#define STACK_FRAME_MARKER	2
+ 
+ /* Size of stack frame allocated when calling signal handler. */
+ #define __SIGNAL_FRAMESIZE	64
+diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
+index 430dc77..c3be6e2 100644
+--- a/include/asm-powerpc/qe.h
++++ b/include/asm-powerpc/qe.h
+@@ -85,6 +85,7 @@ extern int par_io_data_set(u8 port, u8 pin, u8 val);
+ /* QE internal API */
+ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
+ enum qe_clock qe_clock_source(const char *source);
++unsigned int qe_get_brg_clk(void);
+ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
+ int qe_get_snum(void);
+ void qe_put_snum(u8 snum);
+@@ -92,7 +93,16 @@ unsigned long qe_muram_alloc(int size, int align);
+ int qe_muram_free(unsigned long offset);
+ unsigned long qe_muram_alloc_fixed(unsigned long offset, int size);
+ void qe_muram_dump(void);
+-void *qe_muram_addr(unsigned long offset);
++
++static inline void __iomem *qe_muram_addr(unsigned long offset)
++{
++	return (void __iomem *)&qe_immr->muram[offset];
++}
++
++static inline unsigned long qe_muram_offset(void __iomem *addr)
++{
++	return addr - (void __iomem *)qe_immr->muram;
++}
+ 
+ /* Structure that defines QE firmware binary files.
+  *
+diff --git a/include/asm-powerpc/rwsem.h b/include/asm-powerpc/rwsem.h
+index cefc147..a6cc93b 100644
+--- a/include/asm-powerpc/rwsem.h
++++ b/include/asm-powerpc/rwsem.h
+@@ -32,11 +32,20 @@ struct rw_semaphore {
+ #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+ 	spinlock_t		wait_lock;
+ 	struct list_head	wait_list;
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++	struct lockdep_map	dep_map;
++#endif
+ };
+ 
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
++#else
++# define __RWSEM_DEP_MAP_INIT(lockname)
++#endif
++
+ #define __RWSEM_INITIALIZER(name) \
+-	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+-	  LIST_HEAD_INIT((name).wait_list) }
++	{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
++	  LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
+ 
+ #define DECLARE_RWSEM(name)		\
+ 	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+@@ -46,12 +55,15 @@ extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+ extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+ extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+ 
+-static inline void init_rwsem(struct rw_semaphore *sem)
+-{
+-	sem->count = RWSEM_UNLOCKED_VALUE;
+-	spin_lock_init(&sem->wait_lock);
+-	INIT_LIST_HEAD(&sem->wait_list);
+-}
++extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
++			 struct lock_class_key *key);
++
++#define init_rwsem(sem)					\
++	do {						\
++		static struct lock_class_key __key;	\
++							\
++		__init_rwsem((sem), #sem, &__key);	\
++	} while (0)
+ 
+ /*
+  * lock for reading
+@@ -78,7 +90,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
+ /*
+  * lock for writing
+  */
+-static inline void __down_write(struct rw_semaphore *sem)
++static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+ {
+ 	int tmp;
+ 
+@@ -88,6 +100,11 @@ static inline void __down_write(struct rw_semaphore *sem)
+ 		rwsem_down_write_failed(sem);
+ }
+ 
++static inline void __down_write(struct rw_semaphore *sem)
++{
++	__down_write_nested(sem, 0);
++}
++
+ static inline int __down_write_trylock(struct rw_semaphore *sem)
+ {
+ 	int tmp;
+diff --git a/include/asm-powerpc/semaphore.h b/include/asm-powerpc/semaphore.h
+index 48dd32e..d9b2034 100644
+--- a/include/asm-powerpc/semaphore.h
++++ b/include/asm-powerpc/semaphore.h
+@@ -1,94 +1 @@
+-#ifndef _ASM_POWERPC_SEMAPHORE_H
+-#define _ASM_POWERPC_SEMAPHORE_H
+-
+-/*
+- * Remove spinlock-based RW semaphores; RW semaphore definitions are
+- * now in rwsem.h and we use the generic lib/rwsem.c implementation.
+- * Rework semaphores to use atomic_dec_if_positive.
+- * -- Paul Mackerras (paulus at samba.org)
+- */
+-
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+-	/*
+-	 * Note that any negative value of count is equivalent to 0,
+-	 * but additionally indicates that some process(es) might be
+-	 * sleeping on `wait'.
+-	 */
+-	atomic_t count;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name, 1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	atomic_set(&sem->count, val);
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int  __down_interruptible(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-
+-	/*
+-	 * Try to get the semaphore, take the slow path if we fail.
+-	 */
+-	if (unlikely(atomic_dec_return(&sem->count) < 0))
+-		__down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-
+-	might_sleep();
+-
+-	if (unlikely(atomic_dec_return(&sem->count) < 0))
+-		ret = __down_interruptible(sem);
+-	return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	return atomic_dec_if_positive(&sem->count) < 0;
+-}
+-
+-static inline void up(struct semaphore * sem)
+-{
+-	if (unlikely(atomic_inc_return(&sem->count) <= 0))
+-		__up(sem);
+-}
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _ASM_POWERPC_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h
+index e8b493d..9aea8e9 100644
+--- a/include/asm-powerpc/sparsemem.h
++++ b/include/asm-powerpc/sparsemem.h
+@@ -15,6 +15,7 @@
+ 
+ #ifdef CONFIG_MEMORY_HOTPLUG
+ extern void create_section_mapping(unsigned long start, unsigned long end);
++extern int remove_section_mapping(unsigned long start, unsigned long end);
+ #ifdef CONFIG_NUMA
+ extern int hot_add_scn_to_nid(unsigned long scn_addr);
+ #else
+diff --git a/include/asm-powerpc/spinlock.h b/include/asm-powerpc/spinlock.h
+index cc4cfce..258c939 100644
+--- a/include/asm-powerpc/spinlock.h
++++ b/include/asm-powerpc/spinlock.h
+@@ -19,6 +19,7 @@
+  *
+  * (the type definitions are in asm/spinlock_types.h)
+  */
++#include <linux/irqflags.h>
+ #ifdef CONFIG_PPC64
+ #include <asm/paca.h>
+ #include <asm/hvcall.h>
+diff --git a/include/asm-powerpc/string.h b/include/asm-powerpc/string.h
+index aa40f92..e40010a 100644
+--- a/include/asm-powerpc/string.h
++++ b/include/asm-powerpc/string.h
+@@ -7,6 +7,7 @@
+ #define __HAVE_ARCH_STRNCPY
+ #define __HAVE_ARCH_STRLEN
+ #define __HAVE_ARCH_STRCMP
++#define __HAVE_ARCH_STRNCMP
+ #define __HAVE_ARCH_STRCAT
+ #define __HAVE_ARCH_MEMSET
+ #define __HAVE_ARCH_MEMCPY
+@@ -18,6 +19,7 @@ extern char * strcpy(char *,const char *);
+ extern char * strncpy(char *,const char *, __kernel_size_t);
+ extern __kernel_size_t strlen(const char *);
+ extern int strcmp(const char *,const char *);
++extern int strncmp(const char *, const char *, __kernel_size_t);
+ extern char * strcat(char *, const char *);
+ extern void * memset(void *,int,__kernel_size_t);
+ extern void * memcpy(void *,const void *,__kernel_size_t);
+diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
+index 29552ff..fab1674 100644
+--- a/include/asm-powerpc/system.h
++++ b/include/asm-powerpc/system.h
+@@ -5,6 +5,7 @@
+ #define _ASM_POWERPC_SYSTEM_H
+ 
+ #include <linux/kernel.h>
++#include <linux/irqflags.h>
+ 
+ #include <asm/hw_irq.h>
+ 
+diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
+index 40d5f98..d030f5c 100644
+--- a/include/asm-powerpc/thread_info.h
++++ b/include/asm-powerpc/thread_info.h
+@@ -80,12 +80,8 @@ struct thread_info {
+ 
+ #else /* THREAD_SHIFT < PAGE_SHIFT */
+ 
+-#ifdef CONFIG_DEBUG_STACK_USAGE
+-#define alloc_thread_info(tsk)	kzalloc(THREAD_SIZE, GFP_KERNEL)
+-#else
+-#define alloc_thread_info(tsk)	kmalloc(THREAD_SIZE, GFP_KERNEL)
+-#endif
+-#define free_thread_info(ti)	kfree(ti)
++extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
++extern void free_thread_info(struct thread_info *ti);
+ 
+ #endif /* THREAD_SHIFT < PAGE_SHIFT */
+ 
+diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h
+index ca23b68..100c6fb 100644
+--- a/include/asm-powerpc/topology.h
++++ b/include/asm-powerpc/topology.h
+@@ -96,11 +96,10 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev,
+ {
+ }
+ 
++#endif /* CONFIG_NUMA */
+ 
+ #include <asm-generic/topology.h>
+ 
+-#endif /* CONFIG_NUMA */
+-
+ #ifdef CONFIG_SMP
+ #include <asm/cputable.h>
+ #define smt_capable()		(cpu_has_feature(CPU_FTR_SMT))
+diff --git a/include/asm-powerpc/types.h b/include/asm-powerpc/types.h
+index 903fd19..c243a6a 100644
+--- a/include/asm-powerpc/types.h
++++ b/include/asm-powerpc/types.h
+@@ -84,6 +84,13 @@ typedef unsigned long long u64;
+ 
+ typedef __vector128 vector128;
+ 
++/* Physical address used by some IO functions */
++#if defined(CONFIG_PPC64) || defined(CONFIG_PHYS_64BIT)
++typedef u64 phys_addr_t;
++#else
++typedef u32 phys_addr_t;
++#endif
++
+ #ifdef __powerpc64__
+ typedef u64 dma_addr_t;
+ #else
+diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
+index d46b57b..d76ef09 100644
+--- a/include/asm-ppc/mmu.h
++++ b/include/asm-ppc/mmu.h
+@@ -15,10 +15,8 @@
+  * physical need a larger than native word size type. -Matt
+  */
+ #ifndef CONFIG_PHYS_64BIT
+-typedef unsigned long phys_addr_t;
+ #define PHYS_FMT	"%.8lx"
+ #else
+-typedef unsigned long long phys_addr_t;
+ extern phys_addr_t fixup_bigphys_addr(phys_addr_t, phys_addr_t);
+ #define PHYS_FMT	"%16Lx"
+ #endif
+diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
+index 23579d4..402ba15 100644
+--- a/include/asm-ppc/mpc8260.h
++++ b/include/asm-ppc/mpc8260.h
+@@ -35,10 +35,6 @@
+ #include <platforms/tqm8260.h>
+ #endif
+ 
+-#if defined(CONFIG_PQ2ADS) || defined (CONFIG_PQ2FADS)
+-#include <platforms/pq2ads.h>
+-#endif
+-
+ #ifdef CONFIG_PCI_8260
+ #include <syslib/m82xx_pci.h>
+ #endif
+diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
+index d3a2f2f..b9e3060 100644
+--- a/include/asm-ppc/mpc8xx.h
++++ b/include/asm-ppc/mpc8xx.h
+@@ -63,10 +63,6 @@
+ #include <platforms/lantec.h>
+ #endif
+ 
+-#if defined(CONFIG_MPC885ADS)
+-#include <platforms/mpc885ads.h>
+-#endif
+-
+ /* Currently, all 8xx boards that support a processor to PCI/ISA bridge
+  * use the same memory map.
+  */
+diff --git a/include/asm-ppc/ocp.h b/include/asm-ppc/ocp.h
+index 1379a4f..3909a2e 100644
+--- a/include/asm-ppc/ocp.h
++++ b/include/asm-ppc/ocp.h
+@@ -31,7 +31,6 @@
+ 
+ #include <asm/mmu.h>
+ #include <asm/ocp_ids.h>
+-#include <asm/semaphore.h>
+ 
+ #ifdef CONFIG_PPC_OCP
+ 
+diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h
+index 123b557..0818ecd 100644
+--- a/include/asm-s390/cio.h
++++ b/include/asm-s390/cio.h
+@@ -397,6 +397,10 @@ struct cio_iplinfo {
+ 
+ extern int cio_get_iplinfo(struct cio_iplinfo *iplinfo);
+ 
++/* Function from drivers/s390/cio/chsc.c */
++int chsc_sstpc(void *page, unsigned int op, u16 ctrl);
++int chsc_sstpi(void *page, void *result, size_t size);
++
+ #endif
+ 
+ #endif
+diff --git a/include/asm-s390/cpu.h b/include/asm-s390/cpu.h
+index 352dde1..e5a6a9b 100644
+--- a/include/asm-s390/cpu.h
++++ b/include/asm-s390/cpu.h
+@@ -22,4 +22,12 @@ struct s390_idle_data {
+ 
+ DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
+ 
++void s390_idle_leave(void);
++
++static inline void s390_idle_check(void)
++{
++	if ((&__get_cpu_var(s390_idle))->in_idle)
++		s390_idle_leave();
++}
++
+ #endif /* _ASM_S390_CPU_H_ */
+diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h
+index c00dd2b..335baf4 100644
+--- a/include/asm-s390/debug.h
++++ b/include/asm-s390/debug.h
+@@ -73,6 +73,7 @@ typedef struct debug_info {
+ 	struct dentry* debugfs_entries[DEBUG_MAX_VIEWS];
+ 	struct debug_view* views[DEBUG_MAX_VIEWS];	
+ 	char name[DEBUG_MAX_NAME_LEN];
++	mode_t mode;
+ } debug_info_t;
+ 
+ typedef int (debug_header_proc_t) (debug_info_t* id,
+@@ -122,6 +123,10 @@ debug_entry_t* debug_exception_common(debug_info_t* id, int level,
+ debug_info_t* debug_register(char* name, int pages, int nr_areas,
+                              int buf_size);
+ 
++debug_info_t *debug_register_mode(char *name, int pages, int nr_areas,
++				  int buf_size, mode_t mode, uid_t uid,
++				  gid_t gid);
++
+ void debug_unregister(debug_info_t* id);
+ 
+ void debug_set_level(debug_info_t* id, int new_level);
+diff --git a/include/asm-s390/extmem.h b/include/asm-s390/extmem.h
+index c8802c9..33837d7 100644
+--- a/include/asm-s390/extmem.h
++++ b/include/asm-s390/extmem.h
+@@ -22,11 +22,12 @@
+ #define SEGMENT_SHARED 0
+ #define SEGMENT_EXCLUSIVE 1
+ 
+-extern int segment_load (char *name,int segtype,unsigned long *addr,unsigned long *length);
+-extern void segment_unload(char *name);
+-extern void segment_save(char *name);
+-extern int segment_type (char* name);
+-extern int segment_modify_shared (char *name, int do_nonshared);
++int segment_load (char *name, int segtype, unsigned long *addr, unsigned long *length);
++void segment_unload(char *name);
++void segment_save(char *name);
++int segment_type (char* name);
++int segment_modify_shared (char *name, int do_nonshared);
++void segment_warning(int rc, char *seg_name);
+ 
+ #endif
+ #endif
+diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
+index 31beb18..4b7cb96 100644
+--- a/include/asm-s390/hardirq.h
++++ b/include/asm-s390/hardirq.h
+@@ -32,6 +32,6 @@ typedef struct {
+ 
+ #define HARDIRQ_BITS	8
+ 
+-extern void account_ticks(u64 time);
++void clock_comparator_work(void);
+ 
+ #endif /* __ASM_HARDIRQ_H */
+diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
+index 801a6fd..5de3efb 100644
+--- a/include/asm-s390/lowcore.h
++++ b/include/asm-s390/lowcore.h
+@@ -56,6 +56,8 @@
+ #define __LC_IO_INT_WORD                0x0C0
+ #define __LC_MCCK_CODE                  0x0E8
+ 
++#define __LC_LAST_BREAK 		0x110
++
+ #define __LC_RETURN_PSW                 0x200
+ 
+ #define __LC_SAVE_AREA                  0xC00
+@@ -80,7 +82,6 @@
+ #define __LC_CPUID                      0xC60
+ #define __LC_CPUADDR                    0xC68
+ #define __LC_IPLDEV                     0xC7C
+-#define __LC_JIFFY_TIMER		0xC80
+ #define __LC_CURRENT			0xC90
+ #define __LC_INT_CLOCK			0xC98
+ #else /* __s390x__ */
+@@ -103,7 +104,6 @@
+ #define __LC_CPUID			0xD80
+ #define __LC_CPUADDR			0xD88
+ #define __LC_IPLDEV                     0xDB8
+-#define __LC_JIFFY_TIMER		0xDC0
+ #define __LC_CURRENT			0xDD8
+ #define __LC_INT_CLOCK			0xDE8
+ #endif /* __s390x__ */
+@@ -276,7 +276,7 @@ struct _lowcore
+ 	/* entry.S sensitive area end */
+ 
+         /* SMP info area: defined by DJB */
+-        __u64        jiffy_timer;              /* 0xc80 */
++	__u64	     clock_comparator;	       /* 0xc80 */
+ 	__u32        ext_call_fast;            /* 0xc88 */
+ 	__u32        percpu_offset;            /* 0xc8c */
+ 	__u32        current_task;	       /* 0xc90 */
+@@ -368,11 +368,12 @@ struct _lowcore
+ 	/* entry.S sensitive area end */
+ 
+         /* SMP info area: defined by DJB */
+-        __u64        jiffy_timer;              /* 0xdc0 */
++	__u64	     clock_comparator;	       /* 0xdc0 */
+ 	__u64        ext_call_fast;            /* 0xdc8 */
+ 	__u64        percpu_offset;            /* 0xdd0 */
+ 	__u64        current_task;	       /* 0xdd8 */
+-	__u64        softirq_pending;	       /* 0xde0 */
++	__u32	     softirq_pending;	       /* 0xde0 */
++	__u32	     pad_0x0de4;	       /* 0xde4 */
+ 	__u64        int_clock;                /* 0xde8 */
+         __u8         pad12[0xe00-0xdf0];       /* 0xdf0 */
+ 
+diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
+index 51d8891..8eaf343 100644
+--- a/include/asm-s390/processor.h
++++ b/include/asm-s390/processor.h
+@@ -175,6 +175,13 @@ extern void task_show_regs(struct seq_file *m, struct task_struct *task);
+ extern void show_registers(struct pt_regs *regs);
+ extern void show_code(struct pt_regs *regs);
+ extern void show_trace(struct task_struct *task, unsigned long *sp);
++#ifdef CONFIG_64BIT
++extern void show_last_breaking_event(struct pt_regs *regs);
++#else
++static inline void show_last_breaking_event(struct pt_regs *regs)
++{
++}
++#endif
+ 
+ unsigned long get_wchan(struct task_struct *p);
+ #define task_pt_regs(tsk) ((struct pt_regs *) \
+diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
+index 0e7001a..d9b2034 100644
+--- a/include/asm-s390/semaphore.h
++++ b/include/asm-s390/semaphore.h
+@@ -1,107 +1 @@
+-/*
+- *  include/asm-s390/semaphore.h
+- *
+- *  S390 version
+- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+- *
+- *  Derived from "include/asm-i386/semaphore.h"
+- *    (C) Copyright 1996 Linus Torvalds
+- */
+-
+-#ifndef _S390_SEMAPHORE_H
+-#define _S390_SEMAPHORE_H
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+-	/*
+-	 * Note that any negative value of count is equivalent to 0,
+-	 * but additionally indicates that some process(es) might be
+-	 * sleeping on `wait'.
+-	 */
+-	atomic_t count;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name,count) \
+-	{ ATOMIC_INIT(count), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) }
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	atomic_set(&sem->count, val);
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int  __down_interruptible(struct semaphore * sem);
+-asmlinkage int  __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-	if (atomic_dec_return(&sem->count) < 0)
+-		__down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-
+-	might_sleep();
+-	if (atomic_dec_return(&sem->count) < 0)
+-		ret = __down_interruptible(sem);
+-	return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	int old_val, new_val;
+-
+-	/*
+-	 * This inline assembly atomically implements the equivalent
+-	 * to the following C code:
+-	 *   old_val = sem->count.counter;
+-	 *   if ((new_val = old_val) > 0)
+-	 *       sem->count.counter = --new_val;
+-	 * In the ppc code this is called atomic_dec_if_positive.
+-	 */
+-	asm volatile(
+-		"	l	%0,0(%3)\n"
+-		"0:	ltr	%1,%0\n"
+-		"	jle	1f\n"
+-		"	ahi	%1,-1\n"
+-		"	cs	%0,%1,0(%3)\n"
+-		"	jl	0b\n"
+-		"1:"
+-		: "=&d" (old_val), "=&d" (new_val), "=m" (sem->count.counter)
+-		: "a" (&sem->count.counter), "m" (sem->count.counter)
+-		: "cc", "memory");
+-	return old_val <= 0;
+-}
+-
+-static inline void up(struct semaphore * sem)
+-{
+-	if (atomic_inc_return(&sem->count) <= 0)
+-		__up(sem);
+-}
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
+index c7b7432..6f3821a 100644
+--- a/include/asm-s390/smp.h
++++ b/include/asm-s390/smp.h
+@@ -90,6 +90,9 @@ extern void __cpu_die (unsigned int cpu);
+ extern void cpu_die (void) __attribute__ ((noreturn));
+ extern int __cpu_up (unsigned int cpu);
+ 
++extern struct mutex smp_cpu_state_mutex;
++extern int smp_cpu_polarization[];
++
+ extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
+ 	void *info, int wait);
+ #endif
+diff --git a/include/asm-s390/sysinfo.h b/include/asm-s390/sysinfo.h
+new file mode 100644
+index 0000000..abe10ae
+--- /dev/null
++++ b/include/asm-s390/sysinfo.h
+@@ -0,0 +1,116 @@
++/*
++ * definition for store system information stsi
++ *
++ * Copyright IBM Corp. 2001,2008
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License (version 2 only)
++ * as published by the Free Software Foundation.
++ *
++ *    Author(s): Ulrich Weigand <weigand at de.ibm.com>
++ *		 Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++struct sysinfo_1_1_1 {
++	char reserved_0[32];
++	char manufacturer[16];
++	char type[4];
++	char reserved_1[12];
++	char model_capacity[16];
++	char sequence[16];
++	char plant[4];
++	char model[16];
++	char model_perm_cap[16];
++	char model_temp_cap[16];
++	char model_cap_rating[4];
++	char model_perm_cap_rating[4];
++	char model_temp_cap_rating[4];
++};
++
++struct sysinfo_1_2_1 {
++	char reserved_0[80];
++	char sequence[16];
++	char plant[4];
++	char reserved_1[2];
++	unsigned short cpu_address;
++};
++
++struct sysinfo_1_2_2 {
++	char format;
++	char reserved_0[1];
++	unsigned short acc_offset;
++	char reserved_1[24];
++	unsigned int secondary_capability;
++	unsigned int capability;
++	unsigned short cpus_total;
++	unsigned short cpus_configured;
++	unsigned short cpus_standby;
++	unsigned short cpus_reserved;
++	unsigned short adjustment[0];
++};
++
++struct sysinfo_1_2_2_extension {
++	unsigned int alt_capability;
++	unsigned short alt_adjustment[0];
++};
++
++struct sysinfo_2_2_1 {
++	char reserved_0[80];
++	char sequence[16];
++	char plant[4];
++	unsigned short cpu_id;
++	unsigned short cpu_address;
++};
++
++struct sysinfo_2_2_2 {
++	char reserved_0[32];
++	unsigned short lpar_number;
++	char reserved_1;
++	unsigned char characteristics;
++	unsigned short cpus_total;
++	unsigned short cpus_configured;
++	unsigned short cpus_standby;
++	unsigned short cpus_reserved;
++	char name[8];
++	unsigned int caf;
++	char reserved_2[16];
++	unsigned short cpus_dedicated;
++	unsigned short cpus_shared;
++};
++
++#define LPAR_CHAR_DEDICATED	(1 << 7)
++#define LPAR_CHAR_SHARED	(1 << 6)
++#define LPAR_CHAR_LIMITED	(1 << 5)
++
++struct sysinfo_3_2_2 {
++	char reserved_0[31];
++	unsigned char count;
++	struct {
++		char reserved_0[4];
++		unsigned short cpus_total;
++		unsigned short cpus_configured;
++		unsigned short cpus_standby;
++		unsigned short cpus_reserved;
++		char name[8];
++		unsigned int caf;
++		char cpi[16];
++		char reserved_1[24];
++
++	} vm[8];
++};
++
++static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
++{
++	register int r0 asm("0") = (fc << 28) | sel1;
++	register int r1 asm("1") = sel2;
++
++	asm volatile(
++		"   stsi 0(%2)\n"
++		"0: jz   2f\n"
++		"1: lhi  %0,%3\n"
++		"2:\n"
++		EX_TABLE(0b, 1b)
++		: "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS)
++		: "cc", "memory");
++	return r0;
++}
+diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
+index 15aba30..92098df 100644
+--- a/include/asm-s390/system.h
++++ b/include/asm-s390/system.h
+@@ -406,6 +406,8 @@ __set_psw_mask(unsigned long mask)
+ #define local_mcck_enable()  __set_psw_mask(psw_kernel_bits)
+ #define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK)
+ 
++int stfle(unsigned long long *list, int doublewords);
++
+ #ifdef CONFIG_SMP
+ 
+ extern void smp_ctl_set_bit(int cr, int bit);
+diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h
+index 98229db..d744c3d 100644
+--- a/include/asm-s390/timex.h
++++ b/include/asm-s390/timex.h
+@@ -62,16 +62,18 @@ static inline unsigned long long get_clock (void)
+ 	return clk;
+ }
+ 
+-static inline void get_clock_extended(void *dest)
++static inline unsigned long long get_clock_xt(void)
+ {
+-	typedef struct { unsigned long long clk[2]; } __clock_t;
++	unsigned char clk[16];
+ 
+ #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+-	asm volatile("stcke %0" : "=Q" (*((__clock_t *)dest)) : : "cc");
++	asm volatile("stcke %0" : "=Q" (clk) : : "cc");
+ #else /* __GNUC__ */
+-	asm volatile("stcke 0(%1)" : "=m" (*((__clock_t *)dest))
+-				   : "a" ((__clock_t *)dest) : "cc");
++	asm volatile("stcke 0(%1)" : "=m" (clk)
++				   : "a" (clk) : "cc");
+ #endif /* __GNUC__ */
++
++	return *((unsigned long long *)&clk[1]);
+ }
+ 
+ static inline cycles_t get_cycles(void)
+@@ -81,5 +83,6 @@ static inline cycles_t get_cycles(void)
+ 
+ int get_sync_clock(unsigned long long *clock);
+ void init_cpu_timer(void);
++unsigned long long monotonic_clock(void);
+ 
+ #endif
+diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
+index 35fb4f9..9e57a93 100644
+--- a/include/asm-s390/tlbflush.h
++++ b/include/asm-s390/tlbflush.h
+@@ -13,12 +13,14 @@ static inline void __tlb_flush_local(void)
+ 	asm volatile("ptlb" : : : "memory");
+ }
+ 
++#ifdef CONFIG_SMP
+ /*
+  * Flush all tlb entries on all cpus.
+  */
++void smp_ptlb_all(void);
++
+ static inline void __tlb_flush_global(void)
+ {
+-	extern void smp_ptlb_all(void);
+ 	register unsigned long reg2 asm("2");
+ 	register unsigned long reg3 asm("3");
+ 	register unsigned long reg4 asm("4");
+@@ -39,6 +41,25 @@ static inline void __tlb_flush_global(void)
+ 		: : "d" (reg2), "d" (reg3), "d" (reg4), "m" (dummy) : "cc" );
+ }
+ 
++static inline void __tlb_flush_full(struct mm_struct *mm)
++{
++	cpumask_t local_cpumask;
++
++	preempt_disable();
++	/*
++	 * If the process only ran on the local cpu, do a local flush.
++	 */
++	local_cpumask = cpumask_of_cpu(smp_processor_id());
++	if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
++		__tlb_flush_local();
++	else
++		__tlb_flush_global();
++	preempt_enable();
++}
++#else
++#define __tlb_flush_full(mm)	__tlb_flush_local()
++#endif
++
+ /*
+  * Flush all tlb entries of a page table on all cpus.
+  */
+@@ -51,8 +72,6 @@ static inline void __tlb_flush_idte(unsigned long asce)
+ 
+ static inline void __tlb_flush_mm(struct mm_struct * mm)
+ {
+-	cpumask_t local_cpumask;
+-
+ 	if (unlikely(cpus_empty(mm->cpu_vm_mask)))
+ 		return;
+ 	/*
+@@ -69,16 +88,7 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
+ 				 mm->context.asce_bits);
+ 		return;
+ 	}
+-	preempt_disable();
+-	/*
+-	 * If the process only ran on the local cpu, do a local flush.
+-	 */
+-	local_cpumask = cpumask_of_cpu(smp_processor_id());
+-	if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
+-		__tlb_flush_local();
+-	else
+-		__tlb_flush_global();
+-	preempt_enable();
++	__tlb_flush_full(mm);
+ }
+ 
+ static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
+diff --git a/include/asm-s390/topology.h b/include/asm-s390/topology.h
+index 613aa64..8e97b06 100644
+--- a/include/asm-s390/topology.h
++++ b/include/asm-s390/topology.h
+@@ -1,6 +1,29 @@
+ #ifndef _ASM_S390_TOPOLOGY_H
+ #define _ASM_S390_TOPOLOGY_H
+ 
++#include <linux/cpumask.h>
++
++#define mc_capable()	(1)
++
++cpumask_t cpu_coregroup_map(unsigned int cpu);
++
++int topology_set_cpu_management(int fc);
++void topology_schedule_update(void);
++
++#define POLARIZATION_UNKNWN	(-1)
++#define POLARIZATION_HRZ	(0)
++#define POLARIZATION_VL		(1)
++#define POLARIZATION_VM		(2)
++#define POLARIZATION_VH		(3)
++
++#ifdef CONFIG_SMP
++void s390_init_cpu_topology(void);
++#else
++static inline void s390_init_cpu_topology(void)
++{
++};
++#endif
++
+ #include <asm-generic/topology.h>
+ 
+ #endif /* _ASM_S390_TOPOLOGY_H */
+diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h
+index cfda7d5..121b2ec 100644
+--- a/include/asm-sh/bugs.h
++++ b/include/asm-sh/bugs.h
+@@ -25,7 +25,7 @@ static void __init check_bugs(void)
+ 	case CPU_SH7619:
+ 		*p++ = '2';
+ 		break;
+-	case CPU_SH7203 ... CPU_SH7263:
++	case CPU_SH7203 ... CPU_MXG:
+ 		*p++ = '2';
+ 		*p++ = 'a';
+ 		break;
+diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h
+index ec028c6..da46e67 100644
+--- a/include/asm-sh/cpu-sh4/freq.h
++++ b/include/asm-sh/cpu-sh4/freq.h
+@@ -10,14 +10,14 @@
+ #ifndef __ASM_CPU_SH4_FREQ_H
+ #define __ASM_CPU_SH4_FREQ_H
+ 
+-#if defined(CONFIG_CPU_SUBTYPE_SH7722) || defined(CONFIG_CPU_SUBTYPE_SH7366)
++#if defined(CONFIG_CPU_SUBTYPE_SH7722) || \
++    defined(CONFIG_CPU_SUBTYPE_SH7723) || \
++    defined(CONFIG_CPU_SUBTYPE_SH7366)
+ #define FRQCR		        0xa4150000
+ #define VCLKCR			0xa4150004
+ #define SCLKACR			0xa4150008
+ #define SCLKBCR			0xa415000c
+-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
+ #define IrDACLKCR		0xa4150010
+-#endif
+ #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
+       defined(CONFIG_CPU_SUBTYPE_SH7780)
+ #define	FRQCR			0xffc80000
+diff --git a/include/asm-sh/cpu-sh4/rtc.h b/include/asm-sh/cpu-sh4/rtc.h
+index f3d0f53..25b1e6a 100644
+--- a/include/asm-sh/cpu-sh4/rtc.h
++++ b/include/asm-sh/cpu-sh4/rtc.h
+@@ -1,7 +1,12 @@
+ #ifndef __ASM_SH_CPU_SH4_RTC_H
+ #define __ASM_SH_CPU_SH4_RTC_H
+ 
++#ifdef CONFIG_CPU_SUBTYPE_SH7723
++#define rtc_reg_size		sizeof(u16)
++#else
+ #define rtc_reg_size		sizeof(u32)
++#endif
++
+ #define RTC_BIT_INVERTED	0x40	/* bug on SH7750, SH7750S */
+ #define RTC_DEF_CAPABILITIES	RTC_CAP_4_DIGIT_YEAR
+ 
+diff --git a/include/asm-sh/i2c-sh7760.h b/include/asm-sh/i2c-sh7760.h
+new file mode 100644
+index 0000000..2418211
+--- /dev/null
++++ b/include/asm-sh/i2c-sh7760.h
+@@ -0,0 +1,22 @@
++/*
++ * MMIO/IRQ and platform data for SH7760 I2C channels
++ */
++
++#ifndef _I2C_SH7760_H_
++#define _I2C_SH7760_H_
++
++#define SH7760_I2C_DEVNAME	"sh7760-i2c"
++
++#define SH7760_I2C0_MMIO	0xFE140000
++#define SH7760_I2C0_MMIOEND	0xFE14003B
++#define SH7760_I2C0_IRQ		62
++
++#define SH7760_I2C1_MMIO	0xFE150000
++#define SH7760_I2C1_MMIOEND	0xFE15003B
++#define SH7760_I2C1_IRQ		63
++
++struct sh7760_i2c_platdata {
++	unsigned int speed_khz;
++};
++
++#endif
+diff --git a/include/asm-sh/ide.h b/include/asm-sh/ide.h
+index 9f8e914..58e0bdd 100644
+--- a/include/asm-sh/ide.h
++++ b/include/asm-sh/ide.h
+@@ -14,9 +14,6 @@
+ 
+ #ifdef __KERNEL__
+ 
+-
+-#define ide_default_io_ctl(base)	(0)
+-
+ #include <asm-generic/ide_iops.h>
+ 
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-sh/migor.h b/include/asm-sh/migor.h
+new file mode 100644
+index 0000000..2329363
+--- /dev/null
++++ b/include/asm-sh/migor.h
+@@ -0,0 +1,58 @@
++#ifndef __ASM_SH_MIGOR_H
++#define __ASM_SH_MIGOR_H
++
++/*
++ * linux/include/asm-sh/migor.h
++ *
++ * Copyright (C) 2008 Renesas Solutions
++ *
++ * Portions Copyright (C) 2007 Nobuhiro Iwamatsu
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ */
++#include <asm/addrspace.h>
++
++/* GPIO */
++#define MSTPCR0 0xa4150030
++#define MSTPCR1 0xa4150034
++#define MSTPCR2 0xa4150038
++
++#define PORT_PACR 0xa4050100
++#define PORT_PDCR 0xa4050106
++#define PORT_PECR 0xa4050108
++#define PORT_PHCR 0xa405010e
++#define PORT_PJCR 0xa4050110
++#define PORT_PKCR 0xa4050112
++#define PORT_PLCR 0xa4050114
++#define PORT_PMCR 0xa4050116
++#define PORT_PRCR 0xa405011c
++#define PORT_PWCR 0xa4050146
++#define PORT_PXCR 0xa4050148
++#define PORT_PYCR 0xa405014a
++#define PORT_PZCR 0xa405014c
++#define PORT_PADR 0xa4050120
++#define PORT_PWDR 0xa4050166
++
++#define PORT_HIZCRA 0xa4050158
++#define PORT_HIZCRC 0xa405015c
++
++#define PORT_MSELCRB 0xa4050182
++
++#define MSTPCR1 0xa4150034
++#define MSTPCR2 0xa4150038
++
++#define PORT_PSELA 0xa405014e
++#define PORT_PSELB 0xa4050150
++#define PORT_PSELC 0xa4050152
++#define PORT_PSELD 0xa4050154
++
++#define PORT_HIZCRA 0xa4050158
++#define PORT_HIZCRB 0xa405015a
++#define PORT_HIZCRC 0xa405015c
++
++#define BSC_CS6ABCR 0xfec1001c
++
++#endif /* __ASM_SH_MIGOR_H */
+diff --git a/include/asm-sh/mpc1211/pci.h b/include/asm-sh/mpc1211/pci.h
+index 5d3712c..d9162c5 100644
+--- a/include/asm-sh/mpc1211/pci.h
++++ b/include/asm-sh/mpc1211/pci.h
+@@ -24,8 +24,6 @@
+ #define PCI_PROBE_BIOS    1
+ #define PCI_PROBE_CONF1   2
+ #define PCI_PROBE_CONF2   4
+-#define PCI_NO_SORT       0x100
+-#define PCI_BIOS_SORT     0x200
+ #define PCI_NO_CHECKS     0x400
+ #define PCI_ASSIGN_ROMS   0x1000
+ #define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
+index ec707b9..b7c7ce8 100644
+--- a/include/asm-sh/processor.h
++++ b/include/asm-sh/processor.h
+@@ -16,7 +16,7 @@ enum cpu_type {
+ 	CPU_SH7619,
+ 
+ 	/* SH-2A types */
+-	CPU_SH7203, CPU_SH7206, CPU_SH7263,
++	CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_MXG,
+ 
+ 	/* SH-3 types */
+ 	CPU_SH7705, CPU_SH7706, CPU_SH7707,
+@@ -29,7 +29,8 @@ enum cpu_type {
+ 	CPU_SH7760, CPU_SH4_202, CPU_SH4_501,
+ 
+ 	/* SH-4A types */
+-	CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3,
++	CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
++	CPU_SH7723, CPU_SHX3,
+ 
+ 	/* SH4AL-DSP types */
+ 	CPU_SH7343, CPU_SH7722, CPU_SH7366,
+diff --git a/include/asm-sh/r7780rp.h b/include/asm-sh/r7780rp.h
+index 1770460..a33838f 100644
+--- a/include/asm-sh/r7780rp.h
++++ b/include/asm-sh/r7780rp.h
+@@ -55,11 +55,11 @@
+ #define PA_SCSPTR1      (PA_BCR+0x0524) /* SCIF1 Serial Port control */
+ #define PA_SCLSR1       (PA_BCR+0x0528) /* SCIF1 Line Status control */
+ #define PA_SCRER1       (PA_BCR+0x052c) /* SCIF1 Serial Error control */
+-#define PA_ICCR         (PA_BCR+0x0600) /* Serial control */
+-#define PA_SAR          (PA_BCR+0x0602) /* Serial Slave control */
+-#define PA_MDR          (PA_BCR+0x0604) /* Serial Mode control */
+-#define PA_ADR1         (PA_BCR+0x0606) /* Serial Address1 control */
+-#define PA_DAR1         (PA_BCR+0x0646) /* Serial Data1 control */
++#define PA_SMCR         (PA_BCR+0x0600) /* 2-wire Serial control */
++#define PA_SMSMADR      (PA_BCR+0x0602) /* 2-wire Serial Slave control */
++#define PA_SMMR         (PA_BCR+0x0604) /* 2-wire Serial Mode control */
++#define PA_SMSADR1      (PA_BCR+0x0606) /* 2-wire Serial Address1 control */
++#define PA_SMTRDR1      (PA_BCR+0x0646) /* 2-wire Serial Data1 control */
+ #define PA_VERREG       (PA_BCR+0x0700) /* FPGA Version Register */
+ #define PA_POFF         (PA_BCR+0x0800) /* System Power Off control */
+ #define PA_PMR          (PA_BCR+0x0900) /*  */
+@@ -107,11 +107,11 @@
+ #define PA_SCFCR	(PA_BCR+0x040c)	/* SCIF FIFO control */
+ #define PA_SCFDR	(PA_BCR+0x040e)	/* SCIF FIFO data control */
+ #define PA_SCLSR	(PA_BCR+0x0412)	/* SCIF Line Status control */
+-#define PA_ICCR		(PA_BCR+0x0500)	/* Serial control */
+-#define PA_SAR		(PA_BCR+0x0502)	/* Serial Slave control */
+-#define PA_MDR		(PA_BCR+0x0504)	/* Serial Mode control */
+-#define PA_ADR1		(PA_BCR+0x0506)	/* Serial Address1 control */
+-#define PA_DAR1		(PA_BCR+0x0546)	/* Serial Data1 control */
++#define PA_SMCR		(PA_BCR+0x0500)	/* 2-wire Serial control */
++#define PA_SMSMADR	(PA_BCR+0x0502)	/* 2-wire Serial Slave control */
++#define PA_SMMR		(PA_BCR+0x0504)	/* 2-wire Serial Mode control */
++#define PA_SMSADR1	(PA_BCR+0x0506)	/* 2-wire Serial Address1 control */
++#define PA_SMTRDR1	(PA_BCR+0x0546)	/* 2-wire Serial Data1 control */
+ #define PA_VERREG	(PA_BCR+0x0600)	/* FPGA Version Register */
+ 
+ #define PA_AX88796L	0xa5800400	/* AX88796L Area */
+@@ -190,6 +190,8 @@
+ #define IRQ_TP			(HL_FPGA_IRQ_BASE + 12)
+ #define IRQ_RTC			(HL_FPGA_IRQ_BASE + 13)
+ #define IRQ_TH_ALERT		(HL_FPGA_IRQ_BASE + 14)
++#define IRQ_SCIF0		(HL_FPGA_IRQ_BASE + 15)
++#define IRQ_SCIF1		(HL_FPGA_IRQ_BASE + 16)
+ 
+ unsigned char *highlander_init_irq_r7780mp(void);
+ unsigned char *highlander_init_irq_r7780rp(void);
+diff --git a/include/asm-sh/se7721.h b/include/asm-sh/se7721.h
+new file mode 100644
+index 0000000..b957f60
+--- /dev/null
++++ b/include/asm-sh/se7721.h
+@@ -0,0 +1,70 @@
++/*
++ * Copyright (C) 2008 Renesas Solutions Corp.
++ *
++ * Hitachi UL SolutionEngine 7721 Support.
++ *
++ * 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 __ASM_SH_SE7721_H
++#define __ASM_SH_SE7721_H
++#include <asm/addrspace.h>
++
++/* Box specific addresses. */
++#define SE_AREA0_WIDTH	2		/* Area0: 32bit */
++#define PA_ROM		0xa0000000	/* EPROM */
++#define PA_ROM_SIZE	0x00200000	/* EPROM size 2M byte */
++#define PA_FROM		0xa1000000	/* Flash-ROM */
++#define PA_FROM_SIZE	0x01000000	/* Flash-ROM size 16M byte */
++#define PA_EXT1		0xa4000000
++#define PA_EXT1_SIZE	0x04000000
++#define PA_SDRAM	0xaC000000	/* SDRAM(Area3) 64MB */
++#define PA_SDRAM_SIZE	0x04000000
++
++#define PA_EXT4		0xb0000000
++#define PA_EXT4_SIZE	0x04000000
++
++#define PA_PERIPHERAL	0xB8000000
++
++#define PA_PCIC		PA_PERIPHERAL
++#define PA_MRSHPC	(PA_PERIPHERAL + 0x003fffe0)
++#define PA_MRSHPC_MW1	(PA_PERIPHERAL + 0x00400000)
++#define PA_MRSHPC_MW2	(PA_PERIPHERAL + 0x00500000)
++#define PA_MRSHPC_IO	(PA_PERIPHERAL + 0x00600000)
++#define MRSHPC_OPTION	(PA_MRSHPC + 6)
++#define MRSHPC_CSR	(PA_MRSHPC + 8)
++#define MRSHPC_ISR	(PA_MRSHPC + 10)
++#define MRSHPC_ICR	(PA_MRSHPC + 12)
++#define MRSHPC_CPWCR	(PA_MRSHPC + 14)
++#define MRSHPC_MW0CR1	(PA_MRSHPC + 16)
++#define MRSHPC_MW1CR1	(PA_MRSHPC + 18)
++#define MRSHPC_IOWCR1	(PA_MRSHPC + 20)
++#define MRSHPC_MW0CR2	(PA_MRSHPC + 22)
++#define MRSHPC_MW1CR2	(PA_MRSHPC + 24)
++#define MRSHPC_IOWCR2	(PA_MRSHPC + 26)
++#define MRSHPC_CDCR	(PA_MRSHPC + 28)
++#define MRSHPC_PCIC_INFO	(PA_MRSHPC + 30)
++
++#define PA_LED		0xB6800000	/* 8bit LED */
++#define PA_FPGA		0xB7000000 	/* FPGA base address */
++
++#define MRSHPC_IRQ0	10
++
++#define FPGA_ILSR1	(PA_FPGA + 0x02)
++#define FPGA_ILSR2	(PA_FPGA + 0x03)
++#define FPGA_ILSR3	(PA_FPGA + 0x04)
++#define FPGA_ILSR4	(PA_FPGA + 0x05)
++#define FPGA_ILSR5	(PA_FPGA + 0x06)
++#define FPGA_ILSR6	(PA_FPGA + 0x07)
++#define FPGA_ILSR7	(PA_FPGA + 0x08)
++#define FPGA_ILSR8	(PA_FPGA + 0x09)
++
++void init_se7721_IRQ(void);
++
++#define __IO_PREFIX		se7721
++#include <asm/io_generic.h>
++
++#endif  /* __ASM_SH_SE7721_H */
+diff --git a/include/asm-sh/se7722.h b/include/asm-sh/se7722.h
+index e0e89fc..3690fe5 100644
+--- a/include/asm-sh/se7722.h
++++ b/include/asm-sh/se7722.h
+@@ -77,6 +77,8 @@
+ #define PORT_PSELA      0xA405014EUL
+ #define PORT_PYCR       0xA405014AUL
+ #define PORT_PZCR       0xA405014CUL
++#define PORT_HIZCRA     0xA4050158UL
++#define PORT_HIZCRC     0xA405015CUL
+ 
+ /* IRQ */
+ #define IRQ0_IRQ        32
+diff --git a/include/asm-sh/semaphore-helper.h b/include/asm-sh/semaphore-helper.h
+deleted file mode 100644
+index bd8230c..0000000
+--- a/include/asm-sh/semaphore-helper.h
++++ /dev/null
+@@ -1,89 +0,0 @@
+-#ifndef __ASM_SH_SEMAPHORE_HELPER_H
+-#define __ASM_SH_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- * (C) Copyright 1999 Andrea Arcangeli
+- */
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- *
+- * This is trivially done with load_locked/store_cond,
+- * which we have.  Let the rest of the losers suck eggs.
+- */
+-static __inline__ void wake_one_more(struct semaphore * sem)
+-{
+-	atomic_inc((atomic_t *)&sem->sleepers);
+-}
+-
+-static __inline__ int waking_non_zero(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->sleepers > 0) {
+-		sem->sleepers--;
+-		ret = 1;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- *	1	got the lock
+- *	0	go to sleep
+- *	-EINTR	interrupted
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+-						struct task_struct *tsk)
+-{
+-	unsigned long flags;
+-	int ret = 0;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->sleepers > 0) {
+-		sem->sleepers--;
+-		ret = 1;
+-	} else if (signal_pending(tsk)) {
+-		atomic_inc(&sem->count);
+-		ret = -EINTR;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- *	1	failed to lock
+- *	0	got the lock
+- *
+- * We must undo the sem->count down_trylock() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+-{
+-	unsigned long flags;
+-	int ret = 1;
+-
+-	spin_lock_irqsave(&semaphore_wake_lock, flags);
+-	if (sem->sleepers <= 0)
+-		atomic_inc(&sem->count);
+-	else {
+-		sem->sleepers--;
+-		ret = 0;
+-	}
+-	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-	return ret;
+-}
+-
+-#endif /* __ASM_SH_SEMAPHORE_HELPER_H */
+diff --git a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h
+index 9e5a37c..d9b2034 100644
+--- a/include/asm-sh/semaphore.h
++++ b/include/asm-sh/semaphore.h
+@@ -1,115 +1 @@
+-#ifndef __ASM_SH_SEMAPHORE_H
+-#define __ASM_SH_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#ifdef __KERNEL__
+-/*
+- * SMP- and interrupt-safe semaphores.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * SuperH verison by Niibe Yutaka
+- *  (Currently no asm implementation but generic C code...)
+- */
+-
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-#include <linux/wait.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.sleepers	= 0,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-/*
+- *	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+- *
+- * i'd rather use the more flexible initialization above, but sadly
+- * GCC 2.7.2.3 emits a bogus warning. EGCS doesn't. Oh well.
+- */
+-	atomic_set(&sem->count, val);
+-	sem->sleepers = 0;
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-#if 0
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+-asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-#endif
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int  __down_interruptible(struct semaphore * sem);
+-asmlinkage int  __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-	if (atomic_dec_return(&sem->count) < 0)
+-		__down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-
+-	might_sleep();
+-	if (atomic_dec_return(&sem->count) < 0)
+-		ret = __down_interruptible(sem);
+-	return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	int ret = 0;
+-
+-	if (atomic_dec_return(&sem->count) < 0)
+-		ret = __down_trylock(sem);
+-	return ret;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	if (atomic_inc_return(&sem->count) <= 0)
+-		__up(sem);
+-}
+-
+-#endif
+-#endif /* __ASM_SH_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-sh/sh_keysc.h b/include/asm-sh/sh_keysc.h
+new file mode 100644
+index 0000000..b5a4dd5
+--- /dev/null
++++ b/include/asm-sh/sh_keysc.h
+@@ -0,0 +1,13 @@
++#ifndef __ASM_KEYSC_H__
++#define __ASM_KEYSC_H__
++
++#define SH_KEYSC_MAXKEYS 30
++
++struct sh_keysc_info {
++	enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3 } mode;
++	int scan_timing; /* 0 -> 7, see KYCR1, SCN[2:0] */
++	int delay;
++	int keycodes[SH_KEYSC_MAXKEYS];
++};
++
++#endif /* __ASM_KEYSC_H__ */
+diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
+index 5145aa2..e65b6b8 100644
+--- a/include/asm-sh/system.h
++++ b/include/asm-sh/system.h
+@@ -146,6 +146,8 @@ extern unsigned int instruction_size(unsigned int insn);
+ 
+ extern unsigned long cached_to_uncached;
+ 
++extern struct dentry *sh_debugfs_root;
++
+ /* XXX
+  * disable hlt during certain critical i/o operations
+  */
+diff --git a/include/asm-sh/topology.h b/include/asm-sh/topology.h
+index f402a3b..34cdb28 100644
+--- a/include/asm-sh/topology.h
++++ b/include/asm-sh/topology.h
+@@ -16,7 +16,7 @@
+ 	.cache_nice_tries	= 2,			\
+ 	.busy_idx		= 3,			\
+ 	.idle_idx		= 2,			\
+-	.newidle_idx		= 0,			\
++	.newidle_idx		= 2,			\
+ 	.wake_idx		= 1,			\
+ 	.forkexec_idx		= 1,			\
+ 	.flags			= SD_LOAD_BALANCE	\
+diff --git a/include/asm-sh/uaccess_32.h b/include/asm-sh/uaccess_32.h
+index c0318b6..1e41fda 100644
+--- a/include/asm-sh/uaccess_32.h
++++ b/include/asm-sh/uaccess_32.h
+@@ -55,13 +55,10 @@ static inline void set_fs(mm_segment_t s)
+  * If we don't have an MMU (or if its disabled) the only thing we really have
+  * to look out for is if the address resides somewhere outside of what
+  * available RAM we have.
+- *
+- * TODO: This check could probably also stand to be restricted somewhat more..
+- * though it still does the Right Thing(tm) for the time being.
+  */
+ static inline int __access_ok(unsigned long addr, unsigned long size)
+ {
+-	return ((addr >= memory_start) && ((addr + size) < memory_end));
++	return 1;
+ }
+ #else /* CONFIG_MMU */
+ #define __addr_ok(addr) \
+diff --git a/include/asm-sparc/Kbuild b/include/asm-sparc/Kbuild
+index c6a55cf..6712237 100644
+--- a/include/asm-sparc/Kbuild
++++ b/include/asm-sparc/Kbuild
+@@ -5,7 +5,6 @@ header-y += asi.h
+ header-y += bpp.h
+ header-y += jsflash.h
+ header-y += openpromio.h
+-header-y += pconf.h
+ header-y += reg.h
+ header-y += traps.h
+ header-y += vfc_ioctls.h
+diff --git a/include/asm-sparc/a.out-core.h b/include/asm-sparc/a.out-core.h
+deleted file mode 100644
+index e8fd338..0000000
+--- a/include/asm-sparc/a.out-core.h
++++ /dev/null
+@@ -1,52 +0,0 @@
+-/* a.out coredump register dumper
+- *
+- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at 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_A_OUT_CORE_H
+-#define _ASM_A_OUT_CORE_H
+-
+-#ifdef __KERNEL__
+-
+-#include <linux/user.h>
+-
+-/*
+- * fill in the user structure for an a.out core dump
+- */
+-static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+-{
+-	unsigned long first_stack_page;
+-
+-	dump->magic = SUNOS_CORE_MAGIC;
+-	dump->len = sizeof(struct user);
+-	dump->regs.psr = regs->psr;
+-	dump->regs.pc = regs->pc;
+-	dump->regs.npc = regs->npc;
+-	dump->regs.y = regs->y;
+-	/* fuck me plenty */
+-	memcpy(&dump->regs.regs[0], &regs->u_regs[1], (sizeof(unsigned long) * 15));
+-	dump->uexec = current->thread.core_exec;
+-	dump->u_tsize = (((unsigned long) current->mm->end_code) -
+-		((unsigned long) current->mm->start_code)) & ~(PAGE_SIZE - 1);
+-	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1)));
+-	dump->u_dsize -= dump->u_tsize;
+-	dump->u_dsize &= ~(PAGE_SIZE - 1);
+-	first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1));
+-	dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1);
+-	memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->thread.float_regs[0], (sizeof(unsigned long) * 32));
+-	dump->fpu.fpstatus.fsr = current->thread.fsr;
+-	dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
+-	dump->fpu.fpstatus.fpq_count = current->thread.fpqdepth;
+-	memcpy(&dump->fpu.fpstatus.fpq[0], &current->thread.fpqueue[0],
+-	       ((sizeof(unsigned long) * 2) * 16));
+-	dump->sigcode = 0;
+-}
+-
+-#endif /* __KERNEL__ */
+-#endif /* _ASM_A_OUT_CORE_H */
+diff --git a/include/asm-sparc/a.out.h b/include/asm-sparc/a.out.h
+deleted file mode 100644
+index 2f1c374..0000000
+--- a/include/asm-sparc/a.out.h
++++ /dev/null
+@@ -1,97 +0,0 @@
+-#ifndef __SPARC_A_OUT_H__
+-#define __SPARC_A_OUT_H__
+-
+-#define SPARC_PGSIZE    0x2000        /* Thanks to the sun4 architecture... */
+-#define SEGMENT_SIZE    SPARC_PGSIZE  /* whee... */
+-
+-#ifndef __ASSEMBLY__
+-
+-struct exec {
+-	unsigned char a_dynamic:1;      /* A __DYNAMIC is in this image */
+-	unsigned char a_toolversion:7;
+-	unsigned char a_machtype;
+-	unsigned short a_info;
+-	unsigned int a_text;		/* length of text, in bytes */
+-	unsigned int a_data;		/* length of data, in bytes */
+-	unsigned int a_bss;		/* length of bss, in bytes */
+-	unsigned int a_syms;		/* length of symbol table, in bytes */
+-	unsigned int a_entry;		/* where program begins */
+-	unsigned int a_trsize;
+-	unsigned int a_drsize;
+-};
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-/* Where in the file does the text information begin? */
+-#define N_TXTOFF(x)     (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
+-
+-/* Where do the Symbols start? */
+-#define N_SYMOFF(x)     (N_TXTOFF(x) + (x).a_text +   \
+-                         (x).a_data + (x).a_trsize +  \
+-                         (x).a_drsize)
+-
+-/* Where does text segment go in memory after being loaded? */
+-#define N_TXTADDR(x)    (unsigned long)(((N_MAGIC(x) == ZMAGIC) && \
+-	                 ((x).a_entry < SPARC_PGSIZE)) ?   \
+-                          0 : SPARC_PGSIZE)
+-
+-/* And same for the data segment.. */
+-#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ?         \
+-                      (N_TXTADDR(x) + (x).a_text)  \
+-		       : (unsigned long) (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+-
+-#define N_TRSIZE(a)	((a).a_trsize)
+-#define N_DRSIZE(a)	((a).a_drsize)
+-#define N_SYMSIZE(a)	((a).a_syms)
+-
+-#ifndef __ASSEMBLY__
+-
+-/*
+- * Sparc relocation types
+- */
+-enum reloc_type
+-{
+-	RELOC_8,
+-	RELOC_16,
+-	RELOC_32,	/* simplest relocs */
+-	RELOC_DISP8,
+-	RELOC_DISP16,
+-	RELOC_DISP32,	/* Disp's (pc-rel) */
+-	RELOC_WDISP30,
+-	RELOC_WDISP22,  /* SR word disp's */
+-	RELOC_HI22,
+-	RELOC_22,	/* SR 22-bit relocs */
+-	RELOC_13,
+-	RELOC_LO10,	/* SR 13&10-bit relocs */
+-	RELOC_SFA_BASE,
+-	RELOC_SFA_OFF13, /* SR S.F.A. relocs */
+-	RELOC_BASE10,
+-	RELOC_BASE13,
+-	RELOC_BASE22,	/* base_relative pic */
+-	RELOC_PC10,
+-	RELOC_PC22,	/* special pc-rel pic */
+-	RELOC_JMP_TBL,	/* jmp_tbl_rel in pic */
+-	RELOC_SEGOFF16,	/* ShLib offset-in-seg */
+-	RELOC_GLOB_DAT,
+-	RELOC_JMP_SLOT,
+-	RELOC_RELATIVE 	/* rtld relocs */
+-};
+-
+-/*
+- * Format of a relocation datum.
+- */
+-struct relocation_info /* used when header.a_machtype == M_SPARC */
+-{
+-        unsigned int    r_address;  /* relocation addr */
+-        unsigned int    r_index:24; /* segment index or symbol index */
+-        unsigned int    r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
+-        unsigned int    r_pad:2;    /* <unused> */
+-        enum reloc_type r_type:5;   /* type of relocation to perform */
+-        int             r_addend;   /* addend for relocation value */
+-};
+-
+-#define N_RELOCATION_INFO_DECLARED 1
+-
+-#endif /* !(__ASSEMBLY__) */
+-
+-#endif /* __SPARC_A_OUT_H__ */
+diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h
+index 680e51d..19790eb 100644
+--- a/include/asm-sparc/device.h
++++ b/include/asm-sparc/device.h
+@@ -16,6 +16,8 @@ struct dev_archdata {
+ 
+ 	struct device_node	*prom_node;
+ 	struct of_device	*op;
++
++	int			numa_node;
+ };
+ 
+ #endif /* _ASM_SPARC_DEVICE_H */
+diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h
+index dbe7a58..d3978e0 100644
+--- a/include/asm-sparc/floppy.h
++++ b/include/asm-sparc/floppy.h
+@@ -280,7 +280,7 @@ static inline void sun_fd_enable_dma(void)
+ 
+ /* Our low-level entry point in arch/sparc/kernel/entry.S */
+ extern int sparc_floppy_request_irq(int irq, unsigned long flags,
+-				    irqreturn_t (*irq_handler)(int irq, void *));
++				    irq_handler_t irq_handler);
+ 
+ static int sun_fd_request_irq(void)
+ {
+diff --git a/include/asm-sparc/head.h b/include/asm-sparc/head.h
+index 1a03c28..fcdba51 100644
+--- a/include/asm-sparc/head.h
++++ b/include/asm-sparc/head.h
+@@ -46,45 +46,12 @@
+         b linux_sparc_syscall; \
+         rd %psr, %l0;
+ 
+-/* Software trap for SunOS4.1.x system calls. */
+-#define SUNOS_SYSCALL_TRAP \
+-        rd %psr, %l0; \
+-        sethi %hi(sunos_sys_table), %l7; \
+-        b linux_sparc_syscall; \
+-        or %l7, %lo(sunos_sys_table), %l7;
+-
+-#define SUNOS_NO_SYSCALL_TRAP \
+-        b sunos_syscall; \
+-        rd %psr, %l0; \
+-        nop; \
+-        nop;
+-
+-/* Software trap for Slowaris system calls. */
+-#define SOLARIS_SYSCALL_TRAP \
+-        b solaris_syscall; \
+-        rd %psr, %l0; \
+-        nop; \
+-        nop;
+-
+-#define INDIRECT_SOLARIS_SYSCALL(x) \
+-	mov x, %g1; \
+-	b solaris_syscall; \
+-	rd %psr, %l0; \
+-	nop;
+-
+ #define BREAKPOINT_TRAP \
+ 	b breakpoint_trap; \
+ 	rd %psr,%l0; \
+ 	nop; \
+ 	nop;
+ 
+-/* Software trap for Sparc-netbsd system calls. */
+-#define NETBSD_SYSCALL_TRAP \
+-        sethi %hi(sys_call_table), %l7; \
+-        or %l7, %lo(sys_call_table), %l7; \
+-        b bsd_syscall; \
+-        rd %psr, %l0;
+-
+ /* The Get Condition Codes software trap for userland. */
+ #define GETCC_TRAP \
+         b getcc_trap_handler; mov %psr, %l0; nop; nop;
+diff --git a/include/asm-sparc/ide.h b/include/asm-sparc/ide.h
+index 4076cb5..afd1736 100644
+--- a/include/asm-sparc/ide.h
++++ b/include/asm-sparc/ide.h
+@@ -17,8 +17,6 @@
+ #undef  MAX_HWIFS
+ #define MAX_HWIFS	2
+ 
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+ #define __ide_insl(data_reg, buffer, wcount) \
+ 	__ide_insw(data_reg, buffer, (wcount)<<1)
+ #define __ide_outsl(data_reg, buffer, wcount) \
+diff --git a/include/asm-sparc/ioctls.h b/include/asm-sparc/ioctls.h
+index 058c206..3f4d008 100644
+--- a/include/asm-sparc/ioctls.h
++++ b/include/asm-sparc/ioctls.h
+@@ -43,8 +43,6 @@
+ #define __TIOCSETX        _IOW('t', 34, int) /* SunOS Specific */
+ #define __TIOCGETX        _IOR('t', 35, int) /* SunOS Specific */
+ #define TIOCCONS	_IO('t', 36)
+-#define __TIOCSSIZE     _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */
+-#define __TIOCGSIZE     _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */
+ #define TIOCGSOFTCAR	_IOR('t', 100, int)
+ #define TIOCSSOFTCAR	_IOW('t', 101, int)
+ #define __TIOCUCNTL       _IOW('t', 102, int) /* SunOS Specific */
+diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h
+index b7dc40b..e18be98 100644
+--- a/include/asm-sparc/mman.h
++++ b/include/asm-sparc/mman.h
+@@ -22,19 +22,6 @@
+ #define MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
+ #define MAP_NONBLOCK	0x10000		/* do not block on IO */
+ 
+-/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system
+- * XXX calls.
+- */
+-
+-/* SunOS sys_mctl() stuff... */
+-#define MC_SYNC         1  /* Sync pages in memory with storage (usu. a file) */
+-#define MC_LOCK         2  /* Lock pages into core ram, do not allow swapping of them */
+-#define MC_UNLOCK       3  /* Unlock pages locked via previous mctl() with MC_LOCK arg */
+-#define MC_LOCKAS       5  /* Lock an entire address space of the calling process */
+-#define MC_UNLOCKAS     6  /* Unlock entire address space of calling process */
+-
+-#define MADV_FREE	0x5		/* (Solaris) contents can be freed */
+-
+ #ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+ #define arch_mmap_check	sparc_mmap_check
+diff --git a/include/asm-sparc/namei.h b/include/asm-sparc/namei.h
+index f2461e8..618344d 100644
+--- a/include/asm-sparc/namei.h
++++ b/include/asm-sparc/namei.h
+@@ -8,19 +8,6 @@
+ #ifndef __SPARC_NAMEI_H
+ #define __SPARC_NAMEI_H
+ 
+-#define SPARC_BSD_EMUL "/usr/gnemul/sunos/"
+-#define SPARC_SOL_EMUL "/usr/gnemul/solaris/"
+-
+-static inline char * __emul_prefix(void)
+-{
+-	switch (current->personality) {
+-	case PER_SUNOS:
+-		return SPARC_BSD_EMUL;
+-	case PER_SVR4:
+-		return SPARC_SOL_EMUL;
+-	default:
+-		return NULL;
+-	}
+-}
++#define __emul_prefix() NULL
+ 
+ #endif /* __SPARC_NAMEI_H */
+diff --git a/include/asm-sparc/pconf.h b/include/asm-sparc/pconf.h
+deleted file mode 100644
+index d73c1f1..0000000
+--- a/include/asm-sparc/pconf.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/* $Id: pconf.h,v 1.3 1996/04/25 06:13:25 davem Exp $
+- * pconf.h: pathconf() and fpathconf() defines for SunOS
+- *          system call compatibility.
+- *
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#ifndef _SPARC_PCONF_H
+-#define _SPARC_PCONF_H
+-
+-#include <linux/fs.h>
+-#include <linux/limits.h>
+-
+-#define _PCONF_LINK       1 /* Max number of links to an object        */
+-#define _PCONF_CANON      2 /* TTY input buffer line size              */
+-#define _PCONF_INPUT      3 /* Biggest packet a tty can imbibe at once */
+-#define _PCONF_NAME       4 /* Filename length max                     */
+-#define _PCONF_PATH       5 /* Max size of a pathname                  */
+-#define _PCONF_PIPE       6 /* Buffer size for a pipe                  */
+-#define _PCONF_CHRESTRICT 7 /* Can only root chown files?              */
+-#define _PCONF_NOTRUNC    8 /* Are pathnames truncated if too big?     */
+-#define _PCONF_VDISABLE   9 /* Magic char to disable special tty chars */
+-#define _PCONF_MAXPCONF   9
+-
+-#endif /* !(_SPARC_PCONF_H) */
+diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
+index 40b1e41..e300697 100644
+--- a/include/asm-sparc/processor.h
++++ b/include/asm-sparc/processor.h
+@@ -13,8 +13,6 @@
+  */
+ #define current_text_addr() ({ void *pc; __asm__("sethi %%hi(1f), %0; or %0, %%lo(1f), %0;\n1:" : "=r" (pc)); pc; })
+ 
+-#include <linux/a.out.h>
+-
+ #include <asm/psr.h>
+ #include <asm/ptrace.h>
+ #include <asm/head.h>
+@@ -67,7 +65,6 @@ struct thread_struct {
+ 	struct fpq	fpqueue[16];
+ 	unsigned long flags;
+ 	mm_segment_t current_ds;
+-	struct exec core_exec;     /* just what it says. */
+ 	int new_signal;
+ };
+ 
+diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h
+index df5dc44..fd55522 100644
+--- a/include/asm-sparc/prom.h
++++ b/include/asm-sparc/prom.h
+@@ -77,6 +77,11 @@ extern int of_getintprop_default(struct device_node *np,
+ 				 const char *name,
+ 				 int def);
+ extern int of_find_in_proplist(const char *list, const char *match, int len);
++#ifdef CONFIG_NUMA
++extern int of_node_to_nid(struct device_node *dp);
++#else
++#define of_node_to_nid(dp)	(-1)
++#endif
+ 
+ extern void prom_build_devicetree(void);
+ 
+diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h
+index 8018f9f..d9b2034 100644
+--- a/include/asm-sparc/semaphore.h
++++ b/include/asm-sparc/semaphore.h
+@@ -1,192 +1 @@
+-#ifndef _SPARC_SEMAPHORE_H
+-#define _SPARC_SEMAPHORE_H
+-
+-/* Dinky, good for nothing, just barely irq safe, Sparc semaphores. */
+-
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+-	atomic24_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC24_INIT(n),				\
+-	.sleepers	= 0,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	atomic24_set(&sem->count, val);
+-	sem->sleepers = 0;
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int __down_interruptible(struct semaphore * sem);
+-extern int __down_trylock(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-static inline void down(struct semaphore * sem)
+-{
+-	register volatile int *ptr asm("g1");
+-	register int increment asm("g2");
+-
+-	might_sleep();
+-
+-	ptr = &(sem->count.counter);
+-	increment = 1;
+-
+-	__asm__ __volatile__(
+-	"mov	%%o7, %%g4\n\t"
+-	"call	___atomic24_sub\n\t"
+-	" add	%%o7, 8, %%o7\n\t"
+-	"tst	%%g2\n\t"
+-	"bl	2f\n\t"
+-	" nop\n"
+-	"1:\n\t"
+-	".subsection 2\n"
+-	"2:\n\t"
+-	"save	%%sp, -64, %%sp\n\t"
+-	"mov	%%g1, %%l1\n\t"
+-	"mov	%%g5, %%l5\n\t"
+-	"call	%3\n\t"
+-	" mov	%%g1, %%o0\n\t"
+-	"mov	%%l1, %%g1\n\t"
+-	"ba	1b\n\t"
+-	" restore %%l5, %%g0, %%g5\n\t"
+-	".previous\n"
+-	: "=&r" (increment)
+-	: "0" (increment), "r" (ptr), "i" (__down)
+-	: "g3", "g4", "g7", "memory", "cc");
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	register volatile int *ptr asm("g1");
+-	register int increment asm("g2");
+-
+-	might_sleep();
+-
+-	ptr = &(sem->count.counter);
+-	increment = 1;
+-
+-	__asm__ __volatile__(
+-	"mov	%%o7, %%g4\n\t"
+-	"call	___atomic24_sub\n\t"
+-	" add	%%o7, 8, %%o7\n\t"
+-	"tst	%%g2\n\t"
+-	"bl	2f\n\t"
+-	" clr	%%g2\n"
+-	"1:\n\t"
+-	".subsection 2\n"
+-	"2:\n\t"
+-	"save	%%sp, -64, %%sp\n\t"
+-	"mov	%%g1, %%l1\n\t"
+-	"mov	%%g5, %%l5\n\t"
+-	"call	%3\n\t"
+-	" mov	%%g1, %%o0\n\t"
+-	"mov	%%l1, %%g1\n\t"
+-	"mov	%%l5, %%g5\n\t"
+-	"ba	1b\n\t"
+-	" restore %%o0, %%g0, %%g2\n\t"
+-	".previous\n"
+-	: "=&r" (increment)
+-	: "0" (increment), "r" (ptr), "i" (__down_interruptible)
+-	: "g3", "g4", "g7", "memory", "cc");
+-
+-	return increment;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	register volatile int *ptr asm("g1");
+-	register int increment asm("g2");
+-
+-	ptr = &(sem->count.counter);
+-	increment = 1;
+-
+-	__asm__ __volatile__(
+-	"mov	%%o7, %%g4\n\t"
+-	"call	___atomic24_sub\n\t"
+-	" add	%%o7, 8, %%o7\n\t"
+-	"tst	%%g2\n\t"
+-	"bl	2f\n\t"
+-	" clr	%%g2\n"
+-	"1:\n\t"
+-	".subsection 2\n"
+-	"2:\n\t"
+-	"save	%%sp, -64, %%sp\n\t"
+-	"mov	%%g1, %%l1\n\t"
+-	"mov	%%g5, %%l5\n\t"
+-	"call	%3\n\t"
+-	" mov	%%g1, %%o0\n\t"
+-	"mov	%%l1, %%g1\n\t"
+-	"mov	%%l5, %%g5\n\t"
+-	"ba	1b\n\t"
+-	" restore %%o0, %%g0, %%g2\n\t"
+-	".previous\n"
+-	: "=&r" (increment)
+-	: "0" (increment), "r" (ptr), "i" (__down_trylock)
+-	: "g3", "g4", "g7", "memory", "cc");
+-
+-	return increment;
+-}
+-
+-static inline void up(struct semaphore * sem)
+-{
+-	register volatile int *ptr asm("g1");
+-	register int increment asm("g2");
+-
+-	ptr = &(sem->count.counter);
+-	increment = 1;
+-
+-	__asm__ __volatile__(
+-	"mov	%%o7, %%g4\n\t"
+-	"call	___atomic24_add\n\t"
+-	" add	%%o7, 8, %%o7\n\t"
+-	"tst	%%g2\n\t"
+-	"ble	2f\n\t"
+-	" nop\n"
+-	"1:\n\t"
+-	".subsection 2\n"
+-	"2:\n\t"
+-	"save	%%sp, -64, %%sp\n\t"
+-	"mov	%%g1, %%l1\n\t"
+-	"mov	%%g5, %%l5\n\t"
+-	"call	%3\n\t"
+-	" mov	%%g1, %%o0\n\t"
+-	"mov	%%l1, %%g1\n\t"
+-	"ba	1b\n\t"
+-	" restore %%l5, %%g0, %%g5\n\t"
+-	".previous\n"
+-	: "=&r" (increment)
+-	: "0" (increment), "r" (ptr), "i" (__up)
+-	: "g3", "g4", "g7", "memory", "cc");
+-}	
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* !(_SPARC_SEMAPHORE_H) */
++#include <linux/semaphore.h>
+diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
+index 2e2bd0b..a00e15d 100644
+--- a/include/asm-sparc/socket.h
++++ b/include/asm-sparc/socket.h
+@@ -24,9 +24,6 @@
+ #define SO_SNDTIMEO     0x4000
+ #define SO_ACCEPTCONN	0x8000
+ 
+-/* wha!??? */
+-#define SO_DONTLINGER   (~SO_LINGER)  /* Older SunOS compat. hack */
+-
+ #define SO_SNDBUF	0x1001
+ #define SO_RCVBUF	0x1002
+ #define SO_SNDBUFFORCE	0x100a
+diff --git a/include/asm-sparc/solerrno.h b/include/asm-sparc/solerrno.h
+deleted file mode 100644
+index 8abce7e..0000000
+--- a/include/asm-sparc/solerrno.h
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/* $Id: solerrno.h,v 1.5 1996/04/25 06:13:32 davem Exp $
+- * solerrno.h: Solaris error return codes for compatibility.
+- *
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#ifndef _SPARC_SOLERRNO_H
+-#define _SPARC_SOLERRNO_H
+-
+-#define SOL_EPERM          1     /* Required superuser access perms  */
+-#define SOL_ENOENT         2     /* File or directory does not exist */
+-#define SOL_ESRCH          3     /* Process did not exist            */
+-#define	SOL_EINTR          4     /* System call was interrupted      */
+-#define	SOL_EIO            5     /* An i/o error occurred            */
+-#define	SOL_ENXIO          6     /* Device or Address does not exist */
+-#define	SOL_E2BIG          7	 /* Too many arguments were given    */
+-#define	SOL_ENOEXEC        8     /* Header of executable was munged  */
+-#define	SOL_EBADF          9     /* Bogus file number                */
+-#define	SOL_ECHILD         10    /* No children of process exist     */
+-#define	SOL_EAGAIN         11    /* beep beep, "try again later"     */
+-#define	SOL_ENOMEM         12    /* No memory available              */
+-#define	SOL_EACCES         13    /* Access not allowed               */
+-#define	SOL_EFAULT         14    /* Address passed was invalid       */
+-#define	SOL_ENOTBLK        15    /* blkdev op on non-block device    */
+-#define	SOL_EBUSY          16    /* Mounted device was busy          */
+-#define	SOL_EEXIST         17    /* File specified already exists    */
+-#define	SOL_EXDEV          18    /* Link request across diff devices */
+-#define	SOL_ENODEV         19    /* Device does not exist on system  */
+-#define	SOL_ENOTDIR        20    /* Dir operation on non-directory   */
+-#define	SOL_EISDIR         21    /* File was of directory type       */
+-#define	SOL_EINVAL         22    /* Argument passed was invalid      */
+-#define	SOL_ENFILE         23    /* No more room in file table       */
+-#define	SOL_EMFILE         24    /* Proc has too many files open     */
+-#define	SOL_ENOTTY         25    /* Ioctl was invalid for req device */
+-#define	SOL_ETXTBSY        26    /* Text file in busy state          */
+-#define	SOL_EFBIG          27    /* Too big of a file for operation  */
+-#define	SOL_ENOSPC         28    /* Disk is full                     */
+-#define	SOL_ESPIPE         29    /* Seek attempted on non-seeking dev*/
+-#define	SOL_EROFS          30    /* Write attempted on read-only fs  */
+-#define	SOL_EMLINK         31    /* Too many links in file search    */
+-#define	SOL_EPIPE          32    /* Call a plumber                   */
+-#define	SOL_EDOM           33    /* Argument was out of fct domain   */
+-#define	SOL_ERANGE         34    /* Could not represent math result  */
+-#define	SOL_ENOMSG         35    /* Message of req type doesn't exist */
+-#define	SOL_EIDRM          36    /* Identifier has been removed      */
+-#define	SOL_ECHRNG         37    /* Req channel number out of range  */
+-#define	SOL_EL2NSYNC       38    /* Could not sync at run level 2    */
+-#define	SOL_EL3HLT         39    /* Halted at run level 3            */
+-#define	SOL_EL3RST         40    /* Reset at run level 3             */
+-#define	SOL_ELNRNG         41    /* Out of range link number         */
+-#define	SOL_EUNATCH        42    /* Driver for protocol not attached */
+-#define	SOL_ENOCSI         43    /* CSI structure not around         */
+-#define	SOL_EL2HLT         44    /* Halted at run level 2            */
+-#define	SOL_EDEADLK        45    /* Deadlock condition detected      */
+-#define	SOL_ENOLCK         46    /* Record locks unavailable         */
+-#define	SOL_ECANCELED      47    /* Cancellation of oper. happened   */
+-#define	SOL_ENOTSUP        48    /* Attempt of unsupported operation */
+-#define	SOL_EDQUOT         49    /* Users disk quota exceeded        */
+-#define	SOL_EBADE          50    /* Invalid exchange                 */
+-#define	SOL_EBADR          51    /* Request descriptor was invalid   */
+-#define	SOL_EXFULL         52    /* Full exchange                    */
+-#define	SOL_ENOANO         53    /* ano does not exist               */
+-#define	SOL_EBADRQC        54    /* Req code was invalid             */
+-#define	SOL_EBADSLT        55    /* Bad slot number                  */
+-#define	SOL_EDEADLOCK      56    /* Deadlock in fs error             */
+-#define	SOL_EBFONT         57    /* Font file format invalid         */
+-/* YOW, I LOVE SYSV STREAMS!!!! */
+-#define	SOL_ENOSTR         60    /* Stream-op on non-stream dev      */
+-#define	SOL_ENODATA        61    /* No data avail at this time       */
+-#define	SOL_ETIME          62    /* Expiration of time occurred      */
+-#define	SOL_ENOSR          63    /* Streams resources exhausted      */
+-#define	SOL_ENONET         64    /* No network connected             */
+-#define	SOL_ENOPKG         65    /* Non-installed package            */
+-#define	SOL_EREMOTE        66    /* Object was on remote machine     */
+-#define	SOL_ENOLINK        67    /* Cut link                         */
+-#define	SOL_EADV           68    /* Error in advertise               */
+-#define	SOL_ESRMNT         69    /* Some magic srmount problem       */
+-#define	SOL_ECOMM          70    /* During send, comm error occurred */
+-#define	SOL_EPROTO         71    /* Protocol botch                   */
+-#define	SOL_EMULTIHOP      74    /* Multihop attempted               */
+-#define	SOL_EBADMSG        77    /* Message was unreadable           */
+-#define	SOL_ENAMETOOLONG   78    /* Too long of a path name          */
+-#define	SOL_EOVERFLOW      79    /* Data type too small for datum    */
+-#define	SOL_ENOTUNIQ       80    /* Logical name was not unique      */
+-#define	SOL_EBADFD         81    /* Op cannot be performed on fd     */
+-#define	SOL_EREMCHG        82    /* Remote address is now different  */
+-#define	SOL_ELIBACC        83    /* Shared lib could not be accessed */
+-#define	SOL_ELIBBAD        84    /* ShLib is corrupted in some way   */
+-#define	SOL_ELIBSCN        85    /* A.out ShLib problems             */
+-#define	SOL_ELIBMAX        86    /* Exceeded ShLib linkage limit     */
+-#define	SOL_ELIBEXEC       87    /* Execution of ShLib attempted     */
+-#define	SOL_EILSEQ         88    /* Bad byte sequence found          */
+-#define	SOL_ENOSYS         89    /* Invalid filesystem operation     */
+-#define	SOL_ELOOP          90    /* Detected loop in symbolic links  */
+-#define	SOL_ERESTART       91    /* System call is restartable       */
+-#define	SOL_ESTRPIPE       92    /* Do not sleep in head of stream   */
+-#define	SOL_ENOTEMPTY      93    /* Rmdir of non-empty directory     */
+-#define	SOL_EUSERS         94    /* Over abundance of users for ufs  */
+-#define	SOL_ENOTSOCK       95    /* Sock-op on non-sock              */
+-#define	SOL_EDESTADDRREQ   96    /* No dest addr given, but needed   */
+-#define	SOL_EMSGSIZE       97    /* Msg too big                      */
+-#define	SOL_EPROTOTYPE     98    /* Bad socket protocol              */
+-#define	SOL_ENOPROTOOPT    99    /* Unavailable protocol             */
+-#define	SOL_EPROTONOSUPPORT 120  /* Unsupported protocol             */
+-#define	SOL_ESOCKTNOSUPPORT 121  /* Unsupported socket type          */
+-#define	SOL_EOPNOTSUPP     122   /* Unsupported sock-op              */
+-#define	SOL_EPFNOSUPPORT   123   /* Unsupported protocol family      */
+-#define	SOL_EAFNOSUPPORT   124   /* Unsup addr family for protocol   */
+-#define	SOL_EADDRINUSE     125   /* Req addr is already in use       */
+-#define	SOL_EADDRNOTAVAIL  126   /* Req addr not available right now */
+-#define	SOL_ENETDOWN       127   /* Your subnet is on fire           */
+-#define	SOL_ENETUNREACH    128   /* Someone playing with gateway and */
+-                                 /* did not tell you he was going to */
+-#define	SOL_ENETRESET      129   /* Buy less-buggy ethernet cards    */
+-#define	SOL_ECONNABORTED   130   /* Aborted connection due to sw     */
+-#define	SOL_ECONNRESET     131   /* Your peers reset your connection */
+-#define	SOL_ENOBUFS        132   /* No buffer space available        */
+-#define	SOL_EISCONN        133   /* Connect on already connected     */
+-                                 /* socket attempted                 */
+-#define	SOL_ENOTCONN       134   /* Comm on non-connected socket     */
+-#define	SOL_ESHUTDOWN      143   /* Op attempted after sock-shutdown */
+-#define	SOL_ETOOMANYREFS   144   /* Reference limit exceeded         */
+-#define	SOL_ETIMEDOUT      145   /* Timed out connection             */
+-#define	SOL_ECONNREFUSED   146   /* Connection refused by remote host*/
+-#define	SOL_EHOSTDOWN      147   /* Remote host is up in flames      */
+-#define	SOL_EHOSTUNREACH   148   /* Make a left at Easton Ave.....   */
+-#define	SOL_EWOULDBLOCK    EAGAIN /* Just an alias */
+-#define	SOL_EALREADY       149   /* Operation is already occurring   */
+-#define	SOL_EINPROGRESS    150   /* Operation is happening now       */
+-#define	SOL_ESTALE         151   /* Fungus growth on NFS file handle */
+-
+-#endif /* !(_SPARC_SOLERRNO_H) */
+diff --git a/include/asm-sparc/svr4.h b/include/asm-sparc/svr4.h
+deleted file mode 100644
+index da1f1c9..0000000
+--- a/include/asm-sparc/svr4.h
++++ /dev/null
+@@ -1,119 +0,0 @@
+-/* Solaris/SPARC constants and definitions -- 
+- * (C) 1996 Miguel de Icaza
+- *
+- * This file is not meant to be included by user level applications
+- * but the solaris syscall emulator
+- */
+-
+-#ifndef _SPARC_SVR4_H
+-#define _SPARC_SVR4_H
+-
+-/* Signals as used by svr4 */
+-typedef struct {                /* signal set type */
+-	ulong sigbits[4];
+-} svr4_sigset_t;
+-
+-/* Values for siginfo.code */
+-#define SVR4_SINOINFO 32767
+-/* Siginfo, sucker expects bunch of information on those parameters */
+-typedef union {
+-	char total_size [128];
+-	struct {
+-		int signo;
+-		int code;
+-		int error;
+-		union {
+-		} data; 
+-	} siginfo;
+-} svr4_siginfo_t;
+-
+-/* Context definition */
+-
+-/* Location of the user stored registers into a greg_t */
+-enum {
+-	SVR4_PSR, SVR4_PC, SVR4_NPC, SVR4_Y,
+-	SVR4_G1,  SVR4_G2, SVR4_G3,  SVR4_G4,
+-	SVR4_G5,  SVR4_G6, SVR4_G7,  SVR4_O0,
+-	SVR4_O1,  SVR4_O2, SVR4_O3,  SVR4_O4,
+-	SVR4_O5,  SVR4_O6, SVR4_O7
+-};
+-
+-/* sizeof (regs) / sizeof (greg_t), defined in the ABI */
+-#define SVR4_NREGS  19
+-#define SVR4_MAXWIN 31
+-
+-typedef struct {
+-	uint rwin_lo[8];
+-	uint rwin_in[8];
+-} svr4_rwindow_t;
+-
+-typedef struct {
+-	int            count;
+-	int            __user *winptr [SVR4_MAXWIN]; /* pointer to the windows */
+-	svr4_rwindow_t win[SVR4_MAXWIN];      /* the windows */
+-} svr4_gwindows_t;
+-
+-typedef int svr4_gregset_t[SVR4_NREGS];
+-
+-typedef struct {
+-	double   fpu_regs[32];
+-	void     *fp_q;
+-	unsigned fp_fsr;
+-	u_char   fp_nqel;
+-	u_char   fp_nqsize;
+-	u_char   inuse;		/* if fpu is in use */
+-} svr4_fregset_t;
+-
+-typedef struct {
+-	uint    id;		/* if this holds "xrs" string => ptr is valid */
+-	caddr_t ptr;
+-} svr4_xrs_t;
+-
+-/* Machine dependent context */
+-typedef struct {
+-	svr4_gregset_t   greg;	/* registers 0..19 (see top) */
+-	svr4_gwindows_t  __user *gwin;	/* may point to register windows */
+-	svr4_fregset_t   freg;	/* floating point registers */
+-	svr4_xrs_t       xrs;	/* mhm? */
+-	long             pad[19];
+-} svr4_mcontext_t;
+-
+-/* flags for stack_t.flags */
+-enum svr4_stack_flags {
+-	SVR4_SS_ONSTACK,
+-	SVR4_SS_DISABLE,
+-};
+-
+-/* signal stack exection place, unsupported */
+-typedef struct svr4_stack_t {
+-        char __user *sp;
+-        int  size;
+-        int  flags;
+-} svr4_stack_t;
+-
+-/* Context used by getcontext and setcontext */
+-typedef struct svr4_ucontext_t {
+-	u_long               flags; /* context flags, indicate what is loaded */
+-	struct svr4_ucontext *link;
+-	svr4_sigset_t        sigmask;
+-	svr4_stack_t         stack;
+-	svr4_mcontext_t      mcontext;
+-	long                 pad[23];
+-} svr4_ucontext_t;                          
+-
+-/* windows hold the windows as they were at signal time,
+- * ucontext->mcontext holds a pointer to them.
+- * addresses for uc and si are passed as parameters to svr4 signal
+- * handler
+- */
+-
+-/* This is the signal frame that is passed to the signal handler */
+-typedef struct {
+-	svr4_gwindows_t gw;	/* windows */
+-	svr4_ucontext_t uc;	/* machine context */
+-	svr4_siginfo_t  si;	/* siginfo */
+-} svr4_signal_frame_t;
+-
+-#define SVR4_SF_ALIGNED (((sizeof (svr4_signal_frame_t) + 7) & (~7)))
+-
+-#endif /* include control */
+diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h
+index 4333232..733d405 100644
+--- a/include/asm-sparc/termios.h
++++ b/include/asm-sparc/termios.h
+@@ -33,11 +33,6 @@ struct ltchars {
+ };
+ #endif /* __KERNEL__ */
+ 
+-struct sunos_ttysize {
+-	int st_lines;   /* Lines on the terminal */
+-	int st_columns; /* Columns on the terminal */
+-};
+-
+ struct winsize {
+ 	unsigned short ws_row;
+ 	unsigned short ws_col;
+diff --git a/include/asm-sparc/user.h b/include/asm-sparc/user.h
+index b5f1abf..3400ea8 100644
+--- a/include/asm-sparc/user.h
++++ b/include/asm-sparc/user.h
+@@ -1,60 +1,6 @@
+-/* $Id: user.h,v 1.5 1998/02/23 01:49:22 rth Exp $
+- * asm-sparc/user.h: Core file definitions for the Sparc.
+- *
+- * Keep in sync with reg.h.  Actually, we could get rid of this
+- * one, since we won't a.out core dump that much anyways - miguel.
+- * Copyright (C) 1995 (davem at caip.rutgers.edu)
+- */
+ #ifndef _SPARC_USER_H
+ #define _SPARC_USER_H
+ 
+-#include <asm/a.out.h>
+-struct sunos_regs {
+-	unsigned long psr, pc, npc, y;
+-	unsigned long regs[15];
+-};
+-
+-struct sunos_fpqueue {
+-	unsigned long *addr;
+-	unsigned long inst;
+-};
+-
+-struct sunos_fp {
+-	union {
+-		unsigned long regs[32];
+-		double reg_dbls[16];
+-	} fregs;
+-	unsigned long fsr;
+-	unsigned long flags;
+-	unsigned long extra;
+-	unsigned long fpq_count;
+-	struct sunos_fpqueue fpq[16];
+-};
+-
+-struct sunos_fpu {
+-	struct sunos_fp fpstatus;
+-};
+-
+-/* The SunOS core file header layout. */
+-struct user {
+-	unsigned long magic;
+-	unsigned long len;
+-	struct sunos_regs regs;
+-	struct exec uexec;
+-	int           signal;
+-	size_t        u_tsize; /* all of these in bytes! */
+-	size_t        u_dsize;
+-	size_t        u_ssize;
+-	char          u_comm[17];
+-	struct sunos_fpu fpu;
+-	unsigned long sigcode;   /* Special sigcontext subcode, if any */
+-};
+-
+-#define NBPG                   0x2000
+-#define UPAGES                 1
+-#define HOST_TEXT_START_ADDR   (u.start_code)
+-#define HOST_DATA_START_ADDR   (u.uexec.a_data)
+-#define HOST_STACK_END_ADDR    (- u.u_ssize * NBPG)
+-#define SUNOS_CORE_MAGIC       0x080456
++/* Nothing to define.  */
+ 
+ #endif /* !(_SPARC_USER_H) */
+diff --git a/include/asm-sparc64/Kbuild b/include/asm-sparc64/Kbuild
+index a90dc82..dce1cf9 100644
+--- a/include/asm-sparc64/Kbuild
++++ b/include/asm-sparc64/Kbuild
+@@ -12,7 +12,6 @@ header-y += display7seg.h
+ header-y += envctrl.h
+ header-y += openprom.h
+ header-y += openpromio.h
+-header-y += pconf.h
+ header-y += psrcompat.h
+ header-y += pstate.h
+ header-y += reg.h
+diff --git a/include/asm-sparc64/a.out-core.h b/include/asm-sparc64/a.out-core.h
+deleted file mode 100644
+index 3499b3c..0000000
+--- a/include/asm-sparc64/a.out-core.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/* a.out coredump register dumper
+- *
+- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at 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_A_OUT_CORE_H
+-#define _ASM_A_OUT_CORE_H
+-
+-#ifdef __KERNEL__
+-
+-#include <linux/user.h>
+-
+-/*
+- * fill in the user structure for an a.out core dump
+- */
+-static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+-{
+-	/* Only should be used for SunOS and ancient a.out
+-	 * SparcLinux binaries...  Not worth implementing.
+-	 */
+-	memset(dump, 0, sizeof(struct user));
+-}
+-
+-#endif /* __KERNEL__ */
+-#endif /* _ASM_A_OUT_CORE_H */
+diff --git a/include/asm-sparc64/a.out.h b/include/asm-sparc64/a.out.h
+deleted file mode 100644
+index 44208c2..0000000
+--- a/include/asm-sparc64/a.out.h
++++ /dev/null
+@@ -1 +0,0 @@
+-#include <asm-sparc/a.out.h>
+diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
+index ac7eb21..c5fdabe 100644
+--- a/include/asm-sparc64/ide.h
++++ b/include/asm-sparc64/ide.h
+@@ -24,8 +24,6 @@
+ # endif
+ #endif
+ 
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+ #define __ide_insl(data_reg, buffer, wcount) \
+ 	__ide_insw(data_reg, buffer, (wcount)<<1)
+ #define __ide_outsl(data_reg, buffer, wcount) \
+diff --git a/include/asm-sparc64/ioctls.h b/include/asm-sparc64/ioctls.h
+index 083c9a0..c1be406 100644
+--- a/include/asm-sparc64/ioctls.h
++++ b/include/asm-sparc64/ioctls.h
+@@ -44,8 +44,6 @@
+ #define __TIOCSETX        _IOW('t', 34, int) /* SunOS Specific */
+ #define __TIOCGETX        _IOR('t', 35, int) /* SunOS Specific */
+ #define TIOCCONS	_IO('t', 36)
+-#define __TIOCSSIZE     _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */
+-#define __TIOCGSIZE     _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */
+ #define TIOCGSOFTCAR	_IOR('t', 100, int)
+ #define TIOCSSOFTCAR	_IOW('t', 101, int)
+ #define __TIOCUCNTL       _IOW('t', 102, int) /* SunOS Specific */
+diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h
+index 46325dd..d7b9afc 100644
+--- a/include/asm-sparc64/iommu.h
++++ b/include/asm-sparc64/iommu.h
+@@ -56,6 +56,7 @@ struct strbuf {
+ };
+ 
+ extern int iommu_table_init(struct iommu *iommu, int tsbsize,
+-			    u32 dma_offset, u32 dma_addr_mask);
++			    u32 dma_offset, u32 dma_addr_mask,
++			    int numa_node);
+ 
+ #endif /* !(_SPARC64_IOMMU_H) */
+diff --git a/include/asm-sparc64/lmb.h b/include/asm-sparc64/lmb.h
+new file mode 100644
+index 0000000..6a352cb
+--- /dev/null
++++ b/include/asm-sparc64/lmb.h
+@@ -0,0 +1,10 @@
++#ifndef _SPARC64_LMB_H
++#define _SPARC64_LMB_H
++
++#include <asm/oplib.h>
++
++#define LMB_DBG(fmt...) prom_printf(fmt)
++
++#define LMB_REAL_LIMIT	0
++
++#endif /* !(_SPARC64_LMB_H) */
+diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h
+index 8cc1860..e584563 100644
+--- a/include/asm-sparc64/mman.h
++++ b/include/asm-sparc64/mman.h
+@@ -22,19 +22,6 @@
+ #define MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
+ #define MAP_NONBLOCK	0x10000		/* do not block on IO */
+ 
+-/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system
+- * XXX calls.
+- */
+-
+-/* SunOS sys_mctl() stuff... */
+-#define MC_SYNC         1  /* Sync pages in memory with storage (usu. a file) */
+-#define MC_LOCK         2  /* Lock pages into core ram, do not allow swapping of them */
+-#define MC_UNLOCK       3  /* Unlock pages locked via previous mctl() with MC_LOCK arg */
+-#define MC_LOCKAS       5  /* Lock an entire address space of the calling process */
+-#define MC_UNLOCKAS     6  /* Unlock entire address space of calling process */
+-
+-#define MADV_FREE	0x5		/* (Solaris) contents can be freed */
+-
+ #ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+ #define arch_mmap_check	sparc64_mmap_check
+diff --git a/include/asm-sparc64/mmzone.h b/include/asm-sparc64/mmzone.h
+new file mode 100644
+index 0000000..ebf5986
+--- /dev/null
++++ b/include/asm-sparc64/mmzone.h
+@@ -0,0 +1,17 @@
++#ifndef _SPARC64_MMZONE_H
++#define _SPARC64_MMZONE_H
++
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++
++extern struct pglist_data *node_data[];
++
++#define NODE_DATA(nid)		(node_data[nid])
++#define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
++#define node_end_pfn(nid)	(NODE_DATA(nid)->node_end_pfn)
++
++extern int numa_cpu_lookup_table[];
++extern cpumask_t numa_cpumask_lookup_table[];
++
++#endif /* CONFIG_NEED_MULTIPLE_NODES */
++
++#endif /* _SPARC64_MMZONE_H */
+diff --git a/include/asm-sparc64/namei.h b/include/asm-sparc64/namei.h
+index ccda19e..275161f 100644
+--- a/include/asm-sparc64/namei.h
++++ b/include/asm-sparc64/namei.h
+@@ -8,19 +8,6 @@
+ #ifndef __SPARC64_NAMEI_H
+ #define __SPARC64_NAMEI_H
+ 
+-#define SPARC_BSD_EMUL "/usr/gnemul/sunos/"
+-#define SPARC_SOL_EMUL "/usr/gnemul/solaris/"
+-
+-static inline char * __emul_prefix(void)
+-{
+-	switch (current->personality) {
+-	case PER_SUNOS:
+-		return SPARC_BSD_EMUL;
+-	case PER_SVR4:
+-		return SPARC_SOL_EMUL;
+-	default:
+-		return NULL;
+-	}
+-}
++#define __emul_prefix() NULL
+ 
+ #endif /* __SPARC64_NAMEI_H */
+diff --git a/include/asm-sparc64/numnodes.h b/include/asm-sparc64/numnodes.h
+deleted file mode 100644
+index 017e7e7..0000000
+--- a/include/asm-sparc64/numnodes.h
++++ /dev/null
+@@ -1,6 +0,0 @@
+-#ifndef _SPARC64_NUMNODES_H
+-#define _SPARC64_NUMNODES_H
+-
+-#define NODES_SHIFT	0
+-
+-#endif /* !(_SPARC64_NUMNODES_H) */
+diff --git a/include/asm-sparc64/pconf.h b/include/asm-sparc64/pconf.h
+deleted file mode 100644
+index aad106a..0000000
+--- a/include/asm-sparc64/pconf.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/* $Id: pconf.h,v 1.1 1996/12/02 00:09:10 davem Exp $
+- * pconf.h: pathconf() and fpathconf() defines for SunOS
+- *          system call compatibility.
+- *
+- * Copyright (C) 1995, 1996 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#ifndef _SPARC64_PCONF_H
+-#define _SPARC64_PCONF_H
+-
+-#include <linux/fs.h>
+-#include <linux/limits.h>
+-
+-#define _PCONF_LINK       1 /* Max number of links to an object        */
+-#define _PCONF_CANON      2 /* TTY input buffer line size              */
+-#define _PCONF_INPUT      3 /* Biggest packet a tty can imbibe at once */
+-#define _PCONF_NAME       4 /* Filename length max                     */
+-#define _PCONF_PATH       5 /* Max size of a pathname                  */
+-#define _PCONF_PIPE       6 /* Buffer size for a pipe                  */
+-#define _PCONF_CHRESTRICT 7 /* Can only root chown files?              */
+-#define _PCONF_NOTRUNC    8 /* Are pathnames truncated if too big?     */
+-#define _PCONF_VDISABLE   9 /* Magic char to disable special tty chars */
+-#define _PCONF_MAXPCONF   9
+-
+-#endif /* !(_SPARC64_PCONF_H) */
+diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
+index 6da1978..b4b951d 100644
+--- a/include/asm-sparc64/ptrace.h
++++ b/include/asm-sparc64/ptrace.h
+@@ -8,6 +8,8 @@
+  * stack during a system call and basically all traps.
+  */
+ 
++#define PT_REGS_MAGIC 0x57ac6c00
++
+ #ifndef __ASSEMBLY__
+ 
+ struct pt_regs {
+@@ -16,7 +18,19 @@ struct pt_regs {
+ 	unsigned long tpc;
+ 	unsigned long tnpc;
+ 	unsigned int y;
+-	unsigned int fprs;
++
++	/* We encode a magic number, PT_REGS_MAGIC, along
++	 * with the %tt (trap type) register value at trap
++	 * entry time.  The magic number allows us to identify
++	 * accurately a trap stack frame in the stack
++	 * unwinder, and the %tt value allows us to test
++	 * things like "in a system call" etc. for an arbitray
++	 * process.
++	 *
++	 * The PT_REGS_MAGIC is choosen such that it can be
++	 * loaded completely using just a sethi instruction.
++	 */
++	unsigned int magic;
+ };
+ 
+ struct pt_regs32 {
+@@ -147,7 +161,7 @@ extern void __show_regs(struct pt_regs *);
+ #define PT_V9_TPC    0x88
+ #define PT_V9_TNPC   0x90
+ #define PT_V9_Y      0x98
+-#define PT_V9_FPRS   0x9c
++#define PT_V9_MAGIC  0x9c
+ #define PT_TSTATE	PT_V9_TSTATE
+ #define PT_TPC		PT_V9_TPC
+ #define PT_TNPC		PT_V9_TNPC
+diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h
+index 7f7c0c4..d9b2034 100644
+--- a/include/asm-sparc64/semaphore.h
++++ b/include/asm-sparc64/semaphore.h
+@@ -1,53 +1 @@
+-#ifndef _SPARC64_SEMAPHORE_H
+-#define _SPARC64_SEMAPHORE_H
+-
+-/* These are actually reasonable on the V9.
+- *
+- * See asm-ppc/semaphore.h for implementation commentary,
+- * only sparc64 specific issues are commented here.
+- */
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, count) \
+-	{ ATOMIC_INIT(count), \
+-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) }
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name, 1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	atomic_set(&sem->count, val);
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-extern void up(struct semaphore *sem);
+-extern void down(struct semaphore *sem);
+-extern int down_trylock(struct semaphore *sem);
+-extern int down_interruptible(struct semaphore *sem);
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* !(_SPARC64_SEMAPHORE_H) */
++#include <linux/semaphore.h>
+diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
+index 44a625a..8cf071f 100644
+--- a/include/asm-sparc64/socket.h
++++ b/include/asm-sparc64/socket.h
+@@ -24,9 +24,6 @@
+ #define SO_SNDTIMEO     0x4000
+ #define SO_ACCEPTCONN	0x8000
+ 
+-/* wha!??? */
+-#define SO_DONTLINGER   (~SO_LINGER)  /* Older SunOS compat. hack */
+-
+ #define SO_SNDBUF	0x1001
+ #define SO_RCVBUF	0x1002
+ #define SO_SNDBUFFORCE	0x100a
+diff --git a/include/asm-sparc64/solerrno.h b/include/asm-sparc64/solerrno.h
+deleted file mode 100644
+index a2ea6fc..0000000
+--- a/include/asm-sparc64/solerrno.h
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/* $Id: solerrno.h,v 1.1 1996/12/26 14:22:40 davem Exp $
+- * solerrno.h: Solaris error return codes for compatibility.
+- *
+- * Copyright (C) 1996 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#ifndef _SPARC64_SOLERRNO_H
+-#define _SPARC64_SOLERRNO_H
+-
+-#define SOL_EPERM          1     /* Required superuser access perms  */
+-#define SOL_ENOENT         2     /* File or directory does not exist */
+-#define SOL_ESRCH          3     /* Process did not exist            */
+-#define	SOL_EINTR          4     /* System call was interrupted      */
+-#define	SOL_EIO            5     /* An i/o error occurred            */
+-#define	SOL_ENXIO          6     /* Device or Address does not exist */
+-#define	SOL_E2BIG          7	 /* Too many arguments were given    */
+-#define	SOL_ENOEXEC        8     /* Header of executable was munged  */
+-#define	SOL_EBADF          9     /* Bogus file number                */
+-#define	SOL_ECHILD         10    /* No children of process exist     */
+-#define	SOL_EAGAIN         11    /* beep beep, "try again later"     */
+-#define	SOL_ENOMEM         12    /* No memory available              */
+-#define	SOL_EACCES         13    /* Access not allowed               */
+-#define	SOL_EFAULT         14    /* Address passed was invalid       */
+-#define	SOL_ENOTBLK        15    /* blkdev op on non-block device    */
+-#define	SOL_EBUSY          16    /* Mounted device was busy          */
+-#define	SOL_EEXIST         17    /* File specified already exists    */
+-#define	SOL_EXDEV          18    /* Link request across diff devices */
+-#define	SOL_ENODEV         19    /* Device does not exist on system  */
+-#define	SOL_ENOTDIR        20    /* Dir operation on non-directory   */
+-#define	SOL_EISDIR         21    /* File was of directory type       */
+-#define	SOL_EINVAL         22    /* Argument passed was invalid      */
+-#define	SOL_ENFILE         23    /* No more room in file table       */
+-#define	SOL_EMFILE         24    /* Proc has too many files open     */
+-#define	SOL_ENOTTY         25    /* Ioctl was invalid for req device */
+-#define	SOL_ETXTBSY        26    /* Text file in busy state          */
+-#define	SOL_EFBIG          27    /* Too big of a file for operation  */
+-#define	SOL_ENOSPC         28    /* Disk is full                     */
+-#define	SOL_ESPIPE         29    /* Seek attempted on non-seeking dev*/
+-#define	SOL_EROFS          30    /* Write attempted on read-only fs  */
+-#define	SOL_EMLINK         31    /* Too many links in file search    */
+-#define	SOL_EPIPE          32    /* Call a plumber                   */
+-#define	SOL_EDOM           33    /* Argument was out of fct domain   */
+-#define	SOL_ERANGE         34    /* Could not represent math result  */
+-#define	SOL_ENOMSG         35    /* Message of req type doesn't exist */
+-#define	SOL_EIDRM          36    /* Identifier has been removed      */
+-#define	SOL_ECHRNG         37    /* Req channel number out of range  */
+-#define	SOL_EL2NSYNC       38    /* Could not sync at run level 2    */
+-#define	SOL_EL3HLT         39    /* Halted at run level 3            */
+-#define	SOL_EL3RST         40    /* Reset at run level 3             */
+-#define	SOL_ELNRNG         41    /* Out of range link number         */
+-#define	SOL_EUNATCH        42    /* Driver for protocol not attached */
+-#define	SOL_ENOCSI         43    /* CSI structure not around         */
+-#define	SOL_EL2HLT         44    /* Halted at run level 2            */
+-#define	SOL_EDEADLK        45    /* Deadlock condition detected      */
+-#define	SOL_ENOLCK         46    /* Record locks unavailable         */
+-#define	SOL_ECANCELED      47    /* Cancellation of oper. happened   */
+-#define	SOL_ENOTSUP        48    /* Attempt of unsupported operation */
+-#define	SOL_EDQUOT         49    /* Users disk quota exceeded        */
+-#define	SOL_EBADE          50    /* Invalid exchange                 */
+-#define	SOL_EBADR          51    /* Request descriptor was invalid   */
+-#define	SOL_EXFULL         52    /* Full exchange                    */
+-#define	SOL_ENOANO         53    /* ano does not exist               */
+-#define	SOL_EBADRQC        54    /* Req code was invalid             */
+-#define	SOL_EBADSLT        55    /* Bad slot number                  */
+-#define	SOL_EDEADLOCK      56    /* Deadlock in fs error             */
+-#define	SOL_EBFONT         57    /* Font file format invalid         */
+-/* YOW, I LOVE SYSV STREAMS!!!! */
+-#define	SOL_ENOSTR         60    /* Stream-op on non-stream dev      */
+-#define	SOL_ENODATA        61    /* No data avail at this time       */
+-#define	SOL_ETIME          62    /* Expiration of time occurred      */
+-#define	SOL_ENOSR          63    /* Streams resources exhausted      */
+-#define	SOL_ENONET         64    /* No network connected             */
+-#define	SOL_ENOPKG         65    /* Non-installed package            */
+-#define	SOL_EREMOTE        66    /* Object was on remote machine     */
+-#define	SOL_ENOLINK        67    /* Cut link                         */
+-#define	SOL_EADV           68    /* Error in advertise               */
+-#define	SOL_ESRMNT         69    /* Some magic srmount problem       */
+-#define	SOL_ECOMM          70    /* During send, comm error occurred */
+-#define	SOL_EPROTO         71    /* Protocol botch                   */
+-#define	SOL_EMULTIHOP      74    /* Multihop attempted               */
+-#define	SOL_EBADMSG        77    /* Message was unreadable           */
+-#define	SOL_ENAMETOOLONG   78    /* Too long of a path name          */
+-#define	SOL_EOVERFLOW      79    /* Data type too small for datum    */
+-#define	SOL_ENOTUNIQ       80    /* Logical name was not unique      */
+-#define	SOL_EBADFD         81    /* Op cannot be performed on fd     */
+-#define	SOL_EREMCHG        82    /* Remote address is now different  */
+-#define	SOL_ELIBACC        83    /* Shared lib could not be accessed */
+-#define	SOL_ELIBBAD        84    /* ShLib is corrupted in some way   */
+-#define	SOL_ELIBSCN        85    /* A.out ShLib problems             */
+-#define	SOL_ELIBMAX        86    /* Exceeded ShLib linkage limit     */
+-#define	SOL_ELIBEXEC       87    /* Execution of ShLib attempted     */
+-#define	SOL_EILSEQ         88    /* Bad byte sequence found          */
+-#define	SOL_ENOSYS         89    /* Invalid filesystem operation     */
+-#define	SOL_ELOOP          90    /* Detected loop in symbolic links  */
+-#define	SOL_ERESTART       91    /* System call is restartable       */
+-#define	SOL_ESTRPIPE       92    /* Do not sleep in head of stream   */
+-#define	SOL_ENOTEMPTY      93    /* Rmdir of non-empty directory     */
+-#define	SOL_EUSERS         94    /* Over abundance of users for ufs  */
+-#define	SOL_ENOTSOCK       95    /* Sock-op on non-sock              */
+-#define	SOL_EDESTADDRREQ   96    /* No dest addr given, but needed   */
+-#define	SOL_EMSGSIZE       97    /* Msg too big                      */
+-#define	SOL_EPROTOTYPE     98    /* Bad socket protocol              */
+-#define	SOL_ENOPROTOOPT    99    /* Unavailable protocol             */
+-#define	SOL_EPROTONOSUPPORT 120  /* Unsupported protocol             */
+-#define	SOL_ESOCKTNOSUPPORT 121  /* Unsupported socket type          */
+-#define	SOL_EOPNOTSUPP     122   /* Unsupported sock-op              */
+-#define	SOL_EPFNOSUPPORT   123   /* Unsupported protocol family      */
+-#define	SOL_EAFNOSUPPORT   124   /* Unsup addr family for protocol   */
+-#define	SOL_EADDRINUSE     125   /* Req addr is already in use       */
+-#define	SOL_EADDRNOTAVAIL  126   /* Req addr not available right now */
+-#define	SOL_ENETDOWN       127   /* Your subnet is on fire           */
+-#define	SOL_ENETUNREACH    128   /* Someone playing with gateway and */
+-                                 /* did not tell you he was going to */
+-#define	SOL_ENETRESET      129   /* Buy less-buggy ethernet cards    */
+-#define	SOL_ECONNABORTED   130   /* Aborted connection due to sw     */
+-#define	SOL_ECONNRESET     131   /* Your peers reset your connection */
+-#define	SOL_ENOBUFS        132   /* No buffer space available        */
+-#define	SOL_EISCONN        133   /* Connect on already connected     */
+-                                 /* socket attempted                 */
+-#define	SOL_ENOTCONN       134   /* Comm on non-connected socket     */
+-#define	SOL_ESHUTDOWN      143   /* Op attempted after sock-shutdown */
+-#define	SOL_ETOOMANYREFS   144   /* Reference limit exceeded         */
+-#define	SOL_ETIMEDOUT      145   /* Timed out connection             */
+-#define	SOL_ECONNREFUSED   146   /* Connection refused by remote host*/
+-#define	SOL_EHOSTDOWN      147   /* Remote host is up in flames      */
+-#define	SOL_EHOSTUNREACH   148   /* Make a left at Easton Ave.....   */
+-#define	SOL_EWOULDBLOCK    EAGAIN /* Just an alias */
+-#define	SOL_EALREADY       149   /* Operation is already occurring   */
+-#define	SOL_EINPROGRESS    150   /* Operation is happening now       */
+-#define	SOL_ESTALE         151   /* Fungus growth on NFS file handle */
+-
+-#endif /* !(_SPARC64_SOLERRNO_H) */
+diff --git a/include/asm-sparc64/sparsemem.h b/include/asm-sparc64/sparsemem.h
+index 77bcd2b..b99d4e4 100644
+--- a/include/asm-sparc64/sparsemem.h
++++ b/include/asm-sparc64/sparsemem.h
+@@ -3,7 +3,7 @@
+ 
+ #ifdef __KERNEL__
+ 
+-#define SECTION_SIZE_BITS       31
++#define SECTION_SIZE_BITS       30
+ #define MAX_PHYSADDR_BITS       42
+ #define MAX_PHYSMEM_BITS        42
+ 
+diff --git a/include/asm-sparc64/svr4.h b/include/asm-sparc64/svr4.h
+deleted file mode 100644
+index c96d5f1..0000000
+--- a/include/asm-sparc64/svr4.h
++++ /dev/null
+@@ -1,120 +0,0 @@
+-/* Solaris/SPARC constants and definitions -- 
+- * (C) 1996 Miguel de Icaza
+- *
+- * This file is not meant to be included by user level applications
+- * but the solaris syscall emulator
+- */
+-
+-#ifndef _SPARC64_SVR4_H
+-#define _SPARC64_SVR4_H
+-
+-/* Signals as used by svr4 */
+-typedef struct {                /* signal set type */
+-	uint sigbits[4];
+-} svr4_sigset_t;
+-
+-/* Values for siginfo.code */
+-#define SVR4_SINOINFO 32767
+-/* Siginfo, sucker expects bunch of information on those parameters */
+-typedef union {
+-	char total_size [128];
+-	struct {
+-		int signo;
+-		int code;
+-		int error;
+-		union {
+-		} data; 
+-	} siginfo;
+-} svr4_siginfo_t;
+-
+-/* Context definition */
+-
+-/* Location of the user stored registers into a greg_t */
+-enum {
+-	SVR4_PSR, SVR4_PC, SVR4_NPC, SVR4_Y,
+-	SVR4_G1,  SVR4_G2, SVR4_G3,  SVR4_G4,
+-	SVR4_G5,  SVR4_G6, SVR4_G7,  SVR4_O0,
+-	SVR4_O1,  SVR4_O2, SVR4_O3,  SVR4_O4,
+-	SVR4_O5,  SVR4_O6, SVR4_O7
+-};
+-
+-/* sizeof (regs) / sizeof (greg_t), defined in the ABI */
+-#define SVR4_NREGS  19
+-#define SVR4_MAXWIN 31
+-
+-typedef struct {
+-	u32 rwin_lo[8];
+-	u32 rwin_in[8];
+-} svr4_rwindow_t;
+-
+-typedef struct {
+-	int            count;
+-	u32            winptr [SVR4_MAXWIN]; /* pointer to the windows */
+-
+-	svr4_rwindow_t win[SVR4_MAXWIN];      /* the windows */
+-} svr4_gwindows_t;
+-
+-typedef int svr4_gregset_t[SVR4_NREGS];
+-
+-typedef struct {
+-	u64   	 fpu_regs[32];
+-	u32	 fp_q;
+-	u32      fp_fsr;
+-	u_char   fp_nqel;
+-	u_char   fp_nqsize;
+-	u_char   inuse;		/* if fpu is in use */
+-} svr4_fregset_t;
+-
+-typedef struct {
+-	u32    id;		/* if this holds "xrs" string => ptr is valid */
+-	u32    ptr;
+-} svr4_xrs_t;
+-
+-/* Machine dependent context */
+-typedef struct {
+-	svr4_gregset_t   greg;	/* registers 0..19 (see top) */
+-	u32		 gwin;	/* may point to register windows */
+-	svr4_fregset_t   freg;	/* floating point registers */
+-	svr4_xrs_t       xrs;	/* mhm? */
+-	int              pad[19];
+-} svr4_mcontext_t;
+-
+-/* flags for stack_t.flags */
+-enum svr4_stack_flags {
+-	SVR4_SS_ONSTACK,
+-	SVR4_SS_DISABLE,
+-};
+-
+-/* signal stack execution place, unsupported */
+-typedef struct svr4_stack_t {
+-        u32  sp;
+-        int  size;
+-        int  flags;
+-} svr4_stack_t;
+-
+-/* Context used by getcontext and setcontext */
+-typedef struct svr4_ucontext_t {
+-	u32		flags; /* context flags, indicate what is loaded */
+-	u32		link;
+-	svr4_sigset_t	sigmask;
+-	svr4_stack_t	stack;
+-	svr4_mcontext_t	mcontext;
+-	int		pad[23];
+-} svr4_ucontext_t;                          
+-
+-/* windows hold the windows as they were at signal time,
+- * ucontext->mcontext holds a pointer to them.
+- * addresses for uc and si are passed as parameters to svr4 signal
+- * handler
+- */
+-
+-/* This is the signal frame that is passed to the signal handler */
+-typedef struct {
+-	svr4_gwindows_t gw;	/* windows */
+-	svr4_ucontext_t uc;	/* machine context */
+-	svr4_siginfo_t  si;	/* siginfo */
+-} svr4_signal_frame_t;
+-
+-#define SVR4_SF_ALIGNED (((sizeof (svr4_signal_frame_t) + 7) & (~7)))
+-
+-#endif /* include control */
+diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
+index ef52721..cacbea1 100644
+--- a/include/asm-sparc64/termios.h
++++ b/include/asm-sparc64/termios.h
+@@ -33,11 +33,6 @@ struct ltchars {
+ };
+ #endif /* __KERNEL__ */
+ 
+-struct sunos_ttysize {
+-	int st_lines;   /* Lines on the terminal */
+-	int st_columns; /* Columns on the terminal */
+-};
+-
+ struct winsize {
+ 	unsigned short ws_row;
+ 	unsigned short ws_col;
+diff --git a/include/asm-sparc64/topology.h b/include/asm-sparc64/topology.h
+index c6b5570..001c040 100644
+--- a/include/asm-sparc64/topology.h
++++ b/include/asm-sparc64/topology.h
+@@ -1,6 +1,77 @@
+ #ifndef _ASM_SPARC64_TOPOLOGY_H
+ #define _ASM_SPARC64_TOPOLOGY_H
+ 
++#ifdef CONFIG_NUMA
++
++#include <asm/mmzone.h>
++
++static inline int cpu_to_node(int cpu)
++{
++	return numa_cpu_lookup_table[cpu];
++}
++
++#define parent_node(node)	(node)
++
++static inline cpumask_t node_to_cpumask(int node)
++{
++	return numa_cpumask_lookup_table[node];
++}
++
++/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
++#define node_to_cpumask_ptr(v, node)		\
++		cpumask_t *v = &(numa_cpumask_lookup_table[node])
++
++#define node_to_cpumask_ptr_next(v, node)	\
++			   v = &(numa_cpumask_lookup_table[node])
++
++static inline int node_to_first_cpu(int node)
++{
++	cpumask_t tmp;
++	tmp = node_to_cpumask(node);
++	return first_cpu(tmp);
++}
++
++struct pci_bus;
++#ifdef CONFIG_PCI
++extern int pcibus_to_node(struct pci_bus *pbus);
++#else
++static inline int pcibus_to_node(struct pci_bus *pbus)
++{
++	return -1;
++}
++#endif
++
++#define pcibus_to_cpumask(bus)	\
++	(pcibus_to_node(bus) == -1 ? \
++	 CPU_MASK_ALL : \
++	 node_to_cpumask(pcibus_to_node(bus)))
++
++#define SD_NODE_INIT (struct sched_domain) {		\
++	.min_interval		= 8,			\
++	.max_interval		= 32,			\
++	.busy_factor		= 32,			\
++	.imbalance_pct		= 125,			\
++	.cache_nice_tries	= 2,			\
++	.busy_idx		= 3,			\
++	.idle_idx		= 2,			\
++	.newidle_idx		= 0, 			\
++	.wake_idx		= 1,			\
++	.forkexec_idx		= 1,			\
++	.flags			= SD_LOAD_BALANCE	\
++				| SD_BALANCE_FORK	\
++				| SD_BALANCE_EXEC	\
++				| SD_SERIALIZE		\
++				| SD_WAKE_BALANCE,	\
++	.last_balance		= jiffies,		\
++	.balance_interval	= 1,			\
++}
++
++#else /* CONFIG_NUMA */
++
++#include <asm-generic/topology.h>
++
++#endif /* !(CONFIG_NUMA) */
++
+ #ifdef CONFIG_SMP
+ #define topology_physical_package_id(cpu)	(cpu_data(cpu).proc_id)
+ #define topology_core_id(cpu)			(cpu_data(cpu).core_id)
+@@ -10,8 +81,6 @@
+ #define smt_capable()				(sparc64_multi_core)
+ #endif /* CONFIG_SMP */
+ 
+-#include <asm-generic/topology.h>
+-
+ #define cpu_coregroup_map(cpu)			(cpu_core_map[cpu])
+ 
+ #endif /* _ASM_SPARC64_TOPOLOGY_H */
+diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
+index bbb9c8f..d3cc4ef 100644
+--- a/include/asm-sparc64/ttable.h
++++ b/include/asm-sparc64/ttable.h
+@@ -28,7 +28,7 @@
+ 	call	routine;				\
+ 	 add	%sp, PTREGS_OFF, %o0;			\
+ 	ba,pt	%xcc, rtrap;				\
+-	 clr	%l6;					\
++	 nop;						\
+ 	nop;
+ 
+ #define TRAP_7INSNS(routine)				\
+@@ -38,7 +38,7 @@
+ 	call	routine;				\
+ 	 add	%sp, PTREGS_OFF, %o0;			\
+ 	ba,pt	%xcc, rtrap;				\
+-	 clr	%l6;
++	 nop;
+ 
+ #define TRAP_SAVEFPU(routine)				\
+ 	sethi	%hi(109f), %g7;				\
+@@ -47,7 +47,7 @@
+ 	call	routine;				\
+ 	 add	%sp, PTREGS_OFF, %o0;			\
+ 	ba,pt	%xcc, rtrap;				\
+-	 clr	%l6;					\
++	 nop;						\
+ 	nop;
+ 
+ #define TRAP_NOSAVE(routine)				\
+@@ -67,7 +67,7 @@
+ 	call	routine;				\
+ 	 add	%sp, PTREGS_OFF, %o0;			\
+ 	ba,pt	%xcc, rtrap;				\
+-	 clr	%l6;					\
++	 nop;						\
+ 	nop;
+ 	
+ #define TRAP_ARG(routine, arg)				\
+@@ -78,7 +78,7 @@
+ 	call	routine;				\
+ 	 mov	arg, %o1;				\
+ 	ba,pt	%xcc, rtrap;				\
+-	 clr	%l6;
++	 nop;
+ 	
+ #define TRAPTL1_ARG(routine, arg)			\
+ 	sethi	%hi(109f), %g7;				\
+@@ -88,7 +88,7 @@
+ 	call	routine;				\
+ 	 mov	arg, %o1;				\
+ 	ba,pt	%xcc, rtrap;				\
+-	 clr	%l6;
++	 nop;
+ 	
+ #define SYSCALL_TRAP(routine, systbl)			\
+ 	sethi	%hi(109f), %g7;				\
+@@ -99,14 +99,6 @@
+ 	 or	%l7, %lo(systbl), %l7;			\
+ 	nop; nop;
+ 	
+-#define INDIRECT_SOLARIS_SYSCALL(num)			\
+-	sethi	%hi(109f), %g7;				\
+-	ba,pt	%xcc, etrap;				\
+-109:	 or	%g7, %lo(109b), %g7;			\
+-	ba,pt	%xcc, tl0_solaris + 0xc;		\
+-	 mov	num, %g1;				\
+-	nop;nop;nop;
+-	
+ #define TRAP_UTRAP(handler,lvl)				\
+ 	mov	handler, %g3;				\
+ 	ba,pt	%xcc, utrap_trap;			\
+@@ -117,11 +109,6 @@
+ 	nop;						\
+ 	nop;
+ 
+-#ifdef CONFIG_SUNOS_EMUL
+-#define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sunos_sys_table)
+-#else
+-#define SUNOS_SYSCALL_TRAP TRAP(sunos_syscall)
+-#endif
+ #ifdef CONFIG_COMPAT
+ #define	LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sys_call_table32)
+ #else
+@@ -130,11 +117,6 @@
+ #define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64)
+ #define GETCC_TRAP TRAP(getcc)
+ #define SETCC_TRAP TRAP(setcc)
+-#ifdef CONFIG_SOLARIS_EMUL
+-#define SOLARIS_SYSCALL_TRAP TRAP(solaris_sparc_syscall)
+-#else
+-#define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall)
+-#endif
+ #define BREAKPOINT_TRAP TRAP(breakpoint_trap)
+ 
+ #ifdef CONFIG_TRACE_IRQFLAGS
+@@ -184,7 +166,7 @@
+ 	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1;			\
+ 	add	%l1, 4, %l2;						\
+ 	stx	%l1, [%sp + PTREGS_OFF + PT_V9_TPC];			\
+-	ba,pt	%xcc, rtrap_clr_l6;					\
++	ba,pt	%xcc, rtrap;						\
+ 	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
+ 	        
+ #ifdef CONFIG_KPROBES
+diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
+index 77559da..13be445 100644
+--- a/include/asm-sparc64/unistd.h
++++ b/include/asm-sparc64/unistd.h
+@@ -338,16 +338,6 @@
+ #define NR_SYSCALLS		317
+ 
+ #ifdef __KERNEL__
+-/* sysconf options, for SunOS compatibility */
+-#define   _SC_ARG_MAX             1
+-#define   _SC_CHILD_MAX           2
+-#define   _SC_CLK_TCK             3
+-#define   _SC_NGROUPS_MAX         4
+-#define   _SC_OPEN_MAX            5
+-#define   _SC_JOB_CONTROL         6
+-#define   _SC_SAVED_IDS           7
+-#define   _SC_VERSION             8
+-
+ #define __ARCH_WANT_IPC_PARSE_VERSION
+ #define __ARCH_WANT_OLD_READDIR
+ #define __ARCH_WANT_STAT64
+diff --git a/include/asm-sparc64/user.h b/include/asm-sparc64/user.h
+index 02b1389..29fc6e9 100644
+--- a/include/asm-sparc64/user.h
++++ b/include/asm-sparc64/user.h
+@@ -1,60 +1 @@
+-/* $Id: user.h,v 1.1 1996/12/26 14:22:44 davem Exp $
+- * asm-sparc64/user.h: Core file definitions for the Sparc.
+- *
+- * Keep in sync with reg.h.  Actually, we could get rid of this
+- * one, since we won't a.out core dump that much anyways - miguel.
+- * Copyright (C) 1995 (davem at caip.rutgers.edu)
+- */
+-#ifndef _SPARC64_USER_H
+-#define _SPARC64_USER_H
+-
+-#include <linux/a.out.h>
+-struct sunos_regs {
+-	unsigned int psr, pc, npc, y;
+-	unsigned int regs[15];
+-};
+-
+-struct sunos_fpqueue {
+-	unsigned int *addr;
+-	unsigned int inst;
+-};
+-
+-struct sunos_fp {
+-	union {
+-		unsigned int regs[32];
+-		double reg_dbls[16];
+-	} fregs;
+-	unsigned int fsr;
+-	unsigned int flags;
+-	unsigned int extra;
+-	unsigned int fpq_count;
+-	struct sunos_fpqueue fpq[16];
+-};
+-
+-struct sunos_fpu {
+-	struct sunos_fp fpstatus;
+-};
+-
+-/* The SunOS core file header layout. */
+-struct user {
+-	unsigned int magic;
+-	unsigned int len;
+-	struct sunos_regs regs;
+-	struct exec uexec;
+-	int           signal;
+-	size_t        u_tsize; /* all of these in bytes! */
+-	size_t        u_dsize;
+-	size_t        u_ssize;
+-	char          u_comm[17];
+-	struct sunos_fpu fpu;
+-	unsigned int  sigcode;   /* Special sigcontext subcode, if any */
+-};
+-
+-#define NBPG                   PAGE_SIZE /* XXX 4096 maybe? */
+-#define UPAGES                 1
+-#define HOST_TEXT_START_ADDR   (u.start_code)
+-#define HOST_DATA_START_ADDR   (u.start_data)
+-#define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
+-#define SUNOS_CORE_MAGIC       0x080456
+-
+-#endif /* !(_SPARC64_USER_H) */
++#include <asm-sparc/user.h>
+diff --git a/include/asm-um/semaphore.h b/include/asm-um/semaphore.h
+index ff13c34..d9b2034 100644
+--- a/include/asm-um/semaphore.h
++++ b/include/asm-um/semaphore.h
+@@ -1,6 +1 @@
+-#ifndef __UM_SEMAPHORE_H
+-#define __UM_SEMAPHORE_H
+-
+-#include "asm/arch/semaphore.h"
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h
+index 10ed0cc..d9b2034 100644
+--- a/include/asm-v850/semaphore.h
++++ b/include/asm-v850/semaphore.h
+@@ -1,84 +1 @@
+-#ifndef __V850_SEMAPHORE_H__
+-#define __V850_SEMAPHORE_H__
+-
+-#include <linux/linkage.h>
+-#include <linux/spinlock.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/atomic.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name,count)				      \
+-	{ ATOMIC_INIT (count), 0,					      \
+-	  __WAIT_QUEUE_HEAD_INITIALIZER ((name).wait) }
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count)	\
+-	struct semaphore name = __SEMAPHORE_INITIALIZER (name,count)
+-
+-#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC (name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init (sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init (sem, 0);
+-}
+-
+-/*
+- * special register calling convention
+- */
+-asmlinkage void __down_failed (void);
+-asmlinkage int  __down_interruptible_failed (void);
+-asmlinkage int  __down_trylock_failed (void);
+-asmlinkage void __up_wakeup (void);
+-
+-extern void __down (struct semaphore * sem);
+-extern int  __down_interruptible (struct semaphore * sem);
+-extern int  __down_trylock (struct semaphore * sem);
+-extern void __up (struct semaphore * sem);
+-
+-static inline void down (struct semaphore * sem)
+-{
+-	might_sleep();
+-	if (atomic_dec_return (&sem->count) < 0)
+-		__down (sem);
+-}
+-
+-static inline int down_interruptible (struct semaphore * sem)
+-{
+-	int ret = 0;
+-	might_sleep();
+-	if (atomic_dec_return (&sem->count) < 0)
+-		ret = __down_interruptible (sem);
+-	return ret;
+-}
+-
+-static inline int down_trylock (struct semaphore *sem)
+-{
+-	int ret = 0;
+-	if (atomic_dec_return (&sem->count) < 0)
+-		ret = __down_trylock (sem);
+-	return ret;
+-}
+-
+-static inline void up (struct semaphore * sem)
+-{
+-	if (atomic_inc_return (&sem->count) <= 0)
+-		__up (sem);
+-}
+-
+-#endif /* __V850_SEMAPHORE_H__ */
++#include <linux/semaphore.h>
+diff --git a/include/asm-x86/Kbuild b/include/asm-x86/Kbuild
+index 3b8160a..1e35545 100644
+--- a/include/asm-x86/Kbuild
++++ b/include/asm-x86/Kbuild
+@@ -10,6 +10,7 @@ header-y += prctl.h
+ header-y += ptrace-abi.h
+ header-y += sigcontext32.h
+ header-y += ucontext.h
++header-y += processor-flags.h
+ 
+ unifdef-y += e820.h
+ unifdef-y += ist.h
+diff --git a/include/asm-x86/a.out-core.h b/include/asm-x86/a.out-core.h
+index d2b6e11..714207a 100644
+--- a/include/asm-x86/a.out-core.h
++++ b/include/asm-x86/a.out-core.h
+@@ -29,8 +29,9 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+ 	dump->magic = CMAGIC;
+ 	dump->start_code = 0;
+ 	dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
+-	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+-	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
++	dump->u_tsize = ((unsigned long)current->mm->end_code) >> PAGE_SHIFT;
++	dump->u_dsize = ((unsigned long)(current->mm->brk + (PAGE_SIZE - 1)))
++			>> PAGE_SHIFT;
+ 	dump->u_dsize -= dump->u_tsize;
+ 	dump->u_ssize = 0;
+ 	dump->u_debugreg[0] = current->thread.debugreg0;
+@@ -43,7 +44,8 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+ 	dump->u_debugreg[7] = current->thread.debugreg7;
+ 
+ 	if (dump->start_stack < TASK_SIZE)
+-		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
++		dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack))
++				>> PAGE_SHIFT;
+ 
+ 	dump->regs.bx = regs->bx;
+ 	dump->regs.cx = regs->cx;
+@@ -55,7 +57,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+ 	dump->regs.ds = (u16)regs->ds;
+ 	dump->regs.es = (u16)regs->es;
+ 	dump->regs.fs = (u16)regs->fs;
+-	savesegment(gs,gs);
++	savesegment(gs, gs);
+ 	dump->regs.orig_ax = regs->orig_ax;
+ 	dump->regs.ip = regs->ip;
+ 	dump->regs.cs = (u16)regs->cs;
+@@ -63,7 +65,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+ 	dump->regs.sp = regs->sp;
+ 	dump->regs.ss = (u16)regs->ss;
+ 
+-	dump->u_fpvalid = dump_fpu (regs, &dump->i387);
++	dump->u_fpvalid = dump_fpu(regs, &dump->i387);
+ }
+ 
+ #endif /* CONFIG_X86_32 */
+diff --git a/include/asm-x86/acpi.h b/include/asm-x86/acpi.h
+index 7a72d6a..14411c9 100644
+--- a/include/asm-x86/acpi.h
++++ b/include/asm-x86/acpi.h
+@@ -67,16 +67,16 @@ int __acpi_release_global_lock(unsigned int *lock);
+  */
+ #define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \
+ 	asm("divl %2;"				     \
+-	    :"=a"(q32), "=d"(r32)		     \
+-	    :"r"(d32),				     \
++	    : "=a"(q32), "=d"(r32)		     \
++	    : "r"(d32),				     \
+ 	     "0"(n_lo), "1"(n_hi))
+ 
+ 
+ #define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \
+ 	asm("shrl   $1,%2	;"	\
+ 	    "rcrl   $1,%3;"		\
+-	    :"=r"(n_hi), "=r"(n_lo)	\
+-	    :"0"(n_hi), "1"(n_lo))
++	    : "=r"(n_hi), "=r"(n_lo)	\
++	    : "0"(n_hi), "1"(n_lo))
+ 
+ #ifdef CONFIG_ACPI
+ extern int acpi_lapic;
+diff --git a/include/asm-x86/alternative.h b/include/asm-x86/alternative.h
+index d8bacf3..1f6a9ca 100644
+--- a/include/asm-x86/alternative.h
++++ b/include/asm-x86/alternative.h
+@@ -66,8 +66,8 @@ extern void alternatives_smp_module_del(struct module *mod);
+ extern void alternatives_smp_switch(int smp);
+ #else
+ static inline void alternatives_smp_module_add(struct module *mod, char *name,
+-					void *locks, void *locks_end,
+-					void *text, void *text_end) {}
++					       void *locks, void *locks_end,
++					       void *text, void *text_end) {}
+ static inline void alternatives_smp_module_del(struct module *mod) {}
+ static inline void alternatives_smp_switch(int smp) {}
+ #endif	/* CONFIG_SMP */
+@@ -148,14 +148,34 @@ struct paravirt_patch_site;
+ void apply_paravirt(struct paravirt_patch_site *start,
+ 		    struct paravirt_patch_site *end);
+ #else
+-static inline void
+-apply_paravirt(struct paravirt_patch_site *start,
+-	       struct paravirt_patch_site *end)
++static inline void apply_paravirt(struct paravirt_patch_site *start,
++				  struct paravirt_patch_site *end)
+ {}
+ #define __parainstructions	NULL
+ #define __parainstructions_end	NULL
+ #endif
+ 
+-extern void text_poke(void *addr, unsigned char *opcode, int len);
++extern void add_nops(void *insns, unsigned int len);
++
++/*
++ * Clear and restore the kernel write-protection flag on the local CPU.
++ * Allows the kernel to edit read-only pages.
++ * Side-effect: any interrupt handler running between save and restore will have
++ * the ability to write to read-only pages.
++ *
++ * Warning:
++ * Code patching in the UP case is safe if NMIs and MCE handlers are stopped and
++ * no thread can be preempted in the instructions being modified (no iret to an
++ * invalid instruction possible) or if the instructions are changed from a
++ * consistent state to another consistent state atomically.
++ * More care must be taken when modifying code in the SMP case because of
++ * Intel's errata.
++ * On the local CPU you need to be protected again NMI or MCE handlers seeing an
++ * inconsistent instruction while you patch.
++ * The _early version expects the memory to already be RW.
++ */
++
++extern void *text_poke(void *addr, const void *opcode, size_t len);
++extern void *text_poke_early(void *addr, const void *opcode, size_t len);
+ 
+ #endif /* _ASM_X86_ALTERNATIVE_H */
+diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h
+index bcfc07f..be9639a 100644
+--- a/include/asm-x86/apic.h
++++ b/include/asm-x86/apic.h
+@@ -44,7 +44,6 @@ extern int apic_runs_main_timer;
+ extern int ioapic_force;
+ extern int disable_apic;
+ extern int disable_apic_timer;
+-extern unsigned boot_cpu_id;
+ 
+ /*
+  * Basic functions accessing APICs.
+@@ -59,6 +58,8 @@ extern unsigned boot_cpu_id;
+ #define setup_secondary_clock setup_secondary_APIC_clock
+ #endif
+ 
++extern int is_vsmp_box(void);
++
+ static inline void native_apic_write(unsigned long reg, u32 v)
+ {
+ 	*((volatile u32 *)(APIC_BASE + reg)) = v;
+@@ -66,7 +67,7 @@ static inline void native_apic_write(unsigned long reg, u32 v)
+ 
+ static inline void native_apic_write_atomic(unsigned long reg, u32 v)
+ {
+-	(void) xchg((u32*)(APIC_BASE + reg), v);
++	(void)xchg((u32 *)(APIC_BASE + reg), v);
+ }
+ 
+ static inline u32 native_apic_read(unsigned long reg)
+@@ -123,7 +124,7 @@ extern void enable_NMI_through_LVT0(void);
+  * On 32bit this is mach-xxx local
+  */
+ #ifdef CONFIG_X86_64
+-extern void setup_apic_routing(void);
++extern void early_init_lapic_mapping(void);
+ #endif
+ 
+ extern u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask);
+diff --git a/include/asm-x86/apicdef.h b/include/asm-x86/apicdef.h
+index 550af7a..6b9008c 100644
+--- a/include/asm-x86/apicdef.h
++++ b/include/asm-x86/apicdef.h
+@@ -12,17 +12,15 @@
+ 
+ #define	APIC_ID		0x20
+ 
+-#ifdef CONFIG_X86_64
+-# define	APIC_ID_MASK		(0xFFu<<24)
+-# define	GET_APIC_ID(x)		(((x)>>24)&0xFFu)
+-# define	SET_APIC_ID(x)		(((x)<<24))
+-#endif
+-
+ #define	APIC_LVR	0x30
+ #define		APIC_LVR_MASK		0xFF00FF
+-#define		GET_APIC_VERSION(x)	((x)&0xFFu)
+-#define		GET_APIC_MAXLVT(x)	(((x)>>16)&0xFFu)
+-#define		APIC_INTEGRATED(x)	((x)&0xF0u)
++#define		GET_APIC_VERSION(x)	((x) & 0xFFu)
++#define		GET_APIC_MAXLVT(x)	(((x) >> 16) & 0xFFu)
++#ifdef CONFIG_X86_32
++#  define	APIC_INTEGRATED(x)	((x) & 0xF0u)
++#else
++#  define	APIC_INTEGRATED(x)	(1)
++#endif
+ #define		APIC_XAPIC(x)		((x) >= 0x14)
+ #define	APIC_TASKPRI	0x80
+ #define		APIC_TPRI_MASK		0xFFu
+@@ -33,16 +31,16 @@
+ #define		APIC_EIO_ACK		0x0
+ #define	APIC_RRR	0xC0
+ #define	APIC_LDR	0xD0
+-#define		APIC_LDR_MASK		(0xFFu<<24)
+-#define		GET_APIC_LOGICAL_ID(x)	(((x)>>24)&0xFFu)
+-#define		SET_APIC_LOGICAL_ID(x)	(((x)<<24))
++#define		APIC_LDR_MASK		(0xFFu << 24)
++#define		GET_APIC_LOGICAL_ID(x)	(((x) >> 24) & 0xFFu)
++#define		SET_APIC_LOGICAL_ID(x)	(((x) << 24))
+ #define		APIC_ALL_CPUS		0xFFu
+ #define	APIC_DFR	0xE0
+ #define		APIC_DFR_CLUSTER		0x0FFFFFFFul
+ #define		APIC_DFR_FLAT			0xFFFFFFFFul
+ #define	APIC_SPIV	0xF0
+-#define		APIC_SPIV_FOCUS_DISABLED	(1<<9)
+-#define		APIC_SPIV_APIC_ENABLED		(1<<8)
++#define		APIC_SPIV_FOCUS_DISABLED	(1 << 9)
++#define		APIC_SPIV_APIC_ENABLED		(1 << 8)
+ #define	APIC_ISR	0x100
+ #define	APIC_ISR_NR     0x8     /* Number of 32 bit ISR registers. */
+ #define	APIC_TMR	0x180
+@@ -78,27 +76,27 @@
+ #define		APIC_DM_EXTINT		0x00700
+ #define		APIC_VECTOR_MASK	0x000FF
+ #define	APIC_ICR2	0x310
+-#define		GET_APIC_DEST_FIELD(x)	(((x)>>24)&0xFF)
+-#define		SET_APIC_DEST_FIELD(x)	((x)<<24)
++#define		GET_APIC_DEST_FIELD(x)	(((x) >> 24) & 0xFF)
++#define		SET_APIC_DEST_FIELD(x)	((x) << 24)
+ #define	APIC_LVTT	0x320
+ #define	APIC_LVTTHMR	0x330
+ #define	APIC_LVTPC	0x340
+ #define	APIC_LVT0	0x350
+-#define		APIC_LVT_TIMER_BASE_MASK	(0x3<<18)
+-#define		GET_APIC_TIMER_BASE(x)		(((x)>>18)&0x3)
+-#define		SET_APIC_TIMER_BASE(x)		(((x)<<18))
++#define		APIC_LVT_TIMER_BASE_MASK	(0x3 << 18)
++#define		GET_APIC_TIMER_BASE(x)		(((x) >> 18) & 0x3)
++#define		SET_APIC_TIMER_BASE(x)		(((x) << 18))
+ #define		APIC_TIMER_BASE_CLKIN		0x0
+ #define		APIC_TIMER_BASE_TMBASE		0x1
+ #define		APIC_TIMER_BASE_DIV		0x2
+-#define		APIC_LVT_TIMER_PERIODIC		(1<<17)
+-#define		APIC_LVT_MASKED			(1<<16)
+-#define		APIC_LVT_LEVEL_TRIGGER		(1<<15)
+-#define		APIC_LVT_REMOTE_IRR		(1<<14)
+-#define		APIC_INPUT_POLARITY		(1<<13)
+-#define		APIC_SEND_PENDING		(1<<12)
++#define		APIC_LVT_TIMER_PERIODIC		(1 << 17)
++#define		APIC_LVT_MASKED			(1 << 16)
++#define		APIC_LVT_LEVEL_TRIGGER		(1 << 15)
++#define		APIC_LVT_REMOTE_IRR		(1 << 14)
++#define		APIC_INPUT_POLARITY		(1 << 13)
++#define		APIC_SEND_PENDING		(1 << 12)
+ #define		APIC_MODE_MASK			0x700
+-#define		GET_APIC_DELIVERY_MODE(x)	(((x)>>8)&0x7)
+-#define		SET_APIC_DELIVERY_MODE(x, y)	(((x)&~0x700)|((y)<<8))
++#define		GET_APIC_DELIVERY_MODE(x)	(((x) >> 8) & 0x7)
++#define		SET_APIC_DELIVERY_MODE(x, y)	(((x) & ~0x700) | ((y) << 8))
+ #define			APIC_MODE_FIXED		0x0
+ #define			APIC_MODE_NMI		0x4
+ #define			APIC_MODE_EXTINT	0x7
+@@ -107,7 +105,7 @@
+ #define	APIC_TMICT	0x380
+ #define	APIC_TMCCT	0x390
+ #define	APIC_TDCR	0x3E0
+-#define		APIC_TDR_DIV_TMBASE	(1<<2)
++#define		APIC_TDR_DIV_TMBASE	(1 << 2)
+ #define		APIC_TDR_DIV_1		0xB
+ #define		APIC_TDR_DIV_2		0x0
+ #define		APIC_TDR_DIV_4		0x1
+@@ -117,14 +115,14 @@
+ #define		APIC_TDR_DIV_64		0x9
+ #define		APIC_TDR_DIV_128	0xA
+ #define	APIC_EILVT0     0x500
+-#define		APIC_EILVT_NR_AMD_K8	1	/* Number of extended interrupts */
++#define		APIC_EILVT_NR_AMD_K8	1	/* # of extended interrupts */
+ #define		APIC_EILVT_NR_AMD_10H	4
+-#define		APIC_EILVT_LVTOFF(x)	(((x)>>4)&0xF)
++#define		APIC_EILVT_LVTOFF(x)	(((x) >> 4) & 0xF)
+ #define		APIC_EILVT_MSG_FIX	0x0
+ #define		APIC_EILVT_MSG_SMI	0x2
+ #define		APIC_EILVT_MSG_NMI	0x4
+ #define		APIC_EILVT_MSG_EXT	0x7
+-#define		APIC_EILVT_MASKED	(1<<16)
++#define		APIC_EILVT_MASKED	(1 << 16)
+ #define	APIC_EILVT1     0x510
+ #define	APIC_EILVT2     0x520
+ #define	APIC_EILVT3     0x530
+@@ -135,7 +133,7 @@
+ # define MAX_IO_APICS 64
+ #else
+ # define MAX_IO_APICS 128
+-# define MAX_LOCAL_APIC 256
++# define MAX_LOCAL_APIC 32768
+ #endif
+ 
+ /*
+@@ -408,6 +406,9 @@ struct local_apic {
+ 
+ #undef u32
+ 
+-#define BAD_APICID 0xFFu
+-
++#ifdef CONFIG_X86_32
++ #define BAD_APICID 0xFFu
++#else
++ #define BAD_APICID 0xFFFFu
++#endif
+ #endif
+diff --git a/include/asm-x86/atomic_32.h b/include/asm-x86/atomic_32.h
+index 437aac8..21a4825 100644
+--- a/include/asm-x86/atomic_32.h
++++ b/include/asm-x86/atomic_32.h
+@@ -15,138 +15,133 @@
+  * on us. We need to use _exactly_ the address the user gave us,
+  * not some alias that contains the same information.
+  */
+-typedef struct { int counter; } atomic_t;
++typedef struct {
++	int counter;
++} atomic_t;
+ 
+ #define ATOMIC_INIT(i)	{ (i) }
+ 
+ /**
+  * atomic_read - read atomic variable
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically reads the value of @v.
+- */ 
++ */
+ #define atomic_read(v)		((v)->counter)
+ 
+ /**
+  * atomic_set - set atomic variable
+  * @v: pointer of type atomic_t
+  * @i: required value
+- * 
++ *
+  * Atomically sets the value of @v to @i.
+- */ 
+-#define atomic_set(v,i)		(((v)->counter) = (i))
++ */
++#define atomic_set(v, i)	(((v)->counter) = (i))
+ 
+ /**
+  * atomic_add - add integer to atomic variable
+  * @i: integer value to add
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically adds @i to @v.
+  */
+-static __inline__ void atomic_add(int i, atomic_t *v)
++static inline void atomic_add(int i, atomic_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "addl %1,%0"
+-		:"+m" (v->counter)
+-		:"ir" (i));
++	asm volatile(LOCK_PREFIX "addl %1,%0"
++		     : "+m" (v->counter)
++		     : "ir" (i));
+ }
+ 
+ /**
+  * atomic_sub - subtract integer from atomic variable
+  * @i: integer value to subtract
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically subtracts @i from @v.
+  */
+-static __inline__ void atomic_sub(int i, atomic_t *v)
++static inline void atomic_sub(int i, atomic_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "subl %1,%0"
+-		:"+m" (v->counter)
+-		:"ir" (i));
++	asm volatile(LOCK_PREFIX "subl %1,%0"
++		     : "+m" (v->counter)
++		     : "ir" (i));
+ }
+ 
+ /**
+  * atomic_sub_and_test - subtract value from variable and test result
+  * @i: integer value to subtract
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically subtracts @i from @v and returns
+  * true if the result is zero, or false for all
+  * other cases.
+  */
+-static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
++static inline int atomic_sub_and_test(int i, atomic_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "subl %2,%0; sete %1"
+-		:"+m" (v->counter), "=qm" (c)
+-		:"ir" (i) : "memory");
++	asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
++		     : "+m" (v->counter), "=qm" (c)
++		     : "ir" (i) : "memory");
+ 	return c;
+ }
+ 
+ /**
+  * atomic_inc - increment atomic variable
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically increments @v by 1.
+- */ 
+-static __inline__ void atomic_inc(atomic_t *v)
++ */
++static inline void atomic_inc(atomic_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "incl %0"
+-		:"+m" (v->counter));
++	asm volatile(LOCK_PREFIX "incl %0"
++		     : "+m" (v->counter));
+ }
+ 
+ /**
+  * atomic_dec - decrement atomic variable
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically decrements @v by 1.
+- */ 
+-static __inline__ void atomic_dec(atomic_t *v)
++ */
++static inline void atomic_dec(atomic_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "decl %0"
+-		:"+m" (v->counter));
++	asm volatile(LOCK_PREFIX "decl %0"
++		     : "+m" (v->counter));
+ }
+ 
+ /**
+  * atomic_dec_and_test - decrement and test
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically decrements @v by 1 and
+  * returns true if the result is 0, or false for all other
+  * cases.
+- */ 
+-static __inline__ int atomic_dec_and_test(atomic_t *v)
++ */
++static inline int atomic_dec_and_test(atomic_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "decl %0; sete %1"
+-		:"+m" (v->counter), "=qm" (c)
+-		: : "memory");
++	asm volatile(LOCK_PREFIX "decl %0; sete %1"
++		     : "+m" (v->counter), "=qm" (c)
++		     : : "memory");
+ 	return c != 0;
+ }
+ 
+ /**
+- * atomic_inc_and_test - increment and test 
++ * 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(atomic_t *v)
++ */
++static inline int atomic_inc_and_test(atomic_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "incl %0; sete %1"
+-		:"+m" (v->counter), "=qm" (c)
+-		: : "memory");
++	asm volatile(LOCK_PREFIX "incl %0; sete %1"
++		     : "+m" (v->counter), "=qm" (c)
++		     : : "memory");
+ 	return c != 0;
+ }
+ 
+@@ -154,19 +149,18 @@ static __inline__ int atomic_inc_and_test(atomic_t *v)
+  * atomic_add_negative - add and test if negative
+  * @v: pointer of type atomic_t
+  * @i: integer value to add
+- * 
++ *
+  * Atomically adds @i to @v and returns true
+  * if the result is negative, or false when
+  * result is greater than or equal to zero.
+- */ 
+-static __inline__ int atomic_add_negative(int i, atomic_t *v)
++ */
++static inline int atomic_add_negative(int i, atomic_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "addl %2,%0; sets %1"
+-		:"+m" (v->counter), "=qm" (c)
+-		:"ir" (i) : "memory");
++	asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
++		     : "+m" (v->counter), "=qm" (c)
++		     : "ir" (i) : "memory");
+ 	return c;
+ }
+ 
+@@ -177,20 +171,19 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v)
+  *
+  * Atomically adds @i to @v and returns @i + @v
+  */
+-static __inline__ int atomic_add_return(int i, atomic_t *v)
++static inline int atomic_add_return(int i, atomic_t *v)
+ {
+ 	int __i;
+ #ifdef CONFIG_M386
+ 	unsigned long flags;
+-	if(unlikely(boot_cpu_data.x86 <= 3))
++	if (unlikely(boot_cpu_data.x86 <= 3))
+ 		goto no_xadd;
+ #endif
+ 	/* Modern 486+ processor */
+ 	__i = i;
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "xaddl %0, %1"
+-		:"+r" (i), "+m" (v->counter)
+-		: : "memory");
++	asm volatile(LOCK_PREFIX "xaddl %0, %1"
++		     : "+r" (i), "+m" (v->counter)
++		     : : "memory");
+ 	return i + __i;
+ 
+ #ifdef CONFIG_M386
+@@ -210,9 +203,9 @@ no_xadd: /* Legacy 386 processor */
+  *
+  * Atomically subtracts @i from @v and returns @v - @i
+  */
+-static __inline__ int atomic_sub_return(int i, atomic_t *v)
++static inline int atomic_sub_return(int i, atomic_t *v)
+ {
+-	return atomic_add_return(-i,v);
++	return atomic_add_return(-i, v);
+ }
+ 
+ #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
+@@ -227,7 +220,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v)
+  * Atomically adds @a to @v, so long as @v was not already @u.
+  * Returns non-zero if @v was not @u, and zero otherwise.
+  */
+-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
++static inline int atomic_add_unless(atomic_t *v, int a, int u)
+ {
+ 	int c, old;
+ 	c = atomic_read(v);
+@@ -244,17 +237,17 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+ 
+ #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+ 
+-#define atomic_inc_return(v)  (atomic_add_return(1,v))
+-#define atomic_dec_return(v)  (atomic_sub_return(1,v))
++#define atomic_inc_return(v)  (atomic_add_return(1, v))
++#define atomic_dec_return(v)  (atomic_sub_return(1, v))
+ 
+ /* These are x86-specific, used by some header files */
+-#define atomic_clear_mask(mask, addr) \
+-__asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \
+-: : "r" (~(mask)),"m" (*addr) : "memory")
++#define atomic_clear_mask(mask, addr)				\
++	asm volatile(LOCK_PREFIX "andl %0,%1"			\
++		     : : "r" (~(mask)), "m" (*(addr)) : "memory")
+ 
+-#define atomic_set_mask(mask, addr) \
+-__asm__ __volatile__(LOCK_PREFIX "orl %0,%1" \
+-: : "r" (mask),"m" (*(addr)) : "memory")
++#define atomic_set_mask(mask, addr)				\
++	asm volatile(LOCK_PREFIX "orl %0,%1"				\
++		     : : "r" (mask), "m" (*(addr)) : "memory")
+ 
+ /* Atomic operations are already serializing on x86 */
+ #define smp_mb__before_atomic_dec()	barrier()
+diff --git a/include/asm-x86/atomic_64.h b/include/asm-x86/atomic_64.h
+index 2d20a7a..3e0cd7d 100644
+--- a/include/asm-x86/atomic_64.h
++++ b/include/asm-x86/atomic_64.h
+@@ -22,140 +22,135 @@
+  * on us. We need to use _exactly_ the address the user gave us,
+  * not some alias that contains the same information.
+  */
+-typedef struct { int counter; } atomic_t;
++typedef struct {
++	int counter;
++} atomic_t;
+ 
+ #define ATOMIC_INIT(i)	{ (i) }
+ 
+ /**
+  * atomic_read - read atomic variable
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically reads the value of @v.
+- */ 
++ */
+ #define atomic_read(v)		((v)->counter)
+ 
+ /**
+  * atomic_set - set atomic variable
+  * @v: pointer of type atomic_t
+  * @i: required value
+- * 
++ *
+  * Atomically sets the value of @v to @i.
+- */ 
+-#define atomic_set(v,i)		(((v)->counter) = (i))
++ */
++#define atomic_set(v, i)		(((v)->counter) = (i))
+ 
+ /**
+  * atomic_add - add integer to atomic variable
+  * @i: integer value to add
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically adds @i to @v.
+  */
+-static __inline__ void atomic_add(int i, atomic_t *v)
++static inline void atomic_add(int i, atomic_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "addl %1,%0"
+-		:"=m" (v->counter)
+-		:"ir" (i), "m" (v->counter));
++	asm volatile(LOCK_PREFIX "addl %1,%0"
++		     : "=m" (v->counter)
++		     : "ir" (i), "m" (v->counter));
+ }
+ 
+ /**
+  * atomic_sub - subtract the atomic variable
+  * @i: integer value to subtract
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically subtracts @i from @v.
+  */
+-static __inline__ void atomic_sub(int i, atomic_t *v)
++static inline void atomic_sub(int i, atomic_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "subl %1,%0"
+-		:"=m" (v->counter)
+-		:"ir" (i), "m" (v->counter));
++	asm volatile(LOCK_PREFIX "subl %1,%0"
++		     : "=m" (v->counter)
++		     : "ir" (i), "m" (v->counter));
+ }
+ 
+ /**
+  * atomic_sub_and_test - subtract value from variable and test result
+  * @i: integer value to subtract
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically subtracts @i from @v and returns
+  * true if the result is zero, or false for all
+  * other cases.
+  */
+-static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
++static inline int atomic_sub_and_test(int i, atomic_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "subl %2,%0; sete %1"
+-		:"=m" (v->counter), "=qm" (c)
+-		:"ir" (i), "m" (v->counter) : "memory");
++	asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
++		     : "=m" (v->counter), "=qm" (c)
++		     : "ir" (i), "m" (v->counter) : "memory");
+ 	return c;
+ }
+ 
+ /**
+  * atomic_inc - increment atomic variable
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically increments @v by 1.
+- */ 
+-static __inline__ void atomic_inc(atomic_t *v)
++ */
++static inline void atomic_inc(atomic_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "incl %0"
+-		:"=m" (v->counter)
+-		:"m" (v->counter));
++	asm volatile(LOCK_PREFIX "incl %0"
++		     : "=m" (v->counter)
++		     : "m" (v->counter));
+ }
+ 
+ /**
+  * atomic_dec - decrement atomic variable
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically decrements @v by 1.
+- */ 
+-static __inline__ void atomic_dec(atomic_t *v)
++ */
++static inline void atomic_dec(atomic_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "decl %0"
+-		:"=m" (v->counter)
+-		:"m" (v->counter));
++	asm volatile(LOCK_PREFIX "decl %0"
++		     : "=m" (v->counter)
++		     : "m" (v->counter));
+ }
+ 
+ /**
+  * atomic_dec_and_test - decrement and test
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically decrements @v by 1 and
+  * returns true if the result is 0, or false for all other
+  * cases.
+- */ 
+-static __inline__ int atomic_dec_and_test(atomic_t *v)
++ */
++static inline int atomic_dec_and_test(atomic_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "decl %0; sete %1"
+-		:"=m" (v->counter), "=qm" (c)
+-		:"m" (v->counter) : "memory");
++	asm volatile(LOCK_PREFIX "decl %0; sete %1"
++		     : "=m" (v->counter), "=qm" (c)
++		     : "m" (v->counter) : "memory");
+ 	return c != 0;
+ }
+ 
+ /**
+- * atomic_inc_and_test - increment and test 
++ * 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(atomic_t *v)
++ */
++static inline int atomic_inc_and_test(atomic_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "incl %0; sete %1"
+-		:"=m" (v->counter), "=qm" (c)
+-		:"m" (v->counter) : "memory");
++	asm volatile(LOCK_PREFIX "incl %0; sete %1"
++		     : "=m" (v->counter), "=qm" (c)
++		     : "m" (v->counter) : "memory");
+ 	return c != 0;
+ }
+ 
+@@ -163,19 +158,18 @@ static __inline__ int atomic_inc_and_test(atomic_t *v)
+  * atomic_add_negative - add and test if negative
+  * @i: integer value to add
+  * @v: pointer of type atomic_t
+- * 
++ *
+  * Atomically adds @i to @v and returns true
+  * if the result is negative, or false when
+  * result is greater than or equal to zero.
+- */ 
+-static __inline__ int atomic_add_negative(int i, atomic_t *v)
++ */
++static inline int atomic_add_negative(int i, atomic_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "addl %2,%0; sets %1"
+-		:"=m" (v->counter), "=qm" (c)
+-		:"ir" (i), "m" (v->counter) : "memory");
++	asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
++		     : "=m" (v->counter), "=qm" (c)
++		     : "ir" (i), "m" (v->counter) : "memory");
+ 	return c;
+ }
+ 
+@@ -186,27 +180,28 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v)
+  *
+  * Atomically adds @i to @v and returns @i + @v
+  */
+-static __inline__ int atomic_add_return(int i, atomic_t *v)
++static inline int atomic_add_return(int i, atomic_t *v)
+ {
+ 	int __i = i;
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "xaddl %0, %1"
+-		:"+r" (i), "+m" (v->counter)
+-		: : "memory");
++	asm volatile(LOCK_PREFIX "xaddl %0, %1"
++		     : "+r" (i), "+m" (v->counter)
++		     : : "memory");
+ 	return i + __i;
+ }
+ 
+-static __inline__ int atomic_sub_return(int i, atomic_t *v)
++static inline int atomic_sub_return(int i, atomic_t *v)
+ {
+-	return atomic_add_return(-i,v);
++	return atomic_add_return(-i, v);
+ }
+ 
+-#define atomic_inc_return(v)  (atomic_add_return(1,v))
+-#define atomic_dec_return(v)  (atomic_sub_return(1,v))
++#define atomic_inc_return(v)  (atomic_add_return(1, v))
++#define atomic_dec_return(v)  (atomic_sub_return(1, v))
+ 
+ /* An 64bit atomic type */
+ 
+-typedef struct { long counter; } atomic64_t;
++typedef struct {
++	long counter;
++} atomic64_t;
+ 
+ #define ATOMIC64_INIT(i)	{ (i) }
+ 
+@@ -226,7 +221,7 @@ typedef struct { long counter; } atomic64_t;
+  *
+  * Atomically sets the value of @v to @i.
+  */
+-#define atomic64_set(v,i)		(((v)->counter) = (i))
++#define atomic64_set(v, i)		(((v)->counter) = (i))
+ 
+ /**
+  * atomic64_add - add integer to atomic64 variable
+@@ -235,12 +230,11 @@ typedef struct { long counter; } atomic64_t;
+  *
+  * Atomically adds @i to @v.
+  */
+-static __inline__ void atomic64_add(long i, atomic64_t *v)
++static inline void atomic64_add(long i, atomic64_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "addq %1,%0"
+-		:"=m" (v->counter)
+-		:"ir" (i), "m" (v->counter));
++	asm volatile(LOCK_PREFIX "addq %1,%0"
++		     : "=m" (v->counter)
++		     : "ir" (i), "m" (v->counter));
+ }
+ 
+ /**
+@@ -250,12 +244,11 @@ static __inline__ void atomic64_add(long i, atomic64_t *v)
+  *
+  * Atomically subtracts @i from @v.
+  */
+-static __inline__ void atomic64_sub(long i, atomic64_t *v)
++static inline void atomic64_sub(long i, atomic64_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "subq %1,%0"
+-		:"=m" (v->counter)
+-		:"ir" (i), "m" (v->counter));
++	asm volatile(LOCK_PREFIX "subq %1,%0"
++		     : "=m" (v->counter)
++		     : "ir" (i), "m" (v->counter));
+ }
+ 
+ /**
+@@ -267,14 +260,13 @@ static __inline__ void atomic64_sub(long i, atomic64_t *v)
+  * true if the result is zero, or false for all
+  * other cases.
+  */
+-static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
++static inline int atomic64_sub_and_test(long i, atomic64_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "subq %2,%0; sete %1"
+-		:"=m" (v->counter), "=qm" (c)
+-		:"ir" (i), "m" (v->counter) : "memory");
++	asm volatile(LOCK_PREFIX "subq %2,%0; sete %1"
++		     : "=m" (v->counter), "=qm" (c)
++		     : "ir" (i), "m" (v->counter) : "memory");
+ 	return c;
+ }
+ 
+@@ -284,12 +276,11 @@ static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
+  *
+  * Atomically increments @v by 1.
+  */
+-static __inline__ void atomic64_inc(atomic64_t *v)
++static inline void atomic64_inc(atomic64_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "incq %0"
+-		:"=m" (v->counter)
+-		:"m" (v->counter));
++	asm volatile(LOCK_PREFIX "incq %0"
++		     : "=m" (v->counter)
++		     : "m" (v->counter));
+ }
+ 
+ /**
+@@ -298,12 +289,11 @@ static __inline__ void atomic64_inc(atomic64_t *v)
+  *
+  * Atomically decrements @v by 1.
+  */
+-static __inline__ void atomic64_dec(atomic64_t *v)
++static inline void atomic64_dec(atomic64_t *v)
+ {
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "decq %0"
+-		:"=m" (v->counter)
+-		:"m" (v->counter));
++	asm volatile(LOCK_PREFIX "decq %0"
++		     : "=m" (v->counter)
++		     : "m" (v->counter));
+ }
+ 
+ /**
+@@ -314,14 +304,13 @@ static __inline__ void atomic64_dec(atomic64_t *v)
+  * returns true if the result is 0, or false for all other
+  * cases.
+  */
+-static __inline__ int atomic64_dec_and_test(atomic64_t *v)
++static inline int atomic64_dec_and_test(atomic64_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "decq %0; sete %1"
+-		:"=m" (v->counter), "=qm" (c)
+-		:"m" (v->counter) : "memory");
++	asm volatile(LOCK_PREFIX "decq %0; sete %1"
++		     : "=m" (v->counter), "=qm" (c)
++		     : "m" (v->counter) : "memory");
+ 	return c != 0;
+ }
+ 
+@@ -333,14 +322,13 @@ static __inline__ int atomic64_dec_and_test(atomic64_t *v)
+  * and returns true if the result is zero, or false for all
+  * other cases.
+  */
+-static __inline__ int atomic64_inc_and_test(atomic64_t *v)
++static inline int atomic64_inc_and_test(atomic64_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "incq %0; sete %1"
+-		:"=m" (v->counter), "=qm" (c)
+-		:"m" (v->counter) : "memory");
++	asm volatile(LOCK_PREFIX "incq %0; sete %1"
++		     : "=m" (v->counter), "=qm" (c)
++		     : "m" (v->counter) : "memory");
+ 	return c != 0;
+ }
+ 
+@@ -353,14 +341,13 @@ static __inline__ int atomic64_inc_and_test(atomic64_t *v)
+  * if the result is negative, or false when
+  * result is greater than or equal to zero.
+  */
+-static __inline__ int atomic64_add_negative(long i, atomic64_t *v)
++static inline int atomic64_add_negative(long i, atomic64_t *v)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "addq %2,%0; sets %1"
+-		:"=m" (v->counter), "=qm" (c)
+-		:"ir" (i), "m" (v->counter) : "memory");
++	asm volatile(LOCK_PREFIX "addq %2,%0; sets %1"
++		     : "=m" (v->counter), "=qm" (c)
++		     : "ir" (i), "m" (v->counter) : "memory");
+ 	return c;
+ }
+ 
+@@ -371,29 +358,28 @@ static __inline__ int atomic64_add_negative(long i, atomic64_t *v)
+  *
+  * Atomically adds @i to @v and returns @i + @v
+  */
+-static __inline__ long atomic64_add_return(long i, atomic64_t *v)
++static inline long atomic64_add_return(long i, atomic64_t *v)
+ {
+ 	long __i = i;
+-	__asm__ __volatile__(
+-		LOCK_PREFIX "xaddq %0, %1;"
+-		:"+r" (i), "+m" (v->counter)
+-		: : "memory");
++	asm volatile(LOCK_PREFIX "xaddq %0, %1;"
++		     : "+r" (i), "+m" (v->counter)
++		     : : "memory");
+ 	return i + __i;
+ }
+ 
+-static __inline__ long atomic64_sub_return(long i, atomic64_t *v)
++static inline long atomic64_sub_return(long i, atomic64_t *v)
+ {
+-	return atomic64_add_return(-i,v);
++	return atomic64_add_return(-i, v);
+ }
+ 
+-#define atomic64_inc_return(v)  (atomic64_add_return(1,v))
+-#define atomic64_dec_return(v)  (atomic64_sub_return(1,v))
++#define atomic64_inc_return(v)  (atomic64_add_return(1, (v)))
++#define atomic64_dec_return(v)  (atomic64_sub_return(1, (v)))
+ 
+-#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
++#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
+ #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+ 
+-#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
+-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
++#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
++#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
+ 
+ /**
+  * atomic_add_unless - add unless the number is a given value
+@@ -404,7 +390,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t *v)
+  * Atomically adds @a to @v, so long as it was not @u.
+  * Returns non-zero if @v was not @u, and zero otherwise.
+  */
+-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
++static inline int atomic_add_unless(atomic_t *v, int a, int u)
+ {
+ 	int c, old;
+ 	c = atomic_read(v);
+@@ -430,7 +416,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+  * Atomically adds @a to @v, so long as it was not @u.
+  * Returns non-zero if @v was not @u, and zero otherwise.
+  */
+-static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
++static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
+ {
+ 	long c, old;
+ 	c = atomic64_read(v);
+@@ -448,13 +434,14 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+ #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+ 
+ /* These are x86-specific, used by some header files */
+-#define atomic_clear_mask(mask, addr) \
+-__asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \
+-: : "r" (~(mask)),"m" (*addr) : "memory")
+-
+-#define atomic_set_mask(mask, addr) \
+-__asm__ __volatile__(LOCK_PREFIX "orl %0,%1" \
+-: : "r" ((unsigned)mask),"m" (*(addr)) : "memory")
++#define atomic_clear_mask(mask, addr)					\
++	asm volatile(LOCK_PREFIX "andl %0,%1"				\
++		     : : "r" (~(mask)), "m" (*(addr)) : "memory")
++
++#define atomic_set_mask(mask, addr)					\
++	asm volatile(LOCK_PREFIX "orl %0,%1"				\
++		     : : "r" ((unsigned)(mask)), "m" (*(addr))		\
++		     : "memory")
+ 
+ /* Atomic operations are already serializing on x86 */
+ #define smp_mb__before_atomic_dec()	barrier()
+diff --git a/include/asm-x86/bios_ebda.h b/include/asm-x86/bios_ebda.h
+new file mode 100644
+index 0000000..b4a46b7
+--- /dev/null
++++ b/include/asm-x86/bios_ebda.h
+@@ -0,0 +1,17 @@
++#ifndef _MACH_BIOS_EBDA_H
++#define _MACH_BIOS_EBDA_H
++
++#include <asm/io.h>
++
++/*
++ * there is a real-mode segmented pointer pointing to the
++ * 4K EBDA area at 0x40E.
++ */
++static inline unsigned int get_bios_ebda(void)
++{
++	unsigned int address = *(unsigned short *)phys_to_virt(0x40E);
++	address <<= 4;
++	return address;	/* 0 means none */
++}
++
++#endif /* _MACH_BIOS_EBDA_H */
+diff --git a/include/asm-x86/bitops.h b/include/asm-x86/bitops.h
+index 1a23ce1..1ae7b27 100644
+--- a/include/asm-x86/bitops.h
++++ b/include/asm-x86/bitops.h
+@@ -23,10 +23,13 @@
+ #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
+ /* Technically wrong, but this avoids compilation errors on some gcc
+    versions. */
+-#define ADDR "=m" (*(volatile long *) addr)
++#define ADDR "=m" (*(volatile long *)addr)
++#define BIT_ADDR "=m" (((volatile int *)addr)[nr >> 5])
+ #else
+ #define ADDR "+m" (*(volatile long *) addr)
++#define BIT_ADDR "+m" (((volatile int *)addr)[nr >> 5])
+ #endif
++#define BASE_ADDR "m" (*(volatile int *)addr)
+ 
+ /**
+  * set_bit - Atomically set a bit in memory
+@@ -45,9 +48,7 @@
+  */
+ static inline void set_bit(int nr, volatile void *addr)
+ {
+-	asm volatile(LOCK_PREFIX "bts %1,%0"
+-		     : ADDR
+-		     : "Ir" (nr) : "memory");
++	asm volatile(LOCK_PREFIX "bts %1,%0" : ADDR : "Ir" (nr) : "memory");
+ }
+ 
+ /**
+@@ -79,9 +80,7 @@ static inline void __set_bit(int nr, volatile void *addr)
+  */
+ static inline void clear_bit(int nr, volatile void *addr)
+ {
+-	asm volatile(LOCK_PREFIX "btr %1,%0"
+-		     : ADDR
+-		     : "Ir" (nr));
++	asm volatile(LOCK_PREFIX "btr %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ }
+ 
+ /*
+@@ -100,7 +99,7 @@ static inline void clear_bit_unlock(unsigned nr, volatile void *addr)
+ 
+ static inline void __clear_bit(int nr, volatile void *addr)
+ {
+-	asm volatile("btr %1,%0" : ADDR : "Ir" (nr));
++	asm volatile("btr %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ }
+ 
+ /*
+@@ -135,7 +134,7 @@ static inline void __clear_bit_unlock(unsigned nr, volatile void *addr)
+  */
+ static inline void __change_bit(int nr, volatile void *addr)
+ {
+-	asm volatile("btc %1,%0" : ADDR : "Ir" (nr));
++	asm volatile("btc %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ }
+ 
+ /**
+@@ -149,8 +148,7 @@ static inline void __change_bit(int nr, volatile void *addr)
+  */
+ static inline void change_bit(int nr, volatile void *addr)
+ {
+-	asm volatile(LOCK_PREFIX "btc %1,%0"
+-		     : ADDR : "Ir" (nr));
++	asm volatile(LOCK_PREFIX "btc %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ }
+ 
+ /**
+@@ -166,9 +164,7 @@ static inline int test_and_set_bit(int nr, volatile void *addr)
+ 	int oldbit;
+ 
+ 	asm volatile(LOCK_PREFIX "bts %2,%1\n\t"
+-		     "sbb %0,%0"
+-		     : "=r" (oldbit), ADDR
+-		     : "Ir" (nr) : "memory");
++		     "sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
+ 
+ 	return oldbit;
+ }
+@@ -198,10 +194,9 @@ static inline int __test_and_set_bit(int nr, volatile void *addr)
+ {
+ 	int oldbit;
+ 
+-	asm("bts %2,%1\n\t"
+-	    "sbb %0,%0"
+-	    : "=r" (oldbit), ADDR
+-	    : "Ir" (nr));
++	asm volatile("bts %2,%3\n\t"
++		     "sbb %0,%0"
++		     : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ 	return oldbit;
+ }
+ 
+@@ -219,8 +214,7 @@ static inline int test_and_clear_bit(int nr, volatile void *addr)
+ 
+ 	asm volatile(LOCK_PREFIX "btr %2,%1\n\t"
+ 		     "sbb %0,%0"
+-		     : "=r" (oldbit), ADDR
+-		     : "Ir" (nr) : "memory");
++		     : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
+ 
+ 	return oldbit;
+ }
+@@ -238,10 +232,9 @@ static inline int __test_and_clear_bit(int nr, volatile void *addr)
+ {
+ 	int oldbit;
+ 
+-	asm volatile("btr %2,%1\n\t"
++	asm volatile("btr %2,%3\n\t"
+ 		     "sbb %0,%0"
+-		     : "=r" (oldbit), ADDR
+-		     : "Ir" (nr));
++		     : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ 	return oldbit;
+ }
+ 
+@@ -250,10 +243,9 @@ static inline int __test_and_change_bit(int nr, volatile void *addr)
+ {
+ 	int oldbit;
+ 
+-	asm volatile("btc %2,%1\n\t"
++	asm volatile("btc %2,%3\n\t"
+ 		     "sbb %0,%0"
+-		     : "=r" (oldbit), ADDR
+-		     : "Ir" (nr) : "memory");
++		     : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ 
+ 	return oldbit;
+ }
+@@ -272,8 +264,7 @@ static inline int test_and_change_bit(int nr, volatile void *addr)
+ 
+ 	asm volatile(LOCK_PREFIX "btc %2,%1\n\t"
+ 		     "sbb %0,%0"
+-		     : "=r" (oldbit), ADDR
+-		     : "Ir" (nr) : "memory");
++		     : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
+ 
+ 	return oldbit;
+ }
+@@ -288,10 +279,11 @@ static inline int variable_test_bit(int nr, volatile const void *addr)
+ {
+ 	int oldbit;
+ 
+-	asm volatile("bt %2,%1\n\t"
++	asm volatile("bt %2,%3\n\t"
+ 		     "sbb %0,%0"
+ 		     : "=r" (oldbit)
+-		     : "m" (*(unsigned long *)addr), "Ir" (nr));
++		     : "m" (((volatile const int *)addr)[nr >> 5]),
++		       "Ir" (nr), BASE_ADDR);
+ 
+ 	return oldbit;
+ }
+@@ -310,6 +302,8 @@ static int test_bit(int nr, const volatile unsigned long *addr);
+ 	 constant_test_bit((nr),(addr)) :	\
+ 	 variable_test_bit((nr),(addr)))
+ 
++#undef BASE_ADDR
++#undef BIT_ADDR
+ #undef ADDR
+ 
+ #ifdef CONFIG_X86_32
+diff --git a/include/asm-x86/bitops_32.h b/include/asm-x86/bitops_32.h
+index e4d75fc..2513a81 100644
+--- a/include/asm-x86/bitops_32.h
++++ b/include/asm-x86/bitops_32.h
+@@ -20,20 +20,22 @@ static inline int find_first_zero_bit(const unsigned long *addr, unsigned size)
+ 
+ 	if (!size)
+ 		return 0;
+-	/* This looks at memory. Mark it volatile to tell gcc not to move it around */
+-	__asm__ __volatile__(
+-		"movl $-1,%%eax\n\t"
+-		"xorl %%edx,%%edx\n\t"
+-		"repe; scasl\n\t"
+-		"je 1f\n\t"
+-		"xorl -4(%%edi),%%eax\n\t"
+-		"subl $4,%%edi\n\t"
+-		"bsfl %%eax,%%edx\n"
+-		"1:\tsubl %%ebx,%%edi\n\t"
+-		"shll $3,%%edi\n\t"
+-		"addl %%edi,%%edx"
+-		:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+-		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory");
++	/* This looks at memory.
++	 * Mark it volatile to tell gcc not to move it around
++	 */
++	asm volatile("movl $-1,%%eax\n\t"
++		     "xorl %%edx,%%edx\n\t"
++		     "repe; scasl\n\t"
++		     "je 1f\n\t"
++		     "xorl -4(%%edi),%%eax\n\t"
++		     "subl $4,%%edi\n\t"
++		     "bsfl %%eax,%%edx\n"
++		     "1:\tsubl %%ebx,%%edi\n\t"
++		     "shll $3,%%edi\n\t"
++		     "addl %%edi,%%edx"
++		     : "=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
++		     : "1" ((size + 31) >> 5), "2" (addr),
++		       "b" (addr) : "memory");
+ 	return res;
+ }
+ 
+@@ -75,7 +77,7 @@ static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
+ 		unsigned long val = *addr++;
+ 		if (val)
+ 			return __ffs(val) + x;
+-		x += (sizeof(*addr)<<3);
++		x += sizeof(*addr) << 3;
+ 	}
+ 	return x;
+ }
+@@ -152,10 +154,10 @@ static inline int fls(int x)
+ 
+ #include <asm-generic/bitops/ext2-non-atomic.h>
+ 
+-#define ext2_set_bit_atomic(lock, nr, addr) \
+-		test_and_set_bit((nr), (unsigned long *)addr)
+-#define ext2_clear_bit_atomic(lock, nr, addr) \
+-		test_and_clear_bit((nr), (unsigned long *)addr)
++#define ext2_set_bit_atomic(lock, nr, addr)			\
++	test_and_set_bit((nr), (unsigned long *)(addr))
++#define ext2_clear_bit_atomic(lock, nr, addr)			\
++	test_and_clear_bit((nr), (unsigned long *)(addr))
+ 
+ #include <asm-generic/bitops/minix.h>
+ 
+diff --git a/include/asm-x86/bitops_64.h b/include/asm-x86/bitops_64.h
+index aaf1519..365f820 100644
+--- a/include/asm-x86/bitops_64.h
++++ b/include/asm-x86/bitops_64.h
+@@ -17,35 +17,35 @@ static inline long __scanbit(unsigned long val, unsigned long max)
+ 	return val;
+ }
+ 
+-#define find_first_bit(addr,size) \
+-((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ? \
+-  (__scanbit(*(unsigned long *)addr,(size))) : \
+-  find_first_bit(addr,size)))
+-
+ #define find_next_bit(addr,size,off) \
+ ((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ? 	  \
+   ((off) + (__scanbit((*(unsigned long *)addr) >> (off),(size)-(off)))) : \
+ 	find_next_bit(addr,size,off)))
+ 
+-#define find_first_zero_bit(addr,size) \
+-((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ? \
+-  (__scanbit(~*(unsigned long *)addr,(size))) : \
+-  	find_first_zero_bit(addr,size)))
+-	
+ #define find_next_zero_bit(addr,size,off) \
+ ((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ? 	  \
+   ((off)+(__scanbit(~(((*(unsigned long *)addr)) >> (off)),(size)-(off)))) : \
+ 	find_next_zero_bit(addr,size,off)))
+ 
+-static inline void set_bit_string(unsigned long *bitmap, unsigned long i, 
+-				  int len) 
+-{ 
+-	unsigned long end = i + len; 
++#define find_first_bit(addr, size)					\
++	((__builtin_constant_p((size)) && (size) <= BITS_PER_LONG	\
++	  ? (__scanbit(*(unsigned long *)(addr), (size)))		\
++	  : find_first_bit((addr), (size))))
++
++#define find_first_zero_bit(addr, size)					\
++	((__builtin_constant_p((size)) && (size) <= BITS_PER_LONG	\
++	  ? (__scanbit(~*(unsigned long *)(addr), (size)))		\
++	  : find_first_zero_bit((addr), (size))))
++
++static inline void set_bit_string(unsigned long *bitmap, unsigned long i,
++				  int len)
++{
++	unsigned long end = i + len;
+ 	while (i < end) {
+-		__set_bit(i, bitmap); 
++		__set_bit(i, bitmap);
+ 		i++;
+ 	}
+-} 
++}
+ 
+ /**
+  * ffz - find first zero in word.
+@@ -150,10 +150,10 @@ static inline int fls(int x)
+ 
+ #include <asm-generic/bitops/ext2-non-atomic.h>
+ 
+-#define ext2_set_bit_atomic(lock,nr,addr) \
+-	        test_and_set_bit((nr),(unsigned long*)addr)
+-#define ext2_clear_bit_atomic(lock,nr,addr) \
+-	        test_and_clear_bit((nr),(unsigned long*)addr)
++#define ext2_set_bit_atomic(lock, nr, addr)			\
++	test_and_set_bit((nr), (unsigned long *)(addr))
++#define ext2_clear_bit_atomic(lock, nr, addr)			\
++	test_and_clear_bit((nr), (unsigned long *)(addr))
+ 
+ #include <asm-generic/bitops/minix.h>
+ 
+diff --git a/include/asm-x86/boot.h b/include/asm-x86/boot.h
+index ed8affb..2faed7e 100644
+--- a/include/asm-x86/boot.h
++++ b/include/asm-x86/boot.h
+@@ -17,4 +17,12 @@
+ 				+ (CONFIG_PHYSICAL_ALIGN - 1)) \
+ 				& ~(CONFIG_PHYSICAL_ALIGN - 1))
+ 
++#ifdef CONFIG_X86_64
++#define BOOT_HEAP_SIZE	0x7000
++#define BOOT_STACK_SIZE	0x4000
++#else
++#define BOOT_HEAP_SIZE	0x4000
++#define BOOT_STACK_SIZE	0x1000
++#endif
++
+ #endif /* _ASM_BOOT_H */
+diff --git a/include/asm-x86/bug.h b/include/asm-x86/bug.h
+index 8d477a2..b69aa64 100644
+--- a/include/asm-x86/bug.h
++++ b/include/asm-x86/bug.h
+@@ -12,25 +12,25 @@
+ # define __BUG_C0	"2:\t.quad 1b, %c0\n"
+ #endif
+ 
+-#define BUG()								\
+-	do {								\
+-		asm volatile("1:\tud2\n"				\
+-			     ".pushsection __bug_table,\"a\"\n"		\
+-			     __BUG_C0					\
+-			     "\t.word %c1, 0\n"				\
+-			     "\t.org 2b+%c2\n"				\
+-			     ".popsection"				\
+-			     : : "i" (__FILE__), "i" (__LINE__),	\
+-			     "i" (sizeof(struct bug_entry)));		\
+-		for(;;) ;						\
+-	} while(0)
++#define BUG()							\
++do {								\
++	asm volatile("1:\tud2\n"				\
++		     ".pushsection __bug_table,\"a\"\n"		\
++		     __BUG_C0					\
++		     "\t.word %c1, 0\n"				\
++		     "\t.org 2b+%c2\n"				\
++		     ".popsection"				\
++		     : : "i" (__FILE__), "i" (__LINE__),	\
++		     "i" (sizeof(struct bug_entry)));		\
++	for (;;) ;						\
++} while (0)
+ 
+ #else
+-#define BUG()								\
+-	do {								\
+-		asm volatile("ud2");					\
+-		for(;;) ;						\
+-	} while(0)
++#define BUG()							\
++do {								\
++	asm volatile("ud2");					\
++	for (;;) ;						\
++} while (0)
+ #endif
+ 
+ #endif /* !CONFIG_BUG */
+diff --git a/include/asm-x86/byteorder.h b/include/asm-x86/byteorder.h
+index fe2f2e5..e02ae2d 100644
+--- a/include/asm-x86/byteorder.h
++++ b/include/asm-x86/byteorder.h
+@@ -8,50 +8,59 @@
+ 
+ #ifdef __i386__
+ 
+-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
++static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
+ {
+ #ifdef CONFIG_X86_BSWAP
+-	__asm__("bswap %0" : "=r" (x) : "0" (x));
++	asm("bswap %0" : "=r" (x) : "0" (x));
+ #else
+-	__asm__("xchgb %b0,%h0\n\t"	/* swap lower bytes	*/
+-		"rorl $16,%0\n\t"	/* swap words		*/
+-		"xchgb %b0,%h0"		/* swap higher bytes	*/
+-		:"=q" (x)
+-		: "0" (x));
++	asm("xchgb %b0,%h0\n\t"	/* swap lower bytes	*/
++	    "rorl $16,%0\n\t"	/* swap words		*/
++	    "xchgb %b0,%h0"	/* swap higher bytes	*/
++	    : "=q" (x)
++	    : "0" (x));
+ #endif
+ 	return x;
+ }
+ 
+-static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val)
++static inline __attribute_const__ __u64 ___arch__swab64(__u64 val)
+ {
+ 	union {
+-		struct { __u32 a,b; } s;
++		struct {
++			__u32 a;
++			__u32 b;
++		} s;
+ 		__u64 u;
+ 	} v;
+ 	v.u = val;
+ #ifdef CONFIG_X86_BSWAP
+-	__asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
++	asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+ 	    : "=r" (v.s.a), "=r" (v.s.b)
+ 	    : "0" (v.s.a), "1" (v.s.b));
+ #else
+ 	v.s.a = ___arch__swab32(v.s.a);
+ 	v.s.b = ___arch__swab32(v.s.b);
+-	__asm__("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b));
++	asm("xchgl %0,%1"
++	    : "=r" (v.s.a), "=r" (v.s.b)
++	    : "0" (v.s.a), "1" (v.s.b));
+ #endif
+ 	return v.u;
+ }
+ 
+ #else /* __i386__ */
+ 
+-static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x)
++static inline __attribute_const__ __u64 ___arch__swab64(__u64 x)
+ {
+-	__asm__("bswapq %0" : "=r" (x) : "0" (x));
++	asm("bswapq %0"
++	    : "=r" (x)
++	    : "0" (x));
+ 	return x;
+ }
+ 
+-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
++static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
+ {
+-	__asm__("bswapl %0" : "=r" (x) : "0" (x));
++	asm("bswapl %0"
++	    : "=r" (x)
++	    : "0" (x));
+ 	return x;
+ }
+ 
+diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h
+index 5396c21..f4c0ab5 100644
+--- a/include/asm-x86/cacheflush.h
++++ b/include/asm-x86/cacheflush.h
+@@ -14,33 +14,85 @@
+ #define flush_dcache_mmap_lock(mapping)		do { } while (0)
+ #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+ #define flush_icache_range(start, end)		do { } while (0)
+-#define flush_icache_page(vma,pg)		do { } while (0)
+-#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
++#define flush_icache_page(vma, pg)		do { } while (0)
++#define flush_icache_user_range(vma, pg, adr, len)	do { } while (0)
+ #define flush_cache_vmap(start, end)		do { } while (0)
+ #define flush_cache_vunmap(start, end)		do { } while (0)
+ 
+-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+-	memcpy(dst, src, len)
+-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+-	memcpy(dst, src, len)
++#define copy_to_user_page(vma, page, vaddr, dst, src, len)	\
++	memcpy((dst), (src), (len))
++#define copy_from_user_page(vma, page, vaddr, dst, src, len)	\
++	memcpy((dst), (src), (len))
+ 
+-int __deprecated_for_modules change_page_attr(struct page *page, int numpages,
+-								pgprot_t prot);
+ 
+-int set_pages_uc(struct page *page, int numpages);
+-int set_pages_wb(struct page *page, int numpages);
+-int set_pages_x(struct page *page, int numpages);
+-int set_pages_nx(struct page *page, int numpages);
+-int set_pages_ro(struct page *page, int numpages);
+-int set_pages_rw(struct page *page, int numpages);
++/*
++ * The set_memory_* API can be used to change various attributes of a virtual
++ * address range. The attributes include:
++ * Cachability   : UnCached, WriteCombining, WriteBack
++ * Executability : eXeutable, NoteXecutable
++ * Read/Write    : ReadOnly, ReadWrite
++ * Presence      : NotPresent
++ *
++ * Within a catagory, the attributes are mutually exclusive.
++ *
++ * The implementation of this API will take care of various aspects that
++ * are associated with changing such attributes, such as:
++ * - Flushing TLBs
++ * - Flushing CPU caches
++ * - Making sure aliases of the memory behind the mapping don't violate
++ *   coherency rules as defined by the CPU in the system.
++ *
++ * What this API does not do:
++ * - Provide exclusion between various callers - including callers that
++ *   operation on other mappings of the same physical page
++ * - Restore default attributes when a page is freed
++ * - Guarantee that mappings other than the requested one are
++ *   in any state, other than that these do not violate rules for
++ *   the CPU you have. Do not depend on any effects on other mappings,
++ *   CPUs other than the one you have may have more relaxed rules.
++ * The caller is required to take care of these.
++ */
+ 
++int _set_memory_uc(unsigned long addr, int numpages);
++int _set_memory_wc(unsigned long addr, int numpages);
++int _set_memory_wb(unsigned long addr, int numpages);
+ int set_memory_uc(unsigned long addr, int numpages);
++int set_memory_wc(unsigned long addr, int numpages);
+ int set_memory_wb(unsigned long addr, int numpages);
+ int set_memory_x(unsigned long addr, int numpages);
+ int set_memory_nx(unsigned long addr, int numpages);
+ int set_memory_ro(unsigned long addr, int numpages);
+ int set_memory_rw(unsigned long addr, int numpages);
+ int set_memory_np(unsigned long addr, int numpages);
++int set_memory_4k(unsigned long addr, int numpages);
++
++/*
++ * For legacy compatibility with the old APIs, a few functions
++ * are provided that work on a "struct page".
++ * These functions operate ONLY on the 1:1 kernel mapping of the
++ * memory that the struct page represents, and internally just
++ * call the set_memory_* function. See the description of the
++ * set_memory_* function for more details on conventions.
++ *
++ * These APIs should be considered *deprecated* and are likely going to
++ * be removed in the future.
++ * The reason for this is the implicit operation on the 1:1 mapping only,
++ * making this not a generally useful API.
++ *
++ * Specifically, many users of the old APIs had a virtual address,
++ * called virt_to_page() or vmalloc_to_page() on that address to
++ * get a struct page* that the old API required.
++ * To convert these cases, use set_memory_*() on the original
++ * virtual address, do not use these functions.
++ */
++
++int set_pages_uc(struct page *page, int numpages);
++int set_pages_wb(struct page *page, int numpages);
++int set_pages_x(struct page *page, int numpages);
++int set_pages_nx(struct page *page, int numpages);
++int set_pages_ro(struct page *page, int numpages);
++int set_pages_rw(struct page *page, int numpages);
++
+ 
+ void clflush_cache_range(void *addr, unsigned int size);
+ 
+diff --git a/include/asm-x86/checksum_32.h b/include/asm-x86/checksum_32.h
+index 75194ab..52bbb0d 100644
+--- a/include/asm-x86/checksum_32.h
++++ b/include/asm-x86/checksum_32.h
+@@ -28,7 +28,8 @@ asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
+  */
+ 
+ asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
+-						  int len, __wsum sum, int *src_err_ptr, int *dst_err_ptr);
++					    int len, __wsum sum,
++					    int *src_err_ptr, int *dst_err_ptr);
+ 
+ /*
+  *	Note: when you get a NULL pointer exception here this means someone
+@@ -37,20 +38,20 @@ asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
+  *	If you use these functions directly please don't forget the
+  *	access_ok().
+  */
+-static __inline__
+-__wsum csum_partial_copy_nocheck (const void *src, void *dst,
+-					int len, __wsum sum)
++static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst,
++					       int len, __wsum sum)
+ {
+-	return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
++	return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL);
+ }
+ 
+-static __inline__
+-__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+-						int len, __wsum sum, int *err_ptr)
++static inline __wsum csum_partial_copy_from_user(const void __user *src,
++						 void *dst,
++						 int len, __wsum sum,
++						 int *err_ptr)
+ {
+ 	might_sleep();
+ 	return csum_partial_copy_generic((__force void *)src, dst,
+-					len, sum, err_ptr, NULL);
++					 len, sum, err_ptr, NULL);
+ }
+ 
+ /*
+@@ -64,30 +65,29 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+ {
+ 	unsigned int sum;
+ 
+-	__asm__ __volatile__(
+-	    "movl (%1), %0	;\n"
+-	    "subl $4, %2	;\n"
+-	    "jbe 2f		;\n"
+-	    "addl 4(%1), %0	;\n"
+-	    "adcl 8(%1), %0	;\n"
+-	    "adcl 12(%1), %0	;\n"
+-"1:	    adcl 16(%1), %0	;\n"
+-	    "lea 4(%1), %1	;\n"
+-	    "decl %2		;\n"
+-	    "jne 1b		;\n"
+-	    "adcl $0, %0	;\n"
+-	    "movl %0, %2	;\n"
+-	    "shrl $16, %0	;\n"
+-	    "addw %w2, %w0	;\n"
+-	    "adcl $0, %0	;\n"
+-	    "notl %0		;\n"
+-"2:				;\n"
++	asm volatile("movl (%1), %0	;\n"
++		     "subl $4, %2	;\n"
++		     "jbe 2f		;\n"
++		     "addl 4(%1), %0	;\n"
++		     "adcl 8(%1), %0	;\n"
++		     "adcl 12(%1), %0;\n"
++		     "1:	adcl 16(%1), %0	;\n"
++		     "lea 4(%1), %1	;\n"
++		     "decl %2	;\n"
++		     "jne 1b		;\n"
++		     "adcl $0, %0	;\n"
++		     "movl %0, %2	;\n"
++		     "shrl $16, %0	;\n"
++		     "addw %w2, %w0	;\n"
++		     "adcl $0, %0	;\n"
++		     "notl %0	;\n"
++		     "2:		;\n"
+ 	/* Since the input registers which are loaded with iph and ihl
+ 	   are modified, we must also specify them as outputs, or gcc
+ 	   will assume they contain their original values. */
+-	: "=r" (sum), "=r" (iph), "=r" (ihl)
+-	: "1" (iph), "2" (ihl)
+-	: "memory");
++		     : "=r" (sum), "=r" (iph), "=r" (ihl)
++		     : "1" (iph), "2" (ihl)
++		     : "memory");
+ 	return (__force __sum16)sum;
+ }
+ 
+@@ -97,29 +97,27 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+ 
+ static inline __sum16 csum_fold(__wsum sum)
+ {
+-	__asm__(
+-		"addl %1, %0		;\n"
+-		"adcl $0xffff, %0	;\n"
+-		: "=r" (sum)
+-		: "r" ((__force u32)sum << 16),
+-		  "0" ((__force u32)sum & 0xffff0000)
+-	);
++	asm("addl %1, %0		;\n"
++	    "adcl $0xffff, %0	;\n"
++	    : "=r" (sum)
++	    : "r" ((__force u32)sum << 16),
++	      "0" ((__force u32)sum & 0xffff0000));
+ 	return (__force __sum16)(~(__force u32)sum >> 16);
+ }
+ 
+ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+-					   unsigned short len,
+-					   unsigned short proto,
+-					   __wsum sum)
++					unsigned short len,
++					unsigned short proto,
++					__wsum sum)
+ {
+-    __asm__(
+-	"addl %1, %0	;\n"
+-	"adcl %2, %0	;\n"
+-	"adcl %3, %0	;\n"
+-	"adcl $0, %0	;\n"
+-	: "=r" (sum)
+-	: "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
+-    return sum;
++	asm("addl %1, %0	;\n"
++	    "adcl %2, %0	;\n"
++	    "adcl %3, %0	;\n"
++	    "adcl $0, %0	;\n"
++	    : "=r" (sum)
++	    : "g" (daddr), "g"(saddr),
++	      "g" ((len + proto) << 8), "0" (sum));
++	return sum;
+ }
+ 
+ /*
+@@ -127,11 +125,11 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+  * returns a 16-bit checksum, already complemented
+  */
+ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+-						   unsigned short len,
+-						   unsigned short proto,
+-						   __wsum sum)
++					unsigned short len,
++					unsigned short proto,
++					__wsum sum)
+ {
+-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
++	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+ }
+ 
+ /*
+@@ -141,30 +139,29 @@ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+ 
+ static inline __sum16 ip_compute_csum(const void *buff, int len)
+ {
+-    return csum_fold (csum_partial(buff, len, 0));
++    return csum_fold(csum_partial(buff, len, 0));
+ }
+ 
+ #define _HAVE_ARCH_IPV6_CSUM
+-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+-					  const struct in6_addr *daddr,
+-					  __u32 len, unsigned short proto,
+-					  __wsum sum)
++static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
++				      const struct in6_addr *daddr,
++				      __u32 len, unsigned short proto,
++				      __wsum sum)
+ {
+-	__asm__(
+-		"addl 0(%1), %0		;\n"
+-		"adcl 4(%1), %0		;\n"
+-		"adcl 8(%1), %0		;\n"
+-		"adcl 12(%1), %0	;\n"
+-		"adcl 0(%2), %0		;\n"
+-		"adcl 4(%2), %0		;\n"
+-		"adcl 8(%2), %0		;\n"
+-		"adcl 12(%2), %0	;\n"
+-		"adcl %3, %0		;\n"
+-		"adcl %4, %0		;\n"
+-		"adcl $0, %0		;\n"
+-		: "=&r" (sum)
+-		: "r" (saddr), "r" (daddr),
+-		  "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
++	asm("addl 0(%1), %0	;\n"
++	    "adcl 4(%1), %0	;\n"
++	    "adcl 8(%1), %0	;\n"
++	    "adcl 12(%1), %0	;\n"
++	    "adcl 0(%2), %0	;\n"
++	    "adcl 4(%2), %0	;\n"
++	    "adcl 8(%2), %0	;\n"
++	    "adcl 12(%2), %0	;\n"
++	    "adcl %3, %0	;\n"
++	    "adcl %4, %0	;\n"
++	    "adcl $0, %0	;\n"
++	    : "=&r" (sum)
++	    : "r" (saddr), "r" (daddr),
++	      "r" (htonl(len)), "r" (htonl(proto)), "0" (sum));
+ 
+ 	return csum_fold(sum);
+ }
+@@ -173,14 +170,15 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+  *	Copy and checksum to user
+  */
+ #define HAVE_CSUM_COPY_USER
+-static __inline__ __wsum csum_and_copy_to_user(const void *src,
+-						     void __user *dst,
+-						     int len, __wsum sum,
+-						     int *err_ptr)
++static inline __wsum csum_and_copy_to_user(const void *src,
++					   void __user *dst,
++					   int len, __wsum sum,
++					   int *err_ptr)
+ {
+ 	might_sleep();
+ 	if (access_ok(VERIFY_WRITE, dst, len))
+-		return csum_partial_copy_generic(src, (__force void *)dst, len, sum, NULL, err_ptr);
++		return csum_partial_copy_generic(src, (__force void *)dst,
++						 len, sum, NULL, err_ptr);
+ 
+ 	if (len)
+ 		*err_ptr = -EFAULT;
+diff --git a/include/asm-x86/checksum_64.h b/include/asm-x86/checksum_64.h
+index e5f7999..8bd861c 100644
+--- a/include/asm-x86/checksum_64.h
++++ b/include/asm-x86/checksum_64.h
+@@ -1,33 +1,31 @@
+ #ifndef _X86_64_CHECKSUM_H
+ #define _X86_64_CHECKSUM_H
+ 
+-/* 
+- * Checksums for x86-64 
+- * Copyright 2002 by Andi Kleen, SuSE Labs 
++/*
++ * Checksums for x86-64
++ * Copyright 2002 by Andi Kleen, SuSE Labs
+  * with some code from asm-x86/checksum.h
+- */ 
++ */
+ 
+ #include <linux/compiler.h>
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+ 
+-/** 
++/**
+  * csum_fold - Fold and invert a 32bit checksum.
+  * sum: 32bit unfolded sum
+- * 
++ *
+  * Fold a 32bit running checksum to 16bit and invert it. This is usually
+  * the last step before putting a checksum into a packet.
+  * Make sure not to mix with 64bit checksums.
+  */
+ static inline __sum16 csum_fold(__wsum sum)
+ {
+-	__asm__(
+-		"  addl %1,%0\n"
+-		"  adcl $0xffff,%0"
+-		: "=r" (sum)
+-		: "r" ((__force u32)sum << 16),
+-		  "0" ((__force u32)sum & 0xffff0000)
+-	);
++	asm("  addl %1,%0\n"
++	    "  adcl $0xffff,%0"
++	    : "=r" (sum)
++	    : "r" ((__force u32)sum << 16),
++	      "0" ((__force u32)sum & 0xffff0000));
+ 	return (__force __sum16)(~(__force u32)sum >> 16);
+ }
+ 
+@@ -43,46 +41,46 @@ static inline __sum16 csum_fold(__wsum sum)
+  * ip_fast_csum - Compute the IPv4 header checksum efficiently.
+  * iph: ipv4 header
+  * ihl: length of header / 4
+- */ 
++ */
+ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+ {
+ 	unsigned int sum;
+ 
+-	asm(	"  movl (%1), %0\n"
+-		"  subl $4, %2\n"
+-		"  jbe 2f\n"
+-		"  addl 4(%1), %0\n"
+-		"  adcl 8(%1), %0\n"
+-		"  adcl 12(%1), %0\n"
+-		"1: adcl 16(%1), %0\n"
+-		"  lea 4(%1), %1\n"
+-		"  decl %2\n"
+-		"  jne	1b\n"
+-		"  adcl $0, %0\n"
+-		"  movl %0, %2\n"
+-		"  shrl $16, %0\n"
+-		"  addw %w2, %w0\n"
+-		"  adcl $0, %0\n"
+-		"  notl %0\n"
+-		"2:"
++	asm("  movl (%1), %0\n"
++	    "  subl $4, %2\n"
++	    "  jbe 2f\n"
++	    "  addl 4(%1), %0\n"
++	    "  adcl 8(%1), %0\n"
++	    "  adcl 12(%1), %0\n"
++	    "1: adcl 16(%1), %0\n"
++	    "  lea 4(%1), %1\n"
++	    "  decl %2\n"
++	    "  jne	1b\n"
++	    "  adcl $0, %0\n"
++	    "  movl %0, %2\n"
++	    "  shrl $16, %0\n"
++	    "  addw %w2, %w0\n"
++	    "  adcl $0, %0\n"
++	    "  notl %0\n"
++	    "2:"
+ 	/* Since the input registers which are loaded with iph and ihl
+ 	   are modified, we must also specify them as outputs, or gcc
+ 	   will assume they contain their original values. */
+-	: "=r" (sum), "=r" (iph), "=r" (ihl)
+-	: "1" (iph), "2" (ihl)
+-	: "memory");
++	    : "=r" (sum), "=r" (iph), "=r" (ihl)
++	    : "1" (iph), "2" (ihl)
++	    : "memory");
+ 	return (__force __sum16)sum;
+ }
+ 
+-/** 
++/**
+  * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
+  * @saddr: source address
+  * @daddr: destination address
+  * @len: length of packet
+  * @proto: ip protocol of packet
+- * @sum: initial sum to be added in (32bit unfolded) 
+- * 
+- * Returns the pseudo header checksum the input data. Result is 
++ * @sum: initial sum to be added in (32bit unfolded)
++ *
++ * Returns the pseudo header checksum the input data. Result is
+  * 32bit unfolded.
+  */
+ static inline __wsum
+@@ -93,32 +91,32 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ 	    "  adcl %2, %0\n"
+ 	    "  adcl %3, %0\n"
+ 	    "  adcl $0, %0\n"
+-		: "=r" (sum)
++	    : "=r" (sum)
+ 	    : "g" (daddr), "g" (saddr),
+ 	      "g" ((len + proto)<<8), "0" (sum));
+-    return sum;
++	return sum;
+ }
+ 
+ 
+-/** 
++/**
+  * csum_tcpup_magic - Compute an IPv4 pseudo header checksum.
+  * @saddr: source address
+  * @daddr: destination address
+  * @len: length of packet
+  * @proto: ip protocol of packet
+- * @sum: initial sum to be added in (32bit unfolded) 
+- * 
++ * @sum: initial sum to be added in (32bit unfolded)
++ *
+  * Returns the 16bit pseudo header checksum the input data already
+  * complemented and ready to be filled in.
+  */
+-static inline __sum16
+-csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+-		  unsigned short len, unsigned short proto, __wsum sum)
++static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
++					unsigned short len,
++					unsigned short proto, __wsum sum)
+ {
+-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
++	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+ }
+ 
+-/** 
++/**
+  * csum_partial - Compute an internet checksum.
+  * @buff: buffer to be checksummed
+  * @len: length of buffer.
+@@ -127,7 +125,7 @@ csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+  * Returns the 32bit unfolded internet checksum of the buffer.
+  * Before filling it in it needs to be csum_fold()'ed.
+  * buff should be aligned to a 64bit boundary if possible.
+- */ 
++ */
+ extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+ 
+ #define  _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1
+@@ -136,23 +134,22 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+ 
+ /* Do not call this directly. Use the wrappers below */
+ extern __wsum csum_partial_copy_generic(const void *src, const void *dst,
+-					       int len,
+-					       __wsum sum,
+-					       int *src_err_ptr, int *dst_err_ptr);
++					int len, __wsum sum,
++					int *src_err_ptr, int *dst_err_ptr);
+ 
+ 
+ extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+-				       int len, __wsum isum, int *errp);
++					  int len, __wsum isum, int *errp);
+ extern __wsum csum_partial_copy_to_user(const void *src, void __user *dst,
+-				      int len, __wsum isum, int *errp);
+-extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len,
+-					      __wsum sum);
++					int len, __wsum isum, int *errp);
++extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
++					int len, __wsum sum);
+ 
+ /* Old names. To be removed. */
+ #define csum_and_copy_to_user csum_partial_copy_to_user
+ #define csum_and_copy_from_user csum_partial_copy_from_user
+ 
+-/** 
++/**
+  * ip_compute_csum - Compute an 16bit IP checksum.
+  * @buff: buffer address.
+  * @len: length of buffer.
+@@ -170,7 +167,7 @@ extern __sum16 ip_compute_csum(const void *buff, int len);
+  * @proto: protocol of packet
+  * @sum: initial sum (32bit unfolded) to be added in
+  *
+- * Computes an IPv6 pseudo header checksum. This sum is added the checksum 
++ * Computes an IPv6 pseudo header checksum. This sum is added the checksum
+  * into UDP/TCP packets and contains some link layer information.
+  * Returns the unfolded 32bit checksum.
+  */
+@@ -185,11 +182,10 @@ csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
+ static inline unsigned add32_with_carry(unsigned a, unsigned b)
+ {
+ 	asm("addl %2,%0\n\t"
+-	    "adcl $0,%0" 
+-	    : "=r" (a) 
++	    "adcl $0,%0"
++	    : "=r" (a)
+ 	    : "0" (a), "r" (b));
+ 	return a;
+ }
+ 
+ #endif
+-
+diff --git a/include/asm-x86/cmpxchg_32.h b/include/asm-x86/cmpxchg_32.h
+index 959fad0..bf5a69d 100644
+--- a/include/asm-x86/cmpxchg_32.h
++++ b/include/asm-x86/cmpxchg_32.h
+@@ -8,9 +8,12 @@
+  *       you need to test for the feature in boot_cpu_data.
+  */
+ 
+-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
++#define xchg(ptr, v)							\
++	((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), sizeof(*(ptr))))
+ 
+-struct __xchg_dummy { unsigned long a[100]; };
++struct __xchg_dummy {
++	unsigned long a[100];
++};
+ #define __xg(x) ((struct __xchg_dummy *)(x))
+ 
+ /*
+@@ -27,72 +30,74 @@ struct __xchg_dummy { unsigned long a[100]; };
+  * of the instruction set reference 24319102.pdf. We need
+  * the reader side to see the coherent 64bit value.
+  */
+-static inline void __set_64bit (unsigned long long * ptr,
+-		unsigned int low, unsigned int high)
++static inline void __set_64bit(unsigned long long *ptr,
++			       unsigned int low, unsigned int high)
+ {
+-	__asm__ __volatile__ (
+-		"\n1:\t"
+-		"movl (%0), %%eax\n\t"
+-		"movl 4(%0), %%edx\n\t"
+-		LOCK_PREFIX "cmpxchg8b (%0)\n\t"
+-		"jnz 1b"
+-		: /* no outputs */
+-		:	"D"(ptr),
+-			"b"(low),
+-			"c"(high)
+-		:	"ax","dx","memory");
++	asm volatile("\n1:\t"
++		     "movl (%0), %%eax\n\t"
++		     "movl 4(%0), %%edx\n\t"
++		     LOCK_PREFIX "cmpxchg8b (%0)\n\t"
++		     "jnz 1b"
++		     : /* no outputs */
++		     : "D"(ptr),
++		       "b"(low),
++		       "c"(high)
++		     : "ax", "dx", "memory");
+ }
+ 
+-static inline void __set_64bit_constant (unsigned long long *ptr,
+-						 unsigned long long value)
++static inline void __set_64bit_constant(unsigned long long *ptr,
++					unsigned long long value)
+ {
+-	__set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
++	__set_64bit(ptr, (unsigned int)value, (unsigned int)(value >> 32));
+ }
+-#define ll_low(x)	*(((unsigned int*)&(x))+0)
+-#define ll_high(x)	*(((unsigned int*)&(x))+1)
+ 
+-static inline void __set_64bit_var (unsigned long long *ptr,
+-			 unsigned long long value)
++#define ll_low(x)	*(((unsigned int *)&(x)) + 0)
++#define ll_high(x)	*(((unsigned int *)&(x)) + 1)
++
++static inline void __set_64bit_var(unsigned long long *ptr,
++				   unsigned long long value)
+ {
+-	__set_64bit(ptr,ll_low(value), ll_high(value));
++	__set_64bit(ptr, ll_low(value), ll_high(value));
+ }
+ 
+-#define set_64bit(ptr,value) \
+-(__builtin_constant_p(value) ? \
+- __set_64bit_constant(ptr, value) : \
+- __set_64bit_var(ptr, value) )
++#define set_64bit(ptr, value)			\
++	(__builtin_constant_p((value))		\
++	 ? __set_64bit_constant((ptr), (value))	\
++	 : __set_64bit_var((ptr), (value)))
+ 
+-#define _set_64bit(ptr,value) \
+-(__builtin_constant_p(value) ? \
+- __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
+- __set_64bit(ptr, ll_low(value), ll_high(value)) )
++#define _set_64bit(ptr, value)						\
++	(__builtin_constant_p(value)					\
++	 ? __set_64bit(ptr, (unsigned int)(value),			\
++		       (unsigned int)((value) >> 32))			\
++	 : __set_64bit(ptr, ll_low((value)), ll_high((value))))
+ 
+ /*
+  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+  * Note 2: xchg has side effect, so that attribute volatile is necessary,
+  *	  but generally the primitive is invalid, *ptr is output argument. --ANK
+  */
+-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
++				   int size)
+ {
+ 	switch (size) {
+-		case 1:
+-			__asm__ __volatile__("xchgb %b0,%1"
+-				:"=q" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 2:
+-			__asm__ __volatile__("xchgw %w0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 4:
+-			__asm__ __volatile__("xchgl %0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
++	case 1:
++		asm volatile("xchgb %b0,%1"
++			     : "=q" (x)
++			     : "m" (*__xg(ptr)), "0" (x)
++			     : "memory");
++		break;
++	case 2:
++		asm volatile("xchgw %w0,%1"
++			     : "=r" (x)
++			     : "m" (*__xg(ptr)), "0" (x)
++			     : "memory");
++		break;
++	case 4:
++		asm volatile("xchgl %0,%1"
++			     : "=r" (x)
++			     : "m" (*__xg(ptr)), "0" (x)
++			     : "memory");
++		break;
+ 	}
+ 	return x;
+ }
+@@ -105,24 +110,27 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
+ 
+ #ifdef CONFIG_X86_CMPXCHG
+ #define __HAVE_ARCH_CMPXCHG 1
+-#define cmpxchg(ptr, o, n)						     \
+-	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	     \
+-					(unsigned long)(n), sizeof(*(ptr))))
+-#define sync_cmpxchg(ptr, o, n)						     \
+-	((__typeof__(*(ptr)))__sync_cmpxchg((ptr), (unsigned long)(o),	     \
+-					(unsigned long)(n), sizeof(*(ptr))))
+-#define cmpxchg_local(ptr, o, n)					     \
+-	((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),	     \
+-					(unsigned long)(n), sizeof(*(ptr))))
++#define cmpxchg(ptr, o, n)						\
++	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	\
++				       (unsigned long)(n),		\
++				       sizeof(*(ptr))))
++#define sync_cmpxchg(ptr, o, n)						\
++	((__typeof__(*(ptr)))__sync_cmpxchg((ptr), (unsigned long)(o),	\
++					    (unsigned long)(n),		\
++					    sizeof(*(ptr))))
++#define cmpxchg_local(ptr, o, n)					\
++	((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),	\
++					     (unsigned long)(n),	\
++					     sizeof(*(ptr))))
+ #endif
+ 
+ #ifdef CONFIG_X86_CMPXCHG64
+-#define cmpxchg64(ptr, o, n)						      \
+-	((__typeof__(*(ptr)))__cmpxchg64((ptr), (unsigned long long)(o),      \
+-					(unsigned long long)(n)))
+-#define cmpxchg64_local(ptr, o, n)					      \
+-	((__typeof__(*(ptr)))__cmpxchg64_local((ptr), (unsigned long long)(o),\
+-					(unsigned long long)(n)))
++#define cmpxchg64(ptr, o, n)						\
++	((__typeof__(*(ptr)))__cmpxchg64((ptr), (unsigned long long)(o), \
++					 (unsigned long long)(n)))
++#define cmpxchg64_local(ptr, o, n)					\
++	((__typeof__(*(ptr)))__cmpxchg64_local((ptr), (unsigned long long)(o), \
++					       (unsigned long long)(n)))
+ #endif
+ 
+ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+@@ -131,22 +139,22 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ 	unsigned long prev;
+ 	switch (size) {
+ 	case 1:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+-				     : "=a"(prev)
+-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
++			     : "=a"(prev)
++			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 2:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 4:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile(LOCK_PREFIX "cmpxchgl %1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	}
+ 	return old;
+@@ -158,85 +166,88 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+  * isn't.
+  */
+ static inline unsigned long __sync_cmpxchg(volatile void *ptr,
+-					    unsigned long old,
+-					    unsigned long new, int size)
++					   unsigned long old,
++					   unsigned long new, int size)
+ {
+ 	unsigned long prev;
+ 	switch (size) {
+ 	case 1:
+-		__asm__ __volatile__("lock; cmpxchgb %b1,%2"
+-				     : "=a"(prev)
+-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("lock; cmpxchgb %b1,%2"
++			     : "=a"(prev)
++			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 2:
+-		__asm__ __volatile__("lock; cmpxchgw %w1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("lock; cmpxchgw %w1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 4:
+-		__asm__ __volatile__("lock; cmpxchgl %1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("lock; cmpxchgl %1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	}
+ 	return old;
+ }
+ 
+ static inline unsigned long __cmpxchg_local(volatile void *ptr,
+-			unsigned long old, unsigned long new, int size)
++					    unsigned long old,
++					    unsigned long new, int size)
+ {
+ 	unsigned long prev;
+ 	switch (size) {
+ 	case 1:
+-		__asm__ __volatile__("cmpxchgb %b1,%2"
+-				     : "=a"(prev)
+-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("cmpxchgb %b1,%2"
++			     : "=a"(prev)
++			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 2:
+-		__asm__ __volatile__("cmpxchgw %w1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("cmpxchgw %w1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 4:
+-		__asm__ __volatile__("cmpxchgl %1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("cmpxchgl %1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	}
+ 	return old;
+ }
+ 
+ static inline unsigned long long __cmpxchg64(volatile void *ptr,
+-			unsigned long long old, unsigned long long new)
++					     unsigned long long old,
++					     unsigned long long new)
+ {
+ 	unsigned long long prev;
+-	__asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
+-			     : "=A"(prev)
+-			     : "b"((unsigned long)new),
+-			       "c"((unsigned long)(new >> 32)),
+-			       "m"(*__xg(ptr)),
+-			       "0"(old)
+-			     : "memory");
++	asm volatile(LOCK_PREFIX "cmpxchg8b %3"
++		     : "=A"(prev)
++		     : "b"((unsigned long)new),
++		       "c"((unsigned long)(new >> 32)),
++		       "m"(*__xg(ptr)),
++		       "0"(old)
++		     : "memory");
+ 	return prev;
+ }
+ 
+ static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
+-			unsigned long long old, unsigned long long new)
++						   unsigned long long old,
++						   unsigned long long new)
+ {
+ 	unsigned long long prev;
+-	__asm__ __volatile__("cmpxchg8b %3"
+-			     : "=A"(prev)
+-			     : "b"((unsigned long)new),
+-			       "c"((unsigned long)(new >> 32)),
+-			       "m"(*__xg(ptr)),
+-			       "0"(old)
+-			     : "memory");
++	asm volatile("cmpxchg8b %3"
++		     : "=A"(prev)
++		     : "b"((unsigned long)new),
++		       "c"((unsigned long)(new >> 32)),
++		       "m"(*__xg(ptr)),
++		       "0"(old)
++		     : "memory");
+ 	return prev;
+ }
+ 
+@@ -252,7 +263,7 @@ extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16);
+ extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32);
+ 
+ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
+-				      unsigned long new, int size)
++					unsigned long new, int size)
+ {
+ 	switch (size) {
+ 	case 1:
+diff --git a/include/asm-x86/cmpxchg_64.h b/include/asm-x86/cmpxchg_64.h
+index 56f5b41..d9b26b9 100644
+--- a/include/asm-x86/cmpxchg_64.h
++++ b/include/asm-x86/cmpxchg_64.h
+@@ -3,7 +3,8 @@
+ 
+ #include <asm/alternative.h> /* Provides LOCK_PREFIX */
+ 
+-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
++#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), \
++						 (ptr), sizeof(*(ptr))))
+ 
+ #define __xg(x) ((volatile long *)(x))
+ 
+@@ -19,33 +20,34 @@ static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+  * Note 2: xchg has side effect, so that attribute volatile is necessary,
+  *	  but generally the primitive is invalid, *ptr is output argument. --ANK
+  */
+-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
++				   int size)
+ {
+ 	switch (size) {
+-		case 1:
+-			__asm__ __volatile__("xchgb %b0,%1"
+-				:"=q" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 2:
+-			__asm__ __volatile__("xchgw %w0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 4:
+-			__asm__ __volatile__("xchgl %k0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 8:
+-			__asm__ __volatile__("xchgq %0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
++	case 1:
++		asm volatile("xchgb %b0,%1"
++			     : "=q" (x)
++			     : "m" (*__xg(ptr)), "0" (x)
++			     : "memory");
++		break;
++	case 2:
++		asm volatile("xchgw %w0,%1"
++			     : "=r" (x)
++			     : "m" (*__xg(ptr)), "0" (x)
++			     : "memory");
++		break;
++	case 4:
++		asm volatile("xchgl %k0,%1"
++			     : "=r" (x)
++			     : "m" (*__xg(ptr)), "0" (x)
++			     : "memory");
++		break;
++	case 8:
++		asm volatile("xchgq %0,%1"
++			     : "=r" (x)
++			     : "m" (*__xg(ptr)), "0" (x)
++			     : "memory");
++		break;
+ 	}
+ 	return x;
+ }
+@@ -64,61 +66,62 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ 	unsigned long prev;
+ 	switch (size) {
+ 	case 1:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+-				     : "=a"(prev)
+-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
++			     : "=a"(prev)
++			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 2:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 4:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile(LOCK_PREFIX "cmpxchgl %k1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 8:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile(LOCK_PREFIX "cmpxchgq %1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	}
+ 	return old;
+ }
+ 
+ static inline unsigned long __cmpxchg_local(volatile void *ptr,
+-			unsigned long old, unsigned long new, int size)
++					    unsigned long old,
++					    unsigned long new, int size)
+ {
+ 	unsigned long prev;
+ 	switch (size) {
+ 	case 1:
+-		__asm__ __volatile__("cmpxchgb %b1,%2"
+-				     : "=a"(prev)
+-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("cmpxchgb %b1,%2"
++			     : "=a"(prev)
++			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 2:
+-		__asm__ __volatile__("cmpxchgw %w1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("cmpxchgw %w1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 4:
+-		__asm__ __volatile__("cmpxchgl %k1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("cmpxchgl %k1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	case 8:
+-		__asm__ __volatile__("cmpxchgq %1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
++		asm volatile("cmpxchgq %1,%2"
++			     : "=a"(prev)
++			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++			     : "memory");
+ 		return prev;
+ 	}
+ 	return old;
+@@ -126,19 +129,20 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
+ 
+ #define cmpxchg(ptr, o, n)						\
+ 	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	\
+-					(unsigned long)(n), sizeof(*(ptr))))
++				       (unsigned long)(n), sizeof(*(ptr))))
+ #define cmpxchg64(ptr, o, n)						\
+-  ({									\
++({									\
+ 	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
+ 	cmpxchg((ptr), (o), (n));					\
+-  })
++})
+ #define cmpxchg_local(ptr, o, n)					\
+ 	((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),	\
+-					(unsigned long)(n), sizeof(*(ptr))))
++					     (unsigned long)(n),	\
++					     sizeof(*(ptr))))
+ #define cmpxchg64_local(ptr, o, n)					\
+-  ({									\
++({									\
+ 	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
+ 	cmpxchg_local((ptr), (o), (n));					\
+-  })
++})
+ 
+ #endif
+diff --git a/include/asm-x86/compat.h b/include/asm-x86/compat.h
+index d3e8f3e..1793ac3 100644
+--- a/include/asm-x86/compat.h
++++ b/include/asm-x86/compat.h
+@@ -204,7 +204,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+ 	return (u32)(unsigned long)uptr;
+ }
+ 
+-static __inline__ void __user *compat_alloc_user_space(long len)
++static inline void __user *compat_alloc_user_space(long len)
+ {
+ 	struct pt_regs *regs = task_pt_regs(current);
+ 	return (void __user *)regs->sp - len;
+diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h
+index 065e929..0d609c8 100644
+--- a/include/asm-x86/cpufeature.h
++++ b/include/asm-x86/cpufeature.h
+@@ -120,6 +120,9 @@
+ extern const char * const x86_cap_flags[NCAPINTS*32];
+ extern const char * const x86_power_flags[32];
+ 
++#define test_cpu_cap(c, bit)						\
++	 test_bit(bit, (unsigned long *)((c)->x86_capability))
++
+ #define cpu_has(c, bit)							\
+ 	(__builtin_constant_p(bit) &&					\
+ 	 ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) ||	\
+@@ -131,7 +134,8 @@ extern const char * const x86_power_flags[32];
+ 	   (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) ||	\
+ 	   (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) )	\
+ 	  ? 1 :								\
+-	 test_bit(bit, (unsigned long *)((c)->x86_capability)))
++	 test_cpu_cap(c, bit))
++
+ #define boot_cpu_has(bit)	cpu_has(&boot_cpu_data, bit)
+ 
+ #define set_cpu_cap(c, bit)	set_bit(bit, (unsigned long *)((c)->x86_capability))
+@@ -181,6 +185,8 @@ extern const char * const x86_power_flags[32];
+ #define cpu_has_clflush		boot_cpu_has(X86_FEATURE_CLFLSH)
+ #define cpu_has_bts		boot_cpu_has(X86_FEATURE_BTS)
+ #define cpu_has_gbpages		boot_cpu_has(X86_FEATURE_GBPAGES)
++#define cpu_has_arch_perfmon	boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
++#define cpu_has_pat		boot_cpu_has(X86_FEATURE_PAT)
+ 
+ #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
+ # define cpu_has_invlpg		1
+diff --git a/include/asm-x86/current_32.h b/include/asm-x86/current_32.h
+index d352485..5af9bdb 100644
+--- a/include/asm-x86/current_32.h
++++ b/include/asm-x86/current_32.h
+@@ -11,7 +11,7 @@ static __always_inline struct task_struct *get_current(void)
+ {
+ 	return x86_read_percpu(current_task);
+ }
+- 
++
+ #define current get_current()
+ 
+ #endif /* !(_I386_CURRENT_H) */
+diff --git a/include/asm-x86/current_64.h b/include/asm-x86/current_64.h
+index bc8adec..2d368ed 100644
+--- a/include/asm-x86/current_64.h
++++ b/include/asm-x86/current_64.h
+@@ -1,23 +1,23 @@
+ #ifndef _X86_64_CURRENT_H
+ #define _X86_64_CURRENT_H
+ 
+-#if !defined(__ASSEMBLY__) 
++#if !defined(__ASSEMBLY__)
+ struct task_struct;
+ 
+ #include <asm/pda.h>
+ 
+-static inline struct task_struct *get_current(void) 
+-{ 
+-	struct task_struct *t = read_pda(pcurrent); 
++static inline struct task_struct *get_current(void)
++{
++	struct task_struct *t = read_pda(pcurrent);
+ 	return t;
+-} 
++}
+ 
+ #define current get_current()
+ 
+ #else
+ 
+ #ifndef ASM_OFFSET_H
+-#include <asm/asm-offsets.h> 
++#include <asm/asm-offsets.h>
+ #endif
+ 
+ #define GET_CURRENT(reg) movq %gs:(pda_pcurrent),reg
+diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
+index 5b6a05d..268a012 100644
+--- a/include/asm-x86/desc.h
++++ b/include/asm-x86/desc.h
+@@ -62,8 +62,8 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+ }
+ 
+ static inline void pack_gate(gate_desc *gate, unsigned char type,
+-       unsigned long base, unsigned dpl, unsigned flags, unsigned short seg)
+-
++			     unsigned long base, unsigned dpl, unsigned flags,
++			     unsigned short seg)
+ {
+ 	gate->a = (seg << 16) | (base & 0xffff);
+ 	gate->b = (base & 0xffff0000) |
+@@ -84,22 +84,23 @@ static inline int desc_empty(const void *ptr)
+ #define load_TR_desc() native_load_tr_desc()
+ #define load_gdt(dtr) native_load_gdt(dtr)
+ #define load_idt(dtr) native_load_idt(dtr)
+-#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
++#define load_tr(tr) asm volatile("ltr %0"::"m" (tr))
++#define load_ldt(ldt) asm volatile("lldt %0"::"m" (ldt))
+ 
+ #define store_gdt(dtr) native_store_gdt(dtr)
+ #define store_idt(dtr) native_store_idt(dtr)
+ #define store_tr(tr) (tr = native_store_tr())
+-#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
++#define store_ldt(ldt) asm("sldt %0":"=m" (ldt))
+ 
+ #define load_TLS(t, cpu) native_load_tls(t, cpu)
+ #define set_ldt native_set_ldt
+ 
+-#define write_ldt_entry(dt, entry, desc) \
+-				native_write_ldt_entry(dt, entry, desc)
+-#define write_gdt_entry(dt, entry, desc, type) \
+-				native_write_gdt_entry(dt, entry, desc, type)
+-#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
++#define write_ldt_entry(dt, entry, desc)	\
++	native_write_ldt_entry(dt, entry, desc)
++#define write_gdt_entry(dt, entry, desc, type)		\
++	native_write_gdt_entry(dt, entry, desc, type)
++#define write_idt_entry(dt, entry, g)		\
++	native_write_idt_entry(dt, entry, g)
+ #endif
+ 
+ static inline void native_write_idt_entry(gate_desc *idt, int entry,
+@@ -138,8 +139,8 @@ static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
+ {
+ 	desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ 	desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+-		  (limit & 0x000f0000) | ((type & 0xff) << 8) |
+-		  ((flags & 0xf) << 20);
++		(limit & 0x000f0000) | ((type & 0xff) << 8) |
++		((flags & 0xf) << 20);
+ 	desc->p = 1;
+ }
+ 
+@@ -159,7 +160,6 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr,
+ 	desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF;
+ 	desc->base3 = PTR_HIGH(addr);
+ #else
+-
+ 	pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
+ #endif
+ }
+@@ -177,7 +177,8 @@ static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
+ 	 * last valid byte
+ 	 */
+ 	set_tssldt_descriptor(&tss, (unsigned long)addr, DESC_TSS,
+-		IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
++			      IO_BITMAP_OFFSET + IO_BITMAP_BYTES +
++			      sizeof(unsigned long) - 1);
+ 	write_gdt_entry(d, entry, &tss, DESC_TSS);
+ }
+ 
+@@ -186,7 +187,7 @@ static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
+ static inline void native_set_ldt(const void *addr, unsigned int entries)
+ {
+ 	if (likely(entries == 0))
+-		__asm__ __volatile__("lldt %w0"::"q" (0));
++		asm volatile("lldt %w0"::"q" (0));
+ 	else {
+ 		unsigned cpu = smp_processor_id();
+ 		ldt_desc ldt;
+@@ -195,7 +196,7 @@ static inline void native_set_ldt(const void *addr, unsigned int entries)
+ 				      DESC_LDT, entries * sizeof(ldt) - 1);
+ 		write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ 				&ldt, DESC_LDT);
+-		__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
++		asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ 	}
+ }
+ 
+@@ -240,15 +241,15 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+ 		gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+ }
+ 
+-#define _LDT_empty(info) (\
+-	(info)->base_addr	== 0	&& \
+-	(info)->limit		== 0	&& \
+-	(info)->contents	== 0	&& \
+-	(info)->read_exec_only	== 1	&& \
+-	(info)->seg_32bit	== 0	&& \
+-	(info)->limit_in_pages	== 0	&& \
+-	(info)->seg_not_present	== 1	&& \
+-	(info)->useable		== 0)
++#define _LDT_empty(info)				\
++	((info)->base_addr		== 0	&&	\
++	 (info)->limit			== 0	&&	\
++	 (info)->contents		== 0	&&	\
++	 (info)->read_exec_only		== 1	&&	\
++	 (info)->seg_32bit		== 0	&&	\
++	 (info)->limit_in_pages		== 0	&&	\
++	 (info)->seg_not_present	== 1	&&	\
++	 (info)->useable		== 0)
+ 
+ #ifdef CONFIG_X86_64
+ #define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+@@ -287,7 +288,7 @@ static inline unsigned long get_desc_limit(const struct desc_struct *desc)
+ }
+ 
+ static inline void _set_gate(int gate, unsigned type, void *addr,
+-			      unsigned dpl, unsigned ist, unsigned seg)
++			     unsigned dpl, unsigned ist, unsigned seg)
+ {
+ 	gate_desc s;
+ 	pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
+@@ -370,10 +371,10 @@ static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
+  *    Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+  */
+ #define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+-	movb idx*8+4(gdt), lo_b; \
+-	movb idx*8+7(gdt), hi_b; \
+-	shll $16, base; \
+-	movw idx*8+2(gdt), lo_w;
++	movb idx * 8 + 4(gdt), lo_b;			\
++	movb idx * 8 + 7(gdt), hi_b;			\
++	shll $16, base;					\
++	movw idx * 8 + 2(gdt), lo_w;
+ 
+ 
+ #endif /* __ASSEMBLY__ */
+diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
+index e33f078..eccb4ea 100644
+--- a/include/asm-x86/desc_defs.h
++++ b/include/asm-x86/desc_defs.h
+@@ -18,17 +18,19 @@
+  * incrementally. We keep the signature as a struct, rather than an union,
+  * so we can get rid of it transparently in the future -- glommer
+  */
+-// 8 byte segment descriptor
++/* 8 byte segment descriptor */
+ struct desc_struct {
+ 	union {
+-		struct { unsigned int a, b; };
++		struct {
++			unsigned int a;
++			unsigned int b;
++		};
+ 		struct {
+ 			u16 limit0;
+ 			u16 base0;
+ 			unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
+ 			unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
+ 		};
+-
+ 	};
+ } __attribute__((packed));
+ 
+@@ -39,7 +41,7 @@ enum {
+ 	GATE_TASK = 0x5,
+ };
+ 
+-// 16byte gate
++/* 16byte gate */
+ struct gate_struct64 {
+ 	u16 offset_low;
+ 	u16 segment;
+@@ -56,10 +58,10 @@ struct gate_struct64 {
+ enum {
+ 	DESC_TSS = 0x9,
+ 	DESC_LDT = 0x2,
+-	DESCTYPE_S =	0x10,	/* !system */
++	DESCTYPE_S = 0x10,	/* !system */
+ };
+ 
+-// LDT or TSS descriptor in the GDT. 16 bytes.
++/* LDT or TSS descriptor in the GDT. 16 bytes. */
+ struct ldttss_desc64 {
+ 	u16 limit0;
+ 	u16 base0;
+@@ -84,7 +86,6 @@ struct desc_ptr {
+ 	unsigned long address;
+ } __attribute__((packed)) ;
+ 
+-
+ #endif /* !__ASSEMBLY__ */
+ 
+ #endif
+diff --git a/include/asm-x86/div64.h b/include/asm-x86/div64.h
+index e98d16e..0dbf8bf 100644
+--- a/include/asm-x86/div64.h
++++ b/include/asm-x86/div64.h
+@@ -17,18 +17,20 @@
+  * This ends up being the most efficient "calling
+  * convention" on x86.
+  */
+-#define do_div(n,base) ({ \
+-	unsigned long __upper, __low, __high, __mod, __base; \
+-	__base = (base); \
+-	asm("":"=a" (__low), "=d" (__high):"A" (n)); \
+-	__upper = __high; \
+-	if (__high) { \
+-		__upper = __high % (__base); \
+-		__high = __high / (__base); \
+-	} \
+-	asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \
+-	asm("":"=A" (n):"a" (__low),"d" (__high)); \
+-	__mod; \
++#define do_div(n, base)						\
++({								\
++	unsigned long __upper, __low, __high, __mod, __base;	\
++	__base = (base);					\
++	asm("":"=a" (__low), "=d" (__high) : "A" (n));		\
++	__upper = __high;					\
++	if (__high) {						\
++		__upper = __high % (__base);			\
++		__high = __high / (__base);			\
++	}							\
++	asm("divl %2":"=a" (__low), "=d" (__mod)		\
++	    : "rm" (__base), "0" (__low), "1" (__upper));	\
++	asm("":"=A" (n) : "a" (__low), "d" (__high));		\
++	__mod;							\
+ })
+ 
+ /*
+@@ -37,14 +39,13 @@
+  *
+  * Warning, this will do an exception if X overflows.
+  */
+-#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c)
++#define div_long_long_rem(a, b, c) div_ll_X_l_rem(a, b, c)
+ 
+-static inline long
+-div_ll_X_l_rem(long long divs, long div, long *rem)
++static inline long div_ll_X_l_rem(long long divs, long div, long *rem)
+ {
+ 	long dum2;
+-      __asm__("divl %2":"=a"(dum2), "=d"(*rem)
+-      :	"rm"(div), "A"(divs));
++	asm("divl %2":"=a"(dum2), "=d"(*rem)
++	    : "rm"(div), "A"(divs));
+ 
+ 	return dum2;
+ 
+diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
+index 58f790f..a1a4dc7 100644
+--- a/include/asm-x86/dma-mapping.h
++++ b/include/asm-x86/dma-mapping.h
+@@ -1,5 +1,237 @@
++#ifndef _ASM_DMA_MAPPING_H_
++#define _ASM_DMA_MAPPING_H_
++
++/*
++ * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
++ * documentation.
++ */
++
++#include <linux/scatterlist.h>
++#include <asm/io.h>
++#include <asm/swiotlb.h>
++
++extern dma_addr_t bad_dma_address;
++extern int iommu_merge;
++extern struct device fallback_dev;
++extern int panic_on_overflow;
++extern int forbid_dac;
++extern int force_iommu;
++
++struct dma_mapping_ops {
++	int             (*mapping_error)(dma_addr_t dma_addr);
++	void*           (*alloc_coherent)(struct device *dev, size_t size,
++				dma_addr_t *dma_handle, gfp_t gfp);
++	void            (*free_coherent)(struct device *dev, size_t size,
++				void *vaddr, dma_addr_t dma_handle);
++	dma_addr_t      (*map_single)(struct device *hwdev, phys_addr_t ptr,
++				size_t size, int direction);
++	/* like map_single, but doesn't check the device mask */
++	dma_addr_t      (*map_simple)(struct device *hwdev, phys_addr_t ptr,
++				size_t size, int direction);
++	void            (*unmap_single)(struct device *dev, dma_addr_t addr,
++				size_t size, int direction);
++	void            (*sync_single_for_cpu)(struct device *hwdev,
++				dma_addr_t dma_handle, size_t size,
++				int direction);
++	void            (*sync_single_for_device)(struct device *hwdev,
++				dma_addr_t dma_handle, size_t size,
++				int direction);
++	void            (*sync_single_range_for_cpu)(struct device *hwdev,
++				dma_addr_t dma_handle, unsigned long offset,
++				size_t size, int direction);
++	void            (*sync_single_range_for_device)(struct device *hwdev,
++				dma_addr_t dma_handle, unsigned long offset,
++				size_t size, int direction);
++	void            (*sync_sg_for_cpu)(struct device *hwdev,
++				struct scatterlist *sg, int nelems,
++				int direction);
++	void            (*sync_sg_for_device)(struct device *hwdev,
++				struct scatterlist *sg, int nelems,
++				int direction);
++	int             (*map_sg)(struct device *hwdev, struct scatterlist *sg,
++				int nents, int direction);
++	void            (*unmap_sg)(struct device *hwdev,
++				struct scatterlist *sg, int nents,
++				int direction);
++	int             (*dma_supported)(struct device *hwdev, u64 mask);
++	int		is_phys;
++};
++
++extern const struct dma_mapping_ops *dma_ops;
++
++static inline int dma_mapping_error(dma_addr_t dma_addr)
++{
++	if (dma_ops->mapping_error)
++		return dma_ops->mapping_error(dma_addr);
++
++	return (dma_addr == bad_dma_address);
++}
++
++#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
++#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
++
++void *dma_alloc_coherent(struct device *dev, size_t size,
++			   dma_addr_t *dma_handle, gfp_t flag);
++
++void dma_free_coherent(struct device *dev, size_t size,
++			 void *vaddr, dma_addr_t dma_handle);
++
++
++extern int dma_supported(struct device *hwdev, u64 mask);
++extern int dma_set_mask(struct device *dev, u64 mask);
++
++static inline dma_addr_t
++dma_map_single(struct device *hwdev, void *ptr, size_t size,
++	       int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	return dma_ops->map_single(hwdev, virt_to_phys(ptr), size, direction);
++}
++
++static inline void
++dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size,
++		 int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	if (dma_ops->unmap_single)
++		dma_ops->unmap_single(dev, addr, size, direction);
++}
++
++static inline int
++dma_map_sg(struct device *hwdev, struct scatterlist *sg,
++	   int nents, int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	return dma_ops->map_sg(hwdev, sg, nents, direction);
++}
++
++static inline void
++dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
++	     int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	if (dma_ops->unmap_sg)
++		dma_ops->unmap_sg(hwdev, sg, nents, direction);
++}
++
++static inline void
++dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
++			size_t size, int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	if (dma_ops->sync_single_for_cpu)
++		dma_ops->sync_single_for_cpu(hwdev, dma_handle, size,
++					     direction);
++	flush_write_buffers();
++}
++
++static inline void
++dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
++			   size_t size, int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	if (dma_ops->sync_single_for_device)
++		dma_ops->sync_single_for_device(hwdev, dma_handle, size,
++						direction);
++	flush_write_buffers();
++}
++
++static inline void
++dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
++			      unsigned long offset, size_t size, int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	if (dma_ops->sync_single_range_for_cpu)
++		dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset,
++						   size, direction);
++
++	flush_write_buffers();
++}
++
++static inline void
++dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
++				 unsigned long offset, size_t size,
++				 int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	if (dma_ops->sync_single_range_for_device)
++		dma_ops->sync_single_range_for_device(hwdev, dma_handle,
++						      offset, size, direction);
++
++	flush_write_buffers();
++}
++
++static inline void
++dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
++		    int nelems, int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	if (dma_ops->sync_sg_for_cpu)
++		dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
++	flush_write_buffers();
++}
++
++static inline void
++dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
++		       int nelems, int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	if (dma_ops->sync_sg_for_device)
++		dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction);
++
++	flush_write_buffers();
++}
++
++static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
++				      size_t offset, size_t size,
++				      int direction)
++{
++	BUG_ON(!valid_dma_direction(direction));
++	return dma_ops->map_single(dev, page_to_phys(page)+offset,
++				   size, direction);
++}
++
++static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
++				  size_t size, int direction)
++{
++	dma_unmap_single(dev, addr, size, direction);
++}
++
++static inline void
++dma_cache_sync(struct device *dev, void *vaddr, size_t size,
++	enum dma_data_direction dir)
++{
++	flush_write_buffers();
++}
++
++static inline int dma_get_cache_alignment(void)
++{
++	/* no easy way to get cache size on all x86, so return the
++	 * maximum possible, to be safe */
++	return boot_cpu_data.x86_clflush_size;
++}
++
++#define dma_is_consistent(d, h)	(1)
++
+ #ifdef CONFIG_X86_32
+-# include "dma-mapping_32.h"
+-#else
+-# include "dma-mapping_64.h"
++#  define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
++struct dma_coherent_mem {
++	void		*virt_base;
++	u32		device_base;
++	int		size;
++	int		flags;
++	unsigned long	*bitmap;
++};
++
++extern int
++dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
++			    dma_addr_t device_addr, size_t size, int flags);
++
++extern void
++dma_release_declared_memory(struct device *dev);
++
++extern void *
++dma_mark_declared_memory_occupied(struct device *dev,
++				  dma_addr_t device_addr, size_t size);
++#endif /* CONFIG_X86_32 */
+ #endif
+diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
+deleted file mode 100644
+index 55f01bd..0000000
+--- a/include/asm-x86/dma-mapping_32.h
++++ /dev/null
+@@ -1,187 +0,0 @@
+-#ifndef _ASM_I386_DMA_MAPPING_H
+-#define _ASM_I386_DMA_MAPPING_H
+-
+-#include <linux/mm.h>
+-#include <linux/scatterlist.h>
+-
+-#include <asm/cache.h>
+-#include <asm/io.h>
+-#include <asm/bug.h>
+-
+-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+-
+-void *dma_alloc_coherent(struct device *dev, size_t size,
+-			   dma_addr_t *dma_handle, gfp_t flag);
+-
+-void dma_free_coherent(struct device *dev, size_t size,
+-			 void *vaddr, dma_addr_t dma_handle);
+-
+-static inline dma_addr_t
+-dma_map_single(struct device *dev, void *ptr, size_t size,
+-	       enum dma_data_direction direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	WARN_ON(size == 0);
+-	flush_write_buffers();
+-	return virt_to_phys(ptr);
+-}
+-
+-static inline void
+-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+-		 enum dma_data_direction direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-}
+-
+-static inline int
+-dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
+-	   enum dma_data_direction direction)
+-{
+-	struct scatterlist *sg;
+-	int i;
+-
+-	BUG_ON(!valid_dma_direction(direction));
+-	WARN_ON(nents == 0 || sglist[0].length == 0);
+-
+-	for_each_sg(sglist, sg, nents, i) {
+-		BUG_ON(!sg_page(sg));
+-
+-		sg->dma_address = sg_phys(sg);
+-	}
+-
+-	flush_write_buffers();
+-	return nents;
+-}
+-
+-static inline dma_addr_t
+-dma_map_page(struct device *dev, struct page *page, unsigned long offset,
+-	     size_t size, enum dma_data_direction direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	return page_to_phys(page) + offset;
+-}
+-
+-static inline void
+-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+-	       enum dma_data_direction direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-}
+-
+-
+-static inline void
+-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+-	     enum dma_data_direction direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-}
+-
+-static inline void
+-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+-			enum dma_data_direction direction)
+-{
+-}
+-
+-static inline void
+-dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
+-			enum dma_data_direction direction)
+-{
+-	flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+-			      unsigned long offset, size_t size,
+-			      enum dma_data_direction direction)
+-{
+-}
+-
+-static inline void
+-dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+-				 unsigned long offset, size_t size,
+-				 enum dma_data_direction direction)
+-{
+-	flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+-		    enum dma_data_direction direction)
+-{
+-}
+-
+-static inline void
+-dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+-		    enum dma_data_direction direction)
+-{
+-	flush_write_buffers();
+-}
+-
+-static inline int
+-dma_mapping_error(dma_addr_t dma_addr)
+-{
+-	return 0;
+-}
+-
+-extern int forbid_dac;
+-
+-static inline int
+-dma_supported(struct device *dev, u64 mask)
+-{
+-        /*
+-         * we fall back to GFP_DMA when the mask isn't all 1s,
+-         * so we can't guarantee allocations that must be
+-         * within a tighter range than GFP_DMA..
+-         */
+-        if(mask < 0x00ffffff)
+-                return 0;
+-
+-	/* Work around chipset bugs */
+-	if (forbid_dac > 0 && mask > 0xffffffffULL)
+-		return 0;
+-
+-	return 1;
+-}
+-
+-static inline int
+-dma_set_mask(struct device *dev, u64 mask)
+-{
+-	if(!dev->dma_mask || !dma_supported(dev, mask))
+-		return -EIO;
+-
+-	*dev->dma_mask = mask;
+-
+-	return 0;
+-}
+-
+-static inline int
+-dma_get_cache_alignment(void)
+-{
+-	/* no easy way to get cache size on all x86, so return the
+-	 * maximum possible, to be safe */
+-	return (1 << INTERNODE_CACHE_SHIFT);
+-}
+-
+-#define dma_is_consistent(d, h)	(1)
+-
+-static inline void
+-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+-	       enum dma_data_direction direction)
+-{
+-	flush_write_buffers();
+-}
+-
+-#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+-extern int
+-dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+-			    dma_addr_t device_addr, size_t size, int flags);
+-
+-extern void
+-dma_release_declared_memory(struct device *dev);
+-
+-extern void *
+-dma_mark_declared_memory_occupied(struct device *dev,
+-				  dma_addr_t device_addr, size_t size);
+-
+-#endif
+diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
+deleted file mode 100644
+index ecd0f61..0000000
+--- a/include/asm-x86/dma-mapping_64.h
++++ /dev/null
+@@ -1,202 +0,0 @@
+-#ifndef _X8664_DMA_MAPPING_H
+-#define _X8664_DMA_MAPPING_H 1
+-
+-/*
+- * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
+- * documentation.
+- */
+-
+-#include <linux/scatterlist.h>
+-#include <asm/io.h>
+-#include <asm/swiotlb.h>
+-
+-struct dma_mapping_ops {
+-	int             (*mapping_error)(dma_addr_t dma_addr);
+-	void*           (*alloc_coherent)(struct device *dev, size_t size,
+-                                dma_addr_t *dma_handle, gfp_t gfp);
+-	void            (*free_coherent)(struct device *dev, size_t size,
+-                                void *vaddr, dma_addr_t dma_handle);
+-	dma_addr_t      (*map_single)(struct device *hwdev, void *ptr,
+-                                size_t size, int direction);
+-	/* like map_single, but doesn't check the device mask */
+-	dma_addr_t      (*map_simple)(struct device *hwdev, char *ptr,
+-                                size_t size, int direction);
+-	void            (*unmap_single)(struct device *dev, dma_addr_t addr,
+-		                size_t size, int direction);
+-	void            (*sync_single_for_cpu)(struct device *hwdev,
+-		                dma_addr_t dma_handle, size_t size,
+-				int direction);
+-	void            (*sync_single_for_device)(struct device *hwdev,
+-                                dma_addr_t dma_handle, size_t size,
+-				int direction);
+-	void            (*sync_single_range_for_cpu)(struct device *hwdev,
+-                                dma_addr_t dma_handle, unsigned long offset,
+-		                size_t size, int direction);
+-	void            (*sync_single_range_for_device)(struct device *hwdev,
+-				dma_addr_t dma_handle, unsigned long offset,
+-		                size_t size, int direction);
+-	void            (*sync_sg_for_cpu)(struct device *hwdev,
+-                                struct scatterlist *sg, int nelems,
+-				int direction);
+-	void            (*sync_sg_for_device)(struct device *hwdev,
+-				struct scatterlist *sg, int nelems,
+-				int direction);
+-	int             (*map_sg)(struct device *hwdev, struct scatterlist *sg,
+-		                int nents, int direction);
+-	void            (*unmap_sg)(struct device *hwdev,
+-				struct scatterlist *sg, int nents,
+-				int direction);
+-	int             (*dma_supported)(struct device *hwdev, u64 mask);
+-	int		is_phys;
+-};
+-
+-extern dma_addr_t bad_dma_address;
+-extern const struct dma_mapping_ops* dma_ops;
+-extern int iommu_merge;
+-
+-static inline int dma_mapping_error(dma_addr_t dma_addr)
+-{
+-	if (dma_ops->mapping_error)
+-		return dma_ops->mapping_error(dma_addr);
+-
+-	return (dma_addr == bad_dma_address);
+-}
+-
+-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+-
+-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+-
+-extern void *dma_alloc_coherent(struct device *dev, size_t size,
+-				dma_addr_t *dma_handle, gfp_t gfp);
+-extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+-			      dma_addr_t dma_handle);
+-
+-static inline dma_addr_t
+-dma_map_single(struct device *hwdev, void *ptr, size_t size,
+-	       int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	return dma_ops->map_single(hwdev, ptr, size, direction);
+-}
+-
+-static inline void
+-dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
+-		 int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	dma_ops->unmap_single(dev, addr, size, direction);
+-}
+-
+-#define dma_map_page(dev,page,offset,size,dir) \
+-	dma_map_single((dev), page_address(page)+(offset), (size), (dir))
+-
+-#define dma_unmap_page dma_unmap_single
+-
+-static inline void
+-dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
+-			size_t size, int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	if (dma_ops->sync_single_for_cpu)
+-		dma_ops->sync_single_for_cpu(hwdev, dma_handle, size,
+-					     direction);
+-	flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
+-			   size_t size, int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	if (dma_ops->sync_single_for_device)
+-		dma_ops->sync_single_for_device(hwdev, dma_handle, size,
+-						direction);
+-	flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
+-			      unsigned long offset, size_t size, int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	if (dma_ops->sync_single_range_for_cpu) {
+-		dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset, size, direction);
+-	}
+-
+-	flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
+-				 unsigned long offset, size_t size, int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	if (dma_ops->sync_single_range_for_device)
+-		dma_ops->sync_single_range_for_device(hwdev, dma_handle,
+-						      offset, size, direction);
+-
+-	flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
+-		    int nelems, int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	if (dma_ops->sync_sg_for_cpu)
+-		dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
+-	flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
+-		       int nelems, int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	if (dma_ops->sync_sg_for_device) {
+-		dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction);
+-	}
+-
+-	flush_write_buffers();
+-}
+-
+-static inline int
+-dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	return dma_ops->map_sg(hwdev, sg, nents, direction);
+-}
+-
+-static inline void
+-dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
+-	     int direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	dma_ops->unmap_sg(hwdev, sg, nents, direction);
+-}
+-
+-extern int dma_supported(struct device *hwdev, u64 mask);
+-
+-/* same for gart, swiotlb, and nommu */
+-static inline int dma_get_cache_alignment(void)
+-{
+-	return boot_cpu_data.x86_clflush_size;
+-}
+-
+-#define dma_is_consistent(d, h) 1
+-
+-extern int dma_set_mask(struct device *dev, u64 mask);
+-
+-static inline void
+-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+-	enum dma_data_direction dir)
+-{
+-	flush_write_buffers();
+-}
+-
+-extern struct device fallback_dev;
+-extern int panic_on_overflow;
+-
+-#endif /* _X8664_DMA_MAPPING_H */
+diff --git a/include/asm-x86/dma.h b/include/asm-x86/dma.h
+index e9733ce..ca1098a 100644
+--- a/include/asm-x86/dma.h
++++ b/include/asm-x86/dma.h
+@@ -12,7 +12,6 @@
+ #include <asm/io.h>		/* need byte IO */
+ #include <linux/delay.h>
+ 
+-
+ #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
+ #define dma_outb	outb_p
+ #else
+@@ -74,15 +73,15 @@
+ #ifdef CONFIG_X86_32
+ 
+ /* The maximum address that we can perform a DMA transfer to on this platform */
+-#define MAX_DMA_ADDRESS      (PAGE_OFFSET+0x1000000)
++#define MAX_DMA_ADDRESS      (PAGE_OFFSET + 0x1000000)
+ 
+ #else
+ 
+ /* 16MB ISA DMA zone */
+-#define MAX_DMA_PFN   ((16*1024*1024) >> PAGE_SHIFT)
++#define MAX_DMA_PFN   ((16 * 1024 * 1024) >> PAGE_SHIFT)
+ 
+ /* 4GB broken PCI/AGP hardware bus master zone */
+-#define MAX_DMA32_PFN ((4UL*1024*1024*1024) >> PAGE_SHIFT)
++#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
+ 
+ /* Compat define for old dma zone */
+ #define MAX_DMA_ADDRESS ((unsigned long)__va(MAX_DMA_PFN << PAGE_SHIFT))
+@@ -154,20 +153,20 @@
+ 
+ extern spinlock_t  dma_spin_lock;
+ 
+-static __inline__ unsigned long claim_dma_lock(void)
++static inline unsigned long claim_dma_lock(void)
+ {
+ 	unsigned long flags;
+ 	spin_lock_irqsave(&dma_spin_lock, flags);
+ 	return flags;
+ }
+ 
+-static __inline__ void release_dma_lock(unsigned long flags)
++static inline void release_dma_lock(unsigned long flags)
+ {
+ 	spin_unlock_irqrestore(&dma_spin_lock, flags);
+ }
+ 
+ /* enable/disable a specific DMA channel */
+-static __inline__ void enable_dma(unsigned int dmanr)
++static inline void enable_dma(unsigned int dmanr)
+ {
+ 	if (dmanr <= 3)
+ 		dma_outb(dmanr, DMA1_MASK_REG);
+@@ -175,7 +174,7 @@ static __inline__ void enable_dma(unsigned int dmanr)
+ 		dma_outb(dmanr & 3, DMA2_MASK_REG);
+ }
+ 
+-static __inline__ void disable_dma(unsigned int dmanr)
++static inline void disable_dma(unsigned int dmanr)
+ {
+ 	if (dmanr <= 3)
+ 		dma_outb(dmanr | 4, DMA1_MASK_REG);
+@@ -190,7 +189,7 @@ static __inline__ void disable_dma(unsigned int dmanr)
+  * --- In order to do that, the DMA routines below should ---
+  * --- only be used while holding the DMA lock ! ---
+  */
+-static __inline__ void clear_dma_ff(unsigned int dmanr)
++static inline void clear_dma_ff(unsigned int dmanr)
+ {
+ 	if (dmanr <= 3)
+ 		dma_outb(0, DMA1_CLEAR_FF_REG);
+@@ -199,7 +198,7 @@ static __inline__ void clear_dma_ff(unsigned int dmanr)
+ }
+ 
+ /* set mode (above) for a specific DMA channel */
+-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
++static inline void set_dma_mode(unsigned int dmanr, char mode)
+ {
+ 	if (dmanr <= 3)
+ 		dma_outb(mode | dmanr, DMA1_MODE_REG);
+@@ -212,7 +211,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+  * the lower 16 bits of the DMA current address register, but a 64k boundary
+  * may have been crossed.
+  */
+-static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
++static inline void set_dma_page(unsigned int dmanr, char pagenr)
+ {
+ 	switch (dmanr) {
+ 	case 0:
+@@ -243,15 +242,15 @@ static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
+ /* Set transfer address & page bits for specific DMA channel.
+  * Assumes dma flipflop is clear.
+  */
+-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
++static inline void set_dma_addr(unsigned int dmanr, unsigned int a)
+ {
+ 	set_dma_page(dmanr, a>>16);
+ 	if (dmanr <= 3)  {
+ 		dma_outb(a & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE);
+ 		dma_outb((a >> 8) & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE);
+ 	}  else  {
+-	    dma_outb((a >> 1) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
+-	    dma_outb((a >> 9) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
++		dma_outb((a >> 1) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
++		dma_outb((a >> 9) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
+ 	}
+ }
+ 
+@@ -264,18 +263,18 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+  * Assumes dma flip-flop is clear.
+  * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
+  */
+-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
++static inline void set_dma_count(unsigned int dmanr, unsigned int count)
+ {
+ 	count--;
+ 	if (dmanr <= 3)  {
+-	    dma_outb(count & 0xff, ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
+-	    dma_outb((count >> 8) & 0xff,
+-		     ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
++		dma_outb(count & 0xff, ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
++		dma_outb((count >> 8) & 0xff,
++			 ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
+ 	} else {
+-	    dma_outb((count >> 1) & 0xff,
+-		     ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
+-	    dma_outb((count >> 9) & 0xff,
+-		     ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
++		dma_outb((count >> 1) & 0xff,
++			 ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
++		dma_outb((count >> 9) & 0xff,
++			 ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
+ 	}
+ }
+ 
+@@ -288,7 +287,7 @@ static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+  *
+  * Assumes DMA flip-flop is clear.
+  */
+-static __inline__ int get_dma_residue(unsigned int dmanr)
++static inline int get_dma_residue(unsigned int dmanr)
+ {
+ 	unsigned int io_port;
+ 	/* using short to get 16-bit wrap around */
+diff --git a/include/asm-x86/dwarf2_64.h b/include/asm-x86/dwarf2_64.h
+index eedc085..c950519 100644
+--- a/include/asm-x86/dwarf2_64.h
++++ b/include/asm-x86/dwarf2_64.h
+@@ -1,16 +1,15 @@
+ #ifndef _DWARF2_H
+ #define _DWARF2_H 1
+ 
+-
+ #ifndef __ASSEMBLY__
+ #warning "asm/dwarf2.h should be only included in pure assembly files"
+ #endif
+ 
+-/* 
++/*
+    Macros for dwarf2 CFI unwind table entries.
+-   See "as.info" for details on these pseudo ops. Unfortunately 
+-   they are only supported in very new binutils, so define them 
+-   away for older version. 
++   See "as.info" for details on these pseudo ops. Unfortunately
++   they are only supported in very new binutils, so define them
++   away for older version.
+  */
+ 
+ #ifdef CONFIG_AS_CFI
+diff --git a/include/asm-x86/e820_32.h b/include/asm-x86/e820_32.h
+index e7207a6..a9f7c6e 100644
+--- a/include/asm-x86/e820_32.h
++++ b/include/asm-x86/e820_32.h
+@@ -24,7 +24,7 @@ extern void update_e820(void);
+ extern int e820_all_mapped(unsigned long start, unsigned long end,
+ 			   unsigned type);
+ extern int e820_any_mapped(u64 start, u64 end, unsigned type);
+-extern void find_max_pfn(void);
++extern void propagate_e820_map(void);
+ extern void register_bootmem_low_pages(unsigned long max_low_pfn);
+ extern void add_memory_region(unsigned long long start,
+ 			      unsigned long long size, int type);
+@@ -34,8 +34,8 @@ extern void e820_register_memory(void);
+ extern void limit_regions(unsigned long long size);
+ extern void print_memory_map(char *who);
+ extern void init_iomem_resources(struct resource *code_resource,
+-			    struct resource *data_resource,
+-			    struct resource *bss_resource);
++				 struct resource *data_resource,
++				 struct resource *bss_resource);
+ 
+ #if defined(CONFIG_PM) && defined(CONFIG_HIBERNATION)
+ extern void e820_mark_nosave_regions(void);
+diff --git a/include/asm-x86/e820_64.h b/include/asm-x86/e820_64.h
+index 22ede73..f478c57 100644
+--- a/include/asm-x86/e820_64.h
++++ b/include/asm-x86/e820_64.h
+@@ -14,20 +14,24 @@
+ #include <linux/ioport.h>
+ 
+ #ifndef __ASSEMBLY__
+-extern unsigned long find_e820_area(unsigned long start, unsigned long end, 
+-				    unsigned size, unsigned long align);
+-extern void add_memory_region(unsigned long start, unsigned long size, 
++extern unsigned long find_e820_area(unsigned long start, unsigned long end,
++				    unsigned long size, unsigned long align);
++extern unsigned long find_e820_area_size(unsigned long start,
++					 unsigned long *sizep,
++					 unsigned long align);
++extern void add_memory_region(unsigned long start, unsigned long size,
+ 			      int type);
+ extern void update_memory_range(u64 start, u64 size, unsigned old_type,
+ 				unsigned new_type);
+ extern void setup_memory_region(void);
+-extern void contig_e820_setup(void); 
++extern void contig_e820_setup(void);
+ extern unsigned long e820_end_of_ram(void);
+-extern void e820_reserve_resources(struct resource *code_resource,
+-		struct resource *data_resource, struct resource *bss_resource);
++extern void e820_reserve_resources(void);
+ extern void e820_mark_nosave_regions(void);
+-extern int e820_any_mapped(unsigned long start, unsigned long end, unsigned type);
+-extern int e820_all_mapped(unsigned long start, unsigned long end, unsigned type);
++extern int e820_any_mapped(unsigned long start, unsigned long end,
++			   unsigned type);
++extern int e820_all_mapped(unsigned long start, unsigned long end,
++			   unsigned type);
+ extern int e820_any_non_reserved(unsigned long start, unsigned long end);
+ extern int is_memory_any_valid(unsigned long start, unsigned long end);
+ extern int e820_all_non_reserved(unsigned long start, unsigned long end);
+@@ -35,8 +39,8 @@ extern int is_memory_all_valid(unsigned long start, unsigned long end);
+ extern unsigned long e820_hole_size(unsigned long start, unsigned long end);
+ 
+ extern void e820_setup_gap(void);
+-extern void e820_register_active_regions(int nid,
+-				unsigned long start_pfn, unsigned long end_pfn);
++extern void e820_register_active_regions(int nid, unsigned long start_pfn,
++					 unsigned long end_pfn);
+ 
+ extern void finish_e820_parsing(void);
+ 
+diff --git a/include/asm-x86/edac.h b/include/asm-x86/edac.h
+index cf3200a..a8088f6 100644
+--- a/include/asm-x86/edac.h
++++ b/include/asm-x86/edac.h
+@@ -3,7 +3,7 @@
+ 
+ /* ECC atomic, DMA, SMP and interrupt safe scrub function */
+ 
+-static __inline__ void atomic_scrub(void *va, u32 size)
++static inline void atomic_scrub(void *va, u32 size)
+ {
+ 	u32 i, *virt_addr = va;
+ 
+@@ -12,7 +12,7 @@ static __inline__ void atomic_scrub(void *va, u32 size)
+ 	 * are interrupt, DMA and SMP safe.
+ 	 */
+ 	for (i = 0; i < size / 4; i++, virt_addr++)
+-		__asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr));
++		asm volatile("lock; addl $0, %0"::"m" (*virt_addr));
+ }
+ 
+ #endif
+diff --git a/include/asm-x86/efi.h b/include/asm-x86/efi.h
+index ea9734b..d53004b 100644
+--- a/include/asm-x86/efi.h
++++ b/include/asm-x86/efi.h
+@@ -20,7 +20,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
+  */
+ 
+ #define efi_call_virt(f, args...) \
+-     ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args)
++	((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args)
+ 
+ #define efi_call_virt0(f)		efi_call_virt(f)
+ #define efi_call_virt1(f, a1)		efi_call_virt(f, a1)
+diff --git a/include/asm-x86/elf.h b/include/asm-x86/elf.h
+index fb62f99..8f232dc 100644
+--- a/include/asm-x86/elf.h
++++ b/include/asm-x86/elf.h
+@@ -11,7 +11,7 @@
+ 
+ typedef unsigned long elf_greg_t;
+ 
+-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
++#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+ 
+ typedef struct user_i387_struct elf_fpregset_t;
+@@ -82,8 +82,9 @@ extern unsigned int vdso_enabled;
+ #define elf_check_arch_ia32(x) \
+ 	(((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
+ 
+-#ifdef CONFIG_X86_32
+ #include <asm/processor.h>
++
++#ifdef CONFIG_X86_32
+ #include <asm/system.h>		/* for savesegment */
+ #include <asm/desc.h>
+ 
+@@ -99,10 +100,11 @@ extern unsigned int vdso_enabled;
+    We might as well make sure everything else is cleared too (except for %esp),
+    just to make things more deterministic.
+  */
+-#define ELF_PLAT_INIT(_r, load_addr)	do { \
+-	_r->bx = 0; _r->cx = 0; _r->dx = 0; \
+-	_r->si = 0; _r->di = 0; _r->bp = 0; \
+-	_r->ax = 0; \
++#define ELF_PLAT_INIT(_r, load_addr)		\
++	do {					\
++	_r->bx = 0; _r->cx = 0; _r->dx = 0;	\
++	_r->si = 0; _r->di = 0; _r->bp = 0;	\
++	_r->ax = 0;				\
+ } while (0)
+ 
+ /*
+@@ -110,24 +112,25 @@ extern unsigned int vdso_enabled;
+  * now struct_user_regs, they are different)
+  */
+ 
+-#define ELF_CORE_COPY_REGS(pr_reg, regs) do {		\
+-	pr_reg[0] = regs->bx;				\
+-	pr_reg[1] = regs->cx;				\
+-	pr_reg[2] = regs->dx;				\
+-	pr_reg[3] = regs->si;				\
+-	pr_reg[4] = regs->di;				\
+-	pr_reg[5] = regs->bp;				\
+-	pr_reg[6] = regs->ax;				\
+-	pr_reg[7] = regs->ds & 0xffff;			\
+-	pr_reg[8] = regs->es & 0xffff;			\
+-	pr_reg[9] = regs->fs & 0xffff;			\
+-	savesegment(gs, pr_reg[10]);			\
+-	pr_reg[11] = regs->orig_ax;			\
+-	pr_reg[12] = regs->ip;				\
+-	pr_reg[13] = regs->cs & 0xffff;			\
+-	pr_reg[14] = regs->flags;			\
+-	pr_reg[15] = regs->sp;				\
+-	pr_reg[16] = regs->ss & 0xffff;			\
++#define ELF_CORE_COPY_REGS(pr_reg, regs)	\
++do {						\
++	pr_reg[0] = regs->bx;			\
++	pr_reg[1] = regs->cx;			\
++	pr_reg[2] = regs->dx;			\
++	pr_reg[3] = regs->si;			\
++	pr_reg[4] = regs->di;			\
++	pr_reg[5] = regs->bp;			\
++	pr_reg[6] = regs->ax;			\
++	pr_reg[7] = regs->ds & 0xffff;		\
++	pr_reg[8] = regs->es & 0xffff;		\
++	pr_reg[9] = regs->fs & 0xffff;		\
++	savesegment(gs, pr_reg[10]);		\
++	pr_reg[11] = regs->orig_ax;		\
++	pr_reg[12] = regs->ip;			\
++	pr_reg[13] = regs->cs & 0xffff;		\
++	pr_reg[14] = regs->flags;		\
++	pr_reg[15] = regs->sp;			\
++	pr_reg[16] = regs->ss & 0xffff;		\
+ } while (0);
+ 
+ #define ELF_PLATFORM	(utsname()->machine)
+@@ -135,12 +138,10 @@ extern unsigned int vdso_enabled;
+ 
+ #else /* CONFIG_X86_32 */
+ 
+-#include <asm/processor.h>
+-
+ /*
+  * This is used to ensure we don't load something for the wrong architecture.
+  */
+-#define elf_check_arch(x) \
++#define elf_check_arch(x)			\
+ 	((x)->e_machine == EM_X86_64)
+ 
+ #define compat_elf_check_arch(x)	elf_check_arch_ia32(x)
+@@ -169,24 +170,30 @@ static inline void elf_common_init(struct thread_struct *t,
+ 	t->ds = t->es = ds;
+ }
+ 
+-#define ELF_PLAT_INIT(_r, load_addr)	do {		  \
+-	elf_common_init(&current->thread, _r, 0);	  \
+-	clear_thread_flag(TIF_IA32);			  \
++#define ELF_PLAT_INIT(_r, load_addr)			\
++do {							\
++	elf_common_init(&current->thread, _r, 0);	\
++	clear_thread_flag(TIF_IA32);			\
+ } while (0)
+ 
+-#define	COMPAT_ELF_PLAT_INIT(regs, load_addr)	\
++#define	COMPAT_ELF_PLAT_INIT(regs, load_addr)		\
+ 	elf_common_init(&current->thread, regs, __USER_DS)
+-#define	compat_start_thread(regs, ip, sp)	do {		\
+-		start_ia32_thread(regs, ip, sp);		\
+-		set_fs(USER_DS);				\
+-	} while (0)
+-#define COMPAT_SET_PERSONALITY(ex, ibcs2)	do {		\
+-		if (test_thread_flag(TIF_IA32))			\
+-			clear_thread_flag(TIF_ABI_PENDING);	\
+-		else						\
+-			set_thread_flag(TIF_ABI_PENDING);	\
+-		current->personality |= force_personality32;	\
+-	} while (0)
++
++#define	compat_start_thread(regs, ip, sp)		\
++do {							\
++	start_ia32_thread(regs, ip, sp);		\
++	set_fs(USER_DS);				\
++} while (0)
++
++#define COMPAT_SET_PERSONALITY(ex, ibcs2)		\
++do {							\
++	if (test_thread_flag(TIF_IA32))			\
++		clear_thread_flag(TIF_ABI_PENDING);	\
++	else						\
++		set_thread_flag(TIF_ABI_PENDING);	\
++	current->personality |= force_personality32;	\
++} while (0)
++
+ #define COMPAT_ELF_PLATFORM			("i686")
+ 
+ /*
+@@ -195,7 +202,8 @@ static inline void elf_common_init(struct thread_struct *t,
+  * getting dumped.
+  */
+ 
+-#define ELF_CORE_COPY_REGS(pr_reg, regs)  do {			\
++#define ELF_CORE_COPY_REGS(pr_reg, regs)			\
++do {								\
+ 	unsigned v;						\
+ 	(pr_reg)[0] = (regs)->r15;				\
+ 	(pr_reg)[1] = (regs)->r14;				\
+@@ -269,10 +277,12 @@ extern int force_personality32;
+ 
+ struct task_struct;
+ 
+-#define	ARCH_DLINFO_IA32(vdso_enabled) \
+-do if (vdso_enabled) {							\
++#define	ARCH_DLINFO_IA32(vdso_enabled)					\
++do {									\
++	if (vdso_enabled) {						\
+ 		NEW_AUX_ENT(AT_SYSINFO,	VDSO_ENTRY);			\
+ 		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE);	\
++	}								\
+ } while (0)
+ 
+ #ifdef CONFIG_X86_32
+@@ -290,9 +300,11 @@ do if (vdso_enabled) {							\
+ /* 1GB for 64bit, 8MB for 32bit */
+ #define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
+ 
+-#define ARCH_DLINFO						\
+-do if (vdso_enabled) {						\
+-	NEW_AUX_ENT(AT_SYSINFO_EHDR,(unsigned long)current->mm->context.vdso);\
++#define ARCH_DLINFO							\
++do {									\
++	if (vdso_enabled)						\
++		NEW_AUX_ENT(AT_SYSINFO_EHDR,				\
++			    (unsigned long)current->mm->context.vdso);	\
+ } while (0)
+ 
+ #define AT_SYSINFO		32
+@@ -305,8 +317,8 @@ do if (vdso_enabled) {						\
+ 
+ #define VDSO_CURRENT_BASE	((unsigned long)current->mm->context.vdso)
+ 
+-#define VDSO_ENTRY \
+-	((unsigned long) VDSO32_SYMBOL(VDSO_CURRENT_BASE, vsyscall))
++#define VDSO_ENTRY							\
++	((unsigned long)VDSO32_SYMBOL(VDSO_CURRENT_BASE, vsyscall))
+ 
+ struct linux_binprm;
+ 
+diff --git a/include/asm-x86/fixmap.h b/include/asm-x86/fixmap.h
+index 382eb27..5bd2069 100644
+--- a/include/asm-x86/fixmap.h
++++ b/include/asm-x86/fixmap.h
+@@ -1,5 +1,13 @@
++#ifndef _ASM_FIXMAP_H
++#define _ASM_FIXMAP_H
++
+ #ifdef CONFIG_X86_32
+ # include "fixmap_32.h"
+ #else
+ # include "fixmap_64.h"
+ #endif
++
++#define clear_fixmap(idx)			\
++	__set_fixmap(idx, 0, __pgprot(0))
++
++#endif
+diff --git a/include/asm-x86/fixmap_32.h b/include/asm-x86/fixmap_32.h
+index a7404d5..4b96148 100644
+--- a/include/asm-x86/fixmap_32.h
++++ b/include/asm-x86/fixmap_32.h
+@@ -10,8 +10,8 @@
+  * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+  */
+ 
+-#ifndef _ASM_FIXMAP_H
+-#define _ASM_FIXMAP_H
++#ifndef _ASM_FIXMAP_32_H
++#define _ASM_FIXMAP_32_H
+ 
+ 
+ /* used by vmalloc.c, vsyscall.lds.S.
+@@ -99,8 +99,7 @@ enum fixed_addresses {
+ 	 */
+ #define NR_FIX_BTMAPS		64
+ #define FIX_BTMAPS_NESTING	4
+-	FIX_BTMAP_END =
+-		__end_of_permanent_fixed_addresses + 512 -
++	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 -
+ 			(__end_of_permanent_fixed_addresses & 511),
+ 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
+ 	FIX_WP_TEST,
+@@ -110,20 +109,17 @@ enum fixed_addresses {
+ 	__end_of_fixed_addresses
+ };
+ 
+-extern void __set_fixmap (enum fixed_addresses idx,
+-					unsigned long phys, pgprot_t flags);
++extern void __set_fixmap(enum fixed_addresses idx,
++			 unsigned long phys, pgprot_t flags);
+ extern void reserve_top_address(unsigned long reserve);
+ 
+-#define set_fixmap(idx, phys) \
+-		__set_fixmap(idx, phys, PAGE_KERNEL)
++#define set_fixmap(idx, phys)				\
++	__set_fixmap(idx, phys, PAGE_KERNEL)
+ /*
+  * Some hardware wants to get fixmapped without caching.
+  */
+-#define set_fixmap_nocache(idx, phys) \
+-		__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+-
+-#define clear_fixmap(idx) \
+-		__set_fixmap(idx, 0, __pgprot(0))
++#define set_fixmap_nocache(idx, phys)			\
++	__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+ 
+ #define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)
+ 
+@@ -156,7 +152,7 @@ static __always_inline unsigned long fix_to_virt(const unsigned int idx)
+ 	if (idx >= __end_of_fixed_addresses)
+ 		__this_fixmap_does_not_exist();
+ 
+-        return __fix_to_virt(idx);
++	return __fix_to_virt(idx);
+ }
+ 
+ static inline unsigned long virt_to_fix(const unsigned long vaddr)
+diff --git a/include/asm-x86/fixmap_64.h b/include/asm-x86/fixmap_64.h
+index 70ddb21..355d26a 100644
+--- a/include/asm-x86/fixmap_64.h
++++ b/include/asm-x86/fixmap_64.h
+@@ -8,8 +8,8 @@
+  * Copyright (C) 1998 Ingo Molnar
+  */
+ 
+-#ifndef _ASM_FIXMAP_H
+-#define _ASM_FIXMAP_H
++#ifndef _ASM_FIXMAP_64_H
++#define _ASM_FIXMAP_64_H
+ 
+ #include <linux/kernel.h>
+ #include <asm/apicdef.h>
+@@ -34,32 +34,34 @@
+ 
+ enum fixed_addresses {
+ 	VSYSCALL_LAST_PAGE,
+-	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
++	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
++			    + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
+ 	VSYSCALL_HPET,
+ 	FIX_DBGP_BASE,
+ 	FIX_EARLYCON_MEM_BASE,
+ 	FIX_HPET_BASE,
+ 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+ 	FIX_IO_APIC_BASE_0,
+-	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
++	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
+ 	FIX_EFI_IO_MAP_LAST_PAGE,
+-	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE+MAX_EFI_IO_PAGES-1,
++	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE
++				  + MAX_EFI_IO_PAGES - 1,
+ #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+ 	FIX_OHCI1394_BASE,
+ #endif
+ 	__end_of_fixed_addresses
+ };
+ 
+-extern void __set_fixmap (enum fixed_addresses idx,
+-					unsigned long phys, pgprot_t flags);
++extern void __set_fixmap(enum fixed_addresses idx,
++			 unsigned long phys, pgprot_t flags);
+ 
+-#define set_fixmap(idx, phys) \
+-		__set_fixmap(idx, phys, PAGE_KERNEL)
++#define set_fixmap(idx, phys)			\
++	__set_fixmap(idx, phys, PAGE_KERNEL)
+ /*
+  * Some hardware wants to get fixmapped without caching.
+  */
+-#define set_fixmap_nocache(idx, phys) \
+-		__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
++#define set_fixmap_nocache(idx, phys)			\
++	__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+ 
+ #define FIXADDR_TOP	(VSYSCALL_END-PAGE_SIZE)
+ #define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+diff --git a/include/asm-x86/floppy.h b/include/asm-x86/floppy.h
+index a48d715..dbe82a5 100644
+--- a/include/asm-x86/floppy.h
++++ b/include/asm-x86/floppy.h
+@@ -20,20 +20,21 @@
+  * driver otherwise. It doesn't matter much for performance anyway, as most
+  * floppy accesses go through the track buffer.
+  */
+-#define _CROSS_64KB(a,s,vdma) \
+-(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
++#define _CROSS_64KB(a, s, vdma)						\
++	(!(vdma) &&							\
++	 ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
+ 
+-#define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
++#define CROSS_64KB(a, s) _CROSS_64KB(a, s, use_virtual_dma & 1)
+ 
+ 
+-#define SW fd_routine[use_virtual_dma&1]
++#define SW fd_routine[use_virtual_dma & 1]
+ #define CSW fd_routine[can_use_virtual_dma & 1]
+ 
+ 
+ #define fd_inb(port)		inb_p(port)
+-#define fd_outb(value,port)	outb_p(value,port)
++#define fd_outb(value, port)	outb_p(value, port)
+ 
+-#define fd_request_dma()	CSW._request_dma(FLOPPY_DMA,"floppy")
++#define fd_request_dma()	CSW._request_dma(FLOPPY_DMA, "floppy")
+ #define fd_free_dma()		CSW._free_dma(FLOPPY_DMA)
+ #define fd_enable_irq()		enable_irq(FLOPPY_IRQ)
+ #define fd_disable_irq()	disable_irq(FLOPPY_IRQ)
+@@ -52,64 +53,64 @@ static int doing_pdma;
+ 
+ static irqreturn_t floppy_hardint(int irq, void *dev_id)
+ {
+-	register unsigned char st;
++	unsigned char st;
+ 
+ #undef TRACE_FLPY_INT
+ 
+ #ifdef TRACE_FLPY_INT
+-	static int calls=0;
+-	static int bytes=0;
+-	static int dma_wait=0;
++	static int calls;
++	static int bytes;
++	static int dma_wait;
+ #endif
+ 	if (!doing_pdma)
+ 		return floppy_interrupt(irq, dev_id);
+ 
+ #ifdef TRACE_FLPY_INT
+-	if(!calls)
++	if (!calls)
+ 		bytes = virtual_dma_count;
+ #endif
+ 
+ 	{
+-		register int lcount;
+-		register char *lptr;
++		int lcount;
++		char *lptr;
+ 
+ 		st = 1;
+-		for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
+-		    lcount; lcount--, lptr++) {
+-			st=inb(virtual_dma_port+4) & 0xa0 ;
+-			if(st != 0xa0)
++		for (lcount = virtual_dma_count, lptr = virtual_dma_addr;
++		     lcount; lcount--, lptr++) {
++			st = inb(virtual_dma_port + 4) & 0xa0;
++			if (st != 0xa0)
+ 				break;
+-			if(virtual_dma_mode)
+-				outb_p(*lptr, virtual_dma_port+5);
++			if (virtual_dma_mode)
++				outb_p(*lptr, virtual_dma_port + 5);
+ 			else
+-				*lptr = inb_p(virtual_dma_port+5);
++				*lptr = inb_p(virtual_dma_port + 5);
+ 		}
+ 		virtual_dma_count = lcount;
+ 		virtual_dma_addr = lptr;
+-		st = inb(virtual_dma_port+4);
++		st = inb(virtual_dma_port + 4);
+ 	}
+ 
+ #ifdef TRACE_FLPY_INT
+ 	calls++;
+ #endif
+-	if(st == 0x20)
++	if (st == 0x20)
+ 		return IRQ_HANDLED;
+-	if(!(st & 0x20)) {
++	if (!(st & 0x20)) {
+ 		virtual_dma_residue += virtual_dma_count;
+-		virtual_dma_count=0;
++		virtual_dma_count = 0;
+ #ifdef TRACE_FLPY_INT
+ 		printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
+ 		       virtual_dma_count, virtual_dma_residue, calls, bytes,
+ 		       dma_wait);
+ 		calls = 0;
+-		dma_wait=0;
++		dma_wait = 0;
+ #endif
+ 		doing_pdma = 0;
+ 		floppy_interrupt(irq, dev_id);
+ 		return IRQ_HANDLED;
+ 	}
+ #ifdef TRACE_FLPY_INT
+-	if(!virtual_dma_count)
++	if (!virtual_dma_count)
+ 		dma_wait++;
+ #endif
+ 	return IRQ_HANDLED;
+@@ -117,14 +118,14 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id)
+ 
+ static void fd_disable_dma(void)
+ {
+-	if(! (can_use_virtual_dma & 1))
++	if (!(can_use_virtual_dma & 1))
+ 		disable_dma(FLOPPY_DMA);
+ 	doing_pdma = 0;
+ 	virtual_dma_residue += virtual_dma_count;
+-	virtual_dma_count=0;
++	virtual_dma_count = 0;
+ }
+ 
+-static int vdma_request_dma(unsigned int dmanr, const char * device_id)
++static int vdma_request_dma(unsigned int dmanr, const char *device_id)
+ {
+ 	return 0;
+ }
+@@ -142,7 +143,7 @@ static int vdma_get_dma_residue(unsigned int dummy)
+ 
+ static int fd_request_irq(void)
+ {
+-	if(can_use_virtual_dma)
++	if (can_use_virtual_dma)
+ 		return request_irq(FLOPPY_IRQ, floppy_hardint,
+ 				   IRQF_DISABLED, "floppy", NULL);
+ 	else
+@@ -152,13 +153,13 @@ static int fd_request_irq(void)
+ 
+ static unsigned long dma_mem_alloc(unsigned long size)
+ {
+-	return __get_dma_pages(GFP_KERNEL|__GFP_NORETRY,get_order(size));
++	return __get_dma_pages(GFP_KERNEL|__GFP_NORETRY, get_order(size));
+ }
+ 
+ 
+ static unsigned long vdma_mem_alloc(unsigned long size)
+ {
+-	return (unsigned long) vmalloc(size);
++	return (unsigned long)vmalloc(size);
+ 
+ }
+ 
+@@ -166,7 +167,7 @@ static unsigned long vdma_mem_alloc(unsigned long size)
+ 
+ static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
+ {
+-	if((unsigned long) addr >= (unsigned long) high_memory)
++	if ((unsigned long)addr >= (unsigned long)high_memory)
+ 		vfree((void *)addr);
+ 	else
+ 		free_pages(addr, get_order(size));
+@@ -176,10 +177,10 @@ static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
+ 
+ static void _fd_chose_dma_mode(char *addr, unsigned long size)
+ {
+-	if(can_use_virtual_dma == 2) {
+-		if((unsigned long) addr >= (unsigned long) high_memory ||
+-		   isa_virt_to_bus(addr) >= 0x1000000 ||
+-		   _CROSS_64KB(addr, size, 0))
++	if (can_use_virtual_dma == 2) {
++		if ((unsigned long)addr >= (unsigned long)high_memory ||
++		    isa_virt_to_bus(addr) >= 0x1000000 ||
++		    _CROSS_64KB(addr, size, 0))
+ 			use_virtual_dma = 1;
+ 		else
+ 			use_virtual_dma = 0;
+@@ -195,7 +196,7 @@ static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
+ {
+ 	doing_pdma = 1;
+ 	virtual_dma_port = io;
+-	virtual_dma_mode = (mode  == DMA_MODE_WRITE);
++	virtual_dma_mode = (mode == DMA_MODE_WRITE);
+ 	virtual_dma_addr = addr;
+ 	virtual_dma_count = size;
+ 	virtual_dma_residue = 0;
+@@ -213,18 +214,18 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
+ 	/* actual, physical DMA */
+ 	doing_pdma = 0;
+ 	clear_dma_ff(FLOPPY_DMA);
+-	set_dma_mode(FLOPPY_DMA,mode);
+-	set_dma_addr(FLOPPY_DMA,isa_virt_to_bus(addr));
+-	set_dma_count(FLOPPY_DMA,size);
++	set_dma_mode(FLOPPY_DMA, mode);
++	set_dma_addr(FLOPPY_DMA, isa_virt_to_bus(addr));
++	set_dma_count(FLOPPY_DMA, size);
+ 	enable_dma(FLOPPY_DMA);
+ 	return 0;
+ }
+ 
+ static struct fd_routine_l {
+-	int (*_request_dma)(unsigned int dmanr, const char * device_id);
++	int (*_request_dma)(unsigned int dmanr, const char *device_id);
+ 	void (*_free_dma)(unsigned int dmanr);
+ 	int (*_get_dma_residue)(unsigned int dummy);
+-	unsigned long (*_dma_mem_alloc) (unsigned long size);
++	unsigned long (*_dma_mem_alloc)(unsigned long size);
+ 	int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
+ } fd_routine[] = {
+ 	{
+@@ -252,7 +253,8 @@ static int FDC2 = -1;
+  * is needed to prevent corrupted CMOS RAM in case "insmod floppy"
+  * coincides with another rtc CMOS user.		Paul G.
+  */
+-#define FLOPPY0_TYPE	({				\
++#define FLOPPY0_TYPE					\
++({							\
+ 	unsigned long flags;				\
+ 	unsigned char val;				\
+ 	spin_lock_irqsave(&rtc_lock, flags);		\
+@@ -261,7 +263,8 @@ static int FDC2 = -1;
+ 	val;						\
+ })
+ 
+-#define FLOPPY1_TYPE	({				\
++#define FLOPPY1_TYPE					\
++({							\
+ 	unsigned long flags;				\
+ 	unsigned char val;				\
+ 	spin_lock_irqsave(&rtc_lock, flags);		\
+diff --git a/include/asm-x86/futex.h b/include/asm-x86/futex.h
+index c9952ea..ac0fbf2 100644
+--- a/include/asm-x86/futex.h
++++ b/include/asm-x86/futex.h
+@@ -12,35 +12,32 @@
+ #include <asm/uaccess.h>
+ 
+ #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg)	\
+-  __asm__ __volatile(						\
+-"1:	" insn "\n"						\
+-"2:	.section .fixup,\"ax\"\n				\
+-3:	mov	%3, %1\n					\
+-	jmp	2b\n						\
+-	.previous\n"						\
+-	_ASM_EXTABLE(1b,3b)					\
+-	: "=r" (oldval), "=r" (ret), "+m" (*uaddr)		\
+-	: "i" (-EFAULT), "0" (oparg), "1" (0))
++	asm volatile("1:\t" insn "\n"				\
++		     "2:\t.section .fixup,\"ax\"\n"		\
++		     "3:\tmov\t%3, %1\n"			\
++		     "\tjmp\t2b\n"				\
++		     "\t.previous\n"				\
++		     _ASM_EXTABLE(1b, 3b)			\
++		     : "=r" (oldval), "=r" (ret), "+m" (*uaddr)	\
++		     : "i" (-EFAULT), "0" (oparg), "1" (0))
+ 
+ #define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg)	\
+-  __asm__ __volatile(						\
+-"1:	movl	%2, %0\n					\
+-	movl	%0, %3\n"					\
+-	insn "\n"						\
+-"2:	lock; cmpxchgl %3, %2\n					\
+-	jnz	1b\n						\
+-3:	.section .fixup,\"ax\"\n				\
+-4:	mov	%5, %1\n					\
+-	jmp	3b\n						\
+-	.previous\n"						\
+-	_ASM_EXTABLE(1b,4b)					\
+-	_ASM_EXTABLE(2b,4b)					\
+-	: "=&a" (oldval), "=&r" (ret), "+m" (*uaddr),		\
+-	  "=&r" (tem)						\
+-	: "r" (oparg), "i" (-EFAULT), "1" (0))
+-
+-static inline int
+-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
++	asm volatile("1:\tmovl	%2, %0\n"			\
++		     "\tmovl\t%0, %3\n"				\
++		     "\t" insn "\n"				\
++		     "2:\tlock; cmpxchgl %3, %2\n"		\
++		     "\tjnz\t1b\n"				\
++		     "3:\t.section .fixup,\"ax\"\n"		\
++		     "4:\tmov\t%5, %1\n"			\
++		     "\tjmp\t3b\n"				\
++		     "\t.previous\n"				\
++		     _ASM_EXTABLE(1b, 4b)			\
++		     _ASM_EXTABLE(2b, 4b)			\
++		     : "=&a" (oldval), "=&r" (ret),		\
++		       "+m" (*uaddr), "=&r" (tem)		\
++		     : "r" (oparg), "i" (-EFAULT), "1" (0))
++
++static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+ {
+ 	int op = (encoded_op >> 28) & 7;
+ 	int cmp = (encoded_op >> 24) & 15;
+@@ -87,20 +84,33 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+ 
+ 	if (!ret) {
+ 		switch (cmp) {
+-		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+-		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+-		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+-		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+-		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+-		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+-		default: ret = -ENOSYS;
++		case FUTEX_OP_CMP_EQ:
++			ret = (oldval == cmparg);
++			break;
++		case FUTEX_OP_CMP_NE:
++			ret = (oldval != cmparg);
++			break;
++		case FUTEX_OP_CMP_LT:
++			ret = (oldval < cmparg);
++			break;
++		case FUTEX_OP_CMP_GE:
++			ret = (oldval >= cmparg);
++			break;
++		case FUTEX_OP_CMP_LE:
++			ret = (oldval <= cmparg);
++			break;
++		case FUTEX_OP_CMP_GT:
++			ret = (oldval > cmparg);
++			break;
++		default:
++			ret = -ENOSYS;
+ 		}
+ 	}
+ 	return ret;
+ }
+ 
+-static inline int
+-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
++static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
++						int newval)
+ {
+ 
+ #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
+@@ -112,16 +122,15 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+ 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ 		return -EFAULT;
+ 
+-	__asm__ __volatile__(
+-		"1:	lock; cmpxchgl %3, %1			\n"
+-		"2:	.section .fixup, \"ax\"			\n"
+-		"3:	mov     %2, %0				\n"
+-		"	jmp     2b				\n"
+-		"	.previous				\n"
+-		_ASM_EXTABLE(1b,3b)
+-		: "=a" (oldval), "+m" (*uaddr)
+-		: "i" (-EFAULT), "r" (newval), "0" (oldval)
+-		: "memory"
++	asm volatile("1:\tlock; cmpxchgl %3, %1\n"
++		     "2:\t.section .fixup, \"ax\"\n"
++		     "3:\tmov     %2, %0\n"
++		     "\tjmp     2b\n"
++		     "\t.previous\n"
++		     _ASM_EXTABLE(1b, 3b)
++		     : "=a" (oldval), "+m" (*uaddr)
++		     : "i" (-EFAULT), "r" (newval), "0" (oldval)
++		     : "memory"
+ 	);
+ 
+ 	return oldval;
+diff --git a/include/asm-x86/genapic_32.h b/include/asm-x86/genapic_32.h
+index 33e3ffe..b02ea6e 100644
+--- a/include/asm-x86/genapic_32.h
++++ b/include/asm-x86/genapic_32.h
+@@ -14,23 +14,22 @@
+  * Copyright 2003 Andi Kleen, SuSE Labs.
+  */
+ 
+-struct mpc_config_translation;
+ struct mpc_config_bus;
+ struct mp_config_table;
+ struct mpc_config_processor;
+ 
+-struct genapic { 
+-	char *name; 
+-	int (*probe)(void); 
++struct genapic {
++	char *name;
++	int (*probe)(void);
+ 
+ 	int (*apic_id_registered)(void);
+ 	cpumask_t (*target_cpus)(void);
+ 	int int_delivery_mode;
+-	int int_dest_mode; 
++	int int_dest_mode;
+ 	int ESR_DISABLE;
+ 	int apic_destination_logical;
+ 	unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid);
+-	unsigned long (*check_apicid_present)(int apicid); 
++	unsigned long (*check_apicid_present)(int apicid);
+ 	int no_balance_irq;
+ 	int no_ioapic_check;
+ 	void (*init_apic_ldr)(void);
+@@ -38,28 +37,21 @@ struct genapic {
+ 
+ 	void (*setup_apic_routing)(void);
+ 	int (*multi_timer_check)(int apic, int irq);
+-	int (*apicid_to_node)(int logical_apicid); 
++	int (*apicid_to_node)(int logical_apicid);
+ 	int (*cpu_to_logical_apicid)(int cpu);
+ 	int (*cpu_present_to_apicid)(int mps_cpu);
+ 	physid_mask_t (*apicid_to_cpu_present)(int phys_apicid);
+-	int (*mpc_apic_id)(struct mpc_config_processor *m, 
+-			   struct mpc_config_translation *t); 
+-	void (*setup_portio_remap)(void); 
++	void (*setup_portio_remap)(void);
+ 	int (*check_phys_apicid_present)(int boot_cpu_physical_apicid);
+ 	void (*enable_apic_mode)(void);
+ 	u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb);
+ 
+ 	/* mpparse */
+-	void (*mpc_oem_bus_info)(struct mpc_config_bus *, char *, 
+-				 struct mpc_config_translation *);
+-	void (*mpc_oem_pci_bus)(struct mpc_config_bus *, 
+-				struct mpc_config_translation *); 
+-
+ 	/* When one of the next two hooks returns 1 the genapic
+-	   is switched to this. Essentially they are additional probe 
++	   is switched to this. Essentially they are additional probe
+ 	   functions. */
+-	int (*mps_oem_check)(struct mp_config_table *mpc, char *oem, 
+-			      char *productid);
++	int (*mps_oem_check)(struct mp_config_table *mpc, char *oem,
++			     char *productid);
+ 	int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
+ 
+ 	unsigned (*get_apic_id)(unsigned long x);
+@@ -72,7 +64,7 @@ struct genapic {
+ 	void (*send_IPI_allbutself)(int vector);
+ 	void (*send_IPI_all)(int vector);
+ #endif
+-}; 
++};
+ 
+ #define APICFUNC(x) .x = x,
+ 
+@@ -85,43 +77,47 @@ struct genapic {
+ #define IPIFUNC(x)
+ #endif
+ 
+-#define APIC_INIT(aname, aprobe) { \
+-	.name = aname, \
+-	.probe = aprobe, \
+-	.int_delivery_mode = INT_DELIVERY_MODE, \
+-	.int_dest_mode = INT_DEST_MODE, \
+-	.no_balance_irq = NO_BALANCE_IRQ, \
+-	.ESR_DISABLE = esr_disable, \
+-	.apic_destination_logical = APIC_DEST_LOGICAL, \
+-	APICFUNC(apic_id_registered) \
+-	APICFUNC(target_cpus) \
+-	APICFUNC(check_apicid_used) \
+-	APICFUNC(check_apicid_present) \
+-	APICFUNC(init_apic_ldr) \
+-	APICFUNC(ioapic_phys_id_map) \
+-	APICFUNC(setup_apic_routing) \
+-	APICFUNC(multi_timer_check) \
+-	APICFUNC(apicid_to_node) \
+-	APICFUNC(cpu_to_logical_apicid) \
+-	APICFUNC(cpu_present_to_apicid) \
+-	APICFUNC(apicid_to_cpu_present) \
+-	APICFUNC(mpc_apic_id) \
+-	APICFUNC(setup_portio_remap) \
+-	APICFUNC(check_phys_apicid_present) \
+-	APICFUNC(mpc_oem_bus_info) \
+-	APICFUNC(mpc_oem_pci_bus) \
+-	APICFUNC(mps_oem_check) \
+-	APICFUNC(get_apic_id) \
+-	.apic_id_mask = APIC_ID_MASK, \
+-	APICFUNC(cpu_mask_to_apicid) \
+-	APICFUNC(acpi_madt_oem_check) \
+-	IPIFUNC(send_IPI_mask) \
+-	IPIFUNC(send_IPI_allbutself) \
+-	IPIFUNC(send_IPI_all) \
+-	APICFUNC(enable_apic_mode) \
+-	APICFUNC(phys_pkg_id) \
+-	}
++#define APIC_INIT(aname, aprobe)			\
++{							\
++	.name = aname,					\
++	.probe = aprobe,				\
++	.int_delivery_mode = INT_DELIVERY_MODE,		\
++	.int_dest_mode = INT_DEST_MODE,			\
++	.no_balance_irq = NO_BALANCE_IRQ,		\
++	.ESR_DISABLE = esr_disable,			\
++	.apic_destination_logical = APIC_DEST_LOGICAL,	\
++	APICFUNC(apic_id_registered)			\
++	APICFUNC(target_cpus)				\
++	APICFUNC(check_apicid_used)			\
++	APICFUNC(check_apicid_present)			\
++	APICFUNC(init_apic_ldr)				\
++	APICFUNC(ioapic_phys_id_map)			\
++	APICFUNC(setup_apic_routing)			\
++	APICFUNC(multi_timer_check)			\
++	APICFUNC(apicid_to_node)			\
++	APICFUNC(cpu_to_logical_apicid)			\
++	APICFUNC(cpu_present_to_apicid)			\
++	APICFUNC(apicid_to_cpu_present)			\
++	APICFUNC(setup_portio_remap)			\
++	APICFUNC(check_phys_apicid_present)		\
++	APICFUNC(mps_oem_check)				\
++	APICFUNC(get_apic_id)				\
++	.apic_id_mask = APIC_ID_MASK,			\
++	APICFUNC(cpu_mask_to_apicid)			\
++	APICFUNC(acpi_madt_oem_check)			\
++	IPIFUNC(send_IPI_mask)				\
++	IPIFUNC(send_IPI_allbutself)			\
++	IPIFUNC(send_IPI_all)				\
++	APICFUNC(enable_apic_mode)			\
++	APICFUNC(phys_pkg_id)				\
++}
+ 
+ extern struct genapic *genapic;
+ 
++enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC};
++#define get_uv_system_type()		UV_NONE
++#define is_uv_system()			0
++#define uv_wakeup_secondary(a, b)	1
++
++
+ #endif
+diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h
+index d7e516c..1de931b 100644
+--- a/include/asm-x86/genapic_64.h
++++ b/include/asm-x86/genapic_64.h
+@@ -33,5 +33,15 @@ extern struct genapic *genapic;
+ 
+ extern struct genapic apic_flat;
+ extern struct genapic apic_physflat;
++extern int acpi_madt_oem_check(char *, char *);
++
++enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC};
++extern enum uv_system_type get_uv_system_type(void);
++extern int is_uv_system(void);
++
++extern struct genapic apic_x2apic_uv_x;
++DECLARE_PER_CPU(int, x2apic_extra_bits);
++extern void uv_cpu_init(void);
++extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip);
+ 
+ #endif
+diff --git a/include/asm-x86/geode.h b/include/asm-x86/geode.h
+index 9e72800..9870cc1 100644
+--- a/include/asm-x86/geode.h
++++ b/include/asm-x86/geode.h
+@@ -167,7 +167,7 @@ static inline int is_geode(void)
+ /* MFGPTs */
+ 
+ #define MFGPT_MAX_TIMERS	8
+-#define MFGPT_TIMER_ANY		-1
++#define MFGPT_TIMER_ANY		(-1)
+ 
+ #define MFGPT_DOMAIN_WORKING	1
+ #define MFGPT_DOMAIN_STANDBY	2
+diff --git a/include/asm-x86/highmem.h b/include/asm-x86/highmem.h
+index 479767c..e153f3b 100644
+--- a/include/asm-x86/highmem.h
++++ b/include/asm-x86/highmem.h
+@@ -8,7 +8,7 @@
+  *		      Gerhard.Wichert at pdb.siemens.de
+  *
+  *
+- * Redesigned the x86 32-bit VM architecture to deal with 
++ * Redesigned the x86 32-bit VM architecture to deal with
+  * up to 16 Terabyte physical memory. With current x86 CPUs
+  * we now support up to 64 Gigabytes physical RAM.
+  *
+diff --git a/include/asm-x86/hw_irq_64.h b/include/asm-x86/hw_irq_64.h
+index 312a58d..0062ef3 100644
+--- a/include/asm-x86/hw_irq_64.h
++++ b/include/asm-x86/hw_irq_64.h
+@@ -36,7 +36,7 @@
+  * cleanup after irq migration.
+  */
+ #define IRQ_MOVE_CLEANUP_VECTOR	FIRST_EXTERNAL_VECTOR
+- 
++
+ /*
+  * Vectors 0x30-0x3f are used for ISA interrupts.
+  */
+@@ -159,13 +159,12 @@ extern atomic_t irq_mis_count;
+  *	SMP has a few special interrupts for IPI messages
+  */
+ 
+-#define BUILD_IRQ(nr) \
+-asmlinkage void IRQ_NAME(nr); \
+-__asm__( \
+-"\n.p2align\n" \
+-"IRQ" #nr "_interrupt:\n\t" \
+-	"push $~(" #nr ") ; " \
+-	"jmp common_interrupt");
++#define BUILD_IRQ(nr)				\
++	asmlinkage void IRQ_NAME(nr);		\
++	asm("\n.p2align\n"			\
++	    "IRQ" #nr "_interrupt:\n\t"		\
++	    "push $~(" #nr ") ; "		\
++	    "jmp common_interrupt");
+ 
+ #define platform_legacy_irq(irq)	((irq) < 16)
+ 
+diff --git a/include/asm-x86/hypertransport.h b/include/asm-x86/hypertransport.h
+index c16c6ff..d2bbd23 100644
+--- a/include/asm-x86/hypertransport.h
++++ b/include/asm-x86/hypertransport.h
+@@ -8,12 +8,14 @@
+ #define HT_IRQ_LOW_BASE			0xf8000000
+ 
+ #define HT_IRQ_LOW_VECTOR_SHIFT		16
+-#define  HT_IRQ_LOW_VECTOR_MASK		0x00ff0000
+-#define  HT_IRQ_LOW_VECTOR(v)		(((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK)
++#define HT_IRQ_LOW_VECTOR_MASK		0x00ff0000
++#define HT_IRQ_LOW_VECTOR(v)						\
++	(((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK)
+ 
+ #define HT_IRQ_LOW_DEST_ID_SHIFT	8
+-#define  HT_IRQ_LOW_DEST_ID_MASK	0x0000ff00
+-#define  HT_IRQ_LOW_DEST_ID(v)		(((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK)
++#define HT_IRQ_LOW_DEST_ID_MASK		0x0000ff00
++#define HT_IRQ_LOW_DEST_ID(v)						\
++	(((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK)
+ 
+ #define HT_IRQ_LOW_DM_PHYSICAL		0x0000000
+ #define HT_IRQ_LOW_DM_LOGICAL		0x0000040
+@@ -36,7 +38,8 @@
+ 
+ 
+ #define HT_IRQ_HIGH_DEST_ID_SHIFT	0
+-#define  HT_IRQ_HIGH_DEST_ID_MASK	0x00ffffff
+-#define  HT_IRQ_HIGH_DEST_ID(v)		((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK)
++#define HT_IRQ_HIGH_DEST_ID_MASK	0x00ffffff
++#define HT_IRQ_HIGH_DEST_ID(v)						\
++	((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK)
+ 
+ #endif /* ASM_HYPERTRANSPORT_H */
+diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h
+index f377b76..da2adb4 100644
+--- a/include/asm-x86/i387.h
++++ b/include/asm-x86/i387.h
+@@ -21,8 +21,9 @@
+ 
+ extern void fpu_init(void);
+ extern void mxcsr_feature_mask_init(void);
+-extern void init_fpu(struct task_struct *child);
++extern int init_fpu(struct task_struct *child);
+ extern asmlinkage void math_state_restore(void);
++extern void init_thread_xstate(void);
+ 
+ extern user_regset_active_fn fpregs_active, xfpregs_active;
+ extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get;
+@@ -41,7 +42,7 @@ static inline void tolerant_fwait(void)
+ {
+ 	asm volatile("1: fwait\n"
+ 		     "2:\n"
+-		     _ASM_EXTABLE(1b,2b));
++		     _ASM_EXTABLE(1b, 2b));
+ }
+ 
+ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
+@@ -54,7 +55,7 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
+ 		     "3:  movl $-1,%[err]\n"
+ 		     "    jmp  2b\n"
+ 		     ".previous\n"
+-		     _ASM_EXTABLE(1b,3b)
++		     _ASM_EXTABLE(1b, 3b)
+ 		     : [err] "=r" (err)
+ #if 0 /* See comment in __save_init_fpu() below. */
+ 		     : [fx] "r" (fx), "m" (*fx), "0" (0));
+@@ -76,11 +77,11 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
+ static inline void clear_fpu_state(struct i387_fxsave_struct *fx)
+ {
+ 	if (unlikely(fx->swd & X87_FSW_ES))
+-		 asm volatile("fnclex");
++		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);
++			  "    emms\n"		/* clear stack tags */
++			  "    fildl %%gs:0",	/* load to clear state */
++			  X86_FEATURE_FXSAVE_LEAK);
+ }
+ 
+ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
+@@ -93,14 +94,15 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
+ 		     "3:  movl $-1,%[err]\n"
+ 		     "    jmp  2b\n"
+ 		     ".previous\n"
+-		     _ASM_EXTABLE(1b,3b)
++		     _ASM_EXTABLE(1b, 3b)
+ 		     : [err] "=r" (err), "=m" (*fx)
+ #if 0 /* See comment in __fxsave_clear() below. */
+ 		     : [fx] "r" (fx), "0" (0));
+ #else
+ 		     : [fx] "cdaSDb" (fx), "0" (0));
+ #endif
+-	if (unlikely(err) && __clear_user(fx, sizeof(struct i387_fxsave_struct)))
++	if (unlikely(err) &&
++	    __clear_user(fx, sizeof(struct i387_fxsave_struct)))
+ 		err = -EFAULT;
+ 	/* No need to clear here because the caller clears USED_MATH */
+ 	return err;
+@@ -116,24 +118,22 @@ static inline void __save_init_fpu(struct task_struct *tsk)
+ 	/* Using "fxsaveq %0" would be the ideal choice, but is only supported
+ 	   starting with gas 2.16. */
+ 	__asm__ __volatile__("fxsaveq %0"
+-			     : "=m" (tsk->thread.i387.fxsave));
++			     : "=m" (tsk->thread.xstate->fxsave));
+ #elif 0
+ 	/* 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" (tsk->thread.i387.fxsave));
++			     : "=m" (tsk->thread.xstate->fxsave));
+ #else
+ 	/* 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 %P2(%1)"
+-			     : "=m" (tsk->thread.i387.fxsave)
+-			     : "cdaSDb" (tsk),
+-				"i" (offsetof(__typeof__(*tsk),
+-					      thread.i387.fxsave)));
++	__asm__ __volatile__("rex64/fxsave (%1)"
++			     : "=m" (tsk->thread.xstate->fxsave)
++			     : "cdaSDb" (&tsk->thread.xstate->fxsave));
+ #endif
+-	clear_fpu_state(&tsk->thread.i387.fxsave);
++	clear_fpu_state(&tsk->thread.xstate->fxsave);
+ 	task_thread_info(tsk)->status &= ~TS_USEDFPU;
+ }
+ 
+@@ -147,7 +147,7 @@ static inline int save_i387(struct _fpstate __user *buf)
+ 	int err = 0;
+ 
+ 	BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
+-			sizeof(tsk->thread.i387.fxsave));
++			sizeof(tsk->thread.xstate->fxsave));
+ 
+ 	if ((unsigned long)buf % 16)
+ 		printk("save_i387: bad fpstate %p\n", buf);
+@@ -156,12 +156,14 @@ static inline int save_i387(struct _fpstate __user *buf)
+ 		return 0;
+ 	clear_used_math(); /* trigger finit */
+ 	if (task_thread_info(tsk)->status & TS_USEDFPU) {
+-		err = save_i387_checking((struct i387_fxsave_struct __user *)buf);
+-		if (err) return err;
++		err = save_i387_checking((struct i387_fxsave_struct __user *)
++					 buf);
++		if (err)
++			return err;
+ 		task_thread_info(tsk)->status &= ~TS_USEDFPU;
+ 		stts();
+ 	} else {
+-		if (__copy_to_user(buf, &tsk->thread.i387.fxsave,
++		if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
+ 				   sizeof(struct i387_fxsave_struct)))
+ 			return -1;
+ 	}
+@@ -198,7 +200,7 @@ static inline void restore_fpu(struct task_struct *tsk)
+ 		"nop ; frstor %1",
+ 		"fxrstor %1",
+ 		X86_FEATURE_FXSR,
+-		"m" ((tsk)->thread.i387.fxsave));
++		"m" (tsk->thread.xstate->fxsave));
+ }
+ 
+ /* We need a safe address that is cheap to find and that is already
+@@ -222,8 +224,8 @@ static inline void __save_init_fpu(struct task_struct *tsk)
+ 		"fxsave %[fx]\n"
+ 		"bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
+ 		X86_FEATURE_FXSR,
+-		[fx] "m" (tsk->thread.i387.fxsave),
+-		[fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory");
++		[fx] "m" (tsk->thread.xstate->fxsave),
++		[fsw] "m" (tsk->thread.xstate->fxsave.swd) : "memory");
+ 	/* 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 */
+@@ -324,25 +326,25 @@ static inline void clear_fpu(struct task_struct *tsk)
+ static inline unsigned short get_fpu_cwd(struct task_struct *tsk)
+ {
+ 	if (cpu_has_fxsr) {
+-		return tsk->thread.i387.fxsave.cwd;
++		return tsk->thread.xstate->fxsave.cwd;
+ 	} else {
+-		return (unsigned short)tsk->thread.i387.fsave.cwd;
++		return (unsigned short)tsk->thread.xstate->fsave.cwd;
+ 	}
+ }
+ 
+ static inline unsigned short get_fpu_swd(struct task_struct *tsk)
+ {
+ 	if (cpu_has_fxsr) {
+-		return tsk->thread.i387.fxsave.swd;
++		return tsk->thread.xstate->fxsave.swd;
+ 	} else {
+-		return (unsigned short)tsk->thread.i387.fsave.swd;
++		return (unsigned short)tsk->thread.xstate->fsave.swd;
+ 	}
+ }
+ 
+ static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk)
+ {
+ 	if (cpu_has_xmm) {
+-		return tsk->thread.i387.fxsave.mxcsr;
++		return tsk->thread.xstate->fxsave.mxcsr;
+ 	} else {
+ 		return MXCSR_DEFAULT;
+ 	}
+diff --git a/include/asm-x86/i8259.h b/include/asm-x86/i8259.h
+index 67c319e..45d4df3 100644
+--- a/include/asm-x86/i8259.h
++++ b/include/asm-x86/i8259.h
+@@ -1,9 +1,11 @@
+ #ifndef __ASM_I8259_H__
+ #define __ASM_I8259_H__
+ 
++#include <linux/delay.h>
++
+ extern unsigned int cached_irq_mask;
+ 
+-#define __byte(x,y)		(((unsigned char *) &(y))[x])
++#define __byte(x, y)		(((unsigned char *)&(y))[x])
+ #define cached_master_mask	(__byte(0, cached_irq_mask))
+ #define cached_slave_mask	(__byte(1, cached_irq_mask))
+ 
+@@ -29,7 +31,28 @@ extern void enable_8259A_irq(unsigned int irq);
+ extern void disable_8259A_irq(unsigned int irq);
+ extern unsigned int startup_8259A_irq(unsigned int irq);
+ 
+-#define inb_pic		inb_p
+-#define outb_pic	outb_p
++/* the PIC may need a careful delay on some platforms, hence specific calls */
++static inline unsigned char inb_pic(unsigned int port)
++{
++	unsigned char value = inb(port);
++
++	/*
++	 * delay for some accesses to PIC on motherboard or in chipset
++	 * must be at least one microsecond, so be safe here:
++	 */
++	udelay(2);
++
++	return value;
++}
++
++static inline void outb_pic(unsigned char value, unsigned int port)
++{
++	outb(value, port);
++	/*
++	 * delay for some accesses to PIC on motherboard or in chipset
++	 * must be at least one microsecond, so be safe here:
++	 */
++	udelay(2);
++}
+ 
+ #endif	/* __ASM_I8259_H__ */
+diff --git a/include/asm-x86/ia32.h b/include/asm-x86/ia32.h
+index aa97332..55d3abe 100644
+--- a/include/asm-x86/ia32.h
++++ b/include/asm-x86/ia32.h
+@@ -14,19 +14,19 @@
+ 
+ /* signal.h */
+ struct sigaction32 {
+-       unsigned int  sa_handler;	/* Really a pointer, but need to deal 
+-					     with 32 bits */
+-       unsigned int sa_flags;
+-       unsigned int sa_restorer;	/* Another 32 bit pointer */
+-       compat_sigset_t sa_mask;		/* A 32 bit mask */
++	unsigned int  sa_handler;	/* Really a pointer, but need to deal
++					   with 32 bits */
++	unsigned int sa_flags;
++	unsigned int sa_restorer;	/* Another 32 bit pointer */
++	compat_sigset_t sa_mask;	/* A 32 bit mask */
+ };
+ 
+ struct old_sigaction32 {
+-       unsigned int  sa_handler;	/* Really a pointer, but need to deal 
+-					     with 32 bits */
+-       compat_old_sigset_t sa_mask;		/* A 32 bit mask */
+-       unsigned int sa_flags;
+-       unsigned int sa_restorer;	/* Another 32 bit pointer */
++	unsigned int  sa_handler;	/* Really a pointer, but need to deal
++					   with 32 bits */
++	compat_old_sigset_t sa_mask;	/* A 32 bit mask */
++	unsigned int sa_flags;
++	unsigned int sa_restorer;	/* Another 32 bit pointer */
+ };
+ 
+ typedef struct sigaltstack_ia32 {
+@@ -65,7 +65,7 @@ struct stat64 {
+ 	long long		st_size;
+ 	unsigned int		st_blksize;
+ 
+-	long long		st_blocks;/* Number 512-byte blocks allocated. */
++	long long		st_blocks;/* Number 512-byte blocks allocated */
+ 
+ 	unsigned 		st_atime;
+ 	unsigned 		st_atime_nsec;
+@@ -77,13 +77,13 @@ struct stat64 {
+ 	unsigned long long	st_ino;
+ } __attribute__((packed));
+ 
+-typedef struct compat_siginfo{
++typedef struct compat_siginfo {
+ 	int si_signo;
+ 	int si_errno;
+ 	int si_code;
+ 
+ 	union {
+-		int _pad[((128/sizeof(int)) - 3)];
++		int _pad[((128 / sizeof(int)) - 3)];
+ 
+ 		/* kill() */
+ 		struct {
+@@ -129,28 +129,26 @@ typedef struct compat_siginfo{
+ 	} _sifields;
+ } compat_siginfo_t;
+ 
+-struct sigframe32
+-{
+-        u32 pretcode;
+-        int sig;
+-        struct sigcontext_ia32 sc;
+-        struct _fpstate_ia32 fpstate;
+-        unsigned int extramask[_COMPAT_NSIG_WORDS-1];
++struct sigframe32 {
++	u32 pretcode;
++	int sig;
++	struct sigcontext_ia32 sc;
++	struct _fpstate_ia32 fpstate;
++	unsigned int extramask[_COMPAT_NSIG_WORDS-1];
+ };
+ 
+-struct rt_sigframe32
+-{
+-        u32 pretcode;
+-        int sig;
+-        u32 pinfo;
+-        u32 puc;
+-        compat_siginfo_t info;
+-        struct ucontext_ia32 uc;
+-        struct _fpstate_ia32 fpstate;
++struct rt_sigframe32 {
++	u32 pretcode;
++	int sig;
++	u32 pinfo;
++	u32 puc;
++	compat_siginfo_t info;
++	struct ucontext_ia32 uc;
++	struct _fpstate_ia32 fpstate;
+ };
+ 
+ struct ustat32 {
+-	__u32	f_tfree;
++	__u32			f_tfree;
+ 	compat_ino_t		f_tinode;
+ 	char			f_fname[6];
+ 	char			f_fpack[6];
+@@ -168,5 +166,5 @@ extern void ia32_pick_mmap_layout(struct mm_struct *mm);
+ #endif
+ 
+ #endif /* !CONFIG_IA32_SUPPORT */
+- 
+-#endif 
++
++#endif
+diff --git a/include/asm-x86/ide.h b/include/asm-x86/ide.h
+index c2552d8..cf9c98e 100644
+--- a/include/asm-x86/ide.h
++++ b/include/asm-x86/ide.h
+@@ -20,8 +20,6 @@
+ # endif
+ #endif
+ 
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static __inline__ int ide_default_irq(unsigned long base)
+ {
+ 	switch (base) {
+@@ -60,14 +58,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
+ 	}
+ }
+ 
+-#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-#define ide_init_default_irq(base)	(0)
+-#else
+-#define ide_init_default_irq(base)	ide_default_irq(base)
+-#endif
+-
+ #include <asm-generic/ide_iops.h>
+ 
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-x86/io.h b/include/asm-x86/io.h
+index 5a58b17..d5b11f6 100644
+--- a/include/asm-x86/io.h
++++ b/include/asm-x86/io.h
+@@ -1,5 +1,19 @@
++#ifndef _ASM_X86_IO_H
++#define _ASM_X86_IO_H
++
++#define ARCH_HAS_IOREMAP_WC
++
+ #ifdef CONFIG_X86_32
+ # include "io_32.h"
+ #else
+ # include "io_64.h"
+ #endif
++
++extern void *xlate_dev_mem_ptr(unsigned long phys);
++extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
++
++extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
++				unsigned long prot_val);
++extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size);
++
++#endif /* _ASM_X86_IO_H */
+diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
+index d4d8fbd..6e73467 100644
+--- a/include/asm-x86/io_32.h
++++ b/include/asm-x86/io_32.h
+@@ -49,12 +49,6 @@
+ #include <linux/vmalloc.h>
+ 
+ /*
+- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+- * access
+- */
+-#define xlate_dev_mem_ptr(p)	__va(p)
+-
+-/*
+  * Convert a virtual cached pointer to an uncached pointer
+  */
+ #define xlate_dev_kmem_ptr(p)	p
+@@ -65,14 +59,14 @@
+  *
+  *	The returned physical address is the physical (CPU) mapping for
+  *	the memory address given. It is only valid to use this function on
+- *	addresses directly mapped or allocated via kmalloc. 
++ *	addresses directly mapped or allocated via kmalloc.
+  *
+  *	This function does not give bus mappings for DMA transfers. In
+  *	almost all conceivable cases a device driver should not be using
+  *	this function
+  */
+- 
+-static inline unsigned long virt_to_phys(volatile void * address)
++
++static inline unsigned long virt_to_phys(volatile void *address)
+ {
+ 	return __pa(address);
+ }
+@@ -90,7 +84,7 @@ static inline unsigned long virt_to_phys(volatile void * address)
+  *	this function
+  */
+ 
+-static inline void * phys_to_virt(unsigned long address)
++static inline void *phys_to_virt(unsigned long address)
+ {
+ 	return __va(address);
+ }
+@@ -169,16 +163,19 @@ extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
+ 
+ static inline unsigned char readb(const volatile void __iomem *addr)
+ {
+-	return *(volatile unsigned char __force *) addr;
++	return *(volatile unsigned char __force *)addr;
+ }
++
+ static inline unsigned short readw(const volatile void __iomem *addr)
+ {
+-	return *(volatile unsigned short __force *) addr;
++	return *(volatile unsigned short __force *)addr;
+ }
++
+ static inline unsigned int readl(const volatile void __iomem *addr)
+ {
+ 	return *(volatile unsigned int __force *) addr;
+ }
++
+ #define readb_relaxed(addr) readb(addr)
+ #define readw_relaxed(addr) readw(addr)
+ #define readl_relaxed(addr) readl(addr)
+@@ -188,15 +185,17 @@ static inline unsigned int readl(const volatile void __iomem *addr)
+ 
+ static inline void writeb(unsigned char b, volatile void __iomem *addr)
+ {
+-	*(volatile unsigned char __force *) addr = b;
++	*(volatile unsigned char __force *)addr = b;
+ }
++
+ static inline void writew(unsigned short b, volatile void __iomem *addr)
+ {
+-	*(volatile unsigned short __force *) addr = b;
++	*(volatile unsigned short __force *)addr = b;
+ }
++
+ static inline void writel(unsigned int b, volatile void __iomem *addr)
+ {
+-	*(volatile unsigned int __force *) addr = b;
++	*(volatile unsigned int __force *)addr = b;
+ }
+ #define __raw_writeb writeb
+ #define __raw_writew writew
+@@ -239,12 +238,12 @@ memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+  *	1. Out of order aware processors
+  *	2. Accidentally out of order processors (PPro errata #51)
+  */
+- 
++
+ #if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)
+ 
+ static inline void flush_write_buffers(void)
+ {
+-	__asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory");
++	asm volatile("lock; addl $0,0(%%esp)": : :"memory");
+ }
+ 
+ #else
+@@ -264,7 +263,8 @@ extern void io_delay_init(void);
+ #include <asm/paravirt.h>
+ #else
+ 
+-static inline void slow_down_io(void) {
++static inline void slow_down_io(void)
++{
+ 	native_io_delay();
+ #ifdef REALLY_SLOW_IO
+ 	native_io_delay();
+@@ -275,51 +275,74 @@ static inline void slow_down_io(void) {
+ 
+ #endif
+ 
+-#define __BUILDIO(bwl,bw,type) \
+-static inline void out##bwl(unsigned type value, int port) { \
+-	out##bwl##_local(value, port); \
+-} \
+-static inline unsigned type in##bwl(int port) { \
+-	return in##bwl##_local(port); \
++#define __BUILDIO(bwl, bw, type)				\
++static inline void out##bwl(unsigned type value, int port)	\
++{								\
++	out##bwl##_local(value, port);				\
++}								\
++								\
++static inline unsigned type in##bwl(int port)			\
++{								\
++	return in##bwl##_local(port);				\
+ }
+ 
+-#define BUILDIO(bwl,bw,type) \
+-static inline void out##bwl##_local(unsigned type value, int port) { \
+-	__asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \
+-} \
+-static inline unsigned type in##bwl##_local(int port) { \
+-	unsigned type value; \
+-	__asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \
+-	return value; \
+-} \
+-static inline void out##bwl##_local_p(unsigned type value, int port) { \
+-	out##bwl##_local(value, port); \
+-	slow_down_io(); \
+-} \
+-static inline unsigned type in##bwl##_local_p(int port) { \
+-	unsigned type value = in##bwl##_local(port); \
+-	slow_down_io(); \
+-	return value; \
+-} \
+-__BUILDIO(bwl,bw,type) \
+-static inline void out##bwl##_p(unsigned type value, int port) { \
+-	out##bwl(value, port); \
+-	slow_down_io(); \
+-} \
+-static inline unsigned type in##bwl##_p(int port) { \
+-	unsigned type value = in##bwl(port); \
+-	slow_down_io(); \
+-	return value; \
+-} \
+-static inline void outs##bwl(int port, const void *addr, unsigned long count) { \
+-	__asm__ __volatile__("rep; outs" #bwl : "+S"(addr), "+c"(count) : "d"(port)); \
+-} \
+-static inline void ins##bwl(int port, void *addr, unsigned long count) { \
+-	__asm__ __volatile__("rep; ins" #bwl : "+D"(addr), "+c"(count) : "d"(port)); \
++#define BUILDIO(bwl, bw, type)						\
++static inline void out##bwl##_local(unsigned type value, int port)	\
++{									\
++	asm volatile("out" #bwl " %" #bw "0, %w1"		\
++		     : : "a"(value), "Nd"(port));			\
++}									\
++									\
++static inline unsigned type in##bwl##_local(int port)			\
++{									\
++	unsigned type value;						\
++	asm volatile("in" #bwl " %w1, %" #bw "0"		\
++		     : "=a"(value) : "Nd"(port));			\
++	return value;							\
++}									\
++									\
++static inline void out##bwl##_local_p(unsigned type value, int port)	\
++{									\
++	out##bwl##_local(value, port);					\
++	slow_down_io();							\
++}									\
++									\
++static inline unsigned type in##bwl##_local_p(int port)			\
++{									\
++	unsigned type value = in##bwl##_local(port);			\
++	slow_down_io();							\
++	return value;							\
++}									\
++									\
++__BUILDIO(bwl, bw, type)						\
++									\
++static inline void out##bwl##_p(unsigned type value, int port)		\
++{									\
++	out##bwl(value, port);						\
++	slow_down_io();							\
++}									\
++									\
++static inline unsigned type in##bwl##_p(int port)			\
++{									\
++	unsigned type value = in##bwl(port);				\
++	slow_down_io();							\
++	return value;							\
++}									\
++									\
++static inline void outs##bwl(int port, const void *addr, unsigned long count) \
++{									\
++	asm volatile("rep; outs" #bwl					\
++		     : "+S"(addr), "+c"(count) : "d"(port));		\
++}									\
++									\
++static inline void ins##bwl(int port, void *addr, unsigned long count)	\
++{									\
++	asm volatile("rep; ins" #bwl					\
++		     : "+D"(addr), "+c"(count) : "d"(port));		\
+ }
+ 
+-BUILDIO(b,b,char)
+-BUILDIO(w,w,short)
+-BUILDIO(l,,int)
++BUILDIO(b, b, char)
++BUILDIO(w, w, short)
++BUILDIO(l, , int)
+ 
+ #endif
+diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
+index db0be20..0930bed 100644
+--- a/include/asm-x86/io_64.h
++++ b/include/asm-x86/io_64.h
+@@ -58,60 +58,75 @@ static inline void slow_down_io(void)
+ /*
+  * Talk about misusing macros..
+  */
+-#define __OUT1(s,x) \
++#define __OUT1(s, x)							\
+ static inline void out##s(unsigned x value, unsigned short port) {
+ 
+-#define __OUT2(s,s1,s2) \
+-__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
++#define __OUT2(s, s1, s2)				\
++asm volatile ("out" #s " %" s1 "0,%" s2 "1"
+ 
+ #ifndef REALLY_SLOW_IO
+ #define REALLY_SLOW_IO
+ #define UNSET_REALLY_SLOW_IO
+ #endif
+ 
+-#define __OUT(s,s1,x) \
+-__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
+-__OUT1(s##_p, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port)); \
+-		slow_down_io(); }
++#define __OUT(s, s1, x)							\
++	__OUT1(s, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port));	\
++	}								\
++	__OUT1(s##_p, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port)); \
++	slow_down_io();							\
++}
+ 
+-#define __IN1(s) \
+-static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
++#define __IN1(s)							\
++static inline RETURN_TYPE in##s(unsigned short port)			\
++{									\
++	RETURN_TYPE _v;
+ 
+-#define __IN2(s,s1,s2) \
+-__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
++#define __IN2(s, s1, s2)						\
++	asm volatile ("in" #s " %" s2 "1,%" s1 "0"
+ 
+-#define __IN(s,s1,i...) \
+-__IN1(s) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i); return _v; } \
+-__IN1(s##_p) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i);	  \
+-				slow_down_io(); return _v; }
++#define __IN(s, s1, i...)						\
++	__IN1(s) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i);	\
++	return _v;							\
++	}								\
++	__IN1(s##_p) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i);	\
++	slow_down_io(); \
++	return _v; }
+ 
+ #ifdef UNSET_REALLY_SLOW_IO
+ #undef REALLY_SLOW_IO
+ #endif
+ 
+-#define __INS(s) \
+-static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+-{ __asm__ __volatile__ ("rep ; ins" #s \
+-: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
++#define __INS(s)							\
++static inline void ins##s(unsigned short port, void *addr,		\
++			  unsigned long count)				\
++{									\
++	asm volatile ("rep ; ins" #s					\
++		      : "=D" (addr), "=c" (count)			\
++		      : "d" (port), "0" (addr), "1" (count));		\
++}
+ 
+-#define __OUTS(s) \
+-static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
+-{ __asm__ __volatile__ ("rep ; outs" #s \
+-: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
++#define __OUTS(s)							\
++static inline void outs##s(unsigned short port, const void *addr,	\
++			   unsigned long count)				\
++{									\
++	asm volatile ("rep ; outs" #s					\
++		      : "=S" (addr), "=c" (count)			\
++		      : "d" (port), "0" (addr), "1" (count));		\
++}
+ 
+ #define RETURN_TYPE unsigned char
+-__IN(b,"")
++__IN(b, "")
+ #undef RETURN_TYPE
+ #define RETURN_TYPE unsigned short
+-__IN(w,"")
++__IN(w, "")
+ #undef RETURN_TYPE
+ #define RETURN_TYPE unsigned int
+-__IN(l,"")
++__IN(l, "")
+ #undef RETURN_TYPE
+ 
+-__OUT(b,"b",char)
+-__OUT(w,"w",short)
+-__OUT(l,,int)
++__OUT(b, "b", char)
++__OUT(w, "w", short)
++__OUT(l, , int)
+ 
+ __INS(b)
+ __INS(w)
+@@ -132,12 +147,12 @@ __OUTS(l)
+  * Change virtual addresses to physical addresses and vv.
+  * These are pretty trivial
+  */
+-static inline unsigned long virt_to_phys(volatile void * address)
++static inline unsigned long virt_to_phys(volatile void *address)
+ {
+ 	return __pa(address);
+ }
+ 
+-static inline void * phys_to_virt(unsigned long address)
++static inline void *phys_to_virt(unsigned long address)
+ {
+ 	return __va(address);
+ }
+@@ -200,18 +215,22 @@ static inline __u8 __readb(const volatile void __iomem *addr)
+ {
+ 	return *(__force volatile __u8 *)addr;
+ }
++
+ static inline __u16 __readw(const volatile void __iomem *addr)
+ {
+ 	return *(__force volatile __u16 *)addr;
+ }
++
+ static __always_inline __u32 __readl(const volatile void __iomem *addr)
+ {
+ 	return *(__force volatile __u32 *)addr;
+ }
++
+ static inline __u64 __readq(const volatile void __iomem *addr)
+ {
+ 	return *(__force volatile __u64 *)addr;
+ }
++
+ #define readb(x) __readb(x)
+ #define readw(x) __readw(x)
+ #define readl(x) __readl(x)
+@@ -231,37 +250,44 @@ static inline void __writel(__u32 b, volatile void __iomem *addr)
+ {
+ 	*(__force volatile __u32 *)addr = b;
+ }
++
+ static inline void __writeq(__u64 b, volatile void __iomem *addr)
+ {
+ 	*(__force volatile __u64 *)addr = b;
+ }
++
+ static inline void __writeb(__u8 b, volatile void __iomem *addr)
+ {
+ 	*(__force volatile __u8 *)addr = b;
+ }
++
+ static inline void __writew(__u16 b, volatile void __iomem *addr)
+ {
+ 	*(__force volatile __u16 *)addr = b;
+ }
+-#define writeq(val,addr) __writeq((val),(addr))
+-#define writel(val,addr) __writel((val),(addr))
+-#define writew(val,addr) __writew((val),(addr))
+-#define writeb(val,addr) __writeb((val),(addr))
++
++#define writeq(val, addr) __writeq((val), (addr))
++#define writel(val, addr) __writel((val), (addr))
++#define writew(val, addr) __writew((val), (addr))
++#define writeb(val, addr) __writeb((val), (addr))
+ #define __raw_writeb writeb
+ #define __raw_writew writew
+ #define __raw_writel writel
+ #define __raw_writeq writeq
+ 
+-void __memcpy_fromio(void*,unsigned long,unsigned);
+-void __memcpy_toio(unsigned long,const void*,unsigned);
++void __memcpy_fromio(void *, unsigned long, unsigned);
++void __memcpy_toio(unsigned long, const void *, unsigned);
+ 
+-static inline void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len)
++static inline void memcpy_fromio(void *to, const volatile void __iomem *from,
++				 unsigned len)
+ {
+-	__memcpy_fromio(to,(unsigned long)from,len);
++	__memcpy_fromio(to, (unsigned long)from, len);
+ }
+-static inline void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len)
++
++static inline void memcpy_toio(volatile void __iomem *to, const void *from,
++			       unsigned len)
+ {
+-	__memcpy_toio((unsigned long)to,from,len);
++	__memcpy_toio((unsigned long)to, from, len);
+ }
+ 
+ void memset_io(volatile void __iomem *a, int b, size_t c);
+@@ -276,18 +302,12 @@ void memset_io(volatile void __iomem *a, int b, size_t c);
+  */
+ #define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
+ 
+-#define flush_write_buffers() 
++#define flush_write_buffers()
+ 
+ extern int iommu_bio_merge;
+ #define BIO_VMERGE_BOUNDARY iommu_bio_merge
+ 
+ /*
+- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+- * access
+- */
+-#define xlate_dev_mem_ptr(p)	__va(p)
+-
+-/*
+  * Convert a virtual cached pointer to an uncached pointer
+  */
+ #define xlate_dev_kmem_ptr(p)	p
+diff --git a/include/asm-x86/io_apic.h b/include/asm-x86/io_apic.h
+index 0f5b3fe..d593e14 100644
+--- a/include/asm-x86/io_apic.h
++++ b/include/asm-x86/io_apic.h
+@@ -1,7 +1,7 @@
+ #ifndef __ASM_IO_APIC_H
+ #define __ASM_IO_APIC_H
+ 
+-#include <asm/types.h>
++#include <linux/types.h>
+ #include <asm/mpspec.h>
+ #include <asm/apicdef.h>
+ 
+@@ -110,6 +110,15 @@ extern int nr_ioapic_registers[MAX_IO_APICS];
+  * MP-BIOS irq configuration table structures:
+  */
+ 
++#define MP_MAX_IOAPIC_PIN 127
++
++struct mp_ioapic_routing {
++	int apic_id;
++	int gsi_base;
++	int gsi_end;
++	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
++};
++
+ /* I/O APIC entries */
+ extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+ 
+@@ -146,7 +155,6 @@ extern int io_apic_get_version(int ioapic);
+ extern int io_apic_get_redir_entries(int ioapic);
+ extern int io_apic_set_pci_routing(int ioapic, int pin, int irq,
+ 				   int edge_level, int active_high_low);
+-extern int timer_uses_ioapic_pin_0;
+ #endif /* CONFIG_ACPI */
+ 
+ extern int (*ioapic_renumber_irq)(int ioapic, int irq);
+diff --git a/include/asm-x86/ioctls.h b/include/asm-x86/ioctls.h
+index 93c894d..c0c338b 100644
+--- a/include/asm-x86/ioctls.h
++++ b/include/asm-x86/ioctls.h
+@@ -47,12 +47,13 @@
+ #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 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 FIONCLEX	0x5450
+ #define FIOCLEX		0x5451
+diff --git a/include/asm-x86/ipcbuf.h b/include/asm-x86/ipcbuf.h
+index 2adf8b3..ee678fd 100644
+--- a/include/asm-x86/ipcbuf.h
++++ b/include/asm-x86/ipcbuf.h
+@@ -11,8 +11,7 @@
+  * - 2 miscellaneous 32-bit values
+  */
+ 
+-struct ipc64_perm
+-{
++struct ipc64_perm {
+ 	__kernel_key_t		key;
+ 	__kernel_uid32_t	uid;
+ 	__kernel_gid32_t	gid;
+diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h
+index 6d011bd..ecc80f3 100644
+--- a/include/asm-x86/ipi.h
++++ b/include/asm-x86/ipi.h
+@@ -27,7 +27,8 @@
+  * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
+  */
+ 
+-static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, unsigned int dest)
++static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector,
++					 unsigned int dest)
+ {
+ 	unsigned int icr = shortcut | dest;
+ 
+@@ -42,12 +43,13 @@ static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, uns
+ 	return icr;
+ }
+ 
+-static inline int __prepare_ICR2 (unsigned int mask)
++static inline int __prepare_ICR2(unsigned int mask)
+ {
+ 	return SET_APIC_DEST_FIELD(mask);
+ }
+ 
+-static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
++static inline void __send_IPI_shortcut(unsigned int shortcut, int vector,
++				       unsigned int dest)
+ {
+ 	/*
+ 	 * Subtle. In the case of the 'never do double writes' workaround
+@@ -78,7 +80,8 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsign
+  * This is used to send an IPI with no shorthand notation (the destination is
+  * specified in bits 56 to 63 of the ICR).
+  */
+-static inline void __send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest)
++static inline void __send_IPI_dest_field(unsigned int mask, int vector,
++					 unsigned int dest)
+ {
+ 	unsigned long cfg;
+ 
+diff --git a/include/asm-x86/irq_32.h b/include/asm-x86/irq_32.h
+index aca9c96..0b79f31 100644
+--- a/include/asm-x86/irq_32.h
++++ b/include/asm-x86/irq_32.h
+@@ -15,7 +15,7 @@
+ #include "irq_vectors.h"
+ #include <asm/thread_info.h>
+ 
+-static __inline__ int irq_canonicalize(int irq)
++static inline int irq_canonicalize(int irq)
+ {
+ 	return ((irq == 2) ? 9 : irq);
+ }
+diff --git a/include/asm-x86/irq_64.h b/include/asm-x86/irq_64.h
+index 5006c6e..083d35a 100644
+--- a/include/asm-x86/irq_64.h
++++ b/include/asm-x86/irq_64.h
+@@ -31,10 +31,10 @@
+ 
+ #define FIRST_SYSTEM_VECTOR	0xef   /* duplicated in hw_irq.h */
+ 
+-#define NR_IRQS (NR_VECTORS + (32 *NR_CPUS))
++#define NR_IRQS (NR_VECTORS + (32 * NR_CPUS))
+ #define NR_IRQ_VECTORS NR_IRQS
+ 
+-static __inline__ int irq_canonicalize(int irq)
++static inline int irq_canonicalize(int irq)
+ {
+ 	return ((irq == 2) ? 9 : irq);
+ }
+diff --git a/include/asm-x86/irqflags.h b/include/asm-x86/irqflags.h
+index 0e22924..c242527 100644
+--- a/include/asm-x86/irqflags.h
++++ b/include/asm-x86/irqflags.h
+@@ -12,25 +12,21 @@ static inline unsigned long native_save_fl(void)
+ {
+ 	unsigned long flags;
+ 
+-	__asm__ __volatile__(
+-		"# __raw_save_flags\n\t"
+-		"pushf ; pop %0"
+-		: "=g" (flags)
+-		: /* no input */
+-		: "memory"
+-	);
++	asm volatile("# __raw_save_flags\n\t"
++		     "pushf ; pop %0"
++		     : "=g" (flags)
++		     : /* no input */
++		     : "memory");
+ 
+ 	return flags;
+ }
+ 
+ static inline void native_restore_fl(unsigned long flags)
+ {
+-	__asm__ __volatile__(
+-		"push %0 ; popf"
+-		: /* no output */
+-		:"g" (flags)
+-		:"memory", "cc"
+-	);
++	asm volatile("push %0 ; popf"
++		     : /* no output */
++		     :"g" (flags)
++		     :"memory", "cc");
+ }
+ 
+ static inline void native_irq_disable(void)
+@@ -70,26 +66,6 @@ static inline void raw_local_irq_restore(unsigned long flags)
+ 	native_restore_fl(flags);
+ }
+ 
+-#ifdef CONFIG_X86_VSMP
+-
+-/*
+- * Interrupt control for the VSMP architecture:
+- */
+-
+-static inline void raw_local_irq_disable(void)
+-{
+-	unsigned long flags = __raw_local_save_flags();
+-	raw_local_irq_restore((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
+-}
+-
+-static inline void raw_local_irq_enable(void)
+-{
+-	unsigned long flags = __raw_local_save_flags();
+-	raw_local_irq_restore((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
+-}
+-
+-#else
+-
+ static inline void raw_local_irq_disable(void)
+ {
+ 	native_irq_disable();
+@@ -100,8 +76,6 @@ static inline void raw_local_irq_enable(void)
+ 	native_irq_enable();
+ }
+ 
+-#endif
+-
+ /*
+  * Used in the idle loop; sti takes one instruction cycle
+  * to complete:
+@@ -153,23 +127,16 @@ static inline unsigned long __raw_local_irq_save(void)
+ #endif /* CONFIG_PARAVIRT */
+ 
+ #ifndef __ASSEMBLY__
+-#define raw_local_save_flags(flags) \
+-		do { (flags) = __raw_local_save_flags(); } while (0)
++#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)
++#define raw_local_irq_save(flags)				\
++	do { (flags) = __raw_local_irq_save(); } while (0)
+ 
+-#ifdef CONFIG_X86_VSMP
+-static inline int raw_irqs_disabled_flags(unsigned long flags)
+-{
+-	return !(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC);
+-}
+-#else
+ static inline int raw_irqs_disabled_flags(unsigned long flags)
+ {
+ 	return !(flags & X86_EFLAGS_IF);
+ }
+-#endif
+ 
+ static inline int raw_irqs_disabled(void)
+ {
+diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h
+index 99dcbaf..96651bb 100644
+--- a/include/asm-x86/kdebug.h
++++ b/include/asm-x86/kdebug.h
+@@ -20,15 +20,16 @@ enum die_val {
+ 	DIE_CALL,
+ 	DIE_NMI_IPI,
+ 	DIE_PAGE_FAULT,
++	DIE_NMIUNKNOWN,
+ };
+ 
+ extern void printk_address(unsigned long address, int reliable);
+-extern void die(const char *,struct pt_regs *,long);
++extern void die(const char *, struct pt_regs *,long);
+ extern int __must_check __die(const char *, struct pt_regs *, long);
+ extern void show_registers(struct pt_regs *regs);
+ extern void __show_registers(struct pt_regs *, int all);
+ extern void show_trace(struct task_struct *t, struct pt_regs *regs,
+-			unsigned long *sp, unsigned long bp);
++		       unsigned long *sp, unsigned long bp);
+ extern void __show_regs(struct pt_regs *regs);
+ extern void show_regs(struct pt_regs *regs);
+ extern unsigned long oops_begin(void);
+diff --git a/include/asm-x86/kexec.h b/include/asm-x86/kexec.h
+index c90d3c7..8f855a1 100644
+--- a/include/asm-x86/kexec.h
++++ b/include/asm-x86/kexec.h
+@@ -94,10 +94,9 @@ static inline void crash_fixup_ss_esp(struct pt_regs *newregs,
+ {
+ #ifdef CONFIG_X86_32
+ 	newregs->sp = (unsigned long)&(oldregs->sp);
+-	__asm__ __volatile__(
+-			"xorl %%eax, %%eax\n\t"
+-			"movw %%ss, %%ax\n\t"
+-			:"=a"(newregs->ss));
++	asm volatile("xorl %%eax, %%eax\n\t"
++		     "movw %%ss, %%ax\n\t"
++		     :"=a"(newregs->ss));
+ #endif
+ }
+ 
+@@ -114,39 +113,39 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
+ 		crash_fixup_ss_esp(newregs, oldregs);
+ 	} else {
+ #ifdef CONFIG_X86_32
+-		__asm__ __volatile__("movl %%ebx,%0" : "=m"(newregs->bx));
+-		__asm__ __volatile__("movl %%ecx,%0" : "=m"(newregs->cx));
+-		__asm__ __volatile__("movl %%edx,%0" : "=m"(newregs->dx));
+-		__asm__ __volatile__("movl %%esi,%0" : "=m"(newregs->si));
+-		__asm__ __volatile__("movl %%edi,%0" : "=m"(newregs->di));
+-		__asm__ __volatile__("movl %%ebp,%0" : "=m"(newregs->bp));
+-		__asm__ __volatile__("movl %%eax,%0" : "=m"(newregs->ax));
+-		__asm__ __volatile__("movl %%esp,%0" : "=m"(newregs->sp));
+-		__asm__ __volatile__("movl %%ss, %%eax;" :"=a"(newregs->ss));
+-		__asm__ __volatile__("movl %%cs, %%eax;" :"=a"(newregs->cs));
+-		__asm__ __volatile__("movl %%ds, %%eax;" :"=a"(newregs->ds));
+-		__asm__ __volatile__("movl %%es, %%eax;" :"=a"(newregs->es));
+-		__asm__ __volatile__("pushfl; popl %0" :"=m"(newregs->flags));
++		asm volatile("movl %%ebx,%0" : "=m"(newregs->bx));
++		asm volatile("movl %%ecx,%0" : "=m"(newregs->cx));
++		asm volatile("movl %%edx,%0" : "=m"(newregs->dx));
++		asm volatile("movl %%esi,%0" : "=m"(newregs->si));
++		asm volatile("movl %%edi,%0" : "=m"(newregs->di));
++		asm volatile("movl %%ebp,%0" : "=m"(newregs->bp));
++		asm volatile("movl %%eax,%0" : "=m"(newregs->ax));
++		asm volatile("movl %%esp,%0" : "=m"(newregs->sp));
++		asm volatile("movl %%ss, %%eax;" :"=a"(newregs->ss));
++		asm volatile("movl %%cs, %%eax;" :"=a"(newregs->cs));
++		asm volatile("movl %%ds, %%eax;" :"=a"(newregs->ds));
++		asm volatile("movl %%es, %%eax;" :"=a"(newregs->es));
++		asm volatile("pushfl; popl %0" :"=m"(newregs->flags));
+ #else
+-		__asm__ __volatile__("movq %%rbx,%0" : "=m"(newregs->bx));
+-		__asm__ __volatile__("movq %%rcx,%0" : "=m"(newregs->cx));
+-		__asm__ __volatile__("movq %%rdx,%0" : "=m"(newregs->dx));
+-		__asm__ __volatile__("movq %%rsi,%0" : "=m"(newregs->si));
+-		__asm__ __volatile__("movq %%rdi,%0" : "=m"(newregs->di));
+-		__asm__ __volatile__("movq %%rbp,%0" : "=m"(newregs->bp));
+-		__asm__ __volatile__("movq %%rax,%0" : "=m"(newregs->ax));
+-		__asm__ __volatile__("movq %%rsp,%0" : "=m"(newregs->sp));
+-		__asm__ __volatile__("movq %%r8,%0" : "=m"(newregs->r8));
+-		__asm__ __volatile__("movq %%r9,%0" : "=m"(newregs->r9));
+-		__asm__ __volatile__("movq %%r10,%0" : "=m"(newregs->r10));
+-		__asm__ __volatile__("movq %%r11,%0" : "=m"(newregs->r11));
+-		__asm__ __volatile__("movq %%r12,%0" : "=m"(newregs->r12));
+-		__asm__ __volatile__("movq %%r13,%0" : "=m"(newregs->r13));
+-		__asm__ __volatile__("movq %%r14,%0" : "=m"(newregs->r14));
+-		__asm__ __volatile__("movq %%r15,%0" : "=m"(newregs->r15));
+-		__asm__ __volatile__("movl %%ss, %%eax;" :"=a"(newregs->ss));
+-		__asm__ __volatile__("movl %%cs, %%eax;" :"=a"(newregs->cs));
+-		__asm__ __volatile__("pushfq; popq %0" :"=m"(newregs->flags));
++		asm volatile("movq %%rbx,%0" : "=m"(newregs->bx));
++		asm volatile("movq %%rcx,%0" : "=m"(newregs->cx));
++		asm volatile("movq %%rdx,%0" : "=m"(newregs->dx));
++		asm volatile("movq %%rsi,%0" : "=m"(newregs->si));
++		asm volatile("movq %%rdi,%0" : "=m"(newregs->di));
++		asm volatile("movq %%rbp,%0" : "=m"(newregs->bp));
++		asm volatile("movq %%rax,%0" : "=m"(newregs->ax));
++		asm volatile("movq %%rsp,%0" : "=m"(newregs->sp));
++		asm volatile("movq %%r8,%0" : "=m"(newregs->r8));
++		asm volatile("movq %%r9,%0" : "=m"(newregs->r9));
++		asm volatile("movq %%r10,%0" : "=m"(newregs->r10));
++		asm volatile("movq %%r11,%0" : "=m"(newregs->r11));
++		asm volatile("movq %%r12,%0" : "=m"(newregs->r12));
++		asm volatile("movq %%r13,%0" : "=m"(newregs->r13));
++		asm volatile("movq %%r14,%0" : "=m"(newregs->r14));
++		asm volatile("movq %%r15,%0" : "=m"(newregs->r15));
++		asm volatile("movl %%ss, %%eax;" :"=a"(newregs->ss));
++		asm volatile("movl %%cs, %%eax;" :"=a"(newregs->cs));
++		asm volatile("pushfq; popq %0" :"=m"(newregs->flags));
+ #endif
+ 		newregs->ip = (unsigned long)current_text_addr();
+ 	}
+diff --git a/include/asm-x86/kgdb.h b/include/asm-x86/kgdb.h
+new file mode 100644
+index 0000000..484c475
+--- /dev/null
++++ b/include/asm-x86/kgdb.h
+@@ -0,0 +1,81 @@
++#ifndef _ASM_KGDB_H_
++#define _ASM_KGDB_H_
++
++/*
++ * Copyright (C) 2001-2004 Amit S. Kale
++ * Copyright (C) 2008 Wind River Systems, Inc.
++ */
++
++/*
++ * BUFMAX defines the maximum number of characters in inbound/outbound
++ * buffers at least NUMREGBYTES*2 are needed for register packets
++ * Longer buffer is needed to list all threads
++ */
++#define BUFMAX			1024
++
++/*
++ *  Note that this register image is in a different order than
++ *  the register image that Linux produces at interrupt time.
++ *
++ *  Linux's register image is defined by struct pt_regs in ptrace.h.
++ *  Just why GDB uses a different order is a historical mystery.
++ */
++#ifdef CONFIG_X86_32
++enum regnames {
++	GDB_AX,			/* 0 */
++	GDB_CX,			/* 1 */
++	GDB_DX,			/* 2 */
++	GDB_BX,			/* 3 */
++	GDB_SP,			/* 4 */
++	GDB_BP,			/* 5 */
++	GDB_SI,			/* 6 */
++	GDB_DI,			/* 7 */
++	GDB_PC,			/* 8 also known as eip */
++	GDB_PS,			/* 9 also known as eflags */
++	GDB_CS,			/* 10 */
++	GDB_SS,			/* 11 */
++	GDB_DS,			/* 12 */
++	GDB_ES,			/* 13 */
++	GDB_FS,			/* 14 */
++	GDB_GS,			/* 15 */
++};
++#else /* ! CONFIG_X86_32 */
++enum regnames {
++	GDB_AX,			/* 0 */
++	GDB_DX,			/* 1 */
++	GDB_CX,			/* 2 */
++	GDB_BX,			/* 3 */
++	GDB_SI,			/* 4 */
++	GDB_DI,			/* 5 */
++	GDB_BP,			/* 6 */
++	GDB_SP,			/* 7 */
++	GDB_R8,			/* 8 */
++	GDB_R9,			/* 9 */
++	GDB_R10,		/* 10 */
++	GDB_R11,		/* 11 */
++	GDB_R12,		/* 12 */
++	GDB_R13,		/* 13 */
++	GDB_R14,		/* 14 */
++	GDB_R15,		/* 15 */
++	GDB_PC,			/* 16 */
++	GDB_PS,			/* 17 */
++};
++#endif /* CONFIG_X86_32 */
++
++/*
++ * Number of bytes of registers:
++ */
++#ifdef CONFIG_X86_32
++# define NUMREGBYTES		64
++#else
++# define NUMREGBYTES		((GDB_PS+1)*8)
++#endif
++
++static inline void arch_kgdb_breakpoint(void)
++{
++	asm("   int $3");
++}
++#define BREAK_INSTR_SIZE	1
++#define CACHE_FLUSH_IS_SAFE	1
++
++#endif				/* _ASM_KGDB_H_ */
+diff --git a/include/asm-x86/kprobes.h b/include/asm-x86/kprobes.h
+index 61ad7b5..54980b0 100644
+--- a/include/asm-x86/kprobes.h
++++ b/include/asm-x86/kprobes.h
+@@ -35,12 +35,12 @@ typedef u8 kprobe_opcode_t;
+ #define RELATIVEJUMP_INSTRUCTION 0xe9
+ #define MAX_INSN_SIZE 16
+ #define MAX_STACK_SIZE 64
+-#define MIN_STACK_SIZE(ADDR) (((MAX_STACK_SIZE) < \
+-	(((unsigned long)current_thread_info()) + THREAD_SIZE \
+-	 - (unsigned long)(ADDR))) \
+-	? (MAX_STACK_SIZE) \
+-	: (((unsigned long)current_thread_info()) + THREAD_SIZE \
+-	   - (unsigned long)(ADDR)))
++#define MIN_STACK_SIZE(ADDR)					       \
++	(((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \
++			      THREAD_SIZE - (unsigned long)(ADDR)))    \
++	 ? (MAX_STACK_SIZE)					       \
++	 : (((unsigned long)current_thread_info()) +		       \
++	    THREAD_SIZE - (unsigned long)(ADDR)))
+ 
+ #define flush_insn_slot(p)	do { } while (0)
+ 
+diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
+index 4702b04..68ee390 100644
+--- a/include/asm-x86/kvm_host.h
++++ b/include/asm-x86/kvm_host.h
+@@ -22,15 +22,16 @@
+ 
+ #define CR3_PAE_RESERVED_BITS ((X86_CR3_PWT | X86_CR3_PCD) - 1)
+ #define CR3_NONPAE_RESERVED_BITS ((PAGE_SIZE-1) & ~(X86_CR3_PWT | X86_CR3_PCD))
+-#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS|0xFFFFFF0000000000ULL)
++#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS |	\
++				  0xFFFFFF0000000000ULL)
+ 
+-#define KVM_GUEST_CR0_MASK \
++#define KVM_GUEST_CR0_MASK				   \
+ 	(X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE \
+ 	 | X86_CR0_NW | X86_CR0_CD)
+-#define KVM_VM_CR0_ALWAYS_ON \
++#define KVM_VM_CR0_ALWAYS_ON						\
+ 	(X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE | X86_CR0_TS \
+ 	 | X86_CR0_MP)
+-#define KVM_GUEST_CR4_MASK \
++#define KVM_GUEST_CR4_MASK						\
+ 	(X86_CR4_VME | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE | X86_CR4_VMXE)
+ #define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)
+ #define KVM_RMODE_VM_CR4_ALWAYS_ON (X86_CR4_VME | X86_CR4_PAE | X86_CR4_VMXE)
+@@ -133,12 +134,12 @@ struct kvm_pte_chain {
+ union kvm_mmu_page_role {
+ 	unsigned word;
+ 	struct {
+-		unsigned glevels : 4;
+-		unsigned level : 4;
+-		unsigned quadrant : 2;
+-		unsigned pad_for_nice_hex_output : 6;
+-		unsigned metaphysical : 1;
+-		unsigned access : 3;
++		unsigned glevels:4;
++		unsigned level:4;
++		unsigned quadrant:2;
++		unsigned pad_for_nice_hex_output:6;
++		unsigned metaphysical:1;
++		unsigned access:3;
+ 	};
+ };
+ 
+@@ -606,6 +607,7 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
+ #define TSS_BASE_SIZE 0x68
+ #define TSS_IOPB_SIZE (65536 / 8)
+ #define TSS_REDIRECTION_SIZE (256 / 8)
+-#define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
++#define RMODE_TSS_SIZE							\
++	(TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
+ 
+ #endif
+diff --git a/include/asm-x86/kvm_x86_emulate.h b/include/asm-x86/kvm_x86_emulate.h
+index 7db91b9..d6337f9 100644
+--- a/include/asm-x86/kvm_x86_emulate.h
++++ b/include/asm-x86/kvm_x86_emulate.h
+@@ -68,10 +68,10 @@ struct x86_emulate_ops {
+ 	 *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
+ 	 *  @bytes: [IN ] Number of bytes to read from memory.
+ 	 */
+-	int (*read_emulated) (unsigned long addr,
+-			      void *val,
+-			      unsigned int bytes,
+-			      struct kvm_vcpu *vcpu);
++	int (*read_emulated)(unsigned long addr,
++			     void *val,
++			     unsigned int bytes,
++			     struct kvm_vcpu *vcpu);
+ 
+ 	/*
+ 	 * write_emulated: Read bytes from emulated/special memory area.
+@@ -80,10 +80,10 @@ struct x86_emulate_ops {
+ 	 *                required).
+ 	 *  @bytes: [IN ] Number of bytes to write to memory.
+ 	 */
+-	int (*write_emulated) (unsigned long addr,
+-			       const void *val,
+-			       unsigned int bytes,
+-			       struct kvm_vcpu *vcpu);
++	int (*write_emulated)(unsigned long addr,
++			      const void *val,
++			      unsigned int bytes,
++			      struct kvm_vcpu *vcpu);
+ 
+ 	/*
+ 	 * cmpxchg_emulated: Emulate an atomic (LOCKed) CMPXCHG operation on an
+@@ -93,11 +93,11 @@ struct x86_emulate_ops {
+ 	 *  @new:   [IN ] Value to write to @addr.
+ 	 *  @bytes: [IN ] Number of bytes to access using CMPXCHG.
+ 	 */
+-	int (*cmpxchg_emulated) (unsigned long addr,
+-				 const void *old,
+-				 const void *new,
+-				 unsigned int bytes,
+-				 struct kvm_vcpu *vcpu);
++	int (*cmpxchg_emulated)(unsigned long addr,
++				const void *old,
++				const void *new,
++				unsigned int bytes,
++				struct kvm_vcpu *vcpu);
+ 
+ };
+ 
+@@ -143,7 +143,7 @@ struct x86_emulate_ctxt {
+ 	/* Register state before/after emulation. */
+ 	struct kvm_vcpu *vcpu;
+ 
+-	/* Linear faulting address (if emulating a page-faulting instruction). */
++	/* Linear faulting address (if emulating a page-faulting instruction) */
+ 	unsigned long eflags;
+ 
+ 	/* Emulated execution mode, represented by an X86EMUL_MODE value. */
+diff --git a/include/asm-x86/lguest.h b/include/asm-x86/lguest.h
+index 9b17571..be4a724 100644
+--- a/include/asm-x86/lguest.h
++++ b/include/asm-x86/lguest.h
+@@ -34,8 +34,7 @@ extern const char lgstart_iret[], lgend_iret[];
+ extern void lguest_iret(void);
+ extern void lguest_init(void);
+ 
+-struct lguest_regs
+-{
++struct lguest_regs {
+ 	/* Manually saved part. */
+ 	unsigned long eax, ebx, ecx, edx;
+ 	unsigned long esi, edi, ebp;
+@@ -51,8 +50,7 @@ struct lguest_regs
+ };
+ 
+ /* This is a guest-specific page (mapped ro) into the guest. */
+-struct lguest_ro_state
+-{
++struct lguest_ro_state {
+ 	/* Host information we need to restore when we switch back. */
+ 	u32 host_cr3;
+ 	struct desc_ptr host_idt_desc;
+@@ -67,8 +65,7 @@ struct lguest_ro_state
+ 	struct desc_struct guest_gdt[GDT_ENTRIES];
+ };
+ 
+-struct lg_cpu_arch
+-{
++struct lg_cpu_arch {
+ 	/* The GDT entries copied into lguest_ro_state when running. */
+ 	struct desc_struct gdt[GDT_ENTRIES];
+ 
+@@ -85,7 +82,7 @@ static inline void lguest_set_ts(void)
+ 
+ 	cr0 = read_cr0();
+ 	if (!(cr0 & 8))
+-		write_cr0(cr0|8);
++		write_cr0(cr0 | 8);
+ }
+ 
+ /* Full 4G segment descriptors, suitable for CS and DS. */
+diff --git a/include/asm-x86/lguest_hcall.h b/include/asm-x86/lguest_hcall.h
+index f239e70..a3241f2 100644
+--- a/include/asm-x86/lguest_hcall.h
++++ b/include/asm-x86/lguest_hcall.h
+@@ -46,7 +46,7 @@ hcall(unsigned long call,
+ {
+ 	/* "int" is the Intel instruction to trigger a trap. */
+ 	asm volatile("int $" __stringify(LGUEST_TRAP_ENTRY)
+-		       /* The call in %eax (aka "a") might be overwritten */
++		     /* The call in %eax (aka "a") might be overwritten */
+ 		     : "=a"(call)
+ 		       /* The arguments are in %eax, %edx, %ebx & %ecx */
+ 		     : "a"(call), "d"(arg1), "b"(arg2), "c"(arg3)
+@@ -62,8 +62,7 @@ hcall(unsigned long call,
+ #define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
+ 
+ #define LHCALL_RING_SIZE 64
+-struct hcall_args
+-{
++struct hcall_args {
+ 	/* These map directly onto eax, ebx, ecx, edx in struct lguest_regs */
+ 	unsigned long arg0, arg2, arg3, arg1;
+ };
+diff --git a/include/asm-x86/linkage.h b/include/asm-x86/linkage.h
+index c048353..64e444f 100644
+--- a/include/asm-x86/linkage.h
++++ b/include/asm-x86/linkage.h
+@@ -1,6 +1,9 @@
+ #ifndef __ASM_LINKAGE_H
+ #define __ASM_LINKAGE_H
+ 
++#undef notrace
++#define notrace __attribute__((no_instrument_function))
++
+ #ifdef CONFIG_X86_64
+ #define __ALIGN .p2align 4,,15
+ #define __ALIGN_STR ".p2align 4,,15"
+diff --git a/include/asm-x86/local.h b/include/asm-x86/local.h
+index f852c62..330a724 100644
+--- a/include/asm-x86/local.h
++++ b/include/asm-x86/local.h
+@@ -18,32 +18,28 @@ typedef struct {
+ 
+ static inline void local_inc(local_t *l)
+ {
+-	__asm__ __volatile__(
+-		_ASM_INC "%0"
+-		:"+m" (l->a.counter));
++	asm volatile(_ASM_INC "%0"
++		     : "+m" (l->a.counter));
+ }
+ 
+ static inline void local_dec(local_t *l)
+ {
+-	__asm__ __volatile__(
+-		_ASM_DEC "%0"
+-		:"+m" (l->a.counter));
++	asm volatile(_ASM_DEC "%0"
++		     : "+m" (l->a.counter));
+ }
+ 
+ static inline void local_add(long i, local_t *l)
+ {
+-	__asm__ __volatile__(
+-		_ASM_ADD "%1,%0"
+-		:"+m" (l->a.counter)
+-		:"ir" (i));
++	asm volatile(_ASM_ADD "%1,%0"
++		     : "+m" (l->a.counter)
++		     : "ir" (i));
+ }
+ 
+ static inline void local_sub(long i, local_t *l)
+ {
+-	__asm__ __volatile__(
+-		_ASM_SUB "%1,%0"
+-		:"+m" (l->a.counter)
+-		:"ir" (i));
++	asm volatile(_ASM_SUB "%1,%0"
++		     : "+m" (l->a.counter)
++		     : "ir" (i));
+ }
+ 
+ /**
+@@ -59,10 +55,9 @@ static inline int local_sub_and_test(long i, local_t *l)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		_ASM_SUB "%2,%0; sete %1"
+-		:"+m" (l->a.counter), "=qm" (c)
+-		:"ir" (i) : "memory");
++	asm volatile(_ASM_SUB "%2,%0; sete %1"
++		     : "+m" (l->a.counter), "=qm" (c)
++		     : "ir" (i) : "memory");
+ 	return c;
+ }
+ 
+@@ -78,10 +73,9 @@ static inline int local_dec_and_test(local_t *l)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		_ASM_DEC "%0; sete %1"
+-		:"+m" (l->a.counter), "=qm" (c)
+-		: : "memory");
++	asm volatile(_ASM_DEC "%0; sete %1"
++		     : "+m" (l->a.counter), "=qm" (c)
++		     : : "memory");
+ 	return c != 0;
+ }
+ 
+@@ -97,10 +91,9 @@ static inline int local_inc_and_test(local_t *l)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		_ASM_INC "%0; sete %1"
+-		:"+m" (l->a.counter), "=qm" (c)
+-		: : "memory");
++	asm volatile(_ASM_INC "%0; sete %1"
++		     : "+m" (l->a.counter), "=qm" (c)
++		     : : "memory");
+ 	return c != 0;
+ }
+ 
+@@ -117,10 +110,9 @@ static inline int local_add_negative(long i, local_t *l)
+ {
+ 	unsigned char c;
+ 
+-	__asm__ __volatile__(
+-		_ASM_ADD "%2,%0; sets %1"
+-		:"+m" (l->a.counter), "=qm" (c)
+-		:"ir" (i) : "memory");
++	asm volatile(_ASM_ADD "%2,%0; sets %1"
++		     : "+m" (l->a.counter), "=qm" (c)
++		     : "ir" (i) : "memory");
+ 	return c;
+ }
+ 
+@@ -141,10 +133,9 @@ static inline long local_add_return(long i, local_t *l)
+ #endif
+ 	/* Modern 486+ processor */
+ 	__i = i;
+-	__asm__ __volatile__(
+-		_ASM_XADD "%0, %1;"
+-		:"+r" (i), "+m" (l->a.counter)
+-		: : "memory");
++	asm volatile(_ASM_XADD "%0, %1;"
++		     : "+r" (i), "+m" (l->a.counter)
++		     : : "memory");
+ 	return i + __i;
+ 
+ #ifdef CONFIG_M386
+@@ -182,11 +173,11 @@ static inline long local_sub_return(long i, local_t *l)
+ #define local_add_unless(l, a, u)				\
+ ({								\
+ 	long c, old;						\
+-	c = local_read(l);					\
++	c = local_read((l));					\
+ 	for (;;) {						\
+ 		if (unlikely(c == (u)))				\
+ 			break;					\
+-		old = local_cmpxchg((l), c, c + (a));	\
++		old = local_cmpxchg((l), c, c + (a));		\
+ 		if (likely(old == c))				\
+ 			break;					\
+ 		c = old;					\
+@@ -214,26 +205,30 @@ static inline long local_sub_return(long i, local_t *l)
+ 
+ /* Need to disable preemption for the cpu local counters otherwise we could
+    still access a variable of a previous CPU in a non atomic way. */
+-#define cpu_local_wrap_v(l)	 	\
+-	({ local_t res__;		\
+-	   preempt_disable(); 		\
+-	   res__ = (l);			\
+-	   preempt_enable();		\
+-	   res__; })
++#define cpu_local_wrap_v(l)		\
++({					\
++	local_t res__;			\
++	preempt_disable(); 		\
++	res__ = (l);			\
++	preempt_enable();		\
++	res__;				\
++})
+ #define cpu_local_wrap(l)		\
+-	({ preempt_disable();		\
+-	   l;				\
+-	   preempt_enable(); })		\
+-
+-#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
+-#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
+-#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
+-#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
+-#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
+-#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
+-
+-#define __cpu_local_inc(l)	cpu_local_inc(l)
+-#define __cpu_local_dec(l)	cpu_local_dec(l)
++({					\
++	preempt_disable();		\
++	(l);				\
++	preempt_enable();		\
++})					\
++
++#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var((l))))
++#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var((l)), (i)))
++#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var((l))))
++#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var((l))))
++#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var((l))))
++#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var((l))))
++
++#define __cpu_local_inc(l)	cpu_local_inc((l))
++#define __cpu_local_dec(l)	cpu_local_dec((l))
+ #define __cpu_local_add(i, l)	cpu_local_add((i), (l))
+ #define __cpu_local_sub(i, l)	cpu_local_sub((i), (l))
+ 
+diff --git a/include/asm-x86/mach-bigsmp/mach_apic.h b/include/asm-x86/mach-bigsmp/mach_apic.h
+index 6df235e..8327907 100644
+--- a/include/asm-x86/mach-bigsmp/mach_apic.h
++++ b/include/asm-x86/mach-bigsmp/mach_apic.h
+@@ -1,10 +1,7 @@
+ #ifndef __ASM_MACH_APIC_H
+ #define __ASM_MACH_APIC_H
+ 
+-
+-extern u8 bios_cpu_apicid[];
+-
+-#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu])
++#define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu))
+ #define esr_disable (1)
+ 
+ static inline int apic_id_registered(void)
+@@ -90,7 +87,7 @@ static inline int apicid_to_node(int logical_apicid)
+ static inline int cpu_present_to_apicid(int mps_cpu)
+ {
+ 	if (mps_cpu < NR_CPUS)
+-		return (int) bios_cpu_apicid[mps_cpu];
++		return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
+ 
+ 	return BAD_APICID;
+ }
+@@ -109,17 +106,6 @@ static inline int cpu_to_logical_apicid(int cpu)
+ 	return cpu_physical_id(cpu);
+ }
+ 
+-static inline int mpc_apic_id(struct mpc_config_processor *m,
+-			      struct mpc_config_translation *translation_record)
+-{
+-	printk("Processor #%d %u:%u APIC version %d\n",
+-	       m->mpc_apicid,
+-	       (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+-	       (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+-	       m->mpc_apicver);
+-	return m->mpc_apicid;
+-}
+-
+ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
+ {
+ 	/* For clustered we don't have a good way to do this yet - hack */
+diff --git a/include/asm-x86/mach-default/bios_ebda.h b/include/asm-x86/mach-default/bios_ebda.h
+deleted file mode 100644
+index 9cbd9a6..0000000
+--- a/include/asm-x86/mach-default/bios_ebda.h
++++ /dev/null
+@@ -1,15 +0,0 @@
+-#ifndef _MACH_BIOS_EBDA_H
+-#define _MACH_BIOS_EBDA_H
+-
+-/*
+- * there is a real-mode segmented pointer pointing to the
+- * 4K EBDA area at 0x40E.
+- */
+-static inline unsigned int get_bios_ebda(void)
+-{
+-	unsigned int address = *(unsigned short *)phys_to_virt(0x40E);
+-	address <<= 4;
+-	return address;	/* 0 means none */
+-}
+-
+-#endif /* _MACH_BIOS_EBDA_H */
+diff --git a/include/asm-x86/mach-default/mach_apic.h b/include/asm-x86/mach-default/mach_apic.h
+index e3c2c10..0a6634f 100644
+--- a/include/asm-x86/mach-default/mach_apic.h
++++ b/include/asm-x86/mach-default/mach_apic.h
+@@ -1,6 +1,8 @@
+ #ifndef __ASM_MACH_APIC_H
+ #define __ASM_MACH_APIC_H
+ 
++#ifdef CONFIG_X86_LOCAL_APIC
++
+ #include <mach_apicdef.h>
+ #include <asm/smp.h>
+ 
+@@ -14,24 +16,25 @@ static inline cpumask_t target_cpus(void)
+ 	return cpumask_of_cpu(0);
+ #endif
+ } 
+-#define TARGET_CPUS (target_cpus())
+ 
+ #define NO_BALANCE_IRQ (0)
+ #define esr_disable (0)
+ 
++#ifdef CONFIG_X86_64
++#include <asm/genapic.h>
++#define INT_DELIVERY_MODE (genapic->int_delivery_mode)
++#define INT_DEST_MODE (genapic->int_dest_mode)
++#define TARGET_CPUS	  (genapic->target_cpus())
++#define apic_id_registered (genapic->apic_id_registered)
++#define init_apic_ldr (genapic->init_apic_ldr)
++#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
++#define phys_pkg_id	(genapic->phys_pkg_id)
++#define vector_allocation_domain    (genapic->vector_allocation_domain)
++extern void setup_apic_routing(void);
++#else
+ #define INT_DELIVERY_MODE dest_LowestPrio
+ #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
+-
+-static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
+-{
+-	return physid_isset(apicid, bitmap);
+-}
+-
+-static inline unsigned long check_apicid_present(int bit)
+-{
+-	return physid_isset(bit, phys_cpu_present_map);
+-}
+-
++#define TARGET_CPUS (target_cpus())
+ /*
+  * Set up the logical destination ID.
+  *
+@@ -49,23 +52,51 @@ static inline void init_apic_ldr(void)
+ 	apic_write_around(APIC_LDR, val);
+ }
+ 
+-static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
++static inline int apic_id_registered(void)
+ {
+-	return phys_map;
++	return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map);
++}
++
++static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
++{
++	return cpus_addr(cpumask)[0];
++}
++
++static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
++{
++	return cpuid_apic >> index_msb;
+ }
+ 
+ static inline void setup_apic_routing(void)
+ {
++#ifdef CONFIG_X86_IO_APIC
+ 	printk("Enabling APIC mode:  %s.  Using %d I/O APICs\n",
+ 					"Flat", nr_ioapics);
++#endif
+ }
+ 
+-static inline int multi_timer_check(int apic, int irq)
++static inline int apicid_to_node(int logical_apicid)
+ {
+ 	return 0;
+ }
++#endif
+ 
+-static inline int apicid_to_node(int logical_apicid)
++static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
++{
++	return physid_isset(apicid, bitmap);
++}
++
++static inline unsigned long check_apicid_present(int bit)
++{
++	return physid_isset(bit, phys_cpu_present_map);
++}
++
++static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
++{
++	return phys_map;
++}
++
++static inline int multi_timer_check(int apic, int irq)
+ {
+ 	return 0;
+ }
+@@ -78,8 +109,13 @@ static inline int cpu_to_logical_apicid(int cpu)
+ 
+ static inline int cpu_present_to_apicid(int mps_cpu)
+ {
++#ifdef CONFIG_X86_64
++	if (cpu_present(mps_cpu))
++		return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
++#else
+ 	if (mps_cpu < get_physical_broadcast())
+ 		return  mps_cpu;
++#endif
+ 	else
+ 		return BAD_APICID;
+ }
+@@ -89,17 +125,6 @@ static inline physid_mask_t apicid_to_cpu_present(int phys_apicid)
+ 	return physid_mask_of_physid(phys_apicid);
+ }
+ 
+-static inline int mpc_apic_id(struct mpc_config_processor *m,
+-			      struct mpc_config_translation *translation_record)
+-{
+-	printk("Processor #%d %u:%u APIC version %d\n",
+-	       m->mpc_apicid,
+-	       (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+-	       (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+-	       m->mpc_apicver);
+-	return m->mpc_apicid;
+-}
+-
+ static inline void setup_portio_remap(void)
+ {
+ }
+@@ -109,23 +134,9 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
+ 	return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map);
+ }
+ 
+-static inline int apic_id_registered(void)
+-{
+-	return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
+-}
+-
+-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+-{
+-	return cpus_addr(cpumask)[0];
+-}
+-
+ static inline void enable_apic_mode(void)
+ {
+ }
+ 
+-static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
+-{
+-	return cpuid_apic >> index_msb;
+-}
+-
++#endif /* CONFIG_X86_LOCAL_APIC */
+ #endif /* __ASM_MACH_APIC_H */
+diff --git a/include/asm-x86/mach-default/mach_apicdef.h b/include/asm-x86/mach-default/mach_apicdef.h
+index ae98413..e4b29ba 100644
+--- a/include/asm-x86/mach-default/mach_apicdef.h
++++ b/include/asm-x86/mach-default/mach_apicdef.h
+@@ -3,10 +3,14 @@
+ 
+ #include <asm/apic.h>
+ 
++#ifdef CONFIG_X86_64
++#define	APIC_ID_MASK		(0xFFu<<24)
++#define GET_APIC_ID(x)          (((x)>>24)&0xFFu)
++#define	SET_APIC_ID(x)		(((x)<<24))
++#else
+ #define		APIC_ID_MASK		(0xF<<24)
+-
+ static inline unsigned get_apic_id(unsigned long x) 
+-{ 
++{
+ 	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+ 	if (APIC_XAPIC(ver))
+ 		return (((x)>>24)&0xFF);
+@@ -15,5 +19,6 @@ static inline unsigned get_apic_id(unsigned long x)
+ } 
+ 
+ #define		GET_APIC_ID(x)	get_apic_id(x)
++#endif
+ 
+ #endif
+diff --git a/include/asm-x86/mach-default/mach_ipi.h b/include/asm-x86/mach-default/mach_ipi.h
+index 0dba244..be32336 100644
+--- a/include/asm-x86/mach-default/mach_ipi.h
++++ b/include/asm-x86/mach-default/mach_ipi.h
+@@ -9,10 +9,15 @@ void __send_IPI_shortcut(unsigned int shortcut, int vector);
+ 
+ extern int no_broadcast;
+ 
++#ifdef CONFIG_X86_64
++#include <asm/genapic.h>
++#define send_IPI_mask (genapic->send_IPI_mask)
++#else
+ static inline void send_IPI_mask(cpumask_t mask, int vector)
+ {
+ 	send_IPI_mask_bitmask(mask, vector);
+ }
++#endif
+ 
+ static inline void __local_send_IPI_allbutself(int vector)
+ {
+@@ -33,6 +38,10 @@ static inline void __local_send_IPI_all(int vector)
+ 		__send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+ }
+ 
++#ifdef CONFIG_X86_64
++#define send_IPI_allbutself (genapic->send_IPI_allbutself)
++#define send_IPI_all (genapic->send_IPI_all)
++#else
+ static inline void send_IPI_allbutself(int vector)
+ {
+ 	/*
+@@ -50,5 +59,6 @@ static inline void send_IPI_all(int vector)
+ {
+ 	__local_send_IPI_all(vector);
+ }
++#endif
+ 
+ #endif /* __ASM_MACH_IPI_H */
+diff --git a/include/asm-x86/mach-default/mach_mpparse.h b/include/asm-x86/mach-default/mach_mpparse.h
+index 1d38324..d141085 100644
+--- a/include/asm-x86/mach-default/mach_mpparse.h
++++ b/include/asm-x86/mach-default/mach_mpparse.h
+@@ -1,17 +1,6 @@
+ #ifndef __ASM_MACH_MPPARSE_H
+ #define __ASM_MACH_MPPARSE_H
+ 
+-static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name, 
+-				struct mpc_config_translation *translation)
+-{
+-//	Dprintk("Bus #%d is %s\n", m->mpc_busid, name);
+-}
+-
+-static inline void mpc_oem_pci_bus(struct mpc_config_bus *m, 
+-				struct mpc_config_translation *translation)
+-{
+-}
+-
+ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, 
+ 		char *productid)
+ {
+diff --git a/include/asm-x86/mach-default/mach_reboot.h b/include/asm-x86/mach-default/mach_reboot.h
+deleted file mode 100644
+index 6adee6a..0000000
+--- a/include/asm-x86/mach-default/mach_reboot.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-/*
+- *  arch/i386/mach-generic/mach_reboot.h
+- *
+- *  Machine specific reboot functions for generic.
+- *  Split out from reboot.c by Osamu Tomita <tomita at cinet.co.jp>
+- */
+-#ifndef _MACH_REBOOT_H
+-#define _MACH_REBOOT_H
+-
+-static inline void kb_wait(void)
+-{
+-	int i;
+-
+-	for (i = 0; i < 0x10000; i++)
+-		if ((inb_p(0x64) & 0x02) == 0)
+-			break;
+-}
+-
+-static inline void mach_reboot(void)
+-{
+-	int i;
+-
+-	/* old method, works on most machines */
+-	for (i = 0; i < 10; i++) {
+-		kb_wait();
+-		udelay(50);
+-		outb(0xfe, 0x64);	/* pulse reset low */
+-		udelay(50);
+-	}
+-
+-	/* New method: sets the "System flag" which, when set, indicates
+-	 * successful completion of the keyboard controller self-test (Basic
+-	 * Assurance Test, BAT).  This is needed for some machines with no
+-	 * keyboard plugged in.  This read-modify-write sequence sets only the
+-	 * system flag
+-	 */
+-	for (i = 0; i < 10; i++) {
+-		int cmd;
+-
+-		outb(0x20, 0x64);	/* read Controller Command Byte */
+-		udelay(50);
+-		kb_wait();
+-		udelay(50);
+-		cmd = inb(0x60);
+-		udelay(50);
+-		kb_wait();
+-		udelay(50);
+-		outb(0x60, 0x64);	/* write Controller Command Byte */
+-		udelay(50);
+-		kb_wait();
+-		udelay(50);
+-		outb(cmd | 0x14, 0x60); /* set "System flag" and "Keyboard Disabled" */
+-		udelay(50);
+-		kb_wait();
+-		udelay(50);
+-		outb(0xfe, 0x64);	/* pulse reset low */
+-		udelay(50);
+-	}
+-}
+-
+-#endif /* !_MACH_REBOOT_H */
+diff --git a/include/asm-x86/mach-default/smpboot_hooks.h b/include/asm-x86/mach-default/smpboot_hooks.h
+index 7f45f63..56d0e1f 100644
+--- a/include/asm-x86/mach-default/smpboot_hooks.h
++++ b/include/asm-x86/mach-default/smpboot_hooks.h
+@@ -33,7 +33,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
+ 	*((volatile long *) phys_to_virt(0x467)) = 0;
+ }
+ 
+-static inline void smpboot_setup_io_apic(void)
++static inline void __init smpboot_setup_io_apic(void)
+ {
+ 	/*
+ 	 * Here we can be sure that there is an IO-APIC in the system. Let's
+@@ -41,4 +41,11 @@ static inline void smpboot_setup_io_apic(void)
+ 	 */
+ 	if (!skip_ioapic_setup && nr_ioapics)
+ 		setup_IO_APIC();
++	else
++		nr_ioapics = 0;
++}
++
++static inline void smpboot_clear_io_apic(void)
++{
++	nr_ioapics = 0;
+ }
+diff --git a/include/asm-x86/mach-es7000/mach_apic.h b/include/asm-x86/mach-es7000/mach_apic.h
+index d23011f..fbc8ad2 100644
+--- a/include/asm-x86/mach-es7000/mach_apic.h
++++ b/include/asm-x86/mach-es7000/mach_apic.h
+@@ -1,9 +1,7 @@
+ #ifndef __ASM_MACH_APIC_H
+ #define __ASM_MACH_APIC_H
+ 
+-extern u8 bios_cpu_apicid[];
+-
+-#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu])
++#define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu)
+ #define esr_disable (1)
+ 
+ static inline int apic_id_registered(void)
+@@ -80,7 +78,7 @@ extern void enable_apic_mode(void);
+ extern int apic_version [MAX_APICS];
+ static inline void setup_apic_routing(void)
+ {
+-	int apic = bios_cpu_apicid[smp_processor_id()];
++	int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
+ 	printk("Enabling APIC mode:  %s.  Using %d I/O APICs, target cpus %lx\n",
+ 		(apic_version[apic] == 0x14) ? 
+ 		"Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(TARGET_CPUS)[0]);
+@@ -102,7 +100,7 @@ static inline int cpu_present_to_apicid(int mps_cpu)
+ 	if (!mps_cpu)
+ 		return boot_cpu_physical_apicid;
+ 	else if (mps_cpu < NR_CPUS)
+-		return (int) bios_cpu_apicid[mps_cpu];
++		return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
+ 	else
+ 		return BAD_APICID;
+ }
+@@ -129,16 +127,6 @@ static inline int cpu_to_logical_apicid(int cpu)
+ #endif
+ }
+ 
+-static inline int mpc_apic_id(struct mpc_config_processor *m, struct mpc_config_translation *unused)
+-{
+-	printk("Processor #%d %u:%u APIC version %d\n",
+-	       m->mpc_apicid,
+-	       (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+-	       (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+-	       m->mpc_apicver);
+-	return (m->mpc_apicid);
+-}
+-
+ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
+ {
+ 	/* For clustered we don't have a good way to do this yet - hack */
+@@ -153,7 +141,7 @@ static inline void setup_portio_remap(void)
+ extern unsigned int boot_cpu_physical_apicid;
+ static inline int check_phys_apicid_present(int cpu_physical_apicid)
+ {
+-	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
++	boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+ 	return (1);
+ }
+ 
+diff --git a/include/asm-x86/mach-es7000/mach_mpparse.h b/include/asm-x86/mach-es7000/mach_mpparse.h
+index 52ee75c..ef26d35 100644
+--- a/include/asm-x86/mach-es7000/mach_mpparse.h
++++ b/include/asm-x86/mach-es7000/mach_mpparse.h
+@@ -3,17 +3,6 @@
+ 
+ #include <linux/acpi.h>
+ 
+-static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
+-				struct mpc_config_translation *translation)
+-{
+-	Dprintk("Bus #%d is %s\n", m->mpc_busid, name);
+-}
+-
+-static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
+-				struct mpc_config_translation *translation)
+-{
+-}
+-
+ extern int parse_unisys_oem (char *oemptr);
+ extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
+ extern void setup_unisys(void);
+diff --git a/include/asm-x86/mach-generic/mach_apic.h b/include/asm-x86/mach-generic/mach_apic.h
+index a236e70..6eff343 100644
+--- a/include/asm-x86/mach-generic/mach_apic.h
++++ b/include/asm-x86/mach-generic/mach_apic.h
+@@ -19,7 +19,6 @@
+ #define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid) 
+ #define cpu_present_to_apicid (genapic->cpu_present_to_apicid)
+ #define apicid_to_cpu_present (genapic->apicid_to_cpu_present)
+-#define mpc_apic_id (genapic->mpc_apic_id) 
+ #define setup_portio_remap (genapic->setup_portio_remap)
+ #define check_apicid_present (genapic->check_apicid_present)
+ #define check_phys_apicid_present (genapic->check_phys_apicid_present)
+diff --git a/include/asm-x86/mach-generic/mach_mpparse.h b/include/asm-x86/mach-generic/mach_mpparse.h
+index dbd9fce..0d0b5ba 100644
+--- a/include/asm-x86/mach-generic/mach_mpparse.h
++++ b/include/asm-x86/mach-generic/mach_mpparse.h
+@@ -1,11 +1,6 @@
+ #ifndef _MACH_MPPARSE_H
+ #define _MACH_MPPARSE_H 1
+ 
+-#include <asm/genapic.h>
+-
+-#define mpc_oem_bus_info (genapic->mpc_oem_bus_info)
+-#define mpc_oem_pci_bus (genapic->mpc_oem_pci_bus)
+-
+ int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid); 
+ int acpi_madt_oem_check(char *oem_id, char *oem_table_id); 
+ 
+diff --git a/include/asm-x86/mach-numaq/mach_apic.h b/include/asm-x86/mach-numaq/mach_apic.h
+index 3b637fa..75a56e5 100644
+--- a/include/asm-x86/mach-numaq/mach_apic.h
++++ b/include/asm-x86/mach-numaq/mach_apic.h
+@@ -95,6 +95,16 @@ static inline physid_mask_t apicid_to_cpu_present(int logical_apicid)
+ 	return physid_mask_of_physid(cpu + 4*node);
+ }
+ 
++struct mpc_config_translation {
++	unsigned char mpc_type;
++	unsigned char trans_len;
++	unsigned char trans_type;
++	unsigned char trans_quad;
++	unsigned char trans_global;
++	unsigned char trans_local;
++	unsigned short trans_reserved;
++};
++
+ static inline int mpc_apic_id(struct mpc_config_processor *m, 
+ 			struct mpc_config_translation *translation_record)
+ {
+diff --git a/include/asm-x86/mach-numaq/mach_mpparse.h b/include/asm-x86/mach-numaq/mach_mpparse.h
+index 51bbac8..459b124 100644
+--- a/include/asm-x86/mach-numaq/mach_mpparse.h
++++ b/include/asm-x86/mach-numaq/mach_mpparse.h
+@@ -1,25 +1,10 @@
+ #ifndef __ASM_MACH_MPPARSE_H
+ #define __ASM_MACH_MPPARSE_H
+ 
+-static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name, 
+-				struct mpc_config_translation *translation)
+-{
+-	int quad = translation->trans_quad;
+-	int local = translation->trans_local;
+-
+-	mp_bus_id_to_node[m->mpc_busid] = quad;
+-	mp_bus_id_to_local[m->mpc_busid] = local;
+-	printk("Bus #%d is %s (node %d)\n", m->mpc_busid, name, quad);
+-}
+-
+-static inline void mpc_oem_pci_bus(struct mpc_config_bus *m, 
+-				struct mpc_config_translation *translation)
+-{
+-	int quad = translation->trans_quad;
+-	int local = translation->trans_local;
+-
+-	quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
+-}
++extern void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
++			     struct mpc_config_translation *translation);
++extern void mpc_oem_pci_bus(struct mpc_config_bus *m,
++	struct mpc_config_translation *translation);
+ 
+ /* Hook from generic ACPI tables.c */
+ static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+diff --git a/include/asm-x86/mach-summit/mach_apic.h b/include/asm-x86/mach-summit/mach_apic.h
+index 062c97f..1f76c2e 100644
+--- a/include/asm-x86/mach-summit/mach_apic.h
++++ b/include/asm-x86/mach-summit/mach_apic.h
+@@ -40,7 +40,6 @@ static inline unsigned long check_apicid_present(int bit)
+ 
+ #define apicid_cluster(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK)
+ 
+-extern u8 bios_cpu_apicid[];
+ extern u8 cpu_2_logical_apicid[];
+ 
+ static inline void init_apic_ldr(void)
+@@ -110,7 +109,7 @@ static inline int cpu_to_logical_apicid(int cpu)
+ static inline int cpu_present_to_apicid(int mps_cpu)
+ {
+ 	if (mps_cpu < NR_CPUS)
+-		return (int)bios_cpu_apicid[mps_cpu];
++		return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
+ 	else
+ 		return BAD_APICID;
+ }
+@@ -126,17 +125,6 @@ static inline physid_mask_t apicid_to_cpu_present(int apicid)
+ 	return physid_mask_of_physid(0);
+ }
+ 
+-static inline int mpc_apic_id(struct mpc_config_processor *m,
+-			      struct mpc_config_translation *translation_record)
+-{
+-	printk("Processor #%d %u:%u APIC version %d\n",
+-	       m->mpc_apicid,
+-	       (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+-	       (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+-	       m->mpc_apicver);
+-	return m->mpc_apicid;
+-}
+-
+ static inline void setup_portio_remap(void)
+ {
+ }
+diff --git a/include/asm-x86/mach-summit/mach_mpparse.h b/include/asm-x86/mach-summit/mach_mpparse.h
+index c252053..fdf5917 100644
+--- a/include/asm-x86/mach-summit/mach_mpparse.h
++++ b/include/asm-x86/mach-summit/mach_mpparse.h
+@@ -12,17 +12,6 @@ extern void setup_summit(void);
+ #define setup_summit()	{}
+ #endif
+ 
+-static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name, 
+-				struct mpc_config_translation *translation)
+-{
+-	Dprintk("Bus #%d is %s\n", m->mpc_busid, name);
+-}
+-
+-static inline void mpc_oem_pci_bus(struct mpc_config_bus *m, 
+-				struct mpc_config_translation *translation)
+-{
+-}
+-
+ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, 
+ 		char *productid)
+ {
+diff --git a/include/asm-x86/mach-visws/mach_apic.h b/include/asm-x86/mach-visws/mach_apic.h
+index efac6f0..a9ef33a 100644
+--- a/include/asm-x86/mach-visws/mach_apic.h
++++ b/include/asm-x86/mach-visws/mach_apic.h
+@@ -23,7 +23,7 @@
+ 
+ static inline int apic_id_registered(void)
+ {
+-	return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
++	return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map);
+ }
+ 
+ /*
+diff --git a/include/asm-x86/mach-visws/smpboot_hooks.h b/include/asm-x86/mach-visws/smpboot_hooks.h
+index d926471..c9b83e3 100644
+--- a/include/asm-x86/mach-visws/smpboot_hooks.h
++++ b/include/asm-x86/mach-visws/smpboot_hooks.h
+@@ -22,3 +22,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
+ static inline void smpboot_setup_io_apic(void)
+ {
+ }
++
++static inline void smpboot_clear_io_apic(void)
++{
++}
+diff --git a/include/asm-x86/mach_apic.h b/include/asm-x86/mach_apic.h
+deleted file mode 100644
+index 7b7115a..0000000
+--- a/include/asm-x86/mach_apic.h
++++ /dev/null
+@@ -1,29 +0,0 @@
+-#ifndef __ASM_MACH_APIC_H
+-#define __ASM_MACH_APIC_H
+-
+-/*
+- * Copyright 2004 James Cleverdon, IBM.
+- * Subject to the GNU Public License, v.2
+- *
+- * Generic APIC sub-arch defines.
+- *
+- * Hacked for x86-64 by James Cleverdon from i386 architecture code by
+- * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+- * James Cleverdon.
+- */
+-
+-#include <asm/genapic.h>
+-
+-#define INT_DELIVERY_MODE (genapic->int_delivery_mode)
+-#define INT_DEST_MODE (genapic->int_dest_mode)
+-#define TARGET_CPUS	  (genapic->target_cpus())
+-#define vector_allocation_domain	(genapic->vector_allocation_domain)
+-#define apic_id_registered (genapic->apic_id_registered)
+-#define init_apic_ldr (genapic->init_apic_ldr)
+-#define send_IPI_mask (genapic->send_IPI_mask)
+-#define send_IPI_allbutself (genapic->send_IPI_allbutself)
+-#define send_IPI_all (genapic->send_IPI_all)
+-#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
+-#define phys_pkg_id	(genapic->phys_pkg_id)
+-
+-#endif /* __ASM_MACH_APIC_H */
+diff --git a/include/asm-x86/mc146818rtc.h b/include/asm-x86/mc146818rtc.h
+index cdd9f96..daf1ccd 100644
+--- a/include/asm-x86/mc146818rtc.h
++++ b/include/asm-x86/mc146818rtc.h
+@@ -42,7 +42,7 @@ extern volatile unsigned long cmos_lock;
+ static inline void lock_cmos(unsigned char reg)
+ {
+ 	unsigned long new;
+-	new = ((smp_processor_id()+1) << 8) | reg;
++	new = ((smp_processor_id() + 1) << 8) | reg;
+ 	for (;;) {
+ 		if (cmos_lock) {
+ 			cpu_relax();
+@@ -57,22 +57,26 @@ static inline void unlock_cmos(void)
+ {
+ 	cmos_lock = 0;
+ }
++
+ static inline int do_i_have_lock_cmos(void)
+ {
+-	return (cmos_lock >> 8) == (smp_processor_id()+1);
++	return (cmos_lock >> 8) == (smp_processor_id() + 1);
+ }
++
+ static inline unsigned char current_lock_cmos_reg(void)
+ {
+ 	return cmos_lock & 0xff;
+ }
+-#define lock_cmos_prefix(reg) \
++
++#define lock_cmos_prefix(reg)			\
+ 	do {					\
+ 		unsigned long cmos_flags;	\
+ 		local_irq_save(cmos_flags);	\
+ 		lock_cmos(reg)
+-#define lock_cmos_suffix(reg) \
+-		unlock_cmos();			\
+-		local_irq_restore(cmos_flags);	\
++
++#define lock_cmos_suffix(reg)			\
++	unlock_cmos();				\
++	local_irq_restore(cmos_flags);		\
+ 	} while (0)
+ #else
+ #define lock_cmos_prefix(reg) do {} while (0)
+diff --git a/include/asm-x86/mca_dma.h b/include/asm-x86/mca_dma.h
+index fbb1f3b..c3dca6e 100644
+--- a/include/asm-x86/mca_dma.h
++++ b/include/asm-x86/mca_dma.h
+@@ -12,18 +12,18 @@
+  *   count by 2 when using 16-bit dma; that is not handled by these functions.
+  *
+  * Ramen Noodles are yummy.
+- * 
+- *  1998 Tymm Twillman <tymm at computer.org>  
++ *
++ *  1998 Tymm Twillman <tymm at computer.org>
+  */
+ 
+ /*
+- * Registers that are used by the DMA controller; FN is the function register 
++ * Registers that are used by the DMA controller; FN is the function register
+  *   (tell the controller what to do) and EXE is the execution register (how
+  *   to do it)
+  */
+ 
+ #define MCA_DMA_REG_FN  0x18
+-#define MCA_DMA_REG_EXE 0x1A 
++#define MCA_DMA_REG_EXE 0x1A
+ 
+ /*
+  * Functions that the DMA controller can do
+@@ -43,9 +43,9 @@
+ 
+ /*
+  * Modes (used by setting MCA_DMA_FN_MODE in the function register)
+- * 
++ *
+  * Note that the MODE_READ is read from memory (write to device), and
+- *   MODE_WRITE is vice-versa.  
++ *   MODE_WRITE is vice-versa.
+  */
+ 
+ #define MCA_DMA_MODE_XFER  0x04  /* read by default */
+@@ -63,7 +63,7 @@
+  *	IRQ context.
+  */
+ 
+-static __inline__ void mca_enable_dma(unsigned int dmanr)
++static inline void mca_enable_dma(unsigned int dmanr)
+ {
+ 	outb(MCA_DMA_FN_RESET_MASK | dmanr, MCA_DMA_REG_FN);
+ }
+@@ -76,7 +76,7 @@ static __inline__ void mca_enable_dma(unsigned int dmanr)
+  *	IRQ context.
+  */
+ 
+-static __inline__ void mca_disable_dma(unsigned int dmanr)
++static inline void mca_disable_dma(unsigned int dmanr)
+ {
+ 	outb(MCA_DMA_FN_MASK | dmanr, MCA_DMA_REG_FN);
+ }
+@@ -87,10 +87,10 @@ static __inline__ void mca_disable_dma(unsigned int dmanr)
+  *	@a: 24bit bus address
+  *
+  *	Load the address register in the DMA controller. This has a 24bit
+- *	limitation (16Mb). 
++ *	limitation (16Mb).
+  */
+ 
+-static __inline__ void mca_set_dma_addr(unsigned int dmanr, unsigned int a)
++static inline void mca_set_dma_addr(unsigned int dmanr, unsigned int a)
+ {
+ 	outb(MCA_DMA_FN_SET_ADDR | dmanr, MCA_DMA_REG_FN);
+ 	outb(a & 0xff, MCA_DMA_REG_EXE);
+@@ -106,14 +106,14 @@ static __inline__ void mca_set_dma_addr(unsigned int dmanr, unsigned int a)
+  *	limitation (16Mb). The return is a bus address.
+  */
+ 
+-static __inline__ unsigned int mca_get_dma_addr(unsigned int dmanr)
++static inline unsigned int mca_get_dma_addr(unsigned int dmanr)
+ {
+ 	unsigned int addr;
+ 
+ 	outb(MCA_DMA_FN_GET_ADDR | dmanr, MCA_DMA_REG_FN);
+ 	addr = inb(MCA_DMA_REG_EXE);
+ 	addr |= inb(MCA_DMA_REG_EXE) << 8;
+-	addr |= inb(MCA_DMA_REG_EXE) << 16;  
++	addr |= inb(MCA_DMA_REG_EXE) << 16;
+ 
+ 	return addr;
+ }
+@@ -127,7 +127,7 @@ static __inline__ unsigned int mca_get_dma_addr(unsigned int dmanr)
+  *	Setting a count of zero will not do what you expect.
+  */
+ 
+-static __inline__ void mca_set_dma_count(unsigned int dmanr, unsigned int count)
++static inline void mca_set_dma_count(unsigned int dmanr, unsigned int count)
+ {
+ 	count--;  /* transfers one more than count -- correct for this */
+ 
+@@ -144,7 +144,7 @@ static __inline__ void mca_set_dma_count(unsigned int dmanr, unsigned int count)
+  *	on this DMA channel.
+  */
+ 
+-static __inline__ unsigned int mca_get_dma_residue(unsigned int dmanr)
++static inline unsigned int mca_get_dma_residue(unsigned int dmanr)
+ {
+ 	unsigned short count;
+ 
+@@ -164,12 +164,12 @@ static __inline__ unsigned int mca_get_dma_residue(unsigned int dmanr)
+  *	with an I/O port target.
+  */
+ 
+-static __inline__ void mca_set_dma_io(unsigned int dmanr, unsigned int io_addr)
++static inline void mca_set_dma_io(unsigned int dmanr, unsigned int io_addr)
+ {
+ 	/*
+ 	 * DMA from a port address -- set the io address
+ 	 */
+-	
++
+ 	outb(MCA_DMA_FN_SET_IO | dmanr, MCA_DMA_REG_FN);
+ 	outb(io_addr & 0xff, MCA_DMA_REG_EXE);
+ 	outb((io_addr >>  8) & 0xff, MCA_DMA_REG_EXE);
+@@ -192,7 +192,7 @@ static __inline__ void mca_set_dma_io(unsigned int dmanr, unsigned int io_addr)
+  *	%MCA_DMA_MODE_16 to do 16bit transfers.
+  */
+ 
+-static __inline__ void mca_set_dma_mode(unsigned int dmanr, unsigned int mode)
++static inline void mca_set_dma_mode(unsigned int dmanr, unsigned int mode)
+ {
+ 	outb(MCA_DMA_FN_SET_MODE | dmanr, MCA_DMA_REG_FN);
+ 	outb(mode, MCA_DMA_REG_EXE);
+diff --git a/include/asm-x86/mmu.h b/include/asm-x86/mmu.h
+index efa962c..00e8867 100644
+--- a/include/asm-x86/mmu.h
++++ b/include/asm-x86/mmu.h
+@@ -10,10 +10,10 @@
+  *
+  * cpu_vm_mask is used to optimize ldt flushing.
+  */
+-typedef struct { 
++typedef struct {
+ 	void *ldt;
+ #ifdef CONFIG_X86_64
+-	rwlock_t ldtlock; 
++	rwlock_t ldtlock;
+ #endif
+ 	int size;
+ 	struct mutex lock;
+diff --git a/include/asm-x86/mmu_context_32.h b/include/asm-x86/mmu_context_32.h
+index 8198d1c..9756ae0 100644
+--- a/include/asm-x86/mmu_context_32.h
++++ b/include/asm-x86/mmu_context_32.h
+@@ -62,7 +62,7 @@ static inline void switch_mm(struct mm_struct *prev,
+ 		BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next);
+ 
+ 		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+-			/* We were in lazy tlb mode and leave_mm disabled 
++			/* We were in lazy tlb mode and leave_mm disabled
+ 			 * tlb flush IPI delivery. We must reload %cr3.
+ 			 */
+ 			load_cr3(next->pgd);
+@@ -75,10 +75,10 @@ static inline void switch_mm(struct mm_struct *prev,
+ #define deactivate_mm(tsk, mm)			\
+ 	asm("movl %0,%%gs": :"r" (0));
+ 
+-#define activate_mm(prev, next)				\
+-	do {						\
+-		paravirt_activate_mm(prev, next);	\
+-		switch_mm((prev),(next),NULL);		\
+-	} while(0);
++#define activate_mm(prev, next)			\
++do {						\
++	paravirt_activate_mm((prev), (next));	\
++	switch_mm((prev), (next), NULL);	\
++} while (0);
+ 
+ #endif
+diff --git a/include/asm-x86/mmu_context_64.h b/include/asm-x86/mmu_context_64.h
+index ad6dc82..ca44c71 100644
+--- a/include/asm-x86/mmu_context_64.h
++++ b/include/asm-x86/mmu_context_64.h
+@@ -20,12 +20,12 @@ void destroy_context(struct mm_struct *mm);
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
+ #ifdef CONFIG_SMP
+-	if (read_pda(mmu_state) == TLBSTATE_OK) 
++	if (read_pda(mmu_state) == TLBSTATE_OK)
+ 		write_pda(mmu_state, TLBSTATE_LAZY);
+ #endif
+ }
+ 
+-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
++static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ 			     struct task_struct *tsk)
+ {
+ 	unsigned cpu = smp_processor_id();
+@@ -39,7 +39,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ 		cpu_set(cpu, next->cpu_vm_mask);
+ 		load_cr3(next->pgd);
+ 
+-		if (unlikely(next->context.ldt != prev->context.ldt)) 
++		if (unlikely(next->context.ldt != prev->context.ldt))
+ 			load_LDT_nolock(&next->context);
+ 	}
+ #ifdef CONFIG_SMP
+@@ -48,7 +48,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ 		if (read_pda(active_mm) != next)
+ 			BUG();
+ 		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+-			/* We were in lazy tlb mode and leave_mm disabled 
++			/* We were in lazy tlb mode and leave_mm disabled
+ 			 * tlb flush IPI delivery. We must reload CR3
+ 			 * to make sure to use no freed page tables.
+ 			 */
+@@ -59,13 +59,14 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ #endif
+ }
+ 
+-#define deactivate_mm(tsk,mm)	do { \
+-	load_gs_index(0); \
+-	asm volatile("movl %0,%%fs"::"r"(0));  \
+-} while(0)
++#define deactivate_mm(tsk, mm)			\
++do {						\
++	load_gs_index(0);			\
++	asm volatile("movl %0,%%fs"::"r"(0));	\
++} while (0)
+ 
+-#define activate_mm(prev, next) \
+-	switch_mm((prev),(next),NULL)
++#define activate_mm(prev, next)			\
++	switch_mm((prev), (next), NULL)
+ 
+ 
+ #endif
+diff --git a/include/asm-x86/mmx.h b/include/asm-x86/mmx.h
+index 46b71da..9408812 100644
+--- a/include/asm-x86/mmx.h
++++ b/include/asm-x86/mmx.h
+@@ -6,7 +6,7 @@
+  */
+ 
+ #include <linux/types.h>
+- 
++
+ extern void *_mmx_memcpy(void *to, const void *from, size_t size);
+ extern void mmx_clear_page(void *page);
+ extern void mmx_copy_page(void *to, void *from);
+diff --git a/include/asm-x86/mmzone_32.h b/include/asm-x86/mmzone_32.h
+index 274a595..cb2cad0 100644
+--- a/include/asm-x86/mmzone_32.h
++++ b/include/asm-x86/mmzone_32.h
+@@ -18,7 +18,7 @@ extern struct pglist_data *node_data[];
+ 	#include <asm/srat.h>
+ #endif
+ 
+-extern int get_memcfg_numa_flat(void );
++extern int get_memcfg_numa_flat(void);
+ /*
+  * This allows any one NUMA architecture to be compiled
+  * for, and still fall back to the flat function if it
+@@ -129,7 +129,7 @@ static inline int pfn_valid(int pfn)
+ 	struct pglist_data  __maybe_unused			\
+ 				*__alloc_bootmem_node__pgdat = (pgdat);	\
+ 	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE,		\
+-						__pa(MAX_DMA_ADDRESS))	\
++						__pa(MAX_DMA_ADDRESS));	\
+ })
+ #define alloc_bootmem_low_pages_node(pgdat, x)				\
+ ({									\
+diff --git a/include/asm-x86/mmzone_64.h b/include/asm-x86/mmzone_64.h
+index ebaf966..594bd0d 100644
+--- a/include/asm-x86/mmzone_64.h
++++ b/include/asm-x86/mmzone_64.h
+@@ -7,7 +7,7 @@
+ 
+ #ifdef CONFIG_NUMA
+ 
+-#define VIRTUAL_BUG_ON(x) 
++#define VIRTUAL_BUG_ON(x)
+ 
+ #include <asm/smp.h>
+ 
+@@ -16,7 +16,7 @@ struct memnode {
+ 	int shift;
+ 	unsigned int mapsize;
+ 	s16 *map;
+-	s16 embedded_map[64-8];
++	s16 embedded_map[64 - 8];
+ } ____cacheline_aligned; /* total size = 128 bytes */
+ extern struct memnode memnode;
+ #define memnode_shift memnode.shift
+@@ -25,27 +25,27 @@ extern struct memnode memnode;
+ 
+ extern struct pglist_data *node_data[];
+ 
+-static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) 
+-{ 
+-	unsigned nid; 
++static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
++{
++	unsigned nid;
+ 	VIRTUAL_BUG_ON(!memnodemap);
+ 	VIRTUAL_BUG_ON((addr >> memnode_shift) >= memnodemapsize);
+-	nid = memnodemap[addr >> memnode_shift]; 
+-	VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]); 
+-	return nid; 
+-} 
++	nid = memnodemap[addr >> memnode_shift];
++	VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]);
++	return nid;
++}
+ 
+ #define NODE_DATA(nid)		(node_data[nid])
+ 
+ #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
+-#define node_end_pfn(nid)       (NODE_DATA(nid)->node_start_pfn + \
++#define node_end_pfn(nid)       (NODE_DATA(nid)->node_start_pfn +	\
+ 				 NODE_DATA(nid)->node_spanned_pages)
+ 
+ extern int early_pfn_to_nid(unsigned long pfn);
+ 
+ #ifdef CONFIG_NUMA_EMU
+-#define FAKE_NODE_MIN_SIZE	(64*1024*1024)
+-#define FAKE_NODE_MIN_HASH_MASK	(~(FAKE_NODE_MIN_SIZE - 1uL))
++#define FAKE_NODE_MIN_SIZE	(64 * 1024 * 1024)
++#define FAKE_NODE_MIN_HASH_MASK	(~(FAKE_NODE_MIN_SIZE - 1UL))
+ #endif
+ 
+ #endif
+diff --git a/include/asm-x86/mpspec.h b/include/asm-x86/mpspec.h
+index 781ad74..57a991b 100644
+--- a/include/asm-x86/mpspec.h
++++ b/include/asm-x86/mpspec.h
+@@ -1,16 +1,13 @@
+ #ifndef _AM_X86_MPSPEC_H
+ #define _AM_X86_MPSPEC_H
+ 
++#include <linux/init.h>
++
+ #include <asm/mpspec_def.h>
+ 
+ #ifdef CONFIG_X86_32
+ #include <mach_mpspec.h>
+ 
+-extern int mp_bus_id_to_type[MAX_MP_BUSSES];
+-extern int mp_bus_id_to_node[MAX_MP_BUSSES];
+-extern int mp_bus_id_to_local[MAX_MP_BUSSES];
+-extern int quad_local_to_mp_bus_id[NR_CPUS/4][4];
+-
+ extern unsigned int def_to_bigsmp;
+ extern int apic_version[MAX_APICS];
+ extern u8 apicid_2_node[];
+@@ -24,27 +21,30 @@ extern int pic_mode;
+ /* Each PCI slot may be a combo card with its own bus.  4 IRQ pins per slot. */
+ #define MAX_IRQ_SOURCES (MAX_MP_BUSSES * 4)
+ 
+-extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++extern void early_find_smp_config(void);
++extern void early_get_smp_config(void);
+ 
+ #endif
+ 
++#if defined(CONFIG_MCA) || defined(CONFIG_EISA)
++extern int mp_bus_id_to_type[MAX_MP_BUSSES];
++#endif
++
++extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++
+ extern int mp_bus_id_to_pci_bus[MAX_MP_BUSSES];
+ 
+ extern unsigned int boot_cpu_physical_apicid;
+ extern int smp_found_config;
+-extern int nr_ioapics;
+-extern int mp_irq_entries;
+-extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+ extern int mpc_default_type;
+ extern unsigned long mp_lapic_addr;
+ 
+ extern void find_smp_config(void);
+ extern void get_smp_config(void);
+ 
++void __cpuinit generic_processor_info(int apicid, int version);
+ #ifdef CONFIG_ACPI
+-extern void mp_register_lapic(u8 id, u8 enabled);
+-extern void mp_register_lapic_address(u64 address);
+-extern void mp_register_ioapic(u8 id, u32 address, u32 gsi_base);
++extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
+ extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ 				   u32 gsi);
+ extern void mp_config_acpi_legacy_irqs(void);
+@@ -53,8 +53,7 @@ extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+ 
+ #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
+ 
+-struct physid_mask
+-{
++struct physid_mask {
+ 	unsigned long mask[PHYSID_ARRAY_SIZE];
+ };
+ 
+@@ -63,34 +62,34 @@ typedef struct physid_mask physid_mask_t;
+ #define physid_set(physid, map)			set_bit(physid, (map).mask)
+ #define physid_clear(physid, map)		clear_bit(physid, (map).mask)
+ #define physid_isset(physid, map)		test_bit(physid, (map).mask)
+-#define physid_test_and_set(physid, map) \
++#define physid_test_and_set(physid, map)			\
+ 	test_and_set_bit(physid, (map).mask)
+ 
+-#define physids_and(dst, src1, src2) \
++#define physids_and(dst, src1, src2)					\
+ 	bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+ 
+-#define physids_or(dst, src1, src2) \
++#define physids_or(dst, src1, src2)					\
+ 	bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+ 
+-#define physids_clear(map) \
++#define physids_clear(map)					\
+ 	bitmap_zero((map).mask, MAX_APICS)
+ 
+-#define physids_complement(dst, src) \
++#define physids_complement(dst, src)				\
+ 	bitmap_complement((dst).mask, (src).mask, MAX_APICS)
+ 
+-#define physids_empty(map) \
++#define physids_empty(map)					\
+ 	bitmap_empty((map).mask, MAX_APICS)
+ 
+-#define physids_equal(map1, map2) \
++#define physids_equal(map1, map2)				\
+ 	bitmap_equal((map1).mask, (map2).mask, MAX_APICS)
+ 
+-#define physids_weight(map) \
++#define physids_weight(map)					\
+ 	bitmap_weight((map).mask, MAX_APICS)
+ 
+-#define physids_shift_right(d, s, n) \
++#define physids_shift_right(d, s, n)				\
+ 	bitmap_shift_right((d).mask, (s).mask, n, MAX_APICS)
+ 
+-#define physids_shift_left(d, s, n) \
++#define physids_shift_left(d, s, n)				\
+ 	bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS)
+ 
+ #define physids_coerce(map)			((map).mask[0])
+diff --git a/include/asm-x86/mpspec_def.h b/include/asm-x86/mpspec_def.h
+index 3504617..dc6ef85 100644
+--- a/include/asm-x86/mpspec_def.h
++++ b/include/asm-x86/mpspec_def.h
+@@ -11,7 +11,7 @@
+  * information is.
+  */
+ 
+-#define SMP_MAGIC_IDENT	(('_'<<24)|('P'<<16)|('M'<<8)|'_')
++#define SMP_MAGIC_IDENT	(('_'<<24) | ('P'<<16) | ('M'<<8) | '_')
+ 
+ #ifdef CONFIG_X86_32
+ # define MAX_MPC_ENTRY 1024
+@@ -23,8 +23,7 @@
+ # define MAX_APICS 255
+ #endif
+ 
+-struct intel_mp_floating
+-{
++struct intel_mp_floating {
+ 	char mpf_signature[4];		/* "_MP_"			*/
+ 	unsigned int mpf_physptr;	/* Configuration table address	*/
+ 	unsigned char mpf_length;	/* Our length (paragraphs)	*/
+@@ -39,14 +38,13 @@ struct intel_mp_floating
+ 
+ #define MPC_SIGNATURE "PCMP"
+ 
+-struct mp_config_table
+-{
++struct mp_config_table {
+ 	char mpc_signature[4];
+ 	unsigned short mpc_length;	/* Size of table */
+-	char  mpc_spec;			/* 0x01 */
+-	char  mpc_checksum;
+-	char  mpc_oem[8];
+-	char  mpc_productid[12];
++	char mpc_spec;			/* 0x01 */
++	char mpc_checksum;
++	char mpc_oem[8];
++	char mpc_productid[12];
+ 	unsigned int mpc_oemptr;	/* 0 if not present */
+ 	unsigned short mpc_oemsize;	/* 0 if not present */
+ 	unsigned short mpc_oemcount;
+@@ -71,8 +69,7 @@ struct mp_config_table
+ #define CPU_MODEL_MASK		0x00F0
+ #define CPU_FAMILY_MASK		0x0F00
+ 
+-struct mpc_config_processor
+-{
++struct mpc_config_processor {
+ 	unsigned char mpc_type;
+ 	unsigned char mpc_apicid;	/* Local APIC number */
+ 	unsigned char mpc_apicver;	/* Its versions */
+@@ -82,8 +79,7 @@ struct mpc_config_processor
+ 	unsigned int mpc_reserved[2];
+ };
+ 
+-struct mpc_config_bus
+-{
++struct mpc_config_bus {
+ 	unsigned char mpc_type;
+ 	unsigned char mpc_busid;
+ 	unsigned char mpc_bustype[6];
+@@ -111,8 +107,7 @@ struct mpc_config_bus
+ 
+ #define MPC_APIC_USABLE		0x01
+ 
+-struct mpc_config_ioapic
+-{
++struct mpc_config_ioapic {
+ 	unsigned char mpc_type;
+ 	unsigned char mpc_apicid;
+ 	unsigned char mpc_apicver;
+@@ -120,8 +115,7 @@ struct mpc_config_ioapic
+ 	unsigned int mpc_apicaddr;
+ };
+ 
+-struct mpc_config_intsrc
+-{
++struct mpc_config_intsrc {
+ 	unsigned char mpc_type;
+ 	unsigned char mpc_irqtype;
+ 	unsigned short mpc_irqflag;
+@@ -144,8 +138,7 @@ enum mp_irq_source_types {
+ 
+ #define MP_APIC_ALL	0xFF
+ 
+-struct mpc_config_lintsrc
+-{
++struct mpc_config_lintsrc {
+ 	unsigned char mpc_type;
+ 	unsigned char mpc_irqtype;
+ 	unsigned short mpc_irqflag;
+@@ -157,8 +150,7 @@ struct mpc_config_lintsrc
+ 
+ #define MPC_OEM_SIGNATURE "_OEM"
+ 
+-struct mp_config_oemtable
+-{
++struct mp_config_oemtable {
+ 	char oem_signature[4];
+ 	unsigned short oem_length;	/* Size of table */
+ 	char  oem_rev;			/* 0x01 */
+@@ -166,17 +158,6 @@ struct mp_config_oemtable
+ 	char  mpc_oem[8];
+ };
+ 
+-struct mpc_config_translation
+-{
+-	unsigned char mpc_type;
+-	unsigned char trans_len;
+-	unsigned char trans_type;
+-	unsigned char trans_quad;
+-	unsigned char trans_global;
+-	unsigned char trans_local;
+-	unsigned short trans_reserved;
+-};
+-
+ /*
+  *	Default configurations
+  *
+@@ -196,4 +177,3 @@ enum mp_bustype {
+ 	MP_BUS_MCA,
+ };
+ #endif
+-
+diff --git a/include/asm-x86/msidef.h b/include/asm-x86/msidef.h
+index 5b8acdd..296f29c 100644
+--- a/include/asm-x86/msidef.h
++++ b/include/asm-x86/msidef.h
+@@ -11,7 +11,8 @@
+ 
+ #define MSI_DATA_VECTOR_SHIFT		0
+ #define  MSI_DATA_VECTOR_MASK		0x000000ff
+-#define	 MSI_DATA_VECTOR(v)		(((v) << MSI_DATA_VECTOR_SHIFT) & MSI_DATA_VECTOR_MASK)
++#define	 MSI_DATA_VECTOR(v)		(((v) << MSI_DATA_VECTOR_SHIFT) & \
++					 MSI_DATA_VECTOR_MASK)
+ 
+ #define MSI_DATA_DELIVERY_MODE_SHIFT	8
+ #define  MSI_DATA_DELIVERY_FIXED	(0 << MSI_DATA_DELIVERY_MODE_SHIFT)
+@@ -37,11 +38,14 @@
+ #define	 MSI_ADDR_DEST_MODE_LOGICAL	(1 << MSI_ADDR_DEST_MODE_SHIFT)
+ 
+ #define MSI_ADDR_REDIRECTION_SHIFT	3
+-#define  MSI_ADDR_REDIRECTION_CPU	(0 << MSI_ADDR_REDIRECTION_SHIFT) /* dedicated cpu */
+-#define  MSI_ADDR_REDIRECTION_LOWPRI	(1 << MSI_ADDR_REDIRECTION_SHIFT) /* lowest priority */
++#define  MSI_ADDR_REDIRECTION_CPU	(0 << MSI_ADDR_REDIRECTION_SHIFT)
++					/* dedicated cpu */
++#define  MSI_ADDR_REDIRECTION_LOWPRI	(1 << MSI_ADDR_REDIRECTION_SHIFT)
++					/* lowest priority */
+ 
+ #define MSI_ADDR_DEST_ID_SHIFT		12
+ #define	 MSI_ADDR_DEST_ID_MASK		0x00ffff0
+-#define  MSI_ADDR_DEST_ID(dest)		(((dest) << MSI_ADDR_DEST_ID_SHIFT) & MSI_ADDR_DEST_ID_MASK)
++#define  MSI_ADDR_DEST_ID(dest)		(((dest) << MSI_ADDR_DEST_ID_SHIFT) & \
++					 MSI_ADDR_DEST_ID_MASK)
+ 
+ #endif /* ASM_MSIDEF_H */
+diff --git a/include/asm-x86/msr-index.h b/include/asm-x86/msr-index.h
+index fae118a..09413ad 100644
+--- a/include/asm-x86/msr-index.h
++++ b/include/asm-x86/msr-index.h
+@@ -57,6 +57,8 @@
+ #define MSR_MTRRfix4K_F8000		0x0000026f
+ #define MSR_MTRRdefType			0x000002ff
+ 
++#define MSR_IA32_CR_PAT			0x00000277
++
+ #define MSR_IA32_DEBUGCTLMSR		0x000001d9
+ #define MSR_IA32_LASTBRANCHFROMIP	0x000001db
+ #define MSR_IA32_LASTBRANCHTOIP		0x000001dc
+@@ -83,6 +85,7 @@
+ /* AMD64 MSRs. Not complete. See the architecture manual for a more
+    complete list. */
+ 
++#define MSR_AMD64_NB_CFG		0xc001001f
+ #define MSR_AMD64_IBSFETCHCTL		0xc0011030
+ #define MSR_AMD64_IBSFETCHLINAD		0xc0011031
+ #define MSR_AMD64_IBSFETCHPHYSAD	0xc0011032
+@@ -109,6 +112,7 @@
+ #define MSR_K8_SYSCFG			0xc0010010
+ #define MSR_K8_HWCR			0xc0010015
+ #define MSR_K8_ENABLE_C1E		0xc0010055
++#define MSR_K8_TSEG_ADDR		0xc0010112
+ #define K8_MTRRFIXRANGE_DRAM_ENABLE	0x00040000 /* MtrrFixDramEn bit    */
+ #define K8_MTRRFIXRANGE_DRAM_MODIFY	0x00080000 /* MtrrFixDramModEn bit */
+ #define K8_MTRR_RDMEM_WRMEM_MASK	0x18181818 /* Mask: RdMem|WrMem    */
+diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h
+index 3ca29eb..3707650 100644
+--- a/include/asm-x86/msr.h
++++ b/include/asm-x86/msr.h
+@@ -16,8 +16,8 @@
+ static inline unsigned long long native_read_tscp(unsigned int *aux)
+ {
+ 	unsigned long low, high;
+-	asm volatile (".byte 0x0f,0x01,0xf9"
+-		      : "=a" (low), "=d" (high), "=c" (*aux));
++	asm volatile(".byte 0x0f,0x01,0xf9"
++		     : "=a" (low), "=d" (high), "=c" (*aux));
+ 	return low | ((u64)high >> 32);
+ }
+ 
+@@ -29,7 +29,7 @@ static inline unsigned long long native_read_tscp(unsigned int *aux)
+  */
+ #ifdef CONFIG_X86_64
+ #define DECLARE_ARGS(val, low, high)	unsigned low, high
+-#define EAX_EDX_VAL(val, low, high)	(low | ((u64)(high) << 32))
++#define EAX_EDX_VAL(val, low, high)	((low) | ((u64)(high) << 32))
+ #define EAX_EDX_ARGS(val, low, high)	"a" (low), "d" (high)
+ #define EAX_EDX_RET(val, low, high)	"=a" (low), "=d" (high)
+ #else
+@@ -57,7 +57,7 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
+ 		     ".section .fixup,\"ax\"\n\t"
+ 		     "3:  mov %3,%0 ; jmp 1b\n\t"
+ 		     ".previous\n\t"
+-		     _ASM_EXTABLE(2b,3b)
++		     _ASM_EXTABLE(2b, 3b)
+ 		     : "=r" (*err), EAX_EDX_RET(val, low, high)
+ 		     : "c" (msr), "i" (-EFAULT));
+ 	return EAX_EDX_VAL(val, low, high);
+@@ -78,10 +78,10 @@ static inline int native_write_msr_safe(unsigned int msr,
+ 		     ".section .fixup,\"ax\"\n\t"
+ 		     "3:  mov %4,%0 ; jmp 1b\n\t"
+ 		     ".previous\n\t"
+-		     _ASM_EXTABLE(2b,3b)
++		     _ASM_EXTABLE(2b, 3b)
+ 		     : "=a" (err)
+ 		     : "c" (msr), "0" (low), "d" (high),
+-		       "i" (-EFAULT));
++		     "i" (-EFAULT));
+ 	return err;
+ }
+ 
+@@ -116,23 +116,23 @@ static inline unsigned long long native_read_pmc(int counter)
+  * pointer indirection), this allows gcc to optimize better
+  */
+ 
+-#define rdmsr(msr,val1,val2)						\
+-	do {								\
+-		u64 __val = native_read_msr(msr);			\
+-		(val1) = (u32)__val;					\
+-		(val2) = (u32)(__val >> 32);				\
+-	} while(0)
++#define rdmsr(msr, val1, val2)					\
++do {								\
++	u64 __val = native_read_msr((msr));			\
++	(val1) = (u32)__val;					\
++	(val2) = (u32)(__val >> 32);				\
++} while (0)
+ 
+ static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
+ {
+ 	native_write_msr(msr, low, high);
+ }
+ 
+-#define rdmsrl(msr,val)							\
+-	((val) = native_read_msr(msr))
++#define rdmsrl(msr, val)			\
++	((val) = native_read_msr((msr)))
+ 
+ #define wrmsrl(msr, val)						\
+-	native_write_msr(msr, (u32)((u64)(val)), (u32)((u64)(val) >> 32))
++	native_write_msr((msr), (u32)((u64)(val)), (u32)((u64)(val) >> 32))
+ 
+ /* wrmsr with exception handling */
+ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
+@@ -141,14 +141,22 @@ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
+ }
+ 
+ /* rdmsr with exception handling */
+-#define rdmsr_safe(msr,p1,p2)						\
+-	({								\
+-		int __err;						\
+-		u64 __val = native_read_msr_safe(msr, &__err);		\
+-		(*p1) = (u32)__val;					\
+-		(*p2) = (u32)(__val >> 32);				\
+-		__err;							\
+-	})
++#define rdmsr_safe(msr, p1, p2)					\
++({								\
++	int __err;						\
++	u64 __val = native_read_msr_safe((msr), &__err);	\
++	(*p1) = (u32)__val;					\
++	(*p2) = (u32)(__val >> 32);				\
++	__err;							\
++})
++
++static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
++{
++	int err;
++
++	*p = native_read_msr_safe(msr, &err);
++	return err;
++}
+ 
+ #define rdtscl(low)						\
+ 	((low) = (u32)native_read_tsc())
+@@ -156,35 +164,37 @@ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
+ #define rdtscll(val)						\
+ 	((val) = native_read_tsc())
+ 
+-#define rdpmc(counter,low,high)					\
+-	do {							\
+-		u64 _l = native_read_pmc(counter);		\
+-		(low)  = (u32)_l;				\
+-		(high) = (u32)(_l >> 32);			\
+-	} while(0)
++#define rdpmc(counter, low, high)			\
++do {							\
++	u64 _l = native_read_pmc((counter));		\
++	(low)  = (u32)_l;				\
++	(high) = (u32)(_l >> 32);			\
++} while (0)
+ 
+-#define rdtscp(low, high, aux)						\
+-       do {                                                            \
+-		unsigned long long _val = native_read_tscp(&(aux));     \
+-		(low) = (u32)_val;                                      \
+-		(high) = (u32)(_val >> 32);                             \
+-       } while (0)
++#define rdtscp(low, high, aux)					\
++do {                                                            \
++	unsigned long long _val = native_read_tscp(&(aux));     \
++	(low) = (u32)_val;                                      \
++	(high) = (u32)(_val >> 32);                             \
++} while (0)
+ 
+ #define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
+ 
+ #endif	/* !CONFIG_PARAVIRT */
+ 
+ 
+-#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
++#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val),		\
++					     (u32)((val) >> 32))
+ 
+-#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
++#define write_tsc(val1, val2) wrmsr(0x10, (val1), (val2))
+ 
+-#define write_rdtscp_aux(val) wrmsr(0xc0000103, val, 0)
++#define write_rdtscp_aux(val) wrmsr(0xc0000103, (val), 0)
+ 
+ #ifdef CONFIG_SMP
+ void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+ void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+ int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
++
+ int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+ #else  /*  CONFIG_SMP  */
+ static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+@@ -195,7 +205,8 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+ {
+ 	wrmsr(msr_no, l, h);
+ }
+-static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
++static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no,
++				    u32 *l, u32 *h)
+ {
+ 	return rdmsr_safe(msr_no, l, h);
+ }
+diff --git a/include/asm-x86/mtrr.h b/include/asm-x86/mtrr.h
+index 319d065..a69a01a 100644
+--- a/include/asm-x86/mtrr.h
++++ b/include/asm-x86/mtrr.h
+@@ -28,8 +28,7 @@
+ 
+ #define	MTRR_IOCTL_BASE	'M'
+ 
+-struct mtrr_sentry
+-{
++struct mtrr_sentry {
+     unsigned long base;    /*  Base address     */
+     unsigned int size;    /*  Size of region   */
+     unsigned int type;     /*  Type of region   */
+@@ -41,8 +40,7 @@ struct mtrr_sentry
+    will break. */
+ 
+ #ifdef __i386__
+-struct mtrr_gentry
+-{
++struct mtrr_gentry {
+     unsigned int regnum;   /*  Register number  */
+     unsigned long base;    /*  Base address     */
+     unsigned int size;    /*  Size of region   */
+@@ -51,8 +49,7 @@ struct mtrr_gentry
+ 
+ #else /* __i386__ */
+ 
+-struct mtrr_gentry
+-{
++struct mtrr_gentry {
+     unsigned long base;    /*  Base address     */
+     unsigned int size;    /*  Size of region   */
+     unsigned int regnum;   /*  Register number  */
+@@ -86,38 +83,45 @@ struct mtrr_gentry
+ 
+ /*  The following functions are for use by other drivers  */
+ # ifdef CONFIG_MTRR
++extern u8 mtrr_type_lookup(u64 addr, u64 end);
+ extern void mtrr_save_fixed_ranges(void *);
+ extern void mtrr_save_state(void);
+-extern int mtrr_add (unsigned long base, unsigned long size,
+-		     unsigned int type, bool increment);
+-extern int mtrr_add_page (unsigned long base, unsigned long size,
+-		     unsigned int type, bool increment);
+-extern int mtrr_del (int reg, unsigned long base, unsigned long size);
+-extern int mtrr_del_page (int reg, unsigned long base, unsigned long size);
++extern int mtrr_add(unsigned long base, unsigned long size,
++		    unsigned int type, bool increment);
++extern int mtrr_add_page(unsigned long base, unsigned long size,
++			 unsigned int type, bool increment);
++extern int mtrr_del(int reg, unsigned long base, unsigned long size);
++extern int mtrr_del_page(int reg, unsigned long base, unsigned long size);
+ extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
+ extern void mtrr_ap_init(void);
+ extern void mtrr_bp_init(void);
+ extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
++extern int amd_special_default_mtrr(void);
+ #  else
++static inline u8 mtrr_type_lookup(u64 addr, u64 end)
++{
++	/*
++	 * Return no-MTRRs:
++	 */
++	return 0xff;
++}
+ #define mtrr_save_fixed_ranges(arg) do {} while (0)
+ #define mtrr_save_state() do {} while (0)
+-static __inline__ int mtrr_add (unsigned long base, unsigned long size,
+-				unsigned int type, bool increment)
++static inline int mtrr_add(unsigned long base, unsigned long size,
++			   unsigned int type, bool increment)
+ {
+     return -ENODEV;
+ }
+-static __inline__ int mtrr_add_page (unsigned long base, unsigned long size,
++static inline int mtrr_add_page(unsigned long base, unsigned long size,
+ 				unsigned int type, bool increment)
+ {
+     return -ENODEV;
+ }
+-static __inline__ int mtrr_del (int reg, unsigned long base,
+-				unsigned long size)
++static inline int mtrr_del(int reg, unsigned long base, unsigned long size)
+ {
+     return -ENODEV;
+ }
+-static __inline__ int mtrr_del_page (int reg, unsigned long base,
+-				unsigned long size)
++static inline int mtrr_del_page(int reg, unsigned long base, unsigned long size)
+ {
+     return -ENODEV;
+ }
+@@ -125,7 +129,9 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
+ {
+ 	return 0;
+ }
+-static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;}
++static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
++{
++}
+ 
+ #define mtrr_ap_init() do {} while (0)
+ #define mtrr_bp_init() do {} while (0)
+@@ -134,15 +140,13 @@ static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;}
+ #ifdef CONFIG_COMPAT
+ #include <linux/compat.h>
+ 
+-struct mtrr_sentry32
+-{
++struct mtrr_sentry32 {
+     compat_ulong_t base;    /*  Base address     */
+     compat_uint_t size;    /*  Size of region   */
+     compat_uint_t type;     /*  Type of region   */
+ };
+ 
+-struct mtrr_gentry32
+-{
++struct mtrr_gentry32 {
+     compat_ulong_t regnum;   /*  Register number  */
+     compat_uint_t base;    /*  Base address     */
+     compat_uint_t size;    /*  Size of region   */
+@@ -151,16 +155,17 @@ struct mtrr_gentry32
+ 
+ #define MTRR_IOCTL_BASE 'M'
+ 
+-#define MTRRIOC32_ADD_ENTRY        _IOW(MTRR_IOCTL_BASE,  0, struct mtrr_sentry32)
+-#define MTRRIOC32_SET_ENTRY        _IOW(MTRR_IOCTL_BASE,  1, struct mtrr_sentry32)
+-#define MTRRIOC32_DEL_ENTRY        _IOW(MTRR_IOCTL_BASE,  2, struct mtrr_sentry32)
+-#define MTRRIOC32_GET_ENTRY        _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
+-#define MTRRIOC32_KILL_ENTRY       _IOW(MTRR_IOCTL_BASE,  4, struct mtrr_sentry32)
+-#define MTRRIOC32_ADD_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  5, struct mtrr_sentry32)
+-#define MTRRIOC32_SET_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  6, struct mtrr_sentry32)
+-#define MTRRIOC32_DEL_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  7, struct mtrr_sentry32)
+-#define MTRRIOC32_GET_PAGE_ENTRY   _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
+-#define MTRRIOC32_KILL_PAGE_ENTRY  _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry32)
++#define MTRRIOC32_ADD_ENTRY      _IOW(MTRR_IOCTL_BASE,  0, struct mtrr_sentry32)
++#define MTRRIOC32_SET_ENTRY      _IOW(MTRR_IOCTL_BASE,  1, struct mtrr_sentry32)
++#define MTRRIOC32_DEL_ENTRY      _IOW(MTRR_IOCTL_BASE,  2, struct mtrr_sentry32)
++#define MTRRIOC32_GET_ENTRY      _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
++#define MTRRIOC32_KILL_ENTRY     _IOW(MTRR_IOCTL_BASE,  4, struct mtrr_sentry32)
++#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE,  5, struct mtrr_sentry32)
++#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE,  6, struct mtrr_sentry32)
++#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE,  7, struct mtrr_sentry32)
++#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
++#define MTRRIOC32_KILL_PAGE_ENTRY		\
++				 _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry32)
+ #endif /* CONFIG_COMPAT */
+ 
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-x86/mutex_32.h b/include/asm-x86/mutex_32.h
+index bbeefb9..73e928e 100644
+--- a/include/asm-x86/mutex_32.h
++++ b/include/asm-x86/mutex_32.h
+@@ -9,7 +9,7 @@
+ #ifndef _ASM_MUTEX_H
+ #define _ASM_MUTEX_H
+ 
+-#include "asm/alternative.h"
++#include <asm/alternative.h>
+ 
+ /**
+  *  __mutex_fastpath_lock - try to take the lock by moving the count
+@@ -21,22 +21,20 @@
+  * wasn't 1 originally. This function MUST leave the value lower than 1
+  * even when the "1" assertion wasn't true.
+  */
+-#define __mutex_fastpath_lock(count, fail_fn)				\
+-do {									\
+-	unsigned int dummy;						\
+-									\
+-	typecheck(atomic_t *, count);					\
++#define __mutex_fastpath_lock(count, fail_fn)			\
++do {								\
++	unsigned int dummy;					\
++								\
++	typecheck(atomic_t *, count);				\
+ 	typecheck_fn(void (*)(atomic_t *), fail_fn);		\
+-									\
+-	__asm__ __volatile__(						\
+-		LOCK_PREFIX "   decl (%%eax)	\n"			\
+-			"   jns 1f		\n"			\
+-			"   call "#fail_fn"	\n"			\
+-			"1:			\n"			\
+-									\
+-		:"=a" (dummy)						\
+-		: "a" (count)						\
+-		: "memory", "ecx", "edx");				\
++								\
++	asm volatile(LOCK_PREFIX "   decl (%%eax)\n"		\
++		     "   jns 1f	\n"				\
++		     "   call " #fail_fn "\n"			\
++		     "1:\n"					\
++		     : "=a" (dummy)				\
++		     : "a" (count)				\
++		     : "memory", "ecx", "edx");			\
+ } while (0)
+ 
+ 
+@@ -50,8 +48,8 @@ do {									\
+  * wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+  * or anything the slow path function returns
+  */
+-static inline int
+-__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
++static inline int __mutex_fastpath_lock_retval(atomic_t *count,
++					       int (*fail_fn)(atomic_t *))
+ {
+ 	if (unlikely(atomic_dec_return(count) < 0))
+ 		return fail_fn(count);
+@@ -72,22 +70,20 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+  * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
+  * to return 0 otherwise.
+  */
+-#define __mutex_fastpath_unlock(count, fail_fn)				\
+-do {									\
+-	unsigned int dummy;						\
+-									\
+-	typecheck(atomic_t *, count);					\
++#define __mutex_fastpath_unlock(count, fail_fn)			\
++do {								\
++	unsigned int dummy;					\
++								\
++	typecheck(atomic_t *, count);				\
+ 	typecheck_fn(void (*)(atomic_t *), fail_fn);		\
+-									\
+-	__asm__ __volatile__(						\
+-		LOCK_PREFIX "   incl (%%eax)	\n"			\
+-			"   jg	1f		\n"			\
+-			"   call "#fail_fn"	\n"			\
+-			"1:			\n"			\
+-									\
+-		:"=a" (dummy)						\
+-		: "a" (count)						\
+-		: "memory", "ecx", "edx");				\
++								\
++	asm volatile(LOCK_PREFIX "   incl (%%eax)\n"		\
++		     "   jg	1f\n"				\
++		     "   call " #fail_fn "\n"			\
++		     "1:\n"					\
++		     : "=a" (dummy)				\
++		     : "a" (count)				\
++		     : "memory", "ecx", "edx");			\
+ } while (0)
+ 
+ #define __mutex_slowpath_needs_to_unlock()	1
+@@ -104,8 +100,8 @@ do {									\
+  * Additionally, if the value was < 0 originally, this function must not leave
+  * it to 0 on failure.
+  */
+-static inline int
+-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
++static inline int __mutex_fastpath_trylock(atomic_t *count,
++					   int (*fail_fn)(atomic_t *))
+ {
+ 	/*
+ 	 * We have two variants here. The cmpxchg based one is the best one
+diff --git a/include/asm-x86/mutex_64.h b/include/asm-x86/mutex_64.h
+index 6c2949a..f3fae9b 100644
+--- a/include/asm-x86/mutex_64.h
++++ b/include/asm-x86/mutex_64.h
+@@ -16,23 +16,21 @@
+  *
+  * Atomically decrements @v and calls <fail_fn> if the result is negative.
+  */
+-#define __mutex_fastpath_lock(v, fail_fn)				\
+-do {									\
+-	unsigned long dummy;						\
+-									\
+-	typecheck(atomic_t *, v);					\
+-	typecheck_fn(void (*)(atomic_t *), fail_fn);			\
+-									\
+-	__asm__ __volatile__(						\
+-		LOCK_PREFIX "   decl (%%rdi)	\n"			\
+-			"   jns 1f		\n"			\
+-			"   call "#fail_fn"	\n"			\
+-			"1:"						\
+-									\
+-		:"=D" (dummy)						\
+-		: "D" (v)						\
+-		: "rax", "rsi", "rdx", "rcx",				\
+-		  "r8", "r9", "r10", "r11", "memory");			\
++#define __mutex_fastpath_lock(v, fail_fn)			\
++do {								\
++	unsigned long dummy;					\
++								\
++	typecheck(atomic_t *, v);				\
++	typecheck_fn(void (*)(atomic_t *), fail_fn);		\
++								\
++	asm volatile(LOCK_PREFIX "   decl (%%rdi)\n"		\
++		     "   jns 1f		\n"			\
++		     "   call " #fail_fn "\n"			\
++		     "1:"					\
++		     : "=D" (dummy)				\
++		     : "D" (v)					\
++		     : "rax", "rsi", "rdx", "rcx",		\
++		       "r8", "r9", "r10", "r11", "memory");	\
+ } while (0)
+ 
+ /**
+@@ -45,9 +43,8 @@ do {									\
+  * it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+  * or anything the slow path function returns
+  */
+-static inline int
+-__mutex_fastpath_lock_retval(atomic_t *count,
+-			     int (*fail_fn)(atomic_t *))
++static inline int __mutex_fastpath_lock_retval(atomic_t *count,
++					       int (*fail_fn)(atomic_t *))
+ {
+ 	if (unlikely(atomic_dec_return(count) < 0))
+ 		return fail_fn(count);
+@@ -62,23 +59,21 @@ __mutex_fastpath_lock_retval(atomic_t *count,
+  *
+  * Atomically increments @v and calls <fail_fn> if the result is nonpositive.
+  */
+-#define __mutex_fastpath_unlock(v, fail_fn)				\
+-do {									\
+-	unsigned long dummy;						\
+-									\
+-	typecheck(atomic_t *, v);					\
+-	typecheck_fn(void (*)(atomic_t *), fail_fn);			\
+-									\
+-	__asm__ __volatile__(						\
+-		LOCK_PREFIX "   incl (%%rdi)	\n"			\
+-			"   jg 1f		\n"			\
+-			"   call "#fail_fn"	\n"			\
+-			"1:			  "			\
+-									\
+-		:"=D" (dummy)						\
+-		: "D" (v)						\
+-		: "rax", "rsi", "rdx", "rcx",				\
+-		  "r8", "r9", "r10", "r11", "memory");			\
++#define __mutex_fastpath_unlock(v, fail_fn)			\
++do {								\
++	unsigned long dummy;					\
++								\
++	typecheck(atomic_t *, v);				\
++	typecheck_fn(void (*)(atomic_t *), fail_fn);		\
++								\
++	asm volatile(LOCK_PREFIX "   incl (%%rdi)\n"		\
++		     "   jg 1f\n"				\
++		     "   call " #fail_fn "\n"			\
++		     "1:"					\
++		     : "=D" (dummy)				\
++		     : "D" (v)					\
++		     : "rax", "rsi", "rdx", "rcx",		\
++		       "r8", "r9", "r10", "r11", "memory");	\
+ } while (0)
+ 
+ #define __mutex_slowpath_needs_to_unlock()	1
+@@ -93,8 +88,8 @@ do {									\
+  * if it wasn't 1 originally. [the fallback function is never used on
+  * x86_64, because all x86_64 CPUs have a CMPXCHG instruction.]
+  */
+-static inline int
+-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
++static inline int __mutex_fastpath_trylock(atomic_t *count,
++					   int (*fail_fn)(atomic_t *))
+ {
+ 	if (likely(atomic_cmpxchg(count, 1, 0) == 1))
+ 		return 1;
+diff --git a/include/asm-x86/nmi.h b/include/asm-x86/nmi.h
+index 53ccac1..1e36302 100644
+--- a/include/asm-x86/nmi.h
++++ b/include/asm-x86/nmi.h
+@@ -1,5 +1,93 @@
+-#ifdef CONFIG_X86_32
+-# include "nmi_32.h"
++#ifndef _ASM_X86_NMI_H_
++#define _ASM_X86_NMI_H_
++
++#include <linux/pm.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#ifdef ARCH_HAS_NMI_WATCHDOG
++
++/**
++ * do_nmi_callback
++ *
++ * Check to see if a callback exists and execute it.  Return 1
++ * if the handler exists and was handled successfully.
++ */
++int do_nmi_callback(struct pt_regs *regs, int cpu);
++
++#ifdef CONFIG_PM
++
++/** Replace the PM callback routine for NMI. */
++struct pm_dev *set_nmi_pm_callback(pm_callback callback);
++
++/** Unset the PM callback routine back to the default. */
++void unset_nmi_pm_callback(struct pm_dev *dev);
++
+ #else
+-# include "nmi_64.h"
++
++static inline struct pm_dev *set_nmi_pm_callback(pm_callback callback)
++{
++	return 0;
++}
++
++static inline void unset_nmi_pm_callback(struct pm_dev *dev)
++{
++}
++
++#endif /* CONFIG_PM */
++
++#ifdef CONFIG_X86_64
++extern void default_do_nmi(struct pt_regs *);
++extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
++extern void nmi_watchdog_default(void);
++#else
++#define nmi_watchdog_default() do {} while (0)
++#endif
++
++extern int check_nmi_watchdog(void);
++extern int nmi_watchdog_enabled;
++extern int unknown_nmi_panic;
++extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
++extern int avail_to_resrv_perfctr_nmi(unsigned int);
++extern int reserve_perfctr_nmi(unsigned int);
++extern void release_perfctr_nmi(unsigned int);
++extern int reserve_evntsel_nmi(unsigned int);
++extern void release_evntsel_nmi(unsigned int);
++
++extern void setup_apic_nmi_watchdog(void *);
++extern void stop_apic_nmi_watchdog(void *);
++extern void disable_timer_nmi_watchdog(void);
++extern void enable_timer_nmi_watchdog(void);
++extern int nmi_watchdog_tick(struct pt_regs *regs, unsigned reason);
++
++extern atomic_t nmi_active;
++extern unsigned int nmi_watchdog;
++#define NMI_DISABLED    -1
++#define NMI_NONE	0
++#define NMI_IO_APIC	1
++#define NMI_LOCAL_APIC	2
++#define NMI_INVALID	3
++#define NMI_DEFAULT	NMI_DISABLED
++
++struct ctl_table;
++struct file;
++extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
++			void __user *, size_t *, loff_t *);
++extern int unknown_nmi_panic;
++
++void __trigger_all_cpu_backtrace(void);
++#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
++
++#endif
++
++void lapic_watchdog_stop(void);
++int lapic_watchdog_init(unsigned nmi_hz);
++int lapic_wd_event(unsigned nmi_hz);
++unsigned lapic_adjust_nmi_hz(unsigned hz);
++int lapic_watchdog_ok(void);
++void disable_lapic_nmi_watchdog(void);
++void enable_lapic_nmi_watchdog(void);
++void stop_nmi(void);
++void restart_nmi(void);
++
+ #endif
+diff --git a/include/asm-x86/nmi_32.h b/include/asm-x86/nmi_32.h
+deleted file mode 100644
+index 7206c7e..0000000
+--- a/include/asm-x86/nmi_32.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-#ifndef ASM_NMI_H
+-#define ASM_NMI_H
+-
+-#include <linux/pm.h>
+-#include <asm/irq.h>
+-
+-#ifdef ARCH_HAS_NMI_WATCHDOG
+-
+-/**
+- * do_nmi_callback
+- *
+- * Check to see if a callback exists and execute it.  Return 1
+- * if the handler exists and was handled successfully.
+- */
+-int do_nmi_callback(struct pt_regs *regs, int cpu);
+-
+-extern int nmi_watchdog_enabled;
+-extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
+-extern int avail_to_resrv_perfctr_nmi(unsigned int);
+-extern int reserve_perfctr_nmi(unsigned int);
+-extern void release_perfctr_nmi(unsigned int);
+-extern int reserve_evntsel_nmi(unsigned int);
+-extern void release_evntsel_nmi(unsigned int);
+-
+-extern void setup_apic_nmi_watchdog (void *);
+-extern void stop_apic_nmi_watchdog (void *);
+-extern void disable_timer_nmi_watchdog(void);
+-extern void enable_timer_nmi_watchdog(void);
+-extern int nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
+-
+-extern atomic_t nmi_active;
+-extern unsigned int nmi_watchdog;
+-#define NMI_DISABLED    -1
+-#define NMI_NONE	0
+-#define NMI_IO_APIC	1
+-#define NMI_LOCAL_APIC	2
+-#define NMI_INVALID	3
+-#define NMI_DEFAULT	NMI_DISABLED
+-
+-struct ctl_table;
+-struct file;
+-extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
+-			void __user *, size_t *, loff_t *);
+-extern int unknown_nmi_panic;
+-
+-void __trigger_all_cpu_backtrace(void);
+-#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
+-
+-#endif
+-
+-void lapic_watchdog_stop(void);
+-int lapic_watchdog_init(unsigned nmi_hz);
+-int lapic_wd_event(unsigned nmi_hz);
+-unsigned lapic_adjust_nmi_hz(unsigned hz);
+-int lapic_watchdog_ok(void);
+-void disable_lapic_nmi_watchdog(void);
+-void enable_lapic_nmi_watchdog(void);
+-void stop_nmi(void);
+-void restart_nmi(void);
+-
+-#endif /* ASM_NMI_H */
+diff --git a/include/asm-x86/nmi_64.h b/include/asm-x86/nmi_64.h
+deleted file mode 100644
+index 2eeb74e..0000000
+--- a/include/asm-x86/nmi_64.h
++++ /dev/null
+@@ -1,90 +0,0 @@
+-#ifndef ASM_NMI_H
+-#define ASM_NMI_H
+-
+-#include <linux/pm.h>
+-#include <asm/io.h>
+- 
+-/**
+- * do_nmi_callback
+- *
+- * Check to see if a callback exists and execute it.  Return 1
+- * if the handler exists and was handled successfully.
+- */
+-int do_nmi_callback(struct pt_regs *regs, int cpu);
+-
+-#ifdef CONFIG_PM
+- 
+-/** Replace the PM callback routine for NMI. */
+-struct pm_dev * set_nmi_pm_callback(pm_callback callback);
+-
+-/** Unset the PM callback routine back to the default. */
+-void unset_nmi_pm_callback(struct pm_dev * dev);
+-
+-#else
+-
+-static inline struct pm_dev * set_nmi_pm_callback(pm_callback callback)
+-{
+-	return 0;
+-} 
+- 
+-static inline void unset_nmi_pm_callback(struct pm_dev * dev)
+-{
+-}
+-
+-#endif /* CONFIG_PM */
+- 
+-extern void default_do_nmi(struct pt_regs *);
+-extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
+-
+-#define get_nmi_reason() inb(0x61)
+-
+-extern int unknown_nmi_panic;
+-extern int nmi_watchdog_enabled;
+-
+-extern int check_nmi_watchdog(void);
+-extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
+-extern int avail_to_resrv_perfctr_nmi(unsigned int);
+-extern int reserve_perfctr_nmi(unsigned int);
+-extern void release_perfctr_nmi(unsigned int);
+-extern int reserve_evntsel_nmi(unsigned int);
+-extern void release_evntsel_nmi(unsigned int);
+-
+-extern void setup_apic_nmi_watchdog (void *);
+-extern void stop_apic_nmi_watchdog (void *);
+-extern void disable_timer_nmi_watchdog(void);
+-extern void enable_timer_nmi_watchdog(void);
+-extern int nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
+-
+-extern void nmi_watchdog_default(void);
+-
+-extern atomic_t nmi_active;
+-extern unsigned int nmi_watchdog;
+-#define NMI_DISABLED    -1
+-#define NMI_NONE	0
+-#define NMI_IO_APIC	1
+-#define NMI_LOCAL_APIC	2
+-#define NMI_INVALID	3
+-#define NMI_DEFAULT	NMI_DISABLED
+-
+-struct ctl_table;
+-struct file;
+-extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
+-			void __user *, size_t *, loff_t *);
+-
+-extern int unknown_nmi_panic;
+-
+-void __trigger_all_cpu_backtrace(void);
+-#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
+-
+-
+-void lapic_watchdog_stop(void);
+-int lapic_watchdog_init(unsigned nmi_hz);
+-int lapic_wd_event(unsigned nmi_hz);
+-unsigned lapic_adjust_nmi_hz(unsigned hz);
+-int lapic_watchdog_ok(void);
+-void disable_lapic_nmi_watchdog(void);
+-void enable_lapic_nmi_watchdog(void);
+-void stop_nmi(void);
+-void restart_nmi(void);
+-
+-#endif /* ASM_NMI_H */
+diff --git a/include/asm-x86/nops.h b/include/asm-x86/nops.h
+index b3930ae..ad0bedd 100644
+--- a/include/asm-x86/nops.h
++++ b/include/asm-x86/nops.h
+@@ -5,6 +5,8 @@
+ 
+ /* generic versions from gas
+    1: nop
++   the following instructions are NOT nops in 64-bit mode,
++   for 64-bit mode use K8 or P6 nops instead
+    2: movl %esi,%esi
+    3: leal 0x00(%esi),%esi
+    4: leal 0x00(,%esi,1),%esi
+diff --git a/include/asm-x86/numa_64.h b/include/asm-x86/numa_64.h
+index 15fe07c..22e87c9 100644
+--- a/include/asm-x86/numa_64.h
++++ b/include/asm-x86/numa_64.h
+@@ -1,14 +1,16 @@
+-#ifndef _ASM_X8664_NUMA_H 
++#ifndef _ASM_X8664_NUMA_H
+ #define _ASM_X8664_NUMA_H 1
+ 
+ #include <linux/nodemask.h>
+ #include <asm/apicdef.h>
+ 
+ struct bootnode {
+-	u64 start,end; 
++	u64 start;
++	u64 end;
+ };
+ 
+-extern int compute_hash_shift(struct bootnode *nodes, int numnodes);
++extern int compute_hash_shift(struct bootnode *nodes, int numblks,
++			      int *nodeids);
+ 
+ #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
+ 
+diff --git a/include/asm-x86/numaq.h b/include/asm-x86/numaq.h
+index 38f710d..94b86c3 100644
+--- a/include/asm-x86/numaq.h
++++ b/include/asm-x86/numaq.h
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 2002, IBM Corp.
+  *
+- * All rights reserved.          
++ * 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
+@@ -33,7 +33,8 @@ extern int get_memcfg_numaq(void);
+ /*
+  * SYS_CFG_DATA_PRIV_ADDR, struct eachquadmem, and struct sys_cfg_data are the
+  */
+-#define SYS_CFG_DATA_PRIV_ADDR		0x0009d000 /* place for scd in private quad space */
++#define SYS_CFG_DATA_PRIV_ADDR		0x0009d000 /* place for scd in private
++						      quad space */
+ 
+ /*
+  * Communication area for each processor on lynxer-processor tests.
+@@ -139,7 +140,7 @@ struct sys_cfg_data {
+ 	unsigned int	low_shrd_mem_base; /* 0 or 512MB or 1GB */
+ 	unsigned int	low_shrd_mem_quad_offset; /* 0,128M,256M,512M,1G */
+ 					/* may not be totally populated */
+-	unsigned int	split_mem_enbl; /* 0 for no low shared memory */ 
++	unsigned int	split_mem_enbl; /* 0 for no low shared memory */
+ 	unsigned int	mmio_sz; /* Size of total system memory mapped I/O */
+ 				 /* (in MB). */
+ 	unsigned int	quad_spin_lock; /* Spare location used for quad */
+@@ -152,7 +153,7 @@ struct sys_cfg_data {
+ 	/*
+ 	 *	memory configuration area for each quad
+ 	 */
+-        struct	eachquadmem eq[MAX_NUMNODES];	/* indexed by quad id */
++	struct		eachquadmem eq[MAX_NUMNODES];	/* indexed by quad id */
+ };
+ 
+ static inline unsigned long *get_zholes_size(int nid)
+diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h
+index a05b289..b381f4a 100644
+--- a/include/asm-x86/page.h
++++ b/include/asm-x86/page.h
+@@ -33,10 +33,8 @@
+ 
+ #ifdef CONFIG_X86_64
+ #include <asm/page_64.h>
+-#define max_pfn_mapped		end_pfn_map
+ #else
+ #include <asm/page_32.h>
+-#define max_pfn_mapped		max_low_pfn
+ #endif	/* CONFIG_X86_64 */
+ 
+ #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
+@@ -49,6 +47,9 @@
+ #ifndef __ASSEMBLY__
+ 
+ extern int page_is_ram(unsigned long pagenr);
++extern int devmem_is_allowed(unsigned long pagenr);
++
++extern unsigned long max_pfn_mapped;
+ 
+ struct page;
+ 
+diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h
+index 5f7257f..424e82f 100644
+--- a/include/asm-x86/page_32.h
++++ b/include/asm-x86/page_32.h
+@@ -47,7 +47,10 @@ typedef unsigned long	pgdval_t;
+ typedef unsigned long	pgprotval_t;
+ typedef unsigned long	phys_addr_t;
+ 
+-typedef union { pteval_t pte, pte_low; } pte_t;
++typedef union {
++	pteval_t pte;
++	pteval_t pte_low;
++} pte_t;
+ 
+ #endif	/* __ASSEMBLY__ */
+ #endif	/* CONFIG_X86_PAE */
+@@ -61,7 +64,7 @@ typedef struct page *pgtable_t;
+ #endif
+ 
+ #ifndef __ASSEMBLY__
+-#define __phys_addr(x)		((x)-PAGE_OFFSET)
++#define __phys_addr(x)		((x) - PAGE_OFFSET)
+ #define __phys_reloc_hide(x)	RELOC_HIDE((x), 0)
+ 
+ #ifdef CONFIG_FLATMEM
+@@ -78,7 +81,7 @@ extern unsigned int __VMALLOC_RESERVE;
+ extern int sysctl_legacy_va_layout;
+ 
+ #define VMALLOC_RESERVE		((unsigned long)__VMALLOC_RESERVE)
+-#define MAXMEM			(-__PAGE_OFFSET-__VMALLOC_RESERVE)
++#define MAXMEM			(-__PAGE_OFFSET - __VMALLOC_RESERVE)
+ 
+ #ifdef CONFIG_X86_USE_3DNOW
+ #include <asm/mmx.h>
+diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h
+index 1435460..6ea7285 100644
+--- a/include/asm-x86/page_64.h
++++ b/include/asm-x86/page_64.h
+@@ -5,7 +5,7 @@
+ 
+ #define THREAD_ORDER	1
+ #define THREAD_SIZE  (PAGE_SIZE << THREAD_ORDER)
+-#define CURRENT_MASK (~(THREAD_SIZE-1))
++#define CURRENT_MASK (~(THREAD_SIZE - 1))
+ 
+ #define EXCEPTION_STACK_ORDER 0
+ #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
+@@ -48,10 +48,10 @@
+ #define __VIRTUAL_MASK_SHIFT	48
+ 
+ /*
+- * Kernel image size is limited to 128 MB (see level2_kernel_pgt in
++ * Kernel image size is limited to 512 MB (see level2_kernel_pgt in
+  * arch/x86/kernel/head_64.S), and it is mapped here:
+  */
+-#define KERNEL_IMAGE_SIZE	(128*1024*1024)
++#define KERNEL_IMAGE_SIZE	(512 * 1024 * 1024)
+ #define KERNEL_IMAGE_START	_AC(0xffffffff80000000, UL)
+ 
+ #ifndef __ASSEMBLY__
+@@ -59,7 +59,6 @@ void clear_page(void *page);
+ void copy_page(void *to, void *from);
+ 
+ extern unsigned long end_pfn;
+-extern unsigned long end_pfn_map;
+ extern unsigned long phys_base;
+ 
+ extern unsigned long __phys_addr(unsigned long);
+@@ -81,6 +80,9 @@ typedef struct { pteval_t pte; } pte_t;
+ 
+ #define vmemmap ((struct page *)VMEMMAP_START)
+ 
++extern unsigned long init_memory_mapping(unsigned long start,
++					 unsigned long end);
++
+ #endif	/* !__ASSEMBLY__ */
+ 
+ #ifdef CONFIG_FLATMEM
+diff --git a/include/asm-x86/param.h b/include/asm-x86/param.h
+index c996ec4..6f0d042 100644
+--- a/include/asm-x86/param.h
++++ b/include/asm-x86/param.h
+@@ -3,8 +3,8 @@
+ 
+ #ifdef __KERNEL__
+ # define HZ		CONFIG_HZ	/* Internal kernel timer frequency */
+-# define USER_HZ	100		/* .. some user interfaces are in "ticks" */
+-# define CLOCKS_PER_SEC	(USER_HZ)       /* like times() */
++# define USER_HZ	100		/* some user interfaces are */
++# define CLOCKS_PER_SEC	(USER_HZ)       /* in "ticks" like times() */
+ #endif
+ 
+ #ifndef HZ
+diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
+index d6236eb..0f13b94 100644
+--- a/include/asm-x86/paravirt.h
++++ b/include/asm-x86/paravirt.h
+@@ -220,18 +220,21 @@ struct pv_mmu_ops {
+ 				 unsigned long va);
+ 
+ 	/* Hooks for allocating/releasing pagetable pages */
+-	void (*alloc_pt)(struct mm_struct *mm, u32 pfn);
+-	void (*alloc_pd)(struct mm_struct *mm, u32 pfn);
+-	void (*alloc_pd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
+-	void (*release_pt)(u32 pfn);
+-	void (*release_pd)(u32 pfn);
++	void (*alloc_pte)(struct mm_struct *mm, u32 pfn);
++	void (*alloc_pmd)(struct mm_struct *mm, u32 pfn);
++	void (*alloc_pmd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
++	void (*alloc_pud)(struct mm_struct *mm, u32 pfn);
++	void (*release_pte)(u32 pfn);
++	void (*release_pmd)(u32 pfn);
++	void (*release_pud)(u32 pfn);
+ 
+ 	/* Pagetable manipulation functions */
+ 	void (*set_pte)(pte_t *ptep, pte_t pteval);
+ 	void (*set_pte_at)(struct mm_struct *mm, unsigned long addr,
+ 			   pte_t *ptep, pte_t pteval);
+ 	void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);
+-	void (*pte_update)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
++	void (*pte_update)(struct mm_struct *mm, unsigned long addr,
++			   pte_t *ptep);
+ 	void (*pte_update_defer)(struct mm_struct *mm,
+ 				 unsigned long addr, pte_t *ptep);
+ 
+@@ -246,7 +249,8 @@ struct pv_mmu_ops {
+ 	void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
+ 	void (*set_pte_present)(struct mm_struct *mm, unsigned long addr,
+ 				pte_t *ptep, pte_t pte);
+-	void (*pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
++	void (*pte_clear)(struct mm_struct *mm, unsigned long addr,
++			  pte_t *ptep);
+ 	void (*pmd_clear)(pmd_t *pmdp);
+ 
+ #endif	/* CONFIG_X86_PAE */
+@@ -274,8 +278,7 @@ struct pv_mmu_ops {
+ /* This contains all the paravirt structures: we get a convenient
+  * number for each function using the offset which we use to indicate
+  * what to patch. */
+-struct paravirt_patch_template
+-{
++struct paravirt_patch_template {
+ 	struct pv_init_ops pv_init_ops;
+ 	struct pv_time_ops pv_time_ops;
+ 	struct pv_cpu_ops pv_cpu_ops;
+@@ -660,43 +663,56 @@ static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
+ }
+ 
+ /* These should all do BUG_ON(_err), but our headers are too tangled. */
+-#define rdmsr(msr,val1,val2) do {		\
++#define rdmsr(msr, val1, val2)			\
++do {						\
+ 	int _err;				\
+ 	u64 _l = paravirt_read_msr(msr, &_err);	\
+ 	val1 = (u32)_l;				\
+ 	val2 = _l >> 32;			\
+-} while(0)
++} while (0)
+ 
+-#define wrmsr(msr,val1,val2) do {		\
++#define wrmsr(msr, val1, val2)			\
++do {						\
+ 	paravirt_write_msr(msr, val1, val2);	\
+-} while(0)
++} while (0)
+ 
+-#define rdmsrl(msr,val) do {			\
++#define rdmsrl(msr, val)			\
++do {						\
+ 	int _err;				\
+ 	val = paravirt_read_msr(msr, &_err);	\
+-} while(0)
++} while (0)
+ 
+-#define wrmsrl(msr,val)		wrmsr(msr, (u32)((u64)(val)), ((u64)(val))>>32)
+-#define wrmsr_safe(msr,a,b)	paravirt_write_msr(msr, a, b)
++#define wrmsrl(msr, val)	wrmsr(msr, (u32)((u64)(val)), ((u64)(val))>>32)
++#define wrmsr_safe(msr, a, b)	paravirt_write_msr(msr, a, b)
+ 
+ /* rdmsr with exception handling */
+-#define rdmsr_safe(msr,a,b) ({			\
++#define rdmsr_safe(msr, a, b)			\
++({						\
+ 	int _err;				\
+ 	u64 _l = paravirt_read_msr(msr, &_err);	\
+ 	(*a) = (u32)_l;				\
+ 	(*b) = _l >> 32;			\
+-	_err; })
++	_err;					\
++})
+ 
++static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
++{
++	int err;
++
++	*p = paravirt_read_msr(msr, &err);
++	return err;
++}
+ 
+ static inline u64 paravirt_read_tsc(void)
+ {
+ 	return PVOP_CALL0(u64, pv_cpu_ops.read_tsc);
+ }
+ 
+-#define rdtscl(low) do {			\
++#define rdtscl(low)				\
++do {						\
+ 	u64 _l = paravirt_read_tsc();		\
+ 	low = (int)_l;				\
+-} while(0)
++} while (0)
+ 
+ #define rdtscll(val) (val = paravirt_read_tsc())
+ 
+@@ -711,11 +727,12 @@ static inline unsigned long long paravirt_read_pmc(int counter)
+ 	return PVOP_CALL1(u64, pv_cpu_ops.read_pmc, counter);
+ }
+ 
+-#define rdpmc(counter,low,high) do {		\
++#define rdpmc(counter, low, high)		\
++do {						\
+ 	u64 _l = paravirt_read_pmc(counter);	\
+ 	low = (u32)_l;				\
+ 	high = _l >> 32;			\
+-} while(0)
++} while (0)
+ 
+ static inline unsigned long long paravirt_rdtscp(unsigned int *aux)
+ {
+@@ -794,7 +811,8 @@ static inline void set_iopl_mask(unsigned mask)
+ }
+ 
+ /* The paravirtualized I/O functions */
+-static inline void slow_down_io(void) {
++static inline void slow_down_io(void)
++{
+ 	pv_cpu_ops.io_delay();
+ #ifdef REALLY_SLOW_IO
+ 	pv_cpu_ops.io_delay();
+@@ -894,28 +912,37 @@ static inline void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+ 	PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, &cpumask, mm, va);
+ }
+ 
+-static inline void paravirt_alloc_pt(struct mm_struct *mm, unsigned pfn)
++static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned pfn)
+ {
+-	PVOP_VCALL2(pv_mmu_ops.alloc_pt, mm, pfn);
++	PVOP_VCALL2(pv_mmu_ops.alloc_pte, mm, pfn);
+ }
+-static inline void paravirt_release_pt(unsigned pfn)
++static inline void paravirt_release_pte(unsigned pfn)
+ {
+-	PVOP_VCALL1(pv_mmu_ops.release_pt, pfn);
++	PVOP_VCALL1(pv_mmu_ops.release_pte, pfn);
+ }
+ 
+-static inline void paravirt_alloc_pd(struct mm_struct *mm, unsigned pfn)
++static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned pfn)
++{
++	PVOP_VCALL2(pv_mmu_ops.alloc_pmd, mm, pfn);
++}
++
++static inline void paravirt_alloc_pmd_clone(unsigned pfn, unsigned clonepfn,
++					    unsigned start, unsigned count)
++{
++	PVOP_VCALL4(pv_mmu_ops.alloc_pmd_clone, pfn, clonepfn, start, count);
++}
++static inline void paravirt_release_pmd(unsigned pfn)
+ {
+-	PVOP_VCALL2(pv_mmu_ops.alloc_pd, mm, pfn);
++	PVOP_VCALL1(pv_mmu_ops.release_pmd, pfn);
+ }
+ 
+-static inline void paravirt_alloc_pd_clone(unsigned pfn, unsigned clonepfn,
+-					   unsigned start, unsigned count)
++static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned pfn)
+ {
+-	PVOP_VCALL4(pv_mmu_ops.alloc_pd_clone, pfn, clonepfn, start, count);
++	PVOP_VCALL2(pv_mmu_ops.alloc_pud, mm, pfn);
+ }
+-static inline void paravirt_release_pd(unsigned pfn)
++static inline void paravirt_release_pud(unsigned pfn)
+ {
+-	PVOP_VCALL1(pv_mmu_ops.release_pd, pfn);
++	PVOP_VCALL1(pv_mmu_ops.release_pud, pfn);
+ }
+ 
+ #ifdef CONFIG_HIGHPTE
+diff --git a/include/asm-x86/parport.h b/include/asm-x86/parport.h
+index 019cbca..3c4ffeb 100644
+--- a/include/asm-x86/parport.h
++++ b/include/asm-x86/parport.h
+@@ -1,10 +1,10 @@
+ #ifndef _ASM_X86_PARPORT_H
+ #define _ASM_X86_PARPORT_H
+ 
+-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
+-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
++static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma);
++static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma)
+ {
+-	return parport_pc_find_isa_ports (autoirq, autodma);
++	return parport_pc_find_isa_ports(autoirq, autodma);
+ }
+ 
+ #endif /* _ASM_X86_PARPORT_H */
+diff --git a/include/asm-x86/pat.h b/include/asm-x86/pat.h
+new file mode 100644
+index 0000000..8b822b5
+--- /dev/null
++++ b/include/asm-x86/pat.h
+@@ -0,0 +1,16 @@
++
++#ifndef _ASM_PAT_H
++#define _ASM_PAT_H 1
++
++#include <linux/types.h>
++
++extern int pat_wc_enabled;
++
++extern void pat_init(void);
++
++extern int reserve_memtype(u64 start, u64 end,
++		unsigned long req_type, unsigned long *ret_type);
++extern int free_memtype(u64 start, u64 end);
++
++#endif
++
+diff --git a/include/asm-x86/pci-direct.h b/include/asm-x86/pci-direct.h
+index 6823fa4..5b21485 100644
+--- a/include/asm-x86/pci-direct.h
++++ b/include/asm-x86/pci-direct.h
+@@ -4,7 +4,7 @@
+ #include <linux/types.h>
+ 
+ /* Direct PCI access. This is used for PCI accesses in early boot before
+-   the PCI subsystem works. */ 
++   the PCI subsystem works. */
+ 
+ extern u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset);
+ extern u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset);
+diff --git a/include/asm-x86/pci.h b/include/asm-x86/pci.h
+index c61190c..ddd8e24 100644
+--- a/include/asm-x86/pci.h
++++ b/include/asm-x86/pci.h
+@@ -8,14 +8,13 @@
+ #include <asm/scatterlist.h>
+ #include <asm/io.h>
+ 
+-
+ #ifdef __KERNEL__
+ 
+ struct pci_sysdata {
+ 	int		domain;		/* PCI domain */
+ 	int		node;		/* NUMA node */
+ #ifdef CONFIG_X86_64
+-	void*		iommu;		/* IOMMU private data */
++	void		*iommu;		/* IOMMU private data */
+ #endif
+ };
+ 
+@@ -52,7 +51,7 @@ extern unsigned long pci_mem_start;
+ #define PCIBIOS_MIN_CARDBUS_IO	0x4000
+ 
+ void pcibios_config_init(void);
+-struct pci_bus * pcibios_scan_root(int bus);
++struct pci_bus *pcibios_scan_root(int bus);
+ 
+ void pcibios_set_master(struct pci_dev *dev);
+ void pcibios_penalize_isa_irq(int irq, int active);
+@@ -62,7 +61,8 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
+ 
+ #define HAVE_PCI_MMAP
+ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+-			       enum pci_mmap_state mmap_state, int write_combine);
++			       enum pci_mmap_state mmap_state,
++			       int write_combine);
+ 
+ 
+ #ifdef CONFIG_PCI
+diff --git a/include/asm-x86/pci_64.h b/include/asm-x86/pci_64.h
+index 3746903..f330234 100644
+--- a/include/asm-x86/pci_64.h
++++ b/include/asm-x86/pci_64.h
+@@ -1,12 +1,10 @@
+ #ifndef __x8664_PCI_H
+ #define __x8664_PCI_H
+ 
+-
+ #ifdef __KERNEL__
+ 
+-
+ #ifdef CONFIG_CALGARY_IOMMU
+-static inline void* pci_iommu(struct pci_bus *bus)
++static inline void *pci_iommu(struct pci_bus *bus)
+ {
+ 	struct pci_sysdata *sd = bus->sysdata;
+ 	return sd->iommu;
+@@ -19,12 +17,12 @@ static inline void set_pci_iommu(struct pci_bus *bus, void *val)
+ }
+ #endif /* CONFIG_CALGARY_IOMMU */
+ 
++extern int (*pci_config_read)(int seg, int bus, int dev, int fn,
++			      int reg, int len, u32 *value);
++extern int (*pci_config_write)(int seg, int bus, int dev, int fn,
++			       int reg, int len, u32 value);
+ 
+-extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value);
+-extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value);
+-
+-
+-
++extern void dma32_reserve_bootmem(void);
+ extern void pci_iommu_alloc(void);
+ 
+ /* The PCI address space does equal the physical memory
+@@ -65,5 +63,4 @@ extern void pci_iommu_alloc(void);
+ 
+ #endif /* __KERNEL__ */
+ 
+-
+ #endif /* __x8664_PCI_H */
+diff --git a/include/asm-x86/pda.h b/include/asm-x86/pda.h
+index c0305bf..101fb9e 100644
+--- a/include/asm-x86/pda.h
++++ b/include/asm-x86/pda.h
+@@ -22,7 +22,6 @@ struct x8664_pda {
+ 					   offset 40!!! */
+ #endif
+ 	char *irqstackptr;
+-	unsigned int nodenumber;	/* number of current node */
+ 	unsigned int __softirq_pending;
+ 	unsigned int __nmi_count;	/* number of NMI on this CPUs */
+ 	short mmu_state;
+@@ -58,34 +57,36 @@ extern struct x8664_pda _proxy_pda;
+ 
+ #define pda_offset(field) offsetof(struct x8664_pda, field)
+ 
+-#define pda_to_op(op, field, val) do {		\
+-	typedef typeof(_proxy_pda.field) T__;	\
+-	if (0) { T__ tmp__; tmp__ = (val); }	/* type checking */ \
+-	switch (sizeof(_proxy_pda.field)) {	\
+-	case 2:					\
+-		asm(op "w %1,%%gs:%c2" :	\
+-		    "+m" (_proxy_pda.field) :	\
+-		    "ri" ((T__)val),		\
+-		    "i"(pda_offset(field)));	\
+-		break;				\
+-	case 4:					\
+-		asm(op "l %1,%%gs:%c2" :	\
+-		    "+m" (_proxy_pda.field) :	\
+-		    "ri" ((T__)val),		\
+-		    "i" (pda_offset(field)));	\
+-		break;				\
+-	case 8:					\
+-		asm(op "q %1,%%gs:%c2":		\
+-		    "+m" (_proxy_pda.field) :	\
+-		    "ri" ((T__)val),		\
+-		    "i"(pda_offset(field)));	\
+-		break;				\
+-	default:				\
+-		__bad_pda_field();		\
+-	}					\
+-	} while (0)
++#define pda_to_op(op, field, val)					\
++do {									\
++	typedef typeof(_proxy_pda.field) T__;				\
++	if (0) { T__ tmp__; tmp__ = (val); }	/* type checking */	\
++	switch (sizeof(_proxy_pda.field)) {				\
++	case 2:								\
++		asm(op "w %1,%%gs:%c2" :				\
++		    "+m" (_proxy_pda.field) :				\
++		    "ri" ((T__)val),					\
++		    "i"(pda_offset(field)));				\
++		break;							\
++	case 4:								\
++		asm(op "l %1,%%gs:%c2" :				\
++		    "+m" (_proxy_pda.field) :				\
++		    "ri" ((T__)val),					\
++		    "i" (pda_offset(field)));				\
++		break;							\
++	case 8:								\
++		asm(op "q %1,%%gs:%c2":					\
++		    "+m" (_proxy_pda.field) :				\
++		    "ri" ((T__)val),					\
++		    "i"(pda_offset(field)));				\
++		break;							\
++	default:							\
++		__bad_pda_field();					\
++	}								\
++} while (0)
+ 
+-#define pda_from_op(op,field) ({		\
++#define pda_from_op(op, field)			\
++({						\
+ 	typeof(_proxy_pda.field) ret__;		\
+ 	switch (sizeof(_proxy_pda.field)) {	\
+ 	case 2:					\
+@@ -93,23 +94,24 @@ extern struct x8664_pda _proxy_pda;
+ 		    "=r" (ret__) :		\
+ 		    "i" (pda_offset(field)),	\
+ 		    "m" (_proxy_pda.field));	\
+-		 break;				\
++		break;				\
+ 	case 4:					\
+ 		asm(op "l %%gs:%c1,%0":		\
+ 		    "=r" (ret__):		\
+ 		    "i" (pda_offset(field)),	\
+ 		    "m" (_proxy_pda.field));	\
+-		 break;				\
++		break;				\
+ 	case 8:					\
+ 		asm(op "q %%gs:%c1,%0":		\
+ 		    "=r" (ret__) :		\
+ 		    "i" (pda_offset(field)),	\
+ 		    "m" (_proxy_pda.field));	\
+-		 break;				\
++		break;				\
+ 	default:				\
+ 		__bad_pda_field();		\
+-       }					\
+-       ret__; })
++	}					\
++	ret__;					\
++})
+ 
+ #define read_pda(field)		pda_from_op("mov", field)
+ #define write_pda(field, val)	pda_to_op("mov", field, val)
+@@ -118,12 +120,13 @@ extern struct x8664_pda _proxy_pda;
+ #define or_pda(field, val)	pda_to_op("or", field, val)
+ 
+ /* This is not atomic against other CPUs -- CPU preemption needs to be off */
+-#define test_and_clear_bit_pda(bit, field) ({		\
+-	int old__;						\
+-	asm volatile("btr %2,%%gs:%c3\n\tsbbl %0,%0"		\
+-	    : "=r" (old__), "+m" (_proxy_pda.field)		\
+-	    : "dIr" (bit), "i" (pda_offset(field)) : "memory");	\
+-	old__;							\
++#define test_and_clear_bit_pda(bit, field)				\
++({									\
++	int old__;							\
++	asm volatile("btr %2,%%gs:%c3\n\tsbbl %0,%0"			\
++		     : "=r" (old__), "+m" (_proxy_pda.field)		\
++		     : "dIr" (bit), "i" (pda_offset(field)) : "memory");\
++	old__;								\
+ })
+ 
+ #endif
+diff --git a/include/asm-x86/percpu.h b/include/asm-x86/percpu.h
+index 0dec00f..736fc3b 100644
+--- a/include/asm-x86/percpu.h
++++ b/include/asm-x86/percpu.h
+@@ -85,58 +85,62 @@ DECLARE_PER_CPU(unsigned long, this_cpu_off);
+  * don't give an lvalue though). */
+ extern void __bad_percpu_size(void);
+ 
+-#define percpu_to_op(op,var,val)				\
+-	do {							\
+-		typedef typeof(var) T__;			\
+-		if (0) { T__ tmp__; tmp__ = (val); }		\
+-		switch (sizeof(var)) {				\
+-		case 1:						\
+-			asm(op "b %1,"__percpu_seg"%0"		\
+-			    : "+m" (var)			\
+-			    :"ri" ((T__)val));			\
+-			break;					\
+-		case 2:						\
+-			asm(op "w %1,"__percpu_seg"%0"		\
+-			    : "+m" (var)			\
+-			    :"ri" ((T__)val));			\
+-			break;					\
+-		case 4:						\
+-			asm(op "l %1,"__percpu_seg"%0"		\
+-			    : "+m" (var)			\
+-			    :"ri" ((T__)val));			\
+-			break;					\
+-		default: __bad_percpu_size();			\
+-		}						\
+-	} while (0)
+-
+-#define percpu_from_op(op,var)					\
+-	({							\
+-		typeof(var) ret__;				\
+-		switch (sizeof(var)) {				\
+-		case 1:						\
+-			asm(op "b "__percpu_seg"%1,%0"		\
+-			    : "=r" (ret__)			\
+-			    : "m" (var));			\
+-			break;					\
+-		case 2:						\
+-			asm(op "w "__percpu_seg"%1,%0"		\
+-			    : "=r" (ret__)			\
+-			    : "m" (var));			\
+-			break;					\
+-		case 4:						\
+-			asm(op "l "__percpu_seg"%1,%0"		\
+-			    : "=r" (ret__)			\
+-			    : "m" (var));			\
+-			break;					\
+-		default: __bad_percpu_size();			\
+-		}						\
+-		ret__; })
++#define percpu_to_op(op, var, val)			\
++do {							\
++	typedef typeof(var) T__;			\
++	if (0) {					\
++		T__ tmp__;				\
++		tmp__ = (val);				\
++	}						\
++	switch (sizeof(var)) {				\
++	case 1:						\
++		asm(op "b %1,"__percpu_seg"%0"		\
++		    : "+m" (var)			\
++		    : "ri" ((T__)val));			\
++		break;					\
++	case 2:						\
++		asm(op "w %1,"__percpu_seg"%0"		\
++		    : "+m" (var)			\
++		    : "ri" ((T__)val));			\
++		break;					\
++	case 4:						\
++		asm(op "l %1,"__percpu_seg"%0"		\
++		    : "+m" (var)			\
++		    : "ri" ((T__)val));			\
++		break;					\
++	default: __bad_percpu_size();			\
++	}						\
++} while (0)
++
++#define percpu_from_op(op, var)				\
++({							\
++	typeof(var) ret__;				\
++	switch (sizeof(var)) {				\
++	case 1:						\
++		asm(op "b "__percpu_seg"%1,%0"		\
++		    : "=r" (ret__)			\
++		    : "m" (var));			\
++		break;					\
++	case 2:						\
++		asm(op "w "__percpu_seg"%1,%0"		\
++		    : "=r" (ret__)			\
++		    : "m" (var));			\
++		break;					\
++	case 4:						\
++		asm(op "l "__percpu_seg"%1,%0"		\
++		    : "=r" (ret__)			\
++		    : "m" (var));			\
++		break;					\
++	default: __bad_percpu_size();			\
++	}						\
++	ret__;						\
++})
+ 
+ #define x86_read_percpu(var) percpu_from_op("mov", per_cpu__##var)
+-#define x86_write_percpu(var,val) percpu_to_op("mov", per_cpu__##var, val)
+-#define x86_add_percpu(var,val) percpu_to_op("add", per_cpu__##var, val)
+-#define x86_sub_percpu(var,val) percpu_to_op("sub", per_cpu__##var, val)
+-#define x86_or_percpu(var,val) percpu_to_op("or", per_cpu__##var, val)
++#define x86_write_percpu(var, val) percpu_to_op("mov", per_cpu__##var, val)
++#define x86_add_percpu(var, val) percpu_to_op("add", per_cpu__##var, val)
++#define x86_sub_percpu(var, val) percpu_to_op("sub", per_cpu__##var, val)
++#define x86_or_percpu(var, val) percpu_to_op("or", per_cpu__##var, val)
+ #endif /* !__ASSEMBLY__ */
+ #endif /* !CONFIG_X86_64 */
+ #endif /* _ASM_X86_PERCPU_H_ */
+diff --git a/include/asm-x86/pgalloc.h b/include/asm-x86/pgalloc.h
+index 5886eed..91e4641 100644
+--- a/include/asm-x86/pgalloc.h
++++ b/include/asm-x86/pgalloc.h
+@@ -1,5 +1,110 @@
+-#ifdef CONFIG_X86_32
+-# include "pgalloc_32.h"
++#ifndef _ASM_X86_PGALLOC_H
++#define _ASM_X86_PGALLOC_H
++
++#include <linux/threads.h>
++#include <linux/mm.h>		/* for struct page */
++#include <linux/pagemap.h>
++
++#ifdef CONFIG_PARAVIRT
++#include <asm/paravirt.h>
+ #else
+-# include "pgalloc_64.h"
++static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned long pfn)	{}
++static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn)	{}
++static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn,
++					    unsigned long start, unsigned long count) {}
++static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned long pfn)	{}
++static inline void paravirt_release_pte(unsigned long pfn) {}
++static inline void paravirt_release_pmd(unsigned long pfn) {}
++static inline void paravirt_release_pud(unsigned long pfn) {}
+ #endif
++
++/*
++ * Allocate and free page tables.
++ */
++extern pgd_t *pgd_alloc(struct mm_struct *);
++extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
++
++extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
++extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
++
++/* Should really implement gc for free page table pages. This could be
++   done with a reference count in struct page. */
++
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
++{
++	BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
++	free_page((unsigned long)pte);
++}
++
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
++{
++	__free_page(pte);
++}
++
++extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
++
++static inline void pmd_populate_kernel(struct mm_struct *mm,
++				       pmd_t *pmd, pte_t *pte)
++{
++	paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
++	set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
++}
++
++static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
++				struct page *pte)
++{
++	unsigned long pfn = page_to_pfn(pte);
++
++	paravirt_alloc_pte(mm, pfn);
++	set_pmd(pmd, __pmd(((pteval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
++}
++
++#define pmd_pgtable(pmd) pmd_page(pmd)
++
++#if PAGETABLE_LEVELS > 2
++static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
++{
++	return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
++}
++
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
++{
++	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
++	free_page((unsigned long)pmd);
++}
++
++extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
++
++#ifdef CONFIG_X86_PAE
++extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
++#else	/* !CONFIG_X86_PAE */
++static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
++{
++	paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
++	set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)));
++}
++#endif	/* CONFIG_X86_PAE */
++
++#if PAGETABLE_LEVELS > 3
++static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
++{
++	paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT);
++	set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)));
++}
++
++static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
++{
++	return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
++}
++
++static inline void pud_free(struct mm_struct *mm, pud_t *pud)
++{
++	BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
++	free_page((unsigned long)pud);
++}
++
++extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
++#endif	/* PAGETABLE_LEVELS > 3 */
++#endif	/* PAGETABLE_LEVELS > 2 */
++
++#endif	/* _ASM_X86_PGALLOC_H */
+diff --git a/include/asm-x86/pgalloc_32.h b/include/asm-x86/pgalloc_32.h
+deleted file mode 100644
+index 6bea6e5..0000000
+--- a/include/asm-x86/pgalloc_32.h
++++ /dev/null
+@@ -1,95 +0,0 @@
+-#ifndef _I386_PGALLOC_H
+-#define _I386_PGALLOC_H
+-
+-#include <linux/threads.h>
+-#include <linux/mm.h>		/* for struct page */
+-#include <linux/pagemap.h>
+-#include <asm/tlb.h>
+-#include <asm-generic/tlb.h>
+-
+-#ifdef CONFIG_PARAVIRT
+-#include <asm/paravirt.h>
+-#else
+-#define paravirt_alloc_pt(mm, pfn) do { } while (0)
+-#define paravirt_alloc_pd(mm, pfn) do { } while (0)
+-#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
+-#define paravirt_release_pt(pfn) do { } while (0)
+-#define paravirt_release_pd(pfn) do { } while (0)
+-#endif
+-
+-static inline void pmd_populate_kernel(struct mm_struct *mm,
+-				       pmd_t *pmd, pte_t *pte)
+-{
+-	paravirt_alloc_pt(mm, __pa(pte) >> PAGE_SHIFT);
+-	set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
+-}
+-
+-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+-{
+-	unsigned long pfn = page_to_pfn(pte);
+-
+-	paravirt_alloc_pt(mm, pfn);
+-	set_pmd(pmd, __pmd(((pteval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
+-}
+-#define pmd_pgtable(pmd) pmd_page(pmd)
+-
+-/*
+- * Allocate and free page tables.
+- */
+-extern pgd_t *pgd_alloc(struct mm_struct *);
+-extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+-
+-extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+-extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
+-
+-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+-{
+-	free_page((unsigned long)pte);
+-}
+-
+-static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+-{
+-	pgtable_page_dtor(pte);
+-	__free_page(pte);
+-}
+-
+-
+-extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+-
+-#ifdef CONFIG_X86_PAE
+-/*
+- * In the PAE case we free the pmds as part of the pgd.
+- */
+-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+-{
+-	return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-}
+-
+-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+-{
+-	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+-	free_page((unsigned long)pmd);
+-}
+-
+-extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+-
+-static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
+-{
+-	paravirt_alloc_pd(mm, __pa(pmd) >> PAGE_SHIFT);
+-
+-	/* Note: almost everything apart from _PAGE_PRESENT is
+-	   reserved at the pmd (PDPT) level. */
+-	set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
+-
+-	/*
+-	 * According to Intel App note "TLBs, Paging-Structure Caches,
+-	 * and Their Invalidation", April 2007, document 317080-001,
+-	 * section 8.1: in PAE mode we explicitly have to flush the
+-	 * TLB via cr3 if the top-level pgd is changed...
+-	 */
+-	if (mm == current->active_mm)
+-		write_cr3(read_cr3());
+-}
+-#endif	/* CONFIG_X86_PAE */
+-
+-#endif /* _I386_PGALLOC_H */
+diff --git a/include/asm-x86/pgalloc_64.h b/include/asm-x86/pgalloc_64.h
+deleted file mode 100644
+index 8d67223..0000000
+--- a/include/asm-x86/pgalloc_64.h
++++ /dev/null
+@@ -1,133 +0,0 @@
+-#ifndef _X86_64_PGALLOC_H
+-#define _X86_64_PGALLOC_H
+-
+-#include <asm/pda.h>
+-#include <linux/threads.h>
+-#include <linux/mm.h>
+-
+-#define pmd_populate_kernel(mm, pmd, pte) \
+-		set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
+-#define pud_populate(mm, pud, pmd) \
+-		set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)))
+-#define pgd_populate(mm, pgd, pud) \
+-		set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)))
+-
+-#define pmd_pgtable(pmd) pmd_page(pmd)
+-
+-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+-{
+-	set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
+-}
+-
+-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+-{
+-	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+-	free_page((unsigned long)pmd);
+-}
+-
+-static inline pmd_t *pmd_alloc_one (struct mm_struct *mm, unsigned long addr)
+-{
+-	return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-}
+-
+-static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+-{
+-	return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-}
+-
+-static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+-{
+-	BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+-	free_page((unsigned long)pud);
+-}
+-
+-static inline void pgd_list_add(pgd_t *pgd)
+-{
+-	struct page *page = virt_to_page(pgd);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	list_add(&page->lru, &pgd_list);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-static inline void pgd_list_del(pgd_t *pgd)
+-{
+-	struct page *page = virt_to_page(pgd);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	list_del(&page->lru);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+-{
+-	unsigned boundary;
+-	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+-	if (!pgd)
+-		return NULL;
+-	pgd_list_add(pgd);
+-	/*
+-	 * Copy kernel pointers in from init.
+-	 * Could keep a freelist or slab cache of those because the kernel
+-	 * part never changes.
+-	 */
+-	boundary = pgd_index(__PAGE_OFFSET);
+-	memset(pgd, 0, boundary * sizeof(pgd_t));
+-	memcpy(pgd + boundary,
+-	       init_level4_pgt + boundary,
+-	       (PTRS_PER_PGD - boundary) * sizeof(pgd_t));
+-	return pgd;
+-}
+-
+-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+-{
+-	BUG_ON((unsigned long)pgd & (PAGE_SIZE-1));
+-	pgd_list_del(pgd);
+-	free_page((unsigned long)pgd);
+-}
+-
+-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+-{
+-	return (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-}
+-
+-static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
+-{
+-	struct page *page;
+-	void *p;
+-
+-	p = (void *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-	if (!p)
+-		return NULL;
+-	page = virt_to_page(p);
+-	pgtable_page_ctor(page);
+-	return page;
+-}
+-
+-/* Should really implement gc for free page table pages. This could be
+-   done with a reference count in struct page. */
+-
+-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+-{
+-	BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
+-	free_page((unsigned long)pte); 
+-}
+-
+-static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+-{
+-	pgtable_page_dtor(pte);
+-	__free_page(pte);
+-} 
+-
+-#define __pte_free_tlb(tlb,pte)				\
+-do {							\
+-	pgtable_page_dtor((pte));				\
+-	tlb_remove_page((tlb), (pte));			\
+-} while (0)
+-
+-#define __pmd_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
+-#define __pud_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
+-
+-#endif /* _X86_64_PGALLOC_H */
+diff --git a/include/asm-x86/pgtable-2level.h b/include/asm-x86/pgtable-2level.h
+index 701404f..46bc52c 100644
+--- a/include/asm-x86/pgtable-2level.h
++++ b/include/asm-x86/pgtable-2level.h
+@@ -26,7 +26,8 @@ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
+ 	native_set_pte(ptep, pte);
+ }
+ 
+-static inline void native_set_pte_present(struct mm_struct *mm, unsigned long addr,
++static inline void native_set_pte_present(struct mm_struct *mm,
++					  unsigned long addr,
+ 					  pte_t *ptep, pte_t pte)
+ {
+ 	native_set_pte(ptep, pte);
+@@ -37,7 +38,8 @@ static inline void native_pmd_clear(pmd_t *pmdp)
+ 	native_set_pmd(pmdp, __pmd(0));
+ }
+ 
+-static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *xp)
++static inline void native_pte_clear(struct mm_struct *mm,
++				    unsigned long addr, pte_t *xp)
+ {
+ 	*xp = native_make_pte(0);
+ }
+@@ -61,16 +63,18 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp)
+  */
+ #define PTE_FILE_MAX_BITS	29
+ 
+-#define pte_to_pgoff(pte) \
+-	((((pte).pte_low >> 1) & 0x1f ) + (((pte).pte_low >> 8) << 5 ))
++#define pte_to_pgoff(pte)						\
++	((((pte).pte_low >> 1) & 0x1f) + (((pte).pte_low >> 8) << 5))
+ 
+-#define pgoff_to_pte(off) \
+-	((pte_t) { .pte_low = (((off) & 0x1f) << 1) + (((off) >> 5) << 8) + _PAGE_FILE })
++#define pgoff_to_pte(off)						\
++	((pte_t) { .pte_low = (((off) & 0x1f) << 1) +			\
++			(((off) >> 5) << 8) + _PAGE_FILE })
+ 
+ /* Encode and de-code a swap entry */
+ #define __swp_type(x)			(((x).val >> 1) & 0x1f)
+ #define __swp_offset(x)			((x).val >> 8)
+-#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
++#define __swp_entry(type, offset)				\
++	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+ #define __pte_to_swp_entry(pte)		((swp_entry_t) { (pte).pte_low })
+ #define __swp_entry_to_pte(x)		((pte_t) { .pte = (x).val })
+ 
+diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h
+index 1d763ee..8b4a9d4 100644
+--- a/include/asm-x86/pgtable-3level.h
++++ b/include/asm-x86/pgtable-3level.h
+@@ -8,22 +8,26 @@
+  * Copyright (C) 1999 Ingo Molnar <mingo at redhat.com>
+  */
+ 
+-#define pte_ERROR(e) \
+-	printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, &(e), (e).pte_high, (e).pte_low)
+-#define pmd_ERROR(e) \
+-	printk("%s:%d: bad pmd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pmd_val(e))
+-#define pgd_ERROR(e) \
+-	printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
+-
++#define pte_ERROR(e)							\
++	printk("%s:%d: bad pte %p(%08lx%08lx).\n",			\
++	       __FILE__, __LINE__, &(e), (e).pte_high, (e).pte_low)
++#define pmd_ERROR(e)							\
++	printk("%s:%d: bad pmd %p(%016Lx).\n",				\
++	       __FILE__, __LINE__, &(e), pmd_val(e))
++#define pgd_ERROR(e)							\
++	printk("%s:%d: bad pgd %p(%016Lx).\n",				\
++	       __FILE__, __LINE__, &(e), pgd_val(e))
+ 
+ static inline int pud_none(pud_t pud)
+ {
+ 	return pud_val(pud) == 0;
+ }
++
+ static inline int pud_bad(pud_t pud)
+ {
+ 	return (pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
+ }
++
+ static inline int pud_present(pud_t pud)
+ {
+ 	return pud_val(pud) & _PAGE_PRESENT;
+@@ -48,7 +52,8 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte)
+  * we are justified in merely clearing the PTE present bit, followed
+  * by a set.  The ordering here is important.
+  */
+-static inline void native_set_pte_present(struct mm_struct *mm, unsigned long addr,
++static inline void native_set_pte_present(struct mm_struct *mm,
++					  unsigned long addr,
+ 					  pte_t *ptep, pte_t pte)
+ {
+ 	ptep->pte_low = 0;
+@@ -60,15 +65,17 @@ static inline void native_set_pte_present(struct mm_struct *mm, unsigned long ad
+ 
+ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
+ {
+-	set_64bit((unsigned long long *)(ptep),native_pte_val(pte));
++	set_64bit((unsigned long long *)(ptep), native_pte_val(pte));
+ }
++
+ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
+ {
+-	set_64bit((unsigned long long *)(pmdp),native_pmd_val(pmd));
++	set_64bit((unsigned long long *)(pmdp), native_pmd_val(pmd));
+ }
++
+ static inline void native_set_pud(pud_t *pudp, pud_t pud)
+ {
+-	set_64bit((unsigned long long *)(pudp),native_pud_val(pud));
++	set_64bit((unsigned long long *)(pudp), native_pud_val(pud));
+ }
+ 
+ /*
+@@ -76,7 +83,8 @@ static inline void native_set_pud(pud_t *pudp, pud_t pud)
+  * entry, so clear the bottom half first and enforce ordering with a compiler
+  * barrier.
+  */
+-static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr,
++				    pte_t *ptep)
+ {
+ 	ptep->pte_low = 0;
+ 	smp_wmb();
+@@ -107,20 +115,19 @@ static inline void pud_clear(pud_t *pudp)
+ 	 * current pgd to avoid unnecessary TLB flushes.
+ 	 */
+ 	pgd = read_cr3();
+-	if (__pa(pudp) >= pgd && __pa(pudp) < (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
++	if (__pa(pudp) >= pgd && __pa(pudp) <
++	    (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
+ 		write_cr3(pgd);
+ }
+ 
+-#define pud_page(pud) \
+-((struct page *) __va(pud_val(pud) & PAGE_MASK))
++#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PAGE_MASK))
+ 
+-#define pud_page_vaddr(pud) \
+-((unsigned long) __va(pud_val(pud) & PAGE_MASK))
++#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PAGE_MASK))
+ 
+ 
+ /* Find an entry in the second-level page table.. */
+-#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
+-			pmd_index(address))
++#define pmd_offset(pud, address) ((pmd_t *)pud_page(*(pud)) +	\
++				  pmd_index(address))
+ 
+ #ifdef CONFIG_SMP
+ static inline pte_t native_ptep_get_and_clear(pte_t *ptep)
+@@ -161,7 +168,8 @@ static inline unsigned long pte_pfn(pte_t pte)
+  * put the 32 bits of offset into the high part.
+  */
+ #define pte_to_pgoff(pte) ((pte).pte_high)
+-#define pgoff_to_pte(off) ((pte_t) { { .pte_low = _PAGE_FILE, .pte_high = (off) } })
++#define pgoff_to_pte(off)						\
++	((pte_t) { { .pte_low = _PAGE_FILE, .pte_high = (off) } })
+ #define PTE_FILE_MAX_BITS       32
+ 
+ /* Encode and de-code a swap entry */
+diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
+index 9cf472a..a496d63 100644
+--- a/include/asm-x86/pgtable.h
++++ b/include/asm-x86/pgtable.h
+@@ -1,16 +1,15 @@
+ #ifndef _ASM_X86_PGTABLE_H
+ #define _ASM_X86_PGTABLE_H
+ 
+-#define USER_PTRS_PER_PGD	((TASK_SIZE-1)/PGDIR_SIZE+1)
+ #define FIRST_USER_ADDRESS	0
+ 
+-#define _PAGE_BIT_PRESENT	0
+-#define _PAGE_BIT_RW		1
+-#define _PAGE_BIT_USER		2
+-#define _PAGE_BIT_PWT		3
+-#define _PAGE_BIT_PCD		4
+-#define _PAGE_BIT_ACCESSED	5
+-#define _PAGE_BIT_DIRTY		6
++#define _PAGE_BIT_PRESENT	0	/* is present */
++#define _PAGE_BIT_RW		1	/* writeable */
++#define _PAGE_BIT_USER		2	/* userspace addressable */
++#define _PAGE_BIT_PWT		3	/* page write through */
++#define _PAGE_BIT_PCD		4	/* page cache disabled */
++#define _PAGE_BIT_ACCESSED	5	/* was accessed (raised by CPU) */
++#define _PAGE_BIT_DIRTY		6	/* was written to (raised by CPU) */
+ #define _PAGE_BIT_FILE		6
+ #define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
+ #define _PAGE_BIT_PAT		7	/* on 4KB pages */
+@@ -48,24 +47,39 @@
+ #endif
+ 
+ /* If _PAGE_PRESENT is clear, we use these: */
+-#define _PAGE_FILE	_PAGE_DIRTY	/* nonlinear file mapping, saved PTE; unset:swap */
++#define _PAGE_FILE	_PAGE_DIRTY	/* nonlinear file mapping,
++					 * saved PTE; unset:swap */
+ #define _PAGE_PROTNONE	_PAGE_PSE	/* if the user mapped it with PROT_NONE;
+ 					   pte_present gives true */
+ 
+-#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
+-#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
++#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
++			 _PAGE_ACCESSED | _PAGE_DIRTY)
++#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
++			 _PAGE_DIRTY)
+ 
+ #define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+ 
+-#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+-#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define _PAGE_CACHE_MASK	(_PAGE_PCD | _PAGE_PWT)
++#define _PAGE_CACHE_WB		(0)
++#define _PAGE_CACHE_WC		(_PAGE_PWT)
++#define _PAGE_CACHE_UC_MINUS	(_PAGE_PCD)
++#define _PAGE_CACHE_UC		(_PAGE_PCD | _PAGE_PWT)
+ 
+-#define PAGE_SHARED_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+-#define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_COPY_EXEC		__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
++#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
++				 _PAGE_ACCESSED | _PAGE_NX)
++
++#define PAGE_SHARED_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_RW |	\
++					 _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_COPY_EXEC		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED)
+ #define PAGE_COPY		PAGE_COPY_NOEXEC
+-#define PAGE_READONLY		__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_READONLY		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED)
+ 
+ #ifdef CONFIG_X86_32
+ #define _PAGE_KERNEL_EXEC \
+@@ -84,6 +98,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+ #define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
+ #define __PAGE_KERNEL_RX		(__PAGE_KERNEL_EXEC & ~_PAGE_RW)
+ #define __PAGE_KERNEL_EXEC_NOCACHE	(__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_WC		(__PAGE_KERNEL | _PAGE_CACHE_WC)
+ #define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
+ #define __PAGE_KERNEL_UC_MINUS		(__PAGE_KERNEL | _PAGE_PCD)
+ #define __PAGE_KERNEL_VSYSCALL		(__PAGE_KERNEL_RX | _PAGE_USER)
+@@ -101,6 +116,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+ #define PAGE_KERNEL_RO			MAKE_GLOBAL(__PAGE_KERNEL_RO)
+ #define PAGE_KERNEL_EXEC		MAKE_GLOBAL(__PAGE_KERNEL_EXEC)
+ #define PAGE_KERNEL_RX			MAKE_GLOBAL(__PAGE_KERNEL_RX)
++#define PAGE_KERNEL_WC			MAKE_GLOBAL(__PAGE_KERNEL_WC)
+ #define PAGE_KERNEL_NOCACHE		MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
+ #define PAGE_KERNEL_UC_MINUS		MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS)
+ #define PAGE_KERNEL_EXEC_NOCACHE	MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE)
+@@ -134,7 +150,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+  * ZERO_PAGE is a global shared page that is always zero: used
+  * for zero-mapped memory areas etc..
+  */
+-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
++extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+ #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+ 
+ extern spinlock_t pgd_lock;
+@@ -144,30 +160,101 @@ extern struct list_head pgd_list;
+  * The following only work if pte_present() is true.
+  * Undefined behaviour if not..
+  */
+-static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
+-static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
+-static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
+-static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
+-static inline int pte_huge(pte_t pte)		{ return pte_val(pte) & _PAGE_PSE; }
+-static inline int pte_global(pte_t pte) 	{ return pte_val(pte) & _PAGE_GLOBAL; }
+-static inline int pte_exec(pte_t pte)		{ return !(pte_val(pte) & _PAGE_NX); }
+-
+-static inline int pmd_large(pmd_t pte) {
+-	return (pmd_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
+-		(_PAGE_PSE|_PAGE_PRESENT);
++static inline int pte_dirty(pte_t pte)
++{
++	return pte_val(pte) & _PAGE_DIRTY;
++}
++
++static inline int pte_young(pte_t pte)
++{
++	return pte_val(pte) & _PAGE_ACCESSED;
++}
++
++static inline int pte_write(pte_t pte)
++{
++	return pte_val(pte) & _PAGE_RW;
++}
++
++static inline int pte_file(pte_t pte)
++{
++	return pte_val(pte) & _PAGE_FILE;
++}
++
++static inline int pte_huge(pte_t pte)
++{
++	return pte_val(pte) & _PAGE_PSE;
++}
++
++static inline int pte_global(pte_t pte)
++{
++	return pte_val(pte) & _PAGE_GLOBAL;
++}
++
++static inline int pte_exec(pte_t pte)
++{
++	return !(pte_val(pte) & _PAGE_NX);
++}
++
++static inline int pmd_large(pmd_t pte)
++{
++	return (pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
++		(_PAGE_PSE | _PAGE_PRESENT);
++}
++
++static inline pte_t pte_mkclean(pte_t pte)
++{
++	return __pte(pte_val(pte) & ~(pteval_t)_PAGE_DIRTY);
++}
++
++static inline pte_t pte_mkold(pte_t pte)
++{
++	return __pte(pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED);
++}
++
++static inline pte_t pte_wrprotect(pte_t pte)
++{
++	return __pte(pte_val(pte) & ~(pteval_t)_PAGE_RW);
+ }
+ 
+-static inline pte_t pte_mkclean(pte_t pte)	{ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_DIRTY); }
+-static inline pte_t pte_mkold(pte_t pte)	{ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED); }
+-static inline pte_t pte_wrprotect(pte_t pte)	{ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_RW); }
+-static inline pte_t pte_mkexec(pte_t pte)	{ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_NX); }
+-static inline pte_t pte_mkdirty(pte_t pte)	{ return __pte(pte_val(pte) | _PAGE_DIRTY); }
+-static inline pte_t pte_mkyoung(pte_t pte)	{ return __pte(pte_val(pte) | _PAGE_ACCESSED); }
+-static inline pte_t pte_mkwrite(pte_t pte)	{ return __pte(pte_val(pte) | _PAGE_RW); }
+-static inline pte_t pte_mkhuge(pte_t pte)	{ return __pte(pte_val(pte) | _PAGE_PSE); }
+-static inline pte_t pte_clrhuge(pte_t pte)	{ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_PSE); }
+-static inline pte_t pte_mkglobal(pte_t pte)	{ return __pte(pte_val(pte) | _PAGE_GLOBAL); }
+-static inline pte_t pte_clrglobal(pte_t pte)	{ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL); }
++static inline pte_t pte_mkexec(pte_t pte)
++{
++	return __pte(pte_val(pte) & ~(pteval_t)_PAGE_NX);
++}
++
++static inline pte_t pte_mkdirty(pte_t pte)
++{
++	return __pte(pte_val(pte) | _PAGE_DIRTY);
++}
++
++static inline pte_t pte_mkyoung(pte_t pte)
++{
++	return __pte(pte_val(pte) | _PAGE_ACCESSED);
++}
++
++static inline pte_t pte_mkwrite(pte_t pte)
++{
++	return __pte(pte_val(pte) | _PAGE_RW);
++}
++
++static inline pte_t pte_mkhuge(pte_t pte)
++{
++	return __pte(pte_val(pte) | _PAGE_PSE);
++}
++
++static inline pte_t pte_clrhuge(pte_t pte)
++{
++	return __pte(pte_val(pte) & ~(pteval_t)_PAGE_PSE);
++}
++
++static inline pte_t pte_mkglobal(pte_t pte)
++{
++	return __pte(pte_val(pte) | _PAGE_GLOBAL);
++}
++
++static inline pte_t pte_clrglobal(pte_t pte)
++{
++	return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL);
++}
+ 
+ extern pteval_t __supported_pte_mask;
+ 
+@@ -201,6 +288,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ 
+ #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
+ 
++#ifndef __ASSEMBLY__
++#define __HAVE_PHYS_MEM_ACCESS_PROT
++struct file;
++pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
++                              unsigned long size, pgprot_t vma_prot);
++int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
++                              unsigned long size, pgprot_t *vma_prot);
++#endif
++
+ #ifdef CONFIG_PARAVIRT
+ #include <asm/paravirt.h>
+ #else  /* !CONFIG_PARAVIRT */
+@@ -242,6 +338,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ # include "pgtable_64.h"
+ #endif
+ 
++#define KERNEL_PGD_BOUNDARY	pgd_index(PAGE_OFFSET)
++#define KERNEL_PGD_PTRS		(PTRS_PER_PGD - KERNEL_PGD_BOUNDARY)
++
+ #ifndef __ASSEMBLY__
+ 
+ enum {
+@@ -301,40 +400,21 @@ static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
+  * bit at the same time.
+  */
+ #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+-#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
+-({									\
+-	int __changed = !pte_same(*(ptep), entry);			\
+-	if (__changed && dirty) {					\
+-		*ptep = entry;						\
+-		pte_update_defer((vma)->vm_mm, (address), (ptep));	\
+-		flush_tlb_page(vma, address);				\
+-	}								\
+-	__changed;							\
+-})
++extern int ptep_set_access_flags(struct vm_area_struct *vma,
++				 unsigned long address, pte_t *ptep,
++				 pte_t entry, int dirty);
+ 
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+-#define ptep_test_and_clear_young(vma, addr, ptep) ({			\
+-	int __ret = 0;							\
+-	if (pte_young(*(ptep)))						\
+-		__ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,		\
+-					   &(ptep)->pte);		\
+-	if (__ret)							\
+-		pte_update((vma)->vm_mm, addr, ptep);			\
+-	__ret;								\
+-})
++extern int ptep_test_and_clear_young(struct vm_area_struct *vma,
++				     unsigned long addr, pte_t *ptep);
+ 
+ #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+-#define ptep_clear_flush_young(vma, address, ptep)			\
+-({									\
+-	int __young;							\
+-	__young = ptep_test_and_clear_young((vma), (address), (ptep));	\
+-	if (__young)							\
+-		flush_tlb_page(vma, address);				\
+-	__young;							\
+-})
++extern int ptep_clear_flush_young(struct vm_area_struct *vma,
++				  unsigned long address, pte_t *ptep);
+ 
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
++				       pte_t *ptep)
+ {
+ 	pte_t pte = native_ptep_get_and_clear(ptep);
+ 	pte_update(mm, addr, ptep);
+@@ -342,7 +422,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ }
+ 
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+-static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
++static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
++					    unsigned long addr, pte_t *ptep,
++					    int full)
+ {
+ 	pte_t pte;
+ 	if (full) {
+@@ -358,12 +440,29 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
+ }
+ 
+ #define __HAVE_ARCH_PTEP_SET_WRPROTECT
+-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline void ptep_set_wrprotect(struct mm_struct *mm,
++				      unsigned long addr, pte_t *ptep)
+ {
+ 	clear_bit(_PAGE_BIT_RW, (unsigned long *)&ptep->pte);
+ 	pte_update(mm, addr, ptep);
+ }
+ 
++/*
++ * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
++ *
++ *  dst - pointer to pgd range anwhere on a pgd page
++ *  src - ""
++ *  count - the number of pgds to copy.
++ *
++ * dst and src can be on the same page, but the range must not overlap,
++ * and must not cross a page boundary.
++ */
++static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
++{
++       memcpy(dst, src, count * sizeof(pgd_t));
++}
++
++
+ #include <asm-generic/pgtable.h>
+ #endif	/* __ASSEMBLY__ */
+ 
+diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h
+index 4e6a0fc..577ab79 100644
+--- a/include/asm-x86/pgtable_32.h
++++ b/include/asm-x86/pgtable_32.h
+@@ -40,16 +40,13 @@ void paging_init(void);
+ #ifdef CONFIG_X86_PAE
+ # include <asm/pgtable-3level-defs.h>
+ # define PMD_SIZE	(1UL << PMD_SHIFT)
+-# define PMD_MASK	(~(PMD_SIZE-1))
++# define PMD_MASK	(~(PMD_SIZE - 1))
+ #else
+ # include <asm/pgtable-2level-defs.h>
+ #endif
+ 
+ #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+-
+-#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+-#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
++#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+ 
+ /* Just any arbitrary offset to the start of the vmalloc VM area: the
+  * current 8MB value just means that there will be a 8MB "hole" after the
+@@ -58,21 +55,22 @@ void paging_init(void);
+  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+  * area for the same reason. ;)
+  */
+-#define VMALLOC_OFFSET	(8*1024*1024)
+-#define VMALLOC_START	(((unsigned long) high_memory + \
+-			2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
++#define VMALLOC_OFFSET	(8 * 1024 * 1024)
++#define VMALLOC_START	(((unsigned long)high_memory + 2 * VMALLOC_OFFSET - 1) \
++			 & ~(VMALLOC_OFFSET - 1))
+ #ifdef CONFIG_X86_PAE
+ #define LAST_PKMAP 512
+ #else
+ #define LAST_PKMAP 1024
+ #endif
+ 
+-#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK)
++#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE * (LAST_PKMAP + 1))	\
++		    & PMD_MASK)
+ 
+ #ifdef CONFIG_HIGHMEM
+-# define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
++# define VMALLOC_END	(PKMAP_BASE - 2 * PAGE_SIZE)
+ #else
+-# define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
++# define VMALLOC_END	(FIXADDR_START - 2 * PAGE_SIZE)
+ #endif
+ 
+ /*
+@@ -88,10 +86,16 @@ extern unsigned long pg0[];
+ #define pte_present(x)	((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
+ 
+ /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
+-#define pmd_none(x)	(!(unsigned long)pmd_val(x))
+-#define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
+-#define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
++#define pmd_none(x)	(!(unsigned long)pmd_val((x)))
++#define pmd_present(x)	(pmd_val((x)) & _PAGE_PRESENT)
++
++extern int pmd_bad(pmd_t pmd);
+ 
++#define pmd_bad_v1(x)							\
++	(_KERNPG_TABLE != (pmd_val((x)) & ~(PAGE_MASK | _PAGE_USER)))
++#define	pmd_bad_v2(x)							\
++	(_KERNPG_TABLE != (pmd_val((x)) & ~(PAGE_MASK | _PAGE_USER |	\
++					    _PAGE_PSE | _PAGE_NX)))
+ 
+ #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+ 
+@@ -102,32 +106,18 @@ extern unsigned long pg0[];
+ #endif
+ 
+ /*
+- * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
+- *
+- *  dst - pointer to pgd range anwhere on a pgd page
+- *  src - ""
+- *  count - the number of pgds to copy.
+- *
+- * dst and src can be on the same page, but the range must not overlap,
+- * and must not cross a page boundary.
+- */
+-static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
+-{
+-       memcpy(dst, src, count * sizeof(pgd_t));
+-}
+-
+-/*
+- * Macro to mark a page protection value as "uncacheable".  On processors which do not support
+- * it, this is a no-op.
++ * Macro to mark a page protection value as "uncacheable".
++ * On processors which do not support it, this is a no-op.
+  */
+-#define pgprot_noncached(prot)	((boot_cpu_data.x86 > 3)					  \
+-				 ? (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT)) : (prot))
++#define pgprot_noncached(prot)					\
++	((boot_cpu_data.x86 > 3)				\
++	 ? (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))	\
++	 : (prot))
+ 
+ /*
+  * Conversion functions: convert a page and protection to a page entry,
+  * and a page entry and page directory to the page they refer to.
+  */
+-
+ #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+ 
+ /*
+@@ -136,20 +126,20 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
+  * this macro returns the index of the entry in the pgd page which would
+  * control the given virtual address
+  */
+-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+-#define pgd_index_k(addr) pgd_index(addr)
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
++#define pgd_index_k(addr) pgd_index((addr))
+ 
+ /*
+  * pgd_offset() returns a (pgd_t *)
+  * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+  */
+-#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
++#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address)))
+ 
+ /*
+  * a shortcut which implies the use of the kernel's pgd, instead
+  * of a process's
+  */
+-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
++#define pgd_offset_k(address) pgd_offset(&init_mm, (address))
+ 
+ static inline int pud_large(pud_t pud) { return 0; }
+ 
+@@ -159,8 +149,8 @@ static inline int pud_large(pud_t pud) { return 0; }
+  * this macro returns the index of the entry in the pmd page which would
+  * control the given virtual address
+  */
+-#define pmd_index(address) \
+-		(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
++#define pmd_index(address)				\
++	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+ 
+ /*
+  * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+@@ -168,54 +158,56 @@ static inline int pud_large(pud_t pud) { return 0; }
+  * this macro returns the index of the entry in the pte page which would
+  * control the given virtual address
+  */
+-#define pte_index(address) \
+-		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+-#define pte_offset_kernel(dir, address) \
+-	((pte_t *) pmd_page_vaddr(*(dir)) +  pte_index(address))
++#define pte_index(address)					\
++	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define pte_offset_kernel(dir, address)				\
++	((pte_t *)pmd_page_vaddr(*(dir)) +  pte_index((address)))
+ 
+-#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
++#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
+ 
+-#define pmd_page_vaddr(pmd) \
+-		((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
++#define pmd_page_vaddr(pmd)					\
++	((unsigned long)__va(pmd_val((pmd)) & PAGE_MASK))
+ 
+ #if defined(CONFIG_HIGHPTE)
+-#define pte_offset_map(dir, address) \
+-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
+-#define pte_offset_map_nested(dir, address) \
+-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
+-#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
+-#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
++#define pte_offset_map(dir, address)					\
++	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) +		\
++	 pte_index((address)))
++#define pte_offset_map_nested(dir, address)				\
++	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE1) +		\
++	 pte_index((address)))
++#define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0)
++#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
+ #else
+-#define pte_offset_map(dir, address) \
+-	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
+-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
++#define pte_offset_map(dir, address)					\
++	((pte_t *)page_address(pmd_page(*(dir))) + pte_index((address)))
++#define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address))
+ #define pte_unmap(pte) do { } while (0)
+ #define pte_unmap_nested(pte) do { } while (0)
+ #endif
+ 
+ /* Clear a kernel PTE and flush it from the TLB */
+-#define kpte_clear_flush(ptep, vaddr)					\
+-do {									\
+-	pte_clear(&init_mm, vaddr, ptep);				\
+-	__flush_tlb_one(vaddr);						\
++#define kpte_clear_flush(ptep, vaddr)		\
++do {						\
++	pte_clear(&init_mm, (vaddr), (ptep));	\
++	__flush_tlb_one((vaddr));		\
+ } while (0)
+ 
+ /*
+  * The i386 doesn't have any external MMU info: the kernel page
+  * tables contain all the necessary information.
+  */
+-#define update_mmu_cache(vma,address,pte) do { } while (0)
++#define update_mmu_cache(vma, address, pte) do { } while (0)
+ 
+-void native_pagetable_setup_start(pgd_t *base);
+-void native_pagetable_setup_done(pgd_t *base);
++extern void native_pagetable_setup_start(pgd_t *base);
++extern void native_pagetable_setup_done(pgd_t *base);
+ 
+ #ifndef CONFIG_PARAVIRT
+-static inline void paravirt_pagetable_setup_start(pgd_t *base)
++static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
+ {
+ 	native_pagetable_setup_start(base);
+ }
+ 
+-static inline void paravirt_pagetable_setup_done(pgd_t *base)
++static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
+ {
+ 	native_pagetable_setup_done(base);
+ }
+@@ -233,7 +225,7 @@ static inline void paravirt_pagetable_setup_done(pgd_t *base)
+ #define kern_addr_valid(kaddr)	(0)
+ #endif
+ 
+-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
+-		remap_pfn_range(vma, vaddr, pfn, size, prot)
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)	\
++	remap_pfn_range(vma, vaddr, pfn, size, prot)
+ 
+ #endif /* _I386_PGTABLE_H */
+diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h
+index 0a0b77b..a3bbf87 100644
+--- a/include/asm-x86/pgtable_64.h
++++ b/include/asm-x86/pgtable_64.h
+@@ -24,7 +24,7 @@ extern void paging_init(void);
+ 
+ #endif /* !__ASSEMBLY__ */
+ 
+-#define SHARED_KERNEL_PMD	1
++#define SHARED_KERNEL_PMD	0
+ 
+ /*
+  * PGDIR_SHIFT determines what a top-level page table entry can map
+@@ -52,14 +52,18 @@ extern void paging_init(void);
+ 
+ #ifndef __ASSEMBLY__
+ 
+-#define pte_ERROR(e) \
+-	printk("%s:%d: bad pte %p(%016lx).\n", __FILE__, __LINE__, &(e), pte_val(e))
+-#define pmd_ERROR(e) \
+-	printk("%s:%d: bad pmd %p(%016lx).\n", __FILE__, __LINE__, &(e), pmd_val(e))
+-#define pud_ERROR(e) \
+-	printk("%s:%d: bad pud %p(%016lx).\n", __FILE__, __LINE__, &(e), pud_val(e))
+-#define pgd_ERROR(e) \
+-	printk("%s:%d: bad pgd %p(%016lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
++#define pte_ERROR(e)					\
++	printk("%s:%d: bad pte %p(%016lx).\n",		\
++	       __FILE__, __LINE__, &(e), pte_val(e))
++#define pmd_ERROR(e)					\
++	printk("%s:%d: bad pmd %p(%016lx).\n",		\
++	       __FILE__, __LINE__, &(e), pmd_val(e))
++#define pud_ERROR(e)					\
++	printk("%s:%d: bad pud %p(%016lx).\n",		\
++	       __FILE__, __LINE__, &(e), pud_val(e))
++#define pgd_ERROR(e)					\
++	printk("%s:%d: bad pgd %p(%016lx).\n",		\
++	       __FILE__, __LINE__, &(e), pgd_val(e))
+ 
+ #define pgd_none(x)	(!pgd_val(x))
+ #define pud_none(x)	(!pud_val(x))
+@@ -87,7 +91,8 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp)
+ #ifdef CONFIG_SMP
+ 	return native_make_pte(xchg(&xp->pte, 0));
+ #else
+-	/* native_local_ptep_get_and_clear, but duplicated because of cyclic dependency */
++	/* native_local_ptep_get_and_clear,
++	   but duplicated because of cyclic dependency */
+ 	pte_t ret = *xp;
+ 	native_pte_clear(NULL, 0, xp);
+ 	return ret;
+@@ -119,7 +124,7 @@ static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd)
+ 	*pgdp = pgd;
+ }
+ 
+-static inline void native_pgd_clear(pgd_t * pgd)
++static inline void native_pgd_clear(pgd_t *pgd)
+ {
+ 	native_set_pgd(pgd, native_make_pgd(0));
+ }
+@@ -128,19 +133,19 @@ static inline void native_pgd_clear(pgd_t * pgd)
+ 
+ #endif /* !__ASSEMBLY__ */
+ 
+-#define PMD_SIZE	(_AC(1,UL) << PMD_SHIFT)
+-#define PMD_MASK	(~(PMD_SIZE-1))
+-#define PUD_SIZE	(_AC(1,UL) << PUD_SHIFT)
+-#define PUD_MASK	(~(PUD_SIZE-1))
+-#define PGDIR_SIZE	(_AC(1,UL) << PGDIR_SHIFT)
+-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
++#define PMD_SIZE	(_AC(1, UL) << PMD_SHIFT)
++#define PMD_MASK	(~(PMD_SIZE - 1))
++#define PUD_SIZE	(_AC(1, UL) << PUD_SHIFT)
++#define PUD_MASK	(~(PUD_SIZE - 1))
++#define PGDIR_SIZE	(_AC(1, UL) << PGDIR_SHIFT)
++#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+ 
+ 
+-#define MAXMEM		 _AC(0x3fffffffffff, UL)
++#define MAXMEM		 _AC(0x00003fffffffffff, UL)
+ #define VMALLOC_START    _AC(0xffffc20000000000, UL)
+ #define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
+ #define VMEMMAP_START	 _AC(0xffffe20000000000, UL)
+-#define MODULES_VADDR    _AC(0xffffffff88000000, UL)
++#define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
+ #define MODULES_END      _AC(0xfffffffffff00000, UL)
+ #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
+ 
+@@ -153,26 +158,28 @@ static inline unsigned long pgd_bad(pgd_t pgd)
+ 
+ static inline unsigned long pud_bad(pud_t pud)
+ {
+-	return pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
++	return pud_val(pud) &
++		~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER | _PAGE_PSE | _PAGE_NX);
+ }
+ 
+ static inline unsigned long pmd_bad(pmd_t pmd)
+ {
+-	return pmd_val(pmd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
++	return pmd_val(pmd) &
++		~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER | _PAGE_PSE | _PAGE_NX);
+ }
+ 
+-#define pte_none(x)	(!pte_val(x))
+-#define pte_present(x)	(pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
++#define pte_none(x)	(!pte_val((x)))
++#define pte_present(x)	(pte_val((x)) & (_PAGE_PRESENT | _PAGE_PROTNONE))
+ 
+-#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))	/* FIXME: is this right? */
+-#define pte_page(x)	pfn_to_page(pte_pfn(x))
+-#define pte_pfn(x)  ((pte_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++#define pages_to_mb(x)	((x) >> (20 - PAGE_SHIFT))   /* FIXME: is this right? */
++#define pte_page(x)	pfn_to_page(pte_pfn((x)))
++#define pte_pfn(x)	((pte_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+ 
+ /*
+  * Macro to mark a page protection value as "uncacheable".
+  */
+-#define pgprot_noncached(prot)	(__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
+-
++#define pgprot_noncached(prot)					\
++	(__pgprot(pgprot_val((prot)) | _PAGE_PCD | _PAGE_PWT))
+ 
+ /*
+  * Conversion functions: convert a page and protection to a page entry,
+@@ -182,75 +189,81 @@ static inline unsigned long pmd_bad(pmd_t pmd)
+ /*
+  * Level 4 access.
+  */
+-#define pgd_page_vaddr(pgd) ((unsigned long) __va((unsigned long)pgd_val(pgd) & PTE_MASK))
+-#define pgd_page(pgd)		(pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT))
+-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+-#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+-#define pgd_offset_k(address) (init_level4_pgt + pgd_index(address))
++#define pgd_page_vaddr(pgd)						\
++	((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_MASK))
++#define pgd_page(pgd)		(pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT))
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
++#define pgd_offset(mm, address)	((mm)->pgd + pgd_index((address)))
++#define pgd_offset_k(address) (init_level4_pgt + pgd_index((address)))
+ #define pgd_present(pgd) (pgd_val(pgd) & _PAGE_PRESENT)
+ static inline int pgd_large(pgd_t pgd) { return 0; }
+ #define mk_kernel_pgd(address) ((pgd_t){ (address) | _KERNPG_TABLE })
+ 
+ /* PUD - Level3 access */
+ /* to find an entry in a page-table-directory. */
+-#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
+-#define pud_page(pud)		(pfn_to_page(pud_val(pud) >> PAGE_SHIFT))
+-#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+-#define pud_offset(pgd, address) ((pud_t *) pgd_page_vaddr(*(pgd)) + pud_index(address))
+-#define pud_present(pud) (pud_val(pud) & _PAGE_PRESENT)
++#define pud_page_vaddr(pud)						\
++	((unsigned long)__va(pud_val((pud)) & PHYSICAL_PAGE_MASK))
++#define pud_page(pud)	(pfn_to_page(pud_val((pud)) >> PAGE_SHIFT))
++#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
++#define pud_offset(pgd, address)					\
++	((pud_t *)pgd_page_vaddr(*(pgd)) + pud_index((address)))
++#define pud_present(pud) (pud_val((pud)) & _PAGE_PRESENT)
+ 
+ static inline int pud_large(pud_t pte)
+ {
+-	return (pud_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
+-		(_PAGE_PSE|_PAGE_PRESENT);
++	return (pud_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
++		(_PAGE_PSE | _PAGE_PRESENT);
+ }
+ 
+ /* PMD  - Level 2 access */
+-#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
+-#define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+-
+-#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+-#define pmd_offset(dir, address) ((pmd_t *) pud_page_vaddr(*(dir)) + \
+-			pmd_index(address))
+-#define pmd_none(x)	(!pmd_val(x))
+-#define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
+-#define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
+-#define pmd_pfn(x)  ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+-
+-#define pte_to_pgoff(pte) ((pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
+-#define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) | _PAGE_FILE })
++#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_MASK))
++#define pmd_page(pmd)		(pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
++
++#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
++#define pmd_offset(dir, address) ((pmd_t *)pud_page_vaddr(*(dir)) + \
++				  pmd_index(address))
++#define pmd_none(x)	(!pmd_val((x)))
++#define pmd_present(x)	(pmd_val((x)) & _PAGE_PRESENT)
++#define pfn_pmd(nr, prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val((prot))))
++#define pmd_pfn(x)  ((pmd_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++
++#define pte_to_pgoff(pte) ((pte_val((pte)) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
++#define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) |	\
++					    _PAGE_FILE })
+ #define PTE_FILE_MAX_BITS __PHYSICAL_MASK_SHIFT
+ 
+ /* PTE - Level 1 access. */
+ 
+ /* page, protection -> pte */
+-#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+- 
+-#define pte_index(address) \
+-		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn((page)), (pgprot))
++
++#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+ #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
+-			pte_index(address))
++					 pte_index((address)))
+ 
+ /* x86-64 always has all page tables mapped. */
+-#define pte_offset_map(dir,address) pte_offset_kernel(dir,address)
+-#define pte_offset_map_nested(dir,address) pte_offset_kernel(dir,address)
++#define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
++#define pte_offset_map_nested(dir, address) pte_offset_kernel((dir), (address))
+ #define pte_unmap(pte) /* NOP */
+-#define pte_unmap_nested(pte) /* NOP */ 
++#define pte_unmap_nested(pte) /* NOP */
++
++#define update_mmu_cache(vma, address, pte) do { } while (0)
+ 
+-#define update_mmu_cache(vma,address,pte) do { } while (0)
++extern int direct_gbpages;
+ 
+ /* Encode and de-code a swap entry */
+ #define __swp_type(x)			(((x).val >> 1) & 0x3f)
+ #define __swp_offset(x)			((x).val >> 8)
+-#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+-#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
++#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | \
++							 ((offset) << 8) })
++#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val((pte)) })
+ #define __swp_entry_to_pte(x)		((pte_t) { .pte = (x).val })
+ 
+-extern int kern_addr_valid(unsigned long addr); 
++extern int kern_addr_valid(unsigned long addr);
+ extern void cleanup_highmap(void);
+ 
+-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
+-		remap_pfn_range(vma, vaddr, pfn, size, prot)
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)	\
++	remap_pfn_range(vma, vaddr, pfn, size, prot)
+ 
+ #define HAVE_ARCH_UNMAPPED_AREA
+ #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+@@ -263,8 +276,10 @@ extern void cleanup_highmap(void);
+ 
+ /* fs/proc/kcore.c */
+ #define	kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
+-#define	kc_offset_to_vaddr(o) \
+-   (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
++#define	kc_offset_to_vaddr(o)				\
++	(((o) & (1UL << (__VIRTUAL_MASK_SHIFT - 1)))	\
++	 ? ((o) | ~__VIRTUAL_MASK)			\
++	 : (o))
+ 
+ #define __HAVE_ARCH_PTE_SAME
+ #endif /* !__ASSEMBLY__ */
+diff --git a/include/asm-x86/posix_types_32.h b/include/asm-x86/posix_types_32.h
+index 015e539..b031efd 100644
+--- a/include/asm-x86/posix_types_32.h
++++ b/include/asm-x86/posix_types_32.h
+@@ -45,32 +45,39 @@ typedef struct {
+ #if defined(__KERNEL__)
+ 
+ #undef	__FD_SET
+-#define __FD_SET(fd,fdsetp) \
+-		__asm__ __volatile__("btsl %1,%0": \
+-			"+m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
++#define __FD_SET(fd,fdsetp)					\
++	asm volatile("btsl %1,%0":				\
++		     "+m" (*(__kernel_fd_set *)(fdsetp))	\
++		     : "r" ((int)(fd)))
+ 
+ #undef	__FD_CLR
+-#define __FD_CLR(fd,fdsetp) \
+-		__asm__ __volatile__("btrl %1,%0": \
+-			"+m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
++#define __FD_CLR(fd,fdsetp)					\
++	asm volatile("btrl %1,%0":				\
++		     "+m" (*(__kernel_fd_set *)(fdsetp))	\
++		     : "r" ((int) (fd)))
+ 
+ #undef	__FD_ISSET
+-#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
+-		unsigned char __result; \
+-		__asm__ __volatile__("btl %1,%2 ; setb %0" \
+-			:"=q" (__result) :"r" ((int) (fd)), \
+-			"m" (*(__kernel_fd_set *) (fdsetp))); \
+-		__result; }))
++#define __FD_ISSET(fd,fdsetp)					\
++	(__extension__						\
++	 ({							\
++	 unsigned char __result;				\
++	 asm volatile("btl %1,%2 ; setb %0"			\
++		      : "=q" (__result)				\
++		      : "r" ((int)(fd)),			\
++			"m" (*(__kernel_fd_set *)(fdsetp)));	\
++	 __result;						\
++}))
+ 
+ #undef	__FD_ZERO
+-#define __FD_ZERO(fdsetp) \
+-do { \
+-	int __d0, __d1; \
+-	__asm__ __volatile__("cld ; rep ; stosl" \
+-			:"=m" (*(__kernel_fd_set *) (fdsetp)), \
+-			  "=&c" (__d0), "=&D" (__d1) \
+-			:"a" (0), "1" (__FDSET_LONGS), \
+-			"2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
++#define __FD_ZERO(fdsetp)					\
++do {								\
++	int __d0, __d1;						\
++	asm volatile("cld ; rep ; stosl"			\
++		     : "=m" (*(__kernel_fd_set *)(fdsetp)),	\
++		       "=&c" (__d0), "=&D" (__d1)		\
++		     : "a" (0), "1" (__FDSET_LONGS),		\
++		       "2" ((__kernel_fd_set *)(fdsetp))	\
++		     : "memory");				\
+ } while (0)
+ 
+ #endif /* defined(__KERNEL__) */
+diff --git a/include/asm-x86/posix_types_64.h b/include/asm-x86/posix_types_64.h
+index 9926aa4..d6624c9 100644
+--- a/include/asm-x86/posix_types_64.h
++++ b/include/asm-x86/posix_types_64.h
+@@ -46,7 +46,7 @@ typedef unsigned long	__kernel_old_dev_t;
+ #ifdef __KERNEL__
+ 
+ #undef __FD_SET
+-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
++static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+ {
+ 	unsigned long _tmp = fd / __NFDBITS;
+ 	unsigned long _rem = fd % __NFDBITS;
+@@ -54,7 +54,7 @@ static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+ }
+ 
+ #undef __FD_CLR
+-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
++static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+ {
+ 	unsigned long _tmp = fd / __NFDBITS;
+ 	unsigned long _rem = fd % __NFDBITS;
+@@ -62,7 +62,7 @@ static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+ }
+ 
+ #undef __FD_ISSET
+-static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
++static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+ {
+ 	unsigned long _tmp = fd / __NFDBITS;
+ 	unsigned long _rem = fd % __NFDBITS;
+@@ -74,36 +74,36 @@ static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+  * for 256 and 1024-bit fd_sets respectively)
+  */
+ #undef __FD_ZERO
+-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
++static inline void __FD_ZERO(__kernel_fd_set *p)
+ {
+ 	unsigned long *tmp = p->fds_bits;
+ 	int i;
+ 
+ 	if (__builtin_constant_p(__FDSET_LONGS)) {
+ 		switch (__FDSET_LONGS) {
+-			case 32:
+-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+-			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+-			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+-			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+-			  tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
+-			  tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
+-			  tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
+-			  tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
+-			  return;
+-			case 16:
+-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+-			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+-			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+-			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+-			  return;
+-			case 8:
+-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+-			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+-			  return;
+-			case 4:
+-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+-			  return;
++		case 32:
++			tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
++			tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
++			tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
++			tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
++			tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
++			tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
++			tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
++			tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
++			return;
++		case 16:
++			tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
++			tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
++			tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
++			tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
++			return;
++		case 8:
++			tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
++			tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
++			return;
++		case 4:
++			tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
++			return;
+ 		}
+ 	}
+ 	i = __FDSET_LONGS;
+diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h
+index 45a2f0a..117343b 100644
+--- a/include/asm-x86/processor.h
++++ b/include/asm-x86/processor.h
+@@ -3,8 +3,7 @@
+ 
+ #include <asm/processor-flags.h>
+ 
+-/* migration helpers, for KVM - will be removed in 2.6.25: */
+-#include <asm/vm86.h>
++/* migration helper, for KVM - will be removed in 2.6.25: */
+ #define Xgt_desc_struct	desc_ptr
+ 
+ /* Forward declaration, a strange C thing */
+@@ -24,6 +23,7 @@ struct mm_struct;
+ #include <asm/msr.h>
+ #include <asm/desc_defs.h>
+ #include <asm/nops.h>
++
+ #include <linux/personality.h>
+ #include <linux/cpumask.h>
+ #include <linux/cache.h>
+@@ -37,16 +37,18 @@ struct mm_struct;
+ static inline void *current_text_addr(void)
+ {
+ 	void *pc;
+-	asm volatile("mov $1f,%0\n1:":"=r" (pc));
++
++	asm volatile("mov $1f, %0; 1:":"=r" (pc));
++
+ 	return pc;
+ }
+ 
+ #ifdef CONFIG_X86_VSMP
+-#define ARCH_MIN_TASKALIGN	(1 << INTERNODE_CACHE_SHIFT)
+-#define ARCH_MIN_MMSTRUCT_ALIGN	(1 << INTERNODE_CACHE_SHIFT)
++# define ARCH_MIN_TASKALIGN		(1 << INTERNODE_CACHE_SHIFT)
++# define ARCH_MIN_MMSTRUCT_ALIGN	(1 << INTERNODE_CACHE_SHIFT)
+ #else
+-#define ARCH_MIN_TASKALIGN	16
+-#define ARCH_MIN_MMSTRUCT_ALIGN	0
++# define ARCH_MIN_TASKALIGN		16
++# define ARCH_MIN_MMSTRUCT_ALIGN	0
+ #endif
+ 
+ /*
+@@ -56,69 +58,81 @@ static inline void *current_text_addr(void)
+  */
+ 
+ struct cpuinfo_x86 {
+-	__u8	x86;		/* CPU family */
+-	__u8	x86_vendor;	/* CPU vendor */
+-	__u8	x86_model;
+-	__u8	x86_mask;
++	__u8			x86;		/* CPU family */
++	__u8			x86_vendor;	/* CPU vendor */
++	__u8			x86_model;
++	__u8			x86_mask;
+ #ifdef CONFIG_X86_32
+-	char	wp_works_ok;	/* It doesn't on 386's */
+-	char	hlt_works_ok;	/* Problems on some 486Dx4's and old 386's */
+-	char	hard_math;
+-	char	rfu;
+-	char	fdiv_bug;
+-	char	f00f_bug;
+-	char	coma_bug;
+-	char	pad0;
++	char			wp_works_ok;	/* It doesn't on 386's */
++
++	/* Problems on some 486Dx4's and old 386's: */
++	char			hlt_works_ok;
++	char			hard_math;
++	char			rfu;
++	char			fdiv_bug;
++	char			f00f_bug;
++	char			coma_bug;
++	char			pad0;
+ #else
+-	/* number of 4K pages in DTLB/ITLB combined(in pages)*/
+-	int     x86_tlbsize;
+-	__u8    x86_virt_bits, x86_phys_bits;
+-	/* cpuid returned core id bits */
+-	__u8    x86_coreid_bits;
+-	/* Max extended CPUID function supported */
+-	__u32   extended_cpuid_level;
++	/* Number of 4K pages in DTLB/ITLB combined(in pages): */
++	int			 x86_tlbsize;
++	__u8			x86_virt_bits;
++	__u8			x86_phys_bits;
++	/* CPUID returned core id bits: */
++	__u8			x86_coreid_bits;
++	/* Max extended CPUID function supported: */
++	__u32			extended_cpuid_level;
+ #endif
+-	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */
+-	__u32	x86_capability[NCAPINTS];
+-	char	x86_vendor_id[16];
+-	char	x86_model_id[64];
+-	int 	x86_cache_size;  /* in KB - valid for CPUS which support this
+-				    call  */
+-	int 	x86_cache_alignment;	/* In bytes */
+-	int	x86_power;
+-	unsigned long loops_per_jiffy;
++	/* Maximum supported CPUID level, -1=no CPUID: */
++	int			cpuid_level;
++	__u32			x86_capability[NCAPINTS];
++	char			x86_vendor_id[16];
++	char			x86_model_id[64];
++	/* in KB - valid for CPUS which support this call: */
++	int			x86_cache_size;
++	int			x86_cache_alignment;	/* In bytes */
++	int			x86_power;
++	unsigned long		loops_per_jiffy;
+ #ifdef CONFIG_SMP
+-	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
++	/* cpus sharing the last level cache: */
++	cpumask_t		llc_shared_map;
+ #endif
+-	u16 x86_max_cores;		/* cpuid returned max cores value */
+-	u16 apicid;
+-	u16 x86_clflush_size;
++	/* cpuid returned max cores value: */
++	u16			 x86_max_cores;
++	u16			apicid;
++	u16			initial_apicid;
++	u16			x86_clflush_size;
+ #ifdef CONFIG_SMP
+-	u16 booted_cores;		/* number of cores as seen by OS */
+-	u16 phys_proc_id; 		/* Physical processor id. */
+-	u16 cpu_core_id;  		/* Core id */
+-	u16 cpu_index;			/* index into per_cpu list */
++	/* number of cores as seen by the OS: */
++	u16			booted_cores;
++	/* Physical processor id: */
++	u16			phys_proc_id;
++	/* Core id: */
++	u16			cpu_core_id;
++	/* Index into per_cpu list: */
++	u16			cpu_index;
+ #endif
+ } __attribute__((__aligned__(SMP_CACHE_BYTES)));
+ 
+-#define X86_VENDOR_INTEL 0
+-#define X86_VENDOR_CYRIX 1
+-#define X86_VENDOR_AMD 2
+-#define X86_VENDOR_UMC 3
+-#define X86_VENDOR_NEXGEN 4
+-#define X86_VENDOR_CENTAUR 5
+-#define X86_VENDOR_TRANSMETA 7
+-#define X86_VENDOR_NSC 8
+-#define X86_VENDOR_NUM 9
+-#define X86_VENDOR_UNKNOWN 0xff
++#define X86_VENDOR_INTEL	0
++#define X86_VENDOR_CYRIX	1
++#define X86_VENDOR_AMD		2
++#define X86_VENDOR_UMC		3
++#define X86_VENDOR_CENTAUR	5
++#define X86_VENDOR_TRANSMETA	7
++#define X86_VENDOR_NSC		8
++#define X86_VENDOR_NUM		9
++
++#define X86_VENDOR_UNKNOWN	0xff
+ 
+ /*
+  * capabilities of CPUs
+  */
+-extern struct cpuinfo_x86 boot_cpu_data;
+-extern struct cpuinfo_x86 new_cpu_data;
+-extern struct tss_struct doublefault_tss;
+-extern __u32 cleared_cpu_caps[NCAPINTS];
++extern struct cpuinfo_x86	boot_cpu_data;
++extern struct cpuinfo_x86	new_cpu_data;
++
++extern struct tss_struct	doublefault_tss;
++extern __u32			cleared_cpu_caps[NCAPINTS];
+ 
+ #ifdef CONFIG_SMP
+ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+@@ -129,7 +143,18 @@ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+ #define current_cpu_data	boot_cpu_data
+ #endif
+ 
+-void cpu_detect(struct cpuinfo_x86 *c);
++static inline int hlt_works(int cpu)
++{
++#ifdef CONFIG_X86_32
++	return cpu_data(cpu).hlt_works_ok;
++#else
++	return 1;
++#endif
++}
++
++#define cache_line_size()	(boot_cpu_data.x86_cache_alignment)
++
++extern void cpu_detect(struct cpuinfo_x86 *c);
+ 
+ extern void identify_cpu(struct cpuinfo_x86 *);
+ extern void identify_boot_cpu(void);
+@@ -146,15 +171,15 @@ static inline void detect_ht(struct cpuinfo_x86 *c) {}
+ #endif
+ 
+ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
+-					 unsigned int *ecx, unsigned int *edx)
++				unsigned int *ecx, unsigned int *edx)
+ {
+ 	/* ecx is often an input as well as an output. */
+-	__asm__("cpuid"
+-		: "=a" (*eax),
+-		  "=b" (*ebx),
+-		  "=c" (*ecx),
+-		  "=d" (*edx)
+-		: "0" (*eax), "2" (*ecx));
++	asm("cpuid"
++	    : "=a" (*eax),
++	      "=b" (*ebx),
++	      "=c" (*ecx),
++	      "=d" (*edx)
++	    : "0" (*eax), "2" (*ecx));
+ }
+ 
+ static inline void load_cr3(pgd_t *pgdir)
+@@ -165,54 +190,67 @@ static inline void load_cr3(pgd_t *pgdir)
+ #ifdef CONFIG_X86_32
+ /* This is the TSS defined by the hardware. */
+ struct x86_hw_tss {
+-	unsigned short	back_link, __blh;
+-	unsigned long	sp0;
+-	unsigned short	ss0, __ss0h;
+-	unsigned long	sp1;
+-	unsigned short	ss1, __ss1h;	/* ss1 caches MSR_IA32_SYSENTER_CS */
+-	unsigned long	sp2;
+-	unsigned short	ss2, __ss2h;
+-	unsigned long	__cr3;
+-	unsigned long	ip;
+-	unsigned long	flags;
+-	unsigned long	ax, cx, dx, bx;
+-	unsigned long	sp, bp, si, di;
+-	unsigned short	es, __esh;
+-	unsigned short	cs, __csh;
+-	unsigned short	ss, __ssh;
+-	unsigned short	ds, __dsh;
+-	unsigned short	fs, __fsh;
+-	unsigned short	gs, __gsh;
+-	unsigned short	ldt, __ldth;
+-	unsigned short	trace, io_bitmap_base;
++	unsigned short		back_link, __blh;
++	unsigned long		sp0;
++	unsigned short		ss0, __ss0h;
++	unsigned long		sp1;
++	/* ss1 caches MSR_IA32_SYSENTER_CS: */
++	unsigned short		ss1, __ss1h;
++	unsigned long		sp2;
++	unsigned short		ss2, __ss2h;
++	unsigned long		__cr3;
++	unsigned long		ip;
++	unsigned long		flags;
++	unsigned long		ax;
++	unsigned long		cx;
++	unsigned long		dx;
++	unsigned long		bx;
++	unsigned long		sp;
++	unsigned long		bp;
++	unsigned long		si;
++	unsigned long		di;
++	unsigned short		es, __esh;
++	unsigned short		cs, __csh;
++	unsigned short		ss, __ssh;
++	unsigned short		ds, __dsh;
++	unsigned short		fs, __fsh;
++	unsigned short		gs, __gsh;
++	unsigned short		ldt, __ldth;
++	unsigned short		trace;
++	unsigned short		io_bitmap_base;
++
+ } __attribute__((packed));
+ #else
+ struct x86_hw_tss {
+-	u32 reserved1;
+-	u64 sp0;
+-	u64 sp1;
+-	u64 sp2;
+-	u64 reserved2;
+-	u64 ist[7];
+-	u32 reserved3;
+-	u32 reserved4;
+-	u16 reserved5;
+-	u16 io_bitmap_base;
++	u32			reserved1;
++	u64			sp0;
++	u64			sp1;
++	u64			sp2;
++	u64			reserved2;
++	u64			ist[7];
++	u32			reserved3;
++	u32			reserved4;
++	u16			reserved5;
++	u16			io_bitmap_base;
++
+ } __attribute__((packed)) ____cacheline_aligned;
+ #endif
+ 
+ /*
+- * Size of io_bitmap.
++ * IO-bitmap sizes:
+  */
+-#define IO_BITMAP_BITS  65536
+-#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
+-#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
+-#define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap)
+-#define INVALID_IO_BITMAP_OFFSET 0x8000
+-#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
++#define IO_BITMAP_BITS			65536
++#define IO_BITMAP_BYTES			(IO_BITMAP_BITS/8)
++#define IO_BITMAP_LONGS			(IO_BITMAP_BYTES/sizeof(long))
++#define IO_BITMAP_OFFSET		offsetof(struct tss_struct, io_bitmap)
++#define INVALID_IO_BITMAP_OFFSET	0x8000
++#define INVALID_IO_BITMAP_OFFSET_LAZY	0x9000
+ 
+ struct tss_struct {
+-	struct x86_hw_tss x86_tss;
++	/*
++	 * The hardware state:
++	 */
++	struct x86_hw_tss	x86_tss;
+ 
+ 	/*
+ 	 * The extra 1 is there because the CPU will access an
+@@ -220,135 +258,164 @@ struct tss_struct {
+ 	 * bitmap. The extra byte must be all 1 bits, and must
+ 	 * be within the limit.
+ 	 */
+-	unsigned long	io_bitmap[IO_BITMAP_LONGS + 1];
++	unsigned long		io_bitmap[IO_BITMAP_LONGS + 1];
+ 	/*
+ 	 * Cache the current maximum and the last task that used the bitmap:
+ 	 */
+-	unsigned long io_bitmap_max;
+-	struct thread_struct *io_bitmap_owner;
++	unsigned long		io_bitmap_max;
++	struct thread_struct	*io_bitmap_owner;
++
+ 	/*
+-	 * pads the TSS to be cacheline-aligned (size is 0x100)
++	 * Pad the TSS to be cacheline-aligned (size is 0x100):
+ 	 */
+-	unsigned long __cacheline_filler[35];
++	unsigned long		__cacheline_filler[35];
+ 	/*
+-	 * .. and then another 0x100 bytes for emergency kernel stack
++	 * .. and then another 0x100 bytes for the emergency kernel stack:
+ 	 */
+-	unsigned long stack[64];
++	unsigned long		stack[64];
++
+ } __attribute__((packed));
+ 
+ DECLARE_PER_CPU(struct tss_struct, init_tss);
+ 
+-/* Save the original ist values for checking stack pointers during debugging */
++/*
++ * Save the original ist values for checking stack pointers during debugging
++ */
+ struct orig_ist {
+-	unsigned long ist[7];
++	unsigned long		ist[7];
+ };
+ 
+ #define	MXCSR_DEFAULT		0x1f80
+ 
+ struct i387_fsave_struct {
+-	u32	cwd;
+-	u32	swd;
+-	u32	twd;
+-	u32	fip;
+-	u32	fcs;
+-	u32	foo;
+-	u32	fos;
+-	u32	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
+-	u32	status;		/* software status information */
++	u32			cwd;	/* FPU Control Word		*/
++	u32			swd;	/* FPU Status Word		*/
++	u32			twd;	/* FPU Tag Word			*/
++	u32			fip;	/* FPU IP Offset		*/
++	u32			fcs;	/* FPU IP Selector		*/
++	u32			foo;	/* FPU Operand Pointer Offset	*/
++	u32			fos;	/* FPU Operand Pointer Selector	*/
++
++	/* 8*10 bytes for each FP-reg = 80 bytes:			*/
++	u32			st_space[20];
++
++	/* Software status information [not touched by FSAVE ]:		*/
++	u32			status;
+ };
+ 
+ struct i387_fxsave_struct {
+-	u16	cwd;
+-	u16	swd;
+-	u16	twd;
+-	u16	fop;
++	u16			cwd; /* Control Word			*/
++	u16			swd; /* Status Word			*/
++	u16			twd; /* Tag Word			*/
++	u16			fop; /* Last Instruction Opcode		*/
+ 	union {
+ 		struct {
+-			u64	rip;
+-			u64	rdp;
++			u64	rip; /* Instruction Pointer		*/
++			u64	rdp; /* Data Pointer			*/
+ 		};
+ 		struct {
+-			u32	fip;
+-			u32	fcs;
+-			u32	foo;
+-			u32	fos;
++			u32	fip; /* FPU IP Offset			*/
++			u32	fcs; /* FPU IP Selector			*/
++			u32	foo; /* FPU Operand Offset		*/
++			u32	fos; /* FPU Operand Selector		*/
+ 		};
+ 	};
+-	u32	mxcsr;
+-	u32	mxcsr_mask;
+-	u32	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
+-	u32	xmm_space[64];	/* 16*16 bytes for each XMM-reg = 256 bytes */
+-	u32	padding[24];
++	u32			mxcsr;		/* MXCSR Register State */
++	u32			mxcsr_mask;	/* MXCSR Mask		*/
++
++	/* 8*16 bytes for each FP-reg = 128 bytes:			*/
++	u32			st_space[32];
++
++	/* 16*16 bytes for each XMM-reg = 256 bytes:			*/
++	u32			xmm_space[64];
++
++	u32			padding[24];
++
+ } __attribute__((aligned(16)));
+ 
+ struct i387_soft_struct {
+-	u32	cwd;
+-	u32	swd;
+-	u32	twd;
+-	u32	fip;
+-	u32	fcs;
+-	u32	foo;
+-	u32	fos;
+-	u32	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
+-	u8	ftop, changed, lookahead, no_update, rm, alimit;
+-	struct info	*info;
+-	u32	entry_eip;
++	u32			cwd;
++	u32			swd;
++	u32			twd;
++	u32			fip;
++	u32			fcs;
++	u32			foo;
++	u32			fos;
++	/* 8*10 bytes for each FP-reg = 80 bytes: */
++	u32			st_space[20];
++	u8			ftop;
++	u8			changed;
++	u8			lookahead;
++	u8			no_update;
++	u8			rm;
++	u8			alimit;
++	struct info		*info;
++	u32			entry_eip;
+ };
+ 
+-union i387_union {
++union thread_xstate {
+ 	struct i387_fsave_struct	fsave;
+ 	struct i387_fxsave_struct	fxsave;
+-	struct i387_soft_struct 	soft;
++	struct i387_soft_struct		soft;
+ };
+ 
+-#ifdef CONFIG_X86_32
+-DECLARE_PER_CPU(u8, cpu_llc_id);
+-#else
++#ifdef CONFIG_X86_64
+ DECLARE_PER_CPU(struct orig_ist, orig_ist);
+ #endif
+ 
+ extern void print_cpu_info(struct cpuinfo_x86 *);
++extern unsigned int xstate_size;
++extern void free_thread_xstate(struct task_struct *);
++extern struct kmem_cache *task_xstate_cachep;
+ extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+ extern unsigned short num_cache_leaves;
+ 
+ struct thread_struct {
+-/* cached TLS descriptors. */
+-	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
+-	unsigned long	sp0;
+-	unsigned long	sp;
++	/* Cached TLS descriptors: */
++	struct desc_struct	tls_array[GDT_ENTRY_TLS_ENTRIES];
++	unsigned long		sp0;
++	unsigned long		sp;
+ #ifdef CONFIG_X86_32
+-	unsigned long	sysenter_cs;
++	unsigned long		sysenter_cs;
+ #else
+-	unsigned long 	usersp;	/* Copy from PDA */
+-	unsigned short	es, ds, fsindex, gsindex;
++	unsigned long		usersp;	/* Copy from PDA */
++	unsigned short		es;
++	unsigned short		ds;
++	unsigned short		fsindex;
++	unsigned short		gsindex;
+ #endif
+-	unsigned long	ip;
+-	unsigned long	fs;
+-	unsigned long	gs;
+-/* Hardware debugging registers */
+-	unsigned long	debugreg0;
+-	unsigned long	debugreg1;
+-	unsigned long	debugreg2;
+-	unsigned long	debugreg3;
+-	unsigned long	debugreg6;
+-	unsigned long	debugreg7;
+-/* fault info */
+-	unsigned long	cr2, trap_no, error_code;
+-/* floating point info */
+-	union i387_union	i387 __attribute__((aligned(16)));;
++	unsigned long		ip;
++	unsigned long		fs;
++	unsigned long		gs;
++	/* Hardware debugging registers: */
++	unsigned long		debugreg0;
++	unsigned long		debugreg1;
++	unsigned long		debugreg2;
++	unsigned long		debugreg3;
++	unsigned long		debugreg6;
++	unsigned long		debugreg7;
++	/* Fault info: */
++	unsigned long		cr2;
++	unsigned long		trap_no;
++	unsigned long		error_code;
++	/* floating point and extended processor state */
++	union thread_xstate	*xstate;
+ #ifdef CONFIG_X86_32
+-/* virtual 86 mode info */
++	/* Virtual 86 mode info */
+ 	struct vm86_struct __user *vm86_info;
+ 	unsigned long		screen_bitmap;
+-	unsigned long		v86flags, v86mask, saved_sp0;
+-	unsigned int		saved_fs, saved_gs;
++	unsigned long		v86flags;
++	unsigned long		v86mask;
++	unsigned long		saved_sp0;
++	unsigned int		saved_fs;
++	unsigned int		saved_gs;
+ #endif
+-/* IO permissions */
+-	unsigned long	*io_bitmap_ptr;
+-	unsigned long	iopl;
+-/* max allowed port in the bitmap, in bytes: */
+-	unsigned io_bitmap_max;
++	/* IO permissions: */
++	unsigned long		*io_bitmap_ptr;
++	unsigned long		iopl;
++	/* Max allowed port in the bitmap, in bytes: */
++	unsigned		io_bitmap_max;
+ /* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
+ 	unsigned long	debugctlmsr;
+ /* Debug Store - if not 0 points to a DS Save Area configuration;
+@@ -358,21 +425,27 @@ struct thread_struct {
+ 
+ static inline unsigned long native_get_debugreg(int regno)
+ {
+-	unsigned long val = 0; 	/* Damn you, gcc! */
++	unsigned long val = 0;	/* Damn you, gcc! */
+ 
+ 	switch (regno) {
+ 	case 0:
+-		asm("mov %%db0, %0" :"=r" (val)); break;
++		asm("mov %%db0, %0" :"=r" (val));
++		break;
+ 	case 1:
+-		asm("mov %%db1, %0" :"=r" (val)); break;
++		asm("mov %%db1, %0" :"=r" (val));
++		break;
+ 	case 2:
+-		asm("mov %%db2, %0" :"=r" (val)); break;
++		asm("mov %%db2, %0" :"=r" (val));
++		break;
+ 	case 3:
+-		asm("mov %%db3, %0" :"=r" (val)); break;
++		asm("mov %%db3, %0" :"=r" (val));
++		break;
+ 	case 6:
+-		asm("mov %%db6, %0" :"=r" (val)); break;
++		asm("mov %%db6, %0" :"=r" (val));
++		break;
+ 	case 7:
+-		asm("mov %%db7, %0" :"=r" (val)); break;
++		asm("mov %%db7, %0" :"=r" (val));
++		break;
+ 	default:
+ 		BUG();
+ 	}
+@@ -383,22 +456,22 @@ static inline void native_set_debugreg(int regno, unsigned long value)
+ {
+ 	switch (regno) {
+ 	case 0:
+-		asm("mov %0,%%db0"	: /* no output */ :"r" (value));
++		asm("mov %0, %%db0"	::"r" (value));
+ 		break;
+ 	case 1:
+-		asm("mov %0,%%db1"	: /* no output */ :"r" (value));
++		asm("mov %0, %%db1"	::"r" (value));
+ 		break;
+ 	case 2:
+-		asm("mov %0,%%db2"	: /* no output */ :"r" (value));
++		asm("mov %0, %%db2"	::"r" (value));
+ 		break;
+ 	case 3:
+-		asm("mov %0,%%db3"	: /* no output */ :"r" (value));
++		asm("mov %0, %%db3"	::"r" (value));
+ 		break;
+ 	case 6:
+-		asm("mov %0,%%db6"	: /* no output */ :"r" (value));
++		asm("mov %0, %%db6"	::"r" (value));
+ 		break;
+ 	case 7:
+-		asm("mov %0,%%db7"	: /* no output */ :"r" (value));
++		asm("mov %0, %%db7"	::"r" (value));
+ 		break;
+ 	default:
+ 		BUG();
+@@ -412,23 +485,24 @@ static inline void native_set_iopl_mask(unsigned mask)
+ {
+ #ifdef CONFIG_X86_32
+ 	unsigned int reg;
+-	__asm__ __volatile__ ("pushfl;"
+-			      "popl %0;"
+-			      "andl %1, %0;"
+-			      "orl %2, %0;"
+-			      "pushl %0;"
+-			      "popfl"
+-				: "=&r" (reg)
+-				: "i" (~X86_EFLAGS_IOPL), "r" (mask));
++
++	asm volatile ("pushfl;"
++		      "popl %0;"
++		      "andl %1, %0;"
++		      "orl %2, %0;"
++		      "pushl %0;"
++		      "popfl"
++		      : "=&r" (reg)
++		      : "i" (~X86_EFLAGS_IOPL), "r" (mask));
+ #endif
+ }
+ 
+-static inline void native_load_sp0(struct tss_struct *tss,
+-				   struct thread_struct *thread)
++static inline void
++native_load_sp0(struct tss_struct *tss, struct thread_struct *thread)
+ {
+ 	tss->x86_tss.sp0 = thread->sp0;
+ #ifdef CONFIG_X86_32
+-	/* Only happens when SEP is enabled, no need to test "SEP"arately */
++	/* Only happens 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);
+@@ -446,8 +520,8 @@ static inline void native_swapgs(void)
+ #ifdef CONFIG_PARAVIRT
+ #include <asm/paravirt.h>
+ #else
+-#define __cpuid native_cpuid
+-#define paravirt_enabled() 0
++#define __cpuid			native_cpuid
++#define paravirt_enabled()	0
+ 
+ /*
+  * These special macros can be used to get or set a debugging register
+@@ -473,11 +547,12 @@ static inline void load_sp0(struct tss_struct *tss,
+  * enable), so that any CPU's that boot up
+  * after us can get the correct flags.
+  */
+-extern unsigned long mmu_cr4_features;
++extern unsigned long		mmu_cr4_features;
+ 
+ static inline void set_in_cr4(unsigned long mask)
+ {
+ 	unsigned cr4;
++
+ 	mmu_cr4_features |= mask;
+ 	cr4 = read_cr4();
+ 	cr4 |= mask;
+@@ -487,6 +562,7 @@ static inline void set_in_cr4(unsigned long mask)
+ static inline void clear_in_cr4(unsigned long mask)
+ {
+ 	unsigned cr4;
++
+ 	mmu_cr4_features &= ~mask;
+ 	cr4 = read_cr4();
+ 	cr4 &= ~mask;
+@@ -494,42 +570,42 @@ static inline void clear_in_cr4(unsigned long mask)
+ }
+ 
+ struct microcode_header {
+-	unsigned int hdrver;
+-	unsigned int rev;
+-	unsigned int date;
+-	unsigned int sig;
+-	unsigned int cksum;
+-	unsigned int ldrver;
+-	unsigned int pf;
+-	unsigned int datasize;
+-	unsigned int totalsize;
+-	unsigned int reserved[3];
++	unsigned int		hdrver;
++	unsigned int		rev;
++	unsigned int		date;
++	unsigned int		sig;
++	unsigned int		cksum;
++	unsigned int		ldrver;
++	unsigned int		pf;
++	unsigned int		datasize;
++	unsigned int		totalsize;
++	unsigned int		reserved[3];
+ };
+ 
+ struct microcode {
+-	struct microcode_header hdr;
+-	unsigned int bits[0];
++	struct microcode_header	hdr;
++	unsigned int		bits[0];
+ };
+ 
+-typedef struct microcode microcode_t;
+-typedef struct microcode_header microcode_header_t;
++typedef struct microcode	microcode_t;
++typedef struct microcode_header	microcode_header_t;
+ 
+ /* microcode format is extended from prescott processors */
+ struct extended_signature {
+-	unsigned int sig;
+-	unsigned int pf;
+-	unsigned int cksum;
++	unsigned int		sig;
++	unsigned int		pf;
++	unsigned int		cksum;
+ };
+ 
+ struct extended_sigtable {
+-	unsigned int count;
+-	unsigned int cksum;
+-	unsigned int reserved[3];
++	unsigned int		count;
++	unsigned int		cksum;
++	unsigned int		reserved[3];
+ 	struct extended_signature sigs[0];
+ };
+ 
+ typedef struct {
+-	unsigned long seg;
++	unsigned long		seg;
+ } mm_segment_t;
+ 
+ 
+@@ -541,7 +617,7 @@ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+ /* Free all resources held by a thread. */
+ extern void release_thread(struct task_struct *);
+ 
+-/* Prepare to copy thread state - unlazy all lazy status */
++/* Prepare to copy thread state - unlazy all lazy state */
+ extern void prepare_to_copy(struct task_struct *tsk);
+ 
+ unsigned long get_wchan(struct task_struct *p);
+@@ -578,118 +654,137 @@ static inline unsigned int cpuid_eax(unsigned int op)
+ 	unsigned int eax, ebx, ecx, edx;
+ 
+ 	cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ 	return eax;
+ }
++
+ static inline unsigned int cpuid_ebx(unsigned int op)
+ {
+ 	unsigned int eax, ebx, ecx, edx;
+ 
+ 	cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ 	return ebx;
+ }
++
+ static inline unsigned int cpuid_ecx(unsigned int op)
+ {
+ 	unsigned int eax, ebx, ecx, edx;
+ 
+ 	cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ 	return ecx;
+ }
++
+ static inline unsigned int cpuid_edx(unsigned int op)
+ {
+ 	unsigned int eax, ebx, ecx, edx;
+ 
+ 	cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ 	return edx;
+ }
+ 
+ /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+ static inline void rep_nop(void)
+ {
+-	__asm__ __volatile__("rep;nop": : :"memory");
++	asm volatile("rep; nop" ::: "memory");
++}
++
++static inline void cpu_relax(void)
++{
++	rep_nop();
+ }
+ 
+-/* Stop speculative execution */
++/* Stop speculative execution: */
+ static inline void sync_core(void)
+ {
+ 	int tmp;
++
+ 	asm volatile("cpuid" : "=a" (tmp) : "0" (1)
+-					  : "ebx", "ecx", "edx", "memory");
++		     : "ebx", "ecx", "edx", "memory");
+ }
+ 
+-#define cpu_relax()   rep_nop()
+-
+ static inline void __monitor(const void *eax, unsigned long ecx,
+-		unsigned long edx)
++			     unsigned long edx)
+ {
+-	/* "monitor %eax,%ecx,%edx;" */
+-	asm volatile(
+-		".byte 0x0f,0x01,0xc8;"
+-		: :"a" (eax), "c" (ecx), "d"(edx));
++	/* "monitor %eax, %ecx, %edx;" */
++	asm volatile(".byte 0x0f, 0x01, 0xc8;"
++		     :: "a" (eax), "c" (ecx), "d"(edx));
+ }
+ 
+ static inline void __mwait(unsigned long eax, unsigned long ecx)
+ {
+-	/* "mwait %eax,%ecx;" */
+-	asm volatile(
+-		".byte 0x0f,0x01,0xc9;"
+-		: :"a" (eax), "c" (ecx));
++	/* "mwait %eax, %ecx;" */
++	asm volatile(".byte 0x0f, 0x01, 0xc9;"
++		     :: "a" (eax), "c" (ecx));
+ }
+ 
+ static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+ {
+-	/* "mwait %eax,%ecx;" */
+-	asm volatile(
+-		"sti; .byte 0x0f,0x01,0xc9;"
+-		: :"a" (eax), "c" (ecx));
++	/* "mwait %eax, %ecx;" */
++	asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
++		     :: "a" (eax), "c" (ecx));
+ }
+ 
+ extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+ 
+-extern int force_mwait;
++extern int			force_mwait;
+ 
+ extern void select_idle_routine(const struct cpuinfo_x86 *c);
+ 
+-extern unsigned long boot_option_idle_override;
++extern unsigned long		boot_option_idle_override;
+ 
+ extern void enable_sep_cpu(void);
+ extern int sysenter_setup(void);
+ 
+ /* Defined in head.S */
+-extern struct desc_ptr early_gdt_descr;
++extern struct desc_ptr		early_gdt_descr;
+ 
+ extern void cpu_set_gdt(int);
+ extern void switch_to_new_gdt(void);
+ extern void cpu_init(void);
+ extern void init_gdt(int cpu);
+ 
+-/* from system description table in BIOS.  Mostly for MCA use, but
+- * others may find it useful. */
+-extern unsigned int machine_id;
+-extern unsigned int machine_submodel_id;
+-extern unsigned int BIOS_revision;
++static inline void update_debugctlmsr(unsigned long debugctlmsr)
++{
++#ifndef CONFIG_X86_DEBUGCTLMSR
++	if (boot_cpu_data.x86 < 6)
++		return;
++#endif
++	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
++}
++
++/*
++ * from system description table in BIOS. Mostly for MCA use, but
++ * others may find it useful:
++ */
++extern unsigned int		machine_id;
++extern unsigned int		machine_submodel_id;
++extern unsigned int		BIOS_revision;
+ 
+-/* Boot loader type from the setup header */
+-extern int bootloader_type;
++/* Boot loader type from the setup header: */
++extern int			bootloader_type;
+ 
+-extern char ignore_fpu_irq;
+-#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
++extern char			ignore_fpu_irq;
+ 
+ #define HAVE_ARCH_PICK_MMAP_LAYOUT 1
+ #define ARCH_HAS_PREFETCHW
+ #define ARCH_HAS_SPINLOCK_PREFETCH
+ 
+ #ifdef CONFIG_X86_32
+-#define BASE_PREFETCH	ASM_NOP4
+-#define ARCH_HAS_PREFETCH
++# define BASE_PREFETCH		ASM_NOP4
++# define ARCH_HAS_PREFETCH
+ #else
+-#define BASE_PREFETCH	"prefetcht0 (%1)"
++# define BASE_PREFETCH		"prefetcht0 (%1)"
+ #endif
+ 
+-/* Prefetch instructions for Pentium III and AMD Athlon */
+-/* It's not worth to care about 3dnow! prefetches for the K6
+-   because they are microcoded there and very slow.
+-   However we don't do prefetches for pre XP Athlons currently
+-   That should be fixed. */
++/*
++ * Prefetch instructions for Pentium III (+) and AMD Athlon (+)
++ *
++ * It's not worth to care about 3dnow prefetches for the K6
++ * because they are microcoded there and very slow.
++ */
+ static inline void prefetch(const void *x)
+ {
+ 	alternative_input(BASE_PREFETCH,
+@@ -698,8 +793,11 @@ static inline void prefetch(const void *x)
+ 			  "r" (x));
+ }
+ 
+-/* 3dnow! prefetch to get an exclusive cache line. Useful for
+-   spinlocks to avoid one state transition in the cache coherency protocol. */
++/*
++ * 3dnow prefetch to get an exclusive cache line.
++ * Useful for spinlocks to avoid one state transition in the
++ * cache coherency protocol:
++ */
+ static inline void prefetchw(const void *x)
+ {
+ 	alternative_input(BASE_PREFETCH,
+@@ -708,21 +806,25 @@ static inline void prefetchw(const void *x)
+ 			  "r" (x));
+ }
+ 
+-#define spin_lock_prefetch(x)	prefetchw(x)
++static inline void spin_lock_prefetch(const void *x)
++{
++	prefetchw(x);
++}
++
+ #ifdef CONFIG_X86_32
+ /*
+  * User space process size: 3GB (default).
+  */
+-#define TASK_SIZE	(PAGE_OFFSET)
+-#define STACK_TOP	TASK_SIZE
+-#define STACK_TOP_MAX	STACK_TOP
+-
+-#define INIT_THREAD  {							\
+-	.sp0 = sizeof(init_stack) + (long)&init_stack,			\
+-	.vm86_info = NULL,						\
+-	.sysenter_cs = __KERNEL_CS,					\
+-	.io_bitmap_ptr = NULL,						\
+-	.fs = __KERNEL_PERCPU,						\
++#define TASK_SIZE		PAGE_OFFSET
++#define STACK_TOP		TASK_SIZE
++#define STACK_TOP_MAX		STACK_TOP
++
++#define INIT_THREAD  {							  \
++	.sp0			= sizeof(init_stack) + (long)&init_stack, \
++	.vm86_info		= NULL,					  \
++	.sysenter_cs		= __KERNEL_CS,				  \
++	.io_bitmap_ptr		= NULL,					  \
++	.fs			= __KERNEL_PERCPU,			  \
+ }
+ 
+ /*
+@@ -731,28 +833,15 @@ static inline void prefetchw(const void *x)
+  * permission bitmap. The extra byte must be all 1 bits, and must
+  * be within the limit.
+  */
+-#define INIT_TSS  {							\
+-	.x86_tss = {							\
++#define INIT_TSS  {							  \
++	.x86_tss = {							  \
+ 		.sp0		= sizeof(init_stack) + (long)&init_stack, \
+-		.ss0		= __KERNEL_DS,				\
+-		.ss1		= __KERNEL_CS,				\
+-		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		\
+-	 },								\
+-	.io_bitmap	= { [0 ... IO_BITMAP_LONGS] = ~0 },		\
+-}
+-
+-#define start_thread(regs, new_eip, new_esp) do {		\
+-	__asm__("movl %0,%%gs": :"r" (0));			\
+-	regs->fs = 0;						\
+-	set_fs(USER_DS);					\
+-	regs->ds = __USER_DS;					\
+-	regs->es = __USER_DS;					\
+-	regs->ss = __USER_DS;					\
+-	regs->cs = __USER_CS;					\
+-	regs->ip = new_eip;					\
+-	regs->sp = new_esp;					\
+-} while (0)
+-
++		.ss0		= __KERNEL_DS,				  \
++		.ss1		= __KERNEL_CS,				  \
++		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		  \
++	 },								  \
++	.io_bitmap		= { [0 ... IO_BITMAP_LONGS] = ~0 },	  \
++}
+ 
+ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+ 
+@@ -780,24 +869,24 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+        __regs__ - 1;                                                   \
+ })
+ 
+-#define KSTK_ESP(task) (task_pt_regs(task)->sp)
++#define KSTK_ESP(task)		(task_pt_regs(task)->sp)
+ 
+ #else
+ /*
+  * User space process size. 47bits minus one guard page.
+  */
+-#define TASK_SIZE64	(0x800000000000UL - 4096)
++#define TASK_SIZE64	((1UL << 47) - PAGE_SIZE)
+ 
+ /* This decides where the kernel will search for a free chunk of vm
+  * space during mmap's.
+  */
+-#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? \
+-			   0xc0000000 : 0xFFFFe000)
++#define IA32_PAGE_OFFSET	((current->personality & ADDR_LIMIT_3GB) ? \
++					0xc0000000 : 0xFFFFe000)
+ 
+-#define TASK_SIZE 		(test_thread_flag(TIF_IA32) ? \
+-				 IA32_PAGE_OFFSET : TASK_SIZE64)
+-#define TASK_SIZE_OF(child) 	((test_tsk_thread_flag(child, TIF_IA32)) ? \
+-				  IA32_PAGE_OFFSET : TASK_SIZE64)
++#define TASK_SIZE		(test_thread_flag(TIF_IA32) ? \
++					IA32_PAGE_OFFSET : TASK_SIZE64)
++#define TASK_SIZE_OF(child)	((test_tsk_thread_flag(child, TIF_IA32)) ? \
++					IA32_PAGE_OFFSET : TASK_SIZE64)
+ 
+ #define STACK_TOP		TASK_SIZE
+ #define STACK_TOP_MAX		TASK_SIZE64
+@@ -810,33 +899,32 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+ 	.x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+ }
+ 
+-#define start_thread(regs, new_rip, new_rsp) do { 			     \
+-	asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0));  \
+-	load_gs_index(0);						     \
+-	(regs)->ip = (new_rip);						     \
+-	(regs)->sp = (new_rsp);						     \
+-	write_pda(oldrsp, (new_rsp));					     \
+-	(regs)->cs = __USER_CS;						     \
+-	(regs)->ss = __USER_DS;						     \
+-	(regs)->flags = 0x200;						     \
+-	set_fs(USER_DS);						     \
+-} while (0)
+-
+ /*
+  * Return saved PC of a blocked thread.
+  * What is this good for? it will be always the scheduler or ret_from_fork.
+  */
+-#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.sp - 8))
++#define thread_saved_pc(t)	(*(unsigned long *)((t)->thread.sp - 8))
+ 
+-#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.sp0 - 1)
+-#define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */
++#define task_pt_regs(tsk)	((struct pt_regs *)(tsk)->thread.sp0 - 1)
++#define KSTK_ESP(tsk)		-1 /* sorry. doesn't work for syscall. */
+ #endif /* CONFIG_X86_64 */
+ 
+-/* This decides where the kernel will search for a free chunk of vm
++extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
++					       unsigned long new_sp);
++
++/*
++ * This decides where the kernel will search for a free chunk of vm
+  * space during mmap's.
+  */
+ #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
+ 
+-#define KSTK_EIP(task) (task_pt_regs(task)->ip)
++#define KSTK_EIP(task)		(task_pt_regs(task)->ip)
++
++/* Get/set a process' ability to use the timestamp counter instruction */
++#define GET_TSC_CTL(adr)	get_tsc_mode((adr))
++#define SET_TSC_CTL(val)	set_tsc_mode((val))
++
++extern int get_tsc_mode(unsigned long adr);
++extern int set_tsc_mode(unsigned int val);
+ 
+ #endif
+diff --git a/include/asm-x86/proto.h b/include/asm-x86/proto.h
+index 68563c0..1e17bcc 100644
+--- a/include/asm-x86/proto.h
++++ b/include/asm-x86/proto.h
+@@ -7,8 +7,6 @@
+ 
+ extern void early_idt_handler(void);
+ 
+-extern void init_memory_mapping(unsigned long start, unsigned long end);
+-
+ extern void system_call(void);
+ extern void syscall_init(void);
+ 
+@@ -26,7 +24,7 @@ extern int reboot_force;
+ 
+ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
+ 
+-#define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
+-#define round_down(x,y) ((x) & ~((y)-1))
++#define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1))
++#define round_down(x, y) ((x) & ~((y) - 1))
+ 
+ #endif
+diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h
+index d9e04b4..9f922b0 100644
+--- a/include/asm-x86/ptrace.h
++++ b/include/asm-x86/ptrace.h
+@@ -36,23 +36,23 @@ struct pt_regs {
+ #else /* __KERNEL__ */
+ 
+ struct pt_regs {
+-	long bx;
+-	long cx;
+-	long dx;
+-	long si;
+-	long di;
+-	long bp;
+-	long ax;
+-	int  ds;
+-	int  es;
+-	int  fs;
++	unsigned long bx;
++	unsigned long cx;
++	unsigned long dx;
++	unsigned long si;
++	unsigned long di;
++	unsigned long bp;
++	unsigned long ax;
++	unsigned long ds;
++	unsigned long es;
++	unsigned long fs;
+ 	/* int  gs; */
+-	long orig_ax;
+-	long ip;
+-	int  cs;
+-	long flags;
+-	long sp;
+-	int  ss;
++	unsigned long orig_ax;
++	unsigned long ip;
++	unsigned long cs;
++	unsigned long flags;
++	unsigned long sp;
++	unsigned long ss;
+ };
+ 
+ #include <asm/vm86.h>
+@@ -140,12 +140,16 @@ extern unsigned long
+ convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs);
+ 
+ #ifdef CONFIG_X86_32
+-extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
++extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
++			 int error_code);
+ #else
+ void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
+ #endif
+ 
+-#define regs_return_value(regs) ((regs)->ax)
++static inline unsigned long regs_return_value(struct pt_regs *regs)
++{
++	return regs->ax;
++}
+ 
+ /*
+  * user_mode_vm(regs) determines whether a register set came from user mode.
+@@ -166,8 +170,8 @@ static inline int user_mode(struct pt_regs *regs)
+ static inline int user_mode_vm(struct pt_regs *regs)
+ {
+ #ifdef CONFIG_X86_32
+-	return ((regs->cs & SEGMENT_RPL_MASK) |
+-		(regs->flags & VM_MASK)) >= USER_RPL;
++	return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >=
++		USER_RPL;
+ #else
+ 	return user_mode(regs);
+ #endif
+@@ -176,7 +180,7 @@ static inline int user_mode_vm(struct pt_regs *regs)
+ static inline int v8086_mode(struct pt_regs *regs)
+ {
+ #ifdef CONFIG_X86_32
+-	return (regs->flags & VM_MASK);
++	return (regs->flags & X86_VM_MASK);
+ #else
+ 	return 0;	/* No V86 mode support in long mode */
+ #endif
+@@ -227,6 +231,8 @@ extern int do_get_thread_area(struct task_struct *p, int idx,
+ extern int do_set_thread_area(struct task_struct *p, int idx,
+ 			      struct user_desc __user *info, int can_allocate);
+ 
++#define __ARCH_WANT_COMPAT_SYS_PTRACE
++
+ #endif /* __KERNEL__ */
+ 
+ #endif /* !__ASSEMBLY__ */
+diff --git a/include/asm-x86/reboot.h b/include/asm-x86/reboot.h
+index e9e3ffc..6b5233b 100644
+--- a/include/asm-x86/reboot.h
++++ b/include/asm-x86/reboot.h
+@@ -3,8 +3,7 @@
+ 
+ struct pt_regs;
+ 
+-struct machine_ops
+-{
++struct machine_ops {
+ 	void (*restart)(char *cmd);
+ 	void (*halt)(void);
+ 	void (*power_off)(void);
+diff --git a/include/asm-x86/resume-trace.h b/include/asm-x86/resume-trace.h
+index 46f725b..2557514 100644
+--- a/include/asm-x86/resume-trace.h
++++ b/include/asm-x86/resume-trace.h
+@@ -3,16 +3,17 @@
+ 
+ #include <asm/asm.h>
+ 
+-#define TRACE_RESUME(user) do {					\
++#define TRACE_RESUME(user)					\
++do {								\
+ 	if (pm_trace_enabled) {					\
+ 		void *tracedata;				\
+ 		asm volatile(_ASM_MOV_UL " $1f,%0\n"		\
+-			".section .tracedata,\"a\"\n"		\
+-			"1:\t.word %c1\n\t"			\
+-			_ASM_PTR " %c2\n"			\
+-			".previous"				\
+-			:"=r" (tracedata)			\
+-			: "i" (__LINE__), "i" (__FILE__));	\
++			     ".section .tracedata,\"a\"\n"	\
++			     "1:\t.word %c1\n\t"		\
++			     _ASM_PTR " %c2\n"			\
++			     ".previous"			\
++			     :"=r" (tracedata)			\
++			     : "i" (__LINE__), "i" (__FILE__));	\
+ 		generate_resume_trace(tracedata, user);		\
+ 	}							\
+ } while (0)
+diff --git a/include/asm-x86/rio.h b/include/asm-x86/rio.h
+index 97cdcc9..c9448bd 100644
+--- a/include/asm-x86/rio.h
++++ b/include/asm-x86/rio.h
+@@ -11,64 +11,53 @@
+ #define RIO_TABLE_VERSION	3
+ 
+ struct rio_table_hdr {
+-	u8 version;      /* Version number of this data structure  */
+-	u8 num_scal_dev; /* # of Scalability devices               */
+-	u8 num_rio_dev;  /* # of RIO I/O devices                   */
++	u8 version;		/* Version number of this data structure  */
++	u8 num_scal_dev;	/* # of Scalability devices               */
++	u8 num_rio_dev;		/* # of RIO I/O devices                   */
+ } __attribute__((packed));
+ 
+ struct scal_detail {
+-	u8 node_id;      /* Scalability Node ID                    */
+-	u32 CBAR;        /* Address of 1MB register space          */
+-	u8 port0node;    /* Node ID port connected to: 0xFF=None   */
+-	u8 port0port;    /* Port num port connected to: 0,1,2, or  */
+-	                 /* 0xFF=None                              */
+-	u8 port1node;    /* Node ID port connected to: 0xFF = None */
+-	u8 port1port;    /* Port num port connected to: 0,1,2, or  */
+-	                 /* 0xFF=None                              */
+-	u8 port2node;    /* Node ID port connected to: 0xFF = None */
+-	u8 port2port;    /* Port num port connected to: 0,1,2, or  */
+-	                 /* 0xFF=None                              */
+-	u8 chassis_num;  /* 1 based Chassis number (1 = boot node) */
++	u8 node_id;		/* Scalability Node ID                    */
++	u32 CBAR;		/* Address of 1MB register space          */
++	u8 port0node;		/* Node ID port connected to: 0xFF=None   */
++	u8 port0port;		/* Port num port connected to: 0,1,2, or  */
++				/* 0xFF=None                              */
++	u8 port1node;		/* Node ID port connected to: 0xFF = None */
++	u8 port1port;		/* Port num port connected to: 0,1,2, or  */
++				/* 0xFF=None                              */
++	u8 port2node;		/* Node ID port connected to: 0xFF = None */
++	u8 port2port;		/* Port num port connected to: 0,1,2, or  */
++				/* 0xFF=None                              */
++	u8 chassis_num;		/* 1 based Chassis number (1 = boot node) */
+ } __attribute__((packed));
+ 
+ struct rio_detail {
+-	u8 node_id;      /* RIO Node ID                            */
+-	u32 BBAR;        /* Address of 1MB register space          */
+-	u8 type;         /* Type of device                         */
+-	u8 owner_id;     /* Node ID of Hurricane that owns this    */
+-	                 /* node                                   */
+-	u8 port0node;    /* Node ID port connected to: 0xFF=None   */
+-	u8 port0port;    /* Port num port connected to: 0,1,2, or  */
+-	                 /* 0xFF=None                              */
+-	u8 port1node;    /* Node ID port connected to: 0xFF=None   */
+-	u8 port1port;    /* Port num port connected to: 0,1,2, or  */
+-	                 /* 0xFF=None                              */
+-	u8 first_slot;   /* Lowest slot number below this Calgary  */
+-	u8 status;       /* Bit 0 = 1 : the XAPIC is used          */
+-	                 /*       = 0 : the XAPIC is not used, ie: */
+-	                 /*            ints fwded to another XAPIC */
+-	                 /*           Bits1:7 Reserved             */
+-	u8 WP_index;     /* instance index - lower ones have       */
+-	                 /*     lower slot numbers/PCI bus numbers */
+-	u8 chassis_num;  /* 1 based Chassis number                 */
++	u8 node_id;		/* RIO Node ID                            */
++	u32 BBAR;		/* Address of 1MB register space          */
++	u8 type;		/* Type of device                         */
++	u8 owner_id;		/* Node ID of Hurricane that owns this    */
++				/* node                                   */
++	u8 port0node;		/* Node ID port connected to: 0xFF=None   */
++	u8 port0port;		/* Port num port connected to: 0,1,2, or  */
++				/* 0xFF=None                              */
++	u8 port1node;		/* Node ID port connected to: 0xFF=None   */
++	u8 port1port;		/* Port num port connected to: 0,1,2, or  */
++				/* 0xFF=None                              */
++	u8 first_slot;		/* Lowest slot number below this Calgary  */
++	u8 status;		/* Bit 0 = 1 : the XAPIC is used          */
++				/*       = 0 : the XAPIC is not used, ie: */
++				/*            ints fwded to another XAPIC */
++				/*           Bits1:7 Reserved             */
++	u8 WP_index;		/* instance index - lower ones have       */
++				/*     lower slot numbers/PCI bus numbers */
++	u8 chassis_num;		/* 1 based Chassis number                 */
+ } __attribute__((packed));
+ 
+ enum {
+-	HURR_SCALABILTY	= 0,  /* Hurricane Scalability info */
+-	HURR_RIOIB	= 2,  /* Hurricane RIOIB info       */
+-	COMPAT_CALGARY	= 4,  /* Compatibility Calgary      */
+-	ALT_CALGARY	= 5,  /* Second Planar Calgary      */
++	HURR_SCALABILTY	= 0,	/* Hurricane Scalability info */
++	HURR_RIOIB	= 2,	/* Hurricane RIOIB info       */
++	COMPAT_CALGARY	= 4,	/* Compatibility Calgary      */
++	ALT_CALGARY	= 5,	/* Second Planar Calgary      */
+ };
+ 
+-/*
+- * there is a real-mode segmented pointer pointing to the
+- * 4K EBDA area at 0x40E.
+- */
+-static inline unsigned long get_bios_ebda(void)
+-{
+-	unsigned long address = *(unsigned short *)phys_to_virt(0x40EUL);
+-	address <<= 4;
+-	return address;
+-}
+-
+ #endif /* __ASM_RIO_H */
+diff --git a/include/asm-x86/rwsem.h b/include/asm-x86/rwsem.h
+index 520a379..750f2a3 100644
+--- a/include/asm-x86/rwsem.h
++++ b/include/asm-x86/rwsem.h
+@@ -56,14 +56,16 @@ extern asmregparm struct rw_semaphore *
+ /*
+  * the semaphore definition
+  */
+-struct rw_semaphore {
+-	signed long		count;
++
+ #define RWSEM_UNLOCKED_VALUE		0x00000000
+ #define RWSEM_ACTIVE_BIAS		0x00000001
+ #define RWSEM_ACTIVE_MASK		0x0000ffff
+ #define RWSEM_WAITING_BIAS		(-0x00010000)
+ #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
+ #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
++
++struct rw_semaphore {
++	signed long		count;
+ 	spinlock_t		wait_lock;
+ 	struct list_head	wait_list;
+ #ifdef CONFIG_DEBUG_LOCK_ALLOC
+@@ -78,11 +80,13 @@ struct rw_semaphore {
+ #endif
+ 
+ 
+-#define __RWSEM_INITIALIZER(name) \
+-{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
+-  LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
++#define __RWSEM_INITIALIZER(name)				\
++{								\
++	RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
++	LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) \
++}
+ 
+-#define DECLARE_RWSEM(name) \
++#define DECLARE_RWSEM(name)					\
+ 	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+ 
+ extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+@@ -100,16 +104,16 @@ do {								\
+  */
+ static inline void __down_read(struct rw_semaphore *sem)
+ {
+-	__asm__ __volatile__(
+-		"# beginning down_read\n\t"
+-LOCK_PREFIX	"  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
+-		"  jns        1f\n"
+-		"  call call_rwsem_down_read_failed\n"
+-		"1:\n\t"
+-		"# ending down_read\n\t"
+-		: "+m" (sem->count)
+-		: "a" (sem)
+-		: "memory", "cc");
++	asm volatile("# beginning down_read\n\t"
++		     LOCK_PREFIX "  incl      (%%eax)\n\t"
++		     /* adds 0x00000001, returns the old value */
++		     "  jns        1f\n"
++		     "  call call_rwsem_down_read_failed\n"
++		     "1:\n\t"
++		     "# ending down_read\n\t"
++		     : "+m" (sem->count)
++		     : "a" (sem)
++		     : "memory", "cc");
+ }
+ 
+ /*
+@@ -118,21 +122,20 @@ LOCK_PREFIX	"  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value
+ static inline int __down_read_trylock(struct rw_semaphore *sem)
+ {
+ 	__s32 result, tmp;
+-	__asm__ __volatile__(
+-		"# beginning __down_read_trylock\n\t"
+-		"  movl      %0,%1\n\t"
+-		"1:\n\t"
+-		"  movl	     %1,%2\n\t"
+-		"  addl      %3,%2\n\t"
+-		"  jle	     2f\n\t"
+-LOCK_PREFIX	"  cmpxchgl  %2,%0\n\t"
+-		"  jnz	     1b\n\t"
+-		"2:\n\t"
+-		"# ending __down_read_trylock\n\t"
+-		: "+m" (sem->count), "=&a" (result), "=&r" (tmp)
+-		: "i" (RWSEM_ACTIVE_READ_BIAS)
+-		: "memory", "cc");
+-	return result>=0 ? 1 : 0;
++	asm volatile("# beginning __down_read_trylock\n\t"
++		     "  movl      %0,%1\n\t"
++		     "1:\n\t"
++		     "  movl	     %1,%2\n\t"
++		     "  addl      %3,%2\n\t"
++		     "  jle	     2f\n\t"
++		     LOCK_PREFIX "  cmpxchgl  %2,%0\n\t"
++		     "  jnz	     1b\n\t"
++		     "2:\n\t"
++		     "# ending __down_read_trylock\n\t"
++		     : "+m" (sem->count), "=&a" (result), "=&r" (tmp)
++		     : "i" (RWSEM_ACTIVE_READ_BIAS)
++		     : "memory", "cc");
++	return result >= 0 ? 1 : 0;
+ }
+ 
+ /*
+@@ -143,17 +146,18 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+ 	int tmp;
+ 
+ 	tmp = RWSEM_ACTIVE_WRITE_BIAS;
+-	__asm__ __volatile__(
+-		"# beginning down_write\n\t"
+-LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
+-		"  testl     %%edx,%%edx\n\t" /* was the count 0 before? */
+-		"  jz        1f\n"
+-		"  call call_rwsem_down_write_failed\n"
+-		"1:\n"
+-		"# ending down_write"
+-		: "+m" (sem->count), "=d" (tmp)
+-		: "a" (sem), "1" (tmp)
+-		: "memory", "cc");
++	asm volatile("# beginning down_write\n\t"
++		     LOCK_PREFIX "  xadd      %%edx,(%%eax)\n\t"
++		     /* subtract 0x0000ffff, returns the old value */
++		     "  testl     %%edx,%%edx\n\t"
++		     /* was the count 0 before? */
++		     "  jz        1f\n"
++		     "  call call_rwsem_down_write_failed\n"
++		     "1:\n"
++		     "# ending down_write"
++		     : "+m" (sem->count), "=d" (tmp)
++		     : "a" (sem), "1" (tmp)
++		     : "memory", "cc");
+ }
+ 
+ static inline void __down_write(struct rw_semaphore *sem)
+@@ -167,7 +171,7 @@ static inline void __down_write(struct rw_semaphore *sem)
+ static inline int __down_write_trylock(struct rw_semaphore *sem)
+ {
+ 	signed long ret = cmpxchg(&sem->count,
+-				  RWSEM_UNLOCKED_VALUE, 
++				  RWSEM_UNLOCKED_VALUE,
+ 				  RWSEM_ACTIVE_WRITE_BIAS);
+ 	if (ret == RWSEM_UNLOCKED_VALUE)
+ 		return 1;
+@@ -180,16 +184,16 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)
+ static inline void __up_read(struct rw_semaphore *sem)
+ {
+ 	__s32 tmp = -RWSEM_ACTIVE_READ_BIAS;
+-	__asm__ __volatile__(
+-		"# beginning __up_read\n\t"
+-LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
+-		"  jns        1f\n\t"
+-		"  call call_rwsem_wake\n"
+-		"1:\n"
+-		"# ending __up_read\n"
+-		: "+m" (sem->count), "=d" (tmp)
+-		: "a" (sem), "1" (tmp)
+-		: "memory", "cc");
++	asm volatile("# beginning __up_read\n\t"
++		     LOCK_PREFIX "  xadd      %%edx,(%%eax)\n\t"
++		     /* subtracts 1, returns the old value */
++		     "  jns        1f\n\t"
++		     "  call call_rwsem_wake\n"
++		     "1:\n"
++		     "# ending __up_read\n"
++		     : "+m" (sem->count), "=d" (tmp)
++		     : "a" (sem), "1" (tmp)
++		     : "memory", "cc");
+ }
+ 
+ /*
+@@ -197,17 +201,18 @@ LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old valu
+  */
+ static inline void __up_write(struct rw_semaphore *sem)
+ {
+-	__asm__ __volatile__(
+-		"# beginning __up_write\n\t"
+-		"  movl      %2,%%edx\n\t"
+-LOCK_PREFIX	"  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
+-		"  jz       1f\n"
+-		"  call call_rwsem_wake\n"
+-		"1:\n\t"
+-		"# ending __up_write\n"
+-		: "+m" (sem->count)
+-		: "a" (sem), "i" (-RWSEM_ACTIVE_WRITE_BIAS)
+-		: "memory", "cc", "edx");
++	asm volatile("# beginning __up_write\n\t"
++		     "  movl      %2,%%edx\n\t"
++		     LOCK_PREFIX "  xaddl     %%edx,(%%eax)\n\t"
++		     /* tries to transition
++			0xffff0001 -> 0x00000000 */
++		     "  jz       1f\n"
++		     "  call call_rwsem_wake\n"
++		     "1:\n\t"
++		     "# ending __up_write\n"
++		     : "+m" (sem->count)
++		     : "a" (sem), "i" (-RWSEM_ACTIVE_WRITE_BIAS)
++		     : "memory", "cc", "edx");
+ }
+ 
+ /*
+@@ -215,16 +220,16 @@ LOCK_PREFIX	"  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 ->
+  */
+ static inline void __downgrade_write(struct rw_semaphore *sem)
+ {
+-	__asm__ __volatile__(
+-		"# beginning __downgrade_write\n\t"
+-LOCK_PREFIX	"  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
+-		"  jns       1f\n\t"
+-		"  call call_rwsem_downgrade_wake\n"
+-		"1:\n\t"
+-		"# ending __downgrade_write\n"
+-		: "+m" (sem->count)
+-		: "a" (sem), "i" (-RWSEM_WAITING_BIAS)
+-		: "memory", "cc");
++	asm volatile("# beginning __downgrade_write\n\t"
++		     LOCK_PREFIX "  addl      %2,(%%eax)\n\t"
++		     /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
++		     "  jns       1f\n\t"
++		     "  call call_rwsem_downgrade_wake\n"
++		     "1:\n\t"
++		     "# ending __downgrade_write\n"
++		     : "+m" (sem->count)
++		     : "a" (sem), "i" (-RWSEM_WAITING_BIAS)
++		     : "memory", "cc");
+ }
+ 
+ /*
+@@ -232,10 +237,9 @@ LOCK_PREFIX	"  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001
+  */
+ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+ {
+-	__asm__ __volatile__(
+-LOCK_PREFIX	"addl %1,%0"
+-		: "+m" (sem->count)
+-		: "ir" (delta));
++	asm volatile(LOCK_PREFIX "addl %1,%0"
++		     : "+m" (sem->count)
++		     : "ir" (delta));
+ }
+ 
+ /*
+@@ -245,12 +249,11 @@ static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+ {
+ 	int tmp = delta;
+ 
+-	__asm__ __volatile__(
+-LOCK_PREFIX	"xadd %0,%1"
+-		: "+r" (tmp), "+m" (sem->count)
+-		: : "memory");
++	asm volatile(LOCK_PREFIX "xadd %0,%1"
++		     : "+r" (tmp), "+m" (sem->count)
++		     : : "memory");
+ 
+-	return tmp+delta;
++	return tmp + delta;
+ }
+ 
+ static inline int rwsem_is_locked(struct rw_semaphore *sem)
+diff --git a/include/asm-x86/scatterlist.h b/include/asm-x86/scatterlist.h
+index d13c197..c043206 100644
+--- a/include/asm-x86/scatterlist.h
++++ b/include/asm-x86/scatterlist.h
+@@ -11,9 +11,7 @@ struct scatterlist {
+ 	unsigned int	offset;
+ 	unsigned int	length;
+ 	dma_addr_t	dma_address;
+-#ifdef CONFIG_X86_64
+ 	unsigned int	dma_length;
+-#endif
+ };
+ 
+ #define ARCH_HAS_SG_CHAIN
+diff --git a/include/asm-x86/segment.h b/include/asm-x86/segment.h
+index 23f0535..ed5131d 100644
+--- a/include/asm-x86/segment.h
++++ b/include/asm-x86/segment.h
+@@ -191,13 +191,14 @@
+ #define SEGMENT_TI_MASK		0x4
+ 
+ #define IDT_ENTRIES 256
++#define NUM_EXCEPTION_VECTORS 32
+ #define GDT_SIZE (GDT_ENTRIES * 8)
+ #define GDT_ENTRY_TLS_ENTRIES 3
+ #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
+ 
+ #ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+-extern const char early_idt_handlers[IDT_ENTRIES][10];
++extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][10];
+ #endif
+ #endif
+ 
+diff --git a/include/asm-x86/semaphore.h b/include/asm-x86/semaphore.h
+index 572c0b6..d9b2034 100644
+--- a/include/asm-x86/semaphore.h
++++ b/include/asm-x86/semaphore.h
+@@ -1,5 +1 @@
+-#ifdef CONFIG_X86_32
+-# include "semaphore_32.h"
+-#else
+-# include "semaphore_64.h"
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-x86/semaphore_32.h b/include/asm-x86/semaphore_32.h
+deleted file mode 100644
+index ac96d38..0000000
+--- a/include/asm-x86/semaphore_32.h
++++ /dev/null
+@@ -1,175 +0,0 @@
+-#ifndef _I386_SEMAPHORE_H
+-#define _I386_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#ifdef __KERNEL__
+-
+-/*
+- * SMP- and interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * Modified 1996-12-23 by Dave Grothe <dave at gcom.com> to fix bugs in
+- *                     the original code and to make semaphore waits
+- *                     interruptible so that processes waiting on
+- *                     semaphores can be killed.
+- * Modified 1999-02-14 by Andrea Arcangeli, split the sched.c helper
+- *		       functions in asm/sempahore-helper.h while fixing a
+- *		       potential and subtle race discovered by Ulrich Schmid
+- *		       in down_interruptible(). Since I started to play here I
+- *		       also implemented the `trylock' semaphore operation.
+- *          1999-07-02 Artur Skawina <skawina at geocities.com>
+- *                     Optimized "0(ecx)" -> "(ecx)" (the assembler does not
+- *                     do this). Changed calling sequences from push/jmp to
+- *                     traditional call/ret.
+- * Modified 2001-01-01 Andreas Franck <afranck at gmx.de>
+- *		       Some hacks to ensure compatibility with recent
+- *		       GCC snapshots, to avoid stack corruption when compiling
+- *		       with -fomit-frame-pointer. It's not sure if this will
+- *		       be fixed in GCC, as our previous implementation was a
+- *		       bit dubious.
+- *
+- * If you would like to see an analysis of this implementation, please
+- * ftp to gcom.com and download the file
+- * /pub/linux/src/semaphore/semaphore-2.0.24.tar.gz.
+- *
+- */
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.sleepers	= 0,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-/*
+- *	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+- *
+- * i'd rather use the more flexible initialization above, but sadly
+- * GCC 2.7.2.3 emits a bogus warning. EGCS doesn't. Oh well.
+- */
+-	atomic_set(&sem->count, val);
+-	sem->sleepers = 0;
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-extern asmregparm void __down_failed(atomic_t *count_ptr);
+-extern asmregparm int  __down_failed_interruptible(atomic_t *count_ptr);
+-extern asmregparm int  __down_failed_trylock(atomic_t *count_ptr);
+-extern asmregparm void __up_wakeup(atomic_t *count_ptr);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/i386/kernel/semaphore.c
+- */
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-	__asm__ __volatile__(
+-		"# atomic down operation\n\t"
+-		LOCK_PREFIX "decl %0\n\t"     /* --sem->count */
+-		"jns 2f\n"
+-		"\tlea %0,%%eax\n\t"
+-		"call __down_failed\n"
+-		"2:"
+-		:"+m" (sem->count)
+-		:
+-		:"memory","ax");
+-}
+-
+-/*
+- * Interruptible try to acquire a semaphore.  If we obtained
+- * it, return zero.  If we were interrupted, returns -EINTR
+- */
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int result;
+-
+-	might_sleep();
+-	__asm__ __volatile__(
+-		"# atomic interruptible down operation\n\t"
+-		"xorl %0,%0\n\t"
+-		LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
+-		"jns 2f\n\t"
+-		"lea %1,%%eax\n\t"
+-		"call __down_failed_interruptible\n"
+-		"2:"
+-		:"=&a" (result), "+m" (sem->count)
+-		:
+-		:"memory");
+-	return result;
+-}
+-
+-/*
+- * Non-blockingly attempt to down() a semaphore.
+- * Returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	int result;
+-
+-	__asm__ __volatile__(
+-		"# atomic interruptible down operation\n\t"
+-		"xorl %0,%0\n\t"
+-		LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
+-		"jns 2f\n\t"
+-		"lea %1,%%eax\n\t"
+-		"call __down_failed_trylock\n\t"
+-		"2:\n"
+-		:"=&a" (result), "+m" (sem->count)
+-		:
+-		:"memory");
+-	return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	__asm__ __volatile__(
+-		"# atomic up operation\n\t"
+-		LOCK_PREFIX "incl %0\n\t"     /* ++sem->count */
+-		"jg 1f\n\t"
+-		"lea %0,%%eax\n\t"
+-		"call __up_wakeup\n"
+-		"1:"
+-		:"+m" (sem->count)
+-		:
+-		:"memory","ax");
+-}
+-
+-#endif
+-#endif
+diff --git a/include/asm-x86/semaphore_64.h b/include/asm-x86/semaphore_64.h
+deleted file mode 100644
+index 7969430..0000000
+--- a/include/asm-x86/semaphore_64.h
++++ /dev/null
+@@ -1,180 +0,0 @@
+-#ifndef _X86_64_SEMAPHORE_H
+-#define _X86_64_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#ifdef __KERNEL__
+-
+-/*
+- * SMP- and interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * Modified 1996-12-23 by Dave Grothe <dave at gcom.com> to fix bugs in
+- *                     the original code and to make semaphore waits
+- *                     interruptible so that processes waiting on
+- *                     semaphores can be killed.
+- * Modified 1999-02-14 by Andrea Arcangeli, split the sched.c helper
+- *		       functions in asm/sempahore-helper.h while fixing a
+- *		       potential and subtle race discovered by Ulrich Schmid
+- *		       in down_interruptible(). Since I started to play here I
+- *		       also implemented the `trylock' semaphore operation.
+- *          1999-07-02 Artur Skawina <skawina at geocities.com>
+- *                     Optimized "0(ecx)" -> "(ecx)" (the assembler does not
+- *                     do this). Changed calling sequences from push/jmp to
+- *                     traditional call/ret.
+- * Modified 2001-01-01 Andreas Franck <afranck at gmx.de>
+- *		       Some hacks to ensure compatibility with recent
+- *		       GCC snapshots, to avoid stack corruption when compiling
+- *		       with -fomit-frame-pointer. It's not sure if this will
+- *		       be fixed in GCC, as our previous implementation was a
+- *		       bit dubious.
+- *
+- * If you would like to see an analysis of this implementation, please
+- * ftp to gcom.com and download the file
+- * /pub/linux/src/semaphore/semaphore-2.0.24.tar.gz.
+- *
+- */
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <asm/rwlock.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-#include <linux/stringify.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n)				\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.sleepers	= 0,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-/*
+- *	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+- *
+- * i'd rather use the more flexible initialization above, but sadly
+- * GCC 2.7.2.3 emits a bogus warning. EGCS doesn't. Oh well.
+- */
+-	atomic_set(&sem->count, val);
+-	sem->sleepers = 0;
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+-asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int  __down_interruptible(struct semaphore * sem);
+-asmlinkage int  __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/x86_64/kernel/semaphore.c
+- */
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-
+-	__asm__ __volatile__(
+-		"# atomic down operation\n\t"
+-		LOCK_PREFIX "decl %0\n\t"     /* --sem->count */
+-		"jns 1f\n\t"
+-		"call __down_failed\n"
+-		"1:"
+-		:"=m" (sem->count)
+-		:"D" (sem)
+-		:"memory");
+-}
+-
+-/*
+- * Interruptible try to acquire a semaphore.  If we obtained
+- * it, return zero.  If we were interrupted, returns -EINTR
+- */
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int result;
+-
+-	might_sleep();
+-
+-	__asm__ __volatile__(
+-		"# atomic interruptible down operation\n\t"
+-		"xorl %0,%0\n\t"
+-		LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
+-		"jns 2f\n\t"
+-		"call __down_failed_interruptible\n"
+-		"2:\n"
+-		:"=&a" (result), "=m" (sem->count)
+-		:"D" (sem)
+-		:"memory");
+-	return result;
+-}
+-
+-/*
+- * Non-blockingly attempt to down() a semaphore.
+- * Returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	int result;
+-
+-	__asm__ __volatile__(
+-		"# atomic interruptible down operation\n\t"
+-		"xorl %0,%0\n\t"
+-		LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
+-		"jns 2f\n\t"
+-		"call __down_failed_trylock\n\t"
+-		"2:\n"
+-		:"=&a" (result), "=m" (sem->count)
+-		:"D" (sem)
+-		:"memory","cc");
+-	return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	__asm__ __volatile__(
+-		"# atomic up operation\n\t"
+-		LOCK_PREFIX "incl %0\n\t"     /* ++sem->count */
+-		"jg 1f\n\t"
+-		"call __up_wakeup\n"
+-		"1:"
+-		:"=m" (sem->count)
+-		:"D" (sem)
+-		:"memory");
+-}
+-#endif /* __KERNEL__ */
+-#endif
+diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h
+index 071e054..fa6763a 100644
+--- a/include/asm-x86/setup.h
++++ b/include/asm-x86/setup.h
+@@ -4,6 +4,10 @@
+ #define COMMAND_LINE_SIZE 2048
+ 
+ #ifndef __ASSEMBLY__
++
++/* Interrupt control for vSMPowered x86_64 systems */
++void vsmp_init(void);
++
+ char *machine_specific_memory_setup(void);
+ #ifndef CONFIG_PARAVIRT
+ #define paravirt_post_allocator_init()	do {} while (0)
+@@ -51,8 +55,8 @@ struct e820entry;
+ char * __init machine_specific_memory_setup(void);
+ char *memory_setup(void);
+ 
+-int __init copy_e820_map(struct e820entry * biosmap, int nr_map);
+-int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map);
++int __init copy_e820_map(struct e820entry *biosmap, int nr_map);
++int __init sanitize_e820_map(struct e820entry *biosmap, char *pnr_map);
+ void __init add_memory_region(unsigned long long start,
+ 			      unsigned long long size, int type);
+ 
+diff --git a/include/asm-x86/sigcontext.h b/include/asm-x86/sigcontext.h
+index d743947..2f9c884 100644
+--- a/include/asm-x86/sigcontext.h
++++ b/include/asm-x86/sigcontext.h
+@@ -79,7 +79,7 @@ struct sigcontext {
+ 	unsigned long flags;
+ 	unsigned long sp_at_signal;
+ 	unsigned short ss, __ssh;
+-	struct _fpstate __user * fpstate;
++	struct _fpstate __user *fpstate;
+ 	unsigned long oldmask;
+ 	unsigned long cr2;
+ };
+@@ -107,7 +107,7 @@ struct sigcontext {
+ 	unsigned long eflags;
+ 	unsigned long esp_at_signal;
+ 	unsigned short ss, __ssh;
+-	struct _fpstate __user * fpstate;
++	struct _fpstate __user *fpstate;
+ 	unsigned long oldmask;
+ 	unsigned long cr2;
+ };
+@@ -121,7 +121,8 @@ struct sigcontext {
+ struct _fpstate {
+ 	__u16	cwd;
+ 	__u16	swd;
+-	__u16	twd;	/* Note this is not the same as the 32bit/x87/FSAVE twd */
++	__u16	twd;		/* Note this is not the same as the
++				   32bit/x87/FSAVE twd */
+ 	__u16	fop;
+ 	__u64	rip;
+ 	__u64	rdp;
+diff --git a/include/asm-x86/sigcontext32.h b/include/asm-x86/sigcontext32.h
+index 6ffab4f..57a9686 100644
+--- a/include/asm-x86/sigcontext32.h
++++ b/include/asm-x86/sigcontext32.h
+@@ -26,7 +26,7 @@ struct _fpstate_ia32 {
+ 	__u32 	cw;
+ 	__u32	sw;
+ 	__u32	tag;	/* not compatible to 64bit twd */
+-	__u32	ipoff;			
++	__u32	ipoff;
+ 	__u32	cssel;
+ 	__u32	dataoff;
+ 	__u32	datasel;
+@@ -39,7 +39,7 @@ struct _fpstate_ia32 {
+ 	__u32	mxcsr;
+ 	__u32	reserved;
+ 	struct _fpxreg	_fxsr_st[8];
+-	struct _xmmreg	_xmm[8];	/* It's actually 16 */ 
++	struct _xmmreg	_xmm[8];	/* It's actually 16 */
+ 	__u32	padding[56];
+ };
+ 
+diff --git a/include/asm-x86/signal.h b/include/asm-x86/signal.h
+index aee7eca..f15186d 100644
+--- a/include/asm-x86/signal.h
++++ b/include/asm-x86/signal.h
+@@ -185,61 +185,61 @@ typedef struct sigaltstack {
+ 
+ #define __HAVE_ARCH_SIG_BITOPS
+ 
+-#define sigaddset(set,sig)		   \
+-	(__builtin_constantp(sig) ?	   \
+-	 __const_sigaddset((set),(sig)) :  \
+-	 __gen_sigaddset((set),(sig)))
++#define sigaddset(set,sig)		    \
++	(__builtin_constantp(sig)	    \
++	 ? __const_sigaddset((set), (sig))  \
++	 : __gen_sigaddset((set), (sig)))
+ 
+-static __inline__ void __gen_sigaddset(sigset_t *set, int _sig)
++static inline void __gen_sigaddset(sigset_t *set, int _sig)
+ {
+-	__asm__("btsl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
++	asm("btsl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
+ }
+ 
+-static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
++static inline void __const_sigaddset(sigset_t *set, int _sig)
+ {
+ 	unsigned long sig = _sig - 1;
+ 	set->sig[sig / _NSIG_BPW] |= 1 << (sig % _NSIG_BPW);
+ }
+ 
+-#define sigdelset(set,sig)		   \
+-	(__builtin_constant_p(sig) ?       \
+-	 __const_sigdelset((set),(sig)) :  \
+-	 __gen_sigdelset((set),(sig)))
++#define sigdelset(set, sig)		    \
++	(__builtin_constant_p(sig)	    \
++	 ? __const_sigdelset((set), (sig))  \
++	 : __gen_sigdelset((set), (sig)))
+ 
+ 
+-static __inline__ void __gen_sigdelset(sigset_t *set, int _sig)
++static inline void __gen_sigdelset(sigset_t *set, int _sig)
+ {
+-	__asm__("btrl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
++	asm("btrl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
+ }
+ 
+-static __inline__ void __const_sigdelset(sigset_t *set, int _sig)
++static inline void __const_sigdelset(sigset_t *set, int _sig)
+ {
+ 	unsigned long sig = _sig - 1;
+ 	set->sig[sig / _NSIG_BPW] &= ~(1 << (sig % _NSIG_BPW));
+ }
+ 
+-static __inline__ int __const_sigismember(sigset_t *set, int _sig)
++static inline int __const_sigismember(sigset_t *set, int _sig)
+ {
+ 	unsigned long sig = _sig - 1;
+ 	return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW));
+ }
+ 
+-static __inline__ int __gen_sigismember(sigset_t *set, int _sig)
++static inline int __gen_sigismember(sigset_t *set, int _sig)
+ {
+ 	int ret;
+-	__asm__("btl %2,%1\n\tsbbl %0,%0"
+-		: "=r"(ret) : "m"(*set), "Ir"(_sig-1) : "cc");
++	asm("btl %2,%1\n\tsbbl %0,%0"
++	    : "=r"(ret) : "m"(*set), "Ir"(_sig-1) : "cc");
+ 	return ret;
+ }
+ 
+-#define sigismember(set,sig)			\
+-	(__builtin_constant_p(sig) ?		\
+-	 __const_sigismember((set),(sig)) :	\
+-	 __gen_sigismember((set),(sig)))
++#define sigismember(set, sig)			\
++	(__builtin_constant_p(sig)		\
++	 ? __const_sigismember((set), (sig))	\
++	 : __gen_sigismember((set), (sig)))
+ 
+-static __inline__ int sigfindinword(unsigned long word)
++static inline int sigfindinword(unsigned long word)
+ {
+-	__asm__("bsfl %1,%0" : "=r"(word) : "rm"(word) : "cc");
++	asm("bsfl %1,%0" : "=r"(word) : "rm"(word) : "cc");
+ 	return word;
+ }
+ 
+diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h
+index f2e8319..1ebaa5c 100644
+--- a/include/asm-x86/smp.h
++++ b/include/asm-x86/smp.h
+@@ -1,5 +1,208 @@
+-#ifdef CONFIG_X86_32
+-# include "smp_32.h"
++#ifndef _ASM_X86_SMP_H_
++#define _ASM_X86_SMP_H_
++#ifndef __ASSEMBLY__
++#include <linux/cpumask.h>
++#include <linux/init.h>
++#include <asm/percpu.h>
++
++/*
++ * We need the APIC definitions automatically as part of 'smp.h'
++ */
++#ifdef CONFIG_X86_LOCAL_APIC
++# include <asm/mpspec.h>
++# include <asm/apic.h>
++# ifdef CONFIG_X86_IO_APIC
++#  include <asm/io_apic.h>
++# endif
++#endif
++#include <asm/pda.h>
++#include <asm/thread_info.h>
++
++extern cpumask_t cpu_callout_map;
++extern cpumask_t cpu_initialized;
++extern cpumask_t cpu_callin_map;
++
++extern void (*mtrr_hook)(void);
++extern void zap_low_mappings(void);
++
++extern int smp_num_siblings;
++extern unsigned int num_processors;
++extern cpumask_t cpu_initialized;
++
++#ifdef CONFIG_SMP
++extern u16 x86_cpu_to_apicid_init[];
++extern u16 x86_bios_cpu_apicid_init[];
++extern void *x86_cpu_to_apicid_early_ptr;
++extern void *x86_bios_cpu_apicid_early_ptr;
+ #else
+-# include "smp_64.h"
++#define x86_cpu_to_apicid_early_ptr NULL
++#define x86_bios_cpu_apicid_early_ptr NULL
++#endif
++
++DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
++DECLARE_PER_CPU(cpumask_t, cpu_core_map);
++DECLARE_PER_CPU(u16, cpu_llc_id);
++DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
++DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
++
++/* Static state in head.S used to set up a CPU */
++extern struct {
++	void *sp;
++	unsigned short ss;
++} stack_start;
++
++struct smp_ops {
++	void (*smp_prepare_boot_cpu)(void);
++	void (*smp_prepare_cpus)(unsigned max_cpus);
++	int (*cpu_up)(unsigned cpu);
++	void (*smp_cpus_done)(unsigned max_cpus);
++
++	void (*smp_send_stop)(void);
++	void (*smp_send_reschedule)(int cpu);
++	int (*smp_call_function_mask)(cpumask_t mask,
++				      void (*func)(void *info), void *info,
++				      int wait);
++};
++
++/* Globals due to paravirt */
++extern void set_cpu_sibling_map(int cpu);
++
++#ifdef CONFIG_SMP
++#ifndef CONFIG_PARAVIRT
++#define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0)
++#endif
++extern struct smp_ops smp_ops;
++
++static inline void smp_send_stop(void)
++{
++	smp_ops.smp_send_stop();
++}
++
++static inline void smp_prepare_boot_cpu(void)
++{
++	smp_ops.smp_prepare_boot_cpu();
++}
++
++static inline void smp_prepare_cpus(unsigned int max_cpus)
++{
++	smp_ops.smp_prepare_cpus(max_cpus);
++}
++
++static inline void smp_cpus_done(unsigned int max_cpus)
++{
++	smp_ops.smp_cpus_done(max_cpus);
++}
++
++static inline int __cpu_up(unsigned int cpu)
++{
++	return smp_ops.cpu_up(cpu);
++}
++
++static inline void smp_send_reschedule(int cpu)
++{
++	smp_ops.smp_send_reschedule(cpu);
++}
++
++static inline int smp_call_function_mask(cpumask_t mask,
++					 void (*func) (void *info), void *info,
++					 int wait)
++{
++	return smp_ops.smp_call_function_mask(mask, func, info, wait);
++}
++
++void native_smp_prepare_boot_cpu(void);
++void native_smp_prepare_cpus(unsigned int max_cpus);
++void native_smp_cpus_done(unsigned int max_cpus);
++int native_cpu_up(unsigned int cpunum);
++
++extern int __cpu_disable(void);
++extern void __cpu_die(unsigned int cpu);
++
++extern void prefill_possible_map(void);
++
++void smp_store_cpu_info(int id);
++#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
++
++/* We don't mark CPUs online until __cpu_up(), so we need another measure */
++static inline int num_booting_cpus(void)
++{
++	return cpus_weight(cpu_callout_map);
++}
++#endif /* CONFIG_SMP */
++
++extern unsigned disabled_cpus __cpuinitdata;
++
++#ifdef CONFIG_X86_32_SMP
++/*
++ * This function is needed by all SMP systems. It must _always_ be valid
++ * from the initial startup. We map APIC_BASE very early in page_setup(),
++ * so this is correct in the x86 case.
++ */
++DECLARE_PER_CPU(int, cpu_number);
++#define raw_smp_processor_id() (x86_read_percpu(cpu_number))
++extern int safe_smp_processor_id(void);
++
++#elif defined(CONFIG_X86_64_SMP)
++#define raw_smp_processor_id()	read_pda(cpunumber)
++
++#define stack_smp_processor_id()					\
++({								\
++	struct thread_info *ti;						\
++	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
++	ti->cpu;							\
++})
++#define safe_smp_processor_id()		smp_processor_id()
++
++#else /* !CONFIG_X86_32_SMP && !CONFIG_X86_64_SMP */
++#define cpu_physical_id(cpu)		boot_cpu_physical_apicid
++#define safe_smp_processor_id()		0
++#define stack_smp_processor_id() 	0
++#endif
++
++#ifdef CONFIG_X86_LOCAL_APIC
++
++static inline int logical_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
++}
++
++#ifndef CONFIG_X86_64
++static inline unsigned int read_apic_id(void)
++{
++	return *(u32 *)(APIC_BASE + APIC_ID);
++}
++#else
++extern unsigned int read_apic_id(void);
++#endif
++
++
++# ifdef APIC_DEFINITION
++extern int hard_smp_processor_id(void);
++# else
++#  include <mach_apicdef.h>
++static inline int hard_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_ID(read_apic_id());
++}
++# endif /* APIC_DEFINITION */
++
++#else /* CONFIG_X86_LOCAL_APIC */
++
++# ifndef CONFIG_SMP
++#  define hard_smp_processor_id()	0
++# endif
++
++#endif /* CONFIG_X86_LOCAL_APIC */
++
++#ifdef CONFIG_HOTPLUG_CPU
++extern void cpu_exit_clear(void);
++extern void cpu_uninit(void);
++#endif
++
++extern void smp_alloc_memory(void);
++extern void lock_ipi_call_lock(void);
++extern void unlock_ipi_call_lock(void);
++#endif /* __ASSEMBLY__ */
+ #endif
+diff --git a/include/asm-x86/smp_32.h b/include/asm-x86/smp_32.h
+deleted file mode 100644
+index 56152e3..0000000
+--- a/include/asm-x86/smp_32.h
++++ /dev/null
+@@ -1,165 +0,0 @@
+-#ifndef __ASM_SMP_H
+-#define __ASM_SMP_H
+-
+-#ifndef __ASSEMBLY__
+-#include <linux/cpumask.h>
+-#include <linux/init.h>
+-
+-/*
+- * We need the APIC definitions automatically as part of 'smp.h'
+- */
+-#ifdef CONFIG_X86_LOCAL_APIC
+-# include <asm/mpspec.h>
+-# include <asm/apic.h>
+-# ifdef CONFIG_X86_IO_APIC
+-#  include <asm/io_apic.h>
+-# endif
+-#endif
+-
+-extern cpumask_t cpu_callout_map;
+-extern cpumask_t cpu_callin_map;
+-
+-extern int smp_num_siblings;
+-extern unsigned int num_processors;
+-
+-extern void smp_alloc_memory(void);
+-extern void lock_ipi_call_lock(void);
+-extern void unlock_ipi_call_lock(void);
+-
+-extern void (*mtrr_hook) (void);
+-extern void zap_low_mappings (void);
+-
+-extern u8 __initdata x86_cpu_to_apicid_init[];
+-extern void *x86_cpu_to_apicid_early_ptr;
+-
+-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+-DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+-DECLARE_PER_CPU(u8, cpu_llc_id);
+-DECLARE_PER_CPU(u8, x86_cpu_to_apicid);
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-extern void cpu_exit_clear(void);
+-extern void cpu_uninit(void);
+-extern void remove_siblinginfo(int cpu);
+-#endif
+-
+-/* Globals due to paravirt */
+-extern void set_cpu_sibling_map(int cpu);
+-
+-struct smp_ops
+-{
+-	void (*smp_prepare_boot_cpu)(void);
+-	void (*smp_prepare_cpus)(unsigned max_cpus);
+-	int (*cpu_up)(unsigned cpu);
+-	void (*smp_cpus_done)(unsigned max_cpus);
+-
+-	void (*smp_send_stop)(void);
+-	void (*smp_send_reschedule)(int cpu);
+-	int (*smp_call_function_mask)(cpumask_t mask,
+-				      void (*func)(void *info), void *info,
+-				      int wait);
+-};
+-
+-#ifdef CONFIG_SMP
+-extern struct smp_ops smp_ops;
+-
+-static inline void smp_prepare_boot_cpu(void)
+-{
+-	smp_ops.smp_prepare_boot_cpu();
+-}
+-static inline void smp_prepare_cpus(unsigned int max_cpus)
+-{
+-	smp_ops.smp_prepare_cpus(max_cpus);
+-}
+-static inline int __cpu_up(unsigned int cpu)
+-{
+-	return smp_ops.cpu_up(cpu);
+-}
+-static inline void smp_cpus_done(unsigned int max_cpus)
+-{
+-	smp_ops.smp_cpus_done(max_cpus);
+-}
+-
+-static inline void smp_send_stop(void)
+-{
+-	smp_ops.smp_send_stop();
+-}
+-static inline void smp_send_reschedule(int cpu)
+-{
+-	smp_ops.smp_send_reschedule(cpu);
+-}
+-static inline int smp_call_function_mask(cpumask_t mask,
+-					 void (*func) (void *info), void *info,
+-					 int wait)
+-{
+-	return smp_ops.smp_call_function_mask(mask, func, info, wait);
+-}
+-
+-void native_smp_prepare_boot_cpu(void);
+-void native_smp_prepare_cpus(unsigned int max_cpus);
+-int native_cpu_up(unsigned int cpunum);
+-void native_smp_cpus_done(unsigned int max_cpus);
+-
+-#ifndef CONFIG_PARAVIRT
+-#define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0)
+-#endif
+-
+-extern int __cpu_disable(void);
+-extern void __cpu_die(unsigned int cpu);
+-
+-/*
+- * This function is needed by all SMP systems. It must _always_ be valid
+- * from the initial startup. We map APIC_BASE very early in page_setup(),
+- * so this is correct in the x86 case.
+- */
+-DECLARE_PER_CPU(int, cpu_number);
+-#define raw_smp_processor_id() (x86_read_percpu(cpu_number))
+-
+-#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+-
+-extern int safe_smp_processor_id(void);
+-
+-void __cpuinit smp_store_cpu_info(int id);
+-
+-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
+-static inline int num_booting_cpus(void)
+-{
+-	return cpus_weight(cpu_callout_map);
+-}
+-
+-#else /* CONFIG_SMP */
+-
+-#define safe_smp_processor_id()		0
+-#define cpu_physical_id(cpu)		boot_cpu_physical_apicid
+-
+-#endif /* !CONFIG_SMP */
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-
+-static __inline int logical_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+-}
+-
+-# ifdef APIC_DEFINITION
+-extern int hard_smp_processor_id(void);
+-# else
+-#  include <mach_apicdef.h>
+-static inline int hard_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_ID(*(u32 *)(APIC_BASE + APIC_ID));
+-}
+-# endif /* APIC_DEFINITION */
+-
+-#else /* CONFIG_X86_LOCAL_APIC */
+-
+-# ifndef CONFIG_SMP
+-#  define hard_smp_processor_id()	0
+-# endif
+-
+-#endif /* CONFIG_X86_LOCAL_APIC */
+-
+-#endif /* !ASSEMBLY */
+-#endif
+diff --git a/include/asm-x86/smp_64.h b/include/asm-x86/smp_64.h
+deleted file mode 100644
+index e0a7551..0000000
+--- a/include/asm-x86/smp_64.h
++++ /dev/null
+@@ -1,101 +0,0 @@
+-#ifndef __ASM_SMP_H
+-#define __ASM_SMP_H
+-
+-#include <linux/cpumask.h>
+-#include <linux/init.h>
+-
+-/*
+- * We need the APIC definitions automatically as part of 'smp.h'
+- */
+-#include <asm/apic.h>
+-#include <asm/io_apic.h>
+-#include <asm/mpspec.h>
+-#include <asm/pda.h>
+-#include <asm/thread_info.h>
+-
+-extern cpumask_t cpu_callout_map;
+-extern cpumask_t cpu_initialized;
+-
+-extern int smp_num_siblings;
+-extern unsigned int num_processors;
+-
+-extern void smp_alloc_memory(void);
+-extern void lock_ipi_call_lock(void);
+-extern void unlock_ipi_call_lock(void);
+-
+-extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
+-				  void *info, int wait);
+-
+-extern u16 __initdata x86_cpu_to_apicid_init[];
+-extern u16 __initdata x86_bios_cpu_apicid_init[];
+-extern void *x86_cpu_to_apicid_early_ptr;
+-extern void *x86_bios_cpu_apicid_early_ptr;
+-
+-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+-DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+-DECLARE_PER_CPU(u16, cpu_llc_id);
+-DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
+-DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
+-
+-static inline int cpu_present_to_apicid(int mps_cpu)
+-{
+-	if (cpu_present(mps_cpu))
+-		return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
+-	else
+-		return BAD_APICID;
+-}
+-
+-#ifdef CONFIG_SMP
+-
+-#define SMP_TRAMPOLINE_BASE 0x6000
+-
+-extern int __cpu_disable(void);
+-extern void __cpu_die(unsigned int cpu);
+-extern void prefill_possible_map(void);
+-extern unsigned __cpuinitdata disabled_cpus;
+-
+-#define raw_smp_processor_id()	read_pda(cpunumber)
+-#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+-
+-#define stack_smp_processor_id()					\
+-	({								\
+-	struct thread_info *ti;						\
+-	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
+-	ti->cpu;							\
+-})
+-
+-/*
+- * On x86 all CPUs are mapped 1:1 to the APIC space. This simplifies
+- * scheduling and IPI sending and compresses data structures.
+- */
+-static inline int num_booting_cpus(void)
+-{
+-	return cpus_weight(cpu_callout_map);
+-}
+-
+-extern void smp_send_reschedule(int cpu);
+-
+-#else /* CONFIG_SMP */
+-
+-extern unsigned int boot_cpu_id;
+-#define cpu_physical_id(cpu)	boot_cpu_id
+-#define stack_smp_processor_id() 0
+-
+-#endif /* !CONFIG_SMP */
+-
+-#define safe_smp_processor_id()		smp_processor_id()
+-
+-static __inline int logical_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+-}
+-
+-static inline int hard_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_ID(*(u32 *)(APIC_BASE + APIC_ID));
+-}
+-
+-#endif
+-
+diff --git a/include/asm-x86/sparsemem.h b/include/asm-x86/sparsemem.h
+index fa58cd5..9bd48b0 100644
+--- a/include/asm-x86/sparsemem.h
++++ b/include/asm-x86/sparsemem.h
+@@ -16,7 +16,7 @@
+ 
+ #ifdef CONFIG_X86_32
+ # ifdef CONFIG_X86_PAE
+-#  define SECTION_SIZE_BITS	30
++#  define SECTION_SIZE_BITS	29
+ #  define MAX_PHYSADDR_BITS	36
+ #  define MAX_PHYSMEM_BITS	36
+ # else
+@@ -26,8 +26,8 @@
+ # endif
+ #else /* CONFIG_X86_32 */
+ # define SECTION_SIZE_BITS	27 /* matt - 128 is convenient right now */
+-# define MAX_PHYSADDR_BITS	40
+-# define MAX_PHYSMEM_BITS	40
++# define MAX_PHYSADDR_BITS	44
++# define MAX_PHYSMEM_BITS	44
+ #endif
+ 
+ #endif /* CONFIG_SPARSEMEM */
+diff --git a/include/asm-x86/spinlock.h b/include/asm-x86/spinlock.h
+index 23804c1..bc6376f 100644
+--- a/include/asm-x86/spinlock.h
++++ b/include/asm-x86/spinlock.h
+@@ -78,11 +78,11 @@ static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
+ 	return (((tmp >> 8) & 0xff) - (tmp & 0xff)) > 1;
+ }
+ 
+-static inline void __raw_spin_lock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+ {
+ 	short inc = 0x0100;
+ 
+-	__asm__ __volatile__ (
++	asm volatile (
+ 		LOCK_PREFIX "xaddw %w0, %1\n"
+ 		"1:\t"
+ 		"cmpb %h0, %b0\n\t"
+@@ -92,42 +92,40 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
+ 		/* don't need lfence here, because loads are in-order */
+ 		"jmp 1b\n"
+ 		"2:"
+-		:"+Q" (inc), "+m" (lock->slock)
++		: "+Q" (inc), "+m" (lock->slock)
+ 		:
+-		:"memory", "cc");
++		: "memory", "cc");
+ }
+ 
+ #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+ 
+-static inline int __raw_spin_trylock(raw_spinlock_t *lock)
++static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+ {
+ 	int tmp;
+ 	short new;
+ 
+-	asm volatile(
+-		"movw %2,%w0\n\t"
+-		"cmpb %h0,%b0\n\t"
+-		"jne 1f\n\t"
+-		"movw %w0,%w1\n\t"
+-		"incb %h1\n\t"
+-		"lock ; cmpxchgw %w1,%2\n\t"
+-		"1:"
+-		"sete %b1\n\t"
+-		"movzbl %b1,%0\n\t"
+-		:"=&a" (tmp), "=Q" (new), "+m" (lock->slock)
+-		:
+-		: "memory", "cc");
++	asm volatile("movw %2,%w0\n\t"
++		     "cmpb %h0,%b0\n\t"
++		     "jne 1f\n\t"
++		     "movw %w0,%w1\n\t"
++		     "incb %h1\n\t"
++		     "lock ; cmpxchgw %w1,%2\n\t"
++		     "1:"
++		     "sete %b1\n\t"
++		     "movzbl %b1,%0\n\t"
++		     : "=&a" (tmp), "=Q" (new), "+m" (lock->slock)
++		     :
++		     : "memory", "cc");
+ 
+ 	return tmp;
+ }
+ 
+-static inline void __raw_spin_unlock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+ {
+-	__asm__ __volatile__(
+-		UNLOCK_LOCK_PREFIX "incb %0"
+-		:"+m" (lock->slock)
+-		:
+-		:"memory", "cc");
++	asm volatile(UNLOCK_LOCK_PREFIX "incb %0"
++		     : "+m" (lock->slock)
++		     :
++		     : "memory", "cc");
+ }
+ #else
+ static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
+@@ -144,60 +142,57 @@ static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
+ 	return (((tmp >> 16) & 0xffff) - (tmp & 0xffff)) > 1;
+ }
+ 
+-static inline void __raw_spin_lock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+ {
+ 	int inc = 0x00010000;
+ 	int tmp;
+ 
+-	__asm__ __volatile__ (
+-		"lock ; xaddl %0, %1\n"
+-		"movzwl %w0, %2\n\t"
+-		"shrl $16, %0\n\t"
+-		"1:\t"
+-		"cmpl %0, %2\n\t"
+-		"je 2f\n\t"
+-		"rep ; nop\n\t"
+-		"movzwl %1, %2\n\t"
+-		/* don't need lfence here, because loads are in-order */
+-		"jmp 1b\n"
+-		"2:"
+-		:"+Q" (inc), "+m" (lock->slock), "=r" (tmp)
+-		:
+-		:"memory", "cc");
++	asm volatile("lock ; xaddl %0, %1\n"
++		     "movzwl %w0, %2\n\t"
++		     "shrl $16, %0\n\t"
++		     "1:\t"
++		     "cmpl %0, %2\n\t"
++		     "je 2f\n\t"
++		     "rep ; nop\n\t"
++		     "movzwl %1, %2\n\t"
++		     /* don't need lfence here, because loads are in-order */
++		     "jmp 1b\n"
++		     "2:"
++		     : "+Q" (inc), "+m" (lock->slock), "=r" (tmp)
++		     :
++		     : "memory", "cc");
+ }
+ 
+ #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+ 
+-static inline int __raw_spin_trylock(raw_spinlock_t *lock)
++static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+ {
+ 	int tmp;
+ 	int new;
+ 
+-	asm volatile(
+-		"movl %2,%0\n\t"
+-		"movl %0,%1\n\t"
+-		"roll $16, %0\n\t"
+-		"cmpl %0,%1\n\t"
+-		"jne 1f\n\t"
+-		"addl $0x00010000, %1\n\t"
+-		"lock ; cmpxchgl %1,%2\n\t"
+-		"1:"
+-		"sete %b1\n\t"
+-		"movzbl %b1,%0\n\t"
+-		:"=&a" (tmp), "=r" (new), "+m" (lock->slock)
+-		:
+-		: "memory", "cc");
++	asm volatile("movl %2,%0\n\t"
++		     "movl %0,%1\n\t"
++		     "roll $16, %0\n\t"
++		     "cmpl %0,%1\n\t"
++		     "jne 1f\n\t"
++		     "addl $0x00010000, %1\n\t"
++		     "lock ; cmpxchgl %1,%2\n\t"
++		     "1:"
++		     "sete %b1\n\t"
++		     "movzbl %b1,%0\n\t"
++		     : "=&a" (tmp), "=r" (new), "+m" (lock->slock)
++		     :
++		     : "memory", "cc");
+ 
+ 	return tmp;
+ }
+ 
+-static inline void __raw_spin_unlock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+ {
+-	__asm__ __volatile__(
+-		UNLOCK_LOCK_PREFIX "incw %0"
+-		:"+m" (lock->slock)
+-		:
+-		:"memory", "cc");
++	asm volatile(UNLOCK_LOCK_PREFIX "incw %0"
++		     : "+m" (lock->slock)
++		     :
++		     : "memory", "cc");
+ }
+ #endif
+ 
+diff --git a/include/asm-x86/srat.h b/include/asm-x86/srat.h
+index 165ab4b..f4bba13 100644
+--- a/include/asm-x86/srat.h
++++ b/include/asm-x86/srat.h
+@@ -1,5 +1,5 @@
+ /*
+- * Some of the code in this file has been gleaned from the 64 bit 
++ * Some of the code in this file has been gleaned from the 64 bit
+  * discontigmem support code base.
+  *
+  * Copyright (C) 2002, IBM Corp.
+diff --git a/include/asm-x86/string_32.h b/include/asm-x86/string_32.h
+index c5d13a8..b49369a 100644
+--- a/include/asm-x86/string_32.h
++++ b/include/asm-x86/string_32.h
+@@ -3,7 +3,7 @@
+ 
+ #ifdef __KERNEL__
+ 
+-/* Let gcc decide wether to inline or use the out of line functions */
++/* Let gcc decide whether to inline or use the out of line functions */
+ 
+ #define __HAVE_ARCH_STRCPY
+ extern char *strcpy(char *dest, const char *src);
+diff --git a/include/asm-x86/string_64.h b/include/asm-x86/string_64.h
+index e583da7..52b5ab3 100644
+--- a/include/asm-x86/string_64.h
++++ b/include/asm-x86/string_64.h
+@@ -3,26 +3,24 @@
+ 
+ #ifdef __KERNEL__
+ 
+-/* Written 2002 by Andi Kleen */ 
++/* Written 2002 by Andi Kleen */
+ 
+-/* Only used for special circumstances. Stolen from i386/string.h */ 
+-static __always_inline void *
+-__inline_memcpy(void * to, const void * from, size_t n)
++/* Only used for special circumstances. Stolen from i386/string.h */
++static __always_inline void *__inline_memcpy(void *to, const void *from, size_t n)
+ {
+-unsigned long d0, d1, d2;
+-__asm__ __volatile__(
+-	"rep ; movsl\n\t"
+-	"testb $2,%b4\n\t"
+-	"je 1f\n\t"
+-	"movsw\n"
+-	"1:\ttestb $1,%b4\n\t"
+-	"je 2f\n\t"
+-	"movsb\n"
+-	"2:"
+-	: "=&c" (d0), "=&D" (d1), "=&S" (d2)
+-	:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
+-	: "memory");
+-return (to);
++	unsigned long d0, d1, d2;
++	asm volatile("rep ; movsl\n\t"
++		     "testb $2,%b4\n\t"
++		     "je 1f\n\t"
++		     "movsw\n"
++		     "1:\ttestb $1,%b4\n\t"
++		     "je 2f\n\t"
++		     "movsb\n"
++		     "2:"
++		     : "=&c" (d0), "=&D" (d1), "=&S" (d2)
++		     : "0" (n / 4), "q" (n), "1" ((long)to), "2" ((long)from)
++		     : "memory");
++	return to;
+ }
+ 
+ /* Even with __builtin_ the compiler may decide to use the out of line
+@@ -32,28 +30,30 @@ return (to);
+ #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
+ extern void *memcpy(void *to, const void *from, size_t len);
+ #else
+-extern void *__memcpy(void *to, const void *from, size_t len); 
+-#define memcpy(dst,src,len) \
+-	({ size_t __len = (len);				\
+-	   void *__ret;						\
+-	   if (__builtin_constant_p(len) && __len >= 64)	\
+-		 __ret = __memcpy((dst),(src),__len);		\
+-	   else							\
+-		 __ret = __builtin_memcpy((dst),(src),__len);	\
+-	   __ret; }) 
++extern void *__memcpy(void *to, const void *from, size_t len);
++#define memcpy(dst, src, len)					\
++({								\
++	size_t __len = (len);					\
++	void *__ret;						\
++	if (__builtin_constant_p(len) && __len >= 64)		\
++		__ret = __memcpy((dst), (src), __len);		\
++	else							\
++		__ret = __builtin_memcpy((dst), (src), __len);	\
++	__ret;							\
++})
+ #endif
+ 
+ #define __HAVE_ARCH_MEMSET
+ void *memset(void *s, int c, size_t n);
+ 
+ #define __HAVE_ARCH_MEMMOVE
+-void * memmove(void * dest,const void *src,size_t count);
++void *memmove(void *dest, const void *src, size_t count);
+ 
+-int memcmp(const void * cs,const void * ct,size_t count);
+-size_t strlen(const char * s);
+-char *strcpy(char * dest,const char *src);
+-char *strcat(char * dest, const char * src);
+-int strcmp(const char * cs,const char * ct);
++int memcmp(const void *cs, const void *ct, size_t count);
++size_t strlen(const char *s);
++char *strcpy(char *dest, const char *src);
++char *strcat(char *dest, const char *src);
++int strcmp(const char *cs, const char *ct);
+ 
+ #endif /* __KERNEL__ */
+ 
+diff --git a/include/asm-x86/suspend_32.h b/include/asm-x86/suspend_32.h
+index 1bbda3a..24e1c08 100644
+--- a/include/asm-x86/suspend_32.h
++++ b/include/asm-x86/suspend_32.h
+@@ -10,7 +10,7 @@ static inline int arch_prepare_suspend(void) { return 0; }
+ 
+ /* image of the saved processor state */
+ struct saved_context {
+-  	u16 es, fs, gs, ss;
++	u16 es, fs, gs, ss;
+ 	unsigned long cr0, cr2, cr3, cr4;
+ 	struct desc_ptr gdt;
+ 	struct desc_ptr idt;
+@@ -32,11 +32,11 @@ extern unsigned long saved_edi;
+ static inline void acpi_save_register_state(unsigned long return_point)
+ {
+ 	saved_eip = return_point;
+-	asm volatile ("movl %%esp,%0" : "=m" (saved_esp));
+-	asm volatile ("movl %%ebp,%0" : "=m" (saved_ebp));
+-	asm volatile ("movl %%ebx,%0" : "=m" (saved_ebx));
+-	asm volatile ("movl %%edi,%0" : "=m" (saved_edi));
+-	asm volatile ("movl %%esi,%0" : "=m" (saved_esi));
++	asm volatile("movl %%esp,%0" : "=m" (saved_esp));
++	asm volatile("movl %%ebp,%0" : "=m" (saved_ebp));
++	asm volatile("movl %%ebx,%0" : "=m" (saved_ebx));
++	asm volatile("movl %%edi,%0" : "=m" (saved_edi));
++	asm volatile("movl %%esi,%0" : "=m" (saved_esi));
+ }
+ 
+ #define acpi_restore_register_state()  do {} while (0)
+diff --git a/include/asm-x86/suspend_64.h b/include/asm-x86/suspend_64.h
+index 2eb92cb..dc3262b 100644
+--- a/include/asm-x86/suspend_64.h
++++ b/include/asm-x86/suspend_64.h
+@@ -9,8 +9,7 @@
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+ 
+-static inline int
+-arch_prepare_suspend(void)
++static inline int arch_prepare_suspend(void)
+ {
+ 	return 0;
+ }
+@@ -25,7 +24,7 @@ arch_prepare_suspend(void)
+  */
+ struct saved_context {
+ 	struct pt_regs regs;
+-  	u16 ds, es, fs, gs, ss;
++	u16 ds, es, fs, gs, ss;
+ 	unsigned long gs_base, gs_kernel_base, fs_base;
+ 	unsigned long cr0, cr2, cr3, cr4, cr8;
+ 	unsigned long efer;
+diff --git a/include/asm-x86/swiotlb.h b/include/asm-x86/swiotlb.h
+index f9c5895..f5d9e74 100644
+--- a/include/asm-x86/swiotlb.h
++++ b/include/asm-x86/swiotlb.h
+@@ -8,15 +8,15 @@
+ extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr,
+ 				     size_t size, int dir);
+ extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
+-                       dma_addr_t *dma_handle, gfp_t flags);
++				    dma_addr_t *dma_handle, gfp_t flags);
+ extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
+-				  size_t size, int dir);
++				 size_t size, int dir);
+ extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
+-					 dma_addr_t dev_addr,
+-					 size_t size, int dir);
++					dma_addr_t dev_addr,
++					size_t size, int dir);
+ extern void swiotlb_sync_single_for_device(struct device *hwdev,
+-					    dma_addr_t dev_addr,
+-					    size_t size, int dir);
++					   dma_addr_t dev_addr,
++					   size_t size, int dir);
+ extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev,
+ 					      dma_addr_t dev_addr,
+ 					      unsigned long offset,
+@@ -26,18 +26,18 @@ extern void swiotlb_sync_single_range_for_device(struct device *hwdev,
+ 						 unsigned long offset,
+ 						 size_t size, int dir);
+ extern void swiotlb_sync_sg_for_cpu(struct device *hwdev,
+-				     struct scatterlist *sg, int nelems,
+-				     int dir);
++				    struct scatterlist *sg, int nelems,
++				    int dir);
+ extern void swiotlb_sync_sg_for_device(struct device *hwdev,
+-					struct scatterlist *sg, int nelems,
+-					int dir);
++				       struct scatterlist *sg, int nelems,
++				       int dir);
+ extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
+-		      int nents, int direction);
++			  int nents, int direction);
+ extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+-			 int nents, int direction);
++			     int nents, int direction);
+ extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
+-extern void swiotlb_free_coherent (struct device *hwdev, size_t size,
+-				   void *vaddr, dma_addr_t dma_handle);
++extern void swiotlb_free_coherent(struct device *hwdev, size_t size,
++				  void *vaddr, dma_addr_t dma_handle);
+ extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
+ extern void swiotlb_init(void);
+ 
+diff --git a/include/asm-x86/sync_bitops.h b/include/asm-x86/sync_bitops.h
+index 6b775c9..b47a1d0 100644
+--- a/include/asm-x86/sync_bitops.h
++++ b/include/asm-x86/sync_bitops.h
+@@ -13,7 +13,7 @@
+  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+  */
+ 
+-#define ADDR (*(volatile long *) addr)
++#define ADDR (*(volatile long *)addr)
+ 
+ /**
+  * sync_set_bit - Atomically set a bit in memory
+@@ -26,12 +26,12 @@
+  * Note that @nr may be almost arbitrarily large; this function is not
+  * restricted to acting on a single-word quantity.
+  */
+-static inline void sync_set_bit(int nr, volatile unsigned long * addr)
++static inline void sync_set_bit(int nr, volatile unsigned long *addr)
+ {
+-	__asm__ __volatile__("lock; btsl %1,%0"
+-			     :"+m" (ADDR)
+-			     :"Ir" (nr)
+-			     : "memory");
++	asm volatile("lock; btsl %1,%0"
++		     : "+m" (ADDR)
++		     : "Ir" (nr)
++		     : "memory");
+ }
+ 
+ /**
+@@ -44,12 +44,12 @@ static inline void sync_set_bit(int nr, volatile unsigned long * addr)
+  * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+  * in order to ensure changes are visible on other processors.
+  */
+-static inline void sync_clear_bit(int nr, volatile unsigned long * addr)
++static inline void sync_clear_bit(int nr, volatile unsigned long *addr)
+ {
+-	__asm__ __volatile__("lock; btrl %1,%0"
+-			     :"+m" (ADDR)
+-			     :"Ir" (nr)
+-			     : "memory");
++	asm volatile("lock; btrl %1,%0"
++		     : "+m" (ADDR)
++		     : "Ir" (nr)
++		     : "memory");
+ }
+ 
+ /**
+@@ -61,12 +61,12 @@ static inline void sync_clear_bit(int nr, volatile unsigned long * addr)
+  * Note that @nr may be almost arbitrarily large; this function is not
+  * restricted to acting on a single-word quantity.
+  */
+-static inline void sync_change_bit(int nr, volatile unsigned long * addr)
++static inline void sync_change_bit(int nr, volatile unsigned long *addr)
+ {
+-	__asm__ __volatile__("lock; btcl %1,%0"
+-			     :"+m" (ADDR)
+-			     :"Ir" (nr)
+-			     : "memory");
++	asm volatile("lock; btcl %1,%0"
++		     : "+m" (ADDR)
++		     : "Ir" (nr)
++		     : "memory");
+ }
+ 
+ /**
+@@ -77,13 +77,13 @@ static inline void sync_change_bit(int nr, volatile unsigned long * addr)
+  * This operation is atomic and cannot be reordered.
+  * It also implies a memory barrier.
+  */
+-static inline int sync_test_and_set_bit(int nr, volatile unsigned long * addr)
++static inline int sync_test_and_set_bit(int nr, volatile unsigned long *addr)
+ {
+ 	int oldbit;
+ 
+-	__asm__ __volatile__("lock; btsl %2,%1\n\tsbbl %0,%0"
+-			     :"=r" (oldbit),"+m" (ADDR)
+-			     :"Ir" (nr) : "memory");
++	asm volatile("lock; btsl %2,%1\n\tsbbl %0,%0"
++		     : "=r" (oldbit), "+m" (ADDR)
++		     : "Ir" (nr) : "memory");
+ 	return oldbit;
+ }
+ 
+@@ -95,13 +95,13 @@ static inline int sync_test_and_set_bit(int nr, volatile unsigned long * addr)
+  * This operation is atomic and cannot be reordered.
+  * It also implies a memory barrier.
+  */
+-static inline int sync_test_and_clear_bit(int nr, volatile unsigned long * addr)
++static inline int sync_test_and_clear_bit(int nr, volatile unsigned long *addr)
+ {
+ 	int oldbit;
+ 
+-	__asm__ __volatile__("lock; btrl %2,%1\n\tsbbl %0,%0"
+-			     :"=r" (oldbit),"+m" (ADDR)
+-			     :"Ir" (nr) : "memory");
++	asm volatile("lock; btrl %2,%1\n\tsbbl %0,%0"
++		     : "=r" (oldbit), "+m" (ADDR)
++		     : "Ir" (nr) : "memory");
+ 	return oldbit;
+ }
+ 
+@@ -113,36 +113,17 @@ static inline int sync_test_and_clear_bit(int nr, volatile unsigned long * addr)
+  * This operation is atomic and cannot be reordered.
+  * It also implies a memory barrier.
+  */
+-static inline int sync_test_and_change_bit(int nr, volatile unsigned long* addr)
++static inline int sync_test_and_change_bit(int nr, volatile unsigned long *addr)
+ {
+ 	int oldbit;
+ 
+-	__asm__ __volatile__("lock; btcl %2,%1\n\tsbbl %0,%0"
+-			     :"=r" (oldbit),"+m" (ADDR)
+-			     :"Ir" (nr) : "memory");
++	asm volatile("lock; btcl %2,%1\n\tsbbl %0,%0"
++		     : "=r" (oldbit), "+m" (ADDR)
++		     : "Ir" (nr) : "memory");
+ 	return oldbit;
+ }
+ 
+-static __always_inline int sync_constant_test_bit(int nr, const volatile unsigned long *addr)
+-{
+-	return ((1UL << (nr & 31)) &
+-		(((const volatile unsigned int *)addr)[nr >> 5])) != 0;
+-}
+-
+-static inline int sync_var_test_bit(int nr, const volatile unsigned long * addr)
+-{
+-	int oldbit;
+-
+-	__asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
+-			     :"=r" (oldbit)
+-			     :"m" (ADDR),"Ir" (nr));
+-	return oldbit;
+-}
+-
+-#define sync_test_bit(nr,addr)			\
+-	(__builtin_constant_p(nr) ?		\
+-	 sync_constant_test_bit((nr),(addr)) :	\
+-	 sync_var_test_bit((nr),(addr)))
++#define sync_test_bit(nr, addr) test_bit(nr, addr)
+ 
+ #undef ADDR
+ 
+diff --git a/include/asm-x86/system.h b/include/asm-x86/system.h
+index 9cff02f..a2f04cd 100644
+--- a/include/asm-x86/system.h
++++ b/include/asm-x86/system.h
+@@ -27,22 +27,44 @@ struct task_struct *__switch_to(struct task_struct *prev,
+  * Saving eflags is important. It switches not only IOPL between tasks,
+  * it also protects other tasks from NT leaking through sysenter etc.
+  */
+-#define switch_to(prev, next, last) do {				\
+-	unsigned long esi, edi;						\
+-	asm volatile("pushfl\n\t"		/* Save flags */	\
+-		     "pushl %%ebp\n\t"					\
+-		     "movl %%esp,%0\n\t"	/* save ESP */		\
+-		     "movl %5,%%esp\n\t"	/* restore ESP */	\
+-		     "movl $1f,%1\n\t"		/* save EIP */		\
+-		     "pushl %6\n\t"		/* restore EIP */	\
+-		     "jmp __switch_to\n"				\
++#define switch_to(prev, next, last)					\
++do {									\
++	/*								\
++	 * Context-switching clobbers all registers, so we clobber	\
++	 * them explicitly, via unused output variables.		\
++	 * (EAX and EBP is not listed because EBP is saved/restored	\
++	 * explicitly for wchan access and EAX is the return value of	\
++	 * __switch_to())						\
++	 */								\
++	unsigned long ebx, ecx, edx, esi, edi;				\
++									\
++	asm volatile("pushfl\n\t"		/* save    flags */	\
++		     "pushl %%ebp\n\t"		/* save    EBP   */	\
++		     "movl %%esp,%[prev_sp]\n\t"	/* save    ESP   */ \
++		     "movl %[next_sp],%%esp\n\t"	/* restore ESP   */ \
++		     "movl $1f,%[prev_ip]\n\t"	/* save    EIP   */	\
++		     "pushl %[next_ip]\n\t"	/* restore EIP   */	\
++		     "jmp __switch_to\n"	/* regparm call  */	\
+ 		     "1:\t"						\
+-		     "popl %%ebp\n\t"					\
+-		     "popfl"						\
+-		     :"=m" (prev->thread.sp), "=m" (prev->thread.ip),	\
+-		      "=a" (last), "=S" (esi), "=D" (edi)		\
+-		     :"m" (next->thread.sp), "m" (next->thread.ip),	\
+-		      "2" (prev), "d" (next));				\
++		     "popl %%ebp\n\t"		/* restore EBP   */	\
++		     "popfl\n"			/* restore flags */	\
++									\
++		     /* output parameters */				\
++		     : [prev_sp] "=m" (prev->thread.sp),		\
++		       [prev_ip] "=m" (prev->thread.ip),		\
++		       "=a" (last),					\
++									\
++		       /* clobbered output registers: */		\
++		       "=b" (ebx), "=c" (ecx), "=d" (edx),		\
++		       "=S" (esi), "=D" (edi)				\
++		       							\
++		       /* input parameters: */				\
++		     : [next_sp]  "m" (next->thread.sp),		\
++		       [next_ip]  "m" (next->thread.ip),		\
++		       							\
++		       /* regparm parameters for __switch_to(): */	\
++		       [prev]     "a" (prev),				\
++		       [next]     "d" (next));				\
+ } while (0)
+ 
+ /*
+@@ -122,35 +144,34 @@ extern void load_gs_index(unsigned);
+  */
+ #define loadsegment(seg, value)			\
+ 	asm volatile("\n"			\
+-		"1:\t"				\
+-		"movl %k0,%%" #seg "\n"		\
+-		"2:\n"				\
+-		".section .fixup,\"ax\"\n"	\
+-		"3:\t"				\
+-		"movl %k1, %%" #seg "\n\t"	\
+-		"jmp 2b\n"			\
+-		".previous\n"			\
+-		_ASM_EXTABLE(1b,3b)		\
+-		: :"r" (value), "r" (0))
++		     "1:\t"			\
++		     "movl %k0,%%" #seg "\n"	\
++		     "2:\n"			\
++		     ".section .fixup,\"ax\"\n"	\
++		     "3:\t"			\
++		     "movl %k1, %%" #seg "\n\t"	\
++		     "jmp 2b\n"			\
++		     ".previous\n"		\
++		     _ASM_EXTABLE(1b,3b)	\
++		     : :"r" (value), "r" (0))
+ 
+ 
+ /*
+  * Save a segment register away
+  */
+-#define savesegment(seg, value) \
++#define savesegment(seg, value)				\
+ 	asm volatile("mov %%" #seg ",%0":"=rm" (value))
+ 
+ static inline unsigned long get_limit(unsigned long segment)
+ {
+ 	unsigned long __limit;
+-	__asm__("lsll %1,%0"
+-		:"=r" (__limit):"r" (segment));
+-	return __limit+1;
++	asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
++	return __limit + 1;
+ }
+ 
+ static inline void native_clts(void)
+ {
+-	asm volatile ("clts");
++	asm volatile("clts");
+ }
+ 
+ /*
+@@ -165,43 +186,43 @@ static unsigned long __force_order;
+ static inline unsigned long native_read_cr0(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr0,%0\n\t" :"=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
+ 	return val;
+ }
+ 
+ static inline void native_write_cr0(unsigned long val)
+ {
+-	asm volatile("mov %0,%%cr0": :"r" (val), "m" (__force_order));
++	asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
+ }
+ 
+ static inline unsigned long native_read_cr2(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr2,%0\n\t" :"=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
+ 	return val;
+ }
+ 
+ static inline void native_write_cr2(unsigned long val)
+ {
+-	asm volatile("mov %0,%%cr2": :"r" (val), "m" (__force_order));
++	asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
+ }
+ 
+ static inline unsigned long native_read_cr3(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr3,%0\n\t" :"=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
+ 	return val;
+ }
+ 
+ static inline void native_write_cr3(unsigned long val)
+ {
+-	asm volatile("mov %0,%%cr3": :"r" (val), "m" (__force_order));
++	asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
+ }
+ 
+ static inline unsigned long native_read_cr4(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr4,%0\n\t" :"=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
+ 	return val;
+ }
+ 
+@@ -213,7 +234,7 @@ static inline unsigned long native_read_cr4_safe(void)
+ #ifdef CONFIG_X86_32
+ 	asm volatile("1: mov %%cr4, %0\n"
+ 		     "2:\n"
+-		     _ASM_EXTABLE(1b,2b)
++		     _ASM_EXTABLE(1b, 2b)
+ 		     : "=r" (val), "=m" (__force_order) : "0" (0));
+ #else
+ 	val = native_read_cr4();
+@@ -223,7 +244,7 @@ static inline unsigned long native_read_cr4_safe(void)
+ 
+ static inline void native_write_cr4(unsigned long val)
+ {
+-	asm volatile("mov %0,%%cr4": :"r" (val), "m" (__force_order));
++	asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
+ }
+ 
+ #ifdef CONFIG_X86_64
+@@ -244,6 +265,7 @@ static inline void native_wbinvd(void)
+ {
+ 	asm volatile("wbinvd": : :"memory");
+ }
++
+ #ifdef CONFIG_PARAVIRT
+ #include <asm/paravirt.h>
+ #else
+@@ -276,7 +298,7 @@ static inline void clflush(volatile void *__p)
+ 	asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
+ }
+ 
+-#define nop() __asm__ __volatile__ ("nop")
++#define nop() asm volatile ("nop")
+ 
+ void disable_hlt(void);
+ void enable_hlt(void);
+@@ -296,16 +318,7 @@ void default_idle(void);
+  */
+ #ifdef CONFIG_X86_32
+ /*
+- * For now, "wmb()" doesn't actually do anything, as all
+- * Intel CPU's follow what Intel calls a *Processor Order*,
+- * in which all writes are seen in the program order even
+- * outside the CPU.
+- *
+- * I expect future Intel CPU's to have a weaker ordering,
+- * but I'd also expect them to finally get their act together
+- * and add some real memory barriers if so.
+- *
+- * Some non intel clones support out of order store. wmb() ceases to be a
++ * Some non-Intel clones support out of order store. wmb() ceases to be a
+  * nop for these.
+  */
+ #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+@@ -384,7 +397,7 @@ void default_idle(void);
+ # define smp_wmb()	barrier()
+ #endif
+ #define smp_read_barrier_depends()	read_barrier_depends()
+-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
++#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+ #else
+ #define smp_mb()	barrier()
+ #define smp_rmb()	barrier()
+diff --git a/include/asm-x86/tce.h b/include/asm-x86/tce.h
+index cd955d3..b1a4ea0 100644
+--- a/include/asm-x86/tce.h
++++ b/include/asm-x86/tce.h
+@@ -39,7 +39,7 @@ struct iommu_table;
+ #define TCE_RPN_MASK     0x0000fffffffff000ULL
+ 
+ extern void tce_build(struct iommu_table *tbl, unsigned long index,
+-        unsigned int npages, unsigned long uaddr, int direction);
++		      unsigned int npages, unsigned long uaddr, int direction);
+ extern void tce_free(struct iommu_table *tbl, long index, unsigned int npages);
+ extern void * __init alloc_tce_table(void);
+ extern void __init free_tce_table(void *tbl);
+diff --git a/include/asm-x86/thread_info.h b/include/asm-x86/thread_info.h
+index d5fd12f..77244f1 100644
+--- a/include/asm-x86/thread_info.h
++++ b/include/asm-x86/thread_info.h
+@@ -1,5 +1,14 @@
++#ifndef _ASM_X86_THREAD_INFO_H
+ #ifdef CONFIG_X86_32
+ # include "thread_info_32.h"
+ #else
+ # include "thread_info_64.h"
+ #endif
++
++#ifndef __ASSEMBLY__
++extern void arch_task_cache_init(void);
++extern void free_thread_info(struct thread_info *ti);
++extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
++#define arch_task_cache_init arch_task_cache_init
++#endif
++#endif /* _ASM_X86_THREAD_INFO_H */
+diff --git a/include/asm-x86/thread_info_32.h b/include/asm-x86/thread_info_32.h
+index 5bd5082..5318599 100644
+--- a/include/asm-x86/thread_info_32.h
++++ b/include/asm-x86/thread_info_32.h
+@@ -20,7 +20,8 @@
+  * low level task data that entry.S needs immediate access to
+  * - this struct should fit entirely inside of one cache line
+  * - this struct shares the supervisor stack pages
+- * - if the contents of this structure are changed, the assembly constants must also be changed
++ * - if the contents of this structure are changed,
++ *   the assembly constants must also be changed
+  */
+ #ifndef __ASSEMBLY__
+ 
+@@ -30,18 +31,16 @@ struct thread_info {
+ 	unsigned long		flags;		/* low level flags */
+ 	unsigned long		status;		/* thread-synchronous flags */
+ 	__u32			cpu;		/* current CPU */
+-	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+-
+-
++	int			preempt_count;	/* 0 => preemptable,
++						   <0 => BUG */
+ 	mm_segment_t		addr_limit;	/* thread address space:
+-					 	   0-0xBFFFFFFF for user-thead
+-						   0-0xFFFFFFFF for kernel-thread
++						   0-0xBFFFFFFF user-thread
++						   0-0xFFFFFFFF kernel-thread
+ 						*/
+ 	void			*sysenter_return;
+ 	struct restart_block    restart_block;
+-
+-	unsigned long           previous_esp;   /* ESP of the previous stack in case
+-						   of nested (IRQ) stacks
++	unsigned long           previous_esp;   /* ESP of the previous stack in
++						   case of nested (IRQ) stacks
+ 						*/
+ 	__u8			supervisor_stack[0];
+ };
+@@ -90,24 +89,23 @@ register unsigned long current_stack_pointer asm("esp") __used;
+ /* how to get the thread information struct from C */
+ static inline struct thread_info *current_thread_info(void)
+ {
+-	return (struct thread_info *)(current_stack_pointer & ~(THREAD_SIZE - 1));
++	return (struct thread_info *)
++		(current_stack_pointer & ~(THREAD_SIZE - 1));
+ }
+ 
+ /* thread information allocation */
+ #ifdef CONFIG_DEBUG_STACK_USAGE
+-#define alloc_thread_info(tsk) ((struct thread_info *) \
+-	__get_free_pages(GFP_KERNEL| __GFP_ZERO, get_order(THREAD_SIZE)))
++#define alloc_thread_info(tsk) ((struct thread_info *)			\
++	__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(THREAD_SIZE)))
+ #else
+-#define alloc_thread_info(tsk) ((struct thread_info *) \
++#define alloc_thread_info(tsk) ((struct thread_info *)			\
+ 	__get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)))
+ #endif
+ 
+-#define free_thread_info(info)	free_pages((unsigned long)(info), get_order(THREAD_SIZE))
+-
+ #else /* !__ASSEMBLY__ */
+ 
+ /* how to get the thread information struct from ASM */
+-#define GET_THREAD_INFO(reg) \
++#define GET_THREAD_INFO(reg)	 \
+ 	movl $-THREAD_SIZE, reg; \
+ 	andl %esp, reg
+ 
+@@ -119,14 +117,16 @@ static inline struct thread_info *current_thread_info(void)
+ 
+ /*
+  * thread information flags
+- * - these are process state flags that various assembly files may need to access
++ * - these are process state flags that various
++ *   assembly files may need to access
+  * - pending work-to-be-done flags are in LSW
+  * - other flags in MSW
+  */
+ #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+ #define TIF_SIGPENDING		1	/* signal pending */
+ #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
+-#define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
++#define TIF_SINGLESTEP		3	/* restore singlestep on return to
++					   user mode */
+ #define TIF_IRET		4	/* return with iret */
+ #define TIF_SYSCALL_EMU		5	/* syscall emulation active */
+ #define TIF_SYSCALL_AUDIT	6	/* syscall auditing active */
+@@ -143,36 +143,36 @@ static inline struct thread_info *current_thread_info(void)
+ #define TIF_DS_AREA_MSR 	23      /* uses thread_struct.ds_area_msr */
+ #define TIF_BTS_TRACE_TS        24      /* record scheduling event timestamps */
+ 
+-#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+-#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+-#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+-#define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
+-#define _TIF_IRET		(1<<TIF_IRET)
+-#define _TIF_SYSCALL_EMU	(1<<TIF_SYSCALL_EMU)
+-#define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+-#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+-#define _TIF_HRTICK_RESCHED	(1<<TIF_HRTICK_RESCHED)
+-#define _TIF_DEBUG		(1<<TIF_DEBUG)
+-#define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
+-#define _TIF_FREEZE		(1<<TIF_FREEZE)
+-#define _TIF_NOTSC		(1<<TIF_NOTSC)
+-#define _TIF_FORCED_TF		(1<<TIF_FORCED_TF)
+-#define _TIF_DEBUGCTLMSR	(1<<TIF_DEBUGCTLMSR)
+-#define _TIF_DS_AREA_MSR	(1<<TIF_DS_AREA_MSR)
+-#define _TIF_BTS_TRACE_TS	(1<<TIF_BTS_TRACE_TS)
++#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
++#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
++#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
++#define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
++#define _TIF_IRET		(1 << TIF_IRET)
++#define _TIF_SYSCALL_EMU	(1 << TIF_SYSCALL_EMU)
++#define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
++#define _TIF_SECCOMP		(1 << TIF_SECCOMP)
++#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
++#define _TIF_HRTICK_RESCHED	(1 << TIF_HRTICK_RESCHED)
++#define _TIF_DEBUG		(1 << TIF_DEBUG)
++#define _TIF_IO_BITMAP		(1 << TIF_IO_BITMAP)
++#define _TIF_FREEZE		(1 << TIF_FREEZE)
++#define _TIF_NOTSC		(1 << TIF_NOTSC)
++#define _TIF_FORCED_TF		(1 << TIF_FORCED_TF)
++#define _TIF_DEBUGCTLMSR	(1 << TIF_DEBUGCTLMSR)
++#define _TIF_DS_AREA_MSR	(1 << TIF_DS_AREA_MSR)
++#define _TIF_BTS_TRACE_TS	(1 << TIF_BTS_TRACE_TS)
+ 
+ /* work to do on interrupt/exception return */
+-#define _TIF_WORK_MASK \
+-  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
+-		  _TIF_SECCOMP | _TIF_SYSCALL_EMU))
++#define _TIF_WORK_MASK							\
++	(0x0000FFFF & ~(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT |	\
++			_TIF_SECCOMP | _TIF_SYSCALL_EMU))
+ /* work to do on any return to u-space */
+ #define _TIF_ALLWORK_MASK	(0x0000FFFF & ~_TIF_SECCOMP)
+ 
+ /* flags to check in __switch_to() */
+-#define _TIF_WORK_CTXSW \
+-    (_TIF_IO_BITMAP | _TIF_NOTSC | _TIF_DEBUGCTLMSR | \
+-     _TIF_DS_AREA_MSR | _TIF_BTS_TRACE_TS)
++#define _TIF_WORK_CTXSW						\
++	(_TIF_IO_BITMAP | _TIF_NOTSC | _TIF_DEBUGCTLMSR |	\
++	 _TIF_DS_AREA_MSR | _TIF_BTS_TRACE_TS)
+ #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
+ #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW | _TIF_DEBUG)
+ 
+@@ -184,8 +184,10 @@ static inline struct thread_info *current_thread_info(void)
+  * ever touches our thread-synchronous status, so we don't
+  * have to worry about atomic accesses.
+  */
+-#define TS_USEDFPU		0x0001	/* FPU was used by this task this quantum (SMP) */
+-#define TS_POLLING		0x0002	/* True if in idle loop and not sleeping */
++#define TS_USEDFPU		0x0001	/* FPU was used by this task
++					   this quantum (SMP) */
++#define TS_POLLING		0x0002	/* True if in idle loop
++					   and not sleeping */
+ 
+ #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
+ 
+diff --git a/include/asm-x86/thread_info_64.h b/include/asm-x86/thread_info_64.h
+index 6c9b214..ed664e8 100644
+--- a/include/asm-x86/thread_info_64.h
++++ b/include/asm-x86/thread_info_64.h
+@@ -29,9 +29,9 @@ struct thread_info {
+ 	__u32			flags;		/* low level flags */
+ 	__u32			status;		/* thread synchronous flags */
+ 	__u32			cpu;		/* current CPU */
+-	int 			preempt_count;	/* 0 => preemptable, <0 => BUG */
+-
+-	mm_segment_t		addr_limit;	
++	int 			preempt_count;	/* 0 => preemptable,
++						   <0 => BUG */
++	mm_segment_t		addr_limit;
+ 	struct restart_block    restart_block;
+ #ifdef CONFIG_IA32_EMULATION
+ 	void __user		*sysenter_return;
+@@ -61,17 +61,17 @@ struct thread_info {
+ #define init_stack		(init_thread_union.stack)
+ 
+ static inline struct thread_info *current_thread_info(void)
+-{ 
++{
+ 	struct thread_info *ti;
+ 	ti = (void *)(read_pda(kernelstack) + PDA_STACKOFFSET - THREAD_SIZE);
+-	return ti; 
++	return ti;
+ }
+ 
+ /* do not use in interrupt context */
+ static inline struct thread_info *stack_thread_info(void)
+ {
+ 	struct thread_info *ti;
+-	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1)));
++	asm("andq %%rsp,%0; " : "=r" (ti) : "0" (~(THREAD_SIZE - 1)));
+ 	return ti;
+ }
+ 
+@@ -82,10 +82,8 @@ static inline struct thread_info *stack_thread_info(void)
+ #define THREAD_FLAGS GFP_KERNEL
+ #endif
+ 
+-#define alloc_thread_info(tsk) \
+-	((struct thread_info *) __get_free_pages(THREAD_FLAGS, THREAD_ORDER))
+-
+-#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
++#define alloc_thread_info(tsk)						\
++	((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER))
+ 
+ #else /* !__ASSEMBLY__ */
+ 
+@@ -98,7 +96,8 @@ static inline struct thread_info *stack_thread_info(void)
+ 
+ /*
+  * thread information flags
+- * - these are process state flags that various assembly files may need to access
++ * - these are process state flags that various assembly files
++ *   may need to access
+  * - pending work-to-be-done flags are in LSW
+  * - other flags in MSW
+  * Warning: layout of LSW is hardcoded in entry.S
+@@ -114,7 +113,7 @@ static inline struct thread_info *stack_thread_info(void)
+ #define TIF_MCE_NOTIFY		10	/* notify userspace of an MCE */
+ #define TIF_HRTICK_RESCHED	11	/* reprogram hrtick timer */
+ /* 16 free */
+-#define TIF_IA32		17	/* 32bit process */ 
++#define TIF_IA32		17	/* 32bit process */
+ #define TIF_FORK		18	/* ret_from_fork */
+ #define TIF_ABI_PENDING		19
+ #define TIF_MEMDIE		20
+@@ -125,40 +124,43 @@ static inline struct thread_info *stack_thread_info(void)
+ #define TIF_DEBUGCTLMSR		25	/* uses thread_struct.debugctlmsr */
+ #define TIF_DS_AREA_MSR		26      /* uses thread_struct.ds_area_msr */
+ #define TIF_BTS_TRACE_TS	27      /* record scheduling event timestamps */
+-
+-#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+-#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+-#define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
+-#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+-#define _TIF_IRET		(1<<TIF_IRET)
+-#define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+-#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+-#define _TIF_MCE_NOTIFY		(1<<TIF_MCE_NOTIFY)
+-#define _TIF_HRTICK_RESCHED	(1<<TIF_HRTICK_RESCHED)
+-#define _TIF_IA32		(1<<TIF_IA32)
+-#define _TIF_FORK		(1<<TIF_FORK)
+-#define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
+-#define _TIF_DEBUG		(1<<TIF_DEBUG)
+-#define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
+-#define _TIF_FREEZE		(1<<TIF_FREEZE)
+-#define _TIF_FORCED_TF		(1<<TIF_FORCED_TF)
+-#define _TIF_DEBUGCTLMSR	(1<<TIF_DEBUGCTLMSR)
+-#define _TIF_DS_AREA_MSR	(1<<TIF_DS_AREA_MSR)
+-#define _TIF_BTS_TRACE_TS	(1<<TIF_BTS_TRACE_TS)
++#define TIF_NOTSC		28	/* TSC is not accessible in userland */
++
++#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
++#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
++#define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
++#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
++#define _TIF_IRET		(1 << TIF_IRET)
++#define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
++#define _TIF_SECCOMP		(1 << TIF_SECCOMP)
++#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
++#define _TIF_MCE_NOTIFY		(1 << TIF_MCE_NOTIFY)
++#define _TIF_HRTICK_RESCHED	(1 << TIF_HRTICK_RESCHED)
++#define _TIF_IA32		(1 << TIF_IA32)
++#define _TIF_FORK		(1 << TIF_FORK)
++#define _TIF_ABI_PENDING	(1 << TIF_ABI_PENDING)
++#define _TIF_DEBUG		(1 << TIF_DEBUG)
++#define _TIF_IO_BITMAP		(1 << TIF_IO_BITMAP)
++#define _TIF_FREEZE		(1 << TIF_FREEZE)
++#define _TIF_FORCED_TF		(1 << TIF_FORCED_TF)
++#define _TIF_DEBUGCTLMSR	(1 << TIF_DEBUGCTLMSR)
++#define _TIF_DS_AREA_MSR	(1 << TIF_DS_AREA_MSR)
++#define _TIF_BTS_TRACE_TS	(1 << TIF_BTS_TRACE_TS)
++#define _TIF_NOTSC		(1 << TIF_NOTSC)
+ 
+ /* work to do on interrupt/exception return */
+-#define _TIF_WORK_MASK \
+-  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
++#define _TIF_WORK_MASK							\
++	(0x0000FFFF &							\
++	 ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
+ /* work to do on any return to user space */
+ #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
+ 
+-#define _TIF_DO_NOTIFY_MASK \
++#define _TIF_DO_NOTIFY_MASK						\
+ 	(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
+ 
+ /* flags to check in __switch_to() */
+-#define _TIF_WORK_CTXSW \
+-    (_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_BTS_TRACE_TS)
++#define _TIF_WORK_CTXSW							\
++	(_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_BTS_TRACE_TS|_TIF_NOTSC)
+ #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
+ #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
+ 
+@@ -171,9 +173,11 @@ static inline struct thread_info *stack_thread_info(void)
+  * ever touches our thread-synchronous status, so we don't
+  * have to worry about atomic accesses.
+  */
+-#define TS_USEDFPU		0x0001	/* FPU was used by this task this quantum (SMP) */
++#define TS_USEDFPU		0x0001	/* FPU was used by this task
++					   this quantum (SMP) */
+ #define TS_COMPAT		0x0002	/* 32bit syscall active */
+-#define TS_POLLING		0x0004	/* true if in idle loop and not sleeping */
++#define TS_POLLING		0x0004	/* true if in idle loop
++					   and not sleeping */
+ 
+ #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
+ 
+diff --git a/include/asm-x86/tlbflush.h b/include/asm-x86/tlbflush.h
+index 3998709..0c0674d 100644
+--- a/include/asm-x86/tlbflush.h
++++ b/include/asm-x86/tlbflush.h
+@@ -32,7 +32,7 @@ static inline void __native_flush_tlb_global(void)
+ 
+ static inline void __native_flush_tlb_single(unsigned long addr)
+ {
+-	__asm__ __volatile__("invlpg (%0)" ::"r" (addr) : "memory");
++	asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
+ }
+ 
+ static inline void __flush_tlb_all(void)
+@@ -134,8 +134,7 @@ void native_flush_tlb_others(const cpumask_t *cpumask, struct mm_struct *mm,
+ #define TLBSTATE_LAZY	2
+ 
+ #ifdef CONFIG_X86_32
+-struct tlb_state
+-{
++struct tlb_state {
+ 	struct mm_struct *active_mm;
+ 	int state;
+ 	char __cacheline_padding[L1_CACHE_BYTES-8];
+diff --git a/include/asm-x86/topology.h b/include/asm-x86/topology.h
+index 8af05a9..2207326 100644
+--- a/include/asm-x86/topology.h
++++ b/include/asm-x86/topology.h
+@@ -32,13 +32,18 @@
+ /* Mappings between logical cpu number and node number */
+ #ifdef CONFIG_X86_32
+ extern int cpu_to_node_map[];
+-
+ #else
++/* Returns the number of the current Node. */
++#define numa_node_id()		(early_cpu_to_node(raw_smp_processor_id()))
++#endif
++
+ DECLARE_PER_CPU(int, x86_cpu_to_node_map);
++
++#ifdef CONFIG_SMP
+ extern int x86_cpu_to_node_map_init[];
+ extern void *x86_cpu_to_node_map_early_ptr;
+-/* Returns the number of the current Node. */
+-#define numa_node_id()		(early_cpu_to_node(raw_smp_processor_id()))
++#else
++#define x86_cpu_to_node_map_early_ptr NULL
+ #endif
+ 
+ extern cpumask_t node_to_cpumask_map[];
+@@ -54,6 +59,8 @@ static inline int cpu_to_node(int cpu)
+ }
+ 
+ #else /* CONFIG_X86_64 */
++
++#ifdef CONFIG_SMP
+ static inline int early_cpu_to_node(int cpu)
+ {
+ 	int *cpu_to_node_map = x86_cpu_to_node_map_early_ptr;
+@@ -65,22 +72,33 @@ static inline int early_cpu_to_node(int cpu)
+ 	else
+ 		return NUMA_NO_NODE;
+ }
++#else
++#define	early_cpu_to_node(cpu)	cpu_to_node(cpu)
++#endif
+ 
+ static inline int cpu_to_node(int cpu)
+ {
+ #ifdef CONFIG_DEBUG_PER_CPU_MAPS
+ 	if (x86_cpu_to_node_map_early_ptr) {
+ 		printk("KERN_NOTICE cpu_to_node(%d): usage too early!\n",
+-			(int)cpu);
++		       (int)cpu);
+ 		dump_stack();
+ 		return ((int *)x86_cpu_to_node_map_early_ptr)[cpu];
+ 	}
+ #endif
+-	if (per_cpu_offset(cpu))
+-		return per_cpu(x86_cpu_to_node_map, cpu);
+-	else
+-		return NUMA_NO_NODE;
++	return per_cpu(x86_cpu_to_node_map, cpu);
+ }
++
++#ifdef	CONFIG_NUMA
++
++/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
++#define node_to_cpumask_ptr(v, node)		\
++		cpumask_t *v = &(node_to_cpumask_map[node])
++
++#define node_to_cpumask_ptr_next(v, node)	\
++			   v = &(node_to_cpumask_map[node])
++#endif
++
+ #endif /* CONFIG_X86_64 */
+ 
+ /*
+@@ -129,17 +147,13 @@ extern unsigned long node_remap_size[];
+ 
+ # define SD_CACHE_NICE_TRIES	2
+ # define SD_IDLE_IDX		2
+-# define SD_NEWIDLE_IDX		0
++# define SD_NEWIDLE_IDX		2
+ # define SD_FORKEXEC_IDX	1
+ 
+ #endif
+ 
+ /* sched_domains SD_NODE_INIT for NUMAQ machines */
+ #define SD_NODE_INIT (struct sched_domain) {		\
+-	.span			= CPU_MASK_NONE,	\
+-	.parent			= NULL,			\
+-	.child			= NULL,			\
+-	.groups			= NULL,			\
+ 	.min_interval		= 8,			\
+ 	.max_interval		= 32,			\
+ 	.busy_factor		= 32,			\
+@@ -157,7 +171,6 @@ extern unsigned long node_remap_size[];
+ 				| SD_WAKE_BALANCE,	\
+ 	.last_balance		= jiffies,		\
+ 	.balance_interval	= 1,			\
+-	.nr_balance_failed	= 0,			\
+ }
+ 
+ #ifdef CONFIG_X86_64_ACPI_NUMA
+@@ -167,10 +180,10 @@ extern int __node_distance(int, int);
+ 
+ #else /* CONFIG_NUMA */
+ 
+-#include <asm-generic/topology.h>
+-
+ #endif
+ 
++#include <asm-generic/topology.h>
++
+ extern cpumask_t cpu_coregroup_map(int cpu);
+ 
+ #ifdef ENABLE_TOPO_DEFINES
+diff --git a/include/asm-x86/trampoline.h b/include/asm-x86/trampoline.h
+new file mode 100644
+index 0000000..b156b08
+--- /dev/null
++++ b/include/asm-x86/trampoline.h
+@@ -0,0 +1,21 @@
++#ifndef __TRAMPOLINE_HEADER
++#define __TRAMPOLINE_HEADER
++
++#ifndef __ASSEMBLY__
++
++/*
++ * Trampoline 80x86 program as an array.
++ */
++extern const unsigned char trampoline_data [];
++extern const unsigned char trampoline_end  [];
++extern unsigned char *trampoline_base;
++
++extern unsigned long init_rsp;
++extern unsigned long initial_code;
++
++#define TRAMPOLINE_BASE 0x6000
++extern unsigned long setup_trampoline(void);
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __TRAMPOLINE_HEADER */
+diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h
+index 7d3e27f..d2d8eb5 100644
+--- a/include/asm-x86/tsc.h
++++ b/include/asm-x86/tsc.h
+@@ -42,7 +42,7 @@ static inline cycles_t vget_cycles(void)
+ 	if (!cpu_has_tsc)
+ 		return 0;
+ #endif
+-	return (cycles_t) __native_read_tsc();
++	return (cycles_t)__native_read_tsc();
+ }
+ 
+ extern void tsc_init(void);
+diff --git a/include/asm-x86/uaccess_32.h b/include/asm-x86/uaccess_32.h
+index fcc570e..8e7595c 100644
+--- a/include/asm-x86/uaccess_32.h
++++ b/include/asm-x86/uaccess_32.h
+@@ -32,7 +32,7 @@
+ #define get_fs()	(current_thread_info()->addr_limit)
+ #define set_fs(x)	(current_thread_info()->addr_limit = (x))
+ 
+-#define segment_eq(a,b)	((a).seg == (b).seg)
++#define segment_eq(a, b)	((a).seg == (b).seg)
+ 
+ /*
+  * movsl can be slow when source and dest are not both 8-byte aligned
+@@ -43,7 +43,9 @@ extern struct movsl_mask {
+ } ____cacheline_aligned_in_smp movsl_mask;
+ #endif
+ 
+-#define __addr_ok(addr) ((unsigned long __force)(addr) < (current_thread_info()->addr_limit.seg))
++#define __addr_ok(addr)					\
++	((unsigned long __force)(addr) <		\
++	 (current_thread_info()->addr_limit.seg))
+ 
+ /*
+  * Test whether a block of memory is a valid user space address.
+@@ -54,13 +56,16 @@ extern struct movsl_mask {
+  *
+  * This needs 33-bit arithmetic. We have a carry...
+  */
+-#define __range_ok(addr,size) ({ \
+-	unsigned long flag,roksum; \
+-	__chk_user_ptr(addr); \
+-	asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
+-		:"=&r" (flag), "=r" (roksum) \
+-		:"1" (addr),"g" ((int)(size)),"rm" (current_thread_info()->addr_limit.seg)); \
+-	flag; })
++#define __range_ok(addr, size)						\
++({									\
++	unsigned long flag, roksum;					\
++	__chk_user_ptr(addr);						\
++	asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0"		\
++	    :"=&r" (flag), "=r" (roksum)				\
++	    :"1" (addr), "g" ((int)(size)),				\
++	    "rm" (current_thread_info()->addr_limit.seg));		\
++	flag;								\
++})
+ 
+ /**
+  * access_ok: - Checks if a user space pointer is valid
+@@ -81,7 +86,7 @@ extern struct movsl_mask {
+  * checks that the pointer is in the user space range - after calling
+  * this function, memory access functions may still return -EFAULT.
+  */
+-#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
++#define access_ok(type, addr, size) (likely(__range_ok(addr, size) == 0))
+ 
+ /*
+  * The exception table consists of pairs of addresses: the first is the
+@@ -96,8 +101,7 @@ extern struct movsl_mask {
+  * on our cache or tlb entries.
+  */
+ 
+-struct exception_table_entry
+-{
++struct exception_table_entry {
+ 	unsigned long insn, fixup;
+ };
+ 
+@@ -122,13 +126,15 @@ extern void __get_user_1(void);
+ extern void __get_user_2(void);
+ extern void __get_user_4(void);
+ 
+-#define __get_user_x(size,ret,x,ptr) \
+-	__asm__ __volatile__("call __get_user_" #size \
+-		:"=a" (ret),"=d" (x) \
+-		:"0" (ptr))
++#define __get_user_x(size, ret, x, ptr)	      \
++	asm volatile("call __get_user_" #size \
++		     :"=a" (ret),"=d" (x)     \
++		     :"0" (ptr))
++
+ 
++/* Careful: we have to cast the result to the type of the pointer
++ * for sign reasons */
+ 
+-/* Careful: we have to cast the result to the type of the pointer for sign reasons */
+ /**
+  * get_user: - Get a simple variable from user space.
+  * @x:   Variable to store result.
+@@ -146,15 +152,24 @@ extern void __get_user_4(void);
+  * Returns zero on success, or -EFAULT on error.
+  * On error, the variable @x is set to zero.
+  */
+-#define get_user(x,ptr)							\
+-({	int __ret_gu;							\
++#define get_user(x, ptr)						\
++({									\
++	int __ret_gu;							\
+ 	unsigned long __val_gu;						\
+ 	__chk_user_ptr(ptr);						\
+-	switch(sizeof (*(ptr))) {					\
+-	case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;		\
+-	case 2:  __get_user_x(2,__ret_gu,__val_gu,ptr); break;		\
+-	case 4:  __get_user_x(4,__ret_gu,__val_gu,ptr); break;		\
+-	default: __get_user_x(X,__ret_gu,__val_gu,ptr); break;		\
++	switch (sizeof(*(ptr))) {					\
++	case 1:								\
++		__get_user_x(1, __ret_gu, __val_gu, ptr);		\
++		break;							\
++	case 2:								\
++		__get_user_x(2, __ret_gu, __val_gu, ptr);		\
++		break;							\
++	case 4:								\
++		__get_user_x(4, __ret_gu, __val_gu, ptr);		\
++		break;							\
++	default:							\
++		__get_user_x(X, __ret_gu, __val_gu, ptr);		\
++		break;							\
+ 	}								\
+ 	(x) = (__typeof__(*(ptr)))__val_gu;				\
+ 	__ret_gu;							\
+@@ -171,11 +186,25 @@ extern void __put_user_2(void);
+ extern void __put_user_4(void);
+ extern void __put_user_8(void);
+ 
+-#define __put_user_1(x, ptr) __asm__ __volatile__("call __put_user_1":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+-#define __put_user_2(x, ptr) __asm__ __volatile__("call __put_user_2":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+-#define __put_user_4(x, ptr) __asm__ __volatile__("call __put_user_4":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+-#define __put_user_8(x, ptr) __asm__ __volatile__("call __put_user_8":"=a" (__ret_pu):"A" ((typeof(*(ptr)))(x)), "c" (ptr))
+-#define __put_user_X(x, ptr) __asm__ __volatile__("call __put_user_X":"=a" (__ret_pu):"c" (ptr))
++#define __put_user_1(x, ptr)					\
++	asm volatile("call __put_user_1" : "=a" (__ret_pu)	\
++		     : "0" ((typeof(*(ptr)))(x)), "c" (ptr))
++
++#define __put_user_2(x, ptr)					\
++	asm volatile("call __put_user_2" : "=a" (__ret_pu)	\
++		     : "0" ((typeof(*(ptr)))(x)), "c" (ptr))
++
++#define __put_user_4(x, ptr)					\
++	asm volatile("call __put_user_4" : "=a" (__ret_pu)	\
++		     : "0" ((typeof(*(ptr)))(x)), "c" (ptr))
++
++#define __put_user_8(x, ptr)					\
++	asm volatile("call __put_user_8" : "=a" (__ret_pu)	\
++		     : "A" ((typeof(*(ptr)))(x)), "c" (ptr))
++
++#define __put_user_X(x, ptr)					\
++	asm volatile("call __put_user_X" : "=a" (__ret_pu)	\
++		     : "c" (ptr))
+ 
+ /**
+  * put_user: - Write a simple value into user space.
+@@ -195,32 +224,43 @@ extern void __put_user_8(void);
+  */
+ #ifdef CONFIG_X86_WP_WORKS_OK
+ 
+-#define put_user(x,ptr)						\
+-({	int __ret_pu;						\
++#define put_user(x, ptr)					\
++({								\
++	int __ret_pu;						\
+ 	__typeof__(*(ptr)) __pu_val;				\
+ 	__chk_user_ptr(ptr);					\
+ 	__pu_val = x;						\
+-	switch(sizeof(*(ptr))) {				\
+-	case 1: __put_user_1(__pu_val, ptr); break;		\
+-	case 2: __put_user_2(__pu_val, ptr); break;		\
+-	case 4: __put_user_4(__pu_val, ptr); break;		\
+-	case 8: __put_user_8(__pu_val, ptr); break;		\
+-	default:__put_user_X(__pu_val, ptr); break;		\
++	switch (sizeof(*(ptr))) {				\
++	case 1:							\
++		__put_user_1(__pu_val, ptr);			\
++		break;						\
++	case 2:							\
++		__put_user_2(__pu_val, ptr);			\
++		break;						\
++	case 4:							\
++		__put_user_4(__pu_val, ptr);			\
++		break;						\
++	case 8:							\
++		__put_user_8(__pu_val, ptr);			\
++		break;						\
++	default:						\
++		__put_user_X(__pu_val, ptr);			\
++		break;						\
+ 	}							\
+ 	__ret_pu;						\
+ })
+ 
+ #else
+-#define put_user(x,ptr)						\
++#define put_user(x, ptr)					\
+ ({								\
+- 	int __ret_pu;						\
+-	__typeof__(*(ptr)) __pus_tmp = x;			\
+-	__ret_pu=0;						\
+-	if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp,		\
+-				sizeof(*(ptr))) != 0))		\
+- 		__ret_pu=-EFAULT;				\
+- 	__ret_pu;						\
+- })
++	int __ret_pu;						\
++	__typeof__(*(ptr))__pus_tmp = x;			\
++	__ret_pu = 0;						\
++	if (unlikely(__copy_to_user_ll(ptr, &__pus_tmp,		\
++				       sizeof(*(ptr))) != 0))	\
++		__ret_pu = -EFAULT;				\
++	__ret_pu;						\
++})
+ 
+ 
+ #endif
+@@ -245,8 +285,8 @@ extern void __put_user_8(void);
+  * Returns zero on success, or -EFAULT on error.
+  * On error, the variable @x is set to zero.
+  */
+-#define __get_user(x,ptr) \
+-  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
++#define __get_user(x, ptr)				\
++	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+ 
+ 
+ /**
+@@ -268,54 +308,62 @@ extern void __put_user_8(void);
+  *
+  * Returns zero on success, or -EFAULT on error.
+  */
+-#define __put_user(x,ptr) \
+-  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++#define __put_user(x, ptr)						\
++	__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+ 
+-#define __put_user_nocheck(x,ptr,size)				\
++#define __put_user_nocheck(x, ptr, size)			\
+ ({								\
+ 	long __pu_err;						\
+-	__put_user_size((x),(ptr),(size),__pu_err,-EFAULT);	\
++	__put_user_size((x), (ptr), (size), __pu_err, -EFAULT);	\
+ 	__pu_err;						\
+ })
+ 
+ 
+-#define __put_user_u64(x, addr, err)				\
+-	__asm__ __volatile__(					\
+-		"1:	movl %%eax,0(%2)\n"			\
+-		"2:	movl %%edx,4(%2)\n"			\
+-		"3:\n"						\
+-		".section .fixup,\"ax\"\n"			\
+-		"4:	movl %3,%0\n"				\
+-		"	jmp 3b\n"				\
+-		".previous\n"					\
+-		_ASM_EXTABLE(1b,4b)				\
+-		_ASM_EXTABLE(2b,4b)				\
+-		: "=r"(err)					\
+-		: "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
++#define __put_user_u64(x, addr, err)					\
++	asm volatile("1:	movl %%eax,0(%2)\n"			\
++		     "2:	movl %%edx,4(%2)\n"			\
++		     "3:\n"						\
++		     ".section .fixup,\"ax\"\n"				\
++		     "4:	movl %3,%0\n"				\
++		     "	jmp 3b\n"					\
++		     ".previous\n"					\
++		     _ASM_EXTABLE(1b, 4b)				\
++		     _ASM_EXTABLE(2b, 4b)				\
++		     : "=r" (err)					\
++		     : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err))
+ 
+ #ifdef CONFIG_X86_WP_WORKS_OK
+ 
+-#define __put_user_size(x,ptr,size,retval,errret)			\
++#define __put_user_size(x, ptr, size, retval, errret)			\
+ do {									\
+ 	retval = 0;							\
+ 	__chk_user_ptr(ptr);						\
+ 	switch (size) {							\
+-	case 1: __put_user_asm(x,ptr,retval,"b","b","iq",errret);break;	\
+-	case 2: __put_user_asm(x,ptr,retval,"w","w","ir",errret);break; \
+-	case 4: __put_user_asm(x,ptr,retval,"l","","ir",errret); break;	\
+-	case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\
+-	  default: __put_user_bad();					\
++	case 1:								\
++		__put_user_asm(x, ptr, retval, "b", "b", "iq", errret);	\
++		break;							\
++	case 2:								\
++		__put_user_asm(x, ptr, retval, "w", "w", "ir", errret);	\
++		break;							\
++	case 4:								\
++		__put_user_asm(x, ptr, retval, "l", "",  "ir", errret);	\
++		break;							\
++	case 8:								\
++		__put_user_u64((__typeof__(*ptr))(x), ptr, retval);	\
++		break;							\
++	default:							\
++		__put_user_bad();					\
+ 	}								\
+ } while (0)
+ 
+ #else
+ 
+-#define __put_user_size(x,ptr,size,retval,errret)			\
++#define __put_user_size(x, ptr, size, retval, errret)			\
+ do {									\
+-	__typeof__(*(ptr)) __pus_tmp = x;				\
++	__typeof__(*(ptr))__pus_tmp = x;				\
+ 	retval = 0;							\
+ 									\
+-	if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0))	\
++	if (unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0))	\
+ 		retval = errret;					\
+ } while (0)
+ 
+@@ -329,65 +377,70 @@ struct __large_struct { unsigned long buf[100]; };
+  * aliasing issues.
+  */
+ #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
+-	__asm__ __volatile__(						\
+-		"1:	mov"itype" %"rtype"1,%2\n"			\
+-		"2:\n"							\
+-		".section .fixup,\"ax\"\n"				\
+-		"3:	movl %3,%0\n"					\
+-		"	jmp 2b\n"					\
+-		".previous\n"						\
+-		_ASM_EXTABLE(1b,3b)					\
+-		: "=r"(err)						\
+-		: ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))
+-
+-
+-#define __get_user_nocheck(x,ptr,size)				\
+-({								\
+-	long __gu_err;						\
+-	unsigned long __gu_val;					\
+-	__get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\
+-	(x) = (__typeof__(*(ptr)))__gu_val;			\
+-	__gu_err;						\
++	asm volatile("1:	mov"itype" %"rtype"1,%2\n"		\
++		     "2:\n"						\
++		     ".section .fixup,\"ax\"\n"				\
++		     "3:	movl %3,%0\n"				\
++		     "	jmp 2b\n"					\
++		     ".previous\n"					\
++		     _ASM_EXTABLE(1b, 3b)				\
++		     : "=r"(err)					\
++		     : ltype (x), "m" (__m(addr)), "i" (errret), "0" (err))
++
++
++#define __get_user_nocheck(x, ptr, size)				\
++({									\
++	long __gu_err;							\
++	unsigned long __gu_val;						\
++	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
++	(x) = (__typeof__(*(ptr)))__gu_val;				\
++	__gu_err;							\
+ })
+ 
+ extern long __get_user_bad(void);
+ 
+-#define __get_user_size(x,ptr,size,retval,errret)			\
++#define __get_user_size(x, ptr, size, retval, errret)			\
+ do {									\
+ 	retval = 0;							\
+ 	__chk_user_ptr(ptr);						\
+ 	switch (size) {							\
+-	case 1: __get_user_asm(x,ptr,retval,"b","b","=q",errret);break;	\
+-	case 2: __get_user_asm(x,ptr,retval,"w","w","=r",errret);break;	\
+-	case 4: __get_user_asm(x,ptr,retval,"l","","=r",errret);break;	\
+-	default: (x) = __get_user_bad();				\
++	case 1:								\
++		__get_user_asm(x, ptr, retval, "b", "b", "=q", errret);	\
++		break;							\
++	case 2:								\
++		__get_user_asm(x, ptr, retval, "w", "w", "=r", errret);	\
++		break;							\
++	case 4:								\
++		__get_user_asm(x, ptr, retval, "l", "", "=r", errret);	\
++		break;							\
++	default:							\
++		(x) = __get_user_bad();					\
+ 	}								\
+ } while (0)
+ 
+ #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
+-	__asm__ __volatile__(						\
+-		"1:	mov"itype" %2,%"rtype"1\n"			\
+-		"2:\n"							\
+-		".section .fixup,\"ax\"\n"				\
+-		"3:	movl %3,%0\n"					\
+-		"	xor"itype" %"rtype"1,%"rtype"1\n"		\
+-		"	jmp 2b\n"					\
+-		".previous\n"						\
+-		_ASM_EXTABLE(1b,3b)					\
+-		: "=r"(err), ltype (x)					\
+-		: "m"(__m(addr)), "i"(errret), "0"(err))
+-
+-
+-unsigned long __must_check __copy_to_user_ll(void __user *to,
+-				const void *from, unsigned long n);
+-unsigned long __must_check __copy_from_user_ll(void *to,
+-				const void __user *from, unsigned long n);
+-unsigned long __must_check __copy_from_user_ll_nozero(void *to,
+-				const void __user *from, unsigned long n);
+-unsigned long __must_check __copy_from_user_ll_nocache(void *to,
+-				const void __user *from, unsigned long n);
+-unsigned long __must_check __copy_from_user_ll_nocache_nozero(void *to,
+-				const void __user *from, unsigned long n);
++	asm volatile("1:	mov"itype" %2,%"rtype"1\n"		\
++		     "2:\n"						\
++		     ".section .fixup,\"ax\"\n"				\
++		     "3:	movl %3,%0\n"				\
++		     "	xor"itype" %"rtype"1,%"rtype"1\n"		\
++		     "	jmp 2b\n"					\
++		     ".previous\n"					\
++		     _ASM_EXTABLE(1b, 3b)				\
++		     : "=r" (err), ltype (x)				\
++		     : "m" (__m(addr)), "i" (errret), "0" (err))
++
++
++unsigned long __must_check __copy_to_user_ll
++		(void __user *to, const void *from, unsigned long n);
++unsigned long __must_check __copy_from_user_ll
++		(void *to, const void __user *from, unsigned long n);
++unsigned long __must_check __copy_from_user_ll_nozero
++		(void *to, const void __user *from, unsigned long n);
++unsigned long __must_check __copy_from_user_ll_nocache
++		(void *to, const void __user *from, unsigned long n);
++unsigned long __must_check __copy_from_user_ll_nocache_nozero
++		(void *to, const void __user *from, unsigned long n);
+ 
+ /**
+  * __copy_to_user_inatomic: - Copy a block of data into user space, with less checking.
+@@ -416,13 +469,16 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
+ 
+ 		switch (n) {
+ 		case 1:
+-			__put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1);
++			__put_user_size(*(u8 *)from, (u8 __user *)to,
++					1, ret, 1);
+ 			return ret;
+ 		case 2:
+-			__put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2);
++			__put_user_size(*(u16 *)from, (u16 __user *)to,
++					2, ret, 2);
+ 			return ret;
+ 		case 4:
+-			__put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4);
++			__put_user_size(*(u32 *)from, (u32 __user *)to,
++					4, ret, 4);
+ 			return ret;
+ 		}
+ 	}
+@@ -545,19 +601,21 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
+ }
+ 
+ static __always_inline unsigned long
+-__copy_from_user_inatomic_nocache(void *to, const void __user *from, unsigned long n)
++__copy_from_user_inatomic_nocache(void *to, const void __user *from,
++				  unsigned long n)
+ {
+        return __copy_from_user_ll_nocache_nozero(to, from, n);
+ }
+ 
+ unsigned long __must_check copy_to_user(void __user *to,
+-				const void *from, unsigned long n);
++					const void *from, unsigned long n);
+ unsigned long __must_check copy_from_user(void *to,
+-				const void __user *from, unsigned long n);
++					  const void __user *from,
++					  unsigned long n);
+ long __must_check strncpy_from_user(char *dst, const char __user *src,
+-				long count);
++				    long count);
+ long __must_check __strncpy_from_user(char *dst,
+-				const char __user *src, long count);
++				      const char __user *src, long count);
+ 
+ /**
+  * strlen_user: - Get the size of a string in user space.
+diff --git a/include/asm-x86/uaccess_64.h b/include/asm-x86/uaccess_64.h
+index b87eb4b..b8a2f43 100644
+--- a/include/asm-x86/uaccess_64.h
++++ b/include/asm-x86/uaccess_64.h
+@@ -29,23 +29,27 @@
+ #define get_fs()	(current_thread_info()->addr_limit)
+ #define set_fs(x)	(current_thread_info()->addr_limit = (x))
+ 
+-#define segment_eq(a,b)	((a).seg == (b).seg)
++#define segment_eq(a, b)	((a).seg == (b).seg)
+ 
+-#define __addr_ok(addr) (!((unsigned long)(addr) & (current_thread_info()->addr_limit.seg)))
++#define __addr_ok(addr) (!((unsigned long)(addr) &			\
++			   (current_thread_info()->addr_limit.seg)))
+ 
+ /*
+  * Uhhuh, this needs 65-bit arithmetic. We have a carry..
+  */
+-#define __range_not_ok(addr,size) ({ \
+-	unsigned long flag,roksum; \
+-	__chk_user_ptr(addr); \
+-	asm("# range_ok\n\r" \
+-		"addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0"  \
+-		:"=&r" (flag), "=r" (roksum) \
+-		:"1" (addr),"g" ((long)(size)),"g" (current_thread_info()->addr_limit.seg)); \
+-	flag; })
++#define __range_not_ok(addr, size)					\
++({									\
++	unsigned long flag, roksum;					\
++	__chk_user_ptr(addr);						\
++	asm("# range_ok\n\r"						\
++	    "addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0"		\
++	    : "=&r" (flag), "=r" (roksum)				\
++	    : "1" (addr), "g" ((long)(size)),				\
++	      "g" (current_thread_info()->addr_limit.seg));		\
++	flag;								\
++})
+ 
+-#define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0)
++#define access_ok(type, addr, size) (__range_not_ok(addr, size) == 0)
+ 
+ /*
+  * The exception table consists of pairs of addresses: the first is the
+@@ -60,8 +64,7 @@
+  * on our cache or tlb entries.
+  */
+ 
+-struct exception_table_entry
+-{
++struct exception_table_entry {
+ 	unsigned long insn, fixup;
+ };
+ 
+@@ -84,23 +87,36 @@ extern int fixup_exception(struct pt_regs *regs);
+  * accesses to the same area of user memory).
+  */
+ 
+-#define __get_user_x(size,ret,x,ptr) \
+-	asm volatile("call __get_user_" #size \
+-		:"=a" (ret),"=d" (x) \
+-		:"c" (ptr) \
+-		:"r8")
++#define __get_user_x(size, ret, x, ptr)		      \
++	asm volatile("call __get_user_" #size	      \
++		     : "=a" (ret),"=d" (x)	      \
++		     : "c" (ptr)		      \
++		     : "r8")
++
++/* Careful: we have to cast the result to the type of the pointer
++ * for sign reasons */
+ 
+-/* Careful: we have to cast the result to the type of the pointer for sign reasons */
+-#define get_user(x,ptr)							\
+-({	unsigned long __val_gu;						\
+-	int __ret_gu; 							\
++#define get_user(x, ptr)						\
++({									\
++	unsigned long __val_gu;						\
++	int __ret_gu;							\
+ 	__chk_user_ptr(ptr);						\
+-	switch(sizeof (*(ptr))) {					\
+-	case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;		\
+-	case 2:  __get_user_x(2,__ret_gu,__val_gu,ptr); break;		\
+-	case 4:  __get_user_x(4,__ret_gu,__val_gu,ptr); break;		\
+-	case 8:  __get_user_x(8,__ret_gu,__val_gu,ptr); break;		\
+-	default: __get_user_bad(); break;				\
++	switch (sizeof(*(ptr))) {					\
++	case 1:								\
++		__get_user_x(1, __ret_gu, __val_gu, ptr);		\
++		break;							\
++	case 2:								\
++		__get_user_x(2, __ret_gu, __val_gu, ptr);		\
++		break;							\
++	case 4:								\
++		__get_user_x(4, __ret_gu, __val_gu, ptr);		\
++		break;							\
++	case 8:								\
++		__get_user_x(8, __ret_gu, __val_gu, ptr);		\
++		break;							\
++	default:							\
++		__get_user_bad();					\
++		break;							\
+ 	}								\
+ 	(x) = (__force typeof(*(ptr)))__val_gu;				\
+ 	__ret_gu;							\
+@@ -112,55 +128,73 @@ extern void __put_user_4(void);
+ extern void __put_user_8(void);
+ extern void __put_user_bad(void);
+ 
+-#define __put_user_x(size,ret,x,ptr)					\
+-	asm volatile("call __put_user_" #size			\
+-		:"=a" (ret)						\
+-		:"c" (ptr),"d" (x)					\
+-		:"r8")
++#define __put_user_x(size, ret, x, ptr)					\
++	asm volatile("call __put_user_" #size				\
++		     :"=a" (ret)					\
++		     :"c" (ptr),"d" (x)					\
++		     :"r8")
+ 
+-#define put_user(x,ptr)							\
+-  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++#define put_user(x, ptr)						\
++	__put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+ 
+-#define __get_user(x,ptr) \
+-  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+-#define __put_user(x,ptr) \
+-  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++#define __get_user(x, ptr)						\
++	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
++#define __put_user(x, ptr)						\
++	__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+ 
+ #define __get_user_unaligned __get_user
+ #define __put_user_unaligned __put_user
+ 
+-#define __put_user_nocheck(x,ptr,size)			\
++#define __put_user_nocheck(x, ptr, size)		\
+ ({							\
+ 	int __pu_err;					\
+-	__put_user_size((x),(ptr),(size),__pu_err);	\
++	__put_user_size((x), (ptr), (size), __pu_err);	\
+ 	__pu_err;					\
+ })
+ 
+ 
+-#define __put_user_check(x,ptr,size)			\
+-({							\
+-	int __pu_err;					\
+-	typeof(*(ptr)) __user *__pu_addr = (ptr);	\
+-	switch (size) { 				\
+-	case 1: __put_user_x(1,__pu_err,x,__pu_addr); break;	\
+-	case 2: __put_user_x(2,__pu_err,x,__pu_addr); break;	\
+-	case 4: __put_user_x(4,__pu_err,x,__pu_addr); break;	\
+-	case 8: __put_user_x(8,__pu_err,x,__pu_addr); break;	\
+-	default: __put_user_bad();			\
+-	}						\
+-	__pu_err;					\
++#define __put_user_check(x, ptr, size)				\
++({								\
++	int __pu_err;						\
++	typeof(*(ptr)) __user *__pu_addr = (ptr);		\
++	switch (size) {						\
++	case 1:							\
++		__put_user_x(1, __pu_err, x, __pu_addr);	\
++		break;						\
++	case 2:							\
++		__put_user_x(2, __pu_err, x, __pu_addr);	\
++		break;						\
++	case 4:							\
++		__put_user_x(4, __pu_err, x, __pu_addr);	\
++		break;						\
++	case 8:							\
++		__put_user_x(8, __pu_err, x, __pu_addr);	\
++		break;						\
++	default:						\
++		__put_user_bad();				\
++	}							\
++	__pu_err;						\
+ })
+ 
+-#define __put_user_size(x,ptr,size,retval)				\
++#define __put_user_size(x, ptr, size, retval)				\
+ do {									\
+ 	retval = 0;							\
+ 	__chk_user_ptr(ptr);						\
+ 	switch (size) {							\
+-	  case 1: __put_user_asm(x,ptr,retval,"b","b","iq",-EFAULT); break;\
+-	  case 2: __put_user_asm(x,ptr,retval,"w","w","ir",-EFAULT); break;\
+-	  case 4: __put_user_asm(x,ptr,retval,"l","k","ir",-EFAULT); break;\
+-	  case 8: __put_user_asm(x,ptr,retval,"q","","Zr",-EFAULT); break;\
+-	  default: __put_user_bad();					\
++	case 1:								\
++		__put_user_asm(x, ptr, retval, "b", "b", "iq", -EFAULT);\
++		break;							\
++	case 2:								\
++		__put_user_asm(x, ptr, retval, "w", "w", "ir", -EFAULT);\
++		break;							\
++	case 4:								\
++		__put_user_asm(x, ptr, retval, "l", "k", "ir", -EFAULT);\
++		break;							\
++	case 8:								\
++		__put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT);	\
++		break;							\
++	default:							\
++		__put_user_bad();					\
+ 	}								\
+ } while (0)
+ 
+@@ -174,23 +208,22 @@ struct __large_struct { unsigned long buf[100]; };
+  * aliasing issues.
+  */
+ #define __put_user_asm(x, addr, err, itype, rtype, ltype, errno)	\
+-	asm volatile(					\
+-		"1:	mov"itype" %"rtype"1,%2\n"		\
+-		"2:\n"						\
+-		".section .fixup,\"ax\"\n"			\
+-		"3:	mov %3,%0\n"				\
+-		"	jmp 2b\n"				\
+-		".previous\n"					\
+-		_ASM_EXTABLE(1b,3b)				\
+-		: "=r"(err)					\
+-		: ltype (x), "m"(__m(addr)), "i"(errno), "0"(err))
+-
+-
+-#define __get_user_nocheck(x,ptr,size)				\
++	asm volatile("1:	mov"itype" %"rtype"1,%2\n"		\
++		     "2:\n"						\
++		     ".section .fixup, \"ax\"\n"			\
++		     "3:	mov %3,%0\n"				\
++		     "	jmp 2b\n"					\
++		     ".previous\n"					\
++		     _ASM_EXTABLE(1b, 3b)				\
++		     : "=r"(err)					\
++		     : ltype (x), "m" (__m(addr)), "i" (errno), "0" (err))
++
++
++#define __get_user_nocheck(x, ptr, size)			\
+ ({								\
+ 	int __gu_err;						\
+ 	unsigned long __gu_val;					\
+-	__get_user_size(__gu_val,(ptr),(size),__gu_err);	\
++	__get_user_size(__gu_val, (ptr), (size), __gu_err);	\
+ 	(x) = (__force typeof(*(ptr)))__gu_val;			\
+ 	__gu_err;						\
+ })
+@@ -201,31 +234,39 @@ extern int __get_user_4(void);
+ extern int __get_user_8(void);
+ extern int __get_user_bad(void);
+ 
+-#define __get_user_size(x,ptr,size,retval)				\
++#define __get_user_size(x, ptr, size, retval)				\
+ do {									\
+ 	retval = 0;							\
+ 	__chk_user_ptr(ptr);						\
+ 	switch (size) {							\
+-	  case 1: __get_user_asm(x,ptr,retval,"b","b","=q",-EFAULT); break;\
+-	  case 2: __get_user_asm(x,ptr,retval,"w","w","=r",-EFAULT); break;\
+-	  case 4: __get_user_asm(x,ptr,retval,"l","k","=r",-EFAULT); break;\
+-	  case 8: __get_user_asm(x,ptr,retval,"q","","=r",-EFAULT); break;\
+-	  default: (x) = __get_user_bad();				\
++	case 1:								\
++		__get_user_asm(x, ptr, retval, "b", "b", "=q", -EFAULT);\
++		break;							\
++	case 2:								\
++		__get_user_asm(x, ptr, retval, "w", "w", "=r", -EFAULT);\
++		break;							\
++	case 4:								\
++		__get_user_asm(x, ptr, retval, "l", "k", "=r", -EFAULT);\
++		break;							\
++	case 8:								\
++		__get_user_asm(x, ptr, retval, "q", "", "=r", -EFAULT);	\
++		break;							\
++	default:							\
++		(x) = __get_user_bad();					\
+ 	}								\
+ } while (0)
+ 
+ #define __get_user_asm(x, addr, err, itype, rtype, ltype, errno)	\
+-	asm volatile(					\
+-		"1:	mov"itype" %2,%"rtype"1\n"		\
+-		"2:\n"						\
+-		".section .fixup,\"ax\"\n"			\
+-		"3:	mov %3,%0\n"				\
+-		"	xor"itype" %"rtype"1,%"rtype"1\n"	\
+-		"	jmp 2b\n"				\
+-		".previous\n"					\
+-		_ASM_EXTABLE(1b,3b)				\
+-		: "=r"(err), ltype (x)				\
+-		: "m"(__m(addr)), "i"(errno), "0"(err))
++	asm volatile("1:	mov"itype" %2,%"rtype"1\n"		\
++		     "2:\n"						\
++		     ".section .fixup, \"ax\"\n"			\
++		     "3:	mov %3,%0\n"				\
++		     "	xor"itype" %"rtype"1,%"rtype"1\n"		\
++		     "	jmp 2b\n"					\
++		     ".previous\n"					\
++		     _ASM_EXTABLE(1b, 3b)				\
++		     : "=r" (err), ltype (x)				\
++		     : "m" (__m(addr)), "i"(errno), "0"(err))
+ 
+ /*
+  * Copy To/From Userspace
+@@ -244,110 +285,142 @@ copy_in_user(void __user *to, const void __user *from, unsigned len);
+ 
+ static __always_inline __must_check
+ int __copy_from_user(void *dst, const void __user *src, unsigned size)
+-{ 
++{
+ 	int ret = 0;
+ 	if (!__builtin_constant_p(size))
+-		return copy_user_generic(dst,(__force void *)src,size);
+-	switch (size) { 
+-	case 1:__get_user_asm(*(u8*)dst,(u8 __user *)src,ret,"b","b","=q",1); 
++		return copy_user_generic(dst, (__force void *)src, size);
++	switch (size) {
++	case 1:__get_user_asm(*(u8 *)dst, (u8 __user *)src,
++			      ret, "b", "b", "=q", 1);
+ 		return ret;
+-	case 2:__get_user_asm(*(u16*)dst,(u16 __user *)src,ret,"w","w","=r",2);
++	case 2:__get_user_asm(*(u16 *)dst, (u16 __user *)src,
++			      ret, "w", "w", "=r", 2);
+ 		return ret;
+-	case 4:__get_user_asm(*(u32*)dst,(u32 __user *)src,ret,"l","k","=r",4);
++	case 4:__get_user_asm(*(u32 *)dst, (u32 __user *)src,
++			      ret, "l", "k", "=r", 4);
++		return ret;
++	case 8:__get_user_asm(*(u64 *)dst, (u64 __user *)src,
++			      ret, "q", "", "=r", 8);
+ 		return ret;
+-	case 8:__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",8);
+-		return ret; 
+ 	case 10:
+-	       	__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16);
+-		if (unlikely(ret)) return ret;
+-		__get_user_asm(*(u16*)(8+(char*)dst),(u16 __user *)(8+(char __user *)src),ret,"w","w","=r",2);
+-		return ret; 
++		__get_user_asm(*(u64 *)dst, (u64 __user *)src,
++			       ret, "q", "", "=r", 16);
++		if (unlikely(ret))
++			return ret;
++		__get_user_asm(*(u16 *)(8 + (char *)dst),
++			       (u16 __user *)(8 + (char __user *)src),
++			       ret, "w", "w", "=r", 2);
++		return ret;
+ 	case 16:
+-		__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16);
+-		if (unlikely(ret)) return ret;
+-		__get_user_asm(*(u64*)(8+(char*)dst),(u64 __user *)(8+(char __user *)src),ret,"q","","=r",8);
+-		return ret; 
++		__get_user_asm(*(u64 *)dst, (u64 __user *)src,
++			       ret, "q", "", "=r", 16);
++		if (unlikely(ret))
++			return ret;
++		__get_user_asm(*(u64 *)(8 + (char *)dst),
++			       (u64 __user *)(8 + (char __user *)src),
++			       ret, "q", "", "=r", 8);
++		return ret;
+ 	default:
+-		return copy_user_generic(dst,(__force void *)src,size); 
++		return copy_user_generic(dst, (__force void *)src, size);
+ 	}
+-}	
++}
+ 
+ static __always_inline __must_check
+ int __copy_to_user(void __user *dst, const void *src, unsigned size)
+-{ 
++{
+ 	int ret = 0;
+ 	if (!__builtin_constant_p(size))
+-		return copy_user_generic((__force void *)dst,src,size);
+-	switch (size) { 
+-	case 1:__put_user_asm(*(u8*)src,(u8 __user *)dst,ret,"b","b","iq",1); 
++		return copy_user_generic((__force void *)dst, src, size);
++	switch (size) {
++	case 1:__put_user_asm(*(u8 *)src, (u8 __user *)dst,
++			      ret, "b", "b", "iq", 1);
+ 		return ret;
+-	case 2:__put_user_asm(*(u16*)src,(u16 __user *)dst,ret,"w","w","ir",2);
++	case 2:__put_user_asm(*(u16 *)src, (u16 __user *)dst,
++			      ret, "w", "w", "ir", 2);
+ 		return ret;
+-	case 4:__put_user_asm(*(u32*)src,(u32 __user *)dst,ret,"l","k","ir",4);
++	case 4:__put_user_asm(*(u32 *)src, (u32 __user *)dst,
++			      ret, "l", "k", "ir", 4);
++		return ret;
++	case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst,
++			      ret, "q", "", "ir", 8);
+ 		return ret;
+-	case 8:__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",8);
+-		return ret; 
+ 	case 10:
+-		__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",10);
+-		if (unlikely(ret)) return ret;
++		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
++			       ret, "q", "", "ir", 10);
++		if (unlikely(ret))
++			return ret;
+ 		asm("":::"memory");
+-		__put_user_asm(4[(u16*)src],4+(u16 __user *)dst,ret,"w","w","ir",2);
+-		return ret; 
++		__put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst,
++			       ret, "w", "w", "ir", 2);
++		return ret;
+ 	case 16:
+-		__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",16);
+-		if (unlikely(ret)) return ret;
++		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
++			       ret, "q", "", "ir", 16);
++		if (unlikely(ret))
++			return ret;
+ 		asm("":::"memory");
+-		__put_user_asm(1[(u64*)src],1+(u64 __user *)dst,ret,"q","","ir",8);
+-		return ret; 
++		__put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
++			       ret, "q", "", "ir", 8);
++		return ret;
+ 	default:
+-		return copy_user_generic((__force void *)dst,src,size); 
++		return copy_user_generic((__force void *)dst, src, size);
+ 	}
+-}	
++}
+ 
+ static __always_inline __must_check
+ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
+-{ 
++{
+ 	int ret = 0;
+ 	if (!__builtin_constant_p(size))
+-		return copy_user_generic((__force void *)dst,(__force void *)src,size);
+-	switch (size) { 
+-	case 1: { 
++		return copy_user_generic((__force void *)dst,
++					 (__force void *)src, size);
++	switch (size) {
++	case 1: {
+ 		u8 tmp;
+-		__get_user_asm(tmp,(u8 __user *)src,ret,"b","b","=q",1); 
++		__get_user_asm(tmp, (u8 __user *)src,
++			       ret, "b", "b", "=q", 1);
+ 		if (likely(!ret))
+-			__put_user_asm(tmp,(u8 __user *)dst,ret,"b","b","iq",1); 
++			__put_user_asm(tmp, (u8 __user *)dst,
++				       ret, "b", "b", "iq", 1);
+ 		return ret;
+ 	}
+-	case 2: { 
++	case 2: {
+ 		u16 tmp;
+-		__get_user_asm(tmp,(u16 __user *)src,ret,"w","w","=r",2); 
++		__get_user_asm(tmp, (u16 __user *)src,
++			       ret, "w", "w", "=r", 2);
+ 		if (likely(!ret))
+-			__put_user_asm(tmp,(u16 __user *)dst,ret,"w","w","ir",2); 
++			__put_user_asm(tmp, (u16 __user *)dst,
++				       ret, "w", "w", "ir", 2);
+ 		return ret;
+ 	}
+ 
+-	case 4: { 
++	case 4: {
+ 		u32 tmp;
+-		__get_user_asm(tmp,(u32 __user *)src,ret,"l","k","=r",4); 
++		__get_user_asm(tmp, (u32 __user *)src,
++			       ret, "l", "k", "=r", 4);
+ 		if (likely(!ret))
+-			__put_user_asm(tmp,(u32 __user *)dst,ret,"l","k","ir",4); 
++			__put_user_asm(tmp, (u32 __user *)dst,
++				       ret, "l", "k", "ir", 4);
+ 		return ret;
+ 	}
+-	case 8: { 
++	case 8: {
+ 		u64 tmp;
+-		__get_user_asm(tmp,(u64 __user *)src,ret,"q","","=r",8); 
++		__get_user_asm(tmp, (u64 __user *)src,
++			       ret, "q", "", "=r", 8);
+ 		if (likely(!ret))
+-			__put_user_asm(tmp,(u64 __user *)dst,ret,"q","","ir",8); 
++			__put_user_asm(tmp, (u64 __user *)dst,
++				       ret, "q", "", "ir", 8);
+ 		return ret;
+ 	}
+ 	default:
+-		return copy_user_generic((__force void *)dst,(__force void *)src,size); 
++		return copy_user_generic((__force void *)dst,
++					 (__force void *)src, size);
+ 	}
+-}	
++}
+ 
+-__must_check long 
++__must_check long
+ strncpy_from_user(char *dst, const char __user *src, long count);
+-__must_check long 
++__must_check long
+ __strncpy_from_user(char *dst, const char __user *src, long count);
+ __must_check long strnlen_user(const char __user *str, long n);
+ __must_check long __strnlen_user(const char __user *str, long n);
+@@ -355,7 +428,8 @@ __must_check long strlen_user(const char __user *str);
+ __must_check unsigned long clear_user(void __user *mem, unsigned long len);
+ __must_check unsigned long __clear_user(void __user *mem, unsigned long len);
+ 
+-__must_check long __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size);
++__must_check long __copy_from_user_inatomic(void *dst, const void __user *src,
++					    unsigned size);
+ 
+ static __must_check __always_inline int
+ __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
+@@ -364,15 +438,19 @@ __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
+ }
+ 
+ #define ARCH_HAS_NOCACHE_UACCESS 1
+-extern long __copy_user_nocache(void *dst, const void __user *src, unsigned size, int zerorest);
++extern long __copy_user_nocache(void *dst, const void __user *src,
++				unsigned size, int zerorest);
+ 
+-static inline int __copy_from_user_nocache(void *dst, const void __user *src, unsigned size)
++static inline int __copy_from_user_nocache(void *dst, const void __user *src,
++					   unsigned size)
+ {
+ 	might_sleep();
+ 	return __copy_user_nocache(dst, src, size, 1);
+ }
+ 
+-static inline int __copy_from_user_inatomic_nocache(void *dst, const void __user *src, unsigned size)
++static inline int __copy_from_user_inatomic_nocache(void *dst,
++						    const void __user *src,
++						    unsigned size)
+ {
+ 	return __copy_user_nocache(dst, src, size, 0);
+ }
+diff --git a/include/asm-x86/unaligned.h b/include/asm-x86/unaligned.h
+index 913598d..d270ffe 100644
+--- a/include/asm-x86/unaligned.h
++++ b/include/asm-x86/unaligned.h
+@@ -32,6 +32,6 @@
+  *
+  * Note that unaligned accesses can be very expensive on some architectures.
+  */
+-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
++#define put_unaligned(val, ptr) ((void)(*(ptr) = (val)))
+ 
+ #endif /* _ASM_X86_UNALIGNED_H */
+diff --git a/include/asm-x86/unistd_32.h b/include/asm-x86/unistd_32.h
+index 984123a..8317d94 100644
+--- a/include/asm-x86/unistd_32.h
++++ b/include/asm-x86/unistd_32.h
+@@ -81,7 +81,7 @@
+ #define __NR_sigpending		 73
+ #define __NR_sethostname	 74
+ #define __NR_setrlimit		 75
+-#define __NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
++#define __NR_getrlimit		 76   /* Back compatible 2Gig limited rlimit */
+ #define __NR_getrusage		 77
+ #define __NR_gettimeofday	 78
+ #define __NR_settimeofday	 79
+diff --git a/include/asm-x86/unistd_64.h b/include/asm-x86/unistd_64.h
+index 3883ceb..fe26e36 100644
+--- a/include/asm-x86/unistd_64.h
++++ b/include/asm-x86/unistd_64.h
+@@ -2,7 +2,7 @@
+ #define _ASM_X86_64_UNISTD_H_
+ 
+ #ifndef __SYSCALL
+-#define __SYSCALL(a,b)
++#define __SYSCALL(a, b)
+ #endif
+ 
+ /*
+diff --git a/include/asm-x86/user32.h b/include/asm-x86/user32.h
+index f769872..a3d9100 100644
+--- a/include/asm-x86/user32.h
++++ b/include/asm-x86/user32.h
+@@ -1,7 +1,8 @@
+ #ifndef USER32_H
+ #define USER32_H 1
+ 
+-/* IA32 compatible user structures for ptrace. These should be used for 32bit coredumps too. */
++/* IA32 compatible user structures for ptrace.
++ * These should be used for 32bit coredumps too. */
+ 
+ struct user_i387_ia32_struct {
+ 	u32	cwd;
+@@ -42,9 +43,9 @@ struct user_regs_struct32 {
+ };
+ 
+ struct user32 {
+-  struct user_regs_struct32 regs;		/* Where the registers are actually stored */
++  struct user_regs_struct32 regs; /* Where the registers are actually stored */
+   int u_fpvalid;		/* True if math co-processor being used. */
+-                                /* for this mess. Not yet used. */
++				/* for this mess. Not yet used. */
+   struct user_i387_ia32_struct i387;	/* Math Co-processor registers. */
+ /* The rest of this junk is to help gdb figure out what goes where */
+   __u32 u_tsize;	/* Text segment size (pages). */
+diff --git a/include/asm-x86/user_32.h b/include/asm-x86/user_32.h
+index 6157da6..d6e51ed 100644
+--- a/include/asm-x86/user_32.h
++++ b/include/asm-x86/user_32.h
+@@ -100,10 +100,10 @@ struct user_regs_struct {
+ struct user{
+ /* We start with the registers, to mimic the way that "memory" is returned
+    from the ptrace(3,...) function.  */
+-  struct user_regs_struct regs;		/* Where the registers are actually stored */
++  struct user_regs_struct regs;	/* Where the registers are actually stored */
+ /* ptrace does not yet supply these.  Someday.... */
+   int u_fpvalid;		/* True if math co-processor being used. */
+-                                /* for this mess. Not yet used. */
++				/* for this mess. Not yet used. */
+   struct user_i387_struct i387;	/* Math Co-processor registers. */
+ /* The rest of this junk is to help gdb figure out what goes where */
+   unsigned long int u_tsize;	/* Text segment size (pages). */
+@@ -118,7 +118,7 @@ struct user{
+   int reserved;			/* No longer used */
+   unsigned long u_ar0;		/* Used by gdb to help find the values for */
+ 				/* the registers. */
+-  struct user_i387_struct* u_fpstate;	/* Math Co-processor pointer. */
++  struct user_i387_struct *u_fpstate;	/* Math Co-processor pointer. */
+   unsigned long magic;		/* To uniquely identify a core file */
+   char u_comm[32];		/* User command that was responsible */
+   int u_debugreg[8];
+diff --git a/include/asm-x86/user_64.h b/include/asm-x86/user_64.h
+index 9636164..6037b63 100644
+--- a/include/asm-x86/user_64.h
++++ b/include/asm-x86/user_64.h
+@@ -45,12 +45,13 @@
+  */
+ 
+ /* This matches the 64bit FXSAVE format as defined by AMD. It is the same
+-   as the 32bit format defined by Intel, except that the selector:offset pairs for
+-   data and eip are replaced with flat 64bit pointers. */
++   as the 32bit format defined by Intel, except that the selector:offset pairs
++   for data and eip are replaced with flat 64bit pointers. */
+ struct user_i387_struct {
+ 	unsigned short	cwd;
+ 	unsigned short	swd;
+-	unsigned short	twd; /* Note this is not the same as the 32bit/x87/FSAVE twd */
++	unsigned short	twd;	/* Note this is not the same as
++				   the 32bit/x87/FSAVE twd */
+ 	unsigned short	fop;
+ 	__u64	rip;
+ 	__u64	rdp;
+@@ -97,13 +98,14 @@ struct user_regs_struct {
+ /* When the kernel dumps core, it starts by dumping the user struct -
+    this will be used by gdb to figure out where the data and stack segments
+    are within the file, and what virtual addresses to use. */
+-struct user{
++
++struct user {
+ /* We start with the registers, to mimic the way that "memory" is returned
+    from the ptrace(3,...) function.  */
+-  struct user_regs_struct regs;		/* Where the registers are actually stored */
++  struct user_regs_struct regs;	/* Where the registers are actually stored */
+ /* ptrace does not yet supply these.  Someday.... */
+   int u_fpvalid;		/* True if math co-processor being used. */
+-                                /* for this mess. Not yet used. */
++				/* for this mess. Not yet used. */
+   int pad0;
+   struct user_i387_struct i387;	/* Math Co-processor registers. */
+ /* The rest of this junk is to help gdb figure out what goes where */
+@@ -120,7 +122,7 @@ struct user{
+   int pad1;
+   unsigned long u_ar0;		/* Used by gdb to help find the values for */
+ 				/* the registers. */
+-  struct user_i387_struct* u_fpstate;	/* Math Co-processor pointer. */
++  struct user_i387_struct *u_fpstate;	/* Math Co-processor pointer. */
+   unsigned long magic;		/* To uniquely identify a core file */
+   char u_comm[32];		/* User command that was responsible */
+   unsigned long u_debugreg[8];
+diff --git a/include/asm-x86/uv/uv_hub.h b/include/asm-x86/uv/uv_hub.h
+new file mode 100644
+index 0000000..26b9240
+--- /dev/null
++++ b/include/asm-x86/uv/uv_hub.h
+@@ -0,0 +1,284 @@
++/*
++ * 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.
++ *
++ * SGI UV architectural definitions
++ *
++ * Copyright (C) 2007 Silicon Graphics, Inc. All rights reserved.
++ */
++
++#ifndef __ASM_X86_UV_HUB_H__
++#define __ASM_X86_UV_HUB_H__
++
++#include <linux/numa.h>
++#include <linux/percpu.h>
++#include <asm/types.h>
++#include <asm/percpu.h>
++
++
++/*
++ * Addressing Terminology
++ *
++ * 	NASID - network ID of a router, Mbrick or Cbrick. Nasid values of
++ * 		routers always have low bit of 1, C/MBricks have low bit
++ * 		equal to 0. Most addressing macros that target UV hub chips
++ * 		right shift the NASID by 1 to exclude the always-zero bit.
++ *
++ *	SNASID - NASID right shifted by 1 bit.
++ *
++ *
++ *  Memory/UV-HUB Processor Socket Address Format:
++ *  +--------+---------------+---------------------+
++ *  |00..0000|    SNASID     |      NodeOffset     |
++ *  +--------+---------------+---------------------+
++ *           <--- N bits --->|<--------M bits ----->
++ *
++ *	M number of node offset bits (35 .. 40)
++ *	N number of SNASID bits (0 .. 10)
++ *
++ *		Note: M + N cannot currently exceed 44 (x86_64) or 46 (IA64).
++ *		The actual values are configuration dependent and are set at
++ *		boot time
++ *
++ * APICID format
++ * 	NOTE!!!!!! This is the current format of the APICID. However, code
++ * 	should assume that this will change in the future. Use functions
++ * 	in this file for all APICID bit manipulations and conversion.
++ *
++ * 		1111110000000000
++ * 		5432109876543210
++ *		nnnnnnnnnnlc0cch
++ *		sssssssssss
++ *
++ *			n  = snasid bits
++ *			l =  socket number on board
++ *			c  = core
++ *			h  = hyperthread
++ *			s  = bits that are in the socket CSR
++ *
++ *	Note: Processor only supports 12 bits in the APICID register. The ACPI
++ *	      tables hold all 16 bits. Software needs to be aware of this.
++ *
++ * 	      Unless otherwise specified, all references to APICID refer to
++ * 	      the FULL value contained in ACPI tables, not the subset in the
++ * 	      processor APICID register.
++ */
++
++
++/*
++ * Maximum number of bricks in all partitions and in all coherency domains.
++ * This is the total number of bricks accessible in the numalink fabric. It
++ * includes all C & M bricks. Routers are NOT included.
++ *
++ * This value is also the value of the maximum number of non-router NASIDs
++ * in the numalink fabric.
++ *
++ * NOTE: a brick may be 1 or 2 OS nodes. Don't get these confused.
++ */
++#define UV_MAX_NUMALINK_BLADES	16384
++
++/*
++ * Maximum number of C/Mbricks within a software SSI (hardware may support
++ * more).
++ */
++#define UV_MAX_SSI_BLADES	256
++
++/*
++ * The largest possible NASID of a C or M brick (+ 2)
++ */
++#define UV_MAX_NASID_VALUE	(UV_MAX_NUMALINK_NODES * 2)
++
++/*
++ * The following defines attributes of the HUB chip. These attributes are
++ * frequently referenced and are kept in the per-cpu data areas of each cpu.
++ * They are kept together in a struct to minimize cache misses.
++ */
++struct uv_hub_info_s {
++	unsigned long	global_mmr_base;
++	unsigned short	local_nasid;
++	unsigned short	gnode_upper;
++	unsigned short	coherency_domain_number;
++	unsigned short	numa_blade_id;
++	unsigned char	blade_processor_id;
++	unsigned char	m_val;
++	unsigned char	n_val;
++};
++DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
++#define uv_hub_info 		(&__get_cpu_var(__uv_hub_info))
++#define uv_cpu_hub_info(cpu)	(&per_cpu(__uv_hub_info, cpu))
++
++/*
++ * Local & Global MMR space macros.
++ * 	Note: macros are intended to be used ONLY by inline functions
++ * 	in this file - not by other kernel code.
++ */
++#define UV_SNASID(n)			((n) >> 1)
++#define UV_NASID(n)			((n) << 1)
++
++#define UV_LOCAL_MMR_BASE		0xf4000000UL
++#define UV_GLOBAL_MMR32_BASE		0xf8000000UL
++#define UV_GLOBAL_MMR64_BASE		(uv_hub_info->global_mmr_base)
++
++#define UV_GLOBAL_MMR32_SNASID_MASK	0x3ff
++#define UV_GLOBAL_MMR32_SNASID_SHIFT	15
++#define UV_GLOBAL_MMR64_SNASID_SHIFT	26
++
++#define UV_GLOBAL_MMR32_NASID_BITS(n)					\
++		(((UV_SNASID(n) & UV_GLOBAL_MMR32_SNASID_MASK)) <<	\
++		(UV_GLOBAL_MMR32_SNASID_SHIFT))
++
++#define UV_GLOBAL_MMR64_NASID_BITS(n)					\
++	((unsigned long)UV_SNASID(n) << UV_GLOBAL_MMR64_SNASID_SHIFT)
++
++#define UV_APIC_NASID_SHIFT	6
++
++/*
++ * Extract a NASID from an APICID (full apicid, not processor subset)
++ */
++static inline int uv_apicid_to_nasid(int apicid)
++{
++	return (UV_NASID(apicid >> UV_APIC_NASID_SHIFT));
++}
++
++/*
++ * Access global MMRs using the low memory MMR32 space. This region supports
++ * faster MMR access but not all MMRs are accessible in this space.
++ */
++static inline unsigned long *uv_global_mmr32_address(int nasid,
++				unsigned long offset)
++{
++	return __va(UV_GLOBAL_MMR32_BASE |
++		       UV_GLOBAL_MMR32_NASID_BITS(nasid) | offset);
++}
++
++static inline void uv_write_global_mmr32(int nasid, unsigned long offset,
++				 unsigned long val)
++{
++	*uv_global_mmr32_address(nasid, offset) = val;
++}
++
++static inline unsigned long uv_read_global_mmr32(int nasid,
++						 unsigned long offset)
++{
++	return *uv_global_mmr32_address(nasid, offset);
++}
++
++/*
++ * Access Global MMR space using the MMR space located at the top of physical
++ * memory.
++ */
++static inline unsigned long *uv_global_mmr64_address(int nasid,
++				unsigned long offset)
++{
++	return __va(UV_GLOBAL_MMR64_BASE |
++		       UV_GLOBAL_MMR64_NASID_BITS(nasid) | offset);
++}
++
++static inline void uv_write_global_mmr64(int nasid, unsigned long offset,
++				unsigned long val)
++{
++	*uv_global_mmr64_address(nasid, offset) = val;
++}
++
++static inline unsigned long uv_read_global_mmr64(int nasid,
++						 unsigned long offset)
++{
++	return *uv_global_mmr64_address(nasid, offset);
++}
++
++/*
++ * Access node local MMRs. Faster than using global space but only local MMRs
++ * are accessible.
++ */
++static inline unsigned long *uv_local_mmr_address(unsigned long offset)
++{
++	return __va(UV_LOCAL_MMR_BASE | offset);
++}
++
++static inline unsigned long uv_read_local_mmr(unsigned long offset)
++{
++	return *uv_local_mmr_address(offset);
++}
++
++static inline void uv_write_local_mmr(unsigned long offset, unsigned long val)
++{
++	*uv_local_mmr_address(offset) = val;
++}
++
++/*
++ * Structures and definitions for converting between cpu, node, and blade
++ * numbers.
++ */
++struct uv_blade_info {
++	unsigned short	nr_posible_cpus;
++	unsigned short	nr_online_cpus;
++	unsigned short	nasid;
++};
++struct uv_blade_info *uv_blade_info;
++extern short *uv_node_to_blade;
++extern short *uv_cpu_to_blade;
++extern short uv_possible_blades;
++
++/* Blade-local cpu number of current cpu. Numbered 0 .. <# cpus on the blade> */
++static inline int uv_blade_processor_id(void)
++{
++	return uv_hub_info->blade_processor_id;
++}
++
++/* Blade number of current cpu. Numnbered 0 .. <#blades -1> */
++static inline int uv_numa_blade_id(void)
++{
++	return uv_hub_info->numa_blade_id;
++}
++
++/* Convert a cpu number to the the UV blade number */
++static inline int uv_cpu_to_blade_id(int cpu)
++{
++	return uv_cpu_to_blade[cpu];
++}
++
++/* Convert linux node number to the UV blade number */
++static inline int uv_node_to_blade_id(int nid)
++{
++	return uv_node_to_blade[nid];
++}
++
++/* Convert a blade id to the NASID of the blade */
++static inline int uv_blade_to_nasid(int bid)
++{
++	return uv_blade_info[bid].nasid;
++}
++
++/* Determine the number of possible cpus on a blade */
++static inline int uv_blade_nr_possible_cpus(int bid)
++{
++	return uv_blade_info[bid].nr_posible_cpus;
++}
++
++/* Determine the number of online cpus on a blade */
++static inline int uv_blade_nr_online_cpus(int bid)
++{
++	return uv_blade_info[bid].nr_online_cpus;
++}
++
++/* Convert a cpu id to the NASID of the blade containing the cpu */
++static inline int uv_cpu_to_nasid(int cpu)
++{
++	return uv_blade_info[uv_cpu_to_blade_id(cpu)].nasid;
++}
++
++/* Convert a node number to the NASID of the blade */
++static inline int uv_node_to_nasid(int nid)
++{
++	return uv_blade_info[uv_node_to_blade_id(nid)].nasid;
++}
++
++/* Maximum possible number of blades */
++static inline int uv_num_possible_blades(void)
++{
++	return uv_possible_blades;
++}
++
++#endif /* __ASM_X86_UV_HUB__ */
++
+diff --git a/include/asm-x86/uv/uv_mmrs.h b/include/asm-x86/uv/uv_mmrs.h
+new file mode 100644
+index 0000000..3b69fe6
+--- /dev/null
++++ b/include/asm-x86/uv/uv_mmrs.h
+@@ -0,0 +1,373 @@
++/*
++ * 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.
++ *
++ * SGI UV MMR definitions
++ *
++ * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
++ */
++
++#ifndef __ASM_X86_UV_MMRS__
++#define __ASM_X86_UV_MMRS__
++
++/*
++ *       AUTO GENERATED - Do not edit
++ */
++
++ #define UV_MMR_ENABLE		(1UL << 63)
++
++/* ========================================================================= */
++/*                               UVH_IPI_INT                                 */
++/* ========================================================================= */
++#define UVH_IPI_INT 0x60500UL
++#define UVH_IPI_INT_32 0x0360
++
++#define UVH_IPI_INT_VECTOR_SHFT 0
++#define UVH_IPI_INT_VECTOR_MASK 0x00000000000000ffUL
++#define UVH_IPI_INT_DELIVERY_MODE_SHFT 8
++#define UVH_IPI_INT_DELIVERY_MODE_MASK 0x0000000000000700UL
++#define UVH_IPI_INT_DESTMODE_SHFT 11
++#define UVH_IPI_INT_DESTMODE_MASK 0x0000000000000800UL
++#define UVH_IPI_INT_APIC_ID_SHFT 16
++#define UVH_IPI_INT_APIC_ID_MASK 0x0000ffffffff0000UL
++#define UVH_IPI_INT_SEND_SHFT 63
++#define UVH_IPI_INT_SEND_MASK 0x8000000000000000UL
++
++union uvh_ipi_int_u {
++    unsigned long	v;
++    struct uvh_ipi_int_s {
++	unsigned long	vector_       :  8;  /* RW */
++	unsigned long	delivery_mode :  3;  /* RW */
++	unsigned long	destmode      :  1;  /* RW */
++	unsigned long	rsvd_12_15    :  4;  /*    */
++	unsigned long	apic_id       : 32;  /* RW */
++	unsigned long	rsvd_48_62    : 15;  /*    */
++	unsigned long	send          :  1;  /* WP */
++    } s;
++};
++
++/* ========================================================================= */
++/*                   UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST                     */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST 0x320050UL
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_32 0x009f0
++
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_SHFT 4
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_SHFT 49
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_MASK 0x7ffe000000000000UL
++
++union uvh_lb_bau_intd_payload_queue_first_u {
++    unsigned long	v;
++    struct uvh_lb_bau_intd_payload_queue_first_s {
++	unsigned long	rsvd_0_3:  4;  /*    */
++	unsigned long	address : 39;  /* RW */
++	unsigned long	rsvd_43_48:  6;  /*    */
++	unsigned long	node_id : 14;  /* RW */
++	unsigned long	rsvd_63 :  1;  /*    */
++    } s;
++};
++
++/* ========================================================================= */
++/*                    UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST                     */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST 0x320060UL
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_32 0x009f8
++
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT 4
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK 0x000007fffffffff0UL
++
++union uvh_lb_bau_intd_payload_queue_last_u {
++    unsigned long	v;
++    struct uvh_lb_bau_intd_payload_queue_last_s {
++	unsigned long	rsvd_0_3:  4;  /*    */
++	unsigned long	address : 39;  /* RW */
++	unsigned long	rsvd_43_63: 21;  /*    */
++    } s;
++};
++
++/* ========================================================================= */
++/*                    UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL                     */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL 0x320070UL
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_32 0x00a00
++
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT 4
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK 0x000007fffffffff0UL
++
++union uvh_lb_bau_intd_payload_queue_tail_u {
++    unsigned long	v;
++    struct uvh_lb_bau_intd_payload_queue_tail_s {
++	unsigned long	rsvd_0_3:  4;  /*    */
++	unsigned long	address : 39;  /* RW */
++	unsigned long	rsvd_43_63: 21;  /*    */
++    } s;
++};
++
++/* ========================================================================= */
++/*                   UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE                    */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE 0x320080UL
++
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_SHFT 0
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_SHFT 1
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_SHFT 2
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_SHFT 3
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_SHFT 4
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_SHFT 5
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_SHFT 6
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_SHFT 7
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_SHFT 8
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_SHFT 9
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_SHFT 10
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_SHFT 11
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_SHFT 12
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_SHFT 13
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_SHFT 14
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_SHFT 15
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_MASK 0x0000000000008000UL
++union uvh_lb_bau_intd_software_acknowledge_u {
++    unsigned long	v;
++    struct uvh_lb_bau_intd_software_acknowledge_s {
++	unsigned long	pending_0 :  1;  /* RW, W1C */
++	unsigned long	pending_1 :  1;  /* RW, W1C */
++	unsigned long	pending_2 :  1;  /* RW, W1C */
++	unsigned long	pending_3 :  1;  /* RW, W1C */
++	unsigned long	pending_4 :  1;  /* RW, W1C */
++	unsigned long	pending_5 :  1;  /* RW, W1C */
++	unsigned long	pending_6 :  1;  /* RW, W1C */
++	unsigned long	pending_7 :  1;  /* RW, W1C */
++	unsigned long	timeout_0 :  1;  /* RW, W1C */
++	unsigned long	timeout_1 :  1;  /* RW, W1C */
++	unsigned long	timeout_2 :  1;  /* RW, W1C */
++	unsigned long	timeout_3 :  1;  /* RW, W1C */
++	unsigned long	timeout_4 :  1;  /* RW, W1C */
++	unsigned long	timeout_5 :  1;  /* RW, W1C */
++	unsigned long	timeout_6 :  1;  /* RW, W1C */
++	unsigned long	timeout_7 :  1;  /* RW, W1C */
++	unsigned long	rsvd_16_63: 48;  /*    */
++    } s;
++};
++
++/* ========================================================================= */
++/*                UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS                 */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS 0x0000000000320088UL
++
++/* ========================================================================= */
++/*                     UVH_LB_BAU_SB_ACTIVATION_CONTROL                      */
++/* ========================================================================= */
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_32 0x009d8
++
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_SHFT 0
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_MASK 0x000000000000003fUL
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT 62
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_MASK 0x4000000000000000UL
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_SHFT 63
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_MASK 0x8000000000000000UL
++
++union uvh_lb_bau_sb_activation_control_u {
++    unsigned long	v;
++    struct uvh_lb_bau_sb_activation_control_s {
++	unsigned long	index :  6;  /* RW */
++	unsigned long	rsvd_6_61: 56;  /*    */
++	unsigned long	push  :  1;  /* WP */
++	unsigned long	init  :  1;  /* WP */
++    } s;
++};
++
++/* ========================================================================= */
++/*                    UVH_LB_BAU_SB_ACTIVATION_STATUS_0                      */
++/* ========================================================================= */
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0 0x320030UL
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x009e0
++
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_SHFT 0
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_MASK 0xffffffffffffffffUL
++
++union uvh_lb_bau_sb_activation_status_0_u {
++    unsigned long	v;
++    struct uvh_lb_bau_sb_activation_status_0_s {
++	unsigned long	status : 64;  /* RW */
++    } s;
++};
++
++/* ========================================================================= */
++/*                    UVH_LB_BAU_SB_ACTIVATION_STATUS_1                      */
++/* ========================================================================= */
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1 0x320040UL
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x009e8
++
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_SHFT 0
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_MASK 0xffffffffffffffffUL
++
++union uvh_lb_bau_sb_activation_status_1_u {
++    unsigned long	v;
++    struct uvh_lb_bau_sb_activation_status_1_s {
++	unsigned long	status : 64;  /* RW */
++    } s;
++};
++
++/* ========================================================================= */
++/*                      UVH_LB_BAU_SB_DESCRIPTOR_BASE                        */
++/* ========================================================================= */
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE 0x320010UL
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_32 0x009d0
++
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_SHFT 12
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK 0x000007fffffff000UL
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_SHFT 49
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_MASK 0x7ffe000000000000UL
++
++union uvh_lb_bau_sb_descriptor_base_u {
++    unsigned long	v;
++    struct uvh_lb_bau_sb_descriptor_base_s {
++	unsigned long	rsvd_0_11    : 12;  /*    */
++	unsigned long	page_address : 31;  /* RW */
++	unsigned long	rsvd_43_48   :  6;  /*    */
++	unsigned long	node_id      : 14;  /* RW */
++	unsigned long	rsvd_63      :  1;  /*    */
++    } s;
++};
++
++/* ========================================================================= */
++/*                               UVH_NODE_ID                                 */
++/* ========================================================================= */
++#define UVH_NODE_ID 0x0UL
++
++#define UVH_NODE_ID_FORCE1_SHFT 0
++#define UVH_NODE_ID_FORCE1_MASK 0x0000000000000001UL
++#define UVH_NODE_ID_MANUFACTURER_SHFT 1
++#define UVH_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
++#define UVH_NODE_ID_PART_NUMBER_SHFT 12
++#define UVH_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
++#define UVH_NODE_ID_REVISION_SHFT 28
++#define UVH_NODE_ID_REVISION_MASK 0x00000000f0000000UL
++#define UVH_NODE_ID_NODE_ID_SHFT 32
++#define UVH_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
++#define UVH_NODE_ID_NODES_PER_BIT_SHFT 48
++#define UVH_NODE_ID_NODES_PER_BIT_MASK 0x007f000000000000UL
++#define UVH_NODE_ID_NI_PORT_SHFT 56
++#define UVH_NODE_ID_NI_PORT_MASK 0x0f00000000000000UL
++
++union uvh_node_id_u {
++    unsigned long	v;
++    struct uvh_node_id_s {
++	unsigned long	force1        :  1;  /* RO */
++	unsigned long	manufacturer  : 11;  /* RO */
++	unsigned long	part_number   : 16;  /* RO */
++	unsigned long	revision      :  4;  /* RO */
++	unsigned long	node_id       : 15;  /* RW */
++	unsigned long	rsvd_47       :  1;  /*    */
++	unsigned long	nodes_per_bit :  7;  /* RW */
++	unsigned long	rsvd_55       :  1;  /*    */
++	unsigned long	ni_port       :  4;  /* RO */
++	unsigned long	rsvd_60_63    :  4;  /*    */
++    } s;
++};
++
++/* ========================================================================= */
++/*                    UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR                      */
++/* ========================================================================= */
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
++
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT 46
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK 0x0000400000000000UL
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
++
++union uvh_rh_gam_gru_overlay_config_mmr_u {
++    unsigned long	v;
++    struct uvh_rh_gam_gru_overlay_config_mmr_s {
++	unsigned long	rsvd_0_27: 28;  /*    */
++	unsigned long	base   : 18;  /* RW */
++	unsigned long	gr4    :  1;  /* RW */
++	unsigned long	rsvd_47_51:  5;  /*    */
++	unsigned long	n_gru  :  4;  /* RW */
++	unsigned long	rsvd_56_62:  7;  /*    */
++	unsigned long	enable :  1;  /* RW */
++    } s;
++};
++
++/* ========================================================================= */
++/*                    UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR                      */
++/* ========================================================================= */
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
++
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_SHFT 46
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_MASK 0x0000400000000000UL
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
++
++union uvh_rh_gam_mmr_overlay_config_mmr_u {
++    unsigned long	v;
++    struct uvh_rh_gam_mmr_overlay_config_mmr_s {
++	unsigned long	rsvd_0_25: 26;  /*    */
++	unsigned long	base     : 20;  /* RW */
++	unsigned long	dual_hub :  1;  /* RW */
++	unsigned long	rsvd_47_62: 16;  /*    */
++	unsigned long	enable   :  1;  /* RW */
++    } s;
++};
++
++/* ========================================================================= */
++/*                                 UVH_RTC                                   */
++/* ========================================================================= */
++#define UVH_RTC 0x28000UL
++
++#define UVH_RTC_REAL_TIME_CLOCK_SHFT 0
++#define UVH_RTC_REAL_TIME_CLOCK_MASK 0x00ffffffffffffffUL
++
++union uvh_rtc_u {
++    unsigned long	v;
++    struct uvh_rtc_s {
++	unsigned long	real_time_clock : 56;  /* RW */
++	unsigned long	rsvd_56_63      :  8;  /*    */
++    } s;
++};
++
++/* ========================================================================= */
++/*                          UVH_SI_ADDR_MAP_CONFIG                           */
++/* ========================================================================= */
++#define UVH_SI_ADDR_MAP_CONFIG 0xc80000UL
++
++#define UVH_SI_ADDR_MAP_CONFIG_M_SKT_SHFT 0
++#define UVH_SI_ADDR_MAP_CONFIG_M_SKT_MASK 0x000000000000003fUL
++#define UVH_SI_ADDR_MAP_CONFIG_N_SKT_SHFT 8
++#define UVH_SI_ADDR_MAP_CONFIG_N_SKT_MASK 0x0000000000000f00UL
++
++union uvh_si_addr_map_config_u {
++    unsigned long	v;
++    struct uvh_si_addr_map_config_s {
++	unsigned long	m_skt :  6;  /* RW */
++	unsigned long	rsvd_6_7:  2;  /*    */
++	unsigned long	n_skt :  4;  /* RW */
++	unsigned long	rsvd_12_63: 52;  /*    */
++    } s;
++};
++
++
++#endif /* __ASM_X86_UV_MMRS__ */
+diff --git a/include/asm-x86/vdso.h b/include/asm-x86/vdso.h
+index 629bcb6..86e085e 100644
+--- a/include/asm-x86/vdso.h
++++ b/include/asm-x86/vdso.h
+@@ -8,9 +8,11 @@ extern const char VDSO64_PRELINK[];
+  * Given a pointer to the vDSO image, find the pointer to VDSO64_name
+  * as that symbol is defined in the vDSO sources or linker script.
+  */
+-#define VDSO64_SYMBOL(base, name) ({		\
+-	extern const char VDSO64_##name[];	\
+-	(void *) (VDSO64_##name - VDSO64_PRELINK + (unsigned long) (base)); })
++#define VDSO64_SYMBOL(base, name)					\
++({									\
++	extern const char VDSO64_##name[];				\
++	(void *)(VDSO64_##name - VDSO64_PRELINK + (unsigned long)(base)); \
++})
+ #endif
+ 
+ #if defined CONFIG_X86_32 || defined CONFIG_COMPAT
+@@ -20,9 +22,18 @@ extern const char VDSO32_PRELINK[];
+  * Given a pointer to the vDSO image, find the pointer to VDSO32_name
+  * as that symbol is defined in the vDSO sources or linker script.
+  */
+-#define VDSO32_SYMBOL(base, name) ({		\
+-	extern const char VDSO32_##name[];	\
+-	(void *) (VDSO32_##name - VDSO32_PRELINK + (unsigned long) (base)); })
++#define VDSO32_SYMBOL(base, name)					\
++({									\
++	extern const char VDSO32_##name[];				\
++	(void *)(VDSO32_##name - VDSO32_PRELINK + (unsigned long)(base)); \
++})
+ #endif
+ 
++/*
++ * These symbols are defined with the addresses in the vsyscall page.
++ * See vsyscall-sigreturn.S.
++ */
++extern void __user __kernel_sigreturn;
++extern void __user __kernel_rt_sigreturn;
++
+ #endif	/* asm-x86/vdso.h */
+diff --git a/include/asm-x86/vga.h b/include/asm-x86/vga.h
+index 0ecf68a..0ccf804 100644
+--- a/include/asm-x86/vga.h
++++ b/include/asm-x86/vga.h
+@@ -12,9 +12,9 @@
+  *	access the videoram directly without any black magic.
+  */
+ 
+-#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x)
++#define VGA_MAP_MEM(x, s) (unsigned long)phys_to_virt(x)
+ 
+ #define vga_readb(x) (*(x))
+-#define vga_writeb(x,y) (*(y) = (x))
++#define vga_writeb(x, y) (*(y) = (x))
+ 
+ #endif
+diff --git a/include/asm-x86/vm86.h b/include/asm-x86/vm86.h
+index c92fe4a..074b357 100644
+--- a/include/asm-x86/vm86.h
++++ b/include/asm-x86/vm86.h
+@@ -12,19 +12,13 @@
+  * Linus
+  */
+ 
+-#define TF_MASK		0x00000100
+-#define IF_MASK		0x00000200
+-#define IOPL_MASK	0x00003000
+-#define NT_MASK		0x00004000
++#include <asm/processor-flags.h>
++
+ #ifdef CONFIG_VM86
+-#define VM_MASK		0x00020000
++#define X86_VM_MASK	X86_EFLAGS_VM
+ #else
+-#define VM_MASK		0 /* ignored */
++#define X86_VM_MASK	0 /* No VM86 support */
+ #endif
+-#define AC_MASK		0x00040000
+-#define VIF_MASK	0x00080000	/* virtual interrupt flag */
+-#define VIP_MASK	0x00100000	/* virtual interrupt pending */
+-#define ID_MASK		0x00200000
+ 
+ #define BIOSSEG		0x0f000
+ 
+@@ -42,9 +36,11 @@
+ #define VM86_ARG(retval)	((retval) >> 8)
+ 
+ #define VM86_SIGNAL	0	/* return due to signal */
+-#define VM86_UNKNOWN	1	/* unhandled GP fault - IO-instruction or similar */
++#define VM86_UNKNOWN	1	/* unhandled GP fault
++				   - IO-instruction or similar */
+ #define VM86_INTx	2	/* int3/int x instruction (ARG = x) */
+-#define VM86_STI	3	/* sti/popf/iret instruction enabled virtual interrupts */
++#define VM86_STI	3	/* sti/popf/iret instruction enabled
++				   virtual interrupts */
+ 
+ /*
+  * Additional return values when invoking new vm86()
+@@ -205,7 +201,8 @@ void release_vm86_irqs(struct task_struct *);
+ #define handle_vm86_fault(a, b)
+ #define release_vm86_irqs(a)
+ 
+-static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c) {
++static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c)
++{
+ 	return 0;
+ }
+ 
+diff --git a/include/asm-x86/vmi.h b/include/asm-x86/vmi.h
+index eb8bd89..b7c0dea 100644
+--- a/include/asm-x86/vmi.h
++++ b/include/asm-x86/vmi.h
+@@ -155,9 +155,9 @@
+ 
+ #ifndef __ASSEMBLY__
+ struct vmi_relocation_info {
+-        unsigned char           *eip;
+-        unsigned char           type;
+-        unsigned char           reserved[3];
++	unsigned char           *eip;
++	unsigned char           type;
++	unsigned char           reserved[3];
+ };
+ #endif
+ 
+@@ -173,53 +173,53 @@ struct vmi_relocation_info {
+ #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
++	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;
++	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;
++	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 */
+diff --git a/include/asm-x86/voyager.h b/include/asm-x86/voyager.h
+index 91a9932..9c811d2 100644
+--- a/include/asm-x86/voyager.h
++++ b/include/asm-x86/voyager.h
+@@ -91,8 +91,7 @@
+ #define VOYAGER_WRITE_CONFIG			0x2
+ #define VOYAGER_BYPASS				0xff
+ 
+-typedef struct voyager_asic 
+-{
++typedef struct voyager_asic {
+ 	__u8	asic_addr;	/* ASIC address; Level 4 */
+ 	__u8	asic_type;      /* ASIC type */
+ 	__u8	asic_id;	/* ASIC id */
+@@ -113,7 +112,7 @@ typedef struct voyager_module {
+ 	__u16   largest_reg;		/* Largest register in the scan path */
+ 	__u16   smallest_reg;		/* Smallest register in the scan path */
+ 	voyager_asic_t   *asic;		/* First ASIC in scan path (CAT_I) */
+-	struct   voyager_module *submodule;	/* Submodule pointer */ 
++	struct   voyager_module *submodule;	/* Submodule pointer */
+ 	struct   voyager_module *next;		/* Next module in linked list */
+ } voyager_module_t;
+ 
+@@ -135,7 +134,7 @@ typedef struct voyager_eeprom_hdr {
+ 	 __u16 cct_offset;
+ 	 __u16 log_length;	/* length of err log */
+ 	 __u16 xsum_end;	/* offset to end of
+-							   checksum */
++				   checksum */
+ 	 __u8  reserved[4];
+ 	 __u8  sflag;		/* starting sentinal */
+ 	 __u8  part_number[13];	/* prom part number */
+@@ -148,7 +147,8 @@ typedef struct voyager_eeprom_hdr {
+ 
+ 
+ 
+-#define VOYAGER_EPROM_SIZE_OFFSET   ((__u16)(&(((voyager_eprom_hdr_t *)0)->ee_size)))
++#define VOYAGER_EPROM_SIZE_OFFSET				\
++	((__u16)(&(((voyager_eprom_hdr_t *)0)->ee_size)))
+ #define VOYAGER_XSUM_END_OFFSET		0x2a
+ 
+ /* the following three definitions are for internal table layouts
+@@ -199,7 +199,7 @@ typedef struct voyager_asic_data_table {
+ #define VOYAGER_WCBIC_TOM_L	0x4
+ #define VOYAGER_WCBIC_TOM_H	0x5
+ 
+-/* register defines for Voyager Memory Contol (VMC) 
++/* register defines for Voyager Memory Contol (VMC)
+  * these are present on L4 machines only */
+ #define	VOYAGER_VMC1		0x81
+ #define VOYAGER_VMC2		0x91
+@@ -334,7 +334,7 @@ typedef struct {
+ 
+ struct QuadDescription {
+ 	__u8  Type;	/* for type 0 (DYADIC or MONADIC) all fields
+-                         * will be zero except for slot */
++			 * will be zero except for slot */
+ 	__u8 StructureVersion;
+ 	__u32 CPI_BaseAddress;
+ 	__u32  LARC_BankSize;
+@@ -342,7 +342,7 @@ struct QuadDescription {
+ 	__u8  Slot; /* Processor slots 1 - 4 */
+ } __attribute__((packed));
+ 
+-struct ProcBoardInfo { 
++struct ProcBoardInfo {
+ 	__u8 Type;
+ 	__u8 StructureVersion;
+ 	__u8 NumberOfBoards;
+@@ -382,19 +382,30 @@ struct CPU_Info {
+  * packed in it by our friend the compiler.
+  */
+ typedef struct {
+-	__u8	Mailbox_SUS;		/* Written to by SUS to give commands/response to the OS */
+-	__u8	Mailbox_OS;		/* Written to by the OS to give commands/response to SUS */
+-	__u8	SUS_MailboxVersion;	/* Tells the OS which iteration of the interface SUS supports */
+-	__u8	OS_MailboxVersion;	/* Tells SUS which iteration of the interface the OS supports */
+-	__u32	OS_Flags;		/* Flags set by the OS as info for SUS */
+-	__u32	SUS_Flags;		/* Flags set by SUS as info for the OS */
+-	__u32	WatchDogPeriod;		/* Watchdog period (in seconds) which the DP uses to see if the OS is dead */
++	__u8	Mailbox_SUS;		/* Written to by SUS to give
++					   commands/response to the OS */
++	__u8	Mailbox_OS;		/* Written to by the OS to give
++					   commands/response to SUS */
++	__u8	SUS_MailboxVersion;	/* Tells the OS which iteration of the
++					   interface SUS supports */
++	__u8	OS_MailboxVersion;	/* Tells SUS which iteration of the
++					   interface the OS supports */
++	__u32	OS_Flags;		/* Flags set by the OS as info for
++					   SUS */
++	__u32	SUS_Flags;		/* Flags set by SUS as info
++					   for the OS */
++	__u32	WatchDogPeriod;		/* Watchdog period (in seconds) which
++					   the DP uses to see if the OS
++					   is dead */
+ 	__u32	WatchDogCount;		/* Updated by the OS on every tic. */
+-	__u32	MemoryFor_SUS_ErrorLog;	/* Flat 32 bit address which tells SUS where to stuff the SUS error log on a dump */
+-	MC_SlotInformation_t  MC_SlotInfo[NUMBER_OF_MC_BUSSES*SLOTS_PER_MC_BUS];	/* Storage for MCA POS data */
++	__u32	MemoryFor_SUS_ErrorLog;	/* Flat 32 bit address which tells SUS
++					   where to stuff the SUS error log
++					   on a dump */
++	MC_SlotInformation_t MC_SlotInfo[NUMBER_OF_MC_BUSSES*SLOTS_PER_MC_BUS];
++					/* Storage for MCA POS data */
+ 	/* All new SECOND_PASS_INTERFACE fields added from this point */
+-        struct ProcBoardInfo    *BoardData;
+-        struct CPU_Info         *CPU_Data;
++	struct ProcBoardInfo    *BoardData;
++	struct CPU_Info         *CPU_Data;
+ 	/* All new fields must be added from this point */
+ } Voyager_KernelSUS_Mbox_t;
+ 
+@@ -478,7 +489,7 @@ struct voyager_SUS {
+ 	__u32	SUS_errorlog;
+ 	/* lots of system configuration stuff under here */
+ };
+-	
++
+ /* Variables exported by voyager_smp */
+ extern __u32 voyager_extended_vic_processors;
+ extern __u32 voyager_allowed_boot_processors;
+diff --git a/include/asm-x86/xen/events.h b/include/asm-x86/xen/events.h
+new file mode 100644
+index 0000000..596312a
+--- /dev/null
++++ b/include/asm-x86/xen/events.h
+@@ -0,0 +1,22 @@
++#ifndef __XEN_EVENTS_H
++#define __XEN_EVENTS_H
++
++enum ipi_vector {
++	XEN_RESCHEDULE_VECTOR,
++	XEN_CALL_FUNCTION_VECTOR,
++
++	XEN_NR_IPIS,
++};
++
++static inline int xen_irqs_disabled(struct pt_regs *regs)
++{
++	return raw_irqs_disabled_flags(regs->flags);
++}
++
++static inline void xen_do_IRQ(int irq, struct pt_regs *regs)
++{
++	regs->orig_ax = ~irq;
++	do_IRQ(regs);
++}
++
++#endif /* __XEN_EVENTS_H */
+diff --git a/include/asm-x86/xen/grant_table.h b/include/asm-x86/xen/grant_table.h
+new file mode 100644
+index 0000000..2444d45
+--- /dev/null
++++ b/include/asm-x86/xen/grant_table.h
+@@ -0,0 +1,7 @@
++#ifndef __XEN_GRANT_TABLE_H
++#define __XEN_GRANT_TABLE_H
++
++#define xen_alloc_vm_area(size)	alloc_vm_area(size)
++#define xen_free_vm_area(area)	free_vm_area(area)
++
++#endif /* __XEN_GRANT_TABLE_H */
+diff --git a/include/asm-x86/xen/hypercall.h b/include/asm-x86/xen/hypercall.h
+index bc0ee7d..c2ccd99 100644
+--- a/include/asm-x86/xen/hypercall.h
++++ b/include/asm-x86/xen/hypercall.h
+@@ -164,6 +164,12 @@ HYPERVISOR_set_callbacks(unsigned long event_selector,
+ }
+ 
+ static inline int
++HYPERVISOR_callback_op(int cmd, void *arg)
++{
++	return _hypercall2(int, callback_op, cmd, arg);
++}
++
++static inline int
+ HYPERVISOR_fpu_taskswitch(int set)
+ {
+ 	return _hypercall1(int, fpu_taskswitch, set);
+diff --git a/include/asm-x86/xen/interface.h b/include/asm-x86/xen/interface.h
+index 165c396..6227000 100644
+--- a/include/asm-x86/xen/interface.h
++++ b/include/asm-x86/xen/interface.h
+@@ -22,6 +22,30 @@
+ #define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
+ #define GUEST_HANDLE(name)        __guest_handle_ ## name
+ 
++#ifdef __XEN__
++#if defined(__i386__)
++#define set_xen_guest_handle(hnd, val)			\
++	do {						\
++		if (sizeof(hnd) == 8)			\
++			*(uint64_t *)&(hnd) = 0;	\
++		(hnd).p = val;				\
++	} while (0)
++#elif defined(__x86_64__)
++#define set_xen_guest_handle(hnd, val)	do { (hnd).p = val; } while (0)
++#endif
++#else
++#if defined(__i386__)
++#define set_xen_guest_handle(hnd, val)			\
++	do {						\
++		if (sizeof(hnd) == 8)			\
++			*(uint64_t *)&(hnd) = 0;	\
++		(hnd) = val;				\
++	} while (0)
++#elif defined(__x86_64__)
++#define set_xen_guest_handle(hnd, val)	do { (hnd) = val; } while (0)
++#endif
++#endif
++
+ #ifndef __ASSEMBLY__
+ /* Guest handles for primitive C types. */
+ __DEFINE_GUEST_HANDLE(uchar, unsigned char);
+@@ -171,6 +195,10 @@ struct arch_vcpu_info {
+     unsigned long pad[5]; /* sizeof(struct vcpu_info) == 64 */
+ };
+ 
++struct xen_callback {
++	unsigned long cs;
++	unsigned long eip;
++};
+ #endif /* !__ASSEMBLY__ */
+ 
+ /*
+diff --git a/include/asm-x86/xen/page.h b/include/asm-x86/xen/page.h
+new file mode 100644
+index 0000000..0179930
+--- /dev/null
++++ b/include/asm-x86/xen/page.h
+@@ -0,0 +1,168 @@
++#ifndef __XEN_PAGE_H
++#define __XEN_PAGE_H
++
++#include <linux/pfn.h>
++
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++
++#include <xen/features.h>
++
++/* Xen machine address */
++typedef struct xmaddr {
++	phys_addr_t maddr;
++} xmaddr_t;
++
++/* Xen pseudo-physical address */
++typedef struct xpaddr {
++	phys_addr_t paddr;
++} xpaddr_t;
++
++#define XMADDR(x)	((xmaddr_t) { .maddr = (x) })
++#define XPADDR(x)	((xpaddr_t) { .paddr = (x) })
++
++/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
++#define INVALID_P2M_ENTRY	(~0UL)
++#define FOREIGN_FRAME_BIT	(1UL<<31)
++#define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
++
++extern unsigned long *phys_to_machine_mapping;
++
++static inline unsigned long pfn_to_mfn(unsigned long pfn)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return pfn;
++
++	return phys_to_machine_mapping[(unsigned int)(pfn)] &
++		~FOREIGN_FRAME_BIT;
++}
++
++static inline int phys_to_machine_mapping_valid(unsigned long pfn)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return 1;
++
++	return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
++}
++
++static inline unsigned long mfn_to_pfn(unsigned long mfn)
++{
++	unsigned long pfn;
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return mfn;
++
++#if 0
++	if (unlikely((mfn >> machine_to_phys_order) != 0))
++		return max_mapnr;
++#endif
++
++	pfn = 0;
++	/*
++	 * The array access can fail (e.g., device space beyond end of RAM).
++	 * In such cases it doesn't matter what we return (we return garbage),
++	 * but we must handle the fault without crashing!
++	 */
++	__get_user(pfn, &machine_to_phys_mapping[mfn]);
++
++	return pfn;
++}
++
++static inline xmaddr_t phys_to_machine(xpaddr_t phys)
++{
++	unsigned offset = phys.paddr & ~PAGE_MASK;
++	return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
++}
++
++static inline xpaddr_t machine_to_phys(xmaddr_t machine)
++{
++	unsigned offset = machine.maddr & ~PAGE_MASK;
++	return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
++}
++
++/*
++ * We detect special mappings in one of two ways:
++ *  1. If the MFN is an I/O page then Xen will set the m2p entry
++ *     to be outside our maximum possible pseudophys range.
++ *  2. If the MFN belongs to a different domain then we will certainly
++ *     not have MFN in our p2m table. Conversely, if the page is ours,
++ *     then we'll have p2m(m2p(MFN))==MFN.
++ * If we detect a special mapping then it doesn't have a 'struct page'.
++ * We force !pfn_valid() by returning an out-of-range pointer.
++ *
++ * NB. These checks require that, for any MFN that is not in our reservation,
++ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
++ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
++ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
++ *
++ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
++ *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
++ *      require. In all the cases we care about, the FOREIGN_FRAME bit is
++ *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
++ */
++static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
++{
++	extern unsigned long max_mapnr;
++	unsigned long pfn = mfn_to_pfn(mfn);
++	if ((pfn < max_mapnr)
++	    && !xen_feature(XENFEAT_auto_translated_physmap)
++	    && (phys_to_machine_mapping[pfn] != mfn))
++		return max_mapnr; /* force !pfn_valid() */
++	return pfn;
++}
++
++static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap)) {
++		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
++		return;
++	}
++	phys_to_machine_mapping[pfn] = mfn;
++}
++
++/* VIRT <-> MACHINE conversion */
++#define virt_to_machine(v)	(phys_to_machine(XPADDR(__pa(v))))
++#define virt_to_mfn(v)		(pfn_to_mfn(PFN_DOWN(__pa(v))))
++#define mfn_to_virt(m)		(__va(mfn_to_pfn(m) << PAGE_SHIFT))
++
++static inline unsigned long pte_mfn(pte_t pte)
++{
++	return (pte.pte & ~_PAGE_NX) >> PAGE_SHIFT;
++}
++
++static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
++{
++	pte_t pte;
++
++	pte.pte = ((phys_addr_t)page_nr << PAGE_SHIFT) |
++		(pgprot_val(pgprot) & __supported_pte_mask);
++
++	return pte;
++}
++
++static inline pteval_t pte_val_ma(pte_t pte)
++{
++	return pte.pte;
++}
++
++static inline pte_t __pte_ma(pteval_t x)
++{
++	return (pte_t) { .pte = x };
++}
++
++#ifdef CONFIG_X86_PAE
++#define pmd_val_ma(v) ((v).pmd)
++#define pud_val_ma(v) ((v).pgd.pgd)
++#define __pmd_ma(x)	((pmd_t) { (x) } )
++#else  /* !X86_PAE */
++#define pmd_val_ma(v)	((v).pud.pgd.pgd)
++#endif	/* CONFIG_X86_PAE */
++
++#define pgd_val_ma(x)	((x).pgd)
++
++
++xmaddr_t arbitrary_virt_to_machine(unsigned long address);
++void make_lowmem_page_readonly(void *vaddr);
++void make_lowmem_page_readwrite(void *vaddr);
++
++#endif /* __XEN_PAGE_H */
+diff --git a/include/asm-x86/xor_32.h b/include/asm-x86/xor_32.h
+index a41ef1b..067b5c1 100644
+--- a/include/asm-x86/xor_32.h
++++ b/include/asm-x86/xor_32.h
+@@ -16,12 +16,12 @@
+  * Copyright (C) 1998 Ingo Molnar.
+  */
+ 
+-#define LD(x,y)		"       movq   8*("#x")(%1), %%mm"#y"   ;\n"
+-#define ST(x,y)		"       movq %%mm"#y",   8*("#x")(%1)   ;\n"
+-#define XO1(x,y)	"       pxor   8*("#x")(%2), %%mm"#y"   ;\n"
+-#define XO2(x,y)	"       pxor   8*("#x")(%3), %%mm"#y"   ;\n"
+-#define XO3(x,y)	"       pxor   8*("#x")(%4), %%mm"#y"   ;\n"
+-#define XO4(x,y)	"       pxor   8*("#x")(%5), %%mm"#y"   ;\n"
++#define LD(x, y)	"       movq   8*("#x")(%1), %%mm"#y"   ;\n"
++#define ST(x, y)	"       movq %%mm"#y",   8*("#x")(%1)   ;\n"
++#define XO1(x, y)	"       pxor   8*("#x")(%2), %%mm"#y"   ;\n"
++#define XO2(x, y)	"       pxor   8*("#x")(%3), %%mm"#y"   ;\n"
++#define XO3(x, y)	"       pxor   8*("#x")(%4), %%mm"#y"   ;\n"
++#define XO4(x, y)	"       pxor   8*("#x")(%5), %%mm"#y"   ;\n"
+ 
+ #include <asm/i387.h>
+ 
+@@ -32,24 +32,24 @@ xor_pII_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+ 
+ 	kernel_fpu_begin();
+ 
+-	__asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+-	LD(i,0)					\
+-		LD(i+1,1)			\
+-			LD(i+2,2)		\
+-				LD(i+3,3)	\
+-	XO1(i,0)				\
+-	ST(i,0)					\
+-		XO1(i+1,1)			\
+-		ST(i+1,1)			\
+-			XO1(i+2,2)		\
+-			ST(i+2,2)		\
+-				XO1(i+3,3)	\
+-				ST(i+3,3)
++#define BLOCK(i)				\
++	LD(i, 0)				\
++		LD(i + 1, 1)			\
++			LD(i + 2, 2)		\
++				LD(i + 3, 3)	\
++	XO1(i, 0)				\
++	ST(i, 0)				\
++		XO1(i+1, 1)			\
++		ST(i+1, 1)			\
++			XO1(i + 2, 2)		\
++			ST(i + 2, 2)		\
++				XO1(i + 3, 3)	\
++				ST(i + 3, 3)
+ 
+ 	" .align 32			;\n"
+-  	" 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 	BLOCK(0)
+ 	BLOCK(4)
+@@ -76,25 +76,25 @@ xor_pII_mmx_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 
+ 	kernel_fpu_begin();
+ 
+-	__asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+-	LD(i,0)					\
+-		LD(i+1,1)			\
+-			LD(i+2,2)		\
+-				LD(i+3,3)	\
+-	XO1(i,0)				\
+-		XO1(i+1,1)			\
+-			XO1(i+2,2)		\
+-				XO1(i+3,3)	\
+-	XO2(i,0)				\
+-	ST(i,0)					\
+-		XO2(i+1,1)			\
+-		ST(i+1,1)			\
+-			XO2(i+2,2)		\
+-			ST(i+2,2)		\
+-				XO2(i+3,3)	\
+-				ST(i+3,3)
++#define BLOCK(i)				\
++	LD(i, 0)				\
++		LD(i + 1, 1)			\
++			LD(i + 2, 2)		\
++				LD(i + 3, 3)	\
++	XO1(i, 0)				\
++		XO1(i + 1, 1)			\
++			XO1(i + 2, 2)		\
++				XO1(i + 3, 3)	\
++	XO2(i, 0)				\
++	ST(i, 0)				\
++		XO2(i + 1, 1)			\
++		ST(i + 1, 1)			\
++			XO2(i + 2, 2)		\
++			ST(i + 2, 2)		\
++				XO2(i + 3, 3)	\
++				ST(i + 3, 3)
+ 
+ 	" .align 32			;\n"
+ 	" 1:                            ;\n"
+@@ -125,29 +125,29 @@ xor_pII_mmx_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 
+ 	kernel_fpu_begin();
+ 
+-	__asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+-	LD(i,0)					\
+-		LD(i+1,1)			\
+-			LD(i+2,2)		\
+-				LD(i+3,3)	\
+-	XO1(i,0)				\
+-		XO1(i+1,1)			\
+-			XO1(i+2,2)		\
+-				XO1(i+3,3)	\
+-	XO2(i,0)				\
+-		XO2(i+1,1)			\
+-			XO2(i+2,2)		\
+-				XO2(i+3,3)	\
+-	XO3(i,0)				\
+-	ST(i,0)					\
+-		XO3(i+1,1)			\
+-		ST(i+1,1)			\
+-			XO3(i+2,2)		\
+-			ST(i+2,2)		\
+-				XO3(i+3,3)	\
+-				ST(i+3,3)
++#define BLOCK(i)				\
++	LD(i, 0)				\
++		LD(i + 1, 1)			\
++			LD(i + 2, 2)		\
++				LD(i + 3, 3)	\
++	XO1(i, 0)				\
++		XO1(i + 1, 1)			\
++			XO1(i + 2, 2)		\
++				XO1(i + 3, 3)	\
++	XO2(i, 0)				\
++		XO2(i + 1, 1)			\
++			XO2(i + 2, 2)		\
++				XO2(i + 3, 3)	\
++	XO3(i, 0)				\
++	ST(i, 0)				\
++		XO3(i + 1, 1)			\
++		ST(i + 1, 1)			\
++			XO3(i + 2, 2)		\
++			ST(i + 2, 2)		\
++				XO3(i + 3, 3)	\
++				ST(i + 3, 3)
+ 
+ 	" .align 32			;\n"
+ 	" 1:                            ;\n"
+@@ -186,35 +186,35 @@ xor_pII_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	   because we modify p4 and p5 there, but we can't mark them
+ 	   as read/write, otherwise we'd overflow the 10-asm-operands
+ 	   limit of GCC < 3.1.  */
+-	__asm__ ("" : "+r" (p4), "+r" (p5));
++	asm("" : "+r" (p4), "+r" (p5));
+ 
+-	__asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+-	LD(i,0)					\
+-		LD(i+1,1)			\
+-			LD(i+2,2)		\
+-				LD(i+3,3)	\
+-	XO1(i,0)				\
+-		XO1(i+1,1)			\
+-			XO1(i+2,2)		\
+-				XO1(i+3,3)	\
+-	XO2(i,0)				\
+-		XO2(i+1,1)			\
+-			XO2(i+2,2)		\
+-				XO2(i+3,3)	\
+-	XO3(i,0)				\
+-		XO3(i+1,1)			\
+-			XO3(i+2,2)		\
+-				XO3(i+3,3)	\
+-	XO4(i,0)				\
+-	ST(i,0)					\
+-		XO4(i+1,1)			\
+-		ST(i+1,1)			\
+-			XO4(i+2,2)		\
+-			ST(i+2,2)		\
+-				XO4(i+3,3)	\
+-				ST(i+3,3)
++#define BLOCK(i)				\
++	LD(i, 0)				\
++		LD(i + 1, 1)			\
++			LD(i + 2, 2)		\
++				LD(i + 3, 3)	\
++	XO1(i, 0)				\
++		XO1(i + 1, 1)			\
++			XO1(i + 2, 2)		\
++				XO1(i + 3, 3)	\
++	XO2(i, 0)				\
++		XO2(i + 1, 1)			\
++			XO2(i + 2, 2)		\
++				XO2(i + 3, 3)	\
++	XO3(i, 0)				\
++		XO3(i + 1, 1)			\
++			XO3(i + 2, 2)		\
++				XO3(i + 3, 3)	\
++	XO4(i, 0)				\
++	ST(i, 0)				\
++		XO4(i + 1, 1)			\
++		ST(i + 1, 1)			\
++			XO4(i + 2, 2)		\
++			ST(i + 2, 2)		\
++				XO4(i + 3, 3)	\
++				ST(i + 3, 3)
+ 
+ 	" .align 32			;\n"
+ 	" 1:                            ;\n"
+@@ -233,13 +233,13 @@ xor_pII_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	"       jnz 1b                ;\n"
+ 	: "+r" (lines),
+ 	  "+r" (p1), "+r" (p2), "+r" (p3)
+-	: "r" (p4), "r" (p5) 
++	: "r" (p4), "r" (p5)
+ 	: "memory");
+ 
+ 	/* p4 and p5 were modified, and now the variables are dead.
+ 	   Clobber them just to be sure nobody does something stupid
+ 	   like assuming they have some legal value.  */
+-	__asm__ ("" : "=r" (p4), "=r" (p5));
++	asm("" : "=r" (p4), "=r" (p5));
+ 
+ 	kernel_fpu_end();
+ }
+@@ -259,7 +259,7 @@ xor_p5_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+ 
+ 	kernel_fpu_begin();
+ 
+-	__asm__ __volatile__ (
++	asm volatile(
+ 	" .align 32	             ;\n"
+ 	" 1:                         ;\n"
+ 	"       movq   (%1), %%mm0   ;\n"
+@@ -286,7 +286,7 @@ xor_p5_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+ 	"       pxor 56(%2), %%mm7   ;\n"
+ 	"       movq %%mm6, 48(%1)   ;\n"
+ 	"       movq %%mm7, 56(%1)   ;\n"
+-	
++
+ 	"       addl $64, %1         ;\n"
+ 	"       addl $64, %2         ;\n"
+ 	"       decl %0              ;\n"
+@@ -307,7 +307,7 @@ xor_p5_mmx_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 
+ 	kernel_fpu_begin();
+ 
+-	__asm__ __volatile__ (
++	asm volatile(
+ 	" .align 32,0x90             ;\n"
+ 	" 1:                         ;\n"
+ 	"       movq   (%1), %%mm0   ;\n"
+@@ -342,7 +342,7 @@ xor_p5_mmx_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	"       pxor 56(%3), %%mm7   ;\n"
+ 	"       movq %%mm6, 48(%1)   ;\n"
+ 	"       movq %%mm7, 56(%1)   ;\n"
+-      
++
+ 	"       addl $64, %1         ;\n"
+ 	"       addl $64, %2         ;\n"
+ 	"       addl $64, %3         ;\n"
+@@ -364,7 +364,7 @@ xor_p5_mmx_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 
+ 	kernel_fpu_begin();
+ 
+-	__asm__ __volatile__ (
++	asm volatile(
+ 	" .align 32,0x90             ;\n"
+ 	" 1:                         ;\n"
+ 	"       movq   (%1), %%mm0   ;\n"
+@@ -407,7 +407,7 @@ xor_p5_mmx_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	"       pxor 56(%4), %%mm7   ;\n"
+ 	"       movq %%mm6, 48(%1)   ;\n"
+ 	"       movq %%mm7, 56(%1)   ;\n"
+-      
++
+ 	"       addl $64, %1         ;\n"
+ 	"       addl $64, %2         ;\n"
+ 	"       addl $64, %3         ;\n"
+@@ -436,9 +436,9 @@ xor_p5_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	   because we modify p4 and p5 there, but we can't mark them
+ 	   as read/write, otherwise we'd overflow the 10-asm-operands
+ 	   limit of GCC < 3.1.  */
+-	__asm__ ("" : "+r" (p4), "+r" (p5));
++	asm("" : "+r" (p4), "+r" (p5));
+ 
+-	__asm__ __volatile__ (
++	asm volatile(
+ 	" .align 32,0x90             ;\n"
+ 	" 1:                         ;\n"
+ 	"       movq   (%1), %%mm0   ;\n"
+@@ -489,7 +489,7 @@ xor_p5_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	"       pxor 56(%5), %%mm7   ;\n"
+ 	"       movq %%mm6, 48(%1)   ;\n"
+ 	"       movq %%mm7, 56(%1)   ;\n"
+-      
++
+ 	"       addl $64, %1         ;\n"
+ 	"       addl $64, %2         ;\n"
+ 	"       addl $64, %3         ;\n"
+@@ -505,7 +505,7 @@ xor_p5_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	/* p4 and p5 were modified, and now the variables are dead.
+ 	   Clobber them just to be sure nobody does something stupid
+ 	   like assuming they have some legal value.  */
+-	__asm__ ("" : "=r" (p4), "=r" (p5));
++	asm("" : "=r" (p4), "=r" (p5));
+ 
+ 	kernel_fpu_end();
+ }
+@@ -531,11 +531,12 @@ static struct xor_block_template xor_block_p5_mmx = {
+  * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo)
+  */
+ 
+-#define XMMS_SAVE do {				\
++#define XMMS_SAVE				\
++do {						\
+ 	preempt_disable();			\
+ 	cr0 = read_cr0();			\
+ 	clts();					\
+-	__asm__ __volatile__ ( 			\
++	asm volatile(				\
+ 		"movups %%xmm0,(%0)	;\n\t"	\
+ 		"movups %%xmm1,0x10(%0)	;\n\t"	\
+ 		"movups %%xmm2,0x20(%0)	;\n\t"	\
+@@ -543,10 +544,11 @@ static struct xor_block_template xor_block_p5_mmx = {
+ 		:				\
+ 		: "r" (xmm_save) 		\
+ 		: "memory");			\
+-} while(0)
++} while (0)
+ 
+-#define XMMS_RESTORE do {			\
+-	__asm__ __volatile__ ( 			\
++#define XMMS_RESTORE				\
++do {						\
++	asm volatile(				\
+ 		"sfence			;\n\t"	\
+ 		"movups (%0),%%xmm0	;\n\t"	\
+ 		"movups 0x10(%0),%%xmm1	;\n\t"	\
+@@ -557,76 +559,76 @@ static struct xor_block_template xor_block_p5_mmx = {
+ 		: "memory");			\
+ 	write_cr0(cr0);				\
+ 	preempt_enable();			\
+-} while(0)
++} while (0)
+ 
+ #define ALIGN16 __attribute__((aligned(16)))
+ 
+ #define OFFS(x)		"16*("#x")"
+ #define PF_OFFS(x)	"256+16*("#x")"
+ #define	PF0(x)		"	prefetchnta "PF_OFFS(x)"(%1)		;\n"
+-#define LD(x,y)		"       movaps   "OFFS(x)"(%1), %%xmm"#y"	;\n"
+-#define ST(x,y)		"       movaps %%xmm"#y",   "OFFS(x)"(%1)	;\n"
++#define LD(x, y)	"       movaps   "OFFS(x)"(%1), %%xmm"#y"	;\n"
++#define ST(x, y)	"       movaps %%xmm"#y",   "OFFS(x)"(%1)	;\n"
+ #define PF1(x)		"	prefetchnta "PF_OFFS(x)"(%2)		;\n"
+ #define PF2(x)		"	prefetchnta "PF_OFFS(x)"(%3)		;\n"
+ #define PF3(x)		"	prefetchnta "PF_OFFS(x)"(%4)		;\n"
+ #define PF4(x)		"	prefetchnta "PF_OFFS(x)"(%5)		;\n"
+ #define PF5(x)		"	prefetchnta "PF_OFFS(x)"(%6)		;\n"
+-#define XO1(x,y)	"       xorps   "OFFS(x)"(%2), %%xmm"#y"	;\n"
+-#define XO2(x,y)	"       xorps   "OFFS(x)"(%3), %%xmm"#y"	;\n"
+-#define XO3(x,y)	"       xorps   "OFFS(x)"(%4), %%xmm"#y"	;\n"
+-#define XO4(x,y)	"       xorps   "OFFS(x)"(%5), %%xmm"#y"	;\n"
+-#define XO5(x,y)	"       xorps   "OFFS(x)"(%6), %%xmm"#y"	;\n"
++#define XO1(x, y)	"       xorps   "OFFS(x)"(%2), %%xmm"#y"	;\n"
++#define XO2(x, y)	"       xorps   "OFFS(x)"(%3), %%xmm"#y"	;\n"
++#define XO3(x, y)	"       xorps   "OFFS(x)"(%4), %%xmm"#y"	;\n"
++#define XO4(x, y)	"       xorps   "OFFS(x)"(%5), %%xmm"#y"	;\n"
++#define XO5(x, y)	"       xorps   "OFFS(x)"(%6), %%xmm"#y"	;\n"
+ 
+ 
+ static void
+ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+ {
+-        unsigned long lines = bytes >> 8;
++	unsigned long lines = bytes >> 8;
+ 	char xmm_save[16*4] ALIGN16;
+ 	int cr0;
+ 
+ 	XMMS_SAVE;
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+-		LD(i,0)					\
+-			LD(i+1,1)			\
++#define BLOCK(i)					\
++		LD(i, 0)				\
++			LD(i + 1, 1)			\
+ 		PF1(i)					\
+-				PF1(i+2)		\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
+-		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
+-		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++				PF1(i + 2)		\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
++		XO1(i, 0)				\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
++		ST(i, 0)				\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addl $256, %1           ;\n"
+-        "       addl $256, %2           ;\n"
+-        "       decl %0                 ;\n"
+-        "       jnz 1b                  ;\n"
++	"       addl $256, %1           ;\n"
++	"       addl $256, %2           ;\n"
++	"       decl %0                 ;\n"
++	"       jnz 1b                  ;\n"
+ 	: "+r" (lines),
+ 	  "+r" (p1), "+r" (p2)
+ 	:
+-        : "memory");
++	: "memory");
+ 
+ 	XMMS_RESTORE;
+ }
+@@ -635,59 +637,59 @@ static void
+ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	  unsigned long *p3)
+ {
+-        unsigned long lines = bytes >> 8;
++	unsigned long lines = bytes >> 8;
+ 	char xmm_save[16*4] ALIGN16;
+ 	int cr0;
+ 
+ 	XMMS_SAVE;
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ 		PF1(i)					\
+-				PF1(i+2)		\
++				PF1(i + 2)		\
+ 		LD(i,0)					\
+-			LD(i+1,1)			\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
++			LD(i + 1, 1)			\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
+ 		PF2(i)					\
+-				PF2(i+2)		\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
++				PF2(i + 2)		\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
+ 		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
+ 		XO2(i,0)				\
+-			XO2(i+1,1)			\
+-				XO2(i+2,2)		\
+-					XO2(i+3,3)	\
++			XO2(i + 1, 1)			\
++				XO2(i + 2, 2)		\
++					XO2(i + 3, 3)	\
+ 		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addl $256, %1           ;\n"
+-        "       addl $256, %2           ;\n"
+-        "       addl $256, %3           ;\n"
+-        "       decl %0                 ;\n"
+-        "       jnz 1b                  ;\n"
++	"       addl $256, %1           ;\n"
++	"       addl $256, %2           ;\n"
++	"       addl $256, %3           ;\n"
++	"       decl %0                 ;\n"
++	"       jnz 1b                  ;\n"
+ 	: "+r" (lines),
+ 	  "+r" (p1), "+r"(p2), "+r"(p3)
+ 	:
+-        : "memory" );
++	: "memory" );
+ 
+ 	XMMS_RESTORE;
+ }
+@@ -696,66 +698,66 @@ static void
+ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	  unsigned long *p3, unsigned long *p4)
+ {
+-        unsigned long lines = bytes >> 8;
++	unsigned long lines = bytes >> 8;
+ 	char xmm_save[16*4] ALIGN16;
+ 	int cr0;
+ 
+ 	XMMS_SAVE;
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ 		PF1(i)					\
+-				PF1(i+2)		\
++				PF1(i + 2)		\
+ 		LD(i,0)					\
+-			LD(i+1,1)			\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
++			LD(i + 1, 1)			\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
+ 		PF2(i)					\
+-				PF2(i+2)		\
++				PF2(i + 2)		\
+ 		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
+ 		PF3(i)					\
+-				PF3(i+2)		\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
++				PF3(i + 2)		\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
+ 		XO2(i,0)				\
+-			XO2(i+1,1)			\
+-				XO2(i+2,2)		\
+-					XO2(i+3,3)	\
++			XO2(i + 1, 1)			\
++				XO2(i + 2, 2)		\
++					XO2(i + 3, 3)	\
+ 		XO3(i,0)				\
+-			XO3(i+1,1)			\
+-				XO3(i+2,2)		\
+-					XO3(i+3,3)	\
++			XO3(i + 1, 1)			\
++				XO3(i + 2, 2)		\
++					XO3(i + 3, 3)	\
+ 		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addl $256, %1           ;\n"
+-        "       addl $256, %2           ;\n"
+-        "       addl $256, %3           ;\n"
+-        "       addl $256, %4           ;\n"
+-        "       decl %0                 ;\n"
+-        "       jnz 1b                  ;\n"
++	"       addl $256, %1           ;\n"
++	"       addl $256, %2           ;\n"
++	"       addl $256, %3           ;\n"
++	"       addl $256, %4           ;\n"
++	"       decl %0                 ;\n"
++	"       jnz 1b                  ;\n"
+ 	: "+r" (lines),
+ 	  "+r" (p1), "+r" (p2), "+r" (p3), "+r" (p4)
+ 	:
+-        : "memory" );
++	: "memory" );
+ 
+ 	XMMS_RESTORE;
+ }
+@@ -764,7 +766,7 @@ static void
+ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	  unsigned long *p3, unsigned long *p4, unsigned long *p5)
+ {
+-        unsigned long lines = bytes >> 8;
++	unsigned long lines = bytes >> 8;
+ 	char xmm_save[16*4] ALIGN16;
+ 	int cr0;
+ 
+@@ -776,65 +778,65 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	   because we modify p4 and p5 there, but we can't mark them
+ 	   as read/write, otherwise we'd overflow the 10-asm-operands
+ 	   limit of GCC < 3.1.  */
+-	__asm__ ("" : "+r" (p4), "+r" (p5));
++	asm("" : "+r" (p4), "+r" (p5));
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ 		PF1(i)					\
+-				PF1(i+2)		\
++				PF1(i + 2)		\
+ 		LD(i,0)					\
+-			LD(i+1,1)			\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
++			LD(i + 1, 1)			\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
+ 		PF2(i)					\
+-				PF2(i+2)		\
++				PF2(i + 2)		\
+ 		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
+ 		PF3(i)					\
+-				PF3(i+2)		\
++				PF3(i + 2)		\
+ 		XO2(i,0)				\
+-			XO2(i+1,1)			\
+-				XO2(i+2,2)		\
+-					XO2(i+3,3)	\
++			XO2(i + 1, 1)			\
++				XO2(i + 2, 2)		\
++					XO2(i + 3, 3)	\
+ 		PF4(i)					\
+-				PF4(i+2)		\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
++				PF4(i + 2)		\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
+ 		XO3(i,0)				\
+-			XO3(i+1,1)			\
+-				XO3(i+2,2)		\
+-					XO3(i+3,3)	\
++			XO3(i + 1, 1)			\
++				XO3(i + 2, 2)		\
++					XO3(i + 3, 3)	\
+ 		XO4(i,0)				\
+-			XO4(i+1,1)			\
+-				XO4(i+2,2)		\
+-					XO4(i+3,3)	\
++			XO4(i + 1, 1)			\
++				XO4(i + 2, 2)		\
++					XO4(i + 3, 3)	\
+ 		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addl $256, %1           ;\n"
+-        "       addl $256, %2           ;\n"
+-        "       addl $256, %3           ;\n"
+-        "       addl $256, %4           ;\n"
+-        "       addl $256, %5           ;\n"
+-        "       decl %0                 ;\n"
+-        "       jnz 1b                  ;\n"
++	"       addl $256, %1           ;\n"
++	"       addl $256, %2           ;\n"
++	"       addl $256, %3           ;\n"
++	"       addl $256, %4           ;\n"
++	"       addl $256, %5           ;\n"
++	"       decl %0                 ;\n"
++	"       jnz 1b                  ;\n"
+ 	: "+r" (lines),
+ 	  "+r" (p1), "+r" (p2), "+r" (p3)
+ 	: "r" (p4), "r" (p5)
+@@ -843,17 +845,17 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	/* p4 and p5 were modified, and now the variables are dead.
+ 	   Clobber them just to be sure nobody does something stupid
+ 	   like assuming they have some legal value.  */
+-	__asm__ ("" : "=r" (p4), "=r" (p5));
++	asm("" : "=r" (p4), "=r" (p5));
+ 
+ 	XMMS_RESTORE;
+ }
+ 
+ static struct xor_block_template xor_block_pIII_sse = {
+-        .name = "pIII_sse",
+-        .do_2 =  xor_sse_2,
+-        .do_3 =  xor_sse_3,
+-        .do_4 =  xor_sse_4,
+-        .do_5 = xor_sse_5,
++	.name = "pIII_sse",
++	.do_2 = xor_sse_2,
++	.do_3 = xor_sse_3,
++	.do_4 = xor_sse_4,
++	.do_5 = xor_sse_5,
+ };
+ 
+ /* Also try the generic routines.  */
+@@ -861,21 +863,21 @@ static struct xor_block_template xor_block_pIII_sse = {
+ 
+ #undef XOR_TRY_TEMPLATES
+ #define XOR_TRY_TEMPLATES				\
+-	do {						\
+-		xor_speed(&xor_block_8regs);		\
+-		xor_speed(&xor_block_8regs_p);		\
+-		xor_speed(&xor_block_32regs);		\
+-		xor_speed(&xor_block_32regs_p);		\
+-	        if (cpu_has_xmm)			\
+-			xor_speed(&xor_block_pIII_sse);	\
+-	        if (cpu_has_mmx) {			\
+-	                xor_speed(&xor_block_pII_mmx);	\
+-	                xor_speed(&xor_block_p5_mmx);	\
+-	        }					\
+-	} while (0)
++do {							\
++	xor_speed(&xor_block_8regs);			\
++	xor_speed(&xor_block_8regs_p);			\
++	xor_speed(&xor_block_32regs);			\
++	xor_speed(&xor_block_32regs_p);			\
++	if (cpu_has_xmm)				\
++		xor_speed(&xor_block_pIII_sse);		\
++	if (cpu_has_mmx) {				\
++		xor_speed(&xor_block_pII_mmx);		\
++		xor_speed(&xor_block_p5_mmx);		\
++	}						\
++} while (0)
+ 
+ /* We force the use of the SSE xor block because it can write around L2.
+    We may also be able to load into the L1 only depending on how the cpu
+    deals with a load to a line that is being prefetched.  */
+-#define XOR_SELECT_TEMPLATE(FASTEST) \
++#define XOR_SELECT_TEMPLATE(FASTEST)			\
+ 	(cpu_has_xmm ? &xor_block_pIII_sse : FASTEST)
+diff --git a/include/asm-x86/xor_64.h b/include/asm-x86/xor_64.h
+index 1eee7fc..24957e3 100644
+--- a/include/asm-x86/xor_64.h
++++ b/include/asm-x86/xor_64.h
+@@ -24,20 +24,23 @@
+  */
+ 
+ /*
+- * x86-64 changes / gcc fixes from Andi Kleen. 
++ * x86-64 changes / gcc fixes from Andi Kleen.
+  * Copyright 2002 Andi Kleen, SuSE Labs.
+  *
+  * This hasn't been optimized for the hammer yet, but there are likely
+  * no advantages to be gotten from x86-64 here anyways.
+  */
+ 
+-typedef struct { unsigned long a,b; } __attribute__((aligned(16))) xmm_store_t;
++typedef struct {
++	unsigned long a, b;
++} __attribute__((aligned(16))) xmm_store_t;
+ 
+-/* Doesn't use gcc to save the XMM registers, because there is no easy way to 
++/* Doesn't use gcc to save the XMM registers, because there is no easy way to
+    tell it to do a clts before the register saving. */
+-#define XMMS_SAVE do {				\
++#define XMMS_SAVE				\
++do {						\
+ 	preempt_disable();			\
+-	asm volatile (				\
++	asm volatile(				\
+ 		"movq %%cr0,%0		;\n\t"	\
+ 		"clts			;\n\t"	\
+ 		"movups %%xmm0,(%1)	;\n\t"	\
+@@ -47,10 +50,11 @@ typedef struct { unsigned long a,b; } __attribute__((aligned(16))) xmm_store_t;
+ 		: "=&r" (cr0)			\
+ 		: "r" (xmm_save) 		\
+ 		: "memory");			\
+-} while(0)
++} while (0)
+ 
+-#define XMMS_RESTORE do {			\
+-	asm volatile (				\
++#define XMMS_RESTORE				\
++do {						\
++	asm volatile(				\
+ 		"sfence			;\n\t"	\
+ 		"movups (%1),%%xmm0	;\n\t"	\
+ 		"movups 0x10(%1),%%xmm1	;\n\t"	\
+@@ -61,72 +65,72 @@ typedef struct { unsigned long a,b; } __attribute__((aligned(16))) xmm_store_t;
+ 		: "r" (cr0), "r" (xmm_save)	\
+ 		: "memory");			\
+ 	preempt_enable();			\
+-} while(0)
++} while (0)
+ 
+ #define OFFS(x)		"16*("#x")"
+ #define PF_OFFS(x)	"256+16*("#x")"
+ #define	PF0(x)		"	prefetchnta "PF_OFFS(x)"(%[p1])		;\n"
+-#define LD(x,y)		"       movaps   "OFFS(x)"(%[p1]), %%xmm"#y"	;\n"
+-#define ST(x,y)		"       movaps %%xmm"#y",   "OFFS(x)"(%[p1])	;\n"
++#define LD(x, y)	"       movaps   "OFFS(x)"(%[p1]), %%xmm"#y"	;\n"
++#define ST(x, y)	"       movaps %%xmm"#y",   "OFFS(x)"(%[p1])	;\n"
+ #define PF1(x)		"	prefetchnta "PF_OFFS(x)"(%[p2])		;\n"
+ #define PF2(x)		"	prefetchnta "PF_OFFS(x)"(%[p3])		;\n"
+ #define PF3(x)		"	prefetchnta "PF_OFFS(x)"(%[p4])		;\n"
+ #define PF4(x)		"	prefetchnta "PF_OFFS(x)"(%[p5])		;\n"
+ #define PF5(x)		"	prefetchnta "PF_OFFS(x)"(%[p6])		;\n"
+-#define XO1(x,y)	"       xorps   "OFFS(x)"(%[p2]), %%xmm"#y"	;\n"
+-#define XO2(x,y)	"       xorps   "OFFS(x)"(%[p3]), %%xmm"#y"	;\n"
+-#define XO3(x,y)	"       xorps   "OFFS(x)"(%[p4]), %%xmm"#y"	;\n"
+-#define XO4(x,y)	"       xorps   "OFFS(x)"(%[p5]), %%xmm"#y"	;\n"
+-#define XO5(x,y)	"       xorps   "OFFS(x)"(%[p6]), %%xmm"#y"	;\n"
++#define XO1(x, y)	"       xorps   "OFFS(x)"(%[p2]), %%xmm"#y"	;\n"
++#define XO2(x, y)	"       xorps   "OFFS(x)"(%[p3]), %%xmm"#y"	;\n"
++#define XO3(x, y)	"       xorps   "OFFS(x)"(%[p4]), %%xmm"#y"	;\n"
++#define XO4(x, y)	"       xorps   "OFFS(x)"(%[p5]), %%xmm"#y"	;\n"
++#define XO5(x, y)	"       xorps   "OFFS(x)"(%[p6]), %%xmm"#y"	;\n"
+ 
+ 
+ static void
+ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+ {
+-        unsigned int lines = bytes >> 8;
++	unsigned int lines = bytes >> 8;
+ 	unsigned long cr0;
+ 	xmm_store_t xmm_save[4];
+ 
+ 	XMMS_SAVE;
+ 
+-        asm volatile (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+-		LD(i,0)					\
+-			LD(i+1,1)			\
++		LD(i, 0)				\
++			LD(i + 1, 1)			\
+ 		PF1(i)					\
+-				PF1(i+2)		\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
+-		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
+-		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++				PF1(i + 2)		\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
++		XO1(i, 0)				\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
++		ST(i, 0)				\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addq %[inc], %[p1]           ;\n"
+-        "       addq %[inc], %[p2]           ;\n"
++	"       addq %[inc], %[p1]           ;\n"
++	"       addq %[inc], %[p2]           ;\n"
+ 		"		decl %[cnt] ; jnz 1b"
+ 	: [p1] "+r" (p1), [p2] "+r" (p2), [cnt] "+r" (lines)
+-	: [inc] "r" (256UL) 
+-        : "memory");
++	: [inc] "r" (256UL)
++	: "memory");
+ 
+ 	XMMS_RESTORE;
+ }
+@@ -141,52 +145,52 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 
+ 	XMMS_SAVE;
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ 		PF1(i)					\
+-				PF1(i+2)		\
+-		LD(i,0)					\
+-			LD(i+1,1)			\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
++				PF1(i + 2)		\
++		LD(i, 0)					\
++			LD(i + 1, 1)			\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
+ 		PF2(i)					\
+-				PF2(i+2)		\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
+-		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
+-		XO2(i,0)				\
+-			XO2(i+1,1)			\
+-				XO2(i+2,2)		\
+-					XO2(i+3,3)	\
+-		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++				PF2(i + 2)		\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
++		XO1(i, 0)				\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
++		XO2(i, 0)				\
++			XO2(i + 1, 1)			\
++				XO2(i + 2, 2)		\
++					XO2(i + 3, 3)	\
++		ST(i, 0)				\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addq %[inc], %[p1]           ;\n"
+-        "       addq %[inc], %[p2]          ;\n"
+-        "       addq %[inc], %[p3]           ;\n"
++	"       addq %[inc], %[p1]           ;\n"
++	"       addq %[inc], %[p2]          ;\n"
++	"       addq %[inc], %[p3]           ;\n"
+ 		"		decl %[cnt] ; jnz 1b"
+ 	: [cnt] "+r" (lines),
+ 	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
+ 	: [inc] "r" (256UL)
+-	: "memory"); 
++	: "memory");
+ 	XMMS_RESTORE;
+ }
+ 
+@@ -195,64 +199,64 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	  unsigned long *p3, unsigned long *p4)
+ {
+ 	unsigned int lines = bytes >> 8;
+-	xmm_store_t xmm_save[4]; 
++	xmm_store_t xmm_save[4];
+ 	unsigned long cr0;
+ 
+ 	XMMS_SAVE;
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ 		PF1(i)					\
+-				PF1(i+2)		\
+-		LD(i,0)					\
+-			LD(i+1,1)			\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
++				PF1(i + 2)		\
++		LD(i, 0)				\
++			LD(i + 1, 1)			\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
+ 		PF2(i)					\
+-				PF2(i+2)		\
+-		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
++				PF2(i + 2)		\
++		XO1(i, 0)				\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
+ 		PF3(i)					\
+-				PF3(i+2)		\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
+-		XO2(i,0)				\
+-			XO2(i+1,1)			\
+-				XO2(i+2,2)		\
+-					XO2(i+3,3)	\
+-		XO3(i,0)				\
+-			XO3(i+1,1)			\
+-				XO3(i+2,2)		\
+-					XO3(i+3,3)	\
+-		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++				PF3(i + 2)		\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
++		XO2(i, 0)				\
++			XO2(i + 1, 1)			\
++				XO2(i + 2, 2)		\
++					XO2(i + 3, 3)	\
++		XO3(i, 0)				\
++			XO3(i + 1, 1)			\
++				XO3(i + 2, 2)		\
++					XO3(i + 3, 3)	\
++		ST(i, 0)				\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addq %[inc], %[p1]           ;\n"
+-        "       addq %[inc], %[p2]           ;\n"
+-        "       addq %[inc], %[p3]           ;\n"
+-        "       addq %[inc], %[p4]           ;\n"
++	"       addq %[inc], %[p1]           ;\n"
++	"       addq %[inc], %[p2]           ;\n"
++	"       addq %[inc], %[p3]           ;\n"
++	"       addq %[inc], %[p4]           ;\n"
+ 	"	decl %[cnt] ; jnz 1b"
+ 	: [cnt] "+c" (lines),
+ 	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
+ 	: [inc] "r" (256UL)
+-        : "memory" );
++	: "memory" );
+ 
+ 	XMMS_RESTORE;
+ }
+@@ -261,70 +265,70 @@ static void
+ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	  unsigned long *p3, unsigned long *p4, unsigned long *p5)
+ {
+-        unsigned int lines = bytes >> 8;
++	unsigned int lines = bytes >> 8;
+ 	xmm_store_t xmm_save[4];
+ 	unsigned long cr0;
+ 
+ 	XMMS_SAVE;
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ 		PF1(i)					\
+-				PF1(i+2)		\
+-		LD(i,0)					\
+-			LD(i+1,1)			\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
++				PF1(i + 2)		\
++		LD(i, 0)				\
++			LD(i + 1, 1)			\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
+ 		PF2(i)					\
+-				PF2(i+2)		\
+-		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
++				PF2(i + 2)		\
++		XO1(i, 0)				\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
+ 		PF3(i)					\
+-				PF3(i+2)		\
+-		XO2(i,0)				\
+-			XO2(i+1,1)			\
+-				XO2(i+2,2)		\
+-					XO2(i+3,3)	\
++				PF3(i + 2)		\
++		XO2(i, 0)				\
++			XO2(i + 1, 1)			\
++				XO2(i + 2, 2)		\
++					XO2(i + 3, 3)	\
+ 		PF4(i)					\
+-				PF4(i+2)		\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
+-		XO3(i,0)				\
+-			XO3(i+1,1)			\
+-				XO3(i+2,2)		\
+-					XO3(i+3,3)	\
+-		XO4(i,0)				\
+-			XO4(i+1,1)			\
+-				XO4(i+2,2)		\
+-					XO4(i+3,3)	\
+-		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++				PF4(i + 2)		\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
++		XO3(i, 0)				\
++			XO3(i + 1, 1)			\
++				XO3(i + 2, 2)		\
++					XO3(i + 3, 3)	\
++		XO4(i, 0)				\
++			XO4(i + 1, 1)			\
++				XO4(i + 2, 2)		\
++					XO4(i + 3, 3)	\
++		ST(i, 0)				\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addq %[inc], %[p1]           ;\n"
+-        "       addq %[inc], %[p2]           ;\n"
+-        "       addq %[inc], %[p3]           ;\n"
+-        "       addq %[inc], %[p4]           ;\n"
+-        "       addq %[inc], %[p5]           ;\n"
++	"       addq %[inc], %[p1]           ;\n"
++	"       addq %[inc], %[p2]           ;\n"
++	"       addq %[inc], %[p3]           ;\n"
++	"       addq %[inc], %[p4]           ;\n"
++	"       addq %[inc], %[p5]           ;\n"
+ 	"	decl %[cnt] ; jnz 1b"
+ 	: [cnt] "+c" (lines),
+-  	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4), 
++	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4),
+ 	  [p5] "+r" (p5)
+ 	: [inc] "r" (256UL)
+ 	: "memory");
+@@ -333,18 +337,18 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ }
+ 
+ static struct xor_block_template xor_block_sse = {
+-        .name = "generic_sse",
+-        .do_2 = xor_sse_2,
+-        .do_3 = xor_sse_3,
+-        .do_4 = xor_sse_4,
+-        .do_5 = xor_sse_5,
++	.name = "generic_sse",
++	.do_2 = xor_sse_2,
++	.do_3 = xor_sse_3,
++	.do_4 = xor_sse_4,
++	.do_5 = xor_sse_5,
+ };
+ 
+ #undef XOR_TRY_TEMPLATES
+-#define XOR_TRY_TEMPLATES				\
+-	do {						\
+-		xor_speed(&xor_block_sse);	\
+-	} while (0)
++#define XOR_TRY_TEMPLATES			\
++do {						\
++	xor_speed(&xor_block_sse);		\
++} while (0)
+ 
+ /* We force the use of the SSE xor block because it can write around L2.
+    We may also be able to load into the L1 only depending on how the cpu
+diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
+index 3e04167..d9b2034 100644
+--- a/include/asm-xtensa/semaphore.h
++++ b/include/asm-xtensa/semaphore.h
+@@ -1,99 +1 @@
+-/*
+- * linux/include/asm-xtensa/semaphore.h
+- *
+- * 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_SEMAPHORE_H
+-#define _XTENSA_SEMAPHORE_H
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+-	atomic_t count;
+-	int sleepers;
+-	wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name,n)					\
+-{									\
+-	.count		= ATOMIC_INIT(n),				\
+-	.sleepers	= 0,						\
+-	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) 			\
+-	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-	atomic_set(&sem->count, val);
+-	sem->sleepers = 0;
+-	init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+-	sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+-	sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int  __down_interruptible(struct semaphore * sem);
+-asmlinkage int  __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-static inline void down(struct semaphore * sem)
+-{
+-	might_sleep();
+-
+-	if (atomic_sub_return(1, &sem->count) < 0)
+-		__down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+-	int ret = 0;
+-
+-	might_sleep();
+-
+-	if (atomic_sub_return(1, &sem->count) < 0)
+-		ret = __down_interruptible(sem);
+-	return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+-	int ret = 0;
+-
+-	if (atomic_sub_return(1, &sem->count) < 0)
+-		ret = __down_trylock(sem);
+-	return ret;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- */
+-static inline void up(struct semaphore * sem)
+-{
+-	if (atomic_add_return(1, &sem->count) <= 0)
+-		__up(sem);
+-}
+-
+-#endif /* _XTENSA_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/crypto/aes.h b/include/crypto/aes.h
+index d480b76..40008d6 100644
+--- a/include/crypto/aes.h
++++ b/include/crypto/aes.h
+@@ -14,11 +14,13 @@
+ #define AES_KEYSIZE_192		24
+ #define AES_KEYSIZE_256		32
+ #define AES_BLOCK_SIZE		16
++#define AES_MAX_KEYLENGTH	(15 * 16)
++#define AES_MAX_KEYLENGTH_U32	(AES_MAX_KEYLENGTH / sizeof(u32))
+ 
+ struct crypto_aes_ctx {
+ 	u32 key_length;
+-	u32 key_enc[60];
+-	u32 key_dec[60];
++	u32 key_enc[AES_MAX_KEYLENGTH_U32];
++	u32 key_dec[AES_MAX_KEYLENGTH_U32];
+ };
+ 
+ extern u32 crypto_ft_tab[4][256];
+@@ -28,4 +30,6 @@ extern u32 crypto_il_tab[4][256];
+ 
+ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 		unsigned int key_len);
++int crypto_aes_expand_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
++		unsigned int key_len);
+ #endif
+diff --git a/include/keys/rxrpc-type.h b/include/keys/rxrpc-type.h
+index 4ea429b..7609365 100644
+--- a/include/keys/rxrpc-type.h
++++ b/include/keys/rxrpc-type.h
+@@ -21,4 +21,4 @@ extern struct key_type key_type_rxrpc;
+ 
+ extern struct key *rxrpc_get_null_key(const char *);
+ 
+-#endif /* _KEYS_USER_TYPE_H */
++#endif /* _KEYS_RXRPC_TYPE_H */
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index cedbbd8..bda6f04 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -100,7 +100,7 @@ header-y += ixjuser.h
+ header-y += jffs2.h
+ header-y += keyctl.h
+ header-y += limits.h
+-header-y += lock_dlm_plock.h
++header-y += dlm_plock.h
+ header-y += magic.h
+ header-y += major.h
+ header-y += matroxfb.h
+@@ -150,6 +150,7 @@ header-y += tiocl.h
+ header-y += tipc.h
+ header-y += tipc_config.h
+ header-y += toshiba.h
++header-y += udf_fs_i.h
+ header-y += ultrasound.h
+ header-y += un.h
+ header-y += utime.h
+@@ -209,8 +210,9 @@ unifdef-y += hayesesp.h
+ unifdef-y += hdlcdrv.h
+ unifdef-y += hdlc.h
+ unifdef-y += hdreg.h
+-unifdef-y += hdsmart.h
++unifdef-y += hid.h
+ unifdef-y += hiddev.h
++unifdef-y += hidraw.h
+ unifdef-y += hpet.h
+ unifdef-y += i2c.h
+ unifdef-y += i2c-dev.h
+@@ -231,7 +233,6 @@ unifdef-y += if_pppol2tp.h
+ unifdef-y += if_pppox.h
+ unifdef-y += if_tr.h
+ unifdef-y += if_vlan.h
+-unifdef-y += if_wanpipe.h
+ unifdef-y += igmp.h
+ unifdef-y += inet_diag.h
+ unifdef-y += in.h
+@@ -261,6 +262,7 @@ unifdef-y += mempolicy.h
+ unifdef-y += mii.h
+ unifdef-y += mman.h
+ unifdef-y += mroute.h
++unifdef-y += mroute6.h
+ unifdef-y += msdos_fs.h
+ unifdef-y += msg.h
+ unifdef-y += nbd.h
+@@ -289,6 +291,7 @@ unifdef-y += parport.h
+ unifdef-y += patchkey.h
+ unifdef-y += pci.h
+ unifdef-y += personality.h
++unifdef-y += pim.h
+ unifdef-y += pktcdvd.h
+ unifdef-y += pmu.h
+ unifdef-y += poll.h
+@@ -333,7 +336,6 @@ unifdef-y += time.h
+ unifdef-y += timex.h
+ unifdef-y += tty.h
+ unifdef-y += types.h
+-unifdef-y += udf_fs_i.h
+ unifdef-y += udp.h
+ unifdef-y += uinput.h
+ unifdef-y += uio.h
+diff --git a/include/linux/aer.h b/include/linux/aer.h
+index bcf236d..f251814 100644
+--- a/include/linux/aer.h
++++ b/include/linux/aer.h
+@@ -13,7 +13,6 @@ extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
+ extern int pci_find_aer_capability(struct pci_dev *dev);
+ extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
+ extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+-extern int pci_cleanup_aer_correct_error_status(struct pci_dev *dev);
+ #else
+ static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev)
+ {
+@@ -31,10 +30,6 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
+ {
+ 	return -EINVAL;
+ }
+-static inline int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
+-{
+-	return -EINVAL;
+-}
+ #endif
+ 
+ #endif //_AER_H_
+diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h
+index fde6758..a191607 100644
+--- a/include/linux/arcdevice.h
++++ b/include/linux/arcdevice.h
+@@ -283,8 +283,8 @@ struct arcnet_local {
+ 	int next_buf, first_free_buf;
+ 
+ 	/* network "reconfiguration" handling */
+-	time_t first_recon,	/* time of "first" RECON message to count */
+-		last_recon;	/* time of most recent RECON */
++	unsigned long first_recon; /* time of "first" RECON message to count */
++	unsigned long last_recon;  /* time of most recent RECON */
+ 	int num_recons;		/* number of RECONs between first and last. */
+ 	bool network_down;	/* do we think the network is down? */
+ 
+diff --git a/include/linux/ata_platform.h b/include/linux/ata_platform.h
+index b856a2a..9a26c83 100644
+--- a/include/linux/ata_platform.h
++++ b/include/linux/ata_platform.h
+@@ -27,7 +27,10 @@ extern int __devexit __pata_platform_remove(struct device *dev);
+ /*
+  * Marvell SATA private data
+  */
++struct mbus_dram_target_info;
++
+ struct mv_sata_platform_data {
++	struct mbus_dram_target_info	*dram;
+ 	int	n_ports; /* number of sata ports */
+ };
+ 
+diff --git a/include/linux/atalk.h b/include/linux/atalk.h
+index ced8a1e..e9ebac2 100644
+--- a/include/linux/atalk.h
++++ b/include/linux/atalk.h
+@@ -85,8 +85,6 @@ static inline struct atalk_sock *at_sk(struct sock *sk)
+ 	return (struct atalk_sock *)sk;
+ }
+ 
+-#include <asm/byteorder.h>
+-
+ struct ddpehdr {
+ 	__be16	deh_len_hops;	/* lower 10 bits are length, next 4 - hops */
+ 	__be16	deh_sum;
+diff --git a/include/linux/atmel_tc.h b/include/linux/atmel_tc.h
+new file mode 100644
+index 0000000..53ba65e
+--- /dev/null
++++ b/include/linux/atmel_tc.h
+@@ -0,0 +1,252 @@
++/*
++ * Timer/Counter Unit (TC) registers.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the 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 ATMEL_TC_H
++#define ATMEL_TC_H
++
++#include <linux/compiler.h>
++#include <linux/list.h>
++
++/*
++ * Many 32-bit Atmel SOCs include one or more TC blocks, each of which holds
++ * three general-purpose 16-bit timers.  These timers share one register bank.
++ * Depending on the SOC, each timer may have its own clock and IRQ, or those
++ * may be shared by the whole TC block.
++ *
++ * These TC blocks may have up to nine external pins:  TCLK0..2 signals for
++ * clocks or clock gates, and per-timer TIOA and TIOB signals used for PWM
++ * or triggering.  Those pins need to be set up for use with the TC block,
++ * else they will be used as GPIOs or for a different controller.
++ *
++ * Although we expect each TC block to have a platform_device node, those
++ * nodes are not what drivers bind to.  Instead, they ask for a specific
++ * TC block, by number ... which is a common approach on systems with many
++ * timers.  Then they use clk_get() and platform_get_irq() to get clock and
++ * IRQ resources.
++ */
++
++struct clk;
++
++/**
++ * struct atmel_tc - information about a Timer/Counter Block
++ * @pdev: physical device
++ * @iomem: resource associated with the I/O register
++ * @regs: mapping through which the I/O registers can be accessed
++ * @irq: irq for each of the three channels
++ * @clk: internal clock source for each of the three channels
++ * @node: list node, for tclib internal use
++ *
++ * On some platforms, each TC channel has its own clocks and IRQs,
++ * while on others, all TC channels share the same clock and IRQ.
++ * Drivers should clk_enable() all the clocks they need even though
++ * all the entries in @clk may point to the same physical clock.
++ * Likewise, drivers should request irqs independently for each
++ * channel, but they must use IRQF_SHARED in case some of the entries
++ * in @irq are actually the same IRQ.
++ */
++struct atmel_tc {
++	struct platform_device	*pdev;
++	struct resource		*iomem;
++	void __iomem		*regs;
++	int			irq[3];
++	struct clk		*clk[3];
++	struct list_head	node;
++};
++
++extern struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name);
++extern void atmel_tc_free(struct atmel_tc *tc);
++
++/* platform-specific ATMEL_TC_TIMER_CLOCKx divisors (0 means 32KiHz) */
++extern const u8 atmel_tc_divisors[5];
++
++
++/*
++ * Two registers have block-wide controls.  These are: configuring the three
++ * "external" clocks (or event sources) used by the timer channels; and
++ * synchronizing the timers by resetting them all at once.
++ *
++ * "External" can mean "external to chip" using the TCLK0, TCLK1, or TCLK2
++ * signals.  Or, it can mean "external to timer", using the TIOA output from
++ * one of the other two timers that's being run in waveform mode.
++ */
++
++#define ATMEL_TC_BCR	0xc0		/* TC Block Control Register */
++#define     ATMEL_TC_SYNC	(1 << 0)	/* synchronize timers */
++
++#define ATMEL_TC_BMR	0xc4		/* TC Block Mode Register */
++#define     ATMEL_TC_TC0XC0S	(3 << 0)	/* external clock 0 source */
++#define        ATMEL_TC_TC0XC0S_TCLK0	(0 << 0)
++#define        ATMEL_TC_TC0XC0S_NONE	(1 << 0)
++#define        ATMEL_TC_TC0XC0S_TIOA1	(2 << 0)
++#define        ATMEL_TC_TC0XC0S_TIOA2	(3 << 0)
++#define     ATMEL_TC_TC1XC1S	(3 << 2)	/* external clock 1 source */
++#define        ATMEL_TC_TC1XC1S_TCLK1	(0 << 2)
++#define        ATMEL_TC_TC1XC1S_NONE	(1 << 2)
++#define        ATMEL_TC_TC1XC1S_TIOA0	(2 << 2)
++#define        ATMEL_TC_TC1XC1S_TIOA2	(3 << 2)
++#define     ATMEL_TC_TC2XC2S	(3 << 4)	/* external clock 2 source */
++#define        ATMEL_TC_TC2XC2S_TCLK2	(0 << 4)
++#define        ATMEL_TC_TC2XC2S_NONE	(1 << 4)
++#define        ATMEL_TC_TC2XC2S_TIOA0	(2 << 4)
++#define        ATMEL_TC_TC2XC2S_TIOA1	(3 << 4)
++
++
++/*
++ * Each TC block has three "channels", each with one counter and controls.
++ *
++ * Note that the semantics of ATMEL_TC_TIMER_CLOCKx (input clock selection
++ * when it's not "external") is silicon-specific.  AT91 platforms use one
++ * set of definitions; AVR32 platforms use a different set.  Don't hard-wire
++ * such knowledge into your code, use the global "atmel_tc_divisors" ...
++ * where index N is the divisor for clock N+1, else zero to indicate it uses
++ * the 32 KiHz clock.
++ *
++ * The timers can be chained in various ways, and operated in "waveform"
++ * generation mode (including PWM) or "capture" mode (to time events).  In
++ * both modes, behavior can be configured in many ways.
++ *
++ * Each timer has two I/O pins, TIOA and TIOB.  Waveform mode uses TIOA as a
++ * PWM output, and TIOB as either another PWM or as a trigger.  Capture mode
++ * uses them only as inputs.
++ */
++#define ATMEL_TC_CHAN(idx)	((idx)*0x40)
++#define ATMEL_TC_REG(idx, reg)	(ATMEL_TC_CHAN(idx) + ATMEL_TC_ ## reg)
++
++#define ATMEL_TC_CCR	0x00		/* Channel Control Register */
++#define     ATMEL_TC_CLKEN	(1 << 0)	/* clock enable */
++#define     ATMEL_TC_CLKDIS	(1 << 1)	/* clock disable */
++#define     ATMEL_TC_SWTRG	(1 << 2)	/* software trigger */
++
++#define ATMEL_TC_CMR	0x04		/* Channel Mode Register */
++
++/* Both modes share some CMR bits */
++#define     ATMEL_TC_TCCLKS	(7 << 0)	/* clock source */
++#define        ATMEL_TC_TIMER_CLOCK1	(0 << 0)
++#define        ATMEL_TC_TIMER_CLOCK2	(1 << 0)
++#define        ATMEL_TC_TIMER_CLOCK3	(2 << 0)
++#define        ATMEL_TC_TIMER_CLOCK4	(3 << 0)
++#define        ATMEL_TC_TIMER_CLOCK5	(4 << 0)
++#define        ATMEL_TC_XC0		(5 << 0)
++#define        ATMEL_TC_XC1		(6 << 0)
++#define        ATMEL_TC_XC2		(7 << 0)
++#define     ATMEL_TC_CLKI	(1 << 3)	/* clock invert */
++#define     ATMEL_TC_BURST	(3 << 4)	/* clock gating */
++#define        ATMEL_TC_GATE_NONE	(0 << 4)
++#define        ATMEL_TC_GATE_XC0	(1 << 4)
++#define        ATMEL_TC_GATE_XC1	(2 << 4)
++#define        ATMEL_TC_GATE_XC2	(3 << 4)
++#define     ATMEL_TC_WAVE	(1 << 15)	/* true = Waveform mode */
++
++/* CAPTURE mode CMR bits */
++#define     ATMEL_TC_LDBSTOP	(1 << 6)	/* counter stops on RB load */
++#define     ATMEL_TC_LDBDIS	(1 << 7)	/* counter disable on RB load */
++#define     ATMEL_TC_ETRGEDG	(3 << 8)	/* external trigger edge */
++#define        ATMEL_TC_ETRGEDG_NONE	(0 << 8)
++#define        ATMEL_TC_ETRGEDG_RISING	(1 << 8)
++#define        ATMEL_TC_ETRGEDG_FALLING	(2 << 8)
++#define        ATMEL_TC_ETRGEDG_BOTH	(3 << 8)
++#define     ATMEL_TC_ABETRG	(1 << 10)	/* external trigger is TIOA? */
++#define     ATMEL_TC_CPCTRG	(1 << 14)	/* RC compare trigger enable */
++#define     ATMEL_TC_LDRA	(3 << 16)	/* RA loading edge (of TIOA) */
++#define        ATMEL_TC_LDRA_NONE	(0 << 16)
++#define        ATMEL_TC_LDRA_RISING	(1 << 16)
++#define        ATMEL_TC_LDRA_FALLING	(2 << 16)
++#define        ATMEL_TC_LDRA_BOTH	(3 << 16)
++#define     ATMEL_TC_LDRB	(3 << 18)	/* RB loading edge (of TIOA) */
++#define        ATMEL_TC_LDRB_NONE	(0 << 18)
++#define        ATMEL_TC_LDRB_RISING	(1 << 18)
++#define        ATMEL_TC_LDRB_FALLING	(2 << 18)
++#define        ATMEL_TC_LDRB_BOTH	(3 << 18)
++
++/* WAVEFORM mode CMR bits */
++#define     ATMEL_TC_CPCSTOP	(1 <<  6)	/* RC compare stops counter */
++#define     ATMEL_TC_CPCDIS	(1 <<  7)	/* RC compare disables counter */
++#define     ATMEL_TC_EEVTEDG	(3 <<  8)	/* external event edge */
++#define        ATMEL_TC_EEVTEDG_NONE	(0 << 8)
++#define        ATMEL_TC_EEVTEDG_RISING	(1 << 8)
++#define        ATMEL_TC_EEVTEDG_FALLING	(2 << 8)
++#define        ATMEL_TC_EEVTEDG_BOTH	(3 << 8)
++#define     ATMEL_TC_EEVT	(3 << 10)	/* external event source */
++#define        ATMEL_TC_EEVT_TIOB	(0 << 10)
++#define        ATMEL_TC_EEVT_XC0	(1 << 10)
++#define        ATMEL_TC_EEVT_XC1	(2 << 10)
++#define        ATMEL_TC_EEVT_XC2	(3 << 10)
++#define     ATMEL_TC_ENETRG	(1 << 12)	/* external event is trigger */
++#define     ATMEL_TC_WAVESEL	(3 << 13)	/* waveform type */
++#define        ATMEL_TC_WAVESEL_UP	(0 << 13)
++#define        ATMEL_TC_WAVESEL_UPDOWN	(1 << 13)
++#define        ATMEL_TC_WAVESEL_UP_AUTO	(2 << 13)
++#define        ATMEL_TC_WAVESEL_UPDOWN_AUTO (3 << 13)
++#define     ATMEL_TC_ACPA	(3 << 16)	/* RA compare changes TIOA */
++#define        ATMEL_TC_ACPA_NONE	(0 << 16)
++#define        ATMEL_TC_ACPA_SET	(1 << 16)
++#define        ATMEL_TC_ACPA_CLEAR	(2 << 16)
++#define        ATMEL_TC_ACPA_TOGGLE	(3 << 16)
++#define     ATMEL_TC_ACPC	(3 << 18)	/* RC compare changes TIOA */
++#define        ATMEL_TC_ACPC_NONE	(0 << 18)
++#define        ATMEL_TC_ACPC_SET	(1 << 18)
++#define        ATMEL_TC_ACPC_CLEAR	(2 << 18)
++#define        ATMEL_TC_ACPC_TOGGLE	(3 << 18)
++#define     ATMEL_TC_AEEVT	(3 << 20)	/* external event changes TIOA */
++#define        ATMEL_TC_AEEVT_NONE	(0 << 20)
++#define        ATMEL_TC_AEEVT_SET	(1 << 20)
++#define        ATMEL_TC_AEEVT_CLEAR	(2 << 20)
++#define        ATMEL_TC_AEEVT_TOGGLE	(3 << 20)
++#define     ATMEL_TC_ASWTRG	(3 << 22)	/* software trigger changes TIOA */
++#define        ATMEL_TC_ASWTRG_NONE	(0 << 22)
++#define        ATMEL_TC_ASWTRG_SET	(1 << 22)
++#define        ATMEL_TC_ASWTRG_CLEAR	(2 << 22)
++#define        ATMEL_TC_ASWTRG_TOGGLE	(3 << 22)
++#define     ATMEL_TC_BCPB	(3 << 24)	/* RB compare changes TIOB */
++#define        ATMEL_TC_BCPB_NONE	(0 << 24)
++#define        ATMEL_TC_BCPB_SET	(1 << 24)
++#define        ATMEL_TC_BCPB_CLEAR	(2 << 24)
++#define        ATMEL_TC_BCPB_TOGGLE	(3 << 24)
++#define     ATMEL_TC_BCPC	(3 << 26)	/* RC compare changes TIOB */
++#define        ATMEL_TC_BCPC_NONE	(0 << 26)
++#define        ATMEL_TC_BCPC_SET	(1 << 26)
++#define        ATMEL_TC_BCPC_CLEAR	(2 << 26)
++#define        ATMEL_TC_BCPC_TOGGLE	(3 << 26)
++#define     ATMEL_TC_BEEVT	(3 << 28)	/* external event changes TIOB */
++#define        ATMEL_TC_BEEVT_NONE	(0 << 28)
++#define        ATMEL_TC_BEEVT_SET	(1 << 28)
++#define        ATMEL_TC_BEEVT_CLEAR	(2 << 28)
++#define        ATMEL_TC_BEEVT_TOGGLE	(3 << 28)
++#define     ATMEL_TC_BSWTRG	(3 << 30)	/* software trigger changes TIOB */
++#define        ATMEL_TC_BSWTRG_NONE	(0 << 30)
++#define        ATMEL_TC_BSWTRG_SET	(1 << 30)
++#define        ATMEL_TC_BSWTRG_CLEAR	(2 << 30)
++#define        ATMEL_TC_BSWTRG_TOGGLE	(3 << 30)
++
++#define ATMEL_TC_CV	0x10		/* counter Value */
++#define ATMEL_TC_RA	0x14		/* register A */
++#define ATMEL_TC_RB	0x18		/* register B */
++#define ATMEL_TC_RC	0x1c		/* register C */
++
++#define ATMEL_TC_SR	0x20		/* status (read-only) */
++/* Status-only flags */
++#define     ATMEL_TC_CLKSTA	(1 << 16)	/* clock enabled */
++#define     ATMEL_TC_MTIOA	(1 << 17)	/* TIOA mirror */
++#define     ATMEL_TC_MTIOB	(1 << 18)	/* TIOB mirror */
++
++#define ATMEL_TC_IER	0x24		/* interrupt enable (write-only) */
++#define ATMEL_TC_IDR	0x28		/* interrupt disable (write-only) */
++#define ATMEL_TC_IMR	0x2c		/* interrupt mask (read-only) */
++
++/* Status and IRQ flags */
++#define     ATMEL_TC_COVFS	(1 <<  0)	/* counter overflow */
++#define     ATMEL_TC_LOVRS	(1 <<  1)	/* load overrun */
++#define     ATMEL_TC_CPAS	(1 <<  2)	/* RA compare */
++#define     ATMEL_TC_CPBS	(1 <<  3)	/* RB compare */
++#define     ATMEL_TC_CPCS	(1 <<  4)	/* RC compare */
++#define     ATMEL_TC_LDRAS	(1 <<  5)	/* RA loading */
++#define     ATMEL_TC_LDRBS	(1 <<  6)	/* RB loading */
++#define     ATMEL_TC_ETRGS	(1 <<  7)	/* external trigger */
++
++#endif
+diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
+index f558233..794ad74 100644
+--- a/include/linux/attribute_container.h
++++ b/include/linux/attribute_container.h
+@@ -1,5 +1,5 @@
+ /*
+- * class_container.h - a generic container for all classes
++ * attribute_container.h - a generic container for all classes
+  *
+  * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+  *
+@@ -18,7 +18,7 @@ struct attribute_container {
+ 	struct klist		containers;
+ 	struct class		*class;
+ 	struct attribute_group	*grp;
+-	struct class_device_attribute **attrs;
++	struct device_attribute **attrs;
+ 	int (*match)(struct attribute_container *, struct device *);
+ #define	ATTRIBUTE_CONTAINER_NO_CLASSDEVS	0x01
+ 	unsigned long		flags;
+@@ -37,35 +37,35 @@ attribute_container_set_no_classdevs(struct attribute_container *atc)
+ }
+ 
+ int attribute_container_register(struct attribute_container *cont);
+-int attribute_container_unregister(struct attribute_container *cont);
++int __must_check attribute_container_unregister(struct attribute_container *cont);
+ void attribute_container_create_device(struct device *dev,
+ 				       int (*fn)(struct attribute_container *,
+ 						 struct device *,
+-						 struct class_device *));
++						 struct device *));
+ void attribute_container_add_device(struct device *dev,
+ 				    int (*fn)(struct attribute_container *,
+ 					      struct device *,
+-					      struct class_device *));
++					      struct device *));
+ void attribute_container_remove_device(struct device *dev,
+ 				       void (*fn)(struct attribute_container *,
+ 						  struct device *,
+-						  struct class_device *));
++						  struct device *));
+ void attribute_container_device_trigger(struct device *dev, 
+ 					int (*fn)(struct attribute_container *,
+ 						  struct device *,
+-						  struct class_device *));
++						  struct device *));
+ void attribute_container_trigger(struct device *dev, 
+ 				 int (*fn)(struct attribute_container *,
+ 					   struct device *));
+-int attribute_container_add_attrs(struct class_device *classdev);
+-int attribute_container_add_class_device(struct class_device *classdev);
++int attribute_container_add_attrs(struct device *classdev);
++int attribute_container_add_class_device(struct device *classdev);
+ int attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ 						 struct device *dev,
+-						 struct class_device *classdev);
+-void attribute_container_remove_attrs(struct class_device *classdev);
+-void attribute_container_class_device_del(struct class_device *classdev);
+-struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+-struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
+-struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
++						 struct device *classdev);
++void attribute_container_remove_attrs(struct device *classdev);
++void attribute_container_class_device_del(struct device *classdev);
++struct attribute_container *attribute_container_classdev_to_container(struct device *);
++struct device *attribute_container_find_class_device(struct attribute_container *, struct device *);
++struct device_attribute **attribute_container_classdev_to_attrs(const struct device *classdev);
+ 
+ #endif
+diff --git a/include/linux/audit.h b/include/linux/audit.h
+index 2af9ec0..4ccb048 100644
+--- a/include/linux/audit.h
++++ b/include/linux/audit.h
+@@ -353,6 +353,33 @@ struct netlink_skb_parms;
+ struct linux_binprm;
+ struct mq_attr;
+ struct mqstat;
++struct audit_watch;
++struct audit_tree;
++
++struct audit_krule {
++	int			vers_ops;
++	u32			flags;
++	u32			listnr;
++	u32			action;
++	u32			mask[AUDIT_BITMASK_SIZE];
++	u32			buflen; /* for data alloc on list rules */
++	u32			field_count;
++	char			*filterkey; /* ties events to rules */
++	struct audit_field	*fields;
++	struct audit_field	*arch_f; /* quick access to arch field */
++	struct audit_field	*inode_f; /* quick access to an inode field */
++	struct audit_watch	*watch;	/* associated watch */
++	struct audit_tree	*tree;	/* associated watched tree */
++	struct list_head	rlist;	/* entry in audit_{watch,tree}.rules list */
++};
++
++struct audit_field {
++	u32				type;
++	u32				val;
++	u32				op;
++	char				*lsm_str;
++	void				*lsm_rule;
++};
+ 
+ #define AUDITSC_INVALID 0
+ #define AUDITSC_SUCCESS 1
+@@ -536,6 +563,8 @@ extern void		    audit_log_d_path(struct audit_buffer *ab,
+ 					     const char *prefix,
+ 					     struct path *path);
+ extern void		    audit_log_lost(const char *message);
++extern int		    audit_update_lsm_rules(void);
++
+ 				/* Private API (for audit.c only) */
+ extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
+ extern int audit_filter_type(int type);
+diff --git a/include/linux/bio.h b/include/linux/bio.h
+index 4c59bdc..d259690 100644
+--- a/include/linux/bio.h
++++ b/include/linux/bio.h
+@@ -327,6 +327,8 @@ extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
+ extern void bio_set_pages_dirty(struct bio *bio);
+ extern void bio_check_pages_dirty(struct bio *bio);
+ extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
++extern struct bio *bio_copy_user_iov(struct request_queue *, struct sg_iovec *,
++				     int, int);
+ extern int bio_uncopy_user(struct bio *);
+ void zero_fill_bio(struct bio *bio);
+ 
+diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
+index acad110..1dbe074 100644
+--- a/include/linux/bitmap.h
++++ b/include/linux/bitmap.h
+@@ -108,6 +108,7 @@ extern int __bitmap_weight(const unsigned long *bitmap, int bits);
+ 
+ extern int bitmap_scnprintf(char *buf, unsigned int len,
+ 			const unsigned long *src, int nbits);
++extern int bitmap_scnprintf_len(unsigned int len);
+ extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
+ 			unsigned long *dst, int nbits);
+ extern int bitmap_parse_user(const char __user *ubuf, unsigned int ulen,
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 6f79d40..c5065e3 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -112,6 +112,7 @@ enum rq_flag_bits {
+ 	__REQ_RW_SYNC,		/* request is sync (O_DIRECT) */
+ 	__REQ_ALLOCED,		/* request came from our alloc pool */
+ 	__REQ_RW_META,		/* metadata io request */
++	__REQ_COPY_USER,	/* contains copies of user pages */
+ 	__REQ_NR_BITS,		/* stops here */
+ };
+ 
+@@ -133,6 +134,7 @@ enum rq_flag_bits {
+ #define REQ_RW_SYNC	(1 << __REQ_RW_SYNC)
+ #define REQ_ALLOCED	(1 << __REQ_ALLOCED)
+ #define REQ_RW_META	(1 << __REQ_RW_META)
++#define REQ_COPY_USER	(1 << __REQ_COPY_USER)
+ 
+ #define BLK_MAX_CDB	16
+ 
+@@ -533,8 +535,13 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn;
+  * BLK_BOUNCE_ANY	: don't bounce anything
+  * BLK_BOUNCE_ISA	: bounce pages above ISA DMA boundary
+  */
++
++#if BITS_PER_LONG == 32
+ #define BLK_BOUNCE_HIGH		((u64)blk_max_low_pfn << PAGE_SHIFT)
+-#define BLK_BOUNCE_ANY		((u64)blk_max_pfn << PAGE_SHIFT)
++#else
++#define BLK_BOUNCE_HIGH		-1ULL
++#endif
++#define BLK_BOUNCE_ANY		(-1ULL)
+ #define BLK_BOUNCE_ISA		(ISA_DMA_THRESHOLD)
+ 
+ /*
+diff --git a/include/linux/bsg.h b/include/linux/bsg.h
+index 60e377b..e8406c5 100644
+--- a/include/linux/bsg.h
++++ b/include/linux/bsg.h
+@@ -55,7 +55,7 @@ struct sg_io_v4 {
+ 
+ #if defined(CONFIG_BLK_DEV_BSG)
+ struct bsg_class_device {
+-	struct class_device *class_dev;
++	struct device *class_dev;
+ 	struct device *dev;
+ 	int minor;
+ 	struct request_queue *queue;
+diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
+index a5cd204..5db265e 100644
+--- a/include/linux/cdrom.h
++++ b/include/linux/cdrom.h
+@@ -910,6 +910,7 @@ struct mode_page_header {
+ #ifdef __KERNEL__
+ #include <linux/fs.h>		/* not really needed, later.. */
+ #include <linux/device.h>
++#include <linux/list.h>
+ 
+ struct packet_command
+ {
+@@ -934,7 +935,7 @@ struct packet_command
+ /* Uniform cdrom data structures for cdrom.c */
+ struct cdrom_device_info {
+ 	struct cdrom_device_ops  *ops;  /* link to device_ops */
+-	struct cdrom_device_info *next; /* next device_info for this major */
++	struct list_head list;		/* linked list of all device_info */
+ 	struct gendisk *disk;		/* matching block layer disk */
+ 	void *handle;		        /* driver-dependent data */
+ /* specifications */
+@@ -994,7 +995,7 @@ extern int cdrom_ioctl(struct file *file, struct cdrom_device_info *cdi,
+ extern int cdrom_media_changed(struct cdrom_device_info *);
+ 
+ extern int register_cdrom(struct cdrom_device_info *cdi);
+-extern int unregister_cdrom(struct cdrom_device_info *cdi);
++extern void unregister_cdrom(struct cdrom_device_info *cdi);
+ 
+ typedef struct {
+     int data;
+diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
+index 85778a4..3509447 100644
+--- a/include/linux/clocksource.h
++++ b/include/linux/clocksource.h
+@@ -216,6 +216,7 @@ static inline void clocksource_calculate_interval(struct clocksource *c,
+ /* used to install a new clocksource */
+ extern int clocksource_register(struct clocksource*);
+ extern void clocksource_unregister(struct clocksource*);
++extern void clocksource_touch_watchdog(void);
+ extern struct clocksource* clocksource_get_next(void);
+ extern void clocksource_change_rating(struct clocksource *cs, int rating);
+ extern void clocksource_resume(void);
+diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
+index fe23792..b2fd754 100644
+--- a/include/linux/compiler-gcc.h
++++ b/include/linux/compiler-gcc.h
+@@ -28,9 +28,16 @@
+ #define __must_be_array(a) \
+   BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
+ 
+-#define inline		inline		__attribute__((always_inline))
+-#define __inline__	__inline__	__attribute__((always_inline))
+-#define __inline	__inline	__attribute__((always_inline))
++/*
++ * Force always-inline if the user requests it so via the .config:
++ */
++#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
++    !defined(CONFIG_OPTIMIZE_INLINING) && (__GNUC__ >= 4)
++# define inline		inline		__attribute__((always_inline))
++# define __inline__	__inline__	__attribute__((always_inline))
++# define __inline	__inline	__attribute__((always_inline))
++#endif
++
+ #define __deprecated			__attribute__((deprecated))
+ #define __packed			__attribute__((packed))
+ #define __weak				__attribute__((weak))
+diff --git a/include/linux/cpu.h b/include/linux/cpu.h
+index 0be8d65..f212fa9 100644
+--- a/include/linux/cpu.h
++++ b/include/linux/cpu.h
+@@ -23,7 +23,6 @@
+ #include <linux/node.h>
+ #include <linux/compiler.h>
+ #include <linux/cpumask.h>
+-#include <asm/semaphore.h>
+ #include <linux/mutex.h>
+ 
+ struct cpu {
+diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
+index 7047f58..259c805 100644
+--- a/include/linux/cpumask.h
++++ b/include/linux/cpumask.h
+@@ -222,8 +222,13 @@ int __next_cpu(int n, const cpumask_t *srcp);
+ #define next_cpu(n, src)	({ (void)(src); 1; })
+ #endif
+ 
++#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
++extern cpumask_t *cpumask_of_cpu_map;
++#define cpumask_of_cpu(cpu)    (cpumask_of_cpu_map[cpu])
++
++#else
+ #define cpumask_of_cpu(cpu)						\
+-({									\
++(*({									\
+ 	typeof(_unused_cpumask_arg_) m;					\
+ 	if (sizeof(m) == sizeof(unsigned long)) {			\
+ 		m.bits[0] = 1UL<<(cpu);					\
+@@ -231,8 +236,9 @@ int __next_cpu(int n, const cpumask_t *srcp);
+ 		cpus_clear(m);						\
+ 		cpu_set((cpu), m);					\
+ 	}								\
+-	m;								\
+-})
++	&m;								\
++}))
++#endif
+ 
+ #define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS)
+ 
+@@ -243,6 +249,8 @@ int __next_cpu(int n, const cpumask_t *srcp);
+ 	[BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD			\
+ } }
+ 
++#define CPU_MASK_ALL_PTR	(&CPU_MASK_ALL)
++
+ #else
+ 
+ #define CPU_MASK_ALL							\
+@@ -251,6 +259,10 @@ int __next_cpu(int n, const cpumask_t *srcp);
+ 	[BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD			\
+ } }
+ 
++/* cpu_mask_all is in init/main.c */
++extern cpumask_t cpu_mask_all;
++#define CPU_MASK_ALL_PTR	(&cpu_mask_all)
++
+ #endif
+ 
+ #define CPU_MASK_NONE							\
+@@ -273,6 +285,13 @@ static inline int __cpumask_scnprintf(char *buf, int len,
+ 	return bitmap_scnprintf(buf, len, srcp->bits, nbits);
+ }
+ 
++#define cpumask_scnprintf_len(len) \
++			__cpumask_scnprintf_len((len))
++static inline int __cpumask_scnprintf_len(int len)
++{
++	return bitmap_scnprintf_len(len);
++}
++
+ #define cpumask_parse_user(ubuf, ulen, dst) \
+ 			__cpumask_parse_user((ubuf), (ulen), &(dst), NR_CPUS)
+ static inline int __cpumask_parse_user(const char __user *buf, int len,
+diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
+index 0a26be3..726761e 100644
+--- a/include/linux/cpuset.h
++++ b/include/linux/cpuset.h
+@@ -20,8 +20,8 @@ extern int number_of_cpusets;	/* How many cpusets are defined in system? */
+ extern int cpuset_init_early(void);
+ extern int cpuset_init(void);
+ extern void cpuset_init_smp(void);
+-extern cpumask_t cpuset_cpus_allowed(struct task_struct *p);
+-extern cpumask_t cpuset_cpus_allowed_locked(struct task_struct *p);
++extern void cpuset_cpus_allowed(struct task_struct *p, cpumask_t *mask);
++extern void cpuset_cpus_allowed_locked(struct task_struct *p, cpumask_t *mask);
+ extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
+ #define cpuset_current_mems_allowed (current->mems_allowed)
+ void cpuset_init_current_mems_allowed(void);
+@@ -84,13 +84,14 @@ static inline int cpuset_init_early(void) { return 0; }
+ static inline int cpuset_init(void) { return 0; }
+ static inline void cpuset_init_smp(void) {}
+ 
+-static inline cpumask_t cpuset_cpus_allowed(struct task_struct *p)
++static inline void cpuset_cpus_allowed(struct task_struct *p, cpumask_t *mask)
+ {
+-	return cpu_possible_map;
++	*mask = cpu_possible_map;
+ }
+-static inline cpumask_t cpuset_cpus_allowed_locked(struct task_struct *p)
++static inline void cpuset_cpus_allowed_locked(struct task_struct *p,
++								cpumask_t *mask)
+ {
+-	return cpu_possible_map;
++	*mask = cpu_possible_map;
+ }
+ 
+ static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
+diff --git a/include/linux/crypto.h b/include/linux/crypto.h
+index 5e02d1b..425824b 100644
+--- a/include/linux/crypto.h
++++ b/include/linux/crypto.h
+@@ -317,14 +317,7 @@ int crypto_unregister_alg(struct crypto_alg *alg);
+ /*
+  * Algorithm query interface.
+  */
+-#ifdef CONFIG_CRYPTO
+ int crypto_has_alg(const char *name, u32 type, u32 mask);
+-#else
+-static inline int crypto_has_alg(const char *name, u32 type, u32 mask)
+-{
+-	return 0;
+-}
+-#endif
+ 
+ /*
+  * Transforms: user-instantiated objects which encapsulate algorithms
+diff --git a/include/linux/dcache.h b/include/linux/dcache.h
+index 6bd6460..cfb1627 100644
+--- a/include/linux/dcache.h
++++ b/include/linux/dcache.h
+@@ -301,7 +301,9 @@ extern int d_validate(struct dentry *, struct dentry *);
+  */
+ extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+ 
++extern char *__d_path(const struct path *path, struct path *root, char *, int);
+ extern char *d_path(struct path *, char *, int);
++extern char *dentry_path(struct dentry *, char *, int);
+ 
+ /* Allocation counts.. */
+ 
+@@ -359,7 +361,6 @@ static inline int d_mountpoint(struct dentry *dentry)
+ }
+ 
+ extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *);
+-extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
+ extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
+ 
+ extern int sysctl_vfs_cache_pressure;
+diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
+index cb78457..ad3b787 100644
+--- a/include/linux/device-mapper.h
++++ b/include/linux/device-mapper.h
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright (C) 2001 Sistina Software (UK) Limited.
+- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+  *
+  * This file is released under the LGPL.
+  */
+@@ -10,6 +10,8 @@
+ 
+ #ifdef __KERNEL__
+ 
++#include <linux/bio.h>
++
+ struct dm_target;
+ struct dm_table;
+ struct dm_dev;
+@@ -250,11 +252,97 @@ void dm_table_event(struct dm_table *t);
+  */
+ int dm_swap_table(struct mapped_device *md, struct dm_table *t);
+ 
++/*-----------------------------------------------------------------
++ * Macros.
++ *---------------------------------------------------------------*/
++#define DM_NAME "device-mapper"
++
++#define DMERR(f, arg...) \
++	printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
++#define DMERR_LIMIT(f, arg...) \
++	do { \
++		if (printk_ratelimit())	\
++			printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
++			       f "\n", ## arg); \
++	} while (0)
++
++#define DMWARN(f, arg...) \
++	printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
++#define DMWARN_LIMIT(f, arg...) \
++	do { \
++		if (printk_ratelimit())	\
++			printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
++			       f "\n", ## arg); \
++	} while (0)
++
++#define DMINFO(f, arg...) \
++	printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
++#define DMINFO_LIMIT(f, arg...) \
++	do { \
++		if (printk_ratelimit())	\
++			printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
++			       "\n", ## arg); \
++	} while (0)
++
++#ifdef CONFIG_DM_DEBUG
++#  define DMDEBUG(f, arg...) \
++	printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
++#  define DMDEBUG_LIMIT(f, arg...) \
++	do { \
++		if (printk_ratelimit())	\
++			printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
++			       "\n", ## arg); \
++	} while (0)
++#else
++#  define DMDEBUG(f, arg...) do {} while (0)
++#  define DMDEBUG_LIMIT(f, arg...) do {} while (0)
++#endif
++
++#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
++			  0 : scnprintf(result + sz, maxlen - sz, x))
++
++#define SECTOR_SHIFT 9
++
++/*
++ * Definitions of return values from target end_io function.
++ */
++#define DM_ENDIO_INCOMPLETE	1
++#define DM_ENDIO_REQUEUE	2
++
++/*
++ * Definitions of return values from target map function.
++ */
++#define DM_MAPIO_SUBMITTED	0
++#define DM_MAPIO_REMAPPED	1
++#define DM_MAPIO_REQUEUE	DM_ENDIO_REQUEUE
++
++/*
++ * Ceiling(n / sz)
++ */
++#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
++
++#define dm_sector_div_up(n, sz) ( \
++{ \
++	sector_t _r = ((n) + (sz) - 1); \
++	sector_div(_r, (sz)); \
++	_r; \
++} \
++)
++
+ /*
+- * Prepare a table for a device that will error all I/O.
+- * To make it active, call dm_suspend(), dm_swap_table() then dm_resume().
++ * ceiling(n / size) * size
+  */
+-int dm_create_error_table(struct dm_table **result, struct mapped_device *md);
++#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
++
++static inline sector_t to_sector(unsigned long n)
++{
++	return (n >> SECTOR_SHIFT);
++}
++
++static inline unsigned long to_bytes(sector_t n)
++{
++	return (n << SECTOR_SHIFT);
++}
+ 
+ #endif	/* __KERNEL__ */
+ #endif	/* _LINUX_DEVICE_MAPPER_H */
+diff --git a/include/linux/device.h b/include/linux/device.h
+index 2258d89..1a06026 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -20,7 +20,7 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/pm.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+ #include <asm/device.h>
+ 
+@@ -429,7 +429,6 @@ struct device {
+ 	struct kobject kobj;
+ 	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */
+ 	struct device_type	*type;
+-	unsigned		is_registered:1;
+ 	unsigned		uevent_suppress:1;
+ 
+ 	struct semaphore	sem;	/* semaphore to synchronize calls to
+@@ -475,6 +474,9 @@ struct device {
+ 	void	(*release)(struct device *dev);
+ };
+ 
++/* Get the wakeup routines, which depend on struct device */
++#include <linux/pm_wakeup.h>
++
+ #ifdef CONFIG_NUMA
+ static inline int dev_to_node(struct device *dev)
+ {
+@@ -506,7 +508,7 @@ static inline void dev_set_drvdata(struct device *dev, void *data)
+ 
+ static inline int device_is_registered(struct device *dev)
+ {
+-	return dev->is_registered;
++	return dev->kobj.state_in_sysfs;
+ }
+ 
+ void driver_init(void);
+@@ -543,20 +545,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
+ 				    dev_t devt, const char *fmt, ...)
+ 				    __attribute__((format(printf, 4, 5)));
+ extern void device_destroy(struct class *cls, dev_t devt);
+-#ifdef CONFIG_PM_SLEEP
+-extern void destroy_suspended_device(struct class *cls, dev_t devt);
+-extern void device_pm_schedule_removal(struct device *);
+-#else /* !CONFIG_PM_SLEEP */
+-static inline void destroy_suspended_device(struct class *cls, dev_t devt)
+-{
+-	device_destroy(cls, devt);
+-}
+-
+-static inline void device_pm_schedule_removal(struct device *dev)
+-{
+-	device_unregister(dev);
+-}
+-#endif /* !CONFIG_PM_SLEEP */
+ 
+ /*
+  * Platform "fixup" functions - allow the platform to have their say
+@@ -608,21 +596,16 @@ extern const char *dev_driver_string(struct device *dev);
+ #define dev_dbg(dev, format, arg...)		\
+ 	dev_printk(KERN_DEBUG , dev , format , ## arg)
+ #else
+-static inline int __attribute__ ((format (printf, 2, 3)))
+-dev_dbg(struct device *dev, const char *fmt, ...)
+-{
+-	return 0;
+-}
++#define dev_dbg(dev, format, arg...)		\
++	({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
+ #endif
+ 
+ #ifdef VERBOSE_DEBUG
+ #define dev_vdbg	dev_dbg
+ #else
+-static inline int __attribute__ ((format (printf, 2, 3)))
+-dev_vdbg(struct device *dev, const char *fmt, ...)
+-{
+-	return 0;
+-}
++
++#define dev_vdbg(dev, format, arg...)		\
++	({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
+ #endif
+ 
+ /* Create alias, so I can be autoloaded. */
+diff --git a/include/linux/dlm.h b/include/linux/dlm.h
+index c743fbc..203a025 100644
+--- a/include/linux/dlm.h
++++ b/include/linux/dlm.h
+@@ -21,10 +21,7 @@
+ 
+ /* Lock levels and flags are here */
+ #include <linux/dlmconstants.h>
+-
+-
+-#define DLM_RESNAME_MAXLEN	64
+-
++#include <linux/types.h>
+ 
+ typedef void dlm_lockspace_t;
+ 
+@@ -63,7 +60,7 @@ typedef void dlm_lockspace_t;
+ 
+ struct dlm_lksb {
+ 	int 	 sb_status;
+-	uint32_t sb_lkid;
++	__u32	 sb_lkid;
+ 	char 	 sb_flags;
+ 	char *	 sb_lvbptr;
+ };
+diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h
+index 9642277..c603450 100644
+--- a/include/linux/dlm_device.h
++++ b/include/linux/dlm_device.h
+@@ -11,10 +11,16 @@
+ *******************************************************************************
+ ******************************************************************************/
+ 
++#ifndef _LINUX_DLM_DEVICE_H
++#define _LINUX_DLM_DEVICE_H
++
+ /* This is the device interface for dlm, most users will use a library
+  * interface.
+  */
+ 
++#include <linux/dlm.h>
++#include <linux/types.h>
++
+ #define DLM_USER_LVB_LEN	32
+ 
+ /* Version of the device interface */
+@@ -94,10 +100,9 @@ struct dlm_lock_result {
+ #define DLM_USER_PURGE        6
+ #define DLM_USER_DEADLOCK     7
+ 
+-/* Arbitrary length restriction */
+-#define MAX_LS_NAME_LEN 64
+-
+ /* Lockspace flags */
+ #define DLM_USER_LSFLG_AUTOFREE   1
+ #define DLM_USER_LSFLG_FORCEFREE  2
+ 
++#endif
++
+diff --git a/include/linux/dlm_plock.h b/include/linux/dlm_plock.h
+new file mode 100644
+index 0000000..18d5fdb
+--- /dev/null
++++ b/include/linux/dlm_plock.h
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU General Public License v.2.
++ */
++
++#ifndef __DLM_PLOCK_DOT_H__
++#define __DLM_PLOCK_DOT_H__
++
++#define DLM_PLOCK_MISC_NAME		"dlm_plock"
++
++#define DLM_PLOCK_VERSION_MAJOR	1
++#define DLM_PLOCK_VERSION_MINOR	1
++#define DLM_PLOCK_VERSION_PATCH	0
++
++enum {
++	DLM_PLOCK_OP_LOCK = 1,
++	DLM_PLOCK_OP_UNLOCK,
++	DLM_PLOCK_OP_GET,
++};
++
++struct dlm_plock_info {
++	__u32 version[3];
++	__u8 optype;
++	__u8 ex;
++	__u8 wait;
++	__u8 pad;
++	__u32 pid;
++	__s32 nodeid;
++	__s32 rv;
++	__u32 fsid;
++	__u64 number;
++	__u64 start;
++	__u64 end;
++	__u64 owner;
++};
++
++#ifdef __KERNEL__
++int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++		int cmd, struct file_lock *fl);
++int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++		struct file_lock *fl);
++int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++		struct file_lock *fl);
++#endif /* __KERNEL__ */
++
++#endif
++
+diff --git a/include/linux/dlmconstants.h b/include/linux/dlmconstants.h
+index fddb3d3..47bf08d 100644
+--- a/include/linux/dlmconstants.h
++++ b/include/linux/dlmconstants.h
+@@ -18,6 +18,10 @@
+  * Constants used by DLM interface.
+  */
+ 
++#define DLM_LOCKSPACE_LEN       64
++#define DLM_RESNAME_MAXLEN      64
++
++
+ /*
+  * Lock Modes
+  */
+diff --git a/include/linux/dm-dirty-log.h b/include/linux/dm-dirty-log.h
+new file mode 100644
+index 0000000..600c5fb
+--- /dev/null
++++ b/include/linux/dm-dirty-log.h
+@@ -0,0 +1,131 @@
++/*
++ * Copyright (C) 2003 Sistina Software
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
++ *
++ * Device-Mapper dirty region log.
++ *
++ * This file is released under the LGPL.
++ */
++
++#ifndef _LINUX_DM_DIRTY_LOG
++#define _LINUX_DM_DIRTY_LOG
++
++#ifdef __KERNEL__
++
++#include <linux/types.h>
++#include <linux/device-mapper.h>
++
++typedef sector_t region_t;
++
++struct dm_dirty_log_type;
++
++struct dm_dirty_log {
++	struct dm_dirty_log_type *type;
++	void *context;
++};
++
++struct dm_dirty_log_type {
++	const char *name;
++	struct module *module;
++
++	int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti,
++		   unsigned argc, char **argv);
++	void (*dtr)(struct dm_dirty_log *log);
++
++	/*
++	 * There are times when we don't want the log to touch
++	 * the disk.
++	 */
++	int (*presuspend)(struct dm_dirty_log *log);
++	int (*postsuspend)(struct dm_dirty_log *log);
++	int (*resume)(struct dm_dirty_log *log);
++
++	/*
++	 * Retrieves the smallest size of region that the log can
++	 * deal with.
++	 */
++	uint32_t (*get_region_size)(struct dm_dirty_log *log);
++
++	/*
++	 * A predicate to say whether a region is clean or not.
++	 * May block.
++	 */
++	int (*is_clean)(struct dm_dirty_log *log, region_t region);
++
++	/*
++	 *  Returns: 0, 1, -EWOULDBLOCK, < 0
++	 *
++	 * A predicate function to check the area given by
++	 * [sector, sector + len) is in sync.
++	 *
++	 * If -EWOULDBLOCK is returned the state of the region is
++	 * unknown, typically this will result in a read being
++	 * passed to a daemon to deal with, since a daemon is
++	 * allowed to block.
++	 */
++	int (*in_sync)(struct dm_dirty_log *log, region_t region,
++		       int can_block);
++
++	/*
++	 * Flush the current log state (eg, to disk).  This
++	 * function may block.
++	 */
++	int (*flush)(struct dm_dirty_log *log);
++
++	/*
++	 * Mark an area as clean or dirty.  These functions may
++	 * block, though for performance reasons blocking should
++	 * be extremely rare (eg, allocating another chunk of
++	 * memory for some reason).
++	 */
++	void (*mark_region)(struct dm_dirty_log *log, region_t region);
++	void (*clear_region)(struct dm_dirty_log *log, region_t region);
++
++	/*
++	 * Returns: <0 (error), 0 (no region), 1 (region)
++	 *
++	 * The mirrord will need perform recovery on regions of
++	 * the mirror that are in the NOSYNC state.  This
++	 * function asks the log to tell the caller about the
++	 * next region that this machine should recover.
++	 *
++	 * Do not confuse this function with 'in_sync()', one
++	 * tells you if an area is synchronised, the other
++	 * assigns recovery work.
++	*/
++	int (*get_resync_work)(struct dm_dirty_log *log, region_t *region);
++
++	/*
++	 * This notifies the log that the resync status of a region
++	 * has changed.  It also clears the region from the recovering
++	 * list (if present).
++	 */
++	void (*set_region_sync)(struct dm_dirty_log *log,
++				region_t region, int in_sync);
++
++	/*
++	 * Returns the number of regions that are in sync.
++	 */
++	region_t (*get_sync_count)(struct dm_dirty_log *log);
++
++	/*
++	 * Support function for mirror status requests.
++	 */
++	int (*status)(struct dm_dirty_log *log, status_type_t status_type,
++		      char *result, unsigned maxlen);
++};
++
++int dm_dirty_log_type_register(struct dm_dirty_log_type *type);
++int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type);
++
++/*
++ * Make sure you use these two functions, rather than calling
++ * type->constructor/destructor() directly.
++ */
++struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
++					 struct dm_target *ti,
++					 unsigned argc, char **argv);
++void dm_dirty_log_destroy(struct dm_dirty_log *log);
++
++#endif	/* __KERNEL__ */
++#endif	/* _LINUX_DM_DIRTY_LOG_H */
+diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h
+new file mode 100644
+index 0000000..b6bf17e
+--- /dev/null
++++ b/include/linux/dm-io.h
+@@ -0,0 +1,85 @@
++/*
++ * Copyright (C) 2003 Sistina Software
++ * Copyright (C) 2004 - 2008 Red Hat, Inc. All rights reserved.
++ *
++ * Device-Mapper low-level I/O.
++ *
++ * This file is released under the GPL.
++ */
++
++#ifndef _LINUX_DM_IO_H
++#define _LINUX_DM_IO_H
++
++#ifdef __KERNEL__
++
++#include <linux/types.h>
++
++struct dm_io_region {
++	struct block_device *bdev;
++	sector_t sector;
++	sector_t count;		/* If this is zero the region is ignored. */
++};
++
++struct page_list {
++	struct page_list *next;
++	struct page *page;
++};
++
++typedef void (*io_notify_fn)(unsigned long error, void *context);
++
++enum dm_io_mem_type {
++	DM_IO_PAGE_LIST,/* Page list */
++	DM_IO_BVEC,	/* Bio vector */
++	DM_IO_VMA,	/* Virtual memory area */
++	DM_IO_KMEM,	/* Kernel memory */
++};
++
++struct dm_io_memory {
++	enum dm_io_mem_type type;
++
++	union {
++		struct page_list *pl;
++		struct bio_vec *bvec;
++		void *vma;
++		void *addr;
++	} ptr;
++
++	unsigned offset;
++};
++
++struct dm_io_notify {
++	io_notify_fn fn;	/* Callback for asynchronous requests */
++	void *context;		/* Passed to callback */
++};
++
++/*
++ * IO request structure
++ */
++struct dm_io_client;
++struct dm_io_request {
++	int bi_rw;			/* READ|WRITE - not READA */
++	struct dm_io_memory mem;	/* Memory to use for io */
++	struct dm_io_notify notify;	/* Synchronous if notify.fn is NULL */
++	struct dm_io_client *client;	/* Client memory handler */
++};
++
++/*
++ * For async io calls, users can alternatively use the dm_io() function below
++ * and dm_io_client_create() to create private mempools for the client.
++ *
++ * Create/destroy may block.
++ */
++struct dm_io_client *dm_io_client_create(unsigned num_pages);
++int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client);
++void dm_io_client_destroy(struct dm_io_client *client);
++
++/*
++ * IO interface using private per-client pools.
++ * Each bit in the optional 'sync_error_bits' bitset indicates whether an
++ * error occurred doing io to the corresponding region.
++ */
++int dm_io(struct dm_io_request *io_req, unsigned num_regions,
++	  struct dm_io_region *region, unsigned long *sync_error_bits);
++
++#endif	/* __KERNEL__ */
++#endif	/* _LINUX_DM_IO_H */
+diff --git a/include/linux/dm-kcopyd.h b/include/linux/dm-kcopyd.h
+new file mode 100644
+index 0000000..5db2163
+--- /dev/null
++++ b/include/linux/dm-kcopyd.h
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (C) 2001 - 2003 Sistina Software
++ * Copyright (C) 2004 - 2008 Red Hat, Inc. All rights reserved.
++ *
++ * kcopyd provides a simple interface for copying an area of one
++ * block-device to one or more other block-devices, either synchronous
++ * or with an asynchronous completion notification.
++ *
++ * This file is released under the GPL.
++ */
++
++#ifndef _LINUX_DM_KCOPYD_H
++#define _LINUX_DM_KCOPYD_H
++
++#ifdef __KERNEL__
++
++#include <linux/dm-io.h>
++
++/* FIXME: make this configurable */
++#define DM_KCOPYD_MAX_REGIONS 8
++
++#define DM_KCOPYD_IGNORE_ERROR 1
++
++/*
++ * To use kcopyd you must first create a dm_kcopyd_client object.
++ */
++struct dm_kcopyd_client;
++int dm_kcopyd_client_create(unsigned num_pages,
++			    struct dm_kcopyd_client **result);
++void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc);
++
++/*
++ * Submit a copy job to kcopyd.  This is built on top of the
++ * previous three fns.
++ *
++ * read_err is a boolean,
++ * write_err is a bitset, with 1 bit for each destination region
++ */
++typedef void (*dm_kcopyd_notify_fn)(int read_err, unsigned long write_err,
++				    void *context);
++
++int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
++		   unsigned num_dests, struct dm_io_region *dests,
++		   unsigned flags, dm_kcopyd_notify_fn fn, void *context);
++
++#endif	/* __KERNEL__ */
++#endif	/* _LINUX_DM_KCOPYD_H */
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index 34d4406..d08a5c5 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -95,12 +95,17 @@ enum dma_transaction_type {
+ #define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
+ 
+ /**
+- * enum dma_prep_flags - DMA flags to augment operation preparation
++ * enum dma_ctrl_flags - DMA flags to augment operation preparation,
++ * 	control completion, and communicate status.
+  * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of
+  * 	this transaction
++ * @DMA_CTRL_ACK - the descriptor cannot be reused until the client
++ * 	acknowledges receipt, i.e. has has a chance to establish any
++ * 	dependency chains
+  */
+-enum dma_prep_flags {
++enum dma_ctrl_flags {
+ 	DMA_PREP_INTERRUPT = (1 << 0),
++	DMA_CTRL_ACK = (1 << 1),
+ };
+ 
+ /**
+@@ -211,8 +216,8 @@ typedef void (*dma_async_tx_callback)(void *dma_async_param);
+  * ---dma generic offload fields---
+  * @cookie: tracking cookie for this transaction, set to -EBUSY if
+  *	this tx is sitting on a dependency list
+- * @ack: the descriptor can not be reused until the client acknowledges
+- *	receipt, i.e. has has a chance to establish any dependency chains
++ * @flags: flags to augment operation preparation, control completion, and
++ * 	communicate status
+  * @phys: physical address of the descriptor
+  * @tx_list: driver common field for operations that require multiple
+  *	descriptors
+@@ -221,23 +226,20 @@ typedef void (*dma_async_tx_callback)(void *dma_async_param);
+  * @callback: routine to call after this operation is complete
+  * @callback_param: general parameter to pass to the callback routine
+  * ---async_tx api specific fields---
+- * @depend_list: at completion this list of transactions are submitted
+- * @depend_node: allow this transaction to be executed after another
+- *	transaction has completed, possibly on another channel
++ * @next: at completion submit this descriptor
+  * @parent: pointer to the next level up in the dependency chain
+- * @lock: protect the dependency list
++ * @lock: protect the parent and next pointers
+  */
+ struct dma_async_tx_descriptor {
+ 	dma_cookie_t cookie;
+-	int ack;
++	enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */
+ 	dma_addr_t phys;
+ 	struct list_head tx_list;
+ 	struct dma_chan *chan;
+ 	dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
+ 	dma_async_tx_callback callback;
+ 	void *callback_param;
+-	struct list_head depend_list;
+-	struct list_head depend_node;
++	struct dma_async_tx_descriptor *next;
+ 	struct dma_async_tx_descriptor *parent;
+ 	spinlock_t lock;
+ };
+@@ -261,7 +263,6 @@ struct dma_async_tx_descriptor {
+  * @device_prep_dma_zero_sum: prepares a zero_sum operation
+  * @device_prep_dma_memset: prepares a memset operation
+  * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
+- * @device_dependency_added: async_tx notifies the channel about new deps
+  * @device_issue_pending: push pending transactions to hardware
+  */
+ struct dma_device {
+@@ -294,9 +295,8 @@ struct dma_device {
+ 		struct dma_chan *chan, dma_addr_t dest, int value, size_t len,
+ 		unsigned long flags);
+ 	struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
+-		struct dma_chan *chan);
++		struct dma_chan *chan, unsigned long flags);
+ 
+-	void (*device_dependency_added)(struct dma_chan *chan);
+ 	enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
+ 			dma_cookie_t cookie, dma_cookie_t *last,
+ 			dma_cookie_t *used);
+@@ -321,7 +321,13 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+ static inline void
+ async_tx_ack(struct dma_async_tx_descriptor *tx)
+ {
+-	tx->ack = 1;
++	tx->flags |= DMA_CTRL_ACK;
++}
++
++static inline int
++async_tx_test_ack(struct dma_async_tx_descriptor *tx)
++{
++	return tx->flags & DMA_CTRL_ACK;
+ }
+ 
+ #define first_dma_cap(mask) __first_dma_cap(&(mask))
+@@ -398,7 +404,7 @@ static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
+  * @last_used: last cookie value handed out
+  *
+  * dma_async_is_complete() is used in dma_async_memcpy_complete()
+- * the test logic is seperated for lightweight testing of multiple cookies
++ * the test logic is separated for lightweight testing of multiple cookies
+  */
+ static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie,
+ 			dma_cookie_t last_complete, dma_cookie_t last_used)
+diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
+index c6a2353..402fb7a 100644
+--- a/include/linux/dvb/dmx.h
++++ b/include/linux/dvb/dmx.h
+@@ -39,9 +39,10 @@ typedef enum
+ 	DMX_OUT_DECODER, /* Streaming directly to decoder. */
+ 	DMX_OUT_TAP,     /* Output going to a memory buffer */
+ 			 /* (to be retrieved via the read command).*/
+-	DMX_OUT_TS_TAP   /* Output multiplexed into a new TS  */
++	DMX_OUT_TS_TAP,  /* Output multiplexed into a new TS  */
+ 			 /* (to be retrieved by reading from the */
+ 			 /* logical DVR device).                 */
++	DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
+ } dmx_output_t;
+ 
+ 
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index 14813b5..a5f359a 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -18,6 +18,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/rtc.h>
+ #include <linux/ioport.h>
++#include <linux/pfn.h>
+ 
+ #include <asm/page.h>
+ #include <asm/system.h>
+@@ -394,4 +395,10 @@ struct efi_generic_dev_path {
+ 	u16 length;
+ } __attribute ((packed));
+ 
++static inline void memrange_efi_to_native(u64 *addr, u64 *npages)
++{
++	*npages = PFN_UP(*addr + (*npages<<EFI_PAGE_SHIFT)) - PFN_DOWN(*addr);
++	*addr &= PAGE_MASK;
++}
++
+ #endif /* _LINUX_EFI_H */
+diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
+index a5978f1..4332442 100644
+--- a/include/linux/enclosure.h
++++ b/include/linux/enclosure.h
+@@ -82,7 +82,8 @@ struct enclosure_component_callbacks {
+ 
+ struct enclosure_component {
+ 	void *scratch;
+-	struct class_device cdev;
++	struct device cdev;
++	struct device *dev;
+ 	enum enclosure_component_type type;
+ 	int number;
+ 	int fault;
+@@ -94,20 +95,20 @@ struct enclosure_component {
+ struct enclosure_device {
+ 	void *scratch;
+ 	struct list_head node;
+-	struct class_device cdev;
++	struct device edev;
+ 	struct enclosure_component_callbacks *cb;
+ 	int components;
+ 	struct enclosure_component component[0];
+ };
+ 
+ static inline struct enclosure_device *
+-to_enclosure_device(struct class_device *dev)
++to_enclosure_device(struct device *dev)
+ {
+-	return container_of(dev, struct enclosure_device, cdev);
++	return container_of(dev, struct enclosure_device, edev);
+ }
+ 
+ static inline struct enclosure_component *
+-to_enclosure_component(struct class_device *dev)
++to_enclosure_component(struct device *dev)
+ {
+ 	return container_of(dev, struct enclosure_component, cdev);
+ }
+diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
+index adcbb05..de8387b 100644
+--- a/include/linux/exportfs.h
++++ b/include/linux/exportfs.h
+@@ -43,7 +43,7 @@ struct fid {
+ 			u32 parent_ino;
+ 			u32 parent_gen;
+ 		} i32;
+-		__u32 raw[6];
++		__u32 raw[0];
+ 	};
+ };
+ 
+diff --git a/include/linux/file.h b/include/linux/file.h
+index 7239baa..69baf5a 100644
+--- a/include/linux/file.h
++++ b/include/linux/file.h
+@@ -61,6 +61,7 @@ extern struct kmem_cache *filp_cachep;
+ 
+ extern void __fput(struct file *);
+ extern void fput(struct file *);
++extern void drop_file_write_access(struct file *file);
+ 
+ struct file_operations;
+ struct vfsmount;
+@@ -116,7 +117,8 @@ struct task_struct;
+ 
+ struct files_struct *get_files_struct(struct task_struct *);
+ void put_files_struct(struct files_struct *fs);
+-void reset_files_struct(struct task_struct *, struct files_struct *);
++void reset_files_struct(struct files_struct *);
++int unshare_files(struct files_struct **);
+ 
+ extern struct kmem_cache *files_cachep;
+ 
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index ddfa037..b6ea9aa 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -37,21 +37,6 @@ struct sock_fprog	/* Required for SO_ATTACH_FILTER. */
+ 	struct sock_filter __user *filter;
+ };
+ 
+-#ifdef __KERNEL__
+-struct sk_filter
+-{
+-	atomic_t		refcnt;
+-	unsigned int         	len;	/* Number of filter blocks */
+-	struct rcu_head		rcu;
+-	struct sock_filter     	insns[0];
+-};
+-
+-static inline unsigned int sk_filter_len(struct sk_filter *fp)
+-{
+-	return fp->len*sizeof(struct sock_filter) + sizeof(*fp);
+-}
+-#endif
+-
+ /*
+  * Instruction classes
+  */
+@@ -136,15 +121,31 @@ static inline unsigned int sk_filter_len(struct sk_filter *fp)
+ #define SKF_AD_PROTOCOL 0
+ #define SKF_AD_PKTTYPE 	4
+ #define SKF_AD_IFINDEX 	8
+-#define SKF_AD_MAX 	12
++#define SKF_AD_NLATTR	12
++#define SKF_AD_MAX 	16
+ #define SKF_NET_OFF   (-0x100000)
+ #define SKF_LL_OFF    (-0x200000)
+ 
+ #ifdef __KERNEL__
++struct sk_filter
++{
++	atomic_t		refcnt;
++	unsigned int         	len;	/* Number of filter blocks */
++	struct rcu_head		rcu;
++	struct sock_filter     	insns[0];
++};
++
++static inline unsigned int sk_filter_len(const struct sk_filter *fp)
++{
++	return fp->len * sizeof(struct sock_filter) + sizeof(*fp);
++}
++
+ struct sk_buff;
+ struct sock;
+ 
+-extern unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen);
++extern int sk_filter(struct sock *sk, struct sk_buff *skb);
++extern unsigned int sk_run_filter(struct sk_buff *skb,
++				  struct sock_filter *filter, int flen);
+ extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
+ extern int sk_detach_filter(struct sock *sk);
+ extern int sk_chk_filter(struct sock_filter *filter, int flen);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index b84b848..d6d7c52 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -287,9 +287,9 @@ extern int dir_notify_enable;
+ #include <linux/pid.h>
+ #include <linux/mutex.h>
+ #include <linux/capability.h>
++#include <linux/semaphore.h>
+ 
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <asm/byteorder.h>
+ 
+ struct export_operations;
+@@ -305,7 +305,6 @@ struct vfsmount;
+ 
+ extern void __init inode_init(void);
+ extern void __init inode_init_early(void);
+-extern void __init mnt_init(void);
+ extern void __init files_init(unsigned long);
+ 
+ struct buffer_head;
+@@ -776,6 +775,9 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
+ 		index <  ra->start + ra->size);
+ }
+ 
++#define FILE_MNT_WRITE_TAKEN	1
++#define FILE_MNT_WRITE_RELEASED	2
++
+ struct file {
+ 	/*
+ 	 * fu_list becomes invalid after file_free is called and queued via
+@@ -810,6 +812,9 @@ struct file {
+ 	spinlock_t		f_ep_lock;
+ #endif /* #ifdef CONFIG_EPOLL */
+ 	struct address_space	*f_mapping;
++#ifdef CONFIG_DEBUG_WRITECOUNT
++	unsigned long f_mnt_write_state;
++#endif
+ };
+ extern spinlock_t files_lock;
+ #define file_list_lock() spin_lock(&files_lock);
+@@ -818,6 +823,49 @@ extern spinlock_t files_lock;
+ #define get_file(x)	atomic_inc(&(x)->f_count)
+ #define file_count(x)	atomic_read(&(x)->f_count)
+ 
++#ifdef CONFIG_DEBUG_WRITECOUNT
++static inline void file_take_write(struct file *f)
++{
++	WARN_ON(f->f_mnt_write_state != 0);
++	f->f_mnt_write_state = FILE_MNT_WRITE_TAKEN;
++}
++static inline void file_release_write(struct file *f)
++{
++	f->f_mnt_write_state |= FILE_MNT_WRITE_RELEASED;
++}
++static inline void file_reset_write(struct file *f)
++{
++	f->f_mnt_write_state = 0;
++}
++static inline void file_check_state(struct file *f)
++{
++	/*
++	 * At this point, either both or neither of these bits
++	 * should be set.
++	 */
++	WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN);
++	WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_RELEASED);
++}
++static inline int file_check_writeable(struct file *f)
++{
++	if (f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN)
++		return 0;
++	printk(KERN_WARNING "writeable file with no "
++			    "mnt_want_write()\n");
++	WARN_ON(1);
++	return -EINVAL;
++}
++#else /* !CONFIG_DEBUG_WRITECOUNT */
++static inline void file_take_write(struct file *filp) {}
++static inline void file_release_write(struct file *filp) {}
++static inline void file_reset_write(struct file *filp) {}
++static inline void file_check_state(struct file *filp) {}
++static inline int file_check_writeable(struct file *filp)
++{
++	return 0;
++}
++#endif /* CONFIG_DEBUG_WRITECOUNT */
++
+ #define	MAX_NON_LFS	((1UL<<31) - 1)
+ 
+ /* Page cache limit. The filesystems should put that into their s_maxbytes 
+@@ -925,6 +973,7 @@ extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
+ /* fs/locks.c */
+ extern void locks_init_lock(struct file_lock *);
+ extern void locks_copy_lock(struct file_lock *, struct file_lock *);
++extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
+ extern void locks_remove_posix(struct file *, fl_owner_t);
+ extern void locks_remove_flock(struct file *);
+ extern void posix_test_lock(struct file *, struct file_lock *);
+@@ -1260,7 +1309,7 @@ struct super_operations {
+ 	int (*statfs) (struct dentry *, struct kstatfs *);
+ 	int (*remount_fs) (struct super_block *, int *, char *);
+ 	void (*clear_inode) (struct inode *);
+-	void (*umount_begin) (struct vfsmount *, int);
++	void (*umount_begin) (struct super_block *);
+ 
+ 	int (*show_options)(struct seq_file *, struct vfsmount *);
+ 	int (*show_stats)(struct seq_file *, struct vfsmount *);
+@@ -1487,12 +1536,7 @@ extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
+ #define kern_mount(type) kern_mount_data(type, NULL)
+ extern int may_umount_tree(struct vfsmount *);
+ extern int may_umount(struct vfsmount *);
+-extern void umount_tree(struct vfsmount *, int, struct list_head *);
+-extern void release_mounts(struct list_head *);
+ extern long do_mount(char *, char *, char *, unsigned long, void *);
+-extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
+-extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
+-				  struct vfsmount *);
+ extern struct vfsmount *collect_mounts(struct vfsmount *, struct dentry *);
+ extern void drop_collected_mounts(struct vfsmount *);
+ 
+@@ -1735,7 +1779,8 @@ extern struct file *create_read_pipe(struct file *f);
+ extern struct file *create_write_pipe(void);
+ extern void free_write_pipe(struct file *);
+ 
+-extern int open_namei(int dfd, const char *, int, int, struct nameidata *);
++extern struct file *do_filp_open(int dfd, const char *pathname,
++		int open_flag, int mode);
+ extern int may_open(struct nameidata *, int, int);
+ 
+ extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
+@@ -1989,9 +2034,6 @@ static inline ino_t parent_ino(struct dentry *dentry)
+ 	return res;
+ }
+ 
+-/* kernel/fork.c */
+-extern int unshare_files(void);
+-
+ /* Transaction based IO helpers */
+ 
+ /*
+diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
+index 1831b19..2cad5c6 100644
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -50,7 +50,7 @@ struct gianfar_platform_data {
+ 	u32	device_flags;
+ 	/* board specific information */
+ 	u32	board_flags;
+-	u32	bus_id;
++	char	bus_id[MII_BUS_ID_SIZE];
+ 	u32	phy_id;
+ 	u8	mac_addr[6];
+ 	phy_interface_t interface;
+diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
+index e38e759..c37e924 100644
+--- a/include/linux/hdreg.h
++++ b/include/linux/hdreg.h
+@@ -422,9 +422,11 @@ struct hd_geometry {
+ #define HDIO_SET_NOWERR		0x0325	/* change ignore-write-error flag */
+ #define HDIO_SET_DMA		0x0326	/* change use-dma flag */
+ #define HDIO_SET_PIO_MODE	0x0327	/* reconfig interface to new speed */
++#ifndef __KERNEL__
+ #define HDIO_SCAN_HWIF		0x0328	/* register and (re)scan interface */
+-#define HDIO_SET_NICE		0x0329	/* set nice flags */
+ #define HDIO_UNREGISTER_HWIF	0x032a  /* unregister interface */
++#endif
++#define HDIO_SET_NICE		0x0329	/* set nice flags */
+ #define HDIO_SET_WCACHE		0x032b	/* change write cache enable-disable */
+ #define HDIO_SET_ACOUSTIC	0x032c	/* change acoustic behavior */
+ #define HDIO_SET_BUSSTATE	0x032d	/* set the bus state of the hwif */
+diff --git a/include/linux/hdsmart.h b/include/linux/hdsmart.h
+deleted file mode 100644
+index 4f4faf9..0000000
+--- a/include/linux/hdsmart.h
++++ /dev/null
+@@ -1,126 +0,0 @@
+-/*
+- * linux/include/linux/hdsmart.h
+- *
+- * Copyright (C) 1999-2000	Michael Cornwell <cornwell at acm.org>
+- * Copyright (C) 2000		Andre Hedrick <andre at linux-ide.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, or (at your option)
+- * any later version.
+- *
+- * You should have received a copy of the GNU General Public License
+- * (for example /usr/src/linux/COPYING); if not, write to the Free
+- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef _LINUX_HDSMART_H
+-#define _LINUX_HDSMART_H
+-
+-#ifndef __KERNEL__
+-#define OFFLINE_FULL_SCAN		0
+-#define SHORT_SELF_TEST			1
+-#define EXTEND_SELF_TEST		2
+-#define SHORT_CAPTIVE_SELF_TEST		129
+-#define EXTEND_CAPTIVE_SELF_TEST	130
+-
+-/* smart_attribute is the vendor specific in SFF-8035 spec */
+-typedef struct ata_smart_attribute_s {
+-	unsigned char			id;
+-	unsigned short			status_flag;
+-	unsigned char			normalized;
+-	unsigned char			worse_normal;
+-	unsigned char			raw[6];
+-	unsigned char			reserv;
+-} __attribute__ ((packed)) ata_smart_attribute_t;
+-
+-/* smart_values is format of the read drive Atrribute command */
+-typedef struct ata_smart_values_s {
+-	unsigned short			revnumber;
+-	ata_smart_attribute_t		vendor_attributes [30];
+-        unsigned char			offline_data_collection_status;
+-        unsigned char			self_test_exec_status;
+-	unsigned short			total_time_to_complete_off_line;
+-	unsigned char			vendor_specific_366;
+-	unsigned char			offline_data_collection_capability;
+-	unsigned short			smart_capability;
+-	unsigned char			errorlog_capability;
+-	unsigned char			vendor_specific_371;
+-	unsigned char			short_test_completion_time;
+-	unsigned char			extend_test_completion_time;
+-	unsigned char			reserved_374_385 [12];
+-	unsigned char			vendor_specific_386_509 [125];
+-	unsigned char			chksum;
+-} __attribute__ ((packed)) ata_smart_values_t;
+-
+-/* Smart Threshold data structures */
+-/* Vendor attribute of SMART Threshold */
+-typedef struct ata_smart_threshold_entry_s {
+-	unsigned char			id;
+-	unsigned char			normalized_threshold;
+-	unsigned char			reserved[10];
+-} __attribute__ ((packed)) ata_smart_threshold_entry_t;
+-
+-/* Format of Read SMART THreshold Command */
+-typedef struct ata_smart_thresholds_s {
+-	unsigned short			revnumber;
+-	ata_smart_threshold_entry_t	thres_entries[30];
+-	unsigned char			reserved[149];
+-	unsigned char			chksum;
+-} __attribute__ ((packed)) ata_smart_thresholds_t;
+-
+-typedef struct ata_smart_errorlog_command_struct_s {
+-	unsigned char			devicecontrolreg;
+-	unsigned char			featuresreg;
+-	unsigned char			sector_count;
+-	unsigned char			sector_number;
+-	unsigned char			cylinder_low;
+-	unsigned char			cylinder_high;
+-	unsigned char			drive_head;
+-	unsigned char			commandreg;
+-	unsigned int			timestamp;
+-} __attribute__ ((packed)) ata_smart_errorlog_command_struct_t;
+-
+-typedef struct ata_smart_errorlog_error_struct_s {
+-	unsigned char			error_condition;
+-	unsigned char			extended_error[14];
+-	unsigned char			state;
+-	unsigned short			timestamp;
+-} __attribute__ ((packed)) ata_smart_errorlog_error_struct_t;
+-
+-typedef struct ata_smart_errorlog_struct_s {
+-	ata_smart_errorlog_command_struct_t	commands[6];
+-	ata_smart_errorlog_error_struct_t	error_struct;
+-} __attribute__ ((packed)) ata_smart_errorlog_struct_t;
+-
+-typedef struct ata_smart_errorlog_s {
+-	unsigned char			revnumber;
+-	unsigned char			error_log_pointer;
+-	ata_smart_errorlog_struct_t	errorlog_struct[5];
+-	unsigned short			ata_error_count;
+-	unsigned short			non_fatal_count;
+-	unsigned short			drive_timeout_count;
+-	unsigned char			reserved[53];
+-	unsigned char			chksum;
+-} __attribute__ ((packed)) ata_smart_errorlog_t;
+-
+-typedef struct ata_smart_selftestlog_struct_s {
+-	unsigned char			selftestnumber;
+-	unsigned char			selfteststatus;
+-	unsigned short			timestamp;
+-	unsigned char			selftestfailurecheckpoint;
+-	unsigned int			lbafirstfailure;
+-	unsigned char			vendorspecific[15];
+-} __attribute__ ((packed)) ata_smart_selftestlog_struct_t;
+-
+-typedef struct ata_smart_selftestlog_s {
+-	unsigned short			revnumber;
+-	ata_smart_selftestlog_struct_t	selftest_struct[21];
+-	unsigned char			vendorspecific[2];
+-	unsigned char			mostrecenttest;
+-	unsigned char			resevered[2];
+-	unsigned char			chksum;
+-} __attribute__ ((packed)) ata_smart_selftestlog_t;
+-#endif /* __KERNEL__ */
+-
+-#endif	/* _LINUX_HDSMART_H */
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 74ff575..d951ec4 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -284,6 +284,7 @@ struct hid_item {
+ #define HID_QUIRK_2WHEEL_MOUSE_HACK_B8		0x02000000
+ #define HID_QUIRK_HWHEEL_WHEEL_INVERT		0x04000000
+ #define HID_QUIRK_MICROSOFT_KEYS		0x08000000
++#define HID_QUIRK_FULLSPEED_INTERVAL		0x10000000
+ 
+ /*
+  * Separate quirks for runtime report descriptor fixup
+@@ -296,6 +297,8 @@ struct hid_item {
+ #define HID_QUIRK_RDESC_MACBOOK_JIS		0x00000010
+ #define HID_QUIRK_RDESC_BUTTON_CONSUMER		0x00000020
+ #define HID_QUIRK_RDESC_SAMSUNG_REMOTE		0x00000040
++#define HID_QUIRK_RDESC_MICROSOFT_RECV_1028	0x00000080
++#define HID_QUIRK_RDESC_SUNPLUS_WDESKTOP	0x00000100
+ 
+ /*
+  * This is the global environment of the parser. This information is
+@@ -320,7 +323,7 @@ struct hid_global {
+  * This is the local environment. It is persistent up the next main-item.
+  */
+ 
+-#define HID_MAX_USAGES			8192
++#define HID_MAX_USAGES			12288
+ #define HID_DEFAULT_NUM_COLLECTIONS	16
+ 
+ struct hid_local {
+@@ -421,6 +424,7 @@ struct hid_control_fifo {
+ #define HID_RESET_PENDING	4
+ #define HID_SUSPENDED		5
+ #define HID_CLEAR_HALT		6
++#define HID_DISCONNECTED	7
+ 
+ struct hid_input {
+ 	struct list_head list;
+@@ -452,8 +456,6 @@ struct hid_device {							/* device report descriptor */
+ 	void *hidraw;
+ 	int minor;							/* Hiddev minor number */
+ 
+-	wait_queue_head_t wait;						/* For sleeping */
+-
+ 	int open;							/* is the device open by anyone? */
+ 	char name[128];							/* Device name */
+ 	char phys[64];							/* Device physical location */
+@@ -530,14 +532,12 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int
+ int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long **, int *);
+ int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
+ int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32);
+-void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt);
+ void hid_output_report(struct hid_report *report, __u8 *data);
+ void hid_free_device(struct hid_device *device);
+ struct hid_device *hid_parse_report(__u8 *start, unsigned size);
+ 
+ /* HID quirks API */
+ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
+-int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks);
+ int usbhid_quirks_init(char **quirks_param);
+ void usbhid_quirks_exit(void);
+ void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char **);
+@@ -546,6 +546,7 @@ void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char
+ int hid_ff_init(struct hid_device *hid);
+ 
+ int hid_lgff_init(struct hid_device *hid);
++int hid_lg2ff_init(struct hid_device *hid);
+ int hid_plff_init(struct hid_device *hid);
+ int hid_tmff_init(struct hid_device *hid);
+ int hid_zpff_init(struct hid_device *hid);
+@@ -566,7 +567,11 @@ static inline int hid_ff_init(struct hid_device *hid) { return -1; }
+ #define dbg_hid_line(format, arg...) if (hid_debug) \
+ 				printk(format, ## arg)
+ #else
+-#define dbg_hid(format, arg...) do {} while (0)
++static inline int __attribute__((format(printf, 1, 2)))
++dbg_hid(const char *fmt, ...)
++{
++	return 0;
++}
+ #define dbg_hid_line dbg_hid
+ #endif
+ 
+diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h
+index 0536f29..dbb5c8c 100644
+--- a/include/linux/hidraw.h
++++ b/include/linux/hidraw.h
+@@ -16,6 +16,7 @@
+  */
+ 
+ #include <linux/hid.h>
++#include <linux/types.h>
+ 
+ struct hidraw_report_descriptor {
+ 	__u32 size;
+diff --git a/include/linux/hil_mlc.h b/include/linux/hil_mlc.h
+index 8df29ca..394a840 100644
+--- a/include/linux/hil_mlc.h
++++ b/include/linux/hil_mlc.h
+@@ -34,7 +34,7 @@
+ #include <linux/hil.h>
+ #include <linux/time.h>
+ #include <linux/interrupt.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <linux/serio.h>
+ #include <linux/list.h>
+ 
+diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
+index 1ad56a7..56f3236 100644
+--- a/include/linux/hrtimer.h
++++ b/include/linux/hrtimer.h
+@@ -173,7 +173,6 @@ struct hrtimer_clock_base {
+  * struct hrtimer_cpu_base - the per cpu clock bases
+  * @lock:		lock protecting the base and associated clock bases
+  *			and timers
+- * @lock_key:		the lock_class_key for use with lockdep
+  * @clock_base:		array of clock bases for this cpu
+  * @curr_timer:		the timer which is executing a callback right now
+  * @expires_next:	absolute time of the next event which was scheduled
+@@ -189,7 +188,6 @@ struct hrtimer_clock_base {
+  */
+ struct hrtimer_cpu_base {
+ 	spinlock_t			lock;
+-	struct lock_class_key		lock_key;
+ 	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
+ 	struct list_head		cb_pending;
+ #ifdef CONFIG_HIGH_RES_TIMERS
+diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
+index 4213182..85d1191 100644
+--- a/include/linux/hw_random.h
++++ b/include/linux/hw_random.h
+@@ -44,15 +44,7 @@ struct hwrng {
+ /** Register a new Hardware Random Number Generator driver. */
+ extern int hwrng_register(struct hwrng *rng);
+ /** Unregister a Hardware Random Number Generator driver. */
+-extern void __hwrng_unregister(struct hwrng *rng, bool suspended);
+-static inline void hwrng_unregister(struct hwrng *rng)
+-{
+-	__hwrng_unregister(rng, false);
+-}
+-static inline void hwrng_unregister_suspended(struct hwrng *rng)
+-{
+-	__hwrng_unregister(rng, true);
+-}
++extern void hwrng_unregister(struct hwrng *rng);
+ 
+ #endif /* __KERNEL__ */
+ #endif /* LINUX_HWRANDOM_H_ */
+diff --git a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h
+index fce47c0..adcb3dc 100644
+--- a/include/linux/i2c-algo-pca.h
++++ b/include/linux/i2c-algo-pca.h
+@@ -1,14 +1,41 @@
+ #ifndef _LINUX_I2C_ALGO_PCA_H
+ #define _LINUX_I2C_ALGO_PCA_H
+ 
++/* Clock speeds for the bus */
++#define I2C_PCA_CON_330kHz	0x00
++#define I2C_PCA_CON_288kHz	0x01
++#define I2C_PCA_CON_217kHz	0x02
++#define I2C_PCA_CON_146kHz	0x03
++#define I2C_PCA_CON_88kHz	0x04
++#define I2C_PCA_CON_59kHz	0x05
++#define I2C_PCA_CON_44kHz	0x06
++#define I2C_PCA_CON_36kHz	0x07
++
++/* PCA9564 registers */
++#define I2C_PCA_STA		0x00 /* STATUS  Read Only  */
++#define I2C_PCA_TO		0x00 /* TIMEOUT Write Only */
++#define I2C_PCA_DAT		0x01 /* DATA    Read/Write */
++#define I2C_PCA_ADR		0x02 /* OWN ADR Read/Write */
++#define I2C_PCA_CON		0x03 /* CONTROL Read/Write */
++
++#define I2C_PCA_CON_AA		0x80 /* Assert Acknowledge */
++#define I2C_PCA_CON_ENSIO	0x40 /* Enable */
++#define I2C_PCA_CON_STA		0x20 /* Start */
++#define I2C_PCA_CON_STO		0x10 /* Stop */
++#define I2C_PCA_CON_SI		0x08 /* Serial Interrupt */
++#define I2C_PCA_CON_CR		0x07 /* Clock Rate (MASK) */
++
+ struct i2c_algo_pca_data {
+-	int  (*get_own)			(struct i2c_algo_pca_data *adap); /* Obtain own address */
+-	int  (*get_clock)		(struct i2c_algo_pca_data *adap);
+-	void (*write_byte)		(struct i2c_algo_pca_data *adap, int reg, int val);
+-	int  (*read_byte)		(struct i2c_algo_pca_data *adap, int reg);
+-	int  (*wait_for_interrupt)	(struct i2c_algo_pca_data *adap);
++	void 				*data;	/* private low level data */
++	void (*write_byte)		(void *data, int reg, int val);
++	int  (*read_byte)		(void *data, int reg);
++	int  (*wait_for_completion)	(void *data);
++	void (*reset_chip)		(void *data);
++	/* i2c_clock values are defined in linux/i2c-algo-pca.h */
++	unsigned int			i2c_clock;
+ };
+ 
+ int i2c_pca_add_bus(struct i2c_adapter *);
++int i2c_pca_add_numbered_bus(struct i2c_adapter *);
+ 
+ #endif /* _LINUX_I2C_ALGO_PCA_H */
+diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
+index b979112..32eb8bb 100644
+--- a/include/linux/i2c-id.h
++++ b/include/linux/i2c-id.h
+@@ -125,6 +125,7 @@
+ #define I2C_HW_B_CX2341X	0x010020 /* Conexant CX2341X MPEG encoder cards */
+ #define I2C_HW_B_INTELFB	0x010021 /* intel framebuffer driver */
+ #define I2C_HW_B_CX23885	0x010022 /* conexant 23885 based tv cards (bus1) */
++#define I2C_HW_B_AU0828		0x010023 /* auvitek au0828 usb bridge */
+ 
+ /* --- PCF 8584 based algorithms					*/
+ #define I2C_HW_P_ELEK		0x020002 /* Elektor ISA Bus inteface card */
+diff --git a/include/linux/i2c-pca-platform.h b/include/linux/i2c-pca-platform.h
+new file mode 100644
+index 0000000..3d19187
+--- /dev/null
++++ b/include/linux/i2c-pca-platform.h
+@@ -0,0 +1,12 @@
++#ifndef I2C_PCA9564_PLATFORM_H
++#define I2C_PCA9564_PLATFORM_H
++
++struct i2c_pca9564_pf_platform_data {
++	int gpio;		/* pin to reset chip. driver will work when
++				 * not supplied (negative value), but it
++				 * cannot exit some error conditions then */
++	int i2c_clock_speed;	/* values are defined in linux/i2c-algo-pca.h */
++	int timeout;		/* timeout = this value * 10us */
++};
++
++#endif /* I2C_PCA9564_PLATFORM_H */
+diff --git a/include/linux/i2c/tps65010.h b/include/linux/i2c/tps65010.h
+index 7021635..918c535 100644
+--- a/include/linux/i2c/tps65010.h
++++ b/include/linux/i2c/tps65010.h
+@@ -152,5 +152,35 @@ extern int tps65010_config_vregs1(unsigned value);
+  */
+ extern int tps65013_set_low_pwr(unsigned mode);
+ 
++
++struct i2c_client;
++
++/**
++ * struct tps65010_board - packages GPIO and LED lines
++ * @base: the GPIO number to assign to GPIO-1
++ * @outmask: bit (N-1) is set to allow GPIO-N to be used as an
++ *	(open drain) output
++ * @setup: optional callback issued once the GPIOs are valid
++ * @teardown: optional callback issued before the GPIOs are invalidated
++ * @context: optional parameter passed to setup() and teardown()
++ *
++ * Board data may be used to package the GPIO (and LED) lines for use
++ * in by the generic GPIO and LED frameworks.  The first four GPIOs
++ * starting at gpio_base are GPIO1..GPIO4.  The next two are LED1/nPG
++ * and LED2 (with hardware blinking capability, not currently exposed).
++ *
++ * The @setup callback may be used with the kind of board-specific glue
++ * which hands the (now-valid) GPIOs to other drivers, or which puts
++ * devices in their initial states using these GPIOs.
++ */
++struct tps65010_board {
++	int				base;
++	unsigned			outmask;
++
++	int		(*setup)(struct i2c_client *client, void *context);
++	int		(*teardown)(struct i2c_client *client, void *context);
++	void		*context;
++};
++
+ #endif /*  __LINUX_I2C_TPS65010_H */
+ 
+diff --git a/include/linux/i2o.h b/include/linux/i2o.h
+index 7da5b98..e92170d 100644
+--- a/include/linux/i2o.h
++++ b/include/linux/i2o.h
+@@ -33,9 +33,9 @@
+ #include <linux/mempool.h>
+ #include <linux/mutex.h>
+ #include <linux/scatterlist.h>
++#include <linux/semaphore.h>	/* Needed for MUTEX init macros */
+ 
+ #include <asm/io.h>
+-#include <asm/semaphore.h>	/* Needed for MUTEX init macros */
+ 
+ /* message queue empty */
+ #define I2O_QUEUE_EMPTY		0xffffffff
+diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
+index 7c5e981..0306744 100644
+--- a/include/linux/icmpv6.h
++++ b/include/linux/icmpv6.h
+@@ -176,12 +176,21 @@ extern void				icmpv6_send(struct sk_buff *skb,
+ 						    __u32 info, 
+ 						    struct net_device *dev);
+ 
+-extern int				icmpv6_init(struct net_proto_family *ops);
++extern int				icmpv6_init(void);
+ extern int				icmpv6_err_convert(int type, int code,
+ 							   int *err);
+ extern void				icmpv6_cleanup(void);
+ extern void				icmpv6_param_prob(struct sk_buff *skb,
+ 							  int code, int pos);
++
++struct flowi;
++struct in6_addr;
++extern void				icmpv6_flow_init(struct sock *sk,
++							 struct flowi *fl,
++							 u8 type,
++							 const struct in6_addr *saddr,
++							 const struct in6_addr *daddr,
++							 int oif);
+ #endif
+ 
+ #endif
+diff --git a/include/linux/ide.h b/include/linux/ide.h
+index bc26b2f..f20410d 100644
+--- a/include/linux/ide.h
++++ b/include/linux/ide.h
+@@ -23,7 +23,6 @@
+ #include <asm/byteorder.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/mutex.h>
+ 
+ #if defined(CONFIG_CRIS) || defined(CONFIG_FRV)
+@@ -82,24 +81,10 @@ typedef unsigned char	byte;	/* used everywhere */
+ 
+ #define IDE_FEATURE_OFFSET	IDE_ERROR_OFFSET
+ #define IDE_COMMAND_OFFSET	IDE_STATUS_OFFSET
+-
+-#define IDE_DATA_REG		(HWIF(drive)->io_ports[IDE_DATA_OFFSET])
+-#define IDE_ERROR_REG		(HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
+-#define IDE_NSECTOR_REG		(HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
+-#define IDE_SECTOR_REG		(HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])
+-#define IDE_LCYL_REG		(HWIF(drive)->io_ports[IDE_LCYL_OFFSET])
+-#define IDE_HCYL_REG		(HWIF(drive)->io_ports[IDE_HCYL_OFFSET])
+-#define IDE_SELECT_REG		(HWIF(drive)->io_ports[IDE_SELECT_OFFSET])
+-#define IDE_STATUS_REG		(HWIF(drive)->io_ports[IDE_STATUS_OFFSET])
+-#define IDE_CONTROL_REG		(HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])
+-#define IDE_IRQ_REG		(HWIF(drive)->io_ports[IDE_IRQ_OFFSET])
+-
+-#define IDE_FEATURE_REG		IDE_ERROR_REG
+-#define IDE_COMMAND_REG		IDE_STATUS_REG
+-#define IDE_ALTSTATUS_REG	IDE_CONTROL_REG
+-#define IDE_IREASON_REG		IDE_NSECTOR_REG
+-#define IDE_BCOUNTL_REG		IDE_LCYL_REG
+-#define IDE_BCOUNTH_REG		IDE_HCYL_REG
++#define IDE_ALTSTATUS_OFFSET	IDE_CONTROL_OFFSET
++#define IDE_IREASON_OFFSET	IDE_NSECTOR_OFFSET
++#define IDE_BCOUNTL_OFFSET	IDE_LCYL_OFFSET
++#define IDE_BCOUNTH_OFFSET	IDE_HCYL_OFFSET
+ 
+ #define OK_STAT(stat,good,bad)	(((stat)&((good)|(bad)))==(good))
+ #define BAD_R_STAT		(BUSY_STAT   | ERR_STAT)
+@@ -169,7 +154,7 @@ enum {		ide_unknown,	ide_generic,	ide_pci,
+ 		ide_rz1000,	ide_trm290,
+ 		ide_cmd646,	ide_cy82c693,	ide_4drives,
+ 		ide_pmac,	ide_etrax100,	ide_acorn,
+-		ide_au1xxx,	ide_palm3710,	ide_forced
++		ide_au1xxx,	ide_palm3710
+ };
+ 
+ typedef u8 hwif_chipset_t;
+@@ -185,15 +170,9 @@ typedef struct hw_regs_s {
+ 	struct device	*dev;
+ } hw_regs_t;
+ 
+-struct hwif_s * ide_find_port(unsigned long);
+-struct hwif_s *ide_deprecated_find_port(unsigned long);
+ void ide_init_port_data(struct hwif_s *, unsigned int);
+ void ide_init_port_hw(struct hwif_s *, hw_regs_t *);
+ 
+-struct ide_drive_s;
+-int ide_register_hw(hw_regs_t *, void (*)(struct ide_drive_s *),
+-		    struct hwif_s **);
+-
+ static inline void ide_std_init_ports(hw_regs_t *hw,
+ 				      unsigned long io_addr,
+ 				      unsigned long ctl_addr)
+@@ -213,45 +192,6 @@ static inline void ide_std_init_ports(hw_regs_t *hw,
+ #define MAX_HWIFS	CONFIG_IDE_MAX_HWIFS
+ #endif
+ 
+-/* needed on alpha, x86/x86_64, ia64, mips, ppc32 and sh */
+-#ifndef IDE_ARCH_OBSOLETE_DEFAULTS
+-# define ide_default_io_base(index)	(0)
+-# define ide_default_irq(base)		(0)
+-# define ide_init_default_irq(base)	(0)
+-#endif
+-
+-#ifdef CONFIG_IDE_ARCH_OBSOLETE_INIT
+-static inline void ide_init_hwif_ports(hw_regs_t *hw,
+-				       unsigned long io_addr,
+-				       unsigned long ctl_addr,
+-				       int *irq)
+-{
+-	if (!ctl_addr)
+-		ide_std_init_ports(hw, io_addr, ide_default_io_ctl(io_addr));
+-	else
+-		ide_std_init_ports(hw, io_addr, ctl_addr);
+-
+-	if (irq)
+-		*irq = 0;
+-
+-	hw->io_ports[IDE_IRQ_OFFSET] = 0;
+-
+-#ifdef CONFIG_PPC32
+-	if (ppc_ide_md.ide_init_hwif)
+-		ppc_ide_md.ide_init_hwif(hw, io_addr, ctl_addr, irq);
+-#endif
+-}
+-#else
+-static inline void ide_init_hwif_ports(hw_regs_t *hw,
+-				       unsigned long io_addr,
+-				       unsigned long ctl_addr,
+-				       int *irq)
+-{
+-	if (io_addr || ctl_addr)
+-		printk(KERN_WARNING "%s: must not be called\n", __FUNCTION__);
+-}
+-#endif /* CONFIG_IDE_ARCH_OBSOLETE_INIT */
+-
+ /* Currently only m68k, apus and m8xx need it */
+ #ifndef IDE_ARCH_ACK_INTR
+ # define ide_ack_intr(hwif) (1)
+@@ -406,7 +346,7 @@ typedef struct ide_drive_s {
+         u8	wcache;		/* status of write cache */
+ 	u8	acoustic;	/* acoustic management */
+ 	u8	media;		/* disk, cdrom, tape, floppy, ... */
+-	u8	ctl;		/* "normal" value for IDE_CONTROL_REG */
++	u8	ctl;		/* "normal" value for Control register */
+ 	u8	ready_stat;	/* min status value for drive ready */
+ 	u8	mult_count;	/* current multiple sector setting */
+ 	u8	mult_req;	/* requested multiple sector setting */
+@@ -507,8 +447,6 @@ typedef struct hwif_s {
+ 	void	(*maskproc)(ide_drive_t *, int);
+ 	/* check host's drive quirk list */
+ 	void	(*quirkproc)(ide_drive_t *);
+-	/* driver soft-power interface */
+-	int	(*busproc)(ide_drive_t *, int);
+ #endif
+ 	u8 (*mdma_filter)(ide_drive_t *);
+ 	u8 (*udma_filter)(ide_drive_t *);
+@@ -578,15 +516,15 @@ typedef struct hwif_s {
+ 
+ 	unsigned	noprobe    : 1;	/* don't probe for this interface */
+ 	unsigned	present    : 1;	/* this interface exists */
+-	unsigned	hold       : 1; /* this interface is always present */
+ 	unsigned	serialized : 1;	/* serialized all channel operation */
+ 	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
+ 	unsigned	reset      : 1;	/* reset after probe */
+ 	unsigned	sg_mapped  : 1;	/* sg_table and sg_nents are ready */
+ 	unsigned	mmio       : 1; /* host uses MMIO */
+-	unsigned	straight8  : 1;	/* Alan's straight 8 check */
+ 
+-	struct device	gendev;
++	struct device		gendev;
++	struct device		*portdev;
++
+ 	struct completion gendev_rel_comp; /* To deal with device release() */
+ 
+ 	void		*hwif_data;	/* extra hwif data */
+@@ -647,6 +585,68 @@ int set_io_32bit(ide_drive_t *, int);
+ int set_pio_mode(ide_drive_t *, int);
+ int set_using_dma(ide_drive_t *, int);
+ 
++/* ATAPI packet command flags */
++enum {
++	/* set when an error is considered normal - no retry (ide-tape) */
++	PC_FLAG_ABORT			= (1 << 0),
++	PC_FLAG_SUPPRESS_ERROR		= (1 << 1),
++	PC_FLAG_WAIT_FOR_DSC		= (1 << 2),
++	PC_FLAG_DMA_OK			= (1 << 3),
++	PC_FLAG_DMA_RECOMMENDED		= (1 << 4),
++	PC_FLAG_DMA_IN_PROGRESS		= (1 << 5),
++	PC_FLAG_DMA_ERROR		= (1 << 6),
++	PC_FLAG_WRITING			= (1 << 7),
++	/* command timed out */
++	PC_FLAG_TIMEDOUT		= (1 << 8),
++};
++
++struct ide_atapi_pc {
++	/* actual packet bytes */
++	u8 c[12];
++	/* incremented on each retry */
++	int retries;
++	int error;
++
++	/* bytes to transfer */
++	int req_xfer;
++	/* bytes actually transferred */
++	int xferred;
++
++	/* data buffer */
++	u8 *buf;
++	/* current buffer position */
++	u8 *cur_pos;
++	int buf_size;
++	/* missing/available data on the current buffer */
++	int b_count;
++
++	/* the corresponding request */
++	struct request *rq;
++
++	unsigned long flags;
++
++	/*
++	 * those are more or less driver-specific and some of them are subject
++	 * to change/removal later.
++	 */
++	u8 pc_buf[256];
++	void (*idefloppy_callback) (ide_drive_t *);
++	ide_startstop_t (*idetape_callback) (ide_drive_t *);
++
++	/* idetape only */
++	struct idetape_bh *bh;
++	char *b_data;
++
++	/* idescsi only for now */
++	struct scatterlist *sg;
++	unsigned int sg_cnt;
++
++	struct scsi_cmnd *scsi_cmd;
++	void (*done) (struct scsi_cmnd *);
++
++	unsigned long timeout;
++};
++
+ #ifdef CONFIG_IDE_PROC_FS
+ /*
+  * configurable drive settings
+@@ -691,6 +691,7 @@ void proc_ide_create(void);
+ void proc_ide_destroy(void);
+ void ide_proc_register_port(ide_hwif_t *);
+ void ide_proc_port_register_devices(ide_hwif_t *);
++void ide_proc_unregister_device(ide_drive_t *);
+ void ide_proc_unregister_port(ide_hwif_t *);
+ void ide_proc_register_driver(ide_drive_t *, ide_driver_t *);
+ void ide_proc_unregister_driver(ide_drive_t *, ide_driver_t *);
+@@ -724,6 +725,7 @@ static inline void proc_ide_create(void) { ; }
+ static inline void proc_ide_destroy(void) { ; }
+ static inline void ide_proc_register_port(ide_hwif_t *hwif) { ; }
+ static inline void ide_proc_port_register_devices(ide_hwif_t *hwif) { ; }
++static inline void ide_proc_unregister_device(ide_drive_t *drive) { ; }
+ static inline void ide_proc_unregister_port(ide_hwif_t *hwif) { ; }
+ static inline void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { ; }
+ static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { ; }
+@@ -805,6 +807,13 @@ extern	ide_hwif_t	ide_hwifs[];		/* master data repository */
+ #endif
+ extern int noautodma;
+ 
++ide_hwif_t *ide_find_port_slot(const struct ide_port_info *);
++
++static inline ide_hwif_t *ide_find_port(void)
++{
++	return ide_find_port_slot(NULL);
++}
++
+ extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
+ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
+ 			     int uptodate, int nr_sectors);
+@@ -990,7 +999,6 @@ extern void do_ide_request(struct request_queue *);
+ void ide_init_disk(struct gendisk *, ide_drive_t *);
+ 
+ #ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+-extern int ide_scan_direction;
+ extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner, const char *mod_name);
+ #define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE, KBUILD_MODNAME)
+ #else
+@@ -1024,8 +1032,8 @@ enum {
+ 	IDE_HFLAG_SINGLE		= (1 << 1),
+ 	/* don't use legacy PIO blacklist */
+ 	IDE_HFLAG_PIO_NO_BLACKLIST	= (1 << 2),
+-	/* don't use conservative PIO "downgrade" */
+-	IDE_HFLAG_PIO_NO_DOWNGRADE	= (1 << 3),
++	/* set for the second port of QD65xx */
++	IDE_HFLAG_QD_2ND_PORT		= (1 << 3),
+ 	/* use PIO8/9 for prefetch off/on */
+ 	IDE_HFLAG_ABUSE_PREFETCH	= (1 << 4),
+ 	/* use PIO6/7 for fast-devsel off/on */
+@@ -1047,8 +1055,8 @@ enum {
+ 	IDE_HFLAG_VDMA			= (1 << 11),
+ 	/* ATAPI DMA is unsupported */
+ 	IDE_HFLAG_NO_ATAPI_DMA		= (1 << 12),
+-	/* set if host is a "bootable" controller */
+-	IDE_HFLAG_BOOTABLE		= (1 << 13),
++	/* set if host is a "non-bootable" controller */
++	IDE_HFLAG_NON_BOOTABLE		= (1 << 13),
+ 	/* host doesn't support DMA */
+ 	IDE_HFLAG_NO_DMA		= (1 << 14),
+ 	/* check if host is PCI IDE device before allowing DMA */
+@@ -1076,8 +1084,6 @@ enum {
+ 	/* unmask IRQs */
+ 	IDE_HFLAG_UNMASK_IRQS		= (1 << 25),
+ 	IDE_HFLAG_ABUSE_SET_DMA_MODE	= (1 << 26),
+-	/* host is CY82C693 */
+-	IDE_HFLAG_CY82C693		= (1 << 27),
+ 	/* force host out of "simplex" mode */
+ 	IDE_HFLAG_CLEAR_SIMPLEX		= (1 << 28),
+ 	/* DSC overlap is unsupported */
+@@ -1089,9 +1095,9 @@ enum {
+ };
+ 
+ #ifdef CONFIG_BLK_DEV_OFFBOARD
+-# define IDE_HFLAG_OFF_BOARD	IDE_HFLAG_BOOTABLE
+-#else
+ # define IDE_HFLAG_OFF_BOARD	0
++#else
++# define IDE_HFLAG_OFF_BOARD	IDE_HFLAG_NON_BOOTABLE
+ #endif
+ 
+ struct ide_port_info {
+@@ -1195,7 +1201,7 @@ static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
+ void ide_remove_port_from_hwgroup(ide_hwif_t *);
+ extern int ide_hwif_request_regions(ide_hwif_t *hwif);
+ extern void ide_hwif_release_regions(ide_hwif_t* hwif);
+-void ide_unregister(unsigned int, int, int);
++void ide_unregister(unsigned int);
+ 
+ void ide_register_region(struct gendisk *);
+ void ide_unregister_region(struct gendisk *);
+@@ -1204,6 +1210,8 @@ void ide_undecoded_slave(ide_drive_t *);
+ 
+ int ide_device_add_all(u8 *idx, const struct ide_port_info *);
+ int ide_device_add(u8 idx[4], const struct ide_port_info *);
++void ide_port_unregister_devices(ide_hwif_t *);
++void ide_port_scan(ide_hwif_t *);
+ 
+ static inline void *ide_get_hwifdata (ide_hwif_t * hwif)
+ {
+@@ -1279,6 +1287,7 @@ extern struct mutex ide_cfg_mtx;
+ #define local_irq_set(flags)	do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0)
+ 
+ extern struct bus_type ide_bus_type;
++extern struct class *ide_port_class;
+ 
+ /* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */
+ #define ide_id_has_flush_cache(id)	((id)->cfs_enable_2 & 0x3000)
+@@ -1307,7 +1316,10 @@ static inline ide_drive_t *ide_get_paired_drive(ide_drive_t *drive)
+ 
+ static inline void ide_set_irq(ide_drive_t *drive, int on)
+ {
+-	drive->hwif->OUTB(drive->ctl | (on ? 0 : 2), IDE_CONTROL_REG);
++	ide_hwif_t *hwif = drive->hwif;
++
++	hwif->OUTB(drive->ctl | (on ? 0 : 2),
++		   hwif->io_ports[IDE_CONTROL_OFFSET]);
+ }
+ 
+ static inline u8 ide_read_status(ide_drive_t *drive)
+@@ -1331,4 +1343,26 @@ static inline u8 ide_read_error(ide_drive_t *drive)
+ 	return hwif->INB(hwif->io_ports[IDE_ERROR_OFFSET]);
+ }
+ 
++/*
++ * Too bad. The drive wants to send us data which we are not ready to accept.
++ * Just throw it away.
++ */
++static inline void ide_atapi_discard_data(ide_drive_t *drive, unsigned bcount)
++{
++	ide_hwif_t *hwif = drive->hwif;
++
++	/* FIXME: use ->atapi_input_bytes */
++	while (bcount--)
++		(void)hwif->INB(hwif->io_ports[IDE_DATA_OFFSET]);
++}
++
++static inline void ide_atapi_write_zeros(ide_drive_t *drive, unsigned bcount)
++{
++	ide_hwif_t *hwif = drive->hwif;
++
++	/* FIXME: use ->atapi_output_bytes */
++	while (bcount--)
++		hwif->OUTB(0, hwif->io_ports[IDE_DATA_OFFSET]);
++}
++
+ #endif /* _IDE_H */
+diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
+index f577c8f..529f301 100644
+--- a/include/linux/ieee80211.h
++++ b/include/linux/ieee80211.h
+@@ -97,6 +97,7 @@
+ #define IEEE80211_MAX_FRAME_LEN		2352
+ 
+ #define IEEE80211_MAX_SSID_LEN		32
++#define IEEE80211_MAX_MESH_ID_LEN	32
+ 
+ struct ieee80211_hdr {
+ 	__le16 frame_control;
+@@ -109,6 +110,16 @@ struct ieee80211_hdr {
+ } __attribute__ ((packed));
+ 
+ 
++struct ieee80211s_hdr {
++	u8 flags;
++	u8 ttl;
++	u8 seqnum[3];
++	u8 eaddr1[6];
++	u8 eaddr2[6];
++	u8 eaddr3[6];
++} __attribute__ ((packed));
++
++
+ struct ieee80211_mgmt {
+ 	__le16 frame_control;
+ 	__le16 duration;
+@@ -206,6 +217,23 @@ struct ieee80211_mgmt {
+ 					__le16 params;
+ 					__le16 reason_code;
+ 				} __attribute__((packed)) delba;
++				struct{
++					u8 action_code;
++					/* capab_info for open and confirm,
++					 * reason for close
++					 */
++					__le16 aux;
++					/* Followed in plink_confirm by status
++					 * code, AID and supported rates,
++					 * and directly by supported rates in
++					 * plink_open and plink_close
++					 */
++					u8 variable[0];
++				} __attribute__((packed)) plink_action;
++				struct{
++					u8 action_code;
++					u8 variable[0];
++				} __attribute__((packed)) mesh_action;
+ 			} u;
+ 		} __attribute__ ((packed)) action;
+ 	} u;
+@@ -437,6 +465,19 @@ enum ieee80211_eid {
+ 	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.
++	 */
++	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,
+ 	/* 802.11h */
+ 	WLAN_EID_PWR_CONSTRAINT = 32,
+ 	WLAN_EID_PWR_CAPABILITY = 33,
+diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
+index 296e8e8..4d34018 100644
+--- a/include/linux/if_arp.h
++++ b/include/linux/if_arp.h
+@@ -156,6 +156,12 @@ static inline struct arphdr *arp_hdr(const struct sk_buff *skb)
+ {
+ 	return (struct arphdr *)skb_network_header(skb);
+ }
++
++static inline int arp_hdr_len(struct net_device *dev)
++{
++	/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
++	return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2;
++}
+ #endif
+ 
+ #endif	/* _LINUX_IF_ARP_H */
+diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
+index 40743e0..6fb7f17 100644
+--- a/include/linux/if_pppox.h
++++ b/include/linux/if_pppox.h
+@@ -24,7 +24,6 @@
+ #include <linux/if_ether.h>
+ #include <linux/if.h>
+ #include <linux/netdevice.h>
+-#include <asm/semaphore.h>
+ #include <linux/ppp_channel.h>
+ #endif /* __KERNEL__ */
+ #include <linux/if_pppol2tp.h>
+diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
+index 228eb4e..f1fbe9c 100644
+--- a/include/linux/if_tunnel.h
++++ b/include/linux/if_tunnel.h
+@@ -7,6 +7,10 @@
+ #define SIOCADDTUNNEL   (SIOCDEVPRIVATE + 1)
+ #define SIOCDELTUNNEL   (SIOCDEVPRIVATE + 2)
+ #define SIOCCHGTUNNEL   (SIOCDEVPRIVATE + 3)
++#define SIOCGETPRL      (SIOCDEVPRIVATE + 4)
++#define SIOCADDPRL      (SIOCDEVPRIVATE + 5)
++#define SIOCDELPRL      (SIOCDEVPRIVATE + 6)
++#define SIOCCHGPRL      (SIOCDEVPRIVATE + 7)
+ 
+ #define GRE_CSUM	__constant_htons(0x8000)
+ #define GRE_ROUTING	__constant_htons(0x4000)
+@@ -17,9 +21,6 @@
+ #define GRE_FLAGS	__constant_htons(0x00F8)
+ #define GRE_VERSION	__constant_htons(0x0007)
+ 
+-/* i_flags values for SIT mode */
+-#define	SIT_ISATAP	0x0001
+-
+ struct ip_tunnel_parm
+ {
+ 	char			name[IFNAMSIZ];
+@@ -31,4 +32,19 @@ struct ip_tunnel_parm
+ 	struct iphdr		iph;
+ };
+ 
++/* SIT-mode i_flags */
++#define	SIT_ISATAP	0x0001
++
++struct ip_tunnel_prl {
++	__be32			addr;
++	__u16			flags;
++	__u16			__reserved;
++	__u32			datalen;
++	__u32			__reserved2;
++	void __user		*data;
++};
++
++/* PRL flags */
++#define	PRL_DEFAULT		0x0001
++
+ #endif /* _IF_TUNNEL_H_ */
+diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
+index 79504b2..15ace02 100644
+--- a/include/linux/if_vlan.h
++++ b/include/linux/if_vlan.h
+@@ -81,7 +81,9 @@ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
+ #define VLAN_GROUP_ARRAY_PART_LEN     (VLAN_GROUP_ARRAY_LEN/VLAN_GROUP_ARRAY_SPLIT_PARTS)
+ 
+ struct vlan_group {
+-	int real_dev_ifindex; /* The ifindex of the ethernet(like) device the vlan is attached to. */
++	struct net_device	*real_dev; /* The ethernet(like) device
++					    * the vlan is attached to.
++					    */
+ 	unsigned int		nr_vlans;
+ 	struct hlist_node	hlist;	/* linked list */
+ 	struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS];
+@@ -93,7 +95,7 @@ static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
+ {
+ 	struct net_device **array;
+ 	array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
+-	return array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN];
++	return array ? array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] : NULL;
+ }
+ 
+ static inline void vlan_group_set_device(struct vlan_group *vg,
+diff --git a/include/linux/if_wanpipe.h b/include/linux/if_wanpipe.h
+deleted file mode 100644
+index e594ca6..0000000
+--- a/include/linux/if_wanpipe.h
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/*****************************************************************************
+-* if_wanpipe.h	Header file for the Sangoma AF_WANPIPE Socket 	
+-*
+-* Author: 	Nenad Corbic 	
+-*
+-* Copyright:	(c) 2000 Sangoma Technologies 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.
+-* ============================================================================
+-*
+-* Jan 28, 2000	Nenad Corbic 	Initial Version
+-*
+-*****************************************************************************/
+-
+-#ifndef __LINUX_IF_WAN_PACKET_H
+-#define __LINUX_IF_WAN_PACKET_H
+-
+-struct wan_sockaddr_ll
+-{
+-	unsigned short	sll_family;
+-	unsigned short	sll_protocol;
+-	int		sll_ifindex;
+-	unsigned short	sll_hatype;
+-	unsigned char	sll_pkttype;
+-	unsigned char	sll_halen;
+-	unsigned char	sll_addr[8];
+-	unsigned char   sll_device[14];
+-	unsigned char 	sll_card[14];
+-};
+-
+-typedef struct 
+-{
+-	unsigned char free;
+-	unsigned char state_sk;
+-	int rcvbuf;
+-	int sndbuf;
+-	int rmem;
+-	int wmem;
+-	int sk_count;
+-	unsigned char bound;
+-	char name[14];
+-	unsigned char d_state;
+-	unsigned char svc;
+-	unsigned short lcn;
+-	unsigned char mbox;
+-	unsigned char cmd_busy;
+-	unsigned char command;
+-	unsigned poll;
+-	unsigned poll_cnt;
+-	int rblock;	
+-} wan_debug_hdr_t;
+-
+-#define MAX_NUM_DEBUG  10
+-#define X25_PROT       0x16
+-#define PVC_PROT       0x17	
+-
+-typedef struct
+-{
+-	wan_debug_hdr_t debug[MAX_NUM_DEBUG];
+-}wan_debug_t;
+-
+-#define	SIOC_WANPIPE_GET_CALL_DATA	(SIOCPROTOPRIVATE + 0)
+-#define	SIOC_WANPIPE_SET_CALL_DATA	(SIOCPROTOPRIVATE + 1)
+-#define SIOC_WANPIPE_ACCEPT_CALL	(SIOCPROTOPRIVATE + 2)
+-#define SIOC_WANPIPE_CLEAR_CALL	        (SIOCPROTOPRIVATE + 3)
+-#define SIOC_WANPIPE_RESET_CALL	        (SIOCPROTOPRIVATE + 4)
+-#define SIOC_WANPIPE_DEBUG	        (SIOCPROTOPRIVATE + 5)
+-#define SIOC_WANPIPE_SET_NONBLOCK	(SIOCPROTOPRIVATE + 6)
+-#define SIOC_WANPIPE_CHECK_TX		(SIOCPROTOPRIVATE + 7)
+-#define SIOC_WANPIPE_SOCK_STATE		(SIOCPROTOPRIVATE + 8)
+-
+-/* Packet types */
+-
+-#define WAN_PACKET_HOST		0		/* To us		*/
+-#define WAN_PACKET_BROADCAST	1		/* To all		*/
+-#define WAN_PACKET_MULTICAST	2		/* To group		*/
+-#define WAN_PACKET_OTHERHOST	3		/* To someone else 	*/
+-#define WAN_PACKET_OUTGOING		4		/* Outgoing of any type */
+-/* These ones are invisible by user level */
+-#define WAN_PACKET_LOOPBACK		5		/* MC/BRD frame looped back */
+-#define WAN_PACKET_FASTROUTE	6		/* Fastrouted frame	*/
+-
+-
+-/* X25 specific */
+-#define WAN_PACKET_DATA 	7
+-#define WAN_PACKET_CMD 		8
+-#define WAN_PACKET_ASYNC	9
+-#define WAN_PACKET_ERR	       10
+-
+-/* Packet socket options */
+-
+-#define WAN_PACKET_ADD_MEMBERSHIP		1
+-#define WAN_PACKET_DROP_MEMBERSHIP		2
+-
+-#define WAN_PACKET_MR_MULTICAST	0
+-#define WAN_PACKET_MR_PROMISC	1
+-#define WAN_PACKET_MR_ALLMULTI	2
+-
+-#ifdef __KERNEL__
+-
+-/* Private wanpipe socket structures. */
+-struct wanpipe_opt
+-{
+-	void   *mbox;		/* Mail box  */
+-	void   *card; 		/* Card bouded to */
+-	struct net_device *dev;	/* Bounded device */
+-	unsigned short lcn;	/* Binded LCN */
+-	unsigned char  svc;	/* 0=pvc, 1=svc */
+-	unsigned char  timer;   /* flag for delayed transmit*/	
+-	struct timer_list tx_timer;
+-	unsigned poll_cnt;
+-	unsigned char force;	/* Used to force sock release */
+-	atomic_t packet_sent;   
+-	unsigned short num; 
+-};
+-
+-#define wp_sk(__sk) ((struct wanpipe_opt *)(__sk)->sk_protinfo)
+-
+-#endif
+-
+-#endif
+diff --git a/include/linux/igmp.h b/include/linux/igmp.h
+index f510e7e..f5a1a0d 100644
+--- a/include/linux/igmp.h
++++ b/include/linux/igmp.h
+@@ -80,27 +80,6 @@ struct igmpv3_query {
+ 	__be32 srcs[0];
+ };
+ 
+-#ifdef __KERNEL__
+-#include <linux/skbuff.h>
+-
+-static inline struct igmphdr *igmp_hdr(const struct sk_buff *skb)
+-{
+-	return (struct igmphdr *)skb_transport_header(skb);
+-}
+-
+-static inline struct igmpv3_report *
+-			igmpv3_report_hdr(const struct sk_buff *skb)
+-{
+-	return (struct igmpv3_report *)skb_transport_header(skb);
+-}
+-
+-static inline struct igmpv3_query *
+-			igmpv3_query_hdr(const struct sk_buff *skb)
+-{
+-	return (struct igmpv3_query *)skb_transport_header(skb);
+-}
+-#endif
+-
+ #define IGMP_HOST_MEMBERSHIP_QUERY	0x11	/* From RFC1112 */
+ #define IGMP_HOST_MEMBERSHIP_REPORT	0x12	/* Ditto */
+ #define IGMP_DVMRP			0x13	/* DVMRP routing */
+@@ -151,6 +130,23 @@ static inline struct igmpv3_query *
+ #include <linux/timer.h>
+ #include <linux/in.h>
+ 
++static inline struct igmphdr *igmp_hdr(const struct sk_buff *skb)
++{
++	return (struct igmphdr *)skb_transport_header(skb);
++}
++
++static inline struct igmpv3_report *
++			igmpv3_report_hdr(const struct sk_buff *skb)
++{
++	return (struct igmpv3_report *)skb_transport_header(skb);
++}
++
++static inline struct igmpv3_query *
++			igmpv3_query_hdr(const struct sk_buff *skb)
++{
++	return (struct igmpv3_query *)skb_transport_header(skb);
++}
++
+ extern int sysctl_igmp_max_memberships;
+ extern int sysctl_igmp_max_msf;
+ 
+diff --git a/include/linux/in6.h b/include/linux/in6.h
+index 2a61c82..bc49204 100644
+--- a/include/linux/in6.h
++++ b/include/linux/in6.h
+@@ -48,6 +48,14 @@ extern const struct in6_addr in6addr_any;
+ #define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
+ extern const struct in6_addr in6addr_loopback;
+ #define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
++#ifdef __KERNEL__
++extern const struct in6_addr in6addr_linklocal_allnodes;
++#define IN6ADDR_LINKLOCAL_ALLNODES_INIT	\
++		{ { { 0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
++extern const struct in6_addr in6addr_linklocal_allrouters;
++#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
++		{ { { 0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2 } } }
++#endif
+ 
+ struct sockaddr_in6 {
+ 	unsigned short int	sin6_family;    /* AF_INET6 */
+@@ -249,4 +257,30 @@ struct in6_flowlabel_req
+  * IP6T_SO_GET_REVISION_TARGET	69
+  */
+ 
++/* RFC5014: Source address selection */
++#define IPV6_ADDR_PREFERENCES	72
++
++#define IPV6_PREFER_SRC_TMP		0x0001
++#define IPV6_PREFER_SRC_PUBLIC		0x0002
++#define IPV6_PREFER_SRC_PUBTMP_DEFAULT	0x0100
++#define IPV6_PREFER_SRC_COA		0x0004
++#define IPV6_PREFER_SRC_HOME		0x0400
++#define IPV6_PREFER_SRC_CGA		0x0008
++#define IPV6_PREFER_SRC_NONCGA		0x0800
++
++/*
++ * Multicast Routing:
++ * see include/linux/mroute6.h.
++ *
++ * MRT6_INIT			200
++ * MRT6_DONE			201
++ * MRT6_ADD_MIF			202
++ * MRT6_DEL_MIF			203
++ * MRT6_ADD_MFC			204
++ * MRT6_DEL_MFC			205
++ * MRT6_VERSION			206
++ * MRT6_ASSERT			207
++ * MRT6_PIM			208
++ * (reserved)			209
++ */
+ #endif
+diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
+index fc4e3db..7009b0c 100644
+--- a/include/linux/inetdevice.h
++++ b/include/linux/inetdevice.h
+@@ -70,13 +70,13 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
+ 	ipv4_devconf_set((in_dev), NET_IPV4_CONF_ ## attr, (val))
+ 
+ #define IN_DEV_ANDCONF(in_dev, attr) \
+-	(IPV4_DEVCONF_ALL(in_dev->dev->nd_net, attr) && \
++	(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), attr) && \
+ 	 IN_DEV_CONF_GET((in_dev), attr))
+ #define IN_DEV_ORCONF(in_dev, attr) \
+-	(IPV4_DEVCONF_ALL(in_dev->dev->nd_net, attr) || \
++	(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), attr) || \
+ 	 IN_DEV_CONF_GET((in_dev), attr))
+ #define IN_DEV_MAXCONF(in_dev, attr) \
+-	(max(IPV4_DEVCONF_ALL(in_dev->dev->nd_net, attr), \
++	(max(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), attr), \
+ 	     IN_DEV_CONF_GET((in_dev), attr)))
+ 
+ #define IN_DEV_FORWARD(in_dev)		IN_DEV_CONF_GET((in_dev), FORWARDING)
+@@ -129,7 +129,7 @@ extern int unregister_inetaddr_notifier(struct notifier_block *nb);
+ 
+ extern struct net_device *ip_dev_find(struct net *net, __be32 addr);
+ extern int		inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
+-extern int		devinet_ioctl(unsigned int cmd, void __user *);
++extern int		devinet_ioctl(struct net *net, unsigned int cmd, void __user *);
+ extern void		devinet_init(void);
+ extern struct in_device	*inetdev_by_index(struct net *, int);
+ extern __be32		inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
+diff --git a/include/linux/init_task.h b/include/linux/init_task.h
+index 1f74e1d..37a6f5b 100644
+--- a/include/linux/init_task.h
++++ b/include/linux/init_task.h
+@@ -151,6 +151,9 @@ extern struct group_info init_groups;
+ 	.cpus_allowed	= CPU_MASK_ALL,					\
+ 	.mm		= NULL,						\
+ 	.active_mm	= &init_mm,					\
++	.se		= {						\
++		.group_node 	= LIST_HEAD_INIT(tsk.se.group_node),	\
++	},								\
+ 	.rt		= {						\
+ 		.run_list	= LIST_HEAD_INIT(tsk.rt.run_list),	\
+ 		.time_slice	= HZ, 					\
+diff --git a/include/linux/input.h b/include/linux/input.h
+index cae2c35..28a094f 100644
+--- a/include/linux/input.h
++++ b/include/linux/input.h
+@@ -1025,10 +1025,6 @@ struct ff_effect {
+  * @node: used to place the device onto input_dev_list
+  */
+ struct input_dev {
+-	/* private: */
+-	void *private;	/* do not use */
+-	/* public: */
+-
+ 	const char *name;
+ 	const char *phys;
+ 	const char *uniq;
+@@ -1238,12 +1234,12 @@ static inline void input_put_device(struct input_dev *dev)
+ 
+ static inline void *input_get_drvdata(struct input_dev *dev)
+ {
+-	return dev->private;
++	return dev_get_drvdata(&dev->dev);
+ }
+ 
+ static inline void input_set_drvdata(struct input_dev *dev, void *data)
+ {
+-	dev->private = data;
++	dev_set_drvdata(&dev->dev, data);
+ }
+ 
+ int __must_check input_register_device(struct input_dev *);
+diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
+index f8ab4ce..b5fef13 100644
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -102,6 +102,25 @@ extern void disable_irq_nosync(unsigned int irq);
+ extern void disable_irq(unsigned int irq);
+ extern void enable_irq(unsigned int irq);
+ 
++#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
++
++extern int irq_set_affinity(unsigned int irq, cpumask_t cpumask);
++extern int irq_can_set_affinity(unsigned int irq);
++
++#else /* CONFIG_SMP */
++
++static inline int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
++{
++	return -EINVAL;
++}
++
++static inline int irq_can_set_affinity(unsigned int irq)
++{
++	return 0;
++}
++
++#endif /* CONFIG_SMP && CONFIG_GENERIC_HARDIRQS */
++
+ #ifdef CONFIG_GENERIC_HARDIRQS
+ /*
+  * Special lockdep variants of irq disabling/enabling.
+diff --git a/include/linux/ioport.h b/include/linux/ioport.h
+index 605d237..d5d40a9 100644
+--- a/include/linux/ioport.h
++++ b/include/linux/ioport.h
+@@ -44,7 +44,9 @@ struct resource_list {
+ #define IORESOURCE_CACHEABLE	0x00004000
+ #define IORESOURCE_RANGELENGTH	0x00008000
+ #define IORESOURCE_SHADOWABLE	0x00010000
+-#define IORESOURCE_BUS_HAS_VGA	0x00080000
++
++#define IORESOURCE_SIZEALIGN	0x00020000	/* size indicates alignment */
++#define IORESOURCE_STARTALIGN	0x00040000	/* start field is alignment */
+ 
+ #define IORESOURCE_DISABLED	0x10000000
+ #define IORESOURCE_UNSET	0x20000000
+@@ -110,6 +112,7 @@ extern int allocate_resource(struct resource *root, struct resource *new,
+ 			     void *alignf_data);
+ int adjust_resource(struct resource *res, resource_size_t start,
+ 		    resource_size_t size);
++resource_size_t resource_alignment(struct resource *res);
+ 
+ /* Convenience shorthand with allocation */
+ #define request_region(start,n,name)	__request_region(&ioport_resource, (start), (n), (name))
+diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
+index 134c8e5..10b666b 100644
+--- a/include/linux/ipv6.h
++++ b/include/linux/ipv6.h
+@@ -160,6 +160,9 @@ struct ipv6_devconf {
+ #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
+ 	__s32		optimistic_dad;
+ #endif
++#ifdef CONFIG_IPV6_MROUTE
++	__s32		mc_forwarding;
++#endif
+ 	void		*sysctl;
+ };
+ 
+@@ -190,6 +193,7 @@ enum {
+ 	DEVCONF_PROXY_NDP,
+ 	DEVCONF_OPTIMISTIC_DAD,
+ 	DEVCONF_ACCEPT_SOURCE_ROUTE,
++	DEVCONF_MC_FORWARDING,
+ 	DEVCONF_MAX
+ };
+ 
+@@ -230,6 +234,7 @@ struct inet6_skb_parm {
+ #endif
+ 
+ #define IP6SKB_XFRM_TRANSFORMED	1
++#define IP6SKB_FORWARDED	2
+ };
+ 
+ #define IP6CB(skb)	((struct inet6_skb_parm*)((skb)->cb))
+@@ -274,8 +279,29 @@ struct ipv6_pinfo {
+ 
+ 	__be32			flow_label;
+ 	__u32			frag_size;
+-	__s16			hop_limit;
+-	__s16			mcast_hops;
++
++	/*
++	 * Packed in 16bits.
++	 * Omit one shift by by putting the signed field at MSB.
++	 */
++#if defined(__BIG_ENDIAN_BITFIELD)
++	__s16			hop_limit:9;
++	__u16			__unused_1:7;
++#else
++	__u16			__unused_1:7;
++	__s16			hop_limit:9;
++#endif
++
++#if defined(__BIG_ENDIAN_BITFIELD)
++	/* Packed in 16bits. */
++	__s16			mcast_hops:9;
++	__u16			__unused_2:6,
++				mc_loop:1;
++#else
++	__u16			mc_loop:1,
++				__unused_2:6;
++	__s16			mcast_hops:9;
++#endif
+ 	int			mcast_oif;
+ 
+ 	/* pktoption flags */
+@@ -298,11 +324,14 @@ struct ipv6_pinfo {
+ 	} rxopt;
+ 
+ 	/* sockopt flags */
+-	__u8			mc_loop:1,
+-	                        recverr:1,
++	__u8			recverr:1,
+ 	                        sndflow:1,
+ 				pmtudisc:2,
+-				ipv6only:1;
++				ipv6only:1,
++				srcprefs:3;	/* 001: prefer temporary address
++						 * 010: prefer public address
++						 * 100: prefer care-of address
++						 */
+ 	__u8			tclass;
+ 
+ 	__u32			dst_cookie;
+@@ -315,9 +344,8 @@ struct ipv6_pinfo {
+ 	struct sk_buff		*pktoptions;
+ 	struct {
+ 		struct ipv6_txoptions *opt;
+-		struct rt6_info	*rt;
+-		int hop_limit;
+-		int tclass;
++		u8 hop_limit;
++		u8 tclass;
+ 	} cork;
+ };
+ 
+@@ -458,7 +486,7 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
+ #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+ 
+ #define INET6_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif)\
+-	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&& \
++	(((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)	&& \
+ 	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))  	&& \
+ 	 ((__sk)->sk_family		== AF_INET6)		&& \
+ 	 ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr))	&& \
+@@ -466,7 +494,7 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
+ 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+ 
+ #define INET6_TW_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif) \
+-	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&& \
++	(((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)	&& \
+ 	 (*((__portpair *)&(inet_twsk(__sk)->tw_dport)) == (__ports))	&& \
+ 	 ((__sk)->sk_family	       == PF_INET6)			&& \
+ 	 (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr)))	&& \
+diff --git a/include/linux/irq.h b/include/linux/irq.h
+index 176e5e7..1883a85 100644
+--- a/include/linux/irq.h
++++ b/include/linux/irq.h
+@@ -228,21 +228,11 @@ static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
+ 
+ #endif /* CONFIG_GENERIC_PENDING_IRQ */
+ 
+-extern int irq_set_affinity(unsigned int irq, cpumask_t cpumask);
+-extern int irq_can_set_affinity(unsigned int irq);
+-
+ #else /* CONFIG_SMP */
+ 
+ #define move_native_irq(x)
+ #define move_masked_irq(x)
+ 
+-static inline int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
+-{
+-	return -EINVAL;
+-}
+-
+-static inline int irq_can_set_affinity(unsigned int irq) { return 0; }
+-
+ #endif /* CONFIG_SMP */
+ 
+ #ifdef CONFIG_IRQBALANCE
+diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
+index 412e025..e600c4e 100644
+--- a/include/linux/irqflags.h
++++ b/include/linux/irqflags.h
+@@ -84,10 +84,10 @@
+ 
+ #define irqs_disabled()						\
+ ({								\
+-	unsigned long flags;					\
++	unsigned long _flags;					\
+ 								\
+-	raw_local_save_flags(flags);				\
+-	raw_irqs_disabled_flags(flags);				\
++	raw_local_save_flags(_flags);				\
++	raw_irqs_disabled_flags(_flags);			\
+ })
+ 
+ #define irqs_disabled_flags(flags)	raw_irqs_disabled_flags(flags)
+diff --git a/include/linux/iscsi_ibft.h b/include/linux/iscsi_ibft.h
+new file mode 100644
+index 0000000..6092487
+--- /dev/null
++++ b/include/linux/iscsi_ibft.h
+@@ -0,0 +1,50 @@
++/*
++ *  Copyright 2007 Red Hat, Inc.
++ *  by Peter Jones <pjones at redhat.com>
++ *  Copyright 2007 IBM, Inc.
++ *  by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ *  Copyright 2008
++ *  by Konrad Rzeszutek <ketuzsezr at darnok.org>
++ *
++ * This code exposes the iSCSI Boot Format Table to userland via sysfs.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT 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 ISCSI_IBFT_H
++#define ISCSI_IBFT_H
++
++struct ibft_table_header {
++	char signature[4];
++	u32 length;
++	u8 revision;
++	u8 checksum;
++	char oem_id[6];
++	char oem_table_id[8];
++	char reserved[24];
++} __attribute__((__packed__));
++
++/*
++ * Logical location of iSCSI Boot Format Table.
++ * If the value is NULL there is no iBFT on the machine.
++ */
++extern struct ibft_table_header *ibft_addr;
++
++/*
++ * Routine used to find and reserve the iSCSI Boot Format Table. The
++ * mapped address is set in the ibft_addr variable.
++ */
++#ifdef CONFIG_ISCSI_IBFT_FIND
++extern void __init reserve_ibft_region(void);
++#else
++static inline void reserve_ibft_region(void) { }
++#endif
++
++#endif /* ISCSI_IBFT_H */
+diff --git a/include/linux/isdn.h b/include/linux/isdn.h
+index 9cb2855..44cd663 100644
+--- a/include/linux/isdn.h
++++ b/include/linux/isdn.h
+@@ -16,14 +16,8 @@
+ 
+ #include <linux/ioctl.h>
+ 
+-#ifdef CONFIG_COBALT_MICRO_SERVER
+-/* Save memory */
+-#define ISDN_MAX_DRIVERS    2
+-#define ISDN_MAX_CHANNELS   8
+-#else
+ #define ISDN_MAX_DRIVERS    32
+ #define ISDN_MAX_CHANNELS   64
+-#endif
+ 
+ /* New ioctl-codes */
+ #define IIOCNETAIF  _IO('I',1)
+diff --git a/include/linux/jbd.h b/include/linux/jbd.h
+index 423f582..07a9b52 100644
+--- a/include/linux/jbd.h
++++ b/include/linux/jbd.h
+@@ -32,8 +32,6 @@
+ #include <linux/timer.h>
+ #include <linux/lockdep.h>
+ 
+-#include <asm/semaphore.h>
+-
+ #define journal_oom_retry 1
+ 
+ /*
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 2cbf6fd..05e2b30 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -30,8 +30,6 @@
+ #include <linux/bit_spinlock.h>
+ #include <linux/mutex.h>
+ #include <linux/timer.h>
+-
+-#include <asm/semaphore.h>
+ #endif
+ 
+ #define journal_oom_retry 1
+diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
+index e0b5b68..33ef710 100644
+--- a/include/linux/jiffies.h
++++ b/include/linux/jiffies.h
+@@ -36,7 +36,7 @@
+ #elif HZ >= 6144 && HZ < 12288
+ # define SHIFT_HZ	13
+ #else
+-# error You lose.
++# error Invalid value of HZ.
+ #endif
+ 
+ /* LATCH is used in the interval timer and ftape setup. */
+@@ -135,6 +135,22 @@ static inline u64 get_jiffies_64(void)
+ #define time_before_eq64(a,b)	time_after_eq64(b,a)
+ 
+ /*
++ * These four macros compare jiffies and 'a' for convenience.
++ */
++
++/* time_is_before_jiffies(a) return true if a is before jiffies */
++#define time_is_before_jiffies(a) time_after(jiffies, a)
++
++/* time_is_after_jiffies(a) return true if a is after jiffies */
++#define time_is_after_jiffies(a) time_before(jiffies, a)
++
++/* time_is_before_eq_jiffies(a) return true if a is before or equal to jiffies*/
++#define time_is_before_eq_jiffies(a) time_after_eq(jiffies, a)
++
++/* time_is_after_eq_jiffies(a) return true if a is after or equal to jiffies*/
++#define time_is_after_eq_jiffies(a) time_before_eq(jiffies, a)
++
++/*
+  * Have the 32 bit jiffies value wrap 5 minutes after boot
+  * so jiffies wrap bugs show up earlier.
+  */
+diff --git a/include/linux/kernel.h b/include/linux/kernel.h
+index 2df44e7..cd6d02c 100644
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -293,10 +293,8 @@ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ #define pr_debug(fmt, arg...) \
+ 	printk(KERN_DEBUG fmt, ##arg)
+ #else
+-static inline int __attribute__ ((format (printf, 1, 2))) pr_debug(const char * fmt, ...)
+-{
+-	return 0;
+-}
++#define pr_debug(fmt, arg...) \
++	({ if (0) printk(KERN_DEBUG fmt, ##arg); 0; })
+ #endif
+ 
+ /*
+diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h
+index 8c4350a..a53e932 100644
+--- a/include/linux/kernelcapi.h
++++ b/include/linux/kernelcapi.h
+@@ -48,7 +48,6 @@ typedef struct kcapi_carddef {
+ #include <linux/list.h>
+ #include <linux/skbuff.h>
+ #include <linux/workqueue.h>
+-#include <asm/semaphore.h>
+ 
+ #define	KCI_CONTRUP	0	/* arg: struct capi_profile */
+ #define	KCI_CONTRDOWN	1	/* arg: NULL */
+diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
+index 65c2d70..a3c984d 100644
+--- a/include/linux/keyboard.h
++++ b/include/linux/keyboard.h
+@@ -33,6 +33,7 @@ struct keyboard_notifier_param {
+ 	struct vc_data *vc;	/* VC on which the keyboard press was done */
+ 	int down;		/* Pressure of the key? */
+ 	int shift;		/* Current shift mask */
++	int ledstate;		/* Current led state */
+ 	unsigned int value;	/* keycode, unicode value or keysym */
+ };
+ 
+diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
+new file mode 100644
+index 0000000..9757b1a
+--- /dev/null
++++ b/include/linux/kgdb.h
+@@ -0,0 +1,281 @@
++/*
++ * This provides the callbacks and functions that KGDB needs to share between
++ * the core, I/O and arch-specific portions.
++ *
++ * Author: Amit Kale <amitkale at linsyssoft.com> and
++ *         Tom Rini <trini at kernel.crashing.org>
++ *
++ * 2001-2004 (c) Amit S. Kale and 2003-2005 (c) MontaVista Software, Inc.
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++#ifndef _KGDB_H_
++#define _KGDB_H_
++
++#include <linux/serial_8250.h>
++#include <linux/linkage.h>
++#include <linux/init.h>
++
++#include <asm/atomic.h>
++#include <asm/kgdb.h>
++
++struct pt_regs;
++
++/**
++ *	kgdb_skipexception - (optional) exit kgdb_handle_exception early
++ *	@exception: Exception vector number
++ *	@regs: Current &struct pt_regs.
++ *
++ *	On some architectures it is required to skip a breakpoint
++ *	exception when it occurs after a breakpoint has been removed.
++ *	This can be implemented in the architecture specific portion of
++ *	for kgdb.
++ */
++extern int kgdb_skipexception(int exception, struct pt_regs *regs);
++
++/**
++ *	kgdb_post_primary_code - (optional) Save error vector/code numbers.
++ *	@regs: Original pt_regs.
++ *	@e_vector: Original error vector.
++ *	@err_code: Original error code.
++ *
++ *	This is usually needed on architectures which support SMP and
++ *	KGDB.  This function is called after all the secondary cpus have
++ *	been put to a know spin state and the primary CPU has control over
++ *	KGDB.
++ */
++extern void kgdb_post_primary_code(struct pt_regs *regs, int e_vector,
++				  int err_code);
++
++/**
++ *	kgdb_disable_hw_debug - (optional) Disable hardware debugging hook
++ *	@regs: Current &struct pt_regs.
++ *
++ *	This function will be called if the particular architecture must
++ *	disable hardware debugging while it is processing gdb packets or
++ *	handling exception.
++ */
++extern void kgdb_disable_hw_debug(struct pt_regs *regs);
++
++struct tasklet_struct;
++struct task_struct;
++struct uart_port;
++
++/**
++ *	kgdb_breakpoint - compiled in breakpoint
++ *
++ *	This will be impelmented a static inline per architecture.  This
++ *	function is called by the kgdb core to execute an architecture
++ *	specific trap to cause kgdb to enter the exception processing.
++ *
++ */
++void kgdb_breakpoint(void);
++
++extern int kgdb_connected;
++
++extern atomic_t			kgdb_setting_breakpoint;
++extern atomic_t			kgdb_cpu_doing_single_step;
++
++extern struct task_struct	*kgdb_usethread;
++extern struct task_struct	*kgdb_contthread;
++
++enum kgdb_bptype {
++	BP_BREAKPOINT = 0,
++	BP_HARDWARE_BREAKPOINT,
++	BP_WRITE_WATCHPOINT,
++	BP_READ_WATCHPOINT,
++	BP_ACCESS_WATCHPOINT
++};
++
++enum kgdb_bpstate {
++	BP_UNDEFINED = 0,
++	BP_REMOVED,
++	BP_SET,
++	BP_ACTIVE
++};
++
++struct kgdb_bkpt {
++	unsigned long		bpt_addr;
++	unsigned char		saved_instr[BREAK_INSTR_SIZE];
++	enum kgdb_bptype	type;
++	enum kgdb_bpstate	state;
++};
++
++#ifndef KGDB_MAX_BREAKPOINTS
++# define KGDB_MAX_BREAKPOINTS	1000
++#endif
++
++#define KGDB_HW_BREAKPOINT	1
++
++/*
++ * Functions each KGDB-supporting architecture must provide:
++ */
++
++/**
++ *	kgdb_arch_init - Perform any architecture specific initalization.
++ *
++ *	This function will handle the initalization of any architecture
++ *	specific callbacks.
++ */
++extern int kgdb_arch_init(void);
++
++/**
++ *	kgdb_arch_exit - Perform any architecture specific uninitalization.
++ *
++ *	This function will handle the uninitalization of any architecture
++ *	specific callbacks, for dynamic registration and unregistration.
++ */
++extern void kgdb_arch_exit(void);
++
++/**
++ *	pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs
++ *	@gdb_regs: A pointer to hold the registers in the order GDB wants.
++ *	@regs: The &struct pt_regs of the current process.
++ *
++ *	Convert the pt_regs in @regs into the format for registers that
++ *	GDB expects, stored in @gdb_regs.
++ */
++extern void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs);
++
++/**
++ *	sleeping_thread_to_gdb_regs - Convert ptrace regs to GDB regs
++ *	@gdb_regs: A pointer to hold the registers in the order GDB wants.
++ *	@p: The &struct task_struct of the desired process.
++ *
++ *	Convert the register values of the sleeping process in @p to
++ *	the format that GDB expects.
++ *	This function is called when kgdb does not have access to the
++ *	&struct pt_regs and therefore it should fill the gdb registers
++ *	@gdb_regs with what has	been saved in &struct thread_struct
++ *	thread field during switch_to.
++ */
++extern void
++sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p);
++
++/**
++ *	gdb_regs_to_pt_regs - Convert GDB regs to ptrace regs.
++ *	@gdb_regs: A pointer to hold the registers we've received from GDB.
++ *	@regs: A pointer to a &struct pt_regs to hold these values in.
++ *
++ *	Convert the GDB regs in @gdb_regs into the pt_regs, and store them
++ *	in @regs.
++ */
++extern void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs);
++
++/**
++ *	kgdb_arch_handle_exception - Handle architecture specific GDB packets.
++ *	@vector: The error vector of the exception that happened.
++ *	@signo: The signal number of the exception that happened.
++ *	@err_code: The error code of the exception that happened.
++ *	@remcom_in_buffer: The buffer of the packet we have read.
++ *	@remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
++ *	@regs: The &struct pt_regs of the current process.
++ *
++ *	This function MUST handle the 'c' and 's' command packets,
++ *	as well packets to set / remove a hardware breakpoint, if used.
++ *	If there are additional packets which the hardware needs to handle,
++ *	they are handled here.  The code should return -1 if it wants to
++ *	process more packets, and a %0 or %1 if it wants to exit from the
++ *	kgdb callback.
++ */
++extern int
++kgdb_arch_handle_exception(int vector, int signo, int err_code,
++			   char *remcom_in_buffer,
++			   char *remcom_out_buffer,
++			   struct pt_regs *regs);
++
++/**
++ *	kgdb_roundup_cpus - Get other CPUs into a holding pattern
++ *	@flags: Current IRQ state
++ *
++ *	On SMP systems, we need to get the attention of the other CPUs
++ *	and get them be in a known state.  This should do what is needed
++ *	to get the other CPUs to call kgdb_wait(). Note that on some arches,
++ *	the NMI approach is not used for rounding up all the CPUs. For example,
++ *	in case of MIPS, smp_call_function() is used to roundup CPUs. In
++ *	this case, we have to make sure that interrupts are enabled before
++ *	calling smp_call_function(). The argument to this function is
++ *	the flags that will be used when restoring the interrupts. There is
++ *	local_irq_save() call before kgdb_roundup_cpus().
++ *
++ *	On non-SMP systems, this is not called.
++ */
++extern void kgdb_roundup_cpus(unsigned long flags);
++
++/* Optional functions. */
++extern int kgdb_validate_break_address(unsigned long addr);
++extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
++extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
++
++/**
++ * struct kgdb_arch - Describe architecture specific values.
++ * @gdb_bpt_instr: The instruction to trigger a breakpoint.
++ * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT.
++ * @set_breakpoint: Allow an architecture to specify how to set a software
++ * breakpoint.
++ * @remove_breakpoint: Allow an architecture to specify how to remove a
++ * software breakpoint.
++ * @set_hw_breakpoint: Allow an architecture to specify how to set a hardware
++ * breakpoint.
++ * @remove_hw_breakpoint: Allow an architecture to specify how to remove a
++ * hardware breakpoint.
++ * @remove_all_hw_break: Allow an architecture to specify how to remove all
++ * hardware breakpoints.
++ * @correct_hw_break: Allow an architecture to specify how to correct the
++ * hardware debug registers.
++ */
++struct kgdb_arch {
++	unsigned char		gdb_bpt_instr[BREAK_INSTR_SIZE];
++	unsigned long		flags;
++
++	int	(*set_breakpoint)(unsigned long, char *);
++	int	(*remove_breakpoint)(unsigned long, char *);
++	int	(*set_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
++	int	(*remove_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
++	void	(*remove_all_hw_break)(void);
++	void	(*correct_hw_break)(void);
++};
++
++/**
++ * struct kgdb_io - Describe the interface for an I/O driver to talk with KGDB.
++ * @name: Name of the I/O driver.
++ * @read_char: Pointer to a function that will return one char.
++ * @write_char: Pointer to a function that will write one char.
++ * @flush: Pointer to a function that will flush any pending writes.
++ * @init: Pointer to a function that will initialize the device.
++ * @pre_exception: Pointer to a function that will do any prep work for
++ * the I/O driver.
++ * @post_exception: Pointer to a function that will do any cleanup work
++ * for the I/O driver.
++ */
++struct kgdb_io {
++	const char		*name;
++	int			(*read_char) (void);
++	void			(*write_char) (u8);
++	void			(*flush) (void);
++	int			(*init) (void);
++	void			(*pre_exception) (void);
++	void			(*post_exception) (void);
++};
++
++extern struct kgdb_arch		arch_kgdb_ops;
++
++extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
++extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
++
++extern int kgdb_hex2long(char **ptr, long *long_val);
++extern int kgdb_mem2hex(char *mem, char *buf, int count);
++extern int kgdb_hex2mem(char *buf, char *mem, int count);
++
++extern int kgdb_isremovedbreak(unsigned long addr);
++
++extern int
++kgdb_handle_exception(int ex_vector, int signo, int err_code,
++		      struct pt_regs *regs);
++extern int kgdb_nmicallback(int cpu, void *regs);
++
++extern int			kgdb_single_step;
++extern atomic_t			kgdb_active;
++
++#endif /* _KGDB_H_ */
+diff --git a/include/linux/ktime.h b/include/linux/ktime.h
+index 2cd7fa7..ce59832 100644
+--- a/include/linux/ktime.h
++++ b/include/linux/ktime.h
+@@ -327,4 +327,10 @@ extern void ktime_get_ts(struct timespec *ts);
+ /* Get the real (wall-) time in timespec format: */
+ #define ktime_get_real_ts(ts)	getnstimeofday(ts)
+ 
++static inline ktime_t ns_to_ktime(u64 ns)
++{
++	static const ktime_t ktime_zero = { .tv64 = 0 };
++	return ktime_add_ns(ktime_zero, ns);
++}
++
+ #endif
+diff --git a/include/linux/leds.h b/include/linux/leds.h
+index 0201f6f..519df72 100644
+--- a/include/linux/leds.h
++++ b/include/linux/leds.h
+@@ -35,8 +35,11 @@ struct led_classdev {
+ #define LED_SUSPENDED		(1 << 0)
+ 
+ 	/* Set LED brightness level */
++	/* Must not sleep, use a workqueue if needed */
+ 	void		(*brightness_set)(struct led_classdev *led_cdev,
+ 					  enum led_brightness brightness);
++	/* Get LED brightness level */
++	enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
+ 
+ 	/* Activate hardware accelerated blink */
+ 	int		(*blink_set)(struct led_classdev *led_cdev,
+@@ -59,15 +62,7 @@ struct led_classdev {
+ 
+ extern int led_classdev_register(struct device *parent,
+ 				 struct led_classdev *led_cdev);
+-extern void __led_classdev_unregister(struct led_classdev *led_cdev, bool sus);
+-static inline void led_classdev_unregister(struct led_classdev *lcd)
+-{
+-	__led_classdev_unregister(lcd, false);
+-}
+-static inline void led_classdev_unregister_suspended(struct led_classdev *lcd)
+-{
+-	__led_classdev_unregister(lcd, true);
+-}
++extern void led_classdev_unregister(struct led_classdev *lcd);
+ extern void led_classdev_suspend(struct led_classdev *led_cdev);
+ extern void led_classdev_resume(struct led_classdev *led_cdev);
+ 
+@@ -134,6 +129,9 @@ struct gpio_led {
+ struct gpio_led_platform_data {
+ 	int 		num_leds;
+ 	struct gpio_led *leds;
++	int		(*gpio_blink_set)(unsigned gpio,
++					unsigned long *delay_on,
++					unsigned long *delay_off);
+ };
+ 
+ 
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index 37ee881..395a523 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -122,6 +122,8 @@ enum {
+ 
+ 	ATAPI_MAX_DRAIN		= 16 << 10,
+ 
++	ATA_ALL_DEVICES		= (1 << ATA_MAX_DEVICES) - 1,
++
+ 	ATA_SHT_EMULATED	= 1,
+ 	ATA_SHT_CMD_PER_LUN	= 1,
+ 	ATA_SHT_THIS_ID		= -1,
+@@ -163,9 +165,6 @@ enum {
+ 	ATA_DEV_NONE		= 9,	/* no device */
+ 
+ 	/* struct ata_link flags */
+-	ATA_LFLAG_HRST_TO_RESUME = (1 << 0), /* hardreset to resume link */
+-	ATA_LFLAG_SKIP_D2H_BSY	= (1 << 1), /* can't wait for the first D2H
+-					     * Register FIS clearing BSY */
+ 	ATA_LFLAG_NO_SRST	= (1 << 2), /* avoid softreset */
+ 	ATA_LFLAG_ASSUME_ATA	= (1 << 3), /* assume ATA class */
+ 	ATA_LFLAG_ASSUME_SEMB	= (1 << 4), /* assume SEMB class */
+@@ -225,6 +224,7 @@ enum {
+ 	ATA_QCFLAG_RESULT_TF	= (1 << 4), /* result TF requested */
+ 	ATA_QCFLAG_CLEAR_EXCL	= (1 << 5), /* clear excl_link on completion */
+ 	ATA_QCFLAG_QUIET	= (1 << 6), /* don't report device error */
++	ATA_QCFLAG_RETRY	= (1 << 7), /* retry after failure */
+ 
+ 	ATA_QCFLAG_FAILED	= (1 << 16), /* cmd failed and is owned by EH */
+ 	ATA_QCFLAG_SENSE_VALID	= (1 << 17), /* sense data valid */
+@@ -249,6 +249,25 @@ enum {
+ 	 */
+ 	ATA_TMOUT_FF_WAIT	= 4 * HZ / 5,
+ 
++	/* Spec mandates to wait for ">= 2ms" before checking status
++	 * after reset.  We wait 150ms, because that was the magic
++	 * delay used for ATAPI devices in Hale Landis's ATADRVR, for
++	 * the period of time between when the ATA command register is
++	 * written, and then status is checked.  Because waiting for
++	 * "a while" before checking status is fine, post SRST, we
++	 * perform this magic delay here as well.
++	 *
++	 * Old drivers/ide uses the 2mS rule and then waits for ready.
++	 */
++	ATA_WAIT_AFTER_RESET_MSECS = 150,
++
++	/* If PMP is supported, we have to do follow-up SRST.  As some
++	 * PMPs don't send D2H Reg FIS after hardreset, LLDs are
++	 * advised to wait only for the following duration before
++	 * doing SRST.
++	 */
++	ATA_TMOUT_PMP_SRST_WAIT	= 1 * HZ,
++
+ 	/* ATA bus states */
+ 	BUS_UNKNOWN		= 0,
+ 	BUS_DMA			= 1,
+@@ -292,17 +311,16 @@ enum {
+ 
+ 	/* reset / recovery action types */
+ 	ATA_EH_REVALIDATE	= (1 << 0),
+-	ATA_EH_SOFTRESET	= (1 << 1),
+-	ATA_EH_HARDRESET	= (1 << 2),
++	ATA_EH_SOFTRESET	= (1 << 1), /* meaningful only in ->prereset */
++	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_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+ 	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
+ 
+ 	/* ata_eh_info->flags */
+ 	ATA_EHI_HOTPLUGGED	= (1 << 0),  /* could have been hotplugged */
+-	ATA_EHI_RESUME_LINK	= (1 << 1),  /* resume link (reset modifier) */
+ 	ATA_EHI_NO_AUTOPSY	= (1 << 2),  /* no autopsy */
+ 	ATA_EHI_QUIET		= (1 << 3),  /* be quiet */
+ 
+@@ -313,7 +331,6 @@ enum {
+ 	ATA_EHI_POST_SETMODE	= (1 << 20), /* revaildating after setmode */
+ 
+ 	ATA_EHI_DID_RESET	= ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
+-	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+ 
+ 	/* max tries if error condition is still set after ->error_handler */
+ 	ATA_EH_MAX_TRIES	= 5,
+@@ -352,6 +369,22 @@ enum {
+ 	ATAPI_READ_CD		= 2,		/* READ CD [MSF] */
+ 	ATAPI_PASS_THRU		= 3,		/* SAT pass-thru */
+ 	ATAPI_MISC		= 4,		/* the rest */
++
++	/* Timing constants */
++	ATA_TIMING_SETUP	= (1 << 0),
++	ATA_TIMING_ACT8B	= (1 << 1),
++	ATA_TIMING_REC8B	= (1 << 2),
++	ATA_TIMING_CYC8B	= (1 << 3),
++	ATA_TIMING_8BIT		= ATA_TIMING_ACT8B | ATA_TIMING_REC8B |
++				  ATA_TIMING_CYC8B,
++	ATA_TIMING_ACTIVE	= (1 << 4),
++	ATA_TIMING_RECOVER	= (1 << 5),
++	ATA_TIMING_CYCLE	= (1 << 6),
++	ATA_TIMING_UDMA		= (1 << 7),
++	ATA_TIMING_ALL		= ATA_TIMING_SETUP | ATA_TIMING_ACT8B |
++				  ATA_TIMING_REC8B | ATA_TIMING_CYC8B |
++				  ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
++				  ATA_TIMING_CYCLE | ATA_TIMING_UDMA,
+ };
+ 
+ enum ata_xfer_mask {
+@@ -410,8 +443,9 @@ enum link_pm {
+ 	MAX_PERFORMANCE,
+ 	MEDIUM_POWER,
+ };
+-extern struct class_device_attribute class_device_attr_link_power_management_policy;
++extern struct device_attribute dev_attr_link_power_management_policy;
+ 
++#ifdef CONFIG_ATA_SFF
+ struct ata_ioports {
+ 	void __iomem		*cmd_addr;
+ 	void __iomem		*data_addr;
+@@ -429,6 +463,7 @@ struct ata_ioports {
+ 	void __iomem		*bmdma_addr;
+ 	void __iomem		*scr_addr;
+ };
++#endif /* CONFIG_ATA_SFF */
+ 
+ struct ata_host {
+ 	spinlock_t		lock;
+@@ -436,7 +471,7 @@ struct ata_host {
+ 	void __iomem * const	*iomap;
+ 	unsigned int		n_ports;
+ 	void			*private_data;
+-	const struct ata_port_operations *ops;
++	struct ata_port_operations *ops;
+ 	unsigned long		flags;
+ #ifdef CONFIG_ATA_ACPI
+ 	acpi_handle		acpi_handle;
+@@ -605,7 +640,7 @@ struct ata_link {
+ 
+ struct ata_port {
+ 	struct Scsi_Host	*scsi_host; /* our co-allocated scsi host */
+-	const struct ata_port_operations *ops;
++	struct ata_port_operations *ops;
+ 	spinlock_t		*lock;
+ 	unsigned long		flags;	/* ATA_FLAG_xxx */
+ 	unsigned int		pflags; /* ATA_PFLAG_xxx */
+@@ -615,7 +650,9 @@ struct ata_port {
+ 	struct ata_prd		*prd;	 /* our SG list */
+ 	dma_addr_t		prd_dma; /* and its DMA mapping */
+ 
++#ifdef CONFIG_ATA_SFF
+ 	struct ata_ioports	ioaddr;	/* ATA cmd/ctl/dma register blocks */
++#endif /* CONFIG_ATA_SFF */
+ 
+ 	u8			ctl;	/* cache of ATA control register */
+ 	u8			last_ctl;	/* Cache last written value */
+@@ -667,81 +704,108 @@ struct ata_port {
+ 	u8			sector_buf[ATA_SECT_SIZE]; /* owned by EH */
+ };
+ 
+-struct ata_port_operations {
+-	void (*dev_config) (struct ata_device *);
+-
+-	void (*set_piomode) (struct ata_port *, struct ata_device *);
+-	void (*set_dmamode) (struct ata_port *, struct ata_device *);
+-	unsigned long (*mode_filter) (struct ata_device *, unsigned long);
+-
+-	void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf);
+-	void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
+-
+-	void (*exec_command)(struct ata_port *ap, const struct ata_taskfile *tf);
+-	u8   (*check_status)(struct ata_port *ap);
+-	u8   (*check_altstatus)(struct ata_port *ap);
+-	void (*dev_select)(struct ata_port *ap, unsigned int device);
+-
+-	void (*phy_reset) (struct ata_port *ap); /* obsolete */
+-	int  (*set_mode) (struct ata_link *link, struct ata_device **r_failed_dev);
+-
+-	int (*cable_detect) (struct ata_port *ap);
+-
+-	int  (*check_atapi_dma) (struct ata_queued_cmd *qc);
+-
+-	void (*bmdma_setup) (struct ata_queued_cmd *qc);
+-	void (*bmdma_start) (struct ata_queued_cmd *qc);
+-
+-	unsigned int (*data_xfer) (struct ata_device *dev, unsigned char *buf,
+-				   unsigned int buflen, int rw);
+-
+-	int (*qc_defer) (struct ata_queued_cmd *qc);
+-	void (*qc_prep) (struct ata_queued_cmd *qc);
+-	unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
+-
+-	/* port multiplier */
+-	void (*pmp_attach) (struct ata_port *ap);
+-	void (*pmp_detach) (struct ata_port *ap);
++/* The following initializer overrides a method to NULL whether one of
++ * its parent has the method defined or not.  This is equivalent to
++ * ERR_PTR(-ENOENT).  Unfortunately, ERR_PTR doesn't render a constant
++ * expression and thus can't be used as an initializer.
++ */
++#define ATA_OP_NULL		(void *)(unsigned long)(-ENOENT)
+ 
+-	/* Error handlers.  ->error_handler overrides ->eng_timeout and
+-	 * indicates that new-style EH is in place.
++struct ata_port_operations {
++	/*
++	 * Command execution
+ 	 */
+-	void (*eng_timeout) (struct ata_port *ap); /* obsolete */
+-
+-	void (*freeze) (struct ata_port *ap);
+-	void (*thaw) (struct ata_port *ap);
+-	void (*error_handler) (struct ata_port *ap);
+-	void (*post_internal_cmd) (struct ata_queued_cmd *qc);
+-
+-	irq_handler_t irq_handler;
+-	void (*irq_clear) (struct ata_port *);
+-	u8 (*irq_on) (struct ata_port *);
+-
+-	int (*scr_read) (struct ata_port *ap, unsigned int sc_reg, u32 *val);
+-	int (*scr_write) (struct ata_port *ap, unsigned int sc_reg, u32 val);
++	int  (*qc_defer)(struct ata_queued_cmd *qc);
++	int  (*check_atapi_dma)(struct ata_queued_cmd *qc);
++	void (*qc_prep)(struct ata_queued_cmd *qc);
++	unsigned int (*qc_issue)(struct ata_queued_cmd *qc);
++	bool (*qc_fill_rtf)(struct ata_queued_cmd *qc);
++
++	/*
++	 * Configuration and exception handling
++	 */
++	int  (*cable_detect)(struct ata_port *ap);
++	unsigned long (*mode_filter)(struct ata_device *dev, unsigned long xfer_mask);
++	void (*set_piomode)(struct ata_port *ap, struct ata_device *dev);
++	void (*set_dmamode)(struct ata_port *ap, struct ata_device *dev);
++	int  (*set_mode)(struct ata_link *link, struct ata_device **r_failed_dev);
++
++	void (*dev_config)(struct ata_device *dev);
++
++	void (*freeze)(struct ata_port *ap);
++	void (*thaw)(struct ata_port *ap);
++	ata_prereset_fn_t	prereset;
++	ata_reset_fn_t		softreset;
++	ata_reset_fn_t		hardreset;
++	ata_postreset_fn_t	postreset;
++	ata_prereset_fn_t	pmp_prereset;
++	ata_reset_fn_t		pmp_softreset;
++	ata_reset_fn_t		pmp_hardreset;
++	ata_postreset_fn_t	pmp_postreset;
++	void (*error_handler)(struct ata_port *ap);
++	void (*post_internal_cmd)(struct ata_queued_cmd *qc);
++
++	/*
++	 * Optional features
++	 */
++	int  (*scr_read)(struct ata_port *ap, unsigned int sc_reg, u32 *val);
++	int  (*scr_write)(struct ata_port *ap, 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);
++
++	/*
++	 * Start, stop, suspend and resume
++	 */
++	int  (*port_suspend)(struct ata_port *ap, pm_message_t mesg);
++	int  (*port_resume)(struct ata_port *ap);
++	int  (*port_start)(struct ata_port *ap);
++	void (*port_stop)(struct ata_port *ap);
++	void (*host_stop)(struct ata_host *host);
++
++#ifdef CONFIG_ATA_SFF
++	/*
++	 * SFF / taskfile oriented ops
++	 */
++	void (*sff_dev_select)(struct ata_port *ap, unsigned int device);
++	u8   (*sff_check_status)(struct ata_port *ap);
++	u8   (*sff_check_altstatus)(struct ata_port *ap);
++	void (*sff_tf_load)(struct ata_port *ap, const struct ata_taskfile *tf);
++	void (*sff_tf_read)(struct ata_port *ap, struct ata_taskfile *tf);
++	void (*sff_exec_command)(struct ata_port *ap,
++				 const struct ata_taskfile *tf);
++	unsigned int (*sff_data_xfer)(struct ata_device *dev,
++			unsigned char *buf, unsigned int buflen, int rw);
++	u8   (*sff_irq_on)(struct ata_port *);
++	void (*sff_irq_clear)(struct ata_port *);
+ 
+-	int (*port_suspend) (struct ata_port *ap, pm_message_t mesg);
+-	int (*port_resume) (struct ata_port *ap);
+-	int (*enable_pm) (struct ata_port *ap, enum link_pm policy);
+-	void (*disable_pm) (struct ata_port *ap);
+-	int (*port_start) (struct ata_port *ap);
+-	void (*port_stop) (struct ata_port *ap);
++	void (*bmdma_setup)(struct ata_queued_cmd *qc);
++	void (*bmdma_start)(struct ata_queued_cmd *qc);
++	void (*bmdma_stop)(struct ata_queued_cmd *qc);
++	u8   (*bmdma_status)(struct ata_port *ap);
++#endif /* CONFIG_ATA_SFF */
+ 
+-	void (*host_stop) (struct ata_host *host);
++	/*
++	 * Obsolete
++	 */
++	void (*phy_reset)(struct ata_port *ap);
++	void (*eng_timeout)(struct ata_port *ap);
+ 
+-	void (*bmdma_stop) (struct ata_queued_cmd *qc);
+-	u8   (*bmdma_status) (struct ata_port *ap);
++	/*
++	 * ->inherits must be the last field and all the preceding
++	 * fields must be pointers.
++	 */
++	const struct ata_port_operations	*inherits;
+ };
+ 
+ struct ata_port_info {
+-	struct scsi_host_template	*sht;
+ 	unsigned long		flags;
+ 	unsigned long		link_flags;
+ 	unsigned long		pio_mask;
+ 	unsigned long		mwdma_mask;
+ 	unsigned long		udma_mask;
+-	const struct ata_port_operations *port_ops;
+-	irq_handler_t		irq_handler;
++	struct ata_port_operations *port_ops;
+ 	void 			*private_data;
+ };
+ 
+@@ -759,11 +823,14 @@ struct ata_timing {
+ 
+ #define FIT(v, vmin, vmax)	max_t(short, min_t(short, v, vmax), vmin)
+ 
++/*
++ * Core layer - drivers/ata/libata-core.c
++ */
+ extern const unsigned long sata_deb_timing_normal[];
+ extern const unsigned long sata_deb_timing_hotplug[];
+ extern const unsigned long sata_deb_timing_long[];
+ 
+-extern const struct ata_port_operations ata_dummy_port_ops;
++extern struct ata_port_operations ata_dummy_port_ops;
+ extern const struct ata_port_info ata_dummy_port_info;
+ 
+ static inline const unsigned long *
+@@ -780,24 +847,22 @@ static inline int ata_port_is_dummy(struct ata_port *ap)
+ 	return ap->ops == &ata_dummy_port_ops;
+ }
+ 
+-extern void sata_print_link_status(struct ata_link *link);
+ extern void ata_port_probe(struct ata_port *);
+-extern void ata_bus_reset(struct ata_port *ap);
+ extern int sata_set_spd(struct ata_link *link);
++extern int ata_std_prereset(struct ata_link *link, unsigned long deadline);
++extern int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
++				int (*check_ready)(struct ata_link *link));
+ extern int sata_link_debounce(struct ata_link *link,
+ 			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 ata_std_prereset(struct ata_link *link, unsigned long deadline);
+-extern int ata_std_softreset(struct ata_link *link, unsigned int *classes,
+-			     unsigned long deadline);
+ extern int sata_link_hardreset(struct ata_link *link,
+-			const unsigned long *timing, unsigned long deadline);
++			const unsigned long *timing, unsigned long deadline,
++			bool *online, int (*check_ready)(struct ata_link *));
+ extern int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ 			      unsigned long deadline);
+ extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
+ extern void ata_port_disable(struct ata_port *);
+-extern void ata_std_ports(struct ata_ioports *ioaddr);
+ 
+ extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports);
+ extern struct ata_host *ata_host_alloc_pinfo(struct device *dev,
+@@ -810,7 +875,7 @@ extern int ata_host_activate(struct ata_host *host, int irq,
+ 			     struct scsi_host_template *sht);
+ extern void ata_host_detach(struct ata_host *host);
+ extern void ata_host_init(struct ata_host *, struct device *,
+-			  unsigned long, const struct ata_port_operations *);
++			  unsigned long, struct ata_port_operations *);
+ extern int ata_scsi_detect(struct scsi_host_template *sht);
+ extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
+ extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
+@@ -823,7 +888,6 @@ extern void ata_sas_port_stop(struct ata_port *ap);
+ extern int ata_sas_slave_configure(struct scsi_device *, struct ata_port *);
+ extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
+ 			    struct ata_port *ap);
+-extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+ extern int sata_scr_valid(struct ata_link *link);
+ extern int sata_scr_read(struct ata_link *link, int reg, u32 *val);
+ extern int sata_scr_write(struct ata_link *link, int reg, u32 val);
+@@ -835,21 +899,9 @@ extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg);
+ extern void ata_host_resume(struct ata_host *host);
+ #endif
+ extern int ata_ratelimit(void);
+-extern int ata_busy_sleep(struct ata_port *ap,
+-			  unsigned long timeout_pat, unsigned long timeout);
+-extern void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline);
+-extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline);
+ extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+ 			     unsigned long interval_msec,
+ 			     unsigned long timeout_msec);
+-extern unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
+-					 u8 *r_err);
+-
+-/*
+- * Default driver ops implementations
+- */
+-extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
+-extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+ 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);
+@@ -864,23 +916,9 @@ extern unsigned long ata_xfer_mode2mask(u8 xfer_mode);
+ extern int ata_xfer_mode2shift(unsigned long xfer_mode);
+ extern const char *ata_mode_string(unsigned long xfer_mask);
+ extern unsigned long ata_id_xfermask(const u16 *id);
+-extern void ata_noop_dev_select(struct ata_port *ap, unsigned int device);
+-extern void ata_std_dev_select(struct ata_port *ap, unsigned int device);
+-extern u8 ata_check_status(struct ata_port *ap);
+-extern u8 ata_altstatus(struct ata_port *ap);
+-extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
+ extern int ata_port_start(struct ata_port *ap);
+-extern int ata_sff_port_start(struct ata_port *ap);
+-extern irqreturn_t ata_interrupt(int irq, void *dev_instance);
+-extern unsigned int ata_data_xfer(struct ata_device *dev,
+-			unsigned char *buf, unsigned int buflen, int rw);
+-extern unsigned int ata_data_xfer_noirq(struct ata_device *dev,
+-			unsigned char *buf, unsigned int buflen, int rw);
+ extern int ata_std_qc_defer(struct ata_queued_cmd *qc);
+-extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
+-extern void ata_qc_prep(struct ata_queued_cmd *qc);
+ extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
+-extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+ extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
+ 		 unsigned int n_elem);
+ extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
+@@ -889,24 +927,8 @@ extern void ata_id_string(const u16 *id, unsigned char *s,
+ 			  unsigned int ofs, unsigned int len);
+ extern void ata_id_c_string(const u16 *id, unsigned char *s,
+ 			    unsigned int ofs, unsigned int len);
+-extern void ata_bmdma_setup(struct ata_queued_cmd *qc);
+-extern void ata_bmdma_start(struct ata_queued_cmd *qc);
+-extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
+-extern u8   ata_bmdma_status(struct ata_port *ap);
+-extern void ata_bmdma_irq_clear(struct ata_port *ap);
+-extern void ata_bmdma_freeze(struct ata_port *ap);
+-extern void ata_bmdma_thaw(struct ata_port *ap);
+-extern void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+-			       ata_reset_fn_t softreset,
+-			       ata_reset_fn_t hardreset,
+-			       ata_postreset_fn_t postreset);
+-extern void ata_bmdma_error_handler(struct ata_port *ap);
+-extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc);
+-extern int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+-			u8 status, int in_wq);
+ extern void ata_qc_complete(struct ata_queued_cmd *qc);
+-extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+-				    void (*finish_qc)(struct ata_queued_cmd *));
++extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active);
+ extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
+ 			      void (*done)(struct scsi_cmnd *));
+ extern int ata_std_bios_param(struct scsi_device *sdev,
+@@ -918,7 +940,6 @@ extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
+ 				       int queue_depth);
+ extern struct ata_device *ata_dev_pair(struct ata_device *adev);
+ extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
+-extern u8 ata_irq_on(struct ata_port *ap);
+ 
+ extern int ata_cable_40wire(struct ata_port *ap);
+ extern int ata_cable_80wire(struct ata_port *ap);
+@@ -926,10 +947,7 @@ extern int ata_cable_sata(struct ata_port *ap);
+ extern int ata_cable_ignore(struct ata_port *ap);
+ extern int ata_cable_unknown(struct ata_port *ap);
+ 
+-/*
+- * Timing helpers
+- */
+-
++/* Timing helpers */
+ extern unsigned int ata_pio_need_iordy(const struct ata_device *);
+ extern const struct ata_timing *ata_timing_find_mode(u8 xfer_mode);
+ extern int ata_timing_compute(struct ata_device *, unsigned short,
+@@ -939,24 +957,31 @@ extern void ata_timing_merge(const struct ata_timing *,
+ 			     unsigned int);
+ extern u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle);
+ 
+-enum {
+-	ATA_TIMING_SETUP	= (1 << 0),
+-	ATA_TIMING_ACT8B	= (1 << 1),
+-	ATA_TIMING_REC8B	= (1 << 2),
+-	ATA_TIMING_CYC8B	= (1 << 3),
+-	ATA_TIMING_8BIT		= ATA_TIMING_ACT8B | ATA_TIMING_REC8B |
+-				  ATA_TIMING_CYC8B,
+-	ATA_TIMING_ACTIVE	= (1 << 4),
+-	ATA_TIMING_RECOVER	= (1 << 5),
+-	ATA_TIMING_CYCLE	= (1 << 6),
+-	ATA_TIMING_UDMA		= (1 << 7),
+-	ATA_TIMING_ALL		= ATA_TIMING_SETUP | ATA_TIMING_ACT8B |
+-				  ATA_TIMING_REC8B | ATA_TIMING_CYC8B |
+-				  ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
+-				  ATA_TIMING_CYCLE | ATA_TIMING_UDMA,
++/* PCI */
++#ifdef CONFIG_PCI
++struct pci_dev;
++
++struct pci_bits {
++	unsigned int		reg;	/* PCI config register to read */
++	unsigned int		width;	/* 1 (8 bit), 2 (16 bit), 4 (32 bit) */
++	unsigned long		mask;
++	unsigned long		val;
+ };
+ 
+-/* libata-acpi.c */
++extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
++extern void ata_pci_remove_one(struct pci_dev *pdev);
++
++#ifdef CONFIG_PM
++extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
++extern int __must_check ata_pci_device_do_resume(struct pci_dev *pdev);
++extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
++extern int ata_pci_device_resume(struct pci_dev *pdev);
++#endif /* CONFIG_PM */
++#endif /* CONFIG_PCI */
++
++/*
++ * ACPI - drivers/ata/libata-acpi.c
++ */
+ #ifdef CONFIG_ATA_ACPI
+ static inline const struct ata_acpi_gtm *ata_acpi_init_gtm(struct ata_port *ap)
+ {
+@@ -1000,56 +1025,8 @@ static inline int ata_acpi_cbl_80wire(struct ata_port *ap,
+ }
+ #endif
+ 
+-#ifdef CONFIG_PCI
+-struct pci_dev;
+-
+-extern int ata_pci_init_one(struct pci_dev *pdev,
+-			     const struct ata_port_info * const * ppi);
+-extern void ata_pci_remove_one(struct pci_dev *pdev);
+-#ifdef CONFIG_PM
+-extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
+-extern int __must_check ata_pci_device_do_resume(struct pci_dev *pdev);
+-extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+-extern int ata_pci_device_resume(struct pci_dev *pdev);
+-#endif
+-extern int ata_pci_clear_simplex(struct pci_dev *pdev);
+-
+-struct pci_bits {
+-	unsigned int		reg;	/* PCI config register to read */
+-	unsigned int		width;	/* 1 (8 bit), 2 (16 bit), 4 (32 bit) */
+-	unsigned long		mask;
+-	unsigned long		val;
+-};
+-
+-extern int ata_pci_init_sff_host(struct ata_host *host);
+-extern int ata_pci_init_bmdma(struct ata_host *host);
+-extern int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+-				    const struct ata_port_info * const * ppi,
+-				    struct ata_host **r_host);
+-extern int ata_pci_activate_sff_host(struct ata_host *host,
+-				     irq_handler_t irq_handler,
+-				     struct scsi_host_template *sht);
+-extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
+-extern unsigned long ata_pci_default_filter(struct ata_device *dev,
+-					    unsigned long xfer_mask);
+-#endif /* CONFIG_PCI */
+-
+-/*
+- * PMP
+- */
+-extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc);
+-extern int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline);
+-extern int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class,
+-				  unsigned long deadline);
+-extern void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class);
+-extern void sata_pmp_do_eh(struct ata_port *ap,
+-		ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+-		ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
+-		ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
+-		ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset);
+-
+ /*
+- * EH
++ * EH - drivers/ata/libata-eh.c
+  */
+ extern void ata_port_schedule_eh(struct ata_port *ap);
+ extern int ata_link_abort(struct ata_link *link);
+@@ -1066,6 +1043,92 @@ extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
+ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 		      ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+ 		      ata_postreset_fn_t postreset);
++extern void ata_std_error_handler(struct ata_port *ap);
++
++/*
++ * Base operations to inherit from and initializers for sht
++ *
++ * Operations
++ *
++ * base  : Common to all libata drivers.
++ * sata  : SATA controllers w/ native interface.
++ * pmp   : SATA controllers w/ PMP support.
++ * sff   : SFF ATA controllers w/o BMDMA support.
++ * bmdma : SFF ATA controllers w/ BMDMA support.
++ *
++ * sht initializers
++ *
++ * BASE  : Common to all libata drivers.  The user must set
++ *	   sg_tablesize and dma_boundary.
++ * PIO   : SFF ATA controllers w/ only PIO support.
++ * BMDMA : SFF ATA controllers w/ BMDMA support.  sg_tablesize and
++ *	   dma_boundary are set to BMDMA limits.
++ * NCQ   : SATA controllers supporting NCQ.  The user must set
++ *	   sg_tablesize, dma_boundary and can_queue.
++ */
++extern const struct ata_port_operations ata_base_port_ops;
++extern const struct ata_port_operations sata_port_ops;
++
++#define ATA_BASE_SHT(drv_name)					\
++	.module			= THIS_MODULE,			\
++	.name			= drv_name,			\
++	.ioctl			= ata_scsi_ioctl,		\
++	.queuecommand		= ata_scsi_queuecmd,		\
++	.can_queue		= ATA_DEF_QUEUE,		\
++	.this_id		= ATA_SHT_THIS_ID,		\
++	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,		\
++	.emulated		= ATA_SHT_EMULATED,		\
++	.use_clustering		= ATA_SHT_USE_CLUSTERING,	\
++	.proc_name		= drv_name,			\
++	.slave_configure	= ata_scsi_slave_config,	\
++	.slave_destroy		= ata_scsi_slave_destroy,	\
++	.bios_param		= ata_std_bios_param
++
++#define ATA_NCQ_SHT(drv_name)					\
++	ATA_BASE_SHT(drv_name),					\
++	.change_queue_depth	= ata_scsi_change_queue_depth
++
++/*
++ * PMP helpers
++ */
++#ifdef CONFIG_SATA_PMP
++static inline bool sata_pmp_supported(struct ata_port *ap)
++{
++	return ap->flags & ATA_FLAG_PMP;
++}
++
++static inline bool sata_pmp_attached(struct ata_port *ap)
++{
++	return ap->nr_pmp_links != 0;
++}
++
++static inline int ata_is_host_link(const struct ata_link *link)
++{
++	return link == &link->ap->link;
++}
++#else /* CONFIG_SATA_PMP */
++static inline bool sata_pmp_supported(struct ata_port *ap)
++{
++	return false;
++}
++
++static inline bool sata_pmp_attached(struct ata_port *ap)
++{
++	return false;
++}
++
++static inline int ata_is_host_link(const struct ata_link *link)
++{
++	return 1;
++}
++#endif /* CONFIG_SATA_PMP */
++
++static inline int sata_srst_pmp(struct ata_link *link)
++{
++	if (sata_pmp_supported(link->ap) && ata_is_host_link(link))
++		return SATA_PMP_CTRL_PORT;
++	return link->pmp;
++}
+ 
+ /*
+  * printk helpers
+@@ -1074,7 +1137,7 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 	printk("%sata%u: "fmt, lv, (ap)->print_id , ##args)
+ 
+ #define ata_link_printk(link, lv, fmt, args...) do { \
+-	if ((link)->ap->nr_pmp_links) \
++	if (sata_pmp_attached((link)->ap)) \
+ 		printk("%sata%u.%02u: "fmt, lv, (link)->ap->print_id,	\
+ 		       (link)->pmp , ##args); \
+ 	else \
+@@ -1094,18 +1157,11 @@ extern void ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...)
+ 	__attribute__ ((format (printf, 2, 3)));
+ extern void ata_ehi_clear_desc(struct ata_eh_info *ehi);
+ 
+-static inline void ata_ehi_schedule_probe(struct ata_eh_info *ehi)
+-{
+-	ehi->flags |= ATA_EHI_RESUME_LINK;
+-	ehi->action |= ATA_EH_SOFTRESET;
+-	ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
+-}
+-
+ static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
+ {
+-	ata_ehi_schedule_probe(ehi);
++	ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
+ 	ehi->flags |= ATA_EHI_HOTPLUGGED;
+-	ehi->action |= ATA_EH_ENABLE_LINK;
++	ehi->action |= ATA_EH_RESET | ATA_EH_ENABLE_LINK;
+ 	ehi->err_mask |= AC_ERR_ATA_BUS;
+ }
+ 
+@@ -1126,7 +1182,7 @@ static inline unsigned int ata_tag_valid(unsigned int tag)
+ 
+ static inline unsigned int ata_tag_internal(unsigned int tag)
+ {
+-	return tag == ATA_MAX_QUEUE - 1;
++	return tag == ATA_TAG_INTERNAL;
+ }
+ 
+ /*
+@@ -1167,11 +1223,6 @@ static inline unsigned int ata_dev_absent(const struct ata_device *dev)
+ /*
+  * link helpers
+  */
+-static inline int ata_is_host_link(const struct ata_link *link)
+-{
+-	return link == &link->ap->link;
+-}
+-
+ static inline int ata_link_max_devices(const struct ata_link *link)
+ {
+ 	if (ata_is_host_link(link) && link->ap->flags & ATA_FLAG_SLAVE_POSS)
+@@ -1186,7 +1237,7 @@ static inline int ata_link_active(struct ata_link *link)
+ 
+ static inline struct ata_link *ata_port_first_link(struct ata_port *ap)
+ {
+-	if (ap->nr_pmp_links)
++	if (sata_pmp_attached(ap))
+ 		return ap->pmp_link;
+ 	return &ap->link;
+ }
+@@ -1195,8 +1246,8 @@ static inline struct ata_link *ata_port_next_link(struct ata_link *link)
+ {
+ 	struct ata_port *ap = link->ap;
+ 
+-	if (link == &ap->link) {
+-		if (!ap->nr_pmp_links)
++	if (ata_is_host_link(link)) {
++		if (!sata_pmp_attached(ap))
+ 			return NULL;
+ 		return ap->pmp_link;
+ 	}
+@@ -1222,11 +1273,6 @@ static inline struct ata_link *ata_port_next_link(struct ata_link *link)
+ 	for ((dev) = (link)->device + ata_link_max_devices(link) - 1; \
+ 	     (dev) >= (link)->device || ((dev) = NULL); (dev)--)
+ 
+-static inline u8 ata_chk_status(struct ata_port *ap)
+-{
+-	return ap->ops->check_status(ap);
+-}
+-
+ /**
+  *	ata_ncq_enabled - Test whether NCQ is enabled
+  *	@dev: ATA device to test for
+@@ -1243,74 +1289,6 @@ static inline int ata_ncq_enabled(struct ata_device *dev)
+ 			      ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ;
+ }
+ 
+-/**
+- *	ata_pause - Flush writes and pause 400 nanoseconds.
+- *	@ap: Port to wait for.
+- *
+- *	LOCKING:
+- *	Inherited from caller.
+- */
+-
+-static inline void ata_pause(struct ata_port *ap)
+-{
+-	ata_altstatus(ap);
+-	ndelay(400);
+-}
+-
+-
+-/**
+- *	ata_busy_wait - Wait for a port status register
+- *	@ap: Port to wait for.
+- *	@bits: bits that must be clear
+- *	@max: number of 10uS waits to perform
+- *
+- *	Waits up to max*10 microseconds for the selected bits in the port's
+- *	status register to be cleared.
+- *	Returns final value of status register.
+- *
+- *	LOCKING:
+- *	Inherited from caller.
+- */
+-
+-static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
+-			       unsigned int max)
+-{
+-	u8 status;
+-
+-	do {
+-		udelay(10);
+-		status = ata_chk_status(ap);
+-		max--;
+-	} while (status != 0xff && (status & bits) && (max > 0));
+-
+-	return status;
+-}
+-
+-
+-/**
+- *	ata_wait_idle - Wait for a port to be idle.
+- *	@ap: Port to wait for.
+- *
+- *	Waits up to 10ms for port's BUSY and DRQ signals to clear.
+- *	Returns final value of status register.
+- *
+- *	LOCKING:
+- *	Inherited from caller.
+- */
+-
+-static inline u8 ata_wait_idle(struct ata_port *ap)
+-{
+-	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+-
+-#ifdef ATA_DEBUG
+-	if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ)))
+-		ata_port_printk(ap, KERN_DEBUG, "abnormal Status 0x%X\n",
+-				status);
+-#endif
+-
+-	return status;
+-}
+-
+ static inline void ata_qc_set_polling(struct ata_queued_cmd *qc)
+ {
+ 	qc->tf.ctl |= ATA_NIEN;
+@@ -1403,4 +1381,171 @@ static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host)
+ 	return *(struct ata_port **)&host->hostdata[0];
+ }
+ 
++
++/**************************************************************************
++ * PMP - drivers/ata/libata-pmp.c
++ */
++#ifdef CONFIG_SATA_PMP
++
++extern const struct ata_port_operations sata_pmp_port_ops;
++
++extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc);
++extern void sata_pmp_error_handler(struct ata_port *ap);
++
++#else /* CONFIG_SATA_PMP */
++
++#define sata_pmp_port_ops		sata_port_ops
++#define sata_pmp_qc_defer_cmd_switch	ata_std_qc_defer
++#define sata_pmp_error_handler		ata_std_error_handler
++
++#endif /* CONFIG_SATA_PMP */
++
++
++/**************************************************************************
++ * SFF - drivers/ata/libata-sff.c
++ */
++#ifdef CONFIG_ATA_SFF
++
++extern const struct ata_port_operations ata_sff_port_ops;
++extern const struct ata_port_operations ata_bmdma_port_ops;
++
++/* PIO only, sg_tablesize and dma_boundary limits can be removed */
++#define ATA_PIO_SHT(drv_name)					\
++	ATA_BASE_SHT(drv_name),					\
++	.sg_tablesize		= LIBATA_MAX_PRD,		\
++	.dma_boundary		= ATA_DMA_BOUNDARY
++
++#define ATA_BMDMA_SHT(drv_name)					\
++	ATA_BASE_SHT(drv_name),					\
++	.sg_tablesize		= LIBATA_MAX_PRD,		\
++	.dma_boundary		= ATA_DMA_BOUNDARY
++
++extern void ata_sff_qc_prep(struct ata_queued_cmd *qc);
++extern void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc);
++extern void ata_sff_dev_select(struct ata_port *ap, unsigned int device);
++extern u8 ata_sff_check_status(struct ata_port *ap);
++extern u8 ata_sff_altstatus(struct ata_port *ap);
++extern int ata_sff_busy_sleep(struct ata_port *ap,
++			      unsigned long timeout_pat, unsigned long timeout);
++extern int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline);
++extern void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
++extern void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
++extern void ata_sff_exec_command(struct ata_port *ap,
++				 const struct ata_taskfile *tf);
++extern unsigned int ata_sff_data_xfer(struct ata_device *dev,
++			unsigned char *buf, unsigned int buflen, int rw);
++extern unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev,
++			unsigned char *buf, unsigned int buflen, int rw);
++extern u8 ata_sff_irq_on(struct ata_port *ap);
++extern void ata_sff_irq_clear(struct ata_port *ap);
++extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
++			    u8 status, int in_wq);
++extern unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc);
++extern bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc);
++extern unsigned int ata_sff_host_intr(struct ata_port *ap,
++				      struct ata_queued_cmd *qc);
++extern irqreturn_t ata_sff_interrupt(int irq, void *dev_instance);
++extern void ata_sff_freeze(struct ata_port *ap);
++extern void ata_sff_thaw(struct ata_port *ap);
++extern int ata_sff_prereset(struct ata_link *link, unsigned long deadline);
++extern unsigned int ata_sff_dev_classify(struct ata_device *dev, int present,
++					  u8 *r_err);
++extern int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
++				    unsigned long deadline);
++extern int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
++			     unsigned long deadline);
++extern int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
++			       unsigned long deadline);
++extern void ata_sff_postreset(struct ata_link *link, unsigned int *classes);
++extern void ata_sff_error_handler(struct ata_port *ap);
++extern void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc);
++extern int ata_sff_port_start(struct ata_port *ap);
++extern void ata_sff_std_ports(struct ata_ioports *ioaddr);
++extern unsigned long ata_bmdma_mode_filter(struct ata_device *dev,
++					   unsigned long xfer_mask);
++extern void ata_bmdma_setup(struct ata_queued_cmd *qc);
++extern void ata_bmdma_start(struct ata_queued_cmd *qc);
++extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
++extern u8 ata_bmdma_status(struct ata_port *ap);
++extern void ata_bus_reset(struct ata_port *ap);
++
++#ifdef CONFIG_PCI
++extern int ata_pci_bmdma_clear_simplex(struct pci_dev *pdev);
++extern int ata_pci_bmdma_init(struct ata_host *host);
++extern int ata_pci_sff_init_host(struct ata_host *host);
++extern int ata_pci_sff_prepare_host(struct pci_dev *pdev,
++				    const struct ata_port_info * const * ppi,
++				    struct ata_host **r_host);
++extern int ata_pci_sff_activate_host(struct ata_host *host,
++				     irq_handler_t irq_handler,
++				     struct scsi_host_template *sht);
++extern int ata_pci_sff_init_one(struct pci_dev *pdev,
++				const struct ata_port_info * const * ppi,
++				struct scsi_host_template *sht, void *host_priv);
++#endif /* CONFIG_PCI */
++
++/**
++ *	ata_sff_pause - Flush writes and pause 400 nanoseconds.
++ *	@ap: Port to wait for.
++ *
++ *	LOCKING:
++ *	Inherited from caller.
++ */
++static inline void ata_sff_pause(struct ata_port *ap)
++{
++	ata_sff_altstatus(ap);
++	ndelay(400);
++}
++
++/**
++ *	ata_sff_busy_wait - Wait for a port status register
++ *	@ap: Port to wait for.
++ *	@bits: bits that must be clear
++ *	@max: number of 10uS waits to perform
++ *
++ *	Waits up to max*10 microseconds for the selected bits in the port's
++ *	status register to be cleared.
++ *	Returns final value of status register.
++ *
++ *	LOCKING:
++ *	Inherited from caller.
++ */
++static inline u8 ata_sff_busy_wait(struct ata_port *ap, unsigned int bits,
++				   unsigned int max)
++{
++	u8 status;
++
++	do {
++		udelay(10);
++		status = ap->ops->sff_check_status(ap);
++		max--;
++	} while (status != 0xff && (status & bits) && (max > 0));
++
++	return status;
++}
++
++/**
++ *	ata_wait_idle - Wait for a port to be idle.
++ *	@ap: Port to wait for.
++ *
++ *	Waits up to 10ms for port's BUSY and DRQ signals to clear.
++ *	Returns final value of status register.
++ *
++ *	LOCKING:
++ *	Inherited from caller.
++ */
++static inline u8 ata_wait_idle(struct ata_port *ap)
++{
++	u8 status = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
++
++#ifdef ATA_DEBUG
++	if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ)))
++		ata_port_printk(ap, KERN_DEBUG, "abnormal Status 0x%X\n",
++				status);
++#endif
++
++	return status;
++}
++#endif /* CONFIG_ATA_SFF */
++
+ #endif /* __LINUX_LIBATA_H__ */
+diff --git a/include/linux/list.h b/include/linux/list.h
+index 75ce2cb..dac16f9 100644
+--- a/include/linux/list.h
++++ b/include/linux/list.h
+@@ -631,31 +631,14 @@ static inline void list_splice_init_rcu(struct list_head *list,
+  * as long as the traversal is guarded by rcu_read_lock().
+  */
+ #define list_for_each_rcu(pos, head) \
+-	for (pos = (head)->next; \
+-		prefetch(rcu_dereference(pos)->next), pos != (head); \
+-        	pos = pos->next)
++	for (pos = rcu_dereference((head)->next); \
++		prefetch(pos->next), pos != (head); \
++		pos = rcu_dereference(pos->next))
+ 
+ #define __list_for_each_rcu(pos, head) \
+-	for (pos = (head)->next; \
+-		rcu_dereference(pos) != (head); \
+-        	pos = pos->next)
+-
+-/**
+- * list_for_each_safe_rcu
+- * @pos:	the &struct list_head to use as a loop cursor.
+- * @n:		another &struct list_head to use as temporary storage
+- * @head:	the head for your list.
+- *
+- * Iterate over an rcu-protected list, safe against removal of list entry.
+- *
+- * This list-traversal primitive may safely run concurrently with
+- * the _rcu list-mutation primitives such as list_add_rcu()
+- * as long as the traversal is guarded by rcu_read_lock().
+- */
+-#define list_for_each_safe_rcu(pos, n, head) \
+-	for (pos = (head)->next; \
+-		n = rcu_dereference(pos)->next, pos != (head); \
+-		pos = n)
++	for (pos = rcu_dereference((head)->next); \
++		pos != (head); \
++		pos = rcu_dereference(pos->next))
+ 
+ /**
+  * list_for_each_entry_rcu	-	iterate over rcu list of given type
+@@ -668,10 +651,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
+  * as long as the traversal is guarded by rcu_read_lock().
+  */
+ #define list_for_each_entry_rcu(pos, head, member) \
+-	for (pos = list_entry((head)->next, typeof(*pos), member); \
+-		prefetch(rcu_dereference(pos)->member.next), \
+-			&pos->member != (head); \
+-		pos = list_entry(pos->member.next, typeof(*pos), member))
++	for (pos = list_entry(rcu_dereference((head)->next), typeof(*pos), member); \
++		prefetch(pos->member.next), &pos->member != (head); \
++		pos = list_entry(rcu_dereference(pos->member.next), typeof(*pos), member))
+ 
+ 
+ /**
+@@ -686,9 +668,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
+  * as long as the traversal is guarded by rcu_read_lock().
+  */
+ #define list_for_each_continue_rcu(pos, head) \
+-	for ((pos) = (pos)->next; \
+-		prefetch(rcu_dereference((pos))->next), (pos) != (head); \
+-        	(pos) = (pos)->next)
++	for ((pos) = rcu_dereference((pos)->next); \
++		prefetch((pos)->next), (pos) != (head); \
++		(pos) = rcu_dereference((pos)->next))
+ 
+ /*
+  * Double linked lists with a single pointer list head.
+@@ -986,10 +968,10 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
+  * as long as the traversal is guarded by rcu_read_lock().
+  */
+ #define hlist_for_each_entry_rcu(tpos, pos, head, member)		 \
+-	for (pos = (head)->first;					 \
+-	     rcu_dereference(pos) && ({ prefetch(pos->next); 1;}) &&	 \
++	for (pos = rcu_dereference((head)->first);			 \
++	        pos && ({ prefetch(pos->next); 1;}) &&			 \
+ 		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+-	     pos = pos->next)
++	     pos = rcu_dereference(pos->next))
+ 
+ #else
+ #warning "don't include kernel headers in userspace"
+diff --git a/include/linux/lm_interface.h b/include/linux/lm_interface.h
+index 1418fdc..f274997 100644
+--- a/include/linux/lm_interface.h
++++ b/include/linux/lm_interface.h
+@@ -21,9 +21,15 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
+  * modify the filesystem.  The lock module shouldn't assign a journal to the FS
+  * mount.  It shouldn't send recovery callbacks to the FS mount.  If the node
+  * dies or withdraws, all locks can be wiped immediately.
++ *
++ * LM_MFLAG_CONV_NODROP
++ * Do not allow the dlm to internally resolve conversion deadlocks by demoting
++ * the lock to unlocked and then reacquiring it in the requested mode. Instead,
++ * it should cancel the request and return LM_OUT_CONV_DEADLK.
+  */
+ 
+ #define LM_MFLAG_SPECTATOR	0x00000001
++#define LM_MFLAG_CONV_NODROP	0x00000002
+ 
+ /*
+  * lm_lockstruct flags
+@@ -110,6 +116,9 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
+  *
+  * LM_OUT_ASYNC
+  * The result of the request will be returned in an LM_CB_ASYNC callback.
++ *
++ * LM_OUT_CONV_DEADLK
++ * The lock request was canceled do to a conversion deadlock.
+  */
+ 
+ #define LM_OUT_ST_MASK		0x00000003
+@@ -117,6 +126,7 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
+ #define LM_OUT_CANCELED		0x00000008
+ #define LM_OUT_ASYNC		0x00000080
+ #define LM_OUT_ERROR		0x00000100
++#define LM_OUT_CONV_DEADLK	0x00000200
+ 
+ /*
+  * lm_callback_t types
+diff --git a/include/linux/lmb.h b/include/linux/lmb.h
+new file mode 100644
+index 0000000..271153d
+--- /dev/null
++++ b/include/linux/lmb.h
+@@ -0,0 +1,85 @@
++#ifndef _LINUX_LMB_H
++#define _LINUX_LMB_H
++#ifdef __KERNEL__
++
++/*
++ * Logical memory blocks.
++ *
++ * Copyright (C) 2001 Peter Bergner, IBM Corp.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/init.h>
++#include <linux/mm.h>
++
++#define MAX_LMB_REGIONS 128
++
++struct lmb_property {
++	u64 base;
++	u64 size;
++};
++
++struct lmb_region {
++	unsigned long cnt;
++	u64 size;
++	struct lmb_property region[MAX_LMB_REGIONS+1];
++};
++
++struct lmb {
++	unsigned long debug;
++	u64 rmo_size;
++	struct lmb_region memory;
++	struct lmb_region reserved;
++};
++
++extern struct lmb lmb;
++
++extern void __init lmb_init(void);
++extern void __init lmb_analyze(void);
++extern long __init lmb_add(u64 base, u64 size);
++extern long __init lmb_reserve(u64 base, u64 size);
++extern u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
++				u64 (*nid_range)(u64, u64, int *));
++extern u64 __init lmb_alloc(u64 size, u64 align);
++extern u64 __init lmb_alloc_base(u64 size,
++		u64, u64 max_addr);
++extern u64 __init __lmb_alloc_base(u64 size,
++		u64 align, u64 max_addr);
++extern u64 __init lmb_phys_mem_size(void);
++extern u64 __init lmb_end_of_DRAM(void);
++extern void __init lmb_enforce_memory_limit(u64 memory_limit);
++extern int __init lmb_is_reserved(u64 addr);
++
++extern void lmb_dump_all(void);
++
++static inline u64
++lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
++{
++	return type->region[region_nr].size;
++}
++static inline u64
++lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
++{
++	return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
++}
++static inline u64
++lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
++{
++	return type->region[region_nr].base >> PAGE_SHIFT;
++}
++static inline u64
++lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
++{
++	return lmb_start_pfn(type, region_nr) +
++	       lmb_size_pages(type, region_nr);
++}
++
++#include <asm/lmb.h>
++
++#endif /* __KERNEL__ */
++
++#endif /* _LINUX_LMB_H */
+diff --git a/include/linux/lock_dlm_plock.h b/include/linux/lock_dlm_plock.h
+deleted file mode 100644
+index fc34151..0000000
+--- a/include/linux/lock_dlm_plock.h
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/*
+- * Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+- *
+- * This copyrighted material is made available to anyone wishing to use,
+- * modify, copy, or redistribute it subject to the terms and conditions
+- * of the GNU General Public License v.2.
+- */
+-
+-#ifndef __LOCK_DLM_PLOCK_DOT_H__
+-#define __LOCK_DLM_PLOCK_DOT_H__
+-
+-#define GDLM_PLOCK_MISC_NAME		"lock_dlm_plock"
+-
+-#define GDLM_PLOCK_VERSION_MAJOR	1
+-#define GDLM_PLOCK_VERSION_MINOR	1
+-#define GDLM_PLOCK_VERSION_PATCH	0
+-
+-enum {
+-	GDLM_PLOCK_OP_LOCK = 1,
+-	GDLM_PLOCK_OP_UNLOCK,
+-	GDLM_PLOCK_OP_GET,
+-};
+-
+-struct gdlm_plock_info {
+-	__u32 version[3];
+-	__u8 optype;
+-	__u8 ex;
+-	__u8 wait;
+-	__u8 pad;
+-	__u32 pid;
+-	__s32 nodeid;
+-	__s32 rv;
+-	__u32 fsid;
+-	__u64 number;
+-	__u64 start;
+-	__u64 end;
+-	__u64 owner;
+-};
+-
+-#endif
+-
+diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
+index 4babb2a..102d928 100644
+--- a/include/linux/lockd/lockd.h
++++ b/include/linux/lockd/lockd.h
+@@ -91,6 +91,7 @@ struct nlm_wait;
+  */
+ #define NLMCLNT_OHSIZE		((__NEW_UTS_LEN) + 10u)
+ struct nlm_rqst {
++	atomic_t		a_count;
+ 	unsigned int		a_flags;	/* initial RPC task flags */
+ 	struct nlm_host *	a_host;		/* host handle */
+ 	struct nlm_args		a_args;		/* arguments */
+@@ -173,8 +174,10 @@ void		  nlmclnt_next_cookie(struct nlm_cookie *);
+ /*
+  * Host cache
+  */
+-struct nlm_host  *nlmclnt_lookup_host(const struct sockaddr_in *, int, int,
+-					const char *, unsigned int);
++struct nlm_host  *nlmclnt_lookup_host(const struct sockaddr_in *sin,
++					int proto, u32 version,
++					const char *hostname,
++					unsigned int hostname_len);
+ struct nlm_host  *nlmsvc_lookup_host(struct svc_rqst *, const char *,
+ 					unsigned int);
+ struct rpc_clnt * nlm_bind_host(struct nlm_host *);
+@@ -191,7 +194,7 @@ void		  nsm_release(struct nsm_handle *);
+  * This is used in garbage collection and resource reclaim
+  * A return value != 0 means destroy the lock/block/share
+  */
+-typedef int	  (*nlm_host_match_fn_t)(struct nlm_host *cur, struct nlm_host *ref);
++typedef int	  (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref);
+ 
+ /*
+  * Server-side lock handling
+@@ -217,8 +220,13 @@ void		  nlmsvc_mark_resources(void);
+ void		  nlmsvc_free_host_resources(struct nlm_host *);
+ void		  nlmsvc_invalidate_all(void);
+ 
+-static __inline__ struct inode *
+-nlmsvc_file_inode(struct nlm_file *file)
++/*
++ * Cluster failover support
++ */
++int           nlmsvc_unlock_all_by_sb(struct super_block *sb);
++int           nlmsvc_unlock_all_by_ip(__be32 server_addr);
++
++static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
+ {
+ 	return file->f_file->f_path.dentry->d_inode;
+ }
+@@ -226,8 +234,8 @@ nlmsvc_file_inode(struct nlm_file *file)
+ /*
+  * Compare two host addresses (needs modifying for ipv6)
+  */
+-static __inline__ int
+-nlm_cmp_addr(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
++static inline int nlm_cmp_addr(const struct sockaddr_in *sin1,
++			       const struct sockaddr_in *sin2)
+ {
+ 	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
+ }
+@@ -236,8 +244,8 @@ nlm_cmp_addr(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
+  * Compare two NLM locks.
+  * When the second lock is of type F_UNLCK, this acts like a wildcard.
+  */
+-static __inline__ int
+-nlm_compare_locks(const struct file_lock *fl1, const struct file_lock *fl2)
++static inline int nlm_compare_locks(const struct file_lock *fl1,
++				    const struct file_lock *fl2)
+ {
+ 	return	fl1->fl_pid   == fl2->fl_pid
+ 	     && fl1->fl_owner == fl2->fl_owner
+diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h
+index 22a6458..5a5448b 100644
+--- a/include/linux/lockd/sm_inter.h
++++ b/include/linux/lockd/sm_inter.h
+@@ -19,6 +19,7 @@
+ #define SM_NOTIFY	6
+ 
+ #define SM_MAXSTRLEN	1024
++#define SM_PRIV_SIZE	16
+ 
+ /*
+  * Arguments for all calls to statd
+diff --git a/include/linux/mbus.h b/include/linux/mbus.h
+new file mode 100644
+index 0000000..c11ff29
+--- /dev/null
++++ b/include/linux/mbus.h
+@@ -0,0 +1,36 @@
++/*
++ * Marvell MBUS common definitions.
++ *
++ * Copyright (C) 2008 Marvell Semiconductor
++ *
++ * 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 __LINUX_MBUS_H
++#define __LINUX_MBUS_H
++
++struct mbus_dram_target_info
++{
++	/*
++	 * The 4-bit MBUS target ID of the DRAM controller.
++	 */
++	u8		mbus_dram_target_id;
++
++	/*
++	 * The base address, size, and MBUS attribute ID for each
++	 * of the possible DRAM chip selects.  Peripherals are
++	 * required to support at least 4 decode windows.
++	 */
++	int		num_cs;
++	struct mbus_dram_window {
++		u8	cs_index;
++		u8	mbus_attr;
++		u32	base;
++		u32	size;
++	} cs[4];
++};
++
++
++#endif
+diff --git a/include/linux/memory.h b/include/linux/memory.h
+index 33f0ff0..f80e0e3 100644
+--- a/include/linux/memory.h
++++ b/include/linux/memory.h
+@@ -18,8 +18,7 @@
+ #include <linux/sysdev.h>
+ #include <linux/node.h>
+ #include <linux/compiler.h>
+-
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
+ 
+ struct memory_block {
+ 	unsigned long phys_index;
+@@ -30,7 +29,7 @@ struct memory_block {
+ 	 * created long after the critical areas during
+ 	 * initialization.
+ 	 */
+-	struct semaphore state_sem;
++	struct mutex state_mutex;
+ 	int phys_device;		/* to which fru does this belong? */
+ 	void *hw;			/* optional pointer to fw/hw data */
+ 	int (*phys_callback)(struct memory_block *);
+diff --git a/include/linux/memstick.h b/include/linux/memstick.h
+index 3e686ec..37a5cdb 100644
+--- a/include/linux/memstick.h
++++ b/include/linux/memstick.h
+@@ -276,7 +276,7 @@ struct memstick_host {
+ #define MEMSTICK_CAP_PAR8          4
+ 
+ 	struct work_struct  media_checker;
+-	struct class_device cdev;
++	struct device       dev;
+ 
+ 	struct memstick_dev *card;
+ 	unsigned int        retries;
+diff --git a/include/linux/meye.h b/include/linux/meye.h
+index 39fd9c8..12010ac 100644
+--- a/include/linux/meye.h
++++ b/include/linux/meye.h
+@@ -58,7 +58,7 @@ struct meye_params {
+ 
+ /* V4L2 private controls */
+ #define V4L2_CID_AGC		V4L2_CID_PRIVATE_BASE
+-#define V4L2_CID_SHARPNESS	(V4L2_CID_PRIVATE_BASE + 1)
++#define V4L2_CID_MEYE_SHARPNESS	(V4L2_CID_PRIVATE_BASE + 1)
+ #define V4L2_CID_PICTURE	(V4L2_CID_PRIVATE_BASE + 2)
+ #define V4L2_CID_JPEGQUAL	(V4L2_CID_PRIVATE_BASE + 3)
+ #define V4L2_CID_FRAMERATE	(V4L2_CID_PRIVATE_BASE + 4)
+diff --git a/include/linux/mfd/htc-egpio.h b/include/linux/mfd/htc-egpio.h
+new file mode 100644
+index 0000000..b4201c9
+--- /dev/null
++++ b/include/linux/mfd/htc-egpio.h
+@@ -0,0 +1,57 @@
++/*
++ * HTC simple EGPIO irq and gpio extender
++ */
++
++#ifndef __HTC_EGPIO_H__
++#define __HTC_EGPIO_H__
++
++#include <linux/gpio.h>
++
++/* Descriptive values for all-in or all-out htc_egpio_chip descriptors. */
++#define HTC_EGPIO_OUTPUT (~0)
++#define HTC_EGPIO_INPUT  0
++
++/**
++ * struct htc_egpio_chip - descriptor to create gpio_chip for register range
++ * @reg_start: index of first register
++ * @gpio_base: gpio number of first pin in this register range
++ * @num_gpios: number of gpios in this register range, max BITS_PER_LONG
++ *    (number of registers = DIV_ROUND_UP(num_gpios, reg_width))
++ * @direction: bitfield, '0' = input, '1' = output,
++ */
++struct htc_egpio_chip {
++	int           reg_start;
++	int           gpio_base;
++	int           num_gpios;
++	unsigned long direction;
++	unsigned long initial_values;
++};
++
++/**
++ * struct htc_egpio_platform_data - description provided by the arch
++ * @irq_base: beginning of available IRQs (eg, IRQ_BOARD_START)
++ * @num_irqs: number of irqs
++ * @reg_width: number of bits per register, either 8 or 16 bit
++ * @bus_width: alignment of the registers, either 16 or 32 bit
++ * @invert_acks: set if chip requires writing '0' to ack an irq, instead of '1'
++ * @ack_register: location of the irq/ack register
++ * @chip: pointer to array of htc_egpio_chip descriptors
++ * @num_chips: number of egpio chip descriptors
++ */
++struct htc_egpio_platform_data {
++	int                   bus_width;
++	int                   reg_width;
++
++	int                   irq_base;
++	int                   num_irqs;
++	int                   invert_acks;
++	int                   ack_register;
++
++	struct htc_egpio_chip *chip;
++	int                   num_chips;
++};
++
++/* Determine the wakeup irq, to be called during early resume */
++extern int htc_egpio_get_wakeup_irq(struct device *dev);
++
++#endif
+diff --git a/include/linux/mfd/htc-pasic3.h b/include/linux/mfd/htc-pasic3.h
+new file mode 100644
+index 0000000..b4294f1
+--- /dev/null
++++ b/include/linux/mfd/htc-pasic3.h
+@@ -0,0 +1,55 @@
++/*
++ * HTC PASIC3 driver - LEDs and DS1WM
++ *
++ * Copyright (c) 2007 Philipp Zabel <philipp.zabel at gmail.com>
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file COPYING in the main directory of this archive for
++ * more details.
++ *
++ */
++
++#ifndef __PASIC3_H
++#define __PASIC3_H
++
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++
++extern void pasic3_write_register(struct device *dev, u32 reg, u8 val);
++extern u8 pasic3_read_register(struct device *dev, u32 reg);
++
++/*
++ * mask for registers 0x20,0x21,0x22
++ */
++#define PASIC3_MASK_LED0 0x04
++#define PASIC3_MASK_LED1 0x08
++#define PASIC3_MASK_LED2 0x40
++
++/*
++ * bits in register 0x06
++ */
++#define PASIC3_BIT2_LED0 0x08
++#define PASIC3_BIT2_LED1 0x10
++#define PASIC3_BIT2_LED2 0x20
++
++struct pasic3_led {
++	struct led_classdev         led;
++	unsigned int                hw_num;
++	unsigned int                bit2;
++	unsigned int                mask;
++	struct pasic3_leds_machinfo *pdata;
++};
++
++struct pasic3_leds_machinfo {
++	unsigned int      num_leds;
++	unsigned int      power_gpio;
++	struct pasic3_led *leds;
++};
++
++struct pasic3_platform_data {
++	struct pasic3_leds_machinfo *led_pdata;
++	unsigned int                 bus_shift;
++	unsigned int                 clock_rate;
++};
++
++#endif
+diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
+index 24b30b9..26433ec 100644
+--- a/include/linux/miscdevice.h
++++ b/include/linux/miscdevice.h
+@@ -43,15 +43,7 @@ struct miscdevice  {
+ };
+ 
+ extern int misc_register(struct miscdevice * misc);
+-extern int __misc_deregister(struct miscdevice *misc, bool suspended);
+-static inline int misc_deregister(struct miscdevice *misc)
+-{
+-	return __misc_deregister(misc, false);
+-}
+-static inline int misc_deregister_suspended(struct miscdevice *misc)
+-{
+-	return __misc_deregister(misc, true);
+-}
++extern int misc_deregister(struct miscdevice *misc);
+ 
+ #define MODULE_ALIAS_MISCDEV(minor)				\
+ 	MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR)	\
+diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
+index 7d1eaa9..77323a7 100644
+--- a/include/linux/mlx4/cmd.h
++++ b/include/linux/mlx4/cmd.h
+@@ -81,7 +81,7 @@ enum {
+ 	MLX4_CMD_SW2HW_CQ	 = 0x16,
+ 	MLX4_CMD_HW2SW_CQ	 = 0x17,
+ 	MLX4_CMD_QUERY_CQ	 = 0x18,
+-	MLX4_CMD_RESIZE_CQ	 = 0x2c,
++	MLX4_CMD_MODIFY_CQ	 = 0x2c,
+ 
+ 	/* SRQ commands */
+ 	MLX4_CMD_SW2HW_SRQ	 = 0x35,
+diff --git a/include/linux/mlx4/cq.h b/include/linux/mlx4/cq.h
+index 0181e0a..071cf96 100644
+--- a/include/linux/mlx4/cq.h
++++ b/include/linux/mlx4/cq.h
+@@ -45,11 +45,11 @@ struct mlx4_cqe {
+ 	u8			sl;
+ 	u8			reserved1;
+ 	__be16			rlid;
+-	u32			reserved2;
++	__be32			ipoib_status;
+ 	__be32			byte_cnt;
+ 	__be16			wqe_index;
+ 	__be16			checksum;
+-	u8			reserved3[3];
++	u8			reserved2[3];
+ 	u8			owner_sr_opcode;
+ };
+ 
+@@ -85,6 +85,16 @@ enum {
+ 	MLX4_CQE_SYNDROME_REMOTE_ABORTED_ERR		= 0x22,
+ };
+ 
++enum {
++	MLX4_CQE_IPOIB_STATUS_IPV4			= 1 << 22,
++	MLX4_CQE_IPOIB_STATUS_IPV4F			= 1 << 23,
++	MLX4_CQE_IPOIB_STATUS_IPV6			= 1 << 24,
++	MLX4_CQE_IPOIB_STATUS_IPV4OPT			= 1 << 25,
++	MLX4_CQE_IPOIB_STATUS_TCP			= 1 << 26,
++	MLX4_CQE_IPOIB_STATUS_UDP			= 1 << 27,
++	MLX4_CQE_IPOIB_STATUS_IPOK			= 1 << 28,
++};
++
+ static inline void mlx4_cq_arm(struct mlx4_cq *cq, u32 cmd,
+ 			       void __iomem *uar_page,
+ 			       spinlock_t *doorbell_lock)
+@@ -120,4 +130,9 @@ enum {
+ 	MLX4_CQ_DB_REQ_NOT		= 2 << 24
+ };
+ 
++int mlx4_cq_modify(struct mlx4_dev *dev, struct mlx4_cq *cq,
++		   u16 count, u16 period);
++int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
++		   int entries, struct mlx4_mtt *mtt);
++
+ #endif /* MLX4_CQ_H */
+diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
+index 6cdf813..ff7df1a 100644
+--- a/include/linux/mlx4/device.h
++++ b/include/linux/mlx4/device.h
+@@ -186,6 +186,7 @@ struct mlx4_caps {
+ 	u32			flags;
+ 	u16			stat_rate_support;
+ 	u8			port_width_cap[MLX4_MAX_PORTS + 1];
++	int			max_gso_sz;
+ };
+ 
+ struct mlx4_buf_list {
+diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h
+index 1b835ca..53c5fdb 100644
+--- a/include/linux/mlx4/driver.h
++++ b/include/linux/mlx4/driver.h
+@@ -48,8 +48,7 @@ struct mlx4_interface {
+ 	void *			(*add)	 (struct mlx4_dev *dev);
+ 	void			(*remove)(struct mlx4_dev *dev, void *context);
+ 	void			(*event) (struct mlx4_dev *dev, void *context,
+-					  enum mlx4_dev_event event, int subtype,
+-					  int port);
++					  enum mlx4_dev_event event, int port);
+ 	struct list_head	list;
+ };
+ 
+diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
+index 09a2230..a5e43fe 100644
+--- a/include/linux/mlx4/qp.h
++++ b/include/linux/mlx4/qp.h
+@@ -158,10 +158,12 @@ struct mlx4_qp_context {
+ #define MLX4_FW_VER_WQE_CTRL_NEC mlx4_fw_ver(2, 2, 232)
+ 
+ enum {
+-	MLX4_WQE_CTRL_NEC	= 1 << 29,
+-	MLX4_WQE_CTRL_FENCE	= 1 << 6,
+-	MLX4_WQE_CTRL_CQ_UPDATE	= 3 << 2,
+-	MLX4_WQE_CTRL_SOLICITED	= 1 << 1,
++	MLX4_WQE_CTRL_NEC		= 1 << 29,
++	MLX4_WQE_CTRL_FENCE		= 1 << 6,
++	MLX4_WQE_CTRL_CQ_UPDATE		= 3 << 2,
++	MLX4_WQE_CTRL_SOLICITED		= 1 << 1,
++	MLX4_WQE_CTRL_IP_CSUM		= 1 << 4,
++	MLX4_WQE_CTRL_TCP_UDP_CSUM	= 1 << 5,
+ };
+ 
+ struct mlx4_wqe_ctrl_seg {
+@@ -217,6 +219,11 @@ struct mlx4_wqe_datagram_seg {
+ 	__be32			reservd[2];
+ };
+ 
++struct mlx4_lso_seg {
++	__be32			mss_hdr_size;
++	__be32			header[0];
++};
++
+ struct mlx4_wqe_bind_seg {
+ 	__be32			flags1;
+ 	__be32			flags2;
+diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
+index 8d8d197..9f274a6 100644
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -699,7 +699,6 @@ extern char numa_zonelist_order[];
+ extern struct pglist_data contig_page_data;
+ #define NODE_DATA(nid)		(&contig_page_data)
+ #define NODE_MEM_MAP(nid)	mem_map
+-#define MAX_NODES_SHIFT		1
+ 
+ #else /* CONFIG_NEED_MULTIPLE_NODES */
+ 
+diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
+index 8eed44f..830bbcd 100644
+--- a/include/linux/mnt_namespace.h
++++ b/include/linux/mnt_namespace.h
+@@ -5,6 +5,7 @@
+ #include <linux/mount.h>
+ #include <linux/sched.h>
+ #include <linux/nsproxy.h>
++#include <linux/seq_file.h>
+ 
+ struct mnt_namespace {
+ 	atomic_t		count;
+@@ -14,6 +15,13 @@ struct mnt_namespace {
+ 	int event;
+ };
+ 
++struct proc_mounts {
++	struct seq_file m; /* must be the first element */
++	struct mnt_namespace *ns;
++	struct path root;
++	int event;
++};
++
+ extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
+ 		struct fs_struct *);
+ extern void __put_mnt_ns(struct mnt_namespace *ns);
+@@ -37,5 +45,9 @@ static inline void get_mnt_ns(struct mnt_namespace *ns)
+ 	atomic_inc(&ns->count);
+ }
+ 
++extern const struct seq_operations mounts_op;
++extern const struct seq_operations mountinfo_op;
++extern const struct seq_operations mountstats_op;
++
+ #endif
+ #endif
+diff --git a/include/linux/mount.h b/include/linux/mount.h
+index 5ee2df2..b4836d5 100644
+--- a/include/linux/mount.h
++++ b/include/linux/mount.h
+@@ -14,6 +14,7 @@
+ 
+ #include <linux/types.h>
+ #include <linux/list.h>
++#include <linux/nodemask.h>
+ #include <linux/spinlock.h>
+ #include <asm/atomic.h>
+ 
+@@ -28,8 +29,10 @@ struct mnt_namespace;
+ #define MNT_NOATIME	0x08
+ #define MNT_NODIRATIME	0x10
+ #define MNT_RELATIME	0x20
++#define MNT_READONLY	0x40	/* does the user want this to be r/o? */
+ 
+ #define MNT_SHRINKABLE	0x100
++#define MNT_IMBALANCED_WRITE_COUNT	0x200 /* just for debugging */
+ 
+ #define MNT_SHARED	0x1000	/* if the vfsmount is a shared mount */
+ #define MNT_UNBINDABLE	0x2000	/* if the vfsmount is a unbindable mount */
+@@ -53,6 +56,8 @@ struct vfsmount {
+ 	struct list_head mnt_slave;	/* slave list entry */
+ 	struct vfsmount *mnt_master;	/* slave is on master->mnt_slave_list */
+ 	struct mnt_namespace *mnt_ns;	/* containing namespace */
++	int mnt_id;			/* mount identifier */
++	int mnt_group_id;		/* peer group identifier */
+ 	/*
+ 	 * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
+ 	 * to let these frequently modified fields in a separate cache line
+@@ -62,6 +67,11 @@ struct vfsmount {
+ 	int mnt_expiry_mark;		/* true if marked for expiry */
+ 	int mnt_pinned;
+ 	int mnt_ghosts;
++	/*
++	 * This value is not stable unless all of the mnt_writers[] spinlocks
++	 * are held, and all mnt_writer[]s on this mount have 0 as their ->count
++	 */
++	atomic_t __mnt_writers;
+ };
+ 
+ static inline struct vfsmount *mntget(struct vfsmount *mnt)
+@@ -71,9 +81,12 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt)
+ 	return mnt;
+ }
+ 
++extern int mnt_want_write(struct vfsmount *mnt);
++extern void mnt_drop_write(struct vfsmount *mnt);
+ extern void mntput_no_expire(struct vfsmount *mnt);
+ extern void mnt_pin(struct vfsmount *mnt);
+ extern void mnt_unpin(struct vfsmount *mnt);
++extern int __mnt_is_readonly(struct vfsmount *mnt);
+ 
+ static inline void mntput(struct vfsmount *mnt)
+ {
+@@ -83,8 +96,6 @@ static inline void mntput(struct vfsmount *mnt)
+ 	}
+ }
+ 
+-extern void free_vfsmnt(struct vfsmount *mnt);
+-extern struct vfsmount *alloc_vfsmnt(const char *name);
+ extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
+ 				      const char *name, void *data);
+ 
+diff --git a/include/linux/mroute.h b/include/linux/mroute.h
+index 35a8277..de4decf 100644
+--- a/include/linux/mroute.h
++++ b/include/linux/mroute.h
+@@ -2,7 +2,11 @@
+ #define __LINUX_MROUTE_H
+ 
+ #include <linux/sockios.h>
++#include <linux/types.h>
++#ifdef __KERNEL__
+ #include <linux/in.h>
++#endif
++#include <linux/pim.h>
+ 
+ /*
+  *	Based on the MROUTING 3.5 defines primarily to keep
+@@ -210,27 +214,6 @@ struct mfc_cache
+ #define IGMPMSG_WHOLEPKT	3		/* For PIM Register processing */
+ 
+ #ifdef __KERNEL__
+-
+-#define PIM_V1_VERSION		__constant_htonl(0x10000000)
+-#define PIM_V1_REGISTER		1
+-
+-#define PIM_VERSION		2
+-#define PIM_REGISTER		1
+-
+-#define PIM_NULL_REGISTER	__constant_htonl(0x40000000)
+-
+-/* PIMv2 register message header layout (ietf-draft-idmr-pimvsm-v2-00.ps */
+-
+-struct pimreghdr
+-{
+-	__u8	type;
+-	__u8	reserved;
+-	__be16	csum;
+-	__be32	flags;
+-};
+-
+-extern int pim_rcv_v1(struct sk_buff *);
+-
+ struct rtmsg;
+ extern int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait);
+ #endif
+diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
+new file mode 100644
+index 0000000..e798959
+--- /dev/null
++++ b/include/linux/mroute6.h
+@@ -0,0 +1,228 @@
++#ifndef __LINUX_MROUTE6_H
++#define __LINUX_MROUTE6_H
++
++#include <linux/types.h>
++#include <linux/sockios.h>
++
++/*
++ *	Based on the MROUTING 3.5 defines primarily to keep
++ *	source compatibility with BSD.
++ *
++ *	See the pim6sd code for the original history.
++ *
++ *      Protocol Independent Multicast (PIM) data structures included
++ *      Carlos Picoto (cap at di.fc.ul.pt)
++ *
++ */
++
++#define MRT6_BASE	200
++#define MRT6_INIT	(MRT6_BASE)	/* Activate the kernel mroute code 	*/
++#define MRT6_DONE	(MRT6_BASE+1)	/* Shutdown the kernel mroute		*/
++#define MRT6_ADD_MIF	(MRT6_BASE+2)	/* Add a virtual interface		*/
++#define MRT6_DEL_MIF	(MRT6_BASE+3)	/* Delete a virtual interface		*/
++#define MRT6_ADD_MFC	(MRT6_BASE+4)	/* Add a multicast forwarding entry	*/
++#define MRT6_DEL_MFC	(MRT6_BASE+5)	/* Delete a multicast forwarding entry	*/
++#define MRT6_VERSION	(MRT6_BASE+6)	/* Get the kernel multicast version	*/
++#define MRT6_ASSERT	(MRT6_BASE+7)	/* Activate PIM assert mode		*/
++#define MRT6_PIM	(MRT6_BASE+8)	/* enable PIM code	*/
++
++#define SIOCGETMIFCNT_IN6	SIOCPROTOPRIVATE	/* IP protocol privates */
++#define SIOCGETSGCNT_IN6	(SIOCPROTOPRIVATE+1)
++#define SIOCGETRPF	(SIOCPROTOPRIVATE+2)
++
++#define MAXMIFS		32
++typedef unsigned long mifbitmap_t;	/* User mode code depends on this lot */
++typedef unsigned short mifi_t;
++#define ALL_MIFS	((mifi_t)(-1))
++
++#ifndef IF_SETSIZE
++#define IF_SETSIZE	256
++#endif
++
++typedef	__u32		if_mask;
++#define NIFBITS (sizeof(if_mask) * 8)        /* bits per mask */
++
++#if !defined(__KERNEL__) && !defined(DIV_ROUND_UP)
++#define	DIV_ROUND_UP(x,y)	(((x) + ((y) - 1)) / (y))
++#endif
++
++typedef struct if_set {
++	if_mask ifs_bits[DIV_ROUND_UP(IF_SETSIZE, NIFBITS)];
++} if_set;
++
++#define IF_SET(n, p)    ((p)->ifs_bits[(n)/NIFBITS] |= (1 << ((n) % NIFBITS)))
++#define IF_CLR(n, p)    ((p)->ifs_bits[(n)/NIFBITS] &= ~(1 << ((n) % NIFBITS)))
++#define IF_ISSET(n, p)  ((p)->ifs_bits[(n)/NIFBITS] & (1 << ((n) % NIFBITS)))
++#define IF_COPY(f, t)   bcopy(f, t, sizeof(*(f)))
++#define IF_ZERO(p)      bzero(p, sizeof(*(p)))
++
++/*
++ *	Passed by mrouted for an MRT_ADD_MIF - again we use the
++ *	mrouted 3.6 structures for compatibility
++ */
++
++struct mif6ctl {
++	mifi_t	mif6c_mifi;		/* Index of MIF */
++	unsigned char mif6c_flags;	/* MIFF_ flags */
++	unsigned char vifc_threshold;	/* ttl limit */
++	u_short	 mif6c_pifi;		/* the index of the physical IF */
++	unsigned int vifc_rate_limit;	/* Rate limiter values (NI) */
++};
++
++#define MIFF_REGISTER	0x1	/* register vif	*/
++
++/*
++ *	Cache manipulation structures for mrouted and PIMd
++ */
++
++struct mf6cctl
++{
++	struct sockaddr_in6 mf6cc_origin;		/* Origin of mcast	*/
++	struct sockaddr_in6 mf6cc_mcastgrp;		/* Group in question	*/
++	mifi_t	mf6cc_parent;			/* Where it arrived	*/
++	struct if_set mf6cc_ifset;		/* Where it is going */
++};
++
++/*
++ *	Group count retrieval for pim6sd
++ */
++
++struct sioc_sg_req6
++{
++	struct sockaddr_in6 src;
++	struct sockaddr_in6 grp;
++	unsigned long pktcnt;
++	unsigned long bytecnt;
++	unsigned long wrong_if;
++};
++
++/*
++ *	To get vif packet counts
++ */
++
++struct sioc_mif_req6
++{
++	mifi_t	mifi;		/* Which iface */
++	unsigned long icount;	/* In packets */
++	unsigned long ocount;	/* Out packets */
++	unsigned long ibytes;	/* In bytes */
++	unsigned long obytes;	/* Out bytes */
++};
++
++/*
++ *	That's all usermode folks
++ */
++
++#ifdef __KERNEL__
++
++#include <linux/skbuff.h>	/* for struct sk_buff_head */
++
++#ifdef CONFIG_IPV6_MROUTE
++static inline int ip6_mroute_opt(int opt)
++{
++	return (opt >= MRT6_BASE) && (opt <= MRT6_BASE + 10);
++}
++#else
++static inline int ip6_mroute_opt(int opt)
++{
++	return 0;
++}
++#endif
++
++struct sock;
++
++extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, int);
++extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
++extern int ip6_mr_input(struct sk_buff *skb);
++extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg);
++extern void ip6_mr_init(void);
++
++struct mif_device
++{
++	struct net_device 	*dev;			/* Device we are using */
++	unsigned long	bytes_in,bytes_out;
++	unsigned long	pkt_in,pkt_out;		/* Statistics 			*/
++	unsigned long	rate_limit;		/* Traffic shaping (NI) 	*/
++	unsigned char	threshold;		/* TTL threshold 		*/
++	unsigned short	flags;			/* Control flags 		*/
++	int		link;			/* Physical interface index	*/
++};
++
++#define VIFF_STATIC 0x8000
++
++struct mfc6_cache
++{
++	struct mfc6_cache *next;		/* Next entry on cache line 	*/
++	struct in6_addr mf6c_mcastgrp;			/* Group the entry belongs to 	*/
++	struct in6_addr mf6c_origin;			/* Source of packet 		*/
++	mifi_t mf6c_parent;			/* Source interface		*/
++	int mfc_flags;				/* Flags on line		*/
++
++	union {
++		struct {
++			unsigned long expires;
++			struct sk_buff_head unresolved;	/* Unresolved buffers		*/
++		} unres;
++		struct {
++			unsigned long last_assert;
++			int minvif;
++			int maxvif;
++			unsigned long bytes;
++			unsigned long pkt;
++			unsigned long wrong_if;
++			unsigned char ttls[MAXMIFS];	/* TTL thresholds		*/
++		} res;
++	} mfc_un;
++};
++
++#define MFC_STATIC		1
++#define MFC_NOTIFY		2
++
++#define MFC6_LINES		64
++
++#define MFC6_HASH(a, g) (((__force u32)(a)->s6_addr32[0] ^ \
++			  (__force u32)(a)->s6_addr32[1] ^ \
++			  (__force u32)(a)->s6_addr32[2] ^ \
++			  (__force u32)(a)->s6_addr32[3] ^ \
++			  (__force u32)(g)->s6_addr32[0] ^ \
++			  (__force u32)(g)->s6_addr32[1] ^ \
++			  (__force u32)(g)->s6_addr32[2] ^ \
++			  (__force u32)(g)->s6_addr32[3]) % MFC6_LINES)
++
++#define MFC_ASSERT_THRESH (3*HZ)		/* Maximal freq. of asserts */
++
++#endif
++
++#ifdef __KERNEL__
++struct rtmsg;
++extern int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait);
++
++#ifdef CONFIG_IPV6_MROUTE
++extern struct sock *mroute6_socket;
++extern int ip6mr_sk_done(struct sock *sk);
++#else
++#define mroute6_socket NULL
++static inline int ip6mr_sk_done(struct sock *sk) { return 0; }
++#endif
++#endif
++
++/*
++ * Structure used to communicate from kernel to multicast router.
++ * We'll overlay the structure onto an MLD header (not an IPv6 heder like igmpmsg{}
++ * used for IPv4 implementation). This is because this structure will be passed via an
++ * IPv6 raw socket, on wich an application will only receiver the payload i.e the data after
++ * the IPv6 header and all the extension headers. (See section 3 of RFC 3542)
++ */
++
++struct mrt6msg {
++#define MRT6MSG_NOCACHE		1
++#define MRT6MSG_WRONGMIF	2
++#define MRT6MSG_WHOLEPKT	3		/* used for use level encap */
++	__u8		im6_mbz;		/* must be zero		   */
++	__u8		im6_msgtype;		/* what type of message    */
++	__u16		im6_mif;		/* mif rec'd on		   */
++	__u32		im6_pad;		/* padding for 64 bit arch */
++	struct in6_addr	im6_src, im6_dst;
++};
++
++#endif
+diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h
+index 6977780..85fd041 100644
+--- a/include/linux/mtd/inftl.h
++++ b/include/linux/mtd/inftl.h
+@@ -57,6 +57,11 @@ extern char inftlmountrev[];
+ void INFTL_dumptables(struct INFTLrecord *s);
+ void INFTL_dumpVUchains(struct INFTLrecord *s);
+ 
++int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
++		   size_t *retlen, uint8_t *buf);
++int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
++		    size_t *retlen, uint8_t *buf);
++
+ #endif /* __KERNEL__ */
+ 
+ #endif /* __MTD_INFTL_H__ */
+diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h
+index bcf2fb3..001eec5 100644
+--- a/include/linux/mtd/nftl.h
++++ b/include/linux/mtd/nftl.h
+@@ -43,6 +43,11 @@ struct NFTLrecord {
+ int NFTL_mount(struct NFTLrecord *s);
+ int NFTL_formatblock(struct NFTLrecord *s, int block);
+ 
++int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
++		  size_t *retlen, uint8_t *buf);
++int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
++		   size_t *retlen, uint8_t *buf);
++
+ #ifndef NFTL_MAJOR
+ #define NFTL_MAJOR 93
+ #endif
+diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
+index fd0a260..9aa2a91 100644
+--- a/include/linux/mtd/onenand.h
++++ b/include/linux/mtd/onenand.h
+@@ -187,4 +187,7 @@ struct onenand_manufacturers {
+         char *name;
+ };
+ 
++int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
++			 struct mtd_oob_ops *ops);
++
+ #endif	/* __LINUX_MTD_ONENAND_H */
+diff --git a/include/linux/mtd/plat-ram.h b/include/linux/mtd/plat-ram.h
+index 9667863..0e37ad0 100644
+--- a/include/linux/mtd/plat-ram.h
++++ b/include/linux/mtd/plat-ram.h
+@@ -21,8 +21,9 @@
+ #define PLATRAM_RW (1)
+ 
+ struct platdata_mtd_ram {
+-	char			*mapname;
+-	char		       **probes;
++	const char		*mapname;
++	const char		**map_probes;
++	const char		**probes;
+ 	struct mtd_partition	*partitions;
+ 	int			 nr_partitions;
+ 	int			 bankwidth;
+diff --git a/include/linux/mtio.h b/include/linux/mtio.h
+index 6f8d2d4..ef01d6a 100644
+--- a/include/linux/mtio.h
++++ b/include/linux/mtio.h
+@@ -192,6 +192,7 @@ struct	mtpos {
+ #define MT_ST_SCSI2LOGICAL      0x800
+ #define MT_ST_SYSV              0x1000
+ #define MT_ST_NOWAIT            0x2000
++#define MT_ST_SILI		0x4000
+ 
+ /* The mode parameters to be controlled. Parameter chosen with bits 20-28 */
+ #define MT_ST_CLEAR_DEFAULT	0xfffff
+diff --git a/include/linux/net.h b/include/linux/net.h
+index c414d90..71f7dd5 100644
+--- a/include/linux/net.h
++++ b/include/linux/net.h
+@@ -19,6 +19,7 @@
+ #define _LINUX_NET_H
+ 
+ #include <linux/wait.h>
++#include <linux/socket.h>
+ #include <asm/socket.h>
+ 
+ struct poll_table_struct;
+@@ -26,7 +27,7 @@ struct pipe_inode_info;
+ struct inode;
+ struct net;
+ 
+-#define NPROTO		34		/* should be enough for now..	*/
++#define NPROTO		AF_MAX
+ 
+ #define SYS_SOCKET	1		/* sys_socket(2)		*/
+ #define SYS_BIND	2		/* sys_bind(2)			*/
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index ee81906..7c1d446 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -710,8 +710,10 @@ struct net_device
+ 	void                    (*poll_controller)(struct net_device *dev);
+ #endif
+ 
++#ifdef CONFIG_NET_NS
+ 	/* Network namespace this network device is inside */
+ 	struct net		*nd_net;
++#endif
+ 
+ 	/* bridge stuff */
+ 	struct net_bridge_port	*br_port;
+@@ -726,6 +728,10 @@ struct net_device
+ 	/* rtnetlink link ops */
+ 	const struct rtnl_link_ops *rtnl_link_ops;
+ 
++	/* for setting kernel sock attribute on TCP connection setup */
++#define GSO_MAX_SIZE		65536
++	unsigned int		gso_max_size;
++
+ 	/* The TX queue control structures */
+ 	unsigned int			egress_subqueue_count;
+ 	struct net_device_subqueue	egress_subqueue[1];
+@@ -735,6 +741,28 @@ struct net_device
+ #define	NETDEV_ALIGN		32
+ #define	NETDEV_ALIGN_CONST	(NETDEV_ALIGN - 1)
+ 
++/*
++ * Net namespace inlines
++ */
++static inline
++struct net *dev_net(const struct net_device *dev)
++{
++#ifdef CONFIG_NET_NS
++	return dev->nd_net;
++#else
++	return &init_net;
++#endif
++}
++
++static inline
++void dev_net_set(struct net_device *dev, struct net *net)
++{
++#ifdef CONFIG_NET_NS
++	release_net(dev->nd_net);
++	dev->nd_net = hold_net(net);
++#endif
++}
++
+ /**
+  *	netdev_priv - access network device private data
+  *	@dev: network device
+@@ -811,7 +839,7 @@ static inline struct net_device *next_net_device(struct net_device *dev)
+ 	struct list_head *lh;
+ 	struct net *net;
+ 
+-	net = dev->nd_net;
++	net = dev_net(dev);
+ 	lh = dev->dev_list.next;
+ 	return lh == &net->dev_base_head ? NULL : net_device_entry(lh);
+ }
+@@ -1479,6 +1507,12 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
+ 		unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
+ }
+ 
++static inline void netif_set_gso_max_size(struct net_device *dev,
++					  unsigned int size)
++{
++	dev->gso_max_size = size;
++}
++
+ /* On bonding slaves other than the currently active slave, suppress
+  * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
+  * ARP on active-backup slaves with arp_validate enabled.
+diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
+index f0680c2..e4c6659 100644
+--- a/include/linux/netfilter.h
++++ b/include/linux/netfilter.h
+@@ -6,11 +6,13 @@
+ #include <linux/types.h>
+ #include <linux/skbuff.h>
+ #include <linux/net.h>
++#include <linux/netdevice.h>
+ #include <linux/if.h>
+ #include <linux/in.h>
+ #include <linux/in6.h>
+ #include <linux/wait.h>
+ #include <linux/list.h>
++#include <net/net_namespace.h>
+ #endif
+ #include <linux/compiler.h>
+ 
+@@ -61,13 +63,21 @@ union nf_inet_addr {
+ #ifdef __KERNEL__
+ #ifdef CONFIG_NETFILTER
+ 
++static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1,
++				   const union nf_inet_addr *a2)
++{
++	return a1->all[0] == a2->all[0] &&
++	       a1->all[1] == a2->all[1] &&
++	       a1->all[2] == a2->all[2] &&
++	       a1->all[3] == a2->all[3];
++}
++
+ extern void netfilter_init(void);
+ 
+ /* Largest hook number + 1 */
+ #define NF_MAX_HOOKS 8
+ 
+ struct sk_buff;
+-struct net_device;
+ 
+ typedef unsigned int nf_hookfn(unsigned int hooknum,
+ 			       struct sk_buff *skb,
+@@ -224,6 +234,11 @@ struct nf_afinfo {
+ 	unsigned short	family;
+ 	__sum16		(*checksum)(struct sk_buff *skb, unsigned int hook,
+ 				    unsigned int dataoff, u_int8_t protocol);
++	__sum16		(*checksum_partial)(struct sk_buff *skb,
++					    unsigned int hook,
++					    unsigned int dataoff,
++					    unsigned int len,
++					    u_int8_t protocol);
+ 	int		(*route)(struct dst_entry **dst, struct flowi *fl);
+ 	void		(*saveroute)(const struct sk_buff *skb,
+ 				     struct nf_queue_entry *entry);
+@@ -253,6 +268,23 @@ nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff,
+ 	return csum;
+ }
+ 
++static inline __sum16
++nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
++		    unsigned int dataoff, unsigned int len,
++		    u_int8_t protocol, unsigned short family)
++{
++	const struct nf_afinfo *afinfo;
++	__sum16 csum = 0;
++
++	rcu_read_lock();
++	afinfo = nf_get_afinfo(family);
++	if (afinfo)
++		csum = afinfo->checksum_partial(skb, hook, dataoff, len,
++						protocol);
++	rcu_read_unlock();
++	return csum;
++}
++
+ extern int nf_register_afinfo(const struct nf_afinfo *afinfo);
+ extern void nf_unregister_afinfo(const struct nf_afinfo *afinfo);
+ 
+@@ -311,5 +343,56 @@ extern void (*nf_ct_destroy)(struct nf_conntrack *);
+ static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
+ #endif
+ 
++static inline struct net *nf_pre_routing_net(const struct net_device *in,
++					     const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++	return in->nd_net;
++#else
++	return &init_net;
++#endif
++}
++
++static inline struct net *nf_local_in_net(const struct net_device *in,
++					  const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++	return in->nd_net;
++#else
++	return &init_net;
++#endif
++}
++
++static inline struct net *nf_forward_net(const struct net_device *in,
++					 const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++	BUG_ON(in->nd_net != out->nd_net);
++	return in->nd_net;
++#else
++	return &init_net;
++#endif
++}
++
++static inline struct net *nf_local_out_net(const struct net_device *in,
++					   const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++	return out->nd_net;
++#else
++	return &init_net;
++#endif
++}
++
++static inline struct net *nf_post_routing_net(const struct net_device *in,
++					      const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++	return out->nd_net;
++#else
++	return &init_net;
++#endif
++}
++
+ #endif /*__KERNEL__*/
+ #endif /*__LINUX_NETFILTER_H*/
+diff --git a/include/linux/netfilter/nf_conntrack_dccp.h b/include/linux/netfilter/nf_conntrack_dccp.h
+new file mode 100644
+index 0000000..40dcc82
+--- /dev/null
++++ b/include/linux/netfilter/nf_conntrack_dccp.h
+@@ -0,0 +1,40 @@
++#ifndef _NF_CONNTRACK_DCCP_H
++#define _NF_CONNTRACK_DCCP_H
++
++/* Exposed to userspace over nfnetlink */
++enum ct_dccp_states {
++	CT_DCCP_NONE,
++	CT_DCCP_REQUEST,
++	CT_DCCP_RESPOND,
++	CT_DCCP_PARTOPEN,
++	CT_DCCP_OPEN,
++	CT_DCCP_CLOSEREQ,
++	CT_DCCP_CLOSING,
++	CT_DCCP_TIMEWAIT,
++	CT_DCCP_IGNORE,
++	CT_DCCP_INVALID,
++	__CT_DCCP_MAX
++};
++#define CT_DCCP_MAX		(__CT_DCCP_MAX - 1)
++
++enum ct_dccp_roles {
++	CT_DCCP_ROLE_CLIENT,
++	CT_DCCP_ROLE_SERVER,
++	__CT_DCCP_ROLE_MAX
++};
++#define CT_DCCP_ROLE_MAX	(__CT_DCCP_ROLE_MAX - 1)
++
++#ifdef __KERNEL__
++#include <net/netfilter/nf_conntrack_tuple.h>
++
++struct nf_ct_dccp {
++	u_int8_t	role[IP_CT_DIR_MAX];
++	u_int8_t	state;
++	u_int8_t	last_pkt;
++	u_int8_t	last_dir;
++	u_int64_t	handshake_seq;
++};
++
++#endif /* __KERNEL__ */
++
++#endif /* _NF_CONNTRACK_DCCP_H */
+diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
+index 8e5ce1c..5da04e5 100644
+--- a/include/linux/netfilter/nf_conntrack_sip.h
++++ b/include/linux/netfilter/nf_conntrack_sip.h
+@@ -5,37 +5,164 @@
+ #define SIP_PORT	5060
+ #define SIP_TIMEOUT	3600
+ 
+-enum sip_header_pos {
+-	POS_REG_REQ_URI,
+-	POS_REQ_URI,
+-	POS_FROM,
+-	POS_TO,
+-	POS_VIA,
+-	POS_CONTACT,
+-	POS_CONTENT,
+-	POS_MEDIA,
+-	POS_OWNER_IP4,
+-	POS_CONNECTION_IP4,
+-	POS_OWNER_IP6,
+-	POS_CONNECTION_IP6,
+-	POS_SDP_HEADER,
++struct nf_ct_sip_master {
++	unsigned int	register_cseq;
++};
++
++enum sip_expectation_classes {
++	SIP_EXPECT_SIGNALLING,
++	SIP_EXPECT_AUDIO,
++	SIP_EXPECT_VIDEO,
++	__SIP_EXPECT_MAX
++};
++#define SIP_EXPECT_MAX	(__SIP_EXPECT_MAX - 1)
++
++struct sdp_media_type {
++	const char			*name;
++	unsigned int			len;
++	enum sip_expectation_classes	class;
++};
++
++#define SDP_MEDIA_TYPE(__name, __class)					\
++{									\
++	.name	= (__name),						\
++	.len	= sizeof(__name) - 1,					\
++	.class	= (__class),						\
++}
++
++struct sip_handler {
++	const char	*method;
++	unsigned int	len;
++	int		(*request)(struct sk_buff *skb,
++				   const char **dptr, unsigned int *datalen,
++				   unsigned int cseq);
++	int		(*response)(struct sk_buff *skb,
++				    const char **dptr, unsigned int *datalen,
++				    unsigned int cseq, unsigned int code);
++};
++
++#define SIP_HANDLER(__method, __request, __response)			\
++{									\
++	.method		= (__method),					\
++	.len		= sizeof(__method) - 1,				\
++	.request	= (__request),					\
++	.response	= (__response),					\
++}
++
++struct sip_header {
++	const char	*name;
++	const char	*cname;
++	const char	*search;
++	unsigned int	len;
++	unsigned int	clen;
++	unsigned int	slen;
++	int		(*match_len)(const struct nf_conn *ct,
++				     const char *dptr, const char *limit,
++				     int *shift);
++};
++
++#define __SIP_HDR(__name, __cname, __search, __match)			\
++{									\
++	.name		= (__name),					\
++	.len		= sizeof(__name) - 1,				\
++	.cname		= (__cname),					\
++	.clen		= (__cname) ? sizeof(__cname) - 1 : 0,		\
++	.search		= (__search),					\
++	.slen		= (__search) ? sizeof(__search) - 1 : 0,	\
++	.match_len	= (__match),					\
++}
++
++#define SIP_HDR(__name, __cname, __search, __match) \
++	__SIP_HDR(__name, __cname, __search, __match)
++
++#define SDP_HDR(__name, __search, __match) \
++	__SIP_HDR(__name, NULL, __search, __match)
++
++enum sip_header_types {
++	SIP_HDR_CSEQ,
++	SIP_HDR_FROM,
++	SIP_HDR_TO,
++	SIP_HDR_CONTACT,
++	SIP_HDR_VIA,
++	SIP_HDR_EXPIRES,
++	SIP_HDR_CONTENT_LENGTH,
++};
++
++enum sdp_header_types {
++	SDP_HDR_UNSPEC,
++	SDP_HDR_VERSION,
++	SDP_HDR_OWNER_IP4,
++	SDP_HDR_CONNECTION_IP4,
++	SDP_HDR_OWNER_IP6,
++	SDP_HDR_CONNECTION_IP6,
++	SDP_HDR_MEDIA,
+ };
+ 
+ extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
+-				       enum ip_conntrack_info ctinfo,
+-				       struct nf_conn *ct,
+-				       const char **dptr);
+-extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
+-				       enum ip_conntrack_info ctinfo,
+-				       struct nf_conntrack_expect *exp,
+-				       const char *dptr);
+-
+-extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
+-                           size_t dlen, unsigned int *matchoff,
+-                           unsigned int *matchlen, enum sip_header_pos pos);
+-extern int ct_sip_lnlen(const char *line, const char *limit);
+-extern const char *ct_sip_search(const char *needle, const char *haystack,
+-				 size_t needle_len, size_t haystack_len,
+-				 int case_sensitive);
++				       const char **dptr,
++				       unsigned int *datalen);
++extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
++					      const char **dptr,
++					      unsigned int *datalen,
++					      struct nf_conntrack_expect *exp,
++					      unsigned int matchoff,
++					      unsigned int matchlen);
++extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
++					    const char **dptr,
++					    unsigned int dataoff,
++					    unsigned int *datalen,
++					    enum sdp_header_types type,
++					    enum sdp_header_types term,
++					    const union nf_inet_addr *addr);
++extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
++					    const char **dptr,
++					    unsigned int *datalen,
++					    unsigned int matchoff,
++					    unsigned int matchlen,
++					    u_int16_t port);
++extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
++					       const char **dptr,
++					       unsigned int dataoff,
++					       unsigned int *datalen,
++					       const union nf_inet_addr *addr);
++extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
++					     const char **dptr,
++					     unsigned int *datalen,
++					     struct nf_conntrack_expect *rtp_exp,
++					     struct nf_conntrack_expect *rtcp_exp,
++					     unsigned int mediaoff,
++					     unsigned int medialen,
++					     union nf_inet_addr *rtp_addr);
++
++extern int ct_sip_parse_request(const struct nf_conn *ct,
++				const char *dptr, unsigned int datalen,
++				unsigned int *matchoff, unsigned int *matchlen,
++				union nf_inet_addr *addr, __be16 *port);
++extern int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
++			     unsigned int dataoff, unsigned int datalen,
++			     enum sip_header_types type,
++			     unsigned int *matchoff, unsigned int *matchlen);
++extern int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
++				   unsigned int *dataoff, unsigned int datalen,
++				   enum sip_header_types type, int *in_header,
++				   unsigned int *matchoff, unsigned int *matchlen,
++				   union nf_inet_addr *addr, __be16 *port);
++extern int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,
++				      unsigned int dataoff, unsigned int datalen,
++				      const char *name,
++				      unsigned int *matchoff, unsigned int *matchlen,
++				      union nf_inet_addr *addr);
++extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,
++					unsigned int off, unsigned int datalen,
++					const char *name,
++					unsigned int *matchoff, unsigned int *matchen,
++					unsigned int *val);
++
++extern int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
++				 unsigned int dataoff, unsigned int datalen,
++				 enum sdp_header_types type,
++				 enum sdp_header_types term,
++				 unsigned int *matchoff, unsigned int *matchlen);
++
+ #endif /* __KERNEL__ */
+ #endif /* __NF_CONNTRACK_SIP_H__ */
+diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
+index e3e1533..0a383ac 100644
+--- a/include/linux/netfilter/nfnetlink_conntrack.h
++++ b/include/linux/netfilter/nfnetlink_conntrack.h
+@@ -80,6 +80,7 @@ enum ctattr_l4proto {
+ enum ctattr_protoinfo {
+ 	CTA_PROTOINFO_UNSPEC,
+ 	CTA_PROTOINFO_TCP,
++	CTA_PROTOINFO_DCCP,
+ 	__CTA_PROTOINFO_MAX
+ };
+ #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
+@@ -95,6 +96,13 @@ enum ctattr_protoinfo_tcp {
+ };
+ #define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
+ 
++enum ctattr_protoinfo_dccp {
++	CTA_PROTOINFO_DCCP_UNSPEC,
++	CTA_PROTOINFO_DCCP_STATE,
++	__CTA_PROTOINFO_DCCP_MAX,
++};
++#define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1)
++
+ enum ctattr_counters {
+ 	CTA_COUNTERS_UNSPEC,
+ 	CTA_COUNTERS_PACKETS,		/* old 64bit counters */
+diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
+index b2c62cc..2326296 100644
+--- a/include/linux/netfilter/x_tables.h
++++ b/include/linux/netfilter/x_tables.h
+@@ -430,13 +430,13 @@ extern int xt_compat_add_offset(int af, unsigned int offset, short delta);
+ extern void xt_compat_flush_offsets(int af);
+ extern short xt_compat_calc_jump(int af, unsigned int offset);
+ 
+-extern int xt_compat_match_offset(struct xt_match *match);
++extern int xt_compat_match_offset(const struct xt_match *match);
+ extern int xt_compat_match_from_user(struct xt_entry_match *m,
+ 				     void **dstptr, unsigned int *size);
+ extern int xt_compat_match_to_user(struct xt_entry_match *m,
+ 				   void __user **dstptr, unsigned int *size);
+ 
+-extern int xt_compat_target_offset(struct xt_target *target);
++extern int xt_compat_target_offset(const struct xt_target *target);
+ extern void xt_compat_target_from_user(struct xt_entry_target *t,
+ 				       void **dstptr, unsigned int *size);
+ extern int xt_compat_target_to_user(struct xt_entry_target *t,
+diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h
+index dd5a4fd..32000ba 100644
+--- a/include/linux/netfilter/xt_sctp.h
++++ b/include/linux/netfilter/xt_sctp.h
+@@ -37,68 +37,54 @@ struct xt_sctp_info {
+ 
+ #define SCTP_CHUNKMAP_SET(chunkmap, type) 		\
+ 	do { 						\
+-		chunkmap[type / bytes(u_int32_t)] |= 	\
++		(chunkmap)[type / bytes(u_int32_t)] |= 	\
+ 			1 << (type % bytes(u_int32_t));	\
+ 	} while (0)
+ 
+ #define SCTP_CHUNKMAP_CLEAR(chunkmap, type)		 	\
+ 	do {							\
+-		chunkmap[type / bytes(u_int32_t)] &= 		\
++		(chunkmap)[type / bytes(u_int32_t)] &= 		\
+ 			~(1 << (type % bytes(u_int32_t)));	\
+ 	} while (0)
+ 
+ #define SCTP_CHUNKMAP_IS_SET(chunkmap, type) 			\
+ ({								\
+-	(chunkmap[type / bytes (u_int32_t)] & 			\
++	((chunkmap)[type / bytes (u_int32_t)] & 		\
+ 		(1 << (type % bytes (u_int32_t)))) ? 1: 0;	\
+ })
+ 
+-#define SCTP_CHUNKMAP_RESET(chunkmap) 				\
+-	do {							\
+-		int i; 						\
+-		for (i = 0; i < ARRAY_SIZE(chunkmap); i++)	\
+-			chunkmap[i] = 0;			\
+-	} while (0)
+-
+-#define SCTP_CHUNKMAP_SET_ALL(chunkmap) 			\
+-	do {							\
+-		int i; 						\
+-		for (i = 0; i < ARRAY_SIZE(chunkmap); i++) 	\
+-			chunkmap[i] = ~0;			\
+-	} while (0)
+-
+-#define SCTP_CHUNKMAP_COPY(destmap, srcmap) 			\
+-	do {							\
+-		int i; 						\
+-		for (i = 0; i < ARRAY_SIZE(srcmap); i++) 	\
+-			destmap[i] = srcmap[i];			\
+-	} while (0)
+-
+-#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) 		\
+-({							\
+-	int i; 						\
+-	int flag = 1;					\
+-	for (i = 0; i < ARRAY_SIZE(chunkmap); i++) {	\
+-		if (chunkmap[i]) {			\
+-			flag = 0;			\
+-			break;				\
+-		}					\
+-	}						\
+-        flag;						\
+-})
+-
+-#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) 		\
+-({							\
+-	int i; 						\
+-	int flag = 1;					\
+-	for (i = 0; i < ARRAY_SIZE(chunkmap); i++) {	\
+-		if (chunkmap[i] != ~0) {		\
+-			flag = 0;			\
+-				break;			\
+-		}					\
+-	}						\
+-        flag;						\
+-})
++#define SCTP_CHUNKMAP_RESET(chunkmap) \
++	memset((chunkmap), 0, sizeof(chunkmap))
++
++#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
++	memset((chunkmap), ~0U, sizeof(chunkmap))
++
++#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
++	memcpy((destmap), (srcmap), sizeof(srcmap))
++
++#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
++	__sctp_chunkmap_is_clear((chunkmap), ARRAY_SIZE(chunkmap))
++static inline bool
++__sctp_chunkmap_is_clear(const u_int32_t *chunkmap, unsigned int n)
++{
++	unsigned int i;
++	for (i = 0; i < n; ++i)
++		if (chunkmap[i])
++			return false;
++	return true;
++}
++
++#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
++	__sctp_chunkmap_is_all_set((chunkmap), ARRAY_SIZE(chunkmap))
++static inline bool
++__sctp_chunkmap_is_all_set(const u_int32_t *chunkmap, unsigned int n)
++{
++	unsigned int i;
++	for (i = 0; i < n; ++i)
++		if (chunkmap[i] != ~0U)
++			return false;
++	return true;
++}
+ 
+ #endif /* _XT_SCTP_H_ */
+ 
+diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
+index db223ca..dd9c97f 100644
+--- a/include/linux/netfilter_arp/arp_tables.h
++++ b/include/linux/netfilter_arp/arp_tables.h
+@@ -23,8 +23,6 @@
+ 
+ #define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+ #define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
+-#define arpt_target xt_target
+-#define arpt_table xt_table
+ 
+ #define ARPT_DEV_ADDR_LEN_MAX 16
+ 
+@@ -266,20 +264,15 @@ struct arpt_error
+ 	.target.errorname = "ERROR",					       \
+ }
+ 
+-#define arpt_register_target(tgt) 	\
+-({	(tgt)->family = NF_ARP;		\
+- 	xt_register_target(tgt); })
+-#define arpt_unregister_target(tgt) xt_unregister_target(tgt)
+-
+-extern struct arpt_table *arpt_register_table(struct net *net,
+-					      struct arpt_table *table,
+-					      const struct arpt_replace *repl);
+-extern void arpt_unregister_table(struct arpt_table *table);
++extern struct xt_table *arpt_register_table(struct net *net,
++					    struct xt_table *table,
++					    const struct arpt_replace *repl);
++extern void arpt_unregister_table(struct xt_table *table);
+ extern unsigned int arpt_do_table(struct sk_buff *skb,
+ 				  unsigned int hook,
+ 				  const struct net_device *in,
+ 				  const struct net_device *out,
+-				  struct arpt_table *table);
++				  struct xt_table *table);
+ 
+ #define ARPT_ALIGN(s) XT_ALIGN(s)
+ 
+diff --git a/include/linux/netfilter_bridge/ebt_nflog.h b/include/linux/netfilter_bridge/ebt_nflog.h
+new file mode 100644
+index 0000000..0528178
+--- /dev/null
++++ b/include/linux/netfilter_bridge/ebt_nflog.h
+@@ -0,0 +1,21 @@
++#ifndef __LINUX_BRIDGE_EBT_NFLOG_H
++#define __LINUX_BRIDGE_EBT_NFLOG_H
++
++#define EBT_NFLOG_MASK 0x0
++
++#define EBT_NFLOG_PREFIX_SIZE 64
++#define EBT_NFLOG_WATCHER "nflog"
++
++#define EBT_NFLOG_DEFAULT_GROUP		0x1
++#define EBT_NFLOG_DEFAULT_THRESHOLD	1
++
++struct ebt_nflog_info {
++	u_int32_t len;
++	u_int16_t group;
++	u_int16_t threshold;
++	u_int16_t flags;
++	u_int16_t pad;
++	char prefix[EBT_NFLOG_PREFIX_SIZE];
++};
++
++#endif				/* __LINUX_BRIDGE_EBT_NFLOG_H */
+diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
+index 9a10092..650318b 100644
+--- a/include/linux/netfilter_ipv4.h
++++ b/include/linux/netfilter_ipv4.h
+@@ -62,8 +62,6 @@ enum nf_ip_hook_priorities {
+ 	NF_IP_PRI_FILTER = 0,
+ 	NF_IP_PRI_NAT_SRC = 100,
+ 	NF_IP_PRI_SELINUX_LAST = 225,
+-	NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2,
+-	NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1,
+ 	NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
+ 	NF_IP_PRI_LAST = INT_MAX,
+ };
+diff --git a/include/linux/nfs3.h b/include/linux/nfs3.h
+index 7f11fa5..539f3b5 100644
+--- a/include/linux/nfs3.h
++++ b/include/linux/nfs3.h
+@@ -96,7 +96,7 @@ struct nfs3_fh {
+ #define MOUNTPROC3_UMNTALL	4
+  
+ 
+-#if defined(__KERNEL__) || defined(NFS_NEED_KERNEL_TYPES)
++#if defined(__KERNEL__)
+ 
+ /* Number of 32bit words in post_op_attr */
+ #define NFS3_POST_OP_ATTR_WORDS		22
+diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
+index f4a0e4c..27d6a8d 100644
+--- a/include/linux/nfs_fs.h
++++ b/include/linux/nfs_fs.h
+@@ -430,7 +430,6 @@ extern void nfs_unregister_sysctl(void);
+ /*
+  * linux/fs/nfs/namespace.c
+  */
+-extern struct list_head nfs_automount_list;
+ extern const struct inode_operations nfs_mountpoint_inode_operations;
+ extern const struct inode_operations nfs_referral_inode_operations;
+ extern int nfs_mountpoint_expiry_timeout;
+@@ -466,9 +465,9 @@ extern int nfs_wb_page(struct inode *inode, struct page* page);
+ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
+ #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+ extern int  nfs_commit_inode(struct inode *, int);
+-extern struct nfs_write_data *nfs_commit_alloc(void);
++extern struct nfs_write_data *nfs_commitdata_alloc(void);
+ extern void nfs_commit_free(struct nfs_write_data *wdata);
+-extern void nfs_commit_release(void *wdata);
++extern void nfs_commitdata_release(void *wdata);
+ #else
+ static inline int
+ nfs_commit_inode(struct inode *inode, int how)
+diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
+index 3423c67..c9beacd 100644
+--- a/include/linux/nfs_fs_sb.h
++++ b/include/linux/nfs_fs_sb.h
+@@ -32,6 +32,8 @@ struct nfs_client {
+ 	const struct nfs_rpc_ops *rpc_ops;	/* NFS protocol vector */
+ 	int			cl_proto;	/* Network transport protocol */
+ 
++	struct rpc_cred		*cl_machine_cred;
++
+ #ifdef CONFIG_NFS_V4
+ 	u64			cl_clientid;	/* constant */
+ 	nfs4_verifier		cl_confirm;
+@@ -93,6 +95,7 @@ struct nfs_server {
+ 	unsigned int		wpages;		/* write size (in pages) */
+ 	unsigned int		wtmult;		/* server disk block size */
+ 	unsigned int		dtsize;		/* readdir size */
++	unsigned short		port;		/* "port=" setting */
+ 	unsigned int		bsize;		/* server block size */
+ 	unsigned int		acregmin;	/* attr cache timeouts */
+ 	unsigned int		acregmax;
+@@ -117,6 +120,13 @@ struct nfs_server {
+ 
+ 	atomic_t active; /* Keep trace of any activity to this server */
+ 	wait_queue_head_t active_wq;  /* Wait for any activity to stop  */
++
++	/* mountd-related mount options */
++	struct sockaddr_storage	mountd_address;
++	size_t			mountd_addrlen;
++	u32			mountd_version;
++	unsigned short		mountd_port;
++	unsigned short		mountd_protocol;
+ };
+ 
+ /* Server capabilities */
+diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
+index f301d0b..24263bb 100644
+--- a/include/linux/nfs_xdr.h
++++ b/include/linux/nfs_xdr.h
+@@ -140,6 +140,7 @@ struct nfs_openres {
+ 	__u32                   rflags;
+ 	struct nfs_fattr *      f_attr;
+ 	struct nfs_fattr *      dir_attr;
++	struct nfs_seqid *	seqid;
+ 	const struct nfs_server *server;
+ 	int			delegation_type;
+ 	nfs4_stateid		delegation;
+@@ -159,6 +160,7 @@ struct nfs_open_confirmargs {
+ 
+ struct nfs_open_confirmres {
+ 	nfs4_stateid            stateid;
++	struct nfs_seqid *	seqid;
+ };
+ 
+ /*
+@@ -175,6 +177,7 @@ struct nfs_closeargs {
+ struct nfs_closeres {
+ 	nfs4_stateid            stateid;
+ 	struct nfs_fattr *	fattr;
++	struct nfs_seqid *	seqid;
+ 	const struct nfs_server *server;
+ };
+ /*
+@@ -199,7 +202,9 @@ struct nfs_lock_args {
+ };
+ 
+ struct nfs_lock_res {
+-	nfs4_stateid			stateid;
++	nfs4_stateid		stateid;
++	struct nfs_seqid *	lock_seqid;
++	struct nfs_seqid *	open_seqid;
+ };
+ 
+ struct nfs_locku_args {
+@@ -210,7 +215,8 @@ struct nfs_locku_args {
+ };
+ 
+ struct nfs_locku_res {
+-	nfs4_stateid			stateid;
++	nfs4_stateid		stateid;
++	struct nfs_seqid *	seqid;
+ };
+ 
+ struct nfs_lockt_args {
+diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild
+index e726fc3..fc97204 100644
+--- a/include/linux/nfsd/Kbuild
++++ b/include/linux/nfsd/Kbuild
+@@ -1,6 +1,6 @@
+ unifdef-y += const.h
++unifdef-y += debug.h
+ unifdef-y += export.h
++unifdef-y += nfsfh.h
+ unifdef-y += stats.h
+ unifdef-y += syscall.h
+-unifdef-y += nfsfh.h
+-unifdef-y += debug.h
+diff --git a/include/linux/nfsd/cache.h b/include/linux/nfsd/cache.h
+index 7b5d784..04b355c 100644
+--- a/include/linux/nfsd/cache.h
++++ b/include/linux/nfsd/cache.h
+@@ -10,7 +10,6 @@
+ #ifndef NFSCACHE_H
+ #define NFSCACHE_H
+ 
+-#ifdef __KERNEL__
+ #include <linux/in.h>
+ #include <linux/uio.h>
+ 
+@@ -77,5 +76,4 @@ void	nfsd_reply_cache_shutdown(void);
+ int	nfsd_cache_lookup(struct svc_rqst *, int);
+ void	nfsd_cache_update(struct svc_rqst *, int, __be32 *);
+ 
+-#endif /* __KERNEL__ */
+ #endif /* NFSCACHE_H */
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 8caf4c4..41d30c9 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -27,7 +27,6 @@
+ #define NFSD_VERSION		"0.5"
+ #define NFSD_SUPPORTED_MINOR_VERSION	0
+ 
+-#ifdef __KERNEL__
+ /*
+  * Special flags for nfsd_permission. These must be different from MAY_READ,
+  * MAY_WRITE, and MAY_EXEC.
+@@ -56,12 +55,20 @@ extern struct svc_program	nfsd_program;
+ extern struct svc_version	nfsd_version2, nfsd_version3,
+ 				nfsd_version4;
+ extern struct svc_serv		*nfsd_serv;
++
++extern struct seq_operations nfs_exports_op;
++
+ /*
+  * Function prototypes.
+  */
+ int		nfsd_svc(unsigned short port, int nrservs);
+ int		nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
+ 
++int		nfsd_nrthreads(void);
++int		nfsd_nrpools(void);
++int		nfsd_get_nrthreads(int n, int *);
++int		nfsd_set_nrthreads(int n, int *);
++
+ /* nfsd/vfs.c */
+ int		fh_lock_parent(struct svc_fh *, struct dentry *);
+ int		nfsd_racache_init(int);
+@@ -322,10 +329,8 @@ extern struct timeval	nfssvc_boot;
+ (FATTR4_WORD0_SIZE              | FATTR4_WORD0_ACL                                         )
+ #define NFSD_WRITEABLE_ATTRS_WORD1                                                          \
+ (FATTR4_WORD1_MODE              | FATTR4_WORD1_OWNER         | FATTR4_WORD1_OWNER_GROUP     \
+- | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY_SET)
++ | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
+ 
+ #endif /* CONFIG_NFSD_V4 */
+ 
+-#endif /* __KERNEL__ */
+-
+ #endif /* LINUX_NFSD_NFSD_H */
+diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
+index 9fecf90..ea6517e 100644
+--- a/include/linux/nl80211.h
++++ b/include/linux/nl80211.h
+@@ -78,6 +78,18 @@
+  *	or, if no MAC address given, all stations, on the interface identified
+  *	by %NL80211_ATTR_IFINDEX.
+  *
++ * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
++ * 	destination %NL80211_ATTR_MAC on the interface identified by
++ * 	%NL80211_ATTR_IFINDEX.
++ * @NL80211_CMD_SET_MPATH:  Set mesh path attributes for mesh path to
++ * 	destination %NL80211_ATTR_MAC on the interface identified by
++ * 	%NL80211_ATTR_IFINDEX.
++ * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the
++ *	the interface identified by %NL80211_ATTR_IFINDEX.
++ * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
++ *	or, if no MAC address given, all mesh paths, on the interface identified
++ *	by %NL80211_ATTR_IFINDEX.
++ *
+  * @NL80211_CMD_MAX: highest used command number
+  * @__NL80211_CMD_AFTER_LAST: internal use
+  */
+@@ -112,6 +124,11 @@ enum nl80211_commands {
+ 
+ 	/* add commands here */
+ 
++	NL80211_CMD_GET_MPATH,
++	NL80211_CMD_SET_MPATH,
++	NL80211_CMD_NEW_MPATH,
++	NL80211_CMD_DEL_MPATH,
++
+ 	/* used to define NL80211_CMD_MAX below */
+ 	__NL80211_CMD_AFTER_LAST,
+ 	NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
+@@ -157,9 +174,23 @@ enum nl80211_commands {
+  *	restriction (at most %NL80211_MAX_SUPP_RATES).
+  * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
+  *	to, or the AP interface the station was originally added to to.
+- * @NL80211_ATTR_STA_STATS: statistics for a station, part of station info
++ * @NL80211_ATTR_STA_INFO: information about a station, part of station info
+  *	given for %NL80211_CMD_GET_STATION, nested attribute containing
+- *	info as possible, see &enum nl80211_sta_stats.
++ *	info as possible, see &enum nl80211_sta_info.
++ *
++ * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands,
++ *	consisting of a nested array.
++ *
++ * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
++ * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link.
++ * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
++ * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
++ * 	info given for %NL80211_CMD_GET_MPATH, nested attribute described at
++ *	&enum nl80211_mpath_info.
++ *
++ *
++ * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
++ *      &enum nl80211_mntr_flags.
+  *
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -193,10 +224,19 @@ enum nl80211_attrs {
+ 	NL80211_ATTR_STA_LISTEN_INTERVAL,
+ 	NL80211_ATTR_STA_SUPPORTED_RATES,
+ 	NL80211_ATTR_STA_VLAN,
+-	NL80211_ATTR_STA_STATS,
++	NL80211_ATTR_STA_INFO,
++
++	NL80211_ATTR_WIPHY_BANDS,
++
++	NL80211_ATTR_MNTR_FLAGS,
+ 
+ 	/* add attributes here, update the policy in nl80211.c */
+ 
++	NL80211_ATTR_MESH_ID,
++	NL80211_ATTR_STA_PLINK_ACTION,
++	NL80211_ATTR_MPATH_NEXT_HOP,
++	NL80211_ATTR_MPATH_INFO,
++
+ 	__NL80211_ATTR_AFTER_LAST,
+ 	NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
+ };
+@@ -213,6 +253,7 @@ enum nl80211_attrs {
+  * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points
+  * @NL80211_IFTYPE_WDS: wireless distribution interface
+  * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
++ * @NL80211_IFTYPE_MESH_POINT: mesh point
+  * @NL80211_IFTYPE_MAX: highest interface type number currently defined
+  * @__NL80211_IFTYPE_AFTER_LAST: internal use
+  *
+@@ -228,6 +269,7 @@ enum nl80211_iftype {
+ 	NL80211_IFTYPE_AP_VLAN,
+ 	NL80211_IFTYPE_WDS,
+ 	NL80211_IFTYPE_MONITOR,
++	NL80211_IFTYPE_MESH_POINT,
+ 
+ 	/* keep last */
+ 	__NL80211_IFTYPE_AFTER_LAST,
+@@ -257,27 +299,167 @@ enum nl80211_sta_flags {
+ };
+ 
+ /**
+- * enum nl80211_sta_stats - station statistics
++ * enum nl80211_sta_info - station information
+  *
+- * These attribute types are used with %NL80211_ATTR_STA_STATS
++ * These attribute types are used with %NL80211_ATTR_STA_INFO
+  * when getting information about a station.
+  *
+- * @__NL80211_STA_STAT_INVALID: attribute number 0 is reserved
+- * @NL80211_STA_STAT_INACTIVE_TIME: time since last activity (u32, msecs)
+- * @NL80211_STA_STAT_RX_BYTES: total received bytes (u32, from this station)
+- * @NL80211_STA_STAT_TX_BYTES: total transmitted bytes (u32, to this station)
+- * @__NL80211_STA_STAT_AFTER_LAST: internal
+- * @NL80211_STA_STAT_MAX: highest possible station stats attribute
++ * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved
++ * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
++ * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station)
++ * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
++ * @__NL80211_STA_INFO_AFTER_LAST: internal
++ * @NL80211_STA_INFO_MAX: highest possible station info attribute
++ */
++enum nl80211_sta_info {
++	__NL80211_STA_INFO_INVALID,
++	NL80211_STA_INFO_INACTIVE_TIME,
++	NL80211_STA_INFO_RX_BYTES,
++	NL80211_STA_INFO_TX_BYTES,
++	NL80211_STA_INFO_LLID,
++	NL80211_STA_INFO_PLID,
++	NL80211_STA_INFO_PLINK_STATE,
++
++	/* keep last */
++	__NL80211_STA_INFO_AFTER_LAST,
++	NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_mpath_flags - nl80211 mesh path flags
++ *
++ * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active
++ * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running
++ * @NL80211_MPATH_FLAG_DSN_VALID: the mesh path contains a valid DSN
++ * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set
++ * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded
++ */
++enum nl80211_mpath_flags {
++	NL80211_MPATH_FLAG_ACTIVE =	1<<0,
++	NL80211_MPATH_FLAG_RESOLVING =	1<<1,
++	NL80211_MPATH_FLAG_DSN_VALID =	1<<2,
++	NL80211_MPATH_FLAG_FIXED =	1<<3,
++	NL80211_MPATH_FLAG_RESOLVED =	1<<4,
++};
++
++/**
++ * enum nl80211_mpath_info - mesh path information
++ *
++ * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting
++ * 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_DSN: 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
++ * 	&enum nl80211_mpath_flags;
++ * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
++ * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries
++ */
++enum nl80211_mpath_info {
++	__NL80211_MPATH_INFO_INVALID,
++	NL80211_MPATH_INFO_FRAME_QLEN,
++	NL80211_MPATH_INFO_DSN,
++	NL80211_MPATH_INFO_METRIC,
++	NL80211_MPATH_INFO_EXPTIME,
++	NL80211_MPATH_INFO_FLAGS,
++	NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
++	NL80211_MPATH_INFO_DISCOVERY_RETRIES,
++
++	/* keep last */
++	__NL80211_MPATH_INFO_AFTER_LAST,
++	NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_band_attr - band attributes
++ * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved
++ * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band,
++ *	an array of nested frequency attributes
++ * @NL80211_BAND_ATTR_RATES: supported bitrates in this band,
++ *	an array of nested bitrate attributes
++ */
++enum nl80211_band_attr {
++	__NL80211_BAND_ATTR_INVALID,
++	NL80211_BAND_ATTR_FREQS,
++	NL80211_BAND_ATTR_RATES,
++
++	/* keep last */
++	__NL80211_BAND_ATTR_AFTER_LAST,
++	NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_frequency_attr - frequency attributes
++ * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
++ * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
++ *	regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is
++ *	permitted on this channel in current regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted
++ *	on this channel in current regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
++ *	on this channel in current regulatory domain.
++ */
++enum nl80211_frequency_attr {
++	__NL80211_FREQUENCY_ATTR_INVALID,
++	NL80211_FREQUENCY_ATTR_FREQ,
++	NL80211_FREQUENCY_ATTR_DISABLED,
++	NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
++	NL80211_FREQUENCY_ATTR_NO_IBSS,
++	NL80211_FREQUENCY_ATTR_RADAR,
++
++	/* keep last */
++	__NL80211_FREQUENCY_ATTR_AFTER_LAST,
++	NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_bitrate_attr - bitrate attributes
++ * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
++ * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported
++ *	in 2.4 GHz band.
++ */
++enum nl80211_bitrate_attr {
++	__NL80211_BITRATE_ATTR_INVALID,
++	NL80211_BITRATE_ATTR_RATE,
++	NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE,
++
++	/* keep last */
++	__NL80211_BITRATE_ATTR_AFTER_LAST,
++	NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_mntr_flags - monitor configuration flags
++ *
++ * Monitor configuration flags.
++ *
++ * @__NL80211_MNTR_FLAG_INVALID: reserved
++ *
++ * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS
++ * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP
++ * @NL80211_MNTR_FLAG_CONTROL: pass control frames
++ * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering
++ * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing.
++ *	overrides all other flags.
++ *
++ * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
++ * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
+  */
+-enum nl80211_sta_stats {
+-	__NL80211_STA_STAT_INVALID,
+-	NL80211_STA_STAT_INACTIVE_TIME,
+-	NL80211_STA_STAT_RX_BYTES,
+-	NL80211_STA_STAT_TX_BYTES,
++enum nl80211_mntr_flags {
++	__NL80211_MNTR_FLAG_INVALID,
++	NL80211_MNTR_FLAG_FCSFAIL,
++	NL80211_MNTR_FLAG_PLCPFAIL,
++	NL80211_MNTR_FLAG_CONTROL,
++	NL80211_MNTR_FLAG_OTHER_BSS,
++	NL80211_MNTR_FLAG_COOK_FRAMES,
+ 
+ 	/* keep last */
+-	__NL80211_STA_STAT_AFTER_LAST,
+-	NL80211_STA_STAT_MAX = __NL80211_STA_STAT_AFTER_LAST - 1
++	__NL80211_MNTR_FLAG_AFTER_LAST,
++	NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1
+ };
+ 
+ #endif /* __LINUX_NL80211_H */
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 6981016..59a61bd 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -62,6 +62,7 @@ extern struct property *of_find_property(const struct device_node *np,
+ 					 int *lenp);
+ extern int of_device_is_compatible(const struct device_node *device,
+ 				   const char *);
++extern int of_device_is_available(const struct device_node *device);
+ extern const void *of_get_property(const struct device_node *node,
+ 				const char *name,
+ 				int *lenp);
+diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
+new file mode 100644
+index 0000000..2ee97e9
+--- /dev/null
++++ b/include/linux/of_gpio.h
+@@ -0,0 +1,69 @@
++/*
++ * OF helpers for the GPIO API
++ *
++ * Copyright (c) 2007-2008  MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at 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 __LINUX_OF_GPIO_H
++#define __LINUX_OF_GPIO_H
++
++#include <linux/errno.h>
++#include <asm/gpio.h>
++
++#ifdef CONFIG_OF_GPIO
++
++/*
++ * Generic OF GPIO chip
++ */
++struct of_gpio_chip {
++	struct gpio_chip gc;
++	int gpio_cells;
++	int (*xlate)(struct of_gpio_chip *of_gc, struct device_node *np,
++		     const void *gpio_spec);
++};
++
++static inline struct of_gpio_chip *to_of_gpio_chip(struct gpio_chip *gc)
++{
++	return container_of(gc, struct of_gpio_chip, gc);
++}
++
++/*
++ * OF GPIO chip for memory mapped banks
++ */
++struct of_mm_gpio_chip {
++	struct of_gpio_chip of_gc;
++	void (*save_regs)(struct of_mm_gpio_chip *mm_gc);
++	void __iomem *regs;
++};
++
++static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
++{
++	struct of_gpio_chip *of_gc = to_of_gpio_chip(gc);
++
++	return container_of(of_gc, struct of_mm_gpio_chip, of_gc);
++}
++
++extern int of_get_gpio(struct device_node *np, int index);
++extern int of_mm_gpiochip_add(struct device_node *np,
++			      struct of_mm_gpio_chip *mm_gc);
++extern int of_gpio_simple_xlate(struct of_gpio_chip *of_gc,
++				struct device_node *np,
++				const void *gpio_spec);
++#else
++
++/* Drivers may not strictly depend on the GPIO support, so let them link. */
++static inline int of_get_gpio(struct device_node *np, int index)
++{
++	return -ENOSYS;
++}
++
++#endif /* CONFIG_OF_GPIO */
++
++#endif /* __LINUX_OF_GPIO_H */
+diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h
+new file mode 100644
+index 0000000..2e5a967
+--- /dev/null
++++ b/include/linux/of_i2c.h
+@@ -0,0 +1,24 @@
++/*
++ * Generic I2C API implementation for PowerPC.
++ *
++ * Copyright (c) 2008 Jochen Friedrich <jochen at scram.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#ifndef __LINUX_OF_I2C_H
++#define __LINUX_OF_I2C_H
++
++#include <linux/i2c.h>
++
++#ifdef CONFIG_OF_I2C
++
++void of_register_i2c_devices(struct i2c_adapter *adap,
++			     struct device_node *adap_node);
++
++#endif /* CONFIG_OF_I2C */
++
++#endif /* __LINUX_OF_I2C_H */
+diff --git a/include/linux/parport.h b/include/linux/parport.h
+index d1ad546..dcb9e01 100644
+--- a/include/linux/parport.h
++++ b/include/linux/parport.h
+@@ -101,9 +101,9 @@ typedef enum {
+ #include <linux/spinlock.h>
+ #include <linux/wait.h>
+ #include <linux/irqreturn.h>
++#include <linux/semaphore.h>
+ #include <asm/system.h>
+ #include <asm/ptrace.h>
+-#include <asm/semaphore.h>
+ 
+ /* Define this later. */
+ struct parport;
+diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h
+new file mode 100644
+index 0000000..a1a1e61
+--- /dev/null
++++ b/include/linux/pci-aspm.h
+@@ -0,0 +1,56 @@
++/*
++ *	aspm.h
++ *
++ *	PCI Express ASPM defines and function prototypes
++ *
++ *	Copyright (C) 2007 Intel Corp.
++ *		Zhang Yanmin (yanmin.zhang at intel.com)
++ *		Shaohua Li (shaohua.li at intel.com)
++ *
++ *	For more information, please consult the following manuals (look at
++ *	http://www.pcisig.com/ for how to get them):
++ *
++ *	PCI Express Specification
++ */
++
++#ifndef LINUX_ASPM_H
++#define LINUX_ASPM_H
++
++#include <linux/pci.h>
++
++#define PCIE_LINK_STATE_L0S	1
++#define PCIE_LINK_STATE_L1	2
++#define PCIE_LINK_STATE_CLKPM	4
++
++#ifdef CONFIG_PCIEASPM
++extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
++extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
++extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
++extern void pci_disable_link_state(struct pci_dev *pdev, int state);
++#else
++static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
++{
++}
++static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev)
++{
++}
++static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev)
++{
++}
++static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
++{
++}
++#endif
++
++#ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
++extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
++extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
++#else
++static inline void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
++{
++}
++static inline void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
++{
++}
++#endif
++#endif /* LINUX_ASPM_H */
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index ea760e5..2924913 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -20,6 +20,8 @@
+ /* Include the pci register defines */
+ #include <linux/pci_regs.h>
+ 
++struct pci_vpd;
++
+ /*
+  * The PCI interface treats multi-function devices as independent
+  * devices.  The slot/function address of each device is encoded
+@@ -128,11 +130,11 @@ struct pci_cap_saved_state {
+ 	u32 data[0];
+ };
+ 
++struct pcie_link_state;
+ /*
+  * The pci_dev structure is used to describe PCI devices.
+  */
+ struct pci_dev {
+-	struct list_head global_list;	/* node in list of all PCI devices */
+ 	struct list_head bus_list;	/* node in per-bus list */
+ 	struct pci_bus	*bus;		/* bus this device is on */
+ 	struct pci_bus	*subordinate;	/* bus this device bridges to */
+@@ -165,6 +167,10 @@ struct pci_dev {
+ 					   this is D0-D3, D0 being fully functional,
+ 					   and D3 being off. */
+ 
++#ifdef CONFIG_PCIEASPM
++	struct pcie_link_state	*link_state;	/* ASPM link state. */
++#endif
++
+ 	pci_channel_state_t error_state;	/* current connectivity state */
+ 	struct	device	dev;		/* Generic device interface */
+ 
+@@ -181,6 +187,7 @@ struct pci_dev {
+ 	unsigned int	transparent:1;	/* Transparent PCI bridge */
+ 	unsigned int	multifunction:1;/* Part of multi-function device */
+ 	/* keep track of device state */
++	unsigned int	is_added:1;
+ 	unsigned int	is_busmaster:1; /* device is busmaster */
+ 	unsigned int	no_msi:1;	/* device may not use msi */
+ 	unsigned int	no_d1d2:1;   /* only allow d0 or d3 */
+@@ -201,11 +208,11 @@ struct pci_dev {
+ #ifdef CONFIG_PCI_MSI
+ 	struct list_head msi_list;
+ #endif
++	struct pci_vpd *vpd;
+ };
+ 
+ extern struct pci_dev *alloc_pci_dev(void);
+ 
+-#define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
+ #define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list)
+ #define	to_pci_dev(n) container_of(n, struct pci_dev, dev)
+ #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
+@@ -449,7 +456,6 @@ extern struct bus_type pci_bus_type;
+ /* Do NOT directly access these two variables, unless you are arch specific pci
+  * code, or pci core code. */
+ extern struct list_head pci_root_buses;	/* list of all known PCI buses */
+-extern struct list_head pci_devices;	/* list of all devices */
+ /* Some device drivers need know if pci is initiated */
+ extern int no_pci_devices(void);
+ 
+@@ -517,17 +523,13 @@ struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
+ 
+ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
+ 				struct pci_dev *from);
+-struct pci_dev *pci_get_device_reverse(unsigned int vendor, unsigned int device,
+-				struct pci_dev *from);
+-
+ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
+ 				unsigned int ss_vendor, unsigned int ss_device,
+-				struct pci_dev *from);
++				const struct pci_dev *from);
+ struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
+ struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
+ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from);
+ int pci_dev_present(const struct pci_device_id *ids);
+-const struct pci_device_id *pci_find_present(const struct pci_device_id *ids);
+ 
+ int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
+ 			     int where, u8 *val);
+@@ -601,7 +603,6 @@ int pcie_get_readrq(struct pci_dev *dev);
+ int pcie_set_readrq(struct pci_dev *dev, int rq);
+ void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
+ int __must_check pci_assign_resource(struct pci_dev *dev, int i);
+-int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
+ int pci_select_bars(struct pci_dev *dev, unsigned long flags);
+ 
+ /* ROM control related routines */
+@@ -626,6 +627,7 @@ int pci_claim_resource(struct pci_dev *, int);
+ void pci_assign_unassigned_resources(void);
+ void pdev_enable_device(struct pci_dev *);
+ void pdev_sort_resources(struct pci_dev *, struct resource_list *);
++int pci_enable_resources(struct pci_dev *, int mask);
+ void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
+ 		    int (*)(struct pci_dev *, u8, u8));
+ #define HAVE_PCI_REQ_REGIONS	2
+@@ -793,18 +795,11 @@ static inline struct pci_dev *pci_get_device(unsigned int vendor,
+ 	return NULL;
+ }
+ 
+-static inline struct pci_dev *pci_get_device_reverse(unsigned int vendor,
+-						     unsigned int device,
+-						     struct pci_dev *from)
+-{
+-	return NULL;
+-}
+-
+ static inline struct pci_dev *pci_get_subsys(unsigned int vendor,
+ 					     unsigned int device,
+ 					     unsigned int ss_vendor,
+ 					     unsigned int ss_device,
+-					     struct pci_dev *from)
++					     const struct pci_dev *from)
+ {
+ 	return NULL;
+ }
+@@ -817,7 +812,6 @@ static inline struct pci_dev *pci_get_class(unsigned int class,
+ 
+ #define pci_dev_present(ids)	(0)
+ #define no_pci_devices()	(1)
+-#define pci_find_present(ids)	(NULL)
+ #define pci_dev_put(dev)	do { } while (0)
+ 
+ static inline void pci_set_master(struct pci_dev *dev)
+diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
+index c1914a8..c0c1223 100644
+--- a/include/linux/pci_regs.h
++++ b/include/linux/pci_regs.h
+@@ -395,9 +395,17 @@
+ #define  PCI_EXP_DEVSTA_AUXPD	0x10	/* AUX Power Detected */
+ #define  PCI_EXP_DEVSTA_TRPND	0x20	/* Transactions Pending */
+ #define PCI_EXP_LNKCAP		12	/* Link Capabilities */
++#define  PCI_EXP_LNKCAP_ASPMS	0xc00	/* ASPM Support */
++#define  PCI_EXP_LNKCAP_L0SEL	0x7000	/* L0s Exit Latency */
++#define  PCI_EXP_LNKCAP_L1EL	0x38000	/* L1 Exit Latency */
++#define  PCI_EXP_LNKCAP_CLKPM	0x40000	/* L1 Clock Power Management */
+ #define PCI_EXP_LNKCTL		16	/* Link Control */
++#define  PCI_EXP_LNKCTL_RL	0x20	/* Retrain Link */
++#define  PCI_EXP_LNKCTL_CCC	0x40	/* Common Clock COnfiguration */
+ #define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100	/* Enable clkreq */
+ #define PCI_EXP_LNKSTA		18	/* Link Status */
++#define  PCI_EXP_LNKSTA_LT	0x800	/* Link Training */
++#define  PCI_EXP_LNKSTA_SLC	0x1000	/* Slot Clock Configuration */
+ #define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
+ #define PCI_EXP_SLTCTL		24	/* Slot Control */
+ #define PCI_EXP_SLTSTA		26	/* Slot Status */
+diff --git a/include/linux/pcounter.h b/include/linux/pcounter.h
+deleted file mode 100644
+index a82d9f2..0000000
+--- a/include/linux/pcounter.h
++++ /dev/null
+@@ -1,74 +0,0 @@
+-#ifndef __LINUX_PCOUNTER_H
+-#define __LINUX_PCOUNTER_H
+-/*
+- * Using a dynamic percpu 'int' variable has a cost :
+- * 1) Extra dereference
+- * Current per_cpu_ptr() implementation uses an array per 'percpu variable'.
+- * 2) memory cost of NR_CPUS*(32+sizeof(void *)) instead of num_possible_cpus()*4
+- *
+- * This pcounter implementation is an abstraction to be able to use
+- * either a static or a dynamic per cpu variable.
+- * One dynamic per cpu variable gets a fast & cheap implementation, we can
+- * change pcounter implementation too.
+- */
+-struct pcounter {
+-#ifdef CONFIG_SMP
+-	void		(*add)(struct pcounter *self, int inc);
+-	int		(*getval)(const struct pcounter *self, int cpu);
+-	int		*per_cpu_values;
+-#else
+-	int		val;
+-#endif
+-};
+-
+-#ifdef CONFIG_SMP
+-#include <linux/percpu.h>
+-
+-#define DEFINE_PCOUNTER(NAME)						\
+-static DEFINE_PER_CPU(int, NAME##_pcounter_values);			\
+-static void NAME##_pcounter_add(struct pcounter *self, int val)		\
+-{									\
+-       __get_cpu_var(NAME##_pcounter_values) += val;			\
+-}									\
+-static int NAME##_pcounter_getval(const struct pcounter *self, int cpu)	\
+-{									\
+-	return per_cpu(NAME##_pcounter_values, cpu);			\
+-}									\
+-
+-#define PCOUNTER_MEMBER_INITIALIZER(NAME, MEMBER)		\
+-	MEMBER = {						\
+-		.add	= NAME##_pcounter_add,			\
+-		.getval = NAME##_pcounter_getval,		\
+-	}
+-
+-
+-static inline void pcounter_add(struct pcounter *self, int inc)
+-{
+-	self->add(self, inc);
+-}
+-
+-extern int pcounter_getval(const struct pcounter *self);
+-extern int pcounter_alloc(struct pcounter *self);
+-extern void pcounter_free(struct pcounter *self);
+-
+-
+-#else /* CONFIG_SMP */
+-
+-static inline void pcounter_add(struct pcounter *self, int inc)
+-{
+-	self->val += inc;
+-}
+-
+-static inline int pcounter_getval(const struct pcounter *self)
+-{
+-	return self->val;
+-}
+-
+-#define DEFINE_PCOUNTER(NAME)
+-#define PCOUNTER_MEMBER_INITIALIZER(NAME, MEMBER)
+-#define pcounter_alloc(self) 0
+-#define pcounter_free(self)
+-
+-#endif /* CONFIG_SMP */
+-
+-#endif /* __LINUX_PCOUNTER_H */
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index 5e43ae7..02df20f 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -39,7 +39,8 @@
+ 				 SUPPORTED_1000baseT_Half | \
+ 				 SUPPORTED_1000baseT_Full)
+ 
+-/* Set phydev->irq to PHY_POLL if interrupts are not supported,
++/*
++ * Set phydev->irq to PHY_POLL if interrupts are not supported,
+  * or not desired for this PHY.  Set to PHY_IGNORE_INTERRUPT if
+  * the attached driver handles the interrupt
+  */
+@@ -63,8 +64,6 @@ typedef enum {
+ 	PHY_INTERFACE_MODE_RTBI
+ } phy_interface_t;
+ 
+-#define MII_BUS_MAX 4
+-
+ 
+ #define PHY_INIT_TIMEOUT	100000
+ #define PHY_STATE_TIME		1
+@@ -74,20 +73,30 @@ typedef enum {
+ #define PHY_MAX_ADDR	32
+ 
+ /* Used when trying to connect to a specific phy (mii bus id:phy device id) */
+-#define PHY_ID_FMT "%x:%02x"
++#define PHY_ID_FMT "%s:%02x"
++
++/*
++ * Need to be a little smaller than phydev->dev.bus_id to leave room
++ * for the ":%02x"
++ */
++#define MII_BUS_ID_SIZE	(BUS_ID_SIZE - 3)
+ 
+-/* The Bus class for PHYs.  Devices which provide access to
+- * PHYs should register using this structure */
++/*
++ * The Bus class for PHYs.  Devices which provide access to
++ * PHYs should register using this structure
++ */
+ struct mii_bus {
+ 	const char *name;
+-	int id;
++	char id[MII_BUS_ID_SIZE];
+ 	void *priv;
+ 	int (*read)(struct mii_bus *bus, int phy_id, int regnum);
+ 	int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val);
+ 	int (*reset)(struct mii_bus *bus);
+ 
+-	/* A lock to ensure that only one thing can read/write
+-	 * the MDIO bus at a time */
++	/*
++	 * A lock to ensure that only one thing can read/write
++	 * the MDIO bus at a time
++	 */
+ 	struct mutex mdio_lock;
+ 
+ 	struct device *dev;
+@@ -98,8 +107,10 @@ struct mii_bus {
+ 	/* Phy addresses to be ignored when probing */
+ 	u32 phy_mask;
+ 
+-	/* Pointer to an array of interrupts, each PHY's
+-	 * interrupt at the index matching its address */
++	/*
++	 * Pointer to an array of interrupts, each PHY's
++	 * interrupt at the index matching its address
++	 */
+ 	int *irq;
+ };
+ 
+@@ -251,7 +262,8 @@ struct phy_device {
+ 	/* Bus address of the PHY (0-32) */
+ 	int addr;
+ 
+-	/* forced speed & duplex (no autoneg)
++	/*
++	 * forced speed & duplex (no autoneg)
+ 	 * partner speed & duplex & pause (autoneg)
+ 	 */
+ 	int speed;
+@@ -274,8 +286,10 @@ struct phy_device {
+ 
+ 	int link_timeout;
+ 
+-	/* Interrupt number for this PHY
+-	 * -1 means no interrupt */
++	/*
++	 * Interrupt number for this PHY
++	 * -1 means no interrupt
++	 */
+ 	int irq;
+ 
+ 	/* private data pointer */
+@@ -325,22 +339,28 @@ struct phy_driver {
+ 	u32 features;
+ 	u32 flags;
+ 
+-	/* Called to initialize the PHY,
+-	 * including after a reset */
++	/*
++	 * Called to initialize the PHY,
++	 * including after a reset
++	 */
+ 	int (*config_init)(struct phy_device *phydev);
+ 
+-	/* Called during discovery.  Used to set
+-	 * up device-specific structures, if any */
++	/*
++	 * Called during discovery.  Used to set
++	 * up device-specific structures, if any
++	 */
+ 	int (*probe)(struct phy_device *phydev);
+ 
+ 	/* PHY Power Management */
+ 	int (*suspend)(struct phy_device *phydev);
+ 	int (*resume)(struct phy_device *phydev);
+ 
+-	/* Configures the advertisement and resets
++	/*
++	 * Configures the advertisement and resets
+ 	 * autonegotiation if phydev->autoneg is on,
+ 	 * forces the speed to the current settings in phydev
+-	 * if phydev->autoneg is off */
++	 * if phydev->autoneg is off
++	 */
+ 	int (*config_aneg)(struct phy_device *phydev);
+ 
+ 	/* Determines the negotiated speed and duplex */
+@@ -359,14 +379,27 @@ struct phy_driver {
+ };
+ #define to_phy_driver(d) container_of(d, struct phy_driver, driver)
+ 
++#define PHY_ANY_ID "MATCH ANY PHY"
++#define PHY_ANY_UID 0xffffffff
++
++/* A Structure for boards to register fixups with the PHY Lib */
++struct phy_fixup {
++	struct list_head list;
++	char bus_id[BUS_ID_SIZE];
++	u32 phy_uid;
++	u32 phy_uid_mask;
++	int (*run)(struct phy_device *phydev);
++};
++
+ int phy_read(struct phy_device *phydev, u16 regnum);
+ int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
++int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id);
+ struct phy_device* get_phy_device(struct mii_bus *bus, int addr);
+ int phy_clear_interrupt(struct phy_device *phydev);
+ int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
+ struct phy_device * phy_attach(struct net_device *dev,
+-		const char *phy_id, u32 flags, phy_interface_t interface);
+-struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
++		const char *bus_id, u32 flags, phy_interface_t interface);
++struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
+ 		void (*handler)(struct net_device *), u32 flags,
+ 		phy_interface_t interface);
+ void phy_disconnect(struct phy_device *phydev);
+@@ -406,5 +439,13 @@ void phy_print_status(struct phy_device *phydev);
+ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id);
+ void phy_device_free(struct phy_device *phydev);
+ 
++int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
++		int (*run)(struct phy_device *));
++int phy_register_fixup_for_id(const char *bus_id,
++		int (*run)(struct phy_device *));
++int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
++		int (*run)(struct phy_device *));
++int phy_scan_fixups(struct phy_device *phydev);
++
+ extern struct bus_type mdio_bus_type;
+ #endif /* __PHY_H */
+diff --git a/include/linux/pim.h b/include/linux/pim.h
+new file mode 100644
+index 0000000..236ffd3
+--- /dev/null
++++ b/include/linux/pim.h
+@@ -0,0 +1,45 @@
++#ifndef __LINUX_PIM_H
++#define __LINUX_PIM_H
++
++#include <asm/byteorder.h>
++
++#ifndef __KERNEL__
++struct pim {
++#if defined(__LITTLE_ENDIAN_BITFIELD)
++	__u8	pim_type:4,		/* PIM message type */
++		pim_ver:4;		/* PIM version */
++#elif defined(__BIG_ENDIAN_BITFIELD)
++	__u8	pim_ver:4;		/* PIM version */
++		pim_type:4;		/* PIM message type */
++#endif
++	__u8	pim_rsv;		/* Reserved */
++	__be16	pim_cksum;		/* Checksum */
++};
++
++#define PIM_MINLEN		8
++#endif
++
++/* Message types - V1 */
++#define PIM_V1_VERSION		__constant_htonl(0x10000000)
++#define PIM_V1_REGISTER		1
++
++/* Message types - V2 */
++#define PIM_VERSION		2
++#define PIM_REGISTER		1
++
++#if defined(__KERNEL__)
++#define PIM_NULL_REGISTER	__constant_htonl(0x40000000)
++
++/* PIMv2 register message header layout (ietf-draft-idmr-pimvsm-v2-00.ps */
++struct pimreghdr
++{
++	__u8	type;
++	__u8	reserved;
++	__be16	csum;
++	__be32	flags;
++};
++
++struct sk_buff;
++extern int pim_rcv_v1(struct sk_buff *);
++#endif
++#endif
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 015b735..1de72cb 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -183,8 +183,9 @@ typedef struct pm_message {
+ struct dev_pm_info {
+ 	pm_message_t		power_state;
+ 	unsigned		can_wakeup:1;
+-#ifdef	CONFIG_PM_SLEEP
+ 	unsigned		should_wakeup:1;
++	bool			sleeping:1;	/* Owned by the PM core */
++#ifdef	CONFIG_PM_SLEEP
+ 	struct list_head	entry;
+ #endif
+ };
+@@ -197,11 +198,6 @@ extern void device_resume(void);
+ extern int device_suspend(pm_message_t state);
+ extern int device_prepare_suspend(pm_message_t state);
+ 
+-#define device_set_wakeup_enable(dev,val) \
+-	((dev)->power.should_wakeup = !!(val))
+-#define device_may_wakeup(dev) \
+-	(device_can_wakeup(dev) && (dev)->power.should_wakeup)
+-
+ extern void __suspend_report_result(const char *function, void *fn, int ret);
+ 
+ #define suspend_report_result(fn, ret)					\
+@@ -209,20 +205,6 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
+ 		__suspend_report_result(__FUNCTION__, fn, ret);		\
+ 	} while (0)
+ 
+-/*
+- * Platform hook to activate device wakeup capability, if that's not already
+- * handled by enable_irq_wake() etc.
+- * Returns zero on success, else negative errno
+- */
+-extern int (*platform_enable_wakeup)(struct device *dev, int is_on);
+-
+-static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
+-{
+-	if (platform_enable_wakeup)
+-		return (*platform_enable_wakeup)(dev, is_on);
+-	return 0;
+-}
+-
+ #else /* !CONFIG_PM_SLEEP */
+ 
+ static inline int device_suspend(pm_message_t state)
+@@ -230,29 +212,10 @@ static inline int device_suspend(pm_message_t state)
+ 	return 0;
+ }
+ 
+-#define device_set_wakeup_enable(dev,val)	do{}while(0)
+-#define device_may_wakeup(dev)			(0)
+-
+-#define suspend_report_result(fn, ret) do { } while (0)
+-
+-static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
+-{
+-	return 0;
+-}
++#define suspend_report_result(fn, ret)		do {} while (0)
+ 
+ #endif /* !CONFIG_PM_SLEEP */
+ 
+-/* changes to device_may_wakeup take effect on the next pm state change.
+- * by default, devices should wakeup if they can.
+- */
+-#define device_can_wakeup(dev) \
+-	((dev)->power.can_wakeup)
+-#define device_init_wakeup(dev,val) \
+-	do { \
+-		device_can_wakeup(dev) = !!(val); \
+-		device_set_wakeup_enable(dev,val); \
+-	} while(0)
+-
+ /*
+  * Global Power Management flags
+  * Used to keep APM and ACPI from both being active
+diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
+new file mode 100644
+index 0000000..f0d0b2c
+--- /dev/null
++++ b/include/linux/pm_wakeup.h
+@@ -0,0 +1,90 @@
++/*
++ *  pm_wakeup.h - Power management wakeup interface
++ *
++ *  Copyright (C) 2008 Alan Stern
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef _LINUX_PM_WAKEUP_H
++#define _LINUX_PM_WAKEUP_H
++
++#ifndef _DEVICE_H_
++# error "please don't include this file directly"
++#endif
++
++#ifdef CONFIG_PM
++
++/* changes to device_may_wakeup take effect on the next pm state change.
++ * by default, devices should wakeup if they can.
++ */
++static inline void device_init_wakeup(struct device *dev, int val)
++{
++	dev->power.can_wakeup = dev->power.should_wakeup = !!val;
++}
++
++static inline int device_can_wakeup(struct device *dev)
++{
++	return dev->power.can_wakeup;
++}
++
++static inline void device_set_wakeup_enable(struct device *dev, int val)
++{
++	dev->power.should_wakeup = !!val;
++}
++
++static inline int device_may_wakeup(struct device *dev)
++{
++	return dev->power.can_wakeup & dev->power.should_wakeup;
++}
++
++/*
++ * Platform hook to activate device wakeup capability, if that's not already
++ * handled by enable_irq_wake() etc.
++ * Returns zero on success, else negative errno
++ */
++extern int (*platform_enable_wakeup)(struct device *dev, int is_on);
++
++static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
++{
++	if (platform_enable_wakeup)
++		return (*platform_enable_wakeup)(dev, is_on);
++	return 0;
++}
++
++#else /* !CONFIG_PM */
++
++/* For some reason the next two routines work even without CONFIG_PM */
++static inline void device_init_wakeup(struct device *dev, int val)
++{
++	dev->power.can_wakeup = !!val;
++}
++
++static inline int device_can_wakeup(struct device *dev)
++{
++	return dev->power.can_wakeup;
++}
++
++#define device_set_wakeup_enable(dev, val)	do {} while (0)
++#define device_may_wakeup(dev)			0
++
++static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
++{
++	return 0;
++}
++
++#endif /* !CONFIG_PM */
++
++#endif /* _LINUX_PM_WAKEUP_H */
+diff --git a/include/linux/prctl.h b/include/linux/prctl.h
+index 3800639..5c80b19 100644
+--- a/include/linux/prctl.h
++++ b/include/linux/prctl.h
+@@ -67,4 +67,10 @@
+ #define PR_CAPBSET_READ 23
+ #define PR_CAPBSET_DROP 24
+ 
++/* Get/set the process' ability to use the timestamp counter instruction */
++#define PR_GET_TSC 25
++#define PR_SET_TSC 26
++# define PR_TSC_ENABLE		1	/* allow the use of the timestamp counter */
++# define PR_TSC_SIGSEGV		2	/* throw a SIGSEGV instead of reading the TSC */
++
+ #endif /* _LINUX_PRCTL_H */
+diff --git a/include/linux/quota.h b/include/linux/quota.h
+index 6e0393a..eb560d0 100644
+--- a/include/linux/quota.h
++++ b/include/linux/quota.h
+@@ -160,14 +160,18 @@ enum {
+ 
+ 
+ #ifdef __KERNEL__
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
++#include <linux/list.h>
+ #include <linux/mutex.h>
++#include <linux/rwsem.h>
++#include <linux/spinlock.h>
++#include <linux/wait.h>
+ 
+ #include <linux/dqblk_xfs.h>
+ #include <linux/dqblk_v1.h>
+ #include <linux/dqblk_v2.h>
+ 
++#include <asm/atomic.h>
++
+ extern spinlock_t dq_data_lock;
+ 
+ /* Maximal numbers of writes for quota operation (insert/delete/update)
+diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
+index fbaeda7..8ab630b 100644
+--- a/include/linux/raid/md.h
++++ b/include/linux/raid/md.h
+@@ -19,7 +19,6 @@
+ #define _MD_H
+ 
+ #include <linux/blkdev.h>
+-#include <asm/semaphore.h>
+ #include <linux/major.h>
+ #include <linux/ioctl.h>
+ #include <linux/types.h>
+diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
+index d22ad39..6b537f1 100644
+--- a/include/linux/raid_class.h
++++ b/include/linux/raid_class.h
+@@ -53,20 +53,20 @@ struct raid_data {
+ #define DEFINE_RAID_ATTRIBUTE(type, attr)				      \
+ static inline void							      \
+ raid_set_##attr(struct raid_template *r, struct device *dev, type value) {    \
+-	struct class_device *cdev =					      \
++	struct device *device =						      \
+ 		attribute_container_find_class_device(&r->raid_attrs.ac, dev);\
+ 	struct raid_data *rd;						      \
+-	BUG_ON(!cdev);							      \
+-	rd = class_get_devdata(cdev);					      \
++	BUG_ON(!device);						      \
++	rd = dev_get_drvdata(device);					      \
+ 	rd->attr = value;						      \
+ }									      \
+ static inline type							      \
+ raid_get_##attr(struct raid_template *r, struct device *dev) {		      \
+-	struct class_device *cdev =					      \
++	struct device *device =						      \
+ 		attribute_container_find_class_device(&r->raid_attrs.ac, dev);\
+ 	struct raid_data *rd;						      \
+-	BUG_ON(!cdev);							      \
+-	rd = class_get_devdata(cdev);					      \
++	BUG_ON(!device);						      \
++	rd = dev_get_drvdata(device);					      \
+ 	return rd->attr;						      \
+ }
+ 
+diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
+index b9e1740..44c81c7 100644
+--- a/include/linux/rtnetlink.h
++++ b/include/linux/rtnetlink.h
+@@ -740,13 +740,13 @@ extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change);
+ extern void rtnl_lock(void);
+ extern void rtnl_unlock(void);
+ extern int rtnl_trylock(void);
++extern int rtnl_is_locked(void);
+ 
+ extern void rtnetlink_init(void);
+ extern void __rtnl_unlock(void);
+ 
+ #define ASSERT_RTNL() do { \
+-	if (unlikely(rtnl_trylock())) { \
+-		rtnl_unlock(); \
++	if (unlikely(!rtnl_is_locked())) { \
+ 		printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \
+ 		       __FILE__,  __LINE__); \
+ 		dump_stack(); \
+diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
+index a3d567a..71fc813 100644
+--- a/include/linux/scatterlist.h
++++ b/include/linux/scatterlist.h
+@@ -213,6 +213,11 @@ int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t,
+ 		     sg_alloc_fn *);
+ int sg_alloc_table(struct sg_table *, unsigned int, gfp_t);
+ 
++size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
++			   void *buf, size_t buflen);
++size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
++			 void *buf, size_t buflen);
++
+ /*
+  * Maximum number of entries that will be allocated in one piece, if
+  * a list larger than this is required then chaining will be utilized.
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index 6a1e7af..d0bd970 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -61,7 +61,6 @@ struct sched_param {
+ #include <linux/mm_types.h>
+ 
+ #include <asm/system.h>
+-#include <asm/semaphore.h>
+ #include <asm/page.h>
+ #include <asm/ptrace.h>
+ #include <asm/cputime.h>
+@@ -704,6 +703,7 @@ enum cpu_idle_type {
+ #define SD_POWERSAVINGS_BALANCE	256	/* Balance for power savings */
+ #define SD_SHARE_PKG_RESOURCES	512	/* Domain members share cpu pkg resources */
+ #define SD_SERIALIZE		1024	/* Only a single load balancing instance */
++#define SD_WAKE_IDLE_FAR	2048	/* Gain latency sacrificing cache hit */
+ 
+ #define BALANCE_FOR_MC_POWER	\
+ 	(sched_smt_power_savings ? SD_POWERSAVINGS_BALANCE : 0)
+@@ -733,12 +733,31 @@ struct sched_group {
+ 	u32 reciprocal_cpu_power;
+ };
+ 
++enum sched_domain_level {
++	SD_LV_NONE = 0,
++	SD_LV_SIBLING,
++	SD_LV_MC,
++	SD_LV_CPU,
++	SD_LV_NODE,
++	SD_LV_ALLNODES,
++	SD_LV_MAX
++};
++
++struct sched_domain_attr {
++	int relax_domain_level;
++};
++
++#define SD_ATTR_INIT	(struct sched_domain_attr) {	\
++	.relax_domain_level = -1,			\
++}
++
+ struct sched_domain {
+ 	/* These fields must be setup */
+ 	struct sched_domain *parent;	/* top domain must be null terminated */
+ 	struct sched_domain *child;	/* bottom domain must be null terminated */
+ 	struct sched_group *groups;	/* the balancing groups of the domain */
+ 	cpumask_t span;			/* span of all CPUs in this domain */
++	int first_cpu;			/* cache of the first cpu in this domain */
+ 	unsigned long min_interval;	/* Minimum balance interval ms */
+ 	unsigned long max_interval;	/* Maximum balance interval ms */
+ 	unsigned int busy_factor;	/* less balancing by factor if busy */
+@@ -750,6 +769,7 @@ struct sched_domain {
+ 	unsigned int wake_idx;
+ 	unsigned int forkexec_idx;
+ 	int flags;			/* See SD_* */
++	enum sched_domain_level level;
+ 
+ 	/* Runtime fields. */
+ 	unsigned long last_balance;	/* init to jiffies. units in jiffies */
+@@ -789,7 +809,8 @@ struct sched_domain {
+ #endif
+ };
+ 
+-extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new);
++extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
++				    struct sched_domain_attr *dattr_new);
+ extern int arch_reinit_sched_domains(void);
+ 
+ #endif	/* CONFIG_SMP */
+@@ -889,7 +910,8 @@ struct sched_class {
+ 	void (*set_curr_task) (struct rq *rq);
+ 	void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
+ 	void (*task_new) (struct rq *rq, struct task_struct *p);
+-	void (*set_cpus_allowed)(struct task_struct *p, cpumask_t *newmask);
++	void (*set_cpus_allowed)(struct task_struct *p,
++				 const cpumask_t *newmask);
+ 
+ 	void (*join_domain)(struct rq *rq);
+ 	void (*leave_domain)(struct rq *rq);
+@@ -923,6 +945,7 @@ struct load_weight {
+ struct sched_entity {
+ 	struct load_weight	load;		/* for load-balancing */
+ 	struct rb_node		run_node;
++	struct list_head	group_node;
+ 	unsigned int		on_rq;
+ 
+ 	u64			exec_start;
+@@ -982,6 +1005,7 @@ struct sched_rt_entity {
+ 	unsigned long timeout;
+ 	int nr_cpus_allowed;
+ 
++	struct sched_rt_entity *back;
+ #ifdef CONFIG_RT_GROUP_SCHED
+ 	struct sched_rt_entity	*parent;
+ 	/* rq on which this entity is (to be) queued: */
+@@ -1502,15 +1526,21 @@ static inline void put_task_struct(struct task_struct *t)
+ #define used_math() tsk_used_math(current)
+ 
+ #ifdef CONFIG_SMP
+-extern int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask);
++extern int set_cpus_allowed_ptr(struct task_struct *p,
++				const cpumask_t *new_mask);
+ #else
+-static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
++static inline int set_cpus_allowed_ptr(struct task_struct *p,
++				       const cpumask_t *new_mask)
+ {
+-	if (!cpu_isset(0, new_mask))
++	if (!cpu_isset(0, *new_mask))
+ 		return -EINVAL;
+ 	return 0;
+ }
+ #endif
++static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
++{
++	return set_cpus_allowed_ptr(p, &new_mask);
++}
+ 
+ extern unsigned long long sched_clock(void);
+ 
+@@ -1551,7 +1581,6 @@ static inline void wake_up_idle_cpu(int cpu) { }
+ extern unsigned int sysctl_sched_latency;
+ extern unsigned int sysctl_sched_min_granularity;
+ extern unsigned int sysctl_sched_wakeup_granularity;
+-extern unsigned int sysctl_sched_batch_wakeup_granularity;
+ extern unsigned int sysctl_sched_child_runs_first;
+ extern unsigned int sysctl_sched_features;
+ extern unsigned int sysctl_sched_migration_cost;
+@@ -1564,6 +1593,10 @@ int sched_nr_latency_handler(struct ctl_table *table, int write,
+ extern unsigned int sysctl_sched_rt_period;
+ extern int sysctl_sched_rt_runtime;
+ 
++int sched_rt_handler(struct ctl_table *table, int write,
++		struct file *filp, void __user *buffer, size_t *lenp,
++		loff_t *ppos);
++
+ extern unsigned int sysctl_sched_compat_yield;
+ 
+ #ifdef CONFIG_RT_MUTEXES
+@@ -1893,6 +1926,8 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
+ 
+ #endif
+ 
++extern void thread_info_cache_init(void);
++
+ /* set thread flags in other task's structures
+  * - see asm/thread_info.h for TIF_xxxx flags available
+  */
+@@ -2031,7 +2066,7 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm)
+ }
+ #endif
+ 
+-extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
++extern long sched_setaffinity(pid_t pid, const cpumask_t *new_mask);
+ extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
+ 
+ extern int sched_mc_power_savings, sched_smt_power_savings;
+@@ -2041,8 +2076,11 @@ extern void normalize_rt_tasks(void);
+ #ifdef CONFIG_GROUP_SCHED
+ 
+ extern struct task_group init_task_group;
++#ifdef CONFIG_USER_SCHED
++extern struct task_group root_task_group;
++#endif
+ 
+-extern struct task_group *sched_create_group(void);
++extern struct task_group *sched_create_group(struct task_group *parent);
+ extern void sched_destroy_group(struct task_group *tg);
+ extern void sched_move_task(struct task_struct *tsk);
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+@@ -2053,6 +2091,9 @@ extern unsigned long sched_group_shares(struct task_group *tg);
+ extern int sched_group_set_rt_runtime(struct task_group *tg,
+ 				      long rt_runtime_us);
+ extern long sched_group_rt_runtime(struct task_group *tg);
++extern int sched_group_set_rt_period(struct task_group *tg,
++				      long rt_period_us);
++extern long sched_group_rt_period(struct task_group *tg);
+ #endif
+ #endif
+ 
+diff --git a/include/linux/security.h b/include/linux/security.h
+index c673dfd..53a3453 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -36,7 +36,11 @@
+ 
+ extern unsigned securebits;
+ 
++/* Maximum number of letters for an LSM name string */
++#define SECURITY_NAME_MAX	10
++
+ struct ctl_table;
++struct audit_krule;
+ 
+ /*
+  * These functions are in security/capability.c and are used
+@@ -136,6 +140,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ /**
+  * struct security_operations - main security structure
+  *
++ * Security module identifier.
++ *
++ * @name:
++ *	A string that acts as a unique identifeir for the LSM with max number
++ *	of characters = SECURITY_NAME_MAX.
++ *
+  * Security hooks for program execution operations.
+  *
+  * @bprm_alloc_security:
+@@ -220,7 +230,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+  *	loopback/bind mount (@flags & MS_BIND), @dev_name identifies the
+  *	pathname of the object being mounted.
+  *	@dev_name contains the name for object being mounted.
+- *	@nd contains the nameidata structure for mount point object.
++ *	@path contains the path for mount point object.
+  *	@type contains the filesystem type.
+  *	@flags contains the mount flags.
+  *	@data contains the filesystem-specific data.
+@@ -239,7 +249,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+  *	Check permission before the device with superblock @mnt->sb is mounted
+  *	on the mount point named by @nd.
+  *	@mnt contains the vfsmount for device being mounted.
+- *	@nd contains the nameidata object for the mount point.
++ *	@path contains the path for the mount point.
+  *	Return 0 if permission is granted.
+  * @sb_umount:
+  *	Check permission before the @mnt file system is unmounted.
+@@ -268,16 +278,16 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+  *	This hook is called any time a mount is successfully grafetd to
+  *	the tree.
+  *	@mnt contains the mounted filesystem.
+- *	@mountpoint_nd contains the nameidata structure for the mount point.
++ *	@mountpoint contains the path for the mount point.
+  * @sb_pivotroot:
+  *	Check permission before pivoting the root filesystem.
+- *	@old_nd contains the nameidata structure for the new location of the current root (put_old).
+- *      @new_nd contains the nameidata structure for the new root (new_root).
++ *	@old_path contains the path for the new location of the current root (put_old).
++ *      @new_path contains the path for the new root (new_root).
+  *	Return 0 if permission is granted.
+  * @sb_post_pivotroot:
+  *	Update module state after a successful pivot.
+- *	@old_nd contains the nameidata structure for the old root.
+- *      @new_nd contains the nameidata structure for the new root.
++ *	@old_path contains the path for the old root.
++ *      @new_path contains the path for the new root.
+  * @sb_get_mnt_opts:
+  *	Get the security relevant mount options used for a superblock
+  *	@sb the superblock to get security mount options from
+@@ -468,6 +478,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+  *	@dentry is the dentry being changed.
+  *	Return 0 on success.  If error is returned, then the operation
+  *	causing setuid bit removal is failed.
++ * @inode_getsecid:
++ *	Get the secid associated with the node.
++ *	@inode contains a pointer to the inode.
++ *	@secid contains a pointer to the location where result will be saved.
++ *	In case of failure, @secid will be set to zero.
+  *
+  * Security hooks for file operations
+  *
+@@ -636,6 +651,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+  * @task_getsecid:
+  *	Retrieve the security identifier of the process @p.
+  *	@p contains the task_struct for the process and place is into @secid.
++ *	In case of failure, @secid will be set to zero.
++ *
+  * @task_setgroups:
+  *	Check permission before setting the supplementary group set of the
+  *	current process.
+@@ -910,24 +927,24 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+  * Security hooks for XFRM operations.
+  *
+  * @xfrm_policy_alloc_security:
+- *	@xp contains the xfrm_policy being added to Security Policy Database
+- *	used by the XFRM system.
++ *	@ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy
++ *	Database used by the XFRM system.
+  *	@sec_ctx contains the security context information being provided by
+  *	the user-level policy update program (e.g., setkey).
+  *	Allocate a security structure to the xp->security field; the security
+  *	field is initialized to NULL when the xfrm_policy is allocated.
+  *	Return 0 if operation was successful (memory to allocate, legal context)
+  * @xfrm_policy_clone_security:
+- *	@old contains an existing xfrm_policy in the SPD.
+- *	@new contains a new xfrm_policy being cloned from old.
+- *	Allocate a security structure to the new->security field
+- *	that contains the information from the old->security field.
++ *	@old_ctx contains an existing xfrm_sec_ctx.
++ *	@new_ctxp contains a new xfrm_sec_ctx being cloned from old.
++ *	Allocate a security structure in new_ctxp that contains the
++ *	information from the old_ctx structure.
+  *	Return 0 if operation was successful (memory to allocate).
+  * @xfrm_policy_free_security:
+- *	@xp contains the xfrm_policy
++ *	@ctx contains the xfrm_sec_ctx
+  *	Deallocate xp->security.
+  * @xfrm_policy_delete_security:
+- *	@xp contains the xfrm_policy.
++ *	@ctx contains the xfrm_sec_ctx.
+  *	Authorize deletion of xp->security.
+  * @xfrm_state_alloc_security:
+  *	@x contains the xfrm_state being added to the Security Association
+@@ -947,7 +964,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+  *	@x contains the xfrm_state.
+  *	Authorize deletion of x->security.
+  * @xfrm_policy_lookup:
+- *	@xp contains the xfrm_policy for which the access control is being
++ *	@ctx contains the xfrm_sec_ctx for which the access control is being
+  *	checked.
+  *	@fl_secid contains the flow security label that is used to authorize
+  *	access to the policy xp.
+@@ -997,6 +1014,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+  *	@ipcp contains the kernel IPC permission structure
+  *	@flag contains the desired (requested) permission set
+  *	Return 0 if permission is granted.
++ * @ipc_getsecid:
++ *	Get the secid associated with the ipc object.
++ *	@ipcp contains the kernel IPC permission structure.
++ *	@secid contains a pointer to the location where result will be saved.
++ *	In case of failure, @secid will be set to zero.
+  *
+  * Security hooks for individual messages held in System V IPC message queues
+  * @msg_msg_alloc_security:
+@@ -1223,9 +1245,42 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+  *	@secdata contains the security context.
+  *	@seclen contains the length of the security context.
+  *
++ * Security hooks for Audit
++ *
++ * @audit_rule_init:
++ *	Allocate and initialize an LSM audit rule structure.
++ *	@field contains the required Audit action. Fields flags are defined in include/linux/audit.h
++ *	@op contains the operator the rule uses.
++ *	@rulestr contains the context where the rule will be applied to.
++ *	@lsmrule contains a pointer to receive the result.
++ *	Return 0 if @lsmrule has been successfully set,
++ *	-EINVAL in case of an invalid rule.
++ *
++ * @audit_rule_known:
++ *	Specifies whether given @rule contains any fields related to current LSM.
++ *	@rule contains the audit rule of interest.
++ *	Return 1 in case of relation found, 0 otherwise.
++ *
++ * @audit_rule_match:
++ *	Determine if given @secid matches a rule previously approved
++ *	by @audit_rule_known.
++ *	@secid contains the security id in question.
++ *	@field contains the field which relates to current LSM.
++ *	@op contains the operator that will be used for matching.
++ *	@rule points to the audit rule that will be checked against.
++ *	@actx points to the audit context associated with the check.
++ *	Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure.
++ *
++ * @audit_rule_free:
++ *	Deallocate the LSM audit rule structure previously allocated by
++ *	audit_rule_init.
++ *	@rule contains the allocated rule
++ *
+  * This is the main security structure.
+  */
+ struct security_operations {
++	char name[SECURITY_NAME_MAX + 1];
++
+ 	int (*ptrace) (struct task_struct * parent, struct task_struct * child);
+ 	int (*capget) (struct task_struct * target,
+ 		       kernel_cap_t * effective,
+@@ -1260,20 +1315,20 @@ struct security_operations {
+ 	int (*sb_copy_data)(char *orig, char *copy);
+ 	int (*sb_kern_mount) (struct super_block *sb, void *data);
+ 	int (*sb_statfs) (struct dentry *dentry);
+-	int (*sb_mount) (char *dev_name, struct nameidata * nd,
++	int (*sb_mount) (char *dev_name, struct path *path,
+ 			 char *type, unsigned long flags, void *data);
+-	int (*sb_check_sb) (struct vfsmount * mnt, struct nameidata * nd);
++	int (*sb_check_sb) (struct vfsmount * mnt, struct path *path);
+ 	int (*sb_umount) (struct vfsmount * mnt, int flags);
+ 	void (*sb_umount_close) (struct vfsmount * mnt);
+ 	void (*sb_umount_busy) (struct vfsmount * mnt);
+ 	void (*sb_post_remount) (struct vfsmount * mnt,
+ 				 unsigned long flags, void *data);
+ 	void (*sb_post_addmount) (struct vfsmount * mnt,
+-				  struct nameidata * mountpoint_nd);
+-	int (*sb_pivotroot) (struct nameidata * old_nd,
+-			     struct nameidata * new_nd);
+-	void (*sb_post_pivotroot) (struct nameidata * old_nd,
+-				   struct nameidata * new_nd);
++				  struct path *mountpoint);
++	int (*sb_pivotroot) (struct path *old_path,
++			     struct path *new_path);
++	void (*sb_post_pivotroot) (struct path *old_path,
++				   struct path *new_path);
+ 	int (*sb_get_mnt_opts) (const struct super_block *sb,
+ 				struct security_mnt_opts *opts);
+ 	int (*sb_set_mnt_opts) (struct super_block *sb,
+@@ -1317,6 +1372,7 @@ struct security_operations {
+ 	int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
+   	int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
+   	int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);
++	void (*inode_getsecid)(const struct inode *inode, u32 *secid);
+ 
+ 	int (*file_permission) (struct file * file, int mask);
+ 	int (*file_alloc_security) (struct file * file);
+@@ -1369,6 +1425,7 @@ struct security_operations {
+ 	void (*task_to_inode)(struct task_struct *p, struct inode *inode);
+ 
+ 	int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
++	void (*ipc_getsecid) (struct kern_ipc_perm *ipcp, u32 *secid);
+ 
+ 	int (*msg_msg_alloc_security) (struct msg_msg * msg);
+ 	void (*msg_msg_free_security) (struct msg_msg * msg);
+@@ -1454,17 +1511,17 @@ struct security_operations {
+ #endif	/* CONFIG_SECURITY_NETWORK */
+ 
+ #ifdef CONFIG_SECURITY_NETWORK_XFRM
+-	int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp,
++	int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp,
+ 			struct xfrm_user_sec_ctx *sec_ctx);
+-	int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
+-	void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
+-	int (*xfrm_policy_delete_security) (struct xfrm_policy *xp);
++	int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
++	void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
++	int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
+ 	int (*xfrm_state_alloc_security) (struct xfrm_state *x,
+ 		struct xfrm_user_sec_ctx *sec_ctx,
+ 		u32 secid);
+ 	void (*xfrm_state_free_security) (struct xfrm_state *x);
+ 	int (*xfrm_state_delete_security) (struct xfrm_state *x);
+-	int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
++	int (*xfrm_policy_lookup)(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
+ 	int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
+ 			struct xfrm_policy *xp, struct flowi *fl);
+ 	int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
+@@ -1480,10 +1537,18 @@ struct security_operations {
+ 
+ #endif	/* CONFIG_KEYS */
+ 
++#ifdef CONFIG_AUDIT
++	int (*audit_rule_init)(u32 field, u32 op, char *rulestr, void **lsmrule);
++	int (*audit_rule_known)(struct audit_krule *krule);
++	int (*audit_rule_match)(u32 secid, u32 field, u32 op, void *lsmrule,
++				struct audit_context *actx);
++	void (*audit_rule_free)(void *lsmrule);
++#endif /* CONFIG_AUDIT */
+ };
+ 
+ /* prototypes */
+ extern int security_init	(void);
++extern int security_module_enable(struct security_operations *ops);
+ extern int register_security	(struct security_operations *ops);
+ extern int mod_reg_security	(const char *name, struct security_operations *ops);
+ extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
+@@ -1528,16 +1593,16 @@ void security_sb_free(struct super_block *sb);
+ int security_sb_copy_data(char *orig, char *copy);
+ int security_sb_kern_mount(struct super_block *sb, void *data);
+ int security_sb_statfs(struct dentry *dentry);
+-int security_sb_mount(char *dev_name, struct nameidata *nd,
++int security_sb_mount(char *dev_name, struct path *path,
+                        char *type, unsigned long flags, void *data);
+-int security_sb_check_sb(struct vfsmount *mnt, struct nameidata *nd);
++int security_sb_check_sb(struct vfsmount *mnt, struct path *path);
+ int security_sb_umount(struct vfsmount *mnt, int flags);
+ void security_sb_umount_close(struct vfsmount *mnt);
+ void security_sb_umount_busy(struct vfsmount *mnt);
+ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data);
+-void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd);
+-int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
+-void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
++void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint);
++int security_sb_pivotroot(struct path *old_path, struct path *new_path);
++void security_sb_post_pivotroot(struct path *old_path, struct path *new_path);
+ int security_sb_get_mnt_opts(const struct super_block *sb,
+ 				struct security_mnt_opts *opts);
+ int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
+@@ -1578,6 +1643,7 @@ int security_inode_killpriv(struct dentry *dentry);
+ int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
+ int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
+ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
++void security_inode_getsecid(const struct inode *inode, u32 *secid);
+ int security_file_permission(struct file *file, int mask);
+ int security_file_alloc(struct file *file);
+ void security_file_free(struct file *file);
+@@ -1622,6 +1688,7 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+ void security_task_reparent_to_init(struct task_struct *p);
+ void security_task_to_inode(struct task_struct *p, struct inode *inode);
+ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
++void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
+ int security_msg_msg_alloc(struct msg_msg *msg);
+ void security_msg_msg_free(struct msg_msg *msg);
+ int security_msg_queue_alloc(struct msg_queue *msq);
+@@ -1805,7 +1872,7 @@ static inline int security_sb_statfs (struct dentry *dentry)
+ 	return 0;
+ }
+ 
+-static inline int security_sb_mount (char *dev_name, struct nameidata *nd,
++static inline int security_sb_mount (char *dev_name, struct path *path,
+ 				    char *type, unsigned long flags,
+ 				    void *data)
+ {
+@@ -1813,7 +1880,7 @@ static inline int security_sb_mount (char *dev_name, struct nameidata *nd,
+ }
+ 
+ static inline int security_sb_check_sb (struct vfsmount *mnt,
+-					struct nameidata *nd)
++					struct path *path)
+ {
+ 	return 0;
+ }
+@@ -1834,17 +1901,17 @@ static inline void security_sb_post_remount (struct vfsmount *mnt,
+ { }
+ 
+ static inline void security_sb_post_addmount (struct vfsmount *mnt,
+-					      struct nameidata *mountpoint_nd)
++					      struct path *mountpoint)
+ { }
+ 
+-static inline int security_sb_pivotroot (struct nameidata *old_nd,
+-					 struct nameidata *new_nd)
++static inline int security_sb_pivotroot (struct path *old_path,
++					 struct path *new_path)
+ {
+ 	return 0;
+ }
+ 
+-static inline void security_sb_post_pivotroot (struct nameidata *old_nd,
+-					       struct nameidata *new_nd)
++static inline void security_sb_post_pivotroot (struct path *old_path,
++					       struct path *new_path)
+ { }
+ static inline int security_sb_get_mnt_opts(const struct super_block *sb,
+ 					   struct security_mnt_opts *opts)
+@@ -2022,6 +2089,11 @@ static inline int security_inode_listsecurity(struct inode *inode, char *buffer,
+ 	return 0;
+ }
+ 
++static inline void security_inode_getsecid(const struct inode *inode, u32 *secid)
++{
++	*secid = 0;
++}
++
+ static inline int security_file_permission (struct file *file, int mask)
+ {
+ 	return 0;
+@@ -2137,7 +2209,9 @@ static inline int security_task_getsid (struct task_struct *p)
+ }
+ 
+ static inline void security_task_getsecid (struct task_struct *p, u32 *secid)
+-{ }
++{
++	*secid = 0;
++}
+ 
+ static inline int security_task_setgroups (struct group_info *group_info)
+ {
+@@ -2216,6 +2290,11 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
+ 	return 0;
+ }
+ 
++static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
++{
++	*secid = 0;
++}
++
+ static inline int security_msg_msg_alloc (struct msg_msg * msg)
+ {
+ 	return 0;
+@@ -2562,16 +2641,16 @@ static inline void security_inet_conn_established(struct sock *sk,
+ 
+ #ifdef CONFIG_SECURITY_NETWORK_XFRM
+ 
+-int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
+-int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
+-void security_xfrm_policy_free(struct xfrm_policy *xp);
+-int security_xfrm_policy_delete(struct xfrm_policy *xp);
++int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx);
++int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp);
++void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
++int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
+ int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
+ int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
+ 				      struct xfrm_sec_ctx *polsec, u32 secid);
+ int security_xfrm_state_delete(struct xfrm_state *x);
+ void security_xfrm_state_free(struct xfrm_state *x);
+-int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
++int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
+ int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
+ 				       struct xfrm_policy *xp, struct flowi *fl);
+ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid);
+@@ -2579,21 +2658,21 @@ void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);
+ 
+ #else	/* CONFIG_SECURITY_NETWORK_XFRM */
+ 
+-static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
++static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
+ {
+ 	return 0;
+ }
+ 
+-static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
++static inline int security_xfrm_policy_clone(struct xfrm_sec_ctx *old, struct xfrm_sec_ctx **new_ctxp)
+ {
+ 	return 0;
+ }
+ 
+-static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
++static inline void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
+ {
+ }
+ 
+-static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
++static inline int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
+ {
+ 	return 0;
+ }
+@@ -2619,7 +2698,7 @@ static inline int security_xfrm_state_delete(struct xfrm_state *x)
+ 	return 0;
+ }
+ 
+-static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
++static inline int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+ {
+ 	return 0;
+ }
+@@ -2672,5 +2751,38 @@ static inline int security_key_permission(key_ref_t key_ref,
+ #endif
+ #endif /* CONFIG_KEYS */
+ 
++#ifdef CONFIG_AUDIT
++#ifdef CONFIG_SECURITY
++int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule);
++int security_audit_rule_known(struct audit_krule *krule);
++int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
++			      struct audit_context *actx);
++void security_audit_rule_free(void *lsmrule);
++
++#else
++
++static inline int security_audit_rule_init(u32 field, u32 op, char *rulestr,
++					   void **lsmrule)
++{
++	return 0;
++}
++
++static inline int security_audit_rule_known(struct audit_krule *krule)
++{
++	return 0;
++}
++
++static inline int security_audit_rule_match(u32 secid, u32 field, u32 op,
++				   void *lsmrule, struct audit_context *actx)
++{
++	return 0;
++}
++
++static inline void security_audit_rule_free(void *lsmrule)
++{ }
++
++#endif /* CONFIG_SECURITY */
++#endif /* CONFIG_AUDIT */
++
+ #endif /* ! __LINUX_SECURITY_H */
+ 
+diff --git a/include/linux/selinux.h b/include/linux/selinux.h
+index 8c2cc4c..20f965d 100644
+--- a/include/linux/selinux.h
++++ b/include/linux/selinux.h
+@@ -16,99 +16,11 @@
+ 
+ struct selinux_audit_rule;
+ struct audit_context;
+-struct inode;
+ struct kern_ipc_perm;
+ 
+ #ifdef CONFIG_SECURITY_SELINUX
+ 
+ /**
+- *	selinux_audit_rule_init - alloc/init an selinux audit rule structure.
+- *	@field: the field this rule refers to
+- *	@op: the operater the rule uses
+- *	@rulestr: the text "target" of the rule
+- *	@rule: pointer to the new rule structure returned via this
+- *
+- *	Returns 0 if successful, -errno if not.  On success, the rule structure
+- *	will be allocated internally.  The caller must free this structure with
+- *	selinux_audit_rule_free() after use.
+- */
+-int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+-                            struct selinux_audit_rule **rule);
+-
+-/**
+- *	selinux_audit_rule_free - free an selinux audit rule structure.
+- *	@rule: pointer to the audit rule to be freed
+- *
+- *	This will free all memory associated with the given rule.
+- *	If @rule is NULL, no operation is performed.
+- */
+-void selinux_audit_rule_free(struct selinux_audit_rule *rule);
+-
+-/**
+- *	selinux_audit_rule_match - determine if a context ID matches a rule.
+- *	@sid: the context ID to check
+- *	@field: the field this rule refers to
+- *	@op: the operater the rule uses
+- *	@rule: pointer to the audit rule to check against
+- *	@actx: the audit context (can be NULL) associated with the check
+- *
+- *	Returns 1 if the context id matches the rule, 0 if it does not, and
+- *	-errno on failure.
+- */
+-int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+-                             struct selinux_audit_rule *rule,
+-                             struct audit_context *actx);
+-
+-/**
+- *	selinux_audit_set_callback - set the callback for policy reloads.
+- *	@callback: the function to call when the policy is reloaded
+- *
+- *	This sets the function callback function that will update the rules
+- *	upon policy reloads.  This callback should rebuild all existing rules
+- *	using selinux_audit_rule_init().
+- */
+-void selinux_audit_set_callback(int (*callback)(void));
+-
+-/**
+- *     selinux_sid_to_string - map a security context ID to a string
+- *     @sid: security context ID to be converted.
+- *     @ctx: address of context string to be returned
+- *     @ctxlen: length of returned context string.
+- *
+- *     Returns 0 if successful, -errno if not.  On success, the context
+- *     string will be allocated internally, and the caller must call
+- *     kfree() on it after use.
+- */
+-int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen);
+-
+-/**
+- *     selinux_get_inode_sid - get the inode's security context ID
+- *     @inode: inode structure to get the sid from.
+- *     @sid: pointer to security context ID to be filled in.
+- *
+- *     Returns nothing
+- */
+-void selinux_get_inode_sid(const struct inode *inode, u32 *sid);
+-
+-/**
+- *     selinux_get_ipc_sid - get the ipc security context ID
+- *     @ipcp: ipc structure to get the sid from.
+- *     @sid: pointer to security context ID to be filled in.
+- *
+- *     Returns nothing
+- */
+-void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid);
+-
+-/**
+- *     selinux_get_task_sid - return the SID of task
+- *     @tsk: the task whose SID will be returned
+- *     @sid: pointer to security context ID to be filled in.
+- *
+- *     Returns nothing
+- */
+-void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
+-
+-/**
+  *     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.
+@@ -151,52 +63,6 @@ void selinux_secmark_refcount_inc(void);
+ void selinux_secmark_refcount_dec(void);
+ #else
+ 
+-static inline int selinux_audit_rule_init(u32 field, u32 op,
+-                                          char *rulestr,
+-                                          struct selinux_audit_rule **rule)
+-{
+-	return -EOPNOTSUPP;
+-}
+-
+-static inline void selinux_audit_rule_free(struct selinux_audit_rule *rule)
+-{
+-	return;
+-}
+-
+-static inline int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+-                                           struct selinux_audit_rule *rule,
+-                                           struct audit_context *actx)
+-{
+-	return 0;
+-}
+-
+-static inline void selinux_audit_set_callback(int (*callback)(void))
+-{
+-	return;
+-}
+-
+-static inline int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
+-{
+-       *ctx = NULL;
+-       *ctxlen = 0;
+-       return 0;
+-}
+-
+-static inline void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+-{
+-	*sid = 0;
+-}
+-
+-static inline void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
+-{
+-	*sid = 0;
+-}
+-
+-static inline void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+-{
+-	*sid = 0;
+-}
+-
+ static inline int selinux_string_to_sid(const char *str, u32 *sid)
+ {
+        *sid = 0;
+diff --git a/include/linux/semaphore.h b/include/linux/semaphore.h
+new file mode 100644
+index 0000000..9cae64b
+--- /dev/null
++++ b/include/linux/semaphore.h
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (c) 2008 Intel Corporation
++ * Author: Matthew Wilcox <willy at linux.intel.com>
++ *
++ * Distributed under the terms of the GNU GPL, version 2
++ *
++ * Please see kernel/semaphore.c for documentation of these functions
++ */
++#ifndef __LINUX_SEMAPHORE_H
++#define __LINUX_SEMAPHORE_H
++
++#include <linux/list.h>
++#include <linux/spinlock.h>
++
++/* Please don't access any members of this structure directly */
++struct semaphore {
++	spinlock_t		lock;
++	unsigned int		count;
++	struct list_head	wait_list;
++};
++
++#define __SEMAPHORE_INITIALIZER(name, n)				\
++{									\
++	.lock		= __SPIN_LOCK_UNLOCKED((name).lock),		\
++	.count		= n,						\
++	.wait_list	= LIST_HEAD_INIT((name).wait_list),		\
++}
++
++#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
++	struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
++
++#define DECLARE_MUTEX(name)	__DECLARE_SEMAPHORE_GENERIC(name, 1)
++
++static inline void sema_init(struct semaphore *sem, int val)
++{
++	static struct lock_class_key __key;
++	*sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
++	lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
++}
++
++#define init_MUTEX(sem)		sema_init(sem, 1)
++#define init_MUTEX_LOCKED(sem)	sema_init(sem, 0)
++
++extern void down(struct semaphore *sem);
++extern int __must_check down_interruptible(struct semaphore *sem);
++extern int __must_check down_killable(struct semaphore *sem);
++extern int __must_check down_trylock(struct semaphore *sem);
++extern int __must_check down_timeout(struct semaphore *sem, long jiffies);
++extern void up(struct semaphore *sem);
++
++#endif /* __LINUX_SEMAPHORE_H */
+diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
+index 67c2563..5b5369c 100644
+--- a/include/linux/seq_file.h
++++ b/include/linux/seq_file.h
+@@ -10,6 +10,7 @@ struct seq_operations;
+ struct file;
+ struct path;
+ struct inode;
++struct dentry;
+ 
+ struct seq_file {
+ 	char *buf;
+@@ -30,6 +31,8 @@ struct seq_operations {
+ 	int (*show) (struct seq_file *m, void *v);
+ };
+ 
++#define SEQ_SKIP 1
++
+ int seq_open(struct file *, const struct seq_operations *);
+ ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);
+ loff_t seq_lseek(struct file *, loff_t, int);
+@@ -42,6 +45,9 @@ int seq_printf(struct seq_file *, const char *, ...)
+ 	__attribute__ ((format (printf,2,3)));
+ 
+ int seq_path(struct seq_file *, struct path *, char *);
++int seq_dentry(struct seq_file *, struct dentry *, char *);
++int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
++		  char *esc);
+ 
+ int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
+ int single_release(struct inode *, struct file *);
+@@ -62,18 +68,5 @@ extern struct list_head *seq_list_start_head(struct list_head *head,
+ extern struct list_head *seq_list_next(void *v, struct list_head *head,
+ 		loff_t *ppos);
+ 
+-struct net;
+-struct seq_net_private {
+-	struct net *net;
+-};
+-
+-int seq_open_net(struct inode *, struct file *,
+-		 const struct seq_operations *, int);
+-int seq_release_net(struct inode *, struct file *);
+-static inline struct net *seq_file_net(struct seq_file *seq)
+-{
+-	return ((struct seq_net_private *)seq->private)->net;
+-}
+-
+ #endif
+ #endif
+diff --git a/include/linux/seq_file_net.h b/include/linux/seq_file_net.h
+new file mode 100644
+index 0000000..4ac5254
+--- /dev/null
++++ b/include/linux/seq_file_net.h
+@@ -0,0 +1,27 @@
++#ifndef __SEQ_FILE_NET_H__
++#define __SEQ_FILE_NET_H__
++
++#include <linux/seq_file.h>
++
++struct net;
++extern struct net init_net;
++
++struct seq_net_private {
++#ifdef CONFIG_NET_NS
++	struct net *net;
++#endif
++};
++
++int seq_open_net(struct inode *, struct file *,
++		 const struct seq_operations *, int);
++int seq_release_net(struct inode *, struct file *);
++static inline struct net *seq_file_net(struct seq_file *seq)
++{
++#ifdef CONFIG_NET_NS
++	return ((struct seq_net_private *)seq->private)->net;
++#else
++	return &init_net;
++#endif
++}
++
++#endif
+diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
+index 26e4925..632205c 100644
+--- a/include/linux/seqlock.h
++++ b/include/linux/seqlock.h
+@@ -85,23 +85,29 @@ static inline int write_tryseqlock(seqlock_t *sl)
+ /* Start of read calculation -- fetch last complete writer token */
+ static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
+ {
+-	unsigned ret = sl->sequence;
++	unsigned ret;
++
++repeat:
++	ret = sl->sequence;
+ 	smp_rmb();
++	if (unlikely(ret & 1)) {
++		cpu_relax();
++		goto repeat;
++	}
++
+ 	return ret;
+ }
+ 
+-/* Test if reader processed invalid data.
+- * If initial values is odd, 
+- *	then writer had already started when section was entered
+- * If sequence value changed
+- *	then writer changed data while in section
+- *    
+- * Using xor saves one conditional branch.
++/*
++ * Test if reader processed invalid data.
++ *
++ * If sequence value changed then writer changed data while in section.
+  */
+-static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv)
++static __always_inline int read_seqretry(const seqlock_t *sl, unsigned start)
+ {
+ 	smp_rmb();
+-	return (iv & 1) | (sl->sequence ^ iv);
++
++	return (sl->sequence != start);
+ }
+ 
+ 
+@@ -122,20 +128,26 @@ typedef struct seqcount {
+ /* Start of read using pointer to a sequence counter only.  */
+ static inline unsigned read_seqcount_begin(const seqcount_t *s)
+ {
+-	unsigned ret = s->sequence;
++	unsigned ret;
++
++repeat:
++	ret = s->sequence;
+ 	smp_rmb();
++	if (unlikely(ret & 1)) {
++		cpu_relax();
++		goto repeat;
++	}
+ 	return ret;
+ }
+ 
+-/* Test if reader processed invalid data.
+- * Equivalent to: iv is odd or sequence number has changed.
+- *                (iv & 1) || (*s != iv)
+- * Using xor saves one conditional branch.
++/*
++ * Test if reader processed invalid data because sequence number has changed.
+  */
+-static inline int read_seqcount_retry(const seqcount_t *s, unsigned iv)
++static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
+ {
+ 	smp_rmb();
+-	return (iv & 1) | (s->sequence ^ iv);
++
++	return s->sequence != start;
+ }
+ 
+ 
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index 289942f..7cb094a 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -213,6 +213,10 @@ struct uart_ops {
+ 	void		(*config_port)(struct uart_port *, int);
+ 	int		(*verify_port)(struct uart_port *, struct serial_struct *);
+ 	int		(*ioctl)(struct uart_port *, unsigned int, unsigned long);
++#ifdef CONFIG_CONSOLE_POLL
++	void	(*poll_put_char)(struct uart_port *, unsigned char);
++	int		(*poll_get_char)(struct uart_port *);
++#endif
+ };
+ 
+ #define UART_CONFIG_TYPE	(1 << 0)
+diff --git a/include/linux/serio.h b/include/linux/serio.h
+index 9f38250..95674d9 100644
+--- a/include/linux/serio.h
++++ b/include/linux/serio.h
+@@ -211,5 +211,6 @@ static inline void serio_unpin_driver(struct serio *serio)
+ #define SERIO_TOUCHWIN	0x33
+ #define SERIO_TAOSEVM	0x34
+ #define SERIO_FUJITSU	0x35
++#define SERIO_ZHENHUA	0x36
+ 
+ #endif
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index bbd8d00..299ec4b 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -242,6 +242,7 @@ typedef unsigned char *sk_buff_data_t;
+  *	@queue_mapping: Queue mapping for multiqueue devices
+  *	@tc_index: Traffic control index
+  *	@tc_verd: traffic control verdict
++ *	@ndisc_nodetype: router type (from link layer)
+  *	@dma_cookie: a cookie to one of several possible DMA operations
+  *		done by skb DMA functions
+  *	@secmark: security marking
+@@ -256,7 +257,10 @@ struct sk_buff {
+ 	ktime_t			tstamp;
+ 	struct net_device	*dev;
+ 
+-	struct  dst_entry	*dst;
++	union {
++		struct  dst_entry	*dst;
++		struct  rtable		*rtable;
++	};
+ 	struct	sec_path	*sp;
+ 
+ 	/*
+@@ -310,7 +314,10 @@ struct sk_buff {
+ 	__u16			tc_verd;	/* traffic control verdict */
+ #endif
+ #endif
+-	/* 2 byte hole */
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++	__u8			ndisc_nodetype:2;
++#endif
++	/* 14 bit hole */
+ 
+ #ifdef CONFIG_NET_DMA
+ 	dma_cookie_t		dma_cookie;
+@@ -657,11 +664,21 @@ static inline void skb_queue_head_init_class(struct sk_buff_head *list,
+ }
+ 
+ /*
+- *	Insert an sk_buff at the start of a list.
++ *	Insert an sk_buff on a list.
+  *
+  *	The "__skb_xxxx()" functions are the non-atomic ones that
+  *	can only be called with interrupts disabled.
+  */
++extern void        skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
++static inline void __skb_insert(struct sk_buff *newsk,
++				struct sk_buff *prev, struct sk_buff *next,
++				struct sk_buff_head *list)
++{
++	newsk->next = next;
++	newsk->prev = prev;
++	next->prev  = prev->next = newsk;
++	list->qlen++;
++}
+ 
+ /**
+  *	__skb_queue_after - queue a buffer at the list head
+@@ -678,13 +695,17 @@ static inline void __skb_queue_after(struct sk_buff_head *list,
+ 				     struct sk_buff *prev,
+ 				     struct sk_buff *newsk)
+ {
+-	struct sk_buff *next;
+-	list->qlen++;
++	__skb_insert(newsk, prev, prev->next, list);
++}
+ 
+-	next = prev->next;
+-	newsk->next = next;
+-	newsk->prev = prev;
+-	next->prev  = prev->next = newsk;
++extern void skb_append(struct sk_buff *old, struct sk_buff *newsk,
++		       struct sk_buff_head *list);
++
++static inline void __skb_queue_before(struct sk_buff_head *list,
++				      struct sk_buff *next,
++				      struct sk_buff *newsk)
++{
++	__skb_insert(newsk, next->prev, next, list);
+ }
+ 
+ /**
+@@ -718,66 +739,7 @@ extern void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk);
+ static inline void __skb_queue_tail(struct sk_buff_head *list,
+ 				   struct sk_buff *newsk)
+ {
+-	struct sk_buff *prev, *next;
+-
+-	list->qlen++;
+-	next = (struct sk_buff *)list;
+-	prev = next->prev;
+-	newsk->next = next;
+-	newsk->prev = prev;
+-	next->prev  = prev->next = newsk;
+-}
+-
+-
+-/**
+- *	__skb_dequeue - remove from the head of the queue
+- *	@list: list to dequeue from
+- *
+- *	Remove the head of the list. This function does not take any locks
+- *	so must be used with appropriate locks held only. The head item is
+- *	returned or %NULL if the list is empty.
+- */
+-extern struct sk_buff *skb_dequeue(struct sk_buff_head *list);
+-static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
+-{
+-	struct sk_buff *next, *prev, *result;
+-
+-	prev = (struct sk_buff *) list;
+-	next = prev->next;
+-	result = NULL;
+-	if (next != prev) {
+-		result	     = next;
+-		next	     = next->next;
+-		list->qlen--;
+-		next->prev   = prev;
+-		prev->next   = next;
+-		result->next = result->prev = NULL;
+-	}
+-	return result;
+-}
+-
+-
+-/*
+- *	Insert a packet on a list.
+- */
+-extern void        skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
+-static inline void __skb_insert(struct sk_buff *newsk,
+-				struct sk_buff *prev, struct sk_buff *next,
+-				struct sk_buff_head *list)
+-{
+-	newsk->next = next;
+-	newsk->prev = prev;
+-	next->prev  = prev->next = newsk;
+-	list->qlen++;
+-}
+-
+-/*
+- *	Place a packet after a given packet in a list.
+- */
+-extern void	   skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
+-static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
+-{
+-	__skb_insert(newsk, old, old->next, list);
++	__skb_queue_before(list, (struct sk_buff *)list, newsk);
+ }
+ 
+ /*
+@@ -797,8 +759,22 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
+ 	prev->next = next;
+ }
+ 
+-
+-/* XXX: more streamlined implementation */
++/**
++ *	__skb_dequeue - remove from the head of the queue
++ *	@list: list to dequeue from
++ *
++ *	Remove the head of the list. This function does not take any locks
++ *	so must be used with appropriate locks held only. The head item is
++ *	returned or %NULL if the list is empty.
++ */
++extern struct sk_buff *skb_dequeue(struct sk_buff_head *list);
++static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
++{
++	struct sk_buff *skb = skb_peek(list);
++	if (skb)
++		__skb_unlink(skb, list);
++	return skb;
++}
+ 
+ /**
+  *	__skb_dequeue_tail - remove from the tail of the queue
+@@ -889,6 +865,7 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
+ /*
+  *	Add data to an sk_buff
+  */
++extern unsigned char *skb_put(struct sk_buff *skb, unsigned int len);
+ static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+ {
+ 	unsigned char *tmp = skb_tail_pointer(skb);
+@@ -898,26 +875,7 @@ static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+ 	return tmp;
+ }
+ 
+-/**
+- *	skb_put - add data to a buffer
+- *	@skb: buffer to use
+- *	@len: amount of data to add
+- *
+- *	This function extends the used data area of the buffer. If this would
+- *	exceed the total buffer size the kernel will panic. A pointer to the
+- *	first byte of the extra data is returned.
+- */
+-static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
+-{
+-	unsigned char *tmp = skb_tail_pointer(skb);
+-	SKB_LINEAR_ASSERT(skb);
+-	skb->tail += len;
+-	skb->len  += len;
+-	if (unlikely(skb->tail > skb->end))
+-		skb_over_panic(skb, len, current_text_addr());
+-	return tmp;
+-}
+-
++extern unsigned char *skb_push(struct sk_buff *skb, unsigned int len);
+ static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+ {
+ 	skb->data -= len;
+@@ -925,24 +883,7 @@ static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+ 	return skb->data;
+ }
+ 
+-/**
+- *	skb_push - add data to the start of a buffer
+- *	@skb: buffer to use
+- *	@len: amount of data to add
+- *
+- *	This function extends the used data area of the buffer at the buffer
+- *	start. If this would exceed the total buffer headroom the kernel will
+- *	panic. A pointer to the first byte of the extra data is returned.
+- */
+-static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
+-{
+-	skb->data -= len;
+-	skb->len  += len;
+-	if (unlikely(skb->data<skb->head))
+-		skb_under_panic(skb, len, current_text_addr());
+-	return skb->data;
+-}
+-
++extern unsigned char *skb_pull(struct sk_buff *skb, unsigned int len);
+ static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
+ {
+ 	skb->len -= len;
+@@ -950,21 +891,6 @@ static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
+ 	return skb->data += len;
+ }
+ 
+-/**
+- *	skb_pull - remove data from the start of a buffer
+- *	@skb: buffer to use
+- *	@len: amount of data to remove
+- *
+- *	This function removes data from the start of a buffer, returning
+- *	the memory to the headroom. A pointer to the next data in the buffer
+- *	is returned. Once the data has been pulled future pushes will overwrite
+- *	the old data.
+- */
+-static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
+-{
+-	return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
+-}
+-
+ extern unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta);
+ 
+ static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len)
+@@ -1205,21 +1131,7 @@ static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
+ 	skb_set_tail_pointer(skb, len);
+ }
+ 
+-/**
+- *	skb_trim - remove end from a buffer
+- *	@skb: buffer to alter
+- *	@len: new length
+- *
+- *	Cut the length of a buffer down by removing data from the tail. If
+- *	the buffer is already under the length specified it is not modified.
+- *	The skb must be linear.
+- */
+-static inline void skb_trim(struct sk_buff *skb, unsigned int len)
+-{
+-	if (skb->len > len)
+-		__skb_trim(skb, len);
+-}
+-
++extern void skb_trim(struct sk_buff *skb, unsigned int len);
+ 
+ static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
+ {
+@@ -1302,22 +1214,7 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
+ 	return skb;
+ }
+ 
+-/**
+- *	dev_alloc_skb - allocate an skbuff for receiving
+- *	@length: length to allocate
+- *
+- *	Allocate a new &sk_buff and assign it a usage count of one. The
+- *	buffer has unspecified headroom built in. Users should allocate
+- *	the headroom they think they need without accounting for the
+- *	built in space. The built in space is used for optimisations.
+- *
+- *	%NULL is returned if there is no free memory. Although this function
+- *	allocates memory it can be called from an interrupt.
+- */
+-static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+-{
+-	return __dev_alloc_skb(length, GFP_ATOMIC);
+-}
++extern struct sk_buff *dev_alloc_skb(unsigned int length);
+ 
+ extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
+ 		unsigned int length, gfp_t gfp_mask);
+diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
+index b00c1c7..79d59c9 100644
+--- a/include/linux/slub_def.h
++++ b/include/linux/slub_def.h
+@@ -45,9 +45,9 @@ struct kmem_cache_cpu {
+ struct kmem_cache_node {
+ 	spinlock_t list_lock;	/* Protect partial list and nr_partial */
+ 	unsigned long nr_partial;
+-	atomic_long_t nr_slabs;
+ 	struct list_head partial;
+ #ifdef CONFIG_SLUB_DEBUG
++	atomic_long_t nr_slabs;
+ 	struct list_head full;
+ #endif
+ };
+diff --git a/include/linux/smc91x.h b/include/linux/smc91x.h
+new file mode 100644
+index 0000000..8e0556b
+--- /dev/null
++++ b/include/linux/smc91x.h
+@@ -0,0 +1,13 @@
++#ifndef __SMC91X_H__
++#define __SMC91X_H__
++
++#define SMC91X_USE_8BIT (1 << 0)
++#define SMC91X_USE_16BIT (1 << 1)
++#define SMC91X_USE_32BIT (1 << 2)
++
++struct smc91x_platdata {
++	unsigned long flags;
++	unsigned long irq_flags; /* IRQF_... */
++};
++
++#endif /* __SMC91X_H__ */
+diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
+index 334d314..daf7440 100644
+--- a/include/linux/spi/ads7846.h
++++ b/include/linux/spi/ads7846.h
+@@ -14,7 +14,8 @@ enum ads7846_filter {
+ struct ads7846_platform_data {
+ 	u16	model;			/* 7843, 7845, 7846. */
+ 	u16	vref_delay_usecs;	/* 0 for external vref; etc */
+-	int	keep_vref_on:1;		/* set to keep vref on for differential
++	u16	vref_mv;		/* external vref value, milliVolts */
++	bool	keep_vref_on;		/* set to keep vref on for differential
+ 					 * measurements as well */
+ 
+ 	/* Settling time of the analog signals; a function of Vcc and the
+diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
+index 1129ee0..d311a09 100644
+--- a/include/linux/spinlock.h
++++ b/include/linux/spinlock.h
+@@ -296,43 +296,6 @@ do {						\
+ })
+ 
+ /*
+- * Locks two spinlocks l1 and l2.
+- * l1_first indicates if spinlock l1 should be taken first.
+- */
+-static inline void double_spin_lock(spinlock_t *l1, spinlock_t *l2,
+-				    bool l1_first)
+-	__acquires(l1)
+-	__acquires(l2)
+-{
+-	if (l1_first) {
+-		spin_lock(l1);
+-		spin_lock(l2);
+-	} else {
+-		spin_lock(l2);
+-		spin_lock(l1);
+-	}
+-}
+-
+-/*
+- * Unlocks two spinlocks l1 and l2.
+- * l1_taken_first indicates if spinlock l1 was taken first and therefore
+- * should be released after spinlock l2.
+- */
+-static inline void double_spin_unlock(spinlock_t *l1, spinlock_t *l2,
+-				      bool l1_taken_first)
+-	__releases(l1)
+-	__releases(l2)
+-{
+-	if (l1_taken_first) {
+-		spin_unlock(l2);
+-		spin_unlock(l1);
+-	} else {
+-		spin_unlock(l1);
+-		spin_unlock(l2);
+-	}
+-}
+-
+-/*
+  * Pull the atomic_t declaration:
+  * (asm-mips/atomic.h needs above definitions)
+  */
+diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
+index db53def..50dfd0d 100644
+--- a/include/linux/ssb/ssb.h
++++ b/include/linux/ssb/ssb.h
+@@ -72,10 +72,18 @@ struct ssb_device;
+ /* Lowlevel read/write operations on the device MMIO.
+  * Internal, don't use that outside of ssb. */
+ struct ssb_bus_ops {
++	u8 (*read8)(struct ssb_device *dev, u16 offset);
+ 	u16 (*read16)(struct ssb_device *dev, u16 offset);
+ 	u32 (*read32)(struct ssb_device *dev, u16 offset);
++	void (*write8)(struct ssb_device *dev, u16 offset, u8 value);
+ 	void (*write16)(struct ssb_device *dev, u16 offset, u16 value);
+ 	void (*write32)(struct ssb_device *dev, u16 offset, u32 value);
++#ifdef CONFIG_SSB_BLOCKIO
++	void (*block_read)(struct ssb_device *dev, void *buffer,
++			   size_t count, u16 offset, u8 reg_width);
++	void (*block_write)(struct ssb_device *dev, const void *buffer,
++			    size_t count, u16 offset, u8 reg_width);
++#endif
+ };
+ 
+ 
+@@ -247,9 +255,9 @@ struct ssb_bus {
+ 	/* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */
+ 	struct pcmcia_device *host_pcmcia;
+ 
+-#ifdef CONFIG_SSB_PCIHOST
++#ifdef CONFIG_SSB_SPROM
+ 	/* Mutex to protect the SPROM writing. */
+-	struct mutex pci_sprom_mutex;
++	struct mutex sprom_mutex;
+ #endif
+ 
+ 	/* ID information about the Chip. */
+@@ -262,9 +270,6 @@ struct ssb_bus {
+ 	struct ssb_device devices[SSB_MAX_NR_CORES];
+ 	u8 nr_devices;
+ 
+-	/* Reference count. Number of suspended devices. */
+-	u8 suspend_cnt;
+-
+ 	/* Software ID number for this bus. */
+ 	unsigned int busnumber;
+ 
+@@ -336,6 +341,13 @@ extern int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
+ 
+ extern void ssb_bus_unregister(struct ssb_bus *bus);
+ 
++/* Suspend a SSB bus.
++ * Call this from the parent bus suspend routine. */
++extern int ssb_bus_suspend(struct ssb_bus *bus);
++/* Resume a SSB bus.
++ * Call this from the parent bus resume routine. */
++extern int ssb_bus_resume(struct ssb_bus *bus);
++
+ extern u32 ssb_clockspeed(struct ssb_bus *bus);
+ 
+ /* Is the device enabled in hardware? */
+@@ -348,6 +360,10 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags);
+ 
+ 
+ /* Device MMIO register read/write functions. */
++static inline u8 ssb_read8(struct ssb_device *dev, u16 offset)
++{
++	return dev->ops->read8(dev, offset);
++}
+ static inline u16 ssb_read16(struct ssb_device *dev, u16 offset)
+ {
+ 	return dev->ops->read16(dev, offset);
+@@ -356,6 +372,10 @@ static inline u32 ssb_read32(struct ssb_device *dev, u16 offset)
+ {
+ 	return dev->ops->read32(dev, offset);
+ }
++static inline void ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++	dev->ops->write8(dev, offset, value);
++}
+ static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
+ {
+ 	dev->ops->write16(dev, offset, value);
+@@ -364,6 +384,19 @@ static inline void ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
+ {
+ 	dev->ops->write32(dev, offset, value);
+ }
++#ifdef CONFIG_SSB_BLOCKIO
++static inline void ssb_block_read(struct ssb_device *dev, void *buffer,
++				  size_t count, u16 offset, u8 reg_width)
++{
++	dev->ops->block_read(dev, buffer, count, offset, reg_width);
++}
++
++static inline void ssb_block_write(struct ssb_device *dev, const void *buffer,
++				   size_t count, u16 offset, u8 reg_width)
++{
++	dev->ops->block_write(dev, buffer, count, offset, reg_width);
++}
++#endif /* CONFIG_SSB_BLOCKIO */
+ 
+ 
+ /* Translation (routing) bits that need to be ORed to DMA
+@@ -416,5 +449,12 @@ extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl);
+ extern u32 ssb_admatch_base(u32 adm);
+ extern u32 ssb_admatch_size(u32 adm);
+ 
++/* PCI device mapping and fixup routines.
++ * Called from the architecture pcibios init code.
++ * These are only available on SSB_EMBEDDED configurations. */
++#ifdef CONFIG_SSB_EMBEDDED
++int ssb_pcibios_plat_dev_init(struct pci_dev *dev);
++int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
++#endif /* CONFIG_SSB_EMBEDDED */
+ 
+ #endif /* LINUX_SSB_H_ */
+diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
+index 536851b..7d7e03d 100644
+--- a/include/linux/ssb/ssb_driver_chipcommon.h
++++ b/include/linux/ssb/ssb_driver_chipcommon.h
+@@ -367,8 +367,7 @@ static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)
+ 
+ extern void ssb_chipcommon_init(struct ssb_chipcommon *cc);
+ 
+-#include <linux/pm.h>
+-extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state);
++extern void ssb_chipco_suspend(struct ssb_chipcommon *cc);
+ extern void ssb_chipco_resume(struct ssb_chipcommon *cc);
+ 
+ extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
+@@ -390,6 +389,10 @@ extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
+ extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
+ 					  u32 ticks);
+ 
++void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value);
++
++u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask);
++
+ /* Chipcommon GPIO pin access. */
+ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask);
+ u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value);
+diff --git a/include/linux/ssb/ssb_driver_gige.h b/include/linux/ssb/ssb_driver_gige.h
+new file mode 100644
+index 0000000..01fbdf5
+--- /dev/null
++++ b/include/linux/ssb/ssb_driver_gige.h
+@@ -0,0 +1,174 @@
++#ifndef LINUX_SSB_DRIVER_GIGE_H_
++#define LINUX_SSB_DRIVER_GIGE_H_
++
++#include <linux/ssb/ssb.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++
++
++#ifdef CONFIG_SSB_DRIVER_GIGE
++
++
++#define SSB_GIGE_PCIIO			0x0000 /* PCI I/O Registers (1024 bytes) */
++#define SSB_GIGE_RESERVED		0x0400 /* Reserved (1024 bytes) */
++#define SSB_GIGE_PCICFG			0x0800 /* PCI config space (256 bytes) */
++#define SSB_GIGE_SHIM_FLUSHSTAT		0x0C00 /* PCI to OCP: Flush status control (32bit) */
++#define SSB_GIGE_SHIM_FLUSHRDA		0x0C04 /* PCI to OCP: Flush read address (32bit) */
++#define SSB_GIGE_SHIM_FLUSHTO		0x0C08 /* PCI to OCP: Flush timeout counter (32bit) */
++#define SSB_GIGE_SHIM_BARRIER		0x0C0C /* PCI to OCP: Barrier register (32bit) */
++#define SSB_GIGE_SHIM_MAOCPSI		0x0C10 /* PCI to OCP: MaocpSI Control (32bit) */
++#define SSB_GIGE_SHIM_SIOCPMA		0x0C14 /* PCI to OCP: SiocpMa Control (32bit) */
++
++/* TM Status High flags */
++#define SSB_GIGE_TMSHIGH_RGMII		0x00010000 /* Have an RGMII PHY-bus */
++/* TM Status Low flags */
++#define SSB_GIGE_TMSLOW_TXBYPASS	0x00080000 /* TX bypass (no delay) */
++#define SSB_GIGE_TMSLOW_RXBYPASS	0x00100000 /* RX bypass (no delay) */
++#define SSB_GIGE_TMSLOW_DLLEN		0x01000000 /* Enable DLL controls */
++
++/* Boardflags (low) */
++#define SSB_GIGE_BFL_ROBOSWITCH		0x0010
++
++
++#define SSB_GIGE_MEM_RES_NAME		"SSB Broadcom 47xx GigE memory"
++#define SSB_GIGE_IO_RES_NAME		"SSB Broadcom 47xx GigE I/O"
++
++struct ssb_gige {
++	struct ssb_device *dev;
++
++	spinlock_t lock;
++
++	/* True, if the device has an RGMII bus.
++	 * False, if the device has a GMII bus. */
++	bool has_rgmii;
++
++	/* The PCI controller device. */
++	struct pci_controller pci_controller;
++	struct pci_ops pci_ops;
++	struct resource mem_resource;
++	struct resource io_resource;
++};
++
++/* Check whether a PCI device is a SSB Gigabit Ethernet core. */
++extern bool pdev_is_ssb_gige_core(struct pci_dev *pdev);
++
++/* Convert a pci_dev pointer to a ssb_gige pointer. */
++static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
++{
++	if (!pdev_is_ssb_gige_core(pdev))
++		return NULL;
++	return container_of(pdev->bus->ops, struct ssb_gige, pci_ops);
++}
++
++/* Returns whether the PHY is connected by an RGMII bus. */
++static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
++{
++	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
++	return (dev ? dev->has_rgmii : 0);
++}
++
++/* Returns whether we have a Roboswitch. */
++static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
++{
++	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
++	if (dev)
++		return !!(dev->dev->bus->sprom.boardflags_lo &
++			  SSB_GIGE_BFL_ROBOSWITCH);
++	return 0;
++}
++
++/* Returns whether we can only do one DMA at once. */
++static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
++{
++	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
++	if (dev)
++		return ((dev->dev->bus->chip_id == 0x4785) &&
++			(dev->dev->bus->chip_rev < 2));
++	return 0;
++}
++
++/* Returns whether we must flush posted writes. */
++static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
++{
++	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
++	if (dev)
++		return (dev->dev->bus->chip_id == 0x4785);
++	return 0;
++}
++
++extern char * nvram_get(const char *name);
++/* Get the device MAC address */
++static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
++{
++#ifdef CONFIG_BCM947XX
++	char *res = nvram_get("et0macaddr");
++	if (res)
++		memcpy(macaddr, res, 6);
++#endif
++}
++
++extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
++					  struct pci_dev *pdev);
++extern int ssb_gige_map_irq(struct ssb_device *sdev,
++			    const struct pci_dev *pdev);
++
++/* The GigE driver is not a standalone module, because we don't have support
++ * for unregistering the driver. So we could not unload the module anyway. */
++extern int ssb_gige_init(void);
++static inline void ssb_gige_exit(void)
++{
++	/* Currently we can not unregister the GigE driver,
++	 * because we can not unregister the PCI bridge. */
++	BUG();
++}
++
++
++#else /* CONFIG_SSB_DRIVER_GIGE */
++/* Gigabit Ethernet driver disabled */
++
++
++static inline int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
++						 struct pci_dev *pdev)
++{
++	return -ENOSYS;
++}
++static inline int ssb_gige_map_irq(struct ssb_device *sdev,
++				   const struct pci_dev *pdev)
++{
++	return -ENOSYS;
++}
++static inline int ssb_gige_init(void)
++{
++	return 0;
++}
++static inline void ssb_gige_exit(void)
++{
++}
++
++static inline bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
++{
++	return 0;
++}
++static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
++{
++	return NULL;
++}
++static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
++{
++	return 0;
++}
++static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
++{
++	return 0;
++}
++static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
++{
++	return 0;
++}
++static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
++{
++	return 0;
++}
++
++#endif /* CONFIG_SSB_DRIVER_GIGE */
++#endif /* LINUX_SSB_DRIVER_GIGE_H_ */
+diff --git a/include/linux/ssb/ssb_driver_pci.h b/include/linux/ssb/ssb_driver_pci.h
+index 5e25bac..41e330e 100644
+--- a/include/linux/ssb/ssb_driver_pci.h
++++ b/include/linux/ssb/ssb_driver_pci.h
+@@ -1,6 +1,11 @@
+ #ifndef LINUX_SSB_PCICORE_H_
+ #define LINUX_SSB_PCICORE_H_
+ 
++#include <linux/types.h>
++
++struct pci_dev;
++
++
+ #ifdef CONFIG_SSB_DRIVER_PCICORE
+ 
+ /* PCI core registers. */
+@@ -88,6 +93,9 @@ extern void ssb_pcicore_init(struct ssb_pcicore *pc);
+ extern int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
+ 					  struct ssb_device *dev);
+ 
++int ssb_pcicore_plat_dev_init(struct pci_dev *d);
++int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
++
+ 
+ #else /* CONFIG_SSB_DRIVER_PCICORE */
+ 
+@@ -107,5 +115,16 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
+ 	return 0;
+ }
+ 
++static inline
++int ssb_pcicore_plat_dev_init(struct pci_dev *d)
++{
++	return -ENODEV;
++}
++static inline
++int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++	return -ENODEV;
++}
++
+ #endif /* CONFIG_SSB_DRIVER_PCICORE */
+ #endif /* LINUX_SSB_PCICORE_H_ */
+diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
+index 7a69ca3..3f63218 100644
+--- a/include/linux/sunrpc/auth.h
++++ b/include/linux/sunrpc/auth.h
+@@ -26,6 +26,7 @@ struct auth_cred {
+ 	uid_t	uid;
+ 	gid_t	gid;
+ 	struct group_info *group_info;
++	unsigned char machine_cred : 1;
+ };
+ 
+ /*
+@@ -59,8 +60,8 @@ struct rpc_cred {
+ /*
+  * Client authentication handle
+  */
+-#define RPC_CREDCACHE_NR	8
+-#define RPC_CREDCACHE_MASK	(RPC_CREDCACHE_NR - 1)
++#define RPC_CREDCACHE_HASHBITS	4
++#define RPC_CREDCACHE_NR	(1 << RPC_CREDCACHE_HASHBITS)
+ struct rpc_cred_cache {
+ 	struct hlist_head	hashtable[RPC_CREDCACHE_NR];
+ 	spinlock_t		lock;
+@@ -89,7 +90,6 @@ struct rpc_auth {
+ 
+ /* Flags for rpcauth_lookupcred() */
+ #define RPCAUTH_LOOKUP_NEW		0x01	/* Accept an uninitialised cred */
+-#define RPCAUTH_LOOKUP_ROOTCREDS	0x02	/* This really ought to go! */
+ 
+ /*
+  * Client authentication ops
+@@ -97,9 +97,7 @@ struct rpc_auth {
+ struct rpc_authops {
+ 	struct module		*owner;
+ 	rpc_authflavor_t	au_flavor;	/* flavor (RPC_AUTH_*) */
+-#ifdef RPC_DEBUG
+ 	char *			au_name;
+-#endif
+ 	struct rpc_auth *	(*create)(struct rpc_clnt *, rpc_authflavor_t);
+ 	void			(*destroy)(struct rpc_auth *);
+ 
+@@ -113,6 +111,7 @@ struct rpc_credops {
+ 	void			(*crdestroy)(struct rpc_cred *);
+ 
+ 	int			(*crmatch)(struct auth_cred *, struct rpc_cred *, int);
++	void			(*crbind)(struct rpc_task *, struct rpc_cred *);
+ 	__be32 *		(*crmarshal)(struct rpc_task *, __be32 *);
+ 	int			(*crrefresh)(struct rpc_task *);
+ 	__be32 *		(*crvalidate)(struct rpc_task *, __be32 *);
+@@ -126,9 +125,13 @@ extern const struct rpc_authops	authunix_ops;
+ extern const struct rpc_authops	authnull_ops;
+ 
+ void __init		rpc_init_authunix(void);
++void __init		rpc_init_generic_auth(void);
+ void __init		rpcauth_init_module(void);
+ void __exit		rpcauth_remove_module(void);
++void __exit		rpc_destroy_generic_auth(void);
+ 
++struct rpc_cred *	rpc_lookup_cred(void);
++struct rpc_cred *	rpc_lookup_machine_cred(void);
+ int			rpcauth_register(const struct rpc_authops *);
+ int			rpcauth_unregister(const struct rpc_authops *);
+ struct rpc_auth *	rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
+@@ -136,8 +139,8 @@ void			rpcauth_release(struct rpc_auth *);
+ struct rpc_cred *	rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
+ void			rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
+ struct rpc_cred *	rpcauth_lookupcred(struct rpc_auth *, int);
+-struct rpc_cred *	rpcauth_bindcred(struct rpc_task *);
+-void			rpcauth_holdcred(struct rpc_task *);
++void			rpcauth_bindcred(struct rpc_task *, struct rpc_cred *, int);
++void			rpcauth_generic_bind_cred(struct rpc_task *, struct rpc_cred *);
+ void			put_rpccred(struct rpc_cred *);
+ void			rpcauth_unbindcred(struct rpc_task *);
+ __be32 *		rpcauth_marshcred(struct rpc_task *, __be32 *);
+diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
+index 67658e1..fec6899 100644
+--- a/include/linux/sunrpc/auth_gss.h
++++ b/include/linux/sunrpc/auth_gss.h
+@@ -84,6 +84,7 @@ struct gss_cred {
+ 	enum rpc_gss_svc	gc_service;
+ 	struct gss_cl_ctx	*gc_ctx;
+ 	struct gss_upcall_msg	*gc_upcall;
++	unsigned char		gc_machine_cred : 1;
+ };
+ 
+ #endif /* __KERNEL__ */
+diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
+index 03547d6..2d8b211 100644
+--- a/include/linux/sunrpc/cache.h
++++ b/include/linux/sunrpc/cache.h
+@@ -120,7 +120,6 @@ struct cache_deferred_req {
+ 	struct list_head	hash;	/* on hash chain */
+ 	struct list_head	recent; /* on fifo */
+ 	struct cache_head	*item;  /* cache item we wait on */
+-	time_t			recv_time;
+ 	void			*owner; /* we might need to discard all defered requests
+ 					 * owned by someone */
+ 	void			(*revisit)(struct cache_deferred_req *req,
+diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
+index 129a86e..6fff7f8 100644
+--- a/include/linux/sunrpc/clnt.h
++++ b/include/linux/sunrpc/clnt.h
+@@ -127,11 +127,12 @@ int		rpcb_getport_sync(struct sockaddr_in *, u32, u32, int);
+ void		rpcb_getport_async(struct rpc_task *);
+ 
+ void		rpc_call_start(struct rpc_task *);
+-int		rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg,
+-			       int flags, const struct rpc_call_ops *tk_ops,
++int		rpc_call_async(struct rpc_clnt *clnt,
++			       const struct rpc_message *msg, int flags,
++			       const struct rpc_call_ops *tk_ops,
+ 			       void *calldata);
+-int		rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
+-			      int flags);
++int		rpc_call_sync(struct rpc_clnt *clnt,
++			      const struct rpc_message *msg, int flags);
+ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
+ 			       int flags);
+ void		rpc_restart_call(struct rpc_task *);
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 5a4b1e0..a10f1fb 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -70,8 +70,6 @@ enum seal_alg {
+ 	SEAL_ALG_DES3KD = 0x0002
+ };
+ 
+-#define KRB5_CKSUM_LENGTH 8
+-
+ #define CKSUMTYPE_CRC32			0x0001
+ #define CKSUMTYPE_RSA_MD4		0x0002
+ #define CKSUMTYPE_RSA_MD4_DES		0x0003
+@@ -150,9 +148,9 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *inbuf,
+ s32
+ krb5_make_seq_num(struct crypto_blkcipher *key,
+ 		int direction,
+-		s32 seqnum, unsigned char *cksum, unsigned char *buf);
++		u32 seqnum, unsigned char *cksum, unsigned char *buf);
+ 
+ s32
+ krb5_get_seq_num(struct crypto_blkcipher *key,
+ 	       unsigned char *cksum,
+-	       unsigned char *buf, int *direction, s32 * seqnum);
++	       unsigned char *buf, int *direction, u32 *seqnum);
+diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
+index f689f02..d1a5c8c 100644
+--- a/include/linux/sunrpc/sched.h
++++ b/include/linux/sunrpc/sched.h
+@@ -11,7 +11,6 @@
+ 
+ #include <linux/timer.h>
+ #include <linux/sunrpc/types.h>
+-#include <linux/rcupdate.h>
+ #include <linux/spinlock.h>
+ #include <linux/wait.h>
+ #include <linux/workqueue.h>
+@@ -33,7 +32,8 @@ struct rpc_wait_queue;
+ struct rpc_wait {
+ 	struct list_head	list;		/* wait queue links */
+ 	struct list_head	links;		/* Links to related tasks */
+-	struct rpc_wait_queue *	rpc_waitq;	/* RPC wait queue we're on */
++	struct list_head	timer_list;	/* Timer list */
++	unsigned long		expires;
+ };
+ 
+ /*
+@@ -57,33 +57,25 @@ struct rpc_task {
+ 	__u8			tk_cred_retry;
+ 
+ 	/*
+-	 * timeout_fn   to be executed by timer bottom half
+ 	 * callback	to be executed after waking up
+ 	 * action	next procedure for async tasks
+ 	 * tk_ops	caller callbacks
+ 	 */
+-	void			(*tk_timeout_fn)(struct rpc_task *);
+ 	void			(*tk_callback)(struct rpc_task *);
+ 	void			(*tk_action)(struct rpc_task *);
+ 	const struct rpc_call_ops *tk_ops;
+ 	void *			tk_calldata;
+ 
+-	/*
+-	 * tk_timer is used for async processing by the RPC scheduling
+-	 * primitives. You should not access this directly unless
+-	 * you have a pathological interest in kernel oopses.
+-	 */
+-	struct timer_list	tk_timer;	/* kernel timer */
+ 	unsigned long		tk_timeout;	/* timeout for rpc_sleep() */
+ 	unsigned short		tk_flags;	/* misc flags */
+ 	unsigned long		tk_runstate;	/* Task run status */
+ 	struct workqueue_struct	*tk_workqueue;	/* Normally rpciod, but could
+ 						 * be any workqueue
+ 						 */
++	struct rpc_wait_queue 	*tk_waitqueue;	/* RPC wait queue we're on */
+ 	union {
+ 		struct work_struct	tk_work;	/* Async task work queue */
+ 		struct rpc_wait		tk_wait;	/* RPC wait */
+-		struct rcu_head		tk_rcu;		/* for task deletion */
+ 	} u;
+ 
+ 	unsigned short		tk_timeouts;	/* maj timeouts */
+@@ -123,6 +115,7 @@ struct rpc_task_setup {
+ 	const struct rpc_message *rpc_message;
+ 	const struct rpc_call_ops *callback_ops;
+ 	void *callback_data;
++	struct workqueue_struct *workqueue;
+ 	unsigned short flags;
+ 	signed char priority;
+ };
+@@ -147,9 +140,7 @@ struct rpc_task_setup {
+ 
+ #define RPC_TASK_RUNNING	0
+ #define RPC_TASK_QUEUED		1
+-#define RPC_TASK_WAKEUP		2
+-#define RPC_TASK_HAS_TIMER	3
+-#define RPC_TASK_ACTIVE		4
++#define RPC_TASK_ACTIVE		2
+ 
+ #define RPC_IS_RUNNING(t)	test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
+ #define rpc_set_running(t)	set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
+@@ -171,15 +162,6 @@ struct rpc_task_setup {
+ 		smp_mb__after_clear_bit(); \
+ 	} while (0)
+ 
+-#define rpc_start_wakeup(t) \
+-	(test_and_set_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate) == 0)
+-#define rpc_finish_wakeup(t) \
+-	do { \
+-		smp_mb__before_clear_bit(); \
+-		clear_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate); \
+-		smp_mb__after_clear_bit(); \
+-	} while (0)
+-
+ #define RPC_IS_ACTIVATED(t)	test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)
+ 
+ /*
+@@ -192,6 +174,12 @@ struct rpc_task_setup {
+ #define RPC_PRIORITY_HIGH	(1)
+ #define RPC_NR_PRIORITY		(1 + RPC_PRIORITY_HIGH - RPC_PRIORITY_LOW)
+ 
++struct rpc_timer {
++	struct timer_list timer;
++	struct list_head list;
++	unsigned long expires;
++};
++
+ /*
+  * RPC synchronization objects
+  */
+@@ -204,6 +192,7 @@ struct rpc_wait_queue {
+ 	unsigned char		count;			/* # task groups remaining serviced so far */
+ 	unsigned char		nr;			/* # tasks remaining for cookie */
+ 	unsigned short		qlen;			/* total # tasks waiting in queue */
++	struct rpc_timer	timer_list;
+ #ifdef RPC_DEBUG
+ 	const char *		name;
+ #endif
+@@ -229,9 +218,11 @@ void		rpc_killall_tasks(struct rpc_clnt *);
+ void		rpc_execute(struct rpc_task *);
+ void		rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
+ void		rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
++void		rpc_destroy_wait_queue(struct rpc_wait_queue *);
+ void		rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
+-					rpc_action action, rpc_action timer);
+-void		rpc_wake_up_task(struct rpc_task *);
++					rpc_action action);
++void		rpc_wake_up_queued_task(struct rpc_wait_queue *,
++					struct rpc_task *);
+ void		rpc_wake_up(struct rpc_wait_queue *);
+ struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
+ void		rpc_wake_up_status(struct rpc_wait_queue *, int);
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 64c9755..4b54c5f 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -386,7 +386,6 @@ struct svc_serv *  svc_create(struct svc_program *, unsigned int,
+ 			      void (*shutdown)(struct svc_serv*));
+ struct svc_rqst *svc_prepare_thread(struct svc_serv *serv,
+ 					struct svc_pool *pool);
+-int		   svc_create_thread(svc_thread_fn, struct svc_serv *);
+ void		   svc_exit_thread(struct svc_rqst *);
+ struct svc_serv *  svc_create_pooled(struct svc_program *, unsigned int,
+ 			void (*shutdown)(struct svc_serv*),
+diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
+index 22e1ef8..d39dbdc 100644
+--- a/include/linux/sunrpc/svcauth.h
++++ b/include/linux/sunrpc/svcauth.h
+@@ -24,6 +24,7 @@ struct svc_cred {
+ };
+ 
+ struct svc_rqst;		/* forward decl */
++struct in6_addr;
+ 
+ /* Authentication is done in the context of a domain.
+  *
+@@ -120,10 +121,10 @@ extern void	svc_auth_unregister(rpc_authflavor_t flavor);
+ 
+ extern struct auth_domain *unix_domain_find(char *name);
+ extern void auth_domain_put(struct auth_domain *item);
+-extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom);
++extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
+ extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
+ extern struct auth_domain *auth_domain_find(char *name);
+-extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
++extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
+ extern int auth_unix_forget_old(struct auth_domain *dom);
+ extern void svcauth_unix_purge(void);
+ extern void svcauth_unix_info_release(void *);
+diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
+index 206f092..8cff696 100644
+--- a/include/linux/sunrpc/svcsock.h
++++ b/include/linux/sunrpc/svcsock.h
+@@ -26,8 +26,8 @@ struct svc_sock {
+ 	void			(*sk_owspace)(struct sock *);
+ 
+ 	/* private TCP part */
+-	int			sk_reclen;	/* length of record */
+-	int			sk_tcplen;	/* current read length */
++	u32			sk_reclen;	/* length of record */
++	u32			sk_tcplen;	/* current read length */
+ };
+ 
+ /*
+diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
+index b3ff9a8..4d80a11 100644
+--- a/include/linux/sunrpc/xprt.h
++++ b/include/linux/sunrpc/xprt.h
+@@ -86,6 +86,10 @@ struct rpc_rqst {
+ 	unsigned long		rq_majortimeo;	/* major timeout alarm */
+ 	unsigned long		rq_timeout;	/* Current timeout value */
+ 	unsigned int		rq_retries;	/* # of retries */
++	unsigned int		rq_connect_cookie;
++						/* A cookie used to track the
++						   state of the transport
++						   connection */
+ 	
+ 	/*
+ 	 * Partial send handling
+@@ -152,6 +156,9 @@ struct rpc_xprt {
+ 	unsigned long		connect_timeout,
+ 				bind_timeout,
+ 				reestablish_timeout;
++	unsigned int		connect_cookie;	/* A cookie that gets bumped
++						   every time the transport
++						   is reconnected */
+ 
+ 	/*
+ 	 * Disconnection of idle transports
+@@ -232,7 +239,7 @@ int			xprt_unregister_transport(struct xprt_class *type);
+ void			xprt_set_retrans_timeout_def(struct rpc_task *task);
+ void			xprt_set_retrans_timeout_rtt(struct rpc_task *task);
+ void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
+-void			xprt_wait_for_buffer_space(struct rpc_task *task);
++void			xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action);
+ void			xprt_write_space(struct rpc_xprt *xprt);
+ void			xprt_update_rtt(struct rpc_task *task);
+ void			xprt_adjust_cwnd(struct rpc_task *task, int result);
+@@ -241,6 +248,7 @@ void			xprt_complete_rqst(struct rpc_task *task, int copied);
+ void			xprt_release_rqst_cong(struct rpc_task *task);
+ void			xprt_disconnect_done(struct rpc_xprt *xprt);
+ void			xprt_force_disconnect(struct rpc_xprt *xprt);
++void			xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie);
+ 
+ /*
+  * Reserved bit positions in xprt->state
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index 4c2577b..8df6d13 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -60,7 +60,6 @@ struct getcpu_cache;
+ #include <linux/capability.h>
+ #include <linux/list.h>
+ #include <linux/sem.h>
+-#include <asm/semaphore.h>
+ #include <asm/siginfo.h>
+ #include <asm/signal.h>
+ #include <linux/quota.h>
+diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
+index f752e73..f2767bc 100644
+--- a/include/linux/sysdev.h
++++ b/include/linux/sysdev.h
+@@ -45,12 +45,16 @@ struct sysdev_class_attribute {
+ 	ssize_t (*store)(struct sysdev_class *, const char *, size_t);
+ };
+ 
+-#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) 		\
+-struct sysdev_class_attribute attr_##_name = { 			\
++#define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) 		\
++{					 			\
+ 	.attr = {.name = __stringify(_name), .mode = _mode },	\
+ 	.show	= _show,					\
+ 	.store	= _store,					\
+-};
++}
++
++#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) 		\
++	struct sysdev_class_attribute attr_##_name = 		\
++		_SYSDEV_CLASS_ATTR(_name,_mode,_show,_store)
+ 
+ 
+ extern int sysdev_class_register(struct sysdev_class *);
+@@ -100,15 +104,16 @@ struct sysdev_attribute {
+ };
+ 
+ 
+-#define _SYSDEV_ATTR(_name,_mode,_show,_store)			\
++#define _SYSDEV_ATTR(_name, _mode, _show, _store)		\
+ {								\
+ 	.attr = { .name = __stringify(_name), .mode = _mode },	\
+ 	.show	= _show,					\
+ 	.store	= _store,					\
+ }
+ 
+-#define SYSDEV_ATTR(_name,_mode,_show,_store)		\
+-struct sysdev_attribute attr_##_name = _SYSDEV_ATTR(_name,_mode,_show,_store);
++#define SYSDEV_ATTR(_name, _mode, _show, _store)		\
++	struct sysdev_attribute attr_##_name =			\
++		_SYSDEV_ATTR(_name, _mode, _show, _store);
+ 
+ extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
+ extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
+diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
+index 8027104..03378e3 100644
+--- a/include/linux/sysfs.h
++++ b/include/linux/sysfs.h
+@@ -131,7 +131,6 @@ static inline int sysfs_create_dir(struct kobject *kobj)
+ 
+ static inline void sysfs_remove_dir(struct kobject *kobj)
+ {
+-	;
+ }
+ 
+ static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+@@ -160,7 +159,6 @@ static inline int sysfs_chmod_file(struct kobject *kobj,
+ static inline void sysfs_remove_file(struct kobject *kobj,
+ 				     const struct attribute *attr)
+ {
+-	;
+ }
+ 
+ static inline int sysfs_create_bin_file(struct kobject *kobj,
+@@ -169,10 +167,9 @@ static inline int sysfs_create_bin_file(struct kobject *kobj,
+ 	return 0;
+ }
+ 
+-static inline int sysfs_remove_bin_file(struct kobject *kobj,
+-					struct bin_attribute *attr)
++static inline void sysfs_remove_bin_file(struct kobject *kobj,
++					 struct bin_attribute *attr)
+ {
+-	return 0;
+ }
+ 
+ static inline int sysfs_create_link(struct kobject *kobj,
+@@ -183,7 +180,6 @@ static inline int sysfs_create_link(struct kobject *kobj,
+ 
+ static inline void sysfs_remove_link(struct kobject *kobj, const char *name)
+ {
+-	;
+ }
+ 
+ static inline int sysfs_create_group(struct kobject *kobj,
+@@ -195,7 +191,6 @@ static inline int sysfs_create_group(struct kobject *kobj,
+ static inline void sysfs_remove_group(struct kobject *kobj,
+ 				      const struct attribute_group *grp)
+ {
+-	;
+ }
+ 
+ static inline int sysfs_add_file_to_group(struct kobject *kobj,
+diff --git a/include/linux/tcp.h b/include/linux/tcp.h
+index 08027f1..d96d9b1 100644
+--- a/include/linux/tcp.h
++++ b/include/linux/tcp.h
+@@ -239,6 +239,11 @@ static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
+ 	return (struct tcp_request_sock *)req;
+ }
+ 
++struct tcp_deferred_accept_info {
++	struct sock *listen_sk;
++	struct request_sock *request;
++};
++
+ struct tcp_sock {
+ 	/* inet_connection_sock has to be the first member of tcp_sock */
+ 	struct inet_connection_sock	inet_conn;
+@@ -374,6 +379,8 @@ struct tcp_sock {
+ 	unsigned int		keepalive_intvl;  /* time interval between keep alive probes */
+ 	int			linger2;
+ 
++	struct tcp_deferred_accept_info defer_tcp_accept;
++
+ 	unsigned long last_synq_overflow; 
+ 
+ 	u32	tso_deferred;
+diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
+index 421323e..accd7ba 100644
+--- a/include/linux/thread_info.h
++++ b/include/linux/thread_info.h
+@@ -9,6 +9,9 @@
+ 
+ #include <linux/types.h>
+ 
++struct timespec;
++struct compat_timespec;
++
+ /*
+  * System call restart block.
+  */
+@@ -26,6 +29,15 @@ struct restart_block {
+ 			u32 bitset;
+ 			u64 time;
+ 		} futex;
++		/* For nanosleep */
++		struct {
++			clockid_t index;
++			struct timespec __user *rmtp;
++#ifdef CONFIG_COMPAT
++			struct compat_timespec __user *compat_rmtp;
++#endif
++			u64 expires;
++		} nanosleep;
+ 	};
+ };
+ 
+diff --git a/include/linux/topology.h b/include/linux/topology.h
+index bd14f8b..4bb7074 100644
+--- a/include/linux/topology.h
++++ b/include/linux/topology.h
+@@ -38,16 +38,15 @@
+ #endif
+ 
+ #ifndef nr_cpus_node
+-#define nr_cpus_node(node)							\
+-	({									\
+-		cpumask_t __tmp__;						\
+-		__tmp__ = node_to_cpumask(node);				\
+-		cpus_weight(__tmp__);						\
++#define nr_cpus_node(node)				\
++	({						\
++		node_to_cpumask_ptr(__tmp__, node);	\
++		cpus_weight(*__tmp__);			\
+ 	})
+ #endif
+ 
+-#define for_each_node_with_cpus(node)						\
+-	for_each_online_node(node)						\
++#define for_each_node_with_cpus(node)			\
++	for_each_online_node(node)			\
+ 		if (nr_cpus_node(node))
+ 
+ void arch_update_cpu_topology(void);
+@@ -80,7 +79,9 @@ void arch_update_cpu_topology(void);
+  * by defining their own arch-specific initializer in include/asm/topology.h.
+  * A definition there will automagically override these default initializers
+  * and allow arch-specific performance tuning of sched_domains.
++ * (Only non-zero and non-null fields need be specified.)
+  */
++
+ #ifdef CONFIG_SCHED_SMT
+ /* MCD - Do we really need this?  It is always on if CONFIG_SCHED_SMT is,
+  * so can't we drop this in favor of CONFIG_SCHED_SMT?
+@@ -89,20 +90,10 @@ void arch_update_cpu_topology(void);
+ /* Common values for SMT siblings */
+ #ifndef SD_SIBLING_INIT
+ #define SD_SIBLING_INIT (struct sched_domain) {		\
+-	.span			= CPU_MASK_NONE,	\
+-	.parent			= NULL,			\
+-	.child			= NULL,			\
+-	.groups			= NULL,			\
+ 	.min_interval		= 1,			\
+ 	.max_interval		= 2,			\
+ 	.busy_factor		= 64,			\
+ 	.imbalance_pct		= 110,			\
+-	.cache_nice_tries	= 0,			\
+-	.busy_idx		= 0,			\
+-	.idle_idx		= 0,			\
+-	.newidle_idx		= 0,			\
+-	.wake_idx		= 0,			\
+-	.forkexec_idx		= 0,			\
+ 	.flags			= SD_LOAD_BALANCE	\
+ 				| SD_BALANCE_NEWIDLE	\
+ 				| SD_BALANCE_FORK	\
+@@ -112,7 +103,6 @@ void arch_update_cpu_topology(void);
+ 				| SD_SHARE_CPUPOWER,	\
+ 	.last_balance		= jiffies,		\
+ 	.balance_interval	= 1,			\
+-	.nr_balance_failed	= 0,			\
+ }
+ #endif
+ #endif /* CONFIG_SCHED_SMT */
+@@ -121,18 +111,12 @@ void arch_update_cpu_topology(void);
+ /* Common values for MC siblings. for now mostly derived from SD_CPU_INIT */
+ #ifndef SD_MC_INIT
+ #define SD_MC_INIT (struct sched_domain) {		\
+-	.span			= CPU_MASK_NONE,	\
+-	.parent			= NULL,			\
+-	.child			= NULL,			\
+-	.groups			= NULL,			\
+ 	.min_interval		= 1,			\
+ 	.max_interval		= 4,			\
+ 	.busy_factor		= 64,			\
+ 	.imbalance_pct		= 125,			\
+ 	.cache_nice_tries	= 1,			\
+ 	.busy_idx		= 2,			\
+-	.idle_idx		= 0,			\
+-	.newidle_idx		= 0,			\
+ 	.wake_idx		= 1,			\
+ 	.forkexec_idx		= 1,			\
+ 	.flags			= SD_LOAD_BALANCE	\
+@@ -144,7 +128,6 @@ void arch_update_cpu_topology(void);
+ 				| BALANCE_FOR_MC_POWER,	\
+ 	.last_balance		= jiffies,		\
+ 	.balance_interval	= 1,			\
+-	.nr_balance_failed	= 0,			\
+ }
+ #endif
+ #endif /* CONFIG_SCHED_MC */
+@@ -152,10 +135,6 @@ void arch_update_cpu_topology(void);
+ /* Common values for CPUs */
+ #ifndef SD_CPU_INIT
+ #define SD_CPU_INIT (struct sched_domain) {		\
+-	.span			= CPU_MASK_NONE,	\
+-	.parent			= NULL,			\
+-	.child			= NULL,			\
+-	.groups			= NULL,			\
+ 	.min_interval		= 1,			\
+ 	.max_interval		= 4,			\
+ 	.busy_factor		= 64,			\
+@@ -174,16 +153,11 @@ void arch_update_cpu_topology(void);
+ 				| BALANCE_FOR_PKG_POWER,\
+ 	.last_balance		= jiffies,		\
+ 	.balance_interval	= 1,			\
+-	.nr_balance_failed	= 0,			\
+ }
+ #endif
+ 
+ /* sched_domains SD_ALLNODES_INIT for NUMA machines */
+ #define SD_ALLNODES_INIT (struct sched_domain) {	\
+-	.span			= CPU_MASK_NONE,	\
+-	.parent			= NULL,			\
+-	.child			= NULL,			\
+-	.groups			= NULL,			\
+ 	.min_interval		= 64,			\
+ 	.max_interval		= 64*num_online_cpus(),	\
+ 	.busy_factor		= 128,			\
+@@ -191,14 +165,10 @@ void arch_update_cpu_topology(void);
+ 	.cache_nice_tries	= 1,			\
+ 	.busy_idx		= 3,			\
+ 	.idle_idx		= 3,			\
+-	.newidle_idx		= 0, /* unused */	\
+-	.wake_idx		= 0, /* unused */	\
+-	.forkexec_idx		= 0, /* unused */	\
+ 	.flags			= SD_LOAD_BALANCE	\
+ 				| SD_SERIALIZE,	\
+ 	.last_balance		= jiffies,		\
+ 	.balance_interval	= 64,			\
+-	.nr_balance_failed	= 0,			\
+ }
+ 
+ #ifdef CONFIG_NUMA
+diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h
+index 1d6cc22..eaec1ea 100644
+--- a/include/linux/transport_class.h
++++ b/include/linux/transport_class.h
+@@ -17,11 +17,11 @@ struct transport_container;
+ struct transport_class {
+ 	struct class class;
+ 	int (*setup)(struct transport_container *, struct device *,
+-		     struct class_device *);
++		     struct device *);
+ 	int (*configure)(struct transport_container *, struct device *,
+-			 struct class_device *);
++			 struct device *);
+ 	int (*remove)(struct transport_container *, struct device *,
+-		      struct class_device *);
++		      struct device *);
+ };
+ 
+ #define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg)			\
+@@ -86,9 +86,10 @@ static inline int transport_container_register(struct transport_container *tc)
+ 	return attribute_container_register(&tc->ac);
+ }
+ 
+-static inline int transport_container_unregister(struct transport_container *tc)
++static inline void transport_container_unregister(struct transport_container *tc)
+ {
+-	return attribute_container_unregister(&tc->ac);
++	if (unlikely(attribute_container_unregister(&tc->ac)))
++		BUG();
+ }
+ 
+ int transport_class_register(struct transport_class *);
+diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
+index 85c95cd..21f69ac 100644
+--- a/include/linux/tty_driver.h
++++ b/include/linux/tty_driver.h
+@@ -125,6 +125,7 @@
+ #include <linux/cdev.h>
+ 
+ struct tty_struct;
++struct tty_driver;
+ 
+ struct tty_operations {
+ 	int  (*open)(struct tty_struct * tty, struct file * filp);
+@@ -157,6 +158,11 @@ struct tty_operations {
+ 	int (*tiocmget)(struct tty_struct *tty, struct file *file);
+ 	int (*tiocmset)(struct tty_struct *tty, struct file *file,
+ 			unsigned int set, unsigned int clear);
++#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);
++	void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
++#endif
+ };
+ 
+ struct tty_driver {
+@@ -220,6 +226,11 @@ struct tty_driver {
+ 	int (*tiocmget)(struct tty_struct *tty, struct file *file);
+ 	int (*tiocmset)(struct tty_struct *tty, struct file *file,
+ 			unsigned int set, unsigned int clear);
++#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);
++	void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
++#endif
+ 
+ 	struct list_head tty_drivers;
+ };
+@@ -230,6 +241,7 @@ struct tty_driver *alloc_tty_driver(int lines);
+ void put_tty_driver(struct tty_driver *driver);
+ void tty_set_operations(struct tty_driver *driver,
+ 			const struct tty_operations *op);
++extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
+ 
+ /* tty driver magic number */
+ #define TTY_DRIVER_MAGIC		0x5402
+diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
+index 975c963..fec6dec 100644
+--- a/include/linux/uaccess.h
++++ b/include/linux/uaccess.h
+@@ -84,4 +84,26 @@ static inline unsigned long __copy_from_user_nocache(void *to,
+ 		ret;					\
+ 	})
+ 
++/*
++ * probe_kernel_read(): safely attempt to read from a location
++ * @dst: pointer to the buffer that shall take the data
++ * @src: address to read from
++ * @size: size of the data chunk
++ *
++ * Safely read from address @src to the buffer at @dst.  If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++extern long probe_kernel_read(void *dst, void *src, size_t size);
++
++/*
++ * probe_kernel_write(): safely attempt to write to a location
++ * @dst: address to write to
++ * @src: pointer to the data that shall be written
++ * @size: size of the data chunk
++ *
++ * Safely write to address @dst from the buffer at @src.  If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++extern long probe_kernel_write(void *dst, void *src, size_t size);
++
+ #endif		/* __LINUX_UACCESS_H__ */
+diff --git a/include/linux/udf_fs.h b/include/linux/udf_fs.h
+deleted file mode 100644
+index aa88654..0000000
+--- a/include/linux/udf_fs.h
++++ /dev/null
+@@ -1,51 +0,0 @@
+-/*
+- * udf_fs.h
+- *
+- * PURPOSE
+- *  Included by fs/filesystems.c
+- *
+- * DESCRIPTION
+- *  OSTA-UDF(tm) = Optical Storage Technology Association
+- *  Universal Disk Format.
+- *
+- *  This code is based on version 2.50 of the UDF specification,
+- *  and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
+- *    http://www.osta.org/ *    http://www.ecma.ch/
+- *    http://www.iso.org/
+- *
+- * COPYRIGHT
+- *	This file is distributed under the terms of the GNU General Public
+- *	License (GPL). Copies of the GPL can be obtained from:
+- *		ftp://prep.ai.mit.edu/pub/gnu/GPL
+- *	Each contributing author retains all rights to their own work.
+- *
+- *  (C) 1999-2004 Ben Fennema
+- *  (C) 1999-2000 Stelias Computing Inc
+- *
+- * HISTORY
+- *
+- */
+-
+-#ifndef _UDF_FS_H
+-#define _UDF_FS_H 1
+-
+-#define UDF_PREALLOCATE
+-#define UDF_DEFAULT_PREALLOC_BLOCKS	8
+-
+-#undef UDFFS_DEBUG
+-
+-#ifdef UDFFS_DEBUG
+-#define udf_debug(f, a...) \
+-	do { \
+-		printk (KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
+-			__FILE__, __LINE__, __FUNCTION__); \
+-		printk (f, ##a); \
+-	} while (0)
+-#else
+-#define udf_debug(f, a...) /**/
+-#endif
+-
+-#define udf_info(f, a...) \
+-		printk (KERN_INFO "UDF-fs INFO " f, ##a);
+-
+-#endif /* _UDF_FS_H */
+diff --git a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
+index ffaf056..3536965 100644
+--- a/include/linux/udf_fs_i.h
++++ b/include/linux/udf_fs_i.h
+@@ -9,41 +9,10 @@
+  *		ftp://prep.ai.mit.edu/pub/gnu/GPL
+  *	Each contributing author retains all rights to their own work.
+  */
+-
+ #ifndef _UDF_FS_I_H
+ #define _UDF_FS_I_H 1
+ 
+-#ifdef __KERNEL__
+-
+-struct udf_inode_info
+-{
+-	struct timespec		i_crtime;
+-	/* Physical address of inode */
+-	kernel_lb_addr		i_location;
+-	__u64			i_unique;
+-	__u32			i_lenEAttr;
+-	__u32			i_lenAlloc;
+-	__u64			i_lenExtents;
+-	__u32			i_next_alloc_block;
+-	__u32			i_next_alloc_goal;
+-	unsigned		i_alloc_type : 3;
+-	unsigned		i_efe : 1;
+-	unsigned		i_use : 1;
+-	unsigned		i_strat4096 : 1;
+-	unsigned		reserved : 26;
+-	union
+-	{
+-		short_ad	*i_sad;
+-		long_ad		*i_lad;
+-		__u8		*i_data;
+-	} i_ext;
+-	struct inode vfs_inode;
+-};
+-
+-#endif
+-
+ /* exported IOCTLs, we have 'l', 0x40-0x7f */
+-
+ #define UDF_GETEASIZE   _IOR('l', 0x40, int)
+ #define UDF_GETEABLOCK  _IOR('l', 0x41, void *)
+ #define UDF_GETVOLIDENT _IOR('l', 0x42, void *)
+diff --git a/include/linux/udf_fs_sb.h b/include/linux/udf_fs_sb.h
+deleted file mode 100644
+index 9bc4735..0000000
+--- a/include/linux/udf_fs_sb.h
++++ /dev/null
+@@ -1,117 +0,0 @@
+-/*
+- * udf_fs_sb.h
+- * 
+- * This include file is for the Linux kernel/module.
+- *
+- * COPYRIGHT
+- *	This file is distributed under the terms of the GNU General Public
+- *	License (GPL). Copies of the GPL can be obtained from:
+- *		ftp://prep.ai.mit.edu/pub/gnu/GPL
+- *	Each contributing author retains all rights to their own work.
+- */
+-
+-#ifndef _UDF_FS_SB_H
+-#define _UDF_FS_SB_H 1
+-
+-#include <linux/mutex.h>
+-
+-#pragma pack(1)
+-
+-#define UDF_MAX_BLOCK_LOADED	8
+-
+-#define UDF_TYPE1_MAP15			0x1511U
+-#define UDF_VIRTUAL_MAP15		0x1512U
+-#define UDF_VIRTUAL_MAP20		0x2012U
+-#define UDF_SPARABLE_MAP15		0x1522U
+-
+-struct udf_sparing_data
+-{
+-	__u16	s_packet_len;
+-	struct buffer_head *s_spar_map[4];
+-};
+-
+-struct udf_virtual_data
+-{
+-	__u32	s_num_entries;
+-	__u16	s_start_offset;
+-};
+-
+-struct udf_bitmap
+-{
+-	__u32			s_extLength;
+-	__u32			s_extPosition;
+-	__u16			s_nr_groups;
+-	struct buffer_head 	**s_block_bitmap;
+-};
+-
+-struct udf_part_map
+-{
+-	union
+-	{
+-		struct udf_bitmap	*s_bitmap;
+-		struct inode		*s_table;
+-	} s_uspace;
+-	union
+-	{
+-		struct udf_bitmap	*s_bitmap;
+-		struct inode		*s_table;
+-	} s_fspace;
+-	__u32	s_partition_root;
+-	__u32	s_partition_len;
+-	__u16	s_partition_type;
+-	__u16	s_partition_num;
+-	union
+-	{
+-		struct udf_sparing_data s_sparing;
+-		struct udf_virtual_data s_virtual;
+-	} s_type_specific;
+-	__u32	(*s_partition_func)(struct super_block *, __u32, __u16, __u32);
+-	__u16	s_volumeseqnum;
+-	__u16	s_partition_flags;
+-};
+-
+-#pragma pack()
+-
+-struct udf_sb_info
+-{
+-	struct udf_part_map	*s_partmaps;
+-	__u8			s_volume_ident[32];
+-
+-	/* Overall info */
+-	__u16			s_partitions;
+-	__u16			s_partition;
+-
+-	/* Sector headers */
+-	__s32			s_session;
+-	__u32			s_anchor[4];
+-	__u32			s_last_block;
+-
+-	struct buffer_head	*s_lvid_bh;
+-
+-	/* Default permissions */
+-	mode_t			s_umask;
+-	gid_t			s_gid;
+-	uid_t			s_uid;
+-
+-	/* Root Info */
+-	struct timespec		s_record_time;
+-
+-	/* Fileset Info */
+-	__u16			s_serial_number;
+-
+-	/* highest UDF revision we have recorded to this media */
+-	__u16			s_udfrev;
+-
+-	/* Miscellaneous flags */
+-	__u32			s_flags;
+-
+-	/* Encoding info */
+-	struct nls_table	*s_nls_map;
+-
+-	/* VAT inode */
+-	struct inode		*s_vat_inode;
+-
+-	struct mutex		s_alloc_mutex;
+-};
+-
+-#endif /* _UDF_FS_SB_H */
+diff --git a/include/linux/udp.h b/include/linux/udp.h
+index 8ec703f..581ca2c 100644
+--- a/include/linux/udp.h
++++ b/include/linux/udp.h
+@@ -26,15 +26,6 @@ struct udphdr {
+ 	__sum16	check;
+ };
+ 
+-#ifdef __KERNEL__
+-#include <linux/skbuff.h>
+-
+-static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
+-{
+-	return (struct udphdr *)skb_transport_header(skb);
+-}
+-#endif
+-
+ /* UDP socket options */
+ #define UDP_CORK	1	/* Never send partially complete segments */
+ #define UDP_ENCAP	100	/* Set the socket to accept encapsulated packets */
+@@ -45,9 +36,14 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
+ #define UDP_ENCAP_L2TPINUDP	3 /* rfc2661 */
+ 
+ #ifdef __KERNEL__
+-#include <linux/types.h>
+-
+ #include <net/inet_sock.h>
++#include <linux/skbuff.h>
++
++static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
++{
++	return (struct udphdr *)skb_transport_header(skb);
++}
++
+ #define UDP_HTABLE_SIZE		128
+ 
+ struct udp_sock {
+@@ -82,6 +78,7 @@ static inline struct udp_sock *udp_sk(const struct sock *sk)
+ {
+ 	return (struct udp_sock *)sk;
+ }
++
+ #define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag)
+ 
+ #endif
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 583e048..c08689e 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -23,6 +23,7 @@
+ 
+ struct usb_device;
+ struct usb_driver;
++struct wusb_dev;
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+@@ -341,103 +342,146 @@ struct usb_bus {
+ 
+ struct usb_tt;
+ 
+-/*
++/**
+  * struct usb_device - kernel's representation of a USB device
+- *
+- * FIXME: Write the kerneldoc!
+- *
++ * @devnum: device number; address on a USB bus
++ * @devpath: device ID string for use in messages (e.g., /port/...)
++ * @state: device state: configured, not attached, etc.
++ * @speed: device speed: high/full/low (or error)
++ * @tt: Transaction Translator info; used with low/full speed dev, highspeed hub
++ * @ttport: device port on that tt hub
++ * @toggle: one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints
++ * @parent: our hub, unless we're the root
++ * @bus: bus we're part of
++ * @ep0: endpoint 0 data (default control pipe)
++ * @dev: generic device interface
++ * @descriptor: USB device descriptor
++ * @config: all of the device's configs
++ * @actconfig: the active configuration
++ * @ep_in: array of IN endpoints
++ * @ep_out: array of OUT endpoints
++ * @rawdescriptors: raw descriptors for each config
++ * @bus_mA: Current available from the bus
++ * @portnum: parent port number (origin 1)
++ * @level: number of USB hub ancestors
++ * @can_submit: URBs may be submitted
++ * @discon_suspended: disconnected while suspended
++ * @persist_enabled:  USB_PERSIST enabled for this device
++ * @have_langid: whether string_langid is valid
++ * @authorized: policy has said we can use it;
++ *	(user space) policy determines if we authorize this device to be
++ *	used or not. By default, wired USB devices are authorized.
++ *	WUSB devices are not, until we authorize them from user space.
++ *	FIXME -- complete doc
++ * @authenticated: Crypto authentication passed
++ * @wusb: device is Wireless USB
++ * @string_langid: language ID for strings
++ * @product: iProduct string, if present (static)
++ * @manufacturer: iManufacturer string, if present (static)
++ * @serial: iSerialNumber string, if present (static)
++ * @filelist: usbfs files that are open to this device
++ * @usb_classdev: USB class device that was created for usbfs device
++ *	access from userspace
++ * @usbfs_dentry: usbfs dentry entry for the device
++ * @maxchild: number of ports if hub
++ * @children: child devices - USB devices that are attached to this hub
++ * @pm_usage_cnt: usage counter for autosuspend
++ * @quirks: quirks of the whole device
++ * @urbnum: number of URBs submitted for the whole device
++ * @active_duration: total time device is not suspended
++ * @autosuspend: for delayed autosuspends
++ * @pm_mutex: protects PM operations
++ * @last_busy: time of last use
++ * @autosuspend_delay: in jiffies
++ * @connect_time: time device was first connected
++ * @auto_pm: autosuspend/resume in progress
++ * @do_remote_wakeup:  remote wakeup should be enabled
++ * @reset_resume: needs reset instead of resume
++ * @autosuspend_disabled: autosuspend disabled by the user
++ * @autoresume_disabled: autoresume disabled by the user
++ * @skip_sys_resume: skip the next system resume
++ *
++ * Notes:
+  * Usbcore drivers should not set usbdev->state directly.  Instead use
+  * usb_set_device_state().
+- *
+- * @authorized: (user space) policy determines if we authorize this
+- *              device to be used or not. By default, wired USB
+- *              devices are authorized. WUSB devices are not, until we
+- *              authorize them from user space. FIXME -- complete doc
+  */
+ struct usb_device {
+-	int		devnum;		/* Address on USB bus */
+-	char		devpath [16];	/* Use in messages: /port/port/... */
+-	enum usb_device_state	state;	/* configured, not attached, etc */
+-	enum usb_device_speed	speed;	/* high/full/low (or error) */
++	int		devnum;
++	char		devpath [16];
++	enum usb_device_state	state;
++	enum usb_device_speed	speed;
+ 
+-	struct usb_tt	*tt; 		/* low/full speed dev, highspeed hub */
+-	int		ttport;		/* device port on that tt hub */
++	struct usb_tt	*tt;
++	int		ttport;
+ 
+-	unsigned int toggle[2];		/* one bit for each endpoint
+-					 * ([0] = IN, [1] = OUT) */
++	unsigned int toggle[2];
+ 
+-	struct usb_device *parent;	/* our hub, unless we're the root */
+-	struct usb_bus *bus;		/* Bus we're part of */
++	struct usb_device *parent;
++	struct usb_bus *bus;
+ 	struct usb_host_endpoint ep0;
+ 
+-	struct device dev;		/* Generic device interface */
++	struct device dev;
+ 
+-	struct usb_device_descriptor descriptor;/* Descriptor */
+-	struct usb_host_config *config;	/* All of the configs */
++	struct usb_device_descriptor descriptor;
++	struct usb_host_config *config;
+ 
+-	struct usb_host_config *actconfig;/* the active configuration */
++	struct usb_host_config *actconfig;
+ 	struct usb_host_endpoint *ep_in[16];
+ 	struct usb_host_endpoint *ep_out[16];
+ 
+-	char **rawdescriptors;		/* Raw descriptors for each config */
++	char **rawdescriptors;
+ 
+-	unsigned short bus_mA;		/* Current available from the bus */
+-	u8 portnum;			/* Parent port number (origin 1) */
+-	u8 level;			/* Number of USB hub ancestors */
++	unsigned short bus_mA;
++	u8 portnum;
++	u8 level;
+ 
+-	unsigned can_submit:1;		/* URBs may be submitted */
+-	unsigned discon_suspended:1;	/* Disconnected while suspended */
+-	unsigned have_langid:1;		/* whether string_langid is valid */
+-	unsigned authorized:1;		/* Policy has said we can use it */
+-	unsigned wusb:1;		/* Device is Wireless USB */
+-	int string_langid;		/* language ID for strings */
++	unsigned can_submit:1;
++	unsigned discon_suspended:1;
++	unsigned persist_enabled:1;
++	unsigned have_langid:1;
++	unsigned authorized:1;
++ 	unsigned authenticated:1;
++	unsigned wusb:1;
++	int string_langid;
+ 
+ 	/* static strings from the device */
+-	char *product;			/* iProduct string, if present */
+-	char *manufacturer;		/* iManufacturer string, if present */
+-	char *serial;			/* iSerialNumber string, if present */
++	char *product;
++	char *manufacturer;
++	char *serial;
+ 
+ 	struct list_head filelist;
+ #ifdef CONFIG_USB_DEVICE_CLASS
+ 	struct device *usb_classdev;
+ #endif
+ #ifdef CONFIG_USB_DEVICEFS
+-	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the device */
++	struct dentry *usbfs_dentry;
+ #endif
+-	/*
+-	 * Child devices - these can be either new devices
+-	 * (if this is a hub device), or different instances
+-	 * of this same device.
+-	 *
+-	 * Each instance needs its own set of data structures.
+-	 */
+ 
+-	int maxchild;			/* Number of ports if hub */
++	int maxchild;
+ 	struct usb_device *children[USB_MAXCHILDREN];
+ 
+-	int pm_usage_cnt;		/* usage counter for autosuspend */
+-	u32 quirks;			/* quirks of the whole device */
+-	atomic_t urbnum;		/* number of URBs submitted for
+-					   the whole device */
++	int pm_usage_cnt;
++	u32 quirks;
++	atomic_t urbnum;
+ 
+-	unsigned long active_duration;	/* total time device is not suspended */
++	unsigned long active_duration;
+ 
+ #ifdef CONFIG_PM
+-	struct delayed_work autosuspend; /* for delayed autosuspends */
+-	struct mutex pm_mutex;		/* protects PM operations */
+-
+-	unsigned long last_busy;	/* time of last use */
+-	int autosuspend_delay;		/* in jiffies */
+-	unsigned long connect_time;	/* time device was first connected */
+-
+-	unsigned auto_pm:1;		/* autosuspend/resume in progress */
+-	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
+-	unsigned reset_resume:1;	/* needs reset instead of resume */
+-	unsigned persist_enabled:1;	/* USB_PERSIST enabled for this dev */
+-	unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
+-	unsigned autoresume_disabled:1;  /*  disabled by the user */
+-	unsigned skip_sys_resume:1;	/* skip the next system resume */
++	struct delayed_work autosuspend;
++	struct mutex pm_mutex;
++
++	unsigned long last_busy;
++	int autosuspend_delay;
++	unsigned long connect_time;
++
++	unsigned auto_pm:1;
++	unsigned do_remote_wakeup:1;
++	unsigned reset_resume:1;
++	unsigned autosuspend_disabled:1;
++	unsigned autoresume_disabled:1;
++	unsigned skip_sys_resume:1;
+ #endif
++	struct wusb_dev *wusb_dev;
+ };
+ #define	to_usb_device(d) container_of(d, struct usb_device, dev)
+ 
+@@ -898,10 +942,11 @@ struct usbdrv_wrap {
+  *	and should normally be the same as the module name.
+  * @probe: Called to see if the driver is willing to manage a particular
+  *	interface on a device.  If it is, probe returns zero and uses
+- *	dev_set_drvdata() to associate driver-specific data with the
++ *	usb_set_intfdata() to associate driver-specific data with the
+  *	interface.  It may also use usb_set_interface() to specify the
+  *	appropriate altsetting.  If unwilling to manage the interface,
+- *	return a negative errno value.
++ *	return -ENODEV, if genuine IO errors occured, an appropriate
++ *	negative errno value.
+  * @disconnect: Called when the interface is no longer accessible, usually
+  *	because its device has been (or is being) disconnected or the
+  *	driver module is being unloaded.
+@@ -916,10 +961,7 @@ struct usbdrv_wrap {
+  * @pre_reset: Called by usb_reset_composite_device() when the device
+  *	is about to be reset.
+  * @post_reset: Called by usb_reset_composite_device() after the device
+- *	has been reset, or in lieu of @resume following a reset-resume
+- *	(i.e., the device is reset instead of being resumed, as might
+- *	happen if power was lost).  The second argument tells which is
+- *	the reason.
++ *	has been reset
+  * @id_table: USB drivers use ID table to support hotplugging.
+  *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
+  *	or your driver's probe function will never get called.
+@@ -1411,6 +1453,7 @@ extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
+ extern int usb_unlink_urb(struct urb *urb);
+ extern void usb_kill_urb(struct urb *urb);
+ extern void usb_kill_anchored_urbs(struct usb_anchor *anchor);
++extern void usb_unlink_anchored_urbs(struct usb_anchor *anchor);
+ extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor);
+ extern void usb_unanchor_urb(struct urb *urb);
+ extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+@@ -1661,13 +1704,12 @@ extern void usb_unregister_notify(struct notifier_block *nb);
+ #define dbg(format, arg...) do {} while (0)
+ #endif
+ 
+-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+-	__FILE__ , ## arg)
+-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , \
+-	__FILE__ , ## arg)
+-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , \
+-	__FILE__ , ## arg)
+-
++#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
++	format "\n" , ## arg)
++#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \
++	format "\n" , ## arg)
++#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \
++	format "\n" , ## arg)
+ 
+ #endif  /* __KERNEL__ */
+ 
+diff --git a/include/linux/usb/atmel_usba_udc.h b/include/linux/usb/atmel_usba_udc.h
+new file mode 100644
+index 0000000..6311fa2
+--- /dev/null
++++ b/include/linux/usb/atmel_usba_udc.h
+@@ -0,0 +1,22 @@
++/*
++ * Platform data definitions for Atmel USBA gadget driver.
++ */
++#ifndef __LINUX_USB_USBA_H
++#define __LINUX_USB_USBA_H
++
++struct usba_ep_data {
++	char	*name;
++	int	index;
++	int	fifo_size;
++	int	nr_banks;
++	int	can_dma;
++	int	can_isoc;
++};
++
++struct usba_platform_data {
++	int			vbus_pin;
++	int			num_ep;
++	struct usba_ep_data	ep[0];
++};
++
++#endif /* __LINUX_USB_USBA_H */
+diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
+index 2dfeef1..8cb025f 100644
+--- a/include/linux/usb/audio.h
++++ b/include/linux/usb/audio.h
+@@ -50,4 +50,4 @@ struct usb_ac_header_descriptor_##n {				\
+ 	__u8  baInterfaceNr[n];					\
+ } __attribute__ ((packed))
+ 
+-#endif
++#endif /* __LINUX_USB_AUDIO_H */
+diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
+index 94ee4ec..71e52f2 100644
+--- a/include/linux/usb/cdc.h
++++ b/include/linux/usb/cdc.h
+@@ -6,6 +6,9 @@
+  * firmware based USB peripherals.
+  */
+ 
++#ifndef __LINUX_USB_CDC_H
++#define __LINUX_USB_CDC_H
++
+ #define USB_CDC_SUBCLASS_ACM			0x02
+ #define USB_CDC_SUBCLASS_ETHERNET		0x06
+ #define USB_CDC_SUBCLASS_WHCM			0x08
+@@ -221,3 +224,4 @@ struct usb_cdc_notification {
+ 	__le16	wLength;
+ } __attribute__ ((packed));
+ 
++#endif /* __LINUX_USB_CDC_H */
+diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
+index 6169438..7e0d308 100644
+--- a/include/linux/usb/ch9.h
++++ b/include/linux/usb/ch9.h
+@@ -66,8 +66,8 @@
+ #define USB_RECIP_ENDPOINT		0x02
+ #define USB_RECIP_OTHER			0x03
+ /* From Wireless USB 1.0 */
+-#define USB_RECIP_PORT 			0x04
+-#define USB_RECIP_RPIPE 		0x05
++#define USB_RECIP_PORT			0x04
++#define USB_RECIP_RPIPE		0x05
+ 
+ /*
+  * Standard requests, for the bRequest field of a SETUP packet.
+@@ -102,10 +102,16 @@
+ #define USB_REQ_LOOPBACK_DATA_READ	0x16
+ #define USB_REQ_SET_INTERFACE_DS	0x17
+ 
++/* The Link Power Mangement (LPM) ECN defines USB_REQ_TEST_AND_SET command,
++ * used by hubs to put ports into a new L1 suspend state, except that it
++ * forgot to define its number ...
++ */
++
+ /*
+  * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
+  * are read as a bit array returned by USB_REQ_GET_STATUS.  (So there
+- * are at most sixteen features of each type.)
++ * are at most sixteen features of each type.)  Hubs may also support a
++ * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
+  */
+ #define USB_DEVICE_SELF_POWERED		0	/* (read only) */
+ #define USB_DEVICE_REMOTE_WAKEUP	1	/* dev may initiate wakeup */
+@@ -180,6 +186,7 @@ struct usb_ctrlrequest {
+ #define USB_DT_WIRELESS_ENDPOINT_COMP	0x11
+ #define USB_DT_WIRE_ADAPTER		0x21
+ #define USB_DT_RPIPE			0x22
++#define USB_DT_CS_RADIO_CONTROL		0x23
+ 
+ /* Conventional codes for class-specific descriptors.  The convention is
+  * defined in the USB "Common Class" Spec (3.11).  Individual class specs
+@@ -574,7 +581,9 @@ enum usb_device_state {
+ 	/* NOTE:  there are actually four different SUSPENDED
+ 	 * states, returning to POWERED, DEFAULT, ADDRESS, or
+ 	 * CONFIGURED respectively when SOF tokens flow again.
++	 * At this level there's no difference between L1 and L2
++	 * suspend states.  (L2 being original USB 1.1 suspend.)
+ 	 */
+ };
+ 
+-#endif	/* __LINUX_USB_CH9_H */
++#endif /* __LINUX_USB_CH9_H */
+diff --git a/include/linux/usb/g_printer.h b/include/linux/usb/g_printer.h
+index 0c5ea1e..6178fde 100644
+--- a/include/linux/usb/g_printer.h
++++ b/include/linux/usb/g_printer.h
+@@ -18,6 +18,8 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+ 
++#ifndef __LINUX_USB_G_PRINTER_H
++#define __LINUX_USB_G_PRINTER_H
+ 
+ #define PRINTER_NOT_ERROR	0x08
+ #define PRINTER_SELECTED	0x10
+@@ -29,3 +31,5 @@
+  */
+ #define GADGET_GET_PRINTER_STATUS	_IOR('g', 0x21, unsigned char)
+ #define GADGET_SET_PRINTER_STATUS	_IOWR('g', 0x22, unsigned char)
++
++#endif /* __LINUX_USB_G_PRINTER_H */
+diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
+index f329529..d8128f7 100644
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -846,4 +846,4 @@ extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
+ 
+ extern void usb_ep_autoconfig_reset(struct usb_gadget *) __devinit;
+ 
+-#endif	/* __LINUX_USB_GADGET_H */
++#endif /* __LINUX_USB_GADGET_H */
+diff --git a/include/linux/usb/gadgetfs.h b/include/linux/usb/gadgetfs.h
+index c291ab1..ea45f26 100644
+--- a/include/linux/usb/gadgetfs.h
++++ b/include/linux/usb/gadgetfs.h
+@@ -1,11 +1,3 @@
+-#ifndef __LINUX_USB_GADGETFS_H
+-#define __LINUX_USB_GADGETFS_H
+-
+-#include <asm/types.h>
+-#include <asm/ioctl.h>
+-
+-#include <linux/usb/ch9.h>
+-
+ /*
+  * Filesystem based user-mode API to USB Gadget controller hardware
+  *
+@@ -23,6 +15,14 @@
+  * then performing data transfers by reading or writing.
+  */
+ 
++#ifndef __LINUX_USB_GADGETFS_H
++#define __LINUX_USB_GADGETFS_H
++
++#include <asm/types.h>
++#include <asm/ioctl.h>
++
++#include <linux/usb/ch9.h>
++
+ /*
+  * Events are delivered on the ep0 file descriptor, when the user mode driver
+  * reads from this file descriptor after writing the descriptors.  Don't
+diff --git a/include/linux/usb/input.h b/include/linux/usb/input.h
+index 716e0cc..0e010b2 100644
+--- a/include/linux/usb/input.h
++++ b/include/linux/usb/input.h
+@@ -1,6 +1,3 @@
+-#ifndef __USB_INPUT_H
+-#define __USB_INPUT_H
+-
+ /*
+  * Copyright (C) 2005 Dmitry Torokhov
+  *
+@@ -9,6 +6,9 @@
+  * the Free Software Foundation.
+  */
+ 
++#ifndef __LINUX_USB_INPUT_H
++#define __LINUX_USB_INPUT_H
++
+ #include <linux/usb.h>
+ #include <linux/input.h>
+ #include <asm/byteorder.h>
+@@ -22,4 +22,4 @@ usb_to_input_id(const struct usb_device *dev, struct input_id *id)
+ 	id->version = le16_to_cpu(dev->descriptor.bcdDevice);
+ }
+ 
+-#endif
++#endif /* __LINUX_USB_INPUT_H */
+diff --git a/include/linux/usb/iowarrior.h b/include/linux/usb/iowarrior.h
+index de6f380..4fd6513 100644
+--- a/include/linux/usb/iowarrior.h
++++ b/include/linux/usb/iowarrior.h
+@@ -1,5 +1,5 @@
+-#ifndef _IOWARRIOR_H_
+-#define _IOWARRIOR_H_
++#ifndef __LINUX_USB_IOWARRIOR_H
++#define __LINUX_USB_IOWARRIOR_H
+ 
+ #define CODEMERCS_MAGIC_NUMBER	0xC0	/* like COde Mercenaries */
+ 
+@@ -39,4 +39,4 @@ struct iowarrior_info {
+ */
+ #define IOW_GETINFO _IOR(CODEMERCS_MAGIC_NUMBER, 3, struct iowarrior_info)
+ 
+-#endif  /* _IOWARRIOR_H_ */
++#endif /* __LINUX_USB_IOWARRIOR_H */
+diff --git a/include/linux/usb/isp116x.h b/include/linux/usb/isp116x.h
+index 67d2826..96ca114 100644
+--- a/include/linux/usb/isp116x.h
++++ b/include/linux/usb/isp116x.h
+@@ -1,9 +1,11 @@
+-
+ /*
+  * Board initialization code should put one of these into dev->platform_data
+  * and place the isp116x onto platform_bus.
+  */
+ 
++#ifndef __LINUX_USB_ISP116X_H
++#define __LINUX_USB_ISP116X_H
++
+ struct isp116x_platform_data {
+ 	/* Enable internal resistors on downstream ports */
+ 	unsigned sel15Kres:1;
+@@ -27,3 +29,5 @@ struct isp116x_platform_data {
+ 	 */
+ 	void (*delay) (struct device *dev, int delay);
+ };
++
++#endif /* __LINUX_USB_ISP116X_H */
+diff --git a/include/linux/usb/midi.h b/include/linux/usb/midi.h
+index 80624c5..1d10408 100644
+--- a/include/linux/usb/midi.h
++++ b/include/linux/usb/midi.h
+@@ -109,4 +109,4 @@ struct usb_ms_endpoint_descriptor_##n {				\
+ 	__u8  baAssocJackID[n];					\
+ } __attribute__ ((packed))
+ 
+-#endif
++#endif /* __LINUX_USB_MIDI_H */
+diff --git a/include/linux/usb/net2280.h b/include/linux/usb/net2280.h
+index ec897cb..96ca549 100644
+--- a/include/linux/usb/net2280.h
++++ b/include/linux/usb/net2280.h
+@@ -1,11 +1,7 @@
+ /*
+  * NetChip 2280 high/full speed USB device controller.
+  * Unlike many such controllers, this one talks PCI.
+- */
+-#ifndef __LINUX_USB_NET2280_H
+-#define __LINUX_USB_NET2280_H
+-
+-/*
++ *
+  * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+  * Copyright (C) 2003 David Brownell
+  *
+@@ -24,6 +20,9 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+ 
++#ifndef __LINUX_USB_NET2280_H
++#define __LINUX_USB_NET2280_H
++
+ /*-------------------------------------------------------------------------*/
+ 
+ /* NET2280 MEMORY MAPPED REGISTERS
+diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
+index e007074..1db25d1 100644
+--- a/include/linux/usb/otg.h
++++ b/include/linux/usb/otg.h
+@@ -1,11 +1,13 @@
+ /* USB OTG (On The Go) defines */
+-
+ /*
++ *
+  * These APIs may be used between USB controllers.  USB device drivers
+  * (for either host or peripheral roles) don't use these calls; they
+  * continue to use just usb_device and usb_gadget.
+  */
+ 
++#ifndef __LINUX_USB_OTG_H
++#define __LINUX_USB_OTG_H
+ 
+ /* OTG defines lots of enumeration states before device reset */
+ enum usb_otg_state {
+@@ -129,3 +131,5 @@ otg_start_srp(struct otg_transceiver *otg)
+ 
+ /* for OTG controller drivers (and maybe other stuff) */
+ extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
++
++#endif /* __LINUX_USB_OTG_H */
+diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
+index 1f999ec..7f6c603 100644
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -4,6 +4,9 @@
+  * belong here.
+  */
+ 
++#ifndef __LINUX_USB_QUIRKS_H
++#define __LINUX_USB_QUIRKS_H
++
+ /* string descriptors must not be fetched using a 255-byte read */
+ #define USB_QUIRK_STRING_FETCH_255	0x00000001
+ 
+@@ -12,3 +15,5 @@
+ 
+ /* device can't handle Set-Interface requests */
+ #define USB_QUIRK_NO_SET_INTF		0x00000004
++
++#endif /* __LINUX_USB_QUIRKS_H */
+diff --git a/include/linux/usb/rndis_host.h b/include/linux/usb/rndis_host.h
+index edc1d4a..29d6458 100644
+--- a/include/linux/usb/rndis_host.h
++++ b/include/linux/usb/rndis_host.h
+@@ -17,10 +17,8 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+ 
+-
+-#ifndef	__RNDIS_HOST_H
+-#define	__RNDIS_HOST_H
+-
++#ifndef	__LINUX_USB_RNDIS_HOST_H
++#define	__LINUX_USB_RNDIS_HOST_H
+ 
+ /*
+  * CONTROL uses CDC "encapsulated commands" with funky notifications.
+@@ -270,5 +268,4 @@ extern int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb);
+ extern struct sk_buff *
+ rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags);
+ 
+-#endif	/* __RNDIS_HOST_H */
+-
++#endif	/* __LINUX_USB_RNDIS_HOST_H */
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index 21b4a1c..8f891cb 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -10,7 +10,6 @@
+  *
+  */
+ 
+-
+ #ifndef __LINUX_USB_SERIAL_H
+ #define __LINUX_USB_SERIAL_H
+ 
+@@ -146,8 +145,6 @@ struct usb_serial {
+ };
+ #define to_usb_serial(d) container_of(d, struct usb_serial, kref)
+ 
+-#define NUM_DONT_CARE	99
+-
+ /* get and set the serial private data pointer helper functions */
+ static inline void *usb_get_serial_data(struct usb_serial *serial)
+ {
+@@ -165,18 +162,6 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
+  *	used in the syslog messages when a device is inserted or removed.
+  * @id_table: pointer to a list of usb_device_id structures that define all
+  *	of the devices this structure can support.
+- * @num_interrupt_in: If a device doesn't have this many interrupt-in
+- *	endpoints, it won't be sent to the driver's attach() method.
+- *	(But it might still be sent to the probe() method.)
+- * @num_interrupt_out: If a device doesn't have this many interrupt-out
+- *	endpoints, it won't be sent to the driver's attach() method.
+- *	(But it might still be sent to the probe() method.)
+- * @num_bulk_in: If a device doesn't have this many bulk-in
+- *	endpoints, it won't be sent to the driver's attach() method.
+- *	(But it might still be sent to the probe() method.)
+- * @num_bulk_out: If a device doesn't have this many bulk-out
+- *	endpoints, it won't be sent to the driver's attach() method.
+- *	(But it might still be sent to the probe() method.)
+  * @num_ports: the number of different ports this device will have.
+  * @calc_num_ports: pointer to a function to determine how many ports this
+  *	device has dynamically.  It will be called after the probe()
+@@ -212,10 +197,6 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
+ struct usb_serial_driver {
+ 	const char *description;
+ 	const struct usb_device_id *id_table;
+-	char	num_interrupt_in;
+-	char	num_interrupt_out;
+-	char	num_bulk_in;
+-	char	num_bulk_out;
+ 	char	num_ports;
+ 
+ 	struct list_head	driver_list;
+@@ -340,5 +321,5 @@ static inline void usb_serial_debug_data(int debug,
+ 
+ 
+ 
+-#endif	/* ifdef __LINUX_USB_SERIAL_H */
++#endif /* __LINUX_USB_SERIAL_H */
+ 
+diff --git a/include/linux/usb/sl811.h b/include/linux/usb/sl811.h
+index 877373d..3afe4d1 100644
+--- a/include/linux/usb/sl811.h
++++ b/include/linux/usb/sl811.h
+@@ -1,9 +1,11 @@
+-
+ /*
+  * board initialization should put one of these into dev->platform_data
+  * and place the sl811hs onto platform_bus named "sl811-hcd".
+  */
+ 
++#ifndef __LINUX_USB_SL811_H
++#define __LINUX_USB_SL811_H
++
+ struct sl811_platform_data {
+ 	unsigned	can_wakeup:1;
+ 
+@@ -24,3 +26,4 @@ struct sl811_platform_data {
+ 	/* void		(*clock_enable)(struct device *dev, int is_on); */
+ };
+ 
++#endif /* __LINUX_USB_SL811_H */
+diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
+index e0501da..ba09fe8 100644
+--- a/include/linux/usb/usbnet.h
++++ b/include/linux/usb/usbnet.h
+@@ -19,10 +19,8 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+ 
+-
+-#ifndef	__USBNET_H
+-#define	__USBNET_H
+-
++#ifndef	__LINUX_USB_USBNET_H
++#define	__LINUX_USB_USBNET_H
+ 
+ /* interface from usbnet core to each USB networking link we handle */
+ struct usbnet {
+@@ -211,4 +209,4 @@ extern int usbnet_nway_reset(struct net_device *net);
+ 	printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
+ 
+ 
+-#endif	/* __USBNET_H */
++#endif /* __LINUX_USB_USBNET_H */
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index 0a40dfa..d9a3bbe 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -85,6 +85,7 @@ enum { US_DO_ALL_FLAGS };
+ #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 */
+diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
+index 17cb108..3118ede 100644
+--- a/include/linux/usbdevice_fs.h
++++ b/include/linux/usbdevice_fs.h
+@@ -77,8 +77,11 @@ struct usbdevfs_connectinfo {
+ 	unsigned char slow;
+ };
+ 
+-#define USBDEVFS_URB_SHORT_NOT_OK          1
+-#define USBDEVFS_URB_ISO_ASAP              2
++#define USBDEVFS_URB_SHORT_NOT_OK	0x01
++#define USBDEVFS_URB_ISO_ASAP		0x02
++#define USBDEVFS_URB_NO_FSBR		0x20
++#define USBDEVFS_URB_ZERO_PACKET	0x40
++#define USBDEVFS_URB_NO_INTERRUPT	0x80
+ 
+ #define USBDEVFS_URB_TYPE_ISO		   0
+ #define USBDEVFS_URB_TYPE_INTERRUPT	   1
+diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
+index 17a8017..c141118 100644
+--- a/include/linux/videodev2.h
++++ b/include/linux/videodev2.h
+@@ -282,6 +282,7 @@ struct v4l2_pix_format
+ #define V4L2_PIX_FMT_BGR32   v4l2_fourcc('B','G','R','4') /* 32  BGR-8-8-8-8   */
+ #define V4L2_PIX_FMT_RGB32   v4l2_fourcc('R','G','B','4') /* 32  RGB-8-8-8-8   */
+ #define V4L2_PIX_FMT_GREY    v4l2_fourcc('G','R','E','Y') /*  8  Greyscale     */
++#define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y','1','6',' ') /* 16  Greyscale     */
+ #define V4L2_PIX_FMT_PAL8    v4l2_fourcc('P','A','L','8') /*  8  8-bit palette */
+ #define V4L2_PIX_FMT_YVU410  v4l2_fourcc('Y','V','U','9') /*  9  YVU 4:1:0     */
+ #define V4L2_PIX_FMT_YVU420  v4l2_fourcc('Y','V','1','2') /* 12  YVU 4:2:0     */
+@@ -308,6 +309,7 @@ struct v4l2_pix_format
+ 
+ /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
+ #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B','A','8','1') /*  8  BGBG.. GRGR.. */
++#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16  BGBG.. GRGR.. */
+ 
+ /* compressed formats */
+ #define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M','J','P','G') /* Motion-JPEG   */
+@@ -793,6 +795,7 @@ struct v4l2_ext_controls
+ /*  Values for ctrl_class field */
+ #define V4L2_CTRL_CLASS_USER 0x00980000	/* Old-style 'user' controls */
+ #define V4L2_CTRL_CLASS_MPEG 0x00990000	/* MPEG-compression controls */
++#define V4L2_CTRL_CLASS_CAMERA 0x009a0000	/* Camera class controls */
+ 
+ #define V4L2_CTRL_ID_MASK      	  (0x0fffffff)
+ #define V4L2_CTRL_ID2CLASS(id)    ((id) & 0x0fff0000UL)
+@@ -849,21 +852,37 @@ struct v4l2_querymenu
+ #define V4L2_CID_AUDIO_TREBLE		(V4L2_CID_BASE+8)
+ #define V4L2_CID_AUDIO_MUTE		(V4L2_CID_BASE+9)
+ #define V4L2_CID_AUDIO_LOUDNESS		(V4L2_CID_BASE+10)
+-#define V4L2_CID_BLACK_LEVEL		(V4L2_CID_BASE+11)
++#define V4L2_CID_BLACK_LEVEL		(V4L2_CID_BASE+11) /* Deprecated */
+ #define V4L2_CID_AUTO_WHITE_BALANCE	(V4L2_CID_BASE+12)
+ #define V4L2_CID_DO_WHITE_BALANCE	(V4L2_CID_BASE+13)
+ #define V4L2_CID_RED_BALANCE		(V4L2_CID_BASE+14)
+ #define V4L2_CID_BLUE_BALANCE		(V4L2_CID_BASE+15)
+ #define V4L2_CID_GAMMA			(V4L2_CID_BASE+16)
+-#define V4L2_CID_WHITENESS		(V4L2_CID_GAMMA) /* ? Not sure */
++#define V4L2_CID_WHITENESS		(V4L2_CID_GAMMA) /* Deprecated */
+ #define V4L2_CID_EXPOSURE		(V4L2_CID_BASE+17)
+ #define V4L2_CID_AUTOGAIN		(V4L2_CID_BASE+18)
+ #define V4L2_CID_GAIN			(V4L2_CID_BASE+19)
+ #define V4L2_CID_HFLIP			(V4L2_CID_BASE+20)
+ #define V4L2_CID_VFLIP			(V4L2_CID_BASE+21)
+-#define V4L2_CID_HCENTER		(V4L2_CID_BASE+22)
+-#define V4L2_CID_VCENTER		(V4L2_CID_BASE+23)
+-#define V4L2_CID_LASTP1			(V4L2_CID_BASE+24) /* last CID + 1 */
++
++/* Deprecated, use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
++#define V4L2_CID_HCENTER_DEPRECATED	(V4L2_CID_BASE+22)
++#define V4L2_CID_VCENTER_DEPRECATED	(V4L2_CID_BASE+23)
++
++#define V4L2_CID_POWER_LINE_FREQUENCY	(V4L2_CID_BASE+24)
++enum v4l2_power_line_frequency {
++	V4L2_CID_POWER_LINE_FREQUENCY_DISABLED	= 0,
++	V4L2_CID_POWER_LINE_FREQUENCY_50HZ	= 1,
++	V4L2_CID_POWER_LINE_FREQUENCY_60HZ	= 2,
++};
++#define V4L2_CID_HUE_AUTO			(V4L2_CID_BASE+25)
++#define V4L2_CID_WHITE_BALANCE_TEMPERATURE	(V4L2_CID_BASE+26)
++#define V4L2_CID_SHARPNESS			(V4L2_CID_BASE+27)
++#define V4L2_CID_BACKLIGHT_COMPENSATION 	(V4L2_CID_BASE+28)
++#define V4L2_CID_CHROMA_AGC                     (V4L2_CID_BASE+29)
++#define V4L2_CID_COLOR_KILLER                   (V4L2_CID_BASE+30)
++/* last CID + 1 */
++#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+31)
+ 
+ /*  MPEG-class control IDs defined by V4L2 */
+ #define V4L2_CID_MPEG_BASE 			(V4L2_CTRL_CLASS_MPEG | 0x900)
+@@ -1051,6 +1070,32 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type {
+ #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP 	(V4L2_CID_MPEG_CX2341X_BASE+10)
+ #define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS 	(V4L2_CID_MPEG_CX2341X_BASE+11)
+ 
++/*  Camera class control IDs */
++#define V4L2_CID_CAMERA_CLASS_BASE 	(V4L2_CTRL_CLASS_CAMERA | 0x900)
++#define V4L2_CID_CAMERA_CLASS 		(V4L2_CTRL_CLASS_CAMERA | 1)
++
++#define V4L2_CID_EXPOSURE_AUTO			(V4L2_CID_CAMERA_CLASS_BASE+1)
++enum  v4l2_exposure_auto_type {
++	V4L2_EXPOSURE_AUTO = 0,
++	V4L2_EXPOSURE_MANUAL = 1,
++	V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
++	V4L2_EXPOSURE_APERTURE_PRIORITY = 3
++};
++#define V4L2_CID_EXPOSURE_ABSOLUTE		(V4L2_CID_CAMERA_CLASS_BASE+2)
++#define V4L2_CID_EXPOSURE_AUTO_PRIORITY		(V4L2_CID_CAMERA_CLASS_BASE+3)
++
++#define V4L2_CID_PAN_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+4)
++#define V4L2_CID_TILT_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+5)
++#define V4L2_CID_PAN_RESET			(V4L2_CID_CAMERA_CLASS_BASE+6)
++#define V4L2_CID_TILT_RESET			(V4L2_CID_CAMERA_CLASS_BASE+7)
++
++#define V4L2_CID_PAN_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+8)
++#define V4L2_CID_TILT_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+9)
++
++#define V4L2_CID_FOCUS_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+10)
++#define V4L2_CID_FOCUS_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+11)
++#define V4L2_CID_FOCUS_AUTO			(V4L2_CID_CAMERA_CLASS_BASE+12)
++
+ /*
+  *	T U N I N G
+  */
+diff --git a/include/linux/wireless.h b/include/linux/wireless.h
+index 3160dfe..2864b16 100644
+--- a/include/linux/wireless.h
++++ b/include/linux/wireless.h
+@@ -455,6 +455,7 @@
+ #define IW_MODE_REPEAT	4	/* Wireless Repeater (forwarder) */
+ #define IW_MODE_SECOND	5	/* Secondary master/repeater (backup) */
+ #define IW_MODE_MONITOR	6	/* Passive monitor (listen only) */
++#define IW_MODE_MESH	7	/* Mesh (IEEE 802.11s) network */
+ 
+ /* Statistics flags (bitmask in updated) */
+ #define IW_QUAL_QUAL_UPDATED	0x01	/* Value was updated since last read */
+diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h
+new file mode 100644
+index 0000000..4d13732
+--- /dev/null
++++ b/include/linux/wm97xx.h
+@@ -0,0 +1,314 @@
++
++/*
++ * Register bits and API for Wolfson WM97xx series of codecs
++ */
++
++#ifndef _LINUX_WM97XX_H
++#define _LINUX_WM97XX_H
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/ac97_codec.h>
++#include <sound/initval.h>
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/input.h>	/* Input device layer */
++#include <linux/platform_device.h>
++
++/*
++ * WM97xx AC97 Touchscreen registers
++ */
++#define AC97_WM97XX_DIGITISER1		0x76
++#define AC97_WM97XX_DIGITISER2		0x78
++#define AC97_WM97XX_DIGITISER_RD 	0x7a
++#define AC97_WM9713_DIG1		0x74
++#define AC97_WM9713_DIG2		AC97_WM97XX_DIGITISER1
++#define AC97_WM9713_DIG3		AC97_WM97XX_DIGITISER2
++
++/*
++ * WM97xx register bits
++ */
++#define WM97XX_POLL		0x8000	/* initiate a polling measurement */
++#define WM97XX_ADCSEL_X		0x1000	/* x coord measurement */
++#define WM97XX_ADCSEL_Y		0x2000	/* y coord measurement */
++#define WM97XX_ADCSEL_PRES	0x3000	/* pressure measurement */
++#define WM97XX_ADCSEL_MASK	0x7000
++#define WM97XX_COO		0x0800	/* enable coordinate mode */
++#define WM97XX_CTC		0x0400	/* enable continuous mode */
++#define WM97XX_CM_RATE_93	0x0000	/* 93.75Hz continuous rate */
++#define WM97XX_CM_RATE_187	0x0100	/* 187.5Hz continuous rate */
++#define WM97XX_CM_RATE_375	0x0200	/* 375Hz continuous rate */
++#define WM97XX_CM_RATE_750	0x0300	/* 750Hz continuous rate */
++#define WM97XX_CM_RATE_8K	0x00f0	/* 8kHz continuous rate */
++#define WM97XX_CM_RATE_12K	0x01f0	/* 12kHz continuous rate */
++#define WM97XX_CM_RATE_24K	0x02f0	/* 24kHz continuous rate */
++#define WM97XX_CM_RATE_48K	0x03f0	/* 48kHz continuous rate */
++#define WM97XX_CM_RATE_MASK	0x03f0
++#define WM97XX_RATE(i)		(((i & 3) << 8) | ((i & 4) ? 0xf0 : 0))
++#define WM97XX_DELAY(i)		((i << 4) & 0x00f0)	/* sample delay times */
++#define WM97XX_DELAY_MASK	0x00f0
++#define WM97XX_SLEN		0x0008	/* slot read back enable */
++#define WM97XX_SLT(i)		((i - 5) & 0x7)	/* panel slot (5-11) */
++#define WM97XX_SLT_MASK		0x0007
++#define WM97XX_PRP_DETW		0x4000	/* detect on, digitise off, wake */
++#define WM97XX_PRP_DET		0x8000	/* detect on, digitise off, no wake */
++#define WM97XX_PRP_DET_DIG	0xc000	/* setect on, digitise on */
++#define WM97XX_RPR		0x2000	/* wake up on pen down */
++#define WM97XX_PEN_DOWN		0x8000	/* pen is down */
++#define WM97XX_ADCSRC_MASK	0x7000	/* ADC source mask */
++
++#define WM97XX_AUX_ID1		0x8001
++#define WM97XX_AUX_ID2		0x8002
++#define WM97XX_AUX_ID3		0x8003
++#define WM97XX_AUX_ID4		0x8004
++
++
++/* WM9712 Bits */
++#define WM9712_45W		0x1000	/* set for 5-wire touchscreen */
++#define WM9712_PDEN		0x0800	/* measure only when pen down */
++#define WM9712_WAIT		0x0200	/* wait until adc is read before next sample */
++#define WM9712_PIL		0x0100	/* current used for pressure measurement. set 400uA else 200uA */
++#define WM9712_MASK_HI		0x0040	/* hi on mask pin (47) stops conversions */
++#define WM9712_MASK_EDGE	0x0080	/* rising/falling edge on pin delays sample */
++#define	WM9712_MASK_SYNC	0x00c0	/* rising/falling edge on mask initiates sample */
++#define WM9712_RPU(i)		(i&0x3f)	/* internal pull up on pen detect (64k / rpu) */
++#define WM9712_PD(i)		(0x1 << i)	/* power management */
++
++/* WM9712 Registers */
++#define AC97_WM9712_POWER	0x24
++#define AC97_WM9712_REV		0x58
++
++/* WM9705 Bits */
++#define WM9705_PDEN		0x1000	/* measure only when pen is down */
++#define WM9705_PINV		0x0800	/* inverts sense of pen down output */
++#define WM9705_BSEN		0x0400	/* BUSY flag enable, pin47 is 1 when busy */
++#define WM9705_BINV		0x0200	/* invert BUSY (pin47) output */
++#define WM9705_WAIT		0x0100	/* wait until adc is read before next sample */
++#define WM9705_PIL		0x0080	/* current used for pressure measurement. set 400uA else 200uA */
++#define WM9705_PHIZ		0x0040	/* set PHONE and PCBEEP inputs to high impedance */
++#define WM9705_MASK_HI		0x0010	/* hi on mask stops conversions */
++#define WM9705_MASK_EDGE	0x0020	/* rising/falling edge on pin delays sample */
++#define	WM9705_MASK_SYNC	0x0030	/* rising/falling edge on mask initiates sample */
++#define WM9705_PDD(i)		(i & 0x000f)	/* pen detect comparator threshold */
++
++
++/* WM9713 Bits */
++#define WM9713_PDPOL		0x0400	/* Pen down polarity */
++#define WM9713_POLL		0x0200	/* initiate a polling measurement */
++#define WM9713_CTC		0x0100	/* enable continuous mode */
++#define WM9713_ADCSEL_X		0x0002	/* X measurement */
++#define WM9713_ADCSEL_Y		0x0004	/* Y measurement */
++#define WM9713_ADCSEL_PRES	0x0008	/* Pressure measurement */
++#define WM9713_COO		0x0001	/* enable coordinate mode */
++#define WM9713_PDEN		0x0800	/* measure only when pen down */
++#define WM9713_ADCSEL_MASK	0x00fe	/* ADC selection mask */
++#define WM9713_WAIT		0x0200	/* coordinate wait */
++
++/* AUX ADC ID's */
++#define TS_COMP1		0x0
++#define TS_COMP2		0x1
++#define TS_BMON			0x2
++#define TS_WIPER		0x3
++
++/* ID numbers */
++#define WM97XX_ID1		0x574d
++#define WM9712_ID2		0x4c12
++#define WM9705_ID2		0x4c05
++#define WM9713_ID2		0x4c13
++
++/* Codec GPIO's */
++#define WM97XX_MAX_GPIO		16
++#define WM97XX_GPIO_1		(1 << 1)
++#define WM97XX_GPIO_2		(1 << 2)
++#define WM97XX_GPIO_3		(1 << 3)
++#define WM97XX_GPIO_4		(1 << 4)
++#define WM97XX_GPIO_5		(1 << 5)
++#define WM97XX_GPIO_6		(1 << 6)
++#define WM97XX_GPIO_7		(1 << 7)
++#define WM97XX_GPIO_8		(1 << 8)
++#define WM97XX_GPIO_9		(1 << 9)
++#define WM97XX_GPIO_10		(1 << 10)
++#define WM97XX_GPIO_11		(1 << 11)
++#define WM97XX_GPIO_12		(1 << 12)
++#define WM97XX_GPIO_13		(1 << 13)
++#define WM97XX_GPIO_14		(1 << 14)
++#define WM97XX_GPIO_15		(1 << 15)
++
++
++#define AC97_LINK_FRAME		21	/* time in uS for AC97 link frame */
++
++
++/*---------------- Return codes from sample reading functions ---------------*/
++
++/* More data is available; call the sample gathering function again */
++#define RC_AGAIN			0x00000001
++/* The returned sample is valid */
++#define RC_VALID			0x00000002
++/* The pen is up (the first RC_VALID without RC_PENUP means pen is down) */
++#define RC_PENUP			0x00000004
++/* The pen is down (RC_VALID implies RC_PENDOWN, but sometimes it is helpful
++   to tell the handler that the pen is down but we don't know yet his coords,
++   so the handler should not sleep or wait for pendown irq) */
++#define RC_PENDOWN			0x00000008
++
++/*
++ * The wm97xx driver provides a private API for writing platform-specific
++ * drivers.
++ */
++
++/* The structure used to return arch specific sampled data into */
++struct wm97xx_data {
++    int x;
++    int y;
++    int p;
++};
++
++/*
++ * Codec GPIO status
++ */
++enum wm97xx_gpio_status {
++    WM97XX_GPIO_HIGH,
++    WM97XX_GPIO_LOW
++};
++
++/*
++ * Codec GPIO direction
++ */
++enum wm97xx_gpio_dir {
++    WM97XX_GPIO_IN,
++    WM97XX_GPIO_OUT
++};
++
++/*
++ * Codec GPIO polarity
++ */
++enum wm97xx_gpio_pol {
++    WM97XX_GPIO_POL_HIGH,
++    WM97XX_GPIO_POL_LOW
++};
++
++/*
++ * Codec GPIO sticky
++ */
++enum wm97xx_gpio_sticky {
++    WM97XX_GPIO_STICKY,
++    WM97XX_GPIO_NOTSTICKY
++};
++
++/*
++ * Codec GPIO wake
++ */
++enum wm97xx_gpio_wake {
++    WM97XX_GPIO_WAKE,
++    WM97XX_GPIO_NOWAKE
++};
++
++/*
++ * Digitiser ioctl commands
++ */
++#define WM97XX_DIG_START	0x1
++#define WM97XX_DIG_STOP		0x2
++#define WM97XX_PHY_INIT		0x3
++#define WM97XX_AUX_PREPARE	0x4
++#define WM97XX_DIG_RESTORE	0x5
++
++struct wm97xx;
++
++extern struct wm97xx_codec_drv wm9705_codec;
++extern struct wm97xx_codec_drv wm9712_codec;
++extern struct wm97xx_codec_drv wm9713_codec;
++
++/*
++ * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs
++ */
++struct wm97xx_codec_drv {
++	u16 id;
++	char *name;
++
++	/* read 1 sample */
++	int (*poll_sample) (struct wm97xx *, int adcsel, int *sample);
++
++	/* read X,Y,[P] in poll */
++	int (*poll_touch) (struct wm97xx *, struct wm97xx_data *);
++
++	int (*acc_enable) (struct wm97xx *, int enable);
++	void (*phy_init) (struct wm97xx *);
++	void (*dig_enable) (struct wm97xx *, int enable);
++	void (*dig_restore) (struct wm97xx *);
++	void (*aux_prepare) (struct wm97xx *);
++};
++
++
++/* Machine specific and accelerated touch operations */
++struct wm97xx_mach_ops {
++
++	/* accelerated touch readback - coords are transmited on AC97 link */
++	int acc_enabled;
++	void (*acc_pen_up) (struct wm97xx *);
++	int (*acc_pen_down) (struct wm97xx *);
++	int (*acc_startup) (struct wm97xx *);
++	void (*acc_shutdown) (struct wm97xx *);
++
++	/* interrupt mask control - required for accelerated operation */
++	void (*irq_enable) (struct wm97xx *, int enable);
++
++	/* GPIO pin used for accelerated operation */
++	int irq_gpio;
++
++	/* pre and post sample - can be used to minimise any analog noise */
++	void (*pre_sample) (int);  /* function to run before sampling */
++	void (*post_sample) (int);  /* function to run after sampling */
++};
++
++struct wm97xx {
++	u16 dig[3], id, gpio[6], misc;	/* Cached codec registers */
++	u16 dig_save[3];		/* saved during aux reading */
++	struct wm97xx_codec_drv *codec;	/* attached codec driver*/
++	struct input_dev *input_dev;	/* touchscreen input device */
++	struct snd_ac97 *ac97;		/* ALSA codec access */
++	struct device *dev;		/* ALSA device */
++	struct platform_device *battery_dev;
++	struct platform_device *touch_dev;
++	struct wm97xx_mach_ops *mach_ops;
++	struct mutex codec_mutex;
++	struct delayed_work ts_reader;  /* Used to poll touchscreen */
++	unsigned long ts_reader_interval; /* Current interval for timer */
++	unsigned long ts_reader_min_interval; /* Minimum interval */
++	unsigned int pen_irq;		/* Pen IRQ number in use */
++	struct workqueue_struct *ts_workq;
++	struct work_struct pen_event_work;
++	u16 acc_slot;			/* AC97 slot used for acc touch data */
++	u16 acc_rate;			/* acc touch data rate */
++	unsigned pen_is_down:1;		/* Pen is down */
++	unsigned aux_waiting:1;		/* aux measurement waiting */
++	unsigned pen_probably_down:1;	/* used in polling mode */
++	u16 suspend_mode;               /* PRP in suspend mode */
++};
++
++/*
++ * Codec GPIO access (not supported on WM9705)
++ * This can be used to set/get codec GPIO and Virtual GPIO status.
++ */
++enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio);
++void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
++			  enum wm97xx_gpio_status status);
++void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio,
++				     enum wm97xx_gpio_dir dir,
++				     enum wm97xx_gpio_pol pol,
++				     enum wm97xx_gpio_sticky sticky,
++				     enum wm97xx_gpio_wake wake);
++
++void wm97xx_set_suspend_mode(struct wm97xx *wm, u16 mode);
++
++/* codec AC97 IO access */
++int wm97xx_reg_read(struct wm97xx *wm, u16 reg);
++void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val);
++
++/* aux adc readback */
++int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel);
++
++/* machine ops */
++int wm97xx_register_mach_ops(struct wm97xx *, struct wm97xx_mach_ops *);
++void wm97xx_unregister_mach_ops(struct wm97xx *);
++
++#endif
+diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
+index e31b8c8..2ca6bae 100644
+--- a/include/linux/xfrm.h
++++ b/include/linux/xfrm.h
+@@ -97,10 +97,10 @@ struct xfrm_algo {
+ };
+ 
+ struct xfrm_algo_aead {
+-	char	alg_name[64];
+-	int	alg_key_len;	/* in bits */
+-	int	alg_icv_len;	/* in bits */
+-	char	alg_key[0];
++	char		alg_name[64];
++	unsigned int	alg_key_len;	/* in bits */
++	unsigned int	alg_icv_len;	/* in bits */
++	char		alg_key[0];
+ };
+ 
+ struct xfrm_stats {
+@@ -113,7 +113,8 @@ enum
+ {
+ 	XFRM_POLICY_TYPE_MAIN	= 0,
+ 	XFRM_POLICY_TYPE_SUB	= 1,
+-	XFRM_POLICY_TYPE_MAX	= 2
++	XFRM_POLICY_TYPE_MAX	= 2,
++	XFRM_POLICY_TYPE_ANY	= 255
+ };
+ 
+ enum
+diff --git a/include/media/ir-common.h b/include/media/ir-common.h
+index a427420..bfee8be 100644
+--- a/include/media/ir-common.h
++++ b/include/media/ir-common.h
+@@ -107,6 +107,7 @@ extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE];
++extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE];
+@@ -141,8 +142,10 @@ extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE];
++extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE];
++extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE];
+ 
+ #endif
+ 
+diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
+new file mode 100644
+index 0000000..6a8c8be
+--- /dev/null
++++ b/include/media/soc_camera.h
+@@ -0,0 +1,179 @@
++/*
++ * camera image capture (abstract) bus driver header
++ *
++ * Copyright (C) 2006, Sascha Hauer, Pengutronix
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at 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.
++ */
++
++#ifndef SOC_CAMERA_H
++#define SOC_CAMERA_H
++
++#include <linux/videodev2.h>
++#include <media/videobuf-dma-sg.h>
++
++struct soc_camera_device {
++	struct list_head list;
++	struct device dev;
++	struct device *control;
++	unsigned short width;		/* Current window */
++	unsigned short height;		/* sizes */
++	unsigned short x_min;		/* Camera capabilities */
++	unsigned short y_min;
++	unsigned short x_current;	/* Current window location */
++	unsigned short y_current;
++	unsigned short width_min;
++	unsigned short width_max;
++	unsigned short height_min;
++	unsigned short height_max;
++	unsigned short y_skip_top;	/* Lines to skip at the top */
++	unsigned short gain;
++	unsigned short exposure;
++	unsigned char iface;		/* Host number */
++	unsigned char devnum;		/* Device number per host */
++	unsigned char buswidth;		/* See comment in .c */
++	struct soc_camera_ops *ops;
++	struct video_device *vdev;
++	const struct soc_camera_data_format *current_fmt;
++	const struct soc_camera_data_format *formats;
++	int num_formats;
++	struct module *owner;
++	/* soc_camera.c private count. Only accessed with video_lock held */
++	int use_count;
++};
++
++struct soc_camera_file {
++	struct soc_camera_device *icd;
++	struct videobuf_queue vb_vidq;
++	spinlock_t *lock;
++};
++
++struct soc_camera_host {
++	struct list_head list;
++	struct device dev;
++	unsigned char nr;				/* Host number */
++	size_t msize;
++	struct videobuf_queue_ops *vbq_ops;
++	void *priv;
++	char *drv_name;
++	struct soc_camera_host_ops *ops;
++};
++
++struct soc_camera_host_ops {
++	struct module *owner;
++	int (*add)(struct soc_camera_device *);
++	void (*remove)(struct soc_camera_device *);
++	int (*set_fmt_cap)(struct soc_camera_device *, __u32,
++			   struct v4l2_rect *);
++	int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
++	int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *);
++	int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
++	int (*try_bus_param)(struct soc_camera_device *, __u32);
++	int (*set_bus_param)(struct soc_camera_device *, __u32);
++	unsigned int (*poll)(struct file *, poll_table *);
++	spinlock_t* (*spinlock_alloc)(struct soc_camera_file *);
++	void (*spinlock_free)(spinlock_t *);
++};
++
++struct soc_camera_link {
++	/* Camera bus id, used to match a camera and a bus */
++	int bus_id;
++	/* GPIO number to switch between 8 and 10 bit modes */
++	unsigned int gpio;
++};
++
++static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
++{
++	return container_of(dev, struct soc_camera_device, dev);
++}
++
++static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
++{
++	return container_of(dev, struct soc_camera_host, dev);
++}
++
++extern int soc_camera_host_register(struct soc_camera_host *ici);
++extern void soc_camera_host_unregister(struct soc_camera_host *ici);
++extern int soc_camera_device_register(struct soc_camera_device *icd);
++extern void soc_camera_device_unregister(struct soc_camera_device *icd);
++
++extern int soc_camera_video_start(struct soc_camera_device *icd);
++extern void soc_camera_video_stop(struct soc_camera_device *icd);
++
++struct soc_camera_data_format {
++	char *name;
++	unsigned int depth;
++	__u32 fourcc;
++	enum v4l2_colorspace colorspace;
++};
++
++struct soc_camera_ops {
++	struct module *owner;
++	int (*probe)(struct soc_camera_device *);
++	void (*remove)(struct soc_camera_device *);
++	int (*init)(struct soc_camera_device *);
++	int (*release)(struct soc_camera_device *);
++	int (*start_capture)(struct soc_camera_device *);
++	int (*stop_capture)(struct soc_camera_device *);
++	int (*set_fmt_cap)(struct soc_camera_device *, __u32,
++			   struct v4l2_rect *);
++	int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
++	unsigned long (*query_bus_param)(struct soc_camera_device *);
++	int (*set_bus_param)(struct soc_camera_device *, unsigned long);
++	int (*get_chip_id)(struct soc_camera_device *,
++			   struct v4l2_chip_ident *);
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++	int (*get_register)(struct soc_camera_device *, struct v4l2_register *);
++	int (*set_register)(struct soc_camera_device *, struct v4l2_register *);
++#endif
++	int (*get_control)(struct soc_camera_device *, struct v4l2_control *);
++	int (*set_control)(struct soc_camera_device *, struct v4l2_control *);
++	const struct v4l2_queryctrl *controls;
++	int num_controls;
++};
++
++static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
++	struct soc_camera_ops *ops, int id)
++{
++	int i;
++
++	for (i = 0; i < ops->num_controls; i++)
++		if (ops->controls[i].id == id)
++			return &ops->controls[i];
++
++	return NULL;
++}
++
++#define SOCAM_MASTER			(1 << 0)
++#define SOCAM_SLAVE			(1 << 1)
++#define SOCAM_HSYNC_ACTIVE_HIGH		(1 << 2)
++#define SOCAM_HSYNC_ACTIVE_LOW		(1 << 3)
++#define SOCAM_VSYNC_ACTIVE_HIGH		(1 << 4)
++#define SOCAM_VSYNC_ACTIVE_LOW		(1 << 5)
++#define SOCAM_DATAWIDTH_8		(1 << 6)
++#define SOCAM_DATAWIDTH_9		(1 << 7)
++#define SOCAM_DATAWIDTH_10		(1 << 8)
++#define SOCAM_PCLK_SAMPLE_RISING	(1 << 9)
++#define SOCAM_PCLK_SAMPLE_FALLING	(1 << 10)
++
++#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \
++			      SOCAM_DATAWIDTH_10)
++
++static inline unsigned long soc_camera_bus_param_compatible(
++			unsigned long camera_flags, unsigned long bus_flags)
++{
++	unsigned long common_flags, hsync, vsync, pclk;
++
++	common_flags = camera_flags & bus_flags;
++
++	hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
++	vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
++	pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
++
++	return (!hsync || !vsync || !pclk) ? 0 : common_flags;
++}
++
++#endif
+diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h
+index b201371..ab03c53 100644
+--- a/include/media/tuner-types.h
++++ b/include/media/tuner-types.h
+@@ -6,10 +6,11 @@
+ #define __TUNER_TYPES_H__
+ 
+ enum param_type {
+-	TUNER_PARAM_TYPE_RADIO, \
+-	TUNER_PARAM_TYPE_PAL, \
+-	TUNER_PARAM_TYPE_SECAM, \
+-	TUNER_PARAM_TYPE_NTSC
++	TUNER_PARAM_TYPE_RADIO,
++	TUNER_PARAM_TYPE_PAL,
++	TUNER_PARAM_TYPE_SECAM,
++	TUNER_PARAM_TYPE_NTSC,
++	TUNER_PARAM_TYPE_DIGITAL,
+ };
+ 
+ struct tuner_range {
+@@ -105,6 +106,7 @@ struct tuner_params {
+ 	   the SECAM-L/L' standards. Range: -16:+15 */
+ 	signed int default_top_secam_high:5;
+ 
++	u16 iffreq;
+ 
+ 	unsigned int count;
+ 	struct tuner_range *ranges;
+@@ -114,6 +116,13 @@ struct tunertype {
+ 	char *name;
+ 	unsigned int count;
+ 	struct tuner_params *params;
++
++	u16 min;
++	u16 max;
++	u32 stepsize;
++
++	u8 *initdata;
++	u8 *sleepdata;
+ };
+ 
+ extern struct tunertype tuners[];
+diff --git a/include/media/tuner.h b/include/media/tuner.h
+index 1bf24a6..77068fc 100644
+--- a/include/media/tuner.h
++++ b/include/media/tuner.h
+@@ -78,7 +78,7 @@
+ 
+ #define TUNER_HITACHI_NTSC		40
+ #define TUNER_PHILIPS_PAL_MK		41
+-#define TUNER_PHILIPS_ATSC		42
++#define TUNER_PHILIPS_FCV1236D		42
+ #define TUNER_PHILIPS_FM1236_MK3	43
+ 
+ #define TUNER_PHILIPS_4IN1		44	/* ATI TV Wonder Pro - Conexant */
+diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
+index 032bb75..0ea0bd8 100644
+--- a/include/media/v4l2-chip-ident.h
++++ b/include/media/v4l2-chip-ident.h
+@@ -153,6 +153,12 @@ enum {
+ 	V4L2_IDENT_MSP4428G = 44287,
+ 	V4L2_IDENT_MSP4448G = 44487,
+ 	V4L2_IDENT_MSP4458G = 44587,
++
++	/* Micron CMOS sensor chips: 45000-45099 */
++	V4L2_IDENT_MT9M001C12ST		= 45000,
++	V4L2_IDENT_MT9M001C12STM	= 45005,
++	V4L2_IDENT_MT9V022IX7ATC	= 45010, /* No way to detect "normal" I77ATx */
++	V4L2_IDENT_MT9V022IX7ATM	= 45015, /* and "lead free" IA7ATx chips */
+ };
+ 
+ #endif
+diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
+index f211445..a807d2f 100644
+--- a/include/media/v4l2-dev.h
++++ b/include/media/v4l2-dev.h
+@@ -318,6 +318,10 @@ struct video_device
+ 	int (*vidioc_g_chip_ident)     (struct file *file, void *fh,
+ 					struct v4l2_chip_ident *chip);
+ 
++	/* For other private ioctls */
++	int (*vidioc_default)	       (struct file *file, void *fh,
++					int cmd, void *arg);
++
+ 
+ #ifdef OBSOLETE_OWNER /* to be removed soon */
+ /* obsolete -- fops->owner is used instead */
+diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h
+index 9903394..5b39a22 100644
+--- a/include/media/videobuf-core.h
++++ b/include/media/videobuf-core.h
+@@ -13,6 +13,9 @@
+  * the Free Software Foundation; either version 2
+  */
+ 
++#ifndef _VIDEOBUF_CORE_H
++#define _VIDEOBUF_CORE_H
++
+ #include <linux/poll.h>
+ #ifdef CONFIG_VIDEO_V4L1_COMPAT
+ #include <linux/videodev.h>
+@@ -123,7 +126,8 @@ struct videobuf_queue_ops {
+ struct videobuf_qtype_ops {
+ 	u32                     magic;
+ 
+-	void* (*alloc)		(size_t size);
++	void *(*alloc)		(size_t size);
++	void *(*vmalloc)	(struct videobuf_buffer *buf);
+ 	int (*iolock)		(struct videobuf_queue* q,
+ 				 struct videobuf_buffer *vb,
+ 				 struct v4l2_framebuffer *fbuf);
+@@ -151,7 +155,9 @@ struct videobuf_qtype_ops {
+ struct videobuf_queue {
+ 	struct mutex               vb_lock;
+ 	spinlock_t                 *irqlock;
+-	void			   *dev; /* on pci, points to struct pci_dev */
++	struct device		   *dev;
++
++	wait_queue_head_t	   wait; /* wait if queue is empty */
+ 
+ 	enum v4l2_buf_type         type;
+ 	unsigned int               inputs; /* for V4L2_BUF_FLAG_INPUT */
+@@ -183,9 +189,13 @@ int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
+ 
+ void *videobuf_alloc(struct videobuf_queue* q);
+ 
++/* Used on videobuf-dvb */
++void *videobuf_queue_to_vmalloc (struct videobuf_queue* q,
++				 struct videobuf_buffer *buf);
++
+ void videobuf_queue_core_init(struct videobuf_queue *q,
+ 			 struct videobuf_queue_ops *ops,
+-			 void *dev,
++			 struct device *dev,
+ 			 spinlock_t *irqlock,
+ 			 enum v4l2_buf_type type,
+ 			 enum v4l2_field field,
+@@ -231,10 +241,4 @@ int videobuf_mmap_free(struct videobuf_queue *q);
+ int videobuf_mmap_mapper(struct videobuf_queue *q,
+ 			 struct vm_area_struct *vma);
+ 
+-/* --------------------------------------------------------------------- */
+-
+-/*
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
++#endif
+diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h
+index 3810503..be8da26 100644
+--- a/include/media/videobuf-dma-sg.h
++++ b/include/media/videobuf-dma-sg.h
+@@ -1,5 +1,5 @@
+ /*
+- * helper functions for PCI DMA video4linux capture buffers
++ * helper functions for SG DMA video4linux capture buffers
+  *
+  * The functions expect the hardware being able to scatter gatter
+  * (i.e. the buffers are not linear in physical memory, but fragmented
+@@ -68,9 +68,6 @@ struct videobuf_dmabuf {
+ 	/* for kernel buffers */
+ 	void                *vmalloc;
+ 
+-	/* Stores the userspace pointer to vmalloc area */
+-	void                *varea;
+-
+ 	/* for overlay buffers (pci-pci dma) */
+ 	dma_addr_t          bus_addr;
+ 
+@@ -81,7 +78,7 @@ struct videobuf_dmabuf {
+ 	int                 direction;
+ };
+ 
+-struct videbuf_pci_sg_memory
++struct videobuf_dma_sg_memory
+ {
+ 	u32                 magic;
+ 
+@@ -103,11 +100,11 @@ int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
+ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
+ struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf);
+ 
+-void *videobuf_pci_alloc (size_t size);
++void *videobuf_sg_alloc(size_t size);
+ 
+-void videobuf_queue_pci_init(struct videobuf_queue* q,
++void videobuf_queue_sg_init(struct videobuf_queue* q,
+ 			 struct videobuf_queue_ops *ops,
+-			 void *dev,
++			 struct device *dev,
+ 			 spinlock_t *irqlock,
+ 			 enum v4l2_buf_type type,
+ 			 enum v4l2_field field,
+@@ -117,6 +114,6 @@ void videobuf_queue_pci_init(struct videobuf_queue* q,
+ 	/*FIXME: these variants are used only on *-alsa code, where videobuf is
+ 	 * used without queue
+ 	 */
+-int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma);
+-int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma);
++int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma);
++int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma);
+ 
+diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h
+index 8233caf..b777486 100644
+--- a/include/media/videobuf-dvb.h
++++ b/include/media/videobuf-dvb.h
+@@ -27,7 +27,8 @@ struct videobuf_dvb {
+ int videobuf_dvb_register(struct videobuf_dvb *dvb,
+ 			  struct module *module,
+ 			  void *adapter_priv,
+-			  struct device *device);
++			  struct device *device,
++			  short *adapter_nr);
+ void videobuf_dvb_unregister(struct videobuf_dvb *dvb);
+ 
+ /*
+diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h
+index ec63ab0..aed3946 100644
+--- a/include/media/videobuf-vmalloc.h
++++ b/include/media/videobuf-vmalloc.h
+@@ -12,6 +12,8 @@
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2
+  */
++#ifndef _VIDEOBUF_VMALLOC_H
++#define _VIDEOBUF_VMALLOC_H
+ 
+ #include <media/videobuf-core.h>
+ 
+@@ -39,3 +41,5 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
+ void *videobuf_to_vmalloc (struct videobuf_buffer *buf);
+ 
+ void videobuf_vmalloc_free (struct videobuf_buffer *buf);
++
++#endif
+diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild
+index 4d46b3b..8eb018f 100644
+--- a/include/mtd/Kbuild
++++ b/include/mtd/Kbuild
+@@ -3,5 +3,4 @@ header-y += jffs2-user.h
+ header-y += mtd-abi.h
+ header-y += mtd-user.h
+ header-y += nftl-user.h
+-header-y += ubi-header.h
+ header-y += ubi-user.h
+diff --git a/include/mtd/ubi-header.h b/include/mtd/ubi-header.h
+deleted file mode 100644
+index 292f916..0000000
+--- a/include/mtd/ubi-header.h
++++ /dev/null
+@@ -1,372 +0,0 @@
+-/*
+- * Copyright (c) International Business Machines Corp., 2006
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+- * the GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public 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: Artem Bityutskiy (Битюцкий Артём)
+- *          Thomas Gleixner
+- *          Frank Haverkamp
+- *          Oliver Lohmann
+- *          Andreas Arnez
+- */
+-
+-/*
+- * This file defines the layout of UBI headers and all the other UBI on-flash
+- * data structures. May be included by user-space.
+- */
+-
+-#ifndef __UBI_HEADER_H__
+-#define __UBI_HEADER_H__
+-
+-#include <asm/byteorder.h>
+-
+-/* The version of UBI images supported by this implementation */
+-#define UBI_VERSION 1
+-
+-/* The highest erase counter value supported by this implementation */
+-#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
+-
+-/* The initial CRC32 value used when calculating CRC checksums */
+-#define UBI_CRC32_INIT 0xFFFFFFFFU
+-
+-/* Erase counter header magic number (ASCII "UBI#") */
+-#define UBI_EC_HDR_MAGIC  0x55424923
+-/* Volume identifier header magic number (ASCII "UBI!") */
+-#define UBI_VID_HDR_MAGIC 0x55424921
+-
+-/*
+- * Volume type constants used in the volume identifier header.
+- *
+- * @UBI_VID_DYNAMIC: dynamic volume
+- * @UBI_VID_STATIC: static volume
+- */
+-enum {
+-	UBI_VID_DYNAMIC = 1,
+-	UBI_VID_STATIC  = 2
+-};
+-
+-/*
+- * Volume flags used in the volume table record.
+- *
+- * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
+- *
+- * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
+- * table. UBI automatically re-sizes the volume which has this flag and makes
+- * the volume to be of largest possible size. This means that if after the
+- * initialization UBI finds out that there are available physical eraseblocks
+- * present on the device, it automatically appends all of them to the volume
+- * (the physical eraseblocks reserved for bad eraseblocks handling and other
+- * reserved physical eraseblocks are not taken). So, if there is a volume with
+- * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical
+- * eraseblocks will be zero after UBI is loaded, because all of them will be
+- * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared
+- * after the volume had been initialized.
+- *
+- * The auto-resize feature is useful for device production purposes. For
+- * example, different NAND flash chips may have different amount of initial bad
+- * eraseblocks, depending of particular chip instance. Manufacturers of NAND
+- * chips usually guarantee that the amount of initial bad eraseblocks does not
+- * exceed certain percent, e.g. 2%. When one creates an UBI image which will be
+- * flashed to the end devices in production, he does not know the exact amount
+- * of good physical eraseblocks the NAND chip on the device will have, but this
+- * number is required to calculate the volume sized and put them to the volume
+- * table of the UBI image. In this case, one of the volumes (e.g., the one
+- * which will store the root file system) is marked as "auto-resizable", and
+- * UBI will adjust its size on the first boot if needed.
+- *
+- * Note, first UBI reserves some amount of physical eraseblocks for bad
+- * eraseblock handling, and then re-sizes the volume, not vice-versa. This
+- * means that the pool of reserved physical eraseblocks will always be present.
+- */
+-enum {
+-	UBI_VTBL_AUTORESIZE_FLG = 0x01,
+-};
+-
+-/*
+- * Compatibility constants used by internal volumes.
+- *
+- * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
+- * to the flash
+- * @UBI_COMPAT_RO: attach this device in read-only mode
+- * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
+- * physical eraseblocks, don't allow the wear-leveling unit to move them
+- * @UBI_COMPAT_REJECT: reject this UBI image
+- */
+-enum {
+-	UBI_COMPAT_DELETE   = 1,
+-	UBI_COMPAT_RO       = 2,
+-	UBI_COMPAT_PRESERVE = 4,
+-	UBI_COMPAT_REJECT   = 5
+-};
+-
+-/* Sizes of UBI headers */
+-#define UBI_EC_HDR_SIZE  sizeof(struct ubi_ec_hdr)
+-#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
+-
+-/* Sizes of UBI headers without the ending CRC */
+-#define UBI_EC_HDR_SIZE_CRC  (UBI_EC_HDR_SIZE  - sizeof(__be32))
+-#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32))
+-
+-/**
+- * struct ubi_ec_hdr - UBI erase counter header.
+- * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
+- * @version: version of UBI implementation which is supposed to accept this
+- * UBI image
+- * @padding1: reserved for future, zeroes
+- * @ec: the erase counter
+- * @vid_hdr_offset: where the VID header starts
+- * @data_offset: where the user data start
+- * @padding2: reserved for future, zeroes
+- * @hdr_crc: erase counter header CRC checksum
+- *
+- * The erase counter header takes 64 bytes and has a plenty of unused space for
+- * future usage. The unused fields are zeroed. The @version field is used to
+- * indicate the version of UBI implementation which is supposed to be able to
+- * work with this UBI image. If @version is greater then the current UBI
+- * version, the image is rejected. This may be useful in future if something
+- * is changed radically. This field is duplicated in the volume identifier
+- * header.
+- *
+- * The @vid_hdr_offset and @data_offset fields contain the offset of the the
+- * volume identifier header and user data, relative to the beginning of the
+- * physical eraseblock. These values have to be the same for all physical
+- * eraseblocks.
+- */
+-struct ubi_ec_hdr {
+-	__be32  magic;
+-	__u8    version;
+-	__u8    padding1[3];
+-	__be64  ec; /* Warning: the current limit is 31-bit anyway! */
+-	__be32  vid_hdr_offset;
+-	__be32  data_offset;
+-	__u8    padding2[36];
+-	__be32  hdr_crc;
+-} __attribute__ ((packed));
+-
+-/**
+- * struct ubi_vid_hdr - on-flash UBI volume identifier header.
+- * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
+- * @version: UBI implementation version which is supposed to accept this UBI
+- * image (%UBI_VERSION)
+- * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
+- * @copy_flag: if this logical eraseblock was copied from another physical
+- * eraseblock (for wear-leveling reasons)
+- * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
+- * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+- * @vol_id: ID of this volume
+- * @lnum: logical eraseblock number
+- * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
+- * removed, kept only for not breaking older UBI users)
+- * @data_size: how many bytes of data this logical eraseblock contains
+- * @used_ebs: total number of used logical eraseblocks in this volume
+- * @data_pad: how many bytes at the end of this physical eraseblock are not
+- * used
+- * @data_crc: CRC checksum of the data stored in this logical eraseblock
+- * @padding1: reserved for future, zeroes
+- * @sqnum: sequence number
+- * @padding2: reserved for future, zeroes
+- * @hdr_crc: volume identifier header CRC checksum
+- *
+- * The @sqnum is the value of the global sequence counter at the time when this
+- * VID header was created. The global sequence counter is incremented each time
+- * UBI writes a new VID header to the flash, i.e. when it maps a logical
+- * eraseblock to a new physical eraseblock. The global sequence counter is an
+- * unsigned 64-bit integer and we assume it never overflows. The @sqnum
+- * (sequence number) is used to distinguish between older and newer versions of
+- * logical eraseblocks.
+- *
+- * There are 2 situations when there may be more then one physical eraseblock
+- * corresponding to the same logical eraseblock, i.e., having the same @vol_id
+- * and @lnum values in the volume identifier header. Suppose we have a logical
+- * eraseblock L and it is mapped to the physical eraseblock P.
+- *
+- * 1. Because UBI may erase physical eraseblocks asynchronously, the following
+- * situation is possible: L is asynchronously erased, so P is scheduled for
+- * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
+- * so P1 is written to, then an unclean reboot happens. Result - there are 2
+- * physical eraseblocks P and P1 corresponding to the same logical eraseblock
+- * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
+- * flash.
+- *
+- * 2. From time to time UBI moves logical eraseblocks to other physical
+- * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
+- * to P1, and an unclean reboot happens before P is physically erased, there
+- * are two physical eraseblocks P and P1 corresponding to L and UBI has to
+- * select one of them when the flash is attached. The @sqnum field says which
+- * PEB is the original (obviously P will have lower @sqnum) and the copy. But
+- * it is not enough to select the physical eraseblock with the higher sequence
+- * number, because the unclean reboot could have happen in the middle of the
+- * copying process, so the data in P is corrupted. It is also not enough to
+- * just select the physical eraseblock with lower sequence number, because the
+- * data there may be old (consider a case if more data was added to P1 after
+- * the copying). Moreover, the unclean reboot may happen when the erasure of P
+- * was just started, so it result in unstable P, which is "mostly" OK, but
+- * still has unstable bits.
+- *
+- * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
+- * copy. UBI also calculates data CRC when the data is moved and stores it at
+- * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
+- * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
+- * examined. If it is cleared, the situation* is simple and the newer one is
+- * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
+- * checksum is correct, this physical eraseblock is selected (P1). Otherwise
+- * the older one (P) is selected.
+- *
+- * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
+- * in the past. But it is not used anymore and we keep it in order to be able
+- * to deal with old UBI images. It will be removed at some point.
+- *
+- * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
+- * Internal volumes are not seen from outside and are used for various internal
+- * UBI purposes. In this implementation there is only one internal volume - the
+- * layout volume. Internal volumes are the main mechanism of UBI extensions.
+- * For example, in future one may introduce a journal internal volume. Internal
+- * volumes have their own reserved range of IDs.
+- *
+- * The @compat field is only used for internal volumes and contains the "degree
+- * of their compatibility". It is always zero for user volumes. This field
+- * provides a mechanism to introduce UBI extensions and to be still compatible
+- * with older UBI binaries. For example, if someone introduced a journal in
+- * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
+- * journal volume.  And in this case, older UBI binaries, which know nothing
+- * about the journal volume, would just delete this volume and work perfectly
+- * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
+- * - it just ignores the Ext3fs journal.
+- *
+- * The @data_crc field contains the CRC checksum of the contents of the logical
+- * eraseblock if this is a static volume. In case of dynamic volumes, it does
+- * not contain the CRC checksum as a rule. The only exception is when the
+- * data of the physical eraseblock was moved by the wear-leveling unit, then
+- * the wear-leveling unit calculates the data CRC and stores it in the
+- * @data_crc field. And of course, the @copy_flag is %in this case.
+- *
+- * The @data_size field is used only for static volumes because UBI has to know
+- * how many bytes of data are stored in this eraseblock. For dynamic volumes,
+- * this field usually contains zero. The only exception is when the data of the
+- * physical eraseblock was moved to another physical eraseblock for
+- * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
+- * contents and uses both @data_crc and @data_size fields. In this case, the
+- * @data_size field contains data size.
+- *
+- * The @used_ebs field is used only for static volumes and indicates how many
+- * eraseblocks the data of the volume takes. For dynamic volumes this field is
+- * not used and always contains zero.
+- *
+- * The @data_pad is calculated when volumes are created using the alignment
+- * parameter. So, effectively, the @data_pad field reduces the size of logical
+- * eraseblocks of this volume. This is very handy when one uses block-oriented
+- * software (say, cramfs) on top of the UBI volume.
+- */
+-struct ubi_vid_hdr {
+-	__be32  magic;
+-	__u8    version;
+-	__u8    vol_type;
+-	__u8    copy_flag;
+-	__u8    compat;
+-	__be32  vol_id;
+-	__be32  lnum;
+-	__be32  leb_ver; /* obsolete, to be removed, don't use */
+-	__be32  data_size;
+-	__be32  used_ebs;
+-	__be32  data_pad;
+-	__be32  data_crc;
+-	__u8    padding1[4];
+-	__be64  sqnum;
+-	__u8    padding2[12];
+-	__be32  hdr_crc;
+-} __attribute__ ((packed));
+-
+-/* Internal UBI volumes count */
+-#define UBI_INT_VOL_COUNT 1
+-
+-/*
+- * Starting ID of internal volumes. There is reserved room for 4096 internal
+- * volumes.
+- */
+-#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
+-
+-/* The layout volume contains the volume table */
+-
+-#define UBI_LAYOUT_VOLUME_ID     UBI_INTERNAL_VOL_START
+-#define UBI_LAYOUT_VOLUME_TYPE   UBI_VID_DYNAMIC
+-#define UBI_LAYOUT_VOLUME_ALIGN  1
+-#define UBI_LAYOUT_VOLUME_EBS    2
+-#define UBI_LAYOUT_VOLUME_NAME   "layout volume"
+-#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
+-
+-/* The maximum number of volumes per one UBI device */
+-#define UBI_MAX_VOLUMES 128
+-
+-/* The maximum volume name length */
+-#define UBI_VOL_NAME_MAX 127
+-
+-/* Size of the volume table record */
+-#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
+-
+-/* Size of the volume table record without the ending CRC */
+-#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32))
+-
+-/**
+- * struct ubi_vtbl_record - a record in the volume table.
+- * @reserved_pebs: how many physical eraseblocks are reserved for this volume
+- * @alignment: volume alignment
+- * @data_pad: how many bytes are unused at the end of the each physical
+- * eraseblock to satisfy the requested alignment
+- * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+- * @upd_marker: if volume update was started but not finished
+- * @name_len: volume name length
+- * @name: the volume name
+- * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
+- * @padding: reserved, zeroes
+- * @crc: a CRC32 checksum of the record
+- *
+- * The volume table records are stored in the volume table, which is stored in
+- * the layout volume. The layout volume consists of 2 logical eraseblock, each
+- * of which contains a copy of the volume table (i.e., the volume table is
+- * duplicated). The volume table is an array of &struct ubi_vtbl_record
+- * objects indexed by the volume ID.
+- *
+- * If the size of the logical eraseblock is large enough to fit
+- * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
+- * records. Otherwise, it contains as many records as it can fit (i.e., size of
+- * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
+- *
+- * The @upd_marker flag is used to implement volume update. It is set to %1
+- * before update and set to %0 after the update. So if the update operation was
+- * interrupted, UBI knows that the volume is corrupted.
+- *
+- * The @alignment field is specified when the volume is created and cannot be
+- * later changed. It may be useful, for example, when a block-oriented file
+- * system works on top of UBI. The @data_pad field is calculated using the
+- * logical eraseblock size and @alignment. The alignment must be multiple to the
+- * minimal flash I/O unit. If @alignment is 1, all the available space of
+- * the physical eraseblocks is used.
+- *
+- * Empty records contain all zeroes and the CRC checksum of those zeroes.
+- */
+-struct ubi_vtbl_record {
+-	__be32  reserved_pebs;
+-	__be32  alignment;
+-	__be32  data_pad;
+-	__u8    vol_type;
+-	__u8    upd_marker;
+-	__be16  name_len;
+-	__u8    name[UBI_VOL_NAME_MAX+1];
+-	__u8    flags;
+-	__u8    padding[23];
+-	__be32  crc;
+-} __attribute__ ((packed));
+-
+-#endif /* !__UBI_HEADER_H__ */
+diff --git a/include/net/addrconf.h b/include/net/addrconf.h
+index 496503c..0a2f037 100644
+--- a/include/net/addrconf.h
++++ b/include/net/addrconf.h
+@@ -55,9 +55,12 @@ struct prefix_info {
+ extern int			addrconf_init(void);
+ extern void			addrconf_cleanup(void);
+ 
+-extern int			addrconf_add_ifaddr(void __user *arg);
+-extern int			addrconf_del_ifaddr(void __user *arg);
+-extern int			addrconf_set_dstaddr(void __user *arg);
++extern int			addrconf_add_ifaddr(struct net *net,
++						    void __user *arg);
++extern int			addrconf_del_ifaddr(struct net *net,
++						    void __user *arg);
++extern int			addrconf_set_dstaddr(struct net *net,
++						     void __user *arg);
+ 
+ extern int			ipv6_chk_addr(struct net *net,
+ 					      struct in6_addr *addr,
+@@ -68,16 +71,18 @@ extern int			ipv6_chk_addr(struct net *net,
+ extern int			ipv6_chk_home_addr(struct net *net,
+ 						   struct in6_addr *addr);
+ #endif
++
++extern int			ipv6_chk_prefix(struct in6_addr *addr,
++						struct net_device *dev);
++
+ extern struct inet6_ifaddr      *ipv6_get_ifaddr(struct net *net,
+-						 struct in6_addr *addr,
++						 const struct in6_addr *addr,
+ 						 struct net_device *dev,
+ 						 int strict);
+ 
+-extern int			ipv6_get_saddr(struct dst_entry *dst, 
+-					       struct in6_addr *daddr,
+-					       struct in6_addr *saddr);
+ extern int			ipv6_dev_get_saddr(struct net_device *dev, 
+-					       struct in6_addr *daddr,
++					       const struct in6_addr *daddr,
++					       unsigned int srcprefs,
+ 					       struct in6_addr *saddr);
+ extern int			ipv6_get_lladdr(struct net_device *dev,
+ 						struct in6_addr *addr,
+@@ -100,31 +105,31 @@ extern u32			ipv6_addr_label(const struct in6_addr *addr,
+ /*
+  *	multicast prototypes (mcast.c)
+  */
+-extern int ipv6_sock_mc_join(struct sock *sk, int ifindex, 
+-		  struct in6_addr *addr);
+-extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex, 
+-		  struct in6_addr *addr);
++extern int ipv6_sock_mc_join(struct sock *sk, int ifindex,
++			     const struct in6_addr *addr);
++extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
++			     const struct in6_addr *addr);
+ extern void ipv6_sock_mc_close(struct sock *sk);
+-extern int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr,
+-		struct in6_addr *src_addr);
++extern int inet6_mc_check(struct sock *sk,
++			  const struct in6_addr *mc_addr,
++			  const struct in6_addr *src_addr);
+ 
+-extern int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr);
+-extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
+-extern int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr);
++extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
++extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
++extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
+ extern void ipv6_mc_up(struct inet6_dev *idev);
+ extern void ipv6_mc_down(struct inet6_dev *idev);
+ extern void ipv6_mc_init_dev(struct inet6_dev *idev);
+ extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
+ extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
+ 
+-extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
+-		struct in6_addr *src_addr);
++extern int ipv6_chk_mcast_addr(struct net_device *dev,
++			       const struct in6_addr *group,
++			       const struct in6_addr *src_addr);
+ extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr);
+ 
+ extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len);
+ 
+-extern int ipv6_get_hoplimit(struct net_device *dev);
+-
+ /*
+  *	anycast prototypes (anycast.c)
+  */
+@@ -135,7 +140,8 @@ extern int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex);
+ 
+ extern int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr);
+ extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr);
+-extern int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr);
++extern int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
++			       struct in6_addr *addr);
+ 
+ 
+ /* Device notifier */
+@@ -185,26 +191,6 @@ static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
+ #define in6_ifa_hold(ifp)	atomic_inc(&(ifp)->refcnt)
+ 
+ 
+-extern void			addrconf_forwarding_on(void);
+-/*
+- *	Hash function taken from net_alias.c
+- */
+-
+-static __inline__ u8 ipv6_addr_hash(const struct in6_addr *addr)
+-{	
+-	__u32 word;
+-
+-	/* 
+-	 * We perform the hash function over the last 64 bits of the address
+-	 * This will include the IEEE address token on links that support it.
+-	 */
+-
+-	word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]);
+-	word ^= (word >> 16);
+-	word ^= (word >> 8);
+-
+-	return ((word ^ (word >> 4)) & 0x0f);
+-}
+ 
+ /*
+  *	compute link-local solicited-node multicast address
+@@ -214,61 +200,31 @@ static inline void addrconf_addr_solict_mult(const struct in6_addr *addr,
+ 					     struct in6_addr *solicited)
+ {
+ 	ipv6_addr_set(solicited,
+-		      __constant_htonl(0xFF020000), 0,
+-		      __constant_htonl(0x1),
+-		      __constant_htonl(0xFF000000) | addr->s6_addr32[3]);
+-}
+-
+-
+-static inline void ipv6_addr_all_nodes(struct in6_addr *addr)
+-{
+-	ipv6_addr_set(addr,
+-		      __constant_htonl(0xFF020000), 0, 0,
+-		      __constant_htonl(0x1));
+-}
+-
+-static inline void ipv6_addr_all_routers(struct in6_addr *addr)
+-{
+-	ipv6_addr_set(addr,
+-		      __constant_htonl(0xFF020000), 0, 0,
+-		      __constant_htonl(0x2));
++		      htonl(0xFF020000), 0,
++		      htonl(0x1),
++		      htonl(0xFF000000) | addr->s6_addr32[3]);
+ }
+ 
+ static inline int ipv6_addr_is_multicast(const struct in6_addr *addr)
+ {
+-	return (addr->s6_addr32[0] & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000);
++	return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000);
+ }
+ 
+ static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
+ {
+-	return (addr->s6_addr32[0] == htonl(0xff020000) &&
+-		addr->s6_addr32[1] == 0 &&
+-		addr->s6_addr32[2] == 0 &&
+-		addr->s6_addr32[3] == htonl(0x00000001));
++	return (((addr->s6_addr32[0] ^ htonl(0xff020000)) |
++		addr->s6_addr32[1] | addr->s6_addr32[2] |
++		(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) &&
+-		addr->s6_addr32[1] == 0 &&
+-		addr->s6_addr32[2] == 0 &&
+-		addr->s6_addr32[3] == htonl(0x00000002));
++	return (((addr->s6_addr32[0] ^ htonl(0xff020000)) |
++		addr->s6_addr32[1] | addr->s6_addr32[2] |
++		(addr->s6_addr32[3] ^ htonl(0x00000002))) == 0);
+ }
+ 
+-static inline int ipv6_isatap_eui64(u8 *eui, __be32 addr)
+-{
+-	eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) ||
+-		  ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) ||
+-		  ipv4_is_private_172(addr) || ipv4_is_test_192(addr) ||
+-		  ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) ||
+-		  ipv4_is_test_198(addr) || ipv4_is_multicast(addr) ||
+-		  ipv4_is_lbcast(addr)) ? 0x00 : 0x02;
+-	eui[1] = 0;
+-	eui[2] = 0x5E;
+-	eui[3] = 0xFE;
+-	memcpy (eui+4, &addr, 4);
+-	return 0;
+-}
++extern int __ipv6_isatap_ifid(u8 *eui, __be32 addr);
+ 
+ static inline int ipv6_addr_is_isatap(const struct in6_addr *addr)
+ {
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index bcc480b..e007508 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -12,6 +12,16 @@
+  * Copyright 2006, 2007	Johannes Berg <johannes at sipsolutions.net>
+  */
+ 
++/**
++ * struct vif_params - describes virtual interface parameters
++ * @mesh_id: mesh ID to use
++ * @mesh_id_len: length of the mesh ID
++ */
++struct vif_params {
++       u8 *mesh_id;
++       int mesh_id_len;
++};
++
+ /* Radiotap header iteration
+  *   implemented in net/wireless/radiotap.c
+  *   docs in Documentation/networking/radiotap-headers.txt
+@@ -109,6 +119,19 @@ enum station_flags {
+ };
+ 
+ /**
++ * enum plink_action - actions to perform in mesh peers
++ *
++ * @PLINK_ACTION_INVALID: action 0 is reserved
++ * @PLINK_ACTION_OPEN: start mesh peer link establishment
++ * @PLINK_ACTION_BLOCL: block traffic from this mesh peer
++ */
++enum plink_actions {
++	PLINK_ACTION_INVALID,
++	PLINK_ACTION_OPEN,
++	PLINK_ACTION_BLOCK,
++};
++
++/**
+  * struct station_parameters - station parameters
+  *
+  * Used to change and create a new station.
+@@ -128,41 +151,124 @@ struct station_parameters {
+ 	int listen_interval;
+ 	u16 aid;
+ 	u8 supported_rates_len;
++	u8 plink_action;
+ };
+ 
+ /**
+- * enum station_stats_flags - station statistics flags
++ * enum station_info_flags - station information flags
+  *
+- * Used by the driver to indicate which info in &struct station_stats
+- * it has filled in during get_station().
++ * Used by the driver to indicate which info in &struct station_info
++ * it has filled in during get_station() or dump_station().
+  *
+- * @STATION_STAT_INACTIVE_TIME: @inactive_time filled
+- * @STATION_STAT_RX_BYTES: @rx_bytes filled
+- * @STATION_STAT_TX_BYTES: @tx_bytes filled
++ * @STATION_INFO_INACTIVE_TIME: @inactive_time filled
++ * @STATION_INFO_RX_BYTES: @rx_bytes filled
++ * @STATION_INFO_TX_BYTES: @tx_bytes filled
++ * @STATION_INFO_LLID: @llid filled
++ * @STATION_INFO_PLID: @plid filled
++ * @STATION_INFO_PLINK_STATE: @plink_state filled
+  */
+-enum station_stats_flags {
+-	STATION_STAT_INACTIVE_TIME	= 1<<0,
+-	STATION_STAT_RX_BYTES		= 1<<1,
+-	STATION_STAT_TX_BYTES		= 1<<2,
++enum station_info_flags {
++	STATION_INFO_INACTIVE_TIME	= 1<<0,
++	STATION_INFO_RX_BYTES		= 1<<1,
++	STATION_INFO_TX_BYTES		= 1<<2,
++	STATION_INFO_LLID		= 1<<3,
++	STATION_INFO_PLID		= 1<<4,
++	STATION_INFO_PLINK_STATE	= 1<<5,
+ };
+ 
+ /**
+- * struct station_stats - station statistics
++ * struct station_info - station information
+  *
+- * Station information filled by driver for get_station().
++ * Station information filled by driver for get_station() and dump_station.
+  *
+- * @filled: bitflag of flags from &enum station_stats_flags
++ * @filled: bitflag of flags from &enum station_info_flags
+  * @inactive_time: time since last station activity (tx/rx) in milliseconds
+  * @rx_bytes: bytes received from this station
+  * @tx_bytes: bytes transmitted to this station
++ * @llid: mesh local link id
++ * @plid: mesh peer link id
++ * @plink_state: mesh peer link state
+  */
+-struct station_stats {
++struct station_info {
+ 	u32 filled;
+ 	u32 inactive_time;
+ 	u32 rx_bytes;
+ 	u32 tx_bytes;
++	u16 llid;
++	u16 plid;
++	u8 plink_state;
++};
++
++/**
++ * enum monitor_flags - monitor flags
++ *
++ * Monitor interface configuration flags. Note that these must be the bits
++ * according to the nl80211 flags.
++ *
++ * @MONITOR_FLAG_FCSFAIL: pass frames with bad FCS
++ * @MONITOR_FLAG_PLCPFAIL: pass frames with bad PLCP
++ * @MONITOR_FLAG_CONTROL: pass control frames
++ * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering
++ * @MONITOR_FLAG_COOK_FRAMES: report frames after processing
++ */
++enum monitor_flags {
++	MONITOR_FLAG_FCSFAIL		= 1<<NL80211_MNTR_FLAG_FCSFAIL,
++	MONITOR_FLAG_PLCPFAIL		= 1<<NL80211_MNTR_FLAG_PLCPFAIL,
++	MONITOR_FLAG_CONTROL		= 1<<NL80211_MNTR_FLAG_CONTROL,
++	MONITOR_FLAG_OTHER_BSS		= 1<<NL80211_MNTR_FLAG_OTHER_BSS,
++	MONITOR_FLAG_COOK_FRAMES	= 1<<NL80211_MNTR_FLAG_COOK_FRAMES,
+ };
+ 
++/**
++ * enum mpath_info_flags -  mesh path information flags
++ *
++ * Used by the driver to indicate which info in &struct mpath_info it has filled
++ * in during get_station() or dump_station().
++ *
++ * MPATH_INFO_FRAME_QLEN: @frame_qlen filled
++ * MPATH_INFO_DSN: @dsn filled
++ * MPATH_INFO_METRIC: @metric filled
++ * MPATH_INFO_EXPTIME: @exptime filled
++ * MPATH_INFO_DISCOVERY_TIMEOUT: @discovery_timeout filled
++ * MPATH_INFO_DISCOVERY_RETRIES: @discovery_retries filled
++ * MPATH_INFO_FLAGS: @flags filled
++ */
++enum mpath_info_flags {
++	MPATH_INFO_FRAME_QLEN		= BIT(0),
++	MPATH_INFO_DSN			= BIT(1),
++	MPATH_INFO_METRIC		= BIT(2),
++	MPATH_INFO_EXPTIME		= BIT(3),
++	MPATH_INFO_DISCOVERY_TIMEOUT	= BIT(4),
++	MPATH_INFO_DISCOVERY_RETRIES	= BIT(5),
++	MPATH_INFO_FLAGS		= BIT(6),
++};
++
++/**
++ * struct mpath_info - mesh path information
++ *
++ * Mesh path information filled by driver for get_mpath() and dump_mpath().
++ *
++ * @filled: bitfield of flags from &enum mpath_info_flags
++ * @frame_qlen: number of queued frames for this destination
++ * @dsn: destination sequence number
++ * @metric: metric (cost) of this mesh path
++ * @exptime: expiration time for the mesh path from now, in msecs
++ * @flags: mesh path flags
++ * @discovery_timeout: total mesh path discovery timeout, in msecs
++ * @discovery_retries: mesh path discovery retries
++ */
++struct mpath_info {
++	u32 filled;
++	u32 frame_qlen;
++	u32 dsn;
++	u32 metric;
++	u32 exptime;
++	u32 discovery_timeout;
++	u8 discovery_retries;
++	u8 flags;
++};
++
++
+ /* from net/wireless.h */
+ struct wiphy;
+ 
+@@ -210,13 +316,17 @@ struct wiphy;
+  * @del_station: Remove a station; @mac may be NULL to remove all stations.
+  *
+  * @change_station: Modify a given station.
++ *
++ * @set_mesh_cfg: set mesh parameters (by now, just mesh id)
+  */
+ struct cfg80211_ops {
+ 	int	(*add_virtual_intf)(struct wiphy *wiphy, char *name,
+-				    enum nl80211_iftype type);
++				    enum nl80211_iftype type, u32 *flags,
++				    struct vif_params *params);
+ 	int	(*del_virtual_intf)(struct wiphy *wiphy, int ifindex);
+ 	int	(*change_virtual_intf)(struct wiphy *wiphy, int ifindex,
+-				       enum nl80211_iftype type);
++				       enum nl80211_iftype type, u32 *flags,
++				       struct vif_params *params);
+ 
+ 	int	(*add_key)(struct wiphy *wiphy, struct net_device *netdev,
+ 			   u8 key_index, u8 *mac_addr,
+@@ -244,7 +354,22 @@ struct cfg80211_ops {
+ 	int	(*change_station)(struct wiphy *wiphy, struct net_device *dev,
+ 				  u8 *mac, struct station_parameters *params);
+ 	int	(*get_station)(struct wiphy *wiphy, struct net_device *dev,
+-			       u8 *mac, struct station_stats *stats);
++			       u8 *mac, struct station_info *sinfo);
++	int	(*dump_station)(struct wiphy *wiphy, struct net_device *dev,
++			       int idx, u8 *mac, struct station_info *sinfo);
++
++	int	(*add_mpath)(struct wiphy *wiphy, struct net_device *dev,
++			       u8 *dst, u8 *next_hop);
++	int	(*del_mpath)(struct wiphy *wiphy, struct net_device *dev,
++			       u8 *dst);
++	int	(*change_mpath)(struct wiphy *wiphy, struct net_device *dev,
++				  u8 *dst, u8 *next_hop);
++	int	(*get_mpath)(struct wiphy *wiphy, struct net_device *dev,
++			       u8 *dst, u8 *next_hop,
++			       struct mpath_info *pinfo);
++	int	(*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
++			       int idx, u8 *dst, u8 *next_hop,
++			       struct mpath_info *pinfo);
+ };
+ 
+ #endif /* __NET_CFG80211_H */
+diff --git a/include/net/dst.h b/include/net/dst.h
+index ae13370..002500e 100644
+--- a/include/net/dst.h
++++ b/include/net/dst.h
+@@ -163,15 +163,7 @@ struct dst_entry * dst_clone(struct dst_entry * dst)
+ 	return dst;
+ }
+ 
+-static inline
+-void dst_release(struct dst_entry * dst)
+-{
+-	if (dst) {
+-		WARN_ON(atomic_read(&dst->__refcnt) < 1);
+-		smp_mb__before_atomic_dec();
+-		atomic_dec(&dst->__refcnt);
+-	}
+-}
++extern void dst_release(struct dst_entry *dst);
+ 
+ /* Children define the path of the packet through the
+  * Linux networking.  Thus, destinations are stackable.
+diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
+index 34349f9..a5c6ccc 100644
+--- a/include/net/fib_rules.h
++++ b/include/net/fib_rules.h
+@@ -87,6 +87,7 @@ static inline void fib_rule_get(struct fib_rule *rule)
+ static inline void fib_rule_put_rcu(struct rcu_head *head)
+ {
+ 	struct fib_rule *rule = container_of(head, struct fib_rule, rcu);
++	release_net(rule->fr_net);
+ 	kfree(rule);
+ }
+ 
+diff --git a/include/net/icmp.h b/include/net/icmp.h
+index 9f7ef3c..dddb839 100644
+--- a/include/net/icmp.h
++++ b/include/net/icmp.h
+@@ -48,7 +48,7 @@ struct sk_buff;
+ extern void	icmp_send(struct sk_buff *skb_in,  int type, int code, __be32 info);
+ extern int	icmp_rcv(struct sk_buff *skb);
+ extern int	icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+-extern void	icmp_init(struct net_proto_family *ops);
++extern int	icmp_init(void);
+ extern void	icmp_out_count(unsigned char type);
+ 
+ /* Move into dst.h ? */
+@@ -65,11 +65,4 @@ static inline struct raw_sock *raw_sk(const struct sock *sk)
+ 	return (struct raw_sock *)sk;
+ }
+ 
+-extern int sysctl_icmp_echo_ignore_all;
+-extern int sysctl_icmp_echo_ignore_broadcasts;
+-extern int sysctl_icmp_ignore_bogus_error_responses;
+-extern int sysctl_icmp_errors_use_inbound_ifaddr;
+-extern int sysctl_icmp_ratelimit;
+-extern int sysctl_icmp_ratemask;
+-
+ #endif	/* _ICMP_H */
+diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
+index 285b2ad..529816b 100644
+--- a/include/net/ieee80211.h
++++ b/include/net/ieee80211.h
+@@ -183,7 +183,6 @@ const char *escape_essid(const char *essid, u8 essid_len);
+ #define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
+ #define IEEE80211_DEBUG_QOS(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
+ #include <linux/netdevice.h>
+-#include <linux/wireless.h>
+ #include <linux/if_arp.h>	/* ARPHRD_ETHER */
+ 
+ #ifndef WIRELESS_SPY
+diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
+deleted file mode 100644
+index 1ef6282..0000000
+--- a/include/net/ieee80211softmac.h
++++ /dev/null
+@@ -1,373 +0,0 @@
+-/*
+- * ieee80211softmac.h - public interface to the softmac
+- *
+- * Copyright (c) 2005 Johannes Berg <johannes at sipsolutions.net>
+- *                    Joseph Jezak <josejx at gentoo.org>
+- *                    Larry Finger <Larry.Finger at lwfinger.net>
+- *                    Danny van Dyk <kugelfang at gentoo.org>
+- *                    Michael Buesch <mbuesch at freenet.de>
+- *
+- * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#ifndef IEEE80211SOFTMAC_H_
+-#define IEEE80211SOFTMAC_H_
+-
+-#include <linux/kernel.h>
+-#include <linux/spinlock.h>
+-#include <linux/workqueue.h>
+-#include <linux/list.h>
+-#include <net/ieee80211.h>
+-
+-/* Once the API is considered more or less stable,
+- * this should be incremented on API incompatible changes.
+- */
+-#define IEEE80211SOFTMAC_API	0
+-
+-#define IEEE80211SOFTMAC_MAX_RATES_LEN		8
+-#define IEEE80211SOFTMAC_MAX_EX_RATES_LEN	255
+-
+-struct ieee80211softmac_ratesinfo {
+-	u8 count;
+-	u8 rates[IEEE80211SOFTMAC_MAX_RATES_LEN + IEEE80211SOFTMAC_MAX_EX_RATES_LEN];
+-};
+-
+-/* internal structures */
+-struct ieee80211softmac_network;
+-struct ieee80211softmac_scaninfo;
+-
+-struct ieee80211softmac_essid {
+-	u8 len;
+-	char data[IW_ESSID_MAX_SIZE+1];
+-};
+-
+-struct ieee80211softmac_wpa {
+-	char *IE;
+-	int IElen;
+-	int IEbuflen;
+-};
+-
+-/*
+- * Information about association
+- */
+-struct ieee80211softmac_assoc_info {
+-
+-	struct mutex mutex;
+-
+-	/*
+-	 * This is the requested ESSID. It is written
+-	 * only by the WX handlers.
+-	 *
+-	 */
+-	struct ieee80211softmac_essid req_essid;
+-	/*
+-	 * the ESSID of the network we're currently
+-	 * associated (or trying) to. This is
+-	 * updated to the network's actual ESSID
+-	 * even if the requested ESSID was 'ANY'
+-	 */
+-	struct ieee80211softmac_essid associate_essid;
+-	
+-	/* BSSID we're trying to associate to */
+-	char bssid[ETH_ALEN];
+-	
+-	/* some flags.
+-	 * static_essid is valid if the essid is constant,
+-	 * this is for use by the wx handlers only.
+-	 *
+-	 * associating is true, if the network has been
+-	 * auth'ed on and we are in the process of associating.
+-	 *
+-	 * bssvalid is true if we found a matching network
+-	 * and saved it's BSSID into the bssid above.
+-	 *
+-	 * bssfixed is used for SIOCSIWAP.
+-	 */
+-	u8 static_essid;
+-	u8 short_preamble_available;
+-	u8 associating;
+-	u8 associated;
+-	u8 assoc_wait;
+-	u8 bssvalid;
+-	u8 bssfixed;
+-
+-	/* Scan retries remaining */
+-	int scan_retry;
+-
+-	struct delayed_work work;
+-	struct delayed_work timeout;
+-};
+-
+-struct ieee80211softmac_bss_info {
+-	/* Rates supported by the network */
+-	struct ieee80211softmac_ratesinfo supported_rates;
+-
+-	/* This indicates whether frames can currently be transmitted with
+-	 * short preamble (only use this variable during TX at CCK rates) */
+-	u8 short_preamble:1;
+-
+-	/* This indicates whether protection (e.g. self-CTS) should be used
+-	 * when transmitting with OFDM modulation */
+-	u8 use_protection:1;
+-};
+-
+-enum {
+-	IEEE80211SOFTMAC_AUTH_OPEN_REQUEST	= 1,
+-	IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE	= 2,
+-};
+-
+-enum {
+-	IEEE80211SOFTMAC_AUTH_SHARED_REQUEST	= 1,
+-	IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE = 2,
+-	IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE	= 3,
+-	IEEE80211SOFTMAC_AUTH_SHARED_PASS	= 4,
+-};
+-
+-/* We should make these tunable
+- * AUTH_TIMEOUT seems really long, but that's what it is in BSD */
+-#define IEEE80211SOFTMAC_AUTH_TIMEOUT		(12 * HZ)
+-#define IEEE80211SOFTMAC_AUTH_RETRY_LIMIT	5
+-#define IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT	3
+-
+-struct ieee80211softmac_txrates {
+-	/* The Bit-Rate to be used for multicast frames. */
+-	u8 mcast_rate;
+-
+-	/* The Bit-Rate to be used for multicast management frames. */
+-	u8 mgt_mcast_rate;
+-
+-	/* The Bit-Rate to be used for any other (normal) data packet. */
+-	u8 default_rate;
+-	/* The Bit-Rate to be used for default fallback
+-	 * (If the device supports fallback and hardware-retry)
+-	 */
+-	u8 default_fallback;
+-
+-	/* This is the rate that the user asked for */
+-	u8 user_rate;
+-};
+-
+-/* Bits for txrates_change callback. */
+-#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT		(1 << 0) /* default_rate */
+-#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK	(1 << 1) /* default_fallback */
+-#define IEEE80211SOFTMAC_TXRATECHG_MCAST		(1 << 2) /* mcast_rate */
+-#define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST		(1 << 3) /* mgt_mcast_rate */
+-
+-#define IEEE80211SOFTMAC_BSSINFOCHG_RATES		(1 << 0) /* supported_rates */
+-#define IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE	(1 << 1) /* short_preamble */
+-#define IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION		(1 << 2) /* use_protection */
+-
+-struct ieee80211softmac_device {
+-	/* 802.11 structure for data stuff */
+-	struct ieee80211_device *ieee;
+-	struct net_device *dev;
+-
+-	/* only valid if associated, then holds the Association ID */
+-	u16 association_id;
+-	
+-	/* the following methods are callbacks that the driver
+-	 * using this framework has to assign
+-	 */
+-
+-	/* always assign these */
+-	void (*set_bssid_filter)(struct net_device *dev, const u8 *bssid);
+-	void (*set_channel)(struct net_device *dev, u8 channel);
+-
+-	/* assign if you need it, informational only */
+-	void (*link_change)(struct net_device *dev);
+-
+-	/* If the hardware can do scanning, assign _all_ three of these callbacks.
+-	 * When the scan finishes, call ieee80211softmac_scan_finished().
+-	 */
+-	
+-	/* when called, start_scan is guaranteed to not be called again
+-	 * until you call ieee80211softmac_scan_finished.
+-	 * Return 0 if scanning could start, error otherwise.
+-	 * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_start_scan */
+-	int (*start_scan)(struct net_device *dev);
+-	/* this should block until after ieee80211softmac_scan_finished was called
+-	 * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_wait_for_scan */
+-	void (*wait_for_scan)(struct net_device *dev);
+-	/* stop_scan aborts a scan, but is asynchronous.
+-	 * if you want to wait for it too, use wait_for_scan
+-	 * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_stop_scan */
+-	void (*stop_scan)(struct net_device *dev);
+-
+-	/* we'll need something about beacons here too, for AP or ad-hoc modes */
+-
+-	/* Transmission rates to be used by the driver.
+-	 * The SoftMAC figures out the best possible rates.
+-	 * The driver just needs to read them.
+-	 */
+-	struct ieee80211softmac_txrates txrates;
+-
+-	/* If the driver needs to do stuff on TX rate changes, assign this
+-	 * callback. See IEEE80211SOFTMAC_TXRATECHG for change flags. */
+-	void (*txrates_change)(struct net_device *dev,
+-			       u32 changes);
+-
+-	/* If the driver needs to do stuff when BSS properties change, assign
+-	 * this callback. see IEEE80211SOFTMAC_BSSINFOCHG for change flags. */
+-	void (*bssinfo_change)(struct net_device *dev,
+-			       u32 changes);
+-
+-	/* private stuff follows */
+-	/* this lock protects this structure */
+-	spinlock_t lock;
+-
+-	struct workqueue_struct *wq;
+-
+-	u8 running; /* SoftMAC started? */
+-	u8 scanning;
+-
+-	struct ieee80211softmac_scaninfo *scaninfo;
+-	struct ieee80211softmac_assoc_info associnfo;
+-	struct ieee80211softmac_bss_info bssinfo;
+-
+-	struct list_head auth_queue;
+-	struct list_head events;
+-
+- 	struct ieee80211softmac_ratesinfo ratesinfo;
+-	int txrate_badness;
+-	
+-	/* WPA stuff */
+-	struct ieee80211softmac_wpa wpa;
+-
+-	/* we need to keep a list of network structs we copied */
+-	struct list_head network_list;
+-
+-	/* This must be the last item so that it points to the data
+-	 * allocated beyond this structure by alloc_ieee80211 */
+-	u8 priv[0];
+-};
+-
+-extern void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm);
+-
+-static inline void * ieee80211softmac_priv(struct net_device *dev)
+-{
+-	return ((struct ieee80211softmac_device *)ieee80211_priv(dev))->priv;
+-}
+-
+-extern struct net_device * alloc_ieee80211softmac(int sizeof_priv);
+-extern void free_ieee80211softmac(struct net_device *dev);
+-
+-/* Call this function if you detect a lost TX fragment.
+- * (If the device indicates failure of ACK RX, for example.)
+- * It is wise to call this function if you are able to detect lost packets,
+- * because it contributes to the TX Rates auto adjustment.
+- */
+-extern void ieee80211softmac_fragment_lost(struct net_device *dev,
+-					   u16 wireless_sequence_number);
+-/* Call this function before _start to tell the softmac what rates
+- * the hw supports. The rates parameter is copied, so you can
+- * free it right after calling this function. 
+- * Note that the rates need to be sorted. */
+-extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates);
+-
+-/* Finds the highest rate which is:
+- *  1. Present in ri (optionally a basic rate)
+- *  2. Supported by the device
+- *  3. Less than or equal to the user-defined rate
+- */
+-extern u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_ratesinfo *ri, int basic_only);
+-
+-/* Helper function which advises you the rate at which a frame should be
+- * transmitted at. */
+-static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac,
+-						 int is_multicast,
+-						 int is_mgt)
+-{
+-	struct ieee80211softmac_txrates *txrates = &mac->txrates;
+-
+-	if (!mac->associnfo.associated)
+-		return txrates->mgt_mcast_rate;
+-
+-	/* We are associated, sending unicast frame */
+-	if (!is_multicast)
+-		return txrates->default_rate;
+-
+-	/* We are associated, sending multicast frame */
+-	if (is_mgt)
+-		return txrates->mgt_mcast_rate;
+-	else
+-		return txrates->mcast_rate;
+-}
+-
+-/* Helper function which advises you when it is safe to transmit with short
+- * preamble.
+- * You should only call this function when transmitting at CCK rates. */
+-static inline int ieee80211softmac_short_preamble_ok(struct ieee80211softmac_device *mac,
+-						    int is_multicast,
+-						    int is_mgt)
+-{
+-	return (is_multicast && is_mgt) ? 0 : mac->bssinfo.short_preamble;
+-}
+-
+-/* Helper function which advises you whether protection (e.g. self-CTS) is
+- * needed. 1 = protection needed, 0 = no protection needed
+- * Only use this function when transmitting with OFDM modulation. */
+-static inline int ieee80211softmac_protection_needed(struct ieee80211softmac_device *mac)
+-{
+-	return mac->bssinfo.use_protection;
+-}
+-
+-/* Start the SoftMAC. Call this after you initialized the device
+- * and it is ready to run.
+- */
+-extern void ieee80211softmac_start(struct net_device *dev);
+-/* Stop the SoftMAC. Call this before you shutdown the device. */
+-extern void ieee80211softmac_stop(struct net_device *dev);
+-
+-/*
+- * Event system
+- */
+-
+-/* valid event types */
+-#define IEEE80211SOFTMAC_EVENT_ANY			-1 /*private use only*/
+-#define IEEE80211SOFTMAC_EVENT_SCAN_FINISHED		0
+-#define IEEE80211SOFTMAC_EVENT_ASSOCIATED		1
+-#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED		2
+-#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT	3
+-#define IEEE80211SOFTMAC_EVENT_AUTHENTICATED		4
+-#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED		5
+-#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT		6
+-#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND	7
+-#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED		8
+-/* keep this updated! */
+-#define IEEE80211SOFTMAC_EVENT_LAST			8
+-/*
+- * If you want to be notified of certain events, you can call
+- * ieee80211softmac_notify[_atomic] with
+- * 	- event set to one of the constants below
+- * 	- fun set to a function pointer of the appropriate type
+- *	- context set to the context data you want passed
+- * The return value is 0, or an error.
+- */
+-typedef void (*notify_function_ptr)(struct net_device *dev, int event_type, void *context);
+-
+-#define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL);
+-#define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
+-
+-extern int ieee80211softmac_notify_gfp(struct net_device *dev,
+-	int event, notify_function_ptr fun, void *context, gfp_t gfp_mask);
+-
+-/* To clear pending work (for ifconfig down, etc.) */
+-extern void
+-ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm);
+-
+-#endif /* IEEE80211SOFTMAC_H_ */
+diff --git a/include/net/ieee80211softmac_wx.h b/include/net/ieee80211softmac_wx.h
+deleted file mode 100644
+index 4ee3ad5..0000000
+--- a/include/net/ieee80211softmac_wx.h
++++ /dev/null
+@@ -1,99 +0,0 @@
+-/*
+- * This file contains the prototypes for the wireless extension
+- * handlers that the softmac API provides. Include this file to
+- * use the wx handlers, you can assign these directly.
+- *
+- * Copyright (c) 2005 Johannes Berg <johannes at sipsolutions.net>
+- *                    Joseph Jezak <josejx at gentoo.org>
+- *                    Larry Finger <Larry.Finger at lwfinger.net>
+- *                    Danny van Dyk <kugelfang at gentoo.org>
+- *                    Michael Buesch <mbuesch at freenet.de>
+- *
+- * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#ifndef _IEEE80211SOFTMAC_WX_H
+-#define _IEEE80211SOFTMAC_WX_H
+-
+-#include <net/ieee80211softmac.h>
+-#include <net/iw_handler.h>
+-
+-extern int
+-ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
+-				 struct iw_request_info *info,
+-				 union iwreq_data *data,
+-				 char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
+-				     struct iw_request_info *info,
+-				     union iwreq_data *data,
+-				     char *extra);
+-
+-extern int
+-ieee80211softmac_wx_set_essid(struct net_device *net_dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *data,
+-			      char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_essid(struct net_device *net_dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *data,
+-			      char *extra);
+-
+-extern int
+-ieee80211softmac_wx_set_rate(struct net_device *net_dev,
+-			     struct iw_request_info *info,
+-			     union iwreq_data *data,
+-			     char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_rate(struct net_device *net_dev,
+-			     struct iw_request_info *info,
+-			     union iwreq_data *data,
+-			     char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_wap(struct net_device *net_dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *data,
+-			      char *extra);
+-
+-extern int
+-ieee80211softmac_wx_set_wap(struct net_device *net_dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *data,
+-			      char *extra);
+-
+-extern int
+-ieee80211softmac_wx_set_genie(struct net_device *dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *wrqu,
+-			      char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_genie(struct net_device *dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *wrqu,
+-			      char *extra);
+-extern int
+-ieee80211softmac_wx_set_mlme(struct net_device *dev,
+-			     struct iw_request_info *info,
+-			     union iwreq_data *wrqu,
+-			     char *extra);
+-#endif /* _IEEE80211SOFTMAC_WX */
+diff --git a/include/net/inet_common.h b/include/net/inet_common.h
+index 38d5a1e..18c7732 100644
+--- a/include/net/inet_common.h
++++ b/include/net/inet_common.h
+@@ -39,6 +39,17 @@ extern int			inet_getname(struct socket *sock,
+ extern int			inet_ioctl(struct socket *sock, 
+ 					   unsigned int cmd, unsigned long arg);
+ 
++extern int			inet_ctl_sock_create(struct sock **sk,
++						     unsigned short family,
++						     unsigned short type,
++						     unsigned char protocol,
++						     struct net *net);
++
++static inline void inet_ctl_sock_destroy(struct sock *sk)
++{
++	sk_release_kernel(sk);
++}
++
+ #endif
+ 
+ 
+diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
+index f00f057..2ff545a 100644
+--- a/include/net/inet_connection_sock.h
++++ b/include/net/inet_connection_sock.h
+@@ -327,11 +327,6 @@ extern void inet_csk_listen_stop(struct sock *sk);
+ 
+ extern void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
+ 
+-extern int inet_csk_ctl_sock_create(struct socket **sock,
+-				    unsigned short family,
+-				    unsigned short type,
+-				    unsigned char protocol);
+-
+ extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
+ 				      char __user *optval, int __user *optlen);
+ extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
+diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
+index 7374251..e081eef 100644
+--- a/include/net/inet_frag.h
++++ b/include/net/inet_frag.h
+@@ -25,9 +25,9 @@ struct inet_frag_queue {
+ 	int			meat;
+ 	__u8			last_in;    /* first/last segment arrived? */
+ 
+-#define COMPLETE		4
+-#define FIRST_IN		2
+-#define LAST_IN			1
++#define INET_FRAG_COMPLETE	4
++#define INET_FRAG_FIRST_IN	2
++#define INET_FRAG_LAST_IN	1
+ };
+ 
+ #define INETFRAGS_HASHSZ		64
+diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
+index 97dc35a..735b926 100644
+--- a/include/net/inet_hashtables.h
++++ b/include/net/inet_hashtables.h
+@@ -221,26 +221,7 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
+ }
+ 
+ /* Caller must disable local BH processing. */
+-static inline void __inet_inherit_port(struct sock *sk, struct sock *child)
+-{
+-	struct inet_hashinfo *table = sk->sk_prot->hashinfo;
+-	const int bhash = inet_bhashfn(inet_sk(child)->num, 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;
+-	sk_add_bind_node(child, &tb->owners);
+-	inet_csk(child)->icsk_bind_hash = tb;
+-	spin_unlock(&head->lock);
+-}
+-
+-static inline void inet_inherit_port(struct sock *sk, struct sock *child)
+-{
+-	local_bh_disable();
+-	__inet_inherit_port(sk, child);
+-	local_bh_enable();
+-}
++extern void __inet_inherit_port(struct sock *sk, struct sock *child);
+ 
+ extern void inet_put_port(struct sock *sk);
+ 
+@@ -314,25 +295,25 @@ typedef __u64 __bitwise __addrpair;
+ 				   ((__force __u64)(__be32)(__saddr)));
+ #endif /* __BIG_ENDIAN */
+ #define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+-	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&&	\
++	(((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)	&&	\
+ 	 ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie))	&&	\
+ 	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))	&&	\
+ 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+ #define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+-	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&&	\
++	(((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)	&&	\
+ 	 ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&	\
+ 	 ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\
+ 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+ #else /* 32-bit arch */
+ #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
+ #define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)	\
+-	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&&	\
++	(((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)	&&	\
+ 	 (inet_sk(__sk)->daddr		== (__saddr))		&&	\
+ 	 (inet_sk(__sk)->rcv_saddr	== (__daddr))		&&	\
+ 	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))	&&	\
+ 	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+ #define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif)	\
+-	(((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))	&&	\
++	(((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)	&&	\
+ 	 (inet_twsk(__sk)->tw_daddr	== (__saddr))		&&	\
+ 	 (inet_twsk(__sk)->tw_rcv_saddr	== (__daddr))		&&	\
+ 	 ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\
+diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
+index 89cd011..a42cd63 100644
+--- a/include/net/inet_sock.h
++++ b/include/net/inet_sock.h
+@@ -43,8 +43,7 @@ struct ip_options {
+ 	unsigned char	srr;
+ 	unsigned char	rr;
+ 	unsigned char	ts;
+-	unsigned char	is_data:1,
+-			is_strictroute:1,
++	unsigned char	is_strictroute:1,
+ 			srr_is_hit:1,
+ 			is_changed:1,
+ 			rr_needaddr:1,
+@@ -137,7 +136,7 @@ struct inet_sock {
+ 		unsigned int		flags;
+ 		unsigned int		fragsize;
+ 		struct ip_options	*opt;
+-		struct rtable		*rt;
++		struct dst_entry	*dst;
+ 		int			length; /* Total length of all frames */
+ 		__be32			addr;
+ 		struct flowi		fl;
+@@ -195,7 +194,7 @@ static inline int inet_sk_ehashfn(const struct sock *sk)
+ 
+ static inline int inet_iif(const struct sk_buff *skb)
+ {
+-	return ((struct rtable *)skb->dst)->rt_iif;
++	return skb->rtable->rt_iif;
+ }
+ 
+ #endif	/* _INET_SOCK_H */
+diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
+index 296547b..95c660c 100644
+--- a/include/net/inet_timewait_sock.h
++++ b/include/net/inet_timewait_sock.h
+@@ -207,4 +207,22 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
+ 			       const int timeo, const int timewait_len);
+ extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
+ 				 struct inet_timewait_death_row *twdr);
++
++static inline
++struct net *twsk_net(const struct inet_timewait_sock *twsk)
++{
++#ifdef CONFIG_NET_NS
++	return twsk->tw_net;
++#else
++	return &init_net;
++#endif
++}
++
++static inline
++void twsk_net_set(struct inet_timewait_sock *twsk, struct net *net)
++{
++#ifdef CONFIG_NET_NS
++	twsk->tw_net = net;
++#endif
++}
+ #endif	/* _INET_TIMEWAIT_SOCK_ */
+diff --git a/include/net/ip.h b/include/net/ip.h
+index 9f50d4f..6d7bcd5 100644
+--- a/include/net/ip.h
++++ b/include/net/ip.h
+@@ -347,10 +347,11 @@ extern int ip_forward(struct sk_buff *skb);
+ extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, __be32 daddr, struct rtable *rt, int is_frag);
+ extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);
+ extern void ip_options_fragment(struct sk_buff *skb);
+-extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb);
+-extern int ip_options_get(struct ip_options **optp,
++extern int ip_options_compile(struct net *net,
++			      struct ip_options *opt, struct sk_buff *skb);
++extern int ip_options_get(struct net *net, struct ip_options **optp,
+ 			  unsigned char *data, int optlen);
+-extern int ip_options_get_from_user(struct ip_options **optp,
++extern int ip_options_get_from_user(struct net *net, struct ip_options **optp,
+ 				    unsigned char __user *data, int optlen);
+ extern void ip_options_undo(struct ip_options * opt);
+ extern void ip_forward_options(struct sk_buff *skb);
+@@ -361,7 +362,8 @@ extern int ip_options_rcv_srr(struct sk_buff *skb);
+  */
+ 
+ extern void	ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
+-extern int	ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc);
++extern int	ip_cmsg_send(struct net *net,
++			     struct msghdr *msg, struct ipcm_cookie *ipc);
+ extern int	ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen);
+ extern int	ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen);
+ extern int	compat_ip_setsockopt(struct sock *sk, int level,
+diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
+index 953d604..7c5c0f7 100644
+--- a/include/net/ip6_fib.h
++++ b/include/net/ip6_fib.h
+@@ -174,17 +174,19 @@ struct fib6_table {
+ #define RT6_TABLE_LOCAL		RT6_TABLE_MAIN
+ #endif
+ 
+-typedef struct rt6_info *(*pol_lookup_t)(struct fib6_table *,
++typedef struct rt6_info *(*pol_lookup_t)(struct net *,
++					 struct fib6_table *,
+ 					 struct flowi *, int);
+ 
+ /*
+  *	exported functions
+  */
+ 
+-extern struct fib6_table *	fib6_get_table(u32 id);
+-extern struct fib6_table *	fib6_new_table(u32 id);
+-extern struct dst_entry *	fib6_rule_lookup(struct flowi *fl, int flags,
+-						 pol_lookup_t lookup);
++extern struct fib6_table        *fib6_get_table(struct net *net, u32 id);
++extern struct fib6_table        *fib6_new_table(struct net *net, u32 id);
++extern struct dst_entry         *fib6_rule_lookup(struct net *net,
++						  struct flowi *fl, int flags,
++						  pol_lookup_t lookup);
+ 
+ extern struct fib6_node		*fib6_lookup(struct fib6_node *root,
+ 					     struct in6_addr *daddr,
+@@ -194,7 +196,8 @@ struct fib6_node		*fib6_locate(struct fib6_node *root,
+ 					     struct in6_addr *daddr, int dst_len,
+ 					     struct in6_addr *saddr, int src_len);
+ 
+-extern void			fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
++extern void			fib6_clean_all(struct net *net,
++					       int (*func)(struct rt6_info *, void *arg),
+ 					       int prune, void *arg);
+ 
+ extern int			fib6_add(struct fib6_node *root,
+@@ -207,7 +210,8 @@ extern int			fib6_del(struct rt6_info *rt,
+ extern void			inet6_rt_notify(int event, struct rt6_info *rt,
+ 						struct nl_info *info);
+ 
+-extern void			fib6_run_gc(unsigned long dummy);
++extern void			fib6_run_gc(unsigned long expires,
++					    struct net *net);
+ 
+ extern void			fib6_gc_cleanup(void);
+ 
+diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
+index f99e4f0..9313491 100644
+--- a/include/net/ip6_route.h
++++ b/include/net/ip6_route.h
+@@ -30,60 +30,54 @@ struct route_info {
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>
+ 
+-#define RT6_LOOKUP_F_IFACE	0x1
+-#define RT6_LOOKUP_F_REACHABLE	0x2
+-#define RT6_LOOKUP_F_HAS_SADDR	0x4
++#define RT6_LOOKUP_F_IFACE		0x00000001
++#define RT6_LOOKUP_F_REACHABLE		0x00000002
++#define RT6_LOOKUP_F_HAS_SADDR		0x00000004
++#define RT6_LOOKUP_F_SRCPREF_TMP	0x00000008
++#define RT6_LOOKUP_F_SRCPREF_PUBLIC	0x00000010
++#define RT6_LOOKUP_F_SRCPREF_COA	0x00000020
+ 
+-extern struct rt6_info	ip6_null_entry;
+ 
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+-extern struct rt6_info	ip6_prohibit_entry;
+-extern struct rt6_info	ip6_blk_hole_entry;
++extern struct rt6_info	*ip6_prohibit_entry;
++extern struct rt6_info	*ip6_blk_hole_entry;
+ #endif
+ 
+ extern void			ip6_route_input(struct sk_buff *skb);
+ 
+-extern struct dst_entry *	ip6_route_output(struct sock *sk,
++extern struct dst_entry *	ip6_route_output(struct net *net,
++						 struct sock *sk,
+ 						 struct flowi *fl);
+ 
+ extern int			ip6_route_init(void);
+ extern void			ip6_route_cleanup(void);
+ 
+-extern int			ipv6_route_ioctl(unsigned int cmd, void __user *arg);
++extern int			ipv6_route_ioctl(struct net *net,
++						 unsigned int cmd,
++						 void __user *arg);
+ 
+ extern int			ip6_route_add(struct fib6_config *cfg);
+ extern int			ip6_ins_rt(struct rt6_info *);
+ extern int			ip6_del_rt(struct rt6_info *);
+ 
+-extern int			ip6_rt_addr_add(struct in6_addr *addr,
+-						struct net_device *dev,
+-						int anycast);
+-
+-extern int			ip6_rt_addr_del(struct in6_addr *addr,
+-						struct net_device *dev);
+-
+-extern void			rt6_sndmsg(int type, struct in6_addr *dst,
+-					   struct in6_addr *src,
+-					   struct in6_addr *gw,
+-					   struct net_device *dev, 
+-					   int dstlen, int srclen,
+-					   int metric, __u32 flags);
+-
+-extern struct rt6_info		*rt6_lookup(struct in6_addr *daddr,
+-					    struct in6_addr *saddr,
++extern struct rt6_info		*rt6_lookup(struct net *net,
++					    const struct in6_addr *daddr,
++					    const struct in6_addr *saddr,
+ 					    int oif, int flags);
+ 
+-extern struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
++extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
+ 					 struct neighbour *neigh,
+-					 struct in6_addr *addr,
+-					 int (*output)(struct sk_buff *));
+-extern int ndisc_dst_gc(int *more);
+-extern void fib6_force_start_gc(void);
++					 const struct in6_addr *addr);
++extern int icmp6_dst_gc(int *more);
++
++extern void fib6_force_start_gc(struct net *net);
+ 
+ extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+ 					   const struct in6_addr *addr,
+ 					   int anycast);
+ 
++extern int			ip6_dst_hoplimit(struct dst_entry *dst);
++
+ /*
+  *	support functions for ND
+  *
+@@ -94,7 +88,7 @@ extern struct rt6_info *	rt6_add_dflt_router(struct in6_addr *gwaddr,
+ 						    struct net_device *dev,
+ 						    unsigned int pref);
+ 
+-extern void			rt6_purge_dflt_routers(void);
++extern void			rt6_purge_dflt_routers(struct net *net);
+ 
+ extern int			rt6_route_rcv(struct net_device *dev,
+ 					      u8 *opt, int len,
+@@ -121,7 +115,7 @@ struct rt6_rtnl_dump_arg
+ };
+ 
+ extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
+-extern void rt6_ifdown(struct net_device *dev);
++extern void rt6_ifdown(struct net *net, struct net_device *dev);
+ extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
+ 
+ extern rwlock_t rt6_lock;
+diff --git a/include/net/ipip.h b/include/net/ipip.h
+index 549e132..633ed4d 100644
+--- a/include/net/ipip.h
++++ b/include/net/ipip.h
+@@ -24,6 +24,16 @@ struct ip_tunnel
+ 	int			mlink;
+ 
+ 	struct ip_tunnel_parm	parms;
++
++	struct ip_tunnel_prl_entry	*prl;		/* potential router list */
++	unsigned int			prl_count;	/* # of entries in PRL */
++};
++
++struct ip_tunnel_prl_entry
++{
++	struct ip_tunnel_prl_entry	*next;
++	__be32				addr;
++	u16				flags;
+ };
+ 
+ #define IPTUNNEL_XMIT() do {						\
+diff --git a/include/net/ipv6.h b/include/net/ipv6.h
+index c0c019f..e0a612b 100644
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -202,6 +202,7 @@ struct ip6_flowlabel
+ 	u32			owner;
+ 	unsigned long		lastuse;
+ 	unsigned long		expires;
++	struct net		*fl_net;
+ };
+ 
+ #define IPV6_FLOWINFO_MASK	__constant_htonl(0x0FFFFFFF)
+@@ -249,15 +250,6 @@ int ip6_frag_mem(struct net *net);
+ 
+ #define IPV6_FRAG_TIMEOUT	(60*HZ)		/* 60 seconds */
+ 
+-/*
+- *	Function prototype for build_xmit
+- */
+-
+-typedef int		(*inet_getfrag_t) (const void *data,
+-					   struct in6_addr *addr,
+-					   char *,
+-					   unsigned int, unsigned int);
+-
+ extern int __ipv6_addr_type(const struct in6_addr *addr);
+ static inline int ipv6_addr_type(const struct in6_addr *addr)
+ {
+@@ -288,12 +280,10 @@ static inline int
+ ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
+ 		     const struct in6_addr *a2)
+ {
+-	unsigned int i;
+-
+-	for (i = 0; i < 4; i++)
+-		if ((a1->s6_addr32[i] ^ a2->s6_addr32[i]) & m->s6_addr32[i])
+-			return 1;
+-	return 0;
++	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)
+@@ -328,10 +318,10 @@ static inline void ipv6_addr_set(struct in6_addr *addr,
+ 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]);
++	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,
+@@ -379,8 +369,27 @@ static inline int ipv6_addr_any(const struct in6_addr *a)
+ 
+ static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
+ {
+-	return ((a->s6_addr32[0] | a->s6_addr32[1]) == 0 &&
+-		 a->s6_addr32[2] == htonl(0x0000ffff));
++	return ((a->s6_addr32[0] | a->s6_addr32[1] |
++		 (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0);
++}
++
++/*
++ * Check for a RFC 4843 ORCHID address
++ * (Overlay Routable Cryptographic Hash Identifiers)
++ */
++static inline int ipv6_addr_orchid(const struct in6_addr *a)
++{
++	return ((a->s6_addr32[0] & htonl(0xfffffff0))
++		== htonl(0x20010010));
++}
++
++static inline void ipv6_addr_set_v4mapped(const __be32 addr,
++					  struct in6_addr *v4mapped)
++{
++	ipv6_addr_set(v4mapped,
++			0, 0,
++			htonl(0x0000FFFF),
++			addr);
+ }
+ 
+ /*
+@@ -451,8 +460,8 @@ extern int			ip6_xmit(struct sock *sk,
+ extern int			ip6_nd_hdr(struct sock *sk,
+ 					   struct sk_buff *skb,
+ 					   struct net_device *dev,
+-					   struct in6_addr *saddr,
+-					   struct in6_addr *daddr,
++					   const struct in6_addr *saddr,
++					   const struct in6_addr *daddr,
+ 					   int proto, int len);
+ 
+ extern int			ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
+@@ -499,14 +508,6 @@ extern int			ip6_local_out(struct sk_buff *skb);
+  *	Extension header (options) processing
+  */
+ 
+-extern u8 *			ipv6_build_nfrag_opts(struct sk_buff *skb,
+-						      u8 *prev_hdr,
+-						      struct ipv6_txoptions *opt,
+-						      struct in6_addr *daddr,
+-						      u32 jumbolen);
+-extern u8 *			ipv6_build_frag_opts(struct sk_buff *skb,
+-						     u8 *prev_hdr,
+-						     struct ipv6_txoptions *opt);
+ extern void 			ipv6_push_nfrag_opts(struct sk_buff *skb,
+ 						     struct ipv6_txoptions *opt,
+ 						     u8 *proto,
+@@ -545,10 +546,6 @@ extern int			compat_ipv6_getsockopt(struct sock *sk,
+ 						char __user *optval,
+ 						int __user *optlen);
+ 
+-extern int			ipv6_packet_init(void);
+-
+-extern void			ipv6_packet_cleanup(void);
+-
+ extern int			ip6_datagram_connect(struct sock *sk, 
+ 						     struct sockaddr *addr, int addr_len);
+ 
+@@ -585,14 +582,14 @@ extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
+ 			 int __user *optlen);
+ 
+ #ifdef CONFIG_PROC_FS
+-extern int  ac6_proc_init(void);
+-extern void ac6_proc_exit(void);
++extern int  ac6_proc_init(struct net *net);
++extern void ac6_proc_exit(struct net *net);
+ extern int  raw6_proc_init(void);
+ extern void raw6_proc_exit(void);
+-extern int  tcp6_proc_init(void);
+-extern void tcp6_proc_exit(void);
+-extern int  udp6_proc_init(void);
+-extern void udp6_proc_exit(void);
++extern int  tcp6_proc_init(struct net *net);
++extern void tcp6_proc_exit(struct net *net);
++extern int  udp6_proc_init(struct net *net);
++extern void udp6_proc_exit(struct net *net);
+ extern int  udplite6_proc_init(void);
+ extern void udplite6_proc_exit(void);
+ extern int  ipv6_misc_proc_init(void);
+@@ -600,17 +597,11 @@ extern void ipv6_misc_proc_exit(void);
+ extern int snmp6_register_dev(struct inet6_dev *idev);
+ extern int snmp6_unregister_dev(struct inet6_dev *idev);
+ 
+-extern struct rt6_statistics rt6_stats;
+ #else
+-static inline int snmp6_register_dev(struct inet6_dev *idev)
+-{
+-	return 0;
+-}
+-
+-static inline int snmp6_unregister_dev(struct inet6_dev *idev)
+-{
+-	return 0;
+-}
++static inline int ac6_proc_init(struct net *net) { return 0; }
++static inline void ac6_proc_exit(struct net *net) { }
++static inline int snmp6_register_dev(struct inet6_dev *idev) { return 0; }
++static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
+ #endif
+ 
+ #ifdef CONFIG_SYSCTL
+diff --git a/include/net/irda/irlan_eth.h b/include/net/irda/irlan_eth.h
+index 0062347..de5c816 100644
+--- a/include/net/irda/irlan_eth.h
++++ b/include/net/irda/irlan_eth.h
+@@ -29,5 +29,4 @@ struct net_device *alloc_irlandev(const char *name);
+ int  irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb);
+ 
+ void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
+-void irlan_eth_send_gratuitous_arp(struct net_device *dev);
+ #endif
+diff --git a/include/net/llc_if.h b/include/net/llc_if.h
+index c608812..b595a00 100644
+--- a/include/net/llc_if.h
++++ b/include/net/llc_if.h
+@@ -74,11 +74,6 @@ static inline int llc_mac_null(const u8 *mac)
+ 	return is_zero_ether_addr(mac);
+ }
+ 
+-static inline int llc_addrany(const struct llc_addr *addr)
+-{
+-	return llc_mac_null(addr->mac) && !addr->lsap;
+-}
+-
+ static inline int llc_mac_multicast(const u8 *mac)
+ {
+ 	return is_multicast_ether_addr(mac);
+diff --git a/include/net/mac80211.h b/include/net/mac80211.h
+index 9083baf..4a80d74 100644
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -38,7 +38,11 @@
+  * called in hardware interrupt context. The low-level driver must not call any
+  * other functions in hardware interrupt context. If there is a need for such
+  * call, the low-level driver should first ACK the interrupt and perform the
+- * IEEE 802.11 code call after this, e.g. from a scheduled workqueue function.
++ * IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even
++ * tasklet function.
++ *
++ * NOTE: If the driver opts to use the _irqsafe() functions, it may not also
++ *	 use the non-irqsafe functions!
+  */
+ 
+ /**
+@@ -69,93 +73,12 @@
+  * not do so then mac80211 may add this under certain circumstances.
+  */
+ 
+-#define IEEE80211_CHAN_W_SCAN 0x00000001
+-#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002
+-#define IEEE80211_CHAN_W_IBSS 0x00000004
+-
+-/* Channel information structure. Low-level driver is expected to fill in chan,
+- * freq, and val fields. Other fields will be filled in by 80211.o based on
+- * hostapd information and low-level driver does not need to use them. The
+- * limits for each channel will be provided in 'struct ieee80211_conf' when
+- * configuring the low-level driver with hw->config callback. If a device has
+- * a default regulatory domain, IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED
+- * can be set to let the driver configure all fields */
+-struct ieee80211_channel {
+-	short chan; /* channel number (IEEE 802.11) */
+-	short freq; /* frequency in MHz */
+-	int val; /* hw specific value for the channel */
+-	int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
+-	unsigned char power_level;
+-	unsigned char antenna_max;
+-};
+-
+-#define IEEE80211_RATE_ERP 0x00000001
+-#define IEEE80211_RATE_BASIC 0x00000002
+-#define IEEE80211_RATE_PREAMBLE2 0x00000004
+-#define IEEE80211_RATE_SUPPORTED 0x00000010
+-#define IEEE80211_RATE_OFDM 0x00000020
+-#define IEEE80211_RATE_CCK 0x00000040
+-#define IEEE80211_RATE_MANDATORY 0x00000100
+-
+-#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2)
+-#define IEEE80211_RATE_MODULATION(f) \
+-	(f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM))
+-
+-/* Low-level driver should set PREAMBLE2, OFDM and CCK flags.
+- * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
+- * configuration. */
+-struct ieee80211_rate {
+-	int rate; /* rate in 100 kbps */
+-	int val; /* hw specific value for the rate */
+-	int flags; /* IEEE80211_RATE_ flags */
+-	int val2; /* hw specific value for the rate when using short preamble
+-		   * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
+-		   * 2, 5.5, and 11 Mbps) */
+-	signed char min_rssi_ack;
+-	unsigned char min_rssi_ack_delta;
+-
+-	/* following fields are set by 80211.o and need not be filled by the
+-	 * low-level driver */
+-	int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for
+-		       * optimizing channel utilization estimates */
+-};
+-
+ /**
+- * enum ieee80211_phymode - PHY modes
+- *
+- * @MODE_IEEE80211A: 5GHz as defined by 802.11a/802.11h
+- * @MODE_IEEE80211B: 2.4 GHz as defined by 802.11b
+- * @MODE_IEEE80211G: 2.4 GHz as defined by 802.11g (with OFDM),
+- *	backwards compatible with 11b mode
+- * @NUM_IEEE80211_MODES: internal
++ * enum ieee80211_notification_type - Low level driver notification
++ * @IEEE80211_NOTIFY_RE_ASSOC: start the re-association sequence
+  */
+-enum ieee80211_phymode {
+-	MODE_IEEE80211A,
+-	MODE_IEEE80211B,
+-	MODE_IEEE80211G,
+-
+-	/* keep last */
+-	NUM_IEEE80211_MODES
+-};
+-
+-/**
+- * struct ieee80211_ht_info - describing STA's HT capabilities
+- *
+- * This structure describes most essential parameters needed
+- * to describe 802.11n HT capabilities for an STA.
+- *
+- * @ht_supported: is HT supported by STA, 0: no, 1: yes
+- * @cap: HT capabilities map as described in 802.11n spec
+- * @ampdu_factor: Maximum A-MPDU length factor
+- * @ampdu_density: Minimum A-MPDU spacing
+- * @supp_mcs_set: Supported MCS set as described in 802.11n spec
+- */
+-struct ieee80211_ht_info {
+-	u8 ht_supported;
+-	u16 cap; /* use IEEE80211_HT_CAP_ */
+-	u8 ampdu_factor;
+-	u8 ampdu_density;
+-	u8 supp_mcs_set[16];
++enum ieee80211_notification_types {
++	IEEE80211_NOTIFY_RE_ASSOC,
+ };
+ 
+ /**
+@@ -175,46 +98,22 @@ struct ieee80211_ht_bss_info {
+ };
+ 
+ /**
+- * struct ieee80211_hw_mode - PHY mode definition
+- *
+- * This structure describes the capabilities supported by the device
+- * in a single PHY mode.
+- *
+- * @list: internal
+- * @channels: pointer to array of supported channels
+- * @rates: pointer to array of supported bitrates
+- * @mode: the PHY mode for this definition
+- * @num_channels: number of supported channels
+- * @num_rates: number of supported bitrates
+- * @ht_info: PHY's 802.11n HT abilities for this mode
+- */
+-struct ieee80211_hw_mode {
+-	struct list_head list;
+-	struct ieee80211_channel *channels;
+-	struct ieee80211_rate *rates;
+-	enum ieee80211_phymode mode;
+-	int num_channels;
+-	int num_rates;
+-	struct ieee80211_ht_info ht_info;
+-};
+-
+-/**
+  * struct ieee80211_tx_queue_params - transmit queue configuration
+  *
+  * The information provided in this structure is required for QoS
+- * transmit queue configuration.
++ * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29.
+  *
+  * @aifs: arbitration interface space [0..255, -1: use default]
+  * @cw_min: minimum contention window [will be a value of the form
+  *	2^n-1 in the range 1..1023; 0: use default]
+  * @cw_max: maximum contention window [like @cw_min]
+- * @burst_time: maximum burst time in units of 0.1ms, 0 meaning disabled
++ * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
+  */
+ struct ieee80211_tx_queue_params {
+-	int aifs;
+-	int cw_min;
+-	int cw_max;
+-	int burst_time;
++	s16 aifs;
++	u16 cw_min;
++	u16 cw_max;
++	u16 txop;
+ };
+ 
+ /**
+@@ -246,6 +145,7 @@ struct ieee80211_tx_queue_stats_data {
+  * @IEEE80211_TX_QUEUE_AFTER_BEACON: transmit queue for frames to be
+  *	sent after a beacon
+  * @IEEE80211_TX_QUEUE_BEACON: transmit queue for beacon frames
++ * @NUM_TX_DATA_QUEUES_AMPDU: adding more queues for A-MPDU
+  */
+ enum ieee80211_tx_queue {
+ 	IEEE80211_TX_QUEUE_DATA0,
+@@ -261,11 +161,12 @@ enum ieee80211_tx_queue {
+  * this struct need to have fixed values. As soon as it is removed, we can
+  * fix these entries. */
+ 	IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
+-	IEEE80211_TX_QUEUE_BEACON = 7
++	IEEE80211_TX_QUEUE_BEACON = 7,
++	NUM_TX_DATA_QUEUES_AMPDU = 16
+ };
+ 
+ struct ieee80211_tx_queue_stats {
+-	struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES];
++	struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES_AMPDU];
+ };
+ 
+ struct ieee80211_low_level_stats {
+@@ -285,11 +186,13 @@ struct ieee80211_low_level_stats {
+  *	also implies a change in the AID.
+  * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed
+  * @BSS_CHANGED_ERP_PREAMBLE: preamble changed
++ * @BSS_CHANGED_HT: 802.11n parameters changed
+  */
+ enum ieee80211_bss_change {
+ 	BSS_CHANGED_ASSOC		= 1<<0,
+ 	BSS_CHANGED_ERP_CTS_PROT	= 1<<1,
+ 	BSS_CHANGED_ERP_PREAMBLE	= 1<<2,
++	BSS_CHANGED_HT                  = 1<<4,
+ };
+ 
+ /**
+@@ -302,6 +205,12 @@ enum ieee80211_bss_change {
+  * @aid: association ID number, valid only when @assoc is true
+  * @use_cts_prot: use CTS protection
+  * @use_short_preamble: use 802.11b short preamble
++ * @timestamp: beacon timestamp
++ * @beacon_int: beacon interval
++ * @assoc_capability: capabbilities taken from assoc resp
++ * @assoc_ht: association in HT mode
++ * @ht_conf: ht capabilities
++ * @ht_bss_conf: ht extended capabilities
+  */
+ struct ieee80211_bss_conf {
+ 	/* association related data */
+@@ -310,6 +219,69 @@ struct ieee80211_bss_conf {
+ 	/* erp related data */
+ 	bool use_cts_prot;
+ 	bool use_short_preamble;
++	u16 beacon_int;
++	u16 assoc_capability;
++	u64 timestamp;
++	/* ht related data */
++	bool assoc_ht;
++	struct ieee80211_ht_info *ht_conf;
++	struct ieee80211_ht_bss_info *ht_bss_conf;
++};
++
++/**
++ * enum mac80211_tx_control_flags - flags to describe Tx configuration for
++ * 				    the Tx frame
++ *
++ * These flags are used with the @flags member of &ieee80211_tx_control
++ *
++ * @IEEE80211_TXCTL_REQ_TX_STATUS: request TX status callback for this frame.
++ * @IEEE80211_TXCTL_DO_NOT_ENCRYPT: send this frame without encryption;
++ * 				    e.g., for EAPOL frame
++ * @IEEE80211_TXCTL_USE_RTS_CTS: use RTS-CTS before sending frame
++ * @IEEE80211_TXCTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g.,
++ * 				     for combined 802.11g / 802.11b networks)
++ * @IEEE80211_TXCTL_NO_ACK: tell the low level not to wait for an ack
++ * @IEEE80211_TXCTL_RATE_CTRL_PROBE
++ * @EEE80211_TXCTL_CLEAR_PS_FILT: clear powersave filter
++ *                                 for destination station
++ * @IEEE80211_TXCTL_REQUEUE:
++ * @IEEE80211_TXCTL_FIRST_FRAGMENT: this is a first fragment of the frame
++ * @IEEE80211_TXCTL_LONG_RETRY_LIMIT: this frame should be send using the
++ * 				      through set_retry_limit configured long
++ * 				      retry value
++ * @IEEE80211_TXCTL_EAPOL_FRAME: internal to mac80211
++ * @IEEE80211_TXCTL_SEND_AFTER_DTIM: send this frame after DTIM beacon
++ * @IEEE80211_TXCTL_AMPDU: this frame should be sent as part of an A-MPDU
++ * @IEEE80211_TXCTL_OFDM_HT: this frame can be sent in HT OFDM rates. number
++ * 			     of streams when this flag is on can be extracted
++ *			     from antenna_sel_tx, so if 1 antenna is marked
++ *			     use SISO, 2 antennas marked use MIMO, n antennas
++ *			     marked use MIMO_n.
++ * @IEEE80211_TXCTL_GREEN_FIELD: use green field protection for this frame
++ * @IEEE80211_TXCTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width
++ * @IEEE80211_TXCTL_DUP_DATA: duplicate data frame on both 20 Mhz channels
++ * @IEEE80211_TXCTL_SHORT_GI: send this frame using short guard interval
++ */
++enum mac80211_tx_control_flags {
++	IEEE80211_TXCTL_REQ_TX_STATUS		= (1<<0),
++	IEEE80211_TXCTL_DO_NOT_ENCRYPT		= (1<<1),
++	IEEE80211_TXCTL_USE_RTS_CTS		= (1<<2),
++	IEEE80211_TXCTL_USE_CTS_PROTECT		= (1<<3),
++	IEEE80211_TXCTL_NO_ACK			= (1<<4),
++	IEEE80211_TXCTL_RATE_CTRL_PROBE		= (1<<5),
++	IEEE80211_TXCTL_CLEAR_PS_FILT		= (1<<6),
++	IEEE80211_TXCTL_REQUEUE			= (1<<7),
++	IEEE80211_TXCTL_FIRST_FRAGMENT		= (1<<8),
++	IEEE80211_TXCTL_SHORT_PREAMBLE		= (1<<9),
++	IEEE80211_TXCTL_LONG_RETRY_LIMIT	= (1<<10),
++	IEEE80211_TXCTL_EAPOL_FRAME		= (1<<11),
++	IEEE80211_TXCTL_SEND_AFTER_DTIM		= (1<<12),
++	IEEE80211_TXCTL_AMPDU			= (1<<13),
++	IEEE80211_TXCTL_OFDM_HT			= (1<<14),
++	IEEE80211_TXCTL_GREEN_FIELD		= (1<<15),
++	IEEE80211_TXCTL_40_MHZ_WIDTH		= (1<<16),
++	IEEE80211_TXCTL_DUP_DATA		= (1<<17),
++	IEEE80211_TXCTL_SHORT_GI		= (1<<18),
+ };
+ 
+ /* Transmit control fields. This data structure is passed to low-level driver
+@@ -318,57 +290,27 @@ struct ieee80211_bss_conf {
+ 
+ struct ieee80211_tx_control {
+ 	struct ieee80211_vif *vif;
+-	int tx_rate; /* Transmit rate, given as the hw specific value for the
+-		      * rate (from struct ieee80211_rate) */
+-	int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw
+-			   * specific value for the rate (from
+-			   * struct ieee80211_rate) */
+-
+-#define IEEE80211_TXCTL_REQ_TX_STATUS	(1<<0)/* request TX status callback for
+-						* this frame */
+-#define IEEE80211_TXCTL_DO_NOT_ENCRYPT	(1<<1) /* send this frame without
+-						* encryption; e.g., for EAPOL
+-						* frames */
+-#define IEEE80211_TXCTL_USE_RTS_CTS	(1<<2) /* use RTS-CTS before sending
+-						* frame */
+-#define IEEE80211_TXCTL_USE_CTS_PROTECT	(1<<3) /* use CTS protection for the
+-						* frame (e.g., for combined
+-						* 802.11g / 802.11b networks) */
+-#define IEEE80211_TXCTL_NO_ACK		(1<<4) /* tell the low level not to
+-						* wait for an ack */
+-#define IEEE80211_TXCTL_RATE_CTRL_PROBE	(1<<5)
+-#define IEEE80211_TXCTL_CLEAR_DST_MASK	(1<<6)
+-#define IEEE80211_TXCTL_REQUEUE		(1<<7)
+-#define IEEE80211_TXCTL_FIRST_FRAGMENT	(1<<8) /* this is a first fragment of
+-						* the frame */
+-#define IEEE80211_TXCTL_LONG_RETRY_LIMIT (1<<10) /* this frame should be send
+-						  * using the through
+-						  * set_retry_limit configured
+-						  * long retry value */
+-#define IEEE80211_TXCTL_EAPOL_FRAME	(1<<11) /* internal to mac80211 */
+-#define IEEE80211_TXCTL_SEND_AFTER_DTIM	(1<<12) /* send this frame after DTIM
+-						 * beacon */
+-	u32 flags;			       /* tx control flags defined
+-						* above */
++	struct ieee80211_rate *tx_rate;
++
++	/* Transmit rate for RTS/CTS frame */
++	struct ieee80211_rate *rts_cts_rate;
++
++	/* retry rate for the last retries */
++	struct ieee80211_rate *alt_retry_rate;
++
++	u32 flags;		/* tx control flags defined above */
+ 	u8 key_idx;		/* keyidx from hw->set_key(), undefined if
+ 				 * IEEE80211_TXCTL_DO_NOT_ENCRYPT is set */
+ 	u8 retry_limit;		/* 1 = only first attempt, 2 = one retry, ..
+ 				 * This could be used when set_retry_limit
+ 				 * is not implemented by the driver */
+-	u8 power_level;		/* per-packet transmit power level, in dBm */
+-	u8 antenna_sel_tx; 	/* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
++	u8 antenna_sel_tx; 	/* 0 = default/diversity, otherwise bit
++				 * position represents antenna number used */
+ 	u8 icv_len;		/* length of the ICV/MIC field in octets */
+ 	u8 iv_len;		/* length of the IV field in octets */
+ 	u8 queue;		/* hardware queue to use for this frame;
+ 				 * 0 = highest, hw->queues-1 = lowest */
+-	struct ieee80211_rate *rate;		/* internal 80211.o rate */
+-	struct ieee80211_rate *rts_rate;	/* internal 80211.o rate
+-						 * for RTS/CTS */
+-	int alt_retry_rate; /* retry rate for the last retries, given as the
+-			     * hw specific value for the rate (from
+-			     * struct ieee80211_rate). To be used to limit
+-			     * packet dropping when probing higher rates, if hw
+-			     * supports multiple retry rates. -1 = not used */
++	u16 aid;		/* Station AID */
+ 	int type;	/* internal */
+ };
+ 
+@@ -391,7 +333,8 @@ struct ieee80211_tx_control {
+  * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
+  *	the frame.
+  * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field)
+- *	is valid.
++ *	is valid. This is useful in monitor mode and necessary for beacon frames
++ *	to enable IBSS merging.
+  */
+ enum mac80211_rx_flags {
+ 	RX_FLAG_MMIC_ERROR	= 1<<0,
+@@ -410,27 +353,26 @@ enum mac80211_rx_flags {
+  * The low-level driver should provide this information (the subset
+  * supported by hardware) to the 802.11 code with each received
+  * frame.
+- * @mactime: MAC timestamp as defined by 802.11
++ * @mactime: value in microseconds of the 64-bit Time Synchronization Function
++ * 	(TSF) timer when the first data symbol (MPDU) arrived at the hardware.
++ * @band: the active band when this frame was received
+  * @freq: frequency the radio was tuned to when receiving this frame, in MHz
+- * @channel: channel the radio was tuned to
+- * @phymode: active PHY mode
+  * @ssi: signal strength when receiving this frame
+  * @signal: used as 'qual' in statistics reporting
+  * @noise: PHY noise when receiving this frame
+  * @antenna: antenna used
+- * @rate: data rate
++ * @rate_idx: index of data rate into band's supported rates
+  * @flag: %RX_FLAG_*
+  */
+ struct ieee80211_rx_status {
+ 	u64 mactime;
++	enum ieee80211_band band;
+ 	int freq;
+-	int channel;
+-	enum ieee80211_phymode phymode;
+ 	int ssi;
+ 	int signal;
+ 	int noise;
+ 	int antenna;
+-	int rate;
++	int rate_idx;
+ 	int flag;
+ };
+ 
+@@ -441,12 +383,14 @@ struct ieee80211_rx_status {
+  *
+  * @IEEE80211_TX_STATUS_TX_FILTERED: The frame was not transmitted
+  *	because the destination STA was in powersave mode.
+- *
+  * @IEEE80211_TX_STATUS_ACK: Frame was acknowledged
++ * @IEEE80211_TX_STATUS_AMPDU: The frame was aggregated, so status
++ * 	is for the whole aggregation.
+  */
+ enum ieee80211_tx_status_flags {
+ 	IEEE80211_TX_STATUS_TX_FILTERED	= 1<<0,
+ 	IEEE80211_TX_STATUS_ACK		= 1<<1,
++	IEEE80211_TX_STATUS_AMPDU	= 1<<2,
+ };
+ 
+ /**
+@@ -457,24 +401,25 @@ enum ieee80211_tx_status_flags {
+  *
+  * @control: a copy of the &struct ieee80211_tx_control passed to the driver
+  *	in the tx() callback.
+- *
+  * @flags: transmit status flags, defined above
+- *
+- * @ack_signal: signal strength of the ACK frame
+- *
++ * @retry_count: number of retries
+  * @excessive_retries: set to 1 if the frame was retried many times
+  *	but not acknowledged
+- *
+- * @retry_count: number of retries
+- *
++ * @ampdu_ack_len: number of aggregated frames.
++ * 	relevant only if IEEE80211_TX_STATUS_AMPDU was set.
++ * @ampdu_ack_map: block ack bit map for the aggregation.
++ * 	relevant only if IEEE80211_TX_STATUS_AMPDU was set.
++ * @ack_signal: signal strength of the ACK frame
+  * @queue_length: ?? REMOVE
+  * @queue_number: ?? REMOVE
+  */
+ struct ieee80211_tx_status {
+ 	struct ieee80211_tx_control control;
+ 	u8 flags;
+-	bool excessive_retries;
+ 	u8 retry_count;
++	bool excessive_retries;
++	u8 ampdu_ack_len;
++	u64 ampdu_ack_map;
+ 	int ack_signal;
+ 	int queue_length;
+ 	int queue_number;
+@@ -502,41 +447,29 @@ enum ieee80211_conf_flags {
+  *
+  * @radio_enabled: when zero, driver is required to switch off the radio.
+  *	TODO make a flag
+- * @channel: IEEE 802.11 channel number
+- * @freq: frequency in MHz
+- * @channel_val: hardware specific channel value for the channel
+- * @phymode: PHY mode to activate (REMOVE)
+- * @chan: channel to switch to, pointer to the channel information
+- * @mode: pointer to mode definition
+- * @regulatory_domain: ??
+  * @beacon_int: beacon interval (TODO make interface config)
+  * @flags: configuration flags defined above
+- * @power_level: transmit power limit for current regulatory domain in dBm
+- * @antenna_max: maximum antenna gain
++ * @power_level: requested transmit power (in dBm)
++ * @max_antenna_gain: maximum antenna gain (in dBi)
+  * @antenna_sel_tx: transmit antenna selection, 0: default/diversity,
+  *	1/2: antenna 0/1
+  * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx
+  * @ht_conf: describes current self configuration of 802.11n HT capabilies
+  * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters
++ * @channel: the channel to tune to
+  */
+ struct ieee80211_conf {
+-	int channel;			/* IEEE 802.11 channel number */
+-	int freq;			/* MHz */
+-	int channel_val;		/* hw specific value for the channel */
+-
+-	enum ieee80211_phymode phymode;
+-	struct ieee80211_channel *chan;
+-	struct ieee80211_hw_mode *mode;
+-	unsigned int regulatory_domain;
+ 	int radio_enabled;
+ 
+ 	int beacon_int;
+ 	u32 flags;
+-	u8 power_level;
+-	u8 antenna_max;
++	int power_level;
++	int max_antenna_gain;
+ 	u8 antenna_sel_tx;
+ 	u8 antenna_sel_rx;
+ 
++	struct ieee80211_channel *channel;
++
+ 	struct ieee80211_ht_info ht_conf;
+ 	struct ieee80211_ht_bss_info ht_bss_conf;
+ };
+@@ -555,12 +488,14 @@ struct ieee80211_conf {
+  * @IEEE80211_IF_TYPE_WDS: interface in WDS mode.
+  * @IEEE80211_IF_TYPE_VLAN: VLAN interface bound to an AP, drivers
+  *	will never see this type.
++ * @IEEE80211_IF_TYPE_MESH_POINT: 802.11s mesh point
+  */
+ enum ieee80211_if_types {
+ 	IEEE80211_IF_TYPE_INVALID,
+ 	IEEE80211_IF_TYPE_AP,
+ 	IEEE80211_IF_TYPE_STA,
+ 	IEEE80211_IF_TYPE_IBSS,
++	IEEE80211_IF_TYPE_MESH_POINT,
+ 	IEEE80211_IF_TYPE_MNTR,
+ 	IEEE80211_IF_TYPE_WDS,
+ 	IEEE80211_IF_TYPE_VLAN,
+@@ -582,6 +517,14 @@ struct ieee80211_vif {
+ 	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
+ };
+ 
++static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
++{
++#ifdef CONFIG_MAC80211_MESH
++	return vif->type == IEEE80211_IF_TYPE_MESH_POINT;
++#endif
++	return false;
++}
++
+ /**
+  * struct ieee80211_if_init_conf - initial configuration of an interface
+  *
+@@ -725,6 +668,21 @@ enum sta_notify_cmd {
+ };
+ 
+ /**
++ * enum ieee80211_tkip_key_type - get tkip key
++ *
++ * Used by drivers which need to get a tkip key for skb. Some drivers need a
++ * phase 1 key, others need a phase 2 key. A single function allows the driver
++ * to get the key, this enum indicates what type of key is required.
++ *
++ * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key
++ * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key
++ */
++enum ieee80211_tkip_key_type {
++	IEEE80211_TKIP_P1_KEY,
++	IEEE80211_TKIP_P2_KEY,
++};
++
++/**
+  * enum ieee80211_hw_flags - hardware flags
+  *
+  * These flags are used to indicate hardware capabilities to
+@@ -757,15 +715,19 @@ enum sta_notify_cmd {
+  *	%IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is also not set because
+  *	otherwise the stack will not know when the DTIM beacon was sent.
+  *
+- * @IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED:
+- *	Channels are already configured to the default regulatory domain
+- *	specified in the device's EEPROM
++ * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE:
++ *	Hardware is not capable of short slot operation on the 2.4 GHz band.
++ *
++ * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE:
++ *	Hardware is not capable of receiving frames with short preamble on
++ *	the 2.4 GHz band.
+  */
+ enum ieee80211_hw_flags {
+ 	IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE		= 1<<0,
+ 	IEEE80211_HW_RX_INCLUDES_FCS			= 1<<1,
+ 	IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING	= 1<<2,
+-	IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED	= 1<<3,
++	IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE		= 1<<3,
++	IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE	= 1<<4,
+ };
+ 
+ /**
+@@ -777,7 +739,8 @@ enum ieee80211_hw_flags {
+  * @wiphy: This points to the &struct wiphy allocated for this
+  *	802.11 PHY. You must fill in the @perm_addr and @dev
+  *	members of this structure using SET_IEEE80211_DEV()
+- *	and SET_IEEE80211_PERM_ADDR().
++ *	and SET_IEEE80211_PERM_ADDR(). Additionally, all supported
++ *	bands (with channels, bitrates) are registered here.
+  *
+  * @conf: &struct ieee80211_conf, device configuration, don't use.
+  *
+@@ -888,6 +851,16 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
+  * parameter is guaranteed to be valid until another call to set_key()
+  * removes it, but it can only be used as a cookie to differentiate
+  * keys.
++ *
++ * In TKIP some HW need to be provided a phase 1 key, for RX decryption
++ * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key
++ * handler.
++ * The update_tkip_key() call updates the driver with the new phase 1 key.
++ * This happens everytime the iv16 wraps around (every 65536 packets). The
++ * set_key() call will happen only once for each key (unless the AP did
++ * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is
++ * provided by udpate_tkip_key only. The trigger that makes mac80211 call this
++ * handler is software decryption with wrap around of iv16.
+  */
+ 
+ /**
+@@ -913,8 +886,18 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
+  * parameter to see whether multicast frames should be accepted
+  * or dropped.
+  *
+- * All unsupported flags in @total_flags must be cleared, i.e. you
+- * should clear all bits except those you honoured.
++ * All unsupported flags in @total_flags must be cleared.
++ * Hardware does not support a flag if it is incapable of _passing_
++ * the frame to the stack. Otherwise the driver must ignore
++ * the flag, but not clear it.
++ * You must _only_ clear the flag (announce no support for the
++ * flag to mac80211) if you are not able to pass the packet type
++ * to the stack (so the hardware always filters it).
++ * So for example, you should clear @FIF_CONTROL, if your hardware
++ * always filters control frames. If your hardware always passes
++ * control frames to the kernel and is incapable of filtering them,
++ * you do _not_ clear the @FIF_CONTROL flag.
++ * This rule applies to all other FIF flags as well.
+  */
+ 
+ /**
+@@ -967,10 +950,14 @@ enum ieee80211_filter_flags {
+  * &struct ieee80211_ops to indicate which action is needed.
+  * @IEEE80211_AMPDU_RX_START: start Rx aggregation
+  * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation
++ * @IEEE80211_AMPDU_TX_START: start Tx aggregation
++ * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation
+  */
+ enum ieee80211_ampdu_mlme_action {
+ 	IEEE80211_AMPDU_RX_START,
+ 	IEEE80211_AMPDU_RX_STOP,
++	IEEE80211_AMPDU_TX_START,
++	IEEE80211_AMPDU_TX_STOP,
+ };
+ 
+ /**
+@@ -1033,8 +1020,7 @@ enum ieee80211_ampdu_mlme_action {
+  *	level driver (e.g. assoc/disassoc status, erp parameters).
+  *	This function should not be used if no BSS has been set, unless
+  *	for association indication. The @changed parameter indicates which
+- *	of the bss parameters has changed when a call is made. This callback
+- *	has to be atomic.
++ *	of the bss parameters has changed when a call is made.
+  *
+  * @configure_filter: Configure the device's RX filter.
+  *	See the section "Frame filtering" for more information.
+@@ -1050,8 +1036,14 @@ enum ieee80211_ampdu_mlme_action {
+  *	and remove_interface calls, i.e. while the interface with the
+  *	given local_address is enabled.
+  *
++ * @update_tkip_key: See the section "Hardware crypto acceleration"
++ * 	This callback will be called in the context of Rx. Called for drivers
++ * 	which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
++ *
+  * @hw_scan: Ask the hardware to service the scan request, no need to start
+- *	the scan state machine in stack.
++ *	the scan state machine in stack. The scan must honour the channel
++ *	configuration done by the regulatory agent in the wiphy's registered
++ *	bands.
+  *
+  * @get_stats: return low-level statistics
+  *
+@@ -1111,7 +1103,8 @@ enum ieee80211_ampdu_mlme_action {
+  * 	The RA/TID combination determines the destination and TID we want
+  * 	the ampdu action to be performed for. The action is defined through
+  * 	ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
+- * 	is the first frame we expect to perform the action on.
++ * 	is the first frame we expect to perform the action on. notice
++ * 	that TX/RX_STOP can pass NULL for this parameter.
+  */
+ struct ieee80211_ops {
+ 	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1138,6 +1131,9 @@ struct ieee80211_ops {
+ 	int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ 		       const u8 *local_address, const u8 *address,
+ 		       struct ieee80211_key_conf *key);
++	void (*update_tkip_key)(struct ieee80211_hw *hw,
++			struct ieee80211_key_conf *conf, const u8 *address,
++			u32 iv32, u16 *phase1key);
+ 	int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
+ 	int (*get_stats)(struct ieee80211_hw *hw,
+ 			 struct ieee80211_low_level_stats *stats);
+@@ -1159,10 +1155,9 @@ struct ieee80211_ops {
+ 			     struct sk_buff *skb,
+ 			     struct ieee80211_tx_control *control);
+ 	int (*tx_last_beacon)(struct ieee80211_hw *hw);
+-	int (*conf_ht)(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+ 	int (*ampdu_action)(struct ieee80211_hw *hw,
+ 			    enum ieee80211_ampdu_mlme_action action,
+-			    const u8 *ra, u16 tid, u16 ssn);
++			    const u8 *addr, u16 tid, u16 *ssn);
+ };
+ 
+ /**
+@@ -1183,8 +1178,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+ /**
+  * ieee80211_register_hw - Register hardware device
+  *
+- * You must call this function before any other functions
+- * except ieee80211_register_hwmode.
++ * You must call this function before any other functions in
++ * mac80211. Note that before a hardware can be registered, you
++ * need to fill the contained wiphy's information.
+  *
+  * @hw: the device to register as returned by ieee80211_alloc_hw()
+  */
+@@ -1272,10 +1268,6 @@ static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
+ #endif
+ }
+ 
+-/* Register a new hardware PHYMODE capability to the stack. */
+-int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+-			      struct ieee80211_hw_mode *mode);
+-
+ /**
+  * ieee80211_unregister_hw - Unregister a hardware device
+  *
+@@ -1308,7 +1300,10 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+  * buffer in @skb must start with an IEEE 802.11 header or a radiotap
+  * header if %RX_FLAG_RADIOTAP is set in the @status flags.
+  *
+- * This function may not be called in IRQ context.
++ * This function may not be called in IRQ context. Calls to this function
++ * for a single hardware must be synchronized against each other. Calls
++ * to this function and ieee80211_rx_irqsafe() may not be mixed for a
++ * single hardware.
+  *
+  * @hw: the hardware this frame came in on
+  * @skb: the buffer to receive, owned by mac80211 after this call
+@@ -1325,7 +1320,10 @@ static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+  * ieee80211_rx_irqsafe - receive frame
+  *
+  * Like ieee80211_rx() but can be called in IRQ context
+- * (internally defers to a workqueue.)
++ * (internally defers to a tasklet.)
++ *
++ * Calls to this function and ieee80211_rx() may not be mixed for a
++ * single hardware.
+  *
+  * @hw: the hardware this frame came in on
+  * @skb: the buffer to receive, owned by mac80211 after this call
+@@ -1344,6 +1342,11 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw,
+  * transmitted. It is permissible to not call this function for
+  * multicast frames but this can affect statistics.
+  *
++ * This function may not be called in IRQ context. Calls to this function
++ * for a single hardware must be synchronized against each other. Calls
++ * to this function and ieee80211_tx_status_irqsafe() may not be mixed
++ * for a single hardware.
++ *
+  * @hw: the hardware the frame was transmitted by
+  * @skb: the frame that was transmitted, owned by mac80211 after this call
+  * @status: status information for this frame; the status pointer need not
+@@ -1353,6 +1356,22 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw,
+ void ieee80211_tx_status(struct ieee80211_hw *hw,
+ 			 struct sk_buff *skb,
+ 			 struct ieee80211_tx_status *status);
++
++/**
++ * ieee80211_tx_status_irqsafe - irq-safe transmit status callback
++ *
++ * Like ieee80211_tx_status() but can be called in IRQ context
++ * (internally defers to a tasklet.)
++ *
++ * Calls to this function and ieee80211_tx_status() may not be mixed for a
++ * single hardware.
++ *
++ * @hw: the hardware the frame was transmitted by
++ * @skb: the frame that was transmitted, owned by mac80211 after this call
++ * @status: status information for this frame; the status pointer need not
++ *	be valid after this function returns and is not freed by mac80211,
++ *	it is recommended that it points to a stack area
++ */
+ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+ 				 struct sk_buff *skb,
+ 				 struct ieee80211_tx_status *status);
+@@ -1449,7 +1468,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+  * @hw: pointer obtained from ieee80211_alloc_hw().
+  * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
+  * @frame_len: the length of the frame.
+- * @rate: the rate (in 100kbps) at which the frame is going to be transmitted.
++ * @rate: the rate at which the frame is going to be transmitted.
+  *
+  * Calculate the duration field of some generic frame, given its
+  * length and transmission rate (in 100kbps).
+@@ -1457,7 +1476,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
+ 					struct ieee80211_vif *vif,
+ 					size_t frame_len,
+-					int rate);
++					struct ieee80211_rate *rate);
+ 
+ /**
+  * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
+@@ -1507,6 +1526,21 @@ int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
+ int ieee80211_get_hdrlen(u16 fc);
+ 
+ /**
++ * ieee80211_get_tkip_key - get a TKIP rc4 for skb
++ *
++ * This function computes a TKIP rc4 key for an skb. It computes
++ * a phase 1 key if needed (iv16 wraps around). This function is to
++ * be used by drivers which can do HW encryption but need to compute
++ * to phase 1/2 key in SW.
++ *
++ * @keyconf: the parameter passed with the set key
++ * @skb: the skb for which the key is needed
++ * @rc4key: a buffer to which the key will be written
++ */
++void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
++				struct sk_buff *skb,
++				enum ieee80211_tkip_key_type type, u8 *key);
++/**
+  * ieee80211_wake_queue - wake specific queue
+  * @hw: pointer as obtained from ieee80211_alloc_hw().
+  * @queue: queue number (counted from zero).
+@@ -1574,4 +1608,92 @@ void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
+ 						struct ieee80211_vif *vif),
+ 					 void *data);
+ 
++/**
++ * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient
++ * @tid: the TID to BA on.
++ * @return: success if addBA request was sent, failure otherwise
++ *
++ * Although mac80211/low level driver/user space application can estimate
++ * the need to start aggregation on a certain RA/TID, the session level
++ * will be managed by the mac80211.
++ */
++int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid);
++
++/**
++ * ieee80211_start_tx_ba_cb - low level driver ready to aggregate.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient.
++ * @tid: the TID to BA on.
++ *
++ * This function must be called by low level driver once it has
++ * finished with preparations for the BA session.
++ */
++void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid);
++
++/**
++ * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient.
++ * @tid: the TID to BA on.
++ *
++ * This function must be called by low level driver once it has
++ * finished with preparations for the BA session.
++ * This version of the function is irq safe.
++ */
++void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
++				      u16 tid);
++
++/**
++ * ieee80211_stop_tx_ba_session - Stop a Block Ack session.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient
++ * @tid: the TID to stop BA.
++ * @initiator: if indicates initiator DELBA frame will be sent.
++ * @return: error if no sta with matching da found, success otherwise
++ *
++ * Although mac80211/low level driver/user space application can estimate
++ * the need to stop aggregation on a certain RA/TID, the session level
++ * will be managed by the mac80211.
++ */
++int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
++				 u8 *ra, u16 tid,
++				 enum ieee80211_back_parties initiator);
++
++/**
++ * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient.
++ * @tid: the desired TID to BA on.
++ *
++ * This function must be called by low level driver once it has
++ * finished with preparations for the BA session tear down.
++ */
++void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid);
++
++/**
++ * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient.
++ * @tid: the desired TID to BA on.
++ *
++ * This function must be called by low level driver once it has
++ * finished with preparations for the BA session tear down.
++ * This version of the function is irq safe.
++ */
++void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
++				     u16 tid);
++
++/**
++ * ieee80211_notify_mac - low level driver notification
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @notification_types: enum ieee80211_notification_types
++ *
++ * This function must be called by low level driver to inform mac80211 of
++ * low level driver status change or force mac80211 to re-assoc for low
++ * level driver internal error that require re-assoc.
++ */
++void ieee80211_notify_mac(struct ieee80211_hw *hw,
++			  enum ieee80211_notification_types  notif_type);
+ #endif /* MAC80211_H */
+diff --git a/include/net/mip6.h b/include/net/mip6.h
+index 6327261..a83ad19 100644
+--- a/include/net/mip6.h
++++ b/include/net/mip6.h
+@@ -28,9 +28,6 @@
+ #include <linux/skbuff.h>
+ #include <net/sock.h>
+ 
+-#define MIP6_OPT_PAD_1	0
+-#define MIP6_OPT_PAD_N	1
+-
+ /*
+  * Mobility Header
+  */
+diff --git a/include/net/ndisc.h b/include/net/ndisc.h
+index 59b7062..9c451ff 100644
+--- a/include/net/ndisc.h
++++ b/include/net/ndisc.h
+@@ -12,6 +12,15 @@
+ #define NDISC_REDIRECT			137
+ 
+ /*
++ * Router type: cross-layer information from link-layer to
++ * IPv6 layer reported by certain link types (e.g., RFC4214).
++ */
++#define NDISC_NODETYPE_UNSPEC		0	/* unspecified (default) */
++#define NDISC_NODETYPE_HOST		1	/* host or unauthorized router */
++#define NDISC_NODETYPE_NODEFAULT	2	/* non-default router */
++#define NDISC_NODETYPE_DEFAULT		3	/* default router */
++
++/*
+  *	ndisc options
+  */
+ 
+@@ -77,7 +86,7 @@ struct nd_opt_hdr {
+ } __attribute__((__packed__));
+ 
+ 
+-extern int			ndisc_init(struct net_proto_family *ops);
++extern int			ndisc_init(void);
+ 
+ extern void			ndisc_cleanup(void);
+ 
+@@ -85,20 +94,17 @@ extern int			ndisc_rcv(struct sk_buff *skb);
+ 
+ extern void			ndisc_send_ns(struct net_device *dev,
+ 					      struct neighbour *neigh,
+-					      struct in6_addr *solicit,
+-					      struct in6_addr *daddr,
+-					      struct in6_addr *saddr);
++					      const struct in6_addr *solicit,
++					      const struct in6_addr *daddr,
++					      const struct in6_addr *saddr);
+ 
+ extern void			ndisc_send_rs(struct net_device *dev,
+-					      struct in6_addr *saddr,
+-					      struct in6_addr *daddr);
+-
+-extern void			ndisc_forwarding_on(void);
+-extern void			ndisc_forwarding_off(void);
++					      const struct in6_addr *saddr,
++					      const struct in6_addr *daddr);
+ 
+ extern void			ndisc_send_redirect(struct sk_buff *skb,
+ 						    struct neighbour *neigh,
+-						    struct in6_addr *target);
++						    const struct in6_addr *target);
+ 
+ extern int			ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir);
+ 
+@@ -107,7 +113,7 @@ extern int			ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *d
+ /*
+  *	IGMP
+  */
+-extern int			igmp6_init(struct net_proto_family *ops);
++extern int			igmp6_init(void);
+ 
+ extern void			igmp6_cleanup(void);
+ 
+@@ -115,7 +121,6 @@ extern int			igmp6_event_query(struct sk_buff *skb);
+ 
+ extern int			igmp6_event_report(struct sk_buff *skb);
+ 
+-extern void			igmp6_cleanup(void);
+ 
+ #ifdef CONFIG_SYSCTL
+ extern int 			ndisc_ifinfo_sysctl_change(struct ctl_table *ctl,
+@@ -129,7 +134,7 @@ extern int 			ndisc_ifinfo_sysctl_change(struct ctl_table *ctl,
+ extern void 			inet6_ifinfo_notify(int event,
+ 						    struct inet6_dev *idev);
+ 
+-static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, struct in6_addr *addr)
++static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const struct in6_addr *addr)
+ {
+ 
+ 	if (dev)
+diff --git a/include/net/neighbour.h b/include/net/neighbour.h
+index 64a5f01..dc420fe 100644
+--- a/include/net/neighbour.h
++++ b/include/net/neighbour.h
+@@ -38,7 +38,9 @@ struct neighbour;
+ 
+ struct neigh_parms
+ {
++#ifdef CONFIG_NET_NS
+ 	struct net *net;
++#endif
+ 	struct net_device *dev;
+ 	struct neigh_parms *next;
+ 	int	(*neigh_setup)(struct neighbour *);
+@@ -131,7 +133,9 @@ struct neigh_ops
+ struct pneigh_entry
+ {
+ 	struct pneigh_entry	*next;
++#ifdef CONFIG_NET_NS
+ 	struct net		*net;
++#endif
+ 	struct net_device	*dev;
+ 	u8			flags;
+ 	u8			key[0];
+@@ -213,6 +217,17 @@ extern struct neighbour 	*neigh_event_ns(struct neigh_table *tbl,
+ 
+ extern struct neigh_parms	*neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
+ extern void			neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
++
++static inline
++struct net			*neigh_parms_net(const struct neigh_parms *parms)
++{
++#ifdef CONFIG_NET_NS
++	return parms->net;
++#else
++	return &init_net;
++#endif
++}
++
+ extern unsigned long		neigh_rand_reach_time(unsigned long base);
+ 
+ extern void			pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+@@ -224,6 +239,16 @@ extern struct pneigh_entry	*__pneigh_lookup(struct neigh_table *tbl,
+ 						 struct net_device *dev);
+ extern int			pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev);
+ 
++static inline
++struct net			*pneigh_net(const struct pneigh_entry *pneigh)
++{
++#ifdef CONFIG_NET_NS
++	return pneigh->net;
++#else
++	return &init_net;
++#endif
++}
++
+ extern void neigh_app_ns(struct neighbour *n);
+ extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
+ extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
+@@ -288,12 +313,6 @@ static inline void neigh_confirm(struct neighbour *neigh)
+ 		neigh->confirmed = jiffies;
+ }
+ 
+-static inline int neigh_is_connected(struct neighbour *neigh)
+-{
+-	return neigh->nud_state&NUD_CONNECTED;
+-}
+-
+-
+ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
+ {
+ 	neigh->used = jiffies;
+diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
+index 923f2b8..aa540e6 100644
+--- a/include/net/net_namespace.h
++++ b/include/net/net_namespace.h
+@@ -8,24 +8,29 @@
+ #include <linux/workqueue.h>
+ #include <linux/list.h>
+ 
++#include <net/netns/core.h>
+ #include <net/netns/unix.h>
+ #include <net/netns/packet.h>
+ #include <net/netns/ipv4.h>
+ #include <net/netns/ipv6.h>
++#include <net/netns/dccp.h>
+ #include <net/netns/x_tables.h>
+ 
+ struct proc_dir_entry;
+ struct net_device;
+ struct sock;
+ struct ctl_table_header;
++struct net_generic;
+ 
+ struct net {
+ 	atomic_t		count;		/* To decided when the network
+ 						 *  namespace should be freed.
+ 						 */
++#ifdef NETNS_REFCNT_DEBUG
+ 	atomic_t		use_count;	/* To track references we
+ 						 * destroy on demand
+ 						 */
++#endif
+ 	struct list_head	list;		/* list of network namespaces */
+ 	struct work_struct	work;		/* work struct for freeing */
+ 
+@@ -46,40 +51,46 @@ struct net {
+ 
+ 	struct sock 		*rtnl;			/* rtnetlink socket */
+ 
+-	/* core sysctls */
+-	struct ctl_table_header	*sysctl_core_hdr;
+-	int			sysctl_somaxconn;
+-
++	struct netns_core	core;
+ 	struct netns_packet	packet;
+ 	struct netns_unix	unx;
+ 	struct netns_ipv4	ipv4;
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ 	struct netns_ipv6	ipv6;
+ #endif
++#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
++	struct netns_dccp	dccp;
++#endif
+ #ifdef CONFIG_NETFILTER
+ 	struct netns_xt		xt;
+ #endif
++	struct net_generic	*gen;
+ };
+ 
+-#ifdef CONFIG_NET
++
++#include <linux/seq_file_net.h>
++
+ /* Init's network namespace */
+ extern struct net init_net;
+-#define INIT_NET_NS(net_ns) .net_ns = &init_net,
+-#else
+-#define INIT_NET_NS(net_ns)
+-#endif
+-
+-extern struct list_head net_namespace_list;
+ 
+ #ifdef CONFIG_NET
++#define INIT_NET_NS(net_ns) .net_ns = &init_net,
++
+ extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
+-#else
++
++#else /* CONFIG_NET */
++
++#define INIT_NET_NS(net_ns)
++
+ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
+ {
+ 	/* There is nothing to copy so this is a noop */
+ 	return net_ns;
+ }
+-#endif
++#endif /* CONFIG_NET */
++
++
++extern struct list_head net_namespace_list;
+ 
+ #ifdef CONFIG_NET_NS
+ extern void __put_net(struct net *net);
+@@ -108,41 +119,59 @@ static inline void put_net(struct net *net)
+ 		__put_net(net);
+ }
+ 
+-static inline struct net *hold_net(struct net *net)
++static inline
++int net_eq(const struct net *net1, const struct net *net2)
++{
++	return net1 == net2;
++}
++#else
++static inline struct net *get_net(struct net *net)
+ {
+-	atomic_inc(&net->use_count);
+ 	return net;
+ }
+ 
+-static inline void release_net(struct net *net)
++static inline void put_net(struct net *net)
+ {
+-	atomic_dec(&net->use_count);
+ }
+-#else
+-static inline struct net *get_net(struct net *net)
++
++static inline struct net *maybe_get_net(struct net *net)
+ {
+ 	return net;
+ }
+ 
+-static inline void put_net(struct net *net)
++static inline
++int net_eq(const struct net *net1, const struct net *net2)
+ {
++	return 1;
+ }
++#endif
++
+ 
++#ifdef NETNS_REFCNT_DEBUG
+ static inline struct net *hold_net(struct net *net)
+ {
++	if (net)
++		atomic_inc(&net->use_count);
+ 	return net;
+ }
+ 
+ static inline void release_net(struct net *net)
+ {
++	if (net)
++		atomic_dec(&net->use_count);
+ }
+-
+-static inline struct net *maybe_get_net(struct net *net)
++#else
++static inline struct net *hold_net(struct net *net)
+ {
+ 	return net;
+ }
++
++static inline void release_net(struct net *net)
++{
++}
+ #endif
+ 
++
+ #define for_each_net(VAR)				\
+ 	list_for_each_entry(VAR, &net_namespace_list, list)
+ 
+@@ -166,6 +195,8 @@ extern int register_pernet_subsys(struct pernet_operations *);
+ extern void unregister_pernet_subsys(struct pernet_operations *);
+ extern int register_pernet_device(struct pernet_operations *);
+ extern void unregister_pernet_device(struct pernet_operations *);
++extern int register_pernet_gen_device(int *id, struct pernet_operations *);
++extern void unregister_pernet_gen_device(int id, struct pernet_operations *);
+ 
+ struct ctl_path;
+ struct ctl_table;
+diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
+index 90b3e7f..2dbd6c0 100644
+--- a/include/net/netfilter/nf_conntrack.h
++++ b/include/net/netfilter/nf_conntrack.h
+@@ -20,6 +20,7 @@
+ #include <asm/atomic.h>
+ 
+ #include <linux/netfilter/nf_conntrack_tcp.h>
++#include <linux/netfilter/nf_conntrack_dccp.h>
+ #include <linux/netfilter/nf_conntrack_sctp.h>
+ #include <linux/netfilter/nf_conntrack_proto_gre.h>
+ #include <net/netfilter/ipv4/nf_conntrack_icmp.h>
+@@ -30,6 +31,7 @@
+ /* per conntrack: protocol private data */
+ union nf_conntrack_proto {
+ 	/* insert conntrack proto private data here */
++	struct nf_ct_dccp dccp;
+ 	struct ip_ct_sctp sctp;
+ 	struct ip_ct_tcp tcp;
+ 	struct ip_ct_icmp icmp;
+@@ -46,6 +48,7 @@ union nf_conntrack_expect_proto {
+ #include <linux/netfilter/nf_conntrack_pptp.h>
+ #include <linux/netfilter/nf_conntrack_h323.h>
+ #include <linux/netfilter/nf_conntrack_sane.h>
++#include <linux/netfilter/nf_conntrack_sip.h>
+ 
+ /* per conntrack: application helper private data */
+ union nf_conntrack_help {
+@@ -54,6 +57,7 @@ union nf_conntrack_help {
+ 	struct nf_ct_pptp_master ct_pptp_info;
+ 	struct nf_ct_h323_master ct_h323_info;
+ 	struct nf_ct_sane_master ct_sane_info;
++	struct nf_ct_sip_master ct_sip_info;
+ };
+ 
+ #include <linux/types.h>
+@@ -61,20 +65,16 @@ union nf_conntrack_help {
+ #include <linux/timer.h>
+ 
+ #ifdef CONFIG_NETFILTER_DEBUG
+-#define NF_CT_ASSERT(x)							\
+-do {									\
+-	if (!(x))							\
+-		/* Wooah!  I'm tripping my conntrack in a frenzy of	\
+-		   netplay... */					\
+-		printk("NF_CT_ASSERT: %s:%i(%s)\n",			\
+-		       __FILE__, __LINE__, __FUNCTION__);		\
+-} while(0)
++#define NF_CT_ASSERT(x)		WARN_ON(!(x))
+ #else
+ #define NF_CT_ASSERT(x)
+ #endif
+ 
+ struct nf_conntrack_helper;
+ 
++/* Must be kept in sync with the classes defined by helpers */
++#define NF_CT_MAX_EXPECT_CLASSES	3
++
+ /* nf_conn feature for connections that have a helper */
+ struct nf_conn_help {
+ 	/* Helper. if any */
+@@ -85,7 +85,7 @@ struct nf_conn_help {
+ 	struct hlist_head expectations;
+ 
+ 	/* Current number of expected connections */
+-	unsigned int expecting;
++	u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
+ };
+ 
+ 
+@@ -140,6 +140,16 @@ nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash)
+ 			    tuplehash[hash->tuple.dst.dir]);
+ }
+ 
++static inline u_int16_t nf_ct_l3num(const struct nf_conn *ct)
++{
++	return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
++}
++
++static inline u_int8_t nf_ct_protonum(const struct nf_conn *ct)
++{
++	return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
++}
++
+ /* get master conntrack via master expectation */
+ #define master_ct(conntr) (conntr->master)
+ 
+@@ -184,12 +194,11 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct);
+ 
+ extern void nf_conntrack_flush(void);
+ 
+-extern int nf_ct_get_tuplepr(const struct sk_buff *skb,
+-			     unsigned int nhoff,
+-			     u_int16_t l3num,
+-			     struct nf_conntrack_tuple *tuple);
+-extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
+-				const struct nf_conntrack_tuple *orig);
++extern bool nf_ct_get_tuplepr(const struct sk_buff *skb,
++			      unsigned int nhoff, u_int16_t l3num,
++			      struct nf_conntrack_tuple *tuple);
++extern bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
++				 const struct nf_conntrack_tuple *orig);
+ 
+ extern void __nf_ct_refresh_acct(struct nf_conn *ct,
+ 				 enum ip_conntrack_info ctinfo,
+diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
+index 9ee2646..a817712 100644
+--- a/include/net/netfilter/nf_conntrack_core.h
++++ b/include/net/netfilter/nf_conntrack_core.h
+@@ -30,7 +30,7 @@ extern void nf_conntrack_cleanup(void);
+ extern int nf_conntrack_proto_init(void);
+ extern void nf_conntrack_proto_fini(void);
+ 
+-extern int
++extern bool
+ nf_ct_get_tuple(const struct sk_buff *skb,
+ 		unsigned int nhoff,
+ 		unsigned int dataoff,
+@@ -40,7 +40,7 @@ nf_ct_get_tuple(const struct sk_buff *skb,
+ 		const struct nf_conntrack_l3proto *l3proto,
+ 		const struct nf_conntrack_l4proto *l4proto);
+ 
+-extern int
++extern bool
+ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
+ 		   const struct nf_conntrack_tuple *orig,
+ 		   const struct nf_conntrack_l3proto *l3proto,
+diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
+index cb608a1..dfdf4b4 100644
+--- a/include/net/netfilter/nf_conntrack_expect.h
++++ b/include/net/netfilter/nf_conntrack_expect.h
+@@ -41,6 +41,9 @@ struct nf_conntrack_expect
+ 	/* Flags */
+ 	unsigned int flags;
+ 
++	/* Expectation class */
++	unsigned int class;
++
+ #ifdef CONFIG_NF_NAT_NEEDED
+ 	__be32 saved_ip;
+ 	/* This is the original per-proto part, used to map the
+@@ -53,7 +56,16 @@ struct nf_conntrack_expect
+ 	struct rcu_head rcu;
+ };
+ 
+-#define NF_CT_EXPECT_PERMANENT 0x1
++struct nf_conntrack_expect_policy
++{
++	unsigned int	max_expected;
++	unsigned int	timeout;
++};
++
++#define NF_CT_EXPECT_CLASS_DEFAULT	0
++
++#define NF_CT_EXPECT_PERMANENT	0x1
++#define NF_CT_EXPECT_INACTIVE	0x2
+ 
+ int nf_conntrack_expect_init(void);
+ void nf_conntrack_expect_fini(void);
+@@ -74,10 +86,10 @@ void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
+ /* Allocate space for an expectation: this is mandatory before calling
+    nf_ct_expect_related.  You will have to call put afterwards. */
+ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
+-void nf_ct_expect_init(struct nf_conntrack_expect *, int,
+-		       union nf_inet_addr *,
+-		       union nf_inet_addr *,
+-		       u_int8_t, __be16 *, __be16 *);
++void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, int,
++		       const union nf_inet_addr *,
++		       const union nf_inet_addr *,
++		       u_int8_t, const __be16 *, const __be16 *);
+ void nf_ct_expect_put(struct nf_conntrack_expect *exp);
+ int nf_ct_expect_related(struct nf_conntrack_expect *expect);
+ 
+diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
+index 4ca125e..f8060ab 100644
+--- a/include/net/netfilter/nf_conntrack_helper.h
++++ b/include/net/netfilter/nf_conntrack_helper.h
+@@ -20,9 +20,7 @@ struct nf_conntrack_helper
+ 
+ 	const char *name;		/* name of the module */
+ 	struct module *me;		/* pointer to self */
+-	unsigned int max_expected;	/* Maximum number of concurrent 
+-					 * expected connections */
+-	unsigned int timeout;		/* timeout for expecteds */
++	const struct nf_conntrack_expect_policy *expect_policy;
+ 
+ 	/* Tuple of things we will help (compared against server response) */
+ 	struct nf_conntrack_tuple tuple;
+@@ -37,6 +35,7 @@ struct nf_conntrack_helper
+ 	void (*destroy)(struct nf_conn *ct);
+ 
+ 	int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
++	unsigned int expect_class_max;
+ };
+ 
+ extern struct nf_conntrack_helper *
+diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
+index b886e3a..0378676 100644
+--- a/include/net/netfilter/nf_conntrack_l3proto.h
++++ b/include/net/netfilter/nf_conntrack_l3proto.h
+@@ -28,31 +28,20 @@ struct nf_conntrack_l3proto
+ 	 * Try to fill in the third arg: nhoff is offset of l3 proto
+          * hdr.  Return true if possible.
+ 	 */
+-	int (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int nhoff,
+-			    struct nf_conntrack_tuple *tuple);
++	bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int nhoff,
++			     struct nf_conntrack_tuple *tuple);
+ 
+ 	/*
+ 	 * Invert the per-proto part of the tuple: ie. turn xmit into reply.
+ 	 * Some packets can't be inverted: return 0 in that case.
+ 	 */
+-	int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+-			    const struct nf_conntrack_tuple *orig);
++	bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
++			     const struct nf_conntrack_tuple *orig);
+ 
+ 	/* Print out the per-protocol part of the tuple. */
+ 	int (*print_tuple)(struct seq_file *s,
+ 			   const struct nf_conntrack_tuple *);
+ 
+-	/* Returns verdict for packet, or -1 for invalid. */
+-	int (*packet)(struct nf_conn *ct,
+-		      const struct sk_buff *skb,
+-		      enum ip_conntrack_info ctinfo);
+-
+-	/*
+-	 * Called when a new connection for this protocol found;
+-	 * returns TRUE if it's OK.  If so, packet() called next.
+-	 */
+-	int (*new)(struct nf_conn *ct, const struct sk_buff *skb);
+-
+ 	/*
+ 	 * Called before tracking. 
+ 	 *	*dataoff: offset of protocol header (TCP, UDP,...) in skb
+diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
+index efc16ec..723df9d 100644
+--- a/include/net/netfilter/nf_conntrack_l4proto.h
++++ b/include/net/netfilter/nf_conntrack_l4proto.h
+@@ -25,15 +25,14 @@ struct nf_conntrack_l4proto
+ 
+ 	/* Try to fill in the third arg: dataoff is offset past network protocol
+            hdr.  Return true if possible. */
+-	int (*pkt_to_tuple)(const struct sk_buff *skb,
+-			    unsigned int dataoff,
+-			    struct nf_conntrack_tuple *tuple);
++	bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int dataoff,
++			     struct nf_conntrack_tuple *tuple);
+ 
+ 	/* Invert the per-proto part of the tuple: ie. turn xmit into reply.
+ 	 * Some packets can't be inverted: return 0 in that case.
+ 	 */
+-	int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+-			    const struct nf_conntrack_tuple *orig);
++	bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
++			     const struct nf_conntrack_tuple *orig);
+ 
+ 	/* Returns verdict for packet, or -1 for invalid. */
+ 	int (*packet)(struct nf_conn *ct,
+@@ -45,8 +44,8 @@ struct nf_conntrack_l4proto
+ 
+ 	/* Called when a new connection for this protocol found;
+ 	 * returns TRUE if it's OK.  If so, packet() called next. */
+-	int (*new)(struct nf_conn *ct, const struct sk_buff *skb,
+-		   unsigned int dataoff);
++	bool (*new)(struct nf_conn *ct, const struct sk_buff *skb,
++		    unsigned int dataoff);
+ 
+ 	/* Called when a conntrack entry is destroyed */
+ 	void (*destroy)(struct nf_conn *ct);
+diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
+index e69ab2e..1bb7087 100644
+--- a/include/net/netfilter/nf_conntrack_tuple.h
++++ b/include/net/netfilter/nf_conntrack_tuple.h
+@@ -41,6 +41,9 @@ union nf_conntrack_man_proto
+ 	} icmp;
+ 	struct {
+ 		__be16 port;
++	} dccp;
++	struct {
++		__be16 port;
+ 	} sctp;
+ 	struct {
+ 		__be16 key;	/* GRE key is 32bit, PPtP only uses 16bit */
+@@ -79,6 +82,9 @@ struct nf_conntrack_tuple
+ 			} icmp;
+ 			struct {
+ 				__be16 port;
++			} dccp;
++			struct {
++				__be16 port;
+ 			} sctp;
+ 			struct {
+ 				__be16 key;
+@@ -113,11 +119,37 @@ struct nf_conntrack_tuple_mask
+ 
+ #ifdef __KERNEL__
+ 
+-#define NF_CT_DUMP_TUPLE(tp)						     \
+-pr_debug("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",	     \
+-	 (tp), (tp)->src.l3num, (tp)->dst.protonum,			     \
+-	 NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
+-	 NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
++static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t)
++{
++#ifdef DEBUG
++	printk("tuple %p: %u " NIPQUAD_FMT ":%hu -> " NIPQUAD_FMT ":%hu\n",
++	       t, t->dst.protonum,
++	       NIPQUAD(t->src.u3.ip), ntohs(t->src.u.all),
++	       NIPQUAD(t->dst.u3.ip), ntohs(t->dst.u.all));
++#endif
++}
++
++static inline void nf_ct_dump_tuple_ipv6(const struct nf_conntrack_tuple *t)
++{
++#ifdef DEBUG
++	printk("tuple %p: %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",
++	       t, t->dst.protonum,
++	       NIP6(*(struct in6_addr *)t->src.u3.all), ntohs(t->src.u.all),
++	       NIP6(*(struct in6_addr *)t->dst.u3.all), ntohs(t->dst.u.all));
++#endif
++}
++
++static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t)
++{
++	switch (t->src.l3num) {
++	case AF_INET:
++		nf_ct_dump_tuple_ip(t);
++		break;
++	case AF_INET6:
++		nf_ct_dump_tuple_ipv6(t);
++		break;
++	}
++}
+ 
+ /* If we're the first tuple, it's the original dir. */
+ #define NF_CT_DIRECTION(h)						\
+@@ -132,70 +164,64 @@ struct nf_conntrack_tuple_hash
+ 
+ #endif /* __KERNEL__ */
+ 
+-static inline int __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
+-					  const struct nf_conntrack_tuple *t2)
++static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
++					   const struct nf_conntrack_tuple *t2)
+ { 
+-	return (t1->src.u3.all[0] == t2->src.u3.all[0] &&
+-		t1->src.u3.all[1] == t2->src.u3.all[1] &&
+-		t1->src.u3.all[2] == t2->src.u3.all[2] &&
+-		t1->src.u3.all[3] == t2->src.u3.all[3] &&
++	return (nf_inet_addr_cmp(&t1->src.u3, &t2->src.u3) &&
+ 		t1->src.u.all == t2->src.u.all &&
+ 		t1->src.l3num == t2->src.l3num);
+ }
+ 
+-static inline int __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
+-					  const struct nf_conntrack_tuple *t2)
++static inline bool __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
++					   const struct nf_conntrack_tuple *t2)
+ {
+-	return (t1->dst.u3.all[0] == t2->dst.u3.all[0] &&
+-		t1->dst.u3.all[1] == t2->dst.u3.all[1] &&
+-		t1->dst.u3.all[2] == t2->dst.u3.all[2] &&
+-		t1->dst.u3.all[3] == t2->dst.u3.all[3] &&
++	return (nf_inet_addr_cmp(&t1->dst.u3, &t2->dst.u3) &&
+ 		t1->dst.u.all == t2->dst.u.all &&
+ 		t1->dst.protonum == t2->dst.protonum);
+ }
+ 
+-static inline int nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
+-				    const struct nf_conntrack_tuple *t2)
++static inline bool nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
++				     const struct nf_conntrack_tuple *t2)
+ {
+ 	return __nf_ct_tuple_src_equal(t1, t2) &&
+ 	       __nf_ct_tuple_dst_equal(t1, t2);
+ }
+ 
+-static inline int nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
+-					 const struct nf_conntrack_tuple_mask *m2)
++static inline bool
++nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
++		       const struct nf_conntrack_tuple_mask *m2)
+ {
+-	return (m1->src.u3.all[0] == m2->src.u3.all[0] &&
+-		m1->src.u3.all[1] == m2->src.u3.all[1] &&
+-		m1->src.u3.all[2] == m2->src.u3.all[2] &&
+-		m1->src.u3.all[3] == m2->src.u3.all[3] &&
++	return (nf_inet_addr_cmp(&m1->src.u3, &m2->src.u3) &&
+ 		m1->src.u.all == m2->src.u.all);
+ }
+ 
+-static inline int nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
+-					   const struct nf_conntrack_tuple *t2,
+-					   const struct nf_conntrack_tuple_mask *mask)
++static inline bool
++nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
++			 const struct nf_conntrack_tuple *t2,
++			 const struct nf_conntrack_tuple_mask *mask)
+ {
+ 	int count;
+ 
+ 	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) {
+ 		if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) &
+ 		    mask->src.u3.all[count])
+-			return 0;
++			return false;
+ 	}
+ 
+ 	if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all)
+-		return 0;
++		return false;
+ 
+ 	if (t1->src.l3num != t2->src.l3num ||
+ 	    t1->dst.protonum != t2->dst.protonum)
+-		return 0;
++		return false;
+ 
+-	return 1;
++	return true;
+ }
+ 
+-static inline int nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
+-				       const struct nf_conntrack_tuple *tuple,
+-				       const struct nf_conntrack_tuple_mask *mask)
++static inline bool
++nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
++		     const struct nf_conntrack_tuple *tuple,
++		     const struct nf_conntrack_tuple_mask *mask)
+ {
+ 	return nf_ct_tuple_src_mask_cmp(t, tuple, mask) &&
+ 	       __nf_ct_tuple_dst_equal(t, tuple);
+diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
+index 58dd226..237a961 100644
+--- a/include/net/netfilter/nf_nat_helper.h
++++ b/include/net/netfilter/nf_nat_helper.h
+@@ -24,6 +24,9 @@ extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
+ extern int nf_nat_seq_adjust(struct sk_buff *skb,
+ 			     struct nf_conn *ct,
+ 			     enum ip_conntrack_info ctinfo);
++extern int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
++				     struct nf_conn *ct,
++				     enum ip_conntrack_info ctinfo);
+ 
+ /* Setup NAT on this expected conntrack so it follows master, but goes
+  * to port ct->master->saved_proto. */
+diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
+index 4aa0edb..f3662c4 100644
+--- a/include/net/netfilter/nf_nat_protocol.h
++++ b/include/net/netfilter/nf_nat_protocol.h
+@@ -8,9 +8,6 @@ struct nf_nat_range;
+ 
+ struct nf_nat_protocol
+ {
+-	/* Protocol name */
+-	const char *name;
+-
+ 	/* Protocol number. */
+ 	unsigned int protonum;
+ 
+@@ -18,25 +15,25 @@ struct nf_nat_protocol
+ 
+ 	/* Translate a packet to the target according to manip type.
+ 	   Return true if succeeded. */
+-	int (*manip_pkt)(struct sk_buff *skb,
+-			 unsigned int iphdroff,
+-			 const struct nf_conntrack_tuple *tuple,
+-			 enum nf_nat_manip_type maniptype);
++	bool (*manip_pkt)(struct sk_buff *skb,
++			  unsigned int iphdroff,
++			  const struct nf_conntrack_tuple *tuple,
++			  enum nf_nat_manip_type maniptype);
+ 
+ 	/* Is the manipable part of the tuple between min and max incl? */
+-	int (*in_range)(const struct nf_conntrack_tuple *tuple,
+-			enum nf_nat_manip_type maniptype,
+-			const union nf_conntrack_man_proto *min,
+-			const union nf_conntrack_man_proto *max);
++	bool (*in_range)(const struct nf_conntrack_tuple *tuple,
++			 enum nf_nat_manip_type maniptype,
++			 const union nf_conntrack_man_proto *min,
++			 const union nf_conntrack_man_proto *max);
+ 
+ 	/* Alter the per-proto part of the tuple (depending on
+ 	   maniptype), to give a unique tuple in the given range if
+ 	   possible; return false if not.  Per-protocol part of tuple
+ 	   is initialized to the incoming packet. */
+-	int (*unique_tuple)(struct nf_conntrack_tuple *tuple,
+-			    const struct nf_nat_range *range,
+-			    enum nf_nat_manip_type maniptype,
+-			    const struct nf_conn *ct);
++	bool (*unique_tuple)(struct nf_conntrack_tuple *tuple,
++			     const struct nf_nat_range *range,
++			     enum nf_nat_manip_type maniptype,
++			     const struct nf_conn *ct);
+ 
+ 	int (*range_to_nlattr)(struct sk_buff *skb,
+ 			       const struct nf_nat_range *range);
+@@ -62,9 +59,20 @@ extern int init_protocols(void) __init;
+ extern void cleanup_protocols(void);
+ extern const struct nf_nat_protocol *find_nat_proto(u_int16_t protonum);
+ 
+-extern int nf_nat_port_range_to_nlattr(struct sk_buff *skb,
+-				       const struct nf_nat_range *range);
+-extern int nf_nat_port_nlattr_to_range(struct nlattr *tb[],
+-				       struct nf_nat_range *range);
++extern bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
++				  enum nf_nat_manip_type maniptype,
++				  const union nf_conntrack_man_proto *min,
++				  const union nf_conntrack_man_proto *max);
++
++extern bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
++				      const struct nf_nat_range *range,
++				      enum nf_nat_manip_type maniptype,
++				      const struct nf_conn *ct,
++				      u_int16_t *rover);
++
++extern int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,
++					const struct nf_nat_range *range);
++extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
++					struct nf_nat_range *range);
+ 
+ #endif /*_NF_NAT_PROTO_H*/
+diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
+index 75d1825..e4a18ae 100644
+--- a/include/net/netfilter/nf_nat_rule.h
++++ b/include/net/netfilter/nf_nat_rule.h
+@@ -14,7 +14,4 @@ extern int nf_nat_rule_find(struct sk_buff *skb,
+ 
+ extern unsigned int
+ alloc_null_binding(struct nf_conn *ct, unsigned int hooknum);
+-
+-extern unsigned int
+-alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum);
+ #endif /* _NF_NAT_RULE_H */
+diff --git a/include/net/netlabel.h b/include/net/netlabel.h
+index 0ca67d7..5e53a85 100644
+--- a/include/net/netlabel.h
++++ b/include/net/netlabel.h
+@@ -162,7 +162,7 @@ struct netlbl_lsm_secattr_catmap {
+ 
+ /**
+  * struct netlbl_lsm_secattr - NetLabel LSM security attributes
+- * @flags: indicate which attributes are contained in this structure
++ * @flags: indicate structure attributes, see NETLBL_SECATTR_*
+  * @type: indicate the NLTYPE of the attributes
+  * @domain: the NetLabel LSM domain
+  * @cache: NetLabel LSM specific cache
+@@ -180,17 +180,22 @@ struct netlbl_lsm_secattr_catmap {
+  * NetLabel itself when returning security attributes to the LSM.
+  *
+  */
++struct netlbl_lsm_secattr {
++	u32 flags;
++	/* bitmap values for 'flags' */
+ #define NETLBL_SECATTR_NONE             0x00000000
+ #define NETLBL_SECATTR_DOMAIN           0x00000001
++#define NETLBL_SECATTR_DOMAIN_CPY       (NETLBL_SECATTR_DOMAIN | \
++					 NETLBL_SECATTR_FREE_DOMAIN)
+ #define NETLBL_SECATTR_CACHE            0x00000002
+ #define NETLBL_SECATTR_MLS_LVL          0x00000004
+ #define NETLBL_SECATTR_MLS_CAT          0x00000008
+ #define NETLBL_SECATTR_SECID            0x00000010
++	/* bitmap meta-values for 'flags' */
++#define NETLBL_SECATTR_FREE_DOMAIN      0x01000000
+ #define NETLBL_SECATTR_CACHEABLE        (NETLBL_SECATTR_MLS_LVL | \
+ 					 NETLBL_SECATTR_MLS_CAT | \
+ 					 NETLBL_SECATTR_SECID)
+-struct netlbl_lsm_secattr {
+-	u32 flags;
+ 	u32 type;
+ 	char *domain;
+ 	struct netlbl_lsm_cache *cache;
+@@ -303,7 +308,8 @@ static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
+  */
+ static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
+ {
+-	kfree(secattr->domain);
++	if (secattr->flags & NETLBL_SECATTR_FREE_DOMAIN)
++		kfree(secattr->domain);
+ 	if (secattr->flags & NETLBL_SECATTR_CACHE)
+ 		netlbl_secattr_cache_free(secattr->cache);
+ 	if (secattr->flags & NETLBL_SECATTR_MLS_CAT)
+diff --git a/include/net/netns/core.h b/include/net/netns/core.h
+new file mode 100644
+index 0000000..24d4be7
+--- /dev/null
++++ b/include/net/netns/core.h
+@@ -0,0 +1,16 @@
++#ifndef __NETNS_CORE_H__
++#define __NETNS_CORE_H__
++
++struct ctl_table_header;
++struct prot_inuse;
++
++struct netns_core {
++	/* core sysctls */
++	struct ctl_table_header	*sysctl_hdr;
++
++	int	sysctl_somaxconn;
++
++	struct prot_inuse	*inuse;
++};
++
++#endif
+diff --git a/include/net/netns/dccp.h b/include/net/netns/dccp.h
+new file mode 100644
+index 0000000..98d2a7c
+--- /dev/null
++++ b/include/net/netns/dccp.h
+@@ -0,0 +1,11 @@
++#ifndef __NETNS_DCCP_H__
++#define __NETNS_DCCP_H__
++
++struct sock;
++
++struct netns_dccp {
++	struct sock *v4_ctl_sk;
++	struct sock *v6_ctl_sk;
++};
++
++#endif
+diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h
+new file mode 100644
+index 0000000..0c04fd2
+--- /dev/null
++++ b/include/net/netns/generic.h
+@@ -0,0 +1,49 @@
++/*
++ * generic net pointers
++ */
++
++#ifndef __NET_GENERIC_H__
++#define __NET_GENERIC_H__
++
++#include <linux/rcupdate.h>
++
++/*
++ * Generic net pointers are to be used by modules to put some private
++ * stuff on the struct net without explicit struct net modification
++ *
++ * The rules are simple:
++ * 1. register the ops with register_pernet_gen_device to get the id
++ *    of your private pointer;
++ * 2. call net_assign_generic() to put the private data on the struct
++ *    net (most preferably this should be done in the ->init callback
++ *    of the ops registered);
++ * 3. do not change this pointer while the net is alive;
++ * 4. do not try to have any private reference on the net_generic object.
++ *
++ * After accomplishing all of the above, the private pointer can be
++ * accessed with the net_generic() call.
++ */
++
++struct net_generic {
++	unsigned int len;
++	struct rcu_head rcu;
++
++	void *ptr[0];
++};
++
++static inline void *net_generic(struct net *net, int id)
++{
++	struct net_generic *ng;
++	void *ptr;
++
++	rcu_read_lock();
++	ng = rcu_dereference(net->gen);
++	BUG_ON(id == 0 || id > ng->len);
++	ptr = ng->ptr[id - 1];
++	rcu_read_unlock();
++
++	return ptr;
++}
++
++extern int net_assign_generic(struct net *net, int id, void *data);
++#endif
+diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
+index a9b4f60..34ee348 100644
+--- a/include/net/netns/ipv4.h
++++ b/include/net/netns/ipv4.h
+@@ -17,6 +17,7 @@ struct netns_ipv4 {
+ #ifdef CONFIG_SYSCTL
+ 	struct ctl_table_header	*forw_hdr;
+ 	struct ctl_table_header	*frags_hdr;
++	struct ctl_table_header	*ipv4_hdr;
+ #endif
+ 	struct ipv4_devconf	*devconf_all;
+ 	struct ipv4_devconf	*devconf_dflt;
+@@ -26,6 +27,9 @@ struct netns_ipv4 {
+ 	struct hlist_head	*fib_table_hash;
+ 	struct sock		*fibnl;
+ 
++	struct sock		**icmp_sk;
++	struct sock		*tcp_sock;
++
+ 	struct netns_frags	frags;
+ #ifdef CONFIG_NETFILTER
+ 	struct xt_table		*iptable_filter;
+@@ -33,5 +37,12 @@ struct netns_ipv4 {
+ 	struct xt_table		*iptable_raw;
+ 	struct xt_table		*arptable_filter;
+ #endif
++
++	int sysctl_icmp_echo_ignore_all;
++	int sysctl_icmp_echo_ignore_broadcasts;
++	int sysctl_icmp_ignore_bogus_error_responses;
++	int sysctl_icmp_ratelimit;
++	int sysctl_icmp_ratemask;
++	int sysctl_icmp_errors_use_inbound_ifaddr;
+ };
+ #endif
+diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
+index 1dd7de4..ac053be 100644
+--- a/include/net/netns/ipv6.h
++++ b/include/net/netns/ipv6.h
+@@ -36,5 +36,23 @@ struct netns_ipv6 {
+ 	struct xt_table		*ip6table_mangle;
+ 	struct xt_table		*ip6table_raw;
+ #endif
++	struct rt6_info         *ip6_null_entry;
++	struct rt6_statistics   *rt6_stats;
++	struct timer_list       *ip6_fib_timer;
++	struct hlist_head       *fib_table_hash;
++	struct fib6_table       *fib6_main_tbl;
++	struct dst_ops		*ip6_dst_ops;
++	unsigned int		 ip6_rt_gc_expire;
++	unsigned long		 ip6_rt_last_gc;
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++	struct rt6_info         *ip6_prohibit_entry;
++	struct rt6_info         *ip6_blk_hole_entry;
++	struct fib6_table       *fib6_local_tbl;
++	struct fib_rules_ops    *fib6_rules_ops;
++#endif
++	struct sock		**icmp_sk;
++	struct sock             *ndisc_sk;
++	struct sock             *tcp_sk;
++	struct sock             *igmp_sk;
+ };
+ #endif
+diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
+index d349c66..aa9e282 100644
+--- a/include/net/pkt_cls.h
++++ b/include/net/pkt_cls.h
+@@ -353,7 +353,7 @@ tcf_match_indev(struct sk_buff *skb, char *indev)
+ 	if (indev[0]) {
+ 		if  (!skb->iif)
+ 			return 0;
+-		dev = __dev_get_by_index(&init_net, skb->iif);
++		dev = __dev_get_by_index(dev_net(skb->dev), skb->iif);
+ 		if (!dev || strcmp(indev, dev->name))
+ 			return 0;
+ 	}
+diff --git a/include/net/protocol.h b/include/net/protocol.h
+index ad8c584..8d024d7 100644
+--- a/include/net/protocol.h
++++ b/include/net/protocol.h
+@@ -39,7 +39,8 @@ struct net_protocol {
+ 	int			(*gso_send_check)(struct sk_buff *skb);
+ 	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
+ 					       int features);
+-	int			no_policy;
++	unsigned int		no_policy:1,
++				netns_ok:1;
+ };
+ 
+ #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+diff --git a/include/net/raw.h b/include/net/raw.h
+index 1828f81..6c14a65 100644
+--- a/include/net/raw.h
++++ b/include/net/raw.h
+@@ -53,7 +53,7 @@ int raw_seq_open(struct inode *ino, struct file *file,
+ 
+ #endif
+ 
+-void raw_hash_sk(struct sock *sk, struct raw_hashinfo *h);
+-void raw_unhash_sk(struct sock *sk, struct raw_hashinfo *h);
++void raw_hash_sk(struct sock *sk);
++void raw_unhash_sk(struct sock *sk);
+ 
+ #endif	/* _RAW_H */
+diff --git a/include/net/request_sock.h b/include/net/request_sock.h
+index cff4608..b220b5f 100644
+--- a/include/net/request_sock.h
++++ b/include/net/request_sock.h
+@@ -31,8 +31,7 @@ struct request_sock_ops {
+ 	int		obj_size;
+ 	struct kmem_cache	*slab;
+ 	int		(*rtx_syn_ack)(struct sock *sk,
+-				       struct request_sock *req,
+-				       struct dst_entry *dst);
++				       struct request_sock *req);
+ 	void		(*send_ack)(struct sk_buff *skb,
+ 				    struct request_sock *req);
+ 	void		(*send_reset)(struct sock *sk,
+@@ -46,7 +45,7 @@ struct request_sock {
+ 	struct request_sock		*dl_next; /* Must be first member! */
+ 	u16				mss;
+ 	u8				retrans;
+-	u8				__pad;
++	u8				cookie_ts; /* syncookie: encode tcpopts in timestamp */
+ 	/* The following two fields can be easily recomputed I think -AK */
+ 	u32				window_clamp; /* window clamp at creation time */
+ 	u32				rcv_wnd;	  /* rcv_wnd offered first time */
+@@ -116,8 +115,8 @@ struct request_sock_queue {
+ 	struct request_sock	*rskq_accept_head;
+ 	struct request_sock	*rskq_accept_tail;
+ 	rwlock_t		syn_wait_lock;
+-	u8			rskq_defer_accept;
+-	/* 3 bytes hole, try to pack */
++	u16			rskq_defer_accept;
++	/* 2 bytes hole, try to pack */
+ 	struct listen_sock	*listen_opt;
+ };
+ 
+diff --git a/include/net/route.h b/include/net/route.h
+index eadad59..c633880 100644
+--- a/include/net/route.h
++++ b/include/net/route.h
+@@ -34,7 +34,6 @@
+ #include <linux/ip.h>
+ #include <linux/cache.h>
+ #include <linux/security.h>
+-#include <net/sock.h>
+ 
+ #ifndef __KERNEL__
+ #warning This file is not supposed to be used outside of kernel.
+@@ -161,7 +160,7 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
+ 					 .dport = dport } } };
+ 
+ 	int err;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 	if (!dst || !src) {
+ 		err = __ip_route_output_key(net, rp, &fl);
+ 		if (err)
+@@ -189,7 +188,7 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol,
+ 		ip_rt_put(*rp);
+ 		*rp = NULL;
+ 		security_sk_classify_flow(sk, &fl);
+-		return ip_route_output_flow(sk->sk_net, rp, &fl, sk, 0);
++		return ip_route_output_flow(sock_net(sk), rp, &fl, sk, 0);
+ 	}
+ 	return 0;
+ }
+diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
+index 793863e..3c1895e 100644
+--- a/include/net/rtnetlink.h
++++ b/include/net/rtnetlink.h
+@@ -74,6 +74,7 @@ struct rtnl_link_ops {
+ 
+ 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/sctp/command.h b/include/net/sctp/command.h
+index 35b1e83..88988ab 100644
+--- a/include/net/sctp/command.h
++++ b/include/net/sctp/command.h
+@@ -206,12 +206,11 @@ typedef struct {
+ int sctp_init_cmd_seq(sctp_cmd_seq_t *seq);
+ 
+ /* Add a command to an sctp_cmd_seq_t.
+- * Return 0 if the command sequence is full.
+  *
+  * Use the SCTP_* constructors defined by SCTP_ARG_CONSTRUCTOR() above
+  * to wrap data which goes in the obj argument.
+  */
+-int sctp_add_cmd(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj);
++void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj);
+ 
+ /* Return the next command structure in an sctp_cmd_seq.
+  * Return NULL at the end of the sequence.
+diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
+index ea80673..90b1e8d 100644
+--- a/include/net/sctp/sctp.h
++++ b/include/net/sctp/sctp.h
+@@ -368,11 +368,6 @@ void sctp_sysctl_unregister(void);
+ #else
+ static inline void sctp_sysctl_register(void) { return; }
+ static inline void sctp_sysctl_unregister(void) { return; }
+-static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen,
+-		void __user *oldval, size_t __user *oldlenp,
+-		void __user *newval, size_t newlen) {
+-	return -ENOSYS;
+-}
+ #endif
+ 
+ /* Size of Supported Address Parameter for 'x' address types. */
+diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
+index ef9e7ed..2481173 100644
+--- a/include/net/sctp/sm.h
++++ b/include/net/sctp/sm.h
+@@ -385,14 +385,6 @@ static inline int ADDIP_SERIAL_gte(__u16 s, __u16 t)
+ 	return (((s) == (t)) || (((t) - (s)) & ADDIP_SERIAL_SIGN_BIT));
+ }
+ 
+-
+-/* Run sctp_add_cmd() generating a BUG() if there is a failure.  */
+-static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj)
+-{
+-	if (unlikely(!sctp_add_cmd(seq, verb, obj)))
+-		BUG();
+-}
+-
+ /* Check VTAG of the packet matches the sender's own tag. */
+ static inline int
+ sctp_vtag_verify(const struct sctp_chunk *chunk,
+diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
+index 9c827a7..0ce0443 100644
+--- a/include/net/sctp/structs.h
++++ b/include/net/sctp/structs.h
+@@ -637,8 +637,6 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
+ 					    struct sctp_sndrcvinfo *,
+ 					    struct msghdr *, int len);
+ void sctp_datamsg_put(struct sctp_datamsg *);
+-void sctp_datamsg_free(struct sctp_datamsg *);
+-void sctp_datamsg_track(struct sctp_chunk *);
+ void sctp_chunk_fail(struct sctp_chunk *, int error);
+ int sctp_chunk_abandoned(struct sctp_chunk *);
+ 
+@@ -1661,6 +1659,9 @@ struct sctp_association {
+ 	/* Transport to which SHUTDOWN chunk was last sent.  */
+ 	struct sctp_transport *shutdown_last_sent_to;
+ 
++	/* How many times have we resent a SHUTDOWN */
++	int shutdown_retries;
++
+ 	/* Transport to which INIT chunk was last sent.  */
+ 	struct sctp_transport *init_last_sent_to;
+ 
+@@ -1695,6 +1696,11 @@ struct sctp_association {
+ 	 */
+ 	__u16 unack_data;
+ 
++	/* The total number of data chunks that we've had to retransmit
++	 * as the result of a T3 timer expiration
++	 */
++	__u32 rtx_data_chunks;
++
+ 	/* This is the association's receive buffer space.  This value is used
+ 	 * to set a_rwnd field in an INIT or a SACK chunk.
+ 	 */
+diff --git a/include/net/sock.h b/include/net/sock.h
+index fd98760..dc42b44 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -47,7 +47,6 @@
+ #include <linux/module.h>
+ #include <linux/lockdep.h>
+ #include <linux/netdevice.h>
+-#include <linux/pcounter.h>
+ #include <linux/skbuff.h>	/* struct sk_buff */
+ #include <linux/mm.h>
+ #include <linux/security.h>
+@@ -70,7 +69,11 @@
+ #define SOCK_DEBUG(sk, msg...) do { if ((sk) && sock_flag((sk), SOCK_DBG)) \
+ 					printk(KERN_DEBUG msg); } while (0)
+ #else
+-#define SOCK_DEBUG(sk, msg...) do { } while (0)
++/* Validate arguments and do nothing */
++static void inline int __attribute__ ((format (printf, 2, 3)))
++SOCK_DEBUG(struct sock *sk, const char *msg, ...)
++{
++}
+ #endif
+ 
+ /* This is the per-socket lock.  The spinlock provides a synchronization
+@@ -122,7 +125,9 @@ struct sock_common {
+ 	atomic_t		skc_refcnt;
+ 	unsigned int		skc_hash;
+ 	struct proto		*skc_prot;
++#ifdef CONFIG_NET_NS
+ 	struct net	 	*skc_net;
++#endif
+ };
+ 
+ /**
+@@ -151,6 +156,7 @@ struct sock_common {
+   *	@sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
+   *	@sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
+   *	@sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
++  *	@sk_gso_max_size: Maximum GSO segment size to build
+   *	@sk_lingertime: %SO_LINGER l_linger setting
+   *	@sk_backlog: always used with the per-socket spinlock held
+   *	@sk_callback_lock: used with the callbacks in the end of this struct
+@@ -237,6 +243,7 @@ struct sock {
+ 	gfp_t			sk_allocation;
+ 	int			sk_route_caps;
+ 	int			sk_gso_type;
++	unsigned int		sk_gso_max_size;
+ 	int			sk_rcvlowat;
+ 	unsigned long 		sk_flags;
+ 	unsigned long	        sk_lingertime;
+@@ -498,6 +505,7 @@ extern int sk_wait_data(struct sock *sk, long *timeo);
+ struct request_sock_ops;
+ struct timewait_sock_ops;
+ struct inet_hashinfo;
++struct raw_hashinfo;
+ 
+ /* Networking protocol blocks we attach to sockets.
+  * socket layer -> transport layer interface
+@@ -553,7 +561,7 @@ struct proto {
+ 
+ 	/* Keeping track of sockets in use */
+ #ifdef CONFIG_PROC_FS
+-	struct pcounter		inuse;
++	unsigned int		inuse_idx;
+ #endif
+ 
+ 	/* Memory pressure */
+@@ -580,7 +588,11 @@ struct proto {
+ 	struct request_sock_ops	*rsk_prot;
+ 	struct timewait_sock_ops *twsk_prot;
+ 
+-	struct inet_hashinfo	*hashinfo;
++	union {
++		struct inet_hashinfo	*hashinfo;
++		struct hlist_head	*udp_hash;
++		struct raw_hashinfo	*raw_hash;
++	} h;
+ 
+ 	struct module		*owner;
+ 
+@@ -622,36 +634,12 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
+ 
+ 
+ #ifdef CONFIG_PROC_FS
+-# define DEFINE_PROTO_INUSE(NAME) DEFINE_PCOUNTER(NAME)
+-# define REF_PROTO_INUSE(NAME) PCOUNTER_MEMBER_INITIALIZER(NAME, .inuse)
+ /* Called with local bh disabled */
+-static inline void sock_prot_inuse_add(struct proto *prot, int inc)
+-{
+-	pcounter_add(&prot->inuse, inc);
+-}
+-static inline int sock_prot_inuse_init(struct proto *proto)
+-{
+-	return pcounter_alloc(&proto->inuse);
+-}
+-static inline int sock_prot_inuse_get(struct proto *proto)
+-{
+-	return pcounter_getval(&proto->inuse);
+-}
+-static inline void sock_prot_inuse_free(struct proto *proto)
+-{
+-	pcounter_free(&proto->inuse);
+-}
++extern void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc);
++extern int sock_prot_inuse_get(struct net *net, struct proto *proto);
+ #else
+-# define DEFINE_PROTO_INUSE(NAME)
+-# define REF_PROTO_INUSE(NAME)
+-static void inline sock_prot_inuse_add(struct proto *prot, int inc)
+-{
+-}
+-static int inline sock_prot_inuse_init(struct proto *proto)
+-{
+-	return 0;
+-}
+-static void inline sock_prot_inuse_free(struct proto *proto)
++static void inline sock_prot_inuse_add(struct net *net, struct proto *prot,
++		int inc)
+ {
+ }
+ #endif
+@@ -850,6 +838,7 @@ extern struct sock		*sk_alloc(struct net *net, int family,
+ 					  gfp_t priority,
+ 					  struct proto *prot);
+ extern void			sk_free(struct sock *sk);
++extern void			sk_release_kernel(struct sock *sk);
+ extern struct sock		*sk_clone(const struct sock *sk,
+ 					  const gfp_t priority);
+ 
+@@ -939,41 +928,6 @@ extern void sk_common_release(struct sock *sk);
+ extern void sock_init_data(struct socket *sock, struct sock *sk);
+ 
+ /**
+- *	sk_filter - run a packet through a socket filter
+- *	@sk: sock associated with &sk_buff
+- *	@skb: buffer to filter
+- *	@needlock: set to 1 if the sock is not locked by caller.
+- *
+- * Run the filter code and then cut skb->data to correct size returned by
+- * sk_run_filter. If pkt_len is 0 we toss packet. If skb->len is smaller
+- * than pkt_len we keep whole skb->data. This is the socket level
+- * wrapper to sk_run_filter. It returns 0 if the packet should
+- * be accepted or -EPERM if the packet should be tossed.
+- *
+- */
+-
+-static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
+-{
+-	int err;
+-	struct sk_filter *filter;
+-	
+-	err = security_sock_rcv_skb(sk, skb);
+-	if (err)
+-		return err;
+-	
+-	rcu_read_lock_bh();
+-	filter = rcu_dereference(sk->sk_filter);
+-	if (filter) {
+-		unsigned int pkt_len = sk_run_filter(skb, filter->insns,
+-				filter->len);
+-		err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
+-	}
+- 	rcu_read_unlock_bh();
+-
+-	return err;
+-}
+-
+-/**
+  *	sk_filter_release: Release a socket filter
+  *	@sk: socket
+  *	@fp: filter to remove
+@@ -1333,6 +1287,36 @@ static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_e
+ }
+ #endif
+ 
++static inline
++struct net *sock_net(const struct sock *sk)
++{
++#ifdef CONFIG_NET_NS
++	return sk->sk_net;
++#else
++	return &init_net;
++#endif
++}
++
++static inline
++void sock_net_set(struct sock *sk, struct net *net)
++{
++#ifdef CONFIG_NET_NS
++	sk->sk_net = net;
++#endif
++}
++
++/*
++ * Kernel sockets, f.e. rtnl or icmp_socket, are a part of a namespace.
++ * They should not hold a referrence to a namespace in order to allow
++ * to stop it.
++ * Sockets after sk_change_net should be released using sk_release_kernel
++ */
++static inline void sk_change_net(struct sock *sk, struct net *net)
++{
++	put_net(sock_net(sk));
++	sock_net_set(sk, hold_net(net));
++}
++
+ extern void sock_enable_timestamp(struct sock *sk);
+ extern int sock_get_timestamp(struct sock *, struct timeval __user *);
+ extern int sock_get_timestampns(struct sock *, struct timespec __user *);
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 4fd3eb2..633147c 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -29,6 +29,7 @@
+ #include <linux/skbuff.h>
+ #include <linux/dmaengine.h>
+ #include <linux/crypto.h>
++#include <linux/cryptohash.h>
+ 
+ #include <net/inet_connection_sock.h>
+ #include <net/inet_timewait_sock.h>
+@@ -138,6 +139,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
+ #define MAX_TCP_KEEPINTVL	32767
+ #define MAX_TCP_KEEPCNT		127
+ #define MAX_TCP_SYNCNT		127
++#define MAX_TCP_ACCEPT_DEFERRED 65535
+ 
+ #define TCP_SYNQ_INTERVAL	(HZ/5)	/* Period of SYNACK timer */
+ 
+@@ -434,11 +436,20 @@ extern int			tcp_disconnect(struct sock *sk, int flags);
+ extern void			tcp_unhash(struct sock *sk);
+ 
+ /* From syncookies.c */
++extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
+ extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, 
+ 				    struct ip_options *opt);
+ extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, 
+ 				     __u16 *mss);
+ 
++extern __u32 cookie_init_timestamp(struct request_sock *req);
++extern void cookie_check_timestamp(struct tcp_options_received *tcp_opt);
++
++/* From net/ipv6/syncookies.c */
++extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);
++extern __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb,
++				     __u16 *mss);
++
+ /* tcp_output.c */
+ 
+ extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
+@@ -776,11 +787,14 @@ 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);
+ 
+ /* Slow start with delack produces 3 packets of burst, so that
+- * it is safe "de facto".
++ * it is safe "de facto".  This will be the default - same as
++ * the default reordering threshold - but if reordering increases,
++ * we must be able to allow cwnd to burst at least this much in order
++ * to not pull it back when holes are filled.
+  */
+ static __inline__ __u32 tcp_max_burst(const struct tcp_sock *tp)
+ {
+-	return 3;
++	return tp->reordering;
+ }
+ 
+ /* Returns end sequence number of the receiver's advertised window */
+@@ -950,6 +964,7 @@ static inline void tcp_openreq_init(struct request_sock *req,
+ 	struct inet_request_sock *ireq = inet_rsk(req);
+ 
+ 	req->rcv_wnd = 0;		/* So that tcp_send_synack() knows! */
++	req->cookie_ts = 0;
+ 	tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq;
+ 	req->mss = rx_opt->mss_clamp;
+ 	req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0;
+@@ -1237,7 +1252,7 @@ static inline void tcp_insert_write_queue_after(struct sk_buff *skb,
+ 						struct sk_buff *buff,
+ 						struct sock *sk)
+ {
+-	__skb_append(skb, buff, &sk->sk_write_queue);
++	__skb_queue_after(&sk->sk_write_queue, skb, buff);
+ }
+ 
+ /* Insert skb between prev and next on the write queue of sk.  */
+@@ -1315,25 +1330,25 @@ enum tcp_seq_states {
+ };
+ 
+ struct tcp_seq_afinfo {
+-	struct module		*owner;
+ 	char			*name;
+ 	sa_family_t		family;
+-	int			(*seq_show) (struct seq_file *m, void *v);
+-	struct file_operations	*seq_fops;
++	struct file_operations	seq_fops;
++	struct seq_operations	seq_ops;
+ };
+ 
+ struct tcp_iter_state {
++	struct seq_net_private	p;
+ 	sa_family_t		family;
+ 	enum tcp_seq_states	state;
+ 	struct sock		*syn_wait_sk;
+ 	int			bucket, sbucket, num, uid;
+-	struct seq_operations	seq_ops;
+ };
+ 
+-extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo);
+-extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo);
++extern int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo);
++extern void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo);
+ 
+ extern struct request_sock_ops tcp_request_sock_ops;
++extern struct request_sock_ops tcp6_request_sock_ops;
+ 
+ extern int tcp_v4_destroy_sock(struct sock *sk);
+ 
+@@ -1375,7 +1390,7 @@ struct tcp_request_sock_ops {
+ #endif
+ };
+ 
+-extern void tcp_v4_init(struct net_proto_family *ops);
++extern void tcp_v4_init(void);
+ extern void tcp_init(void);
+ 
+ #endif	/* _TCP_H */
+diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h
+index 2151a80..ee2f304 100644
+--- a/include/net/tipc/tipc_bearer.h
++++ b/include/net/tipc/tipc_bearer.h
+@@ -99,6 +99,9 @@ struct tipc_bearer {
+ 	char name[TIPC_MAX_BEARER_NAME];
+ };
+ 
++/*
++ * TIPC routines available to supported media types
++ */
+ 
+ int  tipc_register_media(u32 media_type,
+ 			 char *media_name, 
+@@ -123,6 +126,12 @@ void tipc_continue(struct tipc_bearer *tb_ptr);
+ int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority);
+ int tipc_disable_bearer(const char *name);
+ 
++/*
++ * Routines made available to TIPC by supported media types
++ */
++
++int  tipc_eth_media_start(void);
++void tipc_eth_media_stop(void);
+ 
+ #endif
+ 
+diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h
+index cfc4ba4..11105bc 100644
+--- a/include/net/tipc/tipc_port.h
++++ b/include/net/tipc/tipc_port.h
+@@ -86,13 +86,6 @@ u32 tipc_createport_raw(void *usr_handle,
+ 			void (*wakeup)(struct tipc_port *),
+ 			const u32 importance);
+ 
+-/*
+- * tipc_set_msg_option(): port must be locked.
+- */
+-int tipc_set_msg_option(struct tipc_port *tp_ptr,
+-			const char *opt,
+-			const u32 len);
+-
+ int tipc_reject_msg(struct sk_buff *buf, u32 err);
+ 
+ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode);
+@@ -103,6 +96,12 @@ 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
++ */
++
++int tipc_disconnect_port(struct tipc_port *tp_ptr);
++
+ 
+ #endif
+ 
+diff --git a/include/net/udp.h b/include/net/udp.h
+index c6669c0..3e55a99 100644
+--- a/include/net/udp.h
++++ b/include/net/udp.h
+@@ -115,7 +115,7 @@ static inline void udp_lib_unhash(struct sock *sk)
+ 	write_lock_bh(&udp_hash_lock);
+ 	if (sk_del_node_init(sk)) {
+ 		inet_sk(sk)->num = 0;
+-		sock_prot_inuse_add(sk->sk_prot, -1);
++		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ 	}
+ 	write_unlock_bh(&udp_hash_lock);
+ }
+@@ -125,6 +125,8 @@ static inline void udp_lib_close(struct sock *sk, long timeout)
+ 	sk_common_release(sk);
+ }
+ 
++extern int	udp_lib_get_port(struct sock *sk, unsigned short snum,
++		int (*)(const struct sock*,const struct sock*));
+ 
+ /* net/ipv4/udp.c */
+ extern int	udp_get_port(struct sock *sk, unsigned short snum,
+@@ -183,24 +185,23 @@ DECLARE_SNMP_STAT(struct udp_mib, udplite_stats_in6);
+ 
+ /* /proc */
+ struct udp_seq_afinfo {
+-	struct module		*owner;
+ 	char			*name;
+ 	sa_family_t		family;
+ 	struct hlist_head	*hashtable;
+-	int 			(*seq_show) (struct seq_file *m, void *v);
+-	struct file_operations	*seq_fops;
++	struct file_operations	seq_fops;
++	struct seq_operations	seq_ops;
+ };
+ 
+ struct udp_iter_state {
++	struct seq_net_private  p;
+ 	sa_family_t		family;
+ 	struct hlist_head	*hashtable;
+ 	int			bucket;
+-	struct seq_operations	seq_ops;
+ };
+ 
+ #ifdef CONFIG_PROC_FS
+-extern int udp_proc_register(struct udp_seq_afinfo *afinfo);
+-extern void udp_proc_unregister(struct udp_seq_afinfo *afinfo);
++extern int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo);
++extern void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo);
+ 
+ extern int  udp4_proc_init(void);
+ extern void udp4_proc_exit(void);
+diff --git a/include/net/wireless.h b/include/net/wireless.h
+index d30c4ba..667b408 100644
+--- a/include/net/wireless.h
++++ b/include/net/wireless.h
+@@ -13,6 +13,162 @@
+ #include <net/cfg80211.h>
+ 
+ /**
++ * enum ieee80211_band - supported frequency bands
++ *
++ * The bands are assigned this way because the supported
++ * bitrates differ in these bands.
++ *
++ * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band
++ * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7)
++ */
++enum ieee80211_band {
++	IEEE80211_BAND_2GHZ,
++	IEEE80211_BAND_5GHZ,
++
++	/* keep last */
++	IEEE80211_NUM_BANDS
++};
++
++/**
++ * enum ieee80211_channel_flags - channel flags
++ *
++ * Channel flags set by the regulatory control code.
++ *
++ * @IEEE80211_CHAN_DISABLED: This channel is disabled.
++ * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted
++ *	on this channel.
++ * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel.
++ * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
++ */
++enum ieee80211_channel_flags {
++	IEEE80211_CHAN_DISABLED		= 1<<0,
++	IEEE80211_CHAN_PASSIVE_SCAN	= 1<<1,
++	IEEE80211_CHAN_NO_IBSS		= 1<<2,
++	IEEE80211_CHAN_RADAR		= 1<<3,
++};
++
++/**
++ * struct ieee80211_channel - channel definition
++ *
++ * This structure describes a single channel for use
++ * with cfg80211.
++ *
++ * @center_freq: center frequency in MHz
++ * @hw_value: hardware-specific value for the channel
++ * @flags: channel flags from &enum ieee80211_channel_flags.
++ * @orig_flags: channel flags at registration time, used by regulatory
++ *	code to support devices with additional restrictions
++ * @band: band this channel belongs to.
++ * @max_antenna_gain: maximum antenna gain in dBi
++ * @max_power: maximum transmission power (in dBm)
++ * @orig_mag: internal use
++ * @orig_mpwr: internal use
++ */
++struct ieee80211_channel {
++	enum ieee80211_band band;
++	u16 center_freq;
++	u16 hw_value;
++	u32 flags;
++	int max_antenna_gain;
++	int max_power;
++	u32 orig_flags;
++	int orig_mag, orig_mpwr;
++};
++
++/**
++ * enum ieee80211_rate_flags - rate flags
++ *
++ * Hardware/specification flags for rates. These are structured
++ * in a way that allows using the same bitrate structure for
++ * different bands/PHY modes.
++ *
++ * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short
++ *	preamble on this bitrate; only relevant in 2.4GHz band and
++ *	with CCK rates.
++ * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate
++ *	when used with 802.11a (on the 5 GHz band); filled by the
++ *	core code when registering the wiphy.
++ * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate
++ *	when used with 802.11b (on the 2.4 GHz band); filled by the
++ *	core code when registering the wiphy.
++ * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate
++ *	when used with 802.11g (on the 2.4 GHz band); filled by the
++ *	core code when registering the wiphy.
++ * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode.
++ */
++enum ieee80211_rate_flags {
++	IEEE80211_RATE_SHORT_PREAMBLE	= 1<<0,
++	IEEE80211_RATE_MANDATORY_A	= 1<<1,
++	IEEE80211_RATE_MANDATORY_B	= 1<<2,
++	IEEE80211_RATE_MANDATORY_G	= 1<<3,
++	IEEE80211_RATE_ERP_G		= 1<<4,
++};
++
++/**
++ * struct ieee80211_rate - bitrate definition
++ *
++ * This structure describes a bitrate that an 802.11 PHY can
++ * operate with. The two values @hw_value and @hw_value_short
++ * are only for driver use when pointers to this structure are
++ * passed around.
++ *
++ * @flags: rate-specific flags
++ * @bitrate: bitrate in units of 100 Kbps
++ * @hw_value: driver/hardware value for this rate
++ * @hw_value_short: driver/hardware value for this rate when
++ *	short preamble is used
++ */
++struct ieee80211_rate {
++	u32 flags;
++	u16 bitrate;
++	u16 hw_value, hw_value_short;
++};
++
++/**
++ * struct ieee80211_ht_info - describing STA's HT capabilities
++ *
++ * This structure describes most essential parameters needed
++ * to describe 802.11n HT capabilities for an STA.
++ *
++ * @ht_supported: is HT supported by STA, 0: no, 1: yes
++ * @cap: HT capabilities map as described in 802.11n spec
++ * @ampdu_factor: Maximum A-MPDU length factor
++ * @ampdu_density: Minimum A-MPDU spacing
++ * @supp_mcs_set: Supported MCS set as described in 802.11n spec
++ */
++struct ieee80211_ht_info {
++	u16 cap; /* use IEEE80211_HT_CAP_ */
++	u8 ht_supported;
++	u8 ampdu_factor;
++	u8 ampdu_density;
++	u8 supp_mcs_set[16];
++};
++
++/**
++ * struct ieee80211_supported_band - frequency band definition
++ *
++ * This structure describes a frequency band a wiphy
++ * is able to operate in.
++ *
++ * @channels: Array of channels the hardware can operate in
++ *	in this band.
++ * @band: the band this structure represents
++ * @n_channels: Number of channels in @channels
++ * @bitrates: Array of bitrates the hardware can operate with
++ *	in this band. Must be sorted to give a valid "supported
++ *	rates" IE, i.e. CCK rates first, then OFDM.
++ * @n_bitrates: Number of bitrates in @bitrates
++ */
++struct ieee80211_supported_band {
++	struct ieee80211_channel *channels;
++	struct ieee80211_rate *bitrates;
++	enum ieee80211_band band;
++	int n_channels;
++	int n_bitrates;
++	struct ieee80211_ht_info ht_info;
++};
++
++/**
+  * struct wiphy - wireless hardware description
+  * @idx: the wiphy index assigned to this item
+  * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name>
+@@ -30,6 +186,8 @@ struct wiphy {
+ 	 * help determine whether you own this wiphy or not. */
+ 	void *privid;
+ 
++	struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
++
+ 	/* fields below are read-only, assigned by cfg80211 */
+ 
+ 	/* the item in /sys/class/ieee80211/ points to this,
+@@ -136,4 +294,32 @@ extern void wiphy_unregister(struct wiphy *wiphy);
+  */
+ extern void wiphy_free(struct wiphy *wiphy);
+ 
++/**
++ * ieee80211_channel_to_frequency - convert channel number to frequency
++ */
++extern int ieee80211_channel_to_frequency(int chan);
++
++/**
++ * ieee80211_frequency_to_channel - convert frequency to channel number
++ */
++extern int ieee80211_frequency_to_channel(int freq);
++
++/*
++ * Name indirection necessary because the ieee80211 code also has
++ * a function named "ieee80211_get_channel", so if you include
++ * cfg80211's header file you get cfg80211's version, if you try
++ * to include both header files you'll (rightfully!) get a symbol
++ * clash.
++ */
++extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
++							 int freq);
++
++/**
++ * ieee80211_get_channel - get channel struct from wiphy for specified frequency
++ */
++static inline struct ieee80211_channel *
++ieee80211_get_channel(struct wiphy *wiphy, int freq)
++{
++	return __ieee80211_get_channel(wiphy, freq);
++}
+ #endif /* __NET_WIRELESS_H */
+diff --git a/include/net/xfrm.h b/include/net/xfrm.h
+index 0d255ae..baa9f37 100644
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -121,6 +121,7 @@ extern struct mutex xfrm_cfg_mutex;
+ struct xfrm_state
+ {
+ 	/* Note: bydst is re-used during gc */
++	struct list_head	all;
+ 	struct hlist_node	bydst;
+ 	struct hlist_node	bysrc;
+ 	struct hlist_node	byspi;
+@@ -435,6 +436,9 @@ struct xfrm_tmpl
+ /* May skip this transfomration if no SA is found */
+ 	__u8			optional;
+ 
++/* Skip aalgos/ealgos/calgos checks. */
++	__u8			allalgs;
++
+ /* Bit mask of algos allowed for acquisition */
+ 	__u32			aalgos;
+ 	__u32			ealgos;
+@@ -446,6 +450,7 @@ struct xfrm_tmpl
+ struct xfrm_policy
+ {
+ 	struct xfrm_policy	*next;
++	struct list_head	bytype;
+ 	struct hlist_node	bydst;
+ 	struct hlist_node	byidx;
+ 
+@@ -1071,6 +1076,23 @@ xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
+ 	return NULL;
+ }
+ 
++static __inline__
++void xfrm_flowi_addr_get(struct flowi *fl,
++			 xfrm_address_t *saddr, xfrm_address_t *daddr,
++			 unsigned short family)
++{
++	switch(family) {
++	case AF_INET:
++		memcpy(&saddr->a4, &fl->fl4_src, sizeof(saddr->a4));
++		memcpy(&daddr->a4, &fl->fl4_dst, sizeof(daddr->a4));
++		break;
++	case AF_INET6:
++		ipv6_addr_copy((struct in6_addr *)&saddr->a6, &fl->fl6_src);
++		ipv6_addr_copy((struct in6_addr *)&daddr->a6, &fl->fl6_dst);
++		break;
++	}
++}
++
+ static __inline__ int
+ __xfrm4_state_addr_check(struct xfrm_state *x,
+ 			 xfrm_address_t *daddr, xfrm_address_t *saddr)
+@@ -1188,6 +1210,18 @@ struct xfrm6_tunnel {
+ 	int priority;
+ };
+ 
++struct xfrm_state_walk {
++	struct xfrm_state *state;
++	int count;
++	u8 proto;
++};
++
++struct xfrm_policy_walk {
++	struct xfrm_policy *policy;
++	int count;
++	u8 type, cur_type;
++};
++
+ extern void xfrm_init(void);
+ extern void xfrm4_init(void);
+ extern void xfrm_state_init(void);
+@@ -1212,7 +1246,23 @@ static inline void xfrm6_fini(void)
+ extern int xfrm_proc_init(void);
+ #endif
+ 
+-extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
++static inline void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
++{
++	walk->proto = proto;
++	walk->state = NULL;
++	walk->count = 0;
++}
++
++static inline void xfrm_state_walk_done(struct xfrm_state_walk *walk)
++{
++	if (walk->state != NULL) {
++		xfrm_state_put(walk->state);
++		walk->state = NULL;
++	}
++}
++
++extern int xfrm_state_walk(struct xfrm_state_walk *walk,
++			   int (*func)(struct xfrm_state *, int, void*), void *);
+ extern struct xfrm_state *xfrm_state_alloc(void);
+ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 
+ 					  struct flowi *fl, struct xfrm_tmpl *tmpl,
+@@ -1335,7 +1385,25 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
+ #endif
+ 
+ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
+-extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), void *);
++
++static inline void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type)
++{
++	walk->cur_type = XFRM_POLICY_TYPE_MAIN;
++	walk->type = type;
++	walk->policy = NULL;
++	walk->count = 0;
++}
++
++static inline void xfrm_policy_walk_done(struct xfrm_policy_walk *walk)
++{
++	if (walk->policy != NULL) {
++		xfrm_pol_put(walk->policy);
++		walk->policy = NULL;
++	}
++}
++
++extern int xfrm_policy_walk(struct xfrm_policy_walk *walk,
++	int (*func)(struct xfrm_policy *, int, int, void*), void *);
+ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
+ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
+ 					  struct xfrm_selector *sel,
+diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
+index 64a721f..8d65bf0 100644
+--- a/include/rdma/ib_user_verbs.h
++++ b/include/rdma/ib_user_verbs.h
+@@ -533,7 +533,10 @@ struct ib_uverbs_send_wr {
+ 	__u32 num_sge;
+ 	__u32 opcode;
+ 	__u32 send_flags;
+-	__u32 imm_data;
++	union {
++		__u32 imm_data;
++		__u32 invalidate_rkey;
++	} ex;
+ 	union {
+ 		struct {
+ 			__u64 remote_addr;
+diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
+index 701e7b4..2dcbecc 100644
+--- a/include/rdma/ib_verbs.h
++++ b/include/rdma/ib_verbs.h
+@@ -94,7 +94,7 @@ enum ib_device_cap_flags {
+ 	IB_DEVICE_SRQ_RESIZE		= (1<<13),
+ 	IB_DEVICE_N_NOTIFY_CQ		= (1<<14),
+ 	IB_DEVICE_ZERO_STAG		= (1<<15),
+-	IB_DEVICE_SEND_W_INV		= (1<<16),
++	IB_DEVICE_RESERVED		= (1<<16), /* old SEND_W_INV */
+ 	IB_DEVICE_MEM_WINDOW		= (1<<17),
+ 	/*
+ 	 * Devices should set IB_DEVICE_UD_IP_SUM if they support
+@@ -104,6 +104,8 @@ enum ib_device_cap_flags {
+ 	 * IPoIB driver may set NETIF_F_IP_CSUM for datagram mode.
+ 	 */
+ 	IB_DEVICE_UD_IP_CSUM		= (1<<18),
++	IB_DEVICE_UD_TSO		= (1<<19),
++	IB_DEVICE_SEND_W_INV		= (1<<21),
+ };
+ 
+ enum ib_atomic_cap {
+@@ -411,6 +413,7 @@ enum ib_wc_opcode {
+ 	IB_WC_COMP_SWAP,
+ 	IB_WC_FETCH_ADD,
+ 	IB_WC_BIND_MW,
++	IB_WC_LSO,
+ /*
+  * Set value of IB_WC_RECV so consumers can test if a completion is a
+  * receive by testing (opcode & IB_WC_RECV).
+@@ -495,6 +498,10 @@ enum ib_qp_type {
+ 	IB_QPT_RAW_ETY
+ };
+ 
++enum ib_qp_create_flags {
++	IB_QP_CREATE_IPOIB_UD_LSO	= 1 << 0,
++};
++
+ struct ib_qp_init_attr {
+ 	void                  (*event_handler)(struct ib_event *, void *);
+ 	void		       *qp_context;
+@@ -504,6 +511,7 @@ struct ib_qp_init_attr {
+ 	struct ib_qp_cap	cap;
+ 	enum ib_sig_type	sq_sig_type;
+ 	enum ib_qp_type		qp_type;
++	enum ib_qp_create_flags	create_flags;
+ 	u8			port_num; /* special QP types only */
+ };
+ 
+@@ -617,7 +625,9 @@ enum ib_wr_opcode {
+ 	IB_WR_SEND_WITH_IMM,
+ 	IB_WR_RDMA_READ,
+ 	IB_WR_ATOMIC_CMP_AND_SWP,
+-	IB_WR_ATOMIC_FETCH_AND_ADD
++	IB_WR_ATOMIC_FETCH_AND_ADD,
++	IB_WR_LSO,
++	IB_WR_SEND_WITH_INV,
+ };
+ 
+ enum ib_send_flags {
+@@ -641,7 +651,10 @@ struct ib_send_wr {
+ 	int			num_sge;
+ 	enum ib_wr_opcode	opcode;
+ 	int			send_flags;
+-	__be32			imm_data;
++	union {
++		__be32		imm_data;
++		u32		invalidate_rkey;
++	} ex;
+ 	union {
+ 		struct {
+ 			u64	remote_addr;
+@@ -655,6 +668,9 @@ struct ib_send_wr {
+ 		} atomic;
+ 		struct {
+ 			struct ib_ah *ah;
++			void   *header;
++			int     hlen;
++			int     mss;
+ 			u32	remote_qpn;
+ 			u32	remote_qkey;
+ 			u16	pkey_index; /* valid for GSI only */
+@@ -730,7 +746,7 @@ struct ib_uobject {
+ 	struct ib_ucontext     *context;	/* associated user context */
+ 	void		       *object;		/* containing object */
+ 	struct list_head	list;		/* link to context's list */
+-	u32			id;		/* index into kernel idr */
++	int			id;		/* index into kernel idr */
+ 	struct kref		ref;
+ 	struct rw_semaphore	mutex;		/* protects .live */
+ 	int			live;
+@@ -971,6 +987,8 @@ struct ib_device {
+ 						int comp_vector,
+ 						struct ib_ucontext *context,
+ 						struct ib_udata *udata);
++	int                        (*modify_cq)(struct ib_cq *cq, u16 cq_count,
++						u16 cq_period);
+ 	int                        (*destroy_cq)(struct ib_cq *cq);
+ 	int                        (*resize_cq)(struct ib_cq *cq, int cqe,
+ 						struct ib_udata *udata);
+@@ -1033,7 +1051,7 @@ struct ib_device {
+ 	struct ib_dma_mapping_ops   *dma_ops;
+ 
+ 	struct module               *owner;
+-	struct class_device          class_dev;
++	struct device                dev;
+ 	struct kobject               *ports_parent;
+ 	struct list_head             port_list;
+ 
+@@ -1376,6 +1394,15 @@ struct ib_cq *ib_create_cq(struct ib_device *device,
+ int ib_resize_cq(struct ib_cq *cq, int cqe);
+ 
+ /**
++ * ib_modify_cq - Modifies moderation params of the CQ
++ * @cq: The CQ to modify.
++ * @cq_count: number of CQEs that will trigger an event
++ * @cq_period: max period of time in usec before triggering an event
++ *
++ */
++int ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
++
++/**
+  * ib_destroy_cq - Destroys the specified CQ.
+  * @cq: The CQ to destroy.
+  */
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index 5ffec8a..e0593bf 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -112,6 +112,7 @@ struct iscsi_ahs_hdr {
+ 
+ #define ISCSI_AHSTYPE_CDB		1
+ #define ISCSI_AHSTYPE_RLENGTH		2
++#define ISCSI_CDB_SIZE			16
+ 
+ /* iSCSI PDU Header */
+ struct iscsi_cmd {
+@@ -125,7 +126,7 @@ struct iscsi_cmd {
+ 	__be32 data_length;
+ 	__be32 cmdsn;
+ 	__be32 exp_statsn;
+-	uint8_t cdb[16];	/* SCSI Command Block */
++	uint8_t cdb[ISCSI_CDB_SIZE];	/* SCSI Command Block */
+ 	/* Additional Data (Command Dependent) */
+ };
+ 
+@@ -154,7 +155,8 @@ struct iscsi_ecdb_ahdr {
+ 	__be16 ahslength;	/* CDB length - 15, including reserved byte */
+ 	uint8_t ahstype;
+ 	uint8_t reserved;
+-	uint8_t ecdb[260 - 16];	/* 4-byte aligned extended CDB spillover */
++	/* 4-byte aligned extended CDB spillover */
++	uint8_t ecdb[260 - ISCSI_CDB_SIZE];
+ };
+ 
+ /* SCSI Response Header */
+diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
+index 39e1cac..e78d3b6 100644
+--- a/include/scsi/libsas.h
++++ b/include/scsi/libsas.h
+@@ -32,7 +32,6 @@
+ #include <scsi/sas.h>
+ #include <linux/libata.h>
+ #include <linux/list.h>
+-#include <asm/semaphore.h>
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_transport_sas.h>
+@@ -677,4 +676,6 @@ extern void sas_ssp_task_response(struct device *dev, struct sas_task *task,
+ 				  struct ssp_response_iu *iu);
+ struct sas_phy *sas_find_local_phy(struct domain_device *dev);
+ 
++int sas_request_addr(struct Scsi_Host *shost, u8 *addr);
++
+ #endif /* _SASLIB_H_ */
+diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
+index dd5edc9..c583193 100644
+--- a/include/scsi/sas_ata.h
++++ b/include/scsi/sas_ata.h
+@@ -47,12 +47,12 @@ static inline int dev_is_sata(struct domain_device *dev)
+ {
+ 	return 0;
+ }
+-int sas_ata_init_host_and_port(struct domain_device *found_dev,
++static inline int sas_ata_init_host_and_port(struct domain_device *found_dev,
+ 			       struct scsi_target *starget)
+ {
+ 	return 0;
+ }
+-void sas_ata_task_abort(struct sas_task *task)
++static inline void sas_ata_task_abort(struct sas_task *task)
+ {
+ }
+ #endif
+diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
+index de28aab..8d20e60 100644
+--- a/include/scsi/scsi_cmnd.h
++++ b/include/scsi/scsi_cmnd.h
+@@ -130,6 +130,9 @@ extern void scsi_release_buffers(struct scsi_cmnd *cmd);
+ extern int scsi_dma_map(struct scsi_cmnd *cmd);
+ extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
+ 
++struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask);
++void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd);
++
+ static inline unsigned scsi_sg_count(struct scsi_cmnd *cmd)
+ {
+ 	return cmd->sdb.table.nents;
+@@ -175,4 +178,18 @@ static inline struct scsi_data_buffer *scsi_out(struct scsi_cmnd *cmd)
+ 	return &cmd->sdb;
+ }
+ 
++static inline int scsi_sg_copy_from_buffer(struct scsi_cmnd *cmd,
++					   void *buf, int buflen)
++{
++	return sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
++				   buf, buflen);
++}
++
++static inline int scsi_sg_copy_to_buffer(struct scsi_cmnd *cmd,
++					 void *buf, int buflen)
++{
++	return sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
++				 buf, buflen);
++}
++
+ #endif /* _SCSI_SCSI_CMND_H */
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index ab7acbe..b8b19e2 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -156,8 +156,8 @@ struct scsi_device {
+ 
+ 	int timeout;
+ 
+-	struct device		sdev_gendev;
+-	struct class_device	sdev_classdev;
++	struct device		sdev_gendev,
++				sdev_dev;
+ 
+ 	struct execute_work	ew; /* used to get process context on put */
+ 
+@@ -167,9 +167,9 @@ struct scsi_device {
+ #define	to_scsi_device(d)	\
+ 	container_of(d, struct scsi_device, sdev_gendev)
+ #define	class_to_sdev(d)	\
+-	container_of(d, struct scsi_device, sdev_classdev)
++	container_of(d, struct scsi_device, sdev_dev)
+ #define transport_class_to_sdev(class_dev) \
+-	to_scsi_device(class_dev->dev)
++	to_scsi_device(class_dev->parent)
+ 
+ #define sdev_printk(prefix, sdev, fmt, a...)	\
+ 	dev_printk(prefix, &(sdev)->sdev_gendev, fmt, ##a)
+@@ -220,7 +220,7 @@ static inline struct scsi_target *scsi_target(struct scsi_device *sdev)
+ 	return to_scsi_target(sdev->sdev_gendev.parent);
+ }
+ #define transport_class_to_starget(class_dev) \
+-	to_scsi_target(class_dev->dev)
++	to_scsi_target(class_dev->parent)
+ 
+ #define starget_printk(prefix, starget, fmt, a...)	\
+ 	dev_printk(prefix, &(starget)->dev, fmt, ##a)
+diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
+index 25071d5..d3a133b 100644
+--- a/include/scsi/scsi_eh.h
++++ b/include/scsi/scsi_eh.h
+@@ -57,13 +57,16 @@ extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
+ 
+ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
+ 				   u64 * info_out);
+- 
++
++extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
++
+ /*
+  * Reset request from external source
+  */
+ #define SCSI_TRY_RESET_DEVICE	1
+ #define SCSI_TRY_RESET_BUS	2
+ #define SCSI_TRY_RESET_HOST	3
++#define SCSI_TRY_RESET_TARGET	4
+ 
+ extern int scsi_reset_provider(struct scsi_device *, int);
+ 
+diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
+index 530ff4c..d967d6d 100644
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -172,6 +172,7 @@ struct scsi_host_template {
+ 	 */
+ 	int (* eh_abort_handler)(struct scsi_cmnd *);
+ 	int (* eh_device_reset_handler)(struct scsi_cmnd *);
++	int (* eh_target_reset_handler)(struct scsi_cmnd *);
+ 	int (* eh_bus_reset_handler)(struct scsi_cmnd *);
+ 	int (* eh_host_reset_handler)(struct scsi_cmnd *);
+ 
+@@ -469,7 +470,7 @@ struct scsi_host_template {
+ 	/*
+ 	 * Pointer to the sysfs class properties for this host, NULL terminated.
+ 	 */
+-	struct class_device_attribute **shost_attrs;
++	struct device_attribute **shost_attrs;
+ 
+ 	/*
+ 	 * Pointer to the SCSI device properties for this host, NULL terminated.
+@@ -654,8 +655,7 @@ struct Scsi_Host {
+ 	enum scsi_host_state shost_state;
+ 
+ 	/* ldm bits */
+-	struct device		shost_gendev;
+-	struct class_device	shost_classdev;
++	struct device		shost_gendev, shost_dev;
+ 
+ 	/*
+ 	 * List of hosts per template.
+@@ -682,7 +682,7 @@ struct Scsi_Host {
+ };
+ 
+ #define		class_to_shost(d)	\
+-	container_of(d, struct Scsi_Host, shost_classdev)
++	container_of(d, struct Scsi_Host, shost_dev)
+ 
+ #define shost_printk(prefix, shost, fmt, a...)	\
+ 	dev_printk(prefix, &(shost)->shost_gendev, fmt, ##a)
+diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
+index 0dfef75..490bd13 100644
+--- a/include/scsi/scsi_transport.h
++++ b/include/scsi/scsi_transport.h
+@@ -80,7 +80,7 @@ struct scsi_transport_template {
+ };
+ 
+ #define transport_class_to_shost(tc) \
+-	dev_to_shost((tc)->dev)
++	dev_to_shost((tc)->parent)
+ 
+ 
+ /* Private area maintenance. The driver requested allocations come
+diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
+index 4769efd..06f72ba 100644
+--- a/include/scsi/scsi_transport_fc.h
++++ b/include/scsi/scsi_transport_fc.h
+@@ -163,8 +163,8 @@ enum fc_tgtid_binding_type  {
+ 
+ 
+ /* Macro for use in defining Virtual Port attributes */
+-#define FC_VPORT_ATTR(_name,_mode,_show,_store)				\
+-struct class_device_attribute class_device_attr_vport_##_name = 	\
++#define FC_VPORT_ATTR(_name,_mode,_show,_store)		\
++struct device_attribute dev_attr_vport_##_name = 	\
+ 	__ATTR(_name,_mode,_show,_store)
+ 
+ 
+@@ -234,8 +234,8 @@ struct fc_vport {
+ 
+ #define	dev_to_vport(d)				\
+ 	container_of(d, struct fc_vport, dev)
+-#define transport_class_to_vport(classdev)	\
+-	dev_to_vport(classdev->dev)
++#define transport_class_to_vport(dev)		\
++	dev_to_vport(dev->parent)
+ #define vport_to_shost(v)			\
+ 	(v->shost)
+ #define vport_to_shost_channel(v)		\
+@@ -271,7 +271,7 @@ struct fc_rport_identifiers {
+ 
+ /* Macro for use in defining Remote Port attributes */
+ #define FC_RPORT_ATTR(_name,_mode,_show,_store)				\
+-struct class_device_attribute class_device_attr_rport_##_name = 	\
++struct device_attribute dev_attr_rport_##_name = 	\
+ 	__ATTR(_name,_mode,_show,_store)
+ 
+ 
+@@ -341,8 +341,8 @@ struct fc_rport {	/* aka fc_starget_attrs */
+ 
+ #define	dev_to_rport(d)				\
+ 	container_of(d, struct fc_rport, dev)
+-#define transport_class_to_rport(classdev)	\
+-	dev_to_rport(classdev->dev)
++#define transport_class_to_rport(dev)	\
++	dev_to_rport(dev->parent)
+ #define rport_to_shost(r)			\
+ 	dev_to_shost(r->dev.parent)
+ 
+diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
+index 09125fa..61ad359 100644
+--- a/include/scsi/scsi_transport_sas.h
++++ b/include/scsi/scsi_transport_sas.h
+@@ -80,8 +80,8 @@ struct sas_phy {
+ 
+ #define dev_to_phy(d) \
+ 	container_of((d), struct sas_phy, dev)
+-#define transport_class_to_phy(cdev) \
+-	dev_to_phy((cdev)->dev)
++#define transport_class_to_phy(dev) \
++	dev_to_phy((dev)->parent)
+ #define phy_to_shost(phy) \
+ 	dev_to_shost((phy)->dev.parent)
+ 
+@@ -96,8 +96,8 @@ struct sas_rphy {
+ 
+ #define dev_to_rphy(d) \
+ 	container_of((d), struct sas_rphy, dev)
+-#define transport_class_to_rphy(cdev) \
+-	dev_to_rphy((cdev)->dev)
++#define transport_class_to_rphy(dev) \
++	dev_to_rphy((dev)->parent)
+ #define rphy_to_shost(rphy) \
+ 	dev_to_shost((rphy)->dev.parent)
+ #define target_to_rphy(targ) \
+@@ -152,8 +152,8 @@ struct sas_port {
+ 
+ #define dev_to_sas_port(d) \
+ 	container_of((d), struct sas_port, dev)
+-#define transport_class_to_sas_port(cdev) \
+-	dev_to_sas_port((cdev)->dev)
++#define transport_class_to_sas_port(dev) \
++	dev_to_sas_port((dev)->parent)
+ 
+ struct sas_phy_linkrates {
+ 	enum sas_linkrate maximum_linkrate;
+diff --git a/include/scsi/sd.h b/include/scsi/sd.h
+index 8ea9f73..4f032d4 100644
+--- a/include/scsi/sd.h
++++ b/include/scsi/sd.h
+@@ -34,7 +34,7 @@
+ struct scsi_disk {
+ 	struct scsi_driver *driver;	/* always &sd_template */
+ 	struct scsi_device *device;
+-	struct class_device cdev;
++	struct device	dev;
+ 	struct gendisk	*disk;
+ 	unsigned int	openers;	/* protected by BKL for now, yuck */
+ 	sector_t	capacity;	/* size in 512-byte sectors */
+@@ -46,7 +46,7 @@ struct scsi_disk {
+ 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
+ 	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
+ };
+-#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev)
++#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
+ 
+ #define sd_printk(prefix, sdsk, fmt, a...)				\
+         (sdsk)->disk ?							\
+diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
+index 0148058..049edc5 100644
+--- a/include/sound/ac97_codec.h
++++ b/include/sound/ac97_codec.h
+@@ -397,6 +397,7 @@
+ #define AC97_HAS_NO_TONE	(1<<16) /* no Tone volume */
+ #define AC97_HAS_NO_STD_PCM	(1<<17)	/* no standard AC97 PCM volume and mute */
+ #define AC97_HAS_NO_AUX		(1<<18) /* no standard AC97 AUX volume and mute */
++#define AC97_HAS_8CH		(1<<19) /* supports 8-channel output */
+ 
+ /* rates indexes */
+ #define AC97_RATES_FRONT_DAC	0
+diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
+index 4e80d3f..d293d36 100644
+--- a/include/sound/ak4114.h
++++ b/include/sound/ak4114.h
+@@ -182,6 +182,7 @@ struct ak4114 {
+ 	unsigned char rcs0;
+ 	unsigned char rcs1;
+ 	struct delayed_work work;
++	unsigned int check_flags;
+ 	void *change_callback_private;
+ 	void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1);
+ };
+diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
+index 6153b91..891cf1a 100644
+--- a/include/sound/ak4xxx-adda.h
++++ b/include/sound/ak4xxx-adda.h
+@@ -68,7 +68,7 @@ struct snd_akm4xxx {
+ 	enum {
+ 		SND_AK4524, SND_AK4528, SND_AK4529,
+ 		SND_AK4355, SND_AK4358, SND_AK4381,
+-		SND_AK5365, NON_AKM
++		SND_AK5365
+ 	} type;
+ 
+ 	/* (array) information of combined codecs */
+diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h
+index 024ce62..a6e0fac 100644
+--- a/include/sound/asoundef.h
++++ b/include/sound/asoundef.h
+@@ -112,6 +112,14 @@
+ #define IEC958_AES3_CON_CLOCK_1000PPM	(0<<4)	/* 1000 ppm */
+ #define IEC958_AES3_CON_CLOCK_50PPM	(1<<4)	/* 50 ppm */
+ #define IEC958_AES3_CON_CLOCK_VARIABLE	(2<<4)	/* variable pitch */
++#define IEC958_AES4_CON_MAX_WORDLEN_24	(1<<0)	/* 0 = 20-bit, 1 = 24-bit */
++#define IEC958_AES4_CON_WORDLEN		(7<<1)	/* mask - sample word length */
++#define IEC958_AES4_CON_WORDLEN_NOTID	(0<<1)	/* not indicated */
++#define IEC958_AES4_CON_WORDLEN_20_16	(1<<1)	/* 20-bit or 16-bit */
++#define IEC958_AES4_CON_WORDLEN_22_18	(2<<1)	/* 22-bit or 18-bit */
++#define IEC958_AES4_CON_WORDLEN_23_19	(4<<1)	/* 23-bit or 19-bit */
++#define IEC958_AES4_CON_WORDLEN_24_20	(5<<1)	/* 24-bit or 20-bit */
++#define IEC958_AES4_CON_WORDLEN_21_17	(6<<1)	/* 21-bit or 17-bit */
+ 
+ /*****************************************************************************
+  *                                                                           *
+diff --git a/include/sound/control.h b/include/sound/control.h
+index e79baa6..3dc1291 100644
+--- a/include/sound/control.h
++++ b/include/sound/control.h
+@@ -169,4 +169,11 @@ int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
+ int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
+ 				struct snd_ctl_elem_info *uinfo);
+ 
++/*
++ * virtual master control
++ */
++struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
++						 const unsigned int *tlv);
++int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave);
++		      
+ #endif	/* __SOUND_CONTROL_H */
+diff --git a/include/sound/core.h b/include/sound/core.h
+index 4fc0235..695ee53 100644
+--- a/include/sound/core.h
++++ b/include/sound/core.h
+@@ -277,8 +277,8 @@ int snd_minor_info_done(void);
+ int snd_minor_info_oss_init(void);
+ int snd_minor_info_oss_done(void);
+ #else
+-#define snd_minor_info_oss_init() /*NOP*/
+-#define snd_minor_info_oss_done() /*NOP*/
++static inline int snd_minor_info_oss_init(void) { return 0; }
++static inline int snd_minor_info_oss_done(void) { return 0; }
+ #endif
+ 
+ /* memory.c */
+@@ -310,7 +310,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file);
+ int snd_card_file_remove(struct snd_card *card, struct file *file);
+ 
+ #ifndef snd_card_set_dev
+-#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
++#define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
+ #endif
+ 
+ /* device.c */
+@@ -373,7 +373,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
+  * snd_printd - debug printk
+  * @fmt: format string
+  *
+- * Compiled only when Works like snd_printk() for debugging purpose.
++ * Works like snd_printk() for debugging purposes.
+  * Ignored when CONFIG_SND_DEBUG is not set.
+  */
+ #define snd_printd(fmt, args...) \
+@@ -417,7 +417,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
+  * snd_printdd - debug printk
+  * @format: format string
+  *
+- * Compiled only when Works like snd_printk() for debugging purpose.
++ * Works like snd_printk() for debugging purposes.
+  * Ignored when CONFIG_SND_DEBUG_DETECT is not set.
+  */
+ #define snd_printdd(format, args...) snd_printk(format, ##args)
+diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h
+index d45218b..68b634b 100644
+--- a/include/sound/mpu401.h
++++ b/include/sound/mpu401.h
+@@ -103,6 +103,21 @@ struct snd_mpu401 {
+ #define MPU401D(mpu) (mpu)->port
+ 
+ /*
++ * control register bits
++ */
++/* read MPU401C() */
++#define MPU401_RX_EMPTY		0x80
++#define MPU401_TX_FULL		0x40
++
++/* write MPU401C() */
++#define MPU401_RESET		0xff
++#define MPU401_ENTER_UART	0x3f
++
++/* read MPU401D() */
++#define MPU401_ACK		0xfe
++
++
++/*
+ 
+  */
+ 
+diff --git a/include/sound/version.h b/include/sound/version.h
+index fac66c4..ed6fb2e 100644
+--- a/include/sound/version.h
++++ b/include/sound/version.h
+@@ -1,3 +1,3 @@
+ /* include/version.h.  Generated by alsa/ksync script.  */
+-#define CONFIG_SND_VERSION "1.0.16rc2"
+-#define CONFIG_SND_DATE " (Thu Jan 31 16:40:16 2008 UTC)"
++#define CONFIG_SND_VERSION "1.0.16"
++#define CONFIG_SND_DATE ""
+diff --git a/include/xen/balloon.h b/include/xen/balloon.h
+new file mode 100644
+index 0000000..fe43b0f
+--- /dev/null
++++ b/include/xen/balloon.h
+@@ -0,0 +1,61 @@
++/******************************************************************************
++ * balloon.h
++ *
++ * Xen balloon driver - enables returning/claiming memory to/from Xen.
++ *
++ * Copyright (c) 2003, B Dragovic
++ * Copyright (c) 2003-2004, M Williamson, K Fraser
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#ifndef __XEN_BALLOON_H__
++#define __XEN_BALLOON_H__
++
++#include <linux/spinlock.h>
++
++#if 0
++/*
++ * Inform the balloon driver that it should allow some slop for device-driver
++ * memory activities.
++ */
++void balloon_update_driver_allowance(long delta);
++
++/* Allocate/free a set of empty pages in low memory (i.e., no RAM mapped). */
++struct page **alloc_empty_pages_and_pagevec(int nr_pages);
++void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages);
++
++void balloon_release_driver_page(struct page *page);
++
++/*
++ * Prevent the balloon driver from changing the memory reservation during
++ * a driver critical region.
++ */
++extern spinlock_t balloon_lock;
++#define balloon_lock(__flags)   spin_lock_irqsave(&balloon_lock, __flags)
++#define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags)
++#endif
++
++#endif /* __XEN_BALLOON_H__ */
+diff --git a/include/xen/events.h b/include/xen/events.h
+index 2bde54d..acd8e06 100644
+--- a/include/xen/events.h
++++ b/include/xen/events.h
+@@ -5,13 +5,7 @@
+ 
+ #include <xen/interface/event_channel.h>
+ #include <asm/xen/hypercall.h>
+-
+-enum ipi_vector {
+-	XEN_RESCHEDULE_VECTOR,
+-	XEN_CALL_FUNCTION_VECTOR,
+-
+-	XEN_NR_IPIS,
+-};
++#include <asm/xen/events.h>
+ 
+ int bind_evtchn_to_irq(unsigned int evtchn);
+ int bind_evtchn_to_irqhandler(unsigned int evtchn,
+@@ -37,6 +31,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
+ void unbind_from_irqhandler(unsigned int irq, void *dev_id);
+ 
+ void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector);
++int resend_irq_on_evtchn(unsigned int irq);
+ 
+ static inline void notify_remote_via_evtchn(int port)
+ {
+diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
+index 761c834..4662048 100644
+--- a/include/xen/grant_table.h
++++ b/include/xen/grant_table.h
+@@ -39,6 +39,7 @@
+ 
+ #include <asm/xen/hypervisor.h>
+ #include <xen/interface/grant_table.h>
++#include <asm/xen/grant_table.h>
+ 
+ /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
+ #define NR_GRANT_FRAMES 4
+@@ -102,6 +103,12 @@ void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+ void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
+ 				       unsigned long pfn);
+ 
++int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
++			   unsigned long max_nr_gframes,
++			   struct grant_entry **__shared);
++void arch_gnttab_unmap_shared(struct grant_entry *shared,
++			      unsigned long nr_gframes);
++
+ #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
+ 
+ #endif /* __ASM_GNTTAB_H__ */
+diff --git a/include/xen/interface/callback.h b/include/xen/interface/callback.h
+new file mode 100644
+index 0000000..4aadcba
+--- /dev/null
++++ b/include/xen/interface/callback.h
+@@ -0,0 +1,102 @@
++/******************************************************************************
++ * callback.h
++ *
++ * Register guest OS callbacks with Xen.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * 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.
++ *
++ * Copyright (c) 2006, Ian Campbell
++ */
++
++#ifndef __XEN_PUBLIC_CALLBACK_H__
++#define __XEN_PUBLIC_CALLBACK_H__
++
++#include "xen.h"
++
++/*
++ * Prototype for this hypercall is:
++ *   long callback_op(int cmd, void *extra_args)
++ * @cmd        == CALLBACKOP_??? (callback operation).
++ * @extra_args == Operation-specific extra arguments (NULL if none).
++ */
++
++/* ia64, x86: Callback for event delivery. */
++#define CALLBACKTYPE_event                 0
++
++/* x86: Failsafe callback when guest state cannot be restored by Xen. */
++#define CALLBACKTYPE_failsafe              1
++
++/* x86/64 hypervisor: Syscall by 64-bit guest app ('64-on-64-on-64'). */
++#define CALLBACKTYPE_syscall               2
++
++/*
++ * x86/32 hypervisor: Only available on x86/32 when supervisor_mode_kernel
++ *     feature is enabled. Do not use this callback type in new code.
++ */
++#define CALLBACKTYPE_sysenter_deprecated   3
++
++/* x86: Callback for NMI delivery. */
++#define CALLBACKTYPE_nmi                   4
++
++/*
++ * x86: sysenter is only available as follows:
++ * - 32-bit hypervisor: with the supervisor_mode_kernel feature enabled
++ * - 64-bit hypervisor: 32-bit guest applications on Intel CPUs
++ *                      ('32-on-32-on-64', '32-on-64-on-64')
++ *                      [nb. also 64-bit guest applications on Intel CPUs
++ *                           ('64-on-64-on-64'), but syscall is preferred]
++ */
++#define CALLBACKTYPE_sysenter              5
++
++/*
++ * x86/64 hypervisor: Syscall by 32-bit guest app on AMD CPUs
++ *                    ('32-on-32-on-64', '32-on-64-on-64')
++ */
++#define CALLBACKTYPE_syscall32             7
++
++/*
++ * Disable event deliver during callback? This flag is ignored for event and
++ * NMI callbacks: event delivery is unconditionally disabled.
++ */
++#define _CALLBACKF_mask_events             0
++#define CALLBACKF_mask_events              (1U << _CALLBACKF_mask_events)
++
++/*
++ * Register a callback.
++ */
++#define CALLBACKOP_register                0
++struct callback_register {
++    uint16_t type;
++    uint16_t flags;
++    struct xen_callback address;
++};
++
++/*
++ * Unregister a callback.
++ *
++ * Not all callbacks can be unregistered. -EINVAL will be returned if
++ * you attempt to unregister such a callback.
++ */
++#define CALLBACKOP_unregister              1
++struct callback_unregister {
++    uint16_t type;
++    uint16_t _unused;
++};
++
++#endif /* __XEN_PUBLIC_CALLBACK_H__ */
+diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
+index 2190498..39da93c 100644
+--- a/include/xen/interface/grant_table.h
++++ b/include/xen/interface/grant_table.h
+@@ -185,6 +185,7 @@ struct gnttab_map_grant_ref {
+     grant_handle_t handle;
+     uint64_t dev_bus_addr;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_map_grant_ref);
+ 
+ /*
+  * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
+@@ -206,6 +207,7 @@ struct gnttab_unmap_grant_ref {
+     /* OUT parameters. */
+     int16_t  status;              /* GNTST_* */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_unmap_grant_ref);
+ 
+ /*
+  * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
+@@ -223,8 +225,9 @@ struct gnttab_setup_table {
+     uint32_t nr_frames;
+     /* OUT parameters. */
+     int16_t  status;              /* GNTST_* */
+-    ulong *frame_list;
++    GUEST_HANDLE(ulong) frame_list;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
+ 
+ /*
+  * GNTTABOP_dump_table: Dump the contents of the grant table to the
+@@ -237,6 +240,7 @@ struct gnttab_dump_table {
+     /* OUT parameters. */
+     int16_t status;               /* GNTST_* */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_dump_table);
+ 
+ /*
+  * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
+@@ -255,7 +259,7 @@ struct gnttab_transfer {
+     /* OUT parameters. */
+     int16_t       status;
+ };
+-
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_transfer);
+ 
+ /*
+  * GNTTABOP_copy: Hypervisor based copy
+@@ -296,6 +300,7 @@ struct gnttab_copy {
+ 	/* OUT parameters. */
+ 	int16_t       status;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_copy);
+ 
+ /*
+  * GNTTABOP_query_size: Query the current and maximum sizes of the shared
+@@ -313,7 +318,7 @@ struct gnttab_query_size {
+     uint32_t max_nr_frames;
+     int16_t  status;              /* GNTST_* */
+ };
+-
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);
+ 
+ /*
+  * Bitfield values for update_pin_status.flags.
+diff --git a/include/xen/interface/io/fbif.h b/include/xen/interface/io/fbif.h
+new file mode 100644
+index 0000000..5a934dd
+--- /dev/null
++++ b/include/xen/interface/io/fbif.h
+@@ -0,0 +1,124 @@
++/*
++ * fbif.h -- Xen virtual frame buffer device
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * 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.
++ *
++ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
++ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
++ */
++
++#ifndef __XEN_PUBLIC_IO_FBIF_H__
++#define __XEN_PUBLIC_IO_FBIF_H__
++
++/* Out events (frontend -> backend) */
++
++/*
++ * Out events may be sent only when requested by backend, and receipt
++ * of an unknown out event is an error.
++ */
++
++/* Event type 1 currently not used */
++/*
++ * Framebuffer update notification event
++ * Capable frontend sets feature-update in xenstore.
++ * Backend requests it by setting request-update in xenstore.
++ */
++#define XENFB_TYPE_UPDATE 2
++
++struct xenfb_update {
++	uint8_t type;		/* XENFB_TYPE_UPDATE */
++	int32_t x;		/* source x */
++	int32_t y;		/* source y */
++	int32_t width;		/* rect width */
++	int32_t height;		/* rect height */
++};
++
++#define XENFB_OUT_EVENT_SIZE 40
++
++union xenfb_out_event {
++	uint8_t type;
++	struct xenfb_update update;
++	char pad[XENFB_OUT_EVENT_SIZE];
++};
++
++/* In events (backend -> frontend) */
++
++/*
++ * Frontends should ignore unknown in events.
++ * No in events currently defined.
++ */
++
++#define XENFB_IN_EVENT_SIZE 40
++
++union xenfb_in_event {
++	uint8_t type;
++	char pad[XENFB_IN_EVENT_SIZE];
++};
++
++/* shared page */
++
++#define XENFB_IN_RING_SIZE 1024
++#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
++#define XENFB_IN_RING_OFFS 1024
++#define XENFB_IN_RING(page) \
++	((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
++#define XENFB_IN_RING_REF(page, idx) \
++	(XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
++
++#define XENFB_OUT_RING_SIZE 2048
++#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
++#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
++#define XENFB_OUT_RING(page) \
++	((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
++#define XENFB_OUT_RING_REF(page, idx) \
++	(XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
++
++struct xenfb_page {
++	uint32_t in_cons, in_prod;
++	uint32_t out_cons, out_prod;
++
++	int32_t width;          /* width of the framebuffer (in pixels) */
++	int32_t height;         /* height of the framebuffer (in pixels) */
++	uint32_t line_length;   /* length of a row of pixels (in bytes) */
++	uint32_t mem_length;    /* length of the framebuffer (in bytes) */
++	uint8_t depth;          /* depth of a pixel (in bits) */
++
++	/*
++	 * Framebuffer page directory
++	 *
++	 * Each directory page holds PAGE_SIZE / sizeof(*pd)
++	 * framebuffer pages, and can thus map up to PAGE_SIZE *
++	 * PAGE_SIZE / sizeof(*pd) bytes.  With PAGE_SIZE == 4096 and
++	 * sizeof(unsigned long) == 4, that's 4 Megs.  Two directory
++	 * pages should be enough for a while.
++	 */
++	unsigned long pd[2];
++};
++
++/*
++ * Wart: xenkbd needs to know resolution.  Put it here until a better
++ * solution is found, but don't leak it to the backend.
++ */
++#ifdef __KERNEL__
++#define XENFB_WIDTH 800
++#define XENFB_HEIGHT 600
++#define XENFB_DEPTH 32
++#endif
++
++#endif
+diff --git a/include/xen/interface/io/kbdif.h b/include/xen/interface/io/kbdif.h
+new file mode 100644
+index 0000000..fb97f42
+--- /dev/null
++++ b/include/xen/interface/io/kbdif.h
+@@ -0,0 +1,114 @@
++/*
++ * kbdif.h -- Xen virtual keyboard/mouse
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * 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.
++ *
++ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
++ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
++ */
++
++#ifndef __XEN_PUBLIC_IO_KBDIF_H__
++#define __XEN_PUBLIC_IO_KBDIF_H__
++
++/* In events (backend -> frontend) */
++
++/*
++ * Frontends should ignore unknown in events.
++ */
++
++/* Pointer movement event */
++#define XENKBD_TYPE_MOTION  1
++/* Event type 2 currently not used */
++/* Key event (includes pointer buttons) */
++#define XENKBD_TYPE_KEY     3
++/*
++ * Pointer position event
++ * Capable backend sets feature-abs-pointer in xenstore.
++ * Frontend requests ot instead of XENKBD_TYPE_MOTION by setting
++ * request-abs-update in xenstore.
++ */
++#define XENKBD_TYPE_POS     4
++
++struct xenkbd_motion {
++	uint8_t type;		/* XENKBD_TYPE_MOTION */
++	int32_t rel_x;		/* relative X motion */
++	int32_t rel_y;		/* relative Y motion */
++};
++
++struct xenkbd_key {
++	uint8_t type;		/* XENKBD_TYPE_KEY */
++	uint8_t pressed;	/* 1 if pressed; 0 otherwise */
++	uint32_t keycode;	/* KEY_* from linux/input.h */
++};
++
++struct xenkbd_position {
++	uint8_t type;		/* XENKBD_TYPE_POS */
++	int32_t abs_x;		/* absolute X position (in FB pixels) */
++	int32_t abs_y;		/* absolute Y position (in FB pixels) */
++};
++
++#define XENKBD_IN_EVENT_SIZE 40
++
++union xenkbd_in_event {
++	uint8_t type;
++	struct xenkbd_motion motion;
++	struct xenkbd_key key;
++	struct xenkbd_position pos;
++	char pad[XENKBD_IN_EVENT_SIZE];
++};
++
++/* Out events (frontend -> backend) */
++
++/*
++ * Out events may be sent only when requested by backend, and receipt
++ * of an unknown out event is an error.
++ * No out events currently defined.
++ */
++
++#define XENKBD_OUT_EVENT_SIZE 40
++
++union xenkbd_out_event {
++	uint8_t type;
++	char pad[XENKBD_OUT_EVENT_SIZE];
++};
++
++/* shared page */
++
++#define XENKBD_IN_RING_SIZE 2048
++#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
++#define XENKBD_IN_RING_OFFS 1024
++#define XENKBD_IN_RING(page) \
++	((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
++#define XENKBD_IN_RING_REF(page, idx) \
++	(XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
++
++#define XENKBD_OUT_RING_SIZE 1024
++#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
++#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
++#define XENKBD_OUT_RING(page) \
++	((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
++#define XENKBD_OUT_RING_REF(page, idx) \
++	(XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
++
++struct xenkbd_page {
++	uint32_t in_cons, in_prod;
++	uint32_t out_cons, out_prod;
++};
++
++#endif
+diff --git a/include/xen/interface/io/protocols.h b/include/xen/interface/io/protocols.h
+new file mode 100644
+index 0000000..01fc8ae
+--- /dev/null
++++ b/include/xen/interface/io/protocols.h
+@@ -0,0 +1,21 @@
++#ifndef __XEN_PROTOCOLS_H__
++#define __XEN_PROTOCOLS_H__
++
++#define XEN_IO_PROTO_ABI_X86_32     "x86_32-abi"
++#define XEN_IO_PROTO_ABI_X86_64     "x86_64-abi"
++#define XEN_IO_PROTO_ABI_IA64       "ia64-abi"
++#define XEN_IO_PROTO_ABI_POWERPC64  "powerpc64-abi"
++
++#if defined(__i386__)
++# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
++#elif defined(__x86_64__)
++# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
++#elif defined(__ia64__)
++# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64
++#elif defined(__powerpc64__)
++# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64
++#else
++# error arch fixup needed here
++#endif
++
++#endif
+diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h
+index af36ead..da76846 100644
+--- a/include/xen/interface/memory.h
++++ b/include/xen/interface/memory.h
+@@ -29,7 +29,7 @@ struct xen_memory_reservation {
+      *   OUT: GMFN bases of extents that were allocated
+      *   (NB. This command also updates the mach_to_phys translation table)
+      */
+-    GUEST_HANDLE(ulong) extent_start;
++    ulong extent_start;
+ 
+     /* Number of extents, and size/alignment of each (2^extent_order pages). */
+     unsigned long  nr_extents;
+@@ -50,7 +50,6 @@ struct xen_memory_reservation {
+     domid_t        domid;
+ 
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation);
+ 
+ /*
+  * Returns the maximum machine frame number of mapped RAM in this system.
+@@ -86,7 +85,7 @@ struct xen_machphys_mfn_list {
+      * any large discontiguities in the machine address space, 2MB gaps in
+      * the machphys table will be represented by an MFN base of zero.
+      */
+-    GUEST_HANDLE(ulong) extent_start;
++    ulong extent_start;
+ 
+     /*
+      * Number of extents written to the above array. This will be smaller
+@@ -94,7 +93,6 @@ struct xen_machphys_mfn_list {
+      */
+     unsigned int nr_extents;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
+ 
+ /*
+  * Sets the GPFN at which a particular page appears in the specified guest's
+@@ -117,7 +115,6 @@ struct xen_add_to_physmap {
+     /* GPFN where the source mapping page should appear. */
+     unsigned long gpfn;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
+ 
+ /*
+  * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
+@@ -132,14 +129,13 @@ struct xen_translate_gpfn_list {
+     unsigned long nr_gpfns;
+ 
+     /* List of GPFNs to translate. */
+-    GUEST_HANDLE(ulong) gpfn_list;
++    ulong gpfn_list;
+ 
+     /*
+      * Output list to contain MFN translations. May be the same as the input
+      * list (in which case each input GPFN is overwritten with the output MFN).
+      */
+-    GUEST_HANDLE(ulong) mfn_list;
++    ulong mfn_list;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
+ 
+ #endif /* __XEN_PUBLIC_MEMORY_H__ */
+diff --git a/include/xen/interface/vcpu.h b/include/xen/interface/vcpu.h
+index b05d8a6..87e6f8a 100644
+--- a/include/xen/interface/vcpu.h
++++ b/include/xen/interface/vcpu.h
+@@ -85,6 +85,7 @@ struct vcpu_runstate_info {
+ 		 */
+ 		uint64_t time[4];
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_runstate_info);
+ 
+ /* VCPU is currently running on a physical CPU. */
+ #define RUNSTATE_running  0
+@@ -119,6 +120,7 @@ struct vcpu_runstate_info {
+ #define VCPUOP_register_runstate_memory_area 5
+ struct vcpu_register_runstate_memory_area {
+ 		union {
++				GUEST_HANDLE(vcpu_runstate_info) h;
+ 				struct vcpu_runstate_info *v;
+ 				uint64_t p;
+ 		} addr;
+@@ -134,6 +136,7 @@ struct vcpu_register_runstate_memory_area {
+ struct vcpu_set_periodic_timer {
+ 		uint64_t period_ns;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_periodic_timer);
+ 
+ /*
+  * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
+@@ -145,6 +148,7 @@ struct vcpu_set_singleshot_timer {
+ 		uint64_t timeout_abs_ns;
+ 		uint32_t flags;			   /* VCPU_SSHOTTMR_??? */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_singleshot_timer);
+ 
+ /* Flags to VCPUOP_set_singleshot_timer. */
+  /* Require the timeout to be in the future (return -ETIME if it's passed). */
+@@ -164,5 +168,6 @@ struct vcpu_register_vcpu_info {
+     uint32_t offset; /* offset within page */
+     uint32_t rsvd;   /* unused */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info);
+ 
+ #endif /* __XEN_PUBLIC_VCPU_H__ */
+diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
+index 518a5bf..9b018da 100644
+--- a/include/xen/interface/xen.h
++++ b/include/xen/interface/xen.h
+@@ -58,6 +58,16 @@
+ #define __HYPERVISOR_physdev_op           33
+ #define __HYPERVISOR_hvm_op               34
+ 
++/* Architecture-specific hypercall definitions. */
++#define __HYPERVISOR_arch_0               48
++#define __HYPERVISOR_arch_1               49
++#define __HYPERVISOR_arch_2               50
++#define __HYPERVISOR_arch_3               51
++#define __HYPERVISOR_arch_4               52
++#define __HYPERVISOR_arch_5               53
++#define __HYPERVISOR_arch_6               54
++#define __HYPERVISOR_arch_7               55
++
+ /*
+  * VIRTUAL INTERRUPTS
+  *
+@@ -68,8 +78,18 @@
+ #define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
+ #define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
+ #define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
+-#define NR_VIRQS        8
+ 
++/* Architecture-specific VIRQ definitions. */
++#define VIRQ_ARCH_0    16
++#define VIRQ_ARCH_1    17
++#define VIRQ_ARCH_2    18
++#define VIRQ_ARCH_3    19
++#define VIRQ_ARCH_4    20
++#define VIRQ_ARCH_5    21
++#define VIRQ_ARCH_6    22
++#define VIRQ_ARCH_7    23
++
++#define NR_VIRQS       24
+ /*
+  * MMU-UPDATE REQUESTS
+  *
+diff --git a/include/xen/interface/xencomm.h b/include/xen/interface/xencomm.h
+new file mode 100644
+index 0000000..ac45e07
+--- /dev/null
++++ b/include/xen/interface/xencomm.h
+@@ -0,0 +1,41 @@
++/*
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * 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.
++ *
++ * Copyright (C) IBM Corp. 2006
++ */
++
++#ifndef _XEN_XENCOMM_H_
++#define _XEN_XENCOMM_H_
++
++/* A xencomm descriptor is a scatter/gather list containing physical
++ * addresses corresponding to a virtually contiguous memory area. The
++ * hypervisor translates these physical addresses to machine addresses to copy
++ * to and from the virtually contiguous area.
++ */
++
++#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */
++#define XENCOMM_INVALID (~0UL)
++
++struct xencomm_desc {
++    uint32_t magic;
++    uint32_t nr_addrs; /* the number of entries in address[] */
++    uint64_t address[0];
++};
++
++#endif /* _XEN_XENCOMM_H_ */
+diff --git a/include/xen/page.h b/include/xen/page.h
+index 031ef22..eaf85fa 100644
+--- a/include/xen/page.h
++++ b/include/xen/page.h
+@@ -1,180 +1 @@
+-#ifndef __XEN_PAGE_H
+-#define __XEN_PAGE_H
+-
+-#include <linux/pfn.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/pgtable.h>
+-
+-#include <xen/features.h>
+-
+-#ifdef CONFIG_X86_PAE
+-/* Xen machine address */
+-typedef struct xmaddr {
+-	unsigned long long maddr;
+-} xmaddr_t;
+-
+-/* Xen pseudo-physical address */
+-typedef struct xpaddr {
+-	unsigned long long paddr;
+-} xpaddr_t;
+-#else
+-/* Xen machine address */
+-typedef struct xmaddr {
+-	unsigned long maddr;
+-} xmaddr_t;
+-
+-/* Xen pseudo-physical address */
+-typedef struct xpaddr {
+-	unsigned long paddr;
+-} xpaddr_t;
+-#endif
+-
+-#define XMADDR(x)	((xmaddr_t) { .maddr = (x) })
+-#define XPADDR(x)	((xpaddr_t) { .paddr = (x) })
+-
+-/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
+-#define INVALID_P2M_ENTRY	(~0UL)
+-#define FOREIGN_FRAME_BIT	(1UL<<31)
+-#define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
+-
+-extern unsigned long *phys_to_machine_mapping;
+-
+-static inline unsigned long pfn_to_mfn(unsigned long pfn)
+-{
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
+-		return pfn;
+-
+-	return phys_to_machine_mapping[(unsigned int)(pfn)] &
+-		~FOREIGN_FRAME_BIT;
+-}
+-
+-static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+-{
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
+-		return 1;
+-
+-	return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+-}
+-
+-static inline unsigned long mfn_to_pfn(unsigned long mfn)
+-{
+-	unsigned long pfn;
+-
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
+-		return mfn;
+-
+-#if 0
+-	if (unlikely((mfn >> machine_to_phys_order) != 0))
+-		return max_mapnr;
+-#endif
+-
+-	pfn = 0;
+-	/*
+-	 * The array access can fail (e.g., device space beyond end of RAM).
+-	 * In such cases it doesn't matter what we return (we return garbage),
+-	 * but we must handle the fault without crashing!
+-	 */
+-	__get_user(pfn, &machine_to_phys_mapping[mfn]);
+-
+-	return pfn;
+-}
+-
+-static inline xmaddr_t phys_to_machine(xpaddr_t phys)
+-{
+-	unsigned offset = phys.paddr & ~PAGE_MASK;
+-	return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
+-}
+-
+-static inline xpaddr_t machine_to_phys(xmaddr_t machine)
+-{
+-	unsigned offset = machine.maddr & ~PAGE_MASK;
+-	return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
+-}
+-
+-/*
+- * We detect special mappings in one of two ways:
+- *  1. If the MFN is an I/O page then Xen will set the m2p entry
+- *     to be outside our maximum possible pseudophys range.
+- *  2. If the MFN belongs to a different domain then we will certainly
+- *     not have MFN in our p2m table. Conversely, if the page is ours,
+- *     then we'll have p2m(m2p(MFN))==MFN.
+- * If we detect a special mapping then it doesn't have a 'struct page'.
+- * We force !pfn_valid() by returning an out-of-range pointer.
+- *
+- * NB. These checks require that, for any MFN that is not in our reservation,
+- * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+- * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+- * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+- *
+- * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+- *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+- *      require. In all the cases we care about, the FOREIGN_FRAME bit is
+- *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
+- */
+-static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+-{
+-	extern unsigned long max_mapnr;
+-	unsigned long pfn = mfn_to_pfn(mfn);
+-	if ((pfn < max_mapnr)
+-	    && !xen_feature(XENFEAT_auto_translated_physmap)
+-	    && (phys_to_machine_mapping[pfn] != mfn))
+-		return max_mapnr; /* force !pfn_valid() */
+-	return pfn;
+-}
+-
+-static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+-{
+-	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+-		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+-		return;
+-	}
+-	phys_to_machine_mapping[pfn] = mfn;
+-}
+-
+-/* VIRT <-> MACHINE conversion */
+-#define virt_to_machine(v)	(phys_to_machine(XPADDR(__pa(v))))
+-#define virt_to_mfn(v)		(pfn_to_mfn(PFN_DOWN(__pa(v))))
+-#define mfn_to_virt(m)		(__va(mfn_to_pfn(m) << PAGE_SHIFT))
+-
+-#ifdef CONFIG_X86_PAE
+-#define pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) |			\
+-		       (((_pte).pte_high & 0xfff) << (32-PAGE_SHIFT)))
+-
+-static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
+-{
+-	pte_t pte;
+-
+-	pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) |
+-		(pgprot_val(pgprot) >> 32);
+-	pte.pte_high &= (__supported_pte_mask >> 32);
+-	pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot));
+-	pte.pte_low &= __supported_pte_mask;
+-
+-	return pte;
+-}
+-
+-static inline unsigned long long pte_val_ma(pte_t x)
+-{
+-	return x.pte;
+-}
+-#define pmd_val_ma(v) ((v).pmd)
+-#define pud_val_ma(v) ((v).pgd.pgd)
+-#define __pte_ma(x)	((pte_t) { .pte = (x) })
+-#define __pmd_ma(x)	((pmd_t) { (x) } )
+-#else  /* !X86_PAE */
+-#define pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
+-#define mfn_pte(pfn, prot)	__pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+-#define pte_val_ma(x)	((x).pte)
+-#define pmd_val_ma(v)	((v).pud.pgd.pgd)
+-#define __pte_ma(x)	((pte_t) { (x) } )
+-#endif	/* CONFIG_X86_PAE */
+-
+-#define pgd_val_ma(x)	((x).pgd)
+-
+-
+-xmaddr_t arbitrary_virt_to_machine(unsigned long address);
+-void make_lowmem_page_readonly(void *vaddr);
+-void make_lowmem_page_readwrite(void *vaddr);
+-
+-#endif /* __XEN_PAGE_H */
++#include <asm/xen/page.h>
+diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
+new file mode 100644
+index 0000000..10ddfe0
+--- /dev/null
++++ b/include/xen/xen-ops.h
+@@ -0,0 +1,8 @@
++#ifndef INCLUDE_XEN_OPS_H
++#define INCLUDE_XEN_OPS_H
++
++#include <linux/percpu.h>
++
++DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
++
++#endif /* INCLUDE_XEN_OPS_H */
+diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
+index 6f7c290..6369d89 100644
+--- a/include/xen/xenbus.h
++++ b/include/xen/xenbus.h
+@@ -97,6 +97,7 @@ struct xenbus_driver {
+ 	int (*uevent)(struct xenbus_device *, char **, int, char *, int);
+ 	struct device_driver driver;
+ 	int (*read_otherend_details)(struct xenbus_device *dev);
++	int (*is_ready)(struct xenbus_device *dev);
+ };
+ 
+ static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv)
+diff --git a/include/xen/xencomm.h b/include/xen/xencomm.h
+new file mode 100644
+index 0000000..e43b039
+--- /dev/null
++++ b/include/xen/xencomm.h
+@@ -0,0 +1,77 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public 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 Corp. 2006
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ *          Jerone Young <jyoung5 at us.ibm.com>
++ */
++
++#ifndef _LINUX_XENCOMM_H_
++#define _LINUX_XENCOMM_H_
++
++#include <xen/interface/xencomm.h>
++
++#define XENCOMM_MINI_ADDRS 3
++struct xencomm_mini {
++	struct xencomm_desc _desc;
++	uint64_t address[XENCOMM_MINI_ADDRS];
++};
++
++/* To avoid additionnal virt to phys conversion, an opaque structure is
++   presented.  */
++struct xencomm_handle;
++
++extern void xencomm_free(struct xencomm_handle *desc);
++extern struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes);
++extern struct xencomm_handle *__xencomm_map_no_alloc(void *ptr,
++			unsigned long bytes,  struct xencomm_mini *xc_area);
++
++#if 0
++#define XENCOMM_MINI_ALIGNED(xc_desc, n)				\
++	struct xencomm_mini xc_desc ## _base[(n)]			\
++	__attribute__((__aligned__(sizeof(struct xencomm_mini))));	\
++	struct xencomm_mini *xc_desc = &xc_desc ## _base[0];
++#else
++/*
++ * gcc bug workaround:
++ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660
++ * gcc doesn't handle properly stack variable with
++ * __attribute__((__align__(sizeof(struct xencomm_mini))))
++ */
++#define XENCOMM_MINI_ALIGNED(xc_desc, n)				\
++	unsigned char xc_desc ## _base[((n) + 1 ) *			\
++				       sizeof(struct xencomm_mini)];	\
++	struct xencomm_mini *xc_desc = (struct xencomm_mini *)		\
++		((unsigned long)xc_desc ## _base +			\
++		 (sizeof(struct xencomm_mini) -				\
++		  ((unsigned long)xc_desc ## _base) %			\
++		  sizeof(struct xencomm_mini)));
++#endif
++#define xencomm_map_no_alloc(ptr, bytes)			\
++	({ XENCOMM_MINI_ALIGNED(xc_desc, 1);			\
++		__xencomm_map_no_alloc(ptr, bytes, xc_desc); })
++
++/* provided by architecture code: */
++extern unsigned long xencomm_vtop(unsigned long vaddr);
++
++static inline void *xencomm_pa(void *ptr)
++{
++	return (void *)xencomm_vtop((unsigned long)ptr);
++}
++
++#define xen_guest_handle(hnd)  ((hnd).p)
++
++#endif /* _LINUX_XENCOMM_H_ */
+diff --git a/init/Kconfig b/init/Kconfig
+index a97924b..ba3a389 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -328,6 +328,13 @@ config RT_GROUP_SCHED
+ 	depends on EXPERIMENTAL
+ 	depends on GROUP_SCHED
+ 	default n
++	help
++	  This feature lets you explicitly allocate real CPU bandwidth
++	  to users or control groups (depending on the "Basis for grouping tasks"
++	  setting below. If enabled, it will also make it impossible to
++	  schedule realtime tasks for non-root users until you allocate
++	  realtime bandwidth for them.
++	  See Documentation/sched-rt-group.txt for more information.
+ 
+ choice
+ 	depends on GROUP_SCHED
+@@ -763,7 +770,7 @@ endmenu		# General setup
+ config SLABINFO
+ 	bool
+ 	depends on PROC_FS
+-	depends on SLAB || SLUB
++	depends on SLAB || SLUB_DEBUG
+ 	default y
+ 
+ config RT_MUTEXES
+diff --git a/init/main.c b/init/main.c
+index 99ce949..1687b01 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -359,10 +359,31 @@ static void __init smp_init(void)
+ #endif
+ 
+ static inline void setup_per_cpu_areas(void) { }
++static inline void setup_nr_cpu_ids(void) { }
+ static inline void smp_prepare_cpus(unsigned int maxcpus) { }
+ 
+ #else
+ 
++#if NR_CPUS > BITS_PER_LONG
++cpumask_t cpu_mask_all __read_mostly = CPU_MASK_ALL;
++EXPORT_SYMBOL(cpu_mask_all);
++#endif
++
++/* Setup number of possible processor ids */
++int nr_cpu_ids __read_mostly = NR_CPUS;
++EXPORT_SYMBOL(nr_cpu_ids);
++
++/* An arch may set nr_cpu_ids earlier if needed, so this would be redundant */
++static void __init setup_nr_cpu_ids(void)
++{
++	int cpu, highest_cpu = 0;
++
++	for_each_possible_cpu(cpu)
++		highest_cpu = cpu;
++
++	nr_cpu_ids = highest_cpu + 1;
++}
++
+ #ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
+ unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
+ 
+@@ -500,7 +521,11 @@ static void __init boot_cpu_init(void)
+ 	cpu_set(cpu, cpu_possible_map);
+ }
+ 
+-void __init __attribute__((weak)) smp_setup_processor_id(void)
++void __init __weak smp_setup_processor_id(void)
++{
++}
++
++void __init __weak thread_info_cache_init(void)
+ {
+ }
+ 
+@@ -537,6 +562,7 @@ asmlinkage void __init start_kernel(void)
+ 	setup_command_line(command_line);
+ 	unwind_setup();
+ 	setup_per_cpu_areas();
++	setup_nr_cpu_ids();
+ 	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
+ 
+ 	/*
+@@ -623,6 +649,7 @@ asmlinkage void __init start_kernel(void)
+ 	if (efi_enabled)
+ 		efi_enter_virtual_mode();
+ #endif
++	thread_info_cache_init();
+ 	fork_init(num_physpages);
+ 	proc_caches_init();
+ 	buffer_init();
+@@ -811,7 +838,7 @@ static int __init kernel_init(void * unused)
+ 	/*
+ 	 * init can run on any cpu.
+ 	 */
+-	set_cpus_allowed(current, CPU_MASK_ALL);
++	set_cpus_allowed_ptr(current, CPU_MASK_ALL_PTR);
+ 	/*
+ 	 * Tell the world that we're going to be the grim
+ 	 * reaper of innocent orphaned children.
+diff --git a/ipc/mqueue.c b/ipc/mqueue.c
+index 60f7a27..94fd3b0 100644
+--- a/ipc/mqueue.c
++++ b/ipc/mqueue.c
+@@ -598,6 +598,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
+ 			int oflag, mode_t mode, struct mq_attr __user *u_attr)
+ {
+ 	struct mq_attr attr;
++	struct file *result;
+ 	int ret;
+ 
+ 	if (u_attr) {
+@@ -612,13 +613,24 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
+ 	}
+ 
+ 	mode &= ~current->fs->umask;
++	ret = mnt_want_write(mqueue_mnt);
++	if (ret)
++		goto out;
+ 	ret = vfs_create(dir->d_inode, dentry, mode, NULL);
+ 	dentry->d_fsdata = NULL;
+ 	if (ret)
+-		goto out;
+-
+-	return dentry_open(dentry, mqueue_mnt, oflag);
+-
++		goto out_drop_write;
++
++	result = dentry_open(dentry, mqueue_mnt, oflag);
++	/*
++	 * dentry_open() took a persistent mnt_want_write(),
++	 * so we can now drop this one.
++	 */
++	mnt_drop_write(mqueue_mnt);
++	return result;
++
++out_drop_write:
++	mnt_drop_write(mqueue_mnt);
+ out:
+ 	dput(dentry);
+ 	mntput(mqueue_mnt);
+@@ -742,8 +754,11 @@ asmlinkage long sys_mq_unlink(const char __user *u_name)
+ 	inode = dentry->d_inode;
+ 	if (inode)
+ 		atomic_inc(&inode->i_count);
+-
++	err = mnt_want_write(mqueue_mnt);
++	if (err)
++		goto out_err;
+ 	err = vfs_unlink(dentry->d_parent->d_inode, dentry);
++	mnt_drop_write(mqueue_mnt);
+ out_err:
+ 	dput(dentry);
+ 
+diff --git a/kernel/Makefile b/kernel/Makefile
+index 6c584c5..6c5f081 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -8,7 +8,7 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
+ 	    signal.o sys.o kmod.o workqueue.o pid.o \
+ 	    rcupdate.o extable.o params.o posix-timers.o \
+ 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
+-	    hrtimer.o rwsem.o nsproxy.o srcu.o \
++	    hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
+ 	    notifier.o ksysfs.o pm_qos_params.o
+ 
+ obj-$(CONFIG_SYSCTL) += sysctl_check.o
+@@ -53,6 +53,7 @@ obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
+ obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
+ obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
++obj-$(CONFIG_KGDB) += kgdb.o
+ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
+ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
+ obj-$(CONFIG_SECCOMP) += seccomp.o
+diff --git a/kernel/audit.c b/kernel/audit.c
+index b782b04..a7b1608 100644
+--- a/kernel/audit.c
++++ b/kernel/audit.c
+@@ -21,7 +21,7 @@
+  *
+  * Written by Rickard E. (Rik) Faith <faith at redhat.com>
+  *
+- * Goals: 1) Integrate fully with SELinux.
++ * Goals: 1) Integrate fully with Security Modules.
+  *	  2) Minimal run-time overhead:
+  *	     a) Minimal when syscall auditing is disabled (audit_enable=0).
+  *	     b) Small when syscall auditing is enabled and no audit record
+@@ -55,7 +55,6 @@
+ #include <net/netlink.h>
+ #include <linux/skbuff.h>
+ #include <linux/netlink.h>
+-#include <linux/selinux.h>
+ #include <linux/inotify.h>
+ #include <linux/freezer.h>
+ #include <linux/tty.h>
+@@ -265,13 +264,13 @@ static int audit_log_config_change(char *function_name, int new, int old,
+ 		char *ctx = NULL;
+ 		u32 len;
+ 
+-		rc = selinux_sid_to_string(sid, &ctx, &len);
++		rc = security_secid_to_secctx(sid, &ctx, &len);
+ 		if (rc) {
+ 			audit_log_format(ab, " sid=%u", sid);
+ 			allow_changes = 0; /* Something weird, deny request */
+ 		} else {
+ 			audit_log_format(ab, " subj=%s", ctx);
+-			kfree(ctx);
++			security_release_secctx(ctx, len);
+ 		}
+ 	}
+ 	audit_log_format(ab, " res=%d", allow_changes);
+@@ -550,12 +549,13 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
+ 	audit_log_format(*ab, "user pid=%d uid=%u auid=%u",
+ 			 pid, uid, auid);
+ 	if (sid) {
+-		rc = selinux_sid_to_string(sid, &ctx, &len);
++		rc = security_secid_to_secctx(sid, &ctx, &len);
+ 		if (rc)
+ 			audit_log_format(*ab, " ssid=%u", sid);
+-		else
++		else {
+ 			audit_log_format(*ab, " subj=%s", ctx);
+-		kfree(ctx);
++			security_release_secctx(ctx, len);
++		}
+ 	}
+ 
+ 	return rc;
+@@ -758,18 +758,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		break;
+ 	}
+ 	case AUDIT_SIGNAL_INFO:
+-		err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
++		err = security_secid_to_secctx(audit_sig_sid, &ctx, &len);
+ 		if (err)
+ 			return err;
+ 		sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
+ 		if (!sig_data) {
+-			kfree(ctx);
++			security_release_secctx(ctx, len);
+ 			return -ENOMEM;
+ 		}
+ 		sig_data->uid = audit_sig_uid;
+ 		sig_data->pid = audit_sig_pid;
+ 		memcpy(sig_data->ctx, ctx, len);
+-		kfree(ctx);
++		security_release_secctx(ctx, len);
+ 		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,
+ 				0, 0, sig_data, sizeof(*sig_data) + len);
+ 		kfree(sig_data);
+@@ -881,10 +881,6 @@ static int __init audit_init(void)
+ 	audit_enabled = audit_default;
+ 	audit_ever_enabled |= !!audit_default;
+ 
+-	/* Register the callback with selinux.  This callback will be invoked
+-	 * when a new policy is loaded. */
+-	selinux_audit_set_callback(&selinux_audit_rule_update);
+-
+ 	audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
+ 
+ #ifdef CONFIG_AUDITSYSCALL
+diff --git a/kernel/audit.h b/kernel/audit.h
+index 2554bd5..3cfc54e 100644
+--- a/kernel/audit.h
++++ b/kernel/audit.h
+@@ -65,34 +65,9 @@ struct audit_watch {
+ 	struct list_head	rules;	/* associated rules */
+ };
+ 
+-struct audit_field {
+-	u32				type;
+-	u32				val;
+-	u32				op;
+-	char				*se_str;
+-	struct selinux_audit_rule	*se_rule;
+-};
+-
+ struct audit_tree;
+ struct audit_chunk;
+ 
+-struct audit_krule {
+-	int			vers_ops;
+-	u32			flags;
+-	u32			listnr;
+-	u32			action;
+-	u32			mask[AUDIT_BITMASK_SIZE];
+-	u32			buflen; /* for data alloc on list rules */
+-	u32			field_count;
+-	char			*filterkey; /* ties events to rules */
+-	struct audit_field	*fields;
+-	struct audit_field	*arch_f; /* quick access to arch field */
+-	struct audit_field	*inode_f; /* quick access to an inode field */
+-	struct audit_watch	*watch;	/* associated watch */
+-	struct audit_tree	*tree;	/* associated watched tree */
+-	struct list_head	rlist;	/* entry in audit_{watch,tree}.rules list */
+-};
+-
+ struct audit_entry {
+ 	struct list_head	list;
+ 	struct rcu_head		rcu;
+diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
+index 2f2914b..28fef6b 100644
+--- a/kernel/auditfilter.c
++++ b/kernel/auditfilter.c
+@@ -28,7 +28,7 @@
+ #include <linux/netlink.h>
+ #include <linux/sched.h>
+ #include <linux/inotify.h>
+-#include <linux/selinux.h>
++#include <linux/security.h>
+ #include "audit.h"
+ 
+ /*
+@@ -38,7 +38,7 @@
+  * 		Synchronizes writes and blocking reads of audit's filterlist
+  * 		data.  Rcu is used to traverse the filterlist and access
+  * 		contents of structs audit_entry, audit_watch and opaque
+- * 		selinux rules during filtering.  If modified, these structures
++ * 		LSM rules during filtering.  If modified, these structures
+  * 		must be copied and replace their counterparts in the filterlist.
+  * 		An audit_parent struct is not accessed during filtering, so may
+  * 		be written directly provided audit_filter_mutex is held.
+@@ -139,8 +139,8 @@ static inline void audit_free_rule(struct audit_entry *e)
+ 	if (e->rule.fields)
+ 		for (i = 0; i < e->rule.field_count; i++) {
+ 			struct audit_field *f = &e->rule.fields[i];
+-			kfree(f->se_str);
+-			selinux_audit_rule_free(f->se_rule);
++			kfree(f->lsm_str);
++			security_audit_rule_free(f->lsm_rule);
+ 		}
+ 	kfree(e->rule.fields);
+ 	kfree(e->rule.filterkey);
+@@ -554,8 +554,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ 		f->op = data->fieldflags[i] & AUDIT_OPERATORS;
+ 		f->type = data->fields[i];
+ 		f->val = data->values[i];
+-		f->se_str = NULL;
+-		f->se_rule = NULL;
++		f->lsm_str = NULL;
++		f->lsm_rule = NULL;
+ 		switch(f->type) {
+ 		case AUDIT_PID:
+ 		case AUDIT_UID:
+@@ -597,12 +597,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ 				goto exit_free;
+ 			entry->rule.buflen += f->val;
+ 
+-			err = selinux_audit_rule_init(f->type, f->op, str,
+-						      &f->se_rule);
++			err = security_audit_rule_init(f->type, f->op, str,
++						       (void **)&f->lsm_rule);
+ 			/* Keep currently invalid fields around in case they
+ 			 * become valid after a policy reload. */
+ 			if (err == -EINVAL) {
+-				printk(KERN_WARNING "audit rule for selinux "
++				printk(KERN_WARNING "audit rule for LSM "
+ 				       "\'%s\' is invalid\n",  str);
+ 				err = 0;
+ 			}
+@@ -610,7 +610,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ 				kfree(str);
+ 				goto exit_free;
+ 			} else
+-				f->se_str = str;
++				f->lsm_str = str;
+ 			break;
+ 		case AUDIT_WATCH:
+ 			str = audit_unpack_string(&bufp, &remain, f->val);
+@@ -754,7 +754,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
+ 		case AUDIT_OBJ_LEV_LOW:
+ 		case AUDIT_OBJ_LEV_HIGH:
+ 			data->buflen += data->values[i] =
+-				audit_pack_string(&bufp, f->se_str);
++				audit_pack_string(&bufp, f->lsm_str);
+ 			break;
+ 		case AUDIT_WATCH:
+ 			data->buflen += data->values[i] =
+@@ -806,7 +806,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
+ 		case AUDIT_OBJ_TYPE:
+ 		case AUDIT_OBJ_LEV_LOW:
+ 		case AUDIT_OBJ_LEV_HIGH:
+-			if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
++			if (strcmp(a->fields[i].lsm_str, b->fields[i].lsm_str))
+ 				return 1;
+ 			break;
+ 		case AUDIT_WATCH:
+@@ -862,28 +862,28 @@ out:
+ 	return new;
+ }
+ 
+-/* Duplicate selinux field information.  The se_rule is opaque, so must be
++/* Duplicate LSM field information.  The lsm_rule is opaque, so must be
+  * re-initialized. */
+-static inline int audit_dupe_selinux_field(struct audit_field *df,
++static inline int audit_dupe_lsm_field(struct audit_field *df,
+ 					   struct audit_field *sf)
+ {
+ 	int ret = 0;
+-	char *se_str;
++	char *lsm_str;
+ 
+-	/* our own copy of se_str */
+-	se_str = kstrdup(sf->se_str, GFP_KERNEL);
+-	if (unlikely(!se_str))
++	/* our own copy of lsm_str */
++	lsm_str = kstrdup(sf->lsm_str, GFP_KERNEL);
++	if (unlikely(!lsm_str))
+ 		return -ENOMEM;
+-	df->se_str = se_str;
++	df->lsm_str = lsm_str;
+ 
+-	/* our own (refreshed) copy of se_rule */
+-	ret = selinux_audit_rule_init(df->type, df->op, df->se_str,
+-				      &df->se_rule);
++	/* our own (refreshed) copy of lsm_rule */
++	ret = security_audit_rule_init(df->type, df->op, df->lsm_str,
++				       (void **)&df->lsm_rule);
+ 	/* Keep currently invalid fields around in case they
+ 	 * become valid after a policy reload. */
+ 	if (ret == -EINVAL) {
+-		printk(KERN_WARNING "audit rule for selinux \'%s\' is "
+-		       "invalid\n", df->se_str);
++		printk(KERN_WARNING "audit rule for LSM \'%s\' is "
++		       "invalid\n", df->lsm_str);
+ 		ret = 0;
+ 	}
+ 
+@@ -891,7 +891,7 @@ static inline int audit_dupe_selinux_field(struct audit_field *df,
+ }
+ 
+ /* Duplicate an audit rule.  This will be a deep copy with the exception
+- * of the watch - that pointer is carried over.  The selinux specific fields
++ * of the watch - that pointer is carried over.  The LSM specific fields
+  * will be updated in the copy.  The point is to be able to replace the old
+  * rule with the new rule in the filterlist, then free the old rule.
+  * The rlist element is undefined; list manipulations are handled apart from
+@@ -930,7 +930,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
+ 	new->tree = old->tree;
+ 	memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
+ 
+-	/* deep copy this information, updating the se_rule fields, because
++	/* deep copy this information, updating the lsm_rule fields, because
+ 	 * the originals will all be freed when the old rule is freed. */
+ 	for (i = 0; i < fcount; i++) {
+ 		switch (new->fields[i].type) {
+@@ -944,7 +944,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
+ 		case AUDIT_OBJ_TYPE:
+ 		case AUDIT_OBJ_LEV_LOW:
+ 		case AUDIT_OBJ_LEV_HIGH:
+-			err = audit_dupe_selinux_field(&new->fields[i],
++			err = audit_dupe_lsm_field(&new->fields[i],
+ 						       &old->fields[i]);
+ 			break;
+ 		case AUDIT_FILTERKEY:
+@@ -1515,11 +1515,12 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
+ 	if (sid) {
+ 		char *ctx = NULL;
+ 		u32 len;
+-		if (selinux_sid_to_string(sid, &ctx, &len))
++		if (security_secid_to_secctx(sid, &ctx, &len))
+ 			audit_log_format(ab, " ssid=%u", sid);
+-		else
++		else {
+ 			audit_log_format(ab, " subj=%s", ctx);
+-		kfree(ctx);
++			security_release_secctx(ctx, len);
++		}
+ 	}
+ 	audit_log_format(ab, " op=%s rule key=", action);
+ 	if (rule->filterkey)
+@@ -1761,38 +1762,12 @@ unlock_and_return:
+ 	return result;
+ }
+ 
+-/* Check to see if the rule contains any selinux fields.  Returns 1 if there
+-   are selinux fields specified in the rule, 0 otherwise. */
+-static inline int audit_rule_has_selinux(struct audit_krule *rule)
+-{
+-	int i;
+-
+-	for (i = 0; i < rule->field_count; i++) {
+-		struct audit_field *f = &rule->fields[i];
+-		switch (f->type) {
+-		case AUDIT_SUBJ_USER:
+-		case AUDIT_SUBJ_ROLE:
+-		case AUDIT_SUBJ_TYPE:
+-		case AUDIT_SUBJ_SEN:
+-		case AUDIT_SUBJ_CLR:
+-		case AUDIT_OBJ_USER:
+-		case AUDIT_OBJ_ROLE:
+-		case AUDIT_OBJ_TYPE:
+-		case AUDIT_OBJ_LEV_LOW:
+-		case AUDIT_OBJ_LEV_HIGH:
+-			return 1;
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-/* This function will re-initialize the se_rule field of all applicable rules.
+- * It will traverse the filter lists serarching for rules that contain selinux
++/* This function will re-initialize the lsm_rule field of all applicable rules.
++ * It will traverse the filter lists serarching for rules that contain LSM
+  * specific filter fields.  When such a rule is found, it is copied, the
+- * selinux field is re-initialized, and the old rule is replaced with the
++ * LSM field is re-initialized, and the old rule is replaced with the
+  * updated rule. */
+-int selinux_audit_rule_update(void)
++int audit_update_lsm_rules(void)
+ {
+ 	struct audit_entry *entry, *n, *nentry;
+ 	struct audit_watch *watch;
+@@ -1804,7 +1779,7 @@ int selinux_audit_rule_update(void)
+ 
+ 	for (i = 0; i < AUDIT_NR_FILTERS; i++) {
+ 		list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
+-			if (!audit_rule_has_selinux(&entry->rule))
++			if (!security_audit_rule_known(&entry->rule))
+ 				continue;
+ 
+ 			watch = entry->rule.watch;
+@@ -1815,7 +1790,7 @@ int selinux_audit_rule_update(void)
+ 				 * return value */
+ 				if (!err)
+ 					err = PTR_ERR(nentry);
+-				audit_panic("error updating selinux filters");
++				audit_panic("error updating LSM filters");
+ 				if (watch)
+ 					list_del(&entry->rule.rlist);
+ 				list_del_rcu(&entry->list);
+diff --git a/kernel/auditsc.c b/kernel/auditsc.c
+index 782262e..56e56ed 100644
+--- a/kernel/auditsc.c
++++ b/kernel/auditsc.c
+@@ -61,7 +61,6 @@
+ #include <linux/security.h>
+ #include <linux/list.h>
+ #include <linux/tty.h>
+-#include <linux/selinux.h>
+ #include <linux/binfmts.h>
+ #include <linux/highmem.h>
+ #include <linux/syscalls.h>
+@@ -528,14 +527,14 @@ static int audit_filter_rules(struct task_struct *tsk,
+ 			   match for now to avoid losing information that
+ 			   may be wanted.   An error message will also be
+ 			   logged upon error */
+-			if (f->se_rule) {
++			if (f->lsm_rule) {
+ 				if (need_sid) {
+-					selinux_get_task_sid(tsk, &sid);
++					security_task_getsecid(tsk, &sid);
+ 					need_sid = 0;
+ 				}
+-				result = selinux_audit_rule_match(sid, f->type,
++				result = security_audit_rule_match(sid, f->type,
+ 				                                  f->op,
+-				                                  f->se_rule,
++				                                  f->lsm_rule,
+ 				                                  ctx);
+ 			}
+ 			break;
+@@ -546,18 +545,18 @@ static int audit_filter_rules(struct task_struct *tsk,
+ 		case AUDIT_OBJ_LEV_HIGH:
+ 			/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
+ 			   also applies here */
+-			if (f->se_rule) {
++			if (f->lsm_rule) {
+ 				/* Find files that match */
+ 				if (name) {
+-					result = selinux_audit_rule_match(
++					result = security_audit_rule_match(
+ 					           name->osid, f->type, f->op,
+-					           f->se_rule, ctx);
++					           f->lsm_rule, ctx);
+ 				} else if (ctx) {
+ 					for (j = 0; j < ctx->name_count; j++) {
+-						if (selinux_audit_rule_match(
++						if (security_audit_rule_match(
+ 						      ctx->names[j].osid,
+ 						      f->type, f->op,
+-						      f->se_rule, ctx)) {
++						      f->lsm_rule, ctx)) {
+ 							++result;
+ 							break;
+ 						}
+@@ -570,7 +569,7 @@ static int audit_filter_rules(struct task_struct *tsk,
+ 					     aux = aux->next) {
+ 						if (aux->type == AUDIT_IPC) {
+ 							struct audit_aux_data_ipcctl *axi = (void *)aux;
+-							if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) {
++							if (security_audit_rule_match(axi->osid, f->type, f->op, f->lsm_rule, ctx)) {
+ 								++result;
+ 								break;
+ 							}
+@@ -885,11 +884,11 @@ void audit_log_task_context(struct audit_buffer *ab)
+ 	int error;
+ 	u32 sid;
+ 
+-	selinux_get_task_sid(current, &sid);
++	security_task_getsecid(current, &sid);
+ 	if (!sid)
+ 		return;
+ 
+-	error = selinux_sid_to_string(sid, &ctx, &len);
++	error = security_secid_to_secctx(sid, &ctx, &len);
+ 	if (error) {
+ 		if (error != -EINVAL)
+ 			goto error_path;
+@@ -897,7 +896,7 @@ void audit_log_task_context(struct audit_buffer *ab)
+ 	}
+ 
+ 	audit_log_format(ab, " subj=%s", ctx);
+-	kfree(ctx);
++	security_release_secctx(ctx, len);
+ 	return;
+ 
+ error_path:
+@@ -941,7 +940,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+ 				 u32 sid, char *comm)
+ {
+ 	struct audit_buffer *ab;
+-	char *s = NULL;
++	char *ctx = NULL;
+ 	u32 len;
+ 	int rc = 0;
+ 
+@@ -951,15 +950,16 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+ 
+ 	audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, auid,
+ 			 uid, sessionid);
+-	if (selinux_sid_to_string(sid, &s, &len)) {
++	if (security_secid_to_secctx(sid, &ctx, &len)) {
+ 		audit_log_format(ab, " obj=(none)");
+ 		rc = 1;
+-	} else
+-		audit_log_format(ab, " obj=%s", s);
++	} else {
++		audit_log_format(ab, " obj=%s", ctx);
++		security_release_secctx(ctx, len);
++	}
+ 	audit_log_format(ab, " ocomm=");
+ 	audit_log_untrustedstring(ab, comm);
+ 	audit_log_end(ab);
+-	kfree(s);
+ 
+ 	return rc;
+ }
+@@ -1271,14 +1271,15 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+ 			if (axi->osid != 0) {
+ 				char *ctx = NULL;
+ 				u32 len;
+-				if (selinux_sid_to_string(
++				if (security_secid_to_secctx(
+ 						axi->osid, &ctx, &len)) {
+ 					audit_log_format(ab, " osid=%u",
+ 							axi->osid);
+ 					call_panic = 1;
+-				} else
++				} else {
+ 					audit_log_format(ab, " obj=%s", ctx);
+-				kfree(ctx);
++					security_release_secctx(ctx, len);
++				}
+ 			}
+ 			break; }
+ 
+@@ -1392,13 +1393,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+ 		if (n->osid != 0) {
+ 			char *ctx = NULL;
+ 			u32 len;
+-			if (selinux_sid_to_string(
++			if (security_secid_to_secctx(
+ 				n->osid, &ctx, &len)) {
+ 				audit_log_format(ab, " osid=%u", n->osid);
+ 				call_panic = 2;
+-			} else
++			} else {
+ 				audit_log_format(ab, " obj=%s", ctx);
+-			kfree(ctx);
++				security_release_secctx(ctx, len);
++			}
+ 		}
+ 
+ 		audit_log_end(ab);
+@@ -1775,7 +1777,7 @@ static void audit_copy_inode(struct audit_names *name, const struct inode *inode
+ 	name->uid   = inode->i_uid;
+ 	name->gid   = inode->i_gid;
+ 	name->rdev  = inode->i_rdev;
+-	selinux_get_inode_sid(inode, &name->osid);
++	security_inode_getsecid(inode, &name->osid);
+ }
+ 
+ /**
+@@ -2190,8 +2192,7 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
+ 	ax->uid = ipcp->uid;
+ 	ax->gid = ipcp->gid;
+ 	ax->mode = ipcp->mode;
+-	selinux_get_ipc_sid(ipcp, &ax->osid);
+-
++	security_ipc_getsecid(ipcp, &ax->osid);
+ 	ax->d.type = AUDIT_IPC;
+ 	ax->d.next = context->aux;
+ 	context->aux = (void *)ax;
+@@ -2343,7 +2344,7 @@ void __audit_ptrace(struct task_struct *t)
+ 	context->target_auid = audit_get_loginuid(t);
+ 	context->target_uid = t->uid;
+ 	context->target_sessionid = audit_get_sessionid(t);
+-	selinux_get_task_sid(t, &context->target_sid);
++	security_task_getsecid(t, &context->target_sid);
+ 	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
+ }
+ 
+@@ -2371,7 +2372,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
+ 				audit_sig_uid = tsk->loginuid;
+ 			else
+ 				audit_sig_uid = tsk->uid;
+-			selinux_get_task_sid(tsk, &audit_sig_sid);
++			security_task_getsecid(tsk, &audit_sig_sid);
+ 		}
+ 		if (!audit_signals || audit_dummy_context())
+ 			return 0;
+@@ -2384,7 +2385,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
+ 		ctx->target_auid = audit_get_loginuid(t);
+ 		ctx->target_uid = t->uid;
+ 		ctx->target_sessionid = audit_get_sessionid(t);
+-		selinux_get_task_sid(t, &ctx->target_sid);
++		security_task_getsecid(t, &ctx->target_sid);
+ 		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
+ 		return 0;
+ 	}
+@@ -2405,7 +2406,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
+ 	axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
+ 	axp->target_uid[axp->pid_count] = t->uid;
+ 	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
+-	selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
++	security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
+ 	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
+ 	axp->pid_count++;
+ 
+@@ -2435,16 +2436,17 @@ void audit_core_dumps(long signr)
+ 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+ 	audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
+ 			auid, current->uid, current->gid, sessionid);
+-	selinux_get_task_sid(current, &sid);
++	security_task_getsecid(current, &sid);
+ 	if (sid) {
+ 		char *ctx = NULL;
+ 		u32 len;
+ 
+-		if (selinux_sid_to_string(sid, &ctx, &len))
++		if (security_secid_to_secctx(sid, &ctx, &len))
+ 			audit_log_format(ab, " ssid=%u", sid);
+-		else
++		else {
+ 			audit_log_format(ab, " subj=%s", ctx);
+-		kfree(ctx);
++			security_release_secctx(ctx, len);
++		}
+ 	}
+ 	audit_log_format(ab, " pid=%d comm=", current->pid);
+ 	audit_log_untrustedstring(ab, current->comm);
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 2727f92..6d8de05 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -1722,7 +1722,12 @@ void cgroup_enable_task_cg_lists(void)
+ 	use_task_css_set_links = 1;
+ 	do_each_thread(g, p) {
+ 		task_lock(p);
+-		if (list_empty(&p->cg_list))
++		/*
++		 * We should check if the process is exiting, otherwise
++		 * it will race with cgroup_exit() in that the list
++		 * entry won't be deleted though the process has exited.
++		 */
++		if (!(p->flags & PF_EXITING) && list_empty(&p->cg_list))
+ 			list_add(&p->cg_list, &p->cgroups->tasks);
+ 		task_unlock(p);
+ 	} while_each_thread(g, p);
+diff --git a/kernel/compat.c b/kernel/compat.c
+index 5f0e201..e1ef048 100644
+--- a/kernel/compat.c
++++ b/kernel/compat.c
+@@ -47,15 +47,14 @@ static long compat_nanosleep_restart(struct restart_block *restart)
+ 	mm_segment_t oldfs;
+ 	long ret;
+ 
+-	rmtp = (struct compat_timespec __user *)(restart->arg1);
+-	restart->arg1 = (unsigned long)&rmt;
++	restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
+ 	oldfs = get_fs();
+ 	set_fs(KERNEL_DS);
+ 	ret = hrtimer_nanosleep_restart(restart);
+ 	set_fs(oldfs);
+ 
+ 	if (ret) {
+-		restart->arg1 = (unsigned long)rmtp;
++		rmtp = restart->nanosleep.compat_rmtp;
+ 
+ 		if (rmtp && put_compat_timespec(&rmt, rmtp))
+ 			return -EFAULT;
+@@ -89,7 +88,7 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
+ 			= &current_thread_info()->restart_block;
+ 
+ 		restart->fn = compat_nanosleep_restart;
+-		restart->arg1 = (unsigned long)rmtp;
++		restart->nanosleep.compat_rmtp = rmtp;
+ 
+ 		if (rmtp && put_compat_timespec(&rmt, rmtp))
+ 			return -EFAULT;
+@@ -446,7 +445,7 @@ asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
+ 	if (retval)
+ 		return retval;
+ 
+-	return sched_setaffinity(pid, new_mask);
++	return sched_setaffinity(pid, &new_mask);
+ }
+ 
+ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
+@@ -607,9 +606,9 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
+ 	long err;
+ 	mm_segment_t oldfs;
+ 	struct timespec tu;
+-	struct compat_timespec *rmtp = (struct compat_timespec *)(restart->arg1);
++	struct compat_timespec *rmtp = restart->nanosleep.compat_rmtp;
+ 
+-	restart->arg1 = (unsigned long) &tu;
++	restart->nanosleep.rmtp = (struct timespec __user *) &tu;
+ 	oldfs = get_fs();
+ 	set_fs(KERNEL_DS);
+ 	err = clock_nanosleep_restart(restart);
+@@ -621,7 +620,7 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
+ 
+ 	if (err == -ERESTART_RESTARTBLOCK) {
+ 		restart->fn = compat_clock_nanosleep_restart;
+-		restart->arg1 = (unsigned long) rmtp;
++		restart->nanosleep.compat_rmtp = rmtp;
+ 	}
+ 	return err;
+ }
+@@ -652,7 +651,7 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
+ 	if (err == -ERESTART_RESTARTBLOCK) {
+ 		restart = &current_thread_info()->restart_block;
+ 		restart->fn = compat_clock_nanosleep_restart;
+-		restart->arg1 = (unsigned long) rmtp;
++		restart->nanosleep.compat_rmtp = rmtp;
+ 	}
+ 	return err;
+ }
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index 2eff3f6..2011ad8 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -232,9 +232,9 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
+ 
+ 	/* Ensure that we are not runnable on dying cpu */
+ 	old_allowed = current->cpus_allowed;
+-	tmp = CPU_MASK_ALL;
++	cpus_setall(tmp);
+ 	cpu_clear(cpu, tmp);
+-	set_cpus_allowed(current, tmp);
++	set_cpus_allowed_ptr(current, &tmp);
+ 
+ 	p = __stop_machine_run(take_cpu_down, &tcd_param, cpu);
+ 
+@@ -268,7 +268,7 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
+ out_thread:
+ 	err = kthread_stop(p);
+ out_allowed:
+-	set_cpus_allowed(current, old_allowed);
++	set_cpus_allowed_ptr(current, &old_allowed);
+ out_release:
+ 	cpu_hotplug_done();
+ 	return err;
+diff --git a/kernel/cpuset.c b/kernel/cpuset.c
+index a1b61f4..8b35fbd 100644
+--- a/kernel/cpuset.c
++++ b/kernel/cpuset.c
+@@ -98,6 +98,9 @@ struct cpuset {
+ 	/* partition number for rebuild_sched_domains() */
+ 	int pn;
+ 
++	/* for custom sched domain */
++	int relax_domain_level;
++
+ 	/* used for walking a cpuset heirarchy */
+ 	struct list_head stack_list;
+ };
+@@ -478,6 +481,16 @@ static int cpusets_overlap(struct cpuset *a, struct cpuset *b)
+ 	return cpus_intersects(a->cpus_allowed, b->cpus_allowed);
+ }
+ 
++static void
++update_domain_attr(struct sched_domain_attr *dattr, struct cpuset *c)
++{
++	if (!dattr)
++		return;
++	if (dattr->relax_domain_level < c->relax_domain_level)
++		dattr->relax_domain_level = c->relax_domain_level;
++	return;
++}
++
+ /*
+  * rebuild_sched_domains()
+  *
+@@ -553,12 +566,14 @@ static void rebuild_sched_domains(void)
+ 	int csn;		/* how many cpuset ptrs in csa so far */
+ 	int i, j, k;		/* indices for partition finding loops */
+ 	cpumask_t *doms;	/* resulting partition; i.e. sched domains */
++	struct sched_domain_attr *dattr;  /* attributes for custom domains */
+ 	int ndoms;		/* number of sched domains in result */
+ 	int nslot;		/* next empty doms[] cpumask_t slot */
+ 
+ 	q = NULL;
+ 	csa = NULL;
+ 	doms = NULL;
++	dattr = NULL;
+ 
+ 	/* Special case for the 99% of systems with one, full, sched domain */
+ 	if (is_sched_load_balance(&top_cpuset)) {
+@@ -566,6 +581,11 @@ static void rebuild_sched_domains(void)
+ 		doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
+ 		if (!doms)
+ 			goto rebuild;
++		dattr = kmalloc(sizeof(struct sched_domain_attr), GFP_KERNEL);
++		if (dattr) {
++			*dattr = SD_ATTR_INIT;
++			update_domain_attr(dattr, &top_cpuset);
++		}
+ 		*doms = top_cpuset.cpus_allowed;
+ 		goto rebuild;
+ 	}
+@@ -622,6 +642,7 @@ restart:
+ 	doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
+ 	if (!doms)
+ 		goto rebuild;
++	dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL);
+ 
+ 	for (nslot = 0, i = 0; i < csn; i++) {
+ 		struct cpuset *a = csa[i];
+@@ -644,12 +665,15 @@ restart:
+ 			}
+ 
+ 			cpus_clear(*dp);
++			if (dattr)
++				*(dattr + nslot) = SD_ATTR_INIT;
+ 			for (j = i; j < csn; j++) {
+ 				struct cpuset *b = csa[j];
+ 
+ 				if (apn == b->pn) {
+ 					cpus_or(*dp, *dp, b->cpus_allowed);
+ 					b->pn = -1;
++					update_domain_attr(dattr, b);
+ 				}
+ 			}
+ 			nslot++;
+@@ -660,7 +684,7 @@ restart:
+ rebuild:
+ 	/* Have scheduler rebuild sched domains */
+ 	get_online_cpus();
+-	partition_sched_domains(ndoms, doms);
++	partition_sched_domains(ndoms, doms, dattr);
+ 	put_online_cpus();
+ 
+ done:
+@@ -668,6 +692,7 @@ done:
+ 		kfifo_free(q);
+ 	kfree(csa);
+ 	/* Don't kfree(doms) -- partition_sched_domains() does that. */
++	/* Don't kfree(dattr) -- partition_sched_domains() does that. */
+ }
+ 
+ static inline int started_after_time(struct task_struct *t1,
+@@ -729,7 +754,7 @@ int cpuset_test_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
+  */
+ void cpuset_change_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
+ {
+-	set_cpus_allowed(tsk, (cgroup_cs(scan->cg))->cpus_allowed);
++	set_cpus_allowed_ptr(tsk, &((cgroup_cs(scan->cg))->cpus_allowed));
+ }
+ 
+ /**
+@@ -1011,6 +1036,21 @@ static int update_memory_pressure_enabled(struct cpuset *cs, char *buf)
+ 	return 0;
+ }
+ 
++static int update_relax_domain_level(struct cpuset *cs, char *buf)
++{
++	int val = simple_strtol(buf, NULL, 10);
++
++	if (val < 0)
++		val = -1;
++
++	if (val != cs->relax_domain_level) {
++		cs->relax_domain_level = val;
++		rebuild_sched_domains();
++	}
++
++	return 0;
++}
++
+ /*
+  * update_flag - read a 0 or a 1 in a file and update associated flag
+  * bit:	the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
+@@ -1178,7 +1218,7 @@ static void cpuset_attach(struct cgroup_subsys *ss,
+ 
+ 	mutex_lock(&callback_mutex);
+ 	guarantee_online_cpus(cs, &cpus);
+-	set_cpus_allowed(tsk, cpus);
++	set_cpus_allowed_ptr(tsk, &cpus);
+ 	mutex_unlock(&callback_mutex);
+ 
+ 	from = oldcs->mems_allowed;
+@@ -1202,6 +1242,7 @@ typedef enum {
+ 	FILE_CPU_EXCLUSIVE,
+ 	FILE_MEM_EXCLUSIVE,
+ 	FILE_SCHED_LOAD_BALANCE,
++	FILE_SCHED_RELAX_DOMAIN_LEVEL,
+ 	FILE_MEMORY_PRESSURE_ENABLED,
+ 	FILE_MEMORY_PRESSURE,
+ 	FILE_SPREAD_PAGE,
+@@ -1256,6 +1297,9 @@ static ssize_t cpuset_common_file_write(struct cgroup *cont,
+ 	case FILE_SCHED_LOAD_BALANCE:
+ 		retval = update_flag(CS_SCHED_LOAD_BALANCE, cs, buffer);
+ 		break;
++	case FILE_SCHED_RELAX_DOMAIN_LEVEL:
++		retval = update_relax_domain_level(cs, buffer);
++		break;
+ 	case FILE_MEMORY_MIGRATE:
+ 		retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
+ 		break;
+@@ -1354,6 +1398,9 @@ static ssize_t cpuset_common_file_read(struct cgroup *cont,
+ 	case FILE_SCHED_LOAD_BALANCE:
+ 		*s++ = is_sched_load_balance(cs) ? '1' : '0';
+ 		break;
++	case FILE_SCHED_RELAX_DOMAIN_LEVEL:
++		s += sprintf(s, "%d", cs->relax_domain_level);
++		break;
+ 	case FILE_MEMORY_MIGRATE:
+ 		*s++ = is_memory_migrate(cs) ? '1' : '0';
+ 		break;
+@@ -1424,6 +1471,13 @@ static struct cftype cft_sched_load_balance = {
+ 	.private = FILE_SCHED_LOAD_BALANCE,
+ };
+ 
++static struct cftype cft_sched_relax_domain_level = {
++	.name = "sched_relax_domain_level",
++	.read = cpuset_common_file_read,
++	.write = cpuset_common_file_write,
++	.private = FILE_SCHED_RELAX_DOMAIN_LEVEL,
++};
++
+ static struct cftype cft_memory_migrate = {
+ 	.name = "memory_migrate",
+ 	.read = cpuset_common_file_read,
+@@ -1475,6 +1529,9 @@ static int cpuset_populate(struct cgroup_subsys *ss, struct cgroup *cont)
+ 		return err;
+ 	if ((err = cgroup_add_file(cont, ss, &cft_sched_load_balance)) < 0)
+ 		return err;
++	if ((err = cgroup_add_file(cont, ss,
++					&cft_sched_relax_domain_level)) < 0)
++		return err;
+ 	if ((err = cgroup_add_file(cont, ss, &cft_memory_pressure)) < 0)
+ 		return err;
+ 	if ((err = cgroup_add_file(cont, ss, &cft_spread_page)) < 0)
+@@ -1555,10 +1612,11 @@ static struct cgroup_subsys_state *cpuset_create(
+ 	if (is_spread_slab(parent))
+ 		set_bit(CS_SPREAD_SLAB, &cs->flags);
+ 	set_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
+-	cs->cpus_allowed = CPU_MASK_NONE;
+-	cs->mems_allowed = NODE_MASK_NONE;
++	cpus_clear(cs->cpus_allowed);
++	nodes_clear(cs->mems_allowed);
+ 	cs->mems_generation = cpuset_mems_generation++;
+ 	fmeter_init(&cs->fmeter);
++	cs->relax_domain_level = -1;
+ 
+ 	cs->parent = parent;
+ 	number_of_cpusets++;
+@@ -1625,12 +1683,13 @@ int __init cpuset_init(void)
+ {
+ 	int err = 0;
+ 
+-	top_cpuset.cpus_allowed = CPU_MASK_ALL;
+-	top_cpuset.mems_allowed = NODE_MASK_ALL;
++	cpus_setall(top_cpuset.cpus_allowed);
++	nodes_setall(top_cpuset.mems_allowed);
+ 
+ 	fmeter_init(&top_cpuset.fmeter);
+ 	top_cpuset.mems_generation = cpuset_mems_generation++;
+ 	set_bit(CS_SCHED_LOAD_BALANCE, &top_cpuset.flags);
++	top_cpuset.relax_domain_level = -1;
+ 
+ 	err = register_filesystem(&cpuset_fs_type);
+ 	if (err < 0)
+@@ -1844,6 +1903,7 @@ void __init cpuset_init_smp(void)
+ 
+  * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
+  * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
++ * @pmask: pointer to cpumask_t variable to receive cpus_allowed set.
+  *
+  * Description: Returns the cpumask_t cpus_allowed of the cpuset
+  * attached to the specified @tsk.  Guaranteed to return some non-empty
+@@ -1851,35 +1911,27 @@ void __init cpuset_init_smp(void)
+  * tasks cpuset.
+  **/
+ 
+-cpumask_t cpuset_cpus_allowed(struct task_struct *tsk)
++void cpuset_cpus_allowed(struct task_struct *tsk, cpumask_t *pmask)
+ {
+-	cpumask_t mask;
+-
+ 	mutex_lock(&callback_mutex);
+-	mask = cpuset_cpus_allowed_locked(tsk);
++	cpuset_cpus_allowed_locked(tsk, pmask);
+ 	mutex_unlock(&callback_mutex);
+-
+-	return mask;
+ }
+ 
+ /**
+  * cpuset_cpus_allowed_locked - return cpus_allowed mask from a tasks cpuset.
+  * Must be called with callback_mutex held.
+  **/
+-cpumask_t cpuset_cpus_allowed_locked(struct task_struct *tsk)
++void cpuset_cpus_allowed_locked(struct task_struct *tsk, cpumask_t *pmask)
+ {
+-	cpumask_t mask;
+-
+ 	task_lock(tsk);
+-	guarantee_online_cpus(task_cs(tsk), &mask);
++	guarantee_online_cpus(task_cs(tsk), pmask);
+ 	task_unlock(tsk);
+-
+-	return mask;
+ }
+ 
+ void cpuset_init_current_mems_allowed(void)
+ {
+-	current->mems_allowed = NODE_MASK_ALL;
++	nodes_setall(current->mems_allowed);
+ }
+ 
+ /**
+@@ -2261,8 +2313,16 @@ void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task)
+ 	m->count += cpumask_scnprintf(m->buf + m->count, m->size - m->count,
+ 					task->cpus_allowed);
+ 	seq_printf(m, "\n");
++	seq_printf(m, "Cpus_allowed_list:\t");
++	m->count += cpulist_scnprintf(m->buf + m->count, m->size - m->count,
++					task->cpus_allowed);
++	seq_printf(m, "\n");
+ 	seq_printf(m, "Mems_allowed:\t");
+ 	m->count += nodemask_scnprintf(m->buf + m->count, m->size - m->count,
+ 					task->mems_allowed);
+ 	seq_printf(m, "\n");
++	seq_printf(m, "Mems_allowed_list:\t");
++	m->count += nodelist_scnprintf(m->buf + m->count, m->size - m->count,
++					task->mems_allowed);
++	seq_printf(m, "\n");
+ }
+diff --git a/kernel/exit.c b/kernel/exit.c
+index 073005b..97f609f 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -507,10 +507,9 @@ void put_files_struct(struct files_struct *files)
+ 	}
+ }
+ 
+-EXPORT_SYMBOL(put_files_struct);
+-
+-void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
++void reset_files_struct(struct files_struct *files)
+ {
++	struct task_struct *tsk = current;
+ 	struct files_struct *old;
+ 
+ 	old = tsk->files;
+@@ -519,9 +518,8 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
+ 	task_unlock(tsk);
+ 	put_files_struct(old);
+ }
+-EXPORT_SYMBOL(reset_files_struct);
+ 
+-static void __exit_files(struct task_struct *tsk)
++void exit_files(struct task_struct *tsk)
+ {
+ 	struct files_struct * files = tsk->files;
+ 
+@@ -533,12 +531,7 @@ static void __exit_files(struct task_struct *tsk)
+ 	}
+ }
+ 
+-void exit_files(struct task_struct *tsk)
+-{
+-	__exit_files(tsk);
+-}
+-
+-static void __put_fs_struct(struct fs_struct *fs)
++void put_fs_struct(struct fs_struct *fs)
+ {
+ 	/* No need to hold fs->lock if we are killing it */
+ 	if (atomic_dec_and_test(&fs->count)) {
+@@ -550,12 +543,7 @@ static void __put_fs_struct(struct fs_struct *fs)
+ 	}
+ }
+ 
+-void put_fs_struct(struct fs_struct *fs)
+-{
+-	__put_fs_struct(fs);
+-}
+-
+-static void __exit_fs(struct task_struct *tsk)
++void exit_fs(struct task_struct *tsk)
+ {
+ 	struct fs_struct * fs = tsk->fs;
+ 
+@@ -563,15 +551,10 @@ static void __exit_fs(struct task_struct *tsk)
+ 		task_lock(tsk);
+ 		tsk->fs = NULL;
+ 		task_unlock(tsk);
+-		__put_fs_struct(fs);
++		put_fs_struct(fs);
+ 	}
+ }
+ 
+-void exit_fs(struct task_struct *tsk)
+-{
+-	__exit_fs(tsk);
+-}
+-
+ EXPORT_SYMBOL_GPL(exit_fs);
+ 
+ /*
+@@ -967,8 +950,8 @@ NORET_TYPE void do_exit(long code)
+ 	if (group_dead)
+ 		acct_process();
+ 	exit_sem(tsk);
+-	__exit_files(tsk);
+-	__exit_fs(tsk);
++	exit_files(tsk);
++	exit_fs(tsk);
+ 	check_stack_usage();
+ 	exit_thread();
+ 	cgroup_exit(tsk, 1);
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 9c042f9..cb46bef 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -132,6 +132,14 @@ void __put_task_struct(struct task_struct *tsk)
+ 		free_task(tsk);
+ }
+ 
++/*
++ * macro override instead of weak attribute alias, to workaround
++ * gcc 4.1.0 and 4.1.1 bugs with weak attribute and empty functions.
++ */
++#ifndef arch_task_cache_init
++#define arch_task_cache_init()
++#endif
++
+ void __init fork_init(unsigned long mempages)
+ {
+ #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
+@@ -144,6 +152,9 @@ void __init fork_init(unsigned long mempages)
+ 			ARCH_MIN_TASKALIGN, SLAB_PANIC, NULL);
+ #endif
+ 
++	/* do the arch specific task caches init */
++	arch_task_cache_init();
++
+ 	/*
+ 	 * The default maximum number of threads is set to a safe
+ 	 * value: the thread structures can take up at most half
+@@ -163,6 +174,13 @@ void __init fork_init(unsigned long mempages)
+ 		init_task.signal->rlim[RLIMIT_NPROC];
+ }
+ 
++int __attribute__((weak)) arch_dup_task_struct(struct task_struct *dst,
++					       struct task_struct *src)
++{
++	*dst = *src;
++	return 0;
++}
++
+ static struct task_struct *dup_task_struct(struct task_struct *orig)
+ {
+ 	struct task_struct *tsk;
+@@ -181,15 +199,15 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
+ 		return NULL;
+ 	}
+ 
+-	*tsk = *orig;
++ 	err = arch_dup_task_struct(tsk, orig);
++	if (err)
++		goto out;
++
+ 	tsk->stack = ti;
+ 
+ 	err = prop_local_init_single(&tsk->dirties);
+-	if (err) {
+-		free_thread_info(ti);
+-		free_task_struct(tsk);
+-		return NULL;
+-	}
++	if (err)
++		goto out;
+ 
+ 	setup_thread_stack(tsk, orig);
+ 
+@@ -205,6 +223,11 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
+ #endif
+ 	tsk->splice_pipe = NULL;
+ 	return tsk;
++
++out:
++	free_thread_info(ti);
++	free_task_struct(tsk);
++	return NULL;
+ }
+ 
+ #ifdef CONFIG_MMU
+@@ -782,12 +805,6 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
+ 		goto out;
+ 	}
+ 
+-	/*
+-	 * Note: we may be using current for both targets (See exec.c)
+-	 * This works because we cache current->files (old) as oldf. Don't
+-	 * break this.
+-	 */
+-	tsk->files = NULL;
+ 	newf = dup_fd(oldf, &error);
+ 	if (!newf)
+ 		goto out;
+@@ -823,34 +840,6 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
+ 	return 0;
+ }
+ 
+-/*
+- *	Helper to unshare the files of the current task.
+- *	We don't want to expose copy_files internals to
+- *	the exec layer of the kernel.
+- */
+-
+-int unshare_files(void)
+-{
+-	struct files_struct *files  = current->files;
+-	int rc;
+-
+-	BUG_ON(!files);
+-
+-	/* This can race but the race causes us to copy when we don't
+-	   need to and drop the copy */
+-	if(atomic_read(&files->count) == 1)
+-	{
+-		atomic_inc(&files->count);
+-		return 0;
+-	}
+-	rc = copy_files(0, current);
+-	if(rc)
+-		current->files = files;
+-	return rc;
+-}
+-
+-EXPORT_SYMBOL(unshare_files);
+-
+ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
+ {
+ 	struct sighand_struct *sig;
+@@ -1788,3 +1777,27 @@ bad_unshare_cleanup_thread:
+ bad_unshare_out:
+ 	return err;
+ }
++
++/*
++ *	Helper to unshare the files of the current task.
++ *	We don't want to expose copy_files internals to
++ *	the exec layer of the kernel.
++ */
++
++int unshare_files(struct files_struct **displaced)
++{
++	struct task_struct *task = current;
++	struct files_struct *copy = NULL;
++	int error;
++
++	error = unshare_fd(CLONE_FILES, &copy);
++	if (error || !copy) {
++		*displaced = NULL;
++		return error;
++	}
++	*displaced = task->files;
++	task_lock(task);
++	task->files = copy;
++	task_unlock(task);
++	return 0;
++}
+diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
+index 98bee01..f78777a 100644
+--- a/kernel/hrtimer.c
++++ b/kernel/hrtimer.c
+@@ -1238,51 +1238,50 @@ void hrtimer_run_pending(void)
+ /*
+  * Called from hardirq context every jiffy
+  */
+-static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
+-				     int index)
++void hrtimer_run_queues(void)
+ {
+ 	struct rb_node *node;
+-	struct hrtimer_clock_base *base = &cpu_base->clock_base[index];
++	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
++	struct hrtimer_clock_base *base;
++	int index, gettime = 1;
+ 
+-	if (!base->first)
++	if (hrtimer_hres_active())
+ 		return;
+ 
+-	if (base->get_softirq_time)
+-		base->softirq_time = base->get_softirq_time();
+-
+-	spin_lock(&cpu_base->lock);
++	for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
++		base = &cpu_base->clock_base[index];
+ 
+-	while ((node = base->first)) {
+-		struct hrtimer *timer;
+-
+-		timer = rb_entry(node, struct hrtimer, node);
+-		if (base->softirq_time.tv64 <= timer->expires.tv64)
+-			break;
+-
+-		if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
+-			__remove_hrtimer(timer, base, HRTIMER_STATE_PENDING, 0);
+-			list_add_tail(&timer->cb_entry,
+-					&base->cpu_base->cb_pending);
++		if (!base->first)
+ 			continue;
++
++		if (base->get_softirq_time)
++			base->softirq_time = base->get_softirq_time();
++		else if (gettime) {
++			hrtimer_get_softirq_time(cpu_base);
++			gettime = 0;
+ 		}
+ 
+-		__run_hrtimer(timer);
+-	}
+-	spin_unlock(&cpu_base->lock);
+-}
++		spin_lock(&cpu_base->lock);
+ 
+-void hrtimer_run_queues(void)
+-{
+-	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+-	int i;
++		while ((node = base->first)) {
++			struct hrtimer *timer;
+ 
+-	if (hrtimer_hres_active())
+-		return;
++			timer = rb_entry(node, struct hrtimer, node);
++			if (base->softirq_time.tv64 <= timer->expires.tv64)
++				break;
+ 
+-	hrtimer_get_softirq_time(cpu_base);
++			if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
++				__remove_hrtimer(timer, base,
++					HRTIMER_STATE_PENDING, 0);
++				list_add_tail(&timer->cb_entry,
++					&base->cpu_base->cb_pending);
++				continue;
++			}
+ 
+-	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
+-		run_hrtimer_queue(cpu_base, i);
++			__run_hrtimer(timer);
++		}
++		spin_unlock(&cpu_base->lock);
++	}
+ }
+ 
+ /*
+@@ -1354,13 +1353,13 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
+ 	struct hrtimer_sleeper t;
+ 	struct timespec __user  *rmtp;
+ 
+-	hrtimer_init(&t.timer, restart->arg0, HRTIMER_MODE_ABS);
+-	t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2;
++	hrtimer_init(&t.timer, restart->nanosleep.index, HRTIMER_MODE_ABS);
++	t.timer.expires.tv64 = restart->nanosleep.expires;
+ 
+ 	if (do_nanosleep(&t, HRTIMER_MODE_ABS))
+ 		return 0;
+ 
+-	rmtp = (struct timespec __user *)restart->arg1;
++	rmtp = restart->nanosleep.rmtp;
+ 	if (rmtp) {
+ 		int ret = update_rmtp(&t.timer, rmtp);
+ 		if (ret <= 0)
+@@ -1394,10 +1393,9 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
+ 
+ 	restart = &current_thread_info()->restart_block;
+ 	restart->fn = hrtimer_nanosleep_restart;
+-	restart->arg0 = (unsigned long) t.timer.base->index;
+-	restart->arg1 = (unsigned long) rmtp;
+-	restart->arg2 = t.timer.expires.tv64 & 0xFFFFFFFF;
+-	restart->arg3 = t.timer.expires.tv64 >> 32;
++	restart->nanosleep.index = t.timer.base->index;
++	restart->nanosleep.rmtp = rmtp;
++	restart->nanosleep.expires = t.timer.expires.tv64;
+ 
+ 	return -ERESTART_RESTARTBLOCK;
+ }
+@@ -1425,7 +1423,6 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
+ 	int i;
+ 
+ 	spin_lock_init(&cpu_base->lock);
+-	lockdep_set_class(&cpu_base->lock, &cpu_base->lock_key);
+ 
+ 	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
+ 		cpu_base->clock_base[i].cpu_base = cpu_base;
+@@ -1466,16 +1463,16 @@ static void migrate_hrtimers(int cpu)
+ 	tick_cancel_sched_timer(cpu);
+ 
+ 	local_irq_disable();
+-	double_spin_lock(&new_base->lock, &old_base->lock,
+-			 smp_processor_id() < cpu);
++	spin_lock(&new_base->lock);
++	spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
+ 
+ 	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+ 		migrate_hrtimer_list(&old_base->clock_base[i],
+ 				     &new_base->clock_base[i]);
+ 	}
+ 
+-	double_spin_unlock(&new_base->lock, &old_base->lock,
+-			   smp_processor_id() < cpu);
++	spin_unlock(&old_base->lock);
++	spin_unlock(&new_base->lock);
+ 	local_irq_enable();
+ 	put_cpu_var(hrtimer_bases);
+ }
+diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
+index fdb3fbe..964964b 100644
+--- a/kernel/irq/chip.c
++++ b/kernel/irq/chip.c
+@@ -47,7 +47,7 @@ void dynamic_irq_init(unsigned int irq)
+ 	desc->irq_count = 0;
+ 	desc->irqs_unhandled = 0;
+ #ifdef CONFIG_SMP
+-	desc->affinity = CPU_MASK_ALL;
++	cpus_setall(desc->affinity);
+ #endif
+ 	spin_unlock_irqrestore(&desc->lock, flags);
+ }
+diff --git a/kernel/kexec.c b/kernel/kexec.c
+index 06a0e27..6782dce 100644
+--- a/kernel/kexec.c
++++ b/kernel/kexec.c
+@@ -29,7 +29,6 @@
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/system.h>
+-#include <asm/semaphore.h>
+ #include <asm/sections.h>
+ 
+ /* Per cpu memory for storing cpu states in case of system crash. */
+diff --git a/kernel/kgdb.c b/kernel/kgdb.c
+new file mode 100644
+index 0000000..1bd0ec1
+--- /dev/null
++++ b/kernel/kgdb.c
+@@ -0,0 +1,1700 @@
++/*
++ * KGDB stub.
++ *
++ * Maintainer: Jason Wessel <jason.wessel at windriver.com>
++ *
++ * Copyright (C) 2000-2001 VERITAS Software Corporation.
++ * Copyright (C) 2002-2004 Timesys Corporation
++ * Copyright (C) 2003-2004 Amit S. Kale <amitkale at linsyssoft.com>
++ * Copyright (C) 2004 Pavel Machek <pavel at suse.cz>
++ * Copyright (C) 2004-2006 Tom Rini <trini at kernel.crashing.org>
++ * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd.
++ * Copyright (C) 2005-2008 Wind River Systems, Inc.
++ * Copyright (C) 2007 MontaVista Software, Inc.
++ * Copyright (C) 2008 Red Hat, Inc., Ingo Molnar <mingo at redhat.com>
++ *
++ * Contributors at various stages not listed above:
++ *  Jason Wessel ( jason.wessel at windriver.com )
++ *  George Anzinger <george at mvista.com>
++ *  Anurekh Saxena (anurekh.saxena at timesys.com)
++ *  Lake Stevens Instrument Division (Glenn Engel)
++ *  Jim Kingdon, Cygnus Support.
++ *
++ * Original KGDB stub: David Grothe <dave at gcom.com>,
++ * Tigran Aivazian <tigran at sco.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/pid_namespace.h>
++#include <linux/clocksource.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/console.h>
++#include <linux/threads.h>
++#include <linux/uaccess.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ptrace.h>
++#include <linux/reboot.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/sysrq.h>
++#include <linux/init.h>
++#include <linux/kgdb.h>
++#include <linux/pid.h>
++#include <linux/smp.h>
++#include <linux/mm.h>
++
++#include <asm/cacheflush.h>
++#include <asm/byteorder.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++
++static int kgdb_break_asap;
++
++struct kgdb_state {
++	int			ex_vector;
++	int			signo;
++	int			err_code;
++	int			cpu;
++	int			pass_exception;
++	long			threadid;
++	long			kgdb_usethreadid;
++	struct pt_regs		*linux_regs;
++};
++
++static struct debuggerinfo_struct {
++	void			*debuggerinfo;
++	struct task_struct	*task;
++} kgdb_info[NR_CPUS];
++
++/**
++ * kgdb_connected - Is a host GDB connected to us?
++ */
++int				kgdb_connected;
++EXPORT_SYMBOL_GPL(kgdb_connected);
++
++/* All the KGDB handlers are installed */
++static int			kgdb_io_module_registered;
++
++/* Guard for recursive entry */
++static int			exception_level;
++
++static struct kgdb_io		*kgdb_io_ops;
++static DEFINE_SPINLOCK(kgdb_registration_lock);
++
++/* kgdb console driver is loaded */
++static int kgdb_con_registered;
++/* determine if kgdb console output should be used */
++static int kgdb_use_con;
++
++static int __init opt_kgdb_con(char *str)
++{
++	kgdb_use_con = 1;
++	return 0;
++}
++
++early_param("kgdbcon", opt_kgdb_con);
++
++module_param(kgdb_use_con, int, 0644);
++
++/*
++ * Holds information about breakpoints in a kernel. These breakpoints are
++ * added and removed by gdb.
++ */
++static struct kgdb_bkpt		kgdb_break[KGDB_MAX_BREAKPOINTS] = {
++	[0 ... KGDB_MAX_BREAKPOINTS-1] = { .state = BP_UNDEFINED }
++};
++
++/*
++ * The CPU# of the active CPU, or -1 if none:
++ */
++atomic_t			kgdb_active = ATOMIC_INIT(-1);
++
++/*
++ * 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];
++atomic_t			kgdb_setting_breakpoint;
++
++struct task_struct		*kgdb_usethread;
++struct task_struct		*kgdb_contthread;
++
++int				kgdb_single_step;
++
++/* Our I/O buffers. */
++static char			remcom_in_buffer[BUFMAX];
++static char			remcom_out_buffer[BUFMAX];
++
++/* Storage for the registers, in GDB format. */
++static unsigned long		gdb_regs[(NUMREGBYTES +
++					sizeof(unsigned long) - 1) /
++					sizeof(unsigned long)];
++
++/* to keep track of the CPU which is doing the single stepping*/
++atomic_t			kgdb_cpu_doing_single_step = ATOMIC_INIT(-1);
++
++/*
++ * If you are debugging a problem where roundup (the collection of
++ * all other CPUs) is a problem [this should be extremely rare],
++ * then use the nokgdbroundup option to avoid roundup. In that case
++ * the other CPUs might interfere with your debugging context, so
++ * use this with care:
++ */
++int				kgdb_do_roundup = 1;
++
++static int __init opt_nokgdbroundup(char *str)
++{
++	kgdb_do_roundup = 0;
++
++	return 0;
++}
++
++early_param("nokgdbroundup", opt_nokgdbroundup);
++
++/*
++ * Finally, some KGDB code :-)
++ */
++
++/*
++ * Weak aliases for breakpoint management,
++ * can be overriden by architectures when needed:
++ */
++int __weak kgdb_validate_break_address(unsigned long addr)
++{
++	char tmp_variable[BREAK_INSTR_SIZE];
++
++	return probe_kernel_read(tmp_variable, (char *)addr, BREAK_INSTR_SIZE);
++}
++
++int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
++{
++	int err;
++
++	err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE);
++	if (err)
++		return err;
++
++	return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
++				  BREAK_INSTR_SIZE);
++}
++
++int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
++{
++	return probe_kernel_write((char *)addr,
++				  (char *)bundle, BREAK_INSTR_SIZE);
++}
++
++unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs)
++{
++	return instruction_pointer(regs);
++}
++
++int __weak kgdb_arch_init(void)
++{
++	return 0;
++}
++
++int __weak kgdb_skipexception(int exception, struct pt_regs *regs)
++{
++	return 0;
++}
++
++void __weak
++kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code)
++{
++	return;
++}
++
++/**
++ *	kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb.
++ *	@regs: Current &struct pt_regs.
++ *
++ *	This function will be called if the particular architecture must
++ *	disable hardware debugging while it is processing gdb packets or
++ *	handling exception.
++ */
++void __weak kgdb_disable_hw_debug(struct pt_regs *regs)
++{
++}
++
++/*
++ * GDB remote protocol parser:
++ */
++
++static const char	hexchars[] = "0123456789abcdef";
++
++static int hex(char ch)
++{
++	if ((ch >= 'a') && (ch <= 'f'))
++		return ch - 'a' + 10;
++	if ((ch >= '0') && (ch <= '9'))
++		return ch - '0';
++	if ((ch >= 'A') && (ch <= 'F'))
++		return ch - 'A' + 10;
++	return -1;
++}
++
++/* scan for the sequence $<data>#<checksum> */
++static void get_packet(char *buffer)
++{
++	unsigned char checksum;
++	unsigned char xmitcsum;
++	int count;
++	char ch;
++
++	do {
++		/*
++		 * Spin and wait around for the start character, ignore all
++		 * other characters:
++		 */
++		while ((ch = (kgdb_io_ops->read_char())) != '$')
++			/* nothing */;
++
++		kgdb_connected = 1;
++		checksum = 0;
++		xmitcsum = -1;
++
++		count = 0;
++
++		/*
++		 * now, read until a # or end of buffer is found:
++		 */
++		while (count < (BUFMAX - 1)) {
++			ch = kgdb_io_ops->read_char();
++			if (ch == '#')
++				break;
++			checksum = checksum + ch;
++			buffer[count] = ch;
++			count = count + 1;
++		}
++		buffer[count] = 0;
++
++		if (ch == '#') {
++			xmitcsum = hex(kgdb_io_ops->read_char()) << 4;
++			xmitcsum += hex(kgdb_io_ops->read_char());
++
++			if (checksum != xmitcsum)
++				/* failed checksum */
++				kgdb_io_ops->write_char('-');
++			else
++				/* successful transfer */
++				kgdb_io_ops->write_char('+');
++			if (kgdb_io_ops->flush)
++				kgdb_io_ops->flush();
++		}
++	} while (checksum != xmitcsum);
++}
++
++/*
++ * Send the packet in buffer.
++ * Check for gdb connection if asked for.
++ */
++static void put_packet(char *buffer)
++{
++	unsigned char checksum;
++	int count;
++	char ch;
++
++	/*
++	 * $<packet info>#<checksum>.
++	 */
++	while (1) {
++		kgdb_io_ops->write_char('$');
++		checksum = 0;
++		count = 0;
++
++		while ((ch = buffer[count])) {
++			kgdb_io_ops->write_char(ch);
++			checksum += ch;
++			count++;
++		}
++
++		kgdb_io_ops->write_char('#');
++		kgdb_io_ops->write_char(hexchars[checksum >> 4]);
++		kgdb_io_ops->write_char(hexchars[checksum & 0xf]);
++		if (kgdb_io_ops->flush)
++			kgdb_io_ops->flush();
++
++		/* Now see what we get in reply. */
++		ch = kgdb_io_ops->read_char();
++
++		if (ch == 3)
++			ch = kgdb_io_ops->read_char();
++
++		/* If we get an ACK, we are done. */
++		if (ch == '+')
++			return;
++
++		/*
++		 * If we get the start of another packet, this means
++		 * that GDB is attempting to reconnect.  We will NAK
++		 * the packet being sent, and stop trying to send this
++		 * packet.
++		 */
++		if (ch == '$') {
++			kgdb_io_ops->write_char('-');
++			if (kgdb_io_ops->flush)
++				kgdb_io_ops->flush();
++			return;
++		}
++	}
++}
++
++static char *pack_hex_byte(char *pkt, u8 byte)
++{
++	*pkt++ = hexchars[byte >> 4];
++	*pkt++ = hexchars[byte & 0xf];
++
++	return pkt;
++}
++
++/*
++ * Convert the memory pointed to by mem into hex, placing result in buf.
++ * Return a pointer to the last char put in buf (null). May return an error.
++ */
++int kgdb_mem2hex(char *mem, char *buf, int count)
++{
++	char *tmp;
++	int err;
++
++	/*
++	 * We use the upper half of buf as an intermediate buffer for the
++	 * raw memory copy.  Hex conversion will work against this one.
++	 */
++	tmp = buf + count;
++
++	err = probe_kernel_read(tmp, mem, count);
++	if (!err) {
++		while (count > 0) {
++			buf = pack_hex_byte(buf, *tmp);
++			tmp++;
++			count--;
++		}
++
++		*buf = 0;
++	}
++
++	return err;
++}
++
++/*
++ * Copy the binary array pointed to by buf into mem.  Fix $, #, and
++ * 0x7d escaped with 0x7d.  Return a pointer to the character after
++ * the last byte written.
++ */
++static int kgdb_ebin2mem(char *buf, char *mem, int count)
++{
++	int err = 0;
++	char c;
++
++	while (count-- > 0) {
++		c = *buf++;
++		if (c == 0x7d)
++			c = *buf++ ^ 0x20;
++
++		err = probe_kernel_write(mem, &c, 1);
++		if (err)
++			break;
++
++		mem++;
++	}
++
++	return err;
++}
++
++/*
++ * Convert the hex array pointed to by buf into binary to be placed in mem.
++ * Return a pointer to the character AFTER the last byte written.
++ * May return an error.
++ */
++int kgdb_hex2mem(char *buf, char *mem, int count)
++{
++	char *tmp_raw;
++	char *tmp_hex;
++
++	/*
++	 * We use the upper half of buf as an intermediate buffer for the
++	 * raw memory that is converted from hex.
++	 */
++	tmp_raw = buf + count * 2;
++
++	tmp_hex = tmp_raw - 1;
++	while (tmp_hex >= buf) {
++		tmp_raw--;
++		*tmp_raw = hex(*tmp_hex--);
++		*tmp_raw |= hex(*tmp_hex--) << 4;
++	}
++
++	return probe_kernel_write(mem, tmp_raw, count);
++}
++
++/*
++ * While we find nice hex chars, build a long_val.
++ * Return number of chars processed.
++ */
++int kgdb_hex2long(char **ptr, long *long_val)
++{
++	int hex_val;
++	int num = 0;
++
++	*long_val = 0;
++
++	while (**ptr) {
++		hex_val = hex(**ptr);
++		if (hex_val < 0)
++			break;
++
++		*long_val = (*long_val << 4) | hex_val;
++		num++;
++		(*ptr)++;
++	}
++
++	return num;
++}
++
++/* Write memory due to an 'M' or 'X' packet. */
++static int write_mem_msg(int binary)
++{
++	char *ptr = &remcom_in_buffer[1];
++	unsigned long addr;
++	unsigned long length;
++	int err;
++
++	if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
++	    kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
++		if (binary)
++			err = kgdb_ebin2mem(ptr, (char *)addr, length);
++		else
++			err = kgdb_hex2mem(ptr, (char *)addr, length);
++		if (err)
++			return err;
++		if (CACHE_FLUSH_IS_SAFE)
++			flush_icache_range(addr, addr + length + 1);
++		return 0;
++	}
++
++	return -EINVAL;
++}
++
++static void error_packet(char *pkt, int error)
++{
++	error = -error;
++	pkt[0] = 'E';
++	pkt[1] = hexchars[(error / 10)];
++	pkt[2] = hexchars[(error % 10)];
++	pkt[3] = '\0';
++}
++
++/*
++ * Thread ID accessors. We represent a flat TID space to GDB, where
++ * the per CPU idle threads (which under Linux all have PID 0) are
++ * remapped to negative TIDs.
++ */
++
++#define BUF_THREAD_ID_SIZE	16
++
++static char *pack_threadid(char *pkt, unsigned char *id)
++{
++	char *limit;
++
++	limit = pkt + BUF_THREAD_ID_SIZE;
++	while (pkt < limit)
++		pkt = pack_hex_byte(pkt, *id++);
++
++	return pkt;
++}
++
++static void int_to_threadref(unsigned char *id, int value)
++{
++	unsigned char *scan;
++	int i = 4;
++
++	scan = (unsigned char *)id;
++	while (i--)
++		*scan++ = 0;
++	*scan++ = (value >> 24) & 0xff;
++	*scan++ = (value >> 16) & 0xff;
++	*scan++ = (value >> 8) & 0xff;
++	*scan++ = (value & 0xff);
++}
++
++static struct task_struct *getthread(struct pt_regs *regs, int tid)
++{
++	/*
++	 * Non-positive TIDs are remapped idle tasks:
++	 */
++	if (tid <= 0)
++		return idle_task(-tid);
++
++	/*
++	 * find_task_by_pid_ns() does not take the tasklist lock anymore
++	 * but is nicely RCU locked - hence is a pretty resilient
++	 * thing to use:
++	 */
++	return find_task_by_pid_ns(tid, &init_pid_ns);
++}
++
++/*
++ * CPU debug state control:
++ */
++
++#ifdef CONFIG_SMP
++static void kgdb_wait(struct pt_regs *regs)
++{
++	unsigned long flags;
++	int cpu;
++
++	local_irq_save(flags);
++	cpu = raw_smp_processor_id();
++	kgdb_info[cpu].debuggerinfo = regs;
++	kgdb_info[cpu].task = current;
++	/*
++	 * Make sure the above info reaches the primary CPU before
++	 * our cpu_in_kgdb[] flag setting does:
++	 */
++	smp_wmb();
++	atomic_set(&cpu_in_kgdb[cpu], 1);
++
++	/* Wait till primary CPU is done with debugging */
++	while (atomic_read(&passive_cpu_wait[cpu]))
++		cpu_relax();
++
++	kgdb_info[cpu].debuggerinfo = NULL;
++	kgdb_info[cpu].task = NULL;
++
++	/* fix up hardware debug registers on local cpu */
++	if (arch_kgdb_ops.correct_hw_break)
++		arch_kgdb_ops.correct_hw_break();
++
++	/* Signal the primary CPU that we are done: */
++	atomic_set(&cpu_in_kgdb[cpu], 0);
++	clocksource_touch_watchdog();
++	local_irq_restore(flags);
++}
++#endif
++
++/*
++ * Some architectures need cache flushes when we set/clear a
++ * breakpoint:
++ */
++static void kgdb_flush_swbreak_addr(unsigned long addr)
++{
++	if (!CACHE_FLUSH_IS_SAFE)
++		return;
++
++	if (current->mm && current->mm->mmap_cache) {
++		flush_cache_range(current->mm->mmap_cache,
++				  addr, addr + BREAK_INSTR_SIZE);
++	}
++	/* Force flush instruction cache if it was outside the mm */
++	flush_icache_range(addr, addr + BREAK_INSTR_SIZE);
++}
++
++/*
++ * SW breakpoint management:
++ */
++static int kgdb_activate_sw_breakpoints(void)
++{
++	unsigned long addr;
++	int error = 0;
++	int i;
++
++	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++		if (kgdb_break[i].state != BP_SET)
++			continue;
++
++		addr = kgdb_break[i].bpt_addr;
++		error = kgdb_arch_set_breakpoint(addr,
++				kgdb_break[i].saved_instr);
++		if (error)
++			return error;
++
++		kgdb_flush_swbreak_addr(addr);
++		kgdb_break[i].state = BP_ACTIVE;
++	}
++	return 0;
++}
++
++static int kgdb_set_sw_break(unsigned long addr)
++{
++	int err = kgdb_validate_break_address(addr);
++	int breakno = -1;
++	int i;
++
++	if (err)
++		return err;
++
++	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++		if ((kgdb_break[i].state == BP_SET) &&
++					(kgdb_break[i].bpt_addr == addr))
++			return -EEXIST;
++	}
++	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++		if (kgdb_break[i].state == BP_REMOVED &&
++					kgdb_break[i].bpt_addr == addr) {
++			breakno = i;
++			break;
++		}
++	}
++
++	if (breakno == -1) {
++		for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++			if (kgdb_break[i].state == BP_UNDEFINED) {
++				breakno = i;
++				break;
++			}
++		}
++	}
++
++	if (breakno == -1)
++		return -E2BIG;
++
++	kgdb_break[breakno].state = BP_SET;
++	kgdb_break[breakno].type = BP_BREAKPOINT;
++	kgdb_break[breakno].bpt_addr = addr;
++
++	return 0;
++}
++
++static int kgdb_deactivate_sw_breakpoints(void)
++{
++	unsigned long addr;
++	int error = 0;
++	int i;
++
++	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++		if (kgdb_break[i].state != BP_ACTIVE)
++			continue;
++		addr = kgdb_break[i].bpt_addr;
++		error = kgdb_arch_remove_breakpoint(addr,
++					kgdb_break[i].saved_instr);
++		if (error)
++			return error;
++
++		kgdb_flush_swbreak_addr(addr);
++		kgdb_break[i].state = BP_SET;
++	}
++	return 0;
++}
++
++static int kgdb_remove_sw_break(unsigned long addr)
++{
++	int i;
++
++	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++		if ((kgdb_break[i].state == BP_SET) &&
++				(kgdb_break[i].bpt_addr == addr)) {
++			kgdb_break[i].state = BP_REMOVED;
++			return 0;
++		}
++	}
++	return -ENOENT;
++}
++
++int kgdb_isremovedbreak(unsigned long addr)
++{
++	int i;
++
++	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++		if ((kgdb_break[i].state == BP_REMOVED) &&
++					(kgdb_break[i].bpt_addr == addr))
++			return 1;
++	}
++	return 0;
++}
++
++int remove_all_break(void)
++{
++	unsigned long addr;
++	int error;
++	int i;
++
++	/* Clear memory breakpoints. */
++	for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++		if (kgdb_break[i].state != BP_ACTIVE)
++			goto setundefined;
++		addr = kgdb_break[i].bpt_addr;
++		error = kgdb_arch_remove_breakpoint(addr,
++				kgdb_break[i].saved_instr);
++		if (error)
++			printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
++			   addr);
++setundefined:
++		kgdb_break[i].state = BP_UNDEFINED;
++	}
++
++	/* Clear hardware breakpoints. */
++	if (arch_kgdb_ops.remove_all_hw_break)
++		arch_kgdb_ops.remove_all_hw_break();
++
++	return 0;
++}
++
++/*
++ * Remap normal tasks to their real PID, idle tasks to -1 ... -NR_CPUs:
++ */
++static inline int shadow_pid(int realpid)
++{
++	if (realpid)
++		return realpid;
++
++	return -1-raw_smp_processor_id();
++}
++
++static char gdbmsgbuf[BUFMAX + 1];
++
++static void kgdb_msg_write(const char *s, int len)
++{
++	char *bufptr;
++	int wcount;
++	int i;
++
++	/* 'O'utput */
++	gdbmsgbuf[0] = 'O';
++
++	/* Fill and send buffers... */
++	while (len > 0) {
++		bufptr = gdbmsgbuf + 1;
++
++		/* Calculate how many this time */
++		if ((len << 1) > (BUFMAX - 2))
++			wcount = (BUFMAX - 2) >> 1;
++		else
++			wcount = len;
++
++		/* Pack in hex chars */
++		for (i = 0; i < wcount; i++)
++			bufptr = pack_hex_byte(bufptr, s[i]);
++		*bufptr = '\0';
++
++		/* Move up */
++		s += wcount;
++		len -= wcount;
++
++		/* Write packet */
++		put_packet(gdbmsgbuf);
++	}
++}
++
++/*
++ * Return true if there is a valid kgdb I/O module.  Also if no
++ * debugger is attached a message can be printed to the console about
++ * waiting for the debugger to attach.
++ *
++ * The print_wait argument is only to be true when called from inside
++ * the core kgdb_handle_exception, because it will wait for the
++ * debugger to attach.
++ */
++static int kgdb_io_ready(int print_wait)
++{
++	if (!kgdb_io_ops)
++		return 0;
++	if (kgdb_connected)
++		return 1;
++	if (atomic_read(&kgdb_setting_breakpoint))
++		return 1;
++	if (print_wait)
++		printk(KERN_CRIT "KGDB: Waiting for remote debugger\n");
++	return 1;
++}
++
++/*
++ * All the functions that start with gdb_cmd are the various
++ * operations to implement the handlers for the gdbserial protocol
++ * where KGDB is communicating with an external debugger
++ */
++
++/* Handle the '?' status packets */
++static void gdb_cmd_status(struct kgdb_state *ks)
++{
++	/*
++	 * We know that this packet is only sent
++	 * during initial connect.  So to be safe,
++	 * we clear out our breakpoints now in case
++	 * GDB is reconnecting.
++	 */
++	remove_all_break();
++
++	remcom_out_buffer[0] = 'S';
++	pack_hex_byte(&remcom_out_buffer[1], ks->signo);
++}
++
++/* Handle the 'g' get registers request */
++static void gdb_cmd_getregs(struct kgdb_state *ks)
++{
++	struct task_struct *thread;
++	void *local_debuggerinfo;
++	int i;
++
++	thread = kgdb_usethread;
++	if (!thread) {
++		thread = kgdb_info[ks->cpu].task;
++		local_debuggerinfo = kgdb_info[ks->cpu].debuggerinfo;
++	} else {
++		local_debuggerinfo = NULL;
++		for (i = 0; i < NR_CPUS; i++) {
++			/*
++			 * Try to find the task on some other
++			 * or possibly this node if we do not
++			 * find the matching task then we try
++			 * to approximate the results.
++			 */
++			if (thread == kgdb_info[i].task)
++				local_debuggerinfo = kgdb_info[i].debuggerinfo;
++		}
++	}
++
++	/*
++	 * All threads that don't have debuggerinfo should be
++	 * in __schedule() sleeping, since all other CPUs
++	 * are in kgdb_wait, and thus have debuggerinfo.
++	 */
++	if (local_debuggerinfo) {
++		pt_regs_to_gdb_regs(gdb_regs, local_debuggerinfo);
++	} else {
++		/*
++		 * Pull stuff saved during switch_to; nothing
++		 * else is accessible (or even particularly
++		 * relevant).
++		 *
++		 * This should be enough for a stack trace.
++		 */
++		sleeping_thread_to_gdb_regs(gdb_regs, thread);
++	}
++	kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer, NUMREGBYTES);
++}
++
++/* Handle the 'G' set registers request */
++static void gdb_cmd_setregs(struct kgdb_state *ks)
++{
++	kgdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs, NUMREGBYTES);
++
++	if (kgdb_usethread && kgdb_usethread != current) {
++		error_packet(remcom_out_buffer, -EINVAL);
++	} else {
++		gdb_regs_to_pt_regs(gdb_regs, ks->linux_regs);
++		strcpy(remcom_out_buffer, "OK");
++	}
++}
++
++/* Handle the 'm' memory read bytes */
++static void gdb_cmd_memread(struct kgdb_state *ks)
++{
++	char *ptr = &remcom_in_buffer[1];
++	unsigned long length;
++	unsigned long addr;
++	int err;
++
++	if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&
++					kgdb_hex2long(&ptr, &length) > 0) {
++		err = kgdb_mem2hex((char *)addr, remcom_out_buffer, length);
++		if (err)
++			error_packet(remcom_out_buffer, err);
++	} else {
++		error_packet(remcom_out_buffer, -EINVAL);
++	}
++}
++
++/* Handle the 'M' memory write bytes */
++static void gdb_cmd_memwrite(struct kgdb_state *ks)
++{
++	int err = write_mem_msg(0);
++
++	if (err)
++		error_packet(remcom_out_buffer, err);
++	else
++		strcpy(remcom_out_buffer, "OK");
++}
++
++/* Handle the 'X' memory binary write bytes */
++static void gdb_cmd_binwrite(struct kgdb_state *ks)
++{
++	int err = write_mem_msg(1);
++
++	if (err)
++		error_packet(remcom_out_buffer, err);
++	else
++		strcpy(remcom_out_buffer, "OK");
++}
++
++/* Handle the 'D' or 'k', detach or kill packets */
++static void gdb_cmd_detachkill(struct kgdb_state *ks)
++{
++	int error;
++
++	/* The detach case */
++	if (remcom_in_buffer[0] == 'D') {
++		error = remove_all_break();
++		if (error < 0) {
++			error_packet(remcom_out_buffer, error);
++		} else {
++			strcpy(remcom_out_buffer, "OK");
++			kgdb_connected = 0;
++		}
++		put_packet(remcom_out_buffer);
++	} else {
++		/*
++		 * Assume the kill case, with no exit code checking,
++		 * trying to force detach the debugger:
++		 */
++		remove_all_break();
++		kgdb_connected = 0;
++	}
++}
++
++/* Handle the 'R' reboot packets */
++static int gdb_cmd_reboot(struct kgdb_state *ks)
++{
++	/* For now, only honor R0 */
++	if (strcmp(remcom_in_buffer, "R0") == 0) {
++		printk(KERN_CRIT "Executing emergency reboot\n");
++		strcpy(remcom_out_buffer, "OK");
++		put_packet(remcom_out_buffer);
++
++		/*
++		 * Execution should not return from
++		 * machine_emergency_restart()
++		 */
++		machine_emergency_restart();
++		kgdb_connected = 0;
++
++		return 1;
++	}
++	return 0;
++}
++
++/* Handle the 'q' query packets */
++static void gdb_cmd_query(struct kgdb_state *ks)
++{
++	struct task_struct *thread;
++	unsigned char thref[8];
++	char *ptr;
++	int i;
++
++	switch (remcom_in_buffer[1]) {
++	case 's':
++	case 'f':
++		if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10)) {
++			error_packet(remcom_out_buffer, -EINVAL);
++			break;
++		}
++
++		if (remcom_in_buffer[1] == 'f')
++			ks->threadid = 1;
++
++		remcom_out_buffer[0] = 'm';
++		ptr = remcom_out_buffer + 1;
++
++		for (i = 0; i < 17; ks->threadid++) {
++			thread = getthread(ks->linux_regs, ks->threadid);
++			if (thread) {
++				int_to_threadref(thref, ks->threadid);
++				pack_threadid(ptr, thref);
++				ptr += BUF_THREAD_ID_SIZE;
++				*(ptr++) = ',';
++				i++;
++			}
++		}
++		*(--ptr) = '\0';
++		break;
++
++	case 'C':
++		/* Current thread id */
++		strcpy(remcom_out_buffer, "QC");
++		ks->threadid = shadow_pid(current->pid);
++		int_to_threadref(thref, ks->threadid);
++		pack_threadid(remcom_out_buffer + 2, thref);
++		break;
++	case 'T':
++		if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16)) {
++			error_packet(remcom_out_buffer, -EINVAL);
++			break;
++		}
++		ks->threadid = 0;
++		ptr = remcom_in_buffer + 17;
++		kgdb_hex2long(&ptr, &ks->threadid);
++		if (!getthread(ks->linux_regs, ks->threadid)) {
++			error_packet(remcom_out_buffer, -EINVAL);
++			break;
++		}
++		if (ks->threadid > 0) {
++			kgdb_mem2hex(getthread(ks->linux_regs,
++					ks->threadid)->comm,
++					remcom_out_buffer, 16);
++		} else {
++			static char tmpstr[23 + BUF_THREAD_ID_SIZE];
++
++			sprintf(tmpstr, "Shadow task %d for pid 0",
++					(int)(-ks->threadid-1));
++			kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr));
++		}
++		break;
++	}
++}
++
++/* Handle the 'H' task query packets */
++static void gdb_cmd_task(struct kgdb_state *ks)
++{
++	struct task_struct *thread;
++	char *ptr;
++
++	switch (remcom_in_buffer[1]) {
++	case 'g':
++		ptr = &remcom_in_buffer[2];
++		kgdb_hex2long(&ptr, &ks->threadid);
++		thread = getthread(ks->linux_regs, ks->threadid);
++		if (!thread && ks->threadid > 0) {
++			error_packet(remcom_out_buffer, -EINVAL);
++			break;
++		}
++		kgdb_usethread = thread;
++		ks->kgdb_usethreadid = ks->threadid;
++		strcpy(remcom_out_buffer, "OK");
++		break;
++	case 'c':
++		ptr = &remcom_in_buffer[2];
++		kgdb_hex2long(&ptr, &ks->threadid);
++		if (!ks->threadid) {
++			kgdb_contthread = NULL;
++		} else {
++			thread = getthread(ks->linux_regs, ks->threadid);
++			if (!thread && ks->threadid > 0) {
++				error_packet(remcom_out_buffer, -EINVAL);
++				break;
++			}
++			kgdb_contthread = thread;
++		}
++		strcpy(remcom_out_buffer, "OK");
++		break;
++	}
++}
++
++/* Handle the 'T' thread query packets */
++static void gdb_cmd_thread(struct kgdb_state *ks)
++{
++	char *ptr = &remcom_in_buffer[1];
++	struct task_struct *thread;
++
++	kgdb_hex2long(&ptr, &ks->threadid);
++	thread = getthread(ks->linux_regs, ks->threadid);
++	if (thread)
++		strcpy(remcom_out_buffer, "OK");
++	else
++		error_packet(remcom_out_buffer, -EINVAL);
++}
++
++/* Handle the 'z' or 'Z' breakpoint remove or set packets */
++static void gdb_cmd_break(struct kgdb_state *ks)
++{
++	/*
++	 * Since GDB-5.3, it's been drafted that '0' is a software
++	 * breakpoint, '1' is a hardware breakpoint, so let's do that.
++	 */
++	char *bpt_type = &remcom_in_buffer[1];
++	char *ptr = &remcom_in_buffer[2];
++	unsigned long addr;
++	unsigned long length;
++	int error = 0;
++
++	if (arch_kgdb_ops.set_hw_breakpoint && *bpt_type >= '1') {
++		/* Unsupported */
++		if (*bpt_type > '4')
++			return;
++	} else {
++		if (*bpt_type != '0' && *bpt_type != '1')
++			/* Unsupported. */
++			return;
++	}
++
++	/*
++	 * Test if this is a hardware breakpoint, and
++	 * if we support it:
++	 */
++	if (*bpt_type == '1' && !(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT))
++		/* Unsupported. */
++		return;
++
++	if (*(ptr++) != ',') {
++		error_packet(remcom_out_buffer, -EINVAL);
++		return;
++	}
++	if (!kgdb_hex2long(&ptr, &addr)) {
++		error_packet(remcom_out_buffer, -EINVAL);
++		return;
++	}
++	if (*(ptr++) != ',' ||
++		!kgdb_hex2long(&ptr, &length)) {
++		error_packet(remcom_out_buffer, -EINVAL);
++		return;
++	}
++
++	if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0')
++		error = kgdb_set_sw_break(addr);
++	else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0')
++		error = kgdb_remove_sw_break(addr);
++	else if (remcom_in_buffer[0] == 'Z')
++		error = arch_kgdb_ops.set_hw_breakpoint(addr,
++			(int)length, *bpt_type - '0');
++	else if (remcom_in_buffer[0] == 'z')
++		error = arch_kgdb_ops.remove_hw_breakpoint(addr,
++			(int) length, *bpt_type - '0');
++
++	if (error == 0)
++		strcpy(remcom_out_buffer, "OK");
++	else
++		error_packet(remcom_out_buffer, error);
++}
++
++/* Handle the 'C' signal / exception passing packets */
++static int gdb_cmd_exception_pass(struct kgdb_state *ks)
++{
++	/* C09 == pass exception
++	 * C15 == detach kgdb, pass exception
++	 */
++	if (remcom_in_buffer[1] == '0' && remcom_in_buffer[2] == '9') {
++
++		ks->pass_exception = 1;
++		remcom_in_buffer[0] = 'c';
++
++	} else if (remcom_in_buffer[1] == '1' && remcom_in_buffer[2] == '5') {
++
++		ks->pass_exception = 1;
++		remcom_in_buffer[0] = 'D';
++		remove_all_break();
++		kgdb_connected = 0;
++		return 1;
++
++	} else {
++		error_packet(remcom_out_buffer, -EINVAL);
++		return 0;
++	}
++
++	/* Indicate fall through */
++	return -1;
++}
++
++/*
++ * This function performs all gdbserial command procesing
++ */
++static int gdb_serial_stub(struct kgdb_state *ks)
++{
++	int error = 0;
++	int tmp;
++
++	/* Clear the out buffer. */
++	memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
++
++	if (kgdb_connected) {
++		unsigned char thref[8];
++		char *ptr;
++
++		/* Reply to host that an exception has occurred */
++		ptr = remcom_out_buffer;
++		*ptr++ = 'T';
++		ptr = pack_hex_byte(ptr, ks->signo);
++		ptr += strlen(strcpy(ptr, "thread:"));
++		int_to_threadref(thref, shadow_pid(current->pid));
++		ptr = pack_threadid(ptr, thref);
++		*ptr++ = ';';
++		put_packet(remcom_out_buffer);
++	}
++
++	kgdb_usethread = kgdb_info[ks->cpu].task;
++	ks->kgdb_usethreadid = shadow_pid(kgdb_info[ks->cpu].task->pid);
++	ks->pass_exception = 0;
++
++	while (1) {
++		error = 0;
++
++		/* Clear the out buffer. */
++		memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
++
++		get_packet(remcom_in_buffer);
++
++		switch (remcom_in_buffer[0]) {
++		case '?': /* gdbserial status */
++			gdb_cmd_status(ks);
++			break;
++		case 'g': /* return the value of the CPU registers */
++			gdb_cmd_getregs(ks);
++			break;
++		case 'G': /* set the value of the CPU registers - return OK */
++			gdb_cmd_setregs(ks);
++			break;
++		case 'm': /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
++			gdb_cmd_memread(ks);
++			break;
++		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */
++			gdb_cmd_memwrite(ks);
++			break;
++		case 'X': /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */
++			gdb_cmd_binwrite(ks);
++			break;
++			/* kill or detach. KGDB should treat this like a
++			 * continue.
++			 */
++		case 'D': /* Debugger detach */
++		case 'k': /* Debugger detach via kill */
++			gdb_cmd_detachkill(ks);
++			goto default_handle;
++		case 'R': /* Reboot */
++			if (gdb_cmd_reboot(ks))
++				goto default_handle;
++			break;
++		case 'q': /* query command */
++			gdb_cmd_query(ks);
++			break;
++		case 'H': /* task related */
++			gdb_cmd_task(ks);
++			break;
++		case 'T': /* Query thread status */
++			gdb_cmd_thread(ks);
++			break;
++		case 'z': /* Break point remove */
++		case 'Z': /* Break point set */
++			gdb_cmd_break(ks);
++			break;
++		case 'C': /* Exception passing */
++			tmp = gdb_cmd_exception_pass(ks);
++			if (tmp > 0)
++				goto default_handle;
++			if (tmp == 0)
++				break;
++			/* Fall through on tmp < 0 */
++		case 'c': /* Continue packet */
++		case 's': /* Single step packet */
++			if (kgdb_contthread && kgdb_contthread != current) {
++				/* Can't switch threads in kgdb */
++				error_packet(remcom_out_buffer, -EINVAL);
++				break;
++			}
++			kgdb_activate_sw_breakpoints();
++			/* Fall through to default processing */
++		default:
++default_handle:
++			error = kgdb_arch_handle_exception(ks->ex_vector,
++						ks->signo,
++						ks->err_code,
++						remcom_in_buffer,
++						remcom_out_buffer,
++						ks->linux_regs);
++			/*
++			 * Leave cmd processing on error, detach,
++			 * kill, continue, or single step.
++			 */
++			if (error >= 0 || remcom_in_buffer[0] == 'D' ||
++			    remcom_in_buffer[0] == 'k') {
++				error = 0;
++				goto kgdb_exit;
++			}
++
++		}
++
++		/* reply to the request */
++		put_packet(remcom_out_buffer);
++	}
++
++kgdb_exit:
++	if (ks->pass_exception)
++		error = 1;
++	return error;
++}
++
++static int kgdb_reenter_check(struct kgdb_state *ks)
++{
++	unsigned long addr;
++
++	if (atomic_read(&kgdb_active) != raw_smp_processor_id())
++		return 0;
++
++	/* Panic on recursive debugger calls: */
++	exception_level++;
++	addr = kgdb_arch_pc(ks->ex_vector, ks->linux_regs);
++	kgdb_deactivate_sw_breakpoints();
++
++	/*
++	 * If the break point removed ok at the place exception
++	 * occurred, try to recover and print a warning to the end
++	 * user because the user planted a breakpoint in a place that
++	 * KGDB needs in order to function.
++	 */
++	if (kgdb_remove_sw_break(addr) == 0) {
++		exception_level = 0;
++		kgdb_skipexception(ks->ex_vector, ks->linux_regs);
++		kgdb_activate_sw_breakpoints();
++		printk(KERN_CRIT "KGDB: re-enter error: breakpoint removed %lx\n",
++			addr);
++		WARN_ON_ONCE(1);
++
++		return 1;
++	}
++	remove_all_break();
++	kgdb_skipexception(ks->ex_vector, ks->linux_regs);
++
++	if (exception_level > 1) {
++		dump_stack();
++		panic("Recursive entry to debugger");
++	}
++
++	printk(KERN_CRIT "KGDB: re-enter exception: ALL breakpoints killed\n");
++	dump_stack();
++	panic("Recursive entry to debugger");
++
++	return 1;
++}
++
++/*
++ * kgdb_handle_exception() - main entry point from a kernel exception
++ *
++ * Locking hierarchy:
++ *	interface locks, if any (begin_session)
++ *	kgdb lock (kgdb_active)
++ */
++int
++kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
++{
++	struct kgdb_state kgdb_var;
++	struct kgdb_state *ks = &kgdb_var;
++	unsigned long flags;
++	int error = 0;
++	int i, cpu;
++
++	ks->cpu			= raw_smp_processor_id();
++	ks->ex_vector		= evector;
++	ks->signo		= signo;
++	ks->ex_vector		= evector;
++	ks->err_code		= ecode;
++	ks->kgdb_usethreadid	= 0;
++	ks->linux_regs		= regs;
++
++	if (kgdb_reenter_check(ks))
++		return 0; /* Ouch, double exception ! */
++
++acquirelock:
++	/*
++	 * Interrupts will be restored by the 'trap return' code, except when
++	 * single stepping.
++	 */
++	local_irq_save(flags);
++
++	cpu = raw_smp_processor_id();
++
++	/*
++	 * Acquire the kgdb_active lock:
++	 */
++	while (atomic_cmpxchg(&kgdb_active, -1, cpu) != -1)
++		cpu_relax();
++
++	/*
++	 * Do not start the debugger connection on this CPU if the last
++	 * instance of the exception handler wanted to come into the
++	 * debugger on a different CPU via a single step
++	 */
++	if (atomic_read(&kgdb_cpu_doing_single_step) != -1 &&
++	    atomic_read(&kgdb_cpu_doing_single_step) != cpu) {
++
++		atomic_set(&kgdb_active, -1);
++		clocksource_touch_watchdog();
++		local_irq_restore(flags);
++
++		goto acquirelock;
++	}
++
++	if (!kgdb_io_ready(1)) {
++		error = 1;
++		goto kgdb_restore; /* No I/O connection, so resume the system */
++	}
++
++	/*
++	 * Don't enter if we have hit a removed breakpoint.
++	 */
++	if (kgdb_skipexception(ks->ex_vector, ks->linux_regs))
++		goto kgdb_restore;
++
++	/* Call the I/O driver's pre_exception routine */
++	if (kgdb_io_ops->pre_exception)
++		kgdb_io_ops->pre_exception();
++
++	kgdb_info[ks->cpu].debuggerinfo = ks->linux_regs;
++	kgdb_info[ks->cpu].task = current;
++
++	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 || !kgdb_contthread) {
++		for (i = 0; i < NR_CPUS; i++)
++			atomic_set(&passive_cpu_wait[i], 1);
++	}
++
++	/*
++	 * spin_lock code is good enough as a barrier so we don't
++	 * need one here:
++	 */
++	atomic_set(&cpu_in_kgdb[ks->cpu], 1);
++
++#ifdef CONFIG_SMP
++	/* Signal the other CPUs to enter kgdb_wait() */
++	if ((!kgdb_single_step || !kgdb_contthread) && kgdb_do_roundup)
++		kgdb_roundup_cpus(flags);
++#endif
++
++	/*
++	 * Wait for the other CPUs to be notified and be waiting for us:
++	 */
++	for_each_online_cpu(i) {
++		while (!atomic_read(&cpu_in_kgdb[i]))
++			cpu_relax();
++	}
++
++	/*
++	 * At this point the primary processor is completely
++	 * in the debugger and all secondary CPUs are quiescent
++	 */
++	kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code);
++	kgdb_deactivate_sw_breakpoints();
++	kgdb_single_step = 0;
++	kgdb_contthread = NULL;
++	exception_level = 0;
++
++	/* Talk to debugger with gdbserial protocol */
++	error = gdb_serial_stub(ks);
++
++	/* Call the I/O driver's post_exception routine */
++	if (kgdb_io_ops->post_exception)
++		kgdb_io_ops->post_exception();
++
++	kgdb_info[ks->cpu].debuggerinfo = NULL;
++	kgdb_info[ks->cpu].task = NULL;
++	atomic_set(&cpu_in_kgdb[ks->cpu], 0);
++
++	if (!kgdb_single_step || !kgdb_contthread) {
++		for (i = NR_CPUS-1; i >= 0; i--)
++			atomic_set(&passive_cpu_wait[i], 0);
++		/*
++		 * Wait till all the CPUs have quit
++		 * from the debugger.
++		 */
++		for_each_online_cpu(i) {
++			while (atomic_read(&cpu_in_kgdb[i]))
++				cpu_relax();
++		}
++	}
++
++kgdb_restore:
++	/* Free kgdb_active */
++	atomic_set(&kgdb_active, -1);
++	clocksource_touch_watchdog();
++	local_irq_restore(flags);
++
++	return error;
++}
++
++int kgdb_nmicallback(int cpu, void *regs)
++{
++#ifdef CONFIG_SMP
++	if (!atomic_read(&cpu_in_kgdb[cpu]) &&
++			atomic_read(&kgdb_active) != cpu &&
++			atomic_read(&cpu_in_kgdb[atomic_read(&kgdb_active)])) {
++		kgdb_wait((struct pt_regs *)regs);
++		return 0;
++	}
++#endif
++	return 1;
++}
++
++void kgdb_console_write(struct console *co, const char *s, unsigned count)
++{
++	unsigned long flags;
++
++	/* If we're debugging, or KGDB has not connected, don't try
++	 * and print. */
++	if (!kgdb_connected || atomic_read(&kgdb_active) != -1)
++		return;
++
++	local_irq_save(flags);
++	kgdb_msg_write(s, count);
++	local_irq_restore(flags);
++}
++
++static struct console kgdbcons = {
++	.name		= "kgdb",
++	.write		= kgdb_console_write,
++	.flags		= CON_PRINTBUFFER | CON_ENABLED,
++	.index		= -1,
++};
++
++#ifdef CONFIG_MAGIC_SYSRQ
++static void sysrq_handle_gdb(int key, struct tty_struct *tty)
++{
++	if (!kgdb_io_ops) {
++		printk(KERN_CRIT "ERROR: No KGDB I/O module available\n");
++		return;
++	}
++	if (!kgdb_connected)
++		printk(KERN_CRIT "Entering KGDB\n");
++
++	kgdb_breakpoint();
++}
++
++static struct sysrq_key_op sysrq_gdb_op = {
++	.handler	= sysrq_handle_gdb,
++	.help_msg	= "Gdb",
++	.action_msg	= "GDB",
++};
++#endif
++
++static void kgdb_register_callbacks(void)
++{
++	if (!kgdb_io_module_registered) {
++		kgdb_io_module_registered = 1;
++		kgdb_arch_init();
++#ifdef CONFIG_MAGIC_SYSRQ
++		register_sysrq_key('g', &sysrq_gdb_op);
++#endif
++		if (kgdb_use_con && !kgdb_con_registered) {
++			register_console(&kgdbcons);
++			kgdb_con_registered = 1;
++		}
++	}
++}
++
++static void kgdb_unregister_callbacks(void)
++{
++	/*
++	 * When this routine is called KGDB should unregister from the
++	 * panic handler and clean up, making sure it is not handling any
++	 * break exceptions at the time.
++	 */
++	if (kgdb_io_module_registered) {
++		kgdb_io_module_registered = 0;
++		kgdb_arch_exit();
++#ifdef CONFIG_MAGIC_SYSRQ
++		unregister_sysrq_key('g', &sysrq_gdb_op);
++#endif
++		if (kgdb_con_registered) {
++			unregister_console(&kgdbcons);
++			kgdb_con_registered = 0;
++		}
++	}
++}
++
++static void kgdb_initial_breakpoint(void)
++{
++	kgdb_break_asap = 0;
++
++	printk(KERN_CRIT "kgdb: Waiting for connection from remote gdb...\n");
++	kgdb_breakpoint();
++}
++
++/**
++ *	kgdb_register_io_module - register KGDB IO module
++ *	@new_kgdb_io_ops: the io ops vector
++ *
++ *	Register it with the KGDB core.
++ */
++int kgdb_register_io_module(struct kgdb_io *new_kgdb_io_ops)
++{
++	int err;
++
++	spin_lock(&kgdb_registration_lock);
++
++	if (kgdb_io_ops) {
++		spin_unlock(&kgdb_registration_lock);
++
++		printk(KERN_ERR "kgdb: Another I/O driver is already "
++				"registered with KGDB.\n");
++		return -EBUSY;
++	}
++
++	if (new_kgdb_io_ops->init) {
++		err = new_kgdb_io_ops->init();
++		if (err) {
++			spin_unlock(&kgdb_registration_lock);
++			return err;
++		}
++	}
++
++	kgdb_io_ops = new_kgdb_io_ops;
++
++	spin_unlock(&kgdb_registration_lock);
++
++	printk(KERN_INFO "kgdb: Registered I/O driver %s.\n",
++	       new_kgdb_io_ops->name);
++
++	/* Arm KGDB now. */
++	kgdb_register_callbacks();
++
++	if (kgdb_break_asap)
++		kgdb_initial_breakpoint();
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(kgdb_register_io_module);
++
++/**
++ *	kkgdb_unregister_io_module - unregister KGDB IO module
++ *	@old_kgdb_io_ops: the io ops vector
++ *
++ *	Unregister it with the KGDB core.
++ */
++void kgdb_unregister_io_module(struct kgdb_io *old_kgdb_io_ops)
++{
++	BUG_ON(kgdb_connected);
++
++	/*
++	 * KGDB is no longer able to communicate out, so
++	 * unregister our callbacks and reset state.
++	 */
++	kgdb_unregister_callbacks();
++
++	spin_lock(&kgdb_registration_lock);
++
++	WARN_ON_ONCE(kgdb_io_ops != old_kgdb_io_ops);
++	kgdb_io_ops = NULL;
++
++	spin_unlock(&kgdb_registration_lock);
++
++	printk(KERN_INFO
++		"kgdb: Unregistered I/O driver %s, debugger disabled.\n",
++		old_kgdb_io_ops->name);
++}
++EXPORT_SYMBOL_GPL(kgdb_unregister_io_module);
++
++/**
++ * kgdb_breakpoint - generate breakpoint exception
++ *
++ * This function will generate a breakpoint exception.  It is used at the
++ * beginning of a program to sync up with a debugger and can be used
++ * otherwise as a quick means to stop program execution and "break" into
++ * the debugger.
++ */
++void kgdb_breakpoint(void)
++{
++	atomic_set(&kgdb_setting_breakpoint, 1);
++	wmb(); /* Sync point before breakpoint */
++	arch_kgdb_breakpoint();
++	wmb(); /* Sync point after breakpoint */
++	atomic_set(&kgdb_setting_breakpoint, 0);
++}
++EXPORT_SYMBOL_GPL(kgdb_breakpoint);
++
++static int __init opt_kgdb_wait(char *str)
++{
++	kgdb_break_asap = 1;
++
++	if (kgdb_io_module_registered)
++		kgdb_initial_breakpoint();
++
++	return 0;
++}
++
++early_param("kgdbwait", opt_kgdb_wait);
+diff --git a/kernel/kmod.c b/kernel/kmod.c
+index 22be3ff..e276404 100644
+--- a/kernel/kmod.c
++++ b/kernel/kmod.c
+@@ -165,7 +165,7 @@ static int ____call_usermodehelper(void *data)
+ 	}
+ 
+ 	/* We can run anywhere, unlike our parent keventd(). */
+-	set_cpus_allowed(current, CPU_MASK_ALL);
++	set_cpus_allowed_ptr(current, CPU_MASK_ALL_PTR);
+ 
+ 	/*
+ 	 * Our parent is keventd, which runs with elevated scheduling priority.
+diff --git a/kernel/kthread.c b/kernel/kthread.c
+index 0ac8878..92cf693 100644
+--- a/kernel/kthread.c
++++ b/kernel/kthread.c
+@@ -13,7 +13,6 @@
+ #include <linux/file.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+ 
+ #define KTHREAD_NICE_LEVEL (-5)
+ 
+@@ -180,6 +179,7 @@ void kthread_bind(struct task_struct *k, unsigned int cpu)
+ 	wait_task_inactive(k);
+ 	set_task_cpu(k, cpu);
+ 	k->cpus_allowed = cpumask_of_cpu(cpu);
++	k->rt.nr_cpus_allowed = 1;
+ }
+ EXPORT_SYMBOL(kthread_bind);
+ 
+diff --git a/kernel/latencytop.c b/kernel/latencytop.c
+index b4e3c85..7c74dab 100644
+--- a/kernel/latencytop.c
++++ b/kernel/latencytop.c
+@@ -64,8 +64,8 @@ account_global_scheduler_latency(struct task_struct *tsk, struct latency_record
+ 		return;
+ 
+ 	for (i = 0; i < MAXLR; i++) {
+-		int q;
+-		int same = 1;
++		int q, same = 1;
++
+ 		/* Nothing stored: */
+ 		if (!latency_record[i].backtrace[0]) {
+ 			if (firstnonnull > i)
+@@ -73,12 +73,15 @@ account_global_scheduler_latency(struct task_struct *tsk, struct latency_record
+ 			continue;
+ 		}
+ 		for (q = 0 ; q < LT_BACKTRACEDEPTH ; q++) {
+-			if (latency_record[i].backtrace[q] !=
+-				lat->backtrace[q])
++			unsigned long record = lat->backtrace[q];
++
++			if (latency_record[i].backtrace[q] != record) {
+ 				same = 0;
+-			if (same && lat->backtrace[q] == 0)
+ 				break;
+-			if (same && lat->backtrace[q] == ULONG_MAX)
++			}
++
++			/* 0 and ULONG_MAX entries mean end of backtrace: */
++			if (record == 0 || record == ULONG_MAX)
+ 				break;
+ 		}
+ 		if (same) {
+@@ -143,14 +146,18 @@ account_scheduler_latency(struct task_struct *tsk, int usecs, int inter)
+ 	for (i = 0; i < LT_SAVECOUNT ; i++) {
+ 		struct latency_record *mylat;
+ 		int same = 1;
++
+ 		mylat = &tsk->latency_record[i];
+ 		for (q = 0 ; q < LT_BACKTRACEDEPTH ; q++) {
+-			if (mylat->backtrace[q] !=
+-				lat.backtrace[q])
++			unsigned long record = lat.backtrace[q];
++
++			if (mylat->backtrace[q] != record) {
+ 				same = 0;
+-			if (same && lat.backtrace[q] == 0)
+ 				break;
+-			if (same && lat.backtrace[q] == ULONG_MAX)
++			}
++
++			/* 0 and ULONG_MAX entries mean end of backtrace: */
++			if (record == 0 || record == ULONG_MAX)
+ 				break;
+ 		}
+ 		if (same) {
+diff --git a/kernel/module.c b/kernel/module.c
+index 5d437bf..8d6cccc 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -43,7 +43,6 @@
+ #include <linux/mutex.h>
+ #include <linux/unwind.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/cacheflush.h>
+ #include <linux/license.h>
+ #include <asm/sections.h>
+@@ -664,7 +663,7 @@ static void free_module(struct module *mod);
+ 
+ static void wait_for_zero_refcount(struct module *mod)
+ {
+-	/* Since we might sleep for some time, drop the semaphore first */
++	/* Since we might sleep for some time, release the mutex first */
+ 	mutex_unlock(&module_mutex);
+ 	for (;;) {
+ 		DEBUGP("Looking at refcount...\n");
+diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
+index 2eae91f..ae5c6c1 100644
+--- a/kernel/posix-cpu-timers.c
++++ b/kernel/posix-cpu-timers.c
+@@ -1087,45 +1087,45 @@ static void check_process_timers(struct task_struct *tsk,
+ 	maxfire = 20;
+ 	prof_expires = cputime_zero;
+ 	while (!list_empty(timers)) {
+-		struct cpu_timer_list *t = list_first_entry(timers,
++		struct cpu_timer_list *tl = list_first_entry(timers,
+ 						      struct cpu_timer_list,
+ 						      entry);
+-		if (!--maxfire || cputime_lt(ptime, t->expires.cpu)) {
+-			prof_expires = t->expires.cpu;
++		if (!--maxfire || cputime_lt(ptime, tl->expires.cpu)) {
++			prof_expires = tl->expires.cpu;
+ 			break;
+ 		}
+-		t->firing = 1;
+-		list_move_tail(&t->entry, firing);
++		tl->firing = 1;
++		list_move_tail(&tl->entry, firing);
+ 	}
+ 
+ 	++timers;
+ 	maxfire = 20;
+ 	virt_expires = cputime_zero;
+ 	while (!list_empty(timers)) {
+-		struct cpu_timer_list *t = list_first_entry(timers,
++		struct cpu_timer_list *tl = list_first_entry(timers,
+ 						      struct cpu_timer_list,
+ 						      entry);
+-		if (!--maxfire || cputime_lt(utime, t->expires.cpu)) {
+-			virt_expires = t->expires.cpu;
++		if (!--maxfire || cputime_lt(utime, tl->expires.cpu)) {
++			virt_expires = tl->expires.cpu;
+ 			break;
+ 		}
+-		t->firing = 1;
+-		list_move_tail(&t->entry, firing);
++		tl->firing = 1;
++		list_move_tail(&tl->entry, firing);
+ 	}
+ 
+ 	++timers;
+ 	maxfire = 20;
+ 	sched_expires = 0;
+ 	while (!list_empty(timers)) {
+-		struct cpu_timer_list *t = list_first_entry(timers,
++		struct cpu_timer_list *tl = list_first_entry(timers,
+ 						      struct cpu_timer_list,
+ 						      entry);
+-		if (!--maxfire || sum_sched_runtime < t->expires.sched) {
+-			sched_expires = t->expires.sched;
++		if (!--maxfire || sum_sched_runtime < tl->expires.sched) {
++			sched_expires = tl->expires.sched;
+ 			break;
+ 		}
+-		t->firing = 1;
+-		list_move_tail(&t->entry, firing);
++		tl->firing = 1;
++		list_move_tail(&tl->entry, firing);
+ 	}
+ 
+ 	/*
+diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
+index a9b0420..8476956 100644
+--- a/kernel/posix-timers.c
++++ b/kernel/posix-timers.c
+@@ -37,7 +37,6 @@
+ #include <linux/mutex.h>
+ 
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/list.h>
+ #include <linux/init.h>
+ #include <linux/compiler.h>
+diff --git a/kernel/profile.c b/kernel/profile.c
+index 3b7a1b0..606d738 100644
+--- a/kernel/profile.c
++++ b/kernel/profile.c
+@@ -23,7 +23,6 @@
+ #include <linux/highmem.h>
+ #include <linux/mutex.h>
+ #include <asm/sections.h>
+-#include <asm/semaphore.h>
+ #include <asm/irq_regs.h>
+ #include <asm/ptrace.h>
+ 
+diff --git a/kernel/ptrace.c b/kernel/ptrace.c
+index fdb34e8..67e392e 100644
+--- a/kernel/ptrace.c
++++ b/kernel/ptrace.c
+@@ -323,9 +323,8 @@ static int ptrace_setoptions(struct task_struct *child, long data)
+ 	return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
+ }
+ 
+-static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
++static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info)
+ {
+-	siginfo_t lastinfo;
+ 	int error = -ESRCH;
+ 
+ 	read_lock(&tasklist_lock);
+@@ -333,31 +332,25 @@ static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
+ 		error = -EINVAL;
+ 		spin_lock_irq(&child->sighand->siglock);
+ 		if (likely(child->last_siginfo != NULL)) {
+-			lastinfo = *child->last_siginfo;
++			*info = *child->last_siginfo;
+ 			error = 0;
+ 		}
+ 		spin_unlock_irq(&child->sighand->siglock);
+ 	}
+ 	read_unlock(&tasklist_lock);
+-	if (!error)
+-		return copy_siginfo_to_user(data, &lastinfo);
+ 	return error;
+ }
+ 
+-static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
++static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
+ {
+-	siginfo_t newinfo;
+ 	int error = -ESRCH;
+ 
+-	if (copy_from_user(&newinfo, data, sizeof (siginfo_t)))
+-		return -EFAULT;
+-
+ 	read_lock(&tasklist_lock);
+ 	if (likely(child->sighand != NULL)) {
+ 		error = -EINVAL;
+ 		spin_lock_irq(&child->sighand->siglock);
+ 		if (likely(child->last_siginfo != NULL)) {
+-			*child->last_siginfo = newinfo;
++			*child->last_siginfo = *info;
+ 			error = 0;
+ 		}
+ 		spin_unlock_irq(&child->sighand->siglock);
+@@ -424,6 +417,7 @@ int ptrace_request(struct task_struct *child, long request,
+ 		   long addr, long data)
+ {
+ 	int ret = -EIO;
++	siginfo_t siginfo;
+ 
+ 	switch (request) {
+ 	case PTRACE_PEEKTEXT:
+@@ -442,12 +436,22 @@ int ptrace_request(struct task_struct *child, long request,
+ 	case PTRACE_GETEVENTMSG:
+ 		ret = put_user(child->ptrace_message, (unsigned long __user *) data);
+ 		break;
++
+ 	case PTRACE_GETSIGINFO:
+-		ret = ptrace_getsiginfo(child, (siginfo_t __user *) data);
++		ret = ptrace_getsiginfo(child, &siginfo);
++		if (!ret)
++			ret = copy_siginfo_to_user((siginfo_t __user *) data,
++						   &siginfo);
+ 		break;
++
+ 	case PTRACE_SETSIGINFO:
+-		ret = ptrace_setsiginfo(child, (siginfo_t __user *) data);
++		if (copy_from_user(&siginfo, (siginfo_t __user *) data,
++				   sizeof siginfo))
++			ret = -EFAULT;
++		else
++			ret = ptrace_setsiginfo(child, &siginfo);
+ 		break;
++
+ 	case PTRACE_DETACH:	 /* detach a process that was attached. */
+ 		ret = ptrace_detach(child, data);
+ 		break;
+@@ -616,6 +620,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
+ {
+ 	compat_ulong_t __user *datap = compat_ptr(data);
+ 	compat_ulong_t word;
++	siginfo_t siginfo;
+ 	int ret;
+ 
+ 	switch (request) {
+@@ -638,6 +643,23 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
+ 		ret = put_user((compat_ulong_t) child->ptrace_message, datap);
+ 		break;
+ 
++	case PTRACE_GETSIGINFO:
++		ret = ptrace_getsiginfo(child, &siginfo);
++		if (!ret)
++			ret = copy_siginfo_to_user32(
++				(struct compat_siginfo __user *) datap,
++				&siginfo);
++		break;
++
++	case PTRACE_SETSIGINFO:
++		memset(&siginfo, 0, sizeof siginfo);
++		if (copy_siginfo_from_user32(
++			    &siginfo, (struct compat_siginfo __user *) datap))
++			ret = -EFAULT;
++		else
++			ret = ptrace_setsiginfo(child, &siginfo);
++		break;
++
+ 	default:
+ 		ret = ptrace_request(child, request, addr, data);
+ 	}
+diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c
+index e951701..e1cdf19 100644
+--- a/kernel/rcupreempt.c
++++ b/kernel/rcupreempt.c
+@@ -1007,10 +1007,10 @@ void __synchronize_sched(void)
+ 	if (sched_getaffinity(0, &oldmask) < 0)
+ 		oldmask = cpu_possible_map;
+ 	for_each_online_cpu(cpu) {
+-		sched_setaffinity(0, cpumask_of_cpu(cpu));
++		sched_setaffinity(0, &cpumask_of_cpu(cpu));
+ 		schedule();
+ 	}
+-	sched_setaffinity(0, oldmask);
++	sched_setaffinity(0, &oldmask);
+ }
+ EXPORT_SYMBOL_GPL(__synchronize_sched);
+ 
+diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
+index fd59982..47894f9 100644
+--- a/kernel/rcutorture.c
++++ b/kernel/rcutorture.c
+@@ -723,9 +723,10 @@ static int rcu_idle_cpu;	/* Force all torture tasks off this CPU */
+  */
+ static void rcu_torture_shuffle_tasks(void)
+ {
+-	cpumask_t tmp_mask = CPU_MASK_ALL;
++	cpumask_t tmp_mask;
+ 	int i;
+ 
++	cpus_setall(tmp_mask);
+ 	get_online_cpus();
+ 
+ 	/* No point in shuffling if there is only one online CPU (ex: UP) */
+@@ -737,25 +738,27 @@ static void rcu_torture_shuffle_tasks(void)
+ 	if (rcu_idle_cpu != -1)
+ 		cpu_clear(rcu_idle_cpu, tmp_mask);
+ 
+-	set_cpus_allowed(current, tmp_mask);
++	set_cpus_allowed_ptr(current, &tmp_mask);
+ 
+ 	if (reader_tasks) {
+ 		for (i = 0; i < nrealreaders; i++)
+ 			if (reader_tasks[i])
+-				set_cpus_allowed(reader_tasks[i], tmp_mask);
++				set_cpus_allowed_ptr(reader_tasks[i],
++						     &tmp_mask);
+ 	}
+ 
+ 	if (fakewriter_tasks) {
+ 		for (i = 0; i < nfakewriters; i++)
+ 			if (fakewriter_tasks[i])
+-				set_cpus_allowed(fakewriter_tasks[i], tmp_mask);
++				set_cpus_allowed_ptr(fakewriter_tasks[i],
++						     &tmp_mask);
+ 	}
+ 
+ 	if (writer_task)
+-		set_cpus_allowed(writer_task, tmp_mask);
++		set_cpus_allowed_ptr(writer_task, &tmp_mask);
+ 
+ 	if (stats_task)
+-		set_cpus_allowed(stats_task, tmp_mask);
++		set_cpus_allowed_ptr(stats_task, &tmp_mask);
+ 
+ 	if (rcu_idle_cpu == -1)
+ 		rcu_idle_cpu = num_online_cpus() - 1;
+diff --git a/kernel/resource.c b/kernel/resource.c
+index 82aea81..cee12cc 100644
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -486,6 +486,24 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t
+ 
+ EXPORT_SYMBOL(adjust_resource);
+ 
++/**
++ * resource_alignment - calculate resource's alignment
++ * @res: resource pointer
++ *
++ * Returns alignment on success, 0 (invalid alignment) on failure.
++ */
++resource_size_t resource_alignment(struct resource *res)
++{
++	switch (res->flags & (IORESOURCE_SIZEALIGN | IORESOURCE_STARTALIGN)) {
++	case IORESOURCE_SIZEALIGN:
++		return res->end - res->start + 1;
++	case IORESOURCE_STARTALIGN:
++		return res->start;
++	default:
++		return 0;
++	}
++}
++
+ /*
+  * This is compatibility stuff for IO resources.
+  *
+diff --git a/kernel/sched.c b/kernel/sched.c
+index 8dcdec6..740fb40 100644
+--- a/kernel/sched.c
++++ b/kernel/sched.c
+@@ -66,6 +66,10 @@
+ #include <linux/unistd.h>
+ #include <linux/pagemap.h>
+ #include <linux/hrtimer.h>
++#include <linux/tick.h>
++#include <linux/bootmem.h>
++#include <linux/debugfs.h>
++#include <linux/ctype.h>
+ 
+ #include <asm/tlb.h>
+ #include <asm/irq_regs.h>
+@@ -114,6 +118,11 @@ unsigned long long __attribute__((weak)) sched_clock(void)
+  */
+ #define DEF_TIMESLICE		(100 * HZ / 1000)
+ 
++/*
++ * single value that denotes runtime == period, ie unlimited time.
++ */
++#define RUNTIME_INF	((u64)~0ULL)
++
+ #ifdef CONFIG_SMP
+ /*
+  * Divide a load by a sched group cpu_power : (load / sg->__cpu_power)
+@@ -155,6 +164,84 @@ struct rt_prio_array {
+ 	struct list_head queue[MAX_RT_PRIO];
+ };
+ 
++struct rt_bandwidth {
++	/* nests inside the rq lock: */
++	spinlock_t		rt_runtime_lock;
++	ktime_t			rt_period;
++	u64			rt_runtime;
++	struct hrtimer		rt_period_timer;
++};
++
++static struct rt_bandwidth def_rt_bandwidth;
++
++static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun);
++
++static enum hrtimer_restart sched_rt_period_timer(struct hrtimer *timer)
++{
++	struct rt_bandwidth *rt_b =
++		container_of(timer, struct rt_bandwidth, rt_period_timer);
++	ktime_t now;
++	int overrun;
++	int idle = 0;
++
++	for (;;) {
++		now = hrtimer_cb_get_time(timer);
++		overrun = hrtimer_forward(timer, now, rt_b->rt_period);
++
++		if (!overrun)
++			break;
++
++		idle = do_sched_rt_period_timer(rt_b, overrun);
++	}
++
++	return idle ? HRTIMER_NORESTART : HRTIMER_RESTART;
++}
++
++static
++void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime)
++{
++	rt_b->rt_period = ns_to_ktime(period);
++	rt_b->rt_runtime = runtime;
++
++	spin_lock_init(&rt_b->rt_runtime_lock);
++
++	hrtimer_init(&rt_b->rt_period_timer,
++			CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++	rt_b->rt_period_timer.function = sched_rt_period_timer;
++	rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
++}
++
++static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
++{
++	ktime_t now;
++
++	if (rt_b->rt_runtime == RUNTIME_INF)
++		return;
++
++	if (hrtimer_active(&rt_b->rt_period_timer))
++		return;
++
++	spin_lock(&rt_b->rt_runtime_lock);
++	for (;;) {
++		if (hrtimer_active(&rt_b->rt_period_timer))
++			break;
++
++		now = hrtimer_cb_get_time(&rt_b->rt_period_timer);
++		hrtimer_forward(&rt_b->rt_period_timer, now, rt_b->rt_period);
++		hrtimer_start(&rt_b->rt_period_timer,
++			      rt_b->rt_period_timer.expires,
++			      HRTIMER_MODE_ABS);
++	}
++	spin_unlock(&rt_b->rt_runtime_lock);
++}
++
++#ifdef CONFIG_RT_GROUP_SCHED
++static void destroy_rt_bandwidth(struct rt_bandwidth *rt_b)
++{
++	hrtimer_cancel(&rt_b->rt_period_timer);
++}
++#endif
++
+ #ifdef CONFIG_GROUP_SCHED
+ 
+ #include <linux/cgroup.h>
+@@ -181,29 +268,39 @@ struct task_group {
+ 	struct sched_rt_entity **rt_se;
+ 	struct rt_rq **rt_rq;
+ 
+-	u64 rt_runtime;
++	struct rt_bandwidth rt_bandwidth;
+ #endif
+ 
+ 	struct rcu_head rcu;
+ 	struct list_head list;
++
++	struct task_group *parent;
++	struct list_head siblings;
++	struct list_head children;
+ };
+ 
++#ifdef CONFIG_USER_SCHED
++
++/*
++ * Root task group.
++ * 	Every UID task group (including init_task_group aka UID-0) will
++ * 	be a child to this group.
++ */
++struct task_group root_task_group;
++
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ /* Default task group's sched entity on each cpu */
+ static DEFINE_PER_CPU(struct sched_entity, init_sched_entity);
+ /* Default task group's cfs_rq on each cpu */
+ static DEFINE_PER_CPU(struct cfs_rq, init_cfs_rq) ____cacheline_aligned_in_smp;
+-
+-static struct sched_entity *init_sched_entity_p[NR_CPUS];
+-static struct cfs_rq *init_cfs_rq_p[NR_CPUS];
+ #endif
+ 
+ #ifdef CONFIG_RT_GROUP_SCHED
+ static DEFINE_PER_CPU(struct sched_rt_entity, init_sched_rt_entity);
+ static DEFINE_PER_CPU(struct rt_rq, init_rt_rq) ____cacheline_aligned_in_smp;
+-
+-static struct sched_rt_entity *init_sched_rt_entity_p[NR_CPUS];
+-static struct rt_rq *init_rt_rq_p[NR_CPUS];
++#endif
++#else
++#define root_task_group init_task_group
+ #endif
+ 
+ /* task_group_lock serializes add/remove of task groups and also changes to
+@@ -221,23 +318,15 @@ static DEFINE_MUTEX(doms_cur_mutex);
+ # define INIT_TASK_GROUP_LOAD	NICE_0_LOAD
+ #endif
+ 
++#define MIN_SHARES	2
++
+ static int init_task_group_load = INIT_TASK_GROUP_LOAD;
+ #endif
+ 
+ /* Default task group.
+  *	Every task in system belong to this group at bootup.
+  */
+-struct task_group init_task_group = {
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+-	.se	= init_sched_entity_p,
+-	.cfs_rq = init_cfs_rq_p,
+-#endif
+-
+-#ifdef CONFIG_RT_GROUP_SCHED
+-	.rt_se	= init_sched_rt_entity_p,
+-	.rt_rq	= init_rt_rq_p,
+-#endif
+-};
++struct task_group init_task_group;
+ 
+ /* return group to which a task belongs */
+ static inline struct task_group *task_group(struct task_struct *p)
+@@ -297,8 +386,12 @@ struct cfs_rq {
+ 
+ 	struct rb_root tasks_timeline;
+ 	struct rb_node *rb_leftmost;
+-	struct rb_node *rb_load_balance_curr;
+-	/* 'curr' points to currently running entity on this cfs_rq.
++
++	struct list_head tasks;
++	struct list_head *balance_iterator;
++
++	/*
++	 * 'curr' points to currently running entity on this cfs_rq.
+ 	 * It is set to NULL otherwise (i.e when none are currently running).
+ 	 */
+ 	struct sched_entity *curr, *next;
+@@ -318,6 +411,43 @@ struct cfs_rq {
+ 	 */
+ 	struct list_head leaf_cfs_rq_list;
+ 	struct task_group *tg;	/* group that "owns" this runqueue */
++
++#ifdef CONFIG_SMP
++	unsigned long task_weight;
++	unsigned long shares;
++	/*
++	 * We need space to build a sched_domain wide view of the full task
++	 * group tree, in order to avoid depending on dynamic memory allocation
++	 * during the load balancing we place this in the per cpu task group
++	 * hierarchy. This limits the load balancing to one instance per cpu,
++	 * but more should not be needed anyway.
++	 */
++	struct aggregate_struct {
++		/*
++		 *   load = weight(cpus) * f(tg)
++		 *
++		 * Where f(tg) is the recursive weight fraction assigned to
++		 * this group.
++		 */
++		unsigned long load;
++
++		/*
++		 * part of the group weight distributed to this span.
++		 */
++		unsigned long shares;
++
++		/*
++		 * The sum of all runqueue weights within this span.
++		 */
++		unsigned long rq_weight;
++
++		/*
++		 * Weight contributed by tasks; this is the part we can
++		 * influence by moving tasks around.
++		 */
++		unsigned long task_weight;
++	} aggregate;
++#endif
+ #endif
+ };
+ 
+@@ -334,6 +464,9 @@ struct rt_rq {
+ #endif
+ 	int rt_throttled;
+ 	u64 rt_time;
++	u64 rt_runtime;
++	/* Nests inside the rq lock: */
++	spinlock_t rt_runtime_lock;
+ 
+ #ifdef CONFIG_RT_GROUP_SCHED
+ 	unsigned long rt_nr_boosted;
+@@ -396,6 +529,7 @@ struct rq {
+ 	unsigned long cpu_load[CPU_LOAD_IDX_MAX];
+ 	unsigned char idle_at_tick;
+ #ifdef CONFIG_NO_HZ
++	unsigned long last_tick_seen;
+ 	unsigned char in_nohz_recently;
+ #endif
+ 	/* capture load from *all* tasks on this cpu: */
+@@ -405,8 +539,6 @@ struct rq {
+ 
+ 	struct cfs_rq cfs;
+ 	struct rt_rq rt;
+-	u64 rt_period_expire;
+-	int rt_throttled;
+ 
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ 	/* list of leaf cfs_rq on this cpu: */
+@@ -499,6 +631,32 @@ static inline int cpu_of(struct rq *rq)
+ #endif
+ }
+ 
++#ifdef CONFIG_NO_HZ
++static inline bool nohz_on(int cpu)
++{
++	return tick_get_tick_sched(cpu)->nohz_mode != NOHZ_MODE_INACTIVE;
++}
++
++static inline u64 max_skipped_ticks(struct rq *rq)
++{
++	return nohz_on(cpu_of(rq)) ? jiffies - rq->last_tick_seen + 2 : 1;
++}
++
++static inline void update_last_tick_seen(struct rq *rq)
++{
++	rq->last_tick_seen = jiffies;
++}
++#else
++static inline u64 max_skipped_ticks(struct rq *rq)
++{
++	return 1;
++}
++
++static inline void update_last_tick_seen(struct rq *rq)
++{
++}
++#endif
++
+ /*
+  * Update the per-runqueue clock, as finegrained as the platform can give
+  * us, but without assuming monotonicity, etc.:
+@@ -523,9 +681,12 @@ static void __update_rq_clock(struct rq *rq)
+ 		/*
+ 		 * Catch too large forward jumps too:
+ 		 */
+-		if (unlikely(clock + delta > rq->tick_timestamp + TICK_NSEC)) {
+-			if (clock < rq->tick_timestamp + TICK_NSEC)
+-				clock = rq->tick_timestamp + TICK_NSEC;
++		u64 max_jump = max_skipped_ticks(rq) * TICK_NSEC;
++		u64 max_time = rq->tick_timestamp + max_jump;
++
++		if (unlikely(clock + delta > max_time)) {
++			if (clock < max_time)
++				clock = max_time;
+ 			else
+ 				clock++;
+ 			rq->clock_overflows++;
+@@ -561,23 +722,6 @@ static void update_rq_clock(struct rq *rq)
+ #define task_rq(p)		cpu_rq(task_cpu(p))
+ #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
+ 
+-unsigned long rt_needs_cpu(int cpu)
+-{
+-	struct rq *rq = cpu_rq(cpu);
+-	u64 delta;
+-
+-	if (!rq->rt_throttled)
+-		return 0;
+-
+-	if (rq->clock > rq->rt_period_expire)
+-		return 1;
+-
+-	delta = rq->rt_period_expire - rq->clock;
+-	do_div(delta, NSEC_PER_SEC / HZ);
+-
+-	return (unsigned long)delta;
+-}
+-
+ /*
+  * Tunables that become constants when CONFIG_SCHED_DEBUG is off:
+  */
+@@ -590,22 +734,137 @@ unsigned long rt_needs_cpu(int cpu)
+ /*
+  * Debugging: various feature bits
+  */
++
++#define SCHED_FEAT(name, enabled)	\
++	__SCHED_FEAT_##name ,
++
+ enum {
+-	SCHED_FEAT_NEW_FAIR_SLEEPERS	= 1,
+-	SCHED_FEAT_WAKEUP_PREEMPT	= 2,
+-	SCHED_FEAT_START_DEBIT		= 4,
+-	SCHED_FEAT_HRTICK		= 8,
+-	SCHED_FEAT_DOUBLE_TICK		= 16,
++#include "sched_features.h"
+ };
+ 
++#undef SCHED_FEAT
++
++#define SCHED_FEAT(name, enabled)	\
++	(1UL << __SCHED_FEAT_##name) * enabled |
++
+ const_debug unsigned int sysctl_sched_features =
+-		SCHED_FEAT_NEW_FAIR_SLEEPERS	* 1 |
+-		SCHED_FEAT_WAKEUP_PREEMPT	* 1 |
+-		SCHED_FEAT_START_DEBIT		* 1 |
+-		SCHED_FEAT_HRTICK		* 1 |
+-		SCHED_FEAT_DOUBLE_TICK		* 0;
++#include "sched_features.h"
++	0;
++
++#undef SCHED_FEAT
++
++#ifdef CONFIG_SCHED_DEBUG
++#define SCHED_FEAT(name, enabled)	\
++	#name ,
++
++__read_mostly char *sched_feat_names[] = {
++#include "sched_features.h"
++	NULL
++};
++
++#undef SCHED_FEAT
+ 
+-#define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x)
++int sched_feat_open(struct inode *inode, struct file *filp)
++{
++	filp->private_data = inode->i_private;
++	return 0;
++}
++
++static ssize_t
++sched_feat_read(struct file *filp, char __user *ubuf,
++		size_t cnt, loff_t *ppos)
++{
++	char *buf;
++	int r = 0;
++	int len = 0;
++	int i;
++
++	for (i = 0; sched_feat_names[i]; i++) {
++		len += strlen(sched_feat_names[i]);
++		len += 4;
++	}
++
++	buf = kmalloc(len + 2, GFP_KERNEL);
++	if (!buf)
++		return -ENOMEM;
++
++	for (i = 0; sched_feat_names[i]; i++) {
++		if (sysctl_sched_features & (1UL << i))
++			r += sprintf(buf + r, "%s ", sched_feat_names[i]);
++		else
++			r += sprintf(buf + r, "NO_%s ", sched_feat_names[i]);
++	}
++
++	r += sprintf(buf + r, "\n");
++	WARN_ON(r >= len + 2);
++
++	r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
++
++	kfree(buf);
++
++	return r;
++}
++
++static ssize_t
++sched_feat_write(struct file *filp, const char __user *ubuf,
++		size_t cnt, loff_t *ppos)
++{
++	char buf[64];
++	char *cmp = buf;
++	int neg = 0;
++	int i;
++
++	if (cnt > 63)
++		cnt = 63;
++
++	if (copy_from_user(&buf, ubuf, cnt))
++		return -EFAULT;
++
++	buf[cnt] = 0;
++
++	if (strncmp(buf, "NO_", 3) == 0) {
++		neg = 1;
++		cmp += 3;
++	}
++
++	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 (neg)
++				sysctl_sched_features &= ~(1UL << i);
++			else
++				sysctl_sched_features |= (1UL << i);
++			break;
++		}
++	}
++
++	if (!sched_feat_names[i])
++		return -EINVAL;
++
++	filp->f_pos += cnt;
++
++	return cnt;
++}
++
++static struct file_operations sched_feat_fops = {
++	.open	= sched_feat_open,
++	.read	= sched_feat_read,
++	.write	= sched_feat_write,
++};
++
++static __init int sched_init_debug(void)
++{
++	debugfs_create_file("sched_features", 0644, NULL, NULL,
++			&sched_feat_fops);
++
++	return 0;
++}
++late_initcall(sched_init_debug);
++
++#endif
++
++#define sched_feat(x) (sysctl_sched_features & (1UL << __SCHED_FEAT_##x))
+ 
+ /*
+  * Number of tasks to iterate in a single balance run.
+@@ -627,16 +886,52 @@ static __read_mostly int scheduler_running;
+  */
+ int sysctl_sched_rt_runtime = 950000;
+ 
+-/*
+- * single value that denotes runtime == period, ie unlimited time.
+- */
+-#define RUNTIME_INF	((u64)~0ULL)
++static inline u64 global_rt_period(void)
++{
++	return (u64)sysctl_sched_rt_period * NSEC_PER_USEC;
++}
++
++static inline u64 global_rt_runtime(void)
++{
++	if (sysctl_sched_rt_period < 0)
++		return RUNTIME_INF;
++
++	return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC;
++}
++
++static const unsigned long long time_sync_thresh = 100000;
++
++static DEFINE_PER_CPU(unsigned long long, time_offset);
++static DEFINE_PER_CPU(unsigned long long, prev_cpu_time);
+ 
+ /*
+- * For kernel-internal use: high-speed (but slightly incorrect) per-cpu
+- * clock constructed from sched_clock():
++ * Global lock which we take every now and then to synchronize
++ * the CPUs time. This method is not warp-safe, but it's good
++ * enough to synchronize slowly diverging time sources and thus
++ * it's good enough for tracing:
+  */
+-unsigned long long cpu_clock(int cpu)
++static DEFINE_SPINLOCK(time_sync_lock);
++static unsigned long long prev_global_time;
++
++static unsigned long long __sync_cpu_clock(cycles_t time, int cpu)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&time_sync_lock, flags);
++
++	if (time < prev_global_time) {
++		per_cpu(time_offset, cpu) += prev_global_time - time;
++		time = prev_global_time;
++	} else {
++		prev_global_time = time;
++	}
++
++	spin_unlock_irqrestore(&time_sync_lock, flags);
++
++	return time;
++}
++
++static unsigned long long __cpu_clock(int cpu)
+ {
+ 	unsigned long long now;
+ 	unsigned long flags;
+@@ -657,6 +952,24 @@ unsigned long long cpu_clock(int cpu)
+ 
+ 	return now;
+ }
++
++/*
++ * For kernel-internal use: high-speed (but slightly incorrect) per-cpu
++ * clock constructed from sched_clock():
++ */
++unsigned long long cpu_clock(int cpu)
++{
++	unsigned long long prev_cpu_time, time, delta_time;
++
++	prev_cpu_time = per_cpu(prev_cpu_time, cpu);
++	time = __cpu_clock(cpu) + per_cpu(time_offset, cpu);
++	delta_time = time-prev_cpu_time;
++
++	if (unlikely(delta_time > time_sync_thresh))
++		time = __sync_cpu_clock(time, cpu);
++
++	return time;
++}
+ EXPORT_SYMBOL_GPL(cpu_clock);
+ 
+ #ifndef prepare_arch_switch
+@@ -1116,6 +1429,9 @@ static void __resched_task(struct task_struct *p, int tif_bit)
+  */
+ #define SRR(x, y) (((x) + (1UL << ((y) - 1))) >> (y))
+ 
++/*
++ * delta *= weight / lw
++ */
+ static unsigned long
+ calc_delta_mine(unsigned long delta_exec, unsigned long weight,
+ 		struct load_weight *lw)
+@@ -1138,12 +1454,6 @@ calc_delta_mine(unsigned long delta_exec, unsigned long weight,
+ 	return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX);
+ }
+ 
+-static inline unsigned long
+-calc_delta_fair(unsigned long delta_exec, struct load_weight *lw)
+-{
+-	return calc_delta_mine(delta_exec, NICE_0_LOAD, lw);
+-}
+-
+ static inline void update_load_add(struct load_weight *lw, unsigned long inc)
+ {
+ 	lw->weight += inc;
+@@ -1241,11 +1551,347 @@ static void cpuacct_charge(struct task_struct *tsk, u64 cputime);
+ static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {}
+ #endif
+ 
++static inline void inc_cpu_load(struct rq *rq, unsigned long load)
++{
++	update_load_add(&rq->load, load);
++}
++
++static inline void dec_cpu_load(struct rq *rq, unsigned long load)
++{
++	update_load_sub(&rq->load, load);
++}
++
+ #ifdef CONFIG_SMP
+ static unsigned long source_load(int cpu, int type);
+ static unsigned long target_load(int cpu, int type);
+ static unsigned long cpu_avg_load_per_task(int cpu);
+ static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd);
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++
++/*
++ * Group load balancing.
++ *
++ * We calculate a few balance domain wide aggregate numbers; load and weight.
++ * Given the pictures below, and assuming each item has equal weight:
++ *
++ *         root          1 - thread
++ *         / | \         A - group
++ *        A  1  B
++ *       /|\   / \
++ *      C 2 D 3   4
++ *      |   |
++ *      5   6
++ *
++ * load:
++ *    A and B get 1/3-rd of the total load. C and D get 1/3-rd of A's 1/3-rd,
++ *    which equals 1/9-th of the total load.
++ *
++ * shares:
++ *    The weight of this group on the selected cpus.
++ *
++ * rq_weight:
++ *    Direct sum of all the cpu's their rq weight, e.g. A would get 3 while
++ *    B would get 2.
++ *
++ * task_weight:
++ *    Part of the rq_weight contributed by tasks; all groups except B would
++ *    get 1, B gets 2.
++ */
++
++static inline struct aggregate_struct *
++aggregate(struct task_group *tg, struct sched_domain *sd)
++{
++	return &tg->cfs_rq[sd->first_cpu]->aggregate;
++}
++
++typedef void (*aggregate_func)(struct task_group *, struct sched_domain *);
++
++/*
++ * Iterate the full tree, calling @down when first entering a node and @up when
++ * leaving it for the final time.
++ */
++static
++void aggregate_walk_tree(aggregate_func down, aggregate_func up,
++			 struct sched_domain *sd)
++{
++	struct task_group *parent, *child;
++
++	rcu_read_lock();
++	parent = &root_task_group;
++down:
++	(*down)(parent, sd);
++	list_for_each_entry_rcu(child, &parent->children, siblings) {
++		parent = child;
++		goto down;
++
++up:
++		continue;
++	}
++	(*up)(parent, sd);
++
++	child = parent;
++	parent = parent->parent;
++	if (parent)
++		goto up;
++	rcu_read_unlock();
++}
++
++/*
++ * Calculate the aggregate runqueue weight.
++ */
++static
++void aggregate_group_weight(struct task_group *tg, struct sched_domain *sd)
++{
++	unsigned long rq_weight = 0;
++	unsigned long task_weight = 0;
++	int i;
++
++	for_each_cpu_mask(i, sd->span) {
++		rq_weight += tg->cfs_rq[i]->load.weight;
++		task_weight += tg->cfs_rq[i]->task_weight;
++	}
++
++	aggregate(tg, sd)->rq_weight = rq_weight;
++	aggregate(tg, sd)->task_weight = task_weight;
++}
++
++/*
++ * Compute the weight of this group on the given cpus.
++ */
++static
++void aggregate_group_shares(struct task_group *tg, struct sched_domain *sd)
++{
++	unsigned long shares = 0;
++	int i;
++
++	for_each_cpu_mask(i, sd->span)
++		shares += tg->cfs_rq[i]->shares;
++
++	if ((!shares && aggregate(tg, sd)->rq_weight) || shares > tg->shares)
++		shares = tg->shares;
++
++	aggregate(tg, sd)->shares = shares;
++}
++
++/*
++ * Compute the load fraction assigned to this group, relies on the aggregate
++ * weight and this group's parent's load, i.e. top-down.
++ */
++static
++void aggregate_group_load(struct task_group *tg, struct sched_domain *sd)
++{
++	unsigned long load;
++
++	if (!tg->parent) {
++		int i;
++
++		load = 0;
++		for_each_cpu_mask(i, sd->span)
++			load += cpu_rq(i)->load.weight;
++
++	} else {
++		load = aggregate(tg->parent, sd)->load;
++
++		/*
++		 * shares is our weight in the parent's rq so
++		 * shares/parent->rq_weight gives our fraction of the load
++		 */
++		load *= aggregate(tg, sd)->shares;
++		load /= aggregate(tg->parent, sd)->rq_weight + 1;
++	}
++
++	aggregate(tg, sd)->load = load;
++}
++
++static void __set_se_shares(struct sched_entity *se, unsigned long shares);
++
++/*
++ * Calculate and set the cpu's group shares.
++ */
++static void
++__update_group_shares_cpu(struct task_group *tg, struct sched_domain *sd,
++			  int tcpu)
++{
++	int boost = 0;
++	unsigned long shares;
++	unsigned long rq_weight;
++
++	if (!tg->se[tcpu])
++		return;
++
++	rq_weight = tg->cfs_rq[tcpu]->load.weight;
++
++	/*
++	 * If there are currently no tasks on the cpu pretend there is one of
++	 * average load so that when a new task gets to run here it will not
++	 * get delayed by group starvation.
++	 */
++	if (!rq_weight) {
++		boost = 1;
++		rq_weight = NICE_0_LOAD;
++	}
++
++	/*
++	 *           \Sum shares * rq_weight
++	 * shares =  -----------------------
++	 *               \Sum rq_weight
++	 *
++	 */
++	shares = aggregate(tg, sd)->shares * rq_weight;
++	shares /= aggregate(tg, sd)->rq_weight + 1;
++
++	/*
++	 * record the actual number of shares, not the boosted amount.
++	 */
++	tg->cfs_rq[tcpu]->shares = boost ? 0 : shares;
++
++	if (shares < MIN_SHARES)
++		shares = MIN_SHARES;
++
++	__set_se_shares(tg->se[tcpu], shares);
++}
++
++/*
++ * Re-adjust the weights on the cpu the task came from and on the cpu the
++ * task went to.
++ */
++static void
++__move_group_shares(struct task_group *tg, struct sched_domain *sd,
++		    int scpu, int dcpu)
++{
++	unsigned long shares;
++
++	shares = tg->cfs_rq[scpu]->shares + tg->cfs_rq[dcpu]->shares;
++
++	__update_group_shares_cpu(tg, sd, scpu);
++	__update_group_shares_cpu(tg, sd, dcpu);
++
++	/*
++	 * ensure we never loose shares due to rounding errors in the
++	 * above redistribution.
++	 */
++	shares -= tg->cfs_rq[scpu]->shares + tg->cfs_rq[dcpu]->shares;
++	if (shares)
++		tg->cfs_rq[dcpu]->shares += shares;
++}
++
++/*
++ * Because changing a group's shares changes the weight of the super-group
++ * we need to walk up the tree and change all shares until we hit the root.
++ */
++static void
++move_group_shares(struct task_group *tg, struct sched_domain *sd,
++		  int scpu, int dcpu)
++{
++	while (tg) {
++		__move_group_shares(tg, sd, scpu, dcpu);
++		tg = tg->parent;
++	}
++}
++
++static
++void aggregate_group_set_shares(struct task_group *tg, struct sched_domain *sd)
++{
++	unsigned long shares = aggregate(tg, sd)->shares;
++	int i;
++
++	for_each_cpu_mask(i, sd->span) {
++		struct rq *rq = cpu_rq(i);
++		unsigned long flags;
++
++		spin_lock_irqsave(&rq->lock, flags);
++		__update_group_shares_cpu(tg, sd, i);
++		spin_unlock_irqrestore(&rq->lock, flags);
++	}
++
++	aggregate_group_shares(tg, sd);
++
++	/*
++	 * ensure we never loose shares due to rounding errors in the
++	 * above redistribution.
++	 */
++	shares -= aggregate(tg, sd)->shares;
++	if (shares) {
++		tg->cfs_rq[sd->first_cpu]->shares += shares;
++		aggregate(tg, sd)->shares += shares;
++	}
++}
++
++/*
++ * Calculate the accumulative weight and recursive load of each task group
++ * while walking down the tree.
++ */
++static
++void aggregate_get_down(struct task_group *tg, struct sched_domain *sd)
++{
++	aggregate_group_weight(tg, sd);
++	aggregate_group_shares(tg, sd);
++	aggregate_group_load(tg, sd);
++}
++
++/*
++ * Rebalance the cpu shares while walking back up the tree.
++ */
++static
++void aggregate_get_up(struct task_group *tg, struct sched_domain *sd)
++{
++	aggregate_group_set_shares(tg, sd);
++}
++
++static DEFINE_PER_CPU(spinlock_t, aggregate_lock);
++
++static void __init init_aggregate(void)
++{
++	int i;
++
++	for_each_possible_cpu(i)
++		spin_lock_init(&per_cpu(aggregate_lock, i));
++}
++
++static int get_aggregate(struct sched_domain *sd)
++{
++	if (!spin_trylock(&per_cpu(aggregate_lock, sd->first_cpu)))
++		return 0;
++
++	aggregate_walk_tree(aggregate_get_down, aggregate_get_up, sd);
++	return 1;
++}
++
++static void put_aggregate(struct sched_domain *sd)
++{
++	spin_unlock(&per_cpu(aggregate_lock, sd->first_cpu));
++}
++
++static void cfs_rq_set_shares(struct cfs_rq *cfs_rq, unsigned long shares)
++{
++	cfs_rq->shares = shares;
++}
++
++#else
++
++static inline void init_aggregate(void)
++{
++}
++
++static inline int get_aggregate(struct sched_domain *sd)
++{
++	return 0;
++}
++
++static inline void put_aggregate(struct sched_domain *sd)
++{
++}
++#endif
++
++#else /* CONFIG_SMP */
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++static void cfs_rq_set_shares(struct cfs_rq *cfs_rq, unsigned long shares)
++{
++}
++#endif
++
+ #endif /* CONFIG_SMP */
+ 
+ #include "sched_stats.h"
+@@ -1258,26 +1904,14 @@ static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd);
+ 
+ #define sched_class_highest (&rt_sched_class)
+ 
+-static inline void inc_load(struct rq *rq, const struct task_struct *p)
+-{
+-	update_load_add(&rq->load, p->se.load.weight);
+-}
+-
+-static inline void dec_load(struct rq *rq, const struct task_struct *p)
+-{
+-	update_load_sub(&rq->load, p->se.load.weight);
+-}
+-
+-static void inc_nr_running(struct task_struct *p, struct rq *rq)
++static void inc_nr_running(struct rq *rq)
+ {
+ 	rq->nr_running++;
+-	inc_load(rq, p);
+ }
+ 
+-static void dec_nr_running(struct task_struct *p, struct rq *rq)
++static void dec_nr_running(struct rq *rq)
+ {
+ 	rq->nr_running--;
+-	dec_load(rq, p);
+ }
+ 
+ static void set_load_weight(struct task_struct *p)
+@@ -1369,7 +2003,7 @@ static void activate_task(struct rq *rq, struct task_struct *p, int wakeup)
+ 		rq->nr_uninterruptible--;
+ 
+ 	enqueue_task(rq, p, wakeup);
+-	inc_nr_running(p, rq);
++	inc_nr_running(rq);
+ }
+ 
+ /*
+@@ -1381,7 +2015,7 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep)
+ 		rq->nr_uninterruptible++;
+ 
+ 	dequeue_task(rq, p, sleep);
+-	dec_nr_running(p, rq);
++	dec_nr_running(rq);
+ }
+ 
+ /**
+@@ -1438,7 +2072,7 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
+ 	/*
+ 	 * Buddy candidates are cache hot:
+ 	 */
+-	if (&p->se == cfs_rq_of(&p->se)->next)
++	if (sched_feat(CACHE_HOT_BUDDY) && (&p->se == cfs_rq_of(&p->se)->next))
+ 		return 1;
+ 
+ 	if (p->sched_class != &fair_sched_class)
+@@ -1728,17 +2362,17 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
+  * find_idlest_cpu - find the idlest cpu among the cpus in group.
+  */
+ static int
+-find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
++find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu,
++		cpumask_t *tmp)
+ {
+-	cpumask_t tmp;
+ 	unsigned long load, min_load = ULONG_MAX;
+ 	int idlest = -1;
+ 	int i;
+ 
+ 	/* Traverse only the allowed CPUs */
+-	cpus_and(tmp, group->cpumask, p->cpus_allowed);
++	cpus_and(*tmp, group->cpumask, p->cpus_allowed);
+ 
+-	for_each_cpu_mask(i, tmp) {
++	for_each_cpu_mask(i, *tmp) {
+ 		load = weighted_cpuload(i);
+ 
+ 		if (load < min_load || (load == min_load && i == this_cpu)) {
+@@ -1777,7 +2411,7 @@ static int sched_balance_self(int cpu, int flag)
+ 	}
+ 
+ 	while (sd) {
+-		cpumask_t span;
++		cpumask_t span, tmpmask;
+ 		struct sched_group *group;
+ 		int new_cpu, weight;
+ 
+@@ -1793,7 +2427,7 @@ static int sched_balance_self(int cpu, int flag)
+ 			continue;
+ 		}
+ 
+-		new_cpu = find_idlest_cpu(group, t, cpu);
++		new_cpu = find_idlest_cpu(group, t, cpu, &tmpmask);
+ 		if (new_cpu == -1 || new_cpu == cpu) {
+ 			/* Now try balancing at a lower domain level of cpu */
+ 			sd = sd->child;
+@@ -1839,6 +2473,9 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
+ 	long old_state;
+ 	struct rq *rq;
+ 
++	if (!sched_feat(SYNC_WAKEUPS))
++		sync = 0;
++
+ 	smp_wmb();
+ 	rq = task_rq_lock(p, &flags);
+ 	old_state = p->state;
+@@ -1955,6 +2592,7 @@ static void __sched_fork(struct task_struct *p)
+ 
+ 	INIT_LIST_HEAD(&p->rt.run_list);
+ 	p->se.on_rq = 0;
++	INIT_LIST_HEAD(&p->se.group_node);
+ 
+ #ifdef CONFIG_PREEMPT_NOTIFIERS
+ 	INIT_HLIST_HEAD(&p->preempt_notifiers);
+@@ -2030,7 +2668,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
+ 		 * management (if any):
+ 		 */
+ 		p->sched_class->task_new(rq, p);
+-		inc_nr_running(p, rq);
++		inc_nr_running(rq);
+ 	}
+ 	check_preempt_curr(rq, p);
+ #ifdef CONFIG_SMP
+@@ -2674,7 +3312,7 @@ static int move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ static struct sched_group *
+ find_busiest_group(struct sched_domain *sd, int this_cpu,
+ 		   unsigned long *imbalance, enum cpu_idle_type idle,
+-		   int *sd_idle, cpumask_t *cpus, int *balance)
++		   int *sd_idle, const cpumask_t *cpus, int *balance)
+ {
+ 	struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
+ 	unsigned long max_load, avg_load, total_load, this_load, total_pwr;
+@@ -2975,7 +3613,7 @@ ret:
+  */
+ static struct rq *
+ find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
+-		   unsigned long imbalance, cpumask_t *cpus)
++		   unsigned long imbalance, const cpumask_t *cpus)
+ {
+ 	struct rq *busiest = NULL, *rq;
+ 	unsigned long max_load = 0;
+@@ -3014,14 +3652,18 @@ find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
+  */
+ static int load_balance(int this_cpu, struct rq *this_rq,
+ 			struct sched_domain *sd, enum cpu_idle_type idle,
+-			int *balance)
++			int *balance, cpumask_t *cpus)
+ {
+ 	int ld_moved, all_pinned = 0, active_balance = 0, sd_idle = 0;
+ 	struct sched_group *group;
+ 	unsigned long imbalance;
+ 	struct rq *busiest;
+-	cpumask_t cpus = CPU_MASK_ALL;
+ 	unsigned long flags;
++	int unlock_aggregate;
++
++	cpus_setall(*cpus);
++
++	unlock_aggregate = get_aggregate(sd);
+ 
+ 	/*
+ 	 * When power savings policy is enabled for the parent domain, idle
+@@ -3037,7 +3679,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
+ 
+ redo:
+ 	group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle,
+-				   &cpus, balance);
++				   cpus, balance);
+ 
+ 	if (*balance == 0)
+ 		goto out_balanced;
+@@ -3047,7 +3689,7 @@ redo:
+ 		goto out_balanced;
+ 	}
+ 
+-	busiest = find_busiest_queue(group, idle, imbalance, &cpus);
++	busiest = find_busiest_queue(group, idle, imbalance, cpus);
+ 	if (!busiest) {
+ 		schedstat_inc(sd, lb_nobusyq[idle]);
+ 		goto out_balanced;
+@@ -3080,8 +3722,8 @@ redo:
+ 
+ 		/* All tasks on this runqueue were pinned by CPU affinity */
+ 		if (unlikely(all_pinned)) {
+-			cpu_clear(cpu_of(busiest), cpus);
+-			if (!cpus_empty(cpus))
++			cpu_clear(cpu_of(busiest), *cpus);
++			if (!cpus_empty(*cpus))
+ 				goto redo;
+ 			goto out_balanced;
+ 		}
+@@ -3138,8 +3780,9 @@ redo:
+ 
+ 	if (!ld_moved && !sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
+ 	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
+-		return -1;
+-	return ld_moved;
++		ld_moved = -1;
++
++	goto out;
+ 
+ out_balanced:
+ 	schedstat_inc(sd, lb_balanced[idle]);
+@@ -3154,8 +3797,13 @@ out_one_pinned:
+ 
+ 	if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
+ 	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
+-		return -1;
+-	return 0;
++		ld_moved = -1;
++	else
++		ld_moved = 0;
++out:
++	if (unlock_aggregate)
++		put_aggregate(sd);
++	return ld_moved;
+ }
+ 
+ /*
+@@ -3166,7 +3814,8 @@ out_one_pinned:
+  * this_rq is locked.
+  */
+ static int
+-load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
++load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd,
++			cpumask_t *cpus)
+ {
+ 	struct sched_group *group;
+ 	struct rq *busiest = NULL;
+@@ -3174,7 +3823,8 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
+ 	int ld_moved = 0;
+ 	int sd_idle = 0;
+ 	int all_pinned = 0;
+-	cpumask_t cpus = CPU_MASK_ALL;
++
++	cpus_setall(*cpus);
+ 
+ 	/*
+ 	 * When power savings policy is enabled for the parent domain, idle
+@@ -3189,14 +3839,13 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
+ 	schedstat_inc(sd, lb_count[CPU_NEWLY_IDLE]);
+ redo:
+ 	group = find_busiest_group(sd, this_cpu, &imbalance, CPU_NEWLY_IDLE,
+-				   &sd_idle, &cpus, NULL);
++				   &sd_idle, cpus, NULL);
+ 	if (!group) {
+ 		schedstat_inc(sd, lb_nobusyg[CPU_NEWLY_IDLE]);
+ 		goto out_balanced;
+ 	}
+ 
+-	busiest = find_busiest_queue(group, CPU_NEWLY_IDLE, imbalance,
+-				&cpus);
++	busiest = find_busiest_queue(group, CPU_NEWLY_IDLE, imbalance, cpus);
+ 	if (!busiest) {
+ 		schedstat_inc(sd, lb_nobusyq[CPU_NEWLY_IDLE]);
+ 		goto out_balanced;
+@@ -3218,8 +3867,8 @@ redo:
+ 		spin_unlock(&busiest->lock);
+ 
+ 		if (unlikely(all_pinned)) {
+-			cpu_clear(cpu_of(busiest), cpus);
+-			if (!cpus_empty(cpus))
++			cpu_clear(cpu_of(busiest), *cpus);
++			if (!cpus_empty(*cpus))
+ 				goto redo;
+ 		}
+ 	}
+@@ -3253,6 +3902,7 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
+ 	struct sched_domain *sd;
+ 	int pulled_task = -1;
+ 	unsigned long next_balance = jiffies + HZ;
++	cpumask_t tmpmask;
+ 
+ 	for_each_domain(this_cpu, sd) {
+ 		unsigned long interval;
+@@ -3262,8 +3912,8 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
+ 
+ 		if (sd->flags & SD_BALANCE_NEWIDLE)
+ 			/* If we've pulled tasks over stop searching: */
+-			pulled_task = load_balance_newidle(this_cpu,
+-								this_rq, sd);
++			pulled_task = load_balance_newidle(this_cpu, this_rq,
++							   sd, &tmpmask);
+ 
+ 		interval = msecs_to_jiffies(sd->balance_interval);
+ 		if (time_after(next_balance, sd->last_balance + interval))
+@@ -3422,6 +4072,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
+ 	/* Earliest time when we have to do rebalance again */
+ 	unsigned long next_balance = jiffies + 60*HZ;
+ 	int update_next_balance = 0;
++	cpumask_t tmp;
+ 
+ 	for_each_domain(cpu, sd) {
+ 		if (!(sd->flags & SD_LOAD_BALANCE))
+@@ -3445,7 +4096,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
+ 		}
+ 
+ 		if (time_after_eq(jiffies, sd->last_balance + interval)) {
+-			if (load_balance(cpu, rq, sd, idle, &balance)) {
++			if (load_balance(cpu, rq, sd, idle, &balance, &tmp)) {
+ 				/*
+ 				 * We've pulled tasks over so either we're no
+ 				 * longer idle, or one of our SMT siblings is
+@@ -3561,7 +4212,7 @@ static inline void trigger_load_balance(struct rq *rq, int cpu)
+ 			 */
+ 			int ilb = first_cpu(nohz.cpu_mask);
+ 
+-			if (ilb != NR_CPUS)
++			if (ilb < nr_cpu_ids)
+ 				resched_cpu(ilb);
+ 		}
+ 	}
+@@ -3765,9 +4416,9 @@ void scheduler_tick(void)
+ 		rq->clock_underflows++;
+ 	}
+ 	rq->tick_timestamp = rq->clock;
++	update_last_tick_seen(rq);
+ 	update_cpu_load(rq);
+ 	curr->sched_class->task_tick(rq, curr, 0);
+-	update_sched_rt_period(rq);
+ 	spin_unlock(&rq->lock);
+ 
+ #ifdef CONFIG_SMP
+@@ -4367,10 +5018,8 @@ void set_user_nice(struct task_struct *p, long nice)
+ 		goto out_unlock;
+ 	}
+ 	on_rq = p->se.on_rq;
+-	if (on_rq) {
++	if (on_rq)
+ 		dequeue_task(rq, p, 0);
+-		dec_load(rq, p);
+-	}
+ 
+ 	p->static_prio = NICE_TO_PRIO(nice);
+ 	set_load_weight(p);
+@@ -4380,7 +5029,6 @@ void set_user_nice(struct task_struct *p, long nice)
+ 
+ 	if (on_rq) {
+ 		enqueue_task(rq, p, 0);
+-		inc_load(rq, p);
+ 		/*
+ 		 * If the task increased its priority or is running and
+ 		 * lowered its priority, then reschedule its CPU:
+@@ -4602,7 +5250,7 @@ recheck:
+ 	 * Do not allow realtime tasks into groups that have no runtime
+ 	 * assigned.
+ 	 */
+-	if (rt_policy(policy) && task_group(p)->rt_runtime == 0)
++	if (rt_policy(policy) && task_group(p)->rt_bandwidth.rt_runtime == 0)
+ 		return -EPERM;
+ #endif
+ 
+@@ -4764,9 +5412,10 @@ out_unlock:
+ 	return retval;
+ }
+ 
+-long sched_setaffinity(pid_t pid, cpumask_t new_mask)
++long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
+ {
+ 	cpumask_t cpus_allowed;
++	cpumask_t new_mask = *in_mask;
+ 	struct task_struct *p;
+ 	int retval;
+ 
+@@ -4797,13 +5446,13 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask)
+ 	if (retval)
+ 		goto out_unlock;
+ 
+-	cpus_allowed = cpuset_cpus_allowed(p);
++	cpuset_cpus_allowed(p, &cpus_allowed);
+ 	cpus_and(new_mask, new_mask, cpus_allowed);
+  again:
+-	retval = set_cpus_allowed(p, new_mask);
++	retval = set_cpus_allowed_ptr(p, &new_mask);
+ 
+ 	if (!retval) {
+-		cpus_allowed = cpuset_cpus_allowed(p);
++		cpuset_cpus_allowed(p, &cpus_allowed);
+ 		if (!cpus_subset(new_mask, cpus_allowed)) {
+ 			/*
+ 			 * We must have raced with a concurrent cpuset
+@@ -4847,7 +5496,7 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
+ 	if (retval)
+ 		return retval;
+ 
+-	return sched_setaffinity(pid, new_mask);
++	return sched_setaffinity(pid, &new_mask);
+ }
+ 
+ /*
+@@ -5309,7 +5958,6 @@ static inline void sched_init_granularity(void)
+ 		sysctl_sched_latency = limit;
+ 
+ 	sysctl_sched_wakeup_granularity *= factor;
+-	sysctl_sched_batch_wakeup_granularity *= factor;
+ }
+ 
+ #ifdef CONFIG_SMP
+@@ -5338,7 +5986,7 @@ static inline void sched_init_granularity(void)
+  * task must not exit() & deallocate itself prematurely. The
+  * call is not atomic; no spinlocks may be held.
+  */
+-int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
++int set_cpus_allowed_ptr(struct task_struct *p, const cpumask_t *new_mask)
+ {
+ 	struct migration_req req;
+ 	unsigned long flags;
+@@ -5346,23 +5994,23 @@ int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
+ 	int ret = 0;
+ 
+ 	rq = task_rq_lock(p, &flags);
+-	if (!cpus_intersects(new_mask, cpu_online_map)) {
++	if (!cpus_intersects(*new_mask, cpu_online_map)) {
+ 		ret = -EINVAL;
+ 		goto out;
+ 	}
+ 
+ 	if (p->sched_class->set_cpus_allowed)
+-		p->sched_class->set_cpus_allowed(p, &new_mask);
++		p->sched_class->set_cpus_allowed(p, new_mask);
+ 	else {
+-		p->cpus_allowed = new_mask;
+-		p->rt.nr_cpus_allowed = cpus_weight(new_mask);
++		p->cpus_allowed = *new_mask;
++		p->rt.nr_cpus_allowed = cpus_weight(*new_mask);
+ 	}
+ 
+ 	/* Can the task run on the task's current CPU? If so, we're done */
+-	if (cpu_isset(task_cpu(p), new_mask))
++	if (cpu_isset(task_cpu(p), *new_mask))
+ 		goto out;
+ 
+-	if (migrate_task(p, any_online_cpu(new_mask), &req)) {
++	if (migrate_task(p, any_online_cpu(*new_mask), &req)) {
+ 		/* Need help from migration thread: drop lock and wait. */
+ 		task_rq_unlock(rq, &flags);
+ 		wake_up_process(rq->migration_thread);
+@@ -5375,7 +6023,7 @@ out:
+ 
+ 	return ret;
+ }
+-EXPORT_SYMBOL_GPL(set_cpus_allowed);
++EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr);
+ 
+ /*
+  * Move (not current) task off this cpu, onto dest cpu. We're doing
+@@ -5513,12 +6161,14 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
+ 		dest_cpu = any_online_cpu(mask);
+ 
+ 		/* On any allowed CPU? */
+-		if (dest_cpu == NR_CPUS)
++		if (dest_cpu >= nr_cpu_ids)
+ 			dest_cpu = any_online_cpu(p->cpus_allowed);
+ 
+ 		/* No more Mr. Nice Guy. */
+-		if (dest_cpu == NR_CPUS) {
+-			cpumask_t cpus_allowed = cpuset_cpus_allowed_locked(p);
++		if (dest_cpu >= nr_cpu_ids) {
++			cpumask_t cpus_allowed;
++
++			cpuset_cpus_allowed_locked(p, &cpus_allowed);
+ 			/*
+ 			 * Try to stay on the same cpuset, where the
+ 			 * current cpuset may be a subset of all cpus.
+@@ -5554,7 +6204,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
+  */
+ static void migrate_nr_uninterruptible(struct rq *rq_src)
+ {
+-	struct rq *rq_dest = cpu_rq(any_online_cpu(CPU_MASK_ALL));
++	struct rq *rq_dest = cpu_rq(any_online_cpu(*CPU_MASK_ALL_PTR));
+ 	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+@@ -5966,20 +6616,16 @@ void __init migration_init(void)
+ 
+ #ifdef CONFIG_SMP
+ 
+-/* Number of possible processor ids */
+-int nr_cpu_ids __read_mostly = NR_CPUS;
+-EXPORT_SYMBOL(nr_cpu_ids);
+-
+ #ifdef CONFIG_SCHED_DEBUG
+ 
+-static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level)
++static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
++				  cpumask_t *groupmask)
+ {
+ 	struct sched_group *group = sd->groups;
+-	cpumask_t groupmask;
+-	char str[NR_CPUS];
++	char str[256];
+ 
+-	cpumask_scnprintf(str, NR_CPUS, sd->span);
+-	cpus_clear(groupmask);
++	cpulist_scnprintf(str, sizeof(str), sd->span);
++	cpus_clear(*groupmask);
+ 
+ 	printk(KERN_DEBUG "%*s domain %d: ", level, "", level);
+ 
+@@ -6023,25 +6669,25 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level)
+ 			break;
+ 		}
+ 
+-		if (cpus_intersects(groupmask, group->cpumask)) {
++		if (cpus_intersects(*groupmask, group->cpumask)) {
+ 			printk(KERN_CONT "\n");
+ 			printk(KERN_ERR "ERROR: repeated CPUs\n");
+ 			break;
+ 		}
+ 
+-		cpus_or(groupmask, groupmask, group->cpumask);
++		cpus_or(*groupmask, *groupmask, group->cpumask);
+ 
+-		cpumask_scnprintf(str, NR_CPUS, group->cpumask);
++		cpulist_scnprintf(str, sizeof(str), group->cpumask);
+ 		printk(KERN_CONT " %s", str);
+ 
+ 		group = group->next;
+ 	} while (group != sd->groups);
+ 	printk(KERN_CONT "\n");
+ 
+-	if (!cpus_equal(sd->span, groupmask))
++	if (!cpus_equal(sd->span, *groupmask))
+ 		printk(KERN_ERR "ERROR: groups don't span domain->span\n");
+ 
+-	if (sd->parent && !cpus_subset(groupmask, sd->parent->span))
++	if (sd->parent && !cpus_subset(*groupmask, sd->parent->span))
+ 		printk(KERN_ERR "ERROR: parent span is not a superset "
+ 			"of domain->span\n");
+ 	return 0;
+@@ -6049,6 +6695,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level)
+ 
+ static void sched_domain_debug(struct sched_domain *sd, int cpu)
+ {
++	cpumask_t *groupmask;
+ 	int level = 0;
+ 
+ 	if (!sd) {
+@@ -6058,14 +6705,21 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
+ 
+ 	printk(KERN_DEBUG "CPU%d attaching sched-domain:\n", cpu);
+ 
++	groupmask = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
++	if (!groupmask) {
++		printk(KERN_DEBUG "Cannot load-balance (out of memory)\n");
++		return;
++	}
++
+ 	for (;;) {
+-		if (sched_domain_debug_one(sd, cpu, level))
++		if (sched_domain_debug_one(sd, cpu, level, groupmask))
+ 			break;
+ 		level++;
+ 		sd = sd->parent;
+ 		if (!sd)
+ 			break;
+ 	}
++	kfree(groupmask);
+ }
+ #else
+ # define sched_domain_debug(sd, cpu) do { } while (0)
+@@ -6253,30 +6907,33 @@ __setup("isolcpus=", isolated_cpu_setup);
+  * and ->cpu_power to 0.
+  */
+ static void
+-init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map,
++init_sched_build_groups(const cpumask_t *span, const cpumask_t *cpu_map,
+ 			int (*group_fn)(int cpu, const cpumask_t *cpu_map,
+-					struct sched_group **sg))
++					struct sched_group **sg,
++					cpumask_t *tmpmask),
++			cpumask_t *covered, cpumask_t *tmpmask)
+ {
+ 	struct sched_group *first = NULL, *last = NULL;
+-	cpumask_t covered = CPU_MASK_NONE;
+ 	int i;
+ 
+-	for_each_cpu_mask(i, span) {
++	cpus_clear(*covered);
++
++	for_each_cpu_mask(i, *span) {
+ 		struct sched_group *sg;
+-		int group = group_fn(i, cpu_map, &sg);
++		int group = group_fn(i, cpu_map, &sg, tmpmask);
+ 		int j;
+ 
+-		if (cpu_isset(i, covered))
++		if (cpu_isset(i, *covered))
+ 			continue;
+ 
+-		sg->cpumask = CPU_MASK_NONE;
++		cpus_clear(sg->cpumask);
+ 		sg->__cpu_power = 0;
+ 
+-		for_each_cpu_mask(j, span) {
+-			if (group_fn(j, cpu_map, NULL) != group)
++		for_each_cpu_mask(j, *span) {
++			if (group_fn(j, cpu_map, NULL, tmpmask) != group)
+ 				continue;
+ 
+-			cpu_set(j, covered);
++			cpu_set(j, *covered);
+ 			cpu_set(j, sg->cpumask);
+ 		}
+ 		if (!first)
+@@ -6302,7 +6959,7 @@ init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map,
+  *
+  * Should use nodemask_t.
+  */
+-static int find_next_best_node(int node, unsigned long *used_nodes)
++static int find_next_best_node(int node, nodemask_t *used_nodes)
+ {
+ 	int i, n, val, min_val, best_node = 0;
+ 
+@@ -6316,7 +6973,7 @@ static int find_next_best_node(int node, unsigned long *used_nodes)
+ 			continue;
+ 
+ 		/* Skip already used nodes */
+-		if (test_bit(n, used_nodes))
++		if (node_isset(n, *used_nodes))
+ 			continue;
+ 
+ 		/* Simple min distance search */
+@@ -6328,40 +6985,37 @@ static int find_next_best_node(int node, unsigned long *used_nodes)
+ 		}
+ 	}
+ 
+-	set_bit(best_node, used_nodes);
++	node_set(best_node, *used_nodes);
+ 	return best_node;
+ }
+ 
+ /**
+  * sched_domain_node_span - get a cpumask for a node's sched_domain
+  * @node: node whose cpumask we're constructing
+- * @size: number of nodes to include in this span
++ * @span: resulting cpumask
+  *
+  * Given a node, construct a good cpumask for its sched_domain to span. It
+  * should be one that prevents unnecessary balancing, but also spreads tasks
+  * out optimally.
+  */
+-static cpumask_t sched_domain_node_span(int node)
++static void sched_domain_node_span(int node, cpumask_t *span)
+ {
+-	DECLARE_BITMAP(used_nodes, MAX_NUMNODES);
+-	cpumask_t span, nodemask;
++	nodemask_t used_nodes;
++	node_to_cpumask_ptr(nodemask, node);
+ 	int i;
+ 
+-	cpus_clear(span);
+-	bitmap_zero(used_nodes, MAX_NUMNODES);
++	cpus_clear(*span);
++	nodes_clear(used_nodes);
+ 
+-	nodemask = node_to_cpumask(node);
+-	cpus_or(span, span, nodemask);
+-	set_bit(node, used_nodes);
++	cpus_or(*span, *span, *nodemask);
++	node_set(node, used_nodes);
+ 
+ 	for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {
+-		int next_node = find_next_best_node(node, used_nodes);
++		int next_node = find_next_best_node(node, &used_nodes);
+ 
+-		nodemask = node_to_cpumask(next_node);
+-		cpus_or(span, span, nodemask);
++		node_to_cpumask_ptr_next(nodemask, next_node);
++		cpus_or(*span, *span, *nodemask);
+ 	}
+-
+-	return span;
+ }
+ #endif
+ 
+@@ -6375,7 +7029,8 @@ static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
+ static DEFINE_PER_CPU(struct sched_group, sched_group_cpus);
+ 
+ static int
+-cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
++cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg,
++		 cpumask_t *unused)
+ {
+ 	if (sg)
+ 		*sg = &per_cpu(sched_group_cpus, cpu);
+@@ -6393,19 +7048,22 @@ static DEFINE_PER_CPU(struct sched_group, sched_group_core);
+ 
+ #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT)
+ static int
+-cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
++cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg,
++		  cpumask_t *mask)
+ {
+ 	int group;
+-	cpumask_t mask = per_cpu(cpu_sibling_map, cpu);
+-	cpus_and(mask, mask, *cpu_map);
+-	group = first_cpu(mask);
++
++	*mask = per_cpu(cpu_sibling_map, cpu);
++	cpus_and(*mask, *mask, *cpu_map);
++	group = first_cpu(*mask);
+ 	if (sg)
+ 		*sg = &per_cpu(sched_group_core, group);
+ 	return group;
+ }
+ #elif defined(CONFIG_SCHED_MC)
+ static int
+-cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
++cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg,
++		  cpumask_t *unused)
+ {
+ 	if (sg)
+ 		*sg = &per_cpu(sched_group_core, cpu);
+@@ -6417,17 +7075,18 @@ static DEFINE_PER_CPU(struct sched_domain, phys_domains);
+ static DEFINE_PER_CPU(struct sched_group, sched_group_phys);
+ 
+ static int
+-cpu_to_phys_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
++cpu_to_phys_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg,
++		  cpumask_t *mask)
+ {
+ 	int group;
+ #ifdef CONFIG_SCHED_MC
+-	cpumask_t mask = cpu_coregroup_map(cpu);
+-	cpus_and(mask, mask, *cpu_map);
+-	group = first_cpu(mask);
++	*mask = cpu_coregroup_map(cpu);
++	cpus_and(*mask, *mask, *cpu_map);
++	group = first_cpu(*mask);
+ #elif defined(CONFIG_SCHED_SMT)
+-	cpumask_t mask = per_cpu(cpu_sibling_map, cpu);
+-	cpus_and(mask, mask, *cpu_map);
+-	group = first_cpu(mask);
++	*mask = per_cpu(cpu_sibling_map, cpu);
++	cpus_and(*mask, *mask, *cpu_map);
++	group = first_cpu(*mask);
+ #else
+ 	group = cpu;
+ #endif
+@@ -6443,19 +7102,19 @@ cpu_to_phys_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
+  * gets dynamically allocated.
+  */
+ static DEFINE_PER_CPU(struct sched_domain, node_domains);
+-static struct sched_group **sched_group_nodes_bycpu[NR_CPUS];
++static struct sched_group ***sched_group_nodes_bycpu;
+ 
+ static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
+ static DEFINE_PER_CPU(struct sched_group, sched_group_allnodes);
+ 
+ static int cpu_to_allnodes_group(int cpu, const cpumask_t *cpu_map,
+-				 struct sched_group **sg)
++				 struct sched_group **sg, cpumask_t *nodemask)
+ {
+-	cpumask_t nodemask = node_to_cpumask(cpu_to_node(cpu));
+ 	int group;
+ 
+-	cpus_and(nodemask, nodemask, *cpu_map);
+-	group = first_cpu(nodemask);
++	*nodemask = node_to_cpumask(cpu_to_node(cpu));
++	cpus_and(*nodemask, *nodemask, *cpu_map);
++	group = first_cpu(*nodemask);
+ 
+ 	if (sg)
+ 		*sg = &per_cpu(sched_group_allnodes, group);
+@@ -6491,7 +7150,7 @@ static void init_numa_sched_groups_power(struct sched_group *group_head)
+ 
+ #ifdef CONFIG_NUMA
+ /* Free memory allocated for various sched_group structures */
+-static void free_sched_groups(const cpumask_t *cpu_map)
++static void free_sched_groups(const cpumask_t *cpu_map, cpumask_t *nodemask)
+ {
+ 	int cpu, i;
+ 
+@@ -6503,11 +7162,11 @@ static void free_sched_groups(const cpumask_t *cpu_map)
+ 			continue;
+ 
+ 		for (i = 0; i < MAX_NUMNODES; i++) {
+-			cpumask_t nodemask = node_to_cpumask(i);
+ 			struct sched_group *oldsg, *sg = sched_group_nodes[i];
+ 
+-			cpus_and(nodemask, nodemask, *cpu_map);
+-			if (cpus_empty(nodemask))
++			*nodemask = node_to_cpumask(i);
++			cpus_and(*nodemask, *nodemask, *cpu_map);
++			if (cpus_empty(*nodemask))
+ 				continue;
+ 
+ 			if (sg == NULL)
+@@ -6525,7 +7184,7 @@ next_sg:
+ 	}
+ }
+ #else
+-static void free_sched_groups(const cpumask_t *cpu_map)
++static void free_sched_groups(const cpumask_t *cpu_map, cpumask_t *nodemask)
+ {
+ }
+ #endif
+@@ -6583,13 +7242,106 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd)
+ }
+ 
+ /*
++ * Initializers for schedule domains
++ * Non-inlined to reduce accumulated stack pressure in build_sched_domains()
++ */
++
++#define	SD_INIT(sd, type)	sd_init_##type(sd)
++#define SD_INIT_FUNC(type)	\
++static noinline void sd_init_##type(struct sched_domain *sd)	\
++{								\
++	memset(sd, 0, sizeof(*sd));				\
++	*sd = SD_##type##_INIT;					\
++	sd->level = SD_LV_##type;				\
++}
++
++SD_INIT_FUNC(CPU)
++#ifdef CONFIG_NUMA
++ SD_INIT_FUNC(ALLNODES)
++ SD_INIT_FUNC(NODE)
++#endif
++#ifdef CONFIG_SCHED_SMT
++ SD_INIT_FUNC(SIBLING)
++#endif
++#ifdef CONFIG_SCHED_MC
++ SD_INIT_FUNC(MC)
++#endif
++
++/*
++ * To minimize stack usage kmalloc room for cpumasks and share the
++ * space as the usage in build_sched_domains() dictates.  Used only
++ * if the amount of space is significant.
++ */
++struct allmasks {
++	cpumask_t tmpmask;			/* make this one first */
++	union {
++		cpumask_t nodemask;
++		cpumask_t this_sibling_map;
++		cpumask_t this_core_map;
++	};
++	cpumask_t send_covered;
++
++#ifdef CONFIG_NUMA
++	cpumask_t domainspan;
++	cpumask_t covered;
++	cpumask_t notcovered;
++#endif
++};
++
++#if	NR_CPUS > 128
++#define	SCHED_CPUMASK_ALLOC		1
++#define	SCHED_CPUMASK_FREE(v)		kfree(v)
++#define	SCHED_CPUMASK_DECLARE(v)	struct allmasks *v
++#else
++#define	SCHED_CPUMASK_ALLOC		0
++#define	SCHED_CPUMASK_FREE(v)
++#define	SCHED_CPUMASK_DECLARE(v)	struct allmasks _v, *v = &_v
++#endif
++
++#define	SCHED_CPUMASK_VAR(v, a) 	cpumask_t *v = (cpumask_t *) \
++			((unsigned long)(a) + offsetof(struct allmasks, v))
++
++static int default_relax_domain_level = -1;
++
++static int __init setup_relax_domain_level(char *str)
++{
++	default_relax_domain_level = simple_strtoul(str, NULL, 0);
++	return 1;
++}
++__setup("relax_domain_level=", setup_relax_domain_level);
++
++static void set_domain_attribute(struct sched_domain *sd,
++				 struct sched_domain_attr *attr)
++{
++	int request;
++
++	if (!attr || attr->relax_domain_level < 0) {
++		if (default_relax_domain_level < 0)
++			return;
++		else
++			request = default_relax_domain_level;
++	} else
++		request = attr->relax_domain_level;
++	if (request < sd->level) {
++		/* turn off idle balance on this domain */
++		sd->flags &= ~(SD_WAKE_IDLE|SD_BALANCE_NEWIDLE);
++	} else {
++		/* turn on idle balance on this domain */
++		sd->flags |= (SD_WAKE_IDLE_FAR|SD_BALANCE_NEWIDLE);
++	}
++}
++
++/*
+  * Build sched domains for a given set of cpus and attach the sched domains
+  * to the individual cpus
+  */
+-static int build_sched_domains(const cpumask_t *cpu_map)
++static int __build_sched_domains(const cpumask_t *cpu_map,
++				 struct sched_domain_attr *attr)
+ {
+ 	int i;
+ 	struct root_domain *rd;
++	SCHED_CPUMASK_DECLARE(allmasks);
++	cpumask_t *tmpmask;
+ #ifdef CONFIG_NUMA
+ 	struct sched_group **sched_group_nodes = NULL;
+ 	int sd_allnodes = 0;
+@@ -6603,39 +7355,65 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ 		printk(KERN_WARNING "Can not alloc sched group node list\n");
+ 		return -ENOMEM;
+ 	}
+-	sched_group_nodes_bycpu[first_cpu(*cpu_map)] = sched_group_nodes;
+ #endif
+ 
+ 	rd = alloc_rootdomain();
+ 	if (!rd) {
+ 		printk(KERN_WARNING "Cannot alloc root domain\n");
++#ifdef CONFIG_NUMA
++		kfree(sched_group_nodes);
++#endif
++		return -ENOMEM;
++	}
++
++#if SCHED_CPUMASK_ALLOC
++	/* get space for all scratch cpumask variables */
++	allmasks = kmalloc(sizeof(*allmasks), GFP_KERNEL);
++	if (!allmasks) {
++		printk(KERN_WARNING "Cannot alloc cpumask array\n");
++		kfree(rd);
++#ifdef CONFIG_NUMA
++		kfree(sched_group_nodes);
++#endif
+ 		return -ENOMEM;
+ 	}
++#endif
++	tmpmask = (cpumask_t *)allmasks;
++
++
++#ifdef CONFIG_NUMA
++	sched_group_nodes_bycpu[first_cpu(*cpu_map)] = sched_group_nodes;
++#endif
+ 
+ 	/*
+ 	 * Set up domains for cpus specified by the cpu_map.
+ 	 */
+ 	for_each_cpu_mask(i, *cpu_map) {
+ 		struct sched_domain *sd = NULL, *p;
+-		cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
++		SCHED_CPUMASK_VAR(nodemask, allmasks);
+ 
+-		cpus_and(nodemask, nodemask, *cpu_map);
++		*nodemask = node_to_cpumask(cpu_to_node(i));
++		cpus_and(*nodemask, *nodemask, *cpu_map);
+ 
+ #ifdef CONFIG_NUMA
+ 		if (cpus_weight(*cpu_map) >
+-				SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
++				SD_NODES_PER_DOMAIN*cpus_weight(*nodemask)) {
+ 			sd = &per_cpu(allnodes_domains, i);
+-			*sd = SD_ALLNODES_INIT;
++			SD_INIT(sd, ALLNODES);
++			set_domain_attribute(sd, attr);
+ 			sd->span = *cpu_map;
+-			cpu_to_allnodes_group(i, cpu_map, &sd->groups);
++			sd->first_cpu = first_cpu(sd->span);
++			cpu_to_allnodes_group(i, cpu_map, &sd->groups, tmpmask);
+ 			p = sd;
+ 			sd_allnodes = 1;
+ 		} else
+ 			p = NULL;
+ 
+ 		sd = &per_cpu(node_domains, i);
+-		*sd = SD_NODE_INIT;
+-		sd->span = sched_domain_node_span(cpu_to_node(i));
++		SD_INIT(sd, NODE);
++		set_domain_attribute(sd, attr);
++		sched_domain_node_span(cpu_to_node(i), &sd->span);
++		sd->first_cpu = first_cpu(sd->span);
+ 		sd->parent = p;
+ 		if (p)
+ 			p->child = sd;
+@@ -6644,94 +7422,120 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ 
+ 		p = sd;
+ 		sd = &per_cpu(phys_domains, i);
+-		*sd = SD_CPU_INIT;
+-		sd->span = nodemask;
++		SD_INIT(sd, CPU);
++		set_domain_attribute(sd, attr);
++		sd->span = *nodemask;
++		sd->first_cpu = first_cpu(sd->span);
+ 		sd->parent = p;
+ 		if (p)
+ 			p->child = sd;
+-		cpu_to_phys_group(i, cpu_map, &sd->groups);
++		cpu_to_phys_group(i, cpu_map, &sd->groups, tmpmask);
+ 
+ #ifdef CONFIG_SCHED_MC
+ 		p = sd;
+ 		sd = &per_cpu(core_domains, i);
+-		*sd = SD_MC_INIT;
++		SD_INIT(sd, MC);
++		set_domain_attribute(sd, attr);
+ 		sd->span = cpu_coregroup_map(i);
++		sd->first_cpu = first_cpu(sd->span);
+ 		cpus_and(sd->span, sd->span, *cpu_map);
+ 		sd->parent = p;
+ 		p->child = sd;
+-		cpu_to_core_group(i, cpu_map, &sd->groups);
++		cpu_to_core_group(i, cpu_map, &sd->groups, tmpmask);
+ #endif
+ 
+ #ifdef CONFIG_SCHED_SMT
+ 		p = sd;
+ 		sd = &per_cpu(cpu_domains, i);
+-		*sd = SD_SIBLING_INIT;
++		SD_INIT(sd, SIBLING);
++		set_domain_attribute(sd, attr);
+ 		sd->span = per_cpu(cpu_sibling_map, i);
++		sd->first_cpu = first_cpu(sd->span);
+ 		cpus_and(sd->span, sd->span, *cpu_map);
+ 		sd->parent = p;
+ 		p->child = sd;
+-		cpu_to_cpu_group(i, cpu_map, &sd->groups);
++		cpu_to_cpu_group(i, cpu_map, &sd->groups, tmpmask);
+ #endif
+ 	}
+ 
+ #ifdef CONFIG_SCHED_SMT
+ 	/* Set up CPU (sibling) groups */
+ 	for_each_cpu_mask(i, *cpu_map) {
+-		cpumask_t this_sibling_map = per_cpu(cpu_sibling_map, i);
+-		cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
+-		if (i != first_cpu(this_sibling_map))
++		SCHED_CPUMASK_VAR(this_sibling_map, allmasks);
++		SCHED_CPUMASK_VAR(send_covered, allmasks);
++
++		*this_sibling_map = per_cpu(cpu_sibling_map, i);
++		cpus_and(*this_sibling_map, *this_sibling_map, *cpu_map);
++		if (i != first_cpu(*this_sibling_map))
+ 			continue;
+ 
+ 		init_sched_build_groups(this_sibling_map, cpu_map,
+-					&cpu_to_cpu_group);
++					&cpu_to_cpu_group,
++					send_covered, tmpmask);
+ 	}
+ #endif
+ 
+ #ifdef CONFIG_SCHED_MC
+ 	/* Set up multi-core groups */
+ 	for_each_cpu_mask(i, *cpu_map) {
+-		cpumask_t this_core_map = cpu_coregroup_map(i);
+-		cpus_and(this_core_map, this_core_map, *cpu_map);
+-		if (i != first_cpu(this_core_map))
++		SCHED_CPUMASK_VAR(this_core_map, allmasks);
++		SCHED_CPUMASK_VAR(send_covered, allmasks);
++
++		*this_core_map = cpu_coregroup_map(i);
++		cpus_and(*this_core_map, *this_core_map, *cpu_map);
++		if (i != first_cpu(*this_core_map))
+ 			continue;
++
+ 		init_sched_build_groups(this_core_map, cpu_map,
+-					&cpu_to_core_group);
++					&cpu_to_core_group,
++					send_covered, tmpmask);
+ 	}
+ #endif
+ 
+ 	/* Set up physical groups */
+ 	for (i = 0; i < MAX_NUMNODES; i++) {
+-		cpumask_t nodemask = node_to_cpumask(i);
++		SCHED_CPUMASK_VAR(nodemask, allmasks);
++		SCHED_CPUMASK_VAR(send_covered, allmasks);
+ 
+-		cpus_and(nodemask, nodemask, *cpu_map);
+-		if (cpus_empty(nodemask))
++		*nodemask = node_to_cpumask(i);
++		cpus_and(*nodemask, *nodemask, *cpu_map);
++		if (cpus_empty(*nodemask))
+ 			continue;
+ 
+-		init_sched_build_groups(nodemask, cpu_map, &cpu_to_phys_group);
++		init_sched_build_groups(nodemask, cpu_map,
++					&cpu_to_phys_group,
++					send_covered, tmpmask);
+ 	}
+ 
+ #ifdef CONFIG_NUMA
+ 	/* Set up node groups */
+-	if (sd_allnodes)
+-		init_sched_build_groups(*cpu_map, cpu_map,
+-					&cpu_to_allnodes_group);
++	if (sd_allnodes) {
++		SCHED_CPUMASK_VAR(send_covered, allmasks);
++
++		init_sched_build_groups(cpu_map, cpu_map,
++					&cpu_to_allnodes_group,
++					send_covered, tmpmask);
++	}
+ 
+ 	for (i = 0; i < MAX_NUMNODES; i++) {
+ 		/* Set up node groups */
+ 		struct sched_group *sg, *prev;
+-		cpumask_t nodemask = node_to_cpumask(i);
+-		cpumask_t domainspan;
+-		cpumask_t covered = CPU_MASK_NONE;
++		SCHED_CPUMASK_VAR(nodemask, allmasks);
++		SCHED_CPUMASK_VAR(domainspan, allmasks);
++		SCHED_CPUMASK_VAR(covered, allmasks);
+ 		int j;
+ 
+-		cpus_and(nodemask, nodemask, *cpu_map);
+-		if (cpus_empty(nodemask)) {
++		*nodemask = node_to_cpumask(i);
++		cpus_clear(*covered);
++
++		cpus_and(*nodemask, *nodemask, *cpu_map);
++		if (cpus_empty(*nodemask)) {
+ 			sched_group_nodes[i] = NULL;
+ 			continue;
+ 		}
+ 
+-		domainspan = sched_domain_node_span(i);
+-		cpus_and(domainspan, domainspan, *cpu_map);
++		sched_domain_node_span(i, domainspan);
++		cpus_and(*domainspan, *domainspan, *cpu_map);
+ 
+ 		sg = kmalloc_node(sizeof(struct sched_group), GFP_KERNEL, i);
+ 		if (!sg) {
+@@ -6740,31 +7544,31 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ 			goto error;
+ 		}
+ 		sched_group_nodes[i] = sg;
+-		for_each_cpu_mask(j, nodemask) {
++		for_each_cpu_mask(j, *nodemask) {
+ 			struct sched_domain *sd;
+ 
+ 			sd = &per_cpu(node_domains, j);
+ 			sd->groups = sg;
+ 		}
+ 		sg->__cpu_power = 0;
+-		sg->cpumask = nodemask;
++		sg->cpumask = *nodemask;
+ 		sg->next = sg;
+-		cpus_or(covered, covered, nodemask);
++		cpus_or(*covered, *covered, *nodemask);
+ 		prev = sg;
+ 
+ 		for (j = 0; j < MAX_NUMNODES; j++) {
+-			cpumask_t tmp, notcovered;
++			SCHED_CPUMASK_VAR(notcovered, allmasks);
+ 			int n = (i + j) % MAX_NUMNODES;
++			node_to_cpumask_ptr(pnodemask, n);
+ 
+-			cpus_complement(notcovered, covered);
+-			cpus_and(tmp, notcovered, *cpu_map);
+-			cpus_and(tmp, tmp, domainspan);
+-			if (cpus_empty(tmp))
++			cpus_complement(*notcovered, *covered);
++			cpus_and(*tmpmask, *notcovered, *cpu_map);
++			cpus_and(*tmpmask, *tmpmask, *domainspan);
++			if (cpus_empty(*tmpmask))
+ 				break;
+ 
+-			nodemask = node_to_cpumask(n);
+-			cpus_and(tmp, tmp, nodemask);
+-			if (cpus_empty(tmp))
++			cpus_and(*tmpmask, *tmpmask, *pnodemask);
++			if (cpus_empty(*tmpmask))
+ 				continue;
+ 
+ 			sg = kmalloc_node(sizeof(struct sched_group),
+@@ -6775,9 +7579,9 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ 				goto error;
+ 			}
+ 			sg->__cpu_power = 0;
+-			sg->cpumask = tmp;
++			sg->cpumask = *tmpmask;
+ 			sg->next = prev->next;
+-			cpus_or(covered, covered, tmp);
++			cpus_or(*covered, *covered, *tmpmask);
+ 			prev->next = sg;
+ 			prev = sg;
+ 		}
+@@ -6813,7 +7617,8 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ 	if (sd_allnodes) {
+ 		struct sched_group *sg;
+ 
+-		cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map, &sg);
++		cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map, &sg,
++								tmpmask);
+ 		init_numa_sched_groups_power(sg);
+ 	}
+ #endif
+@@ -6831,17 +7636,26 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ 		cpu_attach_domain(sd, rd, i);
+ 	}
+ 
++	SCHED_CPUMASK_FREE((void *)allmasks);
+ 	return 0;
+ 
+ #ifdef CONFIG_NUMA
+ error:
+-	free_sched_groups(cpu_map);
++	free_sched_groups(cpu_map, tmpmask);
++	SCHED_CPUMASK_FREE((void *)allmasks);
+ 	return -ENOMEM;
+ #endif
+ }
+ 
++static int build_sched_domains(const cpumask_t *cpu_map)
++{
++	return __build_sched_domains(cpu_map, NULL);
++}
++
+ static cpumask_t *doms_cur;	/* current sched domains */
+ static int ndoms_cur;		/* number of sched domains in 'doms_cur' */
++static struct sched_domain_attr *dattr_cur;	/* attribues of custom domains
++						   in 'doms_cur' */
+ 
+ /*
+  * Special case: If a kmalloc of a doms_cur partition (array of
+@@ -6869,15 +7683,17 @@ static int arch_init_sched_domains(const cpumask_t *cpu_map)
+ 	if (!doms_cur)
+ 		doms_cur = &fallback_doms;
+ 	cpus_andnot(*doms_cur, *cpu_map, cpu_isolated_map);
++	dattr_cur = NULL;
+ 	err = build_sched_domains(doms_cur);
+ 	register_sched_domain_sysctl();
+ 
+ 	return err;
+ }
+ 
+-static void arch_destroy_sched_domains(const cpumask_t *cpu_map)
++static void arch_destroy_sched_domains(const cpumask_t *cpu_map,
++				       cpumask_t *tmpmask)
+ {
+-	free_sched_groups(cpu_map);
++	free_sched_groups(cpu_map, tmpmask);
+ }
+ 
+ /*
+@@ -6886,6 +7702,7 @@ static void arch_destroy_sched_domains(const cpumask_t *cpu_map)
+  */
+ static void detach_destroy_domains(const cpumask_t *cpu_map)
+ {
++	cpumask_t tmpmask;
+ 	int i;
+ 
+ 	unregister_sched_domain_sysctl();
+@@ -6893,7 +7710,23 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
+ 	for_each_cpu_mask(i, *cpu_map)
+ 		cpu_attach_domain(NULL, &def_root_domain, i);
+ 	synchronize_sched();
+-	arch_destroy_sched_domains(cpu_map);
++	arch_destroy_sched_domains(cpu_map, &tmpmask);
++}
++
++/* handle null as "default" */
++static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
++			struct sched_domain_attr *new, int idx_new)
++{
++	struct sched_domain_attr tmp;
++
++	/* fast path */
++	if (!new && !cur)
++		return 1;
++
++	tmp = SD_ATTR_INIT;
++	return !memcmp(cur ? (cur + idx_cur) : &tmp,
++			new ? (new + idx_new) : &tmp,
++			sizeof(struct sched_domain_attr));
+ }
+ 
+ /*
+@@ -6917,7 +7750,8 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
+  *
+  * Call with hotplug lock held
+  */
+-void partition_sched_domains(int ndoms_new, cpumask_t *doms_new)
++void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
++			     struct sched_domain_attr *dattr_new)
+ {
+ 	int i, j;
+ 
+@@ -6930,12 +7764,14 @@ void partition_sched_domains(int ndoms_new, cpumask_t *doms_new)
+ 		ndoms_new = 1;
+ 		doms_new = &fallback_doms;
+ 		cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
++		dattr_new = NULL;
+ 	}
+ 
+ 	/* Destroy deleted domains */
+ 	for (i = 0; i < ndoms_cur; i++) {
+ 		for (j = 0; j < ndoms_new; j++) {
+-			if (cpus_equal(doms_cur[i], doms_new[j]))
++			if (cpus_equal(doms_cur[i], doms_new[j])
++			    && dattrs_equal(dattr_cur, i, dattr_new, j))
+ 				goto match1;
+ 		}
+ 		/* no match - a current sched domain not in new doms_new[] */
+@@ -6947,11 +7783,13 @@ match1:
+ 	/* Build new domains */
+ 	for (i = 0; i < ndoms_new; i++) {
+ 		for (j = 0; j < ndoms_cur; j++) {
+-			if (cpus_equal(doms_new[i], doms_cur[j]))
++			if (cpus_equal(doms_new[i], doms_cur[j])
++			    && dattrs_equal(dattr_new, i, dattr_cur, j))
+ 				goto match2;
+ 		}
+ 		/* no match - add a new doms_new */
+-		build_sched_domains(doms_new + i);
++		__build_sched_domains(doms_new + i,
++					dattr_new ? dattr_new + i : NULL);
+ match2:
+ 		;
+ 	}
+@@ -6959,7 +7797,9 @@ match2:
+ 	/* Remember the new sched domains */
+ 	if (doms_cur != &fallback_doms)
+ 		kfree(doms_cur);
++	kfree(dattr_cur);	/* kfree(NULL) is safe */
+ 	doms_cur = doms_new;
++	dattr_cur = dattr_new;
+ 	ndoms_cur = ndoms_new;
+ 
+ 	register_sched_domain_sysctl();
+@@ -7086,6 +7926,11 @@ void __init sched_init_smp(void)
+ {
+ 	cpumask_t non_isolated_cpus;
+ 
++#if defined(CONFIG_NUMA)
++	sched_group_nodes_bycpu = kzalloc(nr_cpu_ids * sizeof(void **),
++								GFP_KERNEL);
++	BUG_ON(sched_group_nodes_bycpu == NULL);
++#endif
+ 	get_online_cpus();
+ 	arch_init_sched_domains(&cpu_online_map);
+ 	cpus_andnot(non_isolated_cpus, cpu_possible_map, cpu_isolated_map);
+@@ -7096,7 +7941,7 @@ void __init sched_init_smp(void)
+ 	hotcpu_notifier(update_sched_domains, 0);
+ 
+ 	/* Move init over to a non-isolated CPU */
+-	if (set_cpus_allowed(current, non_isolated_cpus) < 0)
++	if (set_cpus_allowed_ptr(current, &non_isolated_cpus) < 0)
+ 		BUG();
+ 	sched_init_granularity();
+ }
+@@ -7117,6 +7962,7 @@ int in_sched_functions(unsigned long addr)
+ static void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
+ {
+ 	cfs_rq->tasks_timeline = RB_ROOT;
++	INIT_LIST_HEAD(&cfs_rq->tasks);
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ 	cfs_rq->rq = rq;
+ #endif
+@@ -7146,6 +7992,8 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
+ 
+ 	rt_rq->rt_time = 0;
+ 	rt_rq->rt_throttled = 0;
++	rt_rq->rt_runtime = 0;
++	spin_lock_init(&rt_rq->rt_runtime_lock);
+ 
+ #ifdef CONFIG_RT_GROUP_SCHED
+ 	rt_rq->rt_nr_boosted = 0;
+@@ -7154,10 +8002,11 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
+ }
+ 
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+-static void init_tg_cfs_entry(struct rq *rq, struct task_group *tg,
+-		struct cfs_rq *cfs_rq, struct sched_entity *se,
+-		int cpu, int add)
++static void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
++				struct sched_entity *se, int cpu, int add,
++				struct sched_entity *parent)
+ {
++	struct rq *rq = cpu_rq(cpu);
+ 	tg->cfs_rq[cpu] = cfs_rq;
+ 	init_cfs_rq(cfs_rq, rq);
+ 	cfs_rq->tg = tg;
+@@ -7165,45 +8014,132 @@ static void init_tg_cfs_entry(struct rq *rq, struct task_group *tg,
+ 		list_add(&cfs_rq->leaf_cfs_rq_list, &rq->leaf_cfs_rq_list);
+ 
+ 	tg->se[cpu] = se;
+-	se->cfs_rq = &rq->cfs;
++	/* se could be NULL for init_task_group */
++	if (!se)
++		return;
++
++	if (!parent)
++		se->cfs_rq = &rq->cfs;
++	else
++		se->cfs_rq = parent->my_q;
++
+ 	se->my_q = cfs_rq;
+ 	se->load.weight = tg->shares;
+ 	se->load.inv_weight = div64_64(1ULL<<32, se->load.weight);
+-	se->parent = NULL;
++	se->parent = parent;
+ }
+ #endif
+ 
+ #ifdef CONFIG_RT_GROUP_SCHED
+-static void init_tg_rt_entry(struct rq *rq, struct task_group *tg,
+-		struct rt_rq *rt_rq, struct sched_rt_entity *rt_se,
+-		int cpu, int add)
++static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq,
++		struct sched_rt_entity *rt_se, int cpu, int add,
++		struct sched_rt_entity *parent)
+ {
++	struct rq *rq = cpu_rq(cpu);
++
+ 	tg->rt_rq[cpu] = rt_rq;
+ 	init_rt_rq(rt_rq, rq);
+ 	rt_rq->tg = tg;
+ 	rt_rq->rt_se = rt_se;
++	rt_rq->rt_runtime = tg->rt_bandwidth.rt_runtime;
+ 	if (add)
+ 		list_add(&rt_rq->leaf_rt_rq_list, &rq->leaf_rt_rq_list);
+ 
+ 	tg->rt_se[cpu] = rt_se;
++	if (!rt_se)
++		return;
++
++	if (!parent)
++		rt_se->rt_rq = &rq->rt;
++	else
++		rt_se->rt_rq = parent->my_q;
++
+ 	rt_se->rt_rq = &rq->rt;
+ 	rt_se->my_q = rt_rq;
+-	rt_se->parent = NULL;
++	rt_se->parent = parent;
+ 	INIT_LIST_HEAD(&rt_se->run_list);
+ }
+ #endif
+ 
+ void __init sched_init(void)
+ {
+-	int highest_cpu = 0;
+ 	int i, j;
++	unsigned long alloc_size = 0, ptr;
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++	alloc_size += 2 * nr_cpu_ids * sizeof(void **);
++#endif
++#ifdef CONFIG_RT_GROUP_SCHED
++	alloc_size += 2 * nr_cpu_ids * sizeof(void **);
++#endif
++#ifdef CONFIG_USER_SCHED
++	alloc_size *= 2;
++#endif
++	/*
++	 * As sched_init() is called before page_alloc is setup,
++	 * we use alloc_bootmem().
++	 */
++	if (alloc_size) {
++		ptr = (unsigned long)alloc_bootmem(alloc_size);
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++		init_task_group.se = (struct sched_entity **)ptr;
++		ptr += nr_cpu_ids * sizeof(void **);
++
++		init_task_group.cfs_rq = (struct cfs_rq **)ptr;
++		ptr += nr_cpu_ids * sizeof(void **);
++
++#ifdef CONFIG_USER_SCHED
++		root_task_group.se = (struct sched_entity **)ptr;
++		ptr += nr_cpu_ids * sizeof(void **);
++
++		root_task_group.cfs_rq = (struct cfs_rq **)ptr;
++		ptr += nr_cpu_ids * sizeof(void **);
++#endif
++#endif
++#ifdef CONFIG_RT_GROUP_SCHED
++		init_task_group.rt_se = (struct sched_rt_entity **)ptr;
++		ptr += nr_cpu_ids * sizeof(void **);
++
++		init_task_group.rt_rq = (struct rt_rq **)ptr;
++		ptr += nr_cpu_ids * sizeof(void **);
++
++#ifdef CONFIG_USER_SCHED
++		root_task_group.rt_se = (struct sched_rt_entity **)ptr;
++		ptr += nr_cpu_ids * sizeof(void **);
++
++		root_task_group.rt_rq = (struct rt_rq **)ptr;
++		ptr += nr_cpu_ids * sizeof(void **);
++#endif
++#endif
++	}
+ 
+ #ifdef CONFIG_SMP
++	init_aggregate();
+ 	init_defrootdomain();
+ #endif
+ 
++	init_rt_bandwidth(&def_rt_bandwidth,
++			global_rt_period(), global_rt_runtime());
++
++#ifdef CONFIG_RT_GROUP_SCHED
++	init_rt_bandwidth(&init_task_group.rt_bandwidth,
++			global_rt_period(), global_rt_runtime());
++#ifdef CONFIG_USER_SCHED
++	init_rt_bandwidth(&root_task_group.rt_bandwidth,
++			global_rt_period(), RUNTIME_INF);
++#endif
++#endif
++
+ #ifdef CONFIG_GROUP_SCHED
+ 	list_add(&init_task_group.list, &task_groups);
++	INIT_LIST_HEAD(&init_task_group.children);
++
++#ifdef CONFIG_USER_SCHED
++	INIT_LIST_HEAD(&root_task_group.children);
++	init_task_group.parent = &root_task_group;
++	list_add(&init_task_group.siblings, &root_task_group.children);
++#endif
+ #endif
+ 
+ 	for_each_possible_cpu(i) {
+@@ -7214,26 +8150,68 @@ void __init sched_init(void)
+ 		lockdep_set_class(&rq->lock, &rq->rq_lock_key);
+ 		rq->nr_running = 0;
+ 		rq->clock = 1;
++		update_last_tick_seen(rq);
+ 		init_cfs_rq(&rq->cfs, rq);
+ 		init_rt_rq(&rq->rt, rq);
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ 		init_task_group.shares = init_task_group_load;
+ 		INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
+-		init_tg_cfs_entry(rq, &init_task_group,
++#ifdef CONFIG_CGROUP_SCHED
++		/*
++		 * How much cpu bandwidth does init_task_group get?
++		 *
++		 * In case of task-groups formed thr' the cgroup filesystem, it
++		 * gets 100% of the cpu resources in the system. This overall
++		 * system cpu resource is divided among the tasks of
++		 * init_task_group and its child task-groups in a fair manner,
++		 * based on each entity's (task or task-group's) weight
++		 * (se->load.weight).
++		 *
++		 * In other words, if init_task_group has 10 tasks of weight
++		 * 1024) and two child groups A0 and A1 (of weight 1024 each),
++		 * then A0's share of the cpu resource is:
++		 *
++		 * 	A0's bandwidth = 1024 / (10*1024 + 1024 + 1024) = 8.33%
++		 *
++		 * We achieve this by letting init_task_group's tasks sit
++		 * directly in rq->cfs (i.e init_task_group->se[] = NULL).
++		 */
++		init_tg_cfs_entry(&init_task_group, &rq->cfs, NULL, i, 1, NULL);
++#elif defined CONFIG_USER_SCHED
++		root_task_group.shares = NICE_0_LOAD;
++		init_tg_cfs_entry(&root_task_group, &rq->cfs, NULL, i, 0, NULL);
++		/*
++		 * In case of task-groups formed thr' the user id of tasks,
++		 * init_task_group represents tasks belonging to root user.
++		 * Hence it forms a sibling of all subsequent groups formed.
++		 * In this case, init_task_group gets only a fraction of overall
++		 * system cpu resource, based on the weight assigned to root
++		 * user's cpu share (INIT_TASK_GROUP_LOAD). This is accomplished
++		 * by letting tasks of init_task_group sit in a separate cfs_rq
++		 * (init_cfs_rq) and having one entity represent this group of
++		 * tasks in rq->cfs (i.e init_task_group->se[] != NULL).
++		 */
++		init_tg_cfs_entry(&init_task_group,
+ 				&per_cpu(init_cfs_rq, i),
+-				&per_cpu(init_sched_entity, i), i, 1);
++				&per_cpu(init_sched_entity, i), i, 1,
++				root_task_group.se[i]);
+ 
+ #endif
++#endif /* CONFIG_FAIR_GROUP_SCHED */
++
++		rq->rt.rt_runtime = def_rt_bandwidth.rt_runtime;
+ #ifdef CONFIG_RT_GROUP_SCHED
+-		init_task_group.rt_runtime =
+-			sysctl_sched_rt_runtime * NSEC_PER_USEC;
+ 		INIT_LIST_HEAD(&rq->leaf_rt_rq_list);
+-		init_tg_rt_entry(rq, &init_task_group,
++#ifdef CONFIG_CGROUP_SCHED
++		init_tg_rt_entry(&init_task_group, &rq->rt, NULL, i, 1, NULL);
++#elif defined CONFIG_USER_SCHED
++		init_tg_rt_entry(&root_task_group, &rq->rt, NULL, i, 0, NULL);
++		init_tg_rt_entry(&init_task_group,
+ 				&per_cpu(init_rt_rq, i),
+-				&per_cpu(init_sched_rt_entity, i), i, 1);
++				&per_cpu(init_sched_rt_entity, i), i, 1,
++				root_task_group.rt_se[i]);
++#endif
+ #endif
+-		rq->rt_period_expire = 0;
+-		rq->rt_throttled = 0;
+ 
+ 		for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
+ 			rq->cpu_load[j] = 0;
+@@ -7250,7 +8228,6 @@ void __init sched_init(void)
+ #endif
+ 		init_rq_hrtick(rq);
+ 		atomic_set(&rq->nr_iowait, 0);
+-		highest_cpu = i;
+ 	}
+ 
+ 	set_load_weight(&init_task);
+@@ -7260,7 +8237,6 @@ void __init sched_init(void)
+ #endif
+ 
+ #ifdef CONFIG_SMP
+-	nr_cpu_ids = highest_cpu + 1;
+ 	open_softirq(SCHED_SOFTIRQ, run_rebalance_domains, NULL);
+ #endif
+ 
+@@ -7419,8 +8395,6 @@ void set_curr_task(int cpu, struct task_struct *p)
+ 
+ #endif
+ 
+-#ifdef CONFIG_GROUP_SCHED
+-
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ static void free_fair_sched_group(struct task_group *tg)
+ {
+@@ -7437,17 +8411,18 @@ static void free_fair_sched_group(struct task_group *tg)
+ 	kfree(tg->se);
+ }
+ 
+-static int alloc_fair_sched_group(struct task_group *tg)
++static
++int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
+ {
+ 	struct cfs_rq *cfs_rq;
+-	struct sched_entity *se;
++	struct sched_entity *se, *parent_se;
+ 	struct rq *rq;
+ 	int i;
+ 
+-	tg->cfs_rq = kzalloc(sizeof(cfs_rq) * NR_CPUS, GFP_KERNEL);
++	tg->cfs_rq = kzalloc(sizeof(cfs_rq) * nr_cpu_ids, GFP_KERNEL);
+ 	if (!tg->cfs_rq)
+ 		goto err;
+-	tg->se = kzalloc(sizeof(se) * NR_CPUS, GFP_KERNEL);
++	tg->se = kzalloc(sizeof(se) * nr_cpu_ids, GFP_KERNEL);
+ 	if (!tg->se)
+ 		goto err;
+ 
+@@ -7466,7 +8441,8 @@ static int alloc_fair_sched_group(struct task_group *tg)
+ 		if (!se)
+ 			goto err;
+ 
+-		init_tg_cfs_entry(rq, tg, cfs_rq, se, i, 0);
++		parent_se = parent ? parent->se[i] : NULL;
++		init_tg_cfs_entry(tg, cfs_rq, se, i, 0, parent_se);
+ 	}
+ 
+ 	return 1;
+@@ -7490,7 +8466,8 @@ static inline void free_fair_sched_group(struct task_group *tg)
+ {
+ }
+ 
+-static inline int alloc_fair_sched_group(struct task_group *tg)
++static inline
++int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
+ {
+ 	return 1;
+ }
+@@ -7509,6 +8486,8 @@ static void free_rt_sched_group(struct task_group *tg)
+ {
+ 	int i;
+ 
++	destroy_rt_bandwidth(&tg->rt_bandwidth);
++
+ 	for_each_possible_cpu(i) {
+ 		if (tg->rt_rq)
+ 			kfree(tg->rt_rq[i]);
+@@ -7520,21 +8499,23 @@ static void free_rt_sched_group(struct task_group *tg)
+ 	kfree(tg->rt_se);
+ }
+ 
+-static int alloc_rt_sched_group(struct task_group *tg)
++static
++int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
+ {
+ 	struct rt_rq *rt_rq;
+-	struct sched_rt_entity *rt_se;
++	struct sched_rt_entity *rt_se, *parent_se;
+ 	struct rq *rq;
+ 	int i;
+ 
+-	tg->rt_rq = kzalloc(sizeof(rt_rq) * NR_CPUS, GFP_KERNEL);
++	tg->rt_rq = kzalloc(sizeof(rt_rq) * nr_cpu_ids, GFP_KERNEL);
+ 	if (!tg->rt_rq)
+ 		goto err;
+-	tg->rt_se = kzalloc(sizeof(rt_se) * NR_CPUS, GFP_KERNEL);
++	tg->rt_se = kzalloc(sizeof(rt_se) * nr_cpu_ids, GFP_KERNEL);
+ 	if (!tg->rt_se)
+ 		goto err;
+ 
+-	tg->rt_runtime = 0;
++	init_rt_bandwidth(&tg->rt_bandwidth,
++			ktime_to_ns(def_rt_bandwidth.rt_period), 0);
+ 
+ 	for_each_possible_cpu(i) {
+ 		rq = cpu_rq(i);
+@@ -7549,7 +8530,8 @@ static int alloc_rt_sched_group(struct task_group *tg)
+ 		if (!rt_se)
+ 			goto err;
+ 
+-		init_tg_rt_entry(rq, tg, rt_rq, rt_se, i, 0);
++		parent_se = parent ? parent->rt_se[i] : NULL;
++		init_tg_rt_entry(tg, rt_rq, rt_se, i, 0, parent_se);
+ 	}
+ 
+ 	return 1;
+@@ -7573,7 +8555,8 @@ static inline void free_rt_sched_group(struct task_group *tg)
+ {
+ }
+ 
+-static inline int alloc_rt_sched_group(struct task_group *tg)
++static inline
++int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
+ {
+ 	return 1;
+ }
+@@ -7587,6 +8570,7 @@ static inline void unregister_rt_sched_group(struct task_group *tg, int cpu)
+ }
+ #endif
+ 
++#ifdef CONFIG_GROUP_SCHED
+ static void free_sched_group(struct task_group *tg)
+ {
+ 	free_fair_sched_group(tg);
+@@ -7595,7 +8579,7 @@ static void free_sched_group(struct task_group *tg)
+ }
+ 
+ /* allocate runqueue etc for a new task group */
+-struct task_group *sched_create_group(void)
++struct task_group *sched_create_group(struct task_group *parent)
+ {
+ 	struct task_group *tg;
+ 	unsigned long flags;
+@@ -7605,10 +8589,10 @@ struct task_group *sched_create_group(void)
+ 	if (!tg)
+ 		return ERR_PTR(-ENOMEM);
+ 
+-	if (!alloc_fair_sched_group(tg))
++	if (!alloc_fair_sched_group(tg, parent))
+ 		goto err;
+ 
+-	if (!alloc_rt_sched_group(tg))
++	if (!alloc_rt_sched_group(tg, parent))
+ 		goto err;
+ 
+ 	spin_lock_irqsave(&task_group_lock, flags);
+@@ -7617,6 +8601,12 @@ struct task_group *sched_create_group(void)
+ 		register_rt_sched_group(tg, i);
+ 	}
+ 	list_add_rcu(&tg->list, &task_groups);
++
++	WARN_ON(!parent); /* root should already exist */
++
++	tg->parent = parent;
++	list_add_rcu(&tg->siblings, &parent->children);
++	INIT_LIST_HEAD(&tg->children);
+ 	spin_unlock_irqrestore(&task_group_lock, flags);
+ 
+ 	return tg;
+@@ -7645,6 +8635,7 @@ void sched_destroy_group(struct task_group *tg)
+ 		unregister_rt_sched_group(tg, i);
+ 	}
+ 	list_del_rcu(&tg->list);
++	list_del_rcu(&tg->siblings);
+ 	spin_unlock_irqrestore(&task_group_lock, flags);
+ 
+ 	/* wait for possible concurrent references to cfs_rqs complete */
+@@ -7688,16 +8679,14 @@ void sched_move_task(struct task_struct *tsk)
+ 
+ 	task_rq_unlock(rq, &flags);
+ }
++#endif
+ 
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+-static void set_se_shares(struct sched_entity *se, unsigned long shares)
++static void __set_se_shares(struct sched_entity *se, unsigned long shares)
+ {
+ 	struct cfs_rq *cfs_rq = se->cfs_rq;
+-	struct rq *rq = cfs_rq->rq;
+ 	int on_rq;
+ 
+-	spin_lock_irq(&rq->lock);
+-
+ 	on_rq = se->on_rq;
+ 	if (on_rq)
+ 		dequeue_entity(cfs_rq, se, 0);
+@@ -7707,8 +8696,17 @@ static void set_se_shares(struct sched_entity *se, unsigned long shares)
+ 
+ 	if (on_rq)
+ 		enqueue_entity(cfs_rq, se, 0);
++}
+ 
+-	spin_unlock_irq(&rq->lock);
++static void set_se_shares(struct sched_entity *se, unsigned long shares)
++{
++	struct cfs_rq *cfs_rq = se->cfs_rq;
++	struct rq *rq = cfs_rq->rq;
++	unsigned long flags;
++
++	spin_lock_irqsave(&rq->lock, flags);
++	__set_se_shares(se, shares);
++	spin_unlock_irqrestore(&rq->lock, flags);
+ }
+ 
+ static DEFINE_MUTEX(shares_mutex);
+@@ -7719,12 +8717,18 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
+ 	unsigned long flags;
+ 
+ 	/*
++	 * We can't change the weight of the root cgroup.
++	 */
++	if (!tg->se[0])
++		return -EINVAL;
++
++	/*
+ 	 * A weight of 0 or 1 can cause arithmetics problems.
+ 	 * (The default weight is 1024 - so there's no practical
+ 	 *  limitation from this.)
+ 	 */
+-	if (shares < 2)
+-		shares = 2;
++	if (shares < MIN_SHARES)
++		shares = MIN_SHARES;
+ 
+ 	mutex_lock(&shares_mutex);
+ 	if (tg->shares == shares)
+@@ -7733,6 +8737,7 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
+ 	spin_lock_irqsave(&task_group_lock, flags);
+ 	for_each_possible_cpu(i)
+ 		unregister_fair_sched_group(tg, i);
++	list_del_rcu(&tg->siblings);
+ 	spin_unlock_irqrestore(&task_group_lock, flags);
+ 
+ 	/* wait for any ongoing reference to this group to finish */
+@@ -7743,8 +8748,13 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
+ 	 * w/o tripping rebalance_share or load_balance_fair.
+ 	 */
+ 	tg->shares = shares;
+-	for_each_possible_cpu(i)
+-		set_se_shares(tg->se[i], shares);
++	for_each_possible_cpu(i) {
++		/*
++		 * force a rebalance
++		 */
++		cfs_rq_set_shares(tg->cfs_rq[i], 0);
++		set_se_shares(tg->se[i], shares/nr_cpu_ids);
++	}
+ 
+ 	/*
+ 	 * Enable load balance activity on this group, by inserting it back on
+@@ -7753,6 +8763,7 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
+ 	spin_lock_irqsave(&task_group_lock, flags);
+ 	for_each_possible_cpu(i)
+ 		register_fair_sched_group(tg, i);
++	list_add_rcu(&tg->siblings, &tg->parent->children);
+ 	spin_unlock_irqrestore(&task_group_lock, flags);
+ done:
+ 	mutex_unlock(&shares_mutex);
+@@ -7779,26 +8790,58 @@ static unsigned long to_ratio(u64 period, u64 runtime)
+ 	return div64_64(runtime << 16, period);
+ }
+ 
++#ifdef CONFIG_CGROUP_SCHED
++static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime)
++{
++	struct task_group *tgi, *parent = tg->parent;
++	unsigned long total = 0;
++
++	if (!parent) {
++		if (global_rt_period() < period)
++			return 0;
++
++		return to_ratio(period, runtime) <
++			to_ratio(global_rt_period(), global_rt_runtime());
++	}
++
++	if (ktime_to_ns(parent->rt_bandwidth.rt_period) < period)
++		return 0;
++
++	rcu_read_lock();
++	list_for_each_entry_rcu(tgi, &parent->children, siblings) {
++		if (tgi == tg)
++			continue;
++
++		total += to_ratio(ktime_to_ns(tgi->rt_bandwidth.rt_period),
++				tgi->rt_bandwidth.rt_runtime);
++	}
++	rcu_read_unlock();
++
++	return total + to_ratio(period, runtime) <
++		to_ratio(ktime_to_ns(parent->rt_bandwidth.rt_period),
++				parent->rt_bandwidth.rt_runtime);
++}
++#elif defined CONFIG_USER_SCHED
+ static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime)
+ {
+ 	struct task_group *tgi;
+ 	unsigned long total = 0;
+ 	unsigned long global_ratio =
+-		to_ratio(sysctl_sched_rt_period,
+-			 sysctl_sched_rt_runtime < 0 ?
+-				RUNTIME_INF : sysctl_sched_rt_runtime);
++		to_ratio(global_rt_period(), global_rt_runtime());
+ 
+ 	rcu_read_lock();
+ 	list_for_each_entry_rcu(tgi, &task_groups, list) {
+ 		if (tgi == tg)
+ 			continue;
+ 
+-		total += to_ratio(period, tgi->rt_runtime);
++		total += to_ratio(ktime_to_ns(tgi->rt_bandwidth.rt_period),
++				tgi->rt_bandwidth.rt_runtime);
+ 	}
+ 	rcu_read_unlock();
+ 
+ 	return total + to_ratio(period, runtime) < global_ratio;
+ }
++#endif
+ 
+ /* Must be called with tasklist_lock held */
+ static inline int tg_has_rt_tasks(struct task_group *tg)
+@@ -7811,19 +8854,14 @@ static inline int tg_has_rt_tasks(struct task_group *tg)
+ 	return 0;
+ }
+ 
+-int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
++static int tg_set_bandwidth(struct task_group *tg,
++		u64 rt_period, u64 rt_runtime)
+ {
+-	u64 rt_runtime, rt_period;
+-	int err = 0;
+-
+-	rt_period = (u64)sysctl_sched_rt_period * NSEC_PER_USEC;
+-	rt_runtime = (u64)rt_runtime_us * NSEC_PER_USEC;
+-	if (rt_runtime_us == -1)
+-		rt_runtime = RUNTIME_INF;
++	int i, err = 0;
+ 
+ 	mutex_lock(&rt_constraints_mutex);
+ 	read_lock(&tasklist_lock);
+-	if (rt_runtime_us == 0 && tg_has_rt_tasks(tg)) {
++	if (rt_runtime == 0 && tg_has_rt_tasks(tg)) {
+ 		err = -EBUSY;
+ 		goto unlock;
+ 	}
+@@ -7831,7 +8869,19 @@ int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
+ 		err = -EINVAL;
+ 		goto unlock;
+ 	}
+-	tg->rt_runtime = rt_runtime;
++
++	spin_lock_irq(&tg->rt_bandwidth.rt_runtime_lock);
++	tg->rt_bandwidth.rt_period = ns_to_ktime(rt_period);
++	tg->rt_bandwidth.rt_runtime = rt_runtime;
++
++	for_each_possible_cpu(i) {
++		struct rt_rq *rt_rq = tg->rt_rq[i];
++
++		spin_lock(&rt_rq->rt_runtime_lock);
++		rt_rq->rt_runtime = rt_runtime;
++		spin_unlock(&rt_rq->rt_runtime_lock);
++	}
++	spin_unlock_irq(&tg->rt_bandwidth.rt_runtime_lock);
+  unlock:
+ 	read_unlock(&tasklist_lock);
+ 	mutex_unlock(&rt_constraints_mutex);
+@@ -7839,19 +8889,109 @@ int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
+ 	return err;
+ }
+ 
++int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
++{
++	u64 rt_runtime, rt_period;
++
++	rt_period = ktime_to_ns(tg->rt_bandwidth.rt_period);
++	rt_runtime = (u64)rt_runtime_us * NSEC_PER_USEC;
++	if (rt_runtime_us < 0)
++		rt_runtime = RUNTIME_INF;
++
++	return tg_set_bandwidth(tg, rt_period, rt_runtime);
++}
++
+ long sched_group_rt_runtime(struct task_group *tg)
+ {
+ 	u64 rt_runtime_us;
+ 
+-	if (tg->rt_runtime == RUNTIME_INF)
++	if (tg->rt_bandwidth.rt_runtime == RUNTIME_INF)
+ 		return -1;
+ 
+-	rt_runtime_us = tg->rt_runtime;
++	rt_runtime_us = tg->rt_bandwidth.rt_runtime;
+ 	do_div(rt_runtime_us, NSEC_PER_USEC);
+ 	return rt_runtime_us;
+ }
++
++int sched_group_set_rt_period(struct task_group *tg, long rt_period_us)
++{
++	u64 rt_runtime, rt_period;
++
++	rt_period = (u64)rt_period_us * NSEC_PER_USEC;
++	rt_runtime = tg->rt_bandwidth.rt_runtime;
++
++	return tg_set_bandwidth(tg, rt_period, rt_runtime);
++}
++
++long sched_group_rt_period(struct task_group *tg)
++{
++	u64 rt_period_us;
++
++	rt_period_us = ktime_to_ns(tg->rt_bandwidth.rt_period);
++	do_div(rt_period_us, NSEC_PER_USEC);
++	return rt_period_us;
++}
++
++static int sched_rt_global_constraints(void)
++{
++	int ret = 0;
++
++	mutex_lock(&rt_constraints_mutex);
++	if (!__rt_schedulable(NULL, 1, 0))
++		ret = -EINVAL;
++	mutex_unlock(&rt_constraints_mutex);
++
++	return ret;
++}
++#else
++static int sched_rt_global_constraints(void)
++{
++	unsigned long flags;
++	int i;
++
++	spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags);
++	for_each_possible_cpu(i) {
++		struct rt_rq *rt_rq = &cpu_rq(i)->rt;
++
++		spin_lock(&rt_rq->rt_runtime_lock);
++		rt_rq->rt_runtime = global_rt_runtime();
++		spin_unlock(&rt_rq->rt_runtime_lock);
++	}
++	spin_unlock_irqrestore(&def_rt_bandwidth.rt_runtime_lock, flags);
++
++	return 0;
++}
+ #endif
+-#endif	/* CONFIG_GROUP_SCHED */
++
++int sched_rt_handler(struct ctl_table *table, int write,
++		struct file *filp, void __user *buffer, size_t *lenp,
++		loff_t *ppos)
++{
++	int ret;
++	int old_period, old_runtime;
++	static DEFINE_MUTEX(mutex);
++
++	mutex_lock(&mutex);
++	old_period = sysctl_sched_rt_period;
++	old_runtime = sysctl_sched_rt_runtime;
++
++	ret = proc_dointvec(table, write, filp, buffer, lenp, ppos);
++
++	if (!ret && write) {
++		ret = sched_rt_global_constraints();
++		if (ret) {
++			sysctl_sched_rt_period = old_period;
++			sysctl_sched_rt_runtime = old_runtime;
++		} else {
++			def_rt_bandwidth.rt_runtime = global_rt_runtime();
++			def_rt_bandwidth.rt_period =
++				ns_to_ktime(global_rt_period());
++		}
++	}
++	mutex_unlock(&mutex);
++
++	return ret;
++}
+ 
+ #ifdef CONFIG_CGROUP_SCHED
+ 
+@@ -7865,7 +9005,7 @@ static inline struct task_group *cgroup_tg(struct cgroup *cgrp)
+ static struct cgroup_subsys_state *
+ cpu_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cgrp)
+ {
+-	struct task_group *tg;
++	struct task_group *tg, *parent;
+ 
+ 	if (!cgrp->parent) {
+ 		/* This is early initialization for the top cgroup */
+@@ -7873,11 +9013,8 @@ cpu_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cgrp)
+ 		return &init_task_group.css;
+ 	}
+ 
+-	/* we support only 1-level deep hierarchical scheduler atm */
+-	if (cgrp->parent->parent)
+-		return ERR_PTR(-EINVAL);
+-
+-	tg = sched_create_group();
++	parent = cgroup_tg(cgrp->parent);
++	tg = sched_create_group(parent);
+ 	if (IS_ERR(tg))
+ 		return ERR_PTR(-ENOMEM);
+ 
+@@ -7901,7 +9038,7 @@ cpu_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+ {
+ #ifdef CONFIG_RT_GROUP_SCHED
+ 	/* Don't accept realtime tasks when there is no way for them to run */
+-	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_runtime == 0)
++	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+ 		return -EINVAL;
+ #else
+ 	/* We don't support RT-tasks being in separate groups */
+@@ -7935,7 +9072,7 @@ static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft)
+ #endif
+ 
+ #ifdef CONFIG_RT_GROUP_SCHED
+-static int cpu_rt_runtime_write(struct cgroup *cgrp, struct cftype *cft,
++static ssize_t cpu_rt_runtime_write(struct cgroup *cgrp, struct cftype *cft,
+ 				struct file *file,
+ 				const char __user *userbuf,
+ 				size_t nbytes, loff_t *unused_ppos)
+@@ -7979,6 +9116,17 @@ static ssize_t cpu_rt_runtime_read(struct cgroup *cgrp, struct cftype *cft,
+ 
+ 	return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+ }
++
++static int cpu_rt_period_write_uint(struct cgroup *cgrp, struct cftype *cftype,
++		u64 rt_period_us)
++{
++	return sched_group_set_rt_period(cgroup_tg(cgrp), rt_period_us);
++}
++
++static u64 cpu_rt_period_read_uint(struct cgroup *cgrp, struct cftype *cft)
++{
++	return sched_group_rt_period(cgroup_tg(cgrp));
++}
+ #endif
+ 
+ static struct cftype cpu_files[] = {
+@@ -7995,6 +9143,11 @@ static struct cftype cpu_files[] = {
+ 		.read = cpu_rt_runtime_read,
+ 		.write = cpu_rt_runtime_write,
+ 	},
++	{
++		.name = "rt_period_us",
++		.read_uint = cpu_rt_period_read_uint,
++		.write_uint = cpu_rt_period_write_uint,
++	},
+ #endif
+ };
+ 
+@@ -8035,9 +9188,9 @@ struct cpuacct {
+ struct cgroup_subsys cpuacct_subsys;
+ 
+ /* return cpu accounting group corresponding to this container */
+-static inline struct cpuacct *cgroup_ca(struct cgroup *cont)
++static inline struct cpuacct *cgroup_ca(struct cgroup *cgrp)
+ {
+-	return container_of(cgroup_subsys_state(cont, cpuacct_subsys_id),
++	return container_of(cgroup_subsys_state(cgrp, cpuacct_subsys_id),
+ 			    struct cpuacct, css);
+ }
+ 
+@@ -8050,7 +9203,7 @@ static inline struct cpuacct *task_ca(struct task_struct *tsk)
+ 
+ /* create a new cpu accounting group */
+ static struct cgroup_subsys_state *cpuacct_create(
+-	struct cgroup_subsys *ss, struct cgroup *cont)
++	struct cgroup_subsys *ss, struct cgroup *cgrp)
+ {
+ 	struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
+ 
+@@ -8068,18 +9221,18 @@ static struct cgroup_subsys_state *cpuacct_create(
+ 
+ /* destroy an existing cpu accounting group */
+ static void
+-cpuacct_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
++cpuacct_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp)
+ {
+-	struct cpuacct *ca = cgroup_ca(cont);
++	struct cpuacct *ca = cgroup_ca(cgrp);
+ 
+ 	free_percpu(ca->cpuusage);
+ 	kfree(ca);
+ }
+ 
+ /* return total cpu usage (in nanoseconds) of a group */
+-static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
++static u64 cpuusage_read(struct cgroup *cgrp, struct cftype *cft)
+ {
+-	struct cpuacct *ca = cgroup_ca(cont);
++	struct cpuacct *ca = cgroup_ca(cgrp);
+ 	u64 totalcpuusage = 0;
+ 	int i;
+ 
+@@ -8098,16 +9251,40 @@ static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
+ 	return totalcpuusage;
+ }
+ 
++static int cpuusage_write(struct cgroup *cgrp, struct cftype *cftype,
++								u64 reset)
++{
++	struct cpuacct *ca = cgroup_ca(cgrp);
++	int err = 0;
++	int i;
++
++	if (reset) {
++		err = -EINVAL;
++		goto out;
++	}
++
++	for_each_possible_cpu(i) {
++		u64 *cpuusage = percpu_ptr(ca->cpuusage, i);
++
++		spin_lock_irq(&cpu_rq(i)->lock);
++		*cpuusage = 0;
++		spin_unlock_irq(&cpu_rq(i)->lock);
++	}
++out:
++	return err;
++}
++
+ static struct cftype files[] = {
+ 	{
+ 		.name = "usage",
+ 		.read_uint = cpuusage_read,
++		.write_uint = cpuusage_write,
+ 	},
+ };
+ 
+-static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cont)
++static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
+ {
+-	return cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
++	return cgroup_add_files(cgrp, ss, files, ARRAY_SIZE(files));
+ }
+ 
+ /*
+diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
+index ef358ba..f3f4af4 100644
+--- a/kernel/sched_debug.c
++++ b/kernel/sched_debug.c
+@@ -67,14 +67,24 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
+ 		(long long)(p->nvcsw + p->nivcsw),
+ 		p->prio);
+ #ifdef CONFIG_SCHEDSTATS
+-	SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld\n",
++	SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld",
+ 		SPLIT_NS(p->se.vruntime),
+ 		SPLIT_NS(p->se.sum_exec_runtime),
+ 		SPLIT_NS(p->se.sum_sleep_runtime));
+ #else
+-	SEQ_printf(m, "%15Ld %15Ld %15Ld.%06ld %15Ld.%06ld %15Ld.%06ld\n",
++	SEQ_printf(m, "%15Ld %15Ld %15Ld.%06ld %15Ld.%06ld %15Ld.%06ld",
+ 		0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L);
+ #endif
++
++#ifdef CONFIG_CGROUP_SCHED
++	{
++		char path[64];
++
++		cgroup_path(task_group(p)->css.cgroup, path, sizeof(path));
++		SEQ_printf(m, " %s", path);
++	}
++#endif
++	SEQ_printf(m, "\n");
+ }
+ 
+ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
+@@ -109,7 +119,21 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
+ 	struct sched_entity *last;
+ 	unsigned long flags;
+ 
+-	SEQ_printf(m, "\ncfs_rq\n");
++#if !defined(CONFIG_CGROUP_SCHED) || !defined(CONFIG_USER_SCHED)
++	SEQ_printf(m, "\ncfs_rq[%d]:\n", cpu);
++#else
++	char path[128] = "";
++	struct cgroup *cgroup = NULL;
++	struct task_group *tg = cfs_rq->tg;
++
++	if (tg)
++		cgroup = tg->css.cgroup;
++
++	if (cgroup)
++		cgroup_path(cgroup, path, sizeof(path));
++
++	SEQ_printf(m, "\ncfs_rq[%d]:%s\n", cpu, path);
++#endif
+ 
+ 	SEQ_printf(m, "  .%-30s: %Ld.%06ld\n", "exec_clock",
+ 			SPLIT_NS(cfs_rq->exec_clock));
+@@ -143,6 +167,11 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
+ #endif
+ 	SEQ_printf(m, "  .%-30s: %ld\n", "nr_spread_over",
+ 			cfs_rq->nr_spread_over);
++#ifdef CONFIG_FAIR_GROUP_SCHED
++#ifdef CONFIG_SMP
++	SEQ_printf(m, "  .%-30s: %lu\n", "shares", cfs_rq->shares);
++#endif
++#endif
+ }
+ 
+ static void print_cpu(struct seq_file *m, int cpu)
+@@ -214,7 +243,6 @@ static int sched_debug_show(struct seq_file *m, void *v)
+ 	PN(sysctl_sched_latency);
+ 	PN(sysctl_sched_min_granularity);
+ 	PN(sysctl_sched_wakeup_granularity);
+-	PN(sysctl_sched_batch_wakeup_granularity);
+ 	PN(sysctl_sched_child_runs_first);
+ 	P(sysctl_sched_features);
+ #undef PN
+diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
+index 0080968..89fa32b 100644
+--- a/kernel/sched_fair.c
++++ b/kernel/sched_fair.c
+@@ -62,24 +62,14 @@ const_debug unsigned int sysctl_sched_child_runs_first = 1;
+ unsigned int __read_mostly sysctl_sched_compat_yield;
+ 
+ /*
+- * SCHED_BATCH wake-up granularity.
+- * (default: 10 msec * (1 + ilog(ncpus)), units: nanoseconds)
+- *
+- * This option delays the preemption effects of decoupled workloads
+- * and reduces their over-scheduling. Synchronous workloads will still
+- * have immediate wakeup/sleep latencies.
+- */
+-unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL;
+-
+-/*
+  * SCHED_OTHER wake-up granularity.
+- * (default: 5 msec * (1 + ilog(ncpus)), units: nanoseconds)
++ * (default: 10 msec * (1 + ilog(ncpus)), units: nanoseconds)
+  *
+  * This option delays the preemption effects of decoupled workloads
+  * and reduces their over-scheduling. Synchronous workloads will still
+  * have immediate wakeup/sleep latencies.
+  */
+-unsigned int sysctl_sched_wakeup_granularity = 5000000UL;
++unsigned int sysctl_sched_wakeup_granularity = 10000000UL;
+ 
+ const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
+ 
+@@ -87,6 +77,11 @@ const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
+  * CFS operations on generic schedulable entities:
+  */
+ 
++static inline struct task_struct *task_of(struct sched_entity *se)
++{
++	return container_of(se, struct task_struct, se);
++}
++
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ 
+ /* cpu runqueue to which this cfs_rq is attached */
+@@ -98,6 +93,54 @@ static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+ /* An entity is a task if it doesn't "own" a runqueue */
+ #define entity_is_task(se)	(!se->my_q)
+ 
++/* Walk up scheduling entities hierarchy */
++#define for_each_sched_entity(se) \
++		for (; se; se = se->parent)
++
++static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
++{
++	return p->se.cfs_rq;
++}
++
++/* runqueue on which this entity is (to be) queued */
++static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
++{
++	return se->cfs_rq;
++}
++
++/* runqueue "owned" by this group */
++static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
++{
++	return grp->my_q;
++}
++
++/* Given a group's cfs_rq on one cpu, return its corresponding cfs_rq on
++ * another cpu ('this_cpu')
++ */
++static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
++{
++	return cfs_rq->tg->cfs_rq[this_cpu];
++}
++
++/* Iterate thr' all leaf cfs_rq's on a runqueue */
++#define for_each_leaf_cfs_rq(rq, cfs_rq) \
++	list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
++
++/* Do the two (enqueued) entities belong to the same group ? */
++static inline int
++is_same_group(struct sched_entity *se, struct sched_entity *pse)
++{
++	if (se->cfs_rq == pse->cfs_rq)
++		return 1;
++
++	return 0;
++}
++
++static inline struct sched_entity *parent_entity(struct sched_entity *se)
++{
++	return se->parent;
++}
++
+ #else	/* CONFIG_FAIR_GROUP_SCHED */
+ 
+ static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+@@ -107,13 +150,49 @@ static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+ 
+ #define entity_is_task(se)	1
+ 
+-#endif	/* CONFIG_FAIR_GROUP_SCHED */
++#define for_each_sched_entity(se) \
++		for (; se; se = NULL)
+ 
+-static inline struct task_struct *task_of(struct sched_entity *se)
++static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+ {
+-	return container_of(se, struct task_struct, se);
++	return &task_rq(p)->cfs;
++}
++
++static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
++{
++	struct task_struct *p = task_of(se);
++	struct rq *rq = task_rq(p);
++
++	return &rq->cfs;
++}
++
++/* runqueue "owned" by this group */
++static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
++{
++	return NULL;
++}
++
++static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
++{
++	return &cpu_rq(this_cpu)->cfs;
++}
++
++#define for_each_leaf_cfs_rq(rq, cfs_rq) \
++		for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
++
++static inline int
++is_same_group(struct sched_entity *se, struct sched_entity *pse)
++{
++	return 1;
++}
++
++static inline struct sched_entity *parent_entity(struct sched_entity *se)
++{
++	return NULL;
+ }
+ 
++#endif	/* CONFIG_FAIR_GROUP_SCHED */
++
+ 
+ /**************************************************************
+  * Scheduling class tree data structure manipulation methods:
+@@ -255,6 +334,34 @@ int sched_nr_latency_handler(struct ctl_table *table, int write,
+ #endif
+ 
+ /*
++ * delta *= w / rw
++ */
++static inline unsigned long
++calc_delta_weight(unsigned long delta, struct sched_entity *se)
++{
++	for_each_sched_entity(se) {
++		delta = calc_delta_mine(delta,
++				se->load.weight, &cfs_rq_of(se)->load);
++	}
++
++	return delta;
++}
++
++/*
++ * delta *= rw / w
++ */
++static inline unsigned long
++calc_delta_fair(unsigned long delta, struct sched_entity *se)
++{
++	for_each_sched_entity(se) {
++		delta = calc_delta_mine(delta,
++				cfs_rq_of(se)->load.weight, &se->load);
++	}
++
++	return delta;
++}
++
++/*
+  * The idea is to set a period in which each task runs once.
+  *
+  * When there are too many tasks (sysctl_sched_nr_latency) we have to stretch
+@@ -283,29 +390,54 @@ static u64 __sched_period(unsigned long nr_running)
+  */
+ static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+-	return calc_delta_mine(__sched_period(cfs_rq->nr_running),
+-			       se->load.weight, &cfs_rq->load);
++	return calc_delta_weight(__sched_period(cfs_rq->nr_running), se);
+ }
+ 
+ /*
+- * We calculate the vruntime slice.
++ * We calculate the vruntime slice of a to be inserted task
+  *
+- * vs = s/w = p/rw
++ * vs = s*rw/w = p
+  */
+-static u64 __sched_vslice(unsigned long rq_weight, unsigned long nr_running)
++static u64 sched_vslice_add(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+-	u64 vslice = __sched_period(nr_running);
++	unsigned long nr_running = cfs_rq->nr_running;
+ 
+-	vslice *= NICE_0_LOAD;
+-	do_div(vslice, rq_weight);
++	if (!se->on_rq)
++		nr_running++;
+ 
+-	return vslice;
++	return __sched_period(nr_running);
+ }
+ 
+-static u64 sched_vslice_add(struct cfs_rq *cfs_rq, struct sched_entity *se)
++/*
++ * The goal of calc_delta_asym() is to be asymmetrically around NICE_0_LOAD, in
++ * that it favours >=0 over <0.
++ *
++ *   -20         |
++ *               |
++ *     0 --------+-------
++ *             .'
++ *    19     .'
++ *
++ */
++static unsigned long
++calc_delta_asym(unsigned long delta, struct sched_entity *se)
+ {
+-	return __sched_vslice(cfs_rq->load.weight + se->load.weight,
+-			cfs_rq->nr_running + 1);
++	struct load_weight lw = {
++		.weight = NICE_0_LOAD,
++		.inv_weight = 1UL << (WMULT_SHIFT-NICE_0_SHIFT)
++	};
++
++	for_each_sched_entity(se) {
++		struct load_weight *se_lw = &se->load;
++
++		if (se->load.weight < NICE_0_LOAD)
++			se_lw = &lw;
++
++		delta = calc_delta_mine(delta,
++				cfs_rq_of(se)->load.weight, se_lw);
++	}
++
++	return delta;
+ }
+ 
+ /*
+@@ -322,11 +454,7 @@ __update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr,
+ 
+ 	curr->sum_exec_runtime += delta_exec;
+ 	schedstat_add(cfs_rq, exec_clock, delta_exec);
+-	delta_exec_weighted = delta_exec;
+-	if (unlikely(curr->load.weight != NICE_0_LOAD)) {
+-		delta_exec_weighted = calc_delta_fair(delta_exec_weighted,
+-							&curr->load);
+-	}
++	delta_exec_weighted = calc_delta_fair(delta_exec, curr);
+ 	curr->vruntime += delta_exec_weighted;
+ }
+ 
+@@ -413,20 +541,43 @@ update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
+  * Scheduling class queueing methods:
+  */
+ 
++#if defined CONFIG_SMP && defined CONFIG_FAIR_GROUP_SCHED
++static void
++add_cfs_task_weight(struct cfs_rq *cfs_rq, unsigned long weight)
++{
++	cfs_rq->task_weight += weight;
++}
++#else
++static inline void
++add_cfs_task_weight(struct cfs_rq *cfs_rq, unsigned long weight)
++{
++}
++#endif
++
+ static void
+ account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+ 	update_load_add(&cfs_rq->load, se->load.weight);
++	if (!parent_entity(se))
++		inc_cpu_load(rq_of(cfs_rq), se->load.weight);
++	if (entity_is_task(se))
++		add_cfs_task_weight(cfs_rq, se->load.weight);
+ 	cfs_rq->nr_running++;
+ 	se->on_rq = 1;
++	list_add(&se->group_node, &cfs_rq->tasks);
+ }
+ 
+ static void
+ account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+ 	update_load_sub(&cfs_rq->load, se->load.weight);
++	if (!parent_entity(se))
++		dec_cpu_load(rq_of(cfs_rq), se->load.weight);
++	if (entity_is_task(se))
++		add_cfs_task_weight(cfs_rq, -se->load.weight);
+ 	cfs_rq->nr_running--;
+ 	se->on_rq = 0;
++	list_del_init(&se->group_node);
+ }
+ 
+ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
+@@ -510,8 +661,12 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
+ 
+ 	if (!initial) {
+ 		/* sleeps upto a single latency don't count. */
+-		if (sched_feat(NEW_FAIR_SLEEPERS))
+-			vruntime -= sysctl_sched_latency;
++		if (sched_feat(NEW_FAIR_SLEEPERS)) {
++			if (sched_feat(NORMALIZED_SLEEPER))
++				vruntime -= calc_delta_weight(sysctl_sched_latency, se);
++			else
++				vruntime -= sysctl_sched_latency;
++		}
+ 
+ 		/* ensure we never gain time by being placed backwards. */
+ 		vruntime = max_vruntime(se->vruntime, vruntime);
+@@ -627,20 +782,16 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ 	se->prev_sum_exec_runtime = se->sum_exec_runtime;
+ }
+ 
++static int
++wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se);
++
+ static struct sched_entity *
+ pick_next(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+-	s64 diff, gran;
+-
+ 	if (!cfs_rq->next)
+ 		return se;
+ 
+-	diff = cfs_rq->next->vruntime - se->vruntime;
+-	if (diff < 0)
+-		return se;
+-
+-	gran = calc_delta_fair(sysctl_sched_wakeup_granularity, &cfs_rq->load);
+-	if (diff > gran)
++	if (wakeup_preempt_entity(cfs_rq->next, se) != 0)
+ 		return se;
+ 
+ 	return cfs_rq->next;
+@@ -708,101 +859,6 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
+  * CFS operations on tasks:
+  */
+ 
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+-
+-/* Walk up scheduling entities hierarchy */
+-#define for_each_sched_entity(se) \
+-		for (; se; se = se->parent)
+-
+-static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+-{
+-	return p->se.cfs_rq;
+-}
+-
+-/* runqueue on which this entity is (to be) queued */
+-static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+-{
+-	return se->cfs_rq;
+-}
+-
+-/* runqueue "owned" by this group */
+-static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+-{
+-	return grp->my_q;
+-}
+-
+-/* Given a group's cfs_rq on one cpu, return its corresponding cfs_rq on
+- * another cpu ('this_cpu')
+- */
+-static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+-{
+-	return cfs_rq->tg->cfs_rq[this_cpu];
+-}
+-
+-/* Iterate thr' all leaf cfs_rq's on a runqueue */
+-#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+-	list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
+-
+-/* Do the two (enqueued) entities belong to the same group ? */
+-static inline int
+-is_same_group(struct sched_entity *se, struct sched_entity *pse)
+-{
+-	if (se->cfs_rq == pse->cfs_rq)
+-		return 1;
+-
+-	return 0;
+-}
+-
+-static inline struct sched_entity *parent_entity(struct sched_entity *se)
+-{
+-	return se->parent;
+-}
+-
+-#else	/* CONFIG_FAIR_GROUP_SCHED */
+-
+-#define for_each_sched_entity(se) \
+-		for (; se; se = NULL)
+-
+-static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+-{
+-	return &task_rq(p)->cfs;
+-}
+-
+-static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+-{
+-	struct task_struct *p = task_of(se);
+-	struct rq *rq = task_rq(p);
+-
+-	return &rq->cfs;
+-}
+-
+-/* runqueue "owned" by this group */
+-static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+-{
+-	return NULL;
+-}
+-
+-static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+-{
+-	return &cpu_rq(this_cpu)->cfs;
+-}
+-
+-#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+-		for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
+-
+-static inline int
+-is_same_group(struct sched_entity *se, struct sched_entity *pse)
+-{
+-	return 1;
+-}
+-
+-static inline struct sched_entity *parent_entity(struct sched_entity *se)
+-{
+-	return NULL;
+-}
+-
+-#endif	/* CONFIG_FAIR_GROUP_SCHED */
+-
+ #ifdef CONFIG_SCHED_HRTICK
+ static void hrtick_start_fair(struct rq *rq, struct task_struct *p)
+ {
+@@ -916,7 +972,7 @@ static void yield_task_fair(struct rq *rq)
+ 	/*
+ 	 * Already in the rightmost position?
+ 	 */
+-	if (unlikely(rightmost->vruntime < se->vruntime))
++	if (unlikely(!rightmost || rightmost->vruntime < se->vruntime))
+ 		return;
+ 
+ 	/*
+@@ -955,7 +1011,9 @@ static int wake_idle(int cpu, struct task_struct *p)
+ 		return cpu;
+ 
+ 	for_each_domain(cpu, sd) {
+-		if (sd->flags & SD_WAKE_IDLE) {
++		if ((sd->flags & SD_WAKE_IDLE)
++		    || ((sd->flags & SD_WAKE_IDLE_FAR)
++			&& !task_hot(p, task_rq(p)->clock, sd))) {
+ 			cpus_and(tmp, sd->span, p->cpus_allowed);
+ 			for_each_cpu_mask(i, tmp) {
+ 				if (idle_cpu(i)) {
+@@ -1099,6 +1157,58 @@ out:
+ }
+ #endif /* CONFIG_SMP */
+ 
++static unsigned long wakeup_gran(struct sched_entity *se)
++{
++	unsigned long gran = sysctl_sched_wakeup_granularity;
++
++	/*
++	 * More easily preempt - nice tasks, while not making it harder for
++	 * + nice tasks.
++	 */
++	gran = calc_delta_asym(sysctl_sched_wakeup_granularity, se);
++
++	return gran;
++}
++
++/*
++ * Should 'se' preempt 'curr'.
++ *
++ *             |s1
++ *        |s2
++ *   |s3
++ *         g
++ *      |<--->|c
++ *
++ *  w(c, s1) = -1
++ *  w(c, s2) =  0
++ *  w(c, s3) =  1
++ *
++ */
++static int
++wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se)
++{
++	s64 gran, vdiff = curr->vruntime - se->vruntime;
++
++	if (vdiff < 0)
++		return -1;
++
++	gran = wakeup_gran(curr);
++	if (vdiff > gran)
++		return 1;
++
++	return 0;
++}
++
++/* return depth at which a sched entity is present in the hierarchy */
++static inline int depth_se(struct sched_entity *se)
++{
++	int depth = 0;
++
++	for_each_sched_entity(se)
++		depth++;
++
++	return depth;
++}
+ 
+ /*
+  * Preempt the current task with a newly woken task if needed:
+@@ -1108,7 +1218,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
+ 	struct task_struct *curr = rq->curr;
+ 	struct cfs_rq *cfs_rq = task_cfs_rq(curr);
+ 	struct sched_entity *se = &curr->se, *pse = &p->se;
+-	unsigned long gran;
++	int se_depth, pse_depth;
+ 
+ 	if (unlikely(rt_prio(p->prio))) {
+ 		update_rq_clock(rq);
+@@ -1133,20 +1243,33 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
+ 	if (!sched_feat(WAKEUP_PREEMPT))
+ 		return;
+ 
+-	while (!is_same_group(se, pse)) {
++	/*
++	 * preemption test can be made between sibling entities who are in the
++	 * same cfs_rq i.e who have a common parent. Walk up the hierarchy of
++	 * both tasks until we find their ancestors who are siblings of common
++	 * parent.
++	 */
++
++	/* First walk up until both entities are at same depth */
++	se_depth = depth_se(se);
++	pse_depth = depth_se(pse);
++
++	while (se_depth > pse_depth) {
++		se_depth--;
+ 		se = parent_entity(se);
++	}
++
++	while (pse_depth > se_depth) {
++		pse_depth--;
+ 		pse = parent_entity(pse);
+ 	}
+ 
+-	gran = sysctl_sched_wakeup_granularity;
+-	/*
+-	 * More easily preempt - nice tasks, while not making
+-	 * it harder for + nice tasks.
+-	 */
+-	if (unlikely(se->load.weight > NICE_0_LOAD))
+-		gran = calc_delta_fair(gran, &se->load);
++	while (!is_same_group(se, pse)) {
++		se = parent_entity(se);
++		pse = parent_entity(pse);
++	}
+ 
+-	if (pse->vruntime + gran < se->vruntime)
++	if (wakeup_preempt_entity(se, pse) == 1)
+ 		resched_task(curr);
+ }
+ 
+@@ -1197,15 +1320,27 @@ static void put_prev_task_fair(struct rq *rq, struct task_struct *prev)
+  * the current task:
+  */
+ static struct task_struct *
+-__load_balance_iterator(struct cfs_rq *cfs_rq, struct rb_node *curr)
++__load_balance_iterator(struct cfs_rq *cfs_rq, struct list_head *next)
+ {
+-	struct task_struct *p;
++	struct task_struct *p = NULL;
++	struct sched_entity *se;
++
++	if (next == &cfs_rq->tasks)
++		return NULL;
++
++	/* Skip over entities that are not tasks */
++	do {
++		se = list_entry(next, struct sched_entity, group_node);
++		next = next->next;
++	} while (next != &cfs_rq->tasks && !entity_is_task(se));
+ 
+-	if (!curr)
++	if (next == &cfs_rq->tasks)
+ 		return NULL;
+ 
+-	p = rb_entry(curr, struct task_struct, se.run_node);
+-	cfs_rq->rb_load_balance_curr = rb_next(curr);
++	cfs_rq->balance_iterator = next;
++
++	if (entity_is_task(se))
++		p = task_of(se);
+ 
+ 	return p;
+ }
+@@ -1214,85 +1349,100 @@ static struct task_struct *load_balance_start_fair(void *arg)
+ {
+ 	struct cfs_rq *cfs_rq = arg;
+ 
+-	return __load_balance_iterator(cfs_rq, first_fair(cfs_rq));
++	return __load_balance_iterator(cfs_rq, cfs_rq->tasks.next);
+ }
+ 
+ static struct task_struct *load_balance_next_fair(void *arg)
+ {
+ 	struct cfs_rq *cfs_rq = arg;
+ 
+-	return __load_balance_iterator(cfs_rq, cfs_rq->rb_load_balance_curr);
++	return __load_balance_iterator(cfs_rq, cfs_rq->balance_iterator);
+ }
+ 
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+-static int cfs_rq_best_prio(struct cfs_rq *cfs_rq)
++static unsigned long
++__load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
++		unsigned long max_load_move, struct sched_domain *sd,
++		enum cpu_idle_type idle, int *all_pinned, int *this_best_prio,
++		struct cfs_rq *cfs_rq)
+ {
+-	struct sched_entity *curr;
+-	struct task_struct *p;
+-
+-	if (!cfs_rq->nr_running || !first_fair(cfs_rq))
+-		return MAX_PRIO;
+-
+-	curr = cfs_rq->curr;
+-	if (!curr)
+-		curr = __pick_next_entity(cfs_rq);
++	struct rq_iterator cfs_rq_iterator;
+ 
+-	p = task_of(curr);
++	cfs_rq_iterator.start = load_balance_start_fair;
++	cfs_rq_iterator.next = load_balance_next_fair;
++	cfs_rq_iterator.arg = cfs_rq;
+ 
+-	return p->prio;
++	return balance_tasks(this_rq, this_cpu, busiest,
++			max_load_move, sd, idle, all_pinned,
++			this_best_prio, &cfs_rq_iterator);
+ }
+-#endif
+ 
++#ifdef CONFIG_FAIR_GROUP_SCHED
+ static unsigned long
+ load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ 		  unsigned long max_load_move,
+ 		  struct sched_domain *sd, enum cpu_idle_type idle,
+ 		  int *all_pinned, int *this_best_prio)
+ {
+-	struct cfs_rq *busy_cfs_rq;
+ 	long rem_load_move = max_load_move;
+-	struct rq_iterator cfs_rq_iterator;
+-
+-	cfs_rq_iterator.start = load_balance_start_fair;
+-	cfs_rq_iterator.next = load_balance_next_fair;
++	int busiest_cpu = cpu_of(busiest);
++	struct task_group *tg;
+ 
+-	for_each_leaf_cfs_rq(busiest, busy_cfs_rq) {
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+-		struct cfs_rq *this_cfs_rq;
++	rcu_read_lock();
++	list_for_each_entry(tg, &task_groups, list) {
+ 		long imbalance;
+-		unsigned long maxload;
++		unsigned long this_weight, busiest_weight;
++		long rem_load, max_load, moved_load;
++
++		/*
++		 * empty group
++		 */
++		if (!aggregate(tg, sd)->task_weight)
++			continue;
++
++		rem_load = rem_load_move * aggregate(tg, sd)->rq_weight;
++		rem_load /= aggregate(tg, sd)->load + 1;
++
++		this_weight = tg->cfs_rq[this_cpu]->task_weight;
++		busiest_weight = tg->cfs_rq[busiest_cpu]->task_weight;
++
++		imbalance = (busiest_weight - this_weight) / 2;
+ 
+-		this_cfs_rq = cpu_cfs_rq(busy_cfs_rq, this_cpu);
++		if (imbalance < 0)
++			imbalance = busiest_weight;
+ 
+-		imbalance = busy_cfs_rq->load.weight - this_cfs_rq->load.weight;
+-		/* Don't pull if this_cfs_rq has more load than busy_cfs_rq */
+-		if (imbalance <= 0)
++		max_load = max(rem_load, imbalance);
++		moved_load = __load_balance_fair(this_rq, this_cpu, busiest,
++				max_load, sd, idle, all_pinned, this_best_prio,
++				tg->cfs_rq[busiest_cpu]);
++
++		if (!moved_load)
+ 			continue;
+ 
+-		/* Don't pull more than imbalance/2 */
+-		imbalance /= 2;
+-		maxload = min(rem_load_move, imbalance);
++		move_group_shares(tg, sd, busiest_cpu, this_cpu);
+ 
+-		*this_best_prio = cfs_rq_best_prio(this_cfs_rq);
+-#else
+-# define maxload rem_load_move
+-#endif
+-		/*
+-		 * pass busy_cfs_rq argument into
+-		 * load_balance_[start|next]_fair iterators
+-		 */
+-		cfs_rq_iterator.arg = busy_cfs_rq;
+-		rem_load_move -= balance_tasks(this_rq, this_cpu, busiest,
+-					       maxload, sd, idle, all_pinned,
+-					       this_best_prio,
+-					       &cfs_rq_iterator);
++		moved_load *= aggregate(tg, sd)->load;
++		moved_load /= aggregate(tg, sd)->rq_weight + 1;
+ 
+-		if (rem_load_move <= 0)
++		rem_load_move -= moved_load;
++		if (rem_load_move < 0)
+ 			break;
+ 	}
++	rcu_read_unlock();
+ 
+ 	return max_load_move - rem_load_move;
+ }
++#else
++static unsigned long
++load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
++		  unsigned long max_load_move,
++		  struct sched_domain *sd, enum cpu_idle_type idle,
++		  int *all_pinned, int *this_best_prio)
++{
++	return __load_balance_fair(this_rq, this_cpu, busiest,
++			max_load_move, sd, idle, all_pinned,
++			this_best_prio, &busiest->cfs);
++}
++#endif
+ 
+ static int
+ move_one_task_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
+@@ -1461,16 +1611,40 @@ static const struct sched_class fair_sched_class = {
+ };
+ 
+ #ifdef CONFIG_SCHED_DEBUG
++static void
++print_cfs_rq_tasks(struct seq_file *m, struct cfs_rq *cfs_rq, int depth)
++{
++	struct sched_entity *se;
++
++	if (!cfs_rq)
++		return;
++
++	list_for_each_entry_rcu(se, &cfs_rq->tasks, group_node) {
++		int i;
++
++		for (i = depth; i; i--)
++			seq_puts(m, "  ");
++
++		seq_printf(m, "%lu %s %lu\n",
++				se->load.weight,
++				entity_is_task(se) ? "T" : "G",
++				calc_delta_weight(SCHED_LOAD_SCALE, se)
++				);
++		if (!entity_is_task(se))
++			print_cfs_rq_tasks(m, group_cfs_rq(se), depth + 1);
++	}
++}
++
+ static void print_cfs_stats(struct seq_file *m, int cpu)
+ {
+ 	struct cfs_rq *cfs_rq;
+ 
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+-	print_cfs_rq(m, cpu, &cpu_rq(cpu)->cfs);
+-#endif
+ 	rcu_read_lock();
+ 	for_each_leaf_cfs_rq(cpu_rq(cpu), cfs_rq)
+ 		print_cfs_rq(m, cpu, cfs_rq);
++
++	seq_printf(m, "\nWeight tree:\n");
++	print_cfs_rq_tasks(m, &cpu_rq(cpu)->cfs, 1);
+ 	rcu_read_unlock();
+ }
+ #endif
+diff --git a/kernel/sched_features.h b/kernel/sched_features.h
+new file mode 100644
+index 0000000..1c7283c
+--- /dev/null
++++ b/kernel/sched_features.h
+@@ -0,0 +1,10 @@
++SCHED_FEAT(NEW_FAIR_SLEEPERS, 1)
++SCHED_FEAT(WAKEUP_PREEMPT, 1)
++SCHED_FEAT(START_DEBIT, 1)
++SCHED_FEAT(AFFINE_WAKEUPS, 1)
++SCHED_FEAT(CACHE_HOT_BUDDY, 1)
++SCHED_FEAT(SYNC_WAKEUPS, 1)
++SCHED_FEAT(HRTICK, 1)
++SCHED_FEAT(DOUBLE_TICK, 0)
++SCHED_FEAT(NORMALIZED_SLEEPER, 1)
++SCHED_FEAT(DEADLINE, 1)
+diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
+index 0a6d2e5..c2730a5 100644
+--- a/kernel/sched_rt.c
++++ b/kernel/sched_rt.c
+@@ -62,7 +62,12 @@ static inline u64 sched_rt_runtime(struct rt_rq *rt_rq)
+ 	if (!rt_rq->tg)
+ 		return RUNTIME_INF;
+ 
+-	return rt_rq->tg->rt_runtime;
++	return rt_rq->rt_runtime;
++}
++
++static inline u64 sched_rt_period(struct rt_rq *rt_rq)
++{
++	return ktime_to_ns(rt_rq->tg->rt_bandwidth.rt_period);
+ }
+ 
+ #define for_each_leaf_rt_rq(rt_rq, rq) \
+@@ -127,14 +132,39 @@ static int rt_se_boosted(struct sched_rt_entity *rt_se)
+ 	return p->prio != p->normal_prio;
+ }
+ 
++#ifdef CONFIG_SMP
++static inline cpumask_t sched_rt_period_mask(void)
++{
++	return cpu_rq(smp_processor_id())->rd->span;
++}
++#else
++static inline cpumask_t sched_rt_period_mask(void)
++{
++	return cpu_online_map;
++}
++#endif
++
++static inline
++struct rt_rq *sched_rt_period_rt_rq(struct rt_bandwidth *rt_b, int cpu)
++{
++	return container_of(rt_b, struct task_group, rt_bandwidth)->rt_rq[cpu];
++}
++
++static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq)
++{
++	return &rt_rq->tg->rt_bandwidth;
++}
++
+ #else
+ 
+ static inline u64 sched_rt_runtime(struct rt_rq *rt_rq)
+ {
+-	if (sysctl_sched_rt_runtime == -1)
+-		return RUNTIME_INF;
++	return rt_rq->rt_runtime;
++}
+ 
+-	return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC;
++static inline u64 sched_rt_period(struct rt_rq *rt_rq)
++{
++	return ktime_to_ns(def_rt_bandwidth.rt_period);
+ }
+ 
+ #define for_each_leaf_rt_rq(rt_rq, rq) \
+@@ -173,6 +203,102 @@ static inline int rt_rq_throttled(struct rt_rq *rt_rq)
+ {
+ 	return rt_rq->rt_throttled;
+ }
++
++static inline cpumask_t sched_rt_period_mask(void)
++{
++	return cpu_online_map;
++}
++
++static inline
++struct rt_rq *sched_rt_period_rt_rq(struct rt_bandwidth *rt_b, int cpu)
++{
++	return &cpu_rq(cpu)->rt;
++}
++
++static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq)
++{
++	return &def_rt_bandwidth;
++}
++
++#endif
++
++static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun)
++{
++	int i, idle = 1;
++	cpumask_t span;
++
++	if (rt_b->rt_runtime == RUNTIME_INF)
++		return 1;
++
++	span = sched_rt_period_mask();
++	for_each_cpu_mask(i, span) {
++		int enqueue = 0;
++		struct rt_rq *rt_rq = sched_rt_period_rt_rq(rt_b, i);
++		struct rq *rq = rq_of_rt_rq(rt_rq);
++
++		spin_lock(&rq->lock);
++		if (rt_rq->rt_time) {
++			u64 runtime;
++
++			spin_lock(&rt_rq->rt_runtime_lock);
++			runtime = rt_rq->rt_runtime;
++			rt_rq->rt_time -= min(rt_rq->rt_time, overrun*runtime);
++			if (rt_rq->rt_throttled && rt_rq->rt_time < runtime) {
++				rt_rq->rt_throttled = 0;
++				enqueue = 1;
++			}
++			if (rt_rq->rt_time || rt_rq->rt_nr_running)
++				idle = 0;
++			spin_unlock(&rt_rq->rt_runtime_lock);
++		}
++
++		if (enqueue)
++			sched_rt_rq_enqueue(rt_rq);
++		spin_unlock(&rq->lock);
++	}
++
++	return idle;
++}
++
++#ifdef CONFIG_SMP
++static int balance_runtime(struct rt_rq *rt_rq)
++{
++	struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
++	struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
++	int i, weight, more = 0;
++	u64 rt_period;
++
++	weight = cpus_weight(rd->span);
++
++	spin_lock(&rt_b->rt_runtime_lock);
++	rt_period = ktime_to_ns(rt_b->rt_period);
++	for_each_cpu_mask(i, rd->span) {
++		struct rt_rq *iter = sched_rt_period_rt_rq(rt_b, i);
++		s64 diff;
++
++		if (iter == rt_rq)
++			continue;
++
++		spin_lock(&iter->rt_runtime_lock);
++		diff = iter->rt_runtime - iter->rt_time;
++		if (diff > 0) {
++			do_div(diff, weight);
++			if (rt_rq->rt_runtime + diff > rt_period)
++				diff = rt_period - rt_rq->rt_runtime;
++			iter->rt_runtime -= diff;
++			rt_rq->rt_runtime += diff;
++			more = 1;
++			if (rt_rq->rt_runtime == rt_period) {
++				spin_unlock(&iter->rt_runtime_lock);
++				break;
++			}
++		}
++		spin_unlock(&iter->rt_runtime_lock);
++	}
++	spin_unlock(&rt_b->rt_runtime_lock);
++
++	return more;
++}
+ #endif
+ 
+ static inline int rt_se_prio(struct sched_rt_entity *rt_se)
+@@ -197,12 +323,24 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)
+ 	if (rt_rq->rt_throttled)
+ 		return rt_rq_throttled(rt_rq);
+ 
++	if (sched_rt_runtime(rt_rq) >= sched_rt_period(rt_rq))
++		return 0;
++
++#ifdef CONFIG_SMP
+ 	if (rt_rq->rt_time > runtime) {
+-		struct rq *rq = rq_of_rt_rq(rt_rq);
++		int more;
+ 
+-		rq->rt_throttled = 1;
+-		rt_rq->rt_throttled = 1;
++		spin_unlock(&rt_rq->rt_runtime_lock);
++		more = balance_runtime(rt_rq);
++		spin_lock(&rt_rq->rt_runtime_lock);
+ 
++		if (more)
++			runtime = sched_rt_runtime(rt_rq);
++	}
++#endif
++
++	if (rt_rq->rt_time > runtime) {
++		rt_rq->rt_throttled = 1;
+ 		if (rt_rq_throttled(rt_rq)) {
+ 			sched_rt_rq_dequeue(rt_rq);
+ 			return 1;
+@@ -212,29 +350,6 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)
+ 	return 0;
+ }
+ 
+-static void update_sched_rt_period(struct rq *rq)
+-{
+-	struct rt_rq *rt_rq;
+-	u64 period;
+-
+-	while (rq->clock > rq->rt_period_expire) {
+-		period = (u64)sysctl_sched_rt_period * NSEC_PER_USEC;
+-		rq->rt_period_expire += period;
+-
+-		for_each_leaf_rt_rq(rt_rq, rq) {
+-			u64 runtime = sched_rt_runtime(rt_rq);
+-
+-			rt_rq->rt_time -= min(rt_rq->rt_time, runtime);
+-			if (rt_rq->rt_throttled && rt_rq->rt_time < runtime) {
+-				rt_rq->rt_throttled = 0;
+-				sched_rt_rq_enqueue(rt_rq);
+-			}
+-		}
+-
+-		rq->rt_throttled = 0;
+-	}
+-}
+-
+ /*
+  * Update the current task's runtime statistics. Skip current tasks that
+  * are not in our scheduling class.
+@@ -259,9 +374,15 @@ static void update_curr_rt(struct rq *rq)
+ 	curr->se.exec_start = rq->clock;
+ 	cpuacct_charge(curr, delta_exec);
+ 
+-	rt_rq->rt_time += delta_exec;
+-	if (sched_rt_runtime_exceeded(rt_rq))
+-		resched_task(curr);
++	for_each_sched_rt_entity(rt_se) {
++		rt_rq = rt_rq_of_se(rt_se);
++
++		spin_lock(&rt_rq->rt_runtime_lock);
++		rt_rq->rt_time += delta_exec;
++		if (sched_rt_runtime_exceeded(rt_rq))
++			resched_task(curr);
++		spin_unlock(&rt_rq->rt_runtime_lock);
++	}
+ }
+ 
+ static inline
+@@ -284,6 +405,11 @@ void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
+ #ifdef CONFIG_RT_GROUP_SCHED
+ 	if (rt_se_boosted(rt_se))
+ 		rt_rq->rt_nr_boosted++;
++
++	if (rt_rq->tg)
++		start_rt_bandwidth(&rt_rq->tg->rt_bandwidth);
++#else
++	start_rt_bandwidth(&def_rt_bandwidth);
+ #endif
+ }
+ 
+@@ -353,27 +479,21 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se)
+ /*
+  * Because the prio of an upper entry depends on the lower
+  * entries, we must remove entries top - down.
+- *
+- * XXX: O(1/2 h^2) because we can only walk up, not down the chain.
+- *      doesn't matter much for now, as h=2 for GROUP_SCHED.
+  */
+ static void dequeue_rt_stack(struct task_struct *p)
+ {
+-	struct sched_rt_entity *rt_se, *top_se;
++	struct sched_rt_entity *rt_se, *back = NULL;
+ 
+-	/*
+-	 * dequeue all, top - down.
+-	 */
+-	do {
+-		rt_se = &p->rt;
+-		top_se = NULL;
+-		for_each_sched_rt_entity(rt_se) {
+-			if (on_rt_rq(rt_se))
+-				top_se = rt_se;
+-		}
+-		if (top_se)
+-			dequeue_rt_entity(top_se);
+-	} while (top_se);
++	rt_se = &p->rt;
++	for_each_sched_rt_entity(rt_se) {
++		rt_se->back = back;
++		back = rt_se;
++	}
++
++	for (rt_se = back; rt_se; rt_se = rt_se->back) {
++		if (on_rt_rq(rt_se))
++			dequeue_rt_entity(rt_se);
++	}
+ }
+ 
+ /*
+@@ -393,6 +513,8 @@ static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup)
+ 	 */
+ 	for_each_sched_rt_entity(rt_se)
+ 		enqueue_rt_entity(rt_se);
++
++	inc_cpu_load(rq, p->se.load.weight);
+ }
+ 
+ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep)
+@@ -412,6 +534,8 @@ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep)
+ 		if (rt_rq && rt_rq->rt_nr_running)
+ 			enqueue_rt_entity(rt_se);
+ 	}
++
++	dec_cpu_load(rq, p->se.load.weight);
+ }
+ 
+ /*
+@@ -1001,7 +1125,8 @@ move_one_task_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ 	return 0;
+ }
+ 
+-static void set_cpus_allowed_rt(struct task_struct *p, cpumask_t *new_mask)
++static void set_cpus_allowed_rt(struct task_struct *p,
++				const cpumask_t *new_mask)
+ {
+ 	int weight = cpus_weight(*new_mask);
+ 
+diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h
+index 5b32433..5bae2e0 100644
+--- a/kernel/sched_stats.h
++++ b/kernel/sched_stats.h
+@@ -9,6 +9,11 @@
+ static int show_schedstat(struct seq_file *seq, void *v)
+ {
+ 	int cpu;
++	int mask_len = NR_CPUS/32 * 9;
++	char *mask_str = kmalloc(mask_len, GFP_KERNEL);
++
++	if (mask_str == NULL)
++		return -ENOMEM;
+ 
+ 	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
+ 	seq_printf(seq, "timestamp %lu\n", jiffies);
+@@ -36,9 +41,8 @@ static int show_schedstat(struct seq_file *seq, void *v)
+ 		preempt_disable();
+ 		for_each_domain(cpu, sd) {
+ 			enum cpu_idle_type itype;
+-			char mask_str[NR_CPUS];
+ 
+-			cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
++			cpumask_scnprintf(mask_str, mask_len, sd->span);
+ 			seq_printf(seq, "domain%d %s", dcount++, mask_str);
+ 			for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
+ 					itype++) {
+diff --git a/kernel/semaphore.c b/kernel/semaphore.c
+new file mode 100644
+index 0000000..5c2942e
+--- /dev/null
++++ b/kernel/semaphore.c
+@@ -0,0 +1,264 @@
++/*
++ * Copyright (c) 2008 Intel Corporation
++ * Author: Matthew Wilcox <willy at linux.intel.com>
++ *
++ * Distributed under the terms of the GNU GPL, version 2
++ *
++ * This file implements counting semaphores.
++ * A counting semaphore may be acquired 'n' times before sleeping.
++ * See mutex.c for single-acquisition sleeping locks which enforce
++ * rules which allow code to be debugged more easily.
++ */
++
++/*
++ * Some notes on the implementation:
++ *
++ * The spinlock controls access to the other members of the semaphore.
++ * down_trylock() and up() can be called from interrupt context, so we
++ * have to disable interrupts when taking the lock.  It turns out various
++ * parts of the kernel expect to be able to use down() on a semaphore in
++ * interrupt context when they know it will succeed, so we have to use
++ * irqsave variants for down(), down_interruptible() and down_killable()
++ * too.
++ *
++ * The ->count variable represents how many more tasks can acquire this
++ * semaphore.  If it's zero, there may be tasks waiting on the wait_list.
++ */
++
++#include <linux/compiler.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/semaphore.h>
++#include <linux/spinlock.h>
++
++static noinline void __down(struct semaphore *sem);
++static noinline int __down_interruptible(struct semaphore *sem);
++static noinline int __down_killable(struct semaphore *sem);
++static noinline int __down_timeout(struct semaphore *sem, long jiffies);
++static noinline void __up(struct semaphore *sem);
++
++/**
++ * down - acquire the semaphore
++ * @sem: the semaphore to be acquired
++ *
++ * Acquires the semaphore.  If no more tasks are allowed to acquire the
++ * semaphore, calling this function will put the task to sleep until the
++ * semaphore is released.
++ *
++ * Use of this function is deprecated, please use down_interruptible() or
++ * down_killable() instead.
++ */
++void down(struct semaphore *sem)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&sem->lock, flags);
++	if (likely(sem->count > 0))
++		sem->count--;
++	else
++		__down(sem);
++	spin_unlock_irqrestore(&sem->lock, flags);
++}
++EXPORT_SYMBOL(down);
++
++/**
++ * down_interruptible - acquire the semaphore unless interrupted
++ * @sem: the semaphore to be acquired
++ *
++ * Attempts to acquire the semaphore.  If no more tasks are allowed to
++ * acquire the semaphore, calling this function will put the task to sleep.
++ * If the sleep is interrupted by a signal, this function will return -EINTR.
++ * If the semaphore is successfully acquired, this function returns 0.
++ */
++int down_interruptible(struct semaphore *sem)
++{
++	unsigned long flags;
++	int result = 0;
++
++	spin_lock_irqsave(&sem->lock, flags);
++	if (likely(sem->count > 0))
++		sem->count--;
++	else
++		result = __down_interruptible(sem);
++	spin_unlock_irqrestore(&sem->lock, flags);
++
++	return result;
++}
++EXPORT_SYMBOL(down_interruptible);
++
++/**
++ * down_killable - acquire the semaphore unless killed
++ * @sem: the semaphore to be acquired
++ *
++ * Attempts to acquire the semaphore.  If no more tasks are allowed to
++ * acquire the semaphore, calling this function will put the task to sleep.
++ * If the sleep is interrupted by a fatal signal, this function will return
++ * -EINTR.  If the semaphore is successfully acquired, this function returns
++ * 0.
++ */
++int down_killable(struct semaphore *sem)
++{
++	unsigned long flags;
++	int result = 0;
++
++	spin_lock_irqsave(&sem->lock, flags);
++	if (likely(sem->count > 0))
++		sem->count--;
++	else
++		result = __down_killable(sem);
++	spin_unlock_irqrestore(&sem->lock, flags);
++
++	return result;
++}
++EXPORT_SYMBOL(down_killable);
++
++/**
++ * down_trylock - try to acquire the semaphore, without waiting
++ * @sem: the semaphore to be acquired
++ *
++ * Try to acquire the semaphore atomically.  Returns 0 if the mutex has
++ * been acquired successfully or 1 if it it cannot be acquired.
++ *
++ * NOTE: This return value is inverted from both spin_trylock and
++ * mutex_trylock!  Be careful about this when converting code.
++ *
++ * Unlike mutex_trylock, this function can be used from interrupt context,
++ * and the semaphore can be released by any task or interrupt.
++ */
++int down_trylock(struct semaphore *sem)
++{
++	unsigned long flags;
++	int count;
++
++	spin_lock_irqsave(&sem->lock, flags);
++	count = sem->count - 1;
++	if (likely(count >= 0))
++		sem->count = count;
++	spin_unlock_irqrestore(&sem->lock, flags);
++
++	return (count < 0);
++}
++EXPORT_SYMBOL(down_trylock);
++
++/**
++ * down_timeout - acquire the semaphore within a specified time
++ * @sem: the semaphore to be acquired
++ * @jiffies: how long to wait before failing
++ *
++ * Attempts to acquire the semaphore.  If no more tasks are allowed to
++ * acquire the semaphore, calling this function will put the task to sleep.
++ * If the semaphore is not released within the specified number of jiffies,
++ * this function returns -ETIME.  It returns 0 if the semaphore was acquired.
++ */
++int down_timeout(struct semaphore *sem, long jiffies)
++{
++	unsigned long flags;
++	int result = 0;
++
++	spin_lock_irqsave(&sem->lock, flags);
++	if (likely(sem->count > 0))
++		sem->count--;
++	else
++		result = __down_timeout(sem, jiffies);
++	spin_unlock_irqrestore(&sem->lock, flags);
++
++	return result;
++}
++EXPORT_SYMBOL(down_timeout);
++
++/**
++ * up - release the semaphore
++ * @sem: the semaphore to release
++ *
++ * Release the semaphore.  Unlike mutexes, up() may be called from any
++ * context and even by tasks which have never called down().
++ */
++void up(struct semaphore *sem)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&sem->lock, flags);
++	if (likely(list_empty(&sem->wait_list)))
++		sem->count++;
++	else
++		__up(sem);
++	spin_unlock_irqrestore(&sem->lock, flags);
++}
++EXPORT_SYMBOL(up);
++
++/* Functions for the contended case */
++
++struct semaphore_waiter {
++	struct list_head list;
++	struct task_struct *task;
++	int up;
++};
++
++/*
++ * Because this function is inlined, the 'state' parameter will be
++ * constant, and thus optimised away by the compiler.  Likewise the
++ * 'timeout' parameter for the cases without timeouts.
++ */
++static inline int __sched __down_common(struct semaphore *sem, long state,
++								long timeout)
++{
++	struct task_struct *task = current;
++	struct semaphore_waiter waiter;
++
++	list_add_tail(&waiter.list, &sem->wait_list);
++	waiter.task = task;
++	waiter.up = 0;
++
++	for (;;) {
++		if (state == TASK_INTERRUPTIBLE && signal_pending(task))
++			goto interrupted;
++		if (state == TASK_KILLABLE && fatal_signal_pending(task))
++			goto interrupted;
++		if (timeout <= 0)
++			goto timed_out;
++		__set_task_state(task, state);
++		spin_unlock_irq(&sem->lock);
++		timeout = schedule_timeout(timeout);
++		spin_lock_irq(&sem->lock);
++		if (waiter.up)
++			return 0;
++	}
++
++ timed_out:
++	list_del(&waiter.list);
++	return -ETIME;
++
++ interrupted:
++	list_del(&waiter.list);
++	return -EINTR;
++}
++
++static noinline void __sched __down(struct semaphore *sem)
++{
++	__down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
++}
++
++static noinline int __sched __down_interruptible(struct semaphore *sem)
++{
++	return __down_common(sem, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
++}
++
++static noinline int __sched __down_killable(struct semaphore *sem)
++{
++	return __down_common(sem, TASK_KILLABLE, MAX_SCHEDULE_TIMEOUT);
++}
++
++static noinline int __sched __down_timeout(struct semaphore *sem, long jiffies)
++{
++	return __down_common(sem, TASK_UNINTERRUPTIBLE, jiffies);
++}
++
++static noinline void __sched __up(struct semaphore *sem)
++{
++	struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,
++						struct semaphore_waiter, list);
++	list_del(&waiter->list);
++	waiter->up = 1;
++	wake_up_process(waiter->task);
++}
+diff --git a/kernel/signal.c b/kernel/signal.c
+index 6af1210..64ad0ed 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -220,7 +220,7 @@ void flush_signals(struct task_struct *t)
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&t->sighand->siglock, flags);
+-	clear_tsk_thread_flag(t,TIF_SIGPENDING);
++	clear_tsk_thread_flag(t, TIF_SIGPENDING);
+ 	flush_sigqueue(&t->pending);
+ 	flush_sigqueue(&t->signal->shared_pending);
+ 	spin_unlock_irqrestore(&t->sighand->siglock, flags);
+@@ -424,7 +424,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+ 	}
+ 	if (signr &&
+ 	     ((info->si_code & __SI_MASK) == __SI_TIMER) &&
+-	     info->si_sys_private){
++	     info->si_sys_private) {
+ 		/*
+ 		 * Release the siglock to ensure proper locking order
+ 		 * of timer locks outside of siglocks.  Note, we leave
+@@ -1757,6 +1757,45 @@ static int do_signal_stop(int signr)
+ 	return 1;
+ }
+ 
++static int ptrace_signal(int signr, siginfo_t *info,
++			 struct pt_regs *regs, void *cookie)
++{
++	if (!(current->ptrace & PT_PTRACED))
++		return signr;
++
++	ptrace_signal_deliver(regs, cookie);
++
++	/* Let the debugger run.  */
++	ptrace_stop(signr, 0, info);
++
++	/* We're back.  Did the debugger cancel the sig?  */
++	signr = current->exit_code;
++	if (signr == 0)
++		return signr;
++
++	current->exit_code = 0;
++
++	/* Update the siginfo structure if the signal has
++	   changed.  If the debugger wanted something
++	   specific in the siginfo structure then it should
++	   have updated *info via PTRACE_SETSIGINFO.  */
++	if (signr != info->si_signo) {
++		info->si_signo = signr;
++		info->si_errno = 0;
++		info->si_code = SI_USER;
++		info->si_pid = task_pid_vnr(current->parent);
++		info->si_uid = current->parent->uid;
++	}
++
++	/* If the (new) signal is now blocked, requeue it.  */
++	if (sigismember(&current->blocked, signr)) {
++		specific_send_sig_info(signr, info, current);
++		signr = 0;
++	}
++
++	return signr;
++}
++
+ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
+ 			  struct pt_regs *regs, void *cookie)
+ {
+@@ -1785,36 +1824,10 @@ relock:
+ 		if (!signr)
+ 			break; /* will return 0 */
+ 
+-		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
+-			ptrace_signal_deliver(regs, cookie);
+-
+-			/* Let the debugger run.  */
+-			ptrace_stop(signr, 0, info);
+-
+-			/* We're back.  Did the debugger cancel the sig?  */
+-			signr = current->exit_code;
+-			if (signr == 0)
+-				continue;
+-
+-			current->exit_code = 0;
+-
+-			/* Update the siginfo structure if the signal has
+-			   changed.  If the debugger wanted something
+-			   specific in the siginfo structure then it should
+-			   have updated *info via PTRACE_SETSIGINFO.  */
+-			if (signr != info->si_signo) {
+-				info->si_signo = signr;
+-				info->si_errno = 0;
+-				info->si_code = SI_USER;
+-				info->si_pid = task_pid_vnr(current->parent);
+-				info->si_uid = current->parent->uid;
+-			}
+-
+-			/* If the (new) signal is now blocked, requeue it.  */
+-			if (sigismember(&current->blocked, signr)) {
+-				specific_send_sig_info(signr, info, current);
++		if (signr != SIGKILL) {
++			signr = ptrace_signal(signr, info, regs, cookie);
++			if (!signr)
+ 				continue;
+-			}
+ 		}
+ 
+ 		ka = &current->sighand->action[signr-1];
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index 31e9f2a..3c44956 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -356,7 +356,8 @@ void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
+ /* Tasklets */
+ struct tasklet_head
+ {
+-	struct tasklet_struct *list;
++	struct tasklet_struct *head;
++	struct tasklet_struct **tail;
+ };
+ 
+ /* Some compilers disobey section attribute on statics when not
+@@ -369,8 +370,9 @@ void __tasklet_schedule(struct tasklet_struct *t)
+ 	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+-	t->next = __get_cpu_var(tasklet_vec).list;
+-	__get_cpu_var(tasklet_vec).list = t;
++	t->next = NULL;
++	*__get_cpu_var(tasklet_vec).tail = t;
++	__get_cpu_var(tasklet_vec).tail = &(t->next);
+ 	raise_softirq_irqoff(TASKLET_SOFTIRQ);
+ 	local_irq_restore(flags);
+ }
+@@ -382,8 +384,9 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
+ 	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+-	t->next = __get_cpu_var(tasklet_hi_vec).list;
+-	__get_cpu_var(tasklet_hi_vec).list = t;
++	t->next = NULL;
++	*__get_cpu_var(tasklet_hi_vec).tail = t;
++	__get_cpu_var(tasklet_hi_vec).tail = &(t->next);
+ 	raise_softirq_irqoff(HI_SOFTIRQ);
+ 	local_irq_restore(flags);
+ }
+@@ -395,8 +398,9 @@ static void tasklet_action(struct softirq_action *a)
+ 	struct tasklet_struct *list;
+ 
+ 	local_irq_disable();
+-	list = __get_cpu_var(tasklet_vec).list;
+-	__get_cpu_var(tasklet_vec).list = NULL;
++	list = __get_cpu_var(tasklet_vec).head;
++	__get_cpu_var(tasklet_vec).head = NULL;
++	__get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head;
+ 	local_irq_enable();
+ 
+ 	while (list) {
+@@ -416,8 +420,9 @@ static void tasklet_action(struct softirq_action *a)
+ 		}
+ 
+ 		local_irq_disable();
+-		t->next = __get_cpu_var(tasklet_vec).list;
+-		__get_cpu_var(tasklet_vec).list = t;
++		t->next = NULL;
++		*__get_cpu_var(tasklet_vec).tail = t;
++		__get_cpu_var(tasklet_vec).tail = &(t->next);
+ 		__raise_softirq_irqoff(TASKLET_SOFTIRQ);
+ 		local_irq_enable();
+ 	}
+@@ -428,8 +433,9 @@ static void tasklet_hi_action(struct softirq_action *a)
+ 	struct tasklet_struct *list;
+ 
+ 	local_irq_disable();
+-	list = __get_cpu_var(tasklet_hi_vec).list;
+-	__get_cpu_var(tasklet_hi_vec).list = NULL;
++	list = __get_cpu_var(tasklet_hi_vec).head;
++	__get_cpu_var(tasklet_hi_vec).head = NULL;
++	__get_cpu_var(tasklet_hi_vec).tail = &__get_cpu_var(tasklet_hi_vec).head;
+ 	local_irq_enable();
+ 
+ 	while (list) {
+@@ -449,8 +455,9 @@ static void tasklet_hi_action(struct softirq_action *a)
+ 		}
+ 
+ 		local_irq_disable();
+-		t->next = __get_cpu_var(tasklet_hi_vec).list;
+-		__get_cpu_var(tasklet_hi_vec).list = t;
++		t->next = NULL;
++		*__get_cpu_var(tasklet_hi_vec).tail = t;
++		__get_cpu_var(tasklet_hi_vec).tail = &(t->next);
+ 		__raise_softirq_irqoff(HI_SOFTIRQ);
+ 		local_irq_enable();
+ 	}
+@@ -487,6 +494,15 @@ EXPORT_SYMBOL(tasklet_kill);
+ 
+ void __init softirq_init(void)
+ {
++	int cpu;
++
++	for_each_possible_cpu(cpu) {
++		per_cpu(tasklet_vec, cpu).tail =
++			&per_cpu(tasklet_vec, cpu).head;
++		per_cpu(tasklet_hi_vec, cpu).tail =
++			&per_cpu(tasklet_hi_vec, cpu).head;
++	}
++
+ 	open_softirq(TASKLET_SOFTIRQ, tasklet_action, NULL);
+ 	open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL);
+ }
+@@ -555,9 +571,12 @@ void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu)
+ 		return;
+ 
+ 	/* CPU is dead, so no lock needed. */
+-	for (i = &per_cpu(tasklet_vec, cpu).list; *i; i = &(*i)->next) {
++	for (i = &per_cpu(tasklet_vec, cpu).head; *i; i = &(*i)->next) {
+ 		if (*i == t) {
+ 			*i = t->next;
++			/* If this was the tail element, move the tail ptr */
++			if (*i == NULL)
++				per_cpu(tasklet_vec, cpu).tail = i;
+ 			return;
+ 		}
+ 	}
+@@ -566,20 +585,20 @@ void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu)
+ 
+ static void takeover_tasklets(unsigned int cpu)
+ {
+-	struct tasklet_struct **i;
+-
+ 	/* CPU is dead, so no lock needed. */
+ 	local_irq_disable();
+ 
+ 	/* Find end, append list for that CPU. */
+-	for (i = &__get_cpu_var(tasklet_vec).list; *i; i = &(*i)->next);
+-	*i = per_cpu(tasklet_vec, cpu).list;
+-	per_cpu(tasklet_vec, cpu).list = NULL;
++	*__get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).head;
++	__get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).tail;
++	per_cpu(tasklet_vec, cpu).head = NULL;
++	per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;
+ 	raise_softirq_irqoff(TASKLET_SOFTIRQ);
+ 
+-	for (i = &__get_cpu_var(tasklet_hi_vec).list; *i; i = &(*i)->next);
+-	*i = per_cpu(tasklet_hi_vec, cpu).list;
+-	per_cpu(tasklet_hi_vec, cpu).list = NULL;
++	*__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).head;
++	__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).tail;
++	per_cpu(tasklet_hi_vec, cpu).head = NULL;
++	per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;
+ 	raise_softirq_irqoff(HI_SOFTIRQ);
+ 
+ 	local_irq_enable();
+diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
+index 6f4e0e1..0101aee 100644
+--- a/kernel/stop_machine.c
++++ b/kernel/stop_machine.c
+@@ -11,7 +11,6 @@
+ #include <linux/interrupt.h>
+ 
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ 
+ /* Since we effect priority and affinity (both of which are visible
+@@ -35,7 +34,7 @@ static int stopmachine(void *cpu)
+ 	int irqs_disabled = 0;
+ 	int prepared = 0;
+ 
+-	set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu));
++	set_cpus_allowed_ptr(current, &cpumask_of_cpu((int)(long)cpu));
+ 
+ 	/* Ack: we are alive */
+ 	smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
+@@ -135,8 +134,7 @@ static void restart_machine(void)
+ 	preempt_enable_no_resched();
+ }
+ 
+-struct stop_machine_data
+-{
++struct stop_machine_data {
+ 	int (*fn)(void *);
+ 	void *data;
+ 	struct completion done;
+diff --git a/kernel/sys.c b/kernel/sys.c
+index a626116..6a0cc71 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -67,6 +67,12 @@
+ #ifndef SET_ENDIAN
+ # define SET_ENDIAN(a,b)	(-EINVAL)
+ #endif
++#ifndef GET_TSC_CTL
++# define GET_TSC_CTL(a)		(-EINVAL)
++#endif
++#ifndef SET_TSC_CTL
++# define SET_TSC_CTL(a)		(-EINVAL)
++#endif
+ 
+ /*
+  * this is where the system-wide overflow UID and GID are defined, for
+@@ -1737,7 +1743,12 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+ #else
+ 			return -EINVAL;
+ #endif
+-
++		case PR_GET_TSC:
++			error = GET_TSC_CTL(arg2);
++			break;
++		case PR_SET_TSC:
++			error = SET_TSC_CTL(arg2);
++			break;
+ 		default:
+ 			error = -EINVAL;
+ 			break;
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index b2a2d68..fd33648 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -270,17 +270,6 @@ static struct ctl_table kern_table[] = {
+ 	},
+ 	{
+ 		.ctl_name	= CTL_UNNUMBERED,
+-		.procname	= "sched_batch_wakeup_granularity_ns",
+-		.data		= &sysctl_sched_batch_wakeup_granularity,
+-		.maxlen		= sizeof(unsigned int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec_minmax,
+-		.strategy	= &sysctl_intvec,
+-		.extra1		= &min_wakeup_granularity_ns,
+-		.extra2		= &max_wakeup_granularity_ns,
+-	},
+-	{
+-		.ctl_name	= CTL_UNNUMBERED,
+ 		.procname	= "sched_child_runs_first",
+ 		.data		= &sysctl_sched_child_runs_first,
+ 		.maxlen		= sizeof(unsigned int),
+@@ -318,7 +307,7 @@ static struct ctl_table kern_table[] = {
+ 		.data		= &sysctl_sched_rt_period,
+ 		.maxlen		= sizeof(unsigned int),
+ 		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec,
++		.proc_handler	= &sched_rt_handler,
+ 	},
+ 	{
+ 		.ctl_name	= CTL_UNNUMBERED,
+@@ -326,7 +315,7 @@ static struct ctl_table kern_table[] = {
+ 		.data		= &sysctl_sched_rt_runtime,
+ 		.maxlen		= sizeof(int),
+ 		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec,
++		.proc_handler	= &sched_rt_handler,
+ 	},
+ 	{
+ 		.ctl_name	= CTL_UNNUMBERED,
+diff --git a/kernel/time.c b/kernel/time.c
+index a5ec013..35d373a 100644
+--- a/kernel/time.c
++++ b/kernel/time.c
+@@ -379,6 +379,7 @@ void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec)
+ 	ts->tv_sec = sec;
+ 	ts->tv_nsec = nsec;
+ }
++EXPORT_SYMBOL(set_normalized_timespec);
+ 
+ /**
+  * ns_to_timespec - Convert nanoseconds to timespec
+diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
+index 7f60097..73961f3 100644
+--- a/kernel/time/clocksource.c
++++ b/kernel/time/clocksource.c
+@@ -141,8 +141,16 @@ static void clocksource_watchdog(unsigned long data)
+ 	}
+ 
+ 	if (!list_empty(&watchdog_list)) {
+-		__mod_timer(&watchdog_timer,
+-			    watchdog_timer.expires + WATCHDOG_INTERVAL);
++		/*
++		 * Cycle through CPUs to check if the CPUs stay
++		 * synchronized to each other.
++		 */
++		int next_cpu = next_cpu(raw_smp_processor_id(), cpu_online_map);
++
++		if (next_cpu >= NR_CPUS)
++			next_cpu = first_cpu(cpu_online_map);
++		watchdog_timer.expires += WATCHDOG_INTERVAL;
++		add_timer_on(&watchdog_timer, next_cpu);
+ 	}
+ 	spin_unlock(&watchdog_lock);
+ }
+@@ -164,7 +172,8 @@ static void clocksource_check_watchdog(struct clocksource *cs)
+ 		if (!started && watchdog) {
+ 			watchdog_last = watchdog->read();
+ 			watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
+-			add_timer(&watchdog_timer);
++			add_timer_on(&watchdog_timer,
++				     first_cpu(cpu_online_map));
+ 		}
+ 	} else {
+ 		if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
+@@ -185,7 +194,8 @@ static void clocksource_check_watchdog(struct clocksource *cs)
+ 				watchdog_last = watchdog->read();
+ 				watchdog_timer.expires =
+ 					jiffies + WATCHDOG_INTERVAL;
+-				add_timer(&watchdog_timer);
++				add_timer_on(&watchdog_timer,
++					     first_cpu(cpu_online_map));
+ 			}
+ 		}
+ 	}
+@@ -222,6 +232,18 @@ void clocksource_resume(void)
+ }
+ 
+ /**
++ * clocksource_touch_watchdog - Update watchdog
++ *
++ * Update the watchdog after exception contexts such as kgdb so as not
++ * to incorrectly trip the watchdog.
++ *
++ */
++void clocksource_touch_watchdog(void)
++{
++	clocksource_resume_watchdog();
++}
++
++/**
+  * clocksource_get_next - Returns the selected clocksource
+  *
+  */
+diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
+index e1bd50c..57a1f02 100644
+--- a/kernel/time/tick-broadcast.c
++++ b/kernel/time/tick-broadcast.c
+@@ -14,7 +14,7 @@
+ #include <linux/cpu.h>
+ #include <linux/err.h>
+ #include <linux/hrtimer.h>
+-#include <linux/irq.h>
++#include <linux/interrupt.h>
+ #include <linux/percpu.h>
+ #include <linux/profile.h>
+ #include <linux/sched.h>
+@@ -262,7 +262,7 @@ out:
+ void tick_broadcast_on_off(unsigned long reason, int *oncpu)
+ {
+ 	if (!cpu_isset(*oncpu, cpu_online_map))
+-		printk(KERN_ERR "tick-braodcast: ignoring broadcast for "
++		printk(KERN_ERR "tick-broadcast: ignoring broadcast for "
+ 		       "offline CPU #%d\n", *oncpu);
+ 	else
+ 		smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
+diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
+index 1bea399..4f38865 100644
+--- a/kernel/time/tick-common.c
++++ b/kernel/time/tick-common.c
+@@ -14,12 +14,14 @@
+ #include <linux/cpu.h>
+ #include <linux/err.h>
+ #include <linux/hrtimer.h>
+-#include <linux/irq.h>
++#include <linux/interrupt.h>
+ #include <linux/percpu.h>
+ #include <linux/profile.h>
+ #include <linux/sched.h>
+ #include <linux/tick.h>
+ 
++#include <asm/irq_regs.h>
++
+ #include "tick-internal.h"
+ 
+ /*
+diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c
+index 0258d31..450c049 100644
+--- a/kernel/time/tick-oneshot.c
++++ b/kernel/time/tick-oneshot.c
+@@ -14,7 +14,7 @@
+ #include <linux/cpu.h>
+ #include <linux/err.h>
+ #include <linux/hrtimer.h>
+-#include <linux/irq.h>
++#include <linux/interrupt.h>
+ #include <linux/percpu.h>
+ #include <linux/profile.h>
+ #include <linux/sched.h>
+diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
+index 686da82..b854a89 100644
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -158,9 +158,8 @@ void tick_nohz_stop_idle(int cpu)
+ 	}
+ }
+ 
+-static ktime_t tick_nohz_start_idle(int cpu)
++static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
+ {
+-	struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+ 	ktime_t now, delta;
+ 
+ 	now = ktime_get();
+@@ -192,7 +191,6 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
+ void tick_nohz_stop_sched_tick(void)
+ {
+ 	unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
+-	unsigned long rt_jiffies;
+ 	struct tick_sched *ts;
+ 	ktime_t last_update, expires, now;
+ 	struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+@@ -201,8 +199,8 @@ void tick_nohz_stop_sched_tick(void)
+ 	local_irq_save(flags);
+ 
+ 	cpu = smp_processor_id();
+-	now = tick_nohz_start_idle(cpu);
+ 	ts = &per_cpu(tick_cpu_sched, cpu);
++	now = tick_nohz_start_idle(ts);
+ 
+ 	/*
+ 	 * If this cpu is offline and it is the one which updates
+@@ -222,7 +220,6 @@ void tick_nohz_stop_sched_tick(void)
+ 	if (need_resched())
+ 		goto end;
+ 
+-	cpu = smp_processor_id();
+ 	if (unlikely(local_softirq_pending())) {
+ 		static int ratelimit;
+ 
+@@ -245,10 +242,6 @@ void tick_nohz_stop_sched_tick(void)
+ 	next_jiffies = get_next_timer_interrupt(last_jiffies);
+ 	delta_jiffies = next_jiffies - last_jiffies;
+ 
+-	rt_jiffies = rt_needs_cpu(cpu);
+-	if (rt_jiffies && rt_jiffies < delta_jiffies)
+-		delta_jiffies = rt_jiffies;
+-
+ 	if (rcu_needs_cpu(cpu))
+ 		delta_jiffies = 1;
+ 	/*
+@@ -400,6 +393,7 @@ void tick_nohz_restart_sched_tick(void)
+ 		sub_preempt_count(HARDIRQ_OFFSET);
+ 	}
+ 
++	touch_softlockup_watchdog();
+ 	/*
+ 	 * Cancel the scheduled timer and restore the tick
+ 	 */
+diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
+index a3fa587..2d6087c 100644
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -178,6 +178,7 @@ static void change_clocksource(void)
+ 	if (clock == new)
+ 		return;
+ 
++	new->cycle_last = 0;
+ 	now = clocksource_read(new);
+ 	nsec =  __get_nsec_offset();
+ 	timespec_add_ns(&xtime, nsec);
+@@ -295,6 +296,7 @@ static int timekeeping_resume(struct sys_device *dev)
+ 	timespec_add_ns(&xtime, timekeeping_suspend_nsecs);
+ 	update_xtime_cache(0);
+ 	/* re-base the last cycle value */
++	clock->cycle_last = 0;
+ 	clock->cycle_last = clocksource_read(clock);
+ 	clock->error = 0;
+ 	timekeeping_suspended = 0;
+diff --git a/kernel/timer.c b/kernel/timer.c
+index b024106..f3d35d4 100644
+--- a/kernel/timer.c
++++ b/kernel/timer.c
+@@ -1228,13 +1228,6 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info)
+ 	return 0;
+ }
+ 
+-/*
+- * lockdep: we want to track each per-CPU base as a separate lock-class,
+- * but timer-bases are kmalloc()-ed, so we need to attach separate
+- * keys to them:
+- */
+-static struct lock_class_key base_lock_keys[NR_CPUS];
+-
+ static int __cpuinit init_timers_cpu(int cpu)
+ {
+ 	int j;
+@@ -1277,7 +1270,6 @@ static int __cpuinit init_timers_cpu(int cpu)
+ 	}
+ 
+ 	spin_lock_init(&base->lock);
+-	lockdep_set_class(&base->lock, base_lock_keys + cpu);
+ 
+ 	for (j = 0; j < TVN_SIZE; j++) {
+ 		INIT_LIST_HEAD(base->tv5.vec + j);
+@@ -1316,8 +1308,8 @@ static void __cpuinit migrate_timers(int cpu)
+ 	new_base = get_cpu_var(tvec_bases);
+ 
+ 	local_irq_disable();
+-	double_spin_lock(&new_base->lock, &old_base->lock,
+-			 smp_processor_id() < cpu);
++	spin_lock(&new_base->lock);
++	spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
+ 
+ 	BUG_ON(old_base->running_timer);
+ 
+@@ -1330,8 +1322,8 @@ static void __cpuinit migrate_timers(int cpu)
+ 		migrate_timer_list(new_base, old_base->tv5.vec + i);
+ 	}
+ 
+-	double_spin_unlock(&new_base->lock, &old_base->lock,
+-			   smp_processor_id() < cpu);
++	spin_unlock(&old_base->lock);
++	spin_unlock(&new_base->lock);
+ 	local_irq_enable();
+ 	put_cpu_var(tvec_bases);
+ }
+diff --git a/kernel/user.c b/kernel/user.c
+index 7132022..debce60 100644
+--- a/kernel/user.c
++++ b/kernel/user.c
+@@ -101,7 +101,7 @@ static int sched_create_user(struct user_struct *up)
+ {
+ 	int rc = 0;
+ 
+-	up->tg = sched_create_group();
++	up->tg = sched_create_group(&root_task_group);
+ 	if (IS_ERR(up->tg))
+ 		rc = -ENOMEM;
+ 
+@@ -193,6 +193,33 @@ static ssize_t cpu_rt_runtime_store(struct kobject *kobj,
+ 
+ static struct kobj_attribute cpu_rt_runtime_attr =
+ 	__ATTR(cpu_rt_runtime, 0644, cpu_rt_runtime_show, cpu_rt_runtime_store);
++
++static ssize_t cpu_rt_period_show(struct kobject *kobj,
++				   struct kobj_attribute *attr,
++				   char *buf)
++{
++	struct user_struct *up = container_of(kobj, struct user_struct, kobj);
++
++	return sprintf(buf, "%lu\n", sched_group_rt_period(up->tg));
++}
++
++static ssize_t cpu_rt_period_store(struct kobject *kobj,
++				    struct kobj_attribute *attr,
++				    const char *buf, size_t size)
++{
++	struct user_struct *up = container_of(kobj, struct user_struct, kobj);
++	unsigned long rt_period;
++	int rc;
++
++	sscanf(buf, "%lu", &rt_period);
++
++	rc = sched_group_set_rt_period(up->tg, rt_period);
++
++	return (rc ? rc : size);
++}
++
++static struct kobj_attribute cpu_rt_period_attr =
++	__ATTR(cpu_rt_period, 0644, cpu_rt_period_show, cpu_rt_period_store);
+ #endif
+ 
+ /* default attributes per uid directory */
+@@ -202,6 +229,7 @@ static struct attribute *uids_attributes[] = {
+ #endif
+ #ifdef CONFIG_RT_GROUP_SCHED
+ 	&cpu_rt_runtime_attr.attr,
++	&cpu_rt_period_attr.attr,
+ #endif
+ 	NULL
+ };
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index ff06611..00ff4d0 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -219,6 +219,7 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
+ 	struct timer_list *timer = &dwork->timer;
+ 	struct work_struct *work = &dwork->work;
+ 
++	timer_stats_timer_set_start_info(&dwork->timer);
+ 	if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
+ 		BUG_ON(timer_pending(timer));
+ 		BUG_ON(!list_empty(&work->entry));
+@@ -580,6 +581,7 @@ EXPORT_SYMBOL(schedule_delayed_work);
+ int schedule_delayed_work_on(int cpu,
+ 			struct delayed_work *dwork, unsigned long delay)
+ {
++	timer_stats_timer_set_start_info(&dwork->timer);
+ 	return queue_delayed_work_on(cpu, keventd_wq, dwork, delay);
+ }
+ EXPORT_SYMBOL(schedule_delayed_work_on);
+diff --git a/lib/Kconfig b/lib/Kconfig
+index ba3d104..2d53dc0 100644
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -141,4 +141,7 @@ config HAS_DMA
+ config CHECK_SIGNATURE
+ 	bool
+ 
++config HAVE_LMB
++	boolean
++
+ endmenu
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index 0796c1a..754cc00 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -25,6 +25,17 @@ config ENABLE_MUST_CHECK
+ 	  suppress the "warning: ignoring return value of 'foo', declared with
+ 	  attribute warn_unused_result" messages.
+ 
++config FRAME_WARN
++	int "Warn for stack frames larger than (needs gcc 4.4)"
++	range 0 8192
++	default 1024 if !64BIT
++	default 2048 if 64BIT
++	help
++	  Tell gcc to warn at build time for stack frames larger than this.
++	  Setting this too low will cause a lot of warnings.
++	  Setting it to 0 disables the warning.
++	  Requires gcc 4.4
++
+ config MAGIC_SYSRQ
+ 	bool "Magic SysRq key"
+ 	depends on !UML
+@@ -211,7 +222,7 @@ config SLUB_DEBUG_ON
+ config SLUB_STATS
+ 	default n
+ 	bool "Enable SLUB performance statistics"
+-	depends on SLUB
++	depends on SLUB && SLUB_DEBUG && SYSFS
+ 	help
+ 	  SLUB statistics are useful to debug SLUBs allocation behavior in
+ 	  order find ways to optimize the allocator. This should never be
+@@ -265,16 +276,6 @@ config DEBUG_MUTEXES
+ 	 This feature allows mutex semantics violations to be detected and
+ 	 reported.
+ 
+-config DEBUG_SEMAPHORE
+-	bool "Semaphore debugging"
+-	depends on DEBUG_KERNEL
+-	depends on ALPHA || FRV
+-	default n
+-	help
+-	  If you say Y here then semaphore processing will issue lots of
+-	  verbose debugging messages.  If you suspect a semaphore problem or a
+-	  kernel hacker asks for this option then say Y.  Otherwise say N.
+-
+ config DEBUG_LOCK_ALLOC
+ 	bool "Lock debugging: detect incorrect freeing of live locks"
+ 	depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
+@@ -437,6 +438,16 @@ config DEBUG_VM
+ 
+ 	  If unsure, say N.
+ 
++config DEBUG_WRITECOUNT
++	bool "Debug filesystem writers count"
++	depends on DEBUG_KERNEL
++	help
++	  Enable this to catch wrong use of the writers count in struct
++	  vfsmount.  This will increase the size of each file struct by
++	  32 bits.
++
++	  If unsure, say N.
++
+ config DEBUG_LIST
+ 	bool "Debug linked list manipulation"
+ 	depends on DEBUG_KERNEL
+@@ -593,7 +604,7 @@ config LATENCYTOP
+ 	  to find out which userspace is blocking on what kernel operations.
+ 
+ config PROVIDE_OHCI1394_DMA_INIT
+-	bool "Provide code for enabling DMA over FireWire early on boot"
++	bool "Remote debugging over FireWire early on boot"
+ 	depends on PCI && X86
+ 	help
+ 	  If you want to debug problems which hang or crash the kernel early
+@@ -621,4 +632,17 @@ config PROVIDE_OHCI1394_DMA_INIT
+ 
+ 	  See Documentation/debugging-via-ohci1394.txt for more information.
+ 
++config FIREWIRE_OHCI_REMOTE_DMA
++	bool "Remote debugging over FireWire with firewire-ohci"
++	depends on FIREWIRE_OHCI
++	help
++	  This option lets you use the FireWire bus for remote debugging
++	  with help of the firewire-ohci driver. It enables unfiltered
++	  remote DMA in firewire-ohci.
++	  See Documentation/debugging-via-ohci1394.txt for more information.
++
++	  If unsure, say N.
++
+ source "samples/Kconfig"
++
++source "lib/Kconfig.kgdb"
+diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb
+new file mode 100644
+index 0000000..f2e01ac
+--- /dev/null
++++ b/lib/Kconfig.kgdb
+@@ -0,0 +1,58 @@
++
++menuconfig KGDB
++	bool "KGDB: kernel debugging with remote gdb"
++	select FRAME_POINTER
++	depends on HAVE_ARCH_KGDB
++	depends on DEBUG_KERNEL && EXPERIMENTAL
++	help
++	  If you say Y here, it will be possible to remotely debug the
++	  kernel using gdb.  Documentation of kernel debugger is available
++	  at http://kgdb.sourceforge.net as well as in DocBook form
++	  in Documentation/DocBook/.  If unsure, say N.
++
++config HAVE_ARCH_KGDB_SHADOW_INFO
++	bool
++
++config HAVE_ARCH_KGDB
++	bool
++
++config KGDB_SERIAL_CONSOLE
++	tristate "KGDB: use kgdb over the serial console"
++	depends on KGDB
++	select CONSOLE_POLL
++	select MAGIC_SYSRQ
++	default y
++	help
++	  Share a serial console with kgdb. Sysrq-g must be used
++	  to break in initially.
++
++config KGDB_TESTS
++	bool "KGDB: internal test suite"
++	depends on KGDB
++	default n
++	help
++	  This is a kgdb I/O module specifically designed to test
++	  kgdb's internal functions.  This kgdb I/O module is
++	  intended to for the development of new kgdb stubs
++	  as well as regression testing the kgdb internals.
++	  See the drivers/misc/kgdbts.c for the details about
++	  the tests.  The most basic of this I/O module is to boot
++	  a kernel boot arguments "kgdbwait kgdbts=V1F100"
++
++config KGDB_TESTS_ON_BOOT
++	bool "KGDB: Run tests on boot"
++	depends on KGDB_TESTS
++	default n
++	help
++	  Run the kgdb tests on boot up automatically without the need
++	  to pass in a kernel parameter
++
++config KGDB_TESTS_BOOT_STRING
++	string "KGDB: which internal kgdb tests to run"
++	depends on KGDB_TESTS_ON_BOOT
++	default "V1F100"
++	help
++	  This is the command string to send the kgdb test suite on
++	  boot.  See the drivers/misc/kgdbts.c for detailed
++	  information about other strings you could use beyond the
++	  default of V1F100.
+diff --git a/lib/Makefile b/lib/Makefile
+index 23de261..bf8000f 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -29,7 +29,6 @@ obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
+ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
+ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
+ lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+-lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o
+ lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
+ obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
+ obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
+@@ -61,7 +60,6 @@ obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
+ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o
+ obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
+ obj-$(CONFIG_SMP) += percpu_counter.o
+-obj-$(CONFIG_SMP) += pcounter.o
+ obj-$(CONFIG_AUDIT_GENERIC) += audit.o
+ 
+ obj-$(CONFIG_SWIOTLB) += swiotlb.o
+@@ -70,6 +68,8 @@ obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
+ 
+ lib-$(CONFIG_GENERIC_BUG) += bug.o
+ 
++obj-$(CONFIG_HAVE_LMB) += lmb.o
++
+ hostprogs-y	:= gen_crc32table
+ clean-files	:= crc32table.h
+ 
+diff --git a/lib/bitmap.c b/lib/bitmap.c
+index 2c9242e..a6939e1 100644
+--- a/lib/bitmap.c
++++ b/lib/bitmap.c
+@@ -316,6 +316,22 @@ int bitmap_scnprintf(char *buf, unsigned int buflen,
+ EXPORT_SYMBOL(bitmap_scnprintf);
+ 
+ /**
++ * bitmap_scnprintf_len - return buffer length needed to convert
++ * bitmap to an ASCII hex string.
++ * @len: number of bits to be converted
++ */
++int bitmap_scnprintf_len(unsigned int len)
++{
++	/* we need 9 chars per word for 32 bit words (8 hexdigits + sep/null) */
++	int bitslen = ALIGN(len, CHUNKSZ);
++	int wordlen = CHUNKSZ / 4;
++	int buflen = (bitslen / wordlen) * (wordlen + 1) * sizeof(char);
++
++	return buflen;
++}
++EXPORT_SYMBOL(bitmap_scnprintf_len);
++
++/**
+  * __bitmap_parse - convert an ASCII hex string into a bitmap.
+  * @buf: pointer to buffer containing string.
+  * @buflen: buffer size in bytes.  If string is smaller than this
+diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
+index 812dbf0..cd3e825 100644
+--- a/lib/kernel_lock.c
++++ b/lib/kernel_lock.c
+@@ -8,6 +8,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/module.h>
+ #include <linux/kallsyms.h>
++#include <linux/semaphore.h>
+ 
+ /*
+  * The 'big kernel semaphore'
+diff --git a/lib/kobject.c b/lib/kobject.c
+index 0d03252..2c64903 100644
+--- a/lib/kobject.c
++++ b/lib/kobject.c
+@@ -58,11 +58,6 @@ static int create_dir(struct kobject *kobj)
+ 	return error;
+ }
+ 
+-static inline struct kobject *to_kobj(struct list_head *entry)
+-{
+-	return container_of(entry, struct kobject, entry);
+-}
+-
+ static int get_kobj_path_length(struct kobject *kobj)
+ {
+ 	int length = 1;
+@@ -592,8 +587,15 @@ static void kobject_release(struct kref *kref)
+  */
+ void kobject_put(struct kobject *kobj)
+ {
+-	if (kobj)
++	if (kobj) {
++		if (!kobj->state_initialized) {
++			printk(KERN_WARNING "kobject: '%s' (%p): is not "
++			       "initialized, yet kobject_put() is being "
++			       "called.\n", kobject_name(kobj), kobj);
++			WARN_ON(1);
++		}
+ 		kref_put(&kobj->kref, kobject_release);
++	}
+ }
+ 
+ static void dynamic_kobj_release(struct kobject *kobj)
+@@ -745,12 +747,11 @@ void kset_unregister(struct kset *k)
+  */
+ struct kobject *kset_find_obj(struct kset *kset, const char *name)
+ {
+-	struct list_head *entry;
++	struct kobject *k;
+ 	struct kobject *ret = NULL;
+ 
+ 	spin_lock(&kset->list_lock);
+-	list_for_each(entry, &kset->list) {
+-		struct kobject *k = to_kobj(entry);
++	list_for_each_entry(k, &kset->list, entry) {
+ 		if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
+ 			ret = kobject_get(k);
+ 			break;
+diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
+index 5b6d7f6..9fb6b86 100644
+--- a/lib/kobject_uevent.c
++++ b/lib/kobject_uevent.c
+@@ -15,11 +15,13 @@
+  */
+ 
+ #include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/kobject.h>
++#include <linux/module.h>
++
+ #include <linux/socket.h>
+ #include <linux/skbuff.h>
+ #include <linux/netlink.h>
+-#include <linux/string.h>
+-#include <linux/kobject.h>
+ #include <net/sock.h>
+ 
+ 
+diff --git a/lib/lmb.c b/lib/lmb.c
+new file mode 100644
+index 0000000..207147a
+--- /dev/null
++++ b/lib/lmb.c
+@@ -0,0 +1,428 @@
++/*
++ * Procedures for maintaining information about logical memory blocks.
++ *
++ * Peter Bergner, IBM Corp.	June 2001.
++ * Copyright (C) 2001 Peter Bergner.
++ *
++ *      This program is free software; you can redistribute it and/or
++ *      modify it under the terms of the GNU General Public License
++ *      as published by the Free Software Foundation; either version
++ *      2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/bitops.h>
++#include <linux/lmb.h>
++
++#define LMB_ALLOC_ANYWHERE	0
++
++struct lmb lmb;
++
++void lmb_dump_all(void)
++{
++#ifdef DEBUG
++	unsigned long i;
++
++	pr_debug("lmb_dump_all:\n");
++	pr_debug("    memory.cnt		  = 0x%lx\n", lmb.memory.cnt);
++	pr_debug("    memory.size		  = 0x%llx\n",
++	    (unsigned long long)lmb.memory.size);
++	for (i=0; i < lmb.memory.cnt ;i++) {
++		pr_debug("    memory.region[0x%x].base       = 0x%llx\n",
++		    i, (unsigned long long)lmb.memory.region[i].base);
++		pr_debug("		      .size     = 0x%llx\n",
++		    (unsigned long long)lmb.memory.region[i].size);
++	}
++
++	pr_debug("    reserved.cnt	  = 0x%lx\n", lmb.reserved.cnt);
++	pr_debug("    reserved.size	  = 0x%lx\n", lmb.reserved.size);
++	for (i=0; i < lmb.reserved.cnt ;i++) {
++		pr_debug("    reserved.region[0x%x].base       = 0x%llx\n",
++		    i, (unsigned long long)lmb.reserved.region[i].base);
++		pr_debug("		      .size     = 0x%llx\n",
++		    (unsigned long long)lmb.reserved.region[i].size);
++	}
++#endif /* DEBUG */
++}
++
++static unsigned long __init lmb_addrs_overlap(u64 base1, u64 size1,
++		u64 base2, u64 size2)
++{
++	return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
++}
++
++static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
++		u64 base2, u64 size2)
++{
++	if (base2 == base1 + size1)
++		return 1;
++	else if (base1 == base2 + size2)
++		return -1;
++
++	return 0;
++}
++
++static long __init lmb_regions_adjacent(struct lmb_region *rgn,
++		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;
++
++	return lmb_addrs_adjacent(base1, size1, base2, size2);
++}
++
++static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
++{
++	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;
++	}
++	rgn->cnt--;
++}
++
++/* Assumption: base addr of region 1 < base addr of region 2 */
++static void __init lmb_coalesce_regions(struct lmb_region *rgn,
++		unsigned long r1, unsigned long r2)
++{
++	rgn->region[r1].size += rgn->region[r2].size;
++	lmb_remove_region(rgn, r2);
++}
++
++void __init lmb_init(void)
++{
++	/* Create a dummy zero size LMB which will get coalesced away later.
++	 * This simplifies the lmb_add() code below...
++	 */
++	lmb.memory.region[0].base = 0;
++	lmb.memory.region[0].size = 0;
++	lmb.memory.cnt = 1;
++
++	/* Ditto. */
++	lmb.reserved.region[0].base = 0;
++	lmb.reserved.region[0].size = 0;
++	lmb.reserved.cnt = 1;
++}
++
++void __init lmb_analyze(void)
++{
++	int i;
++
++	lmb.memory.size = 0;
++
++	for (i = 0; i < lmb.memory.cnt; i++)
++		lmb.memory.size += lmb.memory.region[i].size;
++}
++
++static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 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;
++		return 0;
++	}
++
++	/* First try and coalesce this LMB with another. */
++	for (i = 0; i < rgn->cnt; i++) {
++		u64 rgnbase = rgn->region[i].base;
++		u64 rgnsize = rgn->region[i].size;
++
++		if ((rgnbase == base) && (rgnsize == size))
++			/* Already have this region, so we're done */
++			return 0;
++
++		adjacent = lmb_addrs_adjacent(base, size, rgnbase, rgnsize);
++		if (adjacent > 0) {
++			rgn->region[i].base -= size;
++			rgn->region[i].size += size;
++			coalesced++;
++			break;
++		} else if (adjacent < 0) {
++			rgn->region[i].size += size;
++			coalesced++;
++			break;
++		}
++	}
++
++	if ((i < rgn->cnt - 1) && lmb_regions_adjacent(rgn, i, i+1)) {
++		lmb_coalesce_regions(rgn, i, i+1);
++		coalesced++;
++	}
++
++	if (coalesced)
++		return coalesced;
++	if (rgn->cnt >= MAX_LMB_REGIONS)
++		return -1;
++
++	/* Couldn't coalesce the LMB, 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;
++		} else {
++			rgn->region[i+1].base = base;
++			rgn->region[i+1].size = size;
++			break;
++		}
++	}
++
++	if (base < rgn->region[0].base) {
++		rgn->region[0].base = base;
++		rgn->region[0].size = size;
++	}
++	rgn->cnt++;
++
++	return 0;
++}
++
++long __init lmb_add(u64 base, u64 size)
++{
++	struct lmb_region *_rgn = &lmb.memory;
++
++	/* On pSeries LPAR systems, the first LMB is our RMO region. */
++	if (base == 0)
++		lmb.rmo_size = size;
++
++	return lmb_add_region(_rgn, base, size);
++
++}
++
++long __init lmb_reserve(u64 base, u64 size)
++{
++	struct lmb_region *_rgn = &lmb.reserved;
++
++	BUG_ON(0 == size);
++
++	return lmb_add_region(_rgn, base, size);
++}
++
++long __init lmb_overlaps_region(struct lmb_region *rgn, u64 base, u64 size)
++{
++	unsigned long i;
++
++	for (i = 0; i < rgn->cnt; i++) {
++		u64 rgnbase = rgn->region[i].base;
++		u64 rgnsize = rgn->region[i].size;
++		if (lmb_addrs_overlap(base, size, rgnbase, rgnsize))
++			break;
++	}
++
++	return (i < rgn->cnt) ? i : -1;
++}
++
++static u64 lmb_align_down(u64 addr, u64 size)
++{
++	return addr & ~(size - 1);
++}
++
++static u64 lmb_align_up(u64 addr, u64 size)
++{
++	return (addr + (size - 1)) & ~(size - 1);
++}
++
++static u64 __init lmb_alloc_nid_unreserved(u64 start, u64 end,
++					   u64 size, u64 align)
++{
++	u64 base, res_base;
++	long j;
++
++	base = lmb_align_down((end - size), align);
++	while (start <= base) {
++		j = lmb_overlaps_region(&lmb.reserved, base, size);
++		if (j < 0) {
++			/* this area isn't reserved, take it */
++			if (lmb_add_region(&lmb.reserved, base,
++					   lmb_align_up(size, align)) < 0)
++				base = ~(u64)0;
++			return base;
++		}
++		res_base = lmb.reserved.region[j].base;
++		if (res_base < size)
++			break;
++		base = lmb_align_down(res_base - size, align);
++	}
++
++	return ~(u64)0;
++}
++
++static u64 __init lmb_alloc_nid_region(struct lmb_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 = lmb_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 = lmb_alloc_nid_unreserved(start, this_end,
++							   size, align);
++			if (ret != ~(u64)0)
++				return ret;
++		}
++		start = this_end;
++	}
++
++	return ~(u64)0;
++}
++
++u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
++			 u64 (*nid_range)(u64 start, u64 end, int *nid))
++{
++	struct lmb_region *mem = &lmb.memory;
++	int i;
++
++	for (i = 0; i < mem->cnt; i++) {
++		u64 ret = lmb_alloc_nid_region(&mem->region[i],
++					       nid_range,
++					       size, align, nid);
++		if (ret != ~(u64)0)
++			return ret;
++	}
++
++	return lmb_alloc(size, align);
++}
++
++u64 __init lmb_alloc(u64 size, u64 align)
++{
++	return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
++}
++
++u64 __init lmb_alloc_base(u64 size, u64 align, u64 max_addr)
++{
++	u64 alloc;
++
++	alloc = __lmb_alloc_base(size, align, max_addr);
++
++	if (alloc == 0)
++		panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n",
++		      (unsigned long long) size, (unsigned long long) max_addr);
++
++	return alloc;
++}
++
++u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr)
++{
++	long i, j;
++	u64 base = 0;
++	u64 res_base;
++
++	BUG_ON(0 == size);
++
++	/* On some platforms, make sure we allocate lowmem */
++	/* Note that LMB_REAL_LIMIT may be LMB_ALLOC_ANYWHERE */
++	if (max_addr == LMB_ALLOC_ANYWHERE)
++		max_addr = LMB_REAL_LIMIT;
++
++	for (i = lmb.memory.cnt - 1; i >= 0; i--) {
++		u64 lmbbase = lmb.memory.region[i].base;
++		u64 lmbsize = lmb.memory.region[i].size;
++
++		if (lmbsize < size)
++			continue;
++		if (max_addr == LMB_ALLOC_ANYWHERE)
++			base = lmb_align_down(lmbbase + lmbsize - size, align);
++		else if (lmbbase < max_addr) {
++			base = min(lmbbase + lmbsize, max_addr);
++			base = lmb_align_down(base - size, align);
++		} else
++			continue;
++
++		while (base && lmbbase <= base) {
++			j = lmb_overlaps_region(&lmb.reserved, base, size);
++			if (j < 0) {
++				/* this area isn't reserved, take it */
++				if (lmb_add_region(&lmb.reserved, base,
++						   lmb_align_up(size, align)) < 0)
++					return 0;
++				return base;
++			}
++			res_base = lmb.reserved.region[j].base;
++			if (res_base < size)
++				break;
++			base = lmb_align_down(res_base - size, align);
++		}
++	}
++	return 0;
++}
++
++/* You must call lmb_analyze() before this. */
++u64 __init lmb_phys_mem_size(void)
++{
++	return lmb.memory.size;
++}
++
++u64 __init lmb_end_of_DRAM(void)
++{
++	int idx = lmb.memory.cnt - 1;
++
++	return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
++}
++
++/* You must call lmb_analyze() after this. */
++void __init lmb_enforce_memory_limit(u64 memory_limit)
++{
++	unsigned long i;
++	u64 limit;
++	struct lmb_property *p;
++
++	if (!memory_limit)
++		return;
++
++	/* Truncate the lmb regions to satisfy the memory limit. */
++	limit = memory_limit;
++	for (i = 0; i < lmb.memory.cnt; i++) {
++		if (limit > lmb.memory.region[i].size) {
++			limit -= lmb.memory.region[i].size;
++			continue;
++		}
++
++		lmb.memory.region[i].size = limit;
++		lmb.memory.cnt = i + 1;
++		break;
++	}
++
++	if (lmb.memory.region[0].size < lmb.rmo_size)
++		lmb.rmo_size = lmb.memory.region[0].size;
++
++	/* And truncate any reserves above the limit also. */
++	for (i = 0; i < lmb.reserved.cnt; i++) {
++		p = &lmb.reserved.region[i];
++
++		if (p->base > memory_limit)
++			p->size = 0;
++		else if ((p->base + p->size) > memory_limit)
++			p->size = memory_limit - p->base;
++
++		if (p->size == 0) {
++			lmb_remove_region(&lmb.reserved, i);
++			i--;
++		}
++	}
++}
++
++int __init lmb_is_reserved(u64 addr)
++{
++	int i;
++
++	for (i = 0; i < lmb.reserved.cnt; i++) {
++		u64 upper = lmb.reserved.region[i].base +
++			lmb.reserved.region[i].size - 1;
++		if ((addr >= lmb.reserved.region[i].base) && (addr <= upper))
++			return 1;
++	}
++	return 0;
++}
+diff --git a/lib/pcounter.c b/lib/pcounter.c
+deleted file mode 100644
+index 9b56807..0000000
+--- a/lib/pcounter.c
++++ /dev/null
+@@ -1,58 +0,0 @@
+-/*
+- * Define default pcounter functions
+- * Note that often used pcounters use dedicated functions to get a speed increase.
+- * (see DEFINE_PCOUNTER/REF_PCOUNTER_MEMBER)
+- */
+-
+-#include <linux/module.h>
+-#include <linux/pcounter.h>
+-#include <linux/smp.h>
+-#include <linux/cpumask.h>
+-
+-static void pcounter_dyn_add(struct pcounter *self, int inc)
+-{
+-	per_cpu_ptr(self->per_cpu_values, smp_processor_id())[0] += inc;
+-}
+-
+-static int pcounter_dyn_getval(const struct pcounter *self, int cpu)
+-{
+-	return per_cpu_ptr(self->per_cpu_values, cpu)[0];
+-}
+-
+-int pcounter_getval(const struct pcounter *self)
+-{
+-	int res = 0, cpu;
+-
+-	for_each_possible_cpu(cpu)
+-		res += self->getval(self, cpu);
+-
+-	return res;
+-}
+-EXPORT_SYMBOL_GPL(pcounter_getval);
+-
+-int pcounter_alloc(struct pcounter *self)
+-{
+-	int rc = 0;
+-	if (self->add == NULL) {
+-		self->per_cpu_values = alloc_percpu(int);
+-		if (self->per_cpu_values != NULL) {
+-			self->add    = pcounter_dyn_add;
+-			self->getval = pcounter_dyn_getval;
+-		} else
+-			rc = 1;
+-	}
+-	return rc;
+-}
+-EXPORT_SYMBOL_GPL(pcounter_alloc);
+-
+-void pcounter_free(struct pcounter *self)
+-{
+-	if (self->per_cpu_values != NULL) {
+-		free_percpu(self->per_cpu_values);
+-		self->per_cpu_values = NULL;
+-		self->getval = NULL;
+-		self->add = NULL;
+-	}
+-}
+-EXPORT_SYMBOL_GPL(pcounter_free);
+-
+diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c
+index 3ea2db9..06d04cf 100644
+--- a/lib/reed_solomon/reed_solomon.c
++++ b/lib/reed_solomon/reed_solomon.c
+@@ -45,7 +45,6 @@
+ #include <linux/rslib.h>
+ #include <linux/slab.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+ 
+ /* This list holds all currently allocated rs control structures */
+ static LIST_HEAD (rslist);
+diff --git a/lib/scatterlist.c b/lib/scatterlist.c
+index acca490..b80c211 100644
+--- a/lib/scatterlist.c
++++ b/lib/scatterlist.c
+@@ -8,6 +8,7 @@
+  */
+ #include <linux/module.h>
+ #include <linux/scatterlist.h>
++#include <linux/highmem.h>
+ 
+ /**
+  * sg_next - return the next scatterlist entry in a list
+@@ -292,3 +293,104 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
+ 	return ret;
+ }
+ EXPORT_SYMBOL(sg_alloc_table);
++
++/**
++ * sg_copy_buffer - Copy data between a linear buffer and an SG list
++ * @sgl:		 The SG list
++ * @nents:		 Number of SG entries
++ * @buf:		 Where to copy from
++ * @buflen:		 The number of bytes to copy
++ * @to_buffer: 		 transfer direction (non zero == from an sg list to a
++ * 			 buffer, 0 == from a buffer to an sg list
++ *
++ * Returns the number of copied bytes.
++ *
++ **/
++static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
++			     void *buf, size_t buflen, int to_buffer)
++{
++	struct scatterlist *sg;
++	size_t buf_off = 0;
++	int i;
++
++	WARN_ON(!irqs_disabled());
++
++	for_each_sg(sgl, sg, nents, i) {
++		struct page *page;
++		int n = 0;
++		unsigned int sg_off = sg->offset;
++		unsigned int sg_copy = sg->length;
++
++		if (sg_copy > buflen)
++			sg_copy = buflen;
++		buflen -= sg_copy;
++
++		while (sg_copy > 0) {
++			unsigned int page_copy;
++			void *p;
++
++			page_copy = PAGE_SIZE - sg_off;
++			if (page_copy > sg_copy)
++				page_copy = sg_copy;
++
++			page = nth_page(sg_page(sg), n);
++			p = kmap_atomic(page, KM_BIO_SRC_IRQ);
++
++			if (to_buffer)
++				memcpy(buf + buf_off, p + sg_off, page_copy);
++			else {
++				memcpy(p + sg_off, buf + buf_off, page_copy);
++				flush_kernel_dcache_page(page);
++			}
++
++			kunmap_atomic(p, KM_BIO_SRC_IRQ);
++
++			buf_off += page_copy;
++			sg_off += page_copy;
++			if (sg_off == PAGE_SIZE) {
++				sg_off = 0;
++				n++;
++			}
++			sg_copy -= page_copy;
++		}
++
++		if (!buflen)
++			break;
++	}
++
++	return buf_off;
++}
++
++/**
++ * sg_copy_from_buffer - Copy from a linear buffer to an SG list
++ * @sgl:		 The SG list
++ * @nents:		 Number of SG entries
++ * @buf:		 Where to copy from
++ * @buflen:		 The number of bytes to copy
++ *
++ * Returns the number of copied bytes.
++ *
++ **/
++size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
++			   void *buf, size_t buflen)
++{
++	return sg_copy_buffer(sgl, nents, buf, buflen, 0);
++}
++EXPORT_SYMBOL(sg_copy_from_buffer);
++
++/**
++ * sg_copy_to_buffer - Copy from an SG list to a linear buffer
++ * @sgl:		 The SG list
++ * @nents:		 Number of SG entries
++ * @buf:		 Where to copy to
++ * @buflen:		 The number of bytes to copy
++ *
++ * Returns the number of copied bytes.
++ *
++ **/
++size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
++			 void *buf, size_t buflen)
++{
++	return sg_copy_buffer(sgl, nents, buf, buflen, 1);
++}
++EXPORT_SYMBOL(sg_copy_to_buffer);
+diff --git a/lib/semaphore-sleepers.c b/lib/semaphore-sleepers.c
+deleted file mode 100644
+index 0198782..0000000
+--- a/lib/semaphore-sleepers.c
++++ /dev/null
+@@ -1,176 +0,0 @@
+-/*
+- * i386 and x86-64 semaphore implementation.
+- *
+- * (C) Copyright 1999 Linus Torvalds
+- *
+- * Portions Copyright 1999 Red Hat, Inc.
+- *
+- *	This program is free software; you can redistribute it and/or
+- *	modify it under the terms of the GNU General Public License
+- *	as published by the Free Software Foundation; either version
+- *	2 of the License, or (at your option) any later version.
+- *
+- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl at kvack.org>
+- */
+-#include <linux/sched.h>
+-#include <linux/err.h>
+-#include <linux/init.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is protected
+- * by the spinlock in the semaphore's waitqueue head.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- *  - only on a boundary condition do we need to care. When we go
+- *    from a negative count to a non-negative, we wake people up.
+- *  - when we go from a non-negative count to a negative do we
+- *    (a) synchronize with the "sleeper" count and (b) make sure
+- *    that we're on the wakeup list before we synchronize so that
+- *    we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+-	wake_up(&sem->wait);
+-}
+-
+-void __sched __down(struct semaphore *sem)
+-{
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	unsigned long flags;
+-
+-	tsk->state = TASK_UNINTERRUPTIBLE;
+-	spin_lock_irqsave(&sem->wait.lock, flags);
+-	add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+-	sem->sleepers++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock in
+-		 * the wait_queue_head.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-		schedule();
+-
+-		spin_lock_irqsave(&sem->wait.lock, flags);
+-		tsk->state = TASK_UNINTERRUPTIBLE;
+-	}
+-	remove_wait_queue_locked(&sem->wait, &wait);
+-	wake_up_locked(&sem->wait);
+-	spin_unlock_irqrestore(&sem->wait.lock, flags);
+-	tsk->state = TASK_RUNNING;
+-}
+-
+-int __sched __down_interruptible(struct semaphore *sem)
+-{
+-	int retval = 0;
+-	struct task_struct *tsk = current;
+-	DECLARE_WAITQUEUE(wait, tsk);
+-	unsigned long flags;
+-
+-	tsk->state = TASK_INTERRUPTIBLE;
+-	spin_lock_irqsave(&sem->wait.lock, flags);
+-	add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+-	sem->sleepers++;
+-	for (;;) {
+-		int sleepers = sem->sleepers;
+-
+-		/*
+-		 * With signals pending, this turns into
+-		 * the trylock failure case - we won't be
+-		 * sleeping, and we* can't get the lock as
+-		 * it has contention. Just correct the count
+-		 * and exit.
+-		 */
+-		if (signal_pending(current)) {
+-			retval = -EINTR;
+-			sem->sleepers = 0;
+-			atomic_add(sleepers, &sem->count);
+-			break;
+-		}
+-
+-		/*
+-		 * Add "everybody else" into it. They aren't
+-		 * playing, because we own the spinlock in
+-		 * wait_queue_head. The "-1" is because we're
+-		 * still hoping to get the semaphore.
+-		 */
+-		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+-			sem->sleepers = 0;
+-			break;
+-		}
+-		sem->sleepers = 1;	/* us - see -1 above */
+-		spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-		schedule();
+-
+-		spin_lock_irqsave(&sem->wait.lock, flags);
+-		tsk->state = TASK_INTERRUPTIBLE;
+-	}
+-	remove_wait_queue_locked(&sem->wait, &wait);
+-	wake_up_locked(&sem->wait);
+-	spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+-	tsk->state = TASK_RUNNING;
+-	return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- *
+- * We could have done the trylock with a
+- * single "cmpxchg" without failure cases,
+- * but then it wouldn't work on a 386.
+- */
+-int __down_trylock(struct semaphore *sem)
+-{
+-	int sleepers;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&sem->wait.lock, flags);
+-	sleepers = sem->sleepers + 1;
+-	sem->sleepers = 0;
+-
+-	/*
+-	 * Add "everybody else" and us into it. They aren't
+-	 * playing, because we own the spinlock in the
+-	 * wait_queue_head.
+-	 */
+-	if (!atomic_add_negative(sleepers, &sem->count)) {
+-		wake_up_locked(&sem->wait);
+-	}
+-
+-	spin_unlock_irqrestore(&sem->wait.lock, flags);
+-	return 1;
+-}
+diff --git a/mm/Makefile b/mm/Makefile
+index a5b0dd9..18c143b 100644
+--- a/mm/Makefile
++++ b/mm/Makefile
+@@ -8,7 +8,7 @@ mmu-$(CONFIG_MMU)	:= fremap.o highmem.o madvise.o memory.o mincore.o \
+ 			   vmalloc.o
+ 
+ obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
+-			   page_alloc.o page-writeback.o pdflush.o \
++			   maccess.o page_alloc.o page-writeback.o pdflush.o \
+ 			   readahead.o swap.o truncate.o vmscan.o \
+ 			   prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
+ 			   page_isolation.o $(mmu-y)
+diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c
+index b0012e2..f4026ba 100644
+--- a/mm/allocpercpu.c
++++ b/mm/allocpercpu.c
+@@ -82,9 +82,10 @@ EXPORT_SYMBOL_GPL(percpu_populate);
+ int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
+ 			   cpumask_t *mask)
+ {
+-	cpumask_t populated = CPU_MASK_NONE;
++	cpumask_t populated;
+ 	int cpu;
+ 
++	cpus_clear(populated);
+ 	for_each_cpu_mask(cpu, *mask)
+ 		if (unlikely(!percpu_populate(__pdata, size, gfp, cpu))) {
+ 			__percpu_depopulate_mask(__pdata, &populated);
+diff --git a/mm/maccess.c b/mm/maccess.c
+new file mode 100644
+index 0000000..ac40796
+--- /dev/null
++++ b/mm/maccess.c
+@@ -0,0 +1,55 @@
++/*
++ * Access kernel memory without faulting.
++ */
++#include <linux/uaccess.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++
++/**
++ * probe_kernel_read(): safely attempt to read from a location
++ * @dst: pointer to the buffer that shall take the data
++ * @src: address to read from
++ * @size: size of the data chunk
++ *
++ * Safely read from address @src to the buffer at @dst.  If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++long probe_kernel_read(void *dst, void *src, size_t size)
++{
++	long ret;
++	mm_segment_t old_fs = get_fs();
++
++	set_fs(KERNEL_DS);
++	pagefault_disable();
++	ret = __copy_from_user_inatomic(dst,
++			(__force const void __user *)src, size);
++	pagefault_enable();
++	set_fs(old_fs);
++
++	return ret ? -EFAULT : 0;
++}
++EXPORT_SYMBOL_GPL(probe_kernel_read);
++
++/**
++ * probe_kernel_write(): safely attempt to write to a location
++ * @dst: address to write to
++ * @src: pointer to the data that shall be written
++ * @size: size of the data chunk
++ *
++ * Safely write to address @dst from the buffer at @src.  If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++long probe_kernel_write(void *dst, void *src, size_t size)
++{
++	long ret;
++	mm_segment_t old_fs = get_fs();
++
++	set_fs(KERNEL_DS);
++	pagefault_disable();
++	ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
++	pagefault_enable();
++	set_fs(old_fs);
++
++	return ret ? -EFAULT : 0;
++}
++EXPORT_SYMBOL_GPL(probe_kernel_write);
+diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
+index 7469c50..0fb3302 100644
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -208,7 +208,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
+ 	/*
+ 	 * This doesn't need a lock to do pfn_to_page().
+ 	 * The section can't be removed here because of the
+-	 * memory_block->state_sem.
++	 * memory_block->state_mutex.
+ 	 */
+ 	zone = page_zone(pfn_to_page(pfn));
+ 	pgdat_resize_lock(zone->zone_pgdat, &flags);
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 402a504..32e796a 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -2029,6 +2029,7 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
+ 	int n, val;
+ 	int min_val = INT_MAX;
+ 	int best_node = -1;
++	node_to_cpumask_ptr(tmp, 0);
+ 
+ 	/* Use the local node if we haven't already */
+ 	if (!node_isset(node, *used_node_mask)) {
+@@ -2037,7 +2038,6 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
+ 	}
+ 
+ 	for_each_node_state(n, N_HIGH_MEMORY) {
+-		cpumask_t tmp;
+ 
+ 		/* Don't want a node to appear more than once */
+ 		if (node_isset(n, *used_node_mask))
+@@ -2050,8 +2050,8 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
+ 		val += (n < node);
+ 
+ 		/* Give preference to headless and unused nodes */
+-		tmp = node_to_cpumask(n);
+-		if (!cpus_empty(tmp))
++		node_to_cpumask_ptr_next(tmp, n);
++		if (!cpus_empty(*tmp))
+ 			val += PENALTY_FOR_NODE_WITH_CPUS;
+ 
+ 		/* Slight preference for less loaded node */
+diff --git a/mm/pdflush.c b/mm/pdflush.c
+index 8f6ee07..1c96cfc 100644
+--- a/mm/pdflush.c
++++ b/mm/pdflush.c
+@@ -17,8 +17,8 @@
+ #include <linux/gfp.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+-#include <linux/fs.h>		// Needed by writeback.h
+-#include <linux/writeback.h>	// Prototypes pdflush_operation()
++#include <linux/fs.h>		/* Needed by writeback.h	  */
++#include <linux/writeback.h>	/* Prototypes pdflush_operation() */
+ #include <linux/kthread.h>
+ #include <linux/cpuset.h>
+ #include <linux/freezer.h>
+@@ -187,8 +187,8 @@ static int pdflush(void *dummy)
+ 	 * This is needed as pdflush's are dynamically created and destroyed.
+ 	 * The boottime pdflush's are easily placed w/o these 2 lines.
+ 	 */
+-	cpus_allowed = cpuset_cpus_allowed(current);
+-	set_cpus_allowed(current, cpus_allowed);
++	cpuset_cpus_allowed(current, &cpus_allowed);
++	set_cpus_allowed_ptr(current, &cpus_allowed);
+ 
+ 	return __pdflush(&my_work);
+ }
+diff --git a/mm/slab.c b/mm/slab.c
+index 04b308c..03927cb 100644
+--- a/mm/slab.c
++++ b/mm/slab.c
+@@ -1160,14 +1160,13 @@ static void __cpuinit cpuup_canceled(long cpu)
+ 	struct kmem_cache *cachep;
+ 	struct kmem_list3 *l3 = NULL;
+ 	int node = cpu_to_node(cpu);
++	node_to_cpumask_ptr(mask, node);
+ 
+ 	list_for_each_entry(cachep, &cache_chain, next) {
+ 		struct array_cache *nc;
+ 		struct array_cache *shared;
+ 		struct array_cache **alien;
+-		cpumask_t mask;
+ 
+-		mask = node_to_cpumask(node);
+ 		/* cpu is dead; no one can alloc from it. */
+ 		nc = cachep->array[cpu];
+ 		cachep->array[cpu] = NULL;
+@@ -1183,7 +1182,7 @@ static void __cpuinit cpuup_canceled(long cpu)
+ 		if (nc)
+ 			free_block(cachep, nc->entry, nc->avail, node);
+ 
+-		if (!cpus_empty(mask)) {
++		if (!cpus_empty(*mask)) {
+ 			spin_unlock_irq(&l3->list_lock);
+ 			goto free_array_cache;
+ 		}
+diff --git a/mm/slub.c b/mm/slub.c
+index acc975f..39592b5 100644
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -521,7 +521,7 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
+ static void object_err(struct kmem_cache *s, struct page *page,
+ 			u8 *object, char *reason)
+ {
+-	slab_bug(s, reason);
++	slab_bug(s, "%s", reason);
+ 	print_trailer(s, page, object);
+ }
+ 
+@@ -533,7 +533,7 @@ static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
+ 	va_start(args, fmt);
+ 	vsnprintf(buf, sizeof(buf), fmt, args);
+ 	va_end(args);
+-	slab_bug(s, fmt);
++	slab_bug(s, "%s", buf);
+ 	print_page_info(page);
+ 	dump_stack();
+ }
+@@ -837,6 +837,35 @@ static void remove_full(struct kmem_cache *s, struct page *page)
+ 	spin_unlock(&n->list_lock);
+ }
+ 
++/* Tracking of the number of slabs for debugging purposes */
++static inline unsigned long slabs_node(struct kmem_cache *s, int node)
++{
++	struct kmem_cache_node *n = get_node(s, node);
++
++	return atomic_long_read(&n->nr_slabs);
++}
++
++static inline void inc_slabs_node(struct kmem_cache *s, int node)
++{
++	struct kmem_cache_node *n = get_node(s, node);
++
++	/*
++	 * May be called early in order to allocate a slab for the
++	 * kmem_cache_node structure. Solve the chicken-egg
++	 * dilemma by deferring the increment of the count during
++	 * bootstrap (see early_kmem_cache_node_alloc).
++	 */
++	if (!NUMA_BUILD || n)
++		atomic_long_inc(&n->nr_slabs);
++}
++static inline void dec_slabs_node(struct kmem_cache *s, int node)
++{
++	struct kmem_cache_node *n = get_node(s, node);
++
++	atomic_long_dec(&n->nr_slabs);
++}
++
++/* Object debug checks for alloc/free paths */
+ static void setup_object_debug(struct kmem_cache *s, struct page *page,
+ 								void *object)
+ {
+@@ -1028,6 +1057,11 @@ static inline unsigned long kmem_cache_flags(unsigned long objsize,
+ 	return flags;
+ }
+ #define slub_debug 0
++
++static inline unsigned long slabs_node(struct kmem_cache *s, int node)
++							{ return 0; }
++static inline void inc_slabs_node(struct kmem_cache *s, int node) {}
++static inline void dec_slabs_node(struct kmem_cache *s, int node) {}
+ #endif
+ /*
+  * Slab allocation and freeing
+@@ -1066,7 +1100,6 @@ static void setup_object(struct kmem_cache *s, struct page *page,
+ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
+ {
+ 	struct page *page;
+-	struct kmem_cache_node *n;
+ 	void *start;
+ 	void *last;
+ 	void *p;
+@@ -1078,9 +1111,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
+ 	if (!page)
+ 		goto out;
+ 
+-	n = get_node(s, page_to_nid(page));
+-	if (n)
+-		atomic_long_inc(&n->nr_slabs);
++	inc_slabs_node(s, page_to_nid(page));
+ 	page->slab = s;
+ 	page->flags |= 1 << PG_slab;
+ 	if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
+@@ -1125,6 +1156,8 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
+ 		NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
+ 		-pages);
+ 
++	__ClearPageSlab(page);
++	reset_page_mapcount(page);
+ 	__free_pages(page, s->order);
+ }
+ 
+@@ -1151,11 +1184,7 @@ static void free_slab(struct kmem_cache *s, struct page *page)
+ 
+ static void discard_slab(struct kmem_cache *s, struct page *page)
+ {
+-	struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+-
+-	atomic_long_dec(&n->nr_slabs);
+-	reset_page_mapcount(page);
+-	__ClearPageSlab(page);
++	dec_slabs_node(s, page_to_nid(page));
+ 	free_slab(s, page);
+ }
+ 
+@@ -1886,15 +1915,18 @@ static void init_kmem_cache_cpu(struct kmem_cache *s,
+ 	c->node = 0;
+ 	c->offset = s->offset / sizeof(void *);
+ 	c->objsize = s->objsize;
++#ifdef CONFIG_SLUB_STATS
++	memset(c->stat, 0, NR_SLUB_STAT_ITEMS * sizeof(unsigned));
++#endif
+ }
+ 
+ static void init_kmem_cache_node(struct kmem_cache_node *n)
+ {
+ 	n->nr_partial = 0;
+-	atomic_long_set(&n->nr_slabs, 0);
+ 	spin_lock_init(&n->list_lock);
+ 	INIT_LIST_HEAD(&n->partial);
+ #ifdef CONFIG_SLUB_DEBUG
++	atomic_long_set(&n->nr_slabs, 0);
+ 	INIT_LIST_HEAD(&n->full);
+ #endif
+ }
+@@ -2063,7 +2095,7 @@ static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags,
+ 	init_tracking(kmalloc_caches, n);
+ #endif
+ 	init_kmem_cache_node(n);
+-	atomic_long_inc(&n->nr_slabs);
++	inc_slabs_node(kmalloc_caches, node);
+ 
+ 	/*
+ 	 * lockdep requires consistent irq usage for each lock
+@@ -2376,7 +2408,7 @@ static inline int kmem_cache_close(struct kmem_cache *s)
+ 		struct kmem_cache_node *n = get_node(s, node);
+ 
+ 		n->nr_partial -= free_list(s, n, &n->partial);
+-		if (atomic_long_read(&n->nr_slabs))
++		if (slabs_node(s, node))
+ 			return 1;
+ 	}
+ 	free_kmem_cache_nodes(s);
+@@ -2409,10 +2441,6 @@ EXPORT_SYMBOL(kmem_cache_destroy);
+ struct kmem_cache kmalloc_caches[PAGE_SHIFT + 1] __cacheline_aligned;
+ EXPORT_SYMBOL(kmalloc_caches);
+ 
+-#ifdef CONFIG_ZONE_DMA
+-static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT + 1];
+-#endif
+-
+ static int __init setup_slub_min_order(char *str)
+ {
+ 	get_option(&str, &slub_min_order);
+@@ -2472,6 +2500,7 @@ panic:
+ }
+ 
+ #ifdef CONFIG_ZONE_DMA
++static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT + 1];
+ 
+ static void sysfs_add_func(struct work_struct *w)
+ {
+@@ -2688,21 +2717,6 @@ void kfree(const void *x)
+ }
+ EXPORT_SYMBOL(kfree);
+ 
+-#if defined(CONFIG_SLUB_DEBUG) || defined(CONFIG_SLABINFO)
+-static unsigned long count_partial(struct kmem_cache_node *n)
+-{
+-	unsigned long flags;
+-	unsigned long x = 0;
+-	struct page *page;
+-
+-	spin_lock_irqsave(&n->list_lock, flags);
+-	list_for_each_entry(page, &n->partial, lru)
+-		x += page->inuse;
+-	spin_unlock_irqrestore(&n->list_lock, flags);
+-	return x;
+-}
+-#endif
+-
+ /*
+  * kmem_cache_shrink removes empty slabs from the partial lists and sorts
+  * the remaining slabs by the number of items in use. The slabs with the
+@@ -2816,7 +2830,7 @@ static void slab_mem_offline_callback(void *arg)
+ 			 * and offline_pages() function shoudn't call this
+ 			 * callback. So, we must fail.
+ 			 */
+-			BUG_ON(atomic_long_read(&n->nr_slabs));
++			BUG_ON(slabs_node(s, offline_node));
+ 
+ 			s->node[offline_node] = NULL;
+ 			kmem_cache_free(kmalloc_caches, n);
+@@ -3181,6 +3195,21 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
+ 	return slab_alloc(s, gfpflags, node, caller);
+ }
+ 
++#if (defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)) || defined(CONFIG_SLABINFO)
++static unsigned long count_partial(struct kmem_cache_node *n)
++{
++	unsigned long flags;
++	unsigned long x = 0;
++	struct page *page;
++
++	spin_lock_irqsave(&n->list_lock, flags);
++	list_for_each_entry(page, &n->partial, lru)
++		x += page->inuse;
++	spin_unlock_irqrestore(&n->list_lock, flags);
++	return x;
++}
++#endif
++
+ #if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
+ static int validate_slab(struct kmem_cache *s, struct page *page,
+ 						unsigned long *map)
+@@ -3979,10 +4008,12 @@ static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si)
+ 
+ 	len = sprintf(buf, "%lu", sum);
+ 
++#ifdef CONFIG_SMP
+ 	for_each_online_cpu(cpu) {
+ 		if (data[cpu] && len < PAGE_SIZE - 20)
+-			len += sprintf(buf + len, " c%d=%u", cpu, data[cpu]);
++			len += sprintf(buf + len, " C%d=%u", cpu, data[cpu]);
+ 	}
++#endif
+ 	kfree(data);
+ 	return len + sprintf(buf + len, "\n");
+ }
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index 4046434..f80a5b7 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -1647,11 +1647,10 @@ static int kswapd(void *p)
+ 	struct reclaim_state reclaim_state = {
+ 		.reclaimed_slab = 0,
+ 	};
+-	cpumask_t cpumask;
++	node_to_cpumask_ptr(cpumask, pgdat->node_id);
+ 
+-	cpumask = node_to_cpumask(pgdat->node_id);
+-	if (!cpus_empty(cpumask))
+-		set_cpus_allowed(tsk, cpumask);
++	if (!cpus_empty(*cpumask))
++		set_cpus_allowed_ptr(tsk, cpumask);
+ 	current->reclaim_state = &reclaim_state;
+ 
+ 	/*
+@@ -1880,17 +1879,16 @@ out:
+ static int __devinit cpu_callback(struct notifier_block *nfb,
+ 				  unsigned long action, void *hcpu)
+ {
+-	pg_data_t *pgdat;
+-	cpumask_t mask;
+ 	int nid;
+ 
+ 	if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
+ 		for_each_node_state(nid, N_HIGH_MEMORY) {
+-			pgdat = NODE_DATA(nid);
+-			mask = node_to_cpumask(pgdat->node_id);
+-			if (any_online_cpu(mask) != NR_CPUS)
++			pg_data_t *pgdat = NODE_DATA(nid);
++			node_to_cpumask_ptr(mask, pgdat->node_id);
++
++			if (any_online_cpu(*mask) < nr_cpu_ids)
+ 				/* One of our CPUs online: restore mask */
+-				set_cpus_allowed(pgdat->kswapd, mask);
++				set_cpus_allowed_ptr(pgdat->kswapd, mask);
+ 		}
+ 	}
+ 	return NOTIFY_OK;
+diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
+index b33410a..2a739ad 100644
+--- a/net/8021q/vlan.c
++++ b/net/8021q/vlan.c
+@@ -32,6 +32,7 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/notifier.h>
+ #include <net/net_namespace.h>
++#include <net/netns/generic.h>
+ 
+ #include <linux/if_vlan.h>
+ #include "vlan.h"
+@@ -41,6 +42,8 @@
+ 
+ /* Global VLAN variables */
+ 
++int vlan_net_id;
++
+ /* Our listing of VLAN group(s) */
+ static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
+ 
+@@ -49,9 +52,6 @@ static char vlan_version[] = DRV_VERSION;
+ static char vlan_copyright[] = "Ben Greear <greearb at candelatech.com>";
+ static char vlan_buggyright[] = "David S. Miller <davem at redhat.com>";
+ 
+-/* Determines interface naming scheme. */
+-unsigned short vlan_name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
+-
+ static struct packet_type vlan_packet_type = {
+ 	.type = __constant_htons(ETH_P_8021Q),
+ 	.func = vlan_skb_recv, /* VLAN receive method */
+@@ -65,14 +65,14 @@ static inline unsigned int vlan_grp_hashfn(unsigned int idx)
+ }
+ 
+ /* Must be invoked with RCU read lock (no preempt) */
+-static struct vlan_group *__vlan_find_group(int real_dev_ifindex)
++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);
++	int hash = vlan_grp_hashfn(real_dev->ifindex);
+ 
+ 	hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) {
+-		if (grp->real_dev_ifindex == real_dev_ifindex)
++		if (grp->real_dev == real_dev)
+ 			return grp;
+ 	}
+ 
+@@ -86,7 +86,7 @@ static struct vlan_group *__vlan_find_group(int real_dev_ifindex)
+ struct net_device *__find_vlan_dev(struct net_device *real_dev,
+ 				   unsigned short VID)
+ {
+-	struct vlan_group *grp = __vlan_find_group(real_dev->ifindex);
++	struct vlan_group *grp = __vlan_find_group(real_dev);
+ 
+ 	if (grp)
+ 		return vlan_group_get_device(grp, VID);
+@@ -103,32 +103,38 @@ static void vlan_group_free(struct vlan_group *grp)
+ 	kfree(grp);
+ }
+ 
+-static struct vlan_group *vlan_group_alloc(int ifindex)
++static struct vlan_group *vlan_group_alloc(struct net_device *real_dev)
+ {
+ 	struct vlan_group *grp;
+-	unsigned int size;
+-	unsigned int i;
+ 
+ 	grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
+ 	if (!grp)
+ 		return NULL;
+ 
+-	size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
+-
+-	for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
+-		grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
+-		if (!grp->vlan_devices_arrays[i])
+-			goto err;
+-	}
+-
+-	grp->real_dev_ifindex = ifindex;
++	grp->real_dev = real_dev;
+ 	hlist_add_head_rcu(&grp->hlist,
+-			   &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
++			&vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
+ 	return grp;
++}
+ 
+-err:
+-	vlan_group_free(grp);
+-	return NULL;
++static int vlan_group_prealloc_vid(struct vlan_group *vg, int vid)
++{
++	struct net_device **array;
++	unsigned int size;
++
++	ASSERT_RTNL();
++
++	array = vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN];
++	if (array != NULL)
++		return 0;
++
++	size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
++	array = kzalloc(size, GFP_KERNEL);
++	if (array == NULL)
++		return -ENOBUFS;
++
++	vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN] = array;
++	return 0;
+ }
+ 
+ static void vlan_rcu_free(struct rcu_head *rcu)
+@@ -145,11 +151,9 @@ void unregister_vlan_dev(struct net_device *dev)
+ 
+ 	ASSERT_RTNL();
+ 
+-	grp = __vlan_find_group(real_dev->ifindex);
++	grp = __vlan_find_group(real_dev);
+ 	BUG_ON(!grp);
+ 
+-	vlan_proc_rem_dev(dev);
+-
+ 	/* Take it out of our own structures, but be sure to interlock with
+ 	 * HW accelerating devices or SW vlan input packet processing.
+ 	 */
+@@ -240,13 +244,17 @@ int register_vlan_dev(struct net_device *dev)
+ 	struct vlan_group *grp, *ngrp = NULL;
+ 	int err;
+ 
+-	grp = __vlan_find_group(real_dev->ifindex);
++	grp = __vlan_find_group(real_dev);
+ 	if (!grp) {
+-		ngrp = grp = vlan_group_alloc(real_dev->ifindex);
++		ngrp = grp = vlan_group_alloc(real_dev);
+ 		if (!grp)
+ 			return -ENOBUFS;
+ 	}
+ 
++	err = vlan_group_prealloc_vid(grp, vlan_id);
++	if (err < 0)
++		goto out_free_group;
++
+ 	err = register_netdevice(dev);
+ 	if (err < 0)
+ 		goto out_free_group;
+@@ -268,9 +276,6 @@ int register_vlan_dev(struct net_device *dev)
+ 	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
+ 		real_dev->vlan_rx_add_vid(real_dev, vlan_id);
+ 
+-	if (vlan_proc_add_dev(dev) < 0)
+-		pr_warning("8021q: failed to add proc entry for %s\n",
+-			   dev->name);
+ 	return 0;
+ 
+ out_free_group:
+@@ -286,6 +291,8 @@ static int register_vlan_device(struct net_device *real_dev,
+ 				unsigned short VLAN_ID)
+ {
+ 	struct net_device *new_dev;
++	struct net *net = dev_net(real_dev);
++	struct vlan_net *vn = net_generic(net, vlan_net_id);
+ 	char name[IFNAMSIZ];
+ 	int err;
+ 
+@@ -297,7 +304,7 @@ static int register_vlan_device(struct net_device *real_dev,
+ 		return err;
+ 
+ 	/* Gotta set up the fields for the device. */
+-	switch (vlan_name_type) {
++	switch (vn->name_type) {
+ 	case VLAN_NAME_TYPE_RAW_PLUS_VID:
+ 		/* name will look like:	 eth1.0005 */
+ 		snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID);
+@@ -328,6 +335,7 @@ static int register_vlan_device(struct net_device *real_dev,
+ 	if (new_dev == NULL)
+ 		return -ENOBUFS;
+ 
++	dev_net_set(new_dev, net);
+ 	/* need 4 bytes for extra VLAN header info,
+ 	 * hope the underlying device can handle it.
+ 	 */
+@@ -383,6 +391,14 @@ static void __vlan_device_event(struct net_device *dev, unsigned long event)
+ 			pr_warning("8021q: failed to change proc name for %s\n",
+ 					dev->name);
+ 		break;
++	case NETDEV_REGISTER:
++		if (vlan_proc_add_dev(dev) < 0)
++			pr_warning("8021q: failed to add proc entry for %s\n",
++					dev->name);
++		break;
++	case NETDEV_UNREGISTER:
++		vlan_proc_rem_dev(dev);
++		break;
+ 	}
+ }
+ 
+@@ -394,15 +410,12 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ 	int i, flgs;
+ 	struct net_device *vlandev;
+ 
+-	if (dev->nd_net != &init_net)
+-		return NOTIFY_DONE;
+-
+ 	if (is_vlan_dev(dev)) {
+ 		__vlan_device_event(dev, event);
+ 		goto out;
+ 	}
+ 
+-	grp = __vlan_find_group(dev->ifindex);
++	grp = __vlan_find_group(dev);
+ 	if (!grp)
+ 		goto out;
+ 
+@@ -522,7 +535,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
+ 	case GET_VLAN_REALDEV_NAME_CMD:
+ 	case GET_VLAN_VID_CMD:
+ 		err = -ENODEV;
+-		dev = __dev_get_by_name(&init_net, args.device1);
++		dev = __dev_get_by_name(net, args.device1);
+ 		if (!dev)
+ 			goto out;
+ 
+@@ -567,7 +580,10 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
+ 			break;
+ 		if ((args.u.name_type >= 0) &&
+ 		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
+-			vlan_name_type = args.u.name_type;
++			struct vlan_net *vn;
++
++			vn = net_generic(net, vlan_net_id);
++			vn->name_type = args.u.name_type;
+ 			err = 0;
+ 		} else {
+ 			err = -EINVAL;
+@@ -615,6 +631,51 @@ out:
+ 	return err;
+ }
+ 
++static int vlan_init_net(struct net *net)
++{
++	int err;
++	struct vlan_net *vn;
++
++	err = -ENOMEM;
++	vn = kzalloc(sizeof(struct vlan_net), GFP_KERNEL);
++	if (vn == NULL)
++		goto err_alloc;
++
++	err = net_assign_generic(net, vlan_net_id, vn);
++	if (err < 0)
++		goto err_assign;
++
++	vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
++
++	err = vlan_proc_init(net);
++	if (err < 0)
++		goto err_proc;
++
++	return 0;
++
++err_proc:
++	/* nothing */
++err_assign:
++	kfree(vn);
++err_alloc:
++	return err;
++}
++
++static void vlan_exit_net(struct net *net)
++{
++	struct vlan_net *vn;
++
++	vn = net_generic(net, vlan_net_id);
++	rtnl_kill_links(net, &vlan_link_ops);
++	vlan_proc_cleanup(net);
++	kfree(vn);
++}
++
++static struct pernet_operations vlan_net_ops = {
++	.init = vlan_init_net,
++	.exit = vlan_exit_net,
++};
++
+ static int __init vlan_proto_init(void)
+ {
+ 	int err;
+@@ -622,9 +683,9 @@ static int __init vlan_proto_init(void)
+ 	pr_info("%s v%s %s\n", vlan_fullname, vlan_version, vlan_copyright);
+ 	pr_info("All bugs added by %s\n", vlan_buggyright);
+ 
+-	err = vlan_proc_init();
++	err = register_pernet_gen_device(&vlan_net_id, &vlan_net_ops);
+ 	if (err < 0)
+-		goto err1;
++		goto err0;
+ 
+ 	err = register_netdevice_notifier(&vlan_notifier_block);
+ 	if (err < 0)
+@@ -641,8 +702,8 @@ static int __init vlan_proto_init(void)
+ err3:
+ 	unregister_netdevice_notifier(&vlan_notifier_block);
+ err2:
+-	vlan_proc_cleanup();
+-err1:
++	unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
++err0:
+ 	return err;
+ }
+ 
+@@ -661,7 +722,7 @@ static void __exit vlan_cleanup_module(void)
+ 	for (i = 0; i < VLAN_GRP_HASH_SIZE; i++)
+ 		BUG_ON(!hlist_empty(&vlan_group_hash[i]));
+ 
+-	vlan_proc_cleanup();
++	unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
+ 
+ 	synchronize_net();
+ }
+diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
+index 51271ae..5229a72 100644
+--- a/net/8021q/vlan.h
++++ b/net/8021q/vlan.h
+@@ -3,8 +3,6 @@
+ 
+ #include <linux/if_vlan.h>
+ 
+-extern unsigned short vlan_name_type;
+-
+ #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)
+@@ -50,4 +48,17 @@ static inline int is_vlan_dev(struct net_device *dev)
+ 	return dev->priv_flags & IFF_802_1Q_VLAN;
+ }
+ 
++extern int vlan_net_id;
++
++struct proc_dir_entry;
++
++struct vlan_net {
++	/* /proc/net/vlan */
++	struct proc_dir_entry *proc_vlan_dir;
++	/* /proc/net/vlan/config */
++	struct proc_dir_entry *proc_vlan_conf;
++	/* Determines interface naming scheme. */
++	unsigned short name_type;
++};
++
+ #endif /* !(__BEN_VLAN_802_1Q_INC__) */
+diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
+index 41a76a0..c961f08 100644
+--- a/net/8021q/vlan_dev.c
++++ b/net/8021q/vlan_dev.c
+@@ -153,9 +153,6 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
+ 	struct net_device_stats *stats;
+ 	unsigned short vlan_TCI;
+ 
+-	if (dev->nd_net != &init_net)
+-		goto err_free;
+-
+ 	skb = skb_share_check(skb, GFP_ATOMIC);
+ 	if (skb == NULL)
+ 		goto err_free;
+@@ -171,7 +168,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
+ 	skb->dev = __find_vlan_dev(dev, vid);
+ 	if (!skb->dev) {
+ 		pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n",
+-			 __FUNCTION__, (unsigned int)vid, dev->name);
++			 __func__, (unsigned int)vid, dev->name);
+ 		goto err_unlock;
+ 	}
+ 
+@@ -187,7 +184,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
+ 						  ntohs(vhdr->h_vlan_TCI));
+ 
+ 	pr_debug("%s: priority: %u for TCI: %hu\n",
+-		 __FUNCTION__, skb->priority, ntohs(vhdr->h_vlan_TCI));
++		 __func__, skb->priority, ntohs(vhdr->h_vlan_TCI));
+ 
+ 	switch (skb->pkt_type) {
+ 	case PACKET_BROADCAST: /* Yeah, stats collect these together.. */
+@@ -268,7 +265,7 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
+ 	struct net_device *vdev = dev;
+ 
+ 	pr_debug("%s: skb: %p type: %hx len: %u vlan_id: %hx, daddr: %p\n",
+-		 __FUNCTION__, skb, type, len, vlan_dev_info(dev)->vlan_id,
++		 __func__, skb, type, len, vlan_dev_info(dev)->vlan_id,
+ 		 daddr);
+ 
+ 	/* build vlan header only if re_order_header flag is NOT set.  This
+@@ -340,7 +337,7 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
+ 			return -ENOMEM;
+ 		}
+ 		vlan_dev_info(vdev)->cnt_inc_headroom_on_tx++;
+-		pr_debug("%s: %s: had to grow skb\n", __FUNCTION__, vdev->name);
++		pr_debug("%s: %s: had to grow skb\n", __func__, vdev->name);
+ 	}
+ 
+ 	if (build_vlan_header) {
+@@ -382,7 +379,7 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		vlan_dev_info(dev)->cnt_encap_on_xmit++;
+ 
+ 		pr_debug("%s: proto to encap: 0x%hx\n",
+-			 __FUNCTION__, ntohs(veth->h_vlan_proto));
++			 __func__, ntohs(veth->h_vlan_proto));
+ 		/* Construct the second two bytes. This field looks something
+ 		 * like:
+ 		 * usr_priority: 3 bits	 (high bits)
+@@ -403,7 +400,7 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	}
+ 
+ 	pr_debug("%s: about to send skb: %p to dev: %s\n",
+-		__FUNCTION__, skb, skb->dev->name);
++		__func__, skb, skb->dev->name);
+ 	pr_debug("  " MAC_FMT " " MAC_FMT " %4hx %4hx %4hx\n",
+ 		 veth->h_dest[0], veth->h_dest[1], veth->h_dest[2],
+ 		 veth->h_dest[3], veth->h_dest[4], veth->h_dest[5],
+diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
+index e32eeb3..c93e69e 100644
+--- a/net/8021q/vlan_netlink.c
++++ b/net/8021q/vlan_netlink.c
+@@ -113,7 +113,7 @@ static int vlan_newlink(struct net_device *dev,
+ 
+ 	if (!tb[IFLA_LINK])
+ 		return -EINVAL;
+-	real_dev = __dev_get_by_index(&init_net, nla_get_u32(tb[IFLA_LINK]));
++	real_dev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK]));
+ 	if (!real_dev)
+ 		return -ENODEV;
+ 
+diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
+index 9671aa5..daad006 100644
+--- a/net/8021q/vlanproc.c
++++ b/net/8021q/vlanproc.c
+@@ -34,6 +34,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/if_vlan.h>
+ #include <net/net_namespace.h>
++#include <net/netns/generic.h>
+ #include "vlanproc.h"
+ #include "vlan.h"
+ 
+@@ -79,7 +80,8 @@ static const struct seq_operations vlan_seq_ops = {
+ 
+ static int vlan_seq_open(struct inode *inode, struct file *file)
+ {
+-	return seq_open(file, &vlan_seq_ops);
++	return seq_open_net(inode, file, &vlan_seq_ops,
++			sizeof(struct seq_net_private));
+ }
+ 
+ static const struct file_operations vlan_fops = {
+@@ -87,7 +89,7 @@ static const struct file_operations vlan_fops = {
+ 	.open    = vlan_seq_open,
+ 	.read    = seq_read,
+ 	.llseek  = seq_lseek,
+-	.release = seq_release,
++	.release = seq_release_net,
+ };
+ 
+ /*
+@@ -111,18 +113,6 @@ static const struct file_operations vlandev_fops = {
+  * Proc filesystem derectory entries.
+  */
+ 
+-/*
+- *	/proc/net/vlan
+- */
+-
+-static struct proc_dir_entry *proc_vlan_dir;
+-
+-/*
+- *	/proc/net/vlan/config
+- */
+-
+-static struct proc_dir_entry *proc_vlan_conf;
+-
+ /* Strings */
+ static const char *vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
+     [VLAN_NAME_TYPE_RAW_PLUS_VID]        = "VLAN_NAME_TYPE_RAW_PLUS_VID",
+@@ -138,13 +128,15 @@ static const char *vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
+  *	Clean up /proc/net/vlan entries
+  */
+ 
+-void vlan_proc_cleanup(void)
++void vlan_proc_cleanup(struct net *net)
+ {
+-	if (proc_vlan_conf)
+-		remove_proc_entry(name_conf, proc_vlan_dir);
++	struct vlan_net *vn = net_generic(net, vlan_net_id);
++
++	if (vn->proc_vlan_conf)
++		remove_proc_entry(name_conf, vn->proc_vlan_dir);
+ 
+-	if (proc_vlan_dir)
+-		proc_net_remove(&init_net, name_root);
++	if (vn->proc_vlan_dir)
++		proc_net_remove(net, name_root);
+ 
+ 	/* Dynamically added entries should be cleaned up as their vlan_device
+ 	 * is removed, so we should not have to take care of it here...
+@@ -155,21 +147,23 @@ void vlan_proc_cleanup(void)
+  *	Create /proc/net/vlan entries
+  */
+ 
+-int __init vlan_proc_init(void)
++int vlan_proc_init(struct net *net)
+ {
+-	proc_vlan_dir = proc_mkdir(name_root, init_net.proc_net);
+-	if (!proc_vlan_dir)
++	struct vlan_net *vn = net_generic(net, vlan_net_id);
++
++	vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net);
++	if (!vn->proc_vlan_dir)
+ 		goto err;
+ 
+-	proc_vlan_conf = proc_create(name_conf, S_IFREG|S_IRUSR|S_IWUSR,
+-				     proc_vlan_dir, &vlan_fops);
+-	if (!proc_vlan_conf)
++	vn->proc_vlan_conf = proc_create(name_conf, S_IFREG|S_IRUSR|S_IWUSR,
++				     vn->proc_vlan_dir, &vlan_fops);
++	if (!vn->proc_vlan_conf)
+ 		goto err;
+ 	return 0;
+ 
+ err:
+-	pr_err("%s: can't create entry in proc filesystem!\n", __FUNCTION__);
+-	vlan_proc_cleanup();
++	pr_err("%s: can't create entry in proc filesystem!\n", __func__);
++	vlan_proc_cleanup(net);
+ 	return -ENOBUFS;
+ }
+ 
+@@ -180,9 +174,10 @@ err:
+ int vlan_proc_add_dev(struct net_device *vlandev)
+ {
+ 	struct vlan_dev_info *dev_info = vlan_dev_info(vlandev);
++	struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id);
+ 
+ 	dev_info->dent = proc_create(vlandev->name, S_IFREG|S_IRUSR|S_IWUSR,
+-				     proc_vlan_dir, &vlandev_fops);
++				     vn->proc_vlan_dir, &vlandev_fops);
+ 	if (!dev_info->dent)
+ 		return -ENOBUFS;
+ 
+@@ -195,10 +190,12 @@ int vlan_proc_add_dev(struct net_device *vlandev)
+  */
+ int vlan_proc_rem_dev(struct net_device *vlandev)
+ {
++	struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id);
++
+ 	/** NOTE:  This will consume the memory pointed to by dent, it seems. */
+ 	if (vlan_dev_info(vlandev)->dent) {
+ 		remove_proc_entry(vlan_dev_info(vlandev)->dent->name,
+-				  proc_vlan_dir);
++				  vn->proc_vlan_dir);
+ 		vlan_dev_info(vlandev)->dent = NULL;
+ 	}
+ 	return 0;
+@@ -215,6 +212,7 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
+ 	__acquires(dev_base_lock)
+ {
+ 	struct net_device *dev;
++	struct net *net = seq_file_net(seq);
+ 	loff_t i = 1;
+ 
+ 	read_lock(&dev_base_lock);
+@@ -222,7 +220,7 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
+ 	if (*pos == 0)
+ 		return SEQ_START_TOKEN;
+ 
+-	for_each_netdev(&init_net, dev) {
++	for_each_netdev(net, dev) {
+ 		if (!is_vlan_dev(dev))
+ 			continue;
+ 
+@@ -236,14 +234,15 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
+ static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ 	struct net_device *dev;
++	struct net *net = seq_file_net(seq);
+ 
+ 	++*pos;
+ 
+ 	dev = (struct net_device *)v;
+ 	if (v == SEQ_START_TOKEN)
+-		dev = net_device_entry(&init_net.dev_base_head);
++		dev = net_device_entry(&net->dev_base_head);
+ 
+-	for_each_netdev_continue(&init_net, dev) {
++	for_each_netdev_continue(net, dev) {
+ 		if (!is_vlan_dev(dev))
+ 			continue;
+ 
+@@ -261,13 +260,16 @@ static void vlan_seq_stop(struct seq_file *seq, void *v)
+ 
+ static int vlan_seq_show(struct seq_file *seq, void *v)
+ {
++	struct net *net = seq_file_net(seq);
++	struct vlan_net *vn = net_generic(net, vlan_net_id);
++
+ 	if (v == SEQ_START_TOKEN) {
+ 		const char *nmtype = NULL;
+ 
+ 		seq_puts(seq, "VLAN Dev name	 | VLAN ID\n");
+ 
+-		if (vlan_name_type < ARRAY_SIZE(vlan_name_type_str))
+-		    nmtype =  vlan_name_type_str[vlan_name_type];
++		if (vn->name_type < ARRAY_SIZE(vlan_name_type_str))
++		    nmtype =  vlan_name_type_str[vn->name_type];
+ 
+ 		seq_printf(seq, "Name-Type: %s\n",
+ 			   nmtype ? nmtype :  "UNKNOWN");
+diff --git a/net/8021q/vlanproc.h b/net/8021q/vlanproc.h
+index da542ca..063f60a 100644
+--- a/net/8021q/vlanproc.h
++++ b/net/8021q/vlanproc.h
+@@ -2,15 +2,17 @@
+ #define __BEN_VLAN_PROC_INC__
+ 
+ #ifdef CONFIG_PROC_FS
+-int vlan_proc_init(void);
++struct net;
++
++int vlan_proc_init(struct net *net);
+ int vlan_proc_rem_dev(struct net_device *vlandev);
+ int vlan_proc_add_dev(struct net_device *vlandev);
+-void vlan_proc_cleanup(void);
++void vlan_proc_cleanup(struct net *net);
+ 
+ #else /* No CONFIG_PROC_FS */
+ 
+-#define vlan_proc_init()	(0)
+-#define vlan_proc_cleanup()	do {} while (0)
++#define vlan_proc_init(net)	(0)
++#define vlan_proc_cleanup(net)	do {} while (0)
+ #define vlan_proc_add_dev(dev)	({(void)(dev), 0; })
+ #define vlan_proc_rem_dev(dev)	({(void)(dev), 0; })
+ #endif
+diff --git a/net/9p/error.c b/net/9p/error.c
+index ab2458b..64104b9 100644
+--- a/net/9p/error.c
++++ b/net/9p/error.c
+@@ -230,7 +230,7 @@ int p9_errstr2errno(char *errstr, int len)
+ 	if (errno == 0) {
+ 		/* TODO: if error isn't found, add it dynamically */
+ 		errstr[len] = 0;
+-		printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
++		printk(KERN_ERR "%s: errstr :%s: not found\n", __func__,
+ 		       errstr);
+ 		errno = 1;
+ 	}
+diff --git a/net/Kconfig b/net/Kconfig
+index 6627c6a..acbf7c6 100644
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -45,7 +45,7 @@ config INET
+ 	---help---
+ 	  These are the protocols used on the Internet and on most local
+ 	  Ethernets. It is highly recommended to say Y here (this will enlarge
+-	  your kernel by about 144 KB), since some programs (e.g. the X window
++	  your kernel by about 400 KB), since some programs (e.g. the X window
+ 	  system) use TCP/IP even if your machine is not connected to any
+ 	  other computer. You will get the so-called loopback device which
+ 	  allows you to ping yourself (great fun, that!).
+diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
+index 18058bb..25aa37c 100644
+--- a/net/appletalk/aarp.c
++++ b/net/appletalk/aarp.c
+@@ -333,7 +333,7 @@ static int aarp_device_event(struct notifier_block *this, unsigned long event,
+ 	struct net_device *dev = ptr;
+ 	int ct;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event == NETDEV_DOWN) {
+@@ -716,7 +716,7 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	struct atalk_addr sa, *ma, da;
+ 	struct atalk_iface *ifa;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto out0;
+ 
+ 	/* We only do Ethernet SNAP AARP. */
+@@ -1033,25 +1033,8 @@ static const struct seq_operations aarp_seq_ops = {
+ 
+ static int aarp_seq_open(struct inode *inode, struct file *file)
+ {
+-	struct seq_file *seq;
+-	int rc = -ENOMEM;
+-	struct aarp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+-
+-	if (!s)
+-		goto out;
+-
+-	rc = seq_open(file, &aarp_seq_ops);
+-	if (rc)
+-		goto out_kfree;
+-
+-	seq	     = file->private_data;
+-	seq->private = s;
+-	memset(s, 0, sizeof(*s));
+-out:
+-	return rc;
+-out_kfree:
+-	kfree(s);
+-	goto out;
++	return seq_open_private(file, &aarp_seq_ops,
++			sizeof(struct aarp_iter_state));
+ }
+ 
+ const struct file_operations atalk_seq_arp_fops = {
+diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
+index 3be55c8..44cd42f 100644
+--- a/net/appletalk/ddp.c
++++ b/net/appletalk/ddp.c
+@@ -648,7 +648,7 @@ static int ddp_device_event(struct notifier_block *this, unsigned long event,
+ {
+ 	struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event == NETDEV_DOWN)
+@@ -1405,7 +1405,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	int origlen;
+ 	__u16 len_hops;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto freeit;
+ 
+ 	/* Don't mangle buffer if shared */
+@@ -1493,7 +1493,7 @@ freeit:
+ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ 		     struct packet_type *pt, struct net_device *orig_dev)
+ {
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto freeit;
+ 
+ 	/* Expand any short form frames */
+diff --git a/net/atm/clip.c b/net/atm/clip.c
+index 2ab1e36..6f8223e 100644
+--- a/net/atm/clip.c
++++ b/net/atm/clip.c
+@@ -612,7 +612,7 @@ static int clip_device_event(struct notifier_block *this, unsigned long event,
+ {
+ 	struct net_device *dev = arg;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event == NETDEV_UNREGISTER) {
+@@ -648,10 +648,6 @@ static int clip_inet_event(struct notifier_block *this, unsigned long event,
+ 	struct in_device *in_dev;
+ 
+ 	in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
+-	if (!in_dev || !in_dev->dev) {
+-		printk(KERN_WARNING "clip_inet_event: no device\n");
+-		return NOTIFY_DONE;
+-	}
+ 	/*
+ 	 * Transitions are of the down-change-up type, so it's sufficient to
+ 	 * handle the change on up.
+diff --git a/net/atm/lec.c b/net/atm/lec.c
+index 3235c57..653aca3 100644
+--- a/net/atm/lec.c
++++ b/net/atm/lec.c
+@@ -1023,7 +1023,7 @@ static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
+ 
+ 	if (!e)
+ 		e = tbl->first;
+-	if (e == (void *)1) {
++	if (e == SEQ_START_TOKEN) {
+ 		e = tbl->first;
+ 		--*l;
+ 	}
+@@ -1125,9 +1125,9 @@ static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
+ 	state->locked = NULL;
+ 	state->arp_table = 0;
+ 	state->misc_table = 0;
+-	state->node = (void *)1;
++	state->node = SEQ_START_TOKEN;
+ 
+-	return *pos ? lec_get_idx(state, *pos) : (void *)1;
++	return *pos ? lec_get_idx(state, *pos) : SEQ_START_TOKEN;
+ }
+ 
+ static void lec_seq_stop(struct seq_file *seq, void *v)
+@@ -1156,7 +1156,7 @@ static int lec_seq_show(struct seq_file *seq, void *v)
+ 	    "                          Status            Flags "
+ 	    "VPI/VCI Recv VPI/VCI\n";
+ 
+-	if (v == (void *)1)
++	if (v == SEQ_START_TOKEN)
+ 		seq_puts(seq, lec_banner);
+ 	else {
+ 		struct lec_state *state = seq->private;
+@@ -1178,32 +1178,7 @@ static const struct seq_operations lec_seq_ops = {
+ 
+ static int lec_seq_open(struct inode *inode, struct file *file)
+ {
+-	struct lec_state *state;
+-	struct seq_file *seq;
+-	int rc = -EAGAIN;
+-
+-	state = kmalloc(sizeof(*state), GFP_KERNEL);
+-	if (!state) {
+-		rc = -ENOMEM;
+-		goto out;
+-	}
+-
+-	rc = seq_open(file, &lec_seq_ops);
+-	if (rc)
+-		goto out_kfree;
+-	seq = file->private_data;
+-	seq->private = state;
+-out:
+-	return rc;
+-
+-out_kfree:
+-	kfree(state);
+-	goto out;
+-}
+-
+-static int lec_seq_release(struct inode *inode, struct file *file)
+-{
+-	return seq_release_private(inode, file);
++	return seq_open_private(file, &lec_seq_ops, sizeof(struct lec_state));
+ }
+ 
+ static const struct file_operations lec_seq_fops = {
+@@ -1211,7 +1186,7 @@ static const struct file_operations lec_seq_fops = {
+ 	.open = lec_seq_open,
+ 	.read = seq_read,
+ 	.llseek = seq_lseek,
+-	.release = lec_seq_release,
++	.release = seq_release_private,
+ };
+ #endif
+ 
+diff --git a/net/atm/mpc.c b/net/atm/mpc.c
+index 9c7f712..9db332e 100644
+--- a/net/atm/mpc.c
++++ b/net/atm/mpc.c
+@@ -964,7 +964,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
+ 
+ 	dev = (struct net_device *)dev_ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (dev->name == NULL || strncmp(dev->name, "lec", 3))
+diff --git a/net/atm/proc.c b/net/atm/proc.c
+index e9693ae..5c9f3d1 100644
+--- a/net/atm/proc.c
++++ b/net/atm/proc.c
+@@ -78,7 +78,7 @@ static int __vcc_walk(struct sock **sock, int family, int *bucket, loff_t l)
+ {
+ 	struct sock *sk = *sock;
+ 
+-	if (sk == (void *)1) {
++	if (sk == SEQ_START_TOKEN) {
+ 		for (*bucket = 0; *bucket < VCC_HTABLE_SIZE; ++*bucket) {
+ 			struct hlist_head *head = &vcc_hash[*bucket];
+ 
+@@ -98,7 +98,7 @@ try_again:
+ 		sk = sk_head(&vcc_hash[*bucket]);
+ 		goto try_again;
+ 	}
+-	sk = (void *)1;
++	sk = SEQ_START_TOKEN;
+ out:
+ 	*sock = sk;
+ 	return (l < 0);
+@@ -114,31 +114,13 @@ static int __vcc_seq_open(struct inode *inode, struct file *file,
+ 	int family, const struct seq_operations *ops)
+ {
+ 	struct vcc_state *state;
+-	struct seq_file *seq;
+-	int rc = -ENOMEM;
+ 
+-	state = kmalloc(sizeof(*state), GFP_KERNEL);
+-	if (!state)
+-		goto out;
+-
+-	rc = seq_open(file, ops);
+-	if (rc)
+-		goto out_kfree;
++	state = __seq_open_private(file, ops, sizeof(*state));
++	if (state == NULL)
++		return -ENOMEM;
+ 
+ 	state->family = family;
+-
+-	seq = file->private_data;
+-	seq->private = state;
+-out:
+-	return rc;
+-out_kfree:
+-	kfree(state);
+-	goto out;
+-}
+-
+-static int vcc_seq_release(struct inode *inode, struct file *file)
+-{
+-	return seq_release_private(inode, file);
++	return 0;
+ }
+ 
+ static void *vcc_seq_start(struct seq_file *seq, loff_t *pos)
+@@ -148,8 +130,8 @@ static void *vcc_seq_start(struct seq_file *seq, loff_t *pos)
+ 	loff_t left = *pos;
+ 
+ 	read_lock(&vcc_sklist_lock);
+-	state->sk = (void *)1;
+-	return left ? vcc_walk(state, left) : (void *)1;
++	state->sk = SEQ_START_TOKEN;
++	return left ? vcc_walk(state, left) : SEQ_START_TOKEN;
+ }
+ 
+ static void vcc_seq_stop(struct seq_file *seq, void *v)
+@@ -253,7 +235,7 @@ static int atm_dev_seq_show(struct seq_file *seq, void *v)
+ 		"Itf Type    ESI/\"MAC\"addr "
+ 		"AAL(TX,err,RX,err,drop) ...               [refcnt]\n";
+ 
+-	if (v == (void *)1)
++	if (v == SEQ_START_TOKEN)
+ 		seq_puts(seq, atm_dev_banner);
+ 	else {
+ 		struct atm_dev *dev = list_entry(v, struct atm_dev, dev_list);
+@@ -287,7 +269,7 @@ static int pvc_seq_show(struct seq_file *seq, void *v)
+ 	static char atm_pvc_banner[] =
+ 		"Itf VPI VCI   AAL RX(PCR,Class) TX(PCR,Class)\n";
+ 
+-	if (v == (void *)1)
++	if (v == SEQ_START_TOKEN)
+ 		seq_puts(seq, atm_pvc_banner);
+ 	else {
+ 		struct vcc_state *state = seq->private;
+@@ -314,12 +296,12 @@ static const struct file_operations pvc_seq_fops = {
+ 	.open		= pvc_seq_open,
+ 	.read		= seq_read,
+ 	.llseek		= seq_lseek,
+-	.release	= vcc_seq_release,
++	.release	= seq_release_private,
+ };
+ 
+ static int vcc_seq_show(struct seq_file *seq, void *v)
+ {
+-	if (v == (void *)1) {
++	if (v == SEQ_START_TOKEN) {
+ 		seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
+ 			"Address ", "Itf VPI VCI   Fam Flags Reply "
+ 			"Send buffer     Recv buffer      [refcnt]\n");
+@@ -348,7 +330,7 @@ static const struct file_operations vcc_seq_fops = {
+ 	.open		= vcc_seq_open,
+ 	.read		= seq_read,
+ 	.llseek		= seq_lseek,
+-	.release	= vcc_seq_release,
++	.release	= seq_release_private,
+ };
+ 
+ static int svc_seq_show(struct seq_file *seq, void *v)
+@@ -356,7 +338,7 @@ static int svc_seq_show(struct seq_file *seq, void *v)
+ 	static char atm_svc_banner[] =
+ 		"Itf VPI VCI           State      Remote\n";
+ 
+-	if (v == (void *)1)
++	if (v == SEQ_START_TOKEN)
+ 		seq_puts(seq, atm_svc_banner);
+ 	else {
+ 		struct vcc_state *state = seq->private;
+@@ -383,7 +365,7 @@ static const struct file_operations svc_seq_fops = {
+ 	.open		= svc_seq_open,
+ 	.read		= seq_read,
+ 	.llseek		= seq_lseek,
+-	.release	= vcc_seq_release,
++	.release	= seq_release_private,
+ };
+ 
+ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
+diff --git a/net/atm/resources.c b/net/atm/resources.c
+index 1bcf6dc..a34ba94 100644
+--- a/net/atm/resources.c
++++ b/net/atm/resources.c
+@@ -415,7 +415,7 @@ static __inline__ void *dev_get_idx(loff_t left)
+ void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+ 	mutex_lock(&atm_dev_mutex);
+-	return *pos ? dev_get_idx(*pos) : (void *) 1;
++	return *pos ? dev_get_idx(*pos) : SEQ_START_TOKEN;
+ }
+ 
+ void atm_dev_seq_stop(struct seq_file *seq, void *v)
+@@ -426,7 +426,8 @@ void atm_dev_seq_stop(struct seq_file *seq, void *v)
+ void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ 	++*pos;
+-	v = (v == (void *)1) ? atm_devs.next : ((struct list_head *)v)->next;
++	v = (v == SEQ_START_TOKEN)
++		? atm_devs.next : ((struct list_head *)v)->next;
+ 	return (v == &atm_devs) ? NULL : v;
+ }
+ 
+diff --git a/net/atm/svc.c b/net/atm/svc.c
+index daf9a48..de1e4f2 100644
+--- a/net/atm/svc.c
++++ b/net/atm/svc.c
+@@ -326,7 +326,7 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
+ 
+ 	lock_sock(sk);
+ 
+-	error = svc_create(sk->sk_net, newsock,0);
++	error = svc_create(sock_net(sk), newsock,0);
+ 	if (error)
+ 		goto out;
+ 
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 48bfcc7..2712544 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -116,7 +116,7 @@ static int ax25_device_event(struct notifier_block *this, unsigned long event,
+ {
+ 	struct net_device *dev = (struct net_device *)ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	/* Reject non AX.25 devices */
+@@ -869,7 +869,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
+ 	struct sock *sk;
+ 	ax25_cb *ax25, *oax25;
+ 
+-	sk = sk_alloc(osk->sk_net, PF_AX25, GFP_ATOMIC,	osk->sk_prot);
++	sk = sk_alloc(sock_net(osk), PF_AX25, GFP_ATOMIC,	osk->sk_prot);
+ 	if (sk == NULL)
+ 		return NULL;
+ 
+diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
+index d1be080..33790a8 100644
+--- a/net/ax25/ax25_in.c
++++ b/net/ax25/ax25_in.c
+@@ -451,7 +451,7 @@ int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	skb->sk = NULL;		/* Initially we don't know who it's for */
+ 	skb->destructor = NULL;	/* Who initializes this, dammit?! */
+ 
+-	if (dev->nd_net != &init_net) {
++	if (dev_net(dev) != &init_net) {
+ 		kfree_skb(skb);
+ 		return 0;
+ 	}
+diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
+index 2957df4..a4849f2 100644
+--- a/net/bluetooth/l2cap.c
++++ b/net/bluetooth/l2cap.c
+@@ -1499,7 +1499,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
+ 		goto response;
+ 	}
+ 
+-	sk = l2cap_sock_alloc(parent->sk_net, NULL, BTPROTO_L2CAP, GFP_ATOMIC);
++	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
+ 	if (!sk)
+ 		goto response;
+ 
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index af4e393..5083adc 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -868,7 +868,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ 		goto done;
+ 	}
+ 
+-	sk = rfcomm_sock_alloc(parent->sk_net, NULL, BTPROTO_RFCOMM, GFP_ATOMIC);
++	sk = rfcomm_sock_alloc(sock_net(parent), NULL, BTPROTO_RFCOMM, GFP_ATOMIC);
+ 	if (!sk)
+ 		goto done;
+ 
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index cd887cd..b0d487e 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -803,7 +803,7 @@ static void sco_conn_ready(struct sco_conn *conn)
+ 
+ 		bh_lock_sock(parent);
+ 
+-		sk = sco_sock_alloc(parent->sk_net, NULL, BTPROTO_SCO, GFP_ATOMIC);
++		sk = sco_sock_alloc(sock_net(parent), NULL, BTPROTO_SCO, GFP_ATOMIC);
+ 		if (!sk) {
+ 			bh_unlock_sock(parent);
+ 			goto done;
+diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
+index af7e8be..bb90cd7 100644
+--- a/net/bridge/br_netfilter.c
++++ b/net/bridge/br_netfilter.c
+@@ -111,7 +111,9 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
+  * require us to fill additional fields. */
+ static struct net_device __fake_net_device = {
+ 	.hard_header_len	= ETH_HLEN,
++#ifdef CONFIG_NET_NS
+ 	.nd_net			= &init_net,
++#endif
+ };
+ 
+ static struct rtable __fake_rtable = {
+@@ -224,8 +226,8 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
+ 	}
+ 	nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
+ 
+-	skb->dst = (struct dst_entry *)&__fake_rtable;
+-	dst_hold(skb->dst);
++	skb->rtable = &__fake_rtable;
++	dst_hold(&__fake_rtable.u.dst);
+ 
+ 	skb->dev = nf_bridge->physindev;
+ 	nf_bridge_push_encap_header(skb);
+@@ -389,8 +391,8 @@ bridged_dnat:
+ 			skb->pkt_type = PACKET_HOST;
+ 		}
+ 	} else {
+-		skb->dst = (struct dst_entry *)&__fake_rtable;
+-		dst_hold(skb->dst);
++		skb->rtable = &__fake_rtable;
++		dst_hold(&__fake_rtable.u.dst);
+ 	}
+ 
+ 	skb->dev = nf_bridge->physindev;
+@@ -609,9 +611,9 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb,
+ 				   const struct net_device *out,
+ 				   int (*okfn)(struct sk_buff *))
+ {
+-	if (skb->dst == (struct dst_entry *)&__fake_rtable) {
+-		dst_release(skb->dst);
+-		skb->dst = NULL;
++	if (skb->rtable == &__fake_rtable) {
++		dst_release(&__fake_rtable.u.dst);
++		skb->rtable = NULL;
+ 	}
+ 
+ 	return NF_ACCEPT;
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index f5d6933..f155e6c 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -108,7 +108,7 @@ errout:
+  */
+ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct net_device *dev;
+ 	int idx;
+ 
+@@ -140,7 +140,7 @@ skip:
+  */
+ static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct ifinfomsg *ifm;
+ 	struct nlattr *protinfo;
+ 	struct net_device *dev;
+diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
+index 07ac3ae..00644a5 100644
+--- a/net/bridge/br_notify.c
++++ b/net/bridge/br_notify.c
+@@ -37,7 +37,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
+ 	struct net_bridge_port *p = dev->br_port;
+ 	struct net_bridge *br;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	/* not a port of a bridge */
+diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
+index 0edbd2a..8deab64 100644
+--- a/net/bridge/br_stp_bpdu.c
++++ b/net/bridge/br_stp_bpdu.c
+@@ -142,7 +142,7 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	struct net_bridge *br;
+ 	const unsigned char *buf;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto err;
+ 
+ 	if (!p)
+diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
+index 9cf0538..27d6a51 100644
+--- a/net/bridge/br_sysfs_br.c
++++ b/net/bridge/br_sysfs_br.c
+@@ -415,21 +415,21 @@ int br_sysfs_addbr(struct net_device *dev)
+ 	err = sysfs_create_group(brobj, &bridge_group);
+ 	if (err) {
+ 		pr_info("%s: can't create group %s/%s\n",
+-			__FUNCTION__, dev->name, bridge_group.name);
++			__func__, dev->name, bridge_group.name);
+ 		goto out1;
+ 	}
+ 
+ 	err = sysfs_create_bin_file(brobj, &bridge_forward);
+ 	if (err) {
+ 		pr_info("%s: can't create attribute file %s/%s\n",
+-			__FUNCTION__, dev->name, bridge_forward.attr.name);
++			__func__, dev->name, bridge_forward.attr.name);
+ 		goto out2;
+ 	}
+ 
+ 	br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, brobj);
+ 	if (!br->ifobj) {
+ 		pr_info("%s: can't add kobject (directory) %s/%s\n",
+-			__FUNCTION__, dev->name, SYSFS_BRIDGE_PORT_SUBDIR);
++			__func__, dev->name, SYSFS_BRIDGE_PORT_SUBDIR);
+ 		goto out3;
+ 	}
+ 	return 0;
+diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig
+index 4a3e2bf..7beeefa 100644
+--- a/net/bridge/netfilter/Kconfig
++++ b/net/bridge/netfilter/Kconfig
+@@ -212,4 +212,18 @@ config BRIDGE_EBT_ULOG
+ 
+ 	  To compile it as a module, choose M here.  If unsure, say N.
+ 
++config BRIDGE_EBT_NFLOG
++	tristate "ebt: nflog support"
++	depends on BRIDGE_NF_EBTABLES
++	help
++	  This option enables the nflog watcher, which allows to LOG
++	  messages through the netfilter logging API, which can use
++	  either the old LOG target, the old ULOG target or nfnetlink_log
++	  as backend.
++
++	  This option adds the ulog watcher, that you can use in any rule
++	  in any ebtables table.
++
++	  To compile it as a module, choose M here.  If unsure, say N.
++
+ endmenu
+diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile
+index 905087e..83715d7 100644
+--- a/net/bridge/netfilter/Makefile
++++ b/net/bridge/netfilter/Makefile
+@@ -30,3 +30,4 @@ obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o
+ # watchers
+ obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o
+ obj-$(CONFIG_BRIDGE_EBT_ULOG) += ebt_ulog.o
++obj-$(CONFIG_BRIDGE_EBT_NFLOG) += ebt_nflog.o
+diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c
+new file mode 100644
+index 0000000..8e799aa
+--- /dev/null
++++ b/net/bridge/netfilter/ebt_nflog.c
+@@ -0,0 +1,74 @@
++/*
++ * ebt_nflog
++ *
++ *	Author:
++ *	Peter Warasin <peter at endian.com>
++ *
++ *  February, 2008
++ *
++ * Based on:
++ *  xt_NFLOG.c, (C) 2006 by Patrick McHardy <kaber at trash.net>
++ *  ebt_ulog.c, (C) 2004 by Bart De Schuymer <bdschuym at pandora.be>
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/netfilter_bridge/ebtables.h>
++#include <linux/netfilter_bridge/ebt_nflog.h>
++#include <net/netfilter/nf_log.h>
++
++static void ebt_nflog(const struct sk_buff *skb,
++		      unsigned int hooknr,
++		      const struct net_device *in,
++		      const struct net_device *out,
++		      const void *data, unsigned int datalen)
++{
++	struct ebt_nflog_info *info = (struct ebt_nflog_info *)data;
++	struct nf_loginfo li;
++
++	li.type = NF_LOG_TYPE_ULOG;
++	li.u.ulog.copy_len = info->len;
++	li.u.ulog.group = info->group;
++	li.u.ulog.qthreshold = info->threshold;
++
++	nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, "%s", info->prefix);
++}
++
++static int ebt_nflog_check(const char *tablename,
++			   unsigned int hookmask,
++			   const struct ebt_entry *e,
++			   void *data, unsigned int datalen)
++{
++	struct ebt_nflog_info *info = (struct ebt_nflog_info *)data;
++
++	if (datalen != EBT_ALIGN(sizeof(struct ebt_nflog_info)))
++		return -EINVAL;
++	if (info->flags & ~EBT_NFLOG_MASK)
++		return -EINVAL;
++	info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0';
++	return 0;
++}
++
++static struct ebt_watcher nflog __read_mostly = {
++	.name = EBT_NFLOG_WATCHER,
++	.watcher = ebt_nflog,
++	.check = ebt_nflog_check,
++	.me = THIS_MODULE,
++};
++
++static int __init ebt_nflog_init(void)
++{
++	return ebt_register_watcher(&nflog);
++}
++
++static void __exit ebt_nflog_fini(void)
++{
++	ebt_unregister_watcher(&nflog);
++}
++
++module_init(ebt_nflog_init);
++module_exit(ebt_nflog_fini);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Peter Warasin <peter at endian.com>");
++MODULE_DESCRIPTION("ebtables NFLOG netfilter logging module");
+diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
+index be6f186..246626b 100644
+--- a/net/bridge/netfilter/ebtable_broute.c
++++ b/net/bridge/netfilter/ebtable_broute.c
+@@ -46,7 +46,7 @@ static struct ebt_table broute_table =
+ 	.name		= "broute",
+ 	.table		= &initial_table,
+ 	.valid_hooks	= 1 << NF_BR_BROUTING,
+-	.lock		= RW_LOCK_UNLOCKED,
++	.lock		= __RW_LOCK_UNLOCKED(broute_table.lock),
+ 	.check		= check,
+ 	.me		= THIS_MODULE,
+ };
+diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
+index fb81090..690bc3a 100644
+--- a/net/bridge/netfilter/ebtable_filter.c
++++ b/net/bridge/netfilter/ebtable_filter.c
+@@ -55,7 +55,7 @@ static struct ebt_table frame_filter =
+ 	.name		= "filter",
+ 	.table		= &initial_table,
+ 	.valid_hooks	= FILTER_VALID_HOOKS,
+-	.lock		= RW_LOCK_UNLOCKED,
++	.lock		= __RW_LOCK_UNLOCKED(frame_filter.lock),
+ 	.check		= check,
+ 	.me		= THIS_MODULE,
+ };
+diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
+index bc71273..5b495fe 100644
+--- a/net/bridge/netfilter/ebtable_nat.c
++++ b/net/bridge/netfilter/ebtable_nat.c
+@@ -55,7 +55,7 @@ static struct ebt_table frame_nat =
+ 	.name		= "nat",
+ 	.table		= &initial_table,
+ 	.valid_hooks	= NAT_VALID_HOOKS,
+-	.lock		= RW_LOCK_UNLOCKED,
++	.lock		= __RW_LOCK_UNLOCKED(frame_nat.lock),
+ 	.check		= check,
+ 	.me		= THIS_MODULE,
+ };
+diff --git a/net/can/af_can.c b/net/can/af_can.c
+index 36b9f22..2759b76 100644
+--- a/net/can/af_can.c
++++ b/net/can/af_can.c
+@@ -599,7 +599,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	struct dev_rcv_lists *d;
+ 	int matches;
+ 
+-	if (dev->type != ARPHRD_CAN || dev->nd_net != &init_net) {
++	if (dev->type != ARPHRD_CAN || dev_net(dev) != &init_net) {
+ 		kfree_skb(skb);
+ 		return 0;
+ 	}
+@@ -710,7 +710,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
+ 	struct net_device *dev = (struct net_device *)data;
+ 	struct dev_rcv_lists *d;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (dev->type != ARPHRD_CAN)
+diff --git a/net/can/bcm.c b/net/can/bcm.c
+index bd4282d..74fd2d3 100644
+--- a/net/can/bcm.c
++++ b/net/can/bcm.c
+@@ -43,6 +43,7 @@
+ 
+ #include <linux/module.h>
+ #include <linux/init.h>
++#include <linux/hrtimer.h>
+ #include <linux/list.h>
+ #include <linux/proc_fs.h>
+ #include <linux/uio.h>
+@@ -66,7 +67,7 @@
+ #define REGMASK(id) ((id & CAN_RTR_FLAG) | ((id & CAN_EFF_FLAG) ? \
+ 			(CAN_EFF_MASK | CAN_EFF_FLAG) : CAN_SFF_MASK))
+ 
+-#define CAN_BCM_VERSION CAN_VERSION
++#define CAN_BCM_VERSION "20080415"
+ static __initdata const char banner[] = KERN_INFO
+ 	"can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n";
+ 
+@@ -85,11 +86,10 @@ struct bcm_op {
+ 	int ifindex;
+ 	canid_t can_id;
+ 	int flags;
+-	unsigned long j_ival1, j_ival2, j_lastmsg;
+ 	unsigned long frames_abs, frames_filtered;
+-	struct timer_list timer, thrtimer;
+ 	struct timeval ival1, ival2;
+-	ktime_t rx_stamp;
++	struct hrtimer timer, thrtimer;
++	ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
+ 	int rx_ifindex;
+ 	int count;
+ 	int nframes;
+@@ -126,39 +126,6 @@ static inline struct bcm_sock *bcm_sk(const struct sock *sk)
+ #define MHSIZ sizeof(struct bcm_msg_head)
+ 
+ /*
+- * rounded_tv2jif - calculate jiffies from timeval including optional up
+- * @tv: pointer to timeval
+- *
+- * Description:
+- * Unlike timeval_to_jiffies() provided in include/linux/jiffies.h, this
+- * function is intentionally more relaxed on precise timer ticks to get
+- * exact one jiffy for requested 1000us on a 1000HZ machine.
+- * This code is to be removed when upgrading to kernel hrtimer.
+- *
+- * Return:
+- *  calculated jiffies (max: ULONG_MAX)
+- */
+-static unsigned long rounded_tv2jif(const struct timeval *tv)
+-{
+-	unsigned long sec  = tv->tv_sec;
+-	unsigned long usec = tv->tv_usec;
+-	unsigned long jif;
+-
+-	if (sec > ULONG_MAX / HZ)
+-		return ULONG_MAX;
+-
+-	/* round up to get at least the requested time */
+-	usec += 1000000 / HZ - 1;
+-
+-	jif  = usec / (1000000 / HZ);
+-
+-	if (sec * HZ > ULONG_MAX - jif)
+-		return ULONG_MAX;
+-
+-	return jif + sec * HZ;
+-}
+-
+-/*
+  * procfs functions
+  */
+ static char *bcm_proc_getifname(int ifindex)
+@@ -208,13 +175,17 @@ static int bcm_read_proc(char *page, char **start, off_t off,
+ 		len += snprintf(page + len, PAGE_SIZE - len, "[%d]%c ",
+ 				op->nframes,
+ 				(op->flags & RX_CHECK_DLC)?'d':' ');
+-		if (op->j_ival1)
++		if (op->kt_ival1.tv64)
+ 			len += snprintf(page + len, PAGE_SIZE - len,
+-					"timeo=%ld ", op->j_ival1);
++					"timeo=%lld ",
++					(long long)
++					ktime_to_us(op->kt_ival1));
+ 
+-		if (op->j_ival2)
++		if (op->kt_ival2.tv64)
+ 			len += snprintf(page + len, PAGE_SIZE - len,
+-					"thr=%ld ", op->j_ival2);
++					"thr=%lld ",
++					(long long)
++					ktime_to_us(op->kt_ival2));
+ 
+ 		len += snprintf(page + len, PAGE_SIZE - len,
+ 				"# recv %ld (%ld) => reduction: ",
+@@ -238,13 +209,14 @@ static int bcm_read_proc(char *page, char **start, off_t off,
+ 				"tx_op: %03X %s [%d] ",
+ 				op->can_id, bcm_proc_getifname(op->ifindex),
+ 				op->nframes);
+-		if (op->j_ival1)
+-			len += snprintf(page + len, PAGE_SIZE - len, "t1=%ld ",
+-					op->j_ival1);
+ 
+-		if (op->j_ival2)
+-			len += snprintf(page + len, PAGE_SIZE - len, "t2=%ld ",
+-					op->j_ival2);
++		if (op->kt_ival1.tv64)
++			len += snprintf(page + len, PAGE_SIZE - len, "t1=%lld ",
++					(long long) ktime_to_us(op->kt_ival1));
++
++		if (op->kt_ival2.tv64)
++			len += snprintf(page + len, PAGE_SIZE - len, "t2=%lld ",
++					(long long) ktime_to_us(op->kt_ival2));
+ 
+ 		len += snprintf(page + len, PAGE_SIZE - len, "# sent %ld\n",
+ 				op->frames_abs);
+@@ -371,11 +343,12 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
+ /*
+  * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions
+  */
+-static void bcm_tx_timeout_handler(unsigned long data)
++static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
+ {
+-	struct bcm_op *op = (struct bcm_op *)data;
++	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
++	enum hrtimer_restart ret = HRTIMER_NORESTART;
+ 
+-	if (op->j_ival1 && (op->count > 0)) {
++	if (op->kt_ival1.tv64 && (op->count > 0)) {
+ 
+ 		op->count--;
+ 		if (!op->count && (op->flags & TX_COUNTEVT)) {
+@@ -394,22 +367,24 @@ static void bcm_tx_timeout_handler(unsigned long data)
+ 		}
+ 	}
+ 
+-	if (op->j_ival1 && (op->count > 0)) {
++	if (op->kt_ival1.tv64 && (op->count > 0)) {
+ 
+ 		/* send (next) frame */
+ 		bcm_can_tx(op);
+-		mod_timer(&op->timer, jiffies + op->j_ival1);
++		hrtimer_forward(hrtimer, ktime_get(), op->kt_ival1);
++		ret = HRTIMER_RESTART;
+ 
+ 	} else {
+-		if (op->j_ival2) {
++		if (op->kt_ival2.tv64) {
+ 
+ 			/* send (next) frame */
+ 			bcm_can_tx(op);
+-			mod_timer(&op->timer, jiffies + op->j_ival2);
++			hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
++			ret = HRTIMER_RESTART;
+ 		}
+ 	}
+ 
+-	return;
++	return ret;
+ }
+ 
+ /*
+@@ -419,8 +394,6 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data)
+ {
+ 	struct bcm_msg_head head;
+ 
+-	op->j_lastmsg = jiffies;
+-
+ 	/* update statistics */
+ 	op->frames_filtered++;
+ 
+@@ -439,6 +412,12 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data)
+ 	bcm_send_to_user(op, &head, data, 1);
+ }
+ 
++/* TODO: move to linux/hrtimer.h */
++static inline int hrtimer_callback_running(struct hrtimer *timer)
++{
++        return timer->state & HRTIMER_STATE_CALLBACK;
++}
++
+ /*
+  * bcm_rx_update_and_send - process a detected relevant receive content change
+  *                          1. update the last received data
+@@ -448,30 +427,44 @@ static void bcm_rx_update_and_send(struct bcm_op *op,
+ 				   struct can_frame *lastdata,
+ 				   struct can_frame *rxdata)
+ {
+-	unsigned long nexttx = op->j_lastmsg + op->j_ival2;
+-
+ 	memcpy(lastdata, rxdata, CFSIZ);
+ 
+ 	/* mark as used */
+ 	lastdata->can_dlc |= RX_RECV;
+ 
+-	/* throttle bcm_rx_changed ? */
+-	if ((op->thrtimer.expires) ||
+-	    ((op->j_ival2) && (nexttx > jiffies))) {
+-		/* we are already waiting OR we have to start waiting */
++	/* throtteling mode inactive OR data update already on the run ? */
++	if (!op->kt_ival2.tv64 || hrtimer_callback_running(&op->thrtimer)) {
++		/* send RX_CHANGED to the user immediately */
++		bcm_rx_changed(op, rxdata);
++		return;
++	}
+ 
++	if (hrtimer_active(&op->thrtimer)) {
+ 		/* mark as 'throttled' */
+ 		lastdata->can_dlc |= RX_THR;
++		return;
++	}
+ 
+-		if (!(op->thrtimer.expires)) {
+-			/* start the timer only the first time */
+-			mod_timer(&op->thrtimer, nexttx);
+-		}
+-
+-	} else {
+-		/* send RX_CHANGED to the user immediately */
++	if (!op->kt_lastmsg.tv64) {
++		/* send first RX_CHANGED to the user immediately */
+ 		bcm_rx_changed(op, rxdata);
++		op->kt_lastmsg = ktime_get();
++		return;
++	}
++
++	if (ktime_us_delta(ktime_get(), op->kt_lastmsg) <
++	    ktime_to_us(op->kt_ival2)) {
++		/* mark as 'throttled' and start timer */
++		lastdata->can_dlc |= RX_THR;
++		hrtimer_start(&op->thrtimer,
++			      ktime_add(op->kt_lastmsg, op->kt_ival2),
++			      HRTIMER_MODE_ABS);
++		return;
+ 	}
++
++	/* the gap was that big, that throttling was not needed here */
++	bcm_rx_changed(op, rxdata);
++	op->kt_lastmsg = ktime_get();
+ }
+ 
+ /*
+@@ -519,16 +512,16 @@ static void bcm_rx_starttimer(struct bcm_op *op)
+ 	if (op->flags & RX_NO_AUTOTIMER)
+ 		return;
+ 
+-	if (op->j_ival1)
+-		mod_timer(&op->timer, jiffies + op->j_ival1);
++	if (op->kt_ival1.tv64)
++		hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
+ }
+ 
+ /*
+  * bcm_rx_timeout_handler - when the (cyclic) CAN frame receiption timed out
+  */
+-static void bcm_rx_timeout_handler(unsigned long data)
++static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
+ {
+-	struct bcm_op *op = (struct bcm_op *)data;
++	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
+ 	struct bcm_msg_head msg_head;
+ 
+ 	msg_head.opcode  = RX_TIMEOUT;
+@@ -548,27 +541,27 @@ static void bcm_rx_timeout_handler(unsigned long data)
+ 		/* clear received can_frames to indicate 'nothing received' */
+ 		memset(op->last_frames, 0, op->nframes * CFSIZ);
+ 	}
++
++	return HRTIMER_NORESTART;
+ }
+ 
+ /*
+- * bcm_rx_thr_handler - the time for blocked content updates is over now:
+- *                      Check for throttled data and send it to the userspace
++ * bcm_rx_thr_flush - Check for throttled data and send it to the userspace
+  */
+-static void bcm_rx_thr_handler(unsigned long data)
++static int bcm_rx_thr_flush(struct bcm_op *op)
+ {
+-	struct bcm_op *op = (struct bcm_op *)data;
+-	int i = 0;
+-
+-	/* mark disabled / consumed timer */
+-	op->thrtimer.expires = 0;
++	int updated = 0;
+ 
+ 	if (op->nframes > 1) {
++		int i;
++
+ 		/* for MUX filter we start at index 1 */
+ 		for (i = 1; i < op->nframes; i++) {
+ 			if ((op->last_frames) &&
+ 			    (op->last_frames[i].can_dlc & RX_THR)) {
+ 				op->last_frames[i].can_dlc &= ~RX_THR;
+ 				bcm_rx_changed(op, &op->last_frames[i]);
++				updated++;
+ 			}
+ 		}
+ 
+@@ -577,8 +570,29 @@ static void bcm_rx_thr_handler(unsigned long data)
+ 		if (op->last_frames && (op->last_frames[0].can_dlc & RX_THR)) {
+ 			op->last_frames[0].can_dlc &= ~RX_THR;
+ 			bcm_rx_changed(op, &op->last_frames[0]);
++			updated++;
+ 		}
+ 	}
++
++	return updated;
++}
++
++/*
++ * bcm_rx_thr_handler - the time for blocked content updates is over now:
++ *                      Check for throttled data and send it to the userspace
++ */
++static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
++{
++	struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
++
++	if (bcm_rx_thr_flush(op)) {
++		hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
++		return HRTIMER_RESTART;
++	} else {
++		/* rearm throttle handling */
++		op->kt_lastmsg = ktime_set(0, 0);
++		return HRTIMER_NORESTART;
++	}
+ }
+ 
+ /*
+@@ -591,7 +605,7 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
+ 	int i;
+ 
+ 	/* disable timeout */
+-	del_timer(&op->timer);
++	hrtimer_cancel(&op->timer);
+ 
+ 	if (skb->len == sizeof(rxframe)) {
+ 		memcpy(&rxframe, skb->data, sizeof(rxframe));
+@@ -669,8 +683,8 @@ static struct bcm_op *bcm_find_op(struct list_head *ops, canid_t can_id,
+ 
+ static void bcm_remove_op(struct bcm_op *op)
+ {
+-	del_timer(&op->timer);
+-	del_timer(&op->thrtimer);
++	hrtimer_cancel(&op->timer);
++	hrtimer_cancel(&op->thrtimer);
+ 
+ 	if ((op->frames) && (op->frames != &op->sframe))
+ 		kfree(op->frames);
+@@ -871,11 +885,11 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ 		op->ifindex = ifindex;
+ 
+ 		/* initialize uninitialized (kzalloc) structure */
+-		setup_timer(&op->timer, bcm_tx_timeout_handler,
+-			    (unsigned long)op);
++		hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++		op->timer.function = bcm_tx_timeout_handler;
+ 
+ 		/* currently unused in tx_ops */
+-		init_timer(&op->thrtimer);
++		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ 
+ 		/* add this bcm_op to the list of the tx_ops */
+ 		list_add(&op->list, &bo->tx_ops);
+@@ -902,25 +916,27 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ 		op->count = msg_head->count;
+ 		op->ival1 = msg_head->ival1;
+ 		op->ival2 = msg_head->ival2;
+-		op->j_ival1 = rounded_tv2jif(&msg_head->ival1);
+-		op->j_ival2 = rounded_tv2jif(&msg_head->ival2);
++		op->kt_ival1 = timeval_to_ktime(msg_head->ival1);
++		op->kt_ival2 = timeval_to_ktime(msg_head->ival2);
+ 
+ 		/* disable an active timer due to zero values? */
+-		if (!op->j_ival1 && !op->j_ival2)
+-			del_timer(&op->timer);
++		if (!op->kt_ival1.tv64 && !op->kt_ival2.tv64)
++			hrtimer_cancel(&op->timer);
+ 	}
+ 
+ 	if ((op->flags & STARTTIMER) &&
+-	    ((op->j_ival1 && op->count) || op->j_ival2)) {
++	    ((op->kt_ival1.tv64 && op->count) || op->kt_ival2.tv64)) {
+ 
+ 		/* spec: send can_frame when starting timer */
+ 		op->flags |= TX_ANNOUNCE;
+ 
+-		if (op->j_ival1 && (op->count > 0)) {
++		if (op->kt_ival1.tv64 && (op->count > 0)) {
+ 			/* op->count-- is done in bcm_tx_timeout_handler */
+-			mod_timer(&op->timer, jiffies + op->j_ival1);
++			hrtimer_start(&op->timer, op->kt_ival1,
++				      HRTIMER_MODE_REL);
+ 		} else
+-			mod_timer(&op->timer, jiffies + op->j_ival2);
++			hrtimer_start(&op->timer, op->kt_ival2,
++				      HRTIMER_MODE_REL);
+ 	}
+ 
+ 	if (op->flags & TX_ANNOUNCE)
+@@ -1032,15 +1048,11 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ 		op->ifindex = ifindex;
+ 
+ 		/* initialize uninitialized (kzalloc) structure */
+-		setup_timer(&op->timer, bcm_rx_timeout_handler,
+-			    (unsigned long)op);
++		hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++		op->timer.function = bcm_rx_timeout_handler;
+ 
+-		/* init throttle timer for RX_CHANGED */
+-		setup_timer(&op->thrtimer, bcm_rx_thr_handler,
+-			    (unsigned long)op);
+-
+-		/* mark disabled timer */
+-		op->thrtimer.expires = 0;
++		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++		op->thrtimer.function = bcm_rx_thr_handler;
+ 
+ 		/* add this bcm_op to the list of the rx_ops */
+ 		list_add(&op->list, &bo->rx_ops);
+@@ -1056,8 +1068,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ 	if (op->flags & RX_RTR_FRAME) {
+ 
+ 		/* no timers in RTR-mode */
+-		del_timer(&op->thrtimer);
+-		del_timer(&op->timer);
++		hrtimer_cancel(&op->thrtimer);
++		hrtimer_cancel(&op->timer);
+ 
+ 		/*
+ 		 * funny feature in RX(!)_SETUP only for RTR-mode:
+@@ -1074,28 +1086,25 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ 			/* set timer value */
+ 			op->ival1 = msg_head->ival1;
+ 			op->ival2 = msg_head->ival2;
+-			op->j_ival1 = rounded_tv2jif(&msg_head->ival1);
+-			op->j_ival2 = rounded_tv2jif(&msg_head->ival2);
++			op->kt_ival1 = timeval_to_ktime(msg_head->ival1);
++			op->kt_ival2 = timeval_to_ktime(msg_head->ival2);
+ 
+ 			/* disable an active timer due to zero value? */
+-			if (!op->j_ival1)
+-				del_timer(&op->timer);
+-
+-			/* free currently blocked msgs ? */
+-			if (op->thrtimer.expires) {
+-				/* send blocked msgs hereafter */
+-				mod_timer(&op->thrtimer, jiffies + 2);
+-			}
++			if (!op->kt_ival1.tv64)
++				hrtimer_cancel(&op->timer);
+ 
+ 			/*
+-			 * if (op->j_ival2) is zero, no (new) throttling
+-			 * will happen. For details see functions
+-			 * bcm_rx_update_and_send() and bcm_rx_thr_handler()
++			 * In any case cancel the throttle timer, flush
++			 * potentially blocked msgs and reset throttle handling
+ 			 */
++			op->kt_lastmsg = ktime_set(0, 0);
++			hrtimer_cancel(&op->thrtimer);
++			bcm_rx_thr_flush(op);
+ 		}
+ 
+-		if ((op->flags & STARTTIMER) && op->j_ival1)
+-			mod_timer(&op->timer, jiffies + op->j_ival1);
++		if ((op->flags & STARTTIMER) && op->kt_ival1.tv64)
++			hrtimer_start(&op->timer, op->kt_ival1,
++				      HRTIMER_MODE_REL);
+ 	}
+ 
+ 	/* now we can register for can_ids, if we added a new bcm_op */
+@@ -1285,7 +1294,7 @@ static int bcm_notifier(struct notifier_block *nb, unsigned long msg,
+ 	struct bcm_op *op;
+ 	int notify_enodev = 0;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (dev->type != ARPHRD_CAN)
+diff --git a/net/can/raw.c b/net/can/raw.c
+index 94cd7f2..201cbfc 100644
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -210,7 +210,7 @@ static int raw_notifier(struct notifier_block *nb,
+ 	struct raw_sock *ro = container_of(nb, struct raw_sock, notifier);
+ 	struct sock *sk = &ro->sk;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (dev->type != ARPHRD_CAN)
+@@ -573,7 +573,8 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
+ 			int fsize = ro->count * sizeof(struct can_filter);
+ 			if (len > fsize)
+ 				len = fsize;
+-			err = copy_to_user(optval, ro->filter, len);
++			if (copy_to_user(optval, ro->filter, len))
++				err = -EFAULT;
+ 		} else
+ 			len = 0;
+ 		release_sock(sk);
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 460e7f9..e1df1ab 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -216,7 +216,7 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
+ /* Device list insertion */
+ static int list_netdevice(struct net_device *dev)
+ {
+-	struct net *net = dev->nd_net;
++	struct net *net = dev_net(dev);
+ 
+ 	ASSERT_RTNL();
+ 
+@@ -852,8 +852,8 @@ int dev_alloc_name(struct net_device *dev, const char *name)
+ 	struct net *net;
+ 	int ret;
+ 
+-	BUG_ON(!dev->nd_net);
+-	net = dev->nd_net;
++	BUG_ON(!dev_net(dev));
++	net = dev_net(dev);
+ 	ret = __dev_alloc_name(net, name, buf);
+ 	if (ret >= 0)
+ 		strlcpy(dev->name, buf, IFNAMSIZ);
+@@ -877,9 +877,9 @@ int dev_change_name(struct net_device *dev, char *newname)
+ 	struct net *net;
+ 
+ 	ASSERT_RTNL();
+-	BUG_ON(!dev->nd_net);
++	BUG_ON(!dev_net(dev));
+ 
+-	net = dev->nd_net;
++	net = dev_net(dev);
+ 	if (dev->flags & IFF_UP)
+ 		return -EBUSY;
+ 
+@@ -2615,7 +2615,7 @@ static int ptype_seq_show(struct seq_file *seq, void *v)
+ 
+ 	if (v == SEQ_START_TOKEN)
+ 		seq_puts(seq, "Type Device      Function\n");
+-	else {
++	else if (pt->dev == NULL || dev_net(pt->dev) == seq_file_net(seq)) {
+ 		if (pt->type == htons(ETH_P_ALL))
+ 			seq_puts(seq, "ALL ");
+ 		else
+@@ -2639,7 +2639,8 @@ static const struct seq_operations ptype_seq_ops = {
+ 
+ static int ptype_seq_open(struct inode *inode, struct file *file)
+ {
+-	return seq_open(file, &ptype_seq_ops);
++	return seq_open_net(inode, file, &ptype_seq_ops,
++			sizeof(struct seq_net_private));
+ }
+ 
+ static const struct file_operations ptype_seq_fops = {
+@@ -2647,7 +2648,7 @@ static const struct file_operations ptype_seq_fops = {
+ 	.open    = ptype_seq_open,
+ 	.read    = seq_read,
+ 	.llseek  = seq_lseek,
+-	.release = seq_release,
++	.release = seq_release_net,
+ };
+ 
+ 
+@@ -3688,8 +3689,8 @@ int register_netdevice(struct net_device *dev)
+ 
+ 	/* When net_device's are persistent, this will be fatal. */
+ 	BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
+-	BUG_ON(!dev->nd_net);
+-	net = dev->nd_net;
++	BUG_ON(!dev_net(dev));
++	net = dev_net(dev);
+ 
+ 	spin_lock_init(&dev->queue_lock);
+ 	spin_lock_init(&dev->_xmit_lock);
+@@ -3995,11 +3996,15 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+ 
+ 	BUG_ON(strlen(name) >= sizeof(dev->name));
+ 
+-	/* ensure 32-byte alignment of both the device and private area */
+-	alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST +
+-		     (sizeof(struct net_device_subqueue) * (queue_count - 1))) &
+-		     ~NETDEV_ALIGN_CONST;
+-	alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
++	alloc_size = sizeof(struct net_device) +
++		     sizeof(struct net_device_subqueue) * (queue_count - 1);
++	if (sizeof_priv) {
++		/* ensure 32-byte alignment of private area */
++		alloc_size = (alloc_size + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
++		alloc_size += sizeof_priv;
++	}
++	/* ensure 32-byte alignment of whole construct */
++	alloc_size += NETDEV_ALIGN_CONST;
+ 
+ 	p = kzalloc(alloc_size, GFP_KERNEL);
+ 	if (!p) {
+@@ -4010,7 +4015,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+ 	dev = (struct net_device *)
+ 		(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+ 	dev->padded = (char *)dev - (char *)p;
+-	dev->nd_net = &init_net;
++	dev_net_set(dev, &init_net);
+ 
+ 	if (sizeof_priv) {
+ 		dev->priv = ((char *)dev +
+@@ -4021,6 +4026,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+ 	}
+ 
+ 	dev->egress_subqueue_count = queue_count;
++	dev->gso_max_size = GSO_MAX_SIZE;
+ 
+ 	dev->get_stats = internal_stats;
+ 	netpoll_netdev_init(dev);
+@@ -4040,6 +4046,8 @@ EXPORT_SYMBOL(alloc_netdev_mq);
+  */
+ void free_netdev(struct net_device *dev)
+ {
++	release_net(dev_net(dev));
++
+ 	/*  Compatibility with error handling in drivers */
+ 	if (dev->reg_state == NETREG_UNINITIALIZED) {
+ 		kfree((char *)dev - dev->padded);
+@@ -4134,7 +4142,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
+ 
+ 	/* Get out if there is nothing todo */
+ 	err = 0;
+-	if (dev->nd_net == net)
++	if (net_eq(dev_net(dev), net))
+ 		goto out;
+ 
+ 	/* Pick the destination device name, and ensure
+@@ -4185,7 +4193,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
+ 	dev_addr_discard(dev);
+ 
+ 	/* Actually switch the network namespace */
+-	dev->nd_net = net;
++	dev_net_set(dev, net);
+ 
+ 	/* Assign the new device name */
+ 	if (destname != dev->name)
+diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
+index cec5825..f8a3455 100644
+--- a/net/core/dev_mcast.c
++++ b/net/core/dev_mcast.c
+@@ -156,39 +156,14 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
+ EXPORT_SYMBOL(dev_mc_unsync);
+ 
+ #ifdef CONFIG_PROC_FS
+-static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
+-	__acquires(dev_base_lock)
+-{
+-	struct net *net = seq_file_net(seq);
+-	struct net_device *dev;
+-	loff_t off = 0;
+-
+-	read_lock(&dev_base_lock);
+-	for_each_netdev(net, dev) {
+-		if (off++ == *pos)
+-			return dev;
+-	}
+-	return NULL;
+-}
+-
+-static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+-{
+-	++*pos;
+-	return next_net_device((struct net_device *)v);
+-}
+-
+-static void dev_mc_seq_stop(struct seq_file *seq, void *v)
+-	__releases(dev_base_lock)
+-{
+-	read_unlock(&dev_base_lock);
+-}
+-
+-
+ static int dev_mc_seq_show(struct seq_file *seq, void *v)
+ {
+ 	struct dev_addr_list *m;
+ 	struct net_device *dev = v;
+ 
++	if (v == SEQ_START_TOKEN)
++		return 0;
++
+ 	netif_tx_lock_bh(dev);
+ 	for (m = dev->mc_list; m; m = m->next) {
+ 		int i;
+@@ -206,9 +181,9 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v)
+ }
+ 
+ static const struct seq_operations dev_mc_seq_ops = {
+-	.start = dev_mc_seq_start,
+-	.next  = dev_mc_seq_next,
+-	.stop  = dev_mc_seq_stop,
++	.start = dev_seq_start,
++	.next  = dev_seq_next,
++	.stop  = dev_seq_stop,
+ 	.show  = dev_mc_seq_show,
+ };
+ 
+diff --git a/net/core/dst.c b/net/core/dst.c
+index 7deef48..fe03266 100644
+--- a/net/core/dst.c
++++ b/net/core/dst.c
+@@ -259,6 +259,16 @@ again:
+ 	return NULL;
+ }
+ 
++void dst_release(struct dst_entry *dst)
++{
++	if (dst) {
++		WARN_ON(atomic_read(&dst->__refcnt) < 1);
++		smp_mb__before_atomic_dec();
++		atomic_dec(&dst->__refcnt);
++	}
++}
++EXPORT_SYMBOL(dst_release);
++
+ /* 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
+@@ -279,7 +289,7 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ 	if (!unregister) {
+ 		dst->input = dst->output = dst_discard;
+ 	} else {
+-		dst->dev = dst->dev->nd_net->loopback_dev;
++		dst->dev = dev_net(dst->dev)->loopback_dev;
+ 		dev_hold(dst->dev);
+ 		dev_put(dev);
+ 		if (dst->neighbour && dst->neighbour->dev == dev) {
+@@ -295,9 +305,6 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
+ 	struct net_device *dev = ptr;
+ 	struct dst_entry *dst, *last = NULL;
+ 
+-	if (dev->nd_net != &init_net)
+-		return NOTIFY_DONE;
+-
+ 	switch (event) {
+ 	case NETDEV_UNREGISTER:
+ 	case NETDEV_DOWN:
+diff --git a/net/core/ethtool.c b/net/core/ethtool.c
+index 1163eb2..0133b5e 100644
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -284,8 +284,10 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
+ {
+ 	struct ethtool_eeprom eeprom;
+ 	const struct ethtool_ops *ops = dev->ethtool_ops;
++	void __user *userbuf = useraddr + sizeof(eeprom);
++	u32 bytes_remaining;
+ 	u8 *data;
+-	int ret;
++	int ret = 0;
+ 
+ 	if (!ops->get_eeprom || !ops->get_eeprom_len)
+ 		return -EOPNOTSUPP;
+@@ -301,26 +303,31 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
+ 	if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
+ 		return -EINVAL;
+ 
+-	data = kmalloc(eeprom.len, GFP_USER);
++	data = kmalloc(PAGE_SIZE, GFP_USER);
+ 	if (!data)
+ 		return -ENOMEM;
+ 
+-	ret = -EFAULT;
+-	if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
+-		goto out;
++	bytes_remaining = eeprom.len;
++	while (bytes_remaining > 0) {
++		eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
+ 
+-	ret = ops->get_eeprom(dev, &eeprom, data);
+-	if (ret)
+-		goto out;
++		ret = ops->get_eeprom(dev, &eeprom, data);
++		if (ret)
++			break;
++		if (copy_to_user(userbuf, data, eeprom.len)) {
++			ret = -EFAULT;
++			break;
++		}
++		userbuf += eeprom.len;
++		eeprom.offset += eeprom.len;
++		bytes_remaining -= eeprom.len;
++	}
+ 
+-	ret = -EFAULT;
++	eeprom.len = userbuf - (useraddr + sizeof(eeprom));
++	eeprom.offset -= eeprom.len;
+ 	if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
+-		goto out;
+-	if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
+-		goto out;
+-	ret = 0;
++		ret = -EFAULT;
+ 
+- out:
+ 	kfree(data);
+ 	return ret;
+ }
+@@ -329,8 +336,10 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
+ {
+ 	struct ethtool_eeprom eeprom;
+ 	const struct ethtool_ops *ops = dev->ethtool_ops;
++	void __user *userbuf = useraddr + sizeof(eeprom);
++	u32 bytes_remaining;
+ 	u8 *data;
+-	int ret;
++	int ret = 0;
+ 
+ 	if (!ops->set_eeprom || !ops->get_eeprom_len)
+ 		return -EOPNOTSUPP;
+@@ -346,22 +355,26 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
+ 	if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
+ 		return -EINVAL;
+ 
+-	data = kmalloc(eeprom.len, GFP_USER);
++	data = kmalloc(PAGE_SIZE, GFP_USER);
+ 	if (!data)
+ 		return -ENOMEM;
+ 
+-	ret = -EFAULT;
+-	if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
+-		goto out;
+-
+-	ret = ops->set_eeprom(dev, &eeprom, data);
+-	if (ret)
+-		goto out;
++	bytes_remaining = eeprom.len;
++	while (bytes_remaining > 0) {
++		eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
+ 
+-	if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
+-		ret = -EFAULT;
++		if (copy_from_user(data, userbuf, eeprom.len)) {
++			ret = -EFAULT;
++			break;
++		}
++		ret = ops->set_eeprom(dev, &eeprom, data);
++		if (ret)
++			break;
++		userbuf += eeprom.len;
++		eeprom.offset += eeprom.len;
++		bytes_remaining -= eeprom.len;
++	}
+ 
+- out:
+ 	kfree(data);
+ 	return ret;
+ }
+diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
+index 42ccaf5..e3e9ab0 100644
+--- a/net/core/fib_rules.c
++++ b/net/core/fib_rules.c
+@@ -29,7 +29,7 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
+ 	r->pref = pref;
+ 	r->table = table;
+ 	r->flags = flags;
+-	r->fr_net = ops->fro_net;
++	r->fr_net = hold_net(ops->fro_net);
+ 
+ 	/* The lock is not required here, the list in unreacheable
+ 	 * at the moment this function is called */
+@@ -214,7 +214,7 @@ errout:
+ 
+ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct fib_rule_hdr *frh = nlmsg_data(nlh);
+ 	struct fib_rules_ops *ops = NULL;
+ 	struct fib_rule *rule, *r, *last = NULL;
+@@ -243,7 +243,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ 		err = -ENOMEM;
+ 		goto errout;
+ 	}
+-	rule->fr_net = net;
++	rule->fr_net = hold_net(net);
+ 
+ 	if (tb[FRA_PRIORITY])
+ 		rule->pref = nla_get_u32(tb[FRA_PRIORITY]);
+@@ -344,6 +344,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ 	return 0;
+ 
+ errout_free:
++	release_net(rule->fr_net);
+ 	kfree(rule);
+ errout:
+ 	rules_ops_put(ops);
+@@ -352,7 +353,7 @@ errout:
+ 
+ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct fib_rule_hdr *frh = nlmsg_data(nlh);
+ 	struct fib_rules_ops *ops = NULL;
+ 	struct fib_rule *rule, *tmp;
+@@ -534,7 +535,7 @@ skip:
+ 
+ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct fib_rules_ops *ops;
+ 	int idx = 0, family;
+ 
+@@ -618,7 +619,7 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
+ 			    void *ptr)
+ {
+ 	struct net_device *dev = ptr;
+-	struct net *net = dev->nd_net;
++	struct net *net = dev_net(dev);
+ 	struct fib_rules_ops *ops;
+ 
+ 	ASSERT_RTNL();
+diff --git a/net/core/filter.c b/net/core/filter.c
+index e0a0694..f5f3cf6 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -27,6 +27,7 @@
+ #include <linux/if_packet.h>
+ #include <net/ip.h>
+ #include <net/protocol.h>
++#include <net/netlink.h>
+ #include <linux/skbuff.h>
+ #include <net/sock.h>
+ #include <linux/errno.h>
+@@ -64,6 +65,41 @@ static inline void *load_pointer(struct sk_buff *skb, int k,
+ }
+ 
+ /**
++ *	sk_filter - run a packet through a socket filter
++ *	@sk: sock associated with &sk_buff
++ *	@skb: buffer to filter
++ *	@needlock: set to 1 if the sock is not locked by caller.
++ *
++ * Run the filter code and then cut skb->data to correct size returned by
++ * sk_run_filter. If pkt_len is 0 we toss packet. If skb->len is smaller
++ * than pkt_len we keep whole skb->data. This is the socket level
++ * wrapper to sk_run_filter. It returns 0 if the packet should
++ * be accepted or -EPERM if the packet should be tossed.
++ *
++ */
++int sk_filter(struct sock *sk, struct sk_buff *skb)
++{
++	int err;
++	struct sk_filter *filter;
++
++	err = security_sock_rcv_skb(sk, skb);
++	if (err)
++		return err;
++
++	rcu_read_lock_bh();
++	filter = rcu_dereference(sk->sk_filter);
++	if (filter) {
++		unsigned int pkt_len = sk_run_filter(skb, filter->insns,
++				filter->len);
++		err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
++	}
++	rcu_read_unlock_bh();
++
++	return err;
++}
++EXPORT_SYMBOL(sk_filter);
++
++/**
+  *	sk_run_filter - run a filter on a socket
+  *	@skb: buffer to run the filter on
+  *	@filter: filter to apply
+@@ -268,6 +304,22 @@ load_b:
+ 		case SKF_AD_IFINDEX:
+ 			A = skb->dev->ifindex;
+ 			continue;
++		case SKF_AD_NLATTR: {
++			struct nlattr *nla;
++
++			if (skb_is_nonlinear(skb))
++				return 0;
++			if (A > skb->len - sizeof(struct nlattr))
++				return 0;
++
++			nla = nla_find((struct nlattr *)&skb->data[A],
++				       skb->len - A, X);
++			if (nla)
++				A = (void *)nla - (void *)skb->data;
++			else
++				A = 0;
++			continue;
++		}
+ 		default:
+ 			return 0;
+ 		}
+@@ -275,6 +327,7 @@ load_b:
+ 
+ 	return 0;
+ }
++EXPORT_SYMBOL(sk_run_filter);
+ 
+ /**
+  *	sk_chk_filter - verify socket filter code
+@@ -385,6 +438,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
+ 
+ 	return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL;
+ }
++EXPORT_SYMBOL(sk_chk_filter);
+ 
+ /**
+  * 	sk_filter_rcu_release: Release a socket filter by rcu_head
+@@ -467,6 +521,3 @@ int sk_detach_filter(struct sock *sk)
+ 	rcu_read_unlock_bh();
+ 	return ret;
+ }
+-
+-EXPORT_SYMBOL(sk_chk_filter);
+-EXPORT_SYMBOL(sk_run_filter);
+diff --git a/net/core/flow.c b/net/core/flow.c
+index a77531c..1999117 100644
+--- a/net/core/flow.c
++++ b/net/core/flow.c
+@@ -23,7 +23,6 @@
+ #include <linux/mutex.h>
+ #include <net/flow.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <linux/security.h>
+ 
+ struct flow_cache_entry {
+diff --git a/net/core/neighbour.c b/net/core/neighbour.c
+index 19b8e00..75075c3 100644
+--- a/net/core/neighbour.c
++++ b/net/core/neighbour.c
+@@ -123,6 +123,7 @@ unsigned long neigh_rand_reach_time(unsigned long base)
+ {
+ 	return (base ? (net_random() % base) + (base >> 1) : 0);
+ }
++EXPORT_SYMBOL(neigh_rand_reach_time);
+ 
+ 
+ static int neigh_forced_gc(struct neigh_table *tbl)
+@@ -241,6 +242,7 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
+ 	neigh_flush_dev(tbl, dev);
+ 	write_unlock_bh(&tbl->lock);
+ }
++EXPORT_SYMBOL(neigh_changeaddr);
+ 
+ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
+ {
+@@ -253,6 +255,7 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
+ 	pneigh_queue_purge(&tbl->proxy_queue);
+ 	return 0;
+ }
++EXPORT_SYMBOL(neigh_ifdown);
+ 
+ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
+ {
+@@ -374,6 +377,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
+ 	read_unlock_bh(&tbl->lock);
+ 	return n;
+ }
++EXPORT_SYMBOL(neigh_lookup);
+ 
+ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
+ 				     const void *pkey)
+@@ -388,7 +392,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
+ 	hash_val = tbl->hash(pkey, NULL);
+ 	for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
+ 		if (!memcmp(n->primary_key, pkey, key_len) &&
+-		    (net == n->dev->nd_net)) {
++		    net_eq(dev_net(n->dev), net)) {
+ 			neigh_hold(n);
+ 			NEIGH_CACHE_STAT_INC(tbl, hits);
+ 			break;
+@@ -397,6 +401,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
+ 	read_unlock_bh(&tbl->lock);
+ 	return n;
+ }
++EXPORT_SYMBOL(neigh_lookup_nodev);
+ 
+ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
+ 			       struct net_device *dev)
+@@ -465,28 +470,44 @@ out_neigh_release:
+ 	neigh_release(n);
+ 	goto out;
+ }
++EXPORT_SYMBOL(neigh_create);
+ 
+-struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
+-		struct net *net, const void *pkey, struct net_device *dev)
++static u32 pneigh_hash(const void *pkey, int key_len)
+ {
+-	struct pneigh_entry *n;
+-	int key_len = tbl->key_len;
+ 	u32 hash_val = *(u32 *)(pkey + key_len - 4);
+-
+ 	hash_val ^= (hash_val >> 16);
+ 	hash_val ^= hash_val >> 8;
+ 	hash_val ^= hash_val >> 4;
+ 	hash_val &= PNEIGH_HASHMASK;
++	return hash_val;
++}
+ 
+-	for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
++static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
++					      struct net *net,
++					      const void *pkey,
++					      int key_len,
++					      struct net_device *dev)
++{
++	while (n) {
+ 		if (!memcmp(n->key, pkey, key_len) &&
+-		    (n->net == net) &&
++		    net_eq(pneigh_net(n), net) &&
+ 		    (n->dev == dev || !n->dev))
+-			break;
++			return n;
++		n = n->next;
+ 	}
++	return NULL;
++}
+ 
+-	return n;
++struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
++		struct net *net, const void *pkey, struct net_device *dev)
++{
++	int key_len = tbl->key_len;
++	u32 hash_val = pneigh_hash(pkey, key_len);
++
++	return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
++				 net, pkey, key_len, dev);
+ }
++EXPORT_SYMBOL_GPL(__pneigh_lookup);
+ 
+ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+ 				    struct net *net, const void *pkey,
+@@ -494,26 +515,14 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+ {
+ 	struct pneigh_entry *n;
+ 	int key_len = tbl->key_len;
+-	u32 hash_val = *(u32 *)(pkey + key_len - 4);
+-
+-	hash_val ^= (hash_val >> 16);
+-	hash_val ^= hash_val >> 8;
+-	hash_val ^= hash_val >> 4;
+-	hash_val &= PNEIGH_HASHMASK;
++	u32 hash_val = pneigh_hash(pkey, key_len);
+ 
+ 	read_lock_bh(&tbl->lock);
+-
+-	for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
+-		if (!memcmp(n->key, pkey, key_len) &&
+-		    (n->net == net) &&
+-		    (n->dev == dev || !n->dev)) {
+-			read_unlock_bh(&tbl->lock);
+-			goto out;
+-		}
+-	}
++	n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
++			      net, pkey, key_len, dev);
+ 	read_unlock_bh(&tbl->lock);
+-	n = NULL;
+-	if (!creat)
++
++	if (n || !creat)
+ 		goto out;
+ 
+ 	ASSERT_RTNL();
+@@ -522,7 +531,9 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+ 	if (!n)
+ 		goto out;
+ 
++#ifdef CONFIG_NET_NS
+ 	n->net = hold_net(net);
++#endif
+ 	memcpy(n->key, pkey, key_len);
+ 	n->dev = dev;
+ 	if (dev)
+@@ -544,6 +555,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+ out:
+ 	return n;
+ }
++EXPORT_SYMBOL(pneigh_lookup);
+ 
+ 
+ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
+@@ -551,25 +563,20 @@ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
+ {
+ 	struct pneigh_entry *n, **np;
+ 	int key_len = tbl->key_len;
+-	u32 hash_val = *(u32 *)(pkey + key_len - 4);
+-
+-	hash_val ^= (hash_val >> 16);
+-	hash_val ^= hash_val >> 8;
+-	hash_val ^= hash_val >> 4;
+-	hash_val &= PNEIGH_HASHMASK;
++	u32 hash_val = pneigh_hash(pkey, key_len);
+ 
+ 	write_lock_bh(&tbl->lock);
+ 	for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
+ 	     np = &n->next) {
+ 		if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
+-		    (n->net == net)) {
++		    net_eq(pneigh_net(n), net)) {
+ 			*np = n->next;
+ 			write_unlock_bh(&tbl->lock);
+ 			if (tbl->pdestructor)
+ 				tbl->pdestructor(n);
+ 			if (n->dev)
+ 				dev_put(n->dev);
+-			release_net(n->net);
++			release_net(pneigh_net(n));
+ 			kfree(n);
+ 			return 0;
+ 		}
+@@ -592,7 +599,7 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
+ 					tbl->pdestructor(n);
+ 				if (n->dev)
+ 					dev_put(n->dev);
+-				release_net(n->net);
++				release_net(pneigh_net(n));
+ 				kfree(n);
+ 				continue;
+ 			}
+@@ -651,6 +658,7 @@ void neigh_destroy(struct neighbour *neigh)
+ 	atomic_dec(&neigh->tbl->entries);
+ 	kmem_cache_free(neigh->tbl->kmem_cachep, neigh);
+ }
++EXPORT_SYMBOL(neigh_destroy);
+ 
+ /* Neighbour state is suspicious;
+    disable fast path.
+@@ -931,6 +939,7 @@ out_unlock_bh:
+ 	write_unlock_bh(&neigh->lock);
+ 	return rc;
+ }
++EXPORT_SYMBOL(__neigh_event_send);
+ 
+ static void neigh_update_hhs(struct neighbour *neigh)
+ {
+@@ -1103,6 +1112,7 @@ out:
+ 
+ 	return err;
+ }
++EXPORT_SYMBOL(neigh_update);
+ 
+ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
+ 				 u8 *lladdr, void *saddr,
+@@ -1115,6 +1125,7 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
+ 			     NEIGH_UPDATE_F_OVERRIDE);
+ 	return neigh;
+ }
++EXPORT_SYMBOL(neigh_event_ns);
+ 
+ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
+ 			  __be16 protocol)
+@@ -1169,6 +1180,7 @@ int neigh_compat_output(struct sk_buff *skb)
+ 
+ 	return dev_queue_xmit(skb);
+ }
++EXPORT_SYMBOL(neigh_compat_output);
+ 
+ /* Slow and careful. */
+ 
+@@ -1214,6 +1226,7 @@ out_kfree_skb:
+ 	kfree_skb(skb);
+ 	goto out;
+ }
++EXPORT_SYMBOL(neigh_resolve_output);
+ 
+ /* As fast as possible without hh cache */
+ 
+@@ -1238,6 +1251,7 @@ int neigh_connected_output(struct sk_buff *skb)
+ 	}
+ 	return err;
+ }
++EXPORT_SYMBOL(neigh_connected_output);
+ 
+ static void neigh_proxy_process(unsigned long arg)
+ {
+@@ -1299,6 +1313,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+ 	mod_timer(&tbl->proxy_timer, sched_next);
+ 	spin_unlock(&tbl->proxy_queue.lock);
+ }
++EXPORT_SYMBOL(pneigh_enqueue);
+ 
+ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
+ 						      struct net *net, int ifindex)
+@@ -1306,9 +1321,7 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
+ 	struct neigh_parms *p;
+ 
+ 	for (p = &tbl->parms; p; p = p->next) {
+-		if (p->net != net)
+-			continue;
+-		if ((p->dev && p->dev->ifindex == ifindex) ||
++		if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
+ 		    (!p->dev && !ifindex))
+ 			return p;
+ 	}
+@@ -1322,7 +1335,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
+ 	struct neigh_parms *p, *ref;
+ 	struct net *net;
+ 
+-	net = dev->nd_net;
++	net = dev_net(dev);
+ 	ref = lookup_neigh_params(tbl, net, 0);
+ 	if (!ref)
+ 		return NULL;
+@@ -1342,7 +1355,9 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
+ 
+ 		dev_hold(dev);
+ 		p->dev = dev;
++#ifdef CONFIG_NET_NS
+ 		p->net = hold_net(net);
++#endif
+ 		p->sysctl_table = NULL;
+ 		write_lock_bh(&tbl->lock);
+ 		p->next		= tbl->parms.next;
+@@ -1351,6 +1366,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
+ 	}
+ 	return p;
+ }
++EXPORT_SYMBOL(neigh_parms_alloc);
+ 
+ static void neigh_rcu_free_parms(struct rcu_head *head)
+ {
+@@ -1381,10 +1397,11 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
+ 	write_unlock_bh(&tbl->lock);
+ 	NEIGH_PRINTK1("neigh_parms_release: not found\n");
+ }
++EXPORT_SYMBOL(neigh_parms_release);
+ 
+ static void neigh_parms_destroy(struct neigh_parms *parms)
+ {
+-	release_net(parms->net);
++	release_net(neigh_parms_net(parms));
+ 	kfree(parms);
+ }
+ 
+@@ -1395,7 +1412,9 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
+ 	unsigned long now = jiffies;
+ 	unsigned long phsize;
+ 
++#ifdef CONFIG_NET_NS
+ 	tbl->parms.net = &init_net;
++#endif
+ 	atomic_set(&tbl->parms.refcnt, 1);
+ 	INIT_RCU_HEAD(&tbl->parms.rcu_head);
+ 	tbl->parms.reachable_time =
+@@ -1441,6 +1460,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
+ 	tbl->last_flush = now;
+ 	tbl->last_rand	= now + tbl->parms.reachable_time * 20;
+ }
++EXPORT_SYMBOL(neigh_table_init_no_netlink);
+ 
+ void neigh_table_init(struct neigh_table *tbl)
+ {
+@@ -1462,6 +1482,7 @@ void neigh_table_init(struct neigh_table *tbl)
+ 		dump_stack();
+ 	}
+ }
++EXPORT_SYMBOL(neigh_table_init);
+ 
+ int neigh_table_clear(struct neigh_table *tbl)
+ {
+@@ -1499,10 +1520,11 @@ int neigh_table_clear(struct neigh_table *tbl)
+ 
+ 	return 0;
+ }
++EXPORT_SYMBOL(neigh_table_clear);
+ 
+ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct ndmsg *ndm;
+ 	struct nlattr *dst_attr;
+ 	struct neigh_table *tbl;
+@@ -1568,7 +1590,7 @@ out:
+ 
+ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct ndmsg *ndm;
+ 	struct nlattr *tb[NDA_MAX+1];
+ 	struct neigh_table *tbl;
+@@ -1836,7 +1858,7 @@ static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
+ 
+ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct neigh_table *tbl;
+ 	struct ndtmsg *ndtmsg;
+ 	struct nlattr *tb[NDTA_MAX+1];
+@@ -1961,7 +1983,7 @@ errout:
+ 
+ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	int family, tidx, nidx = 0;
+ 	int tbl_skip = cb->args[0];
+ 	int neigh_skip = cb->args[1];
+@@ -1982,7 +2004,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
+ 			break;
+ 
+ 		for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
+-			if (net != p->net)
++			if (!net_eq(neigh_parms_net(p), net))
+ 				continue;
+ 
+ 			if (nidx++ < neigh_skip)
+@@ -2061,7 +2083,7 @@ static void neigh_update_notify(struct neighbour *neigh)
+ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
+ 			    struct netlink_callback *cb)
+ {
+-	struct net * net = skb->sk->sk_net;
++	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];
+@@ -2074,7 +2096,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
+ 			s_idx = 0;
+ 		for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) {
+ 			int lidx;
+-			if (n->dev->nd_net != net)
++			if (dev_net(n->dev) != net)
+ 				continue;
+ 			lidx = idx++;
+ 			if (lidx < s_idx)
+@@ -2169,7 +2191,7 @@ EXPORT_SYMBOL(__neigh_for_each_release);
+ static struct neighbour *neigh_get_first(struct seq_file *seq)
+ {
+ 	struct neigh_seq_state *state = seq->private;
+-	struct net *net = state->p.net;
++	struct net *net = seq_file_net(seq);
+ 	struct neigh_table *tbl = state->tbl;
+ 	struct neighbour *n = NULL;
+ 	int bucket = state->bucket;
+@@ -2179,7 +2201,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
+ 		n = tbl->hash_buckets[bucket];
+ 
+ 		while (n) {
+-			if (n->dev->nd_net != net)
++			if (!net_eq(dev_net(n->dev), net))
+ 				goto next;
+ 			if (state->neigh_sub_iter) {
+ 				loff_t fakep = 0;
+@@ -2210,7 +2232,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
+ 					loff_t *pos)
+ {
+ 	struct neigh_seq_state *state = seq->private;
+-	struct net *net = state->p.net;
++	struct net *net = seq_file_net(seq);
+ 	struct neigh_table *tbl = state->tbl;
+ 
+ 	if (state->neigh_sub_iter) {
+@@ -2222,7 +2244,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
+ 
+ 	while (1) {
+ 		while (n) {
+-			if (n->dev->nd_net != net)
++			if (!net_eq(dev_net(n->dev), net))
+ 				goto next;
+ 			if (state->neigh_sub_iter) {
+ 				void *v = state->neigh_sub_iter(state, n, pos);
+@@ -2270,7 +2292,7 @@ static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
+ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
+ {
+ 	struct neigh_seq_state *state = seq->private;
+-	struct net * net = state->p.net;
++	struct net *net = seq_file_net(seq);
+ 	struct neigh_table *tbl = state->tbl;
+ 	struct pneigh_entry *pn = NULL;
+ 	int bucket = state->bucket;
+@@ -2278,7 +2300,7 @@ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
+ 	state->flags |= NEIGH_SEQ_IS_PNEIGH;
+ 	for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
+ 		pn = tbl->phash_buckets[bucket];
+-		while (pn && (pn->net != net))
++		while (pn && !net_eq(pneigh_net(pn), net))
+ 			pn = pn->next;
+ 		if (pn)
+ 			break;
+@@ -2293,7 +2315,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
+ 					    loff_t *pos)
+ {
+ 	struct neigh_seq_state *state = seq->private;
+-	struct net * net = state->p.net;
++	struct net *net = seq_file_net(seq);
+ 	struct neigh_table *tbl = state->tbl;
+ 
+ 	pn = pn->next;
+@@ -2301,7 +2323,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
+ 		if (++state->bucket > PNEIGH_HASHMASK)
+ 			break;
+ 		pn = tbl->phash_buckets[state->bucket];
+-		while (pn && (pn->net != net))
++		while (pn && !net_eq(pneigh_net(pn), net))
+ 			pn = pn->next;
+ 		if (pn)
+ 			break;
+@@ -2506,7 +2528,7 @@ static inline size_t neigh_nlmsg_size(void)
+ 
+ static void __neigh_notify(struct neighbour *n, int type, int flags)
+ {
+-	struct net *net = n->dev->nd_net;
++	struct net *net = dev_net(n->dev);
+ 	struct sk_buff *skb;
+ 	int err = -ENOBUFS;
+ 
+@@ -2532,6 +2554,7 @@ void neigh_app_ns(struct neighbour *n)
+ {
+ 	__neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
+ }
++EXPORT_SYMBOL(neigh_app_ns);
+ #endif /* CONFIG_ARPD */
+ 
+ #ifdef CONFIG_SYSCTL
+@@ -2763,7 +2786,8 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
+ 	neigh_path[NEIGH_CTL_PATH_PROTO].procname = p_name;
+ 	neigh_path[NEIGH_CTL_PATH_PROTO].ctl_name = p_id;
+ 
+-	t->sysctl_header = register_sysctl_paths(neigh_path, t->neigh_vars);
++	t->sysctl_header =
++		register_net_sysctl_table(neigh_parms_net(p), neigh_path, t->neigh_vars);
+ 	if (!t->sysctl_header)
+ 		goto free_procname;
+ 
+@@ -2777,6 +2801,7 @@ free:
+ err:
+ 	return -ENOBUFS;
+ }
++EXPORT_SYMBOL(neigh_sysctl_register);
+ 
+ void neigh_sysctl_unregister(struct neigh_parms *p)
+ {
+@@ -2788,6 +2813,7 @@ void neigh_sysctl_unregister(struct neigh_parms *p)
+ 		kfree(t);
+ 	}
+ }
++EXPORT_SYMBOL(neigh_sysctl_unregister);
+ 
+ #endif	/* CONFIG_SYSCTL */
+ 
+@@ -2805,32 +2831,3 @@ static int __init neigh_init(void)
+ 
+ subsys_initcall(neigh_init);
+ 
+-EXPORT_SYMBOL(__neigh_event_send);
+-EXPORT_SYMBOL(neigh_changeaddr);
+-EXPORT_SYMBOL(neigh_compat_output);
+-EXPORT_SYMBOL(neigh_connected_output);
+-EXPORT_SYMBOL(neigh_create);
+-EXPORT_SYMBOL(neigh_destroy);
+-EXPORT_SYMBOL(neigh_event_ns);
+-EXPORT_SYMBOL(neigh_ifdown);
+-EXPORT_SYMBOL(neigh_lookup);
+-EXPORT_SYMBOL(neigh_lookup_nodev);
+-EXPORT_SYMBOL(neigh_parms_alloc);
+-EXPORT_SYMBOL(neigh_parms_release);
+-EXPORT_SYMBOL(neigh_rand_reach_time);
+-EXPORT_SYMBOL(neigh_resolve_output);
+-EXPORT_SYMBOL(neigh_table_clear);
+-EXPORT_SYMBOL(neigh_table_init);
+-EXPORT_SYMBOL(neigh_table_init_no_netlink);
+-EXPORT_SYMBOL(neigh_update);
+-EXPORT_SYMBOL(pneigh_enqueue);
+-EXPORT_SYMBOL(pneigh_lookup);
+-EXPORT_SYMBOL_GPL(__pneigh_lookup);
+-
+-#ifdef CONFIG_ARPD
+-EXPORT_SYMBOL(neigh_app_ns);
+-#endif
+-#ifdef CONFIG_SYSCTL
+-EXPORT_SYMBOL(neigh_sysctl_register);
+-EXPORT_SYMBOL(neigh_sysctl_unregister);
+-#endif
+diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
+index 7635d3f..4e7b847 100644
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -87,6 +87,7 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
+ 	return ret;
+ }
+ 
++NETDEVICE_SHOW(dev_id, fmt_hex);
+ NETDEVICE_SHOW(addr_len, fmt_dec);
+ NETDEVICE_SHOW(iflink, fmt_dec);
+ NETDEVICE_SHOW(ifindex, fmt_dec);
+@@ -210,6 +211,7 @@ static ssize_t store_tx_queue_len(struct device *dev,
+ 
+ static struct device_attribute net_class_attributes[] = {
+ 	__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
++	__ATTR(dev_id, S_IRUGO, show_dev_id, NULL),
+ 	__ATTR(iflink, S_IRUGO, show_iflink, NULL),
+ 	__ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
+ 	__ATTR(features, S_IRUGO, show_features, NULL),
+diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
+index 7b66083..72b4c18 100644
+--- a/net/core/net_namespace.c
++++ b/net/core/net_namespace.c
+@@ -5,7 +5,9 @@
+ #include <linux/list.h>
+ #include <linux/delay.h>
+ #include <linux/sched.h>
++#include <linux/idr.h>
+ #include <net/net_namespace.h>
++#include <net/netns/generic.h>
+ 
+ /*
+  *	Our network namespace constructor/destructor lists
+@@ -20,6 +22,8 @@ LIST_HEAD(net_namespace_list);
+ struct net init_net;
+ EXPORT_SYMBOL(init_net);
+ 
++#define INITIAL_NET_GEN_PTRS	13 /* +1 for len +2 for rcu_head */
++
+ /*
+  * setup_net runs the initializers for the network namespace object.
+  */
+@@ -28,9 +32,22 @@ static __net_init int setup_net(struct net *net)
+ 	/* Must be called with net_mutex held */
+ 	struct pernet_operations *ops;
+ 	int error;
++	struct net_generic *ng;
+ 
+ 	atomic_set(&net->count, 1);
++#ifdef NETNS_REFCNT_DEBUG
+ 	atomic_set(&net->use_count, 0);
++#endif
++
++	error = -ENOMEM;
++	ng = kzalloc(sizeof(struct net_generic) +
++			INITIAL_NET_GEN_PTRS * sizeof(void *), GFP_KERNEL);
++	if (ng == NULL)
++		goto out;
++
++	ng->len = INITIAL_NET_GEN_PTRS;
++	INIT_RCU_HEAD(&ng->rcu);
++	rcu_assign_pointer(net->gen, ng);
+ 
+ 	error = 0;
+ 	list_for_each_entry(ops, &pernet_list, list) {
+@@ -53,6 +70,7 @@ out_undo:
+ 	}
+ 
+ 	rcu_barrier();
++	kfree(ng);
+ 	goto out;
+ }
+ 
+@@ -70,11 +88,13 @@ static void net_free(struct net *net)
+ 	if (!net)
+ 		return;
+ 
++#ifdef NETNS_REFCNT_DEBUG
+ 	if (unlikely(atomic_read(&net->use_count) != 0)) {
+ 		printk(KERN_EMERG "network namespace not free! Usage: %d\n",
+ 			atomic_read(&net->use_count));
+ 		return;
+ 	}
++#endif
+ 
+ 	kmem_cache_free(net_cachep, net);
+ }
+@@ -253,6 +273,8 @@ static void unregister_pernet_operations(struct pernet_operations *ops)
+ }
+ #endif
+ 
++static DEFINE_IDA(net_generic_ids);
++
+ /**
+  *      register_pernet_subsys - register a network namespace subsystem
+  *	@ops:  pernet operations structure for the subsystem
+@@ -330,6 +352,30 @@ int register_pernet_device(struct pernet_operations *ops)
+ }
+ EXPORT_SYMBOL_GPL(register_pernet_device);
+ 
++int register_pernet_gen_device(int *id, struct pernet_operations *ops)
++{
++	int error;
++	mutex_lock(&net_mutex);
++again:
++	error = ida_get_new_above(&net_generic_ids, 1, id);
++	if (error) {
++		if (error == -EAGAIN) {
++			ida_pre_get(&net_generic_ids, GFP_KERNEL);
++			goto again;
++		}
++		goto out;
++	}
++	error = register_pernet_operations(&pernet_list, ops);
++	if (error)
++		ida_remove(&net_generic_ids, *id);
++	else if (first_device == &pernet_list)
++		first_device = &ops->list;
++out:
++	mutex_unlock(&net_mutex);
++	return error;
++}
++EXPORT_SYMBOL_GPL(register_pernet_gen_device);
++
+ /**
+  *      unregister_pernet_device - unregister a network namespace netdevice
+  *	@ops: pernet operations structure to manipulate
+@@ -348,3 +394,61 @@ void unregister_pernet_device(struct pernet_operations *ops)
+ 	mutex_unlock(&net_mutex);
+ }
+ EXPORT_SYMBOL_GPL(unregister_pernet_device);
++
++void unregister_pernet_gen_device(int id, struct pernet_operations *ops)
++{
++	mutex_lock(&net_mutex);
++	if (&ops->list == first_device)
++		first_device = first_device->next;
++	unregister_pernet_operations(ops);
++	ida_remove(&net_generic_ids, id);
++	mutex_unlock(&net_mutex);
++}
++EXPORT_SYMBOL_GPL(unregister_pernet_gen_device);
++
++static void net_generic_release(struct rcu_head *rcu)
++{
++	struct net_generic *ng;
++
++	ng = container_of(rcu, struct net_generic, rcu);
++	kfree(ng);
++}
++
++int net_assign_generic(struct net *net, int id, void *data)
++{
++	struct net_generic *ng, *old_ng;
++
++	BUG_ON(!mutex_is_locked(&net_mutex));
++	BUG_ON(id == 0);
++
++	ng = old_ng = net->gen;
++	if (old_ng->len >= id)
++		goto assign;
++
++	ng = kzalloc(sizeof(struct net_generic) +
++			id * sizeof(void *), GFP_KERNEL);
++	if (ng == NULL)
++		return -ENOMEM;
++
++	/*
++	 * Some synchronisation notes:
++	 *
++	 * The net_generic explores the net->gen array inside rcu
++	 * read section. Besides once set the net->gen->ptr[x]
++	 * pointer never changes (see rules in netns/generic.h).
++	 *
++	 * That said, we simply duplicate this array and schedule
++	 * the old copy for kfree after a grace period.
++	 */
++
++	ng->len = id;
++	INIT_RCU_HEAD(&ng->rcu);
++	memcpy(&ng->ptr, &old_ng->ptr, old_ng->len);
++
++	rcu_assign_pointer(net->gen, ng);
++	call_rcu(&old_ng->rcu, net_generic_release);
++assign:
++	ng->ptr[id - 1] = data;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(net_assign_generic);
+diff --git a/net/core/netpoll.c b/net/core/netpoll.c
+index c635de5..b04d643 100644
+--- a/net/core/netpoll.c
++++ b/net/core/netpoll.c
+@@ -390,9 +390,7 @@ static void arp_reply(struct sk_buff *skb)
+ 	if (skb->dev->flags & IFF_NOARP)
+ 		return;
+ 
+-	if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+-				 (2 * skb->dev->addr_len) +
+-				 (2 * sizeof(u32)))))
++	if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
+ 		return;
+ 
+ 	skb_reset_network_header(skb);
+@@ -420,7 +418,7 @@ static void arp_reply(struct sk_buff *skb)
+ 	    ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
+ 		return;
+ 
+-	size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
++	size = arp_hdr_len(skb->dev);
+ 	send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
+ 			    LL_RESERVED_SPACE(np->dev));
+ 
+diff --git a/net/core/pktgen.c b/net/core/pktgen.c
+index 20e63b3..a803b44 100644
+--- a/net/core/pktgen.c
++++ b/net/core/pktgen.c
+@@ -1874,7 +1874,7 @@ static int pktgen_device_event(struct notifier_block *unused,
+ {
+ 	struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	/* It is OK that we do not hold the group lock right now,
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 2bd9c5f..cf857c4 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -82,6 +82,11 @@ int rtnl_trylock(void)
+ 	return mutex_trylock(&rtnl_mutex);
+ }
+ 
++int rtnl_is_locked(void)
++{
++	return mutex_is_locked(&rtnl_mutex);
++}
++
+ static struct rtnl_link *rtnl_msg_handlers[NPROTO];
+ 
+ static inline int rtm_msgindex(int msgtype)
+@@ -269,6 +274,26 @@ int rtnl_link_register(struct rtnl_link_ops *ops)
+ 
+ EXPORT_SYMBOL_GPL(rtnl_link_register);
+ 
++static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
++{
++	struct net_device *dev;
++restart:
++	for_each_netdev(net, dev) {
++		if (dev->rtnl_link_ops == ops) {
++			ops->dellink(dev);
++			goto restart;
++		}
++	}
++}
++
++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
+@@ -277,17 +302,10 @@ EXPORT_SYMBOL_GPL(rtnl_link_register);
+  */
+ void __rtnl_link_unregister(struct rtnl_link_ops *ops)
+ {
+-	struct net_device *dev, *n;
+ 	struct net *net;
+ 
+ 	for_each_net(net) {
+-restart:
+-		for_each_netdev_safe(net, dev, n) {
+-			if (dev->rtnl_link_ops == ops) {
+-				ops->dellink(dev);
+-				goto restart;
+-			}
+-		}
++		__rtnl_kill_links(net, ops);
+ 	}
+ 	list_del(&ops->list);
+ }
+@@ -662,7 +680,7 @@ nla_put_failure:
+ 
+ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	int idx;
+ 	int s_idx = cb->args[0];
+ 	struct net_device *dev;
+@@ -879,7 +897,7 @@ errout:
+ 
+ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct ifinfomsg *ifm;
+ 	struct net_device *dev;
+ 	int err;
+@@ -921,7 +939,7 @@ errout:
+ 
+ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	const struct rtnl_link_ops *ops;
+ 	struct net_device *dev;
+ 	struct ifinfomsg *ifm;
+@@ -972,7 +990,7 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
+ 			goto err_free;
+ 	}
+ 
+-	dev->nd_net = net;
++	dev_net_set(dev, net);
+ 	dev->rtnl_link_ops = ops;
+ 
+ 	if (tb[IFLA_MTU])
+@@ -1000,7 +1018,7 @@ err:
+ 
+ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	const struct rtnl_link_ops *ops;
+ 	struct net_device *dev;
+ 	struct ifinfomsg *ifm;
+@@ -1132,7 +1150,7 @@ replay:
+ 
+ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct ifinfomsg *ifm;
+ 	struct nlattr *tb[IFLA_MAX+1];
+ 	struct net_device *dev = NULL;
+@@ -1198,7 +1216,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
+ 
+ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
+ {
+-	struct net *net = dev->nd_net;
++	struct net *net = dev_net(dev);
+ 	struct sk_buff *skb;
+ 	int err = -ENOBUFS;
+ 
+@@ -1227,7 +1245,7 @@ static int rtattr_max;
+ 
+ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	rtnl_doit_func doit;
+ 	int sz_idx, kind;
+ 	int min_len;
+@@ -1389,6 +1407,7 @@ EXPORT_SYMBOL(rtnetlink_put_metrics);
+ EXPORT_SYMBOL(rtnl_lock);
+ EXPORT_SYMBOL(rtnl_trylock);
+ EXPORT_SYMBOL(rtnl_unlock);
++EXPORT_SYMBOL(rtnl_is_locked);
+ EXPORT_SYMBOL(rtnl_unicast);
+ EXPORT_SYMBOL(rtnl_notify);
+ EXPORT_SYMBOL(rtnl_set_sk_err);
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 6087013..4fe605f 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -263,6 +263,28 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
+ 	return skb;
+ }
+ 
++/**
++ *	dev_alloc_skb - allocate an skbuff for receiving
++ *	@length: length to allocate
++ *
++ *	Allocate a new &sk_buff and assign it a usage count of one. The
++ *	buffer has unspecified headroom built in. Users should allocate
++ *	the headroom they think they need without accounting for the
++ *	built in space. The built in space is used for optimisations.
++ *
++ *	%NULL is returned if there is no free memory. Although this function
++ *	allocates memory it can be called from an interrupt.
++ */
++struct sk_buff *dev_alloc_skb(unsigned int length)
++{
++	/*
++	 * There is more code here than it seems:
++	 * __dev_alloc_skb is an inline
++	 */
++	return __dev_alloc_skb(length, GFP_ATOMIC);
++}
++EXPORT_SYMBOL(dev_alloc_skb);
++
+ static void skb_drop_list(struct sk_buff **listp)
+ {
+ 	struct sk_buff *list = *listp;
+@@ -857,6 +879,78 @@ free_skb:
+ 	return err;
+ }
+ 
++/**
++ *	skb_put - add data to a buffer
++ *	@skb: buffer to use
++ *	@len: amount of data to add
++ *
++ *	This function extends the used data area of the buffer. If this would
++ *	exceed the total buffer size the kernel will panic. A pointer to the
++ *	first byte of the extra data is returned.
++ */
++unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
++{
++	unsigned char *tmp = skb_tail_pointer(skb);
++	SKB_LINEAR_ASSERT(skb);
++	skb->tail += len;
++	skb->len  += len;
++	if (unlikely(skb->tail > skb->end))
++		skb_over_panic(skb, len, __builtin_return_address(0));
++	return tmp;
++}
++EXPORT_SYMBOL(skb_put);
++
++/**
++ *	skb_push - add data to the start of a buffer
++ *	@skb: buffer to use
++ *	@len: amount of data to add
++ *
++ *	This function extends the used data area of the buffer at the buffer
++ *	start. If this would exceed the total buffer headroom the kernel will
++ *	panic. A pointer to the first byte of the extra data is returned.
++ */
++unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
++{
++	skb->data -= len;
++	skb->len  += len;
++	if (unlikely(skb->data<skb->head))
++		skb_under_panic(skb, len, __builtin_return_address(0));
++	return skb->data;
++}
++EXPORT_SYMBOL(skb_push);
++
++/**
++ *	skb_pull - remove data from the start of a buffer
++ *	@skb: buffer to use
++ *	@len: amount of data to remove
++ *
++ *	This function removes data from the start of a buffer, returning
++ *	the memory to the headroom. A pointer to the next data in the buffer
++ *	is returned. Once the data has been pulled future pushes will overwrite
++ *	the old data.
++ */
++unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
++{
++	return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
++}
++EXPORT_SYMBOL(skb_pull);
++
++/**
++ *	skb_trim - remove end from a buffer
++ *	@skb: buffer to alter
++ *	@len: new length
++ *
++ *	Cut the length of a buffer down by removing data from the tail. If
++ *	the buffer is already under the length specified it is not modified.
++ *	The skb must be linear.
++ */
++void skb_trim(struct sk_buff *skb, unsigned int len)
++{
++	if (skb->len > len)
++		__skb_trim(skb, len);
++}
++EXPORT_SYMBOL(skb_trim);
++
+ /* Trims skb to length len. It can change skb pointers.
+  */
+ 
+@@ -1766,7 +1860,7 @@ void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&list->lock, flags);
+-	__skb_append(old, newsk, list);
++	__skb_queue_after(list, old, newsk);
+ 	spin_unlock_irqrestore(&list->lock, flags);
+ }
+ 
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 7a0567b..5dbb81b 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -372,7 +372,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
+ {
+ 	int ret = -ENOPROTOOPT;
+ #ifdef CONFIG_NETDEVICES
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 	char devname[IFNAMSIZ];
+ 	int index;
+ 
+@@ -450,15 +450,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
+ 	 *	Options without arguments
+ 	 */
+ 
+-#ifdef SO_DONTLINGER		/* Compatibility item... */
+-	if (optname == SO_DONTLINGER) {
+-		lock_sock(sk);
+-		sock_reset_flag(sk, SOCK_LINGER);
+-		release_sock(sk);
+-		return 0;
+-	}
+-#endif
+-
+ 	if (optname == SO_BINDTODEVICE)
+ 		return sock_bindtodevice(sk, optval, optlen);
+ 
+@@ -942,7 +933,6 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
+  *	@family: protocol family
+  *	@priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
+  *	@prot: struct proto associated with this new sock instance
+- *	@zero_it: if we should zero the newly allocated sock
+  */
+ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
+ 		      struct proto *prot)
+@@ -958,7 +948,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
+ 		 */
+ 		sk->sk_prot = sk->sk_prot_creator = prot;
+ 		sock_lock_init(sk);
+-		sk->sk_net = get_net(net);
++		sock_net_set(sk, get_net(net));
+ 	}
+ 
+ 	return sk;
+@@ -981,12 +971,32 @@ void sk_free(struct sock *sk)
+ 
+ 	if (atomic_read(&sk->sk_omem_alloc))
+ 		printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n",
+-		       __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
++		       __func__, atomic_read(&sk->sk_omem_alloc));
+ 
+-	put_net(sk->sk_net);
++	put_net(sock_net(sk));
+ 	sk_prot_free(sk->sk_prot_creator, sk);
+ }
+ 
++/*
++ * Last sock_put should drop referrence to sk->sk_net. It has already
++ * been dropped in sk_change_net. Taking referrence to stopping namespace
++ * is not an option.
++ * Take referrence to a socket to remove it from hash _alive_ and after that
++ * destroy it in the context of init_net.
++ */
++void sk_release_kernel(struct sock *sk)
++{
++	if (sk == NULL || sk->sk_socket == NULL)
++		return;
++
++	sock_hold(sk);
++	sock_release(sk->sk_socket);
++	release_net(sock_net(sk));
++	sock_net_set(sk, get_net(&init_net));
++	sock_put(sk);
++}
++EXPORT_SYMBOL(sk_release_kernel);
++
+ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
+ {
+ 	struct sock *newsk;
+@@ -998,7 +1008,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
+ 		sock_copy(newsk, sk);
+ 
+ 		/* SANITY */
+-		get_net(newsk->sk_net);
++		get_net(sock_net(newsk));
+ 		sk_node_init(&newsk->sk_node);
+ 		sock_lock_init(newsk);
+ 		bh_lock_sock(newsk);
+@@ -1076,10 +1086,12 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
+ 	if (sk->sk_route_caps & NETIF_F_GSO)
+ 		sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
+ 	if (sk_can_gso(sk)) {
+-		if (dst->header_len)
++		if (dst->header_len) {
+ 			sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
+-		else
++		} else {
+ 			sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
++			sk->sk_gso_max_size = dst->dev->gso_max_size;
++		}
+ 	}
+ }
+ EXPORT_SYMBOL_GPL(sk_setup_caps);
+@@ -1919,16 +1931,113 @@ EXPORT_SYMBOL(sk_common_release);
+ static DEFINE_RWLOCK(proto_list_lock);
+ static LIST_HEAD(proto_list);
+ 
++#ifdef CONFIG_PROC_FS
++#define PROTO_INUSE_NR	64	/* should be enough for the first time */
++struct prot_inuse {
++	int val[PROTO_INUSE_NR];
++};
++
++static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR);
++
++#ifdef CONFIG_NET_NS
++void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
++{
++	int cpu = smp_processor_id();
++	per_cpu_ptr(net->core.inuse, cpu)->val[prot->inuse_idx] += val;
++}
++EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
++
++int sock_prot_inuse_get(struct net *net, struct proto *prot)
++{
++	int cpu, idx = prot->inuse_idx;
++	int res = 0;
++
++	for_each_possible_cpu(cpu)
++		res += per_cpu_ptr(net->core.inuse, cpu)->val[idx];
++
++	return res >= 0 ? res : 0;
++}
++EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
++
++static int sock_inuse_init_net(struct net *net)
++{
++	net->core.inuse = alloc_percpu(struct prot_inuse);
++	return net->core.inuse ? 0 : -ENOMEM;
++}
++
++static void sock_inuse_exit_net(struct net *net)
++{
++	free_percpu(net->core.inuse);
++}
++
++static struct pernet_operations net_inuse_ops = {
++	.init = sock_inuse_init_net,
++	.exit = sock_inuse_exit_net,
++};
++
++static __init int net_inuse_init(void)
++{
++	if (register_pernet_subsys(&net_inuse_ops))
++		panic("Cannot initialize net inuse counters");
++
++	return 0;
++}
++
++core_initcall(net_inuse_init);
++#else
++static DEFINE_PER_CPU(struct prot_inuse, prot_inuse);
++
++void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
++{
++	__get_cpu_var(prot_inuse).val[prot->inuse_idx] += val;
++}
++EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
++
++int sock_prot_inuse_get(struct net *net, struct proto *prot)
++{
++	int cpu, idx = prot->inuse_idx;
++	int res = 0;
++
++	for_each_possible_cpu(cpu)
++		res += per_cpu(prot_inuse, cpu).val[idx];
++
++	return res >= 0 ? res : 0;
++}
++EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
++#endif
++
++static void assign_proto_idx(struct proto *prot)
++{
++	prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR);
++
++	if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) {
++		printk(KERN_ERR "PROTO_INUSE_NR exhausted\n");
++		return;
++	}
++
++	set_bit(prot->inuse_idx, proto_inuse_idx);
++}
++
++static void release_proto_idx(struct proto *prot)
++{
++	if (prot->inuse_idx != PROTO_INUSE_NR - 1)
++		clear_bit(prot->inuse_idx, proto_inuse_idx);
++}
++#else
++static inline void assign_proto_idx(struct proto *prot)
++{
++}
++
++static inline void release_proto_idx(struct proto *prot)
++{
++}
++#endif
++
+ int proto_register(struct proto *prot, int alloc_slab)
+ {
+ 	char *request_sock_slab_name = NULL;
+ 	char *timewait_sock_slab_name;
+ 
+-	if (sock_prot_inuse_init(prot) != 0) {
+-		printk(KERN_CRIT "%s: Can't alloc inuse counters!\n", prot->name);
+-		goto out;
+-	}
+-
+ 	if (alloc_slab) {
+ 		prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
+ 					       SLAB_HWCACHE_ALIGN, NULL);
+@@ -1936,7 +2045,7 @@ int proto_register(struct proto *prot, int alloc_slab)
+ 		if (prot->slab == NULL) {
+ 			printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
+ 			       prot->name);
+-			goto out_free_inuse;
++			goto out;
+ 		}
+ 
+ 		if (prot->rsk_prot != NULL) {
+@@ -1979,6 +2088,7 @@ int proto_register(struct proto *prot, int alloc_slab)
+ 
+ 	write_lock(&proto_list_lock);
+ 	list_add(&prot->node, &proto_list);
++	assign_proto_idx(prot);
+ 	write_unlock(&proto_list_lock);
+ 	return 0;
+ 
+@@ -1994,8 +2104,6 @@ out_free_request_sock_slab_name:
+ out_free_sock_slab:
+ 	kmem_cache_destroy(prot->slab);
+ 	prot->slab = NULL;
+-out_free_inuse:
+-	sock_prot_inuse_free(prot);
+ out:
+ 	return -ENOBUFS;
+ }
+@@ -2005,11 +2113,10 @@ EXPORT_SYMBOL(proto_register);
+ void proto_unregister(struct proto *prot)
+ {
+ 	write_lock(&proto_list_lock);
++	release_proto_idx(prot);
+ 	list_del(&prot->node);
+ 	write_unlock(&proto_list_lock);
+ 
+-	sock_prot_inuse_free(prot);
+-
+ 	if (prot->slab != NULL) {
+ 		kmem_cache_destroy(prot->slab);
+ 		prot->slab = NULL;
+diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
+index 130338f..5fc8010 100644
+--- a/net/core/sysctl_net_core.c
++++ b/net/core/sysctl_net_core.c
+@@ -127,7 +127,7 @@ static struct ctl_table net_core_table[] = {
+ 	{
+ 		.ctl_name	= NET_CORE_SOMAXCONN,
+ 		.procname	= "somaxconn",
+-		.data		= &init_net.sysctl_somaxconn,
++		.data		= &init_net.core.sysctl_somaxconn,
+ 		.maxlen		= sizeof(int),
+ 		.mode		= 0644,
+ 		.proc_handler	= &proc_dointvec
+@@ -161,7 +161,7 @@ static __net_init int sysctl_core_net_init(struct net *net)
+ {
+ 	struct ctl_table *tbl, *tmp;
+ 
+-	net->sysctl_somaxconn = SOMAXCONN;
++	net->core.sysctl_somaxconn = SOMAXCONN;
+ 
+ 	tbl = net_core_table;
+ 	if (net != &init_net) {
+@@ -178,9 +178,9 @@ static __net_init int sysctl_core_net_init(struct net *net)
+ 		}
+ 	}
+ 
+-	net->sysctl_core_hdr = register_net_sysctl_table(net,
++	net->core.sysctl_hdr = register_net_sysctl_table(net,
+ 			net_core_path, tbl);
+-	if (net->sysctl_core_hdr == NULL)
++	if (net->core.sysctl_hdr == NULL)
+ 		goto err_reg;
+ 
+ 	return 0;
+@@ -196,8 +196,8 @@ static __net_exit void sysctl_core_net_exit(struct net *net)
+ {
+ 	struct ctl_table *tbl;
+ 
+-	tbl = net->sysctl_core_hdr->ctl_table_arg;
+-	unregister_net_sysctl_table(net->sysctl_core_hdr);
++	tbl = net->core.sysctl_hdr->ctl_table_arg;
++	unregister_net_sysctl_table(net->core.sysctl_hdr);
+ 	BUG_ON(tbl == net_core_table);
+ 	kfree(tbl);
+ }
+diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
+index ba2ef94..f44d492 100644
+--- a/net/dccp/dccp.h
++++ b/net/dccp/dccp.h
+@@ -23,9 +23,9 @@
+  * 	DCCP - specific warning and debugging macros.
+  */
+ #define DCCP_WARN(fmt, a...) LIMIT_NETDEBUG(KERN_WARNING "%s: " fmt,       \
+-							__FUNCTION__, ##a)
++							__func__, ##a)
+ #define DCCP_CRIT(fmt, a...) printk(KERN_CRIT fmt " at %s:%d/%s()\n", ##a, \
+-					 __FILE__, __LINE__, __FUNCTION__)
++					 __FILE__, __LINE__, __func__)
+ #define DCCP_BUG(a...)       do { DCCP_CRIT("BUG: " a); dump_stack(); } while(0)
+ #define DCCP_BUG_ON(cond)    do { if (unlikely((cond) != 0))		   \
+ 				     DCCP_BUG("\"%s\" holds (exception!)", \
+@@ -36,7 +36,7 @@
+ 							printk(fmt, ##args); \
+ 						} while(0)
+ #define DCCP_PR_DEBUG(enable, fmt, a...)	DCCP_PRINTK(enable, KERN_DEBUG \
+-						  "%s: " fmt, __FUNCTION__, ##a)
++						  "%s: " fmt, __func__, ##a)
+ 
+ #ifdef CONFIG_IP_DCCP_DEBUG
+ extern int dccp_debug;
+@@ -296,7 +296,7 @@ extern unsigned int dccp_poll(struct file *file, struct socket *sock,
+ extern int	   dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
+ 				   int addr_len);
+ 
+-extern struct sk_buff *dccp_ctl_make_reset(struct socket *ctl,
++extern struct sk_buff *dccp_ctl_make_reset(struct sock *sk,
+ 					   struct sk_buff *skb);
+ extern int	   dccp_send_reset(struct sock *sk, enum dccp_reset_codes code);
+ extern void	   dccp_send_close(struct sock *sk, const int active);
+diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
+index b337044..b348dd7 100644
+--- a/net/dccp/ipv4.c
++++ b/net/dccp/ipv4.c
+@@ -32,11 +32,10 @@
+ #include "feat.h"
+ 
+ /*
+- * This is the global socket data structure used for responding to
++ * The per-net dccp.v4_ctl_sk socket is used for responding to
+  * the Out-of-the-blue (OOTB) packets. A control sock will be created
+  * for this socket at the initialization time.
+  */
+-static struct socket *dccp_v4_ctl_socket;
+ 
+ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+ {
+@@ -212,8 +211,9 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
+ 		return;
+ 	}
+ 
+-	sk = inet_lookup(&init_net, &dccp_hashinfo, iph->daddr, dh->dccph_dport,
+-			 iph->saddr, dh->dccph_sport, inet_iif(skb));
++	sk = inet_lookup(dev_net(skb->dev), &dccp_hashinfo,
++			iph->daddr, dh->dccph_dport,
++			iph->saddr, dh->dccph_sport, inet_iif(skb));
+ 	if (sk == NULL) {
+ 		ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+ 		return;
+@@ -430,7 +430,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
+ 	if (req != NULL)
+ 		return dccp_check_req(sk, skb, req, prev);
+ 
+-	nsk = inet_lookup_established(&init_net, &dccp_hashinfo,
++	nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo,
+ 				      iph->saddr, dh->dccph_sport,
+ 				      iph->daddr, dh->dccph_dport,
+ 				      inet_iif(skb));
+@@ -446,11 +446,11 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
+ 	return sk;
+ }
+ 
+-static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
++static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
+ 					   struct sk_buff *skb)
+ {
+ 	struct rtable *rt;
+-	struct flowi fl = { .oif = ((struct rtable *)skb->dst)->rt_iif,
++	struct flowi fl = { .oif = skb->rtable->rt_iif,
+ 			    .nl_u = { .ip4_u =
+ 				      { .daddr = ip_hdr(skb)->saddr,
+ 					.saddr = ip_hdr(skb)->daddr,
+@@ -463,7 +463,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
+ 			  };
+ 
+ 	security_skb_classify_flow(skb, &fl);
+-	if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0)) {
++	if (ip_route_output_flow(net, &rt, &fl, sk, 0)) {
+ 		IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+ 		return NULL;
+ 	}
+@@ -471,15 +471,14 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
+ 	return &rt->u.dst;
+ }
+ 
+-static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
+-				 struct dst_entry *dst)
++static int dccp_v4_send_response(struct sock *sk, struct request_sock *req)
+ {
+ 	int err = -1;
+ 	struct sk_buff *skb;
++	struct dst_entry *dst;
+ 
+-	/* First, grab a route. */
+-
+-	if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL)
++	dst = inet_csk_route_req(sk, req);
++	if (dst == NULL)
+ 		goto out;
+ 
+ 	skb = dccp_make_response(sk, dst, req);
+@@ -506,19 +505,21 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ 	const struct iphdr *rxiph;
+ 	struct sk_buff *skb;
+ 	struct dst_entry *dst;
++	struct net *net = dev_net(rxskb->dst->dev);
++	struct sock *ctl_sk = net->dccp.v4_ctl_sk;
+ 
+ 	/* Never send a reset in response to a reset. */
+ 	if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
+ 		return;
+ 
+-	if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
++	if (rxskb->rtable->rt_type != RTN_LOCAL)
+ 		return;
+ 
+-	dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb);
++	dst = dccp_v4_route_skb(net, ctl_sk, rxskb);
+ 	if (dst == NULL)
+ 		return;
+ 
+-	skb = dccp_ctl_make_reset(dccp_v4_ctl_socket, rxskb);
++	skb = dccp_ctl_make_reset(ctl_sk, rxskb);
+ 	if (skb == NULL)
+ 		goto out;
+ 
+@@ -527,10 +528,10 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ 								 rxiph->daddr);
+ 	skb->dst = dst_clone(dst);
+ 
+-	bh_lock_sock(dccp_v4_ctl_socket->sk);
+-	err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
++	bh_lock_sock(ctl_sk);
++	err = ip_build_and_send_pkt(skb, ctl_sk,
+ 				    rxiph->daddr, rxiph->saddr, NULL);
+-	bh_unlock_sock(dccp_v4_ctl_socket->sk);
++	bh_unlock_sock(ctl_sk);
+ 
+ 	if (net_xmit_eval(err) == 0) {
+ 		DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
+@@ -563,8 +564,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ 	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
+ 
+ 	/* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
+-	if (((struct rtable *)skb->dst)->rt_flags &
+-	    (RTCF_BROADCAST | RTCF_MULTICAST))
++	if (skb->rtable->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
+ 		return 0;	/* discard, don't send a reset here */
+ 
+ 	if (dccp_bad_service_code(sk, service)) {
+@@ -619,7 +619,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ 	dreq->dreq_iss	   = dccp_v4_init_sequence(skb);
+ 	dreq->dreq_service = service;
+ 
+-	if (dccp_v4_send_response(sk, req, NULL))
++	if (dccp_v4_send_response(sk, req))
+ 		goto drop_and_free;
+ 
+ 	inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
+@@ -810,7 +810,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
+ 
+ 	/* Step 2:
+ 	 *	Look up flow ID in table and get corresponding socket */
+-	sk = __inet_lookup(&init_net, &dccp_hashinfo,
++	sk = __inet_lookup(dev_net(skb->dst->dev), &dccp_hashinfo,
+ 			   iph->saddr, dh->dccph_sport,
+ 			   iph->daddr, dh->dccph_dport, inet_iif(skb));
+ 	/*
+@@ -916,8 +916,6 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = {
+ 	.twsk_obj_size	= sizeof(struct inet_timewait_sock),
+ };
+ 
+-DEFINE_PROTO_INUSE(dccp_v4)
+-
+ static struct proto dccp_v4_prot = {
+ 	.name			= "DCCP",
+ 	.owner			= THIS_MODULE,
+@@ -942,18 +940,18 @@ static struct proto dccp_v4_prot = {
+ 	.obj_size		= sizeof(struct dccp_sock),
+ 	.rsk_prot		= &dccp_request_sock_ops,
+ 	.twsk_prot		= &dccp_timewait_sock_ops,
+-	.hashinfo		= &dccp_hashinfo,
++	.h.hashinfo		= &dccp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt	= compat_dccp_setsockopt,
+ 	.compat_getsockopt	= compat_dccp_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(dccp_v4)
+ };
+ 
+ static struct net_protocol dccp_v4_protocol = {
+ 	.handler	= dccp_v4_rcv,
+ 	.err_handler	= dccp_v4_err,
+ 	.no_policy	= 1,
++	.netns_ok	= 1,
+ };
+ 
+ static const struct proto_ops inet_dccp_ops = {
+@@ -993,6 +991,25 @@ static struct inet_protosw dccp_v4_protosw = {
+ 	.flags		= INET_PROTOSW_ICSK,
+ };
+ 
++static int dccp_v4_init_net(struct net *net)
++{
++	int err;
++
++	err = inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET,
++				   SOCK_DCCP, IPPROTO_DCCP, net);
++	return err;
++}
++
++static void dccp_v4_exit_net(struct net *net)
++{
++	inet_ctl_sock_destroy(net->dccp.v4_ctl_sk);
++}
++
++static struct pernet_operations dccp_v4_ops = {
++	.init	= dccp_v4_init_net,
++	.exit	= dccp_v4_exit_net,
++};
++
+ static int __init dccp_v4_init(void)
+ {
+ 	int err = proto_register(&dccp_v4_prot, 1);
+@@ -1006,13 +1023,12 @@ static int __init dccp_v4_init(void)
+ 
+ 	inet_register_protosw(&dccp_v4_protosw);
+ 
+-	err = inet_csk_ctl_sock_create(&dccp_v4_ctl_socket, PF_INET,
+-				       SOCK_DCCP, IPPROTO_DCCP);
++	err = register_pernet_subsys(&dccp_v4_ops);
+ 	if (err)
+-		goto out_unregister_protosw;
++		goto out_destroy_ctl_sock;
+ out:
+ 	return err;
+-out_unregister_protosw:
++out_destroy_ctl_sock:
+ 	inet_unregister_protosw(&dccp_v4_protosw);
+ 	inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
+ out_proto_unregister:
+@@ -1022,6 +1038,7 @@ out_proto_unregister:
+ 
+ static void __exit dccp_v4_exit(void)
+ {
++	unregister_pernet_subsys(&dccp_v4_ops);
+ 	inet_unregister_protosw(&dccp_v4_protosw);
+ 	inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
+ 	proto_unregister(&dccp_v4_prot);
+diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
+index 490333d..9b1129b 100644
+--- a/net/dccp/ipv6.c
++++ b/net/dccp/ipv6.c
+@@ -33,8 +33,7 @@
+ #include "ipv6.h"
+ #include "feat.h"
+ 
+-/* Socket used for sending RSTs and ACKs */
+-static struct socket *dccp_v6_ctl_socket;
++/* The per-net dccp.v6_ctl_sk is used for sending RSTs and ACKs */
+ 
+ static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
+ static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
+@@ -95,7 +94,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ 	int err;
+ 	__u64 seq;
+ 
+-	sk = inet6_lookup(&init_net, &dccp_hashinfo, &hdr->daddr, dh->dccph_dport,
++	sk = inet6_lookup(dev_net(skb->dev), &dccp_hashinfo,
++			&hdr->daddr, dh->dccph_dport,
+ 			&hdr->saddr, dh->dccph_sport, inet6_iif(skb));
+ 
+ 	if (sk == NULL) {
+@@ -224,8 +224,7 @@ out:
+ }
+ 
+ 
+-static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
+-				 struct dst_entry *dst)
++static int dccp_v6_send_response(struct sock *sk, struct request_sock *req)
+ {
+ 	struct inet6_request_sock *ireq6 = inet6_rsk(req);
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+@@ -234,6 +233,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
+ 	struct in6_addr *final_p = NULL, final;
+ 	struct flowi fl;
+ 	int err = -1;
++	struct dst_entry *dst;
+ 
+ 	memset(&fl, 0, sizeof(fl));
+ 	fl.proto = IPPROTO_DCCP;
+@@ -245,28 +245,26 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
+ 	fl.fl_ip_sport = inet_sk(sk)->sport;
+ 	security_req_classify_flow(req, &fl);
+ 
+-	if (dst == NULL) {
+-		opt = np->opt;
++	opt = np->opt;
+ 
+-		if (opt != NULL && opt->srcrt != NULL) {
+-			const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
++	if (opt != NULL && opt->srcrt != NULL) {
++		const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
+ 
+-			ipv6_addr_copy(&final, &fl.fl6_dst);
+-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+-			final_p = &final;
+-		}
++		ipv6_addr_copy(&final, &fl.fl6_dst);
++		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
++		final_p = &final;
++	}
+ 
+-		err = ip6_dst_lookup(sk, &dst, &fl);
+-		if (err)
+-			goto done;
++	err = ip6_dst_lookup(sk, &dst, &fl);
++	if (err)
++		goto done;
+ 
+-		if (final_p)
+-			ipv6_addr_copy(&fl.fl6_dst, final_p);
++	if (final_p)
++		ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-		err = xfrm_lookup(&dst, &fl, sk, 0);
+-		if (err < 0)
+-			goto done;
+-	}
++	err = xfrm_lookup(&dst, &fl, sk, 0);
++	if (err < 0)
++		goto done;
+ 
+ 	skb = dccp_make_response(sk, dst, req);
+ 	if (skb != NULL) {
+@@ -298,6 +296,8 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ 	struct ipv6hdr *rxip6h;
+ 	struct sk_buff *skb;
+ 	struct flowi fl;
++	struct net *net = dev_net(rxskb->dst->dev);
++	struct sock *ctl_sk = net->dccp.v6_ctl_sk;
+ 
+ 	if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
+ 		return;
+@@ -305,7 +305,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ 	if (!ipv6_unicast_destination(rxskb))
+ 		return;
+ 
+-	skb = dccp_ctl_make_reset(dccp_v6_ctl_socket, rxskb);
++	skb = dccp_ctl_make_reset(ctl_sk, rxskb);
+ 	if (skb == NULL)
+ 		return;
+ 
+@@ -324,9 +324,9 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ 	security_skb_classify_flow(rxskb, &fl);
+ 
+ 	/* sk = NULL, but it is safe for now. RST socket required. */
+-	if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
++	if (!ip6_dst_lookup(ctl_sk, &skb->dst, &fl)) {
+ 		if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
+-			ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
++			ip6_xmit(ctl_sk, skb, &fl, NULL, 0);
+ 			DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
+ 			DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
+ 			return;
+@@ -360,7 +360,7 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+ 	if (req != NULL)
+ 		return dccp_check_req(sk, skb, req, prev);
+ 
+-	nsk = __inet6_lookup_established(&init_net, &dccp_hashinfo,
++	nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo,
+ 					 &iph->saddr, dh->dccph_sport,
+ 					 &iph->daddr, ntohs(dh->dccph_dport),
+ 					 inet6_iif(skb));
+@@ -448,7 +448,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+ 	dreq->dreq_iss	   = dccp_v6_init_sequence(skb);
+ 	dreq->dreq_service = service;
+ 
+-	if (dccp_v6_send_response(sk, req, NULL))
++	if (dccp_v6_send_response(sk, req))
+ 		goto drop_and_free;
+ 
+ 	inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
+@@ -625,7 +625,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
+ 	newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
+ 
+ 	__inet6_hash(newsk);
+-	inet_inherit_port(sk, newsk);
++	__inet_inherit_port(sk, newsk);
+ 
+ 	return newsk;
+ 
+@@ -791,8 +791,8 @@ static int dccp_v6_rcv(struct sk_buff *skb)
+ 
+ 	/* Step 2:
+ 	 *	Look up flow ID in table and get corresponding socket */
+-	sk = __inet6_lookup(&init_net, &dccp_hashinfo, &ipv6_hdr(skb)->saddr,
+-			    dh->dccph_sport,
++	sk = __inet6_lookup(dev_net(skb->dst->dev), &dccp_hashinfo,
++			    &ipv6_hdr(skb)->saddr, dh->dccph_sport,
+ 			    &ipv6_hdr(skb)->daddr, ntohs(dh->dccph_dport),
+ 			    inet6_iif(skb));
+ 	/*
+@@ -1102,8 +1102,6 @@ static struct timewait_sock_ops dccp6_timewait_sock_ops = {
+ 	.twsk_obj_size	= sizeof(struct dccp6_timewait_sock),
+ };
+ 
+-DEFINE_PROTO_INUSE(dccp_v6)
+-
+ static struct proto dccp_v6_prot = {
+ 	.name		   = "DCCPv6",
+ 	.owner		   = THIS_MODULE,
+@@ -1128,12 +1126,11 @@ static struct proto dccp_v6_prot = {
+ 	.obj_size	   = sizeof(struct dccp6_sock),
+ 	.rsk_prot	   = &dccp6_request_sock_ops,
+ 	.twsk_prot	   = &dccp6_timewait_sock_ops,
+-	.hashinfo	   = &dccp_hashinfo,
++	.h.hashinfo	   = &dccp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_dccp_setsockopt,
+ 	.compat_getsockopt = compat_dccp_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(dccp_v6)
+ };
+ 
+ static struct inet6_protocol dccp_v6_protocol = {
+@@ -1176,6 +1173,25 @@ static struct inet_protosw dccp_v6_protosw = {
+ 	.flags		= INET_PROTOSW_ICSK,
+ };
+ 
++static int dccp_v6_init_net(struct net *net)
++{
++	int err;
++
++	err = inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6,
++				   SOCK_DCCP, IPPROTO_DCCP, net);
++	return err;
++}
++
++static void dccp_v6_exit_net(struct net *net)
++{
++	inet_ctl_sock_destroy(net->dccp.v6_ctl_sk);
++}
++
++static struct pernet_operations dccp_v6_ops = {
++	.init   = dccp_v6_init_net,
++	.exit   = dccp_v6_exit_net,
++};
++
+ static int __init dccp_v6_init(void)
+ {
+ 	int err = proto_register(&dccp_v6_prot, 1);
+@@ -1189,13 +1205,13 @@ static int __init dccp_v6_init(void)
+ 
+ 	inet6_register_protosw(&dccp_v6_protosw);
+ 
+-	err = inet_csk_ctl_sock_create(&dccp_v6_ctl_socket, PF_INET6,
+-				       SOCK_DCCP, IPPROTO_DCCP);
++	err = register_pernet_subsys(&dccp_v6_ops);
+ 	if (err != 0)
+-		goto out_unregister_protosw;
++		goto out_destroy_ctl_sock;
+ out:
+ 	return err;
+-out_unregister_protosw:
++
++out_destroy_ctl_sock:
+ 	inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
+ 	inet6_unregister_protosw(&dccp_v6_protosw);
+ out_unregister_proto:
+@@ -1205,6 +1221,7 @@ out_unregister_proto:
+ 
+ static void __exit dccp_v6_exit(void)
+ {
++	unregister_pernet_subsys(&dccp_v6_ops);
+ 	inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
+ 	inet6_unregister_protosw(&dccp_v6_protosw);
+ 	proto_unregister(&dccp_v6_prot);
+diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
+index 027d181..33ad483 100644
+--- a/net/dccp/minisocks.c
++++ b/net/dccp/minisocks.c
+@@ -216,7 +216,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
+ 			 * counter (backoff, monitored by dccp_response_timer).
+ 			 */
+ 			req->retrans++;
+-			req->rsk_ops->rtx_syn_ack(sk, req, NULL);
++			req->rsk_ops->rtx_syn_ack(sk, req);
+ 		}
+ 		/* Network Duplicate, discard packet */
+ 		return NULL;
+diff --git a/net/dccp/output.c b/net/dccp/output.c
+index 3d7d628..1f8a9b6 100644
+--- a/net/dccp/output.c
++++ b/net/dccp/output.c
+@@ -347,7 +347,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
+ EXPORT_SYMBOL_GPL(dccp_make_response);
+ 
+ /* answer offending packet in @rcv_skb with Reset from control socket @ctl */
+-struct sk_buff *dccp_ctl_make_reset(struct socket *ctl, struct sk_buff *rcv_skb)
++struct sk_buff *dccp_ctl_make_reset(struct sock *sk, struct sk_buff *rcv_skb)
+ {
+ 	struct dccp_hdr *rxdh = dccp_hdr(rcv_skb), *dh;
+ 	struct dccp_skb_cb *dcb = DCCP_SKB_CB(rcv_skb);
+@@ -357,11 +357,11 @@ struct sk_buff *dccp_ctl_make_reset(struct socket *ctl, struct sk_buff *rcv_skb)
+ 	struct dccp_hdr_reset *dhr;
+ 	struct sk_buff *skb;
+ 
+-	skb = alloc_skb(ctl->sk->sk_prot->max_header, GFP_ATOMIC);
++	skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC);
+ 	if (skb == NULL)
+ 		return NULL;
+ 
+-	skb_reserve(skb, ctl->sk->sk_prot->max_header);
++	skb_reserve(skb, sk->sk_prot->max_header);
+ 
+ 	/* Swap the send and the receive. */
+ 	dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len);
+diff --git a/net/dccp/probe.c b/net/dccp/probe.c
+index 7053bb8..0bcdc92 100644
+--- a/net/dccp/probe.c
++++ b/net/dccp/probe.c
+@@ -46,29 +46,24 @@ struct {
+ 	struct kfifo	  *fifo;
+ 	spinlock_t	  lock;
+ 	wait_queue_head_t wait;
+-	struct timeval	  tstart;
++	struct timespec	  tstart;
+ } dccpw;
+ 
+ static void printl(const char *fmt, ...)
+ {
+ 	va_list args;
+ 	int len;
+-	struct timeval now;
++	struct timespec now;
+ 	char tbuf[256];
+ 
+ 	va_start(args, fmt);
+-	do_gettimeofday(&now);
++	getnstimeofday(&now);
+ 
+-	now.tv_sec -= dccpw.tstart.tv_sec;
+-	now.tv_usec -= dccpw.tstart.tv_usec;
+-	if (now.tv_usec < 0) {
+-		--now.tv_sec;
+-		now.tv_usec += 1000000;
+-	}
++	now = timespec_sub(now, dccpw.tstart);
+ 
+ 	len = sprintf(tbuf, "%lu.%06lu ",
+ 		      (unsigned long) now.tv_sec,
+-		      (unsigned long) now.tv_usec);
++		      (unsigned long) now.tv_nsec / NSEC_PER_USEC);
+ 	len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
+ 	va_end(args);
+ 
+@@ -119,7 +114,7 @@ static struct jprobe dccp_send_probe = {
+ static int dccpprobe_open(struct inode *inode, struct file *file)
+ {
+ 	kfifo_reset(dccpw.fifo);
+-	do_gettimeofday(&dccpw.tstart);
++	getnstimeofday(&dccpw.tstart);
+ 	return 0;
+ }
+ 
+@@ -145,7 +140,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf,
+ 		goto out_free;
+ 
+ 	cnt = kfifo_get(dccpw.fifo, tbuf, len);
+-	error = copy_to_user(buf, tbuf, cnt);
++	error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0;
+ 
+ out_free:
+ 	vfree(tbuf);
+diff --git a/net/dccp/proto.c b/net/dccp/proto.c
+index c91d3c1..9dfe247 100644
+--- a/net/dccp/proto.c
++++ b/net/dccp/proto.c
+@@ -27,7 +27,6 @@
+ #include <net/xfrm.h>
+ 
+ #include <asm/ioctls.h>
+-#include <asm/semaphore.h>
+ #include <linux/spinlock.h>
+ #include <linux/timer.h>
+ #include <linux/delay.h>
+@@ -1010,33 +1009,14 @@ void dccp_shutdown(struct sock *sk, int how)
+ 
+ EXPORT_SYMBOL_GPL(dccp_shutdown);
+ 
+-static int __init dccp_mib_init(void)
++static inline int dccp_mib_init(void)
+ {
+-	int rc = -ENOMEM;
+-
+-	dccp_statistics[0] = alloc_percpu(struct dccp_mib);
+-	if (dccp_statistics[0] == NULL)
+-		goto out;
+-
+-	dccp_statistics[1] = alloc_percpu(struct dccp_mib);
+-	if (dccp_statistics[1] == NULL)
+-		goto out_free_one;
+-
+-	rc = 0;
+-out:
+-	return rc;
+-out_free_one:
+-	free_percpu(dccp_statistics[0]);
+-	dccp_statistics[0] = NULL;
+-	goto out;
+-
++	return snmp_mib_init((void**)dccp_statistics, sizeof(struct dccp_mib));
+ }
+ 
+-static void dccp_mib_exit(void)
++static inline void dccp_mib_exit(void)
+ {
+-	free_percpu(dccp_statistics[0]);
+-	free_percpu(dccp_statistics[1]);
+-	dccp_statistics[0] = dccp_statistics[1] = NULL;
++	snmp_mib_free((void**)dccp_statistics);
+ }
+ 
+ static int thash_entries;
+diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
+index acd48ee..fc2efe8 100644
+--- a/net/decnet/af_decnet.c
++++ b/net/decnet/af_decnet.c
+@@ -1094,7 +1094,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
+ 
+ 	cb = DN_SKB_CB(skb);
+ 	sk->sk_ack_backlog--;
+-	newsk = dn_alloc_sock(sk->sk_net, newsock, sk->sk_allocation);
++	newsk = dn_alloc_sock(sock_net(sk), newsock, sk->sk_allocation);
+ 	if (newsk == NULL) {
+ 		release_sock(sk);
+ 		kfree_skb(skb);
+@@ -2089,7 +2089,7 @@ static int dn_device_event(struct notifier_block *this, unsigned long event,
+ {
+ 	struct net_device *dev = (struct net_device *)ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	switch(event) {
+@@ -2320,25 +2320,8 @@ static const struct seq_operations dn_socket_seq_ops = {
+ 
+ static int dn_socket_seq_open(struct inode *inode, struct file *file)
+ {
+-	struct seq_file *seq;
+-	int rc = -ENOMEM;
+-	struct dn_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+-
+-	if (!s)
+-		goto out;
+-
+-	rc = seq_open(file, &dn_socket_seq_ops);
+-	if (rc)
+-		goto out_kfree;
+-
+-	seq		= file->private_data;
+-	seq->private	= s;
+-	memset(s, 0, sizeof(*s));
+-out:
+-	return rc;
+-out_kfree:
+-	kfree(s);
+-	goto out;
++	return seq_open_private(file, &dn_socket_seq_ops,
++			sizeof(struct dn_iter_state));
+ }
+ 
+ static const struct file_operations dn_socket_seq_fops = {
+diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
+index 1bbfce5..2f0ac3c 100644
+--- a/net/decnet/dn_dev.c
++++ b/net/decnet/dn_dev.c
+@@ -625,7 +625,7 @@ static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
+ 
+ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct nlattr *tb[IFA_MAX+1];
+ 	struct dn_dev *dn_db;
+ 	struct ifaddrmsg *ifm;
+@@ -663,7 +663,7 @@ errout:
+ 
+ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct nlattr *tb[IFA_MAX+1];
+ 	struct net_device *dev;
+ 	struct dn_dev *dn_db;
+@@ -779,7 +779,7 @@ errout:
+ 
+ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	int idx, dn_idx = 0, skip_ndevs, skip_naddr;
+ 	struct net_device *dev;
+ 	struct dn_dev *dn_db;
+diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
+index 4aa9a42..27ea2e9 100644
+--- a/net/decnet/dn_fib.c
++++ b/net/decnet/dn_fib.c
+@@ -504,7 +504,7 @@ static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
+ 
+ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct dn_fib_table *tb;
+ 	struct rtattr **rta = arg;
+ 	struct rtmsg *r = NLMSG_DATA(nlh);
+@@ -524,7 +524,7 @@ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *
+ 
+ static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct dn_fib_table *tb;
+ 	struct rtattr **rta = arg;
+ 	struct rtmsg *r = NLMSG_DATA(nlh);
+diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
+index 9dc0abb..2f665a5 100644
+--- a/net/decnet/dn_route.c
++++ b/net/decnet/dn_route.c
+@@ -580,7 +580,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
+ 	struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
+ 	unsigned char padlen = 0;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto dump_it;
+ 
+ 	if (dn == NULL)
+@@ -1512,7 +1512,7 @@ rtattr_failure:
+  */
+ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = in_skb->sk->sk_net;
++	struct net *net = sock_net(in_skb->sk);
+ 	struct rtattr **rta = arg;
+ 	struct rtmsg *rtm = NLMSG_DATA(nlh);
+ 	struct dn_route *rt = NULL;
+@@ -1601,7 +1601,7 @@ out_free:
+  */
+ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct dn_route *rt;
+ 	int h, s_h;
+ 	int idx, s_idx;
+diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
+index e09d915..3a2830a 100644
+--- a/net/decnet/dn_table.c
++++ b/net/decnet/dn_table.c
+@@ -463,7 +463,7 @@ static int dn_fib_table_dump(struct dn_fib_table *tb, struct sk_buff *skb,
+ 
+ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	unsigned int h, s_h;
+ 	unsigned int e = 0, s_e;
+ 	struct dn_fib_table *tb;
+diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
+index bc0f625..68d1544 100644
+--- a/net/econet/af_econet.c
++++ b/net/econet/af_econet.c
+@@ -1064,7 +1064,7 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
+ 	struct sock *sk;
+ 	struct ec_device *edev = dev->ec_ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto drop;
+ 
+ 	if (skb->pkt_type == PACKET_OTHERHOST)
+@@ -1121,7 +1121,7 @@ static int econet_notifier(struct notifier_block *this, unsigned long msg, void
+ 	struct net_device *dev = (struct net_device *)data;
+ 	struct ec_device *edev;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	switch (msg) {
+diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
+index bd50104..94ed7d3 100644
+--- a/net/ieee80211/Kconfig
++++ b/net/ieee80211/Kconfig
+@@ -71,4 +71,3 @@ config IEEE80211_CRYPT_TKIP
+ 	This can be compiled as a module and it will be called
+ 	"ieee80211_crypt_tkip".
+ 
+-source "net/ieee80211/softmac/Kconfig"
+diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile
+index 796a7c7..f988417 100644
+--- a/net/ieee80211/Makefile
++++ b/net/ieee80211/Makefile
+@@ -10,4 +10,3 @@ ieee80211-objs := \
+ 	ieee80211_wx.o \
+ 	ieee80211_geo.o
+ 
+-obj-$(CONFIG_IEEE80211_SOFTMAC) += softmac/
+diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
+deleted file mode 100644
+index 2811651..0000000
+--- a/net/ieee80211/softmac/Kconfig
++++ /dev/null
+@@ -1,12 +0,0 @@
+-config IEEE80211_SOFTMAC
+-	tristate "Software MAC add-on to the IEEE 802.11 networking stack"
+-	depends on IEEE80211 && EXPERIMENTAL
+-	select WIRELESS_EXT
+-	select IEEE80211_CRYPT_WEP
+-	---help---
+-	This option enables the hardware independent software MAC addon
+-	for the IEEE 802.11 networking stack.
+-
+-config IEEE80211_SOFTMAC_DEBUG
+-	bool "Enable full debugging output"
+-	depends on IEEE80211_SOFTMAC
+diff --git a/net/ieee80211/softmac/Makefile b/net/ieee80211/softmac/Makefile
+deleted file mode 100644
+index bfcb391..0000000
+--- a/net/ieee80211/softmac/Makefile
++++ /dev/null
+@@ -1,9 +0,0 @@
+-obj-$(CONFIG_IEEE80211_SOFTMAC) += ieee80211softmac.o
+-ieee80211softmac-objs := \
+-			ieee80211softmac_io.o \
+-			ieee80211softmac_auth.o \
+-			ieee80211softmac_module.o \
+-			ieee80211softmac_scan.o \
+-			ieee80211softmac_wx.o \
+-			ieee80211softmac_assoc.o \
+-			ieee80211softmac_event.o
+diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
+deleted file mode 100644
+index c4d122d..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
++++ /dev/null
+@@ -1,489 +0,0 @@
+-/*
+- * This file contains the softmac's association logic.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- *                          Joseph Jezak <josejx at gentoo.org>
+- *                          Larry Finger <Larry.Finger at lwfinger.net>
+- *                          Danny van Dyk <kugelfang at gentoo.org>
+- *                          Michael Buesch <mbuesch at freenet.de>
+- *
+- * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-/*
+- * Overview
+- *
+- * Before you can associate, you have to authenticate.
+- *
+- */
+-
+-/* Sends out an association request to the desired AP */
+-static void
+-ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
+-{
+-	unsigned long flags;
+-
+-	/* Switch to correct channel for this network */
+-	mac->set_channel(mac->dev, net->channel);
+-
+-	/* Send association request */
+-	ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_ASSOC_REQ, 0);
+-
+-	dprintk(KERN_INFO PFX "sent association request!\n");
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-	mac->associnfo.associated = 0; /* just to make sure */
+-
+-	/* Set a timer for timeout */
+-	/* FIXME: make timeout configurable */
+-	if (likely(mac->running))
+-		queue_delayed_work(mac->wq, &mac->associnfo.timeout, 5 * HZ);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-void
+-ieee80211softmac_assoc_timeout(struct work_struct *work)
+-{
+-	struct ieee80211softmac_device *mac =
+-		container_of(work, struct ieee80211softmac_device,
+-			     associnfo.timeout.work);
+-	struct ieee80211softmac_network *n;
+-
+-	mutex_lock(&mac->associnfo.mutex);
+-	/* we might race against ieee80211softmac_handle_assoc_response,
+-	 * so make sure only one of us does something */
+-	if (!mac->associnfo.associating)
+-		goto out;
+-	mac->associnfo.associating = 0;
+-	mac->associnfo.bssvalid = 0;
+-	mac->associnfo.associated = 0;
+-
+-	n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
+-
+-	dprintk(KERN_INFO PFX "assoc request timed out!\n");
+-	ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
+-out:
+-	mutex_unlock(&mac->associnfo.mutex);
+-}
+-
+-void
+-ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-	if (mac->associnfo.associating)
+-		cancel_delayed_work(&mac->associnfo.timeout);
+-
+-	netif_carrier_off(mac->dev);
+-
+-	mac->associnfo.associated = 0;
+-	mac->associnfo.bssvalid = 0;
+-	mac->associnfo.associating = 0;
+-	ieee80211softmac_init_bss(mac);
+-	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-/* Sends out a disassociation request to the desired AP */
+-void
+-ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason)
+-{
+-	struct ieee80211softmac_network *found;
+-
+-	if (mac->associnfo.bssvalid && mac->associnfo.associated) {
+-		found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
+-		if (found)
+-			ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
+-	}
+-
+-	ieee80211softmac_disassoc(mac);
+-}
+-
+-static inline int
+-we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
+-{
+-	int idx;
+-	u8 rate;
+-
+-	for (idx = 0; idx < (from_len); idx++) {
+-		rate = (from)[idx];
+-		if (!(rate & IEEE80211_BASIC_RATE_MASK))
+-			continue;
+-		rate &= ~IEEE80211_BASIC_RATE_MASK;
+-		if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
+-			return 0;
+-	}
+-	return 1;
+-}
+-
+-static int
+-network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_network *net)
+-{
+-	/* we cannot associate to networks whose name we don't know */
+-	if (ieee80211_is_empty_essid(net->ssid, net->ssid_len))
+-		return 0;
+-	/* do not associate to a network whose BSSBasicRateSet we cannot support */
+-	if (!we_support_all_basic_rates(mac, net->rates, net->rates_len))
+-		return 0;
+-	/* do we really need to check the ex rates? */
+-	if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
+-		return 0;
+-
+-	/* assume that users know what they're doing ...
+-	 * (note we don't let them select a net we're incompatible with) */
+-	if (mac->associnfo.bssfixed) {
+-		return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN);
+-	}
+-
+-	/* if 'ANY' network requested, take any that doesn't have privacy enabled */
+-	if (mac->associnfo.req_essid.len == 0
+-	    && !(net->capability & WLAN_CAPABILITY_PRIVACY))
+-		return 1;
+-	if (net->ssid_len != mac->associnfo.req_essid.len)
+-		return 0;
+-	if (!memcmp(net->ssid, mac->associnfo.req_essid.data, mac->associnfo.req_essid.len))
+-		return 1;
+-	return 0;
+-}
+-
+-static void
+-ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	ieee80211softmac_assoc_work(&mac->associnfo.work.work);
+-}
+-
+-static void
+-ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+-	switch (event_type) {
+-	case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
+-		ieee80211softmac_assoc_work(&mac->associnfo.work.work);
+-		break;
+-	case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
+-	case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
+-		ieee80211softmac_disassoc(mac);
+-		break;
+-	}
+-}
+-
+-/* This function is called to handle userspace requests (asynchronously) */
+-void
+-ieee80211softmac_assoc_work(struct work_struct *work)
+-{
+-	struct ieee80211softmac_device *mac =
+-		container_of(work, struct ieee80211softmac_device,
+-			     associnfo.work.work);
+-	struct ieee80211softmac_network *found = NULL;
+-	struct ieee80211_network *net = NULL, *best = NULL;
+-	int bssvalid;
+-	unsigned long flags;
+-
+-	mutex_lock(&mac->associnfo.mutex);
+-
+-	if (!mac->associnfo.associating)
+-		goto out;
+-
+-	/* ieee80211_disassoc might clear this */
+-	bssvalid = mac->associnfo.bssvalid;
+-
+-	/* meh */
+-	if (mac->associnfo.associated)
+-		ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
+-
+-	/* try to find the requested network in our list, if we found one already */
+-	if (bssvalid || mac->associnfo.bssfixed)
+-		found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
+-
+-	/* Search the ieee80211 networks for this network if we didn't find it by bssid,
+-	 * but only if we've scanned at least once (to get a better list of networks to
+-	 * select from). If we have not scanned before, the !found logic below will be
+-	 * invoked and will scan. */
+-	if (!found && (mac->associnfo.scan_retry < IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT))
+-	{
+-		s8 rssi = -128;	/* if I don't initialise, gcc emits an invalid warning
+-				   because it cannot follow the best pointer logic. */
+-		spin_lock_irqsave(&mac->ieee->lock, flags);
+-		list_for_each_entry(net, &mac->ieee->network_list, list) {
+-			/* we're supposed to find the network with
+-			 * the best signal here, as we're asked to join
+-			 * any network with a specific ESSID, and many
+-			 * different ones could have that.
+-			 *
+-			 * I'll for now just go with the reported rssi.
+-			 *
+-			 * We also should take into account the rateset
+-			 * here to find the best BSSID to try.
+-			 */
+-			if (network_matches_request(mac, net)) {
+-				if (!best) {
+-					best = net;
+-					rssi = best->stats.rssi;
+-					continue;
+-				}
+-				/* we already had a matching network, so
+-				 * compare their properties to get the
+-				 * better of the two ... (see above)
+-				 */
+-				if (rssi < net->stats.rssi) {
+-					best = net;
+-					rssi = best->stats.rssi;
+-				}
+-			}
+-		}
+-		/* if we unlock here, we might get interrupted and the `best'
+-		 * pointer could go stale */
+-		if (best) {
+-			found = ieee80211softmac_create_network(mac, best);
+-			/* if found is still NULL, then we got -ENOMEM somewhere */
+-			if (found)
+-				ieee80211softmac_add_network(mac, found);
+-		}
+-		spin_unlock_irqrestore(&mac->ieee->lock, flags);
+-	}
+-
+-	if (!found) {
+-		if (mac->associnfo.scan_retry > 0) {
+-			mac->associnfo.scan_retry--;
+-
+-			/* We know of no such network. Let's scan.
+-			 * NB: this also happens if we had no memory to copy the network info...
+-			 * Maybe we can hope to have more memory after scanning finishes ;)
+-			 */
+-			dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
+-			ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
+-			if (ieee80211softmac_start_scan(mac)) {
+-				dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
+-			}
+-			goto out;
+-		} else {
+-			mac->associnfo.associating = 0;
+-			mac->associnfo.associated = 0;
+-
+-			dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
+-			/* reset the retry counter for the next user request since we
+-			 * break out and don't reschedule ourselves after this point. */
+-			mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+-			ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
+-			goto out;
+-		}
+-	}
+-
+-	/* reset the retry counter for the next user request since we
+-	 * now found a net and will try to associate to it, but not
+-	 * schedule this function again. */
+-	mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+-	mac->associnfo.bssvalid = 1;
+-	memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
+-	/* copy the ESSID for displaying it */
+-	mac->associnfo.associate_essid.len = found->essid.len;
+-	memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
+-
+-	/* we found a network! authenticate (if necessary) and associate to it. */
+-	if (found->authenticating) {
+-		dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n");
+-		if(!mac->associnfo.assoc_wait) {
+-			mac->associnfo.assoc_wait = 1;
+-			ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
+-		}
+-		goto out;
+-	}
+-	if (!found->authenticated && !found->authenticating) {
+-		/* This relies on the fact that _auth_req only queues the work,
+-		 * otherwise adding the notification would be racy. */
+-		if (!ieee80211softmac_auth_req(mac, found)) {
+-			if(!mac->associnfo.assoc_wait) {
+-				dprintk(KERN_INFO PFX "Cannot associate without being authenticated, requested authentication\n");
+-				mac->associnfo.assoc_wait = 1;
+-				ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
+-			}
+-		} else {
+-			printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
+-			mac->associnfo.assoc_wait = 0;
+-			ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
+-		}
+-		goto out;
+-	}
+-	/* finally! now we can start associating */
+-	mac->associnfo.assoc_wait = 0;
+-	ieee80211softmac_assoc(mac, found);
+-
+-out:
+-	mutex_unlock(&mac->associnfo.mutex);
+-}
+-
+-/* call this to do whatever is necessary when we're associated */
+-static void
+-ieee80211softmac_associated(struct ieee80211softmac_device *mac,
+-	struct ieee80211_assoc_response * resp,
+-	struct ieee80211softmac_network *net)
+-{
+-	u16 cap = le16_to_cpu(resp->capability);
+-	u8 erp_value = net->erp_value;
+-
+-	mac->associnfo.associating = 0;
+-	mac->bssinfo.supported_rates = net->supported_rates;
+-	ieee80211softmac_recalc_txrates(mac);
+-
+-	mac->associnfo.associated = 1;
+-
+-	mac->associnfo.short_preamble_available =
+-		(cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
+-	ieee80211softmac_process_erp(mac, erp_value);
+-
+-	if (mac->set_bssid_filter)
+-		mac->set_bssid_filter(mac->dev, net->bssid);
+-	memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
+-	netif_carrier_on(mac->dev);
+-
+-	mac->association_id = le16_to_cpup(&resp->aid);
+-}
+-
+-/* received frame handling functions */
+-int
+-ieee80211softmac_handle_assoc_response(struct net_device * dev,
+-				       struct ieee80211_assoc_response * resp,
+-				       struct ieee80211_network * _ieee80211_network)
+-{
+-	/* NOTE: the network parameter has to be mostly ignored by
+-	 *       this code because it is the ieee80211's pointer
+-	 *       to the struct, not ours (we made a copy)
+-	 */
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	u16 status = le16_to_cpup(&resp->status);
+-	struct ieee80211softmac_network *network = NULL;
+-	unsigned long flags;
+-	DECLARE_MAC_BUF(mac2);
+-
+-	if (unlikely(!mac->running))
+-		return -ENODEV;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-
+-	if (!mac->associnfo.associating) {
+-		/* we race against the timeout function, so make sure
+-		 * only one of us can do work */
+-		spin_unlock_irqrestore(&mac->lock, flags);
+-		return 0;
+-	}
+-	network = ieee80211softmac_get_network_by_bssid_locked(mac, resp->header.addr3);
+-
+-	/* someone sending us things without us knowing him? Ignore. */
+-	if (!network) {
+-		dprintk(KERN_INFO PFX "Received unrequested assocation response from %s\n",
+-			print_mac(mac2, resp->header.addr3));
+-		spin_unlock_irqrestore(&mac->lock, flags);
+-		return 0;
+-	}
+-
+-	/* now that we know it was for us, we can cancel the timeout */
+-	cancel_delayed_work(&mac->associnfo.timeout);
+-
+-	/* if the association response included an ERP IE, update our saved
+-	 * copy */
+-	if (_ieee80211_network->flags & NETWORK_HAS_ERP_VALUE)
+-		network->erp_value = _ieee80211_network->erp_value;
+-
+-	switch (status) {
+-		case 0:
+-			dprintk(KERN_INFO PFX "associated!\n");
+-			ieee80211softmac_associated(mac, resp, network);
+-			ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATED, network);
+-			break;
+-		case WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH:
+-			if (!network->auth_desynced_once) {
+-				/* there seem to be a few rare cases where our view of
+-				 * the world is obscured, or buggy APs that don't DEAUTH
+-				 * us properly. So we handle that, but allow it only once.
+-				 */
+-				printkl(KERN_INFO PFX "We were not authenticated during association, retrying...\n");
+-				network->authenticated = 0;
+-				/* we don't want to do this more than once ... */
+-				network->auth_desynced_once = 1;
+-				queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+-				break;
+-			}
+-		default:
+-			dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status);
+-			mac->associnfo.associating = 0;
+-			mac->associnfo.bssvalid = 0;
+-			mac->associnfo.associated = 0;
+-			ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network);
+-	}
+-
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-	return 0;
+-}
+-
+-void
+-ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-	mac->associnfo.associating = 1;
+-	queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-int
+-ieee80211softmac_handle_disassoc(struct net_device * dev,
+-				 struct ieee80211_disassoc *disassoc)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+-	if (unlikely(!mac->running))
+-		return -ENODEV;
+-
+-	if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN))
+-		return 0;
+-
+-	if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN))
+-		return 0;
+-
+-	dprintk(KERN_INFO PFX "got disassoc frame\n");
+-	ieee80211softmac_disassoc(mac);
+-
+-	ieee80211softmac_try_reassoc(mac);
+-
+-	return 0;
+-}
+-
+-int
+-ieee80211softmac_handle_reassoc_req(struct net_device * dev,
+-				    struct ieee80211_reassoc_request * resp)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	struct ieee80211softmac_network *network;
+-
+-	if (unlikely(!mac->running))
+-		return -ENODEV;
+-
+-	network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3);
+-	if (!network) {
+-		dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
+-		return 0;
+-	}
+-	queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+-
+-	return 0;
+-}
+diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
+deleted file mode 100644
+index 1a96c25..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
++++ /dev/null
+@@ -1,413 +0,0 @@
+-/*
+- * This file contains the softmac's authentication logic.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- *                          Joseph Jezak <josejx at gentoo.org>
+- *                          Larry Finger <Larry.Finger at lwfinger.net>
+- *                          Danny van Dyk <kugelfang at gentoo.org>
+- *                          Michael Buesch <mbuesch at freenet.de>
+- *
+- * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-static void ieee80211softmac_auth_queue(struct work_struct *work);
+-
+-/* Queues an auth request to the desired AP */
+-int
+-ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *net)
+-{
+-	struct ieee80211softmac_auth_queue_item *auth;
+-	unsigned long flags;
+-	DECLARE_MAC_BUF(mac2);
+-
+-	if (net->authenticating || net->authenticated)
+-		return 0;
+-	net->authenticating = 1;
+-
+-	/* Add the network if it's not already added */
+-	ieee80211softmac_add_network(mac, net);
+-
+-	dprintk(KERN_NOTICE PFX "Queueing Authentication Request to %s\n", print_mac(mac2, net->bssid));
+-	/* Queue the auth request */
+-	auth = (struct ieee80211softmac_auth_queue_item *)
+-		kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL);
+-	if(auth == NULL)
+-		return -ENOMEM;
+-
+-	auth->net = net;
+-	auth->mac = mac;
+-	auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
+-	auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
+-	INIT_DELAYED_WORK(&auth->work, ieee80211softmac_auth_queue);
+-
+-	/* Lock (for list) */
+-	spin_lock_irqsave(&mac->lock, flags);
+-
+-	/* add to list */
+-	list_add_tail(&auth->list, &mac->auth_queue);
+-	queue_delayed_work(mac->wq, &auth->work, 0);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-
+-	return 0;
+-}
+-
+-
+-/* Sends an auth request to the desired AP and handles timeouts */
+-static void
+-ieee80211softmac_auth_queue(struct work_struct *work)
+-{
+-	struct ieee80211softmac_device *mac;
+-	struct ieee80211softmac_auth_queue_item *auth;
+-	struct ieee80211softmac_network *net;
+-	unsigned long flags;
+-	DECLARE_MAC_BUF(mac2);
+-
+-	auth = container_of(work, struct ieee80211softmac_auth_queue_item,
+-			    work.work);
+-	net = auth->net;
+-	mac = auth->mac;
+-
+-	if(auth->retry > 0) {
+-		/* Switch to correct channel for this network */
+-		mac->set_channel(mac->dev, net->channel);
+-
+-		/* Lock and set flags */
+-		spin_lock_irqsave(&mac->lock, flags);
+-		if (unlikely(!mac->running)) {
+-			/* Prevent reschedule on workqueue flush */
+-			spin_unlock_irqrestore(&mac->lock, flags);
+-			return;
+-		}
+-		net->authenticated = 0;
+-		/* add a timeout call so we eventually give up waiting for an auth reply */
+-		queue_delayed_work(mac->wq, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
+-		auth->retry--;
+-		spin_unlock_irqrestore(&mac->lock, flags);
+-		if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state))
+-			dprintk(KERN_NOTICE PFX "Sending Authentication Request to %s failed (this shouldn't happen, wait for the timeout).\n",
+-				print_mac(mac2, net->bssid));
+-		else
+-			dprintk(KERN_NOTICE PFX "Sent Authentication Request to %s.\n", print_mac(mac2, net->bssid));
+-		return;
+-	}
+-
+-	printkl(KERN_WARNING PFX "Authentication timed out with %s\n", print_mac(mac2, net->bssid));
+-	/* Remove this item from the queue */
+-	spin_lock_irqsave(&mac->lock, flags);
+-	net->authenticating = 0;
+-	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
+-	cancel_delayed_work(&auth->work); /* just to make sure... */
+-	list_del(&auth->list);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-	/* Free it */
+-	kfree(auth);
+-}
+-
+-/* Sends a response to an auth challenge (for shared key auth). */
+-static void
+-ieee80211softmac_auth_challenge_response(struct work_struct *work)
+-{
+-	struct ieee80211softmac_auth_queue_item *aq =
+-		container_of(work, struct ieee80211softmac_auth_queue_item,
+-			     work.work);
+-
+-	/* Send our response */
+-	ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
+-}
+-
+-/* Handle the auth response from the AP
+- * This should be registered with ieee80211 as handle_auth
+- */
+-int
+-ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
+-{
+-
+-	struct list_head *list_ptr;
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	struct ieee80211softmac_auth_queue_item *aq = NULL;
+-	struct ieee80211softmac_network *net = NULL;
+-	unsigned long flags;
+-	u8 * data;
+-	DECLARE_MAC_BUF(mac2);
+-
+-	if (unlikely(!mac->running))
+-		return -ENODEV;
+-
+-	/* Find correct auth queue item */
+-	spin_lock_irqsave(&mac->lock, flags);
+-	list_for_each(list_ptr, &mac->auth_queue) {
+-		aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
+-		net = aq->net;
+-		if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN))
+-			break;
+-		else
+-			aq = NULL;
+-	}
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-
+-	/* Make sure that we've got an auth queue item for this request */
+-	if(aq == NULL)
+-	{
+-		dprintkl(KERN_DEBUG PFX "Authentication response received from %s but no queue item exists.\n", print_mac(mac2, auth->header.addr2));
+-		/* Error #? */
+-		return -1;
+-	}
+-
+-	/* Check for out of order authentication */
+-	if(!net->authenticating)
+-	{
+-		dprintkl(KERN_DEBUG PFX "Authentication response received from %s but did not request authentication.\n",print_mac(mac2, auth->header.addr2));
+-		return -1;
+-	}
+-
+-	/* Parse the auth packet */
+-	switch(le16_to_cpu(auth->algorithm)) {
+-	case WLAN_AUTH_OPEN:
+-		/* Check the status code of the response */
+-
+-		switch(le16_to_cpu(auth->status)) {
+-		case WLAN_STATUS_SUCCESS:
+-			/* Update the status to Authenticated */
+-			spin_lock_irqsave(&mac->lock, flags);
+-			net->authenticating = 0;
+-			net->authenticated = 1;
+-			spin_unlock_irqrestore(&mac->lock, flags);
+-
+-			/* Send event */
+-			printkl(KERN_NOTICE PFX "Open Authentication completed with %s\n", print_mac(mac2, net->bssid));
+-			ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
+-			break;
+-		default:
+-			/* Lock and reset flags */
+-			spin_lock_irqsave(&mac->lock, flags);
+-			net->authenticated = 0;
+-			net->authenticating = 0;
+-			spin_unlock_irqrestore(&mac->lock, flags);
+-
+-			printkl(KERN_NOTICE PFX "Open Authentication with %s failed, error code: %i\n",
+-				print_mac(mac2, net->bssid), le16_to_cpup(&auth->status));
+-			/* Count the error? */
+-			break;
+-		}
+-		goto free_aq;
+-		break;
+-	case WLAN_AUTH_SHARED_KEY:
+-		/* Figure out where we are in the process */
+-		switch(le16_to_cpu(auth->transaction)) {
+-		case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE:
+-			/* Check to make sure we have a challenge IE */
+-			data = (u8 *)auth->info_element;
+-			if (*data++ != MFIE_TYPE_CHALLENGE) {
+-				printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
+-				break;
+-			}
+-			/* Save the challenge */
+-			spin_lock_irqsave(&mac->lock, flags);
+-			net->challenge_len = *data++;
+-			if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
+-				net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
+-			kfree(net->challenge);
+-			net->challenge = kmemdup(data, net->challenge_len,
+-						 GFP_ATOMIC);
+-			if (net->challenge == NULL) {
+-				printkl(KERN_NOTICE PFX "Shared Key "
+-					"Authentication failed due to "
+-					"memory shortage.\n");
+-				spin_unlock_irqrestore(&mac->lock, flags);
+-				break;
+-			}
+-			aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
+-
+-			/* We reuse the work struct from the auth request here.
+-			 * It is safe to do so as each one is per-request, and
+-			 * at this point (dealing with authentication response)
+-			 * we have obviously already sent the initial auth
+-			 * request. */
+-			cancel_delayed_work(&aq->work);
+-			INIT_DELAYED_WORK(&aq->work, &ieee80211softmac_auth_challenge_response);
+-			queue_delayed_work(mac->wq, &aq->work, 0);
+-			spin_unlock_irqrestore(&mac->lock, flags);
+-			return 0;
+-		case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
+-			kfree(net->challenge);
+-			net->challenge = NULL;
+-			net->challenge_len = 0;
+-			/* Check the status code of the response */
+-			switch(auth->status) {
+-			case WLAN_STATUS_SUCCESS:
+-				/* Update the status to Authenticated */
+-				spin_lock_irqsave(&mac->lock, flags);
+-				net->authenticating = 0;
+-				net->authenticated = 1;
+-				spin_unlock_irqrestore(&mac->lock, flags);
+-				printkl(KERN_NOTICE PFX "Shared Key Authentication completed with %s\n",
+-					print_mac(mac2, net->bssid));
+-				ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
+-				break;
+-			default:
+-				printkl(KERN_NOTICE PFX "Shared Key Authentication with %s failed, error code: %i\n",
+-					print_mac(mac2, net->bssid), le16_to_cpup(&auth->status));
+-				/* Lock and reset flags */
+-				spin_lock_irqsave(&mac->lock, flags);
+-				net->authenticating = 0;
+-				net->authenticated = 0;
+-				spin_unlock_irqrestore(&mac->lock, flags);
+-				/* Count the error? */
+-				break;
+-			}
+-			goto free_aq;
+-			break;
+-		default:
+-			printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction);
+-			break;
+-		}
+-		goto free_aq;
+-		break;
+-	default:
+-		/* ERROR */
+-		goto free_aq;
+-		break;
+-	}
+-	return 0;
+-free_aq:
+-	/* Cancel the timeout */
+-	spin_lock_irqsave(&mac->lock, flags);
+-	cancel_delayed_work(&aq->work);
+-	/* Remove this item from the queue */
+-	list_del(&aq->list);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-
+-	/* Free it */
+-	kfree(aq);
+-	return 0;
+-}
+-
+-/*
+- * Handle deauthorization
+- */
+-static void
+-ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *net)
+-{
+-	struct ieee80211softmac_auth_queue_item *aq = NULL;
+-	struct list_head *list_ptr;
+-	unsigned long flags;
+-
+-	/* deauthentication implies disassociation */
+-	ieee80211softmac_disassoc(mac);
+-
+-	/* Lock and reset status flags */
+-	spin_lock_irqsave(&mac->lock, flags);
+-	net->authenticating = 0;
+-	net->authenticated = 0;
+-
+-	/* Find correct auth queue item, if it exists */
+-	list_for_each(list_ptr, &mac->auth_queue) {
+-		aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
+-		if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN))
+-			break;
+-		else
+-			aq = NULL;
+-	}
+-
+-	/* Cancel pending work */
+-	if(aq != NULL)
+-		/* Not entirely safe?  What about running work? */
+-		cancel_delayed_work(&aq->work);
+-
+-	/* Free our network ref */
+-	ieee80211softmac_del_network_locked(mac, net);
+-	if(net->challenge != NULL)
+-		kfree(net->challenge);
+-	kfree(net);
+-
+-	/* can't transmit data right now... */
+-	netif_carrier_off(mac->dev);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-
+-	ieee80211softmac_try_reassoc(mac);
+-}
+-
+-/*
+- * Sends a deauth request to the desired AP
+- */
+-int
+-ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *net, int reason)
+-{
+-	int ret;
+-
+-	/* Make sure the network is authenticated */
+-	if (!net->authenticated)
+-	{
+-		dprintkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
+-		/* Error okay? */
+-		return -EPERM;
+-	}
+-
+-	/* Send the de-auth packet */
+-	if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason)))
+-		return ret;
+-
+-	ieee80211softmac_deauth_from_net(mac, net);
+-	return 0;
+-}
+-
+-/*
+- * This should be registered with ieee80211 as handle_deauth
+- */
+-int
+-ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth)
+-{
+-
+-	struct ieee80211softmac_network *net = NULL;
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	DECLARE_MAC_BUF(mac2);
+-
+-	if (unlikely(!mac->running))
+-		return -ENODEV;
+-
+-	if (!deauth) {
+-		dprintk("deauth without deauth packet. eek!\n");
+-		return 0;
+-	}
+-
+-	net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2);
+-
+-	if (net == NULL) {
+-		dprintkl(KERN_DEBUG PFX "Received deauthentication packet from %s, but that network is unknown.\n",
+-			print_mac(mac2, deauth->header.addr2));
+-		return 0;
+-	}
+-
+-	/* Make sure the network is authenticated */
+-	if(!net->authenticated)
+-	{
+-		dprintkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
+-		/* Error okay? */
+-		return -EPERM;
+-	}
+-
+-	ieee80211softmac_deauth_from_net(mac, net);
+-
+-	/* let's try to re-associate */
+-	queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+-	return 0;
+-}
+diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
+deleted file mode 100644
+index 8cef05b..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_event.c
++++ /dev/null
+@@ -1,189 +0,0 @@
+-/*
+- * Event system
+- * Also see comments in public header file and longer explanation below.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- *                          Joseph Jezak <josejx at gentoo.org>
+- *                          Larry Finger <Larry.Finger at lwfinger.net>
+- *                          Danny van Dyk <kugelfang at gentoo.org>
+- *                          Michael Buesch <mbuesch at freenet.de>
+- *
+- * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-/*
+- * Each event has associated to it
+- *  - an event type (see constants in public header)
+- *  - an event context (see below)
+- *  - the function to be called
+- *  - a context (extra parameter to call the function with)
+- *  - and the softmac struct
+- *
+- * The event context is private and can only be used from
+- * within this module. Its meaning varies with the event
+- * type:
+- *  SCAN_FINISHED,
+- *  DISASSOCIATED:	NULL
+- *  ASSOCIATED,
+- *  ASSOCIATE_FAILED,
+- *  ASSOCIATE_TIMEOUT,
+- *  AUTHENTICATED,
+- *  AUTH_FAILED,
+- *  AUTH_TIMEOUT:	a pointer to the network struct
+- * ...
+- * Code within this module can use the event context to be only
+- * called when the event is true for that specific context
+- * as per above table.
+- * If the event context is NULL, then the notification is always called,
+- * regardless of the event context. The event context is not passed to
+- * the callback, it is assumed that the context suffices.
+- *
+- * You can also use the event context only by setting the event type
+- * to -1 (private use only), in which case you'll be notified
+- * whenever the event context matches.
+- */
+-
+-static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
+-	NULL, /* scan finished */
+-	NULL, /* associated */
+-	"associating failed",
+-	"associating timed out",
+-	"authenticated",
+-	"authenticating failed",
+-	"authenticating timed out",
+-	"associating failed because no suitable network was found",
+-	NULL, /* disassociated */
+-};
+-
+-
+-static void
+-ieee80211softmac_notify_callback(struct work_struct *work)
+-{
+-	struct ieee80211softmac_event *pevent =
+-		container_of(work, struct ieee80211softmac_event, work.work);
+-	struct ieee80211softmac_event event = *pevent;
+-	kfree(pevent);
+-
+-	event.fun(event.mac->dev, event.event_type, event.context);
+-}
+-
+-int
+-ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
+-	int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask)
+-{
+-	struct ieee80211softmac_event *eventptr;
+-	unsigned long flags;
+-
+-	if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST)
+-		return -ENOSYS;
+-
+-	if (!fun)
+-		return -EINVAL;
+-
+-	eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask);
+-	if (!eventptr)
+-		return -ENOMEM;
+-
+-	eventptr->event_type = event;
+-	INIT_DELAYED_WORK(&eventptr->work, ieee80211softmac_notify_callback);
+-	eventptr->fun = fun;
+-	eventptr->context = context;
+-	eventptr->mac = mac;
+-	eventptr->event_context = event_context;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-	list_add(&eventptr->list, &mac->events);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-
+-	return 0;
+-}
+-
+-int
+-ieee80211softmac_notify_gfp(struct net_device *dev,
+-	int event, notify_function_ptr fun, void *context, gfp_t gfp_mask)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+-	if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST)
+-		return -ENOSYS;
+-
+-	return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp);
+-
+-/* private -- calling all callbacks that were specified */
+-void
+-ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
+-{
+-	struct ieee80211softmac_event *eventptr, *tmp;
+-	struct ieee80211softmac_network *network;
+-
+-	if (event >= 0) {
+-		union iwreq_data wrqu;
+-		int we_event;
+-		char *msg = NULL;
+-
+-		memset(&wrqu, '\0', sizeof (union iwreq_data));
+-
+-		switch(event) {
+-		case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
+-			network = (struct ieee80211softmac_network *)event_ctx;
+-			memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
+-			/* fall through */
+-		case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
+-			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+-			we_event = SIOCGIWAP;
+-			break;
+-		case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
+-			we_event = SIOCGIWSCAN;
+-			break;
+-		default:
+-			msg = event_descriptions[event];
+-			if (!msg)
+-				msg = "SOFTMAC EVENT BUG";
+-			wrqu.data.length = strlen(msg);
+-			we_event = IWEVCUSTOM;
+-			break;
+-		}
+-		wireless_send_event(mac->dev, we_event, &wrqu, msg);
+-	}
+-
+-	if (!list_empty(&mac->events))
+-		list_for_each_entry_safe(eventptr, tmp, &mac->events, list) {
+-			if ((eventptr->event_type == event || eventptr->event_type == -1)
+-				&& (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
+-				list_del(&eventptr->list);
+-				/* User may have subscribed to ANY event, so
+-				 * we tell them which event triggered it. */
+-				eventptr->event_type = event;
+-				queue_delayed_work(mac->wq, &eventptr->work, 0);
+-			}
+-		}
+-}
+-
+-void
+-ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_ctx)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-	ieee80211softmac_call_events_locked(mac, event, event_ctx);
+-
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-}
+diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
+deleted file mode 100644
+index 73b4b13..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_io.c
++++ /dev/null
+@@ -1,488 +0,0 @@
+-/*
+- * Some parts based on code from net80211
+- * Copyright (c) 2001 Atsushi Onoe
+- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+- * All rights reserved.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- *    notice, this list of conditions and the following disclaimer.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- *    notice, this list of conditions and the following disclaimer in the
+- *    documentation and/or other materials provided with the distribution.
+- * 3. The name of the author may not be used to endorse or promote products
+- *    derived from this software without specific prior written permission.
+- *
+- * Alternatively, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") version 2 as published by the Free
+- * Software Foundation.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-/* Helper functions for inserting data into the frames */
+-
+-/*
+- * Adds an ESSID element to the frame
+- *
+- */
+-static u8 *
+-ieee80211softmac_add_essid(u8 *dst, struct ieee80211softmac_essid *essid)
+-{
+-	if (essid) {
+-		*dst++ = MFIE_TYPE_SSID;
+-		*dst++ = essid->len;
+-		memcpy(dst, essid->data, essid->len);
+-		return dst+essid->len;
+-	} else {
+-		*dst++ = MFIE_TYPE_SSID;
+-		*dst++ = 0;
+-		return dst;
+-	}
+-}
+-
+-/* Adds Supported Rates and if required Extended Rates Information Element
+- * to the frame, ASSUMES WE HAVE A SORTED LIST OF RATES */
+-static u8 *
+-ieee80211softmac_frame_add_rates(u8 *dst, const struct ieee80211softmac_ratesinfo *r)
+-{
+-	int cck_len, ofdm_len;
+-	*dst++ = MFIE_TYPE_RATES;
+-
+-	for(cck_len=0; ieee80211_is_cck_rate(r->rates[cck_len]) && (cck_len < r->count);cck_len++);
+-
+-	if(cck_len > IEEE80211SOFTMAC_MAX_RATES_LEN)
+-		cck_len = IEEE80211SOFTMAC_MAX_RATES_LEN;
+-	*dst++ = cck_len;
+-	memcpy(dst, r->rates, cck_len);
+-	dst += cck_len;
+-
+-	if(cck_len < r->count){
+-		for (ofdm_len=0; ieee80211_is_ofdm_rate(r->rates[ofdm_len + cck_len]) && (ofdm_len + cck_len < r->count); ofdm_len++);
+-		if (ofdm_len > 0) {
+-			if (ofdm_len > IEEE80211SOFTMAC_MAX_EX_RATES_LEN)
+-				ofdm_len = IEEE80211SOFTMAC_MAX_EX_RATES_LEN;
+-			*dst++ = MFIE_TYPE_RATES_EX;
+-			*dst++ = ofdm_len;
+-			memcpy(dst, r->rates + cck_len, ofdm_len);
+-			dst += ofdm_len;
+-		}
+-	}
+-	return dst;
+-}
+-
+-/* Allocate a management frame */
+-static u8 *
+-ieee80211softmac_alloc_mgt(u32 size)
+-{
+-	u8 * data;
+-
+-	/* Add the header and FCS to the size */
+-	size = size + IEEE80211_3ADDR_LEN;
+-	if(size > IEEE80211_DATA_LEN)
+-		return NULL;
+-	/* Allocate the frame */
+-	data = kzalloc(size, GFP_ATOMIC);
+-	return data;
+-}
+-
+-/*
+- * Add a 2 Address Header
+- */
+-static void
+-ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac,
+-	struct ieee80211_hdr_2addr *header, u32 type, u8 *dest)
+-{
+-	/* Fill in the frame control flags */
+-	header->frame_ctl = cpu_to_le16(type);
+-	/* Control packets always have WEP turned off */
+-	if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL)
+-		header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0;
+-
+-	/* Fill in the duration */
+-	header->duration_id = 0;
+-	/* FIXME: How do I find this?
+-	 * calculate. But most drivers just fill in 0 (except if it's a station id of course) */
+-
+-	/* Fill in the Destination Address */
+-	if(dest == NULL)
+-		memset(header->addr1, 0xFF, ETH_ALEN);
+-	else
+-		memcpy(header->addr1, dest, ETH_ALEN);
+-	/* Fill in the Source Address */
+-	memcpy(header->addr2, mac->ieee->dev->dev_addr, ETH_ALEN);
+-
+-}
+-
+-
+-/* Add a 3 Address Header */
+-static void
+-ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
+-	struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid)
+-{
+-	/* This is common with 2addr, so use that instead */
+-	ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest);
+-
+-	/* Fill in the BSS ID */
+-	if(bssid == NULL)
+-		memset(header->addr3, 0xFF, ETH_ALEN);
+-	else
+-		memcpy(header->addr3, bssid, ETH_ALEN);
+-
+-	/* Fill in the sequence # */
+-	/* FIXME: I need to add this to the softmac struct
+-	 * shouldn't the sequence number be in ieee80211? */
+-}
+-
+-static __le16
+-ieee80211softmac_capabilities(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *net)
+-{
+-	__le16 capability = 0;
+-
+-	/* ESS and IBSS bits are set according to the current mode */
+-	switch (mac->ieee->iw_mode) {
+-	case IW_MODE_INFRA:
+-		capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+-		break;
+-	case IW_MODE_ADHOC:
+-		capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
+-		break;
+-	case IW_MODE_AUTO:
+-		capability = cpu_to_le16(net->capabilities &
+-			(WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS));
+-		break;
+-	default:
+-		/* bleh. we don't ever go to these modes */
+-		printk(KERN_ERR PFX "invalid iw_mode!\n");
+-		break;
+-	}
+-
+-	/* CF Pollable / CF Poll Request */
+-	/* Needs to be implemented, for now, the 0's == not supported */
+-
+-	/* Privacy Bit */
+-	capability |= mac->ieee->sec.level ?
+-		cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
+-
+-	/* Short Preamble */
+-	/* Always supported: we probably won't ever be powering devices which
+-	 * dont support this... */
+-	capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
+-
+-	/* PBCC */
+-	/* Not widely used */
+-
+-	/* Channel Agility */
+-	/* Not widely used */
+-
+-	/* Short Slot */
+-	/* Will be implemented later */
+-
+-	/* DSSS-OFDM */
+-	/* Not widely used */
+-
+-	return capability;
+-}
+-
+-/*****************************************************************************
+- * Create Management packets
+- *****************************************************************************/
+-
+-/* Creates an association request packet */
+-static u32
+-ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
+-	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
+-{
+-	u8 *data;
+-	(*pkt) = (struct ieee80211_assoc_request *)ieee80211softmac_alloc_mgt(
+-		2 +		/* Capability Info */
+-		2 +	 	/* Listen Interval */
+-		/* SSID IE */
+-		1 + 1 + IW_ESSID_MAX_SIZE +
+-		/* Rates IE */
+-		1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
+-		/* Extended Rates IE */
+-		1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN +
+-		/* WPA IE if present */
+-		mac->wpa.IElen
+-		/* Other IE's?  Optional?
+-		 * Yeah, probably need an extra IE parameter -- lots of vendors like to
+-		 * fill in their own IEs */
+-	);
+-	if (unlikely((*pkt) == NULL))
+-		return 0;
+-	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
+-
+-	/* Fill in the capabilities */
+-	(*pkt)->capability = ieee80211softmac_capabilities(mac, net);
+-
+-	/* Fill in Listen Interval (?) */
+-	(*pkt)->listen_interval = cpu_to_le16(10);
+-
+-	data = (u8 *)(*pkt)->info_element;
+-	/* Add SSID */
+-	data = ieee80211softmac_add_essid(data, &net->essid);
+-	/* Add Rates */
+-	data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
+-	/* Add WPA IE */
+-	if (mac->wpa.IElen && mac->wpa.IE) {
+-		memcpy(data, mac->wpa.IE, mac->wpa.IElen);
+-		data += mac->wpa.IElen;
+-	}
+-	/* Return the number of used bytes */
+-	return (data - (u8*)(*pkt));
+-}
+-
+-/* Create a reassociation request packet */
+-static u32
+-ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
+-	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
+-{
+-	u8 *data;
+-	(*pkt) = (struct ieee80211_reassoc_request *)ieee80211softmac_alloc_mgt(
+-		2 +		/* Capability Info */
+-		2 +	 	/* Listen Interval */
+-		ETH_ALEN +	/* AP MAC */
+-		/* SSID IE */
+-		1 + 1 + IW_ESSID_MAX_SIZE +
+-		/* Rates IE */
+-		1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
+-		/* Extended Rates IE */
+-		1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
+-		/* Other IE's? */
+-	);
+-	if (unlikely((*pkt) == NULL))
+-		return 0;
+-	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
+-
+-	/* Fill in the capabilities */
+-	(*pkt)->capability = ieee80211softmac_capabilities(mac, net);
+-
+-	/* Fill in Listen Interval (?) */
+-	(*pkt)->listen_interval = cpu_to_le16(10);
+-	/* Fill in the current AP MAC */
+-	memcpy((*pkt)->current_ap, mac->ieee->bssid, ETH_ALEN);
+-
+-	data = (u8 *)(*pkt)->info_element;
+-	/* Add SSID */
+-	data = ieee80211softmac_add_essid(data, &net->essid);
+-	/* Add Rates */
+-	data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
+-	/* Return packet size */
+-	return (data - (u8 *)(*pkt));
+-}
+-
+-/* Create an authentication packet */
+-static u32
+-ieee80211softmac_auth(struct ieee80211_auth **pkt,
+-	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
+-	u16 transaction, u16 status, int *encrypt_mpdu)
+-{
+-	u8 *data;
+-	int auth_mode = mac->ieee->sec.auth_mode;
+-	int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY
+-		&& transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE);
+-
+-	/* Allocate Packet */
+-	(*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
+-		2 +		/* Auth Algorithm */
+-		2 +		/* Auth Transaction Seq */
+-		2 +		/* Status Code */
+-		 /* Challenge Text IE */
+-		(is_shared_response ? 1 + 1 + net->challenge_len : 0)
+-	);
+-	if (unlikely((*pkt) == NULL))
+-		return 0;
+-	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
+-
+-	/* Algorithm */
+-	(*pkt)->algorithm = cpu_to_le16(auth_mode);
+-	/* Transaction */
+-	(*pkt)->transaction = cpu_to_le16(transaction);
+-	/* Status */
+-	(*pkt)->status = cpu_to_le16(status);
+-
+-	data = (u8 *)(*pkt)->info_element;
+-	/* Challenge Text */
+-	if (is_shared_response) {
+-		*data = MFIE_TYPE_CHALLENGE;
+-		data++;
+-
+-		/* Copy the challenge in */
+-		*data = net->challenge_len;
+-		data++;
+-		memcpy(data, net->challenge, net->challenge_len);
+-		data += net->challenge_len;
+-
+-		/* Make sure this frame gets encrypted with the shared key */
+-		*encrypt_mpdu = 1;
+-	} else
+-		*encrypt_mpdu = 0;
+-
+-	/* Return the packet size */
+-	return (data - (u8 *)(*pkt));
+-}
+-
+-/* Create a disassocation or deauthentication packet */
+-static u32
+-ieee80211softmac_disassoc_deauth(struct ieee80211_disassoc **pkt,
+-	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
+-	u16 type, u16 reason)
+-{
+-	/* Allocate Packet */
+-	(*pkt) = (struct ieee80211_disassoc *)ieee80211softmac_alloc_mgt(2);
+-	if (unlikely((*pkt) == NULL))
+-		return 0;
+-	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), type, net->bssid, net->bssid);
+-	/* Reason */
+-	(*pkt)->reason = cpu_to_le16(reason);
+-	/* Return the packet size */
+-	return (2 + IEEE80211_3ADDR_LEN);
+-}
+-
+-/* Create a probe request packet */
+-static u32
+-ieee80211softmac_probe_req(struct ieee80211_probe_request **pkt,
+-	struct ieee80211softmac_device *mac, struct ieee80211softmac_essid *essid)
+-{
+-	u8 *data;
+-	/* Allocate Packet */
+-	(*pkt) = (struct ieee80211_probe_request *)ieee80211softmac_alloc_mgt(
+-		/* SSID of requested network */
+-		1 + 1 + IW_ESSID_MAX_SIZE +
+-		/* Rates IE */
+-		1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
+-		/* Extended Rates IE */
+-		1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
+-	);
+-	if (unlikely((*pkt) == NULL))
+-		return 0;
+-	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_REQ, NULL, NULL);
+-
+-	data = (u8 *)(*pkt)->info_element;
+-	/* Add ESSID (can be NULL) */
+-	data = ieee80211softmac_add_essid(data, essid);
+-	/* Add Rates */
+-	data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
+-	/* Return packet size */
+-	return (data - (u8 *)(*pkt));
+-}
+-
+-/* Create a probe response packet */
+-/* FIXME: Not complete */
+-static u32
+-ieee80211softmac_probe_resp(struct ieee80211_probe_response **pkt,
+-	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
+-{
+-	u8 *data;
+-	/* Allocate Packet */
+-	(*pkt) = (struct ieee80211_probe_response *)ieee80211softmac_alloc_mgt(
+-		8 +		/* Timestamp */
+-		2 +		/* Beacon Interval */
+-		2 +		/* Capability Info */
+-				/* SSID IE */
+-		1 + 1 + IW_ESSID_MAX_SIZE +
+-		7 + 		/* FH Parameter Set */
+-		2 +		/* DS Parameter Set */
+-		8 +		/* CF Parameter Set */
+-		4 		/* IBSS Parameter Set */
+-	);
+-	if (unlikely((*pkt) == NULL))
+-		return 0;
+-	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_RESP, net->bssid, net->bssid);
+-	data = (u8 *)(*pkt)->info_element;
+-
+-	/* Return the packet size */
+-	return (data - (u8 *)(*pkt));
+-}
+-
+-
+-/* Sends a manangement packet
+- * FIXME: document the use of the arg parameter
+- * for _AUTH: (transaction #) | (status << 16)
+- */
+-int
+-ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
+-	void *ptrarg, u32 type, u32 arg)
+-{
+-	void *pkt = NULL;
+-	u32 pkt_size = 0;
+-	int encrypt_mpdu = 0;
+-
+-	switch(type) {
+-	case IEEE80211_STYPE_ASSOC_REQ:
+-		pkt_size = ieee80211softmac_assoc_req((struct ieee80211_assoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
+-		break;
+-	case IEEE80211_STYPE_REASSOC_REQ:
+-		pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
+-		break;
+-	case IEEE80211_STYPE_AUTH:
+-		pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu);
+-		break;
+-	case IEEE80211_STYPE_DISASSOC:
+-	case IEEE80211_STYPE_DEAUTH:
+-		pkt_size = ieee80211softmac_disassoc_deauth((struct ieee80211_disassoc **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, type, (u16)(arg & 0xFFFF));
+-		break;
+-	case IEEE80211_STYPE_PROBE_REQ:
+-		pkt_size = ieee80211softmac_probe_req((struct ieee80211_probe_request **)(&pkt), mac, (struct ieee80211softmac_essid *)ptrarg);
+-		break;
+-	case IEEE80211_STYPE_PROBE_RESP:
+-		pkt_size = ieee80211softmac_probe_resp((struct ieee80211_probe_response **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
+-		break;
+-	default:
+-		printkl(KERN_DEBUG PFX "Unsupported Management Frame type: %i\n", type);
+-		return -EINVAL;
+-	};
+-
+-	if(pkt_size == 0 || pkt == NULL) {
+-		printkl(KERN_DEBUG PFX "Error, packet is nonexistant or 0 length\n");
+-		return -ENOMEM;
+-	}
+-
+-	/* Send the packet to the ieee80211 layer for tx */
+-	/* we defined softmac->mgmt_xmit for this. Should we keep it
+-	 * as it is (that means we'd need to wrap this into a txb),
+-	 * modify the prototype (so it matches this function),
+-	 * or get rid of it alltogether?
+-	 * Does this work for you now?
+-	 */
+-	ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt,
+-		IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu);
+-
+-	kfree(pkt);
+-	return 0;
+-}
+-
+-/* Beacon handling */
+-int ieee80211softmac_handle_beacon(struct net_device *dev,
+-	struct ieee80211_beacon *beacon,
+-	struct ieee80211_network *network)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+-	/* This might race, but we don't really care and it's not worth
+-	 * adding heavyweight locking in this fastpath.
+-	 */
+-	if (mac->associnfo.associated) {
+-		if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
+-			ieee80211softmac_process_erp(mac, network->erp_value);
+-	}
+-
+-	return 0;
+-}
+-
+diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
+deleted file mode 100644
+index 07505ca..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_module.c
++++ /dev/null
+@@ -1,568 +0,0 @@
+-/*
+- * Contains some basic softmac functions along with module registration code etc.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- *                          Joseph Jezak <josejx at gentoo.org>
+- *                          Larry Finger <Larry.Finger at lwfinger.net>
+- *                          Danny van Dyk <kugelfang at gentoo.org>
+- *                          Michael Buesch <mbuesch at freenet.de>
+- *
+- * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-#include <linux/sort.h>
+-#include <linux/etherdevice.h>
+-
+-struct net_device *alloc_ieee80211softmac(int sizeof_priv)
+-{
+-	struct ieee80211softmac_device *softmac;
+-	struct net_device *dev;
+-
+-	dev = alloc_ieee80211(sizeof(*softmac) + sizeof_priv);
+-	if (!dev)
+-		return NULL;
+-	softmac = ieee80211_priv(dev);
+-	softmac->wq = create_freezeable_workqueue("softmac");
+-	if (!softmac->wq) {
+-		free_ieee80211(dev);
+-		return NULL;
+-	}
+-
+-	softmac->dev = dev;
+-	softmac->ieee = netdev_priv(dev);
+-	spin_lock_init(&softmac->lock);
+-
+-	softmac->ieee->handle_auth = ieee80211softmac_auth_resp;
+-	softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp;
+-	softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
+-	softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
+-	softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
+-	softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
+-	softmac->scaninfo = NULL;
+-
+-	softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+-
+-	/* TODO: initialise all the other callbacks in the ieee struct
+-	 *	 (once they're written)
+-	 */
+-
+-	INIT_LIST_HEAD(&softmac->auth_queue);
+-	INIT_LIST_HEAD(&softmac->network_list);
+-	INIT_LIST_HEAD(&softmac->events);
+-
+-	mutex_init(&softmac->associnfo.mutex);
+-	INIT_DELAYED_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work);
+-	INIT_DELAYED_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout);
+-	softmac->start_scan = ieee80211softmac_start_scan_implementation;
+-	softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
+-	softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
+-
+-	/* to start with, we can't send anything ... */
+-	netif_carrier_off(dev);
+-
+-	return dev;
+-}
+-EXPORT_SYMBOL_GPL(alloc_ieee80211softmac);
+-
+-/* Clears the pending work queue items, stops all scans, etc. */
+-void
+-ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
+-{
+-	unsigned long flags;
+-	struct ieee80211softmac_event *eventptr, *eventtmp;
+-	struct ieee80211softmac_auth_queue_item *authptr, *authtmp;
+-	struct ieee80211softmac_network *netptr, *nettmp;
+-
+-	ieee80211softmac_stop_scan(sm);
+-	ieee80211softmac_wait_for_scan(sm);
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-	sm->running = 0;
+-
+-	/* Free all pending assoc work items */
+-	cancel_delayed_work(&sm->associnfo.work);
+-
+-	/* Free all pending scan work items */
+-	if(sm->scaninfo != NULL)
+-		cancel_delayed_work(&sm->scaninfo->softmac_scan);
+-
+-	/* Free all pending auth work items */
+-	list_for_each_entry(authptr, &sm->auth_queue, list)
+-		cancel_delayed_work(&authptr->work);
+-
+-	/* delete all pending event calls and work items */
+-	list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list)
+-		cancel_delayed_work(&eventptr->work);
+-
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-	flush_workqueue(sm->wq);
+-
+-	/* now we should be save and no longer need locking... */
+-	spin_lock_irqsave(&sm->lock, flags);
+-	/* Free all pending auth work items */
+-	list_for_each_entry_safe(authptr, authtmp, &sm->auth_queue, list) {
+-		list_del(&authptr->list);
+-		kfree(authptr);
+-	}
+-
+-	/* delete all pending event calls and work items */
+-	list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) {
+-		list_del(&eventptr->list);
+-		kfree(eventptr);
+-	}
+-
+-	/* Free all networks */
+-	list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) {
+-		ieee80211softmac_del_network_locked(sm, netptr);
+-		if(netptr->challenge != NULL)
+-			kfree(netptr->challenge);
+-		kfree(netptr);
+-	}
+-
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_clear_pending_work);
+-
+-void free_ieee80211softmac(struct net_device *dev)
+-{
+-	struct ieee80211softmac_device *sm = ieee80211_priv(dev);
+-	ieee80211softmac_clear_pending_work(sm);
+-	kfree(sm->scaninfo);
+-	kfree(sm->wpa.IE);
+-	destroy_workqueue(sm->wq);
+-	free_ieee80211(dev);
+-}
+-EXPORT_SYMBOL_GPL(free_ieee80211softmac);
+-
+-static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *mac)
+-{
+-	struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
+-	/* I took out the sorting check, we're seperating by modulation now. */
+-	if (ri->count)
+-		return;
+-	/* otherwise assume we hav'em all! */
+-	if (mac->ieee->modulation & IEEE80211_CCK_MODULATION) {
+-		ri->rates[ri->count++] = IEEE80211_CCK_RATE_1MB;
+-		ri->rates[ri->count++] = IEEE80211_CCK_RATE_2MB;
+-		ri->rates[ri->count++] = IEEE80211_CCK_RATE_5MB;
+-		ri->rates[ri->count++] = IEEE80211_CCK_RATE_11MB;
+-	}
+-	if (mac->ieee->modulation & IEEE80211_OFDM_MODULATION) {
+-		ri->rates[ri->count++] = IEEE80211_OFDM_RATE_6MB;
+-		ri->rates[ri->count++] = IEEE80211_OFDM_RATE_9MB;
+-		ri->rates[ri->count++] = IEEE80211_OFDM_RATE_12MB;
+-		ri->rates[ri->count++] = IEEE80211_OFDM_RATE_18MB;
+-		ri->rates[ri->count++] = IEEE80211_OFDM_RATE_24MB;
+-		ri->rates[ri->count++] = IEEE80211_OFDM_RATE_36MB;
+-		ri->rates[ri->count++] = IEEE80211_OFDM_RATE_48MB;
+-		ri->rates[ri->count++] = IEEE80211_OFDM_RATE_54MB;
+-	}
+-}
+-
+-int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate)
+-{
+-	int search;
+-	u8 search_rate;
+-
+-	for (search = 0; search < ri->count; search++) {
+-		search_rate = ri->rates[search];
+-		search_rate &= ~IEEE80211_BASIC_RATE_MASK;
+-		if (rate == search_rate)
+-			return 1;
+-	}
+-
+-	return 0;
+-}
+-
+-u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_ratesinfo *ri, int basic_only)
+-{
+-	u8 user_rate = mac->txrates.user_rate;
+-	int i;
+-
+-	if (ri->count == 0)
+-		return IEEE80211_CCK_RATE_1MB;
+-
+-	for (i = ri->count - 1; i >= 0; i--) {
+-		u8 rate = ri->rates[i];
+-		if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK))
+-			continue;
+-		rate &= ~IEEE80211_BASIC_RATE_MASK;
+-		if (rate > user_rate)
+-			continue;
+-		if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
+-			return rate;
+-	}
+-
+-	/* If we haven't found a suitable rate by now, just trust the user */
+-	return user_rate;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate);
+-
+-void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
+-	u8 erp_value)
+-{
+-	int use_protection;
+-	int short_preamble;
+-	u32 changes = 0;
+-
+-	/* Barker preamble mode */
+-	short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0
+-			  && mac->associnfo.short_preamble_available) ? 1 : 0;
+-
+-	/* Protection needed? */
+-	use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
+-
+-	if (mac->bssinfo.short_preamble != short_preamble) {
+-		changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
+-		mac->bssinfo.short_preamble = short_preamble;
+-	}
+-
+-	if (mac->bssinfo.use_protection != use_protection) {
+-		changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
+-		mac->bssinfo.use_protection = use_protection;
+-	}
+-
+-	if (mac->bssinfo_change && changes)
+-		mac->bssinfo_change(mac->dev, changes);
+-}
+-
+-void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
+-{
+-	struct ieee80211softmac_txrates *txrates = &mac->txrates;
+-	u32 change = 0;
+-
+-	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+-	txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0);
+-
+-	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+-	txrates->default_fallback = lower_rate(mac, txrates->default_rate);
+-
+-	change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+-	txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1);
+-
+-	if (mac->txrates_change)
+-		mac->txrates_change(mac->dev, change);
+-
+-}
+-
+-void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac)
+-{
+-	struct ieee80211_device *ieee = mac->ieee;
+-	u32 change = 0;
+-	struct ieee80211softmac_txrates *txrates = &mac->txrates;
+-	struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo;
+-
+-	/* TODO: We need some kind of state machine to lower the default rates
+-	 *       if we loose too many packets.
+-	 */
+-	/* Change the default txrate to the highest possible value.
+-	 * The txrate machine will lower it, if it is too high.
+-	 */
+-	if (ieee->modulation & IEEE80211_OFDM_MODULATION)
+-		txrates->user_rate = IEEE80211_OFDM_RATE_24MB;
+-	else
+-		txrates->user_rate = IEEE80211_CCK_RATE_11MB;
+-
+-	txrates->default_rate = IEEE80211_CCK_RATE_1MB;
+-	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+-
+-	txrates->default_fallback = IEEE80211_CCK_RATE_1MB;
+-	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+-
+-	txrates->mcast_rate = IEEE80211_CCK_RATE_1MB;
+-	change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+-
+-	txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB;
+-	change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
+-
+-	if (mac->txrates_change)
+-		mac->txrates_change(mac->dev, change);
+-
+-	change = 0;
+-
+-	bssinfo->supported_rates.count = 0;
+-	memset(bssinfo->supported_rates.rates, 0,
+-		sizeof(bssinfo->supported_rates.rates));
+-	change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES;
+-
+-	bssinfo->short_preamble = 0;
+-	change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
+-
+-	bssinfo->use_protection = 0;
+-	change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
+-
+-	if (mac->bssinfo_change)
+-		mac->bssinfo_change(mac->dev, change);
+-
+-	mac->running = 1;
+-}
+-
+-void ieee80211softmac_start(struct net_device *dev)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+-	ieee80211softmac_start_check_rates(mac);
+-	ieee80211softmac_init_bss(mac);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_start);
+-
+-void ieee80211softmac_stop(struct net_device *dev)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+-	ieee80211softmac_clear_pending_work(mac);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_stop);
+-
+-void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-	memcpy(mac->ratesinfo.rates, rates, count);
+-	mac->ratesinfo.count = count;
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_set_rates);
+-
+-static u8 raise_rate(struct ieee80211softmac_device *mac, u8 rate)
+-{
+-	int i;
+-	struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
+-
+-	for (i=0; i<ri->count-1; i++) {
+-		if (ri->rates[i] == rate)
+-			return ri->rates[i+1];
+-	}
+-	/* I guess we can't go any higher... */
+-	return ri->rates[ri->count];
+-}
+-
+-u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta)
+-{
+-	int i;
+-	struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
+-
+-	for (i=delta; i<ri->count; i++) {
+-		if (ri->rates[i] == rate)
+-			return ri->rates[i-delta];
+-	}
+-	/* I guess we can't go any lower... */
+-	return ri->rates[0];
+-}
+-
+-static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac,
+-						 int amount)
+-{
+-	u8 default_rate = mac->txrates.default_rate;
+-	u8 default_fallback = mac->txrates.default_fallback;
+-	u32 changes = 0;
+-
+-	//TODO: This is highly experimental code.
+-	//      Maybe the dynamic rate selection does not work
+-	//      and it has to be removed again.
+-
+-printk("badness %d\n", mac->txrate_badness);
+-	mac->txrate_badness += amount;
+-	if (mac->txrate_badness <= -1000) {
+-		/* Very small badness. Try a faster bitrate. */
+-		default_rate = raise_rate(mac, default_rate);
+-		changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+-		default_fallback = get_fallback_rate(mac, default_rate);
+-		changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+-		mac->txrate_badness = 0;
+-printk("Bitrate raised to %u\n", default_rate);
+-	} else if (mac->txrate_badness >= 10000) {
+-		/* Very high badness. Try a slower bitrate. */
+-		default_rate = lower_rate(mac, default_rate);
+-		changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+-		default_fallback = get_fallback_rate(mac, default_rate);
+-		changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+-		mac->txrate_badness = 0;
+-printk("Bitrate lowered to %u\n", default_rate);
+-	}
+-
+-	mac->txrates.default_rate = default_rate;
+-	mac->txrates.default_fallback = default_fallback;
+-
+-	if (changes && mac->txrates_change)
+-		mac->txrates_change(mac->dev, changes);
+-}
+-
+-void ieee80211softmac_fragment_lost(struct net_device *dev,
+-				    u16 wl_seq)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-	ieee80211softmac_add_txrates_badness(mac, 1000);
+-	//TODO
+-
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_fragment_lost);
+-
+-static int rate_cmp(const void *a_, const void *b_) {
+-	u8 *a, *b;
+-	a = (u8*)a_;
+-	b = (u8*)b_;
+-	return ((*a & ~IEEE80211_BASIC_RATE_MASK) - (*b & ~IEEE80211_BASIC_RATE_MASK));
+-}
+-
+-/* Allocate a softmac network struct and fill it from a network */
+-struct ieee80211softmac_network *
+-ieee80211softmac_create_network(struct ieee80211softmac_device *mac,
+-	struct ieee80211_network *net)
+-{
+-	struct ieee80211softmac_network *softnet;
+-	softnet = kzalloc(sizeof(struct ieee80211softmac_network), GFP_ATOMIC);
+-	if(softnet == NULL)
+-		return NULL;
+-	memcpy(softnet->bssid, net->bssid, ETH_ALEN);
+-	softnet->channel = net->channel;
+-	softnet->essid.len = net->ssid_len;
+-	memcpy(softnet->essid.data, net->ssid, softnet->essid.len);
+-
+-	/* copy rates over */
+-	softnet->supported_rates.count = net->rates_len;
+-	memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len);
+-	memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len);
+-	softnet->supported_rates.count += net->rates_ex_len;
+-	sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL);
+-
+-	/* we save the ERP value because it is needed at association time, and
+-	 * many AP's do not include an ERP IE in the association response. */
+-	softnet->erp_value = net->erp_value;
+-
+-	softnet->capabilities = net->capability;
+-	return softnet;
+-}
+-
+-
+-/* Add a network to the list, while locked */
+-void
+-ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *add_net)
+-{
+-	struct ieee80211softmac_network *softmac_net;
+-
+-	list_for_each_entry(softmac_net, &mac->network_list, list) {
+-		if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
+-			return;
+-	}
+-	list_add(&(add_net->list), &mac->network_list);
+-}
+-
+-/* Add a network to the list, with locking */
+-void
+-ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *add_net)
+-{
+-	unsigned long flags;
+-	spin_lock_irqsave(&mac->lock, flags);
+-	ieee80211softmac_add_network_locked(mac, add_net);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-
+-/* Delete a network from the list, while locked*/
+-void
+-ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *del_net)
+-{
+-	list_del(&(del_net->list));
+-}
+-
+-/* Delete a network from the list with locking */
+-void
+-ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *del_net)
+-{
+-	unsigned long flags;
+-	spin_lock_irqsave(&mac->lock, flags);
+-	ieee80211softmac_del_network_locked(mac, del_net);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-/* Get a network from the list by MAC while locked */
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
+-	u8 *bssid)
+-{
+-	struct ieee80211softmac_network *softmac_net;
+-
+-	list_for_each_entry(softmac_net, &mac->network_list, list) {
+-		if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
+-			return softmac_net;
+-	}
+-	return NULL;
+-}
+-
+-/* Get a network from the list by BSSID with locking */
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_bssid(struct ieee80211softmac_device *mac,
+-	u8 *bssid)
+-{
+-	unsigned long flags;
+-	struct ieee80211softmac_network *softmac_net;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-	softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-	return softmac_net;
+-}
+-
+-/* Get a network from the list by ESSID while locked */
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_essid *essid)
+-{
+-	struct ieee80211softmac_network *softmac_net;
+-
+-	list_for_each_entry(softmac_net, &mac->network_list, list) {
+-		if (softmac_net->essid.len == essid->len &&
+-			!memcmp(softmac_net->essid.data, essid->data, essid->len))
+-			return softmac_net;
+-	}
+-	return NULL;
+-}
+-
+-/* Get a network from the list by ESSID with locking */
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_essid *essid)
+-{
+-	unsigned long flags;
+-	struct ieee80211softmac_network *softmac_net = NULL;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-	softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid);
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-	return softmac_net;
+-}
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Johannes Berg");
+-MODULE_AUTHOR("Joseph Jezak");
+-MODULE_AUTHOR("Larry Finger");
+-MODULE_AUTHOR("Danny van Dyk");
+-MODULE_AUTHOR("Michael Buesch");
+-MODULE_DESCRIPTION("802.11 software MAC");
+diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
+deleted file mode 100644
+index c43b189..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_priv.h
++++ /dev/null
+@@ -1,244 +0,0 @@
+-/*
+- * Internal softmac API definitions.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- *                          Joseph Jezak <josejx at gentoo.org>
+- *                          Larry Finger <Larry.Finger at lwfinger.net>
+- *                          Danny van Dyk <kugelfang at gentoo.org>
+- *                          Michael Buesch <mbuesch at freenet.de>
+- *
+- * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#ifndef IEEE80211SOFTMAC_PRIV_H_
+-#define IEEE80211SOFTMAC_PRIV_H_
+-
+-#include <net/ieee80211softmac.h>
+-#include <net/ieee80211softmac_wx.h>
+-#include <linux/kernel.h>
+-#include <linux/stringify.h>
+-
+-
+-#define PFX				"SoftMAC: "
+-
+-#ifdef assert
+-# undef assert
+-#endif
+-#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
+-#define assert(expr) \
+-	do {										\
+-		if (unlikely(!(expr))) {						\
+-		printkl(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", #expr,	\
+-			__FILE__, __LINE__, __FUNCTION__);				\
+-		}									\
+-	} while (0)
+-#else
+-#define assert(expr) do {} while (0)
+-#endif
+-
+-/* rate limited printk(). */
+-#ifdef printkl
+-# undef printkl
+-#endif
+-#define printkl(f, x...)  do { if (printk_ratelimit()) printk(f ,##x); } while (0)
+-/* rate limited printk() for debugging */
+-#ifdef dprintkl
+-# undef dprintkl
+-#endif
+-#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
+-# define dprintkl		printkl
+-#else
+-# define dprintkl(f, x...)	do { /* nothing */ } while (0)
+-#endif
+-
+-/* debugging printk() */
+-#ifdef dprintk
+-# undef dprintk
+-#endif
+-#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
+-# define dprintk(f, x...)  do { printk(f ,##x); } while (0)
+-#else
+-# define dprintk(f, x...)  do { /* nothing */ } while (0)
+-#endif
+-
+-/* private definitions and prototypes */
+-
+-/*** prototypes from _scan.c */
+-void ieee80211softmac_scan(struct work_struct *work);
+-/* for internal use if scanning is needed */
+-int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac);
+-void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac);
+-void ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *mac);
+-
+-/* for use by _module.c to assign to the callbacks */
+-int ieee80211softmac_start_scan_implementation(struct net_device *dev);
+-void ieee80211softmac_stop_scan_implementation(struct net_device *dev);
+-void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev);
+-
+-/*** Network prototypes from _module.c */
+-struct ieee80211softmac_network * ieee80211softmac_create_network(
+-	struct ieee80211softmac_device *mac, struct ieee80211_network *net);
+-void ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *net);
+-void ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *net);
+-void ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *net);
+-void ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_network *net);
+-struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid_locked(
+-	struct ieee80211softmac_device *mac, u8 *ea);
+-struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid(
+-	struct ieee80211softmac_device *mac, u8 *ea);
+-struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid_locked(
+-	struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len);
+-struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid(
+-	struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len);
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_essid *essid);
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
+-	struct ieee80211softmac_essid *essid);
+-
+-/* Rates related */
+-void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
+-	u8 erp_value);
+-int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate);
+-u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
+-void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac);
+-void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac);
+-static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
+-	return ieee80211softmac_lower_rate_delta(mac, rate, 1);
+-}
+-
+-static inline u8 get_fallback_rate(struct ieee80211softmac_device *mac, u8 rate)
+-{
+-	return ieee80211softmac_lower_rate_delta(mac, rate, 2);
+-}
+-
+-
+-/*** prototypes from _io.c */
+-int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
+-	void* ptrarg, u32 type, u32 arg);
+-int ieee80211softmac_handle_beacon(struct net_device *dev,
+-	struct ieee80211_beacon *beacon,
+-	struct ieee80211_network *network);
+-
+-/*** prototypes from _auth.c */
+-/* do these have to go into the public header? */
+-int ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net);
+-int ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, int reason);
+-
+-/* for use by _module.c to assign to the callbacks */
+-int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth);
+-int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth);
+-
+-/*** prototypes from _assoc.c */
+-void ieee80211softmac_assoc_work(struct work_struct *work);
+-int ieee80211softmac_handle_assoc_response(struct net_device * dev,
+-					   struct ieee80211_assoc_response * resp,
+-					   struct ieee80211_network * network);
+-int ieee80211softmac_handle_disassoc(struct net_device * dev,
+-				     struct ieee80211_disassoc * disassoc);
+-int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
+-					struct ieee80211_reassoc_request * reassoc);
+-void ieee80211softmac_assoc_timeout(struct work_struct *work);
+-void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason);
+-void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac);
+-
+-/* some helper functions */
+-static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm)
+-{
+-	return (sm->start_scan == ieee80211softmac_start_scan_implementation) &&
+-		(sm->stop_scan == ieee80211softmac_stop_scan_implementation) &&
+-		(sm->wait_for_scan == ieee80211softmac_wait_for_scan_implementation);
+-}
+-
+-static inline int ieee80211softmac_scan_sanity_check(struct ieee80211softmac_device *sm)
+-{
+-	return ((sm->start_scan != ieee80211softmac_start_scan_implementation) &&
+-		(sm->stop_scan != ieee80211softmac_stop_scan_implementation) &&
+-		(sm->wait_for_scan != ieee80211softmac_wait_for_scan_implementation)
+-		) || ieee80211softmac_scan_handlers_check_self(sm);
+-}
+-
+-#define IEEE80211SOFTMAC_PROBE_DELAY		HZ/50
+-#define IEEE80211SOFTMAC_WORKQUEUE_NAME_LEN	(17 + IFNAMSIZ)
+-
+-struct ieee80211softmac_network {
+-	struct list_head		list;	/* List */
+-	/* Network information copied from ieee80211_network */
+-	u8 bssid[ETH_ALEN];
+-	u8 channel;
+-	struct ieee80211softmac_essid essid;
+-
+-	struct ieee80211softmac_ratesinfo supported_rates;
+-
+-	/* SoftMAC specific */
+-	u16 authenticating:1,			/* Status Flags */
+-	    authenticated:1,
+-	    auth_desynced_once:1;
+-
+-	u8 erp_value;				/* Saved ERP value */
+-	u16 capabilities;			/* Capabilities bitfield */
+-	u8 challenge_len;			/* Auth Challenge length */
+-	char *challenge;			/* Challenge Text */
+-};
+-
+-/* structure used to keep track of networks we're auth'ing to */
+-struct ieee80211softmac_auth_queue_item {
+-	struct list_head		list;	/* List head */
+-	struct ieee80211softmac_network	*net;	/* Network to auth */
+-	struct ieee80211softmac_device	*mac;	/* SoftMAC device */
+-	u8 retry;				/* Retry limit */
+-	u8 state;				/* Auth State */
+-	struct delayed_work		work;	/* Work queue */
+-};
+-
+-/* scanning information */
+-struct ieee80211softmac_scaninfo {
+-	u8 current_channel_idx,
+-	   number_channels;
+-	struct ieee80211_channel *channels;
+-	u8 started:1,
+-	   stop:1;
+-	u8 skip_flags;
+-	struct completion finished;
+-	struct delayed_work softmac_scan;
+-	struct ieee80211softmac_device *mac;
+-};
+-
+-/* private event struct */
+-struct ieee80211softmac_event {
+-	struct list_head list;
+-	int event_type;
+-	void *event_context;
+-	struct delayed_work work;
+-	notify_function_ptr fun;
+-	void *context;
+-	struct ieee80211softmac_device *mac;
+-};
+-
+-void ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_context);
+-void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_context);
+-int ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
+-	int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask);
+-
+-void ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac);
+-
+-#endif /* IEEE80211SOFTMAC_PRIV_H_ */
+diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
+deleted file mode 100644
+index bfab8d7..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
++++ /dev/null
+@@ -1,254 +0,0 @@
+-/*
+- * Scanning routines.
+- *
+- * These are not exported because they're assigned to the function pointers.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- *                          Joseph Jezak <josejx at gentoo.org>
+- *                          Larry Finger <Larry.Finger at lwfinger.net>
+- *                          Danny van Dyk <kugelfang at gentoo.org>
+- *                          Michael Buesch <mbuesch at freenet.de>
+- *
+- * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include <linux/completion.h>
+-#include "ieee80211softmac_priv.h"
+-
+-/* internal, use to trigger scanning if needed.
+- * Returns -EBUSY if already scanning,
+- * result of start_scan otherwise */
+-int
+-ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
+-{
+-	unsigned long flags;
+-	int ret;
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-	if (sm->scanning)
+-	{
+-		spin_unlock_irqrestore(&sm->lock, flags);
+-		return -EINPROGRESS;
+-	}
+-	sm->scanning = 1;
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-
+-	ret = sm->start_scan(sm->dev);
+-	if (ret) {
+-		spin_lock_irqsave(&sm->lock, flags);
+-		sm->scanning = 0;
+-		spin_unlock_irqrestore(&sm->lock, flags);
+-	}
+-	return ret;
+-}
+-
+-void
+-ieee80211softmac_stop_scan(struct ieee80211softmac_device *sm)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-
+-	if (!sm->scanning) {
+-		spin_unlock_irqrestore(&sm->lock, flags);
+-		return;
+-	}
+-
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-	sm->stop_scan(sm->dev);
+-}
+-
+-void
+-ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-
+-	if (!sm->scanning) {
+-		spin_unlock_irqrestore(&sm->lock, flags);
+-		return;
+-	}
+-
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-	sm->wait_for_scan(sm->dev);
+-}
+-
+-
+-/* internal scanning implementation follows */
+-void ieee80211softmac_scan(struct work_struct *work)
+-{
+-	int invalid_channel;
+-	u8 current_channel_idx;
+-	struct ieee80211softmac_scaninfo *si =
+-		container_of(work, struct ieee80211softmac_scaninfo,
+-			     softmac_scan.work);
+-	struct ieee80211softmac_device *sm = si->mac;
+-	unsigned long flags;
+-
+-	while (!(si->stop) && (si->current_channel_idx < si->number_channels)) {
+-		current_channel_idx = si->current_channel_idx;
+-		si->current_channel_idx++; /* go to the next channel */
+-
+-		invalid_channel = (si->skip_flags & si->channels[current_channel_idx].flags);
+-
+-		if (!invalid_channel) {
+-			sm->set_channel(sm->dev, si->channels[current_channel_idx].channel);
+-			// FIXME make this user configurable (active/passive)
+-			if(ieee80211softmac_send_mgt_frame(sm, NULL, IEEE80211_STYPE_PROBE_REQ, 0))
+-				printkl(KERN_DEBUG PFX "Sending Probe Request Failed\n");
+-
+-			/* also send directed management frame for the network we're looking for */
+-			// TODO: is this if correct, or should we do this only if scanning from assoc request?
+-			if (sm->associnfo.req_essid.len)
+-				ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
+-
+-			spin_lock_irqsave(&sm->lock, flags);
+-			if (unlikely(!sm->running)) {
+-				/* Prevent reschedule on workqueue flush */
+-				spin_unlock_irqrestore(&sm->lock, flags);
+-				break;
+-			}
+-			queue_delayed_work(sm->wq, &si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
+-			spin_unlock_irqrestore(&sm->lock, flags);
+-			return;
+-		} else {
+-			dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
+-		}
+-	}
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-	cancel_delayed_work(&si->softmac_scan);
+-	si->started = 0;
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-
+-	dprintk(PFX "Scanning finished: scanned %d channels starting with channel %d\n",
+-		     sm->scaninfo->number_channels, sm->scaninfo->channels[0].channel);
+-	ieee80211softmac_scan_finished(sm);
+-	complete_all(&sm->scaninfo->finished);
+-}
+-
+-static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee80211softmac_device *mac)
+-{
+-	/* ugh. can we call this without having the spinlock held? */
+-	struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC);
+-	if (unlikely(!info))
+-		return NULL;
+-	INIT_DELAYED_WORK(&info->softmac_scan, ieee80211softmac_scan);
+-	info->mac = mac;
+-	init_completion(&info->finished);
+-	return info;
+-}
+-
+-int ieee80211softmac_start_scan_implementation(struct net_device *dev)
+-{
+-	struct ieee80211softmac_device *sm = ieee80211_priv(dev);
+-	unsigned long flags;
+-
+-	if (!(dev->flags & IFF_UP))
+-		return -ENODEV;
+-
+-	assert(ieee80211softmac_scan_handlers_check_self(sm));
+-	if (!ieee80211softmac_scan_handlers_check_self(sm))
+-		return -EINVAL;
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-	/* it looks like we need to hold the lock here
+-	 * to make sure we don't allocate two of these... */
+-	if (unlikely(!sm->scaninfo))
+-		sm->scaninfo = allocate_scaninfo(sm);
+-	if (unlikely(!sm->scaninfo)) {
+-		spin_unlock_irqrestore(&sm->lock, flags);
+-		return -ENOMEM;
+-	}
+-
+-	sm->scaninfo->skip_flags = IEEE80211_CH_INVALID;
+-	if (0 /* not scanning in IEEE802.11b */)//TODO
+-		sm->scaninfo->skip_flags |= IEEE80211_CH_B_ONLY;
+-	if (0 /* IEEE802.11a */) {//TODO
+-		sm->scaninfo->channels = sm->ieee->geo.a;
+-		sm->scaninfo->number_channels = sm->ieee->geo.a_channels;
+-	} else {
+-		sm->scaninfo->channels = sm->ieee->geo.bg;
+-		sm->scaninfo->number_channels = sm->ieee->geo.bg_channels;
+-	}
+-	sm->scaninfo->current_channel_idx = 0;
+-	sm->scaninfo->started = 1;
+-	sm->scaninfo->stop = 0;
+-	INIT_COMPLETION(sm->scaninfo->finished);
+-	queue_delayed_work(sm->wq, &sm->scaninfo->softmac_scan, 0);
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-	return 0;
+-}
+-
+-void ieee80211softmac_stop_scan_implementation(struct net_device *dev)
+-{
+-	struct ieee80211softmac_device *sm = ieee80211_priv(dev);
+-	unsigned long flags;
+-
+-	assert(ieee80211softmac_scan_handlers_check_self(sm));
+-	if (!ieee80211softmac_scan_handlers_check_self(sm))
+-		return;
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-	assert(sm->scaninfo != NULL);
+-	if (sm->scaninfo) {
+-		if (sm->scaninfo->started)
+-			sm->scaninfo->stop = 1;
+-		else
+-			complete_all(&sm->scaninfo->finished);
+-	}
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-}
+-
+-void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev)
+-{
+-	struct ieee80211softmac_device *sm = ieee80211_priv(dev);
+-	unsigned long flags;
+-
+-	assert(ieee80211softmac_scan_handlers_check_self(sm));
+-	if (!ieee80211softmac_scan_handlers_check_self(sm))
+-		return;
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-	if (!sm->scaninfo->started) {
+-		spin_unlock_irqrestore(&sm->lock, flags);
+-		return;
+-	}
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-	wait_for_completion(&sm->scaninfo->finished);
+-}
+-
+-/* this is what drivers (that do scanning) call when they're done */
+-void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-	sm->scanning = 0;
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-
+-	if (sm->associnfo.bssvalid) {
+-		struct ieee80211softmac_network *net;
+-
+-		net = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
+-		if (net)
+-			sm->set_channel(sm->dev, net->channel);
+-	}
+-	ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
+diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
+deleted file mode 100644
+index e01b59a..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
++++ /dev/null
+@@ -1,508 +0,0 @@
+-/*
+- * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- *                          Joseph Jezak <josejx at gentoo.org>
+- *                          Larry Finger <Larry.Finger at lwfinger.net>
+- *                          Danny van Dyk <kugelfang at gentoo.org>
+- *                          Michael Buesch <mbuesch at freenet.de>
+- *
+- * 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-#include <net/iw_handler.h>
+-/* for is_broadcast_ether_addr and is_zero_ether_addr */
+-#include <linux/etherdevice.h>
+-
+-int
+-ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
+-				 struct iw_request_info *info,
+-				 union iwreq_data *data,
+-				 char *extra)
+-{
+-	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+-	return ieee80211softmac_start_scan(sm);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
+-
+-
+-/* if we're still scanning, return -EAGAIN so that userspace tools
+- * can get the complete scan results, otherwise return 0. */
+-int
+-ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
+-				     struct iw_request_info *info,
+-				     union iwreq_data *data,
+-				     char *extra)
+-{
+-	unsigned long flags;
+-	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+-
+-	spin_lock_irqsave(&sm->lock, flags);
+-	if (sm->scanning) {
+-		spin_unlock_irqrestore(&sm->lock, flags);
+-		return -EAGAIN;
+-	}
+-	spin_unlock_irqrestore(&sm->lock, flags);
+-	return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
+-
+-int
+-ieee80211softmac_wx_set_essid(struct net_device *net_dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *data,
+-			      char *extra)
+-{
+-	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+-	struct ieee80211softmac_auth_queue_item *authptr;
+-	int length = 0;
+-	DECLARE_MAC_BUF(mac);
+-
+-check_assoc_again:
+-	mutex_lock(&sm->associnfo.mutex);
+-	if((sm->associnfo.associating || sm->associnfo.associated) &&
+-	   (data->essid.flags && data->essid.length)) {
+-		dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
+-		/* Cancel assoc work */
+-		cancel_delayed_work(&sm->associnfo.work);
+-		/* We don't have to do this, but it's a little cleaner */
+-		list_for_each_entry(authptr, &sm->auth_queue, list)
+-			cancel_delayed_work(&authptr->work);
+-		sm->associnfo.bssvalid = 0;
+-		sm->associnfo.bssfixed = 0;
+-		sm->associnfo.associating = 0;
+-		sm->associnfo.associated = 0;
+-		/* We must unlock to avoid deadlocks with the assoc workqueue
+-		 * on the associnfo.mutex */
+-		mutex_unlock(&sm->associnfo.mutex);
+-		flush_workqueue(sm->wq);
+-		/* Avoid race! Check assoc status again. Maybe someone started an
+-		 * association while we flushed. */
+-		goto check_assoc_again;
+-	}
+-
+-	sm->associnfo.static_essid = 0;
+-	sm->associnfo.assoc_wait = 0;
+-
+-	if (data->essid.flags && data->essid.length) {
+-		length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
+-		if (length) {
+-			memcpy(sm->associnfo.req_essid.data, extra, length);
+-			sm->associnfo.static_essid = 1;
+-		}
+-	}
+-
+-	/* set our requested ESSID length.
+-	 * If applicable, we have already copied the data in */
+-	sm->associnfo.req_essid.len = length;
+-
+-	sm->associnfo.associating = 1;
+-	/* queue lower level code to do work (if necessary) */
+-	queue_delayed_work(sm->wq, &sm->associnfo.work, 0);
+-
+-	mutex_unlock(&sm->associnfo.mutex);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
+-
+-int
+-ieee80211softmac_wx_get_essid(struct net_device *net_dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *data,
+-			      char *extra)
+-{
+-	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+-
+-	mutex_lock(&sm->associnfo.mutex);
+-	/* If all fails, return ANY (empty) */
+-	data->essid.length = 0;
+-	data->essid.flags = 0;  /* active */
+-
+-	/* If we have a statically configured ESSID then return it */
+-	if (sm->associnfo.static_essid) {
+-		data->essid.length = sm->associnfo.req_essid.len;
+-		data->essid.flags = 1;  /* active */
+-		memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
+-		dprintk(KERN_INFO PFX "Getting essid from req_essid\n");
+-	} else if (sm->associnfo.associated || sm->associnfo.associating) {
+-	/* If we're associating/associated, return that */
+-		data->essid.length = sm->associnfo.associate_essid.len;
+-		data->essid.flags = 1;  /* active */
+-		memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
+-		dprintk(KERN_INFO PFX "Getting essid from associate_essid\n");
+-	}
+-	mutex_unlock(&sm->associnfo.mutex);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
+-
+-int
+-ieee80211softmac_wx_set_rate(struct net_device *net_dev,
+-			     struct iw_request_info *info,
+-			     union iwreq_data *data,
+-			     char *extra)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+-	struct ieee80211_device *ieee = mac->ieee;
+-	unsigned long flags;
+-	s32 in_rate = data->bitrate.value;
+-	u8 rate;
+-	int is_ofdm = 0;
+-	int err = -EINVAL;
+-
+-	if (in_rate == -1) {
+-		if (ieee->modulation & IEEE80211_OFDM_MODULATION)
+-			in_rate = 24000000;
+-		else
+-			in_rate = 11000000;
+-	}
+-
+-	switch (in_rate) {
+-	case 1000000:
+-		rate = IEEE80211_CCK_RATE_1MB;
+-		break;
+-	case 2000000:
+-		rate = IEEE80211_CCK_RATE_2MB;
+-		break;
+-	case 5500000:
+-		rate = IEEE80211_CCK_RATE_5MB;
+-		break;
+-	case 11000000:
+-		rate = IEEE80211_CCK_RATE_11MB;
+-		break;
+-	case 6000000:
+-		rate = IEEE80211_OFDM_RATE_6MB;
+-		is_ofdm = 1;
+-		break;
+-	case 9000000:
+-		rate = IEEE80211_OFDM_RATE_9MB;
+-		is_ofdm = 1;
+-		break;
+-	case 12000000:
+-		rate = IEEE80211_OFDM_RATE_12MB;
+-		is_ofdm = 1;
+-		break;
+-	case 18000000:
+-		rate = IEEE80211_OFDM_RATE_18MB;
+-		is_ofdm = 1;
+-		break;
+-	case 24000000:
+-		rate = IEEE80211_OFDM_RATE_24MB;
+-		is_ofdm = 1;
+-		break;
+-	case 36000000:
+-		rate = IEEE80211_OFDM_RATE_36MB;
+-		is_ofdm = 1;
+-		break;
+-	case 48000000:
+-		rate = IEEE80211_OFDM_RATE_48MB;
+-		is_ofdm = 1;
+-		break;
+-	case 54000000:
+-		rate = IEEE80211_OFDM_RATE_54MB;
+-		is_ofdm = 1;
+-		break;
+-	default:
+-		goto out;
+-	}
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-
+-	/* Check if correct modulation for this PHY. */
+-	if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
+-		goto out_unlock;
+-
+-	mac->txrates.user_rate = rate;
+-	ieee80211softmac_recalc_txrates(mac);
+-	err = 0;
+-
+-out_unlock:
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-out:
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
+-
+-int
+-ieee80211softmac_wx_get_rate(struct net_device *net_dev,
+-			     struct iw_request_info *info,
+-			     union iwreq_data *data,
+-			     char *extra)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+-	unsigned long flags;
+-	int err = -EINVAL;
+-
+-	spin_lock_irqsave(&mac->lock, flags);
+-
+-	if (unlikely(!mac->running)) {
+-		err = -ENODEV;
+-		goto out_unlock;
+-	}
+-
+-	switch (mac->txrates.default_rate) {
+-	case IEEE80211_CCK_RATE_1MB:
+-		data->bitrate.value = 1000000;
+-		break;
+-	case IEEE80211_CCK_RATE_2MB:
+-		data->bitrate.value = 2000000;
+-		break;
+-	case IEEE80211_CCK_RATE_5MB:
+-		data->bitrate.value = 5500000;
+-		break;
+-	case IEEE80211_CCK_RATE_11MB:
+-		data->bitrate.value = 11000000;
+-		break;
+-	case IEEE80211_OFDM_RATE_6MB:
+-		data->bitrate.value = 6000000;
+-		break;
+-	case IEEE80211_OFDM_RATE_9MB:
+-		data->bitrate.value = 9000000;
+-		break;
+-	case IEEE80211_OFDM_RATE_12MB:
+-		data->bitrate.value = 12000000;
+-		break;
+-	case IEEE80211_OFDM_RATE_18MB:
+-		data->bitrate.value = 18000000;
+-		break;
+-	case IEEE80211_OFDM_RATE_24MB:
+-		data->bitrate.value = 24000000;
+-		break;
+-	case IEEE80211_OFDM_RATE_36MB:
+-		data->bitrate.value = 36000000;
+-		break;
+-	case IEEE80211_OFDM_RATE_48MB:
+-		data->bitrate.value = 48000000;
+-		break;
+-	case IEEE80211_OFDM_RATE_54MB:
+-		data->bitrate.value = 54000000;
+-		break;
+-	default:
+-		assert(0);
+-		goto out_unlock;
+-	}
+-	err = 0;
+-out_unlock:
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
+-
+-int
+-ieee80211softmac_wx_get_wap(struct net_device *net_dev,
+-			    struct iw_request_info *info,
+-			    union iwreq_data *data,
+-			    char *extra)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+-	int err = 0;
+-
+-	mutex_lock(&mac->associnfo.mutex);
+-	if (mac->associnfo.bssvalid)
+-		memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
+-	else
+-		memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
+-	data->ap_addr.sa_family = ARPHRD_ETHER;
+-	mutex_unlock(&mac->associnfo.mutex);
+-
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
+-
+-int
+-ieee80211softmac_wx_set_wap(struct net_device *net_dev,
+-			    struct iw_request_info *info,
+-			    union iwreq_data *data,
+-			    char *extra)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+-
+-	/* sanity check */
+-	if (data->ap_addr.sa_family != ARPHRD_ETHER) {
+-		return -EINVAL;
+-	}
+-
+-	mutex_lock(&mac->associnfo.mutex);
+-	if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
+-		/* the bssid we have is not to be fixed any longer,
+-		 * and we should reassociate to the best AP. */
+-		mac->associnfo.bssfixed = 0;
+-		/* force reassociation */
+-		mac->associnfo.bssvalid = 0;
+-		if (mac->associnfo.associated)
+-			queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+-	} else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
+-		/* the bssid we have is no longer fixed */
+-		mac->associnfo.bssfixed = 0;
+-	} else {
+-		if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
+-			if (mac->associnfo.associating || mac->associnfo.associated) {
+-			/* bssid unchanged and associated or associating - just return */
+-				goto out;
+-			}
+-		} else {
+-			/* copy new value in data->ap_addr.sa_data to bssid */
+-			memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
+-		}
+-		/* tell the other code that this bssid should be used no matter what */
+-		mac->associnfo.bssfixed = 1;
+-		/* queue associate if new bssid or (old one again and not associated) */
+-		queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+-	}
+-
+- out:
+-	mutex_unlock(&mac->associnfo.mutex);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
+-
+-int
+-ieee80211softmac_wx_set_genie(struct net_device *dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *wrqu,
+-			      char *extra)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	unsigned long flags;
+-	int err = 0;
+-	char *buf;
+-	int i;
+-
+-	mutex_lock(&mac->associnfo.mutex);
+-	spin_lock_irqsave(&mac->lock, flags);
+-	/* bleh. shouldn't be locked for that kmalloc... */
+-
+-	if (wrqu->data.length) {
+-		if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
+-			/* this is an IE, so the length must be
+-			 * correct. Is it possible though that
+-			 * more than one IE is passed in?
+-			 */
+-			err = -EINVAL;
+-			goto out;
+-		}
+-		if (mac->wpa.IEbuflen <= wrqu->data.length) {
+-			buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
+-			if (!buf) {
+-				err = -ENOMEM;
+-				goto out;
+-			}
+-			kfree(mac->wpa.IE);
+-			mac->wpa.IE = buf;
+-			mac->wpa.IEbuflen = wrqu->data.length;
+-		}
+-		memcpy(mac->wpa.IE, extra, wrqu->data.length);
+-		dprintk(KERN_INFO PFX "generic IE set to ");
+-		for (i=0;i<wrqu->data.length;i++)
+-			dprintk("%.2x", (u8)mac->wpa.IE[i]);
+-		dprintk("\n");
+-		mac->wpa.IElen = wrqu->data.length;
+-	} else {
+-		kfree(mac->wpa.IE);
+-		mac->wpa.IE = NULL;
+-		mac->wpa.IElen = 0;
+-		mac->wpa.IEbuflen = 0;
+-	}
+-
+- out:
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-	mutex_unlock(&mac->associnfo.mutex);
+-
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
+-
+-int
+-ieee80211softmac_wx_get_genie(struct net_device *dev,
+-			      struct iw_request_info *info,
+-			      union iwreq_data *wrqu,
+-			      char *extra)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	unsigned long flags;
+-	int err = 0;
+-	int space = wrqu->data.length;
+-
+-	mutex_lock(&mac->associnfo.mutex);
+-	spin_lock_irqsave(&mac->lock, flags);
+-
+-	wrqu->data.length = 0;
+-
+-	if (mac->wpa.IE && mac->wpa.IElen) {
+-		wrqu->data.length = mac->wpa.IElen;
+-		if (mac->wpa.IElen <= space)
+-			memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
+-		else
+-			err = -E2BIG;
+-	}
+-	spin_unlock_irqrestore(&mac->lock, flags);
+-	mutex_unlock(&mac->associnfo.mutex);
+-
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
+-
+-int
+-ieee80211softmac_wx_set_mlme(struct net_device *dev,
+-			     struct iw_request_info *info,
+-			     union iwreq_data *wrqu,
+-			     char *extra)
+-{
+-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-	struct iw_mlme *mlme = (struct iw_mlme *)extra;
+-	u16 reason = mlme->reason_code;
+-	struct ieee80211softmac_network *net;
+-	int err = -EINVAL;
+-
+-	mutex_lock(&mac->associnfo.mutex);
+-
+-	if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
+-		printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
+-		goto out;
+-	}
+-
+-	switch (mlme->cmd) {
+-	case IW_MLME_DEAUTH:
+-		net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
+-		if (!net) {
+-			printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
+-			goto out;
+-		}
+-		err =  ieee80211softmac_deauth_req(mac, net, reason);
+-		goto out;
+-	case IW_MLME_DISASSOC:
+-		ieee80211softmac_send_disassoc_req(mac, reason);
+-		mac->associnfo.associated = 0;
+-		mac->associnfo.associating = 0;
+-		err = 0;
+-		goto out;
+-	default:
+-		err = -EOPNOTSUPP;
+-	}
+-
+-out:
+-	mutex_unlock(&mac->associnfo.mutex);
+-
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index 0d10950..f2b5270 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -243,6 +243,23 @@ void build_ehash_secret(void)
+ }
+ EXPORT_SYMBOL(build_ehash_secret);
+ 
++static inline int inet_netns_ok(struct net *net, int protocol)
++{
++	int hash;
++	struct net_protocol *ipprot;
++
++	if (net == &init_net)
++		return 1;
++
++	hash = protocol & (MAX_INET_PROTOS - 1);
++	ipprot = rcu_dereference(inet_protos[hash]);
++
++	if (ipprot == NULL)
++		/* raw IP is OK */
++		return 1;
++	return ipprot->netns_ok;
++}
++
+ /*
+  *	Create an inet socket.
+  */
+@@ -259,9 +276,6 @@ static int inet_create(struct net *net, struct socket *sock, int protocol)
+ 	int try_loading_module = 0;
+ 	int err;
+ 
+-	if (net != &init_net)
+-		return -EAFNOSUPPORT;
+-
+ 	if (sock->type != SOCK_RAW &&
+ 	    sock->type != SOCK_DGRAM &&
+ 	    !inet_ehash_secret)
+@@ -320,6 +334,10 @@ lookup_protocol:
+ 	if (answer->capability > 0 && !capable(answer->capability))
+ 		goto out_rcu_unlock;
+ 
++	err = -EAFNOSUPPORT;
++	if (!inet_netns_ok(net, protocol))
++		goto out_rcu_unlock;
++
+ 	sock->ops = answer->ops;
+ 	answer_prot = answer->prot;
+ 	answer_no_check = answer->no_check;
+@@ -446,7 +464,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 	if (addr_len < sizeof(struct sockaddr_in))
+ 		goto out;
+ 
+-	chk_addr_ret = inet_addr_type(&init_net, addr->sin_addr.s_addr);
++	chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+ 
+ 	/* Not specified by any standard per-se, however it breaks too
+ 	 * many applications when removed.  It is unfortunate since
+@@ -784,6 +802,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ {
+ 	struct sock *sk = sock->sk;
+ 	int err = 0;
++	struct net *net = sock_net(sk);
+ 
+ 	switch (cmd) {
+ 		case SIOCGSTAMP:
+@@ -795,12 +814,12 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ 		case SIOCADDRT:
+ 		case SIOCDELRT:
+ 		case SIOCRTMSG:
+-			err = ip_rt_ioctl(sk->sk_net, cmd, (void __user *)arg);
++			err = ip_rt_ioctl(net, cmd, (void __user *)arg);
+ 			break;
+ 		case SIOCDARP:
+ 		case SIOCGARP:
+ 		case SIOCSARP:
+-			err = arp_ioctl(sk->sk_net, cmd, (void __user *)arg);
++			err = arp_ioctl(net, cmd, (void __user *)arg);
+ 			break;
+ 		case SIOCGIFADDR:
+ 		case SIOCSIFADDR:
+@@ -813,7 +832,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ 		case SIOCSIFPFLAGS:
+ 		case SIOCGIFPFLAGS:
+ 		case SIOCSIFFLAGS:
+-			err = devinet_ioctl(cmd, (void __user *)arg);
++			err = devinet_ioctl(net, cmd, (void __user *)arg);
+ 			break;
+ 		default:
+ 			if (sk->sk_prot->ioctl)
+@@ -1058,8 +1077,8 @@ static int inet_sk_reselect_saddr(struct sock *sk)
+ 
+ 	if (sysctl_ip_dynaddr > 1) {
+ 		printk(KERN_INFO "%s(): shifting inet->"
+-				 "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
+-		       __FUNCTION__,
++				 "saddr from " NIPQUAD_FMT " to " NIPQUAD_FMT "\n",
++		       __func__,
+ 		       NIPQUAD(old_saddr),
+ 		       NIPQUAD(new_saddr));
+ 	}
+@@ -1113,7 +1132,7 @@ int inet_sk_rebuild_header(struct sock *sk)
+ 	};
+ 
+ 	security_sk_classify_flow(sk, &fl);
+-	err = ip_route_output_flow(&init_net, &rt, &fl, sk, 0);
++	err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0);
+ }
+ 	if (!err)
+ 		sk_setup_caps(sk, &rt->u.dst);
+@@ -1231,6 +1250,29 @@ out:
+ 	return segs;
+ }
+ 
++int inet_ctl_sock_create(struct sock **sk, unsigned short family,
++			 unsigned short type, unsigned char protocol,
++			 struct net *net)
++{
++	struct socket *sock;
++	int rc = sock_create_kern(family, type, protocol, &sock);
++
++	if (rc == 0) {
++		*sk = sock->sk;
++		(*sk)->sk_allocation = GFP_ATOMIC;
++		/*
++		 * Unhash it so that IP input processing does not even see it,
++		 * we do not wish this socket to see incoming packets.
++		 */
++		(*sk)->sk_prot->unhash(*sk);
++
++		sk_change_net(*sk, net);
++	}
++	return rc;
++}
++
++EXPORT_SYMBOL_GPL(inet_ctl_sock_create);
++
+ unsigned long snmp_fold_field(void *mib[], int offt)
+ {
+ 	unsigned long res = 0;
+@@ -1283,17 +1325,20 @@ static struct net_protocol tcp_protocol = {
+ 	.gso_send_check = tcp_v4_gso_send_check,
+ 	.gso_segment =	tcp_tso_segment,
+ 	.no_policy =	1,
++	.netns_ok =	1,
+ };
+ 
+ static struct net_protocol udp_protocol = {
+ 	.handler =	udp_rcv,
+ 	.err_handler =	udp_err,
+ 	.no_policy =	1,
++	.netns_ok =	1,
+ };
+ 
+ static struct net_protocol icmp_protocol = {
+ 	.handler =	icmp_rcv,
+ 	.no_policy =	1,
++	.netns_ok =	1,
+ };
+ 
+ static int __init init_ipv4_mibs(void)
+@@ -1414,7 +1459,7 @@ static int __init inet_init(void)
+ 
+ 	ip_init();
+ 
+-	tcp_v4_init(&inet_family_ops);
++	tcp_v4_init();
+ 
+ 	/* Setup TCP slab cache for open requests. */
+ 	tcp_init();
+@@ -1429,7 +1474,8 @@ static int __init inet_init(void)
+ 	 *	Set the ICMP layer up
+ 	 */
+ 
+-	icmp_init(&inet_family_ops);
++	if (icmp_init() < 0)
++		panic("Failed to create the ICMP control socket.\n");
+ 
+ 	/*
+ 	 *	Initialise the multicast router
+diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
+index 8e17f65..68b72a7 100644
+--- a/net/ipv4/arp.c
++++ b/net/ipv4/arp.c
+@@ -242,7 +242,7 @@ static int arp_constructor(struct neighbour *neigh)
+ 		return -EINVAL;
+ 	}
+ 
+-	neigh->type = inet_addr_type(&init_net, addr);
++	neigh->type = inet_addr_type(dev_net(dev), addr);
+ 
+ 	parms = in_dev->arp_parms;
+ 	__neigh_parms_put(neigh->parms);
+@@ -341,14 +341,14 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
+ 	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
+ 	default:
+ 	case 0:		/* By default announce any local IP */
+-		if (skb && inet_addr_type(&init_net, 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 */
+ 		if (!skb)
+ 			break;
+ 		saddr = ip_hdr(skb)->saddr;
+-		if (inet_addr_type(&init_net, saddr) == RTN_LOCAL) {
++		if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) {
+ 			/* saddr should be known to target */
+ 			if (inet_addr_onlink(in_dev, target, saddr))
+ 				break;
+@@ -424,7 +424,7 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
+ 	int flag = 0;
+ 	/*unsigned long now; */
+ 
+-	if (ip_route_output_key(&init_net, &rt, &fl) < 0)
++	if (ip_route_output_key(dev_net(dev), &rt, &fl) < 0)
+ 		return 1;
+ 	if (rt->u.dst.dev != dev) {
+ 		NET_INC_STATS_BH(LINUX_MIB_ARPFILTER);
+@@ -475,9 +475,9 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb)
+ 		return 1;
+ 	}
+ 
+-	paddr = ((struct rtable*)skb->dst)->rt_gateway;
++	paddr = skb->rtable->rt_gateway;
+ 
+-	if (arp_set_predefined(inet_addr_type(&init_net, 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);
+@@ -570,14 +570,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
+ 	 *	Allocate a buffer
+ 	 */
+ 
+-	skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
+-				+ LL_RESERVED_SPACE(dev), GFP_ATOMIC);
++	skb = alloc_skb(arp_hdr_len(dev) + LL_RESERVED_SPACE(dev), GFP_ATOMIC);
+ 	if (skb == NULL)
+ 		return NULL;
+ 
+ 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
+ 	skb_reset_network_header(skb);
+-	arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4));
++	arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev));
+ 	skb->dev = dev;
+ 	skb->protocol = htons(ETH_P_ARP);
+ 	if (src_hw == NULL)
+@@ -710,6 +709,7 @@ static int arp_process(struct sk_buff *skb)
+ 	u16 dev_type = dev->type;
+ 	int addr_type;
+ 	struct neighbour *n;
++	struct net *net = dev_net(dev);
+ 
+ 	/* arp_rcv below verifies the ARP header and verifies the device
+ 	 * is ARP'able.
+@@ -805,7 +805,7 @@ static int arp_process(struct sk_buff *skb)
+ 	/* Special case: IPv4 duplicate address detection packet (RFC2131) */
+ 	if (sip == 0) {
+ 		if (arp->ar_op == htons(ARPOP_REQUEST) &&
+-		    inet_addr_type(&init_net, tip) == RTN_LOCAL &&
++		    inet_addr_type(net, tip) == RTN_LOCAL &&
+ 		    !arp_ignore(in_dev, sip, tip))
+ 			arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
+ 				 dev->dev_addr, sha);
+@@ -815,7 +815,7 @@ static int arp_process(struct sk_buff *skb)
+ 	if (arp->ar_op == htons(ARPOP_REQUEST) &&
+ 	    ip_route_input(skb, tip, sip, 0, dev) == 0) {
+ 
+-		rt = (struct rtable*)skb->dst;
++		rt = skb->rtable;
+ 		addr_type = rt->rt_type;
+ 
+ 		if (addr_type == RTN_LOCAL) {
+@@ -835,7 +835,7 @@ static int arp_process(struct sk_buff *skb)
+ 			goto out;
+ 		} else if (IN_DEV_FORWARD(in_dev)) {
+ 			    if (addr_type == RTN_UNICAST  && rt->u.dst.dev != dev &&
+-			     (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &init_net, &tip, dev, 0))) {
++			     (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
+ 				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
+ 				if (n)
+ 					neigh_release(n);
+@@ -858,14 +858,14 @@ static int arp_process(struct sk_buff *skb)
+ 
+ 	n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
+ 
+-	if (IPV4_DEVCONF_ALL(dev->nd_net, ARP_ACCEPT)) {
++	if (IPV4_DEVCONF_ALL(dev_net(dev), ARP_ACCEPT)) {
+ 		/* Unsolicited ARP is not accepted by default.
+ 		   It is possible, that this option should be enabled for some
+ 		   devices (strip is candidate)
+ 		 */
+ 		if (n == NULL &&
+ 		    arp->ar_op == htons(ARPOP_REPLY) &&
+-		    inet_addr_type(&init_net, sip) == RTN_UNICAST)
++		    inet_addr_type(net, sip) == RTN_UNICAST)
+ 			n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
+ 	}
+ 
+@@ -912,13 +912,8 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
+ {
+ 	struct arphdr *arp;
+ 
+-	if (dev->nd_net != &init_net)
+-		goto freeskb;
+-
+ 	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
+-	if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+-				 (2 * dev->addr_len) +
+-				 (2 * sizeof(u32)))))
++	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
+ 		goto freeskb;
+ 
+ 	arp = arp_hdr(skb);
+@@ -1201,9 +1196,6 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
+ {
+ 	struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
+-		return NOTIFY_DONE;
+-
+ 	switch (event) {
+ 	case NETDEV_CHANGEADDR:
+ 		neigh_changeaddr(&arp_tbl, dev);
+@@ -1318,7 +1310,7 @@ static void arp_format_neigh_entry(struct seq_file *seq,
+ #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ 	}
+ #endif
+-	sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key));
++	sprintf(tbuf, NIPQUAD_FMT, NIPQUAD(*(u32*)n->primary_key));
+ 	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
+ 		   tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
+ 	read_unlock(&n->lock);
+@@ -1331,7 +1323,7 @@ static void arp_format_pneigh_entry(struct seq_file *seq,
+ 	int hatype = dev ? dev->type : 0;
+ 	char tbuf[16];
+ 
+-	sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));
++	sprintf(tbuf, NIPQUAD_FMT, NIPQUAD(*(u32*)n->key));
+ 	seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
+ 		   tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00",
+ 		   dev ? dev->name : "*");
+@@ -1385,13 +1377,29 @@ static const struct file_operations arp_seq_fops = {
+ 	.release	= seq_release_net,
+ };
+ 
+-static int __init arp_proc_init(void)
++
++static int __net_init arp_net_init(struct net *net)
+ {
+-	if (!proc_net_fops_create(&init_net, "arp", S_IRUGO, &arp_seq_fops))
++	if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops))
+ 		return -ENOMEM;
+ 	return 0;
+ }
+ 
++static void __net_exit arp_net_exit(struct net *net)
++{
++	proc_net_remove(net, "arp");
++}
++
++static struct pernet_operations arp_net_ops = {
++	.init = arp_net_init,
++	.exit = arp_net_exit,
++};
++
++static int __init arp_proc_init(void)
++{
++	return register_pernet_subsys(&arp_net_ops);
++}
++
+ #else /* CONFIG_PROC_FS */
+ 
+ static int __init arp_proc_init(void)
+diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
+index 8cd357f..4637ded 100644
+--- a/net/ipv4/cipso_ipv4.c
++++ b/net/ipv4/cipso_ipv4.c
+@@ -1800,7 +1800,6 @@ int cipso_v4_sock_setattr(struct sock *sk,
+ 	}
+ 	memcpy(opt->__data, buf, buf_len);
+ 	opt->optlen = opt_len;
+-	opt->is_data = 1;
+ 	opt->cipso = sizeof(struct iphdr);
+ 	kfree(buf);
+ 	buf = NULL;
+diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
+index 87490f7..6848e47 100644
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -165,7 +165,7 @@ static struct in_device *inetdev_init(struct net_device *dev)
+ 	if (!in_dev)
+ 		goto out;
+ 	INIT_RCU_HEAD(&in_dev->rcu_head);
+-	memcpy(&in_dev->cnf, dev->nd_net->ipv4.devconf_dflt,
++	memcpy(&in_dev->cnf, dev_net(dev)->ipv4.devconf_dflt,
+ 			sizeof(in_dev->cnf));
+ 	in_dev->cnf.sysctl = NULL;
+ 	in_dev->dev = dev;
+@@ -437,7 +437,7 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
+ 
+ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct nlattr *tb[IFA_MAX+1];
+ 	struct in_device *in_dev;
+ 	struct ifaddrmsg *ifm;
+@@ -446,9 +446,6 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
+ 
+ 	ASSERT_RTNL();
+ 
+-	if (net != &init_net)
+-		return -EINVAL;
+-
+ 	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
+ 	if (err < 0)
+ 		goto errout;
+@@ -555,14 +552,11 @@ errout:
+ 
+ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct in_ifaddr *ifa;
+ 
+ 	ASSERT_RTNL();
+ 
+-	if (net != &init_net)
+-		return -EINVAL;
+-
+ 	ifa = rtm_to_ifaddr(net, nlh);
+ 	if (IS_ERR(ifa))
+ 		return PTR_ERR(ifa);
+@@ -595,7 +589,7 @@ static __inline__ int inet_abc_len(__be32 addr)
+ }
+ 
+ 
+-int devinet_ioctl(unsigned int cmd, void __user *arg)
++int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
+ {
+ 	struct ifreq ifr;
+ 	struct sockaddr_in sin_orig;
+@@ -624,7 +618,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
+ 		*colon = 0;
+ 
+ #ifdef CONFIG_KMOD
+-	dev_load(&init_net, ifr.ifr_name);
++	dev_load(net, ifr.ifr_name);
+ #endif
+ 
+ 	switch (cmd) {
+@@ -665,7 +659,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
+ 	rtnl_lock();
+ 
+ 	ret = -ENODEV;
+-	if ((dev = __dev_get_by_name(&init_net, ifr.ifr_name)) == NULL)
++	if ((dev = __dev_get_by_name(net, ifr.ifr_name)) == NULL)
+ 		goto done;
+ 
+ 	if (colon)
+@@ -878,6 +872,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
+ {
+ 	__be32 addr = 0;
+ 	struct in_device *in_dev;
++	struct net *net = dev_net(dev);
+ 
+ 	rcu_read_lock();
+ 	in_dev = __in_dev_get_rcu(dev);
+@@ -906,7 +901,7 @@ no_in_dev:
+ 	 */
+ 	read_lock(&dev_base_lock);
+ 	rcu_read_lock();
+-	for_each_netdev(&init_net, dev) {
++	for_each_netdev(net, dev) {
+ 		if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
+ 			continue;
+ 
+@@ -979,7 +974,7 @@ __be32 inet_confirm_addr(struct in_device *in_dev,
+ 	if (scope != RT_SCOPE_LINK)
+ 		return confirm_addr_indev(in_dev, dst, local, scope);
+ 
+-	net = in_dev->dev->nd_net;
++	net = dev_net(in_dev->dev);
+ 	read_lock(&dev_base_lock);
+ 	rcu_read_lock();
+ 	for_each_netdev(net, dev) {
+@@ -1045,9 +1040,6 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
+ 	struct net_device *dev = ptr;
+ 	struct in_device *in_dev = __in_dev_get_rtnl(dev);
+ 
+-	if (dev->nd_net != &init_net)
+-		return NOTIFY_DONE;
+-
+ 	ASSERT_RTNL();
+ 
+ 	if (!in_dev) {
+@@ -1166,16 +1158,13 @@ nla_put_failure:
+ 
+ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	int idx, ip_idx;
+ 	struct net_device *dev;
+ 	struct in_device *in_dev;
+ 	struct in_ifaddr *ifa;
+ 	int s_ip_idx, s_idx = cb->args[0];
+ 
+-	if (net != &init_net)
+-		return 0;
+-
+ 	s_ip_idx = ip_idx = cb->args[1];
+ 	idx = 0;
+ 	for_each_netdev(net, dev) {
+@@ -1214,7 +1203,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
+ 	int err = -ENOBUFS;
+ 	struct net *net;
+ 
+-	net = ifa->ifa_dev->dev->nd_net;
++	net = dev_net(ifa->ifa_dev->dev);
+ 	skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL);
+ 	if (skb == NULL)
+ 		goto errout;
+@@ -1528,7 +1517,7 @@ static void devinet_sysctl_register(struct in_device *idev)
+ {
+ 	neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4,
+ 			NET_IPV4_NEIGH, "ipv4", NULL, NULL);
+-	__devinet_sysctl_register(idev->dev->nd_net, idev->dev->name,
++	__devinet_sysctl_register(dev_net(idev->dev), idev->dev->name,
+ 			idev->dev->ifindex, &idev->cnf);
+ }
+ 
+diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
+index 86ff271..0f1557a 100644
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -257,7 +257,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
+ 	if (in_dev == NULL)
+ 		goto e_inval;
+ 
+-	net = dev->nd_net;
++	net = dev_net(dev);
+ 	if (fib_lookup(net, &fl, &res))
+ 		goto last_resort;
+ 	if (res.type != RTN_UNICAST)
+@@ -583,7 +583,7 @@ errout:
+ 
+ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct fib_config cfg;
+ 	struct fib_table *tb;
+ 	int err;
+@@ -605,7 +605,7 @@ errout:
+ 
+ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct fib_config cfg;
+ 	struct fib_table *tb;
+ 	int err;
+@@ -627,7 +627,7 @@ errout:
+ 
+ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	unsigned int h, s_h;
+ 	unsigned int e = 0, s_e;
+ 	struct fib_table *tb;
+@@ -674,7 +674,7 @@ out:
+ 
+ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
+ {
+-	struct net *net = ifa->ifa_dev->dev->nd_net;
++	struct net *net = dev_net(ifa->ifa_dev->dev);
+ 	struct fib_table *tb;
+ 	struct fib_config cfg = {
+ 		.fc_protocol = RTPROT_KERNEL,
+@@ -801,15 +801,15 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
+ 		fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
+ 
+ 		/* Check, that this local address finally disappeared. */
+-		if (inet_addr_type(dev->nd_net, ifa->ifa_local) != RTN_LOCAL) {
++		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.
+ 			*/
+-			if (fib_sync_down_addr(dev->nd_net, ifa->ifa_local))
+-				fib_flush(dev->nd_net);
++			if (fib_sync_down_addr(dev_net(dev), ifa->ifa_local))
++				fib_flush(dev_net(dev));
+ 		}
+ 	}
+ #undef LOCAL_OK
+@@ -857,7 +857,7 @@ static void nl_fib_input(struct sk_buff *skb)
+ 	struct fib_table *tb;
+ 	u32 pid;
+ 
+-	net = skb->sk->sk_net;
++	net = sock_net(skb->sk);
+ 	nlh = nlmsg_hdr(skb);
+ 	if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
+ 	    nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn)))
+@@ -899,7 +899,7 @@ static void nl_fib_lookup_exit(struct net *net)
+ static void fib_disable_ip(struct net_device *dev, int force)
+ {
+ 	if (fib_sync_down_dev(dev, force))
+-		fib_flush(dev->nd_net);
++		fib_flush(dev_net(dev));
+ 	rt_cache_flush(0);
+ 	arp_ifdown(dev);
+ }
+diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
+index 8d58d85..2e2fc33 100644
+--- a/net/ipv4/fib_hash.c
++++ b/net/ipv4/fib_hash.c
+@@ -821,7 +821,7 @@ static struct fib_alias *fib_get_first(struct seq_file *seq)
+ 	struct fib_table *main_table;
+ 	struct fn_hash *table;
+ 
+-	main_table = fib_get_table(iter->p.net, RT_TABLE_MAIN);
++	main_table = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
+ 	table = (struct fn_hash *)main_table->tb_data;
+ 
+ 	iter->bucket    = 0;
+@@ -959,11 +959,10 @@ static struct fib_alias *fib_get_idx(struct seq_file *seq, loff_t pos)
+ static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
+ 	__acquires(fib_hash_lock)
+ {
+-	struct fib_iter_state *iter = seq->private;
+ 	void *v = NULL;
+ 
+ 	read_lock(&fib_hash_lock);
+-	if (fib_get_table(iter->p.net, RT_TABLE_MAIN))
++	if (fib_get_table(seq_file_net(seq), RT_TABLE_MAIN))
+ 		v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+ 	return v;
+ }
+@@ -1004,7 +1003,7 @@ static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi)
+ static int fib_seq_show(struct seq_file *seq, void *v)
+ {
+ 	struct fib_iter_state *iter;
+-	char bf[128];
++	int len;
+ 	__be32 prefix, mask;
+ 	unsigned flags;
+ 	struct fib_node *f;
+@@ -1026,18 +1025,19 @@ static int fib_seq_show(struct seq_file *seq, void *v)
+ 	mask	= FZ_MASK(iter->zone);
+ 	flags	= fib_flag_trans(fa->fa_type, mask, fi);
+ 	if (fi)
+-		snprintf(bf, sizeof(bf),
+-			 "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
++		seq_printf(seq,
++			 "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n",
+ 			 fi->fib_dev ? fi->fib_dev->name : "*", prefix,
+ 			 fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
+ 			 mask, (fi->fib_advmss ? fi->fib_advmss + 40 : 0),
+ 			 fi->fib_window,
+-			 fi->fib_rtt >> 3);
++			 fi->fib_rtt >> 3, &len);
+ 	else
+-		snprintf(bf, sizeof(bf),
+-			 "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+-			 prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0);
+-	seq_printf(seq, "%-127s\n", bf);
++		seq_printf(seq,
++			 "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n",
++			 prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0, &len);
++
++	seq_printf(seq, "%*s\n", 127 - len, "");
+ out:
+ 	return 0;
+ }
+diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
+index 19274d0..1fb5687 100644
+--- a/net/ipv4/fib_rules.c
++++ b/net/ipv4/fib_rules.c
+@@ -137,7 +137,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
+ 			       struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
+ 			       struct nlattr **tb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	int err = -EINVAL;
+ 	struct fib4_rule *rule4 = (struct fib4_rule *) rule;
+ 
+diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
+index a13c847..3b83c34 100644
+--- a/net/ipv4/fib_semantics.c
++++ b/net/ipv4/fib_semantics.c
+@@ -152,6 +152,7 @@ void free_fib_info(struct fib_info *fi)
+ 		nh->nh_dev = NULL;
+ 	} endfor_nexthops(fi);
+ 	fib_info_cnt--;
++	release_net(fi->fib_net);
+ 	kfree(fi);
+ }
+ 
+@@ -730,7 +731,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
+ 		goto failure;
+ 	fib_info_cnt++;
+ 
+-	fi->fib_net = net;
++	fi->fib_net = hold_net(net);
+ 	fi->fib_protocol = cfg->fc_protocol;
+ 	fi->fib_flags = cfg->fc_flags;
+ 	fi->fib_priority = cfg->fc_priority;
+diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
+index f6cdc01..4b02d14 100644
+--- a/net/ipv4/fib_trie.c
++++ b/net/ipv4/fib_trie.c
+@@ -122,7 +122,10 @@ struct tnode {
+ 	unsigned char bits;		/* 2log(KEYLENGTH) bits needed */
+ 	unsigned int full_children;	/* KEYLENGTH bits needed */
+ 	unsigned int empty_children;	/* KEYLENGTH bits needed */
+-	struct rcu_head rcu;
++	union {
++		struct rcu_head rcu;
++		struct work_struct work;
++	};
+ 	struct node *child[0];
+ };
+ 
+@@ -160,7 +163,6 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
+ static struct node *resize(struct trie *t, struct tnode *tn);
+ static struct tnode *inflate(struct trie *t, struct tnode *tn);
+ static struct tnode *halve(struct trie *t, struct tnode *tn);
+-static void tnode_free(struct tnode *tn);
+ 
+ static struct kmem_cache *fn_alias_kmem __read_mostly;
+ static struct kmem_cache *trie_leaf_kmem __read_mostly;
+@@ -334,6 +336,11 @@ static void __leaf_free_rcu(struct rcu_head *head)
+ 	kmem_cache_free(trie_leaf_kmem, l);
+ }
+ 
++static inline void free_leaf(struct leaf *l)
++{
++	call_rcu_bh(&l->rcu, __leaf_free_rcu);
++}
++
+ static void __leaf_info_free_rcu(struct rcu_head *head)
+ {
+ 	kfree(container_of(head, struct leaf_info, rcu));
+@@ -346,16 +353,16 @@ static inline void free_leaf_info(struct leaf_info *leaf)
+ 
+ static struct tnode *tnode_alloc(size_t size)
+ {
+-	struct page *pages;
+-
+ 	if (size <= PAGE_SIZE)
+ 		return kzalloc(size, GFP_KERNEL);
++	else
++		return __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
++}
+ 
+-	pages = alloc_pages(GFP_KERNEL|__GFP_ZERO, get_order(size));
+-	if (!pages)
+-		return NULL;
+-
+-	return page_address(pages);
++static void __tnode_vfree(struct work_struct *arg)
++{
++	struct tnode *tn = container_of(arg, struct tnode, work);
++	vfree(tn);
+ }
+ 
+ static void __tnode_free_rcu(struct rcu_head *head)
+@@ -366,16 +373,17 @@ static void __tnode_free_rcu(struct rcu_head *head)
+ 
+ 	if (size <= PAGE_SIZE)
+ 		kfree(tn);
+-	else
+-		free_pages((unsigned long)tn, get_order(size));
++	else {
++		INIT_WORK(&tn->work, __tnode_vfree);
++		schedule_work(&tn->work);
++	}
+ }
+ 
+ static inline void tnode_free(struct tnode *tn)
+ {
+-	if (IS_LEAF(tn)) {
+-		struct leaf *l = (struct leaf *) tn;
+-		call_rcu_bh(&l->rcu, __leaf_free_rcu);
+-	} else
++	if (IS_LEAF(tn))
++		free_leaf((struct leaf *) tn);
++	else
+ 		call_rcu(&tn->rcu, __tnode_free_rcu);
+ }
+ 
+@@ -1086,7 +1094,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
+ 	li = leaf_info_new(plen);
+ 
+ 	if (!li) {
+-		tnode_free((struct tnode *) l);
++		free_leaf(l);
+ 		return NULL;
+ 	}
+ 
+@@ -1122,7 +1130,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
+ 
+ 		if (!tn) {
+ 			free_leaf_info(li);
+-			tnode_free((struct tnode *) l);
++			free_leaf(l);
+ 			return NULL;
+ 		}
+ 
+@@ -1578,7 +1586,7 @@ static void trie_leaf_remove(struct trie *t, struct leaf *l)
+ 	} else
+ 		rcu_assign_pointer(t->trie, NULL);
+ 
+-	tnode_free((struct tnode *) l);
++	free_leaf(l);
+ }
+ 
+ /*
+@@ -1665,7 +1673,7 @@ static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
+ 	return 0;
+ }
+ 
+-static int trie_flush_list(struct trie *t, struct list_head *head)
++static int trie_flush_list(struct list_head *head)
+ {
+ 	struct fib_alias *fa, *fa_node;
+ 	int found = 0;
+@@ -1683,7 +1691,7 @@ static int trie_flush_list(struct trie *t, struct list_head *head)
+ 	return found;
+ }
+ 
+-static int trie_flush_leaf(struct trie *t, struct leaf *l)
++static int trie_flush_leaf(struct leaf *l)
+ {
+ 	int found = 0;
+ 	struct hlist_head *lih = &l->list;
+@@ -1691,7 +1699,7 @@ static int trie_flush_leaf(struct trie *t, struct leaf *l)
+ 	struct leaf_info *li = NULL;
+ 
+ 	hlist_for_each_entry_safe(li, node, tmp, lih, hlist) {
+-		found += trie_flush_list(t, &li->falh);
++		found += trie_flush_list(&li->falh);
+ 
+ 		if (list_empty(&li->falh)) {
+ 			hlist_del_rcu(&li->hlist);
+@@ -1782,7 +1790,7 @@ static int fn_trie_flush(struct fib_table *tb)
+ 	int found = 0;
+ 
+ 	for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
+-		found += trie_flush_leaf(t, l);
++		found += trie_flush_leaf(l);
+ 
+ 		if (ll && hlist_empty(&ll->list))
+ 			trie_leaf_remove(t, ll);
+@@ -2029,9 +2037,8 @@ struct fib_table *fib_hash_table(u32 id)
+ /* Depth first Trie walk iterator */
+ struct fib_trie_iter {
+ 	struct seq_net_private p;
+-	struct trie *trie_local, *trie_main;
++	struct fib_table *tb;
+ 	struct tnode *tnode;
+-	struct trie *trie;
+ 	unsigned index;
+ 	unsigned depth;
+ };
+@@ -2084,31 +2091,26 @@ rescan:
+ static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
+ 				       struct trie *t)
+ {
+-	struct node *n ;
++	struct node *n;
+ 
+ 	if (!t)
+ 		return NULL;
+ 
+ 	n = rcu_dereference(t->trie);
+-
+-	if (!iter)
++	if (!n)
+ 		return NULL;
+ 
+-	if (n) {
+-		if (IS_TNODE(n)) {
+-			iter->tnode = (struct tnode *) n;
+-			iter->trie = t;
+-			iter->index = 0;
+-			iter->depth = 1;
+-		} else {
+-			iter->tnode = NULL;
+-			iter->trie  = t;
+-			iter->index = 0;
+-			iter->depth = 0;
+-		}
+-		return n;
++	if (IS_TNODE(n)) {
++		iter->tnode = (struct tnode *) n;
++		iter->index = 0;
++		iter->depth = 1;
++	} else {
++		iter->tnode = NULL;
++		iter->index = 0;
++		iter->depth = 0;
+ 	}
+-	return NULL;
++
++	return n;
+ }
+ 
+ static void trie_collect_stats(struct trie *t, struct trie_stat *s)
+@@ -2119,8 +2121,7 @@ static void trie_collect_stats(struct trie *t, struct trie_stat *s)
+ 	memset(s, 0, sizeof(*s));
+ 
+ 	rcu_read_lock();
+-	for (n = fib_trie_get_first(&iter, t); n;
+-	     n = fib_trie_get_next(&iter)) {
++	for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) {
+ 		if (IS_LEAF(n)) {
+ 			struct leaf *l = (struct leaf *)n;
+ 			struct leaf_info *li;
+@@ -2209,36 +2210,48 @@ static void trie_show_usage(struct seq_file *seq,
+ }
+ #endif /*  CONFIG_IP_FIB_TRIE_STATS */
+ 
+-static void fib_trie_show(struct seq_file *seq, const char *name,
+-			  struct trie *trie)
++static void fib_table_print(struct seq_file *seq, struct fib_table *tb)
+ {
+-	struct trie_stat stat;
+-
+-	trie_collect_stats(trie, &stat);
+-	seq_printf(seq, "%s:\n", name);
+-	trie_show_stats(seq, &stat);
+-#ifdef CONFIG_IP_FIB_TRIE_STATS
+-	trie_show_usage(seq, &trie->stats);
+-#endif
++	if (tb->tb_id == RT_TABLE_LOCAL)
++		seq_puts(seq, "Local:\n");
++	else if (tb->tb_id == RT_TABLE_MAIN)
++		seq_puts(seq, "Main:\n");
++	else
++		seq_printf(seq, "Id %d:\n", tb->tb_id);
+ }
+ 
++
+ static int fib_triestat_seq_show(struct seq_file *seq, void *v)
+ {
+ 	struct net *net = (struct net *)seq->private;
+-	struct fib_table *tb;
++	unsigned int h;
+ 
+ 	seq_printf(seq,
+ 		   "Basic info: size of leaf:"
+ 		   " %Zd bytes, size of tnode: %Zd bytes.\n",
+ 		   sizeof(struct leaf), sizeof(struct tnode));
+ 
+-	tb = fib_get_table(net, RT_TABLE_LOCAL);
+-	if (tb)
+-		fib_trie_show(seq, "Local", (struct trie *) tb->tb_data);
++	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
++		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
++		struct hlist_node *node;
++		struct fib_table *tb;
++
++		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
++			struct trie *t = (struct trie *) tb->tb_data;
++			struct trie_stat stat;
++
++			if (!t)
++				continue;
+ 
+-	tb = fib_get_table(net, RT_TABLE_MAIN);
+-	if (tb)
+-		fib_trie_show(seq, "Main", (struct trie *) tb->tb_data);
++			fib_table_print(seq, tb);
++
++			trie_collect_stats(t, &stat);
++			trie_show_stats(seq, &stat);
++#ifdef CONFIG_IP_FIB_TRIE_STATS
++			trie_show_usage(seq, &t->stats);
++#endif
++		}
++	}
+ 
+ 	return 0;
+ }
+@@ -2274,67 +2287,79 @@ static const struct file_operations fib_triestat_fops = {
+ 	.release = fib_triestat_seq_release,
+ };
+ 
+-static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
+-				      loff_t pos)
++static struct node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
+ {
++	struct fib_trie_iter *iter = seq->private;
++	struct net *net = seq_file_net(seq);
+ 	loff_t idx = 0;
+-	struct node *n;
++	unsigned int h;
+ 
+-	for (n = fib_trie_get_first(iter, iter->trie_local);
+-	     n; ++idx, n = fib_trie_get_next(iter)) {
+-		if (pos == idx)
+-			return n;
+-	}
++	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
++		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
++		struct hlist_node *node;
++		struct fib_table *tb;
+ 
+-	for (n = fib_trie_get_first(iter, iter->trie_main);
+-	     n; ++idx, n = fib_trie_get_next(iter)) {
+-		if (pos == idx)
+-			return n;
++		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
++			struct node *n;
++
++			for (n = fib_trie_get_first(iter,
++						    (struct trie *) tb->tb_data);
++			     n; n = fib_trie_get_next(iter))
++				if (pos == idx++) {
++					iter->tb = tb;
++					return n;
++				}
++		}
+ 	}
++
+ 	return NULL;
+ }
+ 
+ static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
+ 	__acquires(RCU)
+ {
+-	struct fib_trie_iter *iter = seq->private;
+-	struct fib_table *tb;
+-
+-	if (!iter->trie_local) {
+-		tb = fib_get_table(iter->p.net, RT_TABLE_LOCAL);
+-		if (tb)
+-			iter->trie_local = (struct trie *) tb->tb_data;
+-	}
+-	if (!iter->trie_main) {
+-		tb = fib_get_table(iter->p.net, RT_TABLE_MAIN);
+-		if (tb)
+-			iter->trie_main = (struct trie *) tb->tb_data;
+-	}
+ 	rcu_read_lock();
+-	if (*pos == 0)
+-		return SEQ_START_TOKEN;
+-	return fib_trie_get_idx(iter, *pos - 1);
++	return fib_trie_get_idx(seq, *pos);
+ }
+ 
+ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ 	struct fib_trie_iter *iter = seq->private;
+-	void *l = v;
++	struct net *net = seq_file_net(seq);
++	struct fib_table *tb = iter->tb;
++	struct hlist_node *tb_node;
++	unsigned int h;
++	struct node *n;
+ 
+ 	++*pos;
+-	if (v == SEQ_START_TOKEN)
+-		return fib_trie_get_idx(iter, 0);
+-
+-	v = fib_trie_get_next(iter);
+-	BUG_ON(v == l);
+-	if (v)
+-		return v;
++	/* next node in same table */
++	n = fib_trie_get_next(iter);
++	if (n)
++		return n;
+ 
+-	/* continue scan in next trie */
+-	if (iter->trie == iter->trie_local)
+-		return fib_trie_get_first(iter, iter->trie_main);
++	/* walk rest of this hash chain */
++	h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
++	while ( (tb_node = rcu_dereference(tb->tb_hlist.next)) ) {
++		tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
++		n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
++		if (n)
++			goto found;
++	}
+ 
++	/* new hash chain */
++	while (++h < FIB_TABLE_HASHSZ) {
++		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
++		hlist_for_each_entry_rcu(tb, tb_node, head, tb_hlist) {
++			n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
++			if (n)
++				goto found;
++		}
++	}
+ 	return NULL;
++
++found:
++	iter->tb = tb;
++	return n;
+ }
+ 
+ static void fib_trie_seq_stop(struct seq_file *seq, void *v)
+@@ -2391,22 +2416,15 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
+ 	const struct fib_trie_iter *iter = seq->private;
+ 	struct node *n = v;
+ 
+-	if (v == SEQ_START_TOKEN)
+-		return 0;
+-
+-	if (!node_parent_rcu(n)) {
+-		if (iter->trie == iter->trie_local)
+-			seq_puts(seq, "<local>:\n");
+-		else
+-			seq_puts(seq, "<main>:\n");
+-	}
++	if (!node_parent_rcu(n))
++		fib_table_print(seq, iter->tb);
+ 
+ 	if (IS_TNODE(n)) {
+ 		struct tnode *tn = (struct tnode *) n;
+ 		__be32 prf = htonl(mask_pfx(tn->key, tn->pos));
+ 
+ 		seq_indent(seq, iter->depth-1);
+-		seq_printf(seq, "  +-- %d.%d.%d.%d/%d %d %d %d\n",
++		seq_printf(seq, "  +-- " NIPQUAD_FMT "/%d %d %d %d\n",
+ 			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
+ 			   tn->empty_children);
+ 
+@@ -2417,7 +2435,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
+ 		__be32 val = htonl(l->key);
+ 
+ 		seq_indent(seq, iter->depth);
+-		seq_printf(seq, "  |-- %d.%d.%d.%d\n", NIPQUAD(val));
++		seq_printf(seq, "  |-- " NIPQUAD_FMT "\n", NIPQUAD(val));
+ 
+ 		hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
+ 			struct fib_alias *fa;
+@@ -2502,7 +2520,7 @@ static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos)
+ 	struct fib_table *tb;
+ 
+ 	rcu_read_lock();
+-	tb = fib_get_table(iter->p.net, RT_TABLE_MAIN);
++	tb = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
+ 	if (!tb)
+ 		return NULL;
+ 
+@@ -2584,15 +2602,16 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
+ 		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);
+-			char bf[128];
++			int len;
+ 
+ 			if (fa->fa_type == RTN_BROADCAST
+ 			    || fa->fa_type == RTN_MULTICAST)
+ 				continue;
+ 
+ 			if (fi)
+-				snprintf(bf, sizeof(bf),
+-					 "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
++				seq_printf(seq,
++					 "%s\t%08X\t%08X\t%04X\t%d\t%u\t"
++					 "%d\t%08X\t%d\t%u\t%u%n",
+ 					 fi->fib_dev ? fi->fib_dev->name : "*",
+ 					 prefix,
+ 					 fi->fib_nh->nh_gw, flags, 0, 0,
+@@ -2601,14 +2620,15 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
+ 					 (fi->fib_advmss ?
+ 					  fi->fib_advmss + 40 : 0),
+ 					 fi->fib_window,
+-					 fi->fib_rtt >> 3);
++					 fi->fib_rtt >> 3, &len);
+ 			else
+-				snprintf(bf, sizeof(bf),
+-					 "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
++				seq_printf(seq,
++					 "*\t%08X\t%08X\t%04X\t%d\t%u\t"
++					 "%d\t%08X\t%d\t%u\t%u%n",
+ 					 prefix, 0, flags, 0, 0, 0,
+-					 mask, 0, 0, 0);
++					 mask, 0, 0, 0, &len);
+ 
+-			seq_printf(seq, "%-127s\n", bf);
++			seq_printf(seq, "%*s\n", 127 - len, "");
+ 		}
+ 	}
+ 
+diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
+index 40508ba..c67d00e 100644
+--- a/net/ipv4/icmp.c
++++ b/net/ipv4/icmp.c
+@@ -93,6 +93,7 @@
+ #include <asm/uaccess.h>
+ #include <net/checksum.h>
+ #include <net/xfrm.h>
++#include <net/inet_common.h>
+ 
+ /*
+  *	Build xmit assembly blocks
+@@ -188,29 +189,6 @@ struct icmp_err icmp_err_convert[] = {
+ 	},
+ };
+ 
+-/* Control parameters for ECHO replies. */
+-int sysctl_icmp_echo_ignore_all __read_mostly;
+-int sysctl_icmp_echo_ignore_broadcasts __read_mostly = 1;
+-
+-/* Control parameter - ignore bogus broadcast responses? */
+-int sysctl_icmp_ignore_bogus_error_responses __read_mostly = 1;
+-
+-/*
+- * 	Configurable global rate limit.
+- *
+- *	ratelimit defines tokens/packet consumed for dst->rate_token bucket
+- *	ratemask defines which icmp types are ratelimited by setting
+- * 	it's bit position.
+- *
+- *	default:
+- *	dest unreachable (3), source quench (4),
+- *	time exceeded (11), parameter problem (12)
+- */
+-
+-int sysctl_icmp_ratelimit __read_mostly = 1 * HZ;
+-int sysctl_icmp_ratemask __read_mostly = 0x1818;
+-int sysctl_icmp_errors_use_inbound_ifaddr __read_mostly;
+-
+ /*
+  *	ICMP control array. This specifies what to do with each ICMP.
+  */
+@@ -229,14 +207,16 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1];
+  *
+  *	On SMP we have one ICMP socket per-cpu.
+  */
+-static DEFINE_PER_CPU(struct socket *, __icmp_socket) = NULL;
+-#define icmp_socket	__get_cpu_var(__icmp_socket)
++static struct sock *icmp_sk(struct net *net)
++{
++	return net->ipv4.icmp_sk[smp_processor_id()];
++}
+ 
+-static inline int icmp_xmit_lock(void)
++static inline int icmp_xmit_lock(struct sock *sk)
+ {
+ 	local_bh_disable();
+ 
+-	if (unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock))) {
++	if (unlikely(!spin_trylock(&sk->sk_lock.slock))) {
+ 		/* This can happen if the output path signals a
+ 		 * dst_link_failure() for an outgoing ICMP packet.
+ 		 */
+@@ -246,9 +226,9 @@ static inline int icmp_xmit_lock(void)
+ 	return 0;
+ }
+ 
+-static inline void icmp_xmit_unlock(void)
++static inline void icmp_xmit_unlock(struct sock *sk)
+ {
+-	spin_unlock_bh(&icmp_socket->sk->sk_lock.slock);
++	spin_unlock_bh(&sk->sk_lock.slock);
+ }
+ 
+ /*
+@@ -291,7 +271,8 @@ int xrlim_allow(struct dst_entry *dst, int timeout)
+ 	return rc;
+ }
+ 
+-static inline int icmpv4_xrlim_allow(struct rtable *rt, int type, int code)
++static inline int icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
++		int type, int code)
+ {
+ 	struct dst_entry *dst = &rt->u.dst;
+ 	int rc = 1;
+@@ -308,8 +289,8 @@ static inline int icmpv4_xrlim_allow(struct rtable *rt, int type, int code)
+ 		goto out;
+ 
+ 	/* Limit if icmp type is enabled in ratemask. */
+-	if ((1 << type) & sysctl_icmp_ratemask)
+-		rc = xrlim_allow(dst, sysctl_icmp_ratelimit);
++	if ((1 << type) & net->ipv4.sysctl_icmp_ratemask)
++		rc = xrlim_allow(dst, net->ipv4.sysctl_icmp_ratelimit);
+ out:
+ 	return rc;
+ }
+@@ -346,19 +327,21 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
+ static void icmp_push_reply(struct icmp_bxm *icmp_param,
+ 			    struct ipcm_cookie *ipc, struct rtable *rt)
+ {
++	struct sock *sk;
+ 	struct sk_buff *skb;
+ 
+-	if (ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param,
++	sk = icmp_sk(dev_net(rt->u.dst.dev));
++	if (ip_append_data(sk, icmp_glue_bits, icmp_param,
+ 			   icmp_param->data_len+icmp_param->head_len,
+ 			   icmp_param->head_len,
+ 			   ipc, rt, MSG_DONTWAIT) < 0)
+-		ip_flush_pending_frames(icmp_socket->sk);
+-	else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) {
++		ip_flush_pending_frames(sk);
++	else if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {
+ 		struct icmphdr *icmph = icmp_hdr(skb);
+ 		__wsum csum = 0;
+ 		struct sk_buff *skb1;
+ 
+-		skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) {
++		skb_queue_walk(&sk->sk_write_queue, skb1) {
+ 			csum = csum_add(csum, skb1->csum);
+ 		}
+ 		csum = csum_partial_copy_nocheck((void *)&icmp_param->data,
+@@ -366,7 +349,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
+ 						 icmp_param->head_len, csum);
+ 		icmph->checksum = csum_fold(csum);
+ 		skb->ip_summed = CHECKSUM_NONE;
+-		ip_push_pending_frames(icmp_socket->sk);
++		ip_push_pending_frames(sk);
+ 	}
+ }
+ 
+@@ -376,16 +359,17 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
+ 
+ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
+ {
+-	struct sock *sk = icmp_socket->sk;
+-	struct inet_sock *inet = inet_sk(sk);
+ 	struct ipcm_cookie ipc;
+-	struct rtable *rt = (struct rtable *)skb->dst;
++	struct rtable *rt = skb->rtable;
++	struct net *net = dev_net(rt->u.dst.dev);
++	struct sock *sk = icmp_sk(net);
++	struct inet_sock *inet = inet_sk(sk);
+ 	__be32 daddr;
+ 
+ 	if (ip_options_echo(&icmp_param->replyopts, skb))
+ 		return;
+ 
+-	if (icmp_xmit_lock())
++	if (icmp_xmit_lock(sk))
+ 		return;
+ 
+ 	icmp_param->data.icmph.checksum = 0;
+@@ -405,15 +389,15 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
+ 						.tos = RT_TOS(ip_hdr(skb)->tos) } },
+ 				    .proto = IPPROTO_ICMP };
+ 		security_skb_classify_flow(skb, &fl);
+-		if (ip_route_output_key(rt->u.dst.dev->nd_net, &rt, &fl))
++		if (ip_route_output_key(net, &rt, &fl))
+ 			goto out_unlock;
+ 	}
+-	if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type,
++	if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type,
+ 			       icmp_param->data.icmph.code))
+ 		icmp_push_reply(icmp_param, &ipc, rt);
+ 	ip_rt_put(rt);
+ out_unlock:
+-	icmp_xmit_unlock();
++	icmp_xmit_unlock(sk);
+ }
+ 
+ 
+@@ -433,15 +417,17 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ 	struct iphdr *iph;
+ 	int room;
+ 	struct icmp_bxm icmp_param;
+-	struct rtable *rt = (struct rtable *)skb_in->dst;
++	struct rtable *rt = skb_in->rtable;
+ 	struct ipcm_cookie ipc;
+ 	__be32 saddr;
+ 	u8  tos;
+ 	struct net *net;
++	struct sock *sk;
+ 
+ 	if (!rt)
+ 		goto out;
+-	net = rt->u.dst.dev->nd_net;
++	net = dev_net(rt->u.dst.dev);
++	sk = icmp_sk(net);
+ 
+ 	/*
+ 	 *	Find the original header. It is expected to be valid, of course.
+@@ -505,7 +491,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ 		}
+ 	}
+ 
+-	if (icmp_xmit_lock())
++	if (icmp_xmit_lock(sk))
+ 		return;
+ 
+ 	/*
+@@ -516,7 +502,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ 	if (!(rt->rt_flags & RTCF_LOCAL)) {
+ 		struct net_device *dev = NULL;
+ 
+-		if (rt->fl.iif && sysctl_icmp_errors_use_inbound_ifaddr)
++		if (rt->fl.iif &&
++			net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr)
+ 			dev = dev_get_by_index(net, rt->fl.iif);
+ 
+ 		if (dev) {
+@@ -544,7 +531,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ 	icmp_param.data.icmph.checksum	 = 0;
+ 	icmp_param.skb	  = skb_in;
+ 	icmp_param.offset = skb_network_offset(skb_in);
+-	inet_sk(icmp_socket->sk)->tos = tos;
++	inet_sk(sk)->tos = tos;
+ 	ipc.addr = iph->saddr;
+ 	ipc.opt = &icmp_param.replyopts;
+ 
+@@ -609,7 +596,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ 					     RT_TOS(tos), rt2->u.dst.dev);
+ 
+ 			dst_release(&rt2->u.dst);
+-			rt2 = (struct rtable *)skb_in->dst;
++			rt2 = skb_in->rtable;
+ 			skb_in->dst = odst;
+ 		}
+ 
+@@ -634,7 +621,7 @@ relookup_failed:
+ 	}
+ 
+ route_done:
+-	if (!icmpv4_xrlim_allow(rt, type, code))
++	if (!icmpv4_xrlim_allow(net, rt, type, code))
+ 		goto ende;
+ 
+ 	/* RFC says return as much as we can without exceeding 576 bytes. */
+@@ -654,7 +641,7 @@ route_done:
+ ende:
+ 	ip_rt_put(rt);
+ out_unlock:
+-	icmp_xmit_unlock();
++	icmp_xmit_unlock(sk);
+ out:;
+ }
+ 
+@@ -672,7 +659,7 @@ static void icmp_unreach(struct sk_buff *skb)
+ 	u32 info = 0;
+ 	struct net *net;
+ 
+-	net = skb->dst->dev->nd_net;
++	net = dev_net(skb->dst->dev);
+ 
+ 	/*
+ 	 *	Incomplete header ?
+@@ -698,7 +685,7 @@ static void icmp_unreach(struct sk_buff *skb)
+ 			break;
+ 		case ICMP_FRAG_NEEDED:
+ 			if (ipv4_config.no_pmtu_disc) {
+-				LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: "
++				LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": "
+ 							 "fragmentation needed "
+ 							 "and DF set.\n",
+ 					       NIPQUAD(iph->daddr));
+@@ -710,7 +697,7 @@ static void icmp_unreach(struct sk_buff *skb)
+ 			}
+ 			break;
+ 		case ICMP_SR_FAILED:
+-			LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: Source "
++			LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": Source "
+ 						 "Route Failed.\n",
+ 				       NIPQUAD(iph->daddr));
+ 			break;
+@@ -740,12 +727,12 @@ static void icmp_unreach(struct sk_buff *skb)
+ 	 *	get the other vendor to fix their kit.
+ 	 */
+ 
+-	if (!sysctl_icmp_ignore_bogus_error_responses &&
++	if (!net->ipv4.sysctl_icmp_ignore_bogus_error_responses &&
+ 	    inet_addr_type(net, iph->daddr) == RTN_BROADCAST) {
+ 		if (net_ratelimit())
+-			printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP "
++			printk(KERN_WARNING NIPQUAD_FMT " sent an invalid ICMP "
+ 					    "type %u, code %u "
+-					    "error to a broadcast: %u.%u.%u.%u on %s\n",
++					    "error to a broadcast: " NIPQUAD_FMT " on %s\n",
+ 			       NIPQUAD(ip_hdr(skb)->saddr),
+ 			       icmph->type, icmph->code,
+ 			       NIPQUAD(iph->daddr),
+@@ -835,7 +822,10 @@ out_err:
+ 
+ static void icmp_echo(struct sk_buff *skb)
+ {
+-	if (!sysctl_icmp_echo_ignore_all) {
++	struct net *net;
++
++	net = dev_net(skb->dst->dev);
++	if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
+ 		struct icmp_bxm icmp_param;
+ 
+ 		icmp_param.data.icmph	   = *icmp_hdr(skb);
+@@ -857,7 +847,7 @@ static void icmp_echo(struct sk_buff *skb)
+  */
+ static void icmp_timestamp(struct sk_buff *skb)
+ {
+-	struct timeval tv;
++	struct timespec tv;
+ 	struct icmp_bxm icmp_param;
+ 	/*
+ 	 *	Too short.
+@@ -868,9 +858,9 @@ static void icmp_timestamp(struct sk_buff *skb)
+ 	/*
+ 	 *	Fill in the current time as ms since midnight UT:
+ 	 */
+-	do_gettimeofday(&tv);
+-	icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * 1000 +
+-					 tv.tv_usec / 1000);
++	getnstimeofday(&tv);
++	icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC +
++					 tv.tv_nsec / NSEC_PER_MSEC);
+ 	icmp_param.data.times[2] = icmp_param.data.times[1];
+ 	if (skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4))
+ 		BUG();
+@@ -938,7 +928,7 @@ static void icmp_address(struct sk_buff *skb)
+ 
+ static void icmp_address_reply(struct sk_buff *skb)
+ {
+-	struct rtable *rt = (struct rtable *)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	struct net_device *dev = skb->dev;
+ 	struct in_device *in_dev;
+ 	struct in_ifaddr *ifa;
+@@ -963,8 +953,8 @@ static void icmp_address_reply(struct sk_buff *skb)
+ 				break;
+ 		}
+ 		if (!ifa && net_ratelimit()) {
+-			printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from "
+-					 "%s/%u.%u.%u.%u\n",
++			printk(KERN_INFO "Wrong address mask " NIPQUAD_FMT " from "
++					 "%s/" NIPQUAD_FMT "\n",
+ 			       NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
+ 		}
+ 	}
+@@ -983,7 +973,7 @@ static void icmp_discard(struct sk_buff *skb)
+ int icmp_rcv(struct sk_buff *skb)
+ {
+ 	struct icmphdr *icmph;
+-	struct rtable *rt = (struct rtable *)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 
+ 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+ 		int nh;
+@@ -1038,6 +1028,9 @@ int icmp_rcv(struct sk_buff *skb)
+ 	 */
+ 
+ 	if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
++		struct net *net;
++
++		net = dev_net(rt->u.dst.dev);
+ 		/*
+ 		 *	RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be
+ 		 *	  silently ignored (we let user decide with a sysctl).
+@@ -1046,7 +1039,7 @@ int icmp_rcv(struct sk_buff *skb)
+ 		 */
+ 		if ((icmph->type == ICMP_ECHO ||
+ 		     icmph->type == ICMP_TIMESTAMP) &&
+-		    sysctl_icmp_echo_ignore_broadcasts) {
++		    net->ipv4.sysctl_icmp_echo_ignore_broadcasts) {
+ 			goto error;
+ 		}
+ 		if (icmph->type != ICMP_ECHO &&
+@@ -1141,38 +1134,84 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
+ 	},
+ };
+ 
+-void __init icmp_init(struct net_proto_family *ops)
++static void __net_exit icmp_sk_exit(struct net *net)
+ {
+-	struct inet_sock *inet;
+ 	int i;
+ 
+-	for_each_possible_cpu(i) {
+-		int err;
++	for_each_possible_cpu(i)
++		inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
++	kfree(net->ipv4.icmp_sk);
++	net->ipv4.icmp_sk = NULL;
++}
++
++static int __net_init icmp_sk_init(struct net *net)
++{
++	int i, err;
+ 
+-		err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
+-				       &per_cpu(__icmp_socket, i));
++	net->ipv4.icmp_sk =
++		kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
++	if (net->ipv4.icmp_sk == NULL)
++		return -ENOMEM;
+ 
++	for_each_possible_cpu(i) {
++		struct sock *sk;
++
++		err = inet_ctl_sock_create(&sk, PF_INET,
++					   SOCK_RAW, IPPROTO_ICMP, net);
+ 		if (err < 0)
+-			panic("Failed to create the ICMP control socket.\n");
++			goto fail;
+ 
+-		per_cpu(__icmp_socket, i)->sk->sk_allocation = GFP_ATOMIC;
++		net->ipv4.icmp_sk[i] = sk;
+ 
+ 		/* Enough space for 2 64K ICMP packets, including
+ 		 * sk_buff struct overhead.
+ 		 */
+-		per_cpu(__icmp_socket, i)->sk->sk_sndbuf =
++		sk->sk_sndbuf =
+ 			(2 * ((64 * 1024) + sizeof(struct sk_buff)));
+ 
+-		inet = inet_sk(per_cpu(__icmp_socket, i)->sk);
+-		inet->uc_ttl = -1;
+-		inet->pmtudisc = IP_PMTUDISC_DONT;
+-
+-		/* Unhash it so that IP input processing does not even
+-		 * see it, we do not wish this socket to see incoming
+-		 * packets.
+-		 */
+-		per_cpu(__icmp_socket, i)->sk->sk_prot->unhash(per_cpu(__icmp_socket, i)->sk);
++		inet_sk(sk)->pmtudisc = IP_PMTUDISC_DONT;
+ 	}
++
++	/* Control parameters for ECHO replies. */
++	net->ipv4.sysctl_icmp_echo_ignore_all = 0;
++	net->ipv4.sysctl_icmp_echo_ignore_broadcasts = 1;
++
++	/* Control parameter - ignore bogus broadcast responses? */
++	net->ipv4.sysctl_icmp_ignore_bogus_error_responses = 1;
++
++	/*
++	 * 	Configurable global rate limit.
++	 *
++	 *	ratelimit defines tokens/packet consumed for dst->rate_token
++	 *	bucket ratemask defines which icmp types are ratelimited by
++	 *	setting	it's bit position.
++	 *
++	 *	default:
++	 *	dest unreachable (3), source quench (4),
++	 *	time exceeded (11), parameter problem (12)
++	 */
++
++	net->ipv4.sysctl_icmp_ratelimit = 1 * HZ;
++	net->ipv4.sysctl_icmp_ratemask = 0x1818;
++	net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr = 0;
++
++	return 0;
++
++fail:
++	for_each_possible_cpu(i)
++		inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
++	kfree(net->ipv4.icmp_sk);
++	return err;
++}
++
++static struct pernet_operations __net_initdata icmp_sk_ops = {
++       .init = icmp_sk_init,
++       .exit = icmp_sk_exit,
++};
++
++int __init icmp_init(void)
++{
++	return register_pernet_device(&icmp_sk_ops);
+ }
+ 
+ EXPORT_SYMBOL(icmp_err_convert);
+diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
+index 732cd07..6250f42 100644
+--- a/net/ipv4/igmp.c
++++ b/net/ipv4/igmp.c
+@@ -130,12 +130,12 @@
+  */
+ 
+ #define IGMP_V1_SEEN(in_dev) \
+-	(IPV4_DEVCONF_ALL(in_dev->dev->nd_net, FORCE_IGMP_VERSION) == 1 || \
++	(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 1 || \
+ 	 IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
+ 	 ((in_dev)->mr_v1_seen && \
+ 	  time_before(jiffies, (in_dev)->mr_v1_seen)))
+ #define IGMP_V2_SEEN(in_dev) \
+-	(IPV4_DEVCONF_ALL(in_dev->dev->nd_net, FORCE_IGMP_VERSION) == 2 || \
++	(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 2 || \
+ 	 IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
+ 	 ((in_dev)->mr_v2_seen && \
+ 	  time_before(jiffies, (in_dev)->mr_v2_seen)))
+@@ -948,7 +948,7 @@ int igmp_rcv(struct sk_buff *skb)
+ 	case IGMPV2_HOST_MEMBERSHIP_REPORT:
+ 	case IGMPV3_HOST_MEMBERSHIP_REPORT:
+ 		/* Is it our report looped back? */
+-		if (((struct rtable*)skb->dst)->fl.iif == 0)
++		if (skb->rtable->fl.iif == 0)
+ 			break;
+ 		/* don't rely on MC router hearing unicast reports */
+ 		if (skb->pkt_type == PACKET_MULTICAST ||
+@@ -1198,6 +1198,9 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
+ 
+ 	ASSERT_RTNL();
+ 
++	if (dev_net(in_dev->dev) != &init_net)
++		return;
++
+ 	for (im=in_dev->mc_list; im; im=im->next) {
+ 		if (im->multiaddr == addr) {
+ 			im->users++;
+@@ -1277,6 +1280,9 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
+ 
+ 	ASSERT_RTNL();
+ 
++	if (dev_net(in_dev->dev) != &init_net)
++		return;
++
+ 	for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
+ 		if (i->multiaddr==addr) {
+ 			if (--i->users == 0) {
+@@ -1304,6 +1310,9 @@ void ip_mc_down(struct in_device *in_dev)
+ 
+ 	ASSERT_RTNL();
+ 
++	if (dev_net(in_dev->dev) != &init_net)
++		return;
++
+ 	for (i=in_dev->mc_list; i; i=i->next)
+ 		igmp_group_dropped(i);
+ 
+@@ -1324,6 +1333,9 @@ void ip_mc_init_dev(struct in_device *in_dev)
+ {
+ 	ASSERT_RTNL();
+ 
++	if (dev_net(in_dev->dev) != &init_net)
++		return;
++
+ 	in_dev->mc_tomb = NULL;
+ #ifdef CONFIG_IP_MULTICAST
+ 	in_dev->mr_gq_running = 0;
+@@ -1347,6 +1359,9 @@ void ip_mc_up(struct in_device *in_dev)
+ 
+ 	ASSERT_RTNL();
+ 
++	if (dev_net(in_dev->dev) != &init_net)
++		return;
++
+ 	ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
+ 
+ 	for (i=in_dev->mc_list; i; i=i->next)
+@@ -1363,6 +1378,9 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
+ 
+ 	ASSERT_RTNL();
+ 
++	if (dev_net(in_dev->dev) != &init_net)
++		return;
++
+ 	/* Deactivate timers */
+ 	ip_mc_down(in_dev);
+ 
+@@ -1744,6 +1762,9 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
+ 	if (!ipv4_is_multicast(addr))
+ 		return -EINVAL;
+ 
++	if (sock_net(sk) != &init_net)
++		return -EPROTONOSUPPORT;
++
+ 	rtnl_lock();
+ 
+ 	in_dev = ip_mc_find_dev(imr);
+@@ -1812,6 +1833,9 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
+ 	u32 ifindex;
+ 	int ret = -EADDRNOTAVAIL;
+ 
++	if (sock_net(sk) != &init_net)
++		return -EPROTONOSUPPORT;
++
+ 	rtnl_lock();
+ 	in_dev = ip_mc_find_dev(imr);
+ 	ifindex = imr->imr_ifindex;
+@@ -1857,6 +1881,9 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
+ 	if (!ipv4_is_multicast(addr))
+ 		return -EINVAL;
+ 
++	if (sock_net(sk) != &init_net)
++		return -EPROTONOSUPPORT;
++
+ 	rtnl_lock();
+ 
+ 	imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr;
+@@ -1990,6 +2017,9 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
+ 	    msf->imsf_fmode != MCAST_EXCLUDE)
+ 		return -EINVAL;
+ 
++	if (sock_net(sk) != &init_net)
++		return -EPROTONOSUPPORT;
++
+ 	rtnl_lock();
+ 
+ 	imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
+@@ -2070,6 +2100,9 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
+ 	if (!ipv4_is_multicast(addr))
+ 		return -EINVAL;
+ 
++	if (sock_net(sk) != &init_net)
++		return -EPROTONOSUPPORT;
++
+ 	rtnl_lock();
+ 
+ 	imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
+@@ -2132,6 +2165,9 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
+ 	if (!ipv4_is_multicast(addr))
+ 		return -EINVAL;
+ 
++	if (sock_net(sk) != &init_net)
++		return -EPROTONOSUPPORT;
++
+ 	rtnl_lock();
+ 
+ 	err = -EADDRNOTAVAIL;
+@@ -2216,6 +2252,9 @@ void ip_mc_drop_socket(struct sock *sk)
+ 	if (inet->mc_list == NULL)
+ 		return;
+ 
++	if (sock_net(sk) != &init_net)
++		return;
++
+ 	rtnl_lock();
+ 	while ((iml = inet->mc_list) != NULL) {
+ 		struct in_device *in_dev;
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index b189278..828ea21 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -55,6 +55,13 @@ int inet_csk_bind_conflict(const struct sock *sk,
+ 	struct hlist_node *node;
+ 	int reuse = sk->sk_reuse;
+ 
++	/*
++	 * Unlike other sk lookup places we do not check
++	 * for sk_net here, since _all_ the socks listed
++	 * in tb->owners list belong to the same net - the
++	 * one this bucket belongs to.
++	 */
++
+ 	sk_for_each_bound(sk2, node, &tb->owners) {
+ 		if (sk != sk2 &&
+ 		    !inet_v6_ipv6only(sk2) &&
+@@ -80,12 +87,12 @@ EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
+  */
+ int inet_csk_get_port(struct sock *sk, unsigned short snum)
+ {
+-	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++	struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ 	struct inet_bind_hashbucket *head;
+ 	struct hlist_node *node;
+ 	struct inet_bind_bucket *tb;
+ 	int ret;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 
+ 	local_bh_disable();
+ 	if (!snum) {
+@@ -133,8 +140,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
+ 	goto tb_not_found;
+ tb_found:
+ 	if (!hlist_empty(&tb->owners)) {
+-		if (sk->sk_reuse > 1)
+-			goto success;
+ 		if (tb->fastreuse > 0 &&
+ 		    sk->sk_reuse && sk->sk_state != TCP_LISTEN) {
+ 			goto success;
+@@ -333,7 +338,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
+ 					 .dport = ireq->rmt_port } } };
+ 
+ 	security_req_classify_flow(req, &fl);
+-	if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0)) {
++	if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0)) {
+ 		IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+ 		return NULL;
+ 	}
+@@ -414,8 +419,7 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
+ 	struct inet_connection_sock *icsk = inet_csk(parent);
+ 	struct request_sock_queue *queue = &icsk->icsk_accept_queue;
+ 	struct listen_sock *lopt = queue->listen_opt;
+-	int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
+-	int thresh = max_retries;
++	int thresh = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
+ 	unsigned long now = jiffies;
+ 	struct request_sock **reqp, *req;
+ 	int i, budget;
+@@ -451,9 +455,6 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
+ 		}
+ 	}
+ 
+-	if (queue->rskq_defer_accept)
+-		max_retries = queue->rskq_defer_accept;
+-
+ 	budget = 2 * (lopt->nr_table_entries / (timeout / interval));
+ 	i = lopt->clock_hand;
+ 
+@@ -461,9 +462,8 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
+ 		reqp=&lopt->syn_table[i];
+ 		while ((req = *reqp) != NULL) {
+ 			if (time_after_eq(now, req->expires)) {
+-				if ((req->retrans < thresh ||
+-				     (inet_rsk(req)->acked && req->retrans < max_retries))
+-				    && !req->rsk_ops->rtx_syn_ack(parent, req, NULL)) {
++				if (req->retrans < thresh &&
++				    !req->rsk_ops->rtx_syn_ack(parent, req)) {
+ 					unsigned long timeo;
+ 
+ 					if (req->retrans++ == 0)
+@@ -656,25 +656,6 @@ void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr)
+ 
+ EXPORT_SYMBOL_GPL(inet_csk_addr2sockaddr);
+ 
+-int inet_csk_ctl_sock_create(struct socket **sock, unsigned short family,
+-			     unsigned short type, unsigned char protocol)
+-{
+-	int rc = sock_create_kern(family, type, protocol, sock);
+-
+-	if (rc == 0) {
+-		(*sock)->sk->sk_allocation = GFP_ATOMIC;
+-		inet_sk((*sock)->sk)->uc_ttl = -1;
+-		/*
+-		 * Unhash it so that IP input processing does not even see it,
+-		 * we do not wish this socket to see incoming packets.
+-		 */
+-		(*sock)->sk->sk_prot->unhash((*sock)->sk);
+-	}
+-	return rc;
+-}
+-
+-EXPORT_SYMBOL_GPL(inet_csk_ctl_sock_create);
+-
+ #ifdef CONFIG_COMPAT
+ int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
+ 			       char __user *optval, int __user *optlen)
+diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
+index a0a3c78..4ed429b 100644
+--- a/net/ipv4/inet_fragment.c
++++ b/net/ipv4/inet_fragment.c
+@@ -107,10 +107,10 @@ void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
+ 	if (del_timer(&fq->timer))
+ 		atomic_dec(&fq->refcnt);
+ 
+-	if (!(fq->last_in & COMPLETE)) {
++	if (!(fq->last_in & INET_FRAG_COMPLETE)) {
+ 		fq_unlink(fq, f);
+ 		atomic_dec(&fq->refcnt);
+-		fq->last_in |= COMPLETE;
++		fq->last_in |= INET_FRAG_COMPLETE;
+ 	}
+ }
+ 
+@@ -134,7 +134,7 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
+ 	struct sk_buff *fp;
+ 	struct netns_frags *nf;
+ 
+-	BUG_TRAP(q->last_in & COMPLETE);
++	BUG_TRAP(q->last_in & INET_FRAG_COMPLETE);
+ 	BUG_TRAP(del_timer(&q->timer) == 0);
+ 
+ 	/* Release all fragment data. */
+@@ -177,7 +177,7 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f)
+ 		read_unlock(&f->lock);
+ 
+ 		spin_lock(&q->lock);
+-		if (!(q->last_in & COMPLETE))
++		if (!(q->last_in & INET_FRAG_COMPLETE))
+ 			inet_frag_kill(q, f);
+ 		spin_unlock(&q->lock);
+ 
+@@ -209,7 +209,7 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
+ 		if (qp->net == nf && f->match(qp, arg)) {
+ 			atomic_inc(&qp->refcnt);
+ 			write_unlock(&f->lock);
+-			qp_in->last_in |= COMPLETE;
++			qp_in->last_in |= INET_FRAG_COMPLETE;
+ 			inet_frag_put(qp_in, f);
+ 			return qp;
+ 		}
+diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
+index 1aba606..2023d37 100644
+--- a/net/ipv4/inet_hashtables.c
++++ b/net/ipv4/inet_hashtables.c
+@@ -35,7 +35,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
+ 	struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC);
+ 
+ 	if (tb != NULL) {
+-		tb->ib_net       = net;
++		tb->ib_net       = hold_net(net);
+ 		tb->port      = snum;
+ 		tb->fastreuse = 0;
+ 		INIT_HLIST_HEAD(&tb->owners);
+@@ -51,6 +51,7 @@ void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket
+ {
+ 	if (hlist_empty(&tb->owners)) {
+ 		__hlist_del(&tb->node);
++		release_net(tb->ib_net);
+ 		kmem_cache_free(cachep, tb);
+ 	}
+ }
+@@ -68,7 +69,7 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
+  */
+ static void __inet_put_port(struct sock *sk)
+ {
+-	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++	struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ 	const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
+ 	struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
+ 	struct inet_bind_bucket *tb;
+@@ -91,6 +92,22 @@ void inet_put_port(struct sock *sk)
+ 
+ EXPORT_SYMBOL(inet_put_port);
+ 
++void __inet_inherit_port(struct sock *sk, struct sock *child)
++{
++	struct inet_hashinfo *table = sk->sk_prot->h.hashinfo;
++	const int bhash = inet_bhashfn(inet_sk(child)->num, 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;
++	sk_add_bind_node(child, &tb->owners);
++	inet_csk(child)->icsk_bind_hash = tb;
++	spin_unlock(&head->lock);
++}
++
++EXPORT_SYMBOL_GPL(__inet_inherit_port);
++
+ /*
+  * This lock without WQ_FLAG_EXCLUSIVE is good on UP and it can be very bad on SMP.
+  * Look, when several writers sleep and reader wakes them up, all but one
+@@ -139,7 +156,7 @@ static struct sock *inet_lookup_listener_slow(struct net *net,
+ 	sk_for_each(sk, node, head) {
+ 		const struct inet_sock *inet = inet_sk(sk);
+ 
+-		if (sk->sk_net == net && inet->num == hnum &&
++		if (net_eq(sock_net(sk), net) && inet->num == hnum &&
+ 				!ipv6_only_sock(sk)) {
+ 			const __be32 rcv_saddr = inet->rcv_saddr;
+ 			int score = sk->sk_family == PF_INET ? 1 : 0;
+@@ -182,7 +199,7 @@ struct sock *__inet_lookup_listener(struct net *net,
+ 		if (inet->num == hnum && !sk->sk_node.next &&
+ 		    (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
+ 		    (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
+-		    !sk->sk_bound_dev_if && sk->sk_net == net)
++		    !sk->sk_bound_dev_if && net_eq(sock_net(sk), net))
+ 			goto sherry_cache;
+ 		sk = inet_lookup_listener_slow(net, head, daddr, hnum, dif);
+ 	}
+@@ -254,7 +271,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
+ 	struct sock *sk2;
+ 	const struct hlist_node *node;
+ 	struct inet_timewait_sock *tw;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 
+ 	prefetch(head->chain.first);
+ 	write_lock(lock);
+@@ -288,7 +305,7 @@ unique:
+ 	sk->sk_hash = hash;
+ 	BUG_TRAP(sk_unhashed(sk));
+ 	__sk_add_node(sk, &head->chain);
+-	sock_prot_inuse_add(sk->sk_prot, 1);
++	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ 	write_unlock(lock);
+ 
+ 	if (twp) {
+@@ -318,7 +335,7 @@ static inline u32 inet_sk_port_offset(const struct sock *sk)
+ 
+ void __inet_hash_nolisten(struct sock *sk)
+ {
+-	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++	struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ 	struct hlist_head *list;
+ 	rwlock_t *lock;
+ 	struct inet_ehash_bucket *head;
+@@ -332,14 +349,14 @@ void __inet_hash_nolisten(struct sock *sk)
+ 
+ 	write_lock(lock);
+ 	__sk_add_node(sk, list);
+-	sock_prot_inuse_add(sk->sk_prot, 1);
++	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ 	write_unlock(lock);
+ }
+ EXPORT_SYMBOL_GPL(__inet_hash_nolisten);
+ 
+ static void __inet_hash(struct sock *sk)
+ {
+-	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++	struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ 	struct hlist_head *list;
+ 	rwlock_t *lock;
+ 
+@@ -354,7 +371,7 @@ static void __inet_hash(struct sock *sk)
+ 
+ 	inet_listen_wlock(hashinfo);
+ 	__sk_add_node(sk, list);
+-	sock_prot_inuse_add(sk->sk_prot, 1);
++	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ 	write_unlock(lock);
+ 	wake_up(&hashinfo->lhash_wait);
+ }
+@@ -372,7 +389,7 @@ EXPORT_SYMBOL_GPL(inet_hash);
+ void inet_unhash(struct sock *sk)
+ {
+ 	rwlock_t *lock;
+-	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++	struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ 
+ 	if (sk_unhashed(sk))
+ 		goto out;
+@@ -387,7 +404,7 @@ void inet_unhash(struct sock *sk)
+ 	}
+ 
+ 	if (__sk_del_node_init(sk))
+-		sock_prot_inuse_add(sk->sk_prot, -1);
++		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ 	write_unlock_bh(lock);
+ out:
+ 	if (sk->sk_state == TCP_LISTEN)
+@@ -406,7 +423,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+ 	struct inet_bind_hashbucket *head;
+ 	struct inet_bind_bucket *tb;
+ 	int ret;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 
+ 	if (!snum) {
+ 		int i, remaining, low, high, port;
+diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
+index 717c411..ce16e9a 100644
+--- a/net/ipv4/inet_timewait_sock.c
++++ b/net/ipv4/inet_timewait_sock.c
+@@ -57,6 +57,7 @@ void inet_twsk_put(struct inet_timewait_sock *tw)
+ 		printk(KERN_DEBUG "%s timewait_sock %p released\n",
+ 		       tw->tw_prot->name, tw);
+ #endif
++		release_net(twsk_net(tw));
+ 		kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw);
+ 		module_put(owner);
+ 	}
+@@ -91,7 +92,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
+ 
+ 	/* Step 2: Remove SK from established hash. */
+ 	if (__sk_del_node_init(sk))
+-		sock_prot_inuse_add(sk->sk_prot, -1);
++		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ 
+ 	/* Step 3: Hash TW into TIMEWAIT chain. */
+ 	inet_twsk_add_node(tw, &ehead->twchain);
+@@ -124,7 +125,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
+ 		tw->tw_hash	    = sk->sk_hash;
+ 		tw->tw_ipv6only	    = 0;
+ 		tw->tw_prot	    = sk->sk_prot_creator;
+-		tw->tw_net          = sk->sk_net;
++		twsk_net_set(tw, hold_net(sock_net(sk)));
+ 		atomic_set(&tw->tw_refcnt, 1);
+ 		inet_twsk_dead_node_init(tw);
+ 		__module_get(tw->tw_prot->owner);
+diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
+index a4506c8..4813c39 100644
+--- a/net/ipv4/ip_forward.c
++++ b/net/ipv4/ip_forward.c
+@@ -80,7 +80,7 @@ int ip_forward(struct sk_buff *skb)
+ 	if (!xfrm4_route_forward(skb))
+ 		goto drop;
+ 
+-	rt = (struct rtable*)skb->dst;
++	rt = skb->rtable;
+ 
+ 	if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
+ 		goto sr_failed;
+diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
+index 3b2e5ad..cd6ce6a 100644
+--- a/net/ipv4/ip_fragment.c
++++ b/net/ipv4/ip_fragment.c
+@@ -194,7 +194,7 @@ static void ip_expire(unsigned long arg)
+ 
+ 	spin_lock(&qp->q.lock);
+ 
+-	if (qp->q.last_in & COMPLETE)
++	if (qp->q.last_in & INET_FRAG_COMPLETE)
+ 		goto out;
+ 
+ 	ipq_kill(qp);
+@@ -202,10 +202,13 @@ static void ip_expire(unsigned long arg)
+ 	IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT);
+ 	IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+ 
+-	if ((qp->q.last_in&FIRST_IN) && qp->q.fragments != NULL) {
++	if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) {
+ 		struct sk_buff *head = qp->q.fragments;
++		struct net *net;
++
++		net = container_of(qp->q.net, struct net, ipv4.frags);
+ 		/* Send an ICMP "Fragment Reassembly Timeout" message. */
+-		if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) {
++		if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) {
+ 			icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
+ 			dev_put(head->dev);
+ 		}
+@@ -298,7 +301,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ 	int ihl, end;
+ 	int err = -ENOENT;
+ 
+-	if (qp->q.last_in & COMPLETE)
++	if (qp->q.last_in & INET_FRAG_COMPLETE)
+ 		goto err;
+ 
+ 	if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
+@@ -324,9 +327,9 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ 		 * or have different end, the segment is corrrupted.
+ 		 */
+ 		if (end < qp->q.len ||
+-		    ((qp->q.last_in & LAST_IN) && end != qp->q.len))
++		    ((qp->q.last_in & INET_FRAG_LAST_IN) && end != qp->q.len))
+ 			goto err;
+-		qp->q.last_in |= LAST_IN;
++		qp->q.last_in |= INET_FRAG_LAST_IN;
+ 		qp->q.len = end;
+ 	} else {
+ 		if (end&7) {
+@@ -336,7 +339,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ 		}
+ 		if (end > qp->q.len) {
+ 			/* Some bits beyond end -> corruption. */
+-			if (qp->q.last_in & LAST_IN)
++			if (qp->q.last_in & INET_FRAG_LAST_IN)
+ 				goto err;
+ 			qp->q.len = end;
+ 		}
+@@ -435,9 +438,10 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ 	qp->q.meat += skb->len;
+ 	atomic_add(skb->truesize, &qp->q.net->mem);
+ 	if (offset == 0)
+-		qp->q.last_in |= FIRST_IN;
++		qp->q.last_in |= INET_FRAG_FIRST_IN;
+ 
+-	if (qp->q.last_in == (FIRST_IN | LAST_IN) && qp->q.meat == qp->q.len)
++	if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
++	    qp->q.meat == qp->q.len)
+ 		return ip_frag_reasm(qp, prev, dev);
+ 
+ 	write_lock(&ip4_frags.lock);
+@@ -553,7 +557,7 @@ out_nomem:
+ out_oversize:
+ 	if (net_ratelimit())
+ 		printk(KERN_INFO
+-			"Oversized IP packet from %d.%d.%d.%d.\n",
++			"Oversized IP packet from " NIPQUAD_FMT ".\n",
+ 			NIPQUAD(qp->saddr));
+ out_fail:
+ 	IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+@@ -568,7 +572,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
+ 
+ 	IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
+ 
+-	net = skb->dev ? skb->dev->nd_net : skb->dst->dev->nd_net;
++	net = skb->dev ? dev_net(skb->dev) : dev_net(skb->dst->dev);
+ 	/* Start by cleaning up the memory. */
+ 	if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh)
+ 		ip_evictor(net);
+diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
+index e7821ba..2ada033 100644
+--- a/net/ipv4/ip_gre.c
++++ b/net/ipv4/ip_gre.c
+@@ -39,6 +39,8 @@
+ #include <net/dsfield.h>
+ #include <net/inet_ecn.h>
+ #include <net/xfrm.h>
++#include <net/net_namespace.h>
++#include <net/netns/generic.h>
+ 
+ #ifdef CONFIG_IPV6
+ #include <net/ipv6.h>
+@@ -122,7 +124,14 @@ static void ipgre_tunnel_setup(struct net_device *dev);
+ 
+ static int ipgre_fb_tunnel_init(struct net_device *dev);
+ 
+-static struct net_device *ipgre_fb_tunnel_dev;
++#define HASH_SIZE  16
++
++static int ipgre_net_id;
++struct ipgre_net {
++	struct ip_tunnel *tunnels[4][HASH_SIZE];
++
++	struct net_device *fb_tunnel_dev;
++};
+ 
+ /* Tunnel hash table */
+ 
+@@ -142,39 +151,38 @@ static struct net_device *ipgre_fb_tunnel_dev;
+    will match fallback tunnel.
+  */
+ 
+-#define HASH_SIZE  16
+ #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
+ 
+-static struct ip_tunnel *tunnels[4][HASH_SIZE];
+-
+-#define tunnels_r_l	(tunnels[3])
+-#define tunnels_r	(tunnels[2])
+-#define tunnels_l	(tunnels[1])
+-#define tunnels_wc	(tunnels[0])
++#define tunnels_r_l	tunnels[3]
++#define tunnels_r	tunnels[2]
++#define tunnels_l	tunnels[1]
++#define tunnels_wc	tunnels[0]
+ 
+ static DEFINE_RWLOCK(ipgre_lock);
+ 
+ /* Given src, dst and key, find appropriate for input tunnel. */
+ 
+-static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be32 key)
++static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,
++		__be32 remote, __be32 local, __be32 key)
+ {
+ 	unsigned h0 = HASH(remote);
+ 	unsigned h1 = HASH(key);
+ 	struct ip_tunnel *t;
++	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+ 
+-	for (t = tunnels_r_l[h0^h1]; t; t = t->next) {
++	for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {
+ 		if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
+ 			if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ 				return t;
+ 		}
+ 	}
+-	for (t = tunnels_r[h0^h1]; t; t = t->next) {
++	for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {
+ 		if (remote == t->parms.iph.daddr) {
+ 			if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ 				return t;
+ 		}
+ 	}
+-	for (t = tunnels_l[h1]; t; t = t->next) {
++	for (t = ign->tunnels_l[h1]; t; t = t->next) {
+ 		if (local == t->parms.iph.saddr ||
+ 		     (local == t->parms.iph.daddr &&
+ 		      ipv4_is_multicast(local))) {
+@@ -182,17 +190,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be3
+ 				return t;
+ 		}
+ 	}
+-	for (t = tunnels_wc[h1]; t; t = t->next) {
++	for (t = ign->tunnels_wc[h1]; t; t = t->next) {
+ 		if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ 			return t;
+ 	}
+ 
+-	if (ipgre_fb_tunnel_dev->flags&IFF_UP)
+-		return netdev_priv(ipgre_fb_tunnel_dev);
++	if (ign->fb_tunnel_dev->flags&IFF_UP)
++		return netdev_priv(ign->fb_tunnel_dev);
+ 	return NULL;
+ }
+ 
+-static struct ip_tunnel **__ipgre_bucket(struct ip_tunnel_parm *parms)
++static struct ip_tunnel **__ipgre_bucket(struct ipgre_net *ign,
++		struct ip_tunnel_parm *parms)
+ {
+ 	__be32 remote = parms->iph.daddr;
+ 	__be32 local = parms->iph.saddr;
+@@ -207,17 +216,18 @@ static struct ip_tunnel **__ipgre_bucket(struct ip_tunnel_parm *parms)
+ 		h ^= HASH(remote);
+ 	}
+ 
+-	return &tunnels[prio][h];
++	return &ign->tunnels[prio][h];
+ }
+ 
+-static inline struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t)
++static inline struct ip_tunnel **ipgre_bucket(struct ipgre_net *ign,
++		struct ip_tunnel *t)
+ {
+-	return __ipgre_bucket(&t->parms);
++	return __ipgre_bucket(ign, &t->parms);
+ }
+ 
+-static void ipgre_tunnel_link(struct ip_tunnel *t)
++static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
+ {
+-	struct ip_tunnel **tp = ipgre_bucket(t);
++	struct ip_tunnel **tp = ipgre_bucket(ign, t);
+ 
+ 	t->next = *tp;
+ 	write_lock_bh(&ipgre_lock);
+@@ -225,11 +235,11 @@ static void ipgre_tunnel_link(struct ip_tunnel *t)
+ 	write_unlock_bh(&ipgre_lock);
+ }
+ 
+-static void ipgre_tunnel_unlink(struct ip_tunnel *t)
++static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
+ {
+ 	struct ip_tunnel **tp;
+ 
+-	for (tp = ipgre_bucket(t); *tp; tp = &(*tp)->next) {
++	for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) {
+ 		if (t == *tp) {
+ 			write_lock_bh(&ipgre_lock);
+ 			*tp = t->next;
+@@ -239,7 +249,8 @@ static void ipgre_tunnel_unlink(struct ip_tunnel *t)
+ 	}
+ }
+ 
+-static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create)
++static struct ip_tunnel * ipgre_tunnel_locate(struct net *net,
++		struct ip_tunnel_parm *parms, int create)
+ {
+ 	__be32 remote = parms->iph.daddr;
+ 	__be32 local = parms->iph.saddr;
+@@ -247,8 +258,9 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
+ 	struct ip_tunnel *t, **tp, *nt;
+ 	struct net_device *dev;
+ 	char name[IFNAMSIZ];
++	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+ 
+-	for (tp = __ipgre_bucket(parms); (t = *tp) != NULL; tp = &t->next) {
++	for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next) {
+ 		if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
+ 			if (key == t->parms.i_key)
+ 				return t;
+@@ -266,6 +278,8 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
+ 	if (!dev)
+ 	  return NULL;
+ 
++	dev_net_set(dev, net);
++
+ 	if (strchr(name, '%')) {
+ 		if (dev_alloc_name(dev, name) < 0)
+ 			goto failed_free;
+@@ -279,7 +293,7 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
+ 		goto failed_free;
+ 
+ 	dev_hold(dev);
+-	ipgre_tunnel_link(nt);
++	ipgre_tunnel_link(ign, nt);
+ 	return nt;
+ 
+ failed_free:
+@@ -289,7 +303,10 @@ failed_free:
+ 
+ static void ipgre_tunnel_uninit(struct net_device *dev)
+ {
+-	ipgre_tunnel_unlink(netdev_priv(dev));
++	struct net *net = dev_net(dev);
++	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
++
++	ipgre_tunnel_unlink(ign, netdev_priv(dev));
+ 	dev_put(dev);
+ }
+ 
+@@ -363,7 +380,9 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
+ 	}
+ 
+ 	read_lock(&ipgre_lock);
+-	t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((__be32*)p) + (grehlen>>2) - 1) : 0);
++	t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr,
++			(flags&GRE_KEY) ?
++			*(((__be32*)p) + (grehlen>>2) - 1) : 0);
+ 	if (t == NULL || t->parms.iph.daddr == 0 ||
+ 	    ipv4_is_multicast(t->parms.iph.daddr))
+ 		goto out;
+@@ -476,7 +495,7 @@ out:
+ 	fl.fl4_dst = eiph->saddr;
+ 	fl.fl4_tos = RT_TOS(eiph->tos);
+ 	fl.proto = IPPROTO_GRE;
+-	if (ip_route_output_key(&init_net, &rt, &fl)) {
++	if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) {
+ 		kfree_skb(skb2);
+ 		return;
+ 	}
+@@ -489,7 +508,7 @@ out:
+ 		fl.fl4_dst = eiph->daddr;
+ 		fl.fl4_src = eiph->saddr;
+ 		fl.fl4_tos = eiph->tos;
+-		if (ip_route_output_key(&init_net, &rt, &fl) ||
++		if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) ||
+ 		    rt->u.dst.dev->type != ARPHRD_IPGRE) {
+ 			ip_rt_put(rt);
+ 			kfree_skb(skb2);
+@@ -596,7 +615,8 @@ static int ipgre_rcv(struct sk_buff *skb)
+ 	}
+ 
+ 	read_lock(&ipgre_lock);
+-	if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) {
++	if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev),
++					iph->saddr, iph->daddr, key)) != NULL) {
+ 		secpath_reset(skb);
+ 
+ 		skb->protocol = *(__be16*)(h + 2);
+@@ -619,7 +639,7 @@ static int ipgre_rcv(struct sk_buff *skb)
+ #ifdef CONFIG_NET_IPGRE_BROADCAST
+ 		if (ipv4_is_multicast(iph->daddr)) {
+ 			/* Looped back packet, drop it! */
+-			if (((struct rtable*)skb->dst)->fl.iif == 0)
++			if (skb->rtable->fl.iif == 0)
+ 				goto drop;
+ 			tunnel->stat.multicast++;
+ 			skb->pkt_type = PACKET_BROADCAST;
+@@ -699,7 +719,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		}
+ 
+ 		if (skb->protocol == htons(ETH_P_IP)) {
+-			rt = (struct rtable*)skb->dst;
++			rt = skb->rtable;
+ 			if ((dst = rt->rt_gateway) == 0)
+ 				goto tx_error_icmp;
+ 		}
+@@ -744,7 +764,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ 						.saddr = tiph->saddr,
+ 						.tos = RT_TOS(tos) } },
+ 				    .proto = IPPROTO_GRE };
+-		if (ip_route_output_key(&init_net, &rt, &fl)) {
++		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ 			tunnel->stat.tx_carrier_errors++;
+ 			goto tx_error;
+ 		}
+@@ -917,7 +937,7 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev)
+ 						.tos = RT_TOS(iph->tos) } },
+ 				    .proto = IPPROTO_GRE };
+ 		struct rtable *rt;
+-		if (!ip_route_output_key(&init_net, &rt, &fl)) {
++		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ 			tdev = rt->u.dst.dev;
+ 			ip_rt_put(rt);
+ 		}
+@@ -925,7 +945,7 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev)
+ 	}
+ 
+ 	if (!tdev && tunnel->parms.link)
+-		tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
++		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
+ 
+ 	if (tdev) {
+ 		hlen = tdev->hard_header_len;
+@@ -954,16 +974,18 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 	int err = 0;
+ 	struct ip_tunnel_parm p;
+ 	struct ip_tunnel *t;
++	struct net *net = dev_net(dev);
++	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+ 
+ 	switch (cmd) {
+ 	case SIOCGETTUNNEL:
+ 		t = NULL;
+-		if (dev == ipgre_fb_tunnel_dev) {
++		if (dev == ign->fb_tunnel_dev) {
+ 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
+ 				err = -EFAULT;
+ 				break;
+ 			}
+-			t = ipgre_tunnel_locate(&p, 0);
++			t = ipgre_tunnel_locate(net, &p, 0);
+ 		}
+ 		if (t == NULL)
+ 			t = netdev_priv(dev);
+@@ -995,9 +1017,9 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		if (!(p.o_flags&GRE_KEY))
+ 			p.o_key = 0;
+ 
+-		t = ipgre_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
++		t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
+ 
+-		if (dev != ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
++		if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
+ 			if (t != NULL) {
+ 				if (t->dev != dev) {
+ 					err = -EEXIST;
+@@ -1017,14 +1039,14 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 					err = -EINVAL;
+ 					break;
+ 				}
+-				ipgre_tunnel_unlink(t);
++				ipgre_tunnel_unlink(ign, t);
+ 				t->parms.iph.saddr = p.iph.saddr;
+ 				t->parms.iph.daddr = p.iph.daddr;
+ 				t->parms.i_key = p.i_key;
+ 				t->parms.o_key = p.o_key;
+ 				memcpy(dev->dev_addr, &p.iph.saddr, 4);
+ 				memcpy(dev->broadcast, &p.iph.daddr, 4);
+-				ipgre_tunnel_link(t);
++				ipgre_tunnel_link(ign, t);
+ 				netdev_state_change(dev);
+ 			}
+ 		}
+@@ -1052,15 +1074,15 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		if (!capable(CAP_NET_ADMIN))
+ 			goto done;
+ 
+-		if (dev == ipgre_fb_tunnel_dev) {
++		if (dev == ign->fb_tunnel_dev) {
+ 			err = -EFAULT;
+ 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ 				goto done;
+ 			err = -ENOENT;
+-			if ((t = ipgre_tunnel_locate(&p, 0)) == NULL)
++			if ((t = ipgre_tunnel_locate(net, &p, 0)) == NULL)
+ 				goto done;
+ 			err = -EPERM;
+-			if (t == netdev_priv(ipgre_fb_tunnel_dev))
++			if (t == netdev_priv(ign->fb_tunnel_dev))
+ 				goto done;
+ 			dev = t->dev;
+ 		}
+@@ -1173,7 +1195,7 @@ static int ipgre_open(struct net_device *dev)
+ 						.tos = RT_TOS(t->parms.iph.tos) } },
+ 				    .proto = IPPROTO_GRE };
+ 		struct rtable *rt;
+-		if (ip_route_output_key(&init_net, &rt, &fl))
++		if (ip_route_output_key(dev_net(dev), &rt, &fl))
+ 			return -EADDRNOTAVAIL;
+ 		dev = rt->u.dst.dev;
+ 		ip_rt_put(rt);
+@@ -1190,7 +1212,7 @@ static int ipgre_close(struct net_device *dev)
+ 	struct ip_tunnel *t = netdev_priv(dev);
+ 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
+ 		struct in_device *in_dev;
+-		in_dev = inetdev_by_index(dev->nd_net, t->mlink);
++		in_dev = inetdev_by_index(dev_net(dev), t->mlink);
+ 		if (in_dev) {
+ 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
+ 			in_dev_put(in_dev);
+@@ -1216,6 +1238,7 @@ static void ipgre_tunnel_setup(struct net_device *dev)
+ 	dev->flags		= IFF_NOARP;
+ 	dev->iflink		= 0;
+ 	dev->addr_len		= 4;
++	dev->features		|= NETIF_F_NETNS_LOCAL;
+ }
+ 
+ static int ipgre_tunnel_init(struct net_device *dev)
+@@ -1251,10 +1274,11 @@ static int ipgre_tunnel_init(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static int __init ipgre_fb_tunnel_init(struct net_device *dev)
++static int ipgre_fb_tunnel_init(struct net_device *dev)
+ {
+ 	struct ip_tunnel *tunnel = netdev_priv(dev);
+ 	struct iphdr *iph = &tunnel->parms.iph;
++	struct ipgre_net *ign = net_generic(dev_net(dev), ipgre_net_id);
+ 
+ 	tunnel->dev = dev;
+ 	strcpy(tunnel->parms.name, dev->name);
+@@ -1265,7 +1289,7 @@ static int __init ipgre_fb_tunnel_init(struct net_device *dev)
+ 	tunnel->hlen		= sizeof(struct iphdr) + 4;
+ 
+ 	dev_hold(dev);
+-	tunnels_wc[0]		= tunnel;
++	ign->tunnels_wc[0]	= tunnel;
+ 	return 0;
+ }
+ 
+@@ -1273,56 +1297,98 @@ static int __init ipgre_fb_tunnel_init(struct net_device *dev)
+ static struct net_protocol ipgre_protocol = {
+ 	.handler	=	ipgre_rcv,
+ 	.err_handler	=	ipgre_err,
++	.netns_ok	=	1,
+ };
+ 
++static void ipgre_destroy_tunnels(struct ipgre_net *ign)
++{
++	int prio;
+ 
+-/*
+- *	And now the modules code and kernel interface.
+- */
++	for (prio = 0; prio < 4; prio++) {
++		int h;
++		for (h = 0; h < HASH_SIZE; h++) {
++			struct ip_tunnel *t;
++			while ((t = ign->tunnels[prio][h]) != NULL)
++				unregister_netdevice(t->dev);
++		}
++	}
++}
+ 
+-static int __init ipgre_init(void)
++static int ipgre_init_net(struct net *net)
+ {
+ 	int err;
++	struct ipgre_net *ign;
+ 
+-	printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
++	err = -ENOMEM;
++	ign = kzalloc(sizeof(struct ipgre_net), GFP_KERNEL);
++	if (ign == NULL)
++		goto err_alloc;
+ 
+-	if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) {
+-		printk(KERN_INFO "ipgre init: can't add protocol\n");
+-		return -EAGAIN;
+-	}
++	err = net_assign_generic(net, ipgre_net_id, ign);
++	if (err < 0)
++		goto err_assign;
+ 
+-	ipgre_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
++	ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
+ 					   ipgre_tunnel_setup);
+-	if (!ipgre_fb_tunnel_dev) {
++	if (!ign->fb_tunnel_dev) {
+ 		err = -ENOMEM;
+-		goto err1;
++		goto err_alloc_dev;
+ 	}
+ 
+-	ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init;
++	ign->fb_tunnel_dev->init = ipgre_fb_tunnel_init;
++	dev_net_set(ign->fb_tunnel_dev, net);
+ 
+-	if ((err = register_netdev(ipgre_fb_tunnel_dev)))
+-		goto err2;
+-out:
++	if ((err = register_netdev(ign->fb_tunnel_dev)))
++		goto err_reg_dev;
++
++	return 0;
++
++err_reg_dev:
++	free_netdev(ign->fb_tunnel_dev);
++err_alloc_dev:
++	/* nothing */
++err_assign:
++	kfree(ign);
++err_alloc:
+ 	return err;
+-err2:
+-	free_netdev(ipgre_fb_tunnel_dev);
+-err1:
+-	inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+-	goto out;
+ }
+ 
+-static void __exit ipgre_destroy_tunnels(void)
++static void ipgre_exit_net(struct net *net)
+ {
+-	int prio;
++	struct ipgre_net *ign;
+ 
+-	for (prio = 0; prio < 4; prio++) {
+-		int h;
+-		for (h = 0; h < HASH_SIZE; h++) {
+-			struct ip_tunnel *t;
+-			while ((t = tunnels[prio][h]) != NULL)
+-				unregister_netdevice(t->dev);
+-		}
++	ign = net_generic(net, ipgre_net_id);
++	rtnl_lock();
++	ipgre_destroy_tunnels(ign);
++	rtnl_unlock();
++	kfree(ign);
++}
++
++static struct pernet_operations ipgre_net_ops = {
++	.init = ipgre_init_net,
++	.exit = ipgre_exit_net,
++};
++
++/*
++ *	And now the modules code and kernel interface.
++ */
++
++static int __init ipgre_init(void)
++{
++	int err;
++
++	printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
++
++	if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) {
++		printk(KERN_INFO "ipgre init: can't add protocol\n");
++		return -EAGAIN;
+ 	}
++
++	err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops);
++	if (err < 0)
++		inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
++
++	return err;
+ }
+ 
+ static void __exit ipgre_fini(void)
+@@ -1330,9 +1396,7 @@ static void __exit ipgre_fini(void)
+ 	if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
+ 		printk(KERN_INFO "ipgre close: can't remove protocol\n");
+ 
+-	rtnl_lock();
+-	ipgre_destroy_tunnels();
+-	rtnl_unlock();
++	unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
+ }
+ 
+ module_init(ipgre_init);
+diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
+index 6563139..7b4bad6 100644
+--- a/net/ipv4/ip_input.c
++++ b/net/ipv4/ip_input.c
+@@ -160,6 +160,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
+ 	struct ip_ra_chain *ra;
+ 	u8 protocol = ip_hdr(skb)->protocol;
+ 	struct sock *last = NULL;
++	struct net_device *dev = skb->dev;
+ 
+ 	read_lock(&ip_ra_lock);
+ 	for (ra = ip_ra_chain; ra; ra = ra->next) {
+@@ -170,7 +171,8 @@ int ip_call_ra_chain(struct sk_buff *skb)
+ 		 */
+ 		if (sk && inet_sk(sk)->num == protocol &&
+ 		    (!sk->sk_bound_dev_if ||
+-		     sk->sk_bound_dev_if == skb->dev->ifindex)) {
++		     sk->sk_bound_dev_if == dev->ifindex) &&
++		    sock_net(sk) == dev_net(dev)) {
+ 			if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+ 				if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) {
+ 					read_unlock(&ip_ra_lock);
+@@ -197,6 +199,8 @@ int ip_call_ra_chain(struct sk_buff *skb)
+ 
+ static int ip_local_deliver_finish(struct sk_buff *skb)
+ {
++	struct net *net = dev_net(skb->dev);
++
+ 	__skb_pull(skb, ip_hdrlen(skb));
+ 
+ 	/* Point into the IP datagram, just past the header. */
+@@ -212,7 +216,8 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
+ 		raw = raw_local_deliver(skb, protocol);
+ 
+ 		hash = protocol & (MAX_INET_PROTOS - 1);
+-		if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
++		ipprot = rcu_dereference(inet_protos[hash]);
++		if (ipprot != NULL && (net == &init_net || ipprot->netns_ok)) {
+ 			int ret;
+ 
+ 			if (!ipprot->no_policy) {
+@@ -283,13 +288,14 @@ static inline int ip_rcv_options(struct sk_buff *skb)
+ 	}
+ 
+ 	iph = ip_hdr(skb);
++	opt = &(IPCB(skb)->opt);
++	opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
+ 
+-	if (ip_options_compile(NULL, skb)) {
++	if (ip_options_compile(dev_net(dev), opt, skb)) {
+ 		IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ 		goto drop;
+ 	}
+ 
+-	opt = &(IPCB(skb)->opt);
+ 	if (unlikely(opt->srr)) {
+ 		struct in_device *in_dev = in_dev_get(dev);
+ 		if (in_dev) {
+@@ -297,7 +303,7 @@ static inline int ip_rcv_options(struct sk_buff *skb)
+ 				if (IN_DEV_LOG_MARTIANS(in_dev) &&
+ 				    net_ratelimit())
+ 					printk(KERN_INFO "source route option "
+-					       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
++					       NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
+ 					       NIPQUAD(iph->saddr),
+ 					       NIPQUAD(iph->daddr));
+ 				in_dev_put(in_dev);
+@@ -351,7 +357,7 @@ static int ip_rcv_finish(struct sk_buff *skb)
+ 	if (iph->ihl > 5 && ip_rcv_options(skb))
+ 		goto drop;
+ 
+-	rt = (struct rtable*)skb->dst;
++	rt = skb->rtable;
+ 	if (rt->rt_type == RTN_MULTICAST)
+ 		IP_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS);
+ 	else if (rt->rt_type == RTN_BROADCAST)
+@@ -372,9 +378,6 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
+ 	struct iphdr *iph;
+ 	u32 len;
+ 
+-	if (dev->nd_net != &init_net)
+-		goto drop;
+-
+ 	/* When the interface is in promisc. mode, drop all the crap
+ 	 * that it receives, do not try to analyse it.
+ 	 */
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index 4d31515..33126ad 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -45,7 +45,6 @@ void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
+ 	memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options));
+ 	memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen);
+ 	opt = &(IPCB(skb)->opt);
+-	opt->is_data = 0;
+ 
+ 	if (opt->srr)
+ 		memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4);
+@@ -56,10 +55,10 @@ void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
+ 		if (opt->ts_needaddr)
+ 			ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt);
+ 		if (opt->ts_needtime) {
+-			struct timeval tv;
++			struct timespec tv;
+ 			__be32 midtime;
+-			do_gettimeofday(&tv);
+-			midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
++			getnstimeofday(&tv);
++			midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC);
+ 			memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4);
+ 		}
+ 		return;
+@@ -95,8 +94,6 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
+ 
+ 	memset(dopt, 0, sizeof(struct ip_options));
+ 
+-	dopt->is_data = 1;
+-
+ 	sopt = &(IPCB(skb)->opt);
+ 
+ 	if (sopt->optlen == 0) {
+@@ -107,10 +104,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
+ 	sptr = skb_network_header(skb);
+ 	dptr = dopt->__data;
+ 
+-	if (skb->dst)
+-		daddr = ((struct rtable*)skb->dst)->rt_spec_dst;
+-	else
+-		daddr = ip_hdr(skb)->daddr;
++	daddr = skb->rtable->rt_spec_dst;
+ 
+ 	if (sopt->rr) {
+ 		optlen  = sptr[sopt->rr+1];
+@@ -151,7 +145,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
+ 						__be32 addr;
+ 
+ 						memcpy(&addr, sptr+soffset-1, 4);
+-						if (inet_addr_type(&init_net, addr) != RTN_LOCAL) {
++						if (inet_addr_type(dev_net(skb->dst->dev), addr) != RTN_LOCAL) {
+ 							dopt->ts_needtime = 1;
+ 							soffset += 8;
+ 						}
+@@ -254,26 +248,22 @@ void ip_options_fragment(struct sk_buff * skb)
+  * If opt == NULL, then skb->data should point to IP header.
+  */
+ 
+-int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
++int ip_options_compile(struct net *net,
++		       struct ip_options * opt, struct sk_buff * skb)
+ {
+ 	int l;
+ 	unsigned char * iph;
+ 	unsigned char * optptr;
+ 	int optlen;
+ 	unsigned char * pp_ptr = NULL;
+-	struct rtable *rt = skb ? (struct rtable*)skb->dst : NULL;
+-
+-	if (!opt) {
+-		opt = &(IPCB(skb)->opt);
+-		iph = skb_network_header(skb);
+-		opt->optlen = ((struct iphdr *)iph)->ihl*4 - sizeof(struct iphdr);
+-		optptr = iph + sizeof(struct iphdr);
+-		opt->is_data = 0;
+-	} else {
+-		optptr = opt->is_data ? opt->__data :
+-					(unsigned char *)&(ip_hdr(skb)[1]);
+-		iph = optptr - sizeof(struct iphdr);
+-	}
++	struct rtable *rt = NULL;
++
++	if (skb != NULL) {
++		rt = skb->rtable;
++		optptr = (unsigned char *)&(ip_hdr(skb)[1]);
++	} else
++		optptr = opt->__data;
++	iph = optptr - sizeof(struct iphdr);
+ 
+ 	for (l = opt->optlen; l > 0; ) {
+ 		switch (*optptr) {
+@@ -400,7 +390,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
+ 					{
+ 						__be32 addr;
+ 						memcpy(&addr, &optptr[optptr[2]-1], 4);
+-						if (inet_addr_type(&init_net, addr) == RTN_UNICAST)
++						if (inet_addr_type(net, addr) == RTN_UNICAST)
+ 							break;
+ 						if (skb)
+ 							timeptr = (__be32*)&optptr[optptr[2]+3];
+@@ -416,10 +406,10 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
+ 					break;
+ 				}
+ 				if (timeptr) {
+-					struct timeval tv;
++					struct timespec tv;
+ 					__be32  midtime;
+-					do_gettimeofday(&tv);
+-					midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
++					getnstimeofday(&tv);
++					midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC);
+ 					memcpy(timeptr, &midtime, sizeof(__be32));
+ 					opt->is_changed = 1;
+ 				}
+@@ -517,14 +507,13 @@ static struct ip_options *ip_options_get_alloc(const int optlen)
+ 		       GFP_KERNEL);
+ }
+ 
+-static int ip_options_get_finish(struct ip_options **optp,
++static int ip_options_get_finish(struct net *net, struct ip_options **optp,
+ 				 struct ip_options *opt, int optlen)
+ {
+ 	while (optlen & 3)
+ 		opt->__data[optlen++] = IPOPT_END;
+ 	opt->optlen = optlen;
+-	opt->is_data = 1;
+-	if (optlen && ip_options_compile(opt, NULL)) {
++	if (optlen && ip_options_compile(net, opt, NULL)) {
+ 		kfree(opt);
+ 		return -EINVAL;
+ 	}
+@@ -533,7 +522,8 @@ static int ip_options_get_finish(struct ip_options **optp,
+ 	return 0;
+ }
+ 
+-int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen)
++int ip_options_get_from_user(struct net *net, struct ip_options **optp,
++			     unsigned char __user *data, int optlen)
+ {
+ 	struct ip_options *opt = ip_options_get_alloc(optlen);
+ 
+@@ -543,10 +533,11 @@ int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *dat
+ 		kfree(opt);
+ 		return -EFAULT;
+ 	}
+-	return ip_options_get_finish(optp, opt, optlen);
++	return ip_options_get_finish(net, optp, opt, optlen);
+ }
+ 
+-int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen)
++int ip_options_get(struct net *net, struct ip_options **optp,
++		   unsigned char *data, int optlen)
+ {
+ 	struct ip_options *opt = ip_options_get_alloc(optlen);
+ 
+@@ -554,14 +545,14 @@ int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen)
+ 		return -ENOMEM;
+ 	if (optlen)
+ 		memcpy(opt->__data, data, optlen);
+-	return ip_options_get_finish(optp, opt, optlen);
++	return ip_options_get_finish(net, optp, opt, optlen);
+ }
+ 
+ void ip_forward_options(struct sk_buff *skb)
+ {
+ 	struct   ip_options * opt	= &(IPCB(skb)->opt);
+ 	unsigned char * optptr;
+-	struct rtable *rt = (struct rtable*)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	unsigned char *raw = skb_network_header(skb);
+ 
+ 	if (opt->rr_needaddr) {
+@@ -609,7 +600,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
+ 	__be32 nexthop;
+ 	struct iphdr *iph = ip_hdr(skb);
+ 	unsigned char *optptr = skb_network_header(skb) + opt->srr;
+-	struct rtable *rt = (struct rtable*)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	struct rtable *rt2;
+ 	int err;
+ 
+@@ -634,13 +625,13 @@ int ip_options_rcv_srr(struct sk_buff *skb)
+ 		}
+ 		memcpy(&nexthop, &optptr[srrptr-1], 4);
+ 
+-		rt = (struct rtable*)skb->dst;
+-		skb->dst = NULL;
++		rt = skb->rtable;
++		skb->rtable = NULL;
+ 		err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev);
+-		rt2 = (struct rtable*)skb->dst;
++		rt2 = skb->rtable;
+ 		if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) {
+ 			ip_rt_put(rt2);
+-			skb->dst = &rt->u.dst;
++			skb->rtable = rt;
+ 			return -EINVAL;
+ 		}
+ 		ip_rt_put(rt);
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index 341779e..0834926 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -142,7 +142,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
+ 			  __be32 saddr, __be32 daddr, struct ip_options *opt)
+ {
+ 	struct inet_sock *inet = inet_sk(sk);
+-	struct rtable *rt = (struct rtable *)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	struct iphdr *iph;
+ 
+ 	/* Build the IP header. */
+@@ -240,7 +240,7 @@ static int ip_finish_output(struct sk_buff *skb)
+ int ip_mc_output(struct sk_buff *skb)
+ {
+ 	struct sock *sk = skb->sk;
+-	struct rtable *rt = (struct rtable*)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	struct net_device *dev = rt->u.dst.dev;
+ 
+ 	/*
+@@ -321,7 +321,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
+ 	/* Skip all of this if the packet is already routed,
+ 	 * f.e. by something like SCTP.
+ 	 */
+-	rt = (struct rtable *) skb->dst;
++	rt = skb->rtable;
+ 	if (rt != NULL)
+ 		goto packet_routed;
+ 
+@@ -351,7 +351,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
+ 			 * itself out.
+ 			 */
+ 			security_sk_classify_flow(sk, &fl);
+-			if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0))
++			if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0))
+ 				goto no_route;
+ 		}
+ 		sk_setup_caps(sk, &rt->u.dst);
+@@ -441,7 +441,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+ 	unsigned int mtu, hlen, left, len, ll_rs, pad;
+ 	int offset;
+ 	__be16 not_last_frag;
+-	struct rtable *rt = (struct rtable*)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	int err = 0;
+ 
+ 	dev = rt->u.dst.dev;
+@@ -825,7 +825,7 @@ int ip_append_data(struct sock *sk,
+ 		inet->cork.fragsize = mtu = inet->pmtudisc == IP_PMTUDISC_PROBE ?
+ 					    rt->u.dst.dev->mtu :
+ 					    dst_mtu(rt->u.dst.path);
+-		inet->cork.rt = rt;
++		inet->cork.dst = &rt->u.dst;
+ 		inet->cork.length = 0;
+ 		sk->sk_sndmsg_page = NULL;
+ 		sk->sk_sndmsg_off = 0;
+@@ -834,7 +834,7 @@ int ip_append_data(struct sock *sk,
+ 			transhdrlen += exthdrlen;
+ 		}
+ 	} else {
+-		rt = inet->cork.rt;
++		rt = (struct rtable *)inet->cork.dst;
+ 		if (inet->cork.flags & IPCORK_OPT)
+ 			opt = inet->cork.opt;
+ 
+@@ -1083,7 +1083,7 @@ ssize_t	ip_append_page(struct sock *sk, struct page *page,
+ 	if (skb_queue_empty(&sk->sk_write_queue))
+ 		return -EINVAL;
+ 
+-	rt = inet->cork.rt;
++	rt = (struct rtable *)inet->cork.dst;
+ 	if (inet->cork.flags & IPCORK_OPT)
+ 		opt = inet->cork.opt;
+ 
+@@ -1208,10 +1208,8 @@ static void ip_cork_release(struct inet_sock *inet)
+ 	inet->cork.flags &= ~IPCORK_OPT;
+ 	kfree(inet->cork.opt);
+ 	inet->cork.opt = NULL;
+-	if (inet->cork.rt) {
+-		ip_rt_put(inet->cork.rt);
+-		inet->cork.rt = NULL;
+-	}
++	dst_release(inet->cork.dst);
++	inet->cork.dst = NULL;
+ }
+ 
+ /*
+@@ -1224,7 +1222,7 @@ int ip_push_pending_frames(struct sock *sk)
+ 	struct sk_buff **tail_skb;
+ 	struct inet_sock *inet = inet_sk(sk);
+ 	struct ip_options *opt = NULL;
+-	struct rtable *rt = inet->cork.rt;
++	struct rtable *rt = (struct rtable *)inet->cork.dst;
+ 	struct iphdr *iph;
+ 	__be16 df = 0;
+ 	__u8 ttl;
+@@ -1357,7 +1355,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
+ 	} replyopts;
+ 	struct ipcm_cookie ipc;
+ 	__be32 daddr;
+-	struct rtable *rt = (struct rtable*)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 
+ 	if (ip_options_echo(&replyopts.opt, skb))
+ 		return;
+@@ -1384,7 +1382,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
+ 						 .dport = tcp_hdr(skb)->source } },
+ 				    .proto = sk->sk_protocol };
+ 		security_skb_classify_flow(skb, &fl);
+-		if (ip_route_output_key(sk->sk_net, &rt, &fl))
++		if (ip_route_output_key(sock_net(sk), &rt, &fl))
+ 			return;
+ 	}
+ 
+diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
+index c2921d0..d8adfd4 100644
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -57,7 +57,7 @@
+ static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
+ {
+ 	struct in_pktinfo info;
+-	struct rtable *rt = (struct rtable *)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 
+ 	info.ipi_addr.s_addr = ip_hdr(skb)->daddr;
+ 	if (rt) {
+@@ -163,7 +163,7 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
+ 		ip_cmsg_recv_security(msg, skb);
+ }
+ 
+-int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
++int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc)
+ {
+ 	int err;
+ 	struct cmsghdr *cmsg;
+@@ -176,7 +176,7 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
+ 		switch (cmsg->cmsg_type) {
+ 		case IP_RETOPTS:
+ 			err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
+-			err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40);
++			err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40);
+ 			if (err)
+ 				return err;
+ 			break;
+@@ -449,7 +449,8 @@ static int do_ip_setsockopt(struct sock *sk, int level,
+ 		struct ip_options * opt = NULL;
+ 		if (optlen > 40 || optlen < 0)
+ 			goto e_inval;
+-		err = ip_options_get_from_user(&opt, optval, optlen);
++		err = ip_options_get_from_user(sock_net(sk), &opt,
++					       optval, optlen);
+ 		if (err)
+ 			break;
+ 		if (inet->is_icsk) {
+@@ -589,13 +590,13 @@ static int do_ip_setsockopt(struct sock *sk, int level,
+ 				err = 0;
+ 				break;
+ 			}
+-			dev = ip_dev_find(&init_net, mreq.imr_address.s_addr);
++			dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr);
+ 			if (dev) {
+ 				mreq.imr_ifindex = dev->ifindex;
+ 				dev_put(dev);
+ 			}
+ 		} else
+-			dev = __dev_get_by_index(&init_net, mreq.imr_ifindex);
++			dev = __dev_get_by_index(sock_net(sk), mreq.imr_ifindex);
+ 
+ 
+ 		err = -EADDRNOTAVAIL;
+diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
+index 58b60b2..a75807b 100644
+--- a/net/ipv4/ipcomp.c
++++ b/net/ipv4/ipcomp.c
+@@ -14,7 +14,6 @@
+  *   - Adaptive compression.
+  */
+ #include <linux/module.h>
+-#include <asm/semaphore.h>
+ #include <linux/crypto.h>
+ #include <linux/err.h>
+ #include <linux/pfkeyv2.h>
+@@ -179,7 +178,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
+ 			      spi, IPPROTO_COMP, AF_INET);
+ 	if (!x)
+ 		return;
+-	NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%u.%u.%u.%u\n",
++	NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" NIPQUAD_FMT "\n",
+ 		 spi, NIPQUAD(iph->daddr));
+ 	xfrm_state_put(x);
+ }
+diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
+index 4824fe8..0f42d1c 100644
+--- a/net/ipv4/ipconfig.c
++++ b/net/ipv4/ipconfig.c
+@@ -292,7 +292,7 @@ static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
+ 
+ 	mm_segment_t oldfs = get_fs();
+ 	set_fs(get_ds());
+-	res = devinet_ioctl(cmd, (struct ifreq __user *) arg);
++	res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
+ 	set_fs(oldfs);
+ 	return res;
+ }
+@@ -376,7 +376,7 @@ static int __init ic_defaults(void)
+ 	 */
+ 
+ 	if (!ic_host_name_set)
+-		sprintf(init_utsname()->nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr));
++		sprintf(init_utsname()->nodename, NIPQUAD_FMT, NIPQUAD(ic_myaddr));
+ 
+ 	if (root_server_addr == NONE)
+ 		root_server_addr = ic_servaddr;
+@@ -389,11 +389,11 @@ static int __init ic_defaults(void)
+ 		else if (IN_CLASSC(ntohl(ic_myaddr)))
+ 			ic_netmask = htonl(IN_CLASSC_NET);
+ 		else {
+-			printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n",
++			printk(KERN_ERR "IP-Config: Unable to guess netmask for address " NIPQUAD_FMT "\n",
+ 				NIPQUAD(ic_myaddr));
+ 			return -1;
+ 		}
+-		printk("IP-Config: Guessing netmask %u.%u.%u.%u\n", NIPQUAD(ic_netmask));
++		printk("IP-Config: Guessing netmask " NIPQUAD_FMT "\n", NIPQUAD(ic_netmask));
+ 	}
+ 
+ 	return 0;
+@@ -434,7 +434,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
+ 	unsigned char *sha, *tha;		/* s for "source", t for "target" */
+ 	struct ic_device *d;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto drop;
+ 
+ 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+@@ -460,10 +460,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
+ 	if (rarp->ar_pro != htons(ETH_P_IP))
+ 		goto drop;
+ 
+-	if (!pskb_may_pull(skb,
+-			   sizeof(struct arphdr) +
+-			   (2 * dev->addr_len) +
+-			   (2 * 4)))
++	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
+ 		goto drop;
+ 
+ 	/* OK, it is all there and looks valid, process... */
+@@ -857,7 +854,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
+ 	struct ic_device *d;
+ 	int len, ext_len;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto drop;
+ 
+ 	/* Perform verifications before taking the lock.  */
+@@ -984,9 +981,9 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
+ 				ic_myaddr = b->your_ip;
+ 				ic_servaddr = server_id;
+ #ifdef IPCONFIG_DEBUG
+-				printk("DHCP: Offered address %u.%u.%u.%u",
++				printk("DHCP: Offered address " NIPQUAD_FMT,
+ 				       NIPQUAD(ic_myaddr));
+-				printk(" by server %u.%u.%u.%u\n",
++				printk(" by server " NIPQUAD_FMT "\n",
+ 				       NIPQUAD(ic_servaddr));
+ #endif
+ 				/* The DHCP indicated server address takes
+@@ -1182,11 +1179,11 @@ static int __init ic_dynamic(void)
+ 		return -1;
+ 	}
+ 
+-	printk("IP-Config: Got %s answer from %u.%u.%u.%u, ",
++	printk("IP-Config: Got %s answer from " NIPQUAD_FMT ", ",
+ 		((ic_got_reply & IC_RARP) ? "RARP"
+ 		 : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"),
+ 		NIPQUAD(ic_servaddr));
+-	printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr));
++	printk("my address is " NIPQUAD_FMT "\n", NIPQUAD(ic_myaddr));
+ 
+ 	return 0;
+ }
+@@ -1212,12 +1209,12 @@ static int pnp_seq_show(struct seq_file *seq, void *v)
+ 	for (i = 0; i < CONF_NAMESERVERS_MAX; i++) {
+ 		if (ic_nameservers[i] != NONE)
+ 			seq_printf(seq,
+-				   "nameserver %u.%u.%u.%u\n",
++				   "nameserver " NIPQUAD_FMT "\n",
+ 				   NIPQUAD(ic_nameservers[i]));
+ 	}
+ 	if (ic_servaddr != NONE)
+ 		seq_printf(seq,
+-			   "bootserver %u.%u.%u.%u\n",
++			   "bootserver " NIPQUAD_FMT "\n",
+ 			   NIPQUAD(ic_servaddr));
+ 	return 0;
+ }
+@@ -1392,13 +1389,13 @@ static int __init ip_auto_config(void)
+ 	 */
+ 	printk("IP-Config: Complete:");
+ 	printk("\n     device=%s", ic_dev->name);
+-	printk(", addr=%u.%u.%u.%u", NIPQUAD(ic_myaddr));
+-	printk(", mask=%u.%u.%u.%u", NIPQUAD(ic_netmask));
+-	printk(", gw=%u.%u.%u.%u", NIPQUAD(ic_gateway));
++	printk(", addr=" NIPQUAD_FMT, NIPQUAD(ic_myaddr));
++	printk(", mask=" NIPQUAD_FMT, NIPQUAD(ic_netmask));
++	printk(", gw=" NIPQUAD_FMT, NIPQUAD(ic_gateway));
+ 	printk(",\n     host=%s, domain=%s, nis-domain=%s",
+ 	       utsname()->nodename, ic_domain, utsname()->domainname);
+-	printk(",\n     bootserver=%u.%u.%u.%u", NIPQUAD(ic_servaddr));
+-	printk(", rootserver=%u.%u.%u.%u", NIPQUAD(root_server_addr));
++	printk(",\n     bootserver=" NIPQUAD_FMT, NIPQUAD(ic_servaddr));
++	printk(", rootserver=" NIPQUAD_FMT, NIPQUAD(root_server_addr));
+ 	printk(", rootpath=%s", root_server_path);
+ 	printk("\n");
+ #endif /* !SILENT */
+diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
+index dbaed69..149111f 100644
+--- a/net/ipv4/ipip.c
++++ b/net/ipv4/ipip.c
+@@ -115,49 +115,57 @@
+ #include <net/ipip.h>
+ #include <net/inet_ecn.h>
+ #include <net/xfrm.h>
++#include <net/net_namespace.h>
++#include <net/netns/generic.h>
+ 
+ #define HASH_SIZE  16
+ #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
+ 
++static int ipip_net_id;
++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 net_device *fb_tunnel_dev;
++};
++
+ static int ipip_fb_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 struct net_device *ipip_fb_tunnel_dev;
+-
+-static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
+-static struct ip_tunnel *tunnels_r[HASH_SIZE];
+-static struct ip_tunnel *tunnels_l[HASH_SIZE];
+-static struct ip_tunnel *tunnels_wc[1];
+-static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
+-
+ static DEFINE_RWLOCK(ipip_lock);
+ 
+-static struct ip_tunnel * ipip_tunnel_lookup(__be32 remote, __be32 local)
++static struct ip_tunnel * ipip_tunnel_lookup(struct net *net,
++		__be32 remote, __be32 local)
+ {
+ 	unsigned h0 = HASH(remote);
+ 	unsigned h1 = HASH(local);
+ 	struct ip_tunnel *t;
++	struct ipip_net *ipn = net_generic(net, ipip_net_id);
+ 
+-	for (t = tunnels_r_l[h0^h1]; t; t = t->next) {
++	for (t = ipn->tunnels_r_l[h0^h1]; t; t = t->next) {
+ 		if (local == t->parms.iph.saddr &&
+ 		    remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ 			return t;
+ 	}
+-	for (t = tunnels_r[h0]; t; t = t->next) {
++	for (t = ipn->tunnels_r[h0]; t; t = t->next) {
+ 		if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ 			return t;
+ 	}
+-	for (t = tunnels_l[h1]; t; t = t->next) {
++	for (t = ipn->tunnels_l[h1]; t; t = t->next) {
+ 		if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
+ 			return t;
+ 	}
+-	if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
++	if ((t = ipn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
+ 		return t;
+ 	return NULL;
+ }
+ 
+-static struct ip_tunnel **__ipip_bucket(struct ip_tunnel_parm *parms)
++static struct ip_tunnel **__ipip_bucket(struct ipip_net *ipn,
++		struct ip_tunnel_parm *parms)
+ {
+ 	__be32 remote = parms->iph.daddr;
+ 	__be32 local = parms->iph.saddr;
+@@ -172,19 +180,20 @@ static struct ip_tunnel **__ipip_bucket(struct ip_tunnel_parm *parms)
+ 		prio |= 1;
+ 		h ^= HASH(local);
+ 	}
+-	return &tunnels[prio][h];
++	return &ipn->tunnels[prio][h];
+ }
+ 
+-static inline struct ip_tunnel **ipip_bucket(struct ip_tunnel *t)
++static inline struct ip_tunnel **ipip_bucket(struct ipip_net *ipn,
++		struct ip_tunnel *t)
+ {
+-	return __ipip_bucket(&t->parms);
++	return __ipip_bucket(ipn, &t->parms);
+ }
+ 
+-static void ipip_tunnel_unlink(struct ip_tunnel *t)
++static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t)
+ {
+ 	struct ip_tunnel **tp;
+ 
+-	for (tp = ipip_bucket(t); *tp; tp = &(*tp)->next) {
++	for (tp = ipip_bucket(ipn, t); *tp; tp = &(*tp)->next) {
+ 		if (t == *tp) {
+ 			write_lock_bh(&ipip_lock);
+ 			*tp = t->next;
+@@ -194,9 +203,9 @@ static void ipip_tunnel_unlink(struct ip_tunnel *t)
+ 	}
+ }
+ 
+-static void ipip_tunnel_link(struct ip_tunnel *t)
++static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t)
+ {
+-	struct ip_tunnel **tp = ipip_bucket(t);
++	struct ip_tunnel **tp = ipip_bucket(ipn, t);
+ 
+ 	t->next = *tp;
+ 	write_lock_bh(&ipip_lock);
+@@ -204,15 +213,17 @@ static void ipip_tunnel_link(struct ip_tunnel *t)
+ 	write_unlock_bh(&ipip_lock);
+ }
+ 
+-static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create)
++static struct ip_tunnel * ipip_tunnel_locate(struct net *net,
++		struct ip_tunnel_parm *parms, int create)
+ {
+ 	__be32 remote = parms->iph.daddr;
+ 	__be32 local = parms->iph.saddr;
+ 	struct ip_tunnel *t, **tp, *nt;
+ 	struct net_device *dev;
+ 	char name[IFNAMSIZ];
++	struct ipip_net *ipn = net_generic(net, ipip_net_id);
+ 
+-	for (tp = __ipip_bucket(parms); (t = *tp) != NULL; tp = &t->next) {
++	for (tp = __ipip_bucket(ipn, parms); (t = *tp) != NULL; tp = &t->next) {
+ 		if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
+ 			return t;
+ 	}
+@@ -228,6 +239,8 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c
+ 	if (dev == NULL)
+ 		return NULL;
+ 
++	dev_net_set(dev, net);
++
+ 	if (strchr(name, '%')) {
+ 		if (dev_alloc_name(dev, name) < 0)
+ 			goto failed_free;
+@@ -241,7 +254,7 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c
+ 		goto failed_free;
+ 
+ 	dev_hold(dev);
+-	ipip_tunnel_link(nt);
++	ipip_tunnel_link(ipn, nt);
+ 	return nt;
+ 
+ failed_free:
+@@ -251,12 +264,15 @@ failed_free:
+ 
+ static void ipip_tunnel_uninit(struct net_device *dev)
+ {
+-	if (dev == ipip_fb_tunnel_dev) {
++	struct net *net = dev_net(dev);
++	struct ipip_net *ipn = net_generic(net, ipip_net_id);
++
++	if (dev == ipn->fb_tunnel_dev) {
+ 		write_lock_bh(&ipip_lock);
+-		tunnels_wc[0] = NULL;
++		ipn->tunnels_wc[0] = NULL;
+ 		write_unlock_bh(&ipip_lock);
+ 	} else
+-		ipip_tunnel_unlink(netdev_priv(dev));
++		ipip_tunnel_unlink(ipn, netdev_priv(dev));
+ 	dev_put(dev);
+ }
+ 
+@@ -305,7 +321,7 @@ static int ipip_err(struct sk_buff *skb, u32 info)
+ 	err = -ENOENT;
+ 
+ 	read_lock(&ipip_lock);
+-	t = ipip_tunnel_lookup(iph->daddr, iph->saddr);
++	t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr);
+ 	if (t == NULL || t->parms.iph.daddr == 0)
+ 		goto out;
+ 
+@@ -401,7 +417,7 @@ out:
+ 	fl.fl4_daddr = eiph->saddr;
+ 	fl.fl4_tos = RT_TOS(eiph->tos);
+ 	fl.proto = IPPROTO_IPIP;
+-	if (ip_route_output_key(&init_net, &rt, &key)) {
++	if (ip_route_output_key(dev_net(skb->dev), &rt, &key)) {
+ 		kfree_skb(skb2);
+ 		return 0;
+ 	}
+@@ -414,7 +430,7 @@ out:
+ 		fl.fl4_daddr = eiph->daddr;
+ 		fl.fl4_src = eiph->saddr;
+ 		fl.fl4_tos = eiph->tos;
+-		if (ip_route_output_key(&init_net, &rt, &fl) ||
++		if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) ||
+ 		    rt->u.dst.dev->type != ARPHRD_TUNNEL) {
+ 			ip_rt_put(rt);
+ 			kfree_skb(skb2);
+@@ -465,7 +481,8 @@ static int ipip_rcv(struct sk_buff *skb)
+ 	const struct iphdr *iph = ip_hdr(skb);
+ 
+ 	read_lock(&ipip_lock);
+-	if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
++	if ((tunnel = ipip_tunnel_lookup(dev_net(skb->dev),
++					iph->saddr, iph->daddr)) != NULL) {
+ 		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+ 			read_unlock(&ipip_lock);
+ 			kfree_skb(skb);
+@@ -528,7 +545,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 	if (!dst) {
+ 		/* NBMA tunnel */
+-		if ((rt = (struct rtable*)skb->dst) == NULL) {
++		if ((rt = skb->rtable) == NULL) {
+ 			tunnel->stat.tx_fifo_errors++;
+ 			goto tx_error;
+ 		}
+@@ -543,7 +560,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ 						.saddr = tiph->saddr,
+ 						.tos = RT_TOS(tos) } },
+ 				    .proto = IPPROTO_IPIP };
+-		if (ip_route_output_key(&init_net, &rt, &fl)) {
++		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ 			tunnel->stat.tx_carrier_errors++;
+ 			goto tx_error_icmp;
+ 		}
+@@ -664,7 +681,7 @@ static void ipip_tunnel_bind_dev(struct net_device *dev)
+ 						.tos = RT_TOS(iph->tos) } },
+ 				    .proto = IPPROTO_IPIP };
+ 		struct rtable *rt;
+-		if (!ip_route_output_key(&init_net, &rt, &fl)) {
++		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ 			tdev = rt->u.dst.dev;
+ 			ip_rt_put(rt);
+ 		}
+@@ -672,7 +689,7 @@ static void ipip_tunnel_bind_dev(struct net_device *dev)
+ 	}
+ 
+ 	if (!tdev && tunnel->parms.link)
+-		tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
++		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
+ 
+ 	if (tdev) {
+ 		dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+@@ -687,16 +704,18 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 	int err = 0;
+ 	struct ip_tunnel_parm p;
+ 	struct ip_tunnel *t;
++	struct net *net = dev_net(dev);
++	struct ipip_net *ipn = net_generic(net, ipip_net_id);
+ 
+ 	switch (cmd) {
+ 	case SIOCGETTUNNEL:
+ 		t = NULL;
+-		if (dev == ipip_fb_tunnel_dev) {
++		if (dev == ipn->fb_tunnel_dev) {
+ 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
+ 				err = -EFAULT;
+ 				break;
+ 			}
+-			t = ipip_tunnel_locate(&p, 0);
++			t = ipip_tunnel_locate(net, &p, 0);
+ 		}
+ 		if (t == NULL)
+ 			t = netdev_priv(dev);
+@@ -722,9 +741,9 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		if (p.iph.ttl)
+ 			p.iph.frag_off |= htons(IP_DF);
+ 
+-		t = ipip_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
++		t = ipip_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
+ 
+-		if (dev != ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
++		if (dev != ipn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
+ 			if (t != NULL) {
+ 				if (t->dev != dev) {
+ 					err = -EEXIST;
+@@ -737,12 +756,12 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 					break;
+ 				}
+ 				t = netdev_priv(dev);
+-				ipip_tunnel_unlink(t);
++				ipip_tunnel_unlink(ipn, t);
+ 				t->parms.iph.saddr = p.iph.saddr;
+ 				t->parms.iph.daddr = p.iph.daddr;
+ 				memcpy(dev->dev_addr, &p.iph.saddr, 4);
+ 				memcpy(dev->broadcast, &p.iph.daddr, 4);
+-				ipip_tunnel_link(t);
++				ipip_tunnel_link(ipn, t);
+ 				netdev_state_change(dev);
+ 			}
+ 		}
+@@ -770,15 +789,15 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		if (!capable(CAP_NET_ADMIN))
+ 			goto done;
+ 
+-		if (dev == ipip_fb_tunnel_dev) {
++		if (dev == ipn->fb_tunnel_dev) {
+ 			err = -EFAULT;
+ 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ 				goto done;
+ 			err = -ENOENT;
+-			if ((t = ipip_tunnel_locate(&p, 0)) == NULL)
++			if ((t = ipip_tunnel_locate(net, &p, 0)) == NULL)
+ 				goto done;
+ 			err = -EPERM;
+-			if (t->dev == ipip_fb_tunnel_dev)
++			if (t->dev == ipn->fb_tunnel_dev)
+ 				goto done;
+ 			dev = t->dev;
+ 		}
+@@ -822,6 +841,7 @@ static void ipip_tunnel_setup(struct net_device *dev)
+ 	dev->flags		= IFF_NOARP;
+ 	dev->iflink		= 0;
+ 	dev->addr_len		= 4;
++	dev->features		|= NETIF_F_NETNS_LOCAL;
+ }
+ 
+ static int ipip_tunnel_init(struct net_device *dev)
+@@ -841,10 +861,11 @@ static int ipip_tunnel_init(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static int __init ipip_fb_tunnel_init(struct net_device *dev)
++static int ipip_fb_tunnel_init(struct net_device *dev)
+ {
+ 	struct ip_tunnel *tunnel = netdev_priv(dev);
+ 	struct iphdr *iph = &tunnel->parms.iph;
++	struct ipip_net *ipn = net_generic(dev_net(dev), ipip_net_id);
+ 
+ 	tunnel->dev = dev;
+ 	strcpy(tunnel->parms.name, dev->name);
+@@ -854,7 +875,7 @@ static int __init ipip_fb_tunnel_init(struct net_device *dev)
+ 	iph->ihl		= 5;
+ 
+ 	dev_hold(dev);
+-	tunnels_wc[0]		= tunnel;
++	ipn->tunnels_wc[0]	= tunnel;
+ 	return 0;
+ }
+ 
+@@ -867,50 +888,98 @@ static struct xfrm_tunnel ipip_handler = {
+ static char banner[] __initdata =
+ 	KERN_INFO "IPv4 over IPv4 tunneling driver\n";
+ 
+-static int __init ipip_init(void)
++static void ipip_destroy_tunnels(struct ipip_net *ipn)
++{
++	int prio;
++
++	for (prio = 1; prio < 4; prio++) {
++		int h;
++		for (h = 0; h < HASH_SIZE; h++) {
++			struct ip_tunnel *t;
++			while ((t = ipn->tunnels[prio][h]) != NULL)
++				unregister_netdevice(t->dev);
++		}
++	}
++}
++
++static int ipip_init_net(struct net *net)
+ {
+ 	int err;
++	struct ipip_net *ipn;
+ 
+-	printk(banner);
++	err = -ENOMEM;
++	ipn = kzalloc(sizeof(struct ipip_net), GFP_KERNEL);
++	if (ipn == NULL)
++		goto err_alloc;
+ 
+-	if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
+-		printk(KERN_INFO "ipip init: can't register tunnel\n");
+-		return -EAGAIN;
+-	}
++	err = net_assign_generic(net, ipip_net_id, ipn);
++	if (err < 0)
++		goto err_assign;
+ 
+-	ipip_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel),
++	ipn->tunnels[0] = ipn->tunnels_wc;
++	ipn->tunnels[1] = ipn->tunnels_l;
++	ipn->tunnels[2] = ipn->tunnels_r;
++	ipn->tunnels[3] = ipn->tunnels_r_l;
++
++	ipn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel),
+ 					   "tunl0",
+ 					   ipip_tunnel_setup);
+-	if (!ipip_fb_tunnel_dev) {
++	if (!ipn->fb_tunnel_dev) {
+ 		err = -ENOMEM;
+-		goto err1;
++		goto err_alloc_dev;
+ 	}
+ 
+-	ipip_fb_tunnel_dev->init = ipip_fb_tunnel_init;
++	ipn->fb_tunnel_dev->init = ipip_fb_tunnel_init;
++	dev_net_set(ipn->fb_tunnel_dev, net);
++
++	if ((err = register_netdev(ipn->fb_tunnel_dev)))
++		goto err_reg_dev;
++
++	return 0;
+ 
+-	if ((err = register_netdev(ipip_fb_tunnel_dev)))
+-		goto err2;
+- out:
++err_reg_dev:
++	free_netdev(ipn->fb_tunnel_dev);
++err_alloc_dev:
++	/* nothing */
++err_assign:
++	kfree(ipn);
++err_alloc:
+ 	return err;
+- err2:
+-	free_netdev(ipip_fb_tunnel_dev);
+- err1:
+-	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+-	goto out;
+ }
+ 
+-static void __exit ipip_destroy_tunnels(void)
++static void ipip_exit_net(struct net *net)
+ {
+-	int prio;
++	struct ipip_net *ipn;
+ 
+-	for (prio = 1; prio < 4; prio++) {
+-		int h;
+-		for (h = 0; h < HASH_SIZE; h++) {
+-			struct ip_tunnel *t;
+-			while ((t = tunnels[prio][h]) != NULL)
+-				unregister_netdevice(t->dev);
+-		}
++	ipn = net_generic(net, ipip_net_id);
++	rtnl_lock();
++	ipip_destroy_tunnels(ipn);
++	unregister_netdevice(ipn->fb_tunnel_dev);
++	rtnl_unlock();
++	kfree(ipn);
++}
++
++static struct pernet_operations ipip_net_ops = {
++	.init = ipip_init_net,
++	.exit = ipip_exit_net,
++};
++
++static int __init ipip_init(void)
++{
++	int err;
++
++	printk(banner);
++
++	if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
++		printk(KERN_INFO "ipip init: can't register tunnel\n");
++		return -EAGAIN;
+ 	}
++
++	err = register_pernet_gen_device(&ipip_net_id, &ipip_net_ops);
++	if (err)
++		xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
++
++	return err;
+ }
+ 
+ static void __exit ipip_fini(void)
+@@ -918,10 +987,7 @@ static void __exit ipip_fini(void)
+ 	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
+ 		printk(KERN_INFO "ipip close: can't deregister tunnel\n");
+ 
+-	rtnl_lock();
+-	ipip_destroy_tunnels();
+-	unregister_netdevice(ipip_fb_tunnel_dev);
+-	rtnl_unlock();
++	unregister_pernet_gen_device(ipip_net_id, &ipip_net_ops);
+ }
+ 
+ module_init(ipip_init);
+diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
+index a94f52c..11700a4 100644
+--- a/net/ipv4/ipmr.c
++++ b/net/ipv4/ipmr.c
+@@ -849,7 +849,7 @@ static void mrtsock_destruct(struct sock *sk)
+ {
+ 	rtnl_lock();
+ 	if (sk == mroute_socket) {
+-		IPV4_DEVCONF_ALL(sk->sk_net, MC_FORWARDING)--;
++		IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)--;
+ 
+ 		write_lock_bh(&mrt_lock);
+ 		mroute_socket=NULL;
+@@ -898,7 +898,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt
+ 			mroute_socket=sk;
+ 			write_unlock_bh(&mrt_lock);
+ 
+-			IPV4_DEVCONF_ALL(sk->sk_net, MC_FORWARDING)++;
++			IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)++;
+ 		}
+ 		rtnl_unlock();
+ 		return ret;
+@@ -1089,7 +1089,7 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v
+ 	struct vif_device *v;
+ 	int ct;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event != NETDEV_UNREGISTER)
+@@ -1283,7 +1283,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local
+ 	if (vif_table[vif].dev != skb->dev) {
+ 		int true_vifi;
+ 
+-		if (((struct rtable*)skb->dst)->fl.iif == 0) {
++		if (skb->rtable->fl.iif == 0) {
+ 			/* It is our own packet, looped back.
+ 			   Very complicated situation...
+ 
+@@ -1357,7 +1357,7 @@ dont_forward:
+ int ip_mr_input(struct sk_buff *skb)
+ {
+ 	struct mfc_cache *cache;
+-	int local = ((struct rtable*)skb->dst)->rt_flags&RTCF_LOCAL;
++	int local = skb->rtable->rt_flags&RTCF_LOCAL;
+ 
+ 	/* Packet is looped back after forward, it should not be
+ 	   forwarded second time, but still can be delivered locally.
+@@ -1594,7 +1594,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
+ {
+ 	int err;
+ 	struct mfc_cache *cache;
+-	struct rtable *rt = (struct rtable*)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 
+ 	read_lock(&mrt_lock);
+ 	cache = ipmr_cache_find(rt->rt_src, rt->rt_dst);
+diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
+index 12dc0d6..620e40f 100644
+--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
++++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
+@@ -550,7 +550,7 @@ tcp_app_conn_bind(struct ip_vs_conn *cp)
+ 
+ 			IP_VS_DBG(9, "%s: Binding conn %u.%u.%u.%u:%u->"
+ 				  "%u.%u.%u.%u:%u to app %s on port %u\n",
+-				  __FUNCTION__,
++				  __func__,
+ 				  NIPQUAD(cp->caddr), ntohs(cp->cport),
+ 				  NIPQUAD(cp->vaddr), ntohs(cp->vport),
+ 				  inc->name, ntohs(inc->port));
+diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
+index 1fa7b33..1caa290 100644
+--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
++++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
+@@ -344,7 +344,7 @@ static int udp_app_conn_bind(struct ip_vs_conn *cp)
+ 
+ 			IP_VS_DBG(9, "%s: Binding conn %u.%u.%u.%u:%u->"
+ 				  "%u.%u.%u.%u:%u to app %s on port %u\n",
+-				  __FUNCTION__,
++				  __func__,
+ 				  NIPQUAD(cp->caddr), ntohs(cp->cport),
+ 				  NIPQUAD(cp->vaddr), ntohs(cp->vport),
+ 				  inc->name, ntohs(inc->port));
+diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
+index 948378d..69c5666 100644
+--- a/net/ipv4/ipvs/ip_vs_sync.c
++++ b/net/ipv4/ipvs/ip_vs_sync.c
+@@ -916,7 +916,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
+ 	if (!tinfo)
+ 		return -ENOMEM;
+ 
+-	IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current));
++	IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current));
+ 	IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n",
+ 		  sizeof(struct ip_vs_sync_conn));
+ 
+@@ -956,7 +956,7 @@ int stop_sync_thread(int state)
+ 	    (state == IP_VS_STATE_BACKUP && !sync_backup_pid))
+ 		return -ESRCH;
+ 
+-	IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current));
++	IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current));
+ 	IP_VS_INFO("stopping sync thread %d ...\n",
+ 		   (state == IP_VS_STATE_MASTER) ?
+ 		   sync_master_pid : sync_backup_pid);
+diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
+index 9a904c6..f8edacd 100644
+--- a/net/ipv4/netfilter.c
++++ b/net/ipv4/netfilter.c
+@@ -182,21 +182,44 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+ 	}
+ 	return csum;
+ }
+-
+ EXPORT_SYMBOL(nf_ip_checksum);
+ 
++static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
++				      unsigned int dataoff, unsigned int len,
++				      u_int8_t protocol)
++{
++	const struct iphdr *iph = ip_hdr(skb);
++	__sum16 csum = 0;
++
++	switch (skb->ip_summed) {
++	case CHECKSUM_COMPLETE:
++		if (len == skb->len - dataoff)
++			return nf_ip_checksum(skb, hook, dataoff, protocol);
++		/* fall through */
++	case CHECKSUM_NONE:
++		skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, protocol,
++					       skb->len - dataoff, 0);
++		skb->ip_summed = CHECKSUM_NONE;
++		csum = __skb_checksum_complete_head(skb, dataoff + len);
++		if (!csum)
++			skb->ip_summed = CHECKSUM_UNNECESSARY;
++	}
++	return csum;
++}
++
+ static int nf_ip_route(struct dst_entry **dst, struct flowi *fl)
+ {
+ 	return ip_route_output_key(&init_net, (struct rtable **)dst, fl);
+ }
+ 
+ static const struct nf_afinfo nf_ip_afinfo = {
+-	.family		= AF_INET,
+-	.checksum	= nf_ip_checksum,
+-	.route		= nf_ip_route,
+-	.saveroute	= nf_ip_saveroute,
+-	.reroute	= nf_ip_reroute,
+-	.route_key_size	= sizeof(struct ip_rt_info),
++	.family			= AF_INET,
++	.checksum		= nf_ip_checksum,
++	.checksum_partial	= nf_ip_checksum_partial,
++	.route			= nf_ip_route,
++	.saveroute		= nf_ip_saveroute,
++	.reroute		= nf_ip_reroute,
++	.route_key_size		= sizeof(struct ip_rt_info),
+ };
+ 
+ static int ipv4_netfilter_init(void)
+diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
+index 9a077cb..2767841 100644
+--- a/net/ipv4/netfilter/Kconfig
++++ b/net/ipv4/netfilter/Kconfig
+@@ -241,10 +241,26 @@ config NF_NAT_SNMP_BASIC
+ #           <expr> '&&' <expr>                   (6)
+ #
+ # (6) Returns the result of min(/expr/, /expr/).
++config NF_NAT_PROTO_DCCP
++	tristate
++	depends on NF_NAT && NF_CT_PROTO_DCCP
++	default NF_NAT && NF_CT_PROTO_DCCP
++
+ config NF_NAT_PROTO_GRE
+ 	tristate
+ 	depends on NF_NAT && NF_CT_PROTO_GRE
+ 
++config NF_NAT_PROTO_UDPLITE
++	tristate
++	depends on NF_NAT && NF_CT_PROTO_UDPLITE
++	default NF_NAT && NF_CT_PROTO_UDPLITE
++
++config NF_NAT_PROTO_SCTP
++	tristate
++	default NF_NAT && NF_CT_PROTO_SCTP
++	depends on NF_NAT && NF_CT_PROTO_SCTP
++	select LIBCRC32C
++
+ config NF_NAT_FTP
+ 	tristate
+ 	depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
+diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
+index 0c7dc78..d9b92fb 100644
+--- a/net/ipv4/netfilter/Makefile
++++ b/net/ipv4/netfilter/Makefile
+@@ -10,7 +10,7 @@ nf_conntrack_ipv4-objs	+= nf_conntrack_l3proto_ipv4_compat.o
+ endif
+ endif
+ 
+-nf_nat-objs		:= nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
++nf_nat-objs		:= nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_common.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
+ iptable_nat-objs	:= nf_nat_rule.o nf_nat_standalone.o
+ 
+ # connection tracking
+@@ -29,7 +29,10 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
+ obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
+ 
+ # NAT protocols (nf_nat)
++obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
+ obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
++obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
++obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
+ 
+ # generic IP tables 
+ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
+index a7591ce..03e83a6 100644
+--- a/net/ipv4/netfilter/arp_tables.c
++++ b/net/ipv4/netfilter/arp_tables.c
+@@ -52,14 +52,14 @@ MODULE_DESCRIPTION("arptables core");
+ do {								\
+ 	if (!(x))						\
+ 		printk("ARP_NF_ASSERT: %s:%s:%u\n",		\
+-		       __FUNCTION__, __FILE__, __LINE__);	\
++		       __func__, __FILE__, __LINE__);	\
+ } while(0)
+ #else
+ #define ARP_NF_ASSERT(x)
+ #endif
+ 
+ static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
+-				      char *hdr_addr, int len)
++				      const char *hdr_addr, int len)
+ {
+ 	int i, ret;
+ 
+@@ -80,8 +80,8 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
+ 				   const char *outdev,
+ 				   const struct arpt_arp *arpinfo)
+ {
+-	char *arpptr = (char *)(arphdr + 1);
+-	char *src_devaddr, *tgt_devaddr;
++	const char *arpptr = (char *)(arphdr + 1);
++	const char *src_devaddr, *tgt_devaddr;
+ 	__be32 src_ipaddr, tgt_ipaddr;
+ 	int i, ret;
+ 
+@@ -222,21 +222,18 @@ unsigned int arpt_do_table(struct sk_buff *skb,
+ 			   unsigned int hook,
+ 			   const struct net_device *in,
+ 			   const struct net_device *out,
+-			   struct arpt_table *table)
++			   struct xt_table *table)
+ {
+ 	static const char nulldevname[IFNAMSIZ];
+ 	unsigned int verdict = NF_DROP;
+-	struct arphdr *arp;
++	const struct arphdr *arp;
+ 	bool hotdrop = false;
+ 	struct arpt_entry *e, *back;
+ 	const char *indev, *outdev;
+ 	void *table_base;
+-	struct xt_table_info *private;
++	const struct xt_table_info *private;
+ 
+-	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
+-	if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+-				 (2 * skb->dev->addr_len) +
+-				 (2 * sizeof(u32)))))
++	if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
+ 		return NF_DROP;
+ 
+ 	indev = in ? in->name : nulldevname;
+@@ -355,7 +352,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
+ 		e->counters.pcnt = pos;
+ 
+ 		for (;;) {
+-			struct arpt_standard_target *t
++			const struct arpt_standard_target *t
+ 				= (void *)arpt_get_target(e);
+ 			int visited = e->comefrom & (1 << hook);
+ 
+@@ -440,7 +437,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
+ 
+ static inline int check_entry(struct arpt_entry *e, const char *name)
+ {
+-	struct arpt_entry_target *t;
++	const struct arpt_entry_target *t;
+ 
+ 	if (!arp_checkentry(&e->arp)) {
+ 		duprintf("arp_tables: arp check failed %p %s.\n", e, name);
+@@ -460,7 +457,7 @@ static inline int check_entry(struct arpt_entry *e, const char *name)
+ static inline int check_target(struct arpt_entry *e, const char *name)
+ {
+ 	struct arpt_entry_target *t;
+-	struct arpt_target *target;
++	struct xt_target *target;
+ 	int ret;
+ 
+ 	t = arpt_get_target(e);
+@@ -483,7 +480,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
+ 		 unsigned int *i)
+ {
+ 	struct arpt_entry_target *t;
+-	struct arpt_target *target;
++	struct xt_target *target;
+ 	int ret;
+ 
+ 	ret = check_entry(e, name);
+@@ -709,11 +706,11 @@ static void get_counters(const struct xt_table_info *t,
+ 	}
+ }
+ 
+-static inline struct xt_counters *alloc_counters(struct arpt_table *table)
++static inline struct xt_counters *alloc_counters(struct xt_table *table)
+ {
+ 	unsigned int countersize;
+ 	struct xt_counters *counters;
+-	struct xt_table_info *private = table->private;
++	const struct xt_table_info *private = table->private;
+ 
+ 	/* We need atomic snapshot of counters: rest doesn't change
+ 	 * (other than comefrom, which userspace doesn't care
+@@ -734,7 +731,7 @@ static inline struct xt_counters *alloc_counters(struct arpt_table *table)
+ }
+ 
+ static int copy_entries_to_user(unsigned int total_size,
+-				struct arpt_table *table,
++				struct xt_table *table,
+ 				void __user *userptr)
+ {
+ 	unsigned int off, num;
+@@ -854,7 +851,7 @@ static int compat_table_info(const struct xt_table_info *info,
+ static int get_info(struct net *net, void __user *user, int *len, int compat)
+ {
+ 	char name[ARPT_TABLE_MAXNAMELEN];
+-	struct arpt_table *t;
++	struct xt_table *t;
+ 	int ret;
+ 
+ 	if (*len != sizeof(struct arpt_getinfo)) {
+@@ -875,7 +872,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
+ 				    "arptable_%s", name);
+ 	if (t && !IS_ERR(t)) {
+ 		struct arpt_getinfo info;
+-		struct xt_table_info *private = t->private;
++		const struct xt_table_info *private = t->private;
+ 
+ #ifdef CONFIG_COMPAT
+ 		if (compat) {
+@@ -914,7 +911,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
+ {
+ 	int ret;
+ 	struct arpt_get_entries get;
+-	struct arpt_table *t;
++	struct xt_table *t;
+ 
+ 	if (*len < sizeof(get)) {
+ 		duprintf("get_entries: %u < %Zu\n", *len, sizeof(get));
+@@ -930,7 +927,8 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
+ 
+ 	t = xt_find_table_lock(net, NF_ARP, get.name);
+ 	if (t && !IS_ERR(t)) {
+-		struct xt_table_info *private = t->private;
++		const struct xt_table_info *private = t->private;
++
+ 		duprintf("t->private->number = %u\n",
+ 			 private->number);
+ 		if (get.size == private->size)
+@@ -939,7 +937,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
+ 		else {
+ 			duprintf("get_entries: I've got %u not %u!\n",
+ 				 private->size, get.size);
+-			ret = -EINVAL;
++			ret = -EAGAIN;
+ 		}
+ 		module_put(t->me);
+ 		xt_table_unlock(t);
+@@ -956,7 +954,7 @@ static int __do_replace(struct net *net, const char *name,
+ 			void __user *counters_ptr)
+ {
+ 	int ret;
+-	struct arpt_table *t;
++	struct xt_table *t;
+ 	struct xt_table_info *oldinfo;
+ 	struct xt_counters *counters;
+ 	void *loc_cpu_old_entry;
+@@ -1090,11 +1088,11 @@ static int do_add_counters(struct net *net, void __user *user, unsigned int len,
+ 	struct xt_counters_info tmp;
+ 	struct xt_counters *paddc;
+ 	unsigned int num_counters;
+-	char *name;
++	const char *name;
+ 	int size;
+ 	void *ptmp;
+-	struct arpt_table *t;
+-	struct xt_table_info *private;
++	struct xt_table *t;
++	const struct xt_table_info *private;
+ 	int ret = 0;
+ 	void *loc_cpu_entry;
+ #ifdef CONFIG_COMPAT
+@@ -1499,11 +1497,11 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user,
+ 
+ 	switch (cmd) {
+ 	case ARPT_SO_SET_REPLACE:
+-		ret = compat_do_replace(sk->sk_net, user, len);
++		ret = compat_do_replace(sock_net(sk), user, len);
+ 		break;
+ 
+ 	case ARPT_SO_SET_ADD_COUNTERS:
+-		ret = do_add_counters(sk->sk_net, user, len, 1);
++		ret = do_add_counters(sock_net(sk), user, len, 1);
+ 		break;
+ 
+ 	default:
+@@ -1557,11 +1555,11 @@ out:
+ }
+ 
+ static int compat_copy_entries_to_user(unsigned int total_size,
+-				       struct arpt_table *table,
++				       struct xt_table *table,
+ 				       void __user *userptr)
+ {
+ 	struct xt_counters *counters;
+-	struct xt_table_info *private = table->private;
++	const struct xt_table_info *private = table->private;
+ 	void __user *pos;
+ 	unsigned int size;
+ 	int ret = 0;
+@@ -1595,7 +1593,7 @@ static int compat_get_entries(struct net *net,
+ {
+ 	int ret;
+ 	struct compat_arpt_get_entries get;
+-	struct arpt_table *t;
++	struct xt_table *t;
+ 
+ 	if (*len < sizeof(get)) {
+ 		duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
+@@ -1612,7 +1610,7 @@ static int compat_get_entries(struct net *net,
+ 	xt_compat_lock(NF_ARP);
+ 	t = xt_find_table_lock(net, NF_ARP, get.name);
+ 	if (t && !IS_ERR(t)) {
+-		struct xt_table_info *private = t->private;
++		const struct xt_table_info *private = t->private;
+ 		struct xt_table_info info;
+ 
+ 		duprintf("t->private->number = %u\n", private->number);
+@@ -1623,7 +1621,7 @@ static int compat_get_entries(struct net *net,
+ 		} else if (!ret) {
+ 			duprintf("compat_get_entries: I've got %u not %u!\n",
+ 				 private->size, get.size);
+-			ret = -EINVAL;
++			ret = -EAGAIN;
+ 		}
+ 		xt_compat_flush_offsets(NF_ARP);
+ 		module_put(t->me);
+@@ -1647,10 +1645,10 @@ static int compat_do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user,
+ 
+ 	switch (cmd) {
+ 	case ARPT_SO_GET_INFO:
+-		ret = get_info(sk->sk_net, user, len, 1);
++		ret = get_info(sock_net(sk), user, len, 1);
+ 		break;
+ 	case ARPT_SO_GET_ENTRIES:
+-		ret = compat_get_entries(sk->sk_net, user, len);
++		ret = compat_get_entries(sock_net(sk), user, len);
+ 		break;
+ 	default:
+ 		ret = do_arpt_get_ctl(sk, cmd, user, len);
+@@ -1668,11 +1666,11 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned
+ 
+ 	switch (cmd) {
+ 	case ARPT_SO_SET_REPLACE:
+-		ret = do_replace(sk->sk_net, user, len);
++		ret = do_replace(sock_net(sk), user, len);
+ 		break;
+ 
+ 	case ARPT_SO_SET_ADD_COUNTERS:
+-		ret = do_add_counters(sk->sk_net, user, len, 0);
++		ret = do_add_counters(sock_net(sk), user, len, 0);
+ 		break;
+ 
+ 	default:
+@@ -1692,11 +1690,11 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
+ 
+ 	switch (cmd) {
+ 	case ARPT_SO_GET_INFO:
+-		ret = get_info(sk->sk_net, user, len, 0);
++		ret = get_info(sock_net(sk), user, len, 0);
+ 		break;
+ 
+ 	case ARPT_SO_GET_ENTRIES:
+-		ret = get_entries(sk->sk_net, user, len);
++		ret = get_entries(sock_net(sk), user, len);
+ 		break;
+ 
+ 	case ARPT_SO_GET_REVISION_TARGET: {
+@@ -1725,9 +1723,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
+ 	return ret;
+ }
+ 
+-struct arpt_table *arpt_register_table(struct net *net,
+-				       struct arpt_table *table,
+-				       const struct arpt_replace *repl)
++struct xt_table *arpt_register_table(struct net *net, struct xt_table *table,
++				     const struct arpt_replace *repl)
+ {
+ 	int ret;
+ 	struct xt_table_info *newinfo;
+@@ -1769,7 +1766,7 @@ out:
+ 	return ERR_PTR(ret);
+ }
+ 
+-void arpt_unregister_table(struct arpt_table *table)
++void arpt_unregister_table(struct xt_table *table)
+ {
+ 	struct xt_table_info *private;
+ 	void *loc_cpu_entry;
+@@ -1787,7 +1784,7 @@ void arpt_unregister_table(struct arpt_table *table)
+ }
+ 
+ /* The built-in targets: standard (NULL) and error. */
+-static struct arpt_target arpt_standard_target __read_mostly = {
++static struct xt_target arpt_standard_target __read_mostly = {
+ 	.name		= ARPT_STANDARD_TARGET,
+ 	.targetsize	= sizeof(int),
+ 	.family		= NF_ARP,
+@@ -1798,7 +1795,7 @@ static struct arpt_target arpt_standard_target __read_mostly = {
+ #endif
+ };
+ 
+-static struct arpt_target arpt_error_target __read_mostly = {
++static struct xt_target arpt_error_target __read_mostly = {
+ 	.name		= ARPT_ERROR_TARGET,
+ 	.target		= arpt_error,
+ 	.targetsize	= ARPT_FUNCTION_MAXNAMELEN,
+diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
+index 3f4222b..a385959 100644
+--- a/net/ipv4/netfilter/arpt_mangle.c
++++ b/net/ipv4/netfilter/arpt_mangle.c
+@@ -15,7 +15,7 @@ target(struct sk_buff *skb,
+        const void *targinfo)
+ {
+ 	const struct arpt_mangle *mangle = targinfo;
+-	struct arphdr *arp;
++	const struct arphdr *arp;
+ 	unsigned char *arpptr;
+ 	int pln, hln;
+ 
+@@ -73,8 +73,9 @@ checkentry(const char *tablename, const void *e, const struct xt_target *target,
+ 	return true;
+ }
+ 
+-static struct arpt_target arpt_mangle_reg __read_mostly = {
++static struct xt_target arpt_mangle_reg __read_mostly = {
+ 	.name		= "mangle",
++	.family		= NF_ARP,
+ 	.target		= target,
+ 	.targetsize	= sizeof(struct arpt_mangle),
+ 	.checkentry	= checkentry,
+@@ -83,15 +84,12 @@ static struct arpt_target arpt_mangle_reg __read_mostly = {
+ 
+ static int __init arpt_mangle_init(void)
+ {
+-	if (arpt_register_target(&arpt_mangle_reg))
+-		return -EINVAL;
+-
+-	return 0;
++	return xt_register_target(&arpt_mangle_reg);
+ }
+ 
+ static void __exit arpt_mangle_fini(void)
+ {
+-	arpt_unregister_target(&arpt_mangle_reg);
++	xt_unregister_target(&arpt_mangle_reg);
+ }
+ 
+ module_init(arpt_mangle_init);
+diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
+index 4e9c496..3be4d07 100644
+--- a/net/ipv4/netfilter/arptable_filter.c
++++ b/net/ipv4/netfilter/arptable_filter.c
+@@ -45,10 +45,10 @@ static struct
+ 	.term = ARPT_ERROR_INIT,
+ };
+ 
+-static struct arpt_table packet_filter = {
++static struct xt_table packet_filter = {
+ 	.name		= "filter",
+ 	.valid_hooks	= FILTER_VALID_HOOKS,
+-	.lock		= RW_LOCK_UNLOCKED,
++	.lock		= __RW_LOCK_UNLOCKED(packet_filter.lock),
+ 	.private	= NULL,
+ 	.me		= THIS_MODULE,
+ 	.af		= NF_ARP,
+@@ -70,18 +70,21 @@ static struct nf_hook_ops arpt_ops[] __read_mostly = {
+ 		.owner		= THIS_MODULE,
+ 		.pf		= NF_ARP,
+ 		.hooknum	= NF_ARP_IN,
++		.priority	= NF_IP_PRI_FILTER,
+ 	},
+ 	{
+ 		.hook		= arpt_hook,
+ 		.owner		= THIS_MODULE,
+ 		.pf		= NF_ARP,
+ 		.hooknum	= NF_ARP_OUT,
++		.priority	= NF_IP_PRI_FILTER,
+ 	},
+ 	{
+ 		.hook		= arpt_hook,
+ 		.owner		= THIS_MODULE,
+ 		.pf		= NF_ARP,
+ 		.hooknum	= NF_ARP_FORWARD,
++		.priority	= NF_IP_PRI_FILTER,
+ 	},
+ };
+ 
+diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
+index 4dc1628..719be29 100644
+--- a/net/ipv4/netfilter/ip_queue.c
++++ b/net/ipv4/netfilter/ip_queue.c
+@@ -481,7 +481,7 @@ ipq_rcv_dev_event(struct notifier_block *this,
+ {
+ 	struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	/* Drop any packets associated with the downed device */
+diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
+index 600737f..4e7c719 100644
+--- a/net/ipv4/netfilter/ip_tables.c
++++ b/net/ipv4/netfilter/ip_tables.c
+@@ -53,7 +53,7 @@ MODULE_DESCRIPTION("IPv4 packet filter");
+ do {								\
+ 	if (!(x))						\
+ 		printk("IP_NF_ASSERT: %s:%s:%u\n",		\
+-		       __FUNCTION__, __FILE__, __LINE__);	\
++		       __func__, __FILE__, __LINE__);	\
+ } while(0)
+ #else
+ #define IP_NF_ASSERT(x)
+@@ -296,7 +296,7 @@ static void trace_packet(struct sk_buff *skb,
+ 			 struct ipt_entry *e)
+ {
+ 	void *table_base;
+-	struct ipt_entry *root;
++	const struct ipt_entry *root;
+ 	char *hookname, *chainname, *comment;
+ 	unsigned int rulenum = 0;
+ 
+@@ -327,7 +327,7 @@ ipt_do_table(struct sk_buff *skb,
+ {
+ 	static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
+ 	u_int16_t offset;
+-	struct iphdr *ip;
++	const struct iphdr *ip;
+ 	u_int16_t datalen;
+ 	bool hotdrop = false;
+ 	/* Initializing verdict to NF_DROP keeps gcc happy. */
+@@ -926,7 +926,7 @@ static struct xt_counters * alloc_counters(struct xt_table *table)
+ {
+ 	unsigned int countersize;
+ 	struct xt_counters *counters;
+-	struct xt_table_info *private = table->private;
++	const struct xt_table_info *private = table->private;
+ 
+ 	/* We need atomic snapshot of counters: rest doesn't change
+ 	   (other than comefrom, which userspace doesn't care
+@@ -953,9 +953,9 @@ copy_entries_to_user(unsigned int total_size,
+ 	unsigned int off, num;
+ 	struct ipt_entry *e;
+ 	struct xt_counters *counters;
+-	struct xt_table_info *private = table->private;
++	const struct xt_table_info *private = table->private;
+ 	int ret = 0;
+-	void *loc_cpu_entry;
++	const void *loc_cpu_entry;
+ 
+ 	counters = alloc_counters(table);
+ 	if (IS_ERR(counters))
+@@ -975,8 +975,8 @@ copy_entries_to_user(unsigned int total_size,
+ 	/* ... then go back and fix counters and names */
+ 	for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
+ 		unsigned int i;
+-		struct ipt_entry_match *m;
+-		struct ipt_entry_target *t;
++		const struct ipt_entry_match *m;
++		const struct ipt_entry_target *t;
+ 
+ 		e = (struct ipt_entry *)(loc_cpu_entry + off);
+ 		if (copy_to_user(userptr + off
+@@ -1116,7 +1116,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
+ 				    "iptable_%s", name);
+ 	if (t && !IS_ERR(t)) {
+ 		struct ipt_getinfo info;
+-		struct xt_table_info *private = t->private;
++		const struct xt_table_info *private = t->private;
+ 
+ #ifdef CONFIG_COMPAT
+ 		if (compat) {
+@@ -1172,7 +1172,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
+ 
+ 	t = xt_find_table_lock(net, AF_INET, get.name);
+ 	if (t && !IS_ERR(t)) {
+-		struct xt_table_info *private = t->private;
++		const struct xt_table_info *private = t->private;
+ 		duprintf("t->private->number = %u\n", private->number);
+ 		if (get.size == private->size)
+ 			ret = copy_entries_to_user(private->size,
+@@ -1180,7 +1180,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
+ 		else {
+ 			duprintf("get_entries: I've got %u not %u!\n",
+ 				 private->size, get.size);
+-			ret = -EINVAL;
++			ret = -EAGAIN;
+ 		}
+ 		module_put(t->me);
+ 		xt_table_unlock(t);
+@@ -1337,11 +1337,11 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, int compat
+ 	struct xt_counters_info tmp;
+ 	struct xt_counters *paddc;
+ 	unsigned int num_counters;
+-	char *name;
++	const char *name;
+ 	int size;
+ 	void *ptmp;
+ 	struct xt_table *t;
+-	struct xt_table_info *private;
++	const struct xt_table_info *private;
+ 	int ret = 0;
+ 	void *loc_cpu_entry;
+ #ifdef CONFIG_COMPAT
+@@ -1852,11 +1852,11 @@ compat_do_ipt_set_ctl(struct sock *sk,	int cmd, void __user *user,
+ 
+ 	switch (cmd) {
+ 	case IPT_SO_SET_REPLACE:
+-		ret = compat_do_replace(sk->sk_net, user, len);
++		ret = compat_do_replace(sock_net(sk), user, len);
+ 		break;
+ 
+ 	case IPT_SO_SET_ADD_COUNTERS:
+-		ret = do_add_counters(sk->sk_net, user, len, 1);
++		ret = do_add_counters(sock_net(sk), user, len, 1);
+ 		break;
+ 
+ 	default:
+@@ -1878,11 +1878,11 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
+ 			    void __user *userptr)
+ {
+ 	struct xt_counters *counters;
+-	struct xt_table_info *private = table->private;
++	const struct xt_table_info *private = table->private;
+ 	void __user *pos;
+ 	unsigned int size;
+ 	int ret = 0;
+-	void *loc_cpu_entry;
++	const void *loc_cpu_entry;
+ 	unsigned int i = 0;
+ 
+ 	counters = alloc_counters(table);
+@@ -1929,7 +1929,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
+ 	xt_compat_lock(AF_INET);
+ 	t = xt_find_table_lock(net, AF_INET, get.name);
+ 	if (t && !IS_ERR(t)) {
+-		struct xt_table_info *private = t->private;
++		const struct xt_table_info *private = t->private;
+ 		struct xt_table_info info;
+ 		duprintf("t->private->number = %u\n", private->number);
+ 		ret = compat_table_info(private, &info);
+@@ -1939,7 +1939,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
+ 		} else if (!ret) {
+ 			duprintf("compat_get_entries: I've got %u not %u!\n",
+ 				 private->size, get.size);
+-			ret = -EINVAL;
++			ret = -EAGAIN;
+ 		}
+ 		xt_compat_flush_offsets(AF_INET);
+ 		module_put(t->me);
+@@ -1963,10 +1963,10 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+ 
+ 	switch (cmd) {
+ 	case IPT_SO_GET_INFO:
+-		ret = get_info(sk->sk_net, user, len, 1);
++		ret = get_info(sock_net(sk), user, len, 1);
+ 		break;
+ 	case IPT_SO_GET_ENTRIES:
+-		ret = compat_get_entries(sk->sk_net, user, len);
++		ret = compat_get_entries(sock_net(sk), user, len);
+ 		break;
+ 	default:
+ 		ret = do_ipt_get_ctl(sk, cmd, user, len);
+@@ -1985,11 +1985,11 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
+ 
+ 	switch (cmd) {
+ 	case IPT_SO_SET_REPLACE:
+-		ret = do_replace(sk->sk_net, user, len);
++		ret = do_replace(sock_net(sk), user, len);
+ 		break;
+ 
+ 	case IPT_SO_SET_ADD_COUNTERS:
+-		ret = do_add_counters(sk->sk_net, user, len, 0);
++		ret = do_add_counters(sock_net(sk), user, len, 0);
+ 		break;
+ 
+ 	default:
+@@ -2010,11 +2010,11 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+ 
+ 	switch (cmd) {
+ 	case IPT_SO_GET_INFO:
+-		ret = get_info(sk->sk_net, user, len, 0);
++		ret = get_info(sock_net(sk), user, len, 0);
+ 		break;
+ 
+ 	case IPT_SO_GET_ENTRIES:
+-		ret = get_entries(sk->sk_net, user, len);
++		ret = get_entries(sock_net(sk), user, len);
+ 		break;
+ 
+ 	case IPT_SO_GET_REVISION_MATCH:
+@@ -2130,7 +2130,8 @@ icmp_match(const struct sk_buff *skb,
+ 	   unsigned int protoff,
+ 	   bool *hotdrop)
+ {
+-	struct icmphdr _icmph, *ic;
++	const struct icmphdr *ic;
++	struct icmphdr _icmph;
+ 	const struct ipt_icmp *icmpinfo = matchinfo;
+ 
+ 	/* Must not be a fragment. */
+diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
+index a12dd32..22d8e7c 100644
+--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
++++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
+@@ -144,7 +144,7 @@ clusterip_config_init_nodelist(struct clusterip_config *c,
+ }
+ 
+ static struct clusterip_config *
+-clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
++clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
+ 			struct net_device *dev)
+ {
+ 	struct clusterip_config *c;
+@@ -333,7 +333,7 @@ clusterip_tg(struct sk_buff *skb, const struct net_device *in,
+ 	}
+ 
+ #ifdef DEBUG
+-	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++	nf_ct_dump_tuple_ip(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ #endif
+ 	pr_debug("hash=%u ct_hash=%u ", hash, ct->mark);
+ 	if (!clusterip_responsible(cipinfo->config, hash)) {
+@@ -418,7 +418,7 @@ clusterip_tg_check(const char *tablename, const void *e_void,
+ /* drop reference count of cluster config when rule is deleted */
+ static void clusterip_tg_destroy(const struct xt_target *target, void *targinfo)
+ {
+-	struct ipt_clusterip_tgt_info *cipinfo = targinfo;
++	const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
+ 
+ 	/* if no more entries are referencing the config, remove it
+ 	 * from the list and destroy the proc entry */
+@@ -567,7 +567,7 @@ struct clusterip_seq_position {
+ 
+ static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
+ {
+-	struct proc_dir_entry *pde = s->private;
++	const struct proc_dir_entry *pde = s->private;
+ 	struct clusterip_config *c = pde->data;
+ 	unsigned int weight;
+ 	u_int32_t local_nodes;
+@@ -594,7 +594,7 @@ static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
+ 
+ static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos)
+ {
+-	struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
++	struct clusterip_seq_position *idx = v;
+ 
+ 	*pos = ++idx->pos;
+ 	if (*pos >= idx->weight) {
+@@ -613,7 +613,7 @@ static void clusterip_seq_stop(struct seq_file *s, void *v)
+ 
+ static int clusterip_seq_show(struct seq_file *s, void *v)
+ {
+-	struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
++	struct clusterip_seq_position *idx = v;
+ 
+ 	if (idx->pos != 0)
+ 		seq_putc(s, ',');
+@@ -669,7 +669,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
+ {
+ #define PROC_WRITELEN	10
+ 	char buffer[PROC_WRITELEN+1];
+-	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
++	const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ 	struct clusterip_config *c = pde->data;
+ 	unsigned long nodenum;
+ 
+diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
+index 21395bc..d60139c 100644
+--- a/net/ipv4/netfilter/ipt_ECN.c
++++ b/net/ipv4/netfilter/ipt_ECN.c
+@@ -100,7 +100,7 @@ ecn_tg_check(const char *tablename, const void *e_void,
+              const struct xt_target *target, void *targinfo,
+              unsigned int hook_mask)
+ {
+-	const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
++	const struct ipt_ECN_info *einfo = targinfo;
+ 	const struct ipt_entry *e = e_void;
+ 
+ 	if (einfo->operation & IPT_ECN_OP_MASK) {
+diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
+index b38d785..0af1413 100644
+--- a/net/ipv4/netfilter/ipt_LOG.c
++++ b/net/ipv4/netfilter/ipt_LOG.c
+@@ -76,7 +76,8 @@ static void dump_packet(const struct nf_loginfo *info,
+ 
+ 	if ((logflags & IPT_LOG_IPOPT)
+ 	    && ih->ihl * 4 > sizeof(struct iphdr)) {
+-		unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op;
++		const unsigned char *op;
++		unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
+ 		unsigned int i, optsize;
+ 
+ 		optsize = ih->ihl * 4 - sizeof(struct iphdr);
+@@ -338,12 +339,16 @@ static void dump_packet(const struct nf_loginfo *info,
+ 	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",
++			printk("UID=%u GID=%u ",
+ 				skb->sk->sk_socket->file->f_uid,
+ 				skb->sk->sk_socket->file->f_gid);
+ 		read_unlock_bh(&skb->sk->sk_callback_lock);
+ 	}
+ 
++	/* Max length: 16 "MARK=0xFFFFFFFF " */
++	if (!iphoff && skb->mark)
++		printk("MARK=0x%x ", skb->mark);
++
+ 	/* Proto    Max log string length */
+ 	/* IP:      40+46+6+11+127 = 230 */
+ 	/* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
+diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
+index d80fee8..84c26dd 100644
+--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
++++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
+@@ -77,7 +77,7 @@ masquerade_tg(struct sk_buff *skb, const struct net_device *in,
+ 		return NF_ACCEPT;
+ 
+ 	mr = targinfo;
+-	rt = (struct rtable *)skb->dst;
++	rt = skb->rtable;
+ 	newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+ 	if (!newsrc) {
+ 		printk("MASQUERADE: %s ate my IP address\n", out->name);
+@@ -120,7 +120,7 @@ static int masq_device_event(struct notifier_block *this,
+ {
+ 	const struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event == NETDEV_DOWN) {
+@@ -139,18 +139,8 @@ static int masq_inet_event(struct notifier_block *this,
+ 			   unsigned long event,
+ 			   void *ptr)
+ {
+-	const struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
+-
+-	if (event == NETDEV_DOWN) {
+-		/* IP address was deleted.  Search entire table for
+-		   conntracks which were associated with that device,
+-		   and forget them. */
+-		NF_CT_ASSERT(dev->ifindex != 0);
+-
+-		nf_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex);
+-	}
+-
+-	return NOTIFY_DONE;
++	struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
++	return masq_device_event(this, event, dev);
+ }
+ 
+ static struct notifier_block masq_dev_notifier = {
+diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
+index 22606e2..2639872 100644
+--- a/net/ipv4/netfilter/ipt_REJECT.c
++++ b/net/ipv4/netfilter/ipt_REJECT.c
+@@ -35,8 +35,10 @@ MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4");
+ static void send_reset(struct sk_buff *oldskb, int hook)
+ {
+ 	struct sk_buff *nskb;
+-	struct iphdr *oiph, *niph;
+-	struct tcphdr _otcph, *oth, *tcph;
++	const struct iphdr *oiph;
++	struct iphdr *niph;
++	const struct tcphdr *oth;
++	struct tcphdr _otcph, *tcph;
+ 	unsigned int addr_type;
+ 
+ 	/* IP header checks: fragment. */
+diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
+index 50e0669..21cb053 100644
+--- a/net/ipv4/netfilter/ipt_recent.c
++++ b/net/ipv4/netfilter/ipt_recent.c
+@@ -340,7 +340,7 @@ static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
+ static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ 	struct recent_iter_state *st = seq->private;
+-	struct recent_table *t = st->table;
++	const struct recent_table *t = st->table;
+ 	struct recent_entry *e = v;
+ 	struct list_head *head = e->list.next;
+ 
+@@ -361,7 +361,7 @@ static void recent_seq_stop(struct seq_file *s, void *v)
+ 
+ static int recent_seq_show(struct seq_file *seq, void *v)
+ {
+-	struct recent_entry *e = v;
++	const struct recent_entry *e = v;
+ 	unsigned int i;
+ 
+ 	i = (e->index - 1) % ip_pkt_list_tot;
+@@ -396,7 +396,7 @@ static int recent_seq_open(struct inode *inode, struct file *file)
+ static ssize_t recent_proc_write(struct file *file, const char __user *input,
+ 				 size_t size, loff_t *loff)
+ {
+-	struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
++	const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ 	struct recent_table *t = pde->data;
+ 	struct recent_entry *e;
+ 	char buf[sizeof("+255.255.255.255")], *c = buf;
+diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
+index 69f3d7e..1ea677d 100644
+--- a/net/ipv4/netfilter/iptable_filter.c
++++ b/net/ipv4/netfilter/iptable_filter.c
+@@ -56,20 +56,32 @@ static struct
+ static struct xt_table packet_filter = {
+ 	.name		= "filter",
+ 	.valid_hooks	= FILTER_VALID_HOOKS,
+-	.lock		= RW_LOCK_UNLOCKED,
++	.lock		= __RW_LOCK_UNLOCKED(packet_filter.lock),
+ 	.me		= THIS_MODULE,
+ 	.af		= AF_INET,
+ };
+ 
+ /* The work comes in here from netfilter.c. */
+ static unsigned int
++ipt_local_in_hook(unsigned int hook,
++		  struct sk_buff *skb,
++		  const struct net_device *in,
++		  const struct net_device *out,
++		  int (*okfn)(struct sk_buff *))
++{
++	return ipt_do_table(skb, hook, in, out,
++			    nf_local_in_net(in, out)->ipv4.iptable_filter);
++}
++
++static unsigned int
+ ipt_hook(unsigned int hook,
+ 	 struct sk_buff *skb,
+ 	 const struct net_device *in,
+ 	 const struct net_device *out,
+ 	 int (*okfn)(struct sk_buff *))
+ {
+-	return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter);
++	return ipt_do_table(skb, hook, in, out,
++			    nf_forward_net(in, out)->ipv4.iptable_filter);
+ }
+ 
+ static unsigned int
+@@ -88,12 +100,13 @@ ipt_local_out_hook(unsigned int hook,
+ 		return NF_ACCEPT;
+ 	}
+ 
+-	return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter);
++	return ipt_do_table(skb, hook, in, out,
++			    nf_local_out_net(in, out)->ipv4.iptable_filter);
+ }
+ 
+ static struct nf_hook_ops ipt_ops[] __read_mostly = {
+ 	{
+-		.hook		= ipt_hook,
++		.hook		= ipt_local_in_hook,
+ 		.owner		= THIS_MODULE,
+ 		.pf		= PF_INET,
+ 		.hooknum	= NF_INET_LOCAL_IN,
+diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
+index c55a210..da59182 100644
+--- a/net/ipv4/netfilter/iptable_mangle.c
++++ b/net/ipv4/netfilter/iptable_mangle.c
+@@ -67,20 +67,54 @@ static struct
+ static struct xt_table packet_mangler = {
+ 	.name		= "mangle",
+ 	.valid_hooks	= MANGLE_VALID_HOOKS,
+-	.lock		= RW_LOCK_UNLOCKED,
++	.lock		= __RW_LOCK_UNLOCKED(packet_mangler.lock),
+ 	.me		= THIS_MODULE,
+ 	.af		= AF_INET,
+ };
+ 
+ /* The work comes in here from netfilter.c. */
+ static unsigned int
+-ipt_route_hook(unsigned int hook,
++ipt_pre_routing_hook(unsigned int hook,
++		     struct sk_buff *skb,
++		     const struct net_device *in,
++		     const struct net_device *out,
++		     int (*okfn)(struct sk_buff *))
++{
++	return ipt_do_table(skb, hook, in, out,
++			    nf_pre_routing_net(in, out)->ipv4.iptable_mangle);
++}
++
++static unsigned int
++ipt_post_routing_hook(unsigned int hook,
++		      struct sk_buff *skb,
++		      const struct net_device *in,
++		      const struct net_device *out,
++		      int (*okfn)(struct sk_buff *))
++{
++	return ipt_do_table(skb, hook, in, out,
++			    nf_post_routing_net(in, out)->ipv4.iptable_mangle);
++}
++
++static unsigned int
++ipt_local_in_hook(unsigned int hook,
++		  struct sk_buff *skb,
++		  const struct net_device *in,
++		  const struct net_device *out,
++		  int (*okfn)(struct sk_buff *))
++{
++	return ipt_do_table(skb, hook, in, out,
++			    nf_local_in_net(in, out)->ipv4.iptable_mangle);
++}
++
++static unsigned int
++ipt_forward_hook(unsigned int hook,
+ 	 struct sk_buff *skb,
+ 	 const struct net_device *in,
+ 	 const struct net_device *out,
+ 	 int (*okfn)(struct sk_buff *))
+ {
+-	return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle);
++	return ipt_do_table(skb, hook, in, out,
++			    nf_forward_net(in, out)->ipv4.iptable_mangle);
+ }
+ 
+ static unsigned int
+@@ -112,7 +146,8 @@ ipt_local_hook(unsigned int hook,
+ 	daddr = iph->daddr;
+ 	tos = iph->tos;
+ 
+-	ret = ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle);
++	ret = ipt_do_table(skb, hook, in, out,
++			   nf_local_out_net(in, out)->ipv4.iptable_mangle);
+ 	/* Reroute for ANY change. */
+ 	if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
+ 		iph = ip_hdr(skb);
+@@ -130,21 +165,21 @@ ipt_local_hook(unsigned int hook,
+ 
+ static struct nf_hook_ops ipt_ops[] __read_mostly = {
+ 	{
+-		.hook		= ipt_route_hook,
++		.hook		= ipt_pre_routing_hook,
+ 		.owner		= THIS_MODULE,
+ 		.pf		= PF_INET,
+ 		.hooknum	= NF_INET_PRE_ROUTING,
+ 		.priority	= NF_IP_PRI_MANGLE,
+ 	},
+ 	{
+-		.hook		= ipt_route_hook,
++		.hook		= ipt_local_in_hook,
+ 		.owner		= THIS_MODULE,
+ 		.pf		= PF_INET,
+ 		.hooknum	= NF_INET_LOCAL_IN,
+ 		.priority	= NF_IP_PRI_MANGLE,
+ 	},
+ 	{
+-		.hook		= ipt_route_hook,
++		.hook		= ipt_forward_hook,
+ 		.owner		= THIS_MODULE,
+ 		.pf		= PF_INET,
+ 		.hooknum	= NF_INET_FORWARD,
+@@ -158,7 +193,7 @@ static struct nf_hook_ops ipt_ops[] __read_mostly = {
+ 		.priority	= NF_IP_PRI_MANGLE,
+ 	},
+ 	{
+-		.hook		= ipt_route_hook,
++		.hook		= ipt_post_routing_hook,
+ 		.owner		= THIS_MODULE,
+ 		.pf		= PF_INET,
+ 		.hooknum	= NF_INET_POST_ROUTING,
+diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
+index e41fe8c..fddce77 100644
+--- a/net/ipv4/netfilter/iptable_raw.c
++++ b/net/ipv4/netfilter/iptable_raw.c
+@@ -39,7 +39,7 @@ static struct
+ static struct xt_table packet_raw = {
+ 	.name = "raw",
+ 	.valid_hooks =  RAW_VALID_HOOKS,
+-	.lock = RW_LOCK_UNLOCKED,
++	.lock = __RW_LOCK_UNLOCKED(packet_raw.lock),
+ 	.me = THIS_MODULE,
+ 	.af = AF_INET,
+ };
+@@ -52,7 +52,8 @@ ipt_hook(unsigned int hook,
+ 	 const struct net_device *out,
+ 	 int (*okfn)(struct sk_buff *))
+ {
+-	return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw);
++	return ipt_do_table(skb, hook, in, out,
++			    nf_pre_routing_net(in, out)->ipv4.iptable_raw);
+ }
+ 
+ static unsigned int
+@@ -70,7 +71,8 @@ ipt_local_hook(unsigned int hook,
+ 			       "packet.\n");
+ 		return NF_ACCEPT;
+ 	}
+-	return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw);
++	return ipt_do_table(skb, hook, in, out,
++			    nf_local_out_net(in, out)->ipv4.iptable_raw);
+ }
+ 
+ /* 'raw' is the very first table. */
+diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+index a65b845..cacb9cb 100644
+--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+@@ -23,30 +23,36 @@
+ #include <net/netfilter/nf_conntrack_l3proto.h>
+ #include <net/netfilter/nf_conntrack_core.h>
+ #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
++#include <net/netfilter/nf_nat_helper.h>
+ 
+-static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
+-			     struct nf_conntrack_tuple *tuple)
++int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
++			      struct nf_conn *ct,
++			      enum ip_conntrack_info ctinfo);
++EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook);
++
++static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
++			      struct nf_conntrack_tuple *tuple)
+ {
+ 	const __be32 *ap;
+ 	__be32 _addrs[2];
+ 	ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr),
+ 				sizeof(u_int32_t) * 2, _addrs);
+ 	if (ap == NULL)
+-		return 0;
++		return false;
+ 
+ 	tuple->src.u3.ip = ap[0];
+ 	tuple->dst.u3.ip = ap[1];
+ 
+-	return 1;
++	return true;
+ }
+ 
+-static int ipv4_invert_tuple(struct nf_conntrack_tuple *tuple,
+-			   const struct nf_conntrack_tuple *orig)
++static bool ipv4_invert_tuple(struct nf_conntrack_tuple *tuple,
++			      const struct nf_conntrack_tuple *orig)
+ {
+ 	tuple->src.u3.ip = orig->dst.u3.ip;
+ 	tuple->dst.u3.ip = orig->src.u3.ip;
+ 
+-	return 1;
++	return true;
+ }
+ 
+ static int ipv4_print_tuple(struct seq_file *s,
+@@ -101,35 +107,41 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
+ 				 const struct net_device *out,
+ 				 int (*okfn)(struct sk_buff *))
+ {
+-	/* We've seen it coming out the other side: confirm it */
+-	return nf_conntrack_confirm(skb);
+-}
+-
+-static unsigned int ipv4_conntrack_help(unsigned int hooknum,
+-				      struct sk_buff *skb,
+-				      const struct net_device *in,
+-				      const struct net_device *out,
+-				      int (*okfn)(struct sk_buff *))
+-{
+ 	struct nf_conn *ct;
+ 	enum ip_conntrack_info ctinfo;
+ 	const struct nf_conn_help *help;
+ 	const struct nf_conntrack_helper *helper;
++	unsigned int ret;
+ 
+ 	/* This is where we call the helper: as the packet goes out. */
+ 	ct = nf_ct_get(skb, &ctinfo);
+ 	if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
+-		return NF_ACCEPT;
++		goto out;
+ 
+ 	help = nfct_help(ct);
+ 	if (!help)
+-		return NF_ACCEPT;
++		goto out;
++
+ 	/* rcu_read_lock()ed by nf_hook_slow */
+ 	helper = rcu_dereference(help->helper);
+ 	if (!helper)
+-		return NF_ACCEPT;
+-	return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
+-			    ct, ctinfo);
++		goto out;
++
++	ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
++			   ct, ctinfo);
++	if (ret != NF_ACCEPT)
++		return ret;
++
++	if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
++		typeof(nf_nat_seq_adjust_hook) seq_adjust;
++
++		seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
++		if (!seq_adjust || !seq_adjust(skb, ct, ctinfo))
++			return NF_DROP;
++	}
++out:
++	/* We've seen it coming out the other side: confirm it */
++	return nf_conntrack_confirm(skb);
+ }
+ 
+ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
+@@ -211,20 +223,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
+ 		.priority	= NF_IP_PRI_CONNTRACK,
+ 	},
+ 	{
+-		.hook		= ipv4_conntrack_help,
+-		.owner		= THIS_MODULE,
+-		.pf		= PF_INET,
+-		.hooknum	= NF_INET_POST_ROUTING,
+-		.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+-	},
+-	{
+-		.hook		= ipv4_conntrack_help,
+-		.owner		= THIS_MODULE,
+-		.pf		= PF_INET,
+-		.hooknum	= NF_INET_LOCAL_IN,
+-		.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+-	},
+-	{
+ 		.hook		= ipv4_confirm,
+ 		.owner		= THIS_MODULE,
+ 		.pf		= PF_INET,
+diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+index f500b0f..40a46d4 100644
+--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+@@ -106,21 +106,16 @@ static int ct_seq_show(struct seq_file *s, void *v)
+ 	/* we only want to print DIR_ORIGINAL */
+ 	if (NF_CT_DIRECTION(hash))
+ 		return 0;
+-	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num != AF_INET)
++	if (nf_ct_l3num(ct) != AF_INET)
+ 		return 0;
+ 
+-	l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+-				       .tuple.src.l3num);
++	l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
+ 	NF_CT_ASSERT(l3proto);
+-	l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+-				       .tuple.src.l3num,
+-				       ct->tuplehash[IP_CT_DIR_ORIGINAL]
+-				       .tuple.dst.protonum);
++	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ 	NF_CT_ASSERT(l4proto);
+ 
+ 	if (seq_printf(s, "%-8s %u %ld ",
+-		      l4proto->name,
+-		      ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
++		      l4proto->name, nf_ct_protonum(ct),
+ 		      timer_pending(&ct->timeout)
+ 		      ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0)
+ 		return -ENOSPC;
+@@ -379,7 +374,7 @@ static const struct file_operations ct_cpu_seq_fops = {
+ 	.open    = ct_cpu_seq_open,
+ 	.read    = seq_read,
+ 	.llseek  = seq_lseek,
+-	.release = seq_release_private,
++	.release = seq_release,
+ };
+ 
+ int __init nf_conntrack_ipv4_compat_init(void)
+diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+index 6873fdd..78ab19a 100644
+--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
++++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+@@ -22,22 +22,21 @@
+ 
+ static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
+ 
+-static int icmp_pkt_to_tuple(const struct sk_buff *skb,
+-			     unsigned int dataoff,
+-			     struct nf_conntrack_tuple *tuple)
++static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++			      struct nf_conntrack_tuple *tuple)
+ {
+ 	const struct icmphdr *hp;
+ 	struct icmphdr _hdr;
+ 
+ 	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ 	if (hp == NULL)
+-		return 0;
++		return false;
+ 
+ 	tuple->dst.u.icmp.type = hp->type;
+ 	tuple->src.u.icmp.id = hp->un.echo.id;
+ 	tuple->dst.u.icmp.code = hp->code;
+ 
+-	return 1;
++	return true;
+ }
+ 
+ /* Add 1; spaces filled with 0. */
+@@ -52,17 +51,17 @@ static const u_int8_t invmap[] = {
+ 	[ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
+ };
+ 
+-static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
+-			     const struct nf_conntrack_tuple *orig)
++static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
++			      const struct nf_conntrack_tuple *orig)
+ {
+ 	if (orig->dst.u.icmp.type >= sizeof(invmap)
+ 	    || !invmap[orig->dst.u.icmp.type])
+-		return 0;
++		return false;
+ 
+ 	tuple->src.u.icmp.id = orig->src.u.icmp.id;
+ 	tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1;
+ 	tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
+-	return 1;
++	return true;
+ }
+ 
+ /* Print out the per-protocol part of the tuple. */
+@@ -101,8 +100,8 @@ static int icmp_packet(struct nf_conn *ct,
+ }
+ 
+ /* Called when a new connection for this protocol found. */
+-static int icmp_new(struct nf_conn *ct,
+-		    const struct sk_buff *skb, unsigned int dataoff)
++static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
++		     unsigned int dataoff)
+ {
+ 	static const u_int8_t valid_new[] = {
+ 		[ICMP_ECHO] = 1,
+@@ -116,11 +115,11 @@ static int icmp_new(struct nf_conn *ct,
+ 		/* Can't create a new ICMP `conn' with this. */
+ 		pr_debug("icmp: can't create new conn with type %u\n",
+ 			 ct->tuplehash[0].tuple.dst.u.icmp.type);
+-		NF_CT_DUMP_TUPLE(&ct->tuplehash[0].tuple);
+-		return 0;
++		nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple);
++		return false;
+ 	}
+ 	atomic_set(&ct->proto.icmp.count, 0);
+-	return 1;
++	return true;
+ }
+ 
+ /* Returns conntrack if it dealt with ICMP, and filled in skb fields */
+diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
+index 36b4e3b..0457859 100644
+--- a/net/ipv4/netfilter/nf_nat_core.c
++++ b/net/ipv4/netfilter/nf_nat_core.c
+@@ -150,9 +150,9 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple,
+ 		     const struct nf_nat_range *range)
+ {
+ 	unsigned int h = hash_by_src(tuple);
+-	struct nf_conn_nat *nat;
+-	struct nf_conn *ct;
+-	struct hlist_node *n;
++	const struct nf_conn_nat *nat;
++	const struct nf_conn *ct;
++	const struct hlist_node *n;
+ 
+ 	rcu_read_lock();
+ 	hlist_for_each_entry_rcu(nat, n, &bysource[h], bysource) {
+@@ -349,7 +349,7 @@ nf_nat_setup_info(struct nf_conn *ct,
+ EXPORT_SYMBOL(nf_nat_setup_info);
+ 
+ /* Returns true if succeeded. */
+-static int
++static bool
+ manip_pkt(u_int16_t proto,
+ 	  struct sk_buff *skb,
+ 	  unsigned int iphdroff,
+@@ -360,7 +360,7 @@ manip_pkt(u_int16_t proto,
+ 	const struct nf_nat_protocol *p;
+ 
+ 	if (!skb_make_writable(skb, iphdroff + sizeof(*iph)))
+-		return 0;
++		return false;
+ 
+ 	iph = (void *)skb->data + iphdroff;
+ 
+@@ -369,7 +369,7 @@ manip_pkt(u_int16_t proto,
+ 	/* rcu_read_lock()ed by nf_hook_slow */
+ 	p = __nf_nat_proto_find(proto);
+ 	if (!p->manip_pkt(skb, iphdroff, target, maniptype))
+-		return 0;
++		return false;
+ 
+ 	iph = (void *)skb->data + iphdroff;
+ 
+@@ -380,7 +380,7 @@ manip_pkt(u_int16_t proto,
+ 		csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip);
+ 		iph->daddr = target->dst.u3.ip;
+ 	}
+-	return 1;
++	return true;
+ }
+ 
+ /* Do packet manipulations according to nf_nat_setup_info. */
+@@ -426,7 +426,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
+ 		struct icmphdr icmp;
+ 		struct iphdr ip;
+ 	} *inside;
+-	struct nf_conntrack_l4proto *l4proto;
++	const struct nf_conntrack_l4proto *l4proto;
+ 	struct nf_conntrack_tuple inner, target;
+ 	int hdrlen = ip_hdrlen(skb);
+ 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+@@ -544,46 +544,6 @@ void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto)
+ }
+ EXPORT_SYMBOL(nf_nat_protocol_unregister);
+ 
+-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+-int
+-nf_nat_port_range_to_nlattr(struct sk_buff *skb,
+-			    const struct nf_nat_range *range)
+-{
+-	NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MIN, range->min.tcp.port);
+-	NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MAX, range->max.tcp.port);
+-
+-	return 0;
+-
+-nla_put_failure:
+-	return -1;
+-}
+-EXPORT_SYMBOL_GPL(nf_nat_port_nlattr_to_range);
+-
+-int
+-nf_nat_port_nlattr_to_range(struct nlattr *tb[], struct nf_nat_range *range)
+-{
+-	int ret = 0;
+-
+-	/* we have to return whether we actually parsed something or not */
+-
+-	if (tb[CTA_PROTONAT_PORT_MIN]) {
+-		ret = 1;
+-		range->min.tcp.port = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]);
+-	}
+-
+-	if (!tb[CTA_PROTONAT_PORT_MAX]) {
+-		if (ret)
+-			range->max.tcp.port = range->min.tcp.port;
+-	} else {
+-		ret = 1;
+-		range->max.tcp.port = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]);
+-	}
+-
+-	return ret;
+-}
+-EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nlattr);
+-#endif
+-
+ /* Noone using conntrack by the time this called. */
+ static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
+ {
+@@ -660,6 +620,9 @@ static int __init nf_nat_init(void)
+ 	nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
+ 
+ 	l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
++
++	BUG_ON(nf_nat_seq_adjust_hook != NULL);
++	rcu_assign_pointer(nf_nat_seq_adjust_hook, nf_nat_seq_adjust);
+ 	return 0;
+ 
+  cleanup_extend:
+@@ -686,6 +649,8 @@ static void __exit nf_nat_cleanup(void)
+ 	nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size);
+ 	nf_ct_l3proto_put(l3proto);
+ 	nf_ct_extend_unregister(&nat_extend);
++	rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);
++	synchronize_net();
+ }
+ 
+ MODULE_LICENSE("GPL");
+diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
+index ca57f47..11976ea 100644
+--- a/net/ipv4/netfilter/nf_nat_helper.c
++++ b/net/ipv4/netfilter/nf_nat_helper.c
+@@ -139,7 +139,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb,
+ 			 const char *rep_buffer,
+ 			 unsigned int rep_len)
+ {
+-	struct rtable *rt = (struct rtable *)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	struct iphdr *iph;
+ 	struct tcphdr *tcph;
+ 	int oldlen, datalen;
+@@ -217,7 +217,7 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb,
+ 			 const char *rep_buffer,
+ 			 unsigned int rep_len)
+ {
+-	struct rtable *rt = (struct rtable *)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	struct iphdr *iph;
+ 	struct udphdr *udph;
+ 	int datalen, oldlen;
+@@ -416,7 +416,6 @@ nf_nat_seq_adjust(struct sk_buff *skb,
+ 
+ 	return 1;
+ }
+-EXPORT_SYMBOL(nf_nat_seq_adjust);
+ 
+ /* Setup NAT on this expected conntrack so it follows master. */
+ /* If we fail to get a free NAT slot, we'll get dropped on confirm */
+diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
+index 3a1e6d6..da3d91a 100644
+--- a/net/ipv4/netfilter/nf_nat_pptp.c
++++ b/net/ipv4/netfilter/nf_nat_pptp.c
+@@ -72,7 +72,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
+ 	}
+ 
+ 	pr_debug("trying to unexpect other dir: ");
+-	NF_CT_DUMP_TUPLE(&t);
++	nf_ct_dump_tuple_ip(&t);
+ 	other_exp = nf_ct_expect_find_get(&t);
+ 	if (other_exp) {
+ 		nf_ct_unexpect_related(other_exp);
+diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c
+new file mode 100644
+index 0000000..91537f1
+--- /dev/null
++++ b/net/ipv4/netfilter/nf_nat_proto_common.c
+@@ -0,0 +1,120 @@
++/* (C) 1999-2001 Paul `Rusty' Russell
++ * (C) 2002-2006 Netfilter Core Team <coreteam at netfilter.org>
++ * (C) 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/types.h>
++#include <linux/random.h>
++#include <linux/ip.h>
++
++#include <linux/netfilter.h>
++#include <net/netfilter/nf_nat.h>
++#include <net/netfilter/nf_nat_core.h>
++#include <net/netfilter/nf_nat_rule.h>
++#include <net/netfilter/nf_nat_protocol.h>
++
++bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
++			   enum nf_nat_manip_type maniptype,
++			   const union nf_conntrack_man_proto *min,
++			   const union nf_conntrack_man_proto *max)
++{
++	__be16 port;
++
++	if (maniptype == IP_NAT_MANIP_SRC)
++		port = tuple->src.u.all;
++	else
++		port = tuple->dst.u.all;
++
++	return ntohs(port) >= ntohs(min->all) &&
++	       ntohs(port) <= ntohs(max->all);
++}
++EXPORT_SYMBOL_GPL(nf_nat_proto_in_range);
++
++bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
++			       const struct nf_nat_range *range,
++			       enum nf_nat_manip_type maniptype,
++			       const struct nf_conn *ct,
++			       u_int16_t *rover)
++{
++	unsigned int range_size, min, i;
++	__be16 *portptr;
++	u_int16_t off;
++
++	if (maniptype == IP_NAT_MANIP_SRC)
++		portptr = &tuple->src.u.all;
++	else
++		portptr = &tuple->dst.u.all;
++
++	/* If no range specified... */
++	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
++		/* If it's dst rewrite, can't change port */
++		if (maniptype == IP_NAT_MANIP_DST)
++			return false;
++
++		if (ntohs(*portptr) < 1024) {
++			/* Loose convention: >> 512 is credential passing */
++			if (ntohs(*portptr) < 512) {
++				min = 1;
++				range_size = 511 - min + 1;
++			} else {
++				min = 600;
++				range_size = 1023 - min + 1;
++			}
++		} else {
++			min = 1024;
++			range_size = 65535 - 1024 + 1;
++		}
++	} else {
++		min = ntohs(range->min.all);
++		range_size = ntohs(range->max.all) - min + 1;
++	}
++
++	off = *rover;
++	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
++		off = net_random();
++
++	for (i = 0; i < range_size; i++, off++) {
++		*portptr = htons(min + off % range_size);
++		if (nf_nat_used_tuple(tuple, ct))
++			continue;
++		if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
++			*rover = off;
++		return true;
++	}
++	return false;
++}
++EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple);
++
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,
++				 const struct nf_nat_range *range)
++{
++	NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MIN, range->min.all);
++	NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MAX, range->max.all);
++	return 0;
++
++nla_put_failure:
++	return -1;
++}
++EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range);
++
++int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
++				 struct nf_nat_range *range)
++{
++	if (tb[CTA_PROTONAT_PORT_MIN]) {
++		range->min.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]);
++		range->max.all = range->min.tcp.port;
++		range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
++	}
++	if (tb[CTA_PROTONAT_PORT_MAX]) {
++		range->max.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]);
++		range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
++	}
++	return 0;
++}
++EXPORT_SYMBOL_GPL(nf_nat_proto_range_to_nlattr);
++#endif
+diff --git a/net/ipv4/netfilter/nf_nat_proto_dccp.c b/net/ipv4/netfilter/nf_nat_proto_dccp.c
+new file mode 100644
+index 0000000..22485ce
+--- /dev/null
++++ b/net/ipv4/netfilter/nf_nat_proto_dccp.c
+@@ -0,0 +1,108 @@
++/*
++ * DCCP NAT protocol helper
++ *
++ * Copyright (c) 2005, 2006. 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/dccp.h>
++
++#include <net/netfilter/nf_conntrack.h>
++#include <net/netfilter/nf_nat.h>
++#include <net/netfilter/nf_nat_protocol.h>
++
++static u_int16_t dccp_port_rover;
++
++static bool
++dccp_unique_tuple(struct nf_conntrack_tuple *tuple,
++		  const struct nf_nat_range *range,
++		  enum nf_nat_manip_type maniptype,
++		  const struct nf_conn *ct)
++{
++	return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++					 &dccp_port_rover);
++}
++
++static bool
++dccp_manip_pkt(struct sk_buff *skb,
++	       unsigned int iphdroff,
++	       const struct nf_conntrack_tuple *tuple,
++	       enum nf_nat_manip_type maniptype)
++{
++	const struct iphdr *iph = (const void *)(skb->data + iphdroff);
++	struct dccp_hdr *hdr;
++	unsigned int hdroff = iphdroff + iph->ihl * 4;
++	__be32 oldip, newip;
++	__be16 *portptr, oldport, newport;
++	int hdrsize = 8; /* DCCP connection tracking guarantees this much */
++
++	if (skb->len >= hdroff + sizeof(struct dccp_hdr))
++		hdrsize = sizeof(struct dccp_hdr);
++
++	if (!skb_make_writable(skb, hdroff + hdrsize))
++		return false;
++
++	iph = (struct iphdr *)(skb->data + iphdroff);
++	hdr = (struct dccp_hdr *)(skb->data + hdroff);
++
++	if (maniptype == IP_NAT_MANIP_SRC) {
++		oldip = iph->saddr;
++		newip = tuple->src.u3.ip;
++		newport = tuple->src.u.dccp.port;
++		portptr = &hdr->dccph_sport;
++	} else {
++		oldip = iph->daddr;
++		newip = tuple->dst.u3.ip;
++		newport = tuple->dst.u.dccp.port;
++		portptr = &hdr->dccph_dport;
++	}
++
++	oldport = *portptr;
++	*portptr = newport;
++
++	if (hdrsize < sizeof(*hdr))
++		return true;
++
++	inet_proto_csum_replace4(&hdr->dccph_checksum, skb, oldip, newip, 1);
++	inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport,
++				 0);
++	return true;
++}
++
++static const struct nf_nat_protocol nf_nat_protocol_dccp = {
++	.protonum		= IPPROTO_DCCP,
++	.me			= THIS_MODULE,
++	.manip_pkt		= dccp_manip_pkt,
++	.in_range		= nf_nat_proto_in_range,
++	.unique_tuple		= dccp_unique_tuple,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++	.range_to_nlattr	= nf_nat_proto_range_to_nlattr,
++	.nlattr_to_range	= nf_nat_proto_nlattr_to_range,
++#endif
++};
++
++static int __init nf_nat_proto_dccp_init(void)
++{
++	return nf_nat_protocol_register(&nf_nat_protocol_dccp);
++}
++
++static void __exit nf_nat_proto_dccp_fini(void)
++{
++	nf_nat_protocol_unregister(&nf_nat_protocol_dccp);
++}
++
++module_init(nf_nat_proto_dccp_init);
++module_exit(nf_nat_proto_dccp_fini);
++
++MODULE_AUTHOR("Patrick McHardy <kaber at trash.net>");
++MODULE_DESCRIPTION("DCCP NAT protocol helper");
++MODULE_LICENSE("GPL");
+diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
+index a1e4da1..d7e8920 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
++++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
+@@ -36,26 +36,8 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Harald Welte <laforge at gnumonks.org>");
+ MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
+ 
+-/* is key in given range between min and max */
+-static int
+-gre_in_range(const struct nf_conntrack_tuple *tuple,
+-	     enum nf_nat_manip_type maniptype,
+-	     const union nf_conntrack_man_proto *min,
+-	     const union nf_conntrack_man_proto *max)
+-{
+-	__be16 key;
+-
+-	if (maniptype == IP_NAT_MANIP_SRC)
+-		key = tuple->src.u.gre.key;
+-	else
+-		key = tuple->dst.u.gre.key;
+-
+-	return ntohs(key) >= ntohs(min->gre.key) &&
+-	       ntohs(key) <= ntohs(max->gre.key);
+-}
+-
+ /* generate unique tuple ... */
+-static int
++static bool
+ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
+ 		 const struct nf_nat_range *range,
+ 		 enum nf_nat_manip_type maniptype,
+@@ -68,7 +50,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
+ 	/* If there is no master conntrack we are not PPTP,
+ 	   do not change tuples */
+ 	if (!ct->master)
+-		return 0;
++		return false;
+ 
+ 	if (maniptype == IP_NAT_MANIP_SRC)
+ 		keyptr = &tuple->src.u.gre.key;
+@@ -89,20 +71,20 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
+ 	for (i = 0; i < range_size; i++, key++) {
+ 		*keyptr = htons(min + key % range_size);
+ 		if (!nf_nat_used_tuple(tuple, ct))
+-			return 1;
++			return true;
+ 	}
+ 
+ 	pr_debug("%p: no NAT mapping\n", ct);
+-	return 0;
++	return false;
+ }
+ 
+ /* manipulate a GRE packet according to maniptype */
+-static int
++static bool
+ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
+ 	      const struct nf_conntrack_tuple *tuple,
+ 	      enum nf_nat_manip_type maniptype)
+ {
+-	struct gre_hdr *greh;
++	const struct gre_hdr *greh;
+ 	struct gre_hdr_pptp *pgreh;
+ 	const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
+ 	unsigned int hdroff = iphdroff + iph->ihl * 4;
+@@ -110,7 +92,7 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
+ 	/* pgreh includes two optional 32bit fields which are not required
+ 	 * to be there.  That's where the magic '8' comes from */
+ 	if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8))
+-		return 0;
++		return false;
+ 
+ 	greh = (void *)skb->data + hdroff;
+ 	pgreh = (struct gre_hdr_pptp *)greh;
+@@ -118,7 +100,7 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
+ 	/* we only have destination manip of a packet, since 'source key'
+ 	 * is not present in the packet itself */
+ 	if (maniptype != IP_NAT_MANIP_DST)
+-		return 1;
++		return true;
+ 	switch (greh->version) {
+ 	case GRE_VERSION_1701:
+ 		/* We do not currently NAT any GREv0 packets.
+@@ -130,21 +112,20 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
+ 		break;
+ 	default:
+ 		pr_debug("can't nat unknown GRE version\n");
+-		return 0;
++		return false;
+ 	}
+-	return 1;
++	return true;
+ }
+ 
+ static const struct nf_nat_protocol gre = {
+-	.name			= "GRE",
+ 	.protonum		= IPPROTO_GRE,
+ 	.me			= THIS_MODULE,
+ 	.manip_pkt		= gre_manip_pkt,
+-	.in_range		= gre_in_range,
++	.in_range		= nf_nat_proto_in_range,
+ 	.unique_tuple		= gre_unique_tuple,
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+-	.range_to_nlattr	= nf_nat_port_range_to_nlattr,
+-	.nlattr_to_range	= nf_nat_port_nlattr_to_range,
++	.range_to_nlattr	= nf_nat_proto_range_to_nlattr,
++	.nlattr_to_range	= nf_nat_proto_nlattr_to_range,
+ #endif
+ };
+ 
+diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
+index 03a0296..19a8b0b 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_icmp.c
++++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
+@@ -17,7 +17,7 @@
+ #include <net/netfilter/nf_nat_rule.h>
+ #include <net/netfilter/nf_nat_protocol.h>
+ 
+-static int
++static bool
+ icmp_in_range(const struct nf_conntrack_tuple *tuple,
+ 	      enum nf_nat_manip_type maniptype,
+ 	      const union nf_conntrack_man_proto *min,
+@@ -27,7 +27,7 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple,
+ 	       ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
+ }
+ 
+-static int
++static bool
+ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ 		  const struct nf_nat_range *range,
+ 		  enum nf_nat_manip_type maniptype,
+@@ -46,12 +46,12 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ 		tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
+ 					     (id % range_size));
+ 		if (!nf_nat_used_tuple(tuple, ct))
+-			return 1;
++			return true;
+ 	}
+-	return 0;
++	return false;
+ }
+ 
+-static int
++static bool
+ icmp_manip_pkt(struct sk_buff *skb,
+ 	       unsigned int iphdroff,
+ 	       const struct nf_conntrack_tuple *tuple,
+@@ -62,24 +62,23 @@ icmp_manip_pkt(struct sk_buff *skb,
+ 	unsigned int hdroff = iphdroff + iph->ihl*4;
+ 
+ 	if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
+-		return 0;
++		return false;
+ 
+ 	hdr = (struct icmphdr *)(skb->data + hdroff);
+ 	inet_proto_csum_replace2(&hdr->checksum, skb,
+ 				 hdr->un.echo.id, tuple->src.u.icmp.id, 0);
+ 	hdr->un.echo.id = tuple->src.u.icmp.id;
+-	return 1;
++	return true;
+ }
+ 
+ const struct nf_nat_protocol nf_nat_protocol_icmp = {
+-	.name			= "ICMP",
+ 	.protonum		= IPPROTO_ICMP,
+ 	.me			= THIS_MODULE,
+ 	.manip_pkt		= icmp_manip_pkt,
+ 	.in_range		= icmp_in_range,
+ 	.unique_tuple		= icmp_unique_tuple,
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+-	.range_to_nlattr	= nf_nat_port_range_to_nlattr,
+-	.nlattr_to_range	= nf_nat_port_nlattr_to_range,
++	.range_to_nlattr	= nf_nat_proto_range_to_nlattr,
++	.nlattr_to_range	= nf_nat_proto_nlattr_to_range,
+ #endif
+ };
+diff --git a/net/ipv4/netfilter/nf_nat_proto_sctp.c b/net/ipv4/netfilter/nf_nat_proto_sctp.c
+new file mode 100644
+index 0000000..82e4c0e
+--- /dev/null
++++ b/net/ipv4/netfilter/nf_nat_proto_sctp.c
+@@ -0,0 +1,96 @@
++/*
++ * Copyright (c) 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/ip.h>
++#include <linux/sctp.h>
++#include <net/sctp/checksum.h>
++
++#include <net/netfilter/nf_nat_protocol.h>
++
++static u_int16_t nf_sctp_port_rover;
++
++static bool
++sctp_unique_tuple(struct nf_conntrack_tuple *tuple,
++		  const struct nf_nat_range *range,
++		  enum nf_nat_manip_type maniptype,
++		  const struct nf_conn *ct)
++{
++	return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++					 &nf_sctp_port_rover);
++}
++
++static bool
++sctp_manip_pkt(struct sk_buff *skb,
++	       unsigned int iphdroff,
++	       const struct nf_conntrack_tuple *tuple,
++	       enum nf_nat_manip_type maniptype)
++{
++	const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
++	sctp_sctphdr_t *hdr;
++	unsigned int hdroff = iphdroff + iph->ihl*4;
++	__be32 oldip, newip;
++	u32 crc32;
++
++	if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
++		return false;
++
++	iph = (struct iphdr *)(skb->data + iphdroff);
++	hdr = (struct sctphdr *)(skb->data + hdroff);
++
++	if (maniptype == IP_NAT_MANIP_SRC) {
++		/* Get rid of src ip and src pt */
++		oldip = iph->saddr;
++		newip = tuple->src.u3.ip;
++		hdr->source = tuple->src.u.sctp.port;
++	} else {
++		/* Get rid of dst ip and dst pt */
++		oldip = iph->daddr;
++		newip = tuple->dst.u3.ip;
++		hdr->dest = tuple->dst.u.sctp.port;
++	}
++
++	crc32 = sctp_start_cksum((u8 *)hdr, skb_headlen(skb) - hdroff);
++	for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
++		crc32 = sctp_update_cksum((u8 *)skb->data, skb_headlen(skb),
++					  crc32);
++	crc32 = sctp_end_cksum(crc32);
++	hdr->checksum = htonl(crc32);
++
++	return true;
++}
++
++static const struct nf_nat_protocol nf_nat_protocol_sctp = {
++	.protonum		= IPPROTO_SCTP,
++	.me			= THIS_MODULE,
++	.manip_pkt		= sctp_manip_pkt,
++	.in_range		= nf_nat_proto_in_range,
++	.unique_tuple		= sctp_unique_tuple,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++	.range_to_nlattr	= nf_nat_proto_range_to_nlattr,
++	.nlattr_to_range	= nf_nat_proto_nlattr_to_range,
++#endif
++};
++
++static int __init nf_nat_proto_sctp_init(void)
++{
++	return nf_nat_protocol_register(&nf_nat_protocol_sctp);
++}
++
++static void __exit nf_nat_proto_sctp_exit(void)
++{
++	nf_nat_protocol_unregister(&nf_nat_protocol_sctp);
++}
++
++module_init(nf_nat_proto_sctp_init);
++module_exit(nf_nat_proto_sctp_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCTP NAT protocol helper");
++MODULE_AUTHOR("Patrick McHardy <kaber at trash.net>");
+diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
+index ffd5d15..399e2cf 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_tcp.c
++++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
+@@ -8,7 +8,6 @@
+ 
+ #include <linux/types.h>
+ #include <linux/init.h>
+-#include <linux/random.h>
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+ 
+@@ -19,75 +18,19 @@
+ #include <net/netfilter/nf_nat_protocol.h>
+ #include <net/netfilter/nf_nat_core.h>
+ 
+-static int
+-tcp_in_range(const struct nf_conntrack_tuple *tuple,
+-	     enum nf_nat_manip_type maniptype,
+-	     const union nf_conntrack_man_proto *min,
+-	     const union nf_conntrack_man_proto *max)
+-{
+-	__be16 port;
+-
+-	if (maniptype == IP_NAT_MANIP_SRC)
+-		port = tuple->src.u.tcp.port;
+-	else
+-		port = tuple->dst.u.tcp.port;
+-
+-	return ntohs(port) >= ntohs(min->tcp.port) &&
+-	       ntohs(port) <= ntohs(max->tcp.port);
+-}
++static u_int16_t tcp_port_rover;
+ 
+-static int
++static bool
+ tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ 		 const struct nf_nat_range *range,
+ 		 enum nf_nat_manip_type maniptype,
+ 		 const struct nf_conn *ct)
+ {
+-	static u_int16_t port;
+-	__be16 *portptr;
+-	unsigned int range_size, min, i;
+-
+-	if (maniptype == IP_NAT_MANIP_SRC)
+-		portptr = &tuple->src.u.tcp.port;
+-	else
+-		portptr = &tuple->dst.u.tcp.port;
+-
+-	/* If no range specified... */
+-	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
+-		/* If it's dst rewrite, can't change port */
+-		if (maniptype == IP_NAT_MANIP_DST)
+-			return 0;
+-
+-		/* Map privileged onto privileged. */
+-		if (ntohs(*portptr) < 1024) {
+-			/* Loose convention: >> 512 is credential passing */
+-			if (ntohs(*portptr)<512) {
+-				min = 1;
+-				range_size = 511 - min + 1;
+-			} else {
+-				min = 600;
+-				range_size = 1023 - min + 1;
+-			}
+-		} else {
+-			min = 1024;
+-			range_size = 65535 - 1024 + 1;
+-		}
+-	} else {
+-		min = ntohs(range->min.tcp.port);
+-		range_size = ntohs(range->max.tcp.port) - min + 1;
+-	}
+-
+-	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
+-		port =  net_random();
+-
+-	for (i = 0; i < range_size; i++, port++) {
+-		*portptr = htons(min + port % range_size);
+-		if (!nf_nat_used_tuple(tuple, ct))
+-			return 1;
+-	}
+-	return 0;
++	return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++					 &tcp_port_rover);
+ }
+ 
+-static int
++static bool
+ tcp_manip_pkt(struct sk_buff *skb,
+ 	      unsigned int iphdroff,
+ 	      const struct nf_conntrack_tuple *tuple,
+@@ -107,7 +50,7 @@ tcp_manip_pkt(struct sk_buff *skb,
+ 		hdrsize = sizeof(struct tcphdr);
+ 
+ 	if (!skb_make_writable(skb, hdroff + hdrsize))
+-		return 0;
++		return false;
+ 
+ 	iph = (struct iphdr *)(skb->data + iphdroff);
+ 	hdr = (struct tcphdr *)(skb->data + hdroff);
+@@ -130,22 +73,21 @@ tcp_manip_pkt(struct sk_buff *skb,
+ 	*portptr = newport;
+ 
+ 	if (hdrsize < sizeof(*hdr))
+-		return 1;
++		return true;
+ 
+ 	inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
+ 	inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0);
+-	return 1;
++	return true;
+ }
+ 
+ const struct nf_nat_protocol nf_nat_protocol_tcp = {
+-	.name			= "TCP",
+ 	.protonum		= IPPROTO_TCP,
+ 	.me			= THIS_MODULE,
+ 	.manip_pkt		= tcp_manip_pkt,
+-	.in_range		= tcp_in_range,
++	.in_range		= nf_nat_proto_in_range,
+ 	.unique_tuple		= tcp_unique_tuple,
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+-	.range_to_nlattr	= nf_nat_port_range_to_nlattr,
+-	.nlattr_to_range	= nf_nat_port_nlattr_to_range,
++	.range_to_nlattr	= nf_nat_proto_range_to_nlattr,
++	.nlattr_to_range	= nf_nat_proto_nlattr_to_range,
+ #endif
+ };
+diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
+index 4b8f499..9e61c79 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_udp.c
++++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
+@@ -8,7 +8,6 @@
+ 
+ #include <linux/types.h>
+ #include <linux/init.h>
+-#include <linux/random.h>
+ #include <linux/ip.h>
+ #include <linux/udp.h>
+ 
+@@ -18,74 +17,19 @@
+ #include <net/netfilter/nf_nat_rule.h>
+ #include <net/netfilter/nf_nat_protocol.h>
+ 
+-static int
+-udp_in_range(const struct nf_conntrack_tuple *tuple,
+-	     enum nf_nat_manip_type maniptype,
+-	     const union nf_conntrack_man_proto *min,
+-	     const union nf_conntrack_man_proto *max)
+-{
+-	__be16 port;
+-
+-	if (maniptype == IP_NAT_MANIP_SRC)
+-		port = tuple->src.u.udp.port;
+-	else
+-		port = tuple->dst.u.udp.port;
+-
+-	return ntohs(port) >= ntohs(min->udp.port) &&
+-	       ntohs(port) <= ntohs(max->udp.port);
+-}
++static u_int16_t udp_port_rover;
+ 
+-static int
++static bool
+ udp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ 		 const struct nf_nat_range *range,
+ 		 enum nf_nat_manip_type maniptype,
+ 		 const struct nf_conn *ct)
+ {
+-	static u_int16_t port;
+-	__be16 *portptr;
+-	unsigned int range_size, min, i;
+-
+-	if (maniptype == IP_NAT_MANIP_SRC)
+-		portptr = &tuple->src.u.udp.port;
+-	else
+-		portptr = &tuple->dst.u.udp.port;
+-
+-	/* If no range specified... */
+-	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
+-		/* If it's dst rewrite, can't change port */
+-		if (maniptype == IP_NAT_MANIP_DST)
+-			return 0;
+-
+-		if (ntohs(*portptr) < 1024) {
+-			/* Loose convention: >> 512 is credential passing */
+-			if (ntohs(*portptr)<512) {
+-				min = 1;
+-				range_size = 511 - min + 1;
+-			} else {
+-				min = 600;
+-				range_size = 1023 - min + 1;
+-			}
+-		} else {
+-			min = 1024;
+-			range_size = 65535 - 1024 + 1;
+-		}
+-	} else {
+-		min = ntohs(range->min.udp.port);
+-		range_size = ntohs(range->max.udp.port) - min + 1;
+-	}
+-
+-	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
+-		port = net_random();
+-
+-	for (i = 0; i < range_size; i++, port++) {
+-		*portptr = htons(min + port % range_size);
+-		if (!nf_nat_used_tuple(tuple, ct))
+-			return 1;
+-	}
+-	return 0;
++	return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++					 &udp_port_rover);
+ }
+ 
+-static int
++static bool
+ udp_manip_pkt(struct sk_buff *skb,
+ 	      unsigned int iphdroff,
+ 	      const struct nf_conntrack_tuple *tuple,
+@@ -98,7 +42,7 @@ udp_manip_pkt(struct sk_buff *skb,
+ 	__be16 *portptr, newport;
+ 
+ 	if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
+-		return 0;
++		return false;
+ 
+ 	iph = (struct iphdr *)(skb->data + iphdroff);
+ 	hdr = (struct udphdr *)(skb->data + hdroff);
+@@ -124,18 +68,17 @@ udp_manip_pkt(struct sk_buff *skb,
+ 			hdr->check = CSUM_MANGLED_0;
+ 	}
+ 	*portptr = newport;
+-	return 1;
++	return true;
+ }
+ 
+ const struct nf_nat_protocol nf_nat_protocol_udp = {
+-	.name			= "UDP",
+ 	.protonum		= IPPROTO_UDP,
+ 	.me			= THIS_MODULE,
+ 	.manip_pkt		= udp_manip_pkt,
+-	.in_range		= udp_in_range,
++	.in_range		= nf_nat_proto_in_range,
+ 	.unique_tuple		= udp_unique_tuple,
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+-	.range_to_nlattr	= nf_nat_port_range_to_nlattr,
+-	.nlattr_to_range	= nf_nat_port_nlattr_to_range,
++	.range_to_nlattr	= nf_nat_proto_range_to_nlattr,
++	.nlattr_to_range	= nf_nat_proto_nlattr_to_range,
+ #endif
+ };
+diff --git a/net/ipv4/netfilter/nf_nat_proto_udplite.c b/net/ipv4/netfilter/nf_nat_proto_udplite.c
+new file mode 100644
+index 0000000..440a229
+--- /dev/null
++++ b/net/ipv4/netfilter/nf_nat_proto_udplite.c
+@@ -0,0 +1,99 @@
++/* (C) 1999-2001 Paul `Rusty' Russell
++ * (C) 2002-2006 Netfilter Core Team <coreteam at netfilter.org>
++ * (C) 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/ip.h>
++#include <linux/udp.h>
++
++#include <linux/netfilter.h>
++#include <net/netfilter/nf_nat.h>
++#include <net/netfilter/nf_nat_protocol.h>
++
++static u_int16_t udplite_port_rover;
++
++static bool
++udplite_unique_tuple(struct nf_conntrack_tuple *tuple,
++		     const struct nf_nat_range *range,
++		     enum nf_nat_manip_type maniptype,
++		     const struct nf_conn *ct)
++{
++	return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++					 &udplite_port_rover);
++}
++
++static bool
++udplite_manip_pkt(struct sk_buff *skb,
++		  unsigned int iphdroff,
++		  const struct nf_conntrack_tuple *tuple,
++		  enum nf_nat_manip_type maniptype)
++{
++	const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
++	struct udphdr *hdr;
++	unsigned int hdroff = iphdroff + iph->ihl*4;
++	__be32 oldip, newip;
++	__be16 *portptr, newport;
++
++	if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
++		return false;
++
++	iph = (struct iphdr *)(skb->data + iphdroff);
++	hdr = (struct udphdr *)(skb->data + hdroff);
++
++	if (maniptype == IP_NAT_MANIP_SRC) {
++		/* Get rid of src ip and src pt */
++		oldip = iph->saddr;
++		newip = tuple->src.u3.ip;
++		newport = tuple->src.u.udp.port;
++		portptr = &hdr->source;
++	} else {
++		/* Get rid of dst ip and dst pt */
++		oldip = iph->daddr;
++		newip = tuple->dst.u3.ip;
++		newport = tuple->dst.u.udp.port;
++		portptr = &hdr->dest;
++	}
++
++	inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
++	inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport, 0);
++	if (!hdr->check)
++		hdr->check = CSUM_MANGLED_0;
++
++	*portptr = newport;
++	return true;
++}
++
++static const struct nf_nat_protocol nf_nat_protocol_udplite = {
++	.protonum		= IPPROTO_UDPLITE,
++	.me			= THIS_MODULE,
++	.manip_pkt		= udplite_manip_pkt,
++	.in_range		= nf_nat_proto_in_range,
++	.unique_tuple		= udplite_unique_tuple,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++	.range_to_nlattr	= nf_nat_proto_range_to_nlattr,
++	.nlattr_to_range	= nf_nat_proto_nlattr_to_range,
++#endif
++};
++
++static int __init nf_nat_proto_udplite_init(void)
++{
++	return nf_nat_protocol_register(&nf_nat_protocol_udplite);
++}
++
++static void __exit nf_nat_proto_udplite_fini(void)
++{
++	nf_nat_protocol_unregister(&nf_nat_protocol_udplite);
++}
++
++module_init(nf_nat_proto_udplite_init);
++module_exit(nf_nat_proto_udplite_fini);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("UDP-Lite NAT protocol helper");
++MODULE_AUTHOR("Patrick McHardy <kaber at trash.net>");
+diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c
+index a26efeb..14381c6 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_unknown.c
++++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c
+@@ -18,35 +18,34 @@
+ #include <net/netfilter/nf_nat_rule.h>
+ #include <net/netfilter/nf_nat_protocol.h>
+ 
+-static int unknown_in_range(const struct nf_conntrack_tuple *tuple,
+-			    enum nf_nat_manip_type manip_type,
+-			    const union nf_conntrack_man_proto *min,
+-			    const union nf_conntrack_man_proto *max)
++static bool unknown_in_range(const struct nf_conntrack_tuple *tuple,
++			     enum nf_nat_manip_type manip_type,
++			     const union nf_conntrack_man_proto *min,
++			     const union nf_conntrack_man_proto *max)
+ {
+-	return 1;
++	return true;
+ }
+ 
+-static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
+-				const struct nf_nat_range *range,
+-				enum nf_nat_manip_type maniptype,
+-				const struct nf_conn *ct)
++static bool unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
++				 const struct nf_nat_range *range,
++				 enum nf_nat_manip_type maniptype,
++				 const struct nf_conn *ct)
+ {
+ 	/* Sorry: we can't help you; if it's not unique, we can't frob
+ 	   anything. */
+-	return 0;
++	return false;
+ }
+ 
+-static int
++static bool
+ unknown_manip_pkt(struct sk_buff *skb,
+ 		  unsigned int iphdroff,
+ 		  const struct nf_conntrack_tuple *tuple,
+ 		  enum nf_nat_manip_type maniptype)
+ {
+-	return 1;
++	return true;
+ }
+ 
+ const struct nf_nat_protocol nf_nat_unknown_protocol = {
+-	.name			= "unknown",
+ 	/* .me isn't set: getting a ref to this cannot fail. */
+ 	.manip_pkt		= unknown_manip_pkt,
+ 	.in_range		= unknown_in_range,
+diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
+index f8fda57..e8b4d0d 100644
+--- a/net/ipv4/netfilter/nf_nat_rule.c
++++ b/net/ipv4/netfilter/nf_nat_rule.c
+@@ -61,7 +61,7 @@ static struct
+ static struct xt_table __nat_table = {
+ 	.name		= "nat",
+ 	.valid_hooks	= NAT_VALID_HOOKS,
+-	.lock		= RW_LOCK_UNLOCKED,
++	.lock		= __RW_LOCK_UNLOCKED(__nat_table.lock),
+ 	.me		= THIS_MODULE,
+ 	.af		= AF_INET,
+ };
+@@ -143,7 +143,7 @@ static bool ipt_snat_checkentry(const char *tablename,
+ 				void *targinfo,
+ 				unsigned int hook_mask)
+ {
+-	struct nf_nat_multi_range_compat *mr = targinfo;
++	const struct nf_nat_multi_range_compat *mr = targinfo;
+ 
+ 	/* Must be a valid range */
+ 	if (mr->rangesize != 1) {
+@@ -159,7 +159,7 @@ static bool ipt_dnat_checkentry(const char *tablename,
+ 				void *targinfo,
+ 				unsigned int hook_mask)
+ {
+-	struct nf_nat_multi_range_compat *mr = targinfo;
++	const struct nf_nat_multi_range_compat *mr = targinfo;
+ 
+ 	/* Must be a valid range */
+ 	if (mr->rangesize != 1) {
+@@ -188,25 +188,6 @@ alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
+ 	return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
+ }
+ 
+-unsigned int
+-alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
+-{
+-	__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);
+-	__be16 all
+-		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+-		   ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
+-		   : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
+-	struct nf_nat_range range
+-		= { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
+-
+-	pr_debug("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
+-		 ct, NIPQUAD(ip));
+-	return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
+-}
+-
+ int nf_nat_rule_find(struct sk_buff *skb,
+ 		     unsigned int hooknum,
+ 		     const struct net_device *in,
+diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
+index b4c8d49..4334d5c 100644
+--- a/net/ipv4/netfilter/nf_nat_sip.c
++++ b/net/ipv4/netfilter/nf_nat_sip.c
+@@ -2,6 +2,8 @@
+  *
+  * (C) 2005 by Christian Hentschel <chentschel at arnet.com.ar>
+  * based on RR's ip_nat_ftp.c and other modules.
++ * (C) 2007 United Security Providers
++ * (C) 2007, 2008 Patrick McHardy <kaber at trash.net>
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+@@ -26,275 +28,461 @@ MODULE_AUTHOR("Christian Hentschel <chentschel at arnet.com.ar>");
+ MODULE_DESCRIPTION("SIP NAT helper");
+ MODULE_ALIAS("ip_nat_sip");
+ 
+-struct addr_map {
+-	struct {
+-		char		src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+-		char		dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+-		unsigned int	srclen, srciplen;
+-		unsigned int	dstlen, dstiplen;
+-	} addr[IP_CT_DIR_MAX];
+-};
+ 
+-static void addr_map_init(const struct nf_conn *ct, struct addr_map *map)
++static unsigned int mangle_packet(struct sk_buff *skb,
++				  const char **dptr, unsigned int *datalen,
++				  unsigned int matchoff, unsigned int matchlen,
++				  const char *buffer, unsigned int buflen)
+ {
+-	const struct nf_conntrack_tuple *t;
+-	enum ip_conntrack_dir dir;
+-	unsigned int n;
+-
+-	for (dir = 0; dir < IP_CT_DIR_MAX; dir++) {
+-		t = &ct->tuplehash[dir].tuple;
+-
+-		n = sprintf(map->addr[dir].src, "%u.%u.%u.%u",
+-			    NIPQUAD(t->src.u3.ip));
+-		map->addr[dir].srciplen = n;
+-		n += sprintf(map->addr[dir].src + n, ":%u",
+-			     ntohs(t->src.u.udp.port));
+-		map->addr[dir].srclen = n;
+-
+-		n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u",
+-			    NIPQUAD(t->dst.u3.ip));
+-		map->addr[dir].dstiplen = n;
+-		n += sprintf(map->addr[dir].dst + n, ":%u",
+-			     ntohs(t->dst.u.udp.port));
+-		map->addr[dir].dstlen = n;
+-	}
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++	if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, matchoff, matchlen,
++				      buffer, buflen))
++		return 0;
++
++	/* Reload data pointer and adjust datalen value */
++	*dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
++	*datalen += buflen - matchlen;
++	return 1;
+ }
+ 
+-static int map_sip_addr(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
+-			struct nf_conn *ct, const char **dptr, size_t dlen,
+-			enum sip_header_pos pos, struct addr_map *map)
++static int map_addr(struct sk_buff *skb,
++		    const char **dptr, unsigned int *datalen,
++		    unsigned int matchoff, unsigned int matchlen,
++		    union nf_inet_addr *addr, __be16 port)
+ {
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+ 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+-	unsigned int matchlen, matchoff, addrlen;
+-	char *addr;
+-
+-	if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
++	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
++	unsigned int buflen;
++	__be32 newaddr;
++	__be16 newport;
++
++	if (ct->tuplehash[dir].tuple.src.u3.ip == addr->ip &&
++	    ct->tuplehash[dir].tuple.src.u.udp.port == port) {
++		newaddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
++		newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
++	} else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
++		   ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
++		newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
++		newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
++	} else
+ 		return 1;
+ 
+-	if ((matchlen == map->addr[dir].srciplen ||
+-	     matchlen == map->addr[dir].srclen) &&
+-	    memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
+-		addr    = map->addr[!dir].dst;
+-		addrlen = map->addr[!dir].dstlen;
+-	} else if ((matchlen == map->addr[dir].dstiplen ||
+-		    matchlen == map->addr[dir].dstlen) &&
+-		   memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
+-		addr    = map->addr[!dir].src;
+-		addrlen = map->addr[!dir].srclen;
+-	} else
++	if (newaddr == addr->ip && newport == port)
+ 		return 1;
+ 
+-	if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
+-				      matchoff, matchlen, addr, addrlen))
+-		return 0;
+-	*dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
+-	return 1;
++	buflen = sprintf(buffer, "%u.%u.%u.%u:%u",
++			 NIPQUAD(newaddr), ntohs(newport));
+ 
++	return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++			     buffer, buflen);
+ }
+ 
+-static unsigned int ip_nat_sip(struct sk_buff *skb,
+-			       enum ip_conntrack_info ctinfo,
+-			       struct nf_conn *ct,
+-			       const char **dptr)
++static int map_sip_addr(struct sk_buff *skb,
++			const char **dptr, unsigned int *datalen,
++			enum sip_header_types type)
+ {
+-	enum sip_header_pos pos;
+-	struct addr_map map;
+-	int dataoff, datalen;
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	unsigned int matchlen, matchoff;
++	union nf_inet_addr addr;
++	__be16 port;
+ 
+-	dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
+-	datalen = skb->len - dataoff;
+-	if (datalen < sizeof("SIP/2.0") - 1)
+-		return NF_ACCEPT;
++	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
++				    &matchoff, &matchlen, &addr, &port) <= 0)
++		return 1;
++	return map_addr(skb, dptr, datalen, matchoff, matchlen, &addr, port);
++}
+ 
+-	addr_map_init(ct, &map);
++static unsigned int ip_nat_sip(struct sk_buff *skb,
++			       const char **dptr, unsigned int *datalen)
++{
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++	unsigned int dataoff, matchoff, matchlen;
++	union nf_inet_addr addr;
++	__be16 port;
++	int request, in_header;
+ 
+ 	/* Basic rules: requests and responses. */
+-	if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) {
+-		/* 10.2: Constructing the REGISTER Request:
+-		 *
+-		 * The "userinfo" and "@" components of the SIP URI MUST NOT
+-		 * be present.
+-		 */
+-		if (datalen >= sizeof("REGISTER") - 1 &&
+-		    strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0)
+-			pos = POS_REG_REQ_URI;
+-		else
+-			pos = POS_REQ_URI;
+-
+-		if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, pos, &map))
++	if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
++		if (ct_sip_parse_request(ct, *dptr, *datalen,
++					 &matchoff, &matchlen,
++					 &addr, &port) > 0 &&
++		    !map_addr(skb, dptr, datalen, matchoff, matchlen,
++			      &addr, port))
++			return NF_DROP;
++		request = 1;
++	} else
++		request = 0;
++
++	/* Translate topmost Via header and parameters */
++	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
++				    SIP_HDR_VIA, NULL, &matchoff, &matchlen,
++				    &addr, &port) > 0) {
++		unsigned int matchend, poff, plen, buflen, n;
++		char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
++
++		/* We're only interested in headers related to this
++		 * connection */
++		if (request) {
++			if (addr.ip != ct->tuplehash[dir].tuple.src.u3.ip ||
++			    port != ct->tuplehash[dir].tuple.src.u.udp.port)
++				goto next;
++		} else {
++			if (addr.ip != ct->tuplehash[dir].tuple.dst.u3.ip ||
++			    port != ct->tuplehash[dir].tuple.dst.u.udp.port)
++				goto next;
++		}
++
++		if (!map_addr(skb, dptr, datalen, matchoff, matchlen,
++			      &addr, port))
+ 			return NF_DROP;
++
++		matchend = matchoff + matchlen;
++
++		/* The maddr= parameter (RFC 2361) specifies where to send
++		 * the reply. */
++		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
++					       "maddr=", &poff, &plen,
++					       &addr) > 0 &&
++		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
++		    addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
++			__be32 ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
++			buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
++			if (!mangle_packet(skb, dptr, datalen, poff, plen,
++					   buffer, buflen))
++				return NF_DROP;
++		}
++
++		/* The received= parameter (RFC 2361) contains the address
++		 * from which the server received the request. */
++		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
++					       "received=", &poff, &plen,
++					       &addr) > 0 &&
++		    addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
++		    addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
++			__be32 ip = ct->tuplehash[!dir].tuple.src.u3.ip;
++			buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
++			if (!mangle_packet(skb, dptr, datalen, poff, plen,
++					   buffer, buflen))
++				return NF_DROP;
++		}
++
++		/* The rport= parameter (RFC 3581) contains the port number
++		 * from which the server received the request. */
++		if (ct_sip_parse_numerical_param(ct, *dptr, matchend, *datalen,
++						 "rport=", &poff, &plen,
++						 &n) > 0 &&
++		    htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port &&
++		    htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
++			__be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
++			buflen = sprintf(buffer, "%u", ntohs(p));
++			if (!mangle_packet(skb, dptr, datalen, poff, plen,
++					   buffer, buflen))
++				return NF_DROP;
++		}
+ 	}
+ 
+-	if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
+-	    !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
+-	    !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
+-	    !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
++next:
++	/* Translate Contact headers */
++	dataoff = 0;
++	in_header = 0;
++	while (ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen,
++				       SIP_HDR_CONTACT, &in_header,
++				       &matchoff, &matchlen,
++				       &addr, &port) > 0) {
++		if (!map_addr(skb, dptr, datalen, matchoff, matchlen,
++			      &addr, port))
++			return NF_DROP;
++	}
++
++	if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) ||
++	    !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO))
+ 		return NF_DROP;
+ 	return NF_ACCEPT;
+ }
+ 
+-static unsigned int mangle_sip_packet(struct sk_buff *skb,
+-				      enum ip_conntrack_info ctinfo,
+-				      struct nf_conn *ct,
+-				      const char **dptr, size_t dlen,
+-				      char *buffer, int bufflen,
+-				      enum sip_header_pos pos)
++/* Handles expected signalling connections and media streams */
++static void ip_nat_sip_expected(struct nf_conn *ct,
++				struct nf_conntrack_expect *exp)
+ {
+-	unsigned int matchlen, matchoff;
++	struct nf_nat_range range;
+ 
+-	if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
+-		return 0;
++	/* This must be a fresh one. */
++	BUG_ON(ct->status & IPS_NAT_DONE_MASK);
+ 
+-	if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
+-				      matchoff, matchlen, buffer, bufflen))
+-		return 0;
++	/* For DST manip, map port here to where it's expected. */
++	range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
++	range.min = range.max = exp->saved_proto;
++	range.min_ip = range.max_ip = exp->saved_ip;
++	nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST);
+ 
+-	/* We need to reload this. Thanks Patrick. */
+-	*dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
+-	return 1;
++	/* Change src to where master sends to, but only if the connection
++	 * actually came from the same source. */
++	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip ==
++	    ct->master->tuplehash[exp->dir].tuple.src.u3.ip) {
++		range.flags = IP_NAT_RANGE_MAP_IPS;
++		range.min_ip = range.max_ip
++			= ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
++		nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
++	}
+ }
+ 
+-static int mangle_content_len(struct sk_buff *skb,
+-			      enum ip_conntrack_info ctinfo,
+-			      struct nf_conn *ct,
+-			      const char *dptr)
++static unsigned int ip_nat_sip_expect(struct sk_buff *skb,
++				      const char **dptr, unsigned int *datalen,
++				      struct nf_conntrack_expect *exp,
++				      unsigned int matchoff,
++				      unsigned int matchlen)
+ {
+-	unsigned int dataoff, matchoff, matchlen;
+-	char buffer[sizeof("65536")];
+-	int bufflen;
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++	__be32 newip;
++	u_int16_t port;
++	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
++	unsigned buflen;
+ 
+-	dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
++	/* Connection will come from reply */
++	if (ct->tuplehash[dir].tuple.src.u3.ip == ct->tuplehash[!dir].tuple.dst.u3.ip)
++		newip = exp->tuple.dst.u3.ip;
++	else
++		newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+ 
+-	/* Get actual SDP length */
+-	if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff,
+-			    &matchlen, POS_SDP_HEADER) > 0) {
++	/* If the signalling port matches the connection's source port in the
++	 * original direction, try to use the destination port in the opposite
++	 * direction. */
++	if (exp->tuple.dst.u.udp.port ==
++	    ct->tuplehash[dir].tuple.src.u.udp.port)
++		port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
++	else
++		port = ntohs(exp->tuple.dst.u.udp.port);
++
++	exp->saved_ip = exp->tuple.dst.u3.ip;
++	exp->tuple.dst.u3.ip = newip;
++	exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
++	exp->dir = !dir;
++	exp->expectfn = ip_nat_sip_expected;
+ 
+-		/* since ct_sip_get_info() give us a pointer passing 'v='
+-		   we need to add 2 bytes in this count. */
+-		int c_len = skb->len - dataoff - matchoff + 2;
++	for (; port != 0; port++) {
++		exp->tuple.dst.u.udp.port = htons(port);
++		if (nf_ct_expect_related(exp) == 0)
++			break;
++	}
+ 
+-		/* Now, update SDP length */
+-		if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff,
+-				    &matchlen, POS_CONTENT) > 0) {
++	if (port == 0)
++		return NF_DROP;
+ 
+-			bufflen = sprintf(buffer, "%u", c_len);
+-			return nf_nat_mangle_udp_packet(skb, ct, ctinfo,
+-							matchoff, matchlen,
+-							buffer, bufflen);
+-		}
++	if (exp->tuple.dst.u3.ip != exp->saved_ip ||
++	    exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
++		buflen = sprintf(buffer, "%u.%u.%u.%u:%u",
++				 NIPQUAD(newip), port);
++		if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++				   buffer, buflen))
++			goto err;
+ 	}
+-	return 0;
++	return NF_ACCEPT;
++
++err:
++	nf_ct_unexpect_related(exp);
++	return NF_DROP;
+ }
+ 
+-static unsigned int mangle_sdp(struct sk_buff *skb,
+-			       enum ip_conntrack_info ctinfo,
+-			       struct nf_conn *ct,
+-			       __be32 newip, u_int16_t port,
+-			       const char *dptr)
++static int mangle_content_len(struct sk_buff *skb,
++			      const char **dptr, unsigned int *datalen)
+ {
+-	char buffer[sizeof("nnn.nnn.nnn.nnn")];
+-	unsigned int dataoff, bufflen;
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	unsigned int matchoff, matchlen;
++	char buffer[sizeof("65536")];
++	int buflen, c_len;
+ 
+-	dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
++	/* Get actual SDP length */
++	if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
++				  SDP_HDR_VERSION, SDP_HDR_UNSPEC,
++				  &matchoff, &matchlen) <= 0)
++		return 0;
++	c_len = *datalen - matchoff + strlen("v=");
+ 
+-	/* Mangle owner and contact info. */
+-	bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
+-	if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff,
+-			       buffer, bufflen, POS_OWNER_IP4))
++	/* Now, update SDP length */
++	if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CONTENT_LENGTH,
++			      &matchoff, &matchlen) <= 0)
+ 		return 0;
+ 
+-	if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff,
+-			       buffer, bufflen, POS_CONNECTION_IP4))
++	buflen = sprintf(buffer, "%u", c_len);
++	return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++			     buffer, buflen);
++}
++
++static unsigned mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
++				  unsigned int dataoff, unsigned int *datalen,
++				  enum sdp_header_types type,
++				  enum sdp_header_types term,
++				  char *buffer, int buflen)
++{
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	unsigned int matchlen, matchoff;
++
++	if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term,
++				  &matchoff, &matchlen) <= 0)
+ 		return 0;
++	return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++			     buffer, buflen);
++}
+ 
+-	/* Mangle media port. */
+-	bufflen = sprintf(buffer, "%u", port);
+-	if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff,
+-			       buffer, bufflen, POS_MEDIA))
++static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
++				    unsigned int dataoff,
++				    unsigned int *datalen,
++				    enum sdp_header_types type,
++				    enum sdp_header_types term,
++				    const union nf_inet_addr *addr)
++{
++	char buffer[sizeof("nnn.nnn.nnn.nnn")];
++	unsigned int buflen;
++
++	buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip));
++	if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
++			       buffer, buflen))
+ 		return 0;
+ 
+-	return mangle_content_len(skb, ctinfo, ct, dptr);
++	return mangle_content_len(skb, dptr, datalen);
+ }
+ 
+-static void ip_nat_sdp_expect(struct nf_conn *ct,
+-			      struct nf_conntrack_expect *exp)
++static unsigned int ip_nat_sdp_port(struct sk_buff *skb,
++				    const char **dptr,
++				    unsigned int *datalen,
++				    unsigned int matchoff,
++				    unsigned int matchlen,
++				    u_int16_t port)
+ {
+-	struct nf_nat_range range;
++	char buffer[sizeof("nnnnn")];
++	unsigned int buflen;
+ 
+-	/* This must be a fresh one. */
+-	BUG_ON(ct->status & IPS_NAT_DONE_MASK);
++	buflen = sprintf(buffer, "%u", port);
++	if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++			   buffer, buflen))
++		return 0;
+ 
+-	/* Change src to where master sends to */
+-	range.flags = IP_NAT_RANGE_MAP_IPS;
+-	range.min_ip = range.max_ip
+-		= ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
+-	nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
++	return mangle_content_len(skb, dptr, datalen);
++}
+ 
+-	/* For DST manip, map port here to where it's expected. */
+-	range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+-	range.min = range.max = exp->saved_proto;
+-	range.min_ip = range.max_ip = exp->saved_ip;
+-	nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST);
++static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
++				       unsigned int dataoff,
++				       unsigned int *datalen,
++				       const union nf_inet_addr *addr)
++{
++	char buffer[sizeof("nnn.nnn.nnn.nnn")];
++	unsigned int buflen;
++
++	/* Mangle session description owner and contact addresses */
++	buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip));
++	if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
++			       SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
++			       buffer, buflen))
++		return 0;
++
++	if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
++			       SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
++			       buffer, buflen))
++		return 0;
++
++	return mangle_content_len(skb, dptr, datalen);
+ }
+ 
+ /* So, this packet has hit the connection tracking matching code.
+    Mangle it, and change the expectation to match the new version. */
+-static unsigned int ip_nat_sdp(struct sk_buff *skb,
+-			       enum ip_conntrack_info ctinfo,
+-			       struct nf_conntrack_expect *exp,
+-			       const char *dptr)
++static unsigned int ip_nat_sdp_media(struct sk_buff *skb,
++				     const char **dptr,
++				     unsigned int *datalen,
++				     struct nf_conntrack_expect *rtp_exp,
++				     struct nf_conntrack_expect *rtcp_exp,
++				     unsigned int mediaoff,
++				     unsigned int medialen,
++				     union nf_inet_addr *rtp_addr)
+ {
+-	struct nf_conn *ct = exp->master;
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+ 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+-	__be32 newip;
+ 	u_int16_t port;
+ 
+ 	/* Connection will come from reply */
+ 	if (ct->tuplehash[dir].tuple.src.u3.ip ==
+ 	    ct->tuplehash[!dir].tuple.dst.u3.ip)
+-		newip = exp->tuple.dst.u3.ip;
++		rtp_addr->ip = rtp_exp->tuple.dst.u3.ip;
+ 	else
+-		newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+-
+-	exp->saved_ip = exp->tuple.dst.u3.ip;
+-	exp->tuple.dst.u3.ip = newip;
+-	exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
+-	exp->dir = !dir;
+-
+-	/* When you see the packet, we need to NAT it the same as the
+-	   this one. */
+-	exp->expectfn = ip_nat_sdp_expect;
+-
+-	/* Try to get same port: if not, try to change it. */
+-	for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
+-		exp->tuple.dst.u.udp.port = htons(port);
+-		if (nf_ct_expect_related(exp) == 0)
++		rtp_addr->ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
++
++	rtp_exp->saved_ip = rtp_exp->tuple.dst.u3.ip;
++	rtp_exp->tuple.dst.u3.ip = rtp_addr->ip;
++	rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
++	rtp_exp->dir = !dir;
++	rtp_exp->expectfn = ip_nat_sip_expected;
++
++	rtcp_exp->saved_ip = rtcp_exp->tuple.dst.u3.ip;
++	rtcp_exp->tuple.dst.u3.ip = rtp_addr->ip;
++	rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
++	rtcp_exp->dir = !dir;
++	rtcp_exp->expectfn = ip_nat_sip_expected;
++
++	/* 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) {
++		rtp_exp->tuple.dst.u.udp.port = htons(port);
++		if (nf_ct_expect_related(rtp_exp) != 0)
++			continue;
++		rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
++		if (nf_ct_expect_related(rtcp_exp) == 0)
+ 			break;
++		nf_ct_unexpect_related(rtp_exp);
+ 	}
+ 
+ 	if (port == 0)
+-		return NF_DROP;
++		goto err1;
++
++	/* Update media port. */
++	if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
++	    !ip_nat_sdp_port(skb, dptr, datalen, mediaoff, medialen, port))
++		goto err2;
+ 
+-	if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr)) {
+-		nf_ct_unexpect_related(exp);
+-		return NF_DROP;
+-	}
+ 	return NF_ACCEPT;
++
++err2:
++	nf_ct_unexpect_related(rtp_exp);
++	nf_ct_unexpect_related(rtcp_exp);
++err1:
++	return NF_DROP;
+ }
+ 
+ static void __exit nf_nat_sip_fini(void)
+ {
+ 	rcu_assign_pointer(nf_nat_sip_hook, NULL);
+-	rcu_assign_pointer(nf_nat_sdp_hook, NULL);
++	rcu_assign_pointer(nf_nat_sip_expect_hook, NULL);
++	rcu_assign_pointer(nf_nat_sdp_addr_hook, NULL);
++	rcu_assign_pointer(nf_nat_sdp_port_hook, NULL);
++	rcu_assign_pointer(nf_nat_sdp_session_hook, NULL);
++	rcu_assign_pointer(nf_nat_sdp_media_hook, NULL);
+ 	synchronize_rcu();
+ }
+ 
+ static int __init nf_nat_sip_init(void)
+ {
+ 	BUG_ON(nf_nat_sip_hook != NULL);
+-	BUG_ON(nf_nat_sdp_hook != NULL);
++	BUG_ON(nf_nat_sip_expect_hook != NULL);
++	BUG_ON(nf_nat_sdp_addr_hook != NULL);
++	BUG_ON(nf_nat_sdp_port_hook != NULL);
++	BUG_ON(nf_nat_sdp_session_hook != NULL);
++	BUG_ON(nf_nat_sdp_media_hook != NULL);
+ 	rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
+-	rcu_assign_pointer(nf_nat_sdp_hook, ip_nat_sdp);
++	rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect);
++	rcu_assign_pointer(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
++	rcu_assign_pointer(nf_nat_sdp_port_hook, ip_nat_sdp_port);
++	rcu_assign_pointer(nf_nat_sdp_session_hook, ip_nat_sdp_session);
++	rcu_assign_pointer(nf_nat_sdp_media_hook, ip_nat_sdp_media);
+ 	return 0;
+ }
+ 
+diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
+index 540ce6a..5daefad 100644
+--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
++++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
+@@ -50,6 +50,7 @@
+ #include <net/udp.h>
+ 
+ #include <net/netfilter/nf_nat.h>
++#include <net/netfilter/nf_conntrack_expect.h>
+ #include <net/netfilter/nf_conntrack_helper.h>
+ #include <net/netfilter/nf_nat_helper.h>
+ 
+@@ -219,7 +220,7 @@ static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
+ 		if (ch < 0x80)
+ 			*len = ch;
+ 		else {
+-			cnt = (unsigned char) (ch & 0x7F);
++			cnt = ch & 0x7F;
+ 			*len = 0;
+ 
+ 			while (cnt > 0) {
+@@ -617,8 +618,7 @@ struct snmp_cnv
+ 	int syntax;
+ };
+ 
+-static struct snmp_cnv snmp_conv [] =
+-{
++static const struct snmp_cnv snmp_conv[] = {
+ 	{ASN1_UNI, ASN1_NUL, SNMP_NULL},
+ 	{ASN1_UNI, ASN1_INT, SNMP_INTEGER},
+ 	{ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},
+@@ -643,7 +643,7 @@ static unsigned char snmp_tag_cls2syntax(unsigned int tag,
+ 					 unsigned int cls,
+ 					 unsigned short *syntax)
+ {
+-	struct snmp_cnv *cnv;
++	const struct snmp_cnv *cnv;
+ 
+ 	cnv = snmp_conv;
+ 
+@@ -903,7 +903,7 @@ static inline void mangle_address(unsigned char *begin,
+ 		u_int32_t old;
+ 
+ 		if (debug)
+-			memcpy(&old, (unsigned char *)addr, sizeof(old));
++			memcpy(&old, addr, sizeof(old));
+ 
+ 		*addr = map->to;
+ 
+@@ -998,7 +998,7 @@ err_id_free:
+  *
+  *****************************************************************************/
+ 
+-static void hex_dump(unsigned char *buf, size_t len)
++static void hex_dump(const unsigned char *buf, size_t len)
+ {
+ 	size_t i;
+ 
+@@ -1079,7 +1079,7 @@ static int snmp_parse_mangle(unsigned char *msg,
+ 	if (cls != ASN1_CTX || con != ASN1_CON)
+ 		return 0;
+ 	if (debug > 1) {
+-		unsigned char *pdus[] = {
++		static const unsigned char *const pdus[] = {
+ 			[SNMP_PDU_GET] = "get",
+ 			[SNMP_PDU_NEXT] = "get-next",
+ 			[SNMP_PDU_RESPONSE] = "response",
+@@ -1231,8 +1231,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ {
+ 	int dir = CTINFO2DIR(ctinfo);
+ 	unsigned int ret;
+-	struct iphdr *iph = ip_hdr(skb);
+-	struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
++	const struct iphdr *iph = ip_hdr(skb);
++	const struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
+ 
+ 	/* SNMP replies and originating SNMP traps get mangled */
+ 	if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
+@@ -1267,11 +1267,15 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ 	return ret;
+ }
+ 
++static const struct nf_conntrack_expect_policy snmp_exp_policy = {
++	.max_expected	= 0,
++	.timeout	= 180,
++};
++
+ static struct nf_conntrack_helper snmp_helper __read_mostly = {
+-	.max_expected		= 0,
+-	.timeout		= 180,
+ 	.me			= THIS_MODULE,
+ 	.help			= help,
++	.expect_policy		= &snmp_exp_policy,
+ 	.name			= "snmp",
+ 	.tuple.src.l3num	= AF_INET,
+ 	.tuple.src.u.udp.port	= __constant_htons(SNMP_PORT),
+@@ -1279,10 +1283,9 @@ static struct nf_conntrack_helper snmp_helper __read_mostly = {
+ };
+ 
+ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
+-	.max_expected		= 0,
+-	.timeout		= 180,
+ 	.me			= THIS_MODULE,
+ 	.help			= help,
++	.expect_policy		= &snmp_exp_policy,
+ 	.name			= "snmp_trap",
+ 	.tuple.src.l3num	= AF_INET,
+ 	.tuple.src.u.udp.port	= __constant_htons(SNMP_TRAP_PORT),
+diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
+index 99b2c78..b7dd695 100644
+--- a/net/ipv4/netfilter/nf_nat_standalone.c
++++ b/net/ipv4/netfilter/nf_nat_standalone.c
+@@ -30,8 +30,8 @@
+ #ifdef CONFIG_XFRM
+ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
+ {
+-	struct nf_conn *ct;
+-	struct nf_conntrack_tuple *t;
++	const struct nf_conn *ct;
++	const struct nf_conntrack_tuple *t;
+ 	enum ip_conntrack_info ctinfo;
+ 	enum ip_conntrack_dir dir;
+ 	unsigned long statusbit;
+@@ -50,7 +50,10 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
+ 	if (ct->status & statusbit) {
+ 		fl->fl4_dst = t->dst.u3.ip;
+ 		if (t->dst.protonum == IPPROTO_TCP ||
+-		    t->dst.protonum == IPPROTO_UDP)
++		    t->dst.protonum == IPPROTO_UDP ||
++		    t->dst.protonum == IPPROTO_UDPLITE ||
++		    t->dst.protonum == IPPROTO_DCCP ||
++		    t->dst.protonum == IPPROTO_SCTP)
+ 			fl->fl_ip_dport = t->dst.u.tcp.port;
+ 	}
+ 
+@@ -59,7 +62,10 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
+ 	if (ct->status & statusbit) {
+ 		fl->fl4_src = t->src.u3.ip;
+ 		if (t->dst.protonum == IPPROTO_TCP ||
+-		    t->dst.protonum == IPPROTO_UDP)
++		    t->dst.protonum == IPPROTO_UDP ||
++		    t->dst.protonum == IPPROTO_UDPLITE ||
++		    t->dst.protonum == IPPROTO_DCCP ||
++		    t->dst.protonum == IPPROTO_SCTP)
+ 			fl->fl_ip_sport = t->src.u.tcp.port;
+ 	}
+ }
+@@ -87,21 +93,8 @@ nf_nat_fn(unsigned int hooknum,
+ 	   have dropped it.  Hence it's the user's responsibilty to
+ 	   packet filter it out, or implement conntrack/NAT for that
+ 	   protocol. 8) --RR */
+-	if (!ct) {
+-		/* Exception: ICMP redirect to new connection (not in
+-		   hash table yet).  We must not let this through, in
+-		   case we're doing NAT to the same network. */
+-		if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
+-			struct icmphdr _hdr, *hp;
+-
+-			hp = skb_header_pointer(skb, ip_hdrlen(skb),
+-						sizeof(_hdr), &_hdr);
+-			if (hp != NULL &&
+-			    hp->type == ICMP_REDIRECT)
+-				return NF_DROP;
+-		}
++	if (!ct)
+ 		return NF_ACCEPT;
+-	}
+ 
+ 	/* Don't try to NAT if this packet is not conntracked */
+ 	if (ct == &nf_conntrack_untracked)
+@@ -109,6 +102,9 @@ nf_nat_fn(unsigned int hooknum,
+ 
+ 	nat = nfct_nat(ct);
+ 	if (!nat) {
++		/* NAT module was loaded late. */
++		if (nf_ct_is_confirmed(ct))
++			return NF_ACCEPT;
+ 		nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
+ 		if (nat == NULL) {
+ 			pr_debug("failed to add NAT extension\n");
+@@ -134,10 +130,7 @@ nf_nat_fn(unsigned int hooknum,
+ 		if (!nf_nat_initialized(ct, maniptype)) {
+ 			unsigned int ret;
+ 
+-			if (unlikely(nf_ct_is_confirmed(ct)))
+-				/* NAT module was loaded late */
+-				ret = alloc_null_binding_confirmed(ct, hooknum);
+-			else if (hooknum == NF_INET_LOCAL_IN)
++			if (hooknum == NF_INET_LOCAL_IN)
+ 				/* LOCAL_IN hook doesn't have a chain!  */
+ 				ret = alloc_null_binding(ct, hooknum);
+ 			else
+@@ -189,7 +182,7 @@ nf_nat_out(unsigned int hooknum,
+ 	   int (*okfn)(struct sk_buff *))
+ {
+ #ifdef CONFIG_XFRM
+-	struct nf_conn *ct;
++	const struct nf_conn *ct;
+ 	enum ip_conntrack_info ctinfo;
+ #endif
+ 	unsigned int ret;
+@@ -223,7 +216,7 @@ nf_nat_local_fn(unsigned int hooknum,
+ 		const struct net_device *out,
+ 		int (*okfn)(struct sk_buff *))
+ {
+-	struct nf_conn *ct;
++	const struct nf_conn *ct;
+ 	enum ip_conntrack_info ctinfo;
+ 	unsigned int ret;
+ 
+@@ -252,25 +245,6 @@ nf_nat_local_fn(unsigned int hooknum,
+ 	return ret;
+ }
+ 
+-static unsigned int
+-nf_nat_adjust(unsigned int hooknum,
+-	      struct sk_buff *skb,
+-	      const struct net_device *in,
+-	      const struct net_device *out,
+-	      int (*okfn)(struct sk_buff *))
+-{
+-	struct nf_conn *ct;
+-	enum ip_conntrack_info ctinfo;
+-
+-	ct = nf_ct_get(skb, &ctinfo);
+-	if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
+-		pr_debug("nf_nat_standalone: adjusting sequence number\n");
+-		if (!nf_nat_seq_adjust(skb, ct, ctinfo))
+-			return NF_DROP;
+-	}
+-	return NF_ACCEPT;
+-}
+-
+ /* We must be after connection tracking and before packet filtering. */
+ 
+ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
+@@ -290,14 +264,6 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
+ 		.hooknum	= NF_INET_POST_ROUTING,
+ 		.priority	= NF_IP_PRI_NAT_SRC,
+ 	},
+-	/* After conntrack, adjust sequence number */
+-	{
+-		.hook		= nf_nat_adjust,
+-		.owner		= THIS_MODULE,
+-		.pf		= PF_INET,
+-		.hooknum	= NF_INET_POST_ROUTING,
+-		.priority	= NF_IP_PRI_NAT_SEQ_ADJUST,
+-	},
+ 	/* Before packet filtering, change destination */
+ 	{
+ 		.hook		= nf_nat_local_fn,
+@@ -314,14 +280,6 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
+ 		.hooknum	= NF_INET_LOCAL_IN,
+ 		.priority	= NF_IP_PRI_NAT_SRC,
+ 	},
+-	/* After conntrack, adjust sequence number */
+-	{
+-		.hook		= nf_nat_adjust,
+-		.owner		= THIS_MODULE,
+-		.pf		= PF_INET,
+-		.hooknum	= NF_INET_LOCAL_IN,
+-		.priority	= NF_IP_PRI_NAT_SEQ_ADJUST,
+-	},
+ };
+ 
+ static int __init nf_nat_standalone_init(void)
+diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
+index d63474c..552169b 100644
+--- a/net/ipv4/proc.c
++++ b/net/ipv4/proc.c
+@@ -51,24 +51,54 @@
+  */
+ static int sockstat_seq_show(struct seq_file *seq, void *v)
+ {
++	struct net *net = seq->private;
++
+ 	socket_seq_show(seq);
+ 	seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n",
+-		   sock_prot_inuse_get(&tcp_prot),
++		   sock_prot_inuse_get(net, &tcp_prot),
+ 		   atomic_read(&tcp_orphan_count),
+ 		   tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated),
+ 		   atomic_read(&tcp_memory_allocated));
+-	seq_printf(seq, "UDP: inuse %d mem %d\n", sock_prot_inuse_get(&udp_prot),
++	seq_printf(seq, "UDP: inuse %d mem %d\n",
++		   sock_prot_inuse_get(net, &udp_prot),
+ 		   atomic_read(&udp_memory_allocated));
+-	seq_printf(seq, "UDPLITE: inuse %d\n", sock_prot_inuse_get(&udplite_prot));
+-	seq_printf(seq, "RAW: inuse %d\n", sock_prot_inuse_get(&raw_prot));
++	seq_printf(seq, "UDPLITE: inuse %d\n",
++		   sock_prot_inuse_get(net, &udplite_prot));
++	seq_printf(seq, "RAW: inuse %d\n",
++		   sock_prot_inuse_get(net, &raw_prot));
+ 	seq_printf(seq,  "FRAG: inuse %d memory %d\n",
+-			ip_frag_nqueues(&init_net), ip_frag_mem(&init_net));
++			ip_frag_nqueues(net), ip_frag_mem(net));
+ 	return 0;
+ }
+ 
+ static int sockstat_seq_open(struct inode *inode, struct file *file)
+ {
+-	return single_open(file, sockstat_seq_show, NULL);
++	int err;
++	struct net *net;
++
++	err = -ENXIO;
++	net = get_proc_net(inode);
++	if (net == NULL)
++		goto err_net;
++
++	err = single_open(file, sockstat_seq_show, net);
++	if (err < 0)
++		goto err_open;
++
++	return 0;
++
++err_open:
++	put_net(net);
++err_net:
++	return err;
++}
++
++static int sockstat_seq_release(struct inode *inode, struct file *file)
++{
++	struct net *net = ((struct seq_file *)file->private_data)->private;
++
++	put_net(net);
++	return single_release(inode, file);
+ }
+ 
+ static const struct file_operations sockstat_seq_fops = {
+@@ -76,7 +106,7 @@ static const struct file_operations sockstat_seq_fops = {
+ 	.open	 = sockstat_seq_open,
+ 	.read	 = seq_read,
+ 	.llseek	 = seq_lseek,
+-	.release = single_release,
++	.release = sockstat_seq_release,
+ };
+ 
+ /* snmp items */
+@@ -423,25 +453,42 @@ static const struct file_operations netstat_seq_fops = {
+ 	.release = single_release,
+ };
+ 
++static __net_init int ip_proc_init_net(struct net *net)
++{
++	if (!proc_net_fops_create(net, "sockstat", S_IRUGO, &sockstat_seq_fops))
++		return -ENOMEM;
++	return 0;
++}
++
++static __net_exit void ip_proc_exit_net(struct net *net)
++{
++	proc_net_remove(net, "sockstat");
++}
++
++static __net_initdata struct pernet_operations ip_proc_ops = {
++	.init = ip_proc_init_net,
++	.exit = ip_proc_exit_net,
++};
++
+ int __init ip_misc_proc_init(void)
+ {
+ 	int rc = 0;
+ 
++	if (register_pernet_subsys(&ip_proc_ops))
++		goto out_pernet;
++
+ 	if (!proc_net_fops_create(&init_net, "netstat", S_IRUGO, &netstat_seq_fops))
+ 		goto out_netstat;
+ 
+ 	if (!proc_net_fops_create(&init_net, "snmp", S_IRUGO, &snmp_seq_fops))
+ 		goto out_snmp;
+-
+-	if (!proc_net_fops_create(&init_net, "sockstat", S_IRUGO, &sockstat_seq_fops))
+-		goto out_sockstat;
+ out:
+ 	return rc;
+-out_sockstat:
+-	proc_net_remove(&init_net, "snmp");
+ out_snmp:
+ 	proc_net_remove(&init_net, "netstat");
+ out_netstat:
++	unregister_pernet_subsys(&ip_proc_ops);
++out_pernet:
+ 	rc = -ENOMEM;
+ 	goto out;
+ }
+diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
+index a3002fe..11d7f75 100644
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -81,41 +81,34 @@
+ #include <linux/netfilter_ipv4.h>
+ 
+ static struct raw_hashinfo raw_v4_hashinfo = {
+-	.lock = __RW_LOCK_UNLOCKED(),
++	.lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
+ };
+ 
+-void raw_hash_sk(struct sock *sk, struct raw_hashinfo *h)
++void raw_hash_sk(struct sock *sk)
+ {
++	struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
+ 	struct hlist_head *head;
+ 
+ 	head = &h->ht[inet_sk(sk)->num & (RAW_HTABLE_SIZE - 1)];
+ 
+ 	write_lock_bh(&h->lock);
+ 	sk_add_node(sk, head);
+-	sock_prot_inuse_add(sk->sk_prot, 1);
++	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ 	write_unlock_bh(&h->lock);
+ }
+ EXPORT_SYMBOL_GPL(raw_hash_sk);
+ 
+-void raw_unhash_sk(struct sock *sk, struct raw_hashinfo *h)
++void raw_unhash_sk(struct sock *sk)
+ {
++	struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
++
+ 	write_lock_bh(&h->lock);
+ 	if (sk_del_node_init(sk))
+-		sock_prot_inuse_add(sk->sk_prot, -1);
++		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ 	write_unlock_bh(&h->lock);
+ }
+ EXPORT_SYMBOL_GPL(raw_unhash_sk);
+ 
+-static void raw_v4_hash(struct sock *sk)
+-{
+-	raw_hash_sk(sk, &raw_v4_hashinfo);
+-}
+-
+-static void raw_v4_unhash(struct sock *sk)
+-{
+-	raw_unhash_sk(sk, &raw_v4_hashinfo);
+-}
+-
+ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
+ 		unsigned short num, __be32 raddr, __be32 laddr, int dif)
+ {
+@@ -124,7 +117,7 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
+ 	sk_for_each_from(sk, node) {
+ 		struct inet_sock *inet = inet_sk(sk);
+ 
+-		if (sk->sk_net == net && inet->num == num 		&&
++		if (net_eq(sock_net(sk), net) && inet->num == num	&&
+ 		    !(inet->daddr && inet->daddr != raddr) 		&&
+ 		    !(inet->rcv_saddr && inet->rcv_saddr != laddr)	&&
+ 		    !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
+@@ -175,7 +168,7 @@ static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
+ 	if (hlist_empty(head))
+ 		goto out;
+ 
+-	net = skb->dev->nd_net;
++	net = dev_net(skb->dev);
+ 	sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
+ 			     iph->saddr, iph->daddr,
+ 			     skb->dev->ifindex);
+@@ -283,7 +276,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
+ 	raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
+ 	if (raw_sk != NULL) {
+ 		iph = (struct iphdr *)skb->data;
+-		net = skb->dev->nd_net;
++		net = dev_net(skb->dev);
+ 
+ 		while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol,
+ 						iph->daddr, iph->saddr,
+@@ -506,7 +499,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 	ipc.oif = sk->sk_bound_dev_if;
+ 
+ 	if (msg->msg_controllen) {
+-		err = ip_cmsg_send(msg, &ipc);
++		err = ip_cmsg_send(sock_net(sk), msg, &ipc);
+ 		if (err)
+ 			goto out;
+ 		if (ipc.opt)
+@@ -560,7 +553,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 		}
+ 
+ 		security_sk_classify_flow(sk, &fl);
+-		err = ip_route_output_flow(&init_net, &rt, &fl, sk, 1);
++		err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 1);
+ 	}
+ 	if (err)
+ 		goto done;
+@@ -627,7 +620,7 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+ 
+ 	if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
+ 		goto out;
+-	chk_addr_ret = inet_addr_type(sk->sk_net, addr->sin_addr.s_addr);
++	chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+ 	ret = -EADDRNOTAVAIL;
+ 	if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
+ 	    chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
+@@ -825,8 +818,6 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ 	}
+ }
+ 
+-DEFINE_PROTO_INUSE(raw)
+-
+ struct proto raw_prot = {
+ 	.name		   = "RAW",
+ 	.owner		   = THIS_MODULE,
+@@ -841,14 +832,14 @@ struct proto raw_prot = {
+ 	.recvmsg	   = raw_recvmsg,
+ 	.bind		   = raw_bind,
+ 	.backlog_rcv	   = raw_rcv_skb,
+-	.hash		   = raw_v4_hash,
+-	.unhash		   = raw_v4_unhash,
++	.hash		   = raw_hash_sk,
++	.unhash		   = raw_unhash_sk,
+ 	.obj_size	   = sizeof(struct raw_sock),
++	.h.raw_hash	   = &raw_v4_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_raw_setsockopt,
+ 	.compat_getsockopt = compat_raw_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(raw)
+ };
+ 
+ #ifdef CONFIG_PROC_FS
+@@ -862,7 +853,7 @@ static struct sock *raw_get_first(struct seq_file *seq)
+ 		struct hlist_node *node;
+ 
+ 		sk_for_each(sk, node, &state->h->ht[state->bucket])
+-			if (sk->sk_net == state->p.net)
++			if (sock_net(sk) == seq_file_net(seq))
+ 				goto found;
+ 	}
+ 	sk = NULL;
+@@ -878,7 +869,7 @@ static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk)
+ 		sk = sk_next(sk);
+ try_again:
+ 		;
+-	} while (sk && sk->sk_net != state->p.net);
++	} while (sk && sock_net(sk) != seq_file_net(seq));
+ 
+ 	if (!sk && ++state->bucket < RAW_HTABLE_SIZE) {
+ 		sk = sk_head(&state->h->ht[state->bucket]);
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index 7b5e8e1..ce25a13 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -118,21 +118,19 @@
+ #define RT_GC_TIMEOUT (300*HZ)
+ 
+ static int ip_rt_max_size;
+-static int ip_rt_gc_timeout		= RT_GC_TIMEOUT;
+-static int ip_rt_gc_interval		= 60 * HZ;
+-static int ip_rt_gc_min_interval	= HZ / 2;
+-static int ip_rt_redirect_number	= 9;
+-static int ip_rt_redirect_load		= HZ / 50;
+-static int ip_rt_redirect_silence	= ((HZ / 50) << (9 + 1));
+-static int ip_rt_error_cost		= HZ;
+-static int ip_rt_error_burst		= 5 * HZ;
+-static int ip_rt_gc_elasticity		= 8;
+-static int ip_rt_mtu_expires		= 10 * 60 * HZ;
+-static int ip_rt_min_pmtu		= 512 + 20 + 20;
+-static int ip_rt_min_advmss		= 256;
+-static int ip_rt_secret_interval	= 10 * 60 * HZ;
+-
+-#define RTprint(a...)	printk(KERN_DEBUG a)
++static int ip_rt_gc_timeout __read_mostly	= RT_GC_TIMEOUT;
++static int ip_rt_gc_interval __read_mostly	= 60 * HZ;
++static int ip_rt_gc_min_interval __read_mostly	= HZ / 2;
++static int ip_rt_redirect_number __read_mostly	= 9;
++static int ip_rt_redirect_load __read_mostly	= HZ / 50;
++static int ip_rt_redirect_silence __read_mostly	= ((HZ / 50) << (9 + 1));
++static int ip_rt_error_cost __read_mostly	= HZ;
++static int ip_rt_error_burst __read_mostly	= 5 * HZ;
++static int ip_rt_gc_elasticity __read_mostly	= 8;
++static int ip_rt_mtu_expires __read_mostly	= 10 * 60 * HZ;
++static int ip_rt_min_pmtu __read_mostly		= 512 + 20 + 20;
++static int ip_rt_min_advmss __read_mostly	= 256;
++static int ip_rt_secret_interval __read_mostly	= 10 * 60 * HZ;
+ 
+ static void rt_worker_func(struct work_struct *work);
+ static DECLARE_DELAYED_WORK(expires_work, rt_worker_func);
+@@ -252,40 +250,41 @@ static inline void rt_hash_lock_init(void)
+ }
+ #endif
+ 
+-static struct rt_hash_bucket 	*rt_hash_table;
+-static unsigned			rt_hash_mask;
+-static unsigned int		rt_hash_log;
+-static atomic_t			rt_genid;
++static struct rt_hash_bucket 	*rt_hash_table __read_mostly;
++static unsigned			rt_hash_mask __read_mostly;
++static unsigned int		rt_hash_log  __read_mostly;
++static atomic_t			rt_genid __read_mostly;
+ 
+ static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
+ #define RT_CACHE_STAT_INC(field) \
+ 	(__raw_get_cpu_var(rt_cache_stat).field++)
+ 
+-static unsigned int rt_hash_code(u32 daddr, u32 saddr)
++static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx)
+ {
+-	return jhash_2words(daddr, saddr, atomic_read(&rt_genid))
++	return jhash_3words((__force u32)(__be32)(daddr),
++			    (__force u32)(__be32)(saddr),
++			    idx, atomic_read(&rt_genid))
+ 		& rt_hash_mask;
+ }
+ 
+-#define rt_hash(daddr, saddr, idx) \
+-	rt_hash_code((__force u32)(__be32)(daddr),\
+-		     (__force u32)(__be32)(saddr) ^ ((idx) << 5))
+-
+ #ifdef CONFIG_PROC_FS
+ struct rt_cache_iter_state {
++	struct seq_net_private p;
+ 	int bucket;
+ 	int genid;
+ };
+ 
+-static struct rtable *rt_cache_get_first(struct rt_cache_iter_state *st)
++static struct rtable *rt_cache_get_first(struct seq_file *seq)
+ {
++	struct rt_cache_iter_state *st = seq->private;
+ 	struct rtable *r = NULL;
+ 
+ 	for (st->bucket = rt_hash_mask; st->bucket >= 0; --st->bucket) {
+ 		rcu_read_lock_bh();
+ 		r = rcu_dereference(rt_hash_table[st->bucket].chain);
+ 		while (r) {
+-			if (r->rt_genid == st->genid)
++			if (dev_net(r->u.dst.dev) == seq_file_net(seq) &&
++			    r->rt_genid == st->genid)
+ 				return r;
+ 			r = rcu_dereference(r->u.dst.rt_next);
+ 		}
+@@ -294,8 +293,10 @@ static struct rtable *rt_cache_get_first(struct rt_cache_iter_state *st)
+ 	return r;
+ }
+ 
+-static struct rtable *rt_cache_get_next(struct rt_cache_iter_state *st, struct rtable *r)
++static struct rtable *__rt_cache_get_next(struct seq_file *seq,
++					  struct rtable *r)
+ {
++	struct rt_cache_iter_state *st = seq->private;
+ 	r = r->u.dst.rt_next;
+ 	while (!r) {
+ 		rcu_read_unlock_bh();
+@@ -307,25 +308,34 @@ static struct rtable *rt_cache_get_next(struct rt_cache_iter_state *st, struct r
+ 	return rcu_dereference(r);
+ }
+ 
+-static struct rtable *rt_cache_get_idx(struct rt_cache_iter_state *st, loff_t pos)
++static struct rtable *rt_cache_get_next(struct seq_file *seq,
++					struct rtable *r)
++{
++	struct rt_cache_iter_state *st = seq->private;
++	while ((r = __rt_cache_get_next(seq, r)) != NULL) {
++		if (dev_net(r->u.dst.dev) != seq_file_net(seq))
++			continue;
++		if (r->rt_genid == st->genid)
++			break;
++	}
++	return r;
++}
++
++static struct rtable *rt_cache_get_idx(struct seq_file *seq, loff_t pos)
+ {
+-	struct rtable *r = rt_cache_get_first(st);
++	struct rtable *r = rt_cache_get_first(seq);
+ 
+ 	if (r)
+-		while (pos && (r = rt_cache_get_next(st, r))) {
+-			if (r->rt_genid != st->genid)
+-				continue;
++		while (pos && (r = rt_cache_get_next(seq, r)))
+ 			--pos;
+-		}
+ 	return pos ? NULL : r;
+ }
+ 
+ static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+ 	struct rt_cache_iter_state *st = seq->private;
+-
+ 	if (*pos)
+-		return rt_cache_get_idx(st, *pos - 1);
++		return rt_cache_get_idx(seq, *pos - 1);
+ 	st->genid = atomic_read(&rt_genid);
+ 	return SEQ_START_TOKEN;
+ }
+@@ -333,12 +343,11 @@ static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
+ static void *rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ 	struct rtable *r;
+-	struct rt_cache_iter_state *st = seq->private;
+ 
+ 	if (v == SEQ_START_TOKEN)
+-		r = rt_cache_get_first(st);
++		r = rt_cache_get_first(seq);
+ 	else
+-		r = rt_cache_get_next(st, v);
++		r = rt_cache_get_next(seq, v);
+ 	++*pos;
+ 	return r;
+ }
+@@ -358,10 +367,10 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
+ 			   "HHUptod\tSpecDst");
+ 	else {
+ 		struct rtable *r = v;
+-		char temp[256];
++		int len;
+ 
+-		sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
+-			      "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
++		seq_printf(seq, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
++			      "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",
+ 			r->u.dst.dev ? r->u.dst.dev->name : "*",
+ 			(unsigned long)r->rt_dst, (unsigned long)r->rt_gateway,
+ 			r->rt_flags, atomic_read(&r->u.dst.__refcnt),
+@@ -375,8 +384,9 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
+ 			r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1,
+ 			r->u.dst.hh ? (r->u.dst.hh->hh_output ==
+ 				       dev_queue_xmit) : 0,
+-			r->rt_spec_dst);
+-		seq_printf(seq, "%-127s\n", temp);
++			r->rt_spec_dst, &len);
++
++		seq_printf(seq, "%*s\n", 127 - len, "");
+ 	}
+ 	return 0;
+ }
+@@ -390,7 +400,7 @@ static const struct seq_operations rt_cache_seq_ops = {
+ 
+ static int rt_cache_seq_open(struct inode *inode, struct file *file)
+ {
+-	return seq_open_private(file, &rt_cache_seq_ops,
++	return seq_open_net(inode, file, &rt_cache_seq_ops,
+ 			sizeof(struct rt_cache_iter_state));
+ }
+ 
+@@ -399,7 +409,7 @@ static const struct file_operations rt_cache_seq_fops = {
+ 	.open	 = rt_cache_seq_open,
+ 	.read	 = seq_read,
+ 	.llseek	 = seq_lseek,
+-	.release = seq_release_private,
++	.release = seq_release_net,
+ };
+ 
+ 
+@@ -533,7 +543,7 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
+ }
+ #endif
+ 
+-static __init int ip_rt_proc_init(struct net *net)
++static int __net_init ip_rt_do_proc_init(struct net *net)
+ {
+ 	struct proc_dir_entry *pde;
+ 
+@@ -564,25 +574,43 @@ err2:
+ err1:
+ 	return -ENOMEM;
+ }
++
++static void __net_exit ip_rt_do_proc_exit(struct net *net)
++{
++	remove_proc_entry("rt_cache", net->proc_net_stat);
++	remove_proc_entry("rt_cache", net->proc_net);
++	remove_proc_entry("rt_acct", net->proc_net);
++}
++
++static struct pernet_operations ip_rt_proc_ops __net_initdata =  {
++	.init = ip_rt_do_proc_init,
++	.exit = ip_rt_do_proc_exit,
++};
++
++static int __init ip_rt_proc_init(void)
++{
++	return register_pernet_subsys(&ip_rt_proc_ops);
++}
++
+ #else
+-static inline int ip_rt_proc_init(struct net *net)
++static inline int ip_rt_proc_init(void)
+ {
+ 	return 0;
+ }
+ #endif /* CONFIG_PROC_FS */
+ 
+-static __inline__ void rt_free(struct rtable *rt)
++static inline void rt_free(struct rtable *rt)
+ {
+ 	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
+ }
+ 
+-static __inline__ void rt_drop(struct rtable *rt)
++static inline void rt_drop(struct rtable *rt)
+ {
+ 	ip_rt_put(rt);
+ 	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
+ }
+ 
+-static __inline__ int rt_fast_clean(struct rtable *rth)
++static inline int rt_fast_clean(struct rtable *rth)
+ {
+ 	/* Kill broadcast/multicast entries very aggresively, if they
+ 	   collide in hash table with more useful entries */
+@@ -590,7 +618,7 @@ static __inline__ int rt_fast_clean(struct rtable *rth)
+ 		rth->fl.iif && rth->u.dst.rt_next;
+ }
+ 
+-static __inline__ int rt_valuable(struct rtable *rth)
++static inline int rt_valuable(struct rtable *rth)
+ {
+ 	return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) ||
+ 		rth->u.dst.expires;
+@@ -652,7 +680,7 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
+ 
+ static inline int compare_netns(struct rtable *rt1, struct rtable *rt2)
+ {
+-	return rt1->u.dst.dev->nd_net == rt2->u.dst.dev->nd_net;
++	return dev_net(rt1->u.dst.dev) == dev_net(rt2->u.dst.dev);
+ }
+ 
+ /*
+@@ -1032,10 +1060,10 @@ restart:
+ #if RT_CACHE_DEBUG >= 2
+ 	if (rt->u.dst.rt_next) {
+ 		struct rtable *trt;
+-		printk(KERN_DEBUG "rt_cache @%02x: %u.%u.%u.%u", hash,
++		printk(KERN_DEBUG "rt_cache @%02x: " NIPQUAD_FMT, hash,
+ 		       NIPQUAD(rt->rt_dst));
+ 		for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next)
+-			printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst));
++			printk(" . " NIPQUAD_FMT, NIPQUAD(trt->rt_dst));
+ 		printk("\n");
+ 	}
+ #endif
+@@ -1131,10 +1159,12 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+ 	__be32  skeys[2] = { saddr, 0 };
+ 	int  ikeys[2] = { dev->ifindex, 0 };
+ 	struct netevent_redirect netevent;
++	struct net *net;
+ 
+ 	if (!in_dev)
+ 		return;
+ 
++	net = dev_net(dev);
+ 	if (new_gw == old_gw || !IN_DEV_RX_REDIRECTS(in_dev)
+ 	    || ipv4_is_multicast(new_gw) || ipv4_is_lbcast(new_gw)
+ 	    || ipv4_is_zeronet(new_gw))
+@@ -1146,7 +1176,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+ 		if (IN_DEV_SEC_REDIRECTS(in_dev) && ip_fib_check_default(new_gw, dev))
+ 			goto reject_redirect;
+ 	} else {
+-		if (inet_addr_type(&init_net, new_gw) != RTN_UNICAST)
++		if (inet_addr_type(net, new_gw) != RTN_UNICAST)
+ 			goto reject_redirect;
+ 	}
+ 
+@@ -1164,7 +1194,8 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+ 				    rth->fl.fl4_src != skeys[i] ||
+ 				    rth->fl.oif != ikeys[k] ||
+ 				    rth->fl.iif != 0 ||
+-				    rth->rt_genid != atomic_read(&rt_genid)) {
++				    rth->rt_genid != atomic_read(&rt_genid) ||
++				    !net_eq(dev_net(rth->u.dst.dev), net)) {
+ 					rthp = &rth->u.dst.rt_next;
+ 					continue;
+ 				}
+@@ -1245,9 +1276,9 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+ reject_redirect:
+ #ifdef CONFIG_IP_ROUTE_VERBOSE
+ 	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
+-		printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about "
+-			"%u.%u.%u.%u ignored.\n"
+-			"  Advised path = %u.%u.%u.%u -> %u.%u.%u.%u\n",
++		printk(KERN_INFO "Redirect from " NIPQUAD_FMT " on %s about "
++			NIPQUAD_FMT " ignored.\n"
++			"  Advised path = " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
+ 		       NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw),
+ 		       NIPQUAD(saddr), NIPQUAD(daddr));
+ #endif
+@@ -1256,7 +1287,7 @@ reject_redirect:
+ 
+ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
+ {
+-	struct rtable *rt = (struct rtable*)dst;
++	struct rtable *rt = (struct rtable *)dst;
+ 	struct dst_entry *ret = dst;
+ 
+ 	if (rt) {
+@@ -1269,7 +1300,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
+ 						rt->fl.oif);
+ #if RT_CACHE_DEBUG >= 1
+ 			printk(KERN_DEBUG "ipv4_negative_advice: redirect to "
+-					  "%u.%u.%u.%u/%02x dropped\n",
++					  NIPQUAD_FMT "/%02x dropped\n",
+ 				NIPQUAD(rt->rt_dst), rt->fl.fl4_tos);
+ #endif
+ 			rt_del(hash, rt);
+@@ -1297,7 +1328,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
+ 
+ void ip_rt_send_redirect(struct sk_buff *skb)
+ {
+-	struct rtable *rt = (struct rtable*)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	struct in_device *in_dev = in_dev_get(rt->u.dst.dev);
+ 
+ 	if (!in_dev)
+@@ -1334,8 +1365,8 @@ void ip_rt_send_redirect(struct sk_buff *skb)
+ 		if (IN_DEV_LOG_MARTIANS(in_dev) &&
+ 		    rt->u.dst.rate_tokens == ip_rt_redirect_number &&
+ 		    net_ratelimit())
+-			printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores "
+-				"redirects for %u.%u.%u.%u to %u.%u.%u.%u.\n",
++			printk(KERN_WARNING "host " NIPQUAD_FMT "/if%d ignores "
++				"redirects for " NIPQUAD_FMT " to " NIPQUAD_FMT ".\n",
+ 				NIPQUAD(rt->rt_src), rt->rt_iif,
+ 				NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway));
+ #endif
+@@ -1346,7 +1377,7 @@ out:
+ 
+ static int ip_error(struct sk_buff *skb)
+ {
+-	struct rtable *rt = (struct rtable*)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	unsigned long now;
+ 	int code;
+ 
+@@ -1388,7 +1419,7 @@ out:	kfree_skb(skb);
+ static const unsigned short mtu_plateau[] =
+ {32000, 17914, 8166, 4352, 2002, 1492, 576, 296, 216, 128 };
+ 
+-static __inline__ unsigned short guess_mtu(unsigned short old_mtu)
++static inline unsigned short guess_mtu(unsigned short old_mtu)
+ {
+ 	int i;
+ 
+@@ -1423,7 +1454,7 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
+ 			    rth->rt_src  == iph->saddr &&
+ 			    rth->fl.iif == 0 &&
+ 			    !(dst_metric_locked(&rth->u.dst, RTAX_MTU)) &&
+-			    rth->u.dst.dev->nd_net == net &&
++			    net_eq(dev_net(rth->u.dst.dev), net) &&
+ 			    rth->rt_genid == atomic_read(&rt_genid)) {
+ 				unsigned short mtu = new_mtu;
+ 
+@@ -1499,9 +1530,9 @@ static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ {
+ 	struct rtable *rt = (struct rtable *) dst;
+ 	struct in_device *idev = rt->idev;
+-	if (dev != dev->nd_net->loopback_dev && idev && idev->dev == dev) {
++	if (dev != dev_net(dev)->loopback_dev && idev && idev->dev == dev) {
+ 		struct in_device *loopback_idev =
+-			in_dev_get(dev->nd_net->loopback_dev);
++			in_dev_get(dev_net(dev)->loopback_dev);
+ 		if (loopback_idev) {
+ 			rt->idev = loopback_idev;
+ 			in_dev_put(idev);
+@@ -1515,14 +1546,14 @@ static void ipv4_link_failure(struct sk_buff *skb)
+ 
+ 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+ 
+-	rt = (struct rtable *) skb->dst;
++	rt = skb->rtable;
+ 	if (rt)
+ 		dst_set_expires(&rt->u.dst, 0);
+ }
+ 
+ static int ip_rt_bug(struct sk_buff *skb)
+ {
+-	printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n",
++	printk(KERN_DEBUG "ip_rt_bug: " NIPQUAD_FMT " -> " NIPQUAD_FMT ", %s\n",
+ 		NIPQUAD(ip_hdr(skb)->saddr), NIPQUAD(ip_hdr(skb)->daddr),
+ 		skb->dev ? skb->dev->name : "?");
+ 	kfree_skb(skb);
+@@ -1545,7 +1576,7 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt)
+ 
+ 	if (rt->fl.iif == 0)
+ 		src = rt->rt_src;
+-	else if (fib_lookup(rt->u.dst.dev->nd_net, &rt->fl, &res) == 0) {
++	else if (fib_lookup(dev_net(rt->u.dst.dev), &rt->fl, &res) == 0) {
+ 		src = FIB_RES_PREFSRC(res);
+ 		fib_res_put(&res);
+ 	} else
+@@ -1675,7 +1706,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ 
+ 	in_dev_put(in_dev);
+ 	hash = rt_hash(daddr, saddr, dev->ifindex);
+-	return rt_intern_hash(hash, rth, (struct rtable**) &skb->dst);
++	return rt_intern_hash(hash, rth, &skb->rtable);
+ 
+ e_nobufs:
+ 	in_dev_put(in_dev);
+@@ -1700,8 +1731,8 @@ static void ip_handle_martian_source(struct net_device *dev,
+ 		 *	RFC1812 recommendation, if source is martian,
+ 		 *	the only hint is MAC header.
+ 		 */
+-		printk(KERN_WARNING "martian source %u.%u.%u.%u from "
+-			"%u.%u.%u.%u, on dev %s\n",
++		printk(KERN_WARNING "martian source " NIPQUAD_FMT " from "
++			NIPQUAD_FMT", on dev %s\n",
+ 			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
+ 		if (dev->hard_header_len && skb_mac_header_was_set(skb)) {
+ 			int i;
+@@ -1718,11 +1749,11 @@ static void ip_handle_martian_source(struct net_device *dev,
+ #endif
+ }
+ 
+-static inline int __mkroute_input(struct sk_buff *skb,
+-				  struct fib_result* res,
+-				  struct in_device *in_dev,
+-				  __be32 daddr, __be32 saddr, u32 tos,
+-				  struct rtable **result)
++static int __mkroute_input(struct sk_buff *skb,
++			   struct fib_result *res,
++			   struct in_device *in_dev,
++			   __be32 daddr, __be32 saddr, u32 tos,
++			   struct rtable **result)
+ {
+ 
+ 	struct rtable *rth;
+@@ -1814,11 +1845,11 @@ static inline int __mkroute_input(struct sk_buff *skb,
+ 	return err;
+ }
+ 
+-static inline int ip_mkroute_input(struct sk_buff *skb,
+-				   struct fib_result* res,
+-				   const struct flowi *fl,
+-				   struct in_device *in_dev,
+-				   __be32 daddr, __be32 saddr, u32 tos)
++static int ip_mkroute_input(struct sk_buff *skb,
++			    struct fib_result *res,
++			    const struct flowi *fl,
++			    struct in_device *in_dev,
++			    __be32 daddr, __be32 saddr, u32 tos)
+ {
+ 	struct rtable* rth = NULL;
+ 	int err;
+@@ -1836,7 +1867,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
+ 
+ 	/* put it into the cache */
+ 	hash = rt_hash(daddr, saddr, fl->iif);
+-	return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
++	return rt_intern_hash(hash, rth, &skb->rtable);
+ }
+ 
+ /*
+@@ -1869,7 +1900,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ 	__be32		spec_dst;
+ 	int		err = -EINVAL;
+ 	int		free_res = 0;
+-	struct net    * net = dev->nd_net;
++	struct net    * net = dev_net(dev);
+ 
+ 	/* IP on this device is disabled. */
+ 
+@@ -1992,7 +2023,7 @@ local_input:
+ 	}
+ 	rth->rt_type	= res.type;
+ 	hash = rt_hash(daddr, saddr, fl.iif);
+-	err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
++	err = rt_intern_hash(hash, rth, &skb->rtable);
+ 	goto done;
+ 
+ no_route:
+@@ -2010,8 +2041,8 @@ martian_destination:
+ 	RT_CACHE_STAT_INC(in_martian_dst);
+ #ifdef CONFIG_IP_ROUTE_VERBOSE
+ 	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
+-		printk(KERN_WARNING "martian destination %u.%u.%u.%u from "
+-			"%u.%u.%u.%u, dev %s\n",
++		printk(KERN_WARNING "martian destination " NIPQUAD_FMT " from "
++			NIPQUAD_FMT ", dev %s\n",
+ 			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
+ #endif
+ 
+@@ -2040,25 +2071,25 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ 	int iif = dev->ifindex;
+ 	struct net *net;
+ 
+-	net = dev->nd_net;
++	net = dev_net(dev);
+ 	tos &= IPTOS_RT_MASK;
+ 	hash = rt_hash(daddr, saddr, iif);
+ 
+ 	rcu_read_lock();
+ 	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
+ 	     rth = rcu_dereference(rth->u.dst.rt_next)) {
+-		if (rth->fl.fl4_dst == daddr &&
+-		    rth->fl.fl4_src == saddr &&
+-		    rth->fl.iif == iif &&
+-		    rth->fl.oif == 0 &&
++		if (((rth->fl.fl4_dst ^ daddr) |
++		     (rth->fl.fl4_src ^ saddr) |
++		     (rth->fl.iif ^ iif) |
++		     rth->fl.oif |
++		     (rth->fl.fl4_tos ^ tos)) == 0 &&
+ 		    rth->fl.mark == skb->mark &&
+-		    rth->fl.fl4_tos == tos &&
+-		    rth->u.dst.dev->nd_net == net &&
++		    net_eq(dev_net(rth->u.dst.dev), net) &&
+ 		    rth->rt_genid == atomic_read(&rt_genid)) {
+ 			dst_use(&rth->u.dst, jiffies);
+ 			RT_CACHE_STAT_INC(in_hit);
+ 			rcu_read_unlock();
+-			skb->dst = (struct dst_entry*)rth;
++			skb->rtable = rth;
+ 			return 0;
+ 		}
+ 		RT_CACHE_STAT_INC(in_hlist_search);
+@@ -2100,12 +2131,12 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ 	return ip_route_input_slow(skb, daddr, saddr, tos, dev);
+ }
+ 
+-static inline int __mkroute_output(struct rtable **result,
+-				   struct fib_result* res,
+-				   const struct flowi *fl,
+-				   const struct flowi *oldflp,
+-				   struct net_device *dev_out,
+-				   unsigned flags)
++static int __mkroute_output(struct rtable **result,
++			    struct fib_result *res,
++			    const struct flowi *fl,
++			    const struct flowi *oldflp,
++			    struct net_device *dev_out,
++			    unsigned flags)
+ {
+ 	struct rtable *rth;
+ 	struct in_device *in_dev;
+@@ -2220,12 +2251,12 @@ static inline int __mkroute_output(struct rtable **result,
+ 	return err;
+ }
+ 
+-static inline int ip_mkroute_output(struct rtable **rp,
+-				    struct fib_result* res,
+-				    const struct flowi *fl,
+-				    const struct flowi *oldflp,
+-				    struct net_device *dev_out,
+-				    unsigned flags)
++static int ip_mkroute_output(struct rtable **rp,
++			     struct fib_result *res,
++			     const struct flowi *fl,
++			     const struct flowi *oldflp,
++			     struct net_device *dev_out,
++			     unsigned flags)
+ {
+ 	struct rtable *rth = NULL;
+ 	int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
+@@ -2455,7 +2486,7 @@ int __ip_route_output_key(struct net *net, struct rtable **rp,
+ 		    rth->fl.mark == flp->mark &&
+ 		    !((rth->fl.fl4_tos ^ flp->fl4_tos) &
+ 			    (IPTOS_RT_MASK | RTO_ONLINK)) &&
+-		    rth->u.dst.dev->nd_net == net &&
++		    net_eq(dev_net(rth->u.dst.dev), net) &&
+ 		    rth->rt_genid == atomic_read(&rt_genid)) {
+ 			dst_use(&rth->u.dst, jiffies);
+ 			RT_CACHE_STAT_INC(out_hit);
+@@ -2487,7 +2518,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
+ };
+ 
+ 
+-static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp, struct sock *sk)
++static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp)
+ {
+ 	struct rtable *ort = *rp;
+ 	struct rtable *rt = (struct rtable *)
+@@ -2547,7 +2578,7 @@ int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp,
+ 		err = __xfrm_lookup((struct dst_entry **)rp, flp, sk,
+ 				    flags ? XFRM_LOOKUP_WAIT : 0);
+ 		if (err == -EREMOTE)
+-			err = ipv4_dst_blackhole(rp, flp, sk);
++			err = ipv4_dst_blackhole(rp, flp);
+ 
+ 		return err;
+ 	}
+@@ -2565,7 +2596,7 @@ int ip_route_output_key(struct net *net, struct rtable **rp, struct flowi *flp)
+ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+ 			int nowait, unsigned int flags)
+ {
+-	struct rtable *rt = (struct rtable*)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	struct rtmsg *r;
+ 	struct nlmsghdr *nlh;
+ 	long expires;
+@@ -2658,7 +2689,7 @@ nla_put_failure:
+ 
+ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
+ {
+-	struct net *net = in_skb->sk->sk_net;
++	struct net *net = sock_net(in_skb->sk);
+ 	struct rtmsg *rtm;
+ 	struct nlattr *tb[RTA_MAX+1];
+ 	struct rtable *rt = NULL;
+@@ -2668,9 +2699,6 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ 	int err;
+ 	struct sk_buff *skb;
+ 
+-	if (net != &init_net)
+-		return -EINVAL;
+-
+ 	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
+ 	if (err < 0)
+ 		goto errout;
+@@ -2700,7 +2728,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ 	if (iif) {
+ 		struct net_device *dev;
+ 
+-		dev = __dev_get_by_index(&init_net, iif);
++		dev = __dev_get_by_index(net, iif);
+ 		if (dev == NULL) {
+ 			err = -ENODEV;
+ 			goto errout_free;
+@@ -2712,7 +2740,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ 		err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
+ 		local_bh_enable();
+ 
+-		rt = (struct rtable*) skb->dst;
++		rt = skb->rtable;
+ 		if (err == 0 && rt->u.dst.error)
+ 			err = -rt->u.dst.error;
+ 	} else {
+@@ -2726,22 +2754,22 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ 			},
+ 			.oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0,
+ 		};
+-		err = ip_route_output_key(&init_net, &rt, &fl);
++		err = ip_route_output_key(net, &rt, &fl);
+ 	}
+ 
+ 	if (err)
+ 		goto errout_free;
+ 
+-	skb->dst = &rt->u.dst;
++	skb->rtable = rt;
+ 	if (rtm->rtm_flags & RTM_F_NOTIFY)
+ 		rt->rt_flags |= RTCF_NOTIFY;
+ 
+ 	err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
+-				RTM_NEWROUTE, 0, 0);
++			   RTM_NEWROUTE, 0, 0);
+ 	if (err <= 0)
+ 		goto errout_free;
+ 
+-	err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
++	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid);
+ errout:
+ 	return err;
+ 
+@@ -2755,6 +2783,9 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
+ 	struct rtable *rt;
+ 	int h, s_h;
+ 	int idx, s_idx;
++	struct net *net;
++
++	net = sock_net(skb->sk);
+ 
+ 	s_h = cb->args[0];
+ 	if (s_h < 0)
+@@ -2764,7 +2795,7 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
+ 		rcu_read_lock_bh();
+ 		for (rt = rcu_dereference(rt_hash_table[h].chain), idx = 0; rt;
+ 		     rt = rcu_dereference(rt->u.dst.rt_next), idx++) {
+-			if (idx < s_idx)
++			if (!net_eq(dev_net(rt->u.dst.dev), net) || idx < s_idx)
+ 				continue;
+ 			if (rt->rt_genid != atomic_read(&rt_genid))
+ 				continue;
+@@ -3028,7 +3059,9 @@ int __init ip_rt_init(void)
+ 	devinet_init();
+ 	ip_fib_init();
+ 
+-	setup_timer(&rt_secret_timer, rt_secret_rebuild, 0);
++	rt_secret_timer.function = rt_secret_rebuild;
++	rt_secret_timer.data = 0;
++	init_timer_deferrable(&rt_secret_timer);
+ 
+ 	/* All the timers, started at system startup tend
+ 	   to synchronize. Perturb it a bit.
+@@ -3040,7 +3073,7 @@ int __init ip_rt_init(void)
+ 		ip_rt_secret_interval;
+ 	add_timer(&rt_secret_timer);
+ 
+-	if (ip_rt_proc_init(&init_net))
++	if (ip_rt_proc_init())
+ 		printk(KERN_ERR "Unable to create route proc files\n");
+ #ifdef CONFIG_XFRM
+ 	xfrm_init();
+diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
+index f470fe4..73ba989 100644
+--- a/net/ipv4/syncookies.c
++++ b/net/ipv4/syncookies.c
+@@ -10,8 +10,6 @@
+  *      2 of the License, or (at your option) any later version.
+  *
+  *  $Id: syncookies.c,v 1.18 2002/02/01 22:01:04 davem Exp $
+- *
+- *  Missing: IPv6 support.
+  */
+ 
+ #include <linux/tcp.h>
+@@ -21,26 +19,33 @@
+ #include <linux/kernel.h>
+ #include <net/tcp.h>
+ 
++/* Timestamps: lowest 9 bits store TCP options */
++#define TSBITS 9
++#define TSMASK (((__u32)1 << TSBITS) - 1)
++
+ extern int sysctl_tcp_syncookies;
+ 
+-static __u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS];
++__u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
++EXPORT_SYMBOL(syncookie_secret);
+ 
+ static __init int init_syncookies(void)
+ {
+ 	get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
+ 	return 0;
+ }
+-module_init(init_syncookies);
++__initcall(init_syncookies);
+ 
+ #define COOKIEBITS 24	/* Upper bits store count */
+ #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
+ 
++static DEFINE_PER_CPU(__u32, cookie_scratch)[16 + 5 + SHA_WORKSPACE_WORDS];
++
+ static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
+ 		       u32 count, int c)
+ {
+-	__u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS];
++	__u32 *tmp = __get_cpu_var(cookie_scratch);
+ 
+-	memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c]));
++	memcpy(tmp + 4, syncookie_secret[c], sizeof(syncookie_secret[c]));
+ 	tmp[0] = (__force u32)saddr;
+ 	tmp[1] = (__force u32)daddr;
+ 	tmp[2] = ((__force u32)sport << 16) + (__force u32)dport;
+@@ -50,6 +55,39 @@ static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
+ 	return tmp[17];
+ }
+ 
++
++/*
++ * when syncookies are in effect and tcp timestamps are enabled we encode
++ * tcp options in the lowest 9 bits of the timestamp value that will be
++ * sent in the syn-ack.
++ * Since subsequent timestamps use the normal tcp_time_stamp value, we
++ * must make sure that the resulting initial timestamp is <= tcp_time_stamp.
++ */
++__u32 cookie_init_timestamp(struct request_sock *req)
++{
++	struct inet_request_sock *ireq;
++	u32 ts, ts_now = tcp_time_stamp;
++	u32 options = 0;
++
++	ireq = inet_rsk(req);
++	if (ireq->wscale_ok) {
++		options = ireq->snd_wscale;
++		options |= ireq->rcv_wscale << 4;
++	}
++	options |= ireq->sack_ok << 8;
++
++	ts = ts_now & ~TSMASK;
++	ts |= options;
++	if (ts > ts_now) {
++		ts >>= TSBITS;
++		ts--;
++		ts <<= TSBITS;
++		ts |= options;
++	}
++	return ts;
++}
++
++
+ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
+ 				   __be16 dport, __u32 sseq, __u32 count,
+ 				   __u32 data)
+@@ -184,6 +222,35 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
+ 	return child;
+ }
+ 
++
++/*
++ * when syncookies are in effect and tcp timestamps are enabled we stored
++ * additional tcp options in the timestamp.
++ * This extracts these options from the timestamp echo.
++ *
++ * The lowest 4 bits are for snd_wscale
++ * The next 4 lsb are for rcv_wscale
++ * The next lsb is for sack_ok
++ */
++void cookie_check_timestamp(struct tcp_options_received *tcp_opt)
++{
++	/* echoed timestamp, 9 lowest bits contain options */
++	u32 options = tcp_opt->rcv_tsecr & TSMASK;
++
++	tcp_opt->snd_wscale = options & 0xf;
++	options >>= 4;
++	tcp_opt->rcv_wscale = options & 0xf;
++
++	tcp_opt->sack_ok = (options >> 4) & 0x1;
++
++	if (tcp_opt->sack_ok)
++		tcp_sack_reset(tcp_opt);
++
++	if (tcp_opt->snd_wscale || tcp_opt->rcv_wscale)
++		tcp_opt->wscale_ok = 1;
++}
++EXPORT_SYMBOL(cookie_check_timestamp);
++
+ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ 			     struct ip_options *opt)
+ {
+@@ -197,6 +264,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ 	int mss;
+ 	struct rtable *rt;
+ 	__u8 rcv_wscale;
++	struct tcp_options_received tcp_opt;
+ 
+ 	if (!sysctl_tcp_syncookies || !th->ack)
+ 		goto out;
+@@ -209,6 +277,13 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ 
+ 	NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV);
+ 
++	/* check for timestamp cookie support */
++	memset(&tcp_opt, 0, sizeof(tcp_opt));
++	tcp_parse_options(skb, &tcp_opt, 0);
++
++	if (tcp_opt.saw_tstamp)
++		cookie_check_timestamp(&tcp_opt);
++
+ 	ret = NULL;
+ 	req = reqsk_alloc(&tcp_request_sock_ops); /* for safety */
+ 	if (!req)
+@@ -227,6 +302,12 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ 	ireq->loc_addr		= ip_hdr(skb)->daddr;
+ 	ireq->rmt_addr		= ip_hdr(skb)->saddr;
+ 	ireq->opt		= NULL;
++	ireq->snd_wscale	= tcp_opt.snd_wscale;
++	ireq->rcv_wscale	= tcp_opt.rcv_wscale;
++	ireq->sack_ok		= tcp_opt.sack_ok;
++	ireq->wscale_ok		= tcp_opt.wscale_ok;
++	ireq->tstamp_ok		= tcp_opt.saw_tstamp;
++	req->ts_recent		= tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
+ 
+ 	/* We throwed the options of the initial SYN away, so we hope
+ 	 * the ACK carries the same options again (see RFC1122 4.2.3.8)
+@@ -241,8 +322,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ 		}
+ 	}
+ 
+-	ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0;
+-	ireq->wscale_ok	 = ireq->sack_ok = 0;
+ 	req->expires	= 0UL;
+ 	req->retrans	= 0;
+ 
+@@ -271,11 +350,12 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ 	}
+ 
+ 	/* Try to redo what tcp_v4_send_synack did. */
+-	req->window_clamp = dst_metric(&rt->u.dst, RTAX_WINDOW);
++	req->window_clamp = tp->window_clamp ? :dst_metric(&rt->u.dst, RTAX_WINDOW);
++
+ 	tcp_select_initial_window(tcp_full_space(sk), req->mss,
+ 				  &req->rcv_wnd, &req->window_clamp,
+-				  0, &rcv_wscale);
+-	/* BTW win scale with syncookies is 0 by definition */
++				  ireq->wscale_ok, &rcv_wscale);
++
+ 	ireq->rcv_wscale  = rcv_wscale;
+ 
+ 	ret = get_cookie_sock(sk, skb, req, &rt->u.dst);
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 88286f3..c437f80 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -404,38 +404,6 @@ static struct ctl_table ipv4_table[] = {
+ 		.strategy	= &ipv4_sysctl_local_port_range,
+ 	},
+ 	{
+-		.ctl_name	= NET_IPV4_ICMP_ECHO_IGNORE_ALL,
+-		.procname	= "icmp_echo_ignore_all",
+-		.data		= &sysctl_icmp_echo_ignore_all,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec
+-	},
+-	{
+-		.ctl_name	= NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS,
+-		.procname	= "icmp_echo_ignore_broadcasts",
+-		.data		= &sysctl_icmp_echo_ignore_broadcasts,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec
+-	},
+-	{
+-		.ctl_name	= NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES,
+-		.procname	= "icmp_ignore_bogus_error_responses",
+-		.data		= &sysctl_icmp_ignore_bogus_error_responses,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec
+-	},
+-	{
+-		.ctl_name	= NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
+-		.procname	= "icmp_errors_use_inbound_ifaddr",
+-		.data		= &sysctl_icmp_errors_use_inbound_ifaddr,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec
+-	},
+-	{
+ 		.ctl_name	= NET_IPV4_ROUTE,
+ 		.procname	= "route",
+ 		.maxlen		= 0,
+@@ -586,22 +554,6 @@ static struct ctl_table ipv4_table[] = {
+ 		.proc_handler	= &proc_dointvec
+ 	},
+ 	{
+-		.ctl_name	= NET_IPV4_ICMP_RATELIMIT,
+-		.procname	= "icmp_ratelimit",
+-		.data		= &sysctl_icmp_ratelimit,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec
+-	},
+-	{
+-		.ctl_name	= NET_IPV4_ICMP_RATEMASK,
+-		.procname	= "icmp_ratemask",
+-		.data		= &sysctl_icmp_ratemask,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= &proc_dointvec
+-	},
+-	{
+ 		.ctl_name	= NET_TCP_TW_REUSE,
+ 		.procname	= "tcp_tw_reuse",
+ 		.data		= &sysctl_tcp_tw_reuse,
+@@ -804,6 +756,58 @@ static struct ctl_table ipv4_table[] = {
+ 	{ .ctl_name = 0 }
+ };
+ 
++static struct ctl_table ipv4_net_table[] = {
++	{
++		.ctl_name	= NET_IPV4_ICMP_ECHO_IGNORE_ALL,
++		.procname	= "icmp_echo_ignore_all",
++		.data		= &init_net.ipv4.sysctl_icmp_echo_ignore_all,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec
++	},
++	{
++		.ctl_name	= NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS,
++		.procname	= "icmp_echo_ignore_broadcasts",
++		.data		= &init_net.ipv4.sysctl_icmp_echo_ignore_broadcasts,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec
++	},
++	{
++		.ctl_name	= NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES,
++		.procname	= "icmp_ignore_bogus_error_responses",
++		.data		= &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec
++	},
++	{
++		.ctl_name	= NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
++		.procname	= "icmp_errors_use_inbound_ifaddr",
++		.data		= &init_net.ipv4.sysctl_icmp_errors_use_inbound_ifaddr,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec
++	},
++	{
++		.ctl_name	= NET_IPV4_ICMP_RATELIMIT,
++		.procname	= "icmp_ratelimit",
++		.data		= &init_net.ipv4.sysctl_icmp_ratelimit,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec
++	},
++	{
++		.ctl_name	= NET_IPV4_ICMP_RATEMASK,
++		.procname	= "icmp_ratemask",
++		.data		= &init_net.ipv4.sysctl_icmp_ratemask,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec
++	},
++	{ }
++};
++
+ struct ctl_path net_ipv4_ctl_path[] = {
+ 	{ .procname = "net", .ctl_name = CTL_NET, },
+ 	{ .procname = "ipv4", .ctl_name = NET_IPV4, },
+@@ -811,12 +815,72 @@ struct ctl_path net_ipv4_ctl_path[] = {
+ };
+ EXPORT_SYMBOL_GPL(net_ipv4_ctl_path);
+ 
++static __net_init int ipv4_sysctl_init_net(struct net *net)
++{
++	struct ctl_table *table;
++
++	table = ipv4_net_table;
++	if (net != &init_net) {
++		table = kmemdup(table, sizeof(ipv4_net_table), GFP_KERNEL);
++		if (table == NULL)
++			goto err_alloc;
++
++		table[0].data =
++			&net->ipv4.sysctl_icmp_echo_ignore_all;
++		table[1].data =
++			&net->ipv4.sysctl_icmp_echo_ignore_broadcasts;
++		table[2].data =
++			&net->ipv4.sysctl_icmp_ignore_bogus_error_responses;
++		table[3].data =
++			&net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr;
++		table[4].data =
++			&net->ipv4.sysctl_icmp_ratelimit;
++		table[5].data =
++			&net->ipv4.sysctl_icmp_ratemask;
++	}
++
++	net->ipv4.ipv4_hdr = register_net_sysctl_table(net,
++			net_ipv4_ctl_path, table);
++	if (net->ipv4.ipv4_hdr == NULL)
++		goto err_reg;
++
++	return 0;
++
++err_reg:
++	if (net != &init_net)
++		kfree(table);
++err_alloc:
++	return -ENOMEM;
++}
++
++static __net_exit void ipv4_sysctl_exit_net(struct net *net)
++{
++	struct ctl_table *table;
++
++	table = net->ipv4.ipv4_hdr->ctl_table_arg;
++	unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
++	kfree(table);
++}
++
++static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
++	.init = ipv4_sysctl_init_net,
++	.exit = ipv4_sysctl_exit_net,
++};
++
+ static __init int sysctl_ipv4_init(void)
+ {
+ 	struct ctl_table_header *hdr;
+ 
+ 	hdr = register_sysctl_paths(net_ipv4_ctl_path, ipv4_table);
+-	return hdr == NULL ? -ENOMEM : 0;
++	if (hdr == NULL)
++		return -ENOMEM;
++
++	if (register_pernet_subsys(&ipv4_sysctl_ops)) {
++		unregister_sysctl_table(hdr);
++		return -ENOMEM;
++	}
++
++	return 0;
+ }
+ 
+ __initcall(sysctl_ipv4_init);
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 39b629a..f886531 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -1722,7 +1722,7 @@ static int tcp_close_state(struct sock *sk)
+ 
+ /*
+  *	Shutdown the sending side of a connection. Much like close except
+- *	that we don't receive shut down or set_sock_flag(sk, SOCK_DEAD).
++ *	that we don't receive shut down or sock_set_flag(sk, SOCK_DEAD).
+  */
+ 
+ void tcp_shutdown(struct sock *sk, int how)
+@@ -2105,15 +2105,12 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
+ 		break;
+ 
+ 	case TCP_DEFER_ACCEPT:
+-		icsk->icsk_accept_queue.rskq_defer_accept = 0;
+-		if (val > 0) {
+-			/* Translate value in seconds to number of
+-			 * retransmits */
+-			while (icsk->icsk_accept_queue.rskq_defer_accept < 32 &&
+-			       val > ((TCP_TIMEOUT_INIT / HZ) <<
+-				       icsk->icsk_accept_queue.rskq_defer_accept))
+-				icsk->icsk_accept_queue.rskq_defer_accept++;
+-			icsk->icsk_accept_queue.rskq_defer_accept++;
++		if (val < 0) {
++			err = -EINVAL;
++		} else {
++			if (val > MAX_TCP_ACCEPT_DEFERRED)
++				val = MAX_TCP_ACCEPT_DEFERRED;
++			icsk->icsk_accept_queue.rskq_defer_accept = val;
+ 		}
+ 		break;
+ 
+@@ -2295,8 +2292,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
+ 			val = (val ? : sysctl_tcp_fin_timeout) / HZ;
+ 		break;
+ 	case TCP_DEFER_ACCEPT:
+-		val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 :
+-			((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1));
++		val = icsk->icsk_accept_queue.rskq_defer_accept;
+ 		break;
+ 	case TCP_WINDOW_CLAMP:
+ 		val = tp->window_clamp;
+diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
+index 3aa0b23..eb5b985 100644
+--- a/net/ipv4/tcp_cubic.c
++++ b/net/ipv4/tcp_cubic.c
+@@ -1,12 +1,13 @@
+ /*
+- * TCP CUBIC: Binary Increase Congestion control for TCP v2.1
+- *
++ * TCP CUBIC: Binary Increase Congestion control for TCP v2.2
++ * Home page:
++ *      http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC
+  * This is from the implementation of CUBIC TCP in
+  * Injong Rhee, Lisong Xu.
+  *  "CUBIC: A New TCP-Friendly High-Speed TCP Variant
+  *  in PFLDnet 2005
+  * Available from:
+- *  http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf
++ *  http://netsrv.csc.ncsu.edu/export/cubic-paper.pdf
+  *
+  * Unless CUBIC is enabled and congestion window is large
+  * this behaves the same as the original Reno.
+@@ -20,15 +21,10 @@
+ #define BICTCP_BETA_SCALE    1024	/* Scale factor beta calculation
+ 					 * max_cwnd = snd_cwnd * beta
+ 					 */
+-#define BICTCP_B		4	 /*
+-					  * In binary search,
+-					  * go to point (max+min)/N
+-					  */
+ #define	BICTCP_HZ		10	/* BIC HZ 2^10 = 1024 */
+ 
+ static int fast_convergence __read_mostly = 1;
+-static int max_increment __read_mostly = 16;
+-static int beta __read_mostly = 819;	/* = 819/1024 (BICTCP_BETA_SCALE) */
++static int beta __read_mostly = 717;	/* = 717/1024 (BICTCP_BETA_SCALE) */
+ static int initial_ssthresh __read_mostly;
+ static int bic_scale __read_mostly = 41;
+ static int tcp_friendliness __read_mostly = 1;
+@@ -40,9 +36,7 @@ static u64 cube_factor __read_mostly;
+ /* Note parameters that are used for precomputing scale factors are read-only */
+ module_param(fast_convergence, int, 0644);
+ MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
+-module_param(max_increment, int, 0644);
+-MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search");
+-module_param(beta, int, 0444);
++module_param(beta, int, 0644);
+ MODULE_PARM_DESC(beta, "beta for multiplicative increase");
+ module_param(initial_ssthresh, int, 0644);
+ MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
+@@ -145,7 +139,7 @@ static u32 cubic_root(u64 a)
+ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
+ {
+ 	u64 offs;
+-	u32 delta, t, bic_target, min_cnt, max_cnt;
++	u32 delta, t, bic_target, max_cnt;
+ 
+ 	ca->ack_cnt++;	/* count the number of ACKs */
+ 
+@@ -211,19 +205,6 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
+ 		ca->cnt = 100 * cwnd;              /* very small increment*/
+ 	}
+ 
+-	if (ca->delay_min > 0) {
+-		/* max increment = Smax * rtt / 0.1  */
+-		min_cnt = (cwnd * HZ * 8)/(10 * max_increment * ca->delay_min);
+-
+-		/* use concave growth when the target is above the origin */
+-		if (ca->cnt < min_cnt && t >= ca->bic_K)
+-			ca->cnt = min_cnt;
+-	}
+-
+-	/* slow start and low utilization  */
+-	if (ca->loss_cwnd == 0)		/* could be aggressive in slow start */
+-		ca->cnt = 50;
+-
+ 	/* TCP Friendly */
+ 	if (tcp_friendliness) {
+ 		u32 scale = beta_scale;
+@@ -391,4 +372,4 @@ module_exit(cubictcp_unregister);
+ MODULE_AUTHOR("Sangtae Ha, Stephen Hemminger");
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("CUBIC TCP");
+-MODULE_VERSION("2.1");
++MODULE_VERSION("2.2");
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index bbb7d88..ac9b848 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -2298,7 +2298,7 @@ static inline int tcp_packet_delayed(struct tcp_sock *tp)
+ {
+ 	return !tp->retrans_stamp ||
+ 		(tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
+-		 (__s32)(tp->rx_opt.rcv_tsecr - tp->retrans_stamp) < 0);
++		 before(tp->rx_opt.rcv_tsecr, tp->retrans_stamp));
+ }
+ 
+ /* Undo procedures. */
+@@ -2309,12 +2309,25 @@ static void DBGUNDO(struct sock *sk, const char *msg)
+ 	struct tcp_sock *tp = tcp_sk(sk);
+ 	struct inet_sock *inet = inet_sk(sk);
+ 
+-	printk(KERN_DEBUG "Undo %s %u.%u.%u.%u/%u c%u l%u ss%u/%u p%u\n",
+-	       msg,
+-	       NIPQUAD(inet->daddr), ntohs(inet->dport),
+-	       tp->snd_cwnd, tcp_left_out(tp),
+-	       tp->snd_ssthresh, tp->prior_ssthresh,
+-	       tp->packets_out);
++	if (sk->sk_family == AF_INET) {
++		printk(KERN_DEBUG "Undo %s " NIPQUAD_FMT "/%u c%u l%u ss%u/%u p%u\n",
++		       msg,
++		       NIPQUAD(inet->daddr), ntohs(inet->dport),
++		       tp->snd_cwnd, tcp_left_out(tp),
++		       tp->snd_ssthresh, tp->prior_ssthresh,
++		       tp->packets_out);
++	}
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++	else if (sk->sk_family == AF_INET6) {
++		struct ipv6_pinfo *np = inet6_sk(sk);
++		printk(KERN_DEBUG "Undo %s " NIP6_FMT "/%u c%u l%u ss%u/%u p%u\n",
++		       msg,
++		       NIP6(np->daddr), ntohs(inet->dport),
++		       tp->snd_cwnd, tcp_left_out(tp),
++		       tp->snd_ssthresh, tp->prior_ssthresh,
++		       tp->packets_out);
++	}
++#endif
+ }
+ #else
+ #define DBGUNDO(x...) do { } while (0)
+@@ -3592,7 +3605,7 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
+ 		 * cases we should never reach this piece of code.
+ 		 */
+ 		printk(KERN_ERR "%s: Impossible, sk->sk_state=%d\n",
+-		       __FUNCTION__, sk->sk_state);
++		       __func__, sk->sk_state);
+ 		break;
+ 	}
+ 
+@@ -4012,7 +4025,7 @@ drop:
+ 		u32 end_seq = TCP_SKB_CB(skb)->end_seq;
+ 
+ 		if (seq == TCP_SKB_CB(skb1)->end_seq) {
+-			__skb_append(skb1, skb, &tp->out_of_order_queue);
++			__skb_queue_after(&tp->out_of_order_queue, skb1, skb);
+ 
+ 			if (!tp->rx_opt.num_sacks ||
+ 			    tp->selective_acks[0].end_seq != seq)
+@@ -4508,6 +4521,49 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th)
+ 	}
+ }
+ 
++static int tcp_defer_accept_check(struct sock *sk)
++{
++	struct tcp_sock *tp = tcp_sk(sk);
++
++	if (tp->defer_tcp_accept.request) {
++		int queued_data =  tp->rcv_nxt - tp->copied_seq;
++		int hasfin =  !skb_queue_empty(&sk->sk_receive_queue) ?
++			tcp_hdr((struct sk_buff *)
++				sk->sk_receive_queue.prev)->fin : 0;
++
++		if (queued_data && hasfin)
++			queued_data--;
++
++		if (queued_data &&
++		    tp->defer_tcp_accept.listen_sk->sk_state == TCP_LISTEN) {
++			if (sock_flag(sk, SOCK_KEEPOPEN)) {
++				inet_csk_reset_keepalive_timer(sk,
++							       keepalive_time_when(tp));
++			} else {
++				inet_csk_delete_keepalive_timer(sk);
++			}
++
++			inet_csk_reqsk_queue_add(
++				tp->defer_tcp_accept.listen_sk,
++				tp->defer_tcp_accept.request,
++				sk);
++
++			tp->defer_tcp_accept.listen_sk->sk_data_ready(
++				tp->defer_tcp_accept.listen_sk, 0);
++
++			sock_put(tp->defer_tcp_accept.listen_sk);
++			sock_put(sk);
++			tp->defer_tcp_accept.listen_sk = NULL;
++			tp->defer_tcp_accept.request = NULL;
++		} else if (hasfin ||
++			   tp->defer_tcp_accept.listen_sk->sk_state != TCP_LISTEN) {
++			tcp_reset(sk);
++			return -1;
++		}
++	}
++	return 0;
++}
++
+ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
+ {
+ 	struct tcp_sock *tp = tcp_sk(sk);
+@@ -4868,6 +4924,9 @@ step5:
+ 
+ 	tcp_data_snd_check(sk);
+ 	tcp_ack_snd_check(sk);
++
++	if (tcp_defer_accept_check(sk))
++		return -1;
+ 	return 0;
+ 
+ csum_error:
+@@ -5387,6 +5446,7 @@ discard:
+ 
+ EXPORT_SYMBOL(sysctl_tcp_ecn);
+ EXPORT_SYMBOL(sysctl_tcp_reordering);
++EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
+ EXPORT_SYMBOL(tcp_parse_options);
+ EXPORT_SYMBOL(tcp_rcv_established);
+ EXPORT_SYMBOL(tcp_rcv_state_process);
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 00156bf..0e9bc12 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -88,9 +88,6 @@ int sysctl_tcp_low_latency __read_mostly;
+ /* Check TCP sequence numbers in ICMP packets. */
+ #define ICMP_MIN_LENGTH 8
+ 
+-/* Socket used for sending RSTs */
+-static struct socket *tcp_socket __read_mostly;
+-
+ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
+ 
+ #ifdef CONFIG_TCP_MD5SIG
+@@ -353,7 +350,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
+ 		return;
+ 	}
+ 
+-	sk = inet_lookup(skb->dev->nd_net, &tcp_hashinfo, iph->daddr, th->dest,
++	sk = inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->daddr, th->dest,
+ 			iph->saddr, th->source, inet_iif(skb));
+ 	if (!sk) {
+ 		ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+@@ -552,7 +549,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
+ 	if (th->rst)
+ 		return;
+ 
+-	if (((struct rtable *)skb->dst)->rt_type != RTN_LOCAL)
++	if (skb->rtable->rt_type != RTN_LOCAL)
+ 		return;
+ 
+ 	/* Swap the send and the receive. */
+@@ -598,7 +595,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
+ 				      sizeof(struct tcphdr), IPPROTO_TCP, 0);
+ 	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+ 
+-	ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
++	ip_send_reply(dev_net(skb->dst->dev)->ipv4.tcp_sock, skb,
++		      &arg, arg.iov[0].iov_len);
+ 
+ 	TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+ 	TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
+@@ -693,7 +691,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
+ 	if (twsk)
+ 		arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
+ 
+-	ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
++	ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb,
++		      &arg, arg.iov[0].iov_len);
+ 
+ 	TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+ }
+@@ -723,8 +722,8 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
+  *	This still operates on a request_sock only, not on a big
+  *	socket.
+  */
+-static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
+-			      struct dst_entry *dst)
++static int __tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
++				struct dst_entry *dst)
+ {
+ 	const struct inet_request_sock *ireq = inet_rsk(req);
+ 	int err = -1;
+@@ -732,7 +731,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
+ 
+ 	/* First, grab a route. */
+ 	if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
+-		goto out;
++		return -1;
+ 
+ 	skb = tcp_make_synack(sk, dst, req);
+ 
+@@ -751,11 +750,15 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
+ 		err = net_xmit_eval(err);
+ 	}
+ 
+-out:
+ 	dst_release(dst);
+ 	return err;
+ }
+ 
++static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req)
++{
++	return __tcp_v4_send_synack(sk, req, NULL);
++}
++
+ /*
+  *	IPv4 request_sock destructor.
+  */
+@@ -1258,8 +1261,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ #endif
+ 
+ 	/* Never answer to SYNs send to broadcast or multicast */
+-	if (((struct rtable *)skb->dst)->rt_flags &
+-	    (RTCF_BROADCAST | RTCF_MULTICAST))
++	if (skb->rtable->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
+ 		goto drop;
+ 
+ 	/* TW buckets are converted to open requests without
+@@ -1297,10 +1299,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ 
+ 	tcp_parse_options(skb, &tmp_opt, 0);
+ 
+-	if (want_cookie) {
++	if (want_cookie && !tmp_opt.saw_tstamp)
+ 		tcp_clear_options(&tmp_opt);
+-		tmp_opt.saw_tstamp = 0;
+-	}
+ 
+ 	if (tmp_opt.saw_tstamp && !tmp_opt.rcv_tsval) {
+ 		/* Some OSes (unknown ones, but I see them on web server, which
+@@ -1328,6 +1328,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ 	if (want_cookie) {
+ #ifdef CONFIG_SYN_COOKIES
+ 		syn_flood_warning(skb);
++		req->cookie_ts = tmp_opt.tstamp_ok;
+ #endif
+ 		isn = cookie_v4_init_sequence(sk, skb, &req->mss);
+ 	} else if (!isn) {
+@@ -1351,8 +1352,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ 			    (s32)(peer->tcp_ts - req->ts_recent) >
+ 							TCP_PAWS_WINDOW) {
+ 				NET_INC_STATS_BH(LINUX_MIB_PAWSPASSIVEREJECTED);
+-				dst_release(dst);
+-				goto drop_and_free;
++				goto drop_and_release;
+ 			}
+ 		}
+ 		/* Kill the following clause, if you dislike this way. */
+@@ -1369,27 +1369,24 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ 			 * to the moment of synflood.
+ 			 */
+ 			LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open "
+-				       "request from %u.%u.%u.%u/%u\n",
++				       "request from " NIPQUAD_FMT "/%u\n",
+ 				       NIPQUAD(saddr),
+ 				       ntohs(tcp_hdr(skb)->source));
+-			dst_release(dst);
+-			goto drop_and_free;
++			goto drop_and_release;
+ 		}
+ 
+ 		isn = tcp_v4_init_sequence(skb);
+ 	}
+ 	tcp_rsk(req)->snt_isn = isn;
+ 
+-	if (tcp_v4_send_synack(sk, req, dst))
++	if (__tcp_v4_send_synack(sk, req, dst) || want_cookie)
+ 		goto drop_and_free;
+ 
+-	if (want_cookie) {
+-		reqsk_free(req);
+-	} else {
+-		inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
+-	}
++	inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
+ 	return 0;
+ 
++drop_and_release:
++	dst_release(dst);
+ drop_and_free:
+ 	reqsk_free(req);
+ drop:
+@@ -1487,7 +1484,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
+ 	if (req)
+ 		return tcp_check_req(sk, skb, req, prev);
+ 
+-	nsk = inet_lookup_established(sk->sk_net, &tcp_hashinfo, iph->saddr,
++	nsk = inet_lookup_established(sock_net(sk), &tcp_hashinfo, iph->saddr,
+ 			th->source, iph->daddr, th->dest, inet_iif(skb));
+ 
+ 	if (nsk) {
+@@ -1645,7 +1642,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
+ 	TCP_SKB_CB(skb)->flags	 = iph->tos;
+ 	TCP_SKB_CB(skb)->sacked	 = 0;
+ 
+-	sk = __inet_lookup(skb->dev->nd_net, &tcp_hashinfo, iph->saddr,
++	sk = __inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->saddr,
+ 			th->source, iph->daddr, th->dest, inet_iif(skb));
+ 	if (!sk)
+ 		goto no_tcp_socket;
+@@ -1719,7 +1716,7 @@ do_time_wait:
+ 	}
+ 	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
+ 	case TCP_TW_SYN: {
+-		struct sock *sk2 = inet_lookup_listener(skb->dev->nd_net,
++		struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
+ 							&tcp_hashinfo,
+ 							iph->daddr, th->dest,
+ 							inet_iif(skb));
+@@ -1921,6 +1918,14 @@ int tcp_v4_destroy_sock(struct sock *sk)
+ 		sk->sk_sndmsg_page = NULL;
+ 	}
+ 
++	if (tp->defer_tcp_accept.request) {
++		reqsk_free(tp->defer_tcp_accept.request);
++		sock_put(tp->defer_tcp_accept.listen_sk);
++		sock_put(sk);
++		tp->defer_tcp_accept.listen_sk = NULL;
++		tp->defer_tcp_accept.request = NULL;
++	}
++
+ 	atomic_dec(&tcp_sockets_allocated);
+ 
+ 	return 0;
+@@ -1949,6 +1954,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
+ 	struct hlist_node *node;
+ 	struct sock *sk = cur;
+ 	struct tcp_iter_state* st = seq->private;
++	struct net *net = seq_file_net(seq);
+ 
+ 	if (!sk) {
+ 		st->bucket = 0;
+@@ -1965,7 +1971,8 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
+ 		req = req->dl_next;
+ 		while (1) {
+ 			while (req) {
+-				if (req->rsk_ops->family == st->family) {
++				if (req->rsk_ops->family == st->family &&
++				    net_eq(sock_net(req->sk), net)) {
+ 					cur = req;
+ 					goto out;
+ 				}
+@@ -1989,7 +1996,7 @@ get_req:
+ 	}
+ get_sk:
+ 	sk_for_each_from(sk, node) {
+-		if (sk->sk_family == st->family) {
++		if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
+ 			cur = sk;
+ 			goto out;
+ 		}
+@@ -2028,6 +2035,7 @@ static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
+ static void *established_get_first(struct seq_file *seq)
+ {
+ 	struct tcp_iter_state* st = seq->private;
++	struct net *net = seq_file_net(seq);
+ 	void *rc = NULL;
+ 
+ 	for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
+@@ -2038,7 +2046,8 @@ static void *established_get_first(struct seq_file *seq)
+ 
+ 		read_lock_bh(lock);
+ 		sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
+-			if (sk->sk_family != st->family) {
++			if (sk->sk_family != st->family ||
++			    !net_eq(sock_net(sk), net)) {
+ 				continue;
+ 			}
+ 			rc = sk;
+@@ -2047,7 +2056,8 @@ static void *established_get_first(struct seq_file *seq)
+ 		st->state = TCP_SEQ_STATE_TIME_WAIT;
+ 		inet_twsk_for_each(tw, node,
+ 				   &tcp_hashinfo.ehash[st->bucket].twchain) {
+-			if (tw->tw_family != st->family) {
++			if (tw->tw_family != st->family ||
++			    !net_eq(twsk_net(tw), net)) {
+ 				continue;
+ 			}
+ 			rc = tw;
+@@ -2066,6 +2076,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
+ 	struct inet_timewait_sock *tw;
+ 	struct hlist_node *node;
+ 	struct tcp_iter_state* st = seq->private;
++	struct net *net = seq_file_net(seq);
+ 
+ 	++st->num;
+ 
+@@ -2073,7 +2084,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
+ 		tw = cur;
+ 		tw = tw_next(tw);
+ get_tw:
+-		while (tw && tw->tw_family != st->family) {
++		while (tw && (tw->tw_family != st->family || !net_eq(twsk_net(tw), net))) {
+ 			tw = tw_next(tw);
+ 		}
+ 		if (tw) {
+@@ -2094,7 +2105,7 @@ get_tw:
+ 		sk = sk_next(sk);
+ 
+ 	sk_for_each_from(sk, node) {
+-		if (sk->sk_family == st->family)
++		if (sk->sk_family == st->family && net_eq(sock_net(sk), net))
+ 			goto found;
+ 	}
+ 
+@@ -2200,48 +2211,37 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
+ static int tcp_seq_open(struct inode *inode, struct file *file)
+ {
+ 	struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
+-	struct seq_file *seq;
+ 	struct tcp_iter_state *s;
+-	int rc;
++	int err;
+ 
+ 	if (unlikely(afinfo == NULL))
+ 		return -EINVAL;
+ 
+-	s = kzalloc(sizeof(*s), GFP_KERNEL);
+-	if (!s)
+-		return -ENOMEM;
++	err = seq_open_net(inode, file, &afinfo->seq_ops,
++			  sizeof(struct tcp_iter_state));
++	if (err < 0)
++		return err;
++
++	s = ((struct seq_file *)file->private_data)->private;
+ 	s->family		= afinfo->family;
+-	s->seq_ops.start	= tcp_seq_start;
+-	s->seq_ops.next		= tcp_seq_next;
+-	s->seq_ops.show		= afinfo->seq_show;
+-	s->seq_ops.stop		= tcp_seq_stop;
+-
+-	rc = seq_open(file, &s->seq_ops);
+-	if (rc)
+-		goto out_kfree;
+-	seq	     = file->private_data;
+-	seq->private = s;
+-out:
+-	return rc;
+-out_kfree:
+-	kfree(s);
+-	goto out;
++	return 0;
+ }
+ 
+-int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
++int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo)
+ {
+ 	int rc = 0;
+ 	struct proc_dir_entry *p;
+ 
+-	if (!afinfo)
+-		return -EINVAL;
+-	afinfo->seq_fops->owner		= afinfo->owner;
+-	afinfo->seq_fops->open		= tcp_seq_open;
+-	afinfo->seq_fops->read		= seq_read;
+-	afinfo->seq_fops->llseek	= seq_lseek;
+-	afinfo->seq_fops->release	= seq_release_private;
++	afinfo->seq_fops.open		= tcp_seq_open;
++	afinfo->seq_fops.read		= seq_read;
++	afinfo->seq_fops.llseek		= seq_lseek;
++	afinfo->seq_fops.release	= seq_release_net;
++
++	afinfo->seq_ops.start		= tcp_seq_start;
++	afinfo->seq_ops.next		= tcp_seq_next;
++	afinfo->seq_ops.stop		= tcp_seq_stop;
+ 
+-	p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
++	p = proc_net_fops_create(net, afinfo->name, S_IRUGO, &afinfo->seq_fops);
+ 	if (p)
+ 		p->data = afinfo;
+ 	else
+@@ -2249,22 +2249,19 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
+ 	return rc;
+ }
+ 
+-void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
++void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
+ {
+-	if (!afinfo)
+-		return;
+-	proc_net_remove(&init_net, afinfo->name);
+-	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
++	proc_net_remove(net, afinfo->name);
+ }
+ 
+ static void get_openreq4(struct sock *sk, struct request_sock *req,
+-			 char *tmpbuf, int i, int uid)
++			 struct seq_file *f, int i, int uid, int *len)
+ {
+ 	const struct inet_request_sock *ireq = inet_rsk(req);
+ 	int ttd = req->expires - jiffies;
+ 
+-	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+-		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",
++	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
++		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p%n",
+ 		i,
+ 		ireq->loc_addr,
+ 		ntohs(inet_sk(sk)->sport),
+@@ -2279,10 +2276,11 @@ static void get_openreq4(struct sock *sk, struct request_sock *req,
+ 		0,  /* non standard timer */
+ 		0, /* open_requests have no inode */
+ 		atomic_read(&sk->sk_refcnt),
+-		req);
++		req,
++		len);
+ }
+ 
+-static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
++static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
+ {
+ 	int timer_active;
+ 	unsigned long timer_expires;
+@@ -2308,8 +2306,8 @@ static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
+ 		timer_expires = jiffies;
+ 	}
+ 
+-	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
+-			"%08X %5d %8d %lu %d %p %u %u %u %u %d",
++	seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
++			"%08X %5d %8d %lu %d %p %u %u %u %u %d%n",
+ 		i, src, srcp, dest, destp, sk->sk_state,
+ 		tp->write_seq - tp->snd_una,
+ 		sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :
+@@ -2325,11 +2323,12 @@ static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
+ 		icsk->icsk_ack.ato,
+ 		(icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
+ 		tp->snd_cwnd,
+-		tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
++		tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh,
++		len);
+ }
+ 
+ static void get_timewait4_sock(struct inet_timewait_sock *tw,
+-			       char *tmpbuf, int i)
++			       struct seq_file *f, int i, int *len)
+ {
+ 	__be32 dest, src;
+ 	__u16 destp, srcp;
+@@ -2343,11 +2342,11 @@ static void get_timewait4_sock(struct inet_timewait_sock *tw,
+ 	destp = ntohs(tw->tw_dport);
+ 	srcp  = ntohs(tw->tw_sport);
+ 
+-	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+-		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p",
++	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
++		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p%n",
+ 		i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
+ 		3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
+-		atomic_read(&tw->tw_refcnt), tw);
++		atomic_read(&tw->tw_refcnt), tw, len);
+ }
+ 
+ #define TMPSZ 150
+@@ -2355,7 +2354,7 @@ static void get_timewait4_sock(struct inet_timewait_sock *tw,
+ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ {
+ 	struct tcp_iter_state* st;
+-	char tmpbuf[TMPSZ + 1];
++	int len;
+ 
+ 	if (v == SEQ_START_TOKEN) {
+ 		seq_printf(seq, "%-*s\n", TMPSZ - 1,
+@@ -2369,42 +2368,57 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ 	switch (st->state) {
+ 	case TCP_SEQ_STATE_LISTENING:
+ 	case TCP_SEQ_STATE_ESTABLISHED:
+-		get_tcp4_sock(v, tmpbuf, st->num);
++		get_tcp4_sock(v, seq, st->num, &len);
+ 		break;
+ 	case TCP_SEQ_STATE_OPENREQ:
+-		get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid);
++		get_openreq4(st->syn_wait_sk, v, seq, st->num, st->uid, &len);
+ 		break;
+ 	case TCP_SEQ_STATE_TIME_WAIT:
+-		get_timewait4_sock(v, tmpbuf, st->num);
++		get_timewait4_sock(v, seq, st->num, &len);
+ 		break;
+ 	}
+-	seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
++	seq_printf(seq, "%*s\n", TMPSZ - 1 - len, "");
+ out:
+ 	return 0;
+ }
+ 
+-static struct file_operations tcp4_seq_fops;
+ static struct tcp_seq_afinfo tcp4_seq_afinfo = {
+-	.owner		= THIS_MODULE,
+ 	.name		= "tcp",
+ 	.family		= AF_INET,
+-	.seq_show	= tcp4_seq_show,
+-	.seq_fops	= &tcp4_seq_fops,
++	.seq_fops	= {
++		.owner		= THIS_MODULE,
++	},
++	.seq_ops	= {
++		.show		= tcp4_seq_show,
++	},
++};
++
++static int tcp4_proc_init_net(struct net *net)
++{
++	return tcp_proc_register(net, &tcp4_seq_afinfo);
++}
++
++static void tcp4_proc_exit_net(struct net *net)
++{
++	tcp_proc_unregister(net, &tcp4_seq_afinfo);
++}
++
++static struct pernet_operations tcp4_net_ops = {
++	.init = tcp4_proc_init_net,
++	.exit = tcp4_proc_exit_net,
+ };
+ 
+ int __init tcp4_proc_init(void)
+ {
+-	return tcp_proc_register(&tcp4_seq_afinfo);
++	return register_pernet_subsys(&tcp4_net_ops);
+ }
+ 
+ void tcp4_proc_exit(void)
+ {
+-	tcp_proc_unregister(&tcp4_seq_afinfo);
++	unregister_pernet_subsys(&tcp4_net_ops);
+ }
+ #endif /* CONFIG_PROC_FS */
+ 
+-DEFINE_PROTO_INUSE(tcp)
+-
+ struct proto tcp_prot = {
+ 	.name			= "TCP",
+ 	.owner			= THIS_MODULE,
+@@ -2435,18 +2449,33 @@ struct proto tcp_prot = {
+ 	.obj_size		= sizeof(struct tcp_sock),
+ 	.twsk_prot		= &tcp_timewait_sock_ops,
+ 	.rsk_prot		= &tcp_request_sock_ops,
+-	.hashinfo		= &tcp_hashinfo,
++	.h.hashinfo		= &tcp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt	= compat_tcp_setsockopt,
+ 	.compat_getsockopt	= compat_tcp_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(tcp)
+ };
+ 
+-void __init tcp_v4_init(struct net_proto_family *ops)
++
++static int __net_init tcp_sk_init(struct net *net)
++{
++	return inet_ctl_sock_create(&net->ipv4.tcp_sock,
++				    PF_INET, SOCK_RAW, IPPROTO_TCP, net);
++}
++
++static void __net_exit tcp_sk_exit(struct net *net)
++{
++	inet_ctl_sock_destroy(net->ipv4.tcp_sock);
++}
++
++static struct pernet_operations __net_initdata tcp_sk_ops = {
++       .init = tcp_sk_init,
++       .exit = tcp_sk_exit,
++};
++
++void __init tcp_v4_init(void)
+ {
+-	if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW,
+-				     IPPROTO_TCP) < 0)
++	if (register_pernet_device(&tcp_sk_ops))
+ 		panic("Failed to create the TCP control socket.\n");
+ }
+ 
+diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
+index b61b768..019c8c1 100644
+--- a/net/ipv4/tcp_minisocks.c
++++ b/net/ipv4/tcp_minisocks.c
+@@ -35,6 +35,8 @@
+ #endif
+ 
+ int sysctl_tcp_syncookies __read_mostly = SYNC_INIT;
++EXPORT_SYMBOL(sysctl_tcp_syncookies);
++
+ int sysctl_tcp_abort_on_overflow __read_mostly;
+ 
+ struct inet_timewait_death_row tcp_death_row = {
+@@ -536,7 +538,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ 		 * Enforce "SYN-ACK" according to figure 8, figure 6
+ 		 * of RFC793, fixed by RFC1122.
+ 		 */
+-		req->rsk_ops->rtx_syn_ack(sk, req, NULL);
++		req->rsk_ops->rtx_syn_ack(sk, req);
+ 		return NULL;
+ 	}
+ 
+@@ -569,10 +571,8 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ 	   does sequence test, SYN is truncated, and thus we consider
+ 	   it a bare ACK.
+ 
+-	   If icsk->icsk_accept_queue.rskq_defer_accept, we silently drop this
+-	   bare ACK.  Otherwise, we create an established connection.  Both
+-	   ends (listening sockets) accept the new incoming connection and try
+-	   to talk to each other. 8-)
++	   Both ends (listening sockets) accept the new incoming
++	   connection and try to talk to each other. 8-)
+ 
+ 	   Note: This case is both harmless, and rare.  Possibility is about the
+ 	   same as us discovering intelligent life on another plant tomorrow.
+@@ -640,13 +640,6 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ 		if (!(flg & TCP_FLAG_ACK))
+ 			return NULL;
+ 
+-		/* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
+-		if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
+-		    TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
+-			inet_rsk(req)->acked = 1;
+-			return NULL;
+-		}
+-
+ 		/* OK, ACK is valid, create big socket and
+ 		 * feed this segment to it. It will repeat all
+ 		 * the tests. THIS SEGMENT MUST MOVE SOCKET TO
+@@ -685,7 +678,24 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ 		inet_csk_reqsk_queue_unlink(sk, req, prev);
+ 		inet_csk_reqsk_queue_removed(sk, req);
+ 
+-		inet_csk_reqsk_queue_add(sk, req, child);
++		if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
++		    TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
++
++			/* the accept queue handling is done is est recv slow
++			 * path so lets make sure to start there
++			 */
++			tcp_sk(child)->pred_flags = 0;
++			sock_hold(sk);
++			sock_hold(child);
++			tcp_sk(child)->defer_tcp_accept.listen_sk = sk;
++			tcp_sk(child)->defer_tcp_accept.request = req;
++
++			inet_csk_reset_keepalive_timer(child,
++						       inet_csk(sk)->icsk_accept_queue.rskq_defer_accept * HZ);
++		} else {
++			inet_csk_reqsk_queue_add(sk, req, child);
++		}
++
+ 		return child;
+ 
+ 	listen_overflow:
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index d29ef79..debf235 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -998,7 +998,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
+ 	xmit_size_goal = mss_now;
+ 
+ 	if (doing_tso) {
+-		xmit_size_goal = (65535 -
++		xmit_size_goal = ((sk->sk_gso_max_size - 1) -
+ 				  inet_csk(sk)->icsk_af_ops->net_header_len -
+ 				  inet_csk(sk)->icsk_ext_hdr_len -
+ 				  tp->tcp_header_len);
+@@ -1057,7 +1057,7 @@ static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
+ 
+ 	needed = min(skb->len, window);
+ 
+-	if (skb == tcp_write_queue_tail(sk) && cwnd_len <= needed)
++	if (cwnd_len <= needed)
+ 		return cwnd_len;
+ 
+ 	return needed - needed % mss_now;
+@@ -1282,7 +1282,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
+ 	limit = min(send_win, cong_win);
+ 
+ 	/* If a full-sized TSO skb can be sent, do it. */
+-	if (limit >= 65536)
++	if (limit >= sk->sk_gso_max_size)
+ 		goto send_now;
+ 
+ 	if (sysctl_tcp_tso_win_divisor) {
+@@ -2236,7 +2236,11 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
+ 
+ 	/* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
+ 	th->window = htons(min(req->rcv_wnd, 65535U));
+-
++#ifdef CONFIG_SYN_COOKIES
++	if (unlikely(req->cookie_ts))
++		TCP_SKB_CB(skb)->when = cookie_init_timestamp(req);
++	else
++#endif
+ 	TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ 	tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
+ 			      ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
+@@ -2571,6 +2575,7 @@ void tcp_send_probe0(struct sock *sk)
+ 	}
+ }
+ 
++EXPORT_SYMBOL(tcp_select_initial_window);
+ EXPORT_SYMBOL(tcp_connect);
+ EXPORT_SYMBOL(tcp_make_synack);
+ EXPORT_SYMBOL(tcp_simple_retransmit);
+diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
+index 87dd5bf..5ff0ce6 100644
+--- a/net/ipv4/tcp_probe.c
++++ b/net/ipv4/tcp_probe.c
+@@ -153,7 +153,7 @@ static int tcpprobe_sprint(char *tbuf, int n)
+ 		= ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start));
+ 
+ 	return snprintf(tbuf, n,
+-			"%lu.%09lu %d.%d.%d.%d:%u %d.%d.%d.%d:%u"
++			"%lu.%09lu " NIPQUAD_FMT ":%u " NIPQUAD_FMT ":%u"
+ 			" %d %#x %#x %u %u %u %u\n",
+ 			(unsigned long) tv.tv_sec,
+ 			(unsigned long) tv.tv_nsec,
+@@ -190,19 +190,18 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf,
+ 
+ 		width = tcpprobe_sprint(tbuf, sizeof(tbuf));
+ 
+-		if (width < len)
++		if (cnt + width < len)
+ 			tcp_probe.tail = (tcp_probe.tail + 1) % bufsize;
+ 
+ 		spin_unlock_bh(&tcp_probe.lock);
+ 
+ 		/* if record greater than space available
+ 		   return partial buffer (so far) */
+-		if (width >= len)
++		if (cnt + width >= len)
+ 			break;
+ 
+-		error = copy_to_user(buf + cnt, tbuf, width);
+-		if (error)
+-			break;
++		if (copy_to_user(buf + cnt, tbuf, width))
++			return -EFAULT;
+ 		cnt += width;
+ 	}
+ 
+diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
+index 803d758..4de68cf 100644
+--- a/net/ipv4/tcp_timer.c
++++ b/net/ipv4/tcp_timer.c
+@@ -299,12 +299,20 @@ static void tcp_retransmit_timer(struct sock *sk)
+ 		 * we cannot allow such beasts to hang infinitely.
+ 		 */
+ #ifdef TCP_DEBUG
+-		if (1) {
+-			struct inet_sock *inet = inet_sk(sk);
+-			LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
++		struct inet_sock *inet = inet_sk(sk);
++		if (sk->sk_family == AF_INET) {
++			LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer " NIPQUAD_FMT ":%u/%u shrinks window %u:%u. Repaired.\n",
+ 			       NIPQUAD(inet->daddr), ntohs(inet->dport),
+ 			       inet->num, tp->snd_una, tp->snd_nxt);
+ 		}
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++		else if (sk->sk_family == AF_INET6) {
++			struct ipv6_pinfo *np = inet6_sk(sk);
++			LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer " NIP6_FMT ":%u/%u shrinks window %u:%u. Repaired.\n",
++			       NIP6(np->daddr), ntohs(inet->dport),
++			       inet->num, tp->snd_una, tp->snd_nxt);
++		}
++#endif
+ #endif
+ 		if (tcp_time_stamp - tp->rcv_tstamp > TCP_RTO_MAX) {
+ 			tcp_write_err(sk);
+@@ -481,6 +489,11 @@ static void tcp_keepalive_timer (unsigned long data)
+ 		goto death;
+ 	}
+ 
++	if (tp->defer_tcp_accept.request && sk->sk_state == TCP_ESTABLISHED) {
++		tcp_send_active_reset(sk, GFP_ATOMIC);
++		goto death;
++	}
++
+ 	if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE)
+ 		goto out;
+ 
+diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
+index 978b3fd..d3b709a 100644
+--- a/net/ipv4/tunnel4.c
++++ b/net/ipv4/tunnel4.c
+@@ -136,6 +136,7 @@ static struct net_protocol tunnel4_protocol = {
+ 	.handler	=	tunnel4_rcv,
+ 	.err_handler	=	tunnel4_err,
+ 	.no_policy	=	1,
++	.netns_ok	=	1,
+ };
+ 
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+@@ -143,6 +144,7 @@ static struct net_protocol tunnel64_protocol = {
+ 	.handler	=	tunnel64_rcv,
+ 	.err_handler	=	tunnel64_err,
+ 	.no_policy	=	1,
++	.netns_ok	=	1,
+ };
+ #endif
+ 
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 1704c14..1f535e3 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -137,29 +137,28 @@ static inline int __udp_lib_lport_inuse(struct net *net, __u16 num,
+ 	struct hlist_node *node;
+ 
+ 	sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
+-		if (sk->sk_net == net && sk->sk_hash == num)
++		if (net_eq(sock_net(sk), net) && sk->sk_hash == num)
+ 			return 1;
+ 	return 0;
+ }
+ 
+ /**
+- *  __udp_lib_get_port  -  UDP/-Lite port lookup for IPv4 and IPv6
++ *  udp_lib_get_port  -  UDP/-Lite port lookup for IPv4 and IPv6
+  *
+  *  @sk:          socket struct in question
+  *  @snum:        port number to look up
+- *  @udptable:    hash list table, must be of UDP_HTABLE_SIZE
+  *  @saddr_comp:  AF-dependent comparison of bound local IP addresses
+  */
+-int __udp_lib_get_port(struct sock *sk, unsigned short snum,
+-		       struct hlist_head udptable[],
++int udp_lib_get_port(struct sock *sk, unsigned short snum,
+ 		       int (*saddr_comp)(const struct sock *sk1,
+ 					 const struct sock *sk2 )    )
+ {
++	struct hlist_head *udptable = sk->sk_prot->h.udp_hash;
+ 	struct hlist_node *node;
+ 	struct hlist_head *head;
+ 	struct sock *sk2;
+ 	int    error = 1;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 
+ 	write_lock_bh(&udp_hash_lock);
+ 
+@@ -219,7 +218,7 @@ gotit:
+ 		sk_for_each(sk2, node, head)
+ 			if (sk2->sk_hash == snum                             &&
+ 			    sk2 != sk                                        &&
+-			    sk2->sk_net == net				     &&
++			    net_eq(sock_net(sk2), net)			     &&
+ 			    (!sk2->sk_reuse        || !sk->sk_reuse)         &&
+ 			    (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
+ 			     || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
+@@ -232,7 +231,7 @@ gotit:
+ 	if (sk_unhashed(sk)) {
+ 		head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
+ 		sk_add_node(sk, head);
+-		sock_prot_inuse_add(sk->sk_prot, 1);
++		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ 	}
+ 	error = 0;
+ fail:
+@@ -240,13 +239,7 @@ fail:
+ 	return error;
+ }
+ 
+-int udp_get_port(struct sock *sk, unsigned short snum,
+-			int (*scmp)(const struct sock *, const struct sock *))
+-{
+-	return  __udp_lib_get_port(sk, snum, udp_hash, scmp);
+-}
+-
+-int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
++static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+ {
+ 	struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
+ 
+@@ -255,9 +248,9 @@ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+ 		   inet1->rcv_saddr == inet2->rcv_saddr      ));
+ }
+ 
+-static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
++int udp_v4_get_port(struct sock *sk, unsigned short snum)
+ {
+-	return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
++	return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal);
+ }
+ 
+ /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
+@@ -276,7 +269,7 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
+ 	sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
+ 		struct inet_sock *inet = inet_sk(sk);
+ 
+-		if (sk->sk_net == net && sk->sk_hash == hnum &&
++		if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&
+ 				!ipv6_only_sock(sk)) {
+ 			int score = (sk->sk_family == PF_INET ? 1 : 0);
+ 			if (inet->rcv_saddr) {
+@@ -364,7 +357,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
+ 	int harderr;
+ 	int err;
+ 
+-	sk = __udp4_lib_lookup(skb->dev->nd_net, iph->daddr, uh->dest,
++	sk = __udp4_lib_lookup(dev_net(skb->dev), iph->daddr, uh->dest,
+ 			iph->saddr, uh->source, skb->dev->ifindex, udptable);
+ 	if (sk == NULL) {
+ 		ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+@@ -614,7 +607,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 
+ 	ipc.oif = sk->sk_bound_dev_if;
+ 	if (msg->msg_controllen) {
+-		err = ip_cmsg_send(msg, &ipc);
++		err = ip_cmsg_send(sock_net(sk), msg, &ipc);
+ 		if (err)
+ 			return err;
+ 		if (ipc.opt)
+@@ -663,7 +656,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ 					       { .sport = inet->sport,
+ 						 .dport = dport } } };
+ 		security_sk_classify_flow(sk, &fl);
+-		err = ip_route_output_flow(&init_net, &rt, &fl, sk, 1);
++		err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 1);
+ 		if (err) {
+ 			if (err == -ENETUNREACH)
+ 				IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+@@ -1188,7 +1181,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+ 	if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
+ 		return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
+ 
+-	sk = __udp4_lib_lookup(skb->dev->nd_net, saddr, uh->source, daddr,
++	sk = __udp4_lib_lookup(dev_net(skb->dev), saddr, uh->source, daddr,
+ 			uh->dest, inet_iif(skb), udptable);
+ 
+ 	if (sk != NULL) {
+@@ -1228,7 +1221,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+ 	return 0;
+ 
+ short_packet:
+-	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
++	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From " NIPQUAD_FMT ":%u %d/%d to " NIPQUAD_FMT ":%u\n",
+ 		       proto == IPPROTO_UDPLITE ? "-Lite" : "",
+ 		       NIPQUAD(saddr),
+ 		       ntohs(uh->source),
+@@ -1243,7 +1236,7 @@ csum_error:
+ 	 * RFC1122: OK.  Discards the bad packet silently (as far as
+ 	 * the network is concerned, anyway) as per 4.1.3.4 (MUST).
+ 	 */
+-	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
++	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From " NIPQUAD_FMT ":%u to " NIPQUAD_FMT ":%u ulen %d\n",
+ 		       proto == IPPROTO_UDPLITE ? "-Lite" : "",
+ 		       NIPQUAD(saddr),
+ 		       ntohs(uh->source),
+@@ -1474,8 +1467,6 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
+ 
+ }
+ 
+-DEFINE_PROTO_INUSE(udp)
+-
+ struct proto udp_prot = {
+ 	.name		   = "UDP",
+ 	.owner		   = THIS_MODULE,
+@@ -1498,11 +1489,11 @@ struct proto udp_prot = {
+ 	.sysctl_wmem	   = &sysctl_udp_wmem_min,
+ 	.sysctl_rmem	   = &sysctl_udp_rmem_min,
+ 	.obj_size	   = sizeof(struct udp_sock),
++	.h.udp_hash	   = udp_hash,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_udp_setsockopt,
+ 	.compat_getsockopt = compat_udp_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(udp)
+ };
+ 
+ /* ------------------------------------------------------------------------ */
+@@ -1512,10 +1503,13 @@ static struct sock *udp_get_first(struct seq_file *seq)
+ {
+ 	struct sock *sk;
+ 	struct udp_iter_state *state = seq->private;
++	struct net *net = seq_file_net(seq);
+ 
+ 	for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
+ 		struct hlist_node *node;
+ 		sk_for_each(sk, node, state->hashtable + state->bucket) {
++			if (!net_eq(sock_net(sk), net))
++				continue;
+ 			if (sk->sk_family == state->family)
+ 				goto found;
+ 		}
+@@ -1528,12 +1522,13 @@ found:
+ static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
+ {
+ 	struct udp_iter_state *state = seq->private;
++	struct net *net = seq_file_net(seq);
+ 
+ 	do {
+ 		sk = sk_next(sk);
+ try_again:
+ 		;
+-	} while (sk && sk->sk_family != state->family);
++	} while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family));
+ 
+ 	if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
+ 		sk = sk_head(state->hashtable + state->bucket);
+@@ -1581,47 +1576,36 @@ static void udp_seq_stop(struct seq_file *seq, void *v)
+ static int udp_seq_open(struct inode *inode, struct file *file)
+ {
+ 	struct udp_seq_afinfo *afinfo = PDE(inode)->data;
+-	struct seq_file *seq;
+-	int rc = -ENOMEM;
+-	struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
++	struct udp_iter_state *s;
++	int err;
+ 
+-	if (!s)
+-		goto out;
++	err = seq_open_net(inode, file, &afinfo->seq_ops,
++			   sizeof(struct udp_iter_state));
++	if (err < 0)
++		return err;
++
++	s = ((struct seq_file *)file->private_data)->private;
+ 	s->family		= afinfo->family;
+ 	s->hashtable		= afinfo->hashtable;
+-	s->seq_ops.start	= udp_seq_start;
+-	s->seq_ops.next		= udp_seq_next;
+-	s->seq_ops.show		= afinfo->seq_show;
+-	s->seq_ops.stop		= udp_seq_stop;
+-
+-	rc = seq_open(file, &s->seq_ops);
+-	if (rc)
+-		goto out_kfree;
+-
+-	seq	     = file->private_data;
+-	seq->private = s;
+-out:
+-	return rc;
+-out_kfree:
+-	kfree(s);
+-	goto out;
++	return err;
+ }
+ 
+ /* ------------------------------------------------------------------------ */
+-int udp_proc_register(struct udp_seq_afinfo *afinfo)
++int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo)
+ {
+ 	struct proc_dir_entry *p;
+ 	int rc = 0;
+ 
+-	if (!afinfo)
+-		return -EINVAL;
+-	afinfo->seq_fops->owner		= afinfo->owner;
+-	afinfo->seq_fops->open		= udp_seq_open;
+-	afinfo->seq_fops->read		= seq_read;
+-	afinfo->seq_fops->llseek	= seq_lseek;
+-	afinfo->seq_fops->release	= seq_release_private;
++	afinfo->seq_fops.open		= udp_seq_open;
++	afinfo->seq_fops.read		= seq_read;
++	afinfo->seq_fops.llseek		= seq_lseek;
++	afinfo->seq_fops.release	= seq_release_net;
++
++	afinfo->seq_ops.start		= udp_seq_start;
++	afinfo->seq_ops.next		= udp_seq_next;
++	afinfo->seq_ops.stop		= udp_seq_stop;
+ 
+-	p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
++	p = proc_net_fops_create(net, afinfo->name, S_IRUGO, &afinfo->seq_fops);
+ 	if (p)
+ 		p->data = afinfo;
+ 	else
+@@ -1629,16 +1613,14 @@ int udp_proc_register(struct udp_seq_afinfo *afinfo)
+ 	return rc;
+ }
+ 
+-void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
++void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo)
+ {
+-	if (!afinfo)
+-		return;
+-	proc_net_remove(&init_net, afinfo->name);
+-	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
++	proc_net_remove(net, afinfo->name);
+ }
+ 
+ /* ------------------------------------------------------------------------ */
+-static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
++static void udp4_format_sock(struct sock *sp, struct seq_file *f,
++		int bucket, int *len)
+ {
+ 	struct inet_sock *inet = inet_sk(sp);
+ 	__be32 dest = inet->daddr;
+@@ -1646,13 +1628,13 @@ static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
+ 	__u16 destp	  = ntohs(inet->dport);
+ 	__u16 srcp	  = ntohs(inet->sport);
+ 
+-	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+-		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
++	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
++		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p%n",
+ 		bucket, src, srcp, dest, destp, sp->sk_state,
+ 		atomic_read(&sp->sk_wmem_alloc),
+ 		atomic_read(&sp->sk_rmem_alloc),
+ 		0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
+-		atomic_read(&sp->sk_refcnt), sp);
++		atomic_read(&sp->sk_refcnt), sp, len);
+ }
+ 
+ int udp4_seq_show(struct seq_file *seq, void *v)
+@@ -1663,34 +1645,51 @@ int udp4_seq_show(struct seq_file *seq, void *v)
+ 			   "rx_queue tr tm->when retrnsmt   uid  timeout "
+ 			   "inode");
+ 	else {
+-		char tmpbuf[129];
+ 		struct udp_iter_state *state = seq->private;
++		int len;
+ 
+-		udp4_format_sock(v, tmpbuf, state->bucket);
+-		seq_printf(seq, "%-127s\n", tmpbuf);
++		udp4_format_sock(v, seq, state->bucket, &len);
++		seq_printf(seq, "%*s\n", 127 - len ,"");
+ 	}
+ 	return 0;
+ }
+ 
+ /* ------------------------------------------------------------------------ */
+-static struct file_operations udp4_seq_fops;
+ static struct udp_seq_afinfo udp4_seq_afinfo = {
+-	.owner		= THIS_MODULE,
+ 	.name		= "udp",
+ 	.family		= AF_INET,
+ 	.hashtable	= udp_hash,
+-	.seq_show	= udp4_seq_show,
+-	.seq_fops	= &udp4_seq_fops,
++	.seq_fops	= {
++		.owner	=	THIS_MODULE,
++	},
++	.seq_ops	= {
++		.show		= udp4_seq_show,
++	},
++};
++
++static int udp4_proc_init_net(struct net *net)
++{
++	return udp_proc_register(net, &udp4_seq_afinfo);
++}
++
++static void udp4_proc_exit_net(struct net *net)
++{
++	udp_proc_unregister(net, &udp4_seq_afinfo);
++}
++
++static struct pernet_operations udp4_net_ops = {
++	.init = udp4_proc_init_net,
++	.exit = udp4_proc_exit_net,
+ };
+ 
+ int __init udp4_proc_init(void)
+ {
+-	return udp_proc_register(&udp4_seq_afinfo);
++	return register_pernet_subsys(&udp4_net_ops);
+ }
+ 
+ void udp4_proc_exit(void)
+ {
+-	udp_proc_unregister(&udp4_seq_afinfo);
++	unregister_pernet_subsys(&udp4_net_ops);
+ }
+ #endif /* CONFIG_PROC_FS */
+ 
+@@ -1717,12 +1716,12 @@ EXPORT_SYMBOL(udp_disconnect);
+ EXPORT_SYMBOL(udp_hash);
+ EXPORT_SYMBOL(udp_hash_lock);
+ EXPORT_SYMBOL(udp_ioctl);
+-EXPORT_SYMBOL(udp_get_port);
+ EXPORT_SYMBOL(udp_prot);
+ EXPORT_SYMBOL(udp_sendmsg);
+ EXPORT_SYMBOL(udp_lib_getsockopt);
+ EXPORT_SYMBOL(udp_lib_setsockopt);
+ EXPORT_SYMBOL(udp_poll);
++EXPORT_SYMBOL(udp_lib_get_port);
+ 
+ #ifdef CONFIG_PROC_FS
+ EXPORT_SYMBOL(udp_proc_register);
+diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
+index 6c55828..7288bf7 100644
+--- a/net/ipv4/udp_impl.h
++++ b/net/ipv4/udp_impl.h
+@@ -8,11 +8,7 @@
+ extern int  	__udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
+ extern void 	__udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
+ 
+-extern int	__udp_lib_get_port(struct sock *sk, unsigned short snum,
+-				   struct hlist_head udptable[],
+-				   int (*)(const struct sock*,const struct sock*));
+-extern int	ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
+-
++extern int	udp_v4_get_port(struct sock *sk, unsigned short snum);
+ 
+ extern int	udp_setsockopt(struct sock *sk, int level, int optname,
+ 			       char __user *optval, int optlen);
+diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
+index 001b881..72ce26b 100644
+--- a/net/ipv4/udplite.c
++++ b/net/ipv4/udplite.c
+@@ -17,17 +17,6 @@ DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics)	__read_mostly;
+ 
+ struct hlist_head 	udplite_hash[UDP_HTABLE_SIZE];
+ 
+-int udplite_get_port(struct sock *sk, unsigned short p,
+-		     int (*c)(const struct sock *, const struct sock *))
+-{
+-	return  __udp_lib_get_port(sk, p, udplite_hash, c);
+-}
+-
+-static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
+-{
+-	return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
+-}
+-
+ static int udplite_rcv(struct sk_buff *skb)
+ {
+ 	return __udp4_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE);
+@@ -42,10 +31,9 @@ static	struct net_protocol udplite_protocol = {
+ 	.handler	= udplite_rcv,
+ 	.err_handler	= udplite_err,
+ 	.no_policy	= 1,
++	.netns_ok	= 1,
+ };
+ 
+-DEFINE_PROTO_INUSE(udplite)
+-
+ struct proto 	udplite_prot = {
+ 	.name		   = "UDP-Lite",
+ 	.owner		   = THIS_MODULE,
+@@ -63,13 +51,13 @@ struct proto 	udplite_prot = {
+ 	.backlog_rcv	   = udp_queue_rcv_skb,
+ 	.hash		   = udp_lib_hash,
+ 	.unhash		   = udp_lib_unhash,
+-	.get_port	   = udplite_v4_get_port,
++	.get_port	   = udp_v4_get_port,
+ 	.obj_size	   = sizeof(struct udp_sock),
++	.h.udp_hash	   = udplite_hash,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_udp_setsockopt,
+ 	.compat_getsockopt = compat_udp_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(udplite)
+ };
+ 
+ static struct inet_protosw udplite4_protosw = {
+@@ -83,15 +71,42 @@ static struct inet_protosw udplite4_protosw = {
+ };
+ 
+ #ifdef CONFIG_PROC_FS
+-static struct file_operations udplite4_seq_fops;
+ static struct udp_seq_afinfo udplite4_seq_afinfo = {
+-	.owner		= THIS_MODULE,
+ 	.name		= "udplite",
+ 	.family		= AF_INET,
+ 	.hashtable	= udplite_hash,
+-	.seq_show	= udp4_seq_show,
+-	.seq_fops	= &udplite4_seq_fops,
++	.seq_fops	= {
++		.owner	=	THIS_MODULE,
++	},
++	.seq_ops	= {
++		.show		= udp4_seq_show,
++	},
++};
++
++static int udplite4_proc_init_net(struct net *net)
++{
++	return udp_proc_register(net, &udplite4_seq_afinfo);
++}
++
++static void udplite4_proc_exit_net(struct net *net)
++{
++	udp_proc_unregister(net, &udplite4_seq_afinfo);
++}
++
++static struct pernet_operations udplite4_net_ops = {
++	.init = udplite4_proc_init_net,
++	.exit = udplite4_proc_exit_net,
+ };
++
++static __init int udplite4_proc_init(void)
++{
++	return register_pernet_subsys(&udplite4_net_ops);
++}
++#else
++static inline int udplite4_proc_init(void)
++{
++	return 0;
++}
+ #endif
+ 
+ void __init udplite4_register(void)
+@@ -104,18 +119,15 @@ void __init udplite4_register(void)
+ 
+ 	inet_register_protosw(&udplite4_protosw);
+ 
+-#ifdef CONFIG_PROC_FS
+-	if (udp_proc_register(&udplite4_seq_afinfo)) /* udplite4_proc_init() */
+-		printk(KERN_ERR "%s: Cannot register /proc!\n", __FUNCTION__);
+-#endif
++	if (udplite4_proc_init())
++		printk(KERN_ERR "%s: Cannot register /proc!\n", __func__);
+ 	return;
+ 
+ out_unregister_proto:
+ 	proto_unregister(&udplite_prot);
+ out_register_err:
+-	printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __FUNCTION__);
++	printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __func__);
+ }
+ 
+ EXPORT_SYMBOL(udplite_hash);
+ EXPORT_SYMBOL(udplite_prot);
+-EXPORT_SYMBOL(udplite_get_port);
+diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
+index 10ed704..c63de0a 100644
+--- a/net/ipv4/xfrm4_policy.c
++++ b/net/ipv4/xfrm4_policy.c
+@@ -221,7 +221,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ 	xdst = (struct xfrm_dst *)dst;
+ 	if (xdst->u.rt.idev->dev == dev) {
+ 		struct in_device *loopback_idev =
+-			in_dev_get(dev->nd_net->loopback_dev);
++			in_dev_get(dev_net(dev)->loopback_dev);
+ 		BUG_ON(!loopback_idev);
+ 
+ 		do {
+diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
+index 47263e4..b2c9bec 100644
+--- a/net/ipv6/Kconfig
++++ b/net/ipv6/Kconfig
+@@ -3,7 +3,7 @@
+ #
+ 
+ #   IPv6 as module will cause a CRASH if you try to unload it
+-config IPV6
++menuconfig IPV6
+ 	tristate "The IPv6 protocol"
+ 	default m
+ 	---help---
+@@ -19,9 +19,10 @@ config IPV6
+ 	  To compile this protocol support as a module, choose M here: the 
+ 	  module will be called ipv6.
+ 
++if IPV6
++
+ config IPV6_PRIVACY
+ 	bool "IPv6: Privacy Extensions support"
+-	depends on IPV6
+ 	---help---
+ 	  Privacy Extensions for Stateless Address Autoconfiguration in IPv6
+ 	  support.  With this option, additional periodically-alter 
+@@ -40,7 +41,6 @@ config IPV6_PRIVACY
+ 
+ config IPV6_ROUTER_PREF
+ 	bool "IPv6: Router Preference (RFC 4191) support"
+-	depends on IPV6
+ 	---help---
+ 	  Router Preference is an optional extension to the Router
+ 	  Advertisement message to improve the ability of hosts
+@@ -59,7 +59,7 @@ config IPV6_ROUTE_INFO
+ 
+ config IPV6_OPTIMISTIC_DAD
+ 	bool "IPv6: Enable RFC 4429 Optimistic DAD (EXPERIMENTAL)"
+-	depends on IPV6 && EXPERIMENTAL
++	depends on EXPERIMENTAL
+ 	---help---
+ 	  This is experimental support for optimistic Duplicate
+ 	  Address Detection.  It allows for autoconfigured addresses
+@@ -69,7 +69,6 @@ config IPV6_OPTIMISTIC_DAD
+ 
+ config INET6_AH
+ 	tristate "IPv6: AH transformation"
+-	depends on IPV6
+ 	select XFRM
+ 	select CRYPTO
+ 	select CRYPTO_HMAC
+@@ -82,7 +81,6 @@ config INET6_AH
+ 
+ config INET6_ESP
+ 	tristate "IPv6: ESP transformation"
+-	depends on IPV6
+ 	select XFRM
+ 	select CRYPTO
+ 	select CRYPTO_AUTHENC
+@@ -98,7 +96,6 @@ config INET6_ESP
+ 
+ config INET6_IPCOMP
+ 	tristate "IPv6: IPComp transformation"
+-	depends on IPV6
+ 	select XFRM
+ 	select INET6_XFRM_TUNNEL
+ 	select CRYPTO
+@@ -111,7 +108,7 @@ config INET6_IPCOMP
+ 
+ config IPV6_MIP6
+ 	tristate "IPv6: Mobility (EXPERIMENTAL)"
+-	depends on IPV6 && EXPERIMENTAL
++	depends on EXPERIMENTAL
+ 	select XFRM
+ 	---help---
+ 	  Support for IPv6 Mobility described in RFC 3775.
+@@ -129,7 +126,6 @@ config INET6_TUNNEL
+ 
+ config INET6_XFRM_MODE_TRANSPORT
+ 	tristate "IPv6: IPsec transport mode"
+-	depends on IPV6
+ 	default IPV6
+ 	select XFRM
+ 	---help---
+@@ -139,7 +135,6 @@ config INET6_XFRM_MODE_TRANSPORT
+ 
+ config INET6_XFRM_MODE_TUNNEL
+ 	tristate "IPv6: IPsec tunnel mode"
+-	depends on IPV6
+ 	default IPV6
+ 	select XFRM
+ 	---help---
+@@ -149,7 +144,6 @@ config INET6_XFRM_MODE_TUNNEL
+ 
+ config INET6_XFRM_MODE_BEET
+ 	tristate "IPv6: IPsec BEET mode"
+-	depends on IPV6
+ 	default IPV6
+ 	select XFRM
+ 	---help---
+@@ -159,29 +153,31 @@ config INET6_XFRM_MODE_BEET
+ 
+ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
+ 	tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)"
+-	depends on IPV6 && EXPERIMENTAL
++	depends on EXPERIMENTAL
+ 	select XFRM
+ 	---help---
+ 	  Support for MIPv6 route optimization mode.
+ 
+ config IPV6_SIT
+ 	tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
+-	depends on IPV6
+ 	select INET_TUNNEL
++	select IPV6_NDISC_NODETYPE
+ 	default y
+ 	---help---
+ 	  Tunneling means encapsulating data of one protocol type within
+ 	  another protocol and sending it over a channel that understands the
+ 	  encapsulating protocol. This driver implements encapsulation of IPv6
+-	  into IPv4 packets. This is useful if you want to connect two IPv6
++	  into IPv4 packets. This is useful if you want to connect to IPv6
+ 	  networks over an IPv4-only path.
+ 
+ 	  Saying M here will produce a module called sit.ko. If unsure, say Y.
+ 
++config IPV6_NDISC_NODETYPE
++	bool
++
+ config IPV6_TUNNEL
+ 	tristate "IPv6: IP-in-IPv6 tunnel (RFC2473)"
+ 	select INET6_TUNNEL
+-	depends on IPV6
+ 	---help---
+ 	  Support for IPv6-in-IPv6 and IPv4-in-IPv6 tunnels described in
+ 	  RFC 2473.
+@@ -190,7 +186,7 @@ config IPV6_TUNNEL
+ 
+ config IPV6_MULTIPLE_TABLES
+ 	bool "IPv6: Multiple Routing Tables"
+-	depends on IPV6 && EXPERIMENTAL
++	depends on EXPERIMENTAL
+ 	select FIB_RULES
+ 	---help---
+ 	  Support multiple routing tables.
+@@ -209,3 +205,18 @@ config IPV6_SUBTREES
+ 
+ 	  If unsure, say N.
+ 
++config IPV6_MROUTE
++	bool "IPv6: multicast routing (EXPERIMENTAL)"
++	depends on IPV6 && EXPERIMENTAL
++	---help---
++	  Experimental support for IPv6 multicast forwarding.
++	  If unsure, say N.
++
++config IPV6_PIMSM_V2
++	bool "IPv6: PIM-SM version 2 support (EXPERIMENTAL)"
++	depends on IPV6_MROUTE
++	---help---
++	  Support for IPv6 PIM multicast routing protocol PIM-SMv2.
++	  If unsure, say N.
++
++endif # IPV6
+diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
+index 24f3aa0..686934a 100644
+--- a/net/ipv6/Makefile
++++ b/net/ipv6/Makefile
+@@ -11,11 +11,14 @@ ipv6-objs :=	af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
+ 		exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o
+ 
+ ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o
++ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o
++
+ ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
+ 	xfrm6_output.o
+ ipv6-$(CONFIG_NETFILTER) += netfilter.o
+ ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
+ ipv6-$(CONFIG_PROC_FS) += proc.o
++ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
+ 
+ ipv6-objs += $(ipv6-y)
+ 
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index e08955b..e591e09 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -222,6 +222,8 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
+ /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
+ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+ const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
++const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
++const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
+ 
+ /* Check if a valid qdisc is available */
+ static inline int addrconf_qdisc_ok(struct net_device *dev)
+@@ -321,7 +323,6 @@ EXPORT_SYMBOL(in6_dev_finish_destroy);
+ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+ {
+ 	struct inet6_dev *ndev;
+-	struct in6_addr maddr;
+ 
+ 	ASSERT_RTNL();
+ 
+@@ -335,7 +336,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+ 
+ 	rwlock_init(&ndev->lock);
+ 	ndev->dev = dev;
+-	memcpy(&ndev->cnf, dev->nd_net->ipv6.devconf_dflt, sizeof(ndev->cnf));
++	memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
+ 	ndev->cnf.mtu6 = dev->mtu;
+ 	ndev->cnf.sysctl = NULL;
+ 	ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
+@@ -349,7 +350,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+ 	if (snmp6_alloc_dev(ndev) < 0) {
+ 		ADBG((KERN_WARNING
+ 			"%s(): cannot allocate memory for statistics; dev=%s.\n",
+-			__FUNCTION__, dev->name));
++			__func__, dev->name));
+ 		neigh_parms_release(&nd_tbl, ndev->nd_parms);
+ 		ndev->dead = 1;
+ 		in6_dev_finish_destroy(ndev);
+@@ -359,7 +360,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+ 	if (snmp6_register_dev(ndev) < 0) {
+ 		ADBG((KERN_WARNING
+ 			"%s(): cannot create /proc/net/dev_snmp6/%s\n",
+-			__FUNCTION__, dev->name));
++			__func__, dev->name));
+ 		neigh_parms_release(&nd_tbl, ndev->nd_parms);
+ 		ndev->dead = 1;
+ 		in6_dev_finish_destroy(ndev);
+@@ -407,8 +408,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+ 	rcu_assign_pointer(dev->ip6_ptr, ndev);
+ 
+ 	/* Join all-node multicast group */
+-	ipv6_addr_all_nodes(&maddr);
+-	ipv6_dev_mc_inc(dev, &maddr);
++	ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes);
+ 
+ 	return ndev;
+ }
+@@ -434,18 +434,15 @@ static void dev_forward_change(struct inet6_dev *idev)
+ {
+ 	struct net_device *dev;
+ 	struct inet6_ifaddr *ifa;
+-	struct in6_addr addr;
+ 
+ 	if (!idev)
+ 		return;
+ 	dev = idev->dev;
+ 	if (dev && (dev->flags & IFF_MULTICAST)) {
+-		ipv6_addr_all_routers(&addr);
+-
+ 		if (idev->cnf.forwarding)
+-			ipv6_dev_mc_inc(dev, &addr);
++			ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
+ 		else
+-			ipv6_dev_mc_dec(dev, &addr);
++			ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters);
+ 	}
+ 	for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
+ 		if (ifa->flags&IFA_F_TENTATIVE)
+@@ -494,7 +491,7 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
+ 		dev_forward_change((struct inet6_dev *)table->extra1);
+ 
+ 	if (*p)
+-		rt6_purge_dflt_routers();
++		rt6_purge_dflt_routers(net);
+ }
+ #endif
+ 
+@@ -542,6 +539,25 @@ ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
+ 	*ifap = ifp;
+ }
+ 
++/*
++ *	Hash function taken from net_alias.c
++ */
++static u8 ipv6_addr_hash(const struct in6_addr *addr)
++{
++	__u32 word;
++
++	/*
++	 * We perform the hash function over the last 64 bits of the address
++	 * This will include the IEEE address token on links that support it.
++	 */
++
++	word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]);
++	word ^= (word >> 16);
++	word ^= (word >> 8);
++
++	return ((word ^ (word >> 4)) & 0x0f);
++}
++
+ /* On success it returns ifp with increased reference count */
+ 
+ static struct inet6_ifaddr *
+@@ -562,7 +578,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
+ 	write_lock(&addrconf_hash_lock);
+ 
+ 	/* Ignore adding duplicate addresses on an interface */
+-	if (ipv6_chk_same_addr(&init_net, addr, idev->dev)) {
++	if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) {
+ 		ADBG(("ipv6_add_addr: already assigned\n"));
+ 		err = -EEXIST;
+ 		goto out;
+@@ -752,9 +768,9 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
+ 	if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
+ 		struct in6_addr prefix;
+ 		struct rt6_info *rt;
+-
++		struct net *net = dev_net(ifp->idev->dev);
+ 		ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
+-		rt = rt6_lookup(&prefix, NULL, ifp->idev->dev->ifindex, 1);
++		rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1);
+ 
+ 		if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
+ 			if (onlink == 0) {
+@@ -894,20 +910,40 @@ out:
+ /*
+  *	Choose an appropriate source address (RFC3484)
+  */
++enum {
++	IPV6_SADDR_RULE_INIT = 0,
++	IPV6_SADDR_RULE_LOCAL,
++	IPV6_SADDR_RULE_SCOPE,
++	IPV6_SADDR_RULE_PREFERRED,
++#ifdef CONFIG_IPV6_MIP6
++	IPV6_SADDR_RULE_HOA,
++#endif
++	IPV6_SADDR_RULE_OIF,
++	IPV6_SADDR_RULE_LABEL,
++#ifdef CONFIG_IPV6_PRIVACY
++	IPV6_SADDR_RULE_PRIVACY,
++#endif
++	IPV6_SADDR_RULE_ORCHID,
++	IPV6_SADDR_RULE_PREFIX,
++	IPV6_SADDR_RULE_MAX
++};
++
+ struct ipv6_saddr_score {
+-	int		addr_type;
+-	unsigned int	attrs;
+-	int		matchlen;
+-	int		scope;
+-	unsigned int	rule;
++	int			rule;
++	int			addr_type;
++	struct inet6_ifaddr	*ifa;
++	DECLARE_BITMAP(scorebits, IPV6_SADDR_RULE_MAX);
++	int			scopedist;
++	int			matchlen;
+ };
+ 
+-#define IPV6_SADDR_SCORE_LOCAL		0x0001
+-#define IPV6_SADDR_SCORE_PREFERRED	0x0004
+-#define IPV6_SADDR_SCORE_HOA		0x0008
+-#define IPV6_SADDR_SCORE_OIF		0x0010
+-#define IPV6_SADDR_SCORE_LABEL		0x0020
+-#define IPV6_SADDR_SCORE_PRIVACY	0x0040
++struct ipv6_saddr_dst {
++	const struct in6_addr *addr;
++	int ifindex;
++	int scope;
++	int label;
++	unsigned int prefs;
++};
+ 
+ static inline int ipv6_saddr_preferred(int type)
+ {
+@@ -917,27 +953,152 @@ static inline int ipv6_saddr_preferred(int type)
+ 	return 0;
+ }
+ 
+-int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+-		       struct in6_addr *daddr, struct in6_addr *saddr)
++static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score,
++			       struct ipv6_saddr_dst *dst,
++			       int i)
+ {
+-	struct ipv6_saddr_score hiscore;
+-	struct inet6_ifaddr *ifa_result = NULL;
+-	int daddr_type = __ipv6_addr_type(daddr);
+-	int daddr_scope = __ipv6_addr_src_scope(daddr_type);
+-	int daddr_ifindex = daddr_dev ? daddr_dev->ifindex : 0;
+-	u32 daddr_label = ipv6_addr_label(daddr, daddr_type, daddr_ifindex);
++	int ret;
++
++	if (i <= score->rule) {
++		switch (i) {
++		case IPV6_SADDR_RULE_SCOPE:
++			ret = score->scopedist;
++			break;
++		case IPV6_SADDR_RULE_PREFIX:
++			ret = score->matchlen;
++			break;
++		default:
++			ret = !!test_bit(i, score->scorebits);
++		}
++		goto out;
++	}
++
++	switch (i) {
++	case IPV6_SADDR_RULE_INIT:
++		/* Rule 0: remember if hiscore is not ready yet */
++		ret = !!score->ifa;
++		break;
++	case IPV6_SADDR_RULE_LOCAL:
++		/* Rule 1: Prefer same address */
++		ret = ipv6_addr_equal(&score->ifa->addr, dst->addr);
++		break;
++	case IPV6_SADDR_RULE_SCOPE:
++		/* Rule 2: Prefer appropriate scope
++		 *
++		 *      ret
++		 *       ^
++		 *    -1 |  d 15
++		 *    ---+--+-+---> scope
++		 *       |
++		 *       |             d is scope of the destination.
++		 *  B-d  |  \
++		 *       |   \      <- smaller scope is better if
++		 *  B-15 |    \        if scope is enough for destinaion.
++		 *       |             ret = B - scope (-1 <= scope >= d <= 15).
++		 * d-C-1 | /
++		 *       |/         <- greater is better
++		 *   -C  /             if scope is not enough for destination.
++		 *      /|             ret = scope - C (-1 <= d < scope <= 15).
++		 *
++		 * d - C - 1 < B -15 (for all -1 <= d <= 15).
++		 * C > d + 14 - B >= 15 + 14 - B = 29 - B.
++		 * Assume B = 0 and we get C > 29.
++		 */
++		ret = __ipv6_addr_src_scope(score->addr_type);
++		if (ret >= dst->scope)
++			ret = -ret;
++		else
++			ret -= 128;	/* 30 is enough */
++		score->scopedist = ret;
++		break;
++	case IPV6_SADDR_RULE_PREFERRED:
++		/* Rule 3: Avoid deprecated and optimistic addresses */
++		ret = ipv6_saddr_preferred(score->addr_type) ||
++		      !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC));
++		break;
++#ifdef CONFIG_IPV6_MIP6
++	case IPV6_SADDR_RULE_HOA:
++	    {
++		/* Rule 4: Prefer home address */
++		int prefhome = !(dst->prefs & IPV6_PREFER_SRC_COA);
++		ret = !(score->ifa->flags & IFA_F_HOMEADDRESS) ^ prefhome;
++		break;
++	    }
++#endif
++	case IPV6_SADDR_RULE_OIF:
++		/* Rule 5: Prefer outgoing interface */
++		ret = (!dst->ifindex ||
++		       dst->ifindex == score->ifa->idev->dev->ifindex);
++		break;
++	case IPV6_SADDR_RULE_LABEL:
++		/* Rule 6: Prefer matching label */
++		ret = ipv6_addr_label(&score->ifa->addr, score->addr_type,
++				      score->ifa->idev->dev->ifindex) == dst->label;
++		break;
++#ifdef CONFIG_IPV6_PRIVACY
++	case IPV6_SADDR_RULE_PRIVACY:
++	    {
++		/* Rule 7: Prefer public address
++		 * Note: prefer temprary address if use_tempaddr >= 2
++		 */
++		int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ?
++				!!(dst->prefs & IPV6_PREFER_SRC_TMP) :
++				score->ifa->idev->cnf.use_tempaddr >= 2;
++		ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ preftmp;
++		break;
++	    }
++#endif
++	case IPV6_SADDR_RULE_ORCHID:
++		/* Rule 8-: Prefer ORCHID vs ORCHID or
++		 *	    non-ORCHID vs non-ORCHID
++		 */
++		ret = !(ipv6_addr_orchid(&score->ifa->addr) ^
++			ipv6_addr_orchid(dst->addr));
++		break;
++	case IPV6_SADDR_RULE_PREFIX:
++		/* Rule 8: Use longest matching prefix */
++		score->matchlen = ret = ipv6_addr_diff(&score->ifa->addr,
++						       dst->addr);
++		break;
++	default:
++		ret = 0;
++	}
++
++	if (ret)
++		__set_bit(i, score->scorebits);
++	score->rule = i;
++out:
++	return ret;
++}
++
++int ipv6_dev_get_saddr(struct net_device *dst_dev,
++		       const struct in6_addr *daddr, unsigned int prefs,
++		       struct in6_addr *saddr)
++{
++	struct ipv6_saddr_score scores[2],
++				*score = &scores[0], *hiscore = &scores[1];
++	struct net *net = dev_net(dst_dev);
++	struct ipv6_saddr_dst dst;
+ 	struct net_device *dev;
++	int dst_type;
+ 
+-	memset(&hiscore, 0, sizeof(hiscore));
++	dst_type = __ipv6_addr_type(daddr);
++	dst.addr = daddr;
++	dst.ifindex = dst_dev ? dst_dev->ifindex : 0;
++	dst.scope = __ipv6_addr_src_scope(dst_type);
++	dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex);
++	dst.prefs = prefs;
++
++	hiscore->rule = -1;
++	hiscore->ifa = NULL;
+ 
+ 	read_lock(&dev_base_lock);
+ 	rcu_read_lock();
+ 
+-	for_each_netdev(&init_net, dev) {
++	for_each_netdev(net, dev) {
+ 		struct inet6_dev *idev;
+-		struct inet6_ifaddr *ifa;
+ 
+-		/* Rule 0: Candidate Source Address (section 4)
++		/* Candidate Source Address (section 4)
+ 		 *  - multicast and link-local destination address,
+ 		 *    the set of candidate source address MUST only
+ 		 *    include addresses assigned to interfaces
+@@ -949,9 +1110,9 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ 		 *    belonging to the same site as the outgoing
+ 		 *    interface.)
+ 		 */
+-		if ((daddr_type & IPV6_ADDR_MULTICAST ||
+-		     daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
+-		    daddr_dev && dev != daddr_dev)
++		if (((dst_type & IPV6_ADDR_MULTICAST) ||
++		     dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
++		    dst.ifindex && dev->ifindex != dst.ifindex)
+ 			continue;
+ 
+ 		idev = __in6_dev_get(dev);
+@@ -959,12 +1120,10 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ 			continue;
+ 
+ 		read_lock_bh(&idev->lock);
+-		for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) {
+-			struct ipv6_saddr_score score;
++		for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) {
++			int i;
+ 
+-			score.addr_type = __ipv6_addr_type(&ifa->addr);
+-
+-			/* Rule 0:
++			/*
+ 			 * - Tentative Address (RFC2462 section 5.4)
+ 			 *  - A tentative address is not considered
+ 			 *    "assigned to an interface" in the traditional
+@@ -974,11 +1133,14 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ 			 *    addresses, and the unspecified address MUST
+ 			 *    NOT be included in a candidate set.
+ 			 */
+-			if ((ifa->flags & IFA_F_TENTATIVE) &&
+-			    (!(ifa->flags & IFA_F_OPTIMISTIC)))
++			if ((score->ifa->flags & IFA_F_TENTATIVE) &&
++			    (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
+ 				continue;
+-			if (unlikely(score.addr_type == IPV6_ADDR_ANY ||
+-				     score.addr_type & IPV6_ADDR_MULTICAST)) {
++
++			score->addr_type = __ipv6_addr_type(&score->ifa->addr);
++
++			if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
++				     score->addr_type & IPV6_ADDR_MULTICAST)) {
+ 				LIMIT_NETDEBUG(KERN_DEBUG
+ 					       "ADDRCONF: unspecified / multicast address "
+ 					       "assigned as unicast address on %s",
+@@ -986,207 +1148,63 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ 				continue;
+ 			}
+ 
+-			score.attrs = 0;
+-			score.matchlen = 0;
+-			score.scope = 0;
+-			score.rule = 0;
+-
+-			if (ifa_result == NULL) {
+-				/* record it if the first available entry */
+-				goto record_it;
+-			}
+-
+-			/* Rule 1: Prefer same address */
+-			if (hiscore.rule < 1) {
+-				if (ipv6_addr_equal(&ifa_result->addr, daddr))
+-					hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL;
+-				hiscore.rule++;
+-			}
+-			if (ipv6_addr_equal(&ifa->addr, daddr)) {
+-				score.attrs |= IPV6_SADDR_SCORE_LOCAL;
+-				if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) {
+-					score.rule = 1;
+-					goto record_it;
+-				}
+-			} else {
+-				if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)
+-					continue;
+-			}
+-
+-			/* Rule 2: Prefer appropriate scope */
+-			if (hiscore.rule < 2) {
+-				hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type);
+-				hiscore.rule++;
+-			}
+-			score.scope = __ipv6_addr_src_scope(score.addr_type);
+-			if (hiscore.scope < score.scope) {
+-				if (hiscore.scope < daddr_scope) {
+-					score.rule = 2;
+-					goto record_it;
+-				} else
+-					continue;
+-			} else if (score.scope < hiscore.scope) {
+-				if (score.scope < daddr_scope)
+-					break; /* addresses sorted by scope */
+-				else {
+-					score.rule = 2;
+-					goto record_it;
+-				}
+-			}
++			score->rule = -1;
++			bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
++
++			for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
++				int minihiscore, miniscore;
++
++				minihiscore = ipv6_get_saddr_eval(hiscore, &dst, i);
++				miniscore = ipv6_get_saddr_eval(score, &dst, i);
++
++				if (minihiscore > miniscore) {
++					if (i == IPV6_SADDR_RULE_SCOPE &&
++					    score->scopedist > 0) {
++						/*
++						 * special case:
++						 * each remaining entry
++						 * has too small (not enough)
++						 * scope, because ifa entries
++						 * are sorted by their scope
++						 * values.
++						 */
++						goto try_nextdev;
++					}
++					break;
++				} else if (minihiscore < miniscore) {
++					struct ipv6_saddr_score *tmp;
+ 
+-			/* Rule 3: Avoid deprecated and optimistic addresses */
+-			if (hiscore.rule < 3) {
+-				if (ipv6_saddr_preferred(hiscore.addr_type) ||
+-				   (((ifa_result->flags &
+-				    (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0)))
+-					hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED;
+-				hiscore.rule++;
+-			}
+-			if (ipv6_saddr_preferred(score.addr_type) ||
+-			   (((ifa->flags &
+-			    (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) {
+-				score.attrs |= IPV6_SADDR_SCORE_PREFERRED;
+-				if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) {
+-					score.rule = 3;
+-					goto record_it;
+-				}
+-			} else {
+-				if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)
+-					continue;
+-			}
++					if (hiscore->ifa)
++						in6_ifa_put(hiscore->ifa);
+ 
+-			/* Rule 4: Prefer home address */
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+-			if (hiscore.rule < 4) {
+-				if (ifa_result->flags & IFA_F_HOMEADDRESS)
+-					hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
+-				hiscore.rule++;
+-			}
+-			if (ifa->flags & IFA_F_HOMEADDRESS) {
+-				score.attrs |= IPV6_SADDR_SCORE_HOA;
+-				if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) {
+-					score.rule = 4;
+-					goto record_it;
+-				}
+-			} else {
+-				if (hiscore.attrs & IPV6_SADDR_SCORE_HOA)
+-					continue;
+-			}
+-#else
+-			if (hiscore.rule < 4)
+-				hiscore.rule++;
+-#endif
++					in6_ifa_hold(score->ifa);
+ 
+-			/* Rule 5: Prefer outgoing interface */
+-			if (hiscore.rule < 5) {
+-				if (daddr_dev == NULL ||
+-				    daddr_dev == ifa_result->idev->dev)
+-					hiscore.attrs |= IPV6_SADDR_SCORE_OIF;
+-				hiscore.rule++;
+-			}
+-			if (daddr_dev == NULL ||
+-			    daddr_dev == ifa->idev->dev) {
+-				score.attrs |= IPV6_SADDR_SCORE_OIF;
+-				if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) {
+-					score.rule = 5;
+-					goto record_it;
+-				}
+-			} else {
+-				if (hiscore.attrs & IPV6_SADDR_SCORE_OIF)
+-					continue;
+-			}
++					tmp = hiscore;
++					hiscore = score;
++					score = tmp;
+ 
+-			/* Rule 6: Prefer matching label */
+-			if (hiscore.rule < 6) {
+-				if (ipv6_addr_label(&ifa_result->addr,
+-						    hiscore.addr_type,
+-						    ifa_result->idev->dev->ifindex) == daddr_label)
+-					hiscore.attrs |= IPV6_SADDR_SCORE_LABEL;
+-				hiscore.rule++;
+-			}
+-			if (ipv6_addr_label(&ifa->addr,
+-					    score.addr_type,
+-					    ifa->idev->dev->ifindex) == daddr_label) {
+-				score.attrs |= IPV6_SADDR_SCORE_LABEL;
+-				if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) {
+-					score.rule = 6;
+-					goto record_it;
+-				}
+-			} else {
+-				if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL)
+-					continue;
+-			}
++					/* restore our iterator */
++					score->ifa = hiscore->ifa;
+ 
+-#ifdef CONFIG_IPV6_PRIVACY
+-			/* Rule 7: Prefer public address
+-			 * Note: prefer temprary address if use_tempaddr >= 2
+-			 */
+-			if (hiscore.rule < 7) {
+-				if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^
+-				    (ifa_result->idev->cnf.use_tempaddr >= 2))
+-					hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY;
+-				hiscore.rule++;
+-			}
+-			if ((!(ifa->flags & IFA_F_TEMPORARY)) ^
+-			    (ifa->idev->cnf.use_tempaddr >= 2)) {
+-				score.attrs |= IPV6_SADDR_SCORE_PRIVACY;
+-				if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) {
+-					score.rule = 7;
+-					goto record_it;
++					break;
+ 				}
+-			} else {
+-				if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)
+-					continue;
+-			}
+-#else
+-			if (hiscore.rule < 7)
+-				hiscore.rule++;
+-#endif
+-			/* Rule 8: Use longest matching prefix */
+-			if (hiscore.rule < 8) {
+-				hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr);
+-				hiscore.rule++;
+ 			}
+-			score.matchlen = ipv6_addr_diff(&ifa->addr, daddr);
+-			if (score.matchlen > hiscore.matchlen) {
+-				score.rule = 8;
+-				goto record_it;
+-			}
+-#if 0
+-			else if (score.matchlen < hiscore.matchlen)
+-				continue;
+-#endif
+-
+-			/* Final Rule: choose first available one */
+-			continue;
+-record_it:
+-			if (ifa_result)
+-				in6_ifa_put(ifa_result);
+-			in6_ifa_hold(ifa);
+-			ifa_result = ifa;
+-			hiscore = score;
+ 		}
++try_nextdev:
+ 		read_unlock_bh(&idev->lock);
+ 	}
+ 	rcu_read_unlock();
+ 	read_unlock(&dev_base_lock);
+ 
+-	if (!ifa_result)
++	if (!hiscore->ifa)
+ 		return -EADDRNOTAVAIL;
+ 
+-	ipv6_addr_copy(saddr, &ifa_result->addr);
+-	in6_ifa_put(ifa_result);
++	ipv6_addr_copy(saddr, &hiscore->ifa->addr);
++	in6_ifa_put(hiscore->ifa);
+ 	return 0;
+ }
+ 
+-
+-int ipv6_get_saddr(struct dst_entry *dst,
+-		   struct in6_addr *daddr, struct in6_addr *saddr)
+-{
+-	return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr);
+-}
+-
+-EXPORT_SYMBOL(ipv6_get_saddr);
++EXPORT_SYMBOL(ipv6_dev_get_saddr);
+ 
+ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
+ 		    unsigned char banned_flags)
+@@ -1232,7 +1250,7 @@ int ipv6_chk_addr(struct net *net, struct in6_addr *addr,
+ 
+ 	read_lock_bh(&addrconf_hash_lock);
+ 	for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
+-		if (ifp->idev->dev->nd_net != net)
++		if (!net_eq(dev_net(ifp->idev->dev), net))
+ 			continue;
+ 		if (ipv6_addr_equal(&ifp->addr, addr) &&
+ 		    !(ifp->flags&IFA_F_TENTATIVE)) {
+@@ -1254,7 +1272,7 @@ int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
+ 	u8 hash = ipv6_addr_hash(addr);
+ 
+ 	for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
+-		if (ifp->idev->dev->nd_net != net)
++		if (!net_eq(dev_net(ifp->idev->dev), net))
+ 			continue;
+ 		if (ipv6_addr_equal(&ifp->addr, addr)) {
+ 			if (dev == NULL || ifp->idev->dev == dev)
+@@ -1264,7 +1282,32 @@ int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
+ 	return ifp != NULL;
+ }
+ 
+-struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr,
++int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev)
++{
++	struct inet6_dev *idev;
++	struct inet6_ifaddr *ifa;
++	int	onlink;
++
++	onlink = 0;
++	rcu_read_lock();
++	idev = __in6_dev_get(dev);
++	if (idev) {
++		read_lock_bh(&idev->lock);
++		for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) {
++			onlink = ipv6_prefix_equal(addr, &ifa->addr,
++						   ifa->prefix_len);
++			if (onlink)
++				break;
++		}
++		read_unlock_bh(&idev->lock);
++	}
++	rcu_read_unlock();
++	return onlink;
++}
++
++EXPORT_SYMBOL(ipv6_chk_prefix);
++
++struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr,
+ 				     struct net_device *dev, int strict)
+ {
+ 	struct inet6_ifaddr * ifp;
+@@ -1272,7 +1315,7 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr,
+ 
+ 	read_lock_bh(&addrconf_hash_lock);
+ 	for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
+-		if (ifp->idev->dev->nd_net != net)
++		if (!net_eq(dev_net(ifp->idev->dev), net))
+ 			continue;
+ 		if (ipv6_addr_equal(&ifp->addr, addr)) {
+ 			if (dev == NULL || ifp->idev->dev == dev ||
+@@ -1449,6 +1492,29 @@ static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
+ 	return 0;
+ }
+ 
++int __ipv6_isatap_ifid(u8 *eui, __be32 addr)
++{
++	eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) ||
++		  ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) ||
++		  ipv4_is_private_172(addr) || ipv4_is_test_192(addr) ||
++		  ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) ||
++		  ipv4_is_test_198(addr) || ipv4_is_multicast(addr) ||
++		  ipv4_is_lbcast(addr)) ? 0x00 : 0x02;
++	eui[1] = 0;
++	eui[2] = 0x5E;
++	eui[3] = 0xFE;
++	memcpy(eui + 4, &addr, 4);
++	return 0;
++}
++EXPORT_SYMBOL(__ipv6_isatap_ifid);
++
++static int addrconf_ifid_sit(u8 *eui, struct net_device *dev)
++{
++	if (dev->priv_flags & IFF_ISATAP)
++		return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr);
++	return -1;
++}
++
+ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
+ {
+ 	switch (dev->type) {
+@@ -1461,8 +1527,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
+ 	case ARPHRD_INFINIBAND:
+ 		return addrconf_ifid_infiniband(eui, dev);
+ 	case ARPHRD_SIT:
+-		if (dev->priv_flags & IFF_ISATAP)
+-			return ipv6_isatap_eui64(eui, *(__be32 *)dev->dev_addr);
++		return addrconf_ifid_sit(eui, dev);
+ 	}
+ 	return -1;
+ }
+@@ -1574,7 +1639,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
+ 		.fc_expires = expires,
+ 		.fc_dst_len = plen,
+ 		.fc_flags = RTF_UP | flags,
+-		.fc_nlinfo.nl_net = &init_net,
++		.fc_nlinfo.nl_net = dev_net(dev),
+ 	};
+ 
+ 	ipv6_addr_copy(&cfg.fc_dst, pfx);
+@@ -1601,7 +1666,7 @@ static void addrconf_add_mroute(struct net_device *dev)
+ 		.fc_ifindex = dev->ifindex,
+ 		.fc_dst_len = 8,
+ 		.fc_flags = RTF_UP,
+-		.fc_nlinfo.nl_net = &init_net,
++		.fc_nlinfo.nl_net = dev_net(dev),
+ 	};
+ 
+ 	ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
+@@ -1618,7 +1683,7 @@ static void sit_route_add(struct net_device *dev)
+ 		.fc_ifindex = dev->ifindex,
+ 		.fc_dst_len = 96,
+ 		.fc_flags = RTF_UP | RTF_NONEXTHOP,
+-		.fc_nlinfo.nl_net = &init_net,
++		.fc_nlinfo.nl_net = dev_net(dev),
+ 	};
+ 
+ 	/* prefix length - 96 bits "::d.d.d.d" */
+@@ -1719,7 +1784,8 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
+ 
+ 	if (pinfo->onlink) {
+ 		struct rt6_info *rt;
+-		rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1);
++		rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL,
++				dev->ifindex, 1);
+ 
+ 		if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
+ 			if (rt->rt6i_flags&RTF_EXPIRES) {
+@@ -1762,7 +1828,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
+ 
+ ok:
+ 
+-		ifp = ipv6_get_ifaddr(&init_net, &addr, dev, 1);
++		ifp = ipv6_get_ifaddr(dev_net(dev), &addr, dev, 1);
+ 
+ 		if (ifp == NULL && valid_lft) {
+ 			int max_addresses = in6_dev->cnf.max_addresses;
+@@ -1888,7 +1954,7 @@ ok:
+  *	Special case for SIT interfaces where we create a new "virtual"
+  *	device.
+  */
+-int addrconf_set_dstaddr(void __user *arg)
++int addrconf_set_dstaddr(struct net *net, void __user *arg)
+ {
+ 	struct in6_ifreq ireq;
+ 	struct net_device *dev;
+@@ -1900,7 +1966,7 @@ int addrconf_set_dstaddr(void __user *arg)
+ 	if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
+ 		goto err_exit;
+ 
+-	dev = __dev_get_by_index(&init_net, ireq.ifr6_ifindex);
++	dev = __dev_get_by_index(net, ireq.ifr6_ifindex);
+ 
+ 	err = -ENODEV;
+ 	if (dev == NULL)
+@@ -1931,7 +1997,8 @@ int addrconf_set_dstaddr(void __user *arg)
+ 
+ 		if (err == 0) {
+ 			err = -ENOBUFS;
+-			if ((dev = __dev_get_by_name(&init_net, p.name)) == NULL)
++			dev = __dev_get_by_name(net, p.name);
++			if (!dev)
+ 				goto err_exit;
+ 			err = dev_open(dev);
+ 		}
+@@ -1946,8 +2013,9 @@ err_exit:
+ /*
+  *	Manual configuration of address on an interface
+  */
+-static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
+-			  __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft)
++static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
++			  int plen, __u8 ifa_flags, __u32 prefered_lft,
++			  __u32 valid_lft)
+ {
+ 	struct inet6_ifaddr *ifp;
+ 	struct inet6_dev *idev;
+@@ -1961,7 +2029,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
+ 	if (!valid_lft || prefered_lft > valid_lft)
+ 		return -EINVAL;
+ 
+-	if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
++	dev = __dev_get_by_index(net, ifindex);
++	if (!dev)
+ 		return -ENODEV;
+ 
+ 	if ((idev = addrconf_add_dev(dev)) == NULL)
+@@ -2006,13 +2075,15 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
+ 	return PTR_ERR(ifp);
+ }
+ 
+-static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
++static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx,
++			  int plen)
+ {
+ 	struct inet6_ifaddr *ifp;
+ 	struct inet6_dev *idev;
+ 	struct net_device *dev;
+ 
+-	if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
++	dev = __dev_get_by_index(net, ifindex);
++	if (!dev)
+ 		return -ENODEV;
+ 
+ 	if ((idev = __in6_dev_get(dev)) == NULL)
+@@ -2040,7 +2111,7 @@ static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
+ }
+ 
+ 
+-int addrconf_add_ifaddr(void __user *arg)
++int addrconf_add_ifaddr(struct net *net, void __user *arg)
+ {
+ 	struct in6_ifreq ireq;
+ 	int err;
+@@ -2052,13 +2123,14 @@ int addrconf_add_ifaddr(void __user *arg)
+ 		return -EFAULT;
+ 
+ 	rtnl_lock();
+-	err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen,
+-			     IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
++	err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr,
++			     ireq.ifr6_prefixlen, IFA_F_PERMANENT,
++			     INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
+ 	rtnl_unlock();
+ 	return err;
+ }
+ 
+-int addrconf_del_ifaddr(void __user *arg)
++int addrconf_del_ifaddr(struct net *net, void __user *arg)
+ {
+ 	struct in6_ifreq ireq;
+ 	int err;
+@@ -2070,7 +2142,8 @@ int addrconf_del_ifaddr(void __user *arg)
+ 		return -EFAULT;
+ 
+ 	rtnl_lock();
+-	err = inet6_addr_del(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen);
++	err = inet6_addr_del(net, ireq.ifr6_ifindex, &ireq.ifr6_addr,
++			     ireq.ifr6_prefixlen);
+ 	rtnl_unlock();
+ 	return err;
+ }
+@@ -2081,6 +2154,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
+ 	struct inet6_ifaddr * ifp;
+ 	struct in6_addr addr;
+ 	struct net_device *dev;
++	struct net *net = dev_net(idev->dev);
+ 	int scope;
+ 
+ 	ASSERT_RTNL();
+@@ -2107,7 +2181,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
+ 		return;
+ 	}
+ 
+-	for_each_netdev(&init_net, dev) {
++	for_each_netdev(net, dev) {
+ 		struct in_device * in_dev = __in_dev_get_rtnl(dev);
+ 		if (in_dev && (dev->flags & IFF_UP)) {
+ 			struct in_ifaddr * ifa;
+@@ -2270,15 +2344,16 @@ ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
+ static void ip6_tnl_add_linklocal(struct inet6_dev *idev)
+ {
+ 	struct net_device *link_dev;
++	struct net *net = dev_net(idev->dev);
+ 
+ 	/* first try to inherit the link-local address from the link device */
+ 	if (idev->dev->iflink &&
+-	    (link_dev = __dev_get_by_index(&init_net, idev->dev->iflink))) {
++	    (link_dev = __dev_get_by_index(net, idev->dev->iflink))) {
+ 		if (!ipv6_inherit_linklocal(idev, link_dev))
+ 			return;
+ 	}
+ 	/* then try to inherit it from any device */
+-	for_each_netdev(&init_net, link_dev) {
++	for_each_netdev(net, link_dev) {
+ 		if (!ipv6_inherit_linklocal(idev, link_dev))
+ 			return;
+ 	}
+@@ -2311,9 +2386,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
+ 	int run_pending = 0;
+ 	int err;
+ 
+-	if (dev->nd_net != &init_net)
+-		return NOTIFY_DONE;
+-
+ 	switch(event) {
+ 	case NETDEV_REGISTER:
+ 		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
+@@ -2453,6 +2525,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
+ {
+ 	struct inet6_dev *idev;
+ 	struct inet6_ifaddr *ifa, **bifa;
++	struct net *net = dev_net(dev);
+ 	int i;
+ 
+ 	ASSERT_RTNL();
+@@ -2460,7 +2533,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
+ 	if ((dev->flags & IFF_LOOPBACK) && how == 1)
+ 		how = 0;
+ 
+-	rt6_ifdown(dev);
++	rt6_ifdown(net, dev);
+ 	neigh_ifdown(&nd_tbl, dev);
+ 
+ 	idev = __in6_dev_get(dev);
+@@ -2579,8 +2652,6 @@ static void addrconf_rs_timer(unsigned long data)
+ 
+ 	spin_lock(&ifp->lock);
+ 	if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) {
+-		struct in6_addr all_routers;
+-
+ 		/* The wait after the last probe can be shorter */
+ 		addrconf_mod_timer(ifp, AC_RS,
+ 				   (ifp->probes == ifp->idev->cnf.rtr_solicits) ?
+@@ -2588,9 +2659,7 @@ static void addrconf_rs_timer(unsigned long data)
+ 				   ifp->idev->cnf.rtr_solicit_interval);
+ 		spin_unlock(&ifp->lock);
+ 
+-		ipv6_addr_all_routers(&all_routers);
+-
+-		ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
++		ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);
+ 	} else {
+ 		spin_unlock(&ifp->lock);
+ 		/*
+@@ -2677,7 +2746,6 @@ static void addrconf_dad_timer(unsigned long data)
+ {
+ 	struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
+ 	struct inet6_dev *idev = ifp->idev;
+-	struct in6_addr unspec;
+ 	struct in6_addr mcaddr;
+ 
+ 	read_lock_bh(&idev->lock);
+@@ -2706,9 +2774,8 @@ static void addrconf_dad_timer(unsigned long data)
+ 	read_unlock_bh(&idev->lock);
+ 
+ 	/* send a neighbour solicitation for our addr */
+-	memset(&unspec, 0, sizeof(unspec));
+ 	addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
+-	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);
++	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any);
+ out:
+ 	in6_ifa_put(ifp);
+ }
+@@ -2731,16 +2798,12 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
+ 	    ifp->idev->cnf.rtr_solicits > 0 &&
+ 	    (dev->flags&IFF_LOOPBACK) == 0 &&
+ 	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
+-		struct in6_addr all_routers;
+-
+-		ipv6_addr_all_routers(&all_routers);
+-
+ 		/*
+ 		 *	If a host as already performed a random delay
+ 		 *	[...] as part of DAD [...] there is no need
+ 		 *	to delay again before sending the first RS
+ 		 */
+-		ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
++		ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);
+ 
+ 		spin_lock_bh(&ifp->lock);
+ 		ifp->probes = 1;
+@@ -2776,12 +2839,12 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq)
+ {
+ 	struct inet6_ifaddr *ifa = NULL;
+ 	struct if6_iter_state *state = seq->private;
+-	struct net *net = state->p.net;
++	struct net *net = seq_file_net(seq);
+ 
+ 	for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
+ 		ifa = inet6_addr_lst[state->bucket];
+ 
+-		while (ifa && ifa->idev->dev->nd_net != net)
++		while (ifa && !net_eq(dev_net(ifa->idev->dev), net))
+ 			ifa = ifa->lst_next;
+ 		if (ifa)
+ 			break;
+@@ -2792,12 +2855,12 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq)
+ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa)
+ {
+ 	struct if6_iter_state *state = seq->private;
+-	struct net *net = state->p.net;
++	struct net *net = seq_file_net(seq);
+ 
+ 	ifa = ifa->lst_next;
+ try_again:
+ 	if (ifa) {
+-		if (ifa->idev->dev->nd_net != net) {
++		if (!net_eq(dev_net(ifa->idev->dev), net)) {
+ 			ifa = ifa->lst_next;
+ 			goto try_again;
+ 		}
+@@ -2915,9 +2978,9 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr)
+ 	u8 hash = ipv6_addr_hash(addr);
+ 	read_lock_bh(&addrconf_hash_lock);
+ 	for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) {
+-		if (ifp->idev->dev->nd_net != net)
++		if (!net_eq(dev_net(ifp->idev->dev), net))
+ 			continue;
+-		if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
++		if (ipv6_addr_equal(&ifp->addr, addr) &&
+ 		    (ifp->flags & IFA_F_HOMEADDRESS)) {
+ 			ret = 1;
+ 			break;
+@@ -3064,15 +3127,12 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
+ static int
+ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct ifaddrmsg *ifm;
+ 	struct nlattr *tb[IFA_MAX+1];
+ 	struct in6_addr *pfx;
+ 	int err;
+ 
+-	if (net != &init_net)
+-		return -EINVAL;
+-
+ 	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+ 	if (err < 0)
+ 		return err;
+@@ -3082,7 +3142,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ 	if (pfx == NULL)
+ 		return -EINVAL;
+ 
+-	return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
++	return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen);
+ }
+ 
+ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
+@@ -3125,7 +3185,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
+ static int
+ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct ifaddrmsg *ifm;
+ 	struct nlattr *tb[IFA_MAX+1];
+ 	struct in6_addr *pfx;
+@@ -3135,9 +3195,6 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ 	u8 ifa_flags;
+ 	int err;
+ 
+-	if (net != &init_net)
+-		return -EINVAL;
+-
+ 	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+ 	if (err < 0)
+ 		return err;
+@@ -3158,7 +3215,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ 		valid_lft = INFINITY_LIFE_TIME;
+ 	}
+ 
+-	dev =  __dev_get_by_index(&init_net, ifm->ifa_index);
++	dev =  __dev_get_by_index(net, ifm->ifa_index);
+ 	if (dev == NULL)
+ 		return -ENODEV;
+ 
+@@ -3171,8 +3228,9 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ 		 * It would be best to check for !NLM_F_CREATE here but
+ 		 * userspace alreay relies on not having to provide this.
+ 		 */
+-		return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
+-				      ifa_flags, preferred_lft, valid_lft);
++		return inet6_addr_add(net, ifm->ifa_index, pfx,
++				      ifm->ifa_prefixlen, ifa_flags,
++				      preferred_lft, valid_lft);
+ 	}
+ 
+ 	if (nlh->nlmsg_flags & NLM_F_EXCL ||
+@@ -3337,12 +3395,13 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
+ 	struct inet6_ifaddr *ifa;
+ 	struct ifmcaddr6 *ifmca;
+ 	struct ifacaddr6 *ifaca;
++	struct net *net = sock_net(skb->sk);
+ 
+ 	s_idx = cb->args[0];
+ 	s_ip_idx = ip_idx = cb->args[1];
+ 
+ 	idx = 0;
+-	for_each_netdev(&init_net, dev) {
++	for_each_netdev(net, dev) {
+ 		if (idx < s_idx)
+ 			goto cont;
+ 		if (idx > s_idx)
+@@ -3409,42 +3468,30 @@ cont:
+ 
+ static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
+ 	enum addr_type_t type = UNICAST_ADDR;
+ 
+-	if (net != &init_net)
+-		return 0;
+-
+ 	return inet6_dump_addr(skb, cb, type);
+ }
+ 
+ static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
+ 	enum addr_type_t type = MULTICAST_ADDR;
+ 
+-	if (net != &init_net)
+-		return 0;
+-
+ 	return inet6_dump_addr(skb, cb, type);
+ }
+ 
+ 
+ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
+ 	enum addr_type_t type = ANYCAST_ADDR;
+ 
+-	if (net != &init_net)
+-		return 0;
+-
+ 	return inet6_dump_addr(skb, cb, type);
+ }
+ 
+ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+ 			     void *arg)
+ {
+-	struct net *net = in_skb->sk->sk_net;
++	struct net *net = sock_net(in_skb->sk);
+ 	struct ifaddrmsg *ifm;
+ 	struct nlattr *tb[IFA_MAX+1];
+ 	struct in6_addr *addr = NULL;
+@@ -3453,9 +3500,6 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+ 	struct sk_buff *skb;
+ 	int err;
+ 
+-	if (net != &init_net)
+-		return -EINVAL;
+-
+ 	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+ 	if (err < 0)
+ 		goto errout;
+@@ -3468,7 +3512,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+ 
+ 	ifm = nlmsg_data(nlh);
+ 	if (ifm->ifa_index)
+-		dev = __dev_get_by_index(&init_net, ifm->ifa_index);
++		dev = __dev_get_by_index(net, ifm->ifa_index);
+ 
+ 	if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) {
+ 		err = -EADDRNOTAVAIL;
+@@ -3488,7 +3532,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+ 		kfree_skb(skb);
+ 		goto errout_ifa;
+ 	}
+-	err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
++	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid);
+ errout_ifa:
+ 	in6_ifa_put(ifa);
+ errout:
+@@ -3498,6 +3542,7 @@ errout:
+ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
+ {
+ 	struct sk_buff *skb;
++	struct net *net = dev_net(ifa->idev->dev);
+ 	int err = -ENOBUFS;
+ 
+ 	skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
+@@ -3511,10 +3556,10 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
+ 		kfree_skb(skb);
+ 		goto errout;
+ 	}
+-	err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
++	err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+ errout:
+ 	if (err < 0)
+-		rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
++		rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
+ }
+ 
+ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
+@@ -3556,6 +3601,9 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
+ #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
+ 	array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
+ #endif
++#ifdef CONFIG_IPV6_MROUTE
++	array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
++#endif
+ }
+ 
+ static inline size_t inet6_if_nlmsg_size(void)
+@@ -3673,18 +3721,15 @@ nla_put_failure:
+ 
+ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	int idx, err;
+ 	int s_idx = cb->args[0];
+ 	struct net_device *dev;
+ 	struct inet6_dev *idev;
+ 
+-	if (net != &init_net)
+-		return 0;
+-
+ 	read_lock(&dev_base_lock);
+ 	idx = 0;
+-	for_each_netdev(&init_net, dev) {
++	for_each_netdev(net, dev) {
+ 		if (idx < s_idx)
+ 			goto cont;
+ 		if ((idev = in6_dev_get(dev)) == NULL)
+@@ -3706,6 +3751,7 @@ cont:
+ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
+ {
+ 	struct sk_buff *skb;
++	struct net *net = dev_net(idev->dev);
+ 	int err = -ENOBUFS;
+ 
+ 	skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
+@@ -3719,10 +3765,10 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
+ 		kfree_skb(skb);
+ 		goto errout;
+ 	}
+-	err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
++	err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+ errout:
+ 	if (err < 0)
+-		rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
++		rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
+ }
+ 
+ static inline size_t inet6_prefix_nlmsg_size(void)
+@@ -3775,6 +3821,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
+ 			 struct prefix_info *pinfo)
+ {
+ 	struct sk_buff *skb;
++	struct net *net = dev_net(idev->dev);
+ 	int err = -ENOBUFS;
+ 
+ 	skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
+@@ -3788,10 +3835,10 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
+ 		kfree_skb(skb);
+ 		goto errout;
+ 	}
+-	err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
++	err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
+ errout:
+ 	if (err < 0)
+-		rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_PREFIX, err);
++		rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
+ }
+ 
+ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
+@@ -3887,7 +3934,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
+ static struct addrconf_sysctl_table
+ {
+ 	struct ctl_table_header *sysctl_header;
+-	ctl_table addrconf_vars[__NET_IPV6_MAX];
++	ctl_table addrconf_vars[DEVCONF_MAX+1];
+ 	char *dev_name;
+ } addrconf_sysctl __read_mostly = {
+ 	.sysctl_header = NULL,
+@@ -4105,6 +4152,16 @@ static struct addrconf_sysctl_table
+ 
+ 		},
+ #endif
++#ifdef CONFIG_IPV6_MROUTE
++		{
++			.ctl_name	=	CTL_UNNUMBERED,
++			.procname	=	"mc_forwarding",
++			.data		=	&ipv6_devconf.mc_forwarding,
++			.maxlen		=	sizeof(int),
++			.mode		=	0644,
++			.proc_handler	=	&proc_dointvec,
++		},
++#endif
+ 		{
+ 			.ctl_name	=	0,	/* sentinel */
+ 		}
+@@ -4186,7 +4243,7 @@ static void addrconf_sysctl_register(struct inet6_dev *idev)
+ 			      NET_IPV6_NEIGH, "ipv6",
+ 			      &ndisc_ifinfo_sysctl_change,
+ 			      NULL);
+-	__addrconf_sysctl_register(idev->dev->nd_net, idev->dev->name,
++	__addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
+ 			idev->dev->ifindex, idev, &idev->cnf);
+ }
+ 
+@@ -4281,6 +4338,25 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
+ 
+ EXPORT_SYMBOL(unregister_inet6addr_notifier);
+ 
++static void addrconf_net_exit(struct net *net)
++{
++	struct net_device *dev;
++
++	rtnl_lock();
++	/* clean dev list */
++	for_each_netdev(net, dev) {
++		if (__in6_dev_get(dev) == NULL)
++			continue;
++		addrconf_ifdown(dev, 1);
++	}
++	addrconf_ifdown(net->loopback_dev, 2);
++	rtnl_unlock();
++}
++
++static struct pernet_operations addrconf_net_ops = {
++	.exit = addrconf_net_exit,
++};
++
+ /*
+  *	Init / cleanup code
+  */
+@@ -4322,14 +4398,9 @@ int __init addrconf_init(void)
+ 	if (err)
+ 		goto errlo;
+ 
+-	ip6_null_entry.u.dst.dev = init_net.loopback_dev;
+-	ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
+-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+-	ip6_prohibit_entry.u.dst.dev = init_net.loopback_dev;
+-	ip6_prohibit_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
+-	ip6_blk_hole_entry.u.dst.dev = init_net.loopback_dev;
+-	ip6_blk_hole_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
+-#endif
++	err = register_pernet_device(&addrconf_net_ops);
++	if (err)
++		return err;
+ 
+ 	register_netdevice_notifier(&ipv6_dev_notf);
+ 
+@@ -4359,31 +4430,19 @@ errlo:
+ 
+ void addrconf_cleanup(void)
+ {
+-	struct net_device *dev;
+ 	struct inet6_ifaddr *ifa;
+ 	int i;
+ 
+ 	unregister_netdevice_notifier(&ipv6_dev_notf);
++	unregister_pernet_device(&addrconf_net_ops);
+ 
+ 	unregister_pernet_subsys(&addrconf_ops);
+ 
+ 	rtnl_lock();
+ 
+ 	/*
+-	 *	clean dev list.
+-	 */
+-
+-	for_each_netdev(&init_net, dev) {
+-		if (__in6_dev_get(dev) == NULL)
+-			continue;
+-		addrconf_ifdown(dev, 1);
+-	}
+-	addrconf_ifdown(init_net.loopback_dev, 2);
+-
+-	/*
+ 	 *	Check hash table.
+ 	 */
+-
+ 	write_lock_bh(&addrconf_hash_lock);
+ 	for (i=0; i < IN6_ADDR_HSIZE; i++) {
+ 		for (ifa=inet6_addr_lst[i]; ifa; ) {
+@@ -4400,6 +4459,7 @@ void addrconf_cleanup(void)
+ 	write_unlock_bh(&addrconf_hash_lock);
+ 
+ 	del_timer(&addr_chk_timer);
+-
+ 	rtnl_unlock();
++
++	unregister_pernet_subsys(&addrconf_net_ops);
+ }
+diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
+index a3c5a72..9bfa884 100644
+--- a/net/ipv6/addrlabel.c
++++ b/net/ipv6/addrlabel.c
+@@ -58,6 +58,7 @@ static struct ip6addrlbl_table
+  * ::ffff:0:0/96	V4MAPPED	4
+  * fc00::/7		N/A		5		ULA (RFC 4193)
+  * 2001::/32		N/A		6		Teredo (RFC 4380)
++ * 2001:10::/28		N/A		7		ORCHID (RFC 4843)
+  *
+  * Note: 0xffffffff is used if we do not have any policies.
+  */
+@@ -85,6 +86,10 @@ static const __initdata struct ip6addrlbl_init_table
+ 		.prefix = &(struct in6_addr){{{ 0x20, 0x01 }}},
+ 		.prefixlen = 32,
+ 		.label = 6,
++	},{	/* 2001:10::/28 */
++		.prefix = &(struct in6_addr){{{ 0x20, 0x01, 0x00, 0x10 }}},
++		.prefixlen = 28,
++		.label = 7,
+ 	},{	/* ::ffff:0:0 */
+ 		.prefix = &(struct in6_addr){{{ [10] = 0xff, [11] = 0xff }}},
+ 		.prefixlen = 96,
+@@ -161,7 +166,7 @@ u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex)
+ 	rcu_read_unlock();
+ 
+ 	ADDRLABEL(KERN_DEBUG "%s(addr=" NIP6_FMT ", type=%d, ifindex=%d) => %08x\n",
+-			__FUNCTION__,
++			__func__,
+ 			NIP6(*addr), type, ifindex,
+ 			label);
+ 
+@@ -177,7 +182,7 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix,
+ 	int addrtype;
+ 
+ 	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u)\n",
+-			__FUNCTION__,
++			__func__,
+ 			NIP6(*prefix), prefixlen,
+ 			ifindex,
+ 			(unsigned int)label);
+@@ -221,7 +226,7 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace)
+ 	int ret = 0;
+ 
+ 	ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n",
+-			__FUNCTION__,
++			__func__,
+ 			newp, replace);
+ 
+ 	if (hlist_empty(&ip6addrlbl_table.head)) {
+@@ -263,7 +268,7 @@ static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen,
+ 	int ret = 0;
+ 
+ 	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n",
+-			__FUNCTION__,
++			__func__,
+ 			NIP6(*prefix), prefixlen,
+ 			ifindex,
+ 			(unsigned int)label,
+@@ -289,7 +294,7 @@ static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen,
+ 	int ret = -ESRCH;
+ 
+ 	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n",
+-			__FUNCTION__,
++			__func__,
+ 			NIP6(*prefix), prefixlen,
+ 			ifindex);
+ 
+@@ -313,7 +318,7 @@ static int ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen,
+ 	int ret;
+ 
+ 	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n",
+-			__FUNCTION__,
++			__func__,
+ 			NIP6(*prefix), prefixlen,
+ 			ifindex);
+ 
+@@ -330,7 +335,7 @@ static __init int ip6addrlbl_init(void)
+ 	int err = 0;
+ 	int i;
+ 
+-	ADDRLABEL(KERN_DEBUG "%s()\n", __FUNCTION__);
++	ADDRLABEL(KERN_DEBUG "%s()\n", __func__);
+ 
+ 	for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) {
+ 		int ret = ip6addrlbl_add(ip6addrlbl_init_table[i].prefix,
+@@ -359,7 +364,7 @@ static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
+ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,
+ 			     void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct ifaddrlblmsg *ifal;
+ 	struct nlattr *tb[IFAL_MAX+1];
+ 	struct in6_addr *pfx;
+@@ -447,7 +452,7 @@ static int ip6addrlbl_fill(struct sk_buff *skb,
+ 
+ static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct ip6addrlbl_entry *p;
+ 	struct hlist_node *pos;
+ 	int idx = 0, s_idx = cb->args[0];
+@@ -485,7 +490,7 @@ static inline int ip6addrlbl_msgsize(void)
+ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+ 			  void *arg)
+ {
+-	struct net *net = in_skb->sk->sk_net;
++	struct net *net = sock_net(in_skb->sk);
+ 	struct ifaddrlblmsg *ifal;
+ 	struct nlattr *tb[IFAL_MAX+1];
+ 	struct in6_addr *addr;
+diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
+index f0aa977..3c6aafb 100644
+--- a/net/ipv6/af_inet6.c
++++ b/net/ipv6/af_inet6.c
+@@ -61,6 +61,9 @@
+ 
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
++#ifdef CONFIG_IPV6_MROUTE
++#include <linux/mroute6.h>
++#endif
+ 
+ MODULE_AUTHOR("Cast of dozens");
+ MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
+@@ -92,9 +95,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol)
+ 	int try_loading_module = 0;
+ 	int err;
+ 
+-	if (net != &init_net)
+-		return -EAFNOSUPPORT;
+-
+ 	if (sock->type != SOCK_RAW &&
+ 	    sock->type != SOCK_DGRAM &&
+ 	    !inet_ehash_secret)
+@@ -248,6 +248,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 	struct sock *sk = sock->sk;
+ 	struct inet_sock *inet = inet_sk(sk);
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
++	struct net *net = sock_net(sk);
+ 	__be32 v4addr = 0;
+ 	unsigned short snum;
+ 	int addr_type = 0;
+@@ -278,7 +279,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 	/* Check if the address belongs to the host. */
+ 	if (addr_type == IPV6_ADDR_MAPPED) {
+ 		v4addr = addr->sin6_addr.s6_addr32[3];
+-		if (inet_addr_type(&init_net, v4addr) != RTN_LOCAL) {
++		if (inet_addr_type(net, v4addr) != RTN_LOCAL) {
+ 			err = -EADDRNOTAVAIL;
+ 			goto out;
+ 		}
+@@ -300,7 +301,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 					err = -EINVAL;
+ 					goto out;
+ 				}
+-				dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
++				dev = dev_get_by_index(net, sk->sk_bound_dev_if);
+ 				if (!dev) {
+ 					err = -ENODEV;
+ 					goto out;
+@@ -312,7 +313,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 			 */
+ 			v4addr = LOOPBACK4_IPV6;
+ 			if (!(addr_type & IPV6_ADDR_MULTICAST))	{
+-				if (!ipv6_chk_addr(&init_net, &addr->sin6_addr,
++				if (!ipv6_chk_addr(net, &addr->sin6_addr,
+ 						   dev, 0)) {
+ 					if (dev)
+ 						dev_put(dev);
+@@ -440,6 +441,7 @@ EXPORT_SYMBOL(inet6_getname);
+ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ {
+ 	struct sock *sk = sock->sk;
++	struct net *net = sock_net(sk);
+ 
+ 	switch(cmd)
+ 	{
+@@ -452,14 +454,14 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ 	case SIOCADDRT:
+ 	case SIOCDELRT:
+ 
+-		return(ipv6_route_ioctl(cmd,(void __user *)arg));
++		return(ipv6_route_ioctl(net, cmd, (void __user *)arg));
+ 
+ 	case SIOCSIFADDR:
+-		return addrconf_add_ifaddr((void __user *) arg);
++		return addrconf_add_ifaddr(net, (void __user *) arg);
+ 	case SIOCDIFADDR:
+-		return addrconf_del_ifaddr((void __user *) arg);
++		return addrconf_del_ifaddr(net, (void __user *) arg);
+ 	case SIOCSIFDSTADDR:
+-		return addrconf_set_dstaddr((void __user *) arg);
++		return addrconf_set_dstaddr(net, (void __user *) arg);
+ 	default:
+ 		if (!sk->sk_prot->ioctl)
+ 			return -ENOIOCTLCMD;
+@@ -678,6 +680,129 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
+ 
+ EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
+ 
++static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb,
++						    int proto)
++{
++	struct inet6_protocol *ops = NULL;
++
++	for (;;) {
++		struct ipv6_opt_hdr *opth;
++		int len;
++
++		if (proto != NEXTHDR_HOP) {
++			ops = rcu_dereference(inet6_protos[proto]);
++
++			if (unlikely(!ops))
++				break;
++
++			if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
++				break;
++		}
++
++		if (unlikely(!pskb_may_pull(skb, 8)))
++			break;
++
++		opth = (void *)skb->data;
++		len = ipv6_optlen(opth);
++
++		if (unlikely(!pskb_may_pull(skb, len)))
++			break;
++
++		proto = opth->nexthdr;
++		__skb_pull(skb, len);
++	}
++
++	return ops;
++}
++
++static int ipv6_gso_send_check(struct sk_buff *skb)
++{
++	struct ipv6hdr *ipv6h;
++	struct inet6_protocol *ops;
++	int err = -EINVAL;
++
++	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
++		goto out;
++
++	ipv6h = ipv6_hdr(skb);
++	__skb_pull(skb, sizeof(*ipv6h));
++	err = -EPROTONOSUPPORT;
++
++	rcu_read_lock();
++	ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
++	if (likely(ops && ops->gso_send_check)) {
++		skb_reset_transport_header(skb);
++		err = ops->gso_send_check(skb);
++	}
++	rcu_read_unlock();
++
++out:
++	return err;
++}
++
++static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
++{
++	struct sk_buff *segs = ERR_PTR(-EINVAL);
++	struct ipv6hdr *ipv6h;
++	struct inet6_protocol *ops;
++
++	if (!(features & NETIF_F_V6_CSUM))
++		features &= ~NETIF_F_SG;
++
++	if (unlikely(skb_shinfo(skb)->gso_type &
++		     ~(SKB_GSO_UDP |
++		       SKB_GSO_DODGY |
++		       SKB_GSO_TCP_ECN |
++		       SKB_GSO_TCPV6 |
++		       0)))
++		goto out;
++
++	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
++		goto out;
++
++	ipv6h = ipv6_hdr(skb);
++	__skb_pull(skb, sizeof(*ipv6h));
++	segs = ERR_PTR(-EPROTONOSUPPORT);
++
++	rcu_read_lock();
++	ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
++	if (likely(ops && ops->gso_segment)) {
++		skb_reset_transport_header(skb);
++		segs = ops->gso_segment(skb, features);
++	}
++	rcu_read_unlock();
++
++	if (unlikely(IS_ERR(segs)))
++		goto out;
++
++	for (skb = segs; skb; skb = skb->next) {
++		ipv6h = ipv6_hdr(skb);
++		ipv6h->payload_len = htons(skb->len - skb->mac_len -
++					   sizeof(*ipv6h));
++	}
++
++out:
++	return segs;
++}
++
++static struct packet_type ipv6_packet_type = {
++	.type = __constant_htons(ETH_P_IPV6),
++	.func = ipv6_rcv,
++	.gso_send_check = ipv6_gso_send_check,
++	.gso_segment = ipv6_gso_segment,
++};
++
++static int __init ipv6_packet_init(void)
++{
++	dev_add_pack(&ipv6_packet_type);
++	return 0;
++}
++
++static void ipv6_packet_cleanup(void)
++{
++	dev_remove_pack(&ipv6_packet_type);
++}
++
+ static int __init init_ipv6_mibs(void)
+ {
+ 	if (snmp_mib_init((void **)ipv6_statistics,
+@@ -720,6 +845,8 @@ static void cleanup_ipv6_mibs(void)
+ 
+ static int inet6_net_init(struct net *net)
+ {
++	int err = 0;
++
+ 	net->ipv6.sysctl.bindv6only = 0;
+ 	net->ipv6.sysctl.flush_delay = 0;
+ 	net->ipv6.sysctl.ip6_rt_max_size = 4096;
+@@ -731,12 +858,36 @@ static int inet6_net_init(struct net *net)
+ 	net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
+ 	net->ipv6.sysctl.icmpv6_time = 1*HZ;
+ 
+-	return 0;
++#ifdef CONFIG_PROC_FS
++	err = udp6_proc_init(net);
++	if (err)
++		goto out;
++	err = tcp6_proc_init(net);
++	if (err)
++		goto proc_tcp6_fail;
++	err = ac6_proc_init(net);
++	if (err)
++		goto proc_ac6_fail;
++out:
++#endif
++	return err;
++
++#ifdef CONFIG_PROC_FS
++proc_ac6_fail:
++	tcp6_proc_exit(net);
++proc_tcp6_fail:
++	udp6_proc_exit(net);
++	goto out;
++#endif
+ }
+ 
+ static void inet6_net_exit(struct net *net)
+ {
+-	return;
++#ifdef CONFIG_PROC_FS
++	udp6_proc_exit(net);
++	tcp6_proc_exit(net);
++	ac6_proc_exit(net);
++#endif
+ }
+ 
+ static struct pernet_operations inet6_net_ops = {
+@@ -802,19 +953,16 @@ static int __init inet6_init(void)
+ 	err = register_pernet_subsys(&inet6_net_ops);
+ 	if (err)
+ 		goto register_pernet_fail;
+-
+-#ifdef CONFIG_SYSCTL
+-	err = ipv6_sysctl_register();
+-	if (err)
+-		goto sysctl_fail;
+-#endif
+-	err = icmpv6_init(&inet6_family_ops);
++	err = icmpv6_init();
+ 	if (err)
+ 		goto icmp_fail;
+-	err = ndisc_init(&inet6_family_ops);
++#ifdef CONFIG_IPV6_MROUTE
++	ip6_mr_init();
++#endif
++	err = ndisc_init();
+ 	if (err)
+ 		goto ndisc_fail;
+-	err = igmp6_init(&inet6_family_ops);
++	err = igmp6_init();
+ 	if (err)
+ 		goto igmp_fail;
+ 	err = ipv6_netfilter_init();
+@@ -825,17 +973,10 @@ static int __init inet6_init(void)
+ 	err = -ENOMEM;
+ 	if (raw6_proc_init())
+ 		goto proc_raw6_fail;
+-	if (tcp6_proc_init())
+-		goto proc_tcp6_fail;
+-	if (udp6_proc_init())
+-		goto proc_udp6_fail;
+ 	if (udplite6_proc_init())
+ 		goto proc_udplite6_fail;
+ 	if (ipv6_misc_proc_init())
+ 		goto proc_misc6_fail;
+-
+-	if (ac6_proc_init())
+-		goto proc_anycast6_fail;
+ 	if (if6_proc_init())
+ 		goto proc_if6_fail;
+ #endif
+@@ -874,9 +1015,19 @@ static int __init inet6_init(void)
+ 	err = ipv6_packet_init();
+ 	if (err)
+ 		goto ipv6_packet_fail;
++
++#ifdef CONFIG_SYSCTL
++	err = ipv6_sysctl_register();
++	if (err)
++		goto sysctl_fail;
++#endif
+ out:
+ 	return err;
+ 
++#ifdef CONFIG_SYSCTL
++sysctl_fail:
++	ipv6_packet_cleanup();
++#endif
+ ipv6_packet_fail:
+ 	tcpv6_exit();
+ tcpv6_fail:
+@@ -897,16 +1048,10 @@ ip6_route_fail:
+ #ifdef CONFIG_PROC_FS
+ 	if6_proc_exit();
+ proc_if6_fail:
+-	ac6_proc_exit();
+-proc_anycast6_fail:
+ 	ipv6_misc_proc_exit();
+ proc_misc6_fail:
+ 	udplite6_proc_exit();
+ proc_udplite6_fail:
+-	udp6_proc_exit();
+-proc_udp6_fail:
+-	tcp6_proc_exit();
+-proc_tcp6_fail:
+ 	raw6_proc_exit();
+ proc_raw6_fail:
+ #endif
+@@ -918,10 +1063,6 @@ igmp_fail:
+ ndisc_fail:
+ 	icmpv6_cleanup();
+ icmp_fail:
+-#ifdef CONFIG_SYSCTL
+-	ipv6_sysctl_unregister();
+-sysctl_fail:
+-#endif
+ 	unregister_pernet_subsys(&inet6_net_ops);
+ register_pernet_fail:
+ 	cleanup_ipv6_mibs();
+@@ -949,6 +1090,9 @@ static void __exit inet6_exit(void)
+ 	/* Disallow any further netlink messages */
+ 	rtnl_unregister_all(PF_INET6);
+ 
++#ifdef CONFIG_SYSCTL
++	ipv6_sysctl_unregister();
++#endif
+ 	udpv6_exit();
+ 	udplitev6_exit();
+ 	tcpv6_exit();
+@@ -964,11 +1108,8 @@ static void __exit inet6_exit(void)
+ 
+ 	/* Cleanup code parts. */
+ 	if6_proc_exit();
+-	ac6_proc_exit();
+ 	ipv6_misc_proc_exit();
+ 	udplite6_proc_exit();
+-	udp6_proc_exit();
+-	tcp6_proc_exit();
+ 	raw6_proc_exit();
+ #endif
+ 	ipv6_netfilter_fini();
+@@ -976,9 +1117,7 @@ static void __exit inet6_exit(void)
+ 	ndisc_cleanup();
+ 	icmpv6_cleanup();
+ 	rawv6_exit();
+-#ifdef CONFIG_SYSCTL
+-	ipv6_sysctl_unregister();
+-#endif
++
+ 	unregister_pernet_subsys(&inet6_net_ops);
+ 	cleanup_ipv6_mibs();
+ 	proto_unregister(&rawv6_prot);
+diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
+index e5f56c9..4e1b29f 100644
+--- a/net/ipv6/anycast.c
++++ b/net/ipv6/anycast.c
+@@ -48,29 +48,6 @@ static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr);
+ /* Big ac list lock for all the sockets */
+ static DEFINE_RWLOCK(ipv6_sk_ac_lock);
+ 
+-static int
+-ip6_onlink(struct in6_addr *addr, struct net_device *dev)
+-{
+-	struct inet6_dev	*idev;
+-	struct inet6_ifaddr	*ifa;
+-	int	onlink;
+-
+-	onlink = 0;
+-	rcu_read_lock();
+-	idev = __in6_dev_get(dev);
+-	if (idev) {
+-		read_lock_bh(&idev->lock);
+-		for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
+-			onlink = ipv6_prefix_equal(addr, &ifa->addr,
+-						   ifa->prefix_len);
+-			if (onlink)
+-				break;
+-		}
+-		read_unlock_bh(&idev->lock);
+-	}
+-	rcu_read_unlock();
+-	return onlink;
+-}
+ 
+ /*
+  *	socket join an anycast group
+@@ -82,6 +59,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 	struct net_device *dev = NULL;
+ 	struct inet6_dev *idev;
+ 	struct ipv6_ac_socklist *pac;
++	struct net *net = sock_net(sk);
+ 	int	ishost = !ipv6_devconf.forwarding;
+ 	int	err = 0;
+ 
+@@ -89,7 +67,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 		return -EPERM;
+ 	if (ipv6_addr_is_multicast(addr))
+ 		return -EINVAL;
+-	if (ipv6_chk_addr(&init_net, addr, NULL, 0))
++	if (ipv6_chk_addr(net, addr, NULL, 0))
+ 		return -EINVAL;
+ 
+ 	pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL);
+@@ -101,7 +79,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 	if (ifindex == 0) {
+ 		struct rt6_info *rt;
+ 
+-		rt = rt6_lookup(addr, NULL, 0, 0);
++		rt = rt6_lookup(net, addr, NULL, 0, 0);
+ 		if (rt) {
+ 			dev = rt->rt6i_dev;
+ 			dev_hold(dev);
+@@ -112,10 +90,10 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 		} else {
+ 			/* router, no matching interface: just pick one */
+ 
+-			dev = dev_get_by_flags(&init_net, IFF_UP, IFF_UP|IFF_LOOPBACK);
++			dev = dev_get_by_flags(net, IFF_UP, IFF_UP|IFF_LOOPBACK);
+ 		}
+ 	} else
+-		dev = dev_get_by_index(&init_net, ifindex);
++		dev = dev_get_by_index(net, ifindex);
+ 
+ 	if (dev == NULL) {
+ 		err = -ENODEV;
+@@ -141,7 +119,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 	 * This obviates the need for propagating anycast routes while
+ 	 * still allowing some non-router anycast participation.
+ 	 */
+-	if (!ip6_onlink(addr, dev)) {
++	if (!ipv6_chk_prefix(addr, dev)) {
+ 		if (ishost)
+ 			err = -EADDRNOTAVAIL;
+ 		if (err)
+@@ -176,6 +154,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+ 	struct net_device *dev;
+ 	struct ipv6_ac_socklist *pac, *prev_pac;
++	struct net *net = sock_net(sk);
+ 
+ 	write_lock_bh(&ipv6_sk_ac_lock);
+ 	prev_pac = NULL;
+@@ -196,7 +175,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 
+ 	write_unlock_bh(&ipv6_sk_ac_lock);
+ 
+-	dev = dev_get_by_index(&init_net, pac->acl_ifindex);
++	dev = dev_get_by_index(net, pac->acl_ifindex);
+ 	if (dev) {
+ 		ipv6_dev_ac_dec(dev, &pac->acl_addr);
+ 		dev_put(dev);
+@@ -210,6 +189,7 @@ void ipv6_sock_ac_close(struct sock *sk)
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+ 	struct net_device *dev = NULL;
+ 	struct ipv6_ac_socklist *pac;
++	struct net *net = sock_net(sk);
+ 	int	prev_index;
+ 
+ 	write_lock_bh(&ipv6_sk_ac_lock);
+@@ -224,7 +204,7 @@ void ipv6_sock_ac_close(struct sock *sk)
+ 		if (pac->acl_ifindex != prev_index) {
+ 			if (dev)
+ 				dev_put(dev);
+-			dev = dev_get_by_index(&init_net, pac->acl_ifindex);
++			dev = dev_get_by_index(net, pac->acl_ifindex);
+ 			prev_index = pac->acl_ifindex;
+ 		}
+ 		if (dev)
+@@ -417,14 +397,15 @@ static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr)
+ /*
+  *	check if given interface (or any, if dev==0) has this anycast address
+  */
+-int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr)
++int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
++			struct in6_addr *addr)
+ {
+ 	int found = 0;
+ 
+ 	if (dev)
+ 		return ipv6_chk_acast_dev(dev, addr);
+ 	read_lock(&dev_base_lock);
+-	for_each_netdev(&init_net, dev)
++	for_each_netdev(net, dev)
+ 		if (ipv6_chk_acast_dev(dev, addr)) {
+ 			found = 1;
+ 			break;
+@@ -436,6 +417,7 @@ int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr)
+ 
+ #ifdef CONFIG_PROC_FS
+ struct ac6_iter_state {
++	struct seq_net_private p;
+ 	struct net_device *dev;
+ 	struct inet6_dev *idev;
+ };
+@@ -446,9 +428,10 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
+ {
+ 	struct ifacaddr6 *im = NULL;
+ 	struct ac6_iter_state *state = ac6_seq_private(seq);
++	struct net *net = seq_file_net(seq);
+ 
+ 	state->idev = NULL;
+-	for_each_netdev(&init_net, state->dev) {
++	for_each_netdev(net, state->dev) {
+ 		struct inet6_dev *idev;
+ 		idev = in6_dev_get(state->dev);
+ 		if (!idev)
+@@ -546,8 +529,8 @@ static const struct seq_operations ac6_seq_ops = {
+ 
+ static int ac6_seq_open(struct inode *inode, struct file *file)
+ {
+-	return seq_open_private(file, &ac6_seq_ops,
+-			sizeof(struct ac6_iter_state));
++	return seq_open_net(inode, file, &ac6_seq_ops,
++			    sizeof(struct ac6_iter_state));
+ }
+ 
+ static const struct file_operations ac6_seq_fops = {
+@@ -555,20 +538,20 @@ static const struct file_operations ac6_seq_fops = {
+ 	.open		=	ac6_seq_open,
+ 	.read		=	seq_read,
+ 	.llseek		=	seq_lseek,
+-	.release	=	seq_release_private,
++	.release	=	seq_release_net,
+ };
+ 
+-int __init ac6_proc_init(void)
++int ac6_proc_init(struct net *net)
+ {
+-	if (!proc_net_fops_create(&init_net, "anycast6", S_IRUGO, &ac6_seq_fops))
++	if (!proc_net_fops_create(net, "anycast6", S_IRUGO, &ac6_seq_fops))
+ 		return -ENOMEM;
+ 
+ 	return 0;
+ }
+ 
+-void ac6_proc_exit(void)
++void ac6_proc_exit(struct net *net)
+ {
+-	proc_net_remove(&init_net, "anycast6");
++	proc_net_remove(net, "anycast6");
+ }
+ #endif
+ 
+diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
+index 695c0ca..8d05527 100644
+--- a/net/ipv6/fib6_rules.c
++++ b/net/ipv6/fib6_rules.c
+@@ -29,24 +29,22 @@ struct fib6_rule
+ 	u8			tclass;
+ };
+ 
+-static struct fib_rules_ops fib6_rules_ops;
+-
+-struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
+-				   pol_lookup_t lookup)
++struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
++				   int flags, pol_lookup_t lookup)
+ {
+ 	struct fib_lookup_arg arg = {
+ 		.lookup_ptr = lookup,
+ 	};
+ 
+-	fib_rules_lookup(&fib6_rules_ops, fl, flags, &arg);
++	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;
+ 
+-	dst_hold(&ip6_null_entry.u.dst);
+-	return &ip6_null_entry.u.dst;
++	dst_hold(&net->ipv6.ip6_null_entry->u.dst);
++	return &net->ipv6.ip6_null_entry->u.dst;
+ }
+ 
+ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
+@@ -54,28 +52,29 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
+ {
+ 	struct rt6_info *rt = NULL;
+ 	struct fib6_table *table;
++	struct net *net = rule->fr_net;
+ 	pol_lookup_t lookup = arg->lookup_ptr;
+ 
+ 	switch (rule->action) {
+ 	case FR_ACT_TO_TBL:
+ 		break;
+ 	case FR_ACT_UNREACHABLE:
+-		rt = &ip6_null_entry;
++		rt = net->ipv6.ip6_null_entry;
+ 		goto discard_pkt;
+ 	default:
+ 	case FR_ACT_BLACKHOLE:
+-		rt = &ip6_blk_hole_entry;
++		rt = net->ipv6.ip6_blk_hole_entry;
+ 		goto discard_pkt;
+ 	case FR_ACT_PROHIBIT:
+-		rt = &ip6_prohibit_entry;
++		rt = net->ipv6.ip6_prohibit_entry;
+ 		goto discard_pkt;
+ 	}
+ 
+-	table = fib6_get_table(rule->table);
++	table = fib6_get_table(net, rule->table);
+ 	if (table)
+-		rt = lookup(table, flp, flags);
++		rt = lookup(net, table, flp, flags);
+ 
+-	if (rt != &ip6_null_entry) {
++	if (rt != net->ipv6.ip6_null_entry) {
+ 		struct fib6_rule *r = (struct fib6_rule *)rule;
+ 
+ 		/*
+@@ -85,8 +84,18 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
+ 		if ((rule->flags & FIB_RULE_FIND_SADDR) &&
+ 		    r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) {
+ 			struct in6_addr saddr;
+-			if (ipv6_get_saddr(&rt->u.dst, &flp->fl6_dst,
+-					   &saddr))
++			unsigned int srcprefs = 0;
++
++			if (flags & RT6_LOOKUP_F_SRCPREF_TMP)
++				srcprefs |= IPV6_PREFER_SRC_TMP;
++			if (flags & RT6_LOOKUP_F_SRCPREF_PUBLIC)
++				srcprefs |= IPV6_PREFER_SRC_PUBLIC;
++			if (flags & RT6_LOOKUP_F_SRCPREF_COA)
++				srcprefs |= IPV6_PREFER_SRC_COA;
++
++			if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev,
++					       &flp->fl6_dst, srcprefs,
++					       &saddr))
+ 				goto again;
+ 			if (!ipv6_prefix_equal(&saddr, &r->src.addr,
+ 					       r->src.plen))
+@@ -145,13 +154,14 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
+ 			       struct nlattr **tb)
+ {
+ 	int err = -EINVAL;
++	struct net *net = sock_net(skb->sk);
+ 	struct fib6_rule *rule6 = (struct fib6_rule *) rule;
+ 
+ 	if (rule->action == FR_ACT_TO_TBL) {
+ 		if (rule->table == RT6_TABLE_UNSPEC)
+ 			goto errout;
+ 
+-		if (fib6_new_table(rule->table) == NULL) {
++		if (fib6_new_table(net, rule->table) == NULL) {
+ 			err = -ENOBUFS;
+ 			goto errout;
+ 		}
+@@ -234,7 +244,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
+ 	       + nla_total_size(16); /* src */
+ }
+ 
+-static struct fib_rules_ops fib6_rules_ops = {
++static struct fib_rules_ops fib6_rules_ops_template = {
+ 	.family			= AF_INET6,
+ 	.rule_size		= sizeof(struct fib6_rule),
+ 	.addr_size		= sizeof(struct in6_addr),
+@@ -247,45 +257,64 @@ static struct fib_rules_ops fib6_rules_ops = {
+ 	.nlmsg_payload		= fib6_rule_nlmsg_payload,
+ 	.nlgroup		= RTNLGRP_IPV6_RULE,
+ 	.policy			= fib6_rule_policy,
+-	.rules_list		= LIST_HEAD_INIT(fib6_rules_ops.rules_list),
+ 	.owner			= THIS_MODULE,
+ 	.fro_net		= &init_net,
+ };
+ 
+-static int __init fib6_default_rules_init(void)
++static int fib6_rules_net_init(struct net *net)
+ {
+-	int err;
++	int err = -ENOMEM;
+ 
+-	err = fib_default_rule_add(&fib6_rules_ops, 0,
+-				   RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
+-	if (err < 0)
+-		return err;
+-	err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
+-	if (err < 0)
+-		return err;
+-	return 0;
+-}
++	net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template,
++					   sizeof(*net->ipv6.fib6_rules_ops),
++					   GFP_KERNEL);
++	if (!net->ipv6.fib6_rules_ops)
++		goto out;
+ 
+-int __init fib6_rules_init(void)
+-{
+-	int ret;
++	net->ipv6.fib6_rules_ops->fro_net = net;
++	INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list);
+ 
+-	ret = fib6_default_rules_init();
+-	if (ret)
+-		goto out;
++	err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0,
++				   RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
++	if (err)
++		goto out_fib6_rules_ops;
+ 
+-	ret = fib_rules_register(&fib6_rules_ops);
+-	if (ret)
+-		goto out_default_rules_init;
++	err = fib_default_rule_add(net->ipv6.fib6_rules_ops,
++				   0x7FFE, RT6_TABLE_MAIN, 0);
++	if (err)
++		goto out_fib6_default_rule_add;
++
++	err = fib_rules_register(net->ipv6.fib6_rules_ops);
++	if (err)
++		goto out_fib6_default_rule_add;
+ out:
+-	return ret;
++	return err;
+ 
+-out_default_rules_init:
+-	fib_rules_cleanup_ops(&fib6_rules_ops);
++out_fib6_default_rule_add:
++	fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops);
++out_fib6_rules_ops:
++	kfree(net->ipv6.fib6_rules_ops);
+ 	goto out;
+ }
+ 
++static void fib6_rules_net_exit(struct net *net)
++{
++	fib_rules_unregister(net->ipv6.fib6_rules_ops);
++	kfree(net->ipv6.fib6_rules_ops);
++}
++
++static struct pernet_operations fib6_rules_net_ops = {
++	.init = fib6_rules_net_init,
++	.exit = fib6_rules_net_exit,
++};
++
++int __init fib6_rules_init(void)
++{
++	return register_pernet_subsys(&fib6_rules_net_ops);
++}
++
++
+ void fib6_rules_cleanup(void)
+ {
+-	fib_rules_unregister(&fib6_rules_ops);
++	unregister_pernet_subsys(&fib6_rules_net_ops);
+ }
+diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
+index 893287e..d42dd16 100644
+--- a/net/ipv6/icmp.c
++++ b/net/ipv6/icmp.c
+@@ -64,6 +64,7 @@
+ #include <net/addrconf.h>
+ #include <net/icmp.h>
+ #include <net/xfrm.h>
++#include <net/inet_common.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+@@ -80,8 +81,10 @@ EXPORT_SYMBOL(icmpv6msg_statistics);
+  *
+  *	On SMP we have one ICMP socket per-cpu.
+  */
+-static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL;
+-#define icmpv6_socket	__get_cpu_var(__icmpv6_socket)
++static inline struct sock *icmpv6_sk(struct net *net)
++{
++	return net->ipv6.icmp_sk[smp_processor_id()];
++}
+ 
+ static int icmpv6_rcv(struct sk_buff *skb);
+ 
+@@ -90,11 +93,11 @@ static struct inet6_protocol icmpv6_protocol = {
+ 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+ };
+ 
+-static __inline__ int icmpv6_xmit_lock(void)
++static __inline__ int icmpv6_xmit_lock(struct sock *sk)
+ {
+ 	local_bh_disable();
+ 
+-	if (unlikely(!spin_trylock(&icmpv6_socket->sk->sk_lock.slock))) {
++	if (unlikely(!spin_trylock(&sk->sk_lock.slock))) {
+ 		/* This can happen if the output path (f.e. SIT or
+ 		 * ip6ip6 tunnel) signals dst_link_failure() for an
+ 		 * outgoing ICMP6 packet.
+@@ -105,9 +108,9 @@ static __inline__ int icmpv6_xmit_lock(void)
+ 	return 0;
+ }
+ 
+-static __inline__ void icmpv6_xmit_unlock(void)
++static __inline__ void icmpv6_xmit_unlock(struct sock *sk)
+ {
+-	spin_unlock_bh(&icmpv6_socket->sk->sk_lock.slock);
++	spin_unlock_bh(&sk->sk_lock.slock);
+ }
+ 
+ /*
+@@ -161,6 +164,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
+ 				     struct flowi *fl)
+ {
+ 	struct dst_entry *dst;
++	struct net *net = sock_net(sk);
+ 	int res = 0;
+ 
+ 	/* Informational messages are not limited. */
+@@ -176,7 +180,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
+ 	 * XXX: perhaps the expire for routing entries cloned by
+ 	 * this lookup should be more aggressive (not longer than timeout).
+ 	 */
+-	dst = ip6_route_output(sk, fl);
++	dst = ip6_route_output(net, sk, fl);
+ 	if (dst->error) {
+ 		IP6_INC_STATS(ip6_dst_idev(dst),
+ 			      IPSTATS_MIB_OUTNOROUTES);
+@@ -184,7 +188,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
+ 		res = 1;
+ 	} else {
+ 		struct rt6_info *rt = (struct rt6_info *)dst;
+-		int tmo = init_net.ipv6.sysctl.icmpv6_time;
++		int tmo = net->ipv6.sysctl.icmpv6_time;
+ 
+ 		/* Give more bandwidth to wider prefixes. */
+ 		if (rt->rt6i_dst.plen < 128)
+@@ -303,6 +307,7 @@ static inline void mip6_addr_swap(struct sk_buff *skb) {}
+ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
+ 		 struct net_device *dev)
+ {
++	struct net *net = dev_net(skb->dev);
+ 	struct inet6_dev *idev = NULL;
+ 	struct ipv6hdr *hdr = ipv6_hdr(skb);
+ 	struct sock *sk;
+@@ -332,7 +337,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
+ 	 */
+ 	addr_type = ipv6_addr_type(&hdr->daddr);
+ 
+-	if (ipv6_chk_addr(&init_net, &hdr->daddr, skb->dev, 0))
++	if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0))
+ 		saddr = &hdr->daddr;
+ 
+ 	/*
+@@ -389,12 +394,12 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
+ 	fl.fl_icmp_code = code;
+ 	security_skb_classify_flow(skb, &fl);
+ 
+-	if (icmpv6_xmit_lock())
+-		return;
+-
+-	sk = icmpv6_socket->sk;
++	sk = icmpv6_sk(net);
+ 	np = inet6_sk(sk);
+ 
++	if (icmpv6_xmit_lock(sk))
++		return;
++
+ 	if (!icmpv6_xrlim_allow(sk, type, &fl))
+ 		goto out;
+ 
+@@ -462,9 +467,7 @@ route_done:
+ 	else
+ 		hlimit = np->hop_limit;
+ 	if (hlimit < 0)
+-		hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+-	if (hlimit < 0)
+-		hlimit = ipv6_get_hoplimit(dst->dev);
++		hlimit = ip6_dst_hoplimit(dst);
+ 
+ 	tclass = np->tclass;
+ 	if (tclass < 0)
+@@ -500,13 +503,14 @@ out_put:
+ out_dst_release:
+ 	dst_release(dst);
+ out:
+-	icmpv6_xmit_unlock();
++	icmpv6_xmit_unlock(sk);
+ }
+ 
+ EXPORT_SYMBOL(icmpv6_send);
+ 
+ static void icmpv6_echo_reply(struct sk_buff *skb)
+ {
++	struct net *net = dev_net(skb->dev);
+ 	struct sock *sk;
+ 	struct inet6_dev *idev;
+ 	struct ipv6_pinfo *np;
+@@ -537,12 +541,12 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
+ 	fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
+ 	security_skb_classify_flow(skb, &fl);
+ 
+-	if (icmpv6_xmit_lock())
+-		return;
+-
+-	sk = icmpv6_socket->sk;
++	sk = icmpv6_sk(net);
+ 	np = inet6_sk(sk);
+ 
++	if (icmpv6_xmit_lock(sk))
++		return;
++
+ 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
+ 		fl.oif = np->mcast_oif;
+ 
+@@ -557,9 +561,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
+ 	else
+ 		hlimit = np->hop_limit;
+ 	if (hlimit < 0)
+-		hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+-	if (hlimit < 0)
+-		hlimit = ipv6_get_hoplimit(dst->dev);
++		hlimit = ip6_dst_hoplimit(dst);
+ 
+ 	tclass = np->tclass;
+ 	if (tclass < 0)
+@@ -586,7 +588,7 @@ out_put:
+ 		in6_dev_put(idev);
+ 	dst_release(dst);
+ out:
+-	icmpv6_xmit_unlock();
++	icmpv6_xmit_unlock(sk);
+ }
+ 
+ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info)
+@@ -777,19 +779,40 @@ drop_no_count:
+ 	return 0;
+ }
+ 
++void icmpv6_flow_init(struct sock *sk, struct flowi *fl,
++		      u8 type,
++		      const struct in6_addr *saddr,
++		      const struct in6_addr *daddr,
++		      int oif)
++{
++	memset(fl, 0, sizeof(*fl));
++	ipv6_addr_copy(&fl->fl6_src, saddr);
++	ipv6_addr_copy(&fl->fl6_dst, daddr);
++	fl->proto	 	= IPPROTO_ICMPV6;
++	fl->fl_icmp_type	= type;
++	fl->fl_icmp_code	= 0;
++	fl->oif			= oif;
++	security_sk_classify_flow(sk, fl);
++}
++
+ /*
+- * Special lock-class for __icmpv6_socket:
++ * Special lock-class for __icmpv6_sk:
+  */
+ static struct lock_class_key icmpv6_socket_sk_dst_lock_key;
+ 
+-int __init icmpv6_init(struct net_proto_family *ops)
++static int __net_init icmpv6_sk_init(struct net *net)
+ {
+ 	struct sock *sk;
+ 	int err, i, j;
+ 
++	net->ipv6.icmp_sk =
++		kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
++	if (net->ipv6.icmp_sk == NULL)
++		return -ENOMEM;
++
+ 	for_each_possible_cpu(i) {
+-		err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
+-				       &per_cpu(__icmpv6_socket, i));
++		err = inet_ctl_sock_create(&sk, PF_INET6,
++					   SOCK_RAW, IPPROTO_ICMPV6, net);
+ 		if (err < 0) {
+ 			printk(KERN_ERR
+ 			       "Failed to initialize the ICMP6 control socket "
+@@ -798,12 +821,12 @@ int __init icmpv6_init(struct net_proto_family *ops)
+ 			goto fail;
+ 		}
+ 
+-		sk = per_cpu(__icmpv6_socket, i)->sk;
+-		sk->sk_allocation = GFP_ATOMIC;
++		net->ipv6.icmp_sk[i] = sk;
++
+ 		/*
+ 		 * Split off their lock-class, because sk->sk_dst_lock
+ 		 * gets used from softirqs, which is safe for
+-		 * __icmpv6_socket (because those never get directly used
++		 * __icmpv6_sk (because those never get directly used
+ 		 * via userspace syscalls), but unsafe for normal sockets.
+ 		 */
+ 		lockdep_set_class(&sk->sk_dst_lock,
+@@ -814,39 +837,57 @@ int __init icmpv6_init(struct net_proto_family *ops)
+ 		 */
+ 		sk->sk_sndbuf =
+ 			(2 * ((64 * 1024) + sizeof(struct sk_buff)));
+-
+-		sk->sk_prot->unhash(sk);
+ 	}
+-
+-
+-	if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) {
+-		printk(KERN_ERR "Failed to register ICMP6 protocol\n");
+-		err = -EAGAIN;
+-		goto fail;
+-	}
+-
+ 	return 0;
+ 
+  fail:
+-	for (j = 0; j < i; j++) {
+-		if (!cpu_possible(j))
+-			continue;
+-		sock_release(per_cpu(__icmpv6_socket, j));
+-	}
+-
++	for (j = 0; j < i; j++)
++		inet_ctl_sock_destroy(net->ipv6.icmp_sk[j]);
++	kfree(net->ipv6.icmp_sk);
+ 	return err;
+ }
+ 
+-void icmpv6_cleanup(void)
++static void __net_exit icmpv6_sk_exit(struct net *net)
+ {
+ 	int i;
+ 
+ 	for_each_possible_cpu(i) {
+-		sock_release(per_cpu(__icmpv6_socket, i));
++		inet_ctl_sock_destroy(net->ipv6.icmp_sk[i]);
+ 	}
++	kfree(net->ipv6.icmp_sk);
++}
++
++static struct pernet_operations icmpv6_sk_ops = {
++       .init = icmpv6_sk_init,
++       .exit = icmpv6_sk_exit,
++};
++
++int __init icmpv6_init(void)
++{
++	int err;
++
++	err = register_pernet_subsys(&icmpv6_sk_ops);
++	if (err < 0)
++		return err;
++
++	err = -EAGAIN;
++	if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0)
++		goto fail;
++	return 0;
++
++fail:
++	printk(KERN_ERR "Failed to register ICMP6 protocol\n");
++	unregister_pernet_subsys(&icmpv6_sk_ops);
++	return err;
++}
++
++void icmpv6_cleanup(void)
++{
++	unregister_pernet_subsys(&icmpv6_sk_ops);
+ 	inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
+ }
+ 
++
+ static const struct icmp6_err {
+ 	int err;
+ 	int fatal;
+@@ -927,6 +968,10 @@ struct ctl_table *ipv6_icmp_sysctl_init(struct net *net)
+ 	table = kmemdup(ipv6_icmp_table_template,
+ 			sizeof(ipv6_icmp_table_template),
+ 			GFP_KERNEL);
++
++	if (table)
++		table[0].data = &net->ipv6.sysctl.icmpv6_time;
++
+ 	return table;
+ }
+ #endif
+diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
+index 78de42a..87801cc 100644
+--- a/net/ipv6/inet6_connection_sock.c
++++ b/net/ipv6/inet6_connection_sock.c
+@@ -33,6 +33,10 @@ int inet6_csk_bind_conflict(const struct sock *sk,
+ 	const struct hlist_node *node;
+ 
+ 	/* We must walk the whole port owner list in this case. -DaveM */
++	/*
++	 * See comment in inet_csk_bind_conflict about sock lookup
++	 * vs net namespaces issues.
++	 */
+ 	sk_for_each_bound(sk2, node, &tb->owners) {
+ 		if (sk != sk2 &&
+ 		    (!sk->sk_bound_dev_if ||
+diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
+index 99fd25f..580014a 100644
+--- a/net/ipv6/inet6_hashtables.c
++++ b/net/ipv6/inet6_hashtables.c
+@@ -24,7 +24,7 @@
+ 
+ void __inet6_hash(struct sock *sk)
+ {
+-	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++	struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ 	struct hlist_head *list;
+ 	rwlock_t *lock;
+ 
+@@ -43,7 +43,7 @@ void __inet6_hash(struct sock *sk)
+ 	}
+ 
+ 	__sk_add_node(sk, list);
+-	sock_prot_inuse_add(sk->sk_prot, 1);
++	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ 	write_unlock(lock);
+ }
+ EXPORT_SYMBOL(__inet6_hash);
+@@ -105,7 +105,7 @@ struct sock *inet6_lookup_listener(struct net *net,
+ 
+ 	read_lock(&hashinfo->lhash_lock);
+ 	sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) {
+-		if (sk->sk_net == net && inet_sk(sk)->num == hnum &&
++		if (net_eq(sock_net(sk), net) && inet_sk(sk)->num == hnum &&
+ 				sk->sk_family == PF_INET6) {
+ 			const struct ipv6_pinfo *np = inet6_sk(sk);
+ 
+@@ -172,7 +172,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
+ 	struct sock *sk2;
+ 	const struct hlist_node *node;
+ 	struct inet_timewait_sock *tw;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 
+ 	prefetch(head->chain.first);
+ 	write_lock(lock);
+@@ -204,7 +204,7 @@ unique:
+ 	BUG_TRAP(sk_unhashed(sk));
+ 	__sk_add_node(sk, &head->chain);
+ 	sk->sk_hash = hash;
+-	sock_prot_inuse_add(sk->sk_prot, 1);
++	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ 	write_unlock(lock);
+ 
+ 	if (twp != NULL) {
+diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
+index bab72b6..1ee4fa1 100644
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -48,8 +48,6 @@
+ #define RT6_TRACE(x...) do { ; } while (0)
+ #endif
+ 
+-struct rt6_statistics	rt6_stats;
+-
+ static struct kmem_cache * fib6_node_kmem __read_mostly;
+ 
+ enum fib_walk_state_t
+@@ -66,6 +64,7 @@ enum fib_walk_state_t
+ struct fib6_cleaner_t
+ {
+ 	struct fib6_walker_t w;
++	struct net *net;
+ 	int (*func)(struct rt6_info *, void *arg);
+ 	void *arg;
+ };
+@@ -78,9 +77,10 @@ static DEFINE_RWLOCK(fib6_walker_lock);
+ #define FWS_INIT FWS_L
+ #endif
+ 
+-static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt);
+-static struct rt6_info * fib6_find_prefix(struct fib6_node *fn);
+-static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
++static void fib6_prune_clones(struct net *net, struct fib6_node *fn,
++			      struct rt6_info *rt);
++static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn);
++static struct fib6_node *fib6_repair_tree(struct net *net, struct fib6_node *fn);
+ static int fib6_walk(struct fib6_walker_t *w);
+ static int fib6_walk_continue(struct fib6_walker_t *w);
+ 
+@@ -93,7 +93,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w);
+ 
+ static __u32 rt_sernum;
+ 
+-static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0);
++static void fib6_gc_timer_cb(unsigned long arg);
+ 
+ static struct fib6_walker_t fib6_walker_list = {
+ 	.prev	= &fib6_walker_list,
+@@ -166,22 +166,13 @@ static __inline__ void rt6_release(struct rt6_info *rt)
+ 		dst_free(&rt->u.dst);
+ }
+ 
+-static struct fib6_table fib6_main_tbl = {
+-	.tb6_id		= RT6_TABLE_MAIN,
+-	.tb6_root	= {
+-		.leaf		= &ip6_null_entry,
+-		.fn_flags	= RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
+-	},
+-};
+-
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+ #define FIB_TABLE_HASHSZ 256
+ #else
+ #define FIB_TABLE_HASHSZ 1
+ #endif
+-static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
+ 
+-static void fib6_link_table(struct fib6_table *tb)
++static void fib6_link_table(struct net *net, struct fib6_table *tb)
+ {
+ 	unsigned int h;
+ 
+@@ -197,52 +188,46 @@ static void fib6_link_table(struct fib6_table *tb)
+ 	 * No protection necessary, this is the only list mutatation
+ 	 * operation, tables never disappear once they exist.
+ 	 */
+-	hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]);
++	hlist_add_head_rcu(&tb->tb6_hlist, &net->ipv6.fib_table_hash[h]);
+ }
+ 
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+-static struct fib6_table fib6_local_tbl = {
+-	.tb6_id		= RT6_TABLE_LOCAL,
+-	.tb6_root 	= {
+-		.leaf		= &ip6_null_entry,
+-		.fn_flags	= RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
+-	},
+-};
+ 
+-static struct fib6_table *fib6_alloc_table(u32 id)
++static struct fib6_table *fib6_alloc_table(struct net *net, u32 id)
+ {
+ 	struct fib6_table *table;
+ 
+ 	table = kzalloc(sizeof(*table), GFP_ATOMIC);
+ 	if (table != NULL) {
+ 		table->tb6_id = id;
+-		table->tb6_root.leaf = &ip6_null_entry;
++		table->tb6_root.leaf = net->ipv6.ip6_null_entry;
+ 		table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
+ 	}
+ 
+ 	return table;
+ }
+ 
+-struct fib6_table *fib6_new_table(u32 id)
++struct fib6_table *fib6_new_table(struct net *net, u32 id)
+ {
+ 	struct fib6_table *tb;
+ 
+ 	if (id == 0)
+ 		id = RT6_TABLE_MAIN;
+-	tb = fib6_get_table(id);
++	tb = fib6_get_table(net, id);
+ 	if (tb)
+ 		return tb;
+ 
+-	tb = fib6_alloc_table(id);
++	tb = fib6_alloc_table(net, id);
+ 	if (tb != NULL)
+-		fib6_link_table(tb);
++		fib6_link_table(net, tb);
+ 
+ 	return tb;
+ }
+ 
+-struct fib6_table *fib6_get_table(u32 id)
++struct fib6_table *fib6_get_table(struct net *net, u32 id)
+ {
+ 	struct fib6_table *tb;
++	struct hlist_head *head;
+ 	struct hlist_node *node;
+ 	unsigned int h;
+ 
+@@ -250,7 +235,8 @@ struct fib6_table *fib6_get_table(u32 id)
+ 		id = RT6_TABLE_MAIN;
+ 	h = id & (FIB_TABLE_HASHSZ - 1);
+ 	rcu_read_lock();
+-	hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) {
++	head = &net->ipv6.fib_table_hash[h];
++	hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) {
+ 		if (tb->tb6_id == id) {
+ 			rcu_read_unlock();
+ 			return tb;
+@@ -261,33 +247,32 @@ struct fib6_table *fib6_get_table(u32 id)
+ 	return NULL;
+ }
+ 
+-static void __init fib6_tables_init(void)
++static void fib6_tables_init(struct net *net)
+ {
+-	fib6_link_table(&fib6_main_tbl);
+-	fib6_link_table(&fib6_local_tbl);
++	fib6_link_table(net, net->ipv6.fib6_main_tbl);
++	fib6_link_table(net, net->ipv6.fib6_local_tbl);
+ }
+-
+ #else
+ 
+-struct fib6_table *fib6_new_table(u32 id)
++struct fib6_table *fib6_new_table(struct net *net, u32 id)
+ {
+-	return fib6_get_table(id);
++	return fib6_get_table(net, id);
+ }
+ 
+-struct fib6_table *fib6_get_table(u32 id)
++struct fib6_table *fib6_get_table(struct net *net, u32 id)
+ {
+-	return &fib6_main_tbl;
++	  return net->ipv6.fib6_main_tbl;
+ }
+ 
+-struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
+-				   pol_lookup_t lookup)
++struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
++				   int flags, pol_lookup_t lookup)
+ {
+-	return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags);
++	return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags);
+ }
+ 
+-static void __init fib6_tables_init(void)
++static void fib6_tables_init(struct net *net)
+ {
+-	fib6_link_table(&fib6_main_tbl);
++	fib6_link_table(net, net->ipv6.fib6_main_tbl);
+ }
+ 
+ #endif
+@@ -361,18 +346,16 @@ end:
+ 
+ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	unsigned int h, s_h;
+ 	unsigned int e = 0, s_e;
+ 	struct rt6_rtnl_dump_arg arg;
+ 	struct fib6_walker_t *w;
+ 	struct fib6_table *tb;
+ 	struct hlist_node *node;
++	struct hlist_head *head;
+ 	int res = 0;
+ 
+-	if (net != &init_net)
+-		return 0;
+-
+ 	s_h = cb->args[0];
+ 	s_e = cb->args[1];
+ 
+@@ -401,7 +384,8 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+ 
+ 	for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
+ 		e = 0;
+-		hlist_for_each_entry(tb, node, &fib_table_hash[h], tb6_hlist) {
++		head = &net->ipv6.fib_table_hash[h];
++		hlist_for_each_entry(tb, node, head, tb6_hlist) {
+ 			if (e < s_e)
+ 				goto next;
+ 			res = fib6_dump_table(tb, skb, cb);
+@@ -667,29 +651,29 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
+ 	rt->rt6i_node = fn;
+ 	atomic_inc(&rt->rt6i_ref);
+ 	inet6_rt_notify(RTM_NEWROUTE, rt, info);
+-	rt6_stats.fib_rt_entries++;
++	info->nl_net->ipv6.rt6_stats->fib_rt_entries++;
+ 
+ 	if ((fn->fn_flags & RTN_RTINFO) == 0) {
+-		rt6_stats.fib_route_nodes++;
++		info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
+ 		fn->fn_flags |= RTN_RTINFO;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-static __inline__ void fib6_start_gc(struct rt6_info *rt)
++static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt)
+ {
+-	if (ip6_fib_timer.expires == 0 &&
++	if (net->ipv6.ip6_fib_timer->expires == 0 &&
+ 	    (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE)))
+-		mod_timer(&ip6_fib_timer, jiffies +
+-			  init_net.ipv6.sysctl.ip6_rt_gc_interval);
++		mod_timer(net->ipv6.ip6_fib_timer, jiffies +
++			  net->ipv6.sysctl.ip6_rt_gc_interval);
+ }
+ 
+-void fib6_force_start_gc(void)
++void fib6_force_start_gc(struct net *net)
+ {
+-	if (ip6_fib_timer.expires == 0)
+-		mod_timer(&ip6_fib_timer, jiffies +
+-			  init_net.ipv6.sysctl.ip6_rt_gc_interval);
++	if (net->ipv6.ip6_fib_timer->expires == 0)
++		mod_timer(net->ipv6.ip6_fib_timer, jiffies +
++			  net->ipv6.sysctl.ip6_rt_gc_interval);
+ }
+ 
+ /*
+@@ -733,8 +717,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
+ 			if (sfn == NULL)
+ 				goto st_failure;
+ 
+-			sfn->leaf = &ip6_null_entry;
+-			atomic_inc(&ip6_null_entry.rt6i_ref);
++			sfn->leaf = info->nl_net->ipv6.ip6_null_entry;
++			atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref);
+ 			sfn->fn_flags = RTN_ROOT;
+ 			sfn->fn_sernum = fib6_new_sernum();
+ 
+@@ -776,9 +760,9 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
+ 	err = fib6_add_rt2node(fn, rt, info);
+ 
+ 	if (err == 0) {
+-		fib6_start_gc(rt);
++		fib6_start_gc(info->nl_net, rt);
+ 		if (!(rt->rt6i_flags&RTF_CACHE))
+-			fib6_prune_clones(pn, rt);
++			fib6_prune_clones(info->nl_net, pn, rt);
+ 	}
+ 
+ out:
+@@ -788,12 +772,16 @@ out:
+ 		 * If fib6_add_1 has cleared the old leaf pointer in the
+ 		 * super-tree leaf node we have to find a new one for it.
+ 		 */
++		if (pn != fn && pn->leaf == rt) {
++			pn->leaf = NULL;
++			atomic_dec(&rt->rt6i_ref);
++		}
+ 		if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) {
+-			pn->leaf = fib6_find_prefix(pn);
++			pn->leaf = fib6_find_prefix(info->nl_net, pn);
+ #if RT6_DEBUG >= 2
+ 			if (!pn->leaf) {
+ 				BUG_TRAP(pn->leaf != NULL);
+-				pn->leaf = &ip6_null_entry;
++				pn->leaf = info->nl_net->ipv6.ip6_null_entry;
+ 			}
+ #endif
+ 			atomic_inc(&pn->leaf->rt6i_ref);
+@@ -809,7 +797,7 @@ out:
+ 	 */
+ st_failure:
+ 	if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT)))
+-		fib6_repair_tree(fn);
++		fib6_repair_tree(info->nl_net, fn);
+ 	dst_free(&rt->u.dst);
+ 	return err;
+ #endif
+@@ -975,10 +963,10 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
+  *
+  */
+ 
+-static struct rt6_info * fib6_find_prefix(struct fib6_node *fn)
++static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn)
+ {
+ 	if (fn->fn_flags&RTN_ROOT)
+-		return &ip6_null_entry;
++		return net->ipv6.ip6_null_entry;
+ 
+ 	while(fn) {
+ 		if(fn->left)
+@@ -997,7 +985,8 @@ static struct rt6_info * fib6_find_prefix(struct fib6_node *fn)
+  *	is the node we want to try and remove.
+  */
+ 
+-static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
++static struct fib6_node *fib6_repair_tree(struct net *net,
++					   struct fib6_node *fn)
+ {
+ 	int children;
+ 	int nstate;
+@@ -1024,11 +1013,11 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
+ 		    || (children && fn->fn_flags&RTN_ROOT)
+ #endif
+ 		    ) {
+-			fn->leaf = fib6_find_prefix(fn);
++			fn->leaf = fib6_find_prefix(net, fn);
+ #if RT6_DEBUG >= 2
+ 			if (fn->leaf==NULL) {
+ 				BUG_TRAP(fn->leaf);
+-				fn->leaf = &ip6_null_entry;
++				fn->leaf = net->ipv6.ip6_null_entry;
+ 			}
+ #endif
+ 			atomic_inc(&fn->leaf->rt6i_ref);
+@@ -1101,14 +1090,15 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+ {
+ 	struct fib6_walker_t *w;
+ 	struct rt6_info *rt = *rtp;
++	struct net *net = info->nl_net;
+ 
+ 	RT6_TRACE("fib6_del_route\n");
+ 
+ 	/* Unlink it */
+ 	*rtp = rt->u.dst.rt6_next;
+ 	rt->rt6i_node = NULL;
+-	rt6_stats.fib_rt_entries--;
+-	rt6_stats.fib_discarded_routes++;
++	net->ipv6.rt6_stats->fib_rt_entries--;
++	net->ipv6.rt6_stats->fib_discarded_routes++;
+ 
+ 	/* Reset round-robin state, if necessary */
+ 	if (fn->rr_ptr == rt)
+@@ -1131,8 +1121,8 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+ 	/* If it was last route, expunge its radix tree node */
+ 	if (fn->leaf == NULL) {
+ 		fn->fn_flags &= ~RTN_RTINFO;
+-		rt6_stats.fib_route_nodes--;
+-		fn = fib6_repair_tree(fn);
++		net->ipv6.rt6_stats->fib_route_nodes--;
++		fn = fib6_repair_tree(net, fn);
+ 	}
+ 
+ 	if (atomic_read(&rt->rt6i_ref) != 1) {
+@@ -1144,7 +1134,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+ 		 */
+ 		while (fn) {
+ 			if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) {
+-				fn->leaf = fib6_find_prefix(fn);
++				fn->leaf = fib6_find_prefix(net, fn);
+ 				atomic_inc(&fn->leaf->rt6i_ref);
+ 				rt6_release(rt);
+ 			}
+@@ -1160,6 +1150,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+ 
+ int fib6_del(struct rt6_info *rt, struct nl_info *info)
+ {
++	struct net *net = info->nl_net;
+ 	struct fib6_node *fn = rt->rt6i_node;
+ 	struct rt6_info **rtp;
+ 
+@@ -1169,7 +1160,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
+ 		return -ENOENT;
+ 	}
+ #endif
+-	if (fn == NULL || rt == &ip6_null_entry)
++	if (fn == NULL || rt == net->ipv6.ip6_null_entry)
+ 		return -ENOENT;
+ 
+ 	BUG_TRAP(fn->fn_flags&RTN_RTINFO);
+@@ -1184,7 +1175,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
+ 			pn = pn->parent;
+ 		}
+ #endif
+-		fib6_prune_clones(pn, rt);
++		fib6_prune_clones(info->nl_net, pn, rt);
+ 	}
+ 
+ 	/*
+@@ -1314,12 +1305,12 @@ static int fib6_walk(struct fib6_walker_t *w)
+ 
+ static int fib6_clean_node(struct fib6_walker_t *w)
+ {
+-	struct nl_info info = {
+-		.nl_net = &init_net,
+-	};
+ 	int res;
+ 	struct rt6_info *rt;
+ 	struct fib6_cleaner_t *c = container_of(w, struct fib6_cleaner_t, w);
++	struct nl_info info = {
++		.nl_net = c->net,
++	};
+ 
+ 	for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) {
+ 		res = c->func(rt, c->arg);
+@@ -1351,7 +1342,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
+  *	ignoring pure split nodes) will be scanned.
+  */
+ 
+-static void fib6_clean_tree(struct fib6_node *root,
++static void fib6_clean_tree(struct net *net, struct fib6_node *root,
+ 			    int (*func)(struct rt6_info *, void *arg),
+ 			    int prune, void *arg)
+ {
+@@ -1362,23 +1353,26 @@ static void fib6_clean_tree(struct fib6_node *root,
+ 	c.w.prune = prune;
+ 	c.func = func;
+ 	c.arg = arg;
++	c.net = net;
+ 
+ 	fib6_walk(&c.w);
+ }
+ 
+-void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
++void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
+ 		    int prune, void *arg)
+ {
+ 	struct fib6_table *table;
+ 	struct hlist_node *node;
++	struct hlist_head *head;
+ 	unsigned int h;
+ 
+ 	rcu_read_lock();
+ 	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
+-		hlist_for_each_entry_rcu(table, node, &fib_table_hash[h],
+-					 tb6_hlist) {
++		head = &net->ipv6.fib_table_hash[h];
++		hlist_for_each_entry_rcu(table, node, head, tb6_hlist) {
+ 			write_lock_bh(&table->tb6_lock);
+-			fib6_clean_tree(&table->tb6_root, func, prune, arg);
++			fib6_clean_tree(net, &table->tb6_root,
++					func, prune, arg);
+ 			write_unlock_bh(&table->tb6_lock);
+ 		}
+ 	}
+@@ -1395,9 +1389,10 @@ static int fib6_prune_clone(struct rt6_info *rt, void *arg)
+ 	return 0;
+ }
+ 
+-static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt)
++static void fib6_prune_clones(struct net *net, struct fib6_node *fn,
++			      struct rt6_info *rt)
+ {
+-	fib6_clean_tree(fn, fib6_prune_clone, 1, rt);
++	fib6_clean_tree(net, fn, fib6_prune_clone, 1, rt);
+ }
+ 
+ /*
+@@ -1447,54 +1442,145 @@ static int fib6_age(struct rt6_info *rt, void *arg)
+ 
+ static DEFINE_SPINLOCK(fib6_gc_lock);
+ 
+-void fib6_run_gc(unsigned long dummy)
++void fib6_run_gc(unsigned long expires, struct net *net)
+ {
+-	if (dummy != ~0UL) {
++	if (expires != ~0UL) {
+ 		spin_lock_bh(&fib6_gc_lock);
+-		gc_args.timeout = dummy ? (int)dummy :
+-			init_net.ipv6.sysctl.ip6_rt_gc_interval;
++		gc_args.timeout = expires ? (int)expires :
++			net->ipv6.sysctl.ip6_rt_gc_interval;
+ 	} else {
+ 		local_bh_disable();
+ 		if (!spin_trylock(&fib6_gc_lock)) {
+-			mod_timer(&ip6_fib_timer, jiffies + HZ);
++			mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ);
+ 			local_bh_enable();
+ 			return;
+ 		}
+-		gc_args.timeout = init_net.ipv6.sysctl.ip6_rt_gc_interval;
++		gc_args.timeout = net->ipv6.sysctl.ip6_rt_gc_interval;
+ 	}
+ 	gc_args.more = 0;
+ 
+-	ndisc_dst_gc(&gc_args.more);
+-	fib6_clean_all(fib6_age, 0, NULL);
++	icmp6_dst_gc(&gc_args.more);
++
++	fib6_clean_all(net, fib6_age, 0, NULL);
+ 
+ 	if (gc_args.more)
+-		mod_timer(&ip6_fib_timer, jiffies +
+-			  init_net.ipv6.sysctl.ip6_rt_gc_interval);
++		mod_timer(net->ipv6.ip6_fib_timer, jiffies +
++			  net->ipv6.sysctl.ip6_rt_gc_interval);
+ 	else {
+-		del_timer(&ip6_fib_timer);
+-		ip6_fib_timer.expires = 0;
++		del_timer(net->ipv6.ip6_fib_timer);
++		net->ipv6.ip6_fib_timer->expires = 0;
+ 	}
+ 	spin_unlock_bh(&fib6_gc_lock);
+ }
+ 
+-int __init fib6_init(void)
++static void fib6_gc_timer_cb(unsigned long arg)
++{
++	fib6_run_gc(0, (struct net *)arg);
++}
++
++static int fib6_net_init(struct net *net)
+ {
+ 	int ret;
++	struct timer_list *timer;
++
++	ret = -ENOMEM;
++	timer = kzalloc(sizeof(*timer), GFP_KERNEL);
++	if (!timer)
++		goto out;
++
++	setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net);
++	net->ipv6.ip6_fib_timer = timer;
++
++	net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL);
++	if (!net->ipv6.rt6_stats)
++		goto out_timer;
++
++	net->ipv6.fib_table_hash =
++		kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
++			GFP_KERNEL);
++	if (!net->ipv6.fib_table_hash)
++		goto out_rt6_stats;
++
++	net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl),
++					  GFP_KERNEL);
++	if (!net->ipv6.fib6_main_tbl)
++		goto out_fib_table_hash;
++
++	net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
++	net->ipv6.fib6_main_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry;
++	net->ipv6.fib6_main_tbl->tb6_root.fn_flags =
++		RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
++
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++	net->ipv6.fib6_local_tbl = kzalloc(sizeof(*net->ipv6.fib6_local_tbl),
++					   GFP_KERNEL);
++	if (!net->ipv6.fib6_local_tbl)
++		goto out_fib6_main_tbl;
++	net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
++	net->ipv6.fib6_local_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry;
++	net->ipv6.fib6_local_tbl->tb6_root.fn_flags =
++		RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
++#endif
++	fib6_tables_init(net);
++
++	ret = 0;
++out:
++	return ret;
++
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++out_fib6_main_tbl:
++	kfree(net->ipv6.fib6_main_tbl);
++#endif
++out_fib_table_hash:
++	kfree(net->ipv6.fib_table_hash);
++out_rt6_stats:
++	kfree(net->ipv6.rt6_stats);
++out_timer:
++	kfree(timer);
++	goto out;
++ }
++
++static void fib6_net_exit(struct net *net)
++{
++	rt6_ifdown(net, NULL);
++	del_timer_sync(net->ipv6.ip6_fib_timer);
++	kfree(net->ipv6.ip6_fib_timer);
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++	kfree(net->ipv6.fib6_local_tbl);
++#endif
++	kfree(net->ipv6.fib6_main_tbl);
++	kfree(net->ipv6.fib_table_hash);
++	kfree(net->ipv6.rt6_stats);
++}
++
++static struct pernet_operations fib6_net_ops = {
++	.init = fib6_net_init,
++	.exit = fib6_net_exit,
++};
++
++int __init fib6_init(void)
++{
++	int ret = -ENOMEM;
++
+ 	fib6_node_kmem = kmem_cache_create("fib6_nodes",
+ 					   sizeof(struct fib6_node),
+ 					   0, SLAB_HWCACHE_ALIGN,
+ 					   NULL);
+ 	if (!fib6_node_kmem)
+-		return -ENOMEM;
++		goto out;
+ 
+-	fib6_tables_init();
++	ret = register_pernet_subsys(&fib6_net_ops);
++	if (ret)
++		goto out_kmem_cache_create;
+ 
+ 	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
+ 	if (ret)
+-		goto out_kmem_cache_create;
++		goto out_unregister_subsys;
+ out:
+ 	return ret;
+ 
++out_unregister_subsys:
++	unregister_pernet_subsys(&fib6_net_ops);
+ out_kmem_cache_create:
+ 	kmem_cache_destroy(fib6_node_kmem);
+ 	goto out;
+@@ -1502,6 +1588,6 @@ out_kmem_cache_create:
+ 
+ void fib6_gc_cleanup(void)
+ {
+-	del_timer(&ip6_fib_timer);
++	unregister_pernet_subsys(&fib6_net_ops);
+ 	kmem_cache_destroy(fib6_node_kmem);
+ }
+diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
+index 2b7d9ee..eb7a940 100644
+--- a/net/ipv6/ip6_flowlabel.c
++++ b/net/ipv6/ip6_flowlabel.c
+@@ -62,23 +62,23 @@ static DEFINE_RWLOCK(ip6_fl_lock);
+ static DEFINE_RWLOCK(ip6_sk_fl_lock);
+ 
+ 
+-static __inline__ struct ip6_flowlabel * __fl_lookup(__be32 label)
++static inline struct ip6_flowlabel *__fl_lookup(struct net *net, __be32 label)
+ {
+ 	struct ip6_flowlabel *fl;
+ 
+ 	for (fl=fl_ht[FL_HASH(label)]; fl; fl = fl->next) {
+-		if (fl->label == label)
++		if (fl->label == label && fl->fl_net == net)
+ 			return fl;
+ 	}
+ 	return NULL;
+ }
+ 
+-static struct ip6_flowlabel * fl_lookup(__be32 label)
++static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label)
+ {
+ 	struct ip6_flowlabel *fl;
+ 
+ 	read_lock_bh(&ip6_fl_lock);
+-	fl = __fl_lookup(label);
++	fl = __fl_lookup(net, label);
+ 	if (fl)
+ 		atomic_inc(&fl->users);
+ 	read_unlock_bh(&ip6_fl_lock);
+@@ -88,8 +88,10 @@ static struct ip6_flowlabel * fl_lookup(__be32 label)
+ 
+ static void fl_free(struct ip6_flowlabel *fl)
+ {
+-	if (fl)
++	if (fl) {
++		release_net(fl->fl_net);
+ 		kfree(fl->opt);
++	}
+ 	kfree(fl);
+ }
+ 
+@@ -112,7 +114,6 @@ static void fl_release(struct ip6_flowlabel *fl)
+ 		    time_after(ip6_fl_gc_timer.expires, ttd))
+ 			mod_timer(&ip6_fl_gc_timer, ttd);
+ 	}
+-
+ 	write_unlock_bh(&ip6_fl_lock);
+ }
+ 
+@@ -148,13 +149,34 @@ static void ip6_fl_gc(unsigned long dummy)
+ 	if (!sched && atomic_read(&fl_size))
+ 		sched = now + FL_MAX_LINGER;
+ 	if (sched) {
+-		ip6_fl_gc_timer.expires = sched;
+-		add_timer(&ip6_fl_gc_timer);
++		mod_timer(&ip6_fl_gc_timer, sched);
++	}
++	write_unlock(&ip6_fl_lock);
++}
++
++static void ip6_fl_purge(struct net *net)
++{
++	int i;
++
++	write_lock(&ip6_fl_lock);
++	for (i = 0; i <= FL_HASH_MASK; i++) {
++		struct ip6_flowlabel *fl, **flp;
++		flp = &fl_ht[i];
++		while ((fl = *flp) != NULL) {
++			if (fl->fl_net == net && atomic_read(&fl->users) == 0) {
++				*flp = fl->next;
++				fl_free(fl);
++				atomic_dec(&fl_size);
++				continue;
++			}
++			flp = &fl->next;
++		}
+ 	}
+ 	write_unlock(&ip6_fl_lock);
+ }
+ 
+-static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label)
++static struct ip6_flowlabel *fl_intern(struct net *net,
++				       struct ip6_flowlabel *fl, __be32 label)
+ {
+ 	struct ip6_flowlabel *lfl;
+ 
+@@ -165,7 +187,7 @@ static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label)
+ 		for (;;) {
+ 			fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK;
+ 			if (fl->label) {
+-				lfl = __fl_lookup(fl->label);
++				lfl = __fl_lookup(net, fl->label);
+ 				if (lfl == NULL)
+ 					break;
+ 			}
+@@ -179,7 +201,7 @@ static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label)
+ 		 * done in ipv6_flowlabel_opt - sock is locked, so new entry
+ 		 * with the same label can only appear on another sock
+ 		 */
+-		lfl = __fl_lookup(fl->label);
++		lfl = __fl_lookup(net, fl->label);
+ 		if (lfl != NULL) {
+ 			atomic_inc(&lfl->users);
+ 			write_unlock_bh(&ip6_fl_lock);
+@@ -298,7 +320,8 @@ static int fl6_renew(struct ip6_flowlabel *fl, unsigned long linger, unsigned lo
+ }
+ 
+ static struct ip6_flowlabel *
+-fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *err_p)
++fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval,
++	  int optlen, int *err_p)
+ {
+ 	struct ip6_flowlabel *fl;
+ 	int olen;
+@@ -343,6 +366,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
+ 		}
+ 	}
+ 
++	fl->fl_net = hold_net(net);
+ 	fl->expires = jiffies;
+ 	err = fl6_renew(fl, freq->flr_linger, freq->flr_expires);
+ 	if (err)
+@@ -441,6 +465,7 @@ static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl,
+ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
+ {
+ 	int err;
++	struct net *net = sock_net(sk);
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+ 	struct in6_flowlabel_req freq;
+ 	struct ipv6_fl_socklist *sfl1=NULL;
+@@ -483,7 +508,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
+ 		read_unlock_bh(&ip6_sk_fl_lock);
+ 
+ 		if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) {
+-			fl = fl_lookup(freq.flr_label);
++			fl = fl_lookup(net, freq.flr_label);
+ 			if (fl) {
+ 				err = fl6_renew(fl, freq.flr_linger, freq.flr_expires);
+ 				fl_release(fl);
+@@ -496,7 +521,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
+ 		if (freq.flr_label & ~IPV6_FLOWLABEL_MASK)
+ 			return -EINVAL;
+ 
+-		fl = fl_create(&freq, optval, optlen, &err);
++		fl = fl_create(net, &freq, optval, optlen, &err);
+ 		if (fl == NULL)
+ 			return err;
+ 		sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL);
+@@ -518,7 +543,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
+ 			read_unlock_bh(&ip6_sk_fl_lock);
+ 
+ 			if (fl1 == NULL)
+-				fl1 = fl_lookup(freq.flr_label);
++				fl1 = fl_lookup(net, freq.flr_label);
+ 			if (fl1) {
+ recheck:
+ 				err = -EEXIST;
+@@ -559,7 +584,7 @@ release:
+ 		if (sfl1 == NULL || (err = mem_check(sk)) != 0)
+ 			goto done;
+ 
+-		fl1 = fl_intern(fl, freq.flr_label);
++		fl1 = fl_intern(net, fl, freq.flr_label);
+ 		if (fl1 != NULL)
+ 			goto recheck;
+ 
+@@ -586,6 +611,7 @@ done:
+ #ifdef CONFIG_PROC_FS
+ 
+ struct ip6fl_iter_state {
++	struct seq_net_private p;
+ 	int bucket;
+ };
+ 
+@@ -595,12 +621,15 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq)
+ {
+ 	struct ip6_flowlabel *fl = NULL;
+ 	struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
++	struct net *net = seq_file_net(seq);
+ 
+ 	for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) {
+-		if (fl_ht[state->bucket]) {
+-			fl = fl_ht[state->bucket];
++		fl = fl_ht[state->bucket];
++
++		while (fl && fl->fl_net != net)
++			fl = fl->next;
++		if (fl)
+ 			break;
+-		}
+ 	}
+ 	return fl;
+ }
+@@ -608,12 +637,18 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq)
+ static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl)
+ {
+ 	struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
++	struct net *net = seq_file_net(seq);
+ 
+ 	fl = fl->next;
++try_again:
++	while (fl && fl->fl_net != net)
++		fl = fl->next;
++
+ 	while (!fl) {
+-		if (++state->bucket <= FL_HASH_MASK)
++		if (++state->bucket <= FL_HASH_MASK) {
+ 			fl = fl_ht[state->bucket];
+-		else
++			goto try_again;
++		} else
+ 			break;
+ 	}
+ 	return fl;
+@@ -683,8 +718,8 @@ static const struct seq_operations ip6fl_seq_ops = {
+ 
+ static int ip6fl_seq_open(struct inode *inode, struct file *file)
+ {
+-	return seq_open_private(file, &ip6fl_seq_ops,
+-			sizeof(struct ip6fl_iter_state));
++	return seq_open_net(inode, file, &ip6fl_seq_ops,
++			    sizeof(struct ip6fl_iter_state));
+ }
+ 
+ static const struct file_operations ip6fl_seq_fops = {
+@@ -692,12 +727,13 @@ static const struct file_operations ip6fl_seq_fops = {
+ 	.open		=	ip6fl_seq_open,
+ 	.read		=	seq_read,
+ 	.llseek		=	seq_lseek,
+-	.release	=	seq_release_private,
++	.release	=	seq_release_net,
+ };
+ 
+ static int ip6_flowlabel_proc_init(struct net *net)
+ {
+-	if (!proc_net_fops_create(net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops))
++	if (!proc_net_fops_create(net, "ip6_flowlabel",
++				  S_IRUGO, &ip6fl_seq_fops))
+ 		return -ENOMEM;
+ 	return 0;
+ }
+@@ -717,13 +753,24 @@ static inline void ip6_flowlabel_proc_fini(struct net *net)
+ }
+ #endif
+ 
++static inline void ip6_flowlabel_net_exit(struct net *net)
++{
++	ip6_fl_purge(net);
++	ip6_flowlabel_proc_fini(net);
++}
++
++static struct pernet_operations ip6_flowlabel_net_ops = {
++	.init = ip6_flowlabel_proc_init,
++	.exit = ip6_flowlabel_net_exit,
++};
++
+ int ip6_flowlabel_init(void)
+ {
+-	return ip6_flowlabel_proc_init(&init_net);
++	return register_pernet_subsys(&ip6_flowlabel_net_ops);
+ }
+ 
+ void ip6_flowlabel_cleanup(void)
+ {
+ 	del_timer(&ip6_fl_gc_timer);
+-	ip6_flowlabel_proc_fini(&init_net);
++	unregister_pernet_subsys(&ip6_flowlabel_net_ops);
+ }
+diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
+index 98ab4f4..4e5c861 100644
+--- a/net/ipv6/ip6_input.c
++++ b/net/ipv6/ip6_input.c
+@@ -29,6 +29,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/in6.h>
+ #include <linux/icmpv6.h>
++#include <linux/mroute6.h>
+ 
+ #include <linux/netfilter.h>
+ #include <linux/netfilter_ipv6.h>
+@@ -61,11 +62,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
+ 	u32 		pkt_len;
+ 	struct inet6_dev *idev;
+ 
+-	if (dev->nd_net != &init_net) {
+-		kfree_skb(skb);
+-		return 0;
+-	}
+-
+ 	if (skb->pkt_type == PACKET_OTHERHOST) {
+ 		kfree_skb(skb);
+ 		return 0;
+@@ -241,38 +237,84 @@ int ip6_mc_input(struct sk_buff *skb)
+ 	hdr = ipv6_hdr(skb);
+ 	deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
+ 
++#ifdef CONFIG_IPV6_MROUTE
+ 	/*
+-	 *	IPv6 multicast router mode isnt currently supported.
++	 *      IPv6 multicast router mode is now supported ;)
+ 	 */
+-#if 0
+-	if (ipv6_config.multicast_route) {
+-		int addr_type;
+-
+-		addr_type = ipv6_addr_type(&hdr->daddr);
+-
+-		if (!(addr_type & (IPV6_ADDR_LOOPBACK | IPV6_ADDR_LINKLOCAL))) {
+-			struct sk_buff *skb2;
+-			struct dst_entry *dst;
++	if (ipv6_devconf.mc_forwarding &&
++	    likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
++		/*
++		 * Okay, we try to forward - split and duplicate
++		 * packets.
++		 */
++		struct sk_buff *skb2;
++		struct inet6_skb_parm *opt = IP6CB(skb);
++
++		/* Check for MLD */
++		if (unlikely(opt->ra)) {
++			/* Check if this is a mld message */
++			u8 *ptr = skb_network_header(skb) + opt->ra;
++			struct icmp6hdr *icmp6;
++			u8 nexthdr = hdr->nexthdr;
++			int offset;
++
++			/* Check if the value of Router Alert
++			 * is for MLD (0x0000).
++			 */
++			if ((ptr[2] | ptr[3]) == 0) {
++				deliver = 0;
++
++				if (!ipv6_ext_hdr(nexthdr)) {
++					/* BUG */
++					goto out;
++				}
++				offset = ipv6_skip_exthdr(skb, sizeof(*hdr),
++							  &nexthdr);
++				if (offset < 0)
++					goto out;
++
++				if (nexthdr != IPPROTO_ICMPV6)
++					goto out;
++
++				if (!pskb_may_pull(skb, (skb_network_header(skb) +
++						   offset + 1 - skb->data)))
++					goto out;
++
++				icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset);
++
++				switch (icmp6->icmp6_type) {
++				case ICMPV6_MGM_QUERY:
++				case ICMPV6_MGM_REPORT:
++				case ICMPV6_MGM_REDUCTION:
++				case ICMPV6_MLD2_REPORT:
++					deliver = 1;
++					break;
++				}
++				goto out;
++			}
++			/* unknown RA - process it normally */
++		}
+ 
+-			dst = skb->dst;
++		if (deliver)
++			skb2 = skb_clone(skb, GFP_ATOMIC);
++		else {
++			skb2 = skb;
++			skb = NULL;
++		}
+ 
+-			if (deliver) {
+-				skb2 = skb_clone(skb, GFP_ATOMIC);
+-				dst_output(skb2);
+-			} else {
+-				dst_output(skb);
+-				return 0;
+-			}
++		if (skb2) {
++			skb2->dev = skb2->dst->dev;
++			ip6_mr_input(skb2);
+ 		}
+ 	}
++out:
+ #endif
+-
+-	if (likely(deliver)) {
++	if (likely(deliver))
+ 		ip6_input(skb);
+-		return 0;
++	else {
++		/* discard */
++		kfree_skb(skb);
+ 	}
+-	/* discard */
+-	kfree_skb(skb);
+ 
+ 	return 0;
+ }
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 8b67ca0..0af2e05 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -55,6 +55,7 @@
+ #include <net/icmp.h>
+ #include <net/xfrm.h>
+ #include <net/checksum.h>
++#include <linux/mroute6.h>
+ 
+ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
+ 
+@@ -137,8 +138,9 @@ static int ip6_output2(struct sk_buff *skb)
+ 		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
+ 
+ 		if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) &&
+-		    ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
+-					&ipv6_hdr(skb)->saddr)) {
++		    ((mroute6_socket && !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
++		     ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
++					 &ipv6_hdr(skb)->saddr))) {
+ 			struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
+ 
+ 			/* Do not check for IFF_ALLMULTI; multicast routing
+@@ -237,9 +239,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
+ 	if (np)
+ 		hlimit = np->hop_limit;
+ 	if (hlimit < 0)
+-		hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+-	if (hlimit < 0)
+-		hlimit = ipv6_get_hoplimit(dst->dev);
++		hlimit = ip6_dst_hoplimit(dst);
+ 
+ 	tclass = -1;
+ 	if (np)
+@@ -286,7 +286,7 @@ EXPORT_SYMBOL(ip6_xmit);
+  */
+ 
+ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,
+-	       struct in6_addr *saddr, struct in6_addr *daddr,
++	       const struct in6_addr *saddr, const struct in6_addr *daddr,
+ 	       int proto, int len)
+ {
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+@@ -404,6 +404,7 @@ int ip6_forward(struct sk_buff *skb)
+ 	struct dst_entry *dst = skb->dst;
+ 	struct ipv6hdr *hdr = ipv6_hdr(skb);
+ 	struct inet6_skb_parm *opt = IP6CB(skb);
++	struct net *net = dev_net(dst->dev);
+ 
+ 	if (ipv6_devconf.forwarding == 0)
+ 		goto error;
+@@ -450,7 +451,7 @@ int ip6_forward(struct sk_buff *skb)
+ 
+ 	/* XXX: idev->cnf.proxy_ndp? */
+ 	if (ipv6_devconf.proxy_ndp &&
+-	    pneigh_lookup(&nd_tbl, &init_net, &hdr->daddr, skb->dev, 0)) {
++	    pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) {
+ 		int proxied = ip6_forward_proxy_check(skb);
+ 		if (proxied > 0)
+ 			return ip6_input(skb);
+@@ -596,7 +597,6 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
+ 
+ 	return offset;
+ }
+-EXPORT_SYMBOL_GPL(ip6_find_1stfragopt);
+ 
+ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
+ {
+@@ -912,15 +912,19 @@ static int ip6_dst_lookup_tail(struct sock *sk,
+ 			       struct dst_entry **dst, struct flowi *fl)
+ {
+ 	int err;
++	struct net *net = sock_net(sk);
+ 
+ 	if (*dst == NULL)
+-		*dst = ip6_route_output(sk, fl);
++		*dst = ip6_route_output(net, sk, fl);
+ 
+ 	if ((err = (*dst)->error))
+ 		goto out_err_release;
+ 
+ 	if (ipv6_addr_any(&fl->fl6_src)) {
+-		err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
++		err = ipv6_dev_get_saddr(ip6_dst_idev(*dst)->dev,
++					 &fl->fl6_dst,
++					 sk ? inet6_sk(sk)->srcprefs : 0,
++					 &fl->fl6_src);
+ 		if (err)
+ 			goto out_err_release;
+ 	}
+@@ -939,7 +943,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
+ 			struct flowi fl_gw;
+ 			int redirect;
+ 
+-			ifp = ipv6_get_ifaddr(&init_net, &fl->fl6_src,
++			ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
+ 					      (*dst)->dev, 1);
+ 
+ 			redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
+@@ -954,7 +958,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
+ 				dst_release(*dst);
+ 				memcpy(&fl_gw, fl, sizeof(struct flowi));
+ 				memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
+-				*dst = ip6_route_output(sk, &fl_gw);
++				*dst = ip6_route_output(net, sk, &fl_gw);
+ 				if ((err = (*dst)->error))
+ 					goto out_err_release;
+ 			}
+@@ -1113,7 +1117,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ 			/* need source address above miyazawa*/
+ 		}
+ 		dst_hold(&rt->u.dst);
+-		np->cork.rt = rt;
++		inet->cork.dst = &rt->u.dst;
+ 		inet->cork.fl = *fl;
+ 		np->cork.hop_limit = hlimit;
+ 		np->cork.tclass = tclass;
+@@ -1134,7 +1138,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ 		length += exthdrlen;
+ 		transhdrlen += exthdrlen;
+ 	} else {
+-		rt = np->cork.rt;
++		rt = (struct rt6_info *)inet->cork.dst;
+ 		fl = &inet->cork.fl;
+ 		if (inet->cork.flags & IPCORK_OPT)
+ 			opt = np->cork.opt;
+@@ -1379,9 +1383,9 @@ static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np)
+ 	inet->cork.flags &= ~IPCORK_OPT;
+ 	kfree(np->cork.opt);
+ 	np->cork.opt = NULL;
+-	if (np->cork.rt) {
+-		dst_release(&np->cork.rt->u.dst);
+-		np->cork.rt = NULL;
++	if (inet->cork.dst) {
++		dst_release(inet->cork.dst);
++		inet->cork.dst = NULL;
+ 		inet->cork.flags &= ~IPCORK_ALLFRAG;
+ 	}
+ 	memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
+@@ -1396,7 +1400,7 @@ int ip6_push_pending_frames(struct sock *sk)
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+ 	struct ipv6hdr *hdr;
+ 	struct ipv6_txoptions *opt = np->cork.opt;
+-	struct rt6_info *rt = np->cork.rt;
++	struct rt6_info *rt = (struct rt6_info *)inet->cork.dst;
+ 	struct flowi *fl = &inet->cork.fl;
+ 	unsigned char proto = fl->proto;
+ 	int err = 0;
+diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
+index 78f4388..2bda3ba 100644
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -52,6 +52,8 @@
+ #include <net/xfrm.h>
+ #include <net/dsfield.h>
+ #include <net/inet_ecn.h>
++#include <net/net_namespace.h>
++#include <net/netns/generic.h>
+ 
+ MODULE_AUTHOR("Ville Nuorvala");
+ MODULE_DESCRIPTION("IPv6 tunneling device");
+@@ -60,7 +62,7 @@ MODULE_LICENSE("GPL");
+ #define IPV6_TLV_TEL_DST_SIZE 8
+ 
+ #ifdef IP6_TNL_DEBUG
+-#define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __FUNCTION__)
++#define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__)
+ #else
+ #define IP6_TNL_TRACE(x...) do {;} while(0)
+ #endif
+@@ -78,14 +80,15 @@ static int ip6_fb_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);
+ 
+-/* the IPv6 tunnel fallback device */
+-static struct net_device *ip6_fb_tnl_dev;
+-
+-
+-/* lists for storing tunnels in use */
+-static struct ip6_tnl *tnls_r_l[HASH_SIZE];
+-static struct ip6_tnl *tnls_wc[1];
+-static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l };
++static int ip6_tnl_net_id;
++struct ip6_tnl_net {
++	/* 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];
++};
+ 
+ /* lock for the tunnel lists */
+ static DEFINE_RWLOCK(ip6_tnl_lock);
+@@ -130,19 +133,20 @@ static inline void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst)
+  **/
+ 
+ static struct ip6_tnl *
+-ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local)
++ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local)
+ {
+ 	unsigned h0 = HASH(remote);
+ 	unsigned h1 = HASH(local);
+ 	struct ip6_tnl *t;
++	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+ 
+-	for (t = tnls_r_l[h0 ^ h1]; t; t = t->next) {
++	for (t = ip6n->tnls_r_l[h0 ^ h1]; t; t = t->next) {
+ 		if (ipv6_addr_equal(local, &t->parms.laddr) &&
+ 		    ipv6_addr_equal(remote, &t->parms.raddr) &&
+ 		    (t->dev->flags & IFF_UP))
+ 			return t;
+ 	}
+-	if ((t = tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP))
++	if ((t = ip6n->tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP))
+ 		return t;
+ 
+ 	return NULL;
+@@ -160,7 +164,7 @@ ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local)
+  **/
+ 
+ static struct ip6_tnl **
+-ip6_tnl_bucket(struct ip6_tnl_parm *p)
++ip6_tnl_bucket(struct ip6_tnl_net *ip6n, struct ip6_tnl_parm *p)
+ {
+ 	struct in6_addr *remote = &p->raddr;
+ 	struct in6_addr *local = &p->laddr;
+@@ -171,7 +175,7 @@ ip6_tnl_bucket(struct ip6_tnl_parm *p)
+ 		prio = 1;
+ 		h = HASH(remote) ^ HASH(local);
+ 	}
+-	return &tnls[prio][h];
++	return &ip6n->tnls[prio][h];
+ }
+ 
+ /**
+@@ -180,9 +184,9 @@ ip6_tnl_bucket(struct ip6_tnl_parm *p)
+  **/
+ 
+ static void
+-ip6_tnl_link(struct ip6_tnl *t)
++ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
+ {
+-	struct ip6_tnl **tp = ip6_tnl_bucket(&t->parms);
++	struct ip6_tnl **tp = ip6_tnl_bucket(ip6n, &t->parms);
+ 
+ 	t->next = *tp;
+ 	write_lock_bh(&ip6_tnl_lock);
+@@ -196,11 +200,11 @@ ip6_tnl_link(struct ip6_tnl *t)
+  **/
+ 
+ static void
+-ip6_tnl_unlink(struct ip6_tnl *t)
++ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
+ {
+ 	struct ip6_tnl **tp;
+ 
+-	for (tp = ip6_tnl_bucket(&t->parms); *tp; tp = &(*tp)->next) {
++	for (tp = ip6_tnl_bucket(ip6n, &t->parms); *tp; tp = &(*tp)->next) {
+ 		if (t == *tp) {
+ 			write_lock_bh(&ip6_tnl_lock);
+ 			*tp = t->next;
+@@ -222,12 +226,13 @@ ip6_tnl_unlink(struct ip6_tnl *t)
+  *   created tunnel or NULL
+  **/
+ 
+-static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p)
++static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p)
+ {
+ 	struct net_device *dev;
+ 	struct ip6_tnl *t;
+ 	char name[IFNAMSIZ];
+ 	int err;
++	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+ 
+ 	if (p->name[0])
+ 		strlcpy(name, p->name, IFNAMSIZ);
+@@ -238,6 +243,8 @@ static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p)
+ 	if (dev == NULL)
+ 		goto failed;
+ 
++	dev_net_set(dev, net);
++
+ 	if (strchr(name, '%')) {
+ 		if (dev_alloc_name(dev, name) < 0)
+ 			goto failed_free;
+@@ -251,7 +258,7 @@ static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p)
+ 		goto failed_free;
+ 
+ 	dev_hold(dev);
+-	ip6_tnl_link(t);
++	ip6_tnl_link(ip6n, t);
+ 	return t;
+ 
+ failed_free:
+@@ -274,20 +281,22 @@ failed:
+  *   matching tunnel or NULL
+  **/
+ 
+-static struct ip6_tnl *ip6_tnl_locate(struct ip6_tnl_parm *p, int create)
++static struct ip6_tnl *ip6_tnl_locate(struct net *net,
++		struct ip6_tnl_parm *p, int create)
+ {
+ 	struct in6_addr *remote = &p->raddr;
+ 	struct in6_addr *local = &p->laddr;
+ 	struct ip6_tnl *t;
++	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+ 
+-	for (t = *ip6_tnl_bucket(p); t; t = t->next) {
++	for (t = *ip6_tnl_bucket(ip6n, p); t; t = t->next) {
+ 		if (ipv6_addr_equal(local, &t->parms.laddr) &&
+ 		    ipv6_addr_equal(remote, &t->parms.raddr))
+ 			return t;
+ 	}
+ 	if (!create)
+ 		return NULL;
+-	return ip6_tnl_create(p);
++	return ip6_tnl_create(net, p);
+ }
+ 
+ /**
+@@ -302,13 +311,15 @@ static void
+ ip6_tnl_dev_uninit(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);
+ 
+-	if (dev == ip6_fb_tnl_dev) {
++	if (dev == ip6n->fb_tnl_dev) {
+ 		write_lock_bh(&ip6_tnl_lock);
+-		tnls_wc[0] = NULL;
++		ip6n->tnls_wc[0] = NULL;
+ 		write_unlock_bh(&ip6_tnl_lock);
+ 	} else {
+-		ip6_tnl_unlink(t);
++		ip6_tnl_unlink(ip6n, t);
+ 	}
+ 	ip6_tnl_dst_reset(t);
+ 	dev_put(dev);
+@@ -401,7 +412,8 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
+ 	   processing of the error. */
+ 
+ 	read_lock(&ip6_tnl_lock);
+-	if ((t = ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL)
++	if ((t = ip6_tnl_lookup(dev_net(skb->dev), &ipv6h->daddr,
++					&ipv6h->saddr)) == NULL)
+ 		goto out;
+ 
+ 	if (t->parms.proto != ipproto && t->parms.proto != 0)
+@@ -533,7 +545,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ 	fl.fl4_dst = eiph->saddr;
+ 	fl.fl4_tos = RT_TOS(eiph->tos);
+ 	fl.proto = IPPROTO_IPIP;
+-	if (ip_route_output_key(&init_net, &rt, &fl))
++	if (ip_route_output_key(dev_net(skb->dev), &rt, &fl))
+ 		goto out;
+ 
+ 	skb2->dev = rt->u.dst.dev;
+@@ -545,7 +557,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ 		fl.fl4_dst = eiph->daddr;
+ 		fl.fl4_src = eiph->saddr;
+ 		fl.fl4_tos = eiph->tos;
+-		if (ip_route_output_key(&init_net, &rt, &fl) ||
++		if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) ||
+ 		    rt->u.dst.dev->type != ARPHRD_TUNNEL) {
+ 			ip_rt_put(rt);
+ 			goto out;
+@@ -602,7 +614,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ 		skb_reset_network_header(skb2);
+ 
+ 		/* Try to guess incoming interface */
+-		rt = rt6_lookup(&ipv6_hdr(skb2)->saddr, NULL, 0, 0);
++		rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr,
++				NULL, 0, 0);
+ 
+ 		if (rt && rt->rt6i_dev)
+ 			skb2->dev = rt->rt6i_dev;
+@@ -646,16 +659,17 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t)
+ {
+ 	struct ip6_tnl_parm *p = &t->parms;
+ 	int ret = 0;
++	struct net *net = dev_net(t->dev);
+ 
+ 	if (p->flags & IP6_TNL_F_CAP_RCV) {
+ 		struct net_device *ldev = NULL;
+ 
+ 		if (p->link)
+-			ldev = dev_get_by_index(&init_net, p->link);
++			ldev = dev_get_by_index(net, p->link);
+ 
+ 		if ((ipv6_addr_is_multicast(&p->laddr) ||
+-		     likely(ipv6_chk_addr(&init_net, &p->laddr, ldev, 0))) &&
+-		    likely(!ipv6_chk_addr(&init_net, &p->raddr, NULL, 0)))
++		     likely(ipv6_chk_addr(net, &p->laddr, ldev, 0))) &&
++		    likely(!ipv6_chk_addr(net, &p->raddr, NULL, 0)))
+ 			ret = 1;
+ 
+ 		if (ldev)
+@@ -684,7 +698,8 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
+ 
+ 	read_lock(&ip6_tnl_lock);
+ 
+-	if ((t = ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
++	if ((t = ip6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr,
++					&ipv6h->daddr)) != NULL) {
+ 		if (t->parms.proto != ipproto && t->parms.proto != 0) {
+ 			read_unlock(&ip6_tnl_lock);
+ 			goto discard;
+@@ -782,19 +797,20 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
+ {
+ 	struct ip6_tnl_parm *p = &t->parms;
+ 	int ret = 0;
++	struct net *net = dev_net(t->dev);
+ 
+ 	if (p->flags & IP6_TNL_F_CAP_XMIT) {
+ 		struct net_device *ldev = NULL;
+ 
+ 		if (p->link)
+-			ldev = dev_get_by_index(&init_net, p->link);
++			ldev = dev_get_by_index(net, p->link);
+ 
+-		if (unlikely(!ipv6_chk_addr(&init_net, &p->laddr, ldev, 0)))
++		if (unlikely(!ipv6_chk_addr(net, &p->laddr, ldev, 0)))
+ 			printk(KERN_WARNING
+ 			       "%s xmit: Local address not yet configured!\n",
+ 			       p->name);
+ 		else if (!ipv6_addr_is_multicast(&p->raddr) &&
+-			 unlikely(ipv6_chk_addr(&init_net, &p->raddr, NULL, 0)))
++			 unlikely(ipv6_chk_addr(net, &p->raddr, NULL, 0)))
+ 			printk(KERN_WARNING
+ 			       "%s xmit: Routing loop! "
+ 			       "Remote address found on this node!\n",
+@@ -847,7 +863,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
+ 	if ((dst = ip6_tnl_dst_check(t)) != NULL)
+ 		dst_hold(dst);
+ 	else {
+-		dst = ip6_route_output(NULL, fl);
++		dst = ip6_route_output(dev_net(dev), NULL, fl);
+ 
+ 		if (dst->error || xfrm_lookup(&dst, fl, NULL, 0) < 0)
+ 			goto tx_err_link_failure;
+@@ -1112,7 +1128,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
+ 		int strict = (ipv6_addr_type(&p->raddr) &
+ 			      (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL));
+ 
+-		struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr,
++		struct rt6_info *rt = rt6_lookup(dev_net(dev),
++						 &p->raddr, &p->laddr,
+ 						 p->link, strict);
+ 
+ 		if (rt == NULL)
+@@ -1191,15 +1208,17 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ 	int err = 0;
+ 	struct ip6_tnl_parm p;
+ 	struct ip6_tnl *t = NULL;
++	struct net *net = dev_net(dev);
++	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+ 
+ 	switch (cmd) {
+ 	case SIOCGETTUNNEL:
+-		if (dev == ip6_fb_tnl_dev) {
++		if (dev == ip6n->fb_tnl_dev) {
+ 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) {
+ 				err = -EFAULT;
+ 				break;
+ 			}
+-			t = ip6_tnl_locate(&p, 0);
++			t = ip6_tnl_locate(net, &p, 0);
+ 		}
+ 		if (t == NULL)
+ 			t = netdev_priv(dev);
+@@ -1220,8 +1239,8 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP &&
+ 		    p.proto != 0)
+ 			break;
+-		t = ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL);
+-		if (dev != ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) {
++		t = ip6_tnl_locate(net, &p, cmd == SIOCADDTUNNEL);
++		if (dev != ip6n->fb_tnl_dev && cmd == SIOCCHGTUNNEL) {
+ 			if (t != NULL) {
+ 				if (t->dev != dev) {
+ 					err = -EEXIST;
+@@ -1230,9 +1249,9 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ 			} else
+ 				t = netdev_priv(dev);
+ 
+-			ip6_tnl_unlink(t);
++			ip6_tnl_unlink(ip6n, t);
+ 			err = ip6_tnl_change(t, &p);
+-			ip6_tnl_link(t);
++			ip6_tnl_link(ip6n, t);
+ 			netdev_state_change(dev);
+ 		}
+ 		if (t) {
+@@ -1248,15 +1267,15 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		if (!capable(CAP_NET_ADMIN))
+ 			break;
+ 
+-		if (dev == ip6_fb_tnl_dev) {
++		if (dev == ip6n->fb_tnl_dev) {
+ 			err = -EFAULT;
+ 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p)))
+ 				break;
+ 			err = -ENOENT;
+-			if ((t = ip6_tnl_locate(&p, 0)) == NULL)
++			if ((t = ip6_tnl_locate(net, &p, 0)) == NULL)
+ 				break;
+ 			err = -EPERM;
+-			if (t->dev == ip6_fb_tnl_dev)
++			if (t->dev == ip6n->fb_tnl_dev)
+ 				break;
+ 			dev = t->dev;
+ 		}
+@@ -1324,6 +1343,7 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
+ 	dev->mtu = ETH_DATA_LEN - sizeof (struct ipv6hdr);
+ 	dev->flags |= IFF_NOARP;
+ 	dev->addr_len = sizeof(struct in6_addr);
++	dev->features |= NETIF_F_NETNS_LOCAL;
+ }
+ 
+ 
+@@ -1365,10 +1385,13 @@ static int
+ 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);
++
+ 	ip6_tnl_dev_init_gen(dev);
+ 	t->parms.proto = IPPROTO_IPV6;
+ 	dev_hold(dev);
+-	tnls_wc[0] = t;
++	ip6n->tnls_wc[0] = t;
+ 	return 0;
+ }
+ 
+@@ -1384,6 +1407,78 @@ static struct xfrm6_tunnel ip6ip6_handler = {
+ 	.priority	=	1,
+ };
+ 
++static void ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n)
++{
++	int h;
++	struct ip6_tnl *t;
++
++	for (h = 0; h < HASH_SIZE; h++) {
++		while ((t = ip6n->tnls_r_l[h]) != NULL)
++			unregister_netdevice(t->dev);
++	}
++
++	t = ip6n->tnls_wc[0];
++	unregister_netdevice(t->dev);
++}
++
++static int ip6_tnl_init_net(struct net *net)
++{
++	int err;
++	struct ip6_tnl_net *ip6n;
++
++	err = -ENOMEM;
++	ip6n = kzalloc(sizeof(struct ip6_tnl_net), GFP_KERNEL);
++	if (ip6n == NULL)
++		goto err_alloc;
++
++	err = net_assign_generic(net, ip6_tnl_net_id, ip6n);
++	if (err < 0)
++		goto err_assign;
++
++	ip6n->tnls[0] = ip6n->tnls_wc;
++	ip6n->tnls[1] = ip6n->tnls_r_l;
++
++	err = -ENOMEM;
++	ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
++				      ip6_tnl_dev_setup);
++
++	if (!ip6n->fb_tnl_dev)
++		goto err_alloc_dev;
++
++	ip6n->fb_tnl_dev->init = ip6_fb_tnl_dev_init;
++	dev_net_set(ip6n->fb_tnl_dev, net);
++
++	err = register_netdev(ip6n->fb_tnl_dev);
++	if (err < 0)
++		goto err_register;
++	return 0;
++
++err_register:
++	free_netdev(ip6n->fb_tnl_dev);
++err_alloc_dev:
++	/* nothing */
++err_assign:
++	kfree(ip6n);
++err_alloc:
++	return err;
++}
++
++static void ip6_tnl_exit_net(struct net *net)
++{
++	struct ip6_tnl_net *ip6n;
++
++	ip6n = net_generic(net, ip6_tnl_net_id);
++	rtnl_lock();
++	ip6_tnl_destroy_tunnels(ip6n);
++	rtnl_unlock();
++	kfree(ip6n);
++}
++
++static struct pernet_operations ip6_tnl_net_ops = {
++	.init = ip6_tnl_init_net,
++	.exit = ip6_tnl_exit_net,
++};
++
+ /**
+  * ip6_tunnel_init - register protocol and reserve needed resources
+  *
+@@ -1405,21 +1500,12 @@ static int __init ip6_tunnel_init(void)
+ 		err = -EAGAIN;
+ 		goto unreg_ip4ip6;
+ 	}
+-	ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
+-				      ip6_tnl_dev_setup);
+ 
+-	if (!ip6_fb_tnl_dev) {
+-		err = -ENOMEM;
+-		goto fail;
+-	}
+-	ip6_fb_tnl_dev->init = ip6_fb_tnl_dev_init;
+-
+-	if ((err = register_netdev(ip6_fb_tnl_dev))) {
+-		free_netdev(ip6_fb_tnl_dev);
+-		goto fail;
+-	}
++	err = register_pernet_gen_device(&ip6_tnl_net_id, &ip6_tnl_net_ops);
++	if (err < 0)
++		goto err_pernet;
+ 	return 0;
+-fail:
++err_pernet:
+ 	xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
+ unreg_ip4ip6:
+ 	xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET);
+@@ -1427,20 +1513,6 @@ out:
+ 	return err;
+ }
+ 
+-static void __exit ip6_tnl_destroy_tunnels(void)
+-{
+-	int h;
+-	struct ip6_tnl *t;
+-
+-	for (h = 0; h < HASH_SIZE; h++) {
+-		while ((t = tnls_r_l[h]) != NULL)
+-			unregister_netdevice(t->dev);
+-	}
+-
+-	t = tnls_wc[0];
+-	unregister_netdevice(t->dev);
+-}
+-
+ /**
+  * ip6_tunnel_cleanup - free resources and unregister protocol
+  **/
+@@ -1453,9 +1525,7 @@ static void __exit ip6_tunnel_cleanup(void)
+ 	if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6))
+ 		printk(KERN_INFO "ip6_tunnel close: can't deregister ip6ip6\n");
+ 
+-	rtnl_lock();
+-	ip6_tnl_destroy_tunnels();
+-	rtnl_unlock();
++	unregister_pernet_gen_device(ip6_tnl_net_id, &ip6_tnl_net_ops);
+ }
+ 
+ module_init(ip6_tunnel_init);
+diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
+new file mode 100644
+index 0000000..c8c6e33
+--- /dev/null
++++ b/net/ipv6/ip6mr.c
+@@ -0,0 +1,1643 @@
++/*
++ *	Linux IPv6 multicast routing support for BSD pim6sd
++ *	Based on net/ipv4/ipmr.c.
++ *
++ *	(c) 2004 Mickael Hoerdt, <hoerdt at clarinet.u-strasbg.fr>
++ *		LSIIT Laboratory, Strasbourg, France
++ *	(c) 2004 Jean-Philippe Andriot, <jean-philippe.andriot at 6WIND.com>
++ *		6WIND, Paris, France
++ *	Copyright (C)2007,2008 USAGI/WIDE Project
++ *		YOSHIFUJI Hideaki <yoshfuji at linux-ipv6.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 <asm/system.h>
++#include <asm/uaccess.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/fcntl.h>
++#include <linux/stat.h>
++#include <linux/socket.h>
++#include <linux/inet.h>
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/init.h>
++#include <net/protocol.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++#include <net/raw.h>
++#include <linux/notifier.h>
++#include <linux/if_arp.h>
++#include <net/checksum.h>
++#include <net/netlink.h>
++
++#include <net/ipv6.h>
++#include <net/ip6_route.h>
++#include <linux/mroute6.h>
++#include <linux/pim.h>
++#include <net/addrconf.h>
++#include <linux/netfilter_ipv6.h>
++
++struct sock *mroute6_socket;
++
++
++/* Big lock, protecting vif table, mrt cache and mroute socket state.
++   Note that the changes are semaphored via rtnl_lock.
++ */
++
++static DEFINE_RWLOCK(mrt_lock);
++
++/*
++ *	Multicast router control variables
++ */
++
++static struct mif_device vif6_table[MAXMIFS];		/* Devices 		*/
++static int maxvif;
++
++#define MIF_EXISTS(idx) (vif6_table[idx].dev != NULL)
++
++static int mroute_do_assert;				/* Set in PIM assert	*/
++#ifdef CONFIG_IPV6_PIMSM_V2
++static int mroute_do_pim;
++#else
++#define mroute_do_pim 0
++#endif
++
++static struct mfc6_cache *mfc6_cache_array[MFC6_LINES];	/* Forwarding cache	*/
++
++static struct mfc6_cache *mfc_unres_queue;		/* Queue of unresolved entries */
++static atomic_t cache_resolve_queue_len;		/* Size of unresolved	*/
++
++/* Special spinlock for queue of unresolved entries */
++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.
++ */
++
++static struct kmem_cache *mrt_cachep __read_mostly;
++
++static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache);
++static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert);
++static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm);
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++static struct inet6_protocol pim6_protocol;
++#endif
++
++static struct timer_list ipmr_expire_timer;
++
++
++#ifdef CONFIG_PROC_FS
++
++struct ipmr_mfc_iter {
++	struct mfc6_cache **cache;
++	int ct;
++};
++
++
++static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
++{
++	struct mfc6_cache *mfc;
++
++	it->cache = mfc6_cache_array;
++	read_lock(&mrt_lock);
++	for (it->ct = 0; it->ct < ARRAY_SIZE(mfc6_cache_array); it->ct++)
++		for (mfc = mfc6_cache_array[it->ct]; mfc; mfc = mfc->next)
++			if (pos-- == 0)
++				return mfc;
++	read_unlock(&mrt_lock);
++
++	it->cache = &mfc_unres_queue;
++	spin_lock_bh(&mfc_unres_lock);
++	for (mfc = mfc_unres_queue; mfc; mfc = mfc->next)
++		if (pos-- == 0)
++			return mfc;
++	spin_unlock_bh(&mfc_unres_lock);
++
++	it->cache = NULL;
++	return NULL;
++}
++
++
++
++
++/*
++ *	The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif
++ */
++
++struct ipmr_vif_iter {
++	int ct;
++};
++
++static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter,
++					    loff_t pos)
++{
++	for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) {
++		if (!MIF_EXISTS(iter->ct))
++			continue;
++		if (pos-- == 0)
++			return &vif6_table[iter->ct];
++	}
++	return NULL;
++}
++
++static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
++	__acquires(mrt_lock)
++{
++	read_lock(&mrt_lock);
++	return (*pos ? ip6mr_vif_seq_idx(seq->private, *pos - 1)
++		: SEQ_START_TOKEN);
++}
++
++static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++	struct ipmr_vif_iter *iter = seq->private;
++
++	++*pos;
++	if (v == SEQ_START_TOKEN)
++		return ip6mr_vif_seq_idx(iter, 0);
++
++	while (++iter->ct < maxvif) {
++		if (!MIF_EXISTS(iter->ct))
++			continue;
++		return &vif6_table[iter->ct];
++	}
++	return NULL;
++}
++
++static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
++	__releases(mrt_lock)
++{
++	read_unlock(&mrt_lock);
++}
++
++static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
++{
++	if (v == SEQ_START_TOKEN) {
++		seq_puts(seq,
++			 "Interface      BytesIn  PktsIn  BytesOut PktsOut Flags\n");
++	} else {
++		const struct mif_device *vif = v;
++		const char *name = vif->dev ? vif->dev->name : "none";
++
++		seq_printf(seq,
++			   "%2Zd %-10s %8ld %7ld  %8ld %7ld %05X\n",
++			   vif - vif6_table,
++			   name, vif->bytes_in, vif->pkt_in,
++			   vif->bytes_out, vif->pkt_out,
++			   vif->flags);
++	}
++	return 0;
++}
++
++static struct seq_operations ip6mr_vif_seq_ops = {
++	.start = ip6mr_vif_seq_start,
++	.next  = ip6mr_vif_seq_next,
++	.stop  = ip6mr_vif_seq_stop,
++	.show  = ip6mr_vif_seq_show,
++};
++
++static int ip6mr_vif_open(struct inode *inode, struct file *file)
++{
++	return seq_open_private(file, &ip6mr_vif_seq_ops,
++				sizeof(struct ipmr_vif_iter));
++}
++
++static struct file_operations ip6mr_vif_fops = {
++	.owner	 = THIS_MODULE,
++	.open    = ip6mr_vif_open,
++	.read    = seq_read,
++	.llseek  = seq_lseek,
++	.release = seq_release,
++};
++
++static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
++{
++	return (*pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1)
++		: SEQ_START_TOKEN);
++}
++
++static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++	struct mfc6_cache *mfc = v;
++	struct ipmr_mfc_iter *it = seq->private;
++
++	++*pos;
++
++	if (v == SEQ_START_TOKEN)
++		return ipmr_mfc_seq_idx(seq->private, 0);
++
++	if (mfc->next)
++		return mfc->next;
++
++	if (it->cache == &mfc_unres_queue)
++		goto end_of_list;
++
++	BUG_ON(it->cache != mfc6_cache_array);
++
++	while (++it->ct < ARRAY_SIZE(mfc6_cache_array)) {
++		mfc = mfc6_cache_array[it->ct];
++		if (mfc)
++			return mfc;
++	}
++
++	/* exhausted cache_array, show unresolved */
++	read_unlock(&mrt_lock);
++	it->cache = &mfc_unres_queue;
++	it->ct = 0;
++
++	spin_lock_bh(&mfc_unres_lock);
++	mfc = mfc_unres_queue;
++	if (mfc)
++		return mfc;
++
++ end_of_list:
++	spin_unlock_bh(&mfc_unres_lock);
++	it->cache = NULL;
++
++	return NULL;
++}
++
++static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
++{
++	struct ipmr_mfc_iter *it = seq->private;
++
++	if (it->cache == &mfc_unres_queue)
++		spin_unlock_bh(&mfc_unres_lock);
++	else if (it->cache == mfc6_cache_array)
++		read_unlock(&mrt_lock);
++}
++
++static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
++{
++	int n;
++
++	if (v == SEQ_START_TOKEN) {
++		seq_puts(seq,
++			 "Group                            "
++			 "Origin                           "
++			 "Iif      Pkts  Bytes     Wrong  Oifs\n");
++	} else {
++		const struct mfc6_cache *mfc = v;
++		const struct ipmr_mfc_iter *it = seq->private;
++
++		seq_printf(seq,
++			   NIP6_FMT " " NIP6_FMT " %-3d %8ld %8ld %8ld",
++			   NIP6(mfc->mf6c_mcastgrp), NIP6(mfc->mf6c_origin),
++			   mfc->mf6c_parent,
++			   mfc->mfc_un.res.pkt,
++			   mfc->mfc_un.res.bytes,
++			   mfc->mfc_un.res.wrong_if);
++
++		if (it->cache != &mfc_unres_queue) {
++			for (n = mfc->mfc_un.res.minvif;
++			     n < mfc->mfc_un.res.maxvif; n++) {
++				if (MIF_EXISTS(n) &&
++				    mfc->mfc_un.res.ttls[n] < 255)
++					seq_printf(seq,
++						   " %2d:%-3d",
++						   n, mfc->mfc_un.res.ttls[n]);
++			}
++		}
++		seq_putc(seq, '\n');
++	}
++	return 0;
++}
++
++static struct seq_operations ipmr_mfc_seq_ops = {
++	.start = ipmr_mfc_seq_start,
++	.next  = ipmr_mfc_seq_next,
++	.stop  = ipmr_mfc_seq_stop,
++	.show  = ipmr_mfc_seq_show,
++};
++
++static int ipmr_mfc_open(struct inode *inode, struct file *file)
++{
++	return seq_open_private(file, &ipmr_mfc_seq_ops,
++				sizeof(struct ipmr_mfc_iter));
++}
++
++static struct file_operations ip6mr_mfc_fops = {
++	.owner	 = THIS_MODULE,
++	.open    = ipmr_mfc_open,
++	.read    = seq_read,
++	.llseek  = seq_lseek,
++	.release = seq_release,
++};
++#endif
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++static int reg_vif_num = -1;
++
++static int pim6_rcv(struct sk_buff *skb)
++{
++	struct pimreghdr *pim;
++	struct ipv6hdr   *encap;
++	struct net_device  *reg_dev = NULL;
++
++	if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
++		goto drop;
++
++	pim = (struct pimreghdr *)skb_transport_header(skb);
++	if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) ||
++	    (pim->flags & PIM_NULL_REGISTER) ||
++	    (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
++	     (u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))))
++		goto drop;
++
++	/* check if the inner packet is destined to mcast group */
++	encap = (struct ipv6hdr *)(skb_transport_header(skb) +
++				   sizeof(*pim));
++
++	if (!ipv6_addr_is_multicast(&encap->daddr) ||
++	    encap->payload_len == 0 ||
++	    ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
++		goto drop;
++
++	read_lock(&mrt_lock);
++	if (reg_vif_num >= 0)
++		reg_dev = vif6_table[reg_vif_num].dev;
++	if (reg_dev)
++		dev_hold(reg_dev);
++	read_unlock(&mrt_lock);
++
++	if (reg_dev == NULL)
++		goto drop;
++
++	skb->mac_header = skb->network_header;
++	skb_pull(skb, (u8 *)encap - skb->data);
++	skb_reset_network_header(skb);
++	skb->dev = reg_dev;
++	skb->protocol = htons(ETH_P_IP);
++	skb->ip_summed = 0;
++	skb->pkt_type = PACKET_HOST;
++	dst_release(skb->dst);
++	((struct net_device_stats *)netdev_priv(reg_dev))->rx_bytes += skb->len;
++	((struct net_device_stats *)netdev_priv(reg_dev))->rx_packets++;
++	skb->dst = NULL;
++	nf_reset(skb);
++	netif_rx(skb);
++	dev_put(reg_dev);
++	return 0;
++ drop:
++	kfree_skb(skb);
++	return 0;
++}
++
++static struct inet6_protocol pim6_protocol = {
++	.handler	=	pim6_rcv,
++};
++
++/* Service routines creating virtual interfaces: PIMREG */
++
++static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	read_lock(&mrt_lock);
++	((struct net_device_stats *)netdev_priv(dev))->tx_bytes += skb->len;
++	((struct net_device_stats *)netdev_priv(dev))->tx_packets++;
++	ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT);
++	read_unlock(&mrt_lock);
++	kfree_skb(skb);
++	return 0;
++}
++
++static struct net_device_stats *reg_vif_get_stats(struct net_device *dev)
++{
++	return (struct net_device_stats *)netdev_priv(dev);
++}
++
++static void reg_vif_setup(struct net_device *dev)
++{
++	dev->type		= ARPHRD_PIMREG;
++	dev->mtu		= 1500 - sizeof(struct ipv6hdr) - 8;
++	dev->flags		= IFF_NOARP;
++	dev->hard_start_xmit	= reg_vif_xmit;
++	dev->get_stats		= reg_vif_get_stats;
++	dev->destructor		= free_netdev;
++}
++
++static struct net_device *ip6mr_reg_vif(void)
++{
++	struct net_device *dev;
++
++	dev = alloc_netdev(sizeof(struct net_device_stats), "pim6reg",
++			   reg_vif_setup);
++
++	if (dev == NULL)
++		return NULL;
++
++	if (register_netdevice(dev)) {
++		free_netdev(dev);
++		return NULL;
++	}
++	dev->iflink = 0;
++
++	if (dev_open(dev))
++		goto failure;
++
++	return dev;
++
++failure:
++	/* allow the register to be completed before unregistering. */
++	rtnl_unlock();
++	rtnl_lock();
++
++	unregister_netdevice(dev);
++	return NULL;
++}
++#endif
++
++/*
++ *	Delete a VIF entry
++ */
++
++static int mif6_delete(int vifi)
++{
++	struct mif_device *v;
++	struct net_device *dev;
++	if (vifi < 0 || vifi >= maxvif)
++		return -EADDRNOTAVAIL;
++
++	v = &vif6_table[vifi];
++
++	write_lock_bh(&mrt_lock);
++	dev = v->dev;
++	v->dev = NULL;
++
++	if (!dev) {
++		write_unlock_bh(&mrt_lock);
++		return -EADDRNOTAVAIL;
++	}
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++	if (vifi == reg_vif_num)
++		reg_vif_num = -1;
++#endif
++
++	if (vifi + 1 == maxvif) {
++		int tmp;
++		for (tmp = vifi - 1; tmp >= 0; tmp--) {
++			if (MIF_EXISTS(tmp))
++				break;
++		}
++		maxvif = tmp + 1;
++	}
++
++	write_unlock_bh(&mrt_lock);
++
++	dev_set_allmulti(dev, -1);
++
++	if (v->flags & MIFF_REGISTER)
++		unregister_netdevice(dev);
++
++	dev_put(dev);
++	return 0;
++}
++
++/* Destroy an unresolved cache entry, killing queued skbs
++   and reporting error to netlink readers.
++ */
++
++static void ip6mr_destroy_unres(struct mfc6_cache *c)
++{
++	struct sk_buff *skb;
++
++	atomic_dec(&cache_resolve_queue_len);
++
++	while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) {
++		if (ipv6_hdr(skb)->version == 0) {
++			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
++			nlh->nlmsg_type = NLMSG_ERROR;
++			nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
++			skb_trim(skb, nlh->nlmsg_len);
++			((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -ETIMEDOUT;
++			rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
++		} else
++			kfree_skb(skb);
++	}
++
++	kmem_cache_free(mrt_cachep, c);
++}
++
++
++/* Single timer process for all the unresolved queue. */
++
++static void ipmr_do_expire_process(unsigned long dummy)
++{
++	unsigned long now = jiffies;
++	unsigned long expires = 10 * HZ;
++	struct mfc6_cache *c, **cp;
++
++	cp = &mfc_unres_queue;
++
++	while ((c = *cp) != NULL) {
++		if (time_after(c->mfc_un.unres.expires, now)) {
++			/* not yet... */
++			unsigned long interval = c->mfc_un.unres.expires - now;
++			if (interval < expires)
++				expires = interval;
++			cp = &c->next;
++			continue;
++		}
++
++		*cp = c->next;
++		ip6mr_destroy_unres(c);
++	}
++
++	if (atomic_read(&cache_resolve_queue_len))
++		mod_timer(&ipmr_expire_timer, jiffies + expires);
++}
++
++static void ipmr_expire_process(unsigned long dummy)
++{
++	if (!spin_trylock(&mfc_unres_lock)) {
++		mod_timer(&ipmr_expire_timer, jiffies + 1);
++		return;
++	}
++
++	if (atomic_read(&cache_resolve_queue_len))
++		ipmr_do_expire_process(dummy);
++
++	spin_unlock(&mfc_unres_lock);
++}
++
++/* Fill oifs list. It is called under write locked mrt_lock. */
++
++static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttls)
++{
++	int vifi;
++
++	cache->mfc_un.res.minvif = MAXMIFS;
++	cache->mfc_un.res.maxvif = 0;
++	memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
++
++	for (vifi = 0; vifi < maxvif; vifi++) {
++		if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) {
++			cache->mfc_un.res.ttls[vifi] = ttls[vifi];
++			if (cache->mfc_un.res.minvif > vifi)
++				cache->mfc_un.res.minvif = vifi;
++			if (cache->mfc_un.res.maxvif <= vifi)
++				cache->mfc_un.res.maxvif = vifi + 1;
++		}
++	}
++}
++
++static int mif6_add(struct mif6ctl *vifc, int mrtsock)
++{
++	int vifi = vifc->mif6c_mifi;
++	struct mif_device *v = &vif6_table[vifi];
++	struct net_device *dev;
++
++	/* Is vif busy ? */
++	if (MIF_EXISTS(vifi))
++		return -EADDRINUSE;
++
++	switch (vifc->mif6c_flags) {
++#ifdef CONFIG_IPV6_PIMSM_V2
++	case MIFF_REGISTER:
++		/*
++		 * Special Purpose VIF in PIM
++		 * All the packets will be sent to the daemon
++		 */
++		if (reg_vif_num >= 0)
++			return -EADDRINUSE;
++		dev = ip6mr_reg_vif();
++		if (!dev)
++			return -ENOBUFS;
++		break;
++#endif
++	case 0:
++		dev = dev_get_by_index(&init_net, vifc->mif6c_pifi);
++		if (!dev)
++			return -EADDRNOTAVAIL;
++		dev_put(dev);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	dev_set_allmulti(dev, 1);
++
++	/*
++	 *	Fill in the VIF structures
++	 */
++	v->rate_limit = vifc->vifc_rate_limit;
++	v->flags = vifc->mif6c_flags;
++	if (!mrtsock)
++		v->flags |= VIFF_STATIC;
++	v->threshold = vifc->vifc_threshold;
++	v->bytes_in = 0;
++	v->bytes_out = 0;
++	v->pkt_in = 0;
++	v->pkt_out = 0;
++	v->link = dev->ifindex;
++	if (v->flags & MIFF_REGISTER)
++		v->link = dev->iflink;
++
++	/* And finish update writing critical data */
++	write_lock_bh(&mrt_lock);
++	dev_hold(dev);
++	v->dev = dev;
++#ifdef CONFIG_IPV6_PIMSM_V2
++	if (v->flags & MIFF_REGISTER)
++		reg_vif_num = vifi;
++#endif
++	if (vifi + 1 > maxvif)
++		maxvif = vifi + 1;
++	write_unlock_bh(&mrt_lock);
++	return 0;
++}
++
++static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_addr *mcastgrp)
++{
++	int line = MFC6_HASH(mcastgrp, origin);
++	struct mfc6_cache *c;
++
++	for (c = mfc6_cache_array[line]; c; c = c->next) {
++		if (ipv6_addr_equal(&c->mf6c_origin, origin) &&
++		    ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp))
++			break;
++	}
++	return c;
++}
++
++/*
++ *	Allocate a multicast cache entry
++ */
++static struct mfc6_cache *ip6mr_cache_alloc(void)
++{
++	struct mfc6_cache *c = kmem_cache_alloc(mrt_cachep, GFP_KERNEL);
++	if (c == NULL)
++		return NULL;
++	memset(c, 0, sizeof(*c));
++	c->mfc_un.res.minvif = MAXMIFS;
++	return c;
++}
++
++static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
++{
++	struct mfc6_cache *c = kmem_cache_alloc(mrt_cachep, GFP_ATOMIC);
++	if (c == NULL)
++		return NULL;
++	memset(c, 0, sizeof(*c));
++	skb_queue_head_init(&c->mfc_un.unres.unresolved);
++	c->mfc_un.unres.expires = jiffies + 10 * HZ;
++	return c;
++}
++
++/*
++ *	A cache entry has gone into a resolved state from queued
++ */
++
++static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c)
++{
++	struct sk_buff *skb;
++
++	/*
++	 *	Play the pending entries through our router
++	 */
++
++	while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) {
++		if (ipv6_hdr(skb)->version == 0) {
++			int err;
++			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
++
++			if (ip6mr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) {
++				nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
++			} else {
++				nlh->nlmsg_type = NLMSG_ERROR;
++				nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
++				skb_trim(skb, nlh->nlmsg_len);
++				((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE;
++			}
++			err = rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
++		} else
++			ip6_mr_forward(skb, c);
++	}
++}
++
++/*
++ *	Bounce a cache query up to pim6sd. We could use netlink for this but pim6sd
++ *	expects the following bizarre scheme.
++ *
++ *	Called under mrt_lock.
++ */
++
++static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
++{
++	struct sk_buff *skb;
++	struct mrt6msg *msg;
++	int ret;
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++	if (assert == MRT6MSG_WHOLEPKT)
++		skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
++						+sizeof(*msg));
++	else
++#endif
++		skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
++
++	if (!skb)
++		return -ENOBUFS;
++
++	/* I suppose that internal messages
++	 * do not require checksums */
++
++	skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++	if (assert == MRT6MSG_WHOLEPKT) {
++		/* Ugly, but we have no choice with this interface.
++		   Duplicate old header, fix length etc.
++		   And all this only to mangle msg->im6_msgtype and
++		   to set msg->im6_mbz to "mbz" :-)
++		 */
++		skb_push(skb, -skb_network_offset(pkt));
++
++		skb_push(skb, sizeof(*msg));
++		skb_reset_transport_header(skb);
++		msg = (struct mrt6msg *)skb_transport_header(skb);
++		msg->im6_mbz = 0;
++		msg->im6_msgtype = MRT6MSG_WHOLEPKT;
++		msg->im6_mif = reg_vif_num;
++		msg->im6_pad = 0;
++		ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
++		ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
++
++		skb->ip_summed = CHECKSUM_UNNECESSARY;
++	} else
++#endif
++	{
++	/*
++	 *	Copy the IP header
++	 */
++
++	skb_put(skb, sizeof(struct ipv6hdr));
++	skb_reset_network_header(skb);
++	skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
++
++	/*
++	 *	Add our header
++	 */
++	skb_put(skb, sizeof(*msg));
++	skb_reset_transport_header(skb);
++	msg = (struct mrt6msg *)skb_transport_header(skb);
++
++	msg->im6_mbz = 0;
++	msg->im6_msgtype = assert;
++	msg->im6_mif = mifi;
++	msg->im6_pad = 0;
++	ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
++	ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
++
++	skb->dst = dst_clone(pkt->dst);
++	skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++	skb_pull(skb, sizeof(struct ipv6hdr));
++	}
++
++	if (mroute6_socket == NULL) {
++		kfree_skb(skb);
++		return -EINVAL;
++	}
++
++	/*
++	 *	Deliver to user space multicast routing algorithms
++	 */
++	if ((ret = sock_queue_rcv_skb(mroute6_socket, skb)) < 0) {
++		if (net_ratelimit())
++			printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n");
++		kfree_skb(skb);
++	}
++
++	return ret;
++}
++
++/*
++ *	Queue a packet for resolution. It gets locked cache entry!
++ */
++
++static int
++ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
++{
++	int err;
++	struct mfc6_cache *c;
++
++	spin_lock_bh(&mfc_unres_lock);
++	for (c = mfc_unres_queue; c; c = c->next) {
++		if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
++		    ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr))
++			break;
++	}
++
++	if (c == NULL) {
++		/*
++		 *	Create a new entry if allowable
++		 */
++
++		if (atomic_read(&cache_resolve_queue_len) >= 10 ||
++		    (c = ip6mr_cache_alloc_unres()) == NULL) {
++			spin_unlock_bh(&mfc_unres_lock);
++
++			kfree_skb(skb);
++			return -ENOBUFS;
++		}
++
++		/*
++		 *	Fill in the new cache entry
++		 */
++		c->mf6c_parent = -1;
++		c->mf6c_origin = ipv6_hdr(skb)->saddr;
++		c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
++
++		/*
++		 *	Reflect first query at pim6sd
++		 */
++		if ((err = ip6mr_cache_report(skb, mifi, MRT6MSG_NOCACHE)) < 0) {
++			/* If the report failed throw the cache entry
++			   out - Brad Parker
++			 */
++			spin_unlock_bh(&mfc_unres_lock);
++
++			kmem_cache_free(mrt_cachep, c);
++			kfree_skb(skb);
++			return err;
++		}
++
++		atomic_inc(&cache_resolve_queue_len);
++		c->next = mfc_unres_queue;
++		mfc_unres_queue = c;
++
++		ipmr_do_expire_process(1);
++	}
++
++	/*
++	 *	See if we can append the packet
++	 */
++	if (c->mfc_un.unres.unresolved.qlen > 3) {
++		kfree_skb(skb);
++		err = -ENOBUFS;
++	} else {
++		skb_queue_tail(&c->mfc_un.unres.unresolved, skb);
++		err = 0;
++	}
++
++	spin_unlock_bh(&mfc_unres_lock);
++	return err;
++}
++
++/*
++ *	MFC6 cache manipulation by user space
++ */
++
++static int ip6mr_mfc_delete(struct mf6cctl *mfc)
++{
++	int line;
++	struct mfc6_cache *c, **cp;
++
++	line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
++
++	for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) {
++		if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
++		    ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) {
++			write_lock_bh(&mrt_lock);
++			*cp = c->next;
++			write_unlock_bh(&mrt_lock);
++
++			kmem_cache_free(mrt_cachep, c);
++			return 0;
++		}
++	}
++	return -ENOENT;
++}
++
++static int ip6mr_device_event(struct notifier_block *this,
++			      unsigned long event, void *ptr)
++{
++	struct net_device *dev = ptr;
++	struct mif_device *v;
++	int ct;
++
++	if (dev_net(dev) != &init_net)
++		return NOTIFY_DONE;
++
++	if (event != NETDEV_UNREGISTER)
++		return NOTIFY_DONE;
++
++	v = &vif6_table[0];
++	for (ct = 0; ct < maxvif; ct++, v++) {
++		if (v->dev == dev)
++			mif6_delete(ct);
++	}
++	return NOTIFY_DONE;
++}
++
++static struct notifier_block ip6_mr_notifier = {
++	.notifier_call = ip6mr_device_event
++};
++
++/*
++ *	Setup for IP multicast routing
++ */
++
++void __init ip6_mr_init(void)
++{
++	mrt_cachep = kmem_cache_create("ip6_mrt_cache",
++				       sizeof(struct mfc6_cache),
++				       0, SLAB_HWCACHE_ALIGN,
++				       NULL);
++	if (!mrt_cachep)
++		panic("cannot allocate ip6_mrt_cache");
++
++	setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
++	register_netdevice_notifier(&ip6_mr_notifier);
++#ifdef CONFIG_PROC_FS
++	proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops);
++	proc_net_fops_create(&init_net, "ip6_mr_cache", 0, &ip6mr_mfc_fops);
++#endif
++}
++
++
++static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
++{
++	int line;
++	struct mfc6_cache *uc, *c, **cp;
++	unsigned char ttls[MAXMIFS];
++	int i;
++
++	memset(ttls, 255, MAXMIFS);
++	for (i = 0; i < MAXMIFS; i++) {
++		if (IF_ISSET(i, &mfc->mf6cc_ifset))
++			ttls[i] = 1;
++
++	}
++
++	line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
++
++	for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) {
++		if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
++		    ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr))
++			break;
++	}
++
++	if (c != NULL) {
++		write_lock_bh(&mrt_lock);
++		c->mf6c_parent = mfc->mf6cc_parent;
++		ip6mr_update_thresholds(c, ttls);
++		if (!mrtsock)
++			c->mfc_flags |= MFC_STATIC;
++		write_unlock_bh(&mrt_lock);
++		return 0;
++	}
++
++	if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
++		return -EINVAL;
++
++	c = ip6mr_cache_alloc();
++	if (c == NULL)
++		return -ENOMEM;
++
++	c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
++	c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
++	c->mf6c_parent = mfc->mf6cc_parent;
++	ip6mr_update_thresholds(c, ttls);
++	if (!mrtsock)
++		c->mfc_flags |= MFC_STATIC;
++
++	write_lock_bh(&mrt_lock);
++	c->next = mfc6_cache_array[line];
++	mfc6_cache_array[line] = c;
++	write_unlock_bh(&mrt_lock);
++
++	/*
++	 *	Check to see if we resolved a queued list. If so we
++	 *	need to send on the frames and tidy up.
++	 */
++	spin_lock_bh(&mfc_unres_lock);
++	for (cp = &mfc_unres_queue; (uc = *cp) != NULL;
++	     cp = &uc->next) {
++		if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
++		    ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
++			*cp = uc->next;
++			if (atomic_dec_and_test(&cache_resolve_queue_len))
++				del_timer(&ipmr_expire_timer);
++			break;
++		}
++	}
++	spin_unlock_bh(&mfc_unres_lock);
++
++	if (uc) {
++		ip6mr_cache_resolve(uc, c);
++		kmem_cache_free(mrt_cachep, uc);
++	}
++	return 0;
++}
++
++/*
++ *	Close the multicast socket, and clear the vif tables etc
++ */
++
++static void mroute_clean_tables(struct sock *sk)
++{
++	int i;
++
++	/*
++	 *	Shut down all active vif entries
++	 */
++	for (i = 0; i < maxvif; i++) {
++		if (!(vif6_table[i].flags & VIFF_STATIC))
++			mif6_delete(i);
++	}
++
++	/*
++	 *	Wipe the cache
++	 */
++	for (i = 0; i < ARRAY_SIZE(mfc6_cache_array); i++) {
++		struct mfc6_cache *c, **cp;
++
++		cp = &mfc6_cache_array[i];
++		while ((c = *cp) != NULL) {
++			if (c->mfc_flags & MFC_STATIC) {
++				cp = &c->next;
++				continue;
++			}
++			write_lock_bh(&mrt_lock);
++			*cp = c->next;
++			write_unlock_bh(&mrt_lock);
++
++			kmem_cache_free(mrt_cachep, c);
++		}
++	}
++
++	if (atomic_read(&cache_resolve_queue_len) != 0) {
++		struct mfc6_cache *c;
++
++		spin_lock_bh(&mfc_unres_lock);
++		while (mfc_unres_queue != NULL) {
++			c = mfc_unres_queue;
++			mfc_unres_queue = c->next;
++			spin_unlock_bh(&mfc_unres_lock);
++
++			ip6mr_destroy_unres(c);
++
++			spin_lock_bh(&mfc_unres_lock);
++		}
++		spin_unlock_bh(&mfc_unres_lock);
++	}
++}
++
++static int ip6mr_sk_init(struct sock *sk)
++{
++	int err = 0;
++
++	rtnl_lock();
++	write_lock_bh(&mrt_lock);
++	if (likely(mroute6_socket == NULL))
++		mroute6_socket = sk;
++	else
++		err = -EADDRINUSE;
++	write_unlock_bh(&mrt_lock);
++
++	rtnl_unlock();
++
++	return err;
++}
++
++int ip6mr_sk_done(struct sock *sk)
++{
++	int err = 0;
++
++	rtnl_lock();
++	if (sk == mroute6_socket) {
++		write_lock_bh(&mrt_lock);
++		mroute6_socket = NULL;
++		write_unlock_bh(&mrt_lock);
++
++		mroute_clean_tables(sk);
++	} else
++		err = -EACCES;
++	rtnl_unlock();
++
++	return err;
++}
++
++/*
++ *	Socket options and virtual interface manipulation. The whole
++ *	virtual interface system is a complete heap, but unfortunately
++ *	that's how BSD mrouted happens to think. Maybe one day with a proper
++ *	MOSPF/PIM router set up we can clean this up.
++ */
++
++int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int optlen)
++{
++	int ret;
++	struct mif6ctl vif;
++	struct mf6cctl mfc;
++	mifi_t mifi;
++
++	if (optname != MRT6_INIT) {
++		if (sk != mroute6_socket && !capable(CAP_NET_ADMIN))
++			return -EACCES;
++	}
++
++	switch (optname) {
++	case MRT6_INIT:
++		if (sk->sk_type != SOCK_RAW ||
++		    inet_sk(sk)->num != IPPROTO_ICMPV6)
++			return -EOPNOTSUPP;
++		if (optlen < sizeof(int))
++			return -EINVAL;
++
++		return ip6mr_sk_init(sk);
++
++	case MRT6_DONE:
++		return ip6mr_sk_done(sk);
++
++	case MRT6_ADD_MIF:
++		if (optlen < sizeof(vif))
++			return -EINVAL;
++		if (copy_from_user(&vif, optval, sizeof(vif)))
++			return -EFAULT;
++		if (vif.mif6c_mifi >= MAXMIFS)
++			return -ENFILE;
++		rtnl_lock();
++		ret = mif6_add(&vif, sk == mroute6_socket);
++		rtnl_unlock();
++		return ret;
++
++	case MRT6_DEL_MIF:
++		if (optlen < sizeof(mifi_t))
++			return -EINVAL;
++		if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
++			return -EFAULT;
++		rtnl_lock();
++		ret = mif6_delete(mifi);
++		rtnl_unlock();
++		return ret;
++
++	/*
++	 *	Manipulate the forwarding caches. These live
++	 *	in a sort of kernel/user symbiosis.
++	 */
++	case MRT6_ADD_MFC:
++	case MRT6_DEL_MFC:
++		if (optlen < sizeof(mfc))
++			return -EINVAL;
++		if (copy_from_user(&mfc, optval, sizeof(mfc)))
++			return -EFAULT;
++		rtnl_lock();
++		if (optname == MRT6_DEL_MFC)
++			ret = ip6mr_mfc_delete(&mfc);
++		else
++			ret = ip6mr_mfc_add(&mfc, sk == mroute6_socket);
++		rtnl_unlock();
++		return ret;
++
++	/*
++	 *	Control PIM assert (to activate pim will activate assert)
++	 */
++	case MRT6_ASSERT:
++	{
++		int v;
++		if (get_user(v, (int __user *)optval))
++			return -EFAULT;
++		mroute_do_assert = !!v;
++		return 0;
++	}
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++	case MRT6_PIM:
++	{
++		int v;
++		if (get_user(v, (int __user *)optval))
++			return -EFAULT;
++		v = !!v;
++		rtnl_lock();
++		ret = 0;
++		if (v != mroute_do_pim) {
++			mroute_do_pim = v;
++			mroute_do_assert = v;
++			if (mroute_do_pim)
++				ret = inet6_add_protocol(&pim6_protocol,
++							 IPPROTO_PIM);
++			else
++				ret = inet6_del_protocol(&pim6_protocol,
++							 IPPROTO_PIM);
++			if (ret < 0)
++				ret = -EAGAIN;
++		}
++		rtnl_unlock();
++		return ret;
++	}
++
++#endif
++	/*
++	 *	Spurious command, or MRT_VERSION which you cannot
++	 *	set.
++	 */
++	default:
++		return -ENOPROTOOPT;
++	}
++}
++
++/*
++ *	Getsock opt support for the multicast routing system.
++ */
++
++int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
++			  int __user *optlen)
++{
++	int olr;
++	int val;
++
++	switch (optname) {
++	case MRT6_VERSION:
++		val = 0x0305;
++		break;
++#ifdef CONFIG_IPV6_PIMSM_V2
++	case MRT6_PIM:
++		val = mroute_do_pim;
++		break;
++#endif
++	case MRT6_ASSERT:
++		val = mroute_do_assert;
++		break;
++	default:
++		return -ENOPROTOOPT;
++	}
++
++	if (get_user(olr, optlen))
++		return -EFAULT;
++
++	olr = min_t(int, olr, sizeof(int));
++	if (olr < 0)
++		return -EINVAL;
++
++	if (put_user(olr, optlen))
++		return -EFAULT;
++	if (copy_to_user(optval, &val, olr))
++		return -EFAULT;
++	return 0;
++}
++
++/*
++ *	The IP multicast ioctl support routines.
++ */
++
++int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
++{
++	struct sioc_sg_req6 sr;
++	struct sioc_mif_req6 vr;
++	struct mif_device *vif;
++	struct mfc6_cache *c;
++
++	switch (cmd) {
++	case SIOCGETMIFCNT_IN6:
++		if (copy_from_user(&vr, arg, sizeof(vr)))
++			return -EFAULT;
++		if (vr.mifi >= maxvif)
++			return -EINVAL;
++		read_lock(&mrt_lock);
++		vif = &vif6_table[vr.mifi];
++		if (MIF_EXISTS(vr.mifi)) {
++			vr.icount = vif->pkt_in;
++			vr.ocount = vif->pkt_out;
++			vr.ibytes = vif->bytes_in;
++			vr.obytes = vif->bytes_out;
++			read_unlock(&mrt_lock);
++
++			if (copy_to_user(arg, &vr, sizeof(vr)))
++				return -EFAULT;
++			return 0;
++		}
++		read_unlock(&mrt_lock);
++		return -EADDRNOTAVAIL;
++	case SIOCGETSGCNT_IN6:
++		if (copy_from_user(&sr, arg, sizeof(sr)))
++			return -EFAULT;
++
++		read_lock(&mrt_lock);
++		c = ip6mr_cache_find(&sr.src.sin6_addr, &sr.grp.sin6_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);
++
++			if (copy_to_user(arg, &sr, sizeof(sr)))
++				return -EFAULT;
++			return 0;
++		}
++		read_unlock(&mrt_lock);
++		return -EADDRNOTAVAIL;
++	default:
++		return -ENOIOCTLCMD;
++	}
++}
++
++
++static inline int ip6mr_forward2_finish(struct sk_buff *skb)
++{
++	IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
++	return dst_output(skb);
++}
++
++/*
++ *	Processing handlers for ip6mr_forward
++ */
++
++static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi)
++{
++	struct ipv6hdr *ipv6h;
++	struct mif_device *vif = &vif6_table[vifi];
++	struct net_device *dev;
++	struct dst_entry *dst;
++	struct flowi fl;
++
++	if (vif->dev == NULL)
++		goto out_free;
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++	if (vif->flags & MIFF_REGISTER) {
++		vif->pkt_out++;
++		vif->bytes_out += skb->len;
++		((struct net_device_stats *)netdev_priv(vif->dev))->tx_bytes += skb->len;
++		((struct net_device_stats *)netdev_priv(vif->dev))->tx_packets++;
++		ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT);
++		kfree_skb(skb);
++		return 0;
++	}
++#endif
++
++	ipv6h = ipv6_hdr(skb);
++
++	fl = (struct flowi) {
++		.oif = vif->link,
++		.nl_u = { .ip6_u =
++				{ .daddr = ipv6h->daddr, }
++		}
++	};
++
++	dst = ip6_route_output(&init_net, NULL, &fl);
++	if (!dst)
++		goto out_free;
++
++	dst_release(skb->dst);
++	skb->dst = dst;
++
++	/*
++	 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
++	 * not only before forwarding, but after forwarding on all output
++	 * interfaces. It is clear, if mrouter runs a multicasting
++	 * program, it should receive packets not depending to what interface
++	 * program is joined.
++	 * If we will not make it, the program will have to join on all
++	 * interfaces. On the other hand, multihoming host (or router, but
++	 * not mrouter) cannot join to more than one interface - it will
++	 * result in receiving multiple packets.
++	 */
++	dev = vif->dev;
++	skb->dev = dev;
++	vif->pkt_out++;
++	vif->bytes_out += skb->len;
++
++	/* We are about to write */
++	/* XXX: extension headers? */
++	if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
++		goto out_free;
++
++	ipv6h = ipv6_hdr(skb);
++	ipv6h->hop_limit--;
++
++	IP6CB(skb)->flags |= IP6SKB_FORWARDED;
++
++	return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dev,
++		       ip6mr_forward2_finish);
++
++out_free:
++	kfree_skb(skb);
++	return 0;
++}
++
++static int ip6mr_find_vif(struct net_device *dev)
++{
++	int ct;
++	for (ct = maxvif - 1; ct >= 0; ct--) {
++		if (vif6_table[ct].dev == dev)
++			break;
++	}
++	return ct;
++}
++
++static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
++{
++	int psend = -1;
++	int vif, ct;
++
++	vif = cache->mf6c_parent;
++	cache->mfc_un.res.pkt++;
++	cache->mfc_un.res.bytes += skb->len;
++
++	/*
++	 * Wrong interface: drop packet and (maybe) send PIM assert.
++	 */
++	if (vif6_table[vif].dev != skb->dev) {
++		int true_vifi;
++
++		cache->mfc_un.res.wrong_if++;
++		true_vifi = ip6mr_find_vif(skb->dev);
++
++		if (true_vifi >= 0 && 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
++		     */
++		    (mroute_do_pim || cache->mfc_un.res.ttls[true_vifi] < 255) &&
++		    time_after(jiffies,
++			       cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
++			cache->mfc_un.res.last_assert = jiffies;
++			ip6mr_cache_report(skb, true_vifi, MRT6MSG_WRONGMIF);
++		}
++		goto dont_forward;
++	}
++
++	vif6_table[vif].pkt_in++;
++	vif6_table[vif].bytes_in += skb->len;
++
++	/*
++	 *	Forward the frame
++	 */
++	for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) {
++		if (ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) {
++			if (psend != -1) {
++				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
++				if (skb2)
++					ip6mr_forward2(skb2, cache, psend);
++			}
++			psend = ct;
++		}
++	}
++	if (psend != -1) {
++		ip6mr_forward2(skb, cache, psend);
++		return 0;
++	}
++
++dont_forward:
++	kfree_skb(skb);
++	return 0;
++}
++
++
++/*
++ *	Multicast packets for forwarding arrive here
++ */
++
++int ip6_mr_input(struct sk_buff *skb)
++{
++	struct mfc6_cache *cache;
++
++	read_lock(&mrt_lock);
++	cache = ip6mr_cache_find(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
++
++	/*
++	 *	No usable cache entry
++	 */
++	if (cache == NULL) {
++		int vif;
++
++		vif = ip6mr_find_vif(skb->dev);
++		if (vif >= 0) {
++			int err = ip6mr_cache_unresolved(vif, skb);
++			read_unlock(&mrt_lock);
++
++			return err;
++		}
++		read_unlock(&mrt_lock);
++		kfree_skb(skb);
++		return -ENODEV;
++	}
++
++	ip6_mr_forward(skb, cache);
++
++	read_unlock(&mrt_lock);
++
++	return 0;
++}
++
++
++static int
++ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
++{
++	int ct;
++	struct rtnexthop *nhp;
++	struct net_device *dev = vif6_table[c->mf6c_parent].dev;
++	u8 *b = skb_tail_pointer(skb);
++	struct rtattr *mp_head;
++
++	if (dev)
++		RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex);
++
++	mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
++
++	for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
++		if (c->mfc_un.res.ttls[ct] < 255) {
++			if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
++				goto rtattr_failure;
++			nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
++			nhp->rtnh_flags = 0;
++			nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
++			nhp->rtnh_ifindex = vif6_table[ct].dev->ifindex;
++			nhp->rtnh_len = sizeof(*nhp);
++		}
++	}
++	mp_head->rta_type = RTA_MULTIPATH;
++	mp_head->rta_len = skb_tail_pointer(skb) - (u8 *)mp_head;
++	rtm->rtm_type = RTN_MULTICAST;
++	return 1;
++
++rtattr_failure:
++	nlmsg_trim(skb, b);
++	return -EMSGSIZE;
++}
++
++int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
++{
++	int err;
++	struct mfc6_cache *cache;
++	struct rt6_info *rt = (struct rt6_info *)skb->dst;
++
++	read_lock(&mrt_lock);
++	cache = ip6mr_cache_find(&rt->rt6i_src.addr, &rt->rt6i_dst.addr);
++
++	if (!cache) {
++		struct sk_buff *skb2;
++		struct ipv6hdr *iph;
++		struct net_device *dev;
++		int vif;
++
++		if (nowait) {
++			read_unlock(&mrt_lock);
++			return -EAGAIN;
++		}
++
++		dev = skb->dev;
++		if (dev == NULL || (vif = ip6mr_find_vif(dev)) < 0) {
++			read_unlock(&mrt_lock);
++			return -ENODEV;
++		}
++
++		/* really correct? */
++		skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
++		if (!skb2) {
++			read_unlock(&mrt_lock);
++			return -ENOMEM;
++		}
++
++		skb_reset_transport_header(skb2);
++
++		skb_put(skb2, sizeof(struct ipv6hdr));
++		skb_reset_network_header(skb2);
++
++		iph = ipv6_hdr(skb2);
++		iph->version = 0;
++		iph->priority = 0;
++		iph->flow_lbl[0] = 0;
++		iph->flow_lbl[1] = 0;
++		iph->flow_lbl[2] = 0;
++		iph->payload_len = 0;
++		iph->nexthdr = IPPROTO_NONE;
++		iph->hop_limit = 0;
++		ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr);
++		ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr);
++
++		err = ip6mr_cache_unresolved(vif, skb2);
++		read_unlock(&mrt_lock);
++
++		return err;
++	}
++
++	if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY))
++		cache->mfc_flags |= MFC_NOTIFY;
++
++	err = ip6mr_fill_mroute(skb, cache, rtm);
++	read_unlock(&mrt_lock);
++	return err;
++}
++
+diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
+index e3dcfa2..ee6de42 100644
+--- a/net/ipv6/ipcomp6.c
++++ b/net/ipv6/ipcomp6.c
+@@ -34,7 +34,6 @@
+ #include <net/ip.h>
+ #include <net/xfrm.h>
+ #include <net/ipcomp.h>
+-#include <asm/semaphore.h>
+ #include <linux/crypto.h>
+ #include <linux/err.h>
+ #include <linux/pfkeyv2.h>
+diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
+index bf2a686..06de9d0 100644
+--- a/net/ipv6/ipv6_sockglue.c
++++ b/net/ipv6/ipv6_sockglue.c
+@@ -16,7 +16,6 @@
+  *
+  *	FIXME: Make the setsockopt code POSIX compliant: That is
+  *
+- *	o	Return -EINVAL for setsockopt of short lengths
+  *	o	Truncate getsockopt returns
+  *	o	Return an optlen of the truncated length if need be
+  *
+@@ -33,6 +32,7 @@
+ #include <linux/sockios.h>
+ #include <linux/net.h>
+ #include <linux/in6.h>
++#include <linux/mroute6.h>
+ #include <linux/netdevice.h>
+ #include <linux/if_arp.h>
+ #include <linux/init.h>
+@@ -57,118 +57,6 @@
+ 
+ DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly;
+ 
+-static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb,
+-						    int proto)
+-{
+-	struct inet6_protocol *ops = NULL;
+-
+-	for (;;) {
+-		struct ipv6_opt_hdr *opth;
+-		int len;
+-
+-		if (proto != NEXTHDR_HOP) {
+-			ops = rcu_dereference(inet6_protos[proto]);
+-
+-			if (unlikely(!ops))
+-				break;
+-
+-			if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
+-				break;
+-		}
+-
+-		if (unlikely(!pskb_may_pull(skb, 8)))
+-			break;
+-
+-		opth = (void *)skb->data;
+-		len = opth->hdrlen * 8 + 8;
+-
+-		if (unlikely(!pskb_may_pull(skb, len)))
+-			break;
+-
+-		proto = opth->nexthdr;
+-		__skb_pull(skb, len);
+-	}
+-
+-	return ops;
+-}
+-
+-static int ipv6_gso_send_check(struct sk_buff *skb)
+-{
+-	struct ipv6hdr *ipv6h;
+-	struct inet6_protocol *ops;
+-	int err = -EINVAL;
+-
+-	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+-		goto out;
+-
+-	ipv6h = ipv6_hdr(skb);
+-	__skb_pull(skb, sizeof(*ipv6h));
+-	err = -EPROTONOSUPPORT;
+-
+-	rcu_read_lock();
+-	ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
+-	if (likely(ops && ops->gso_send_check)) {
+-		skb_reset_transport_header(skb);
+-		err = ops->gso_send_check(skb);
+-	}
+-	rcu_read_unlock();
+-
+-out:
+-	return err;
+-}
+-
+-static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
+-{
+-	struct sk_buff *segs = ERR_PTR(-EINVAL);
+-	struct ipv6hdr *ipv6h;
+-	struct inet6_protocol *ops;
+-
+-	if (!(features & NETIF_F_V6_CSUM))
+-		features &= ~NETIF_F_SG;
+-
+-	if (unlikely(skb_shinfo(skb)->gso_type &
+-		     ~(SKB_GSO_UDP |
+-		       SKB_GSO_DODGY |
+-		       SKB_GSO_TCP_ECN |
+-		       SKB_GSO_TCPV6 |
+-		       0)))
+-		goto out;
+-
+-	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+-		goto out;
+-
+-	ipv6h = ipv6_hdr(skb);
+-	__skb_pull(skb, sizeof(*ipv6h));
+-	segs = ERR_PTR(-EPROTONOSUPPORT);
+-
+-	rcu_read_lock();
+-	ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
+-	if (likely(ops && ops->gso_segment)) {
+-		skb_reset_transport_header(skb);
+-		segs = ops->gso_segment(skb, features);
+-	}
+-	rcu_read_unlock();
+-
+-	if (unlikely(IS_ERR(segs)))
+-		goto out;
+-
+-	for (skb = segs; skb; skb = skb->next) {
+-		ipv6h = ipv6_hdr(skb);
+-		ipv6h->payload_len = htons(skb->len - skb->mac_len -
+-					   sizeof(*ipv6h));
+-	}
+-
+-out:
+-	return segs;
+-}
+-
+-static struct packet_type ipv6_packet_type = {
+-	.type = __constant_htons(ETH_P_IPV6),
+-	.func = ipv6_rcv,
+-	.gso_send_check = ipv6_gso_send_check,
+-	.gso_segment = ipv6_gso_segment,
+-};
+-
+ struct ip6_ra_chain *ip6_ra_chain;
+ DEFINE_RWLOCK(ip6_ra_lock);
+ 
+@@ -215,25 +103,59 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
+ 	return 0;
+ }
+ 
++static
++struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
++					   struct ipv6_txoptions *opt)
++{
++	if (inet_sk(sk)->is_icsk) {
++		if (opt &&
++		    !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
++		    inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
++			struct inet_connection_sock *icsk = inet_csk(sk);
++			icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen;
++			icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
++		}
++		opt = xchg(&inet6_sk(sk)->opt, opt);
++	} else {
++		write_lock(&sk->sk_dst_lock);
++		opt = xchg(&inet6_sk(sk)->opt, opt);
++		write_unlock(&sk->sk_dst_lock);
++	}
++	sk_dst_reset(sk);
++
++	return opt;
++}
++
+ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ 		    char __user *optval, int optlen)
+ {
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
++	struct net *net = sock_net(sk);
+ 	int val, valbool;
+ 	int retv = -ENOPROTOOPT;
+ 
+ 	if (optval == NULL)
+ 		val=0;
+-	else if (get_user(val, (int __user *) optval))
+-		return -EFAULT;
++	else {
++		if (optlen >= sizeof(int)) {
++			if (get_user(val, (int __user *) optval))
++				return -EFAULT;
++		} else
++			val = 0;
++	}
+ 
+ 	valbool = (val!=0);
+ 
++	if (ip6_mroute_opt(optname))
++		return ip6_mroute_setsockopt(sk, optname, optval, optlen);
++
+ 	lock_sock(sk);
+ 
+ 	switch (optname) {
+ 
+ 	case IPV6_ADDRFORM:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		if (val == PF_INET) {
+ 			struct ipv6_txoptions *opt;
+ 			struct sk_buff *pktopt;
+@@ -266,10 +188,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ 
+ 			if (sk->sk_protocol == IPPROTO_TCP) {
+ 				struct inet_connection_sock *icsk = inet_csk(sk);
+-
+ 				local_bh_disable();
+-				sock_prot_inuse_add(sk->sk_prot, -1);
+-				sock_prot_inuse_add(&tcp_prot, 1);
++				sock_prot_inuse_add(net, sk->sk_prot, -1);
++				sock_prot_inuse_add(net, &tcp_prot, 1);
+ 				local_bh_enable();
+ 				sk->sk_prot = &tcp_prot;
+ 				icsk->icsk_af_ops = &ipv4_specific;
+@@ -282,8 +203,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ 				if (sk->sk_protocol == IPPROTO_UDPLITE)
+ 					prot = &udplite_prot;
+ 				local_bh_disable();
+-				sock_prot_inuse_add(sk->sk_prot, -1);
+-				sock_prot_inuse_add(prot, 1);
++				sock_prot_inuse_add(net, sk->sk_prot, -1);
++				sock_prot_inuse_add(net, prot, 1);
+ 				local_bh_enable();
+ 				sk->sk_prot = prot;
+ 				sk->sk_socket->ops = &inet_dgram_ops;
+@@ -309,63 +230,86 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ 		goto e_inval;
+ 
+ 	case IPV6_V6ONLY:
+-		if (inet_sk(sk)->num)
++		if (optlen < sizeof(int) ||
++		    inet_sk(sk)->num)
+ 			goto e_inval;
+ 		np->ipv6only = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_RECVPKTINFO:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.rxinfo = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_2292PKTINFO:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.rxoinfo = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_RECVHOPLIMIT:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.rxhlim = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_2292HOPLIMIT:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.rxohlim = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_RECVRTHDR:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.srcrt = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_2292RTHDR:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.osrcrt = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_RECVHOPOPTS:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.hopopts = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_2292HOPOPTS:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.ohopopts = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_RECVDSTOPTS:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.dstopts = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_2292DSTOPTS:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.odstopts = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_TCLASS:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		if (val < -1 || val > 0xff)
+ 			goto e_inval;
+ 		np->tclass = val;
+@@ -373,11 +317,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ 		break;
+ 
+ 	case IPV6_RECVTCLASS:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.rxtclass = valbool;
+ 		retv = 0;
+ 		break;
+ 
+ 	case IPV6_FLOWINFO:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->rxopt.bits.rxflow = valbool;
+ 		retv = 0;
+ 		break;
+@@ -396,9 +344,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ 		if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
+ 			break;
+ 
+-		retv = -EINVAL;
+-		if (optlen & 0x7 || optlen > 8 * 255)
+-			break;
++		if (optlen < sizeof(struct ipv6_opt_hdr) ||
++		    optlen & 0x7 || optlen > 8 * 255)
++			goto e_inval;
+ 
+ 		opt = ipv6_renew_options(sk, np->opt, optname,
+ 					 (struct ipv6_opt_hdr __user *)optval,
+@@ -426,25 +374,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ 		}
+ 
+ 		retv = 0;
+-		if (inet_sk(sk)->is_icsk) {
+-			if (opt) {
+-				struct inet_connection_sock *icsk = inet_csk(sk);
+-				if (!((1 << sk->sk_state) &
+-				      (TCPF_LISTEN | TCPF_CLOSE))
+-				    && inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
+-					icsk->icsk_ext_hdr_len =
+-						opt->opt_flen + opt->opt_nflen;
+-					icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
+-				}
+-			}
+-			opt = xchg(&np->opt, opt);
+-			sk_dst_reset(sk);
+-		} else {
+-			write_lock(&sk->sk_dst_lock);
+-			opt = xchg(&np->opt, opt);
+-			write_unlock(&sk->sk_dst_lock);
+-			sk_dst_reset(sk);
+-		}
++		opt = ipv6_update_options(sk, opt);
+ sticky_done:
+ 		if (opt)
+ 			sock_kfree_s(sk, opt, opt->tot_len);
+@@ -490,32 +420,15 @@ sticky_done:
+ 			goto done;
+ update:
+ 		retv = 0;
+-		if (inet_sk(sk)->is_icsk) {
+-			if (opt) {
+-				struct inet_connection_sock *icsk = inet_csk(sk);
+-				if (!((1 << sk->sk_state) &
+-				      (TCPF_LISTEN | TCPF_CLOSE))
+-				    && inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
+-					icsk->icsk_ext_hdr_len =
+-						opt->opt_flen + opt->opt_nflen;
+-					icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
+-				}
+-			}
+-			opt = xchg(&np->opt, opt);
+-			sk_dst_reset(sk);
+-		} else {
+-			write_lock(&sk->sk_dst_lock);
+-			opt = xchg(&np->opt, opt);
+-			write_unlock(&sk->sk_dst_lock);
+-			sk_dst_reset(sk);
+-		}
+-
++		opt = ipv6_update_options(sk, opt);
+ done:
+ 		if (opt)
+ 			sock_kfree_s(sk, opt, opt->tot_len);
+ 		break;
+ 	}
+ 	case IPV6_UNICAST_HOPS:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		if (val > 255 || val < -1)
+ 			goto e_inval;
+ 		np->hop_limit = val;
+@@ -525,6 +438,8 @@ done:
+ 	case IPV6_MULTICAST_HOPS:
+ 		if (sk->sk_type == SOCK_STREAM)
+ 			goto e_inval;
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		if (val > 255 || val < -1)
+ 			goto e_inval;
+ 		np->mcast_hops = val;
+@@ -532,6 +447,8 @@ done:
+ 		break;
+ 
+ 	case IPV6_MULTICAST_LOOP:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->mc_loop = valbool;
+ 		retv = 0;
+ 		break;
+@@ -539,12 +456,14 @@ done:
+ 	case IPV6_MULTICAST_IF:
+ 		if (sk->sk_type == SOCK_STREAM)
+ 			goto e_inval;
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 
+ 		if (val) {
+ 			if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val)
+ 				goto e_inval;
+ 
+-			if (__dev_get_by_index(&init_net, val) == NULL) {
++			if (__dev_get_by_index(net, val) == NULL) {
+ 				retv = -ENODEV;
+ 				break;
+ 			}
+@@ -557,6 +476,9 @@ done:
+ 	{
+ 		struct ipv6_mreq mreq;
+ 
++		if (optlen < sizeof(struct ipv6_mreq))
++			goto e_inval;
++
+ 		retv = -EPROTO;
+ 		if (inet_sk(sk)->is_icsk)
+ 			break;
+@@ -576,7 +498,7 @@ done:
+ 	{
+ 		struct ipv6_mreq mreq;
+ 
+-		if (optlen != sizeof(struct ipv6_mreq))
++		if (optlen < sizeof(struct ipv6_mreq))
+ 			goto e_inval;
+ 
+ 		retv = -EFAULT;
+@@ -595,6 +517,9 @@ done:
+ 		struct group_req greq;
+ 		struct sockaddr_in6 *psin6;
+ 
++		if (optlen < sizeof(struct group_req))
++			goto e_inval;
++
+ 		retv = -EFAULT;
+ 		if (copy_from_user(&greq, optval, sizeof(struct group_req)))
+ 			break;
+@@ -619,7 +544,7 @@ done:
+ 		struct group_source_req greqs;
+ 		int omode, add;
+ 
+-		if (optlen != sizeof(struct group_source_req))
++		if (optlen < sizeof(struct group_source_req))
+ 			goto e_inval;
+ 		if (copy_from_user(&greqs, optval, sizeof(greqs))) {
+ 			retv = -EFAULT;
+@@ -693,27 +618,37 @@ done:
+ 		break;
+ 	}
+ 	case IPV6_ROUTER_ALERT:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		retv = ip6_ra_control(sk, val, NULL);
+ 		break;
+ 	case IPV6_MTU_DISCOVER:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		if (val<0 || val>3)
+ 			goto e_inval;
+ 		np->pmtudisc = val;
+ 		retv = 0;
+ 		break;
+ 	case IPV6_MTU:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		if (val && val < IPV6_MIN_MTU)
+ 			goto e_inval;
+ 		np->frag_size = val;
+ 		retv = 0;
+ 		break;
+ 	case IPV6_RECVERR:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->recverr = valbool;
+ 		if (!val)
+ 			skb_queue_purge(&sk->sk_error_queue);
+ 		retv = 0;
+ 		break;
+ 	case IPV6_FLOWINFO_SEND:
++		if (optlen < sizeof(int))
++			goto e_inval;
+ 		np->sndflow = valbool;
+ 		retv = 0;
+ 		break;
+@@ -728,7 +663,70 @@ done:
+ 		retv = xfrm_user_policy(sk, optname, optval, optlen);
+ 		break;
+ 
++	case IPV6_ADDR_PREFERENCES:
++	    {
++		unsigned int pref = 0;
++		unsigned int prefmask = ~0;
++
++		if (optlen < sizeof(int))
++			goto e_inval;
++
++		retv = -EINVAL;
++
++		/* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
++		switch (val & (IPV6_PREFER_SRC_PUBLIC|
++			       IPV6_PREFER_SRC_TMP|
++			       IPV6_PREFER_SRC_PUBTMP_DEFAULT)) {
++		case IPV6_PREFER_SRC_PUBLIC:
++			pref |= IPV6_PREFER_SRC_PUBLIC;
++			break;
++		case IPV6_PREFER_SRC_TMP:
++			pref |= IPV6_PREFER_SRC_TMP;
++			break;
++		case IPV6_PREFER_SRC_PUBTMP_DEFAULT:
++			break;
++		case 0:
++			goto pref_skip_pubtmp;
++		default:
++			goto e_inval;
++		}
++
++		prefmask &= ~(IPV6_PREFER_SRC_PUBLIC|
++			      IPV6_PREFER_SRC_TMP);
++pref_skip_pubtmp:
++
++		/* check HOME/COA conflicts */
++		switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) {
++		case IPV6_PREFER_SRC_HOME:
++			break;
++		case IPV6_PREFER_SRC_COA:
++			pref |= IPV6_PREFER_SRC_COA;
++		case 0:
++			goto pref_skip_coa;
++		default:
++			goto e_inval;
++		}
++
++		prefmask &= ~IPV6_PREFER_SRC_COA;
++pref_skip_coa:
++
++		/* check CGA/NONCGA conflicts */
++		switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) {
++		case IPV6_PREFER_SRC_CGA:
++		case IPV6_PREFER_SRC_NONCGA:
++		case 0:
++			break;
++		default:
++			goto e_inval;
++		}
++
++		np->srcprefs = (np->srcprefs & prefmask) | pref;
++		retv = 0;
++
++		break;
++	    }
+ 	}
++
+ 	release_sock(sk);
+ 
+ 	return retv;
+@@ -839,6 +837,9 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ 	int len;
+ 	int val;
+ 
++	if (ip6_mroute_opt(optname))
++		return ip6_mroute_getsockopt(sk, optname, optval, optlen);
++
+ 	if (get_user(len, optlen))
+ 		return -EFAULT;
+ 	switch (optname) {
+@@ -1015,9 +1016,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ 		dst = sk_dst_get(sk);
+ 		if (dst) {
+ 			if (val < 0)
+-				val = dst_metric(dst, RTAX_HOPLIMIT);
+-			if (val < 0)
+-				val = ipv6_get_hoplimit(dst->dev);
++				val = ip6_dst_hoplimit(dst);
+ 			dst_release(dst);
+ 		}
+ 		if (val < 0)
+@@ -1045,6 +1044,24 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ 		val = np->sndflow;
+ 		break;
+ 
++	case IPV6_ADDR_PREFERENCES:
++		val = 0;
++
++		if (np->srcprefs & IPV6_PREFER_SRC_TMP)
++			val |= IPV6_PREFER_SRC_TMP;
++		else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC)
++			val |= IPV6_PREFER_SRC_PUBLIC;
++		else {
++			/* XXX: should we return system default? */
++			val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT;
++		}
++
++		if (np->srcprefs & IPV6_PREFER_SRC_COA)
++			val |= IPV6_PREFER_SRC_COA;
++		else
++			val |= IPV6_PREFER_SRC_HOME;
++		break;
++
+ 	default:
+ 		return -ENOPROTOOPT;
+ 	}
+@@ -1128,13 +1145,3 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ EXPORT_SYMBOL(compat_ipv6_getsockopt);
+ #endif
+ 
+-int __init ipv6_packet_init(void)
+-{
+-	dev_add_pack(&ipv6_packet_type);
+-	return 0;
+-}
+-
+-void ipv6_packet_cleanup(void)
+-{
+-	dev_remove_pack(&ipv6_packet_type);
+-}
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index ab228d1..54f91ef 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -59,6 +59,7 @@
+ #include <net/ndisc.h>
+ #include <net/addrconf.h>
+ #include <net/ip6_route.h>
++#include <net/inet_common.h>
+ 
+ #include <net/ip6_checksum.h>
+ 
+@@ -126,10 +127,6 @@ static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
+ /* Big mc list lock for all the sockets */
+ static DEFINE_RWLOCK(ipv6_sk_mc_lock);
+ 
+-static struct socket *igmp6_socket;
+-
+-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
+-
+ static void igmp6_join_group(struct ifmcaddr6 *ma);
+ static void igmp6_leave_group(struct ifmcaddr6 *ma);
+ static void igmp6_timer_handler(unsigned long data);
+@@ -178,11 +175,12 @@ int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
+  *	socket join on multicast group
+  */
+ 
+-int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
++int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
+ {
+ 	struct net_device *dev = NULL;
+ 	struct ipv6_mc_socklist *mc_lst;
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
++	struct net *net = sock_net(sk);
+ 	int err;
+ 
+ 	if (!ipv6_addr_is_multicast(addr))
+@@ -208,14 +206,14 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 
+ 	if (ifindex == 0) {
+ 		struct rt6_info *rt;
+-		rt = rt6_lookup(addr, NULL, 0, 0);
++		rt = rt6_lookup(net, addr, NULL, 0, 0);
+ 		if (rt) {
+ 			dev = rt->rt6i_dev;
+ 			dev_hold(dev);
+ 			dst_release(&rt->u.dst);
+ 		}
+ 	} else
+-		dev = dev_get_by_index(&init_net, ifindex);
++		dev = dev_get_by_index(net, ifindex);
+ 
+ 	if (dev == NULL) {
+ 		sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
+@@ -252,10 +250,11 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ /*
+  *	socket leave on multicast group
+  */
+-int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
++int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
+ {
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+ 	struct ipv6_mc_socklist *mc_lst, **lnk;
++	struct net *net = sock_net(sk);
+ 
+ 	write_lock_bh(&ipv6_sk_mc_lock);
+ 	for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) {
+@@ -266,7 +265,8 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 			*lnk = mc_lst->next;
+ 			write_unlock_bh(&ipv6_sk_mc_lock);
+ 
+-			if ((dev = dev_get_by_index(&init_net, mc_lst->ifindex)) != NULL) {
++			dev = dev_get_by_index(net, mc_lst->ifindex);
++			if (dev != NULL) {
+ 				struct inet6_dev *idev = in6_dev_get(dev);
+ 
+ 				(void) ip6_mc_leave_src(sk, mc_lst, idev);
+@@ -286,7 +286,9 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+ 	return -EADDRNOTAVAIL;
+ }
+ 
+-static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex)
++static struct inet6_dev *ip6_mc_find_dev(struct net *net,
++					 struct in6_addr *group,
++					 int ifindex)
+ {
+ 	struct net_device *dev = NULL;
+ 	struct inet6_dev *idev = NULL;
+@@ -294,14 +296,14 @@ static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex)
+ 	if (ifindex == 0) {
+ 		struct rt6_info *rt;
+ 
+-		rt = rt6_lookup(group, NULL, 0, 0);
++		rt = rt6_lookup(net, group, NULL, 0, 0);
+ 		if (rt) {
+ 			dev = rt->rt6i_dev;
+ 			dev_hold(dev);
+ 			dst_release(&rt->u.dst);
+ 		}
+ 	} else
+-		dev = dev_get_by_index(&init_net, ifindex);
++		dev = dev_get_by_index(net, ifindex);
+ 
+ 	if (!dev)
+ 		return NULL;
+@@ -324,6 +326,7 @@ void ipv6_sock_mc_close(struct sock *sk)
+ {
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+ 	struct ipv6_mc_socklist *mc_lst;
++	struct net *net = sock_net(sk);
+ 
+ 	write_lock_bh(&ipv6_sk_mc_lock);
+ 	while ((mc_lst = np->ipv6_mc_list) != NULL) {
+@@ -332,7 +335,7 @@ void ipv6_sock_mc_close(struct sock *sk)
+ 		np->ipv6_mc_list = mc_lst->next;
+ 		write_unlock_bh(&ipv6_sk_mc_lock);
+ 
+-		dev = dev_get_by_index(&init_net, mc_lst->ifindex);
++		dev = dev_get_by_index(net, mc_lst->ifindex);
+ 		if (dev) {
+ 			struct inet6_dev *idev = in6_dev_get(dev);
+ 
+@@ -361,6 +364,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
+ 	struct inet6_dev *idev;
+ 	struct ipv6_pinfo *inet6 = inet6_sk(sk);
+ 	struct ip6_sf_socklist *psl;
++	struct net *net = sock_net(sk);
+ 	int i, j, rv;
+ 	int leavegroup = 0;
+ 	int pmclocked = 0;
+@@ -376,7 +380,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
+ 	if (!ipv6_addr_is_multicast(group))
+ 		return -EINVAL;
+ 
+-	idev = ip6_mc_find_dev(group, pgsr->gsr_interface);
++	idev = ip6_mc_find_dev(net, group, pgsr->gsr_interface);
+ 	if (!idev)
+ 		return -ENODEV;
+ 	dev = idev->dev;
+@@ -500,6 +504,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
+ 	struct inet6_dev *idev;
+ 	struct ipv6_pinfo *inet6 = inet6_sk(sk);
+ 	struct ip6_sf_socklist *newpsl, *psl;
++	struct net *net = sock_net(sk);
+ 	int leavegroup = 0;
+ 	int i, err;
+ 
+@@ -511,7 +516,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
+ 	    gsf->gf_fmode != MCAST_EXCLUDE)
+ 		return -EINVAL;
+ 
+-	idev = ip6_mc_find_dev(group, gsf->gf_interface);
++	idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
+ 
+ 	if (!idev)
+ 		return -ENODEV;
+@@ -592,13 +597,14 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
+ 	struct net_device *dev;
+ 	struct ipv6_pinfo *inet6 = inet6_sk(sk);
+ 	struct ip6_sf_socklist *psl;
++	struct net *net = sock_net(sk);
+ 
+ 	group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
+ 
+ 	if (!ipv6_addr_is_multicast(group))
+ 		return -EINVAL;
+ 
+-	idev = ip6_mc_find_dev(group, gsf->gf_interface);
++	idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
+ 
+ 	if (!idev)
+ 		return -ENODEV;
+@@ -656,8 +662,8 @@ done:
+ 	return err;
+ }
+ 
+-int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr,
+-	struct in6_addr *src_addr)
++int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
++		   const struct in6_addr *src_addr)
+ {
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+ 	struct ipv6_mc_socklist *mc;
+@@ -863,7 +869,7 @@ static void mld_clear_delrec(struct inet6_dev *idev)
+ /*
+  *	device multicast group inc (add if not found)
+  */
+-int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
++int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
+ {
+ 	struct ifmcaddr6 *mc;
+ 	struct inet6_dev *idev;
+@@ -934,7 +940,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
+ /*
+  *	device multicast group del
+  */
+-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
++int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
+ {
+ 	struct ifmcaddr6 *ma, **map;
+ 
+@@ -959,7 +965,7 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
+ 	return -ENOENT;
+ }
+ 
+-int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
++int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
+ {
+ 	struct inet6_dev *idev = in6_dev_get(dev);
+ 	int err;
+@@ -1004,8 +1010,8 @@ int ipv6_is_mld(struct sk_buff *skb, int nexthdr)
+ /*
+  *	check if the interface/address pair is valid
+  */
+-int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
+-	struct in6_addr *src_addr)
++int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
++			const struct in6_addr *src_addr)
+ {
+ 	struct inet6_dev *idev;
+ 	struct ifmcaddr6 *mc;
+@@ -1393,10 +1399,12 @@ mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted)
+ 
+ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
+ {
+-	struct sock *sk = igmp6_socket->sk;
++	struct net *net = dev_net(dev);
++	struct sock *sk = net->ipv6.igmp_sk;
+ 	struct sk_buff *skb;
+ 	struct mld2_report *pmr;
+ 	struct in6_addr addr_buf;
++	const struct in6_addr *saddr;
+ 	int err;
+ 	u8 ra[8] = { IPPROTO_ICMPV6, 0,
+ 		     IPV6_TLV_ROUTERALERT, 2, 0, 0,
+@@ -1415,10 +1423,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
+ 		 * use unspecified address as the source address
+ 		 * when a valid link-local address is not available.
+ 		 */
+-		memset(&addr_buf, 0, sizeof(addr_buf));
+-	}
++		saddr = &in6addr_any;
++	} else
++		saddr = &addr_buf;
+ 
+-	ip6_nd_hdr(sk, skb, dev, &addr_buf, &mld2_all_mcr, NEXTHDR_HOP, 0);
++	ip6_nd_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
+ 
+ 	memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
+ 
+@@ -1433,25 +1442,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
+ 	return skb;
+ }
+ 
+-static inline int mld_dev_queue_xmit2(struct sk_buff *skb)
+-{
+-	struct net_device *dev = skb->dev;
+-	unsigned char ha[MAX_ADDR_LEN];
+-
+-	ndisc_mc_map(&ipv6_hdr(skb)->daddr, ha, dev, 1);
+-	if (dev_hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len) < 0) {
+-		kfree_skb(skb);
+-		return -EINVAL;
+-	}
+-	return dev_queue_xmit(skb);
+-}
+-
+-static inline int mld_dev_queue_xmit(struct sk_buff *skb)
+-{
+-	return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
+-		       mld_dev_queue_xmit2);
+-}
+-
+ static void mld_sendpack(struct sk_buff *skb)
+ {
+ 	struct ipv6hdr *pip6 = ipv6_hdr(skb);
+@@ -1459,7 +1449,9 @@ static void mld_sendpack(struct sk_buff *skb)
+ 			      (struct mld2_report *)skb_transport_header(skb);
+ 	int payload_len, mldlen;
+ 	struct inet6_dev *idev = in6_dev_get(skb->dev);
++	struct net *net = dev_net(skb->dev);
+ 	int err;
++	struct flowi fl;
+ 
+ 	IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
+ 	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
+@@ -1469,8 +1461,25 @@ static void mld_sendpack(struct sk_buff *skb)
+ 	pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
+ 		IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb),
+ 					     mldlen, 0));
++
++	skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
++
++	if (!skb->dst) {
++		err = -ENOMEM;
++		goto err_out;
++	}
++
++	icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT,
++			 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
++			 skb->dev->ifindex);
++
++	err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
++	if (err)
++		goto err_out;
++
+ 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
+-		mld_dev_queue_xmit);
++		      dst_output);
++out:
+ 	if (!err) {
+ 		ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT);
+ 		ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
+@@ -1480,6 +1489,11 @@ static void mld_sendpack(struct sk_buff *skb)
+ 
+ 	if (likely(idev != NULL))
+ 		in6_dev_put(idev);
++	return;
++
++err_out:
++	kfree_skb(skb);
++	goto out;
+ }
+ 
+ static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
+@@ -1749,28 +1763,28 @@ static void mld_send_cr(struct inet6_dev *idev)
+ 
+ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
+ {
+-	struct sock *sk = igmp6_socket->sk;
++	struct net *net = dev_net(dev);
++	struct sock *sk = net->ipv6.igmp_sk;
+ 	struct inet6_dev *idev;
+ 	struct sk_buff *skb;
+ 	struct icmp6hdr *hdr;
+-	struct in6_addr *snd_addr;
++	const struct in6_addr *snd_addr, *saddr;
+ 	struct in6_addr *addrp;
+ 	struct in6_addr addr_buf;
+-	struct in6_addr all_routers;
+ 	int err, len, payload_len, full_len;
+ 	u8 ra[8] = { IPPROTO_ICMPV6, 0,
+ 		     IPV6_TLV_ROUTERALERT, 2, 0, 0,
+ 		     IPV6_TLV_PADN, 0 };
++	struct flowi fl;
+ 
+ 	rcu_read_lock();
+ 	IP6_INC_STATS(__in6_dev_get(dev),
+ 		      IPSTATS_MIB_OUTREQUESTS);
+ 	rcu_read_unlock();
+-	snd_addr = addr;
+-	if (type == ICMPV6_MGM_REDUCTION) {
+-		snd_addr = &all_routers;
+-		ipv6_addr_all_routers(&all_routers);
+-	}
++	if (type == ICMPV6_MGM_REDUCTION)
++		snd_addr = &in6addr_linklocal_allrouters;
++	else
++		snd_addr = addr;
+ 
+ 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
+ 	payload_len = len + sizeof(ra);
+@@ -1793,10 +1807,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
+ 		 * use unspecified address as the source address
+ 		 * when a valid link-local address is not available.
+ 		 */
+-		memset(&addr_buf, 0, sizeof(addr_buf));
+-	}
++		saddr = &in6addr_any;
++	} else
++		saddr = &addr_buf;
+ 
+-	ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len);
++	ip6_nd_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len);
+ 
+ 	memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
+ 
+@@ -1807,14 +1822,29 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
+ 	addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr));
+ 	ipv6_addr_copy(addrp, addr);
+ 
+-	hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len,
++	hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len,
+ 					   IPPROTO_ICMPV6,
+ 					   csum_partial((__u8 *) hdr, len, 0));
+ 
+ 	idev = in6_dev_get(skb->dev);
+ 
++	skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
++	if (!skb->dst) {
++		err = -ENOMEM;
++		goto err_out;
++	}
++
++	icmpv6_flow_init(sk, &fl, type,
++			 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
++			 skb->dev->ifindex);
++
++	err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
++	if (err)
++		goto err_out;
++
+ 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
+-		mld_dev_queue_xmit);
++		      dst_output);
++out:
+ 	if (!err) {
+ 		ICMP6MSGOUT_INC_STATS(idev, type);
+ 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
+@@ -1825,6 +1855,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
+ 	if (likely(idev != NULL))
+ 		in6_dev_put(idev);
+ 	return;
++
++err_out:
++	kfree_skb(skb);
++	goto out;
+ }
+ 
+ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
+@@ -2276,24 +2310,19 @@ void ipv6_mc_init_dev(struct inet6_dev *idev)
+ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
+ {
+ 	struct ifmcaddr6 *i;
+-	struct in6_addr maddr;
+ 
+ 	/* Deactivate timers */
+ 	ipv6_mc_down(idev);
+ 
+ 	/* Delete all-nodes address. */
+-	ipv6_addr_all_nodes(&maddr);
+-
+ 	/* We cannot call ipv6_dev_mc_dec() directly, our caller in
+ 	 * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will
+ 	 * fail.
+ 	 */
+-	__ipv6_dev_mc_dec(idev, &maddr);
++	__ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes);
+ 
+-	if (idev->cnf.forwarding) {
+-		ipv6_addr_all_routers(&maddr);
+-		__ipv6_dev_mc_dec(idev, &maddr);
+-	}
++	if (idev->cnf.forwarding)
++		__ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters);
+ 
+ 	write_lock_bh(&idev->lock);
+ 	while ((i = idev->mc_list) != NULL) {
+@@ -2310,6 +2339,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
+ 
+ #ifdef CONFIG_PROC_FS
+ struct igmp6_mc_iter_state {
++	struct seq_net_private p;
+ 	struct net_device *dev;
+ 	struct inet6_dev *idev;
+ };
+@@ -2320,9 +2350,10 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
+ {
+ 	struct ifmcaddr6 *im = NULL;
+ 	struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
++	struct net *net = seq_file_net(seq);
+ 
+ 	state->idev = NULL;
+-	for_each_netdev(&init_net, state->dev) {
++	for_each_netdev(net, state->dev) {
+ 		struct inet6_dev *idev;
+ 		idev = in6_dev_get(state->dev);
+ 		if (!idev)
+@@ -2424,8 +2455,8 @@ static const struct seq_operations igmp6_mc_seq_ops = {
+ 
+ static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
+ {
+-	return seq_open_private(file, &igmp6_mc_seq_ops,
+-			sizeof(struct igmp6_mc_iter_state));
++	return seq_open_net(inode, file, &igmp6_mc_seq_ops,
++			    sizeof(struct igmp6_mc_iter_state));
+ }
+ 
+ static const struct file_operations igmp6_mc_seq_fops = {
+@@ -2433,10 +2464,11 @@ static const struct file_operations igmp6_mc_seq_fops = {
+ 	.open		=	igmp6_mc_seq_open,
+ 	.read		=	seq_read,
+ 	.llseek		=	seq_lseek,
+-	.release	=	seq_release_private,
++	.release	=	seq_release_net,
+ };
+ 
+ struct igmp6_mcf_iter_state {
++	struct seq_net_private p;
+ 	struct net_device *dev;
+ 	struct inet6_dev *idev;
+ 	struct ifmcaddr6 *im;
+@@ -2449,10 +2481,11 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
+ 	struct ip6_sf_list *psf = NULL;
+ 	struct ifmcaddr6 *im = NULL;
+ 	struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
++	struct net *net = seq_file_net(seq);
+ 
+ 	state->idev = NULL;
+ 	state->im = NULL;
+-	for_each_netdev(&init_net, state->dev) {
++	for_each_netdev(net, state->dev) {
+ 		struct inet6_dev *idev;
+ 		idev = in6_dev_get(state->dev);
+ 		if (unlikely(idev == NULL))
+@@ -2584,8 +2617,8 @@ static const struct seq_operations igmp6_mcf_seq_ops = {
+ 
+ static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
+ {
+-	return seq_open_private(file, &igmp6_mcf_seq_ops,
+-			sizeof(struct igmp6_mcf_iter_state));
++	return seq_open_net(inode, file, &igmp6_mcf_seq_ops,
++			    sizeof(struct igmp6_mcf_iter_state));
+ }
+ 
+ static const struct file_operations igmp6_mcf_seq_fops = {
+@@ -2593,47 +2626,88 @@ static const struct file_operations igmp6_mcf_seq_fops = {
+ 	.open		=	igmp6_mcf_seq_open,
+ 	.read		=	seq_read,
+ 	.llseek		=	seq_lseek,
+-	.release	=	seq_release_private,
++	.release	=	seq_release_net,
+ };
++
++static int igmp6_proc_init(struct net *net)
++{
++	int err;
++
++	err = -ENOMEM;
++	if (!proc_net_fops_create(net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops))
++		goto out;
++	if (!proc_net_fops_create(net, "mcfilter6", S_IRUGO,
++				  &igmp6_mcf_seq_fops))
++		goto out_proc_net_igmp6;
++
++	err = 0;
++out:
++	return err;
++
++out_proc_net_igmp6:
++	proc_net_remove(net, "igmp6");
++	goto out;
++}
++
++static void igmp6_proc_exit(struct net *net)
++{
++	proc_net_remove(net, "mcfilter6");
++	proc_net_remove(net, "igmp6");
++}
++#else
++static int igmp6_proc_init(struct net *net)
++{
++	return 0;
++}
++static void igmp6_proc_exit(struct net *net)
++{
++	;
++}
+ #endif
+ 
+-int __init igmp6_init(struct net_proto_family *ops)
++static int igmp6_net_init(struct net *net)
+ {
+-	struct ipv6_pinfo *np;
+-	struct sock *sk;
+ 	int err;
+ 
+-	err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket);
++	err = inet_ctl_sock_create(&net->ipv6.igmp_sk, PF_INET6,
++				   SOCK_RAW, IPPROTO_ICMPV6, net);
+ 	if (err < 0) {
+ 		printk(KERN_ERR
+ 		       "Failed to initialize the IGMP6 control socket (err %d).\n",
+ 		       err);
+-		igmp6_socket = NULL; /* For safety. */
+-		return err;
++		goto out;
+ 	}
+ 
+-	sk = igmp6_socket->sk;
+-	sk->sk_allocation = GFP_ATOMIC;
+-	sk->sk_prot->unhash(sk);
++	inet6_sk(net->ipv6.igmp_sk)->hop_limit = 1;
+ 
+-	np = inet6_sk(sk);
+-	np->hop_limit = 1;
++	err = igmp6_proc_init(net);
++	if (err)
++		goto out_sock_create;
++out:
++	return err;
+ 
+-#ifdef CONFIG_PROC_FS
+-	proc_net_fops_create(&init_net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops);
+-	proc_net_fops_create(&init_net, "mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops);
+-#endif
++out_sock_create:
++	inet_ctl_sock_destroy(net->ipv6.igmp_sk);
++	goto out;
++}
+ 
+-	return 0;
++static void igmp6_net_exit(struct net *net)
++{
++	inet_ctl_sock_destroy(net->ipv6.igmp_sk);
++	igmp6_proc_exit(net);
+ }
+ 
+-void igmp6_cleanup(void)
++static struct pernet_operations igmp6_net_ops = {
++	.init = igmp6_net_init,
++	.exit = igmp6_net_exit,
++};
++
++int __init igmp6_init(void)
+ {
+-	sock_release(igmp6_socket);
+-	igmp6_socket = NULL; /* for safety */
++	return register_pernet_subsys(&igmp6_net_ops);
++}
+ 
+-#ifdef CONFIG_PROC_FS
+-	proc_net_remove(&init_net, "mcfilter6");
+-	proc_net_remove(&init_net, "igmp6");
+-#endif
++void igmp6_cleanup(void)
++{
++	unregister_pernet_subsys(&igmp6_net_ops);
+ }
+diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
+index cd8a5bd..ad1cc5b 100644
+--- a/net/ipv6/mip6.c
++++ b/net/ipv6/mip6.c
+@@ -44,9 +44,9 @@ static inline void *mip6_padn(__u8 *data, __u8 padlen)
+ 	if (!data)
+ 		return NULL;
+ 	if (padlen == 1) {
+-		data[0] = MIP6_OPT_PAD_1;
++		data[0] = IPV6_TLV_PAD0;
+ 	} else if (padlen > 1) {
+-		data[0] = MIP6_OPT_PAD_N;
++		data[0] = IPV6_TLV_PADN;
+ 		data[1] = padlen - 2;
+ 		if (padlen > 2)
+ 			memset(data+2, 0, data[1]);
+@@ -304,13 +304,13 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
+ static int mip6_destopt_init_state(struct xfrm_state *x)
+ {
+ 	if (x->id.spi) {
+-		printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
++		printk(KERN_INFO "%s: spi is not 0: %u\n", __func__,
+ 		       x->id.spi);
+ 		return -EINVAL;
+ 	}
+ 	if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
+ 		printk(KERN_INFO "%s: state's mode is not %u: %u\n",
+-		       __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
++		       __func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -439,13 +439,13 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
+ static int mip6_rthdr_init_state(struct xfrm_state *x)
+ {
+ 	if (x->id.spi) {
+-		printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
++		printk(KERN_INFO "%s: spi is not 0: %u\n", __func__,
+ 		       x->id.spi);
+ 		return -EINVAL;
+ 	}
+ 	if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
+ 		printk(KERN_INFO "%s: state's mode is not %u: %u\n",
+-		       __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
++		       __func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -480,15 +480,15 @@ static int __init mip6_init(void)
+ 	printk(KERN_INFO "Mobile IPv6\n");
+ 
+ 	if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) {
+-		printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __FUNCTION__);
++		printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __func__);
+ 		goto mip6_destopt_xfrm_fail;
+ 	}
+ 	if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) {
+-		printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
++		printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __func__);
+ 		goto mip6_rthdr_xfrm_fail;
+ 	}
+ 	if (rawv6_mh_filter_register(mip6_mh_filter) < 0) {
+-		printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__);
++		printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __func__);
+ 		goto mip6_rawv6_mh_fail;
+ 	}
+ 
+@@ -506,11 +506,11 @@ static int __init mip6_init(void)
+ static void __exit mip6_fini(void)
+ {
+ 	if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
+-		printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__);
++		printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __func__);
+ 	if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
+-		printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
++		printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __func__);
+ 	if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
+-		printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
++		printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __func__);
+ }
+ 
+ module_init(mip6_init);
+diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
+index 452a2ac..2c74885 100644
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -84,13 +84,12 @@
+ 
+ #include <net/flow.h>
+ #include <net/ip6_checksum.h>
++#include <net/inet_common.h>
+ #include <linux/proc_fs.h>
+ 
+ #include <linux/netfilter.h>
+ #include <linux/netfilter_ipv6.h>
+ 
+-static struct socket *ndisc_socket;
+-
+ static u32 ndisc_hash(const void *pkey, const struct net_device *dev);
+ static int ndisc_constructor(struct neighbour *neigh);
+ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
+@@ -270,7 +269,7 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
+ 			if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
+ 				ND_PRINTK2(KERN_WARNING
+ 					   "%s(): duplicated ND6 option found: type=%d\n",
+-					   __FUNCTION__,
++					   __func__,
+ 					   nd_opt->nd_opt_type);
+ 			} else {
+ 				ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
+@@ -301,7 +300,7 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
+ 				 */
+ 				ND_PRINTK2(KERN_NOTICE
+ 					   "%s(): ignored unsupported option; type=%d, len=%d\n",
+-					   __FUNCTION__,
++					   __func__,
+ 					   nd_opt->nd_opt_type, nd_opt->nd_opt_len);
+ 			}
+ 		}
+@@ -441,30 +440,17 @@ static void pndisc_destructor(struct pneigh_entry *n)
+ /*
+  *	Send a Neighbour Advertisement
+  */
+-
+-static inline void ndisc_flow_init(struct flowi *fl, u8 type,
+-			    struct in6_addr *saddr, struct in6_addr *daddr,
+-			    int oif)
+-{
+-	memset(fl, 0, sizeof(*fl));
+-	ipv6_addr_copy(&fl->fl6_src, saddr);
+-	ipv6_addr_copy(&fl->fl6_dst, daddr);
+-	fl->proto	 	= IPPROTO_ICMPV6;
+-	fl->fl_icmp_type	= type;
+-	fl->fl_icmp_code	= 0;
+-	fl->oif			= oif;
+-	security_sk_classify_flow(ndisc_socket->sk, fl);
+-}
+-
+ static void __ndisc_send(struct net_device *dev,
+ 			 struct neighbour *neigh,
+-			 struct in6_addr *daddr, struct in6_addr *saddr,
+-			 struct icmp6hdr *icmp6h, struct in6_addr *target,
++			 const struct in6_addr *daddr,
++			 const struct in6_addr *saddr,
++			 struct icmp6hdr *icmp6h, const struct in6_addr *target,
+ 			 int llinfo)
+ {
+ 	struct flowi fl;
+ 	struct dst_entry *dst;
+-	struct sock *sk = ndisc_socket->sk;
++	struct net *net = dev_net(dev);
++	struct sock *sk = net->ipv6.ndisc_sk;
+ 	struct sk_buff *skb;
+ 	struct icmp6hdr *hdr;
+ 	struct inet6_dev *idev;
+@@ -474,10 +460,9 @@ static void __ndisc_send(struct net_device *dev,
+ 
+ 	type = icmp6h->icmp6_type;
+ 
+-	ndisc_flow_init(&fl, type, saddr, daddr,
+-			dev->ifindex);
++	icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex);
+ 
+-	dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
++	dst = icmp6_dst_alloc(dev, neigh, daddr);
+ 	if (!dst)
+ 		return;
+ 
+@@ -499,7 +484,7 @@ static void __ndisc_send(struct net_device *dev,
+ 	if (!skb) {
+ 		ND_PRINTK0(KERN_ERR
+ 			   "ICMPv6 ND: %s() failed to allocate an skb.\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		dst_release(dst);
+ 		return;
+ 	}
+@@ -545,25 +530,28 @@ static void __ndisc_send(struct net_device *dev,
+ }
+ 
+ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
+-		   struct in6_addr *daddr, struct in6_addr *solicited_addr,
+-		   int router, int solicited, int override, int inc_opt)
++			  const struct in6_addr *daddr,
++			  const struct in6_addr *solicited_addr,
++			  int router, int solicited, int override, int inc_opt)
+ {
+ 	struct in6_addr tmpaddr;
+ 	struct inet6_ifaddr *ifp;
+-	struct in6_addr *src_addr;
++	const struct in6_addr *src_addr;
+ 	struct icmp6hdr icmp6h = {
+ 		.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
+ 	};
+ 
+ 	/* for anycast or proxy, solicited_addr != src_addr */
+-	ifp = ipv6_get_ifaddr(&init_net, solicited_addr, dev, 1);
++	ifp = ipv6_get_ifaddr(dev_net(dev), solicited_addr, dev, 1);
+ 	if (ifp) {
+ 		src_addr = solicited_addr;
+ 		if (ifp->flags & IFA_F_OPTIMISTIC)
+ 			override = 0;
+ 		in6_ifa_put(ifp);
+ 	} else {
+-		if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
++		if (ipv6_dev_get_saddr(dev, daddr,
++				       inet6_sk(dev_net(dev)->ipv6.ndisc_sk)->srcprefs,
++				       &tmpaddr))
+ 			return;
+ 		src_addr = &tmpaddr;
+ 	}
+@@ -578,8 +566,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
+ }
+ 
+ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
+-		   struct in6_addr *solicit,
+-		   struct in6_addr *daddr, struct in6_addr *saddr)
++		   const struct in6_addr *solicit,
++		   const struct in6_addr *daddr, const struct in6_addr *saddr)
+ {
+ 	struct in6_addr addr_buf;
+ 	struct icmp6hdr icmp6h = {
+@@ -598,8 +586,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
+ 		     !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0);
+ }
+ 
+-void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
+-		   struct in6_addr *daddr)
++void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
++		   const struct in6_addr *daddr)
+ {
+ 	struct icmp6hdr icmp6h = {
+ 		.icmp6_type = NDISC_ROUTER_SOLICITATION,
+@@ -616,7 +604,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
+ 	 * suppress the inclusion of the sllao.
+ 	 */
+ 	if (send_sllao) {
+-		struct inet6_ifaddr *ifp = ipv6_get_ifaddr(&init_net, saddr,
++		struct inet6_ifaddr *ifp = ipv6_get_ifaddr(dev_net(dev), saddr,
+ 							   dev, 1);
+ 		if (ifp) {
+ 			if (ifp->flags & IFA_F_OPTIMISTIC)  {
+@@ -654,7 +642,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
+ 	struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
+ 	int probes = atomic_read(&neigh->probes);
+ 
+-	if (skb && ipv6_chk_addr(&init_net, &ipv6_hdr(skb)->saddr, dev, 1))
++	if (skb && ipv6_chk_addr(dev_net(dev), &ipv6_hdr(skb)->saddr, dev, 1))
+ 		saddr = &ipv6_hdr(skb)->saddr;
+ 
+ 	if ((probes -= neigh->parms->ucast_probes) < 0) {
+@@ -662,7 +650,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
+ 			ND_PRINTK1(KERN_DEBUG
+ 				   "%s(): trying to ucast probe in NUD_INVALID: "
+ 				   NIP6_FMT "\n",
+-				   __FUNCTION__,
++				   __func__,
+ 				   NIP6(*target));
+ 		}
+ 		ndisc_send_ns(dev, neigh, target, target, saddr);
+@@ -676,18 +664,19 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
+ 	}
+ }
+ 
+-static struct pneigh_entry *pndisc_check_router(struct net_device *dev,
+-		struct in6_addr *addr, int *is_router)
++static int pndisc_is_router(const void *pkey,
++			    struct net_device *dev)
+ {
+ 	struct pneigh_entry *n;
++	int ret = -1;
+ 
+ 	read_lock_bh(&nd_tbl.lock);
+-	n = __pneigh_lookup(&nd_tbl, &init_net, addr, dev);
+-	if (n != NULL)
+-		*is_router = (n->flags & NTF_ROUTER);
++	n = __pneigh_lookup(&nd_tbl, dev_net(dev), pkey, dev);
++	if (n)
++		ret = !!(n->flags & NTF_ROUTER);
+ 	read_unlock_bh(&nd_tbl.lock);
+ 
+-	return n;
++	return ret;
+ }
+ 
+ static void ndisc_recv_ns(struct sk_buff *skb)
+@@ -703,10 +692,9 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ 	struct inet6_ifaddr *ifp;
+ 	struct inet6_dev *idev = NULL;
+ 	struct neighbour *neigh;
+-	struct pneigh_entry *pneigh = NULL;
+ 	int dad = ipv6_addr_any(saddr);
+ 	int inc;
+-	int is_router = 0;
++	int is_router = -1;
+ 
+ 	if (ipv6_addr_is_multicast(&msg->target)) {
+ 		ND_PRINTK2(KERN_WARNING
+@@ -756,7 +744,8 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ 
+ 	inc = ipv6_addr_is_multicast(daddr);
+ 
+-	if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1)) != NULL) {
++	ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
++	if (ifp) {
+ 
+ 		if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
+ 			if (dad) {
+@@ -801,11 +790,10 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ 			return;
+ 		}
+ 
+-		if (ipv6_chk_acast_addr(dev, &msg->target) ||
++		if (ipv6_chk_acast_addr(dev_net(dev), dev, &msg->target) ||
+ 		    (idev->cnf.forwarding &&
+ 		     (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
+-		     (pneigh = pndisc_check_router(dev, &msg->target,
+-						  &is_router)) != NULL)) {
++		     (is_router = pndisc_is_router(&msg->target, dev)) >= 0)) {
+ 			if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
+ 			    skb->pkt_type != PACKET_HOST &&
+ 			    inc != 0 &&
+@@ -826,13 +814,11 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ 			goto out;
+ 	}
+ 
+-	is_router = !!(pneigh ? is_router : idev->cnf.forwarding);
++	if (is_router < 0)
++		is_router = !!idev->cnf.forwarding;
+ 
+ 	if (dad) {
+-		struct in6_addr maddr;
+-
+-		ipv6_addr_all_nodes(&maddr);
+-		ndisc_send_na(dev, NULL, &maddr, &msg->target,
++		ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &msg->target,
+ 			      is_router, 0, (ifp != NULL), 1);
+ 		goto out;
+ 	}
+@@ -914,7 +900,8 @@ static void ndisc_recv_na(struct sk_buff *skb)
+ 			return;
+ 		}
+ 	}
+-	if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1))) {
++	ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
++	if (ifp) {
+ 		if (ifp->flags & IFA_F_TENTATIVE) {
+ 			addrconf_dad_failure(ifp);
+ 			return;
+@@ -945,7 +932,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
+ 		 */
+ 		if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
+ 		    ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
+-		    pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) {
++		    pneigh_lookup(&nd_tbl, dev_net(dev), &msg->target, dev, 0)) {
+ 			/* XXX: idev->cnf.prixy_ndp */
+ 			goto out;
+ 		}
+@@ -1035,6 +1022,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
+ 	struct sk_buff *skb;
+ 	struct nlmsghdr *nlh;
+ 	struct nduseroptmsg *ndmsg;
++	struct net *net = dev_net(ra->dev);
+ 	int err;
+ 	int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg)
+ 				    + (opt->nd_opt_len << 3));
+@@ -1064,7 +1052,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
+ 		&ipv6_hdr(ra)->saddr);
+ 	nlmsg_end(skb, nlh);
+ 
+-	err = rtnl_notify(skb, &init_net, 0, RTNLGRP_ND_USEROPT, NULL,
++	err = rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL,
+ 			  GFP_ATOMIC);
+ 	if (err < 0)
+ 		goto errout;
+@@ -1075,7 +1063,7 @@ nla_put_failure:
+ 	nlmsg_free(skb);
+ 	err = -EMSGSIZE;
+ errout:
+-	rtnl_set_sk_err(&init_net, RTNLGRP_ND_USEROPT, err);
++	rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err);
+ }
+ 
+ static void ndisc_router_discovery(struct sk_buff *skb)
+@@ -1104,6 +1092,14 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ 		return;
+ 	}
+ 
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++	if (skb->ndisc_nodetype == NDISC_NODETYPE_HOST) {
++		ND_PRINTK2(KERN_WARNING
++			   "ICMPv6 RA: from host or unauthorized router\n");
++		return;
++	}
++#endif
++
+ 	/*
+ 	 *	set the RA_RECV flag in the interface
+ 	 */
+@@ -1127,6 +1123,12 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ 		return;
+ 	}
+ 
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++	/* skip link-specific parameters from interior routers */
++	if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
++		goto skip_linkparms;
++#endif
++
+ 	if (in6_dev->if_flags & IF_RS_SENT) {
+ 		/*
+ 		 *	flag that an RA was received after an RS was sent
+@@ -1178,7 +1180,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ 		if (rt == NULL) {
+ 			ND_PRINTK0(KERN_ERR
+ 				   "ICMPv6 RA: %s() failed to add default route.\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			in6_dev_put(in6_dev);
+ 			return;
+ 		}
+@@ -1187,7 +1189,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ 		if (neigh == NULL) {
+ 			ND_PRINTK0(KERN_ERR
+ 				   "ICMPv6 RA: %s() got default router without neighbour.\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			dst_release(&rt->u.dst);
+ 			in6_dev_put(in6_dev);
+ 			return;
+@@ -1241,6 +1243,10 @@ skip_defrtr:
+ 		}
+ 	}
+ 
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++skip_linkparms:
++#endif
++
+ 	/*
+ 	 *	Process options.
+ 	 */
+@@ -1272,7 +1278,13 @@ skip_defrtr:
+ 		for (p = ndopts.nd_opts_ri;
+ 		     p;
+ 		     p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) {
+-			if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
++			struct route_info *ri = (struct route_info *)p;
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++			if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT &&
++			    ri->prefix_len == 0)
++				continue;
++#endif
++			if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
+ 				continue;
+ 			rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
+ 				      &ipv6_hdr(skb)->saddr);
+@@ -1280,6 +1292,12 @@ skip_defrtr:
+ 	}
+ #endif
+ 
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++	/* skip link-specific ndopts from interior routers */
++	if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
++		goto out;
++#endif
++
+ 	if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) {
+ 		struct nd_opt_hdr *p;
+ 		for (p = ndopts.nd_opts_pi;
+@@ -1343,6 +1361,16 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
+ 	int optlen;
+ 	u8 *lladdr = NULL;
+ 
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++	switch (skb->ndisc_nodetype) {
++	case NDISC_NODETYPE_HOST:
++	case NDISC_NODETYPE_NODEFAULT:
++		ND_PRINTK2(KERN_WARNING
++			   "ICMPv6 Redirect: from host or unauthorized router\n");
++		return;
++	}
++#endif
++
+ 	if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
+ 		ND_PRINTK2(KERN_WARNING
+ 			   "ICMPv6 Redirect: source address is not link-local.\n");
+@@ -1418,15 +1446,16 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
+ }
+ 
+ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
+-			 struct in6_addr *target)
++			 const struct in6_addr *target)
+ {
+-	struct sock *sk = ndisc_socket->sk;
++	struct net_device *dev = skb->dev;
++	struct net *net = dev_net(dev);
++	struct sock *sk = net->ipv6.ndisc_sk;
+ 	int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
+ 	struct sk_buff *buff;
+ 	struct icmp6hdr *icmph;
+ 	struct in6_addr saddr_buf;
+ 	struct in6_addr *addrp;
+-	struct net_device *dev;
+ 	struct rt6_info *rt;
+ 	struct dst_entry *dst;
+ 	struct inet6_dev *idev;
+@@ -1436,8 +1465,6 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
+ 	int err;
+ 	u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
+ 
+-	dev = skb->dev;
+-
+ 	if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) {
+ 		ND_PRINTK2(KERN_WARNING
+ 			   "ICMPv6 Redirect: no link-local address on %s\n",
+@@ -1452,10 +1479,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
+ 		return;
+ 	}
+ 
+-	ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &ipv6_hdr(skb)->saddr,
+-			dev->ifindex);
++	icmpv6_flow_init(sk, &fl, NDISC_REDIRECT,
++			 &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex);
+ 
+-	dst = ip6_route_output(NULL, &fl);
++	dst = ip6_route_output(net, NULL, &fl);
+ 	if (dst == NULL)
+ 		return;
+ 
+@@ -1499,12 +1526,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
+ 	if (buff == NULL) {
+ 		ND_PRINTK0(KERN_ERR
+ 			   "ICMPv6 Redirect: %s() failed to allocate an skb.\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		dst_release(dst);
+ 		return;
+ 	}
+ 
+-
+ 	skb_reserve(buff, LL_RESERVED_SPACE(dev));
+ 	ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr,
+ 		   IPPROTO_ICMPV6, len);
+@@ -1625,18 +1651,16 @@ int ndisc_rcv(struct sk_buff *skb)
+ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
+ {
+ 	struct net_device *dev = ptr;
+-
+-	if (dev->nd_net != &init_net)
+-		return NOTIFY_DONE;
++	struct net *net = dev_net(dev);
+ 
+ 	switch (event) {
+ 	case NETDEV_CHANGEADDR:
+ 		neigh_changeaddr(&nd_tbl, dev);
+-		fib6_run_gc(~0UL);
++		fib6_run_gc(~0UL, net);
+ 		break;
+ 	case NETDEV_DOWN:
+ 		neigh_ifdown(&nd_tbl, dev);
+-		fib6_run_gc(~0UL);
++		fib6_run_gc(~0UL, net);
+ 		break;
+ 	default:
+ 		break;
+@@ -1745,44 +1769,74 @@ static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
+ 
+ #endif
+ 
+-int __init ndisc_init(struct net_proto_family *ops)
++static int ndisc_net_init(struct net *net)
+ {
+ 	struct ipv6_pinfo *np;
+ 	struct sock *sk;
+ 	int err;
+ 
+-	err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
++	err = inet_ctl_sock_create(&sk, PF_INET6,
++				   SOCK_RAW, IPPROTO_ICMPV6, net);
+ 	if (err < 0) {
+ 		ND_PRINTK0(KERN_ERR
+ 			   "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
+ 			   err);
+-		ndisc_socket = NULL; /* For safety. */
+ 		return err;
+ 	}
+ 
+-	sk = ndisc_socket->sk;
++	net->ipv6.ndisc_sk = sk;
++
+ 	np = inet6_sk(sk);
+-	sk->sk_allocation = GFP_ATOMIC;
+ 	np->hop_limit = 255;
+ 	/* Do not loopback ndisc messages */
+ 	np->mc_loop = 0;
+-	sk->sk_prot->unhash(sk);
+ 
++	return 0;
++}
++
++static void ndisc_net_exit(struct net *net)
++{
++	inet_ctl_sock_destroy(net->ipv6.ndisc_sk);
++}
++
++static struct pernet_operations ndisc_net_ops = {
++	.init = ndisc_net_init,
++	.exit = ndisc_net_exit,
++};
++
++int __init ndisc_init(void)
++{
++	int err;
++
++	err = register_pernet_subsys(&ndisc_net_ops);
++	if (err)
++		return err;
+ 	/*
+ 	 * Initialize the neighbour table
+ 	 */
+-
+ 	neigh_table_init(&nd_tbl);
+ 
+ #ifdef CONFIG_SYSCTL
+-	neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH,
+-			      "ipv6",
+-			      &ndisc_ifinfo_sysctl_change,
+-			      &ndisc_ifinfo_sysctl_strategy);
++	err = neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6,
++				    NET_IPV6_NEIGH, "ipv6",
++				    &ndisc_ifinfo_sysctl_change,
++				    &ndisc_ifinfo_sysctl_strategy);
++	if (err)
++		goto out_unregister_pernet;
+ #endif
++	err = register_netdevice_notifier(&ndisc_netdev_notifier);
++	if (err)
++		goto out_unregister_sysctl;
++out:
++	return err;
+ 
+-	register_netdevice_notifier(&ndisc_netdev_notifier);
+-	return 0;
++out_unregister_sysctl:
++#ifdef CONFIG_SYSCTL
++	neigh_sysctl_unregister(&nd_tbl.parms);
++out_unregister_pernet:
++#endif
++	unregister_pernet_subsys(&ndisc_net_ops);
++	goto out;
+ }
+ 
+ void ndisc_cleanup(void)
+@@ -1792,6 +1846,5 @@ void ndisc_cleanup(void)
+ 	neigh_sysctl_unregister(&nd_tbl.parms);
+ #endif
+ 	neigh_table_clear(&nd_tbl);
+-	sock_release(ndisc_socket);
+-	ndisc_socket = NULL; /* For safety. */
++	unregister_pernet_subsys(&ndisc_net_ops);
+ }
+diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
+index 2e06724..8c6c5e7 100644
+--- a/net/ipv6/netfilter.c
++++ b/net/ipv6/netfilter.c
+@@ -23,7 +23,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
+ 		    .saddr = iph->saddr, } },
+ 	};
+ 
+-	dst = ip6_route_output(skb->sk, &fl);
++	dst = ip6_route_output(&init_net, skb->sk, &fl);
+ 
+ #ifdef CONFIG_XFRM
+ 	if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+@@ -86,7 +86,7 @@ static int nf_ip6_reroute(struct sk_buff *skb,
+ 
+ static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl)
+ {
+-	*dst = ip6_route_output(NULL, fl);
++	*dst = ip6_route_output(&init_net, NULL, fl);
+ 	return (*dst)->error;
+ }
+ 
+@@ -121,16 +121,44 @@ __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+ 	}
+ 	return csum;
+ }
+-
+ EXPORT_SYMBOL(nf_ip6_checksum);
+ 
++static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,
++				       unsigned int dataoff, unsigned int len,
++				       u_int8_t protocol)
++{
++	struct ipv6hdr *ip6h = ipv6_hdr(skb);
++	__wsum hsum;
++	__sum16 csum = 0;
++
++	switch (skb->ip_summed) {
++	case CHECKSUM_COMPLETE:
++		if (len == skb->len - dataoff)
++			return nf_ip6_checksum(skb, hook, dataoff, protocol);
++		/* fall through */
++	case CHECKSUM_NONE:
++		hsum = skb_checksum(skb, 0, dataoff, 0);
++		skb->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr,
++							 &ip6h->daddr,
++							 skb->len - dataoff,
++							 protocol,
++							 csum_sub(0, hsum)));
++		skb->ip_summed = CHECKSUM_NONE;
++		csum = __skb_checksum_complete_head(skb, dataoff + len);
++		if (!csum)
++			skb->ip_summed = CHECKSUM_UNNECESSARY;
++	}
++	return csum;
++};
++
+ static const struct nf_afinfo nf_ip6_afinfo = {
+-	.family		= AF_INET6,
+-	.checksum	= nf_ip6_checksum,
+-	.route		= nf_ip6_route,
+-	.saveroute	= nf_ip6_saveroute,
+-	.reroute	= nf_ip6_reroute,
+-	.route_key_size	= sizeof(struct ip6_rt_info),
++	.family			= AF_INET6,
++	.checksum		= nf_ip6_checksum,
++	.checksum_partial	= nf_ip6_checksum_partial,
++	.route			= nf_ip6_route,
++	.saveroute		= nf_ip6_saveroute,
++	.reroute		= nf_ip6_reroute,
++	.route_key_size		= sizeof(struct ip6_rt_info),
+ };
+ 
+ int __init ipv6_netfilter_init(void)
+diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
+index 8d366f7..92a36c9 100644
+--- a/net/ipv6/netfilter/ip6_queue.c
++++ b/net/ipv6/netfilter/ip6_queue.c
+@@ -484,7 +484,7 @@ ipq_rcv_dev_event(struct notifier_block *this,
+ {
+ 	struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	/* Drop any packets associated with the downed device */
+diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
+index bf9bb6e..0b4557e 100644
+--- a/net/ipv6/netfilter/ip6_tables.c
++++ b/net/ipv6/netfilter/ip6_tables.c
+@@ -55,7 +55,7 @@ MODULE_DESCRIPTION("IPv6 packet filter");
+ do {								\
+ 	if (!(x))						\
+ 		printk("IP_NF_ASSERT: %s:%s:%u\n",		\
+-		       __FUNCTION__, __FILE__, __LINE__);	\
++		       __func__, __FILE__, __LINE__);	\
+ } while(0)
+ #else
+ #define IP_NF_ASSERT(x)
+@@ -325,7 +325,7 @@ static void trace_packet(struct sk_buff *skb,
+ 			 struct ip6t_entry *e)
+ {
+ 	void *table_base;
+-	struct ip6t_entry *root;
++	const struct ip6t_entry *root;
+ 	char *hookname, *chainname, *comment;
+ 	unsigned int rulenum = 0;
+ 
+@@ -952,7 +952,7 @@ static struct xt_counters *alloc_counters(struct xt_table *table)
+ {
+ 	unsigned int countersize;
+ 	struct xt_counters *counters;
+-	struct xt_table_info *private = table->private;
++	const struct xt_table_info *private = table->private;
+ 
+ 	/* We need atomic snapshot of counters: rest doesn't change
+ 	   (other than comefrom, which userspace doesn't care
+@@ -979,9 +979,9 @@ copy_entries_to_user(unsigned int total_size,
+ 	unsigned int off, num;
+ 	struct ip6t_entry *e;
+ 	struct xt_counters *counters;
+-	struct xt_table_info *private = table->private;
++	const struct xt_table_info *private = table->private;
+ 	int ret = 0;
+-	void *loc_cpu_entry;
++	const void *loc_cpu_entry;
+ 
+ 	counters = alloc_counters(table);
+ 	if (IS_ERR(counters))
+@@ -1001,8 +1001,8 @@ copy_entries_to_user(unsigned int total_size,
+ 	/* ... then go back and fix counters and names */
+ 	for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
+ 		unsigned int i;
+-		struct ip6t_entry_match *m;
+-		struct ip6t_entry_target *t;
++		const struct ip6t_entry_match *m;
++		const struct ip6t_entry_target *t;
+ 
+ 		e = (struct ip6t_entry *)(loc_cpu_entry + off);
+ 		if (copy_to_user(userptr + off
+@@ -1142,7 +1142,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
+ 				    "ip6table_%s", name);
+ 	if (t && !IS_ERR(t)) {
+ 		struct ip6t_getinfo info;
+-		struct xt_table_info *private = t->private;
++		const struct xt_table_info *private = t->private;
+ 
+ #ifdef CONFIG_COMPAT
+ 		if (compat) {
+@@ -1206,7 +1206,7 @@ get_entries(struct net *net, struct ip6t_get_entries __user *uptr, int *len)
+ 		else {
+ 			duprintf("get_entries: I've got %u not %u!\n",
+ 				 private->size, get.size);
+-			ret = -EINVAL;
++			ret = -EAGAIN;
+ 		}
+ 		module_put(t->me);
+ 		xt_table_unlock(t);
+@@ -1225,7 +1225,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
+ 	struct xt_table *t;
+ 	struct xt_table_info *oldinfo;
+ 	struct xt_counters *counters;
+-	void *loc_cpu_old_entry;
++	const void *loc_cpu_old_entry;
+ 
+ 	ret = 0;
+ 	counters = vmalloc_node(num_counters * sizeof(struct xt_counters),
+@@ -1369,9 +1369,9 @@ do_add_counters(struct net *net, void __user *user, unsigned int len,
+ 	int size;
+ 	void *ptmp;
+ 	struct xt_table *t;
+-	struct xt_table_info *private;
++	const struct xt_table_info *private;
+ 	int ret = 0;
+-	void *loc_cpu_entry;
++	const void *loc_cpu_entry;
+ #ifdef CONFIG_COMPAT
+ 	struct compat_xt_counters_info compat_tmp;
+ 
+@@ -1879,11 +1879,11 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
+ 
+ 	switch (cmd) {
+ 	case IP6T_SO_SET_REPLACE:
+-		ret = compat_do_replace(sk->sk_net, user, len);
++		ret = compat_do_replace(sock_net(sk), user, len);
+ 		break;
+ 
+ 	case IP6T_SO_SET_ADD_COUNTERS:
+-		ret = do_add_counters(sk->sk_net, user, len, 1);
++		ret = do_add_counters(sock_net(sk), user, len, 1);
+ 		break;
+ 
+ 	default:
+@@ -1905,11 +1905,11 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
+ 			    void __user *userptr)
+ {
+ 	struct xt_counters *counters;
+-	struct xt_table_info *private = table->private;
++	const struct xt_table_info *private = table->private;
+ 	void __user *pos;
+ 	unsigned int size;
+ 	int ret = 0;
+-	void *loc_cpu_entry;
++	const void *loc_cpu_entry;
+ 	unsigned int i = 0;
+ 
+ 	counters = alloc_counters(table);
+@@ -1956,7 +1956,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
+ 	xt_compat_lock(AF_INET6);
+ 	t = xt_find_table_lock(net, AF_INET6, get.name);
+ 	if (t && !IS_ERR(t)) {
+-		struct xt_table_info *private = t->private;
++		const struct xt_table_info *private = t->private;
+ 		struct xt_table_info info;
+ 		duprintf("t->private->number = %u\n", private->number);
+ 		ret = compat_table_info(private, &info);
+@@ -1966,7 +1966,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
+ 		} else if (!ret) {
+ 			duprintf("compat_get_entries: I've got %u not %u!\n",
+ 				 private->size, get.size);
+-			ret = -EINVAL;
++			ret = -EAGAIN;
+ 		}
+ 		xt_compat_flush_offsets(AF_INET6);
+ 		module_put(t->me);
+@@ -1990,10 +1990,10 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+ 
+ 	switch (cmd) {
+ 	case IP6T_SO_GET_INFO:
+-		ret = get_info(sk->sk_net, user, len, 1);
++		ret = get_info(sock_net(sk), user, len, 1);
+ 		break;
+ 	case IP6T_SO_GET_ENTRIES:
+-		ret = compat_get_entries(sk->sk_net, user, len);
++		ret = compat_get_entries(sock_net(sk), user, len);
+ 		break;
+ 	default:
+ 		ret = do_ip6t_get_ctl(sk, cmd, user, len);
+@@ -2012,11 +2012,11 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
+ 
+ 	switch (cmd) {
+ 	case IP6T_SO_SET_REPLACE:
+-		ret = do_replace(sk->sk_net, user, len);
++		ret = do_replace(sock_net(sk), user, len);
+ 		break;
+ 
+ 	case IP6T_SO_SET_ADD_COUNTERS:
+-		ret = do_add_counters(sk->sk_net, user, len, 0);
++		ret = do_add_counters(sock_net(sk), user, len, 0);
+ 		break;
+ 
+ 	default:
+@@ -2037,11 +2037,11 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+ 
+ 	switch (cmd) {
+ 	case IP6T_SO_GET_INFO:
+-		ret = get_info(sk->sk_net, user, len, 0);
++		ret = get_info(sock_net(sk), user, len, 0);
+ 		break;
+ 
+ 	case IP6T_SO_GET_ENTRIES:
+-		ret = get_entries(sk->sk_net, user, len);
++		ret = get_entries(sock_net(sk), user, len);
+ 		break;
+ 
+ 	case IP6T_SO_GET_REVISION_MATCH:
+@@ -2155,7 +2155,8 @@ icmp6_match(const struct sk_buff *skb,
+ 	   unsigned int protoff,
+ 	   bool *hotdrop)
+ {
+-	struct icmp6hdr _icmph, *ic;
++	const struct icmp6hdr *ic;
++	struct icmp6hdr _icmph;
+ 	const struct ip6t_icmp *icmpinfo = matchinfo;
+ 
+ 	/* Must not be a fragment. */
+diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
+index 86a6138..3a23169 100644
+--- a/net/ipv6/netfilter/ip6t_LOG.c
++++ b/net/ipv6/netfilter/ip6t_LOG.c
+@@ -363,11 +363,15 @@ static void dump_packet(const struct nf_loginfo *info,
+ 	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",
++			printk("UID=%u GID=%u ",
+ 				skb->sk->sk_socket->file->f_uid,
+ 				skb->sk->sk_socket->file->f_gid);
+ 		read_unlock_bh(&skb->sk->sk_callback_lock);
+ 	}
++
++	/* Max length: 16 "MARK=0xFFFFFFFF " */
++	if (!recurse && skb->mark)
++		printk("MARK=0x%x ", skb->mark);
+ }
+ 
+ static struct nf_loginfo default_loginfo = {
+diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
+index b23baa6..44c8d65 100644
+--- a/net/ipv6/netfilter/ip6t_REJECT.c
++++ b/net/ipv6/netfilter/ip6t_REJECT.c
+@@ -41,7 +41,8 @@ static void send_reset(struct sk_buff *oldskb)
+ 	struct tcphdr otcph, *tcph;
+ 	unsigned int otcplen, hh_len;
+ 	int tcphoff, needs_ack;
+-	struct ipv6hdr *oip6h = ipv6_hdr(oldskb), *ip6h;
++	const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
++	struct ipv6hdr *ip6h;
+ 	struct dst_entry *dst = NULL;
+ 	u8 proto;
+ 	struct flowi fl;
+@@ -93,7 +94,7 @@ static void send_reset(struct sk_buff *oldskb)
+ 	fl.fl_ip_sport = otcph.dest;
+ 	fl.fl_ip_dport = otcph.source;
+ 	security_skb_classify_flow(oldskb, &fl);
+-	dst = ip6_route_output(NULL, &fl);
++	dst = ip6_route_output(&init_net, NULL, &fl);
+ 	if (dst == NULL)
+ 		return;
+ 	if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0))
+@@ -177,7 +178,7 @@ reject_tg6(struct sk_buff *skb, const struct net_device *in,
+ {
+ 	const struct ip6t_reject_info *reject = targinfo;
+ 
+-	pr_debug("%s: medium point\n", __FUNCTION__);
++	pr_debug("%s: medium point\n", __func__);
+ 	/* WARNING: This code causes reentry within ip6tables.
+ 	   This means that the ip6tables jump stack is now crap.  We
+ 	   must return an absolute verdict. --RR */
+diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
+index 3a94017..317a896 100644
+--- a/net/ipv6/netfilter/ip6t_ipv6header.c
++++ b/net/ipv6/netfilter/ip6t_ipv6header.c
+@@ -49,7 +49,8 @@ ipv6header_mt6(const struct sk_buff *skb, const struct net_device *in,
+ 	temp = 0;
+ 
+ 	while (ip6t_ext_hdr(nexthdr)) {
+-		struct ipv6_opt_hdr _hdr, *hp;
++		const struct ipv6_opt_hdr *hp;
++		struct ipv6_opt_hdr _hdr;
+ 		int hdrlen;
+ 
+ 		/* Is there enough space for the next ext header? */
+diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
+index 12a9efe..81aaf7a 100644
+--- a/net/ipv6/netfilter/ip6t_rt.c
++++ b/net/ipv6/netfilter/ip6t_rt.c
+@@ -110,7 +110,8 @@ rt_mt6(const struct sk_buff *skb, const struct net_device *in,
+ 		!!(rtinfo->invflags & IP6T_RT_INV_TYP)));
+ 
+ 	if (ret && (rtinfo->flags & IP6T_RT_RES)) {
+-		u_int32_t *rp, _reserved;
++		const u_int32_t *rp;
++		u_int32_t _reserved;
+ 		rp = skb_header_pointer(skb,
+ 					ptr + offsetof(struct rt0_hdr,
+ 						       reserved),
+diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
+index 2d9cd09..f979e48 100644
+--- a/net/ipv6/netfilter/ip6table_filter.c
++++ b/net/ipv6/netfilter/ip6table_filter.c
+@@ -54,7 +54,7 @@ static struct
+ static struct xt_table packet_filter = {
+ 	.name		= "filter",
+ 	.valid_hooks	= FILTER_VALID_HOOKS,
+-	.lock		= RW_LOCK_UNLOCKED,
++	.lock		= __RW_LOCK_UNLOCKED(packet_filter.lock),
+ 	.me		= THIS_MODULE,
+ 	.af		= AF_INET6,
+ };
+diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
+index 035343a..27a5e8b 100644
+--- a/net/ipv6/netfilter/ip6table_mangle.c
++++ b/net/ipv6/netfilter/ip6table_mangle.c
+@@ -60,7 +60,7 @@ static struct
+ static struct xt_table packet_mangler = {
+ 	.name		= "mangle",
+ 	.valid_hooks	= MANGLE_VALID_HOOKS,
+-	.lock		= RW_LOCK_UNLOCKED,
++	.lock		= __RW_LOCK_UNLOCKED(packet_mangler.lock),
+ 	.me		= THIS_MODULE,
+ 	.af		= AF_INET6,
+ };
+diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
+index 5cd8420..92b9107 100644
+--- a/net/ipv6/netfilter/ip6table_raw.c
++++ b/net/ipv6/netfilter/ip6table_raw.c
+@@ -38,7 +38,7 @@ static struct
+ static struct xt_table packet_raw = {
+ 	.name = "raw",
+ 	.valid_hooks = RAW_VALID_HOOKS,
+-	.lock = RW_LOCK_UNLOCKED,
++	.lock = __RW_LOCK_UNLOCKED(packet_raw.lock),
+ 	.me = THIS_MODULE,
+ 	.af = AF_INET6,
+ };
+diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+index 3717bdf..85050c0 100644
+--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
++++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+@@ -27,8 +27,8 @@
+ #include <net/netfilter/nf_conntrack_l3proto.h>
+ #include <net/netfilter/nf_conntrack_core.h>
+ 
+-static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
+-			     struct nf_conntrack_tuple *tuple)
++static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
++			      struct nf_conntrack_tuple *tuple)
+ {
+ 	const u_int32_t *ap;
+ 	u_int32_t _addrs[8];
+@@ -36,21 +36,21 @@ static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
+ 	ap = skb_header_pointer(skb, nhoff + offsetof(struct ipv6hdr, saddr),
+ 				sizeof(_addrs), _addrs);
+ 	if (ap == NULL)
+-		return 0;
++		return false;
+ 
+ 	memcpy(tuple->src.u3.ip6, ap, sizeof(tuple->src.u3.ip6));
+ 	memcpy(tuple->dst.u3.ip6, ap + 4, sizeof(tuple->dst.u3.ip6));
+ 
+-	return 1;
++	return true;
+ }
+ 
+-static int ipv6_invert_tuple(struct nf_conntrack_tuple *tuple,
+-			     const struct nf_conntrack_tuple *orig)
++static bool ipv6_invert_tuple(struct nf_conntrack_tuple *tuple,
++			      const struct nf_conntrack_tuple *orig)
+ {
+ 	memcpy(tuple->src.u3.ip6, orig->dst.u3.ip6, sizeof(tuple->src.u3.ip6));
+ 	memcpy(tuple->dst.u3.ip6, orig->src.u3.ip6, sizeof(tuple->dst.u3.ip6));
+ 
+-	return 1;
++	return true;
+ }
+ 
+ static int ipv6_print_tuple(struct seq_file *s,
+diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+index 0897d0f..ee713b0 100644
+--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
++++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+@@ -28,21 +28,21 @@
+ 
+ static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
+ 
+-static int icmpv6_pkt_to_tuple(const struct sk_buff *skb,
+-			       unsigned int dataoff,
+-			       struct nf_conntrack_tuple *tuple)
++static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb,
++				unsigned int dataoff,
++				struct nf_conntrack_tuple *tuple)
+ {
+ 	const struct icmp6hdr *hp;
+ 	struct icmp6hdr _hdr;
+ 
+ 	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ 	if (hp == NULL)
+-		return 0;
++		return false;
+ 	tuple->dst.u.icmp.type = hp->icmp6_type;
+ 	tuple->src.u.icmp.id = hp->icmp6_identifier;
+ 	tuple->dst.u.icmp.code = hp->icmp6_code;
+ 
+-	return 1;
++	return true;
+ }
+ 
+ /* Add 1; spaces filled with 0. */
+@@ -53,17 +53,17 @@ static const u_int8_t invmap[] = {
+ 	[ICMPV6_NI_REPLY - 128]		= ICMPV6_NI_REPLY +1
+ };
+ 
+-static int icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple,
+-			       const struct nf_conntrack_tuple *orig)
++static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple,
++				const struct nf_conntrack_tuple *orig)
+ {
+ 	int type = orig->dst.u.icmp.type - 128;
+ 	if (type < 0 || type >= sizeof(invmap) || !invmap[type])
+-		return 0;
++		return false;
+ 
+ 	tuple->src.u.icmp.id   = orig->src.u.icmp.id;
+ 	tuple->dst.u.icmp.type = invmap[type] - 1;
+ 	tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
+-	return 1;
++	return true;
+ }
+ 
+ /* Print out the per-protocol part of the tuple. */
+@@ -102,9 +102,8 @@ static int icmpv6_packet(struct nf_conn *ct,
+ }
+ 
+ /* Called when a new connection for this protocol found. */
+-static int icmpv6_new(struct nf_conn *ct,
+-		      const struct sk_buff *skb,
+-		      unsigned int dataoff)
++static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb,
++		       unsigned int dataoff)
+ {
+ 	static const u_int8_t valid_new[] = {
+ 		[ICMPV6_ECHO_REQUEST - 128] = 1,
+@@ -116,11 +115,11 @@ static int icmpv6_new(struct nf_conn *ct,
+ 		/* Can't create a new ICMPv6 `conn' with this. */
+ 		pr_debug("icmpv6: can't create new conn with type %u\n",
+ 			 type + 128);
+-		NF_CT_DUMP_TUPLE(&ct->tuplehash[0].tuple);
+-		return 0;
++		nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple);
++		return false;
+ 	}
+ 	atomic_set(&ct->proto.icmp.count, 0);
+-	return 1;
++	return true;
+ }
+ 
+ static int
+diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
+index 24c0d03..2dccad4 100644
+--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
+@@ -103,8 +103,8 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = {
+ };
+ #endif
+ 
+-static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
+-			       struct in6_addr *daddr)
++static unsigned int ip6qhashfn(__be32 id, const struct in6_addr *saddr,
++			       const struct in6_addr *daddr)
+ {
+ 	u32 a, b, c;
+ 
+@@ -132,7 +132,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
+ 
+ static unsigned int nf_hashfn(struct inet_frag_queue *q)
+ {
+-	struct nf_ct_frag6_queue *nq;
++	const struct nf_ct_frag6_queue *nq;
+ 
+ 	nq = container_of(q, struct nf_ct_frag6_queue, q);
+ 	return ip6qhashfn(nq->id, &nq->saddr, &nq->daddr);
+@@ -185,7 +185,7 @@ static void nf_ct_frag6_expire(unsigned long data)
+ 
+ 	spin_lock(&fq->q.lock);
+ 
+-	if (fq->q.last_in & COMPLETE)
++	if (fq->q.last_in & INET_FRAG_COMPLETE)
+ 		goto out;
+ 
+ 	fq_kill(fq);
+@@ -222,12 +222,12 @@ oom:
+ 
+ 
+ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
+-			     struct frag_hdr *fhdr, int nhoff)
++			     const struct frag_hdr *fhdr, int nhoff)
+ {
+ 	struct sk_buff *prev, *next;
+ 	int offset, end;
+ 
+-	if (fq->q.last_in & COMPLETE) {
++	if (fq->q.last_in & INET_FRAG_COMPLETE) {
+ 		pr_debug("Allready completed\n");
+ 		goto err;
+ 	}
+@@ -254,11 +254,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
+ 		 * or have different end, the segment is corrupted.
+ 		 */
+ 		if (end < fq->q.len ||
+-		    ((fq->q.last_in & LAST_IN) && end != fq->q.len)) {
++		    ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) {
+ 			pr_debug("already received last fragment\n");
+ 			goto err;
+ 		}
+-		fq->q.last_in |= LAST_IN;
++		fq->q.last_in |= INET_FRAG_LAST_IN;
+ 		fq->q.len = end;
+ 	} else {
+ 		/* Check if the fragment is rounded to 8 bytes.
+@@ -273,7 +273,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
+ 		}
+ 		if (end > fq->q.len) {
+ 			/* Some bits beyond end -> corruption. */
+-			if (fq->q.last_in & LAST_IN) {
++			if (fq->q.last_in & INET_FRAG_LAST_IN) {
+ 				pr_debug("last packet already reached.\n");
+ 				goto err;
+ 			}
+@@ -385,7 +385,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
+ 	 */
+ 	if (offset == 0) {
+ 		fq->nhoffset = nhoff;
+-		fq->q.last_in |= FIRST_IN;
++		fq->q.last_in |= INET_FRAG_FIRST_IN;
+ 	}
+ 	write_lock(&nf_frags.lock);
+ 	list_move_tail(&fq->q.lru_list, &nf_init_frags.lru_list);
+@@ -647,7 +647,8 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
+ 		goto ret_orig;
+ 	}
+ 
+-	if (fq->q.last_in == (FIRST_IN|LAST_IN) && fq->q.meat == fq->q.len) {
++	if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
++	    fq->q.meat == fq->q.len) {
+ 		ret_skb = nf_ct_frag6_reasm(fq, dev);
+ 		if (ret_skb == NULL)
+ 			pr_debug("Can't reassemble fragmented packets\n");
+diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
+index 199ef37..ca8b82f 100644
+--- a/net/ipv6/proc.c
++++ b/net/ipv6/proc.c
+@@ -35,16 +35,18 @@ static struct proc_dir_entry *proc_net_devsnmp6;
+ 
+ static int sockstat6_seq_show(struct seq_file *seq, void *v)
+ {
++	struct net *net = seq->private;
++
+ 	seq_printf(seq, "TCP6: inuse %d\n",
+-		       sock_prot_inuse_get(&tcpv6_prot));
++		       sock_prot_inuse_get(net, &tcpv6_prot));
+ 	seq_printf(seq, "UDP6: inuse %d\n",
+-		       sock_prot_inuse_get(&udpv6_prot));
++		       sock_prot_inuse_get(net, &udpv6_prot));
+ 	seq_printf(seq, "UDPLITE6: inuse %d\n",
+-			sock_prot_inuse_get(&udplitev6_prot));
++			sock_prot_inuse_get(net, &udplitev6_prot));
+ 	seq_printf(seq, "RAW6: inuse %d\n",
+-		       sock_prot_inuse_get(&rawv6_prot));
++		       sock_prot_inuse_get(net, &rawv6_prot));
+ 	seq_printf(seq, "FRAG6: inuse %d memory %d\n",
+-		       ip6_frag_nqueues(&init_net), ip6_frag_mem(&init_net));
++		       ip6_frag_nqueues(net), ip6_frag_mem(net));
+ 	return 0;
+ }
+ 
+@@ -183,7 +185,32 @@ static int snmp6_seq_show(struct seq_file *seq, void *v)
+ 
+ static int sockstat6_seq_open(struct inode *inode, struct file *file)
+ {
+-	return single_open(file, sockstat6_seq_show, NULL);
++	int err;
++	struct net *net;
++
++	err = -ENXIO;
++	net = get_proc_net(inode);
++	if (net == NULL)
++		goto err_net;
++
++	err = single_open(file, sockstat6_seq_show, net);
++	if (err < 0)
++		goto err_open;
++
++	return 0;
++
++err_open:
++	put_net(net);
++err_net:
++	return err;
++}
++
++static int sockstat6_seq_release(struct inode *inode, struct file *file)
++{
++	struct net *net = ((struct seq_file *)file->private_data)->private;
++
++	put_net(net);
++	return single_release(inode, file);
+ }
+ 
+ static const struct file_operations sockstat6_seq_fops = {
+@@ -191,7 +218,7 @@ static const struct file_operations sockstat6_seq_fops = {
+ 	.open	 = sockstat6_seq_open,
+ 	.read	 = seq_read,
+ 	.llseek	 = seq_lseek,
+-	.release = single_release,
++	.release = sockstat6_seq_release,
+ };
+ 
+ static int snmp6_seq_open(struct inode *inode, struct file *file)
+@@ -214,6 +241,9 @@ int snmp6_register_dev(struct inet6_dev *idev)
+ 	if (!idev || !idev->dev)
+ 		return -EINVAL;
+ 
++	if (dev_net(idev->dev) != &init_net)
++		return 0;
++
+ 	if (!proc_net_devsnmp6)
+ 		return -ENOENT;
+ 
+@@ -240,27 +270,45 @@ int snmp6_unregister_dev(struct inet6_dev *idev)
+ 	return 0;
+ }
+ 
++static int ipv6_proc_init_net(struct net *net)
++{
++	if (!proc_net_fops_create(net, "sockstat6", S_IRUGO,
++			&sockstat6_seq_fops))
++		return -ENOMEM;
++	return 0;
++}
++
++static void ipv6_proc_exit_net(struct net *net)
++{
++	proc_net_remove(net, "sockstat6");
++}
++
++static struct pernet_operations ipv6_proc_ops = {
++	.init = ipv6_proc_init_net,
++	.exit = ipv6_proc_exit_net,
++};
++
+ int __init ipv6_misc_proc_init(void)
+ {
+ 	int rc = 0;
+ 
++	if (register_pernet_subsys(&ipv6_proc_ops))
++		goto proc_net_fail;
++
+ 	if (!proc_net_fops_create(&init_net, "snmp6", S_IRUGO, &snmp6_seq_fops))
+ 		goto proc_snmp6_fail;
+ 
+ 	proc_net_devsnmp6 = proc_mkdir("dev_snmp6", init_net.proc_net);
+ 	if (!proc_net_devsnmp6)
+ 		goto proc_dev_snmp6_fail;
+-
+-	if (!proc_net_fops_create(&init_net, "sockstat6", S_IRUGO, &sockstat6_seq_fops))
+-		goto proc_sockstat6_fail;
+ out:
+ 	return rc;
+ 
+-proc_sockstat6_fail:
+-	proc_net_remove(&init_net, "dev_snmp6");
+ proc_dev_snmp6_fail:
+ 	proc_net_remove(&init_net, "snmp6");
+ proc_snmp6_fail:
++	unregister_pernet_subsys(&ipv6_proc_ops);
++proc_net_fail:
+ 	rc = -ENOMEM;
+ 	goto out;
+ }
+@@ -270,5 +318,6 @@ void ipv6_misc_proc_exit(void)
+ 	proc_net_remove(&init_net, "sockstat6");
+ 	proc_net_remove(&init_net, "dev_snmp6");
+ 	proc_net_remove(&init_net, "snmp6");
++	unregister_pernet_subsys(&ipv6_proc_ops);
+ }
+ 
+diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
+index 0a6fbc1..396f0ea 100644
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -53,6 +53,7 @@
+ #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+ #include <net/mip6.h>
+ #endif
++#include <linux/mroute6.h>
+ 
+ #include <net/raw.h>
+ #include <net/rawv6.h>
+@@ -62,20 +63,9 @@
+ #include <linux/seq_file.h>
+ 
+ static struct raw_hashinfo raw_v6_hashinfo = {
+-	.lock = __RW_LOCK_UNLOCKED(),
++	.lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock),
+ };
+ 
+-static void raw_v6_hash(struct sock *sk)
+-{
+-	raw_hash_sk(sk, &raw_v6_hashinfo);
+-}
+-
+-static void raw_v6_unhash(struct sock *sk)
+-{
+-	raw_unhash_sk(sk, &raw_v6_hashinfo);
+-}
+-
+-
+ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
+ 		unsigned short num, struct in6_addr *loc_addr,
+ 		struct in6_addr *rmt_addr, int dif)
+@@ -87,7 +77,7 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
+ 		if (inet_sk(sk)->num == num) {
+ 			struct ipv6_pinfo *np = inet6_sk(sk);
+ 
+-			if (sk->sk_net != net)
++			if (!net_eq(sock_net(sk), net))
+ 				continue;
+ 
+ 			if (!ipv6_addr_any(&np->daddr) &&
+@@ -179,15 +169,10 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
+ 	read_lock(&raw_v6_hashinfo.lock);
+ 	sk = sk_head(&raw_v6_hashinfo.ht[hash]);
+ 
+-	/*
+-	 *	The first socket found will be delivered after
+-	 *	delivery to transport protocols.
+-	 */
+-
+ 	if (sk == NULL)
+ 		goto out;
+ 
+-	net = skb->dev->nd_net;
++	net = dev_net(skb->dev);
+ 	sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
+ 
+ 	while (sk) {
+@@ -291,7 +276,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+ 			if (!sk->sk_bound_dev_if)
+ 				goto out;
+ 
+-			dev = dev_get_by_index(sk->sk_net, sk->sk_bound_dev_if);
++			dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if);
+ 			if (!dev) {
+ 				err = -ENODEV;
+ 				goto out;
+@@ -304,7 +289,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+ 		v4addr = LOOPBACK4_IPV6;
+ 		if (!(addr_type & IPV6_ADDR_MULTICAST))	{
+ 			err = -EADDRNOTAVAIL;
+-			if (!ipv6_chk_addr(sk->sk_net, &addr->sin6_addr,
++			if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr,
+ 					   dev, 0)) {
+ 				if (dev)
+ 					dev_put(dev);
+@@ -372,11 +357,11 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
+ 	read_lock(&raw_v6_hashinfo.lock);
+ 	sk = sk_head(&raw_v6_hashinfo.ht[hash]);
+ 	if (sk != NULL) {
+-		struct ipv6hdr *hdr = (struct ipv6hdr *) skb->data;
+-
+-		saddr = &hdr->saddr;
+-		daddr = &hdr->daddr;
+-		net = skb->dev->nd_net;
++		/* Note: ipv6_hdr(skb) != skb->data */
++		struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data;
++		saddr = &ip6h->saddr;
++		daddr = &ip6h->daddr;
++		net = dev_net(skb->dev);
+ 
+ 		while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr,
+ 						IP6CB(skb)->iif))) {
+@@ -822,15 +807,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
+ 		fl.fl6_flowlabel = np->flow_label;
+ 	}
+ 
+-	if (ipv6_addr_any(daddr)) {
+-		/*
+-		 * unspecified destination address
+-		 * treated as error... is this correct ?
+-		 */
+-		fl6_sock_release(flowlabel);
+-		return(-EINVAL);
+-	}
+-
+ 	if (fl.oif == 0)
+ 		fl.oif = sk->sk_bound_dev_if;
+ 
+@@ -863,7 +839,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
+ 	if (err)
+ 		goto out;
+ 
+-	ipv6_addr_copy(&fl.fl6_dst, daddr);
++	if (!ipv6_addr_any(daddr))
++		ipv6_addr_copy(&fl.fl6_dst, daddr);
++	else
++		fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+ 	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
+ 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+ 
+@@ -898,9 +877,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
+ 		else
+ 			hlimit = np->hop_limit;
+ 		if (hlimit < 0)
+-			hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+-		if (hlimit < 0)
+-			hlimit = ipv6_get_hoplimit(dst->dev);
++			hlimit = ip6_dst_hoplimit(dst);
+ 	}
+ 
+ 	if (tclass < 0) {
+@@ -994,6 +971,19 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
+ 
+ 	switch (optname) {
+ 		case IPV6_CHECKSUM:
++			if (inet_sk(sk)->num == IPPROTO_ICMPV6 &&
++			    level == IPPROTO_IPV6) {
++				/*
++				 * RFC3542 tells that IPV6_CHECKSUM socket
++				 * option in the IPPROTO_IPV6 level is not
++				 * allowed on ICMPv6 sockets.
++				 * If you want to set it, use IPPROTO_RAW
++				 * level IPV6_CHECKSUM socket option
++				 * (Linux extension).
++				 */
++				return -EINVAL;
++			}
++
+ 			/* You may get strange result with a positive odd offset;
+ 			   RFC2292bis agrees with me. */
+ 			if (val > 0 && (val&1))
+@@ -1069,6 +1059,11 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
+ 
+ 	switch (optname) {
+ 	case IPV6_CHECKSUM:
++		/*
++		 * We allow getsockopt() for IPPROTO_IPV6-level
++		 * IPV6_CHECKSUM socket option on ICMPv6 sockets
++		 * since RFC3542 is silent about it.
++		 */
+ 		if (rp->checksum == 0)
+ 			val = -1;
+ 		else
+@@ -1155,7 +1150,11 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ 		}
+ 
+ 		default:
++#ifdef CONFIG_IPV6_MROUTE
++			return ip6mr_ioctl(sk, cmd, (void __user *)arg);
++#else
+ 			return -ENOIOCTLCMD;
++#endif
+ 	}
+ }
+ 
+@@ -1163,7 +1162,7 @@ static void rawv6_close(struct sock *sk, long timeout)
+ {
+ 	if (inet_sk(sk)->num == IPPROTO_RAW)
+ 		ip6_ra_control(sk, -1, NULL);
+-
++	ip6mr_sk_done(sk);
+ 	sk_common_release(sk);
+ }
+ 
+@@ -1186,8 +1185,6 @@ static int rawv6_init_sk(struct sock *sk)
+ 	return(0);
+ }
+ 
+-DEFINE_PROTO_INUSE(rawv6)
+-
+ struct proto rawv6_prot = {
+ 	.name		   = "RAWv6",
+ 	.owner		   = THIS_MODULE,
+@@ -1203,14 +1200,14 @@ struct proto rawv6_prot = {
+ 	.recvmsg	   = rawv6_recvmsg,
+ 	.bind		   = rawv6_bind,
+ 	.backlog_rcv	   = rawv6_rcv_skb,
+-	.hash		   = raw_v6_hash,
+-	.unhash		   = raw_v6_unhash,
++	.hash		   = raw_hash_sk,
++	.unhash		   = raw_unhash_sk,
+ 	.obj_size	   = sizeof(struct raw6_sock),
++	.h.raw_hash	   = &raw_v6_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_rawv6_setsockopt,
+ 	.compat_getsockopt = compat_rawv6_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(rawv6)
+ };
+ 
+ #ifdef CONFIG_PROC_FS
+diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
+index f936d04..7b247e3 100644
+--- a/net/ipv6/reassembly.c
++++ b/net/ipv6/reassembly.c
+@@ -202,7 +202,7 @@ static void ip6_frag_expire(unsigned long data)
+ 
+ 	spin_lock(&fq->q.lock);
+ 
+-	if (fq->q.last_in & COMPLETE)
++	if (fq->q.last_in & INET_FRAG_COMPLETE)
+ 		goto out;
+ 
+ 	fq_kill(fq);
+@@ -217,7 +217,7 @@ static void ip6_frag_expire(unsigned long data)
+ 	rcu_read_unlock();
+ 
+ 	/* Don't send error if the first segment did not arrive. */
+-	if (!(fq->q.last_in&FIRST_IN) || !fq->q.fragments)
++	if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments)
+ 		goto out;
+ 
+ 	/*
+@@ -265,7 +265,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+ 	struct net_device *dev;
+ 	int offset, end;
+ 
+-	if (fq->q.last_in & COMPLETE)
++	if (fq->q.last_in & INET_FRAG_COMPLETE)
+ 		goto err;
+ 
+ 	offset = ntohs(fhdr->frag_off) & ~0x7;
+@@ -294,9 +294,9 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+ 		 * or have different end, the segment is corrupted.
+ 		 */
+ 		if (end < fq->q.len ||
+-		    ((fq->q.last_in & LAST_IN) && end != fq->q.len))
++		    ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len))
+ 			goto err;
+-		fq->q.last_in |= LAST_IN;
++		fq->q.last_in |= INET_FRAG_LAST_IN;
+ 		fq->q.len = end;
+ 	} else {
+ 		/* Check if the fragment is rounded to 8 bytes.
+@@ -314,7 +314,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+ 		}
+ 		if (end > fq->q.len) {
+ 			/* Some bits beyond end -> corruption. */
+-			if (fq->q.last_in & LAST_IN)
++			if (fq->q.last_in & INET_FRAG_LAST_IN)
+ 				goto err;
+ 			fq->q.len = end;
+ 		}
+@@ -417,10 +417,11 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+ 	 */
+ 	if (offset == 0) {
+ 		fq->nhoffset = nhoff;
+-		fq->q.last_in |= FIRST_IN;
++		fq->q.last_in |= INET_FRAG_FIRST_IN;
+ 	}
+ 
+-	if (fq->q.last_in == (FIRST_IN | LAST_IN) && fq->q.meat == fq->q.len)
++	if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
++	    fq->q.meat == fq->q.len)
+ 		return ip6_frag_reasm(fq, prev, dev);
+ 
+ 	write_lock(&ip6_frags.lock);
+@@ -600,7 +601,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
+ 		return 1;
+ 	}
+ 
+-	net = skb->dev->nd_net;
++	net = dev_net(skb->dev);
+ 	if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh)
+ 		ip6_evictor(net, ip6_dst_idev(skb->dst));
+ 
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index e8b241c..a493ad9 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -36,10 +36,12 @@
+ #include <linux/route.h>
+ #include <linux/netdevice.h>
+ #include <linux/in6.h>
++#include <linux/mroute6.h>
+ #include <linux/init.h>
+ #include <linux/if_arp.h>
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
++#include <linux/nsproxy.h>
+ #include <net/net_namespace.h>
+ #include <net/snmp.h>
+ #include <net/ipv6.h>
+@@ -87,14 +89,16 @@ static void		ip6_link_failure(struct sk_buff *skb);
+ static void		ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
+ 
+ #ifdef CONFIG_IPV6_ROUTE_INFO
+-static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen,
++static struct rt6_info *rt6_add_route_info(struct net *net,
++					   struct in6_addr *prefix, int prefixlen,
+ 					   struct in6_addr *gwaddr, int ifindex,
+ 					   unsigned pref);
+-static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen,
++static struct rt6_info *rt6_get_route_info(struct net *net,
++					   struct in6_addr *prefix, int prefixlen,
+ 					   struct in6_addr *gwaddr, int ifindex);
+ #endif
+ 
+-static struct dst_ops ip6_dst_ops = {
++static struct dst_ops ip6_dst_ops_template = {
+ 	.family			=	AF_INET6,
+ 	.protocol		=	__constant_htons(ETH_P_IPV6),
+ 	.gc			=	ip6_dst_gc,
+@@ -124,7 +128,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
+ 	.entries		=	ATOMIC_INIT(0),
+ };
+ 
+-struct rt6_info ip6_null_entry = {
++static struct rt6_info ip6_null_entry_template = {
+ 	.u = {
+ 		.dst = {
+ 			.__refcnt	= ATOMIC_INIT(1),
+@@ -134,8 +138,6 @@ struct rt6_info ip6_null_entry = {
+ 			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
+ 			.input		= ip6_pkt_discard,
+ 			.output		= ip6_pkt_discard_out,
+-			.ops		= &ip6_dst_ops,
+-			.path		= (struct dst_entry*)&ip6_null_entry,
+ 		}
+ 	},
+ 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
+@@ -148,7 +150,7 @@ struct rt6_info ip6_null_entry = {
+ static int ip6_pkt_prohibit(struct sk_buff *skb);
+ static int ip6_pkt_prohibit_out(struct sk_buff *skb);
+ 
+-struct rt6_info ip6_prohibit_entry = {
++static struct rt6_info ip6_prohibit_entry_template = {
+ 	.u = {
+ 		.dst = {
+ 			.__refcnt	= ATOMIC_INIT(1),
+@@ -158,8 +160,6 @@ struct rt6_info ip6_prohibit_entry = {
+ 			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
+ 			.input		= ip6_pkt_prohibit,
+ 			.output		= ip6_pkt_prohibit_out,
+-			.ops		= &ip6_dst_ops,
+-			.path		= (struct dst_entry*)&ip6_prohibit_entry,
+ 		}
+ 	},
+ 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
+@@ -167,7 +167,7 @@ struct rt6_info ip6_prohibit_entry = {
+ 	.rt6i_ref	= ATOMIC_INIT(1),
+ };
+ 
+-struct rt6_info ip6_blk_hole_entry = {
++static struct rt6_info ip6_blk_hole_entry_template = {
+ 	.u = {
+ 		.dst = {
+ 			.__refcnt	= ATOMIC_INIT(1),
+@@ -177,8 +177,6 @@ struct rt6_info ip6_blk_hole_entry = {
+ 			.metrics	= { [RTAX_HOPLIMIT - 1] = 255, },
+ 			.input		= dst_discard,
+ 			.output		= dst_discard,
+-			.ops		= &ip6_dst_ops,
+-			.path		= (struct dst_entry*)&ip6_blk_hole_entry,
+ 		}
+ 	},
+ 	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),
+@@ -189,9 +187,9 @@ struct rt6_info ip6_blk_hole_entry = {
+ #endif
+ 
+ /* allocate dst with ip6_dst_ops */
+-static __inline__ struct rt6_info *ip6_dst_alloc(void)
++static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops)
+ {
+-	return (struct rt6_info *)dst_alloc(&ip6_dst_ops);
++	return (struct rt6_info *)dst_alloc(ops);
+ }
+ 
+ static void ip6_dst_destroy(struct dst_entry *dst)
+@@ -211,7 +209,7 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ 	struct rt6_info *rt = (struct rt6_info *)dst;
+ 	struct inet6_dev *idev = rt->rt6i_idev;
+ 	struct net_device *loopback_dev =
+-		dev->nd_net->loopback_dev;
++		dev_net(dev)->loopback_dev;
+ 
+ 	if (dev != loopback_dev && idev != NULL && idev->dev == dev) {
+ 		struct inet6_dev *loopback_idev =
+@@ -239,7 +237,8 @@ static inline int rt6_need_strict(struct in6_addr *daddr)
+  *	Route lookup. Any table->tb6_lock is implied.
+  */
+ 
+-static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
++static inline struct rt6_info *rt6_device_match(struct net *net,
++						    struct rt6_info *rt,
+ 						    int oif,
+ 						    int strict)
+ {
+@@ -268,7 +267,7 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
+ 			return local;
+ 
+ 		if (strict)
+-			return &ip6_null_entry;
++			return net->ipv6.ip6_null_entry;
+ 	}
+ 	return rt;
+ }
+@@ -409,9 +408,10 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
+ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
+ {
+ 	struct rt6_info *match, *rt0;
++	struct net *net;
+ 
+ 	RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n",
+-		  __FUNCTION__, fn->leaf, oif);
++		  __func__, fn->leaf, oif);
+ 
+ 	rt0 = fn->rr_ptr;
+ 	if (!rt0)
+@@ -432,15 +432,17 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
+ 	}
+ 
+ 	RT6_TRACE("%s() => %p\n",
+-		  __FUNCTION__, match);
++		  __func__, match);
+ 
+-	return (match ? match : &ip6_null_entry);
++	net = dev_net(rt0->rt6i_dev);
++	return (match ? match : net->ipv6.ip6_null_entry);
+ }
+ 
+ #ifdef CONFIG_IPV6_ROUTE_INFO
+ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
+ 		  struct in6_addr *gwaddr)
+ {
++	struct net *net = dev_net(dev);
+ 	struct route_info *rinfo = (struct route_info *) opt;
+ 	struct in6_addr prefix_buf, *prefix;
+ 	unsigned int pref;
+@@ -488,7 +490,8 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
+ 		prefix = &prefix_buf;
+ 	}
+ 
+-	rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex);
++	rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr,
++				dev->ifindex);
+ 
+ 	if (rt && !lifetime) {
+ 		ip6_del_rt(rt);
+@@ -496,7 +499,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
+ 	}
+ 
+ 	if (!rt && lifetime)
+-		rt = rt6_add_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
++		rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
+ 					pref);
+ 	else if (rt)
+ 		rt->rt6i_flags = RTF_ROUTEINFO |
+@@ -515,9 +518,9 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
+ }
+ #endif
+ 
+-#define BACKTRACK(saddr) \
++#define BACKTRACK(__net, saddr)			\
+ do { \
+-	if (rt == &ip6_null_entry) { \
++	if (rt == __net->ipv6.ip6_null_entry) {	\
+ 		struct fib6_node *pn; \
+ 		while (1) { \
+ 			if (fn->fn_flags & RTN_TL_ROOT) \
+@@ -533,7 +536,8 @@ do { \
+ 	} \
+ } while(0)
+ 
+-static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table,
++static struct rt6_info *ip6_pol_route_lookup(struct net *net,
++					     struct fib6_table *table,
+ 					     struct flowi *fl, int flags)
+ {
+ 	struct fib6_node *fn;
+@@ -543,8 +547,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table,
+ 	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
+ restart:
+ 	rt = fn->leaf;
+-	rt = rt6_device_match(rt, fl->oif, flags);
+-	BACKTRACK(&fl->fl6_src);
++	rt = rt6_device_match(net, rt, fl->oif, flags);
++	BACKTRACK(net, &fl->fl6_src);
+ out:
+ 	dst_use(&rt->u.dst, jiffies);
+ 	read_unlock_bh(&table->tb6_lock);
+@@ -552,8 +556,8 @@ out:
+ 
+ }
+ 
+-struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
+-			    int oif, int strict)
++struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
++			    const struct in6_addr *saddr, int oif, int strict)
+ {
+ 	struct flowi fl = {
+ 		.oif = oif,
+@@ -571,7 +575,7 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
+ 		flags |= RT6_LOOKUP_F_HAS_SADDR;
+ 	}
+ 
+-	dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
++	dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_lookup);
+ 	if (dst->error == 0)
+ 		return (struct rt6_info *) dst;
+ 
+@@ -604,7 +608,7 @@ static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info)
+ int ip6_ins_rt(struct rt6_info *rt)
+ {
+ 	struct nl_info info = {
+-		.nl_net = &init_net,
++		.nl_net = dev_net(rt->rt6i_dev),
+ 	};
+ 	return __ip6_ins_rt(rt, &info);
+ }
+@@ -660,8 +664,8 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
+ 	return rt;
+ }
+ 
+-static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif,
+-					    struct flowi *fl, int flags)
++static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
++				      struct flowi *fl, int flags)
+ {
+ 	struct fib6_node *fn;
+ 	struct rt6_info *rt, *nrt;
+@@ -680,8 +684,9 @@ restart_2:
+ 
+ restart:
+ 	rt = rt6_select(fn, oif, strict | reachable);
+-	BACKTRACK(&fl->fl6_src);
+-	if (rt == &ip6_null_entry ||
++
++	BACKTRACK(net, &fl->fl6_src);
++	if (rt == net->ipv6.ip6_null_entry ||
+ 	    rt->rt6i_flags & RTF_CACHE)
+ 		goto out;
+ 
+@@ -699,7 +704,7 @@ restart:
+ 	}
+ 
+ 	dst_release(&rt->u.dst);
+-	rt = nrt ? : &ip6_null_entry;
++	rt = nrt ? : net->ipv6.ip6_null_entry;
+ 
+ 	dst_hold(&rt->u.dst);
+ 	if (nrt) {
+@@ -732,15 +737,16 @@ out2:
+ 	return rt;
+ }
+ 
+-static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
++static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
+ 					    struct flowi *fl, int flags)
+ {
+-	return ip6_pol_route(table, fl->iif, fl, flags);
++	return ip6_pol_route(net, table, fl->iif, fl, flags);
+ }
+ 
+ void ip6_route_input(struct sk_buff *skb)
+ {
+ 	struct ipv6hdr *iph = ipv6_hdr(skb);
++	struct net *net = dev_net(skb->dev);
+ 	int flags = RT6_LOOKUP_F_HAS_SADDR;
+ 	struct flowi fl = {
+ 		.iif = skb->dev->ifindex,
+@@ -758,16 +764,17 @@ void ip6_route_input(struct sk_buff *skb)
+ 	if (rt6_need_strict(&iph->daddr))
+ 		flags |= RT6_LOOKUP_F_IFACE;
+ 
+-	skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input);
++	skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input);
+ }
+ 
+-static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
++static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
+ 					     struct flowi *fl, int flags)
+ {
+-	return ip6_pol_route(table, fl->oif, fl, flags);
++	return ip6_pol_route(net, table, fl->oif, fl, flags);
+ }
+ 
+-struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
++struct dst_entry * ip6_route_output(struct net *net, struct sock *sk,
++				    struct flowi *fl)
+ {
+ 	int flags = 0;
+ 
+@@ -776,8 +783,17 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
+ 
+ 	if (!ipv6_addr_any(&fl->fl6_src))
+ 		flags |= RT6_LOOKUP_F_HAS_SADDR;
++	else if (sk) {
++		unsigned int prefs = inet6_sk(sk)->srcprefs;
++		if (prefs & IPV6_PREFER_SRC_TMP)
++			flags |= RT6_LOOKUP_F_SRCPREF_TMP;
++		if (prefs & IPV6_PREFER_SRC_PUBLIC)
++			flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC;
++		if (prefs & IPV6_PREFER_SRC_COA)
++			flags |= RT6_LOOKUP_F_SRCPREF_COA;
++	}
+ 
+-	return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
++	return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output);
+ }
+ 
+ EXPORT_SYMBOL(ip6_route_output);
+@@ -886,12 +902,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
+ 
+ static int ipv6_get_mtu(struct net_device *dev);
+ 
+-static inline unsigned int ipv6_advmss(unsigned int mtu)
++static inline unsigned int ipv6_advmss(struct net *net, unsigned int mtu)
+ {
+ 	mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
+ 
+-	if (mtu < init_net.ipv6.sysctl.ip6_rt_min_advmss)
+-		mtu = init_net.ipv6.sysctl.ip6_rt_min_advmss;
++	if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
++		mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
+ 
+ 	/*
+ 	 * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and
+@@ -904,21 +920,21 @@ static inline unsigned int ipv6_advmss(unsigned int mtu)
+ 	return mtu;
+ }
+ 
+-static struct dst_entry *ndisc_dst_gc_list;
+-static DEFINE_SPINLOCK(ndisc_lock);
++static struct dst_entry *icmp6_dst_gc_list;
++static DEFINE_SPINLOCK(icmp6_dst_lock);
+ 
+-struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
++struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
+ 				  struct neighbour *neigh,
+-				  struct in6_addr *addr,
+-				  int (*output)(struct sk_buff *))
++				  const struct in6_addr *addr)
+ {
+ 	struct rt6_info *rt;
+ 	struct inet6_dev *idev = in6_dev_get(dev);
++	struct net *net = dev_net(dev);
+ 
+ 	if (unlikely(idev == NULL))
+ 		return NULL;
+ 
+-	rt = ip6_dst_alloc();
++	rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
+ 	if (unlikely(rt == NULL)) {
+ 		in6_dev_put(idev);
+ 		goto out;
+@@ -936,8 +952,8 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
+ 	atomic_set(&rt->u.dst.__refcnt, 1);
+ 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
+ 	rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
+-	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
+-	rt->u.dst.output  = output;
++	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
++	rt->u.dst.output  = ip6_output;
+ 
+ #if 0	/* there's no chance to use these for ndisc */
+ 	rt->u.dst.flags   = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST
+@@ -947,18 +963,18 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
+ 	rt->rt6i_dst.plen = 128;
+ #endif
+ 
+-	spin_lock_bh(&ndisc_lock);
+-	rt->u.dst.next = ndisc_dst_gc_list;
+-	ndisc_dst_gc_list = &rt->u.dst;
+-	spin_unlock_bh(&ndisc_lock);
++	spin_lock_bh(&icmp6_dst_lock);
++	rt->u.dst.next = icmp6_dst_gc_list;
++	icmp6_dst_gc_list = &rt->u.dst;
++	spin_unlock_bh(&icmp6_dst_lock);
+ 
+-	fib6_force_start_gc();
++	fib6_force_start_gc(net);
+ 
+ out:
+ 	return &rt->u.dst;
+ }
+ 
+-int ndisc_dst_gc(int *more)
++int icmp6_dst_gc(int *more)
+ {
+ 	struct dst_entry *dst, *next, **pprev;
+ 	int freed;
+@@ -966,8 +982,8 @@ int ndisc_dst_gc(int *more)
+ 	next = NULL;
+ 	freed = 0;
+ 
+-	spin_lock_bh(&ndisc_lock);
+-	pprev = &ndisc_dst_gc_list;
++	spin_lock_bh(&icmp6_dst_lock);
++	pprev = &icmp6_dst_gc_list;
+ 
+ 	while ((dst = *pprev) != NULL) {
+ 		if (!atomic_read(&dst->__refcnt)) {
+@@ -980,30 +996,33 @@ int ndisc_dst_gc(int *more)
+ 		}
+ 	}
+ 
+-	spin_unlock_bh(&ndisc_lock);
++	spin_unlock_bh(&icmp6_dst_lock);
+ 
+ 	return freed;
+ }
+ 
+ static int ip6_dst_gc(struct dst_ops *ops)
+ {
+-	static unsigned expire = 30*HZ;
+-	static unsigned long last_gc;
+ 	unsigned long now = jiffies;
+-
+-	if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) &&
+-	    atomic_read(&ip6_dst_ops.entries) <= init_net.ipv6.sysctl.ip6_rt_max_size)
++	struct net *net = ops->dst_net;
++	int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
++	int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;
++	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;
++
++	if (time_after(rt_last_gc + rt_min_interval, now) &&
++	    atomic_read(&ops->entries) <= rt_max_size)
+ 		goto out;
+ 
+-	expire++;
+-	fib6_run_gc(expire);
+-	last_gc = now;
+-	if (atomic_read(&ip6_dst_ops.entries) < ip6_dst_ops.gc_thresh)
+-		expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1;
+-
++	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)
++		net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
+ out:
+-	expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity;
+-	return (atomic_read(&ip6_dst_ops.entries) > init_net.ipv6.sysctl.ip6_rt_max_size);
++	net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
++	return (atomic_read(&ops->entries) > rt_max_size);
+ }
+ 
+ /* Clean host part of a prefix. Not necessary in radix tree,
+@@ -1025,15 +1044,17 @@ static int ipv6_get_mtu(struct net_device *dev)
+ 	return mtu;
+ }
+ 
+-int ipv6_get_hoplimit(struct net_device *dev)
++int ip6_dst_hoplimit(struct dst_entry *dst)
+ {
+-	int hoplimit = ipv6_devconf.hop_limit;
+-	struct inet6_dev *idev;
+-
+-	idev = in6_dev_get(dev);
+-	if (idev) {
+-		hoplimit = idev->cnf.hop_limit;
+-		in6_dev_put(idev);
++	int hoplimit = dst_metric(dst, RTAX_HOPLIMIT);
++	if (hoplimit < 0) {
++		struct net_device *dev = dst->dev;
++		struct inet6_dev *idev = in6_dev_get(dev);
++		if (idev) {
++			hoplimit = idev->cnf.hop_limit;
++			in6_dev_put(idev);
++		} else
++			hoplimit = ipv6_devconf.hop_limit;
+ 	}
+ 	return hoplimit;
+ }
+@@ -1045,6 +1066,7 @@ int ipv6_get_hoplimit(struct net_device *dev)
+ int ip6_route_add(struct fib6_config *cfg)
+ {
+ 	int err;
++	struct net *net = cfg->fc_nlinfo.nl_net;
+ 	struct rt6_info *rt = NULL;
+ 	struct net_device *dev = NULL;
+ 	struct inet6_dev *idev = NULL;
+@@ -1059,7 +1081,7 @@ int ip6_route_add(struct fib6_config *cfg)
+ #endif
+ 	if (cfg->fc_ifindex) {
+ 		err = -ENODEV;
+-		dev = dev_get_by_index(&init_net, cfg->fc_ifindex);
++		dev = dev_get_by_index(net, cfg->fc_ifindex);
+ 		if (!dev)
+ 			goto out;
+ 		idev = in6_dev_get(dev);
+@@ -1070,13 +1092,13 @@ int ip6_route_add(struct fib6_config *cfg)
+ 	if (cfg->fc_metric == 0)
+ 		cfg->fc_metric = IP6_RT_PRIO_USER;
+ 
+-	table = fib6_new_table(cfg->fc_table);
++	table = fib6_new_table(net, cfg->fc_table);
+ 	if (table == NULL) {
+ 		err = -ENOBUFS;
+ 		goto out;
+ 	}
+ 
+-	rt = ip6_dst_alloc();
++	rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
+ 
+ 	if (rt == NULL) {
+ 		err = -ENOMEM;
+@@ -1117,12 +1139,12 @@ int ip6_route_add(struct fib6_config *cfg)
+ 	if ((cfg->fc_flags & RTF_REJECT) ||
+ 	    (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
+ 		/* hold loopback dev/idev if we haven't done so. */
+-		if (dev != init_net.loopback_dev) {
++		if (dev != net->loopback_dev) {
+ 			if (dev) {
+ 				dev_put(dev);
+ 				in6_dev_put(idev);
+ 			}
+-			dev = init_net.loopback_dev;
++			dev = net->loopback_dev;
+ 			dev_hold(dev);
+ 			idev = in6_dev_get(dev);
+ 			if (!idev) {
+@@ -1159,7 +1181,7 @@ int ip6_route_add(struct fib6_config *cfg)
+ 			if (!(gwa_type&IPV6_ADDR_UNICAST))
+ 				goto out;
+ 
+-			grt = rt6_lookup(gw_addr, NULL, cfg->fc_ifindex, 1);
++			grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1);
+ 
+ 			err = -EHOSTUNREACH;
+ 			if (grt == NULL)
+@@ -1226,10 +1248,13 @@ install_route:
+ 	if (!rt->u.dst.metrics[RTAX_MTU-1])
+ 		rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
+ 	if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
+-		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
++		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
+ 	rt->u.dst.dev = dev;
+ 	rt->rt6i_idev = idev;
+ 	rt->rt6i_table = table;
++
++	cfg->fc_nlinfo.nl_net = dev_net(dev);
++
+ 	return __ip6_ins_rt(rt, &cfg->fc_nlinfo);
+ 
+ out:
+@@ -1246,8 +1271,9 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
+ {
+ 	int err;
+ 	struct fib6_table *table;
++	struct net *net = dev_net(rt->rt6i_dev);
+ 
+-	if (rt == &ip6_null_entry)
++	if (rt == net->ipv6.ip6_null_entry)
+ 		return -ENOENT;
+ 
+ 	table = rt->rt6i_table;
+@@ -1264,7 +1290,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
+ int ip6_del_rt(struct rt6_info *rt)
+ {
+ 	struct nl_info info = {
+-		.nl_net = &init_net,
++		.nl_net = dev_net(rt->rt6i_dev),
+ 	};
+ 	return __ip6_del_rt(rt, &info);
+ }
+@@ -1276,7 +1302,7 @@ static int ip6_route_del(struct fib6_config *cfg)
+ 	struct rt6_info *rt;
+ 	int err = -ESRCH;
+ 
+-	table = fib6_get_table(cfg->fc_table);
++	table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table);
+ 	if (table == NULL)
+ 		return err;
+ 
+@@ -1316,7 +1342,8 @@ struct ip6rd_flowi {
+ 	struct in6_addr gateway;
+ };
+ 
+-static struct rt6_info *__ip6_route_redirect(struct fib6_table *table,
++static struct rt6_info *__ip6_route_redirect(struct net *net,
++					     struct fib6_table *table,
+ 					     struct flowi *fl,
+ 					     int flags)
+ {
+@@ -1359,8 +1386,8 @@ restart:
+ 	}
+ 
+ 	if (!rt)
+-		rt = &ip6_null_entry;
+-	BACKTRACK(&fl->fl6_src);
++		rt = net->ipv6.ip6_null_entry;
++	BACKTRACK(net, &fl->fl6_src);
+ out:
+ 	dst_hold(&rt->u.dst);
+ 
+@@ -1375,6 +1402,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
+ 					   struct net_device *dev)
+ {
+ 	int flags = RT6_LOOKUP_F_HAS_SADDR;
++	struct net *net = dev_net(dev);
+ 	struct ip6rd_flowi rdfl = {
+ 		.fl = {
+ 			.oif = dev->ifindex,
+@@ -1391,7 +1419,8 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
+ 	if (rt6_need_strict(dest))
+ 		flags |= RT6_LOOKUP_F_IFACE;
+ 
+-	return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
++	return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl,
++						   flags, __ip6_route_redirect);
+ }
+ 
+ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
+@@ -1400,10 +1429,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
+ {
+ 	struct rt6_info *rt, *nrt = NULL;
+ 	struct netevent_redirect netevent;
++	struct net *net = dev_net(neigh->dev);
+ 
+ 	rt = ip6_route_redirect(dest, src, saddr, neigh->dev);
+ 
+-	if (rt == &ip6_null_entry) {
++	if (rt == net->ipv6.ip6_null_entry) {
+ 		if (net_ratelimit())
+ 			printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
+ 			       "for redirect target\n");
+@@ -1448,7 +1478,8 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
+ 	nrt->rt6i_nexthop = neigh_clone(neigh);
+ 	/* Reset pmtu, it may be better */
+ 	nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
+-	nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
++	nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev),
++							dst_mtu(&nrt->u.dst));
+ 
+ 	if (ip6_ins_rt(nrt))
+ 		goto out;
+@@ -1476,9 +1507,10 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
+ 			struct net_device *dev, u32 pmtu)
+ {
+ 	struct rt6_info *rt, *nrt;
++	struct net *net = dev_net(dev);
+ 	int allfrag = 0;
+ 
+-	rt = rt6_lookup(daddr, saddr, dev->ifindex, 0);
++	rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0);
+ 	if (rt == NULL)
+ 		return;
+ 
+@@ -1511,7 +1543,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
+ 		rt->u.dst.metrics[RTAX_MTU-1] = pmtu;
+ 		if (allfrag)
+ 			rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
+-		dst_set_expires(&rt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires);
++		dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
+ 		rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
+ 		goto out;
+ 	}
+@@ -1537,7 +1569,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
+ 		 * which is 10 mins. After 10 mins the decreased pmtu is expired
+ 		 * and detecting PMTU increase will be automatically happened.
+ 		 */
+-		dst_set_expires(&nrt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires);
++		dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
+ 		nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
+ 
+ 		ip6_ins_rt(nrt);
+@@ -1552,7 +1584,8 @@ out:
+ 
+ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
+ {
+-	struct rt6_info *rt = ip6_dst_alloc();
++	struct net *net = dev_net(ort->rt6i_dev);
++	struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
+ 
+ 	if (rt) {
+ 		rt->u.dst.input = ort->u.dst.input;
+@@ -1583,14 +1616,15 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
+ }
+ 
+ #ifdef CONFIG_IPV6_ROUTE_INFO
+-static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen,
++static struct rt6_info *rt6_get_route_info(struct net *net,
++					   struct in6_addr *prefix, int prefixlen,
+ 					   struct in6_addr *gwaddr, int ifindex)
+ {
+ 	struct fib6_node *fn;
+ 	struct rt6_info *rt = NULL;
+ 	struct fib6_table *table;
+ 
+-	table = fib6_get_table(RT6_TABLE_INFO);
++	table = fib6_get_table(net, RT6_TABLE_INFO);
+ 	if (table == NULL)
+ 		return NULL;
+ 
+@@ -1614,7 +1648,8 @@ out:
+ 	return rt;
+ }
+ 
+-static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen,
++static struct rt6_info *rt6_add_route_info(struct net *net,
++					   struct in6_addr *prefix, int prefixlen,
+ 					   struct in6_addr *gwaddr, int ifindex,
+ 					   unsigned pref)
+ {
+@@ -1625,6 +1660,9 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle
+ 		.fc_dst_len	= prefixlen,
+ 		.fc_flags	= RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
+ 				  RTF_UP | RTF_PREF(pref),
++		.fc_nlinfo.pid = 0,
++		.fc_nlinfo.nlh = NULL,
++		.fc_nlinfo.nl_net = net,
+ 	};
+ 
+ 	ipv6_addr_copy(&cfg.fc_dst, prefix);
+@@ -1636,7 +1674,7 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle
+ 
+ 	ip6_route_add(&cfg);
+ 
+-	return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex);
++	return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
+ }
+ #endif
+ 
+@@ -1645,7 +1683,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
+ 	struct rt6_info *rt;
+ 	struct fib6_table *table;
+ 
+-	table = fib6_get_table(RT6_TABLE_DFLT);
++	table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
+ 	if (table == NULL)
+ 		return NULL;
+ 
+@@ -1662,8 +1700,6 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
+ 	return rt;
+ }
+ 
+-EXPORT_SYMBOL(rt6_get_dflt_router);
+-
+ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
+ 				     struct net_device *dev,
+ 				     unsigned int pref)
+@@ -1674,6 +1710,9 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
+ 		.fc_ifindex	= dev->ifindex,
+ 		.fc_flags	= RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
+ 				  RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
++		.fc_nlinfo.pid = 0,
++		.fc_nlinfo.nlh = NULL,
++		.fc_nlinfo.nl_net = dev_net(dev),
+ 	};
+ 
+ 	ipv6_addr_copy(&cfg.fc_gateway, gwaddr);
+@@ -1683,13 +1722,13 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
+ 	return rt6_get_dflt_router(gwaddr, dev);
+ }
+ 
+-void rt6_purge_dflt_routers(void)
++void rt6_purge_dflt_routers(struct net *net)
+ {
+ 	struct rt6_info *rt;
+ 	struct fib6_table *table;
+ 
+ 	/* NOTE: Keep consistent with rt6_get_dflt_router */
+-	table = fib6_get_table(RT6_TABLE_DFLT);
++	table = fib6_get_table(net, RT6_TABLE_DFLT);
+ 	if (table == NULL)
+ 		return;
+ 
+@@ -1706,7 +1745,8 @@ restart:
+ 	read_unlock_bh(&table->tb6_lock);
+ }
+ 
+-static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg,
++static void rtmsg_to_fib6_config(struct net *net,
++				 struct in6_rtmsg *rtmsg,
+ 				 struct fib6_config *cfg)
+ {
+ 	memset(cfg, 0, sizeof(*cfg));
+@@ -1719,14 +1759,14 @@ static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg,
+ 	cfg->fc_src_len = rtmsg->rtmsg_src_len;
+ 	cfg->fc_flags = rtmsg->rtmsg_flags;
+ 
+-	cfg->fc_nlinfo.nl_net = &init_net;
++	cfg->fc_nlinfo.nl_net = net;
+ 
+ 	ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
+ 	ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
+ 	ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
+ }
+ 
+-int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
++int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
+ {
+ 	struct fib6_config cfg;
+ 	struct in6_rtmsg rtmsg;
+@@ -1742,7 +1782,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
+ 		if (err)
+ 			return -EFAULT;
+ 
+-		rtmsg_to_fib6_config(&rtmsg, &cfg);
++		rtmsg_to_fib6_config(net, &rtmsg, &cfg);
+ 
+ 		rtnl_lock();
+ 		switch (cmd) {
+@@ -1821,21 +1861,22 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+ 				    const struct in6_addr *addr,
+ 				    int anycast)
+ {
+-	struct rt6_info *rt = ip6_dst_alloc();
++	struct net *net = dev_net(idev->dev);
++	struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
+ 
+ 	if (rt == NULL)
+ 		return ERR_PTR(-ENOMEM);
+ 
+-	dev_hold(init_net.loopback_dev);
++	dev_hold(net->loopback_dev);
+ 	in6_dev_hold(idev);
+ 
+ 	rt->u.dst.flags = DST_HOST;
+ 	rt->u.dst.input = ip6_input;
+ 	rt->u.dst.output = ip6_output;
+-	rt->rt6i_dev = init_net.loopback_dev;
++	rt->rt6i_dev = net->loopback_dev;
+ 	rt->rt6i_idev = idev;
+ 	rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
+-	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
++	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
+ 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
+ 	rt->u.dst.obsolete = -1;
+ 
+@@ -1852,26 +1893,39 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+ 
+ 	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
+ 	rt->rt6i_dst.plen = 128;
+-	rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL);
++	rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
+ 
+ 	atomic_set(&rt->u.dst.__refcnt, 1);
+ 
+ 	return rt;
+ }
+ 
++struct arg_dev_net {
++	struct net_device *dev;
++	struct net *net;
++};
++
+ static int fib6_ifdown(struct rt6_info *rt, void *arg)
+ {
+-	if (((void*)rt->rt6i_dev == arg || arg == NULL) &&
+-	    rt != &ip6_null_entry) {
++	struct net_device *dev = ((struct arg_dev_net *)arg)->dev;
++	struct net *net = ((struct arg_dev_net *)arg)->net;
++
++	if (((void *)rt->rt6i_dev == dev || dev == NULL) &&
++	    rt != net->ipv6.ip6_null_entry) {
+ 		RT6_TRACE("deleted by ifdown %p\n", rt);
+ 		return -1;
+ 	}
+ 	return 0;
+ }
+ 
+-void rt6_ifdown(struct net_device *dev)
++void rt6_ifdown(struct net *net, struct net_device *dev)
+ {
+-	fib6_clean_all(fib6_ifdown, 0, dev);
++	struct arg_dev_net adn = {
++		.dev = dev,
++		.net = net,
++	};
++
++	fib6_clean_all(net, fib6_ifdown, 0, &adn);
+ }
+ 
+ struct rt6_mtu_change_arg
+@@ -1884,6 +1938,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
+ {
+ 	struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg;
+ 	struct inet6_dev *idev;
++	struct net *net = dev_net(arg->dev);
+ 
+ 	/* In IPv6 pmtu discovery is not optional,
+ 	   so that RTAX_MTU lock cannot disable it.
+@@ -1915,7 +1970,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
+ 	     (dst_mtu(&rt->u.dst) < arg->mtu &&
+ 	      dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) {
+ 		rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
+-		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu);
++		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu);
+ 	}
+ 	return 0;
+ }
+@@ -1927,7 +1982,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu)
+ 		.mtu = mtu,
+ 	};
+ 
+-	fib6_clean_all(rt6_mtu_change_route, 0, &arg);
++	fib6_clean_all(dev_net(dev), rt6_mtu_change_route, 0, &arg);
+ }
+ 
+ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
+@@ -1964,7 +2019,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
+ 
+ 	cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
+ 	cfg->fc_nlinfo.nlh = nlh;
+-	cfg->fc_nlinfo.nl_net = skb->sk->sk_net;
++	cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
+ 
+ 	if (tb[RTA_GATEWAY]) {
+ 		nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16);
+@@ -2010,13 +2065,9 @@ errout:
+ 
+ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
+ 	struct fib6_config cfg;
+ 	int err;
+ 
+-	if (net != &init_net)
+-		return -EINVAL;
+-
+ 	err = rtm_to_fib6_config(skb, nlh, &cfg);
+ 	if (err < 0)
+ 		return err;
+@@ -2026,13 +2077,9 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
+ 
+ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
+ 	struct fib6_config cfg;
+ 	int err;
+ 
+-	if (net != &init_net)
+-		return -EINVAL;
+-
+ 	err = rtm_to_fib6_config(skb, nlh, &cfg);
+ 	if (err < 0)
+ 		return err;
+@@ -2058,7 +2105,7 @@ static inline size_t rt6_nlmsg_size(void)
+ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
+ 			 struct in6_addr *dst, struct in6_addr *src,
+ 			 int iif, int type, u32 pid, u32 seq,
+-			 int prefix, unsigned int flags)
++			 int prefix, int nowait, unsigned int flags)
+ {
+ 	struct rtmsg *rtm;
+ 	struct nlmsghdr *nlh;
+@@ -2118,11 +2165,27 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
+ 	} else if (rtm->rtm_src_len)
+ 		NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr);
+ #endif
+-	if (iif)
+-		NLA_PUT_U32(skb, RTA_IIF, iif);
+-	else if (dst) {
++	if (iif) {
++#ifdef CONFIG_IPV6_MROUTE
++		if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
++			int err = ip6mr_get_route(skb, rtm, nowait);
++			if (err <= 0) {
++				if (!nowait) {
++					if (err == 0)
++						return 0;
++					goto nla_put_failure;
++				} else {
++					if (err == -EMSGSIZE)
++						goto nla_put_failure;
++				}
++			}
++		} else
++#endif
++			NLA_PUT_U32(skb, RTA_IIF, iif);
++	} else if (dst) {
+ 		struct in6_addr saddr_buf;
+-		if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)
++		if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev,
++				       dst, 0, &saddr_buf) == 0)
+ 			NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
+ 	}
+ 
+@@ -2162,12 +2225,12 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg)
+ 
+ 	return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
+ 		     NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
+-		     prefix, NLM_F_MULTI);
++		     prefix, 0, NLM_F_MULTI);
+ }
+ 
+ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
+ {
+-	struct net *net = in_skb->sk->sk_net;
++	struct net *net = sock_net(in_skb->sk);
+ 	struct nlattr *tb[RTA_MAX+1];
+ 	struct rt6_info *rt;
+ 	struct sk_buff *skb;
+@@ -2175,9 +2238,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ 	struct flowi fl;
+ 	int err, iif = 0;
+ 
+-	if (net != &init_net)
+-		return -EINVAL;
+-
+ 	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
+ 	if (err < 0)
+ 		goto errout;
+@@ -2207,7 +2267,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ 
+ 	if (iif) {
+ 		struct net_device *dev;
+-		dev = __dev_get_by_index(&init_net, iif);
++		dev = __dev_get_by_index(net, iif);
+ 		if (!dev) {
+ 			err = -ENODEV;
+ 			goto errout;
+@@ -2226,18 +2286,18 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ 	skb_reset_mac_header(skb);
+ 	skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
+ 
+-	rt = (struct rt6_info*) ip6_route_output(NULL, &fl);
++	rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl);
+ 	skb->dst = &rt->u.dst;
+ 
+ 	err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,
+ 			    RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
+-			    nlh->nlmsg_seq, 0, 0);
++			    nlh->nlmsg_seq, 0, 0, 0);
+ 	if (err < 0) {
+ 		kfree_skb(skb);
+ 		goto errout;
+ 	}
+ 
+-	err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
++	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid);
+ errout:
+ 	return err;
+ }
+@@ -2245,6 +2305,7 @@ errout:
+ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
+ {
+ 	struct sk_buff *skb;
++	struct net *net = info->nl_net;
+ 	u32 seq;
+ 	int err;
+ 
+@@ -2256,18 +2317,38 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
+ 		goto errout;
+ 
+ 	err = rt6_fill_node(skb, rt, NULL, NULL, 0,
+-				event, info->pid, seq, 0, 0);
++				event, info->pid, seq, 0, 0, 0);
+ 	if (err < 0) {
+ 		/* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
+ 		WARN_ON(err == -EMSGSIZE);
+ 		kfree_skb(skb);
+ 		goto errout;
+ 	}
+-	err = rtnl_notify(skb, &init_net, info->pid,
+-				RTNLGRP_IPV6_ROUTE, info->nlh, gfp_any());
++	err = rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE,
++			  info->nlh, gfp_any());
+ errout:
+ 	if (err < 0)
+-		rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err);
++		rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
++}
++
++static int ip6_route_dev_notify(struct notifier_block *this,
++				unsigned long event, void *data)
++{
++	struct net_device *dev = (struct net_device *)data;
++	struct net *net = dev_net(dev);
++
++	if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
++		net->ipv6.ip6_null_entry->u.dst.dev = dev;
++		net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++		net->ipv6.ip6_prohibit_entry->u.dst.dev = dev;
++		net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
++		net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev;
++		net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
++#endif
++	}
++
++	return NOTIFY_OK;
+ }
+ 
+ /*
+@@ -2316,13 +2397,33 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
+ 
+ static int ipv6_route_show(struct seq_file *m, void *v)
+ {
+-	fib6_clean_all(rt6_info_route, 0, m);
++	struct net *net = (struct net *)m->private;
++	fib6_clean_all(net, rt6_info_route, 0, m);
+ 	return 0;
+ }
+ 
+ static int ipv6_route_open(struct inode *inode, struct file *file)
+ {
+-	return single_open(file, ipv6_route_show, NULL);
++	int err;
++	struct net *net = get_proc_net(inode);
++	if (!net)
++		return -ENXIO;
++
++	err = single_open(file, ipv6_route_show, net);
++	if (err < 0) {
++		put_net(net);
++		return err;
++	}
++
++	return 0;
++}
++
++static int ipv6_route_release(struct inode *inode, struct file *file)
++{
++	struct seq_file *seq = file->private_data;
++	struct net *net = seq->private;
++	put_net(net);
++	return single_release(inode, file);
+ }
+ 
+ static const struct file_operations ipv6_route_proc_fops = {
+@@ -2330,24 +2431,46 @@ static const struct file_operations ipv6_route_proc_fops = {
+ 	.open		= ipv6_route_open,
+ 	.read		= seq_read,
+ 	.llseek		= seq_lseek,
+-	.release	= single_release,
++	.release	= ipv6_route_release,
+ };
+ 
+ static int rt6_stats_seq_show(struct seq_file *seq, void *v)
+ {
++	struct net *net = (struct net *)seq->private;
+ 	seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
+-		      rt6_stats.fib_nodes, rt6_stats.fib_route_nodes,
+-		      rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries,
+-		      rt6_stats.fib_rt_cache,
+-		      atomic_read(&ip6_dst_ops.entries),
+-		      rt6_stats.fib_discarded_routes);
++		   net->ipv6.rt6_stats->fib_nodes,
++		   net->ipv6.rt6_stats->fib_route_nodes,
++		   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),
++		   net->ipv6.rt6_stats->fib_discarded_routes);
+ 
+ 	return 0;
+ }
+ 
+ static int rt6_stats_seq_open(struct inode *inode, struct file *file)
+ {
+-	return single_open(file, rt6_stats_seq_show, NULL);
++	int err;
++	struct net *net = get_proc_net(inode);
++	if (!net)
++		return -ENXIO;
++
++	err = single_open(file, rt6_stats_seq_show, net);
++	if (err < 0) {
++		put_net(net);
++		return err;
++	}
++
++	return 0;
++}
++
++static int rt6_stats_seq_release(struct inode *inode, struct file *file)
++{
++	struct seq_file *seq = file->private_data;
++	struct net *net = (struct net *)seq->private;
++	put_net(net);
++	return single_release(inode, file);
+ }
+ 
+ static const struct file_operations rt6_stats_seq_fops = {
+@@ -2355,42 +2478,8 @@ static const struct file_operations rt6_stats_seq_fops = {
+ 	.open	 = rt6_stats_seq_open,
+ 	.read	 = seq_read,
+ 	.llseek	 = seq_lseek,
+-	.release = single_release,
++	.release = rt6_stats_seq_release,
+ };
+-
+-static int ipv6_route_proc_init(struct net *net)
+-{
+-	int ret = -ENOMEM;
+-	if (!proc_net_fops_create(net, "ipv6_route",
+-				  0, &ipv6_route_proc_fops))
+-		goto out;
+-
+-	if (!proc_net_fops_create(net, "rt6_stats",
+-				  S_IRUGO, &rt6_stats_seq_fops))
+-		goto out_ipv6_route;
+-
+-	ret = 0;
+-out:
+-	return ret;
+-out_ipv6_route:
+-	proc_net_remove(net, "ipv6_route");
+-	goto out;
+-}
+-
+-static void ipv6_route_proc_fini(struct net *net)
+-{
+-	proc_net_remove(net, "ipv6_route");
+-	proc_net_remove(net, "rt6_stats");
+-}
+-#else
+-static inline int ipv6_route_proc_init(struct net *net)
+-{
+-	return 0;
+-}
+-static inline void ipv6_route_proc_fini(struct net *net)
+-{
+-	return ;
+-}
+ #endif	/* CONFIG_PROC_FS */
+ 
+ #ifdef CONFIG_SYSCTL
+@@ -2399,10 +2488,11 @@ static
+ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,
+ 			      void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+-	int delay = init_net.ipv6.sysctl.flush_delay;
++	struct net *net = current->nsproxy->net_ns;
++	int delay = net->ipv6.sysctl.flush_delay;
+ 	if (write) {
+ 		proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+-		fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay);
++		fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net);
+ 		return 0;
+ 	} else
+ 		return -EINVAL;
+@@ -2419,7 +2509,7 @@ ctl_table ipv6_route_table_template[] = {
+ 	{
+ 		.ctl_name	=	NET_IPV6_ROUTE_GC_THRESH,
+ 		.procname	=	"gc_thresh",
+-		.data		=	&ip6_dst_ops.gc_thresh,
++		.data		=	&ip6_dst_ops_template.gc_thresh,
+ 		.maxlen		=	sizeof(int),
+ 		.mode		=	0644,
+ 		.proc_handler	=	&proc_dointvec,
+@@ -2505,33 +2595,142 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net)
+ 	table = kmemdup(ipv6_route_table_template,
+ 			sizeof(ipv6_route_table_template),
+ 			GFP_KERNEL);
++
++	if (table) {
++		table[0].data = &net->ipv6.sysctl.flush_delay;
++		table[1].data = &net->ipv6.ip6_dst_ops->gc_thresh;
++		table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
++		table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
++		table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
++		table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval;
++		table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
++		table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
++		table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
++	}
++
+ 	return table;
+ }
+ #endif
+ 
++static int ip6_route_net_init(struct net *net)
++{
++	int ret = -ENOMEM;
++
++	net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template,
++					sizeof(*net->ipv6.ip6_dst_ops),
++					GFP_KERNEL);
++	if (!net->ipv6.ip6_dst_ops)
++		goto out;
++	net->ipv6.ip6_dst_ops->dst_net = hold_net(net);
++
++	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;
++	net->ipv6.ip6_null_entry->u.dst.path =
++		(struct dst_entry *)net->ipv6.ip6_null_entry;
++	net->ipv6.ip6_null_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
++
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++	net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
++					       sizeof(*net->ipv6.ip6_prohibit_entry),
++					       GFP_KERNEL);
++	if (!net->ipv6.ip6_prohibit_entry) {
++		kfree(net->ipv6.ip6_null_entry);
++		goto out;
++	}
++	net->ipv6.ip6_prohibit_entry->u.dst.path =
++		(struct dst_entry *)net->ipv6.ip6_prohibit_entry;
++	net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
++
++	net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
++					       sizeof(*net->ipv6.ip6_blk_hole_entry),
++					       GFP_KERNEL);
++	if (!net->ipv6.ip6_blk_hole_entry) {
++		kfree(net->ipv6.ip6_null_entry);
++		kfree(net->ipv6.ip6_prohibit_entry);
++		goto out;
++	}
++	net->ipv6.ip6_blk_hole_entry->u.dst.path =
++		(struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
++	net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
++#endif
++
++#ifdef CONFIG_PROC_FS
++	proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
++	proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
++#endif
++	net->ipv6.ip6_rt_gc_expire = 30*HZ;
++
++	ret = 0;
++out:
++	return ret;
++
++out_ip6_dst_ops:
++	release_net(net->ipv6.ip6_dst_ops->dst_net);
++	kfree(net->ipv6.ip6_dst_ops);
++	goto out;
++}
++
++static void ip6_route_net_exit(struct net *net)
++{
++#ifdef CONFIG_PROC_FS
++	proc_net_remove(net, "ipv6_route");
++	proc_net_remove(net, "rt6_stats");
++#endif
++	kfree(net->ipv6.ip6_null_entry);
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++	kfree(net->ipv6.ip6_prohibit_entry);
++	kfree(net->ipv6.ip6_blk_hole_entry);
++#endif
++	release_net(net->ipv6.ip6_dst_ops->dst_net);
++	kfree(net->ipv6.ip6_dst_ops);
++}
++
++static struct pernet_operations ip6_route_net_ops = {
++	.init = ip6_route_net_init,
++	.exit = ip6_route_net_exit,
++};
++
++static struct notifier_block ip6_route_dev_notifier = {
++	.notifier_call = ip6_route_dev_notify,
++	.priority = 0,
++};
++
+ int __init ip6_route_init(void)
+ {
+ 	int ret;
+ 
+-	ip6_dst_ops.kmem_cachep =
++	ret = -ENOMEM;
++	ip6_dst_ops_template.kmem_cachep =
+ 		kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
+ 				  SLAB_HWCACHE_ALIGN, NULL);
+-	if (!ip6_dst_ops.kmem_cachep)
+-		return -ENOMEM;
+-
+-	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
++	if (!ip6_dst_ops_template.kmem_cachep)
++		goto out;;
+ 
+-	ret = fib6_init();
++	ret = register_pernet_subsys(&ip6_route_net_ops);
+ 	if (ret)
+ 		goto out_kmem_cache;
+ 
+-	ret = ipv6_route_proc_init(&init_net);
++	/* Registering of the loopback is done before this portion of code,
++	 * the loopback reference in rt6_info will not be taken, do it
++	 * manually for init_net */
++	init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev;
++	init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
++  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
++	init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev;
++	init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
++	init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev;
++	init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
++  #endif
++	ret = fib6_init();
+ 	if (ret)
+-		goto out_fib6_init;
++		goto out_register_subsys;
+ 
+ 	ret = xfrm6_init();
+ 	if (ret)
+-		goto out_proc_init;
++		goto out_fib6_init;
+ 
+ 	ret = fib6_rules_init();
+ 	if (ret)
+@@ -2543,7 +2742,10 @@ int __init ip6_route_init(void)
+ 	    __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
+ 		goto fib6_rules_init;
+ 
+-	ret = 0;
++	ret = register_netdevice_notifier(&ip6_route_dev_notifier);
++	if (ret)
++		goto fib6_rules_init;
++
+ out:
+ 	return ret;
+ 
+@@ -2551,22 +2753,21 @@ fib6_rules_init:
+ 	fib6_rules_cleanup();
+ xfrm6_init:
+ 	xfrm6_fini();
+-out_proc_init:
+-	ipv6_route_proc_fini(&init_net);
+ out_fib6_init:
+-	rt6_ifdown(NULL);
+ 	fib6_gc_cleanup();
++out_register_subsys:
++	unregister_pernet_subsys(&ip6_route_net_ops);
+ out_kmem_cache:
+-	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
++	kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
+ 	goto out;
+ }
+ 
+ void ip6_route_cleanup(void)
+ {
++	unregister_netdevice_notifier(&ip6_route_dev_notifier);
+ 	fib6_rules_cleanup();
+-	ipv6_route_proc_fini(&init_net);
+ 	xfrm6_fini();
+-	rt6_ifdown(NULL);
+ 	fib6_gc_cleanup();
+-	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
++	unregister_pernet_subsys(&ip6_route_net_ops);
++	kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
+ }
+diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
+index 1656c00..4b2f103 100644
+--- a/net/ipv6/sit.c
++++ b/net/ipv6/sit.c
+@@ -16,7 +16,7 @@
+  *	Changes:
+  * Roger Venning <r.venning at telstra.com>:	6to4 support
+  * Nate Thompson <nate at thebog.net>:		6to4 support
+- * Fred L. Templin <fltemplin at acm.org>:		isatap support
++ * Fred Templin <fred.l.templin at boeing.com>:	isatap support
+  */
+ 
+ #include <linux/module.h>
+@@ -52,6 +52,8 @@
+ #include <net/inet_ecn.h>
+ #include <net/xfrm.h>
+ #include <net/dsfield.h>
++#include <net/net_namespace.h>
++#include <net/netns/generic.h>
+ 
+ /*
+    This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c
+@@ -66,41 +68,47 @@ static int ipip6_fb_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 struct net_device *ipip6_fb_tunnel_dev;
++static int sit_net_id;
++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];
+ 
+-static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
+-static struct ip_tunnel *tunnels_r[HASH_SIZE];
+-static struct ip_tunnel *tunnels_l[HASH_SIZE];
+-static struct ip_tunnel *tunnels_wc[1];
+-static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
++	struct net_device *fb_tunnel_dev;
++};
+ 
+ static DEFINE_RWLOCK(ipip6_lock);
+ 
+-static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local)
++static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
++		__be32 remote, __be32 local)
+ {
+ 	unsigned h0 = HASH(remote);
+ 	unsigned h1 = HASH(local);
+ 	struct ip_tunnel *t;
++	struct sit_net *sitn = net_generic(net, sit_net_id);
+ 
+-	for (t = tunnels_r_l[h0^h1]; t; t = t->next) {
++	for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) {
+ 		if (local == t->parms.iph.saddr &&
+ 		    remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ 			return t;
+ 	}
+-	for (t = tunnels_r[h0]; t; t = t->next) {
++	for (t = sitn->tunnels_r[h0]; t; t = t->next) {
+ 		if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ 			return t;
+ 	}
+-	for (t = tunnels_l[h1]; t; t = t->next) {
++	for (t = sitn->tunnels_l[h1]; t; t = t->next) {
+ 		if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
+ 			return t;
+ 	}
+-	if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
++	if ((t = sitn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
+ 		return t;
+ 	return NULL;
+ }
+ 
+-static struct ip_tunnel **__ipip6_bucket(struct ip_tunnel_parm *parms)
++static struct ip_tunnel **__ipip6_bucket(struct sit_net *sitn,
++		struct ip_tunnel_parm *parms)
+ {
+ 	__be32 remote = parms->iph.daddr;
+ 	__be32 local = parms->iph.saddr;
+@@ -115,19 +123,20 @@ static struct ip_tunnel **__ipip6_bucket(struct ip_tunnel_parm *parms)
+ 		prio |= 1;
+ 		h ^= HASH(local);
+ 	}
+-	return &tunnels[prio][h];
++	return &sitn->tunnels[prio][h];
+ }
+ 
+-static inline struct ip_tunnel **ipip6_bucket(struct ip_tunnel *t)
++static inline struct ip_tunnel **ipip6_bucket(struct sit_net *sitn,
++		struct ip_tunnel *t)
+ {
+-	return __ipip6_bucket(&t->parms);
++	return __ipip6_bucket(sitn, &t->parms);
+ }
+ 
+-static void ipip6_tunnel_unlink(struct ip_tunnel *t)
++static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t)
+ {
+ 	struct ip_tunnel **tp;
+ 
+-	for (tp = ipip6_bucket(t); *tp; tp = &(*tp)->next) {
++	for (tp = ipip6_bucket(sitn, t); *tp; tp = &(*tp)->next) {
+ 		if (t == *tp) {
+ 			write_lock_bh(&ipip6_lock);
+ 			*tp = t->next;
+@@ -137,9 +146,9 @@ static void ipip6_tunnel_unlink(struct ip_tunnel *t)
+ 	}
+ }
+ 
+-static void ipip6_tunnel_link(struct ip_tunnel *t)
++static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t)
+ {
+-	struct ip_tunnel **tp = ipip6_bucket(t);
++	struct ip_tunnel **tp = ipip6_bucket(sitn, t);
+ 
+ 	t->next = *tp;
+ 	write_lock_bh(&ipip6_lock);
+@@ -147,15 +156,17 @@ static void ipip6_tunnel_link(struct ip_tunnel *t)
+ 	write_unlock_bh(&ipip6_lock);
+ }
+ 
+-static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create)
++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 net_device *dev;
+ 	char name[IFNAMSIZ];
++	struct sit_net *sitn = net_generic(net, sit_net_id);
+ 
+-	for (tp = __ipip6_bucket(parms); (t = *tp) != NULL; tp = &t->next) {
++	for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) {
+ 		if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
+ 			return t;
+ 	}
+@@ -171,6 +182,8 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
+ 	if (dev == NULL)
+ 		return NULL;
+ 
++	dev_net_set(dev, net);
++
+ 	if (strchr(name, '%')) {
+ 		if (dev_alloc_name(dev, name) < 0)
+ 			goto failed_free;
+@@ -188,7 +201,7 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
+ 
+ 	dev_hold(dev);
+ 
+-	ipip6_tunnel_link(nt);
++	ipip6_tunnel_link(sitn, nt);
+ 	return nt;
+ 
+ failed_free:
+@@ -197,15 +210,192 @@ failed:
+ 	return NULL;
+ }
+ 
++static struct ip_tunnel_prl_entry *
++__ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)
++{
++	struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *)NULL;
++
++	for (p = t->prl; p; p = p->next)
++		if (p->addr == addr)
++			break;
++	return p;
++
++}
++
++static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
++{
++	struct ip_tunnel_prl *kp;
++	struct ip_tunnel_prl_entry *prl;
++	unsigned int cmax, c = 0, ca, len;
++	int ret = 0;
++
++	cmax = a->datalen / sizeof(*a);
++	if (cmax > 1 && a->addr != htonl(INADDR_ANY))
++		cmax = 1;
++
++	/* For simple GET or for root users,
++	 * we try harder to allocate.
++	 */
++	kp = (cmax <= 1 || capable(CAP_NET_ADMIN)) ?
++		kcalloc(cmax, sizeof(*kp), GFP_KERNEL) :
++		NULL;
++
++	read_lock(&ipip6_lock);
++
++	ca = t->prl_count < cmax ? t->prl_count : cmax;
++
++	if (!kp) {
++		/* We don't try hard to allocate much memory for
++		 * non-root users.
++		 * For root users, retry allocating enough memory for
++		 * the answer.
++		 */
++		kp = kcalloc(ca, sizeof(*kp), GFP_ATOMIC);
++		if (!kp) {
++			ret = -ENOMEM;
++			goto out;
++		}
++	}
++
++	c = 0;
++	for (prl = t->prl; prl; prl = prl->next) {
++		if (c > cmax)
++			break;
++		if (a->addr != htonl(INADDR_ANY) && prl->addr != a->addr)
++			continue;
++		kp[c].addr = prl->addr;
++		kp[c].flags = prl->flags;
++		c++;
++		if (a->addr != htonl(INADDR_ANY))
++			break;
++	}
++out:
++	read_unlock(&ipip6_lock);
++
++	len = sizeof(*kp) * c;
++	ret = len ? copy_to_user(a->data, kp, len) : 0;
++
++	kfree(kp);
++	if (ret)
++		return -EFAULT;
++
++	a->datalen = len;
++	return 0;
++}
++
++static int
++ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
++{
++	struct ip_tunnel_prl_entry *p;
++	int err = 0;
++
++	if (a->addr == htonl(INADDR_ANY))
++		return -EINVAL;
++
++	write_lock(&ipip6_lock);
++
++	for (p = t->prl; p; p = p->next) {
++		if (p->addr == a->addr) {
++			if (chg)
++				goto update;
++			err = -EEXIST;
++			goto out;
++		}
++	}
++
++	if (chg) {
++		err = -ENXIO;
++		goto out;
++	}
++
++	p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL);
++	if (!p) {
++		err = -ENOBUFS;
++		goto out;
++	}
++
++	p->next = t->prl;
++	t->prl = p;
++	t->prl_count++;
++update:
++	p->addr = a->addr;
++	p->flags = a->flags;
++out:
++	write_unlock(&ipip6_lock);
++	return err;
++}
++
++static int
++ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
++{
++	struct ip_tunnel_prl_entry *x, **p;
++	int err = 0;
++
++	write_lock(&ipip6_lock);
++
++	if (a && a->addr != htonl(INADDR_ANY)) {
++		for (p = &t->prl; *p; p = &(*p)->next) {
++			if ((*p)->addr == a->addr) {
++				x = *p;
++				*p = x->next;
++				kfree(x);
++				t->prl_count--;
++				goto out;
++			}
++		}
++		err = -ENXIO;
++	} else {
++		while (t->prl) {
++			x = t->prl;
++			t->prl = t->prl->next;
++			kfree(x);
++			t->prl_count--;
++		}
++	}
++out:
++	write_unlock(&ipip6_lock);
++	return 0;
++}
++
++static int
++isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t)
++{
++	struct ip_tunnel_prl_entry *p;
++	int ok = 1;
++
++	read_lock(&ipip6_lock);
++	p = __ipip6_tunnel_locate_prl(t, iph->saddr);
++	if (p) {
++		if (p->flags & PRL_DEFAULT)
++			skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT;
++		else
++			skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT;
++	} else {
++		struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr;
++		if (ipv6_addr_is_isatap(addr6) &&
++		    (addr6->s6_addr32[3] == iph->saddr) &&
++		    ipv6_chk_prefix(addr6, t->dev))
++			skb->ndisc_nodetype = NDISC_NODETYPE_HOST;
++		else
++			ok = 0;
++	}
++	read_unlock(&ipip6_lock);
++	return ok;
++}
++
+ static void ipip6_tunnel_uninit(struct net_device *dev)
+ {
+-	if (dev == ipip6_fb_tunnel_dev) {
++	struct net *net = dev_net(dev);
++	struct sit_net *sitn = net_generic(net, sit_net_id);
++
++	if (dev == sitn->fb_tunnel_dev) {
+ 		write_lock_bh(&ipip6_lock);
+-		tunnels_wc[0] = NULL;
++		sitn->tunnels_wc[0] = NULL;
+ 		write_unlock_bh(&ipip6_lock);
+ 		dev_put(dev);
+ 	} else {
+-		ipip6_tunnel_unlink(netdev_priv(dev));
++		ipip6_tunnel_unlink(sitn, netdev_priv(dev));
++		ipip6_tunnel_del_prl(netdev_priv(dev), NULL);
+ 		dev_put(dev);
+ 	}
+ }
+@@ -256,7 +446,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
+ 	err = -ENOENT;
+ 
+ 	read_lock(&ipip6_lock);
+-	t = ipip6_tunnel_lookup(iph->daddr, iph->saddr);
++	t = ipip6_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr);
+ 	if (t == NULL || t->parms.iph.daddr == 0)
+ 		goto out;
+ 
+@@ -339,11 +529,12 @@ out:
+ 	skb_reset_network_header(skb2);
+ 
+ 	/* Try to guess incoming interface */
+-	rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0);
++	rt6i = rt6_lookup(dev_net(skb->dev), &iph6->saddr, NULL, NULL, 0);
+ 	if (rt6i && rt6i->rt6i_dev) {
+ 		skb2->dev = rt6i->rt6i_dev;
+ 
+-		rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0);
++		rt6i = rt6_lookup(dev_net(skb->dev),
++				&iph6->daddr, &iph6->saddr, NULL, 0);
+ 
+ 		if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) {
+ 			struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev);
+@@ -365,48 +556,6 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+ 		IP6_ECN_set_ce(ipv6_hdr(skb));
+ }
+ 
+-/* ISATAP (RFC4214) - check source address */
+-static int
+-isatap_srcok(struct sk_buff *skb, struct iphdr *iph, struct net_device *dev)
+-{
+-	struct neighbour *neigh;
+-	struct dst_entry *dst;
+-	struct rt6_info *rt;
+-	struct flowi fl;
+-	struct in6_addr *addr6;
+-	struct in6_addr rtr;
+-	struct ipv6hdr *iph6;
+-	int ok = 0;
+-
+-	/* from onlink default router */
+-	ipv6_addr_set(&rtr,  htonl(0xFE800000), 0, 0, 0);
+-	ipv6_isatap_eui64(rtr.s6_addr + 8, iph->saddr);
+-	if ((rt = rt6_get_dflt_router(&rtr, dev))) {
+-		dst_release(&rt->u.dst);
+-		return 1;
+-	}
+-
+-	iph6 = ipv6_hdr(skb);
+-	memset(&fl, 0, sizeof(fl));
+-	fl.proto = iph6->nexthdr;
+-	ipv6_addr_copy(&fl.fl6_dst, &iph6->saddr);
+-	fl.oif = dev->ifindex;
+-	security_skb_classify_flow(skb, &fl);
+-
+-	dst = ip6_route_output(NULL, &fl);
+-	if (!dst->error && (dst->dev == dev) && (neigh = dst->neighbour)) {
+-
+-		addr6 = (struct in6_addr*)&neigh->primary_key;
+-
+-		/* from correct previous hop */
+-		if (ipv6_addr_is_isatap(addr6) &&
+-		    (addr6->s6_addr32[3] == iph->saddr))
+-			ok = 1;
+-	}
+-	dst_release(dst);
+-	return ok;
+-}
+-
+ static int ipip6_rcv(struct sk_buff *skb)
+ {
+ 	struct iphdr *iph;
+@@ -418,7 +567,8 @@ static int ipip6_rcv(struct sk_buff *skb)
+ 	iph = ip_hdr(skb);
+ 
+ 	read_lock(&ipip6_lock);
+-	if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
++	if ((tunnel = ipip6_tunnel_lookup(dev_net(skb->dev),
++					iph->saddr, iph->daddr)) != NULL) {
+ 		secpath_reset(skb);
+ 		skb->mac_header = skb->network_header;
+ 		skb_reset_network_header(skb);
+@@ -427,7 +577,7 @@ static int ipip6_rcv(struct sk_buff *skb)
+ 		skb->pkt_type = PACKET_HOST;
+ 
+ 		if ((tunnel->dev->priv_flags & IFF_ISATAP) &&
+-		    !isatap_srcok(skb, iph, tunnel->dev)) {
++		    !isatap_chksrc(skb, iph, tunnel)) {
+ 			tunnel->stat.rx_errors++;
+ 			read_unlock(&ipip6_lock);
+ 			kfree_skb(skb);
+@@ -554,7 +704,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ 						.tos = RT_TOS(tos) } },
+ 				    .oif = tunnel->parms.link,
+ 				    .proto = IPPROTO_IPV6 };
+-		if (ip_route_output_key(&init_net, &rt, &fl)) {
++		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ 			tunnel->stat.tx_carrier_errors++;
+ 			goto tx_error_icmp;
+ 		}
+@@ -683,7 +833,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
+ 				    .oif = tunnel->parms.link,
+ 				    .proto = IPPROTO_IPV6 };
+ 		struct rtable *rt;
+-		if (!ip_route_output_key(&init_net, &rt, &fl)) {
++		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ 			tdev = rt->u.dst.dev;
+ 			ip_rt_put(rt);
+ 		}
+@@ -691,7 +841,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
+ 	}
+ 
+ 	if (!tdev && tunnel->parms.link)
+-		tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
++		tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
+ 
+ 	if (tdev) {
+ 		dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+@@ -707,17 +857,20 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+ 	int err = 0;
+ 	struct ip_tunnel_parm p;
++	struct ip_tunnel_prl prl;
+ 	struct ip_tunnel *t;
++	struct net *net = dev_net(dev);
++	struct sit_net *sitn = net_generic(net, sit_net_id);
+ 
+ 	switch (cmd) {
+ 	case SIOCGETTUNNEL:
+ 		t = NULL;
+-		if (dev == ipip6_fb_tunnel_dev) {
++		if (dev == sitn->fb_tunnel_dev) {
+ 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
+ 				err = -EFAULT;
+ 				break;
+ 			}
+-			t = ipip6_tunnel_locate(&p, 0);
++			t = ipip6_tunnel_locate(net, &p, 0);
+ 		}
+ 		if (t == NULL)
+ 			t = netdev_priv(dev);
+@@ -743,9 +896,9 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		if (p.iph.ttl)
+ 			p.iph.frag_off |= htons(IP_DF);
+ 
+-		t = ipip6_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
++		t = ipip6_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
+ 
+-		if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
++		if (dev != sitn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
+ 			if (t != NULL) {
+ 				if (t->dev != dev) {
+ 					err = -EEXIST;
+@@ -758,12 +911,12 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 					break;
+ 				}
+ 				t = netdev_priv(dev);
+-				ipip6_tunnel_unlink(t);
++				ipip6_tunnel_unlink(sitn, t);
+ 				t->parms.iph.saddr = p.iph.saddr;
+ 				t->parms.iph.daddr = p.iph.daddr;
+ 				memcpy(dev->dev_addr, &p.iph.saddr, 4);
+ 				memcpy(dev->broadcast, &p.iph.daddr, 4);
+-				ipip6_tunnel_link(t);
++				ipip6_tunnel_link(sitn, t);
+ 				netdev_state_change(dev);
+ 			}
+ 		}
+@@ -790,15 +943,15 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		if (!capable(CAP_NET_ADMIN))
+ 			goto done;
+ 
+-		if (dev == ipip6_fb_tunnel_dev) {
++		if (dev == sitn->fb_tunnel_dev) {
+ 			err = -EFAULT;
+ 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ 				goto done;
+ 			err = -ENOENT;
+-			if ((t = ipip6_tunnel_locate(&p, 0)) == NULL)
++			if ((t = ipip6_tunnel_locate(net, &p, 0)) == NULL)
+ 				goto done;
+ 			err = -EPERM;
+-			if (t == netdev_priv(ipip6_fb_tunnel_dev))
++			if (t == netdev_priv(sitn->fb_tunnel_dev))
+ 				goto done;
+ 			dev = t->dev;
+ 		}
+@@ -806,6 +959,42 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ 		err = 0;
+ 		break;
+ 
++	case SIOCGETPRL:
++	case SIOCADDPRL:
++	case SIOCDELPRL:
++	case SIOCCHGPRL:
++		err = -EPERM;
++		if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN))
++			goto done;
++		err = -EINVAL;
++		if (dev == sitn->fb_tunnel_dev)
++			goto done;
++		err = -EFAULT;
++		if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl)))
++			goto done;
++		err = -ENOENT;
++		if (!(t = netdev_priv(dev)))
++			goto done;
++
++		switch (cmd) {
++		case SIOCGETPRL:
++			err = ipip6_tunnel_get_prl(t, &prl);
++			if (!err && copy_to_user(ifr->ifr_ifru.ifru_data,
++						 &prl, sizeof(prl)))
++				err = -EFAULT;
++			break;
++		case SIOCDELPRL:
++			err = ipip6_tunnel_del_prl(t, &prl);
++			break;
++		case SIOCADDPRL:
++		case SIOCCHGPRL:
++			err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
++			break;
++		}
++		if (cmd != SIOCGETPRL)
++			netdev_state_change(dev);
++		break;
++
+ 	default:
+ 		err = -EINVAL;
+ 	}
+@@ -842,6 +1031,7 @@ static void ipip6_tunnel_setup(struct net_device *dev)
+ 	dev->flags		= IFF_NOARP;
+ 	dev->iflink		= 0;
+ 	dev->addr_len		= 4;
++	dev->features		|= NETIF_F_NETNS_LOCAL;
+ }
+ 
+ static int ipip6_tunnel_init(struct net_device *dev)
+@@ -861,10 +1051,12 @@ static int ipip6_tunnel_init(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static int __init ipip6_fb_tunnel_init(struct net_device *dev)
++static int ipip6_fb_tunnel_init(struct net_device *dev)
+ {
+ 	struct ip_tunnel *tunnel = netdev_priv(dev);
+ 	struct iphdr *iph = &tunnel->parms.iph;
++	struct net *net = dev_net(dev);
++	struct sit_net *sitn = net_generic(net, sit_net_id);
+ 
+ 	tunnel->dev = dev;
+ 	strcpy(tunnel->parms.name, dev->name);
+@@ -875,7 +1067,7 @@ static int __init ipip6_fb_tunnel_init(struct net_device *dev)
+ 	iph->ttl		= 64;
+ 
+ 	dev_hold(dev);
+-	tunnels_wc[0]		= tunnel;
++	sitn->tunnels_wc[0]	= tunnel;
+ 	return 0;
+ }
+ 
+@@ -885,7 +1077,7 @@ static struct xfrm_tunnel sit_handler = {
+ 	.priority	=	1,
+ };
+ 
+-static void __exit sit_destroy_tunnels(void)
++static void sit_destroy_tunnels(struct sit_net *sitn)
+ {
+ 	int prio;
+ 
+@@ -893,20 +1085,78 @@ static void __exit sit_destroy_tunnels(void)
+ 		int h;
+ 		for (h = 0; h < HASH_SIZE; h++) {
+ 			struct ip_tunnel *t;
+-			while ((t = tunnels[prio][h]) != NULL)
++			while ((t = sitn->tunnels[prio][h]) != NULL)
+ 				unregister_netdevice(t->dev);
+ 		}
+ 	}
+ }
+ 
+-static void __exit sit_cleanup(void)
++static int sit_init_net(struct net *net)
+ {
+-	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
++	int err;
++	struct sit_net *sitn;
++
++	err = -ENOMEM;
++	sitn = kzalloc(sizeof(struct sit_net), GFP_KERNEL);
++	if (sitn == NULL)
++		goto err_alloc;
++
++	err = net_assign_generic(net, sit_net_id, sitn);
++	if (err < 0)
++		goto err_assign;
++
++	sitn->tunnels[0] = sitn->tunnels_wc;
++	sitn->tunnels[1] = sitn->tunnels_l;
++	sitn->tunnels[2] = sitn->tunnels_r;
++	sitn->tunnels[3] = sitn->tunnels_r_l;
++
++	sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
++					   ipip6_tunnel_setup);
++	if (!sitn->fb_tunnel_dev) {
++		err = -ENOMEM;
++		goto err_alloc_dev;
++	}
++
++	sitn->fb_tunnel_dev->init = ipip6_fb_tunnel_init;
++	dev_net_set(sitn->fb_tunnel_dev, net);
++
++	if ((err = register_netdev(sitn->fb_tunnel_dev)))
++		goto err_reg_dev;
+ 
++	return 0;
++
++err_reg_dev:
++	free_netdev(sitn->fb_tunnel_dev);
++err_alloc_dev:
++	/* nothing */
++err_assign:
++	kfree(sitn);
++err_alloc:
++	return err;
++}
++
++static void sit_exit_net(struct net *net)
++{
++	struct sit_net *sitn;
++
++	sitn = net_generic(net, sit_net_id);
+ 	rtnl_lock();
+-	sit_destroy_tunnels();
+-	unregister_netdevice(ipip6_fb_tunnel_dev);
++	sit_destroy_tunnels(sitn);
++	unregister_netdevice(sitn->fb_tunnel_dev);
+ 	rtnl_unlock();
++	kfree(sitn);
++}
++
++static struct pernet_operations sit_net_ops = {
++	.init = sit_init_net,
++	.exit = sit_exit_net,
++};
++
++static void __exit sit_cleanup(void)
++{
++	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
++
++	unregister_pernet_gen_device(sit_net_id, &sit_net_ops);
+ }
+ 
+ static int __init sit_init(void)
+@@ -920,25 +1170,11 @@ static int __init sit_init(void)
+ 		return -EAGAIN;
+ 	}
+ 
+-	ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
+-					   ipip6_tunnel_setup);
+-	if (!ipip6_fb_tunnel_dev) {
+-		err = -ENOMEM;
+-		goto err1;
+-	}
+-
+-	ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init;
++	err = register_pernet_gen_device(&sit_net_id, &sit_net_ops);
++	if (err < 0)
++		xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+ 
+-	if ((err =  register_netdev(ipip6_fb_tunnel_dev)))
+-		goto err2;
+-
+- out:
+ 	return err;
+- err2:
+-	free_netdev(ipip6_fb_tunnel_dev);
+- err1:
+-	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+-	goto out;
+ }
+ 
+ module_init(sit_init);
+diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
+new file mode 100644
+index 0000000..938ce4e
+--- /dev/null
++++ b/net/ipv6/syncookies.c
+@@ -0,0 +1,279 @@
++/*
++ *  IPv6 Syncookies implementation for the Linux kernel
++ *
++ *  Authors:
++ *  Glenn Griffin	<ggriffin.kernel at gmail.com>
++ *
++ *  Based on IPv4 implementation by Andi Kleen
++ *  linux/net/ipv4/syncookies.c
++ *
++ *	This program is free software; you can redistribute it and/or
++ *      modify it under the terms of the GNU General Public License
++ *      as published by the Free Software Foundation; either version
++ *      2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/tcp.h>
++#include <linux/random.h>
++#include <linux/cryptohash.h>
++#include <linux/kernel.h>
++#include <net/ipv6.h>
++#include <net/tcp.h>
++
++extern int sysctl_tcp_syncookies;
++extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
++
++#define COOKIEBITS 24	/* Upper bits store count */
++#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
++
++/*
++ * This table has to be sorted and terminated with (__u16)-1.
++ * XXX generate a better table.
++ * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
++ *
++ * Taken directly from ipv4 implementation.
++ * Should this list be modified for ipv6 use or is it close enough?
++ * rfc 2460 8.3 suggests mss values 20 bytes less than ipv4 counterpart
++ */
++static __u16 const msstab[] = {
++	64 - 1,
++	256 - 1,
++	512 - 1,
++	536 - 1,
++	1024 - 1,
++	1440 - 1,
++	1460 - 1,
++	4312 - 1,
++	(__u16)-1
++};
++/* The number doesn't include the -1 terminator */
++#define NUM_MSS (ARRAY_SIZE(msstab) - 1)
++
++/*
++ * This (misnamed) value is the age of syncookie which is permitted.
++ * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
++ * sysctl_tcp_retries1. It's a rather complicated formula (exponential
++ * backoff) to compute at runtime so it's currently hardcoded here.
++ */
++#define COUNTER_TRIES 4
++
++static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
++					   struct request_sock *req,
++					   struct dst_entry *dst)
++{
++	struct inet_connection_sock *icsk = inet_csk(sk);
++	struct sock *child;
++
++	child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst);
++	if (child)
++		inet_csk_reqsk_queue_add(sk, req, child);
++	else
++		reqsk_free(req);
++
++	return child;
++}
++
++static DEFINE_PER_CPU(__u32, cookie_scratch)[16 + 5 + SHA_WORKSPACE_WORDS];
++
++static u32 cookie_hash(struct in6_addr *saddr, struct in6_addr *daddr,
++		       __be16 sport, __be16 dport, u32 count, int c)
++{
++	__u32 *tmp = __get_cpu_var(cookie_scratch);
++
++	/*
++	 * we have 320 bits of information to hash, copy in the remaining
++	 * 192 bits required for sha_transform, from the syncookie_secret
++	 * and overwrite the digest with the secret
++	 */
++	memcpy(tmp + 10, syncookie_secret[c], 44);
++	memcpy(tmp, saddr, 16);
++	memcpy(tmp + 4, daddr, 16);
++	tmp[8] = ((__force u32)sport << 16) + (__force u32)dport;
++	tmp[9] = count;
++	sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
++
++	return tmp[17];
++}
++
++static __u32 secure_tcp_syn_cookie(struct in6_addr *saddr, struct in6_addr *daddr,
++				   __be16 sport, __be16 dport, __u32 sseq,
++				   __u32 count, __u32 data)
++{
++	return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
++		sseq + (count << COOKIEBITS) +
++		((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
++		& COOKIEMASK));
++}
++
++static __u32 check_tcp_syn_cookie(__u32 cookie, struct in6_addr *saddr,
++				  struct in6_addr *daddr, __be16 sport,
++				  __be16 dport, __u32 sseq, __u32 count,
++				  __u32 maxdiff)
++{
++	__u32 diff;
++
++	cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
++
++	diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS);
++	if (diff >= maxdiff)
++		return (__u32)-1;
++
++	return (cookie -
++		cookie_hash(saddr, daddr, sport, dport, count - diff, 1))
++		& COOKIEMASK;
++}
++
++__u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)
++{
++	struct ipv6hdr *iph = ipv6_hdr(skb);
++	const struct tcphdr *th = tcp_hdr(skb);
++	int mssind;
++	const __u16 mss = *mssp;
++
++	tcp_sk(sk)->last_synq_overflow = jiffies;
++
++	for (mssind = 0; mss > msstab[mssind + 1]; mssind++)
++		;
++	*mssp = msstab[mssind] + 1;
++
++	NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESSENT);
++
++	return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source,
++				     th->dest, ntohl(th->seq),
++				     jiffies / (HZ * 60), mssind);
++}
++
++static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
++{
++	struct ipv6hdr *iph = ipv6_hdr(skb);
++	const struct tcphdr *th = tcp_hdr(skb);
++	__u32 seq = ntohl(th->seq) - 1;
++	__u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr,
++					    th->source, th->dest, seq,
++					    jiffies / (HZ * 60), COUNTER_TRIES);
++
++	return mssind < NUM_MSS ? msstab[mssind] + 1 : 0;
++}
++
++struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
++{
++	struct inet_request_sock *ireq;
++	struct inet6_request_sock *ireq6;
++	struct tcp_request_sock *treq;
++	struct ipv6_pinfo *np = inet6_sk(sk);
++	struct tcp_sock *tp = tcp_sk(sk);
++	const struct tcphdr *th = tcp_hdr(skb);
++	__u32 cookie = ntohl(th->ack_seq) - 1;
++	struct sock *ret = sk;
++	struct request_sock *req;
++	int mss;
++	struct dst_entry *dst;
++	__u8 rcv_wscale;
++	struct tcp_options_received tcp_opt;
++
++	if (!sysctl_tcp_syncookies || !th->ack)
++		goto out;
++
++	if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) ||
++		(mss = cookie_check(skb, cookie)) == 0) {
++		NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESFAILED);
++		goto out;
++	}
++
++	NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV);
++
++	/* check for timestamp cookie support */
++	memset(&tcp_opt, 0, sizeof(tcp_opt));
++	tcp_parse_options(skb, &tcp_opt, 0);
++
++	if (tcp_opt.saw_tstamp)
++		cookie_check_timestamp(&tcp_opt);
++
++	ret = NULL;
++	req = inet6_reqsk_alloc(&tcp6_request_sock_ops);
++	if (!req)
++		goto out;
++
++	ireq = inet_rsk(req);
++	ireq6 = inet6_rsk(req);
++	treq = tcp_rsk(req);
++	ireq6->pktopts = NULL;
++
++	if (security_inet_conn_request(sk, skb, req)) {
++		reqsk_free(req);
++		goto out;
++	}
++
++	req->mss = mss;
++	ireq->rmt_port = th->source;
++	ipv6_addr_copy(&ireq6->rmt_addr, &ipv6_hdr(skb)->saddr);
++	ipv6_addr_copy(&ireq6->loc_addr, &ipv6_hdr(skb)->daddr);
++	if (ipv6_opt_accepted(sk, skb) ||
++	    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
++	    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
++		atomic_inc(&skb->users);
++		ireq6->pktopts = skb;
++	}
++
++	ireq6->iif = sk->sk_bound_dev_if;
++	/* So that link locals have meaning */
++	if (!sk->sk_bound_dev_if &&
++	    ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)
++		ireq6->iif = inet6_iif(skb);
++
++	req->expires = 0UL;
++	req->retrans = 0;
++	ireq->snd_wscale	= tcp_opt.snd_wscale;
++	ireq->rcv_wscale	= tcp_opt.rcv_wscale;
++	ireq->sack_ok		= tcp_opt.sack_ok;
++	ireq->wscale_ok		= tcp_opt.wscale_ok;
++	ireq->tstamp_ok		= tcp_opt.saw_tstamp;
++	req->ts_recent		= tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
++	treq->rcv_isn = ntohl(th->seq) - 1;
++	treq->snt_isn = cookie;
++
++	/*
++	 * We need to lookup the dst_entry to get the correct window size.
++	 * This is taken from tcp_v6_syn_recv_sock.  Somebody please enlighten
++	 * me if there is a preferred way.
++	 */
++	{
++		struct in6_addr *final_p = NULL, final;
++		struct flowi fl;
++		memset(&fl, 0, sizeof(fl));
++		fl.proto = IPPROTO_TCP;
++		ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
++		if (np->opt && np->opt->srcrt) {
++			struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
++			ipv6_addr_copy(&final, &fl.fl6_dst);
++			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
++			final_p = &final;
++		}
++		ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
++		fl.oif = sk->sk_bound_dev_if;
++		fl.fl_ip_dport = inet_rsk(req)->rmt_port;
++		fl.fl_ip_sport = inet_sk(sk)->sport;
++		security_req_classify_flow(req, &fl);
++		if (ip6_dst_lookup(sk, &dst, &fl)) {
++			reqsk_free(req);
++			goto out;
++		}
++		if (final_p)
++			ipv6_addr_copy(&fl.fl6_dst, final_p);
++		if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++			goto out;
++	}
++
++	req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW);
++	tcp_select_initial_window(tcp_full_space(sk), req->mss,
++				  &req->rcv_wnd, &req->window_clamp,
++				  ireq->wscale_ok, &rcv_wscale);
++
++	ireq->rcv_wscale = rcv_wscale;
++
++	ret = get_cookie_sock(sk, skb, req, dst);
++
++out:	return ret;
++}
++
+diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
+index d6d3e68..3804dcb 100644
+--- a/net/ipv6/sysctl_net_ipv6.c
++++ b/net/ipv6/sysctl_net_ipv6.c
+@@ -71,24 +71,11 @@ static int ipv6_sysctl_net_init(struct net *net)
+ 	ipv6_route_table = ipv6_route_sysctl_init(net);
+ 	if (!ipv6_route_table)
+ 		goto out_ipv6_table;
++	ipv6_table[0].child = ipv6_route_table;
+ 
+ 	ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
+ 	if (!ipv6_icmp_table)
+ 		goto out_ipv6_route_table;
+-
+-	ipv6_route_table[0].data = &net->ipv6.sysctl.flush_delay;
+-	/* ipv6_route_table[1].data will be handled when we have
+-	   routes per namespace */
+-	ipv6_route_table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
+-	ipv6_route_table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
+-	ipv6_route_table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
+-	ipv6_route_table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval;
+-	ipv6_route_table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
+-	ipv6_route_table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
+-	ipv6_route_table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
+-	ipv6_table[0].child = ipv6_route_table;
+-
+-	ipv6_icmp_table[0].data = &net->ipv6.sysctl.icmpv6_time;
+ 	ipv6_table[1].child = ipv6_icmp_table;
+ 
+ 	ipv6_table[2].data = &net->ipv6.sysctl.bindv6only;
+diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
+index 12750f2..715965f 100644
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -60,6 +60,7 @@
+ #include <net/dsfield.h>
+ #include <net/timewait_sock.h>
+ #include <net/netdma.h>
++#include <net/inet_common.h>
+ 
+ #include <asm/uaccess.h>
+ 
+@@ -69,9 +70,6 @@
+ #include <linux/crypto.h>
+ #include <linux/scatterlist.h>
+ 
+-/* Socket used for sending RSTs and ACKs */
+-static struct socket *tcp6_socket;
+-
+ static void	tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
+ static void	tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
+ static void	tcp_v6_send_check(struct sock *sk, int len,
+@@ -324,7 +322,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ 	struct tcp_sock *tp;
+ 	__u32 seq;
+ 
+-	sk = inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, &hdr->daddr,
++	sk = inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, &hdr->daddr,
+ 			th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
+ 
+ 	if (sk == NULL) {
+@@ -455,8 +453,7 @@ out:
+ }
+ 
+ 
+-static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
+-			      struct dst_entry *dst)
++static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req)
+ {
+ 	struct inet6_request_sock *treq = inet6_rsk(req);
+ 	struct ipv6_pinfo *np = inet6_sk(sk);
+@@ -464,6 +461,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
+ 	struct ipv6_txoptions *opt = NULL;
+ 	struct in6_addr * final_p = NULL, final;
+ 	struct flowi fl;
++	struct dst_entry *dst;
+ 	int err = -1;
+ 
+ 	memset(&fl, 0, sizeof(fl));
+@@ -476,24 +474,22 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
+ 	fl.fl_ip_sport = inet_sk(sk)->sport;
+ 	security_req_classify_flow(req, &fl);
+ 
+-	if (dst == NULL) {
+-		opt = np->opt;
+-		if (opt && opt->srcrt) {
+-			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+-			ipv6_addr_copy(&final, &fl.fl6_dst);
+-			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+-			final_p = &final;
+-		}
+-
+-		err = ip6_dst_lookup(sk, &dst, &fl);
+-		if (err)
+-			goto done;
+-		if (final_p)
+-			ipv6_addr_copy(&fl.fl6_dst, final_p);
+-		if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+-			goto done;
++	opt = np->opt;
++	if (opt && opt->srcrt) {
++		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
++		ipv6_addr_copy(&final, &fl.fl6_dst);
++		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
++		final_p = &final;
+ 	}
+ 
++	err = ip6_dst_lookup(sk, &dst, &fl);
++	if (err)
++		goto done;
++	if (final_p)
++		ipv6_addr_copy(&fl.fl6_dst, final_p);
++	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++		goto done;
++
+ 	skb = tcp_make_synack(sk, dst, req);
+ 	if (skb) {
+ 		struct tcphdr *th = tcp_hdr(skb);
+@@ -514,6 +510,20 @@ done:
+ 	return err;
+ }
+ 
++static inline void syn_flood_warning(struct sk_buff *skb)
++{
++#ifdef CONFIG_SYN_COOKIES
++	if (sysctl_tcp_syncookies)
++		printk(KERN_INFO
++		       "TCPv6: Possible SYN flooding on port %d. "
++		       "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest));
++	else
++#endif
++		printk(KERN_INFO
++		       "TCPv6: Possible SYN flooding on port %d. "
++		       "Dropping request.\n", ntohs(tcp_hdr(skb)->dest));
++}
++
+ static void tcp_v6_reqsk_destructor(struct request_sock *req)
+ {
+ 	if (inet6_rsk(req)->pktopts)
+@@ -533,7 +543,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
+ 		return NULL;
+ 
+ 	for (i = 0; i < tp->md5sig_info->entries6; i++) {
+-		if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0)
++		if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, addr))
+ 			return &tp->md5sig_info->keys6[i].base;
+ 	}
+ 	return NULL;
+@@ -622,7 +632,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer)
+ 	int i;
+ 
+ 	for (i = 0; i < tp->md5sig_info->entries6; i++) {
+-		if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) {
++		if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, peer)) {
+ 			/* Free the key */
+ 			kfree(tp->md5sig_info->keys6[i].base.key);
+ 			tp->md5sig_info->entries6--;
+@@ -741,7 +751,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+ 
+ 	hp = tcp_get_md5sig_pool();
+ 	if (!hp) {
+-		printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__);
++		printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
+ 		goto clear_hash_noput;
+ 	}
+ 	bp = &hp->md5_blk.ip6;
+@@ -781,17 +791,17 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+ 	/* Now store the hash into the packet */
+ 	err = crypto_hash_init(desc);
+ 	if (err) {
+-		printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__);
++		printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
+ 		goto clear_hash;
+ 	}
+ 	err = crypto_hash_update(desc, sg, nbytes);
+ 	if (err) {
+-		printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__);
++		printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
+ 		goto clear_hash;
+ 	}
+ 	err = crypto_hash_final(desc, md5_hash);
+ 	if (err) {
+-		printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__);
++		printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
+ 		goto clear_hash;
+ 	}
+ 
+@@ -917,7 +927,7 @@ done_opts:
+ }
+ #endif
+ 
+-static struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
++struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
+ 	.family		=	AF_INET6,
+ 	.obj_size	=	sizeof(struct tcp6_request_sock),
+ 	.rtx_syn_ack	=	tcp_v6_send_synack,
+@@ -979,6 +989,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
+ 	struct tcphdr *th = tcp_hdr(skb), *t1;
+ 	struct sk_buff *buff;
+ 	struct flowi fl;
++	struct net *net = dev_net(skb->dst->dev);
++	struct sock *ctl_sk = net->ipv6.tcp_sk;
+ 	unsigned int tot_len = sizeof(*th);
+ #ifdef CONFIG_TCP_MD5SIG
+ 	struct tcp_md5sig_key *key;
+@@ -1059,11 +1071,14 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
+ 	fl.fl_ip_sport = t1->source;
+ 	security_skb_classify_flow(skb, &fl);
+ 
+-	/* sk = NULL, but it is safe for now. RST socket required. */
+-	if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
++	/* Pass a socket to ip6_dst_lookup either it is for RST
++	 * Underlying function will use this to retrieve the network
++	 * namespace
++	 */
++	if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
+ 
+ 		if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
+-			ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
++			ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
+ 			TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+ 			TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
+ 			return;
+@@ -1079,6 +1094,8 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
+ 	struct tcphdr *th = tcp_hdr(skb), *t1;
+ 	struct sk_buff *buff;
+ 	struct flowi fl;
++	struct net *net = dev_net(skb->dev);
++	struct sock *ctl_sk = net->ipv6.tcp_sk;
+ 	unsigned int tot_len = sizeof(struct tcphdr);
+ 	__be32 *topt;
+ #ifdef CONFIG_TCP_MD5SIG
+@@ -1160,9 +1177,9 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
+ 	fl.fl_ip_sport = t1->source;
+ 	security_skb_classify_flow(skb, &fl);
+ 
+-	if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
++	if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
+ 		if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
+-			ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
++			ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
+ 			TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+ 			return;
+ 		}
+@@ -1202,7 +1219,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+ 	if (req)
+ 		return tcp_check_req(sk, skb, req, prev);
+ 
+-	nsk = __inet6_lookup_established(sk->sk_net, &tcp_hashinfo,
++	nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
+ 			&ipv6_hdr(skb)->saddr, th->source,
+ 			&ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb));
+ 
+@@ -1215,9 +1232,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+ 		return NULL;
+ 	}
+ 
+-#if 0 /*def CONFIG_SYN_COOKIES*/
++#ifdef CONFIG_SYN_COOKIES
+ 	if (!th->rst && !th->syn && th->ack)
+-		sk = cookie_v6_check(sk, skb, &(IPCB(skb)->opt));
++		sk = cookie_v6_check(sk, skb);
+ #endif
+ 	return sk;
+ }
+@@ -1233,6 +1250,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+ 	struct tcp_sock *tp = tcp_sk(sk);
+ 	struct request_sock *req = NULL;
+ 	__u32 isn = TCP_SKB_CB(skb)->when;
++#ifdef CONFIG_SYN_COOKIES
++	int want_cookie = 0;
++#else
++#define want_cookie 0
++#endif
+ 
+ 	if (skb->protocol == htons(ETH_P_IP))
+ 		return tcp_v4_conn_request(sk, skb);
+@@ -1240,12 +1262,14 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+ 	if (!ipv6_unicast_destination(skb))
+ 		goto drop;
+ 
+-	/*
+-	 *	There are no SYN attacks on IPv6, yet...
+-	 */
+ 	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
+ 		if (net_ratelimit())
+-			printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n");
++			syn_flood_warning(skb);
++#ifdef CONFIG_SYN_COOKIES
++		if (sysctl_tcp_syncookies)
++			want_cookie = 1;
++		else
++#endif
+ 		goto drop;
+ 	}
+ 
+@@ -1266,39 +1290,50 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+ 
+ 	tcp_parse_options(skb, &tmp_opt, 0);
+ 
++	if (want_cookie && !tmp_opt.saw_tstamp)
++		tcp_clear_options(&tmp_opt);
++
+ 	tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
+ 	tcp_openreq_init(req, &tmp_opt, skb);
+ 
+ 	treq = inet6_rsk(req);
+ 	ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr);
+ 	ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr);
+-	TCP_ECN_create_request(req, tcp_hdr(skb));
+ 	treq->pktopts = NULL;
+-	if (ipv6_opt_accepted(sk, skb) ||
+-	    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
+-	    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
+-		atomic_inc(&skb->users);
+-		treq->pktopts = skb;
+-	}
+-	treq->iif = sk->sk_bound_dev_if;
++	if (!want_cookie)
++		TCP_ECN_create_request(req, tcp_hdr(skb));
++
++	if (want_cookie) {
++		isn = cookie_v6_init_sequence(sk, skb, &req->mss);
++		req->cookie_ts = tmp_opt.tstamp_ok;
++	} else if (!isn) {
++		if (ipv6_opt_accepted(sk, skb) ||
++		    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
++		    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
++			atomic_inc(&skb->users);
++			treq->pktopts = skb;
++		}
++		treq->iif = sk->sk_bound_dev_if;
+ 
+-	/* So that link locals have meaning */
+-	if (!sk->sk_bound_dev_if &&
+-	    ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
+-		treq->iif = inet6_iif(skb);
++		/* So that link locals have meaning */
++		if (!sk->sk_bound_dev_if &&
++		    ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
++			treq->iif = inet6_iif(skb);
+ 
+-	if (isn == 0)
+ 		isn = tcp_v6_init_sequence(skb);
++	}
+ 
+ 	tcp_rsk(req)->snt_isn = isn;
+ 
+ 	security_inet_conn_request(sk, skb, req);
+ 
+-	if (tcp_v6_send_synack(sk, req, NULL))
++	if (tcp_v6_send_synack(sk, req))
+ 		goto drop;
+ 
+-	inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
+-	return 0;
++	if (!want_cookie) {
++		inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
++		return 0;
++	}
+ 
+ drop:
+ 	if (req)
+@@ -1499,7 +1534,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+ #endif
+ 
+ 	__inet6_hash(newsk);
+-	inet_inherit_port(sk, newsk);
++	__inet_inherit_port(sk, newsk);
+ 
+ 	return newsk;
+ 
+@@ -1704,7 +1739,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
+ 	TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb));
+ 	TCP_SKB_CB(skb)->sacked = 0;
+ 
+-	sk = __inet6_lookup(skb->dev->nd_net, &tcp_hashinfo,
++	sk = __inet6_lookup(dev_net(skb->dev), &tcp_hashinfo,
+ 			&ipv6_hdr(skb)->saddr, th->source,
+ 			&ipv6_hdr(skb)->daddr, ntohs(th->dest),
+ 			inet6_iif(skb));
+@@ -1787,7 +1822,7 @@ do_time_wait:
+ 	{
+ 		struct sock *sk2;
+ 
+-		sk2 = inet6_lookup_listener(skb->dev->nd_net, &tcp_hashinfo,
++		sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
+ 					    &ipv6_hdr(skb)->daddr,
+ 					    ntohs(th->dest), inet6_iif(skb));
+ 		if (sk2 != NULL) {
+@@ -2085,28 +2120,28 @@ out:
+ 	return 0;
+ }
+ 
+-static struct file_operations tcp6_seq_fops;
+ static struct tcp_seq_afinfo tcp6_seq_afinfo = {
+-	.owner		= THIS_MODULE,
+ 	.name		= "tcp6",
+ 	.family		= AF_INET6,
+-	.seq_show	= tcp6_seq_show,
+-	.seq_fops	= &tcp6_seq_fops,
++	.seq_fops	= {
++		.owner		= THIS_MODULE,
++	},
++	.seq_ops	= {
++		.show		= tcp6_seq_show,
++	},
+ };
+ 
+-int __init tcp6_proc_init(void)
++int tcp6_proc_init(struct net *net)
+ {
+-	return tcp_proc_register(&tcp6_seq_afinfo);
++	return tcp_proc_register(net, &tcp6_seq_afinfo);
+ }
+ 
+-void tcp6_proc_exit(void)
++void tcp6_proc_exit(struct net *net)
+ {
+-	tcp_proc_unregister(&tcp6_seq_afinfo);
++	tcp_proc_unregister(net, &tcp6_seq_afinfo);
+ }
+ #endif
+ 
+-DEFINE_PROTO_INUSE(tcpv6)
+-
+ struct proto tcpv6_prot = {
+ 	.name			= "TCPv6",
+ 	.owner			= THIS_MODULE,
+@@ -2137,12 +2172,11 @@ struct proto tcpv6_prot = {
+ 	.obj_size		= sizeof(struct tcp6_sock),
+ 	.twsk_prot		= &tcp6_timewait_sock_ops,
+ 	.rsk_prot		= &tcp6_request_sock_ops,
+-	.hashinfo		= &tcp_hashinfo,
++	.h.hashinfo		= &tcp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt	= compat_tcp_setsockopt,
+ 	.compat_getsockopt	= compat_tcp_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(tcpv6)
+ };
+ 
+ static struct inet6_protocol tcpv6_protocol = {
+@@ -2164,6 +2198,22 @@ static struct inet_protosw tcpv6_protosw = {
+ 				INET_PROTOSW_ICSK,
+ };
+ 
++static int tcpv6_net_init(struct net *net)
++{
++	return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6,
++				    SOCK_RAW, IPPROTO_TCP, net);
++}
++
++static void tcpv6_net_exit(struct net *net)
++{
++	inet_ctl_sock_destroy(net->ipv6.tcp_sk);
++}
++
++static struct pernet_operations tcpv6_net_ops = {
++	.init = tcpv6_net_init,
++	.exit = tcpv6_net_exit,
++};
++
+ int __init tcpv6_init(void)
+ {
+ 	int ret;
+@@ -2177,8 +2227,7 @@ int __init tcpv6_init(void)
+ 	if (ret)
+ 		goto out_tcpv6_protocol;
+ 
+-	ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6,
+-				       SOCK_RAW, IPPROTO_TCP);
++	ret = register_pernet_subsys(&tcpv6_net_ops);
+ 	if (ret)
+ 		goto out_tcpv6_protosw;
+ out:
+@@ -2193,7 +2242,7 @@ out_tcpv6_protosw:
+ 
+ void tcpv6_exit(void)
+ {
+-	sock_release(tcp6_socket);
++	unregister_pernet_subsys(&tcpv6_net_ops);
+ 	inet6_unregister_protosw(&tcpv6_protosw);
+ 	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
+ }
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 53739de..1fd784f 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -51,9 +51,9 @@
+ #include <linux/seq_file.h>
+ #include "udp_impl.h"
+ 
+-static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
++int udp_v6_get_port(struct sock *sk, unsigned short snum)
+ {
+-	return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
++	return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal);
+ }
+ 
+ static struct sock *__udp6_lib_lookup(struct net *net,
+@@ -70,7 +70,7 @@ static struct sock *__udp6_lib_lookup(struct net *net,
+ 	sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
+ 		struct inet_sock *inet = inet_sk(sk);
+ 
+-		if (sk->sk_net == net && sk->sk_hash == hnum &&
++		if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&
+ 				sk->sk_family == PF_INET6) {
+ 			struct ipv6_pinfo *np = inet6_sk(sk);
+ 			int score = 0;
+@@ -235,7 +235,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ 	struct sock *sk;
+ 	int err;
+ 
+-	sk = __udp6_lib_lookup(skb->dev->nd_net, daddr, uh->dest,
++	sk = __udp6_lib_lookup(dev_net(skb->dev), daddr, uh->dest,
+ 			       saddr, uh->source, inet6_iif(skb), udptable);
+ 	if (sk == NULL)
+ 		return;
+@@ -323,6 +323,9 @@ static struct sock *udp_v6_mcast_next(struct sock *sk,
+ 	sk_for_each_from(s, node) {
+ 		struct inet_sock *inet = inet_sk(s);
+ 
++		if (sock_net(s) != sock_net(sk))
++			continue;
++
+ 		if (s->sk_hash == num && s->sk_family == PF_INET6) {
+ 			struct ipv6_pinfo *np = inet6_sk(s);
+ 			if (inet->dport) {
+@@ -480,7 +483,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+ 	 * check socket cache ... must talk to Alan about his plans
+ 	 * for sock caches... i'll skip this for now.
+ 	 */
+-	sk = __udp6_lib_lookup(skb->dev->nd_net, saddr, uh->source,
++	sk = __udp6_lib_lookup(dev_net(skb->dev), saddr, uh->source,
+ 			       daddr, uh->dest, inet6_iif(skb), udptable);
+ 
+ 	if (sk == NULL) {
+@@ -749,7 +752,10 @@ do_udp_sendmsg:
+ 	opt = ipv6_fixup_options(&opt_space, opt);
+ 
+ 	fl.proto = sk->sk_protocol;
+-	ipv6_addr_copy(&fl.fl6_dst, daddr);
++	if (!ipv6_addr_any(daddr))
++		ipv6_addr_copy(&fl.fl6_dst, daddr);
++	else
++		fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+ 	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
+ 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+ 	fl.fl_ip_sport = inet->sport;
+@@ -789,9 +795,7 @@ do_udp_sendmsg:
+ 		else
+ 			hlimit = np->hop_limit;
+ 		if (hlimit < 0)
+-			hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+-		if (hlimit < 0)
+-			hlimit = ipv6_get_hoplimit(dst->dev);
++			hlimit = ip6_dst_hoplimit(dst);
+ 	}
+ 
+ 	if (tclass < 0) {
+@@ -976,30 +980,30 @@ int udp6_seq_show(struct seq_file *seq, void *v)
+ 	return 0;
+ }
+ 
+-static struct file_operations udp6_seq_fops;
+ static struct udp_seq_afinfo udp6_seq_afinfo = {
+-	.owner		= THIS_MODULE,
+ 	.name		= "udp6",
+ 	.family		= AF_INET6,
+ 	.hashtable	= udp_hash,
+-	.seq_show	= udp6_seq_show,
+-	.seq_fops	= &udp6_seq_fops,
++	.seq_fops	= {
++		.owner	=	THIS_MODULE,
++	},
++	.seq_ops	= {
++		.show		= udp6_seq_show,
++	},
+ };
+ 
+-int __init udp6_proc_init(void)
++int udp6_proc_init(struct net *net)
+ {
+-	return udp_proc_register(&udp6_seq_afinfo);
++	return udp_proc_register(net, &udp6_seq_afinfo);
+ }
+ 
+-void udp6_proc_exit(void) {
+-	udp_proc_unregister(&udp6_seq_afinfo);
++void udp6_proc_exit(struct net *net) {
++	udp_proc_unregister(net, &udp6_seq_afinfo);
+ }
+ #endif /* CONFIG_PROC_FS */
+ 
+ /* ------------------------------------------------------------------------ */
+ 
+-DEFINE_PROTO_INUSE(udpv6)
+-
+ struct proto udpv6_prot = {
+ 	.name		   = "UDPv6",
+ 	.owner		   = THIS_MODULE,
+@@ -1021,11 +1025,11 @@ struct proto udpv6_prot = {
+ 	.sysctl_wmem	   = &sysctl_udp_wmem_min,
+ 	.sysctl_rmem	   = &sysctl_udp_rmem_min,
+ 	.obj_size	   = sizeof(struct udp6_sock),
++	.h.udp_hash	   = udp_hash,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_udpv6_setsockopt,
+ 	.compat_getsockopt = compat_udpv6_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(udpv6)
+ };
+ 
+ static struct inet_protosw udpv6_protosw = {
+diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
+index 21be3a8..321b81a 100644
+--- a/net/ipv6/udp_impl.h
++++ b/net/ipv6/udp_impl.h
+@@ -11,6 +11,8 @@ extern int  	__udp6_lib_rcv(struct sk_buff *, struct hlist_head [], int );
+ extern void 	__udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
+ 			       int , int , int , __be32 , struct hlist_head []);
+ 
++extern int	udp_v6_get_port(struct sock *sk, unsigned short snum);
++
+ extern int	udpv6_getsockopt(struct sock *sk, int level, int optname,
+ 				 char __user *optval, int __user *optlen);
+ extern int	udpv6_setsockopt(struct sock *sk, int level, int optname,
+diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
+index 87d4202..491efd0 100644
+--- a/net/ipv6/udplite.c
++++ b/net/ipv6/udplite.c
+@@ -35,13 +35,6 @@ static struct inet6_protocol udplitev6_protocol = {
+ 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+ };
+ 
+-static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
+-{
+-	return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
+-}
+-
+-DEFINE_PROTO_INUSE(udplitev6)
+-
+ struct proto udplitev6_prot = {
+ 	.name		   = "UDPLITEv6",
+ 	.owner		   = THIS_MODULE,
+@@ -58,13 +51,13 @@ struct proto udplitev6_prot = {
+ 	.backlog_rcv	   = udpv6_queue_rcv_skb,
+ 	.hash		   = udp_lib_hash,
+ 	.unhash		   = udp_lib_unhash,
+-	.get_port	   = udplite_v6_get_port,
++	.get_port	   = udp_v6_get_port,
+ 	.obj_size	   = sizeof(struct udp6_sock),
++	.h.udp_hash	   = udplite_hash,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_udpv6_setsockopt,
+ 	.compat_getsockopt = compat_udpv6_getsockopt,
+ #endif
+-	REF_PROTO_INUSE(udplitev6)
+ };
+ 
+ static struct inet_protosw udplite6_protosw = {
+@@ -103,23 +96,40 @@ void udplitev6_exit(void)
+ }
+ 
+ #ifdef CONFIG_PROC_FS
+-static struct file_operations udplite6_seq_fops;
+ static struct udp_seq_afinfo udplite6_seq_afinfo = {
+-	.owner		= THIS_MODULE,
+ 	.name		= "udplite6",
+ 	.family		= AF_INET6,
+ 	.hashtable	= udplite_hash,
+-	.seq_show	= udp6_seq_show,
+-	.seq_fops	= &udplite6_seq_fops,
++	.seq_fops	= {
++		.owner	=	THIS_MODULE,
++	},
++	.seq_ops	= {
++		.show		= udp6_seq_show,
++	},
++};
++
++static int udplite6_proc_init_net(struct net *net)
++{
++	return udp_proc_register(net, &udplite6_seq_afinfo);
++}
++
++static void udplite6_proc_exit_net(struct net *net)
++{
++	udp_proc_unregister(net, &udplite6_seq_afinfo);
++}
++
++static struct pernet_operations udplite6_net_ops = {
++	.init = udplite6_proc_init_net,
++	.exit = udplite6_proc_exit_net,
+ };
+ 
+ int __init udplite6_proc_init(void)
+ {
+-	return udp_proc_register(&udplite6_seq_afinfo);
++	return register_pernet_subsys(&udplite6_net_ops);
+ }
+ 
+ void udplite6_proc_exit(void)
+ {
+-	udp_proc_unregister(&udplite6_seq_afinfo);
++	unregister_pernet_subsys(&udplite6_net_ops);
+ }
+ #endif
+diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
+index a4714d7..a71c7dd 100644
+--- a/net/ipv6/xfrm6_input.c
++++ b/net/ipv6/xfrm6_input.c
+@@ -59,9 +59,6 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+ 		     xfrm_address_t *saddr, u8 proto)
+ {
+ 	struct xfrm_state *x = NULL;
+-	int wildcard = 0;
+-	xfrm_address_t *xany;
+-	int nh = 0;
+ 	int i = 0;
+ 
+ 	/* Allocate new secpath or COW existing one. */
+@@ -83,10 +80,9 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+ 		goto drop;
+ 	}
+ 
+-	xany = (xfrm_address_t *)&in6addr_any;
+-
+ 	for (i = 0; i < 3; i++) {
+ 		xfrm_address_t *dst, *src;
++
+ 		switch (i) {
+ 		case 0:
+ 			dst = daddr;
+@@ -94,16 +90,13 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+ 			break;
+ 		case 1:
+ 			/* lookup state with wild-card source address */
+-			wildcard = 1;
+ 			dst = daddr;
+-			src = xany;
++			src = (xfrm_address_t *)&in6addr_any;
+ 			break;
+-		case 2:
+ 		default:
+ 			/* lookup state with wild-card addresses */
+-			wildcard = 1; /* XXX */
+-			dst = xany;
+-			src = xany;
++			dst = (xfrm_address_t *)&in6addr_any;
++			src = (xfrm_address_t *)&in6addr_any;
+ 			break;
+ 		}
+ 
+@@ -113,39 +106,19 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+ 
+ 		spin_lock(&x->lock);
+ 
+-		if (wildcard) {
+-			if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) {
+-				spin_unlock(&x->lock);
+-				xfrm_state_put(x);
+-				x = NULL;
+-				continue;
+-			}
+-		}
+-
+-		if (unlikely(x->km.state != XFRM_STATE_VALID)) {
++		if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) &&
++		    likely(x->km.state == XFRM_STATE_VALID) &&
++		    !xfrm_state_check_expire(x)) {
+ 			spin_unlock(&x->lock);
+-			xfrm_state_put(x);
+-			x = NULL;
+-			continue;
+-		}
+-		if (xfrm_state_check_expire(x)) {
++			if (x->type->input(x, skb) > 0) {
++				/* found a valid state */
++				break;
++			}
++		} else
+ 			spin_unlock(&x->lock);
+-			xfrm_state_put(x);
+-			x = NULL;
+-			continue;
+-		}
+-
+-		spin_unlock(&x->lock);
+-
+-		nh = x->type->input(x, skb);
+-		if (nh <= 0) {
+-			xfrm_state_put(x);
+-			x = NULL;
+-			continue;
+-		}
+ 
+-		/* Found a state */
+-		break;
++		xfrm_state_put(x);
++		x = NULL;
+ 	}
+ 
+ 	if (!x) {
+diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
+index 7d20199..8f1e054 100644
+--- a/net/ipv6/xfrm6_policy.c
++++ b/net/ipv6/xfrm6_policy.c
+@@ -38,7 +38,7 @@ static struct dst_entry *xfrm6_dst_lookup(int tos, xfrm_address_t *saddr,
+ 	if (saddr)
+ 		memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src));
+ 
+-	dst = ip6_route_output(NULL, &fl);
++	dst = ip6_route_output(&init_net, NULL, &fl);
+ 
+ 	err = dst->error;
+ 	if (dst->error) {
+@@ -57,8 +57,9 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
+ 	if (IS_ERR(dst))
+ 		return -EHOSTUNREACH;
+ 
+-	ipv6_get_saddr(dst, (struct in6_addr *)&daddr->a6,
+-		       (struct in6_addr *)&saddr->a6);
++	ipv6_dev_get_saddr(ip6_dst_idev(dst)->dev,
++			   (struct in6_addr *)&daddr->a6, 0,
++			   (struct in6_addr *)&saddr->a6);
+ 	dst_release(dst);
+ 	return 0;
+ }
+@@ -246,7 +247,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ 	xdst = (struct xfrm_dst *)dst;
+ 	if (xdst->u.rt6.rt6i_idev->dev == dev) {
+ 		struct inet6_dev *loopback_idev =
+-			in6_dev_get(dev->nd_net->loopback_dev);
++			in6_dev_get(dev_net(dev)->loopback_dev);
+ 		BUG_ON(!loopback_idev);
+ 
+ 		do {
+diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
+index ff1e1db..89884a4 100644
+--- a/net/ipv6/xfrm6_state.c
++++ b/net/ipv6/xfrm6_state.c
+@@ -49,125 +49,102 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
+ 	x->props.family = AF_INET6;
+ }
+ 
++/* distribution counting sort function for xfrm_state and xfrm_tmpl */
+ static int
+-__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
++__xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass)
+ {
+ 	int i;
+-	int j = 0;
++	int class[XFRM_MAX_DEPTH];
++	int count[maxclass];
+ 
+-	/* Rule 1: select IPsec transport except AH */
+-	for (i = 0; i < n; i++) {
+-		if (src[i]->props.mode == XFRM_MODE_TRANSPORT &&
+-		    src[i]->id.proto != IPPROTO_AH) {
+-			dst[j++] = src[i];
+-			src[i] = NULL;
+-		}
+-	}
+-	if (j == n)
+-		goto end;
++	memset(count, 0, sizeof(count));
+ 
+-	/* Rule 2: select MIPv6 RO or inbound trigger */
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+ 	for (i = 0; i < n; i++) {
+-		if (src[i] &&
+-		    (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
+-		     src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) {
+-			dst[j++] = src[i];
+-			src[i] = NULL;
+-		}
++		int c;
++		class[i] = c = cmp(src[i]);
++		count[c]++;
+ 	}
+-	if (j == n)
+-		goto end;
+-#endif
+ 
+-	/* Rule 3: select IPsec transport AH */
+-	for (i = 0; i < n; i++) {
+-		if (src[i] &&
+-		    src[i]->props.mode == XFRM_MODE_TRANSPORT &&
+-		    src[i]->id.proto == IPPROTO_AH) {
+-			dst[j++] = src[i];
+-			src[i] = NULL;
+-		}
+-	}
+-	if (j == n)
+-		goto end;
++	for (i = 2; i < maxclass; i++)
++		count[i] += count[i - 1];
+ 
+-	/* Rule 4: select IPsec tunnel */
+ 	for (i = 0; i < n; i++) {
+-		if (src[i] &&
+-		    (src[i]->props.mode == XFRM_MODE_TUNNEL ||
+-		     src[i]->props.mode == XFRM_MODE_BEET)) {
+-			dst[j++] = src[i];
+-			src[i] = NULL;
+-		}
++		dst[count[class[i] - 1]++] = src[i];
++		src[i] = 0;
+ 	}
+-	if (likely(j == n))
+-		goto end;
+ 
+-	/* Final rule */
+-	for (i = 0; i < n; i++) {
+-		if (src[i]) {
+-			dst[j++] = src[i];
+-			src[i] = NULL;
+-		}
+-	}
+-
+- end:
+ 	return 0;
+ }
+ 
+-static int
+-__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
++/*
++ * Rule for xfrm_state:
++ *
++ * rule 1: select IPsec transport except AH
++ * rule 2: select MIPv6 RO or inbound trigger
++ * rule 3: select IPsec transport AH
++ * rule 4: select IPsec tunnel
++ * rule 5: others
++ */
++static int __xfrm6_state_sort_cmp(void *p)
+ {
+-	int i;
+-	int j = 0;
+-
+-	/* Rule 1: select IPsec transport */
+-	for (i = 0; i < n; i++) {
+-		if (src[i]->mode == XFRM_MODE_TRANSPORT) {
+-			dst[j++] = src[i];
+-			src[i] = NULL;
+-		}
+-	}
+-	if (j == n)
+-		goto end;
+-
+-	/* Rule 2: select MIPv6 RO or inbound trigger */
++	struct xfrm_state *v = p;
++
++	switch (v->props.mode) {
++	case XFRM_MODE_TRANSPORT:
++		if (v->id.proto != IPPROTO_AH)
++			return 1;
++		else
++			return 3;
+ #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+-	for (i = 0; i < n; i++) {
+-		if (src[i] &&
+-		    (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
+-		     src[i]->mode == XFRM_MODE_IN_TRIGGER)) {
+-			dst[j++] = src[i];
+-			src[i] = NULL;
+-		}
+-	}
+-	if (j == n)
+-		goto end;
++	case XFRM_MODE_ROUTEOPTIMIZATION:
++	case XFRM_MODE_IN_TRIGGER:
++		return 2;
+ #endif
+-
+-	/* Rule 3: select IPsec tunnel */
+-	for (i = 0; i < n; i++) {
+-		if (src[i] &&
+-		    (src[i]->mode == XFRM_MODE_TUNNEL ||
+-		     src[i]->mode == XFRM_MODE_BEET)) {
+-			dst[j++] = src[i];
+-			src[i] = NULL;
+-		}
++	case XFRM_MODE_TUNNEL:
++	case XFRM_MODE_BEET:
++		return 4;
+ 	}
+-	if (likely(j == n))
+-		goto end;
++	return 5;
++}
+ 
+-	/* Final rule */
+-	for (i = 0; i < n; i++) {
+-		if (src[i]) {
+-			dst[j++] = src[i];
+-			src[i] = NULL;
+-		}
++static int
++__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
++{
++	return __xfrm6_sort((void **)dst, (void **)src, n,
++			    __xfrm6_state_sort_cmp, 6);
++}
++
++/*
++ * Rule for xfrm_tmpl:
++ *
++ * rule 1: select IPsec transport
++ * rule 2: select MIPv6 RO or inbound trigger
++ * rule 3: select IPsec tunnel
++ * rule 4: others
++ */
++static int __xfrm6_tmpl_sort_cmp(void *p)
++{
++	struct xfrm_tmpl *v = p;
++	switch (v->mode) {
++	case XFRM_MODE_TRANSPORT:
++		return 1;
++#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++	case XFRM_MODE_ROUTEOPTIMIZATION:
++	case XFRM_MODE_IN_TRIGGER:
++		return 2;
++#endif
++	case XFRM_MODE_TUNNEL:
++	case XFRM_MODE_BEET:
++		return 3;
+ 	}
++	return 4;
++}
+ 
+- end:
+-	return 0;
++static int
++__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
++{
++	return __xfrm6_sort((void **)dst, (void **)src, n,
++			    __xfrm6_tmpl_sort_cmp, 5);
+ }
+ 
+ int xfrm6_extract_header(struct sk_buff *skb)
+diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
+index 639fe8a..c2b2781 100644
+--- a/net/ipv6/xfrm6_tunnel.c
++++ b/net/ipv6/xfrm6_tunnel.c
+@@ -140,12 +140,26 @@ __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
+ 
+ EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup);
+ 
++static int __xfrm6_tunnel_spi_check(u32 spi)
++{
++	struct xfrm6_tunnel_spi *x6spi;
++	int index = xfrm6_tunnel_spi_hash_byspi(spi);
++	struct hlist_node *pos;
++
++	hlist_for_each_entry(x6spi, pos,
++			     &xfrm6_tunnel_spi_byspi[index],
++			     list_byspi) {
++		if (x6spi->spi == spi)
++			return -1;
++	}
++	return index;
++}
++
+ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+ {
+ 	u32 spi;
+ 	struct xfrm6_tunnel_spi *x6spi;
+-	struct hlist_node *pos;
+-	unsigned index;
++	int index;
+ 
+ 	if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN ||
+ 	    xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX)
+@@ -154,32 +168,19 @@ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+ 		xfrm6_tunnel_spi++;
+ 
+ 	for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) {
+-		index = xfrm6_tunnel_spi_hash_byspi(spi);
+-		hlist_for_each_entry(x6spi, pos,
+-				     &xfrm6_tunnel_spi_byspi[index],
+-				     list_byspi) {
+-			if (x6spi->spi == spi)
+-				goto try_next_1;
+-		}
+-		xfrm6_tunnel_spi = spi;
+-		goto alloc_spi;
+-try_next_1:;
++		index = __xfrm6_tunnel_spi_check(spi);
++		if (index >= 0)
++			goto alloc_spi;
+ 	}
+ 	for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) {
+-		index = xfrm6_tunnel_spi_hash_byspi(spi);
+-		hlist_for_each_entry(x6spi, pos,
+-				     &xfrm6_tunnel_spi_byspi[index],
+-				     list_byspi) {
+-			if (x6spi->spi == spi)
+-				goto try_next_2;
+-		}
+-		xfrm6_tunnel_spi = spi;
+-		goto alloc_spi;
+-try_next_2:;
++		index = __xfrm6_tunnel_spi_check(spi);
++		if (index >= 0)
++			goto alloc_spi;
+ 	}
+ 	spi = 0;
+ 	goto out;
+ alloc_spi:
++	xfrm6_tunnel_spi = spi;
+ 	x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC);
+ 	if (!x6spi)
+ 		goto out;
+diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
+index c76a952..81ae873 100644
+--- a/net/ipx/af_ipx.c
++++ b/net/ipx/af_ipx.c
+@@ -335,7 +335,7 @@ static int ipxitf_device_event(struct notifier_block *notifier,
+ 	struct net_device *dev = ptr;
+ 	struct ipx_interface *i, *tmp;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event != NETDEV_DOWN && event != NETDEV_UP)
+@@ -1636,7 +1636,7 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
+ 	u16 ipx_pktsize;
+ 	int rc = 0;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto drop;
+ 
+ 	/* Not ours */
+diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
+index 240b0cb..ae54b20 100644
+--- a/net/irda/af_irda.c
++++ b/net/irda/af_irda.c
+@@ -85,14 +85,14 @@ static int irda_data_indication(void *instance, void *sap, struct sk_buff *skb)
+ 	struct sock *sk;
+ 	int err;
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	self = instance;
+ 	sk = instance;
+ 
+ 	err = sock_queue_rcv_skb(sk, skb);
+ 	if (err) {
+-		IRDA_DEBUG(1, "%s(), error: no more mem!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), error: no more mem!\n", __func__);
+ 		self->rx_flow = FLOW_STOP;
+ 
+ 		/* When we return error, TTP will need to requeue the skb */
+@@ -116,7 +116,7 @@ static void irda_disconnect_indication(void *instance, void *sap,
+ 
+ 	self = instance;
+ 
+-	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ 
+ 	/* Don't care about it, but let's not leak it */
+ 	if(skb)
+@@ -125,7 +125,7 @@ static void irda_disconnect_indication(void *instance, void *sap,
+ 	sk = instance;
+ 	if (sk == NULL) {
+ 		IRDA_DEBUG(0, "%s(%p) : BUG : sk is NULL\n",
+-			   __FUNCTION__, self);
++			   __func__, self);
+ 		return;
+ 	}
+ 
+@@ -181,7 +181,7 @@ static void irda_connect_confirm(void *instance, void *sap,
+ 
+ 	self = instance;
+ 
+-	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ 
+ 	sk = instance;
+ 	if (sk == NULL) {
+@@ -203,7 +203,7 @@ static void irda_connect_confirm(void *instance, void *sap,
+ 	case SOCK_STREAM:
+ 		if (max_sdu_size != 0) {
+ 			IRDA_ERROR("%s: max_sdu_size must be 0\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			return;
+ 		}
+ 		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+@@ -211,7 +211,7 @@ static void irda_connect_confirm(void *instance, void *sap,
+ 	case SOCK_SEQPACKET:
+ 		if (max_sdu_size == 0) {
+ 			IRDA_ERROR("%s: max_sdu_size cannot be 0\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			return;
+ 		}
+ 		self->max_data_size = max_sdu_size;
+@@ -220,7 +220,7 @@ static void irda_connect_confirm(void *instance, void *sap,
+ 		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+ 	}
+ 
+-	IRDA_DEBUG(2, "%s(), max_data_size=%d\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s(), max_data_size=%d\n", __func__,
+ 		   self->max_data_size);
+ 
+ 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
+@@ -245,7 +245,7 @@ static void irda_connect_indication(void *instance, void *sap,
+ 
+ 	self = instance;
+ 
+-	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ 
+ 	sk = instance;
+ 	if (sk == NULL) {
+@@ -264,7 +264,7 @@ static void irda_connect_indication(void *instance, void *sap,
+ 	case SOCK_STREAM:
+ 		if (max_sdu_size != 0) {
+ 			IRDA_ERROR("%s: max_sdu_size must be 0\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			kfree_skb(skb);
+ 			return;
+ 		}
+@@ -273,7 +273,7 @@ static void irda_connect_indication(void *instance, void *sap,
+ 	case SOCK_SEQPACKET:
+ 		if (max_sdu_size == 0) {
+ 			IRDA_ERROR("%s: max_sdu_size cannot be 0\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			kfree_skb(skb);
+ 			return;
+ 		}
+@@ -283,7 +283,7 @@ static void irda_connect_indication(void *instance, void *sap,
+ 		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+ 	}
+ 
+-	IRDA_DEBUG(2, "%s(), max_data_size=%d\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s(), max_data_size=%d\n", __func__,
+ 		   self->max_data_size);
+ 
+ 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
+@@ -302,13 +302,13 @@ static void irda_connect_response(struct irda_sock *self)
+ {
+ 	struct sk_buff *skb;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+ 			GFP_ATOMIC);
+ 	if (skb == NULL) {
+ 		IRDA_DEBUG(0, "%s() Unable to allocate sk_buff!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		return;
+ 	}
+ 
+@@ -329,7 +329,7 @@ static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ 	struct irda_sock *self;
+ 	struct sock *sk;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	self = instance;
+ 	sk = instance;
+@@ -338,17 +338,17 @@ static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ 	switch (flow) {
+ 	case FLOW_STOP:
+ 		IRDA_DEBUG(1, "%s(), IrTTP wants us to slow down\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		self->tx_flow = flow;
+ 		break;
+ 	case FLOW_START:
+ 		self->tx_flow = flow;
+ 		IRDA_DEBUG(1, "%s(), IrTTP wants us to start again\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		wake_up_interruptible(sk->sk_sleep);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), Unknown flow command!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), Unknown flow command!\n", __func__);
+ 		/* Unknown flow command, better stop */
+ 		self->tx_flow = flow;
+ 		break;
+@@ -370,11 +370,11 @@ static void irda_getvalue_confirm(int result, __u16 obj_id,
+ 
+ 	self = (struct irda_sock *) priv;
+ 	if (!self) {
+-		IRDA_WARNING("%s: lost myself!\n", __FUNCTION__);
++		IRDA_WARNING("%s: lost myself!\n", __func__);
+ 		return;
+ 	}
+ 
+-	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ 
+ 	/* We probably don't need to make any more queries */
+ 	iriap_close(self->iriap);
+@@ -382,7 +382,7 @@ static void irda_getvalue_confirm(int result, __u16 obj_id,
+ 
+ 	/* Check if request succeeded */
+ 	if (result != IAS_SUCCESS) {
+-		IRDA_DEBUG(1, "%s(), IAS query failed! (%d)\n", __FUNCTION__,
++		IRDA_DEBUG(1, "%s(), IAS query failed! (%d)\n", __func__,
+ 			   result);
+ 
+ 		self->errno = result;	/* We really need it later */
+@@ -415,11 +415,11 @@ static void irda_selective_discovery_indication(discinfo_t *discovery,
+ {
+ 	struct irda_sock *self;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	self = (struct irda_sock *) priv;
+ 	if (!self) {
+-		IRDA_WARNING("%s: lost myself!\n", __FUNCTION__);
++		IRDA_WARNING("%s: lost myself!\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -442,7 +442,7 @@ static void irda_discovery_timeout(u_long priv)
+ {
+ 	struct irda_sock *self;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	self = (struct irda_sock *) priv;
+ 	BUG_ON(self == NULL);
+@@ -467,7 +467,7 @@ static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
+ 	notify_t notify;
+ 
+ 	if (self->tsap) {
+-		IRDA_WARNING("%s: busy!\n", __FUNCTION__);
++		IRDA_WARNING("%s: busy!\n", __func__);
+ 		return -EBUSY;
+ 	}
+ 
+@@ -486,7 +486,7 @@ static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
+ 				     &notify);
+ 	if (self->tsap == NULL) {
+ 		IRDA_DEBUG(0, "%s(), Unable to allocate TSAP!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		return -ENOMEM;
+ 	}
+ 	/* Remember which TSAP selector we actually got */
+@@ -507,7 +507,7 @@ static int irda_open_lsap(struct irda_sock *self, int pid)
+ 	notify_t notify;
+ 
+ 	if (self->lsap) {
+-		IRDA_WARNING("%s(), busy!\n", __FUNCTION__);
++		IRDA_WARNING("%s(), busy!\n", __func__);
+ 		return -EBUSY;
+ 	}
+ 
+@@ -519,7 +519,7 @@ static int irda_open_lsap(struct irda_sock *self, int pid)
+ 
+ 	self->lsap = irlmp_open_lsap(LSAP_CONNLESS, &notify, pid);
+ 	if (self->lsap == NULL) {
+-		IRDA_DEBUG( 0, "%s(), Unable to allocate LSAP!\n", __FUNCTION__);
++		IRDA_DEBUG( 0, "%s(), Unable to allocate LSAP!\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -540,11 +540,11 @@ static int irda_open_lsap(struct irda_sock *self, int pid)
+  */
+ static int irda_find_lsap_sel(struct irda_sock *self, char *name)
+ {
+-	IRDA_DEBUG(2, "%s(%p, %s)\n", __FUNCTION__, self, name);
++	IRDA_DEBUG(2, "%s(%p, %s)\n", __func__, self, name);
+ 
+ 	if (self->iriap) {
+ 		IRDA_WARNING("%s(): busy with a previous query\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		return -EBUSY;
+ 	}
+ 
+@@ -580,7 +580,7 @@ static int irda_find_lsap_sel(struct irda_sock *self, char *name)
+ 	switch (self->ias_result->type) {
+ 	case IAS_INTEGER:
+ 		IRDA_DEBUG(4, "%s() int=%d\n",
+-			   __FUNCTION__, self->ias_result->t.integer);
++			   __func__, self->ias_result->t.integer);
+ 
+ 		if (self->ias_result->t.integer != -1)
+ 			self->dtsap_sel = self->ias_result->t.integer;
+@@ -589,7 +589,7 @@ static int irda_find_lsap_sel(struct irda_sock *self, char *name)
+ 		break;
+ 	default:
+ 		self->dtsap_sel = 0;
+-		IRDA_DEBUG(0, "%s(), bad type!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), bad type!\n", __func__);
+ 		break;
+ 	}
+ 	if (self->ias_result)
+@@ -627,7 +627,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ 	__u32	daddr = DEV_ADDR_ANY;	/* Address we found the service on */
+ 	__u8	dtsap_sel = 0x0;	/* TSAP associated with it */
+ 
+-	IRDA_DEBUG(2, "%s(), name=%s\n", __FUNCTION__, name);
++	IRDA_DEBUG(2, "%s(), name=%s\n", __func__, name);
+ 
+ 	/* Ask lmp for the current discovery log
+ 	 * Note : we have to use irlmp_get_discoveries(), as opposed
+@@ -649,7 +649,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ 		self->daddr = discoveries[i].daddr;
+ 		self->saddr = 0x0;
+ 		IRDA_DEBUG(1, "%s(), trying daddr = %08x\n",
+-			   __FUNCTION__, self->daddr);
++			   __func__, self->daddr);
+ 
+ 		/* Query remote LM-IAS for this service */
+ 		err = irda_find_lsap_sel(self, name);
+@@ -658,7 +658,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ 			/* We found the requested service */
+ 			if(daddr != DEV_ADDR_ANY) {
+ 				IRDA_DEBUG(1, "%s(), discovered service ''%s'' in two different devices !!!\n",
+-					   __FUNCTION__, name);
++					   __func__, name);
+ 				self->daddr = DEV_ADDR_ANY;
+ 				kfree(discoveries);
+ 				return(-ENOTUNIQ);
+@@ -672,7 +672,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ 			break;
+ 		default:
+ 			/* Something bad did happen :-( */
+-			IRDA_DEBUG(0, "%s(), unexpected IAS query failure\n", __FUNCTION__);
++			IRDA_DEBUG(0, "%s(), unexpected IAS query failure\n", __func__);
+ 			self->daddr = DEV_ADDR_ANY;
+ 			kfree(discoveries);
+ 			return(-EHOSTUNREACH);
+@@ -685,7 +685,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ 	/* Check out what we found */
+ 	if(daddr == DEV_ADDR_ANY) {
+ 		IRDA_DEBUG(1, "%s(), cannot discover service ''%s'' in any device !!!\n",
+-			   __FUNCTION__, name);
++			   __func__, name);
+ 		self->daddr = DEV_ADDR_ANY;
+ 		return(-EADDRNOTAVAIL);
+ 	}
+@@ -696,7 +696,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ 	self->dtsap_sel = dtsap_sel;
+ 
+ 	IRDA_DEBUG(1, "%s(), discovered requested service ''%s'' at address %08x\n",
+-		   __FUNCTION__, name, self->daddr);
++		   __func__, name, self->daddr);
+ 
+ 	return 0;
+ }
+@@ -727,8 +727,8 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
+ 		saddr.sir_addr = self->saddr;
+ 	}
+ 
+-	IRDA_DEBUG(1, "%s(), tsap_sel = %#x\n", __FUNCTION__, saddr.sir_lsap_sel);
+-	IRDA_DEBUG(1, "%s(), addr = %08x\n", __FUNCTION__, saddr.sir_addr);
++	IRDA_DEBUG(1, "%s(), tsap_sel = %#x\n", __func__, saddr.sir_lsap_sel);
++	IRDA_DEBUG(1, "%s(), addr = %08x\n", __func__, saddr.sir_addr);
+ 
+ 	/* uaddr_len come to us uninitialised */
+ 	*uaddr_len = sizeof (struct sockaddr_irda);
+@@ -747,7 +747,7 @@ static int irda_listen(struct socket *sock, int backlog)
+ {
+ 	struct sock *sk = sock->sk;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
+ 	    (sk->sk_type != SOCK_DGRAM))
+@@ -776,7 +776,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 	struct irda_sock *self = irda_sk(sk);
+ 	int err;
+ 
+-	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ 
+ 	if (addr_len != sizeof(struct sockaddr_irda))
+ 		return -EINVAL;
+@@ -787,7 +787,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 	    (sk->sk_protocol == IRDAPROTO_ULTRA)) {
+ 		self->pid = addr->sir_lsap_sel;
+ 		if (self->pid & 0x80) {
+-			IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __FUNCTION__);
++			IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
+ 			return -EOPNOTSUPP;
+ 		}
+ 		err = irda_open_lsap(self, self->pid);
+@@ -835,9 +835,9 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
+ 	struct sk_buff *skb;
+ 	int err;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+-	err = irda_create(sk->sk_net, newsock, sk->sk_protocol);
++	err = irda_create(sock_net(sk), newsock, sk->sk_protocol);
+ 	if (err)
+ 		return err;
+ 
+@@ -893,7 +893,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
+ 	/* Now attach up the new socket */
+ 	new->tsap = irttp_dup(self->tsap, new);
+ 	if (!new->tsap) {
+-		IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
+ 		kfree_skb(skb);
+ 		return -1;
+ 	}
+@@ -954,7 +954,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
+ 	struct irda_sock *self = irda_sk(sk);
+ 	int err;
+ 
+-	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ 
+ 	/* Don't allow connect for Ultra sockets */
+ 	if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA))
+@@ -984,13 +984,13 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
+ 		/* Try to find one suitable */
+ 		err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
+ 		if (err) {
+-			IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __FUNCTION__);
++			IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__);
+ 			return err;
+ 		}
+ 	} else {
+ 		/* Use the one provided by the user */
+ 		self->daddr = addr->sir_addr;
+-		IRDA_DEBUG(1, "%s(), daddr = %08x\n", __FUNCTION__, self->daddr);
++		IRDA_DEBUG(1, "%s(), daddr = %08x\n", __func__, self->daddr);
+ 
+ 		/* If we don't have a valid service name, we assume the
+ 		 * user want to connect on a specific LSAP. Prevent
+@@ -1000,7 +1000,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
+ 			/* Query remote LM-IAS using service name */
+ 			err = irda_find_lsap_sel(self, addr->sir_name);
+ 			if (err) {
+-				IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
++				IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
+ 				return err;
+ 			}
+ 		} else {
+@@ -1025,7 +1025,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
+ 				    self->saddr, self->daddr, NULL,
+ 				    self->max_sdu_size_rx, NULL);
+ 	if (err) {
+-		IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
+ 		return err;
+ 	}
+ 
+@@ -1068,7 +1068,7 @@ static int irda_create(struct net *net, struct socket *sock, int protocol)
+ 	struct sock *sk;
+ 	struct irda_sock *self;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	if (net != &init_net)
+ 		return -EAFNOSUPPORT;
+@@ -1089,7 +1089,7 @@ static int irda_create(struct net *net, struct socket *sock, int protocol)
+ 		return -ENOMEM;
+ 
+ 	self = irda_sk(sk);
+-	IRDA_DEBUG(2, "%s() : self is %p\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s() : self is %p\n", __func__, self);
+ 
+ 	init_waitqueue_head(&self->query_wait);
+ 
+@@ -1149,7 +1149,7 @@ static int irda_create(struct net *net, struct socket *sock, int protocol)
+  */
+ static void irda_destroy_socket(struct irda_sock *self)
+ {
+-	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ 
+ 	/* Unregister with IrLMP */
+ 	irlmp_unregister_client(self->ckey);
+@@ -1186,7 +1186,7 @@ static int irda_release(struct socket *sock)
+ {
+ 	struct sock *sk = sock->sk;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	if (sk == NULL)
+ 		return 0;
+@@ -1254,7 +1254,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
+ 	struct sk_buff *skb;
+ 	int err = -EPIPE;
+ 
+-	IRDA_DEBUG(4, "%s(), len=%zd\n", __FUNCTION__, len);
++	IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
+ 
+ 	/* Note : socket.c set MSG_EOR on SEQPACKET sockets */
+ 	if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
+@@ -1282,7 +1282,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
+ 	/* Check that we don't send out too big frames */
+ 	if (len > self->max_data_size) {
+ 		IRDA_DEBUG(2, "%s(), Chopping frame from %zd to %d bytes!\n",
+-			   __FUNCTION__, len, self->max_data_size);
++			   __func__, len, self->max_data_size);
+ 		len = self->max_data_size;
+ 	}
+ 
+@@ -1306,7 +1306,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
+ 	 */
+ 	err = irttp_data_request(self->tsap, skb);
+ 	if (err) {
+-		IRDA_DEBUG(0, "%s(), err=%d\n", __FUNCTION__, err);
++		IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
+ 		goto out_err;
+ 	}
+ 	/* Tell client how much data we actually sent */
+@@ -1332,7 +1332,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ 	size_t copied;
+ 	int err;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	if ((err = sock_error(sk)) < 0)
+ 		return err;
+@@ -1347,7 +1347,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ 
+ 	if (copied > size) {
+ 		IRDA_DEBUG(2, "%s(), Received truncated frame (%zd < %zd)!\n",
+-			   __FUNCTION__, copied, size);
++			   __func__, copied, size);
+ 		copied = size;
+ 		msg->msg_flags |= MSG_TRUNC;
+ 	}
+@@ -1363,7 +1363,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ 	 */
+ 	if (self->rx_flow == FLOW_STOP) {
+ 		if ((atomic_read(&sk->sk_rmem_alloc) << 2) <= sk->sk_rcvbuf) {
+-			IRDA_DEBUG(2, "%s(), Starting IrTTP\n", __FUNCTION__);
++			IRDA_DEBUG(2, "%s(), Starting IrTTP\n", __func__);
+ 			self->rx_flow = FLOW_START;
+ 			irttp_flow_request(self->tsap, FLOW_START);
+ 		}
+@@ -1385,7 +1385,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
+ 	int target, err;
+ 	long timeo;
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	if ((err = sock_error(sk)) < 0)
+ 		return err;
+@@ -1459,14 +1459,14 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
+ 			/* put the skb back if we didn't use it up.. */
+ 			if (skb->len) {
+ 				IRDA_DEBUG(1, "%s(), back on q!\n",
+-					   __FUNCTION__);
++					   __func__);
+ 				skb_queue_head(&sk->sk_receive_queue, skb);
+ 				break;
+ 			}
+ 
+ 			kfree_skb(skb);
+ 		} else {
+-			IRDA_DEBUG(0, "%s() questionable!?\n", __FUNCTION__);
++			IRDA_DEBUG(0, "%s() questionable!?\n", __func__);
+ 
+ 			/* put message back and return */
+ 			skb_queue_head(&sk->sk_receive_queue, skb);
+@@ -1482,7 +1482,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
+ 	 */
+ 	if (self->rx_flow == FLOW_STOP) {
+ 		if ((atomic_read(&sk->sk_rmem_alloc) << 2) <= sk->sk_rcvbuf) {
+-			IRDA_DEBUG(2, "%s(), Starting IrTTP\n", __FUNCTION__);
++			IRDA_DEBUG(2, "%s(), Starting IrTTP\n", __func__);
+ 			self->rx_flow = FLOW_START;
+ 			irttp_flow_request(self->tsap, FLOW_START);
+ 		}
+@@ -1506,7 +1506,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ 	struct sk_buff *skb;
+ 	int err;
+ 
+-	IRDA_DEBUG(4, "%s(), len=%zd\n", __FUNCTION__, len);
++	IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
+ 
+ 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
+ 		return -EINVAL;
+@@ -1528,7 +1528,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ 	if (len > self->max_data_size) {
+ 		IRDA_DEBUG(0, "%s(), Warning to much data! "
+ 			   "Chopping frame from %zd to %d bytes!\n",
+-			   __FUNCTION__, len, self->max_data_size);
++			   __func__, len, self->max_data_size);
+ 		len = self->max_data_size;
+ 	}
+ 
+@@ -1540,7 +1540,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ 	skb_reserve(skb, self->max_header_size);
+ 	skb_reset_transport_header(skb);
+ 
+-	IRDA_DEBUG(4, "%s(), appending user data\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s(), appending user data\n", __func__);
+ 	skb_put(skb, len);
+ 	err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
+ 	if (err) {
+@@ -1554,7 +1554,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ 	 */
+ 	err = irttp_udata_request(self->tsap, skb);
+ 	if (err) {
+-		IRDA_DEBUG(0, "%s(), err=%d\n", __FUNCTION__, err);
++		IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
+ 		return err;
+ 	}
+ 	return len;
+@@ -1577,7 +1577,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ 	struct sk_buff *skb;
+ 	int err;
+ 
+-	IRDA_DEBUG(4, "%s(), len=%zd\n", __FUNCTION__, len);
++	IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
+ 
+ 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
+ 		return -EINVAL;
+@@ -1600,7 +1600,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ 
+ 		pid = addr->sir_lsap_sel;
+ 		if (pid & 0x80) {
+-			IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __FUNCTION__);
++			IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
+ 			return -EOPNOTSUPP;
+ 		}
+ 	} else {
+@@ -1609,7 +1609,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ 		if ((self->lsap == NULL) ||
+ 		    (sk->sk_state != TCP_ESTABLISHED)) {
+ 			IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			return -ENOTCONN;
+ 		}
+ 		/* Use PID from socket */
+@@ -1623,7 +1623,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ 	if (len > self->max_data_size) {
+ 		IRDA_DEBUG(0, "%s(), Warning to much data! "
+ 			   "Chopping frame from %zd to %d bytes!\n",
+-			   __FUNCTION__, len, self->max_data_size);
++			   __func__, len, self->max_data_size);
+ 		len = self->max_data_size;
+ 	}
+ 
+@@ -1635,7 +1635,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ 	skb_reserve(skb, self->max_header_size);
+ 	skb_reset_transport_header(skb);
+ 
+-	IRDA_DEBUG(4, "%s(), appending user data\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s(), appending user data\n", __func__);
+ 	skb_put(skb, len);
+ 	err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
+ 	if (err) {
+@@ -1646,7 +1646,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ 	err = irlmp_connless_data_request((bound ? self->lsap : NULL),
+ 					  skb, pid);
+ 	if (err) {
+-		IRDA_DEBUG(0, "%s(), err=%d\n", __FUNCTION__, err);
++		IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
+ 		return err;
+ 	}
+ 	return len;
+@@ -1661,7 +1661,7 @@ static int irda_shutdown(struct socket *sock, int how)
+ 	struct sock *sk = sock->sk;
+ 	struct irda_sock *self = irda_sk(sk);
+ 
+-	IRDA_DEBUG(1, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(1, "%s(%p)\n", __func__, self);
+ 
+ 	sk->sk_state       = TCP_CLOSE;
+ 	sk->sk_shutdown   |= SEND_SHUTDOWN;
+@@ -1696,7 +1696,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
+ 	struct irda_sock *self = irda_sk(sk);
+ 	unsigned int mask;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	poll_wait(file, sk->sk_sleep, wait);
+ 	mask = 0;
+@@ -1705,7 +1705,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
+ 	if (sk->sk_err)
+ 		mask |= POLLERR;
+ 	if (sk->sk_shutdown & RCV_SHUTDOWN) {
+-		IRDA_DEBUG(0, "%s(), POLLHUP\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), POLLHUP\n", __func__);
+ 		mask |= POLLHUP;
+ 	}
+ 
+@@ -1719,7 +1719,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
+ 	switch (sk->sk_type) {
+ 	case SOCK_STREAM:
+ 		if (sk->sk_state == TCP_CLOSE) {
+-			IRDA_DEBUG(0, "%s(), POLLHUP\n", __FUNCTION__);
++			IRDA_DEBUG(0, "%s(), POLLHUP\n", __func__);
+ 			mask |= POLLHUP;
+ 		}
+ 
+@@ -1755,7 +1755,7 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ {
+ 	struct sock *sk = sock->sk;
+ 
+-	IRDA_DEBUG(4, "%s(), cmd=%#x\n", __FUNCTION__, cmd);
++	IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd);
+ 
+ 	switch (cmd) {
+ 	case TIOCOUTQ: {
+@@ -1796,7 +1796,7 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ 	case SIOCSIFMETRIC:
+ 		return -EINVAL;
+ 	default:
+-		IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__);
+ 		return -ENOIOCTLCMD;
+ 	}
+ 
+@@ -1833,7 +1833,7 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
+ 	struct ias_attrib *	ias_attr;	/* Attribute in IAS object */
+ 	int opt, free_ias = 0;
+ 
+-	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ 
+ 	if (level != SOL_IRLMP)
+ 		return -ENOPROTOOPT;
+@@ -2012,7 +2012,7 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
+ 
+ 		/* 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", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), attempting to delete a kernel attribute\n", __func__);
+ 			kfree(ias_opt);
+ 			return -EPERM;
+ 		}
+@@ -2031,11 +2031,11 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
+ 		/* Only possible for a seqpacket service (TTP with SAR) */
+ 		if (sk->sk_type != SOCK_SEQPACKET) {
+ 			IRDA_DEBUG(2, "%s(), setting max_sdu_size = %d\n",
+-				   __FUNCTION__, opt);
++				   __func__, opt);
+ 			self->max_sdu_size_rx = opt;
+ 		} else {
+ 			IRDA_WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			return -ENOPROTOOPT;
+ 		}
+ 		break;
+@@ -2149,7 +2149,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
+ 	int err;
+ 	int offset, total;
+ 
+-	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ 
+ 	if (level != SOL_IRLMP)
+ 		return -ENOPROTOOPT;
+@@ -2310,7 +2310,7 @@ bed:
+ 		/* Check that we can proceed with IAP */
+ 		if (self->iriap) {
+ 			IRDA_WARNING("%s: busy with a previous query\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			kfree(ias_opt);
+ 			return -EBUSY;
+ 		}
+@@ -2406,7 +2406,7 @@ bed:
+ 		if (!self->cachedaddr) {
+ 			int ret = 0;
+ 
+-			IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __func__);
+ 
+ 			/* Set watchdog timer to expire in <val> ms. */
+ 			self->errno = 0;
+@@ -2424,14 +2424,14 @@ bed:
+ 			if(timer_pending(&(self->watchdog)))
+ 				del_timer(&(self->watchdog));
+ 
+-			IRDA_DEBUG(1, "%s(), ...waking up !\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), ...waking up !\n", __func__);
+ 
+ 			if (ret != 0)
+ 				return ret;
+ 		}
+ 		else
+ 			IRDA_DEBUG(1, "%s(), found immediately !\n",
+-				   __FUNCTION__);
++				   __func__);
+ 
+ 		/* Tell IrLMP that we have been notified */
+ 		irlmp_update_client(self->ckey, self->mask.word,
+diff --git a/net/irda/discovery.c b/net/irda/discovery.c
+index 80c33f4..bfacef8 100644
+--- a/net/irda/discovery.c
++++ b/net/irda/discovery.c
+@@ -110,7 +110,7 @@ void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log)
+ {
+ 	discovery_t *discovery;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	/*
+ 	 *  If log is missing this means that IrLAP was unable to perform the
+@@ -157,7 +157,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
+ 	int			i = 0;		/* How many we expired */
+ 
+ 	IRDA_ASSERT(log != NULL, return;);
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	spin_lock_irqsave(&log->hb_spinlock, flags);
+ 
+diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
+index 6eef1f2..018c929 100644
+--- a/net/irda/ircomm/ircomm_core.c
++++ b/net/irda/ircomm/ircomm_core.c
+@@ -70,7 +70,7 @@ static int __init ircomm_init(void)
+ {
+ 	ircomm = hashbin_new(HB_LOCK);
+ 	if (ircomm == NULL) {
+-		IRDA_ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
++		IRDA_ERROR("%s(), can't allocate hashbin!\n", __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -91,7 +91,7 @@ static int __init ircomm_init(void)
+ 
+ static void __exit ircomm_cleanup(void)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	hashbin_delete(ircomm, (FREE_FUNC) __ircomm_close);
+ 
+@@ -111,7 +111,7 @@ struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line)
+ 	struct ircomm_cb *self = NULL;
+ 	int ret;
+ 
+-	IRDA_DEBUG(2, "%s(), service_type=0x%02x\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s(), service_type=0x%02x\n", __func__ ,
+ 		   service_type);
+ 
+ 	IRDA_ASSERT(ircomm != NULL, return NULL;);
+@@ -155,7 +155,7 @@ EXPORT_SYMBOL(ircomm_open);
+  */
+ static int __ircomm_close(struct ircomm_cb *self)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	/* Disconnect link if any */
+ 	ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL, NULL);
+@@ -191,7 +191,7 @@ int ircomm_close(struct ircomm_cb *self)
+ 	IRDA_ASSERT(self != NULL, return -EIO;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;);
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	entry = hashbin_remove(ircomm, self->line, NULL);
+ 
+@@ -216,7 +216,7 @@ int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel,
+ 	struct ircomm_info info;
+ 	int ret;
+ 
+-	IRDA_DEBUG(2 , "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2 , "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+@@ -245,7 +245,7 @@ void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ {
+ 	int clen = 0;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	/* Check if the packet contains data on the control channel */
+ 	if (skb->len > 0)
+@@ -261,7 +261,7 @@ void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ 						info->qos, info->max_data_size,
+ 						info->max_header_size, skb);
+ 	else {
+-		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ 	}
+ }
+ 
+@@ -278,7 +278,7 @@ int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata)
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	ret = ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata, NULL);
+ 
+@@ -296,7 +296,7 @@ EXPORT_SYMBOL(ircomm_connect_response);
+ void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
+ 			    struct ircomm_info *info)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	if (self->notify.connect_confirm )
+ 		self->notify.connect_confirm(self->notify.instance,
+@@ -304,7 +304,7 @@ void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
+ 					     info->max_data_size,
+ 					     info->max_header_size, skb);
+ 	else {
+-		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ 	}
+ }
+ 
+@@ -318,7 +318,7 @@ int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb)
+ {
+ 	int ret;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -EFAULT;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+@@ -339,14 +339,14 @@ EXPORT_SYMBOL(ircomm_data_request);
+  */
+ void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(skb->len > 0, return;);
+ 
+ 	if (self->notify.data_indication)
+ 		self->notify.data_indication(self->notify.instance, self, skb);
+ 	else {
+-		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ 	}
+ }
+ 
+@@ -372,7 +372,7 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
+ 	 */
+ 	if (unlikely(skb->len < (clen + 1))) {
+ 		IRDA_DEBUG(2, "%s() throwing away illegal frame\n",
+-			   __FUNCTION__ );
++			   __func__ );
+ 		return;
+ 	}
+ 
+@@ -391,7 +391,7 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
+ 		ircomm_data_indication(self, skb);
+ 	else {
+ 		IRDA_DEBUG(4, "%s(), data was control info only!\n",
+-			   __FUNCTION__ );
++			   __func__ );
+ 	}
+ }
+ 
+@@ -405,7 +405,7 @@ int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb)
+ {
+ 	int ret;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -EFAULT;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+@@ -427,7 +427,7 @@ EXPORT_SYMBOL(ircomm_control_request);
+ static void ircomm_control_indication(struct ircomm_cb *self,
+ 				      struct sk_buff *skb, int clen)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	/* Use udata for delivering data on the control channel */
+ 	if (self->notify.udata_indication) {
+@@ -448,7 +448,7 @@ static void ircomm_control_indication(struct ircomm_cb *self,
+ 		 * see ircomm_tty_control_indication(). */
+ 		dev_kfree_skb(ctrl_skb);
+ 	} else {
+-		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ 	}
+ }
+ 
+@@ -463,7 +463,7 @@ int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata)
+ 	struct ircomm_info info;
+ 	int ret;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+@@ -484,7 +484,7 @@ EXPORT_SYMBOL(ircomm_disconnect_request);
+ void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ 				  struct ircomm_info *info)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(info != NULL, return;);
+ 
+@@ -492,7 +492,7 @@ void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ 		self->notify.disconnect_indication(self->notify.instance, self,
+ 						   info->reason, skb);
+ 	} else {
+-		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ 	}
+ }
+ 
+@@ -504,7 +504,7 @@ void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+  */
+ void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+diff --git a/net/irda/ircomm/ircomm_event.c b/net/irda/ircomm/ircomm_event.c
+index 8ba4e59..c35b3ef 100644
+--- a/net/irda/ircomm/ircomm_event.c
++++ b/net/irda/ircomm/ircomm_event.c
+@@ -108,7 +108,7 @@ static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event,
+ 		ircomm_connect_indication(self, skb, info);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(4, "%s(), unknown event: %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(4, "%s(), unknown event: %s\n", __func__ ,
+ 			   ircomm_event[event]);
+ 		ret = -EINVAL;
+ 	}
+@@ -138,7 +138,7 @@ static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
+ 		ircomm_disconnect_indication(self, skb, info);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), unknown event: %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(0, "%s(), unknown event: %s\n", __func__ ,
+ 			   ircomm_event[event]);
+ 		ret = -EINVAL;
+ 	}
+@@ -171,7 +171,7 @@ static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
+ 		ircomm_disconnect_indication(self, skb, info);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), unknown event = %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(0, "%s(), unknown event = %s\n", __func__ ,
+ 			   ircomm_event[event]);
+ 		ret = -EINVAL;
+ 	}
+@@ -213,7 +213,7 @@ static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
+ 		ret = self->issue.disconnect_request(self, skb, info);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), unknown event = %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(0, "%s(), unknown event = %s\n", __func__ ,
+ 			   ircomm_event[event]);
+ 		ret = -EINVAL;
+ 	}
+@@ -229,7 +229,7 @@ static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
+ int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event,
+ 		    struct sk_buff *skb, struct ircomm_info *info)
+ {
+-	IRDA_DEBUG(4, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++	IRDA_DEBUG(4, "%s: state=%s, event=%s\n", __func__ ,
+ 		   ircomm_state[self->state], ircomm_event[event]);
+ 
+ 	return (*state[self->state])(self, event, skb, info);
+@@ -245,6 +245,6 @@ void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state)
+ {
+ 	self->state = state;
+ 
+-	IRDA_DEBUG(4, "%s: next state=%s, service type=%d\n", __FUNCTION__ ,
++	IRDA_DEBUG(4, "%s: next state=%s, service type=%d\n", __func__ ,
+ 		   ircomm_state[self->state], self->service_type);
+ }
+diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c
+index 55860ee..67c99d2 100644
+--- a/net/irda/ircomm/ircomm_lmp.c
++++ b/net/irda/ircomm/ircomm_lmp.c
+@@ -53,7 +53,7 @@ static int ircomm_lmp_connect_request(struct ircomm_cb *self,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	/* Don't forget to refcount it - should be NULL anyway */
+ 	if(userdata)
+@@ -76,7 +76,7 @@ static int ircomm_lmp_connect_response(struct ircomm_cb *self,
+ 	struct sk_buff *tx_skb;
+ 	int ret;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	/* Any userdata supplied? */
+ 	if (userdata == NULL) {
+@@ -111,7 +111,7 @@ static int ircomm_lmp_disconnect_request(struct ircomm_cb *self,
+ 	struct sk_buff *tx_skb;
+ 	int ret;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	if (!userdata) {
+ 		tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
+@@ -148,13 +148,13 @@ static void ircomm_lmp_flow_control(struct sk_buff *skb)
+ 
+ 	cb = (struct irda_skb_cb *) skb->cb;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	line = cb->line;
+ 
+ 	self = (struct ircomm_cb *) hashbin_lock_find(ircomm, line, NULL);
+ 	if (!self) {
+-		IRDA_DEBUG(2, "%s(), didn't find myself\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), didn't find myself\n", __func__ );
+ 		return;
+ 	}
+ 
+@@ -164,7 +164,7 @@ static void ircomm_lmp_flow_control(struct sk_buff *skb)
+ 	self->pkt_count--;
+ 
+ 	if ((self->pkt_count < 2) && (self->flow_status == FLOW_STOP)) {
+-		IRDA_DEBUG(2, "%s(), asking TTY to start again!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), asking TTY to start again!\n", __func__ );
+ 		self->flow_status = FLOW_START;
+ 		if (self->notify.flow_indication)
+ 			self->notify.flow_indication(self->notify.instance,
+@@ -191,7 +191,7 @@ static int ircomm_lmp_data_request(struct ircomm_cb *self,
+ 
+ 	cb->line = self->line;
+ 
+-	IRDA_DEBUG(4, "%s(), sending frame\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s(), sending frame\n", __func__ );
+ 
+ 	/* Don't forget to refcount it - see ircomm_tty_do_softint() */
+ 	skb_get(skb);
+@@ -199,7 +199,7 @@ static int ircomm_lmp_data_request(struct ircomm_cb *self,
+ 	skb->destructor = ircomm_lmp_flow_control;
+ 
+ 	if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) {
+-		IRDA_DEBUG(2, "%s(), asking TTY to slow down!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), asking TTY to slow down!\n", __func__ );
+ 		self->flow_status = FLOW_STOP;
+ 		if (self->notify.flow_indication)
+ 			self->notify.flow_indication(self->notify.instance,
+@@ -207,7 +207,7 @@ static int ircomm_lmp_data_request(struct ircomm_cb *self,
+ 	}
+ 	ret = irlmp_data_request(self->lsap, skb);
+ 	if (ret) {
+-		IRDA_ERROR("%s(), failed\n", __FUNCTION__);
++		IRDA_ERROR("%s(), failed\n", __func__);
+ 		/* irlmp_data_request already free the packet */
+ 	}
+ 
+@@ -225,7 +225,7 @@ static int ircomm_lmp_data_indication(void *instance, void *sap,
+ {
+ 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+@@ -255,7 +255,7 @@ static void ircomm_lmp_connect_confirm(void *instance, void *sap,
+ 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ 	struct ircomm_info info;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -288,7 +288,7 @@ static void ircomm_lmp_connect_indication(void *instance, void *sap,
+ 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+ 	struct ircomm_info info;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -318,7 +318,7 @@ static void ircomm_lmp_disconnect_indication(void *instance, void *sap,
+ 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ 	struct ircomm_info info;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -341,7 +341,7 @@ int ircomm_open_lsap(struct ircomm_cb *self)
+ {
+ 	notify_t notify;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	/* Register callbacks */
+ 	irda_notify_init(&notify);
+@@ -354,7 +354,7 @@ int ircomm_open_lsap(struct ircomm_cb *self)
+ 
+ 	self->lsap = irlmp_open_lsap(LSAP_ANY, &notify, 0);
+ 	if (!self->lsap) {
+-		IRDA_DEBUG(0,"%sfailed to allocate tsap\n", __FUNCTION__ );
++		IRDA_DEBUG(0,"%sfailed to allocate tsap\n", __func__ );
+ 		return -1;
+ 	}
+ 	self->slsap_sel = self->lsap->slsap_sel;
+diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
+index 598dcbe..d57aefd 100644
+--- a/net/irda/ircomm/ircomm_param.c
++++ b/net/irda/ircomm/ircomm_param.c
+@@ -103,7 +103,7 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
+ 	struct sk_buff *skb;
+ 	int count;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+@@ -136,7 +136,7 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
+ 	count = irda_param_insert(self, pi, skb_tail_pointer(skb),
+ 				  skb_tailroom(skb), &ircomm_param_info);
+ 	if (count < 0) {
+-		IRDA_WARNING("%s(), no room for parameter!\n", __FUNCTION__);
++		IRDA_WARNING("%s(), no room for parameter!\n", __func__);
+ 		spin_unlock_irqrestore(&self->spinlock, flags);
+ 		return -1;
+ 	}
+@@ -144,7 +144,7 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
+ 
+ 	spin_unlock_irqrestore(&self->spinlock, flags);
+ 
+-	IRDA_DEBUG(2, "%s(), skb->len=%d\n", __FUNCTION__ , skb->len);
++	IRDA_DEBUG(2, "%s(), skb->len=%d\n", __func__ , skb->len);
+ 
+ 	if (flush) {
+ 		/* ircomm_tty_do_softint will take care of the rest */
+@@ -179,10 +179,10 @@ static int ircomm_param_service_type(void *instance, irda_param_t *param,
+ 	service_type &= self->service_type;
+ 	if (!service_type) {
+ 		IRDA_DEBUG(2,
+-			   "%s(), No common service type to use!\n", __FUNCTION__ );
++			   "%s(), No common service type to use!\n", __func__ );
+ 		return -1;
+ 	}
+-	IRDA_DEBUG(0, "%s(), services in common=%02x\n", __FUNCTION__ ,
++	IRDA_DEBUG(0, "%s(), services in common=%02x\n", __func__ ,
+ 		   service_type);
+ 
+ 	/*
+@@ -197,7 +197,7 @@ static int ircomm_param_service_type(void *instance, irda_param_t *param,
+ 	else if (service_type & IRCOMM_3_WIRE_RAW)
+ 		self->settings.service_type = IRCOMM_3_WIRE_RAW;
+ 
+-	IRDA_DEBUG(0, "%s(), resulting service type=0x%02x\n", __FUNCTION__ ,
++	IRDA_DEBUG(0, "%s(), resulting service type=0x%02x\n", __func__ ,
+ 		   self->settings.service_type);
+ 
+ 	/*
+@@ -240,7 +240,7 @@ static int ircomm_param_port_type(void *instance, irda_param_t *param, int get)
+ 	else {
+ 		self->settings.port_type = (__u8) param->pv.i;
+ 
+-		IRDA_DEBUG(0, "%s(), port type=%d\n", __FUNCTION__ ,
++		IRDA_DEBUG(0, "%s(), port type=%d\n", __func__ ,
+ 			   self->settings.port_type);
+ 	}
+ 	return 0;
+@@ -260,9 +260,9 @@ static int ircomm_param_port_name(void *instance, irda_param_t *param, int get)
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ 
+ 	if (get) {
+-		IRDA_DEBUG(0, "%s(), not imp!\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), not imp!\n", __func__ );
+ 	} else {
+-		IRDA_DEBUG(0, "%s(), port-name=%s\n", __FUNCTION__ , param->pv.c);
++		IRDA_DEBUG(0, "%s(), port-name=%s\n", __func__ , param->pv.c);
+ 		strncpy(self->settings.port_name, param->pv.c, 32);
+ 	}
+ 
+@@ -287,7 +287,7 @@ static int ircomm_param_data_rate(void *instance, irda_param_t *param, int get)
+ 	else
+ 		self->settings.data_rate = param->pv.i;
+ 
+-	IRDA_DEBUG(2, "%s(), data rate = %d\n", __FUNCTION__ , param->pv.i);
++	IRDA_DEBUG(2, "%s(), data rate = %d\n", __func__ , param->pv.i);
+ 
+ 	return 0;
+ }
+@@ -333,7 +333,7 @@ static int ircomm_param_flow_control(void *instance, irda_param_t *param,
+ 	else
+ 		self->settings.flow_control = (__u8) param->pv.i;
+ 
+-	IRDA_DEBUG(1, "%s(), flow control = 0x%02x\n", __FUNCTION__ , (__u8) param->pv.i);
++	IRDA_DEBUG(1, "%s(), flow control = 0x%02x\n", __func__ , (__u8) param->pv.i);
+ 
+ 	return 0;
+ }
+@@ -359,7 +359,7 @@ static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get)
+ 		self->settings.xonxoff[1] = (__u16) param->pv.i >> 8;
+ 	}
+ 
+-	IRDA_DEBUG(0, "%s(), XON/XOFF = 0x%02x,0x%02x\n", __FUNCTION__ ,
++	IRDA_DEBUG(0, "%s(), XON/XOFF = 0x%02x,0x%02x\n", __func__ ,
+ 		   param->pv.i & 0xff, param->pv.i >> 8);
+ 
+ 	return 0;
+@@ -386,7 +386,7 @@ static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get)
+ 		self->settings.enqack[1] = (__u16) param->pv.i >> 8;
+ 	}
+ 
+-	IRDA_DEBUG(0, "%s(), ENQ/ACK = 0x%02x,0x%02x\n", __FUNCTION__ ,
++	IRDA_DEBUG(0, "%s(), ENQ/ACK = 0x%02x,0x%02x\n", __func__ ,
+ 		   param->pv.i & 0xff, param->pv.i >> 8);
+ 
+ 	return 0;
+@@ -401,7 +401,7 @@ static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get)
+ static int ircomm_param_line_status(void *instance, irda_param_t *param,
+ 				    int get)
+ {
+-	IRDA_DEBUG(2, "%s(), not impl.\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s(), not impl.\n", __func__ );
+ 
+ 	return 0;
+ }
+@@ -462,7 +462,7 @@ static int ircomm_param_dce(void *instance, irda_param_t *param, int get)
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ 	__u8 dce;
+ 
+-	IRDA_DEBUG(1, "%s(), dce = 0x%02x\n", __FUNCTION__ , (__u8) param->pv.i);
++	IRDA_DEBUG(1, "%s(), dce = 0x%02x\n", __func__ , (__u8) param->pv.i);
+ 
+ 	dce = (__u8) param->pv.i;
+ 
+@@ -474,7 +474,7 @@ static int ircomm_param_dce(void *instance, irda_param_t *param, int get)
+ 	/* Check if any of the settings have changed */
+ 	if (dce & 0x0f) {
+ 		if (dce & IRCOMM_DELTA_CTS) {
+-			IRDA_DEBUG(2, "%s(), CTS \n", __FUNCTION__ );
++			IRDA_DEBUG(2, "%s(), CTS \n", __func__ );
+ 		}
+ 	}
+ 
+diff --git a/net/irda/ircomm/ircomm_ttp.c b/net/irda/ircomm/ircomm_ttp.c
+index 712eafd..6e6509f 100644
+--- a/net/irda/ircomm/ircomm_ttp.c
++++ b/net/irda/ircomm/ircomm_ttp.c
+@@ -78,7 +78,7 @@ int ircomm_open_tsap(struct ircomm_cb *self)
+ {
+ 	notify_t notify;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	/* Register callbacks */
+ 	irda_notify_init(&notify);
+@@ -93,7 +93,7 @@ int ircomm_open_tsap(struct ircomm_cb *self)
+ 	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
+ 				     &notify);
+ 	if (!self->tsap) {
+-		IRDA_DEBUG(0, "%sfailed to allocate tsap\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%sfailed to allocate tsap\n", __func__ );
+ 		return -1;
+ 	}
+ 	self->slsap_sel = self->tsap->stsap_sel;
+@@ -121,7 +121,7 @@ static int ircomm_ttp_connect_request(struct ircomm_cb *self,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	/* Don't forget to refcount it - should be NULL anyway */
+ 	if(userdata)
+@@ -145,7 +145,7 @@ static int ircomm_ttp_connect_response(struct ircomm_cb *self,
+ {
+ 	int ret;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	/* Don't forget to refcount it - should be NULL anyway */
+ 	if(userdata)
+@@ -173,7 +173,7 @@ static int ircomm_ttp_data_request(struct ircomm_cb *self,
+ 
+ 	IRDA_ASSERT(skb != NULL, return -1;);
+ 
+-	IRDA_DEBUG(2, "%s(), clen=%d\n", __FUNCTION__ , clen);
++	IRDA_DEBUG(2, "%s(), clen=%d\n", __func__ , clen);
+ 
+ 	/*
+ 	 * Insert clen field, currently we either send data only, or control
+@@ -190,7 +190,7 @@ static int ircomm_ttp_data_request(struct ircomm_cb *self,
+ 
+ 	ret = irttp_data_request(self->tsap, skb);
+ 	if (ret) {
+-		IRDA_ERROR("%s(), failed\n", __FUNCTION__);
++		IRDA_ERROR("%s(), failed\n", __func__);
+ 		/* irttp_data_request already free the packet */
+ 	}
+ 
+@@ -208,7 +208,7 @@ static int ircomm_ttp_data_indication(void *instance, void *sap,
+ {
+ 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+@@ -231,7 +231,7 @@ static void ircomm_ttp_connect_confirm(void *instance, void *sap,
+ 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ 	struct ircomm_info info;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -240,7 +240,7 @@ static void ircomm_ttp_connect_confirm(void *instance, void *sap,
+ 
+ 	if (max_sdu_size != TTP_SAR_DISABLE) {
+ 		IRDA_ERROR("%s(), SAR not allowed for IrCOMM!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		goto out;
+ 	}
+ 
+@@ -272,7 +272,7 @@ static void ircomm_ttp_connect_indication(void *instance, void *sap,
+ 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+ 	struct ircomm_info info;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -281,7 +281,7 @@ static void ircomm_ttp_connect_indication(void *instance, void *sap,
+ 
+ 	if (max_sdu_size != TTP_SAR_DISABLE) {
+ 		IRDA_ERROR("%s(), SAR not allowed for IrCOMM!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		goto out;
+ 	}
+ 
+@@ -331,7 +331,7 @@ static void ircomm_ttp_disconnect_indication(void *instance, void *sap,
+ 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ 	struct ircomm_info info;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -356,7 +356,7 @@ static void ircomm_ttp_flow_indication(void *instance, void *sap,
+ {
+ 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
+index be627e1..d262041 100644
+--- a/net/irda/ircomm/ircomm_tty.c
++++ b/net/irda/ircomm/ircomm_tty.c
+@@ -115,7 +115,7 @@ static int __init ircomm_tty_init(void)
+ 		return -ENOMEM;
+ 	ircomm_tty = hashbin_new(HB_LOCK);
+ 	if (ircomm_tty == NULL) {
+-		IRDA_ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
++		IRDA_ERROR("%s(), can't allocate hashbin!\n", __func__);
+ 		put_tty_driver(driver);
+ 		return -ENOMEM;
+ 	}
+@@ -133,7 +133,7 @@ static int __init ircomm_tty_init(void)
+ 	tty_set_operations(driver, &ops);
+ 	if (tty_register_driver(driver)) {
+ 		IRDA_ERROR("%s(): Couldn't register serial driver\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		put_tty_driver(driver);
+ 		return -1;
+ 	}
+@@ -142,7 +142,7 @@ static int __init ircomm_tty_init(void)
+ 
+ static void __exit __ircomm_tty_cleanup(struct ircomm_tty_cb *self)
+ {
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -163,12 +163,12 @@ static void __exit ircomm_tty_cleanup(void)
+ {
+ 	int ret;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	ret = tty_unregister_driver(driver);
+ 	if (ret) {
+ 		IRDA_ERROR("%s(), failed to unregister driver\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		return;
+ 	}
+ 
+@@ -187,14 +187,14 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)
+ 	notify_t notify;
+ 	int ret = -ENODEV;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ 
+ 	/* Check if already open */
+ 	if (test_and_set_bit(ASYNC_B_INITIALIZED, &self->flags)) {
+-		IRDA_DEBUG(2, "%s(), already open so break out!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), already open so break out!\n", __func__ );
+ 		return 0;
+ 	}
+ 
+@@ -224,7 +224,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)
+ 	/* Connect IrCOMM link with remote device */
+ 	ret = ircomm_tty_attach_cable(self);
+ 	if (ret < 0) {
+-		IRDA_ERROR("%s(), error attaching cable!\n", __FUNCTION__);
++		IRDA_ERROR("%s(), error attaching cable!\n", __func__);
+ 		goto err;
+ 	}
+ 
+@@ -249,7 +249,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
+ 	unsigned long	flags;
+ 	struct tty_struct *tty;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	tty = self->tty;
+ 
+@@ -260,12 +260,12 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
+ 	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
+ 		/* nonblock mode is set or port is not enabled */
+ 		self->flags |= ASYNC_NORMAL_ACTIVE;
+-		IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __FUNCTION__ );
++		IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );
+ 		return 0;
+ 	}
+ 
+ 	if (tty->termios->c_cflag & CLOCAL) {
+-		IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __FUNCTION__ );
++		IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __func__ );
+ 		do_clocal = 1;
+ 	}
+ 
+@@ -368,7 +368,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ 	unsigned long	flags;
+ 	int ret;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	line = tty->index;
+ 	if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) {
+@@ -381,7 +381,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ 		/* No, so make new instance */
+ 		self = kzalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
+ 		if (self == NULL) {
+-			IRDA_ERROR("%s(), kmalloc failed!\n", __FUNCTION__);
++			IRDA_ERROR("%s(), kmalloc failed!\n", __func__);
+ 			return -ENOMEM;
+ 		}
+ 
+@@ -420,7 +420,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ 	self->tty = tty;
+ 	spin_unlock_irqrestore(&self->spinlock, flags);
+ 
+-	IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __FUNCTION__ , tty->driver->name,
++	IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name,
+ 		   self->line, self->open_count);
+ 
+ 	/* Not really used by us, but lets do it anyway */
+@@ -442,7 +442,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ 
+ 		if (wait_event_interruptible(self->close_wait, !test_bit(ASYNC_B_CLOSING, &self->flags))) {
+ 			IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			return -ERESTARTSYS;
+ 		}
+ 
+@@ -460,9 +460,9 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ 		self->settings.service_type = IRCOMM_9_WIRE; /* 9 wire as default */
+ 		/* Jan Kiszka -> add DSR/RI -> Conform to IrCOMM spec */
+ 		self->settings.dce = IRCOMM_CTS | IRCOMM_CD | IRCOMM_DSR | IRCOMM_RI; /* Default line settings */
+-		IRDA_DEBUG(2, "%s(), IrCOMM device\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IrCOMM device\n", __func__ );
+ 	} else {
+-		IRDA_DEBUG(2, "%s(), IrLPT device\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IrLPT device\n", __func__ );
+ 		self->service_type = IRCOMM_3_WIRE_RAW;
+ 		self->settings.service_type = IRCOMM_3_WIRE_RAW; /* Default */
+ 	}
+@@ -474,7 +474,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ 	ret = ircomm_tty_block_til_ready(self, filp);
+ 	if (ret) {
+ 		IRDA_DEBUG(2,
+-		      "%s(), returning after block_til_ready with %d\n", __FUNCTION__ ,
++		      "%s(), returning after block_til_ready with %d\n", __func__ ,
+ 		      ret);
+ 
+ 		return ret;
+@@ -493,7 +493,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ 	unsigned long flags;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	if (!tty)
+ 		return;
+@@ -506,7 +506,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
+ 	if (tty_hung_up_p(filp)) {
+ 		spin_unlock_irqrestore(&self->spinlock, flags);
+ 
+-		IRDA_DEBUG(0, "%s(), returning 1\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), returning 1\n", __func__ );
+ 		return;
+ 	}
+ 
+@@ -519,20 +519,20 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
+ 		 * serial port won't be shutdown.
+ 		 */
+ 		IRDA_DEBUG(0, "%s(), bad serial port count; "
+-			   "tty->count is 1, state->count is %d\n", __FUNCTION__ ,
++			   "tty->count is 1, state->count is %d\n", __func__ ,
+ 			   self->open_count);
+ 		self->open_count = 1;
+ 	}
+ 
+ 	if (--self->open_count < 0) {
+ 		IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n",
+-			   __FUNCTION__, self->line, self->open_count);
++			   __func__, self->line, self->open_count);
+ 		self->open_count = 0;
+ 	}
+ 	if (self->open_count) {
+ 		spin_unlock_irqrestore(&self->spinlock, flags);
+ 
+-		IRDA_DEBUG(0, "%s(), open count > 0\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ );
+ 		return;
+ 	}
+ 
+@@ -608,7 +608,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)
+ 	unsigned long flags;
+ 	struct sk_buff *skb, *ctrl_skb;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	if (!self || self->magic != IRCOMM_TTY_MAGIC)
+ 		return;
+@@ -678,7 +678,7 @@ static int ircomm_tty_write(struct tty_struct *tty,
+ 	int len = 0;
+ 	int size;
+ 
+-	IRDA_DEBUG(2, "%s(), count=%d, hw_stopped=%d\n", __FUNCTION__ , count,
++	IRDA_DEBUG(2, "%s(), count=%d, hw_stopped=%d\n", __func__ , count,
+ 		   tty->hw_stopped);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+@@ -701,7 +701,7 @@ static int ircomm_tty_write(struct tty_struct *tty,
+ 	 * we don't mess up the original "safe skb" (see tx_data_size).
+ 	 * Jean II */
+ 	if (self->max_header_size == IRCOMM_TTY_HDR_UNINITIALISED) {
+-		IRDA_DEBUG(1, "%s() : not initialised\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s() : not initialised\n", __func__);
+ #ifdef IRCOMM_NO_TX_BEFORE_INIT
+ 		/* We didn't consume anything, TTY will retry */
+ 		return 0;
+@@ -830,7 +830,7 @@ static int ircomm_tty_write_room(struct tty_struct *tty)
+ 			ret = self->max_data_size;
+ 		spin_unlock_irqrestore(&self->spinlock, flags);
+ 	}
+-	IRDA_DEBUG(2, "%s(), ret=%d\n", __FUNCTION__ , ret);
++	IRDA_DEBUG(2, "%s(), ret=%d\n", __func__ , ret);
+ 
+ 	return ret;
+ }
+@@ -847,7 +847,7 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
+ 	unsigned long orig_jiffies, poll_time;
+ 	unsigned long flags;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -882,7 +882,7 @@ static void ircomm_tty_throttle(struct tty_struct *tty)
+ {
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -913,7 +913,7 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty)
+ {
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -928,7 +928,7 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty)
+ 		self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);
+ 
+ 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+-		IRDA_DEBUG(1, "%s(), FLOW_START\n", __FUNCTION__ );
++		IRDA_DEBUG(1, "%s(), FLOW_START\n", __func__ );
+ 	}
+ 	ircomm_flow_request(self->ircomm, FLOW_START);
+ }
+@@ -965,7 +965,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	if (!test_and_clear_bit(ASYNC_B_INITIALIZED, &self->flags))
+ 		return;
+@@ -1008,7 +1008,7 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ 	unsigned long	flags;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -1037,7 +1037,7 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
+  */
+ static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch)
+ {
+-	IRDA_DEBUG(0, "%s(), not impl\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s(), not impl\n", __func__ );
+ }
+ 
+ /*
+@@ -1081,7 +1081,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+ 	struct tty_struct *tty;
+ 	int status;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -1095,14 +1095,14 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+ 	}
+ 	if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
+ 		IRDA_DEBUG(2,
+-			   "%s(), ircomm%d CD now %s...\n", __FUNCTION__ , self->line,
++			   "%s(), ircomm%d CD now %s...\n", __func__ , self->line,
+ 			   (status & IRCOMM_CD) ? "on" : "off");
+ 
+ 		if (status & IRCOMM_CD) {
+ 			wake_up_interruptible(&self->open_wait);
+ 		} else {
+ 			IRDA_DEBUG(2,
+-				   "%s(), Doing serial hangup..\n", __FUNCTION__ );
++				   "%s(), Doing serial hangup..\n", __func__ );
+ 			if (tty)
+ 				tty_hangup(tty);
+ 
+@@ -1114,7 +1114,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+ 		if (tty->hw_stopped) {
+ 			if (status & IRCOMM_CTS) {
+ 				IRDA_DEBUG(2,
+-					   "%s(), CTS tx start...\n", __FUNCTION__ );
++					   "%s(), CTS tx start...\n", __func__ );
+ 				tty->hw_stopped = 0;
+ 
+ 				/* Wake up processes blocked on open */
+@@ -1126,7 +1126,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+ 		} else {
+ 			if (!(status & IRCOMM_CTS)) {
+ 				IRDA_DEBUG(2,
+-					   "%s(), CTS tx stop...\n", __FUNCTION__ );
++					   "%s(), CTS tx stop...\n", __func__ );
+ 				tty->hw_stopped = 1;
+ 			}
+ 		}
+@@ -1144,14 +1144,14 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
+ {
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ 	IRDA_ASSERT(skb != NULL, return -1;);
+ 
+ 	if (!self->tty) {
+-		IRDA_DEBUG(0, "%s(), no tty!\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), no tty!\n", __func__ );
+ 		return 0;
+ 	}
+ 
+@@ -1162,7 +1162,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
+ 	 * params, we can just as well declare the hardware for running.
+ 	 */
+ 	if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
+-		IRDA_DEBUG(0, "%s(), polling for line settings!\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), polling for line settings!\n", __func__ );
+ 		ircomm_param_request(self, IRCOMM_POLL, TRUE);
+ 
+ 		/* We can just as well declare the hardware for running */
+@@ -1194,7 +1194,7 @@ static int ircomm_tty_control_indication(void *instance, void *sap,
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ 	int clen;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+@@ -1230,7 +1230,7 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
+ 
+ 	switch (cmd) {
+ 	case FLOW_START:
+-		IRDA_DEBUG(2, "%s(), hw start!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), hw start!\n", __func__ );
+ 		tty->hw_stopped = 0;
+ 
+ 		/* ircomm_tty_do_softint will take care of the rest */
+@@ -1238,7 +1238,7 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
+ 		break;
+ 	default:  /* If we get here, something is very wrong, better stop */
+ 	case FLOW_STOP:
+-		IRDA_DEBUG(2, "%s(), hw stopped!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), hw stopped!\n", __func__ );
+ 		tty->hw_stopped = 1;
+ 		break;
+ 	}
+diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
+index b5a1388..9032a1d 100644
+--- a/net/irda/ircomm/ircomm_tty_attach.c
++++ b/net/irda/ircomm/ircomm_tty_attach.c
+@@ -129,14 +129,14 @@ static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+  */
+ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
+ {
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ 
+ 	/* Check if somebody has already connected to us */
+ 	if (ircomm_is_connected(self->ircomm)) {
+-		IRDA_DEBUG(0, "%s(), already connected!\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), already connected!\n", __func__ );
+ 		return 0;
+ 	}
+ 
+@@ -158,7 +158,7 @@ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
+  */
+ void ircomm_tty_detach_cable(struct ircomm_tty_cb *self)
+ {
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -207,7 +207,7 @@ static void ircomm_tty_ias_register(struct ircomm_tty_cb *self)
+ 	__u8 oct_seq[6];
+ 	__u16 hints;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -308,16 +308,16 @@ int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self)
+ 	 * Set default values, but only if the application for some reason
+ 	 * haven't set them already
+ 	 */
+-	IRDA_DEBUG(2, "%s(), data-rate = %d\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s(), data-rate = %d\n", __func__ ,
+ 		   self->settings.data_rate);
+ 	if (!self->settings.data_rate)
+ 		self->settings.data_rate = 9600;
+-	IRDA_DEBUG(2, "%s(), data-format = %d\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s(), data-format = %d\n", __func__ ,
+ 		   self->settings.data_format);
+ 	if (!self->settings.data_format)
+ 		self->settings.data_format = IRCOMM_WSIZE_8;  /* 8N1 */
+ 
+-	IRDA_DEBUG(2, "%s(), flow-control = %d\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s(), flow-control = %d\n", __func__ ,
+ 		   self->settings.flow_control);
+ 	/*self->settings.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/
+ 
+@@ -362,7 +362,7 @@ static void ircomm_tty_discovery_indication(discinfo_t *discovery,
+ 	struct ircomm_tty_cb *self;
+ 	struct ircomm_tty_info info;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	/* Important note :
+ 	 * We need to drop all passive discoveries.
+@@ -398,7 +398,7 @@ void ircomm_tty_disconnect_indication(void *instance, void *sap,
+ {
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -428,7 +428,7 @@ static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
+ {
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) priv;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -439,13 +439,13 @@ static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
+ 
+ 	/* Check if request succeeded */
+ 	if (result != IAS_SUCCESS) {
+-		IRDA_DEBUG(4, "%s(), got NULL value!\n", __FUNCTION__ );
++		IRDA_DEBUG(4, "%s(), got NULL value!\n", __func__ );
+ 		return;
+ 	}
+ 
+ 	switch (value->type) {
+ 	case IAS_OCT_SEQ:
+-		IRDA_DEBUG(2, "%s(), got octet sequence\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), got octet sequence\n", __func__ );
+ 
+ 		irda_param_extract_all(self, value->t.oct_seq, value->len,
+ 				       &ircomm_param_info);
+@@ -455,21 +455,21 @@ static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
+ 		break;
+ 	case IAS_INTEGER:
+ 		/* Got LSAP selector */
+-		IRDA_DEBUG(2, "%s(), got lsapsel = %d\n", __FUNCTION__ ,
++		IRDA_DEBUG(2, "%s(), got lsapsel = %d\n", __func__ ,
+ 			   value->t.integer);
+ 
+ 		if (value->t.integer == -1) {
+-			IRDA_DEBUG(0, "%s(), invalid value!\n", __FUNCTION__ );
++			IRDA_DEBUG(0, "%s(), invalid value!\n", __func__ );
+ 		} else
+ 			self->dlsap_sel = value->t.integer;
+ 
+ 		ircomm_tty_do_event(self, IRCOMM_TTY_GOT_LSAPSEL, NULL, NULL);
+ 		break;
+ 	case IAS_MISSING:
+-		IRDA_DEBUG(0, "%s(), got IAS_MISSING\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), got IAS_MISSING\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), got unknown type!\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), got unknown type!\n", __func__ );
+ 		break;
+ 	}
+ 	irias_delete_value(value);
+@@ -489,7 +489,7 @@ void ircomm_tty_connect_confirm(void *instance, void *sap,
+ {
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -520,7 +520,7 @@ void ircomm_tty_connect_indication(void *instance, void *sap,
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ 	int clen;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -549,7 +549,7 @@ void ircomm_tty_connect_indication(void *instance, void *sap,
+  */
+ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -566,10 +566,10 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
+ 	 * line.
+ 	 */
+ 	if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) {
+-		IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ );
+ 		return;
+ 	} else {
+-		IRDA_DEBUG(1, "%s(), starting hardware!\n", __FUNCTION__ );
++		IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ );
+ 
+ 		self->tty->hw_stopped = 0;
+ 
+@@ -607,7 +607,7 @@ static void ircomm_tty_watchdog_timer_expired(void *data)
+ {
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -628,7 +628,7 @@ int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ 
+-	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ 		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+ 
+ 	return (*state[self->state])(self, event, skb, info);
+@@ -646,7 +646,7 @@ static inline void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ 
+-	IRDA_DEBUG(2, "%s: next state=%s, service type=%d\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s: next state=%s, service type=%d\n", __func__ ,
+ 		   ircomm_tty_state[self->state], self->service_type);
+ 	*/
+ 	self->state = state;
+@@ -665,7 +665,7 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ 		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+ 	switch (event) {
+ 	case IRCOMM_TTY_ATTACH_CABLE:
+@@ -681,7 +681,7 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
+ 
+ 		if (self->iriap) {
+ 			IRDA_WARNING("%s(), busy with a previous query\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			return -EBUSY;
+ 		}
+ 
+@@ -709,7 +709,7 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
+ 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ 			   ircomm_tty_event[event]);
+ 		ret = -EINVAL;
+ 	}
+@@ -729,7 +729,7 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ 		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+ 
+ 	switch (event) {
+@@ -739,7 +739,7 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
+ 
+ 		if (self->iriap) {
+ 			IRDA_WARNING("%s(), busy with a previous query\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			return -EBUSY;
+ 		}
+ 
+@@ -782,7 +782,7 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
+ 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ 			   ircomm_tty_event[event]);
+ 		ret = -EINVAL;
+ 	}
+@@ -802,14 +802,14 @@ static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ 		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+ 
+ 	switch (event) {
+ 	case IRCOMM_TTY_GOT_PARAMETERS:
+ 		if (self->iriap) {
+ 			IRDA_WARNING("%s(), busy with a previous query\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			return -EBUSY;
+ 		}
+ 
+@@ -840,7 +840,7 @@ static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
+ 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ 			   ircomm_tty_event[event]);
+ 		ret = -EINVAL;
+ 	}
+@@ -860,7 +860,7 @@ static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ 		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+ 
+ 	switch (event) {
+@@ -889,7 +889,7 @@ static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
+ 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ 			   ircomm_tty_event[event]);
+ 		ret = -EINVAL;
+ 	}
+@@ -909,7 +909,7 @@ static int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ 		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
+ 
+ 	switch (event) {
+@@ -943,7 +943,7 @@ static int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
+ 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ 			   ircomm_tty_event[event]);
+ 		ret = -EINVAL;
+ 	}
+@@ -981,13 +981,13 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
+ 			self->settings.dce = IRCOMM_DELTA_CD;
+ 			ircomm_tty_check_modem_status(self);
+ 		} else {
+-			IRDA_DEBUG(0, "%s(), hanging up!\n", __FUNCTION__ );
++			IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ );
+ 			if (self->tty)
+ 				tty_hangup(self->tty);
+ 		}
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ 			   ircomm_tty_event[event]);
+ 		ret = -EINVAL;
+ 	}
+diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
+index 6030947..24cb3aa 100644
+--- a/net/irda/ircomm/ircomm_tty_ioctl.c
++++ b/net/irda/ircomm/ircomm_tty_ioctl.c
+@@ -57,7 +57,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
+ 	unsigned cflag, cval;
+ 	int baud;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	if (!self->tty || !self->tty->termios || !self->ircomm)
+ 		return;
+@@ -94,7 +94,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
+ 		self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
+ 		/* This got me. Bummer. Jean II */
+ 		if (self->service_type == IRCOMM_3_WIRE_RAW)
+-			IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __FUNCTION__);
++			IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__);
+ 	} else {
+ 		self->flags &= ~ASYNC_CTS_FLOW;
+ 		self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
+@@ -150,7 +150,7 @@ void ircomm_tty_set_termios(struct tty_struct *tty,
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ 	unsigned int cflag = tty->termios->c_cflag;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	if ((cflag == old_termios->c_cflag) &&
+ 	    (RELEVANT_IFLAG(tty->termios->c_iflag) ==
+@@ -199,7 +199,7 @@ int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file)
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ 	unsigned int result;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	if (tty->flags & (1 << TTY_IO_ERROR))
+ 		return -EIO;
+@@ -224,7 +224,7 @@ int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ {
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	if (tty->flags & (1 << TTY_IO_ERROR))
+ 		return -EIO;
+@@ -266,7 +266,7 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
+ 	if (!retinfo)
+ 		return -EFAULT;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	memset(&info, 0, sizeof(info));
+ 	info.line = self->line;
+@@ -302,7 +302,7 @@ static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *self,
+ 	struct serial_struct new_serial;
+ 	struct ircomm_tty_cb old_state, *state;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+ 		return -EFAULT;
+@@ -376,7 +376,7 @@ int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
+ 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ 	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+@@ -397,7 +397,7 @@ int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
+ 		break;
+ 
+ 	case TIOCGICOUNT:
+-		IRDA_DEBUG(0, "%s(), TIOCGICOUNT not impl!\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s(), TIOCGICOUNT not impl!\n", __func__ );
+ #if 0
+ 		save_flags(flags); cli();
+ 		cnow = driver->icount;
+diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
+index 8718591..ea319e3 100644
+--- a/net/irda/irda_device.c
++++ b/net/irda/irda_device.c
+@@ -90,7 +90,7 @@ static void leftover_dongle(void *arg)
+ 
+ void irda_device_cleanup(void)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	hashbin_delete(tasks, (FREE_FUNC) __irda_task_delete);
+ 
+@@ -107,7 +107,7 @@ void irda_device_set_media_busy(struct net_device *dev, int status)
+ {
+ 	struct irlap_cb *self;
+ 
+-	IRDA_DEBUG(4, "%s(%s)\n", __FUNCTION__, status ? "TRUE" : "FALSE");
++	IRDA_DEBUG(4, "%s(%s)\n", __func__, status ? "TRUE" : "FALSE");
+ 
+ 	self = (struct irlap_cb *) dev->atalk_ptr;
+ 
+@@ -147,11 +147,11 @@ int irda_device_is_receiving(struct net_device *dev)
+ 	struct if_irda_req req;
+ 	int ret;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	if (!dev->do_ioctl) {
+ 		IRDA_ERROR("%s: do_ioctl not impl. by device driver\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		return -1;
+ 	}
+ 
+@@ -191,7 +191,7 @@ static int irda_task_kick(struct irda_task *task)
+ 	int count = 0;
+ 	int timeout;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(task != NULL, return -1;);
+ 	IRDA_ASSERT(task->magic == IRDA_TASK_MAGIC, return -1;);
+@@ -201,14 +201,14 @@ static int irda_task_kick(struct irda_task *task)
+ 		timeout = task->function(task);
+ 		if (count++ > 100) {
+ 			IRDA_ERROR("%s: error in task handler!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			irda_task_delete(task);
+ 			return TRUE;
+ 		}
+ 	} while ((timeout == 0) && (task->state != IRDA_TASK_DONE));
+ 
+ 	if (timeout < 0) {
+-		IRDA_ERROR("%s: Error executing task!\n", __FUNCTION__);
++		IRDA_ERROR("%s: Error executing task!\n", __func__);
+ 		irda_task_delete(task);
+ 		return TRUE;
+ 	}
+@@ -241,7 +241,7 @@ static int irda_task_kick(struct irda_task *task)
+ 		finished = FALSE;
+ 	} else {
+ 		IRDA_DEBUG(0, "%s(), not finished, and no timeout!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		finished = FALSE;
+ 	}
+ 
+@@ -258,7 +258,7 @@ static void irda_task_timer_expired(void *data)
+ {
+ 	struct irda_task *task;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	task = (struct irda_task *) data;
+ 
+diff --git a/net/irda/iriap.c b/net/irda/iriap.c
+index 390a790..9e15c82 100644
+--- a/net/irda/iriap.c
++++ b/net/irda/iriap.c
+@@ -108,7 +108,7 @@ int __init iriap_init(void)
+ 	irias_objects = hashbin_new(HB_LOCK);
+ 	if (!irias_objects) {
+ 		IRDA_WARNING("%s: Can't allocate irias_objects hashbin!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		hashbin_delete(iriap, NULL);
+ 		return -ENOMEM;
+ 	}
+@@ -139,7 +139,7 @@ int __init iriap_init(void)
+ 	 */
+ 	server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
+ 	if (!server) {
+-		IRDA_DEBUG(0, "%s(), unable to open server\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), unable to open server\n", __func__);
+ 		return -1;
+ 	}
+ 	iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
+@@ -171,11 +171,11 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
+ {
+ 	struct iriap_cb *self;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	self = kzalloc(sizeof(*self), GFP_ATOMIC);
+ 	if (!self) {
+-		IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -217,7 +217,7 @@ EXPORT_SYMBOL(iriap_open);
+  */
+ static void __iriap_close(struct iriap_cb *self)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -241,7 +241,7 @@ void iriap_close(struct iriap_cb *self)
+ {
+ 	struct iriap_cb *entry;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -262,7 +262,7 @@ static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
+ {
+ 	notify_t notify;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	irda_notify_init(&notify);
+ 	notify.connect_confirm       = iriap_connect_confirm;
+@@ -277,7 +277,7 @@ static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
+ 
+ 	self->lsap = irlmp_open_lsap(slsap_sel, &notify, 0);
+ 	if (self->lsap == NULL) {
+-		IRDA_ERROR("%s: Unable to allocated LSAP!\n", __FUNCTION__);
++		IRDA_ERROR("%s: Unable to allocated LSAP!\n", __func__);
+ 		return -1;
+ 	}
+ 	self->slsap_sel = self->lsap->slsap_sel;
+@@ -297,7 +297,7 @@ static void iriap_disconnect_indication(void *instance, void *sap,
+ {
+ 	struct iriap_cb *self;
+ 
+-	IRDA_DEBUG(4, "%s(), reason=%s\n", __FUNCTION__, irlmp_reasons[reason]);
++	IRDA_DEBUG(4, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
+ 
+ 	self = (struct iriap_cb *) instance;
+ 
+@@ -313,7 +313,7 @@ static void iriap_disconnect_indication(void *instance, void *sap,
+ 		dev_kfree_skb(skb);
+ 
+ 	if (self->mode == IAS_CLIENT) {
+-		IRDA_DEBUG(4, "%s(), disconnect as client\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), disconnect as client\n", __func__);
+ 
+ 
+ 		iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION,
+@@ -326,7 +326,7 @@ static void iriap_disconnect_indication(void *instance, void *sap,
+ 		if (self->confirm)
+ 			self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
+ 	} else {
+-		IRDA_DEBUG(4, "%s(), disconnect as server\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), disconnect as server\n", __func__);
+ 		iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION,
+ 				      NULL);
+ 		iriap_close(self);
+@@ -340,7 +340,7 @@ static void iriap_disconnect_request(struct iriap_cb *self)
+ {
+ 	struct sk_buff *tx_skb;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -349,7 +349,7 @@ static void iriap_disconnect_request(struct iriap_cb *self)
+ 	if (tx_skb == NULL) {
+ 		IRDA_DEBUG(0,
+ 			   "%s(), Could not allocate an sk_buff of length %d\n",
+-			   __FUNCTION__, LMP_MAX_HEADER);
++			   __func__, LMP_MAX_HEADER);
+ 		return;
+ 	}
+ 
+@@ -453,13 +453,13 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ 	/* Get length, MSB first */
+ 	len = be16_to_cpu(get_unaligned((__be16 *)(fp+n))); n += 2;
+ 
+-	IRDA_DEBUG(4, "%s(), len=%d\n", __FUNCTION__, len);
++	IRDA_DEBUG(4, "%s(), len=%d\n", __func__, len);
+ 
+ 	/* Get object ID, MSB first */
+ 	obj_id = be16_to_cpu(get_unaligned((__be16 *)(fp+n))); n += 2;
+ 
+ 	type = fp[n++];
+-	IRDA_DEBUG(4, "%s(), Value type = %d\n", __FUNCTION__, type);
++	IRDA_DEBUG(4, "%s(), Value type = %d\n", __func__, type);
+ 
+ 	switch (type) {
+ 	case IAS_INTEGER:
+@@ -468,7 +468,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ 		value = irias_new_integer_value(tmp_cpu32);
+ 
+ 		/*  Legal values restricted to 0x01-0x6f, page 15 irttp */
+-		IRDA_DEBUG(4, "%s(), lsap=%d\n", __FUNCTION__, value->t.integer);
++		IRDA_DEBUG(4, "%s(), lsap=%d\n", __func__, value->t.integer);
+ 		break;
+ 	case IAS_STRING:
+ 		charset = fp[n++];
+@@ -488,7 +488,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ /*		case CS_UNICODE: */
+ 		default:
+ 			IRDA_DEBUG(0, "%s(), charset %s, not supported\n",
+-				   __FUNCTION__, ias_charset_types[charset]);
++				   __func__, ias_charset_types[charset]);
+ 
+ 			/* Aborting, close connection! */
+ 			iriap_disconnect_request(self);
+@@ -496,7 +496,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ 			/* break; */
+ 		}
+ 		value_len = fp[n++];
+-		IRDA_DEBUG(4, "%s(), strlen=%d\n", __FUNCTION__, value_len);
++		IRDA_DEBUG(4, "%s(), strlen=%d\n", __func__, value_len);
+ 
+ 		/* Make sure the string is null-terminated */
+ 		fp[n+value_len] = 0x00;
+@@ -526,7 +526,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ 	if (self->confirm)
+ 		self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
+ 	else {
+-		IRDA_DEBUG(0, "%s(), missing handler!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), missing handler!\n", __func__);
+ 		irias_delete_value(value);
+ 	}
+ }
+@@ -548,7 +548,7 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self,
+ 	__be16 tmp_be16;
+ 	__u8 *fp;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -610,12 +610,12 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self,
+ 		memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
+ 		break;
+ 	case IAS_MISSING:
+-		IRDA_DEBUG( 3, "%s: sending IAS_MISSING\n", __FUNCTION__);
++		IRDA_DEBUG( 3, "%s: sending IAS_MISSING\n", __func__);
+ 		skb_put(tx_skb, 1);
+ 		fp[n++] = value->type;
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), type not implemented!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), type not implemented!\n", __func__);
+ 		break;
+ 	}
+ 	iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, tx_skb);
+@@ -642,7 +642,7 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
+ 	__u8 *fp;
+ 	int n;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -697,7 +697,7 @@ void iriap_send_ack(struct iriap_cb *self)
+ 	struct sk_buff *tx_skb;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -728,7 +728,7 @@ void iriap_connect_request(struct iriap_cb *self)
+ 				    self->saddr, self->daddr,
+ 				    NULL, NULL);
+ 	if (ret < 0) {
+-		IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
+ 		self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
+ 	}
+ }
+@@ -776,7 +776,7 @@ static void iriap_connect_indication(void *instance, void *sap,
+ {
+ 	struct iriap_cb *self, *new;
+ 
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 
+ 	self = (struct iriap_cb *) instance;
+ 
+@@ -787,14 +787,14 @@ static void iriap_connect_indication(void *instance, void *sap,
+ 	/* Start new server */
+ 	new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
+ 	if (!new) {
+-		IRDA_DEBUG(0, "%s(), open failed\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), open failed\n", __func__);
+ 		goto out;
+ 	}
+ 
+ 	/* Now attach up the new "socket" */
+ 	new->lsap = irlmp_dup(self->lsap, new);
+ 	if (!new->lsap) {
+-		IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
+ 		goto out;
+ 	}
+ 
+@@ -824,7 +824,7 @@ static int iriap_data_indication(void *instance, void *sap,
+ 	__u8  *frame;
+ 	__u8  opcode;
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	self = (struct iriap_cb *) instance;
+ 
+@@ -836,7 +836,7 @@ static int iriap_data_indication(void *instance, void *sap,
+ 
+ 	if (self->mode == IAS_SERVER) {
+ 		/* Call server */
+-		IRDA_DEBUG(4, "%s(), Calling server!\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), Calling server!\n", __func__);
+ 		iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
+ 		goto out;
+ 	}
+@@ -844,13 +844,13 @@ static int iriap_data_indication(void *instance, void *sap,
+ 	if (~opcode & IAP_LST) {
+ 		IRDA_WARNING("%s:, IrIAS multiframe commands or "
+ 			     "results is not implemented yet!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		goto out;
+ 	}
+ 
+ 	/* Check for ack frames since they don't contain any data */
+ 	if (opcode & IAP_ACK) {
+-		IRDA_DEBUG(0, "%s() Got ack frame!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s() Got ack frame!\n", __func__);
+ 		goto out;
+ 	}
+ 
+@@ -868,7 +868,7 @@ static int iriap_data_indication(void *instance, void *sap,
+ 			iriap_getvaluebyclass_confirm(self, skb);
+ 			break;
+ 		case IAS_CLASS_UNKNOWN:
+-			IRDA_DEBUG(1, "%s(), No such class!\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), No such class!\n", __func__);
+ 			/* Finished, close connection! */
+ 			iriap_disconnect_request(self);
+ 
+@@ -881,7 +881,7 @@ static int iriap_data_indication(void *instance, void *sap,
+ 					      self->priv);
+ 			break;
+ 		case IAS_ATTRIB_UNKNOWN:
+-			IRDA_DEBUG(1, "%s(), No such attribute!\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), No such attribute!\n", __func__);
+ 			/* Finished, close connection! */
+ 			iriap_disconnect_request(self);
+ 
+@@ -896,7 +896,7 @@ static int iriap_data_indication(void *instance, void *sap,
+ 		}
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __FUNCTION__,
++		IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __func__,
+ 			   opcode);
+ 		break;
+ 	}
+@@ -918,7 +918,7 @@ void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
+ 	__u8 *fp;
+ 	__u8 opcode;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -929,7 +929,7 @@ void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
+ 	opcode = fp[0];
+ 	if (~opcode & 0x80) {
+ 		IRDA_WARNING("%s: IrIAS multiframe commands or results "
+-			     "is not implemented yet!\n", __FUNCTION__);
++			     "is not implemented yet!\n", __func__);
+ 		return;
+ 	}
+ 	opcode &= 0x7f; /* Mask away LST bit */
+@@ -937,7 +937,7 @@ void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
+ 	switch (opcode) {
+ 	case GET_INFO_BASE:
+ 		IRDA_WARNING("%s: GetInfoBaseDetails not implemented yet!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		break;
+ 	case GET_VALUE_BY_CLASS:
+ 		iriap_getvaluebyclass_indication(self, skb);
+diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c
+index 8fb9d72..a301cbd 100644
+--- a/net/irda/iriap_event.c
++++ b/net/irda/iriap_event.c
+@@ -185,7 +185,7 @@ static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
+ 	case IAP_LM_DISCONNECT_INDICATION:
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), Unknown event %d\n", __FUNCTION__, event);
++		IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
+ 		break;
+ 	}
+ }
+@@ -217,7 +217,7 @@ static void state_s_connecting(struct iriap_cb *self, IRIAP_EVENT event,
+ 		iriap_next_client_state(self, S_DISCONNECT);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), Unknown event %d\n", __FUNCTION__, event);
++		IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
+ 		break;
+ 	}
+ }
+@@ -269,7 +269,7 @@ static void state_s_make_call(struct iriap_cb *self, IRIAP_EVENT event,
+ 		iriap_next_call_state(self, S_OUTSTANDING);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), Unknown event %d\n", __FUNCTION__, event);
++		IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
+ 		break;
+ 	}
+ }
+@@ -283,7 +283,7 @@ static void state_s_make_call(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_s_calling(struct iriap_cb *self, IRIAP_EVENT event,
+ 			    struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+ 
+ /*
+@@ -305,7 +305,7 @@ static void state_s_outstanding(struct iriap_cb *self, IRIAP_EVENT event,
+ 		iriap_next_call_state(self, S_WAIT_FOR_CALL);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), Unknown event %d\n", __FUNCTION__, event);
++		IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
+ 		break;
+ 	}
+ }
+@@ -318,7 +318,7 @@ static void state_s_outstanding(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_s_replying(struct iriap_cb *self, IRIAP_EVENT event,
+ 			     struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+ 
+ /*
+@@ -330,7 +330,7 @@ static void state_s_replying(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event,
+ 				  struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+ 
+ 
+@@ -343,7 +343,7 @@ static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_s_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
+ 				struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+ 
+ /**************************************************************************
+@@ -367,7 +367,7 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
+ 	case IAP_LM_CONNECT_INDICATION:
+ 		tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
+ 		if (tx_skb == NULL) {
+-			IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);
++			IRDA_WARNING("%s: unable to malloc!\n", __func__);
+ 			return;
+ 		}
+ 
+@@ -386,7 +386,7 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
+ 		iriap_next_r_connect_state(self, R_RECEIVING);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), unknown event %d\n", __FUNCTION__, event);
++		IRDA_DEBUG(0, "%s(), unknown event %d\n", __func__, event);
+ 		break;
+ 	}
+ }
+@@ -397,7 +397,7 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event,
+ 			 struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	switch (event) {
+ 	case IAP_LM_DISCONNECT_INDICATION:
+@@ -406,7 +406,7 @@ static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event,
+ 		iriap_next_r_connect_state(self, R_WAITING);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), unknown event!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), unknown event!\n", __func__);
+ 		break;
+ 	}
+ }
+@@ -421,13 +421,13 @@ static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_waiting(struct iriap_cb *self, IRIAP_EVENT event,
+ 			    struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+ 
+ static void state_r_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
+ 				struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+ 
+ /*
+@@ -439,7 +439,7 @@ static void state_r_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event,
+ 			      struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	switch (event) {
+ 	case IAP_RECV_F_LST:
+@@ -448,7 +448,7 @@ static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event,
+ 		iriap_call_indication(self, skb);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), unknown event!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), unknown event!\n", __func__);
+ 		break;
+ 	}
+ }
+@@ -462,7 +462,7 @@ static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
+ 			    struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(skb != NULL, return;);
+ 	IRDA_ASSERT(self != NULL, return;);
+@@ -483,7 +483,7 @@ static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
+ 		irlmp_data_request(self->lsap, skb);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), unknown event!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), unknown event!\n", __func__);
+ 		break;
+ 	}
+ }
+@@ -491,7 +491,7 @@ static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_returning(struct iriap_cb *self, IRIAP_EVENT event,
+ 			      struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(0, "%s(), event=%d\n", __FUNCTION__, event);
++	IRDA_DEBUG(0, "%s(), event=%d\n", __func__, event);
+ 
+ 	switch (event) {
+ 	case IAP_RECV_F_LST:
+diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
+index cbcf043..99ebb96 100644
+--- a/net/irda/irias_object.c
++++ b/net/irda/irias_object.c
+@@ -47,12 +47,12 @@ struct ias_object *irias_new_object( char *name, int id)
+ {
+ 	struct ias_object *obj;
+ 
+-	IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG( 4, "%s()\n", __func__);
+ 
+ 	obj = kzalloc(sizeof(struct ias_object), GFP_ATOMIC);
+ 	if (obj == NULL) {
+ 		IRDA_WARNING("%s(), Unable to allocate object!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -60,7 +60,7 @@ struct ias_object *irias_new_object( char *name, int id)
+ 	obj->name = kstrndup(name, IAS_MAX_CLASSNAME, GFP_ATOMIC);
+ 	if (!obj->name) {
+ 		IRDA_WARNING("%s(), Unable to allocate name!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		kfree(obj);
+ 		return NULL;
+ 	}
+@@ -73,7 +73,7 @@ struct ias_object *irias_new_object( char *name, int id)
+ 
+ 	if (obj->attribs == NULL) {
+ 		IRDA_WARNING("%s(), Unable to allocate attribs!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		kfree(obj->name);
+ 		kfree(obj);
+ 		return NULL;
+@@ -134,7 +134,7 @@ int irias_delete_object(struct ias_object *obj)
+ 	node = hashbin_remove_this(irias_objects, (irda_queue_t *) obj);
+ 	if (!node)
+ 		IRDA_DEBUG( 0, "%s(), object already removed!\n",
+-			    __FUNCTION__);
++			    __func__);
+ 
+ 	/* Destroy */
+ 	__irias_delete_object(obj);
+@@ -268,7 +268,7 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
+ 	/* Find object */
+ 	obj = hashbin_lock_find(irias_objects, 0, obj_name);
+ 	if (obj == NULL) {
+-		IRDA_WARNING("%s: Unable to find object: %s\n", __FUNCTION__,
++		IRDA_WARNING("%s: Unable to find object: %s\n", __func__,
+ 			     obj_name);
+ 		return -1;
+ 	}
+@@ -280,14 +280,14 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
+ 	attrib = hashbin_find(obj->attribs, 0, attrib_name);
+ 	if (attrib == NULL) {
+ 		IRDA_WARNING("%s: Unable to find attribute: %s\n",
+-			     __FUNCTION__, attrib_name);
++			     __func__, attrib_name);
+ 		spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
+ 		return -1;
+ 	}
+ 
+ 	if ( attrib->value->type != new_value->type) {
+ 		IRDA_DEBUG( 0, "%s(), changing value type not allowed!\n",
+-			    __FUNCTION__);
++			    __func__);
+ 		spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
+ 		return -1;
+ 	}
+@@ -322,7 +322,7 @@ void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
+ 	attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
+ 	if (attrib == NULL) {
+ 		IRDA_WARNING("%s: Unable to allocate attribute!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		return;
+ 	}
+ 
+@@ -333,7 +333,7 @@ void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
+ 	attrib->value = irias_new_integer_value(value);
+ 	if (!attrib->name || !attrib->value) {
+ 		IRDA_WARNING("%s: Unable to allocate attribute!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		if (attrib->value)
+ 			irias_delete_value(attrib->value);
+ 		kfree(attrib->name);
+@@ -366,7 +366,7 @@ void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+ 	attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
+ 	if (attrib == NULL) {
+ 		IRDA_WARNING("%s: Unable to allocate attribute!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		return;
+ 	}
+ 
+@@ -376,7 +376,7 @@ void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+ 	attrib->value = irias_new_octseq_value( octets, len);
+ 	if (!attrib->name || !attrib->value) {
+ 		IRDA_WARNING("%s: Unable to allocate attribute!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		if (attrib->value)
+ 			irias_delete_value(attrib->value);
+ 		kfree(attrib->name);
+@@ -408,7 +408,7 @@ void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
+ 	attrib = kzalloc(sizeof( struct ias_attrib), GFP_ATOMIC);
+ 	if (attrib == NULL) {
+ 		IRDA_WARNING("%s: Unable to allocate attribute!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		return;
+ 	}
+ 
+@@ -418,7 +418,7 @@ void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
+ 	attrib->value = irias_new_string_value(value);
+ 	if (!attrib->name || !attrib->value) {
+ 		IRDA_WARNING("%s: Unable to allocate attribute!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		if (attrib->value)
+ 			irias_delete_value(attrib->value);
+ 		kfree(attrib->name);
+@@ -442,7 +442,7 @@ struct ias_value *irias_new_integer_value(int integer)
+ 
+ 	value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ 	if (value == NULL) {
+-		IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -467,7 +467,7 @@ struct ias_value *irias_new_string_value(char *string)
+ 
+ 	value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ 	if (value == NULL) {
+-		IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -475,7 +475,7 @@ struct ias_value *irias_new_string_value(char *string)
+ 	value->charset = CS_ASCII;
+ 	value->t.string = kstrndup(string, IAS_MAX_STRING, GFP_ATOMIC);
+ 	if (!value->t.string) {
+-		IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ 		kfree(value);
+ 		return NULL;
+ 	}
+@@ -498,7 +498,7 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
+ 
+ 	value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ 	if (value == NULL) {
+-		IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -510,7 +510,7 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
+ 
+ 	value->t.oct_seq = kmemdup(octseq, len, GFP_ATOMIC);
+ 	if (value->t.oct_seq == NULL){
+-		IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ 		kfree(value);
+ 		return NULL;
+ 	}
+@@ -523,7 +523,7 @@ struct ias_value *irias_new_missing_value(void)
+ 
+ 	value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ 	if (value == NULL) {
+-		IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -540,7 +540,7 @@ struct ias_value *irias_new_missing_value(void)
+  */
+ void irias_delete_value(struct ias_value *value)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(value != NULL, return;);
+ 
+@@ -558,7 +558,7 @@ void irias_delete_value(struct ias_value *value)
+ 		 kfree(value->t.oct_seq);
+ 		 break;
+ 	default:
+-		IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), Unknown value type!\n", __func__);
+ 		break;
+ 	}
+ 	kfree(value);
+diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
+index fff52d5..6be1ec2 100644
+--- a/net/irda/irlan/irlan_client.c
++++ b/net/irda/irlan/irlan_client.c
+@@ -72,7 +72,7 @@ static void irlan_client_kick_timer_expired(void *data)
+ {
+ 	struct irlan_cb *self = (struct irlan_cb *) data;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -91,7 +91,7 @@ static void irlan_client_kick_timer_expired(void *data)
+ 
+ static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	irda_start_timer(&self->client.kick_timer, timeout, (void *) self,
+ 			 irlan_client_kick_timer_expired);
+@@ -105,7 +105,7 @@ static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
+  */
+ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
+ {
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(1, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -117,7 +117,7 @@ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
+ 	if ((self->client.state != IRLAN_IDLE) ||
+ 	    (self->provider.access_type == ACCESS_DIRECT))
+ 	{
+-			IRDA_DEBUG(0, "%s(), already awake!\n", __FUNCTION__ );
++			IRDA_DEBUG(0, "%s(), already awake!\n", __func__ );
+ 			return;
+ 	}
+ 
+@@ -126,7 +126,7 @@ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
+ 	self->daddr = daddr;
+ 
+ 	if (self->disconnect_reason == LM_USER_REQUEST) {
+-			IRDA_DEBUG(0, "%s(), still stopped by user\n", __FUNCTION__ );
++			IRDA_DEBUG(0, "%s(), still stopped by user\n", __func__ );
+ 			return;
+ 	}
+ 
+@@ -153,7 +153,7 @@ void irlan_client_discovery_indication(discinfo_t *discovery,
+ 	struct irlan_cb *self;
+ 	__u32 saddr, daddr;
+ 
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(1, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(discovery != NULL, return;);
+ 
+@@ -175,7 +175,7 @@ void irlan_client_discovery_indication(discinfo_t *discovery,
+ 	if (self) {
+ 		IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;);
+ 
+-		IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __FUNCTION__ ,
++		IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __func__ ,
+ 		      daddr);
+ 
+ 		irlan_client_wakeup(self, saddr, daddr);
+@@ -195,7 +195,7 @@ static int irlan_client_ctrl_data_indication(void *instance, void *sap,
+ {
+ 	struct irlan_cb *self;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	self = (struct irlan_cb *) instance;
+ 
+@@ -206,7 +206,7 @@ static int irlan_client_ctrl_data_indication(void *instance, void *sap,
+ 	irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
+ 
+ 	/* Ready for a new command */
+-	IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __func__ );
+ 	self->client.tx_busy = FALSE;
+ 
+ 	/* Check if we have some queued commands waiting to be sent */
+@@ -223,7 +223,7 @@ static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
+ 	struct tsap_cb *tsap;
+ 	struct sk_buff *skb;
+ 
+-	IRDA_DEBUG(4, "%s(), reason=%d\n", __FUNCTION__ , reason);
++	IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
+ 
+ 	self = (struct irlan_cb *) instance;
+ 	tsap = (struct tsap_cb *) sap;
+@@ -255,7 +255,7 @@ static void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
+ 	struct tsap_cb *tsap;
+ 	notify_t notify;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -275,7 +275,7 @@ static void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
+ 
+ 	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
+ 	if (!tsap) {
+-		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
+ 		return;
+ 	}
+ 	self->client.tsap_ctrl = tsap;
+@@ -295,7 +295,7 @@ static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
+ {
+ 	struct irlan_cb *self;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	self = (struct irlan_cb *) instance;
+ 
+@@ -374,13 +374,13 @@ void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
+ 
+ 	IRDA_ASSERT(skb != NULL, return;);
+ 
+-	IRDA_DEBUG(4, "%s() skb->len=%d\n", __FUNCTION__ , (int) skb->len);
++	IRDA_DEBUG(4, "%s() skb->len=%d\n", __func__ , (int) skb->len);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+ 
+ 	if (!skb) {
+-		IRDA_ERROR("%s(), Got NULL skb!\n", __FUNCTION__);
++		IRDA_ERROR("%s(), Got NULL skb!\n", __func__);
+ 		return;
+ 	}
+ 	frame = skb->data;
+@@ -405,7 +405,7 @@ void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
+ 	/* How many parameters? */
+ 	count = frame[1];
+ 
+-	IRDA_DEBUG(4, "%s(), got %d parameters\n", __FUNCTION__ , count);
++	IRDA_DEBUG(4, "%s(), got %d parameters\n", __func__ , count);
+ 
+ 	ptr = frame+2;
+ 
+@@ -413,7 +413,7 @@ void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
+ 	for (i=0; i<count;i++) {
+ 		ret = irlan_extract_param(ptr, name, value, &val_len);
+ 		if (ret < 0) {
+-			IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __FUNCTION__ );
++			IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __func__ );
+ 			break;
+ 		}
+ 		ptr += ret;
+@@ -438,7 +438,7 @@ static void irlan_check_response_param(struct irlan_cb *self, char *param,
+ 	int i;
+ 	DECLARE_MAC_BUF(mac);
+ 
+-	IRDA_DEBUG(4, "%s(), parm=%s\n", __FUNCTION__ , param);
++	IRDA_DEBUG(4, "%s(), parm=%s\n", __func__ , param);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -476,7 +476,7 @@ static void irlan_check_response_param(struct irlan_cb *self, char *param,
+ 		else if (strcmp(value, "HOSTED") == 0)
+ 			self->client.access_type = ACCESS_HOSTED;
+ 		else {
+-			IRDA_DEBUG(2, "%s(), unknown access type!\n", __FUNCTION__ );
++			IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
+ 		}
+ 	}
+ 	/* IRLAN version */
+@@ -498,14 +498,14 @@ static void irlan_check_response_param(struct irlan_cb *self, char *param,
+ 		memcpy(&tmp_cpu, value, 2); /* Align value */
+ 		le16_to_cpus(&tmp_cpu);     /* Convert to host order */
+ 		self->client.recv_arb_val = tmp_cpu;
+-		IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __FUNCTION__ ,
++		IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __func__ ,
+ 			   self->client.recv_arb_val);
+ 	}
+ 	if (strcmp(param, "MAX_FRAME") == 0) {
+ 		memcpy(&tmp_cpu, value, 2); /* Align value */
+ 		le16_to_cpus(&tmp_cpu);     /* Convert to host order */
+ 		self->client.max_frame = tmp_cpu;
+-		IRDA_DEBUG(4, "%s(), max frame=%d\n", __FUNCTION__ ,
++		IRDA_DEBUG(4, "%s(), max frame=%d\n", __func__ ,
+ 			   self->client.max_frame);
+ 	}
+ 
+@@ -539,7 +539,7 @@ void irlan_client_get_value_confirm(int result, __u16 obj_id,
+ {
+ 	struct irlan_cb *self;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(priv != NULL, return;);
+ 
+@@ -552,7 +552,7 @@ void irlan_client_get_value_confirm(int result, __u16 obj_id,
+ 
+ 	/* Check if request succeeded */
+ 	if (result != IAS_SUCCESS) {
+-		IRDA_DEBUG(2, "%s(), got NULL value!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), got NULL value!\n", __func__ );
+ 		irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL,
+ 				      NULL);
+ 		return;
+@@ -570,7 +570,7 @@ void irlan_client_get_value_confirm(int result, __u16 obj_id,
+ 		irias_delete_value(value);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), unknown type!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), unknown type!\n", __func__ );
+ 		break;
+ 	}
+ 	irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
+diff --git a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c
+index 6afcee5..8d5a8eb 100644
+--- a/net/irda/irlan/irlan_client_event.c
++++ b/net/irda/irlan/irlan_client_event.c
+@@ -92,7 +92,7 @@ void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ 				   struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -101,7 +101,7 @@ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ 	case IRLAN_DISCOVERY_INDICATION:
+ 		if (self->client.iriap) {
+ 			IRDA_WARNING("%s(), busy with a previous query\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			return -EBUSY;
+ 		}
+ 
+@@ -114,10 +114,10 @@ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ 					      "IrLAN", "IrDA:TinyTP:LsapSel");
+ 		break;
+ 	case IRLAN_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(4, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(4, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -136,7 +136,7 @@ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
+ 				    struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -154,7 +154,7 @@ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_client_state(self, IRLAN_CONN);
+ 		break;
+ 	case IRLAN_IAS_PROVIDER_NOT_AVAIL:
+-		IRDA_DEBUG(2, "%s(), IAS_PROVIDER_NOT_AVAIL\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IAS_PROVIDER_NOT_AVAIL\n", __func__ );
+ 		irlan_next_client_state(self, IRLAN_IDLE);
+ 
+ 		/* Give the client a kick! */
+@@ -167,10 +167,10 @@ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_client_state(self, IRLAN_IDLE);
+ 		break;
+ 	case IRLAN_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -189,7 +189,7 @@ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
+ 				   struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 
+@@ -204,10 +204,10 @@ static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_client_state(self, IRLAN_IDLE);
+ 		break;
+ 	case IRLAN_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -224,7 +224,7 @@ static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ 				   struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 
+@@ -244,10 +244,10 @@ static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_client_state(self, IRLAN_IDLE);
+ 		break;
+ 	case IRLAN_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -266,7 +266,7 @@ static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
+ 				    struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 
+@@ -281,10 +281,10 @@ static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_client_state(self, IRLAN_IDLE);
+ 		break;
+ 	case IRLAN_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -305,7 +305,7 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ {
+ 	struct qos_info qos;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 
+@@ -344,7 +344,7 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ 			irlan_next_client_state(self, IRLAN_DATA);
+ 			break;
+ 		default:
+-			IRDA_DEBUG(2, "%s(), unknown access type!\n", __FUNCTION__ );
++			IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
+ 			break;
+ 		}
+ 		break;
+@@ -353,10 +353,10 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_client_state(self, IRLAN_IDLE);
+ 		break;
+ 	case IRLAN_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 
+@@ -376,7 +376,7 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
+ 				   struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 
+@@ -390,10 +390,10 @@ static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_client_state(self, IRLAN_IDLE);
+ 		break;
+ 	case IRLAN_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -407,7 +407,7 @@ static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
+ {
+ 	struct qos_info qos;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 
+@@ -429,7 +429,7 @@ static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
+ 		} else if (self->client.recv_arb_val >
+ 			   self->provider.send_arb_val)
+ 		{
+-			IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __FUNCTION__ );
++			IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __func__ );
+ 		}
+ 		break;
+ 	case IRLAN_DATA_CONNECT_INDICATION:
+@@ -440,10 +440,10 @@ static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_client_state(self, IRLAN_IDLE);
+ 		break;
+ 	case IRLAN_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -462,7 +462,7 @@ static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ 				   struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -476,7 +476,7 @@ static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_client_state(self, IRLAN_IDLE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -494,7 +494,7 @@ static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
+ 				    struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	if (skb)
+ 		dev_kfree_skb(skb);
+@@ -511,7 +511,7 @@ static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event,
+ 				   struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	if (skb)
+ 		dev_kfree_skb(skb);
+diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
+index 1eb4bbc..9a1cd87 100644
+--- a/net/irda/irlan/irlan_common.c
++++ b/net/irda/irlan/irlan_common.c
+@@ -54,13 +54,6 @@
+ #include <net/irda/irlan_filter.h>
+ 
+ 
+-/*
+- * Send gratuitous ARP when connected to a new AP or not. May be a clever
+- * thing to do, but for some reason the machine crashes if you use DHCP. So
+- * lets not use it by default.
+- */
+-#undef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
+-
+ /* extern char sysctl_devname[]; */
+ 
+ /*
+@@ -124,7 +117,7 @@ static int __init irlan_init(void)
+ 	struct irlan_cb *new;
+ 	__u16 hints;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ #ifdef CONFIG_PROC_FS
+ 	{ struct proc_dir_entry *proc;
+@@ -136,7 +129,7 @@ static int __init irlan_init(void)
+ 	}
+ #endif /* CONFIG_PROC_FS */
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 	hints = irlmp_service_to_hint(S_LAN);
+ 
+ 	/* Register with IrLMP as a client */
+@@ -179,7 +172,7 @@ static void __exit irlan_cleanup(void)
+ {
+ 	struct irlan_cb *self, *next;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	irlmp_unregister_client(ckey);
+ 	irlmp_unregister_service(skey);
+@@ -207,7 +200,7 @@ static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
+ 	struct net_device *dev;
+ 	struct irlan_cb *self;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	/* Create network device with irlan */
+ 	dev = alloc_irlandev(eth ? "eth%d" : "irlan%d");
+@@ -252,7 +245,7 @@ static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
+ 
+ 	if (register_netdev(dev)) {
+ 		IRDA_DEBUG(2, "%s(), register_netdev() failed!\n",
+-			   __FUNCTION__ );
++			   __func__ );
+ 		self = NULL;
+ 		free_netdev(dev);
+ 	} else {
+@@ -272,7 +265,7 @@ static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
+  */
+ static void __irlan_close(struct irlan_cb *self)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	ASSERT_RTNL();
+ 	IRDA_ASSERT(self != NULL, return;);
+@@ -320,7 +313,7 @@ static void irlan_connect_indication(void *instance, void *sap,
+ 	struct irlan_cb *self;
+ 	struct tsap_cb *tsap;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	self = (struct irlan_cb *) instance;
+ 	tsap = (struct tsap_cb *) sap;
+@@ -332,7 +325,7 @@ static void irlan_connect_indication(void *instance, void *sap,
+ 	self->max_sdu_size = max_sdu_size;
+ 	self->max_header_size = max_header_size;
+ 
+-	IRDA_DEBUG(0, "%s: We are now connected!\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s: We are now connected!\n", __func__);
+ 
+ 	del_timer(&self->watchdog_timer);
+ 
+@@ -376,7 +369,7 @@ static void irlan_connect_confirm(void *instance, void *sap,
+ 
+ 	/* TODO: we could set the MTU depending on the max_sdu_size */
+ 
+-	IRDA_DEBUG(0, "%s: We are now connected!\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s: We are now connected!\n", __func__);
+ 	del_timer(&self->watchdog_timer);
+ 
+ 	/*
+@@ -393,9 +386,6 @@ static void irlan_connect_confirm(void *instance, void *sap,
+ 	/* Ready to transfer Ethernet frames */
+ 	netif_start_queue(self->dev);
+ 	self->disconnect_reason = 0; /* Clear reason */
+-#ifdef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
+-	irlan_eth_send_gratuitous_arp(&self->dev);
+-#endif
+ 	wake_up_interruptible(&self->open_wait);
+ }
+ 
+@@ -412,7 +402,7 @@ static void irlan_disconnect_indication(void *instance,
+ 	struct irlan_cb *self;
+ 	struct tsap_cb *tsap;
+ 
+-	IRDA_DEBUG(0, "%s(), reason=%d\n", __FUNCTION__ , reason);
++	IRDA_DEBUG(0, "%s(), reason=%d\n", __func__ , reason);
+ 
+ 	self = (struct irlan_cb *) instance;
+ 	tsap = (struct tsap_cb *) sap;
+@@ -431,22 +421,22 @@ static void irlan_disconnect_indication(void *instance,
+ 
+ 	switch (reason) {
+ 	case LM_USER_REQUEST: /* User request */
+-		IRDA_DEBUG(2, "%s(), User requested\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), User requested\n", __func__ );
+ 		break;
+ 	case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
+-		IRDA_DEBUG(2, "%s(), Unexpected IrLAP disconnect\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), Unexpected IrLAP disconnect\n", __func__ );
+ 		break;
+ 	case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */
+-		IRDA_DEBUG(2, "%s(), IrLAP connect failed\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IrLAP connect failed\n", __func__ );
+ 		break;
+ 	case LM_LAP_RESET:  /* IrLAP reset */
+-		IRDA_DEBUG(2, "%s(), IrLAP reset\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IrLAP reset\n", __func__ );
+ 		break;
+ 	case LM_INIT_DISCONNECT:
+-		IRDA_DEBUG(2, "%s(), IrLMP connect failed\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), IrLMP connect failed\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);
++		IRDA_ERROR("%s(), Unknown disconnect reason\n", __func__);
+ 		break;
+ 	}
+ 
+@@ -468,7 +458,7 @@ void irlan_open_data_tsap(struct irlan_cb *self)
+ 	struct tsap_cb *tsap;
+ 	notify_t notify;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -490,7 +480,7 @@ void irlan_open_data_tsap(struct irlan_cb *self)
+ 
+ 	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
+ 	if (!tsap) {
+-		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
+ 		return;
+ 	}
+ 	self->tsap_data = tsap;
+@@ -504,7 +494,7 @@ void irlan_open_data_tsap(struct irlan_cb *self)
+ 
+ void irlan_close_tsaps(struct irlan_cb *self)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -594,7 +584,7 @@ int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
+ {
+ 	struct sk_buff *skb;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	if (irda_lock(&self->client.tx_busy) == FALSE)
+ 		return -EBUSY;
+@@ -613,7 +603,7 @@ int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
+ 		dev_kfree_skb(skb);
+ 		return -1;
+ 	}
+-	IRDA_DEBUG(2, "%s(), sending ...\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s(), sending ...\n", __func__ );
+ 
+ 	return irttp_data_request(self->client.tsap_ctrl, skb);
+ }
+@@ -626,7 +616,7 @@ int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
+  */
+ static void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	/* Queue command */
+ 	skb_queue_tail(&self->client.txq, skb);
+@@ -646,7 +636,7 @@ void irlan_get_provider_info(struct irlan_cb *self)
+ 	struct sk_buff *skb;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -679,7 +669,7 @@ void irlan_open_data_channel(struct irlan_cb *self)
+ 	struct sk_buff *skb;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -714,7 +704,7 @@ void irlan_close_data_channel(struct irlan_cb *self)
+ 	struct sk_buff *skb;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -755,7 +745,7 @@ static void irlan_open_unicast_addr(struct irlan_cb *self)
+ 	struct sk_buff *skb;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -797,7 +787,7 @@ void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
+ 	struct sk_buff *skb;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -841,7 +831,7 @@ void irlan_set_multicast_filter(struct irlan_cb *self, int status)
+ 	struct sk_buff *skb;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -886,7 +876,7 @@ static void irlan_get_unicast_addr(struct irlan_cb *self)
+ 	struct sk_buff *skb;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -926,7 +916,7 @@ void irlan_get_media_char(struct irlan_cb *self)
+ 	struct sk_buff *skb;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -1014,7 +1004,7 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
+ 	int n=0;
+ 
+ 	if (skb == NULL) {
+-		IRDA_DEBUG(2, "%s(), Got NULL skb\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), Got NULL skb\n", __func__ );
+ 		return 0;
+ 	}
+ 
+@@ -1031,7 +1021,7 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
+ 		IRDA_ASSERT(value_len > 0, return 0;);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __func__ );
+ 		return 0;
+ 		break;
+ 	}
+@@ -1041,7 +1031,7 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
+ 
+ 	/* Make space for data */
+ 	if (skb_tailroom(skb) < (param_len+value_len+3)) {
+-		IRDA_DEBUG(2, "%s(), No more space at end of skb\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), No more space at end of skb\n", __func__ );
+ 		return 0;
+ 	}
+ 	skb_put(skb, param_len+value_len+3);
+@@ -1088,13 +1078,13 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
+ 	__u16 val_len;
+ 	int n=0;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	/* get length of parameter name (1 byte) */
+ 	name_len = buf[n++];
+ 
+ 	if (name_len > 254) {
+-		IRDA_DEBUG(2, "%s(), name_len > 254\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), name_len > 254\n", __func__ );
+ 		return -RSP_INVALID_COMMAND_FORMAT;
+ 	}
+ 
+@@ -1111,7 +1101,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
+ 	le16_to_cpus(&val_len); n+=2;
+ 
+ 	if (val_len > 1016) {
+-		IRDA_DEBUG(2, "%s(), parameter length to long\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ );
+ 		return -RSP_INVALID_COMMAND_FORMAT;
+ 	}
+ 	*len = val_len;
+diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
+index 1ab91f7..05112be 100644
+--- a/net/irda/irlan/irlan_eth.c
++++ b/net/irda/irlan/irlan_eth.c
+@@ -103,7 +103,7 @@ static int irlan_eth_open(struct net_device *dev)
+ {
+ 	struct irlan_cb *self = netdev_priv(dev);
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	/* Ready to play! */
+ 	netif_stop_queue(dev); /* Wait until data link is ready */
+@@ -130,7 +130,7 @@ static int irlan_eth_close(struct net_device *dev)
+ {
+ 	struct irlan_cb *self = netdev_priv(dev);
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	/* Stop device */
+ 	netif_stop_queue(dev);
+@@ -221,7 +221,7 @@ int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
+ 	}
+ 	if (skb->len < ETH_HLEN) {
+ 		IRDA_DEBUG(0, "%s() : IrLAN frame too short (%d)\n",
+-			   __FUNCTION__, skb->len);
++			   __func__, skb->len);
+ 		++self->stats.rx_dropped;
+ 		dev_kfree_skb(skb);
+ 		return 0;
+@@ -270,7 +270,7 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ 
+ 	IRDA_ASSERT(dev != NULL, return;);
+ 
+-	IRDA_DEBUG(0, "%s() : flow %s ; running %d\n", __FUNCTION__,
++	IRDA_DEBUG(0, "%s() : flow %s ; running %d\n", __func__,
+ 		   flow == FLOW_STOP ? "FLOW_STOP" : "FLOW_START",
+ 		   netif_running(dev));
+ 
+@@ -289,39 +289,6 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ }
+ 
+ /*
+- * Function irlan_etc_send_gratuitous_arp (dev)
+- *
+- *    Send gratuitous ARP to announce that we have changed
+- *    hardware address, so that all peers updates their ARP tables
+- */
+-void irlan_eth_send_gratuitous_arp(struct net_device *dev)
+-{
+-#ifdef CONFIG_INET
+-	struct in_device *in_dev;
+-
+-	/*
+-	 * When we get a new MAC address do a gratuitous ARP. This
+-	 * is useful if we have changed access points on the same
+-	 * subnet.
+-	 */
+-	IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
+-	rcu_read_lock();
+-	in_dev = __in_dev_get_rcu(dev);
+-	if (in_dev == NULL)
+-		goto out;
+-	if (in_dev->ifa_list)
+-
+-	arp_send(ARPOP_REQUEST, ETH_P_ARP,
+-		 in_dev->ifa_list->ifa_address,
+-		 dev,
+-		 in_dev->ifa_list->ifa_address,
+-		 NULL, dev->dev_addr, NULL);
+-out:
+-	rcu_read_unlock();
+-#endif /* CONFIG_INET */
+-}
+-
+-/*
+  * Function set_multicast_list (dev)
+  *
+  *    Configure the filtering of the device
+@@ -332,11 +299,11 @@ static void irlan_eth_set_multicast_list(struct net_device *dev)
+ {
+ 	struct irlan_cb *self = netdev_priv(dev);
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(2, "%s()\n", __func__ );
+ 
+ 	/* Check if data channel has been connected yet */
+ 	if (self->client.state != IRLAN_DATA) {
+-		IRDA_DEBUG(1, "%s(), delaying!\n", __FUNCTION__ );
++		IRDA_DEBUG(1, "%s(), delaying!\n", __func__ );
+ 		return;
+ 	}
+ 
+@@ -346,20 +313,20 @@ static void irlan_eth_set_multicast_list(struct net_device *dev)
+ 	}
+ 	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
+ 		/* Disable promiscuous mode, use normal mode. */
+-		IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __FUNCTION__ );
++		IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ );
+ 		/* hardware_set_filter(NULL); */
+ 
+ 		irlan_set_multicast_filter(self, TRUE);
+ 	}
+ 	else if (dev->mc_count) {
+-		IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __FUNCTION__ );
++		IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ );
+ 		/* Walk the address list, and load the filter */
+ 		/* hardware_set_filter(dev->mc_list); */
+ 
+ 		irlan_set_multicast_filter(self, TRUE);
+ 	}
+ 	else {
+-		IRDA_DEBUG(4, "%s(), Clearing multicast filter\n", __FUNCTION__ );
++		IRDA_DEBUG(4, "%s(), Clearing multicast filter\n", __func__ );
+ 		irlan_set_multicast_filter(self, FALSE);
+ 	}
+ 
+diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c
+index a9750a8..cbcb4eb 100644
+--- a/net/irda/irlan/irlan_event.c
++++ b/net/irda/irlan/irlan_event.c
+@@ -40,7 +40,7 @@ char *irlan_state[] = {
+ 
+ void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state)
+ {
+-	IRDA_DEBUG(2, "%s(), %s\n", __FUNCTION__ , irlan_state[state]);
++	IRDA_DEBUG(2, "%s(), %s\n", __func__ , irlan_state[state]);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -50,7 +50,7 @@ void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state)
+ 
+ void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state)
+ {
+-	IRDA_DEBUG(2, "%s(), %s\n", __FUNCTION__ , irlan_state[state]);
++	IRDA_DEBUG(2, "%s(), %s\n", __func__ , irlan_state[state]);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c
+index 4384be9..9ff7823 100644
+--- a/net/irda/irlan/irlan_filter.c
++++ b/net/irda/irlan/irlan_filter.c
+@@ -145,7 +145,7 @@ void irlan_check_command_param(struct irlan_cb *self, char *param, char *value)
+ {
+ 	__u8 *bytes;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	bytes = value;
+ 
+@@ -158,7 +158,7 @@ void irlan_check_command_param(struct irlan_cb *self, char *param, char *value)
+ 	 *  This is experimental!! DB.
+ 	 */
+ 	 if (strcmp(param, "MODE") == 0) {
+-		IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++		IRDA_DEBUG(0, "%s()\n", __func__ );
+ 		self->use_udata = TRUE;
+ 		return;
+ 	}
+diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
+index 13db942..3f81f81 100644
+--- a/net/irda/irlan/irlan_provider.c
++++ b/net/irda/irlan/irlan_provider.c
+@@ -70,7 +70,7 @@ static int irlan_provider_data_indication(void *instance, void *sap,
+ 	struct irlan_cb *self;
+ 	__u8 code;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	self = (struct irlan_cb *) instance;
+ 
+@@ -99,15 +99,15 @@ static int irlan_provider_data_indication(void *instance, void *sap,
+ 		irlan_do_provider_event(self, IRLAN_FILTER_CONFIG_CMD, skb);
+ 		break;
+ 	case CMD_RECONNECT_DATA_CHAN:
+-		IRDA_DEBUG(2, "%s(), Got RECONNECT_DATA_CHAN command\n", __FUNCTION__ );
+-		IRDA_DEBUG(2, "%s(), NOT IMPLEMENTED\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), Got RECONNECT_DATA_CHAN command\n", __func__ );
++		IRDA_DEBUG(2, "%s(), NOT IMPLEMENTED\n", __func__ );
+ 		break;
+ 	case CMD_CLOSE_DATA_CHAN:
+ 		IRDA_DEBUG(2, "Got CLOSE_DATA_CHAN command!\n");
+-		IRDA_DEBUG(2, "%s(), NOT IMPLEMENTED\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), NOT IMPLEMENTED\n", __func__ );
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown command!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), Unknown command!\n", __func__ );
+ 		break;
+ 	}
+ 	return 0;
+@@ -129,7 +129,7 @@ static void irlan_provider_connect_indication(void *instance, void *sap,
+ 	struct tsap_cb *tsap;
+ 	__u32 saddr, daddr;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(0, "%s()\n", __func__ );
+ 
+ 	self = (struct irlan_cb *) instance;
+ 	tsap = (struct tsap_cb *) sap;
+@@ -182,7 +182,7 @@ static void irlan_provider_disconnect_indication(void *instance, void *sap,
+ 	struct irlan_cb *self;
+ 	struct tsap_cb *tsap;
+ 
+-	IRDA_DEBUG(4, "%s(), reason=%d\n", __FUNCTION__ , reason);
++	IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
+ 
+ 	self = (struct irlan_cb *) instance;
+ 	tsap = (struct tsap_cb *) sap;
+@@ -236,7 +236,7 @@ int irlan_provider_parse_command(struct irlan_cb *self, int cmd,
+ 
+ 	IRDA_ASSERT(skb != NULL, return -RSP_PROTOCOL_ERROR;);
+ 
+-	IRDA_DEBUG(4, "%s(), skb->len=%d\n", __FUNCTION__ , (int)skb->len);
++	IRDA_DEBUG(4, "%s(), skb->len=%d\n", __func__ , (int)skb->len);
+ 
+ 	IRDA_ASSERT(self != NULL, return -RSP_PROTOCOL_ERROR;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
+@@ -266,7 +266,7 @@ int irlan_provider_parse_command(struct irlan_cb *self, int cmd,
+ 	for (i=0; i<count;i++) {
+ 		ret = irlan_extract_param(ptr, name, value, &val_len);
+ 		if (ret < 0) {
+-			IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __FUNCTION__ );
++			IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __func__ );
+ 			break;
+ 		}
+ 		ptr+=ret;
+@@ -291,7 +291,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
+ {
+ 	struct sk_buff *skb;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -323,7 +323,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
+ 			irlan_insert_string_param(skb, "MEDIA", "802.5");
+ 			break;
+ 		default:
+-			IRDA_DEBUG(2, "%s(), unknown media type!\n", __FUNCTION__ );
++			IRDA_DEBUG(2, "%s(), unknown media type!\n", __func__ );
+ 			break;
+ 		}
+ 		irlan_insert_short_param(skb, "IRLAN_VER", 0x0101);
+@@ -347,7 +347,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
+ 			irlan_insert_string_param(skb, "ACCESS_TYPE", "HOSTED");
+ 			break;
+ 		default:
+-			IRDA_DEBUG(2, "%s(), Unknown access type\n", __FUNCTION__ );
++			IRDA_DEBUG(2, "%s(), Unknown access type\n", __func__ );
+ 			break;
+ 		}
+ 		irlan_insert_short_param(skb, "MAX_FRAME", 0x05ee);
+@@ -367,7 +367,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
+ 		irlan_filter_request(self, skb);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown command!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), Unknown command!\n", __func__ );
+ 		break;
+ 	}
+ 
+@@ -385,7 +385,7 @@ int irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
+ 	struct tsap_cb *tsap;
+ 	notify_t notify;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -406,7 +406,7 @@ int irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
+ 
+ 	tsap = irttp_open_tsap(LSAP_ANY, 1, &notify);
+ 	if (!tsap) {
+-		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );
++		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
+ 		return -1;
+ 	}
+ 	self->provider.tsap_ctrl = tsap;
+diff --git a/net/irda/irlan/irlan_provider_event.c b/net/irda/irlan/irlan_provider_event.c
+index 10ece5a..01a9d7c 100644
+--- a/net/irda/irlan/irlan_provider_event.c
++++ b/net/irda/irlan/irlan_provider_event.c
+@@ -72,7 +72,7 @@ void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ 				     struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 
+@@ -82,7 +82,7 @@ static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ 	     irlan_next_provider_state( self, IRLAN_INFO);
+ 	     break;
+ 	default:
+-		IRDA_DEBUG(4, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(4, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -101,7 +101,7 @@ static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ {
+ 	int ret;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 
+@@ -147,7 +147,7 @@ static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_provider_state(self, IRLAN_IDLE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG( 0, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG( 0, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -166,7 +166,7 @@ static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ 				     struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 
+@@ -186,7 +186,7 @@ static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_provider_state(self, IRLAN_IDLE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+@@ -205,7 +205,7 @@ static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ 				     struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++	IRDA_DEBUG(4, "%s()\n", __func__ );
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -221,7 +221,7 @@ static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ 		irlan_next_provider_state(self, IRLAN_IDLE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG( 0, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++		IRDA_DEBUG( 0, "%s(), Unknown event %d\n", __func__ , event);
+ 		break;
+ 	}
+ 	if (skb)
+diff --git a/net/irda/irlap.c b/net/irda/irlap.c
+index f3236ac..e4965b7 100644
+--- a/net/irda/irlap.c
++++ b/net/irda/irlap.c
+@@ -88,7 +88,7 @@ int __init irlap_init(void)
+ 	irlap = hashbin_new(HB_LOCK);
+ 	if (irlap == NULL) {
+ 		IRDA_ERROR("%s: can't allocate irlap hashbin!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -113,7 +113,7 @@ struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos,
+ {
+ 	struct irlap_cb *self;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	/* Initialize the irlap structure. */
+ 	self = kzalloc(sizeof(struct irlap_cb), GFP_KERNEL);
+@@ -215,7 +215,7 @@ void irlap_close(struct irlap_cb *self)
+ {
+ 	struct irlap_cb *lap;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -231,7 +231,7 @@ void irlap_close(struct irlap_cb *self)
+ 	/* Be sure that we manage to remove ourself from the hash */
+ 	lap = hashbin_remove(irlap, self->saddr, NULL);
+ 	if (!lap) {
+-		IRDA_DEBUG(1, "%s(), Didn't find myself!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Didn't find myself!\n", __func__);
+ 		return;
+ 	}
+ 	__irlap_close(lap);
+@@ -246,7 +246,7 @@ EXPORT_SYMBOL(irlap_close);
+  */
+ void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -265,7 +265,7 @@ void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb)
+  */
+ void irlap_connect_response(struct irlap_cb *self, struct sk_buff *userdata)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	irlap_do_event(self, CONNECT_RESPONSE, userdata, NULL);
+ }
+@@ -280,7 +280,7 @@ void irlap_connect_response(struct irlap_cb *self, struct sk_buff *userdata)
+ void irlap_connect_request(struct irlap_cb *self, __u32 daddr,
+ 			   struct qos_info *qos_user, int sniff)
+ {
+-	IRDA_DEBUG(3, "%s(), daddr=0x%08x\n", __FUNCTION__, daddr);
++	IRDA_DEBUG(3, "%s(), daddr=0x%08x\n", __func__, daddr);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -307,7 +307,7 @@ void irlap_connect_request(struct irlap_cb *self, __u32 daddr,
+  */
+ void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -344,7 +344,7 @@ void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
+ 		    return;);
+@@ -391,7 +391,7 @@ void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
+ 	       return;);
+@@ -417,7 +417,7 @@ void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
+ #ifdef CONFIG_IRDA_ULTRA
+ void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -437,7 +437,7 @@ void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
+  */
+ void irlap_disconnect_request(struct irlap_cb *self)
+ {
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -458,7 +458,7 @@ void irlap_disconnect_request(struct irlap_cb *self)
+ 		irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), disconnect pending!\n", __FUNCTION__);
++		IRDA_DEBUG(2, "%s(), disconnect pending!\n", __func__);
+ 		self->disconnect_pending = TRUE;
+ 		break;
+ 	}
+@@ -472,7 +472,7 @@ void irlap_disconnect_request(struct irlap_cb *self)
+  */
+ void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
+ {
+-	IRDA_DEBUG(1, "%s(), reason=%s\n", __FUNCTION__, lap_reasons[reason]);
++	IRDA_DEBUG(1, "%s(), reason=%s\n", __func__, lap_reasons[reason]);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -482,7 +482,7 @@ void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
+ 
+ 	switch (reason) {
+ 	case LAP_RESET_INDICATION:
+-		IRDA_DEBUG(1, "%s(), Sending reset request!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Sending reset request!\n", __func__);
+ 		irlap_do_event(self, RESET_REQUEST, NULL, NULL);
+ 		break;
+ 	case LAP_NO_RESPONSE:	   /* FALLTROUGH */
+@@ -493,7 +493,7 @@ void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
+ 						 reason, NULL);
+ 		break;
+ 	default:
+-		IRDA_ERROR("%s: Unknown reason %d\n", __FUNCTION__, reason);
++		IRDA_ERROR("%s: Unknown reason %d\n", __func__, reason);
+ 	}
+ }
+ 
+@@ -511,7 +511,7 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ 	IRDA_ASSERT(discovery != NULL, return;);
+ 
+-	IRDA_DEBUG(4, "%s(), nslots = %d\n", __FUNCTION__, discovery->nslots);
++	IRDA_DEBUG(4, "%s(), nslots = %d\n", __func__, discovery->nslots);
+ 
+ 	IRDA_ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
+ 		    (discovery->nslots == 8) || (discovery->nslots == 16),
+@@ -520,7 +520,7 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
+ 	/* Discovery is only possible in NDM mode */
+ 	if (self->state != LAP_NDM) {
+ 		IRDA_DEBUG(4, "%s(), discovery only possible in NDM mode\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		irlap_discovery_confirm(self, NULL);
+ 		/* Note : in theory, if we are not in NDM, we could postpone
+ 		 * the discovery like we do for connection request.
+@@ -543,7 +543,7 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
+ 
+ 	if (self->discovery_log == NULL) {
+ 		IRDA_WARNING("%s(), Unable to allocate discovery log!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		return;
+ 	}
+ 
+@@ -598,7 +598,7 @@ void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log)
+  */
+ void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -644,7 +644,7 @@ void irlap_status_indication(struct irlap_cb *self, int quality_of_link)
+  */
+ void irlap_reset_indication(struct irlap_cb *self)
+ {
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -660,7 +660,7 @@ void irlap_reset_indication(struct irlap_cb *self)
+  */
+ void irlap_reset_confirm(void)
+ {
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ }
+ 
+ /*
+@@ -760,7 +760,7 @@ int irlap_validate_nr_received(struct irlap_cb *self, int nr)
+ {
+ 	/*  nr as expected?  */
+ 	if (nr == self->vs) {
+-		IRDA_DEBUG(4, "%s(), expected!\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), expected!\n", __func__);
+ 		return NR_EXPECTED;
+ 	}
+ 
+@@ -788,7 +788,7 @@ int irlap_validate_nr_received(struct irlap_cb *self, int nr)
+  */
+ void irlap_initiate_connection_state(struct irlap_cb *self)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -871,7 +871,7 @@ static void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
+ {
+ 	struct sk_buff *skb;
+ 
+-	IRDA_DEBUG(0, "%s(), setting speed to %d\n", __FUNCTION__, speed);
++	IRDA_DEBUG(0, "%s(), setting speed to %d\n", __func__, speed);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -914,7 +914,7 @@ static void irlap_init_qos_capabilities(struct irlap_cb *self,
+ 	 *  user may not have set all of them.
+ 	 */
+ 	if (qos_user) {
+-		IRDA_DEBUG(1, "%s(), Found user specified QoS!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Found user specified QoS!\n", __func__);
+ 
+ 		if (qos_user->baud_rate.bits)
+ 			self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
+@@ -944,7 +944,7 @@ static void irlap_init_qos_capabilities(struct irlap_cb *self,
+  */
+ void irlap_apply_default_connection_parameters(struct irlap_cb *self)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -1007,7 +1007,7 @@ void irlap_apply_default_connection_parameters(struct irlap_cb *self)
+  */
+ void irlap_apply_connection_parameters(struct irlap_cb *self, int now)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
+index 6af86eb..16c4ef0 100644
+--- a/net/irda/irlap_event.c
++++ b/net/irda/irlap_event.c
+@@ -217,7 +217,7 @@ static void irlap_start_poll_timer(struct irlap_cb *self, int timeout)
+ 	} else
+ 		self->fast_RR = FALSE;
+ 
+-	IRDA_DEBUG(3, "%s(), timeout=%d (%ld)\n", __FUNCTION__, timeout, jiffies);
++	IRDA_DEBUG(3, "%s(), timeout=%d (%ld)\n", __func__, timeout, jiffies);
+ #endif /* CONFIG_IRDA_FAST_RR */
+ 
+ 	if (timeout == 0)
+@@ -241,7 +241,7 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
+ 	if (!self || self->magic != LAP_MAGIC)
+ 		return;
+ 
+-	IRDA_DEBUG(3, "%s(), event = %s, state = %s\n", __FUNCTION__,
++	IRDA_DEBUG(3, "%s(), event = %s, state = %s\n", __func__,
+ 		   irlap_event[event], irlap_state[self->state]);
+ 
+ 	ret = (*state[self->state])(self, event, skb, info);
+@@ -259,7 +259,7 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
+ 		 * try to disconnect link if we send any data frames, since
+ 		 * that will change the state away form XMIT
+ 		 */
+-		IRDA_DEBUG(2, "%s() : queue len = %d\n", __FUNCTION__,
++		IRDA_DEBUG(2, "%s() : queue len = %d\n", __func__,
+ 			   skb_queue_len(&self->txq));
+ 
+ 		if (!skb_queue_empty(&self->txq)) {
+@@ -340,7 +340,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ 			 * media busy in irlap_connect_request() and
+ 			 * postpone the event... - Jean II */
+ 			IRDA_DEBUG(0, "%s(), CONNECT_REQUEST: media busy!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 
+ 			/* Always switch state before calling upper layers */
+ 			irlap_next_state(self, LAP_NDM);
+@@ -367,7 +367,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ 			irlap_connect_indication(self, skb);
+ 		} else {
+ 			IRDA_DEBUG(0, "%s(), SNRM frame does not "
+-				   "contain an I field!\n", __FUNCTION__);
++				   "contain an I field!\n", __func__);
+ 		}
+ 		break;
+ 	case DISCOVERY_REQUEST:
+@@ -375,7 +375,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ 
+ 		if (self->media_busy) {
+ 			IRDA_DEBUG(1, "%s(), DISCOVERY_REQUEST: media busy!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			/* irlap->log.condition = MEDIA_BUSY; */
+ 
+ 			/* This will make IrLMP try again */
+@@ -441,7 +441,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ 		 * those cases...
+ 		 * Jean II
+ 		 */
+-			IRDA_DEBUG(1, "%s(), Receiving final discovery request, missed the discovery slots :-(\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), Receiving final discovery request, missed the discovery slots :-(\n", __func__);
+ 
+ 			/* Last discovery request -> in the log */
+ 			irlap_discovery_indication(self, info->discovery);
+@@ -520,7 +520,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ 		/* Only accept broadcast frames in NDM mode */
+ 		if (info->caddr != CBROADCAST) {
+ 			IRDA_DEBUG(0, "%s(), not a broadcast frame!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 		} else
+ 			irlap_unitdata_indication(self, skb);
+ 		break;
+@@ -536,10 +536,10 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ 		irlap_send_test_frame(self, CBROADCAST, info->daddr, skb);
+ 		break;
+ 	case RECV_TEST_RSP:
+-		IRDA_DEBUG(0, "%s() not implemented!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s() not implemented!\n", __func__);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,
++		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __func__,
+ 			   irlap_event[event]);
+ 
+ 		ret = -1;
+@@ -567,13 +567,13 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
+ 		IRDA_ASSERT(info != NULL, return -1;);
+ 		IRDA_ASSERT(info->discovery != NULL, return -1;);
+ 
+-		IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__,
++		IRDA_DEBUG(4, "%s(), daddr=%08x\n", __func__,
+ 			   info->discovery->data.daddr);
+ 
+ 		if (!self->discovery_log) {
+ 			IRDA_WARNING("%s: discovery log is gone! "
+ 				     "maybe the discovery timeout has been set"
+-				     " too short?\n", __FUNCTION__);
++				     " too short?\n", __func__);
+ 			break;
+ 		}
+ 		hashbin_insert(self->discovery_log,
+@@ -598,7 +598,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
+ 
+ 		IRDA_ASSERT(info != NULL, return -1;);
+ 
+-		IRDA_DEBUG(1, "%s(), Receiving discovery request (s = %d) while performing discovery :-(\n", __FUNCTION__, info->s);
++		IRDA_DEBUG(1, "%s(), Receiving discovery request (s = %d) while performing discovery :-(\n", __func__, info->s);
+ 
+ 		/* Last discovery request ? */
+ 		if (info->s == 0xff)
+@@ -613,7 +613,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
+ 		 */
+ 		if (irda_device_is_receiving(self->netdev) && !self->add_wait) {
+ 			IRDA_DEBUG(2, "%s(), device is slow to answer, "
+-				   "waiting some more!\n", __FUNCTION__);
++				   "waiting some more!\n", __func__);
+ 			irlap_start_slot_timer(self, msecs_to_jiffies(10));
+ 			self->add_wait = TRUE;
+ 			return ret;
+@@ -649,7 +649,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
+ 		}
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,
++		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __func__,
+ 			   irlap_event[event]);
+ 
+ 		ret = -1;
+@@ -671,7 +671,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
+ 	discovery_t *discovery_rsp;
+ 	int ret=0;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -679,7 +679,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
+ 	switch (event) {
+ 	case QUERY_TIMER_EXPIRED:
+ 		IRDA_DEBUG(0, "%s(), QUERY_TIMER_EXPIRED <%ld>\n",
+-			   __FUNCTION__, jiffies);
++			   __func__, jiffies);
+ 		irlap_next_state(self, LAP_NDM);
+ 		break;
+ 	case RECV_DISCOVERY_XID_CMD:
+@@ -717,7 +717,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
+ 		}
+ 		break;
+ 	default:
+-		IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__,
++		IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __func__,
+ 			   event, irlap_event[event]);
+ 
+ 		ret = -1;
+@@ -738,7 +738,7 @@ static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[ event]);
++	IRDA_DEBUG(4, "%s(), event=%s\n", __func__, irlap_event[ event]);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -799,18 +799,18 @@ static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event,
+ 		break;
+ 	case RECV_DISCOVERY_XID_CMD:
+ 		IRDA_DEBUG(3, "%s(), event RECV_DISCOVER_XID_CMD!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		irlap_next_state(self, LAP_NDM);
+ 
+ 		break;
+ 	case DISCONNECT_REQUEST:
+-		IRDA_DEBUG(0, "%s(), Disconnect request!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), Disconnect request!\n", __func__);
+ 		irlap_send_dm_frame(self);
+ 		irlap_next_state( self, LAP_NDM);
+ 		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__,
++		IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __func__,
+ 			   event, irlap_event[event]);
+ 
+ 		ret = -1;
+@@ -832,7 +832,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -861,7 +861,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
+ 		self->retry_count++;
+ 		break;
+ 	case RECV_SNRM_CMD:
+-		IRDA_DEBUG(4, "%s(), SNRM battle!\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), SNRM battle!\n", __func__);
+ 
+ 		IRDA_ASSERT(skb != NULL, return 0;);
+ 		IRDA_ASSERT(info != NULL, return 0;);
+@@ -948,7 +948,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
+ 		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__,
++		IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __func__,
+ 			   event, irlap_event[event]);
+ 
+ 		ret = -1;
+@@ -966,7 +966,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
+ static int irlap_state_offline(struct irlap_cb *self, IRLAP_EVENT event,
+ 			       struct sk_buff *skb, struct irlap_info *info)
+ {
+-	IRDA_DEBUG( 0, "%s(), Unknown event\n", __FUNCTION__);
++	IRDA_DEBUG( 0, "%s(), Unknown event\n", __func__);
+ 
+ 	return -1;
+ }
+@@ -1030,7 +1030,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 			 */
+ 			if((!nextfit) && (skb->len > self->bytes_left)) {
+ 				IRDA_DEBUG(0, "%s(), Not allowed to transmit"
+-					   " more bytes!\n", __FUNCTION__);
++					   " more bytes!\n", __func__);
+ 				/* Requeue the skb */
+ 				skb_queue_head(&self->txq, skb_get(skb));
+ 				/*
+@@ -1082,7 +1082,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
+ #endif /* CONFIG_IRDA_FAST_RR */
+ 		} else {
+ 			IRDA_DEBUG(4, "%s(), Unable to send! remote busy?\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			skb_queue_head(&self->txq, skb_get(skb));
+ 
+ 			/*
+@@ -1094,7 +1094,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 		break;
+ 	case POLL_TIMER_EXPIRED:
+ 		IRDA_DEBUG(3, "%s(), POLL_TIMER_EXPIRED <%ld>\n",
+-			    __FUNCTION__, jiffies);
++			    __func__, jiffies);
+ 		irlap_send_rr_frame(self, CMD_FRAME);
+ 		/* Return to NRM properly - Jean II  */
+ 		self->window = self->window_size;
+@@ -1120,7 +1120,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(0, "%s(), Unknown event %s\n",
+-			   __FUNCTION__, irlap_event[event]);
++			   __func__, irlap_event[event]);
+ 
+ 		ret = -EINVAL;
+ 		break;
+@@ -1138,7 +1138,7 @@ static int irlap_state_pclose(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -1173,7 +1173,7 @@ static int irlap_state_pclose(struct irlap_cb *self, IRLAP_EVENT event,
+ 		}
+ 		break;
+ 	default:
+-		IRDA_DEBUG(1, "%s(), Unknown event %d\n", __FUNCTION__, event);
++		IRDA_DEBUG(1, "%s(), Unknown event %d\n", __func__, event);
+ 
+ 		ret = -1;
+ 		break;
+@@ -1297,7 +1297,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 			} else {
+ 				IRDA_DEBUG(4,
+ 				       "%s(), missing or duplicate frame!\n",
+-					   __FUNCTION__);
++					   __func__);
+ 
+ 				/* Update Nr received */
+ 				irlap_update_nr_received(self, info->nr);
+@@ -1367,7 +1367,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 		    (nr_status == NR_UNEXPECTED))
+ 		{
+ 			IRDA_DEBUG(4, "%s(), unexpected nr and ns!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			if (info->pf) {
+ 				/* Resend rejected frames */
+ 				irlap_resend_rejected_frames(self, CMD_FRAME);
+@@ -1407,9 +1407,9 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 			}
+ 			break;
+ 		}
+-		IRDA_DEBUG(1, "%s(), Not implemented!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Not implemented!\n", __func__);
+ 		IRDA_DEBUG(1, "%s(), event=%s, ns_status=%d, nr_status=%d\n",
+-		       __FUNCTION__, irlap_event[event], ns_status, nr_status);
++		       __func__, irlap_event[event], ns_status, nr_status);
+ 		break;
+ 	case RECV_UI_FRAME:
+ 		/* Poll bit cleared? */
+@@ -1420,7 +1420,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 			del_timer(&self->final_timer);
+ 			irlap_data_indication(self, skb, TRUE);
+ 			irlap_next_state(self, LAP_XMIT_P);
+-			IRDA_DEBUG(1, "%s: RECV_UI_FRAME: next state %s\n", __FUNCTION__, irlap_state[self->state]);
++			IRDA_DEBUG(1, "%s: RECV_UI_FRAME: next state %s\n", __func__, irlap_state[self->state]);
+ 			irlap_start_poll_timer(self, self->poll_timeout);
+ 		}
+ 		break;
+@@ -1475,7 +1475,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 			irlap_next_state(self, LAP_NRM_P);
+ 		} else if (ret == NR_INVALID) {
+ 			IRDA_DEBUG(1, "%s(), Received RR with "
+-				   "invalid nr !\n", __FUNCTION__);
++				   "invalid nr !\n", __func__);
+ 
+ 			irlap_next_state(self, LAP_RESET_WAIT);
+ 
+@@ -1580,7 +1580,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 		irlap_start_final_timer(self, 2 * self->final_timeout);
+ 		break;
+ 	case RECV_RD_RSP:
+-		IRDA_DEBUG(1, "%s(), RECV_RD_RSP\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), RECV_RD_RSP\n", __func__);
+ 
+ 		irlap_flush_all_queues(self);
+ 		irlap_next_state(self, LAP_XMIT_P);
+@@ -1589,7 +1589,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(1, "%s(), Unknown event %s\n",
+-			    __FUNCTION__, irlap_event[event]);
++			    __func__, irlap_event[event]);
+ 
+ 		ret = -1;
+ 		break;
+@@ -1609,7 +1609,7 @@ static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(3, "%s(), event = %s\n", __FUNCTION__, irlap_event[event]);
++	IRDA_DEBUG(3, "%s(), event = %s\n", __func__, irlap_event[event]);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -1635,7 +1635,7 @@ static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event,
+ 		irlap_next_state( self, LAP_PCLOSE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,
++		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __func__,
+ 			   irlap_event[event]);
+ 
+ 		ret = -1;
+@@ -1656,7 +1656,7 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(3, "%s(), event = %s\n", __FUNCTION__, irlap_event[event]);
++	IRDA_DEBUG(3, "%s(), event = %s\n", __func__, irlap_event[event]);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -1714,7 +1714,7 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event,
+ 		 * state
+ 		 */
+ 		if (!info) {
+-			IRDA_DEBUG(3, "%s(), RECV_SNRM_CMD\n", __FUNCTION__);
++			IRDA_DEBUG(3, "%s(), RECV_SNRM_CMD\n", __func__);
+ 			irlap_initiate_connection_state(self);
+ 			irlap_wait_min_turn_around(self, &self->qos_tx);
+ 			irlap_send_ua_response_frame(self, &self->qos_rx);
+@@ -1724,12 +1724,12 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event,
+ 		} else {
+ 			IRDA_DEBUG(0,
+ 				   "%s(), SNRM frame contained an I field!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 		}
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(1, "%s(), Unknown event %s\n",
+-			   __FUNCTION__, irlap_event[event]);
++			   __func__, irlap_event[event]);
+ 
+ 		ret = -1;
+ 		break;
+@@ -1749,7 +1749,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[event]);
++	IRDA_DEBUG(4, "%s(), event=%s\n", __func__, irlap_event[event]);
+ 
+ 	IRDA_ASSERT(self != NULL, return -ENODEV;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+@@ -1786,7 +1786,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
+ 			 */
+ 			if((!nextfit) && (skb->len > self->bytes_left)) {
+ 				IRDA_DEBUG(0, "%s(), Not allowed to transmit"
+-					   " more bytes!\n", __FUNCTION__);
++					   " more bytes!\n", __func__);
+ 				/* Requeue the skb */
+ 				skb_queue_head(&self->txq, skb_get(skb));
+ 
+@@ -1832,7 +1832,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
+ 				ret = -EPROTO;
+ 			}
+ 		} else {
+-			IRDA_DEBUG(2, "%s(), Unable to send!\n", __FUNCTION__);
++			IRDA_DEBUG(2, "%s(), Unable to send!\n", __func__);
+ 			skb_queue_head(&self->txq, skb_get(skb));
+ 			ret = -EPROTO;
+ 		}
+@@ -1848,7 +1848,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
+ 		 * when we return... - Jean II */
+ 		break;
+ 	default:
+-		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,
++		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __func__,
+ 			   irlap_event[event]);
+ 
+ 		ret = -EINVAL;
+@@ -1871,7 +1871,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ 	int nr_status;
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[ event]);
++	IRDA_DEBUG(4, "%s(), event=%s\n", __func__, irlap_event[ event]);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -1880,7 +1880,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ 	case RECV_I_CMD: /* Optimize for the common case */
+ 		/* FIXME: must check for remote_busy below */
+ 		IRDA_DEBUG(4, "%s(), event=%s nr=%d, vs=%d, ns=%d, "
+-			   "vr=%d, pf=%d\n", __FUNCTION__,
++			   "vr=%d, pf=%d\n", __func__,
+ 			   irlap_event[event], info->nr,
+ 			   self->vs, info->ns, self->vr, info->pf);
+ 
+@@ -2112,21 +2112,21 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ 			irlap_next_state(self, LAP_NRM_S);
+ 		} else {
+ 			IRDA_DEBUG(1, "%s(), invalid nr not implemented!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 		}
+ 		break;
+ 	case RECV_SNRM_CMD:
+ 		/* SNRM frame is not allowed to contain an I-field */
+ 		if (!info) {
+ 			del_timer(&self->wd_timer);
+-			IRDA_DEBUG(1, "%s(), received SNRM cmd\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), received SNRM cmd\n", __func__);
+ 			irlap_next_state(self, LAP_RESET_CHECK);
+ 
+ 			irlap_reset_indication(self);
+ 		} else {
+ 			IRDA_DEBUG(0,
+ 				   "%s(), SNRM frame contained an I-field!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 
+ 		}
+ 		break;
+@@ -2158,7 +2158,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ 		 *   which explain why we use (self->N2 / 2) here !!!
+ 		 * Jean II
+ 		 */
+-		IRDA_DEBUG(1, "%s(), retry_count = %d\n", __FUNCTION__,
++		IRDA_DEBUG(1, "%s(), retry_count = %d\n", __func__,
+ 			   self->retry_count);
+ 
+ 		if (self->retry_count < (self->N2 / 2)) {
+@@ -2211,7 +2211,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ 		irlap_send_test_frame(self, self->caddr, info->daddr, skb);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __FUNCTION__,
++		IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __func__,
+ 			   event, irlap_event[event]);
+ 
+ 		ret = -EINVAL;
+@@ -2228,7 +2228,7 @@ static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -ENODEV;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+@@ -2285,7 +2285,7 @@ static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event,
+ 			break;		/* stay in SCLOSE */
+ 		}
+ 
+-		IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __FUNCTION__,
++		IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __func__,
+ 			   event, irlap_event[event]);
+ 
+ 		ret = -EINVAL;
+@@ -2301,7 +2301,7 @@ static int irlap_state_reset_check( struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(1, "%s(), event=%s\n", __FUNCTION__, irlap_event[event]);
++	IRDA_DEBUG(1, "%s(), event=%s\n", __func__, irlap_event[event]);
+ 
+ 	IRDA_ASSERT(self != NULL, return -ENODEV;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+@@ -2322,7 +2322,7 @@ static int irlap_state_reset_check( struct irlap_cb *self, IRLAP_EVENT event,
+ 		irlap_next_state(self, LAP_SCLOSE);
+ 		break;
+ 	default:
+-		IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __FUNCTION__,
++		IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __func__,
+ 			   event, irlap_event[event]);
+ 
+ 		ret = -EINVAL;
+diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
+index 7c132d6..9089453 100644
+--- a/net/irda/irlap_frame.c
++++ b/net/irda/irlap_frame.c
+@@ -102,7 +102,7 @@ void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb)
+ 	irlap_insert_info(self, skb);
+ 
+ 	if (unlikely(self->mode & IRDA_MODE_MONITOR)) {
+-		IRDA_DEBUG(3, "%s(): %s is in monitor mode\n", __FUNCTION__,
++		IRDA_DEBUG(3, "%s(): %s is in monitor mode\n", __func__,
+ 			   self->netdev->name);
+ 		dev_kfree_skb(skb);
+ 		return;
+@@ -182,7 +182,7 @@ static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
+ 		/* Check if the new connection address is valid */
+ 		if ((info->caddr == 0x00) || (info->caddr == 0xfe)) {
+ 			IRDA_DEBUG(3, "%s(), invalid connection address!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			return;
+ 		}
+ 
+@@ -193,7 +193,7 @@ static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
+ 		/* Only accept if addressed directly to us */
+ 		if (info->saddr != self->saddr) {
+ 			IRDA_DEBUG(2, "%s(), not addressed to us!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			return;
+ 		}
+ 		irlap_do_event(self, RECV_SNRM_CMD, skb, info);
+@@ -215,7 +215,7 @@ void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
+ 	struct ua_frame *frame;
+ 	int ret;
+ 
+-	IRDA_DEBUG(2, "%s() <%ld>\n", __FUNCTION__, jiffies);
++	IRDA_DEBUG(2, "%s() <%ld>\n", __func__, jiffies);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -290,7 +290,7 @@ void irlap_send_disc_frame(struct irlap_cb *self)
+ 	struct sk_buff *tx_skb = NULL;
+ 	struct disc_frame *frame;
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -321,7 +321,7 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
+ 	__u32 bcast = BROADCAST;
+ 	__u8 *info;
+ 
+-	IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__,
++	IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __func__,
+ 		   s, S, command);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+@@ -414,13 +414,13 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
+ 	__u8 *discovery_info;
+ 	char *text;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ 
+ 	if (!pskb_may_pull(skb, sizeof(struct xid_frame))) {
+-		IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++		IRDA_ERROR("%s: frame too short!\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -432,12 +432,12 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
+ 	/* Make sure frame is addressed to us */
+ 	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+ 		IRDA_DEBUG(0, "%s(), frame is not addressed to us!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		return;
+ 	}
+ 
+ 	if ((discovery = kzalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
+-		IRDA_WARNING("%s: kmalloc failed!\n", __FUNCTION__);
++		IRDA_WARNING("%s: kmalloc failed!\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -445,7 +445,7 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
+ 	discovery->data.saddr = self->saddr;
+ 	discovery->timestamp = jiffies;
+ 
+-	IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__,
++	IRDA_DEBUG(4, "%s(), daddr=%08x\n", __func__,
+ 		   discovery->data.daddr);
+ 
+ 	discovery_info = skb_pull(skb, sizeof(struct xid_frame));
+@@ -491,7 +491,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ 	char *text;
+ 
+ 	if (!pskb_may_pull(skb, sizeof(struct xid_frame))) {
+-		IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++		IRDA_ERROR("%s: frame too short!\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -503,7 +503,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ 	/* Make sure frame is addressed to us */
+ 	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+ 		IRDA_DEBUG(0, "%s(), frame is not addressed to us!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		return;
+ 	}
+ 
+@@ -536,7 +536,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ 		if((discovery_info == NULL) ||
+ 		   !pskb_may_pull(skb, 3)) {
+ 			IRDA_ERROR("%s: discovery frame too short!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			return;
+ 		}
+ 
+@@ -545,7 +545,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ 		 */
+ 		discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
+ 		if (!discovery) {
+-			IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);
++			IRDA_WARNING("%s: unable to malloc!\n", __func__);
+ 			return;
+ 		}
+ 
+@@ -657,7 +657,7 @@ static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
+ {
+ 	info->nr = skb->data[1] >> 5;
+ 
+-	IRDA_DEBUG(4, "%s(), nr=%d, %ld\n", __FUNCTION__, info->nr, jiffies);
++	IRDA_DEBUG(4, "%s(), nr=%d, %ld\n", __func__, info->nr, jiffies);
+ 
+ 	if (command)
+ 		irlap_do_event(self, RECV_RNR_CMD, skb, info);
+@@ -668,7 +668,7 @@ static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
+ static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
+ 				 struct irlap_info *info, int command)
+ {
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s()\n", __func__);
+ 
+ 	info->nr = skb->data[1] >> 5;
+ 
+@@ -682,7 +682,7 @@ static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
+ static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
+ 				  struct irlap_info *info, int command)
+ {
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s()\n", __func__);
+ 
+ 	info->nr = skb->data[1] >> 5;
+ 
+@@ -696,7 +696,7 @@ static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
+ static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
+ 				  struct irlap_info *info, int command)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	/* Check if this is a command or a response frame */
+ 	if (command)
+@@ -755,7 +755,7 @@ void irlap_send_data_primary(struct irlap_cb *self, struct sk_buff *skb)
+ 
+ 		irlap_send_i_frame( self, tx_skb, CMD_FRAME);
+ 	} else {
+-		IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __func__);
+ 		irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);
+ 		self->window -= 1;
+ 	}
+@@ -808,7 +808,7 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
+ 		irlap_next_state(self, LAP_NRM_P);
+ 		irlap_send_i_frame(self, tx_skb, CMD_FRAME);
+ 	} else {
+-		IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __func__);
+ 
+ 		if (self->ack_required) {
+ 			irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);
+@@ -835,7 +835,7 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
+ 	 * See max_line_capacities[][] in qos.c for details. Jean II */
+ 	transmission_time -= (self->final_timeout * self->bytes_left
+ 			      / self->line_capacity);
+-	IRDA_DEBUG(4, "%s() adjusting transmission_time : ft=%d, bl=%d, lc=%d -> tt=%d\n", __FUNCTION__, self->final_timeout, self->bytes_left, self->line_capacity, transmission_time);
++	IRDA_DEBUG(4, "%s() adjusting transmission_time : ft=%d, bl=%d, lc=%d -> tt=%d\n", __func__, self->final_timeout, self->bytes_left, self->line_capacity, transmission_time);
+ 
+ 	/* We are allowed to transmit a maximum number of bytes again. */
+ 	self->bytes_left = self->line_capacity;
+@@ -1001,7 +1001,7 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
+ 		/* tx_skb = skb_clone( skb, GFP_ATOMIC); */
+ 		tx_skb = skb_copy(skb, GFP_ATOMIC);
+ 		if (!tx_skb) {
+-			IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
++			IRDA_DEBUG(0, "%s(), unable to copy\n", __func__);
+ 			return;
+ 		}
+ 
+@@ -1033,7 +1033,7 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
+ 	 */
+ 	while (!skb_queue_empty(&self->txq)) {
+ 
+-		IRDA_DEBUG(0, "%s(), sending additional frames!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), sending additional frames!\n", __func__);
+ 		if (self->window > 0) {
+ 			skb = skb_dequeue( &self->txq);
+ 			IRDA_ASSERT(skb != NULL, return;);
+@@ -1073,7 +1073,7 @@ void irlap_resend_rejected_frame(struct irlap_cb *self, int command)
+ 		/* tx_skb = skb_clone( skb, GFP_ATOMIC); */
+ 		tx_skb = skb_copy(skb, GFP_ATOMIC);
+ 		if (!tx_skb) {
+-			IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
++			IRDA_DEBUG(0, "%s(), unable to copy\n", __func__);
+ 			return;
+ 		}
+ 
+@@ -1096,7 +1096,7 @@ void irlap_resend_rejected_frame(struct irlap_cb *self, int command)
+ void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
+ 			 __u8 caddr, int command)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -1156,7 +1156,7 @@ static inline void irlap_recv_i_frame(struct irlap_cb *self,
+ static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
+ 				struct irlap_info *info)
+ {
+-	IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG( 4, "%s()\n", __func__);
+ 
+ 	info->pf = skb->data[1] & PF_BIT;      /* Final bit */
+ 
+@@ -1175,7 +1175,7 @@ static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
+ 	__u8 *frame;
+ 	int w, x, y, z;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -1183,7 +1183,7 @@ static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
+ 	IRDA_ASSERT(info != NULL, return;);
+ 
+ 	if (!pskb_may_pull(skb, 4)) {
+-		IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++		IRDA_ERROR("%s: frame too short!\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -1269,10 +1269,10 @@ static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
+ {
+ 	struct test_frame *frame;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	if (!pskb_may_pull(skb, sizeof(*frame))) {
+-		IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++		IRDA_ERROR("%s: frame too short!\n", __func__);
+ 		return;
+ 	}
+ 	frame = (struct test_frame *) skb->data;
+@@ -1281,7 +1281,7 @@ static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
+ 	if (info->caddr == CBROADCAST) {
+ 		if (skb->len < sizeof(struct test_frame)) {
+ 			IRDA_DEBUG(0, "%s() test frame too short!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			return;
+ 		}
+ 
+@@ -1326,7 +1326,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	int command;
+ 	__u8 control;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto out;
+ 
+ 	/* FIXME: should we get our own field? */
+@@ -1342,14 +1342,14 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	 * share and non linear skbs. This should never happen, so
+ 	 * we don't need to be clever about it. Jean II */
+ 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
+-		IRDA_ERROR("%s: can't clone shared skb!\n", __FUNCTION__);
++		IRDA_ERROR("%s: can't clone shared skb!\n", __func__);
+ 		dev_kfree_skb(skb);
+ 		return -1;
+ 	}
+ 
+ 	/* Check if frame is large enough for parsing */
+ 	if (!pskb_may_pull(skb, 2)) {
+-		IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++		IRDA_ERROR("%s: frame too short!\n", __func__);
+ 		dev_kfree_skb(skb);
+ 		return -1;
+ 	}
+@@ -1365,7 +1365,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	/*  First we check if this frame has a valid connection address */
+ 	if ((info.caddr != self->caddr) && (info.caddr != CBROADCAST)) {
+ 		IRDA_DEBUG(0, "%s(), wrong connection address!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		goto out;
+ 	}
+ 	/*
+@@ -1400,7 +1400,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ 			break;
+ 		default:
+ 			IRDA_WARNING("%s: Unknown S-frame %02x received!\n",
+-				__FUNCTION__, info.control);
++				__func__, info.control);
+ 			break;
+ 		}
+ 		goto out;
+@@ -1438,7 +1438,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ 		break;
+ 	default:
+ 		IRDA_WARNING("%s: Unknown frame %02x received!\n",
+-				__FUNCTION__, info.control);
++				__func__, info.control);
+ 		break;
+ 	}
+ out:
+diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
+index 135ac69..1f81f8e 100644
+--- a/net/irda/irlmp.c
++++ b/net/irda/irlmp.c
+@@ -76,7 +76,7 @@ const char *irlmp_reasons[] = {
+  */
+ int __init irlmp_init(void)
+ {
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 	/* Initialize the irlmp structure. */
+ 	irlmp = kzalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
+ 	if (irlmp == NULL)
+@@ -164,7 +164,7 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
+ 	/* Allocate new instance of a LSAP connection */
+ 	self = kzalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
+ 	if (self == NULL) {
+-		IRDA_ERROR("%s: can't allocate memory\n", __FUNCTION__);
++		IRDA_ERROR("%s: can't allocate memory\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -202,7 +202,7 @@ EXPORT_SYMBOL(irlmp_open_lsap);
+  */
+ static void __irlmp_close_lsap(struct lsap_cb *self)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+@@ -264,7 +264,7 @@ void irlmp_close_lsap(struct lsap_cb *self)
+ 	if (!lsap) {
+ 		IRDA_DEBUG(0,
+ 		     "%s(), Looks like somebody has removed me already!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		return;
+ 	}
+ 	__irlmp_close_lsap(self);
+@@ -291,7 +291,7 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
+ 	 */
+ 	lap = kzalloc(sizeof(struct lap_cb), GFP_KERNEL);
+ 	if (lap == NULL) {
+-		IRDA_ERROR("%s: unable to kmalloc\n", __FUNCTION__);
++		IRDA_ERROR("%s: unable to kmalloc\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -304,7 +304,7 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
+ #endif
+ 	lap->lsaps = hashbin_new(HB_LOCK);
+ 	if (lap->lsaps == NULL) {
+-		IRDA_WARNING("%s(), unable to kmalloc lsaps\n", __FUNCTION__);
++		IRDA_WARNING("%s(), unable to kmalloc lsaps\n", __func__);
+ 		kfree(lap);
+ 		return;
+ 	}
+@@ -336,7 +336,7 @@ void irlmp_unregister_link(__u32 saddr)
+ {
+ 	struct lap_cb *link;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	/* We must remove ourselves from the hashbin *first*. This ensure
+ 	 * that no more LSAPs will be open on this link and no discovery
+@@ -381,7 +381,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
+ 
+ 	IRDA_DEBUG(2,
+ 	      "%s(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n",
+-	      __FUNCTION__, self->slsap_sel, dlsap_sel, saddr, daddr);
++	      __func__, self->slsap_sel, dlsap_sel, saddr, daddr);
+ 
+ 	if (test_bit(0, &self->connected)) {
+ 		ret = -EISCONN;
+@@ -425,7 +425,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
+ 		if (daddr != DEV_ADDR_ANY)
+ 			discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
+ 		else {
+-			IRDA_DEBUG(2, "%s(), no daddr\n", __FUNCTION__);
++			IRDA_DEBUG(2, "%s(), no daddr\n", __func__);
+ 			discovery = (discovery_t *)
+ 				hashbin_get_first(irlmp->cachelog);
+ 		}
+@@ -438,7 +438,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
+ 	}
+ 	lap = hashbin_lock_find(irlmp->links, saddr, NULL);
+ 	if (lap == NULL) {
+-		IRDA_DEBUG(1, "%s(), Unable to find a usable link!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Unable to find a usable link!\n", __func__);
+ 		ret = -EHOSTUNREACH;
+ 		goto err;
+ 	}
+@@ -453,14 +453,14 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
+ 			 * disconnected yet (waiting for timeout in LAP).
+ 			 * Maybe we could give LAP a bit of help in this case.
+ 			 */
+-			IRDA_DEBUG(0, "%s(), sorry, but I'm waiting for LAP to timeout!\n", __FUNCTION__);
++			IRDA_DEBUG(0, "%s(), sorry, but I'm waiting for LAP to timeout!\n", __func__);
+ 			ret = -EAGAIN;
+ 			goto err;
+ 		}
+ 
+ 		/* LAP is already connected to a different node, and LAP
+ 		 * can only talk to one node at a time */
+-		IRDA_DEBUG(0, "%s(), sorry, but link is busy!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), sorry, but link is busy!\n", __func__);
+ 		ret = -EBUSY;
+ 		goto err;
+ 	}
+@@ -522,7 +522,7 @@ void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb)
+ 	IRDA_ASSERT(self->lap != NULL, return;);
+ 
+ 	IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
+-		   __FUNCTION__, self->slsap_sel, self->dlsap_sel);
++		   __func__, self->slsap_sel, self->dlsap_sel);
+ 
+ 	/* Note : self->lap is set in irlmp_link_data_indication(),
+ 	 * (case CONNECT_CMD:) because we have no way to set it here.
+@@ -563,7 +563,7 @@ int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata)
+ 	 * in the state machine itself. Jean II */
+ 
+ 	IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
+-		   __FUNCTION__, self->slsap_sel, self->dlsap_sel);
++		   __func__, self->slsap_sel, self->dlsap_sel);
+ 
+ 	/* Make room for MUX control header (3 bytes) */
+ 	IRDA_ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;);
+@@ -589,7 +589,7 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb)
+ 	int lap_header_size;
+ 	int max_seg_size;
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(skb != NULL, return;);
+ 	IRDA_ASSERT(self != NULL, return;);
+@@ -603,7 +603,7 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb)
+ 	max_header_size = LMP_HEADER + lap_header_size;
+ 
+ 	IRDA_DEBUG(2, "%s(), max_header_size=%d\n",
+-		   __FUNCTION__, max_header_size);
++		   __func__, max_header_size);
+ 
+ 	/* Hide LMP_CONTROL_HEADER header from layer above */
+ 	skb_pull(skb, LMP_CONTROL_HEADER);
+@@ -629,7 +629,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
+ 	struct lsap_cb *new;
+ 	unsigned long flags;
+ 
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 
+ 	spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
+ 
+@@ -638,7 +638,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
+ 	if ((!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) ||
+ 	    (orig->lap == NULL)) {
+ 		IRDA_DEBUG(0, "%s(), invalid LSAP (wrong state)\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
+ 				       flags);
+ 		return NULL;
+@@ -647,7 +647,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
+ 	/* Allocate a new instance */
+ 	new = kmemdup(orig, sizeof(*new), GFP_ATOMIC);
+ 	if (!new)  {
+-		IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __func__);
+ 		spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
+ 				       flags);
+ 		return NULL;
+@@ -693,7 +693,7 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
+ 	 * and us that might mess up the hashbins below. This fixes it.
+ 	 * Jean II */
+ 	if (! test_and_clear_bit(0, &self->connected)) {
+-		IRDA_DEBUG(0, "%s(), already disconnected!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), already disconnected!\n", __func__);
+ 		dev_kfree_skb(userdata);
+ 		return -1;
+ 	}
+@@ -747,19 +747,19 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
+ {
+ 	struct lsap_cb *lsap;
+ 
+-	IRDA_DEBUG(1, "%s(), reason=%s\n", __FUNCTION__, irlmp_reasons[reason]);
++	IRDA_DEBUG(1, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ 
+ 	IRDA_DEBUG(3, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
+-		   __FUNCTION__, self->slsap_sel, self->dlsap_sel);
++		   __func__, self->slsap_sel, self->dlsap_sel);
+ 
+ 	/* Already disconnected ?
+ 	 * There is a race condition between irlmp_disconnect_request()
+ 	 * and us that might mess up the hashbins below. This fixes it.
+ 	 * Jean II */
+ 	if (! test_and_clear_bit(0, &self->connected)) {
+-		IRDA_DEBUG(0, "%s(), already disconnected!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), already disconnected!\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -792,7 +792,7 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
+ 		self->notify.disconnect_indication(self->notify.instance,
+ 						   self, reason, skb);
+ 	} else {
+-		IRDA_DEBUG(0, "%s(), no handler\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), no handler\n", __func__);
+ 	}
+ }
+ 
+@@ -845,7 +845,7 @@ void irlmp_do_discovery(int nslots)
+ 	/* Make sure the value is sane */
+ 	if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){
+ 		IRDA_WARNING("%s: invalid value for number of slots!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		nslots = sysctl_discovery_slots = 8;
+ 	}
+ 
+@@ -963,7 +963,7 @@ irlmp_notify_client(irlmp_client_t *client,
+ 	int	number;			/* Number of nodes in the log */
+ 	int	i;
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	/* Check if client wants or not partial/selective log (optimisation) */
+ 	if (!client->disco_callback)
+@@ -1014,7 +1014,7 @@ void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode)
+ 	irlmp_client_t *client;
+ 	irlmp_client_t *client_next;
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(log != NULL, return;);
+ 
+@@ -1049,7 +1049,7 @@ void irlmp_discovery_expiry(discinfo_t *expiries, int number)
+ 	irlmp_client_t *client_next;
+ 	int		i;
+ 
+-	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(3, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(expiries != NULL, return;);
+ 
+@@ -1082,7 +1082,7 @@ void irlmp_discovery_expiry(discinfo_t *expiries, int number)
+  */
+ discovery_t *irlmp_get_discovery_response(void)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(irlmp != NULL, return NULL;);
+ 
+@@ -1160,7 +1160,7 @@ int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *userdata)
+ {
+ 	int	ret;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(userdata != NULL, return -1;);
+ 
+@@ -1184,7 +1184,7 @@ int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *userdata)
+  */
+ void irlmp_udata_indication(struct lsap_cb *self, struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+@@ -1211,7 +1211,7 @@ int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *userdata,
+ 	struct sk_buff *clone_skb;
+ 	struct lap_cb *lap;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(userdata != NULL, return -1;);
+ 
+@@ -1262,7 +1262,7 @@ int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *userdata,
+ #ifdef CONFIG_IRDA_ULTRA
+ void irlmp_connless_data_indication(struct lsap_cb *self, struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+@@ -1305,7 +1305,7 @@ void irlmp_status_indication(struct lap_cb *self,
+ 			curr->notify.status_indication(curr->notify.instance,
+ 						       link, lock);
+ 		else
+-			IRDA_DEBUG(2, "%s(), no handler\n", __FUNCTION__);
++			IRDA_DEBUG(2, "%s(), no handler\n", __func__);
+ 
+ 		curr = next;
+ 	}
+@@ -1333,7 +1333,7 @@ void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow)
+ 	/* Get the number of lsap. That's the only safe way to know
+ 	 * that we have looped around... - Jean II */
+ 	lsap_todo = HASHBIN_GET_SIZE(self->lsaps);
+-	IRDA_DEBUG(4, "%s() : %d lsaps to scan\n", __FUNCTION__, lsap_todo);
++	IRDA_DEBUG(4, "%s() : %d lsaps to scan\n", __func__, lsap_todo);
+ 
+ 	/* Poll lsap in order until the queue is full or until we
+ 	 * tried them all.
+@@ -1352,14 +1352,14 @@ void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow)
+ 		/* Uh-oh... Paranoia */
+ 		if(curr == NULL)
+ 			break;
+-		IRDA_DEBUG(4, "%s() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", __FUNCTION__, curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));
++		IRDA_DEBUG(4, "%s() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", __func__, curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));
+ 
+ 		/* Inform lsap user that it can send one more packet. */
+ 		if (curr->notify.flow_indication != NULL)
+ 			curr->notify.flow_indication(curr->notify.instance,
+ 						     curr, flow);
+ 		else
+-			IRDA_DEBUG(1, "%s(), no handler\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), no handler\n", __func__);
+ 	}
+ }
+ 
+@@ -1381,7 +1381,7 @@ __u8 *irlmp_hint_to_service(__u8 *hint)
+ 	 */
+ 	service = kmalloc(16, GFP_ATOMIC);
+ 	if (!service) {
+-		IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -1482,12 +1482,12 @@ void *irlmp_register_service(__u16 hints)
+ {
+ 	irlmp_service_t *service;
+ 
+-	IRDA_DEBUG(4, "%s(), hints = %04x\n", __FUNCTION__, hints);
++	IRDA_DEBUG(4, "%s(), hints = %04x\n", __func__, hints);
+ 
+ 	/* Make a new registration */
+ 	service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC);
+ 	if (!service) {
+-		IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __func__);
+ 		return NULL;
+ 	}
+ 	service->hints.word = hints;
+@@ -1512,7 +1512,7 @@ int irlmp_unregister_service(void *handle)
+ 	irlmp_service_t *service;
+ 	unsigned long flags;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	if (!handle)
+ 		return -1;
+@@ -1520,7 +1520,7 @@ int irlmp_unregister_service(void *handle)
+ 	/* Caller may call with invalid handle (it's legal) - Jean II */
+ 	service = hashbin_lock_find(irlmp->services, (long) handle, NULL);
+ 	if (!service) {
+-		IRDA_DEBUG(1, "%s(), Unknown service!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Unknown service!\n", __func__);
+ 		return -1;
+ 	}
+ 
+@@ -1557,13 +1557,13 @@ void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
+ {
+ 	irlmp_client_t *client;
+ 
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 	IRDA_ASSERT(irlmp != NULL, return NULL;);
+ 
+ 	/* Make a new registration */
+ 	client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC);
+ 	if (!client) {
+-		IRDA_DEBUG( 1, "%s(), Unable to kmalloc!\n", __FUNCTION__);
++		IRDA_DEBUG( 1, "%s(), Unable to kmalloc!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -1599,7 +1599,7 @@ int irlmp_update_client(void *handle, __u16 hint_mask,
+ 
+ 	client = hashbin_lock_find(irlmp->clients, (long) handle, NULL);
+ 	if (!client) {
+-		IRDA_DEBUG(1, "%s(), Unknown client!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Unknown client!\n", __func__);
+ 		return -1;
+ 	}
+ 
+@@ -1622,7 +1622,7 @@ int irlmp_unregister_client(void *handle)
+ {
+ 	struct irlmp_client *client;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	if (!handle)
+ 		return -1;
+@@ -1630,11 +1630,11 @@ int irlmp_unregister_client(void *handle)
+ 	/* Caller may call with invalid handle (it's legal) - Jean II */
+ 	client = hashbin_lock_find(irlmp->clients, (long) handle, NULL);
+ 	if (!client) {
+-		IRDA_DEBUG(1, "%s(), Unknown client!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Unknown client!\n", __func__);
+ 		return -1;
+ 	}
+ 
+-	IRDA_DEBUG(4, "%s(), removing client!\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s(), removing client!\n", __func__);
+ 	hashbin_remove_this(irlmp->clients, (irda_queue_t *) client);
+ 	kfree(client);
+ 
+@@ -1663,7 +1663,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
+ 	IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
+ 	IRDA_ASSERT(slsap_sel != LSAP_ANY, return TRUE;);
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ #ifdef CONFIG_IRDA_ULTRA
+ 	/* Accept all bindings to the connectionless LSAP */
+@@ -1790,7 +1790,7 @@ static __u8 irlmp_find_free_slsap(void)
+ 			/* Make sure we terminate the loop */
+ 			if (wrapped++) {
+ 				IRDA_ERROR("%s: no more free LSAPs !\n",
+-					   __FUNCTION__);
++					   __func__);
+ 				return 0;
+ 			}
+ 		}
+@@ -1805,7 +1805,7 @@ static __u8 irlmp_find_free_slsap(void)
+ 	/* Got it ! */
+ 	lsap_sel = irlmp->last_lsap_sel;
+ 	IRDA_DEBUG(4, "%s(), found free lsap_sel=%02x\n",
+-		   __FUNCTION__, lsap_sel);
++		   __func__, lsap_sel);
+ 
+ 	return lsap_sel;
+ }
+@@ -1823,26 +1823,26 @@ LM_REASON irlmp_convert_lap_reason( LAP_REASON lap_reason)
+ 
+ 	switch (lap_reason) {
+ 	case LAP_DISC_INDICATION: /* Received a disconnect request from peer */
+-		IRDA_DEBUG( 1, "%s(), LAP_DISC_INDICATION\n", __FUNCTION__);
++		IRDA_DEBUG( 1, "%s(), LAP_DISC_INDICATION\n", __func__);
+ 		reason = LM_USER_REQUEST;
+ 		break;
+ 	case LAP_NO_RESPONSE:    /* To many retransmits without response */
+-		IRDA_DEBUG( 1, "%s(), LAP_NO_RESPONSE\n", __FUNCTION__);
++		IRDA_DEBUG( 1, "%s(), LAP_NO_RESPONSE\n", __func__);
+ 		reason = LM_LAP_DISCONNECT;
+ 		break;
+ 	case LAP_RESET_INDICATION:
+-		IRDA_DEBUG( 1, "%s(), LAP_RESET_INDICATION\n", __FUNCTION__);
++		IRDA_DEBUG( 1, "%s(), LAP_RESET_INDICATION\n", __func__);
+ 		reason = LM_LAP_RESET;
+ 		break;
+ 	case LAP_FOUND_NONE:
+ 	case LAP_MEDIA_BUSY:
+ 	case LAP_PRIMARY_CONFLICT:
+-		IRDA_DEBUG(1, "%s(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n", __func__);
+ 		reason = LM_CONNECT_FAILURE;
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(1, "%s(), Unknow IrLAP disconnect reason %d!\n",
+-			   __FUNCTION__, lap_reason);
++			   __func__, lap_reason);
+ 		reason = LM_LAP_DISCONNECT;
+ 		break;
+ 	}
+diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c
+index 150cd3f..78cce0c 100644
+--- a/net/irda/irlmp_event.c
++++ b/net/irda/irlmp_event.c
+@@ -120,7 +120,7 @@ static inline void irlmp_next_lap_state(struct lap_cb *self,
+ 					IRLMP_STATE state)
+ {
+ 	/*
+-	IRDA_DEBUG(4, "%s(), LMP LAP = %s\n", __FUNCTION__, irlmp_state[state]);
++	IRDA_DEBUG(4, "%s(), LMP LAP = %s\n", __func__, irlmp_state[state]);
+ 	*/
+ 	self->lap_state = state;
+ }
+@@ -130,7 +130,7 @@ static inline void irlmp_next_lsap_state(struct lsap_cb *self,
+ {
+ 	/*
+ 	IRDA_ASSERT(self != NULL, return;);
+-	IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __FUNCTION__, irlsap_state[state]);
++	IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __func__, irlsap_state[state]);
+ 	*/
+ 	self->lsap_state = state;
+ }
+@@ -143,7 +143,7 @@ int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ 
+ 	IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n",
+-		__FUNCTION__, irlmp_event[event], irlsap_state[ self->lsap_state]);
++		__func__, irlmp_event[event], irlsap_state[ self->lsap_state]);
+ 
+ 	return (*lsap_state[self->lsap_state]) (self, event, skb);
+ }
+@@ -160,7 +160,7 @@ void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ 
+-	IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n", __FUNCTION__,
++	IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n", __func__,
+ 		   irlmp_event[event],
+ 		   irlmp_state[self->lap_state]);
+ 
+@@ -169,7 +169,7 @@ void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
+ 
+ void irlmp_discovery_timer_expired(void *data)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	/* We always cleanup the log (active & passive discovery) */
+ 	irlmp_do_expiry();
+@@ -184,7 +184,7 @@ void irlmp_watchdog_timer_expired(void *data)
+ {
+ 	struct lsap_cb *self = (struct lsap_cb *) data;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+@@ -196,7 +196,7 @@ void irlmp_idle_timer_expired(void *data)
+ {
+ 	struct lap_cb *self = (struct lap_cb *) data;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -256,7 +256,7 @@ irlmp_do_all_lsap_event(hashbin_t *	lsap_hashbin,
+ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
+ 				struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 	IRDA_ASSERT(self->irlap != NULL, return;);
+ 
+ 	switch (event) {
+@@ -276,7 +276,7 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
+ 		irlap_connect_response(self->irlap, skb);
+ 		break;
+ 	case LM_LAP_CONNECT_REQUEST:
+-		IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __func__);
+ 
+ 		irlmp_next_lap_state(self, LAP_U_CONNECT);
+ 
+@@ -285,13 +285,13 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
+ 		break;
+ 	case LM_LAP_DISCONNECT_INDICATION:
+ 		IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
+-			   __FUNCTION__);
++			   __func__);
+ 
+ 		irlmp_next_lap_state(self, LAP_STANDBY);
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(0, "%s(), Unknown event %s\n",
+-			   __FUNCTION__, irlmp_event[event]);
++			   __func__, irlmp_event[event]);
+ 		break;
+ 	}
+ }
+@@ -306,7 +306,7 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
+ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ 				  struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(2, "%s(), event=%s\n", __FUNCTION__, irlmp_event[event]);
++	IRDA_DEBUG(2, "%s(), event=%s\n", __func__, irlmp_event[event]);
+ 
+ 	switch (event) {
+ 	case LM_LAP_CONNECT_INDICATION:
+@@ -326,7 +326,7 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ 		 * the lsaps may already have gone. This avoid getting stuck
+ 		 * forever in LAP_ACTIVE state - Jean II */
+ 		if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
+-			IRDA_DEBUG(0, "%s() NO LSAPs !\n",  __FUNCTION__);
++			IRDA_DEBUG(0, "%s() NO LSAPs !\n",  __func__);
+ 			irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
+ 		}
+ 		break;
+@@ -344,12 +344,12 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ 		 * the lsaps may already have gone. This avoid getting stuck
+ 		 * forever in LAP_ACTIVE state - Jean II */
+ 		if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
+-			IRDA_DEBUG(0, "%s() NO LSAPs !\n",  __FUNCTION__);
++			IRDA_DEBUG(0, "%s() NO LSAPs !\n",  __func__);
+ 			irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
+ 		}
+ 		break;
+ 	case LM_LAP_DISCONNECT_INDICATION:
+-		IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n",  __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n",  __func__);
+ 		irlmp_next_lap_state(self, LAP_STANDBY);
+ 
+ 		/* Send disconnect event to all LSAPs using this link */
+@@ -357,7 +357,7 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ 					LM_LAP_DISCONNECT_INDICATION);
+ 		break;
+ 	case LM_LAP_DISCONNECT_REQUEST:
+-		IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n",  __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n",  __func__);
+ 
+ 		/* One of the LSAP did timeout or was closed, if it was
+ 		 * the last one, try to get out of here - Jean II */
+@@ -367,7 +367,7 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(0, "%s(), Unknown event %s\n",
+-			 __FUNCTION__, irlmp_event[event]);
++			 __func__, irlmp_event[event]);
+ 		break;
+ 	}
+ }
+@@ -381,11 +381,11 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
+ 			       struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	switch (event) {
+ 	case LM_LAP_CONNECT_REQUEST:
+-		IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __func__);
+ 
+ 		/*
+ 		 * IrLAP may have a pending disconnect. We tried to close
+@@ -468,7 +468,7 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(0, "%s(), Unknown event %s\n",
+-			 __FUNCTION__, irlmp_event[event]);
++			 __func__, irlmp_event[event]);
+ 		break;
+ 	}
+ }
+@@ -490,7 +490,7 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+@@ -505,11 +505,11 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+ 		break;
+ #endif /* CONFIG_IRDA_ULTRA */
+ 	case LM_CONNECT_REQUEST:
+-		IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __func__);
+ 
+ 		if (self->conn_skb) {
+ 			IRDA_WARNING("%s: busy with another request!\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			return -EBUSY;
+ 		}
+ 		/* Don't forget to refcount it (see irlmp_connect_request()) */
+@@ -526,7 +526,7 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+ 	case LM_CONNECT_INDICATION:
+ 		if (self->conn_skb) {
+ 			IRDA_WARNING("%s: busy with another request!\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			return -EBUSY;
+ 		}
+ 		/* Don't forget to refcount it (see irlap_driver_rcv()) */
+@@ -552,7 +552,7 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
+-			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
++			   __func__, irlmp_event[event], self->slsap_sel);
+ 		break;
+ 	}
+ 	return ret;
+@@ -570,7 +570,7 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
+ 	struct lsap_cb *lsap;
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+@@ -603,7 +603,7 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
+ 	case LM_WATCHDOG_TIMEOUT:
+ 		/* May happen, who knows...
+ 		 * Jean II */
+-		IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __FUNCTION__);
++		IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __func__);
+ 
+ 		/* Disconnect, get out... - Jean II */
+ 		self->lap = NULL;
+@@ -614,7 +614,7 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
+ 		/* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
+ 		 * are *not* yet bound to the IrLAP link. Jean II */
+ 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+-			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
++			   __func__, irlmp_event[event], self->slsap_sel);
+ 		break;
+ 	}
+ 	return ret;
+@@ -632,7 +632,7 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ 	struct sk_buff *tx_skb;
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+@@ -643,16 +643,16 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ 		break;
+ 	case LM_CONNECT_RESPONSE:
+ 		IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
+-			   "no indication issued yet\n",  __FUNCTION__);
++			   "no indication issued yet\n",  __func__);
+ 		/* Keep state */
+ 		break;
+ 	case LM_DISCONNECT_REQUEST:
+ 		IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
+-			   "not yet bound to IrLAP connection\n",  __FUNCTION__);
++			   "not yet bound to IrLAP connection\n",  __func__);
+ 		/* Keep state */
+ 		break;
+ 	case LM_LAP_CONNECT_CONFIRM:
+-		IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n",  __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n",  __func__);
+ 		irlmp_next_lsap_state(self, LSAP_CONNECT);
+ 
+ 		tx_skb = self->conn_skb;
+@@ -666,7 +666,7 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ 		/* Will happen in some rare cases because of a race condition.
+ 		 * Just make sure we don't stay there forever...
+ 		 * Jean II */
+-		IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __FUNCTION__);
++		IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __func__);
+ 
+ 		/* Go back to disconnected mode, keep the socket waiting */
+ 		self->lap = NULL;
+@@ -680,7 +680,7 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ 		/* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
+ 		 * are *not* yet bound to the IrLAP link. Jean II */
+ 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+-			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
++			   __func__, irlmp_event[event], self->slsap_sel);
+ 		break;
+ 	}
+ 	return ret;
+@@ -698,7 +698,7 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
+ 	LM_REASON reason;
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+@@ -722,12 +722,12 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
+ 		break;
+ 	case LM_CONNECT_REQUEST:
+ 		IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
+-			   "error, LSAP already connected\n", __FUNCTION__);
++			   "error, LSAP already connected\n", __func__);
+ 		/* Keep state */
+ 		break;
+ 	case LM_CONNECT_RESPONSE:
+ 		IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
+-			   "error, LSAP already connected\n", __FUNCTION__);
++			   "error, LSAP already connected\n", __func__);
+ 		/* Keep state */
+ 		break;
+ 	case LM_DISCONNECT_REQUEST:
+@@ -740,7 +740,7 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
+ 		/* Try to close the LAP connection if its still there */
+ 		if (self->lap) {
+ 			IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			irlmp_do_lap_event(self->lap,
+ 					   LM_LAP_DISCONNECT_REQUEST,
+ 					   NULL);
+@@ -764,14 +764,14 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
+ 		reason = skb->data[3];
+ 
+ 		 /* Try to close the LAP connection */
+-		IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __func__);
+ 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+ 
+ 		irlmp_disconnect_indication(self, reason, skb);
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+-			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
++			   __func__, irlmp_event[event], self->slsap_sel);
+ 		break;
+ 	}
+ 	return ret;
+@@ -793,7 +793,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	switch (event) {
+ 	case LM_CONNECT_CONFIRM:
+@@ -814,7 +814,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
+ 		reason = skb->data[3];
+ 
+ 		 /* Try to close the LAP connection */
+-		IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",  __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",  __func__);
+ 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+ 
+ 		irlmp_disconnect_indication(self, reason, skb);
+@@ -832,7 +832,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
+ 		irlmp_disconnect_indication(self, reason, skb);
+ 		break;
+ 	case LM_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__);
+ 
+ 		IRDA_ASSERT(self->lap != NULL, return -1;);
+ 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+@@ -842,7 +842,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+-			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
++			   __func__, irlmp_event[event], self->slsap_sel);
+ 		break;
+ 	}
+ 	return ret;
+@@ -863,7 +863,7 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ 	LM_REASON reason;
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(irlmp != NULL, return -1;);
+@@ -883,7 +883,7 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ 		irlmp_next_lsap_state(self, LSAP_SETUP);
+ 		break;
+ 	case LM_WATCHDOG_TIMEOUT:
+-		IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n",  __FUNCTION__);
++		IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n",  __func__);
+ 
+ 		IRDA_ASSERT(self->lap != NULL, return -1;);
+ 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+@@ -902,7 +902,7 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ 		break;
+ 	default:
+ 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+-			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
++			   __func__, irlmp_event[event], self->slsap_sel);
+ 		break;
+ 	}
+ 	return ret;
+diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c
+index 0a79d9a..3750884 100644
+--- a/net/irda/irlmp_frame.c
++++ b/net/irda/irlmp_frame.c
+@@ -44,7 +44,7 @@ inline void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
+ 	skb->data[1] = slsap;
+ 
+ 	if (expedited) {
+-		IRDA_DEBUG(4, "%s(), sending expedited data\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), sending expedited data\n", __func__);
+ 		irlap_data_request(self->irlap, skb, TRUE);
+ 	} else
+ 		irlap_data_request(self->irlap, skb, FALSE);
+@@ -60,7 +60,7 @@ void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
+ {
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -95,7 +95,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ 	__u8   dlsap_sel;   /* Destination LSAP address */
+ 	__u8   *fp;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -117,7 +117,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ 	if ((fp[0] & CONTROL_BIT) && (fp[2] == CONNECT_CMD)) {
+ 		IRDA_DEBUG(3, "%s(), incoming connection, "
+ 			   "source LSAP=%d, dest LSAP=%d\n",
+-			   __FUNCTION__, slsap_sel, dlsap_sel);
++			   __func__, slsap_sel, dlsap_sel);
+ 
+ 		/* Try to find LSAP among the unconnected LSAPs */
+ 		lsap = irlmp_find_lsap(self, dlsap_sel, slsap_sel, CONNECT_CMD,
+@@ -125,7 +125,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ 
+ 		/* Maybe LSAP was already connected, so try one more time */
+ 		if (!lsap) {
+-			IRDA_DEBUG(1, "%s(), incoming connection for LSAP already connected\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), incoming connection for LSAP already connected\n", __func__);
+ 			lsap = irlmp_find_lsap(self, dlsap_sel, slsap_sel, 0,
+ 					       self->lsaps);
+ 		}
+@@ -136,12 +136,12 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ 	if (lsap == NULL) {
+ 		IRDA_DEBUG(2, "IrLMP, Sorry, no LSAP for received frame!\n");
+ 		IRDA_DEBUG(2, "%s(), slsap_sel = %02x, dlsap_sel = %02x\n",
+-			   __FUNCTION__, slsap_sel, dlsap_sel);
++			   __func__, slsap_sel, dlsap_sel);
+ 		if (fp[0] & CONTROL_BIT) {
+ 			IRDA_DEBUG(2, "%s(), received control frame %02x\n",
+-				   __FUNCTION__, fp[2]);
++				   __func__, fp[2]);
+ 		} else {
+-			IRDA_DEBUG(2, "%s(), received data frame\n", __FUNCTION__);
++			IRDA_DEBUG(2, "%s(), received data frame\n", __func__);
+ 		}
+ 		return;
+ 	}
+@@ -160,7 +160,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ 			break;
+ 		case DISCONNECT:
+ 			IRDA_DEBUG(4, "%s(), Disconnect indication!\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			irlmp_do_lsap_event(lsap, LM_DISCONNECT_INDICATION,
+ 					    skb);
+ 			break;
+@@ -172,7 +172,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ 			break;
+ 		default:
+ 			IRDA_DEBUG(0, "%s(), Unknown control frame %02x\n",
+-				   __FUNCTION__, fp[2]);
++				   __func__, fp[2]);
+ 			break;
+ 		}
+ 	} else if (unreliable) {
+@@ -206,7 +206,7 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
+ 	__u8   *fp;
+ 	unsigned long flags;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -224,13 +224,13 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
+ 
+ 	if (pid & 0x80) {
+ 		IRDA_DEBUG(0, "%s(), extension in PID not supp!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		return;
+ 	}
+ 
+ 	/* Check if frame is addressed to the connectionless LSAP */
+ 	if ((slsap_sel != LSAP_CONNLESS) || (dlsap_sel != LSAP_CONNLESS)) {
+-		IRDA_DEBUG(0, "%s(), dropping frame!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), dropping frame!\n", __func__);
+ 		return;
+ 	}
+ 
+@@ -254,7 +254,7 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
+ 	if (lsap)
+ 		irlmp_connless_data_indication(lsap, skb);
+ 	else {
+-		IRDA_DEBUG(0, "%s(), found no matching LSAP!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), found no matching LSAP!\n", __func__);
+ 	}
+ }
+ #endif /* CONFIG_IRDA_ULTRA */
+@@ -270,7 +270,7 @@ void irlmp_link_disconnect_indication(struct lap_cb *lap,
+ 				      LAP_REASON reason,
+ 				      struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(lap != NULL, return;);
+ 	IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+@@ -296,7 +296,7 @@ void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr,
+ 				   __u32 daddr, struct qos_info *qos,
+ 				   struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	/* Copy QoS settings for this session */
+ 	self->qos = qos;
+@@ -317,7 +317,7 @@ void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr,
+ void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos,
+ 				struct sk_buff *skb)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -383,7 +383,7 @@ void irlmp_link_discovery_indication(struct lap_cb *self,
+  */
+ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log)
+ {
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+diff --git a/net/irda/irmod.c b/net/irda/irmod.c
+index 01554b9..4c487a8 100644
+--- a/net/irda/irmod.c
++++ b/net/irda/irmod.c
+@@ -90,7 +90,7 @@ static int __init irda_init(void)
+ {
+ 	int ret = 0;
+ 
+-	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s()\n", __func__);
+ 
+ 	/* Lower layer of the stack */
+ 	irlmp_init();
+diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
+index 7873c39..b001c36 100644
+--- a/net/irda/irnet/irnet.h
++++ b/net/irda/irnet/irnet.h
+@@ -337,27 +337,27 @@
+ /* All error messages (will show up in the normal logs) */
+ #define DERROR(dbg, format, args...) \
+ 	{if(DEBUG_##dbg) \
+-		printk(KERN_INFO "irnet: %s(): " format, __FUNCTION__ , ##args);}
++		printk(KERN_INFO "irnet: %s(): " format, __func__ , ##args);}
+ 
+ /* Normal debug message (will show up in /var/log/debug) */
+ #define DEBUG(dbg, format, args...) \
+ 	{if(DEBUG_##dbg) \
+-		printk(KERN_DEBUG "irnet: %s(): " format, __FUNCTION__ , ##args);}
++		printk(KERN_DEBUG "irnet: %s(): " format, __func__ , ##args);}
+ 
+ /* Entering a function (trace) */
+ #define DENTER(dbg, format, args...) \
+ 	{if(DEBUG_##dbg) \
+-		printk(KERN_DEBUG "irnet: -> %s" format, __FUNCTION__ , ##args);}
++		printk(KERN_DEBUG "irnet: -> %s" format, __func__ , ##args);}
+ 
+ /* Entering and exiting a function in one go (trace) */
+ #define DPASS(dbg, format, args...) \
+ 	{if(DEBUG_##dbg) \
+-		printk(KERN_DEBUG "irnet: <>%s" format, __FUNCTION__ , ##args);}
++		printk(KERN_DEBUG "irnet: <>%s" format, __func__ , ##args);}
+ 
+ /* Exiting a function (trace) */
+ #define DEXIT(dbg, format, args...) \
+ 	{if(DEBUG_##dbg) \
+-		printk(KERN_DEBUG "irnet: <-%s()" format, __FUNCTION__ , ##args);}
++		printk(KERN_DEBUG "irnet: <-%s()" format, __func__ , ##args);}
+ 
+ /* Exit a function with debug */
+ #define DRETURN(ret, dbg, args...) \
+diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
+index cd9ff17..9e1fb82 100644
+--- a/net/irda/irnetlink.c
++++ b/net/irda/irnetlink.c
+@@ -40,7 +40,7 @@ static struct net_device * ifname_to_netdev(struct net *net, struct genl_info *i
+ 
+ 	ifname = nla_data(info->attrs[IRDA_NL_ATTR_IFNAME]);
+ 
+-	IRDA_DEBUG(5, "%s(): Looking for %s\n", __FUNCTION__, ifname);
++	IRDA_DEBUG(5, "%s(): Looking for %s\n", __func__, ifname);
+ 
+ 	return dev_get_by_name(net, ifname);
+ }
+@@ -56,7 +56,7 @@ static int irda_nl_set_mode(struct sk_buff *skb, struct genl_info *info)
+ 
+ 	mode = nla_get_u32(info->attrs[IRDA_NL_ATTR_MODE]);
+ 
+-	IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __FUNCTION__, mode);
++	IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __func__, mode);
+ 
+ 	dev = ifname_to_netdev(&init_net, info);
+ 	if (!dev)
+diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
+index 40c28ef..ba01938 100644
+--- a/net/irda/irqueue.c
++++ b/net/irda/irqueue.c
+@@ -232,7 +232,7 @@ static __u32 hash( const char* name)
+ static void enqueue_first(irda_queue_t **queue, irda_queue_t* element)
+ {
+ 
+-	IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG( 4, "%s()\n", __func__);
+ 
+ 	/*
+ 	 * Check if queue is empty.
+@@ -451,7 +451,7 @@ void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, long hashv,
+ 	unsigned long flags = 0;
+ 	int bin;
+ 
+-	IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG( 4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT( hashbin != NULL, return;);
+ 	IRDA_ASSERT( hashbin->magic == HB_MAGIC, return;);
+@@ -564,7 +564,7 @@ void* hashbin_remove( hashbin_t* hashbin, long hashv, const char* name)
+ 	unsigned long flags = 0;
+ 	irda_queue_t* entry;
+ 
+-	IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG( 4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT( hashbin != NULL, return NULL;);
+ 	IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+@@ -657,7 +657,7 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
+ 	int	bin;
+ 	long	hashv;
+ 
+-	IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG( 4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT( hashbin != NULL, return NULL;);
+ 	IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+diff --git a/net/irda/irttp.c b/net/irda/irttp.c
+index 97db158..74e439e 100644
+--- a/net/irda/irttp.c
++++ b/net/irda/irttp.c
+@@ -95,7 +95,7 @@ int __init irttp_init(void)
+ 	irttp->tsaps = hashbin_new(HB_LOCK);
+ 	if (!irttp->tsaps) {
+ 		IRDA_ERROR("%s: can't allocate IrTTP hashbin!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		kfree(irttp);
+ 		return -ENOMEM;
+ 	}
+@@ -164,7 +164,7 @@ static void irttp_todo_expired(unsigned long data)
+ 	if (!self || self->magic != TTP_TSAP_MAGIC)
+ 		return;
+ 
+-	IRDA_DEBUG(4, "%s(instance=%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(4, "%s(instance=%p)\n", __func__, self);
+ 
+ 	/* Try to make some progress, especially on Tx side - Jean II */
+ 	irttp_run_rx_queue(self);
+@@ -205,7 +205,7 @@ void irttp_flush_queues(struct tsap_cb *self)
+ {
+ 	struct sk_buff* skb;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+@@ -238,7 +238,7 @@ static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
+ 	IRDA_ASSERT(self != NULL, return NULL;);
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
+ 
+-	IRDA_DEBUG(2, "%s(), self->rx_sdu_size=%d\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s(), self->rx_sdu_size=%d\n", __func__,
+ 		   self->rx_sdu_size);
+ 
+ 	skb = dev_alloc_skb(TTP_HEADER + self->rx_sdu_size);
+@@ -264,7 +264,7 @@ static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
+ 
+ 	IRDA_DEBUG(2,
+ 		   "%s(), frame len=%d, rx_sdu_size=%d, rx_max_sdu_size=%d\n",
+-		   __FUNCTION__, n, self->rx_sdu_size, self->rx_max_sdu_size);
++		   __func__, n, self->rx_sdu_size, self->rx_max_sdu_size);
+ 	/* Note : irttp_run_rx_queue() calculate self->rx_sdu_size
+ 	 * by summing the size of all fragments, so we should always
+ 	 * have n == self->rx_sdu_size, except in cases where we
+@@ -293,7 +293,7 @@ static inline void irttp_fragment_skb(struct tsap_cb *self,
+ 	struct sk_buff *frag;
+ 	__u8 *frame;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+@@ -303,7 +303,7 @@ static inline void irttp_fragment_skb(struct tsap_cb *self,
+ 	 *  Split frame into a number of segments
+ 	 */
+ 	while (skb->len > self->max_seg_size) {
+-		IRDA_DEBUG(2, "%s(), fragmenting ...\n", __FUNCTION__);
++		IRDA_DEBUG(2, "%s(), fragmenting ...\n", __func__);
+ 
+ 		/* Make new segment */
+ 		frag = alloc_skb(self->max_seg_size+self->max_header_size,
+@@ -328,7 +328,7 @@ static inline void irttp_fragment_skb(struct tsap_cb *self,
+ 		skb_queue_tail(&self->tx_queue, frag);
+ 	}
+ 	/* Queue what is left of the original skb */
+-	IRDA_DEBUG(2, "%s(), queuing last segment\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s(), queuing last segment\n", __func__);
+ 
+ 	frame = skb_push(skb, TTP_HEADER);
+ 	frame[0] = 0x00; /* Clear more bit */
+@@ -359,7 +359,7 @@ static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
+ 	else
+ 		self->tx_max_sdu_size = param->pv.i;
+ 
+-	IRDA_DEBUG(1, "%s(), MaxSduSize=%d\n", __FUNCTION__, param->pv.i);
++	IRDA_DEBUG(1, "%s(), MaxSduSize=%d\n", __func__, param->pv.i);
+ 
+ 	return 0;
+ }
+@@ -400,13 +400,13 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
+ 	 * JeanII */
+ 	if((stsap_sel != LSAP_ANY) &&
+ 	   ((stsap_sel < 0x01) || (stsap_sel >= 0x70))) {
+-		IRDA_DEBUG(0, "%s(), invalid tsap!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), invalid tsap!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+ 	self = kzalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+ 	if (self == NULL) {
+-		IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -438,7 +438,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
+ 	 */
+ 	lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
+ 	if (lsap == NULL) {
+-		IRDA_WARNING("%s: unable to allocate LSAP!!\n", __FUNCTION__);
++		IRDA_WARNING("%s: unable to allocate LSAP!!\n", __func__);
+ 		return NULL;
+ 	}
+ 
+@@ -448,7 +448,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
+ 	 *  the stsap_sel we have might not be valid anymore
+ 	 */
+ 	self->stsap_sel = lsap->slsap_sel;
+-	IRDA_DEBUG(4, "%s(), stsap_sel=%02x\n", __FUNCTION__, self->stsap_sel);
++	IRDA_DEBUG(4, "%s(), stsap_sel=%02x\n", __func__, self->stsap_sel);
+ 
+ 	self->notify = *notify;
+ 	self->lsap = lsap;
+@@ -506,7 +506,7 @@ int irttp_close_tsap(struct tsap_cb *self)
+ {
+ 	struct tsap_cb *tsap;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+@@ -516,7 +516,7 @@ int irttp_close_tsap(struct tsap_cb *self)
+ 		/* Check if disconnect is not pending */
+ 		if (!test_bit(0, &self->disconnect_pend)) {
+ 			IRDA_WARNING("%s: TSAP still connected!\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			irttp_disconnect_request(self, NULL, P_NORMAL);
+ 		}
+ 		self->close_pend = TRUE;
+@@ -553,18 +553,18 @@ int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb)
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ 	IRDA_ASSERT(skb != NULL, return -1;);
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	/* Check that nothing bad happens */
+ 	if ((skb->len == 0) || (!self->connected)) {
+ 		IRDA_DEBUG(1, "%s(), No data, or not connected\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		goto err;
+ 	}
+ 
+ 	if (skb->len > self->max_seg_size) {
+ 		IRDA_DEBUG(1, "%s(), UData is too large for IrLAP!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		goto err;
+ 	}
+ 
+@@ -595,12 +595,12 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ 	IRDA_ASSERT(skb != NULL, return -1;);
+ 
+-	IRDA_DEBUG(2, "%s() : queue len = %d\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s() : queue len = %d\n", __func__,
+ 		   skb_queue_len(&self->tx_queue));
+ 
+ 	/* Check that nothing bad happens */
+ 	if ((skb->len == 0) || (!self->connected)) {
+-		IRDA_WARNING("%s: No data, or not connected\n", __FUNCTION__);
++		IRDA_WARNING("%s: No data, or not connected\n", __func__);
+ 		ret = -ENOTCONN;
+ 		goto err;
+ 	}
+@@ -611,7 +611,7 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
+ 	 */
+ 	if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
+ 		IRDA_ERROR("%s: SAR disabled, and data is too large for IrLAP!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		ret = -EMSGSIZE;
+ 		goto err;
+ 	}
+@@ -625,7 +625,7 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
+ 	    (skb->len > self->tx_max_sdu_size))
+ 	{
+ 		IRDA_ERROR("%s: SAR enabled, but data is larger than TxMaxSduSize!\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		ret = -EMSGSIZE;
+ 		goto err;
+ 	}
+@@ -704,7 +704,7 @@ static void irttp_run_tx_queue(struct tsap_cb *self)
+ 	int n;
+ 
+ 	IRDA_DEBUG(2, "%s() : send_credit = %d, queue_len = %d\n",
+-		   __FUNCTION__,
++		   __func__,
+ 		   self->send_credit, skb_queue_len(&self->tx_queue));
+ 
+ 	/* Get exclusive access to the tx queue, otherwise don't touch it */
+@@ -813,7 +813,7 @@ static inline void irttp_give_credit(struct tsap_cb *self)
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ 
+ 	IRDA_DEBUG(4, "%s() send=%d,avail=%d,remote=%d\n",
+-		   __FUNCTION__,
++		   __func__,
+ 		   self->send_credit, self->avail_credit, self->remote_credit);
+ 
+ 	/* Give credit to peer */
+@@ -862,7 +862,7 @@ static int irttp_udata_indication(void *instance, void *sap,
+ 	struct tsap_cb *self;
+ 	int err;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	self = (struct tsap_cb *) instance;
+ 
+@@ -979,7 +979,7 @@ static void irttp_status_indication(void *instance,
+ {
+ 	struct tsap_cb *self;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	self = (struct tsap_cb *) instance;
+ 
+@@ -997,7 +997,7 @@ static void irttp_status_indication(void *instance,
+ 		self->notify.status_indication(self->notify.instance,
+ 					       link, lock);
+ 	else
+-		IRDA_DEBUG(2, "%s(), no handler\n", __FUNCTION__);
++		IRDA_DEBUG(2, "%s(), no handler\n", __func__);
+ }
+ 
+ /*
+@@ -1015,7 +1015,7 @@ static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ 
+-	IRDA_DEBUG(4, "%s(instance=%p)\n", __FUNCTION__, self);
++	IRDA_DEBUG(4, "%s(instance=%p)\n", __func__, self);
+ 
+ 	/* We are "polled" directly from LAP, and the LAP want to fill
+ 	 * its Tx window. We want to do our best to send it data, so that
+@@ -1053,18 +1053,18 @@ static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+  */
+ void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
+ {
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 
+ 	IRDA_ASSERT(self != NULL, return;);
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ 
+ 	switch (flow) {
+ 	case FLOW_STOP:
+-		IRDA_DEBUG(1, "%s(), flow stop\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), flow stop\n", __func__);
+ 		self->rx_sdu_busy = TRUE;
+ 		break;
+ 	case FLOW_START:
+-		IRDA_DEBUG(1, "%s(), flow start\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), flow start\n", __func__);
+ 		self->rx_sdu_busy = FALSE;
+ 
+ 		/* Client say he can accept more data, try to free our
+@@ -1073,7 +1073,7 @@ void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
+ 
+ 		break;
+ 	default:
+-		IRDA_DEBUG(1, "%s(), Unknown flow command!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), Unknown flow command!\n", __func__);
+ 	}
+ }
+ EXPORT_SYMBOL(irttp_flow_request);
+@@ -1093,7 +1093,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
+ 	__u8 *frame;
+ 	__u8 n;
+ 
+-	IRDA_DEBUG(4, "%s(), max_sdu_size=%d\n", __FUNCTION__, max_sdu_size);
++	IRDA_DEBUG(4, "%s(), max_sdu_size=%d\n", __func__, max_sdu_size);
+ 
+ 	IRDA_ASSERT(self != NULL, return -EBADR;);
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
+@@ -1191,7 +1191,7 @@ static void irttp_connect_confirm(void *instance, void *sap,
+ 	__u8 plen;
+ 	__u8 n;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	self = (struct tsap_cb *) instance;
+ 
+@@ -1215,7 +1215,7 @@ static void irttp_connect_confirm(void *instance, void *sap,
+ 
+ 	n = skb->data[0] & 0x7f;
+ 
+-	IRDA_DEBUG(4, "%s(), Initial send_credit=%d\n", __FUNCTION__, n);
++	IRDA_DEBUG(4, "%s(), Initial send_credit=%d\n", __func__, n);
+ 
+ 	self->send_credit = n;
+ 	self->tx_max_sdu_size = 0;
+@@ -1236,7 +1236,7 @@ static void irttp_connect_confirm(void *instance, void *sap,
+ 		/* Any errors in the parameter list? */
+ 		if (ret < 0) {
+ 			IRDA_WARNING("%s: error extracting parameters\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			dev_kfree_skb(skb);
+ 
+ 			/* Do not accept this connection attempt */
+@@ -1246,10 +1246,10 @@ static void irttp_connect_confirm(void *instance, void *sap,
+ 		skb_pull(skb, IRDA_MIN(skb->len, plen+1));
+ 	}
+ 
+-	IRDA_DEBUG(4, "%s() send=%d,avail=%d,remote=%d\n", __FUNCTION__,
++	IRDA_DEBUG(4, "%s() send=%d,avail=%d,remote=%d\n", __func__,
+ 	      self->send_credit, self->avail_credit, self->remote_credit);
+ 
+-	IRDA_DEBUG(2, "%s(), MaxSduSize=%d\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s(), MaxSduSize=%d\n", __func__,
+ 		   self->tx_max_sdu_size);
+ 
+ 	if (self->notify.connect_confirm) {
+@@ -1288,7 +1288,7 @@ void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
+ 	self->max_seg_size = max_seg_size - TTP_HEADER;
+ 	self->max_header_size = max_header_size+TTP_HEADER;
+ 
+-	IRDA_DEBUG(4, "%s(), TSAP sel=%02x\n", __FUNCTION__, self->stsap_sel);
++	IRDA_DEBUG(4, "%s(), TSAP sel=%02x\n", __func__, self->stsap_sel);
+ 
+ 	/* Need to update dtsap_sel if its equal to LSAP_ANY */
+ 	self->dtsap_sel = lsap->dlsap_sel;
+@@ -1313,7 +1313,7 @@ void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
+ 		/* Any errors in the parameter list? */
+ 		if (ret < 0) {
+ 			IRDA_WARNING("%s: error extracting parameters\n",
+-				     __FUNCTION__);
++				     __func__);
+ 			dev_kfree_skb(skb);
+ 
+ 			/* Do not accept this connection attempt */
+@@ -1350,7 +1350,7 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
+ 	IRDA_ASSERT(self != NULL, return -1;);
+ 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ 
+-	IRDA_DEBUG(4, "%s(), Source TSAP selector=%02x\n", __FUNCTION__,
++	IRDA_DEBUG(4, "%s(), Source TSAP selector=%02x\n", __func__,
+ 		   self->stsap_sel);
+ 
+ 	/* Any userdata supplied? */
+@@ -1432,14 +1432,14 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
+ 	struct tsap_cb *new;
+ 	unsigned long flags;
+ 
+-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s()\n", __func__);
+ 
+ 	/* Protect our access to the old tsap instance */
+ 	spin_lock_irqsave(&irttp->tsaps->hb_spinlock, flags);
+ 
+ 	/* Find the old instance */
+ 	if (!hashbin_find(irttp->tsaps, (long) orig, NULL)) {
+-		IRDA_DEBUG(0, "%s(), unable to find TSAP\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), unable to find TSAP\n", __func__);
+ 		spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
+ 		return NULL;
+ 	}
+@@ -1447,7 +1447,7 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
+ 	/* Allocate a new instance */
+ 	new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+ 	if (!new) {
+-		IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __func__);
+ 		spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
+ 		return NULL;
+ 	}
+@@ -1460,7 +1460,7 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
+ 	/* Try to dup the LSAP (may fail if we were too slow) */
+ 	new->lsap = irlmp_dup(orig->lsap, new);
+ 	if (!new->lsap) {
+-		IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
+ 		kfree(new);
+ 		return NULL;
+ 	}
+@@ -1495,7 +1495,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+ 
+ 	/* Already disconnected? */
+ 	if (!self->connected) {
+-		IRDA_DEBUG(4, "%s(), already disconnected!\n", __FUNCTION__);
++		IRDA_DEBUG(4, "%s(), already disconnected!\n", __func__);
+ 		if (userdata)
+ 			dev_kfree_skb(userdata);
+ 		return -1;
+@@ -1508,7 +1508,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+ 	 * Jean II */
+ 	if(test_and_set_bit(0, &self->disconnect_pend)) {
+ 		IRDA_DEBUG(0, "%s(), disconnect already pending\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		if (userdata)
+ 			dev_kfree_skb(userdata);
+ 
+@@ -1527,7 +1527,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+ 			 *  disconnecting right now since the data will
+ 			 *  not have any usable connection to be sent on
+ 			 */
+-			IRDA_DEBUG(1, "%s(): High priority!!()\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(): High priority!!()\n", __func__);
+ 			irttp_flush_queues(self);
+ 		} else if (priority == P_NORMAL) {
+ 			/*
+@@ -1548,7 +1548,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+ 	 * be sent at the LMP level (so even if the peer has its Tx queue
+ 	 * full of data). - Jean II */
+ 
+-	IRDA_DEBUG(1, "%s(), Disconnecting ...\n", __FUNCTION__);
++	IRDA_DEBUG(1, "%s(), Disconnecting ...\n", __func__);
+ 	self->connected = FALSE;
+ 
+ 	if (!userdata) {
+@@ -1584,7 +1584,7 @@ void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason,
+ {
+ 	struct tsap_cb *self;
+ 
+-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(4, "%s()\n", __func__);
+ 
+ 	self = (struct tsap_cb *) instance;
+ 
+@@ -1644,7 +1644,7 @@ static void irttp_do_data_indication(struct tsap_cb *self, struct sk_buff *skb)
+ 	 * give an error back
+ 	 */
+ 	if (err) {
+-		IRDA_DEBUG(0, "%s() requeueing skb!\n", __FUNCTION__);
++		IRDA_DEBUG(0, "%s() requeueing skb!\n", __func__);
+ 
+ 		/* Make sure we take a break */
+ 		self->rx_sdu_busy = TRUE;
+@@ -1669,7 +1669,7 @@ void irttp_run_rx_queue(struct tsap_cb *self)
+ 	struct sk_buff *skb;
+ 	int more = 0;
+ 
+-	IRDA_DEBUG(2, "%s() send=%d,avail=%d,remote=%d\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s() send=%d,avail=%d,remote=%d\n", __func__,
+ 		   self->send_credit, self->avail_credit, self->remote_credit);
+ 
+ 	/* Get exclusive access to the rx queue, otherwise don't touch it */
+@@ -1710,7 +1710,7 @@ void irttp_run_rx_queue(struct tsap_cb *self)
+ 			 */
+ 			if (self->rx_sdu_size <= self->rx_max_sdu_size) {
+ 				IRDA_DEBUG(4, "%s(), queueing frag\n",
+-					   __FUNCTION__);
++					   __func__);
+ 				skb_queue_tail(&self->rx_fragments, skb);
+ 			} else {
+ 				/* Free the part of the SDU that is too big */
+@@ -1740,7 +1740,7 @@ void irttp_run_rx_queue(struct tsap_cb *self)
+ 			/* Now we can deliver the reassembled skb */
+ 			irttp_do_data_indication(self, skb);
+ 		} else {
+-			IRDA_DEBUG(1, "%s(), Truncated frame\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), Truncated frame\n", __func__);
+ 
+ 			/* Free the part of the SDU that is too big */
+ 			dev_kfree_skb(skb);
+diff --git a/net/irda/parameters.c b/net/irda/parameters.c
+index 722bbe0..fc1a205 100644
+--- a/net/irda/parameters.c
++++ b/net/irda/parameters.c
+@@ -148,23 +148,23 @@ static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi,
+ 	 */
+ 	if (p.pl == 0) {
+ 		if (p.pv.i < 0xff) {
+-			IRDA_DEBUG(2, "%s(), using 1 byte\n", __FUNCTION__);
++			IRDA_DEBUG(2, "%s(), using 1 byte\n", __func__);
+ 			p.pl = 1;
+ 		} else if (p.pv.i < 0xffff) {
+-			IRDA_DEBUG(2, "%s(), using 2 bytes\n", __FUNCTION__);
++			IRDA_DEBUG(2, "%s(), using 2 bytes\n", __func__);
+ 			p.pl = 2;
+ 		} else {
+-			IRDA_DEBUG(2, "%s(), using 4 bytes\n", __FUNCTION__);
++			IRDA_DEBUG(2, "%s(), using 4 bytes\n", __func__);
+ 			p.pl = 4; /* Default length */
+ 		}
+ 	}
+ 	/* Check if buffer is long enough for insertion */
+ 	if (len < (2+p.pl)) {
+ 		IRDA_WARNING("%s: buffer too short for insertion!\n",
+-			     __FUNCTION__);
++			     __func__);
+ 		return -1;
+ 	}
+-	IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d, pi=%d\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d, pi=%d\n", __func__,
+ 		   p.pi, p.pl, p.pv.i);
+ 	switch (p.pl) {
+ 	case 1:
+@@ -187,7 +187,7 @@ static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi,
+ 		break;
+ 	default:
+ 		IRDA_WARNING("%s: length %d not supported\n",
+-			     __FUNCTION__, p.pl);
++			     __func__, p.pl);
+ 		/* Skip parameter */
+ 		return -1;
+ 	}
+@@ -218,7 +218,7 @@ static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
+ 	if (len < (2+p.pl)) {
+ 		IRDA_WARNING("%s: buffer too short for parsing! "
+ 			     "Need %d bytes, but len is only %d\n",
+-			     __FUNCTION__, p.pl, len);
++			     __func__, p.pl, len);
+ 		return -1;
+ 	}
+ 
+@@ -230,7 +230,7 @@ static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
+ 	if (((type & PV_MASK) != PV_INTEGER) && ((type & PV_MASK) != p.pl)) {
+ 		IRDA_ERROR("%s: invalid parameter length! "
+ 			   "Expected %d bytes, but value had %d bytes!\n",
+-			   __FUNCTION__, type & PV_MASK, p.pl);
++			   __func__, type & PV_MASK, p.pl);
+ 
+ 		/* Most parameters are bit/byte fields or little endian,
+ 		 * so it's ok to only extract a subset of it (the subset
+@@ -268,13 +268,13 @@ static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
+ 		break;
+ 	default:
+ 		IRDA_WARNING("%s: length %d not supported\n",
+-			     __FUNCTION__, p.pl);
++			     __func__, p.pl);
+ 
+ 		/* Skip parameter */
+ 		return p.pl+2;
+ 	}
+ 
+-	IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d, pi=%d\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d, pi=%d\n", __func__,
+ 		   p.pi, p.pl, p.pv.i);
+ 	/* Call handler for this parameter */
+ 	err = (*func)(self, &p, PV_PUT);
+@@ -294,19 +294,19 @@ static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi,
+ 	irda_param_t p;
+ 	int err;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	p.pi = pi;     /* In case handler needs to know */
+ 	p.pl = buf[1]; /* Extract length of value */
+ 
+-	IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d\n", __func__,
+ 		   p.pi, p.pl);
+ 
+ 	/* Check if buffer is long enough for parsing */
+ 	if (len < (2+p.pl)) {
+ 		IRDA_WARNING("%s: buffer too short for parsing! "
+ 			     "Need %d bytes, but len is only %d\n",
+-			     __FUNCTION__, p.pl, len);
++			     __func__, p.pl, len);
+ 		return -1;
+ 	}
+ 
+@@ -314,7 +314,7 @@ static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi,
+ 	 * checked that the buffer is long enough */
+ 	strncpy(str, buf+2, p.pl);
+ 
+-	IRDA_DEBUG(2, "%s(), str=0x%02x 0x%02x\n", __FUNCTION__,
++	IRDA_DEBUG(2, "%s(), str=0x%02x 0x%02x\n", __func__,
+ 		   (__u8) str[0], (__u8) str[1]);
+ 
+ 	/* Null terminate string */
+@@ -345,11 +345,11 @@ static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi,
+ 	if (len < (2+p.pl)) {
+ 		IRDA_WARNING("%s: buffer too short for parsing! "
+ 			     "Need %d bytes, but len is only %d\n",
+-			     __FUNCTION__, p.pl, len);
++			     __func__, p.pl, len);
+ 		return -1;
+ 	}
+ 
+-	IRDA_DEBUG(0, "%s(), not impl\n", __FUNCTION__);
++	IRDA_DEBUG(0, "%s(), not impl\n", __func__);
+ 
+ 	return p.pl+2; /* Extracted pl+2 bytes */
+ }
+@@ -473,7 +473,7 @@ int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len,
+ 	    (pi_minor > info->tables[pi_major].len-1))
+ 	{
+ 		IRDA_DEBUG(0, "%s(), no handler for parameter=0x%02x\n",
+-			   __FUNCTION__, pi);
++			   __func__, pi);
+ 
+ 		/* Skip this parameter */
+ 		return -1;
+@@ -487,7 +487,7 @@ int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len,
+ 
+ 	/*  Check if handler has been implemented */
+ 	if (!pi_minor_info->func) {
+-		IRDA_MESSAGE("%s: no handler for pi=%#x\n", __FUNCTION__, pi);
++		IRDA_MESSAGE("%s: no handler for pi=%#x\n", __func__, pi);
+ 		/* Skip this parameter */
+ 		return -1;
+ 	}
+@@ -527,7 +527,7 @@ static int irda_param_extract(void *self, __u8 *buf, int len,
+ 	    (pi_minor > info->tables[pi_major].len-1))
+ 	{
+ 		IRDA_DEBUG(0, "%s(), no handler for parameter=0x%02x\n",
+-			   __FUNCTION__, buf[0]);
++			   __func__, buf[0]);
+ 
+ 		/* Skip this parameter */
+ 		return 2 + buf[n + 1];  /* Continue */
+@@ -539,13 +539,13 @@ static int irda_param_extract(void *self, __u8 *buf, int len,
+ 	/* Find expected data type for this parameter identifier (pi)*/
+ 	type = pi_minor_info->type;
+ 
+-	IRDA_DEBUG(3, "%s(), pi=[%d,%d], type=%d\n", __FUNCTION__,
++	IRDA_DEBUG(3, "%s(), pi=[%d,%d], type=%d\n", __func__,
+ 		   pi_major, pi_minor, type);
+ 
+ 	/*  Check if handler has been implemented */
+ 	if (!pi_minor_info->func) {
+ 		IRDA_MESSAGE("%s: no handler for pi=%#x\n",
+-			     __FUNCTION__, buf[n]);
++			     __func__, buf[n]);
+ 		/* Skip this parameter */
+ 		return 2 + buf[n + 1]; /* Continue */
+ 	}
+diff --git a/net/irda/qos.c b/net/irda/qos.c
+index aeb18cf..2b00974 100644
+--- a/net/irda/qos.c
++++ b/net/irda/qos.c
+@@ -201,7 +201,7 @@ static int msb_index (__u16 word)
+ 	 * it's very likely the peer. - Jean II */
+ 	if (word == 0) {
+ 		IRDA_WARNING("%s(), Detected buggy peer, adjust null PV to 0x1!\n",
+-			 __FUNCTION__);
++			 __func__);
+ 		/* The only safe choice (we don't know the array size) */
+ 		word = 0x1;
+ 	}
+@@ -342,7 +342,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ 	__u32 line_capacity;
+ 	int index;
+ 
+-	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++	IRDA_DEBUG(2, "%s()\n", __func__);
+ 
+ 	/*
+ 	 * Make sure the mintt is sensible.
+@@ -352,7 +352,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ 		int i;
+ 
+ 		IRDA_WARNING("%s(), Detected buggy peer, adjust mtt to %dus!\n",
+-			 __FUNCTION__, sysctl_min_tx_turn_time);
++			 __func__, sysctl_min_tx_turn_time);
+ 
+ 		/* We don't really need bits, but easier this way */
+ 		i = value_highest_bit(sysctl_min_tx_turn_time, min_turn_times,
+@@ -370,7 +370,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ 	{
+ 		IRDA_DEBUG(0,
+ 			   "%s(), adjusting max turn time from %d to 500 ms\n",
+-			   __FUNCTION__, qos->max_turn_time.value);
++			   __func__, qos->max_turn_time.value);
+ 		qos->max_turn_time.value = 500;
+ 	}
+ 
+@@ -386,7 +386,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ 	while ((qos->data_size.value > line_capacity) && (index > 0)) {
+ 		qos->data_size.value = data_sizes[index--];
+ 		IRDA_DEBUG(2, "%s(), reducing data size to %d\n",
+-			   __FUNCTION__, qos->data_size.value);
++			   __func__, qos->data_size.value);
+ 	}
+ #else /* Use method described in section 6.6.11 of IrLAP */
+ 	while (irlap_requested_line_capacity(qos) > line_capacity) {
+@@ -396,14 +396,14 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ 		if (qos->window_size.value > 1) {
+ 			qos->window_size.value--;
+ 			IRDA_DEBUG(2, "%s(), reducing window size to %d\n",
+-				   __FUNCTION__, qos->window_size.value);
++				   __func__, qos->window_size.value);
+ 		} else if (index > 1) {
+ 			qos->data_size.value = data_sizes[index--];
+ 			IRDA_DEBUG(2, "%s(), reducing data size to %d\n",
+-				   __FUNCTION__, qos->data_size.value);
++				   __func__, qos->data_size.value);
+ 		} else {
+ 			IRDA_WARNING("%s(), nothing more we can do!\n",
+-				     __FUNCTION__);
++				     __func__);
+ 		}
+ 	}
+ #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
+@@ -538,7 +538,7 @@ static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get)
+ 	if (get) {
+ 		param->pv.i = self->qos_rx.baud_rate.bits;
+ 		IRDA_DEBUG(2, "%s(), baud rate = 0x%02x\n",
+-			   __FUNCTION__, param->pv.i);
++			   __func__, param->pv.i);
+ 	} else {
+ 		/*
+ 		 *  Stations must agree on baud rate, so calculate
+@@ -711,7 +711,7 @@ __u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
+ 	int i,j;
+ 
+ 	IRDA_DEBUG(2, "%s(), speed=%d, max_turn_time=%d\n",
+-		   __FUNCTION__, speed, max_turn_time);
++		   __func__, speed, max_turn_time);
+ 
+ 	i = value_index(speed, baud_rates, 10);
+ 	j = value_index(max_turn_time, max_turn_times, 4);
+@@ -722,7 +722,7 @@ __u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
+ 	line_capacity = max_line_capacities[i][j];
+ 
+ 	IRDA_DEBUG(2, "%s(), line capacity=%d bytes\n",
+-		   __FUNCTION__, line_capacity);
++		   __func__, line_capacity);
+ 
+ 	return line_capacity;
+ }
+@@ -738,7 +738,7 @@ static __u32 irlap_requested_line_capacity(struct qos_info *qos)
+ 					     qos->min_turn_time.value);
+ 
+ 	IRDA_DEBUG(2, "%s(), requested line capacity=%d\n",
+-		   __FUNCTION__, line_capacity);
++		   __func__, line_capacity);
+ 
+ 	return line_capacity;
+ }
+diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c
+index c246983..fd0995b 100644
+--- a/net/irda/wrapper.c
++++ b/net/irda/wrapper.c
+@@ -106,16 +106,16 @@ int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
+ 		 * Nothing to worry about, but we set the default number of
+ 		 * BOF's
+ 		 */
+-		IRDA_DEBUG(1, "%s(), wrong magic in skb!\n", __FUNCTION__);
++		IRDA_DEBUG(1, "%s(), wrong magic in skb!\n", __func__);
+ 		xbofs = 10;
+ 	} else
+ 		xbofs = cb->xbofs + cb->xbofs_delay;
+ 
+-	IRDA_DEBUG(4, "%s(), xbofs=%d\n", __FUNCTION__, xbofs);
++	IRDA_DEBUG(4, "%s(), xbofs=%d\n", __func__, xbofs);
+ 
+ 	/* Check that we never use more than 115 + 48 xbofs */
+ 	if (xbofs > 163) {
+-		IRDA_DEBUG(0, "%s(), too many xbofs (%d)\n", __FUNCTION__,
++		IRDA_DEBUG(0, "%s(), too many xbofs (%d)\n", __func__,
+ 			   xbofs);
+ 		xbofs = 163;
+ 	}
+@@ -135,7 +135,7 @@ int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
+ 		 */
+ 		if(n >= (buffsize-5)) {
+ 			IRDA_ERROR("%s(), tx buffer overflow (n=%d)\n",
+-				   __FUNCTION__, n);
++				   __func__, n);
+ 			return n;
+ 		}
+ 
+@@ -287,7 +287,7 @@ async_unwrap_bof(struct net_device *dev,
+ 		/* Not supposed to happen, the previous frame is not
+ 		 * finished - Jean II */
+ 		IRDA_DEBUG(1, "%s(), Discarding incomplete frame\n",
+-			   __FUNCTION__);
++			   __func__);
+ 		stats->rx_errors++;
+ 		stats->rx_missed_errors++;
+ 		irda_device_set_media_busy(dev, TRUE);
+@@ -360,7 +360,7 @@ async_unwrap_eof(struct net_device *dev,
+ 			/* Wrong CRC, discard frame!  */
+ 			irda_device_set_media_busy(dev, TRUE);
+ 
+-			IRDA_DEBUG(1, "%s(), crc error\n", __FUNCTION__);
++			IRDA_DEBUG(1, "%s(), crc error\n", __func__);
+ 			stats->rx_errors++;
+ 			stats->rx_crc_errors++;
+ 		}
+@@ -386,7 +386,7 @@ async_unwrap_ce(struct net_device *dev,
+ 		break;
+ 
+ 	case LINK_ESCAPE:
+-		IRDA_WARNING("%s: state not defined\n", __FUNCTION__);
++		IRDA_WARNING("%s: state not defined\n", __func__);
+ 		break;
+ 
+ 	case BEGIN_FRAME:
+@@ -421,7 +421,7 @@ async_unwrap_other(struct net_device *dev,
+ #endif
+ 		} else {
+ 			IRDA_DEBUG(1, "%s(), Rx buffer overflow, aborting\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			rx_buff->state = OUTSIDE_FRAME;
+ 		}
+ 		break;
+@@ -440,7 +440,7 @@ async_unwrap_other(struct net_device *dev,
+ 			rx_buff->state = INSIDE_FRAME;
+ 		} else {
+ 			IRDA_DEBUG(1, "%s(), Rx buffer overflow, aborting\n",
+-				   __FUNCTION__);
++				   __func__);
+ 			rx_buff->state = OUTSIDE_FRAME;
+ 		}
+ 		break;
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index fee22ca..7b0038f 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -53,7 +53,7 @@ static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8],
+ static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
+ 
+ static struct iucv_sock_list iucv_sk_list = {
+-	.lock = RW_LOCK_UNLOCKED,
++	.lock = __RW_LOCK_UNLOCKED(iucv_sk_list.lock),
+ 	.autobind_name = ATOMIC_INIT(0)
+ };
+ 
+diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
+index d764f4c..9189707 100644
+--- a/net/iucv/iucv.c
++++ b/net/iucv/iucv.c
+@@ -795,7 +795,6 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
+ 	union iucv_param *parm;
+ 	int rc;
+ 
+-	BUG_ON(in_atomic());
+ 	spin_lock_bh(&iucv_table_lock);
+ 	iucv_cleanup_queue();
+ 	parm = iucv_param[smp_processor_id()];
+@@ -1609,13 +1608,10 @@ static int __init iucv_init(void)
+ 	rc = register_external_interrupt(0x4000, iucv_external_interrupt);
+ 	if (rc)
+ 		goto out;
+-	rc = bus_register(&iucv_bus);
+-	if (rc)
+-		goto out_int;
+ 	iucv_root = s390_root_dev_register("iucv");
+ 	if (IS_ERR(iucv_root)) {
+ 		rc = PTR_ERR(iucv_root);
+-		goto out_bus;
++		goto out_int;
+ 	}
+ 
+ 	for_each_online_cpu(cpu) {
+@@ -1635,13 +1631,20 @@ static int __init iucv_init(void)
+ 			goto out_free;
+ 		}
+ 	}
+-	register_hotcpu_notifier(&iucv_cpu_notifier);
++	rc = register_hotcpu_notifier(&iucv_cpu_notifier);
++	if (rc)
++		goto out_free;
+ 	ASCEBC(iucv_error_no_listener, 16);
+ 	ASCEBC(iucv_error_no_memory, 16);
+ 	ASCEBC(iucv_error_pathid, 16);
+ 	iucv_available = 1;
++	rc = bus_register(&iucv_bus);
++	if (rc)
++		goto out_cpu;
+ 	return 0;
+ 
++out_cpu:
++	unregister_hotcpu_notifier(&iucv_cpu_notifier);
+ out_free:
+ 	for_each_possible_cpu(cpu) {
+ 		kfree(iucv_param[cpu]);
+@@ -1650,8 +1653,6 @@ out_free:
+ 		iucv_irq_data[cpu] = NULL;
+ 	}
+ 	s390_root_dev_unregister(iucv_root);
+-out_bus:
+-	bus_unregister(&iucv_bus);
+ out_int:
+ 	unregister_external_interrupt(0x4000, iucv_external_interrupt);
+ out:
+diff --git a/net/key/af_key.c b/net/key/af_key.c
+index e9ef9af..2403a31 100644
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -48,6 +48,17 @@ struct pfkey_sock {
+ 	struct sock	sk;
+ 	int		registered;
+ 	int		promisc;
++
++	struct {
++		uint8_t		msg_version;
++		uint32_t	msg_pid;
++		int		(*dump)(struct pfkey_sock *sk);
++		void		(*done)(struct pfkey_sock *sk);
++		union {
++			struct xfrm_policy_walk	policy;
++			struct xfrm_state_walk	state;
++		} u;
++	} dump;
+ };
+ 
+ static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
+@@ -55,6 +66,27 @@ static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
+ 	return (struct pfkey_sock *)sk;
+ }
+ 
++static int pfkey_can_dump(struct sock *sk)
++{
++	if (3 * atomic_read(&sk->sk_rmem_alloc) <= 2 * sk->sk_rcvbuf)
++		return 1;
++	return 0;
++}
++
++static int pfkey_do_dump(struct pfkey_sock *pfk)
++{
++	int rc;
++
++	rc = pfk->dump.dump(pfk);
++	if (rc == -ENOBUFS)
++		return 0;
++
++	pfk->dump.done(pfk);
++	pfk->dump.dump = NULL;
++	pfk->dump.done = NULL;
++	return rc;
++}
++
+ static void pfkey_sock_destruct(struct sock *sk)
+ {
+ 	skb_queue_purge(&sk->sk_receive_queue);
+@@ -1709,45 +1741,60 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
+ 	return 0;
+ }
+ 
+-struct pfkey_dump_data
+-{
+-	struct sk_buff *skb;
+-	struct sadb_msg *hdr;
+-	struct sock *sk;
+-};
+-
+ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
+ {
+-	struct pfkey_dump_data *data = ptr;
++	struct pfkey_sock *pfk = ptr;
+ 	struct sk_buff *out_skb;
+ 	struct sadb_msg *out_hdr;
+ 
++	if (!pfkey_can_dump(&pfk->sk))
++		return -ENOBUFS;
++
+ 	out_skb = pfkey_xfrm_state2msg(x);
+ 	if (IS_ERR(out_skb))
+ 		return PTR_ERR(out_skb);
+ 
+ 	out_hdr = (struct sadb_msg *) out_skb->data;
+-	out_hdr->sadb_msg_version = data->hdr->sadb_msg_version;
++	out_hdr->sadb_msg_version = pfk->dump.msg_version;
+ 	out_hdr->sadb_msg_type = SADB_DUMP;
+ 	out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
+ 	out_hdr->sadb_msg_errno = 0;
+ 	out_hdr->sadb_msg_reserved = 0;
+ 	out_hdr->sadb_msg_seq = count;
+-	out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid;
+-	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk);
++	out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
++	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
+ 	return 0;
+ }
+ 
++static int pfkey_dump_sa(struct pfkey_sock *pfk)
++{
++	return xfrm_state_walk(&pfk->dump.u.state, dump_sa, (void *) pfk);
++}
++
++static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
++{
++	xfrm_state_walk_done(&pfk->dump.u.state);
++}
++
+ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+ {
+ 	u8 proto;
+-	struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk };
++	struct pfkey_sock *pfk = pfkey_sk(sk);
++
++	if (pfk->dump.dump != NULL)
++		return -EBUSY;
+ 
+ 	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
+ 	if (proto == 0)
+ 		return -EINVAL;
+ 
+-	return xfrm_state_walk(proto, dump_sa, &data);
++	pfk->dump.msg_version = hdr->sadb_msg_version;
++	pfk->dump.msg_pid = hdr->sadb_msg_pid;
++	pfk->dump.dump = pfkey_dump_sa;
++	pfk->dump.done = pfkey_dump_sa_done;
++	xfrm_state_walk_init(&pfk->dump.u.state, proto);
++
++	return pfkey_do_dump(pfk);
+ }
+ 
+ static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+@@ -1780,7 +1827,9 @@ static int check_reqid(struct xfrm_policy *xp, int dir, int count, void *ptr)
+ 
+ static u32 gen_reqid(void)
+ {
++	struct xfrm_policy_walk walk;
+ 	u32 start;
++	int rc;
+ 	static u32 reqid = IPSEC_MANUAL_REQID_MAX;
+ 
+ 	start = reqid;
+@@ -1788,8 +1837,10 @@ static u32 gen_reqid(void)
+ 		++reqid;
+ 		if (reqid == 0)
+ 			reqid = IPSEC_MANUAL_REQID_MAX+1;
+-		if (xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, check_reqid,
+-				     (void*)&reqid) != -EEXIST)
++		xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN);
++		rc = xfrm_policy_walk(&walk, check_reqid, (void*)&reqid);
++		xfrm_policy_walk_done(&walk);
++		if (rc != -EEXIST)
+ 			return reqid;
+ 	} while (reqid != start);
+ 	return 0;
+@@ -1856,7 +1907,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
+ 		t->encap_family = xp->family;
+ 
+ 	/* No way to set this via kame pfkey */
+-	t->aalgos = t->ealgos = t->calgos = ~0;
++	t->allalgs = 1;
+ 	xp->xfrm_nr++;
+ 	return 0;
+ }
+@@ -2241,7 +2292,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
+ 			goto out;
+ 		}
+ 
+-		err = security_xfrm_policy_alloc(xp, uctx);
++		err = security_xfrm_policy_alloc(&xp->security, uctx);
+ 		kfree(uctx);
+ 
+ 		if (err)
+@@ -2301,10 +2352,11 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
+ 	int err;
+ 	struct sadb_address *sa;
+ 	struct sadb_x_policy *pol;
+-	struct xfrm_policy *xp, tmp;
++	struct xfrm_policy *xp;
+ 	struct xfrm_selector sel;
+ 	struct km_event c;
+ 	struct sadb_x_sec_ctx *sec_ctx;
++	struct xfrm_sec_ctx *pol_ctx = NULL;
+ 
+ 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
+ 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
+@@ -2334,25 +2386,22 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
+ 		sel.dport_mask = htons(0xffff);
+ 
+ 	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+-	memset(&tmp, 0, sizeof(struct xfrm_policy));
+-
+ 	if (sec_ctx != NULL) {
+ 		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+ 
+ 		if (!uctx)
+ 			return -ENOMEM;
+ 
+-		err = security_xfrm_policy_alloc(&tmp, uctx);
++		err = security_xfrm_policy_alloc(&pol_ctx, uctx);
+ 		kfree(uctx);
+-
+ 		if (err)
+ 			return err;
+ 	}
+ 
+-	xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
+-				   &sel, tmp.security, 1, &err);
+-	security_xfrm_policy_free(&tmp);
+-
++	xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN,
++				   pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
++				   1, &err);
++	security_xfrm_policy_free(pol_ctx);
+ 	if (xp == NULL)
+ 		return -ENOENT;
+ 
+@@ -2638,11 +2687,14 @@ out:
+ 
+ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
+ {
+-	struct pfkey_dump_data *data = ptr;
++	struct pfkey_sock *pfk = ptr;
+ 	struct sk_buff *out_skb;
+ 	struct sadb_msg *out_hdr;
+ 	int err;
+ 
++	if (!pfkey_can_dump(&pfk->sk))
++		return -ENOBUFS;
++
+ 	out_skb = pfkey_xfrm_policy2msg_prep(xp);
+ 	if (IS_ERR(out_skb))
+ 		return PTR_ERR(out_skb);
+@@ -2652,21 +2704,40 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
+ 		return err;
+ 
+ 	out_hdr = (struct sadb_msg *) out_skb->data;
+-	out_hdr->sadb_msg_version = data->hdr->sadb_msg_version;
++	out_hdr->sadb_msg_version = pfk->dump.msg_version;
+ 	out_hdr->sadb_msg_type = SADB_X_SPDDUMP;
+ 	out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ 	out_hdr->sadb_msg_errno = 0;
+ 	out_hdr->sadb_msg_seq = count;
+-	out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid;
+-	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk);
++	out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
++	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
+ 	return 0;
+ }
+ 
++static int pfkey_dump_sp(struct pfkey_sock *pfk)
++{
++	return xfrm_policy_walk(&pfk->dump.u.policy, dump_sp, (void *) pfk);
++}
++
++static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
++{
++	xfrm_policy_walk_done(&pfk->dump.u.policy);
++}
++
+ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+ {
+-	struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk };
++	struct pfkey_sock *pfk = pfkey_sk(sk);
++
++	if (pfk->dump.dump != NULL)
++		return -EBUSY;
++
++	pfk->dump.msg_version = hdr->sadb_msg_version;
++	pfk->dump.msg_pid = hdr->sadb_msg_pid;
++	pfk->dump.dump = pfkey_dump_sp;
++	pfk->dump.done = pfkey_dump_sp_done;
++	xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN);
+ 
+-	return xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_sp, &data);
++	return pfkey_do_dump(pfk);
+ }
+ 
+ static int key_notify_policy_flush(struct km_event *c)
+@@ -3225,7 +3296,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
+ 		if ((*dir = verify_sec_ctx_len(p)))
+ 			goto out;
+ 		uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+-		*dir = security_xfrm_policy_alloc(xp, uctx);
++		*dir = security_xfrm_policy_alloc(&xp->security, uctx);
+ 		kfree(uctx);
+ 
+ 		if (*dir)
+@@ -3671,6 +3742,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
+ 			 int flags)
+ {
+ 	struct sock *sk = sock->sk;
++	struct pfkey_sock *pfk = pfkey_sk(sk);
+ 	struct sk_buff *skb;
+ 	int copied, err;
+ 
+@@ -3698,6 +3770,10 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
+ 
+ 	err = (flags & MSG_TRUNC) ? skb->len : copied;
+ 
++	if (pfk->dump.dump != NULL &&
++	    3 * atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf)
++		pfkey_do_dump(pfk);
++
+ out_free:
+ 	skb_free_datagram(sk, skb);
+ out:
+diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
+index 8c50eb4..97101dc 100644
+--- a/net/llc/af_llc.c
++++ b/net/llc/af_llc.c
+@@ -188,7 +188,7 @@ static int llc_ui_release(struct socket *sock)
+ 	sock_hold(sk);
+ 	lock_sock(sk);
+ 	llc = llc_sk(sk);
+-	dprintk("%s: closing local(%02X) remote(%02X)\n", __FUNCTION__,
++	dprintk("%s: closing local(%02X) remote(%02X)\n", __func__,
+ 		llc->laddr.lsap, llc->daddr.lsap);
+ 	if (!llc_send_disc(sk))
+ 		llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
+@@ -298,7 +298,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
+ 	struct llc_sap *sap;
+ 	int rc = -EINVAL;
+ 
+-	dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);
++	dprintk("%s: binding %02X\n", __func__, addr->sllc_sap);
+ 	if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))
+ 		goto out;
+ 	rc = -EAFNOSUPPORT;
+@@ -435,7 +435,7 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
+ 	rc = llc_establish_connection(sk, llc->dev->dev_addr,
+ 				      addr->sllc_mac, addr->sllc_sap);
+ 	if (rc) {
+-		dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__);
++		dprintk("%s: llc_ui_send_conn failed :-(\n", __func__);
+ 		sock->state  = SS_UNCONNECTED;
+ 		sk->sk_state = TCP_CLOSE;
+ 		goto out;
+@@ -607,7 +607,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
+ 	struct sk_buff *skb;
+ 	int rc = -EOPNOTSUPP;
+ 
+-	dprintk("%s: accepting on %02X\n", __FUNCTION__,
++	dprintk("%s: accepting on %02X\n", __func__,
+ 		llc_sk(sk)->laddr.lsap);
+ 	lock_sock(sk);
+ 	if (unlikely(sk->sk_type != SOCK_STREAM))
+@@ -622,7 +622,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
+ 		if (rc)
+ 			goto out;
+ 	}
+-	dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
++	dprintk("%s: got a new connection on %02X\n", __func__,
+ 		llc_sk(sk)->laddr.lsap);
+ 	skb = skb_dequeue(&sk->sk_receive_queue);
+ 	rc = -EINVAL;
+@@ -643,7 +643,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
+ 	/* put original socket back into a clean listen state. */
+ 	sk->sk_state = TCP_LISTEN;
+ 	sk->sk_ack_backlog--;
+-	dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,
++	dprintk("%s: ok success on %02X, client on %02X\n", __func__,
+ 		llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
+ frees:
+ 	kfree_skb(skb);
+@@ -836,7 +836,7 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
+ 	size_t size = 0;
+ 	int rc = -EINVAL, copied = 0, hdrlen;
+ 
+-	dprintk("%s: sending from %02X to %02X\n", __FUNCTION__,
++	dprintk("%s: sending from %02X to %02X\n", __func__,
+ 		llc->laddr.lsap, llc->daddr.lsap);
+ 	lock_sock(sk);
+ 	if (addr) {
+@@ -894,7 +894,7 @@ out:
+ 		kfree_skb(skb);
+ release:
+ 		dprintk("%s: failed sending from %02X to %02X: %d\n",
+-			__FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc);
++			__func__, llc->laddr.lsap, llc->daddr.lsap, rc);
+ 	}
+ 	release_sock(sk);
+ 	return rc ? : copied;
+diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c
+index 71a0022..019c780 100644
+--- a/net/llc/llc_c_ac.c
++++ b/net/llc/llc_c_ac.c
+@@ -1430,7 +1430,7 @@ static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb)
+ {
+ 	if (llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) {
+ 		printk(KERN_WARNING "%s: timer called on closed connection\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		kfree_skb(skb);
+ 	} else {
+ 		if (!sock_owned_by_user(sk))
+diff --git a/net/llc/llc_c_ev.c b/net/llc/llc_c_ev.c
+index c5deda2..523fdd1 100644
+--- a/net/llc/llc_c_ev.c
++++ b/net/llc/llc_c_ev.c
+@@ -228,7 +228,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
+ 		 llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
+ 	if (!rc)
+ 		dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
+-			__FUNCTION__, llc_sk(sk)->state, ns, vr);
++			__func__, llc_sk(sk)->state, ns, vr);
+ 	return rc;
+ }
+ 
+@@ -306,7 +306,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
+ 		 llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
+ 	if (!rc)
+ 		dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
+-			__FUNCTION__, llc_sk(sk)->state, ns, vr);
++			__func__, llc_sk(sk)->state, ns, vr);
+ 	return rc;
+ }
+ 
+@@ -511,7 +511,7 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
+ 	    (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
+ 	    nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
+ 		dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
+-			__FUNCTION__, llc_sk(sk)->state, vs, nr);
++			__func__, llc_sk(sk)->state, vs, nr);
+ 		rc = 0;
+ 	}
+ 	return rc;
+@@ -530,7 +530,7 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
+ 	    nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
+ 		rc = 0;
+ 		dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
+-			__FUNCTION__, llc_sk(sk)->state, vs, nr);
++			__func__, llc_sk(sk)->state, vs, nr);
+ 	}
+ 	return rc;
+ }
+diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
+index 441bc18..5c6d89c 100644
+--- a/net/llc/llc_conn.c
++++ b/net/llc/llc_conn.c
+@@ -73,7 +73,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
+ 	 */
+ 	rc = llc_conn_service(skb->sk, skb);
+ 	if (unlikely(rc != 0)) {
+-		printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);
++		printk(KERN_ERR "%s: llc_conn_service failed\n", __func__);
+ 		goto out_kfree_skb;
+ 	}
+ 
+@@ -99,7 +99,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
+ 			 * shouldn't happen
+ 			 */
+ 			printk(KERN_ERR "%s: sock_queue_rcv_skb failed!\n",
+-			       __FUNCTION__);
++			       __func__);
+ 			kfree_skb(skb);
+ 		}
+ 		break;
+@@ -132,13 +132,13 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
+ 		 * FIXME:
+ 		 * RESET is not being notified to upper layers for now
+ 		 */
+-		printk(KERN_INFO "%s: received a reset ind!\n", __FUNCTION__);
++		printk(KERN_INFO "%s: received a reset ind!\n", __func__);
+ 		kfree_skb(skb);
+ 		break;
+ 	default:
+ 		if (ev->ind_prim) {
+ 			printk(KERN_INFO "%s: received unknown %d prim!\n",
+-				__FUNCTION__, ev->ind_prim);
++				__func__, ev->ind_prim);
+ 			kfree_skb(skb);
+ 		}
+ 		/* No indication */
+@@ -179,12 +179,12 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
+ 		 * FIXME:
+ 		 * RESET is not being notified to upper layers for now
+ 		 */
+-		printk(KERN_INFO "%s: received a reset conf!\n", __FUNCTION__);
++		printk(KERN_INFO "%s: received a reset conf!\n", __func__);
+ 		break;
+ 	default:
+ 		if (ev->cfm_prim) {
+ 			printk(KERN_INFO "%s: received unknown %d prim!\n",
+-					__FUNCTION__, ev->cfm_prim);
++					__func__, ev->cfm_prim);
+ 			break;
+ 		}
+ 		goto out_skb_put; /* No confirmation */
+@@ -700,7 +700,7 @@ static struct sock *llc_create_incoming_sock(struct sock *sk,
+ 					     struct llc_addr *saddr,
+ 					     struct llc_addr *daddr)
+ {
+-	struct sock *newsk = llc_sk_alloc(sk->sk_net, sk->sk_family, GFP_ATOMIC,
++	struct sock *newsk = llc_sk_alloc(sock_net(sk), sk->sk_family, GFP_ATOMIC,
+ 					  sk->sk_prot);
+ 	struct llc_sock *newllc, *llc = llc_sk(sk);
+ 
+@@ -759,7 +759,7 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
+ 	if (!sock_owned_by_user(sk))
+ 		llc_conn_rcv(sk, skb);
+ 	else {
+-		dprintk("%s: adding to backlog...\n", __FUNCTION__);
++		dprintk("%s: adding to backlog...\n", __func__);
+ 		llc_set_backlog_type(skb, LLC_PACKET);
+ 		sk_add_backlog(sk, skb);
+ 	}
+@@ -807,7 +807,7 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
+ 		else
+ 			goto out_kfree_skb;
+ 	} else {
+-		printk(KERN_ERR "%s: invalid skb in backlog\n", __FUNCTION__);
++		printk(KERN_ERR "%s: invalid skb in backlog\n", __func__);
+ 		goto out_kfree_skb;
+ 	}
+ out:
+@@ -874,7 +874,7 @@ struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, struct pr
+ #ifdef LLC_REFCNT_DEBUG
+ 	atomic_inc(&llc_sock_nr);
+ 	printk(KERN_DEBUG "LLC socket %p created in %s, now we have %d alive\n", sk,
+-		__FUNCTION__, atomic_read(&llc_sock_nr));
++		__func__, atomic_read(&llc_sock_nr));
+ #endif
+ out:
+ 	return sk;
+@@ -894,7 +894,7 @@ void llc_sk_free(struct sock *sk)
+ 	/* Stop all (possibly) running timers */
+ 	llc_conn_ac_stop_all_timers(sk, NULL);
+ #ifdef DEBUG_LLC_CONN_ALLOC
+-	printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__,
++	printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __func__,
+ 		skb_queue_len(&llc->pdu_unack_q),
+ 		skb_queue_len(&sk->sk_write_queue));
+ #endif
+@@ -904,13 +904,13 @@ void llc_sk_free(struct sock *sk)
+ #ifdef LLC_REFCNT_DEBUG
+ 	if (atomic_read(&sk->sk_refcnt) != 1) {
+ 		printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n",
+-			sk, __FUNCTION__, atomic_read(&sk->sk_refcnt));
++			sk, __func__, atomic_read(&sk->sk_refcnt));
+ 		printk(KERN_DEBUG "%d LLC sockets are still alive\n",
+ 			atomic_read(&llc_sock_nr));
+ 	} else {
+ 		atomic_dec(&llc_sock_nr);
+ 		printk(KERN_DEBUG "LLC socket %p released in %s, %d are still alive\n", sk,
+-			__FUNCTION__, atomic_read(&llc_sock_nr));
++			__func__, atomic_read(&llc_sock_nr));
+ 	}
+ #endif
+ 	sock_put(sk);
+diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
+index bfd2567..1c45f17 100644
+--- a/net/llc/llc_input.c
++++ b/net/llc/llc_input.c
+@@ -150,7 +150,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	int (*rcv)(struct sk_buff *, struct net_device *,
+ 		   struct packet_type *, struct net_device *);
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto drop;
+ 
+ 	/*
+@@ -158,7 +158,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	 * receives, do not try to analyse it.
+ 	 */
+ 	if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
+-		dprintk("%s: PACKET_OTHERHOST\n", __FUNCTION__);
++		dprintk("%s: PACKET_OTHERHOST\n", __func__);
+ 		goto drop;
+ 	}
+ 	skb = skb_share_check(skb, GFP_ATOMIC);
+@@ -171,7 +171,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ 	       goto handle_station;
+ 	sap = llc_sap_find(pdu->dsap);
+ 	if (unlikely(!sap)) {/* unknown SAP */
+-		dprintk("%s: llc_sap_find(%02X) failed!\n", __FUNCTION__,
++		dprintk("%s: llc_sap_find(%02X) failed!\n", __func__,
+ 			pdu->dsap);
+ 		goto drop;
+ 	}
+diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
+index 45c7c0c..520a518 100644
+--- a/net/mac80211/Kconfig
++++ b/net/mac80211/Kconfig
+@@ -32,15 +32,6 @@ config MAC80211_RC_DEFAULT_PID
+ 	  default rate control algorithm. You should choose
+ 	  this unless you know what you are doing.
+ 
+-config MAC80211_RC_DEFAULT_SIMPLE
+-	bool "Simple rate control algorithm"
+-	select MAC80211_RC_SIMPLE
+-	---help---
+-	  Select the simple rate control as the default rate
+-	  control algorithm. Note that this is a non-responsive,
+-	  dumb algorithm. You should choose the PID rate control
+-	  instead.
+-
+ config MAC80211_RC_DEFAULT_NONE
+ 	bool "No default algorithm"
+ 	depends on EMBEDDED
+@@ -57,7 +48,6 @@ comment "build the algorithm into mac80211."
+ config MAC80211_RC_DEFAULT
+ 	string
+ 	default "pid" if MAC80211_RC_DEFAULT_PID
+-	default "simple" if MAC80211_RC_DEFAULT_SIMPLE
+ 	default ""
+ 
+ config MAC80211_RC_PID
+@@ -70,16 +60,16 @@ config MAC80211_RC_PID
+ 	  Say Y or M unless you're sure you want to use a
+ 	  different rate control algorithm.
+ 
+-config MAC80211_RC_SIMPLE
+-	tristate "Simple rate control algorithm (DEPRECATED)"
++endmenu
++
++config MAC80211_MESH
++	bool "Enable mac80211 mesh networking (pre-802.11s) support"
++	depends on MAC80211 && EXPERIMENTAL
+ 	---help---
+-	  This option enables a very simple, non-responsive TX
+-	  rate control algorithm. This algorithm is deprecated
+-	  and will be removed from the kernel in the near future.
+-	  It has been replaced by the PID algorithm.
++	 This options enables support of Draft 802.11s mesh networking.
++	 The implementation is based on Draft 1.08 of the Mesh Networking
++	 amendment. For more information visit http://o11s.org/.
+ 
+-	  Say N unless you know what you are doing.
+-endmenu
+ 
+ config MAC80211_LEDS
+ 	bool "Enable LED triggers"
+@@ -166,3 +156,10 @@ config MAC80211_VERBOSE_PS_DEBUG
+ 	---help---
+ 	  Say Y here to print out verbose powersave
+ 	  mode debug messages.
++
++config MAC80211_VERBOSE_MPL_DEBUG
++	bool "Verbose mesh peer link debugging"
++	depends on MAC80211_DEBUG && MAC80211_MESH
++	---help---
++	  Say Y here to print out verbose mesh peer link
++	  debug messages.
+diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
+index 54f46bc..4e5847f 100644
+--- a/net/mac80211/Makefile
++++ b/net/mac80211/Makefile
+@@ -10,16 +10,15 @@ rc-pid-m := rc80211_pid.o
+ 
+ # mac80211 objects
+ mac80211-y := \
+-	ieee80211.o \
+-	ieee80211_ioctl.o \
++	main.o \
++	wext.o \
+ 	sta_info.o \
+ 	wep.o \
+ 	wpa.o \
+-	ieee80211_sta.o \
+-	ieee80211_iface.o \
+-	ieee80211_rate.o \
++	mlme.o \
++	iface.o \
++	rate.o \
+ 	michael.o \
+-	regdomain.o \
+ 	tkip.o \
+ 	aes_ccm.o \
+ 	cfg.o \
+@@ -29,7 +28,7 @@ mac80211-y := \
+ 	util.o \
+ 	event.o
+ 
+-mac80211-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
++mac80211-$(CONFIG_MAC80211_LEDS) += led.o
+ mac80211-$(CONFIG_NET_SCHED) += wme.o
+ mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
+ 	debugfs.o \
+@@ -37,11 +36,15 @@ mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
+ 	debugfs_netdev.o \
+ 	debugfs_key.o
+ 
++mac80211-$(CONFIG_MAC80211_MESH) += \
++	mesh.o \
++	mesh_pathtbl.o \
++	mesh_plink.o \
++	mesh_hwmp.o
++
+ 
+ # Build rate control algorithm(s)
+-CFLAGS_rc80211_simple.o += -DRC80211_SIMPLE_COMPILE
+ CFLAGS_rc80211_pid_algo.o += -DRC80211_PID_COMPILE
+-mac80211-$(CONFIG_MAC80211_RC_SIMPLE) += rc80211_simple.o
+ mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc-pid-$(CONFIG_MAC80211_RC_PID))
+ 
+ # Modular rate algorithms are assigned to mac80211-m - make separate modules
+diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
+index e62fe55..59f1691 100644
+--- a/net/mac80211/aes_ccm.c
++++ b/net/mac80211/aes_ccm.c
+@@ -13,7 +13,7 @@
+ #include <linux/err.h>
+ 
+ #include <net/mac80211.h>
+-#include "ieee80211_key.h"
++#include "key.h"
+ #include "aes_ccm.h"
+ 
+ 
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 22c9619..699d97b 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -14,7 +14,8 @@
+ #include <net/cfg80211.h>
+ #include "ieee80211_i.h"
+ #include "cfg.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
++#include "mesh.h"
+ 
+ static enum ieee80211_if_types
+ nl80211_type_to_mac80211_type(enum nl80211_iftype type)
+@@ -28,16 +29,26 @@ nl80211_type_to_mac80211_type(enum nl80211_iftype type)
+ 		return IEEE80211_IF_TYPE_STA;
+ 	case NL80211_IFTYPE_MONITOR:
+ 		return IEEE80211_IF_TYPE_MNTR;
++#ifdef CONFIG_MAC80211_MESH
++	case NL80211_IFTYPE_MESH_POINT:
++		return IEEE80211_IF_TYPE_MESH_POINT;
++#endif
++	case NL80211_IFTYPE_WDS:
++		return IEEE80211_IF_TYPE_WDS;
+ 	default:
+ 		return IEEE80211_IF_TYPE_INVALID;
+ 	}
+ }
+ 
+ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
+-			       enum nl80211_iftype type)
++			       enum nl80211_iftype type, u32 *flags,
++			       struct vif_params *params)
+ {
+ 	struct ieee80211_local *local = wiphy_priv(wiphy);
+ 	enum ieee80211_if_types itype;
++	struct net_device *dev;
++	struct ieee80211_sub_if_data *sdata;
++	int err;
+ 
+ 	if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+ 		return -ENODEV;
+@@ -46,7 +57,13 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
+ 	if (itype == IEEE80211_IF_TYPE_INVALID)
+ 		return -EINVAL;
+ 
+-	return ieee80211_if_add(local->mdev, name, NULL, itype);
++	err = ieee80211_if_add(local->mdev, name, &dev, itype, params);
++	if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags)
++		return err;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	sdata->u.mntr_flags = *flags;
++	return 0;
+ }
+ 
+ static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
+@@ -69,7 +86,8 @@ static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
+ }
+ 
+ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
+-				  enum nl80211_iftype type)
++				  enum nl80211_iftype type, u32 *flags,
++				  struct vif_params *params)
+ {
+ 	struct ieee80211_local *local = wiphy_priv(wiphy);
+ 	struct net_device *dev;
+@@ -99,6 +117,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
+ 	ieee80211_if_reinit(dev);
+ 	ieee80211_if_set_type(dev, itype);
+ 
++	if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
++		ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
++					     params->mesh_id_len,
++					     params->mesh_id);
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags)
++		return 0;
++
++	sdata->u.mntr_flags = *flags;
+ 	return 0;
+ }
+ 
+@@ -109,7 +136,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ 	struct ieee80211_sub_if_data *sdata;
+ 	struct sta_info *sta = NULL;
+ 	enum ieee80211_key_alg alg;
+-	int ret;
++	struct ieee80211_key *key;
++	int err;
+ 
+ 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ 
+@@ -128,21 +156,28 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ 		return -EINVAL;
+ 	}
+ 
++	key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
++	if (!key)
++		return -ENOMEM;
++
++	rcu_read_lock();
++
+ 	if (mac_addr) {
+ 		sta = sta_info_get(sdata->local, mac_addr);
+-		if (!sta)
+-			return -ENOENT;
++		if (!sta) {
++			ieee80211_key_free(key);
++			err = -ENOENT;
++			goto out_unlock;
++		}
+ 	}
+ 
+-	ret = 0;
+-	if (!ieee80211_key_alloc(sdata, sta, alg, key_idx,
+-				 params->key_len, params->key))
+-		ret = -ENOMEM;
++	ieee80211_key_link(key, sdata, sta);
+ 
+-	if (sta)
+-		sta_info_put(sta);
++	err = 0;
++ out_unlock:
++	rcu_read_unlock();
+ 
+-	return ret;
++	return err;
+ }
+ 
+ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+@@ -154,27 +189,37 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+ 
+ 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ 
++	rcu_read_lock();
++
+ 	if (mac_addr) {
++		ret = -ENOENT;
++
+ 		sta = sta_info_get(sdata->local, mac_addr);
+ 		if (!sta)
+-			return -ENOENT;
++			goto out_unlock;
+ 
+-		ret = 0;
+-		if (sta->key)
++		if (sta->key) {
+ 			ieee80211_key_free(sta->key);
+-		else
+-			ret = -ENOENT;
++			WARN_ON(sta->key);
++			ret = 0;
++		}
+ 
+-		sta_info_put(sta);
+-		return ret;
++		goto out_unlock;
+ 	}
+ 
+-	if (!sdata->keys[key_idx])
+-		return -ENOENT;
++	if (!sdata->keys[key_idx]) {
++		ret = -ENOENT;
++		goto out_unlock;
++	}
+ 
+ 	ieee80211_key_free(sdata->keys[key_idx]);
++	WARN_ON(sdata->keys[key_idx]);
+ 
+-	return 0;
++	ret = 0;
++ out_unlock:
++	rcu_read_unlock();
++
++	return ret;
+ }
+ 
+ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+@@ -191,6 +236,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ 	u16 iv16;
+ 	int err = -ENOENT;
+ 
++	rcu_read_lock();
++
+ 	if (mac_addr) {
+ 		sta = sta_info_get(sdata->local, mac_addr);
+ 		if (!sta)
+@@ -254,8 +301,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ 	err = 0;
+ 
+  out:
+-	if (sta)
+-		sta_info_put(sta);
++	rcu_read_unlock();
+ 	return err;
+ }
+ 
+@@ -265,35 +311,83 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
+ {
+ 	struct ieee80211_sub_if_data *sdata;
+ 
++	rcu_read_lock();
++
+ 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ 	ieee80211_set_default_key(sdata, key_idx);
+ 
++	rcu_read_unlock();
++
+ 	return 0;
+ }
+ 
++static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
++{
++	struct ieee80211_sub_if_data *sdata = sta->sdata;
++
++	sinfo->filled = STATION_INFO_INACTIVE_TIME |
++			STATION_INFO_RX_BYTES |
++			STATION_INFO_TX_BYTES;
++
++	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
++	sinfo->rx_bytes = sta->rx_bytes;
++	sinfo->tx_bytes = sta->tx_bytes;
++
++	if (ieee80211_vif_is_mesh(&sdata->vif)) {
++#ifdef CONFIG_MAC80211_MESH
++		sinfo->filled |= STATION_INFO_LLID |
++				 STATION_INFO_PLID |
++				 STATION_INFO_PLINK_STATE;
++
++		sinfo->llid = le16_to_cpu(sta->llid);
++		sinfo->plid = le16_to_cpu(sta->plid);
++		sinfo->plink_state = sta->plink_state;
++#endif
++	}
++}
++
++
++static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
++				 int idx, u8 *mac, struct station_info *sinfo)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sta_info *sta;
++	int ret = -ENOENT;
++
++	rcu_read_lock();
++
++	sta = sta_info_get_by_idx(local, idx, dev);
++	if (sta) {
++		ret = 0;
++		memcpy(mac, sta->addr, ETH_ALEN);
++		sta_set_sinfo(sta, sinfo);
++	}
++
++	rcu_read_unlock();
++
++	return ret;
++}
++
+ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+-				 u8 *mac, struct station_stats *stats)
++				 u8 *mac, struct station_info *sinfo)
+ {
+ 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ 	struct sta_info *sta;
++	int ret = -ENOENT;
+ 
+-	sta = sta_info_get(local, mac);
+-	if (!sta)
+-		return -ENOENT;
++	rcu_read_lock();
+ 
+ 	/* XXX: verify sta->dev == dev */
+ 
+-	stats->filled = STATION_STAT_INACTIVE_TIME |
+-			STATION_STAT_RX_BYTES |
+-			STATION_STAT_TX_BYTES;
+-
+-	stats->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
+-	stats->rx_bytes = sta->rx_bytes;
+-	stats->tx_bytes = sta->tx_bytes;
++	sta = sta_info_get(local, mac);
++	if (sta) {
++		ret = 0;
++		sta_set_sinfo(sta, sinfo);
++	}
+ 
+-	sta_info_put(sta);
++	rcu_read_unlock();
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ /*
+@@ -486,8 +580,8 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
+ 	msg->xid_info[1] = 1;	/* LLC types/classes: Type 1 LLC */
+ 	msg->xid_info[2] = 0;	/* XID sender's receive window size (RW) */
+ 
+-	skb->dev = sta->dev;
+-	skb->protocol = eth_type_trans(skb, sta->dev);
++	skb->dev = sta->sdata->dev;
++	skb->protocol = eth_type_trans(skb, sta->sdata->dev);
+ 	memset(skb->cb, 0, sizeof(skb->cb));
+ 	netif_rx(skb);
+ }
+@@ -498,7 +592,14 @@ static void sta_apply_parameters(struct ieee80211_local *local,
+ {
+ 	u32 rates;
+ 	int i, j;
+-	struct ieee80211_hw_mode *mode;
++	struct ieee80211_supported_band *sband;
++	struct ieee80211_sub_if_data *sdata = sta->sdata;
++
++	/*
++	 * FIXME: updating the flags is racy when this function is
++	 *	  called from ieee80211_change_station(), this will
++	 *	  be resolved in a future patch.
++	 */
+ 
+ 	if (params->station_flags & STATION_FLAG_CHANGED) {
+ 		sta->flags &= ~WLAN_STA_AUTHORIZED;
+@@ -514,6 +615,13 @@ static void sta_apply_parameters(struct ieee80211_local *local,
+ 			sta->flags |= WLAN_STA_WME;
+ 	}
+ 
++	/*
++	 * FIXME: updating the following information is racy when this
++	 *	  function is called from ieee80211_change_station().
++	 *	  However, all this information should be static so
++	 *	  maybe we should just reject attemps to change it.
++	 */
++
+ 	if (params->aid) {
+ 		sta->aid = params->aid;
+ 		if (sta->aid > IEEE80211_MAX_AID)
+@@ -525,15 +633,27 @@ static void sta_apply_parameters(struct ieee80211_local *local,
+ 
+ 	if (params->supported_rates) {
+ 		rates = 0;
+-		mode = local->oper_hw_mode;
++		sband = local->hw.wiphy->bands[local->oper_channel->band];
++
+ 		for (i = 0; i < params->supported_rates_len; i++) {
+ 			int rate = (params->supported_rates[i] & 0x7f) * 5;
+-			for (j = 0; j < mode->num_rates; j++) {
+-				if (mode->rates[j].rate == rate)
++			for (j = 0; j < sband->n_bitrates; j++) {
++				if (sband->bitrates[j].bitrate == rate)
+ 					rates |= BIT(j);
+ 			}
+ 		}
+-		sta->supp_rates = rates;
++		sta->supp_rates[local->oper_channel->band] = rates;
++	}
++
++	if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
++		switch (params->plink_action) {
++		case PLINK_ACTION_OPEN:
++			mesh_plink_open(sta);
++			break;
++		case PLINK_ACTION_BLOCK:
++			mesh_plink_block(sta);
++			break;
++		}
+ 	}
+ }
+ 
+@@ -543,18 +663,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
+ 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ 	struct sta_info *sta;
+ 	struct ieee80211_sub_if_data *sdata;
++	int err;
+ 
+ 	/* Prevent a race with changing the rate control algorithm */
+ 	if (!netif_running(dev))
+ 		return -ENETDOWN;
+ 
+-	/* XXX: get sta belonging to dev */
+-	sta = sta_info_get(local, mac);
+-	if (sta) {
+-		sta_info_put(sta);
+-		return -EEXIST;
+-	}
+-
+ 	if (params->vlan) {
+ 		sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
+ 
+@@ -564,22 +678,36 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
+ 	} else
+ 		sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ 
+-	sta = sta_info_add(local, dev, mac, GFP_KERNEL);
++	if (compare_ether_addr(mac, dev->dev_addr) == 0)
++		return -EINVAL;
++
++	if (is_multicast_ether_addr(mac))
++		return -EINVAL;
++
++	sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
+ 	if (!sta)
+ 		return -ENOMEM;
+ 
+-	sta->dev = sdata->dev;
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
+-	    sdata->vif.type == IEEE80211_IF_TYPE_AP)
+-		ieee80211_send_layer2_update(sta);
+-
+ 	sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
+ 
+ 	sta_apply_parameters(local, sta, params);
+ 
+ 	rate_control_rate_init(sta, local);
+ 
+-	sta_info_put(sta);
++	rcu_read_lock();
++
++	err = sta_info_insert(sta);
++	if (err) {
++		/* STA has been freed */
++		rcu_read_unlock();
++		return err;
++	}
++
++	if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
++	    sdata->vif.type == IEEE80211_IF_TYPE_AP)
++		ieee80211_send_layer2_update(sta);
++
++	rcu_read_unlock();
+ 
+ 	return 0;
+ }
+@@ -587,19 +715,26 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
+ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
+ 				 u8 *mac)
+ {
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_local *local = sdata->local;
+ 	struct sta_info *sta;
+ 
+ 	if (mac) {
++		rcu_read_lock();
++
+ 		/* XXX: get sta belonging to dev */
+ 		sta = sta_info_get(local, mac);
+-		if (!sta)
++		if (!sta) {
++			rcu_read_unlock();
+ 			return -ENOENT;
++		}
++
++		sta_info_unlink(&sta);
++		rcu_read_unlock();
+ 
+-		sta_info_free(sta);
+-		sta_info_put(sta);
++		sta_info_destroy(sta);
+ 	} else
+-		sta_info_flush(local, dev);
++		sta_info_flush(local, sdata);
+ 
+ 	return 0;
+ }
+@@ -613,28 +748,203 @@ static int ieee80211_change_station(struct wiphy *wiphy,
+ 	struct sta_info *sta;
+ 	struct ieee80211_sub_if_data *vlansdata;
+ 
++	rcu_read_lock();
++
+ 	/* XXX: get sta belonging to dev */
+ 	sta = sta_info_get(local, mac);
+-	if (!sta)
++	if (!sta) {
++		rcu_read_unlock();
+ 		return -ENOENT;
++	}
+ 
+-	if (params->vlan && params->vlan != sta->dev) {
++	if (params->vlan && params->vlan != sta->sdata->dev) {
+ 		vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
+ 
+ 		if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
+-		    vlansdata->vif.type != IEEE80211_IF_TYPE_AP)
++		    vlansdata->vif.type != IEEE80211_IF_TYPE_AP) {
++			rcu_read_unlock();
+ 			return -EINVAL;
++		}
+ 
+-		sta->dev = params->vlan;
++		sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
+ 		ieee80211_send_layer2_update(sta);
+ 	}
+ 
+ 	sta_apply_parameters(local, sta, params);
+ 
+-	sta_info_put(sta);
++	rcu_read_unlock();
++
++	return 0;
++}
++
++#ifdef CONFIG_MAC80211_MESH
++static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
++				 u8 *dst, u8 *next_hop)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct mesh_path *mpath;
++	struct sta_info *sta;
++	int err;
++
++	if (!netif_running(dev))
++		return -ENETDOWN;
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
++		return -ENOTSUPP;
++
++	rcu_read_lock();
++	sta = sta_info_get(local, next_hop);
++	if (!sta) {
++		rcu_read_unlock();
++		return -ENOENT;
++	}
+ 
++	err = mesh_path_add(dst, dev);
++	if (err) {
++		rcu_read_unlock();
++		return err;
++	}
++
++	mpath = mesh_path_lookup(dst, dev);
++	if (!mpath) {
++		rcu_read_unlock();
++		return -ENXIO;
++	}
++	mesh_path_fix_nexthop(mpath, sta);
++
++	rcu_read_unlock();
++	return 0;
++}
++
++static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
++				 u8 *dst)
++{
++	if (dst)
++		return mesh_path_del(dst, dev);
++
++	mesh_path_flush(dev);
++	return 0;
++}
++
++static int ieee80211_change_mpath(struct wiphy *wiphy,
++				    struct net_device *dev,
++				    u8 *dst, u8 *next_hop)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct mesh_path *mpath;
++	struct sta_info *sta;
++
++	if (!netif_running(dev))
++		return -ENETDOWN;
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
++		return -ENOTSUPP;
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, next_hop);
++	if (!sta) {
++		rcu_read_unlock();
++		return -ENOENT;
++	}
++
++	mpath = mesh_path_lookup(dst, dev);
++	if (!mpath) {
++		rcu_read_unlock();
++		return -ENOENT;
++	}
++
++	mesh_path_fix_nexthop(mpath, sta);
++
++	rcu_read_unlock();
++	return 0;
++}
++
++static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
++			    struct mpath_info *pinfo)
++{
++	if (mpath->next_hop)
++		memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
++	else
++		memset(next_hop, 0, ETH_ALEN);
++
++	pinfo->filled = MPATH_INFO_FRAME_QLEN |
++			MPATH_INFO_DSN |
++			MPATH_INFO_METRIC |
++			MPATH_INFO_EXPTIME |
++			MPATH_INFO_DISCOVERY_TIMEOUT |
++			MPATH_INFO_DISCOVERY_RETRIES |
++			MPATH_INFO_FLAGS;
++
++	pinfo->frame_qlen = mpath->frame_queue.qlen;
++	pinfo->dsn = mpath->dsn;
++	pinfo->metric = mpath->metric;
++	if (time_before(jiffies, mpath->exp_time))
++		pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
++	pinfo->discovery_timeout =
++			jiffies_to_msecs(mpath->discovery_timeout);
++	pinfo->discovery_retries = mpath->discovery_retries;
++	pinfo->flags = 0;
++	if (mpath->flags & MESH_PATH_ACTIVE)
++		pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
++	if (mpath->flags & MESH_PATH_RESOLVING)
++		pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
++	if (mpath->flags & MESH_PATH_DSN_VALID)
++		pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
++	if (mpath->flags & MESH_PATH_FIXED)
++		pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
++	if (mpath->flags & MESH_PATH_RESOLVING)
++		pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
++
++	pinfo->flags = mpath->flags;
++}
++
++static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
++			       u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
++
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct mesh_path *mpath;
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
++		return -ENOTSUPP;
++
++	rcu_read_lock();
++	mpath = mesh_path_lookup(dst, dev);
++	if (!mpath) {
++		rcu_read_unlock();
++		return -ENOENT;
++	}
++	memcpy(dst, mpath->dst, ETH_ALEN);
++	mpath_set_pinfo(mpath, next_hop, pinfo);
++	rcu_read_unlock();
++	return 0;
++}
++
++static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
++				 int idx, u8 *dst, u8 *next_hop,
++				 struct mpath_info *pinfo)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct mesh_path *mpath;
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
++		return -ENOTSUPP;
++
++	rcu_read_lock();
++	mpath = mesh_path_lookup_by_idx(idx, dev);
++	if (!mpath) {
++		rcu_read_unlock();
++		return -ENOENT;
++	}
++	memcpy(dst, mpath->dst, ETH_ALEN);
++	mpath_set_pinfo(mpath, next_hop, pinfo);
++	rcu_read_unlock();
+ 	return 0;
+ }
++#endif
+ 
+ struct cfg80211_ops mac80211_config_ops = {
+ 	.add_virtual_intf = ieee80211_add_iface,
+@@ -651,4 +961,12 @@ struct cfg80211_ops mac80211_config_ops = {
+ 	.del_station = ieee80211_del_station,
+ 	.change_station = ieee80211_change_station,
+ 	.get_station = ieee80211_get_station,
++	.dump_station = ieee80211_dump_station,
++#ifdef CONFIG_MAC80211_MESH
++	.add_mpath = ieee80211_add_mpath,
++	.del_mpath = ieee80211_del_mpath,
++	.change_mpath = ieee80211_change_mpath,
++	.get_mpath = ieee80211_get_mpath,
++	.dump_mpath = ieee80211_dump_mpath,
++#endif
+ };
+diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
+index 60514b2..1cccbfd 100644
+--- a/net/mac80211/debugfs.c
++++ b/net/mac80211/debugfs.c
+@@ -10,7 +10,7 @@
+ #include <linux/debugfs.h>
+ #include <linux/rtnetlink.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
+ #include "debugfs.h"
+ 
+ int mac80211_open_file_generic(struct inode *inode, struct file *file)
+@@ -19,41 +19,6 @@ int mac80211_open_file_generic(struct inode *inode, struct file *file)
+ 	return 0;
+ }
+ 
+-static const char *ieee80211_mode_str(int mode)
+-{
+-	switch (mode) {
+-	case MODE_IEEE80211A:
+-		return "IEEE 802.11a";
+-	case MODE_IEEE80211B:
+-		return "IEEE 802.11b";
+-	case MODE_IEEE80211G:
+-		return "IEEE 802.11g";
+-	default:
+-		return "UNKNOWN";
+-	}
+-}
+-
+-static ssize_t modes_read(struct file *file, char __user *userbuf,
+-			  size_t count, loff_t *ppos)
+-{
+-	struct ieee80211_local *local = file->private_data;
+-	struct ieee80211_hw_mode *mode;
+-	char buf[150], *p = buf;
+-
+-	/* FIXME: locking! */
+-	list_for_each_entry(mode, &local->modes_list, list) {
+-		p += scnprintf(p, sizeof(buf)+buf-p,
+-			       "%s\n", ieee80211_mode_str(mode->mode));
+-	}
+-
+-	return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+-}
+-
+-static const struct file_operations modes_ops = {
+-	.read = modes_read,
+-	.open = mac80211_open_file_generic,
+-};
+-
+ #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)			\
+@@ -72,7 +37,7 @@ static const struct file_operations name## _ops = {			\
+ };
+ 
+ #define DEBUGFS_ADD(name)						\
+-	local->debugfs.name = debugfs_create_file(#name, 0444, phyd,	\
++	local->debugfs.name = debugfs_create_file(#name, 0400, phyd,	\
+ 						  local, &name## _ops);
+ 
+ #define DEBUGFS_DEL(name)						\
+@@ -80,10 +45,8 @@ static const struct file_operations name## _ops = {			\
+ 	local->debugfs.name = NULL;
+ 
+ 
+-DEBUGFS_READONLY_FILE(channel, 20, "%d",
+-		      local->hw.conf.channel);
+ DEBUGFS_READONLY_FILE(frequency, 20, "%d",
+-		      local->hw.conf.freq);
++		      local->hw.conf.channel->center_freq);
+ DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
+ 		      local->hw.conf.antenna_sel_tx);
+ DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
+@@ -100,8 +63,6 @@ DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
+ 		      local->long_retry_limit);
+ DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
+ 		      local->total_ps_buffered);
+-DEBUGFS_READONLY_FILE(mode, 20, "%s",
+-		      ieee80211_mode_str(local->hw.conf.phymode));
+ DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
+ 		      local->wep_iv & 0xffffff);
+ DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
+@@ -169,7 +130,7 @@ static const struct file_operations stats_ ##name## _ops = {		\
+ };
+ 
+ #define DEBUGFS_STATS_ADD(name)						\
+-	local->debugfs.stats.name = debugfs_create_file(#name, 0444, statsd,\
++	local->debugfs.stats.name = debugfs_create_file(#name, 0400, statsd,\
+ 		local, &stats_ ##name## _ops);
+ 
+ #define DEBUGFS_STATS_DEL(name)						\
+@@ -294,7 +255,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
+ 	local->debugfs.stations = debugfs_create_dir("stations", phyd);
+ 	local->debugfs.keys = debugfs_create_dir("keys", phyd);
+ 
+-	DEBUGFS_ADD(channel);
+ 	DEBUGFS_ADD(frequency);
+ 	DEBUGFS_ADD(antenna_sel_tx);
+ 	DEBUGFS_ADD(antenna_sel_rx);
+@@ -304,9 +264,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
+ 	DEBUGFS_ADD(short_retry_limit);
+ 	DEBUGFS_ADD(long_retry_limit);
+ 	DEBUGFS_ADD(total_ps_buffered);
+-	DEBUGFS_ADD(mode);
+ 	DEBUGFS_ADD(wep_iv);
+-	DEBUGFS_ADD(modes);
+ 
+ 	statsd = debugfs_create_dir("statistics", phyd);
+ 	local->debugfs.statistics = statsd;
+@@ -356,7 +314,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
+ 
+ void debugfs_hw_del(struct ieee80211_local *local)
+ {
+-	DEBUGFS_DEL(channel);
+ 	DEBUGFS_DEL(frequency);
+ 	DEBUGFS_DEL(antenna_sel_tx);
+ 	DEBUGFS_DEL(antenna_sel_rx);
+@@ -366,9 +323,7 @@ void debugfs_hw_del(struct ieee80211_local *local)
+ 	DEBUGFS_DEL(short_retry_limit);
+ 	DEBUGFS_DEL(long_retry_limit);
+ 	DEBUGFS_DEL(total_ps_buffered);
+-	DEBUGFS_DEL(mode);
+ 	DEBUGFS_DEL(wep_iv);
+-	DEBUGFS_DEL(modes);
+ 
+ 	DEBUGFS_STATS_DEL(transmitted_fragment_count);
+ 	DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
+diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
+index c881524..879e721 100644
+--- a/net/mac80211/debugfs_key.c
++++ b/net/mac80211/debugfs_key.c
+@@ -10,7 +10,7 @@
+ 
+ #include <linux/kobject.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_key.h"
++#include "key.h"
+ #include "debugfs.h"
+ #include "debugfs_key.h"
+ 
+@@ -184,23 +184,36 @@ KEY_OPS(key);
+ 	key->debugfs.name = debugfs_create_file(#name, 0400,\
+ 				key->debugfs.dir, key, &key_##name##_ops);
+ 
+-void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+-			       struct ieee80211_key *key)
+-{
++void ieee80211_debugfs_key_add(struct ieee80211_key *key)
++  {
+ 	static int keycount;
+-	char buf[20];
++	char buf[50];
++	DECLARE_MAC_BUF(mac);
++	struct sta_info *sta;
+ 
+-	if (!local->debugfs.keys)
++	if (!key->local->debugfs.keys)
+ 		return;
+ 
+ 	sprintf(buf, "%d", keycount);
++	key->debugfs.cnt = keycount;
+ 	keycount++;
+ 	key->debugfs.dir = debugfs_create_dir(buf,
+-					local->debugfs.keys);
++					key->local->debugfs.keys);
+ 
+ 	if (!key->debugfs.dir)
+ 		return;
+ 
++	rcu_read_lock();
++	sta = rcu_dereference(key->sta);
++	if (sta)
++		sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
++	rcu_read_unlock();
++
++	/* using sta as a boolean is fine outside RCU lock */
++	if (sta)
++		key->debugfs.stalink =
++			debugfs_create_symlink("station", key->debugfs.dir, buf);
++
+ 	DEBUGFS_ADD(keylen);
+ 	DEBUGFS_ADD(flags);
+ 	DEBUGFS_ADD(keyidx);
+@@ -246,7 +259,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
+ 	if (!sdata->debugfsdir)
+ 		return;
+ 
+-	sprintf(buf, "../keys/%d", sdata->default_key->conf.keyidx);
++	sprintf(buf, "../keys/%d", sdata->default_key->debugfs.cnt);
+ 	sdata->debugfs.default_key =
+ 		debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
+ }
+@@ -258,19 +271,6 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
+ 	debugfs_remove(sdata->debugfs.default_key);
+ 	sdata->debugfs.default_key = NULL;
+ }
+-void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+-				    struct sta_info *sta)
+-{
+-	char buf[50];
+-	DECLARE_MAC_BUF(mac);
+-
+-	if (!key->debugfs.dir)
+-		return;
+-
+-	sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
+-	key->debugfs.stalink =
+-		debugfs_create_symlink("station", key->debugfs.dir, buf);
+-}
+ 
+ void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+ 				   struct sta_info *sta)
+diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h
+index aecfce3..b1a3754 100644
+--- a/net/mac80211/debugfs_key.h
++++ b/net/mac80211/debugfs_key.h
+@@ -2,18 +2,14 @@
+ #define __MAC80211_DEBUGFS_KEY_H
+ 
+ #ifdef CONFIG_MAC80211_DEBUGFS
+-void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+-			       struct ieee80211_key *key);
++void ieee80211_debugfs_key_add(struct ieee80211_key *key);
+ void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
+ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
+ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
+-void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+-				    struct sta_info *sta);
+ void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+ 				   struct sta_info *sta);
+ #else
+-static inline void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+-					     struct ieee80211_key *key)
++static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key)
+ {}
+ static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
+ {}
+@@ -23,9 +19,6 @@ static inline void ieee80211_debugfs_key_add_default(
+ static inline void ieee80211_debugfs_key_remove_default(
+ 	struct ieee80211_sub_if_data *sdata)
+ {}
+-static inline void ieee80211_debugfs_key_sta_link(
+-	struct ieee80211_key *key, struct sta_info *sta)
+-{}
+ static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+ 						 struct sta_info *sta)
+ {}
+diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
+index 829872a..e3326d0 100644
+--- a/net/mac80211/debugfs_netdev.c
++++ b/net/mac80211/debugfs_netdev.c
+@@ -17,7 +17,7 @@
+ #include <net/mac80211.h>
+ #include <net/cfg80211.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
+ #include "debugfs.h"
+ #include "debugfs_netdev.h"
+ 
+@@ -31,14 +31,39 @@ static ssize_t ieee80211_if_read(
+ 	ssize_t ret = -EINVAL;
+ 
+ 	read_lock(&dev_base_lock);
+-	if (sdata->dev->reg_state == NETREG_REGISTERED) {
++	if (sdata->dev->reg_state == NETREG_REGISTERED)
+ 		ret = (*format)(sdata, buf, sizeof(buf));
+-		ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
+-	}
+ 	read_unlock(&dev_base_lock);
++
++	if (ret != -EINVAL)
++		ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
++
+ 	return ret;
+ }
+ 
++#ifdef CONFIG_MAC80211_MESH
++static ssize_t ieee80211_if_write(
++	struct ieee80211_sub_if_data *sdata,
++	char const __user *userbuf,
++	size_t count, loff_t *ppos,
++	int (*format)(struct ieee80211_sub_if_data *, char *))
++{
++	char buf[10];
++	int buf_size;
++
++	memset(buf, 0x00, sizeof(buf));
++	buf_size = min(count, (sizeof(buf)-1));
++	if (copy_from_user(buf, userbuf, buf_size))
++		return count;
++	read_lock(&dev_base_lock);
++	if (sdata->dev->reg_state == NETREG_REGISTERED)
++		(*format)(sdata, buf);
++	read_unlock(&dev_base_lock);
++
++	return count;
++}
++#endif
++
+ #define IEEE80211_IF_FMT(name, field, format_string)			\
+ static ssize_t ieee80211_if_fmt_##name(					\
+ 	const struct ieee80211_sub_if_data *sdata, char *buf,		\
+@@ -46,6 +71,19 @@ static ssize_t ieee80211_if_fmt_##name(					\
+ {									\
+ 	return scnprintf(buf, buflen, format_string, sdata->field);	\
+ }
++#define IEEE80211_IF_WFMT(name, field, type)				\
++static int ieee80211_if_wfmt_##name(					\
++	struct ieee80211_sub_if_data *sdata, char *buf)			\
++{									\
++	unsigned long tmp;						\
++	char *endp;							\
++									\
++	tmp = simple_strtoul(buf, &endp, 0);				\
++	if ((endp == buf) || ((type)tmp != tmp))			\
++		return -EINVAL;						\
++	sdata->field = tmp;						\
++	return 0;							\
++}
+ #define IEEE80211_IF_FMT_DEC(name, field)				\
+ 		IEEE80211_IF_FMT(name, field, "%d\n")
+ #define IEEE80211_IF_FMT_HEX(name, field)				\
+@@ -88,10 +126,37 @@ static const struct file_operations name##_ops = {			\
+ 		IEEE80211_IF_FMT_##format(name, field)			\
+ 		__IEEE80211_IF_FILE(name)
+ 
++#define __IEEE80211_IF_WFILE(name)					\
++static ssize_t ieee80211_if_read_##name(struct file *file,		\
++					char __user *userbuf,		\
++					size_t count, loff_t *ppos)	\
++{									\
++	return ieee80211_if_read(file->private_data,			\
++				 userbuf, count, ppos,			\
++				 ieee80211_if_fmt_##name);		\
++}									\
++static ssize_t ieee80211_if_write_##name(struct file *file,		\
++					const char __user *userbuf,	\
++					size_t count, loff_t *ppos)	\
++{									\
++	return ieee80211_if_write(file->private_data,			\
++				 userbuf, count, ppos,			\
++				 ieee80211_if_wfmt_##name);		\
++}									\
++static const struct file_operations name##_ops = {			\
++	.read = ieee80211_if_read_##name,				\
++	.write = ieee80211_if_write_##name,				\
++	.open = mac80211_open_file_generic,				\
++}
++
++#define IEEE80211_IF_WFILE(name, field, format, type)			\
++		IEEE80211_IF_FMT_##format(name, field)			\
++		IEEE80211_IF_WFMT(name, field, type)			\
++		__IEEE80211_IF_WFILE(name)
++
+ /* common attributes */
+ IEEE80211_IF_FILE(channel_use, channel_use, DEC);
+ IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
+-IEEE80211_IF_FILE(ieee802_1x_pac, ieee802_1x_pac, DEC);
+ 
+ /* STA/IBSS attributes */
+ IEEE80211_IF_FILE(state, u.sta.state, DEC);
+@@ -107,6 +172,7 @@ IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
+ IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
+ IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
+ IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
++IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC);
+ 
+ static ssize_t ieee80211_if_fmt_flags(
+ 	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+@@ -140,15 +206,50 @@ __IEEE80211_IF_FILE(num_buffered_multicast);
+ /* WDS attributes */
+ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
+ 
++#ifdef CONFIG_MAC80211_MESH
++/* Mesh stats attributes */
++IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC);
++IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC);
++IEEE80211_IF_FILE(dropped_frames_no_route,
++		u.sta.mshstats.dropped_frames_no_route, DEC);
++IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC);
++
++/* Mesh parameters */
++IEEE80211_IF_WFILE(dot11MeshMaxRetries,
++		u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8);
++IEEE80211_IF_WFILE(dot11MeshRetryTimeout,
++		u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshConfirmTimeout,
++		u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshHoldingTimeout,
++		u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8);
++IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8);
++IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks,
++		u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout,
++		u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32);
++IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval,
++		u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime,
++		u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries,
++		u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8);
++IEEE80211_IF_WFILE(path_refresh_time,
++		u.sta.mshcfg.path_refresh_time, DEC, u32);
++IEEE80211_IF_WFILE(min_discovery_timeout,
++		u.sta.mshcfg.min_discovery_timeout, DEC, u16);
++#endif
++
++
+ #define DEBUGFS_ADD(name, type)\
+-	sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
++	sdata->debugfs.type.name = debugfs_create_file(#name, 0400,\
+ 		sdata->debugfsdir, sdata, &name##_ops);
+ 
+ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
+ {
+ 	DEBUGFS_ADD(channel_use, sta);
+ 	DEBUGFS_ADD(drop_unencrypted, sta);
+-	DEBUGFS_ADD(ieee802_1x_pac, sta);
+ 	DEBUGFS_ADD(state, sta);
+ 	DEBUGFS_ADD(bssid, sta);
+ 	DEBUGFS_ADD(prev_bssid, sta);
+@@ -163,13 +264,13 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
+ 	DEBUGFS_ADD(auth_alg, sta);
+ 	DEBUGFS_ADD(auth_transaction, sta);
+ 	DEBUGFS_ADD(flags, sta);
++	DEBUGFS_ADD(num_beacons_sta, sta);
+ }
+ 
+ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
+ {
+ 	DEBUGFS_ADD(channel_use, ap);
+ 	DEBUGFS_ADD(drop_unencrypted, ap);
+-	DEBUGFS_ADD(ieee802_1x_pac, ap);
+ 	DEBUGFS_ADD(num_sta_ps, ap);
+ 	DEBUGFS_ADD(dtim_count, ap);
+ 	DEBUGFS_ADD(num_beacons, ap);
+@@ -182,7 +283,6 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata)
+ {
+ 	DEBUGFS_ADD(channel_use, wds);
+ 	DEBUGFS_ADD(drop_unencrypted, wds);
+-	DEBUGFS_ADD(ieee802_1x_pac, wds);
+ 	DEBUGFS_ADD(peer, wds);
+ }
+ 
+@@ -190,19 +290,63 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
+ {
+ 	DEBUGFS_ADD(channel_use, vlan);
+ 	DEBUGFS_ADD(drop_unencrypted, vlan);
+-	DEBUGFS_ADD(ieee802_1x_pac, vlan);
+ }
+ 
+ static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
+ {
+ }
+ 
++#ifdef CONFIG_MAC80211_MESH
++#define MESHSTATS_ADD(name)\
++	sdata->mesh_stats.name = debugfs_create_file(#name, 0400,\
++		sdata->mesh_stats_dir, sdata, &name##_ops);
++
++static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
++{
++	sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats",
++				sdata->debugfsdir);
++	MESHSTATS_ADD(fwded_frames);
++	MESHSTATS_ADD(dropped_frames_ttl);
++	MESHSTATS_ADD(dropped_frames_no_route);
++	MESHSTATS_ADD(estab_plinks);
++}
++
++#define MESHPARAMS_ADD(name)\
++	sdata->mesh_config.name = debugfs_create_file(#name, 0600,\
++		sdata->mesh_config_dir, sdata, &name##_ops);
++
++static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
++{
++	sdata->mesh_config_dir = debugfs_create_dir("mesh_config",
++				sdata->debugfsdir);
++	MESHPARAMS_ADD(dot11MeshMaxRetries);
++	MESHPARAMS_ADD(dot11MeshRetryTimeout);
++	MESHPARAMS_ADD(dot11MeshConfirmTimeout);
++	MESHPARAMS_ADD(dot11MeshHoldingTimeout);
++	MESHPARAMS_ADD(dot11MeshTTL);
++	MESHPARAMS_ADD(auto_open_plinks);
++	MESHPARAMS_ADD(dot11MeshMaxPeerLinks);
++	MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout);
++	MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval);
++	MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime);
++	MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
++	MESHPARAMS_ADD(path_refresh_time);
++	MESHPARAMS_ADD(min_discovery_timeout);
++}
++#endif
++
+ static void add_files(struct ieee80211_sub_if_data *sdata)
+ {
+ 	if (!sdata->debugfsdir)
+ 		return;
+ 
+ 	switch (sdata->vif.type) {
++	case IEEE80211_IF_TYPE_MESH_POINT:
++#ifdef CONFIG_MAC80211_MESH
++		add_mesh_stats(sdata);
++		add_mesh_config(sdata);
++#endif
++		/* fall through */
+ 	case IEEE80211_IF_TYPE_STA:
+ 	case IEEE80211_IF_TYPE_IBSS:
+ 		add_sta_files(sdata);
+@@ -234,7 +378,6 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata)
+ {
+ 	DEBUGFS_DEL(channel_use, sta);
+ 	DEBUGFS_DEL(drop_unencrypted, sta);
+-	DEBUGFS_DEL(ieee802_1x_pac, sta);
+ 	DEBUGFS_DEL(state, sta);
+ 	DEBUGFS_DEL(bssid, sta);
+ 	DEBUGFS_DEL(prev_bssid, sta);
+@@ -249,13 +392,13 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata)
+ 	DEBUGFS_DEL(auth_alg, sta);
+ 	DEBUGFS_DEL(auth_transaction, sta);
+ 	DEBUGFS_DEL(flags, sta);
++	DEBUGFS_DEL(num_beacons_sta, sta);
+ }
+ 
+ static void del_ap_files(struct ieee80211_sub_if_data *sdata)
+ {
+ 	DEBUGFS_DEL(channel_use, ap);
+ 	DEBUGFS_DEL(drop_unencrypted, ap);
+-	DEBUGFS_DEL(ieee802_1x_pac, ap);
+ 	DEBUGFS_DEL(num_sta_ps, ap);
+ 	DEBUGFS_DEL(dtim_count, ap);
+ 	DEBUGFS_DEL(num_beacons, ap);
+@@ -268,7 +411,6 @@ static void del_wds_files(struct ieee80211_sub_if_data *sdata)
+ {
+ 	DEBUGFS_DEL(channel_use, wds);
+ 	DEBUGFS_DEL(drop_unencrypted, wds);
+-	DEBUGFS_DEL(ieee802_1x_pac, wds);
+ 	DEBUGFS_DEL(peer, wds);
+ }
+ 
+@@ -276,19 +418,67 @@ static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
+ {
+ 	DEBUGFS_DEL(channel_use, vlan);
+ 	DEBUGFS_DEL(drop_unencrypted, vlan);
+-	DEBUGFS_DEL(ieee802_1x_pac, vlan);
+ }
+ 
+ static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
+ {
+ }
+ 
++#ifdef CONFIG_MAC80211_MESH
++#define MESHSTATS_DEL(name)			\
++	do {						\
++		debugfs_remove(sdata->mesh_stats.name);	\
++		sdata->mesh_stats.name = NULL;		\
++	} while (0)
++
++static void del_mesh_stats(struct ieee80211_sub_if_data *sdata)
++{
++	MESHSTATS_DEL(fwded_frames);
++	MESHSTATS_DEL(dropped_frames_ttl);
++	MESHSTATS_DEL(dropped_frames_no_route);
++	MESHSTATS_DEL(estab_plinks);
++	debugfs_remove(sdata->mesh_stats_dir);
++	sdata->mesh_stats_dir = NULL;
++}
++
++#define MESHPARAMS_DEL(name)			\
++	do {						\
++		debugfs_remove(sdata->mesh_config.name);	\
++		sdata->mesh_config.name = NULL;		\
++	} while (0)
++
++static void del_mesh_config(struct ieee80211_sub_if_data *sdata)
++{
++	MESHPARAMS_DEL(dot11MeshMaxRetries);
++	MESHPARAMS_DEL(dot11MeshRetryTimeout);
++	MESHPARAMS_DEL(dot11MeshConfirmTimeout);
++	MESHPARAMS_DEL(dot11MeshHoldingTimeout);
++	MESHPARAMS_DEL(dot11MeshTTL);
++	MESHPARAMS_DEL(auto_open_plinks);
++	MESHPARAMS_DEL(dot11MeshMaxPeerLinks);
++	MESHPARAMS_DEL(dot11MeshHWMPactivePathTimeout);
++	MESHPARAMS_DEL(dot11MeshHWMPpreqMinInterval);
++	MESHPARAMS_DEL(dot11MeshHWMPnetDiameterTraversalTime);
++	MESHPARAMS_DEL(dot11MeshHWMPmaxPREQretries);
++	MESHPARAMS_DEL(path_refresh_time);
++	MESHPARAMS_DEL(min_discovery_timeout);
++	debugfs_remove(sdata->mesh_config_dir);
++	sdata->mesh_config_dir = NULL;
++}
++#endif
++
+ static void del_files(struct ieee80211_sub_if_data *sdata, int type)
+ {
+ 	if (!sdata->debugfsdir)
+ 		return;
+ 
+ 	switch (type) {
++	case IEEE80211_IF_TYPE_MESH_POINT:
++#ifdef CONFIG_MAC80211_MESH
++		del_mesh_stats(sdata);
++		del_mesh_config(sdata);
++#endif
++		/* fall through */
+ 	case IEEE80211_IF_TYPE_STA:
+ 	case IEEE80211_IF_TYPE_IBSS:
+ 		del_sta_files(sdata);
+diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
+index 8f5944c..6d47a1d 100644
+--- a/net/mac80211/debugfs_sta.c
++++ b/net/mac80211/debugfs_sta.c
+@@ -33,25 +33,16 @@ static ssize_t sta_ ##name## _read(struct file *file,			\
+ #define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n")
+ #define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n")
+ 
+-#define STA_READ_RATE(name, field)					\
+-static ssize_t sta_##name##_read(struct file *file,			\
+-				 char __user *userbuf,			\
+-				 size_t count, loff_t *ppos)		\
+-{									\
+-	struct sta_info *sta = file->private_data;			\
+-	struct ieee80211_local *local = wdev_priv(sta->dev->ieee80211_ptr);\
+-	struct ieee80211_hw_mode *mode = local->oper_hw_mode;		\
+-	char buf[20];							\
+-	int res = scnprintf(buf, sizeof(buf), "%d\n",			\
+-			    (sta->field >= 0 &&				\
+-			    sta->field < mode->num_rates) ?		\
+-			    mode->rates[sta->field].rate : -1);		\
+-	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
++#define STA_OPS(name)							\
++static const struct file_operations sta_ ##name## _ops = {		\
++	.read = sta_##name##_read,					\
++	.open = mac80211_open_file_generic,				\
+ }
+ 
+-#define STA_OPS(name)							\
++#define STA_OPS_WR(name)						\
+ static const struct file_operations sta_ ##name## _ops = {		\
+ 	.read = sta_##name##_read,					\
++	.write = sta_##name##_write,					\
+ 	.open = mac80211_open_file_generic,				\
+ }
+ 
+@@ -60,7 +51,7 @@ static const struct file_operations sta_ ##name## _ops = {		\
+ 		STA_OPS(name)
+ 
+ STA_FILE(aid, aid, D);
+-STA_FILE(dev, dev->name, S);
++STA_FILE(dev, sdata->dev->name, S);
+ STA_FILE(rx_packets, rx_packets, LU);
+ STA_FILE(tx_packets, tx_packets, LU);
+ STA_FILE(rx_bytes, rx_bytes, LU);
+@@ -70,27 +61,23 @@ STA_FILE(rx_fragments, rx_fragments, LU);
+ STA_FILE(rx_dropped, rx_dropped, LU);
+ STA_FILE(tx_fragments, tx_fragments, LU);
+ STA_FILE(tx_filtered, tx_filtered_count, LU);
+-STA_FILE(txrate, txrate, RATE);
+-STA_FILE(last_txrate, last_txrate, RATE);
+ STA_FILE(tx_retry_failed, tx_retry_failed, LU);
+ STA_FILE(tx_retry_count, tx_retry_count, LU);
+ STA_FILE(last_rssi, last_rssi, D);
+ STA_FILE(last_signal, last_signal, D);
+ STA_FILE(last_noise, last_noise, D);
+ STA_FILE(channel_use, channel_use, D);
+-STA_FILE(wep_weak_iv_count, wep_weak_iv_count, D);
++STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
+ 
+ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
+ 			      size_t count, loff_t *ppos)
+ {
+ 	char buf[100];
+ 	struct sta_info *sta = file->private_data;
+-	int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
++	int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
+ 		sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
+ 		sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
+ 		sta->flags & WLAN_STA_PS ? "PS\n" : "",
+-		sta->flags & WLAN_STA_TIM ? "TIM\n" : "",
+-		sta->flags & WLAN_STA_PERM ? "PERM\n" : "",
+ 		sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
+ 		sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
+ 		sta->flags & WLAN_STA_WME ? "WME\n" : "",
+@@ -111,31 +98,6 @@ static ssize_t sta_num_ps_buf_frames_read(struct file *file,
+ }
+ STA_OPS(num_ps_buf_frames);
+ 
+-static ssize_t sta_last_ack_rssi_read(struct file *file, char __user *userbuf,
+-				      size_t count, loff_t *ppos)
+-{
+-	char buf[100];
+-	struct sta_info *sta = file->private_data;
+-	int res = scnprintf(buf, sizeof(buf), "%d %d %d\n",
+-			    sta->last_ack_rssi[0],
+-			    sta->last_ack_rssi[1],
+-			    sta->last_ack_rssi[2]);
+-	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+-}
+-STA_OPS(last_ack_rssi);
+-
+-static ssize_t sta_last_ack_ms_read(struct file *file, char __user *userbuf,
+-				    size_t count, loff_t *ppos)
+-{
+-	char buf[20];
+-	struct sta_info *sta = file->private_data;
+-	int res = scnprintf(buf, sizeof(buf), "%d\n",
+-			    sta->last_ack ?
+-			    jiffies_to_msecs(jiffies - sta->last_ack) : -1);
+-	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+-}
+-STA_OPS(last_ack_ms);
+-
+ static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
+ 				    size_t count, loff_t *ppos)
+ {
+@@ -191,8 +153,120 @@ static ssize_t sta_wme_tx_queue_read(struct file *file, char __user *userbuf,
+ STA_OPS(wme_tx_queue);
+ #endif
+ 
++static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
++					size_t count, loff_t *ppos)
++{
++	char buf[768], *p = buf;
++	int i;
++	struct sta_info *sta = file->private_data;
++	p += scnprintf(p, sizeof(buf)+buf-p, "Agg state for STA is:\n");
++	p += scnprintf(p, sizeof(buf)+buf-p, " STA next dialog_token is %d \n "
++			"TIDs info is: \n TID :",
++			(sta->ampdu_mlme.dialog_token_allocator + 1));
++	for (i = 0; i < STA_TID_NUM; i++)
++		p += scnprintf(p, sizeof(buf)+buf-p, "%5d", i);
++
++	p += scnprintf(p, sizeof(buf)+buf-p, "\n RX  :");
++	for (i = 0; i < STA_TID_NUM; i++)
++		p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++			sta->ampdu_mlme.tid_state_rx[i]);
++
++	p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
++	for (i = 0; i < STA_TID_NUM; i++)
++		p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++			sta->ampdu_mlme.tid_state_rx[i]?
++			sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
++
++	p += scnprintf(p, sizeof(buf)+buf-p, "\n TX  :");
++	for (i = 0; i < STA_TID_NUM; i++)
++		p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++			sta->ampdu_mlme.tid_state_tx[i]);
++
++	p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
++	for (i = 0; i < STA_TID_NUM; i++)
++		p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++			sta->ampdu_mlme.tid_state_tx[i]?
++			sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
++
++	p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :");
++	for (i = 0; i < STA_TID_NUM; i++)
++		p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++			sta->ampdu_mlme.tid_state_tx[i]?
++			sta->ampdu_mlme.tid_tx[i]->ssn : 0);
++
++	p += scnprintf(p, sizeof(buf)+buf-p, "\n");
++
++	return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
++}
++
++static ssize_t sta_agg_status_write(struct file *file,
++		const char __user *user_buf, size_t count, loff_t *ppos)
++{
++	struct sta_info *sta = file->private_data;
++	struct net_device *dev = sta->sdata->dev;
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_hw *hw = &local->hw;
++	u8 *da = sta->addr;
++	static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0,
++					0, 0, 0, 0, 0, 0, 0, 0};
++	static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1,
++					1, 1, 1, 1, 1, 1, 1, 1};
++	char *endp;
++	char buf[32];
++	int buf_size, rs;
++	unsigned int tid_num;
++	char state[4];
++
++	memset(buf, 0x00, sizeof(buf));
++	buf_size = min(count, (sizeof(buf)-1));
++	if (copy_from_user(buf, user_buf, buf_size))
++		return -EFAULT;
++
++	tid_num = simple_strtoul(buf, &endp, 0);
++	if (endp == buf)
++		return -EINVAL;
++
++	if ((tid_num >= 100) && (tid_num <= 115)) {
++		/* toggle Rx aggregation command */
++		tid_num = tid_num - 100;
++		if (tid_static_rx[tid_num] == 1) {
++			strcpy(state, "off ");
++			ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0,
++					WLAN_REASON_QSTA_REQUIRE_SETUP);
++			sta->ampdu_mlme.tid_state_rx[tid_num] |=
++					HT_AGG_STATE_DEBUGFS_CTL;
++			tid_static_rx[tid_num] = 0;
++		} else {
++			strcpy(state, "on ");
++			sta->ampdu_mlme.tid_state_rx[tid_num] &=
++					~HT_AGG_STATE_DEBUGFS_CTL;
++			tid_static_rx[tid_num] = 1;
++		}
++		printk(KERN_DEBUG "debugfs - try switching tid %u %s\n",
++				tid_num, state);
++	} else if ((tid_num >= 0) && (tid_num <= 15)) {
++		/* toggle Tx aggregation command */
++		if (tid_static_tx[tid_num] == 0) {
++			strcpy(state, "on ");
++			rs =  ieee80211_start_tx_ba_session(hw, da, tid_num);
++			if (rs == 0)
++				tid_static_tx[tid_num] = 1;
++		} else {
++			strcpy(state, "off");
++			rs =  ieee80211_stop_tx_ba_session(hw, da, tid_num, 1);
++			if (rs == 0)
++				tid_static_tx[tid_num] = 0;
++		}
++		printk(KERN_DEBUG "debugfs - switching tid %u %s, return=%d\n",
++				tid_num, state, rs);
++	}
++
++	return count;
++}
++STA_OPS_WR(agg_status);
++
+ #define DEBUGFS_ADD(name) \
+-	sta->debugfs.name = debugfs_create_file(#name, 0444, \
++	sta->debugfs.name = debugfs_create_file(#name, 0400, \
+ 		sta->debugfs.dir, sta, &sta_ ##name## _ops);
+ 
+ #define DEBUGFS_DEL(name) \
+@@ -203,12 +277,13 @@ STA_OPS(wme_tx_queue);
+ void ieee80211_sta_debugfs_add(struct sta_info *sta)
+ {
+ 	struct dentry *stations_dir = sta->local->debugfs.stations;
+-	DECLARE_MAC_BUF(mac);
++	DECLARE_MAC_BUF(mbuf);
++	u8 *mac;
+ 
+ 	if (!stations_dir)
+ 		return;
+ 
+-	print_mac(mac, sta->addr);
++	mac = print_mac(mbuf, sta->addr);
+ 
+ 	sta->debugfs.dir = debugfs_create_dir(mac, stations_dir);
+ 	if (!sta->debugfs.dir)
+@@ -216,28 +291,26 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
+ 
+ 	DEBUGFS_ADD(flags);
+ 	DEBUGFS_ADD(num_ps_buf_frames);
+-	DEBUGFS_ADD(last_ack_rssi);
+-	DEBUGFS_ADD(last_ack_ms);
+ 	DEBUGFS_ADD(inactive_ms);
+ 	DEBUGFS_ADD(last_seq_ctrl);
+ #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ 	DEBUGFS_ADD(wme_rx_queue);
+ 	DEBUGFS_ADD(wme_tx_queue);
+ #endif
++	DEBUGFS_ADD(agg_status);
+ }
+ 
+ void ieee80211_sta_debugfs_remove(struct sta_info *sta)
+ {
+ 	DEBUGFS_DEL(flags);
+ 	DEBUGFS_DEL(num_ps_buf_frames);
+-	DEBUGFS_DEL(last_ack_rssi);
+-	DEBUGFS_DEL(last_ack_ms);
+ 	DEBUGFS_DEL(inactive_ms);
+ 	DEBUGFS_DEL(last_seq_ctrl);
+ #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ 	DEBUGFS_DEL(wme_rx_queue);
+ 	DEBUGFS_DEL(wme_tx_queue);
+ #endif
++	DEBUGFS_DEL(agg_status);
+ 
+ 	debugfs_remove(sta->debugfs.dir);
+ 	sta->debugfs.dir = NULL;
+diff --git a/net/mac80211/debugfs_sta.h b/net/mac80211/debugfs_sta.h
+index 574a1cd..8b60890 100644
+--- a/net/mac80211/debugfs_sta.h
++++ b/net/mac80211/debugfs_sta.h
+@@ -1,6 +1,8 @@
+ #ifndef __MAC80211_DEBUGFS_STA_H
+ #define __MAC80211_DEBUGFS_STA_H
+ 
++#include "sta_info.h"
++
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ void ieee80211_sta_debugfs_add(struct sta_info *sta);
+ void ieee80211_sta_debugfs_remove(struct sta_info *sta);
+diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
+deleted file mode 100644
+index 8e58639..0000000
+--- a/net/mac80211/ieee80211.c
++++ /dev/null
+@@ -1,1402 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- * Copyright 2006-2007	Jiri Benc <jbenc at suse.cz>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <net/mac80211.h>
+-#include <net/ieee80211_radiotap.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/netdevice.h>
+-#include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/skbuff.h>
+-#include <linux/etherdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/wireless.h>
+-#include <linux/rtnetlink.h>
+-#include <linux/bitmap.h>
+-#include <net/net_namespace.h>
+-#include <net/cfg80211.h>
+-
+-#include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
+-#include "wep.h"
+-#include "wme.h"
+-#include "aes_ccm.h"
+-#include "ieee80211_led.h"
+-#include "cfg.h"
+-#include "debugfs.h"
+-#include "debugfs_netdev.h"
+-
+-#define SUPP_MCS_SET_LEN 16
+-
+-/*
+- * For seeing transmitted packets on monitor interfaces
+- * we have a radiotap header too.
+- */
+-struct ieee80211_tx_status_rtap_hdr {
+-	struct ieee80211_radiotap_header hdr;
+-	__le16 tx_flags;
+-	u8 data_retries;
+-} __attribute__ ((packed));
+-
+-/* common interface routines */
+-
+-static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
+-{
+-	memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
+-	return ETH_ALEN;
+-}
+-
+-/* must be called under mdev tx lock */
+-static void ieee80211_configure_filter(struct ieee80211_local *local)
+-{
+-	unsigned int changed_flags;
+-	unsigned int new_flags = 0;
+-
+-	if (atomic_read(&local->iff_promiscs))
+-		new_flags |= FIF_PROMISC_IN_BSS;
+-
+-	if (atomic_read(&local->iff_allmultis))
+-		new_flags |= FIF_ALLMULTI;
+-
+-	if (local->monitors)
+-		new_flags |= FIF_CONTROL |
+-			     FIF_OTHER_BSS |
+-			     FIF_BCN_PRBRESP_PROMISC;
+-
+-	changed_flags = local->filter_flags ^ new_flags;
+-
+-	/* be a bit nasty */
+-	new_flags |= (1<<31);
+-
+-	local->ops->configure_filter(local_to_hw(local),
+-				     changed_flags, &new_flags,
+-				     local->mdev->mc_count,
+-				     local->mdev->mc_list);
+-
+-	WARN_ON(new_flags & (1<<31));
+-
+-	local->filter_flags = new_flags & ~(1<<31);
+-}
+-
+-/* master interface */
+-
+-static int ieee80211_master_open(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata;
+-	int res = -EOPNOTSUPP;
+-
+-	/* we hold the RTNL here so can safely walk the list */
+-	list_for_each_entry(sdata, &local->interfaces, list) {
+-		if (sdata->dev != dev && netif_running(sdata->dev)) {
+-			res = 0;
+-			break;
+-		}
+-	}
+-	return res;
+-}
+-
+-static int ieee80211_master_stop(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	/* we hold the RTNL here so can safely walk the list */
+-	list_for_each_entry(sdata, &local->interfaces, list)
+-		if (sdata->dev != dev && netif_running(sdata->dev))
+-			dev_close(sdata->dev);
+-
+-	return 0;
+-}
+-
+-static void ieee80211_master_set_multicast_list(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	ieee80211_configure_filter(local);
+-}
+-
+-/* regular interfaces */
+-
+-static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
+-{
+-	/* FIX: what would be proper limits for MTU?
+-	 * This interface uses 802.3 frames. */
+-	if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6) {
+-		printk(KERN_WARNING "%s: invalid MTU %d\n",
+-		       dev->name, new_mtu);
+-		return -EINVAL;
+-	}
+-
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+-	printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+-	dev->mtu = new_mtu;
+-	return 0;
+-}
+-
+-static inline int identical_mac_addr_allowed(int type1, int type2)
+-{
+-	return (type1 == IEEE80211_IF_TYPE_MNTR ||
+-		type2 == IEEE80211_IF_TYPE_MNTR ||
+-		(type1 == IEEE80211_IF_TYPE_AP &&
+-		 type2 == IEEE80211_IF_TYPE_WDS) ||
+-		(type1 == IEEE80211_IF_TYPE_WDS &&
+-		 (type2 == IEEE80211_IF_TYPE_WDS ||
+-		  type2 == IEEE80211_IF_TYPE_AP)) ||
+-		(type1 == IEEE80211_IF_TYPE_AP &&
+-		 type2 == IEEE80211_IF_TYPE_VLAN) ||
+-		(type1 == IEEE80211_IF_TYPE_VLAN &&
+-		 (type2 == IEEE80211_IF_TYPE_AP ||
+-		  type2 == IEEE80211_IF_TYPE_VLAN)));
+-}
+-
+-static int ieee80211_open(struct net_device *dev)
+-{
+-	struct ieee80211_sub_if_data *sdata, *nsdata;
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_if_init_conf conf;
+-	int res;
+-	bool need_hw_reconfig = 0;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	/* we hold the RTNL here so can safely walk the list */
+-	list_for_each_entry(nsdata, &local->interfaces, list) {
+-		struct net_device *ndev = nsdata->dev;
+-
+-		if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
+-		    compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0) {
+-			/*
+-			 * check whether it may have the same address
+-			 */
+-			if (!identical_mac_addr_allowed(sdata->vif.type,
+-							nsdata->vif.type))
+-				return -ENOTUNIQ;
+-
+-			/*
+-			 * can only add VLANs to enabled APs
+-			 */
+-			if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
+-			    nsdata->vif.type == IEEE80211_IF_TYPE_AP &&
+-			    netif_running(nsdata->dev))
+-				sdata->u.vlan.ap = nsdata;
+-		}
+-	}
+-
+-	switch (sdata->vif.type) {
+-	case IEEE80211_IF_TYPE_WDS:
+-		if (is_zero_ether_addr(sdata->u.wds.remote_addr))
+-			return -ENOLINK;
+-		break;
+-	case IEEE80211_IF_TYPE_VLAN:
+-		if (!sdata->u.vlan.ap)
+-			return -ENOLINK;
+-		break;
+-	case IEEE80211_IF_TYPE_AP:
+-	case IEEE80211_IF_TYPE_STA:
+-	case IEEE80211_IF_TYPE_MNTR:
+-	case IEEE80211_IF_TYPE_IBSS:
+-		/* no special treatment */
+-		break;
+-	case IEEE80211_IF_TYPE_INVALID:
+-		/* cannot happen */
+-		WARN_ON(1);
+-		break;
+-	}
+-
+-	if (local->open_count == 0) {
+-		res = 0;
+-		if (local->ops->start)
+-			res = local->ops->start(local_to_hw(local));
+-		if (res)
+-			return res;
+-		need_hw_reconfig = 1;
+-		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
+-	}
+-
+-	switch (sdata->vif.type) {
+-	case IEEE80211_IF_TYPE_VLAN:
+-		list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
+-		/* no need to tell driver */
+-		break;
+-	case IEEE80211_IF_TYPE_MNTR:
+-		/* must be before the call to ieee80211_configure_filter */
+-		local->monitors++;
+-		if (local->monitors == 1) {
+-			netif_tx_lock_bh(local->mdev);
+-			ieee80211_configure_filter(local);
+-			netif_tx_unlock_bh(local->mdev);
+-
+-			local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+-		}
+-		break;
+-	case IEEE80211_IF_TYPE_STA:
+-	case IEEE80211_IF_TYPE_IBSS:
+-		sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
+-		/* fall through */
+-	default:
+-		conf.vif = &sdata->vif;
+-		conf.type = sdata->vif.type;
+-		conf.mac_addr = dev->dev_addr;
+-		res = local->ops->add_interface(local_to_hw(local), &conf);
+-		if (res && !local->open_count && local->ops->stop)
+-			local->ops->stop(local_to_hw(local));
+-		if (res)
+-			return res;
+-
+-		ieee80211_if_config(dev);
+-		ieee80211_reset_erp_info(dev);
+-		ieee80211_enable_keys(sdata);
+-
+-		if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
+-		    !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
+-			netif_carrier_off(dev);
+-		else
+-			netif_carrier_on(dev);
+-	}
+-
+-	if (local->open_count == 0) {
+-		res = dev_open(local->mdev);
+-		WARN_ON(res);
+-		tasklet_enable(&local->tx_pending_tasklet);
+-		tasklet_enable(&local->tasklet);
+-	}
+-
+-	/*
+-	 * set_multicast_list will be invoked by the networking core
+-	 * which will check whether any increments here were done in
+-	 * error and sync them down to the hardware as filter flags.
+-	 */
+-	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
+-		atomic_inc(&local->iff_allmultis);
+-
+-	if (sdata->flags & IEEE80211_SDATA_PROMISC)
+-		atomic_inc(&local->iff_promiscs);
+-
+-	local->open_count++;
+-	if (need_hw_reconfig)
+-		ieee80211_hw_config(local);
+-
+-	/*
+-	 * ieee80211_sta_work is disabled while network interface
+-	 * is down. Therefore, some configuration changes may not
+-	 * yet be effective. Trigger execution of ieee80211_sta_work
+-	 * to fix this.
+-	 */
+-	if(sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-	   sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+-		struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-		queue_work(local->hw.workqueue, &ifsta->work);
+-	}
+-
+-	netif_start_queue(dev);
+-
+-	return 0;
+-}
+-
+-static int ieee80211_stop(struct net_device *dev)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_if_init_conf conf;
+-	struct sta_info *sta;
+-	int i;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	list_for_each_entry(sta, &local->sta_list, list) {
+-		if (sta->dev == dev)
+-			for (i = 0; i <  STA_TID_NUM; i++)
+-				ieee80211_sta_stop_rx_ba_session(sta->dev,
+-						sta->addr, i,
+-						WLAN_BACK_RECIPIENT,
+-						WLAN_REASON_QSTA_LEAVE_QBSS);
+-	}
+-
+-	netif_stop_queue(dev);
+-
+-	/*
+-	 * Don't count this interface for promisc/allmulti while it
+-	 * is down. dev_mc_unsync() will invoke set_multicast_list
+-	 * on the master interface which will sync these down to the
+-	 * hardware as filter flags.
+-	 */
+-	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
+-		atomic_dec(&local->iff_allmultis);
+-
+-	if (sdata->flags & IEEE80211_SDATA_PROMISC)
+-		atomic_dec(&local->iff_promiscs);
+-
+-	dev_mc_unsync(local->mdev, dev);
+-
+-	/* APs need special treatment */
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+-		struct ieee80211_sub_if_data *vlan, *tmp;
+-		struct beacon_data *old_beacon = sdata->u.ap.beacon;
+-
+-		/* remove beacon */
+-		rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+-		synchronize_rcu();
+-		kfree(old_beacon);
+-
+-		/* down all dependent devices, that is VLANs */
+-		list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
+-					 u.vlan.list)
+-			dev_close(vlan->dev);
+-		WARN_ON(!list_empty(&sdata->u.ap.vlans));
+-	}
+-
+-	local->open_count--;
+-
+-	switch (sdata->vif.type) {
+-	case IEEE80211_IF_TYPE_VLAN:
+-		list_del(&sdata->u.vlan.list);
+-		sdata->u.vlan.ap = NULL;
+-		/* no need to tell driver */
+-		break;
+-	case IEEE80211_IF_TYPE_MNTR:
+-		local->monitors--;
+-		if (local->monitors == 0) {
+-			netif_tx_lock_bh(local->mdev);
+-			ieee80211_configure_filter(local);
+-			netif_tx_unlock_bh(local->mdev);
+-
+-			local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+-		}
+-		break;
+-	case IEEE80211_IF_TYPE_STA:
+-	case IEEE80211_IF_TYPE_IBSS:
+-		sdata->u.sta.state = IEEE80211_DISABLED;
+-		del_timer_sync(&sdata->u.sta.timer);
+-		/*
+-		 * When we get here, the interface is marked down.
+-		 * Call synchronize_rcu() to wait for the RX path
+-		 * should it be using the interface and enqueuing
+-		 * frames at this very time on another CPU.
+-		 */
+-		synchronize_rcu();
+-		skb_queue_purge(&sdata->u.sta.skb_queue);
+-
+-		if (local->scan_dev == sdata->dev) {
+-			if (!local->ops->hw_scan) {
+-				local->sta_sw_scanning = 0;
+-				cancel_delayed_work(&local->scan_work);
+-			} else
+-				local->sta_hw_scanning = 0;
+-		}
+-
+-		flush_workqueue(local->hw.workqueue);
+-
+-		sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
+-		kfree(sdata->u.sta.extra_ie);
+-		sdata->u.sta.extra_ie = NULL;
+-		sdata->u.sta.extra_ie_len = 0;
+-		/* fall through */
+-	default:
+-		conf.vif = &sdata->vif;
+-		conf.type = sdata->vif.type;
+-		conf.mac_addr = dev->dev_addr;
+-		/* disable all keys for as long as this netdev is down */
+-		ieee80211_disable_keys(sdata);
+-		local->ops->remove_interface(local_to_hw(local), &conf);
+-	}
+-
+-	if (local->open_count == 0) {
+-		if (netif_running(local->mdev))
+-			dev_close(local->mdev);
+-
+-		if (local->ops->stop)
+-			local->ops->stop(local_to_hw(local));
+-
+-		ieee80211_led_radio(local, 0);
+-
+-		tasklet_disable(&local->tx_pending_tasklet);
+-		tasklet_disable(&local->tasklet);
+-	}
+-
+-	return 0;
+-}
+-
+-static void ieee80211_set_multicast_list(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	int allmulti, promisc, sdata_allmulti, sdata_promisc;
+-
+-	allmulti = !!(dev->flags & IFF_ALLMULTI);
+-	promisc = !!(dev->flags & IFF_PROMISC);
+-	sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
+-	sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
+-
+-	if (allmulti != sdata_allmulti) {
+-		if (dev->flags & IFF_ALLMULTI)
+-			atomic_inc(&local->iff_allmultis);
+-		else
+-			atomic_dec(&local->iff_allmultis);
+-		sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
+-	}
+-
+-	if (promisc != sdata_promisc) {
+-		if (dev->flags & IFF_PROMISC)
+-			atomic_inc(&local->iff_promiscs);
+-		else
+-			atomic_dec(&local->iff_promiscs);
+-		sdata->flags ^= IEEE80211_SDATA_PROMISC;
+-	}
+-
+-	dev_mc_sync(local->mdev, dev);
+-}
+-
+-static const struct header_ops ieee80211_header_ops = {
+-	.create		= eth_header,
+-	.parse		= header_parse_80211,
+-	.rebuild	= eth_rebuild_header,
+-	.cache		= eth_header_cache,
+-	.cache_update	= eth_header_cache_update,
+-};
+-
+-/* Must not be called for mdev */
+-void ieee80211_if_setup(struct net_device *dev)
+-{
+-	ether_setup(dev);
+-	dev->hard_start_xmit = ieee80211_subif_start_xmit;
+-	dev->wireless_handlers = &ieee80211_iw_handler_def;
+-	dev->set_multicast_list = ieee80211_set_multicast_list;
+-	dev->change_mtu = ieee80211_change_mtu;
+-	dev->open = ieee80211_open;
+-	dev->stop = ieee80211_stop;
+-	dev->destructor = ieee80211_if_free;
+-}
+-
+-/* WDS specialties */
+-
+-int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct sta_info *sta;
+-	DECLARE_MAC_BUF(mac);
+-
+-	if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
+-		return 0;
+-
+-	/* Create STA entry for the new peer */
+-	sta = sta_info_add(local, dev, remote_addr, GFP_KERNEL);
+-	if (!sta)
+-		return -ENOMEM;
+-	sta_info_put(sta);
+-
+-	/* Remove STA entry for the old peer */
+-	sta = sta_info_get(local, sdata->u.wds.remote_addr);
+-	if (sta) {
+-		sta_info_free(sta);
+-		sta_info_put(sta);
+-	} else {
+-		printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
+-		       "peer %s\n",
+-		       dev->name, print_mac(mac, sdata->u.wds.remote_addr));
+-	}
+-
+-	/* Update WDS link data */
+-	memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN);
+-
+-	return 0;
+-}
+-
+-/* everything else */
+-
+-static int __ieee80211_if_config(struct net_device *dev,
+-				 struct sk_buff *beacon,
+-				 struct ieee80211_tx_control *control)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_if_conf conf;
+-
+-	if (!local->ops->config_interface || !netif_running(dev))
+-		return 0;
+-
+-	memset(&conf, 0, sizeof(conf));
+-	conf.type = sdata->vif.type;
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+-		conf.bssid = sdata->u.sta.bssid;
+-		conf.ssid = sdata->u.sta.ssid;
+-		conf.ssid_len = sdata->u.sta.ssid_len;
+-	} else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+-		conf.ssid = sdata->u.ap.ssid;
+-		conf.ssid_len = sdata->u.ap.ssid_len;
+-		conf.beacon = beacon;
+-		conf.beacon_control = control;
+-	}
+-	return local->ops->config_interface(local_to_hw(local),
+-					    &sdata->vif, &conf);
+-}
+-
+-int ieee80211_if_config(struct net_device *dev)
+-{
+-	return __ieee80211_if_config(dev, NULL, NULL);
+-}
+-
+-int ieee80211_if_config_beacon(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_tx_control control;
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct sk_buff *skb;
+-
+-	if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
+-		return 0;
+-	skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif,
+-				   &control);
+-	if (!skb)
+-		return -ENOMEM;
+-	return __ieee80211_if_config(dev, skb, &control);
+-}
+-
+-int ieee80211_hw_config(struct ieee80211_local *local)
+-{
+-	struct ieee80211_hw_mode *mode;
+-	struct ieee80211_channel *chan;
+-	int ret = 0;
+-
+-	if (local->sta_sw_scanning) {
+-		chan = local->scan_channel;
+-		mode = local->scan_hw_mode;
+-	} else {
+-		chan = local->oper_channel;
+-		mode = local->oper_hw_mode;
+-	}
+-
+-	local->hw.conf.channel = chan->chan;
+-	local->hw.conf.channel_val = chan->val;
+-	if (!local->hw.conf.power_level) {
+-		local->hw.conf.power_level = chan->power_level;
+-	} else {
+-		local->hw.conf.power_level = min(chan->power_level,
+-						 local->hw.conf.power_level);
+-	}
+-	local->hw.conf.freq = chan->freq;
+-	local->hw.conf.phymode = mode->mode;
+-	local->hw.conf.antenna_max = chan->antenna_max;
+-	local->hw.conf.chan = chan;
+-	local->hw.conf.mode = mode;
+-
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+-	printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
+-	       "phymode=%d\n", local->hw.conf.channel, local->hw.conf.freq,
+-	       local->hw.conf.phymode);
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+-
+-	if (local->open_count)
+-		ret = local->ops->config(local_to_hw(local), &local->hw.conf);
+-
+-	return ret;
+-}
+-
+-/**
+- * ieee80211_hw_config_ht should be used only after legacy configuration
+- * has been determined, as ht configuration depends upon the hardware's
+- * HT abilities for a _specific_ band.
+- */
+-int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
+-			   struct ieee80211_ht_info *req_ht_cap,
+-			   struct ieee80211_ht_bss_info *req_bss_cap)
+-{
+-	struct ieee80211_conf *conf = &local->hw.conf;
+-	struct ieee80211_hw_mode *mode = conf->mode;
+-	int i;
+-
+-	/* HT is not supported */
+-	if (!mode->ht_info.ht_supported) {
+-		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
+-		return -EOPNOTSUPP;
+-	}
+-
+-	/* disable HT */
+-	if (!enable_ht) {
+-		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
+-	} else {
+-		conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
+-		conf->ht_conf.cap = req_ht_cap->cap & mode->ht_info.cap;
+-		conf->ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
+-		conf->ht_conf.cap |=
+-			mode->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
+-		conf->ht_bss_conf.primary_channel =
+-			req_bss_cap->primary_channel;
+-		conf->ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
+-		conf->ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
+-		for (i = 0; i < SUPP_MCS_SET_LEN; i++)
+-			conf->ht_conf.supp_mcs_set[i] =
+-				mode->ht_info.supp_mcs_set[i] &
+-				  req_ht_cap->supp_mcs_set[i];
+-
+-		/* In STA mode, this gives us indication
+-		 * to the AP's mode of operation */
+-		conf->ht_conf.ht_supported = 1;
+-		conf->ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
+-		conf->ht_conf.ampdu_density = req_ht_cap->ampdu_density;
+-	}
+-
+-	local->ops->conf_ht(local_to_hw(local), &local->hw.conf);
+-
+-	return 0;
+-}
+-
+-void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
+-				      u32 changed)
+-{
+-	struct ieee80211_local *local = sdata->local;
+-
+-	if (!changed)
+-		return;
+-
+-	if (local->ops->bss_info_changed)
+-		local->ops->bss_info_changed(local_to_hw(local),
+-					     &sdata->vif,
+-					     &sdata->bss_conf,
+-					     changed);
+-}
+-
+-void ieee80211_reset_erp_info(struct net_device *dev)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	sdata->bss_conf.use_cts_prot = 0;
+-	sdata->bss_conf.use_short_preamble = 0;
+-	ieee80211_bss_info_change_notify(sdata,
+-					 BSS_CHANGED_ERP_CTS_PROT |
+-					 BSS_CHANGED_ERP_PREAMBLE);
+-}
+-
+-void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+-				 struct sk_buff *skb,
+-				 struct ieee80211_tx_status *status)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-	struct ieee80211_tx_status *saved;
+-	int tmp;
+-
+-	skb->dev = local->mdev;
+-	saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC);
+-	if (unlikely(!saved)) {
+-		if (net_ratelimit())
+-			printk(KERN_WARNING "%s: Not enough memory, "
+-			       "dropping tx status", skb->dev->name);
+-		/* should be dev_kfree_skb_irq, but due to this function being
+-		 * named _irqsafe instead of just _irq we can't be sure that
+-		 * people won't call it from non-irq contexts */
+-		dev_kfree_skb_any(skb);
+-		return;
+-	}
+-	memcpy(saved, status, sizeof(struct ieee80211_tx_status));
+-	/* copy pointer to saved status into skb->cb for use by tasklet */
+-	memcpy(skb->cb, &saved, sizeof(saved));
+-
+-	skb->pkt_type = IEEE80211_TX_STATUS_MSG;
+-	skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
+-		       &local->skb_queue : &local->skb_queue_unreliable, skb);
+-	tmp = skb_queue_len(&local->skb_queue) +
+-		skb_queue_len(&local->skb_queue_unreliable);
+-	while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
+-	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
+-		memcpy(&saved, skb->cb, sizeof(saved));
+-		kfree(saved);
+-		dev_kfree_skb_irq(skb);
+-		tmp--;
+-		I802_DEBUG_INC(local->tx_status_drop);
+-	}
+-	tasklet_schedule(&local->tasklet);
+-}
+-EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
+-
+-static void ieee80211_tasklet_handler(unsigned long data)
+-{
+-	struct ieee80211_local *local = (struct ieee80211_local *) data;
+-	struct sk_buff *skb;
+-	struct ieee80211_rx_status rx_status;
+-	struct ieee80211_tx_status *tx_status;
+-
+-	while ((skb = skb_dequeue(&local->skb_queue)) ||
+-	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
+-		switch (skb->pkt_type) {
+-		case IEEE80211_RX_MSG:
+-			/* status is in skb->cb */
+-			memcpy(&rx_status, skb->cb, sizeof(rx_status));
+-			/* Clear skb->pkt_type in order to not confuse kernel
+-			 * netstack. */
+-			skb->pkt_type = 0;
+-			__ieee80211_rx(local_to_hw(local), skb, &rx_status);
+-			break;
+-		case IEEE80211_TX_STATUS_MSG:
+-			/* get pointer to saved status out of skb->cb */
+-			memcpy(&tx_status, skb->cb, sizeof(tx_status));
+-			skb->pkt_type = 0;
+-			ieee80211_tx_status(local_to_hw(local),
+-					    skb, tx_status);
+-			kfree(tx_status);
+-			break;
+-		default: /* should never get here! */
+-			printk(KERN_ERR "%s: Unknown message type (%d)\n",
+-			       wiphy_name(local->hw.wiphy), skb->pkt_type);
+-			dev_kfree_skb(skb);
+-			break;
+-		}
+-	}
+-}
+-
+-/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
+- * make a prepared TX frame (one that has been given to hw) to look like brand
+- * new IEEE 802.11 frame that is ready to go through TX processing again.
+- * Also, tx_packet_data in cb is restored from tx_control. */
+-static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
+-				      struct ieee80211_key *key,
+-				      struct sk_buff *skb,
+-				      struct ieee80211_tx_control *control)
+-{
+-	int hdrlen, iv_len, mic_len;
+-	struct ieee80211_tx_packet_data *pkt_data;
+-
+-	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+-	pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex;
+-	pkt_data->flags = 0;
+-	if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS)
+-		pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
+-	if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)
+-		pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
+-	if (control->flags & IEEE80211_TXCTL_REQUEUE)
+-		pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
+-	if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME)
+-		pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
+-	pkt_data->queue = control->queue;
+-
+-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+-
+-	if (!key)
+-		goto no_key;
+-
+-	switch (key->conf.alg) {
+-	case ALG_WEP:
+-		iv_len = WEP_IV_LEN;
+-		mic_len = WEP_ICV_LEN;
+-		break;
+-	case ALG_TKIP:
+-		iv_len = TKIP_IV_LEN;
+-		mic_len = TKIP_ICV_LEN;
+-		break;
+-	case ALG_CCMP:
+-		iv_len = CCMP_HDR_LEN;
+-		mic_len = CCMP_MIC_LEN;
+-		break;
+-	default:
+-		goto no_key;
+-	}
+-
+-	if (skb->len >= mic_len &&
+-	    !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
+-		skb_trim(skb, skb->len - mic_len);
+-	if (skb->len >= iv_len && skb->len > hdrlen) {
+-		memmove(skb->data + iv_len, skb->data, hdrlen);
+-		skb_pull(skb, iv_len);
+-	}
+-
+-no_key:
+-	{
+-		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-		u16 fc = le16_to_cpu(hdr->frame_control);
+-		if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
+-			fc &= ~IEEE80211_STYPE_QOS_DATA;
+-			hdr->frame_control = cpu_to_le16(fc);
+-			memmove(skb->data + 2, skb->data, hdrlen - 2);
+-			skb_pull(skb, 2);
+-		}
+-	}
+-}
+-
+-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
+-			 struct ieee80211_tx_status *status)
+-{
+-	struct sk_buff *skb2;
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-	struct ieee80211_local *local = hw_to_local(hw);
+-	u16 frag, type;
+-	struct ieee80211_tx_status_rtap_hdr *rthdr;
+-	struct ieee80211_sub_if_data *sdata;
+-	int monitors;
+-
+-	if (!status) {
+-		printk(KERN_ERR
+-		       "%s: ieee80211_tx_status called with NULL status\n",
+-		       wiphy_name(local->hw.wiphy));
+-		dev_kfree_skb(skb);
+-		return;
+-	}
+-
+-	if (status->excessive_retries) {
+-		struct sta_info *sta;
+-		sta = sta_info_get(local, hdr->addr1);
+-		if (sta) {
+-			if (sta->flags & WLAN_STA_PS) {
+-				/* The STA is in power save mode, so assume
+-				 * that this TX packet failed because of that.
+-				 */
+-				status->excessive_retries = 0;
+-				status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
+-			}
+-			sta_info_put(sta);
+-		}
+-	}
+-
+-	if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) {
+-		struct sta_info *sta;
+-		sta = sta_info_get(local, hdr->addr1);
+-		if (sta) {
+-			sta->tx_filtered_count++;
+-
+-			/* Clear the TX filter mask for this STA when sending
+-			 * the next packet. If the STA went to power save mode,
+-			 * this will happen when it is waking up for the next
+-			 * time. */
+-			sta->clear_dst_mask = 1;
+-
+-			/* TODO: Is the WLAN_STA_PS flag always set here or is
+-			 * the race between RX and TX status causing some
+-			 * packets to be filtered out before 80211.o gets an
+-			 * update for PS status? This seems to be the case, so
+-			 * no changes are likely to be needed. */
+-			if (sta->flags & WLAN_STA_PS &&
+-			    skb_queue_len(&sta->tx_filtered) <
+-			    STA_MAX_TX_BUFFER) {
+-				ieee80211_remove_tx_extra(local, sta->key,
+-							  skb,
+-							  &status->control);
+-				skb_queue_tail(&sta->tx_filtered, skb);
+-			} else if (!(sta->flags & WLAN_STA_PS) &&
+-				   !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
+-				/* Software retry the packet once */
+-				status->control.flags |= IEEE80211_TXCTL_REQUEUE;
+-				ieee80211_remove_tx_extra(local, sta->key,
+-							  skb,
+-							  &status->control);
+-				dev_queue_xmit(skb);
+-			} else {
+-				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),
+-					       !!(sta->flags & WLAN_STA_PS),
+-					       jiffies);
+-				}
+-				dev_kfree_skb(skb);
+-			}
+-			sta_info_put(sta);
+-			return;
+-		}
+-	} else
+-		rate_control_tx_status(local->mdev, skb, status);
+-
+-	ieee80211_led_tx(local, 0);
+-
+-	/* SNMP counters
+-	 * Fragments are passed to low-level drivers as separate skbs, so these
+-	 * are actually fragments, not frames. Update frame counters only for
+-	 * the first fragment of the frame. */
+-
+-	frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
+-	type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
+-
+-	if (status->flags & IEEE80211_TX_STATUS_ACK) {
+-		if (frag == 0) {
+-			local->dot11TransmittedFrameCount++;
+-			if (is_multicast_ether_addr(hdr->addr1))
+-				local->dot11MulticastTransmittedFrameCount++;
+-			if (status->retry_count > 0)
+-				local->dot11RetryCount++;
+-			if (status->retry_count > 1)
+-				local->dot11MultipleRetryCount++;
+-		}
+-
+-		/* This counter shall be incremented for an acknowledged MPDU
+-		 * with an individual address in the address 1 field or an MPDU
+-		 * with a multicast address in the address 1 field of type Data
+-		 * or Management. */
+-		if (!is_multicast_ether_addr(hdr->addr1) ||
+-		    type == IEEE80211_FTYPE_DATA ||
+-		    type == IEEE80211_FTYPE_MGMT)
+-			local->dot11TransmittedFragmentCount++;
+-	} else {
+-		if (frag == 0)
+-			local->dot11FailedCount++;
+-	}
+-
+-	/* this was a transmitted frame, but now we want to reuse it */
+-	skb_orphan(skb);
+-
+-	if (!local->monitors) {
+-		dev_kfree_skb(skb);
+-		return;
+-	}
+-
+-	/* send frame to monitor interfaces now */
+-
+-	if (skb_headroom(skb) < sizeof(*rthdr)) {
+-		printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
+-		dev_kfree_skb(skb);
+-		return;
+-	}
+-
+-	rthdr = (struct ieee80211_tx_status_rtap_hdr*)
+-				skb_push(skb, sizeof(*rthdr));
+-
+-	memset(rthdr, 0, sizeof(*rthdr));
+-	rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
+-	rthdr->hdr.it_present =
+-		cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
+-			    (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
+-
+-	if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&
+-	    !is_multicast_ether_addr(hdr->addr1))
+-		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
+-
+-	if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&
+-	    (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))
+-		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
+-	else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)
+-		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
+-
+-	rthdr->data_retries = status->retry_count;
+-
+-	rcu_read_lock();
+-	monitors = local->monitors;
+-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+-		/*
+-		 * Using the monitors counter is possibly racy, but
+-		 * if the value is wrong we simply either clone the skb
+-		 * once too much or forget sending it to one monitor iface
+-		 * The latter case isn't nice but fixing the race is much
+-		 * more complicated.
+-		 */
+-		if (!monitors || !skb)
+-			goto out;
+-
+-		if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) {
+-			if (!netif_running(sdata->dev))
+-				continue;
+-			monitors--;
+-			if (monitors)
+-				skb2 = skb_clone(skb, GFP_ATOMIC);
+-			else
+-				skb2 = NULL;
+-			skb->dev = sdata->dev;
+-			/* XXX: is this sufficient for BPF? */
+-			skb_set_mac_header(skb, 0);
+-			skb->ip_summed = CHECKSUM_UNNECESSARY;
+-			skb->pkt_type = PACKET_OTHERHOST;
+-			skb->protocol = htons(ETH_P_802_2);
+-			memset(skb->cb, 0, sizeof(skb->cb));
+-			netif_rx(skb);
+-			skb = skb2;
+-		}
+-	}
+- out:
+-	rcu_read_unlock();
+-	if (skb)
+-		dev_kfree_skb(skb);
+-}
+-EXPORT_SYMBOL(ieee80211_tx_status);
+-
+-struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+-					const struct ieee80211_ops *ops)
+-{
+-	struct net_device *mdev;
+-	struct ieee80211_local *local;
+-	struct ieee80211_sub_if_data *sdata;
+-	int priv_size;
+-	struct wiphy *wiphy;
+-
+-	/* Ensure 32-byte alignment of our private data and hw private data.
+-	 * We use the wiphy priv data for both our ieee80211_local and for
+-	 * the driver's private data
+-	 *
+-	 * In memory it'll be like this:
+-	 *
+-	 * +-------------------------+
+-	 * | struct wiphy	    |
+-	 * +-------------------------+
+-	 * | struct ieee80211_local  |
+-	 * +-------------------------+
+-	 * | driver's private data   |
+-	 * +-------------------------+
+-	 *
+-	 */
+-	priv_size = ((sizeof(struct ieee80211_local) +
+-		      NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
+-		    priv_data_len;
+-
+-	wiphy = wiphy_new(&mac80211_config_ops, priv_size);
+-
+-	if (!wiphy)
+-		return NULL;
+-
+-	wiphy->privid = mac80211_wiphy_privid;
+-
+-	local = wiphy_priv(wiphy);
+-	local->hw.wiphy = wiphy;
+-
+-	local->hw.priv = (char *)local +
+-			 ((sizeof(struct ieee80211_local) +
+-			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+-
+-	BUG_ON(!ops->tx);
+-	BUG_ON(!ops->start);
+-	BUG_ON(!ops->stop);
+-	BUG_ON(!ops->config);
+-	BUG_ON(!ops->add_interface);
+-	BUG_ON(!ops->remove_interface);
+-	BUG_ON(!ops->configure_filter);
+-	local->ops = ops;
+-
+-	/* for now, mdev needs sub_if_data :/ */
+-	mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
+-			    "wmaster%d", ether_setup);
+-	if (!mdev) {
+-		wiphy_free(wiphy);
+-		return NULL;
+-	}
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
+-	mdev->ieee80211_ptr = &sdata->wdev;
+-	sdata->wdev.wiphy = wiphy;
+-
+-	local->hw.queues = 1; /* default */
+-
+-	local->mdev = mdev;
+-	local->rx_pre_handlers = ieee80211_rx_pre_handlers;
+-	local->rx_handlers = ieee80211_rx_handlers;
+-	local->tx_handlers = ieee80211_tx_handlers;
+-
+-	local->bridge_packets = 1;
+-
+-	local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+-	local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+-	local->short_retry_limit = 7;
+-	local->long_retry_limit = 4;
+-	local->hw.conf.radio_enabled = 1;
+-
+-	local->enabled_modes = ~0;
+-
+-	INIT_LIST_HEAD(&local->modes_list);
+-
+-	INIT_LIST_HEAD(&local->interfaces);
+-
+-	INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
+-	ieee80211_rx_bss_list_init(mdev);
+-
+-	sta_info_init(local);
+-
+-	mdev->hard_start_xmit = ieee80211_master_start_xmit;
+-	mdev->open = ieee80211_master_open;
+-	mdev->stop = ieee80211_master_stop;
+-	mdev->type = ARPHRD_IEEE80211;
+-	mdev->header_ops = &ieee80211_header_ops;
+-	mdev->set_multicast_list = ieee80211_master_set_multicast_list;
+-
+-	sdata->vif.type = IEEE80211_IF_TYPE_AP;
+-	sdata->dev = mdev;
+-	sdata->local = local;
+-	sdata->u.ap.force_unicast_rateidx = -1;
+-	sdata->u.ap.max_ratectrl_rateidx = -1;
+-	ieee80211_if_sdata_init(sdata);
+-	/* no RCU needed since we're still during init phase */
+-	list_add_tail(&sdata->list, &local->interfaces);
+-
+-	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
+-		     (unsigned long)local);
+-	tasklet_disable(&local->tx_pending_tasklet);
+-
+-	tasklet_init(&local->tasklet,
+-		     ieee80211_tasklet_handler,
+-		     (unsigned long) local);
+-	tasklet_disable(&local->tasklet);
+-
+-	skb_queue_head_init(&local->skb_queue);
+-	skb_queue_head_init(&local->skb_queue_unreliable);
+-
+-	return local_to_hw(local);
+-}
+-EXPORT_SYMBOL(ieee80211_alloc_hw);
+-
+-int ieee80211_register_hw(struct ieee80211_hw *hw)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-	const char *name;
+-	int result;
+-
+-	result = wiphy_register(local->hw.wiphy);
+-	if (result < 0)
+-		return result;
+-
+-	name = wiphy_dev(local->hw.wiphy)->driver->name;
+-	local->hw.workqueue = create_singlethread_workqueue(name);
+-	if (!local->hw.workqueue) {
+-		result = -ENOMEM;
+-		goto fail_workqueue;
+-	}
+-
+-	/*
+-	 * The hardware needs headroom for sending the frame,
+-	 * and we need some headroom for passing the frame to monitor
+-	 * interfaces, but never both at the same time.
+-	 */
+-	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
+-				   sizeof(struct ieee80211_tx_status_rtap_hdr));
+-
+-	debugfs_hw_add(local);
+-
+-	local->hw.conf.beacon_int = 1000;
+-
+-	local->wstats_flags |= local->hw.max_rssi ?
+-			       IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
+-	local->wstats_flags |= local->hw.max_signal ?
+-			       IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
+-	local->wstats_flags |= local->hw.max_noise ?
+-			       IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
+-	if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
+-		local->wstats_flags |= IW_QUAL_DBM;
+-
+-	result = sta_info_start(local);
+-	if (result < 0)
+-		goto fail_sta_info;
+-
+-	rtnl_lock();
+-	result = dev_alloc_name(local->mdev, local->mdev->name);
+-	if (result < 0)
+-		goto fail_dev;
+-
+-	memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+-	SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
+-
+-	result = register_netdevice(local->mdev);
+-	if (result < 0)
+-		goto fail_dev;
+-
+-	ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
+-	ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
+-
+-	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));
+-		goto fail_rate;
+-	}
+-
+-	result = ieee80211_wep_init(local);
+-
+-	if (result < 0) {
+-		printk(KERN_DEBUG "%s: Failed to initialize wep\n",
+-		       wiphy_name(local->hw.wiphy));
+-		goto fail_wep;
+-	}
+-
+-	ieee80211_install_qdisc(local->mdev);
+-
+-	/* add one default STA interface */
+-	result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
+-				  IEEE80211_IF_TYPE_STA);
+-	if (result)
+-		printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
+-		       wiphy_name(local->hw.wiphy));
+-
+-	local->reg_state = IEEE80211_DEV_REGISTERED;
+-	rtnl_unlock();
+-
+-	ieee80211_led_init(local);
+-
+-	return 0;
+-
+-fail_wep:
+-	rate_control_deinitialize(local);
+-fail_rate:
+-	ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
+-	unregister_netdevice(local->mdev);
+-fail_dev:
+-	rtnl_unlock();
+-	sta_info_stop(local);
+-fail_sta_info:
+-	debugfs_hw_del(local);
+-	destroy_workqueue(local->hw.workqueue);
+-fail_workqueue:
+-	wiphy_unregister(local->hw.wiphy);
+-	return result;
+-}
+-EXPORT_SYMBOL(ieee80211_register_hw);
+-
+-int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+-			      struct ieee80211_hw_mode *mode)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-	struct ieee80211_rate *rate;
+-	int i;
+-
+-	INIT_LIST_HEAD(&mode->list);
+-	list_add_tail(&mode->list, &local->modes_list);
+-
+-	local->hw_modes |= (1 << mode->mode);
+-	for (i = 0; i < mode->num_rates; i++) {
+-		rate = &(mode->rates[i]);
+-		rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate;
+-	}
+-	ieee80211_prepare_rates(local, mode);
+-
+-	if (!local->oper_hw_mode) {
+-		/* Default to this mode */
+-		local->hw.conf.phymode = mode->mode;
+-		local->oper_hw_mode = local->scan_hw_mode = mode;
+-		local->oper_channel = local->scan_channel = &mode->channels[0];
+-		local->hw.conf.mode = local->oper_hw_mode;
+-		local->hw.conf.chan = local->oper_channel;
+-	}
+-
+-	if (!(hw->flags & IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED))
+-		ieee80211_set_default_regdomain(mode);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL(ieee80211_register_hwmode);
+-
+-void ieee80211_unregister_hw(struct ieee80211_hw *hw)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-	struct ieee80211_sub_if_data *sdata, *tmp;
+-	int i;
+-
+-	tasklet_kill(&local->tx_pending_tasklet);
+-	tasklet_kill(&local->tasklet);
+-
+-	rtnl_lock();
+-
+-	BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
+-
+-	local->reg_state = IEEE80211_DEV_UNREGISTERED;
+-
+-	/*
+-	 * At this point, interface list manipulations are fine
+-	 * because the driver cannot be handing us frames any
+-	 * more and the tasklet is killed.
+-	 */
+-
+-	/*
+-	 * First, we remove all non-master interfaces. Do this because they
+-	 * may have bss pointer dependency on the master, and when we free
+-	 * the master these would be freed as well, breaking our list
+-	 * iteration completely.
+-	 */
+-	list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
+-		if (sdata->dev == local->mdev)
+-			continue;
+-		list_del(&sdata->list);
+-		__ieee80211_if_del(local, sdata);
+-	}
+-
+-	/* then, finally, remove the master interface */
+-	__ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
+-
+-	rtnl_unlock();
+-
+-	ieee80211_rx_bss_list_deinit(local->mdev);
+-	ieee80211_clear_tx_pending(local);
+-	sta_info_stop(local);
+-	rate_control_deinitialize(local);
+-	debugfs_hw_del(local);
+-
+-	for (i = 0; i < NUM_IEEE80211_MODES; i++) {
+-		kfree(local->supp_rates[i]);
+-		kfree(local->basic_rates[i]);
+-	}
+-
+-	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));
+-	skb_queue_purge(&local->skb_queue);
+-	skb_queue_purge(&local->skb_queue_unreliable);
+-
+-	destroy_workqueue(local->hw.workqueue);
+-	wiphy_unregister(local->hw.wiphy);
+-	ieee80211_wep_free(local);
+-	ieee80211_led_exit(local);
+-}
+-EXPORT_SYMBOL(ieee80211_unregister_hw);
+-
+-void ieee80211_free_hw(struct ieee80211_hw *hw)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-
+-	ieee80211_if_free(local->mdev);
+-	wiphy_free(local->hw.wiphy);
+-}
+-EXPORT_SYMBOL(ieee80211_free_hw);
+-
+-static int __init ieee80211_init(void)
+-{
+-	struct sk_buff *skb;
+-	int ret;
+-
+-	BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
+-
+-	ret = rc80211_simple_init();
+-	if (ret)
+-		goto out;
+-
+-	ret = rc80211_pid_init();
+-	if (ret)
+-		goto out_cleanup_simple;
+-
+-	ret = ieee80211_wme_register();
+-	if (ret) {
+-		printk(KERN_DEBUG "ieee80211_init: failed to "
+-		       "initialize WME (err=%d)\n", ret);
+-		goto out_cleanup_pid;
+-	}
+-
+-	ieee80211_debugfs_netdev_init();
+-	ieee80211_regdomain_init();
+-
+-	return 0;
+-
+- out_cleanup_pid:
+-	rc80211_pid_exit();
+- out_cleanup_simple:
+-	rc80211_simple_exit();
+- out:
+-	return ret;
+-}
+-
+-static void __exit ieee80211_exit(void)
+-{
+-	rc80211_simple_exit();
+-	rc80211_pid_exit();
+-
+-	ieee80211_wme_unregister();
+-	ieee80211_debugfs_netdev_exit();
+-}
+-
+-
+-subsys_initcall(ieee80211_init);
+-module_exit(ieee80211_exit);
+-
+-MODULE_DESCRIPTION("IEEE 802.11 subsystem");
+-MODULE_LICENSE("GPL");
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index 72ecbf7..8e53ce7 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -23,7 +23,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/etherdevice.h>
+ #include <net/wireless.h>
+-#include "ieee80211_key.h"
++#include "key.h"
+ #include "sta_info.h"
+ 
+ /* ieee80211.o internal definitions, etc. These are not included into
+@@ -35,9 +35,9 @@
+ 
+ #define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08)
+ 
+-struct ieee80211_local;
++#define IEEE80211_FC(type, subtype) cpu_to_le16(type | subtype)
+ 
+-#define IEEE80211_ALIGN32_PAD(a) ((4 - ((a) & 3)) & 3)
++struct ieee80211_local;
+ 
+ /* Maximum number of broadcast/multicast frames to buffer when some of the
+  * associated stations are using power saving. */
+@@ -73,14 +73,14 @@ struct ieee80211_fragment_entry {
+ struct ieee80211_sta_bss {
+ 	struct list_head list;
+ 	struct ieee80211_sta_bss *hnext;
++	size_t ssid_len;
++
+ 	atomic_t users;
+ 
+ 	u8 bssid[ETH_ALEN];
+ 	u8 ssid[IEEE80211_MAX_SSID_LEN];
+-	size_t ssid_len;
+ 	u16 capability; /* host byte order */
+-	int hw_mode;
+-	int channel;
++	enum ieee80211_band band;
+ 	int freq;
+ 	int rssi, signal, noise;
+ 	u8 *wpa_ie;
+@@ -91,13 +91,18 @@ struct ieee80211_sta_bss {
+ 	size_t wmm_ie_len;
+ 	u8 *ht_ie;
+ 	size_t ht_ie_len;
++#ifdef CONFIG_MAC80211_MESH
++	u8 *mesh_id;
++	size_t mesh_id_len;
++	u8 *mesh_cfg;
++#endif
+ #define IEEE80211_MAX_SUPP_RATES 32
+ 	u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+ 	size_t supp_rates_len;
+-	int beacon_int;
+ 	u64 timestamp;
++	int beacon_int;
+ 
+-	int probe_resp;
++	bool probe_resp;
+ 	unsigned long last_update;
+ 
+ 	/* during assocation, we save an ERP value from a probe response so
+@@ -108,56 +113,98 @@ struct ieee80211_sta_bss {
+ 	u8 erp_value;
+ };
+ 
++static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss)
++{
++#ifdef CONFIG_MAC80211_MESH
++	return bss->mesh_cfg;
++#endif
++	return NULL;
++}
+ 
+-typedef enum {
+-	TXRX_CONTINUE, TXRX_DROP, TXRX_QUEUED
+-} ieee80211_txrx_result;
++static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss)
++{
++#ifdef CONFIG_MAC80211_MESH
++	return bss->mesh_id;
++#endif
++	return NULL;
++}
+ 
+-/* flags used in struct ieee80211_txrx_data.flags */
+-/* whether the MSDU was fragmented */
+-#define IEEE80211_TXRXD_FRAGMENTED		BIT(0)
+-#define IEEE80211_TXRXD_TXUNICAST		BIT(1)
+-#define IEEE80211_TXRXD_TXPS_BUFFERED		BIT(2)
+-#define IEEE80211_TXRXD_TXPROBE_LAST_FRAG	BIT(3)
+-#define IEEE80211_TXRXD_RXIN_SCAN		BIT(4)
+-/* frame is destined to interface currently processed (incl. multicast frames) */
+-#define IEEE80211_TXRXD_RXRA_MATCH		BIT(5)
+-#define IEEE80211_TXRXD_TX_INJECTED		BIT(6)
+-#define IEEE80211_TXRXD_RX_AMSDU		BIT(7)
+-struct ieee80211_txrx_data {
++static inline u8 bss_mesh_id_len(struct ieee80211_sta_bss *bss)
++{
++#ifdef CONFIG_MAC80211_MESH
++	return bss->mesh_id_len;
++#endif
++	return 0;
++}
++
++
++typedef unsigned __bitwise__ ieee80211_tx_result;
++#define TX_CONTINUE	((__force ieee80211_tx_result) 0u)
++#define TX_DROP		((__force ieee80211_tx_result) 1u)
++#define TX_QUEUED	((__force ieee80211_tx_result) 2u)
++
++#define IEEE80211_TX_FRAGMENTED		BIT(0)
++#define IEEE80211_TX_UNICAST		BIT(1)
++#define IEEE80211_TX_PS_BUFFERED	BIT(2)
++#define IEEE80211_TX_PROBE_LAST_FRAG	BIT(3)
++#define IEEE80211_TX_INJECTED		BIT(4)
++
++struct ieee80211_tx_data {
+ 	struct sk_buff *skb;
+ 	struct net_device *dev;
+ 	struct ieee80211_local *local;
+ 	struct ieee80211_sub_if_data *sdata;
+ 	struct sta_info *sta;
++	struct ieee80211_key *key;
++
++	struct ieee80211_tx_control *control;
++	struct ieee80211_channel *channel;
++	struct ieee80211_rate *rate;
++	/* use this rate (if set) for last fragment; rate can
++	 * be set to lower rate for the first fragments, e.g.,
++	 * when using CTS protection with IEEE 802.11g. */
++	struct ieee80211_rate *last_frag_rate;
++
++	/* Extra fragments (in addition to the first fragment
++	 * in skb) */
++	struct sk_buff **extra_frag;
++	int num_extra_frag;
++
+ 	u16 fc, ethertype;
++	unsigned int flags;
++};
++
++
++typedef unsigned __bitwise__ ieee80211_rx_result;
++#define RX_CONTINUE		((__force ieee80211_rx_result) 0u)
++#define RX_DROP_UNUSABLE	((__force ieee80211_rx_result) 1u)
++#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_CMNTR_REPORTED	BIT(3)
++#define IEEE80211_RX_FRAGMENTED		BIT(4)
++
++struct ieee80211_rx_data {
++	struct sk_buff *skb;
++	struct net_device *dev;
++	struct ieee80211_local *local;
++	struct ieee80211_sub_if_data *sdata;
++	struct sta_info *sta;
+ 	struct ieee80211_key *key;
++	struct ieee80211_rx_status *status;
++	struct ieee80211_rate *rate;
++
++	u16 fc, ethertype;
+ 	unsigned int flags;
+-	union {
+-		struct {
+-			struct ieee80211_tx_control *control;
+-			struct ieee80211_hw_mode *mode;
+-			struct ieee80211_rate *rate;
+-			/* use this rate (if set) for last fragment; rate can
+-			 * be set to lower rate for the first fragments, e.g.,
+-			 * when using CTS protection with IEEE 802.11g. */
+-			struct ieee80211_rate *last_frag_rate;
+-			int last_frag_hwrate;
+-
+-			/* Extra fragments (in addition to the first fragment
+-			 * in skb) */
+-			int num_extra_frag;
+-			struct sk_buff **extra_frag;
+-		} tx;
+-		struct {
+-			struct ieee80211_rx_status *status;
+-			int sent_ps_buffered;
+-			int queue;
+-			int load;
+-			u32 tkip_iv32;
+-			u16 tkip_iv16;
+-		} rx;
+-	} u;
++	int sent_ps_buffered;
++	int queue;
++	int load;
++	u32 tkip_iv32;
++	u16 tkip_iv16;
+ };
+ 
+ /* flags used in struct ieee80211_tx_packet_data.flags */
+@@ -165,6 +212,7 @@ struct ieee80211_txrx_data {
+ #define IEEE80211_TXPD_DO_NOT_ENCRYPT	BIT(1)
+ #define IEEE80211_TXPD_REQUEUE		BIT(2)
+ #define IEEE80211_TXPD_EAPOL_FRAME	BIT(3)
++#define IEEE80211_TXPD_AMPDU		BIT(4)
+ /* Stored in sk_buff->cb */
+ struct ieee80211_tx_packet_data {
+ 	int ifindex;
+@@ -176,20 +224,12 @@ struct ieee80211_tx_packet_data {
+ struct ieee80211_tx_stored_packet {
+ 	struct ieee80211_tx_control control;
+ 	struct sk_buff *skb;
+-	int num_extra_frag;
+ 	struct sk_buff **extra_frag;
+-	int last_frag_rateidx;
+-	int last_frag_hwrate;
+ 	struct ieee80211_rate *last_frag_rate;
++	int num_extra_frag;
+ 	unsigned int last_frag_rate_ctrl_probe;
+ };
+ 
+-typedef ieee80211_txrx_result (*ieee80211_tx_handler)
+-(struct ieee80211_txrx_data *tx);
+-
+-typedef ieee80211_txrx_result (*ieee80211_rx_handler)
+-(struct ieee80211_txrx_data *rx);
+-
+ struct beacon_data {
+ 	u8 *head, *tail;
+ 	int head_len, tail_len;
+@@ -206,10 +246,10 @@ struct ieee80211_if_ap {
+ 
+ 	/* yes, this looks ugly, but guarantees that we can later use
+ 	 * bitmap_empty :)
+-	 * NB: don't ever use set_bit, use bss_tim_set/bss_tim_clear! */
++	 * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */
+ 	u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
+-	atomic_t num_sta_ps; /* number of stations in PS mode */
+ 	struct sk_buff_head ps_bc_buf;
++	atomic_t num_sta_ps; /* number of stations in PS mode */
+ 	int dtim_count;
+ 	int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
+ 	int max_ratectrl_rateidx; /* max TX rateidx for rate control */
+@@ -217,8 +257,8 @@ struct ieee80211_if_ap {
+ };
+ 
+ struct ieee80211_if_wds {
+-	u8 remote_addr[ETH_ALEN];
+ 	struct sta_info *sta;
++	u8 remote_addr[ETH_ALEN];
+ };
+ 
+ struct ieee80211_if_vlan {
+@@ -226,6 +266,41 @@ struct ieee80211_if_vlan {
+ 	struct list_head list;
+ };
+ 
++struct mesh_stats {
++	__u32 fwded_frames;		/* Mesh forwarded frames */
++	__u32 dropped_frames_ttl;	/* Not transmitted since mesh_ttl == 0*/
++	__u32 dropped_frames_no_route;	/* Not transmitted, no route found */
++	atomic_t estab_plinks;
++};
++
++#define PREQ_Q_F_START		0x1
++#define PREQ_Q_F_REFRESH	0x2
++struct mesh_preq_queue {
++	struct list_head list;
++	u8 dst[ETH_ALEN];
++	u8 flags;
++};
++
++struct mesh_config {
++	/* Timeouts in ms */
++	/* Mesh plink management parameters */
++	u16 dot11MeshRetryTimeout;
++	u16 dot11MeshConfirmTimeout;
++	u16 dot11MeshHoldingTimeout;
++	u16 dot11MeshMaxPeerLinks;
++	u8  dot11MeshMaxRetries;
++	u8  dot11MeshTTL;
++	bool auto_open_plinks;
++	/* HWMP parameters */
++	u8  dot11MeshHWMPmaxPREQretries;
++	u32 path_refresh_time;
++	u16 min_discovery_timeout;
++	u32 dot11MeshHWMPactivePathTimeout;
++	u16 dot11MeshHWMPpreqMinInterval;
++	u16 dot11MeshHWMPnetDiameterTraversalTime;
++};
++
++
+ /* flags used in struct ieee80211_if_sta.flags */
+ #define IEEE80211_STA_SSID_SET		BIT(0)
+ #define IEEE80211_STA_BSSID_SET		BIT(1)
+@@ -241,18 +316,47 @@ struct ieee80211_if_vlan {
+ #define IEEE80211_STA_AUTO_CHANNEL_SEL	BIT(12)
+ #define IEEE80211_STA_PRIVACY_INVOKED	BIT(13)
+ struct ieee80211_if_sta {
+-	enum {
+-		IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
+-		IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
+-		IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED
+-	} state;
+ 	struct timer_list timer;
+ 	struct work_struct work;
+ 	u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
+ 	u8 ssid[IEEE80211_MAX_SSID_LEN];
++	enum {
++		IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
++		IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
++		IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED,
++		IEEE80211_MESH_UP
++	} state;
+ 	size_t ssid_len;
+ 	u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
+ 	size_t scan_ssid_len;
++#ifdef CONFIG_MAC80211_MESH
++	struct timer_list mesh_path_timer;
++	u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
++	size_t mesh_id_len;
++	/* Active Path Selection Protocol Identifier */
++	u8 mesh_pp_id[4];
++	/* Active Path Selection Metric Identifier */
++	u8 mesh_pm_id[4];
++	/* Congestion Control Mode Identifier */
++	u8 mesh_cc_id[4];
++	/* Local mesh Destination Sequence Number */
++	u32 dsn;
++	/* Last used PREQ ID */
++	u32 preq_id;
++	atomic_t mpaths;
++	/* Timestamp of last DSN update */
++	unsigned long last_dsn_update;
++	/* Timestamp of last DSN sent */
++	unsigned long last_preq;
++	struct mesh_rmc *rmc;
++	spinlock_t mesh_preq_queue_lock;
++	struct mesh_preq_queue preq_queue;
++	int preq_queue_len;
++	struct mesh_stats mshstats;
++	struct mesh_config mshcfg;
++	u8 mesh_seqnum[3];
++	bool accepting_plinks;
++#endif
+ 	u16 aid;
+ 	u16 ap_capab, capab;
+ 	u8 *extra_ie; /* to be added to the end of AssocReq */
+@@ -262,16 +366,18 @@ struct ieee80211_if_sta {
+ 	u8 *assocreq_ies, *assocresp_ies;
+ 	size_t assocreq_ies_len, assocresp_ies_len;
+ 
++	struct sk_buff_head skb_queue;
++
+ 	int auth_tries, assoc_tries;
+ 
++	unsigned long request;
++
++	unsigned long last_probe;
++
+ 	unsigned int flags;
+ #define IEEE80211_STA_REQ_SCAN 0
+ #define IEEE80211_STA_REQ_AUTH 1
+ #define IEEE80211_STA_REQ_RUN  2
+-	unsigned long request;
+-	struct sk_buff_head skb_queue;
+-
+-	unsigned long last_probe;
+ 
+ #define IEEE80211_AUTH_ALG_OPEN BIT(0)
+ #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
+@@ -282,16 +388,34 @@ struct ieee80211_if_sta {
+ 
+ 	unsigned long ibss_join_req;
+ 	struct sk_buff *probe_resp; /* ProbeResp template for IBSS */
+-	u32 supp_rates_bits;
++	u32 supp_rates_bits[IEEE80211_NUM_BANDS];
+ 
+ 	int wmm_last_param_set;
++	int num_beacons; /* number of TXed beacon frames by this STA */
+ };
+ 
++static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta,
++						u8 mesh_id_len, u8 *mesh_id)
++{
++#ifdef CONFIG_MAC80211_MESH
++	ifsta->mesh_id_len = mesh_id_len;
++	memcpy(ifsta->mesh_id, mesh_id, mesh_id_len);
++#endif
++}
++
++#ifdef CONFIG_MAC80211_MESH
++#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name)	\
++	do { (sta)->mshstats.name++; } while (0)
++#else
++#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \
++	do { } while (0)
++#endif
+ 
+ /* flags used in struct ieee80211_sub_if_data.flags */
+ #define IEEE80211_SDATA_ALLMULTI	BIT(0)
+ #define IEEE80211_SDATA_PROMISC		BIT(1)
+ #define IEEE80211_SDATA_USERSPACE_MLME	BIT(2)
++#define IEEE80211_SDATA_OPERATING_GMODE	BIT(3)
+ struct ieee80211_sub_if_data {
+ 	struct list_head list;
+ 
+@@ -306,11 +430,11 @@ struct ieee80211_sub_if_data {
+ 	unsigned int flags;
+ 
+ 	int drop_unencrypted;
++
+ 	/*
+-	 * IEEE 802.1X Port access control in effect,
+-	 * drop packets to/from unauthorized port
++	 * basic rates of this AP or the AP we're associated to
+ 	 */
+-	int ieee802_1x_pac;
++	u64 basic_rates;
+ 
+ 	u16 sequence;
+ 
+@@ -338,6 +462,7 @@ struct ieee80211_sub_if_data {
+ 		struct ieee80211_if_wds wds;
+ 		struct ieee80211_if_vlan vlan;
+ 		struct ieee80211_if_sta sta;
++		u32 mntr_flags;
+ 	} u;
+ 	int channel_use;
+ 	int channel_use_raw;
+@@ -348,7 +473,6 @@ struct ieee80211_sub_if_data {
+ 		struct {
+ 			struct dentry *channel_use;
+ 			struct dentry *drop_unencrypted;
+-			struct dentry *ieee802_1x_pac;
+ 			struct dentry *state;
+ 			struct dentry *bssid;
+ 			struct dentry *prev_bssid;
+@@ -363,11 +487,11 @@ struct ieee80211_sub_if_data {
+ 			struct dentry *auth_alg;
+ 			struct dentry *auth_transaction;
+ 			struct dentry *flags;
++			struct dentry *num_beacons_sta;
+ 		} sta;
+ 		struct {
+ 			struct dentry *channel_use;
+ 			struct dentry *drop_unencrypted;
+-			struct dentry *ieee802_1x_pac;
+ 			struct dentry *num_sta_ps;
+ 			struct dentry *dtim_count;
+ 			struct dentry *num_beacons;
+@@ -378,19 +502,46 @@ struct ieee80211_sub_if_data {
+ 		struct {
+ 			struct dentry *channel_use;
+ 			struct dentry *drop_unencrypted;
+-			struct dentry *ieee802_1x_pac;
+ 			struct dentry *peer;
+ 		} wds;
+ 		struct {
+ 			struct dentry *channel_use;
+ 			struct dentry *drop_unencrypted;
+-			struct dentry *ieee802_1x_pac;
+ 		} vlan;
+ 		struct {
+ 			struct dentry *mode;
+ 		} monitor;
+ 		struct dentry *default_key;
+ 	} debugfs;
++
++#ifdef CONFIG_MAC80211_MESH
++	struct dentry *mesh_stats_dir;
++	struct {
++		struct dentry *fwded_frames;
++		struct dentry *dropped_frames_ttl;
++		struct dentry *dropped_frames_no_route;
++		struct dentry *estab_plinks;
++		struct timer_list mesh_path_timer;
++	} mesh_stats;
++
++	struct dentry *mesh_config_dir;
++	struct {
++		struct dentry *dot11MeshRetryTimeout;
++		struct dentry *dot11MeshConfirmTimeout;
++		struct dentry *dot11MeshHoldingTimeout;
++		struct dentry *dot11MeshMaxRetries;
++		struct dentry *dot11MeshTTL;
++		struct dentry *auto_open_plinks;
++		struct dentry *dot11MeshMaxPeerLinks;
++		struct dentry *dot11MeshHWMPactivePathTimeout;
++		struct dentry *dot11MeshHWMPpreqMinInterval;
++		struct dentry *dot11MeshHWMPnetDiameterTraversalTime;
++		struct dentry *dot11MeshHWMPmaxPREQretries;
++		struct dentry *path_refresh_time;
++		struct dentry *min_discovery_timeout;
++	} mesh_config;
++#endif
++
+ #endif
+ 	/* must be last, dynamically sized area in this! */
+ 	struct ieee80211_vif vif;
+@@ -407,6 +558,8 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
+ enum {
+ 	IEEE80211_RX_MSG	= 1,
+ 	IEEE80211_TX_STATUS_MSG	= 2,
++	IEEE80211_DELBA_MSG	= 3,
++	IEEE80211_ADDBA_MSG	= 4,
+ };
+ 
+ struct ieee80211_local {
+@@ -417,15 +570,15 @@ struct ieee80211_local {
+ 
+ 	const struct ieee80211_ops *ops;
+ 
+-	/* List of registered struct ieee80211_hw_mode */
+-	struct list_head modes_list;
+-
+ 	struct net_device *mdev; /* wmaster# - "master" 802.11 device */
+ 	int open_count;
+-	int monitors;
++	int monitors, cooked_mntrs;
++	/* number of interfaces with corresponding FIF_ flags */
++	int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss;
+ 	unsigned int filter_flags; /* FIF_* */
+ 	struct iw_statistics wstats;
+ 	u8 wstats_flags;
++	bool tim_in_locked_section; /* see ieee80211_beacon_get() */
+ 	int tx_headroom; /* required headroom for hardware/radiotap */
+ 
+ 	enum {
+@@ -443,15 +596,22 @@ struct ieee80211_local {
+ 	struct sk_buff_head skb_queue;
+ 	struct sk_buff_head skb_queue_unreliable;
+ 
+-	/* Station data structures */
+-	rwlock_t sta_lock; /* protects STA data structures */
+-	int num_sta; /* number of stations in sta_list */
++	/* Station data */
++	/*
++	 * The lock only protects the list, hash, timer and counter
++	 * against manipulation, reads are done in RCU. Additionally,
++	 * the lock protects each BSS's TIM bitmap.
++	 */
++	spinlock_t sta_lock;
++	unsigned long num_sta;
+ 	struct list_head sta_list;
++	struct list_head sta_flush_list;
++	struct work_struct sta_flush_work;
+ 	struct sta_info *sta_hash[STA_HASH_SIZE];
+ 	struct timer_list sta_cleanup;
+ 
+-	unsigned long state[NUM_TX_DATA_QUEUES];
+-	struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES];
++	unsigned long state[NUM_TX_DATA_QUEUES_AMPDU];
++	struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES_AMPDU];
+ 	struct tasklet_struct tx_pending_tasklet;
+ 
+ 	/* number of interfaces with corresponding IFF_ flags */
+@@ -459,11 +619,6 @@ struct ieee80211_local {
+ 
+ 	struct rate_control_ref *rate_ctrl;
+ 
+-	/* Supported and basic rate filters for different modes. These are
+-	 * pointers to -1 terminated lists and rates in 100 kbps units. */
+-	int *supp_rates[NUM_IEEE80211_MODES];
+-	int *basic_rates[NUM_IEEE80211_MODES];
+-
+ 	int rts_threshold;
+ 	int fragmentation_threshold;
+ 	int short_retry_limit; /* dot11ShortRetryLimit */
+@@ -477,21 +632,25 @@ struct ieee80211_local {
+ 			     * deliver multicast frames both back to wireless
+ 			     * media and to the local net stack */
+ 
+-	ieee80211_rx_handler *rx_pre_handlers;
+-	ieee80211_rx_handler *rx_handlers;
+-	ieee80211_tx_handler *tx_handlers;
+-
+ 	struct list_head interfaces;
+ 
++	/*
++	 * Key lock, protects sdata's key_list and sta_info's
++	 * key pointers (write access, they're RCU.)
++	 */
++	spinlock_t key_lock;
++
++
+ 	bool sta_sw_scanning;
+ 	bool sta_hw_scanning;
+ 	int scan_channel_idx;
++	enum ieee80211_band scan_band;
++
+ 	enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
+ 	unsigned long last_scan_completed;
+ 	struct delayed_work scan_work;
+ 	struct net_device *scan_dev;
+ 	struct ieee80211_channel *oper_channel, *scan_channel;
+-	struct ieee80211_hw_mode *oper_hw_mode, *scan_hw_mode;
+ 	u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
+ 	size_t scan_ssid_len;
+ 	struct list_head sta_bss_list;
+@@ -560,14 +719,8 @@ struct ieee80211_local {
+ 	int wifi_wme_noack_test;
+ 	unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
+ 
+-	unsigned int enabled_modes; /* bitfield of allowed modes;
+-				      * (1 << MODE_*) */
+-	unsigned int hw_modes; /* bitfield of supported hardware modes;
+-				* (1 << MODE_*) */
+-
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ 	struct local_debugfsdentries {
+-		struct dentry *channel;
+ 		struct dentry *frequency;
+ 		struct dentry *antenna_sel_tx;
+ 		struct dentry *antenna_sel_rx;
+@@ -577,9 +730,7 @@ struct ieee80211_local {
+ 		struct dentry *short_retry_limit;
+ 		struct dentry *long_retry_limit;
+ 		struct dentry *total_ps_buffered;
+-		struct dentry *mode;
+ 		struct dentry *wep_iv;
+-		struct dentry *modes;
+ 		struct dentry *statistics;
+ 		struct local_debugfsdentries_statsdentries {
+ 			struct dentry *transmitted_fragment_count;
+@@ -627,6 +778,63 @@ struct ieee80211_local {
+ #endif
+ };
+ 
++/* this struct represents 802.11n's RA/TID combination */
++struct ieee80211_ra_tid {
++	u8 ra[ETH_ALEN];
++	u16 tid;
++};
++
++/* Parsed Information Elements */
++struct ieee802_11_elems {
++	/* pointers to IEs */
++	u8 *ssid;
++	u8 *supp_rates;
++	u8 *fh_params;
++	u8 *ds_params;
++	u8 *cf_params;
++	u8 *tim;
++	u8 *ibss_params;
++	u8 *challenge;
++	u8 *wpa;
++	u8 *rsn;
++	u8 *erp_info;
++	u8 *ext_supp_rates;
++	u8 *wmm_info;
++	u8 *wmm_param;
++	u8 *ht_cap_elem;
++	u8 *ht_info_elem;
++	u8 *mesh_config;
++	u8 *mesh_id;
++	u8 *peer_link;
++	u8 *preq;
++	u8 *prep;
++	u8 *perr;
++
++	/* length of them, respectively */
++	u8 ssid_len;
++	u8 supp_rates_len;
++	u8 fh_params_len;
++	u8 ds_params_len;
++	u8 cf_params_len;
++	u8 tim_len;
++	u8 ibss_params_len;
++	u8 challenge_len;
++	u8 wpa_len;
++	u8 rsn_len;
++	u8 erp_info_len;
++	u8 ext_supp_rates_len;
++	u8 wmm_info_len;
++	u8 wmm_param_len;
++	u8 ht_cap_elem_len;
++	u8 ht_info_elem_len;
++	u8 mesh_config_len;
++	u8 mesh_id_len;
++	u8 peer_link_len;
++	u8 preq_len;
++	u8 prep_len;
++	u8 perr_len;
++};
++
+ static inline struct ieee80211_local *hw_to_local(
+ 	struct ieee80211_hw *hw)
+ {
+@@ -650,57 +858,6 @@ struct sta_attribute {
+ 	ssize_t (*store)(struct sta_info *, const char *buf, size_t count);
+ };
+ 
+-static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
+-{
+-	/*
+-	 * This format has been mandated by the IEEE specifications,
+-	 * so this line may not be changed to use the __set_bit() format.
+-	 */
+-	bss->tim[aid / 8] |= (1 << (aid % 8));
+-}
+-
+-static inline void bss_tim_set(struct ieee80211_local *local,
+-			       struct ieee80211_if_ap *bss, u16 aid)
+-{
+-	read_lock_bh(&local->sta_lock);
+-	__bss_tim_set(bss, aid);
+-	read_unlock_bh(&local->sta_lock);
+-}
+-
+-static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
+-{
+-	/*
+-	 * This format has been mandated by the IEEE specifications,
+-	 * so this line may not be changed to use the __clear_bit() format.
+-	 */
+-	bss->tim[aid / 8] &= ~(1 << (aid % 8));
+-}
+-
+-static inline void bss_tim_clear(struct ieee80211_local *local,
+-				 struct ieee80211_if_ap *bss, u16 aid)
+-{
+-	read_lock_bh(&local->sta_lock);
+-	__bss_tim_clear(bss, aid);
+-	read_unlock_bh(&local->sta_lock);
+-}
+-
+-/**
+- * ieee80211_is_erp_rate - Check if a rate is an ERP rate
+- * @phymode: The PHY-mode for this rate (MODE_IEEE80211...)
+- * @rate: Transmission rate to check, in 100 kbps
+- *
+- * Check if a given rate is an Extended Rate PHY (ERP) rate.
+- */
+-static inline int ieee80211_is_erp_rate(int phymode, int rate)
+-{
+-	if (phymode == MODE_IEEE80211G) {
+-		if (rate != 10 && rate != 20 &&
+-		    rate != 55 && rate != 110)
+-			return 1;
+-	}
+-	return 0;
+-}
+-
+ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
+ {
+ 	return compare_ether_addr(raddr, addr) == 0 ||
+@@ -712,16 +869,11 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
+ int ieee80211_hw_config(struct ieee80211_local *local);
+ int ieee80211_if_config(struct net_device *dev);
+ int ieee80211_if_config_beacon(struct net_device *dev);
+-void ieee80211_prepare_rates(struct ieee80211_local *local,
+-			     struct ieee80211_hw_mode *mode);
+-void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
+-int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
++void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
+ void ieee80211_if_setup(struct net_device *dev);
+-struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local,
+-					  int phymode, int hwrate);
+-int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
+-			   struct ieee80211_ht_info *req_ht_cap,
+-			   struct ieee80211_ht_bss_info *req_bss_cap);
++u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
++			struct ieee80211_ht_info *req_ht_cap,
++			struct ieee80211_ht_bss_info *req_bss_cap);
+ 
+ /* ieee80211_ioctl.c */
+ extern const struct iw_handler_def ieee80211_iw_handler_def;
+@@ -747,9 +899,7 @@ extern const struct iw_handler_def ieee80211_iw_handler_def;
+ 
+ 
+ /* ieee80211_ioctl.c */
+-int ieee80211_set_compression(struct ieee80211_local *local,
+-			      struct net_device *dev, struct sta_info *sta);
+-int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq);
++int ieee80211_set_freq(struct ieee80211_local *local, int freq);
+ /* ieee80211_sta.c */
+ void ieee80211_sta_timer(unsigned long data);
+ void ieee80211_sta_work(struct work_struct *work);
+@@ -763,9 +913,9 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len);
+ void ieee80211_sta_req_auth(struct net_device *dev,
+ 			    struct ieee80211_if_sta *ifsta);
+ int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len);
+-ieee80211_txrx_result ieee80211_sta_rx_scan(struct net_device *dev,
+-					    struct sk_buff *skb,
+-			   struct ieee80211_rx_status *rx_status);
++ieee80211_rx_result ieee80211_sta_rx_scan(
++	struct net_device *dev, struct sk_buff *skb,
++	struct ieee80211_rx_status *rx_status);
+ void ieee80211_rx_bss_list_init(struct net_device *dev);
+ void ieee80211_rx_bss_list_deinit(struct net_device *dev);
+ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len);
+@@ -782,12 +932,36 @@ int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
+ int ieee80211_ht_addt_info_ie_to_ht_bss_info(
+ 			struct ieee80211_ht_addt_info *ht_add_info_ie,
+ 			struct ieee80211_ht_bss_info *bss_info);
++void ieee80211_send_addba_request(struct net_device *dev, const u8 *da,
++				  u16 tid, u8 dialog_token, u16 start_seq_num,
++				  u16 agg_size, u16 timeout);
++void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
++				u16 initiator, u16 reason_code);
++
+ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da,
+ 				u16 tid, u16 initiator, u16 reason);
+ void sta_rx_agg_session_timer_expired(unsigned long data);
++void sta_addba_resp_timer_expired(unsigned long data);
++void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr);
++u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
++			    struct ieee802_11_elems *elems,
++			    enum ieee80211_band band);
++void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
++		int encrypt);
++void ieee802_11_parse_elems(u8 *start, size_t len,
++				   struct ieee802_11_elems *elems);
++
++#ifdef CONFIG_MAC80211_MESH
++void ieee80211_start_mesh(struct net_device *dev);
++#else
++static inline void ieee80211_start_mesh(struct net_device *dev)
++{}
++#endif
++
+ /* ieee80211_iface.c */
+ int ieee80211_if_add(struct net_device *dev, const char *name,
+-		     struct net_device **new_dev, int type);
++		     struct net_device **new_dev, int type,
++		     struct vif_params *params);
+ void ieee80211_if_set_type(struct net_device *dev, int type);
+ void ieee80211_if_reinit(struct net_device *dev);
+ void __ieee80211_if_del(struct ieee80211_local *local,
+@@ -796,16 +970,7 @@ int ieee80211_if_remove(struct net_device *dev, const char *name, int id);
+ void ieee80211_if_free(struct net_device *dev);
+ void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata);
+ 
+-/* regdomain.c */
+-void ieee80211_regdomain_init(void);
+-void ieee80211_set_default_regdomain(struct ieee80211_hw_mode *mode);
+-
+-/* rx handling */
+-extern ieee80211_rx_handler ieee80211_rx_pre_handlers[];
+-extern ieee80211_rx_handler ieee80211_rx_handlers[];
+-
+ /* tx handling */
+-extern ieee80211_tx_handler ieee80211_tx_handlers[];
+ void ieee80211_clear_tx_pending(struct ieee80211_local *local);
+ void ieee80211_tx_pending(unsigned long data);
+ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
+diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
+deleted file mode 100644
+index 92f1eb2..0000000
+--- a/net/mac80211/ieee80211_iface.c
++++ /dev/null
+@@ -1,298 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-#include <linux/kernel.h>
+-#include <linux/if_arp.h>
+-#include <linux/netdevice.h>
+-#include <linux/rtnetlink.h>
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "sta_info.h"
+-#include "debugfs_netdev.h"
+-
+-void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
+-{
+-	int i;
+-
+-	/* Default values for sub-interface parameters */
+-	sdata->drop_unencrypted = 0;
+-	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+-		skb_queue_head_init(&sdata->fragments[i].skb_list);
+-
+-	INIT_LIST_HEAD(&sdata->key_list);
+-}
+-
+-static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
+-{
+-	int i;
+-
+-	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+-		__skb_queue_purge(&sdata->fragments[i].skb_list);
+-	}
+-}
+-
+-/* Must be called with rtnl lock held. */
+-int ieee80211_if_add(struct net_device *dev, const char *name,
+-		     struct net_device **new_dev, int type)
+-{
+-	struct net_device *ndev;
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata = NULL;
+-	int ret;
+-
+-	ASSERT_RTNL();
+-	ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
+-			    name, ieee80211_if_setup);
+-	if (!ndev)
+-		return -ENOMEM;
+-
+-	ret = dev_alloc_name(ndev, ndev->name);
+-	if (ret < 0)
+-		goto fail;
+-
+-	memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+-	ndev->base_addr = dev->base_addr;
+-	ndev->irq = dev->irq;
+-	ndev->mem_start = dev->mem_start;
+-	ndev->mem_end = dev->mem_end;
+-	SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+-	ndev->ieee80211_ptr = &sdata->wdev;
+-	sdata->wdev.wiphy = local->hw.wiphy;
+-	sdata->vif.type = IEEE80211_IF_TYPE_AP;
+-	sdata->dev = ndev;
+-	sdata->local = local;
+-	ieee80211_if_sdata_init(sdata);
+-
+-	ret = register_netdevice(ndev);
+-	if (ret)
+-		goto fail;
+-
+-	ieee80211_debugfs_add_netdev(sdata);
+-	ieee80211_if_set_type(ndev, type);
+-
+-	/* we're under RTNL so all this is fine */
+-	if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
+-		__ieee80211_if_del(local, sdata);
+-		return -ENODEV;
+-	}
+-	list_add_tail_rcu(&sdata->list, &local->interfaces);
+-
+-	if (new_dev)
+-		*new_dev = ndev;
+-
+-	return 0;
+-
+-fail:
+-	free_netdev(ndev);
+-	return ret;
+-}
+-
+-void ieee80211_if_set_type(struct net_device *dev, int type)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	int oldtype = sdata->vif.type;
+-
+-	/*
+-	 * We need to call this function on the master interface
+-	 * which already has a hard_start_xmit routine assigned
+-	 * which must not be changed.
+-	 */
+-	if (dev != sdata->local->mdev)
+-		dev->hard_start_xmit = ieee80211_subif_start_xmit;
+-
+-	/*
+-	 * Called even when register_netdevice fails, it would
+-	 * oops if assigned before initialising the rest.
+-	 */
+-	dev->uninit = ieee80211_if_reinit;
+-
+-	/* most have no BSS pointer */
+-	sdata->bss = NULL;
+-	sdata->vif.type = type;
+-
+-	switch (type) {
+-	case IEEE80211_IF_TYPE_WDS:
+-		/* nothing special */
+-		break;
+-	case IEEE80211_IF_TYPE_VLAN:
+-		sdata->u.vlan.ap = NULL;
+-		break;
+-	case IEEE80211_IF_TYPE_AP:
+-		sdata->u.ap.force_unicast_rateidx = -1;
+-		sdata->u.ap.max_ratectrl_rateidx = -1;
+-		skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
+-		sdata->bss = &sdata->u.ap;
+-		INIT_LIST_HEAD(&sdata->u.ap.vlans);
+-		break;
+-	case IEEE80211_IF_TYPE_STA:
+-	case IEEE80211_IF_TYPE_IBSS: {
+-		struct ieee80211_sub_if_data *msdata;
+-		struct ieee80211_if_sta *ifsta;
+-
+-		ifsta = &sdata->u.sta;
+-		INIT_WORK(&ifsta->work, ieee80211_sta_work);
+-		setup_timer(&ifsta->timer, ieee80211_sta_timer,
+-			    (unsigned long) sdata);
+-		skb_queue_head_init(&ifsta->skb_queue);
+-
+-		ifsta->capab = WLAN_CAPABILITY_ESS;
+-		ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
+-			IEEE80211_AUTH_ALG_SHARED_KEY;
+-		ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
+-			IEEE80211_STA_WMM_ENABLED |
+-			IEEE80211_STA_AUTO_BSSID_SEL |
+-			IEEE80211_STA_AUTO_CHANNEL_SEL;
+-
+-		msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
+-		sdata->bss = &msdata->u.ap;
+-		break;
+-	}
+-	case IEEE80211_IF_TYPE_MNTR:
+-		dev->type = ARPHRD_IEEE80211_RADIOTAP;
+-		dev->hard_start_xmit = ieee80211_monitor_start_xmit;
+-		break;
+-	default:
+-		printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
+-		       dev->name, __FUNCTION__, type);
+-	}
+-	ieee80211_debugfs_change_if_type(sdata, oldtype);
+-}
+-
+-/* Must be called with rtnl lock held. */
+-void ieee80211_if_reinit(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct sta_info *sta;
+-	struct sk_buff *skb;
+-
+-	ASSERT_RTNL();
+-
+-	ieee80211_free_keys(sdata);
+-
+-	ieee80211_if_sdata_deinit(sdata);
+-
+-	switch (sdata->vif.type) {
+-	case IEEE80211_IF_TYPE_INVALID:
+-		/* cannot happen */
+-		WARN_ON(1);
+-		break;
+-	case IEEE80211_IF_TYPE_AP: {
+-		/* Remove all virtual interfaces that use this BSS
+-		 * as their sdata->bss */
+-		struct ieee80211_sub_if_data *tsdata, *n;
+-
+-		list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
+-			if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
+-				printk(KERN_DEBUG "%s: removing virtual "
+-				       "interface %s because its BSS interface"
+-				       " is being removed\n",
+-				       sdata->dev->name, tsdata->dev->name);
+-				list_del_rcu(&tsdata->list);
+-				/*
+-				 * We have lots of time and can afford
+-				 * to sync for each interface
+-				 */
+-				synchronize_rcu();
+-				__ieee80211_if_del(local, tsdata);
+-			}
+-		}
+-
+-		kfree(sdata->u.ap.beacon);
+-
+-		while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
+-			local->total_ps_buffered--;
+-			dev_kfree_skb(skb);
+-		}
+-
+-		break;
+-	}
+-	case IEEE80211_IF_TYPE_WDS:
+-		sta = sta_info_get(local, sdata->u.wds.remote_addr);
+-		if (sta) {
+-			sta_info_free(sta);
+-			sta_info_put(sta);
+-		} else {
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+-			printk(KERN_DEBUG "%s: Someone had deleted my STA "
+-			       "entry for the WDS link\n", dev->name);
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+-		}
+-		break;
+-	case IEEE80211_IF_TYPE_STA:
+-	case IEEE80211_IF_TYPE_IBSS:
+-		kfree(sdata->u.sta.extra_ie);
+-		sdata->u.sta.extra_ie = NULL;
+-		kfree(sdata->u.sta.assocreq_ies);
+-		sdata->u.sta.assocreq_ies = NULL;
+-		kfree(sdata->u.sta.assocresp_ies);
+-		sdata->u.sta.assocresp_ies = NULL;
+-		if (sdata->u.sta.probe_resp) {
+-			dev_kfree_skb(sdata->u.sta.probe_resp);
+-			sdata->u.sta.probe_resp = NULL;
+-		}
+-
+-		break;
+-	case IEEE80211_IF_TYPE_MNTR:
+-		dev->type = ARPHRD_ETHER;
+-		break;
+-	case IEEE80211_IF_TYPE_VLAN:
+-		sdata->u.vlan.ap = NULL;
+-		break;
+-	}
+-
+-	/* remove all STAs that are bound to this virtual interface */
+-	sta_info_flush(local, dev);
+-
+-	memset(&sdata->u, 0, sizeof(sdata->u));
+-	ieee80211_if_sdata_init(sdata);
+-}
+-
+-/* Must be called with rtnl lock held. */
+-void __ieee80211_if_del(struct ieee80211_local *local,
+-			struct ieee80211_sub_if_data *sdata)
+-{
+-	struct net_device *dev = sdata->dev;
+-
+-	ieee80211_debugfs_remove_netdev(sdata);
+-	unregister_netdevice(dev);
+-	/* Except master interface, the net_device will be freed by
+-	 * net_device->destructor (i. e. ieee80211_if_free). */
+-}
+-
+-/* Must be called with rtnl lock held. */
+-int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata, *n;
+-
+-	ASSERT_RTNL();
+-
+-	list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
+-		if ((sdata->vif.type == id || id == -1) &&
+-		    strcmp(name, sdata->dev->name) == 0 &&
+-		    sdata->dev != local->mdev) {
+-			list_del_rcu(&sdata->list);
+-			synchronize_rcu();
+-			__ieee80211_if_del(local, sdata);
+-			return 0;
+-		}
+-	}
+-	return -ENODEV;
+-}
+-
+-void ieee80211_if_free(struct net_device *dev)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	ieee80211_if_sdata_deinit(sdata);
+-	free_netdev(dev);
+-}
+diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
+deleted file mode 100644
+index 5024d37..0000000
+--- a/net/mac80211/ieee80211_ioctl.c
++++ /dev/null
+@@ -1,1138 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/netdevice.h>
+-#include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/skbuff.h>
+-#include <linux/etherdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/wireless.h>
+-#include <net/iw_handler.h>
+-#include <asm/uaccess.h>
+-
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "ieee80211_led.h"
+-#include "ieee80211_rate.h"
+-#include "wpa.h"
+-#include "aes_ccm.h"
+-
+-
+-static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
+-				    int idx, int alg, int remove,
+-				    int set_tx_key, const u8 *_key,
+-				    size_t key_len)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	int ret = 0;
+-	struct sta_info *sta;
+-	struct ieee80211_key *key;
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
+-		printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
+-		       dev->name, idx);
+-		return -EINVAL;
+-	}
+-
+-	if (is_broadcast_ether_addr(sta_addr)) {
+-		sta = NULL;
+-		key = sdata->keys[idx];
+-	} else {
+-		set_tx_key = 0;
+-		/*
+-		 * According to the standard, the key index of a pairwise
+-		 * key must be zero. However, some AP are broken when it
+-		 * comes to WEP key indices, so we work around this.
+-		 */
+-		if (idx != 0 && alg != ALG_WEP) {
+-			printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
+-			       "individual key\n", dev->name);
+-			return -EINVAL;
+-		}
+-
+-		sta = sta_info_get(local, sta_addr);
+-		if (!sta) {
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+-			DECLARE_MAC_BUF(mac);
+-			printk(KERN_DEBUG "%s: set_encrypt - unknown addr "
+-			       "%s\n",
+-			       dev->name, print_mac(mac, sta_addr));
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+-
+-			return -ENOENT;
+-		}
+-
+-		key = sta->key;
+-	}
+-
+-	if (remove) {
+-		ieee80211_key_free(key);
+-		key = NULL;
+-	} else {
+-		/*
+-		 * Automatically frees any old key if present.
+-		 */
+-		key = ieee80211_key_alloc(sdata, sta, alg, idx, key_len, _key);
+-		if (!key) {
+-			ret = -ENOMEM;
+-			goto err_out;
+-		}
+-	}
+-
+-	if (set_tx_key || (!sta && !sdata->default_key && key))
+-		ieee80211_set_default_key(sdata, idx);
+-
+-	ret = 0;
+- err_out:
+-	if (sta)
+-		sta_info_put(sta);
+-	return ret;
+-}
+-
+-static int ieee80211_ioctl_siwgenie(struct net_device *dev,
+-				    struct iw_request_info *info,
+-				    struct iw_point *data, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
+-		return -EOPNOTSUPP;
+-
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+-		int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
+-		if (ret)
+-			return ret;
+-		sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
+-		ieee80211_sta_req_auth(dev, &sdata->u.sta);
+-		return 0;
+-	}
+-
+-	return -EOPNOTSUPP;
+-}
+-
+-static int ieee80211_ioctl_giwname(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   char *name, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	switch (local->hw.conf.phymode) {
+-	case MODE_IEEE80211A:
+-		strcpy(name, "IEEE 802.11a");
+-		break;
+-	case MODE_IEEE80211B:
+-		strcpy(name, "IEEE 802.11b");
+-		break;
+-	case MODE_IEEE80211G:
+-		strcpy(name, "IEEE 802.11g");
+-		break;
+-	default:
+-		strcpy(name, "IEEE 802.11");
+-		break;
+-	}
+-
+-	return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_giwrange(struct net_device *dev,
+-				 struct iw_request_info *info,
+-				 struct iw_point *data, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct iw_range *range = (struct iw_range *) extra;
+-	struct ieee80211_hw_mode *mode = NULL;
+-	int c = 0;
+-
+-	data->length = sizeof(struct iw_range);
+-	memset(range, 0, sizeof(struct iw_range));
+-
+-	range->we_version_compiled = WIRELESS_EXT;
+-	range->we_version_source = 21;
+-	range->retry_capa = IW_RETRY_LIMIT;
+-	range->retry_flags = IW_RETRY_LIMIT;
+-	range->min_retry = 0;
+-	range->max_retry = 255;
+-	range->min_rts = 0;
+-	range->max_rts = 2347;
+-	range->min_frag = 256;
+-	range->max_frag = 2346;
+-
+-	range->encoding_size[0] = 5;
+-	range->encoding_size[1] = 13;
+-	range->num_encoding_sizes = 2;
+-	range->max_encoding_tokens = NUM_DEFAULT_KEYS;
+-
+-	range->max_qual.qual = local->hw.max_signal;
+-	range->max_qual.level = local->hw.max_rssi;
+-	range->max_qual.noise = local->hw.max_noise;
+-	range->max_qual.updated = local->wstats_flags;
+-
+-	range->avg_qual.qual = local->hw.max_signal/2;
+-	range->avg_qual.level = 0;
+-	range->avg_qual.noise = 0;
+-	range->avg_qual.updated = local->wstats_flags;
+-
+-	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+-			  IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+-
+-	list_for_each_entry(mode, &local->modes_list, list) {
+-		int i = 0;
+-
+-		if (!(local->enabled_modes & (1 << mode->mode)) ||
+-		    (local->hw_modes & local->enabled_modes &
+-		     (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
+-			continue;
+-
+-		while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) {
+-			struct ieee80211_channel *chan = &mode->channels[i];
+-
+-			if (chan->flag & IEEE80211_CHAN_W_SCAN) {
+-				range->freq[c].i = chan->chan;
+-				range->freq[c].m = chan->freq * 100000;
+-				range->freq[c].e = 1;
+-				c++;
+-			}
+-			i++;
+-		}
+-	}
+-	range->num_channels = c;
+-	range->num_frequency = c;
+-
+-	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+-	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
+-	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+-	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+-
+-	range->scan_capa |= IW_SCAN_CAPA_ESSID;
+-
+-	return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_siwmode(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   __u32 *mode, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	int type;
+-
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
+-		return -EOPNOTSUPP;
+-
+-	switch (*mode) {
+-	case IW_MODE_INFRA:
+-		type = IEEE80211_IF_TYPE_STA;
+-		break;
+-	case IW_MODE_ADHOC:
+-		type = IEEE80211_IF_TYPE_IBSS;
+-		break;
+-	case IW_MODE_MONITOR:
+-		type = IEEE80211_IF_TYPE_MNTR;
+-		break;
+-	default:
+-		return -EINVAL;
+-	}
+-
+-	if (type == sdata->vif.type)
+-		return 0;
+-	if (netif_running(dev))
+-		return -EBUSY;
+-
+-	ieee80211_if_reinit(dev);
+-	ieee80211_if_set_type(dev, type);
+-
+-	return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_giwmode(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   __u32 *mode, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	switch (sdata->vif.type) {
+-	case IEEE80211_IF_TYPE_AP:
+-		*mode = IW_MODE_MASTER;
+-		break;
+-	case IEEE80211_IF_TYPE_STA:
+-		*mode = IW_MODE_INFRA;
+-		break;
+-	case IEEE80211_IF_TYPE_IBSS:
+-		*mode = IW_MODE_ADHOC;
+-		break;
+-	case IEEE80211_IF_TYPE_MNTR:
+-		*mode = IW_MODE_MONITOR;
+-		break;
+-	case IEEE80211_IF_TYPE_WDS:
+-		*mode = IW_MODE_REPEAT;
+-		break;
+-	case IEEE80211_IF_TYPE_VLAN:
+-		*mode = IW_MODE_SECOND;		/* FIXME */
+-		break;
+-	default:
+-		*mode = IW_MODE_AUTO;
+-		break;
+-	}
+-	return 0;
+-}
+-
+-int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
+-{
+-	struct ieee80211_hw_mode *mode;
+-	int c, set = 0;
+-	int ret = -EINVAL;
+-
+-	list_for_each_entry(mode, &local->modes_list, list) {
+-		if (!(local->enabled_modes & (1 << mode->mode)))
+-			continue;
+-		for (c = 0; c < mode->num_channels; c++) {
+-			struct ieee80211_channel *chan = &mode->channels[c];
+-			if (chan->flag & IEEE80211_CHAN_W_SCAN &&
+-			    ((chan->chan == channel) || (chan->freq == freq))) {
+-				local->oper_channel = chan;
+-				local->oper_hw_mode = mode;
+-				set = 1;
+-				break;
+-			}
+-		}
+-		if (set)
+-			break;
+-	}
+-
+-	if (set) {
+-		if (local->sta_sw_scanning)
+-			ret = 0;
+-		else
+-			ret = ieee80211_hw_config(local);
+-
+-		rate_control_clear(local);
+-	}
+-
+-	return ret;
+-}
+-
+-static int ieee80211_ioctl_siwfreq(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   struct iw_freq *freq, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
+-		sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
+-
+-	/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
+-	if (freq->e == 0) {
+-		if (freq->m < 0) {
+-			if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
+-				sdata->u.sta.flags |=
+-					IEEE80211_STA_AUTO_CHANNEL_SEL;
+-			return 0;
+-		} else
+-			return ieee80211_set_channel(local, freq->m, -1);
+-	} else {
+-		int i, div = 1000000;
+-		for (i = 0; i < freq->e; i++)
+-			div /= 10;
+-		if (div > 0)
+-			return ieee80211_set_channel(local, -1, freq->m / div);
+-		else
+-			return -EINVAL;
+-	}
+-}
+-
+-
+-static int ieee80211_ioctl_giwfreq(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   struct iw_freq *freq, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	/* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
+-	 * driver for the current channel with firmware-based management */
+-
+-	freq->m = local->hw.conf.freq;
+-	freq->e = 6;
+-
+-	return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_siwessid(struct net_device *dev,
+-				    struct iw_request_info *info,
+-				    struct iw_point *data, char *ssid)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	size_t len = data->length;
+-
+-	/* iwconfig uses nul termination in SSID.. */
+-	if (len > 0 && ssid[len - 1] == '\0')
+-		len--;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+-		int ret;
+-		if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
+-			if (len > IEEE80211_MAX_SSID_LEN)
+-				return -EINVAL;
+-			memcpy(sdata->u.sta.ssid, ssid, len);
+-			sdata->u.sta.ssid_len = len;
+-			return 0;
+-		}
+-		if (data->flags)
+-			sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
+-		else
+-			sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
+-		ret = ieee80211_sta_set_ssid(dev, ssid, len);
+-		if (ret)
+-			return ret;
+-		ieee80211_sta_req_auth(dev, &sdata->u.sta);
+-		return 0;
+-	}
+-
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+-		memcpy(sdata->u.ap.ssid, ssid, len);
+-		memset(sdata->u.ap.ssid + len, 0,
+-		       IEEE80211_MAX_SSID_LEN - len);
+-		sdata->u.ap.ssid_len = len;
+-		return ieee80211_if_config(dev);
+-	}
+-	return -EOPNOTSUPP;
+-}
+-
+-
+-static int ieee80211_ioctl_giwessid(struct net_device *dev,
+-				    struct iw_request_info *info,
+-				    struct iw_point *data, char *ssid)
+-{
+-	size_t len;
+-
+-	struct ieee80211_sub_if_data *sdata;
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+-		int res = ieee80211_sta_get_ssid(dev, ssid, &len);
+-		if (res == 0) {
+-			data->length = len;
+-			data->flags = 1;
+-		} else
+-			data->flags = 0;
+-		return res;
+-	}
+-
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+-		len = sdata->u.ap.ssid_len;
+-		if (len > IW_ESSID_MAX_SIZE)
+-			len = IW_ESSID_MAX_SIZE;
+-		memcpy(ssid, sdata->u.ap.ssid, len);
+-		data->length = len;
+-		data->flags = 1;
+-		return 0;
+-	}
+-	return -EOPNOTSUPP;
+-}
+-
+-
+-static int ieee80211_ioctl_siwap(struct net_device *dev,
+-				 struct iw_request_info *info,
+-				 struct sockaddr *ap_addr, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+-		int ret;
+-		if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
+-			memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
+-			       ETH_ALEN);
+-			return 0;
+-		}
+-		if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
+-			sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
+-				IEEE80211_STA_AUTO_CHANNEL_SEL;
+-		else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
+-			sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
+-		else
+-			sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
+-		ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
+-		if (ret)
+-			return ret;
+-		ieee80211_sta_req_auth(dev, &sdata->u.sta);
+-		return 0;
+-	} else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
+-		if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
+-			   ETH_ALEN) == 0)
+-			return 0;
+-		return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
+-	}
+-
+-	return -EOPNOTSUPP;
+-}
+-
+-
+-static int ieee80211_ioctl_giwap(struct net_device *dev,
+-				 struct iw_request_info *info,
+-				 struct sockaddr *ap_addr, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+-		ap_addr->sa_family = ARPHRD_ETHER;
+-		memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
+-		return 0;
+-	} else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
+-		ap_addr->sa_family = ARPHRD_ETHER;
+-		memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
+-		return 0;
+-	}
+-
+-	return -EOPNOTSUPP;
+-}
+-
+-
+-static int ieee80211_ioctl_siwscan(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   union iwreq_data *wrqu, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct iw_scan_req *req = NULL;
+-	u8 *ssid = NULL;
+-	size_t ssid_len = 0;
+-
+-	if (!netif_running(dev))
+-		return -ENETDOWN;
+-
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
+-	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+-	    sdata->vif.type != IEEE80211_IF_TYPE_AP)
+-		return -EOPNOTSUPP;
+-
+-	/* if SSID was specified explicitly then use that */
+-	if (wrqu->data.length == sizeof(struct iw_scan_req) &&
+-	    wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+-		req = (struct iw_scan_req *)extra;
+-		ssid = req->essid;
+-		ssid_len = req->essid_len;
+-	}
+-
+-	return ieee80211_sta_req_scan(dev, ssid, ssid_len);
+-}
+-
+-
+-static int ieee80211_ioctl_giwscan(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   struct iw_point *data, char *extra)
+-{
+-	int res;
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	if (local->sta_sw_scanning || local->sta_hw_scanning)
+-		return -EAGAIN;
+-
+-	res = ieee80211_sta_scan_results(dev, extra, data->length);
+-	if (res >= 0) {
+-		data->length = res;
+-		return 0;
+-	}
+-	data->length = 0;
+-	return res;
+-}
+-
+-
+-static int ieee80211_ioctl_siwrate(struct net_device *dev,
+-				  struct iw_request_info *info,
+-				  struct iw_param *rate, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_hw_mode *mode;
+-	int i;
+-	u32 target_rate = rate->value / 100000;
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (!sdata->bss)
+-		return -ENODEV;
+-	mode = local->oper_hw_mode;
+-	/* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
+-	 * target_rate = X, rate->fixed = 1 means only rate X
+-	 * target_rate = X, rate->fixed = 0 means all rates <= X */
+-	sdata->bss->max_ratectrl_rateidx = -1;
+-	sdata->bss->force_unicast_rateidx = -1;
+-	if (rate->value < 0)
+-		return 0;
+-	for (i=0; i < mode->num_rates; i++) {
+-		struct ieee80211_rate *rates = &mode->rates[i];
+-		int this_rate = rates->rate;
+-
+-		if (target_rate == this_rate) {
+-			sdata->bss->max_ratectrl_rateidx = i;
+-			if (rate->fixed)
+-				sdata->bss->force_unicast_rateidx = i;
+-			return 0;
+-		}
+-	}
+-	return -EINVAL;
+-}
+-
+-static int ieee80211_ioctl_giwrate(struct net_device *dev,
+-				  struct iw_request_info *info,
+-				  struct iw_param *rate, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct sta_info *sta;
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
+-		sta = sta_info_get(local, sdata->u.sta.bssid);
+-	else
+-		return -EOPNOTSUPP;
+-	if (!sta)
+-		return -ENODEV;
+-	if (sta->txrate < local->oper_hw_mode->num_rates)
+-		rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
+-	else
+-		rate->value = 0;
+-	sta_info_put(sta);
+-	return 0;
+-}
+-
+-static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
+-				      struct iw_request_info *info,
+-				      union iwreq_data *data, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	bool need_reconfig = 0;
+-	u8 new_power_level;
+-
+-	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
+-		return -EINVAL;
+-	if (data->txpower.flags & IW_TXPOW_RANGE)
+-		return -EINVAL;
+-
+-	if (data->txpower.fixed) {
+-		new_power_level = data->txpower.value;
+-	} else {
+-		/* Automatic power level. Get the px power from the current
+-		 * channel. */
+-		struct ieee80211_channel* chan = local->oper_channel;
+-		if (!chan)
+-			return -EINVAL;
+-
+-		new_power_level = chan->power_level;
+-	}
+-
+-	if (local->hw.conf.power_level != new_power_level) {
+-		local->hw.conf.power_level = new_power_level;
+-		need_reconfig = 1;
+-	}
+-
+-	if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
+-		local->hw.conf.radio_enabled = !(data->txpower.disabled);
+-		need_reconfig = 1;
+-		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
+-	}
+-
+-	if (need_reconfig) {
+-		ieee80211_hw_config(local);
+-		/* The return value of hw_config is not of big interest here,
+-		 * as it doesn't say that it failed because of _this_ config
+-		 * change or something else. Ignore it. */
+-	}
+-
+-	return 0;
+-}
+-
+-static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   union iwreq_data *data, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	data->txpower.fixed = 1;
+-	data->txpower.disabled = !(local->hw.conf.radio_enabled);
+-	data->txpower.value = local->hw.conf.power_level;
+-	data->txpower.flags = IW_TXPOW_DBM;
+-
+-	return 0;
+-}
+-
+-static int ieee80211_ioctl_siwrts(struct net_device *dev,
+-				  struct iw_request_info *info,
+-				  struct iw_param *rts, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	if (rts->disabled)
+-		local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+-	else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
+-		return -EINVAL;
+-	else
+-		local->rts_threshold = rts->value;
+-
+-	/* If the wlan card performs RTS/CTS in hardware/firmware,
+-	 * configure it here */
+-
+-	if (local->ops->set_rts_threshold)
+-		local->ops->set_rts_threshold(local_to_hw(local),
+-					     local->rts_threshold);
+-
+-	return 0;
+-}
+-
+-static int ieee80211_ioctl_giwrts(struct net_device *dev,
+-				  struct iw_request_info *info,
+-				  struct iw_param *rts, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	rts->value = local->rts_threshold;
+-	rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
+-	rts->fixed = 1;
+-
+-	return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_siwfrag(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   struct iw_param *frag, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	if (frag->disabled)
+-		local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+-	else if (frag->value < 256 ||
+-		 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
+-		return -EINVAL;
+-	else {
+-		/* Fragment length must be even, so strip LSB. */
+-		local->fragmentation_threshold = frag->value & ~0x1;
+-	}
+-
+-	/* If the wlan card performs fragmentation in hardware/firmware,
+-	 * configure it here */
+-
+-	if (local->ops->set_frag_threshold)
+-		local->ops->set_frag_threshold(
+-			local_to_hw(local),
+-			local->fragmentation_threshold);
+-
+-	return 0;
+-}
+-
+-static int ieee80211_ioctl_giwfrag(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   struct iw_param *frag, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	frag->value = local->fragmentation_threshold;
+-	frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
+-	frag->fixed = 1;
+-
+-	return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_siwretry(struct net_device *dev,
+-				    struct iw_request_info *info,
+-				    struct iw_param *retry, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	if (retry->disabled ||
+-	    (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
+-		return -EINVAL;
+-
+-	if (retry->flags & IW_RETRY_MAX)
+-		local->long_retry_limit = retry->value;
+-	else if (retry->flags & IW_RETRY_MIN)
+-		local->short_retry_limit = retry->value;
+-	else {
+-		local->long_retry_limit = retry->value;
+-		local->short_retry_limit = retry->value;
+-	}
+-
+-	if (local->ops->set_retry_limit) {
+-		return local->ops->set_retry_limit(
+-			local_to_hw(local),
+-			local->short_retry_limit,
+-			local->long_retry_limit);
+-	}
+-
+-	return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_giwretry(struct net_device *dev,
+-				    struct iw_request_info *info,
+-				    struct iw_param *retry, char *extra)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	retry->disabled = 0;
+-	if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
+-		/* first return min value, iwconfig will ask max value
+-		 * later if needed */
+-		retry->flags |= IW_RETRY_LIMIT;
+-		retry->value = local->short_retry_limit;
+-		if (local->long_retry_limit != local->short_retry_limit)
+-			retry->flags |= IW_RETRY_MIN;
+-		return 0;
+-	}
+-	if (retry->flags & IW_RETRY_MAX) {
+-		retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+-		retry->value = local->long_retry_limit;
+-	}
+-
+-	return 0;
+-}
+-
+-static int ieee80211_ioctl_siwmlme(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   struct iw_point *data, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	struct iw_mlme *mlme = (struct iw_mlme *) extra;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
+-	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
+-		return -EINVAL;
+-
+-	switch (mlme->cmd) {
+-	case IW_MLME_DEAUTH:
+-		/* TODO: mlme->addr.sa_data */
+-		return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
+-	case IW_MLME_DISASSOC:
+-		/* TODO: mlme->addr.sa_data */
+-		return ieee80211_sta_disassociate(dev, mlme->reason_code);
+-	default:
+-		return -EOPNOTSUPP;
+-	}
+-}
+-
+-
+-static int ieee80211_ioctl_siwencode(struct net_device *dev,
+-				     struct iw_request_info *info,
+-				     struct iw_point *erq, char *keybuf)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	int idx, i, alg = ALG_WEP;
+-	u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+-	int remove = 0;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	idx = erq->flags & IW_ENCODE_INDEX;
+-	if (idx == 0) {
+-		if (sdata->default_key)
+-			for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+-				if (sdata->default_key == sdata->keys[i]) {
+-					idx = i;
+-					break;
+-				}
+-			}
+-	} else if (idx < 1 || idx > 4)
+-		return -EINVAL;
+-	else
+-		idx--;
+-
+-	if (erq->flags & IW_ENCODE_DISABLED)
+-		remove = 1;
+-	else if (erq->length == 0) {
+-		/* No key data - just set the default TX key index */
+-		ieee80211_set_default_key(sdata, idx);
+-		return 0;
+-	}
+-
+-	return ieee80211_set_encryption(
+-		dev, bcaddr,
+-		idx, alg, remove,
+-		!sdata->default_key,
+-		keybuf, erq->length);
+-}
+-
+-
+-static int ieee80211_ioctl_giwencode(struct net_device *dev,
+-				     struct iw_request_info *info,
+-				     struct iw_point *erq, char *key)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	int idx, i;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	idx = erq->flags & IW_ENCODE_INDEX;
+-	if (idx < 1 || idx > 4) {
+-		idx = -1;
+-		if (!sdata->default_key)
+-			idx = 0;
+-		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+-			if (sdata->default_key == sdata->keys[i]) {
+-				idx = i;
+-				break;
+-			}
+-		}
+-		if (idx < 0)
+-			return -EINVAL;
+-	} else
+-		idx--;
+-
+-	erq->flags = idx + 1;
+-
+-	if (!sdata->keys[idx]) {
+-		erq->length = 0;
+-		erq->flags |= IW_ENCODE_DISABLED;
+-		return 0;
+-	}
+-
+-	memcpy(key, sdata->keys[idx]->conf.key,
+-	       min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
+-	erq->length = sdata->keys[idx]->conf.keylen;
+-	erq->flags |= IW_ENCODE_ENABLED;
+-
+-	return 0;
+-}
+-
+-static int ieee80211_ioctl_siwauth(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   struct iw_param *data, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	int ret = 0;
+-
+-	switch (data->flags & IW_AUTH_INDEX) {
+-	case IW_AUTH_WPA_VERSION:
+-	case IW_AUTH_CIPHER_PAIRWISE:
+-	case IW_AUTH_CIPHER_GROUP:
+-	case IW_AUTH_WPA_ENABLED:
+-	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+-	case IW_AUTH_KEY_MGMT:
+-		break;
+-	case IW_AUTH_DROP_UNENCRYPTED:
+-		sdata->drop_unencrypted = !!data->value;
+-		break;
+-	case IW_AUTH_PRIVACY_INVOKED:
+-		if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+-			ret = -EINVAL;
+-		else {
+-			sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
+-			/*
+-			 * Privacy invoked by wpa_supplicant, store the
+-			 * value and allow associating to a protected
+-			 * network without having a key up front.
+-			 */
+-			if (data->value)
+-				sdata->u.sta.flags |=
+-					IEEE80211_STA_PRIVACY_INVOKED;
+-		}
+-		break;
+-	case IW_AUTH_80211_AUTH_ALG:
+-		if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-		    sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
+-			sdata->u.sta.auth_algs = data->value;
+-		else
+-			ret = -EOPNOTSUPP;
+-		break;
+-	default:
+-		ret = -EOPNOTSUPP;
+-		break;
+-	}
+-	return ret;
+-}
+-
+-/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
+-static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct iw_statistics *wstats = &local->wstats;
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct sta_info *sta = NULL;
+-
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
+-		sta = sta_info_get(local, sdata->u.sta.bssid);
+-	if (!sta) {
+-		wstats->discard.fragment = 0;
+-		wstats->discard.misc = 0;
+-		wstats->qual.qual = 0;
+-		wstats->qual.level = 0;
+-		wstats->qual.noise = 0;
+-		wstats->qual.updated = IW_QUAL_ALL_INVALID;
+-	} else {
+-		wstats->qual.level = sta->last_rssi;
+-		wstats->qual.qual = sta->last_signal;
+-		wstats->qual.noise = sta->last_noise;
+-		wstats->qual.updated = local->wstats_flags;
+-		sta_info_put(sta);
+-	}
+-	return wstats;
+-}
+-
+-static int ieee80211_ioctl_giwauth(struct net_device *dev,
+-				   struct iw_request_info *info,
+-				   struct iw_param *data, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	int ret = 0;
+-
+-	switch (data->flags & IW_AUTH_INDEX) {
+-	case IW_AUTH_80211_AUTH_ALG:
+-		if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-		    sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
+-			data->value = sdata->u.sta.auth_algs;
+-		else
+-			ret = -EOPNOTSUPP;
+-		break;
+-	default:
+-		ret = -EOPNOTSUPP;
+-		break;
+-	}
+-	return ret;
+-}
+-
+-
+-static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
+-					struct iw_request_info *info,
+-					struct iw_point *erq, char *extra)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+-	int uninitialized_var(alg), idx, i, remove = 0;
+-
+-	switch (ext->alg) {
+-	case IW_ENCODE_ALG_NONE:
+-		remove = 1;
+-		break;
+-	case IW_ENCODE_ALG_WEP:
+-		alg = ALG_WEP;
+-		break;
+-	case IW_ENCODE_ALG_TKIP:
+-		alg = ALG_TKIP;
+-		break;
+-	case IW_ENCODE_ALG_CCMP:
+-		alg = ALG_CCMP;
+-		break;
+-	default:
+-		return -EOPNOTSUPP;
+-	}
+-
+-	if (erq->flags & IW_ENCODE_DISABLED)
+-		remove = 1;
+-
+-	idx = erq->flags & IW_ENCODE_INDEX;
+-	if (idx < 1 || idx > 4) {
+-		idx = -1;
+-		if (!sdata->default_key)
+-			idx = 0;
+-		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+-			if (sdata->default_key == sdata->keys[i]) {
+-				idx = i;
+-				break;
+-			}
+-		}
+-		if (idx < 0)
+-			return -EINVAL;
+-	} else
+-		idx--;
+-
+-	return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
+-					remove,
+-					ext->ext_flags &
+-					IW_ENCODE_EXT_SET_TX_KEY,
+-					ext->key, ext->key_len);
+-}
+-
+-
+-/* Structures to export the Wireless Handlers */
+-
+-static const iw_handler ieee80211_handler[] =
+-{
+-	(iw_handler) NULL,				/* SIOCSIWCOMMIT */
+-	(iw_handler) ieee80211_ioctl_giwname,		/* SIOCGIWNAME */
+-	(iw_handler) NULL,				/* SIOCSIWNWID */
+-	(iw_handler) NULL,				/* SIOCGIWNWID */
+-	(iw_handler) ieee80211_ioctl_siwfreq,		/* SIOCSIWFREQ */
+-	(iw_handler) ieee80211_ioctl_giwfreq,		/* SIOCGIWFREQ */
+-	(iw_handler) ieee80211_ioctl_siwmode,		/* SIOCSIWMODE */
+-	(iw_handler) ieee80211_ioctl_giwmode,		/* SIOCGIWMODE */
+-	(iw_handler) NULL,				/* SIOCSIWSENS */
+-	(iw_handler) NULL,				/* SIOCGIWSENS */
+-	(iw_handler) NULL /* not used */,		/* SIOCSIWRANGE */
+-	(iw_handler) ieee80211_ioctl_giwrange,		/* SIOCGIWRANGE */
+-	(iw_handler) NULL /* not used */,		/* SIOCSIWPRIV */
+-	(iw_handler) NULL /* kernel code */,		/* SIOCGIWPRIV */
+-	(iw_handler) NULL /* not used */,		/* SIOCSIWSTATS */
+-	(iw_handler) NULL /* kernel code */,		/* SIOCGIWSTATS */
+-	(iw_handler) NULL,				/* SIOCSIWSPY */
+-	(iw_handler) NULL,				/* SIOCGIWSPY */
+-	(iw_handler) NULL,				/* SIOCSIWTHRSPY */
+-	(iw_handler) NULL,				/* SIOCGIWTHRSPY */
+-	(iw_handler) ieee80211_ioctl_siwap,		/* SIOCSIWAP */
+-	(iw_handler) ieee80211_ioctl_giwap,		/* SIOCGIWAP */
+-	(iw_handler) ieee80211_ioctl_siwmlme,		/* SIOCSIWMLME */
+-	(iw_handler) NULL,				/* SIOCGIWAPLIST */
+-	(iw_handler) ieee80211_ioctl_siwscan,		/* SIOCSIWSCAN */
+-	(iw_handler) ieee80211_ioctl_giwscan,		/* SIOCGIWSCAN */
+-	(iw_handler) ieee80211_ioctl_siwessid,		/* SIOCSIWESSID */
+-	(iw_handler) ieee80211_ioctl_giwessid,		/* SIOCGIWESSID */
+-	(iw_handler) NULL,				/* SIOCSIWNICKN */
+-	(iw_handler) NULL,				/* SIOCGIWNICKN */
+-	(iw_handler) NULL,				/* -- hole -- */
+-	(iw_handler) NULL,				/* -- hole -- */
+-	(iw_handler) ieee80211_ioctl_siwrate,		/* SIOCSIWRATE */
+-	(iw_handler) ieee80211_ioctl_giwrate,		/* SIOCGIWRATE */
+-	(iw_handler) ieee80211_ioctl_siwrts,		/* SIOCSIWRTS */
+-	(iw_handler) ieee80211_ioctl_giwrts,		/* SIOCGIWRTS */
+-	(iw_handler) ieee80211_ioctl_siwfrag,		/* SIOCSIWFRAG */
+-	(iw_handler) ieee80211_ioctl_giwfrag,		/* SIOCGIWFRAG */
+-	(iw_handler) ieee80211_ioctl_siwtxpower,	/* SIOCSIWTXPOW */
+-	(iw_handler) ieee80211_ioctl_giwtxpower,	/* SIOCGIWTXPOW */
+-	(iw_handler) ieee80211_ioctl_siwretry,		/* SIOCSIWRETRY */
+-	(iw_handler) ieee80211_ioctl_giwretry,		/* SIOCGIWRETRY */
+-	(iw_handler) ieee80211_ioctl_siwencode,		/* SIOCSIWENCODE */
+-	(iw_handler) ieee80211_ioctl_giwencode,		/* SIOCGIWENCODE */
+-	(iw_handler) NULL,				/* SIOCSIWPOWER */
+-	(iw_handler) NULL,				/* SIOCGIWPOWER */
+-	(iw_handler) NULL,				/* -- hole -- */
+-	(iw_handler) NULL,				/* -- hole -- */
+-	(iw_handler) ieee80211_ioctl_siwgenie,		/* SIOCSIWGENIE */
+-	(iw_handler) NULL,				/* SIOCGIWGENIE */
+-	(iw_handler) ieee80211_ioctl_siwauth,		/* SIOCSIWAUTH */
+-	(iw_handler) ieee80211_ioctl_giwauth,		/* SIOCGIWAUTH */
+-	(iw_handler) ieee80211_ioctl_siwencodeext,	/* SIOCSIWENCODEEXT */
+-	(iw_handler) NULL,				/* SIOCGIWENCODEEXT */
+-	(iw_handler) NULL,				/* SIOCSIWPMKSA */
+-	(iw_handler) NULL,				/* -- hole -- */
+-};
+-
+-const struct iw_handler_def ieee80211_iw_handler_def =
+-{
+-	.num_standard	= ARRAY_SIZE(ieee80211_handler),
+-	.standard	= (iw_handler *) ieee80211_handler,
+-	.get_wireless_stats = ieee80211_get_wireless_stats,
+-};
+diff --git a/net/mac80211/ieee80211_key.h b/net/mac80211/ieee80211_key.h
+deleted file mode 100644
+index fc770e9..0000000
+--- a/net/mac80211/ieee80211_key.h
++++ /dev/null
+@@ -1,127 +0,0 @@
+-/*
+- * Copyright 2002-2004, Instant802 Networks, Inc.
+- * Copyright 2005, Devicescape Software, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#ifndef IEEE80211_KEY_H
+-#define IEEE80211_KEY_H
+-
+-#include <linux/types.h>
+-#include <linux/list.h>
+-#include <linux/crypto.h>
+-#include <net/mac80211.h>
+-
+-/* ALG_TKIP
+- * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block:
+- * Temporal Encryption Key (128 bits)
+- * Temporal Authenticator Tx MIC Key (64 bits)
+- * Temporal Authenticator Rx MIC Key (64 bits)
+- */
+-
+-#define WEP_IV_LEN 4
+-#define WEP_ICV_LEN 4
+-
+-#define ALG_TKIP_KEY_LEN 32
+-/* Starting offsets for each key */
+-#define ALG_TKIP_TEMP_ENCR_KEY 0
+-#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16
+-#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24
+-#define TKIP_IV_LEN 8
+-#define TKIP_ICV_LEN 4
+-
+-#define ALG_CCMP_KEY_LEN 16
+-#define CCMP_HDR_LEN 8
+-#define CCMP_MIC_LEN 8
+-#define CCMP_TK_LEN 16
+-#define CCMP_PN_LEN 6
+-
+-#define NUM_RX_DATA_QUEUES 17
+-
+-struct ieee80211_local;
+-struct ieee80211_sub_if_data;
+-struct sta_info;
+-
+-#define KEY_FLAG_UPLOADED_TO_HARDWARE	(1<<0)
+-
+-struct ieee80211_key {
+-	struct ieee80211_local *local;
+-	struct ieee80211_sub_if_data *sdata;
+-	struct sta_info *sta;
+-
+-	struct list_head list;
+-
+-	unsigned int flags;
+-
+-	union {
+-		struct {
+-			/* last used TSC */
+-			u32 iv32;
+-			u16 iv16;
+-			u16 p1k[5];
+-			int tx_initialized;
+-
+-			/* last received RSC */
+-			u32 iv32_rx[NUM_RX_DATA_QUEUES];
+-			u16 iv16_rx[NUM_RX_DATA_QUEUES];
+-			u16 p1k_rx[NUM_RX_DATA_QUEUES][5];
+-			int rx_initialized[NUM_RX_DATA_QUEUES];
+-		} tkip;
+-		struct {
+-			u8 tx_pn[6];
+-			u8 rx_pn[NUM_RX_DATA_QUEUES][6];
+-			struct crypto_cipher *tfm;
+-			u32 replays; /* dot11RSNAStatsCCMPReplays */
+-			/* scratch buffers for virt_to_page() (crypto API) */
+-#ifndef AES_BLOCK_LEN
+-#define AES_BLOCK_LEN 16
+-#endif
+-			u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
+-			u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
+-		} ccmp;
+-	} u;
+-
+-	/* number of times this key has been used */
+-	int tx_rx_count;
+-
+-#ifdef CONFIG_MAC80211_DEBUGFS
+-	struct {
+-		struct dentry *stalink;
+-		struct dentry *dir;
+-		struct dentry *keylen;
+-		struct dentry *flags;
+-		struct dentry *keyidx;
+-		struct dentry *hw_key_idx;
+-		struct dentry *tx_rx_count;
+-		struct dentry *algorithm;
+-		struct dentry *tx_spec;
+-		struct dentry *rx_spec;
+-		struct dentry *replays;
+-		struct dentry *key;
+-		struct dentry *ifindex;
+-	} debugfs;
+-#endif
+-
+-	/*
+-	 * key config, must be last because it contains key
+-	 * material as variable length member
+-	 */
+-	struct ieee80211_key_conf conf;
+-};
+-
+-struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+-					  struct sta_info *sta,
+-					  enum ieee80211_key_alg alg,
+-					  int idx,
+-					  size_t key_len,
+-					  const u8 *key_data);
+-void ieee80211_key_free(struct ieee80211_key *key);
+-void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
+-void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
+-void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
+-void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
+-
+-#endif /* IEEE80211_KEY_H */
+diff --git a/net/mac80211/ieee80211_led.c b/net/mac80211/ieee80211_led.c
+deleted file mode 100644
+index f401484..0000000
+--- a/net/mac80211/ieee80211_led.c
++++ /dev/null
+@@ -1,161 +0,0 @@
+-/*
+- * Copyright 2006, Johannes Berg <johannes at sipsolutions.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/* just for IFNAMSIZ */
+-#include <linux/if.h>
+-#include "ieee80211_led.h"
+-
+-void ieee80211_led_rx(struct ieee80211_local *local)
+-{
+-	if (unlikely(!local->rx_led))
+-		return;
+-	if (local->rx_led_counter++ % 2 == 0)
+-		led_trigger_event(local->rx_led, LED_OFF);
+-	else
+-		led_trigger_event(local->rx_led, LED_FULL);
+-}
+-
+-/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
+-void ieee80211_led_tx(struct ieee80211_local *local, int q)
+-{
+-	if (unlikely(!local->tx_led))
+-		return;
+-	/* not sure how this is supposed to work ... */
+-	local->tx_led_counter += 2*q-1;
+-	if (local->tx_led_counter % 2 == 0)
+-		led_trigger_event(local->tx_led, LED_OFF);
+-	else
+-		led_trigger_event(local->tx_led, LED_FULL);
+-}
+-
+-void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
+-{
+-	if (unlikely(!local->assoc_led))
+-		return;
+-	if (associated)
+-		led_trigger_event(local->assoc_led, LED_FULL);
+-	else
+-		led_trigger_event(local->assoc_led, LED_OFF);
+-}
+-
+-void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
+-{
+-	if (unlikely(!local->radio_led))
+-		return;
+-	if (enabled)
+-		led_trigger_event(local->radio_led, LED_FULL);
+-	else
+-		led_trigger_event(local->radio_led, LED_OFF);
+-}
+-
+-void ieee80211_led_init(struct ieee80211_local *local)
+-{
+-	local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+-	if (local->rx_led) {
+-		snprintf(local->rx_led_name, sizeof(local->rx_led_name),
+-			 "%srx", wiphy_name(local->hw.wiphy));
+-		local->rx_led->name = local->rx_led_name;
+-		if (led_trigger_register(local->rx_led)) {
+-			kfree(local->rx_led);
+-			local->rx_led = NULL;
+-		}
+-	}
+-
+-	local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+-	if (local->tx_led) {
+-		snprintf(local->tx_led_name, sizeof(local->tx_led_name),
+-			 "%stx", wiphy_name(local->hw.wiphy));
+-		local->tx_led->name = local->tx_led_name;
+-		if (led_trigger_register(local->tx_led)) {
+-			kfree(local->tx_led);
+-			local->tx_led = NULL;
+-		}
+-	}
+-
+-	local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+-	if (local->assoc_led) {
+-		snprintf(local->assoc_led_name, sizeof(local->assoc_led_name),
+-			 "%sassoc", wiphy_name(local->hw.wiphy));
+-		local->assoc_led->name = local->assoc_led_name;
+-		if (led_trigger_register(local->assoc_led)) {
+-			kfree(local->assoc_led);
+-			local->assoc_led = NULL;
+-		}
+-	}
+-
+-	local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+-	if (local->radio_led) {
+-		snprintf(local->radio_led_name, sizeof(local->radio_led_name),
+-			 "%sradio", wiphy_name(local->hw.wiphy));
+-		local->radio_led->name = local->radio_led_name;
+-		if (led_trigger_register(local->radio_led)) {
+-			kfree(local->radio_led);
+-			local->radio_led = NULL;
+-		}
+-	}
+-}
+-
+-void ieee80211_led_exit(struct ieee80211_local *local)
+-{
+-	if (local->radio_led) {
+-		led_trigger_unregister(local->radio_led);
+-		kfree(local->radio_led);
+-	}
+-	if (local->assoc_led) {
+-		led_trigger_unregister(local->assoc_led);
+-		kfree(local->assoc_led);
+-	}
+-	if (local->tx_led) {
+-		led_trigger_unregister(local->tx_led);
+-		kfree(local->tx_led);
+-	}
+-	if (local->rx_led) {
+-		led_trigger_unregister(local->rx_led);
+-		kfree(local->rx_led);
+-	}
+-}
+-
+-char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-
+-	if (local->radio_led)
+-		return local->radio_led_name;
+-	return NULL;
+-}
+-EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
+-
+-char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-
+-	if (local->assoc_led)
+-		return local->assoc_led_name;
+-	return NULL;
+-}
+-EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
+-
+-char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-
+-	if (local->tx_led)
+-		return local->tx_led_name;
+-	return NULL;
+-}
+-EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
+-
+-char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-
+-	if (local->rx_led)
+-		return local->rx_led_name;
+-	return NULL;
+-}
+-EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
+diff --git a/net/mac80211/ieee80211_led.h b/net/mac80211/ieee80211_led.h
+deleted file mode 100644
+index 77b1e1b..0000000
+--- a/net/mac80211/ieee80211_led.h
++++ /dev/null
+@@ -1,44 +0,0 @@
+-/*
+- * Copyright 2006, Johannes Berg <johannes at sipsolutions.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/list.h>
+-#include <linux/spinlock.h>
+-#include <linux/leds.h>
+-#include "ieee80211_i.h"
+-
+-#ifdef CONFIG_MAC80211_LEDS
+-extern void ieee80211_led_rx(struct ieee80211_local *local);
+-extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
+-extern void ieee80211_led_assoc(struct ieee80211_local *local,
+-				bool associated);
+-extern void ieee80211_led_radio(struct ieee80211_local *local,
+-				bool enabled);
+-extern void ieee80211_led_init(struct ieee80211_local *local);
+-extern void ieee80211_led_exit(struct ieee80211_local *local);
+-#else
+-static inline void ieee80211_led_rx(struct ieee80211_local *local)
+-{
+-}
+-static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
+-{
+-}
+-static inline void ieee80211_led_assoc(struct ieee80211_local *local,
+-				       bool associated)
+-{
+-}
+-static inline void ieee80211_led_radio(struct ieee80211_local *local,
+-				       bool enabled)
+-{
+-}
+-static inline void ieee80211_led_init(struct ieee80211_local *local)
+-{
+-}
+-static inline void ieee80211_led_exit(struct ieee80211_local *local)
+-{
+-}
+-#endif
+diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c
+deleted file mode 100644
+index b957e67..0000000
+--- a/net/mac80211/ieee80211_rate.c
++++ /dev/null
+@@ -1,246 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/rtnetlink.h>
+-#include "ieee80211_rate.h"
+-#include "ieee80211_i.h"
+-
+-struct rate_control_alg {
+-	struct list_head list;
+-	struct rate_control_ops *ops;
+-};
+-
+-static LIST_HEAD(rate_ctrl_algs);
+-static DEFINE_MUTEX(rate_ctrl_mutex);
+-
+-static char *ieee80211_default_rc_algo = CONFIG_MAC80211_RC_DEFAULT;
+-module_param(ieee80211_default_rc_algo, charp, 0644);
+-MODULE_PARM_DESC(ieee80211_default_rc_algo,
+-		 "Default rate control algorithm for mac80211 to use");
+-
+-int ieee80211_rate_control_register(struct rate_control_ops *ops)
+-{
+-	struct rate_control_alg *alg;
+-
+-	if (!ops->name)
+-		return -EINVAL;
+-
+-	mutex_lock(&rate_ctrl_mutex);
+-	list_for_each_entry(alg, &rate_ctrl_algs, list) {
+-		if (!strcmp(alg->ops->name, ops->name)) {
+-			/* don't register an algorithm twice */
+-			WARN_ON(1);
+-			mutex_unlock(&rate_ctrl_mutex);
+-			return -EALREADY;
+-		}
+-	}
+-
+-	alg = kzalloc(sizeof(*alg), GFP_KERNEL);
+-	if (alg == NULL) {
+-		mutex_unlock(&rate_ctrl_mutex);
+-		return -ENOMEM;
+-	}
+-	alg->ops = ops;
+-
+-	list_add_tail(&alg->list, &rate_ctrl_algs);
+-	mutex_unlock(&rate_ctrl_mutex);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL(ieee80211_rate_control_register);
+-
+-void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
+-{
+-	struct rate_control_alg *alg;
+-
+-	mutex_lock(&rate_ctrl_mutex);
+-	list_for_each_entry(alg, &rate_ctrl_algs, list) {
+-		if (alg->ops == ops) {
+-			list_del(&alg->list);
+-			kfree(alg);
+-			break;
+-		}
+-	}
+-	mutex_unlock(&rate_ctrl_mutex);
+-}
+-EXPORT_SYMBOL(ieee80211_rate_control_unregister);
+-
+-static struct rate_control_ops *
+-ieee80211_try_rate_control_ops_get(const char *name)
+-{
+-	struct rate_control_alg *alg;
+-	struct rate_control_ops *ops = NULL;
+-
+-	if (!name)
+-		return NULL;
+-
+-	mutex_lock(&rate_ctrl_mutex);
+-	list_for_each_entry(alg, &rate_ctrl_algs, list) {
+-		if (!strcmp(alg->ops->name, name))
+-			if (try_module_get(alg->ops->module)) {
+-				ops = alg->ops;
+-				break;
+-			}
+-	}
+-	mutex_unlock(&rate_ctrl_mutex);
+-	return ops;
+-}
+-
+-/* Get the rate control algorithm. */
+-static struct rate_control_ops *
+-ieee80211_rate_control_ops_get(const char *name)
+-{
+-	struct rate_control_ops *ops;
+-	const char *alg_name;
+-
+-	if (!name)
+-		alg_name = ieee80211_default_rc_algo;
+-	else
+-		alg_name = name;
+-
+-	ops = ieee80211_try_rate_control_ops_get(alg_name);
+-	if (!ops) {
+-		request_module("rc80211_%s", alg_name);
+-		ops = ieee80211_try_rate_control_ops_get(alg_name);
+-	}
+-	if (!ops && name)
+-		/* try default if specific alg requested but not found */
+-		ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo);
+-
+-	/* try built-in one if specific alg requested but not found */
+-	if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT))
+-		ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT);
+-
+-	return ops;
+-}
+-
+-static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
+-{
+-	module_put(ops->module);
+-}
+-
+-struct rate_control_ref *rate_control_alloc(const char *name,
+-					    struct ieee80211_local *local)
+-{
+-	struct rate_control_ref *ref;
+-
+-	ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
+-	if (!ref)
+-		goto fail_ref;
+-	kref_init(&ref->kref);
+-	ref->ops = ieee80211_rate_control_ops_get(name);
+-	if (!ref->ops)
+-		goto fail_ops;
+-	ref->priv = ref->ops->alloc(local);
+-	if (!ref->priv)
+-		goto fail_priv;
+-	return ref;
+-
+-fail_priv:
+-	ieee80211_rate_control_ops_put(ref->ops);
+-fail_ops:
+-	kfree(ref);
+-fail_ref:
+-	return NULL;
+-}
+-
+-static void rate_control_release(struct kref *kref)
+-{
+-	struct rate_control_ref *ctrl_ref;
+-
+-	ctrl_ref = container_of(kref, struct rate_control_ref, kref);
+-	ctrl_ref->ops->free(ctrl_ref->priv);
+-	ieee80211_rate_control_ops_put(ctrl_ref->ops);
+-	kfree(ctrl_ref);
+-}
+-
+-void rate_control_get_rate(struct net_device *dev,
+-			   struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+-			   struct rate_selection *sel)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct rate_control_ref *ref = local->rate_ctrl;
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-	struct sta_info *sta = sta_info_get(local, hdr->addr1);
+-	int i;
+-
+-	memset(sel, 0, sizeof(struct rate_selection));
+-
+-	ref->ops->get_rate(ref->priv, dev, mode, skb, sel);
+-
+-	/* Select a non-ERP backup rate. */
+-	if (!sel->nonerp) {
+-		for (i = 0; i < mode->num_rates - 1; i++) {
+-			struct ieee80211_rate *rate = &mode->rates[i];
+-			if (sel->rate->rate < rate->rate)
+-				break;
+-
+-			if (rate_supported(sta, mode, i) &&
+-			    !(rate->flags & IEEE80211_RATE_ERP))
+-				sel->nonerp = rate;
+-		}
+-	}
+-
+-	if (sta)
+-		sta_info_put(sta);
+-}
+-
+-struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
+-{
+-	kref_get(&ref->kref);
+-	return ref;
+-}
+-
+-void rate_control_put(struct rate_control_ref *ref)
+-{
+-	kref_put(&ref->kref, rate_control_release);
+-}
+-
+-int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
+-				 const char *name)
+-{
+-	struct rate_control_ref *ref, *old;
+-
+-	ASSERT_RTNL();
+-	if (local->open_count || netif_running(local->mdev))
+-		return -EBUSY;
+-
+-	ref = rate_control_alloc(name, local);
+-	if (!ref) {
+-		printk(KERN_WARNING "%s: Failed to select rate control "
+-		       "algorithm\n", wiphy_name(local->hw.wiphy));
+-		return -ENOENT;
+-	}
+-
+-	old = local->rate_ctrl;
+-	local->rate_ctrl = ref;
+-	if (old) {
+-		rate_control_put(old);
+-		sta_info_flush(local, NULL);
+-	}
+-
+-	printk(KERN_DEBUG "%s: Selected rate control "
+-	       "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
+-	       ref->ops->name);
+-
+-
+-	return 0;
+-}
+-
+-void rate_control_deinitialize(struct ieee80211_local *local)
+-{
+-	struct rate_control_ref *ref;
+-
+-	ref = local->rate_ctrl;
+-	local->rate_ctrl = NULL;
+-	rate_control_put(ref);
+-}
+-
+diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
+deleted file mode 100644
+index 73f19e8..0000000
+--- a/net/mac80211/ieee80211_rate.h
++++ /dev/null
+@@ -1,199 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005, Devicescape Software, Inc.
+- * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#ifndef IEEE80211_RATE_H
+-#define IEEE80211_RATE_H
+-
+-#include <linux/netdevice.h>
+-#include <linux/skbuff.h>
+-#include <linux/types.h>
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "sta_info.h"
+-
+-struct rate_selection {
+-	/* Selected transmission rate */
+-	struct ieee80211_rate *rate;
+-	/* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */
+-	struct ieee80211_rate *nonerp;
+-	/* probe with this rate, or NULL for no probing */
+-	struct ieee80211_rate *probe;
+-};
+-
+-struct rate_control_ops {
+-	struct module *module;
+-	const char *name;
+-	void (*tx_status)(void *priv, struct net_device *dev,
+-			  struct sk_buff *skb,
+-			  struct ieee80211_tx_status *status);
+-	void (*get_rate)(void *priv, struct net_device *dev,
+-			 struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+-			 struct rate_selection *sel);
+-	void (*rate_init)(void *priv, void *priv_sta,
+-			  struct ieee80211_local *local, struct sta_info *sta);
+-	void (*clear)(void *priv);
+-
+-	void *(*alloc)(struct ieee80211_local *local);
+-	void (*free)(void *priv);
+-	void *(*alloc_sta)(void *priv, gfp_t gfp);
+-	void (*free_sta)(void *priv, void *priv_sta);
+-
+-	int (*add_attrs)(void *priv, struct kobject *kobj);
+-	void (*remove_attrs)(void *priv, struct kobject *kobj);
+-	void (*add_sta_debugfs)(void *priv, void *priv_sta,
+-				struct dentry *dir);
+-	void (*remove_sta_debugfs)(void *priv, void *priv_sta);
+-};
+-
+-struct rate_control_ref {
+-	struct rate_control_ops *ops;
+-	void *priv;
+-	struct kref kref;
+-};
+-
+-int ieee80211_rate_control_register(struct rate_control_ops *ops);
+-void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
+-
+-/* Get a reference to the rate control algorithm. If `name' is NULL, get the
+- * first available algorithm. */
+-struct rate_control_ref *rate_control_alloc(const char *name,
+-					    struct ieee80211_local *local);
+-void rate_control_get_rate(struct net_device *dev,
+-			   struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+-			   struct rate_selection *sel);
+-struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
+-void rate_control_put(struct rate_control_ref *ref);
+-
+-static inline void rate_control_tx_status(struct net_device *dev,
+-					  struct sk_buff *skb,
+-					  struct ieee80211_tx_status *status)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct rate_control_ref *ref = local->rate_ctrl;
+-
+-	ref->ops->tx_status(ref->priv, dev, skb, status);
+-}
+-
+-
+-static inline void rate_control_rate_init(struct sta_info *sta,
+-					  struct ieee80211_local *local)
+-{
+-	struct rate_control_ref *ref = sta->rate_ctrl;
+-	ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta);
+-}
+-
+-
+-static inline void rate_control_clear(struct ieee80211_local *local)
+-{
+-	struct rate_control_ref *ref = local->rate_ctrl;
+-	ref->ops->clear(ref->priv);
+-}
+-
+-static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
+-					   gfp_t gfp)
+-{
+-	return ref->ops->alloc_sta(ref->priv, gfp);
+-}
+-
+-static inline void rate_control_free_sta(struct rate_control_ref *ref,
+-					 void *priv)
+-{
+-	ref->ops->free_sta(ref->priv, priv);
+-}
+-
+-static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
+-{
+-#ifdef CONFIG_MAC80211_DEBUGFS
+-	struct rate_control_ref *ref = sta->rate_ctrl;
+-	if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
+-		ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
+-					  sta->debugfs.dir);
+-#endif
+-}
+-
+-static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
+-{
+-#ifdef CONFIG_MAC80211_DEBUGFS
+-	struct rate_control_ref *ref = sta->rate_ctrl;
+-	if (ref->ops->remove_sta_debugfs)
+-		ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
+-#endif
+-}
+-
+-static inline int
+-rate_supported(struct sta_info *sta, struct ieee80211_hw_mode *mode, int index)
+-{
+-	return (sta == NULL || sta->supp_rates & BIT(index)) &&
+-	       (mode->rates[index].flags & IEEE80211_RATE_SUPPORTED);
+-}
+-
+-static inline int
+-rate_lowest_index(struct ieee80211_local *local, struct ieee80211_hw_mode *mode,
+-		  struct sta_info *sta)
+-{
+-	int i;
+-
+-	for (i = 0; i < mode->num_rates; i++) {
+-		if (rate_supported(sta, mode, i))
+-			return i;
+-	}
+-
+-	/* warn when we cannot find a rate. */
+-	WARN_ON(1);
+-
+-	return 0;
+-}
+-
+-static inline struct ieee80211_rate *
+-rate_lowest(struct ieee80211_local *local, struct ieee80211_hw_mode *mode,
+-	    struct sta_info *sta)
+-{
+-	return &mode->rates[rate_lowest_index(local, mode, sta)];
+-}
+-
+-
+-/* functions for rate control related to a device */
+-int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
+-				 const char *name);
+-void rate_control_deinitialize(struct ieee80211_local *local);
+-
+-
+-/* Rate control algorithms */
+-#if defined(RC80211_SIMPLE_COMPILE) || \
+-	(defined(CONFIG_MAC80211_RC_SIMPLE) && \
+-	 !defined(CONFIG_MAC80211_RC_SIMPLE_MODULE))
+-extern int rc80211_simple_init(void);
+-extern void rc80211_simple_exit(void);
+-#else
+-static inline int rc80211_simple_init(void)
+-{
+-	return 0;
+-}
+-static inline void rc80211_simple_exit(void)
+-{
+-}
+-#endif
+-
+-#if defined(RC80211_PID_COMPILE) || \
+-	(defined(CONFIG_MAC80211_RC_PID) && \
+-	 !defined(CONFIG_MAC80211_RC_PID_MODULE))
+-extern int rc80211_pid_init(void);
+-extern void rc80211_pid_exit(void);
+-#else
+-static inline int rc80211_pid_init(void)
+-{
+-	return 0;
+-}
+-static inline void rc80211_pid_exit(void)
+-{
+-}
+-#endif
+-
+-#endif /* IEEE80211_RATE_H */
+diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
+deleted file mode 100644
+index c170685..0000000
+--- a/net/mac80211/ieee80211_sta.c
++++ /dev/null
+@@ -1,3632 +0,0 @@
+-/*
+- * BSS client mode implementation
+- * Copyright 2003, Jouni Malinen <jkmaline at cc.hut.fi>
+- * Copyright 2004, Instant802 Networks, Inc.
+- * Copyright 2005, Devicescape Software, Inc.
+- * Copyright 2006-2007	Jiri Benc <jbenc at suse.cz>
+- * Copyright 2007, Michael Wu <flamingice at sourmilk.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/* TODO:
+- * order BSS list by RSSI(?) ("quality of AP")
+- * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
+- *    SSID)
+- */
+-#include <linux/delay.h>
+-#include <linux/if_ether.h>
+-#include <linux/skbuff.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/wireless.h>
+-#include <linux/random.h>
+-#include <linux/etherdevice.h>
+-#include <net/iw_handler.h>
+-#include <asm/types.h>
+-
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
+-#include "ieee80211_led.h"
+-
+-#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
+-#define IEEE80211_AUTH_MAX_TRIES 3
+-#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
+-#define IEEE80211_ASSOC_MAX_TRIES 3
+-#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
+-#define IEEE80211_PROBE_INTERVAL (60 * HZ)
+-#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
+-#define IEEE80211_SCAN_INTERVAL (2 * HZ)
+-#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
+-#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ)
+-
+-#define IEEE80211_PROBE_DELAY (HZ / 33)
+-#define IEEE80211_CHANNEL_TIME (HZ / 33)
+-#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
+-#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
+-#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
+-#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
+-
+-#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
+-
+-
+-#define IEEE80211_FC(type, stype) cpu_to_le16(type | stype)
+-
+-#define ERP_INFO_USE_PROTECTION BIT(1)
+-
+-/* mgmt header + 1 byte action code */
+-#define IEEE80211_MIN_ACTION_SIZE (24 + 1)
+-
+-#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
+-#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
+-#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0
+-#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
+-#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
+-
+-/* next values represent the buffer size for A-MPDU frame.
+- * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */
+-#define IEEE80211_MIN_AMPDU_BUF 0x8
+-#define IEEE80211_MAX_AMPDU_BUF 0x40
+-
+-static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
+-				     u8 *ssid, size_t ssid_len);
+-static struct ieee80211_sta_bss *
+-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
+-		     u8 *ssid, u8 ssid_len);
+-static void ieee80211_rx_bss_put(struct net_device *dev,
+-				 struct ieee80211_sta_bss *bss);
+-static int ieee80211_sta_find_ibss(struct net_device *dev,
+-				   struct ieee80211_if_sta *ifsta);
+-static int ieee80211_sta_wep_configured(struct net_device *dev);
+-static int ieee80211_sta_start_scan(struct net_device *dev,
+-				    u8 *ssid, size_t ssid_len);
+-static int ieee80211_sta_config_auth(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta);
+-
+-
+-/* Parsed Information Elements */
+-struct ieee802_11_elems {
+-	/* pointers to IEs */
+-	u8 *ssid;
+-	u8 *supp_rates;
+-	u8 *fh_params;
+-	u8 *ds_params;
+-	u8 *cf_params;
+-	u8 *tim;
+-	u8 *ibss_params;
+-	u8 *challenge;
+-	u8 *wpa;
+-	u8 *rsn;
+-	u8 *erp_info;
+-	u8 *ext_supp_rates;
+-	u8 *wmm_info;
+-	u8 *wmm_param;
+-	u8 *ht_cap_elem;
+-	u8 *ht_info_elem;
+-	/* length of them, respectively */
+-	u8 ssid_len;
+-	u8 supp_rates_len;
+-	u8 fh_params_len;
+-	u8 ds_params_len;
+-	u8 cf_params_len;
+-	u8 tim_len;
+-	u8 ibss_params_len;
+-	u8 challenge_len;
+-	u8 wpa_len;
+-	u8 rsn_len;
+-	u8 erp_info_len;
+-	u8 ext_supp_rates_len;
+-	u8 wmm_info_len;
+-	u8 wmm_param_len;
+-	u8 ht_cap_elem_len;
+-	u8 ht_info_elem_len;
+-};
+-
+-static void ieee802_11_parse_elems(u8 *start, size_t len,
+-				   struct ieee802_11_elems *elems)
+-{
+-	size_t left = len;
+-	u8 *pos = start;
+-
+-	memset(elems, 0, sizeof(*elems));
+-
+-	while (left >= 2) {
+-		u8 id, elen;
+-
+-		id = *pos++;
+-		elen = *pos++;
+-		left -= 2;
+-
+-		if (elen > left)
+-			return;
+-
+-		switch (id) {
+-		case WLAN_EID_SSID:
+-			elems->ssid = pos;
+-			elems->ssid_len = elen;
+-			break;
+-		case WLAN_EID_SUPP_RATES:
+-			elems->supp_rates = pos;
+-			elems->supp_rates_len = elen;
+-			break;
+-		case WLAN_EID_FH_PARAMS:
+-			elems->fh_params = pos;
+-			elems->fh_params_len = elen;
+-			break;
+-		case WLAN_EID_DS_PARAMS:
+-			elems->ds_params = pos;
+-			elems->ds_params_len = elen;
+-			break;
+-		case WLAN_EID_CF_PARAMS:
+-			elems->cf_params = pos;
+-			elems->cf_params_len = elen;
+-			break;
+-		case WLAN_EID_TIM:
+-			elems->tim = pos;
+-			elems->tim_len = elen;
+-			break;
+-		case WLAN_EID_IBSS_PARAMS:
+-			elems->ibss_params = pos;
+-			elems->ibss_params_len = elen;
+-			break;
+-		case WLAN_EID_CHALLENGE:
+-			elems->challenge = pos;
+-			elems->challenge_len = elen;
+-			break;
+-		case WLAN_EID_WPA:
+-			if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
+-			    pos[2] == 0xf2) {
+-				/* Microsoft OUI (00:50:F2) */
+-				if (pos[3] == 1) {
+-					/* OUI Type 1 - WPA IE */
+-					elems->wpa = pos;
+-					elems->wpa_len = elen;
+-				} else if (elen >= 5 && pos[3] == 2) {
+-					if (pos[4] == 0) {
+-						elems->wmm_info = pos;
+-						elems->wmm_info_len = elen;
+-					} else if (pos[4] == 1) {
+-						elems->wmm_param = pos;
+-						elems->wmm_param_len = elen;
+-					}
+-				}
+-			}
+-			break;
+-		case WLAN_EID_RSN:
+-			elems->rsn = pos;
+-			elems->rsn_len = elen;
+-			break;
+-		case WLAN_EID_ERP_INFO:
+-			elems->erp_info = pos;
+-			elems->erp_info_len = elen;
+-			break;
+-		case WLAN_EID_EXT_SUPP_RATES:
+-			elems->ext_supp_rates = pos;
+-			elems->ext_supp_rates_len = elen;
+-			break;
+-		case WLAN_EID_HT_CAPABILITY:
+-			elems->ht_cap_elem = pos;
+-			elems->ht_cap_elem_len = elen;
+-			break;
+-		case WLAN_EID_HT_EXTRA_INFO:
+-			elems->ht_info_elem = pos;
+-			elems->ht_info_elem_len = elen;
+-			break;
+-		default:
+-			break;
+-		}
+-
+-		left -= elen;
+-		pos += elen;
+-	}
+-}
+-
+-
+-static int ecw2cw(int ecw)
+-{
+-	int cw = 1;
+-	while (ecw > 0) {
+-		cw <<= 1;
+-		ecw--;
+-	}
+-	return cw - 1;
+-}
+-
+-static void ieee80211_sta_wmm_params(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta,
+-				     u8 *wmm_param, size_t wmm_param_len)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_tx_queue_params params;
+-	size_t left;
+-	int count;
+-	u8 *pos;
+-
+-	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
+-		return;
+-	count = wmm_param[6] & 0x0f;
+-	if (count == ifsta->wmm_last_param_set)
+-		return;
+-	ifsta->wmm_last_param_set = count;
+-
+-	pos = wmm_param + 8;
+-	left = wmm_param_len - 8;
+-
+-	memset(&params, 0, sizeof(params));
+-
+-	if (!local->ops->conf_tx)
+-		return;
+-
+-	local->wmm_acm = 0;
+-	for (; left >= 4; left -= 4, pos += 4) {
+-		int aci = (pos[0] >> 5) & 0x03;
+-		int acm = (pos[0] >> 4) & 0x01;
+-		int queue;
+-
+-		switch (aci) {
+-		case 1:
+-			queue = IEEE80211_TX_QUEUE_DATA3;
+-			if (acm) {
+-				local->wmm_acm |= BIT(0) | BIT(3);
+-			}
+-			break;
+-		case 2:
+-			queue = IEEE80211_TX_QUEUE_DATA1;
+-			if (acm) {
+-				local->wmm_acm |= BIT(4) | BIT(5);
+-			}
+-			break;
+-		case 3:
+-			queue = IEEE80211_TX_QUEUE_DATA0;
+-			if (acm) {
+-				local->wmm_acm |= BIT(6) | BIT(7);
+-			}
+-			break;
+-		case 0:
+-		default:
+-			queue = IEEE80211_TX_QUEUE_DATA2;
+-			if (acm) {
+-				local->wmm_acm |= BIT(1) | BIT(2);
+-			}
+-			break;
+-		}
+-
+-		params.aifs = pos[0] & 0x0f;
+-		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
+-		params.cw_min = ecw2cw(pos[1] & 0x0f);
+-		/* TXOP is in units of 32 usec; burst_time in 0.1 ms */
+-		params.burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100;
+-		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
+-		       "cWmin=%d cWmax=%d burst=%d\n",
+-		       dev->name, queue, aci, acm, params.aifs, params.cw_min,
+-		       params.cw_max, params.burst_time);
+-		/* TODO: handle ACM (block TX, fallback to next lowest allowed
+-		 * AC for now) */
+-		if (local->ops->conf_tx(local_to_hw(local), queue, &params)) {
+-			printk(KERN_DEBUG "%s: failed to set TX queue "
+-			       "parameters for queue %d\n", dev->name, queue);
+-		}
+-	}
+-}
+-
+-static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
+-					   bool use_protection,
+-					   bool use_short_preamble)
+-{
+-	struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
+-	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-	DECLARE_MAC_BUF(mac);
+-	u32 changed = 0;
+-
+-	if (use_protection != bss_conf->use_cts_prot) {
+-		if (net_ratelimit()) {
+-			printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
+-			       "%s)\n",
+-			       sdata->dev->name,
+-			       use_protection ? "enabled" : "disabled",
+-			       print_mac(mac, ifsta->bssid));
+-		}
+-		bss_conf->use_cts_prot = use_protection;
+-		changed |= BSS_CHANGED_ERP_CTS_PROT;
+-	}
+-
+-	if (use_short_preamble != bss_conf->use_short_preamble) {
+-		if (net_ratelimit()) {
+-			printk(KERN_DEBUG "%s: switched to %s barker preamble"
+-			       " (BSSID=%s)\n",
+-			       sdata->dev->name,
+-			       use_short_preamble ? "short" : "long",
+-			       print_mac(mac, ifsta->bssid));
+-		}
+-		bss_conf->use_short_preamble = use_short_preamble;
+-		changed |= BSS_CHANGED_ERP_PREAMBLE;
+-	}
+-
+-	return changed;
+-}
+-
+-static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
+-				   u8 erp_value)
+-{
+-	bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
+-	bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
+-
+-	return ieee80211_handle_protect_preamb(sdata,
+-			use_protection, use_short_preamble);
+-}
+-
+-static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
+-					   struct ieee80211_sta_bss *bss)
+-{
+-	u32 changed = 0;
+-
+-	if (bss->has_erp_value)
+-		changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value);
+-	else {
+-		u16 capab = bss->capability;
+-		changed |= ieee80211_handle_protect_preamb(sdata, false,
+-				(capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
+-	}
+-
+-	return changed;
+-}
+-
+-int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
+-				   struct ieee80211_ht_info *ht_info)
+-{
+-
+-	if (ht_info == NULL)
+-		return -EINVAL;
+-
+-	memset(ht_info, 0, sizeof(*ht_info));
+-
+-	if (ht_cap_ie) {
+-		u8 ampdu_info = ht_cap_ie->ampdu_params_info;
+-
+-		ht_info->ht_supported = 1;
+-		ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
+-		ht_info->ampdu_factor =
+-			ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
+-		ht_info->ampdu_density =
+-			(ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
+-		memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
+-	} else
+-		ht_info->ht_supported = 0;
+-
+-	return 0;
+-}
+-
+-int ieee80211_ht_addt_info_ie_to_ht_bss_info(
+-			struct ieee80211_ht_addt_info *ht_add_info_ie,
+-			struct ieee80211_ht_bss_info *bss_info)
+-{
+-	if (bss_info == NULL)
+-		return -EINVAL;
+-
+-	memset(bss_info, 0, sizeof(*bss_info));
+-
+-	if (ht_add_info_ie) {
+-		u16 op_mode;
+-		op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
+-
+-		bss_info->primary_channel = ht_add_info_ie->control_chan;
+-		bss_info->bss_cap = ht_add_info_ie->ht_param;
+-		bss_info->bss_op_mode = (u8)(op_mode & 0xff);
+-	}
+-
+-	return 0;
+-}
+-
+-static void ieee80211_sta_send_associnfo(struct net_device *dev,
+-					 struct ieee80211_if_sta *ifsta)
+-{
+-	char *buf;
+-	size_t len;
+-	int i;
+-	union iwreq_data wrqu;
+-
+-	if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
+-		return;
+-
+-	buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
+-				ifsta->assocresp_ies_len), GFP_KERNEL);
+-	if (!buf)
+-		return;
+-
+-	len = sprintf(buf, "ASSOCINFO(");
+-	if (ifsta->assocreq_ies) {
+-		len += sprintf(buf + len, "ReqIEs=");
+-		for (i = 0; i < ifsta->assocreq_ies_len; i++) {
+-			len += sprintf(buf + len, "%02x",
+-				       ifsta->assocreq_ies[i]);
+-		}
+-	}
+-	if (ifsta->assocresp_ies) {
+-		if (ifsta->assocreq_ies)
+-			len += sprintf(buf + len, " ");
+-		len += sprintf(buf + len, "RespIEs=");
+-		for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+-			len += sprintf(buf + len, "%02x",
+-				       ifsta->assocresp_ies[i]);
+-		}
+-	}
+-	len += sprintf(buf + len, ")");
+-
+-	if (len > IW_CUSTOM_MAX) {
+-		len = sprintf(buf, "ASSOCRESPIE=");
+-		for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+-			len += sprintf(buf + len, "%02x",
+-				       ifsta->assocresp_ies[i]);
+-		}
+-	}
+-
+-	memset(&wrqu, 0, sizeof(wrqu));
+-	wrqu.data.length = len;
+-	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+-
+-	kfree(buf);
+-}
+-
+-
+-static void ieee80211_set_associated(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta,
+-				     bool assoc)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_local *local = sdata->local;
+-	union iwreq_data wrqu;
+-	u32 changed = BSS_CHANGED_ASSOC;
+-
+-	if (assoc) {
+-		struct ieee80211_sta_bss *bss;
+-
+-		ifsta->flags |= IEEE80211_STA_ASSOCIATED;
+-
+-		if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+-			return;
+-
+-		bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
+-					   local->hw.conf.channel,
+-					   ifsta->ssid, ifsta->ssid_len);
+-		if (bss) {
+-			changed |= ieee80211_handle_bss_capability(sdata, bss);
+-			ieee80211_rx_bss_put(dev, bss);
+-		}
+-
+-		netif_carrier_on(dev);
+-		ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
+-		memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
+-		memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
+-		ieee80211_sta_send_associnfo(dev, ifsta);
+-	} else {
+-		ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
+-
+-		netif_carrier_off(dev);
+-		ieee80211_reset_erp_info(dev);
+-		memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+-	}
+-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+-	wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+-	ifsta->last_probe = jiffies;
+-	ieee80211_led_assoc(local, assoc);
+-
+-	ieee80211_bss_info_change_notify(sdata, changed);
+-}
+-
+-static void ieee80211_set_disassoc(struct net_device *dev,
+-				   struct ieee80211_if_sta *ifsta, int deauth)
+-{
+-	if (deauth)
+-		ifsta->auth_tries = 0;
+-	ifsta->assoc_tries = 0;
+-	ieee80211_set_associated(dev, ifsta, 0);
+-}
+-
+-static void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
+-			     int encrypt)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_tx_packet_data *pkt_data;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	skb->dev = sdata->local->mdev;
+-	skb_set_mac_header(skb, 0);
+-	skb_set_network_header(skb, 0);
+-	skb_set_transport_header(skb, 0);
+-
+-	pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+-	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
+-	pkt_data->ifindex = sdata->dev->ifindex;
+-	if (!encrypt)
+-		pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
+-
+-	dev_queue_xmit(skb);
+-}
+-
+-
+-static void ieee80211_send_auth(struct net_device *dev,
+-				struct ieee80211_if_sta *ifsta,
+-				int transaction, u8 *extra, size_t extra_len,
+-				int encrypt)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct sk_buff *skb;
+-	struct ieee80211_mgmt *mgmt;
+-
+-	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+-			    sizeof(*mgmt) + 6 + extra_len);
+-	if (!skb) {
+-		printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
+-		       "frame\n", dev->name);
+-		return;
+-	}
+-	skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+-	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
+-	memset(mgmt, 0, 24 + 6);
+-	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-					   IEEE80211_STYPE_AUTH);
+-	if (encrypt)
+-		mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+-	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+-	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+-	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+-	mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
+-	mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
+-	ifsta->auth_transaction = transaction + 1;
+-	mgmt->u.auth.status_code = cpu_to_le16(0);
+-	if (extra)
+-		memcpy(skb_put(skb, extra_len), extra, extra_len);
+-
+-	ieee80211_sta_tx(dev, skb, encrypt);
+-}
+-
+-
+-static void ieee80211_authenticate(struct net_device *dev,
+-				   struct ieee80211_if_sta *ifsta)
+-{
+-	DECLARE_MAC_BUF(mac);
+-
+-	ifsta->auth_tries++;
+-	if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
+-		printk(KERN_DEBUG "%s: authentication with AP %s"
+-		       " timed out\n",
+-		       dev->name, print_mac(mac, ifsta->bssid));
+-		ifsta->state = IEEE80211_DISABLED;
+-		return;
+-	}
+-
+-	ifsta->state = IEEE80211_AUTHENTICATE;
+-	printk(KERN_DEBUG "%s: authenticate with AP %s\n",
+-	       dev->name, print_mac(mac, ifsta->bssid));
+-
+-	ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0);
+-
+-	mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
+-}
+-
+-
+-static void ieee80211_send_assoc(struct net_device *dev,
+-				 struct ieee80211_if_sta *ifsta)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_hw_mode *mode;
+-	struct sk_buff *skb;
+-	struct ieee80211_mgmt *mgmt;
+-	u8 *pos, *ies;
+-	int i, len;
+-	u16 capab;
+-	struct ieee80211_sta_bss *bss;
+-	int wmm = 0;
+-
+-	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+-			    sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
+-			    ifsta->ssid_len);
+-	if (!skb) {
+-		printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
+-		       "frame\n", dev->name);
+-		return;
+-	}
+-	skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+-	mode = local->oper_hw_mode;
+-	capab = ifsta->capab;
+-	if (mode->mode == MODE_IEEE80211G) {
+-		capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
+-			WLAN_CAPABILITY_SHORT_PREAMBLE;
+-	}
+-	bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
+-				   ifsta->ssid, ifsta->ssid_len);
+-	if (bss) {
+-		if (bss->capability & WLAN_CAPABILITY_PRIVACY)
+-			capab |= WLAN_CAPABILITY_PRIVACY;
+-		if (bss->wmm_ie) {
+-			wmm = 1;
+-		}
+-		ieee80211_rx_bss_put(dev, bss);
+-	}
+-
+-	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+-	memset(mgmt, 0, 24);
+-	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+-	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+-	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+-
+-	if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
+-		skb_put(skb, 10);
+-		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-						   IEEE80211_STYPE_REASSOC_REQ);
+-		mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
+-		mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);
+-		memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
+-		       ETH_ALEN);
+-	} else {
+-		skb_put(skb, 4);
+-		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-						   IEEE80211_STYPE_ASSOC_REQ);
+-		mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
+-		mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);
+-	}
+-
+-	/* SSID */
+-	ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
+-	*pos++ = WLAN_EID_SSID;
+-	*pos++ = ifsta->ssid_len;
+-	memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+-
+-	len = mode->num_rates;
+-	if (len > 8)
+-		len = 8;
+-	pos = skb_put(skb, len + 2);
+-	*pos++ = WLAN_EID_SUPP_RATES;
+-	*pos++ = len;
+-	for (i = 0; i < len; i++) {
+-		int rate = mode->rates[i].rate;
+-		*pos++ = (u8) (rate / 5);
+-	}
+-
+-	if (mode->num_rates > len) {
+-		pos = skb_put(skb, mode->num_rates - len + 2);
+-		*pos++ = WLAN_EID_EXT_SUPP_RATES;
+-		*pos++ = mode->num_rates - len;
+-		for (i = len; i < mode->num_rates; i++) {
+-			int rate = mode->rates[i].rate;
+-			*pos++ = (u8) (rate / 5);
+-		}
+-	}
+-
+-	if (ifsta->extra_ie) {
+-		pos = skb_put(skb, ifsta->extra_ie_len);
+-		memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
+-	}
+-
+-	if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
+-		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;
+-	}
+-	/* wmm support is a must to HT */
+-	if (wmm && mode->ht_info.ht_supported) {
+-		__le16 tmp = cpu_to_le16(mode->ht_info.cap);
+-		pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
+-		*pos++ = WLAN_EID_HT_CAPABILITY;
+-		*pos++ = sizeof(struct ieee80211_ht_cap);
+-		memset(pos, 0, sizeof(struct ieee80211_ht_cap));
+-		memcpy(pos, &tmp, sizeof(u16));
+-		pos += sizeof(u16);
+-		*pos++ = (mode->ht_info.ampdu_factor |
+-				(mode->ht_info.ampdu_density << 2));
+-		memcpy(pos, mode->ht_info.supp_mcs_set, 16);
+-	}
+-
+-	kfree(ifsta->assocreq_ies);
+-	ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
+-	ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
+-	if (ifsta->assocreq_ies)
+-		memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
+-
+-	ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-
+-static void ieee80211_send_deauth(struct net_device *dev,
+-				  struct ieee80211_if_sta *ifsta, u16 reason)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct sk_buff *skb;
+-	struct ieee80211_mgmt *mgmt;
+-
+-	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
+-	if (!skb) {
+-		printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
+-		       "frame\n", dev->name);
+-		return;
+-	}
+-	skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+-	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+-	memset(mgmt, 0, 24);
+-	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+-	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+-	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+-	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-					   IEEE80211_STYPE_DEAUTH);
+-	skb_put(skb, 2);
+-	mgmt->u.deauth.reason_code = cpu_to_le16(reason);
+-
+-	ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-
+-static void ieee80211_send_disassoc(struct net_device *dev,
+-				    struct ieee80211_if_sta *ifsta, u16 reason)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct sk_buff *skb;
+-	struct ieee80211_mgmt *mgmt;
+-
+-	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
+-	if (!skb) {
+-		printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
+-		       "frame\n", dev->name);
+-		return;
+-	}
+-	skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+-	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+-	memset(mgmt, 0, 24);
+-	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+-	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+-	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+-	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-					   IEEE80211_STYPE_DISASSOC);
+-	skb_put(skb, 2);
+-	mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
+-
+-	ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-
+-static int ieee80211_privacy_mismatch(struct net_device *dev,
+-				      struct ieee80211_if_sta *ifsta)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sta_bss *bss;
+-	int bss_privacy;
+-	int wep_privacy;
+-	int privacy_invoked;
+-
+-	if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
+-		return 0;
+-
+-	bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
+-				   ifsta->ssid, ifsta->ssid_len);
+-	if (!bss)
+-		return 0;
+-
+-	bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
+-	wep_privacy = !!ieee80211_sta_wep_configured(dev);
+-	privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
+-
+-	ieee80211_rx_bss_put(dev, bss);
+-
+-	if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
+-		return 0;
+-
+-	return 1;
+-}
+-
+-
+-static void ieee80211_associate(struct net_device *dev,
+-				struct ieee80211_if_sta *ifsta)
+-{
+-	DECLARE_MAC_BUF(mac);
+-
+-	ifsta->assoc_tries++;
+-	if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
+-		printk(KERN_DEBUG "%s: association with AP %s"
+-		       " timed out\n",
+-		       dev->name, print_mac(mac, ifsta->bssid));
+-		ifsta->state = IEEE80211_DISABLED;
+-		return;
+-	}
+-
+-	ifsta->state = IEEE80211_ASSOCIATE;
+-	printk(KERN_DEBUG "%s: associate with AP %s\n",
+-	       dev->name, print_mac(mac, ifsta->bssid));
+-	if (ieee80211_privacy_mismatch(dev, ifsta)) {
+-		printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
+-		       "mixed-cell disabled - abort association\n", dev->name);
+-		ifsta->state = IEEE80211_DISABLED;
+-		return;
+-	}
+-
+-	ieee80211_send_assoc(dev, ifsta);
+-
+-	mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
+-}
+-
+-
+-static void ieee80211_associated(struct net_device *dev,
+-				 struct ieee80211_if_sta *ifsta)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct sta_info *sta;
+-	int disassoc;
+-	DECLARE_MAC_BUF(mac);
+-
+-	/* TODO: start monitoring current AP signal quality and number of
+-	 * missed beacons. Scan other channels every now and then and search
+-	 * for better APs. */
+-	/* TODO: remove expired BSSes */
+-
+-	ifsta->state = IEEE80211_ASSOCIATED;
+-
+-	sta = sta_info_get(local, ifsta->bssid);
+-	if (!sta) {
+-		printk(KERN_DEBUG "%s: No STA entry for own AP %s\n",
+-		       dev->name, print_mac(mac, ifsta->bssid));
+-		disassoc = 1;
+-	} else {
+-		disassoc = 0;
+-		if (time_after(jiffies,
+-			       sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
+-			if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
+-				printk(KERN_DEBUG "%s: No ProbeResp from "
+-				       "current AP %s - assume out of "
+-				       "range\n",
+-				       dev->name, print_mac(mac, ifsta->bssid));
+-				disassoc = 1;
+-				sta_info_free(sta);
+-			} else
+-				ieee80211_send_probe_req(dev, ifsta->bssid,
+-							 local->scan_ssid,
+-							 local->scan_ssid_len);
+-			ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
+-		} else {
+-			ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
+-			if (time_after(jiffies, ifsta->last_probe +
+-				       IEEE80211_PROBE_INTERVAL)) {
+-				ifsta->last_probe = jiffies;
+-				ieee80211_send_probe_req(dev, ifsta->bssid,
+-							 ifsta->ssid,
+-							 ifsta->ssid_len);
+-			}
+-		}
+-		sta_info_put(sta);
+-	}
+-	if (disassoc) {
+-		ifsta->state = IEEE80211_DISABLED;
+-		ieee80211_set_associated(dev, ifsta, 0);
+-	} else {
+-		mod_timer(&ifsta->timer, jiffies +
+-				      IEEE80211_MONITORING_INTERVAL);
+-	}
+-}
+-
+-
+-static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
+-				     u8 *ssid, size_t ssid_len)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_hw_mode *mode;
+-	struct sk_buff *skb;
+-	struct ieee80211_mgmt *mgmt;
+-	u8 *pos, *supp_rates, *esupp_rates = NULL;
+-	int i;
+-
+-	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
+-	if (!skb) {
+-		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
+-		       "request\n", dev->name);
+-		return;
+-	}
+-	skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+-	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+-	memset(mgmt, 0, 24);
+-	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-					   IEEE80211_STYPE_PROBE_REQ);
+-	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+-	if (dst) {
+-		memcpy(mgmt->da, dst, ETH_ALEN);
+-		memcpy(mgmt->bssid, dst, ETH_ALEN);
+-	} else {
+-		memset(mgmt->da, 0xff, ETH_ALEN);
+-		memset(mgmt->bssid, 0xff, ETH_ALEN);
+-	}
+-	pos = skb_put(skb, 2 + ssid_len);
+-	*pos++ = WLAN_EID_SSID;
+-	*pos++ = ssid_len;
+-	memcpy(pos, ssid, ssid_len);
+-
+-	supp_rates = skb_put(skb, 2);
+-	supp_rates[0] = WLAN_EID_SUPP_RATES;
+-	supp_rates[1] = 0;
+-	mode = local->oper_hw_mode;
+-	for (i = 0; i < mode->num_rates; i++) {
+-		struct ieee80211_rate *rate = &mode->rates[i];
+-		if (!(rate->flags & IEEE80211_RATE_SUPPORTED))
+-			continue;
+-		if (esupp_rates) {
+-			pos = skb_put(skb, 1);
+-			esupp_rates[1]++;
+-		} else if (supp_rates[1] == 8) {
+-			esupp_rates = skb_put(skb, 3);
+-			esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
+-			esupp_rates[1] = 1;
+-			pos = &esupp_rates[2];
+-		} else {
+-			pos = skb_put(skb, 1);
+-			supp_rates[1]++;
+-		}
+-		*pos = rate->rate / 5;
+-	}
+-
+-	ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-
+-static int ieee80211_sta_wep_configured(struct net_device *dev)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (!sdata || !sdata->default_key ||
+-	    sdata->default_key->conf.alg != ALG_WEP)
+-		return 0;
+-	return 1;
+-}
+-
+-
+-static void ieee80211_auth_completed(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta)
+-{
+-	printk(KERN_DEBUG "%s: authenticated\n", dev->name);
+-	ifsta->flags |= IEEE80211_STA_AUTHENTICATED;
+-	ieee80211_associate(dev, ifsta);
+-}
+-
+-
+-static void ieee80211_auth_challenge(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta,
+-				     struct ieee80211_mgmt *mgmt,
+-				     size_t len)
+-{
+-	u8 *pos;
+-	struct ieee802_11_elems elems;
+-
+-	printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
+-	pos = mgmt->u.auth.variable;
+-	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+-	if (!elems.challenge) {
+-		printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
+-		       "frame\n", dev->name);
+-		return;
+-	}
+-	ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,
+-			    elems.challenge_len + 2, 1);
+-}
+-
+-static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid,
+-					u8 dialog_token, u16 status, u16 policy,
+-					u16 buf_size, u16 timeout)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct sk_buff *skb;
+-	struct ieee80211_mgmt *mgmt;
+-	u16 capab;
+-
+-	skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
+-					sizeof(mgmt->u.action.u.addba_resp));
+-	if (!skb) {
+-		printk(KERN_DEBUG "%s: failed to allocate buffer "
+-		       "for addba resp frame\n", dev->name);
+-		return;
+-	}
+-
+-	skb_reserve(skb, local->hw.extra_tx_headroom);
+-	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+-	memset(mgmt, 0, 24);
+-	memcpy(mgmt->da, da, ETH_ALEN);
+-	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
+-		memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
+-	else
+-		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+-	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-					   IEEE80211_STYPE_ACTION);
+-
+-	skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
+-	mgmt->u.action.category = WLAN_CATEGORY_BACK;
+-	mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
+-	mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
+-
+-	capab = (u16)(policy << 1);	/* bit 1 aggregation policy */
+-	capab |= (u16)(tid << 2); 	/* bit 5:2 TID number */
+-	capab |= (u16)(buf_size << 6);	/* bit 15:6 max size of aggregation */
+-
+-	mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
+-	mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
+-	mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
+-
+-	ieee80211_sta_tx(dev, skb, 0);
+-
+-	return;
+-}
+-
+-static void ieee80211_sta_process_addba_request(struct net_device *dev,
+-						struct ieee80211_mgmt *mgmt,
+-						size_t len)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_hw *hw = &local->hw;
+-	struct ieee80211_conf *conf = &hw->conf;
+-	struct sta_info *sta;
+-	struct tid_ampdu_rx *tid_agg_rx;
+-	u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
+-	u8 dialog_token;
+-	int ret = -EOPNOTSUPP;
+-	DECLARE_MAC_BUF(mac);
+-
+-	sta = sta_info_get(local, mgmt->sa);
+-	if (!sta)
+-		return;
+-
+-	/* extract session parameters from addba request frame */
+-	dialog_token = mgmt->u.action.u.addba_req.dialog_token;
+-	timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
+-	start_seq_num =
+-		le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
+-
+-	capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+-	ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
+-	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
+-	buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
+-
+-	status = WLAN_STATUS_REQUEST_DECLINED;
+-
+-	/* sanity check for incoming parameters:
+-	 * check if configuration can support the BA policy
+-	 * and if buffer size does not exceeds max value */
+-	if (((ba_policy != 1)
+-		&& (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA)))
+-		|| (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
+-		status = WLAN_STATUS_INVALID_QOS_PARAM;
+-#ifdef CONFIG_MAC80211_HT_DEBUG
+-		if (net_ratelimit())
+-			printk(KERN_DEBUG "Block Ack Req with bad params from "
+-				"%s on tid %u. policy %d, buffer size %d\n",
+-				print_mac(mac, mgmt->sa), tid, ba_policy,
+-				buf_size);
+-#endif /* CONFIG_MAC80211_HT_DEBUG */
+-		goto end_no_lock;
+-	}
+-	/* determine default buffer size */
+-	if (buf_size == 0) {
+-		struct ieee80211_hw_mode *mode = conf->mode;
+-		buf_size = IEEE80211_MIN_AMPDU_BUF;
+-		buf_size = buf_size << mode->ht_info.ampdu_factor;
+-	}
+-
+-	tid_agg_rx = &sta->ampdu_mlme.tid_rx[tid];
+-
+-	/* examine state machine */
+-	spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
+-
+-	if (tid_agg_rx->state != HT_AGG_STATE_IDLE) {
+-#ifdef CONFIG_MAC80211_HT_DEBUG
+-		if (net_ratelimit())
+-			printk(KERN_DEBUG "unexpected Block Ack Req from "
+-				"%s on tid %u\n",
+-				print_mac(mac, mgmt->sa), tid);
+-#endif /* CONFIG_MAC80211_HT_DEBUG */
+-		goto end;
+-	}
+-
+-	/* prepare reordering buffer */
+-	tid_agg_rx->reorder_buf =
+-		kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC);
+-	if (!tid_agg_rx->reorder_buf) {
+-		if (net_ratelimit())
+-			printk(KERN_ERR "can not allocate reordering buffer "
+-			       "to tid %d\n", tid);
+-		goto end;
+-	}
+-	memset(tid_agg_rx->reorder_buf, 0,
+-		buf_size * sizeof(struct sk_buf *));
+-
+-	if (local->ops->ampdu_action)
+-		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
+-					       sta->addr, tid, start_seq_num);
+-#ifdef CONFIG_MAC80211_HT_DEBUG
+-	printk(KERN_DEBUG "Rx A-MPDU on tid %d result %d", tid, ret);
+-#endif /* CONFIG_MAC80211_HT_DEBUG */
+-
+-	if (ret) {
+-		kfree(tid_agg_rx->reorder_buf);
+-		goto end;
+-	}
+-
+-	/* change state and send addba resp */
+-	tid_agg_rx->state = HT_AGG_STATE_OPERATIONAL;
+-	tid_agg_rx->dialog_token = dialog_token;
+-	tid_agg_rx->ssn = start_seq_num;
+-	tid_agg_rx->head_seq_num = start_seq_num;
+-	tid_agg_rx->buf_size = buf_size;
+-	tid_agg_rx->timeout = timeout;
+-	tid_agg_rx->stored_mpdu_num = 0;
+-	status = WLAN_STATUS_SUCCESS;
+-end:
+-	spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+-
+-end_no_lock:
+-	ieee80211_send_addba_resp(sta->dev, sta->addr, tid, dialog_token,
+-				status, 1, buf_size, timeout);
+-	sta_info_put(sta);
+-}
+-
+-static void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
+-				 u16 initiator, u16 reason_code)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-	struct sk_buff *skb;
+-	struct ieee80211_mgmt *mgmt;
+-	u16 params;
+-
+-	skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
+-					sizeof(mgmt->u.action.u.delba));
+-
+-	if (!skb) {
+-		printk(KERN_ERR "%s: failed to allocate buffer "
+-					"for delba frame\n", dev->name);
+-		return;
+-	}
+-
+-	skb_reserve(skb, local->hw.extra_tx_headroom);
+-	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+-	memset(mgmt, 0, 24);
+-	memcpy(mgmt->da, da, ETH_ALEN);
+-	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
+-		memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
+-	else
+-		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+-	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-					IEEE80211_STYPE_ACTION);
+-
+-	skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
+-
+-	mgmt->u.action.category = WLAN_CATEGORY_BACK;
+-	mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
+-	params = (u16)(initiator << 11); 	/* bit 11 initiator */
+-	params |= (u16)(tid << 12); 		/* bit 15:12 TID number */
+-
+-	mgmt->u.action.u.delba.params = cpu_to_le16(params);
+-	mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
+-
+-	ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
+-					u16 initiator, u16 reason)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_hw *hw = &local->hw;
+-	struct sta_info *sta;
+-	int ret, i;
+-
+-	sta = sta_info_get(local, ra);
+-	if (!sta)
+-		return;
+-
+-	/* check if TID is in operational state */
+-	spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
+-	if (sta->ampdu_mlme.tid_rx[tid].state
+-				!= HT_AGG_STATE_OPERATIONAL) {
+-		spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+-		sta_info_put(sta);
+-		return;
+-	}
+-	sta->ampdu_mlme.tid_rx[tid].state =
+-		HT_AGG_STATE_REQ_STOP_BA_MSK |
+-		(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
+-		spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+-
+-	/* stop HW Rx aggregation. ampdu_action existence
+-	 * already verified in session init so we add the BUG_ON */
+-	BUG_ON(!local->ops->ampdu_action);
+-
+-	ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
+-					ra, tid, EINVAL);
+-	if (ret)
+-		printk(KERN_DEBUG "HW problem - can not stop rx "
+-				"aggergation for tid %d\n", tid);
+-
+-	/* shutdown timer has not expired */
+-	if (initiator != WLAN_BACK_TIMER)
+-		del_timer_sync(&sta->ampdu_mlme.tid_rx[tid].
+-					session_timer);
+-
+-	/* check if this is a self generated aggregation halt */
+-	if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
+-		ieee80211_send_delba(dev, ra, tid, 0, reason);
+-
+-	/* free the reordering buffer */
+-	for (i = 0; i < sta->ampdu_mlme.tid_rx[tid].buf_size; i++) {
+-		if (sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]) {
+-			/* release the reordered frames */
+-			dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]);
+-			sta->ampdu_mlme.tid_rx[tid].stored_mpdu_num--;
+-			sta->ampdu_mlme.tid_rx[tid].reorder_buf[i] = NULL;
+-		}
+-	}
+-	kfree(sta->ampdu_mlme.tid_rx[tid].reorder_buf);
+-
+-	sta->ampdu_mlme.tid_rx[tid].state = HT_AGG_STATE_IDLE;
+-	sta_info_put(sta);
+-}
+-
+-static void ieee80211_sta_process_delba(struct net_device *dev,
+-			struct ieee80211_mgmt *mgmt, size_t len)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct sta_info *sta;
+-	u16 tid, params;
+-	u16 initiator;
+-	DECLARE_MAC_BUF(mac);
+-
+-	sta = sta_info_get(local, mgmt->sa);
+-	if (!sta)
+-		return;
+-
+-	params = le16_to_cpu(mgmt->u.action.u.delba.params);
+-	tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
+-	initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
+-
+-#ifdef CONFIG_MAC80211_HT_DEBUG
+-	if (net_ratelimit())
+-		printk(KERN_DEBUG "delba from %s on tid %d reason code %d\n",
+-			print_mac(mac, mgmt->sa), tid,
+-			mgmt->u.action.u.delba.reason_code);
+-#endif /* CONFIG_MAC80211_HT_DEBUG */
+-
+-	if (initiator == WLAN_BACK_INITIATOR)
+-		ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid,
+-						 WLAN_BACK_INITIATOR, 0);
+-	sta_info_put(sta);
+-}
+-
+-/*
+- * After receiving Block Ack Request (BAR) we activated a
+- * timer after each frame arrives from the originator.
+- * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
+- */
+-void sta_rx_agg_session_timer_expired(unsigned long data)
+-{
+-	/* not an elegant detour, but there is no choice as the timer passes
+-	 * only one argument, and verious sta_info are needed here, so init
+-	 * flow in sta_info_add gives the TID as data, while the timer_to_id
+-	 * array gives the sta through container_of */
+-	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]);
+-
+-	printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
+-	ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr, (u16)*ptid,
+-					 WLAN_BACK_TIMER,
+-					 WLAN_REASON_QSTA_TIMEOUT);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_auth(struct net_device *dev,
+-				   struct ieee80211_if_sta *ifsta,
+-				   struct ieee80211_mgmt *mgmt,
+-				   size_t len)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	u16 auth_alg, auth_transaction, status_code;
+-	DECLARE_MAC_BUF(mac);
+-
+-	if (ifsta->state != IEEE80211_AUTHENTICATE &&
+-	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
+-		printk(KERN_DEBUG "%s: authentication frame received from "
+-		       "%s, but not in authenticate state - ignored\n",
+-		       dev->name, print_mac(mac, mgmt->sa));
+-		return;
+-	}
+-
+-	if (len < 24 + 6) {
+-		printk(KERN_DEBUG "%s: too short (%zd) authentication frame "
+-		       "received from %s - ignored\n",
+-		       dev->name, len, print_mac(mac, mgmt->sa));
+-		return;
+-	}
+-
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+-	    memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+-		printk(KERN_DEBUG "%s: authentication frame received from "
+-		       "unknown AP (SA=%s BSSID=%s) - "
+-		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+-		       print_mac(mac, mgmt->bssid));
+-		return;
+-	}
+-
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+-	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
+-		printk(KERN_DEBUG "%s: authentication frame received from "
+-		       "unknown BSSID (SA=%s BSSID=%s) - "
+-		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+-		       print_mac(mac, mgmt->bssid));
+-		return;
+-	}
+-
+-	auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
+-	auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
+-	status_code = le16_to_cpu(mgmt->u.auth.status_code);
+-
+-	printk(KERN_DEBUG "%s: RX authentication from %s (alg=%d "
+-	       "transaction=%d status=%d)\n",
+-	       dev->name, print_mac(mac, mgmt->sa), auth_alg,
+-	       auth_transaction, status_code);
+-
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+-		/* IEEE 802.11 standard does not require authentication in IBSS
+-		 * networks and most implementations do not seem to use it.
+-		 * However, try to reply to authentication attempts if someone
+-		 * has actually implemented this.
+-		 * TODO: Could implement shared key authentication. */
+-		if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
+-			printk(KERN_DEBUG "%s: unexpected IBSS authentication "
+-			       "frame (alg=%d transaction=%d)\n",
+-			       dev->name, auth_alg, auth_transaction);
+-			return;
+-		}
+-		ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0);
+-	}
+-
+-	if (auth_alg != ifsta->auth_alg ||
+-	    auth_transaction != ifsta->auth_transaction) {
+-		printk(KERN_DEBUG "%s: unexpected authentication frame "
+-		       "(alg=%d transaction=%d)\n",
+-		       dev->name, auth_alg, auth_transaction);
+-		return;
+-	}
+-
+-	if (status_code != WLAN_STATUS_SUCCESS) {
+-		printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d "
+-		       "code=%d)\n", dev->name, ifsta->auth_alg, status_code);
+-		if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
+-			u8 algs[3];
+-			const int num_algs = ARRAY_SIZE(algs);
+-			int i, pos;
+-			algs[0] = algs[1] = algs[2] = 0xff;
+-			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
+-				algs[0] = WLAN_AUTH_OPEN;
+-			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
+-				algs[1] = WLAN_AUTH_SHARED_KEY;
+-			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
+-				algs[2] = WLAN_AUTH_LEAP;
+-			if (ifsta->auth_alg == WLAN_AUTH_OPEN)
+-				pos = 0;
+-			else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY)
+-				pos = 1;
+-			else
+-				pos = 2;
+-			for (i = 0; i < num_algs; i++) {
+-				pos++;
+-				if (pos >= num_algs)
+-					pos = 0;
+-				if (algs[pos] == ifsta->auth_alg ||
+-				    algs[pos] == 0xff)
+-					continue;
+-				if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
+-				    !ieee80211_sta_wep_configured(dev))
+-					continue;
+-				ifsta->auth_alg = algs[pos];
+-				printk(KERN_DEBUG "%s: set auth_alg=%d for "
+-				       "next try\n",
+-				       dev->name, ifsta->auth_alg);
+-				break;
+-			}
+-		}
+-		return;
+-	}
+-
+-	switch (ifsta->auth_alg) {
+-	case WLAN_AUTH_OPEN:
+-	case WLAN_AUTH_LEAP:
+-		ieee80211_auth_completed(dev, ifsta);
+-		break;
+-	case WLAN_AUTH_SHARED_KEY:
+-		if (ifsta->auth_transaction == 4)
+-			ieee80211_auth_completed(dev, ifsta);
+-		else
+-			ieee80211_auth_challenge(dev, ifsta, mgmt, len);
+-		break;
+-	}
+-}
+-
+-
+-static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta,
+-				     struct ieee80211_mgmt *mgmt,
+-				     size_t len)
+-{
+-	u16 reason_code;
+-	DECLARE_MAC_BUF(mac);
+-
+-	if (len < 24 + 2) {
+-		printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame "
+-		       "received from %s - ignored\n",
+-		       dev->name, len, print_mac(mac, mgmt->sa));
+-		return;
+-	}
+-
+-	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+-		printk(KERN_DEBUG "%s: deauthentication frame received from "
+-		       "unknown AP (SA=%s BSSID=%s) - "
+-		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+-		       print_mac(mac, mgmt->bssid));
+-		return;
+-	}
+-
+-	reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
+-
+-	printk(KERN_DEBUG "%s: RX deauthentication from %s"
+-	       " (reason=%d)\n",
+-	       dev->name, print_mac(mac, mgmt->sa), reason_code);
+-
+-	if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) {
+-		printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
+-	}
+-
+-	if (ifsta->state == IEEE80211_AUTHENTICATE ||
+-	    ifsta->state == IEEE80211_ASSOCIATE ||
+-	    ifsta->state == IEEE80211_ASSOCIATED) {
+-		ifsta->state = IEEE80211_AUTHENTICATE;
+-		mod_timer(&ifsta->timer, jiffies +
+-				      IEEE80211_RETRY_AUTH_INTERVAL);
+-	}
+-
+-	ieee80211_set_disassoc(dev, ifsta, 1);
+-	ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
+-}
+-
+-
+-static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
+-				       struct ieee80211_if_sta *ifsta,
+-				       struct ieee80211_mgmt *mgmt,
+-				       size_t len)
+-{
+-	u16 reason_code;
+-	DECLARE_MAC_BUF(mac);
+-
+-	if (len < 24 + 2) {
+-		printk(KERN_DEBUG "%s: too short (%zd) disassociation frame "
+-		       "received from %s - ignored\n",
+-		       dev->name, len, print_mac(mac, mgmt->sa));
+-		return;
+-	}
+-
+-	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+-		printk(KERN_DEBUG "%s: disassociation frame received from "
+-		       "unknown AP (SA=%s BSSID=%s) - "
+-		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+-		       print_mac(mac, mgmt->bssid));
+-		return;
+-	}
+-
+-	reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
+-
+-	printk(KERN_DEBUG "%s: RX disassociation from %s"
+-	       " (reason=%d)\n",
+-	       dev->name, print_mac(mac, mgmt->sa), reason_code);
+-
+-	if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
+-		printk(KERN_DEBUG "%s: disassociated\n", dev->name);
+-
+-	if (ifsta->state == IEEE80211_ASSOCIATED) {
+-		ifsta->state = IEEE80211_ASSOCIATE;
+-		mod_timer(&ifsta->timer, jiffies +
+-				      IEEE80211_RETRY_AUTH_INTERVAL);
+-	}
+-
+-	ieee80211_set_disassoc(dev, ifsta, 0);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+-					 struct ieee80211_if_sta *ifsta,
+-					 struct ieee80211_mgmt *mgmt,
+-					 size_t len,
+-					 int reassoc)
+-{
+-	struct ieee80211_local *local = sdata->local;
+-	struct net_device *dev = sdata->dev;
+-	struct ieee80211_hw_mode *mode;
+-	struct sta_info *sta;
+-	u32 rates;
+-	u16 capab_info, status_code, aid;
+-	struct ieee802_11_elems elems;
+-	struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
+-	u8 *pos;
+-	int i, j;
+-	DECLARE_MAC_BUF(mac);
+-
+-	/* AssocResp and ReassocResp have identical structure, so process both
+-	 * of them in this function. */
+-
+-	if (ifsta->state != IEEE80211_ASSOCIATE) {
+-		printk(KERN_DEBUG "%s: association frame received from "
+-		       "%s, but not in associate state - ignored\n",
+-		       dev->name, print_mac(mac, mgmt->sa));
+-		return;
+-	}
+-
+-	if (len < 24 + 6) {
+-		printk(KERN_DEBUG "%s: too short (%zd) association frame "
+-		       "received from %s - ignored\n",
+-		       dev->name, len, print_mac(mac, mgmt->sa));
+-		return;
+-	}
+-
+-	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+-		printk(KERN_DEBUG "%s: association frame received from "
+-		       "unknown AP (SA=%s BSSID=%s) - "
+-		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+-		       print_mac(mac, mgmt->bssid));
+-		return;
+-	}
+-
+-	capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
+-	status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+-	aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
+-
+-	printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
+-	       "status=%d aid=%d)\n",
+-	       dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
+-	       capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
+-
+-	if (status_code != WLAN_STATUS_SUCCESS) {
+-		printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
+-		       dev->name, status_code);
+-		/* if this was a reassociation, ensure we try a "full"
+-		 * association next time. This works around some broken APs
+-		 * which do not correctly reject reassociation requests. */
+-		ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
+-		return;
+-	}
+-
+-	if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
+-		printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
+-		       "set\n", dev->name, aid);
+-	aid &= ~(BIT(15) | BIT(14));
+-
+-	pos = mgmt->u.assoc_resp.variable;
+-	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+-
+-	if (!elems.supp_rates) {
+-		printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
+-		       dev->name);
+-		return;
+-	}
+-
+-	printk(KERN_DEBUG "%s: associated\n", dev->name);
+-	ifsta->aid = aid;
+-	ifsta->ap_capab = capab_info;
+-
+-	kfree(ifsta->assocresp_ies);
+-	ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
+-	ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL);
+-	if (ifsta->assocresp_ies)
+-		memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
+-
+-	/* set AID, ieee80211_set_associated() will tell the driver */
+-	bss_conf->aid = aid;
+-	ieee80211_set_associated(dev, ifsta, 1);
+-
+-	/* Add STA entry for the AP */
+-	sta = sta_info_get(local, ifsta->bssid);
+-	if (!sta) {
+-		struct ieee80211_sta_bss *bss;
+-		sta = sta_info_add(local, dev, ifsta->bssid, GFP_KERNEL);
+-		if (!sta) {
+-			printk(KERN_DEBUG "%s: failed to add STA entry for the"
+-			       " AP\n", dev->name);
+-			return;
+-		}
+-		bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
+-					   local->hw.conf.channel,
+-					   ifsta->ssid, ifsta->ssid_len);
+-		if (bss) {
+-			sta->last_rssi = bss->rssi;
+-			sta->last_signal = bss->signal;
+-			sta->last_noise = bss->noise;
+-			ieee80211_rx_bss_put(dev, bss);
+-		}
+-	}
+-
+-	sta->dev = dev;
+-	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP;
+-
+-	rates = 0;
+-	mode = local->oper_hw_mode;
+-	for (i = 0; i < elems.supp_rates_len; i++) {
+-		int rate = (elems.supp_rates[i] & 0x7f) * 5;
+-		for (j = 0; j < mode->num_rates; j++)
+-			if (mode->rates[j].rate == rate)
+-				rates |= BIT(j);
+-	}
+-	for (i = 0; i < elems.ext_supp_rates_len; i++) {
+-		int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
+-		for (j = 0; j < mode->num_rates; j++)
+-			if (mode->rates[j].rate == rate)
+-				rates |= BIT(j);
+-	}
+-	sta->supp_rates = rates;
+-
+-	if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
+-	    local->ops->conf_ht) {
+-		struct ieee80211_ht_bss_info bss_info;
+-
+-		ieee80211_ht_cap_ie_to_ht_info(
+-				(struct ieee80211_ht_cap *)
+-				elems.ht_cap_elem, &sta->ht_info);
+-		ieee80211_ht_addt_info_ie_to_ht_bss_info(
+-				(struct ieee80211_ht_addt_info *)
+-				elems.ht_info_elem, &bss_info);
+-		ieee80211_hw_config_ht(local, 1, &sta->ht_info, &bss_info);
+-	}
+-
+-	rate_control_rate_init(sta, local);
+-
+-	if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
+-		sta->flags |= WLAN_STA_WME;
+-		ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
+-					 elems.wmm_param_len);
+-	}
+-
+-
+-	sta_info_put(sta);
+-
+-	ieee80211_associated(dev, ifsta);
+-}
+-
+-
+-/* Caller must hold local->sta_bss_lock */
+-static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
+-					struct ieee80211_sta_bss *bss)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	bss->hnext = local->sta_bss_hash[STA_HASH(bss->bssid)];
+-	local->sta_bss_hash[STA_HASH(bss->bssid)] = bss;
+-}
+-
+-
+-/* Caller must hold local->sta_bss_lock */
+-static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
+-					struct ieee80211_sta_bss *bss)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sta_bss *b, *prev = NULL;
+-	b = local->sta_bss_hash[STA_HASH(bss->bssid)];
+-	while (b) {
+-		if (b == bss) {
+-			if (!prev)
+-				local->sta_bss_hash[STA_HASH(bss->bssid)] =
+-					bss->hnext;
+-			else
+-				prev->hnext = bss->hnext;
+-			break;
+-		}
+-		prev = b;
+-		b = b->hnext;
+-	}
+-}
+-
+-
+-static struct ieee80211_sta_bss *
+-ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel,
+-		     u8 *ssid, u8 ssid_len)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sta_bss *bss;
+-
+-	bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
+-	if (!bss)
+-		return NULL;
+-	atomic_inc(&bss->users);
+-	atomic_inc(&bss->users);
+-	memcpy(bss->bssid, bssid, ETH_ALEN);
+-	bss->channel = channel;
+-	if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
+-		memcpy(bss->ssid, ssid, ssid_len);
+-		bss->ssid_len = ssid_len;
+-	}
+-
+-	spin_lock_bh(&local->sta_bss_lock);
+-	/* TODO: order by RSSI? */
+-	list_add_tail(&bss->list, &local->sta_bss_list);
+-	__ieee80211_rx_bss_hash_add(dev, bss);
+-	spin_unlock_bh(&local->sta_bss_lock);
+-	return bss;
+-}
+-
+-
+-static struct ieee80211_sta_bss *
+-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
+-		     u8 *ssid, u8 ssid_len)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sta_bss *bss;
+-
+-	spin_lock_bh(&local->sta_bss_lock);
+-	bss = local->sta_bss_hash[STA_HASH(bssid)];
+-	while (bss) {
+-		if (!memcmp(bss->bssid, bssid, ETH_ALEN) &&
+-		    bss->channel == channel &&
+-		    bss->ssid_len == ssid_len &&
+-		    (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
+-			atomic_inc(&bss->users);
+-			break;
+-		}
+-		bss = bss->hnext;
+-	}
+-	spin_unlock_bh(&local->sta_bss_lock);
+-	return bss;
+-}
+-
+-
+-static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
+-{
+-	kfree(bss->wpa_ie);
+-	kfree(bss->rsn_ie);
+-	kfree(bss->wmm_ie);
+-	kfree(bss->ht_ie);
+-	kfree(bss);
+-}
+-
+-
+-static void ieee80211_rx_bss_put(struct net_device *dev,
+-				 struct ieee80211_sta_bss *bss)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	if (!atomic_dec_and_test(&bss->users))
+-		return;
+-
+-	spin_lock_bh(&local->sta_bss_lock);
+-	__ieee80211_rx_bss_hash_del(dev, bss);
+-	list_del(&bss->list);
+-	spin_unlock_bh(&local->sta_bss_lock);
+-	ieee80211_rx_bss_free(bss);
+-}
+-
+-
+-void ieee80211_rx_bss_list_init(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	spin_lock_init(&local->sta_bss_lock);
+-	INIT_LIST_HEAD(&local->sta_bss_list);
+-}
+-
+-
+-void ieee80211_rx_bss_list_deinit(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sta_bss *bss, *tmp;
+-
+-	list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
+-		ieee80211_rx_bss_put(dev, bss);
+-}
+-
+-
+-static void ieee80211_rx_bss_info(struct net_device *dev,
+-				  struct ieee80211_mgmt *mgmt,
+-				  size_t len,
+-				  struct ieee80211_rx_status *rx_status,
+-				  int beacon)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee802_11_elems elems;
+-	size_t baselen;
+-	int channel, clen;
+-	struct ieee80211_sta_bss *bss;
+-	struct sta_info *sta;
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	u64 timestamp;
+-	DECLARE_MAC_BUF(mac);
+-	DECLARE_MAC_BUF(mac2);
+-
+-	if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
+-		return; /* ignore ProbeResp to foreign address */
+-
+-#if 0
+-	printk(KERN_DEBUG "%s: RX %s from %s to %s\n",
+-	       dev->name, beacon ? "Beacon" : "Probe Response",
+-	       print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da));
+-#endif
+-
+-	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+-	if (baselen > len)
+-		return;
+-
+-	timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+-
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
+-	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+-		static unsigned long last_tsf_debug = 0;
+-		u64 tsf;
+-		if (local->ops->get_tsf)
+-			tsf = local->ops->get_tsf(local_to_hw(local));
+-		else
+-			tsf = -1LLU;
+-		if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
+-			printk(KERN_DEBUG "RX beacon SA=%s BSSID="
+-			       "%s TSF=0x%llx BCN=0x%llx diff=%lld "
+-			       "@%lu\n",
+-			       print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->bssid),
+-			       (unsigned long long)tsf,
+-			       (unsigned long long)timestamp,
+-			       (unsigned long long)(tsf - timestamp),
+-			       jiffies);
+-			last_tsf_debug = jiffies;
+-		}
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+-	}
+-
+-	ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
+-
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
+-	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
+-	    (sta = sta_info_get(local, mgmt->sa))) {
+-		struct ieee80211_hw_mode *mode;
+-		struct ieee80211_rate *rates;
+-		size_t num_rates;
+-		u32 supp_rates, prev_rates;
+-		int i, j;
+-
+-		mode = local->sta_sw_scanning ?
+-		       local->scan_hw_mode : local->oper_hw_mode;
+-
+-		if (local->sta_hw_scanning) {
+-			/* search for the correct mode matches the beacon */
+-			list_for_each_entry(mode, &local->modes_list, list)
+-				if (mode->mode == rx_status->phymode)
+-					break;
+-
+-			if (mode == NULL)
+-				mode = local->oper_hw_mode;
+-		}
+-		rates = mode->rates;
+-		num_rates = mode->num_rates;
+-
+-		supp_rates = 0;
+-		for (i = 0; i < elems.supp_rates_len +
+-			     elems.ext_supp_rates_len; i++) {
+-			u8 rate = 0;
+-			int own_rate;
+-			if (i < elems.supp_rates_len)
+-				rate = elems.supp_rates[i];
+-			else if (elems.ext_supp_rates)
+-				rate = elems.ext_supp_rates
+-					[i - elems.supp_rates_len];
+-			own_rate = 5 * (rate & 0x7f);
+-			for (j = 0; j < num_rates; j++)
+-				if (rates[j].rate == own_rate)
+-					supp_rates |= BIT(j);
+-		}
+-
+-		prev_rates = sta->supp_rates;
+-		sta->supp_rates &= supp_rates;
+-		if (sta->supp_rates == 0) {
+-			/* No matching rates - this should not really happen.
+-			 * Make sure that at least one rate is marked
+-			 * supported to avoid issues with TX rate ctrl. */
+-			sta->supp_rates = sdata->u.sta.supp_rates_bits;
+-		}
+-		if (sta->supp_rates != prev_rates) {
+-			printk(KERN_DEBUG "%s: updated supp_rates set for "
+-			       "%s based on beacon info (0x%x & 0x%x -> "
+-			       "0x%x)\n",
+-			       dev->name, print_mac(mac, sta->addr), prev_rates,
+-			       supp_rates, sta->supp_rates);
+-		}
+-		sta_info_put(sta);
+-	}
+-
+-	if (!elems.ssid)
+-		return;
+-
+-	if (elems.ds_params && elems.ds_params_len == 1)
+-		channel = elems.ds_params[0];
+-	else
+-		channel = rx_status->channel;
+-
+-	bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel,
+-				   elems.ssid, elems.ssid_len);
+-	if (!bss) {
+-		bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel,
+-					   elems.ssid, elems.ssid_len);
+-		if (!bss)
+-			return;
+-	} else {
+-#if 0
+-		/* TODO: order by RSSI? */
+-		spin_lock_bh(&local->sta_bss_lock);
+-		list_move_tail(&bss->list, &local->sta_bss_list);
+-		spin_unlock_bh(&local->sta_bss_lock);
+-#endif
+-	}
+-
+-	if (bss->probe_resp && beacon) {
+-		/* Do not allow beacon to override data from Probe Response. */
+-		ieee80211_rx_bss_put(dev, bss);
+-		return;
+-	}
+-
+-	/* save the ERP value so that it is available at association time */
+-	if (elems.erp_info && elems.erp_info_len >= 1) {
+-		bss->erp_value = elems.erp_info[0];
+-		bss->has_erp_value = 1;
+-	}
+-
+-	bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
+-	bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
+-
+-	bss->supp_rates_len = 0;
+-	if (elems.supp_rates) {
+-		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+-		if (clen > elems.supp_rates_len)
+-			clen = elems.supp_rates_len;
+-		memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates,
+-		       clen);
+-		bss->supp_rates_len += clen;
+-	}
+-	if (elems.ext_supp_rates) {
+-		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+-		if (clen > elems.ext_supp_rates_len)
+-			clen = elems.ext_supp_rates_len;
+-		memcpy(&bss->supp_rates[bss->supp_rates_len],
+-		       elems.ext_supp_rates, clen);
+-		bss->supp_rates_len += clen;
+-	}
+-
+-	if (elems.wpa &&
+-	    (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
+-	     memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
+-		kfree(bss->wpa_ie);
+-		bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);
+-		if (bss->wpa_ie) {
+-			memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2);
+-			bss->wpa_ie_len = elems.wpa_len + 2;
+-		} else
+-			bss->wpa_ie_len = 0;
+-	} else if (!elems.wpa && bss->wpa_ie) {
+-		kfree(bss->wpa_ie);
+-		bss->wpa_ie = NULL;
+-		bss->wpa_ie_len = 0;
+-	}
+-
+-	if (elems.rsn &&
+-	    (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||
+-	     memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
+-		kfree(bss->rsn_ie);
+-		bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);
+-		if (bss->rsn_ie) {
+-			memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2);
+-			bss->rsn_ie_len = elems.rsn_len + 2;
+-		} else
+-			bss->rsn_ie_len = 0;
+-	} else if (!elems.rsn && bss->rsn_ie) {
+-		kfree(bss->rsn_ie);
+-		bss->rsn_ie = NULL;
+-		bss->rsn_ie_len = 0;
+-	}
+-
+-	if (elems.wmm_param &&
+-	    (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
+-	     memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
+-		kfree(bss->wmm_ie);
+-		bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);
+-		if (bss->wmm_ie) {
+-			memcpy(bss->wmm_ie, elems.wmm_param - 2,
+-			       elems.wmm_param_len + 2);
+-			bss->wmm_ie_len = elems.wmm_param_len + 2;
+-		} else
+-			bss->wmm_ie_len = 0;
+-	} else if (!elems.wmm_param && bss->wmm_ie) {
+-		kfree(bss->wmm_ie);
+-		bss->wmm_ie = NULL;
+-		bss->wmm_ie_len = 0;
+-	}
+-	if (elems.ht_cap_elem &&
+-	    (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
+-	     memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
+-		kfree(bss->ht_ie);
+-		bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
+-		if (bss->ht_ie) {
+-			memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
+-			       elems.ht_cap_elem_len + 2);
+-			bss->ht_ie_len = elems.ht_cap_elem_len + 2;
+-		} else
+-			bss->ht_ie_len = 0;
+-	} else if (!elems.ht_cap_elem && bss->ht_ie) {
+-		kfree(bss->ht_ie);
+-		bss->ht_ie = NULL;
+-		bss->ht_ie_len = 0;
+-	}
+-
+-	bss->hw_mode = rx_status->phymode;
+-	bss->freq = rx_status->freq;
+-	if (channel != rx_status->channel &&
+-	    (bss->hw_mode == MODE_IEEE80211G ||
+-	     bss->hw_mode == MODE_IEEE80211B) &&
+-	    channel >= 1 && channel <= 14) {
+-		static const int freq_list[] = {
+-			2412, 2417, 2422, 2427, 2432, 2437, 2442,
+-			2447, 2452, 2457, 2462, 2467, 2472, 2484
+-		};
+-		/* IEEE 802.11g/b mode can receive packets from neighboring
+-		 * channels, so map the channel into frequency. */
+-		bss->freq = freq_list[channel - 1];
+-	}
+-	bss->timestamp = timestamp;
+-	bss->last_update = jiffies;
+-	bss->rssi = rx_status->ssi;
+-	bss->signal = rx_status->signal;
+-	bss->noise = rx_status->noise;
+-	if (!beacon)
+-		bss->probe_resp++;
+-	ieee80211_rx_bss_put(dev, bss);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,
+-					 struct ieee80211_mgmt *mgmt,
+-					 size_t len,
+-					 struct ieee80211_rx_status *rx_status)
+-{
+-	ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
+-				     struct ieee80211_mgmt *mgmt,
+-				     size_t len,
+-				     struct ieee80211_rx_status *rx_status)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_if_sta *ifsta;
+-	size_t baselen;
+-	struct ieee802_11_elems elems;
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_conf *conf = &local->hw.conf;
+-	u32 changed = 0;
+-
+-	ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+-		return;
+-	ifsta = &sdata->u.sta;
+-
+-	if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||
+-	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
+-		return;
+-
+-	/* Process beacon from the current BSS */
+-	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+-	if (baselen > len)
+-		return;
+-
+-	ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
+-
+-	if (elems.erp_info && elems.erp_info_len >= 1)
+-		changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
+-	else {
+-		u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info);
+-		changed |= ieee80211_handle_protect_preamb(sdata, false,
+-				(capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
+-	}
+-
+-	if (elems.ht_cap_elem && elems.ht_info_elem &&
+-	    elems.wmm_param && local->ops->conf_ht &&
+-	    conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
+-		struct ieee80211_ht_bss_info bss_info;
+-
+-		ieee80211_ht_addt_info_ie_to_ht_bss_info(
+-				(struct ieee80211_ht_addt_info *)
+-				elems.ht_info_elem, &bss_info);
+-		/* check if AP changed bss inforamation */
+-		if ((conf->ht_bss_conf.primary_channel !=
+-		     bss_info.primary_channel) ||
+-		    (conf->ht_bss_conf.bss_cap != bss_info.bss_cap) ||
+-		    (conf->ht_bss_conf.bss_op_mode != bss_info.bss_op_mode))
+-			ieee80211_hw_config_ht(local, 1, &conf->ht_conf,
+-						&bss_info);
+-	}
+-
+-	if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
+-		ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
+-					 elems.wmm_param_len);
+-	}
+-
+-	ieee80211_bss_info_change_notify(sdata, changed);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
+-					struct ieee80211_if_sta *ifsta,
+-					struct ieee80211_mgmt *mgmt,
+-					size_t len,
+-					struct ieee80211_rx_status *rx_status)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	int tx_last_beacon;
+-	struct sk_buff *skb;
+-	struct ieee80211_mgmt *resp;
+-	u8 *pos, *end;
+-	DECLARE_MAC_BUF(mac);
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+-	DECLARE_MAC_BUF(mac2);
+-	DECLARE_MAC_BUF(mac3);
+-#endif
+-
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS ||
+-	    ifsta->state != IEEE80211_IBSS_JOINED ||
+-	    len < 24 + 2 || !ifsta->probe_resp)
+-		return;
+-
+-	if (local->ops->tx_last_beacon)
+-		tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));
+-	else
+-		tx_last_beacon = 1;
+-
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+-	printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID="
+-	       "%s (tx_last_beacon=%d)\n",
+-	       dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da),
+-	       print_mac(mac3, mgmt->bssid), tx_last_beacon);
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+-
+-	if (!tx_last_beacon)
+-		return;
+-
+-	if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&
+-	    memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
+-		return;
+-
+-	end = ((u8 *) mgmt) + len;
+-	pos = mgmt->u.probe_req.variable;
+-	if (pos[0] != WLAN_EID_SSID ||
+-	    pos + 2 + pos[1] > end) {
+-		if (net_ratelimit()) {
+-			printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
+-			       "from %s\n",
+-			       dev->name, print_mac(mac, mgmt->sa));
+-		}
+-		return;
+-	}
+-	if (pos[1] != 0 &&
+-	    (pos[1] != ifsta->ssid_len ||
+-	     memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {
+-		/* Ignore ProbeReq for foreign SSID */
+-		return;
+-	}
+-
+-	/* Reply with ProbeResp */
+-	skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);
+-	if (!skb)
+-		return;
+-
+-	resp = (struct ieee80211_mgmt *) skb->data;
+-	memcpy(resp->da, mgmt->sa, ETH_ALEN);
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+-	printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n",
+-	       dev->name, print_mac(mac, resp->da));
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+-	ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-static void ieee80211_rx_mgmt_action(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta,
+-				     struct ieee80211_mgmt *mgmt,
+-				     size_t len)
+-{
+-	if (len < IEEE80211_MIN_ACTION_SIZE)
+-		return;
+-
+-	switch (mgmt->u.action.category) {
+-	case WLAN_CATEGORY_BACK:
+-		switch (mgmt->u.action.u.addba_req.action_code) {
+-		case WLAN_ACTION_ADDBA_REQ:
+-			if (len < (IEEE80211_MIN_ACTION_SIZE +
+-				   sizeof(mgmt->u.action.u.addba_req)))
+-				break;
+-			ieee80211_sta_process_addba_request(dev, mgmt, len);
+-			break;
+-		case WLAN_ACTION_DELBA:
+-			if (len < (IEEE80211_MIN_ACTION_SIZE +
+-				   sizeof(mgmt->u.action.u.delba)))
+-				break;
+-			ieee80211_sta_process_delba(dev, mgmt, len);
+-			break;
+-		default:
+-			if (net_ratelimit())
+-			   printk(KERN_DEBUG "%s: Rx unknown A-MPDU action\n",
+-					dev->name);
+-			break;
+-		}
+-		break;
+-	default:
+-		break;
+-	}
+-}
+-
+-void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
+-			   struct ieee80211_rx_status *rx_status)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_if_sta *ifsta;
+-	struct ieee80211_mgmt *mgmt;
+-	u16 fc;
+-
+-	if (skb->len < 24)
+-		goto fail;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	ifsta = &sdata->u.sta;
+-
+-	mgmt = (struct ieee80211_mgmt *) skb->data;
+-	fc = le16_to_cpu(mgmt->frame_control);
+-
+-	switch (fc & IEEE80211_FCTL_STYPE) {
+-	case IEEE80211_STYPE_PROBE_REQ:
+-	case IEEE80211_STYPE_PROBE_RESP:
+-	case IEEE80211_STYPE_BEACON:
+-		memcpy(skb->cb, rx_status, sizeof(*rx_status));
+-	case IEEE80211_STYPE_AUTH:
+-	case IEEE80211_STYPE_ASSOC_RESP:
+-	case IEEE80211_STYPE_REASSOC_RESP:
+-	case IEEE80211_STYPE_DEAUTH:
+-	case IEEE80211_STYPE_DISASSOC:
+-	case IEEE80211_STYPE_ACTION:
+-		skb_queue_tail(&ifsta->skb_queue, skb);
+-		queue_work(local->hw.workqueue, &ifsta->work);
+-		return;
+-	default:
+-		printk(KERN_DEBUG "%s: received unknown management frame - "
+-		       "stype=%d\n", dev->name,
+-		       (fc & IEEE80211_FCTL_STYPE) >> 4);
+-		break;
+-	}
+-
+- fail:
+-	kfree_skb(skb);
+-}
+-
+-
+-static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
+-					 struct sk_buff *skb)
+-{
+-	struct ieee80211_rx_status *rx_status;
+-	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_if_sta *ifsta;
+-	struct ieee80211_mgmt *mgmt;
+-	u16 fc;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	ifsta = &sdata->u.sta;
+-
+-	rx_status = (struct ieee80211_rx_status *) skb->cb;
+-	mgmt = (struct ieee80211_mgmt *) skb->data;
+-	fc = le16_to_cpu(mgmt->frame_control);
+-
+-	switch (fc & IEEE80211_FCTL_STYPE) {
+-	case IEEE80211_STYPE_PROBE_REQ:
+-		ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len,
+-					    rx_status);
+-		break;
+-	case IEEE80211_STYPE_PROBE_RESP:
+-		ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status);
+-		break;
+-	case IEEE80211_STYPE_BEACON:
+-		ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status);
+-		break;
+-	case IEEE80211_STYPE_AUTH:
+-		ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);
+-		break;
+-	case IEEE80211_STYPE_ASSOC_RESP:
+-		ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
+-		break;
+-	case IEEE80211_STYPE_REASSOC_RESP:
+-		ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
+-		break;
+-	case IEEE80211_STYPE_DEAUTH:
+-		ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);
+-		break;
+-	case IEEE80211_STYPE_DISASSOC:
+-		ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
+-		break;
+-	case IEEE80211_STYPE_ACTION:
+-		ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len);
+-		break;
+-	}
+-
+-	kfree_skb(skb);
+-}
+-
+-
+-ieee80211_txrx_result
+-ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
+-		      struct ieee80211_rx_status *rx_status)
+-{
+-	struct ieee80211_mgmt *mgmt;
+-	u16 fc;
+-
+-	if (skb->len < 2)
+-		return TXRX_DROP;
+-
+-	mgmt = (struct ieee80211_mgmt *) skb->data;
+-	fc = le16_to_cpu(mgmt->frame_control);
+-
+-	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
+-		return TXRX_CONTINUE;
+-
+-	if (skb->len < 24)
+-		return TXRX_DROP;
+-
+-	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
+-		if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) {
+-			ieee80211_rx_mgmt_probe_resp(dev, mgmt,
+-						     skb->len, rx_status);
+-			dev_kfree_skb(skb);
+-			return TXRX_QUEUED;
+-		} else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
+-			ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len,
+-						 rx_status);
+-			dev_kfree_skb(skb);
+-			return TXRX_QUEUED;
+-		}
+-	}
+-	return TXRX_CONTINUE;
+-}
+-
+-
+-static int ieee80211_sta_active_ibss(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	int active = 0;
+-	struct sta_info *sta;
+-
+-	read_lock_bh(&local->sta_lock);
+-	list_for_each_entry(sta, &local->sta_list, list) {
+-		if (sta->dev == dev &&
+-		    time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
+-			       jiffies)) {
+-			active++;
+-			break;
+-		}
+-	}
+-	read_unlock_bh(&local->sta_lock);
+-
+-	return active;
+-}
+-
+-
+-static void ieee80211_sta_expire(struct net_device *dev)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct sta_info *sta, *tmp;
+-	LIST_HEAD(tmp_list);
+-	DECLARE_MAC_BUF(mac);
+-
+-	write_lock_bh(&local->sta_lock);
+-	list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
+-		if (time_after(jiffies, sta->last_rx +
+-			       IEEE80211_IBSS_INACTIVITY_LIMIT)) {
+-			printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
+-			       dev->name, print_mac(mac, sta->addr));
+-			__sta_info_get(sta);
+-			sta_info_remove(sta);
+-			list_add(&sta->list, &tmp_list);
+-		}
+-	write_unlock_bh(&local->sta_lock);
+-
+-	list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
+-		sta_info_free(sta);
+-		sta_info_put(sta);
+-	}
+-}
+-
+-
+-static void ieee80211_sta_merge_ibss(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta)
+-{
+-	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+-
+-	ieee80211_sta_expire(dev);
+-	if (ieee80211_sta_active_ibss(dev))
+-		return;
+-
+-	printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
+-	       "IBSS networks with same SSID (merge)\n", dev->name);
+-	ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len);
+-}
+-
+-
+-void ieee80211_sta_timer(unsigned long data)
+-{
+-	struct ieee80211_sub_if_data *sdata =
+-		(struct ieee80211_sub_if_data *) data;
+-	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-	struct ieee80211_local *local = wdev_priv(&sdata->wdev);
+-
+-	set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
+-	queue_work(local->hw.workqueue, &ifsta->work);
+-}
+-
+-
+-void ieee80211_sta_work(struct work_struct *work)
+-{
+-	struct ieee80211_sub_if_data *sdata =
+-		container_of(work, struct ieee80211_sub_if_data, u.sta.work);
+-	struct net_device *dev = sdata->dev;
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_if_sta *ifsta;
+-	struct sk_buff *skb;
+-
+-	if (!netif_running(dev))
+-		return;
+-
+-	if (local->sta_sw_scanning || local->sta_hw_scanning)
+-		return;
+-
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
+-	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
+-		printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
+-		       "(type=%d)\n", dev->name, sdata->vif.type);
+-		return;
+-	}
+-	ifsta = &sdata->u.sta;
+-
+-	while ((skb = skb_dequeue(&ifsta->skb_queue)))
+-		ieee80211_sta_rx_queued_mgmt(dev, skb);
+-
+-	if (ifsta->state != IEEE80211_AUTHENTICATE &&
+-	    ifsta->state != IEEE80211_ASSOCIATE &&
+-	    test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
+-		if (ifsta->scan_ssid_len)
+-			ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len);
+-		else
+-			ieee80211_sta_start_scan(dev, NULL, 0);
+-		return;
+-	}
+-
+-	if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
+-		if (ieee80211_sta_config_auth(dev, ifsta))
+-			return;
+-		clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
+-	} else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
+-		return;
+-
+-	switch (ifsta->state) {
+-	case IEEE80211_DISABLED:
+-		break;
+-	case IEEE80211_AUTHENTICATE:
+-		ieee80211_authenticate(dev, ifsta);
+-		break;
+-	case IEEE80211_ASSOCIATE:
+-		ieee80211_associate(dev, ifsta);
+-		break;
+-	case IEEE80211_ASSOCIATED:
+-		ieee80211_associated(dev, ifsta);
+-		break;
+-	case IEEE80211_IBSS_SEARCH:
+-		ieee80211_sta_find_ibss(dev, ifsta);
+-		break;
+-	case IEEE80211_IBSS_JOINED:
+-		ieee80211_sta_merge_ibss(dev, ifsta);
+-		break;
+-	default:
+-		printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
+-		       ifsta->state);
+-		break;
+-	}
+-
+-	if (ieee80211_privacy_mismatch(dev, ifsta)) {
+-		printk(KERN_DEBUG "%s: privacy configuration mismatch and "
+-		       "mixed-cell disabled - disassociate\n", dev->name);
+-
+-		ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED);
+-		ieee80211_set_disassoc(dev, ifsta, 0);
+-	}
+-}
+-
+-
+-static void ieee80211_sta_reset_auth(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	if (local->ops->reset_tsf) {
+-		/* Reset own TSF to allow time synchronization work. */
+-		local->ops->reset_tsf(local_to_hw(local));
+-	}
+-
+-	ifsta->wmm_last_param_set = -1; /* allow any WMM update */
+-
+-
+-	if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
+-		ifsta->auth_alg = WLAN_AUTH_OPEN;
+-	else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
+-		ifsta->auth_alg = WLAN_AUTH_SHARED_KEY;
+-	else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
+-		ifsta->auth_alg = WLAN_AUTH_LEAP;
+-	else
+-		ifsta->auth_alg = WLAN_AUTH_OPEN;
+-	printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
+-	       ifsta->auth_alg);
+-	ifsta->auth_transaction = -1;
+-	ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
+-	ifsta->auth_tries = ifsta->assoc_tries = 0;
+-	netif_carrier_off(dev);
+-}
+-
+-
+-void ieee80211_sta_req_auth(struct net_device *dev,
+-			    struct ieee80211_if_sta *ifsta)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+-		return;
+-
+-	if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
+-				IEEE80211_STA_AUTO_BSSID_SEL)) &&
+-	    (ifsta->flags & (IEEE80211_STA_SSID_SET |
+-				IEEE80211_STA_AUTO_SSID_SEL))) {
+-		set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
+-		queue_work(local->hw.workqueue, &ifsta->work);
+-	}
+-}
+-
+-static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
+-				    const char *ssid, int ssid_len)
+-{
+-	int tmp, hidden_ssid;
+-
+-	if (ssid_len == ifsta->ssid_len &&
+-	    !memcmp(ifsta->ssid, ssid, ssid_len))
+-		return 1;
+-
+-	if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
+-		return 0;
+-
+-	hidden_ssid = 1;
+-	tmp = ssid_len;
+-	while (tmp--) {
+-		if (ssid[tmp] != '\0') {
+-			hidden_ssid = 0;
+-			break;
+-		}
+-	}
+-
+-	if (hidden_ssid && ifsta->ssid_len == ssid_len)
+-		return 1;
+-
+-	if (ssid_len == 1 && ssid[0] == ' ')
+-		return 1;
+-
+-	return 0;
+-}
+-
+-static int ieee80211_sta_config_auth(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_sta_bss *bss, *selected = NULL;
+-	int top_rssi = 0, freq;
+-
+-	if (!(ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
+-	    IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL))) {
+-		ifsta->state = IEEE80211_AUTHENTICATE;
+-		ieee80211_sta_reset_auth(dev, ifsta);
+-		return 0;
+-	}
+-
+-	spin_lock_bh(&local->sta_bss_lock);
+-	freq = local->oper_channel->freq;
+-	list_for_each_entry(bss, &local->sta_bss_list, list) {
+-		if (!(bss->capability & WLAN_CAPABILITY_ESS))
+-			continue;
+-
+-		if (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
+-		    !!sdata->default_key)
+-			continue;
+-
+-		if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
+-		    bss->freq != freq)
+-			continue;
+-
+-		if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
+-		    memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
+-			continue;
+-
+-		if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
+-		    !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
+-			continue;
+-
+-		if (!selected || top_rssi < bss->rssi) {
+-			selected = bss;
+-			top_rssi = bss->rssi;
+-		}
+-	}
+-	if (selected)
+-		atomic_inc(&selected->users);
+-	spin_unlock_bh(&local->sta_bss_lock);
+-
+-	if (selected) {
+-		ieee80211_set_channel(local, -1, selected->freq);
+-		if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
+-			ieee80211_sta_set_ssid(dev, selected->ssid,
+-					       selected->ssid_len);
+-		ieee80211_sta_set_bssid(dev, selected->bssid);
+-		ieee80211_rx_bss_put(dev, selected);
+-		ifsta->state = IEEE80211_AUTHENTICATE;
+-		ieee80211_sta_reset_auth(dev, ifsta);
+-		return 0;
+-	} else {
+-		if (ifsta->state != IEEE80211_AUTHENTICATE) {
+-			if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
+-				ieee80211_sta_start_scan(dev, NULL, 0);
+-			else
+-				ieee80211_sta_start_scan(dev, ifsta->ssid,
+-							 ifsta->ssid_len);
+-			ifsta->state = IEEE80211_AUTHENTICATE;
+-			set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
+-		} else
+-			ifsta->state = IEEE80211_DISABLED;
+-	}
+-	return -1;
+-}
+-
+-static int ieee80211_sta_join_ibss(struct net_device *dev,
+-				   struct ieee80211_if_sta *ifsta,
+-				   struct ieee80211_sta_bss *bss)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	int res, rates, i, j;
+-	struct sk_buff *skb;
+-	struct ieee80211_mgmt *mgmt;
+-	struct ieee80211_tx_control control;
+-	struct ieee80211_hw_mode *mode;
+-	struct rate_selection ratesel;
+-	u8 *pos;
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	/* Remove possible STA entries from other IBSS networks. */
+-	sta_info_flush(local, NULL);
+-
+-	if (local->ops->reset_tsf) {
+-		/* Reset own TSF to allow time synchronization work. */
+-		local->ops->reset_tsf(local_to_hw(local));
+-	}
+-	memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
+-	res = ieee80211_if_config(dev);
+-	if (res)
+-		return res;
+-
+-	local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	sdata->drop_unencrypted = bss->capability &
+-		WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+-
+-	res = ieee80211_set_channel(local, -1, bss->freq);
+-
+-	if (!(local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)) {
+-		printk(KERN_DEBUG "%s: IBSS not allowed on channel %d "
+-		       "(%d MHz)\n", dev->name, local->hw.conf.channel,
+-		       local->hw.conf.freq);
+-		return -1;
+-	}
+-
+-	/* Set beacon template based on scan results */
+-	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+-	do {
+-		if (!skb)
+-			break;
+-
+-		skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+-		mgmt = (struct ieee80211_mgmt *)
+-			skb_put(skb, 24 + sizeof(mgmt->u.beacon));
+-		memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
+-		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-						   IEEE80211_STYPE_BEACON);
+-		memset(mgmt->da, 0xff, ETH_ALEN);
+-		memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+-		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+-		mgmt->u.beacon.beacon_int =
+-			cpu_to_le16(local->hw.conf.beacon_int);
+-		mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
+-
+-		pos = skb_put(skb, 2 + ifsta->ssid_len);
+-		*pos++ = WLAN_EID_SSID;
+-		*pos++ = ifsta->ssid_len;
+-		memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+-
+-		rates = bss->supp_rates_len;
+-		if (rates > 8)
+-			rates = 8;
+-		pos = skb_put(skb, 2 + rates);
+-		*pos++ = WLAN_EID_SUPP_RATES;
+-		*pos++ = rates;
+-		memcpy(pos, bss->supp_rates, rates);
+-
+-		pos = skb_put(skb, 2 + 1);
+-		*pos++ = WLAN_EID_DS_PARAMS;
+-		*pos++ = 1;
+-		*pos++ = bss->channel;
+-
+-		pos = skb_put(skb, 2 + 2);
+-		*pos++ = WLAN_EID_IBSS_PARAMS;
+-		*pos++ = 2;
+-		/* FIX: set ATIM window based on scan results */
+-		*pos++ = 0;
+-		*pos++ = 0;
+-
+-		if (bss->supp_rates_len > 8) {
+-			rates = bss->supp_rates_len - 8;
+-			pos = skb_put(skb, 2 + rates);
+-			*pos++ = WLAN_EID_EXT_SUPP_RATES;
+-			*pos++ = rates;
+-			memcpy(pos, &bss->supp_rates[8], rates);
+-		}
+-
+-		memset(&control, 0, sizeof(control));
+-		rate_control_get_rate(dev, local->oper_hw_mode, skb, &ratesel);
+-		if (!ratesel.rate) {
+-			printk(KERN_DEBUG "%s: Failed to determine TX rate "
+-			       "for IBSS beacon\n", dev->name);
+-			break;
+-		}
+-		control.vif = &sdata->vif;
+-		control.tx_rate =
+-			(sdata->bss_conf.use_short_preamble &&
+-			(ratesel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
+-			ratesel.rate->val2 : ratesel.rate->val;
+-		control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+-		control.power_level = local->hw.conf.power_level;
+-		control.flags |= IEEE80211_TXCTL_NO_ACK;
+-		control.retry_limit = 1;
+-
+-		ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
+-		if (ifsta->probe_resp) {
+-			mgmt = (struct ieee80211_mgmt *)
+-				ifsta->probe_resp->data;
+-			mgmt->frame_control =
+-				IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+-					     IEEE80211_STYPE_PROBE_RESP);
+-		} else {
+-			printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
+-			       "template for IBSS\n", dev->name);
+-		}
+-
+-		if (local->ops->beacon_update &&
+-		    local->ops->beacon_update(local_to_hw(local),
+-					     skb, &control) == 0) {
+-			printk(KERN_DEBUG "%s: Configured IBSS beacon "
+-			       "template based on scan results\n", dev->name);
+-			skb = NULL;
+-		}
+-
+-		rates = 0;
+-		mode = local->oper_hw_mode;
+-		for (i = 0; i < bss->supp_rates_len; i++) {
+-			int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
+-			for (j = 0; j < mode->num_rates; j++)
+-				if (mode->rates[j].rate == bitrate)
+-					rates |= BIT(j);
+-		}
+-		ifsta->supp_rates_bits = rates;
+-	} while (0);
+-
+-	if (skb) {
+-		printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
+-		       "template\n", dev->name);
+-		dev_kfree_skb(skb);
+-	}
+-
+-	ifsta->state = IEEE80211_IBSS_JOINED;
+-	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+-
+-	ieee80211_rx_bss_put(dev, bss);
+-
+-	return res;
+-}
+-
+-
+-static int ieee80211_sta_create_ibss(struct net_device *dev,
+-				     struct ieee80211_if_sta *ifsta)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sta_bss *bss;
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_hw_mode *mode;
+-	u8 bssid[ETH_ALEN], *pos;
+-	int i;
+-	DECLARE_MAC_BUF(mac);
+-
+-#if 0
+-	/* Easier testing, use fixed BSSID. */
+-	memset(bssid, 0xfe, ETH_ALEN);
+-#else
+-	/* Generate random, not broadcast, locally administered BSSID. Mix in
+-	 * own MAC address to make sure that devices that do not have proper
+-	 * random number generator get different BSSID. */
+-	get_random_bytes(bssid, ETH_ALEN);
+-	for (i = 0; i < ETH_ALEN; i++)
+-		bssid[i] ^= dev->dev_addr[i];
+-	bssid[0] &= ~0x01;
+-	bssid[0] |= 0x02;
+-#endif
+-
+-	printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
+-	       dev->name, print_mac(mac, bssid));
+-
+-	bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel,
+-				   sdata->u.sta.ssid, sdata->u.sta.ssid_len);
+-	if (!bss)
+-		return -ENOMEM;
+-
+-	mode = local->oper_hw_mode;
+-
+-	if (local->hw.conf.beacon_int == 0)
+-		local->hw.conf.beacon_int = 100;
+-	bss->beacon_int = local->hw.conf.beacon_int;
+-	bss->hw_mode = local->hw.conf.phymode;
+-	bss->freq = local->hw.conf.freq;
+-	bss->last_update = jiffies;
+-	bss->capability = WLAN_CAPABILITY_IBSS;
+-	if (sdata->default_key) {
+-		bss->capability |= WLAN_CAPABILITY_PRIVACY;
+-	} else
+-		sdata->drop_unencrypted = 0;
+-	bss->supp_rates_len = mode->num_rates;
+-	pos = bss->supp_rates;
+-	for (i = 0; i < mode->num_rates; i++) {
+-		int rate = mode->rates[i].rate;
+-		*pos++ = (u8) (rate / 5);
+-	}
+-
+-	return ieee80211_sta_join_ibss(dev, ifsta, bss);
+-}
+-
+-
+-static int ieee80211_sta_find_ibss(struct net_device *dev,
+-				   struct ieee80211_if_sta *ifsta)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sta_bss *bss;
+-	int found = 0;
+-	u8 bssid[ETH_ALEN];
+-	int active_ibss;
+-	DECLARE_MAC_BUF(mac);
+-	DECLARE_MAC_BUF(mac2);
+-
+-	if (ifsta->ssid_len == 0)
+-		return -EINVAL;
+-
+-	active_ibss = ieee80211_sta_active_ibss(dev);
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+-	printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
+-	       dev->name, active_ibss);
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+-	spin_lock_bh(&local->sta_bss_lock);
+-	list_for_each_entry(bss, &local->sta_bss_list, list) {
+-		if (ifsta->ssid_len != bss->ssid_len ||
+-		    memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
+-		    || !(bss->capability & WLAN_CAPABILITY_IBSS))
+-			continue;
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+-		printk(KERN_DEBUG "   bssid=%s found\n",
+-		       print_mac(mac, bss->bssid));
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+-		memcpy(bssid, bss->bssid, ETH_ALEN);
+-		found = 1;
+-		if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
+-			break;
+-	}
+-	spin_unlock_bh(&local->sta_bss_lock);
+-
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+-	printk(KERN_DEBUG "   sta_find_ibss: selected %s current "
+-	       "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+-	if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
+-	    (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel,
+-					ifsta->ssid, ifsta->ssid_len))) {
+-		printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
+-		       " based on configured SSID\n",
+-		       dev->name, print_mac(mac, bssid));
+-		return ieee80211_sta_join_ibss(dev, ifsta, bss);
+-	}
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+-	printk(KERN_DEBUG "   did not try to join ibss\n");
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+-
+-	/* Selected IBSS not found in current scan results - try to scan */
+-	if (ifsta->state == IEEE80211_IBSS_JOINED &&
+-	    !ieee80211_sta_active_ibss(dev)) {
+-		mod_timer(&ifsta->timer, jiffies +
+-				      IEEE80211_IBSS_MERGE_INTERVAL);
+-	} else if (time_after(jiffies, local->last_scan_completed +
+-			      IEEE80211_SCAN_INTERVAL)) {
+-		printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
+-		       "join\n", dev->name);
+-		return ieee80211_sta_req_scan(dev, ifsta->ssid,
+-					      ifsta->ssid_len);
+-	} else if (ifsta->state != IEEE80211_IBSS_JOINED) {
+-		int interval = IEEE80211_SCAN_INTERVAL;
+-
+-		if (time_after(jiffies, ifsta->ibss_join_req +
+-			       IEEE80211_IBSS_JOIN_TIMEOUT)) {
+-			if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) &&
+-			    local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)
+-				return ieee80211_sta_create_ibss(dev, ifsta);
+-			if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) {
+-				printk(KERN_DEBUG "%s: IBSS not allowed on the"
+-				       " configured channel %d (%d MHz)\n",
+-				       dev->name, local->hw.conf.channel,
+-				       local->hw.conf.freq);
+-			}
+-
+-			/* No IBSS found - decrease scan interval and continue
+-			 * scanning. */
+-			interval = IEEE80211_SCAN_INTERVAL_SLOW;
+-		}
+-
+-		ifsta->state = IEEE80211_IBSS_SEARCH;
+-		mod_timer(&ifsta->timer, jiffies + interval);
+-		return 0;
+-	}
+-
+-	return 0;
+-}
+-
+-
+-int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_if_sta *ifsta;
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	if (len > IEEE80211_MAX_SSID_LEN)
+-		return -EINVAL;
+-
+-	/* TODO: This should always be done for IBSS, even if IEEE80211_QOS is
+-	 * not defined. */
+-	if (local->ops->conf_tx) {
+-		struct ieee80211_tx_queue_params qparam;
+-		int i;
+-
+-		memset(&qparam, 0, sizeof(qparam));
+-		/* TODO: are these ok defaults for all hw_modes? */
+-		qparam.aifs = 2;
+-		qparam.cw_min =
+-			local->hw.conf.phymode == MODE_IEEE80211B ? 31 : 15;
+-		qparam.cw_max = 1023;
+-		qparam.burst_time = 0;
+-		for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
+-		{
+-			local->ops->conf_tx(local_to_hw(local),
+-					   i + IEEE80211_TX_QUEUE_DATA0,
+-					   &qparam);
+-		}
+-		/* IBSS uses different parameters for Beacon sending */
+-		qparam.cw_min++;
+-		qparam.cw_min *= 2;
+-		qparam.cw_min--;
+-		local->ops->conf_tx(local_to_hw(local),
+-				   IEEE80211_TX_QUEUE_BEACON, &qparam);
+-	}
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	ifsta = &sdata->u.sta;
+-
+-	if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
+-		ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
+-	memcpy(ifsta->ssid, ssid, len);
+-	memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
+-	ifsta->ssid_len = len;
+-
+-	if (len)
+-		ifsta->flags |= IEEE80211_STA_SSID_SET;
+-	else
+-		ifsta->flags &= ~IEEE80211_STA_SSID_SET;
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
+-	    !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
+-		ifsta->ibss_join_req = jiffies;
+-		ifsta->state = IEEE80211_IBSS_SEARCH;
+-		return ieee80211_sta_find_ibss(dev, ifsta);
+-	}
+-	return 0;
+-}
+-
+-
+-int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-	memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
+-	*len = ifsta->ssid_len;
+-	return 0;
+-}
+-
+-
+-int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_if_sta *ifsta;
+-	int res;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	ifsta = &sdata->u.sta;
+-
+-	if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
+-		memcpy(ifsta->bssid, bssid, ETH_ALEN);
+-		res = ieee80211_if_config(dev);
+-		if (res) {
+-			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
+-			       "the low-level driver\n", dev->name);
+-			return res;
+-		}
+-	}
+-
+-	if (is_valid_ether_addr(bssid))
+-		ifsta->flags |= IEEE80211_STA_BSSID_SET;
+-	else
+-		ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
+-
+-	return 0;
+-}
+-
+-
+-static void ieee80211_send_nullfunc(struct ieee80211_local *local,
+-				    struct ieee80211_sub_if_data *sdata,
+-				    int powersave)
+-{
+-	struct sk_buff *skb;
+-	struct ieee80211_hdr *nullfunc;
+-	u16 fc;
+-
+-	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
+-	if (!skb) {
+-		printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
+-		       "frame\n", sdata->dev->name);
+-		return;
+-	}
+-	skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+-	nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
+-	memset(nullfunc, 0, 24);
+-	fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
+-	     IEEE80211_FCTL_TODS;
+-	if (powersave)
+-		fc |= IEEE80211_FCTL_PM;
+-	nullfunc->frame_control = cpu_to_le16(fc);
+-	memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN);
+-	memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
+-	memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN);
+-
+-	ieee80211_sta_tx(sdata->dev, skb, 0);
+-}
+-
+-
+-void ieee80211_scan_completed(struct ieee80211_hw *hw)
+-{
+-	struct ieee80211_local *local = hw_to_local(hw);
+-	struct net_device *dev = local->scan_dev;
+-	struct ieee80211_sub_if_data *sdata;
+-	union iwreq_data wrqu;
+-
+-	local->last_scan_completed = jiffies;
+-	memset(&wrqu, 0, sizeof(wrqu));
+-	wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+-
+-	if (local->sta_hw_scanning) {
+-		local->sta_hw_scanning = 0;
+-		goto done;
+-	}
+-
+-	local->sta_sw_scanning = 0;
+-	if (ieee80211_hw_config(local))
+-		printk(KERN_DEBUG "%s: failed to restore operational "
+-		       "channel after scan\n", dev->name);
+-
+-
+-	netif_tx_lock_bh(local->mdev);
+-	local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
+-	local->ops->configure_filter(local_to_hw(local),
+-				     FIF_BCN_PRBRESP_PROMISC,
+-				     &local->filter_flags,
+-				     local->mdev->mc_count,
+-				     local->mdev->mc_list);
+-
+-	netif_tx_unlock_bh(local->mdev);
+-
+-	rcu_read_lock();
+-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+-
+-		/* No need to wake the master device. */
+-		if (sdata->dev == local->mdev)
+-			continue;
+-
+-		if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
+-			if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)
+-				ieee80211_send_nullfunc(local, sdata, 0);
+-			ieee80211_sta_timer((unsigned long)sdata);
+-		}
+-
+-		netif_wake_queue(sdata->dev);
+-	}
+-	rcu_read_unlock();
+-
+-done:
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+-		struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-		if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) ||
+-		    (!ifsta->state == IEEE80211_IBSS_JOINED &&
+-		    !ieee80211_sta_active_ibss(dev)))
+-			ieee80211_sta_find_ibss(dev, ifsta);
+-	}
+-}
+-EXPORT_SYMBOL(ieee80211_scan_completed);
+-
+-void ieee80211_sta_scan_work(struct work_struct *work)
+-{
+-	struct ieee80211_local *local =
+-		container_of(work, struct ieee80211_local, scan_work.work);
+-	struct net_device *dev = local->scan_dev;
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_hw_mode *mode;
+-	struct ieee80211_channel *chan;
+-	int skip;
+-	unsigned long next_delay = 0;
+-
+-	if (!local->sta_sw_scanning)
+-		return;
+-
+-	switch (local->scan_state) {
+-	case SCAN_SET_CHANNEL:
+-		mode = local->scan_hw_mode;
+-		if (local->scan_hw_mode->list.next == &local->modes_list &&
+-		    local->scan_channel_idx >= mode->num_channels) {
+-			ieee80211_scan_completed(local_to_hw(local));
+-			return;
+-		}
+-		skip = !(local->enabled_modes & (1 << mode->mode));
+-		chan = &mode->channels[local->scan_channel_idx];
+-		if (!(chan->flag & IEEE80211_CHAN_W_SCAN) ||
+-		    (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
+-		     !(chan->flag & IEEE80211_CHAN_W_IBSS)) ||
+-		    (local->hw_modes & local->enabled_modes &
+-		     (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
+-			skip = 1;
+-
+-		if (!skip) {
+-#if 0
+-			printk(KERN_DEBUG "%s: scan channel %d (%d MHz)\n",
+-			       dev->name, chan->chan, chan->freq);
+-#endif
+-
+-			local->scan_channel = chan;
+-			if (ieee80211_hw_config(local)) {
+-				printk(KERN_DEBUG "%s: failed to set channel "
+-				       "%d (%d MHz) for scan\n", dev->name,
+-				       chan->chan, chan->freq);
+-				skip = 1;
+-			}
+-		}
+-
+-		local->scan_channel_idx++;
+-		if (local->scan_channel_idx >= local->scan_hw_mode->num_channels) {
+-			if (local->scan_hw_mode->list.next != &local->modes_list) {
+-				local->scan_hw_mode = list_entry(local->scan_hw_mode->list.next,
+-								 struct ieee80211_hw_mode,
+-								 list);
+-				local->scan_channel_idx = 0;
+-			}
+-		}
+-
+-		if (skip)
+-			break;
+-
+-		next_delay = IEEE80211_PROBE_DELAY +
+-			     usecs_to_jiffies(local->hw.channel_change_time);
+-		local->scan_state = SCAN_SEND_PROBE;
+-		break;
+-	case SCAN_SEND_PROBE:
+-		if (local->scan_channel->flag & IEEE80211_CHAN_W_ACTIVE_SCAN) {
+-			ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
+-						 local->scan_ssid_len);
+-			next_delay = IEEE80211_CHANNEL_TIME;
+-		} else
+-			next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+-		local->scan_state = SCAN_SET_CHANNEL;
+-		break;
+-	}
+-
+-	if (local->sta_sw_scanning)
+-		queue_delayed_work(local->hw.workqueue, &local->scan_work,
+-				   next_delay);
+-}
+-
+-
+-static int ieee80211_sta_start_scan(struct net_device *dev,
+-				    u8 *ssid, size_t ssid_len)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_sub_if_data *sdata;
+-
+-	if (ssid_len > IEEE80211_MAX_SSID_LEN)
+-		return -EINVAL;
+-
+-	/* MLME-SCAN.request (page 118)  page 144 (11.1.3.1)
+-	 * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
+-	 * BSSID: MACAddress
+-	 * SSID
+-	 * ScanType: ACTIVE, PASSIVE
+-	 * ProbeDelay: delay (in microseconds) to be used prior to transmitting
+-	 *    a Probe frame during active scanning
+-	 * ChannelList
+-	 * MinChannelTime (>= ProbeDelay), in TU
+-	 * MaxChannelTime: (>= MinChannelTime), in TU
+-	 */
+-
+-	 /* MLME-SCAN.confirm
+-	  * BSSDescriptionSet
+-	  * ResultCode: SUCCESS, INVALID_PARAMETERS
+-	 */
+-
+-	if (local->sta_sw_scanning || local->sta_hw_scanning) {
+-		if (local->scan_dev == dev)
+-			return 0;
+-		return -EBUSY;
+-	}
+-
+-	if (local->ops->hw_scan) {
+-		int rc = local->ops->hw_scan(local_to_hw(local),
+-					     ssid, ssid_len);
+-		if (!rc) {
+-			local->sta_hw_scanning = 1;
+-			local->scan_dev = dev;
+-		}
+-		return rc;
+-	}
+-
+-	local->sta_sw_scanning = 1;
+-
+-	rcu_read_lock();
+-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+-
+-		/* Don't stop the master interface, otherwise we can't transmit
+-		 * probes! */
+-		if (sdata->dev == local->mdev)
+-			continue;
+-
+-		netif_stop_queue(sdata->dev);
+-		if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
+-		    (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
+-			ieee80211_send_nullfunc(local, sdata, 1);
+-	}
+-	rcu_read_unlock();
+-
+-	if (ssid) {
+-		local->scan_ssid_len = ssid_len;
+-		memcpy(local->scan_ssid, ssid, ssid_len);
+-	} else
+-		local->scan_ssid_len = 0;
+-	local->scan_state = SCAN_SET_CHANNEL;
+-	local->scan_hw_mode = list_entry(local->modes_list.next,
+-					 struct ieee80211_hw_mode,
+-					 list);
+-	local->scan_channel_idx = 0;
+-	local->scan_dev = dev;
+-
+-	netif_tx_lock_bh(local->mdev);
+-	local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
+-	local->ops->configure_filter(local_to_hw(local),
+-				     FIF_BCN_PRBRESP_PROMISC,
+-				     &local->filter_flags,
+-				     local->mdev->mc_count,
+-				     local->mdev->mc_list);
+-	netif_tx_unlock_bh(local->mdev);
+-
+-	/* TODO: start scan as soon as all nullfunc frames are ACKed */
+-	queue_delayed_work(local->hw.workqueue, &local->scan_work,
+-			   IEEE80211_CHANNEL_TIME);
+-
+-	return 0;
+-}
+-
+-
+-int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+-		return ieee80211_sta_start_scan(dev, ssid, ssid_len);
+-
+-	if (local->sta_sw_scanning || local->sta_hw_scanning) {
+-		if (local->scan_dev == dev)
+-			return 0;
+-		return -EBUSY;
+-	}
+-
+-	ifsta->scan_ssid_len = ssid_len;
+-	if (ssid_len)
+-		memcpy(ifsta->scan_ssid, ssid, ssid_len);
+-	set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
+-	queue_work(local->hw.workqueue, &ifsta->work);
+-	return 0;
+-}
+-
+-static char *
+-ieee80211_sta_scan_result(struct net_device *dev,
+-			  struct ieee80211_sta_bss *bss,
+-			  char *current_ev, char *end_buf)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct iw_event iwe;
+-
+-	if (time_after(jiffies,
+-		       bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE))
+-		return current_ev;
+-
+-	if (!(local->enabled_modes & (1 << bss->hw_mode)))
+-		return current_ev;
+-
+-	memset(&iwe, 0, sizeof(iwe));
+-	iwe.cmd = SIOCGIWAP;
+-	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+-	memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
+-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+-					  IW_EV_ADDR_LEN);
+-
+-	memset(&iwe, 0, sizeof(iwe));
+-	iwe.cmd = SIOCGIWESSID;
+-	iwe.u.data.length = bss->ssid_len;
+-	iwe.u.data.flags = 1;
+-	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+-					  bss->ssid);
+-
+-	if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+-		memset(&iwe, 0, sizeof(iwe));
+-		iwe.cmd = SIOCGIWMODE;
+-		if (bss->capability & WLAN_CAPABILITY_ESS)
+-			iwe.u.mode = IW_MODE_MASTER;
+-		else
+-			iwe.u.mode = IW_MODE_ADHOC;
+-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+-						  IW_EV_UINT_LEN);
+-	}
+-
+-	memset(&iwe, 0, sizeof(iwe));
+-	iwe.cmd = SIOCGIWFREQ;
+-	iwe.u.freq.m = bss->channel;
+-	iwe.u.freq.e = 0;
+-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+-					  IW_EV_FREQ_LEN);
+-	iwe.u.freq.m = bss->freq * 100000;
+-	iwe.u.freq.e = 1;
+-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+-					  IW_EV_FREQ_LEN);
+-
+-	memset(&iwe, 0, sizeof(iwe));
+-	iwe.cmd = IWEVQUAL;
+-	iwe.u.qual.qual = bss->signal;
+-	iwe.u.qual.level = bss->rssi;
+-	iwe.u.qual.noise = bss->noise;
+-	iwe.u.qual.updated = local->wstats_flags;
+-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+-					  IW_EV_QUAL_LEN);
+-
+-	memset(&iwe, 0, sizeof(iwe));
+-	iwe.cmd = SIOCGIWENCODE;
+-	if (bss->capability & WLAN_CAPABILITY_PRIVACY)
+-		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+-	else
+-		iwe.u.data.flags = IW_ENCODE_DISABLED;
+-	iwe.u.data.length = 0;
+-	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
+-
+-	if (bss && bss->wpa_ie) {
+-		memset(&iwe, 0, sizeof(iwe));
+-		iwe.cmd = IWEVGENIE;
+-		iwe.u.data.length = bss->wpa_ie_len;
+-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+-						  bss->wpa_ie);
+-	}
+-
+-	if (bss && bss->rsn_ie) {
+-		memset(&iwe, 0, sizeof(iwe));
+-		iwe.cmd = IWEVGENIE;
+-		iwe.u.data.length = bss->rsn_ie_len;
+-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+-						  bss->rsn_ie);
+-	}
+-
+-	if (bss && bss->supp_rates_len > 0) {
+-		/* display all supported rates in readable format */
+-		char *p = current_ev + IW_EV_LCP_LEN;
+-		int i;
+-
+-		memset(&iwe, 0, sizeof(iwe));
+-		iwe.cmd = SIOCGIWRATE;
+-		/* Those two flags are ignored... */
+-		iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+-
+-		for (i = 0; i < bss->supp_rates_len; i++) {
+-			iwe.u.bitrate.value = ((bss->supp_rates[i] &
+-							0x7f) * 500000);
+-			p = iwe_stream_add_value(current_ev, p,
+-					end_buf, &iwe, IW_EV_PARAM_LEN);
+-		}
+-		current_ev = p;
+-	}
+-
+-	if (bss) {
+-		char *buf;
+-		buf = kmalloc(30, GFP_ATOMIC);
+-		if (buf) {
+-			memset(&iwe, 0, sizeof(iwe));
+-			iwe.cmd = IWEVCUSTOM;
+-			sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp));
+-			iwe.u.data.length = strlen(buf);
+-			current_ev = iwe_stream_add_point(current_ev, end_buf,
+-							  &iwe, buf);
+-			kfree(buf);
+-		}
+-	}
+-
+-	return current_ev;
+-}
+-
+-
+-int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	char *current_ev = buf;
+-	char *end_buf = buf + len;
+-	struct ieee80211_sta_bss *bss;
+-
+-	spin_lock_bh(&local->sta_bss_lock);
+-	list_for_each_entry(bss, &local->sta_bss_list, list) {
+-		if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
+-			spin_unlock_bh(&local->sta_bss_lock);
+-			return -E2BIG;
+-		}
+-		current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
+-						       end_buf);
+-	}
+-	spin_unlock_bh(&local->sta_bss_lock);
+-	return current_ev - buf;
+-}
+-
+-
+-int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-	kfree(ifsta->extra_ie);
+-	if (len == 0) {
+-		ifsta->extra_ie = NULL;
+-		ifsta->extra_ie_len = 0;
+-		return 0;
+-	}
+-	ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
+-	if (!ifsta->extra_ie) {
+-		ifsta->extra_ie_len = 0;
+-		return -ENOMEM;
+-	}
+-	memcpy(ifsta->extra_ie, ie, len);
+-	ifsta->extra_ie_len = len;
+-	return 0;
+-}
+-
+-
+-struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
+-					 struct sk_buff *skb, u8 *bssid,
+-					 u8 *addr)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct sta_info *sta;
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	DECLARE_MAC_BUF(mac);
+-
+-	/* TODO: Could consider removing the least recently used entry and
+-	 * allow new one to be added. */
+-	if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
+-		if (net_ratelimit()) {
+-			printk(KERN_DEBUG "%s: No room for a new IBSS STA "
+-			       "entry %s\n", dev->name, print_mac(mac, addr));
+-		}
+-		return NULL;
+-	}
+-
+-	printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
+-	       wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
+-
+-	sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
+-	if (!sta)
+-		return NULL;
+-
+-	sta->supp_rates = sdata->u.sta.supp_rates_bits;
+-
+-	rate_control_rate_init(sta, local);
+-
+-	return sta; /* caller will call sta_info_put() */
+-}
+-
+-
+-int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-
+-	printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
+-	       dev->name, reason);
+-
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
+-	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
+-		return -EINVAL;
+-
+-	ieee80211_send_deauth(dev, ifsta, reason);
+-	ieee80211_set_disassoc(dev, ifsta, 1);
+-	return 0;
+-}
+-
+-
+-int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
+-{
+-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-
+-	printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
+-	       dev->name, reason);
+-
+-	if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+-		return -EINVAL;
+-
+-	if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
+-		return -1;
+-
+-	ieee80211_send_disassoc(dev, ifsta, reason);
+-	ieee80211_set_disassoc(dev, ifsta, 0);
+-	return 0;
+-}
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+new file mode 100644
+index 0000000..80954a5
+--- /dev/null
++++ b/net/mac80211/iface.c
+@@ -0,0 +1,314 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/if_arp.h>
++#include <linux/netdevice.h>
++#include <linux/rtnetlink.h>
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "sta_info.h"
++#include "debugfs_netdev.h"
++#include "mesh.h"
++
++void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
++{
++	int i;
++
++	/* Default values for sub-interface parameters */
++	sdata->drop_unencrypted = 0;
++	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
++		skb_queue_head_init(&sdata->fragments[i].skb_list);
++
++	INIT_LIST_HEAD(&sdata->key_list);
++}
++
++static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
++{
++	int i;
++
++	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
++		__skb_queue_purge(&sdata->fragments[i].skb_list);
++	}
++}
++
++/* Must be called with rtnl lock held. */
++int ieee80211_if_add(struct net_device *dev, const char *name,
++		     struct net_device **new_dev, int type,
++		     struct vif_params *params)
++{
++	struct net_device *ndev;
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = NULL;
++	int ret;
++
++	ASSERT_RTNL();
++	ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
++			    name, ieee80211_if_setup);
++	if (!ndev)
++		return -ENOMEM;
++
++	ret = dev_alloc_name(ndev, ndev->name);
++	if (ret < 0)
++		goto fail;
++
++	memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
++	ndev->base_addr = dev->base_addr;
++	ndev->irq = dev->irq;
++	ndev->mem_start = dev->mem_start;
++	ndev->mem_end = dev->mem_end;
++	SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
++	ndev->ieee80211_ptr = &sdata->wdev;
++	sdata->wdev.wiphy = local->hw.wiphy;
++	sdata->vif.type = IEEE80211_IF_TYPE_AP;
++	sdata->dev = ndev;
++	sdata->local = local;
++	ieee80211_if_sdata_init(sdata);
++
++	ret = register_netdevice(ndev);
++	if (ret)
++		goto fail;
++
++	ieee80211_debugfs_add_netdev(sdata);
++	ieee80211_if_set_type(ndev, type);
++
++	if (ieee80211_vif_is_mesh(&sdata->vif) &&
++	    params && params->mesh_id_len)
++		ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
++					     params->mesh_id_len,
++					     params->mesh_id);
++
++	/* we're under RTNL so all this is fine */
++	if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
++		__ieee80211_if_del(local, sdata);
++		return -ENODEV;
++	}
++	list_add_tail_rcu(&sdata->list, &local->interfaces);
++
++	if (new_dev)
++		*new_dev = ndev;
++
++	return 0;
++
++fail:
++	free_netdev(ndev);
++	return ret;
++}
++
++void ieee80211_if_set_type(struct net_device *dev, int type)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	int oldtype = sdata->vif.type;
++
++	/*
++	 * We need to call this function on the master interface
++	 * which already has a hard_start_xmit routine assigned
++	 * which must not be changed.
++	 */
++	if (dev != sdata->local->mdev)
++		dev->hard_start_xmit = ieee80211_subif_start_xmit;
++
++	/*
++	 * Called even when register_netdevice fails, it would
++	 * oops if assigned before initialising the rest.
++	 */
++	dev->uninit = ieee80211_if_reinit;
++
++	/* most have no BSS pointer */
++	sdata->bss = NULL;
++	sdata->vif.type = type;
++
++	sdata->basic_rates = 0;
++
++	switch (type) {
++	case IEEE80211_IF_TYPE_WDS:
++		/* nothing special */
++		break;
++	case IEEE80211_IF_TYPE_VLAN:
++		sdata->u.vlan.ap = NULL;
++		break;
++	case IEEE80211_IF_TYPE_AP:
++		sdata->u.ap.force_unicast_rateidx = -1;
++		sdata->u.ap.max_ratectrl_rateidx = -1;
++		skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
++		sdata->bss = &sdata->u.ap;
++		INIT_LIST_HEAD(&sdata->u.ap.vlans);
++		break;
++	case IEEE80211_IF_TYPE_MESH_POINT:
++	case IEEE80211_IF_TYPE_STA:
++	case IEEE80211_IF_TYPE_IBSS: {
++		struct ieee80211_sub_if_data *msdata;
++		struct ieee80211_if_sta *ifsta;
++
++		ifsta = &sdata->u.sta;
++		INIT_WORK(&ifsta->work, ieee80211_sta_work);
++		setup_timer(&ifsta->timer, ieee80211_sta_timer,
++			    (unsigned long) sdata);
++		skb_queue_head_init(&ifsta->skb_queue);
++
++		ifsta->capab = WLAN_CAPABILITY_ESS;
++		ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
++			IEEE80211_AUTH_ALG_SHARED_KEY;
++		ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
++			IEEE80211_STA_WMM_ENABLED |
++			IEEE80211_STA_AUTO_BSSID_SEL |
++			IEEE80211_STA_AUTO_CHANNEL_SEL;
++
++		msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
++		sdata->bss = &msdata->u.ap;
++
++		if (ieee80211_vif_is_mesh(&sdata->vif))
++			ieee80211_mesh_init_sdata(sdata);
++		break;
++	}
++	case IEEE80211_IF_TYPE_MNTR:
++		dev->type = ARPHRD_IEEE80211_RADIOTAP;
++		dev->hard_start_xmit = ieee80211_monitor_start_xmit;
++		sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
++				      MONITOR_FLAG_OTHER_BSS;
++		break;
++	default:
++		printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
++		       dev->name, __func__, type);
++	}
++	ieee80211_debugfs_change_if_type(sdata, oldtype);
++}
++
++/* Must be called with rtnl lock held. */
++void ieee80211_if_reinit(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct sk_buff *skb;
++	int flushed;
++
++	ASSERT_RTNL();
++
++	ieee80211_free_keys(sdata);
++
++	ieee80211_if_sdata_deinit(sdata);
++
++	/* Need to handle mesh specially to allow eliding the function call */
++	if (ieee80211_vif_is_mesh(&sdata->vif))
++		mesh_rmc_free(dev);
++
++	switch (sdata->vif.type) {
++	case IEEE80211_IF_TYPE_INVALID:
++		/* cannot happen */
++		WARN_ON(1);
++		break;
++	case IEEE80211_IF_TYPE_AP: {
++		/* Remove all virtual interfaces that use this BSS
++		 * as their sdata->bss */
++		struct ieee80211_sub_if_data *tsdata, *n;
++		struct beacon_data *beacon;
++
++		list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
++			if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
++				printk(KERN_DEBUG "%s: removing virtual "
++				       "interface %s because its BSS interface"
++				       " is being removed\n",
++				       sdata->dev->name, tsdata->dev->name);
++				list_del_rcu(&tsdata->list);
++				/*
++				 * We have lots of time and can afford
++				 * to sync for each interface
++				 */
++				synchronize_rcu();
++				__ieee80211_if_del(local, tsdata);
++			}
++		}
++
++		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 IEEE80211_IF_TYPE_WDS:
++		/* nothing to do */
++		break;
++	case IEEE80211_IF_TYPE_MESH_POINT:
++	case IEEE80211_IF_TYPE_STA:
++	case IEEE80211_IF_TYPE_IBSS:
++		kfree(sdata->u.sta.extra_ie);
++		sdata->u.sta.extra_ie = NULL;
++		kfree(sdata->u.sta.assocreq_ies);
++		sdata->u.sta.assocreq_ies = NULL;
++		kfree(sdata->u.sta.assocresp_ies);
++		sdata->u.sta.assocresp_ies = NULL;
++		if (sdata->u.sta.probe_resp) {
++			dev_kfree_skb(sdata->u.sta.probe_resp);
++			sdata->u.sta.probe_resp = NULL;
++		}
++
++		break;
++	case IEEE80211_IF_TYPE_MNTR:
++		dev->type = ARPHRD_ETHER;
++		break;
++	case IEEE80211_IF_TYPE_VLAN:
++		sdata->u.vlan.ap = NULL;
++		break;
++	}
++
++	flushed = sta_info_flush(local, sdata);
++	WARN_ON(flushed);
++
++	memset(&sdata->u, 0, sizeof(sdata->u));
++	ieee80211_if_sdata_init(sdata);
++}
++
++/* Must be called with rtnl lock held. */
++void __ieee80211_if_del(struct ieee80211_local *local,
++			struct ieee80211_sub_if_data *sdata)
++{
++	struct net_device *dev = sdata->dev;
++
++	ieee80211_debugfs_remove_netdev(sdata);
++	unregister_netdevice(dev);
++	/* Except master interface, the net_device will be freed by
++	 * net_device->destructor (i. e. ieee80211_if_free). */
++}
++
++/* Must be called with rtnl lock held. */
++int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata, *n;
++
++	ASSERT_RTNL();
++
++	list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
++		if ((sdata->vif.type == id || id == -1) &&
++		    strcmp(name, sdata->dev->name) == 0 &&
++		    sdata->dev != local->mdev) {
++			list_del_rcu(&sdata->list);
++			synchronize_rcu();
++			__ieee80211_if_del(local, sdata);
++			return 0;
++		}
++	}
++	return -ENODEV;
++}
++
++void ieee80211_if_free(struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	ieee80211_if_sdata_deinit(sdata);
++	free_netdev(dev);
++}
+diff --git a/net/mac80211/key.c b/net/mac80211/key.c
+index ed57fb8..150d66d 100644
+--- a/net/mac80211/key.c
++++ b/net/mac80211/key.c
+@@ -2,7 +2,7 @@
+  * Copyright 2002-2005, Instant802 Networks, Inc.
+  * Copyright 2005-2006, Devicescape Software, Inc.
+  * Copyright 2006-2007	Jiri Benc <jbenc at suse.cz>
+- * Copyright 2007	Johannes Berg <johannes at sipsolutions.net>
++ * Copyright 2007-2008	Johannes Berg <johannes at sipsolutions.net>
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+@@ -13,14 +13,15 @@
+ #include <linux/etherdevice.h>
+ #include <linux/list.h>
+ #include <linux/rcupdate.h>
++#include <linux/rtnetlink.h>
+ #include <net/mac80211.h>
+ #include "ieee80211_i.h"
+ #include "debugfs_key.h"
+ #include "aes_ccm.h"
+ 
+ 
+-/*
+- * Key handling basics
++/**
++ * DOC: Key handling basics
+  *
+  * Key handling in mac80211 is done based on per-interface (sub_if_data)
+  * keys and per-station keys. Since each station belongs to an interface,
+@@ -32,13 +33,81 @@
+  * There is currently no way of knowing this except by looking into
+  * debugfs.
+  *
+- * All operations here are called under RTNL so no extra locking is
+- * required.
++ * All key operations are protected internally so you can call them at
++ * any time.
++ *
++ * Within mac80211, key references are, just as STA structure references,
++ * protected by RCU. Note, however, that some things are unprotected,
++ * namely the key->sta dereferences within the hardware acceleration
++ * functions. This means that sta_info_destroy() must flush the key todo
++ * list.
++ *
++ * All the direct key list manipulation functions must not sleep because
++ * they can operate on STA info structs that are protected by RCU.
+  */
+ 
+ static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ static const u8 zero_addr[ETH_ALEN];
+ 
++/* key mutex: used to synchronise todo runners */
++static DEFINE_MUTEX(key_mutex);
++static DEFINE_SPINLOCK(todo_lock);
++static LIST_HEAD(todo_list);
++
++static void key_todo(struct work_struct *work)
++{
++	ieee80211_key_todo();
++}
++
++static DECLARE_WORK(todo_work, key_todo);
++
++/**
++ * add_todo - add todo item for a key
++ *
++ * @key: key to add to do item for
++ * @flag: todo flag(s)
++ */
++static void add_todo(struct ieee80211_key *key, u32 flag)
++{
++	if (!key)
++		return;
++
++	spin_lock(&todo_lock);
++	key->flags |= flag;
++	/*
++	 * Remove again if already on the list so that we move it to the end.
++	 */
++	if (!list_empty(&key->todo))
++		list_del(&key->todo);
++	list_add_tail(&key->todo, &todo_list);
++	schedule_work(&todo_work);
++	spin_unlock(&todo_lock);
++}
++
++/**
++ * ieee80211_key_lock - lock the mac80211 key operation lock
++ *
++ * This locks the (global) mac80211 key operation lock, all
++ * key operations must be done under this lock.
++ */
++static void ieee80211_key_lock(void)
++{
++	mutex_lock(&key_mutex);
++}
++
++/**
++ * ieee80211_key_unlock - unlock the mac80211 key operation lock
++ */
++static void ieee80211_key_unlock(void)
++{
++	mutex_unlock(&key_mutex);
++}
++
++static void assert_key_lock(void)
++{
++	WARN_ON(!mutex_is_locked(&key_mutex));
++}
++
+ static const u8 *get_mac_for_key(struct ieee80211_key *key)
+ {
+ 	const u8 *addr = bcast_addr;
+@@ -65,6 +134,9 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
+ 	int ret;
+ 	DECLARE_MAC_BUF(mac);
+ 
++	assert_key_lock();
++	might_sleep();
++
+ 	if (!key->local->ops->set_key)
+ 		return;
+ 
+@@ -74,8 +146,11 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
+ 				       key->sdata->dev->dev_addr, addr,
+ 				       &key->conf);
+ 
+-	if (!ret)
++	if (!ret) {
++		spin_lock(&todo_lock);
+ 		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
++		spin_unlock(&todo_lock);
++	}
+ 
+ 	if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
+ 		printk(KERN_ERR "mac80211-%s: failed to set key "
+@@ -90,11 +165,18 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
+ 	int ret;
+ 	DECLARE_MAC_BUF(mac);
+ 
+-	if (!key->local->ops->set_key)
++	assert_key_lock();
++	might_sleep();
++
++	if (!key || !key->local->ops->set_key)
+ 		return;
+ 
+-	if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
++	spin_lock(&todo_lock);
++	if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
++		spin_unlock(&todo_lock);
+ 		return;
++	}
++	spin_unlock(&todo_lock);
+ 
+ 	addr = get_mac_for_key(key);
+ 
+@@ -108,12 +190,75 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
+ 		       wiphy_name(key->local->hw.wiphy),
+ 		       key->conf.keyidx, print_mac(mac, addr), ret);
+ 
++	spin_lock(&todo_lock);
+ 	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
++	spin_unlock(&todo_lock);
+ }
+ 
+-struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+-					  struct sta_info *sta,
+-					  enum ieee80211_key_alg alg,
++static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
++					int idx)
++{
++	struct ieee80211_key *key = NULL;
++
++	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
++		key = sdata->keys[idx];
++
++	rcu_assign_pointer(sdata->default_key, key);
++
++	if (key)
++		add_todo(key, KEY_FLAG_TODO_DEFKEY);
++}
++
++void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&sdata->local->key_lock, flags);
++	__ieee80211_set_default_key(sdata, idx);
++	spin_unlock_irqrestore(&sdata->local->key_lock, flags);
++}
++
++
++static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
++				    struct sta_info *sta,
++				    struct ieee80211_key *old,
++				    struct ieee80211_key *new)
++{
++	int idx, defkey;
++
++	if (new)
++		list_add(&new->list, &sdata->key_list);
++
++	if (sta) {
++		rcu_assign_pointer(sta->key, new);
++	} else {
++		WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
++
++		if (old)
++			idx = old->conf.keyidx;
++		else
++			idx = new->conf.keyidx;
++
++		defkey = old && sdata->default_key == old;
++
++		if (defkey && !new)
++			__ieee80211_set_default_key(sdata, -1);
++
++		rcu_assign_pointer(sdata->keys[idx], new);
++		if (defkey && new)
++			__ieee80211_set_default_key(sdata, new->conf.keyidx);
++	}
++
++	if (old) {
++		/*
++		 * We'll use an empty list to indicate that the key
++		 * has already been removed.
++		 */
++		list_del_init(&old->list);
++	}
++}
++
++struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
+ 					  int idx,
+ 					  size_t key_len,
+ 					  const u8 *key_data)
+@@ -137,10 +282,8 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+ 	key->conf.keyidx = idx;
+ 	key->conf.keylen = key_len;
+ 	memcpy(key->conf.key, key_data, key_len);
+-
+-	key->local = sdata->local;
+-	key->sdata = sdata;
+-	key->sta = sta;
++	INIT_LIST_HEAD(&key->list);
++	INIT_LIST_HEAD(&key->todo);
+ 
+ 	if (alg == ALG_CCMP) {
+ 		/*
+@@ -149,22 +292,31 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+ 		 */
+ 		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
+ 		if (!key->u.ccmp.tfm) {
+-			ieee80211_key_free(key);
++			kfree(key);
+ 			return NULL;
+ 		}
+ 	}
+ 
+-	ieee80211_debugfs_key_add(key->local, key);
++	return key;
++}
+ 
+-	/* remove key first */
+-	if (sta)
+-		ieee80211_key_free(sta->key);
+-	else
+-		ieee80211_key_free(sdata->keys[idx]);
++void ieee80211_key_link(struct ieee80211_key *key,
++			struct ieee80211_sub_if_data *sdata,
++			struct sta_info *sta)
++{
++	struct ieee80211_key *old_key;
++	unsigned long flags;
++	int idx;
+ 
+-	if (sta) {
+-		ieee80211_debugfs_key_sta_link(key, sta);
++	BUG_ON(!sdata);
++	BUG_ON(!key);
+ 
++	idx = key->conf.keyidx;
++	key->local = sdata->local;
++	key->sdata = sdata;
++	key->sta = sta;
++
++	if (sta) {
+ 		/*
+ 		 * some hardware cannot handle TKIP with QoS, so
+ 		 * we indicate whether QoS could be in use.
+@@ -175,105 +327,194 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+ 		if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
+ 			struct sta_info *ap;
+ 
++			/*
++			 * We're getting a sta pointer in,
++			 * so must be under RCU read lock.
++			 */
++
+ 			/* same here, the AP could be using QoS */
+ 			ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
+ 			if (ap) {
+ 				if (ap->flags & WLAN_STA_WME)
+ 					key->conf.flags |=
+ 						IEEE80211_KEY_FLAG_WMM_STA;
+-				sta_info_put(ap);
+ 			}
+ 		}
+ 	}
+ 
+-	/* enable hwaccel if appropriate */
+-	if (netif_running(key->sdata->dev))
+-		ieee80211_key_enable_hw_accel(key);
++	spin_lock_irqsave(&sdata->local->key_lock, flags);
+ 
+ 	if (sta)
+-		rcu_assign_pointer(sta->key, key);
++		old_key = sta->key;
+ 	else
+-		rcu_assign_pointer(sdata->keys[idx], key);
++		old_key = sdata->keys[idx];
+ 
+-	list_add(&key->list, &sdata->key_list);
++	__ieee80211_key_replace(sdata, sta, old_key, key);
+ 
+-	return key;
++	spin_unlock_irqrestore(&sdata->local->key_lock, flags);
++
++	/* free old key later */
++	add_todo(old_key, KEY_FLAG_TODO_DELETE);
++
++	add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
++	if (netif_running(sdata->dev))
++		add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
++}
++
++static void __ieee80211_key_free(struct ieee80211_key *key)
++{
++	/*
++	 * Replace key with nothingness if it was ever used.
++	 */
++	if (key->sdata)
++		__ieee80211_key_replace(key->sdata, key->sta,
++					key, NULL);
++
++	add_todo(key, KEY_FLAG_TODO_DELETE);
+ }
+ 
+ void ieee80211_key_free(struct ieee80211_key *key)
+ {
++	unsigned long flags;
++
+ 	if (!key)
+ 		return;
+ 
+-	if (key->sta) {
+-		rcu_assign_pointer(key->sta->key, NULL);
+-	} else {
+-		if (key->sdata->default_key == key)
+-			ieee80211_set_default_key(key->sdata, -1);
+-		if (key->conf.keyidx >= 0 &&
+-		    key->conf.keyidx < NUM_DEFAULT_KEYS)
+-			rcu_assign_pointer(key->sdata->keys[key->conf.keyidx],
+-					   NULL);
+-		else
+-			WARN_ON(1);
+-	}
++	spin_lock_irqsave(&key->sdata->local->key_lock, flags);
++	__ieee80211_key_free(key);
++	spin_unlock_irqrestore(&key->sdata->local->key_lock, flags);
++}
+ 
+-	/* wait for all key users to complete */
+-	synchronize_rcu();
++/*
++ * To be safe against concurrent manipulations of the list (which shouldn't
++ * actually happen) we need to hold the spinlock. But under the spinlock we
++ * can't actually do much, so we defer processing to the todo list. Then run
++ * the todo list to be sure the operation and possibly previously pending
++ * operations are completed.
++ */
++static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata,
++					u32 todo_flags)
++{
++	struct ieee80211_key *key;
++	unsigned long flags;
++
++	might_sleep();
++
++	spin_lock_irqsave(&sdata->local->key_lock, flags);
++	list_for_each_entry(key, &sdata->key_list, list)
++		add_todo(key, todo_flags);
++	spin_unlock_irqrestore(&sdata->local->key_lock, flags);
++
++	ieee80211_key_todo();
++}
++
++void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
++{
++	ASSERT_RTNL();
++
++	if (WARN_ON(!netif_running(sdata->dev)))
++		return;
++
++	ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD);
++}
++
++void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
++{
++	ASSERT_RTNL();
++
++	ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE);
++}
++
++static void __ieee80211_key_destroy(struct ieee80211_key *key)
++{
++	if (!key)
++		return;
+ 
+-	/* remove from hwaccel if appropriate */
+ 	ieee80211_key_disable_hw_accel(key);
+ 
+ 	if (key->conf.alg == ALG_CCMP)
+ 		ieee80211_aes_key_free(key->u.ccmp.tfm);
+ 	ieee80211_debugfs_key_remove(key);
+ 
+-	list_del(&key->list);
+-
+ 	kfree(key);
+ }
+ 
+-void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
++static void __ieee80211_key_todo(void)
+ {
+-	struct ieee80211_key *key = NULL;
++	struct ieee80211_key *key;
++	bool work_done;
++	u32 todoflags;
+ 
+-	if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
+-		key = sdata->keys[idx];
++	/*
++	 * NB: sta_info_destroy relies on this!
++	 */
++	synchronize_rcu();
+ 
+-	if (sdata->default_key != key) {
+-		ieee80211_debugfs_key_remove_default(sdata);
++	spin_lock(&todo_lock);
++	while (!list_empty(&todo_list)) {
++		key = list_first_entry(&todo_list, struct ieee80211_key, todo);
++		list_del_init(&key->todo);
++		todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
++					  KEY_FLAG_TODO_DEFKEY |
++					  KEY_FLAG_TODO_HWACCEL_ADD |
++					  KEY_FLAG_TODO_HWACCEL_REMOVE |
++					  KEY_FLAG_TODO_DELETE);
++		key->flags &= ~todoflags;
++		spin_unlock(&todo_lock);
++
++		work_done = false;
++
++		if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) {
++			ieee80211_debugfs_key_add(key);
++			work_done = true;
++		}
++		if (todoflags & KEY_FLAG_TODO_DEFKEY) {
++			ieee80211_debugfs_key_remove_default(key->sdata);
++			ieee80211_debugfs_key_add_default(key->sdata);
++			work_done = true;
++		}
++		if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
++			ieee80211_key_enable_hw_accel(key);
++			work_done = true;
++		}
++		if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
++			ieee80211_key_disable_hw_accel(key);
++			work_done = true;
++		}
++		if (todoflags & KEY_FLAG_TODO_DELETE) {
++			__ieee80211_key_destroy(key);
++			work_done = true;
++		}
+ 
+-		rcu_assign_pointer(sdata->default_key, key);
++		WARN_ON(!work_done);
+ 
+-		if (sdata->default_key)
+-			ieee80211_debugfs_key_add_default(sdata);
++		spin_lock(&todo_lock);
+ 	}
++	spin_unlock(&todo_lock);
+ }
+ 
+-void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
++void ieee80211_key_todo(void)
+ {
+-	struct ieee80211_key *key, *tmp;
+-
+-	list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
+-		ieee80211_key_free(key);
++	ieee80211_key_lock();
++	__ieee80211_key_todo();
++	ieee80211_key_unlock();
+ }
+ 
+-void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
++void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
+ {
+-	struct ieee80211_key *key;
++	struct ieee80211_key *key, *tmp;
++	unsigned long flags;
+ 
+-	WARN_ON(!netif_running(sdata->dev));
+-	if (!netif_running(sdata->dev))
+-		return;
++	ieee80211_key_lock();
+ 
+-	list_for_each_entry(key, &sdata->key_list, list)
+-		ieee80211_key_enable_hw_accel(key);
+-}
++	ieee80211_debugfs_key_remove_default(sdata);
+ 
+-void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
+-{
+-	struct ieee80211_key *key;
++	spin_lock_irqsave(&sdata->local->key_lock, flags);
++	list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
++		__ieee80211_key_free(key);
++	spin_unlock_irqrestore(&sdata->local->key_lock, flags);
+ 
+-	list_for_each_entry(key, &sdata->key_list, list)
+-		ieee80211_key_disable_hw_accel(key);
++	__ieee80211_key_todo();
++
++	ieee80211_key_unlock();
+ }
+diff --git a/net/mac80211/key.h b/net/mac80211/key.h
+new file mode 100644
+index 0000000..f52c3df
+--- /dev/null
++++ b/net/mac80211/key.h
+@@ -0,0 +1,161 @@
++/*
++ * Copyright 2002-2004, Instant802 Networks, Inc.
++ * Copyright 2005, Devicescape Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef IEEE80211_KEY_H
++#define IEEE80211_KEY_H
++
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/crypto.h>
++#include <linux/rcupdate.h>
++#include <net/mac80211.h>
++
++/* ALG_TKIP
++ * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block:
++ * Temporal Encryption Key (128 bits)
++ * Temporal Authenticator Tx MIC Key (64 bits)
++ * Temporal Authenticator Rx MIC Key (64 bits)
++ */
++
++#define WEP_IV_LEN 4
++#define WEP_ICV_LEN 4
++
++#define ALG_TKIP_KEY_LEN 32
++/* Starting offsets for each key */
++#define ALG_TKIP_TEMP_ENCR_KEY 0
++#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16
++#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24
++#define TKIP_IV_LEN 8
++#define TKIP_ICV_LEN 4
++
++#define ALG_CCMP_KEY_LEN 16
++#define CCMP_HDR_LEN 8
++#define CCMP_MIC_LEN 8
++#define CCMP_TK_LEN 16
++#define CCMP_PN_LEN 6
++
++#define NUM_RX_DATA_QUEUES 17
++
++struct ieee80211_local;
++struct ieee80211_sub_if_data;
++struct sta_info;
++
++/**
++ * enum ieee80211_internal_key_flags - internal key flags
++ *
++ * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present
++ *	in the hardware for TX crypto hardware acceleration.
++ * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an
++ *	RCU grace period, no longer be reachable other than from the
++ *	todo list.
++ * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration.
++ * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware
++ *	acceleration.
++ * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated.
++ * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
++ */
++enum ieee80211_internal_key_flags {
++	KEY_FLAG_UPLOADED_TO_HARDWARE	= BIT(0),
++	KEY_FLAG_TODO_DELETE		= BIT(1),
++	KEY_FLAG_TODO_HWACCEL_ADD	= BIT(2),
++	KEY_FLAG_TODO_HWACCEL_REMOVE	= BIT(3),
++	KEY_FLAG_TODO_DEFKEY		= BIT(4),
++	KEY_FLAG_TODO_ADD_DEBUGFS	= BIT(5),
++};
++
++struct ieee80211_key {
++	struct ieee80211_local *local;
++	struct ieee80211_sub_if_data *sdata;
++	struct sta_info *sta;
++
++	/* for sdata list */
++	struct list_head list;
++	/* for todo list */
++	struct list_head todo;
++
++	/* protected by todo lock! */
++	unsigned int flags;
++
++	union {
++		struct {
++			/* last used TSC */
++			u32 iv32;
++			u16 iv16;
++			u16 p1k[5];
++			int tx_initialized;
++
++			/* last received RSC */
++			u32 iv32_rx[NUM_RX_DATA_QUEUES];
++			u16 iv16_rx[NUM_RX_DATA_QUEUES];
++			u16 p1k_rx[NUM_RX_DATA_QUEUES][5];
++			int rx_initialized[NUM_RX_DATA_QUEUES];
++		} tkip;
++		struct {
++			u8 tx_pn[6];
++			u8 rx_pn[NUM_RX_DATA_QUEUES][6];
++			struct crypto_cipher *tfm;
++			u32 replays; /* dot11RSNAStatsCCMPReplays */
++			/* scratch buffers for virt_to_page() (crypto API) */
++#ifndef AES_BLOCK_LEN
++#define AES_BLOCK_LEN 16
++#endif
++			u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
++			u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
++		} ccmp;
++	} u;
++
++	/* number of times this key has been used */
++	int tx_rx_count;
++
++#ifdef CONFIG_MAC80211_DEBUGFS
++	struct {
++		struct dentry *stalink;
++		struct dentry *dir;
++		struct dentry *keylen;
++		struct dentry *flags;
++		struct dentry *keyidx;
++		struct dentry *hw_key_idx;
++		struct dentry *tx_rx_count;
++		struct dentry *algorithm;
++		struct dentry *tx_spec;
++		struct dentry *rx_spec;
++		struct dentry *replays;
++		struct dentry *key;
++		struct dentry *ifindex;
++		int cnt;
++	} debugfs;
++#endif
++
++	/*
++	 * key config, must be last because it contains key
++	 * material as variable length member
++	 */
++	struct ieee80211_key_conf conf;
++};
++
++struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
++					  int idx,
++					  size_t key_len,
++					  const u8 *key_data);
++/*
++ * 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);
++void ieee80211_key_free(struct ieee80211_key *key);
++void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
++void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
++void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
++void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
++
++void ieee80211_key_todo(void);
++
++#endif /* IEEE80211_KEY_H */
+diff --git a/net/mac80211/led.c b/net/mac80211/led.c
+new file mode 100644
+index 0000000..162a643
+--- /dev/null
++++ b/net/mac80211/led.c
+@@ -0,0 +1,161 @@
++/*
++ * Copyright 2006, Johannes Berg <johannes at sipsolutions.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* just for IFNAMSIZ */
++#include <linux/if.h>
++#include "led.h"
++
++void ieee80211_led_rx(struct ieee80211_local *local)
++{
++	if (unlikely(!local->rx_led))
++		return;
++	if (local->rx_led_counter++ % 2 == 0)
++		led_trigger_event(local->rx_led, LED_OFF);
++	else
++		led_trigger_event(local->rx_led, LED_FULL);
++}
++
++/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
++void ieee80211_led_tx(struct ieee80211_local *local, int q)
++{
++	if (unlikely(!local->tx_led))
++		return;
++	/* not sure how this is supposed to work ... */
++	local->tx_led_counter += 2*q-1;
++	if (local->tx_led_counter % 2 == 0)
++		led_trigger_event(local->tx_led, LED_OFF);
++	else
++		led_trigger_event(local->tx_led, LED_FULL);
++}
++
++void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
++{
++	if (unlikely(!local->assoc_led))
++		return;
++	if (associated)
++		led_trigger_event(local->assoc_led, LED_FULL);
++	else
++		led_trigger_event(local->assoc_led, LED_OFF);
++}
++
++void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
++{
++	if (unlikely(!local->radio_led))
++		return;
++	if (enabled)
++		led_trigger_event(local->radio_led, LED_FULL);
++	else
++		led_trigger_event(local->radio_led, LED_OFF);
++}
++
++void ieee80211_led_init(struct ieee80211_local *local)
++{
++	local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++	if (local->rx_led) {
++		snprintf(local->rx_led_name, sizeof(local->rx_led_name),
++			 "%srx", wiphy_name(local->hw.wiphy));
++		local->rx_led->name = local->rx_led_name;
++		if (led_trigger_register(local->rx_led)) {
++			kfree(local->rx_led);
++			local->rx_led = NULL;
++		}
++	}
++
++	local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++	if (local->tx_led) {
++		snprintf(local->tx_led_name, sizeof(local->tx_led_name),
++			 "%stx", wiphy_name(local->hw.wiphy));
++		local->tx_led->name = local->tx_led_name;
++		if (led_trigger_register(local->tx_led)) {
++			kfree(local->tx_led);
++			local->tx_led = NULL;
++		}
++	}
++
++	local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++	if (local->assoc_led) {
++		snprintf(local->assoc_led_name, sizeof(local->assoc_led_name),
++			 "%sassoc", wiphy_name(local->hw.wiphy));
++		local->assoc_led->name = local->assoc_led_name;
++		if (led_trigger_register(local->assoc_led)) {
++			kfree(local->assoc_led);
++			local->assoc_led = NULL;
++		}
++	}
++
++	local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++	if (local->radio_led) {
++		snprintf(local->radio_led_name, sizeof(local->radio_led_name),
++			 "%sradio", wiphy_name(local->hw.wiphy));
++		local->radio_led->name = local->radio_led_name;
++		if (led_trigger_register(local->radio_led)) {
++			kfree(local->radio_led);
++			local->radio_led = NULL;
++		}
++	}
++}
++
++void ieee80211_led_exit(struct ieee80211_local *local)
++{
++	if (local->radio_led) {
++		led_trigger_unregister(local->radio_led);
++		kfree(local->radio_led);
++	}
++	if (local->assoc_led) {
++		led_trigger_unregister(local->assoc_led);
++		kfree(local->assoc_led);
++	}
++	if (local->tx_led) {
++		led_trigger_unregister(local->tx_led);
++		kfree(local->tx_led);
++	}
++	if (local->rx_led) {
++		led_trigger_unregister(local->rx_led);
++		kfree(local->rx_led);
++	}
++}
++
++char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++
++	if (local->radio_led)
++		return local->radio_led_name;
++	return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
++
++char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++
++	if (local->assoc_led)
++		return local->assoc_led_name;
++	return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
++
++char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++
++	if (local->tx_led)
++		return local->tx_led_name;
++	return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
++
++char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++
++	if (local->rx_led)
++		return local->rx_led_name;
++	return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
+diff --git a/net/mac80211/led.h b/net/mac80211/led.h
+new file mode 100644
+index 0000000..77b1e1b
+--- /dev/null
++++ b/net/mac80211/led.h
+@@ -0,0 +1,44 @@
++/*
++ * Copyright 2006, Johannes Berg <johannes at sipsolutions.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/leds.h>
++#include "ieee80211_i.h"
++
++#ifdef CONFIG_MAC80211_LEDS
++extern void ieee80211_led_rx(struct ieee80211_local *local);
++extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
++extern void ieee80211_led_assoc(struct ieee80211_local *local,
++				bool associated);
++extern void ieee80211_led_radio(struct ieee80211_local *local,
++				bool enabled);
++extern void ieee80211_led_init(struct ieee80211_local *local);
++extern void ieee80211_led_exit(struct ieee80211_local *local);
++#else
++static inline void ieee80211_led_rx(struct ieee80211_local *local)
++{
++}
++static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
++{
++}
++static inline void ieee80211_led_assoc(struct ieee80211_local *local,
++				       bool associated)
++{
++}
++static inline void ieee80211_led_radio(struct ieee80211_local *local,
++				       bool enabled)
++{
++}
++static inline void ieee80211_led_init(struct ieee80211_local *local)
++{
++}
++static inline void ieee80211_led_exit(struct ieee80211_local *local)
++{
++}
++#endif
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+new file mode 100644
+index 0000000..e9a9789
+--- /dev/null
++++ b/net/mac80211/main.c
+@@ -0,0 +1,1891 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ * Copyright 2006-2007	Jiri Benc <jbenc at suse.cz>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <net/mac80211.h>
++#include <net/ieee80211_radiotap.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/skbuff.h>
++#include <linux/etherdevice.h>
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#include <linux/rtnetlink.h>
++#include <linux/bitmap.h>
++#include <net/net_namespace.h>
++#include <net/cfg80211.h>
++
++#include "ieee80211_i.h"
++#include "rate.h"
++#include "mesh.h"
++#include "wep.h"
++#include "wme.h"
++#include "aes_ccm.h"
++#include "led.h"
++#include "cfg.h"
++#include "debugfs.h"
++#include "debugfs_netdev.h"
++
++#define SUPP_MCS_SET_LEN 16
++
++/*
++ * For seeing transmitted packets on monitor interfaces
++ * we have a radiotap header too.
++ */
++struct ieee80211_tx_status_rtap_hdr {
++	struct ieee80211_radiotap_header hdr;
++	__le16 tx_flags;
++	u8 data_retries;
++} __attribute__ ((packed));
++
++/* common interface routines */
++
++static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
++{
++	memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
++	return ETH_ALEN;
++}
++
++/* must be called under mdev tx lock */
++static void ieee80211_configure_filter(struct ieee80211_local *local)
++{
++	unsigned int changed_flags;
++	unsigned int new_flags = 0;
++
++	if (atomic_read(&local->iff_promiscs))
++		new_flags |= FIF_PROMISC_IN_BSS;
++
++	if (atomic_read(&local->iff_allmultis))
++		new_flags |= FIF_ALLMULTI;
++
++	if (local->monitors)
++		new_flags |= FIF_BCN_PRBRESP_PROMISC;
++
++	if (local->fif_fcsfail)
++		new_flags |= FIF_FCSFAIL;
++
++	if (local->fif_plcpfail)
++		new_flags |= FIF_PLCPFAIL;
++
++	if (local->fif_control)
++		new_flags |= FIF_CONTROL;
++
++	if (local->fif_other_bss)
++		new_flags |= FIF_OTHER_BSS;
++
++	changed_flags = local->filter_flags ^ new_flags;
++
++	/* be a bit nasty */
++	new_flags |= (1<<31);
++
++	local->ops->configure_filter(local_to_hw(local),
++				     changed_flags, &new_flags,
++				     local->mdev->mc_count,
++				     local->mdev->mc_list);
++
++	WARN_ON(new_flags & (1<<31));
++
++	local->filter_flags = new_flags & ~(1<<31);
++}
++
++/* master interface */
++
++static int ieee80211_master_open(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata;
++	int res = -EOPNOTSUPP;
++
++	/* we hold the RTNL here so can safely walk the list */
++	list_for_each_entry(sdata, &local->interfaces, list) {
++		if (sdata->dev != dev && netif_running(sdata->dev)) {
++			res = 0;
++			break;
++		}
++	}
++	return res;
++}
++
++static int ieee80211_master_stop(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata;
++
++	/* we hold the RTNL here so can safely walk the list */
++	list_for_each_entry(sdata, &local->interfaces, list)
++		if (sdata->dev != dev && netif_running(sdata->dev))
++			dev_close(sdata->dev);
++
++	return 0;
++}
++
++static void ieee80211_master_set_multicast_list(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	ieee80211_configure_filter(local);
++}
++
++/* regular interfaces */
++
++static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
++{
++	int meshhdrlen;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	meshhdrlen = (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) ? 5 : 0;
++
++	/* FIX: what would be proper limits for MTU?
++	 * This interface uses 802.3 frames. */
++	if (new_mtu < 256 ||
++		new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
++		printk(KERN_WARNING "%s: invalid MTU %d\n",
++		       dev->name, new_mtu);
++		return -EINVAL;
++	}
++
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++	printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
++#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
++	dev->mtu = new_mtu;
++	return 0;
++}
++
++static inline int identical_mac_addr_allowed(int type1, int type2)
++{
++	return (type1 == IEEE80211_IF_TYPE_MNTR ||
++		type2 == IEEE80211_IF_TYPE_MNTR ||
++		(type1 == IEEE80211_IF_TYPE_AP &&
++		 type2 == IEEE80211_IF_TYPE_WDS) ||
++		(type1 == IEEE80211_IF_TYPE_WDS &&
++		 (type2 == IEEE80211_IF_TYPE_WDS ||
++		  type2 == IEEE80211_IF_TYPE_AP)) ||
++		(type1 == IEEE80211_IF_TYPE_AP &&
++		 type2 == IEEE80211_IF_TYPE_VLAN) ||
++		(type1 == IEEE80211_IF_TYPE_VLAN &&
++		 (type2 == IEEE80211_IF_TYPE_AP ||
++		  type2 == IEEE80211_IF_TYPE_VLAN)));
++}
++
++static int ieee80211_open(struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata, *nsdata;
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_if_init_conf conf;
++	int res;
++	bool need_hw_reconfig = 0;
++	struct sta_info *sta;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	/* we hold the RTNL here so can safely walk the list */
++	list_for_each_entry(nsdata, &local->interfaces, list) {
++		struct net_device *ndev = nsdata->dev;
++
++		if (ndev != dev && ndev != local->mdev && netif_running(ndev)) {
++			/*
++			 * Allow only a single IBSS interface to be up at any
++			 * time. This is restricted because beacon distribution
++			 * cannot work properly if both are in the same IBSS.
++			 *
++			 * To remove this restriction we'd have to disallow them
++			 * from setting the same SSID on different IBSS interfaces
++			 * belonging to the same hardware. Then, however, we're
++			 * faced with having to adopt two different TSF timers...
++			 */
++			if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
++			    nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)
++				return -EBUSY;
++
++			/*
++			 * Disallow multiple IBSS/STA mode interfaces.
++			 *
++			 * This is a technical restriction, it is possible although
++			 * most likely not IEEE 802.11 compliant to have multiple
++			 * STAs with just a single hardware (the TSF timer will not
++			 * be adjusted properly.)
++			 *
++			 * However, because mac80211 uses the master device's BSS
++			 * information for each STA/IBSS interface, doing this will
++			 * currently corrupt that BSS information completely, unless,
++			 * a not very useful case, both STAs are associated to the
++			 * same BSS.
++			 *
++			 * To remove this restriction, the BSS information needs to
++			 * be embedded in the STA/IBSS mode sdata instead of using
++			 * the master device's BSS structure.
++			 */
++			if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++			     sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
++			    (nsdata->vif.type == IEEE80211_IF_TYPE_STA ||
++			     nsdata->vif.type == IEEE80211_IF_TYPE_IBSS))
++				return -EBUSY;
++
++			/*
++			 * The remaining checks are only performed for interfaces
++			 * with the same MAC address.
++			 */
++			if (compare_ether_addr(dev->dev_addr, ndev->dev_addr))
++				continue;
++
++			/*
++			 * check whether it may have the same address
++			 */
++			if (!identical_mac_addr_allowed(sdata->vif.type,
++							nsdata->vif.type))
++				return -ENOTUNIQ;
++
++			/*
++			 * can only add VLANs to enabled APs
++			 */
++			if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
++			    nsdata->vif.type == IEEE80211_IF_TYPE_AP)
++				sdata->u.vlan.ap = nsdata;
++		}
++	}
++
++	switch (sdata->vif.type) {
++	case IEEE80211_IF_TYPE_WDS:
++		if (is_zero_ether_addr(sdata->u.wds.remote_addr))
++			return -ENOLINK;
++
++		/* Create STA entry for the WDS peer */
++		sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
++				     GFP_KERNEL);
++		if (!sta)
++			return -ENOMEM;
++
++		sta->flags |= WLAN_STA_AUTHORIZED;
++
++		res = sta_info_insert(sta);
++		if (res) {
++			/* STA has been freed */
++			return res;
++		}
++		break;
++	case IEEE80211_IF_TYPE_VLAN:
++		if (!sdata->u.vlan.ap)
++			return -ENOLINK;
++		break;
++	case IEEE80211_IF_TYPE_AP:
++	case IEEE80211_IF_TYPE_STA:
++	case IEEE80211_IF_TYPE_MNTR:
++	case IEEE80211_IF_TYPE_IBSS:
++	case IEEE80211_IF_TYPE_MESH_POINT:
++		/* no special treatment */
++		break;
++	case IEEE80211_IF_TYPE_INVALID:
++		/* cannot happen */
++		WARN_ON(1);
++		break;
++	}
++
++	if (local->open_count == 0) {
++		res = 0;
++		if (local->ops->start)
++			res = local->ops->start(local_to_hw(local));
++		if (res)
++			return res;
++		need_hw_reconfig = 1;
++		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
++	}
++
++	switch (sdata->vif.type) {
++	case IEEE80211_IF_TYPE_VLAN:
++		list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
++		/* no need to tell driver */
++		break;
++	case IEEE80211_IF_TYPE_MNTR:
++		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
++			local->cooked_mntrs++;
++			break;
++		}
++
++		/* must be before the call to ieee80211_configure_filter */
++		local->monitors++;
++		if (local->monitors == 1)
++			local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
++
++		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++;
++		if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
++			local->fif_other_bss++;
++
++		netif_tx_lock_bh(local->mdev);
++		ieee80211_configure_filter(local);
++		netif_tx_unlock_bh(local->mdev);
++		break;
++	case IEEE80211_IF_TYPE_STA:
++	case IEEE80211_IF_TYPE_IBSS:
++		sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
++		/* fall through */
++	default:
++		conf.vif = &sdata->vif;
++		conf.type = sdata->vif.type;
++		conf.mac_addr = dev->dev_addr;
++		res = local->ops->add_interface(local_to_hw(local), &conf);
++		if (res && !local->open_count && local->ops->stop)
++			local->ops->stop(local_to_hw(local));
++		if (res)
++			return res;
++
++		ieee80211_if_config(dev);
++		ieee80211_reset_erp_info(dev);
++		ieee80211_enable_keys(sdata);
++
++		if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
++		    !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
++			netif_carrier_off(dev);
++		else
++			netif_carrier_on(dev);
++	}
++
++	if (local->open_count == 0) {
++		res = dev_open(local->mdev);
++		WARN_ON(res);
++		tasklet_enable(&local->tx_pending_tasklet);
++		tasklet_enable(&local->tasklet);
++	}
++
++	/*
++	 * set_multicast_list will be invoked by the networking core
++	 * which will check whether any increments here were done in
++	 * error and sync them down to the hardware as filter flags.
++	 */
++	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
++		atomic_inc(&local->iff_allmultis);
++
++	if (sdata->flags & IEEE80211_SDATA_PROMISC)
++		atomic_inc(&local->iff_promiscs);
++
++	local->open_count++;
++	if (need_hw_reconfig)
++		ieee80211_hw_config(local);
++
++	/*
++	 * ieee80211_sta_work is disabled while network interface
++	 * is down. Therefore, some configuration changes may not
++	 * yet be effective. Trigger execution of ieee80211_sta_work
++	 * to fix this.
++	 */
++	if(sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++	   sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++		struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++		queue_work(local->hw.workqueue, &ifsta->work);
++	}
++
++	netif_start_queue(dev);
++
++	return 0;
++}
++
++static int ieee80211_stop(struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_local *local = sdata->local;
++	struct ieee80211_if_init_conf conf;
++	struct sta_info *sta;
++
++	/*
++	 * Stop TX on this interface first.
++	 */
++	netif_stop_queue(dev);
++
++	/*
++	 * Now delete all active aggregation sessions.
++	 */
++	rcu_read_lock();
++
++	list_for_each_entry_rcu(sta, &local->sta_list, list) {
++		if (sta->sdata == sdata)
++			ieee80211_sta_tear_down_BA_sessions(dev, sta->addr);
++	}
++
++	rcu_read_unlock();
++
++	/*
++	 * Remove all stations associated with this interface.
++	 *
++	 * This must be done before calling ops->remove_interface()
++	 * because otherwise we can later invoke ops->sta_notify()
++	 * whenever the STAs are removed, and that invalidates driver
++	 * assumptions about always getting a vif pointer that is valid
++	 * (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.
++	 */
++	sta_info_flush(local, sdata);
++
++	/*
++	 * Don't count this interface for promisc/allmulti while it
++	 * is down. dev_mc_unsync() will invoke set_multicast_list
++	 * on the master interface which will sync these down to the
++	 * hardware as filter flags.
++	 */
++	if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
++		atomic_dec(&local->iff_allmultis);
++
++	if (sdata->flags & IEEE80211_SDATA_PROMISC)
++		atomic_dec(&local->iff_promiscs);
++
++	dev_mc_unsync(local->mdev, dev);
++
++	/* APs need special treatment */
++	if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++		struct ieee80211_sub_if_data *vlan, *tmp;
++		struct beacon_data *old_beacon = sdata->u.ap.beacon;
++
++		/* remove beacon */
++		rcu_assign_pointer(sdata->u.ap.beacon, NULL);
++		synchronize_rcu();
++		kfree(old_beacon);
++
++		/* down all dependent devices, that is VLANs */
++		list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
++					 u.vlan.list)
++			dev_close(vlan->dev);
++		WARN_ON(!list_empty(&sdata->u.ap.vlans));
++	}
++
++	local->open_count--;
++
++	switch (sdata->vif.type) {
++	case IEEE80211_IF_TYPE_VLAN:
++		list_del(&sdata->u.vlan.list);
++		sdata->u.vlan.ap = NULL;
++		/* no need to tell driver */
++		break;
++	case IEEE80211_IF_TYPE_MNTR:
++		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
++			local->cooked_mntrs--;
++			break;
++		}
++
++		local->monitors--;
++		if (local->monitors == 0)
++			local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
++
++		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--;
++		if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
++			local->fif_other_bss--;
++
++		netif_tx_lock_bh(local->mdev);
++		ieee80211_configure_filter(local);
++		netif_tx_unlock_bh(local->mdev);
++		break;
++	case IEEE80211_IF_TYPE_MESH_POINT:
++	case IEEE80211_IF_TYPE_STA:
++	case IEEE80211_IF_TYPE_IBSS:
++		sdata->u.sta.state = IEEE80211_DISABLED;
++		del_timer_sync(&sdata->u.sta.timer);
++		/*
++		 * When we get here, the interface is marked down.
++		 * Call synchronize_rcu() to wait for the RX path
++		 * should it be using the interface and enqueuing
++		 * frames at this very time on another CPU.
++		 */
++		synchronize_rcu();
++		skb_queue_purge(&sdata->u.sta.skb_queue);
++
++		if (local->scan_dev == sdata->dev) {
++			if (!local->ops->hw_scan) {
++				local->sta_sw_scanning = 0;
++				cancel_delayed_work(&local->scan_work);
++			} else
++				local->sta_hw_scanning = 0;
++		}
++
++		flush_workqueue(local->hw.workqueue);
++
++		sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
++		kfree(sdata->u.sta.extra_ie);
++		sdata->u.sta.extra_ie = NULL;
++		sdata->u.sta.extra_ie_len = 0;
++		/* fall through */
++	default:
++		conf.vif = &sdata->vif;
++		conf.type = sdata->vif.type;
++		conf.mac_addr = dev->dev_addr;
++		/* disable all keys for as long as this netdev is down */
++		ieee80211_disable_keys(sdata);
++		local->ops->remove_interface(local_to_hw(local), &conf);
++	}
++
++	if (local->open_count == 0) {
++		if (netif_running(local->mdev))
++			dev_close(local->mdev);
++
++		if (local->ops->stop)
++			local->ops->stop(local_to_hw(local));
++
++		ieee80211_led_radio(local, 0);
++
++		tasklet_disable(&local->tx_pending_tasklet);
++		tasklet_disable(&local->tasklet);
++	}
++
++	return 0;
++}
++
++int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct sta_info *sta;
++	struct ieee80211_sub_if_data *sdata;
++	u16 start_seq_num = 0;
++	u8 *state;
++	int ret;
++	DECLARE_MAC_BUF(mac);
++
++	if (tid >= STA_TID_NUM)
++		return -EINVAL;
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++	printk(KERN_DEBUG "Open BA session requested for %s tid %u\n",
++				print_mac(mac, ra), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, ra);
++	if (!sta) {
++		printk(KERN_DEBUG "Could not find the station\n");
++		rcu_read_unlock();
++		return -ENOENT;
++	}
++
++	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++	/* we have tried too many times, receiver does not want A-MPDU */
++	if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
++		ret = -EBUSY;
++		goto start_ba_exit;
++	}
++
++	state = &sta->ampdu_mlme.tid_state_tx[tid];
++	/* check if the TID is not in aggregation flow already */
++	if (*state != HT_AGG_STATE_IDLE) {
++#ifdef CONFIG_MAC80211_HT_DEBUG
++		printk(KERN_DEBUG "BA request denied - session is not "
++				 "idle on tid %u\n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++		ret = -EAGAIN;
++		goto start_ba_exit;
++	}
++
++	/* prepare A-MPDU MLME for Tx aggregation */
++	sta->ampdu_mlme.tid_tx[tid] =
++			kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
++	if (!sta->ampdu_mlme.tid_tx[tid]) {
++		if (net_ratelimit())
++			printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
++					tid);
++		ret = -ENOMEM;
++		goto start_ba_exit;
++	}
++	/* Tx timer */
++	sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
++			sta_addba_resp_timer_expired;
++	sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
++			(unsigned long)&sta->timer_to_tid[tid];
++	init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
++
++	/* ensure that TX flow won't interrupt us
++	 * until the end of the call to requeue function */
++	spin_lock_bh(&local->mdev->queue_lock);
++
++	/* create a new queue for this aggregation */
++	ret = ieee80211_ht_agg_queue_add(local, sta, tid);
++
++	/* case no queue is available to aggregation
++	 * don't switch to aggregation */
++	if (ret) {
++#ifdef CONFIG_MAC80211_HT_DEBUG
++		printk(KERN_DEBUG "BA request denied - queue unavailable for"
++					" tid %d\n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++		goto start_ba_err;
++	}
++	sdata = sta->sdata;
++
++	/* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
++	 * call back right away, it must see that the flow has begun */
++	*state |= HT_ADDBA_REQUESTED_MSK;
++
++	if (local->ops->ampdu_action)
++		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
++						ra, tid, &start_seq_num);
++
++	if (ret) {
++		/* No need to requeue the packets in the agg queue, since we
++		 * held the tx lock: no packet could be enqueued to the newly
++		 * allocated queue */
++		 ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
++#ifdef CONFIG_MAC80211_HT_DEBUG
++		printk(KERN_DEBUG "BA request denied - HW unavailable for"
++					" tid %d\n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++		*state = HT_AGG_STATE_IDLE;
++		goto start_ba_err;
++	}
++
++	/* Will put all the packets in the new SW queue */
++	ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
++	spin_unlock_bh(&local->mdev->queue_lock);
++
++	/* send an addBA request */
++	sta->ampdu_mlme.dialog_token_allocator++;
++	sta->ampdu_mlme.tid_tx[tid]->dialog_token =
++			sta->ampdu_mlme.dialog_token_allocator;
++	sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
++
++	ieee80211_send_addba_request(sta->sdata->dev, ra, tid,
++			 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
++			 sta->ampdu_mlme.tid_tx[tid]->ssn,
++			 0x40, 5000);
++
++	/* activate the timer for the recipient's addBA response */
++	sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
++				jiffies + ADDBA_RESP_INTERVAL;
++	add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
++	printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
++	goto start_ba_exit;
++
++start_ba_err:
++	kfree(sta->ampdu_mlme.tid_tx[tid]);
++	sta->ampdu_mlme.tid_tx[tid] = NULL;
++	spin_unlock_bh(&local->mdev->queue_lock);
++	ret = -EBUSY;
++start_ba_exit:
++	spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++	rcu_read_unlock();
++	return ret;
++}
++EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
++
++int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
++				 u8 *ra, u16 tid,
++				 enum ieee80211_back_parties initiator)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct sta_info *sta;
++	u8 *state;
++	int ret = 0;
++	DECLARE_MAC_BUF(mac);
++
++	if (tid >= STA_TID_NUM)
++		return -EINVAL;
++
++	rcu_read_lock();
++	sta = sta_info_get(local, ra);
++	if (!sta) {
++		rcu_read_unlock();
++		return -ENOENT;
++	}
++
++	/* check if the TID is in aggregation */
++	state = &sta->ampdu_mlme.tid_state_tx[tid];
++	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++	if (*state != HT_AGG_STATE_OPERATIONAL) {
++		ret = -ENOENT;
++		goto stop_BA_exit;
++	}
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++	printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n",
++				print_mac(mac, ra), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++	ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
++
++	*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
++		(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
++
++	if (local->ops->ampdu_action)
++		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
++						ra, tid, NULL);
++
++	/* case HW denied going back to legacy */
++	if (ret) {
++		WARN_ON(ret != -EBUSY);
++		*state = HT_AGG_STATE_OPERATIONAL;
++		ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
++		goto stop_BA_exit;
++	}
++
++stop_BA_exit:
++	spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++	rcu_read_unlock();
++	return ret;
++}
++EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
++
++void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct sta_info *sta;
++	u8 *state;
++	DECLARE_MAC_BUF(mac);
++
++	if (tid >= STA_TID_NUM) {
++		printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
++				tid, STA_TID_NUM);
++		return;
++	}
++
++	rcu_read_lock();
++	sta = sta_info_get(local, ra);
++	if (!sta) {
++		rcu_read_unlock();
++		printk(KERN_DEBUG "Could not find station: %s\n",
++				print_mac(mac, ra));
++		return;
++	}
++
++	state = &sta->ampdu_mlme.tid_state_tx[tid];
++	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
++		printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
++				*state);
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++		rcu_read_unlock();
++		return;
++	}
++
++	WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
++
++	*state |= HT_ADDBA_DRV_READY_MSK;
++
++	if (*state == HT_AGG_STATE_OPERATIONAL) {
++		printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
++		ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
++	}
++	spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++	rcu_read_unlock();
++}
++EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
++
++void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct sta_info *sta;
++	u8 *state;
++	int agg_queue;
++	DECLARE_MAC_BUF(mac);
++
++	if (tid >= STA_TID_NUM) {
++		printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
++				tid, STA_TID_NUM);
++		return;
++	}
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++	printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n",
++				print_mac(mac, ra), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++	rcu_read_lock();
++	sta = sta_info_get(local, ra);
++	if (!sta) {
++		printk(KERN_DEBUG "Could not find station: %s\n",
++				print_mac(mac, ra));
++		rcu_read_unlock();
++		return;
++	}
++	state = &sta->ampdu_mlme.tid_state_tx[tid];
++
++	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++	if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
++		printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++		rcu_read_unlock();
++		return;
++	}
++
++	if (*state & HT_AGG_STATE_INITIATOR_MSK)
++		ieee80211_send_delba(sta->sdata->dev, ra, tid,
++			WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
++
++	agg_queue = sta->tid_to_tx_q[tid];
++
++	/* avoid ordering issues: we are the only one that can modify
++	 * the content of the qdiscs */
++	spin_lock_bh(&local->mdev->queue_lock);
++	/* remove the queue for this aggregation */
++	ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
++	spin_unlock_bh(&local->mdev->queue_lock);
++
++	/* we just requeued the all the frames that were in the removed
++	 * queue, and since we might miss a softirq we do netif_schedule.
++	 * ieee80211_wake_queue is not used here as this queue is not
++	 * necessarily stopped */
++	netif_schedule(local->mdev);
++	*state = HT_AGG_STATE_IDLE;
++	sta->ampdu_mlme.addba_req_num[tid] = 0;
++	kfree(sta->ampdu_mlme.tid_tx[tid]);
++	sta->ampdu_mlme.tid_tx[tid] = NULL;
++	spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++	rcu_read_unlock();
++}
++EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
++
++void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
++				      const u8 *ra, u16 tid)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct ieee80211_ra_tid *ra_tid;
++	struct sk_buff *skb = dev_alloc_skb(0);
++
++	if (unlikely(!skb)) {
++		if (net_ratelimit())
++			printk(KERN_WARNING "%s: Not enough memory, "
++			       "dropping start BA session", skb->dev->name);
++		return;
++	}
++	ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
++	memcpy(&ra_tid->ra, ra, ETH_ALEN);
++	ra_tid->tid = tid;
++
++	skb->pkt_type = IEEE80211_ADDBA_MSG;
++	skb_queue_tail(&local->skb_queue, skb);
++	tasklet_schedule(&local->tasklet);
++}
++EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
++
++void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
++				     const u8 *ra, u16 tid)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct ieee80211_ra_tid *ra_tid;
++	struct sk_buff *skb = dev_alloc_skb(0);
++
++	if (unlikely(!skb)) {
++		if (net_ratelimit())
++			printk(KERN_WARNING "%s: Not enough memory, "
++			       "dropping stop BA session", skb->dev->name);
++		return;
++	}
++	ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
++	memcpy(&ra_tid->ra, ra, ETH_ALEN);
++	ra_tid->tid = tid;
++
++	skb->pkt_type = IEEE80211_DELBA_MSG;
++	skb_queue_tail(&local->skb_queue, skb);
++	tasklet_schedule(&local->tasklet);
++}
++EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
++
++static void ieee80211_set_multicast_list(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	int allmulti, promisc, sdata_allmulti, sdata_promisc;
++
++	allmulti = !!(dev->flags & IFF_ALLMULTI);
++	promisc = !!(dev->flags & IFF_PROMISC);
++	sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
++	sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
++
++	if (allmulti != sdata_allmulti) {
++		if (dev->flags & IFF_ALLMULTI)
++			atomic_inc(&local->iff_allmultis);
++		else
++			atomic_dec(&local->iff_allmultis);
++		sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
++	}
++
++	if (promisc != sdata_promisc) {
++		if (dev->flags & IFF_PROMISC)
++			atomic_inc(&local->iff_promiscs);
++		else
++			atomic_dec(&local->iff_promiscs);
++		sdata->flags ^= IEEE80211_SDATA_PROMISC;
++	}
++
++	dev_mc_sync(local->mdev, dev);
++}
++
++static const struct header_ops ieee80211_header_ops = {
++	.create		= eth_header,
++	.parse		= header_parse_80211,
++	.rebuild	= eth_rebuild_header,
++	.cache		= eth_header_cache,
++	.cache_update	= eth_header_cache_update,
++};
++
++/* Must not be called for mdev */
++void ieee80211_if_setup(struct net_device *dev)
++{
++	ether_setup(dev);
++	dev->hard_start_xmit = ieee80211_subif_start_xmit;
++	dev->wireless_handlers = &ieee80211_iw_handler_def;
++	dev->set_multicast_list = ieee80211_set_multicast_list;
++	dev->change_mtu = ieee80211_change_mtu;
++	dev->open = ieee80211_open;
++	dev->stop = ieee80211_stop;
++	dev->destructor = ieee80211_if_free;
++}
++
++/* everything else */
++
++static int __ieee80211_if_config(struct net_device *dev,
++				 struct sk_buff *beacon,
++				 struct ieee80211_tx_control *control)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_if_conf conf;
++
++	if (!local->ops->config_interface || !netif_running(dev))
++		return 0;
++
++	memset(&conf, 0, sizeof(conf));
++	conf.type = sdata->vif.type;
++	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++		conf.bssid = sdata->u.sta.bssid;
++		conf.ssid = sdata->u.sta.ssid;
++		conf.ssid_len = sdata->u.sta.ssid_len;
++	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
++		conf.beacon = beacon;
++		ieee80211_start_mesh(dev);
++	} else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++		conf.ssid = sdata->u.ap.ssid;
++		conf.ssid_len = sdata->u.ap.ssid_len;
++		conf.beacon = beacon;
++		conf.beacon_control = control;
++	}
++	return local->ops->config_interface(local_to_hw(local),
++					    &sdata->vif, &conf);
++}
++
++int ieee80211_if_config(struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT &&
++	    (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
++		return ieee80211_if_config_beacon(dev);
++	return __ieee80211_if_config(dev, NULL, NULL);
++}
++
++int ieee80211_if_config_beacon(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_tx_control control;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct sk_buff *skb;
++
++	if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
++		return 0;
++	skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif,
++				   &control);
++	if (!skb)
++		return -ENOMEM;
++	return __ieee80211_if_config(dev, skb, &control);
++}
++
++int ieee80211_hw_config(struct ieee80211_local *local)
++{
++	struct ieee80211_channel *chan;
++	int ret = 0;
++
++	if (local->sta_sw_scanning)
++		chan = local->scan_channel;
++	else
++		chan = local->oper_channel;
++
++	local->hw.conf.channel = chan;
++
++	if (!local->hw.conf.power_level)
++		local->hw.conf.power_level = chan->max_power;
++	else
++		local->hw.conf.power_level = min(chan->max_power,
++					       local->hw.conf.power_level);
++
++	local->hw.conf.max_antenna_gain = chan->max_antenna_gain;
++
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++	printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n",
++	       wiphy_name(local->hw.wiphy), chan->center_freq);
++#endif
++
++	if (local->open_count)
++		ret = local->ops->config(local_to_hw(local), &local->hw.conf);
++
++	return ret;
++}
++
++/**
++ * ieee80211_handle_ht should be used only after legacy configuration
++ * has been determined namely band, as ht configuration depends upon
++ * the hardware's HT abilities for a _specific_ band.
++ */
++u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
++			   struct ieee80211_ht_info *req_ht_cap,
++			   struct ieee80211_ht_bss_info *req_bss_cap)
++{
++	struct ieee80211_conf *conf = &local->hw.conf;
++	struct ieee80211_supported_band *sband;
++	struct ieee80211_ht_info ht_conf;
++	struct ieee80211_ht_bss_info ht_bss_conf;
++	int i;
++	u32 changed = 0;
++
++	sband = local->hw.wiphy->bands[conf->channel->band];
++
++	/* HT is not supported */
++	if (!sband->ht_info.ht_supported) {
++		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
++		return 0;
++	}
++
++	memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info));
++	memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
++
++	if (enable_ht) {
++		if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
++			changed |= BSS_CHANGED_HT;
++
++		conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
++		ht_conf.ht_supported = 1;
++
++		ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap;
++		ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
++		ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
++
++		for (i = 0; i < SUPP_MCS_SET_LEN; i++)
++			ht_conf.supp_mcs_set[i] =
++					sband->ht_info.supp_mcs_set[i] &
++					req_ht_cap->supp_mcs_set[i];
++
++		ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
++		ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
++		ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
++
++		ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
++		ht_conf.ampdu_density = req_ht_cap->ampdu_density;
++
++		/* if bss configuration changed store the new one */
++		if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) ||
++		    memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
++			changed |= BSS_CHANGED_HT;
++			memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf));
++			memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
++		}
++	} else {
++		if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
++			changed |= BSS_CHANGED_HT;
++		conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
++	}
++
++	return changed;
++}
++
++void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
++				      u32 changed)
++{
++	struct ieee80211_local *local = sdata->local;
++
++	if (!changed)
++		return;
++
++	if (local->ops->bss_info_changed)
++		local->ops->bss_info_changed(local_to_hw(local),
++					     &sdata->vif,
++					     &sdata->bss_conf,
++					     changed);
++}
++
++void ieee80211_reset_erp_info(struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	sdata->bss_conf.use_cts_prot = 0;
++	sdata->bss_conf.use_short_preamble = 0;
++	ieee80211_bss_info_change_notify(sdata,
++					 BSS_CHANGED_ERP_CTS_PROT |
++					 BSS_CHANGED_ERP_PREAMBLE);
++}
++
++void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
++				 struct sk_buff *skb,
++				 struct ieee80211_tx_status *status)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct ieee80211_tx_status *saved;
++	int tmp;
++
++	skb->dev = local->mdev;
++	saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC);
++	if (unlikely(!saved)) {
++		if (net_ratelimit())
++			printk(KERN_WARNING "%s: Not enough memory, "
++			       "dropping tx status", skb->dev->name);
++		/* should be dev_kfree_skb_irq, but due to this function being
++		 * named _irqsafe instead of just _irq we can't be sure that
++		 * people won't call it from non-irq contexts */
++		dev_kfree_skb_any(skb);
++		return;
++	}
++	memcpy(saved, status, sizeof(struct ieee80211_tx_status));
++	/* copy pointer to saved status into skb->cb for use by tasklet */
++	memcpy(skb->cb, &saved, sizeof(saved));
++
++	skb->pkt_type = IEEE80211_TX_STATUS_MSG;
++	skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
++		       &local->skb_queue : &local->skb_queue_unreliable, skb);
++	tmp = skb_queue_len(&local->skb_queue) +
++		skb_queue_len(&local->skb_queue_unreliable);
++	while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
++	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
++		memcpy(&saved, skb->cb, sizeof(saved));
++		kfree(saved);
++		dev_kfree_skb_irq(skb);
++		tmp--;
++		I802_DEBUG_INC(local->tx_status_drop);
++	}
++	tasklet_schedule(&local->tasklet);
++}
++EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
++
++static void ieee80211_tasklet_handler(unsigned long data)
++{
++	struct ieee80211_local *local = (struct ieee80211_local *) data;
++	struct sk_buff *skb;
++	struct ieee80211_rx_status rx_status;
++	struct ieee80211_tx_status *tx_status;
++	struct ieee80211_ra_tid *ra_tid;
++
++	while ((skb = skb_dequeue(&local->skb_queue)) ||
++	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
++		switch (skb->pkt_type) {
++		case IEEE80211_RX_MSG:
++			/* status is in skb->cb */
++			memcpy(&rx_status, skb->cb, sizeof(rx_status));
++			/* Clear skb->pkt_type in order to not confuse kernel
++			 * netstack. */
++			skb->pkt_type = 0;
++			__ieee80211_rx(local_to_hw(local), skb, &rx_status);
++			break;
++		case IEEE80211_TX_STATUS_MSG:
++			/* get pointer to saved status out of skb->cb */
++			memcpy(&tx_status, skb->cb, sizeof(tx_status));
++			skb->pkt_type = 0;
++			ieee80211_tx_status(local_to_hw(local),
++					    skb, tx_status);
++			kfree(tx_status);
++			break;
++		case IEEE80211_DELBA_MSG:
++			ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
++			ieee80211_stop_tx_ba_cb(local_to_hw(local),
++						ra_tid->ra, ra_tid->tid);
++			dev_kfree_skb(skb);
++			break;
++		case IEEE80211_ADDBA_MSG:
++			ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
++			ieee80211_start_tx_ba_cb(local_to_hw(local),
++						 ra_tid->ra, ra_tid->tid);
++			dev_kfree_skb(skb);
++			break ;
++		default: /* should never get here! */
++			printk(KERN_ERR "%s: Unknown message type (%d)\n",
++			       wiphy_name(local->hw.wiphy), skb->pkt_type);
++			dev_kfree_skb(skb);
++			break;
++		}
++	}
++}
++
++/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
++ * make a prepared TX frame (one that has been given to hw) to look like brand
++ * new IEEE 802.11 frame that is ready to go through TX processing again.
++ * Also, tx_packet_data in cb is restored from tx_control. */
++static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
++				      struct ieee80211_key *key,
++				      struct sk_buff *skb,
++				      struct ieee80211_tx_control *control)
++{
++	int hdrlen, iv_len, mic_len;
++	struct ieee80211_tx_packet_data *pkt_data;
++
++	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
++	pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex;
++	pkt_data->flags = 0;
++	if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS)
++		pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
++	if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)
++		pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
++	if (control->flags & IEEE80211_TXCTL_REQUEUE)
++		pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
++	if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME)
++		pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
++	pkt_data->queue = control->queue;
++
++	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
++
++	if (!key)
++		goto no_key;
++
++	switch (key->conf.alg) {
++	case ALG_WEP:
++		iv_len = WEP_IV_LEN;
++		mic_len = WEP_ICV_LEN;
++		break;
++	case ALG_TKIP:
++		iv_len = TKIP_IV_LEN;
++		mic_len = TKIP_ICV_LEN;
++		break;
++	case ALG_CCMP:
++		iv_len = CCMP_HDR_LEN;
++		mic_len = CCMP_MIC_LEN;
++		break;
++	default:
++		goto no_key;
++	}
++
++	if (skb->len >= mic_len &&
++	    !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
++		skb_trim(skb, skb->len - mic_len);
++	if (skb->len >= iv_len && skb->len > hdrlen) {
++		memmove(skb->data + iv_len, skb->data, hdrlen);
++		skb_pull(skb, iv_len);
++	}
++
++no_key:
++	{
++		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++		u16 fc = le16_to_cpu(hdr->frame_control);
++		if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
++			fc &= ~IEEE80211_STYPE_QOS_DATA;
++			hdr->frame_control = cpu_to_le16(fc);
++			memmove(skb->data + 2, skb->data, hdrlen - 2);
++			skb_pull(skb, 2);
++		}
++	}
++}
++
++static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
++					    struct sta_info *sta,
++					    struct sk_buff *skb,
++					    struct ieee80211_tx_status *status)
++{
++	sta->tx_filtered_count++;
++
++	/*
++	 * Clear the TX filter mask for this STA when sending the next
++	 * packet. If the STA went to power save mode, this will happen
++	 * happen when it wakes up for the next time.
++	 */
++	sta->flags |= WLAN_STA_CLEAR_PS_FILT;
++
++	/*
++	 * This code races in the following way:
++	 *
++	 *  (1) STA sends frame indicating it will go to sleep and does so
++	 *  (2) hardware/firmware adds STA to filter list, passes frame up
++	 *  (3) hardware/firmware processes TX fifo and suppresses a frame
++	 *  (4) we get TX status before having processed the frame and
++	 *	knowing that the STA has gone to sleep.
++	 *
++	 * This is actually quite unlikely even when both those events are
++	 * processed from interrupts coming in quickly after one another or
++	 * even at the same time because we queue both TX status events and
++	 * RX frames to be processed by a tasklet and process them in the
++	 * same order that they were received or TX status last. Hence, there
++	 * is no race as long as the frame RX is processed before the next TX
++	 * status, which drivers can ensure, see below.
++	 *
++	 * Note that this can only happen if the hardware or firmware can
++	 * actually add STAs to the filter list, if this is done by the
++	 * driver in response to set_tim() (which will only reduce the race
++	 * this whole filtering tries to solve, not completely solve it)
++	 * this situation cannot happen.
++	 *
++	 * To completely solve this race drivers need to make sure that they
++	 *  (a) don't mix the irq-safe/not irq-safe TX status/RX processing
++	 *	functions and
++	 *  (b) always process RX events before TX status events if ordering
++	 *      can be unknown, for example with different interrupt status
++	 *	bits.
++	 */
++	if (sta->flags & WLAN_STA_PS &&
++	    skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
++		ieee80211_remove_tx_extra(local, sta->key, skb,
++					  &status->control);
++		skb_queue_tail(&sta->tx_filtered, skb);
++		return;
++	}
++
++	if (!(sta->flags & WLAN_STA_PS) &&
++	    !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
++		/* Software retry the packet once */
++		status->control.flags |= IEEE80211_TXCTL_REQUEUE;
++		ieee80211_remove_tx_extra(local, sta->key, skb,
++					  &status->control);
++		dev_queue_xmit(skb);
++		return;
++	}
++
++	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),
++		       !!(sta->flags & WLAN_STA_PS), jiffies);
++	dev_kfree_skb(skb);
++}
++
++void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
++			 struct ieee80211_tx_status *status)
++{
++	struct sk_buff *skb2;
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	struct ieee80211_local *local = hw_to_local(hw);
++	u16 frag, type;
++	struct ieee80211_tx_status_rtap_hdr *rthdr;
++	struct ieee80211_sub_if_data *sdata;
++	struct net_device *prev_dev = NULL;
++
++	if (!status) {
++		printk(KERN_ERR
++		       "%s: ieee80211_tx_status called with NULL status\n",
++		       wiphy_name(local->hw.wiphy));
++		dev_kfree_skb(skb);
++		return;
++	}
++
++	rcu_read_lock();
++
++	if (status->excessive_retries) {
++		struct sta_info *sta;
++		sta = sta_info_get(local, hdr->addr1);
++		if (sta) {
++			if (sta->flags & WLAN_STA_PS) {
++				/*
++				 * The STA is in power save mode, so assume
++				 * that this TX packet failed because of that.
++				 */
++				status->excessive_retries = 0;
++				status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
++				ieee80211_handle_filtered_frame(local, sta,
++								skb, status);
++				rcu_read_unlock();
++				return;
++			}
++		}
++	}
++
++	if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) {
++		struct sta_info *sta;
++		sta = sta_info_get(local, hdr->addr1);
++		if (sta) {
++			ieee80211_handle_filtered_frame(local, sta, skb,
++							status);
++			rcu_read_unlock();
++			return;
++		}
++	} else
++		rate_control_tx_status(local->mdev, skb, status);
++
++	rcu_read_unlock();
++
++	ieee80211_led_tx(local, 0);
++
++	/* SNMP counters
++	 * Fragments are passed to low-level drivers as separate skbs, so these
++	 * are actually fragments, not frames. Update frame counters only for
++	 * the first fragment of the frame. */
++
++	frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
++	type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
++
++	if (status->flags & IEEE80211_TX_STATUS_ACK) {
++		if (frag == 0) {
++			local->dot11TransmittedFrameCount++;
++			if (is_multicast_ether_addr(hdr->addr1))
++				local->dot11MulticastTransmittedFrameCount++;
++			if (status->retry_count > 0)
++				local->dot11RetryCount++;
++			if (status->retry_count > 1)
++				local->dot11MultipleRetryCount++;
++		}
++
++		/* This counter shall be incremented for an acknowledged MPDU
++		 * with an individual address in the address 1 field or an MPDU
++		 * with a multicast address in the address 1 field of type Data
++		 * or Management. */
++		if (!is_multicast_ether_addr(hdr->addr1) ||
++		    type == IEEE80211_FTYPE_DATA ||
++		    type == IEEE80211_FTYPE_MGMT)
++			local->dot11TransmittedFragmentCount++;
++	} else {
++		if (frag == 0)
++			local->dot11FailedCount++;
++	}
++
++	/* this was a transmitted frame, but now we want to reuse it */
++	skb_orphan(skb);
++
++	/*
++	 * This is a bit racy but we can avoid a lot of work
++	 * with this test...
++	 */
++	if (!local->monitors && !local->cooked_mntrs) {
++		dev_kfree_skb(skb);
++		return;
++	}
++
++	/* send frame to monitor interfaces now */
++
++	if (skb_headroom(skb) < sizeof(*rthdr)) {
++		printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
++		dev_kfree_skb(skb);
++		return;
++	}
++
++	rthdr = (struct ieee80211_tx_status_rtap_hdr*)
++				skb_push(skb, sizeof(*rthdr));
++
++	memset(rthdr, 0, sizeof(*rthdr));
++	rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
++	rthdr->hdr.it_present =
++		cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
++			    (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
++
++	if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&
++	    !is_multicast_ether_addr(hdr->addr1))
++		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
++
++	if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&
++	    (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))
++		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
++	else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)
++		rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
++
++	rthdr->data_retries = status->retry_count;
++
++	/* XXX: is this sufficient for BPF? */
++	skb_set_mac_header(skb, 0);
++	skb->ip_summed = CHECKSUM_UNNECESSARY;
++	skb->pkt_type = PACKET_OTHERHOST;
++	skb->protocol = htons(ETH_P_802_2);
++	memset(skb->cb, 0, sizeof(skb->cb));
++
++	rcu_read_lock();
++	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++		if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) {
++			if (!netif_running(sdata->dev))
++				continue;
++
++			if (prev_dev) {
++				skb2 = skb_clone(skb, GFP_ATOMIC);
++				if (skb2) {
++					skb2->dev = prev_dev;
++					netif_rx(skb2);
++				}
++			}
++
++			prev_dev = sdata->dev;
++		}
++	}
++	if (prev_dev) {
++		skb->dev = prev_dev;
++		netif_rx(skb);
++		skb = NULL;
++	}
++	rcu_read_unlock();
++	dev_kfree_skb(skb);
++}
++EXPORT_SYMBOL(ieee80211_tx_status);
++
++struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
++					const struct ieee80211_ops *ops)
++{
++	struct ieee80211_local *local;
++	int priv_size;
++	struct wiphy *wiphy;
++
++	/* Ensure 32-byte alignment of our private data and hw private data.
++	 * We use the wiphy priv data for both our ieee80211_local and for
++	 * the driver's private data
++	 *
++	 * In memory it'll be like this:
++	 *
++	 * +-------------------------+
++	 * | struct wiphy	    |
++	 * +-------------------------+
++	 * | struct ieee80211_local  |
++	 * +-------------------------+
++	 * | driver's private data   |
++	 * +-------------------------+
++	 *
++	 */
++	priv_size = ((sizeof(struct ieee80211_local) +
++		      NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
++		    priv_data_len;
++
++	wiphy = wiphy_new(&mac80211_config_ops, priv_size);
++
++	if (!wiphy)
++		return NULL;
++
++	wiphy->privid = mac80211_wiphy_privid;
++
++	local = wiphy_priv(wiphy);
++	local->hw.wiphy = wiphy;
++
++	local->hw.priv = (char *)local +
++			 ((sizeof(struct ieee80211_local) +
++			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
++
++	BUG_ON(!ops->tx);
++	BUG_ON(!ops->start);
++	BUG_ON(!ops->stop);
++	BUG_ON(!ops->config);
++	BUG_ON(!ops->add_interface);
++	BUG_ON(!ops->remove_interface);
++	BUG_ON(!ops->configure_filter);
++	local->ops = ops;
++
++	local->hw.queues = 1; /* default */
++
++	local->bridge_packets = 1;
++
++	local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
++	local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
++	local->short_retry_limit = 7;
++	local->long_retry_limit = 4;
++	local->hw.conf.radio_enabled = 1;
++
++	INIT_LIST_HEAD(&local->interfaces);
++
++	spin_lock_init(&local->key_lock);
++
++	INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
++
++	sta_info_init(local);
++
++	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
++		     (unsigned long)local);
++	tasklet_disable(&local->tx_pending_tasklet);
++
++	tasklet_init(&local->tasklet,
++		     ieee80211_tasklet_handler,
++		     (unsigned long) local);
++	tasklet_disable(&local->tasklet);
++
++	skb_queue_head_init(&local->skb_queue);
++	skb_queue_head_init(&local->skb_queue_unreliable);
++
++	return local_to_hw(local);
++}
++EXPORT_SYMBOL(ieee80211_alloc_hw);
++
++int ieee80211_register_hw(struct ieee80211_hw *hw)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	const char *name;
++	int result;
++	enum ieee80211_band band;
++	struct net_device *mdev;
++	struct ieee80211_sub_if_data *sdata;
++
++	/*
++	 * generic code guarantees at least one band,
++	 * set this very early because much code assumes
++	 * that hw.conf.channel is assigned
++	 */
++	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
++		struct ieee80211_supported_band *sband;
++
++		sband = local->hw.wiphy->bands[band];
++		if (sband) {
++			/* init channel we're on */
++			local->hw.conf.channel =
++			local->oper_channel =
++			local->scan_channel = &sband->channels[0];
++			break;
++		}
++	}
++
++	result = wiphy_register(local->hw.wiphy);
++	if (result < 0)
++		return result;
++
++	/* for now, mdev needs sub_if_data :/ */
++	mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
++			    "wmaster%d", ether_setup);
++	if (!mdev)
++		goto fail_mdev_alloc;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
++	mdev->ieee80211_ptr = &sdata->wdev;
++	sdata->wdev.wiphy = local->hw.wiphy;
++
++	local->mdev = mdev;
++
++	ieee80211_rx_bss_list_init(mdev);
++
++	mdev->hard_start_xmit = ieee80211_master_start_xmit;
++	mdev->open = ieee80211_master_open;
++	mdev->stop = ieee80211_master_stop;
++	mdev->type = ARPHRD_IEEE80211;
++	mdev->header_ops = &ieee80211_header_ops;
++	mdev->set_multicast_list = ieee80211_master_set_multicast_list;
++
++	sdata->vif.type = IEEE80211_IF_TYPE_AP;
++	sdata->dev = mdev;
++	sdata->local = local;
++	sdata->u.ap.force_unicast_rateidx = -1;
++	sdata->u.ap.max_ratectrl_rateidx = -1;
++	ieee80211_if_sdata_init(sdata);
++
++	/* no RCU needed since we're still during init phase */
++	list_add_tail(&sdata->list, &local->interfaces);
++
++	name = wiphy_dev(local->hw.wiphy)->driver->name;
++	local->hw.workqueue = create_singlethread_workqueue(name);
++	if (!local->hw.workqueue) {
++		result = -ENOMEM;
++		goto fail_workqueue;
++	}
++
++	/*
++	 * The hardware needs headroom for sending the frame,
++	 * and we need some headroom for passing the frame to monitor
++	 * interfaces, but never both at the same time.
++	 */
++	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
++				   sizeof(struct ieee80211_tx_status_rtap_hdr));
++
++	debugfs_hw_add(local);
++
++	local->hw.conf.beacon_int = 1000;
++
++	local->wstats_flags |= local->hw.max_rssi ?
++			       IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
++	local->wstats_flags |= local->hw.max_signal ?
++			       IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
++	local->wstats_flags |= local->hw.max_noise ?
++			       IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
++	if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
++		local->wstats_flags |= IW_QUAL_DBM;
++
++	result = sta_info_start(local);
++	if (result < 0)
++		goto fail_sta_info;
++
++	rtnl_lock();
++	result = dev_alloc_name(local->mdev, local->mdev->name);
++	if (result < 0)
++		goto fail_dev;
++
++	memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
++	SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
++
++	result = register_netdevice(local->mdev);
++	if (result < 0)
++		goto fail_dev;
++
++	ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
++	ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
++
++	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));
++		goto fail_rate;
++	}
++
++	result = ieee80211_wep_init(local);
++
++	if (result < 0) {
++		printk(KERN_DEBUG "%s: Failed to initialize wep\n",
++		       wiphy_name(local->hw.wiphy));
++		goto fail_wep;
++	}
++
++	ieee80211_install_qdisc(local->mdev);
++
++	/* add one default STA interface */
++	result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
++				  IEEE80211_IF_TYPE_STA, NULL);
++	if (result)
++		printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
++		       wiphy_name(local->hw.wiphy));
++
++	local->reg_state = IEEE80211_DEV_REGISTERED;
++	rtnl_unlock();
++
++	ieee80211_led_init(local);
++
++	return 0;
++
++fail_wep:
++	rate_control_deinitialize(local);
++fail_rate:
++	ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
++	unregister_netdevice(local->mdev);
++fail_dev:
++	rtnl_unlock();
++	sta_info_stop(local);
++fail_sta_info:
++	debugfs_hw_del(local);
++	destroy_workqueue(local->hw.workqueue);
++fail_workqueue:
++	ieee80211_if_free(local->mdev);
++	local->mdev = NULL;
++fail_mdev_alloc:
++	wiphy_unregister(local->hw.wiphy);
++	return result;
++}
++EXPORT_SYMBOL(ieee80211_register_hw);
++
++void ieee80211_unregister_hw(struct ieee80211_hw *hw)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct ieee80211_sub_if_data *sdata, *tmp;
++
++	tasklet_kill(&local->tx_pending_tasklet);
++	tasklet_kill(&local->tasklet);
++
++	rtnl_lock();
++
++	BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
++
++	local->reg_state = IEEE80211_DEV_UNREGISTERED;
++
++	/*
++	 * At this point, interface list manipulations are fine
++	 * because the driver cannot be handing us frames any
++	 * more and the tasklet is killed.
++	 */
++
++	/*
++	 * First, we remove all non-master interfaces. Do this because they
++	 * may have bss pointer dependency on the master, and when we free
++	 * the master these would be freed as well, breaking our list
++	 * iteration completely.
++	 */
++	list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
++		if (sdata->dev == local->mdev)
++			continue;
++		list_del(&sdata->list);
++		__ieee80211_if_del(local, sdata);
++	}
++
++	/* then, finally, remove the master interface */
++	__ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
++
++	rtnl_unlock();
++
++	ieee80211_rx_bss_list_deinit(local->mdev);
++	ieee80211_clear_tx_pending(local);
++	sta_info_stop(local);
++	rate_control_deinitialize(local);
++	debugfs_hw_del(local);
++
++	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));
++	skb_queue_purge(&local->skb_queue);
++	skb_queue_purge(&local->skb_queue_unreliable);
++
++	destroy_workqueue(local->hw.workqueue);
++	wiphy_unregister(local->hw.wiphy);
++	ieee80211_wep_free(local);
++	ieee80211_led_exit(local);
++	ieee80211_if_free(local->mdev);
++	local->mdev = NULL;
++}
++EXPORT_SYMBOL(ieee80211_unregister_hw);
++
++void ieee80211_free_hw(struct ieee80211_hw *hw)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++
++	wiphy_free(local->hw.wiphy);
++}
++EXPORT_SYMBOL(ieee80211_free_hw);
++
++static int __init ieee80211_init(void)
++{
++	struct sk_buff *skb;
++	int ret;
++
++	BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
++
++	ret = rc80211_pid_init();
++	if (ret)
++		goto out;
++
++	ret = ieee80211_wme_register();
++	if (ret) {
++		printk(KERN_DEBUG "ieee80211_init: failed to "
++		       "initialize WME (err=%d)\n", ret);
++		goto out_cleanup_pid;
++	}
++
++	ieee80211_debugfs_netdev_init();
++
++	return 0;
++
++ out_cleanup_pid:
++	rc80211_pid_exit();
++ out:
++	return ret;
++}
++
++static void __exit ieee80211_exit(void)
++{
++	rc80211_pid_exit();
++
++	/*
++	 * For key todo, it'll be empty by now but the work
++	 * might still be scheduled.
++	 */
++	flush_scheduled_work();
++
++	if (mesh_allocated)
++		ieee80211s_stop();
++
++	ieee80211_wme_unregister();
++	ieee80211_debugfs_netdev_exit();
++}
++
++
++subsys_initcall(ieee80211_init);
++module_exit(ieee80211_exit);
++
++MODULE_DESCRIPTION("IEEE 802.11 subsystem");
++MODULE_LICENSE("GPL");
+diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
+new file mode 100644
+index 0000000..594a335
+--- /dev/null
++++ b/net/mac80211/mesh.c
+@@ -0,0 +1,449 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Authors:    Luis Carlos Cobo <luisca at cozybit.com>
++ * 	       Javier Cardona <javier at cozybit.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 "ieee80211_i.h"
++#include "mesh.h"
++
++#define PP_OFFSET 	1		/* Path Selection Protocol */
++#define PM_OFFSET	5		/* Path Selection Metric   */
++#define CC_OFFSET	9		/* Congestion Control Mode */
++#define CAPAB_OFFSET 17
++#define ACCEPT_PLINKS 0x80
++
++int mesh_allocated;
++static struct kmem_cache *rm_cache;
++
++void ieee80211s_init(void)
++{
++	mesh_pathtbl_init();
++	mesh_allocated = 1;
++	rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry),
++				     0, 0, NULL);
++}
++
++void ieee80211s_stop(void)
++{
++	mesh_pathtbl_unregister();
++	kmem_cache_destroy(rm_cache);
++}
++
++/**
++ * mesh_matches_local - check if the config of a mesh point matches ours
++ *
++ * @ie: information elements of a management frame from the mesh peer
++ * @dev: local mesh interface
++ *
++ * This function checks if the mesh configuration of a mesh point matches the
++ * local mesh configuration, i.e. if both nodes belong to the same mesh network.
++ */
++bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *sta = &sdata->u.sta;
++
++	/*
++	 * As support for each feature is added, check for matching
++	 * - On mesh config capabilities
++	 *   - Power Save Support En
++	 *   - Sync support enabled
++	 *   - Sync support active
++	 *   - Sync support required from peer
++	 *   - MDA enabled
++	 * - Power management control on fc
++	 */
++	if (sta->mesh_id_len == ie->mesh_id_len &&
++		memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
++		memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 &&
++		memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 &&
++		memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0)
++		return true;
++
++	return false;
++}
++
++/**
++ * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links
++ *
++ * @ie: information elements of a management frame from the mesh peer
++ * @dev: local mesh interface
++ */
++bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie,
++			      struct net_device *dev)
++{
++	return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0;
++}
++
++/**
++ * mesh_accept_plinks_update: update accepting_plink in local mesh beacons
++ *
++ * @sdata: mesh interface in which mesh beacons are going to be updated
++ */
++void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
++{
++	bool free_plinks;
++
++	/* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0,
++	 * the mesh interface might be able to establish plinks with peers that
++	 * are already on the table but are not on PLINK_ESTAB state. However,
++	 * in general the mesh interface is not accepting peer link requests
++	 * from new peers, and that must be reflected in the beacon
++	 */
++	free_plinks = mesh_plink_availables(sdata);
++
++	if (free_plinks != sdata->u.sta.accepting_plinks)
++		ieee80211_sta_timer((unsigned long) sdata);
++}
++
++void mesh_ids_set_default(struct ieee80211_if_sta *sta)
++{
++	u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff};
++
++	memcpy(sta->mesh_pp_id, def_id, 4);
++	memcpy(sta->mesh_pm_id, def_id, 4);
++	memcpy(sta->mesh_cc_id, def_id, 4);
++}
++
++int mesh_rmc_init(struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	int i;
++
++	sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL);
++	if (!sdata->u.sta.rmc)
++		return -ENOMEM;
++	sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1;
++	for (i = 0; i < RMC_BUCKETS; i++)
++		INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list);
++	return 0;
++}
++
++void mesh_rmc_free(struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct mesh_rmc *rmc = sdata->u.sta.rmc;
++	struct rmc_entry *p, *n;
++	int i;
++
++	if (!sdata->u.sta.rmc)
++		return;
++
++	for (i = 0; i < RMC_BUCKETS; i++)
++		list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) {
++			list_del(&p->list);
++			kmem_cache_free(rm_cache, p);
++		}
++
++	kfree(rmc);
++	sdata->u.sta.rmc = NULL;
++}
++
++/**
++ * mesh_rmc_check - Check frame in recent multicast cache and add if absent.
++ *
++ * @sa:		source address
++ * @mesh_hdr:	mesh_header
++ *
++ * Returns: 0 if the frame is not in the cache, nonzero otherwise.
++ *
++ * Checks using the source address and the mesh sequence number if we have
++ * received this frame lately. If the frame is not in the cache, it is added to
++ * it.
++ */
++int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
++		   struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct mesh_rmc *rmc = sdata->u.sta.rmc;
++	u32 seqnum = 0;
++	int entries = 0;
++	u8 idx;
++	struct rmc_entry *p, *n;
++
++	/* Don't care about endianness since only match matters */
++	memcpy(&seqnum, mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
++	idx = mesh_hdr->seqnum[0] & rmc->idx_mask;
++	list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) {
++		++entries;
++		if (time_after(jiffies, p->exp_time) ||
++				(entries == RMC_QUEUE_MAX_LEN)) {
++			list_del(&p->list);
++			kmem_cache_free(rm_cache, p);
++			--entries;
++		} else if ((seqnum == p->seqnum)
++				&& (memcmp(sa, p->sa, ETH_ALEN) == 0))
++			return -1;
++	}
++
++	p = kmem_cache_alloc(rm_cache, GFP_ATOMIC);
++	if (!p) {
++		printk(KERN_DEBUG "o11s: could not allocate RMC entry\n");
++		return 0;
++	}
++	p->seqnum = seqnum;
++	p->exp_time = jiffies + RMC_TIMEOUT;
++	memcpy(p->sa, sa, ETH_ALEN);
++	list_add(&p->list, &rmc->bucket[idx].list);
++	return 0;
++}
++
++void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_supported_band *sband;
++	u8 *pos;
++	int len, i, rate;
++
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++	len = sband->n_bitrates;
++	if (len > 8)
++		len = 8;
++	pos = skb_put(skb, len + 2);
++	*pos++ = WLAN_EID_SUPP_RATES;
++	*pos++ = len;
++	for (i = 0; i < len; i++) {
++		rate = sband->bitrates[i].bitrate;
++		*pos++ = (u8) (rate / 5);
++	}
++
++	if (sband->n_bitrates > len) {
++		pos = skb_put(skb, sband->n_bitrates - len + 2);
++		*pos++ = WLAN_EID_EXT_SUPP_RATES;
++		*pos++ = sband->n_bitrates - len;
++		for (i = len; i < sband->n_bitrates; i++) {
++			rate = sband->bitrates[i].bitrate;
++			*pos++ = (u8) (rate / 5);
++		}
++	}
++
++	pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len);
++	*pos++ = WLAN_EID_MESH_ID;
++	*pos++ = sdata->u.sta.mesh_id_len;
++	if (sdata->u.sta.mesh_id_len)
++		memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len);
++
++	pos = skb_put(skb, 21);
++	*pos++ = WLAN_EID_MESH_CONFIG;
++	*pos++ = MESH_CFG_LEN;
++	/* Version */
++	*pos++ = 1;
++
++	/* Active path selection protocol ID */
++	memcpy(pos, sdata->u.sta.mesh_pp_id, 4);
++	pos += 4;
++
++	/* Active path selection metric ID   */
++	memcpy(pos, sdata->u.sta.mesh_pm_id, 4);
++	pos += 4;
++
++	/* Congestion control mode identifier */
++	memcpy(pos, sdata->u.sta.mesh_cc_id, 4);
++	pos += 4;
++
++	/* Channel precedence:
++	 * Not running simple channel unification protocol
++	 */
++	memset(pos, 0x00, 4);
++	pos += 4;
++
++	/* Mesh capability */
++	sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata);
++	*pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00;
++	*pos++ = 0x00;
++
++	return;
++}
++
++u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl)
++{
++	/* Use last four bytes of hw addr and interface index as hash index */
++	return jhash_2words(*(u32 *)(addr+2), dev->ifindex, tbl->hash_rnd)
++		& tbl->hash_mask;
++}
++
++u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len)
++{
++	if (!mesh_id_len)
++		return 1;
++	else if (mesh_id_len == 1)
++		return (u8) mesh_id[0];
++	else
++		return (u8) (mesh_id[0] + 2 * mesh_id[1]);
++}
++
++struct mesh_table *mesh_table_alloc(int size_order)
++{
++	int i;
++	struct mesh_table *newtbl;
++
++	newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL);
++	if (!newtbl)
++		return NULL;
++
++	newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) *
++			(1 << size_order), GFP_KERNEL);
++
++	if (!newtbl->hash_buckets) {
++		kfree(newtbl);
++		return NULL;
++	}
++
++	newtbl->hashwlock = kmalloc(sizeof(spinlock_t) *
++			(1 << size_order), GFP_KERNEL);
++	if (!newtbl->hashwlock) {
++		kfree(newtbl->hash_buckets);
++		kfree(newtbl);
++		return NULL;
++	}
++
++	newtbl->size_order = size_order;
++	newtbl->hash_mask = (1 << size_order) - 1;
++	atomic_set(&newtbl->entries,  0);
++	get_random_bytes(&newtbl->hash_rnd,
++			sizeof(newtbl->hash_rnd));
++	for (i = 0; i <= newtbl->hash_mask; i++)
++		spin_lock_init(&newtbl->hashwlock[i]);
++
++	return newtbl;
++}
++
++void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
++{
++	struct hlist_head *mesh_hash;
++	struct hlist_node *p, *q;
++	int i;
++
++	mesh_hash = tbl->hash_buckets;
++	for (i = 0; i <= tbl->hash_mask; i++) {
++		spin_lock(&tbl->hashwlock[i]);
++		hlist_for_each_safe(p, q, &mesh_hash[i]) {
++			tbl->free_node(p, free_leafs);
++			atomic_dec(&tbl->entries);
++		}
++		spin_unlock(&tbl->hashwlock[i]);
++	}
++	kfree(tbl->hash_buckets);
++	kfree(tbl->hashwlock);
++	kfree(tbl);
++}
++
++static void ieee80211_mesh_path_timer(unsigned long data)
++{
++	struct ieee80211_sub_if_data *sdata =
++		(struct ieee80211_sub_if_data *) data;
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	struct ieee80211_local *local = wdev_priv(&sdata->wdev);
++
++	queue_work(local->hw.workqueue, &ifsta->work);
++}
++
++struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
++{
++	struct mesh_table *newtbl;
++	struct hlist_head *oldhash;
++	struct hlist_node *p;
++	int err = 0;
++	int i;
++
++	if (atomic_read(&tbl->entries)
++			< tbl->mean_chain_len * (tbl->hash_mask + 1)) {
++		err = -EPERM;
++		goto endgrow;
++	}
++
++	newtbl = mesh_table_alloc(tbl->size_order + 1);
++	if (!newtbl) {
++		err = -ENOMEM;
++		goto endgrow;
++	}
++
++	newtbl->free_node = tbl->free_node;
++	newtbl->mean_chain_len = tbl->mean_chain_len;
++	newtbl->copy_node = tbl->copy_node;
++	atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
++
++	oldhash = tbl->hash_buckets;
++	for (i = 0; i <= tbl->hash_mask; i++)
++		hlist_for_each(p, &oldhash[i])
++			tbl->copy_node(p, newtbl);
++
++endgrow:
++	if (err)
++		return NULL;
++	else
++		return newtbl;
++}
++
++/**
++ * ieee80211_new_mesh_header - create a new mesh header
++ * @meshhdr:    uninitialized mesh header
++ * @sdata:	mesh interface to be used
++ *
++ * Return the header length.
++ */
++int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
++		struct ieee80211_sub_if_data *sdata)
++{
++	meshhdr->flags = 0;
++	meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL;
++
++	meshhdr->seqnum[0] = sdata->u.sta.mesh_seqnum[0]++;
++	meshhdr->seqnum[1] = sdata->u.sta.mesh_seqnum[1];
++	meshhdr->seqnum[2] = sdata->u.sta.mesh_seqnum[2];
++
++	if (sdata->u.sta.mesh_seqnum[0] == 0) {
++		sdata->u.sta.mesh_seqnum[1]++;
++		if (sdata->u.sta.mesh_seqnum[1] == 0)
++			sdata->u.sta.mesh_seqnum[2]++;
++	}
++
++	return 5;
++}
++
++void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
++{
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++
++	ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
++	ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
++	ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T;
++	ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR;
++	ifsta->mshcfg.dot11MeshTTL = MESH_TTL;
++	ifsta->mshcfg.auto_open_plinks = true;
++	ifsta->mshcfg.dot11MeshMaxPeerLinks =
++		MESH_MAX_ESTAB_PLINKS;
++	ifsta->mshcfg.dot11MeshHWMPactivePathTimeout =
++		MESH_PATH_TIMEOUT;
++	ifsta->mshcfg.dot11MeshHWMPpreqMinInterval =
++		MESH_PREQ_MIN_INT;
++	ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime =
++		MESH_DIAM_TRAVERSAL_TIME;
++	ifsta->mshcfg.dot11MeshHWMPmaxPREQretries =
++		MESH_MAX_PREQ_RETRIES;
++	ifsta->mshcfg.path_refresh_time =
++		MESH_PATH_REFRESH_TIME;
++	ifsta->mshcfg.min_discovery_timeout =
++		MESH_MIN_DISCOVERY_TIMEOUT;
++	ifsta->accepting_plinks = true;
++	ifsta->preq_id = 0;
++	ifsta->dsn = 0;
++	atomic_set(&ifsta->mpaths, 0);
++	mesh_rmc_init(sdata->dev);
++	ifsta->last_preq = jiffies;
++	/* Allocate all mesh structures when creating the first mesh interface. */
++	if (!mesh_allocated)
++		ieee80211s_init();
++	mesh_ids_set_default(ifsta);
++	setup_timer(&ifsta->mesh_path_timer,
++		    ieee80211_mesh_path_timer,
++		    (unsigned long) sdata);
++	INIT_LIST_HEAD(&ifsta->preq_queue.list);
++	spin_lock_init(&ifsta->mesh_preq_queue_lock);
++}
+diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
+new file mode 100644
+index 0000000..742003d
+--- /dev/null
++++ b/net/mac80211/mesh.h
+@@ -0,0 +1,290 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Authors:    Luis Carlos Cobo <luisca at cozybit.com>
++ *             Javier Cardona <javier at cozybit.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 IEEE80211S_H
++#define IEEE80211S_H
++
++#include <linux/types.h>
++#include <linux/jhash.h>
++#include "ieee80211_i.h"
++
++
++/* Data structures */
++
++/**
++ * enum mesh_path_flags - mac80211 mesh path flags
++ *
++ *
++ *
++ * @MESH_PATH_ACTIVE: the mesh path is can be used for forwarding
++ * @MESH_PATH_RESOLVED: the discovery process is running for this mesh path
++ * @MESH_PATH_DSN_VALID: the mesh path contains a valid destination sequence
++ * 	number
++ * @MESH_PATH_FIXED: the mesh path has been manually set and should not be
++ * 	modified
++ * @MESH_PATH_RESOLVED: the mesh path can has been resolved
++ *
++ * MESH_PATH_RESOLVED and MESH_PATH_DELETE are used by the mesh path timer to
++ * decide when to stop or cancel the mesh path discovery.
++ */
++enum mesh_path_flags {
++	MESH_PATH_ACTIVE =	BIT(0),
++	MESH_PATH_RESOLVING =	BIT(1),
++	MESH_PATH_DSN_VALID =	BIT(2),
++	MESH_PATH_FIXED	=	BIT(3),
++	MESH_PATH_RESOLVED =	BIT(4),
++};
++
++/**
++ * struct mesh_path - mac80211 mesh path structure
++ *
++ * @dst: mesh path destination mac address
++ * @dev: mesh path device
++ * @next_hop: mesh neighbor to which frames for this destination will be
++ * 	forwarded
++ * @timer: mesh path discovery timer
++ * @frame_queue: pending queue for frames sent to this destination while the
++ * 	path is unresolved
++ * @dsn: destination sequence number of the destination
++ * @metric: current metric to this destination
++ * @hop_count: hops to destination
++ * @exp_time: in jiffies, when the path will expire or when it expired
++ * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery
++ * 	retry
++ * @discovery_retries: number of discovery retries
++ * @flags: mesh path flags, as specified on &enum mesh_path_flags
++ * @state_lock: mesh pat state lock
++ *
++ *
++ * The combination of dst and dev is unique in the mesh path table. Since the
++ * next_hop STA is only protected by RCU as well, deleting the STA must also
++ * remove/substitute the mesh_path structure and wait until that is no longer
++ * reachable before destroying the STA completely.
++ */
++struct mesh_path {
++	u8 dst[ETH_ALEN];
++	struct net_device *dev;
++	struct sta_info *next_hop;
++	struct timer_list timer;
++	struct sk_buff_head frame_queue;
++	struct rcu_head rcu;
++	u32 dsn;
++	u32 metric;
++	u8 hop_count;
++	unsigned long exp_time;
++	u32 discovery_timeout;
++	u8 discovery_retries;
++	enum mesh_path_flags flags;
++	spinlock_t state_lock;
++};
++
++/**
++ * struct mesh_table
++ *
++ * @hash_buckets: array of hash buckets of the table
++ * @hashwlock: array of locks to protect write operations, one per bucket
++ * @hash_mask: 2^size_order - 1, used to compute hash idx
++ * @hash_rnd: random value used for hash computations
++ * @entries: number of entries in the table
++ * @free_node: function to free nodes of the table
++ * @copy_node: fuction to copy nodes of the table
++ * @size_order: determines size of the table, there will be 2^size_order hash
++ *	buckets
++ * @mean_chain_len: maximum average length for the hash buckets' list, if it is
++ *	reached, the table will grow
++ */
++struct mesh_table {
++	/* Number of buckets will be 2^N */
++	struct hlist_head *hash_buckets;
++	spinlock_t *hashwlock;		/* One per bucket, for add/del */
++	unsigned int hash_mask;		/* (2^size_order) - 1 */
++	__u32 hash_rnd;			/* Used for hash generation */
++	atomic_t entries;		/* Up to MAX_MESH_NEIGHBOURS */
++	void (*free_node) (struct hlist_node *p, bool free_leafs);
++	void (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl);
++	int size_order;
++	int mean_chain_len;
++};
++
++/* Recent multicast cache */
++/* RMC_BUCKETS must be a power of 2, maximum 256 */
++#define RMC_BUCKETS		256
++#define RMC_QUEUE_MAX_LEN	4
++#define RMC_TIMEOUT		(3 * HZ)
++
++/**
++ * struct rmc_entry - entry in the Recent Multicast Cache
++ *
++ * @seqnum: mesh sequence number of the frame
++ * @exp_time: expiration time of the entry, in jiffies
++ * @sa: source address of the frame
++ *
++ * The Recent Multicast Cache keeps track of the latest multicast frames that
++ * have been received by a mesh interface and discards received multicast frames
++ * that are found in the cache.
++ */
++struct rmc_entry {
++	struct list_head list;
++	u32 seqnum;
++	unsigned long exp_time;
++	u8 sa[ETH_ALEN];
++};
++
++struct mesh_rmc {
++	struct rmc_entry bucket[RMC_BUCKETS];
++	u8 idx_mask;
++};
++
++
++/* Mesh IEs constants */
++#define MESH_CFG_LEN		19
++
++/*
++ * MESH_CFG_COMP_LEN Includes:
++ * 	- Active path selection protocol ID.
++ * 	- Active path selection metric ID.
++ * 	- Congestion control mode identifier.
++ * 	- Channel precedence.
++ * Does not include mesh capabilities, which may vary across nodes in the same
++ * mesh
++ */
++#define MESH_CFG_CMP_LEN 	17
++
++/* Default values, timeouts in ms */
++#define MESH_TTL 		5
++#define MESH_MAX_RETR	 	3
++#define MESH_RET_T 		100
++#define MESH_CONF_T 		100
++#define MESH_HOLD_T 		100
++
++#define MESH_PATH_TIMEOUT	5000
++/* Minimum interval between two consecutive PREQs originated by the same
++ * interface
++ */
++#define MESH_PREQ_MIN_INT	10
++#define MESH_DIAM_TRAVERSAL_TIME 50
++/* Paths will be refreshed if they are closer than PATH_REFRESH_TIME to their
++ * expiration
++ */
++#define MESH_PATH_REFRESH_TIME			1000
++#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
++
++#define MESH_MAX_PREQ_RETRIES 4
++#define MESH_PATH_EXPIRE (600 * HZ)
++
++/* Default maximum number of established plinks per interface */
++#define MESH_MAX_ESTAB_PLINKS	32
++
++/* Default maximum number of plinks per interface */
++#define MESH_MAX_PLINKS		256
++
++/* Maximum number of paths per interface */
++#define MESH_MAX_MPATHS		1024
++
++/* Pending ANA approval */
++#define PLINK_CATEGORY		30
++#define MESH_PATH_SEL_CATEGORY	32
++
++/* Mesh Header Flags */
++#define IEEE80211S_FLAGS_AE	0x3
++
++/* Public interfaces */
++/* Various */
++u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len);
++int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
++int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
++		struct ieee80211_sub_if_data *sdata);
++int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
++		struct net_device *dev);
++bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev);
++void mesh_ids_set_default(struct ieee80211_if_sta *sta);
++void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev);
++void mesh_rmc_free(struct net_device *dev);
++int mesh_rmc_init(struct net_device *dev);
++void ieee80211s_init(void);
++void ieee80211s_stop(void);
++void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
++
++/* Mesh paths */
++int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb,
++		struct net_device *dev);
++void mesh_path_start_discovery(struct net_device *dev);
++struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev);
++struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev);
++void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
++void mesh_path_expire(struct net_device *dev);
++void mesh_path_flush(struct net_device *dev);
++void mesh_rx_path_sel_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
++		size_t len);
++int mesh_path_add(u8 *dst, struct net_device *dev);
++/* Mesh plinks */
++void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev,
++		bool add);
++bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie,
++			      struct net_device *dev);
++void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
++void mesh_plink_broken(struct sta_info *sta);
++void mesh_plink_deactivate(struct sta_info *sta);
++int mesh_plink_open(struct sta_info *sta);
++int mesh_plink_close(struct sta_info *sta);
++void mesh_plink_block(struct sta_info *sta);
++void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
++			 size_t len, struct ieee80211_rx_status *rx_status);
++
++/* Private interfaces */
++/* Mesh tables */
++struct mesh_table *mesh_table_alloc(int size_order);
++void mesh_table_free(struct mesh_table *tbl, bool free_leafs);
++struct mesh_table *mesh_table_grow(struct mesh_table *tbl);
++u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl);
++/* Mesh paths */
++int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra,
++		struct net_device *dev);
++void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta);
++void mesh_path_flush_pending(struct mesh_path *mpath);
++void mesh_path_tx_pending(struct mesh_path *mpath);
++int mesh_pathtbl_init(void);
++void mesh_pathtbl_unregister(void);
++int mesh_path_del(u8 *addr, struct net_device *dev);
++void mesh_path_timer(unsigned long data);
++void mesh_path_flush_by_nexthop(struct sta_info *sta);
++void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev);
++
++#ifdef CONFIG_MAC80211_MESH
++extern int mesh_allocated;
++
++static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata)
++{
++	return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks -
++	       atomic_read(&sdata->u.sta.mshstats.estab_plinks);
++}
++
++static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata)
++{
++	return (min_t(long, mesh_plink_free_count(sdata),
++		   MESH_MAX_PLINKS - sdata->local->num_sta)) > 0;
++}
++
++static inline void mesh_path_activate(struct mesh_path *mpath)
++{
++	mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED;
++}
++
++#define for_each_mesh_entry(x, p, node, i) \
++	for (i = 0; i <= x->hash_mask; i++) \
++		hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list)
++
++#else
++#define mesh_allocated	0
++#endif
++
++#define MESH_PREQ(skb)	(skb->cb + 30)
++
++#endif /* IEEE80211S_H */
+diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
+new file mode 100644
+index 0000000..02de8f1
+--- /dev/null
++++ b/net/mac80211/mesh_hwmp.c
+@@ -0,0 +1,855 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Author:     Luis Carlos Cobo <luisca at cozybit.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <asm/unaligned.h>
++#include "mesh.h"
++
++#define TEST_FRAME_LEN	8192
++#define MAX_METRIC	0xffffffff
++#define ARITH_SHIFT	8
++
++/* Number of frames buffered per destination for unresolved destinations */
++#define MESH_FRAME_QUEUE_LEN	10
++#define MAX_PREQ_QUEUE_LEN	64
++
++/* Destination only */
++#define MP_F_DO	0x1
++/* Reply and forward */
++#define MP_F_RF	0x2
++
++static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
++{
++	if (ae)
++		offset += 6;
++	return le32_to_cpu(get_unaligned((__le32 *) (preq_elem + offset)));
++}
++
++/* HWMP IE processing macros */
++#define AE_F			(1<<6)
++#define AE_F_SET(x)		(*x & AE_F)
++#define PREQ_IE_FLAGS(x)	(*(x))
++#define PREQ_IE_HOPCOUNT(x)	(*(x + 1))
++#define PREQ_IE_TTL(x)		(*(x + 2))
++#define PREQ_IE_PREQ_ID(x)	u32_field_get(x, 3, 0)
++#define PREQ_IE_ORIG_ADDR(x)	(x + 7)
++#define PREQ_IE_ORIG_DSN(x)	u32_field_get(x, 13, 0);
++#define PREQ_IE_LIFETIME(x)	u32_field_get(x, 17, AE_F_SET(x));
++#define PREQ_IE_METRIC(x) 	u32_field_get(x, 21, AE_F_SET(x));
++#define PREQ_IE_DST_F(x)	(*(AE_F_SET(x) ? x + 32 : x + 26))
++#define PREQ_IE_DST_ADDR(x) 	(AE_F_SET(x) ? x + 33 : x + 27)
++#define PREQ_IE_DST_DSN(x) 	u32_field_get(x, 33, AE_F_SET(x));
++
++
++#define PREP_IE_FLAGS(x)	PREQ_IE_FLAGS(x)
++#define PREP_IE_HOPCOUNT(x)	PREQ_IE_HOPCOUNT(x)
++#define PREP_IE_TTL(x)		PREQ_IE_TTL(x)
++#define PREP_IE_ORIG_ADDR(x)	(x + 3)
++#define PREP_IE_ORIG_DSN(x)	u32_field_get(x, 9, 0);
++#define PREP_IE_LIFETIME(x)	u32_field_get(x, 13, AE_F_SET(x));
++#define PREP_IE_METRIC(x)	u32_field_get(x, 17, AE_F_SET(x));
++#define PREP_IE_DST_ADDR(x)	(AE_F_SET(x) ? x + 27 : x + 21)
++#define PREP_IE_DST_DSN(x)	u32_field_get(x, 27, AE_F_SET(x));
++
++#define PERR_IE_DST_ADDR(x)	(x + 2)
++#define PERR_IE_DST_DSN(x)	u32_field_get(x, 8, 0);
++
++#define TU_TO_EXP_TIME(x) (jiffies + msecs_to_jiffies(x * 1024 / 1000))
++#define MSEC_TO_TU(x) (x*1000/1024)
++#define DSN_GT(x, y) ((long) (y) - (long) (x) < 0)
++#define DSN_LT(x, y) ((long) (x) - (long) (y) < 0)
++
++#define net_traversal_jiffies(s) \
++	msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
++#define default_lifetime(s) \
++	MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout)
++#define min_preq_int_jiff(s) \
++	(msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval))
++#define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries)
++#define disc_timeout_jiff(s) \
++	msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout)
++
++enum mpath_frame_type {
++	MPATH_PREQ = 0,
++	MPATH_PREP,
++	MPATH_PERR
++};
++
++static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
++		u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst,
++		__le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime,
++		__le32 metric, __le32 preq_id, struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
++	struct ieee80211_mgmt *mgmt;
++	u8 *pos;
++	int ie_len;
++
++	if (!skb)
++		return -1;
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++	/* 25 is the size of the common mgmt part (24) plus the size of the
++	 * common action part (1)
++	 */
++	mgmt = (struct ieee80211_mgmt *)
++		skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
++	memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					   IEEE80211_STYPE_ACTION);
++
++	memcpy(mgmt->da, da, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	/* BSSID is left zeroed, wildcard value */
++	mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
++	mgmt->u.action.u.mesh_action.action_code = action;
++
++	switch (action) {
++	case MPATH_PREQ:
++		ie_len = 37;
++		pos = skb_put(skb, 2 + ie_len);
++		*pos++ = WLAN_EID_PREQ;
++		break;
++	case MPATH_PREP:
++		ie_len = 31;
++		pos = skb_put(skb, 2 + ie_len);
++		*pos++ = WLAN_EID_PREP;
++		break;
++	default:
++		kfree(skb);
++		return -ENOTSUPP;
++		break;
++	}
++	*pos++ = ie_len;
++	*pos++ = flags;
++	*pos++ = hop_count;
++	*pos++ = ttl;
++	if (action == MPATH_PREQ) {
++		memcpy(pos, &preq_id, 4);
++		pos += 4;
++	}
++	memcpy(pos, orig_addr, ETH_ALEN);
++	pos += ETH_ALEN;
++	memcpy(pos, &orig_dsn, 4);
++	pos += 4;
++	memcpy(pos, &lifetime, 4);
++	pos += 4;
++	memcpy(pos, &metric, 4);
++	pos += 4;
++	if (action == MPATH_PREQ) {
++		/* destination count */
++		*pos++ = 1;
++		*pos++ = dst_flags;
++	}
++	memcpy(pos, dst, ETH_ALEN);
++	pos += ETH_ALEN;
++	memcpy(pos, &dst_dsn, 4);
++
++	ieee80211_sta_tx(dev, skb, 0);
++	return 0;
++}
++
++/**
++ * mesh_send_path error - Sends a PERR mesh management frame
++ *
++ * @dst: broken destination
++ * @dst_dsn: dsn of the broken destination
++ * @ra: node this frame is addressed to
++ */
++int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
++		struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
++	struct ieee80211_mgmt *mgmt;
++	u8 *pos;
++	int ie_len;
++
++	if (!skb)
++		return -1;
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++	/* 25 is the size of the common mgmt part (24) plus the size of the
++	 * common action part (1)
++	 */
++	mgmt = (struct ieee80211_mgmt *)
++		skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
++	memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					   IEEE80211_STYPE_ACTION);
++
++	memcpy(mgmt->da, ra, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	/* BSSID is left zeroed, wildcard value */
++	mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
++	mgmt->u.action.u.mesh_action.action_code = MPATH_PERR;
++	ie_len = 12;
++	pos = skb_put(skb, 2 + ie_len);
++	*pos++ = WLAN_EID_PERR;
++	*pos++ = ie_len;
++	/* mode flags, reserved */
++	*pos++ = 0;
++	/* number of destinations */
++	*pos++ = 1;
++	memcpy(pos, dst, ETH_ALEN);
++	pos += ETH_ALEN;
++	memcpy(pos, &dst_dsn, 4);
++
++	ieee80211_sta_tx(dev, skb, 0);
++	return 0;
++}
++
++static u32 airtime_link_metric_get(struct ieee80211_local *local,
++				   struct sta_info *sta)
++{
++	struct ieee80211_supported_band *sband;
++	/* This should be adjusted for each device */
++	int device_constant = 1 << ARITH_SHIFT;
++	int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
++	int s_unit = 1 << ARITH_SHIFT;
++	int rate, err;
++	u32 tx_time, estimated_retx;
++	u64 result;
++
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++	if (sta->fail_avg >= 100)
++		return MAX_METRIC;
++	err = (sta->fail_avg << ARITH_SHIFT) / 100;
++
++	/* bitrate is in units of 100 Kbps, while we need rate in units of
++	 * 1Mbps. This will be corrected on tx_time computation.
++	 */
++	rate = sband->bitrates[sta->txrate_idx].bitrate;
++	tx_time = (device_constant + 10 * test_frame_len / rate);
++	estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
++	result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
++	return (u32)result;
++}
++
++/**
++ * hwmp_route_info_get - Update routing info to originator and transmitter
++ *
++ * @dev: local mesh interface
++ * @mgmt: mesh management frame
++ * @hwmp_ie: hwmp information element (PREP or PREQ)
++ *
++ * This function updates the path routing information to the originator and the
++ * transmitter of a HWMP PREQ or PREP fram.
++ *
++ * Returns: metric to frame originator or 0 if the frame should not be further
++ * processed
++ *
++ * Notes: this function is the only place (besides user-provided info) where
++ * path routing information is updated.
++ */
++static u32 hwmp_route_info_get(struct net_device *dev,
++			    struct ieee80211_mgmt *mgmt,
++			    u8 *hwmp_ie)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct mesh_path *mpath;
++	struct sta_info *sta;
++	bool fresh_info;
++	u8 *orig_addr, *ta;
++	u32 orig_dsn, orig_metric;
++	unsigned long orig_lifetime, exp_time;
++	u32 last_hop_metric, new_metric;
++	bool process = true;
++	u8 action = mgmt->u.action.u.mesh_action.action_code;
++
++	rcu_read_lock();
++	sta = sta_info_get(local, mgmt->sa);
++	if (!sta) {
++		rcu_read_unlock();
++		return 0;
++	}
++
++	last_hop_metric = airtime_link_metric_get(local, sta);
++	/* Update and check originator routing info */
++	fresh_info = true;
++
++	switch (action) {
++	case MPATH_PREQ:
++		orig_addr = PREQ_IE_ORIG_ADDR(hwmp_ie);
++		orig_dsn = PREQ_IE_ORIG_DSN(hwmp_ie);
++		orig_lifetime = PREQ_IE_LIFETIME(hwmp_ie);
++		orig_metric = PREQ_IE_METRIC(hwmp_ie);
++		break;
++	case MPATH_PREP:
++		/* Originator here refers to the MP that was the destination in
++		 * the Path Request. The draft refers to that MP as the
++		 * destination address, even though usually it is the origin of
++		 * the PREP frame. We divert from the nomenclature in the draft
++		 * so that we can easily use a single function to gather path
++		 * information from both PREQ and PREP frames.
++		 */
++		orig_addr = PREP_IE_ORIG_ADDR(hwmp_ie);
++		orig_dsn = PREP_IE_ORIG_DSN(hwmp_ie);
++		orig_lifetime = PREP_IE_LIFETIME(hwmp_ie);
++		orig_metric = PREP_IE_METRIC(hwmp_ie);
++		break;
++	default:
++		rcu_read_unlock();
++		return 0;
++	}
++	new_metric = orig_metric + last_hop_metric;
++	if (new_metric < orig_metric)
++		new_metric = MAX_METRIC;
++	exp_time = TU_TO_EXP_TIME(orig_lifetime);
++
++	if (memcmp(orig_addr, dev->dev_addr, ETH_ALEN) == 0) {
++		/* This MP is the originator, we are not interested in this
++		 * frame, except for updating transmitter's path info.
++		 */
++		process = false;
++		fresh_info = false;
++	} else {
++		mpath = mesh_path_lookup(orig_addr, dev);
++		if (mpath) {
++			spin_lock_bh(&mpath->state_lock);
++			if (mpath->flags & MESH_PATH_FIXED)
++				fresh_info = false;
++			else if ((mpath->flags & MESH_PATH_ACTIVE) &&
++			    (mpath->flags & MESH_PATH_DSN_VALID)) {
++				if (DSN_GT(mpath->dsn, orig_dsn) ||
++				    (mpath->dsn == orig_dsn &&
++				     action == MPATH_PREQ &&
++				     new_metric > mpath->metric)) {
++					process = false;
++					fresh_info = false;
++				}
++			}
++		} else {
++			mesh_path_add(orig_addr, dev);
++			mpath = mesh_path_lookup(orig_addr, dev);
++			if (!mpath) {
++				rcu_read_unlock();
++				return 0;
++			}
++			spin_lock_bh(&mpath->state_lock);
++		}
++
++		if (fresh_info) {
++			mesh_path_assign_nexthop(mpath, sta);
++			mpath->flags |= MESH_PATH_DSN_VALID;
++			mpath->metric = new_metric;
++			mpath->dsn = orig_dsn;
++			mpath->exp_time = time_after(mpath->exp_time, exp_time)
++					  ?  mpath->exp_time : exp_time;
++			mesh_path_activate(mpath);
++			spin_unlock_bh(&mpath->state_lock);
++			mesh_path_tx_pending(mpath);
++			/* draft says preq_id should be saved to, but there does
++			 * not seem to be any use for it, skipping by now
++			 */
++		} else
++			spin_unlock_bh(&mpath->state_lock);
++	}
++
++	/* Update and check transmitter routing info */
++	ta = mgmt->sa;
++	if (memcmp(orig_addr, ta, ETH_ALEN) == 0)
++		fresh_info = false;
++	else {
++		fresh_info = true;
++
++		mpath = mesh_path_lookup(ta, dev);
++		if (mpath) {
++			spin_lock_bh(&mpath->state_lock);
++			if ((mpath->flags & MESH_PATH_FIXED) ||
++				((mpath->flags & MESH_PATH_ACTIVE) &&
++					(last_hop_metric > mpath->metric)))
++				fresh_info = false;
++		} else {
++			mesh_path_add(ta, dev);
++			mpath = mesh_path_lookup(ta, dev);
++			if (!mpath) {
++				rcu_read_unlock();
++				return 0;
++			}
++			spin_lock_bh(&mpath->state_lock);
++		}
++
++		if (fresh_info) {
++			mesh_path_assign_nexthop(mpath, sta);
++			mpath->flags &= ~MESH_PATH_DSN_VALID;
++			mpath->metric = last_hop_metric;
++			mpath->exp_time = time_after(mpath->exp_time, exp_time)
++					  ?  mpath->exp_time : exp_time;
++			mesh_path_activate(mpath);
++			spin_unlock_bh(&mpath->state_lock);
++			mesh_path_tx_pending(mpath);
++		} else
++			spin_unlock_bh(&mpath->state_lock);
++	}
++
++	rcu_read_unlock();
++
++	return process ? new_metric : 0;
++}
++
++static void hwmp_preq_frame_process(struct net_device *dev,
++				    struct ieee80211_mgmt *mgmt,
++				    u8 *preq_elem, u32 metric) {
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	struct mesh_path *mpath;
++	u8 *dst_addr, *orig_addr;
++	u8 dst_flags, ttl;
++	u32 orig_dsn, dst_dsn, lifetime;
++	bool reply = false;
++	bool forward = true;
++
++	/* Update destination DSN, if present */
++	dst_addr = PREQ_IE_DST_ADDR(preq_elem);
++	orig_addr = PREQ_IE_ORIG_ADDR(preq_elem);
++	dst_dsn = PREQ_IE_DST_DSN(preq_elem);
++	orig_dsn = PREQ_IE_ORIG_DSN(preq_elem);
++	dst_flags = PREQ_IE_DST_F(preq_elem);
++
++	if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) {
++		forward = false;
++		reply = true;
++		metric = 0;
++		if (time_after(jiffies, ifsta->last_dsn_update +
++					net_traversal_jiffies(sdata)) ||
++		    time_before(jiffies, ifsta->last_dsn_update)) {
++			dst_dsn = ++ifsta->dsn;
++			ifsta->last_dsn_update = jiffies;
++		}
++	} else {
++		rcu_read_lock();
++		mpath = mesh_path_lookup(dst_addr, dev);
++		if (mpath) {
++			if ((!(mpath->flags & MESH_PATH_DSN_VALID)) ||
++					DSN_LT(mpath->dsn, dst_dsn)) {
++				mpath->dsn = dst_dsn;
++				mpath->flags &= MESH_PATH_DSN_VALID;
++			} else if ((!(dst_flags & MP_F_DO)) &&
++					(mpath->flags & MESH_PATH_ACTIVE)) {
++				reply = true;
++				metric = mpath->metric;
++				dst_dsn = mpath->dsn;
++				if (dst_flags & MP_F_RF)
++					dst_flags |= MP_F_DO;
++				else
++					forward = false;
++			}
++		}
++		rcu_read_unlock();
++	}
++
++	if (reply) {
++		lifetime = PREQ_IE_LIFETIME(preq_elem);
++		ttl = ifsta->mshcfg.dot11MeshTTL;
++		if (ttl != 0)
++			mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr,
++				cpu_to_le32(dst_dsn), 0, orig_addr,
++				cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl,
++				cpu_to_le32(lifetime), cpu_to_le32(metric),
++				0, dev);
++		else
++			ifsta->mshstats.dropped_frames_ttl++;
++	}
++
++	if (forward) {
++		u32 preq_id;
++		u8 hopcount, flags;
++
++		ttl = PREQ_IE_TTL(preq_elem);
++		lifetime = PREQ_IE_LIFETIME(preq_elem);
++		if (ttl <= 1) {
++			ifsta->mshstats.dropped_frames_ttl++;
++			return;
++		}
++		--ttl;
++		flags = PREQ_IE_FLAGS(preq_elem);
++		preq_id = PREQ_IE_PREQ_ID(preq_elem);
++		hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
++		mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
++				cpu_to_le32(orig_dsn), dst_flags, dst_addr,
++				cpu_to_le32(dst_dsn), dev->broadcast,
++				hopcount, ttl, cpu_to_le32(lifetime),
++				cpu_to_le32(metric), cpu_to_le32(preq_id),
++				dev);
++		ifsta->mshstats.fwded_frames++;
++	}
++}
++
++
++static void hwmp_prep_frame_process(struct net_device *dev,
++				    struct ieee80211_mgmt *mgmt,
++				    u8 *prep_elem, u32 metric)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct mesh_path *mpath;
++	u8 *dst_addr, *orig_addr;
++	u8 ttl, hopcount, flags;
++	u8 next_hop[ETH_ALEN];
++	u32 dst_dsn, orig_dsn, lifetime;
++
++	/* Note that we divert from the draft nomenclature and denominate
++	 * destination to what the draft refers to as origininator. So in this
++	 * function destnation refers to the final destination of the PREP,
++	 * which corresponds with the originator of the PREQ which this PREP
++	 * replies
++	 */
++	dst_addr = PREP_IE_DST_ADDR(prep_elem);
++	if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0)
++		/* destination, no forwarding required */
++		return;
++
++	ttl = PREP_IE_TTL(prep_elem);
++	if (ttl <= 1) {
++		sdata->u.sta.mshstats.dropped_frames_ttl++;
++		return;
++	}
++
++	rcu_read_lock();
++	mpath = mesh_path_lookup(dst_addr, dev);
++	if (mpath)
++		spin_lock_bh(&mpath->state_lock);
++	else
++		goto fail;
++	if (!(mpath->flags & MESH_PATH_ACTIVE)) {
++		spin_unlock_bh(&mpath->state_lock);
++		goto fail;
++	}
++	memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
++	spin_unlock_bh(&mpath->state_lock);
++	--ttl;
++	flags = PREP_IE_FLAGS(prep_elem);
++	lifetime = PREP_IE_LIFETIME(prep_elem);
++	hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1;
++	orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
++	dst_dsn = PREP_IE_DST_DSN(prep_elem);
++	orig_dsn = PREP_IE_ORIG_DSN(prep_elem);
++
++	mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
++		cpu_to_le32(orig_dsn), 0, dst_addr,
++		cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl,
++		cpu_to_le32(lifetime), cpu_to_le32(metric),
++		0, dev);
++	rcu_read_unlock();
++	sdata->u.sta.mshstats.fwded_frames++;
++	return;
++
++fail:
++	rcu_read_unlock();
++	sdata->u.sta.mshstats.dropped_frames_no_route++;
++	return;
++}
++
++static void hwmp_perr_frame_process(struct net_device *dev,
++			     struct ieee80211_mgmt *mgmt, u8 *perr_elem)
++{
++	struct mesh_path *mpath;
++	u8 *ta, *dst_addr;
++	u32 dst_dsn;
++
++	ta = mgmt->sa;
++	dst_addr = PERR_IE_DST_ADDR(perr_elem);
++	dst_dsn = PERR_IE_DST_DSN(perr_elem);
++	rcu_read_lock();
++	mpath = mesh_path_lookup(dst_addr, dev);
++	if (mpath) {
++		spin_lock_bh(&mpath->state_lock);
++		if (mpath->flags & MESH_PATH_ACTIVE &&
++		    memcmp(ta, mpath->next_hop->addr, ETH_ALEN) == 0 &&
++		    (!(mpath->flags & MESH_PATH_DSN_VALID) ||
++		    DSN_GT(dst_dsn, mpath->dsn))) {
++			mpath->flags &= ~MESH_PATH_ACTIVE;
++			mpath->dsn = dst_dsn;
++			spin_unlock_bh(&mpath->state_lock);
++			mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn),
++					   dev->broadcast, dev);
++		} else
++			spin_unlock_bh(&mpath->state_lock);
++	}
++	rcu_read_unlock();
++}
++
++
++
++void mesh_rx_path_sel_frame(struct net_device *dev,
++			    struct ieee80211_mgmt *mgmt,
++			    size_t len)
++{
++	struct ieee802_11_elems elems;
++	size_t baselen;
++	u32 last_hop_metric;
++
++	baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
++	ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
++			len - baselen, &elems);
++
++	switch (mgmt->u.action.u.mesh_action.action_code) {
++	case MPATH_PREQ:
++		if (!elems.preq || elems.preq_len != 37)
++			/* Right now we support just 1 destination and no AE */
++			return;
++		last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.preq);
++		if (!last_hop_metric)
++			return;
++		hwmp_preq_frame_process(dev, mgmt, elems.preq, last_hop_metric);
++		break;
++	case MPATH_PREP:
++		if (!elems.prep || elems.prep_len != 31)
++			/* Right now we support no AE */
++			return;
++		last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.prep);
++		if (!last_hop_metric)
++			return;
++		hwmp_prep_frame_process(dev, mgmt, elems.prep, last_hop_metric);
++		break;
++	case MPATH_PERR:
++		if (!elems.perr || elems.perr_len != 12)
++			/* Right now we support only one destination per PERR */
++			return;
++		hwmp_perr_frame_process(dev, mgmt, elems.perr);
++	default:
++		return;
++	}
++
++}
++
++/**
++ * mesh_queue_preq - queue a PREQ to a given destination
++ *
++ * @mpath: mesh path to discover
++ * @flags: special attributes of the PREQ to be sent
++ *
++ * Locking: the function must be called from within a rcu read lock block.
++ *
++ */
++static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
++{
++	struct ieee80211_sub_if_data *sdata =
++		IEEE80211_DEV_TO_SUB_IF(mpath->dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	struct mesh_preq_queue *preq_node;
++
++	preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL);
++	if (!preq_node) {
++		printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n");
++		return;
++	}
++
++	spin_lock(&ifsta->mesh_preq_queue_lock);
++	if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
++		spin_unlock(&ifsta->mesh_preq_queue_lock);
++		kfree(preq_node);
++		if (printk_ratelimit())
++			printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n");
++		return;
++	}
++
++	memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
++	preq_node->flags = flags;
++
++	list_add_tail(&preq_node->list, &ifsta->preq_queue.list);
++	++ifsta->preq_queue_len;
++	spin_unlock(&ifsta->mesh_preq_queue_lock);
++
++	if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata)))
++		queue_work(sdata->local->hw.workqueue, &ifsta->work);
++
++	else if (time_before(jiffies, ifsta->last_preq)) {
++		/* avoid long wait if did not send preqs for a long time
++		 * and jiffies wrapped around
++		 */
++		ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
++		queue_work(sdata->local->hw.workqueue, &ifsta->work);
++	} else
++		mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq +
++						min_preq_int_jiff(sdata));
++}
++
++/**
++ * mesh_path_start_discovery - launch a path discovery from the PREQ queue
++ *
++ * @dev: local mesh interface
++ */
++void mesh_path_start_discovery(struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata =
++		IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	struct mesh_preq_queue *preq_node;
++	struct mesh_path *mpath;
++	u8 ttl, dst_flags;
++	u32 lifetime;
++
++	spin_lock(&ifsta->mesh_preq_queue_lock);
++	if (!ifsta->preq_queue_len ||
++		time_before(jiffies, ifsta->last_preq +
++				min_preq_int_jiff(sdata))) {
++		spin_unlock(&ifsta->mesh_preq_queue_lock);
++		return;
++	}
++
++	preq_node = list_first_entry(&ifsta->preq_queue.list,
++			struct mesh_preq_queue, list);
++	list_del(&preq_node->list);
++	--ifsta->preq_queue_len;
++	spin_unlock(&ifsta->mesh_preq_queue_lock);
++
++	rcu_read_lock();
++	mpath = mesh_path_lookup(preq_node->dst, dev);
++	if (!mpath)
++		goto enddiscovery;
++
++	spin_lock_bh(&mpath->state_lock);
++	if (preq_node->flags & PREQ_Q_F_START) {
++		if (mpath->flags & MESH_PATH_RESOLVING) {
++			spin_unlock_bh(&mpath->state_lock);
++			goto enddiscovery;
++		} else {
++			mpath->flags &= ~MESH_PATH_RESOLVED;
++			mpath->flags |= MESH_PATH_RESOLVING;
++			mpath->discovery_retries = 0;
++			mpath->discovery_timeout = disc_timeout_jiff(sdata);
++		}
++	} else if (!(mpath->flags & MESH_PATH_RESOLVING) ||
++			mpath->flags & MESH_PATH_RESOLVED) {
++		mpath->flags &= ~MESH_PATH_RESOLVING;
++		spin_unlock_bh(&mpath->state_lock);
++		goto enddiscovery;
++	}
++
++	ifsta->last_preq = jiffies;
++
++	if (time_after(jiffies, ifsta->last_dsn_update +
++				net_traversal_jiffies(sdata)) ||
++	    time_before(jiffies, ifsta->last_dsn_update)) {
++		++ifsta->dsn;
++		sdata->u.sta.last_dsn_update = jiffies;
++	}
++	lifetime = default_lifetime(sdata);
++	ttl = sdata->u.sta.mshcfg.dot11MeshTTL;
++	if (ttl == 0) {
++		sdata->u.sta.mshstats.dropped_frames_ttl++;
++		spin_unlock_bh(&mpath->state_lock);
++		goto enddiscovery;
++	}
++
++	if (preq_node->flags & PREQ_Q_F_REFRESH)
++		dst_flags = MP_F_DO;
++	else
++		dst_flags = MP_F_RF;
++
++	spin_unlock_bh(&mpath->state_lock);
++	mesh_path_sel_frame_tx(MPATH_PREQ, 0, dev->dev_addr,
++			cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst,
++			cpu_to_le32(mpath->dsn), dev->broadcast, 0,
++			ttl, cpu_to_le32(lifetime), 0,
++			cpu_to_le32(ifsta->preq_id++), dev);
++	mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
++
++enddiscovery:
++	rcu_read_unlock();
++	kfree(preq_node);
++}
++
++/**
++ * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame
++ *
++ * @next_hop: output argument for next hop address
++ * @skb: frame to be sent
++ * @dev: network device the frame will be sent through
++ *
++ * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is
++ * found, the function will start a path discovery and queue the frame so it is
++ * sent when the path is resolved. This means the caller must not free the skb
++ * in this case.
++ */
++int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb,
++		struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct sk_buff *skb_to_free = NULL;
++	struct mesh_path *mpath;
++	int err = 0;
++
++	rcu_read_lock();
++	mpath = mesh_path_lookup(skb->data, dev);
++
++	if (!mpath) {
++		mesh_path_add(skb->data, dev);
++		mpath = mesh_path_lookup(skb->data, dev);
++		if (!mpath) {
++			dev_kfree_skb(skb);
++			sdata->u.sta.mshstats.dropped_frames_no_route++;
++			err = -ENOSPC;
++			goto endlookup;
++		}
++	}
++
++	if (mpath->flags & MESH_PATH_ACTIVE) {
++		if (time_after(jiffies, mpath->exp_time -
++			msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time))
++				&& skb->pkt_type != PACKET_OTHERHOST
++				&& !(mpath->flags & MESH_PATH_RESOLVING)
++				&& !(mpath->flags & MESH_PATH_FIXED)) {
++			mesh_queue_preq(mpath,
++					PREQ_Q_F_START | PREQ_Q_F_REFRESH);
++		}
++		memcpy(next_hop, mpath->next_hop->addr,
++				ETH_ALEN);
++	} else {
++		if (!(mpath->flags & MESH_PATH_RESOLVING)) {
++			/* Start discovery only if it is not running yet */
++			mesh_queue_preq(mpath, PREQ_Q_F_START);
++		}
++
++		if (skb_queue_len(&mpath->frame_queue) >=
++				MESH_FRAME_QUEUE_LEN) {
++			skb_to_free = mpath->frame_queue.next;
++			skb_unlink(skb_to_free, &mpath->frame_queue);
++		}
++
++		skb_queue_tail(&mpath->frame_queue, skb);
++		if (skb_to_free)
++			mesh_path_discard_frame(skb_to_free, dev);
++		err = -ENOENT;
++	}
++
++endlookup:
++	rcu_read_unlock();
++	return err;
++}
++
++void mesh_path_timer(unsigned long data)
++{
++	struct ieee80211_sub_if_data *sdata;
++	struct mesh_path *mpath;
++
++	rcu_read_lock();
++	mpath = (struct mesh_path *) data;
++	mpath = rcu_dereference(mpath);
++	if (!mpath)
++		goto endmpathtimer;
++	spin_lock_bh(&mpath->state_lock);
++	sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev);
++	if (mpath->flags & MESH_PATH_RESOLVED ||
++			(!(mpath->flags & MESH_PATH_RESOLVING)))
++		mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
++	else if (mpath->discovery_retries < max_preq_retries(sdata)) {
++		++mpath->discovery_retries;
++		mpath->discovery_timeout *= 2;
++		mesh_queue_preq(mpath, 0);
++	} else {
++		mpath->flags = 0;
++		mpath->exp_time = jiffies;
++		mesh_path_flush_pending(mpath);
++	}
++
++	spin_unlock_bh(&mpath->state_lock);
++endmpathtimer:
++	rcu_read_unlock();
++}
+diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
+new file mode 100644
+index 0000000..5845dc2
+--- /dev/null
++++ b/net/mac80211/mesh_pathtbl.c
+@@ -0,0 +1,516 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Author:     Luis Carlos Cobo <luisca at cozybit.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/etherdevice.h>
++#include <linux/list.h>
++#include <linux/netdevice.h>
++#include <linux/random.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "mesh.h"
++
++/* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */
++#define INIT_PATHS_SIZE_ORDER	2
++
++/* Keep the mean chain length below this constant */
++#define MEAN_CHAIN_LEN		2
++
++#define MPATH_EXPIRED(mpath) ((mpath->flags & MESH_PATH_ACTIVE) && \
++				time_after(jiffies, mpath->exp_time) && \
++				!(mpath->flags & MESH_PATH_FIXED))
++
++struct mpath_node {
++	struct hlist_node list;
++	struct rcu_head rcu;
++	/* This indirection allows two different tables to point to the same
++	 * mesh_path structure, useful when resizing
++	 */
++	struct mesh_path *mpath;
++};
++
++static struct mesh_table *mesh_paths;
++
++/* This lock will have the grow table function as writer and add / delete nodes
++ * as readers. When reading the table (i.e. doing lookups) we are well protected
++ * by RCU
++ */
++static DEFINE_RWLOCK(pathtbl_resize_lock);
++
++/**
++ *
++ * mesh_path_assign_nexthop - update mesh path next hop
++ *
++ * @mpath: mesh path to update
++ * @sta: next hop to assign
++ *
++ * Locking: mpath->state_lock must be held when calling this function
++ */
++void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
++{
++	rcu_assign_pointer(mpath->next_hop, sta);
++}
++
++
++/**
++ * mesh_path_lookup - look up a path in the mesh path table
++ * @dst: hardware address (ETH_ALEN length) of destination
++ * @dev: local interface
++ *
++ * Returns: pointer to the mesh path structure, or NULL if not found
++ *
++ * Locking: must be called within a read rcu section.
++ */
++struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev)
++{
++	struct mesh_path *mpath;
++	struct hlist_node *n;
++	struct hlist_head *bucket;
++	struct mesh_table *tbl;
++	struct mpath_node *node;
++
++	tbl = rcu_dereference(mesh_paths);
++
++	bucket = &tbl->hash_buckets[mesh_table_hash(dst, dev, tbl)];
++	hlist_for_each_entry_rcu(node, n, bucket, list) {
++		mpath = node->mpath;
++		if (mpath->dev == dev &&
++				memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
++			if (MPATH_EXPIRED(mpath)) {
++				spin_lock_bh(&mpath->state_lock);
++				if (MPATH_EXPIRED(mpath))
++					mpath->flags &= ~MESH_PATH_ACTIVE;
++				spin_unlock_bh(&mpath->state_lock);
++			}
++			return mpath;
++		}
++	}
++	return NULL;
++}
++
++/**
++ * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index
++ * @idx: index
++ * @dev: local interface, or NULL for all entries
++ *
++ * Returns: pointer to the mesh path structure, or NULL if not found.
++ *
++ * Locking: must be called within a read rcu section.
++ */
++struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev)
++{
++	struct mpath_node *node;
++	struct hlist_node *p;
++	int i;
++	int j = 0;
++
++	for_each_mesh_entry(mesh_paths, p, node, i) {
++		if (dev && node->mpath->dev != dev)
++			continue;
++		if (j++ == idx) {
++			if (MPATH_EXPIRED(node->mpath)) {
++				spin_lock_bh(&node->mpath->state_lock);
++				if (MPATH_EXPIRED(node->mpath))
++					node->mpath->flags &= ~MESH_PATH_ACTIVE;
++				spin_unlock_bh(&node->mpath->state_lock);
++			}
++			return node->mpath;
++		}
++	}
++
++	return NULL;
++}
++
++/**
++ * mesh_path_add - allocate and add a new path to the mesh path table
++ * @addr: destination address of the path (ETH_ALEN length)
++ * @dev: local interface
++ *
++ * Returns: 0 on sucess
++ *
++ * State: the initial state of the new path is set to 0
++ */
++int mesh_path_add(u8 *dst, struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct mesh_path *mpath, *new_mpath;
++	struct mpath_node *node, *new_node;
++	struct hlist_head *bucket;
++	struct hlist_node *n;
++	int grow = 0;
++	int err = 0;
++	u32 hash_idx;
++
++	if (memcmp(dst, dev->dev_addr, ETH_ALEN) == 0)
++		/* never add ourselves as neighbours */
++		return -ENOTSUPP;
++
++	if (is_multicast_ether_addr(dst))
++		return -ENOTSUPP;
++
++	if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0)
++		return -ENOSPC;
++
++	read_lock(&pathtbl_resize_lock);
++
++	new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
++	if (!new_mpath) {
++		atomic_dec(&sdata->u.sta.mpaths);
++		err = -ENOMEM;
++		goto endadd2;
++	}
++	memcpy(new_mpath->dst, dst, ETH_ALEN);
++	new_mpath->dev = dev;
++	new_mpath->flags = 0;
++	skb_queue_head_init(&new_mpath->frame_queue);
++	new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
++	new_node->mpath = new_mpath;
++	new_mpath->timer.data = (unsigned long) new_mpath;
++	new_mpath->timer.function = mesh_path_timer;
++	new_mpath->exp_time = jiffies;
++	spin_lock_init(&new_mpath->state_lock);
++	init_timer(&new_mpath->timer);
++
++	hash_idx = mesh_table_hash(dst, dev, mesh_paths);
++	bucket = &mesh_paths->hash_buckets[hash_idx];
++
++	spin_lock(&mesh_paths->hashwlock[hash_idx]);
++
++	hlist_for_each_entry(node, n, bucket, list) {
++		mpath = node->mpath;
++		if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN)
++				== 0) {
++			err = -EEXIST;
++			atomic_dec(&sdata->u.sta.mpaths);
++			kfree(new_node);
++			kfree(new_mpath);
++			goto endadd;
++		}
++	}
++
++	hlist_add_head_rcu(&new_node->list, bucket);
++	if (atomic_inc_return(&mesh_paths->entries) >=
++		mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1))
++		grow = 1;
++
++endadd:
++	spin_unlock(&mesh_paths->hashwlock[hash_idx]);
++endadd2:
++	read_unlock(&pathtbl_resize_lock);
++	if (!err && grow) {
++		struct mesh_table *oldtbl, *newtbl;
++
++		write_lock(&pathtbl_resize_lock);
++		oldtbl = mesh_paths;
++		newtbl = mesh_table_grow(mesh_paths);
++		if (!newtbl) {
++			write_unlock(&pathtbl_resize_lock);
++			return -ENOMEM;
++		}
++		rcu_assign_pointer(mesh_paths, newtbl);
++		synchronize_rcu();
++		mesh_table_free(oldtbl, false);
++		write_unlock(&pathtbl_resize_lock);
++	}
++	return err;
++}
++
++
++/**
++ * mesh_plink_broken - deactivates paths and sends perr when a link breaks
++ *
++ * @sta: broken peer link
++ *
++ * This function must be called from the rate control algorithm if enough
++ * delivery errors suggest that a peer link is no longer usable.
++ */
++void mesh_plink_broken(struct sta_info *sta)
++{
++	struct mesh_path *mpath;
++	struct mpath_node *node;
++	struct hlist_node *p;
++	struct net_device *dev = sta->sdata->dev;
++	int i;
++
++	rcu_read_lock();
++	for_each_mesh_entry(mesh_paths, p, node, i) {
++		mpath = node->mpath;
++		spin_lock_bh(&mpath->state_lock);
++		if (mpath->next_hop == sta &&
++		    mpath->flags & MESH_PATH_ACTIVE &&
++		    !(mpath->flags & MESH_PATH_FIXED)) {
++			mpath->flags &= ~MESH_PATH_ACTIVE;
++			++mpath->dsn;
++			spin_unlock_bh(&mpath->state_lock);
++			mesh_path_error_tx(mpath->dst,
++					cpu_to_le32(mpath->dsn),
++					dev->broadcast, dev);
++		} else
++		spin_unlock_bh(&mpath->state_lock);
++	}
++	rcu_read_unlock();
++}
++EXPORT_SYMBOL(mesh_plink_broken);
++
++/**
++ * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches
++ *
++ * @sta - mesh peer to match
++ *
++ * RCU notes: this function is called when a mesh plink transitions from
++ * PLINK_ESTAB to any other state, since PLINK_ESTAB state is the only one that
++ * allows path creation. This will happen before the sta can be freed (because
++ * sta_info_destroy() calls this) so any reader in a rcu read block will be
++ * protected against the plink disappearing.
++ */
++void mesh_path_flush_by_nexthop(struct sta_info *sta)
++{
++	struct mesh_path *mpath;
++	struct mpath_node *node;
++	struct hlist_node *p;
++	int i;
++
++	for_each_mesh_entry(mesh_paths, p, node, i) {
++		mpath = node->mpath;
++		if (mpath->next_hop == sta)
++			mesh_path_del(mpath->dst, mpath->dev);
++	}
++}
++
++void mesh_path_flush(struct net_device *dev)
++{
++	struct mesh_path *mpath;
++	struct mpath_node *node;
++	struct hlist_node *p;
++	int i;
++
++	for_each_mesh_entry(mesh_paths, p, node, i) {
++		mpath = node->mpath;
++		if (mpath->dev == dev)
++			mesh_path_del(mpath->dst, mpath->dev);
++	}
++}
++
++static void mesh_path_node_reclaim(struct rcu_head *rp)
++{
++	struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
++	struct ieee80211_sub_if_data *sdata =
++		IEEE80211_DEV_TO_SUB_IF(node->mpath->dev);
++
++	del_timer_sync(&node->mpath->timer);
++	atomic_dec(&sdata->u.sta.mpaths);
++	kfree(node->mpath);
++	kfree(node);
++}
++
++/**
++ * mesh_path_del - delete a mesh path from the table
++ *
++ * @addr: dst address (ETH_ALEN length)
++ * @dev: local interface
++ *
++ * Returns: 0 if succesful
++ */
++int mesh_path_del(u8 *addr, struct net_device *dev)
++{
++	struct mesh_path *mpath;
++	struct mpath_node *node;
++	struct hlist_head *bucket;
++	struct hlist_node *n;
++	int hash_idx;
++	int err = 0;
++
++	read_lock(&pathtbl_resize_lock);
++	hash_idx = mesh_table_hash(addr, dev, mesh_paths);
++	bucket = &mesh_paths->hash_buckets[hash_idx];
++
++	spin_lock(&mesh_paths->hashwlock[hash_idx]);
++	hlist_for_each_entry(node, n, bucket, list) {
++		mpath = node->mpath;
++		if (mpath->dev == dev &&
++				memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
++			spin_lock_bh(&mpath->state_lock);
++			mpath->flags |= MESH_PATH_RESOLVING;
++			hlist_del_rcu(&node->list);
++			call_rcu(&node->rcu, mesh_path_node_reclaim);
++			atomic_dec(&mesh_paths->entries);
++			spin_unlock_bh(&mpath->state_lock);
++			goto enddel;
++		}
++	}
++
++	err = -ENXIO;
++enddel:
++	spin_unlock(&mesh_paths->hashwlock[hash_idx]);
++	read_unlock(&pathtbl_resize_lock);
++	return err;
++}
++
++/**
++ * mesh_path_tx_pending - sends pending frames in a mesh path queue
++ *
++ * @mpath: mesh path to activate
++ *
++ * Locking: the state_lock of the mpath structure must NOT be held when calling
++ * this function.
++ */
++void mesh_path_tx_pending(struct mesh_path *mpath)
++{
++	struct sk_buff *skb;
++
++	while ((skb = skb_dequeue(&mpath->frame_queue)) &&
++			(mpath->flags & MESH_PATH_ACTIVE))
++		dev_queue_xmit(skb);
++}
++
++/**
++ * mesh_path_discard_frame - discard a frame whose path could not be resolved
++ *
++ * @skb: frame to discard
++ * @dev: network device the frame was to be sent through
++ *
++ * If the frame was beign forwarded from another MP, a PERR frame will be sent
++ * to the precursor.
++ *
++ * Locking: the function must me called within a rcu_read_lock region
++ */
++void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct mesh_path *mpath;
++	u32 dsn = 0;
++
++	if (skb->pkt_type == PACKET_OTHERHOST) {
++		struct ieee80211s_hdr *prev_meshhdr;
++		int mshhdrlen;
++		u8 *ra, *da;
++
++		prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb);
++		mshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr);
++		da = skb->data;
++		ra = MESH_PREQ(skb);
++		mpath = mesh_path_lookup(da, dev);
++		if (mpath)
++			dsn = ++mpath->dsn;
++		mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, dev);
++	}
++
++	kfree_skb(skb);
++	sdata->u.sta.mshstats.dropped_frames_no_route++;
++}
++
++/**
++ * mesh_path_flush_pending - free the pending queue of a mesh path
++ *
++ * @mpath: mesh path whose queue has to be freed
++ *
++ * Locking: the function must me called withing a rcu_read_lock region
++ */
++void mesh_path_flush_pending(struct mesh_path *mpath)
++{
++	struct ieee80211_sub_if_data *sdata;
++	struct sk_buff *skb;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev);
++
++	while ((skb = skb_dequeue(&mpath->frame_queue)) &&
++			(mpath->flags & MESH_PATH_ACTIVE))
++		mesh_path_discard_frame(skb, mpath->dev);
++}
++
++/**
++ * mesh_path_fix_nexthop - force a specific next hop for a mesh path
++ *
++ * @mpath: the mesh path to modify
++ * @next_hop: the next hop to force
++ *
++ * Locking: this function must be called holding mpath->state_lock
++ */
++void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop)
++{
++	spin_lock_bh(&mpath->state_lock);
++	mesh_path_assign_nexthop(mpath, next_hop);
++	mpath->dsn = 0xffff;
++	mpath->metric = 0;
++	mpath->hop_count = 0;
++	mpath->exp_time = 0;
++	mpath->flags |= MESH_PATH_FIXED;
++	mesh_path_activate(mpath);
++	spin_unlock_bh(&mpath->state_lock);
++	mesh_path_tx_pending(mpath);
++}
++
++static void mesh_path_node_free(struct hlist_node *p, bool free_leafs)
++{
++	struct mesh_path *mpath;
++	struct mpath_node *node = hlist_entry(p, struct mpath_node, list);
++	mpath = node->mpath;
++	hlist_del_rcu(p);
++	synchronize_rcu();
++	if (free_leafs)
++		kfree(mpath);
++	kfree(node);
++}
++
++static void mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
++{
++	struct mesh_path *mpath;
++	struct mpath_node *node, *new_node;
++	u32 hash_idx;
++
++	node = hlist_entry(p, struct mpath_node, list);
++	mpath = node->mpath;
++	new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
++	new_node->mpath = mpath;
++	hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl);
++	hlist_add_head(&new_node->list,
++			&newtbl->hash_buckets[hash_idx]);
++}
++
++int mesh_pathtbl_init(void)
++{
++	mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
++	mesh_paths->free_node = &mesh_path_node_free;
++	mesh_paths->copy_node = &mesh_path_node_copy;
++	mesh_paths->mean_chain_len = MEAN_CHAIN_LEN;
++	if (!mesh_paths)
++		return -ENOMEM;
++	return 0;
++}
++
++void mesh_path_expire(struct net_device *dev)
++{
++	struct mesh_path *mpath;
++	struct mpath_node *node;
++	struct hlist_node *p;
++	int i;
++
++	read_lock(&pathtbl_resize_lock);
++	for_each_mesh_entry(mesh_paths, p, node, i) {
++		if (node->mpath->dev != dev)
++			continue;
++		mpath = node->mpath;
++		spin_lock_bh(&mpath->state_lock);
++		if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
++		    (!(mpath->flags & MESH_PATH_FIXED)) &&
++			time_after(jiffies,
++			 mpath->exp_time + MESH_PATH_EXPIRE)) {
++			spin_unlock_bh(&mpath->state_lock);
++			mesh_path_del(mpath->dst, mpath->dev);
++		} else
++			spin_unlock_bh(&mpath->state_lock);
++	}
++	read_unlock(&pathtbl_resize_lock);
++}
++
++void mesh_pathtbl_unregister(void)
++{
++	mesh_table_free(mesh_paths, true);
++}
+diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
+new file mode 100644
+index 0000000..37f0c2b
+--- /dev/null
++++ b/net/mac80211/mesh_plink.c
+@@ -0,0 +1,762 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Author:     Luis Carlos Cobo <luisca at cozybit.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/random.h>
++#include "ieee80211_i.h"
++#include "rate.h"
++#include "mesh.h"
++
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++#define mpl_dbg(fmt, args...)	printk(KERN_DEBUG fmt, ##args)
++#else
++#define mpl_dbg(fmt, args...)	do { (void)(0); } while (0)
++#endif
++
++#define PLINK_GET_FRAME_SUBTYPE(p) (p)
++#define PLINK_GET_LLID(p) (p + 1)
++#define PLINK_GET_PLID(p) (p + 3)
++
++#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
++				jiffies + HZ * t / 1000))
++
++/* Peer link cancel reasons, all subject to ANA approval */
++#define MESH_LINK_CANCELLED			2
++#define MESH_MAX_NEIGHBORS			3
++#define MESH_CAPABILITY_POLICY_VIOLATION	4
++#define MESH_CLOSE_RCVD				5
++#define MESH_MAX_RETRIES			6
++#define MESH_CONFIRM_TIMEOUT			7
++#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS	8
++#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE	9
++#define MESH_SECURITY_FAILED_VERIFICATION	10
++
++#define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries)
++#define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout)
++#define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout)
++#define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout)
++#define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks)
++
++enum plink_frame_type {
++	PLINK_OPEN = 0,
++	PLINK_CONFIRM,
++	PLINK_CLOSE
++};
++
++enum plink_event {
++	PLINK_UNDEFINED,
++	OPN_ACPT,
++	OPN_RJCT,
++	OPN_IGNR,
++	CNF_ACPT,
++	CNF_RJCT,
++	CNF_IGNR,
++	CLS_ACPT,
++	CLS_IGNR
++};
++
++static inline
++void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
++{
++	atomic_inc(&sdata->u.sta.mshstats.estab_plinks);
++	mesh_accept_plinks_update(sdata);
++}
++
++static inline
++void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
++{
++	atomic_dec(&sdata->u.sta.mshstats.estab_plinks);
++	mesh_accept_plinks_update(sdata);
++}
++
++/**
++ * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
++ *
++ * @sta: mes peer link to restart
++ *
++ * Locking: this function must be called holding sta->plink_lock
++ */
++static inline void mesh_plink_fsm_restart(struct sta_info *sta)
++{
++	sta->plink_state = PLINK_LISTEN;
++	sta->llid = sta->plid = sta->reason = 0;
++	sta->plink_retries = 0;
++}
++
++/*
++ * NOTE: This is just an alias for sta_info_alloc(), see notes
++ *       on it in the lifecycle management section!
++ */
++static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
++					 u8 *hw_addr, u64 rates)
++{
++	struct ieee80211_local *local = sdata->local;
++	struct sta_info *sta;
++
++	if (local->num_sta >= MESH_MAX_PLINKS)
++		return NULL;
++
++	sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC);
++	if (!sta)
++		return NULL;
++
++	sta->flags |= WLAN_STA_AUTHORIZED;
++	sta->supp_rates[local->hw.conf.channel->band] = rates;
++
++	return sta;
++}
++
++/**
++ * mesh_plink_deactivate - deactivate mesh peer link
++ *
++ * @sta: mesh peer link to deactivate
++ *
++ * All mesh paths with this peer as next hop will be flushed
++ *
++ * Locking: the caller must hold sta->plink_lock
++ */
++static void __mesh_plink_deactivate(struct sta_info *sta)
++{
++	struct ieee80211_sub_if_data *sdata = sta->sdata;
++
++	if (sta->plink_state == PLINK_ESTAB)
++		mesh_plink_dec_estab_count(sdata);
++	sta->plink_state = PLINK_BLOCKED;
++	mesh_path_flush_by_nexthop(sta);
++}
++
++/**
++ * __mesh_plink_deactivate - deactivate mesh peer link
++ *
++ * @sta: mesh peer link to deactivate
++ *
++ * All mesh paths with this peer as next hop will be flushed
++ */
++void mesh_plink_deactivate(struct sta_info *sta)
++{
++	spin_lock_bh(&sta->plink_lock);
++	__mesh_plink_deactivate(sta);
++	spin_unlock_bh(&sta->plink_lock);
++}
++
++static int mesh_plink_frame_tx(struct net_device *dev,
++		enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid,
++		__le16 reason) {
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
++	struct ieee80211_mgmt *mgmt;
++	bool include_plid = false;
++	u8 *pos;
++	int ie_len;
++
++	if (!skb)
++		return -1;
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++	/* 25 is the size of the common mgmt part (24) plus the size of the
++	 * common action part (1)
++	 */
++	mgmt = (struct ieee80211_mgmt *)
++		skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action));
++	memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action));
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					   IEEE80211_STYPE_ACTION);
++	memcpy(mgmt->da, da, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	/* BSSID is left zeroed, wildcard value */
++	mgmt->u.action.category = PLINK_CATEGORY;
++	mgmt->u.action.u.plink_action.action_code = action;
++
++	if (action == PLINK_CLOSE)
++		mgmt->u.action.u.plink_action.aux = reason;
++	else {
++		mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0);
++		if (action == PLINK_CONFIRM) {
++			pos = skb_put(skb, 4);
++			/* two-byte status code followed by two-byte AID */
++			memset(pos, 0, 4);
++		}
++		mesh_mgmt_ies_add(skb, dev);
++	}
++
++	/* Add Peer Link Management element */
++	switch (action) {
++	case PLINK_OPEN:
++		ie_len = 3;
++		break;
++	case PLINK_CONFIRM:
++		ie_len = 5;
++		include_plid = true;
++		break;
++	case PLINK_CLOSE:
++	default:
++		if (!plid)
++			ie_len = 5;
++		else {
++			ie_len = 7;
++			include_plid = true;
++		}
++		break;
++	}
++
++	pos = skb_put(skb, 2 + ie_len);
++	*pos++ = WLAN_EID_PEER_LINK;
++	*pos++ = ie_len;
++	*pos++ = action;
++	memcpy(pos, &llid, 2);
++	if (include_plid) {
++		pos += 2;
++		memcpy(pos, &plid, 2);
++	}
++	if (action == PLINK_CLOSE) {
++		pos += 2;
++		memcpy(pos, &reason, 2);
++	}
++
++	ieee80211_sta_tx(dev, skb, 0);
++	return 0;
++}
++
++void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev,
++			   bool peer_accepting_plinks)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sta_info *sta;
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, hw_addr);
++	if (!sta) {
++		sta = mesh_plink_alloc(sdata, hw_addr, rates);
++		if (!sta) {
++			rcu_read_unlock();
++			return;
++		}
++		if (sta_info_insert(sta)) {
++			rcu_read_unlock();
++			return;
++		}
++	}
++
++	sta->last_rx = jiffies;
++	sta->supp_rates[local->hw.conf.channel->band] = rates;
++	if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN &&
++			sdata->u.sta.accepting_plinks &&
++			sdata->u.sta.mshcfg.auto_open_plinks)
++		mesh_plink_open(sta);
++
++	rcu_read_unlock();
++}
++
++static void mesh_plink_timer(unsigned long data)
++{
++	struct sta_info *sta;
++	__le16 llid, plid, reason;
++	struct net_device *dev = NULL;
++	struct ieee80211_sub_if_data *sdata;
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++	DECLARE_MAC_BUF(mac);
++#endif
++
++	/*
++	 * This STA is valid because sta_info_destroy() will
++	 * del_timer_sync() this timer after having made sure
++	 * it cannot be readded (by deleting the plink.)
++	 */
++	sta = (struct sta_info *) data;
++
++	spin_lock_bh(&sta->plink_lock);
++	if (sta->ignore_plink_timer) {
++		sta->ignore_plink_timer = false;
++		spin_unlock_bh(&sta->plink_lock);
++		return;
++	}
++	mpl_dbg("Mesh plink timer for %s fired on state %d\n",
++			print_mac(mac, sta->addr), sta->plink_state);
++	reason = 0;
++	llid = sta->llid;
++	plid = sta->plid;
++	sdata = sta->sdata;
++	dev = sdata->dev;
++
++	switch (sta->plink_state) {
++	case PLINK_OPN_RCVD:
++	case PLINK_OPN_SNT:
++		/* retry timer */
++		if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
++			u32 rand;
++			mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n",
++					print_mac(mac, sta->addr),
++					sta->plink_retries, sta->plink_timeout);
++			get_random_bytes(&rand, sizeof(u32));
++			sta->plink_timeout = sta->plink_timeout +
++					     rand % sta->plink_timeout;
++			++sta->plink_retries;
++			mod_plink_timer(sta, sta->plink_timeout);
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
++					    0, 0);
++			break;
++		}
++		reason = cpu_to_le16(MESH_MAX_RETRIES);
++		/* fall through on else */
++	case PLINK_CNF_RCVD:
++		/* confirm timer */
++		if (!reason)
++			reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT);
++		sta->plink_state = PLINK_HOLDING;
++		mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
++		spin_unlock_bh(&sta->plink_lock);
++		mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid,
++				    reason);
++		break;
++	case PLINK_HOLDING:
++		/* holding timer */
++		del_timer(&sta->plink_timer);
++		mesh_plink_fsm_restart(sta);
++		spin_unlock_bh(&sta->plink_lock);
++		break;
++	default:
++		spin_unlock_bh(&sta->plink_lock);
++		break;
++	}
++}
++
++static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
++{
++	sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
++	sta->plink_timer.data = (unsigned long) sta;
++	sta->plink_timer.function = mesh_plink_timer;
++	sta->plink_timeout = timeout;
++	add_timer(&sta->plink_timer);
++}
++
++int mesh_plink_open(struct sta_info *sta)
++{
++	__le16 llid;
++	struct ieee80211_sub_if_data *sdata = sta->sdata;
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++	DECLARE_MAC_BUF(mac);
++#endif
++
++	spin_lock_bh(&sta->plink_lock);
++	get_random_bytes(&llid, 2);
++	sta->llid = llid;
++	if (sta->plink_state != PLINK_LISTEN) {
++		spin_unlock_bh(&sta->plink_lock);
++		return -EBUSY;
++	}
++	sta->plink_state = PLINK_OPN_SNT;
++	mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
++	spin_unlock_bh(&sta->plink_lock);
++	mpl_dbg("Mesh plink: starting establishment with %s\n",
++		print_mac(mac, sta->addr));
++
++	return mesh_plink_frame_tx(sdata->dev, PLINK_OPEN,
++				   sta->addr, llid, 0, 0);
++}
++
++void mesh_plink_block(struct sta_info *sta)
++{
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++	DECLARE_MAC_BUF(mac);
++#endif
++
++	spin_lock_bh(&sta->plink_lock);
++	__mesh_plink_deactivate(sta);
++	sta->plink_state = PLINK_BLOCKED;
++	spin_unlock_bh(&sta->plink_lock);
++}
++
++int mesh_plink_close(struct sta_info *sta)
++{
++	struct ieee80211_sub_if_data *sdata = sta->sdata;
++	__le16 llid, plid, reason;
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++	DECLARE_MAC_BUF(mac);
++#endif
++
++	mpl_dbg("Mesh plink: closing link with %s\n",
++			print_mac(mac, sta->addr));
++	spin_lock_bh(&sta->plink_lock);
++	sta->reason = cpu_to_le16(MESH_LINK_CANCELLED);
++	reason = sta->reason;
++
++	if (sta->plink_state == PLINK_LISTEN ||
++	    sta->plink_state == PLINK_BLOCKED) {
++		mesh_plink_fsm_restart(sta);
++		spin_unlock_bh(&sta->plink_lock);
++		return 0;
++	} else if (sta->plink_state == PLINK_ESTAB) {
++		__mesh_plink_deactivate(sta);
++		/* The timer should not be running */
++		mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
++	} else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)))
++		sta->ignore_plink_timer = true;
++
++	sta->plink_state = PLINK_HOLDING;
++	llid = sta->llid;
++	plid = sta->plid;
++	spin_unlock_bh(&sta->plink_lock);
++	mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid,
++			    plid, reason);
++	return 0;
++}
++
++void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
++			 size_t len, struct ieee80211_rx_status *rx_status)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_local *local = sdata->local;
++	struct ieee802_11_elems elems;
++	struct sta_info *sta;
++	enum plink_event event;
++	enum plink_frame_type ftype;
++	size_t baselen;
++	u8 ie_len;
++	u8 *baseaddr;
++	__le16 plid, llid, reason;
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++	DECLARE_MAC_BUF(mac);
++#endif
++
++	if (is_multicast_ether_addr(mgmt->da)) {
++		mpl_dbg("Mesh plink: ignore frame from multicast address");
++		return;
++	}
++
++	baseaddr = mgmt->u.action.u.plink_action.variable;
++	baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;
++	if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {
++		baseaddr += 4;
++		baselen -= 4;
++	}
++	ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
++	if (!elems.peer_link) {
++		mpl_dbg("Mesh plink: missing necessary peer link ie\n");
++		return;
++	}
++
++	ftype = *((u8 *)PLINK_GET_FRAME_SUBTYPE(elems.peer_link));
++	ie_len = elems.peer_link_len;
++	if ((ftype == PLINK_OPEN && ie_len != 3) ||
++	    (ftype == PLINK_CONFIRM && ie_len != 5) ||
++	    (ftype == PLINK_CLOSE && ie_len != 5 && ie_len != 7)) {
++		mpl_dbg("Mesh plink: incorrect plink ie length\n");
++		return;
++	}
++
++	if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) {
++		mpl_dbg("Mesh plink: missing necessary ie\n");
++		return;
++	}
++	/* Note the lines below are correct, the llid in the frame is the plid
++	 * from the point of view of this host.
++	 */
++	memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2);
++	if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 7))
++		memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2);
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, mgmt->sa);
++	if (!sta && ftype != PLINK_OPEN) {
++		mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
++		rcu_read_unlock();
++		return;
++	}
++
++	if (sta && sta->plink_state == PLINK_BLOCKED) {
++		rcu_read_unlock();
++		return;
++	}
++
++	/* Now we will figure out the appropriate event... */
++	event = PLINK_UNDEFINED;
++	if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, dev))) {
++		switch (ftype) {
++		case PLINK_OPEN:
++			event = OPN_RJCT;
++			break;
++		case PLINK_CONFIRM:
++			event = CNF_RJCT;
++			break;
++		case PLINK_CLOSE:
++			/* avoid warning */
++			break;
++		}
++		spin_lock_bh(&sta->plink_lock);
++	} else if (!sta) {
++		/* ftype == PLINK_OPEN */
++		u64 rates;
++		if (!mesh_plink_free_count(sdata)) {
++			mpl_dbg("Mesh plink error: no more free plinks\n");
++			rcu_read_unlock();
++			return;
++		}
++
++		rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
++		sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
++		if (!sta) {
++			mpl_dbg("Mesh plink error: plink table full\n");
++			rcu_read_unlock();
++			return;
++		}
++		if (sta_info_insert(sta)) {
++			rcu_read_unlock();
++			return;
++		}
++		event = OPN_ACPT;
++		spin_lock_bh(&sta->plink_lock);
++	} else {
++		spin_lock_bh(&sta->plink_lock);
++		switch (ftype) {
++		case PLINK_OPEN:
++			if (!mesh_plink_free_count(sdata) ||
++			    (sta->plid && sta->plid != plid))
++				event = OPN_IGNR;
++			else
++				event = OPN_ACPT;
++			break;
++		case PLINK_CONFIRM:
++			if (!mesh_plink_free_count(sdata) ||
++			    (sta->llid != llid || sta->plid != plid))
++				event = CNF_IGNR;
++			else
++				event = CNF_ACPT;
++			break;
++		case PLINK_CLOSE:
++			if (sta->plink_state == PLINK_ESTAB)
++				/* Do not check for llid or plid. This does not
++				 * follow the standard but since multiple plinks
++				 * per sta are not supported, it is necessary in
++				 * order to avoid a livelock when MP A sees an
++				 * establish peer link to MP B but MP B does not
++				 * see it. This can be caused by a timeout in
++				 * B's peer link establishment or B beign
++				 * restarted.
++				 */
++				event = CLS_ACPT;
++			else if (sta->plid != plid)
++				event = CLS_IGNR;
++			else if (ie_len == 7 && sta->llid != llid)
++				event = CLS_IGNR;
++			else
++				event = CLS_ACPT;
++			break;
++		default:
++			mpl_dbg("Mesh plink: unknown frame subtype\n");
++			spin_unlock_bh(&sta->plink_lock);
++			rcu_read_unlock();
++			return;
++		}
++	}
++
++	mpl_dbg("Mesh plink (peer, state, llid, plid, event): %s %d %d %d %d\n",
++			print_mac(mac, mgmt->sa), sta->plink_state,
++			le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
++			event);
++	reason = 0;
++	switch (sta->plink_state) {
++		/* spin_unlock as soon as state is updated at each case */
++	case PLINK_LISTEN:
++		switch (event) {
++		case CLS_ACPT:
++			mesh_plink_fsm_restart(sta);
++			spin_unlock_bh(&sta->plink_lock);
++			break;
++		case OPN_ACPT:
++			sta->plink_state = PLINK_OPN_RCVD;
++			sta->plid = plid;
++			get_random_bytes(&llid, 2);
++			sta->llid = llid;
++			mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
++					    0, 0);
++			mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr,
++					    llid, plid, 0);
++			break;
++		default:
++			spin_unlock_bh(&sta->plink_lock);
++			break;
++		}
++		break;
++
++	case PLINK_OPN_SNT:
++		switch (event) {
++		case OPN_RJCT:
++		case CNF_RJCT:
++			reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
++		case CLS_ACPT:
++			if (!reason)
++				reason = cpu_to_le16(MESH_CLOSE_RCVD);
++			sta->reason = reason;
++			sta->plink_state = PLINK_HOLDING;
++			if (!mod_plink_timer(sta,
++					     dot11MeshHoldingTimeout(sdata)))
++				sta->ignore_plink_timer = true;
++
++			llid = sta->llid;
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++					    plid, reason);
++			break;
++		case OPN_ACPT:
++			/* retry timer is left untouched */
++			sta->plink_state = PLINK_OPN_RCVD;
++			sta->plid = plid;
++			llid = sta->llid;
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
++					    plid, 0);
++			break;
++		case CNF_ACPT:
++			sta->plink_state = PLINK_CNF_RCVD;
++			if (!mod_plink_timer(sta,
++					     dot11MeshConfirmTimeout(sdata)))
++				sta->ignore_plink_timer = true;
++
++			spin_unlock_bh(&sta->plink_lock);
++			break;
++		default:
++			spin_unlock_bh(&sta->plink_lock);
++			break;
++		}
++		break;
++
++	case PLINK_OPN_RCVD:
++		switch (event) {
++		case OPN_RJCT:
++		case CNF_RJCT:
++			reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
++		case CLS_ACPT:
++			if (!reason)
++				reason = cpu_to_le16(MESH_CLOSE_RCVD);
++			sta->reason = reason;
++			sta->plink_state = PLINK_HOLDING;
++			if (!mod_plink_timer(sta,
++					     dot11MeshHoldingTimeout(sdata)))
++				sta->ignore_plink_timer = true;
++
++			llid = sta->llid;
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++					    plid, reason);
++			break;
++		case OPN_ACPT:
++			llid = sta->llid;
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
++					    plid, 0);
++			break;
++		case CNF_ACPT:
++			del_timer(&sta->plink_timer);
++			sta->plink_state = PLINK_ESTAB;
++			mesh_plink_inc_estab_count(sdata);
++			spin_unlock_bh(&sta->plink_lock);
++			mpl_dbg("Mesh plink with %s ESTABLISHED\n",
++					print_mac(mac, sta->addr));
++			break;
++		default:
++			spin_unlock_bh(&sta->plink_lock);
++			break;
++		}
++		break;
++
++	case PLINK_CNF_RCVD:
++		switch (event) {
++		case OPN_RJCT:
++		case CNF_RJCT:
++			reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
++		case CLS_ACPT:
++			if (!reason)
++				reason = cpu_to_le16(MESH_CLOSE_RCVD);
++			sta->reason = reason;
++			sta->plink_state = PLINK_HOLDING;
++			if (!mod_plink_timer(sta,
++					     dot11MeshHoldingTimeout(sdata)))
++				sta->ignore_plink_timer = true;
++
++			llid = sta->llid;
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++					    plid, reason);
++			break;
++		case OPN_ACPT:
++			del_timer(&sta->plink_timer);
++			sta->plink_state = PLINK_ESTAB;
++			mesh_plink_inc_estab_count(sdata);
++			spin_unlock_bh(&sta->plink_lock);
++			mpl_dbg("Mesh plink with %s ESTABLISHED\n",
++					print_mac(mac, sta->addr));
++			mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
++					    plid, 0);
++			break;
++		default:
++			spin_unlock_bh(&sta->plink_lock);
++			break;
++		}
++		break;
++
++	case PLINK_ESTAB:
++		switch (event) {
++		case CLS_ACPT:
++			reason = cpu_to_le16(MESH_CLOSE_RCVD);
++			sta->reason = reason;
++			__mesh_plink_deactivate(sta);
++			sta->plink_state = PLINK_HOLDING;
++			llid = sta->llid;
++			mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++					    plid, reason);
++			break;
++		case OPN_ACPT:
++			llid = sta->llid;
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
++					    plid, 0);
++			break;
++		default:
++			spin_unlock_bh(&sta->plink_lock);
++			break;
++		}
++		break;
++	case PLINK_HOLDING:
++		switch (event) {
++		case CLS_ACPT:
++			if (del_timer(&sta->plink_timer))
++				sta->ignore_plink_timer = 1;
++			mesh_plink_fsm_restart(sta);
++			spin_unlock_bh(&sta->plink_lock);
++			break;
++		case OPN_ACPT:
++		case CNF_ACPT:
++		case OPN_RJCT:
++		case CNF_RJCT:
++			llid = sta->llid;
++			reason = sta->reason;
++			spin_unlock_bh(&sta->plink_lock);
++			mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++					    plid, reason);
++			break;
++		default:
++			spin_unlock_bh(&sta->plink_lock);
++		}
++		break;
++	default:
++		/* should not get here, PLINK_BLOCKED is dealt with at the
++		 * beggining of the function
++		 */
++		spin_unlock_bh(&sta->plink_lock);
++		break;
++	}
++
++	rcu_read_unlock();
++}
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+new file mode 100644
+index 0000000..a5e5c31
+--- /dev/null
++++ b/net/mac80211/mlme.c
+@@ -0,0 +1,4321 @@
++/*
++ * BSS client mode implementation
++ * Copyright 2003, Jouni Malinen <jkmaline at cc.hut.fi>
++ * Copyright 2004, Instant802 Networks, Inc.
++ * Copyright 2005, Devicescape Software, Inc.
++ * Copyright 2006-2007	Jiri Benc <jbenc at suse.cz>
++ * Copyright 2007, Michael Wu <flamingice at sourmilk.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* TODO:
++ * order BSS list by RSSI(?) ("quality of AP")
++ * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
++ *    SSID)
++ */
++#include <linux/delay.h>
++#include <linux/if_ether.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#include <linux/random.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <net/iw_handler.h>
++#include <asm/types.h>
++
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "rate.h"
++#include "led.h"
++#include "mesh.h"
++
++#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
++#define IEEE80211_AUTH_MAX_TRIES 3
++#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
++#define IEEE80211_ASSOC_MAX_TRIES 3
++#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
++#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
++#define IEEE80211_PROBE_INTERVAL (60 * HZ)
++#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
++#define IEEE80211_SCAN_INTERVAL (2 * HZ)
++#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
++#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ)
++
++#define IEEE80211_PROBE_DELAY (HZ / 33)
++#define IEEE80211_CHANNEL_TIME (HZ / 33)
++#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
++#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
++#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
++#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
++#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
++
++#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
++
++
++#define ERP_INFO_USE_PROTECTION BIT(1)
++
++/* mgmt header + 1 byte action code */
++#define IEEE80211_MIN_ACTION_SIZE (24 + 1)
++
++#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
++#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
++#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0
++#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
++#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
++
++/* next values represent the buffer size for A-MPDU frame.
++ * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */
++#define IEEE80211_MIN_AMPDU_BUF 0x8
++#define IEEE80211_MAX_AMPDU_BUF 0x40
++
++static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
++				     u8 *ssid, size_t ssid_len);
++static struct ieee80211_sta_bss *
++ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
++		     u8 *ssid, u8 ssid_len);
++static void ieee80211_rx_bss_put(struct net_device *dev,
++				 struct ieee80211_sta_bss *bss);
++static int ieee80211_sta_find_ibss(struct net_device *dev,
++				   struct ieee80211_if_sta *ifsta);
++static int ieee80211_sta_wep_configured(struct net_device *dev);
++static int ieee80211_sta_start_scan(struct net_device *dev,
++				    u8 *ssid, size_t ssid_len);
++static int ieee80211_sta_config_auth(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta);
++
++
++void ieee802_11_parse_elems(u8 *start, size_t len,
++			    struct ieee802_11_elems *elems)
++{
++	size_t left = len;
++	u8 *pos = start;
++
++	memset(elems, 0, sizeof(*elems));
++
++	while (left >= 2) {
++		u8 id, elen;
++
++		id = *pos++;
++		elen = *pos++;
++		left -= 2;
++
++		if (elen > left)
++			return;
++
++		switch (id) {
++		case WLAN_EID_SSID:
++			elems->ssid = pos;
++			elems->ssid_len = elen;
++			break;
++		case WLAN_EID_SUPP_RATES:
++			elems->supp_rates = pos;
++			elems->supp_rates_len = elen;
++			break;
++		case WLAN_EID_FH_PARAMS:
++			elems->fh_params = pos;
++			elems->fh_params_len = elen;
++			break;
++		case WLAN_EID_DS_PARAMS:
++			elems->ds_params = pos;
++			elems->ds_params_len = elen;
++			break;
++		case WLAN_EID_CF_PARAMS:
++			elems->cf_params = pos;
++			elems->cf_params_len = elen;
++			break;
++		case WLAN_EID_TIM:
++			elems->tim = pos;
++			elems->tim_len = elen;
++			break;
++		case WLAN_EID_IBSS_PARAMS:
++			elems->ibss_params = pos;
++			elems->ibss_params_len = elen;
++			break;
++		case WLAN_EID_CHALLENGE:
++			elems->challenge = pos;
++			elems->challenge_len = elen;
++			break;
++		case WLAN_EID_WPA:
++			if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
++			    pos[2] == 0xf2) {
++				/* Microsoft OUI (00:50:F2) */
++				if (pos[3] == 1) {
++					/* OUI Type 1 - WPA IE */
++					elems->wpa = pos;
++					elems->wpa_len = elen;
++				} else if (elen >= 5 && pos[3] == 2) {
++					if (pos[4] == 0) {
++						elems->wmm_info = pos;
++						elems->wmm_info_len = elen;
++					} else if (pos[4] == 1) {
++						elems->wmm_param = pos;
++						elems->wmm_param_len = elen;
++					}
++				}
++			}
++			break;
++		case WLAN_EID_RSN:
++			elems->rsn = pos;
++			elems->rsn_len = elen;
++			break;
++		case WLAN_EID_ERP_INFO:
++			elems->erp_info = pos;
++			elems->erp_info_len = elen;
++			break;
++		case WLAN_EID_EXT_SUPP_RATES:
++			elems->ext_supp_rates = pos;
++			elems->ext_supp_rates_len = elen;
++			break;
++		case WLAN_EID_HT_CAPABILITY:
++			elems->ht_cap_elem = pos;
++			elems->ht_cap_elem_len = elen;
++			break;
++		case WLAN_EID_HT_EXTRA_INFO:
++			elems->ht_info_elem = pos;
++			elems->ht_info_elem_len = elen;
++			break;
++		case WLAN_EID_MESH_ID:
++			elems->mesh_id = pos;
++			elems->mesh_id_len = elen;
++			break;
++		case WLAN_EID_MESH_CONFIG:
++			elems->mesh_config = pos;
++			elems->mesh_config_len = elen;
++			break;
++		case WLAN_EID_PEER_LINK:
++			elems->peer_link = pos;
++			elems->peer_link_len = elen;
++			break;
++		case WLAN_EID_PREQ:
++			elems->preq = pos;
++			elems->preq_len = elen;
++			break;
++		case WLAN_EID_PREP:
++			elems->prep = pos;
++			elems->prep_len = elen;
++			break;
++		case WLAN_EID_PERR:
++			elems->perr = pos;
++			elems->perr_len = elen;
++			break;
++		default:
++			break;
++		}
++
++		left -= elen;
++		pos += elen;
++	}
++}
++
++
++static int ecw2cw(int ecw)
++{
++	return (1 << ecw) - 1;
++}
++
++
++static void ieee80211_sta_def_wmm_params(struct net_device *dev,
++					 struct ieee80211_sta_bss *bss,
++					 int ibss)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_local *local = sdata->local;
++	int i, have_higher_than_11mbit = 0;
++
++
++	/* cf. IEEE 802.11 9.2.12 */
++	for (i = 0; i < bss->supp_rates_len; i++)
++		if ((bss->supp_rates[i] & 0x7f) * 5 > 110)
++			have_higher_than_11mbit = 1;
++
++	if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
++	    have_higher_than_11mbit)
++		sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
++	else
++		sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
++
++
++	if (local->ops->conf_tx) {
++		struct ieee80211_tx_queue_params qparam;
++
++		memset(&qparam, 0, sizeof(qparam));
++
++		qparam.aifs = 2;
++
++		if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
++		    !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE))
++			qparam.cw_min = 31;
++		else
++			qparam.cw_min = 15;
++
++		qparam.cw_max = 1023;
++		qparam.txop = 0;
++
++		for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
++			local->ops->conf_tx(local_to_hw(local),
++					   i + IEEE80211_TX_QUEUE_DATA0,
++					   &qparam);
++
++		if (ibss) {
++			/* IBSS uses different parameters for Beacon sending */
++			qparam.cw_min++;
++			qparam.cw_min *= 2;
++			qparam.cw_min--;
++			local->ops->conf_tx(local_to_hw(local),
++					   IEEE80211_TX_QUEUE_BEACON, &qparam);
++		}
++	}
++}
++
++static void ieee80211_sta_wmm_params(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta,
++				     u8 *wmm_param, size_t wmm_param_len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_tx_queue_params params;
++	size_t left;
++	int count;
++	u8 *pos;
++
++	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
++		return;
++	count = wmm_param[6] & 0x0f;
++	if (count == ifsta->wmm_last_param_set)
++		return;
++	ifsta->wmm_last_param_set = count;
++
++	pos = wmm_param + 8;
++	left = wmm_param_len - 8;
++
++	memset(&params, 0, sizeof(params));
++
++	if (!local->ops->conf_tx)
++		return;
++
++	local->wmm_acm = 0;
++	for (; left >= 4; left -= 4, pos += 4) {
++		int aci = (pos[0] >> 5) & 0x03;
++		int acm = (pos[0] >> 4) & 0x01;
++		int queue;
++
++		switch (aci) {
++		case 1:
++			queue = IEEE80211_TX_QUEUE_DATA3;
++			if (acm) {
++				local->wmm_acm |= BIT(0) | BIT(3);
++			}
++			break;
++		case 2:
++			queue = IEEE80211_TX_QUEUE_DATA1;
++			if (acm) {
++				local->wmm_acm |= BIT(4) | BIT(5);
++			}
++			break;
++		case 3:
++			queue = IEEE80211_TX_QUEUE_DATA0;
++			if (acm) {
++				local->wmm_acm |= BIT(6) | BIT(7);
++			}
++			break;
++		case 0:
++		default:
++			queue = IEEE80211_TX_QUEUE_DATA2;
++			if (acm) {
++				local->wmm_acm |= BIT(1) | BIT(2);
++			}
++			break;
++		}
++
++		params.aifs = pos[0] & 0x0f;
++		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
++		params.cw_min = ecw2cw(pos[1] & 0x0f);
++		params.txop = pos[2] | (pos[3] << 8);
++#ifdef CONFIG_MAC80211_DEBUG
++		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
++		       "cWmin=%d cWmax=%d txop=%d\n",
++		       dev->name, queue, aci, acm, params.aifs, params.cw_min,
++		       params.cw_max, params.txop);
++#endif
++		/* TODO: handle ACM (block TX, fallback to next lowest allowed
++		 * AC for now) */
++		if (local->ops->conf_tx(local_to_hw(local), queue, &params)) {
++			printk(KERN_DEBUG "%s: failed to set TX queue "
++			       "parameters for queue %d\n", dev->name, queue);
++		}
++	}
++}
++
++static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
++					   bool use_protection,
++					   bool use_short_preamble)
++{
++	struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	DECLARE_MAC_BUF(mac);
++	u32 changed = 0;
++
++	if (use_protection != bss_conf->use_cts_prot) {
++		if (net_ratelimit()) {
++			printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
++			       "%s)\n",
++			       sdata->dev->name,
++			       use_protection ? "enabled" : "disabled",
++			       print_mac(mac, ifsta->bssid));
++		}
++		bss_conf->use_cts_prot = use_protection;
++		changed |= BSS_CHANGED_ERP_CTS_PROT;
++	}
++
++	if (use_short_preamble != bss_conf->use_short_preamble) {
++		if (net_ratelimit()) {
++			printk(KERN_DEBUG "%s: switched to %s barker preamble"
++			       " (BSSID=%s)\n",
++			       sdata->dev->name,
++			       use_short_preamble ? "short" : "long",
++			       print_mac(mac, ifsta->bssid));
++		}
++		bss_conf->use_short_preamble = use_short_preamble;
++		changed |= BSS_CHANGED_ERP_PREAMBLE;
++	}
++
++	return changed;
++}
++
++static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
++				   u8 erp_value)
++{
++	bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
++	bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
++
++	return ieee80211_handle_protect_preamb(sdata,
++			use_protection, use_short_preamble);
++}
++
++static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
++					   struct ieee80211_sta_bss *bss)
++{
++	u32 changed = 0;
++
++	if (bss->has_erp_value)
++		changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value);
++	else {
++		u16 capab = bss->capability;
++		changed |= ieee80211_handle_protect_preamb(sdata, false,
++				(capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
++	}
++
++	return changed;
++}
++
++int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
++				   struct ieee80211_ht_info *ht_info)
++{
++
++	if (ht_info == NULL)
++		return -EINVAL;
++
++	memset(ht_info, 0, sizeof(*ht_info));
++
++	if (ht_cap_ie) {
++		u8 ampdu_info = ht_cap_ie->ampdu_params_info;
++
++		ht_info->ht_supported = 1;
++		ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
++		ht_info->ampdu_factor =
++			ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
++		ht_info->ampdu_density =
++			(ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
++		memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
++	} else
++		ht_info->ht_supported = 0;
++
++	return 0;
++}
++
++int ieee80211_ht_addt_info_ie_to_ht_bss_info(
++			struct ieee80211_ht_addt_info *ht_add_info_ie,
++			struct ieee80211_ht_bss_info *bss_info)
++{
++	if (bss_info == NULL)
++		return -EINVAL;
++
++	memset(bss_info, 0, sizeof(*bss_info));
++
++	if (ht_add_info_ie) {
++		u16 op_mode;
++		op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
++
++		bss_info->primary_channel = ht_add_info_ie->control_chan;
++		bss_info->bss_cap = ht_add_info_ie->ht_param;
++		bss_info->bss_op_mode = (u8)(op_mode & 0xff);
++	}
++
++	return 0;
++}
++
++static void ieee80211_sta_send_associnfo(struct net_device *dev,
++					 struct ieee80211_if_sta *ifsta)
++{
++	char *buf;
++	size_t len;
++	int i;
++	union iwreq_data wrqu;
++
++	if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
++		return;
++
++	buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
++				ifsta->assocresp_ies_len), GFP_KERNEL);
++	if (!buf)
++		return;
++
++	len = sprintf(buf, "ASSOCINFO(");
++	if (ifsta->assocreq_ies) {
++		len += sprintf(buf + len, "ReqIEs=");
++		for (i = 0; i < ifsta->assocreq_ies_len; i++) {
++			len += sprintf(buf + len, "%02x",
++				       ifsta->assocreq_ies[i]);
++		}
++	}
++	if (ifsta->assocresp_ies) {
++		if (ifsta->assocreq_ies)
++			len += sprintf(buf + len, " ");
++		len += sprintf(buf + len, "RespIEs=");
++		for (i = 0; i < ifsta->assocresp_ies_len; i++) {
++			len += sprintf(buf + len, "%02x",
++				       ifsta->assocresp_ies[i]);
++		}
++	}
++	len += sprintf(buf + len, ")");
++
++	if (len > IW_CUSTOM_MAX) {
++		len = sprintf(buf, "ASSOCRESPIE=");
++		for (i = 0; i < ifsta->assocresp_ies_len; i++) {
++			len += sprintf(buf + len, "%02x",
++				       ifsta->assocresp_ies[i]);
++		}
++	}
++
++	memset(&wrqu, 0, sizeof(wrqu));
++	wrqu.data.length = len;
++	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
++
++	kfree(buf);
++}
++
++
++static void ieee80211_set_associated(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta,
++				     bool assoc)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_local *local = sdata->local;
++	struct ieee80211_conf *conf = &local_to_hw(local)->conf;
++	union iwreq_data wrqu;
++	u32 changed = BSS_CHANGED_ASSOC;
++
++	if (assoc) {
++		struct ieee80211_sta_bss *bss;
++
++		ifsta->flags |= IEEE80211_STA_ASSOCIATED;
++
++		if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++			return;
++
++		bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++					   conf->channel->center_freq,
++					   ifsta->ssid, ifsta->ssid_len);
++		if (bss) {
++			/* set timing information */
++			sdata->bss_conf.beacon_int = bss->beacon_int;
++			sdata->bss_conf.timestamp = bss->timestamp;
++
++			changed |= ieee80211_handle_bss_capability(sdata, bss);
++
++			ieee80211_rx_bss_put(dev, bss);
++		}
++
++		if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
++			changed |= BSS_CHANGED_HT;
++			sdata->bss_conf.assoc_ht = 1;
++			sdata->bss_conf.ht_conf = &conf->ht_conf;
++			sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf;
++		}
++
++		netif_carrier_on(dev);
++		ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
++		memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
++		memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
++		ieee80211_sta_send_associnfo(dev, ifsta);
++	} else {
++		ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid);
++		ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
++		netif_carrier_off(dev);
++		ieee80211_reset_erp_info(dev);
++
++		sdata->bss_conf.assoc_ht = 0;
++		sdata->bss_conf.ht_conf = NULL;
++		sdata->bss_conf.ht_bss_conf = NULL;
++
++		memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
++	}
++	ifsta->last_probe = jiffies;
++	ieee80211_led_assoc(local, assoc);
++
++	sdata->bss_conf.assoc = assoc;
++	ieee80211_bss_info_change_notify(sdata, changed);
++	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++	wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
++}
++
++static void ieee80211_set_disassoc(struct net_device *dev,
++				   struct ieee80211_if_sta *ifsta, int deauth)
++{
++	if (deauth)
++		ifsta->auth_tries = 0;
++	ifsta->assoc_tries = 0;
++	ieee80211_set_associated(dev, ifsta, 0);
++}
++
++void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
++		      int encrypt)
++{
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_tx_packet_data *pkt_data;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	skb->dev = sdata->local->mdev;
++	skb_set_mac_header(skb, 0);
++	skb_set_network_header(skb, 0);
++	skb_set_transport_header(skb, 0);
++
++	pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
++	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
++	pkt_data->ifindex = sdata->dev->ifindex;
++	if (!encrypt)
++		pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
++
++	dev_queue_xmit(skb);
++}
++
++
++static void ieee80211_send_auth(struct net_device *dev,
++				struct ieee80211_if_sta *ifsta,
++				int transaction, u8 *extra, size_t extra_len,
++				int encrypt)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *mgmt;
++
++	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
++			    sizeof(*mgmt) + 6 + extra_len);
++	if (!skb) {
++		printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
++		       "frame\n", dev->name);
++		return;
++	}
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++
++	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
++	memset(mgmt, 0, 24 + 6);
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					   IEEE80211_STYPE_AUTH);
++	if (encrypt)
++		mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++	mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
++	mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
++	ifsta->auth_transaction = transaction + 1;
++	mgmt->u.auth.status_code = cpu_to_le16(0);
++	if (extra)
++		memcpy(skb_put(skb, extra_len), extra, extra_len);
++
++	ieee80211_sta_tx(dev, skb, encrypt);
++}
++
++
++static void ieee80211_authenticate(struct net_device *dev,
++				   struct ieee80211_if_sta *ifsta)
++{
++	DECLARE_MAC_BUF(mac);
++
++	ifsta->auth_tries++;
++	if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
++		printk(KERN_DEBUG "%s: authentication with AP %s"
++		       " timed out\n",
++		       dev->name, print_mac(mac, ifsta->bssid));
++		ifsta->state = IEEE80211_DISABLED;
++		return;
++	}
++
++	ifsta->state = IEEE80211_AUTHENTICATE;
++	printk(KERN_DEBUG "%s: authenticate with AP %s\n",
++	       dev->name, print_mac(mac, ifsta->bssid));
++
++	ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0);
++
++	mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
++}
++
++
++static void ieee80211_send_assoc(struct net_device *dev,
++				 struct ieee80211_if_sta *ifsta)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *mgmt;
++	u8 *pos, *ies;
++	int i, len;
++	u16 capab;
++	struct ieee80211_sta_bss *bss;
++	int wmm = 0;
++	struct ieee80211_supported_band *sband;
++
++	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
++			    sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
++			    ifsta->ssid_len);
++	if (!skb) {
++		printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
++		       "frame\n", dev->name);
++		return;
++	}
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++	capab = ifsta->capab;
++
++	if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) {
++		if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
++			capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
++		if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
++			capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
++	}
++
++	bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++				   local->hw.conf.channel->center_freq,
++				   ifsta->ssid, ifsta->ssid_len);
++	if (bss) {
++		if (bss->capability & WLAN_CAPABILITY_PRIVACY)
++			capab |= WLAN_CAPABILITY_PRIVACY;
++		if (bss->wmm_ie) {
++			wmm = 1;
++		}
++		ieee80211_rx_bss_put(dev, bss);
++	}
++
++	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++	memset(mgmt, 0, 24);
++	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++
++	if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
++		skb_put(skb, 10);
++		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++						   IEEE80211_STYPE_REASSOC_REQ);
++		mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
++		mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);
++		memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
++		       ETH_ALEN);
++	} else {
++		skb_put(skb, 4);
++		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++						   IEEE80211_STYPE_ASSOC_REQ);
++		mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
++		mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);
++	}
++
++	/* SSID */
++	ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
++	*pos++ = WLAN_EID_SSID;
++	*pos++ = ifsta->ssid_len;
++	memcpy(pos, ifsta->ssid, ifsta->ssid_len);
++
++	len = sband->n_bitrates;
++	if (len > 8)
++		len = 8;
++	pos = skb_put(skb, len + 2);
++	*pos++ = WLAN_EID_SUPP_RATES;
++	*pos++ = len;
++	for (i = 0; i < len; i++) {
++		int rate = sband->bitrates[i].bitrate;
++		*pos++ = (u8) (rate / 5);
++	}
++
++	if (sband->n_bitrates > len) {
++		pos = skb_put(skb, sband->n_bitrates - len + 2);
++		*pos++ = WLAN_EID_EXT_SUPP_RATES;
++		*pos++ = sband->n_bitrates - len;
++		for (i = len; i < sband->n_bitrates; i++) {
++			int rate = sband->bitrates[i].bitrate;
++			*pos++ = (u8) (rate / 5);
++		}
++	}
++
++	if (ifsta->extra_ie) {
++		pos = skb_put(skb, ifsta->extra_ie_len);
++		memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
++	}
++
++	if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
++		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;
++	}
++	/* wmm support is a must to HT */
++	if (wmm && sband->ht_info.ht_supported) {
++		__le16 tmp = cpu_to_le16(sband->ht_info.cap);
++		pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
++		*pos++ = WLAN_EID_HT_CAPABILITY;
++		*pos++ = sizeof(struct ieee80211_ht_cap);
++		memset(pos, 0, sizeof(struct ieee80211_ht_cap));
++		memcpy(pos, &tmp, sizeof(u16));
++		pos += sizeof(u16);
++		/* TODO: needs a define here for << 2 */
++		*pos++ = sband->ht_info.ampdu_factor |
++			 (sband->ht_info.ampdu_density << 2);
++		memcpy(pos, sband->ht_info.supp_mcs_set, 16);
++	}
++
++	kfree(ifsta->assocreq_ies);
++	ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
++	ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
++	if (ifsta->assocreq_ies)
++		memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
++
++	ieee80211_sta_tx(dev, skb, 0);
++}
++
++
++static void ieee80211_send_deauth(struct net_device *dev,
++				  struct ieee80211_if_sta *ifsta, u16 reason)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *mgmt;
++
++	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
++	if (!skb) {
++		printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
++		       "frame\n", dev->name);
++		return;
++	}
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++
++	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++	memset(mgmt, 0, 24);
++	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					   IEEE80211_STYPE_DEAUTH);
++	skb_put(skb, 2);
++	mgmt->u.deauth.reason_code = cpu_to_le16(reason);
++
++	ieee80211_sta_tx(dev, skb, 0);
++}
++
++
++static void ieee80211_send_disassoc(struct net_device *dev,
++				    struct ieee80211_if_sta *ifsta, u16 reason)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *mgmt;
++
++	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
++	if (!skb) {
++		printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
++		       "frame\n", dev->name);
++		return;
++	}
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++
++	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++	memset(mgmt, 0, 24);
++	memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					   IEEE80211_STYPE_DISASSOC);
++	skb_put(skb, 2);
++	mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
++
++	ieee80211_sta_tx(dev, skb, 0);
++}
++
++
++static int ieee80211_privacy_mismatch(struct net_device *dev,
++				      struct ieee80211_if_sta *ifsta)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sta_bss *bss;
++	int bss_privacy;
++	int wep_privacy;
++	int privacy_invoked;
++
++	if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
++		return 0;
++
++	bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++				   local->hw.conf.channel->center_freq,
++				   ifsta->ssid, ifsta->ssid_len);
++	if (!bss)
++		return 0;
++
++	bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
++	wep_privacy = !!ieee80211_sta_wep_configured(dev);
++	privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
++
++	ieee80211_rx_bss_put(dev, bss);
++
++	if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
++		return 0;
++
++	return 1;
++}
++
++
++static void ieee80211_associate(struct net_device *dev,
++				struct ieee80211_if_sta *ifsta)
++{
++	DECLARE_MAC_BUF(mac);
++
++	ifsta->assoc_tries++;
++	if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
++		printk(KERN_DEBUG "%s: association with AP %s"
++		       " timed out\n",
++		       dev->name, print_mac(mac, ifsta->bssid));
++		ifsta->state = IEEE80211_DISABLED;
++		return;
++	}
++
++	ifsta->state = IEEE80211_ASSOCIATE;
++	printk(KERN_DEBUG "%s: associate with AP %s\n",
++	       dev->name, print_mac(mac, ifsta->bssid));
++	if (ieee80211_privacy_mismatch(dev, ifsta)) {
++		printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
++		       "mixed-cell disabled - abort association\n", dev->name);
++		ifsta->state = IEEE80211_DISABLED;
++		return;
++	}
++
++	ieee80211_send_assoc(dev, ifsta);
++
++	mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
++}
++
++
++static void ieee80211_associated(struct net_device *dev,
++				 struct ieee80211_if_sta *ifsta)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sta_info *sta;
++	int disassoc;
++	DECLARE_MAC_BUF(mac);
++
++	/* TODO: start monitoring current AP signal quality and number of
++	 * missed beacons. Scan other channels every now and then and search
++	 * for better APs. */
++	/* TODO: remove expired BSSes */
++
++	ifsta->state = IEEE80211_ASSOCIATED;
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, ifsta->bssid);
++	if (!sta) {
++		printk(KERN_DEBUG "%s: No STA entry for own AP %s\n",
++		       dev->name, print_mac(mac, ifsta->bssid));
++		disassoc = 1;
++	} else {
++		disassoc = 0;
++		if (time_after(jiffies,
++			       sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
++			if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
++				printk(KERN_DEBUG "%s: No ProbeResp from "
++				       "current AP %s - assume out of "
++				       "range\n",
++				       dev->name, print_mac(mac, ifsta->bssid));
++				disassoc = 1;
++				sta_info_unlink(&sta);
++			} else
++				ieee80211_send_probe_req(dev, ifsta->bssid,
++							 local->scan_ssid,
++							 local->scan_ssid_len);
++			ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
++		} else {
++			ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
++			if (time_after(jiffies, ifsta->last_probe +
++				       IEEE80211_PROBE_INTERVAL)) {
++				ifsta->last_probe = jiffies;
++				ieee80211_send_probe_req(dev, ifsta->bssid,
++							 ifsta->ssid,
++							 ifsta->ssid_len);
++			}
++		}
++	}
++
++	rcu_read_unlock();
++
++	if (disassoc && sta)
++		sta_info_destroy(sta);
++
++	if (disassoc) {
++		ifsta->state = IEEE80211_DISABLED;
++		ieee80211_set_associated(dev, ifsta, 0);
++	} else {
++		mod_timer(&ifsta->timer, jiffies +
++				      IEEE80211_MONITORING_INTERVAL);
++	}
++}
++
++
++static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
++				     u8 *ssid, size_t ssid_len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_supported_band *sband;
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *mgmt;
++	u8 *pos, *supp_rates, *esupp_rates = NULL;
++	int i;
++
++	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
++	if (!skb) {
++		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
++		       "request\n", dev->name);
++		return;
++	}
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++
++	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++	memset(mgmt, 0, 24);
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					   IEEE80211_STYPE_PROBE_REQ);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	if (dst) {
++		memcpy(mgmt->da, dst, ETH_ALEN);
++		memcpy(mgmt->bssid, dst, ETH_ALEN);
++	} else {
++		memset(mgmt->da, 0xff, ETH_ALEN);
++		memset(mgmt->bssid, 0xff, ETH_ALEN);
++	}
++	pos = skb_put(skb, 2 + ssid_len);
++	*pos++ = WLAN_EID_SSID;
++	*pos++ = ssid_len;
++	memcpy(pos, ssid, ssid_len);
++
++	supp_rates = skb_put(skb, 2);
++	supp_rates[0] = WLAN_EID_SUPP_RATES;
++	supp_rates[1] = 0;
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++	for (i = 0; i < sband->n_bitrates; i++) {
++		struct ieee80211_rate *rate = &sband->bitrates[i];
++		if (esupp_rates) {
++			pos = skb_put(skb, 1);
++			esupp_rates[1]++;
++		} else if (supp_rates[1] == 8) {
++			esupp_rates = skb_put(skb, 3);
++			esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
++			esupp_rates[1] = 1;
++			pos = &esupp_rates[2];
++		} else {
++			pos = skb_put(skb, 1);
++			supp_rates[1]++;
++		}
++		*pos = rate->bitrate / 5;
++	}
++
++	ieee80211_sta_tx(dev, skb, 0);
++}
++
++
++static int ieee80211_sta_wep_configured(struct net_device *dev)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	if (!sdata || !sdata->default_key ||
++	    sdata->default_key->conf.alg != ALG_WEP)
++		return 0;
++	return 1;
++}
++
++
++static void ieee80211_auth_completed(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta)
++{
++	printk(KERN_DEBUG "%s: authenticated\n", dev->name);
++	ifsta->flags |= IEEE80211_STA_AUTHENTICATED;
++	ieee80211_associate(dev, ifsta);
++}
++
++
++static void ieee80211_auth_challenge(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta,
++				     struct ieee80211_mgmt *mgmt,
++				     size_t len)
++{
++	u8 *pos;
++	struct ieee802_11_elems elems;
++
++	printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
++	pos = mgmt->u.auth.variable;
++	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
++	if (!elems.challenge) {
++		printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
++		       "frame\n", dev->name);
++		return;
++	}
++	ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,
++			    elems.challenge_len + 2, 1);
++}
++
++static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid,
++					u8 dialog_token, u16 status, u16 policy,
++					u16 buf_size, u16 timeout)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *mgmt;
++	u16 capab;
++
++	skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
++					sizeof(mgmt->u.action.u.addba_resp));
++	if (!skb) {
++		printk(KERN_DEBUG "%s: failed to allocate buffer "
++		       "for addba resp frame\n", dev->name);
++		return;
++	}
++
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++	memset(mgmt, 0, 24);
++	memcpy(mgmt->da, da, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
++		memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
++	else
++		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					   IEEE80211_STYPE_ACTION);
++
++	skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
++	mgmt->u.action.category = WLAN_CATEGORY_BACK;
++	mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
++	mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
++
++	capab = (u16)(policy << 1);	/* bit 1 aggregation policy */
++	capab |= (u16)(tid << 2); 	/* bit 5:2 TID number */
++	capab |= (u16)(buf_size << 6);	/* bit 15:6 max size of aggregation */
++
++	mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
++	mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
++	mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
++
++	ieee80211_sta_tx(dev, skb, 0);
++
++	return;
++}
++
++void ieee80211_send_addba_request(struct net_device *dev, const u8 *da,
++				u16 tid, u8 dialog_token, u16 start_seq_num,
++				u16 agg_size, u16 timeout)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *mgmt;
++	u16 capab;
++
++	skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
++				sizeof(mgmt->u.action.u.addba_req));
++
++
++	if (!skb) {
++		printk(KERN_ERR "%s: failed to allocate buffer "
++				"for addba request frame\n", dev->name);
++		return;
++	}
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++	memset(mgmt, 0, 24);
++	memcpy(mgmt->da, da, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
++		memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
++	else
++		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					IEEE80211_STYPE_ACTION);
++
++	skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
++
++	mgmt->u.action.category = WLAN_CATEGORY_BACK;
++	mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
++
++	mgmt->u.action.u.addba_req.dialog_token = dialog_token;
++	capab = (u16)(1 << 1);		/* bit 1 aggregation policy */
++	capab |= (u16)(tid << 2); 	/* bit 5:2 TID number */
++	capab |= (u16)(agg_size << 6);	/* bit 15:6 max size of aggergation */
++
++	mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
++
++	mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
++	mgmt->u.action.u.addba_req.start_seq_num =
++					cpu_to_le16(start_seq_num << 4);
++
++	ieee80211_sta_tx(dev, skb, 0);
++}
++
++static void ieee80211_sta_process_addba_request(struct net_device *dev,
++						struct ieee80211_mgmt *mgmt,
++						size_t len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_hw *hw = &local->hw;
++	struct ieee80211_conf *conf = &hw->conf;
++	struct sta_info *sta;
++	struct tid_ampdu_rx *tid_agg_rx;
++	u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
++	u8 dialog_token;
++	int ret = -EOPNOTSUPP;
++	DECLARE_MAC_BUF(mac);
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, mgmt->sa);
++	if (!sta) {
++		rcu_read_unlock();
++		return;
++	}
++
++	/* extract session parameters from addba request frame */
++	dialog_token = mgmt->u.action.u.addba_req.dialog_token;
++	timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
++	start_seq_num =
++		le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
++
++	capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
++	ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
++	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
++	buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
++
++	status = WLAN_STATUS_REQUEST_DECLINED;
++
++	/* sanity check for incoming parameters:
++	 * check if configuration can support the BA policy
++	 * and if buffer size does not exceeds max value */
++	if (((ba_policy != 1)
++		&& (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA)))
++		|| (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
++		status = WLAN_STATUS_INVALID_QOS_PARAM;
++#ifdef CONFIG_MAC80211_HT_DEBUG
++		if (net_ratelimit())
++			printk(KERN_DEBUG "AddBA Req with bad params from "
++				"%s on tid %u. policy %d, buffer size %d\n",
++				print_mac(mac, mgmt->sa), tid, ba_policy,
++				buf_size);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++		goto end_no_lock;
++	}
++	/* determine default buffer size */
++	if (buf_size == 0) {
++		struct ieee80211_supported_band *sband;
++
++		sband = local->hw.wiphy->bands[conf->channel->band];
++		buf_size = IEEE80211_MIN_AMPDU_BUF;
++		buf_size = buf_size << sband->ht_info.ampdu_factor;
++	}
++
++
++	/* examine state machine */
++	spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
++
++	if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
++#ifdef CONFIG_MAC80211_HT_DEBUG
++		if (net_ratelimit())
++			printk(KERN_DEBUG "unexpected AddBA Req from "
++				"%s on tid %u\n",
++				print_mac(mac, mgmt->sa), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++		goto end;
++	}
++
++	/* prepare A-MPDU MLME for Rx aggregation */
++	sta->ampdu_mlme.tid_rx[tid] =
++			kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC);
++	if (!sta->ampdu_mlme.tid_rx[tid]) {
++		if (net_ratelimit())
++			printk(KERN_ERR "allocate rx mlme to tid %d failed\n",
++					tid);
++		goto end;
++	}
++	/* rx timer */
++	sta->ampdu_mlme.tid_rx[tid]->session_timer.function =
++				sta_rx_agg_session_timer_expired;
++	sta->ampdu_mlme.tid_rx[tid]->session_timer.data =
++				(unsigned long)&sta->timer_to_tid[tid];
++	init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
++
++	tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
++
++	/* prepare reordering buffer */
++	tid_agg_rx->reorder_buf =
++		kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC);
++	if (!tid_agg_rx->reorder_buf) {
++		if (net_ratelimit())
++			printk(KERN_ERR "can not allocate reordering buffer "
++			       "to tid %d\n", tid);
++		kfree(sta->ampdu_mlme.tid_rx[tid]);
++		goto end;
++	}
++	memset(tid_agg_rx->reorder_buf, 0,
++		buf_size * sizeof(struct sk_buf *));
++
++	if (local->ops->ampdu_action)
++		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
++					       sta->addr, tid, &start_seq_num);
++#ifdef CONFIG_MAC80211_HT_DEBUG
++	printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++	if (ret) {
++		kfree(tid_agg_rx->reorder_buf);
++		kfree(tid_agg_rx);
++		sta->ampdu_mlme.tid_rx[tid] = NULL;
++		goto end;
++	}
++
++	/* change state and send addba resp */
++	sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL;
++	tid_agg_rx->dialog_token = dialog_token;
++	tid_agg_rx->ssn = start_seq_num;
++	tid_agg_rx->head_seq_num = start_seq_num;
++	tid_agg_rx->buf_size = buf_size;
++	tid_agg_rx->timeout = timeout;
++	tid_agg_rx->stored_mpdu_num = 0;
++	status = WLAN_STATUS_SUCCESS;
++end:
++	spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
++
++end_no_lock:
++	ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid,
++				  dialog_token, status, 1, buf_size, timeout);
++	rcu_read_unlock();
++}
++
++static void ieee80211_sta_process_addba_resp(struct net_device *dev,
++					     struct ieee80211_mgmt *mgmt,
++					     size_t len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_hw *hw = &local->hw;
++	struct sta_info *sta;
++	u16 capab;
++	u16 tid;
++	u8 *state;
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, mgmt->sa);
++	if (!sta) {
++		rcu_read_unlock();
++		return;
++	}
++
++	capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
++	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
++
++	state = &sta->ampdu_mlme.tid_state_tx[tid];
++
++	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++		printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
++			"%d\n", *state);
++		goto addba_resp_exit;
++	}
++
++	if (mgmt->u.action.u.addba_resp.dialog_token !=
++		sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++#ifdef CONFIG_MAC80211_HT_DEBUG
++		printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++		goto addba_resp_exit;
++	}
++
++	del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
++#ifdef CONFIG_MAC80211_HT_DEBUG
++	printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++	if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
++			== WLAN_STATUS_SUCCESS) {
++		if (*state & HT_ADDBA_RECEIVED_MSK)
++			printk(KERN_DEBUG "double addBA response\n");
++
++		*state |= HT_ADDBA_RECEIVED_MSK;
++		sta->ampdu_mlme.addba_req_num[tid] = 0;
++
++		if (*state == HT_AGG_STATE_OPERATIONAL) {
++			printk(KERN_DEBUG "Aggregation on for tid %d \n", tid);
++			ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
++		}
++
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++		printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid);
++	} else {
++		printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid);
++
++		sta->ampdu_mlme.addba_req_num[tid]++;
++		/* this will allow the state check in stop_BA_session */
++		*state = HT_AGG_STATE_OPERATIONAL;
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++		ieee80211_stop_tx_ba_session(hw, sta->addr, tid,
++					     WLAN_BACK_INITIATOR);
++	}
++
++addba_resp_exit:
++	rcu_read_unlock();
++}
++
++void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
++			  u16 initiator, u16 reason_code)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *mgmt;
++	u16 params;
++
++	skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
++					sizeof(mgmt->u.action.u.delba));
++
++	if (!skb) {
++		printk(KERN_ERR "%s: failed to allocate buffer "
++					"for delba frame\n", dev->name);
++		return;
++	}
++
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++	memset(mgmt, 0, 24);
++	memcpy(mgmt->da, da, ETH_ALEN);
++	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
++		memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
++	else
++		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					IEEE80211_STYPE_ACTION);
++
++	skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
++
++	mgmt->u.action.category = WLAN_CATEGORY_BACK;
++	mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
++	params = (u16)(initiator << 11); 	/* bit 11 initiator */
++	params |= (u16)(tid << 12); 		/* bit 15:12 TID number */
++
++	mgmt->u.action.u.delba.params = cpu_to_le16(params);
++	mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
++
++	ieee80211_sta_tx(dev, skb, 0);
++}
++
++void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
++					u16 initiator, u16 reason)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_hw *hw = &local->hw;
++	struct sta_info *sta;
++	int ret, i;
++	DECLARE_MAC_BUF(mac);
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, ra);
++	if (!sta) {
++		rcu_read_unlock();
++		return;
++	}
++
++	/* check if TID is in operational state */
++	spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
++	if (sta->ampdu_mlme.tid_state_rx[tid]
++				!= HT_AGG_STATE_OPERATIONAL) {
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
++		rcu_read_unlock();
++		return;
++	}
++	sta->ampdu_mlme.tid_state_rx[tid] =
++		HT_AGG_STATE_REQ_STOP_BA_MSK |
++		(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
++	spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
++
++	/* stop HW Rx aggregation. ampdu_action existence
++	 * already verified in session init so we add the BUG_ON */
++	BUG_ON(!local->ops->ampdu_action);
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++	printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n",
++				print_mac(mac, ra), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++	ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
++					ra, tid, NULL);
++	if (ret)
++		printk(KERN_DEBUG "HW problem - can not stop rx "
++				"aggergation for tid %d\n", tid);
++
++	/* shutdown timer has not expired */
++	if (initiator != WLAN_BACK_TIMER)
++		del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
++
++	/* check if this is a self generated aggregation halt */
++	if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
++		ieee80211_send_delba(dev, ra, tid, 0, reason);
++
++	/* free the reordering buffer */
++	for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
++		if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
++			/* release the reordered frames */
++			dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
++			sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
++			sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
++		}
++	}
++	/* free resources */
++	kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
++	kfree(sta->ampdu_mlme.tid_rx[tid]);
++	sta->ampdu_mlme.tid_rx[tid] = NULL;
++	sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
++
++	rcu_read_unlock();
++}
++
++
++static void ieee80211_sta_process_delba(struct net_device *dev,
++			struct ieee80211_mgmt *mgmt, size_t len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sta_info *sta;
++	u16 tid, params;
++	u16 initiator;
++	DECLARE_MAC_BUF(mac);
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, mgmt->sa);
++	if (!sta) {
++		rcu_read_unlock();
++		return;
++	}
++
++	params = le16_to_cpu(mgmt->u.action.u.delba.params);
++	tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
++	initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++	if (net_ratelimit())
++		printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n",
++			print_mac(mac, mgmt->sa),
++			initiator ? "initiator" : "recipient", tid,
++			mgmt->u.action.u.delba.reason_code);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++	if (initiator == WLAN_BACK_INITIATOR)
++		ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid,
++						 WLAN_BACK_INITIATOR, 0);
++	else { /* WLAN_BACK_RECIPIENT */
++		spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++		sta->ampdu_mlme.tid_state_tx[tid] =
++				HT_AGG_STATE_OPERATIONAL;
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++		ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid,
++					     WLAN_BACK_RECIPIENT);
++	}
++	rcu_read_unlock();
++}
++
++/*
++ * After sending add Block Ack request we activated a timer until
++ * add Block Ack response will arrive from the recipient.
++ * If this timer expires sta_addba_resp_timer_expired will be executed.
++ */
++void sta_addba_resp_timer_expired(unsigned long data)
++{
++	/* not an elegant detour, but there is no choice as the timer passes
++	 * only one argument, and both sta_info and TID are needed, so init
++	 * flow in sta_info_create gives the TID as data, while the timer_to_id
++	 * array gives the sta through container_of */
++	u16 tid = *(int *)data;
++	struct sta_info *temp_sta = container_of((void *)data,
++		struct sta_info, timer_to_tid[tid]);
++
++	struct ieee80211_local *local = temp_sta->local;
++	struct ieee80211_hw *hw = &local->hw;
++	struct sta_info *sta;
++	u8 *state;
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, temp_sta->addr);
++	if (!sta) {
++		rcu_read_unlock();
++		return;
++	}
++
++	state = &sta->ampdu_mlme.tid_state_tx[tid];
++	/* check if the TID waits for addBA response */
++	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++		*state = HT_AGG_STATE_IDLE;
++		printk(KERN_DEBUG "timer expired on tid %d but we are not "
++				"expecting addBA response there", tid);
++		goto timer_expired_exit;
++	}
++
++	printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
++
++	/* go through the state check in stop_BA_session */
++	*state = HT_AGG_STATE_OPERATIONAL;
++	spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++	ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid,
++				     WLAN_BACK_INITIATOR);
++
++timer_expired_exit:
++	rcu_read_unlock();
++}
++
++/*
++ * After accepting the AddBA Request we activated a timer,
++ * resetting it after each frame that arrives from the originator.
++ * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
++ */
++void sta_rx_agg_session_timer_expired(unsigned long data)
++{
++	/* not an elegant detour, but there is no choice as the timer passes
++	 * only one argument, and verious sta_info are needed here, so init
++	 * flow in sta_info_create gives the TID as data, while the timer_to_id
++	 * array gives the sta through container_of */
++	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]);
++
++	printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
++	ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
++					 (u16)*ptid, WLAN_BACK_TIMER,
++					 WLAN_REASON_QSTA_TIMEOUT);
++}
++
++void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	int i;
++
++	for (i = 0; i <  STA_TID_NUM; i++) {
++		ieee80211_stop_tx_ba_session(&local->hw, addr, i,
++					     WLAN_BACK_INITIATOR);
++		ieee80211_sta_stop_rx_ba_session(dev, addr, i,
++						 WLAN_BACK_RECIPIENT,
++						 WLAN_REASON_QSTA_LEAVE_QBSS);
++	}
++}
++
++static void ieee80211_rx_mgmt_auth(struct net_device *dev,
++				   struct ieee80211_if_sta *ifsta,
++				   struct ieee80211_mgmt *mgmt,
++				   size_t len)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	u16 auth_alg, auth_transaction, status_code;
++	DECLARE_MAC_BUF(mac);
++
++	if (ifsta->state != IEEE80211_AUTHENTICATE &&
++	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
++		printk(KERN_DEBUG "%s: authentication frame received from "
++		       "%s, but not in authenticate state - ignored\n",
++		       dev->name, print_mac(mac, mgmt->sa));
++		return;
++	}
++
++	if (len < 24 + 6) {
++		printk(KERN_DEBUG "%s: too short (%zd) authentication frame "
++		       "received from %s - ignored\n",
++		       dev->name, len, print_mac(mac, mgmt->sa));
++		return;
++	}
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++	    memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
++		printk(KERN_DEBUG "%s: authentication frame received from "
++		       "unknown AP (SA=%s BSSID=%s) - "
++		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++		       print_mac(mac, mgmt->bssid));
++		return;
++	}
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
++		printk(KERN_DEBUG "%s: authentication frame received from "
++		       "unknown BSSID (SA=%s BSSID=%s) - "
++		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++		       print_mac(mac, mgmt->bssid));
++		return;
++	}
++
++	auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
++	auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
++	status_code = le16_to_cpu(mgmt->u.auth.status_code);
++
++	printk(KERN_DEBUG "%s: RX authentication from %s (alg=%d "
++	       "transaction=%d status=%d)\n",
++	       dev->name, print_mac(mac, mgmt->sa), auth_alg,
++	       auth_transaction, status_code);
++
++	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++		/* IEEE 802.11 standard does not require authentication in IBSS
++		 * networks and most implementations do not seem to use it.
++		 * However, try to reply to authentication attempts if someone
++		 * has actually implemented this.
++		 * TODO: Could implement shared key authentication. */
++		if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
++			printk(KERN_DEBUG "%s: unexpected IBSS authentication "
++			       "frame (alg=%d transaction=%d)\n",
++			       dev->name, auth_alg, auth_transaction);
++			return;
++		}
++		ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0);
++	}
++
++	if (auth_alg != ifsta->auth_alg ||
++	    auth_transaction != ifsta->auth_transaction) {
++		printk(KERN_DEBUG "%s: unexpected authentication frame "
++		       "(alg=%d transaction=%d)\n",
++		       dev->name, auth_alg, auth_transaction);
++		return;
++	}
++
++	if (status_code != WLAN_STATUS_SUCCESS) {
++		printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d "
++		       "code=%d)\n", dev->name, ifsta->auth_alg, status_code);
++		if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
++			u8 algs[3];
++			const int num_algs = ARRAY_SIZE(algs);
++			int i, pos;
++			algs[0] = algs[1] = algs[2] = 0xff;
++			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
++				algs[0] = WLAN_AUTH_OPEN;
++			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
++				algs[1] = WLAN_AUTH_SHARED_KEY;
++			if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
++				algs[2] = WLAN_AUTH_LEAP;
++			if (ifsta->auth_alg == WLAN_AUTH_OPEN)
++				pos = 0;
++			else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY)
++				pos = 1;
++			else
++				pos = 2;
++			for (i = 0; i < num_algs; i++) {
++				pos++;
++				if (pos >= num_algs)
++					pos = 0;
++				if (algs[pos] == ifsta->auth_alg ||
++				    algs[pos] == 0xff)
++					continue;
++				if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
++				    !ieee80211_sta_wep_configured(dev))
++					continue;
++				ifsta->auth_alg = algs[pos];
++				printk(KERN_DEBUG "%s: set auth_alg=%d for "
++				       "next try\n",
++				       dev->name, ifsta->auth_alg);
++				break;
++			}
++		}
++		return;
++	}
++
++	switch (ifsta->auth_alg) {
++	case WLAN_AUTH_OPEN:
++	case WLAN_AUTH_LEAP:
++		ieee80211_auth_completed(dev, ifsta);
++		break;
++	case WLAN_AUTH_SHARED_KEY:
++		if (ifsta->auth_transaction == 4)
++			ieee80211_auth_completed(dev, ifsta);
++		else
++			ieee80211_auth_challenge(dev, ifsta, mgmt, len);
++		break;
++	}
++}
++
++
++static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta,
++				     struct ieee80211_mgmt *mgmt,
++				     size_t len)
++{
++	u16 reason_code;
++	DECLARE_MAC_BUF(mac);
++
++	if (len < 24 + 2) {
++		printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame "
++		       "received from %s - ignored\n",
++		       dev->name, len, print_mac(mac, mgmt->sa));
++		return;
++	}
++
++	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
++		printk(KERN_DEBUG "%s: deauthentication frame received from "
++		       "unknown AP (SA=%s BSSID=%s) - "
++		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++		       print_mac(mac, mgmt->bssid));
++		return;
++	}
++
++	reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
++
++	printk(KERN_DEBUG "%s: RX deauthentication from %s"
++	       " (reason=%d)\n",
++	       dev->name, print_mac(mac, mgmt->sa), reason_code);
++
++	if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) {
++		printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
++	}
++
++	if (ifsta->state == IEEE80211_AUTHENTICATE ||
++	    ifsta->state == IEEE80211_ASSOCIATE ||
++	    ifsta->state == IEEE80211_ASSOCIATED) {
++		ifsta->state = IEEE80211_AUTHENTICATE;
++		mod_timer(&ifsta->timer, jiffies +
++				      IEEE80211_RETRY_AUTH_INTERVAL);
++	}
++
++	ieee80211_set_disassoc(dev, ifsta, 1);
++	ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
++}
++
++
++static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
++				       struct ieee80211_if_sta *ifsta,
++				       struct ieee80211_mgmt *mgmt,
++				       size_t len)
++{
++	u16 reason_code;
++	DECLARE_MAC_BUF(mac);
++
++	if (len < 24 + 2) {
++		printk(KERN_DEBUG "%s: too short (%zd) disassociation frame "
++		       "received from %s - ignored\n",
++		       dev->name, len, print_mac(mac, mgmt->sa));
++		return;
++	}
++
++	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
++		printk(KERN_DEBUG "%s: disassociation frame received from "
++		       "unknown AP (SA=%s BSSID=%s) - "
++		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++		       print_mac(mac, mgmt->bssid));
++		return;
++	}
++
++	reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
++
++	printk(KERN_DEBUG "%s: RX disassociation from %s"
++	       " (reason=%d)\n",
++	       dev->name, print_mac(mac, mgmt->sa), reason_code);
++
++	if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
++		printk(KERN_DEBUG "%s: disassociated\n", dev->name);
++
++	if (ifsta->state == IEEE80211_ASSOCIATED) {
++		ifsta->state = IEEE80211_ASSOCIATE;
++		mod_timer(&ifsta->timer, jiffies +
++				      IEEE80211_RETRY_AUTH_INTERVAL);
++	}
++
++	ieee80211_set_disassoc(dev, ifsta, 0);
++}
++
++
++static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
++					 struct ieee80211_if_sta *ifsta,
++					 struct ieee80211_mgmt *mgmt,
++					 size_t len,
++					 int reassoc)
++{
++	struct ieee80211_local *local = sdata->local;
++	struct net_device *dev = sdata->dev;
++	struct ieee80211_supported_band *sband;
++	struct sta_info *sta;
++	u64 rates, basic_rates;
++	u16 capab_info, status_code, aid;
++	struct ieee802_11_elems elems;
++	struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
++	u8 *pos;
++	int i, j;
++	DECLARE_MAC_BUF(mac);
++	bool have_higher_than_11mbit = false;
++
++	/* AssocResp and ReassocResp have identical structure, so process both
++	 * of them in this function. */
++
++	if (ifsta->state != IEEE80211_ASSOCIATE) {
++		printk(KERN_DEBUG "%s: association frame received from "
++		       "%s, but not in associate state - ignored\n",
++		       dev->name, print_mac(mac, mgmt->sa));
++		return;
++	}
++
++	if (len < 24 + 6) {
++		printk(KERN_DEBUG "%s: too short (%zd) association frame "
++		       "received from %s - ignored\n",
++		       dev->name, len, print_mac(mac, mgmt->sa));
++		return;
++	}
++
++	if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
++		printk(KERN_DEBUG "%s: association frame received from "
++		       "unknown AP (SA=%s BSSID=%s) - "
++		       "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++		       print_mac(mac, mgmt->bssid));
++		return;
++	}
++
++	capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
++	status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
++	aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
++
++	printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
++	       "status=%d aid=%d)\n",
++	       dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
++	       capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
++
++	if (status_code != WLAN_STATUS_SUCCESS) {
++		printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
++		       dev->name, status_code);
++		/* if this was a reassociation, ensure we try a "full"
++		 * association next time. This works around some broken APs
++		 * which do not correctly reject reassociation requests. */
++		ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
++		return;
++	}
++
++	if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
++		printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
++		       "set\n", dev->name, aid);
++	aid &= ~(BIT(15) | BIT(14));
++
++	pos = mgmt->u.assoc_resp.variable;
++	ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
++
++	if (!elems.supp_rates) {
++		printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
++		       dev->name);
++		return;
++	}
++
++	printk(KERN_DEBUG "%s: associated\n", dev->name);
++	ifsta->aid = aid;
++	ifsta->ap_capab = capab_info;
++
++	kfree(ifsta->assocresp_ies);
++	ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
++	ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL);
++	if (ifsta->assocresp_ies)
++		memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
++
++	rcu_read_lock();
++
++	/* Add STA entry for the AP */
++	sta = sta_info_get(local, ifsta->bssid);
++	if (!sta) {
++		struct ieee80211_sta_bss *bss;
++		int err;
++
++		sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
++		if (!sta) {
++			printk(KERN_DEBUG "%s: failed to alloc STA entry for"
++			       " the AP\n", dev->name);
++			rcu_read_unlock();
++			return;
++		}
++		bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++					   local->hw.conf.channel->center_freq,
++					   ifsta->ssid, ifsta->ssid_len);
++		if (bss) {
++			sta->last_rssi = bss->rssi;
++			sta->last_signal = bss->signal;
++			sta->last_noise = bss->noise;
++			ieee80211_rx_bss_put(dev, bss);
++		}
++
++		err = sta_info_insert(sta);
++		if (err) {
++			printk(KERN_DEBUG "%s: failed to insert STA entry for"
++			       " the AP (error %d)\n", dev->name, err);
++			rcu_read_unlock();
++			return;
++		}
++	}
++
++	/*
++	 * FIXME: Do we really need to update the sta_info's information here?
++	 *	  We already know about the AP (we found it in our list) so it
++	 *	  should already be filled with the right info, no?
++	 *	  As is stands, all this is racy because typically we assume
++	 *	  the information that is filled in here (except flags) doesn't
++	 *	  change while a STA structure is alive. As such, it should move
++	 *	  to between the sta_info_alloc() and sta_info_insert() above.
++	 */
++
++	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
++		      WLAN_STA_AUTHORIZED;
++
++	rates = 0;
++	basic_rates = 0;
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++	for (i = 0; i < elems.supp_rates_len; i++) {
++		int rate = (elems.supp_rates[i] & 0x7f) * 5;
++
++		if (rate > 110)
++			have_higher_than_11mbit = true;
++
++		for (j = 0; j < sband->n_bitrates; j++) {
++			if (sband->bitrates[j].bitrate == rate)
++				rates |= BIT(j);
++			if (elems.supp_rates[i] & 0x80)
++				basic_rates |= BIT(j);
++		}
++	}
++
++	for (i = 0; i < elems.ext_supp_rates_len; i++) {
++		int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
++
++		if (rate > 110)
++			have_higher_than_11mbit = true;
++
++		for (j = 0; j < sband->n_bitrates; j++) {
++			if (sband->bitrates[j].bitrate == rate)
++				rates |= BIT(j);
++			if (elems.ext_supp_rates[i] & 0x80)
++				basic_rates |= BIT(j);
++		}
++	}
++
++	sta->supp_rates[local->hw.conf.channel->band] = rates;
++	sdata->basic_rates = basic_rates;
++
++	/* cf. IEEE 802.11 9.2.12 */
++	if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
++	    have_higher_than_11mbit)
++		sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
++	else
++		sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
++
++	if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
++		struct ieee80211_ht_bss_info bss_info;
++		ieee80211_ht_cap_ie_to_ht_info(
++				(struct ieee80211_ht_cap *)
++				elems.ht_cap_elem, &sta->ht_info);
++		ieee80211_ht_addt_info_ie_to_ht_bss_info(
++				(struct ieee80211_ht_addt_info *)
++				elems.ht_info_elem, &bss_info);
++		ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info);
++	}
++
++	rate_control_rate_init(sta, local);
++
++	if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
++		sta->flags |= WLAN_STA_WME;
++		rcu_read_unlock();
++		ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
++					 elems.wmm_param_len);
++	} else
++		rcu_read_unlock();
++
++	/* set AID and assoc capability,
++	 * ieee80211_set_associated() will tell the driver */
++	bss_conf->aid = aid;
++	bss_conf->assoc_capability = capab_info;
++	ieee80211_set_associated(dev, ifsta, 1);
++
++	ieee80211_associated(dev, ifsta);
++}
++
++
++/* Caller must hold local->sta_bss_lock */
++static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
++					struct ieee80211_sta_bss *bss)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	u8 hash_idx;
++
++	if (bss_mesh_cfg(bss))
++		hash_idx = mesh_id_hash(bss_mesh_id(bss),
++					bss_mesh_id_len(bss));
++	else
++		hash_idx = STA_HASH(bss->bssid);
++
++	bss->hnext = local->sta_bss_hash[hash_idx];
++	local->sta_bss_hash[hash_idx] = bss;
++}
++
++
++/* Caller must hold local->sta_bss_lock */
++static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
++					struct ieee80211_sta_bss *bss)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sta_bss *b, *prev = NULL;
++	b = local->sta_bss_hash[STA_HASH(bss->bssid)];
++	while (b) {
++		if (b == bss) {
++			if (!prev)
++				local->sta_bss_hash[STA_HASH(bss->bssid)] =
++					bss->hnext;
++			else
++				prev->hnext = bss->hnext;
++			break;
++		}
++		prev = b;
++		b = b->hnext;
++	}
++}
++
++
++static struct ieee80211_sta_bss *
++ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq,
++		     u8 *ssid, u8 ssid_len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sta_bss *bss;
++
++	bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
++	if (!bss)
++		return NULL;
++	atomic_inc(&bss->users);
++	atomic_inc(&bss->users);
++	memcpy(bss->bssid, bssid, ETH_ALEN);
++	bss->freq = freq;
++	if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
++		memcpy(bss->ssid, ssid, ssid_len);
++		bss->ssid_len = ssid_len;
++	}
++
++	spin_lock_bh(&local->sta_bss_lock);
++	/* TODO: order by RSSI? */
++	list_add_tail(&bss->list, &local->sta_bss_list);
++	__ieee80211_rx_bss_hash_add(dev, bss);
++	spin_unlock_bh(&local->sta_bss_lock);
++	return bss;
++}
++
++static struct ieee80211_sta_bss *
++ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
++		     u8 *ssid, u8 ssid_len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sta_bss *bss;
++
++	spin_lock_bh(&local->sta_bss_lock);
++	bss = local->sta_bss_hash[STA_HASH(bssid)];
++	while (bss) {
++		if (!bss_mesh_cfg(bss) &&
++		    !memcmp(bss->bssid, bssid, ETH_ALEN) &&
++		    bss->freq == freq &&
++		    bss->ssid_len == ssid_len &&
++		    (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
++			atomic_inc(&bss->users);
++			break;
++		}
++		bss = bss->hnext;
++	}
++	spin_unlock_bh(&local->sta_bss_lock);
++	return bss;
++}
++
++#ifdef CONFIG_MAC80211_MESH
++static struct ieee80211_sta_bss *
++ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len,
++			  u8 *mesh_cfg, int freq)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sta_bss *bss;
++
++	spin_lock_bh(&local->sta_bss_lock);
++	bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
++	while (bss) {
++		if (bss_mesh_cfg(bss) &&
++		    !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) &&
++		    bss->freq == freq &&
++		    mesh_id_len == bss->mesh_id_len &&
++		    (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id,
++						 mesh_id_len))) {
++			atomic_inc(&bss->users);
++			break;
++		}
++		bss = bss->hnext;
++	}
++	spin_unlock_bh(&local->sta_bss_lock);
++	return bss;
++}
++
++static struct ieee80211_sta_bss *
++ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len,
++			  u8 *mesh_cfg, int mesh_config_len, int freq)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sta_bss *bss;
++
++	if (mesh_config_len != MESH_CFG_LEN)
++		return NULL;
++
++	bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
++	if (!bss)
++		return NULL;
++
++	bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC);
++	if (!bss->mesh_cfg) {
++		kfree(bss);
++		return NULL;
++	}
++
++	if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) {
++		bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC);
++		if (!bss->mesh_id) {
++			kfree(bss->mesh_cfg);
++			kfree(bss);
++			return NULL;
++		}
++		memcpy(bss->mesh_id, mesh_id, mesh_id_len);
++	}
++
++	atomic_inc(&bss->users);
++	atomic_inc(&bss->users);
++	memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
++	bss->mesh_id_len = mesh_id_len;
++	bss->freq = freq;
++	spin_lock_bh(&local->sta_bss_lock);
++	/* TODO: order by RSSI? */
++	list_add_tail(&bss->list, &local->sta_bss_list);
++	__ieee80211_rx_bss_hash_add(dev, bss);
++	spin_unlock_bh(&local->sta_bss_lock);
++	return bss;
++}
++#endif
++
++static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
++{
++	kfree(bss->wpa_ie);
++	kfree(bss->rsn_ie);
++	kfree(bss->wmm_ie);
++	kfree(bss->ht_ie);
++	kfree(bss_mesh_id(bss));
++	kfree(bss_mesh_cfg(bss));
++	kfree(bss);
++}
++
++
++static void ieee80211_rx_bss_put(struct net_device *dev,
++				 struct ieee80211_sta_bss *bss)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	local_bh_disable();
++	if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) {
++		local_bh_enable();
++		return;
++	}
++
++	__ieee80211_rx_bss_hash_del(dev, bss);
++	list_del(&bss->list);
++	spin_unlock_bh(&local->sta_bss_lock);
++	ieee80211_rx_bss_free(bss);
++}
++
++
++void ieee80211_rx_bss_list_init(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	spin_lock_init(&local->sta_bss_lock);
++	INIT_LIST_HEAD(&local->sta_bss_list);
++}
++
++
++void ieee80211_rx_bss_list_deinit(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sta_bss *bss, *tmp;
++
++	list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
++		ieee80211_rx_bss_put(dev, bss);
++}
++
++
++static int ieee80211_sta_join_ibss(struct net_device *dev,
++				   struct ieee80211_if_sta *ifsta,
++				   struct ieee80211_sta_bss *bss)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	int res, rates, i, j;
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *mgmt;
++	struct ieee80211_tx_control control;
++	struct rate_selection ratesel;
++	u8 *pos;
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_supported_band *sband;
++
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	/* Remove possible STA entries from other IBSS networks. */
++	sta_info_flush_delayed(sdata);
++
++	if (local->ops->reset_tsf) {
++		/* Reset own TSF to allow time synchronization work. */
++		local->ops->reset_tsf(local_to_hw(local));
++	}
++	memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
++	res = ieee80211_if_config(dev);
++	if (res)
++		return res;
++
++	local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
++
++	sdata->drop_unencrypted = bss->capability &
++		WLAN_CAPABILITY_PRIVACY ? 1 : 0;
++
++	res = ieee80211_set_freq(local, bss->freq);
++
++	if (local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS) {
++		printk(KERN_DEBUG "%s: IBSS not allowed on frequency "
++		       "%d MHz\n", dev->name, local->oper_channel->center_freq);
++		return -1;
++	}
++
++	/* Set beacon template */
++	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
++	do {
++		if (!skb)
++			break;
++
++		skb_reserve(skb, local->hw.extra_tx_headroom);
++
++		mgmt = (struct ieee80211_mgmt *)
++			skb_put(skb, 24 + sizeof(mgmt->u.beacon));
++		memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
++		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++						   IEEE80211_STYPE_BEACON);
++		memset(mgmt->da, 0xff, ETH_ALEN);
++		memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++		mgmt->u.beacon.beacon_int =
++			cpu_to_le16(local->hw.conf.beacon_int);
++		mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
++
++		pos = skb_put(skb, 2 + ifsta->ssid_len);
++		*pos++ = WLAN_EID_SSID;
++		*pos++ = ifsta->ssid_len;
++		memcpy(pos, ifsta->ssid, ifsta->ssid_len);
++
++		rates = bss->supp_rates_len;
++		if (rates > 8)
++			rates = 8;
++		pos = skb_put(skb, 2 + rates);
++		*pos++ = WLAN_EID_SUPP_RATES;
++		*pos++ = rates;
++		memcpy(pos, bss->supp_rates, rates);
++
++		if (bss->band == IEEE80211_BAND_2GHZ) {
++			pos = skb_put(skb, 2 + 1);
++			*pos++ = WLAN_EID_DS_PARAMS;
++			*pos++ = 1;
++			*pos++ = ieee80211_frequency_to_channel(bss->freq);
++		}
++
++		pos = skb_put(skb, 2 + 2);
++		*pos++ = WLAN_EID_IBSS_PARAMS;
++		*pos++ = 2;
++		/* FIX: set ATIM window based on scan results */
++		*pos++ = 0;
++		*pos++ = 0;
++
++		if (bss->supp_rates_len > 8) {
++			rates = bss->supp_rates_len - 8;
++			pos = skb_put(skb, 2 + rates);
++			*pos++ = WLAN_EID_EXT_SUPP_RATES;
++			*pos++ = rates;
++			memcpy(pos, &bss->supp_rates[8], rates);
++		}
++
++		memset(&control, 0, sizeof(control));
++		rate_control_get_rate(dev, sband, skb, &ratesel);
++		if (!ratesel.rate) {
++			printk(KERN_DEBUG "%s: Failed to determine TX rate "
++			       "for IBSS beacon\n", dev->name);
++			break;
++		}
++		control.vif = &sdata->vif;
++		control.tx_rate = ratesel.rate;
++		if (sdata->bss_conf.use_short_preamble &&
++		    ratesel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
++			control.flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
++		control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
++		control.flags |= IEEE80211_TXCTL_NO_ACK;
++		control.retry_limit = 1;
++
++		ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
++		if (ifsta->probe_resp) {
++			mgmt = (struct ieee80211_mgmt *)
++				ifsta->probe_resp->data;
++			mgmt->frame_control =
++				IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++					     IEEE80211_STYPE_PROBE_RESP);
++		} else {
++			printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
++			       "template for IBSS\n", dev->name);
++		}
++
++		if (local->ops->beacon_update &&
++		    local->ops->beacon_update(local_to_hw(local),
++					     skb, &control) == 0) {
++			printk(KERN_DEBUG "%s: Configured IBSS beacon "
++			       "template\n", dev->name);
++			skb = NULL;
++		}
++
++		rates = 0;
++		sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++		for (i = 0; i < bss->supp_rates_len; i++) {
++			int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
++			for (j = 0; j < sband->n_bitrates; j++)
++				if (sband->bitrates[j].bitrate == bitrate)
++					rates |= BIT(j);
++		}
++		ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;
++
++		ieee80211_sta_def_wmm_params(dev, bss, 1);
++	} while (0);
++
++	if (skb) {
++		printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
++		       "template\n", dev->name);
++		dev_kfree_skb(skb);
++	}
++
++	ifsta->state = IEEE80211_IBSS_JOINED;
++	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
++
++	ieee80211_rx_bss_put(dev, bss);
++
++	return res;
++}
++
++u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
++			    struct ieee802_11_elems *elems,
++			    enum ieee80211_band band)
++{
++	struct ieee80211_supported_band *sband;
++	struct ieee80211_rate *bitrates;
++	size_t num_rates;
++	u64 supp_rates;
++	int i, j;
++	sband = local->hw.wiphy->bands[band];
++
++	if (!sband) {
++		WARN_ON(1);
++		sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++	}
++
++	bitrates = sband->bitrates;
++	num_rates = sband->n_bitrates;
++	supp_rates = 0;
++	for (i = 0; i < elems->supp_rates_len +
++		     elems->ext_supp_rates_len; i++) {
++		u8 rate = 0;
++		int own_rate;
++		if (i < elems->supp_rates_len)
++			rate = elems->supp_rates[i];
++		else if (elems->ext_supp_rates)
++			rate = elems->ext_supp_rates
++				[i - elems->supp_rates_len];
++		own_rate = 5 * (rate & 0x7f);
++		for (j = 0; j < num_rates; j++)
++			if (bitrates[j].bitrate == own_rate)
++				supp_rates |= BIT(j);
++	}
++	return supp_rates;
++}
++
++
++static void ieee80211_rx_bss_info(struct net_device *dev,
++				  struct ieee80211_mgmt *mgmt,
++				  size_t len,
++				  struct ieee80211_rx_status *rx_status,
++				  int beacon)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee802_11_elems elems;
++	size_t baselen;
++	int freq, clen;
++	struct ieee80211_sta_bss *bss;
++	struct sta_info *sta;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	u64 beacon_timestamp, rx_timestamp;
++	struct ieee80211_channel *channel;
++	DECLARE_MAC_BUF(mac);
++	DECLARE_MAC_BUF(mac2);
++
++	if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
++		return; /* ignore ProbeResp to foreign address */
++
++#if 0
++	printk(KERN_DEBUG "%s: RX %s from %s to %s\n",
++	       dev->name, beacon ? "Beacon" : "Probe Response",
++	       print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da));
++#endif
++
++	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
++	if (baselen > len)
++		return;
++
++	beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
++	ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
++
++	if (ieee80211_vif_is_mesh(&sdata->vif) && elems.mesh_id &&
++	    elems.mesh_config && mesh_matches_local(&elems, dev)) {
++		u64 rates = ieee80211_sta_get_rates(local, &elems,
++						rx_status->band);
++
++		mesh_neighbour_update(mgmt->sa, rates, dev,
++				      mesh_peer_accepts_plinks(&elems, dev));
++	}
++
++	rcu_read_lock();
++
++	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
++	    memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
++	    (sta = sta_info_get(local, mgmt->sa))) {
++		u64 prev_rates;
++		u64 supp_rates = ieee80211_sta_get_rates(local, &elems,
++							rx_status->band);
++
++		prev_rates = sta->supp_rates[rx_status->band];
++		sta->supp_rates[rx_status->band] &= supp_rates;
++		if (sta->supp_rates[rx_status->band] == 0) {
++			/* No matching rates - this should not really happen.
++			 * Make sure that at least one rate is marked
++			 * supported to avoid issues with TX rate ctrl. */
++			sta->supp_rates[rx_status->band] =
++				sdata->u.sta.supp_rates_bits[rx_status->band];
++		}
++		if (sta->supp_rates[rx_status->band] != prev_rates) {
++			printk(KERN_DEBUG "%s: updated supp_rates set for "
++			       "%s based on beacon info (0x%llx & 0x%llx -> "
++			       "0x%llx)\n",
++			       dev->name, print_mac(mac, sta->addr),
++			       (unsigned long long) prev_rates,
++			       (unsigned long long) supp_rates,
++			       (unsigned long long) sta->supp_rates[rx_status->band]);
++		}
++	}
++
++	rcu_read_unlock();
++
++	if (elems.ds_params && elems.ds_params_len == 1)
++		freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
++	else
++		freq = rx_status->freq;
++
++	channel = ieee80211_get_channel(local->hw.wiphy, freq);
++
++	if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
++		return;
++
++#ifdef CONFIG_MAC80211_MESH
++	if (elems.mesh_config)
++		bss = ieee80211_rx_mesh_bss_get(dev, elems.mesh_id,
++				elems.mesh_id_len, elems.mesh_config, freq);
++	else
++#endif
++		bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq,
++					   elems.ssid, elems.ssid_len);
++	if (!bss) {
++#ifdef CONFIG_MAC80211_MESH
++		if (elems.mesh_config)
++			bss = ieee80211_rx_mesh_bss_add(dev, elems.mesh_id,
++				elems.mesh_id_len, elems.mesh_config,
++				elems.mesh_config_len, freq);
++		else
++#endif
++			bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq,
++						   elems.ssid, elems.ssid_len);
++		if (!bss)
++			return;
++	} else {
++#if 0
++		/* TODO: order by RSSI? */
++		spin_lock_bh(&local->sta_bss_lock);
++		list_move_tail(&bss->list, &local->sta_bss_list);
++		spin_unlock_bh(&local->sta_bss_lock);
++#endif
++	}
++
++	/* save the ERP value so that it is available at association time */
++	if (elems.erp_info && elems.erp_info_len >= 1) {
++		bss->erp_value = elems.erp_info[0];
++		bss->has_erp_value = 1;
++	}
++
++	if (elems.ht_cap_elem &&
++	     (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
++	     memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
++		kfree(bss->ht_ie);
++		bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
++		if (bss->ht_ie) {
++			memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
++				elems.ht_cap_elem_len + 2);
++			bss->ht_ie_len = elems.ht_cap_elem_len + 2;
++		} else
++			bss->ht_ie_len = 0;
++	} else if (!elems.ht_cap_elem && bss->ht_ie) {
++		kfree(bss->ht_ie);
++		bss->ht_ie = NULL;
++		bss->ht_ie_len = 0;
++	}
++
++	bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
++	bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
++
++	bss->supp_rates_len = 0;
++	if (elems.supp_rates) {
++		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
++		if (clen > elems.supp_rates_len)
++			clen = elems.supp_rates_len;
++		memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates,
++		       clen);
++		bss->supp_rates_len += clen;
++	}
++	if (elems.ext_supp_rates) {
++		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
++		if (clen > elems.ext_supp_rates_len)
++			clen = elems.ext_supp_rates_len;
++		memcpy(&bss->supp_rates[bss->supp_rates_len],
++		       elems.ext_supp_rates, clen);
++		bss->supp_rates_len += clen;
++	}
++
++	bss->band = rx_status->band;
++
++	bss->timestamp = beacon_timestamp;
++	bss->last_update = jiffies;
++	bss->rssi = rx_status->ssi;
++	bss->signal = rx_status->signal;
++	bss->noise = rx_status->noise;
++	if (!beacon && !bss->probe_resp)
++		bss->probe_resp = true;
++
++	/*
++	 * In STA mode, the remaining parameters should not be overridden
++	 * by beacons because they're not necessarily accurate there.
++	 */
++	if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++	    bss->probe_resp && beacon) {
++		ieee80211_rx_bss_put(dev, bss);
++		return;
++	}
++
++	if (elems.wpa &&
++	    (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
++	     memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
++		kfree(bss->wpa_ie);
++		bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);
++		if (bss->wpa_ie) {
++			memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2);
++			bss->wpa_ie_len = elems.wpa_len + 2;
++		} else
++			bss->wpa_ie_len = 0;
++	} else if (!elems.wpa && bss->wpa_ie) {
++		kfree(bss->wpa_ie);
++		bss->wpa_ie = NULL;
++		bss->wpa_ie_len = 0;
++	}
++
++	if (elems.rsn &&
++	    (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||
++	     memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
++		kfree(bss->rsn_ie);
++		bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);
++		if (bss->rsn_ie) {
++			memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2);
++			bss->rsn_ie_len = elems.rsn_len + 2;
++		} else
++			bss->rsn_ie_len = 0;
++	} else if (!elems.rsn && bss->rsn_ie) {
++		kfree(bss->rsn_ie);
++		bss->rsn_ie = NULL;
++		bss->rsn_ie_len = 0;
++	}
++
++	/*
++	 * Cf.
++	 * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC
++	 *
++	 * quoting:
++	 *
++	 * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia
++	 * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi
++	 * Alliance (September 1, 2004) is incorporated by reference herein.
++	 * The inclusion of the WMM Parameters in probe responses and
++	 * association responses is mandatory for WMM enabled networks. The
++	 * inclusion of the WMM Parameters in beacons, however, is optional.
++	 */
++
++	if (elems.wmm_param &&
++	    (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
++	     memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
++		kfree(bss->wmm_ie);
++		bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);
++		if (bss->wmm_ie) {
++			memcpy(bss->wmm_ie, elems.wmm_param - 2,
++			       elems.wmm_param_len + 2);
++			bss->wmm_ie_len = elems.wmm_param_len + 2;
++		} else
++			bss->wmm_ie_len = 0;
++	} else if (elems.wmm_info &&
++		    (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_info_len ||
++		     memcmp(bss->wmm_ie, elems.wmm_info, elems.wmm_info_len))) {
++		 /* As for certain AP's Fifth bit is not set in WMM IE in
++		  * beacon frames.So while parsing the beacon frame the
++		  * wmm_info structure is used instead of wmm_param.
++		  * wmm_info structure was never used to set bss->wmm_ie.
++		  * This code fixes this problem by copying the WME
++		  * information from wmm_info to bss->wmm_ie and enabling
++		  * n-band association.
++		  */
++		kfree(bss->wmm_ie);
++		bss->wmm_ie = kmalloc(elems.wmm_info_len + 2, GFP_ATOMIC);
++		if (bss->wmm_ie) {
++			memcpy(bss->wmm_ie, elems.wmm_info - 2,
++			       elems.wmm_info_len + 2);
++			bss->wmm_ie_len = elems.wmm_info_len + 2;
++		} else
++			bss->wmm_ie_len = 0;
++	} else if (!elems.wmm_param && !elems.wmm_info && bss->wmm_ie) {
++		kfree(bss->wmm_ie);
++		bss->wmm_ie = NULL;
++		bss->wmm_ie_len = 0;
++	}
++
++	/* check if we need to merge IBSS */
++	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
++	    !local->sta_sw_scanning && !local->sta_hw_scanning &&
++	    bss->capability & WLAN_CAPABILITY_IBSS &&
++	    bss->freq == local->oper_channel->center_freq &&
++	    elems.ssid_len == sdata->u.sta.ssid_len &&
++	    memcmp(elems.ssid, sdata->u.sta.ssid, sdata->u.sta.ssid_len) == 0) {
++		if (rx_status->flag & RX_FLAG_TSFT) {
++			/* in order for correct IBSS merging we need mactime
++			 *
++			 * since mactime is defined as the time the first data
++			 * symbol of the frame hits the PHY, and the timestamp
++			 * of the beacon is defined as "the time that the data
++			 * symbol containing the first bit of the timestamp is
++			 * transmitted to the PHY plus the transmitting STA’s
++			 * delays through its local PHY from the MAC-PHY
++			 * interface to its interface with the WM"
++			 * (802.11 11.1.2) - equals the time this bit arrives at
++			 * the receiver - we have to take into account the
++			 * offset between the two.
++			 * e.g: at 1 MBit that means mactime is 192 usec earlier
++			 * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
++			 */
++			int rate = local->hw.wiphy->bands[rx_status->band]->
++					bitrates[rx_status->rate_idx].bitrate;
++			rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
++		} else if (local && local->ops && local->ops->get_tsf)
++			/* second best option: get current TSF */
++			rx_timestamp = local->ops->get_tsf(local_to_hw(local));
++		else
++			/* can't merge without knowing the TSF */
++			rx_timestamp = -1LLU;
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++		printk(KERN_DEBUG "RX beacon SA=%s BSSID="
++		       "%s TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
++		       print_mac(mac, mgmt->sa),
++		       print_mac(mac2, mgmt->bssid),
++		       (unsigned long long)rx_timestamp,
++		       (unsigned long long)beacon_timestamp,
++		       (unsigned long long)(rx_timestamp - beacon_timestamp),
++		       jiffies);
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++		if (beacon_timestamp > rx_timestamp) {
++#ifndef CONFIG_MAC80211_IBSS_DEBUG
++			if (net_ratelimit())
++#endif
++				printk(KERN_DEBUG "%s: beacon TSF higher than "
++				       "local TSF - IBSS merge with BSSID %s\n",
++				       dev->name, print_mac(mac, mgmt->bssid));
++			ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss);
++			ieee80211_ibss_add_sta(dev, NULL,
++					       mgmt->bssid, mgmt->sa);
++		}
++	}
++
++	ieee80211_rx_bss_put(dev, bss);
++}
++
++
++static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,
++					 struct ieee80211_mgmt *mgmt,
++					 size_t len,
++					 struct ieee80211_rx_status *rx_status)
++{
++	ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);
++}
++
++
++static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
++				     struct ieee80211_mgmt *mgmt,
++				     size_t len,
++				     struct ieee80211_rx_status *rx_status)
++{
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_if_sta *ifsta;
++	size_t baselen;
++	struct ieee802_11_elems elems;
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_conf *conf = &local->hw.conf;
++	u32 changed = 0;
++
++	ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++		return;
++	ifsta = &sdata->u.sta;
++
++	if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||
++	    memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
++		return;
++
++	/* Process beacon from the current BSS */
++	baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
++	if (baselen > len)
++		return;
++
++	ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
++
++	if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
++		ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
++					 elems.wmm_param_len);
++	}
++
++	/* Do not send changes to driver if we are scanning. This removes
++	 * requirement that driver's bss_info_changed function needs to be
++	 * atomic. */
++	if (local->sta_sw_scanning || local->sta_hw_scanning)
++		return;
++
++	if (elems.erp_info && elems.erp_info_len >= 1)
++		changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
++	else {
++		u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info);
++		changed |= ieee80211_handle_protect_preamb(sdata, false,
++				(capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
++	}
++
++	if (elems.ht_cap_elem && elems.ht_info_elem &&
++	    elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
++		struct ieee80211_ht_bss_info bss_info;
++
++		ieee80211_ht_addt_info_ie_to_ht_bss_info(
++				(struct ieee80211_ht_addt_info *)
++				elems.ht_info_elem, &bss_info);
++		changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf,
++					       &bss_info);
++	}
++
++	ieee80211_bss_info_change_notify(sdata, changed);
++}
++
++
++static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
++					struct ieee80211_if_sta *ifsta,
++					struct ieee80211_mgmt *mgmt,
++					size_t len,
++					struct ieee80211_rx_status *rx_status)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	int tx_last_beacon;
++	struct sk_buff *skb;
++	struct ieee80211_mgmt *resp;
++	u8 *pos, *end;
++	DECLARE_MAC_BUF(mac);
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++	DECLARE_MAC_BUF(mac2);
++	DECLARE_MAC_BUF(mac3);
++#endif
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS ||
++	    ifsta->state != IEEE80211_IBSS_JOINED ||
++	    len < 24 + 2 || !ifsta->probe_resp)
++		return;
++
++	if (local->ops->tx_last_beacon)
++		tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));
++	else
++		tx_last_beacon = 1;
++
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++	printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID="
++	       "%s (tx_last_beacon=%d)\n",
++	       dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da),
++	       print_mac(mac3, mgmt->bssid), tx_last_beacon);
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++
++	if (!tx_last_beacon)
++		return;
++
++	if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&
++	    memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
++		return;
++
++	end = ((u8 *) mgmt) + len;
++	pos = mgmt->u.probe_req.variable;
++	if (pos[0] != WLAN_EID_SSID ||
++	    pos + 2 + pos[1] > end) {
++		if (net_ratelimit()) {
++			printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
++			       "from %s\n",
++			       dev->name, print_mac(mac, mgmt->sa));
++		}
++		return;
++	}
++	if (pos[1] != 0 &&
++	    (pos[1] != ifsta->ssid_len ||
++	     memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {
++		/* Ignore ProbeReq for foreign SSID */
++		return;
++	}
++
++	/* Reply with ProbeResp */
++	skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);
++	if (!skb)
++		return;
++
++	resp = (struct ieee80211_mgmt *) skb->data;
++	memcpy(resp->da, mgmt->sa, ETH_ALEN);
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++	printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n",
++	       dev->name, print_mac(mac, resp->da));
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++	ieee80211_sta_tx(dev, skb, 0);
++}
++
++static void ieee80211_rx_mgmt_action(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta,
++				     struct ieee80211_mgmt *mgmt,
++				     size_t len,
++				     struct ieee80211_rx_status *rx_status)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	if (len < IEEE80211_MIN_ACTION_SIZE)
++		return;
++
++	switch (mgmt->u.action.category) {
++	case WLAN_CATEGORY_BACK:
++		switch (mgmt->u.action.u.addba_req.action_code) {
++		case WLAN_ACTION_ADDBA_REQ:
++			if (len < (IEEE80211_MIN_ACTION_SIZE +
++				   sizeof(mgmt->u.action.u.addba_req)))
++				break;
++			ieee80211_sta_process_addba_request(dev, mgmt, len);
++			break;
++		case WLAN_ACTION_ADDBA_RESP:
++			if (len < (IEEE80211_MIN_ACTION_SIZE +
++				   sizeof(mgmt->u.action.u.addba_resp)))
++				break;
++			ieee80211_sta_process_addba_resp(dev, mgmt, len);
++			break;
++		case WLAN_ACTION_DELBA:
++			if (len < (IEEE80211_MIN_ACTION_SIZE +
++				   sizeof(mgmt->u.action.u.delba)))
++				break;
++			ieee80211_sta_process_delba(dev, mgmt, len);
++			break;
++		default:
++			if (net_ratelimit())
++			   printk(KERN_DEBUG "%s: Rx unknown A-MPDU action\n",
++					dev->name);
++			break;
++		}
++		break;
++	case PLINK_CATEGORY:
++		if (ieee80211_vif_is_mesh(&sdata->vif))
++			mesh_rx_plink_frame(dev, mgmt, len, rx_status);
++		break;
++	case MESH_PATH_SEL_CATEGORY:
++		if (ieee80211_vif_is_mesh(&sdata->vif))
++			mesh_rx_path_sel_frame(dev, mgmt, len);
++		break;
++	default:
++		if (net_ratelimit())
++			printk(KERN_DEBUG "%s: Rx unknown action frame - "
++			"category=%d\n", dev->name, mgmt->u.action.category);
++		break;
++	}
++}
++
++void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
++			   struct ieee80211_rx_status *rx_status)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_if_sta *ifsta;
++	struct ieee80211_mgmt *mgmt;
++	u16 fc;
++
++	if (skb->len < 24)
++		goto fail;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	ifsta = &sdata->u.sta;
++
++	mgmt = (struct ieee80211_mgmt *) skb->data;
++	fc = le16_to_cpu(mgmt->frame_control);
++
++	switch (fc & IEEE80211_FCTL_STYPE) {
++	case IEEE80211_STYPE_PROBE_REQ:
++	case IEEE80211_STYPE_PROBE_RESP:
++	case IEEE80211_STYPE_BEACON:
++	case IEEE80211_STYPE_ACTION:
++		memcpy(skb->cb, rx_status, sizeof(*rx_status));
++	case IEEE80211_STYPE_AUTH:
++	case IEEE80211_STYPE_ASSOC_RESP:
++	case IEEE80211_STYPE_REASSOC_RESP:
++	case IEEE80211_STYPE_DEAUTH:
++	case IEEE80211_STYPE_DISASSOC:
++		skb_queue_tail(&ifsta->skb_queue, skb);
++		queue_work(local->hw.workqueue, &ifsta->work);
++		return;
++	default:
++		printk(KERN_DEBUG "%s: received unknown management frame - "
++		       "stype=%d\n", dev->name,
++		       (fc & IEEE80211_FCTL_STYPE) >> 4);
++		break;
++	}
++
++ fail:
++	kfree_skb(skb);
++}
++
++
++static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
++					 struct sk_buff *skb)
++{
++	struct ieee80211_rx_status *rx_status;
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_if_sta *ifsta;
++	struct ieee80211_mgmt *mgmt;
++	u16 fc;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	ifsta = &sdata->u.sta;
++
++	rx_status = (struct ieee80211_rx_status *) skb->cb;
++	mgmt = (struct ieee80211_mgmt *) skb->data;
++	fc = le16_to_cpu(mgmt->frame_control);
++
++	switch (fc & IEEE80211_FCTL_STYPE) {
++	case IEEE80211_STYPE_PROBE_REQ:
++		ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len,
++					    rx_status);
++		break;
++	case IEEE80211_STYPE_PROBE_RESP:
++		ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status);
++		break;
++	case IEEE80211_STYPE_BEACON:
++		ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status);
++		break;
++	case IEEE80211_STYPE_AUTH:
++		ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);
++		break;
++	case IEEE80211_STYPE_ASSOC_RESP:
++		ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
++		break;
++	case IEEE80211_STYPE_REASSOC_RESP:
++		ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
++		break;
++	case IEEE80211_STYPE_DEAUTH:
++		ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);
++		break;
++	case IEEE80211_STYPE_DISASSOC:
++		ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
++		break;
++	case IEEE80211_STYPE_ACTION:
++		ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len, rx_status);
++		break;
++	}
++
++	kfree_skb(skb);
++}
++
++
++ieee80211_rx_result
++ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
++		      struct ieee80211_rx_status *rx_status)
++{
++	struct ieee80211_mgmt *mgmt;
++	u16 fc;
++
++	if (skb->len < 2)
++		return RX_DROP_UNUSABLE;
++
++	mgmt = (struct ieee80211_mgmt *) skb->data;
++	fc = le16_to_cpu(mgmt->frame_control);
++
++	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
++		return RX_CONTINUE;
++
++	if (skb->len < 24)
++		return RX_DROP_MONITOR;
++
++	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
++		if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) {
++			ieee80211_rx_mgmt_probe_resp(dev, mgmt,
++						     skb->len, rx_status);
++			dev_kfree_skb(skb);
++			return RX_QUEUED;
++		} else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
++			ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len,
++						 rx_status);
++			dev_kfree_skb(skb);
++			return RX_QUEUED;
++		}
++	}
++	return RX_CONTINUE;
++}
++
++
++static int ieee80211_sta_active_ibss(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	int active = 0;
++	struct sta_info *sta;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	rcu_read_lock();
++
++	list_for_each_entry_rcu(sta, &local->sta_list, list) {
++		if (sta->sdata == sdata &&
++		    time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
++			       jiffies)) {
++			active++;
++			break;
++		}
++	}
++
++	rcu_read_unlock();
++
++	return active;
++}
++
++
++static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sta_info *sta, *tmp;
++	LIST_HEAD(tmp_list);
++	DECLARE_MAC_BUF(mac);
++	unsigned long flags;
++
++	spin_lock_irqsave(&local->sta_lock, flags);
++	list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
++		if (time_after(jiffies, sta->last_rx + exp_time)) {
++			printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
++			       dev->name, print_mac(mac, sta->addr));
++			__sta_info_unlink(&sta);
++			if (sta)
++				list_add(&sta->list, &tmp_list);
++		}
++	spin_unlock_irqrestore(&local->sta_lock, flags);
++
++	list_for_each_entry_safe(sta, tmp, &tmp_list, list)
++		sta_info_destroy(sta);
++}
++
++
++static void ieee80211_sta_merge_ibss(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta)
++{
++	mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
++
++	ieee80211_sta_expire(dev, IEEE80211_IBSS_INACTIVITY_LIMIT);
++	if (ieee80211_sta_active_ibss(dev))
++		return;
++
++	printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
++	       "IBSS networks with same SSID (merge)\n", dev->name);
++	ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len);
++}
++
++
++#ifdef CONFIG_MAC80211_MESH
++static void ieee80211_mesh_housekeeping(struct net_device *dev,
++			   struct ieee80211_if_sta *ifsta)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	bool free_plinks;
++
++	ieee80211_sta_expire(dev, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
++	mesh_path_expire(dev);
++
++	free_plinks = mesh_plink_availables(sdata);
++	if (free_plinks != sdata->u.sta.accepting_plinks)
++		ieee80211_if_config_beacon(dev);
++
++	mod_timer(&ifsta->timer, jiffies +
++			IEEE80211_MESH_HOUSEKEEPING_INTERVAL);
++}
++
++
++void ieee80211_start_mesh(struct net_device *dev)
++{
++	struct ieee80211_if_sta *ifsta;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	ifsta = &sdata->u.sta;
++	ifsta->state = IEEE80211_MESH_UP;
++	ieee80211_sta_timer((unsigned long)sdata);
++}
++#endif
++
++
++void ieee80211_sta_timer(unsigned long data)
++{
++	struct ieee80211_sub_if_data *sdata =
++		(struct ieee80211_sub_if_data *) data;
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	struct ieee80211_local *local = wdev_priv(&sdata->wdev);
++
++	set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
++	queue_work(local->hw.workqueue, &ifsta->work);
++}
++
++void ieee80211_sta_work(struct work_struct *work)
++{
++	struct ieee80211_sub_if_data *sdata =
++		container_of(work, struct ieee80211_sub_if_data, u.sta.work);
++	struct net_device *dev = sdata->dev;
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_if_sta *ifsta;
++	struct sk_buff *skb;
++
++	if (!netif_running(dev))
++		return;
++
++	if (local->sta_sw_scanning || local->sta_hw_scanning)
++		return;
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
++	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++	    sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) {
++		printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
++		       "(type=%d)\n", dev->name, sdata->vif.type);
++		return;
++	}
++	ifsta = &sdata->u.sta;
++
++	while ((skb = skb_dequeue(&ifsta->skb_queue)))
++		ieee80211_sta_rx_queued_mgmt(dev, skb);
++
++#ifdef CONFIG_MAC80211_MESH
++	if (ifsta->preq_queue_len &&
++	    time_after(jiffies,
++		       ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval)))
++		mesh_path_start_discovery(dev);
++#endif
++
++	if (ifsta->state != IEEE80211_AUTHENTICATE &&
++	    ifsta->state != IEEE80211_ASSOCIATE &&
++	    test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
++		if (ifsta->scan_ssid_len)
++			ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len);
++		else
++			ieee80211_sta_start_scan(dev, NULL, 0);
++		return;
++	}
++
++	if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
++		if (ieee80211_sta_config_auth(dev, ifsta))
++			return;
++		clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
++	} else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
++		return;
++
++	switch (ifsta->state) {
++	case IEEE80211_DISABLED:
++		break;
++	case IEEE80211_AUTHENTICATE:
++		ieee80211_authenticate(dev, ifsta);
++		break;
++	case IEEE80211_ASSOCIATE:
++		ieee80211_associate(dev, ifsta);
++		break;
++	case IEEE80211_ASSOCIATED:
++		ieee80211_associated(dev, ifsta);
++		break;
++	case IEEE80211_IBSS_SEARCH:
++		ieee80211_sta_find_ibss(dev, ifsta);
++		break;
++	case IEEE80211_IBSS_JOINED:
++		ieee80211_sta_merge_ibss(dev, ifsta);
++		break;
++#ifdef CONFIG_MAC80211_MESH
++	case IEEE80211_MESH_UP:
++		ieee80211_mesh_housekeeping(dev, ifsta);
++		break;
++#endif
++	default:
++		printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
++		       ifsta->state);
++		break;
++	}
++
++	if (ieee80211_privacy_mismatch(dev, ifsta)) {
++		printk(KERN_DEBUG "%s: privacy configuration mismatch and "
++		       "mixed-cell disabled - disassociate\n", dev->name);
++
++		ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED);
++		ieee80211_set_disassoc(dev, ifsta, 0);
++	}
++}
++
++
++static void ieee80211_sta_reset_auth(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	if (local->ops->reset_tsf) {
++		/* Reset own TSF to allow time synchronization work. */
++		local->ops->reset_tsf(local_to_hw(local));
++	}
++
++	ifsta->wmm_last_param_set = -1; /* allow any WMM update */
++
++
++	if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
++		ifsta->auth_alg = WLAN_AUTH_OPEN;
++	else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
++		ifsta->auth_alg = WLAN_AUTH_SHARED_KEY;
++	else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
++		ifsta->auth_alg = WLAN_AUTH_LEAP;
++	else
++		ifsta->auth_alg = WLAN_AUTH_OPEN;
++	printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
++	       ifsta->auth_alg);
++	ifsta->auth_transaction = -1;
++	ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
++	ifsta->auth_tries = ifsta->assoc_tries = 0;
++	netif_carrier_off(dev);
++}
++
++
++void ieee80211_sta_req_auth(struct net_device *dev,
++			    struct ieee80211_if_sta *ifsta)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++		return;
++
++	if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
++				IEEE80211_STA_AUTO_BSSID_SEL)) &&
++	    (ifsta->flags & (IEEE80211_STA_SSID_SET |
++				IEEE80211_STA_AUTO_SSID_SEL))) {
++		set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
++		queue_work(local->hw.workqueue, &ifsta->work);
++	}
++}
++
++static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
++				    const char *ssid, int ssid_len)
++{
++	int tmp, hidden_ssid;
++
++	if (ssid_len == ifsta->ssid_len &&
++	    !memcmp(ifsta->ssid, ssid, ssid_len))
++		return 1;
++
++	if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
++		return 0;
++
++	hidden_ssid = 1;
++	tmp = ssid_len;
++	while (tmp--) {
++		if (ssid[tmp] != '\0') {
++			hidden_ssid = 0;
++			break;
++		}
++	}
++
++	if (hidden_ssid && ifsta->ssid_len == ssid_len)
++		return 1;
++
++	if (ssid_len == 1 && ssid[0] == ' ')
++		return 1;
++
++	return 0;
++}
++
++static int ieee80211_sta_config_auth(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_sta_bss *bss, *selected = NULL;
++	int top_rssi = 0, freq;
++
++	if (!(ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
++	    IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL))) {
++		ifsta->state = IEEE80211_AUTHENTICATE;
++		ieee80211_sta_reset_auth(dev, ifsta);
++		return 0;
++	}
++
++	spin_lock_bh(&local->sta_bss_lock);
++	freq = local->oper_channel->center_freq;
++	list_for_each_entry(bss, &local->sta_bss_list, list) {
++		if (!(bss->capability & WLAN_CAPABILITY_ESS))
++			continue;
++
++		if (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
++		    !!sdata->default_key)
++			continue;
++
++		if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
++		    bss->freq != freq)
++			continue;
++
++		if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
++		    memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
++			continue;
++
++		if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
++		    !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
++			continue;
++
++		if (!selected || top_rssi < bss->rssi) {
++			selected = bss;
++			top_rssi = bss->rssi;
++		}
++	}
++	if (selected)
++		atomic_inc(&selected->users);
++	spin_unlock_bh(&local->sta_bss_lock);
++
++	if (selected) {
++		ieee80211_set_freq(local, selected->freq);
++		if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
++			ieee80211_sta_set_ssid(dev, selected->ssid,
++					       selected->ssid_len);
++		ieee80211_sta_set_bssid(dev, selected->bssid);
++		ieee80211_sta_def_wmm_params(dev, selected, 0);
++		ieee80211_rx_bss_put(dev, selected);
++		ifsta->state = IEEE80211_AUTHENTICATE;
++		ieee80211_sta_reset_auth(dev, ifsta);
++		return 0;
++	} else {
++		if (ifsta->state != IEEE80211_AUTHENTICATE) {
++			if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
++				ieee80211_sta_start_scan(dev, NULL, 0);
++			else
++				ieee80211_sta_start_scan(dev, ifsta->ssid,
++							 ifsta->ssid_len);
++			ifsta->state = IEEE80211_AUTHENTICATE;
++			set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
++		} else
++			ifsta->state = IEEE80211_DISABLED;
++	}
++	return -1;
++}
++
++
++static int ieee80211_sta_create_ibss(struct net_device *dev,
++				     struct ieee80211_if_sta *ifsta)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sta_bss *bss;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_supported_band *sband;
++	u8 bssid[ETH_ALEN], *pos;
++	int i;
++	DECLARE_MAC_BUF(mac);
++
++#if 0
++	/* Easier testing, use fixed BSSID. */
++	memset(bssid, 0xfe, ETH_ALEN);
++#else
++	/* Generate random, not broadcast, locally administered BSSID. Mix in
++	 * own MAC address to make sure that devices that do not have proper
++	 * random number generator get different BSSID. */
++	get_random_bytes(bssid, ETH_ALEN);
++	for (i = 0; i < ETH_ALEN; i++)
++		bssid[i] ^= dev->dev_addr[i];
++	bssid[0] &= ~0x01;
++	bssid[0] |= 0x02;
++#endif
++
++	printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
++	       dev->name, print_mac(mac, bssid));
++
++	bss = ieee80211_rx_bss_add(dev, bssid,
++				   local->hw.conf.channel->center_freq,
++				   sdata->u.sta.ssid, sdata->u.sta.ssid_len);
++	if (!bss)
++		return -ENOMEM;
++
++	bss->band = local->hw.conf.channel->band;
++	sband = local->hw.wiphy->bands[bss->band];
++
++	if (local->hw.conf.beacon_int == 0)
++		local->hw.conf.beacon_int = 10000;
++	bss->beacon_int = local->hw.conf.beacon_int;
++	bss->last_update = jiffies;
++	bss->capability = WLAN_CAPABILITY_IBSS;
++	if (sdata->default_key) {
++		bss->capability |= WLAN_CAPABILITY_PRIVACY;
++	} else
++		sdata->drop_unencrypted = 0;
++	bss->supp_rates_len = sband->n_bitrates;
++	pos = bss->supp_rates;
++	for (i = 0; i < sband->n_bitrates; i++) {
++		int rate = sband->bitrates[i].bitrate;
++		*pos++ = (u8) (rate / 5);
++	}
++
++	return ieee80211_sta_join_ibss(dev, ifsta, bss);
++}
++
++
++static int ieee80211_sta_find_ibss(struct net_device *dev,
++				   struct ieee80211_if_sta *ifsta)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sta_bss *bss;
++	int found = 0;
++	u8 bssid[ETH_ALEN];
++	int active_ibss;
++	DECLARE_MAC_BUF(mac);
++	DECLARE_MAC_BUF(mac2);
++
++	if (ifsta->ssid_len == 0)
++		return -EINVAL;
++
++	active_ibss = ieee80211_sta_active_ibss(dev);
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++	printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
++	       dev->name, active_ibss);
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++	spin_lock_bh(&local->sta_bss_lock);
++	list_for_each_entry(bss, &local->sta_bss_list, list) {
++		if (ifsta->ssid_len != bss->ssid_len ||
++		    memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
++		    || !(bss->capability & WLAN_CAPABILITY_IBSS))
++			continue;
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++		printk(KERN_DEBUG "   bssid=%s found\n",
++		       print_mac(mac, bss->bssid));
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++		memcpy(bssid, bss->bssid, ETH_ALEN);
++		found = 1;
++		if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
++			break;
++	}
++	spin_unlock_bh(&local->sta_bss_lock);
++
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++	printk(KERN_DEBUG "   sta_find_ibss: selected %s current "
++	       "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++	if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
++	    (bss = ieee80211_rx_bss_get(dev, bssid,
++					local->hw.conf.channel->center_freq,
++					ifsta->ssid, ifsta->ssid_len))) {
++		printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
++		       " based on configured SSID\n",
++		       dev->name, print_mac(mac, bssid));
++		return ieee80211_sta_join_ibss(dev, ifsta, bss);
++	}
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++	printk(KERN_DEBUG "   did not try to join ibss\n");
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++
++	/* Selected IBSS not found in current scan results - try to scan */
++	if (ifsta->state == IEEE80211_IBSS_JOINED &&
++	    !ieee80211_sta_active_ibss(dev)) {
++		mod_timer(&ifsta->timer, jiffies +
++				      IEEE80211_IBSS_MERGE_INTERVAL);
++	} else if (time_after(jiffies, local->last_scan_completed +
++			      IEEE80211_SCAN_INTERVAL)) {
++		printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
++		       "join\n", dev->name);
++		return ieee80211_sta_req_scan(dev, ifsta->ssid,
++					      ifsta->ssid_len);
++	} else if (ifsta->state != IEEE80211_IBSS_JOINED) {
++		int interval = IEEE80211_SCAN_INTERVAL;
++
++		if (time_after(jiffies, ifsta->ibss_join_req +
++			       IEEE80211_IBSS_JOIN_TIMEOUT)) {
++			if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) &&
++			    (!(local->oper_channel->flags &
++					IEEE80211_CHAN_NO_IBSS)))
++				return ieee80211_sta_create_ibss(dev, ifsta);
++			if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) {
++				printk(KERN_DEBUG "%s: IBSS not allowed on"
++				       " %d MHz\n", dev->name,
++				       local->hw.conf.channel->center_freq);
++			}
++
++			/* No IBSS found - decrease scan interval and continue
++			 * scanning. */
++			interval = IEEE80211_SCAN_INTERVAL_SLOW;
++		}
++
++		ifsta->state = IEEE80211_IBSS_SEARCH;
++		mod_timer(&ifsta->timer, jiffies + interval);
++		return 0;
++	}
++
++	return 0;
++}
++
++
++int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta;
++
++	if (len > IEEE80211_MAX_SSID_LEN)
++		return -EINVAL;
++
++	ifsta = &sdata->u.sta;
++
++	if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
++		ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
++	memcpy(ifsta->ssid, ssid, len);
++	memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
++	ifsta->ssid_len = len;
++
++	if (len)
++		ifsta->flags |= IEEE80211_STA_SSID_SET;
++	else
++		ifsta->flags &= ~IEEE80211_STA_SSID_SET;
++	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
++	    !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
++		ifsta->ibss_join_req = jiffies;
++		ifsta->state = IEEE80211_IBSS_SEARCH;
++		return ieee80211_sta_find_ibss(dev, ifsta);
++	}
++	return 0;
++}
++
++
++int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
++	*len = ifsta->ssid_len;
++	return 0;
++}
++
++
++int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
++{
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_if_sta *ifsta;
++	int res;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	ifsta = &sdata->u.sta;
++
++	if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
++		memcpy(ifsta->bssid, bssid, ETH_ALEN);
++		res = ieee80211_if_config(dev);
++		if (res) {
++			printk(KERN_DEBUG "%s: Failed to config new BSSID to "
++			       "the low-level driver\n", dev->name);
++			return res;
++		}
++	}
++
++	if (is_valid_ether_addr(bssid))
++		ifsta->flags |= IEEE80211_STA_BSSID_SET;
++	else
++		ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
++
++	return 0;
++}
++
++
++static void ieee80211_send_nullfunc(struct ieee80211_local *local,
++				    struct ieee80211_sub_if_data *sdata,
++				    int powersave)
++{
++	struct sk_buff *skb;
++	struct ieee80211_hdr *nullfunc;
++	u16 fc;
++
++	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
++	if (!skb) {
++		printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
++		       "frame\n", sdata->dev->name);
++		return;
++	}
++	skb_reserve(skb, local->hw.extra_tx_headroom);
++
++	nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
++	memset(nullfunc, 0, 24);
++	fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
++	     IEEE80211_FCTL_TODS;
++	if (powersave)
++		fc |= IEEE80211_FCTL_PM;
++	nullfunc->frame_control = cpu_to_le16(fc);
++	memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN);
++	memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
++	memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN);
++
++	ieee80211_sta_tx(sdata->dev, skb, 0);
++}
++
++
++static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
++{
++	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++	    ieee80211_vif_is_mesh(&sdata->vif))
++		ieee80211_sta_timer((unsigned long)sdata);
++}
++
++void ieee80211_scan_completed(struct ieee80211_hw *hw)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct net_device *dev = local->scan_dev;
++	struct ieee80211_sub_if_data *sdata;
++	union iwreq_data wrqu;
++
++	local->last_scan_completed = jiffies;
++	memset(&wrqu, 0, sizeof(wrqu));
++	wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
++
++	if (local->sta_hw_scanning) {
++		local->sta_hw_scanning = 0;
++		if (ieee80211_hw_config(local))
++			printk(KERN_DEBUG "%s: failed to restore operational "
++			       "channel after scan\n", dev->name);
++		/* Restart STA timer for HW scan case */
++		rcu_read_lock();
++		list_for_each_entry_rcu(sdata, &local->interfaces, list)
++			ieee80211_restart_sta_timer(sdata);
++		rcu_read_unlock();
++
++		goto done;
++	}
++
++	local->sta_sw_scanning = 0;
++	if (ieee80211_hw_config(local))
++		printk(KERN_DEBUG "%s: failed to restore operational "
++		       "channel after scan\n", dev->name);
++
++
++	netif_tx_lock_bh(local->mdev);
++	local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
++	local->ops->configure_filter(local_to_hw(local),
++				     FIF_BCN_PRBRESP_PROMISC,
++				     &local->filter_flags,
++				     local->mdev->mc_count,
++				     local->mdev->mc_list);
++
++	netif_tx_unlock_bh(local->mdev);
++
++	rcu_read_lock();
++	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++
++		/* No need to wake the master device. */
++		if (sdata->dev == local->mdev)
++			continue;
++
++		/* Tell AP we're back */
++		if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
++		    sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)
++			ieee80211_send_nullfunc(local, sdata, 0);
++
++		ieee80211_restart_sta_timer(sdata);
++
++		netif_wake_queue(sdata->dev);
++	}
++	rcu_read_unlock();
++
++done:
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++		struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++		if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) ||
++		    (!ifsta->state == IEEE80211_IBSS_JOINED &&
++		    !ieee80211_sta_active_ibss(dev)))
++			ieee80211_sta_find_ibss(dev, ifsta);
++	}
++}
++EXPORT_SYMBOL(ieee80211_scan_completed);
++
++void ieee80211_sta_scan_work(struct work_struct *work)
++{
++	struct ieee80211_local *local =
++		container_of(work, struct ieee80211_local, scan_work.work);
++	struct net_device *dev = local->scan_dev;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_supported_band *sband;
++	struct ieee80211_channel *chan;
++	int skip;
++	unsigned long next_delay = 0;
++
++	if (!local->sta_sw_scanning)
++		return;
++
++	switch (local->scan_state) {
++	case SCAN_SET_CHANNEL:
++		/*
++		 * Get current scan band. scan_band may be IEEE80211_NUM_BANDS
++		 * after we successfully scanned the last channel of the last
++		 * band (and the last band is supported by the hw)
++		 */
++		if (local->scan_band < IEEE80211_NUM_BANDS)
++			sband = local->hw.wiphy->bands[local->scan_band];
++		else
++			sband = NULL;
++
++		/*
++		 * If we are at an unsupported band and have more bands
++		 * left to scan, advance to the next supported one.
++		 */
++		while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) {
++			local->scan_band++;
++			sband = local->hw.wiphy->bands[local->scan_band];
++			local->scan_channel_idx = 0;
++		}
++
++		/* if no more bands/channels left, complete scan */
++		if (!sband || local->scan_channel_idx >= sband->n_channels) {
++			ieee80211_scan_completed(local_to_hw(local));
++			return;
++		}
++		skip = 0;
++		chan = &sband->channels[local->scan_channel_idx];
++
++		if (chan->flags & IEEE80211_CHAN_DISABLED ||
++		    (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
++		     chan->flags & IEEE80211_CHAN_NO_IBSS))
++			skip = 1;
++
++		if (!skip) {
++			local->scan_channel = chan;
++			if (ieee80211_hw_config(local)) {
++				printk(KERN_DEBUG "%s: failed to set freq to "
++				       "%d MHz for scan\n", dev->name,
++				       chan->center_freq);
++				skip = 1;
++			}
++		}
++
++		/* advance state machine to next channel/band */
++		local->scan_channel_idx++;
++		if (local->scan_channel_idx >= sband->n_channels) {
++			/*
++			 * scan_band may end up == IEEE80211_NUM_BANDS, but
++			 * we'll catch that case above and complete the scan
++			 * if that is the case.
++			 */
++			local->scan_band++;
++			local->scan_channel_idx = 0;
++		}
++
++		if (skip)
++			break;
++
++		next_delay = IEEE80211_PROBE_DELAY +
++			     usecs_to_jiffies(local->hw.channel_change_time);
++		local->scan_state = SCAN_SEND_PROBE;
++		break;
++	case SCAN_SEND_PROBE:
++		next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
++		local->scan_state = SCAN_SET_CHANNEL;
++
++		if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN)
++			break;
++		ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
++					 local->scan_ssid_len);
++		next_delay = IEEE80211_CHANNEL_TIME;
++		break;
++	}
++
++	if (local->sta_sw_scanning)
++		queue_delayed_work(local->hw.workqueue, &local->scan_work,
++				   next_delay);
++}
++
++
++static int ieee80211_sta_start_scan(struct net_device *dev,
++				    u8 *ssid, size_t ssid_len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata;
++
++	if (ssid_len > IEEE80211_MAX_SSID_LEN)
++		return -EINVAL;
++
++	/* MLME-SCAN.request (page 118)  page 144 (11.1.3.1)
++	 * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
++	 * BSSID: MACAddress
++	 * SSID
++	 * ScanType: ACTIVE, PASSIVE
++	 * ProbeDelay: delay (in microseconds) to be used prior to transmitting
++	 *    a Probe frame during active scanning
++	 * ChannelList
++	 * MinChannelTime (>= ProbeDelay), in TU
++	 * MaxChannelTime: (>= MinChannelTime), in TU
++	 */
++
++	 /* MLME-SCAN.confirm
++	  * BSSDescriptionSet
++	  * ResultCode: SUCCESS, INVALID_PARAMETERS
++	 */
++
++	if (local->sta_sw_scanning || local->sta_hw_scanning) {
++		if (local->scan_dev == dev)
++			return 0;
++		return -EBUSY;
++	}
++
++	if (local->ops->hw_scan) {
++		int rc = local->ops->hw_scan(local_to_hw(local),
++					     ssid, ssid_len);
++		if (!rc) {
++			local->sta_hw_scanning = 1;
++			local->scan_dev = dev;
++		}
++		return rc;
++	}
++
++	local->sta_sw_scanning = 1;
++
++	rcu_read_lock();
++	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++
++		/* Don't stop the master interface, otherwise we can't transmit
++		 * probes! */
++		if (sdata->dev == local->mdev)
++			continue;
++
++		netif_stop_queue(sdata->dev);
++		if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
++		    (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
++			ieee80211_send_nullfunc(local, sdata, 1);
++	}
++	rcu_read_unlock();
++
++	if (ssid) {
++		local->scan_ssid_len = ssid_len;
++		memcpy(local->scan_ssid, ssid, ssid_len);
++	} else
++		local->scan_ssid_len = 0;
++	local->scan_state = SCAN_SET_CHANNEL;
++	local->scan_channel_idx = 0;
++	local->scan_band = IEEE80211_BAND_2GHZ;
++	local->scan_dev = dev;
++
++	netif_tx_lock_bh(local->mdev);
++	local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
++	local->ops->configure_filter(local_to_hw(local),
++				     FIF_BCN_PRBRESP_PROMISC,
++				     &local->filter_flags,
++				     local->mdev->mc_count,
++				     local->mdev->mc_list);
++	netif_tx_unlock_bh(local->mdev);
++
++	/* TODO: start scan as soon as all nullfunc frames are ACKed */
++	queue_delayed_work(local->hw.workqueue, &local->scan_work,
++			   IEEE80211_CHANNEL_TIME);
++
++	return 0;
++}
++
++
++int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++		return ieee80211_sta_start_scan(dev, ssid, ssid_len);
++
++	if (local->sta_sw_scanning || local->sta_hw_scanning) {
++		if (local->scan_dev == dev)
++			return 0;
++		return -EBUSY;
++	}
++
++	ifsta->scan_ssid_len = ssid_len;
++	if (ssid_len)
++		memcpy(ifsta->scan_ssid, ssid, ssid_len);
++	set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
++	queue_work(local->hw.workqueue, &ifsta->work);
++	return 0;
++}
++
++static char *
++ieee80211_sta_scan_result(struct net_device *dev,
++			  struct ieee80211_sta_bss *bss,
++			  char *current_ev, char *end_buf)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct iw_event iwe;
++
++	if (time_after(jiffies,
++		       bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE))
++		return current_ev;
++
++	memset(&iwe, 0, sizeof(iwe));
++	iwe.cmd = SIOCGIWAP;
++	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
++	memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
++	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++					  IW_EV_ADDR_LEN);
++
++	memset(&iwe, 0, sizeof(iwe));
++	iwe.cmd = SIOCGIWESSID;
++	if (bss_mesh_cfg(bss)) {
++		iwe.u.data.length = bss_mesh_id_len(bss);
++		iwe.u.data.flags = 1;
++		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
++						  bss_mesh_id(bss));
++	} else {
++		iwe.u.data.length = bss->ssid_len;
++		iwe.u.data.flags = 1;
++		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
++						  bss->ssid);
++	}
++
++	if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)
++	    || bss_mesh_cfg(bss)) {
++		memset(&iwe, 0, sizeof(iwe));
++		iwe.cmd = SIOCGIWMODE;
++		if (bss_mesh_cfg(bss))
++			iwe.u.mode = IW_MODE_MESH;
++		else if (bss->capability & WLAN_CAPABILITY_ESS)
++			iwe.u.mode = IW_MODE_MASTER;
++		else
++			iwe.u.mode = IW_MODE_ADHOC;
++		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++						  IW_EV_UINT_LEN);
++	}
++
++	memset(&iwe, 0, sizeof(iwe));
++	iwe.cmd = SIOCGIWFREQ;
++	iwe.u.freq.m = bss->freq;
++	iwe.u.freq.e = 6;
++	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++					  IW_EV_FREQ_LEN);
++
++	memset(&iwe, 0, sizeof(iwe));
++	iwe.cmd = SIOCGIWFREQ;
++	iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq);
++	iwe.u.freq.e = 0;
++	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++					  IW_EV_FREQ_LEN);
++
++	memset(&iwe, 0, sizeof(iwe));
++	iwe.cmd = IWEVQUAL;
++	iwe.u.qual.qual = bss->signal;
++	iwe.u.qual.level = bss->rssi;
++	iwe.u.qual.noise = bss->noise;
++	iwe.u.qual.updated = local->wstats_flags;
++	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++					  IW_EV_QUAL_LEN);
++
++	memset(&iwe, 0, sizeof(iwe));
++	iwe.cmd = SIOCGIWENCODE;
++	if (bss->capability & WLAN_CAPABILITY_PRIVACY)
++		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
++	else
++		iwe.u.data.flags = IW_ENCODE_DISABLED;
++	iwe.u.data.length = 0;
++	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
++
++	if (bss && bss->wpa_ie) {
++		memset(&iwe, 0, sizeof(iwe));
++		iwe.cmd = IWEVGENIE;
++		iwe.u.data.length = bss->wpa_ie_len;
++		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
++						  bss->wpa_ie);
++	}
++
++	if (bss && bss->rsn_ie) {
++		memset(&iwe, 0, sizeof(iwe));
++		iwe.cmd = IWEVGENIE;
++		iwe.u.data.length = bss->rsn_ie_len;
++		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
++						  bss->rsn_ie);
++	}
++
++	if (bss && bss->supp_rates_len > 0) {
++		/* display all supported rates in readable format */
++		char *p = current_ev + IW_EV_LCP_LEN;
++		int i;
++
++		memset(&iwe, 0, sizeof(iwe));
++		iwe.cmd = SIOCGIWRATE;
++		/* Those two flags are ignored... */
++		iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
++
++		for (i = 0; i < bss->supp_rates_len; i++) {
++			iwe.u.bitrate.value = ((bss->supp_rates[i] &
++							0x7f) * 500000);
++			p = iwe_stream_add_value(current_ev, p,
++					end_buf, &iwe, IW_EV_PARAM_LEN);
++		}
++		current_ev = p;
++	}
++
++	if (bss) {
++		char *buf;
++		buf = kmalloc(30, GFP_ATOMIC);
++		if (buf) {
++			memset(&iwe, 0, sizeof(iwe));
++			iwe.cmd = IWEVCUSTOM;
++			sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp));
++			iwe.u.data.length = strlen(buf);
++			current_ev = iwe_stream_add_point(current_ev, end_buf,
++							  &iwe, buf);
++			kfree(buf);
++		}
++	}
++
++	if (bss_mesh_cfg(bss)) {
++		char *buf;
++		u8 *cfg = bss_mesh_cfg(bss);
++		buf = kmalloc(50, GFP_ATOMIC);
++		if (buf) {
++			memset(&iwe, 0, sizeof(iwe));
++			iwe.cmd = IWEVCUSTOM;
++			sprintf(buf, "Mesh network (version %d)", cfg[0]);
++			iwe.u.data.length = strlen(buf);
++			current_ev = iwe_stream_add_point(current_ev, end_buf,
++							  &iwe, buf);
++			sprintf(buf, "Path Selection Protocol ID: "
++				"0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3],
++							cfg[4]);
++			iwe.u.data.length = strlen(buf);
++			current_ev = iwe_stream_add_point(current_ev, end_buf,
++							  &iwe, buf);
++			sprintf(buf, "Path Selection Metric ID: "
++				"0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7],
++							cfg[8]);
++			iwe.u.data.length = strlen(buf);
++			current_ev = iwe_stream_add_point(current_ev, end_buf,
++							  &iwe, buf);
++			sprintf(buf, "Congestion Control Mode ID: "
++				"0x%02X%02X%02X%02X", cfg[9], cfg[10],
++							cfg[11], cfg[12]);
++			iwe.u.data.length = strlen(buf);
++			current_ev = iwe_stream_add_point(current_ev, end_buf,
++							  &iwe, buf);
++			sprintf(buf, "Channel Precedence: "
++				"0x%02X%02X%02X%02X", cfg[13], cfg[14],
++							cfg[15], cfg[16]);
++			iwe.u.data.length = strlen(buf);
++			current_ev = iwe_stream_add_point(current_ev, end_buf,
++							  &iwe, buf);
++			kfree(buf);
++		}
++	}
++
++	return current_ev;
++}
++
++
++int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	char *current_ev = buf;
++	char *end_buf = buf + len;
++	struct ieee80211_sta_bss *bss;
++
++	spin_lock_bh(&local->sta_bss_lock);
++	list_for_each_entry(bss, &local->sta_bss_list, list) {
++		if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
++			spin_unlock_bh(&local->sta_bss_lock);
++			return -E2BIG;
++		}
++		current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
++						       end_buf);
++	}
++	spin_unlock_bh(&local->sta_bss_lock);
++	return current_ev - buf;
++}
++
++
++int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++	kfree(ifsta->extra_ie);
++	if (len == 0) {
++		ifsta->extra_ie = NULL;
++		ifsta->extra_ie_len = 0;
++		return 0;
++	}
++	ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
++	if (!ifsta->extra_ie) {
++		ifsta->extra_ie_len = 0;
++		return -ENOMEM;
++	}
++	memcpy(ifsta->extra_ie, ie, len);
++	ifsta->extra_ie_len = len;
++	return 0;
++}
++
++
++struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
++					 struct sk_buff *skb, u8 *bssid,
++					 u8 *addr)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sta_info *sta;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	DECLARE_MAC_BUF(mac);
++
++	/* TODO: Could consider removing the least recently used entry and
++	 * allow new one to be added. */
++	if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
++		if (net_ratelimit()) {
++			printk(KERN_DEBUG "%s: No room for a new IBSS STA "
++			       "entry %s\n", dev->name, print_mac(mac, addr));
++		}
++		return NULL;
++	}
++
++	printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
++	       wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
++
++	sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
++	if (!sta)
++		return NULL;
++
++	sta->flags |= WLAN_STA_AUTHORIZED;
++
++	sta->supp_rates[local->hw.conf.channel->band] =
++		sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band];
++
++	rate_control_rate_init(sta, local);
++
++	if (sta_info_insert(sta))
++		return NULL;
++
++	return sta;
++}
++
++
++int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++
++	printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
++	       dev->name, reason);
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
++	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
++		return -EINVAL;
++
++	ieee80211_send_deauth(dev, ifsta, reason);
++	ieee80211_set_disassoc(dev, ifsta, 1);
++	return 0;
++}
++
++
++int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++
++	printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
++	       dev->name, reason);
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++		return -EINVAL;
++
++	if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
++		return -1;
++
++	ieee80211_send_disassoc(dev, ifsta, reason);
++	ieee80211_set_disassoc(dev, ifsta, 0);
++	return 0;
++}
++
++void ieee80211_notify_mac(struct ieee80211_hw *hw,
++			  enum ieee80211_notification_types  notif_type)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct ieee80211_sub_if_data *sdata;
++
++	switch (notif_type) {
++	case IEEE80211_NOTIFY_RE_ASSOC:
++		rcu_read_lock();
++		list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++
++			if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
++				ieee80211_sta_req_auth(sdata->dev,
++						       &sdata->u.sta);
++			}
++
++		}
++		rcu_read_unlock();
++		break;
++	}
++}
++EXPORT_SYMBOL(ieee80211_notify_mac);
+diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
+new file mode 100644
+index 0000000..841df93
+--- /dev/null
++++ b/net/mac80211/rate.c
+@@ -0,0 +1,249 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/rtnetlink.h>
++#include "rate.h"
++#include "ieee80211_i.h"
++
++struct rate_control_alg {
++	struct list_head list;
++	struct rate_control_ops *ops;
++};
++
++static LIST_HEAD(rate_ctrl_algs);
++static DEFINE_MUTEX(rate_ctrl_mutex);
++
++static char *ieee80211_default_rc_algo = CONFIG_MAC80211_RC_DEFAULT;
++module_param(ieee80211_default_rc_algo, charp, 0644);
++MODULE_PARM_DESC(ieee80211_default_rc_algo,
++		 "Default rate control algorithm for mac80211 to use");
++
++int ieee80211_rate_control_register(struct rate_control_ops *ops)
++{
++	struct rate_control_alg *alg;
++
++	if (!ops->name)
++		return -EINVAL;
++
++	mutex_lock(&rate_ctrl_mutex);
++	list_for_each_entry(alg, &rate_ctrl_algs, list) {
++		if (!strcmp(alg->ops->name, ops->name)) {
++			/* don't register an algorithm twice */
++			WARN_ON(1);
++			mutex_unlock(&rate_ctrl_mutex);
++			return -EALREADY;
++		}
++	}
++
++	alg = kzalloc(sizeof(*alg), GFP_KERNEL);
++	if (alg == NULL) {
++		mutex_unlock(&rate_ctrl_mutex);
++		return -ENOMEM;
++	}
++	alg->ops = ops;
++
++	list_add_tail(&alg->list, &rate_ctrl_algs);
++	mutex_unlock(&rate_ctrl_mutex);
++
++	return 0;
++}
++EXPORT_SYMBOL(ieee80211_rate_control_register);
++
++void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
++{
++	struct rate_control_alg *alg;
++
++	mutex_lock(&rate_ctrl_mutex);
++	list_for_each_entry(alg, &rate_ctrl_algs, list) {
++		if (alg->ops == ops) {
++			list_del(&alg->list);
++			kfree(alg);
++			break;
++		}
++	}
++	mutex_unlock(&rate_ctrl_mutex);
++}
++EXPORT_SYMBOL(ieee80211_rate_control_unregister);
++
++static struct rate_control_ops *
++ieee80211_try_rate_control_ops_get(const char *name)
++{
++	struct rate_control_alg *alg;
++	struct rate_control_ops *ops = NULL;
++
++	if (!name)
++		return NULL;
++
++	mutex_lock(&rate_ctrl_mutex);
++	list_for_each_entry(alg, &rate_ctrl_algs, list) {
++		if (!strcmp(alg->ops->name, name))
++			if (try_module_get(alg->ops->module)) {
++				ops = alg->ops;
++				break;
++			}
++	}
++	mutex_unlock(&rate_ctrl_mutex);
++	return ops;
++}
++
++/* Get the rate control algorithm. */
++static struct rate_control_ops *
++ieee80211_rate_control_ops_get(const char *name)
++{
++	struct rate_control_ops *ops;
++	const char *alg_name;
++
++	if (!name)
++		alg_name = ieee80211_default_rc_algo;
++	else
++		alg_name = name;
++
++	ops = ieee80211_try_rate_control_ops_get(alg_name);
++	if (!ops) {
++		request_module("rc80211_%s", alg_name);
++		ops = ieee80211_try_rate_control_ops_get(alg_name);
++	}
++	if (!ops && name)
++		/* try default if specific alg requested but not found */
++		ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo);
++
++	/* try built-in one if specific alg requested but not found */
++	if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT))
++		ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT);
++
++	return ops;
++}
++
++static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
++{
++	module_put(ops->module);
++}
++
++struct rate_control_ref *rate_control_alloc(const char *name,
++					    struct ieee80211_local *local)
++{
++	struct rate_control_ref *ref;
++
++	ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
++	if (!ref)
++		goto fail_ref;
++	kref_init(&ref->kref);
++	ref->ops = ieee80211_rate_control_ops_get(name);
++	if (!ref->ops)
++		goto fail_ops;
++	ref->priv = ref->ops->alloc(local);
++	if (!ref->priv)
++		goto fail_priv;
++	return ref;
++
++fail_priv:
++	ieee80211_rate_control_ops_put(ref->ops);
++fail_ops:
++	kfree(ref);
++fail_ref:
++	return NULL;
++}
++
++static void rate_control_release(struct kref *kref)
++{
++	struct rate_control_ref *ctrl_ref;
++
++	ctrl_ref = container_of(kref, struct rate_control_ref, kref);
++	ctrl_ref->ops->free(ctrl_ref->priv);
++	ieee80211_rate_control_ops_put(ctrl_ref->ops);
++	kfree(ctrl_ref);
++}
++
++void rate_control_get_rate(struct net_device *dev,
++			   struct ieee80211_supported_band *sband,
++			   struct sk_buff *skb,
++			   struct rate_selection *sel)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct rate_control_ref *ref = local->rate_ctrl;
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	struct sta_info *sta;
++	int i;
++
++	rcu_read_lock();
++	sta = sta_info_get(local, hdr->addr1);
++
++	memset(sel, 0, sizeof(struct rate_selection));
++
++	ref->ops->get_rate(ref->priv, dev, sband, skb, sel);
++
++	/* Select a non-ERP backup rate. */
++	if (!sel->nonerp) {
++		for (i = 0; i < sband->n_bitrates; i++) {
++			struct ieee80211_rate *rate = &sband->bitrates[i];
++			if (sel->rate->bitrate < rate->bitrate)
++				break;
++
++			if (rate_supported(sta, sband->band, i) &&
++			    !(rate->flags & IEEE80211_RATE_ERP_G))
++				sel->nonerp = rate;
++		}
++	}
++
++	rcu_read_unlock();
++}
++
++struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
++{
++	kref_get(&ref->kref);
++	return ref;
++}
++
++void rate_control_put(struct rate_control_ref *ref)
++{
++	kref_put(&ref->kref, rate_control_release);
++}
++
++int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
++				 const char *name)
++{
++	struct rate_control_ref *ref, *old;
++
++	ASSERT_RTNL();
++	if (local->open_count || netif_running(local->mdev))
++		return -EBUSY;
++
++	ref = rate_control_alloc(name, local);
++	if (!ref) {
++		printk(KERN_WARNING "%s: Failed to select rate control "
++		       "algorithm\n", wiphy_name(local->hw.wiphy));
++		return -ENOENT;
++	}
++
++	old = local->rate_ctrl;
++	local->rate_ctrl = ref;
++	if (old) {
++		rate_control_put(old);
++		sta_info_flush(local, NULL);
++	}
++
++	printk(KERN_DEBUG "%s: Selected rate control "
++	       "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
++	       ref->ops->name);
++
++
++	return 0;
++}
++
++void rate_control_deinitialize(struct ieee80211_local *local)
++{
++	struct rate_control_ref *ref;
++
++	ref = local->rate_ctrl;
++	local->rate_ctrl = NULL;
++	rate_control_put(ref);
++}
++
+diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
+new file mode 100644
+index 0000000..5b45f33
+--- /dev/null
++++ b/net/mac80211/rate.h
+@@ -0,0 +1,189 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005, Devicescape Software, Inc.
++ * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef IEEE80211_RATE_H
++#define IEEE80211_RATE_H
++
++#include <linux/netdevice.h>
++#include <linux/skbuff.h>
++#include <linux/types.h>
++#include <linux/kref.h>
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "sta_info.h"
++
++/* TODO: kdoc */
++struct rate_selection {
++	/* Selected transmission rate */
++	struct ieee80211_rate *rate;
++	/* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */
++	struct ieee80211_rate *nonerp;
++	/* probe with this rate, or NULL for no probing */
++	struct ieee80211_rate *probe;
++};
++
++struct rate_control_ops {
++	struct module *module;
++	const char *name;
++	void (*tx_status)(void *priv, struct net_device *dev,
++			  struct sk_buff *skb,
++			  struct ieee80211_tx_status *status);
++	void (*get_rate)(void *priv, struct net_device *dev,
++			 struct ieee80211_supported_band *band,
++			 struct sk_buff *skb,
++			 struct rate_selection *sel);
++	void (*rate_init)(void *priv, void *priv_sta,
++			  struct ieee80211_local *local, struct sta_info *sta);
++	void (*clear)(void *priv);
++
++	void *(*alloc)(struct ieee80211_local *local);
++	void (*free)(void *priv);
++	void *(*alloc_sta)(void *priv, gfp_t gfp);
++	void (*free_sta)(void *priv, void *priv_sta);
++
++	int (*add_attrs)(void *priv, struct kobject *kobj);
++	void (*remove_attrs)(void *priv, struct kobject *kobj);
++	void (*add_sta_debugfs)(void *priv, void *priv_sta,
++				struct dentry *dir);
++	void (*remove_sta_debugfs)(void *priv, void *priv_sta);
++};
++
++struct rate_control_ref {
++	struct rate_control_ops *ops;
++	void *priv;
++	struct kref kref;
++};
++
++int ieee80211_rate_control_register(struct rate_control_ops *ops);
++void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
++
++/* Get a reference to the rate control algorithm. If `name' is NULL, get the
++ * first available algorithm. */
++struct rate_control_ref *rate_control_alloc(const char *name,
++					    struct ieee80211_local *local);
++void rate_control_get_rate(struct net_device *dev,
++			   struct ieee80211_supported_band *sband,
++			   struct sk_buff *skb,
++			   struct rate_selection *sel);
++struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
++void rate_control_put(struct rate_control_ref *ref);
++
++static inline void rate_control_tx_status(struct net_device *dev,
++					  struct sk_buff *skb,
++					  struct ieee80211_tx_status *status)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct rate_control_ref *ref = local->rate_ctrl;
++
++	ref->ops->tx_status(ref->priv, dev, skb, status);
++}
++
++
++static inline void rate_control_rate_init(struct sta_info *sta,
++					  struct ieee80211_local *local)
++{
++	struct rate_control_ref *ref = sta->rate_ctrl;
++	ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta);
++}
++
++
++static inline void rate_control_clear(struct ieee80211_local *local)
++{
++	struct rate_control_ref *ref = local->rate_ctrl;
++	ref->ops->clear(ref->priv);
++}
++
++static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
++					   gfp_t gfp)
++{
++	return ref->ops->alloc_sta(ref->priv, gfp);
++}
++
++static inline void rate_control_free_sta(struct rate_control_ref *ref,
++					 void *priv)
++{
++	ref->ops->free_sta(ref->priv, priv);
++}
++
++static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
++{
++#ifdef CONFIG_MAC80211_DEBUGFS
++	struct rate_control_ref *ref = sta->rate_ctrl;
++	if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
++		ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
++					  sta->debugfs.dir);
++#endif
++}
++
++static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
++{
++#ifdef CONFIG_MAC80211_DEBUGFS
++	struct rate_control_ref *ref = sta->rate_ctrl;
++	if (ref->ops->remove_sta_debugfs)
++		ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
++#endif
++}
++
++static inline int rate_supported(struct sta_info *sta,
++				 enum ieee80211_band band,
++				 int index)
++{
++	return (sta == NULL || sta->supp_rates[band] & BIT(index));
++}
++
++static inline int
++rate_lowest_index(struct ieee80211_local *local,
++		  struct ieee80211_supported_band *sband,
++		  struct sta_info *sta)
++{
++	int i;
++
++	for (i = 0; i < sband->n_bitrates; i++)
++		if (rate_supported(sta, sband->band, i))
++			return i;
++
++	/* warn when we cannot find a rate. */
++	WARN_ON(1);
++
++	return 0;
++}
++
++static inline struct ieee80211_rate *
++rate_lowest(struct ieee80211_local *local,
++	    struct ieee80211_supported_band *sband,
++	    struct sta_info *sta)
++{
++	return &sband->bitrates[rate_lowest_index(local, sband, sta)];
++}
++
++
++/* functions for rate control related to a device */
++int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
++				 const char *name);
++void rate_control_deinitialize(struct ieee80211_local *local);
++
++
++/* Rate control algorithms */
++#if defined(RC80211_PID_COMPILE) || \
++	(defined(CONFIG_MAC80211_RC_PID) && \
++	 !defined(CONFIG_MAC80211_RC_PID_MODULE))
++extern int rc80211_pid_init(void);
++extern void rc80211_pid_exit(void);
++#else
++static inline int rc80211_pid_init(void)
++{
++	return 0;
++}
++static inline void rc80211_pid_exit(void)
++{
++}
++#endif
++
++#endif /* IEEE80211_RATE_H */
+diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
+index 3b77410..a849b74 100644
+--- a/net/mac80211/rc80211_pid_algo.c
++++ b/net/mac80211/rc80211_pid_algo.c
+@@ -14,8 +14,8 @@
+ #include <linux/skbuff.h>
+ #include <linux/debugfs.h>
+ #include <net/mac80211.h>
+-#include "ieee80211_rate.h"
+-
++#include "rate.h"
++#include "mesh.h"
+ #include "rc80211_pid.h"
+ 
+ 
+@@ -63,6 +63,7 @@
+  * RC_PID_ARITH_SHIFT.
+  */
+ 
++
+ /* Adjust the rate while ensuring that we won't switch to a lower rate if it
+  * exhibited a worse failed frames behaviour and we'll choose the highest rate
+  * whose failed frames behaviour is not worse than the one of the original rate
+@@ -72,14 +73,14 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
+ 					 struct rc_pid_rateinfo *rinfo)
+ {
+ 	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_hw_mode *mode;
+-	int cur_sorted, new_sorted, probe, tmp, n_bitrates;
+-	int cur = sta->txrate;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++	struct ieee80211_supported_band *sband;
++	int cur_sorted, new_sorted, probe, tmp, n_bitrates, band;
++	int cur = sta->txrate_idx;
+ 
+-	mode = local->oper_hw_mode;
+-	n_bitrates = mode->num_rates;
++	sdata = sta->sdata;
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++	band = sband->band;
++	n_bitrates = sband->n_bitrates;
+ 
+ 	/* Map passed arguments to sorted values. */
+ 	cur_sorted = rinfo[cur].rev_index;
+@@ -97,20 +98,20 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
+ 		/* Ensure that the rate decrease isn't disadvantageous. */
+ 		for (probe = cur_sorted; probe >= new_sorted; probe--)
+ 			if (rinfo[probe].diff <= rinfo[cur_sorted].diff &&
+-			    rate_supported(sta, mode, rinfo[probe].index))
++			    rate_supported(sta, band, rinfo[probe].index))
+ 				tmp = probe;
+ 	} else {
+ 		/* Look for rate increase with zero (or below) cost. */
+ 		for (probe = new_sorted + 1; probe < n_bitrates; probe++)
+ 			if (rinfo[probe].diff <= rinfo[new_sorted].diff &&
+-			    rate_supported(sta, mode, rinfo[probe].index))
++			    rate_supported(sta, band, rinfo[probe].index))
+ 				tmp = probe;
+ 	}
+ 
+ 	/* Fit the rate found to the nearest supported rate. */
+ 	do {
+-		if (rate_supported(sta, mode, rinfo[tmp].index)) {
+-			sta->txrate = rinfo[tmp].index;
++		if (rate_supported(sta, band, rinfo[tmp].index)) {
++			sta->txrate_idx = rinfo[tmp].index;
+ 			break;
+ 		}
+ 		if (adj < 0)
+@@ -122,7 +123,7 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ 	rate_control_pid_event_rate_change(
+ 		&((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events,
+-		cur, mode->rates[cur].rate);
++		sta->txrate_idx, sband->bitrates[sta->txrate_idx].bitrate);
+ #endif
+ }
+ 
+@@ -147,9 +148,12 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
+ 				    struct ieee80211_local *local,
+ 				    struct sta_info *sta)
+ {
++#ifdef CONFIG_MAC80211_MESH
++	struct ieee80211_sub_if_data *sdata = sta->sdata;
++#endif
+ 	struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv;
+ 	struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
+-	struct ieee80211_hw_mode *mode;
++	struct ieee80211_supported_band *sband;
+ 	u32 pf;
+ 	s32 err_avg;
+ 	u32 err_prop;
+@@ -158,7 +162,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
+ 	int adj, i, j, tmp;
+ 	unsigned long period;
+ 
+-	mode = local->oper_hw_mode;
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ 	spinfo = sta->rate_ctrl_priv;
+ 
+ 	/* In case nothing happened during the previous control interval, turn
+@@ -177,25 +181,32 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
+ 		pf = spinfo->last_pf;
+ 	else {
+ 		pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
++#ifdef CONFIG_MAC80211_MESH
++		if (pf == 100 &&
++		    sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
++			mesh_plink_broken(sta);
++#endif
+ 		pf <<= RC_PID_ARITH_SHIFT;
++		sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
++					>> RC_PID_ARITH_SHIFT;
+ 	}
+ 
+ 	spinfo->tx_num_xmit = 0;
+ 	spinfo->tx_num_failed = 0;
+ 
+ 	/* If we just switched rate, update the rate behaviour info. */
+-	if (pinfo->oldrate != sta->txrate) {
++	if (pinfo->oldrate != sta->txrate_idx) {
+ 
+ 		i = rinfo[pinfo->oldrate].rev_index;
+-		j = rinfo[sta->txrate].rev_index;
++		j = rinfo[sta->txrate_idx].rev_index;
+ 
+ 		tmp = (pf - spinfo->last_pf);
+ 		tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT);
+ 
+ 		rinfo[j].diff = rinfo[i].diff + tmp;
+-		pinfo->oldrate = sta->txrate;
++		pinfo->oldrate = sta->txrate_idx;
+ 	}
+-	rate_control_pid_normalize(pinfo, mode->num_rates);
++	rate_control_pid_normalize(pinfo, sband->n_bitrates);
+ 
+ 	/* Compute the proportional, integral and derivative errors. */
+ 	err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf;
+@@ -236,23 +247,27 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
+ 	struct sta_info *sta;
+ 	struct rc_pid_sta_info *spinfo;
+ 	unsigned long period;
++	struct ieee80211_supported_band *sband;
++
++	rcu_read_lock();
+ 
+ 	sta = sta_info_get(local, hdr->addr1);
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ 
+ 	if (!sta)
+-		return;
++		goto unlock;
+ 
+ 	/* Don't update the state if we're not controlling the rate. */
+-	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++	sdata = sta->sdata;
+ 	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+-		sta->txrate = sdata->bss->max_ratectrl_rateidx;
+-		return;
++		sta->txrate_idx = sdata->bss->max_ratectrl_rateidx;
++		goto unlock;
+ 	}
+ 
+ 	/* Ignore all frames that were sent with a different rate than the rate
+ 	 * we currently advise mac80211 to use. */
+-	if (status->control.rate != &local->oper_hw_mode->rates[sta->txrate])
+-		goto ignore;
++	if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx])
++		goto unlock;
+ 
+ 	spinfo = sta->rate_ctrl_priv;
+ 	spinfo->tx_num_xmit++;
+@@ -277,9 +292,6 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
+ 		sta->tx_num_consecutive_failures++;
+ 		sta->tx_num_mpdu_fail++;
+ 	} else {
+-		sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
+-		sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
+-		sta->last_ack_rssi[2] = status->ack_signal;
+ 		sta->tx_num_consecutive_failures = 0;
+ 		sta->tx_num_mpdu_ok++;
+ 	}
+@@ -293,12 +305,12 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
+ 	if (time_after(jiffies, spinfo->last_sample + period))
+ 		rate_control_pid_sample(pinfo, local, sta);
+ 
+-ignore:
+-	sta_info_put(sta);
++ unlock:
++	rcu_read_unlock();
+ }
+ 
+ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
+-				      struct ieee80211_hw_mode *mode,
++				      struct ieee80211_supported_band *sband,
+ 				      struct sk_buff *skb,
+ 				      struct rate_selection *sel)
+ {
+@@ -309,6 +321,8 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
+ 	int rateidx;
+ 	u16 fc;
+ 
++	rcu_read_lock();
++
+ 	sta = sta_info_get(local, hdr->addr1);
+ 
+ 	/* Send management frames and broadcast/multicast data using lowest
+@@ -316,32 +330,31 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
+ 	fc = le16_to_cpu(hdr->frame_control);
+ 	if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+ 	    is_multicast_ether_addr(hdr->addr1) || !sta) {
+-		sel->rate = rate_lowest(local, mode, sta);
+-		if (sta)
+-			sta_info_put(sta);
++		sel->rate = rate_lowest(local, sband, sta);
++		rcu_read_unlock();
+ 		return;
+ 	}
+ 
+ 	/* If a forced rate is in effect, select it. */
+ 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ 	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
+-		sta->txrate = sdata->bss->force_unicast_rateidx;
++		sta->txrate_idx = sdata->bss->force_unicast_rateidx;
+ 
+-	rateidx = sta->txrate;
++	rateidx = sta->txrate_idx;
+ 
+-	if (rateidx >= mode->num_rates)
+-		rateidx = mode->num_rates - 1;
++	if (rateidx >= sband->n_bitrates)
++		rateidx = sband->n_bitrates - 1;
+ 
+-	sta->last_txrate = rateidx;
++	sta->last_txrate_idx = rateidx;
+ 
+-	sta_info_put(sta);
++	rcu_read_unlock();
+ 
+-	sel->rate = &mode->rates[rateidx];
++	sel->rate = &sband->bitrates[rateidx];
+ 
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ 	rate_control_pid_event_tx_rate(
+ 		&((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events,
+-		rateidx, mode->rates[rateidx].rate);
++		rateidx, sband->bitrates[rateidx].bitrate);
+ #endif
+ }
+ 
+@@ -353,28 +366,33 @@ static void rate_control_pid_rate_init(void *priv, void *priv_sta,
+ 	 * as we need to have IEEE 802.1X auth succeed immediately after assoc..
+ 	 * Until that method is implemented, we will use the lowest supported
+ 	 * rate as a workaround. */
+-	sta->txrate = rate_lowest_index(local, local->oper_hw_mode, sta);
++	struct ieee80211_supported_band *sband;
++
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++	sta->txrate_idx = rate_lowest_index(local, sband, sta);
++	sta->fail_avg = 0;
+ }
+ 
+ static void *rate_control_pid_alloc(struct ieee80211_local *local)
+ {
+ 	struct rc_pid_info *pinfo;
+ 	struct rc_pid_rateinfo *rinfo;
+-	struct ieee80211_hw_mode *mode;
++	struct ieee80211_supported_band *sband;
+ 	int i, j, tmp;
+ 	bool s;
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ 	struct rc_pid_debugfs_entries *de;
+ #endif
+ 
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
+ 	pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC);
+ 	if (!pinfo)
+ 		return NULL;
+ 
+-	/* We can safely assume that oper_hw_mode won't change unless we get
++	/* We can safely assume that sband won't change unless we get
+ 	 * reinitialized. */
+-	mode = local->oper_hw_mode;
+-	rinfo = kmalloc(sizeof(*rinfo) * mode->num_rates, GFP_ATOMIC);
++	rinfo = kmalloc(sizeof(*rinfo) * sband->n_bitrates, GFP_ATOMIC);
+ 	if (!rinfo) {
+ 		kfree(pinfo);
+ 		return NULL;
+@@ -383,7 +401,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
+ 	/* Sort the rates. This is optimized for the most common case (i.e.
+ 	 * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed
+ 	 * mapping too. */
+-	for (i = 0; i < mode->num_rates; i++) {
++	for (i = 0; i < sband->n_bitrates; i++) {
+ 		rinfo[i].index = i;
+ 		rinfo[i].rev_index = i;
+ 		if (pinfo->fast_start)
+@@ -391,11 +409,11 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
+ 		else
+ 			rinfo[i].diff = i * pinfo->norm_offset;
+ 	}
+-	for (i = 1; i < mode->num_rates; i++) {
++	for (i = 1; i < sband->n_bitrates; i++) {
+ 		s = 0;
+-		for (j = 0; j < mode->num_rates - i; j++)
+-			if (unlikely(mode->rates[rinfo[j].index].rate >
+-				     mode->rates[rinfo[j + 1].index].rate)) {
++		for (j = 0; j < sband->n_bitrates - i; j++)
++			if (unlikely(sband->bitrates[rinfo[j].index].bitrate >
++				     sband->bitrates[rinfo[j + 1].index].bitrate)) {
+ 				tmp = rinfo[j].index;
+ 				rinfo[j].index = rinfo[j + 1].index;
+ 				rinfo[j + 1].index = tmp;
+diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c
+index 88b8dc9..ae75d41 100644
+--- a/net/mac80211/rc80211_pid_debugfs.c
++++ b/net/mac80211/rc80211_pid_debugfs.c
+@@ -13,7 +13,7 @@
+ #include <linux/skbuff.h>
+ 
+ #include <net/mac80211.h>
+-#include "ieee80211_rate.h"
++#include "rate.h"
+ 
+ #include "rc80211_pid.h"
+ 
+diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
+deleted file mode 100644
+index 9a78b11..0000000
+--- a/net/mac80211/rc80211_simple.c
++++ /dev/null
+@@ -1,400 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005, Devicescape Software, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/netdevice.h>
+-#include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/skbuff.h>
+-#include <linux/compiler.h>
+-#include <linux/module.h>
+-
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
+-#include "debugfs.h"
+-
+-
+-/* This is a minimal implementation of TX rate controlling that can be used
+- * as the default when no improved mechanisms are available. */
+-
+-#define RATE_CONTROL_NUM_DOWN 20
+-#define RATE_CONTROL_NUM_UP   15
+-
+-#define RATE_CONTROL_EMERG_DEC 2
+-#define RATE_CONTROL_INTERVAL (HZ / 20)
+-#define RATE_CONTROL_MIN_TX 10
+-
+-static void rate_control_rate_inc(struct ieee80211_local *local,
+-				  struct sta_info *sta)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_hw_mode *mode;
+-	int i = sta->txrate;
+-	int maxrate;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+-	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+-		/* forced unicast rate - do not change STA rate */
+-		return;
+-	}
+-
+-	mode = local->oper_hw_mode;
+-	maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;
+-
+-	if (i > mode->num_rates)
+-		i = mode->num_rates - 2;
+-
+-	while (i + 1 < mode->num_rates) {
+-		i++;
+-		if (sta->supp_rates & BIT(i) &&
+-		    mode->rates[i].flags & IEEE80211_RATE_SUPPORTED &&
+-		    (maxrate < 0 || i <= maxrate)) {
+-			sta->txrate = i;
+-			break;
+-		}
+-	}
+-}
+-
+-
+-static void rate_control_rate_dec(struct ieee80211_local *local,
+-				  struct sta_info *sta)
+-{
+-	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_hw_mode *mode;
+-	int i = sta->txrate;
+-
+-	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+-	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+-		/* forced unicast rate - do not change STA rate */
+-		return;
+-	}
+-
+-	mode = local->oper_hw_mode;
+-	if (i > mode->num_rates)
+-		i = mode->num_rates;
+-
+-	while (i > 0) {
+-		i--;
+-		if (sta->supp_rates & BIT(i) &&
+-		    mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) {
+-			sta->txrate = i;
+-			break;
+-		}
+-	}
+-}
+-
+-struct global_rate_control {
+-	int dummy;
+-};
+-
+-struct sta_rate_control {
+-	unsigned long last_rate_change;
+-	u32 tx_num_failures;
+-	u32 tx_num_xmit;
+-
+-	unsigned long avg_rate_update;
+-	u32 tx_avg_rate_sum;
+-	u32 tx_avg_rate_num;
+-
+-#ifdef CONFIG_MAC80211_DEBUGFS
+-	struct dentry *tx_avg_rate_sum_dentry;
+-	struct dentry *tx_avg_rate_num_dentry;
+-#endif
+-};
+-
+-
+-static void rate_control_simple_tx_status(void *priv, struct net_device *dev,
+-					  struct sk_buff *skb,
+-					  struct ieee80211_tx_status *status)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-	struct sta_info *sta;
+-	struct sta_rate_control *srctrl;
+-
+-	sta = sta_info_get(local, hdr->addr1);
+-
+-	if (!sta)
+-	    return;
+-
+-	srctrl = sta->rate_ctrl_priv;
+-	srctrl->tx_num_xmit++;
+-	if (status->excessive_retries) {
+-		srctrl->tx_num_failures++;
+-		sta->tx_retry_failed++;
+-		sta->tx_num_consecutive_failures++;
+-		sta->tx_num_mpdu_fail++;
+-	} else {
+-		sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
+-		sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
+-		sta->last_ack_rssi[2] = status->ack_signal;
+-		sta->tx_num_consecutive_failures = 0;
+-		sta->tx_num_mpdu_ok++;
+-	}
+-	sta->tx_retry_count += status->retry_count;
+-	sta->tx_num_mpdu_fail += status->retry_count;
+-
+-	if (time_after(jiffies,
+-		       srctrl->last_rate_change + RATE_CONTROL_INTERVAL) &&
+-		srctrl->tx_num_xmit > RATE_CONTROL_MIN_TX) {
+-		u32 per_failed;
+-		srctrl->last_rate_change = jiffies;
+-
+-		per_failed = (100 * sta->tx_num_mpdu_fail) /
+-			(sta->tx_num_mpdu_fail + sta->tx_num_mpdu_ok);
+-		/* TODO: calculate average per_failed to make adjusting
+-		 * parameters easier */
+-#if 0
+-		if (net_ratelimit()) {
+-			printk(KERN_DEBUG "MPDU fail=%d ok=%d per_failed=%d\n",
+-			       sta->tx_num_mpdu_fail, sta->tx_num_mpdu_ok,
+-			       per_failed);
+-		}
+-#endif
+-
+-		/*
+-		 * XXX: Make these configurable once we have an
+-		 * interface to the rate control algorithms
+-		 */
+-		if (per_failed > RATE_CONTROL_NUM_DOWN) {
+-			rate_control_rate_dec(local, sta);
+-		} else if (per_failed < RATE_CONTROL_NUM_UP) {
+-			rate_control_rate_inc(local, sta);
+-		}
+-		srctrl->tx_avg_rate_sum += status->control.rate->rate;
+-		srctrl->tx_avg_rate_num++;
+-		srctrl->tx_num_failures = 0;
+-		srctrl->tx_num_xmit = 0;
+-	} else if (sta->tx_num_consecutive_failures >=
+-		   RATE_CONTROL_EMERG_DEC) {
+-		rate_control_rate_dec(local, sta);
+-	}
+-
+-	if (srctrl->avg_rate_update + 60 * HZ < jiffies) {
+-		srctrl->avg_rate_update = jiffies;
+-		if (srctrl->tx_avg_rate_num > 0) {
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+-			DECLARE_MAC_BUF(mac);
+-			printk(KERN_DEBUG "%s: STA %s Average rate: "
+-			       "%d (%d/%d)\n",
+-			       dev->name, print_mac(mac, sta->addr),
+-			       srctrl->tx_avg_rate_sum /
+-			       srctrl->tx_avg_rate_num,
+-			       srctrl->tx_avg_rate_sum,
+-			       srctrl->tx_avg_rate_num);
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+-			srctrl->tx_avg_rate_sum = 0;
+-			srctrl->tx_avg_rate_num = 0;
+-		}
+-	}
+-
+-	sta_info_put(sta);
+-}
+-
+-
+-static void
+-rate_control_simple_get_rate(void *priv, struct net_device *dev,
+-			     struct ieee80211_hw_mode *mode,
+-			     struct sk_buff *skb,
+-			     struct rate_selection *sel)
+-{
+-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-	struct ieee80211_sub_if_data *sdata;
+-	struct sta_info *sta;
+-	int rateidx;
+-	u16 fc;
+-
+-	sta = sta_info_get(local, hdr->addr1);
+-
+-	/* Send management frames and broadcast/multicast data using lowest
+-	 * rate. */
+-	fc = le16_to_cpu(hdr->frame_control);
+-	if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+-	    is_multicast_ether_addr(hdr->addr1) || !sta) {
+-		sel->rate = rate_lowest(local, mode, sta);
+-		if (sta)
+-			sta_info_put(sta);
+-		return;
+-	}
+-
+-	/* If a forced rate is in effect, select it. */
+-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
+-		sta->txrate = sdata->bss->force_unicast_rateidx;
+-
+-	rateidx = sta->txrate;
+-
+-	if (rateidx >= mode->num_rates)
+-		rateidx = mode->num_rates - 1;
+-
+-	sta->last_txrate = rateidx;
+-
+-	sta_info_put(sta);
+-
+-	sel->rate = &mode->rates[rateidx];
+-}
+-
+-
+-static void rate_control_simple_rate_init(void *priv, void *priv_sta,
+-					  struct ieee80211_local *local,
+-					  struct sta_info *sta)
+-{
+-	struct ieee80211_hw_mode *mode;
+-	int i;
+-	sta->txrate = 0;
+-	mode = local->oper_hw_mode;
+-	/* TODO: This routine should consider using RSSI from previous packets
+-	 * as we need to have IEEE 802.1X auth succeed immediately after assoc..
+-	 * Until that method is implemented, we will use the lowest supported rate
+-	 * as a workaround, */
+-	for (i = 0; i < mode->num_rates; i++) {
+-		if ((sta->supp_rates & BIT(i)) &&
+-		    (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) {
+-			sta->txrate = i;
+-			break;
+-		}
+-	}
+-}
+-
+-
+-static void * rate_control_simple_alloc(struct ieee80211_local *local)
+-{
+-	struct global_rate_control *rctrl;
+-
+-	rctrl = kzalloc(sizeof(*rctrl), GFP_ATOMIC);
+-
+-	return rctrl;
+-}
+-
+-
+-static void rate_control_simple_free(void *priv)
+-{
+-	struct global_rate_control *rctrl = priv;
+-	kfree(rctrl);
+-}
+-
+-
+-static void rate_control_simple_clear(void *priv)
+-{
+-}
+-
+-
+-static void * rate_control_simple_alloc_sta(void *priv, gfp_t gfp)
+-{
+-	struct sta_rate_control *rctrl;
+-
+-	rctrl = kzalloc(sizeof(*rctrl), gfp);
+-
+-	return rctrl;
+-}
+-
+-
+-static void rate_control_simple_free_sta(void *priv, void *priv_sta)
+-{
+-	struct sta_rate_control *rctrl = priv_sta;
+-	kfree(rctrl);
+-}
+-
+-#ifdef CONFIG_MAC80211_DEBUGFS
+-
+-static int open_file_generic(struct inode *inode, struct file *file)
+-{
+-	file->private_data = inode->i_private;
+-	return 0;
+-}
+-
+-static ssize_t sta_tx_avg_rate_sum_read(struct file *file,
+-					char __user *userbuf,
+-					size_t count, loff_t *ppos)
+-{
+-	struct sta_rate_control *srctrl = file->private_data;
+-	char buf[20];
+-
+-	sprintf(buf, "%d\n", srctrl->tx_avg_rate_sum);
+-	return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+-}
+-
+-static const struct file_operations sta_tx_avg_rate_sum_ops = {
+-	.read = sta_tx_avg_rate_sum_read,
+-	.open = open_file_generic,
+-};
+-
+-static ssize_t sta_tx_avg_rate_num_read(struct file *file,
+-					char __user *userbuf,
+-					size_t count, loff_t *ppos)
+-{
+-	struct sta_rate_control *srctrl = file->private_data;
+-	char buf[20];
+-
+-	sprintf(buf, "%d\n", srctrl->tx_avg_rate_num);
+-	return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+-}
+-
+-static const struct file_operations sta_tx_avg_rate_num_ops = {
+-	.read = sta_tx_avg_rate_num_read,
+-	.open = open_file_generic,
+-};
+-
+-static void rate_control_simple_add_sta_debugfs(void *priv, void *priv_sta,
+-						struct dentry *dir)
+-{
+-	struct sta_rate_control *srctrl = priv_sta;
+-
+-	srctrl->tx_avg_rate_num_dentry =
+-		debugfs_create_file("rc_simple_sta_tx_avg_rate_num", 0400,
+-				    dir, srctrl, &sta_tx_avg_rate_num_ops);
+-	srctrl->tx_avg_rate_sum_dentry =
+-		debugfs_create_file("rc_simple_sta_tx_avg_rate_sum", 0400,
+-				    dir, srctrl, &sta_tx_avg_rate_sum_ops);
+-}
+-
+-static void rate_control_simple_remove_sta_debugfs(void *priv, void *priv_sta)
+-{
+-	struct sta_rate_control *srctrl = priv_sta;
+-
+-	debugfs_remove(srctrl->tx_avg_rate_sum_dentry);
+-	debugfs_remove(srctrl->tx_avg_rate_num_dentry);
+-}
+-#endif
+-
+-static struct rate_control_ops mac80211_rcsimple = {
+-	.name = "simple",
+-	.tx_status = rate_control_simple_tx_status,
+-	.get_rate = rate_control_simple_get_rate,
+-	.rate_init = rate_control_simple_rate_init,
+-	.clear = rate_control_simple_clear,
+-	.alloc = rate_control_simple_alloc,
+-	.free = rate_control_simple_free,
+-	.alloc_sta = rate_control_simple_alloc_sta,
+-	.free_sta = rate_control_simple_free_sta,
+-#ifdef CONFIG_MAC80211_DEBUGFS
+-	.add_sta_debugfs = rate_control_simple_add_sta_debugfs,
+-	.remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
+-#endif
+-};
+-
+-MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("Simple rate control algorithm");
+-
+-int __init rc80211_simple_init(void)
+-{
+-	return ieee80211_rate_control_register(&mac80211_rcsimple);
+-}
+-
+-void rc80211_simple_exit(void)
+-{
+-	ieee80211_rate_control_unregister(&mac80211_rcsimple);
+-}
+-
+-#ifdef CONFIG_MAC80211_RC_SIMPLE_MODULE
+-module_init(rc80211_simple_init);
+-module_exit(rc80211_simple_exit);
+-#endif
+diff --git a/net/mac80211/regdomain.c b/net/mac80211/regdomain.c
+deleted file mode 100644
+index f42678f..0000000
+--- a/net/mac80211/regdomain.c
++++ /dev/null
+@@ -1,152 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/*
+- * This regulatory domain control implementation is known to be incomplete
+- * and confusing. mac80211 regulatory domain control will be significantly
+- * reworked in the not-too-distant future.
+- *
+- * For now, drivers wishing to control which channels are and aren't available
+- * are advised as follows:
+- *  - set the IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED flag
+- *  - continue to include *ALL* possible channels in the modes registered
+- *    through ieee80211_register_hwmode()
+- *  - for each allowable ieee80211_channel structure registered in the above
+- *    call, set the flag member to some meaningful value such as
+- *    IEEE80211_CHAN_W_SCAN | IEEE80211_CHAN_W_ACTIVE_SCAN |
+- *    IEEE80211_CHAN_W_IBSS.
+- *  - leave flag as 0 for non-allowable channels
+- *
+- * The usual implementation is for a driver to read a device EEPROM to
+- * determine which regulatory domain it should be operating under, then
+- * looking up the allowable channels in a driver-local table, then performing
+- * the above.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/netdevice.h>
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-
+-static int ieee80211_regdom = 0x10; /* FCC */
+-module_param(ieee80211_regdom, int, 0444);
+-MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain; 64=MKK");
+-
+-/*
+- * If firmware is upgraded by the vendor, additional channels can be used based
+- * on the new Japanese regulatory rules. This is indicated by setting
+- * ieee80211_japan_5ghz module parameter to one when loading the 80211 kernel
+- * module.
+- */
+-static int ieee80211_japan_5ghz /* = 0 */;
+-module_param(ieee80211_japan_5ghz, int, 0444);
+-MODULE_PARM_DESC(ieee80211_japan_5ghz, "Vendor-updated firmware for 5 GHz");
+-
+-
+-struct ieee80211_channel_range {
+-	short start_freq;
+-	short end_freq;
+-	unsigned char power_level;
+-	unsigned char antenna_max;
+-};
+-
+-static const struct ieee80211_channel_range ieee80211_fcc_channels[] = {
+-	{ 2412, 2462, 27, 6 } /* IEEE 802.11b/g, channels 1..11 */,
+-	{ 5180, 5240, 17, 6 } /* IEEE 802.11a, channels 36..48 */,
+-	{ 5260, 5320, 23, 6 } /* IEEE 802.11a, channels 52..64 */,
+-	{ 5745, 5825, 30, 6 } /* IEEE 802.11a, channels 149..165, outdoor */,
+-	{ 0 }
+-};
+-
+-static const struct ieee80211_channel_range ieee80211_mkk_channels[] = {
+-	{ 2412, 2472, 20, 6 } /* IEEE 802.11b/g, channels 1..13 */,
+-	{ 5170, 5240, 20, 6 } /* IEEE 802.11a, channels 34..48 */,
+-	{ 5260, 5320, 20, 6 } /* IEEE 802.11a, channels 52..64 */,
+-	{ 0 }
+-};
+-
+-
+-static const struct ieee80211_channel_range *channel_range =
+-	ieee80211_fcc_channels;
+-
+-
+-static void ieee80211_unmask_channel(int mode, struct ieee80211_channel *chan)
+-{
+-	int i;
+-
+-	chan->flag = 0;
+-
+-	for (i = 0; channel_range[i].start_freq; i++) {
+-		const struct ieee80211_channel_range *r = &channel_range[i];
+-		if (r->start_freq <= chan->freq && r->end_freq >= chan->freq) {
+-			if (ieee80211_regdom == 64 && !ieee80211_japan_5ghz &&
+-			    chan->freq >= 5260 && chan->freq <= 5320) {
+-				/*
+-				 * Skip new channels in Japan since the
+-				 * firmware was not marked having been upgraded
+-				 * by the vendor.
+-				 */
+-				continue;
+-			}
+-
+-			if (ieee80211_regdom == 0x10 &&
+-			    (chan->freq == 5190 || chan->freq == 5210 ||
+-			     chan->freq == 5230)) {
+-				    /* Skip MKK channels when in FCC domain. */
+-				    continue;
+-			}
+-
+-			chan->flag |= IEEE80211_CHAN_W_SCAN |
+-				IEEE80211_CHAN_W_ACTIVE_SCAN |
+-				IEEE80211_CHAN_W_IBSS;
+-			chan->power_level = r->power_level;
+-			chan->antenna_max = r->antenna_max;
+-
+-			if (ieee80211_regdom == 64 &&
+-			    (chan->freq == 5170 || chan->freq == 5190 ||
+-			     chan->freq == 5210 || chan->freq == 5230)) {
+-				/*
+-				 * New regulatory rules in Japan have backwards
+-				 * compatibility with old channels in 5.15-5.25
+-				 * GHz band, but the station is not allowed to
+-				 * use active scan on these old channels.
+-				 */
+-				chan->flag &= ~IEEE80211_CHAN_W_ACTIVE_SCAN;
+-			}
+-
+-			if (ieee80211_regdom == 64 &&
+-			    (chan->freq == 5260 || chan->freq == 5280 ||
+-			     chan->freq == 5300 || chan->freq == 5320)) {
+-				/*
+-				 * IBSS is not allowed on 5.25-5.35 GHz band
+-				 * due to radar detection requirements.
+-				 */
+-				chan->flag &= ~IEEE80211_CHAN_W_IBSS;
+-			}
+-
+-			break;
+-		}
+-	}
+-}
+-
+-
+-void ieee80211_set_default_regdomain(struct ieee80211_hw_mode *mode)
+-{
+-	int c;
+-	for (c = 0; c < mode->num_channels; c++)
+-		ieee80211_unmask_channel(mode->mode, &mode->channels[c]);
+-}
+-
+-
+-void ieee80211_regdomain_init(void)
+-{
+-	if (ieee80211_regdom == 0x40)
+-		channel_range = ieee80211_mkk_channels;
+-}
+-
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index a8a40ab..02f436a 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -9,6 +9,7 @@
+  * published by the Free Software Foundation.
+  */
+ 
++#include <linux/jiffies.h>
+ #include <linux/kernel.h>
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
+@@ -18,7 +19,8 @@
+ #include <net/ieee80211_radiotap.h>
+ 
+ #include "ieee80211_i.h"
+-#include "ieee80211_led.h"
++#include "led.h"
++#include "mesh.h"
+ #include "wep.h"
+ #include "wpa.h"
+ #include "tkip.h"
+@@ -82,10 +84,10 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status,
+  */
+ static struct sk_buff *
+ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
+-		     struct ieee80211_rx_status *status)
++		     struct ieee80211_rx_status *status,
++		     struct ieee80211_rate *rate)
+ {
+ 	struct ieee80211_sub_if_data *sdata;
+-	struct ieee80211_rate *rate;
+ 	int needed_headroom = 0;
+ 	struct ieee80211_radiotap_header *rthdr;
+ 	__le64 *rttsft = NULL;
+@@ -194,14 +196,11 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
+ 			rtfixed->rx_flags |=
+ 				cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
+ 
+-		rate = ieee80211_get_rate(local, status->phymode,
+-					  status->rate);
+-		if (rate)
+-			rtfixed->rate = rate->rate / 5;
++		rtfixed->rate = rate->bitrate / 5;
+ 
+ 		rtfixed->chan_freq = cpu_to_le16(status->freq);
+ 
+-		if (status->phymode == MODE_IEEE80211A)
++		if (status->band == IEEE80211_BAND_5GHZ)
+ 			rtfixed->chan_flags =
+ 				cpu_to_le16(IEEE80211_CHAN_OFDM |
+ 					    IEEE80211_CHAN_5GHZ);
+@@ -226,6 +225,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
+ 		if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR)
+ 			continue;
+ 
++		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
++			continue;
++
+ 		if (prev_dev) {
+ 			skb2 = skb_clone(skb, GFP_ATOMIC);
+ 			if (skb2) {
+@@ -249,15 +251,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
+ }
+ 
+ 
+-/* pre-rx handlers
+- *
+- * these don't have dev/sdata fields in the rx data
+- * The sta value should also not be used because it may
+- * be NULL even though a STA (in IBSS mode) will be added.
+- */
+-
+-static ieee80211_txrx_result
+-ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
++static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
+ {
+ 	u8 *data = rx->skb->data;
+ 	int tid;
+@@ -268,9 +262,9 @@ ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
+ 		/* frame has qos control */
+ 		tid = qc[0] & QOS_CONTROL_TID_MASK;
+ 		if (qc[0] & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+-			rx->flags |= IEEE80211_TXRXD_RX_AMSDU;
++			rx->flags |= IEEE80211_RX_AMSDU;
+ 		else
+-			rx->flags &= ~IEEE80211_TXRXD_RX_AMSDU;
++			rx->flags &= ~IEEE80211_RX_AMSDU;
+ 	} else {
+ 		if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) {
+ 			/* Separate TID for management frames */
+@@ -286,68 +280,19 @@ ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
+ 	if (rx->sta)
+ 		I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]);
+ 
+-	rx->u.rx.queue = tid;
++	rx->queue = tid;
+ 	/* Set skb->priority to 1d tag if highest order bit of TID is not set.
+ 	 * For now, set skb->priority to 0 for other cases. */
+ 	rx->skb->priority = (tid > 7) ? 0 : tid;
+-
+-	return TXRX_CONTINUE;
+ }
+ 
+-
+-static u32 ieee80211_rx_load_stats(struct ieee80211_local *local,
+-			      struct sk_buff *skb,
+-			      struct ieee80211_rx_status *status)
++static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
+ {
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-	u32 load = 0, hdrtime;
+-	struct ieee80211_rate *rate;
+-	struct ieee80211_hw_mode *mode = local->hw.conf.mode;
+-	int i;
+-
+-	/* Estimate total channel use caused by this frame */
+-
+-	if (unlikely(mode->num_rates < 0))
+-		return TXRX_CONTINUE;
+-
+-	rate = &mode->rates[0];
+-	for (i = 0; i < mode->num_rates; i++) {
+-		if (mode->rates[i].val == status->rate) {
+-			rate = &mode->rates[i];
+-			break;
+-		}
+-	}
+-
+-	/* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
+-	 * 1 usec = 1/8 * (1080 / 10) = 13.5 */
+-
+-	if (mode->mode == MODE_IEEE80211A ||
+-	    (mode->mode == MODE_IEEE80211G &&
+-	     rate->flags & IEEE80211_RATE_ERP))
+-		hdrtime = CHAN_UTIL_HDR_SHORT;
+-	else
+-		hdrtime = CHAN_UTIL_HDR_LONG;
+-
+-	load = hdrtime;
+-	if (!is_multicast_ether_addr(hdr->addr1))
+-		load += hdrtime;
+-
+-	load += skb->len * rate->rate_inv;
+-
+-	/* Divide channel_use by 8 to avoid wrapping around the counter */
+-	load >>= CHAN_UTIL_SHIFT;
+-
+-	return load;
+-}
+-
+ #ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
+-static ieee80211_txrx_result
+-ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx)
+-{
+ 	int hdrlen;
+ 
+ 	if (!WLAN_FC_DATA_PRESENT(rx->fc))
+-		return TXRX_CONTINUE;
++		return;
+ 
+ 	/*
+ 	 * Drivers are required to align the payload data in a way that
+@@ -369,83 +314,158 @@ ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx)
+ 	 * to move the 802.11 header further back in that case.
+ 	 */
+ 	hdrlen = ieee80211_get_hdrlen(rx->fc);
+-	if (rx->flags & IEEE80211_TXRXD_RX_AMSDU)
++	if (rx->flags & IEEE80211_RX_AMSDU)
+ 		hdrlen += ETH_HLEN;
+ 	WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3);
+-
+-	return TXRX_CONTINUE;
+-}
+ #endif
++}
+ 
+-ieee80211_rx_handler ieee80211_rx_pre_handlers[] =
++
++static u32 ieee80211_rx_load_stats(struct ieee80211_local *local,
++				   struct sk_buff *skb,
++				   struct ieee80211_rx_status *status,
++				   struct ieee80211_rate *rate)
+ {
+-	ieee80211_rx_h_parse_qos,
+-#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
+-	ieee80211_rx_h_verify_ip_alignment,
+-#endif
+-	NULL
+-};
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	u32 load = 0, hdrtime;
++
++	/* Estimate total channel use caused by this frame */
++
++	/* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
++	 * 1 usec = 1/8 * (1080 / 10) = 13.5 */
++
++	if (status->band == IEEE80211_BAND_5GHZ ||
++	    (status->band == IEEE80211_BAND_5GHZ &&
++	     rate->flags & IEEE80211_RATE_ERP_G))
++		hdrtime = CHAN_UTIL_HDR_SHORT;
++	else
++		hdrtime = CHAN_UTIL_HDR_LONG;
++
++	load = hdrtime;
++	if (!is_multicast_ether_addr(hdr->addr1))
++		load += hdrtime;
++
++	/* TODO: optimise again */
++	load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate;
++
++	/* Divide channel_use by 8 to avoid wrapping around the counter */
++	load >>= CHAN_UTIL_SHIFT;
++
++	return load;
++}
+ 
+ /* rx handlers */
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_if_stats(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_if_stats(struct ieee80211_rx_data *rx)
+ {
+ 	if (rx->sta)
+-		rx->sta->channel_use_raw += rx->u.rx.load;
+-	rx->sdata->channel_use_raw += rx->u.rx.load;
+-	return TXRX_CONTINUE;
++		rx->sta->channel_use_raw += rx->load;
++	rx->sdata->channel_use_raw += rx->load;
++	return RX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
+ {
+ 	struct ieee80211_local *local = rx->local;
+ 	struct sk_buff *skb = rx->skb;
+ 
+ 	if (unlikely(local->sta_hw_scanning))
+-		return ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status);
++		return ieee80211_sta_rx_scan(rx->dev, skb, rx->status);
+ 
+ 	if (unlikely(local->sta_sw_scanning)) {
+ 		/* drop all the other packets during a software scan anyway */
+-		if (ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status)
+-		    != TXRX_QUEUED)
++		if (ieee80211_sta_rx_scan(rx->dev, skb, rx->status)
++		    != RX_QUEUED)
+ 			dev_kfree_skb(skb);
+-		return TXRX_QUEUED;
++		return RX_QUEUED;
+ 	}
+ 
+-	if (unlikely(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) {
++	if (unlikely(rx->flags & IEEE80211_RX_IN_SCAN)) {
+ 		/* scanning finished during invoking of handlers */
+ 		I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
++}
++
++static ieee80211_rx_result
++ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
++{
++	int hdrlen = ieee80211_get_hdrlen(rx->fc);
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
++
++#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l))
++
++	if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
++		if (!((rx->fc & IEEE80211_FCTL_FROMDS) &&
++		      (rx->fc & IEEE80211_FCTL_TODS)))
++			return RX_DROP_MONITOR;
++		if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0)
++			return RX_DROP_MONITOR;
++	}
++
++	/* If there is not an established peer link and this is not a peer link
++	 * establisment frame, beacon or probe, drop the frame.
++	 */
++
++	if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) {
++		struct ieee80211_mgmt *mgmt;
++
++		if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
++			return RX_DROP_MONITOR;
++
++		switch (rx->fc & IEEE80211_FCTL_STYPE) {
++		case IEEE80211_STYPE_ACTION:
++			mgmt = (struct ieee80211_mgmt *)hdr;
++			if (mgmt->u.action.category != PLINK_CATEGORY)
++				return RX_DROP_MONITOR;
++			/* fall through on else */
++		case IEEE80211_STYPE_PROBE_REQ:
++		case IEEE80211_STYPE_PROBE_RESP:
++		case IEEE80211_STYPE_BEACON:
++			return RX_CONTINUE;
++			break;
++		default:
++			return RX_DROP_MONITOR;
++		}
++
++	 } else if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
++		    is_multicast_ether_addr(hdr->addr1) &&
++		    mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev))
++		return RX_DROP_MONITOR;
++#undef msh_h_get
++
++	return RX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
++
++static ieee80211_rx_result
++ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
+ {
+ 	struct ieee80211_hdr *hdr;
++
+ 	hdr = (struct ieee80211_hdr *) rx->skb->data;
+ 
+ 	/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
+ 	if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
+ 		if (unlikely(rx->fc & IEEE80211_FCTL_RETRY &&
+-			     rx->sta->last_seq_ctrl[rx->u.rx.queue] ==
++			     rx->sta->last_seq_ctrl[rx->queue] ==
+ 			     hdr->seq_ctrl)) {
+-			if (rx->flags & IEEE80211_TXRXD_RXRA_MATCH) {
++			if (rx->flags & IEEE80211_RX_RA_MATCH) {
+ 				rx->local->dot11FrameDuplicateCount++;
+ 				rx->sta->num_duplicates++;
+ 			}
+-			return TXRX_DROP;
++			return RX_DROP_MONITOR;
+ 		} else
+-			rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl;
++			rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl;
+ 	}
+ 
+ 	if (unlikely(rx->skb->len < 16)) {
+ 		I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
+-		return TXRX_DROP;
++		return RX_DROP_MONITOR;
+ 	}
+ 
+ 	/* Drop disallowed frame classes based on STA auth/assoc state;
+@@ -456,6 +476,10 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
+ 	 * deauth/disassoc frames when needed. In addition, hostapd is
+ 	 * responsible for filtering on both auth and assoc states.
+ 	 */
++
++	if (ieee80211_vif_is_mesh(&rx->sdata->vif))
++		return ieee80211_rx_mesh_check(rx);
++
+ 	if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA ||
+ 		      ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
+ 		       (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
+@@ -464,26 +488,26 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
+ 		if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
+ 		     !(rx->fc & IEEE80211_FCTL_TODS) &&
+ 		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+-		    || !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
++		    || !(rx->flags & IEEE80211_RX_RA_MATCH)) {
+ 			/* Drop IBSS frames and frames for other hosts
+ 			 * silently. */
+-			return TXRX_DROP;
++			return RX_DROP_MONITOR;
+ 		}
+ 
+-		return TXRX_DROP;
++		return RX_DROP_MONITOR;
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
+ }
+ 
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ 	int keyidx;
+ 	int hdrlen;
+-	ieee80211_txrx_result result = TXRX_DROP;
++	ieee80211_rx_result result = RX_DROP_UNUSABLE;
+ 	struct ieee80211_key *stakey = NULL;
+ 
+ 	/*
+@@ -513,14 +537,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+ 	 */
+ 
+ 	if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+ 	/*
+ 	 * No point in finding a key and decrypting if the frame is neither
+ 	 * addressed to us nor a multicast frame.
+ 	 */
+-	if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+-		return TXRX_CONTINUE;
++	if (!(rx->flags & IEEE80211_RX_RA_MATCH))
++		return RX_CONTINUE;
+ 
+ 	if (rx->sta)
+ 		stakey = rcu_dereference(rx->sta->key);
+@@ -537,14 +561,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+ 		 * we somehow allow the driver to tell us which key
+ 		 * the hardware used if this flag is set?
+ 		 */
+-		if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+-		    (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
+-			return TXRX_CONTINUE;
++		if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
++		    (rx->status->flag & RX_FLAG_IV_STRIPPED))
++			return RX_CONTINUE;
+ 
+ 		hdrlen = ieee80211_get_hdrlen(rx->fc);
+ 
+ 		if (rx->skb->len < 8 + hdrlen)
+-			return TXRX_DROP; /* TODO: count this? */
++			return RX_DROP_UNUSABLE; /* TODO: count this? */
+ 
+ 		/*
+ 		 * no need to call ieee80211_wep_get_keyidx,
+@@ -573,14 +597,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+ 			printk(KERN_DEBUG "%s: RX protected frame,"
+ 			       " but have no key\n", rx->dev->name);
+ #endif /* CONFIG_MAC80211_DEBUG */
+-		return TXRX_DROP;
++		return RX_DROP_MONITOR;
+ 	}
+ 
+ 	/* Check for weak IVs if possible */
+ 	if (rx->sta && rx->key->conf.alg == ALG_WEP &&
+ 	    ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+-	    (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
+-	     !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) &&
++	    (!(rx->status->flag & RX_FLAG_IV_STRIPPED) ||
++	     !(rx->status->flag & RX_FLAG_DECRYPTED)) &&
+ 	    ieee80211_wep_is_weak_iv(rx->skb, rx->key))
+ 		rx->sta->wep_weak_iv_count++;
+ 
+@@ -597,7 +621,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+ 	}
+ 
+ 	/* either the frame has been decrypted or will be dropped */
+-	rx->u.rx.status->flag |= RX_FLAG_DECRYPTED;
++	rx->status->flag |= RX_FLAG_DECRYPTED;
+ 
+ 	return result;
+ }
+@@ -607,12 +631,12 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
+ 	struct ieee80211_sub_if_data *sdata;
+ 	DECLARE_MAC_BUF(mac);
+ 
+-	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++	sdata = sta->sdata;
+ 
+ 	if (sdata->bss)
+ 		atomic_inc(&sdata->bss->num_sta_ps);
+ 	sta->flags |= WLAN_STA_PS;
+-	sta->pspoll = 0;
++	sta->flags &= ~WLAN_STA_PSPOLL;
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ 	printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
+ 	       dev->name, print_mac(mac, sta->addr), sta->aid);
+@@ -628,21 +652,21 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
+ 	struct ieee80211_tx_packet_data *pkt_data;
+ 	DECLARE_MAC_BUF(mac);
+ 
+-	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++	sdata = sta->sdata;
++
+ 	if (sdata->bss)
+ 		atomic_dec(&sdata->bss->num_sta_ps);
+-	sta->flags &= ~(WLAN_STA_PS | WLAN_STA_TIM);
+-	sta->pspoll = 0;
+-	if (!skb_queue_empty(&sta->ps_tx_buf)) {
+-		if (local->ops->set_tim)
+-			local->ops->set_tim(local_to_hw(local), sta->aid, 0);
+-		if (sdata->bss)
+-			bss_tim_clear(local, sdata->bss, sta->aid);
+-	}
++
++	sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL);
++
++	if (!skb_queue_empty(&sta->ps_tx_buf))
++		sta_info_clear_tim_bit(sta);
++
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ 	printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n",
+ 	       dev->name, print_mac(mac, sta->addr), sta->aid);
+ #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
++
+ 	/* Send all buffered frames to the station */
+ 	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+ 		pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+@@ -666,15 +690,15 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
+ 	return sent;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
+ {
+ 	struct sta_info *sta = rx->sta;
+ 	struct net_device *dev = rx->dev;
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ 
+ 	if (!sta)
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+ 	/* Update last_rx only for IBSS packets which are for the current
+ 	 * BSSID to avoid keeping the current IBSS network alive in cases where
+@@ -690,24 +714,26 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
+ 		/* Update last_rx only for unicast frames in order to prevent
+ 		 * the Probe Request frames (the only broadcast frames from a
+ 		 * STA in infrastructure mode) from keeping a connection alive.
++		 * Mesh beacons will update last_rx when if they are found to
++		 * match the current local configuration when processed.
+ 		 */
+ 		sta->last_rx = jiffies;
+ 	}
+ 
+-	if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+-		return TXRX_CONTINUE;
++	if (!(rx->flags & IEEE80211_RX_RA_MATCH))
++		return RX_CONTINUE;
+ 
+ 	sta->rx_fragments++;
+ 	sta->rx_bytes += rx->skb->len;
+-	sta->last_rssi = rx->u.rx.status->ssi;
+-	sta->last_signal = rx->u.rx.status->signal;
+-	sta->last_noise = rx->u.rx.status->noise;
++	sta->last_rssi = rx->status->ssi;
++	sta->last_signal = rx->status->signal;
++	sta->last_noise = rx->status->noise;
+ 
+ 	if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
+ 		/* Change STA power saving mode only in the end of a frame
+ 		 * exchange sequence */
+ 		if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM))
+-			rx->u.rx.sent_ps_buffered += ap_sta_ps_end(dev, sta);
++			rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
+ 		else if (!(sta->flags & WLAN_STA_PS) &&
+ 			 (rx->fc & IEEE80211_FCTL_PM))
+ 			ap_sta_ps_start(dev, sta);
+@@ -722,10 +748,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
+ 		 * as a dropped packed. */
+ 		sta->rx_packets++;
+ 		dev_kfree_skb(rx->skb);
+-		return TXRX_QUEUED;
++		return RX_QUEUED;
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
+ } /* ieee80211_rx_h_sta_process */
+ 
+ static inline struct ieee80211_fragment_entry *
+@@ -801,7 +827,7 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
+ 		    compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0)
+ 			continue;
+ 
+-		if (entry->first_frag_time + 2 * HZ < jiffies) {
++		if (time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
+ 			__skb_queue_purge(&entry->skb_list);
+ 			continue;
+ 		}
+@@ -811,8 +837,8 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
+ 	return NULL;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
+ {
+ 	struct ieee80211_hdr *hdr;
+ 	u16 sc;
+@@ -838,27 +864,27 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ 	if (frag == 0) {
+ 		/* This is the first fragment of a new frame. */
+ 		entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
+-						 rx->u.rx.queue, &(rx->skb));
++						 rx->queue, &(rx->skb));
+ 		if (rx->key && rx->key->conf.alg == ALG_CCMP &&
+ 		    (rx->fc & IEEE80211_FCTL_PROTECTED)) {
+ 			/* Store CCMP PN so that we can verify that the next
+ 			 * fragment has a sequential PN value. */
+ 			entry->ccmp = 1;
+ 			memcpy(entry->last_pn,
+-			       rx->key->u.ccmp.rx_pn[rx->u.rx.queue],
++			       rx->key->u.ccmp.rx_pn[rx->queue],
+ 			       CCMP_PN_LEN);
+ 		}
+-		return TXRX_QUEUED;
++		return RX_QUEUED;
+ 	}
+ 
+ 	/* This is a fragment for a frame that should already be pending in
+ 	 * fragment cache. Add this fragment to the end of the pending entry.
+ 	 */
+ 	entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,
+-					  rx->u.rx.queue, hdr);
++					  rx->queue, hdr);
+ 	if (!entry) {
+ 		I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+-		return TXRX_DROP;
++		return RX_DROP_MONITOR;
+ 	}
+ 
+ 	/* Verify that MPDUs within one MSDU have sequential PN values.
+@@ -867,14 +893,14 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ 		int i;
+ 		u8 pn[CCMP_PN_LEN], *rpn;
+ 		if (!rx->key || rx->key->conf.alg != ALG_CCMP)
+-			return TXRX_DROP;
++			return RX_DROP_UNUSABLE;
+ 		memcpy(pn, entry->last_pn, CCMP_PN_LEN);
+ 		for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
+ 			pn[i]++;
+ 			if (pn[i])
+ 				break;
+ 		}
+-		rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue];
++		rpn = rx->key->u.ccmp.rx_pn[rx->queue];
+ 		if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {
+ 			if (net_ratelimit())
+ 				printk(KERN_DEBUG "%s: defrag: CCMP PN not "
+@@ -885,7 +911,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ 				       rpn[0], rpn[1], rpn[2], rpn[3], rpn[4],
+ 				       rpn[5], pn[0], pn[1], pn[2], pn[3],
+ 				       pn[4], pn[5]);
+-			return TXRX_DROP;
++			return RX_DROP_UNUSABLE;
+ 		}
+ 		memcpy(entry->last_pn, pn, CCMP_PN_LEN);
+ 	}
+@@ -896,7 +922,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ 	entry->extra_len += rx->skb->len;
+ 	if (rx->fc & IEEE80211_FCTL_MOREFRAGS) {
+ 		rx->skb = NULL;
+-		return TXRX_QUEUED;
++		return RX_QUEUED;
+ 	}
+ 
+ 	rx->skb = __skb_dequeue(&entry->skb_list);
+@@ -906,7 +932,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ 					      GFP_ATOMIC))) {
+ 			I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+ 			__skb_queue_purge(&entry->skb_list);
+-			return TXRX_DROP;
++			return RX_DROP_UNUSABLE;
+ 		}
+ 	}
+ 	while ((skb = __skb_dequeue(&entry->skb_list))) {
+@@ -915,7 +941,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ 	}
+ 
+ 	/* Complete frame has been reassembled - process it now */
+-	rx->flags |= IEEE80211_TXRXD_FRAGMENTED;
++	rx->flags |= IEEE80211_RX_FRAGMENTED;
+ 
+  out:
+ 	if (rx->sta)
+@@ -924,11 +950,11 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ 		rx->local->dot11MulticastReceivedFrameCount++;
+ 	else
+ 		ieee80211_led_rx(rx->local);
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
+ {
+ 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+ 	struct sk_buff *skb;
+@@ -938,12 +964,12 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+ 	if (likely(!rx->sta ||
+ 		   (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL ||
+ 		   (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL ||
+-		   !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)))
+-		return TXRX_CONTINUE;
++		   !(rx->flags & IEEE80211_RX_RA_MATCH)))
++		return RX_CONTINUE;
+ 
+ 	if ((sdata->vif.type != IEEE80211_IF_TYPE_AP) &&
+ 	    (sdata->vif.type != IEEE80211_IF_TYPE_VLAN))
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 
+ 	skb = skb_dequeue(&rx->sta->tx_filtered);
+ 	if (!skb) {
+@@ -958,9 +984,11 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+ 		struct ieee80211_hdr *hdr =
+ 			(struct ieee80211_hdr *) skb->data;
+ 
+-		/* tell TX path to send one frame even though the STA may
+-		 * still remain is PS mode after this frame exchange */
+-		rx->sta->pspoll = 1;
++		/*
++		 * Tell TX path to send one frame even though the STA may
++		 * still remain is PS mode after this frame exchange.
++		 */
++		rx->sta->flags |= WLAN_STA_PSPOLL;
+ 
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ 		printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n",
+@@ -970,46 +998,45 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+ 
+ 		/* Use MoreData flag to indicate whether there are more
+ 		 * buffered frames for this STA */
+-		if (no_pending_pkts) {
++		if (no_pending_pkts)
+ 			hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
+-			rx->sta->flags &= ~WLAN_STA_TIM;
+-		} else
++		else
+ 			hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ 
+ 		dev_queue_xmit(skb);
+ 
+-		if (no_pending_pkts) {
+-			if (rx->local->ops->set_tim)
+-				rx->local->ops->set_tim(local_to_hw(rx->local),
+-						       rx->sta->aid, 0);
+-			if (rx->sdata->bss)
+-				bss_tim_clear(rx->local, rx->sdata->bss, rx->sta->aid);
+-		}
++		if (no_pending_pkts)
++			sta_info_clear_tim_bit(rx->sta);
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+-	} else if (!rx->u.rx.sent_ps_buffered) {
++	} else if (!rx->sent_ps_buffered) {
++		/*
++		 * FIXME: This can be the result of a race condition between
++		 *	  us expiring a frame and the station polling for it.
++		 *	  Should we send it a null-func frame indicating we
++		 *	  have nothing buffered for it?
++		 */
+ 		printk(KERN_DEBUG "%s: STA %s sent PS Poll even "
+ 		       "though there is no buffered frames for it\n",
+ 		       rx->dev->name, print_mac(mac, rx->sta->addr));
+ #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+-
+ 	}
+ 
+-	/* Free PS Poll skb here instead of returning TXRX_DROP that would
++	/* Free PS Poll skb here instead of returning RX_DROP that would
+ 	 * count as an dropped frame. */
+ 	dev_kfree_skb(rx->skb);
+ 
+-	return TXRX_QUEUED;
++	return RX_QUEUED;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
+ {
+ 	u16 fc = rx->fc;
+ 	u8 *data = rx->skb->data;
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data;
+ 
+ 	if (!WLAN_FC_IS_QOS_DATA(fc))
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+ 	/* remove the qos control field, update frame type and meta-data */
+ 	memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2);
+@@ -1018,17 +1045,17 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
+ 	rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;
+ 	hdr->frame_control = cpu_to_le16(fc);
+ 
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
+ }
+ 
+ static int
+-ieee80211_802_1x_port_control(struct ieee80211_txrx_data *rx)
++ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
+ {
+-	if (unlikely(rx->sdata->ieee802_1x_pac &&
+-		     (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)))) {
++	if (unlikely(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED))) {
+ #ifdef CONFIG_MAC80211_DEBUG
+-		printk(KERN_DEBUG "%s: dropped frame "
+-		       "(unauthorized port)\n", rx->dev->name);
++		if (net_ratelimit())
++			printk(KERN_DEBUG "%s: dropped frame "
++			       "(unauthorized port)\n", rx->dev->name);
+ #endif /* CONFIG_MAC80211_DEBUG */
+ 		return -EACCES;
+ 	}
+@@ -1037,13 +1064,13 @@ ieee80211_802_1x_port_control(struct ieee80211_txrx_data *rx)
+ }
+ 
+ static int
+-ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx)
++ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx)
+ {
+ 	/*
+ 	 * Pass through unencrypted frames if the hardware has
+ 	 * decrypted them already.
+ 	 */
+-	if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
++	if (rx->status->flag & RX_FLAG_DECRYPTED)
+ 		return 0;
+ 
+ 	/* Drop unencrypted frames if key is set. */
+@@ -1057,7 +1084,7 @@ ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx)
+ }
+ 
+ static int
+-ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
++ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
+ {
+ 	struct net_device *dev = rx->dev;
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+@@ -1079,6 +1106,21 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
+ 
+ 	hdrlen = ieee80211_get_hdrlen(fc);
+ 
++	if (ieee80211_vif_is_mesh(&sdata->vif)) {
++		int meshhdrlen = ieee80211_get_mesh_hdrlen(
++				(struct ieee80211s_hdr *) (skb->data + hdrlen));
++		/* Copy on cb:
++		 *  - mesh header: to be used for mesh forwarding
++		 * decision. It will also be used as mesh header template at
++		 * tx.c:ieee80211_subif_start_xmit() if interface
++		 * type is mesh and skb->pkt_type == PACKET_OTHERHOST
++		 *  - ta: to be used if a RERR needs to be sent.
++		 */
++		memcpy(skb->cb, skb->data + hdrlen, meshhdrlen);
++		memcpy(MESH_PREQ(skb), hdr->addr2, ETH_ALEN);
++		hdrlen += meshhdrlen;
++	}
++
+ 	/* convert IEEE 802.11 header + possible LLC headers into Ethernet
+ 	 * header
+ 	 * IEEE 802.11 address fields:
+@@ -1112,9 +1154,10 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
+ 		memcpy(dst, hdr->addr3, ETH_ALEN);
+ 		memcpy(src, hdr->addr4, ETH_ALEN);
+ 
+-		if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS)) {
+-			if (net_ratelimit())
+-				printk(KERN_DEBUG "%s: dropped FromDS&ToDS "
++		 if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS &&
++			     sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) {
++			 if (net_ratelimit())
++				 printk(KERN_DEBUG "%s: dropped FromDS&ToDS "
+ 				       "frame (RA=%s TA=%s DA=%s SA=%s)\n",
+ 				       rx->dev->name,
+ 				       print_mac(mac, hdr->addr1),
+@@ -1189,7 +1232,7 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
+ /*
+  * requires that rx->skb is a frame with ethernet header
+  */
+-static bool ieee80211_frame_allowed(struct ieee80211_txrx_data *rx)
++static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx)
+ {
+ 	static const u8 pae_group_addr[ETH_ALEN]
+ 		= { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
+@@ -1215,7 +1258,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_txrx_data *rx)
+  * requires that rx->skb is a frame with ethernet header
+  */
+ static void
+-ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
++ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
+ {
+ 	struct net_device *dev = rx->dev;
+ 	struct ieee80211_local *local = rx->local;
+@@ -1229,7 +1272,7 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
+ 
+ 	if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP ||
+ 				      sdata->vif.type == IEEE80211_IF_TYPE_VLAN) &&
+-	    (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
++	    (rx->flags & IEEE80211_RX_RA_MATCH)) {
+ 		if (is_multicast_ether_addr(ehdr->h_dest)) {
+ 			/*
+ 			 * send multicast frames both to higher layers in
+@@ -1241,7 +1284,7 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
+ 				       "multicast frame\n", dev->name);
+ 		} else {
+ 			dsta = sta_info_get(local, skb->data);
+-			if (dsta && dsta->dev == dev) {
++			if (dsta && dsta->sdata->dev == dev) {
+ 				/*
+ 				 * The destination station is associated to
+ 				 * this AP (in this VLAN), so send the frame
+@@ -1251,8 +1294,38 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
+ 				xmit_skb = skb;
+ 				skb = NULL;
+ 			}
+-			if (dsta)
+-				sta_info_put(dsta);
++		}
++	}
++
++	/* Mesh forwarding */
++	if (ieee80211_vif_is_mesh(&sdata->vif)) {
++		u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl;
++		(*mesh_ttl)--;
++
++		if (is_multicast_ether_addr(skb->data)) {
++			if (*mesh_ttl > 0) {
++				xmit_skb = skb_copy(skb, GFP_ATOMIC);
++				if (!xmit_skb && net_ratelimit())
++					printk(KERN_DEBUG "%s: failed to clone "
++					       "multicast frame\n", dev->name);
++				else
++					xmit_skb->pkt_type = PACKET_OTHERHOST;
++			} else
++				IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
++							     dropped_frames_ttl);
++		} else if (skb->pkt_type != PACKET_OTHERHOST &&
++			compare_ether_addr(dev->dev_addr, skb->data) != 0) {
++			if (*mesh_ttl == 0) {
++				IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
++							     dropped_frames_ttl);
++				dev_kfree_skb(skb);
++				skb = NULL;
++			} else {
++				xmit_skb = skb;
++				xmit_skb->pkt_type = PACKET_OTHERHOST;
++				if (!(dev->flags & IFF_PROMISC))
++					skb  = NULL;
++			}
+ 		}
+ 	}
+ 
+@@ -1272,8 +1345,8 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
+ 	}
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
+ {
+ 	struct net_device *dev = rx->dev;
+ 	struct ieee80211_local *local = rx->local;
+@@ -1288,17 +1361,17 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ 
+ 	fc = rx->fc;
+ 	if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+ 	if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+-		return TXRX_DROP;
++		return RX_DROP_MONITOR;
+ 
+-	if (!(rx->flags & IEEE80211_TXRXD_RX_AMSDU))
+-		return TXRX_CONTINUE;
++	if (!(rx->flags & IEEE80211_RX_AMSDU))
++		return RX_CONTINUE;
+ 
+ 	err = ieee80211_data_to_8023(rx);
+ 	if (unlikely(err))
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 
+ 	skb->dev = dev;
+ 
+@@ -1308,7 +1381,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ 	/* skip the wrapping header */
+ 	eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
+ 	if (!eth)
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 
+ 	while (skb != frame) {
+ 		u8 padding;
+@@ -1323,7 +1396,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ 		/* the last MSDU has no padding */
+ 		if (subframe_len > remaining) {
+ 			printk(KERN_DEBUG "%s: wrong buffer size", dev->name);
+-			return TXRX_DROP;
++			return RX_DROP_UNUSABLE;
+ 		}
+ 
+ 		skb_pull(skb, sizeof(struct ethhdr));
+@@ -1335,7 +1408,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ 					      subframe_len);
+ 
+ 			if (frame == NULL)
+-				return TXRX_DROP;
++				return RX_DROP_UNUSABLE;
+ 
+ 			skb_reserve(frame, local->hw.extra_tx_headroom +
+ 				    sizeof(struct ethhdr));
+@@ -1348,7 +1421,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ 				printk(KERN_DEBUG "%s: wrong buffer size ",
+ 				       dev->name);
+ 				dev_kfree_skb(frame);
+-				return TXRX_DROP;
++				return RX_DROP_UNUSABLE;
+ 			}
+ 		}
+ 
+@@ -1378,7 +1451,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ 
+ 		if (!ieee80211_frame_allowed(rx)) {
+ 			if (skb == frame) /* last frame */
+-				return TXRX_DROP;
++				return RX_DROP_UNUSABLE;
+ 			dev_kfree_skb(frame);
+ 			continue;
+ 		}
+@@ -1386,11 +1459,11 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ 		ieee80211_deliver_skb(rx);
+ 	}
+ 
+-	return TXRX_QUEUED;
++	return RX_QUEUED;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
+ {
+ 	struct net_device *dev = rx->dev;
+ 	u16 fc;
+@@ -1398,17 +1471,17 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+ 
+ 	fc = rx->fc;
+ 	if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+ 	if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+-		return TXRX_DROP;
++		return RX_DROP_MONITOR;
+ 
+ 	err = ieee80211_data_to_8023(rx);
+ 	if (unlikely(err))
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 
+ 	if (!ieee80211_frame_allowed(rx))
+-		return TXRX_DROP;
++		return RX_DROP_MONITOR;
+ 
+ 	rx->skb->dev = dev;
+ 
+@@ -1417,11 +1490,11 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+ 
+ 	ieee80211_deliver_skb(rx);
+ 
+-	return TXRX_QUEUED;
++	return RX_QUEUED;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
+ {
+ 	struct ieee80211_local *local = rx->local;
+ 	struct ieee80211_hw *hw = &local->hw;
+@@ -1432,15 +1505,16 @@ ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
+ 	u16 tid;
+ 
+ 	if (likely((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL))
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+ 	if ((rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ) {
+ 		if (!rx->sta)
+-			return TXRX_CONTINUE;
++			return RX_CONTINUE;
+ 		tid = le16_to_cpu(bar->control) >> 12;
+-		tid_agg_rx = &(rx->sta->ampdu_mlme.tid_rx[tid]);
+-		if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
+-			return TXRX_CONTINUE;
++		if (rx->sta->ampdu_mlme.tid_state_rx[tid]
++					!= HT_AGG_STATE_OPERATIONAL)
++			return RX_CONTINUE;
++		tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
+ 
+ 		start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
+ 
+@@ -1457,77 +1531,35 @@ ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
+ 		ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL,
+ 						 start_seq_num, 1);
+ 		rcu_read_unlock();
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
+ {
+ 	struct ieee80211_sub_if_data *sdata;
+ 
+-	if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+-		return TXRX_DROP;
++	if (!(rx->flags & IEEE80211_RX_RA_MATCH))
++		return RX_DROP_MONITOR;
+ 
+ 	sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+ 	if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+-	     sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
++	     sdata->vif.type == IEEE80211_IF_TYPE_IBSS ||
++	     sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) &&
+ 	    !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
+-		ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
++		ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->status);
+ 	else
+-		return TXRX_DROP;
++		return RX_DROP_MONITOR;
+ 
+-	return TXRX_QUEUED;
+-}
+-
+-static inline ieee80211_txrx_result __ieee80211_invoke_rx_handlers(
+-				struct ieee80211_local *local,
+-				ieee80211_rx_handler *handlers,
+-				struct ieee80211_txrx_data *rx,
+-				struct sta_info *sta)
+-{
+-	ieee80211_rx_handler *handler;
+-	ieee80211_txrx_result res = TXRX_DROP;
+-
+-	for (handler = handlers; *handler != NULL; handler++) {
+-		res = (*handler)(rx);
+-
+-		switch (res) {
+-		case TXRX_CONTINUE:
+-			continue;
+-		case TXRX_DROP:
+-			I802_DEBUG_INC(local->rx_handlers_drop);
+-			if (sta)
+-				sta->rx_dropped++;
+-			break;
+-		case TXRX_QUEUED:
+-			I802_DEBUG_INC(local->rx_handlers_queued);
+-			break;
+-		}
+-		break;
+-	}
+-
+-	if (res == TXRX_DROP)
+-		dev_kfree_skb(rx->skb);
+-	return res;
+-}
+-
+-static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local,
+-						ieee80211_rx_handler *handlers,
+-						struct ieee80211_txrx_data *rx,
+-						struct sta_info *sta)
+-{
+-	if (__ieee80211_invoke_rx_handlers(local, handlers, rx, sta) ==
+-	    TXRX_CONTINUE)
+-		dev_kfree_skb(rx->skb);
++	return RX_QUEUED;
+ }
+ 
+ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
+ 					    struct ieee80211_hdr *hdr,
+-					    struct sta_info *sta,
+-					    struct ieee80211_txrx_data *rx)
++					    struct ieee80211_rx_data *rx)
+ {
+ 	int keyidx, hdrlen;
+ 	DECLARE_MAC_BUF(mac);
+@@ -1545,7 +1577,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
+ 		       dev->name, print_mac(mac, hdr->addr2),
+ 		       print_mac(mac2, hdr->addr1), keyidx);
+ 
+-	if (!sta) {
++	if (!rx->sta) {
+ 		/*
+ 		 * Some hardware seem to generate incorrect Michael MIC
+ 		 * reports; ignore them to avoid triggering countermeasures.
+@@ -1597,7 +1629,89 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
+ 	rx->skb = NULL;
+ }
+ 
+-ieee80211_rx_handler ieee80211_rx_handlers[] =
++/* TODO: use IEEE80211_RX_FRAGMENTED */
++static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx)
++{
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_local *local = rx->local;
++	struct ieee80211_rtap_hdr {
++		struct ieee80211_radiotap_header hdr;
++		u8 flags;
++		u8 rate;
++		__le16 chan_freq;
++		__le16 chan_flags;
++	} __attribute__ ((packed)) *rthdr;
++	struct sk_buff *skb = rx->skb, *skb2;
++	struct net_device *prev_dev = NULL;
++	struct ieee80211_rx_status *status = rx->status;
++
++	if (rx->flags & IEEE80211_RX_CMNTR_REPORTED)
++		goto out_free_skb;
++
++	if (skb_headroom(skb) < sizeof(*rthdr) &&
++	    pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
++		goto out_free_skb;
++
++	rthdr = (void *)skb_push(skb, sizeof(*rthdr));
++	memset(rthdr, 0, sizeof(*rthdr));
++	rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
++	rthdr->hdr.it_present =
++		cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
++			    (1 << IEEE80211_RADIOTAP_RATE) |
++			    (1 << IEEE80211_RADIOTAP_CHANNEL));
++
++	rthdr->rate = rx->rate->bitrate / 5;
++	rthdr->chan_freq = cpu_to_le16(status->freq);
++
++	if (status->band == IEEE80211_BAND_5GHZ)
++		rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_OFDM |
++						IEEE80211_CHAN_5GHZ);
++	else
++		rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_DYN |
++						IEEE80211_CHAN_2GHZ);
++
++	skb_set_mac_header(skb, 0);
++	skb->ip_summed = CHECKSUM_UNNECESSARY;
++	skb->pkt_type = PACKET_OTHERHOST;
++	skb->protocol = htons(ETH_P_802_2);
++
++	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++		if (!netif_running(sdata->dev))
++			continue;
++
++		if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR ||
++		    !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
++			continue;
++
++		if (prev_dev) {
++			skb2 = skb_clone(skb, GFP_ATOMIC);
++			if (skb2) {
++				skb2->dev = prev_dev;
++				netif_rx(skb2);
++			}
++		}
++
++		prev_dev = sdata->dev;
++		sdata->dev->stats.rx_packets++;
++		sdata->dev->stats.rx_bytes += skb->len;
++	}
++
++	if (prev_dev) {
++		skb->dev = prev_dev;
++		netif_rx(skb);
++		skb = NULL;
++	} else
++		goto out_free_skb;
++
++	rx->flags |= IEEE80211_RX_CMNTR_REPORTED;
++	return;
++
++ out_free_skb:
++	dev_kfree_skb(skb);
++}
++
++typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_rx_data *);
++static ieee80211_rx_handler ieee80211_rx_handlers[] =
+ {
+ 	ieee80211_rx_h_if_stats,
+ 	ieee80211_rx_h_passive_scan,
+@@ -1619,10 +1733,51 @@ ieee80211_rx_handler ieee80211_rx_handlers[] =
+ 	NULL
+ };
+ 
++static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
++					 struct ieee80211_rx_data *rx,
++					 struct sk_buff *skb)
++{
++	ieee80211_rx_handler *handler;
++	ieee80211_rx_result res = RX_DROP_MONITOR;
++
++	rx->skb = skb;
++	rx->sdata = sdata;
++	rx->dev = sdata->dev;
++
++	for (handler = ieee80211_rx_handlers; *handler != NULL; handler++) {
++		res = (*handler)(rx);
++
++		switch (res) {
++		case RX_CONTINUE:
++			continue;
++		case RX_DROP_UNUSABLE:
++		case RX_DROP_MONITOR:
++			I802_DEBUG_INC(sdata->local->rx_handlers_drop);
++			if (rx->sta)
++				rx->sta->rx_dropped++;
++			break;
++		case RX_QUEUED:
++			I802_DEBUG_INC(sdata->local->rx_handlers_queued);
++			break;
++		}
++		break;
++	}
++
++	switch (res) {
++	case RX_CONTINUE:
++	case RX_DROP_MONITOR:
++		ieee80211_rx_cooked_monitor(rx);
++		break;
++	case RX_DROP_UNUSABLE:
++		dev_kfree_skb(rx->skb);
++		break;
++	}
++}
++
+ /* main receive path */
+ 
+ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+-				u8 *bssid, struct ieee80211_txrx_data *rx,
++				u8 *bssid, struct ieee80211_rx_data *rx,
+ 				struct ieee80211_hdr *hdr)
+ {
+ 	int multicast = is_multicast_ether_addr(hdr->addr1);
+@@ -1632,34 +1787,47 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+ 		if (!bssid)
+ 			return 0;
+ 		if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
+-			if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
++			if (!(rx->flags & IEEE80211_RX_IN_SCAN))
+ 				return 0;
+-			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ 		} else if (!multicast &&
+ 			   compare_ether_addr(sdata->dev->dev_addr,
+ 					      hdr->addr1) != 0) {
+ 			if (!(sdata->dev->flags & IFF_PROMISC))
+ 				return 0;
+-			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ 		}
+ 		break;
+ 	case IEEE80211_IF_TYPE_IBSS:
+ 		if (!bssid)
+ 			return 0;
+-		if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
+-			if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
++		if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
++		    (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
++			return 1;
++		else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
++			if (!(rx->flags & IEEE80211_RX_IN_SCAN))
+ 				return 0;
+-			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ 		} else if (!multicast &&
+ 			   compare_ether_addr(sdata->dev->dev_addr,
+ 					      hdr->addr1) != 0) {
+ 			if (!(sdata->dev->flags & IFF_PROMISC))
+ 				return 0;
+-			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ 		} else if (!rx->sta)
+ 			rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb,
+ 							 bssid, hdr->addr2);
+ 		break;
++	case IEEE80211_IF_TYPE_MESH_POINT:
++		if (!multicast &&
++		    compare_ether_addr(sdata->dev->dev_addr,
++				       hdr->addr1) != 0) {
++			if (!(sdata->dev->flags & IFF_PROMISC))
++				return 0;
++
++			rx->flags &= ~IEEE80211_RX_RA_MATCH;
++		}
++		break;
+ 	case IEEE80211_IF_TYPE_VLAN:
+ 	case IEEE80211_IF_TYPE_AP:
+ 		if (!bssid) {
+@@ -1668,12 +1836,12 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+ 				return 0;
+ 		} else if (!ieee80211_bssid_match(bssid,
+ 					sdata->dev->dev_addr)) {
+-			if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
++			if (!(rx->flags & IEEE80211_RX_IN_SCAN))
+ 				return 0;
+-			rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++			rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ 		}
+ 		if (sdata->dev == sdata->local->mdev &&
+-		    !(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
++		    !(rx->flags & IEEE80211_RX_IN_SCAN))
+ 			/* do not receive anything via
+ 			 * master device when not scanning */
+ 			return 0;
+@@ -1704,13 +1872,13 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+ 					 struct sk_buff *skb,
+ 					 struct ieee80211_rx_status *status,
+-					 u32 load)
++					 u32 load,
++					 struct ieee80211_rate *rate)
+ {
+ 	struct ieee80211_local *local = hw_to_local(hw);
+ 	struct ieee80211_sub_if_data *sdata;
+-	struct sta_info *sta;
+ 	struct ieee80211_hdr *hdr;
+-	struct ieee80211_txrx_data rx;
++	struct ieee80211_rx_data rx;
+ 	u16 type;
+ 	int prepares;
+ 	struct ieee80211_sub_if_data *prev = NULL;
+@@ -1722,42 +1890,33 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+ 	rx.skb = skb;
+ 	rx.local = local;
+ 
+-	rx.u.rx.status = status;
+-	rx.u.rx.load = load;
++	rx.status = status;
++	rx.load = load;
++	rx.rate = rate;
+ 	rx.fc = le16_to_cpu(hdr->frame_control);
+ 	type = rx.fc & IEEE80211_FCTL_FTYPE;
+ 
+ 	if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT)
+ 		local->dot11ReceivedFragmentCount++;
+ 
+-	sta = rx.sta = sta_info_get(local, hdr->addr2);
+-	if (sta) {
+-		rx.dev = rx.sta->dev;
+-		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
++	rx.sta = sta_info_get(local, hdr->addr2);
++	if (rx.sta) {
++		rx.sdata = rx.sta->sdata;
++		rx.dev = rx.sta->sdata->dev;
+ 	}
+ 
+ 	if ((status->flag & RX_FLAG_MMIC_ERROR)) {
+-		ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx);
+-		goto end;
++		ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx);
++		return;
+ 	}
+ 
+ 	if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
+-		rx.flags |= IEEE80211_TXRXD_RXIN_SCAN;
++		rx.flags |= IEEE80211_RX_IN_SCAN;
+ 
+-	if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,
+-					   sta) != TXRX_CONTINUE)
+-		goto end;
+-	skb = rx.skb;
++	ieee80211_parse_qos(&rx);
++	ieee80211_verify_ip_alignment(&rx);
+ 
+-	if (sta && !(sta->flags & (WLAN_STA_WDS | WLAN_STA_ASSOC_AP)) &&
+-	    !atomic_read(&local->iff_promiscs) &&
+-	    !is_multicast_ether_addr(hdr->addr1)) {
+-		rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
+-		ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
+-					     rx.sta);
+-		sta_info_put(sta);
+-		return;
+-	}
++	skb = rx.skb;
+ 
+ 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ 		if (!netif_running(sdata->dev))
+@@ -1767,10 +1926,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+ 			continue;
+ 
+ 		bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
+-		rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
++		rx.flags |= IEEE80211_RX_RA_MATCH;
+ 		prepares = prepare_for_handlers(sdata, bssid, &rx, hdr);
+-		/* prepare_for_handlers can change sta */
+-		sta = rx.sta;
+ 
+ 		if (!prepares)
+ 			continue;
+@@ -1801,26 +1958,14 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+ 			continue;
+ 		}
+ 		rx.fc = le16_to_cpu(hdr->frame_control);
+-		rx.skb = skb_new;
+-		rx.dev = prev->dev;
+-		rx.sdata = prev;
+-		ieee80211_invoke_rx_handlers(local, local->rx_handlers,
+-					     &rx, sta);
++		ieee80211_invoke_rx_handlers(prev, &rx, skb_new);
+ 		prev = sdata;
+ 	}
+ 	if (prev) {
+ 		rx.fc = le16_to_cpu(hdr->frame_control);
+-		rx.skb = skb;
+-		rx.dev = prev->dev;
+-		rx.sdata = prev;
+-		ieee80211_invoke_rx_handlers(local, local->rx_handlers,
+-					     &rx, sta);
++		ieee80211_invoke_rx_handlers(prev, &rx, skb);
+ 	} else
+ 		dev_kfree_skb(skb);
+-
+- end:
+-	if (sta)
+-		sta_info_put(sta);
+ }
+ 
+ #define SEQ_MODULO 0x1000
+@@ -1856,6 +2001,8 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+ 	u16 head_seq_num, buf_size;
+ 	int index;
+ 	u32 pkt_load;
++	struct ieee80211_supported_band *sband;
++	struct ieee80211_rate *rate;
+ 
+ 	buf_size = tid_agg_rx->buf_size;
+ 	head_seq_num = tid_agg_rx->head_seq_num;
+@@ -1886,12 +2033,14 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+ 				memcpy(&status,
+ 					tid_agg_rx->reorder_buf[index]->cb,
+ 					sizeof(status));
++				sband = local->hw.wiphy->bands[status.band];
++				rate = &sband->bitrates[status.rate_idx];
+ 				pkt_load = ieee80211_rx_load_stats(local,
+ 						tid_agg_rx->reorder_buf[index],
+-						&status);
++						&status, rate);
+ 				__ieee80211_rx_handle_packet(hw,
+ 					tid_agg_rx->reorder_buf[index],
+-					&status, pkt_load);
++					&status, pkt_load, rate);
+ 				tid_agg_rx->stored_mpdu_num--;
+ 				tid_agg_rx->reorder_buf[index] = NULL;
+ 			}
+@@ -1931,11 +2080,13 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+ 		/* release the reordered frame back to stack */
+ 		memcpy(&status, tid_agg_rx->reorder_buf[index]->cb,
+ 			sizeof(status));
++		sband = local->hw.wiphy->bands[status.band];
++		rate = &sband->bitrates[status.rate_idx];
+ 		pkt_load = ieee80211_rx_load_stats(local,
+ 					tid_agg_rx->reorder_buf[index],
+-					&status);
++					&status, rate);
+ 		__ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index],
+-						&status, pkt_load);
++					     &status, pkt_load, rate);
+ 		tid_agg_rx->stored_mpdu_num--;
+ 		tid_agg_rx->reorder_buf[index] = NULL;
+ 		tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
+@@ -1970,11 +2121,12 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
+ 
+ 	qc = skb->data + ieee80211_get_hdrlen(fc) - QOS_CONTROL_LEN;
+ 	tid = qc[0] & QOS_CONTROL_TID_MASK;
+-	tid_agg_rx = &(sta->ampdu_mlme.tid_rx[tid]);
+ 
+-	if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
++	if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
+ 		goto end_reorder;
+ 
++	tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
++
+ 	/* null data frames are excluded */
+ 	if (unlikely(fc & IEEE80211_STYPE_NULLFUNC))
+ 		goto end_reorder;
+@@ -1991,7 +2143,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
+ 	/* if this mpdu is fragmented - terminate rx aggregation session */
+ 	sc = le16_to_cpu(hdr->seq_ctrl);
+ 	if (sc & IEEE80211_SCTL_FRAG) {
+-		ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr,
++		ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
+ 			tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
+ 		ret = 1;
+ 		goto end_reorder;
+@@ -2001,9 +2153,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
+ 	mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
+ 	ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb,
+ 						mpdu_seq_num, 0);
+-end_reorder:
+-	if (sta)
+-		sta_info_put(sta);
++ end_reorder:
+ 	return ret;
+ }
+ 
+@@ -2016,6 +2166,25 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ {
+ 	struct ieee80211_local *local = hw_to_local(hw);
+ 	u32 pkt_load;
++	struct ieee80211_rate *rate = NULL;
++	struct ieee80211_supported_band *sband;
++
++	if (status->band < 0 ||
++	    status->band >= IEEE80211_NUM_BANDS) {
++		WARN_ON(1);
++		return;
++	}
++
++	sband = local->hw.wiphy->bands[status->band];
++
++	if (!sband ||
++	    status->rate_idx < 0 ||
++	    status->rate_idx >= sband->n_bitrates) {
++		WARN_ON(1);
++		return;
++	}
++
++	rate = &sband->bitrates[status->rate_idx];
+ 
+ 	/*
+ 	 * key references and virtual interfaces are protected using RCU
+@@ -2030,17 +2199,17 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ 	 * if it was previously present.
+ 	 * Also, frames with less than 16 bytes are dropped.
+ 	 */
+-	skb = ieee80211_rx_monitor(local, skb, status);
++	skb = ieee80211_rx_monitor(local, skb, status, rate);
+ 	if (!skb) {
+ 		rcu_read_unlock();
+ 		return;
+ 	}
+ 
+-	pkt_load = ieee80211_rx_load_stats(local, skb, status);
++	pkt_load = ieee80211_rx_load_stats(local, skb, status, rate);
+ 	local->channel_use_raw += pkt_load;
+ 
+ 	if (!ieee80211_rx_reorder_ampdu(local, skb))
+-		__ieee80211_rx_handle_packet(hw, skb, status, pkt_load);
++		__ieee80211_rx_handle_packet(hw, skb, status, pkt_load, rate);
+ 
+ 	rcu_read_unlock();
+ }
+diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
+index 1f74bd2..7d4fe4a 100644
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -15,21 +15,57 @@
+ #include <linux/skbuff.h>
+ #include <linux/if_arp.h>
+ #include <linux/timer.h>
++#include <linux/rtnetlink.h>
+ 
+ #include <net/mac80211.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
+ #include "sta_info.h"
+ #include "debugfs_sta.h"
++#include "mesh.h"
+ 
+-/* Caller must hold local->sta_lock */
+-static void sta_info_hash_add(struct ieee80211_local *local,
+-			      struct sta_info *sta)
+-{
+-	sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
+-	local->sta_hash[STA_HASH(sta->addr)] = sta;
+-}
+-
++/**
++ * DOC: STA information lifetime rules
++ *
++ * STA info structures (&struct sta_info) are managed in a hash table
++ * for faster lookup and a list for iteration. They are managed using
++ * RCU, i.e. access to the list and hash table is protected by RCU.
++ *
++ * Upon allocating a STA info structure with sta_info_alloc(), the caller owns
++ * that structure. It must then either destroy it using sta_info_destroy()
++ * (which is pretty useless) or insert it into the hash table using
++ * sta_info_insert() which demotes the reference from ownership to a regular
++ * RCU-protected reference; if the function is called without protection by an
++ * RCU critical section the reference is instantly invalidated. Note that the
++ * caller may not do much with the STA info before inserting it, in particular,
++ * it may not start any mesh peer link management or add encryption keys.
++ *
++ * When the insertion fails (sta_info_insert()) returns non-zero), the
++ * structure will have been freed by sta_info_insert()!
++ *
++ * Because there are debugfs entries for each station, and adding those
++ * must be able to sleep, it is also possible to "pin" a station entry,
++ * that means it can be removed from the hash table but not be freed.
++ * See the comment in __sta_info_unlink() for more information, this is
++ * an internal capability only.
++ *
++ * In order to remove a STA info structure, the caller needs to first
++ * unlink it (sta_info_unlink()) from the list and hash tables and
++ * then destroy it; sta_info_destroy() will wait for an RCU grace period
++ * to elapse before actually freeing it. Due to the pinning and the
++ * possibility of multiple callers trying to remove the same STA info at
++ * the same time, sta_info_unlink() can clear the STA info pointer it is
++ * passed to indicate that the STA info is owned by somebody else now.
++ *
++ * If sta_info_unlink() did not clear the pointer then the caller owns
++ * the STA info structure now and is responsible of destroying it with
++ * a call to sta_info_destroy().
++ *
++ * In all other cases, there is no concept of ownership on a STA entry,
++ * each structure is owned by the global hash table/list until it is
++ * removed. All users of the structure need to be RCU protected so that
++ * the structure won't be freed before they are done using it.
++ */
+ 
+ /* Caller must hold local->sta_lock */
+ static int sta_info_hash_del(struct ieee80211_local *local,
+@@ -41,237 +77,439 @@ static int sta_info_hash_del(struct ieee80211_local *local,
+ 	if (!s)
+ 		return -ENOENT;
+ 	if (s == sta) {
+-		local->sta_hash[STA_HASH(sta->addr)] = s->hnext;
++		rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)],
++				   s->hnext);
+ 		return 0;
+ 	}
+ 
+ 	while (s->hnext && s->hnext != sta)
+ 		s = s->hnext;
+ 	if (s->hnext) {
+-		s->hnext = sta->hnext;
++		rcu_assign_pointer(s->hnext, sta->hnext);
+ 		return 0;
+ 	}
+ 
+ 	return -ENOENT;
+ }
+ 
+-struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
++/* protected by RCU */
++static struct sta_info *__sta_info_find(struct ieee80211_local *local,
++					u8 *addr)
+ {
+ 	struct sta_info *sta;
+ 
+-	read_lock_bh(&local->sta_lock);
+-	sta = local->sta_hash[STA_HASH(addr)];
++	sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
+ 	while (sta) {
+-		if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
+-			__sta_info_get(sta);
++		if (compare_ether_addr(sta->addr, addr) == 0)
+ 			break;
+-		}
+-		sta = sta->hnext;
++		sta = rcu_dereference(sta->hnext);
+ 	}
+-	read_unlock_bh(&local->sta_lock);
+-
+ 	return sta;
+ }
++
++struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
++{
++	return __sta_info_find(local, addr);
++}
+ EXPORT_SYMBOL(sta_info_get);
+ 
+-int sta_info_min_txrate_get(struct ieee80211_local *local)
++struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
++				     struct net_device *dev)
+ {
+ 	struct sta_info *sta;
+-	struct ieee80211_hw_mode *mode;
+-	int min_txrate = 9999999;
+-	int i;
+-
+-	read_lock_bh(&local->sta_lock);
+-	mode = local->oper_hw_mode;
+-	for (i = 0; i < STA_HASH_SIZE; i++) {
+-		sta = local->sta_hash[i];
+-		while (sta) {
+-			if (sta->txrate < min_txrate)
+-				min_txrate = sta->txrate;
+-			sta = sta->hnext;
++	int i = 0;
++
++	list_for_each_entry_rcu(sta, &local->sta_list, list) {
++		if (dev && dev != sta->sdata->dev)
++			continue;
++		if (i < idx) {
++			++i;
++			continue;
+ 		}
++		return sta;
+ 	}
+-	read_unlock_bh(&local->sta_lock);
+-	if (min_txrate == 9999999)
+-		min_txrate = 0;
+ 
+-	return mode->rates[min_txrate].rate;
++	return NULL;
+ }
+ 
++/**
++ * __sta_info_free - internal STA free helper
++ *
++ * @sta: STA info to free
++ *
++ * This function must undo everything done by sta_info_alloc()
++ * that may happen before sta_info_insert().
++ */
++static void __sta_info_free(struct ieee80211_local *local,
++			    struct sta_info *sta)
++{
++	DECLARE_MAC_BUF(mbuf);
++
++	rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
++	rate_control_put(sta->rate_ctrl);
++
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++	printk(KERN_DEBUG "%s: Destroyed STA %s\n",
++	       wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
++#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ 
+-static void sta_info_release(struct kref *kref)
++	kfree(sta);
++}
++
++void sta_info_destroy(struct sta_info *sta)
+ {
+-	struct sta_info *sta = container_of(kref, struct sta_info, kref);
+-	struct ieee80211_local *local = sta->local;
++	struct ieee80211_local *local;
+ 	struct sk_buff *skb;
+ 	int i;
+ 
+-	/* free sta structure; it has already been removed from
+-	 * hash table etc. external structures. Make sure that all
+-	 * buffered frames are release (one might have been added
+-	 * after sta_info_free() was called). */
++	might_sleep();
++
++	if (!sta)
++		return;
++
++	local = sta->local;
++
++	rate_control_remove_sta_debugfs(sta);
++	ieee80211_sta_debugfs_remove(sta);
++
++#ifdef CONFIG_MAC80211_MESH
++	if (ieee80211_vif_is_mesh(&sta->sdata->vif))
++		mesh_plink_deactivate(sta);
++#endif
++
++	/*
++	 * We have only unlinked the key, and actually destroying it
++	 * may mean it is removed from hardware which requires that
++	 * the key->sta pointer is still valid, so flush the key todo
++	 * list here.
++	 *
++	 * ieee80211_key_todo() will synchronize_rcu() so after this
++	 * nothing can reference this sta struct any more.
++	 */
++	ieee80211_key_todo();
++
++#ifdef CONFIG_MAC80211_MESH
++	if (ieee80211_vif_is_mesh(&sta->sdata->vif))
++		del_timer_sync(&sta->plink_timer);
++#endif
++
+ 	while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+ 		local->total_ps_buffered--;
+ 		dev_kfree_skb_any(skb);
+ 	}
+-	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
++
++	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL)
+ 		dev_kfree_skb_any(skb);
++
++	for (i = 0; i <  STA_TID_NUM; i++) {
++		spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
++		if (sta->ampdu_mlme.tid_rx[i])
++		  del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer);
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
++		spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++		if (sta->ampdu_mlme.tid_tx[i])
++		  del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer);
++		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ 	}
+-	for (i = 0; i <  STA_TID_NUM; i++)
+-		del_timer_sync(&sta->ampdu_mlme.tid_rx[i].session_timer);
+-	rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
+-	rate_control_put(sta->rate_ctrl);
+-	kfree(sta);
++
++	__sta_info_free(local, sta);
+ }
+ 
+ 
+-void sta_info_put(struct sta_info *sta)
++/* Caller must hold local->sta_lock */
++static void sta_info_hash_add(struct ieee80211_local *local,
++			      struct sta_info *sta)
+ {
+-	kref_put(&sta->kref, sta_info_release);
++	sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
++	rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta);
+ }
+-EXPORT_SYMBOL(sta_info_put);
+ 
+-
+-struct sta_info * sta_info_add(struct ieee80211_local *local,
+-			       struct net_device *dev, u8 *addr, gfp_t gfp)
++struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
++				u8 *addr, gfp_t gfp)
+ {
++	struct ieee80211_local *local = sdata->local;
+ 	struct sta_info *sta;
+ 	int i;
+-	DECLARE_MAC_BUF(mac);
++	DECLARE_MAC_BUF(mbuf);
+ 
+ 	sta = kzalloc(sizeof(*sta), gfp);
+ 	if (!sta)
+ 		return NULL;
+ 
+-	kref_init(&sta->kref);
++	memcpy(sta->addr, addr, ETH_ALEN);
++	sta->local = local;
++	sta->sdata = sdata;
+ 
+ 	sta->rate_ctrl = rate_control_get(local->rate_ctrl);
+-	sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, gfp);
++	sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
++						     gfp);
+ 	if (!sta->rate_ctrl_priv) {
+ 		rate_control_put(sta->rate_ctrl);
+ 		kfree(sta);
+ 		return NULL;
+ 	}
+ 
+-	memcpy(sta->addr, addr, ETH_ALEN);
+-	sta->local = local;
+-	sta->dev = dev;
+ 	spin_lock_init(&sta->ampdu_mlme.ampdu_rx);
++	spin_lock_init(&sta->ampdu_mlme.ampdu_tx);
+ 	for (i = 0; i < STA_TID_NUM; i++) {
+ 		/* timer_to_tid must be initialized with identity mapping to
+ 		 * enable session_timer's data differentiation. refer to
+ 		 * sta_rx_agg_session_timer_expired for useage */
+ 		sta->timer_to_tid[i] = i;
+-		/* rx timers */
+-		sta->ampdu_mlme.tid_rx[i].session_timer.function =
+-			sta_rx_agg_session_timer_expired;
+-		sta->ampdu_mlme.tid_rx[i].session_timer.data =
+-			(unsigned long)&sta->timer_to_tid[i];
+-		init_timer(&sta->ampdu_mlme.tid_rx[i].session_timer);
++		/* tid to tx queue: initialize according to HW (0 is valid) */
++		sta->tid_to_tx_q[i] = local->hw.queues;
++		/* rx */
++		sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE;
++		sta->ampdu_mlme.tid_rx[i] = NULL;
++		/* tx */
++		sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE;
++		sta->ampdu_mlme.tid_tx[i] = NULL;
++		sta->ampdu_mlme.addba_req_num[i] = 0;
+ 	}
+ 	skb_queue_head_init(&sta->ps_tx_buf);
+ 	skb_queue_head_init(&sta->tx_filtered);
+-	__sta_info_get(sta);	/* sta used by caller, decremented by
+-				 * sta_info_put() */
+-	write_lock_bh(&local->sta_lock);
++
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++	printk(KERN_DEBUG "%s: Allocated STA %s\n",
++	       wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
++#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
++
++#ifdef CONFIG_MAC80211_MESH
++	sta->plink_state = PLINK_LISTEN;
++	spin_lock_init(&sta->plink_lock);
++	init_timer(&sta->plink_timer);
++#endif
++
++	return sta;
++}
++
++int sta_info_insert(struct sta_info *sta)
++{
++	struct ieee80211_local *local = sta->local;
++	struct ieee80211_sub_if_data *sdata = sta->sdata;
++	unsigned long flags;
++	int err = 0;
++	DECLARE_MAC_BUF(mac);
++
++	/*
++	 * Can't be a WARN_ON because it can be triggered through a race:
++	 * something inserts a STA (on one CPU) without holding the RTNL
++	 * and another CPU turns off the net device.
++	 */
++	if (unlikely(!netif_running(sdata->dev))) {
++		err = -ENETDOWN;
++		goto out_free;
++	}
++
++	if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 ||
++	            is_multicast_ether_addr(sta->addr))) {
++		err = -EINVAL;
++		goto out_free;
++	}
++
++	spin_lock_irqsave(&local->sta_lock, flags);
++	/* check if STA exists already */
++	if (__sta_info_find(local, sta->addr)) {
++		spin_unlock_irqrestore(&local->sta_lock, flags);
++		err = -EEXIST;
++		goto out_free;
++	}
+ 	list_add(&sta->list, &local->sta_list);
+ 	local->num_sta++;
+ 	sta_info_hash_add(local, sta);
+-	if (local->ops->sta_notify) {
+-		struct ieee80211_sub_if_data *sdata;
+ 
+-		sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	/* notify driver */
++	if (local->ops->sta_notify) {
+ 		if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
+ 			sdata = sdata->u.vlan.ap;
+ 
+ 		local->ops->sta_notify(local_to_hw(local), &sdata->vif,
+-				       STA_NOTIFY_ADD, addr);
++				       STA_NOTIFY_ADD, sta->addr);
+ 	}
+-	write_unlock_bh(&local->sta_lock);
+ 
+ #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+-	printk(KERN_DEBUG "%s: Added STA %s\n",
+-	       wiphy_name(local->hw.wiphy), print_mac(mac, addr));
++	printk(KERN_DEBUG "%s: Inserted STA %s\n",
++	       wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr));
+ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ 
++	spin_unlock_irqrestore(&local->sta_lock, flags);
++
+ #ifdef CONFIG_MAC80211_DEBUGFS
+-	/* debugfs entry adding might sleep, so schedule process
++	/*
++	 * Debugfs entry adding might sleep, so schedule process
+ 	 * context task for adding entry for STAs that do not yet
+-	 * have one. */
+-	queue_work(local->hw.workqueue, &local->sta_debugfs_add);
++	 * have one.
++	 * NOTE: due to auto-freeing semantics this may only be done
++	 *       if the insertion is successful!
++	 */
++	schedule_work(&local->sta_debugfs_add);
+ #endif
+ 
+-	return sta;
++	if (ieee80211_vif_is_mesh(&sdata->vif))
++		mesh_accept_plinks_update(sdata);
++
++	return 0;
++ out_free:
++	BUG_ON(!err);
++	__sta_info_free(local, sta);
++	return err;
+ }
+ 
+-/* Caller must hold local->sta_lock */
+-void sta_info_remove(struct sta_info *sta)
++static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
+ {
+-	struct ieee80211_local *local = sta->local;
+-	struct ieee80211_sub_if_data *sdata;
++	/*
++	 * This format has been mandated by the IEEE specifications,
++	 * so this line may not be changed to use the __set_bit() format.
++	 */
++	bss->tim[aid / 8] |= (1 << (aid % 8));
++}
+ 
+-	/* don't do anything if we've been removed already */
+-	if (sta_info_hash_del(local, sta))
+-		return;
++static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
++{
++	/*
++	 * This format has been mandated by the IEEE specifications,
++	 * so this line may not be changed to use the __clear_bit() format.
++	 */
++	bss->tim[aid / 8] &= ~(1 << (aid % 8));
++}
+ 
+-	list_del(&sta->list);
+-	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+-	if (sta->flags & WLAN_STA_PS) {
+-		sta->flags &= ~WLAN_STA_PS;
+-		if (sdata->bss)
+-			atomic_dec(&sdata->bss->num_sta_ps);
++static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss,
++				   struct sta_info *sta)
++{
++	if (bss)
++		__bss_tim_set(bss, sta->aid);
++	if (sta->local->ops->set_tim) {
++		sta->local->tim_in_locked_section = true;
++		sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1);
++		sta->local->tim_in_locked_section = false;
+ 	}
+-	local->num_sta--;
+-	sta_info_remove_aid_ptr(sta);
++}
++
++void sta_info_set_tim_bit(struct sta_info *sta)
++{
++	unsigned long flags;
+ 
++	spin_lock_irqsave(&sta->local->sta_lock, flags);
++	__sta_info_set_tim_bit(sta->sdata->bss, sta);
++	spin_unlock_irqrestore(&sta->local->sta_lock, flags);
+ }
+ 
+-void sta_info_free(struct sta_info *sta)
++static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss,
++				     struct sta_info *sta)
+ {
+-	struct sk_buff *skb;
+-	struct ieee80211_local *local = sta->local;
+-	DECLARE_MAC_BUF(mac);
++	if (bss)
++		__bss_tim_clear(bss, sta->aid);
++	if (sta->local->ops->set_tim) {
++		sta->local->tim_in_locked_section = true;
++		sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0);
++		sta->local->tim_in_locked_section = false;
++	}
++}
+ 
+-	might_sleep();
++void sta_info_clear_tim_bit(struct sta_info *sta)
++{
++	unsigned long flags;
+ 
+-	write_lock_bh(&local->sta_lock);
+-	sta_info_remove(sta);
+-	write_unlock_bh(&local->sta_lock);
++	spin_lock_irqsave(&sta->local->sta_lock, flags);
++	__sta_info_clear_tim_bit(sta->sdata->bss, sta);
++	spin_unlock_irqrestore(&sta->local->sta_lock, flags);
++}
+ 
+-	while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+-		local->total_ps_buffered--;
+-		dev_kfree_skb(skb);
+-	}
+-	while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+-		dev_kfree_skb(skb);
++void __sta_info_unlink(struct sta_info **sta)
++{
++	struct ieee80211_local *local = (*sta)->local;
++	struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++	DECLARE_MAC_BUF(mbuf);
++#endif
++	/*
++	 * pull caller's reference if we're already gone.
++	 */
++	if (sta_info_hash_del(local, *sta)) {
++		*sta = NULL;
++		return;
+ 	}
+ 
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+-	printk(KERN_DEBUG "%s: Removed STA %s\n",
+-	       wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr));
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
++	if ((*sta)->key) {
++		ieee80211_key_free((*sta)->key);
++		WARN_ON((*sta)->key);
++	}
+ 
+-	ieee80211_key_free(sta->key);
+-	sta->key = NULL;
++	list_del(&(*sta)->list);
+ 
+-	if (local->ops->sta_notify) {
+-		struct ieee80211_sub_if_data *sdata;
++	if ((*sta)->flags & WLAN_STA_PS) {
++		(*sta)->flags &= ~WLAN_STA_PS;
++		if (sdata->bss)
++			atomic_dec(&sdata->bss->num_sta_ps);
++		__sta_info_clear_tim_bit(sdata->bss, *sta);
++	}
+ 
+-		sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++	local->num_sta--;
+ 
++	if (local->ops->sta_notify) {
+ 		if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
+ 			sdata = sdata->u.vlan.ap;
+ 
+ 		local->ops->sta_notify(local_to_hw(local), &sdata->vif,
+-				       STA_NOTIFY_REMOVE, sta->addr);
++				       STA_NOTIFY_REMOVE, (*sta)->addr);
+ 	}
+ 
+-	rate_control_remove_sta_debugfs(sta);
+-	ieee80211_sta_debugfs_remove(sta);
++	if (ieee80211_vif_is_mesh(&sdata->vif)) {
++		mesh_accept_plinks_update(sdata);
++#ifdef CONFIG_MAC80211_MESH
++		del_timer(&(*sta)->plink_timer);
++#endif
++	}
+ 
+-	sta_info_put(sta);
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++	printk(KERN_DEBUG "%s: Removed STA %s\n",
++	       wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr));
++#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
++
++	/*
++	 * Finally, pull caller's reference if the STA is pinned by the
++	 * task that is adding the debugfs entries. In that case, we
++	 * leave the STA "to be freed".
++	 *
++	 * The rules are not trivial, but not too complex either:
++	 *  (1) pin_status is only modified under the sta_lock
++	 *  (2) STAs may only be pinned under the RTNL so that
++	 *	sta_info_flush() is guaranteed to actually destroy
++	 *	all STAs that are active for a given interface, this
++	 *	is required for correctness because otherwise we
++	 *	could notify a driver that an interface is going
++	 *	away and only after that (!) notify it about a STA
++	 *	on that interface going away.
++	 *  (3) sta_info_debugfs_add_work() will set the status
++	 *	to PINNED when it found an item that needs a new
++	 *	debugfs directory created. In that case, that item
++	 *	must not be freed although all *RCU* users are done
++	 *	with it. Hence, we tell the caller of _unlink()
++	 *	that the item is already gone (as can happen when
++	 *	two tasks try to unlink/destroy at the same time)
++	 *  (4) We set the pin_status to DESTROY here when we
++	 *	find such an item.
++	 *  (5) sta_info_debugfs_add_work() will reset the pin_status
++	 *	from PINNED to NORMAL when it is done with the item,
++	 *	but will check for DESTROY before resetting it in
++	 *	which case it will free the item.
++	 */
++	if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) {
++		(*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY;
++		*sta = NULL;
++		return;
++	}
+ }
+ 
++void sta_info_unlink(struct sta_info **sta)
++{
++	struct ieee80211_local *local = (*sta)->local;
++	unsigned long flags;
++
++	spin_lock_irqsave(&local->sta_lock, flags);
++	__sta_info_unlink(sta);
++	spin_unlock_irqrestore(&local->sta_lock, flags);
++}
+ 
+ static inline int sta_info_buffer_expired(struct ieee80211_local *local,
+ 					  struct sta_info *sta,
+@@ -299,6 +537,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
+ {
+ 	unsigned long flags;
+ 	struct sk_buff *skb;
++	struct ieee80211_sub_if_data *sdata;
+ 	DECLARE_MAC_BUF(mac);
+ 
+ 	if (skb_queue_empty(&sta->ps_tx_buf))
+@@ -307,21 +546,23 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
+ 	for (;;) {
+ 		spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
+ 		skb = skb_peek(&sta->ps_tx_buf);
+-		if (sta_info_buffer_expired(local, sta, skb)) {
++		if (sta_info_buffer_expired(local, sta, skb))
+ 			skb = __skb_dequeue(&sta->ps_tx_buf);
+-			if (skb_queue_empty(&sta->ps_tx_buf))
+-				sta->flags &= ~WLAN_STA_TIM;
+-		} else
++		else
+ 			skb = NULL;
+ 		spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags);
+ 
+-		if (skb) {
+-			local->total_ps_buffered--;
+-			printk(KERN_DEBUG "Buffered frame expired (STA "
+-			       "%s)\n", print_mac(mac, sta->addr));
+-			dev_kfree_skb(skb);
+-		} else
++		if (!skb)
+ 			break;
++
++		sdata = sta->sdata;
++		local->total_ps_buffered--;
++		printk(KERN_DEBUG "Buffered frame expired (STA "
++		       "%s)\n", print_mac(mac, sta->addr));
++		dev_kfree_skb(skb);
++
++		if (skb_queue_empty(&sta->ps_tx_buf))
++			sta_info_clear_tim_bit(sta);
+ 	}
+ }
+ 
+@@ -331,13 +572,10 @@ static void sta_info_cleanup(unsigned long data)
+ 	struct ieee80211_local *local = (struct ieee80211_local *) data;
+ 	struct sta_info *sta;
+ 
+-	read_lock_bh(&local->sta_lock);
+-	list_for_each_entry(sta, &local->sta_list, list) {
+-		__sta_info_get(sta);
++	rcu_read_lock();
++	list_for_each_entry_rcu(sta, &local->sta_list, list)
+ 		sta_info_cleanup_expire_buffered(local, sta);
+-		sta_info_put(sta);
+-	}
+-	read_unlock_bh(&local->sta_lock);
++	rcu_read_unlock();
+ 
+ 	local->sta_cleanup.expires =
+ 		round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
+@@ -345,38 +583,106 @@ static void sta_info_cleanup(unsigned long data)
+ }
+ 
+ #ifdef CONFIG_MAC80211_DEBUGFS
+-static void sta_info_debugfs_add_task(struct work_struct *work)
++/*
++ * See comment in __sta_info_unlink,
++ * caller must hold local->sta_lock.
++ */
++static void __sta_info_pin(struct sta_info *sta)
++{
++	WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL);
++	sta->pin_status = STA_INFO_PIN_STAT_PINNED;
++}
++
++/*
++ * See comment in __sta_info_unlink, returns sta if it
++ * needs to be destroyed.
++ */
++static struct sta_info *__sta_info_unpin(struct sta_info *sta)
++{
++	struct sta_info *ret = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&sta->local->sta_lock, flags);
++	WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY &&
++		sta->pin_status != STA_INFO_PIN_STAT_PINNED);
++	if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY)
++		ret = sta;
++	sta->pin_status = STA_INFO_PIN_STAT_NORMAL;
++	spin_unlock_irqrestore(&sta->local->sta_lock, flags);
++
++	return ret;
++}
++
++static void sta_info_debugfs_add_work(struct work_struct *work)
+ {
+ 	struct ieee80211_local *local =
+ 		container_of(work, struct ieee80211_local, sta_debugfs_add);
+ 	struct sta_info *sta, *tmp;
++	unsigned long flags;
+ 
++	/* We need to keep the RTNL across the whole pinned status. */
++	rtnl_lock();
+ 	while (1) {
+ 		sta = NULL;
+-		read_lock_bh(&local->sta_lock);
++
++		spin_lock_irqsave(&local->sta_lock, flags);
+ 		list_for_each_entry(tmp, &local->sta_list, list) {
+ 			if (!tmp->debugfs.dir) {
+ 				sta = tmp;
+-				__sta_info_get(sta);
++				__sta_info_pin(sta);
+ 				break;
+ 			}
+ 		}
+-		read_unlock_bh(&local->sta_lock);
++		spin_unlock_irqrestore(&local->sta_lock, flags);
+ 
+ 		if (!sta)
+ 			break;
+ 
+ 		ieee80211_sta_debugfs_add(sta);
+ 		rate_control_add_sta_debugfs(sta);
+-		sta_info_put(sta);
++
++		sta = __sta_info_unpin(sta);
++		sta_info_destroy(sta);
+ 	}
++	rtnl_unlock();
+ }
+ #endif
+ 
++static void __ieee80211_run_pending_flush(struct ieee80211_local *local)
++{
++	struct sta_info *sta;
++	unsigned long flags;
++
++	ASSERT_RTNL();
++
++	spin_lock_irqsave(&local->sta_lock, flags);
++	while (!list_empty(&local->sta_flush_list)) {
++		sta = list_first_entry(&local->sta_flush_list,
++				       struct sta_info, list);
++		list_del(&sta->list);
++		spin_unlock_irqrestore(&local->sta_lock, flags);
++		sta_info_destroy(sta);
++		spin_lock_irqsave(&local->sta_lock, flags);
++	}
++	spin_unlock_irqrestore(&local->sta_lock, flags);
++}
++
++static void ieee80211_sta_flush_work(struct work_struct *work)
++{
++	struct ieee80211_local *local =
++		container_of(work, struct ieee80211_local, sta_flush_work);
++
++	rtnl_lock();
++	__ieee80211_run_pending_flush(local);
++	rtnl_unlock();
++}
++
+ void sta_info_init(struct ieee80211_local *local)
+ {
+-	rwlock_init(&local->sta_lock);
++	spin_lock_init(&local->sta_lock);
+ 	INIT_LIST_HEAD(&local->sta_list);
++	INIT_LIST_HEAD(&local->sta_flush_list);
++	INIT_WORK(&local->sta_flush_work, ieee80211_sta_flush_work);
+ 
+ 	setup_timer(&local->sta_cleanup, sta_info_cleanup,
+ 		    (unsigned long)local);
+@@ -384,7 +690,7 @@ void sta_info_init(struct ieee80211_local *local)
+ 		round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
+ 
+ #ifdef CONFIG_MAC80211_DEBUGFS
+-	INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_task);
++	INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work);
+ #endif
+ }
+ 
+@@ -397,47 +703,89 @@ int sta_info_start(struct ieee80211_local *local)
+ void sta_info_stop(struct ieee80211_local *local)
+ {
+ 	del_timer(&local->sta_cleanup);
++	cancel_work_sync(&local->sta_flush_work);
++#ifdef CONFIG_MAC80211_DEBUGFS
++	/*
++	 * Make sure the debugfs adding work isn't pending after this
++	 * because we're about to be destroyed. It doesn't matter
++	 * whether it ran or not since we're going to flush all STAs
++	 * anyway.
++	 */
++	cancel_work_sync(&local->sta_debugfs_add);
++#endif
++
++	rtnl_lock();
+ 	sta_info_flush(local, NULL);
++	__ieee80211_run_pending_flush(local);
++	rtnl_unlock();
+ }
+ 
+-void sta_info_remove_aid_ptr(struct sta_info *sta)
++/**
++ * sta_info_flush - flush matching STA entries from the STA table
++ *
++ * Returns the number of removed STA entries.
++ *
++ * @local: local interface data
++ * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs
++ */
++int sta_info_flush(struct ieee80211_local *local,
++		    struct ieee80211_sub_if_data *sdata)
+ {
+-	struct ieee80211_sub_if_data *sdata;
++	struct sta_info *sta, *tmp;
++	LIST_HEAD(tmp_list);
++	int ret = 0;
++	unsigned long flags;
+ 
+-	if (sta->aid <= 0)
+-		return;
++	might_sleep();
++	ASSERT_RTNL();
++
++	spin_lock_irqsave(&local->sta_lock, flags);
++	list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
++		if (!sdata || sdata == sta->sdata) {
++			__sta_info_unlink(&sta);
++			if (sta) {
++				list_add_tail(&sta->list, &tmp_list);
++				ret++;
++			}
++		}
++	}
++	spin_unlock_irqrestore(&local->sta_lock, flags);
+ 
+-	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++	list_for_each_entry_safe(sta, tmp, &tmp_list, list)
++		sta_info_destroy(sta);
+ 
+-	if (sdata->local->ops->set_tim)
+-		sdata->local->ops->set_tim(local_to_hw(sdata->local),
+-					  sta->aid, 0);
+-	if (sdata->bss)
+-		__bss_tim_clear(sdata->bss, sta->aid);
++	return ret;
+ }
+ 
+-
+ /**
+- * sta_info_flush - flush matching STA entries from the STA table
+- * @local: local interface data
+- * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs
++ * sta_info_flush_delayed - flush matching STA entries from the STA table
++ *
++ * This function unlinks all stations for a given interface and queues
++ * them for freeing. Note that the workqueue function scheduled here has
++ * to run before any new keys can be added to the system to avoid set_key()
++ * callback ordering issues.
++ *
++ * @sdata: the interface
+  */
+-void sta_info_flush(struct ieee80211_local *local, struct net_device *dev)
++void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata)
+ {
++	struct ieee80211_local *local = sdata->local;
+ 	struct sta_info *sta, *tmp;
+-	LIST_HEAD(tmp_list);
+-
+-	write_lock_bh(&local->sta_lock);
+-	list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
+-		if (!dev || dev == sta->dev) {
+-			__sta_info_get(sta);
+-			sta_info_remove(sta);
+-			list_add_tail(&sta->list, &tmp_list);
++	unsigned long flags;
++	bool work = false;
++
++	spin_lock_irqsave(&local->sta_lock, flags);
++	list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
++		if (sdata == sta->sdata) {
++			__sta_info_unlink(&sta);
++			if (sta) {
++				list_add_tail(&sta->list,
++					      &local->sta_flush_list);
++				work = true;
++			}
+ 		}
+-	write_unlock_bh(&local->sta_lock);
+-
+-	list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
+-		sta_info_free(sta);
+-		sta_info_put(sta);
+ 	}
++	if (work)
++		schedule_work(&local->sta_flush_work);
++	spin_unlock_irqrestore(&local->sta_lock, flags);
+ }
+diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
+index 96fe3ed..f8c95bc 100644
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -12,160 +12,293 @@
+ #include <linux/list.h>
+ #include <linux/types.h>
+ #include <linux/if_ether.h>
+-#include <linux/kref.h>
+-#include "ieee80211_key.h"
+-
+-/* Stations flags (struct sta_info::flags) */
+-#define WLAN_STA_AUTH BIT(0)
+-#define WLAN_STA_ASSOC BIT(1)
+-#define WLAN_STA_PS BIT(2)
+-#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */
+-#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */
+-#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is
+-				    * controlling whether STA is authorized to
+-				    * send and receive non-IEEE 802.1X frames
+-				    */
+-#define WLAN_STA_SHORT_PREAMBLE BIT(7)
+-/* whether this is an AP that we are associated with as a client */
+-#define WLAN_STA_ASSOC_AP BIT(8)
+-#define WLAN_STA_WME BIT(9)
+-#define WLAN_STA_WDS BIT(27)
++#include "key.h"
++
++/**
++ * enum ieee80211_sta_info_flags - Stations flags
++ *
++ * These flags are used with &struct sta_info's @flags member.
++ *
++ * @WLAN_STA_AUTH: Station is authenticated.
++ * @WLAN_STA_ASSOC: Station is associated.
++ * @WLAN_STA_PS: Station is in power-save mode
++ * @WLAN_STA_AUTHORIZED: Station is authorized to send/receive traffic.
++ *	This bit is always checked so needs to be enabled for all stations
++ *	when virtual port control is not in use.
++ * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
++ *	frames.
++ * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
++ * @WLAN_STA_WME: Station is a QoS-STA.
++ * @WLAN_STA_WDS: Station is one of our WDS peers.
++ * @WLAN_STA_PSPOLL: Station has just PS-polled us.
++ * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
++ *	IEEE80211_TXCTL_CLEAR_PS_FILT control flag) when the next
++ *	frame to this station is transmitted.
++ */
++enum ieee80211_sta_info_flags {
++	WLAN_STA_AUTH		= 1<<0,
++	WLAN_STA_ASSOC		= 1<<1,
++	WLAN_STA_PS		= 1<<2,
++	WLAN_STA_AUTHORIZED	= 1<<3,
++	WLAN_STA_SHORT_PREAMBLE	= 1<<4,
++	WLAN_STA_ASSOC_AP	= 1<<5,
++	WLAN_STA_WME		= 1<<6,
++	WLAN_STA_WDS		= 1<<7,
++	WLAN_STA_PSPOLL		= 1<<8,
++	WLAN_STA_CLEAR_PS_FILT	= 1<<9,
++};
+ 
+ #define STA_TID_NUM 16
+ #define ADDBA_RESP_INTERVAL HZ
++#define HT_AGG_MAX_RETRIES		(0x3)
+ 
+ #define HT_AGG_STATE_INITIATOR_SHIFT	(4)
+ 
++#define HT_ADDBA_REQUESTED_MSK		BIT(0)
++#define HT_ADDBA_DRV_READY_MSK		BIT(1)
++#define HT_ADDBA_RECEIVED_MSK		BIT(2)
+ #define HT_AGG_STATE_REQ_STOP_BA_MSK	BIT(3)
+-
++#define HT_AGG_STATE_INITIATOR_MSK      BIT(HT_AGG_STATE_INITIATOR_SHIFT)
+ #define HT_AGG_STATE_IDLE		(0x0)
+-#define HT_AGG_STATE_OPERATIONAL	(0x7)
++#define HT_AGG_STATE_OPERATIONAL	(HT_ADDBA_REQUESTED_MSK |	\
++					 HT_ADDBA_DRV_READY_MSK |	\
++					 HT_ADDBA_RECEIVED_MSK)
++#define HT_AGG_STATE_DEBUGFS_CTL	BIT(7)
+ 
+ /**
+- * struct tid_ampdu_rx - TID aggregation information (Rx).
++ * struct tid_ampdu_tx - TID aggregation information (Tx).
+  *
+- * @state: TID's state in session state machine.
++ * @addba_resp_timer: timer for peer's response to addba request
++ * @ssn: Starting Sequence Number expected to be aggregated.
+  * @dialog_token: dialog token for aggregation session
++ */
++struct tid_ampdu_tx {
++	struct timer_list addba_resp_timer;
++	u16 ssn;
++	u8 dialog_token;
++};
++
++/**
++ * struct tid_ampdu_rx - TID aggregation information (Rx).
++ *
++ * @reorder_buf: buffer to reorder incoming aggregated MPDUs
++ * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
++ * @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.
+  * @buf_size: buffer size for incoming A-MPDUs
+  * @timeout: reset timer value.
+- * @head_seq_num: head sequence number in reordering buffer.
+- * @stored_mpdu_num: number of MPDUs in reordering buffer
+- * @reorder_buf: buffer to reorder incoming aggregated MPDUs
+- * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
++ * @dialog_token: dialog token for aggregation session
+  */
+ struct tid_ampdu_rx {
+-	u8 state;
+-	u8 dialog_token;
++	struct sk_buff **reorder_buf;
++	struct timer_list session_timer;
++	u16 head_seq_num;
++	u16 stored_mpdu_num;
+ 	u16 ssn;
+ 	u16 buf_size;
+ 	u16 timeout;
+-	u16 head_seq_num;
+-	u16 stored_mpdu_num;
+-	struct sk_buff **reorder_buf;
+-	struct timer_list session_timer;
++	u8 dialog_token;
++};
++
++/**
++ * enum plink_state - state of a mesh peer link finite state machine
++ *
++ * @PLINK_LISTEN: initial state, considered the implicit state of non existant
++ * 	mesh peer links
++ * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh peer
++ * @PLINK_OPN_RCVD: mesh plink open frame has been received from this mesh peer
++ * @PLINK_CNF_RCVD: mesh plink confirm frame has been received from this mesh
++ * 	peer
++ * @PLINK_ESTAB: mesh peer link is established
++ * @PLINK_HOLDING: mesh peer link is being closed or cancelled
++ * @PLINK_BLOCKED: all frames transmitted from this mesh plink are discarded
++ */
++enum plink_state {
++	PLINK_LISTEN,
++	PLINK_OPN_SNT,
++	PLINK_OPN_RCVD,
++	PLINK_CNF_RCVD,
++	PLINK_ESTAB,
++	PLINK_HOLDING,
++	PLINK_BLOCKED
+ };
+ 
+ /**
+  * struct sta_ampdu_mlme - STA aggregation information.
+  *
+- * @tid_agg_info_rx: aggregation info for Rx per TID
++ * @tid_state_rx: TID's state in Rx session state machine.
++ * @tid_rx: aggregation info for Rx per TID
+  * @ampdu_rx: for locking sections in aggregation Rx flow
++ * @tid_state_tx: TID's state in Tx session state machine.
++ * @tid_tx: aggregation info for Tx per TID
++ * @addba_req_num: number of times addBA request has been sent.
++ * @ampdu_tx: for locking sectionsi in aggregation Tx flow
++ * @dialog_token_allocator: dialog token enumerator for each new session;
+  */
+ struct sta_ampdu_mlme {
+-	struct tid_ampdu_rx tid_rx[STA_TID_NUM];
++	/* rx */
++	u8 tid_state_rx[STA_TID_NUM];
++	struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
+ 	spinlock_t ampdu_rx;
++	/* tx */
++	u8 tid_state_tx[STA_TID_NUM];
++	struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
++	u8 addba_req_num[STA_TID_NUM];
++	spinlock_t ampdu_tx;
++	u8 dialog_token_allocator;
+ };
+ 
++
++/* see __sta_info_unlink */
++#define STA_INFO_PIN_STAT_NORMAL	0
++#define STA_INFO_PIN_STAT_PINNED	1
++#define STA_INFO_PIN_STAT_DESTROY	2
++
++/**
++ * struct sta_info - STA information
++ *
++ * This structure collects information about a station that
++ * mac80211 is communicating with.
++ *
++ * @list: global linked list entry
++ * @hnext: hash table linked list pointer
++ * @local: pointer to the global information
++ * @addr: MAC address of this STA
++ * @aid: STA's unique AID (1..2007, 0 = not assigned yet),
++ *	only used in AP (and IBSS?) mode
++ * @flags: STA flags, see &enum ieee80211_sta_info_flags
++ * @ps_tx_buf: buffer of frames to transmit to this station
++ *	when it leaves power saving state
++ * @tx_filtered: buffer of frames we already tried to transmit
++ *	but were filtered by hardware due to STA having entered
++ *	power saving state
++ * @rx_packets: Number of MSDUs received from this STA
++ * @rx_bytes: Number of bytes received from this STA
++ * @supp_rates: Bitmap of supported rates (per band)
++ * @ht_info: HT capabilities of this STA
++ */
+ struct sta_info {
+-	struct kref kref;
++	/* General information, mostly static */
+ 	struct list_head list;
+-	struct sta_info *hnext; /* next entry in hash table list */
+-
++	struct sta_info *hnext;
+ 	struct ieee80211_local *local;
+-
+-	u8 addr[ETH_ALEN];
+-	u16 aid; /* STA's unique AID (1..2007), 0 = not yet assigned */
+-	u32 flags; /* WLAN_STA_ */
+-
+-	struct sk_buff_head ps_tx_buf; /* buffer of TX frames for station in
+-					* power saving state */
+-	int pspoll; /* whether STA has send a PS Poll frame */
+-	struct sk_buff_head tx_filtered; /* buffer of TX frames that were
+-					  * already given to low-level driver,
+-					  * but were filtered */
+-	int clear_dst_mask;
+-
+-	unsigned long rx_packets, tx_packets; /* number of RX/TX MSDUs */
+-	unsigned long rx_bytes, tx_bytes;
+-	unsigned long tx_retry_failed, tx_retry_count;
+-	unsigned long tx_filtered_count;
+-
+-	unsigned int wep_weak_iv_count; /* number of RX frames with weak IV */
+-
+-	unsigned long last_rx;
+-	u32 supp_rates; /* bitmap of supported rates in local->curr_rates */
+-	int txrate; /* index in local->curr_rates */
+-	int last_txrate; /* last rate used to send a frame to this STA */
+-	int last_nonerp_idx;
+-
+-	struct net_device *dev; /* which net device is this station associated
+-				 * to */
+-
++	struct ieee80211_sub_if_data *sdata;
+ 	struct ieee80211_key *key;
+-
+-	u32 tx_num_consecutive_failures;
+-	u32 tx_num_mpdu_ok;
+-	u32 tx_num_mpdu_fail;
+-
+ 	struct rate_control_ref *rate_ctrl;
+ 	void *rate_ctrl_priv;
++	struct ieee80211_ht_info ht_info;
++	u64 supp_rates[IEEE80211_NUM_BANDS];
++	u8 addr[ETH_ALEN];
++	u16 aid;
++	u16 listen_interval;
+ 
+-	/* last received seq/frag number from this STA (per RX queue) */
+-	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
++	/*
++	 * for use by the internal lifetime management,
++	 * see __sta_info_unlink
++	 */
++	u8 pin_status;
++
++	/* frequently updated information, needs locking? */
++	u32 flags;
++
++	/*
++	 * STA powersave frame queues, no more than the internal
++	 * locking required.
++	 */
++	struct sk_buff_head ps_tx_buf;
++	struct sk_buff_head tx_filtered;
++
++	/* Updated from RX path only, no locking requirements */
++	unsigned long rx_packets, rx_bytes;
++	unsigned long wep_weak_iv_count;
++	unsigned long last_rx;
+ 	unsigned long num_duplicates; /* number of duplicate frames received
+ 				       * from this STA */
+-	unsigned long tx_fragments; /* number of transmitted MPDUs */
+ 	unsigned long rx_fragments; /* number of received MPDUs */
+ 	unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
+-
+ 	int last_rssi; /* RSSI of last received frame from this STA */
+ 	int last_signal; /* signal of last received frame from this STA */
+ 	int last_noise; /* noise of last received frame from this STA */
+-	int last_ack_rssi[3]; /* RSSI of last received ACKs from this STA */
+-	unsigned long last_ack;
+-	int channel_use;
+-	int channel_use_raw;
+-
++	/* last received seq/frag number from this STA (per RX queue) */
++	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
+ #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ 	unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
++#endif
++
++	/* Updated from TX status path only, no locking requirements */
++	unsigned long tx_filtered_count;
++	unsigned long tx_retry_failed, tx_retry_count;
++	/* TODO: update in generic code not rate control? */
++	u32 tx_num_consecutive_failures;
++	u32 tx_num_mpdu_ok;
++	u32 tx_num_mpdu_fail;
++	/* moving percentage of failed MSDUs */
++	unsigned int fail_avg;
++
++	/* Updated from TX path only, no locking requirements */
++	unsigned long tx_packets; /* number of RX/TX MSDUs */
++	unsigned long tx_bytes;
++	unsigned long tx_fragments; /* number of transmitted MPDUs */
++	int txrate_idx;
++	int last_txrate_idx;
++#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ 	unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
+-#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
++#endif
+ 
+-	u16 listen_interval;
++	/* Debug counters, no locking doesn't matter */
++	int channel_use;
++	int channel_use_raw;
+ 
+-	struct ieee80211_ht_info ht_info; /* 802.11n HT capabilities
+-					     of this STA */
++	/*
++	 * Aggregation information, comes with own locking.
++	 */
+ 	struct sta_ampdu_mlme ampdu_mlme;
+-	u8 timer_to_tid[STA_TID_NUM];	/* convert timer id to tid */
++	u8 timer_to_tid[STA_TID_NUM];	/* identity mapping to ID timers */
++	u8 tid_to_tx_q[STA_TID_NUM];	/* map tid to tx queue */
++
++#ifdef CONFIG_MAC80211_MESH
++	/*
++	 * Mesh peer link attributes
++	 * TODO: move to a sub-structure that is referenced with pointer?
++	 */
++	__le16 llid;		/* Local link ID */
++	__le16 plid;		/* Peer link ID */
++	__le16 reason;		/* Cancel reason on PLINK_HOLDING state */
++	u8 plink_retries;	/* Retries in establishment */
++	bool ignore_plink_timer;
++	enum plink_state plink_state;
++	u32 plink_timeout;
++	struct timer_list plink_timer;
++	spinlock_t plink_lock;	/* For peer_state reads / updates and other
++				   updates in the structure. Ensures robust
++				   transitions for the peerlink FSM */
++#endif
+ 
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ 	struct sta_info_debugfsdentries {
+ 		struct dentry *dir;
+ 		struct dentry *flags;
+ 		struct dentry *num_ps_buf_frames;
+-		struct dentry *last_ack_rssi;
+-		struct dentry *last_ack_ms;
+ 		struct dentry *inactive_ms;
+ 		struct dentry *last_seq_ctrl;
+ #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ 		struct dentry *wme_rx_queue;
+ 		struct dentry *wme_tx_queue;
+ #endif
++		struct dentry *agg_status;
+ 	} debugfs;
+ #endif
+ };
+ 
++static inline enum plink_state sta_plink_state(struct sta_info *sta)
++{
++#ifdef CONFIG_MAC80211_MESH
++	return sta->plink_state;
++#endif
++	return PLINK_LISTEN;
++}
++
+ 
+ /* Maximum number of concurrently registered stations */
+ #define MAX_STA_COUNT 2007
+@@ -185,22 +318,46 @@ struct sta_info {
+  */
+ #define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
+ 
+-static inline void __sta_info_get(struct sta_info *sta)
+-{
+-	kref_get(&sta->kref);
+-}
++/*
++ * Get a STA info, must have be under RCU read lock.
++ */
++struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr);
++/*
++ * Get STA info by index, BROKEN!
++ */
++struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
++				      struct net_device *dev);
++/*
++ * Create a new STA info, caller owns returned structure
++ * until sta_info_insert().
++ */
++struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
++				u8 *addr, gfp_t gfp);
++/*
++ * Insert STA info into hash table/list, returns zero or a
++ * -EEXIST if (if the same MAC address is already present).
++ *
++ * Calling this without RCU protection makes the caller
++ * relinquish its reference to @sta.
++ */
++int sta_info_insert(struct sta_info *sta);
++/*
++ * Unlink a STA info from the hash table/list.
++ * This can NULL the STA pointer if somebody else
++ * has already unlinked it.
++ */
++void sta_info_unlink(struct sta_info **sta);
++void __sta_info_unlink(struct sta_info **sta);
++
++void sta_info_destroy(struct sta_info *sta);
++void sta_info_set_tim_bit(struct sta_info *sta);
++void sta_info_clear_tim_bit(struct sta_info *sta);
+ 
+-struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
+-int sta_info_min_txrate_get(struct ieee80211_local *local);
+-void sta_info_put(struct sta_info *sta);
+-struct sta_info * sta_info_add(struct ieee80211_local *local,
+-			       struct net_device *dev, u8 *addr, gfp_t gfp);
+-void sta_info_remove(struct sta_info *sta);
+-void sta_info_free(struct sta_info *sta);
+ void sta_info_init(struct ieee80211_local *local);
+ int sta_info_start(struct ieee80211_local *local);
+ void sta_info_stop(struct ieee80211_local *local);
+-void sta_info_remove_aid_ptr(struct sta_info *sta);
+-void sta_info_flush(struct ieee80211_local *local, struct net_device *dev);
++int sta_info_flush(struct ieee80211_local *local,
++		    struct ieee80211_sub_if_data *sdata);
++void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata);
+ 
+ #endif /* STA_INFO_H */
+diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
+index 3abe194..dddbfd6 100644
+--- a/net/mac80211/tkip.c
++++ b/net/mac80211/tkip.c
+@@ -12,7 +12,7 @@
+ #include <linux/netdevice.h>
+ 
+ #include <net/mac80211.h>
+-#include "ieee80211_key.h"
++#include "key.h"
+ #include "tkip.h"
+ #include "wep.h"
+ 
+@@ -214,6 +214,59 @@ void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta,
+ 			   key->u.tkip.iv16, rc4key);
+ }
+ 
++void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
++			struct sk_buff *skb, enum ieee80211_tkip_key_type type,
++			u8 *outkey)
++{
++	struct ieee80211_key *key = (struct ieee80211_key *)
++			container_of(keyconf, struct ieee80211_key, conf);
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	u8 *data = (u8 *) hdr;
++	u16 fc = le16_to_cpu(hdr->frame_control);
++	int hdr_len = ieee80211_get_hdrlen(fc);
++	u8 *ta = hdr->addr2;
++	u16 iv16;
++	u32 iv32;
++
++	iv16 = data[hdr_len] << 8;
++	iv16 += data[hdr_len + 2];
++	iv32 = data[hdr_len + 4] +
++		(data[hdr_len + 5] >> 8) +
++		(data[hdr_len + 6] >> 16) +
++		(data[hdr_len + 7] >> 24);
++
++#ifdef CONFIG_TKIP_DEBUG
++	printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n",
++			iv16, iv32);
++
++	if (iv32 != key->u.tkip.iv32) {
++		printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n",
++			iv32, key->u.tkip.iv32);
++		printk(KERN_DEBUG "Wrap around of iv16 in the middle of a "
++			"fragmented packet\n");
++	}
++#endif /* CONFIG_TKIP_DEBUG */
++
++	/* Update the p1k only when the iv16 in the packet wraps around, this
++	 * might occur after the wrap around of iv16 in the key in case of
++	 * fragmented packets. */
++	if (iv16 == 0 || !key->u.tkip.tx_initialized) {
++		/* IV16 wrapped around - perform TKIP phase 1 */
++		tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],
++			iv32, key->u.tkip.p1k);
++		key->u.tkip.tx_initialized = 1;
++	}
++
++	if (type == IEEE80211_TKIP_P1_KEY) {
++		memcpy(outkey, key->u.tkip.p1k, sizeof(u16) * 5);
++		return;
++	}
++
++	tkip_mixing_phase2(key->u.tkip.p1k,
++		&key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],	iv16, outkey);
++}
++EXPORT_SYMBOL(ieee80211_get_tkip_key);
++
+ /* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
+  * beginning of the buffer containing payload. This payload must include
+  * headroom of eight octets for IV and Ext. IV and taildroom of four octets
+@@ -238,7 +291,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
+ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+ 				struct ieee80211_key *key,
+ 				u8 *payload, size_t payload_len, u8 *ta,
+-				int only_iv, int queue,
++				u8 *ra, int only_iv, int queue,
+ 				u32 *out_iv32, u16 *out_iv16)
+ {
+ 	u32 iv32;
+@@ -315,6 +368,19 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+ 			printk("\n");
+ 		}
+ #endif /* CONFIG_TKIP_DEBUG */
++		if (key->local->ops->update_tkip_key &&
++			key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
++			u8 bcast[ETH_ALEN] =
++				{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
++			u8 *sta_addr = key->sta->addr;
++
++			if (is_multicast_ether_addr(ra))
++				sta_addr = bcast;
++
++			key->local->ops->update_tkip_key(
++				local_to_hw(key->local), &key->conf,
++				sta_addr, iv32, key->u.tkip.p1k_rx[queue]);
++		}
+ 	}
+ 
+ 	tkip_mixing_phase2(key->u.tkip.p1k_rx[queue],
+diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h
+index 73d8ef2..b7c2ee7 100644
+--- a/net/mac80211/tkip.h
++++ b/net/mac80211/tkip.h
+@@ -11,7 +11,7 @@
+ 
+ #include <linux/types.h>
+ #include <linux/crypto.h>
+-#include "ieee80211_key.h"
++#include "key.h"
+ 
+ u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
+ 			   u8 iv0, u8 iv1, u8 iv2);
+@@ -31,7 +31,7 @@ enum {
+ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+ 				struct ieee80211_key *key,
+ 				u8 *payload, size_t payload_len, u8 *ta,
+-				int only_iv, int queue,
++				u8 *ra, int only_iv, int queue,
+ 				u32 *out_iv32, u16 *out_iv16);
+ 
+ #endif /* TKIP_H */
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 67b509e..f35eaea 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -25,11 +25,12 @@
+ #include <asm/unaligned.h>
+ 
+ #include "ieee80211_i.h"
+-#include "ieee80211_led.h"
++#include "led.h"
++#include "mesh.h"
+ #include "wep.h"
+ #include "wpa.h"
+ #include "wme.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
+ 
+ #define IEEE80211_TX_OK		0
+ #define IEEE80211_TX_AGAIN	1
+@@ -86,15 +87,19 @@ static inline void ieee80211_dump_frame(const char *ifname, const char *title,
+ }
+ #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
+ 
+-static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
++static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
+ 			      int next_frag_len)
+ {
+ 	int rate, mrate, erp, dur, i;
+-	struct ieee80211_rate *txrate = tx->u.tx.rate;
++	struct ieee80211_rate *txrate = tx->rate;
+ 	struct ieee80211_local *local = tx->local;
+-	struct ieee80211_hw_mode *mode = tx->u.tx.mode;
++	struct ieee80211_supported_band *sband;
+ 
+-	erp = txrate->flags & IEEE80211_RATE_ERP;
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++	erp = 0;
++	if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++		erp = txrate->flags & IEEE80211_RATE_ERP_G;
+ 
+ 	/*
+ 	 * data and mgmt (except PS Poll):
+@@ -150,20 +155,36 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
+ 	 * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps
+ 	 */
+ 	rate = -1;
+-	mrate = 10; /* use 1 Mbps if everything fails */
+-	for (i = 0; i < mode->num_rates; i++) {
+-		struct ieee80211_rate *r = &mode->rates[i];
+-		if (r->rate > txrate->rate)
+-			break;
++	/* use lowest available if everything fails */
++	mrate = sband->bitrates[0].bitrate;
++	for (i = 0; i < sband->n_bitrates; i++) {
++		struct ieee80211_rate *r = &sband->bitrates[i];
+ 
+-		if (IEEE80211_RATE_MODULATION(txrate->flags) !=
+-		    IEEE80211_RATE_MODULATION(r->flags))
+-			continue;
++		if (r->bitrate > txrate->bitrate)
++			break;
+ 
+-		if (r->flags & IEEE80211_RATE_BASIC)
+-			rate = r->rate;
+-		else if (r->flags & IEEE80211_RATE_MANDATORY)
+-			mrate = r->rate;
++		if (tx->sdata->basic_rates & BIT(i))
++			rate = r->bitrate;
++
++		switch (sband->band) {
++		case IEEE80211_BAND_2GHZ: {
++			u32 flag;
++			if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++				flag = IEEE80211_RATE_MANDATORY_G;
++			else
++				flag = IEEE80211_RATE_MANDATORY_B;
++			if (r->flags & flag)
++				mrate = r->bitrate;
++			break;
++		}
++		case IEEE80211_BAND_5GHZ:
++			if (r->flags & IEEE80211_RATE_MANDATORY_A)
++				mrate = r->bitrate;
++			break;
++		case IEEE80211_NUM_BANDS:
++			WARN_ON(1);
++			break;
++		}
+ 	}
+ 	if (rate == -1) {
+ 		/* No matching basic rate found; use highest suitable mandatory
+@@ -184,7 +205,7 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
+ 		dur *= 2; /* ACK + SIFS */
+ 		/* next fragment */
+ 		dur += ieee80211_frame_duration(local, next_frag_len,
+-				txrate->rate, erp,
++				txrate->bitrate, erp,
+ 				tx->sdata->bss_conf.use_short_preamble);
+ 	}
+ 
+@@ -212,8 +233,8 @@ static int inline is_ieee80211_device(struct net_device *dev,
+ 
+ /* tx handlers */
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
+ {
+ #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ 	struct sk_buff *skb = tx->skb;
+@@ -221,20 +242,23 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
+ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ 	u32 sta_flags;
+ 
+-	if (unlikely(tx->flags & IEEE80211_TXRXD_TX_INJECTED))
+-		return TXRX_CONTINUE;
++	if (unlikely(tx->flags & IEEE80211_TX_INJECTED))
++		return TX_CONTINUE;
+ 
+ 	if (unlikely(tx->local->sta_sw_scanning) &&
+ 	    ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+ 	     (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ))
+-		return TXRX_DROP;
++		return TX_DROP;
+ 
+-	if (tx->flags & IEEE80211_TXRXD_TXPS_BUFFERED)
+-		return TXRX_CONTINUE;
++	if (tx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
++		return TX_CONTINUE;
++
++	if (tx->flags & IEEE80211_TX_PS_BUFFERED)
++		return TX_CONTINUE;
+ 
+ 	sta_flags = tx->sta ? tx->sta->flags : 0;
+ 
+-	if (likely(tx->flags & IEEE80211_TXRXD_TXUNICAST)) {
++	if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
+ 		if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
+ 			     tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+ 			     (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
+@@ -245,7 +269,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
+ 			       tx->dev->name, print_mac(mac, hdr->addr1));
+ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ 			I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
+-			return TXRX_DROP;
++			return TX_DROP;
+ 		}
+ 	} else {
+ 		if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+@@ -255,23 +279,23 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
+ 			 * No associated STAs - no need to send multicast
+ 			 * frames.
+ 			 */
+-			return TXRX_DROP;
++			return TX_DROP;
+ 		}
+-		return TXRX_CONTINUE;
++		return TX_CONTINUE;
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_sequence(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+ 
+ 	if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24)
+ 		ieee80211_include_sequence(tx->sdata, hdr);
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+ /* This function is called whenever the AP is about to exceed the maximum limit
+@@ -303,10 +327,8 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
+ 		}
+ 		total += skb_queue_len(&ap->ps_bc_buf);
+ 	}
+-	rcu_read_unlock();
+ 
+-	read_lock_bh(&local->sta_lock);
+-	list_for_each_entry(sta, &local->sta_list, list) {
++	list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ 		skb = skb_dequeue(&sta->ps_tx_buf);
+ 		if (skb) {
+ 			purged++;
+@@ -314,15 +336,16 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
+ 		}
+ 		total += skb_queue_len(&sta->ps_tx_buf);
+ 	}
+-	read_unlock_bh(&local->sta_lock);
++
++	rcu_read_unlock();
+ 
+ 	local->total_ps_buffered = total;
+ 	printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n",
+ 	       wiphy_name(local->hw.wiphy), purged);
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
+ {
+ 	/*
+ 	 * broadcast/multicast frame
+@@ -334,11 +357,11 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
+ 
+ 	/* not AP/IBSS or ordered frame */
+ 	if (!tx->sdata->bss || (tx->fc & IEEE80211_FCTL_ORDER))
+-		return TXRX_CONTINUE;
++		return TX_CONTINUE;
+ 
+ 	/* no stations in PS mode */
+ 	if (!atomic_read(&tx->sdata->bss->num_sta_ps))
+-		return TXRX_CONTINUE;
++		return TX_CONTINUE;
+ 
+ 	/* buffered in mac80211 */
+ 	if (tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) {
+@@ -355,17 +378,17 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
+ 		} else
+ 			tx->local->total_ps_buffered++;
+ 		skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
+-		return TXRX_QUEUED;
++		return TX_QUEUED;
+ 	}
+ 
+ 	/* buffered in hardware */
+-	tx->u.tx.control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
++	tx->control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
+ {
+ 	struct sta_info *sta = tx->sta;
+ 	DECLARE_MAC_BUF(mac);
+@@ -373,9 +396,10 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+ 	if (unlikely(!sta ||
+ 		     ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
+ 		      (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)))
+-		return TXRX_CONTINUE;
++		return TX_CONTINUE;
+ 
+-	if (unlikely((sta->flags & WLAN_STA_PS) && !sta->pspoll)) {
++	if (unlikely((sta->flags & WLAN_STA_PS) &&
++		     !(sta->flags & WLAN_STA_PSPOLL))) {
+ 		struct ieee80211_tx_packet_data *pkt_data;
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ 		printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries "
+@@ -383,7 +407,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+ 		       print_mac(mac, sta->addr), sta->aid,
+ 		       skb_queue_len(&sta->ps_tx_buf));
+ #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+-		sta->flags |= WLAN_STA_TIM;
+ 		if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
+ 			purge_old_ps_buffers(tx->local);
+ 		if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) {
+@@ -396,18 +419,15 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+ 			dev_kfree_skb(old);
+ 		} else
+ 			tx->local->total_ps_buffered++;
++
+ 		/* Queue frame to be sent after STA sends an PS Poll frame */
+-		if (skb_queue_empty(&sta->ps_tx_buf)) {
+-			if (tx->local->ops->set_tim)
+-				tx->local->ops->set_tim(local_to_hw(tx->local),
+-						       sta->aid, 1);
+-			if (tx->sdata->bss)
+-				bss_tim_set(tx->local, tx->sdata->bss, sta->aid);
+-		}
++		if (skb_queue_empty(&sta->ps_tx_buf))
++			sta_info_set_tim_bit(sta);
++
+ 		pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb;
+ 		pkt_data->jiffies = jiffies;
+ 		skb_queue_tail(&sta->ps_tx_buf, tx->skb);
+-		return TXRX_QUEUED;
++		return TX_QUEUED;
+ 	}
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ 	else if (unlikely(sta->flags & WLAN_STA_PS)) {
+@@ -416,40 +436,40 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+ 		       print_mac(mac, sta->addr));
+ 	}
+ #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+-	sta->pspoll = 0;
++	sta->flags &= ~WLAN_STA_PSPOLL;
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
+ {
+-	if (unlikely(tx->flags & IEEE80211_TXRXD_TXPS_BUFFERED))
+-		return TXRX_CONTINUE;
++	if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
++		return TX_CONTINUE;
+ 
+-	if (tx->flags & IEEE80211_TXRXD_TXUNICAST)
++	if (tx->flags & IEEE80211_TX_UNICAST)
+ 		return ieee80211_tx_h_unicast_ps_buf(tx);
+ 	else
+ 		return ieee80211_tx_h_multicast_ps_buf(tx);
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
+ {
+ 	struct ieee80211_key *key;
+ 	u16 fc = tx->fc;
+ 
+-	if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
++	if (unlikely(tx->control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
+ 		tx->key = NULL;
+ 	else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
+ 		tx->key = key;
+ 	else if ((key = rcu_dereference(tx->sdata->default_key)))
+ 		tx->key = key;
+ 	else if (tx->sdata->drop_unencrypted &&
+-		 !(tx->u.tx.control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
+-		 !(tx->flags & IEEE80211_TXRXD_TX_INJECTED)) {
++		 !(tx->control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
++		 !(tx->flags & IEEE80211_TX_INJECTED)) {
+ 		I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
+-		return TXRX_DROP;
++		return TX_DROP;
+ 	} else
+ 		tx->key = NULL;
+ 
+@@ -476,13 +496,13 @@ ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
+ 	}
+ 
+ 	if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
+-		tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
++		tx->control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+ 	size_t hdrlen, per_fragm, num_fragm, payload_len, left;
+@@ -492,8 +512,8 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
+ 	u8 *pos;
+ 	int frag_threshold = tx->local->fragmentation_threshold;
+ 
+-	if (!(tx->flags & IEEE80211_TXRXD_FRAGMENTED))
+-		return TXRX_CONTINUE;
++	if (!(tx->flags & IEEE80211_TX_FRAGMENTED))
++		return TX_CONTINUE;
+ 
+ 	first = tx->skb;
+ 
+@@ -544,10 +564,10 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
+ 	}
+ 	skb_trim(first, hdrlen + per_fragm);
+ 
+-	tx->u.tx.num_extra_frag = num_fragm - 1;
+-	tx->u.tx.extra_frag = frags;
++	tx->num_extra_frag = num_fragm - 1;
++	tx->extra_frag = frags;
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ 
+  fail:
+ 	printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);
+@@ -558,14 +578,14 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
+ 		kfree(frags);
+ 	}
+ 	I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment);
+-	return TXRX_DROP;
++	return TX_DROP;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_encrypt(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
+ {
+ 	if (!tx->key)
+-		return TXRX_CONTINUE;
++		return TX_CONTINUE;
+ 
+ 	switch (tx->key->conf.alg) {
+ 	case ALG_WEP:
+@@ -578,59 +598,60 @@ ieee80211_tx_h_encrypt(struct ieee80211_txrx_data *tx)
+ 
+ 	/* not reached */
+ 	WARN_ON(1);
+-	return TXRX_DROP;
++	return TX_DROP;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
+ {
+ 	struct rate_selection rsel;
++	struct ieee80211_supported_band *sband;
++
++	sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
+ 
+-	if (likely(!tx->u.tx.rate)) {
+-		rate_control_get_rate(tx->dev, tx->u.tx.mode, tx->skb, &rsel);
+-		tx->u.tx.rate = rsel.rate;
+-		if (unlikely(rsel.probe != NULL)) {
+-			tx->u.tx.control->flags |=
++	if (likely(!tx->rate)) {
++		rate_control_get_rate(tx->dev, sband, tx->skb, &rsel);
++		tx->rate = rsel.rate;
++		if (unlikely(rsel.probe)) {
++			tx->control->flags |=
+ 				IEEE80211_TXCTL_RATE_CTRL_PROBE;
+-			tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
+-			tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val;
+-			tx->u.tx.rate = rsel.probe;
++			tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
++			tx->control->alt_retry_rate = tx->rate;
++			tx->rate = rsel.probe;
+ 		} else
+-			tx->u.tx.control->alt_retry_rate = -1;
++			tx->control->alt_retry_rate = NULL;
+ 
+-		if (!tx->u.tx.rate)
+-			return TXRX_DROP;
++		if (!tx->rate)
++			return TX_DROP;
+ 	} else
+-		tx->u.tx.control->alt_retry_rate = -1;
++		tx->control->alt_retry_rate = NULL;
+ 
+-	if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
+-	    tx->sdata->bss_conf.use_cts_prot &&
+-	    (tx->flags & IEEE80211_TXRXD_FRAGMENTED) && rsel.nonerp) {
+-		tx->u.tx.last_frag_rate = tx->u.tx.rate;
++	if (tx->sdata->bss_conf.use_cts_prot &&
++	    (tx->flags & IEEE80211_TX_FRAGMENTED) && rsel.nonerp) {
++		tx->last_frag_rate = tx->rate;
+ 		if (rsel.probe)
+-			tx->flags &= ~IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
++			tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG;
+ 		else
+-			tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
+-		tx->u.tx.rate = rsel.nonerp;
+-		tx->u.tx.control->rate = rsel.nonerp;
+-		tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
++			tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
++		tx->rate = rsel.nonerp;
++		tx->control->tx_rate = rsel.nonerp;
++		tx->control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
+ 	} else {
+-		tx->u.tx.last_frag_rate = tx->u.tx.rate;
+-		tx->u.tx.control->rate = tx->u.tx.rate;
++		tx->last_frag_rate = tx->rate;
++		tx->control->tx_rate = tx->rate;
+ 	}
+-	tx->u.tx.control->tx_rate = tx->u.tx.rate->val;
++	tx->control->tx_rate = tx->rate;
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+ 	u16 fc = le16_to_cpu(hdr->frame_control);
+ 	u16 dur;
+-	struct ieee80211_tx_control *control = tx->u.tx.control;
+-	struct ieee80211_hw_mode *mode = tx->u.tx.mode;
++	struct ieee80211_tx_control *control = tx->control;
+ 
+ 	if (!control->retry_limit) {
+ 		if (!is_multicast_ether_addr(hdr->addr1)) {
+@@ -652,20 +673,20 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
+ 		}
+ 	}
+ 
+-	if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
++	if (tx->flags & IEEE80211_TX_FRAGMENTED) {
+ 		/* Do not use multiple retry rates when sending fragmented
+ 		 * frames.
+ 		 * TODO: The last fragment could still use multiple retry
+ 		 * rates. */
+-		control->alt_retry_rate = -1;
++		control->alt_retry_rate = NULL;
+ 	}
+ 
+ 	/* Use CTS protection for unicast frames sent using extended rates if
+ 	 * there are associated non-ERP stations and RTS/CTS is not configured
+ 	 * for the frame. */
+-	if (mode->mode == MODE_IEEE80211G &&
+-	    (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
+-	    (tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
++	if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) &&
++	    (tx->rate->flags & IEEE80211_RATE_ERP_G) &&
++	    (tx->flags & IEEE80211_TX_UNICAST) &&
+ 	    tx->sdata->bss_conf.use_cts_prot &&
+ 	    !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
+ 		control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
+@@ -674,62 +695,77 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
+ 	 * short preambles at the selected rate and short preambles are
+ 	 * available on the network at the current point in time. */
+ 	if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+-	    (tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
++	    (tx->rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
+ 	    tx->sdata->bss_conf.use_short_preamble &&
+ 	    (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
+-		tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
++		tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
+ 	}
+ 
+ 	/* Setup duration field for the first fragment of the frame. Duration
+ 	 * for remaining fragments will be updated when they are being sent
+ 	 * to low-level driver in ieee80211_tx(). */
+ 	dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1),
+-				 (tx->flags & IEEE80211_TXRXD_FRAGMENTED) ?
+-				 tx->u.tx.extra_frag[0]->len : 0);
++				 (tx->flags & IEEE80211_TX_FRAGMENTED) ?
++				 tx->extra_frag[0]->len : 0);
+ 	hdr->duration_id = cpu_to_le16(dur);
+ 
+ 	if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
+ 	    (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
+-		struct ieee80211_rate *rate;
++		struct ieee80211_supported_band *sband;
++		struct ieee80211_rate *rate, *baserate;
++		int idx;
++
++		sband = tx->local->hw.wiphy->bands[
++				tx->local->hw.conf.channel->band];
+ 
+ 		/* Do not use multiple retry rates when using RTS/CTS */
+-		control->alt_retry_rate = -1;
++		control->alt_retry_rate = NULL;
+ 
+ 		/* Use min(data rate, max base rate) as CTS/RTS rate */
+-		rate = tx->u.tx.rate;
+-		while (rate > mode->rates &&
+-		       !(rate->flags & IEEE80211_RATE_BASIC))
+-			rate--;
++		rate = tx->rate;
++		baserate = NULL;
++
++		for (idx = 0; idx < sband->n_bitrates; idx++) {
++			if (sband->bitrates[idx].bitrate > rate->bitrate)
++				continue;
++			if (tx->sdata->basic_rates & BIT(idx) &&
++			    (!baserate ||
++			     (baserate->bitrate < sband->bitrates[idx].bitrate)))
++				baserate = &sband->bitrates[idx];
++		}
+ 
+-		control->rts_cts_rate = rate->val;
+-		control->rts_rate = rate;
++		if (baserate)
++			control->rts_cts_rate = baserate;
++		else
++			control->rts_cts_rate = &sband->bitrates[0];
+ 	}
+ 
+ 	if (tx->sta) {
++		control->aid = tx->sta->aid;
+ 		tx->sta->tx_packets++;
+ 		tx->sta->tx_fragments++;
+ 		tx->sta->tx_bytes += tx->skb->len;
+-		if (tx->u.tx.extra_frag) {
++		if (tx->extra_frag) {
+ 			int i;
+-			tx->sta->tx_fragments += tx->u.tx.num_extra_frag;
+-			for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
++			tx->sta->tx_fragments += tx->num_extra_frag;
++			for (i = 0; i < tx->num_extra_frag; i++) {
+ 				tx->sta->tx_bytes +=
+-					tx->u.tx.extra_frag[i]->len;
++					tx->extra_frag[i]->len;
+ 			}
+ 		}
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+-static ieee80211_txrx_result
+-ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx)
+ {
+ 	struct ieee80211_local *local = tx->local;
+-	struct ieee80211_hw_mode *mode = tx->u.tx.mode;
+ 	struct sk_buff *skb = tx->skb;
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ 	u32 load = 0, hdrtime;
++	struct ieee80211_rate *rate = tx->rate;
+ 
+ 	/* TODO: this could be part of tx_status handling, so that the number
+ 	 * of retries would be known; TX rate should in that case be stored
+@@ -740,9 +776,9 @@ ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
+ 	/* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
+ 	 * 1 usec = 1/8 * (1080 / 10) = 13.5 */
+ 
+-	if (mode->mode == MODE_IEEE80211A ||
+-	    (mode->mode == MODE_IEEE80211G &&
+-	     tx->u.tx.rate->flags & IEEE80211_RATE_ERP))
++	if (tx->channel->band == IEEE80211_BAND_5GHZ ||
++	    (tx->channel->band == IEEE80211_BAND_2GHZ &&
++	     rate->flags & IEEE80211_RATE_ERP_G))
+ 		hdrtime = CHAN_UTIL_HDR_SHORT;
+ 	else
+ 		hdrtime = CHAN_UTIL_HDR_LONG;
+@@ -751,19 +787,20 @@ ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
+ 	if (!is_multicast_ether_addr(hdr->addr1))
+ 		load += hdrtime;
+ 
+-	if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
++	if (tx->control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
+ 		load += 2 * hdrtime;
+-	else if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
++	else if (tx->control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+ 		load += hdrtime;
+ 
+-	load += skb->len * tx->u.tx.rate->rate_inv;
++	/* TODO: optimise again */
++	load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate;
+ 
+-	if (tx->u.tx.extra_frag) {
++	if (tx->extra_frag) {
+ 		int i;
+-		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
++		for (i = 0; i < tx->num_extra_frag; i++) {
+ 			load += 2 * hdrtime;
+-			load += tx->u.tx.extra_frag[i]->len *
+-				tx->u.tx.rate->rate;
++			load += tx->extra_frag[i]->len *
++				tx->rate->bitrate;
+ 		}
+ 	}
+ 
+@@ -774,13 +811,12 @@ ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
+ 		tx->sta->channel_use_raw += load;
+ 	tx->sdata->channel_use_raw += load;
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+-/* TODO: implement register/unregister functions for adding TX/RX handlers
+- * into ordered list */
+ 
+-ieee80211_tx_handler ieee80211_tx_handlers[] =
++typedef ieee80211_tx_result (*ieee80211_tx_handler)(struct ieee80211_tx_data *);
++static ieee80211_tx_handler ieee80211_tx_handlers[] =
+ {
+ 	ieee80211_tx_h_check_assoc,
+ 	ieee80211_tx_h_sequence,
+@@ -801,8 +837,8 @@ ieee80211_tx_handler ieee80211_tx_handlers[] =
+  * deal with packet injection down monitor interface
+  * with Radiotap Header -- only called for monitor mode interface
+  */
+-static ieee80211_txrx_result
+-__ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
++static ieee80211_tx_result
++__ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
+ 			      struct sk_buff *skb)
+ {
+ 	/*
+@@ -816,13 +852,15 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ 	struct ieee80211_radiotap_iterator iterator;
+ 	struct ieee80211_radiotap_header *rthdr =
+ 		(struct ieee80211_radiotap_header *) skb->data;
+-	struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode;
++	struct ieee80211_supported_band *sband;
+ 	int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
+-	struct ieee80211_tx_control *control = tx->u.tx.control;
++	struct ieee80211_tx_control *control = tx->control;
++
++	sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
+ 
+ 	control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+-	tx->flags |= IEEE80211_TXRXD_TX_INJECTED;
+-	tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
++	tx->flags |= IEEE80211_TX_INJECTED;
++	tx->flags &= ~IEEE80211_TX_FRAGMENTED;
+ 
+ 	/*
+ 	 * for every radiotap entry that is present
+@@ -852,11 +890,13 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ 			 * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps
+ 			 */
+ 			target_rate = (*iterator.this_arg) * 5;
+-			for (i = 0; i < mode->num_rates; i++) {
+-				struct ieee80211_rate *r = &mode->rates[i];
++			for (i = 0; i < sband->n_bitrates; i++) {
++				struct ieee80211_rate *r;
++
++				r = &sband->bitrates[i];
+ 
+-				if (r->rate == target_rate) {
+-					tx->u.tx.rate = r;
++				if (r->bitrate == target_rate) {
++					tx->rate = r;
+ 					break;
+ 				}
+ 			}
+@@ -870,9 +910,11 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ 			control->antenna_sel_tx = (*iterator.this_arg) + 1;
+ 			break;
+ 
++#if 0
+ 		case IEEE80211_RADIOTAP_DBM_TX_POWER:
+ 			control->power_level = *iterator.this_arg;
+ 			break;
++#endif
+ 
+ 		case IEEE80211_RADIOTAP_FLAGS:
+ 			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
+@@ -884,7 +926,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ 				 * on transmission
+ 				 */
+ 				if (skb->len < (iterator.max_length + FCS_LEN))
+-					return TXRX_DROP;
++					return TX_DROP;
+ 
+ 				skb_trim(skb, skb->len - FCS_LEN);
+ 			}
+@@ -892,7 +934,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ 				control->flags &=
+ 					~IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+ 			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
+-				tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
++				tx->flags |= IEEE80211_TX_FRAGMENTED;
+ 			break;
+ 
+ 		/*
+@@ -907,7 +949,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ 	}
+ 
+ 	if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
+-		return TXRX_DROP;
++		return TX_DROP;
+ 
+ 	/*
+ 	 * remove the radiotap header
+@@ -916,14 +958,14 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ 	 */
+ 	skb_pull(skb, iterator.max_length);
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+ /*
+  * initialises @tx
+  */
+-static ieee80211_txrx_result
+-__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
++static ieee80211_tx_result
++__ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
+ 		       struct sk_buff *skb,
+ 		       struct net_device *dev,
+ 		       struct ieee80211_tx_control *control)
+@@ -939,18 +981,18 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ 	tx->dev = dev; /* use original interface */
+ 	tx->local = local;
+ 	tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-	tx->u.tx.control = control;
++	tx->control = control;
+ 	/*
+ 	 * Set this flag (used below to indicate "automatic fragmentation"),
+ 	 * it will be cleared/left by radiotap as desired.
+ 	 */
+-	tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
++	tx->flags |= IEEE80211_TX_FRAGMENTED;
+ 
+ 	/* process and remove the injection radiotap header */
+ 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ 	if (unlikely(sdata->vif.type == IEEE80211_IF_TYPE_MNTR)) {
+-		if (__ieee80211_parse_tx_radiotap(tx, skb) == TXRX_DROP)
+-			return TXRX_DROP;
++		if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP)
++			return TX_DROP;
+ 
+ 		/*
+ 		 * __ieee80211_parse_tx_radiotap has now removed
+@@ -965,27 +1007,27 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ 	tx->fc = le16_to_cpu(hdr->frame_control);
+ 
+ 	if (is_multicast_ether_addr(hdr->addr1)) {
+-		tx->flags &= ~IEEE80211_TXRXD_TXUNICAST;
++		tx->flags &= ~IEEE80211_TX_UNICAST;
+ 		control->flags |= IEEE80211_TXCTL_NO_ACK;
+ 	} else {
+-		tx->flags |= IEEE80211_TXRXD_TXUNICAST;
++		tx->flags |= IEEE80211_TX_UNICAST;
+ 		control->flags &= ~IEEE80211_TXCTL_NO_ACK;
+ 	}
+ 
+-	if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
+-		if ((tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
++	if (tx->flags & IEEE80211_TX_FRAGMENTED) {
++		if ((tx->flags & IEEE80211_TX_UNICAST) &&
+ 		    skb->len + FCS_LEN > local->fragmentation_threshold &&
+ 		    !local->ops->set_frag_threshold)
+-			tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
++			tx->flags |= IEEE80211_TX_FRAGMENTED;
+ 		else
+-			tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
++			tx->flags &= ~IEEE80211_TX_FRAGMENTED;
+ 	}
+ 
+ 	if (!tx->sta)
+-		control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+-	else if (tx->sta->clear_dst_mask) {
+-		control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+-		tx->sta->clear_dst_mask = 0;
++		control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
++	else if (tx->sta->flags & WLAN_STA_CLEAR_PS_FILT) {
++		control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
++		tx->sta->flags &= ~WLAN_STA_CLEAR_PS_FILT;
+ 	}
+ 
+ 	hdrlen = ieee80211_get_hdrlen(tx->fc);
+@@ -995,13 +1037,13 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ 	}
+ 	control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+ /*
+  * NB: @tx is uninitialised when passed in here
+  */
+-static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
++static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
+ 				struct sk_buff *skb,
+ 				struct net_device *mdev,
+ 				struct ieee80211_tx_control *control)
+@@ -1024,9 +1066,9 @@ static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ }
+ 
+ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
+-			  struct ieee80211_txrx_data *tx)
++			  struct ieee80211_tx_data *tx)
+ {
+-	struct ieee80211_tx_control *control = tx->u.tx.control;
++	struct ieee80211_tx_control *control = tx->control;
+ 	int ret, i;
+ 
+ 	if (!ieee80211_qdisc_installed(local->mdev) &&
+@@ -1043,20 +1085,20 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
+ 		local->mdev->trans_start = jiffies;
+ 		ieee80211_led_tx(local, 1);
+ 	}
+-	if (tx->u.tx.extra_frag) {
++	if (tx->extra_frag) {
+ 		control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
+ 				    IEEE80211_TXCTL_USE_CTS_PROTECT |
+-				    IEEE80211_TXCTL_CLEAR_DST_MASK |
++				    IEEE80211_TXCTL_CLEAR_PS_FILT |
+ 				    IEEE80211_TXCTL_FIRST_FRAGMENT);
+-		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+-			if (!tx->u.tx.extra_frag[i])
++		for (i = 0; i < tx->num_extra_frag; i++) {
++			if (!tx->extra_frag[i])
+ 				continue;
+ 			if (__ieee80211_queue_stopped(local, control->queue))
+ 				return IEEE80211_TX_FRAG_AGAIN;
+-			if (i == tx->u.tx.num_extra_frag) {
+-				control->tx_rate = tx->u.tx.last_frag_hwrate;
+-				control->rate = tx->u.tx.last_frag_rate;
+-				if (tx->flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG)
++			if (i == tx->num_extra_frag) {
++				control->tx_rate = tx->last_frag_rate;
++
++				if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG)
+ 					control->flags |=
+ 						IEEE80211_TXCTL_RATE_CTRL_PROBE;
+ 				else
+@@ -1066,18 +1108,18 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
+ 
+ 			ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
+ 					     "TX to low-level driver",
+-					     tx->u.tx.extra_frag[i]);
++					     tx->extra_frag[i]);
+ 			ret = local->ops->tx(local_to_hw(local),
+-					    tx->u.tx.extra_frag[i],
++					    tx->extra_frag[i],
+ 					    control);
+ 			if (ret)
+ 				return IEEE80211_TX_FRAG_AGAIN;
+ 			local->mdev->trans_start = jiffies;
+ 			ieee80211_led_tx(local, 1);
+-			tx->u.tx.extra_frag[i] = NULL;
++			tx->extra_frag[i] = NULL;
+ 		}
+-		kfree(tx->u.tx.extra_frag);
+-		tx->u.tx.extra_frag = NULL;
++		kfree(tx->extra_frag);
++		tx->extra_frag = NULL;
+ 	}
+ 	return IEEE80211_TX_OK;
+ }
+@@ -1088,8 +1130,8 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
+ 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ 	struct sta_info *sta;
+ 	ieee80211_tx_handler *handler;
+-	struct ieee80211_txrx_data tx;
+-	ieee80211_txrx_result res = TXRX_DROP, res_prepare;
++	struct ieee80211_tx_data tx;
++	ieee80211_tx_result res = TX_DROP, res_prepare;
+ 	int ret, i;
+ 
+ 	WARN_ON(__ieee80211_queue_pending(local, control->queue));
+@@ -1099,59 +1141,52 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
+ 		return 0;
+ 	}
+ 
++	rcu_read_lock();
++
+ 	/* initialises tx */
+ 	res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control);
+ 
+-	if (res_prepare == TXRX_DROP) {
++	if (res_prepare == TX_DROP) {
+ 		dev_kfree_skb(skb);
++		rcu_read_unlock();
+ 		return 0;
+ 	}
+ 
+-	/*
+-	 * key references are protected using RCU and this requires that
+-	 * we are in a read-site RCU section during receive processing
+-	 */
+-	rcu_read_lock();
+-
+ 	sta = tx.sta;
+-	tx.u.tx.mode = local->hw.conf.mode;
++	tx.channel = local->hw.conf.channel;
+ 
+-	for (handler = local->tx_handlers; *handler != NULL;
++	for (handler = ieee80211_tx_handlers; *handler != NULL;
+ 	     handler++) {
+ 		res = (*handler)(&tx);
+-		if (res != TXRX_CONTINUE)
++		if (res != TX_CONTINUE)
+ 			break;
+ 	}
+ 
+ 	skb = tx.skb; /* handlers are allowed to change skb */
+ 
+-	if (sta)
+-		sta_info_put(sta);
+-
+-	if (unlikely(res == TXRX_DROP)) {
++	if (unlikely(res == TX_DROP)) {
+ 		I802_DEBUG_INC(local->tx_handlers_drop);
+ 		goto drop;
+ 	}
+ 
+-	if (unlikely(res == TXRX_QUEUED)) {
++	if (unlikely(res == TX_QUEUED)) {
+ 		I802_DEBUG_INC(local->tx_handlers_queued);
+ 		rcu_read_unlock();
+ 		return 0;
+ 	}
+ 
+-	if (tx.u.tx.extra_frag) {
+-		for (i = 0; i < tx.u.tx.num_extra_frag; i++) {
++	if (tx.extra_frag) {
++		for (i = 0; i < tx.num_extra_frag; i++) {
+ 			int next_len, dur;
+ 			struct ieee80211_hdr *hdr =
+ 				(struct ieee80211_hdr *)
+-				tx.u.tx.extra_frag[i]->data;
++				tx.extra_frag[i]->data;
+ 
+-			if (i + 1 < tx.u.tx.num_extra_frag) {
+-				next_len = tx.u.tx.extra_frag[i + 1]->len;
++			if (i + 1 < tx.num_extra_frag) {
++				next_len = tx.extra_frag[i + 1]->len;
+ 			} else {
+ 				next_len = 0;
+-				tx.u.tx.rate = tx.u.tx.last_frag_rate;
+-				tx.u.tx.last_frag_hwrate = tx.u.tx.rate->val;
++				tx.rate = tx.last_frag_rate;
+ 			}
+ 			dur = ieee80211_duration(&tx, 0, next_len);
+ 			hdr->duration_id = cpu_to_le16(dur);
+@@ -1186,12 +1221,11 @@ retry:
+ 		memcpy(&store->control, control,
+ 		       sizeof(struct ieee80211_tx_control));
+ 		store->skb = skb;
+-		store->extra_frag = tx.u.tx.extra_frag;
+-		store->num_extra_frag = tx.u.tx.num_extra_frag;
+-		store->last_frag_hwrate = tx.u.tx.last_frag_hwrate;
+-		store->last_frag_rate = tx.u.tx.last_frag_rate;
++		store->extra_frag = tx.extra_frag;
++		store->num_extra_frag = tx.num_extra_frag;
++		store->last_frag_rate = tx.last_frag_rate;
+ 		store->last_frag_rate_ctrl_probe =
+-			!!(tx.flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG);
++			!!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG);
+ 	}
+ 	rcu_read_unlock();
+ 	return 0;
+@@ -1199,10 +1233,10 @@ retry:
+  drop:
+ 	if (skb)
+ 		dev_kfree_skb(skb);
+-	for (i = 0; i < tx.u.tx.num_extra_frag; i++)
+-		if (tx.u.tx.extra_frag[i])
+-			dev_kfree_skb(tx.u.tx.extra_frag[i]);
+-	kfree(tx.u.tx.extra_frag);
++	for (i = 0; i < tx.num_extra_frag; i++)
++		if (tx.extra_frag[i])
++			dev_kfree_skb(tx.extra_frag[i]);
++	kfree(tx.extra_frag);
+ 	rcu_read_unlock();
+ 	return 0;
+ }
+@@ -1260,6 +1294,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
+ 		control.flags |= IEEE80211_TXCTL_REQUEUE;
+ 	if (pkt_data->flags & IEEE80211_TXPD_EAPOL_FRAME)
+ 		control.flags |= IEEE80211_TXCTL_EAPOL_FRAME;
++	if (pkt_data->flags & IEEE80211_TXPD_AMPDU)
++		control.flags |= IEEE80211_TXCTL_AMPDU;
+ 	control.queue = pkt_data->queue;
+ 
+ 	ret = ieee80211_tx(odev, skb, &control);
+@@ -1346,8 +1382,9 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ 	struct ieee80211_tx_packet_data *pkt_data;
+ 	struct ieee80211_sub_if_data *sdata;
+ 	int ret = 1, head_need;
+-	u16 ethertype, hdrlen, fc;
++	u16 ethertype, hdrlen,  meshhdrlen = 0, fc;
+ 	struct ieee80211_hdr hdr;
++	struct ieee80211s_hdr mesh_hdr;
+ 	const u8 *encaps_data;
+ 	int encaps_len, skip_header_bytes;
+ 	int nh_pos, h_pos;
+@@ -1389,6 +1426,37 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ 		memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+ 		hdrlen = 30;
+ 		break;
++#ifdef CONFIG_MAC80211_MESH
++	case IEEE80211_IF_TYPE_MESH_POINT:
++		fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
++		/* RA TA DA SA */
++		if (is_multicast_ether_addr(skb->data))
++			memcpy(hdr.addr1, skb->data, ETH_ALEN);
++		else if (mesh_nexthop_lookup(hdr.addr1, skb, dev))
++				return 0;
++		memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
++		memcpy(hdr.addr3, skb->data, ETH_ALEN);
++		memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
++		if (skb->pkt_type == PACKET_OTHERHOST) {
++			/* Forwarded frame, keep mesh ttl and seqnum */
++			struct ieee80211s_hdr *prev_meshhdr;
++			prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb);
++			meshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr);
++			memcpy(&mesh_hdr, prev_meshhdr, meshhdrlen);
++			sdata->u.sta.mshstats.fwded_frames++;
++		} else {
++			if (!sdata->u.sta.mshcfg.dot11MeshTTL) {
++				/* Do not send frames with mesh_ttl == 0 */
++				sdata->u.sta.mshstats.dropped_frames_ttl++;
++				ret = 0;
++				goto fail;
++			}
++			meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
++							       sdata);
++		}
++		hdrlen = 30;
++		break;
++#endif
+ 	case IEEE80211_IF_TYPE_STA:
+ 		fc |= IEEE80211_FCTL_TODS;
+ 		/* BSSID SA DA */
+@@ -1409,10 +1477,17 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ 		goto fail;
+ 	}
+ 
+-	sta = sta_info_get(local, hdr.addr1);
+-	if (sta) {
+-		sta_flags = sta->flags;
+-		sta_info_put(sta);
++	/*
++	 * There's no need to try to look up the destination
++	 * if it is a multicast address (which can only happen
++	 * in AP mode)
++	 */
++	if (!is_multicast_ether_addr(hdr.addr1)) {
++		rcu_read_lock();
++		sta = sta_info_get(local, hdr.addr1);
++		if (sta)
++			sta_flags = sta->flags;
++		rcu_read_unlock();
+ 	}
+ 
+ 	/* receiver is QoS enabled, use a QoS type frame */
+@@ -1422,12 +1497,12 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ 	}
+ 
+ 	/*
+-	 * If port access control is enabled, drop frames to unauthorised
+-	 * stations unless they are EAPOL frames from the local station.
++	 * Drop unicast frames to unauthorised stations unless they are
++	 * EAPOL frames from the local station.
+ 	 */
+-	if (unlikely(sdata->ieee802_1x_pac &&
+-		     !(sta_flags & WLAN_STA_AUTHORIZED) &&
+-		     !(ethertype == ETH_P_PAE &&
++	if (unlikely(!is_multicast_ether_addr(hdr.addr1) &&
++		      !(sta_flags & WLAN_STA_AUTHORIZED) &&
++		      !(ethertype == ETH_P_PAE &&
+ 		       compare_ether_addr(dev->dev_addr,
+ 					  skb->data + ETH_ALEN) == 0))) {
+ #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+@@ -1480,7 +1555,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ 	 * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and
+ 	 * alloc_skb() (net/core/skbuff.c)
+ 	 */
+-	head_need = hdrlen + encaps_len + local->tx_headroom;
++	head_need = hdrlen + encaps_len + meshhdrlen + local->tx_headroom;
+ 	head_need -= skb_headroom(skb);
+ 
+ 	/* We are going to modify skb data, so make a copy of it if happens to
+@@ -1514,6 +1589,12 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ 		h_pos += encaps_len;
+ 	}
+ 
++	if (meshhdrlen > 0) {
++		memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
++		nh_pos += meshhdrlen;
++		h_pos += meshhdrlen;
++	}
++
+ 	if (fc & IEEE80211_STYPE_QOS_DATA) {
+ 		__le16 *qos_control;
+ 
+@@ -1583,7 +1664,7 @@ void ieee80211_tx_pending(unsigned long data)
+ 	struct ieee80211_local *local = (struct ieee80211_local *)data;
+ 	struct net_device *dev = local->mdev;
+ 	struct ieee80211_tx_stored_packet *store;
+-	struct ieee80211_txrx_data tx;
++	struct ieee80211_tx_data tx;
+ 	int i, ret, reschedule = 0;
+ 
+ 	netif_tx_lock_bh(dev);
+@@ -1595,14 +1676,13 @@ void ieee80211_tx_pending(unsigned long data)
+ 			continue;
+ 		}
+ 		store = &local->pending_packet[i];
+-		tx.u.tx.control = &store->control;
+-		tx.u.tx.extra_frag = store->extra_frag;
+-		tx.u.tx.num_extra_frag = store->num_extra_frag;
+-		tx.u.tx.last_frag_hwrate = store->last_frag_hwrate;
+-		tx.u.tx.last_frag_rate = store->last_frag_rate;
++		tx.control = &store->control;
++		tx.extra_frag = store->extra_frag;
++		tx.num_extra_frag = store->num_extra_frag;
++		tx.last_frag_rate = store->last_frag_rate;
+ 		tx.flags = 0;
+ 		if (store->last_frag_rate_ctrl_probe)
+-			tx.flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
++			tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG;
+ 		ret = __ieee80211_tx(local, store->skb, &tx);
+ 		if (ret) {
+ 			if (ret == IEEE80211_TX_FRAG_AGAIN)
+@@ -1636,7 +1716,6 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
+ 
+ 	/* Generate bitmap for TIM only if there are any STAs in power save
+ 	 * mode. */
+-	read_lock_bh(&local->sta_lock);
+ 	if (atomic_read(&bss->num_sta_ps) > 0)
+ 		/* in the hope that this is faster than
+ 		 * checking byte-for-byte */
+@@ -1687,7 +1766,6 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
+ 		*pos++ = aid0; /* Bitmap control */
+ 		*pos++ = 0; /* Part Virt Bitmap */
+ 	}
+-	read_unlock_bh(&local->sta_lock);
+ }
+ 
+ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+@@ -1701,16 +1779,96 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+ 	struct ieee80211_if_ap *ap = NULL;
+ 	struct rate_selection rsel;
+ 	struct beacon_data *beacon;
++	struct ieee80211_supported_band *sband;
++	struct ieee80211_mgmt *mgmt;
++	int *num_beacons;
++	bool err = true;
++	u8 *pos;
++
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ 
+ 	rcu_read_lock();
+ 
+ 	sdata = vif_to_sdata(vif);
+ 	bdev = sdata->dev;
+-	ap = &sdata->u.ap;
+ 
+-	beacon = rcu_dereference(ap->beacon);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++		ap = &sdata->u.ap;
++		beacon = rcu_dereference(ap->beacon);
++		if (ap && beacon) {
++			/*
++			 * headroom, head length,
++			 * tail length and maximum TIM length
++			 */
++			skb = dev_alloc_skb(local->tx_headroom +
++					    beacon->head_len +
++					    beacon->tail_len + 256);
++			if (!skb)
++				goto out;
++
++			skb_reserve(skb, local->tx_headroom);
++			memcpy(skb_put(skb, beacon->head_len), beacon->head,
++			       beacon->head_len);
++
++			ieee80211_include_sequence(sdata,
++					(struct ieee80211_hdr *)skb->data);
++
++			/*
++			 * Not very nice, but we want to allow the driver to call
++			 * ieee80211_beacon_get() as a response to the set_tim()
++			 * callback. That, however, is already invoked under the
++			 * sta_lock to guarantee consistent and race-free update
++			 * of the tim bitmap in mac80211 and the driver.
++			 */
++			if (local->tim_in_locked_section) {
++				ieee80211_beacon_add_tim(local, ap, skb, beacon);
++			} else {
++				unsigned long flags;
++
++				spin_lock_irqsave(&local->sta_lock, flags);
++				ieee80211_beacon_add_tim(local, ap, skb, beacon);
++				spin_unlock_irqrestore(&local->sta_lock, flags);
++			}
++
++			if (beacon->tail)
++				memcpy(skb_put(skb, beacon->tail_len),
++				       beacon->tail, beacon->tail_len);
+ 
+-	if (!ap || sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon) {
++			num_beacons = &ap->num_beacons;
++
++			err = false;
++		}
++	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
++		/* headroom, head length, tail length and maximum TIM length */
++		skb = dev_alloc_skb(local->tx_headroom + 400);
++		if (!skb)
++			goto out;
++
++		skb_reserve(skb, local->hw.extra_tx_headroom);
++		mgmt = (struct ieee80211_mgmt *)
++			skb_put(skb, 24 + sizeof(mgmt->u.beacon));
++		memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
++		mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++						   IEEE80211_STYPE_BEACON);
++		memset(mgmt->da, 0xff, ETH_ALEN);
++		memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
++		/* BSSID is left zeroed, wildcard value */
++		mgmt->u.beacon.beacon_int =
++			cpu_to_le16(local->hw.conf.beacon_int);
++		mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */
++
++		pos = skb_put(skb, 2);
++		*pos++ = WLAN_EID_SSID;
++		*pos++ = 0x0;
++
++		mesh_mgmt_ies_add(skb, sdata->dev);
++
++		num_beacons = &sdata->u.sta.num_beacons;
++
++		err = false;
++	}
++
++	if (err) {
+ #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ 		if (net_ratelimit())
+ 			printk(KERN_DEBUG "no beacon data avail for %s\n",
+@@ -1720,27 +1878,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+ 		goto out;
+ 	}
+ 
+-	/* headroom, head length, tail length and maximum TIM length */
+-	skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
+-			    beacon->tail_len + 256);
+-	if (!skb)
+-		goto out;
+-
+-	skb_reserve(skb, local->tx_headroom);
+-	memcpy(skb_put(skb, beacon->head_len), beacon->head,
+-	       beacon->head_len);
+-
+-	ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
+-
+-	ieee80211_beacon_add_tim(local, ap, skb, beacon);
+-
+-	if (beacon->tail)
+-		memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
+-		       beacon->tail_len);
+-
+ 	if (control) {
+-		rate_control_get_rate(local->mdev, local->oper_hw_mode, skb,
+-				      &rsel);
++		rate_control_get_rate(local->mdev, sband, skb, &rsel);
+ 		if (!rsel.rate) {
+ 			if (net_ratelimit()) {
+ 				printk(KERN_DEBUG "%s: ieee80211_beacon_get: "
+@@ -1753,20 +1892,17 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+ 		}
+ 
+ 		control->vif = vif;
+-		control->tx_rate =
+-			(sdata->bss_conf.use_short_preamble &&
+-			(rsel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
+-			rsel.rate->val2 : rsel.rate->val;
++		control->tx_rate = rsel.rate;
++		if (sdata->bss_conf.use_short_preamble &&
++		    rsel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
++			control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
+ 		control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+-		control->power_level = local->hw.conf.power_level;
+ 		control->flags |= IEEE80211_TXCTL_NO_ACK;
+ 		control->retry_limit = 1;
+-		control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
++		control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
+ 	}
+-
+-	ap->num_beacons++;
+-
+- out:
++	(*num_beacons)++;
++out:
+ 	rcu_read_unlock();
+ 	return skb;
+ }
+@@ -1814,8 +1950,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
+ 	struct sk_buff *skb;
+ 	struct sta_info *sta;
+ 	ieee80211_tx_handler *handler;
+-	struct ieee80211_txrx_data tx;
+-	ieee80211_txrx_result res = TXRX_DROP;
++	struct ieee80211_tx_data tx;
++	ieee80211_tx_result res = TX_DROP;
+ 	struct net_device *bdev;
+ 	struct ieee80211_sub_if_data *sdata;
+ 	struct ieee80211_if_ap *bss = NULL;
+@@ -1836,7 +1972,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
+ 		rcu_read_unlock();
+ 		return NULL;
+ 	}
+-	rcu_read_unlock();
+ 
+ 	if (bss->dtim_count != 0)
+ 		return NULL; /* send buffered bc/mc only after DTIM beacon */
+@@ -1862,27 +1997,26 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
+ 		dev_kfree_skb_any(skb);
+ 	}
+ 	sta = tx.sta;
+-	tx.flags |= IEEE80211_TXRXD_TXPS_BUFFERED;
+-	tx.u.tx.mode = local->hw.conf.mode;
++	tx.flags |= IEEE80211_TX_PS_BUFFERED;
++	tx.channel = local->hw.conf.channel;
+ 
+-	for (handler = local->tx_handlers; *handler != NULL; handler++) {
++	for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) {
+ 		res = (*handler)(&tx);
+-		if (res == TXRX_DROP || res == TXRX_QUEUED)
++		if (res == TX_DROP || res == TX_QUEUED)
+ 			break;
+ 	}
+ 	skb = tx.skb; /* handlers are allowed to change skb */
+ 
+-	if (res == TXRX_DROP) {
++	if (res == TX_DROP) {
+ 		I802_DEBUG_INC(local->tx_handlers_drop);
+ 		dev_kfree_skb(skb);
+ 		skb = NULL;
+-	} else if (res == TXRX_QUEUED) {
++	} else if (res == TX_QUEUED) {
+ 		I802_DEBUG_INC(local->tx_handlers_queued);
+ 		skb = NULL;
+ 	}
+ 
+-	if (sta)
+-		sta_info_put(sta);
++	rcu_read_unlock();
+ 
+ 	return skb;
+ }
+diff --git a/net/mac80211/util.c b/net/mac80211/util.c
+index 5e631ce..cc9f715 100644
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -25,7 +25,8 @@
+ #include <net/rtnetlink.h>
+ 
+ #include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
++#include "mesh.h"
+ #include "wme.h"
+ 
+ /* privid for wiphys to determine whether they belong to us or not */
+@@ -41,92 +42,6 @@ const unsigned char bridge_tunnel_header[] =
+ 	{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+ 
+ 
+-static int rate_list_match(const int *rate_list, int rate)
+-{
+-	int i;
+-
+-	if (!rate_list)
+-		return 0;
+-
+-	for (i = 0; rate_list[i] >= 0; i++)
+-		if (rate_list[i] == rate)
+-			return 1;
+-
+-	return 0;
+-}
+-
+-void ieee80211_prepare_rates(struct ieee80211_local *local,
+-			     struct ieee80211_hw_mode *mode)
+-{
+-	int i;
+-
+-	for (i = 0; i < mode->num_rates; i++) {
+-		struct ieee80211_rate *rate = &mode->rates[i];
+-
+-		rate->flags &= ~(IEEE80211_RATE_SUPPORTED |
+-				 IEEE80211_RATE_BASIC);
+-
+-		if (local->supp_rates[mode->mode]) {
+-			if (!rate_list_match(local->supp_rates[mode->mode],
+-					     rate->rate))
+-				continue;
+-		}
+-
+-		rate->flags |= IEEE80211_RATE_SUPPORTED;
+-
+-		/* Use configured basic rate set if it is available. If not,
+-		 * use defaults that are sane for most cases. */
+-		if (local->basic_rates[mode->mode]) {
+-			if (rate_list_match(local->basic_rates[mode->mode],
+-					    rate->rate))
+-				rate->flags |= IEEE80211_RATE_BASIC;
+-		} else switch (mode->mode) {
+-		case MODE_IEEE80211A:
+-			if (rate->rate == 60 || rate->rate == 120 ||
+-			    rate->rate == 240)
+-				rate->flags |= IEEE80211_RATE_BASIC;
+-			break;
+-		case MODE_IEEE80211B:
+-			if (rate->rate == 10 || rate->rate == 20)
+-				rate->flags |= IEEE80211_RATE_BASIC;
+-			break;
+-		case MODE_IEEE80211G:
+-			if (rate->rate == 10 || rate->rate == 20 ||
+-			    rate->rate == 55 || rate->rate == 110)
+-				rate->flags |= IEEE80211_RATE_BASIC;
+-			break;
+-		case NUM_IEEE80211_MODES:
+-			/* not useful */
+-			break;
+-		}
+-
+-		/* Set ERP and MANDATORY flags based on phymode */
+-		switch (mode->mode) {
+-		case MODE_IEEE80211A:
+-			if (rate->rate == 60 || rate->rate == 120 ||
+-			    rate->rate == 240)
+-				rate->flags |= IEEE80211_RATE_MANDATORY;
+-			break;
+-		case MODE_IEEE80211B:
+-			if (rate->rate == 10)
+-				rate->flags |= IEEE80211_RATE_MANDATORY;
+-			break;
+-		case MODE_IEEE80211G:
+-			if (rate->rate == 10 || rate->rate == 20 ||
+-			    rate->rate == 55 || rate->rate == 110 ||
+-			    rate->rate == 60 || rate->rate == 120 ||
+-			    rate->rate == 240)
+-				rate->flags |= IEEE80211_RATE_MANDATORY;
+-			break;
+-		case NUM_IEEE80211_MODES:
+-			/* not useful */
+-			break;
+-		}
+-		if (ieee80211_is_erp_rate(mode->mode, rate->rate))
+-			rate->flags |= IEEE80211_RATE_ERP;
+-	}
+-}
+-
+ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
+ 			enum ieee80211_if_types type)
+ {
+@@ -232,17 +147,35 @@ int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
+ }
+ EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
+ 
+-void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx)
++int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
++{
++	int ae = meshhdr->flags & IEEE80211S_FLAGS_AE;
++	/* 7.1.3.5a.2 */
++	switch (ae) {
++	case 0:
++		return 5;
++	case 1:
++		return 11;
++	case 2:
++		return 17;
++	case 3:
++		return 23;
++	default:
++		return 5;
++	}
++}
++
++void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+ 
+ 	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+-	if (tx->u.tx.extra_frag) {
++	if (tx->extra_frag) {
+ 		struct ieee80211_hdr *fhdr;
+ 		int i;
+-		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
++		for (i = 0; i < tx->num_extra_frag; i++) {
+ 			fhdr = (struct ieee80211_hdr *)
+-				tx->u.tx.extra_frag[i]->data;
++				tx->extra_frag[i]->data;
+ 			fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ 		}
+ 	}
+@@ -262,7 +195,7 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
+ 	 * DIV_ROUND_UP() operations.
+ 	 */
+ 
+-	if (local->hw.conf.phymode == MODE_IEEE80211A || erp) {
++	if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) {
+ 		/*
+ 		 * OFDM:
+ 		 *
+@@ -304,15 +237,19 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
+ /* Exported duration function for driver use */
+ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
+ 					struct ieee80211_vif *vif,
+-					size_t frame_len, int rate)
++					size_t frame_len,
++					struct ieee80211_rate *rate)
+ {
+ 	struct ieee80211_local *local = hw_to_local(hw);
+ 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ 	u16 dur;
+ 	int erp;
+ 
+-	erp = ieee80211_is_erp_rate(hw->conf.phymode, rate);
+-	dur = ieee80211_frame_duration(local, frame_len, rate, erp,
++	erp = 0;
++	if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++		erp = rate->flags & IEEE80211_RATE_ERP_G;
++
++	dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp,
+ 				       sdata->bss_conf.use_short_preamble);
+ 
+ 	return cpu_to_le16(dur);
+@@ -332,17 +269,20 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
+ 
+ 	short_preamble = sdata->bss_conf.use_short_preamble;
+ 
+-	rate = frame_txctl->rts_rate;
+-	erp = !!(rate->flags & IEEE80211_RATE_ERP);
++	rate = frame_txctl->rts_cts_rate;
++
++	erp = 0;
++	if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++		erp = rate->flags & IEEE80211_RATE_ERP_G;
+ 
+ 	/* CTS duration */
+-	dur = ieee80211_frame_duration(local, 10, rate->rate,
++	dur = ieee80211_frame_duration(local, 10, rate->bitrate,
+ 				       erp, short_preamble);
+ 	/* Data frame duration */
+-	dur += ieee80211_frame_duration(local, frame_len, rate->rate,
++	dur += ieee80211_frame_duration(local, frame_len, rate->bitrate,
+ 					erp, short_preamble);
+ 	/* ACK duration */
+-	dur += ieee80211_frame_duration(local, 10, rate->rate,
++	dur += ieee80211_frame_duration(local, 10, rate->bitrate,
+ 					erp, short_preamble);
+ 
+ 	return cpu_to_le16(dur);
+@@ -363,15 +303,17 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+ 
+ 	short_preamble = sdata->bss_conf.use_short_preamble;
+ 
+-	rate = frame_txctl->rts_rate;
+-	erp = !!(rate->flags & IEEE80211_RATE_ERP);
++	rate = frame_txctl->rts_cts_rate;
++	erp = 0;
++	if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++		erp = rate->flags & IEEE80211_RATE_ERP_G;
+ 
+ 	/* Data frame duration */
+-	dur = ieee80211_frame_duration(local, frame_len, rate->rate,
++	dur = ieee80211_frame_duration(local, frame_len, rate->bitrate,
+ 				       erp, short_preamble);
+ 	if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) {
+ 		/* ACK duration */
+-		dur += ieee80211_frame_duration(local, 10, rate->rate,
++		dur += ieee80211_frame_duration(local, 10, rate->bitrate,
+ 						erp, short_preamble);
+ 	}
+ 
+@@ -379,27 +321,6 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+ }
+ EXPORT_SYMBOL(ieee80211_ctstoself_duration);
+ 
+-struct ieee80211_rate *
+-ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate)
+-{
+-	struct ieee80211_hw_mode *mode;
+-	int r;
+-
+-	list_for_each_entry(mode, &local->modes_list, list) {
+-		if (mode->mode != phymode)
+-			continue;
+-		for (r = 0; r < mode->num_rates; r++) {
+-			struct ieee80211_rate *rate = &mode->rates[r];
+-			if (rate->val == hw_rate ||
+-			    (rate->flags & IEEE80211_RATE_PREAMBLE2 &&
+-			     rate->val2 == hw_rate))
+-				return rate;
+-		}
+-	}
+-
+-	return NULL;
+-}
+-
+ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
+ {
+ 	struct ieee80211_local *local = hw_to_local(hw);
+@@ -480,6 +401,7 @@ void ieee80211_iterate_active_interfaces(
+ 		case IEEE80211_IF_TYPE_STA:
+ 		case IEEE80211_IF_TYPE_IBSS:
+ 		case IEEE80211_IF_TYPE_WDS:
++		case IEEE80211_IF_TYPE_MESH_POINT:
+ 			break;
+ 		}
+ 		if (sdata->dev == local->mdev)
+diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
+index a0cff72..affcecd 100644
+--- a/net/mac80211/wep.c
++++ b/net/mac80211/wep.c
+@@ -305,39 +305,39 @@ u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key)
+ 	return NULL;
+ }
+ 
+-ieee80211_txrx_result
+-ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx)
++ieee80211_rx_result
++ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
+ {
+ 	if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
+ 	    ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+ 	     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH))
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+-	if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
++	if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
+ 		if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
+ #ifdef CONFIG_MAC80211_DEBUG
+ 			if (net_ratelimit())
+ 				printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
+ 				       "failed\n", rx->dev->name);
+ #endif /* CONFIG_MAC80211_DEBUG */
+-			return TXRX_DROP;
++			return RX_DROP_UNUSABLE;
+ 		}
+-	} else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) {
++	} else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) {
+ 		ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
+ 		/* remove ICV */
+ 		skb_trim(rx->skb, rx->skb->len - 4);
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
+ }
+ 
+-static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
++static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
+ {
+ 	if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
+ 		if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
+ 			return -1;
+ 	} else {
+-		tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
++		tx->control->key_idx = tx->key->conf.hw_key_idx;
+ 		if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
+ 			if (!ieee80211_wep_add_iv(tx->local, skb, tx->key))
+ 				return -1;
+@@ -346,28 +346,28 @@ static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
+ 	return 0;
+ }
+ 
+-ieee80211_txrx_result
+-ieee80211_crypto_wep_encrypt(struct ieee80211_txrx_data *tx)
++ieee80211_tx_result
++ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx)
+ {
+-	tx->u.tx.control->iv_len = WEP_IV_LEN;
+-	tx->u.tx.control->icv_len = WEP_ICV_LEN;
+-	ieee80211_tx_set_iswep(tx);
++	tx->control->iv_len = WEP_IV_LEN;
++	tx->control->icv_len = WEP_ICV_LEN;
++	ieee80211_tx_set_protected(tx);
+ 
+ 	if (wep_encrypt_skb(tx, tx->skb) < 0) {
+ 		I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
+-		return TXRX_DROP;
++		return TX_DROP;
+ 	}
+ 
+-	if (tx->u.tx.extra_frag) {
++	if (tx->extra_frag) {
+ 		int i;
+-		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+-			if (wep_encrypt_skb(tx, tx->u.tx.extra_frag[i]) < 0) {
++		for (i = 0; i < tx->num_extra_frag; i++) {
++			if (wep_encrypt_skb(tx, tx->extra_frag[i]) < 0) {
+ 				I802_DEBUG_INC(tx->local->
+ 					       tx_handlers_drop_wep);
+-				return TXRX_DROP;
++				return TX_DROP;
+ 			}
+ 		}
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
+index 785fbb4..363779c 100644
+--- a/net/mac80211/wep.h
++++ b/net/mac80211/wep.h
+@@ -14,7 +14,7 @@
+ #include <linux/skbuff.h>
+ #include <linux/types.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_key.h"
++#include "key.h"
+ 
+ int ieee80211_wep_init(struct ieee80211_local *local);
+ void ieee80211_wep_free(struct ieee80211_local *local);
+@@ -28,9 +28,9 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
+ 			  struct ieee80211_key *key);
+ u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
+ 
+-ieee80211_txrx_result
+-ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx);
+-ieee80211_txrx_result
+-ieee80211_crypto_wep_encrypt(struct ieee80211_txrx_data *tx);
++ieee80211_rx_result
++ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx);
++ieee80211_tx_result
++ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx);
+ 
+ #endif /* WEP_H */
+diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
+new file mode 100644
+index 0000000..76e1de1
+--- /dev/null
++++ b/net/mac80211/wext.c
+@@ -0,0 +1,1152 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/skbuff.h>
++#include <linux/etherdevice.h>
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++#include <asm/uaccess.h>
++
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "led.h"
++#include "rate.h"
++#include "wpa.h"
++#include "aes_ccm.h"
++
++
++static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
++				    int idx, int alg, int remove,
++				    int set_tx_key, const u8 *_key,
++				    size_t key_len)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sta_info *sta;
++	struct ieee80211_key *key;
++	struct ieee80211_sub_if_data *sdata;
++	int err;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
++		printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
++		       dev->name, idx);
++		return -EINVAL;
++	}
++
++	if (remove) {
++		rcu_read_lock();
++
++		err = 0;
++
++		if (is_broadcast_ether_addr(sta_addr)) {
++			key = sdata->keys[idx];
++		} else {
++			sta = sta_info_get(local, sta_addr);
++			if (!sta) {
++				err = -ENOENT;
++				goto out_unlock;
++			}
++			key = sta->key;
++		}
++
++		ieee80211_key_free(key);
++	} else {
++		key = ieee80211_key_alloc(alg, idx, key_len, _key);
++		if (!key)
++			return -ENOMEM;
++
++		sta = NULL;
++		err = 0;
++
++		rcu_read_lock();
++
++		if (!is_broadcast_ether_addr(sta_addr)) {
++			set_tx_key = 0;
++			/*
++			 * According to the standard, the key index of a
++			 * pairwise key must be zero. However, some AP are
++			 * broken when it comes to WEP key indices, so we
++			 * work around this.
++			 */
++			if (idx != 0 && alg != ALG_WEP) {
++				ieee80211_key_free(key);
++				err = -EINVAL;
++				goto out_unlock;
++			}
++
++			sta = sta_info_get(local, sta_addr);
++			if (!sta) {
++				ieee80211_key_free(key);
++				err = -ENOENT;
++				goto out_unlock;
++			}
++		}
++
++		ieee80211_key_link(key, sdata, sta);
++
++		if (set_tx_key || (!sta && !sdata->default_key && key))
++			ieee80211_set_default_key(sdata, idx);
++	}
++
++ out_unlock:
++	rcu_read_unlock();
++
++	return err;
++}
++
++static int ieee80211_ioctl_siwgenie(struct net_device *dev,
++				    struct iw_request_info *info,
++				    struct iw_point *data, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
++		return -EOPNOTSUPP;
++
++	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++		int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
++		if (ret)
++			return ret;
++		sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
++		ieee80211_sta_req_auth(dev, &sdata->u.sta);
++		return 0;
++	}
++
++	return -EOPNOTSUPP;
++}
++
++static int ieee80211_ioctl_giwname(struct net_device *dev,
++				   struct iw_request_info *info,
++				   char *name, char *extra)
++{
++	strcpy(name, "IEEE 802.11");
++
++	return 0;
++}
++
++
++static int ieee80211_ioctl_giwrange(struct net_device *dev,
++				 struct iw_request_info *info,
++				 struct iw_point *data, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct iw_range *range = (struct iw_range *) extra;
++	enum ieee80211_band band;
++	int c = 0;
++
++	data->length = sizeof(struct iw_range);
++	memset(range, 0, sizeof(struct iw_range));
++
++	range->we_version_compiled = WIRELESS_EXT;
++	range->we_version_source = 21;
++	range->retry_capa = IW_RETRY_LIMIT;
++	range->retry_flags = IW_RETRY_LIMIT;
++	range->min_retry = 0;
++	range->max_retry = 255;
++	range->min_rts = 0;
++	range->max_rts = 2347;
++	range->min_frag = 256;
++	range->max_frag = 2346;
++
++	range->encoding_size[0] = 5;
++	range->encoding_size[1] = 13;
++	range->num_encoding_sizes = 2;
++	range->max_encoding_tokens = NUM_DEFAULT_KEYS;
++
++	range->max_qual.qual = local->hw.max_signal;
++	range->max_qual.level = local->hw.max_rssi;
++	range->max_qual.noise = local->hw.max_noise;
++	range->max_qual.updated = local->wstats_flags;
++
++	range->avg_qual.qual = local->hw.max_signal/2;
++	range->avg_qual.level = 0;
++	range->avg_qual.noise = 0;
++	range->avg_qual.updated = local->wstats_flags;
++
++	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
++			  IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
++
++
++	for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
++		int i;
++		struct ieee80211_supported_band *sband;
++
++		sband = local->hw.wiphy->bands[band];
++
++		if (!sband)
++			continue;
++
++		for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
++			struct ieee80211_channel *chan = &sband->channels[i];
++
++			if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
++				range->freq[c].i =
++					ieee80211_frequency_to_channel(
++						chan->center_freq);
++				range->freq[c].m = chan->center_freq;
++				range->freq[c].e = 6;
++				c++;
++			}
++		}
++	}
++	range->num_channels = c;
++	range->num_frequency = c;
++
++	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
++	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
++	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
++	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
++
++	range->scan_capa |= IW_SCAN_CAPA_ESSID;
++
++	return 0;
++}
++
++
++static int ieee80211_ioctl_siwmode(struct net_device *dev,
++				   struct iw_request_info *info,
++				   __u32 *mode, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	int type;
++
++	if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
++		return -EOPNOTSUPP;
++
++	switch (*mode) {
++	case IW_MODE_INFRA:
++		type = IEEE80211_IF_TYPE_STA;
++		break;
++	case IW_MODE_ADHOC:
++		type = IEEE80211_IF_TYPE_IBSS;
++		break;
++	case IW_MODE_REPEAT:
++		type = IEEE80211_IF_TYPE_WDS;
++		break;
++	case IW_MODE_MONITOR:
++		type = IEEE80211_IF_TYPE_MNTR;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	if (type == sdata->vif.type)
++		return 0;
++	if (netif_running(dev))
++		return -EBUSY;
++
++	ieee80211_if_reinit(dev);
++	ieee80211_if_set_type(dev, type);
++
++	return 0;
++}
++
++
++static int ieee80211_ioctl_giwmode(struct net_device *dev,
++				   struct iw_request_info *info,
++				   __u32 *mode, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	switch (sdata->vif.type) {
++	case IEEE80211_IF_TYPE_AP:
++		*mode = IW_MODE_MASTER;
++		break;
++	case IEEE80211_IF_TYPE_STA:
++		*mode = IW_MODE_INFRA;
++		break;
++	case IEEE80211_IF_TYPE_IBSS:
++		*mode = IW_MODE_ADHOC;
++		break;
++	case IEEE80211_IF_TYPE_MNTR:
++		*mode = IW_MODE_MONITOR;
++		break;
++	case IEEE80211_IF_TYPE_WDS:
++		*mode = IW_MODE_REPEAT;
++		break;
++	case IEEE80211_IF_TYPE_VLAN:
++		*mode = IW_MODE_SECOND;		/* FIXME */
++		break;
++	default:
++		*mode = IW_MODE_AUTO;
++		break;
++	}
++	return 0;
++}
++
++int ieee80211_set_freq(struct ieee80211_local *local, int freqMHz)
++{
++	int ret = -EINVAL;
++	struct ieee80211_channel *chan;
++
++	chan = ieee80211_get_channel(local->hw.wiphy, freqMHz);
++
++	if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
++		local->oper_channel = chan;
++
++		if (local->sta_sw_scanning || local->sta_hw_scanning)
++			ret = 0;
++		else
++			ret = ieee80211_hw_config(local);
++
++		rate_control_clear(local);
++	}
++
++	return ret;
++}
++
++static int ieee80211_ioctl_siwfreq(struct net_device *dev,
++				   struct iw_request_info *info,
++				   struct iw_freq *freq, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
++		sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
++
++	/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
++	if (freq->e == 0) {
++		if (freq->m < 0) {
++			if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
++				sdata->u.sta.flags |=
++					IEEE80211_STA_AUTO_CHANNEL_SEL;
++			return 0;
++		} else
++			return ieee80211_set_freq(local,
++				ieee80211_channel_to_frequency(freq->m));
++	} else {
++		int i, div = 1000000;
++		for (i = 0; i < freq->e; i++)
++			div /= 10;
++		if (div > 0)
++			return ieee80211_set_freq(local, freq->m / div);
++		else
++			return -EINVAL;
++	}
++}
++
++
++static int ieee80211_ioctl_giwfreq(struct net_device *dev,
++				   struct iw_request_info *info,
++				   struct iw_freq *freq, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	freq->m = local->hw.conf.channel->center_freq;
++	freq->e = 6;
++
++	return 0;
++}
++
++
++static int ieee80211_ioctl_siwessid(struct net_device *dev,
++				    struct iw_request_info *info,
++				    struct iw_point *data, char *ssid)
++{
++	struct ieee80211_sub_if_data *sdata;
++	size_t len = data->length;
++
++	/* iwconfig uses nul termination in SSID.. */
++	if (len > 0 && ssid[len - 1] == '\0')
++		len--;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++		int ret;
++		if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
++			if (len > IEEE80211_MAX_SSID_LEN)
++				return -EINVAL;
++			memcpy(sdata->u.sta.ssid, ssid, len);
++			sdata->u.sta.ssid_len = len;
++			return 0;
++		}
++		if (data->flags)
++			sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
++		else
++			sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
++		ret = ieee80211_sta_set_ssid(dev, ssid, len);
++		if (ret)
++			return ret;
++		ieee80211_sta_req_auth(dev, &sdata->u.sta);
++		return 0;
++	}
++
++	if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++		memcpy(sdata->u.ap.ssid, ssid, len);
++		memset(sdata->u.ap.ssid + len, 0,
++		       IEEE80211_MAX_SSID_LEN - len);
++		sdata->u.ap.ssid_len = len;
++		return ieee80211_if_config(dev);
++	}
++	return -EOPNOTSUPP;
++}
++
++
++static int ieee80211_ioctl_giwessid(struct net_device *dev,
++				    struct iw_request_info *info,
++				    struct iw_point *data, char *ssid)
++{
++	size_t len;
++
++	struct ieee80211_sub_if_data *sdata;
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++		int res = ieee80211_sta_get_ssid(dev, ssid, &len);
++		if (res == 0) {
++			data->length = len;
++			data->flags = 1;
++		} else
++			data->flags = 0;
++		return res;
++	}
++
++	if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++		len = sdata->u.ap.ssid_len;
++		if (len > IW_ESSID_MAX_SIZE)
++			len = IW_ESSID_MAX_SIZE;
++		memcpy(ssid, sdata->u.ap.ssid, len);
++		data->length = len;
++		data->flags = 1;
++		return 0;
++	}
++	return -EOPNOTSUPP;
++}
++
++
++static int ieee80211_ioctl_siwap(struct net_device *dev,
++				 struct iw_request_info *info,
++				 struct sockaddr *ap_addr, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++		int ret;
++		if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
++			memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
++			       ETH_ALEN);
++			return 0;
++		}
++		if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
++			sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
++				IEEE80211_STA_AUTO_CHANNEL_SEL;
++		else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
++			sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
++		else
++			sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
++		ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
++		if (ret)
++			return ret;
++		ieee80211_sta_req_auth(dev, &sdata->u.sta);
++		return 0;
++	} else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
++		/*
++		 * If it is necessary to update the WDS peer address
++		 * while the interface is running, then we need to do
++		 * more work here, namely if it is running we need to
++		 * add a new and remove the old STA entry, this is
++		 * normally handled by _open() and _stop().
++		 */
++		if (netif_running(dev))
++			return -EBUSY;
++
++		memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
++		       ETH_ALEN);
++
++		return 0;
++	}
++
++	return -EOPNOTSUPP;
++}
++
++
++static int ieee80211_ioctl_giwap(struct net_device *dev,
++				 struct iw_request_info *info,
++				 struct sockaddr *ap_addr, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++		ap_addr->sa_family = ARPHRD_ETHER;
++		memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
++		return 0;
++	} else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
++		ap_addr->sa_family = ARPHRD_ETHER;
++		memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
++		return 0;
++	}
++
++	return -EOPNOTSUPP;
++}
++
++
++static int ieee80211_ioctl_siwscan(struct net_device *dev,
++				   struct iw_request_info *info,
++				   union iwreq_data *wrqu, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct iw_scan_req *req = NULL;
++	u8 *ssid = NULL;
++	size_t ssid_len = 0;
++
++	if (!netif_running(dev))
++		return -ENETDOWN;
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
++	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++	    sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT &&
++	    sdata->vif.type != IEEE80211_IF_TYPE_AP)
++		return -EOPNOTSUPP;
++
++	/* if SSID was specified explicitly then use that */
++	if (wrqu->data.length == sizeof(struct iw_scan_req) &&
++	    wrqu->data.flags & IW_SCAN_THIS_ESSID) {
++		req = (struct iw_scan_req *)extra;
++		ssid = req->essid;
++		ssid_len = req->essid_len;
++	}
++
++	return ieee80211_sta_req_scan(dev, ssid, ssid_len);
++}
++
++
++static int ieee80211_ioctl_giwscan(struct net_device *dev,
++				   struct iw_request_info *info,
++				   struct iw_point *data, char *extra)
++{
++	int res;
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	if (local->sta_sw_scanning || local->sta_hw_scanning)
++		return -EAGAIN;
++
++	res = ieee80211_sta_scan_results(dev, extra, data->length);
++	if (res >= 0) {
++		data->length = res;
++		return 0;
++	}
++	data->length = 0;
++	return res;
++}
++
++
++static int ieee80211_ioctl_siwrate(struct net_device *dev,
++				  struct iw_request_info *info,
++				  struct iw_param *rate, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	int i, err = -EINVAL;
++	u32 target_rate = rate->value / 100000;
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_supported_band *sband;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	if (!sdata->bss)
++		return -ENODEV;
++
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++	/* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
++	 * target_rate = X, rate->fixed = 1 means only rate X
++	 * target_rate = X, rate->fixed = 0 means all rates <= X */
++	sdata->bss->max_ratectrl_rateidx = -1;
++	sdata->bss->force_unicast_rateidx = -1;
++	if (rate->value < 0)
++		return 0;
++
++	for (i=0; i< sband->n_bitrates; i++) {
++		struct ieee80211_rate *brate = &sband->bitrates[i];
++		int this_rate = brate->bitrate;
++
++		if (target_rate == this_rate) {
++			sdata->bss->max_ratectrl_rateidx = i;
++			if (rate->fixed)
++				sdata->bss->force_unicast_rateidx = i;
++			err = 0;
++			break;
++		}
++	}
++	return err;
++}
++
++static int ieee80211_ioctl_giwrate(struct net_device *dev,
++				  struct iw_request_info *info,
++				  struct iw_param *rate, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct sta_info *sta;
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_supported_band *sband;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++		return -EOPNOTSUPP;
++
++	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++	rcu_read_lock();
++
++	sta = sta_info_get(local, sdata->u.sta.bssid);
++
++	if (sta && sta->txrate_idx < sband->n_bitrates)
++		rate->value = sband->bitrates[sta->txrate_idx].bitrate;
++	else
++		rate->value = 0;
++
++	rcu_read_unlock();
++
++	if (!sta)
++		return -ENODEV;
++
++	rate->value *= 100000;
++
++	return 0;
++}
++
++static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
++				      struct iw_request_info *info,
++				      union iwreq_data *data, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	bool need_reconfig = 0;
++	int new_power_level;
++
++	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
++		return -EINVAL;
++	if (data->txpower.flags & IW_TXPOW_RANGE)
++		return -EINVAL;
++
++	if (data->txpower.fixed) {
++		new_power_level = data->txpower.value;
++	} else {
++		/*
++		 * Automatic power level. Use maximum power for the current
++		 * channel. Should be part of rate control.
++		 */
++		struct ieee80211_channel* chan = local->hw.conf.channel;
++		if (!chan)
++			return -EINVAL;
++
++		new_power_level = chan->max_power;
++	}
++
++	if (local->hw.conf.power_level != new_power_level) {
++		local->hw.conf.power_level = new_power_level;
++		need_reconfig = 1;
++	}
++
++	if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
++		local->hw.conf.radio_enabled = !(data->txpower.disabled);
++		need_reconfig = 1;
++		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
++	}
++
++	if (need_reconfig) {
++		ieee80211_hw_config(local);
++		/* The return value of hw_config is not of big interest here,
++		 * as it doesn't say that it failed because of _this_ config
++		 * change or something else. Ignore it. */
++	}
++
++	return 0;
++}
++
++static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
++				   struct iw_request_info *info,
++				   union iwreq_data *data, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	data->txpower.fixed = 1;
++	data->txpower.disabled = !(local->hw.conf.radio_enabled);
++	data->txpower.value = local->hw.conf.power_level;
++	data->txpower.flags = IW_TXPOW_DBM;
++
++	return 0;
++}
++
++static int ieee80211_ioctl_siwrts(struct net_device *dev,
++				  struct iw_request_info *info,
++				  struct iw_param *rts, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	if (rts->disabled)
++		local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
++	else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
++		return -EINVAL;
++	else
++		local->rts_threshold = rts->value;
++
++	/* If the wlan card performs RTS/CTS in hardware/firmware,
++	 * configure it here */
++
++	if (local->ops->set_rts_threshold)
++		local->ops->set_rts_threshold(local_to_hw(local),
++					     local->rts_threshold);
++
++	return 0;
++}
++
++static int ieee80211_ioctl_giwrts(struct net_device *dev,
++				  struct iw_request_info *info,
++				  struct iw_param *rts, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	rts->value = local->rts_threshold;
++	rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
++	rts->fixed = 1;
++
++	return 0;
++}
++
++
++static int ieee80211_ioctl_siwfrag(struct net_device *dev,
++				   struct iw_request_info *info,
++				   struct iw_param *frag, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	if (frag->disabled)
++		local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
++	else if (frag->value < 256 ||
++		 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
++		return -EINVAL;
++	else {
++		/* Fragment length must be even, so strip LSB. */
++		local->fragmentation_threshold = frag->value & ~0x1;
++	}
++
++	/* If the wlan card performs fragmentation in hardware/firmware,
++	 * configure it here */
++
++	if (local->ops->set_frag_threshold)
++		local->ops->set_frag_threshold(
++			local_to_hw(local),
++			local->fragmentation_threshold);
++
++	return 0;
++}
++
++static int ieee80211_ioctl_giwfrag(struct net_device *dev,
++				   struct iw_request_info *info,
++				   struct iw_param *frag, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	frag->value = local->fragmentation_threshold;
++	frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
++	frag->fixed = 1;
++
++	return 0;
++}
++
++
++static int ieee80211_ioctl_siwretry(struct net_device *dev,
++				    struct iw_request_info *info,
++				    struct iw_param *retry, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	if (retry->disabled ||
++	    (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
++		return -EINVAL;
++
++	if (retry->flags & IW_RETRY_MAX)
++		local->long_retry_limit = retry->value;
++	else if (retry->flags & IW_RETRY_MIN)
++		local->short_retry_limit = retry->value;
++	else {
++		local->long_retry_limit = retry->value;
++		local->short_retry_limit = retry->value;
++	}
++
++	if (local->ops->set_retry_limit) {
++		return local->ops->set_retry_limit(
++			local_to_hw(local),
++			local->short_retry_limit,
++			local->long_retry_limit);
++	}
++
++	return 0;
++}
++
++
++static int ieee80211_ioctl_giwretry(struct net_device *dev,
++				    struct iw_request_info *info,
++				    struct iw_param *retry, char *extra)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++	retry->disabled = 0;
++	if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
++		/* first return min value, iwconfig will ask max value
++		 * later if needed */
++		retry->flags |= IW_RETRY_LIMIT;
++		retry->value = local->short_retry_limit;
++		if (local->long_retry_limit != local->short_retry_limit)
++			retry->flags |= IW_RETRY_MIN;
++		return 0;
++	}
++	if (retry->flags & IW_RETRY_MAX) {
++		retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
++		retry->value = local->long_retry_limit;
++	}
++
++	return 0;
++}
++
++static int ieee80211_ioctl_siwmlme(struct net_device *dev,
++				   struct iw_request_info *info,
++				   struct iw_point *data, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata;
++	struct iw_mlme *mlme = (struct iw_mlme *) extra;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
++	    sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
++		return -EINVAL;
++
++	switch (mlme->cmd) {
++	case IW_MLME_DEAUTH:
++		/* TODO: mlme->addr.sa_data */
++		return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
++	case IW_MLME_DISASSOC:
++		/* TODO: mlme->addr.sa_data */
++		return ieee80211_sta_disassociate(dev, mlme->reason_code);
++	default:
++		return -EOPNOTSUPP;
++	}
++}
++
++
++static int ieee80211_ioctl_siwencode(struct net_device *dev,
++				     struct iw_request_info *info,
++				     struct iw_point *erq, char *keybuf)
++{
++	struct ieee80211_sub_if_data *sdata;
++	int idx, i, alg = ALG_WEP;
++	u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
++	int remove = 0;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	idx = erq->flags & IW_ENCODE_INDEX;
++	if (idx == 0) {
++		if (sdata->default_key)
++			for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
++				if (sdata->default_key == sdata->keys[i]) {
++					idx = i;
++					break;
++				}
++			}
++	} else if (idx < 1 || idx > 4)
++		return -EINVAL;
++	else
++		idx--;
++
++	if (erq->flags & IW_ENCODE_DISABLED)
++		remove = 1;
++	else if (erq->length == 0) {
++		/* No key data - just set the default TX key index */
++		ieee80211_set_default_key(sdata, idx);
++		return 0;
++	}
++
++	return ieee80211_set_encryption(
++		dev, bcaddr,
++		idx, alg, remove,
++		!sdata->default_key,
++		keybuf, erq->length);
++}
++
++
++static int ieee80211_ioctl_giwencode(struct net_device *dev,
++				     struct iw_request_info *info,
++				     struct iw_point *erq, char *key)
++{
++	struct ieee80211_sub_if_data *sdata;
++	int idx, i;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++	idx = erq->flags & IW_ENCODE_INDEX;
++	if (idx < 1 || idx > 4) {
++		idx = -1;
++		if (!sdata->default_key)
++			idx = 0;
++		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
++			if (sdata->default_key == sdata->keys[i]) {
++				idx = i;
++				break;
++			}
++		}
++		if (idx < 0)
++			return -EINVAL;
++	} else
++		idx--;
++
++	erq->flags = idx + 1;
++
++	if (!sdata->keys[idx]) {
++		erq->length = 0;
++		erq->flags |= IW_ENCODE_DISABLED;
++		return 0;
++	}
++
++	memcpy(key, sdata->keys[idx]->conf.key,
++	       min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
++	erq->length = sdata->keys[idx]->conf.keylen;
++	erq->flags |= IW_ENCODE_ENABLED;
++
++	return 0;
++}
++
++static int ieee80211_ioctl_siwauth(struct net_device *dev,
++				   struct iw_request_info *info,
++				   struct iw_param *data, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	int ret = 0;
++
++	switch (data->flags & IW_AUTH_INDEX) {
++	case IW_AUTH_WPA_VERSION:
++	case IW_AUTH_CIPHER_PAIRWISE:
++	case IW_AUTH_CIPHER_GROUP:
++	case IW_AUTH_WPA_ENABLED:
++	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
++	case IW_AUTH_KEY_MGMT:
++		break;
++	case IW_AUTH_DROP_UNENCRYPTED:
++		sdata->drop_unencrypted = !!data->value;
++		break;
++	case IW_AUTH_PRIVACY_INVOKED:
++		if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++			ret = -EINVAL;
++		else {
++			sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
++			/*
++			 * Privacy invoked by wpa_supplicant, store the
++			 * value and allow associating to a protected
++			 * network without having a key up front.
++			 */
++			if (data->value)
++				sdata->u.sta.flags |=
++					IEEE80211_STA_PRIVACY_INVOKED;
++		}
++		break;
++	case IW_AUTH_80211_AUTH_ALG:
++		if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++		    sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
++			sdata->u.sta.auth_algs = data->value;
++		else
++			ret = -EOPNOTSUPP;
++		break;
++	default:
++		ret = -EOPNOTSUPP;
++		break;
++	}
++	return ret;
++}
++
++/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
++static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
++{
++	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++	struct iw_statistics *wstats = &local->wstats;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct sta_info *sta = NULL;
++
++	rcu_read_lock();
++
++	if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++	    sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
++		sta = sta_info_get(local, sdata->u.sta.bssid);
++	if (!sta) {
++		wstats->discard.fragment = 0;
++		wstats->discard.misc = 0;
++		wstats->qual.qual = 0;
++		wstats->qual.level = 0;
++		wstats->qual.noise = 0;
++		wstats->qual.updated = IW_QUAL_ALL_INVALID;
++	} else {
++		wstats->qual.level = sta->last_rssi;
++		wstats->qual.qual = sta->last_signal;
++		wstats->qual.noise = sta->last_noise;
++		wstats->qual.updated = local->wstats_flags;
++	}
++
++	rcu_read_unlock();
++
++	return wstats;
++}
++
++static int ieee80211_ioctl_giwauth(struct net_device *dev,
++				   struct iw_request_info *info,
++				   struct iw_param *data, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	int ret = 0;
++
++	switch (data->flags & IW_AUTH_INDEX) {
++	case IW_AUTH_80211_AUTH_ALG:
++		if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++		    sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
++			data->value = sdata->u.sta.auth_algs;
++		else
++			ret = -EOPNOTSUPP;
++		break;
++	default:
++		ret = -EOPNOTSUPP;
++		break;
++	}
++	return ret;
++}
++
++
++static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
++					struct iw_request_info *info,
++					struct iw_point *erq, char *extra)
++{
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
++	int uninitialized_var(alg), idx, i, remove = 0;
++
++	switch (ext->alg) {
++	case IW_ENCODE_ALG_NONE:
++		remove = 1;
++		break;
++	case IW_ENCODE_ALG_WEP:
++		alg = ALG_WEP;
++		break;
++	case IW_ENCODE_ALG_TKIP:
++		alg = ALG_TKIP;
++		break;
++	case IW_ENCODE_ALG_CCMP:
++		alg = ALG_CCMP;
++		break;
++	default:
++		return -EOPNOTSUPP;
++	}
++
++	if (erq->flags & IW_ENCODE_DISABLED)
++		remove = 1;
++
++	idx = erq->flags & IW_ENCODE_INDEX;
++	if (idx < 1 || idx > 4) {
++		idx = -1;
++		if (!sdata->default_key)
++			idx = 0;
++		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
++			if (sdata->default_key == sdata->keys[i]) {
++				idx = i;
++				break;
++			}
++		}
++		if (idx < 0)
++			return -EINVAL;
++	} else
++		idx--;
++
++	return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
++					remove,
++					ext->ext_flags &
++					IW_ENCODE_EXT_SET_TX_KEY,
++					ext->key, ext->key_len);
++}
++
++
++/* Structures to export the Wireless Handlers */
++
++static const iw_handler ieee80211_handler[] =
++{
++	(iw_handler) NULL,				/* SIOCSIWCOMMIT */
++	(iw_handler) ieee80211_ioctl_giwname,		/* SIOCGIWNAME */
++	(iw_handler) NULL,				/* SIOCSIWNWID */
++	(iw_handler) NULL,				/* SIOCGIWNWID */
++	(iw_handler) ieee80211_ioctl_siwfreq,		/* SIOCSIWFREQ */
++	(iw_handler) ieee80211_ioctl_giwfreq,		/* SIOCGIWFREQ */
++	(iw_handler) ieee80211_ioctl_siwmode,		/* SIOCSIWMODE */
++	(iw_handler) ieee80211_ioctl_giwmode,		/* SIOCGIWMODE */
++	(iw_handler) NULL,				/* SIOCSIWSENS */
++	(iw_handler) NULL,				/* SIOCGIWSENS */
++	(iw_handler) NULL /* not used */,		/* SIOCSIWRANGE */
++	(iw_handler) ieee80211_ioctl_giwrange,		/* SIOCGIWRANGE */
++	(iw_handler) NULL /* not used */,		/* SIOCSIWPRIV */
++	(iw_handler) NULL /* kernel code */,		/* SIOCGIWPRIV */
++	(iw_handler) NULL /* not used */,		/* SIOCSIWSTATS */
++	(iw_handler) NULL /* kernel code */,		/* SIOCGIWSTATS */
++	(iw_handler) NULL,				/* SIOCSIWSPY */
++	(iw_handler) NULL,				/* SIOCGIWSPY */
++	(iw_handler) NULL,				/* SIOCSIWTHRSPY */
++	(iw_handler) NULL,				/* SIOCGIWTHRSPY */
++	(iw_handler) ieee80211_ioctl_siwap,		/* SIOCSIWAP */
++	(iw_handler) ieee80211_ioctl_giwap,		/* SIOCGIWAP */
++	(iw_handler) ieee80211_ioctl_siwmlme,		/* SIOCSIWMLME */
++	(iw_handler) NULL,				/* SIOCGIWAPLIST */
++	(iw_handler) ieee80211_ioctl_siwscan,		/* SIOCSIWSCAN */
++	(iw_handler) ieee80211_ioctl_giwscan,		/* SIOCGIWSCAN */
++	(iw_handler) ieee80211_ioctl_siwessid,		/* SIOCSIWESSID */
++	(iw_handler) ieee80211_ioctl_giwessid,		/* SIOCGIWESSID */
++	(iw_handler) NULL,				/* SIOCSIWNICKN */
++	(iw_handler) NULL,				/* SIOCGIWNICKN */
++	(iw_handler) NULL,				/* -- hole -- */
++	(iw_handler) NULL,				/* -- hole -- */
++	(iw_handler) ieee80211_ioctl_siwrate,		/* SIOCSIWRATE */
++	(iw_handler) ieee80211_ioctl_giwrate,		/* SIOCGIWRATE */
++	(iw_handler) ieee80211_ioctl_siwrts,		/* SIOCSIWRTS */
++	(iw_handler) ieee80211_ioctl_giwrts,		/* SIOCGIWRTS */
++	(iw_handler) ieee80211_ioctl_siwfrag,		/* SIOCSIWFRAG */
++	(iw_handler) ieee80211_ioctl_giwfrag,		/* SIOCGIWFRAG */
++	(iw_handler) ieee80211_ioctl_siwtxpower,	/* SIOCSIWTXPOW */
++	(iw_handler) ieee80211_ioctl_giwtxpower,	/* SIOCGIWTXPOW */
++	(iw_handler) ieee80211_ioctl_siwretry,		/* SIOCSIWRETRY */
++	(iw_handler) ieee80211_ioctl_giwretry,		/* SIOCGIWRETRY */
++	(iw_handler) ieee80211_ioctl_siwencode,		/* SIOCSIWENCODE */
++	(iw_handler) ieee80211_ioctl_giwencode,		/* SIOCGIWENCODE */
++	(iw_handler) NULL,				/* SIOCSIWPOWER */
++	(iw_handler) NULL,				/* SIOCGIWPOWER */
++	(iw_handler) NULL,				/* -- hole -- */
++	(iw_handler) NULL,				/* -- hole -- */
++	(iw_handler) ieee80211_ioctl_siwgenie,		/* SIOCSIWGENIE */
++	(iw_handler) NULL,				/* SIOCGIWGENIE */
++	(iw_handler) ieee80211_ioctl_siwauth,		/* SIOCSIWAUTH */
++	(iw_handler) ieee80211_ioctl_giwauth,		/* SIOCGIWAUTH */
++	(iw_handler) ieee80211_ioctl_siwencodeext,	/* SIOCSIWENCODEEXT */
++	(iw_handler) NULL,				/* SIOCGIWENCODEEXT */
++	(iw_handler) NULL,				/* SIOCSIWPMKSA */
++	(iw_handler) NULL,				/* -- hole -- */
++};
++
++const struct iw_handler_def ieee80211_iw_handler_def =
++{
++	.num_standard	= ARRAY_SIZE(ieee80211_handler),
++	.standard	= (iw_handler *) ieee80211_handler,
++	.get_wireless_stats = ieee80211_get_wireless_stats,
++};
+diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
+index 4e23659..64faa3d 100644
+--- a/net/mac80211/wme.c
++++ b/net/mac80211/wme.c
+@@ -19,10 +19,13 @@
+ #include "wme.h"
+ 
+ /* maximum number of hardware queues we support. */
+-#define TC_80211_MAX_QUEUES 8
++#define TC_80211_MAX_QUEUES 16
++
++const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+ 
+ struct ieee80211_sched_data
+ {
++	unsigned long qdisc_pool[BITS_TO_LONGS(TC_80211_MAX_QUEUES)];
+ 	struct tcf_proto *filter_list;
+ 	struct Qdisc *queues[TC_80211_MAX_QUEUES];
+ 	struct sk_buff_head requeued[TC_80211_MAX_QUEUES];
+@@ -98,7 +101,6 @@ static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ 	unsigned short fc = le16_to_cpu(hdr->frame_control);
+ 	int qos;
+-	const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+ 
+ 	/* see if frame is data or non data frame */
+ 	if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) {
+@@ -146,9 +148,26 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
+ 	unsigned short fc = le16_to_cpu(hdr->frame_control);
+ 	struct Qdisc *qdisc;
+ 	int err, queue;
++	struct sta_info *sta;
++	u8 tid;
+ 
+ 	if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) {
+-		skb_queue_tail(&q->requeued[pkt_data->queue], skb);
++		queue = pkt_data->queue;
++		rcu_read_lock();
++		sta = sta_info_get(local, hdr->addr1);
++		tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
++		if (sta) {
++			int ampdu_queue = sta->tid_to_tx_q[tid];
++			if ((ampdu_queue < local->hw.queues) &&
++			    test_bit(ampdu_queue, q->qdisc_pool)) {
++				queue = ampdu_queue;
++				pkt_data->flags |= IEEE80211_TXPD_AMPDU;
++			} else {
++				pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
++			}
++		}
++		rcu_read_unlock();
++		skb_queue_tail(&q->requeued[queue], skb);
+ 		qd->q.qlen++;
+ 		return 0;
+ 	}
+@@ -159,14 +178,31 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
+ 	 */
+ 	if (WLAN_FC_IS_QOS_DATA(fc)) {
+ 		u8 *p = skb->data + ieee80211_get_hdrlen(fc) - 2;
+-		u8 qos_hdr = skb->priority & QOS_CONTROL_TAG1D_MASK;
++		u8 ack_policy = 0;
++		tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
+ 		if (local->wifi_wme_noack_test)
+-			qos_hdr |= QOS_CONTROL_ACK_POLICY_NOACK <<
++			ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
+ 					QOS_CONTROL_ACK_POLICY_SHIFT;
+ 		/* qos header is 2 bytes, second reserved */
+-		*p = qos_hdr;
++		*p = ack_policy | tid;
+ 		p++;
+ 		*p = 0;
++
++		rcu_read_lock();
++
++		sta = sta_info_get(local, hdr->addr1);
++		if (sta) {
++			int ampdu_queue = sta->tid_to_tx_q[tid];
++			if ((ampdu_queue < local->hw.queues) &&
++				test_bit(ampdu_queue, q->qdisc_pool)) {
++				queue = ampdu_queue;
++				pkt_data->flags |= IEEE80211_TXPD_AMPDU;
++			} else {
++				pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
++			}
++		}
++
++		rcu_read_unlock();
+ 	}
+ 
+ 	if (unlikely(queue >= local->hw.queues)) {
+@@ -184,6 +220,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
+ 			kfree_skb(skb);
+ 			err = NET_XMIT_DROP;
+ 	} else {
++		tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
+ 		pkt_data->queue = (unsigned int) queue;
+ 		qdisc = q->queues[queue];
+ 		err = qdisc->enqueue(skb, qdisc);
+@@ -235,10 +272,11 @@ static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd)
+ 	/* check all the h/w queues in numeric/priority order */
+ 	for (queue = 0; queue < hw->queues; queue++) {
+ 		/* see if there is room in this hardware queue */
+-		if (test_bit(IEEE80211_LINK_STATE_XOFF,
+-			     &local->state[queue]) ||
+-		    test_bit(IEEE80211_LINK_STATE_PENDING,
+-			     &local->state[queue]))
++		if ((test_bit(IEEE80211_LINK_STATE_XOFF,
++				&local->state[queue])) ||
++		    (test_bit(IEEE80211_LINK_STATE_PENDING,
++				&local->state[queue])) ||
++			 (!test_bit(queue, q->qdisc_pool)))
+ 			continue;
+ 
+ 		/* there is space - try and get a frame */
+@@ -360,6 +398,10 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt)
+ 		}
+ 	}
+ 
++	/* reserve all legacy QoS queues */
++	for (i = 0; i < min(IEEE80211_TX_QUEUE_DATA4, queues); i++)
++		set_bit(i, q->qdisc_pool);
++
+ 	return err;
+ }
+ 
+@@ -605,3 +647,80 @@ void ieee80211_wme_unregister(void)
+ {
+ 	unregister_qdisc(&wme_qdisc_ops);
+ }
++
++int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
++			struct sta_info *sta, u16 tid)
++{
++	int i;
++	struct ieee80211_sched_data *q =
++			qdisc_priv(local->mdev->qdisc_sleeping);
++	DECLARE_MAC_BUF(mac);
++
++	/* prepare the filter and save it for the SW queue
++	 * matching the recieved HW queue */
++
++	/* try to get a Qdisc from the pool */
++	for (i = IEEE80211_TX_QUEUE_BEACON; i < local->hw.queues; i++)
++		if (!test_and_set_bit(i, q->qdisc_pool)) {
++			ieee80211_stop_queue(local_to_hw(local), i);
++			sta->tid_to_tx_q[tid] = i;
++
++			/* IF there are already pending packets
++			 * on this tid first we need to drain them
++			 * on the previous queue
++			 * since HT is strict in order */
++#ifdef CONFIG_MAC80211_HT_DEBUG
++			if (net_ratelimit())
++				printk(KERN_DEBUG "allocated aggregation queue"
++					" %d tid %d addr %s pool=0x%lX",
++					i, tid, print_mac(mac, sta->addr),
++					q->qdisc_pool[0]);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++			return 0;
++		}
++
++	return -EAGAIN;
++}
++
++/**
++ * the caller needs to hold local->mdev->queue_lock
++ */
++void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
++				   struct sta_info *sta, u16 tid,
++				   u8 requeue)
++{
++	struct ieee80211_sched_data *q =
++		qdisc_priv(local->mdev->qdisc_sleeping);
++	int agg_queue = sta->tid_to_tx_q[tid];
++
++	/* return the qdisc to the pool */
++	clear_bit(agg_queue, q->qdisc_pool);
++	sta->tid_to_tx_q[tid] = local->hw.queues;
++
++	if (requeue)
++		ieee80211_requeue(local, agg_queue);
++	else
++		q->queues[agg_queue]->ops->reset(q->queues[agg_queue]);
++}
++
++void ieee80211_requeue(struct ieee80211_local *local, int queue)
++{
++	struct Qdisc *root_qd = local->mdev->qdisc_sleeping;
++	struct ieee80211_sched_data *q = qdisc_priv(root_qd);
++	struct Qdisc *qdisc = q->queues[queue];
++	struct sk_buff *skb = NULL;
++	u32 len;
++
++	if (!qdisc || !qdisc->dequeue)
++		return;
++
++	printk(KERN_DEBUG "requeue: qlen = %d\n", qdisc->q.qlen);
++	for (len = qdisc->q.qlen; len > 0; len--) {
++		skb = qdisc->dequeue(qdisc);
++		root_qd->q.qlen--;
++		/* packet will be classified again and */
++		/* skb->packet_data->queue will be overridden if needed */
++		if (skb)
++			wme_qdiscop_enqueue(skb, root_qd);
++	}
++}
+diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
+index 76c713a..fcc6b05 100644
+--- a/net/mac80211/wme.h
++++ b/net/mac80211/wme.h
+@@ -24,6 +24,8 @@
+ 
+ #define QOS_CONTROL_TAG1D_MASK 0x07
+ 
++extern const int ieee802_1d_to_ac[8];
++
+ static inline int WLAN_FC_IS_QOS_DATA(u16 fc)
+ {
+ 	return (fc & 0x8C) == 0x88;
+@@ -32,7 +34,12 @@ static inline int WLAN_FC_IS_QOS_DATA(u16 fc)
+ #ifdef CONFIG_NET_SCHED
+ void ieee80211_install_qdisc(struct net_device *dev);
+ int ieee80211_qdisc_installed(struct net_device *dev);
+-
++int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
++			       struct sta_info *sta, u16 tid);
++void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
++				   struct sta_info *sta, u16 tid,
++				   u8 requeue);
++void ieee80211_requeue(struct ieee80211_local *local, int queue);
+ int ieee80211_wme_register(void);
+ void ieee80211_wme_unregister(void);
+ #else
+@@ -43,7 +50,19 @@ static inline int ieee80211_qdisc_installed(struct net_device *dev)
+ {
+ 	return 0;
+ }
+-
++static inline int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
++					     struct sta_info *sta, u16 tid)
++{
++	return -EAGAIN;
++}
++static inline void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
++						 struct sta_info *sta, u16 tid,
++						 u8 requeue)
++{
++}
++static inline void ieee80211_requeue(struct ieee80211_local *local, int queue)
++{
++}
+ static inline int ieee80211_wme_register(void)
+ {
+ 	return 0;
+diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
+index 6f04311..45709ad 100644
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -70,8 +70,8 @@ static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da,
+ }
+ 
+ 
+-ieee80211_txrx_result
+-ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
++ieee80211_tx_result
++ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
+ {
+ 	u8 *data, *sa, *da, *key, *mic, qos_tid;
+ 	size_t data_len;
+@@ -84,18 +84,18 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
+ 
+ 	if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 ||
+ 	    !WLAN_FC_DATA_PRESENT(fc))
+-		return TXRX_CONTINUE;
++		return TX_CONTINUE;
+ 
+ 	if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len))
+-		return TXRX_DROP;
++		return TX_DROP;
+ 
+ 	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
+-	    !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) &&
++	    !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
+ 	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
+ 	    !wpa_test) {
+ 		/* hwaccel - with no need for preallocated room for Michael MIC
+ 		 */
+-		return TXRX_CONTINUE;
++		return TX_CONTINUE;
+ 	}
+ 
+ 	if (skb_tailroom(skb) < MICHAEL_MIC_LEN) {
+@@ -105,7 +105,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
+ 					      GFP_ATOMIC))) {
+ 			printk(KERN_DEBUG "%s: failed to allocate more memory "
+ 			       "for Michael MIC\n", tx->dev->name);
+-			return TXRX_DROP;
++			return TX_DROP;
+ 		}
+ 	}
+ 
+@@ -119,12 +119,12 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
+ 	mic = skb_put(skb, MICHAEL_MIC_LEN);
+ 	michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+ 
+-ieee80211_txrx_result
+-ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
++ieee80211_rx_result
++ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
+ {
+ 	u8 *data, *sa, *da, *key = NULL, qos_tid;
+ 	size_t data_len;
+@@ -139,16 +139,16 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
+ 	/*
+ 	 * No way to verify the MIC if the hardware stripped it
+ 	 */
+-	if (rx->u.rx.status->flag & RX_FLAG_MMIC_STRIPPED)
+-		return TXRX_CONTINUE;
++	if (rx->status->flag & RX_FLAG_MMIC_STRIPPED)
++		return RX_CONTINUE;
+ 
+ 	if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
+ 	    !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc))
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+ 	if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)
+ 	    || data_len < MICHAEL_MIC_LEN)
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 
+ 	data_len -= MICHAEL_MIC_LEN;
+ 
+@@ -161,29 +161,29 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
+ 				 ALG_TKIP_TEMP_AUTH_TX_MIC_KEY];
+ 	michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+ 	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
+-		if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+-			return TXRX_DROP;
++		if (!(rx->flags & IEEE80211_RX_RA_MATCH))
++			return RX_DROP_UNUSABLE;
+ 
+ 		printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from "
+ 		       "%s\n", rx->dev->name, print_mac(mac, sa));
+ 
+ 		mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx,
+ 						(void *) skb->data);
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 	}
+ 
+ 	/* remove Michael MIC from payload */
+ 	skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
+ 
+ 	/* update IV in key information to be able to detect replays */
+-	rx->key->u.tkip.iv32_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv32;
+-	rx->key->u.tkip.iv16_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv16;
++	rx->key->u.tkip.iv32_rx[rx->queue] = rx->tkip_iv32;
++	rx->key->u.tkip.iv16_rx[rx->queue] = rx->tkip_iv16;
+ 
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
+ }
+ 
+ 
+-static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
++static int tkip_encrypt_skb(struct ieee80211_tx_data *tx,
+ 			    struct sk_buff *skb, int test)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+@@ -228,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
+ 					    0x7f),
+ 				      (u8) key->u.tkip.iv16);
+ 
+-		tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
++		tx->control->key_idx = tx->key->conf.hw_key_idx;
+ 		return 0;
+ 	}
+ 
+@@ -242,42 +242,42 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
+ }
+ 
+ 
+-ieee80211_txrx_result
+-ieee80211_crypto_tkip_encrypt(struct ieee80211_txrx_data *tx)
++ieee80211_tx_result
++ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
+ {
+ 	struct sk_buff *skb = tx->skb;
+ 	int wpa_test = 0, test = 0;
+ 
+-	tx->u.tx.control->icv_len = TKIP_ICV_LEN;
+-	tx->u.tx.control->iv_len = TKIP_IV_LEN;
+-	ieee80211_tx_set_iswep(tx);
++	tx->control->icv_len = TKIP_ICV_LEN;
++	tx->control->iv_len = TKIP_IV_LEN;
++	ieee80211_tx_set_protected(tx);
+ 
+ 	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
+ 	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+ 	    !wpa_test) {
+ 		/* hwaccel - with no need for preallocated room for IV/ICV */
+-		tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
+-		return TXRX_CONTINUE;
++		tx->control->key_idx = tx->key->conf.hw_key_idx;
++		return TX_CONTINUE;
+ 	}
+ 
+ 	if (tkip_encrypt_skb(tx, skb, test) < 0)
+-		return TXRX_DROP;
++		return TX_DROP;
+ 
+-	if (tx->u.tx.extra_frag) {
++	if (tx->extra_frag) {
+ 		int i;
+-		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+-			if (tkip_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
++		for (i = 0; i < tx->num_extra_frag; i++) {
++			if (tkip_encrypt_skb(tx, tx->extra_frag[i], test)
+ 			    < 0)
+-				return TXRX_DROP;
++				return TX_DROP;
+ 		}
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+ 
+-ieee80211_txrx_result
+-ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
++ieee80211_rx_result
++ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ 	u16 fc;
+@@ -290,19 +290,19 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
+ 	hdrlen = ieee80211_get_hdrlen(fc);
+ 
+ 	if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+ 	if (!rx->sta || skb->len - hdrlen < 12)
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 
+-	if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED) {
+-		if (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) {
++	if (rx->status->flag & RX_FLAG_DECRYPTED) {
++		if (rx->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 TXRX_CONTINUE;
++			return RX_CONTINUE;
+ 		}
+ 
+ 		/* let TKIP code verify IV, but skip decryption */
+@@ -312,9 +312,9 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
+ 	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
+ 					  key, skb->data + hdrlen,
+ 					  skb->len - hdrlen, rx->sta->addr,
+-					  hwaccel, rx->u.rx.queue,
+-					  &rx->u.rx.tkip_iv32,
+-					  &rx->u.rx.tkip_iv16);
++					  hdr->addr1, hwaccel, rx->queue,
++					  &rx->tkip_iv32,
++					  &rx->tkip_iv16);
+ 	if (res != TKIP_DECRYPT_OK || wpa_test) {
+ #ifdef CONFIG_MAC80211_DEBUG
+ 		if (net_ratelimit())
+@@ -322,7 +322,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
+ 			       "frame from %s (res=%d)\n", rx->dev->name,
+ 			       print_mac(mac, rx->sta->addr), res);
+ #endif /* CONFIG_MAC80211_DEBUG */
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 	}
+ 
+ 	/* Trim ICV */
+@@ -332,7 +332,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
+ 	memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
+ 	skb_pull(skb, TKIP_IV_LEN);
+ 
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
+ }
+ 
+ 
+@@ -429,7 +429,7 @@ static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr)
+ }
+ 
+ 
+-static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
++static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx,
+ 			    struct sk_buff *skb, int test)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+@@ -478,7 +478,7 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
+ 
+ 	if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+ 		/* hwaccel - with preallocated room for CCMP header */
+-		tx->u.tx.control->key_idx = key->conf.hw_key_idx;
++		tx->control->key_idx = key->conf.hw_key_idx;
+ 		return 0;
+ 	}
+ 
+@@ -491,42 +491,42 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
+ }
+ 
+ 
+-ieee80211_txrx_result
+-ieee80211_crypto_ccmp_encrypt(struct ieee80211_txrx_data *tx)
++ieee80211_tx_result
++ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
+ {
+ 	struct sk_buff *skb = tx->skb;
+ 	int test = 0;
+ 
+-	tx->u.tx.control->icv_len = CCMP_MIC_LEN;
+-	tx->u.tx.control->iv_len = CCMP_HDR_LEN;
+-	ieee80211_tx_set_iswep(tx);
++	tx->control->icv_len = CCMP_MIC_LEN;
++	tx->control->iv_len = CCMP_HDR_LEN;
++	ieee80211_tx_set_protected(tx);
+ 
+ 	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
+ 	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
+ 		/* hwaccel - with no need for preallocated room for CCMP "
+ 		 * header or MIC fields */
+-		tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
+-		return TXRX_CONTINUE;
++		tx->control->key_idx = tx->key->conf.hw_key_idx;
++		return TX_CONTINUE;
+ 	}
+ 
+ 	if (ccmp_encrypt_skb(tx, skb, test) < 0)
+-		return TXRX_DROP;
++		return TX_DROP;
+ 
+-	if (tx->u.tx.extra_frag) {
++	if (tx->extra_frag) {
+ 		int i;
+-		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+-			if (ccmp_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
++		for (i = 0; i < tx->num_extra_frag; i++) {
++			if (ccmp_encrypt_skb(tx, tx->extra_frag[i], test)
+ 			    < 0)
+-				return TXRX_DROP;
++				return TX_DROP;
+ 		}
+ 	}
+ 
+-	return TXRX_CONTINUE;
++	return TX_CONTINUE;
+ }
+ 
+ 
+-ieee80211_txrx_result
+-ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
++ieee80211_rx_result
++ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ 	u16 fc;
+@@ -541,21 +541,21 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
+ 	hdrlen = ieee80211_get_hdrlen(fc);
+ 
+ 	if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+-		return TXRX_CONTINUE;
++		return RX_CONTINUE;
+ 
+ 	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
+ 	if (!rx->sta || data_len < 0)
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 
+-	if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+-	    (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
+-		return TXRX_CONTINUE;
++	if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
++	    (rx->status->flag & RX_FLAG_IV_STRIPPED))
++		return RX_CONTINUE;
+ 
+ 	(void) ccmp_hdr2pn(pn, skb->data + hdrlen);
+ 
+-	if (memcmp(pn, key->u.ccmp.rx_pn[rx->u.rx.queue], CCMP_PN_LEN) <= 0) {
++	if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
+ #ifdef CONFIG_MAC80211_DEBUG
+-		u8 *ppn = key->u.ccmp.rx_pn[rx->u.rx.queue];
++		u8 *ppn = key->u.ccmp.rx_pn[rx->queue];
+ 
+ 		printk(KERN_DEBUG "%s: CCMP replay detected for RX frame from "
+ 		       "%s (RX PN %02x%02x%02x%02x%02x%02x <= prev. PN "
+@@ -565,10 +565,10 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
+ 		       ppn[0], ppn[1], ppn[2], ppn[3], ppn[4], ppn[5]);
+ #endif /* CONFIG_MAC80211_DEBUG */
+ 		key->u.ccmp.replays++;
+-		return TXRX_DROP;
++		return RX_DROP_UNUSABLE;
+ 	}
+ 
+-	if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
++	if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
+ 		/* hardware didn't decrypt/verify MIC */
+ 		u8 *scratch, *b_0, *aad;
+ 
+@@ -589,16 +589,16 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
+ 				       "for RX frame from %s\n", rx->dev->name,
+ 				       print_mac(mac, rx->sta->addr));
+ #endif /* CONFIG_MAC80211_DEBUG */
+-			return TXRX_DROP;
++			return RX_DROP_UNUSABLE;
+ 		}
+ 	}
+ 
+-	memcpy(key->u.ccmp.rx_pn[rx->u.rx.queue], pn, CCMP_PN_LEN);
++	memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN);
+ 
+ 	/* Remove CCMP header and MIC */
+ 	skb_trim(skb, skb->len - CCMP_MIC_LEN);
+ 	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
+ 	skb_pull(skb, CCMP_HDR_LEN);
+ 
+-	return TXRX_CONTINUE;
++	return RX_CONTINUE;
+ }
+diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h
+index 49d80cf..d42d221 100644
+--- a/net/mac80211/wpa.h
++++ b/net/mac80211/wpa.h
+@@ -13,19 +13,19 @@
+ #include <linux/types.h>
+ #include "ieee80211_i.h"
+ 
+-ieee80211_txrx_result
+-ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx);
+-ieee80211_txrx_result
+-ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx);
++ieee80211_tx_result
++ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx);
++ieee80211_rx_result
++ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx);
+ 
+-ieee80211_txrx_result
+-ieee80211_crypto_tkip_encrypt(struct ieee80211_txrx_data *tx);
+-ieee80211_txrx_result
+-ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx);
++ieee80211_tx_result
++ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx);
++ieee80211_rx_result
++ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx);
+ 
+-ieee80211_txrx_result
+-ieee80211_crypto_ccmp_encrypt(struct ieee80211_txrx_data *tx);
+-ieee80211_txrx_result
+-ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx);
++ieee80211_tx_result
++ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx);
++ieee80211_rx_result
++ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx);
+ 
+ #endif /* WPA_H */
+diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
+index daf5b88..c1fc0f1 100644
+--- a/net/netfilter/Kconfig
++++ b/net/netfilter/Kconfig
+@@ -86,6 +86,16 @@ config NF_CONNTRACK_EVENTS
+ 
+ 	  If unsure, say `N'.
+ 
++config NF_CT_PROTO_DCCP
++	tristate 'DCCP protocol connection tracking support (EXPERIMENTAL)'
++	depends on EXPERIMENTAL && NF_CONNTRACK
++	depends on NETFILTER_ADVANCED
++	help
++	  With this option enabled, the layer 3 independent connection
++	  tracking code will be able to do state tracking on DCCP connections.
++
++	  If unsure, say 'N'.
++
+ config NF_CT_PROTO_GRE
+ 	tristate
+ 	depends on NF_CONNTRACK
+diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
+index ea75083..5c4b183 100644
+--- a/net/netfilter/Makefile
++++ b/net/netfilter/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
+ obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
+ 
+ # SCTP protocol connection tracking
++obj-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o
+ obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
+ obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
+ obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
+diff --git a/net/netfilter/core.c b/net/netfilter/core.c
+index c4065b8..292fa28 100644
+--- a/net/netfilter/core.c
++++ b/net/netfilter/core.c
+@@ -165,6 +165,14 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
+ 	unsigned int verdict;
+ 	int ret = 0;
+ 
++#ifdef CONFIG_NET_NS
++	struct net *net;
++
++	net = indev == NULL ? dev_net(outdev) : dev_net(indev);
++	if (net != &init_net)
++		return 1;
++#endif
++
+ 	/* We may already have this, but read-locks nest anyway */
+ 	rcu_read_lock();
+ 
+diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
+index 7b8239c..38aedee 100644
+--- a/net/netfilter/nf_conntrack_amanda.c
++++ b/net/netfilter/nf_conntrack_amanda.c
+@@ -53,7 +53,7 @@ enum amanda_strings {
+ };
+ 
+ static struct {
+-	char			*string;
++	const char		*string;
+ 	size_t			len;
+ 	struct ts_config	*ts;
+ } search[] __read_mostly = {
+@@ -91,7 +91,6 @@ static int amanda_help(struct sk_buff *skb,
+ 	char pbuf[sizeof("65535")], *tmp;
+ 	u_int16_t len;
+ 	__be16 port;
+-	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ 	int ret = NF_ACCEPT;
+ 	typeof(nf_nat_amanda_hook) nf_nat_amanda;
+ 
+@@ -148,7 +147,9 @@ static int amanda_help(struct sk_buff *skb,
+ 			goto out;
+ 		}
+ 		tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+-		nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
++		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
++				  nf_ct_l3num(ct),
++				  &tuple->src.u3, &tuple->dst.u3,
+ 				  IPPROTO_TCP, NULL, &port);
+ 
+ 		nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
+@@ -164,26 +165,29 @@ out:
+ 	return ret;
+ }
+ 
++static const struct nf_conntrack_expect_policy amanda_exp_policy = {
++	.max_expected		= 3,
++	.timeout		= 180,
++};
++
+ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
+ 	{
+ 		.name			= "amanda",
+-		.max_expected		= 3,
+-		.timeout		= 180,
+ 		.me			= THIS_MODULE,
+ 		.help			= amanda_help,
+ 		.tuple.src.l3num	= AF_INET,
+ 		.tuple.src.u.udp.port	= __constant_htons(10080),
+ 		.tuple.dst.protonum	= IPPROTO_UDP,
++		.expect_policy		= &amanda_exp_policy,
+ 	},
+ 	{
+ 		.name			= "amanda",
+-		.max_expected		= 3,
+-		.timeout		= 180,
+ 		.me			= THIS_MODULE,
+ 		.help			= amanda_help,
+ 		.tuple.src.l3num	= AF_INET6,
+ 		.tuple.src.u.udp.port	= __constant_htons(10080),
+ 		.tuple.dst.protonum	= IPPROTO_UDP,
++		.expect_policy		= &amanda_exp_policy,
+ 	},
+ };
+ 
+diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
+index b77eb56..4eac65c 100644
+--- a/net/netfilter/nf_conntrack_core.c
++++ b/net/netfilter/nf_conntrack_core.c
+@@ -94,7 +94,7 @@ static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)
+ 				nf_conntrack_hash_rnd);
+ }
+ 
+-int
++bool
+ nf_ct_get_tuple(const struct sk_buff *skb,
+ 		unsigned int nhoff,
+ 		unsigned int dataoff,
+@@ -108,7 +108,7 @@ nf_ct_get_tuple(const struct sk_buff *skb,
+ 
+ 	tuple->src.l3num = l3num;
+ 	if (l3proto->pkt_to_tuple(skb, nhoff, tuple) == 0)
+-		return 0;
++		return false;
+ 
+ 	tuple->dst.protonum = protonum;
+ 	tuple->dst.dir = IP_CT_DIR_ORIGINAL;
+@@ -117,10 +117,8 @@ nf_ct_get_tuple(const struct sk_buff *skb,
+ }
+ EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
+ 
+-int nf_ct_get_tuplepr(const struct sk_buff *skb,
+-		      unsigned int nhoff,
+-		      u_int16_t l3num,
+-		      struct nf_conntrack_tuple *tuple)
++bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
++		       u_int16_t l3num, struct nf_conntrack_tuple *tuple)
+ {
+ 	struct nf_conntrack_l3proto *l3proto;
+ 	struct nf_conntrack_l4proto *l4proto;
+@@ -134,7 +132,7 @@ int nf_ct_get_tuplepr(const struct sk_buff *skb,
+ 	ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum);
+ 	if (ret != NF_ACCEPT) {
+ 		rcu_read_unlock();
+-		return 0;
++		return false;
+ 	}
+ 
+ 	l4proto = __nf_ct_l4proto_find(l3num, protonum);
+@@ -147,7 +145,7 @@ int nf_ct_get_tuplepr(const struct sk_buff *skb,
+ }
+ EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr);
+ 
+-int
++bool
+ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
+ 		   const struct nf_conntrack_tuple *orig,
+ 		   const struct nf_conntrack_l3proto *l3proto,
+@@ -157,7 +155,7 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
+ 
+ 	inverse->src.l3num = orig->src.l3num;
+ 	if (l3proto->invert_tuple(inverse, orig) == 0)
+-		return 0;
++		return false;
+ 
+ 	inverse->dst.dir = !orig->dst.dir;
+ 
+@@ -194,8 +192,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
+ 	 * destroy_conntrack() MUST NOT be called with a write lock
+ 	 * to nf_conntrack_lock!!! -HW */
+ 	rcu_read_lock();
+-	l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
+-				       ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
++	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ 	if (l4proto && l4proto->destroy)
+ 		l4proto->destroy(ct);
+ 
+@@ -739,10 +736,10 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff *skb)
+ }
+ EXPORT_SYMBOL_GPL(nf_conntrack_in);
+ 
+-int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
+-			 const struct nf_conntrack_tuple *orig)
++bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
++			  const struct nf_conntrack_tuple *orig)
+ {
+-	int ret;
++	bool ret;
+ 
+ 	rcu_read_lock();
+ 	ret = nf_ct_invert_tuple(inverse, orig,
+@@ -766,10 +763,10 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
+ 	NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
+ 
+ 	pr_debug("Altering reply tuple of %p to ", ct);
+-	NF_CT_DUMP_TUPLE(newreply);
++	nf_ct_dump_tuple(newreply);
+ 
+ 	ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
+-	if (ct->master || (help && help->expecting != 0))
++	if (ct->master || (help && !hlist_empty(&help->expectations)))
+ 		return;
+ 
+ 	rcu_read_lock();
+diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
+index 684ec9c..e31beeb 100644
+--- a/net/netfilter/nf_conntrack_expect.c
++++ b/net/netfilter/nf_conntrack_expect.c
+@@ -54,7 +54,7 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
+ 	nf_ct_expect_count--;
+ 
+ 	hlist_del(&exp->lnode);
+-	master_help->expecting--;
++	master_help->expecting[exp->class]--;
+ 	nf_ct_expect_put(exp);
+ 
+ 	NF_CT_STAT_INC(expect_delete);
+@@ -126,9 +126,21 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
+ struct nf_conntrack_expect *
+ nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple)
+ {
+-	struct nf_conntrack_expect *exp;
++	struct nf_conntrack_expect *i, *exp = NULL;
++	struct hlist_node *n;
++	unsigned int h;
++
++	if (!nf_ct_expect_count)
++		return NULL;
+ 
+-	exp = __nf_ct_expect_find(tuple);
++	h = nf_ct_expect_dst_hash(tuple);
++	hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
++		if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
++		    nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
++			exp = i;
++			break;
++		}
++	}
+ 	if (!exp)
+ 		return NULL;
+ 
+@@ -159,7 +171,7 @@ void nf_ct_remove_expectations(struct nf_conn *ct)
+ 	struct hlist_node *n, *next;
+ 
+ 	/* Optimization: most connection never expect any others. */
+-	if (!help || help->expecting == 0)
++	if (!help)
+ 		return;
+ 
+ 	hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
+@@ -193,7 +205,7 @@ static inline int expect_clash(const struct nf_conntrack_expect *a,
+ static inline int expect_matches(const struct nf_conntrack_expect *a,
+ 				 const struct nf_conntrack_expect *b)
+ {
+-	return a->master == b->master
++	return a->master == b->master && a->class == b->class
+ 		&& nf_ct_tuple_equal(&a->tuple, &b->tuple)
+ 		&& nf_ct_tuple_mask_equal(&a->mask, &b->mask);
+ }
+@@ -228,10 +240,11 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
+ }
+ EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
+ 
+-void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family,
+-		       union nf_inet_addr *saddr,
+-		       union nf_inet_addr *daddr,
+-		       u_int8_t proto, __be16 *src, __be16 *dst)
++void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
++		       int family,
++		       const union nf_inet_addr *saddr,
++		       const union nf_inet_addr *daddr,
++		       u_int8_t proto, const __be16 *src, const __be16 *dst)
+ {
+ 	int len;
+ 
+@@ -241,6 +254,7 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family,
+ 		len = 16;
+ 
+ 	exp->flags = 0;
++	exp->class = class;
+ 	exp->expectfn = NULL;
+ 	exp->helper = NULL;
+ 	exp->tuple.src.l3num = family;
+@@ -297,19 +311,21 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_put);
+ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
+ {
+ 	struct nf_conn_help *master_help = nfct_help(exp->master);
++	const struct nf_conntrack_expect_policy *p;
+ 	unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
+ 
+ 	atomic_inc(&exp->use);
+ 
+ 	hlist_add_head(&exp->lnode, &master_help->expectations);
+-	master_help->expecting++;
++	master_help->expecting[exp->class]++;
+ 
+ 	hlist_add_head_rcu(&exp->hnode, &nf_ct_expect_hash[h]);
+ 	nf_ct_expect_count++;
+ 
+ 	setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
+ 		    (unsigned long)exp);
+-	exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
++	p = &master_help->helper->expect_policy[exp->class];
++	exp->timeout.expires = jiffies + p->timeout * HZ;
+ 	add_timer(&exp->timeout);
+ 
+ 	atomic_inc(&exp->use);
+@@ -317,35 +333,41 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
+ }
+ 
+ /* Race with expectations being used means we could have none to find; OK. */
+-static void evict_oldest_expect(struct nf_conn *master)
++static void evict_oldest_expect(struct nf_conn *master,
++				struct nf_conntrack_expect *new)
+ {
+ 	struct nf_conn_help *master_help = nfct_help(master);
+-	struct nf_conntrack_expect *exp = NULL;
++	struct nf_conntrack_expect *exp, *last = NULL;
+ 	struct hlist_node *n;
+ 
+-	hlist_for_each_entry(exp, n, &master_help->expectations, lnode)
+-		; /* nothing */
++	hlist_for_each_entry(exp, n, &master_help->expectations, lnode) {
++		if (exp->class == new->class)
++			last = exp;
++	}
+ 
+-	if (exp && del_timer(&exp->timeout)) {
+-		nf_ct_unlink_expect(exp);
+-		nf_ct_expect_put(exp);
++	if (last && del_timer(&last->timeout)) {
++		nf_ct_unlink_expect(last);
++		nf_ct_expect_put(last);
+ 	}
+ }
+ 
+ static inline int refresh_timer(struct nf_conntrack_expect *i)
+ {
+ 	struct nf_conn_help *master_help = nfct_help(i->master);
++	const struct nf_conntrack_expect_policy *p;
+ 
+ 	if (!del_timer(&i->timeout))
+ 		return 0;
+ 
+-	i->timeout.expires = jiffies + master_help->helper->timeout*HZ;
++	p = &master_help->helper->expect_policy[i->class];
++	i->timeout.expires = jiffies + p->timeout * HZ;
+ 	add_timer(&i->timeout);
+ 	return 1;
+ }
+ 
+ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
+ {
++	const struct nf_conntrack_expect_policy *p;
+ 	struct nf_conntrack_expect *i;
+ 	struct nf_conn *master = expect->master;
+ 	struct nf_conn_help *master_help = nfct_help(master);
+@@ -374,9 +396,15 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
+ 		}
+ 	}
+ 	/* Will be over limit? */
+-	if (master_help->helper->max_expected &&
+-	    master_help->expecting >= master_help->helper->max_expected)
+-		evict_oldest_expect(master);
++	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 (nf_ct_expect_count >= nf_ct_expect_max) {
+ 		if (net_ratelimit())
+@@ -460,6 +488,7 @@ static int exp_seq_show(struct seq_file *s, void *v)
+ {
+ 	struct nf_conntrack_expect *expect;
+ 	struct hlist_node *n = v;
++	char *delim = "";
+ 
+ 	expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
+ 
+@@ -475,6 +504,14 @@ static int exp_seq_show(struct seq_file *s, void *v)
+ 		    __nf_ct_l3proto_find(expect->tuple.src.l3num),
+ 		    __nf_ct_l4proto_find(expect->tuple.src.l3num,
+ 				       expect->tuple.dst.protonum));
++
++	if (expect->flags & NF_CT_EXPECT_PERMANENT) {
++		seq_printf(s, "PERMANENT");
++		delim = ",";
++	}
++	if (expect->flags & NF_CT_EXPECT_INACTIVE)
++		seq_printf(s, "%sINACTIVE", delim);
++
+ 	return seq_putc(s, '\n');
+ }
+ 
+diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
+index 2bd9963..bcc19fa 100644
+--- a/net/netfilter/nf_conntrack_extend.c
++++ b/net/netfilter/nf_conntrack_extend.c
+@@ -71,6 +71,9 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
+ 	int i, newlen, newoff;
+ 	struct nf_ct_ext_type *t;
+ 
++	/* Conntrack must not be confirmed to avoid races on reallocation. */
++	NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
++
+ 	if (!ct->ext)
+ 		return nf_ct_ext_create(&ct->ext, id, gfp);
+ 
+diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
+index 6770baf..bb20672 100644
+--- a/net/netfilter/nf_conntrack_ftp.c
++++ b/net/netfilter/nf_conntrack_ftp.c
+@@ -350,8 +350,9 @@ static int help(struct sk_buff *skb,
+ 		enum ip_conntrack_info ctinfo)
+ {
+ 	unsigned int dataoff, datalen;
+-	struct tcphdr _tcph, *th;
+-	char *fb_ptr;
++	const struct tcphdr *th;
++	struct tcphdr _tcph;
++	const char *fb_ptr;
+ 	int ret;
+ 	u32 seq;
+ 	int dir = CTINFO2DIR(ctinfo);
+@@ -405,7 +406,7 @@ static int help(struct sk_buff *skb,
+ 
+ 	/* Initialize IP/IPv6 addr to expected address (it's not mentioned
+ 	   in EPSV responses) */
+-	cmd.l3num = ct->tuplehash[dir].tuple.src.l3num;
++	cmd.l3num = nf_ct_l3num(ct);
+ 	memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
+ 	       sizeof(cmd.u3.all));
+ 
+@@ -452,7 +453,7 @@ static int help(struct sk_buff *skb,
+ 	daddr = &ct->tuplehash[!dir].tuple.dst.u3;
+ 
+ 	/* Update the ftp info */
+-	if ((cmd.l3num == ct->tuplehash[dir].tuple.src.l3num) &&
++	if ((cmd.l3num == nf_ct_l3num(ct)) &&
+ 	    memcmp(&cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
+ 		     sizeof(cmd.u3.all))) {
+ 		/* Enrico Scholz's passive FTP to partially RNAT'd ftp
+@@ -483,7 +484,7 @@ static int help(struct sk_buff *skb,
+ 		daddr = &cmd.u3;
+ 	}
+ 
+-	nf_ct_expect_init(exp, cmd.l3num,
++	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, cmd.l3num,
+ 			  &ct->tuplehash[!dir].tuple.src.u3, daddr,
+ 			  IPPROTO_TCP, NULL, &cmd.u.tcp.port);
+ 
+@@ -517,6 +518,11 @@ out_update_nl:
+ static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
+ static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")] __read_mostly;
+ 
++static const struct nf_conntrack_expect_policy ftp_exp_policy = {
++	.max_expected	= 1,
++	.timeout	= 5 * 60,
++};
++
+ /* don't make this __exit, since it's called from __init ! */
+ static void nf_conntrack_ftp_fini(void)
+ {
+@@ -556,8 +562,7 @@ static int __init nf_conntrack_ftp_init(void)
+ 		for (j = 0; j < 2; j++) {
+ 			ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
+ 			ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
+-			ftp[i][j].max_expected = 1;
+-			ftp[i][j].timeout = 5 * 60;	/* 5 Minutes */
++			ftp[i][j].expect_policy = &ftp_exp_policy;
+ 			ftp[i][j].me = THIS_MODULE;
+ 			ftp[i][j].help = help;
+ 			tmpname = &ftp_names[i][j][0];
+diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
+index 898f192..95da1a2 100644
+--- a/net/netfilter/nf_conntrack_h323_main.c
++++ b/net/netfilter/nf_conntrack_h323_main.c
+@@ -218,7 +218,6 @@ static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
+ 			 union nf_inet_addr *addr, __be16 *port)
+ {
+ 	const unsigned char *p;
+-	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ 	int len;
+ 
+ 	if (taddr->choice != eH245_TransportAddress_unicastAddress)
+@@ -226,13 +225,13 @@ static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
+ 
+ 	switch (taddr->unicastAddress.choice) {
+ 	case eUnicastAddress_iPAddress:
+-		if (family != AF_INET)
++		if (nf_ct_l3num(ct) != AF_INET)
+ 			return 0;
+ 		p = data + taddr->unicastAddress.iPAddress.network;
+ 		len = 4;
+ 		break;
+ 	case eUnicastAddress_iP6Address:
+-		if (family != AF_INET6)
++		if (nf_ct_l3num(ct) != AF_INET6)
+ 			return 0;
+ 		p = data + taddr->unicastAddress.iP6Address.network;
+ 		len = 16;
+@@ -277,7 +276,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
+ 	/* Create expect for RTP */
+ 	if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL)
+ 		return -1;
+-	nf_ct_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
++	nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ 			  &ct->tuplehash[!dir].tuple.src.u3,
+ 			  &ct->tuplehash[!dir].tuple.dst.u3,
+ 			  IPPROTO_UDP, NULL, &rtp_port);
+@@ -287,7 +286,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
+ 		nf_ct_expect_put(rtp_exp);
+ 		return -1;
+ 	}
+-	nf_ct_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
++	nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ 			  &ct->tuplehash[!dir].tuple.src.u3,
+ 			  &ct->tuplehash[!dir].tuple.dst.u3,
+ 			  IPPROTO_UDP, NULL, &rtcp_port);
+@@ -304,9 +303,9 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
+ 		if (nf_ct_expect_related(rtp_exp) == 0) {
+ 			if (nf_ct_expect_related(rtcp_exp) == 0) {
+ 				pr_debug("nf_ct_h323: expect RTP ");
+-				NF_CT_DUMP_TUPLE(&rtp_exp->tuple);
++				nf_ct_dump_tuple(&rtp_exp->tuple);
+ 				pr_debug("nf_ct_h323: expect RTCP ");
+-				NF_CT_DUMP_TUPLE(&rtcp_exp->tuple);
++				nf_ct_dump_tuple(&rtcp_exp->tuple);
+ 			} else {
+ 				nf_ct_unexpect_related(rtp_exp);
+ 				ret = -1;
+@@ -344,7 +343,7 @@ static int expect_t120(struct sk_buff *skb,
+ 	/* Create expect for T.120 connections */
+ 	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ 		return -1;
+-	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ 			  &ct->tuplehash[!dir].tuple.src.u3,
+ 			  &ct->tuplehash[!dir].tuple.dst.u3,
+ 			  IPPROTO_TCP, NULL, &port);
+@@ -361,7 +360,7 @@ static int expect_t120(struct sk_buff *skb,
+ 	} else {		/* Conntrack only */
+ 		if (nf_ct_expect_related(exp) == 0) {
+ 			pr_debug("nf_ct_h323: expect T.120 ");
+-			NF_CT_DUMP_TUPLE(&exp->tuple);
++			nf_ct_dump_tuple(&exp->tuple);
+ 		} else
+ 			ret = -1;
+ 	}
+@@ -583,7 +582,7 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff,
+ 	while (get_tpkt_data(skb, protoff, ct, ctinfo,
+ 			     &data, &datalen, &dataoff)) {
+ 		pr_debug("nf_ct_h245: TPKT len=%d ", datalen);
+-		NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
++		nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+ 
+ 		/* Decode H.245 signal */
+ 		ret = DecodeMultimediaSystemControlMessage(data, datalen,
+@@ -612,13 +611,17 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff,
+ }
+ 
+ /****************************************************************************/
++static const struct nf_conntrack_expect_policy h245_exp_policy = {
++	.max_expected	= H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
++	.timeout	= 240,
++};
++
+ static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
+ 	.name			= "H.245",
+ 	.me			= THIS_MODULE,
+-	.max_expected		= H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
+-	.timeout		= 240,
+ 	.tuple.dst.protonum	= IPPROTO_UDP,
+-	.help			= h245_help
++	.help			= h245_help,
++	.expect_policy		= &h245_exp_policy,
+ };
+ 
+ /****************************************************************************/
+@@ -627,18 +630,17 @@ int get_h225_addr(struct nf_conn *ct, unsigned char *data,
+ 		  union nf_inet_addr *addr, __be16 *port)
+ {
+ 	const unsigned char *p;
+-	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ 	int len;
+ 
+ 	switch (taddr->choice) {
+ 	case eTransportAddress_ipAddress:
+-		if (family != AF_INET)
++		if (nf_ct_l3num(ct) != AF_INET)
+ 			return 0;
+ 		p = data + taddr->ipAddress.ip;
+ 		len = 4;
+ 		break;
+ 	case eTransportAddress_ip6Address:
+-		if (family != AF_INET6)
++		if (nf_ct_l3num(ct) != AF_INET6)
+ 			return 0;
+ 		p = data + taddr->ip6Address.ip;
+ 		len = 16;
+@@ -676,7 +678,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
+ 	/* Create expect for h245 connection */
+ 	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ 		return -1;
+-	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ 			  &ct->tuplehash[!dir].tuple.src.u3,
+ 			  &ct->tuplehash[!dir].tuple.dst.u3,
+ 			  IPPROTO_TCP, NULL, &port);
+@@ -693,7 +695,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
+ 	} else {		/* Conntrack only */
+ 		if (nf_ct_expect_related(exp) == 0) {
+ 			pr_debug("nf_ct_q931: expect H.245 ");
+-			NF_CT_DUMP_TUPLE(&exp->tuple);
++			nf_ct_dump_tuple(&exp->tuple);
+ 		} else
+ 			ret = -1;
+ 	}
+@@ -784,7 +786,7 @@ static int expect_callforwarding(struct sk_buff *skb,
+ 	 * we don't need to track the second call */
+ 	if (callforward_filter &&
+ 	    callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
+-				  ct->tuplehash[!dir].tuple.src.l3num)) {
++				  nf_ct_l3num(ct))) {
+ 		pr_debug("nf_ct_q931: Call Forwarding not tracked\n");
+ 		return 0;
+ 	}
+@@ -792,7 +794,7 @@ static int expect_callforwarding(struct sk_buff *skb,
+ 	/* Create expect for the second call leg */
+ 	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ 		return -1;
+-	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ 			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ 			  IPPROTO_TCP, NULL, &port);
+ 	exp->helper = nf_conntrack_helper_q931;
+@@ -808,7 +810,7 @@ static int expect_callforwarding(struct sk_buff *skb,
+ 	} else {		/* Conntrack only */
+ 		if (nf_ct_expect_related(exp) == 0) {
+ 			pr_debug("nf_ct_q931: expect Call Forwarding ");
+-			NF_CT_DUMP_TUPLE(&exp->tuple);
++			nf_ct_dump_tuple(&exp->tuple);
+ 		} else
+ 			ret = -1;
+ 	}
+@@ -1128,7 +1130,7 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff,
+ 	while (get_tpkt_data(skb, protoff, ct, ctinfo,
+ 			     &data, &datalen, &dataoff)) {
+ 		pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
+-		NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
++		nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+ 
+ 		/* Decode Q.931 signal */
+ 		ret = DecodeQ931(data, datalen, &q931);
+@@ -1156,28 +1158,30 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff,
+ }
+ 
+ /****************************************************************************/
++static const struct nf_conntrack_expect_policy q931_exp_policy = {
++	/* T.120 and H.245 */
++	.max_expected		= H323_RTP_CHANNEL_MAX * 4 + 4,
++	.timeout		= 240,
++};
++
+ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
+ 	{
+ 		.name			= "Q.931",
+ 		.me			= THIS_MODULE,
+-					  /* T.120 and H.245 */
+-		.max_expected		= H323_RTP_CHANNEL_MAX * 4 + 4,
+-		.timeout		= 240,
+ 		.tuple.src.l3num	= AF_INET,
+ 		.tuple.src.u.tcp.port	= __constant_htons(Q931_PORT),
+ 		.tuple.dst.protonum	= IPPROTO_TCP,
+-		.help			= q931_help
++		.help			= q931_help,
++		.expect_policy		= &q931_exp_policy,
+ 	},
+ 	{
+ 		.name			= "Q.931",
+ 		.me			= THIS_MODULE,
+-					  /* T.120 and H.245 */
+-		.max_expected		= H323_RTP_CHANNEL_MAX * 4 + 4,
+-		.timeout		= 240,
+ 		.tuple.src.l3num	= AF_INET6,
+ 		.tuple.src.u.tcp.port	= __constant_htons(Q931_PORT),
+ 		.tuple.dst.protonum	= IPPROTO_TCP,
+-		.help			= q931_help
++		.help			= q931_help,
++		.expect_policy		= &q931_exp_policy,
+ 	},
+ };
+ 
+@@ -1261,7 +1265,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
+ 	/* Create expect for Q.931 */
+ 	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ 		return -1;
+-	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ 			  gkrouted_only ? /* only accept calls from GK? */
+ 				&ct->tuplehash[!dir].tuple.src.u3 : NULL,
+ 			  &ct->tuplehash[!dir].tuple.dst.u3,
+@@ -1275,7 +1279,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
+ 	} else {		/* Conntrack only */
+ 		if (nf_ct_expect_related(exp) == 0) {
+ 			pr_debug("nf_ct_ras: expect Q.931 ");
+-			NF_CT_DUMP_TUPLE(&exp->tuple);
++			nf_ct_dump_tuple(&exp->tuple);
+ 
+ 			/* Save port for looking up expect in processing RCF */
+ 			info->sig_port[dir] = port;
+@@ -1332,14 +1336,14 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
+ 	/* Need new expect */
+ 	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ 		return -1;
+-	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ 			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ 			  IPPROTO_UDP, NULL, &port);
+ 	exp->helper = nf_conntrack_helper_ras;
+ 
+ 	if (nf_ct_expect_related(exp) == 0) {
+ 		pr_debug("nf_ct_ras: expect RAS ");
+-		NF_CT_DUMP_TUPLE(&exp->tuple);
++		nf_ct_dump_tuple(&exp->tuple);
+ 	} else
+ 		ret = -1;
+ 
+@@ -1423,7 +1427,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
+ 			pr_debug("nf_ct_ras: set Q.931 expect "
+ 				 "timeout to %u seconds for",
+ 				 info->timeout);
+-			NF_CT_DUMP_TUPLE(&exp->tuple);
++			nf_ct_dump_tuple(&exp->tuple);
+ 			set_expect_timeout(exp, info->timeout);
+ 		}
+ 		spin_unlock_bh(&nf_conntrack_lock);
+@@ -1536,7 +1540,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
+ 	/* Need new expect */
+ 	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ 		return -1;
+-	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ 			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ 			  IPPROTO_TCP, NULL, &port);
+ 	exp->flags = NF_CT_EXPECT_PERMANENT;
+@@ -1544,7 +1548,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
+ 
+ 	if (nf_ct_expect_related(exp) == 0) {
+ 		pr_debug("nf_ct_ras: expect Q.931 ");
+-		NF_CT_DUMP_TUPLE(&exp->tuple);
++		nf_ct_dump_tuple(&exp->tuple);
+ 	} else
+ 		ret = -1;
+ 
+@@ -1589,7 +1593,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
+ 	/* Need new expect for call signal */
+ 	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ 		return -1;
+-	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ 			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ 			  IPPROTO_TCP, NULL, &port);
+ 	exp->flags = NF_CT_EXPECT_PERMANENT;
+@@ -1597,7 +1601,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
+ 
+ 	if (nf_ct_expect_related(exp) == 0) {
+ 		pr_debug("nf_ct_ras: expect Q.931 ");
+-		NF_CT_DUMP_TUPLE(&exp->tuple);
++		nf_ct_dump_tuple(&exp->tuple);
+ 	} else
+ 		ret = -1;
+ 
+@@ -1701,7 +1705,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
+ 	if (data == NULL)
+ 		goto accept;
+ 	pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
+-	NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
++	nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+ 
+ 	/* Decode RAS message */
+ 	ret = DecodeRasMessage(data, datalen, &ras);
+@@ -1728,26 +1732,29 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
+ }
+ 
+ /****************************************************************************/
++static const struct nf_conntrack_expect_policy ras_exp_policy = {
++	.max_expected		= 32,
++	.timeout		= 240,
++};
++
+ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
+ 	{
+ 		.name			= "RAS",
+ 		.me			= THIS_MODULE,
+-		.max_expected		= 32,
+-		.timeout		= 240,
+ 		.tuple.src.l3num	= AF_INET,
+ 		.tuple.src.u.udp.port	= __constant_htons(RAS_PORT),
+ 		.tuple.dst.protonum	= IPPROTO_UDP,
+ 		.help			= ras_help,
++		.expect_policy		= &ras_exp_policy,
+ 	},
+ 	{
+ 		.name			= "RAS",
+ 		.me			= THIS_MODULE,
+-		.max_expected		= 32,
+-		.timeout		= 240,
+ 		.tuple.src.l3num	= AF_INET6,
+ 		.tuple.src.u.udp.port	= __constant_htons(RAS_PORT),
+ 		.tuple.dst.protonum	= IPPROTO_UDP,
+ 		.help			= ras_help,
++		.expect_policy		= &ras_exp_policy,
+ 	},
+ };
+ 
+diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
+index b1fd21c..7d1b117 100644
+--- a/net/netfilter/nf_conntrack_helper.c
++++ b/net/netfilter/nf_conntrack_helper.c
+@@ -110,7 +110,8 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
+ {
+ 	unsigned int h = helper_hash(&me->tuple);
+ 
+-	BUG_ON(me->timeout == 0);
++	BUG_ON(me->expect_policy == NULL);
++	BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
+ 
+ 	mutex_lock(&nf_ct_helper_mutex);
+ 	hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);
+@@ -125,7 +126,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
+ {
+ 	struct nf_conntrack_tuple_hash *h;
+ 	struct nf_conntrack_expect *exp;
+-	struct hlist_node *n, *next;
++	const struct hlist_node *n, *next;
+ 	unsigned int i;
+ 
+ 	mutex_lock(&nf_ct_helper_mutex);
+diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
+index c336b07..1b1226d 100644
+--- a/net/netfilter/nf_conntrack_irc.c
++++ b/net/netfilter/nf_conntrack_irc.c
+@@ -50,7 +50,7 @@ MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per "
+ module_param(dcc_timeout, uint, 0400);
+ MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
+ 
+-static const char *dccprotos[] = {
++static const char *const dccprotos[] = {
+ 	"SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT "
+ };
+ 
+@@ -65,7 +65,7 @@ static const char *dccprotos[] = {
+  *	ad_beg_p	returns pointer to first byte of addr data
+  *	ad_end_p	returns pointer to last byte of addr data
+  */
+-static int parse_dcc(char *data, char *data_end, u_int32_t *ip,
++static int parse_dcc(char *data, const char *data_end, u_int32_t *ip,
+ 		     u_int16_t *port, char **ad_beg_p, char **ad_end_p)
+ {
+ 	/* at least 12: "AAAAAAAA P\1\n" */
+@@ -93,9 +93,11 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ 		struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+ {
+ 	unsigned int dataoff;
+-	struct iphdr *iph;
+-	struct tcphdr _tcph, *th;
+-	char *data, *data_limit, *ib_ptr;
++	const struct iphdr *iph;
++	const struct tcphdr *th;
++	struct tcphdr _tcph;
++	const char *data_limit;
++	char *data, *ib_ptr;
+ 	int dir = CTINFO2DIR(ctinfo);
+ 	struct nf_conntrack_expect *exp;
+ 	struct nf_conntrack_tuple *tuple;
+@@ -159,7 +161,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ 			/* we have at least
+ 			 * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
+ 			 * data left (== 14/13 bytes) */
+-			if (parse_dcc((char *)data, data_limit, &dcc_ip,
++			if (parse_dcc(data, data_limit, &dcc_ip,
+ 				       &dcc_port, &addr_beg_p, &addr_end_p)) {
+ 				pr_debug("unable to parse dcc command\n");
+ 				continue;
+@@ -187,7 +189,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ 			}
+ 			tuple = &ct->tuplehash[!dir].tuple;
+ 			port = htons(dcc_port);
+-			nf_ct_expect_init(exp, tuple->src.l3num,
++			nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
++					  tuple->src.l3num,
+ 					  NULL, &tuple->dst.u3,
+ 					  IPPROTO_TCP, NULL, &port);
+ 
+@@ -210,6 +213,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ 
+ static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly;
+ static char irc_names[MAX_PORTS][sizeof("irc-65535")] __read_mostly;
++static struct nf_conntrack_expect_policy irc_exp_policy;
+ 
+ static void nf_conntrack_irc_fini(void);
+ 
+@@ -223,6 +227,9 @@ static int __init nf_conntrack_irc_init(void)
+ 		return -EINVAL;
+ 	}
+ 
++	irc_exp_policy.max_expected = max_dcc_channels;
++	irc_exp_policy.timeout = dcc_timeout;
++
+ 	irc_buffer = kmalloc(65536, GFP_KERNEL);
+ 	if (!irc_buffer)
+ 		return -ENOMEM;
+@@ -235,8 +242,7 @@ static int __init nf_conntrack_irc_init(void)
+ 		irc[i].tuple.src.l3num = AF_INET;
+ 		irc[i].tuple.src.u.tcp.port = htons(ports[i]);
+ 		irc[i].tuple.dst.protonum = IPPROTO_TCP;
+-		irc[i].max_expected = max_dcc_channels;
+-		irc[i].timeout = dcc_timeout;
++		irc[i].expect_policy = &irc_exp_policy;
+ 		irc[i].me = THIS_MODULE;
+ 		irc[i].help = help;
+ 
+diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
+index 8e914e5..e7eb807 100644
+--- a/net/netfilter/nf_conntrack_l3proto_generic.c
++++ b/net/netfilter/nf_conntrack_l3proto_generic.c
+@@ -31,22 +31,22 @@
+ #include <net/netfilter/nf_conntrack_core.h>
+ #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
+ 
+-static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
+-				struct nf_conntrack_tuple *tuple)
++static bool generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
++				 struct nf_conntrack_tuple *tuple)
+ {
+ 	memset(&tuple->src.u3, 0, sizeof(tuple->src.u3));
+ 	memset(&tuple->dst.u3, 0, sizeof(tuple->dst.u3));
+ 
+-	return 1;
++	return true;
+ }
+ 
+-static int generic_invert_tuple(struct nf_conntrack_tuple *tuple,
+-			   const struct nf_conntrack_tuple *orig)
++static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
++				 const struct nf_conntrack_tuple *orig)
+ {
+ 	memset(&tuple->src.u3, 0, sizeof(tuple->src.u3));
+ 	memset(&tuple->dst.u3, 0, sizeof(tuple->dst.u3));
+ 
+-	return 1;
++	return true;
+ }
+ 
+ static int generic_print_tuple(struct seq_file *s,
+diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
+index 9810d81..08404e6 100644
+--- a/net/netfilter/nf_conntrack_netbios_ns.c
++++ b/net/netfilter/nf_conntrack_netbios_ns.c
+@@ -47,7 +47,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ {
+ 	struct nf_conntrack_expect *exp;
+ 	struct iphdr *iph = ip_hdr(skb);
+-	struct rtable *rt = (struct rtable *)skb->dst;
++	struct rtable *rt = skb->rtable;
+ 	struct in_device *in_dev;
+ 	__be32 mask = 0;
+ 
+@@ -86,6 +86,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ 
+ 	exp->expectfn             = NULL;
+ 	exp->flags                = NF_CT_EXPECT_PERMANENT;
++	exp->class		  = NF_CT_EXPECT_CLASS_DEFAULT;
+ 	exp->helper               = NULL;
+ 
+ 	nf_ct_expect_related(exp);
+@@ -96,19 +97,23 @@ out:
+ 	return NF_ACCEPT;
+ }
+ 
++static struct nf_conntrack_expect_policy exp_policy = {
++	.max_expected	= 1,
++};
++
+ static struct nf_conntrack_helper helper __read_mostly = {
+ 	.name			= "netbios-ns",
+ 	.tuple.src.l3num	= AF_INET,
+ 	.tuple.src.u.udp.port	= __constant_htons(NMBD_PORT),
+ 	.tuple.dst.protonum	= IPPROTO_UDP,
+-	.max_expected		= 1,
+ 	.me			= THIS_MODULE,
+ 	.help			= help,
++	.expect_policy		= &exp_policy,
+ };
+ 
+ static int __init nf_conntrack_netbios_ns_init(void)
+ {
+-	helper.timeout = timeout;
++	exp_policy.timeout = timeout;
+ 	return nf_conntrack_helper_register(&helper);
+ }
+ 
+diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
+index 4a1b42b..16774ec 100644
+--- a/net/netfilter/nf_conntrack_netlink.c
++++ b/net/netfilter/nf_conntrack_netlink.c
+@@ -145,10 +145,11 @@ nla_put_failure:
+ static inline int
+ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct)
+ {
+-	struct nf_conntrack_l4proto *l4proto = nf_ct_l4proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
++	struct nf_conntrack_l4proto *l4proto;
+ 	struct nlattr *nest_proto;
+ 	int ret;
+ 
++	l4proto = nf_ct_l4proto_find_get(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ 	if (!l4proto->to_nlattr) {
+ 		nf_ct_l4proto_put(l4proto);
+ 		return 0;
+@@ -368,8 +369,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
+ 	nfmsg  = NLMSG_DATA(nlh);
+ 
+ 	nlh->nlmsg_flags    = (nowait && pid) ? NLM_F_MULTI : 0;
+-	nfmsg->nfgen_family =
+-		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
++	nfmsg->nfgen_family = nf_ct_l3num(ct);
+ 	nfmsg->version      = NFNETLINK_V0;
+ 	nfmsg->res_id	    = 0;
+ 
+@@ -454,7 +454,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
+ 	nfmsg = NLMSG_DATA(nlh);
+ 
+ 	nlh->nlmsg_flags    = flags;
+-	nfmsg->nfgen_family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
++	nfmsg->nfgen_family = nf_ct_l3num(ct);
+ 	nfmsg->version	= NFNETLINK_V0;
+ 	nfmsg->res_id	= 0;
+ 
+@@ -535,8 +535,6 @@ static int ctnetlink_done(struct netlink_callback *cb)
+ 	return 0;
+ }
+ 
+-#define L3PROTO(ct) (ct)->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
+-
+ static int
+ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+@@ -558,7 +556,7 @@ restart:
+ 			/* Dump entries of a given L3 protocol number.
+ 			 * If it is not specified, ie. l3proto == 0,
+ 			 * then dump everything. */
+-			if (l3proto && L3PROTO(ct) != l3proto)
++			if (l3proto && nf_ct_l3num(ct) != l3proto)
+ 				continue;
+ 			if (cb->args[1]) {
+ 				if (ct != last)
+@@ -704,20 +702,11 @@ static int nfnetlink_parse_nat_proto(struct nlattr *attr,
+ 	if (err < 0)
+ 		return err;
+ 
+-	npt = nf_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+-
+-	if (!npt->nlattr_to_range) {
+-		nf_nat_proto_put(npt);
+-		return 0;
+-	}
+-
+-	/* nlattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
+-	if (npt->nlattr_to_range(tb, range) > 0)
+-		range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+-
++	npt = nf_nat_proto_find_get(nf_ct_protonum(ct));
++	if (npt->nlattr_to_range)
++		err = npt->nlattr_to_range(tb, range);
+ 	nf_nat_proto_put(npt);
+-
+-	return 0;
++	return err;
+ }
+ 
+ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
+@@ -1010,14 +999,11 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[])
+ {
+ 	struct nlattr *tb[CTA_PROTOINFO_MAX+1], *attr = cda[CTA_PROTOINFO];
+ 	struct nf_conntrack_l4proto *l4proto;
+-	u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
+-	u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ 	int err = 0;
+ 
+ 	nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, NULL);
+ 
+-	l4proto = nf_ct_l4proto_find_get(l3num, npt);
+-
++	l4proto = nf_ct_l4proto_find_get(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ 	if (l4proto->from_nlattr)
+ 		err = l4proto->from_nlattr(tb, ct);
+ 	nf_ct_l4proto_put(l4proto);
+diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
+index b5cb8e8..97e54b0 100644
+--- a/net/netfilter/nf_conntrack_pptp.c
++++ b/net/netfilter/nf_conntrack_pptp.c
+@@ -119,7 +119,7 @@ static void pptp_expectfn(struct nf_conn *ct,
+ 		/* obviously this tuple inversion only works until you do NAT */
+ 		nf_ct_invert_tuplepr(&inv_t, &exp->tuple);
+ 		pr_debug("trying to unexpect other dir: ");
+-		NF_CT_DUMP_TUPLE(&inv_t);
++		nf_ct_dump_tuple(&inv_t);
+ 
+ 		exp_other = nf_ct_expect_find_get(&inv_t);
+ 		if (exp_other) {
+@@ -141,7 +141,7 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
+ 	struct nf_conn *sibling;
+ 
+ 	pr_debug("trying to timeout ct or exp for tuple ");
+-	NF_CT_DUMP_TUPLE(t);
++	nf_ct_dump_tuple(t);
+ 
+ 	h = nf_conntrack_find_get(t);
+ 	if (h)  {
+@@ -208,7 +208,8 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
+ 
+ 	/* original direction, PNS->PAC */
+ 	dir = IP_CT_DIR_ORIGINAL;
+-	nf_ct_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
++	nf_ct_expect_init(exp_orig, NF_CT_EXPECT_CLASS_DEFAULT,
++			  nf_ct_l3num(ct),
+ 			  &ct->tuplehash[dir].tuple.src.u3,
+ 			  &ct->tuplehash[dir].tuple.dst.u3,
+ 			  IPPROTO_GRE, &peer_callid, &callid);
+@@ -216,7 +217,8 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
+ 
+ 	/* reply direction, PAC->PNS */
+ 	dir = IP_CT_DIR_REPLY;
+-	nf_ct_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
++	nf_ct_expect_init(exp_reply, NF_CT_EXPECT_CLASS_DEFAULT,
++			  nf_ct_l3num(ct),
+ 			  &ct->tuplehash[dir].tuple.src.u3,
+ 			  &ct->tuplehash[dir].tuple.dst.u3,
+ 			  IPPROTO_GRE, &callid, &peer_callid);
+@@ -575,17 +577,21 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff,
+ 	return ret;
+ }
+ 
++static const struct nf_conntrack_expect_policy pptp_exp_policy = {
++	.max_expected	= 2,
++	.timeout	= 5 * 60,
++};
++
+ /* control protocol helper */
+ static struct nf_conntrack_helper pptp __read_mostly = {
+ 	.name			= "pptp",
+ 	.me			= THIS_MODULE,
+-	.max_expected		= 2,
+-	.timeout		= 5 * 60,
+ 	.tuple.src.l3num	= AF_INET,
+ 	.tuple.src.u.tcp.port	= __constant_htons(PPTP_CONTROL_PORT),
+ 	.tuple.dst.protonum	= IPPROTO_TCP,
+ 	.help			= conntrack_pptp_help,
+ 	.destroy		= pptp_destroy_siblings,
++	.expect_policy		= &pptp_exp_policy,
+ };
+ 
+ static int __init nf_conntrack_pptp_init(void)
+diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
+index 8595b59..a49fc93 100644
+--- a/net/netfilter/nf_conntrack_proto.c
++++ b/net/netfilter/nf_conntrack_proto.c
+@@ -146,18 +146,15 @@ EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
+ 
+ static int kill_l3proto(struct nf_conn *i, void *data)
+ {
+-	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
+-			((struct nf_conntrack_l3proto *)data)->l3proto);
++	return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto;
+ }
+ 
+ static int kill_l4proto(struct nf_conn *i, void *data)
+ {
+ 	struct nf_conntrack_l4proto *l4proto;
+ 	l4proto = (struct nf_conntrack_l4proto *)data;
+-	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
+-			l4proto->l4proto) &&
+-	       (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
+-			l4proto->l3proto);
++	return nf_ct_protonum(i) == l4proto->l4proto &&
++	       nf_ct_l3num(i) == l4proto->l3proto;
+ }
+ 
+ static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto)
+diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
+new file mode 100644
+index 0000000..afb4a18
+--- /dev/null
++++ b/net/netfilter/nf_conntrack_proto_dccp.c
+@@ -0,0 +1,815 @@
++/*
++ * DCCP connection tracking protocol helper
++ *
++ * Copyright (c) 2005, 2006, 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/sysctl.h>
++#include <linux/spinlock.h>
++#include <linux/skbuff.h>
++#include <linux/dccp.h>
++
++#include <linux/netfilter/nfnetlink_conntrack.h>
++#include <net/netfilter/nf_conntrack.h>
++#include <net/netfilter/nf_conntrack_l4proto.h>
++#include <net/netfilter/nf_log.h>
++
++static DEFINE_RWLOCK(dccp_lock);
++
++static int nf_ct_dccp_loose __read_mostly = 1;
++
++/* Timeouts are based on values from RFC4340:
++ *
++ * - REQUEST:
++ *
++ *   8.1.2. Client Request
++ *
++ *   A client MAY give up on its DCCP-Requests after some time
++ *   (3 minutes, for example).
++ *
++ * - RESPOND:
++ *
++ *   8.1.3. Server Response
++ *
++ *   It MAY also leave the RESPOND state for CLOSED after a timeout of
++ *   not less than 4MSL (8 minutes);
++ *
++ * - PARTOPEN:
++ *
++ *   8.1.5. Handshake Completion
++ *
++ *   If the client remains in PARTOPEN for more than 4MSL (8 minutes),
++ *   it SHOULD reset the connection with Reset Code 2, "Aborted".
++ *
++ * - OPEN:
++ *
++ *   The DCCP timestamp overflows after 11.9 hours. If the connection
++ *   stays idle this long the sequence number won't be recognized
++ *   as valid anymore.
++ *
++ * - CLOSEREQ/CLOSING:
++ *
++ *   8.3. Termination
++ *
++ *   The retransmission timer should initially be set to go off in two
++ *   round-trip times and should back off to not less than once every
++ *   64 seconds ...
++ *
++ * - TIMEWAIT:
++ *
++ *   4.3. States
++ *
++ *   A server or client socket remains in this state for 2MSL (4 minutes)
++ *   after the connection has been town down, ...
++ */
++
++#define DCCP_MSL (2 * 60 * HZ)
++
++static unsigned int dccp_timeout[CT_DCCP_MAX + 1] __read_mostly = {
++	[CT_DCCP_REQUEST]	= 2 * DCCP_MSL,
++	[CT_DCCP_RESPOND]	= 4 * DCCP_MSL,
++	[CT_DCCP_PARTOPEN]	= 4 * DCCP_MSL,
++	[CT_DCCP_OPEN]		= 12 * 3600 * HZ,
++	[CT_DCCP_CLOSEREQ]	= 64 * HZ,
++	[CT_DCCP_CLOSING]	= 64 * HZ,
++	[CT_DCCP_TIMEWAIT]	= 2 * DCCP_MSL,
++};
++
++static const char * const dccp_state_names[] = {
++	[CT_DCCP_NONE]		= "NONE",
++	[CT_DCCP_REQUEST]	= "REQUEST",
++	[CT_DCCP_RESPOND]	= "RESPOND",
++	[CT_DCCP_PARTOPEN]	= "PARTOPEN",
++	[CT_DCCP_OPEN]		= "OPEN",
++	[CT_DCCP_CLOSEREQ]	= "CLOSEREQ",
++	[CT_DCCP_CLOSING]	= "CLOSING",
++	[CT_DCCP_TIMEWAIT]	= "TIMEWAIT",
++	[CT_DCCP_IGNORE]	= "IGNORE",
++	[CT_DCCP_INVALID]	= "INVALID",
++};
++
++#define sNO	CT_DCCP_NONE
++#define sRQ	CT_DCCP_REQUEST
++#define sRS	CT_DCCP_RESPOND
++#define sPO	CT_DCCP_PARTOPEN
++#define sOP	CT_DCCP_OPEN
++#define sCR	CT_DCCP_CLOSEREQ
++#define sCG	CT_DCCP_CLOSING
++#define sTW	CT_DCCP_TIMEWAIT
++#define sIG	CT_DCCP_IGNORE
++#define sIV	CT_DCCP_INVALID
++
++/*
++ * DCCP state transistion table
++ *
++ * The assumption is the same as for TCP tracking:
++ *
++ * We are the man in the middle. All the packets go through us but might
++ * get lost in transit to the destination. It is assumed that the destination
++ * can't receive segments we haven't seen.
++ *
++ * The following states exist:
++ *
++ * NONE:	Initial state, expecting Request
++ * REQUEST:	Request seen, waiting for Response from server
++ * RESPOND:	Response from server seen, waiting for Ack from client
++ * PARTOPEN:	Ack after Response seen, waiting for packet other than Response,
++ * 		Reset or Sync from server
++ * OPEN:	Packet other than Response, Reset or Sync seen
++ * CLOSEREQ:	CloseReq from server seen, expecting Close from client
++ * CLOSING:	Close seen, expecting Reset
++ * TIMEWAIT:	Reset seen
++ * IGNORE:	Not determinable whether packet is valid
++ *
++ * Some states exist only on one side of the connection: REQUEST, RESPOND,
++ * PARTOPEN, CLOSEREQ. For the other side these states are equivalent to
++ * the one it was in before.
++ *
++ * Packets are marked as ignored (sIG) if we don't know if they're valid
++ * (for example a reincarnation of a connection we didn't notice is dead
++ * already) and the server may send back a connection closing Reset or a
++ * Response. They're also used for Sync/SyncAck packets, which we don't
++ * care about.
++ */
++static const u_int8_t
++dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = {
++	[CT_DCCP_ROLE_CLIENT] = {
++		[DCCP_PKT_REQUEST] = {
++		/*
++		 * sNO -> sRQ		Regular Request
++		 * sRQ -> sRQ		Retransmitted Request or reincarnation
++		 * sRS -> sRS		Retransmitted Request (apparently Response
++		 * 			got lost after we saw it) or reincarnation
++		 * sPO -> sIG		Ignore, conntrack might be out of sync
++		 * sOP -> sIG		Ignore, conntrack might be out of sync
++		 * sCR -> sIG		Ignore, conntrack might be out of sync
++		 * sCG -> sIG		Ignore, conntrack might be out of sync
++		 * sTW -> sRQ		Reincarnation
++		 *
++		 *	sNO, sRQ, sRS, sPO. sOP, sCR, sCG, sTW, */
++			sRQ, sRQ, sRS, sIG, sIG, sIG, sIG, sRQ,
++		},
++		[DCCP_PKT_RESPONSE] = {
++		/*
++		 * sNO -> sIV		Invalid
++		 * sRQ -> sIG		Ignore, might be response to ignored Request
++		 * sRS -> sIG		Ignore, might be response to ignored Request
++		 * sPO -> sIG		Ignore, might be response to ignored Request
++		 * sOP -> sIG		Ignore, might be response to ignored Request
++		 * sCR -> sIG		Ignore, might be response to ignored Request
++		 * sCG -> sIG		Ignore, might be response to ignored Request
++		 * sTW -> sIV		Invalid, reincarnation in reverse direction
++		 *			goes through sRQ
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIV,
++		},
++		[DCCP_PKT_ACK] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sIV		No connection
++		 * sRS -> sPO		Ack for Response, move to PARTOPEN (8.1.5.)
++		 * sPO -> sPO		Retransmitted Ack for Response, remain in PARTOPEN
++		 * sOP -> sOP		Regular ACK, remain in OPEN
++		 * sCR -> sCR		Ack in CLOSEREQ MAY be processed (8.3.)
++		 * sCG -> sCG		Ack in CLOSING MAY be processed (8.3.)
++		 * sTW -> sIV
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV
++		},
++		[DCCP_PKT_DATA] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sIV		No connection
++		 * sRS -> sIV		No connection
++		 * sPO -> sIV		MUST use DataAck in PARTOPEN state (8.1.5.)
++		 * sOP -> sOP		Regular Data packet
++		 * sCR -> sCR		Data in CLOSEREQ MAY be processed (8.3.)
++		 * sCG -> sCG		Data in CLOSING MAY be processed (8.3.)
++		 * sTW -> sIV
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sIV, sIV, sOP, sCR, sCG, sIV,
++		},
++		[DCCP_PKT_DATAACK] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sIV		No connection
++		 * sRS -> sPO		Ack for Response, move to PARTOPEN (8.1.5.)
++		 * sPO -> sPO		Remain in PARTOPEN state
++		 * sOP -> sOP		Regular DataAck packet in OPEN state
++		 * sCR -> sCR		DataAck in CLOSEREQ MAY be processed (8.3.)
++		 * sCG -> sCG		DataAck in CLOSING MAY be processed (8.3.)
++		 * sTW -> sIV
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV
++		},
++		[DCCP_PKT_CLOSEREQ] = {
++		/*
++		 * CLOSEREQ may only be sent by the server.
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV
++		},
++		[DCCP_PKT_CLOSE] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sIV		No connection
++		 * sRS -> sIV		No connection
++		 * sPO -> sCG		Client-initiated close
++		 * sOP -> sCG		Client-initiated close
++		 * sCR -> sCG		Close in response to CloseReq (8.3.)
++		 * sCG -> sCG		Retransmit
++		 * sTW -> sIV		Late retransmit, already in TIME_WAIT
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sIV, sCG, sCG, sCG, sIV, sIV
++		},
++		[DCCP_PKT_RESET] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sTW		Sync received or timeout, SHOULD send Reset (8.1.1.)
++		 * sRS -> sTW		Response received without Request
++		 * sPO -> sTW		Timeout, SHOULD send Reset (8.1.5.)
++		 * sOP -> sTW		Connection reset
++		 * sCR -> sTW		Connection reset
++		 * sCG -> sTW		Connection reset
++		 * sTW -> sIG		Ignore (don't refresh timer)
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sTW, sTW, sTW, sTW, sTW, sTW, sIG
++		},
++		[DCCP_PKT_SYNC] = {
++		/*
++		 * We currently ignore Sync packets
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
++		},
++		[DCCP_PKT_SYNCACK] = {
++		/*
++		 * We currently ignore SyncAck packets
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
++		},
++	},
++	[CT_DCCP_ROLE_SERVER] = {
++		[DCCP_PKT_REQUEST] = {
++		/*
++		 * sNO -> sIV		Invalid
++		 * sRQ -> sIG		Ignore, conntrack might be out of sync
++		 * sRS -> sIG		Ignore, conntrack might be out of sync
++		 * sPO -> sIG		Ignore, conntrack might be out of sync
++		 * sOP -> sIG		Ignore, conntrack might be out of sync
++		 * sCR -> sIG		Ignore, conntrack might be out of sync
++		 * sCG -> sIG		Ignore, conntrack might be out of sync
++		 * sTW -> sRQ		Reincarnation, must reverse roles
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIG, sIG, sIG, sIG, sIG, sIG, sRQ
++		},
++		[DCCP_PKT_RESPONSE] = {
++		/*
++		 * sNO -> sIV		Response without Request
++		 * sRQ -> sRS		Response to clients Request
++		 * sRS -> sRS		Retransmitted Response (8.1.3. SHOULD NOT)
++		 * sPO -> sIG		Response to an ignored Request or late retransmit
++		 * sOP -> sIG		Ignore, might be response to ignored Request
++		 * sCR -> sIG		Ignore, might be response to ignored Request
++		 * sCG -> sIG		Ignore, might be response to ignored Request
++		 * sTW -> sIV		Invalid, Request from client in sTW moves to sRQ
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sRS, sRS, sIG, sIG, sIG, sIG, sIV
++		},
++		[DCCP_PKT_ACK] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sIV		No connection
++		 * sRS -> sIV		No connection
++		 * sPO -> sOP		Enter OPEN state (8.1.5.)
++		 * sOP -> sOP		Regular Ack in OPEN state
++		 * sCR -> sIV		Waiting for Close from client
++		 * sCG -> sCG		Ack in CLOSING MAY be processed (8.3.)
++		 * sTW -> sIV
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
++		},
++		[DCCP_PKT_DATA] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sIV		No connection
++		 * sRS -> sIV		No connection
++		 * sPO -> sOP		Enter OPEN state (8.1.5.)
++		 * sOP -> sOP		Regular Data packet in OPEN state
++		 * sCR -> sIV		Waiting for Close from client
++		 * sCG -> sCG		Data in CLOSING MAY be processed (8.3.)
++		 * sTW -> sIV
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
++		},
++		[DCCP_PKT_DATAACK] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sIV		No connection
++		 * sRS -> sIV		No connection
++		 * sPO -> sOP		Enter OPEN state (8.1.5.)
++		 * sOP -> sOP		Regular DataAck in OPEN state
++		 * sCR -> sIV		Waiting for Close from client
++		 * sCG -> sCG		Data in CLOSING MAY be processed (8.3.)
++		 * sTW -> sIV
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
++		},
++		[DCCP_PKT_CLOSEREQ] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sIV		No connection
++		 * sRS -> sIV		No connection
++		 * sPO -> sOP -> sCR	Move directly to CLOSEREQ (8.1.5.)
++		 * sOP -> sCR		CloseReq in OPEN state
++		 * sCR -> sCR		Retransmit
++		 * sCG -> sCR		Simultaneous close, client sends another Close
++		 * sTW -> sIV		Already closed
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sIV, sCR, sCR, sCR, sCR, sIV
++		},
++		[DCCP_PKT_CLOSE] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sIV		No connection
++		 * sRS -> sIV		No connection
++		 * sPO -> sOP -> sCG	Move direcly to CLOSING
++		 * sOP -> sCG		Move to CLOSING
++		 * sCR -> sIV		Close after CloseReq is invalid
++		 * sCG -> sCG		Retransmit
++		 * sTW -> sIV		Already closed
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIV, sIV, sIV, sCG, sCG, sIV, sCG, sIV
++		},
++		[DCCP_PKT_RESET] = {
++		/*
++		 * sNO -> sIV		No connection
++		 * sRQ -> sTW		Reset in response to Request
++		 * sRS -> sTW		Timeout, SHOULD send Reset (8.1.3.)
++		 * sPO -> sTW		Timeout, SHOULD send Reset (8.1.3.)
++		 * sOP -> sTW
++		 * sCR -> sTW
++		 * sCG -> sTW
++		 * sTW -> sIG		Ignore (don't refresh timer)
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW, sTW */
++			sIV, sTW, sTW, sTW, sTW, sTW, sTW, sTW, sIG
++		},
++		[DCCP_PKT_SYNC] = {
++		/*
++		 * We currently ignore Sync packets
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
++		},
++		[DCCP_PKT_SYNCACK] = {
++		/*
++		 * We currently ignore SyncAck packets
++		 *
++		 *	sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++			sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
++		},
++	},
++};
++
++static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++			      struct nf_conntrack_tuple *tuple)
++{
++	struct dccp_hdr _hdr, *dh;
++
++	dh = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
++	if (dh == NULL)
++		return false;
++
++	tuple->src.u.dccp.port = dh->dccph_sport;
++	tuple->dst.u.dccp.port = dh->dccph_dport;
++	return true;
++}
++
++static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv,
++			      const struct nf_conntrack_tuple *tuple)
++{
++	inv->src.u.dccp.port = tuple->dst.u.dccp.port;
++	inv->dst.u.dccp.port = tuple->src.u.dccp.port;
++	return true;
++}
++
++static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
++		     unsigned int dataoff)
++{
++	struct dccp_hdr _dh, *dh;
++	const char *msg;
++	u_int8_t state;
++
++	dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
++	BUG_ON(dh == NULL);
++
++	state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
++	switch (state) {
++	default:
++		if (nf_ct_dccp_loose == 0) {
++			msg = "nf_ct_dccp: not picking up existing connection ";
++			goto out_invalid;
++		}
++	case CT_DCCP_REQUEST:
++		break;
++	case CT_DCCP_INVALID:
++		msg = "nf_ct_dccp: invalid state transition ";
++		goto out_invalid;
++	}
++
++	ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
++	ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
++	ct->proto.dccp.state = CT_DCCP_NONE;
++	return true;
++
++out_invalid:
++	if (LOG_INVALID(IPPROTO_DCCP))
++		nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, msg);
++	return false;
++}
++
++static u64 dccp_ack_seq(const struct dccp_hdr *dh)
++{
++	const struct dccp_hdr_ack_bits *dhack;
++
++	dhack = (void *)dh + __dccp_basic_hdr_len(dh);
++	return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) +
++		     ntohl(dhack->dccph_ack_nr_low);
++}
++
++static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
++		       unsigned int dataoff, enum ip_conntrack_info ctinfo,
++		       int pf, unsigned int hooknum)
++{
++	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++	struct dccp_hdr _dh, *dh;
++	u_int8_t type, old_state, new_state;
++	enum ct_dccp_roles role;
++
++	dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
++	BUG_ON(dh == NULL);
++	type = dh->dccph_type;
++
++	if (type == DCCP_PKT_RESET &&
++	    !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
++		/* Tear down connection immediately if only reply is a RESET */
++		if (del_timer(&ct->timeout))
++			ct->timeout.function((unsigned long)ct);
++		return NF_ACCEPT;
++	}
++
++	write_lock_bh(&dccp_lock);
++
++	role = ct->proto.dccp.role[dir];
++	old_state = ct->proto.dccp.state;
++	new_state = dccp_state_table[role][type][old_state];
++
++	switch (new_state) {
++	case CT_DCCP_REQUEST:
++		if (old_state == CT_DCCP_TIMEWAIT &&
++		    role == CT_DCCP_ROLE_SERVER) {
++			/* Reincarnation in the reverse direction: reopen and
++			 * reverse client/server roles. */
++			ct->proto.dccp.role[dir] = CT_DCCP_ROLE_CLIENT;
++			ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_SERVER;
++		}
++		break;
++	case CT_DCCP_RESPOND:
++		if (old_state == CT_DCCP_REQUEST)
++			ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
++		break;
++	case CT_DCCP_PARTOPEN:
++		if (old_state == CT_DCCP_RESPOND &&
++		    type == DCCP_PKT_ACK &&
++		    dccp_ack_seq(dh) == ct->proto.dccp.handshake_seq)
++			set_bit(IPS_ASSURED_BIT, &ct->status);
++		break;
++	case CT_DCCP_IGNORE:
++		/*
++		 * Connection tracking might be out of sync, so we ignore
++		 * packets that might establish a new connection and resync
++		 * if the server responds with a valid Response.
++		 */
++		if (ct->proto.dccp.last_dir == !dir &&
++		    ct->proto.dccp.last_pkt == DCCP_PKT_REQUEST &&
++		    type == DCCP_PKT_RESPONSE) {
++			ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_CLIENT;
++			ct->proto.dccp.role[dir] = CT_DCCP_ROLE_SERVER;
++			ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
++			new_state = CT_DCCP_RESPOND;
++			break;
++		}
++		ct->proto.dccp.last_dir = dir;
++		ct->proto.dccp.last_pkt = type;
++
++		write_unlock_bh(&dccp_lock);
++		if (LOG_INVALID(IPPROTO_DCCP))
++			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
++				      "nf_ct_dccp: invalid packet ignored ");
++		return NF_ACCEPT;
++	case CT_DCCP_INVALID:
++		write_unlock_bh(&dccp_lock);
++		if (LOG_INVALID(IPPROTO_DCCP))
++			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
++				      "nf_ct_dccp: invalid state transition ");
++		return -NF_ACCEPT;
++	}
++
++	ct->proto.dccp.last_dir = dir;
++	ct->proto.dccp.last_pkt = type;
++	ct->proto.dccp.state = new_state;
++	write_unlock_bh(&dccp_lock);
++	nf_ct_refresh_acct(ct, ctinfo, skb, dccp_timeout[new_state]);
++
++	return NF_ACCEPT;
++}
++
++static int dccp_error(struct sk_buff *skb, unsigned int dataoff,
++		      enum ip_conntrack_info *ctinfo, int pf,
++		      unsigned int hooknum)
++{
++	struct dccp_hdr _dh, *dh;
++	unsigned int dccp_len = skb->len - dataoff;
++	unsigned int cscov;
++	const char *msg;
++
++	dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
++	if (dh == NULL) {
++		msg = "nf_ct_dccp: short packet ";
++		goto out_invalid;
++	}
++
++	if (dh->dccph_doff * 4 < sizeof(struct dccp_hdr) ||
++	    dh->dccph_doff * 4 > dccp_len) {
++		msg = "nf_ct_dccp: truncated/malformed packet ";
++		goto out_invalid;
++	}
++
++	cscov = dccp_len;
++	if (dh->dccph_cscov) {
++		cscov = (dh->dccph_cscov - 1) * 4;
++		if (cscov > dccp_len) {
++			msg = "nf_ct_dccp: bad checksum coverage ";
++			goto out_invalid;
++		}
++	}
++
++	if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
++	    nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_DCCP,
++				pf)) {
++		msg = "nf_ct_dccp: bad checksum ";
++		goto out_invalid;
++	}
++
++	if (dh->dccph_type >= DCCP_PKT_INVALID) {
++		msg = "nf_ct_dccp: reserved packet type ";
++		goto out_invalid;
++	}
++
++	return NF_ACCEPT;
++
++out_invalid:
++	if (LOG_INVALID(IPPROTO_DCCP))
++		nf_log_packet(pf, 0, skb, NULL, NULL, NULL, msg);
++	return -NF_ACCEPT;
++}
++
++static int dccp_print_tuple(struct seq_file *s,
++			    const struct nf_conntrack_tuple *tuple)
++{
++	return seq_printf(s, "sport=%hu dport=%hu ",
++			  ntohs(tuple->src.u.dccp.port),
++			  ntohs(tuple->dst.u.dccp.port));
++}
++
++static int dccp_print_conntrack(struct seq_file *s, const struct nf_conn *ct)
++{
++	return seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]);
++}
++
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
++			  const struct nf_conn *ct)
++{
++	struct nlattr *nest_parms;
++
++	read_lock_bh(&dccp_lock);
++	nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED);
++	if (!nest_parms)
++		goto nla_put_failure;
++	NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state);
++	nla_nest_end(skb, nest_parms);
++	read_unlock_bh(&dccp_lock);
++	return 0;
++
++nla_put_failure:
++	read_unlock_bh(&dccp_lock);
++	return -1;
++}
++
++static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = {
++	[CTA_PROTOINFO_DCCP_STATE]	= { .type = NLA_U8 },
++};
++
++static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
++{
++	struct nlattr *attr = cda[CTA_PROTOINFO_DCCP];
++	struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX + 1];
++	int err;
++
++	if (!attr)
++		return 0;
++
++	err = nla_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr,
++			       dccp_nla_policy);
++	if (err < 0)
++		return err;
++
++	if (!tb[CTA_PROTOINFO_DCCP_STATE] ||
++	    nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE)
++		return -EINVAL;
++
++	write_lock_bh(&dccp_lock);
++	ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
++	write_unlock_bh(&dccp_lock);
++	return 0;
++}
++#endif
++
++#ifdef CONFIG_SYSCTL
++static unsigned int dccp_sysctl_table_users;
++static struct ctl_table_header *dccp_sysctl_header;
++static ctl_table dccp_sysctl_table[] = {
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "nf_conntrack_dccp_timeout_request",
++		.data		= &dccp_timeout[CT_DCCP_REQUEST],
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec_jiffies,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "nf_conntrack_dccp_timeout_respond",
++		.data		= &dccp_timeout[CT_DCCP_RESPOND],
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec_jiffies,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "nf_conntrack_dccp_timeout_partopen",
++		.data		= &dccp_timeout[CT_DCCP_PARTOPEN],
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec_jiffies,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "nf_conntrack_dccp_timeout_open",
++		.data		= &dccp_timeout[CT_DCCP_OPEN],
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec_jiffies,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "nf_conntrack_dccp_timeout_closereq",
++		.data		= &dccp_timeout[CT_DCCP_CLOSEREQ],
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec_jiffies,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "nf_conntrack_dccp_timeout_closing",
++		.data		= &dccp_timeout[CT_DCCP_CLOSING],
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec_jiffies,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "nf_conntrack_dccp_timeout_timewait",
++		.data		= &dccp_timeout[CT_DCCP_TIMEWAIT],
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec_jiffies,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "nf_conntrack_dccp_loose",
++		.data		= &nf_ct_dccp_loose,
++		.maxlen		= sizeof(nf_ct_dccp_loose),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec,
++	},
++	{
++		.ctl_name	= 0,
++	}
++};
++#endif /* CONFIG_SYSCTL */
++
++static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
++	.l3proto		= AF_INET,
++	.l4proto		= IPPROTO_DCCP,
++	.name			= "dccp",
++	.pkt_to_tuple		= dccp_pkt_to_tuple,
++	.invert_tuple		= dccp_invert_tuple,
++	.new			= dccp_new,
++	.packet			= dccp_packet,
++	.error			= dccp_error,
++	.print_tuple		= dccp_print_tuple,
++	.print_conntrack	= dccp_print_conntrack,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++	.to_nlattr		= dccp_to_nlattr,
++	.from_nlattr		= nlattr_to_dccp,
++	.tuple_to_nlattr	= nf_ct_port_tuple_to_nlattr,
++	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
++	.nla_policy		= nf_ct_port_nla_policy,
++#endif
++#ifdef CONFIG_SYSCTL
++	.ctl_table_users	= &dccp_sysctl_table_users,
++	.ctl_table_header	= &dccp_sysctl_header,
++	.ctl_table		= dccp_sysctl_table,
++#endif
++};
++
++static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
++	.l3proto		= AF_INET6,
++	.l4proto		= IPPROTO_DCCP,
++	.name			= "dccp",
++	.pkt_to_tuple		= dccp_pkt_to_tuple,
++	.invert_tuple		= dccp_invert_tuple,
++	.new			= dccp_new,
++	.packet			= dccp_packet,
++	.error			= dccp_error,
++	.print_tuple		= dccp_print_tuple,
++	.print_conntrack	= dccp_print_conntrack,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++	.to_nlattr		= dccp_to_nlattr,
++	.from_nlattr		= nlattr_to_dccp,
++	.tuple_to_nlattr	= nf_ct_port_tuple_to_nlattr,
++	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
++	.nla_policy		= nf_ct_port_nla_policy,
++#endif
++#ifdef CONFIG_SYSCTL
++	.ctl_table_users	= &dccp_sysctl_table_users,
++	.ctl_table_header	= &dccp_sysctl_header,
++	.ctl_table		= dccp_sysctl_table,
++#endif
++};
++
++static int __init nf_conntrack_proto_dccp_init(void)
++{
++	int err;
++
++	err = nf_conntrack_l4proto_register(&dccp_proto4);
++	if (err < 0)
++		goto err1;
++
++	err = nf_conntrack_l4proto_register(&dccp_proto6);
++	if (err < 0)
++		goto err2;
++	return 0;
++
++err2:
++	nf_conntrack_l4proto_unregister(&dccp_proto4);
++err1:
++	return err;
++}
++
++static void __exit nf_conntrack_proto_dccp_fini(void)
++{
++	nf_conntrack_l4proto_unregister(&dccp_proto6);
++	nf_conntrack_l4proto_unregister(&dccp_proto4);
++}
++
++module_init(nf_conntrack_proto_dccp_init);
++module_exit(nf_conntrack_proto_dccp_fini);
++
++MODULE_AUTHOR("Patrick McHardy <kaber at trash.net>");
++MODULE_DESCRIPTION("DCCP connection tracking protocol helper");
++MODULE_LICENSE("GPL");
+diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
+index 5545891..e31b0e7 100644
+--- a/net/netfilter/nf_conntrack_proto_generic.c
++++ b/net/netfilter/nf_conntrack_proto_generic.c
+@@ -14,23 +14,23 @@
+ 
+ static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
+ 
+-static int generic_pkt_to_tuple(const struct sk_buff *skb,
+-				unsigned int dataoff,
+-				struct nf_conntrack_tuple *tuple)
++static bool generic_pkt_to_tuple(const struct sk_buff *skb,
++				 unsigned int dataoff,
++				 struct nf_conntrack_tuple *tuple)
+ {
+ 	tuple->src.u.all = 0;
+ 	tuple->dst.u.all = 0;
+ 
+-	return 1;
++	return true;
+ }
+ 
+-static int generic_invert_tuple(struct nf_conntrack_tuple *tuple,
+-				const struct nf_conntrack_tuple *orig)
++static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
++				 const struct nf_conntrack_tuple *orig)
+ {
+ 	tuple->src.u.all = 0;
+ 	tuple->dst.u.all = 0;
+ 
+-	return 1;
++	return true;
+ }
+ 
+ /* Print out the per-protocol part of the tuple. */
+@@ -53,10 +53,10 @@ static int packet(struct nf_conn *ct,
+ }
+ 
+ /* Called when a new connection for this protocol found. */
+-static int new(struct nf_conn *ct, const struct sk_buff *skb,
+-	       unsigned int dataoff)
++static bool new(struct nf_conn *ct, const struct sk_buff *skb,
++		unsigned int dataoff)
+ {
+-	return 1;
++	return true;
+ }
+ 
+ #ifdef CONFIG_SYSCTL
+diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
+index e10024a..654a4f7 100644
+--- a/net/netfilter/nf_conntrack_proto_gre.c
++++ b/net/netfilter/nf_conntrack_proto_gre.c
+@@ -82,7 +82,7 @@ static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t)
+ 	read_unlock_bh(&nf_ct_gre_lock);
+ 
+ 	pr_debug("lookup src key 0x%x for ", key);
+-	NF_CT_DUMP_TUPLE(t);
++	nf_ct_dump_tuple(t);
+ 
+ 	return key;
+ }
+@@ -113,7 +113,7 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
+ 	*kmp = km;
+ 
+ 	pr_debug("adding new entry %p: ", km);
+-	NF_CT_DUMP_TUPLE(&km->tuple);
++	nf_ct_dump_tuple(&km->tuple);
+ 
+ 	write_lock_bh(&nf_ct_gre_lock);
+ 	list_add_tail(&km->list, &gre_keymap_list);
+@@ -148,18 +148,17 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy);
+ /* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
+ 
+ /* invert gre part of tuple */
+-static int gre_invert_tuple(struct nf_conntrack_tuple *tuple,
+-			    const struct nf_conntrack_tuple *orig)
++static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple,
++			     const struct nf_conntrack_tuple *orig)
+ {
+ 	tuple->dst.u.gre.key = orig->src.u.gre.key;
+ 	tuple->src.u.gre.key = orig->dst.u.gre.key;
+-	return 1;
++	return true;
+ }
+ 
+ /* gre hdr info to tuple */
+-static int gre_pkt_to_tuple(const struct sk_buff *skb,
+-			   unsigned int dataoff,
+-			   struct nf_conntrack_tuple *tuple)
++static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++			     struct nf_conntrack_tuple *tuple)
+ {
+ 	const struct gre_hdr_pptp *pgrehdr;
+ 	struct gre_hdr_pptp _pgrehdr;
+@@ -173,24 +172,24 @@ static int gre_pkt_to_tuple(const struct sk_buff *skb,
+ 		/* try to behave like "nf_conntrack_proto_generic" */
+ 		tuple->src.u.all = 0;
+ 		tuple->dst.u.all = 0;
+-		return 1;
++		return true;
+ 	}
+ 
+ 	/* PPTP header is variable length, only need up to the call_id field */
+ 	pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr);
+ 	if (!pgrehdr)
+-		return 1;
++		return true;
+ 
+ 	if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
+ 		pr_debug("GRE_VERSION_PPTP but unknown proto\n");
+-		return 0;
++		return false;
+ 	}
+ 
+ 	tuple->dst.u.gre.key = pgrehdr->call_id;
+ 	srckey = gre_keymap_lookup(tuple);
+ 	tuple->src.u.gre.key = srckey;
+ 
+-	return 1;
++	return true;
+ }
+ 
+ /* print gre part of tuple */
+@@ -235,18 +234,18 @@ static int gre_packet(struct nf_conn *ct,
+ }
+ 
+ /* Called when a new connection for this protocol found. */
+-static int gre_new(struct nf_conn *ct, const struct sk_buff *skb,
+-		   unsigned int dataoff)
++static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb,
++		    unsigned int dataoff)
+ {
+ 	pr_debug(": ");
+-	NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++	nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ 
+ 	/* initialize to sane value.  Ideally a conntrack helper
+ 	 * (e.g. in case of pptp) is increasing them */
+ 	ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
+ 	ct->proto.gre.timeout = GRE_TIMEOUT;
+ 
+-	return 1;
++	return true;
+ }
+ 
+ /* Called when a conntrack entry has already been removed from the hashes
+diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
+index f9a0837..cbf2e27 100644
+--- a/net/netfilter/nf_conntrack_proto_sctp.c
++++ b/net/netfilter/nf_conntrack_proto_sctp.c
+@@ -33,7 +33,7 @@ static DEFINE_RWLOCK(sctp_lock);
+ 
+    And so for me for SCTP :D -Kiran */
+ 
+-static const char *sctp_conntrack_names[] = {
++static const char *const sctp_conntrack_names[] = {
+ 	"NONE",
+ 	"CLOSED",
+ 	"COOKIE_WAIT",
+@@ -130,28 +130,28 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
+ 	}
+ };
+ 
+-static int sctp_pkt_to_tuple(const struct sk_buff *skb,
+-			     unsigned int dataoff,
+-			     struct nf_conntrack_tuple *tuple)
++static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++			      struct nf_conntrack_tuple *tuple)
+ {
+-	sctp_sctphdr_t _hdr, *hp;
++	const struct sctphdr *hp;
++	struct sctphdr _hdr;
+ 
+ 	/* Actually only need first 8 bytes. */
+ 	hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
+ 	if (hp == NULL)
+-		return 0;
++		return false;
+ 
+ 	tuple->src.u.sctp.port = hp->source;
+ 	tuple->dst.u.sctp.port = hp->dest;
+-	return 1;
++	return true;
+ }
+ 
+-static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
+-			     const struct nf_conntrack_tuple *orig)
++static bool sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
++			      const struct nf_conntrack_tuple *orig)
+ {
+ 	tuple->src.u.sctp.port = orig->dst.u.sctp.port;
+ 	tuple->dst.u.sctp.port = orig->src.u.sctp.port;
+-	return 1;
++	return true;
+ }
+ 
+ /* Print out the per-protocol part of the tuple. */
+@@ -292,8 +292,10 @@ static int sctp_packet(struct nf_conn *ct,
+ {
+ 	enum sctp_conntrack new_state, old_state;
+ 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+-	sctp_sctphdr_t _sctph, *sh;
+-	sctp_chunkhdr_t _sch, *sch;
++	const struct sctphdr *sh;
++	struct sctphdr _sctph;
++	const struct sctp_chunkhdr *sch;
++	struct sctp_chunkhdr _sch;
+ 	u_int32_t offset, count;
+ 	unsigned long map[256 / sizeof(unsigned long)] = { 0 };
+ 
+@@ -390,27 +392,29 @@ out:
+ }
+ 
+ /* Called when a new connection for this protocol found. */
+-static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+-		    unsigned int dataoff)
++static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
++		     unsigned int dataoff)
+ {
+ 	enum sctp_conntrack new_state;
+-	sctp_sctphdr_t _sctph, *sh;
+-	sctp_chunkhdr_t _sch, *sch;
++	const struct sctphdr *sh;
++	struct sctphdr _sctph;
++	const struct sctp_chunkhdr *sch;
++	struct sctp_chunkhdr _sch;
+ 	u_int32_t offset, count;
+ 	unsigned long map[256 / sizeof(unsigned long)] = { 0 };
+ 
+ 	sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
+ 	if (sh == NULL)
+-		return 0;
++		return false;
+ 
+ 	if (do_basic_checks(ct, skb, dataoff, map) != 0)
+-		return 0;
++		return false;
+ 
+ 	/* If an OOTB packet has any of these chunks discard (Sec 8.4) */
+ 	if (test_bit(SCTP_CID_ABORT, map) ||
+ 	    test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) ||
+ 	    test_bit(SCTP_CID_COOKIE_ACK, map))
+-		return 0;
++		return false;
+ 
+ 	new_state = SCTP_CONNTRACK_MAX;
+ 	for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
+@@ -422,7 +426,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ 		if (new_state == SCTP_CONNTRACK_NONE ||
+ 		    new_state == SCTP_CONNTRACK_MAX) {
+ 			pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
+-			return 0;
++			return false;
+ 		}
+ 
+ 		/* Copy the vtag into the state info */
+@@ -433,7 +437,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ 				ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
+ 							sizeof(_inithdr), &_inithdr);
+ 				if (ih == NULL)
+-					return 0;
++					return false;
+ 
+ 				pr_debug("Setting vtag %x for new conn\n",
+ 					 ih->init_tag);
+@@ -442,7 +446,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ 								ih->init_tag;
+ 			} else {
+ 				/* Sec 8.5.1 (A) */
+-				return 0;
++				return false;
+ 			}
+ 		}
+ 		/* If it is a shutdown ack OOTB packet, we expect a return
+@@ -456,7 +460,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ 		ct->proto.sctp.state = new_state;
+ 	}
+ 
+-	return 1;
++	return true;
+ }
+ 
+ #ifdef CONFIG_SYSCTL
+diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
+index 6256795..ba94004 100644
+--- a/net/netfilter/nf_conntrack_proto_tcp.c
++++ b/net/netfilter/nf_conntrack_proto_tcp.c
+@@ -257,9 +257,8 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
+ 	}
+ };
+ 
+-static int tcp_pkt_to_tuple(const struct sk_buff *skb,
+-			    unsigned int dataoff,
+-			    struct nf_conntrack_tuple *tuple)
++static bool tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++			     struct nf_conntrack_tuple *tuple)
+ {
+ 	const struct tcphdr *hp;
+ 	struct tcphdr _hdr;
+@@ -267,20 +266,20 @@ static int tcp_pkt_to_tuple(const struct sk_buff *skb,
+ 	/* Actually only need first 8 bytes. */
+ 	hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
+ 	if (hp == NULL)
+-		return 0;
++		return false;
+ 
+ 	tuple->src.u.tcp.port = hp->source;
+ 	tuple->dst.u.tcp.port = hp->dest;
+ 
+-	return 1;
++	return true;
+ }
+ 
+-static int tcp_invert_tuple(struct nf_conntrack_tuple *tuple,
+-			    const struct nf_conntrack_tuple *orig)
++static bool tcp_invert_tuple(struct nf_conntrack_tuple *tuple,
++			     const struct nf_conntrack_tuple *orig)
+ {
+ 	tuple->src.u.tcp.port = orig->dst.u.tcp.port;
+ 	tuple->dst.u.tcp.port = orig->src.u.tcp.port;
+-	return 1;
++	return true;
+ }
+ 
+ /* Print out the per-protocol part of the tuple. */
+@@ -478,20 +477,20 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
+ 	}
+ }
+ 
+-static int tcp_in_window(const struct nf_conn *ct,
+-			 struct ip_ct_tcp *state,
+-			 enum ip_conntrack_dir dir,
+-			 unsigned int index,
+-			 const struct sk_buff *skb,
+-			 unsigned int dataoff,
+-			 const struct tcphdr *tcph,
+-			 int pf)
++static bool tcp_in_window(const struct nf_conn *ct,
++			  struct ip_ct_tcp *state,
++			  enum ip_conntrack_dir dir,
++			  unsigned int index,
++			  const struct sk_buff *skb,
++			  unsigned int dataoff,
++			  const struct tcphdr *tcph,
++			  int pf)
+ {
+ 	struct ip_ct_tcp_state *sender = &state->seen[dir];
+ 	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
+ 	const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
+ 	__u32 seq, ack, sack, end, win, swin;
+-	int res;
++	bool res;
+ 
+ 	/*
+ 	 * Get the required data from the packet.
+@@ -506,7 +505,7 @@ static int tcp_in_window(const struct nf_conn *ct,
+ 
+ 	pr_debug("tcp_in_window: START\n");
+ 	pr_debug("tcp_in_window: ");
+-	NF_CT_DUMP_TUPLE(tuple);
++	nf_ct_dump_tuple(tuple);
+ 	pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n",
+ 		 seq, ack, sack, win, end);
+ 	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+@@ -593,7 +592,7 @@ static int tcp_in_window(const struct nf_conn *ct,
+ 		seq = end = sender->td_end;
+ 
+ 	pr_debug("tcp_in_window: ");
+-	NF_CT_DUMP_TUPLE(tuple);
++	nf_ct_dump_tuple(tuple);
+ 	pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n",
+ 		 seq, ack, sack, win, end);
+ 	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+@@ -657,12 +656,12 @@ static int tcp_in_window(const struct nf_conn *ct,
+ 				state->retrans = 0;
+ 			}
+ 		}
+-		res = 1;
++		res = true;
+ 	} else {
+-		res = 0;
++		res = false;
+ 		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
+ 		    nf_ct_tcp_be_liberal)
+-			res = 1;
++			res = true;
+ 		if (!res && LOG_INVALID(IPPROTO_TCP))
+ 			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+ 			"nf_ct_tcp: %s ",
+@@ -676,7 +675,7 @@ static int tcp_in_window(const struct nf_conn *ct,
+ 			: "SEQ is over the upper bound (over the window of the receiver)");
+ 	}
+ 
+-	pr_debug("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
++	pr_debug("tcp_in_window: res=%u sender end=%u maxend=%u maxwin=%u "
+ 		 "receiver end=%u maxend=%u maxwin=%u\n",
+ 		 res, sender->td_end, sender->td_maxend, sender->td_maxwin,
+ 		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
+@@ -937,7 +936,7 @@ static int tcp_packet(struct nf_conn *ct,
+ 	ct->proto.tcp.last_dir = dir;
+ 
+ 	pr_debug("tcp_conntracks: ");
+-	NF_CT_DUMP_TUPLE(tuple);
++	nf_ct_dump_tuple(tuple);
+ 	pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
+ 		 (th->syn ? 1 : 0), (th->ack ? 1 : 0),
+ 		 (th->fin ? 1 : 0), (th->rst ? 1 : 0),
+@@ -982,9 +981,8 @@ static int tcp_packet(struct nf_conn *ct,
+ }
+ 
+ /* Called when a new connection for this protocol found. */
+-static int tcp_new(struct nf_conn *ct,
+-		   const struct sk_buff *skb,
+-		   unsigned int dataoff)
++static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
++		    unsigned int dataoff)
+ {
+ 	enum tcp_conntrack new_state;
+ 	const struct tcphdr *th;
+@@ -1003,7 +1001,7 @@ static int tcp_new(struct nf_conn *ct,
+ 	/* Invalid: delete conntrack */
+ 	if (new_state >= TCP_CONNTRACK_MAX) {
+ 		pr_debug("nf_ct_tcp: invalid new deleting.\n");
+-		return 0;
++		return false;
+ 	}
+ 
+ 	if (new_state == TCP_CONNTRACK_SYN_SENT) {
+@@ -1021,7 +1019,7 @@ static int tcp_new(struct nf_conn *ct,
+ 		ct->proto.tcp.seen[1].flags = 0;
+ 	} else if (nf_ct_tcp_loose == 0) {
+ 		/* Don't try to pick up connections. */
+-		return 0;
++		return false;
+ 	} else {
+ 		/*
+ 		 * We are in the middle of a connection,
+@@ -1061,7 +1059,7 @@ static int tcp_new(struct nf_conn *ct,
+ 		 sender->td_scale,
+ 		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+ 		 receiver->td_scale);
+-	return 1;
++	return true;
+ }
+ 
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+@@ -1129,11 +1127,13 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
+ 	if (err < 0)
+ 		return err;
+ 
+-	if (!tb[CTA_PROTOINFO_TCP_STATE])
++	if (tb[CTA_PROTOINFO_TCP_STATE] &&
++	    nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX)
+ 		return -EINVAL;
+ 
+ 	write_lock_bh(&tcp_lock);
+-	ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
++	if (tb[CTA_PROTOINFO_TCP_STATE])
++		ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
+ 
+ 	if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]) {
+ 		struct nf_ct_tcp_flags *attr =
+diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
+index b8a35cc..8b21762 100644
+--- a/net/netfilter/nf_conntrack_proto_udp.c
++++ b/net/netfilter/nf_conntrack_proto_udp.c
+@@ -26,7 +26,7 @@
+ static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
+ static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
+ 
+-static int udp_pkt_to_tuple(const struct sk_buff *skb,
++static bool udp_pkt_to_tuple(const struct sk_buff *skb,
+ 			     unsigned int dataoff,
+ 			     struct nf_conntrack_tuple *tuple)
+ {
+@@ -36,20 +36,20 @@ static int udp_pkt_to_tuple(const struct sk_buff *skb,
+ 	/* Actually only need first 8 bytes. */
+ 	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ 	if (hp == NULL)
+-		return 0;
++		return false;
+ 
+ 	tuple->src.u.udp.port = hp->source;
+ 	tuple->dst.u.udp.port = hp->dest;
+ 
+-	return 1;
++	return true;
+ }
+ 
+-static int udp_invert_tuple(struct nf_conntrack_tuple *tuple,
+-			    const struct nf_conntrack_tuple *orig)
++static bool udp_invert_tuple(struct nf_conntrack_tuple *tuple,
++			     const struct nf_conntrack_tuple *orig)
+ {
+ 	tuple->src.u.udp.port = orig->dst.u.udp.port;
+ 	tuple->dst.u.udp.port = orig->src.u.udp.port;
+-	return 1;
++	return true;
+ }
+ 
+ /* Print out the per-protocol part of the tuple. */
+@@ -83,10 +83,10 @@ static int udp_packet(struct nf_conn *ct,
+ }
+ 
+ /* Called when a new connection for this protocol found. */
+-static int udp_new(struct nf_conn *ct, const struct sk_buff *skb,
+-		   unsigned int dataoff)
++static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
++		    unsigned int dataoff)
+ {
+-	return 1;
++	return true;
+ }
+ 
+ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
+diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
+index 9dd03c7..1fa62f3 100644
+--- a/net/netfilter/nf_conntrack_proto_udplite.c
++++ b/net/netfilter/nf_conntrack_proto_udplite.c
+@@ -27,28 +27,28 @@
+ static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ;
+ static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ;
+ 
+-static int udplite_pkt_to_tuple(const struct sk_buff *skb,
+-				unsigned int dataoff,
+-				struct nf_conntrack_tuple *tuple)
++static bool udplite_pkt_to_tuple(const struct sk_buff *skb,
++				 unsigned int dataoff,
++				 struct nf_conntrack_tuple *tuple)
+ {
+ 	const struct udphdr *hp;
+ 	struct udphdr _hdr;
+ 
+ 	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ 	if (hp == NULL)
+-		return 0;
++		return false;
+ 
+ 	tuple->src.u.udp.port = hp->source;
+ 	tuple->dst.u.udp.port = hp->dest;
+-	return 1;
++	return true;
+ }
+ 
+-static int udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
+-				const struct nf_conntrack_tuple *orig)
++static bool udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
++				 const struct nf_conntrack_tuple *orig)
+ {
+ 	tuple->src.u.udp.port = orig->dst.u.udp.port;
+ 	tuple->dst.u.udp.port = orig->src.u.udp.port;
+-	return 1;
++	return true;
+ }
+ 
+ /* Print out the per-protocol part of the tuple. */
+@@ -83,10 +83,10 @@ static int udplite_packet(struct nf_conn *ct,
+ }
+ 
+ /* Called when a new connection for this protocol found. */
+-static int udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
+-		       unsigned int dataoff)
++static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
++			unsigned int dataoff)
+ {
+-	return 1;
++	return true;
+ }
+ 
+ static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
+@@ -127,32 +127,13 @@ static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
+ 	}
+ 
+ 	/* Checksum invalid? Ignore. */
+-	if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) &&
+-	    hooknum == NF_INET_PRE_ROUTING) {
+-		if (pf == PF_INET) {
+-			struct iphdr *iph = ip_hdr(skb);
+-
+-			skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+-						       udplen, IPPROTO_UDPLITE, 0);
+-		} else {
+-			struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+-			__wsum hsum = skb_checksum(skb, 0, dataoff, 0);
+-
+-			skb->csum = ~csum_unfold(
+-				csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
+-						udplen, IPPROTO_UDPLITE,
+-						csum_sub(0, hsum)));
+-		}
+-
+-		skb->ip_summed = CHECKSUM_NONE;
+-		if (__skb_checksum_complete_head(skb, dataoff + cscov)) {
+-			if (LOG_INVALID(IPPROTO_UDPLITE))
+-				nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+-					      "nf_ct_udplite: bad UDPLite "
+-					      "checksum ");
+-			return -NF_ACCEPT;
+-		}
+-		skb->ip_summed = CHECKSUM_UNNECESSARY;
++	if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
++	    nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
++	    			pf)) {
++		if (LOG_INVALID(IPPROTO_UDPLITE))
++			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
++				      "nf_ct_udplite: bad UDPLite checksum ");
++		return -NF_ACCEPT;
+ 	}
+ 
+ 	return NF_ACCEPT;
+diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
+index a70051d..a94294b 100644
+--- a/net/netfilter/nf_conntrack_sane.c
++++ b/net/netfilter/nf_conntrack_sane.c
+@@ -72,7 +72,6 @@ static int help(struct sk_buff *skb,
+ 	struct nf_conntrack_tuple *tuple;
+ 	struct sane_request *req;
+ 	struct sane_reply_net_start *reply;
+-	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ 
+ 	ct_sane_info = &nfct_help(ct)->help.ct_sane_info;
+ 	/* Until there's been traffic both ways, don't look in packets. */
+@@ -143,11 +142,12 @@ static int help(struct sk_buff *skb,
+ 	}
+ 
+ 	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+-	nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
++	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
++			  &tuple->src.u3, &tuple->dst.u3,
+ 			  IPPROTO_TCP, NULL, &reply->port);
+ 
+ 	pr_debug("nf_ct_sane: expect: ");
+-	NF_CT_DUMP_TUPLE(&exp->tuple);
++	nf_ct_dump_tuple(&exp->tuple);
+ 
+ 	/* Can't expect this?  Best to drop packet now. */
+ 	if (nf_ct_expect_related(exp) != 0)
+@@ -163,6 +163,11 @@ out:
+ static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly;
+ static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly;
+ 
++static const struct nf_conntrack_expect_policy sane_exp_policy = {
++	.max_expected	= 1,
++	.timeout	= 5 * 60,
++};
++
+ /* don't make this __exit, since it's called from __init ! */
+ static void nf_conntrack_sane_fini(void)
+ {
+@@ -200,8 +205,7 @@ static int __init nf_conntrack_sane_init(void)
+ 		for (j = 0; j < 2; j++) {
+ 			sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
+ 			sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
+-			sane[i][j].max_expected = 1;
+-			sane[i][j].timeout = 5 * 60;	/* 5 Minutes */
++			sane[i][j].expect_policy = &sane_exp_policy;
+ 			sane[i][j].me = THIS_MODULE;
+ 			sane[i][j].help = help;
+ 			tmpname = &sane_names[i][j][0];
+diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
+index c521c89..9f49000 100644
+--- a/net/netfilter/nf_conntrack_sip.c
++++ b/net/netfilter/nf_conntrack_sip.c
+@@ -2,6 +2,8 @@
+  *
+  * (C) 2005 by Christian Hentschel <chentschel at arnet.com.ar>
+  * based on RR's ip_conntrack_ftp.c and other modules.
++ * (C) 2007 United Security Providers
++ * (C) 2007, 2008 Patrick McHardy <kaber at trash.net>
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+@@ -17,6 +19,7 @@
+ #include <linux/netfilter.h>
+ 
+ #include <net/netfilter/nf_conntrack.h>
++#include <net/netfilter/nf_conntrack_core.h>
+ #include <net/netfilter/nf_conntrack_expect.h>
+ #include <net/netfilter/nf_conntrack_helper.h>
+ #include <linux/netfilter/nf_conntrack_sip.h>
+@@ -36,214 +39,102 @@ static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT;
+ module_param(sip_timeout, uint, 0600);
+ MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
+ 
++static int sip_direct_signalling __read_mostly = 1;
++module_param(sip_direct_signalling, int, 0600);
++MODULE_PARM_DESC(sip_direct_signalling, "expect incoming calls from registrar "
++					"only (default 1)");
++
++static int sip_direct_media __read_mostly = 1;
++module_param(sip_direct_media, int, 0600);
++MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
++				   "endpoints only (default 1)");
++
+ unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
+-				enum ip_conntrack_info ctinfo,
+-				struct nf_conn *ct,
+-				const char **dptr) __read_mostly;
++				const char **dptr,
++				unsigned int *datalen) __read_mostly;
+ EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
+ 
+-unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
+-				enum ip_conntrack_info ctinfo,
+-				struct nf_conntrack_expect *exp,
+-				const char *dptr) __read_mostly;
+-EXPORT_SYMBOL_GPL(nf_nat_sdp_hook);
+-
+-static int digits_len(const struct nf_conn *, const char *, const char *, int *);
+-static int epaddr_len(const struct nf_conn *, const char *, const char *, int *);
+-static int skp_digits_len(const struct nf_conn *, const char *, const char *, int *);
+-static int skp_epaddr_len(const struct nf_conn *, const char *, const char *, int *);
+-
+-struct sip_header_nfo {
+-	const char	*lname;
+-	const char	*sname;
+-	const char	*ln_str;
+-	size_t		lnlen;
+-	size_t		snlen;
+-	size_t		ln_strlen;
+-	int		case_sensitive;
+-	int		(*match_len)(const struct nf_conn *, const char *,
+-				     const char *, int *);
+-};
++unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
++				       const char **dptr,
++				       unsigned int *datalen,
++				       struct nf_conntrack_expect *exp,
++				       unsigned int matchoff,
++				       unsigned int matchlen) __read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook);
+ 
+-static const struct sip_header_nfo ct_sip_hdrs[] = {
+-	[POS_REG_REQ_URI] = { 	/* SIP REGISTER request URI */
+-		.lname		= "sip:",
+-		.lnlen		= sizeof("sip:") - 1,
+-		.ln_str		= ":",
+-		.ln_strlen	= sizeof(":") - 1,
+-		.match_len	= epaddr_len,
+-	},
+-	[POS_REQ_URI] = { 	/* SIP request URI */
+-		.lname		= "sip:",
+-		.lnlen		= sizeof("sip:") - 1,
+-		.ln_str		= "@",
+-		.ln_strlen	= sizeof("@") - 1,
+-		.match_len	= epaddr_len,
+-	},
+-	[POS_FROM] = {		/* SIP From header */
+-		.lname		= "From:",
+-		.lnlen		= sizeof("From:") - 1,
+-		.sname		= "\r\nf:",
+-		.snlen		= sizeof("\r\nf:") - 1,
+-		.ln_str		= "sip:",
+-		.ln_strlen	= sizeof("sip:") - 1,
+-		.match_len	= skp_epaddr_len,
+-	},
+-	[POS_TO] = {		/* SIP To header */
+-		.lname		= "To:",
+-		.lnlen		= sizeof("To:") - 1,
+-		.sname		= "\r\nt:",
+-		.snlen		= sizeof("\r\nt:") - 1,
+-		.ln_str		= "sip:",
+-		.ln_strlen	= sizeof("sip:") - 1,
+-		.match_len	= skp_epaddr_len
+-	},
+-	[POS_VIA] = { 		/* SIP Via header */
+-		.lname		= "Via:",
+-		.lnlen		= sizeof("Via:") - 1,
+-		.sname		= "\r\nv:",
+-		.snlen		= sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */
+-		.ln_str		= "UDP ",
+-		.ln_strlen	= sizeof("UDP ") - 1,
+-		.match_len	= epaddr_len,
+-	},
+-	[POS_CONTACT] = { 	/* SIP Contact header */
+-		.lname		= "Contact:",
+-		.lnlen		= sizeof("Contact:") - 1,
+-		.sname		= "\r\nm:",
+-		.snlen		= sizeof("\r\nm:") - 1,
+-		.ln_str		= "sip:",
+-		.ln_strlen	= sizeof("sip:") - 1,
+-		.match_len	= skp_epaddr_len
+-	},
+-	[POS_CONTENT] = { 	/* SIP Content length header */
+-		.lname		= "Content-Length:",
+-		.lnlen		= sizeof("Content-Length:") - 1,
+-		.sname		= "\r\nl:",
+-		.snlen		= sizeof("\r\nl:") - 1,
+-		.ln_str		= ":",
+-		.ln_strlen	= sizeof(":") - 1,
+-		.match_len	= skp_digits_len
+-	},
+-	[POS_MEDIA] = {		/* SDP media info */
+-		.case_sensitive	= 1,
+-		.lname		= "\nm=",
+-		.lnlen		= sizeof("\nm=") - 1,
+-		.sname		= "\rm=",
+-		.snlen		= sizeof("\rm=") - 1,
+-		.ln_str		= "audio ",
+-		.ln_strlen	= sizeof("audio ") - 1,
+-		.match_len	= digits_len
+-	},
+-	[POS_OWNER_IP4] = {	/* SDP owner address*/
+-		.case_sensitive	= 1,
+-		.lname		= "\no=",
+-		.lnlen		= sizeof("\no=") - 1,
+-		.sname		= "\ro=",
+-		.snlen		= sizeof("\ro=") - 1,
+-		.ln_str		= "IN IP4 ",
+-		.ln_strlen	= sizeof("IN IP4 ") - 1,
+-		.match_len	= epaddr_len
+-	},
+-	[POS_CONNECTION_IP4] = {/* SDP connection info */
+-		.case_sensitive	= 1,
+-		.lname		= "\nc=",
+-		.lnlen		= sizeof("\nc=") - 1,
+-		.sname		= "\rc=",
+-		.snlen		= sizeof("\rc=") - 1,
+-		.ln_str		= "IN IP4 ",
+-		.ln_strlen	= sizeof("IN IP4 ") - 1,
+-		.match_len	= epaddr_len
+-	},
+-	[POS_OWNER_IP6] = {	/* SDP owner address*/
+-		.case_sensitive	= 1,
+-		.lname		= "\no=",
+-		.lnlen		= sizeof("\no=") - 1,
+-		.sname		= "\ro=",
+-		.snlen		= sizeof("\ro=") - 1,
+-		.ln_str		= "IN IP6 ",
+-		.ln_strlen	= sizeof("IN IP6 ") - 1,
+-		.match_len	= epaddr_len
+-	},
+-	[POS_CONNECTION_IP6] = {/* SDP connection info */
+-		.case_sensitive	= 1,
+-		.lname		= "\nc=",
+-		.lnlen		= sizeof("\nc=") - 1,
+-		.sname		= "\rc=",
+-		.snlen		= sizeof("\rc=") - 1,
+-		.ln_str		= "IN IP6 ",
+-		.ln_strlen	= sizeof("IN IP6 ") - 1,
+-		.match_len	= epaddr_len
+-	},
+-	[POS_SDP_HEADER] = { 	/* SDP version header */
+-		.case_sensitive	= 1,
+-		.lname		= "\nv=",
+-		.lnlen		= sizeof("\nv=") - 1,
+-		.sname		= "\rv=",
+-		.snlen		= sizeof("\rv=") - 1,
+-		.ln_str		= "=",
+-		.ln_strlen	= sizeof("=") - 1,
+-		.match_len	= digits_len
+-	}
+-};
++unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
++				     const char **dptr,
++				     unsigned int dataoff,
++				     unsigned int *datalen,
++				     enum sdp_header_types type,
++				     enum sdp_header_types term,
++				     const union nf_inet_addr *addr)
++				     __read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook);
+ 
+-/* get line length until first CR or LF seen. */
+-int ct_sip_lnlen(const char *line, const char *limit)
+-{
+-	const char *k = line;
++unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
++				     const char **dptr,
++				     unsigned int *datalen,
++				     unsigned int matchoff,
++				     unsigned int matchlen,
++				     u_int16_t port) __read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook);
+ 
+-	while ((line <= limit) && (*line == '\r' || *line == '\n'))
+-		line++;
++unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
++					const char **dptr,
++					unsigned int dataoff,
++					unsigned int *datalen,
++					const union nf_inet_addr *addr)
++					__read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook);
+ 
+-	while (line <= limit) {
+-		if (*line == '\r' || *line == '\n')
+-			break;
+-		line++;
+-	}
+-	return line - k;
+-}
+-EXPORT_SYMBOL_GPL(ct_sip_lnlen);
++unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
++				      const char **dptr,
++				      unsigned int *datalen,
++				      struct nf_conntrack_expect *rtp_exp,
++				      struct nf_conntrack_expect *rtcp_exp,
++				      unsigned int mediaoff,
++				      unsigned int medialen,
++				      union nf_inet_addr *rtp_addr)
++				      __read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sdp_media_hook);
+ 
+-/* Linear string search, case sensitive. */
+-const char *ct_sip_search(const char *needle, const char *haystack,
+-			  size_t needle_len, size_t haystack_len,
+-			  int case_sensitive)
++static int string_len(const struct nf_conn *ct, const char *dptr,
++		      const char *limit, int *shift)
+ {
+-	const char *limit = haystack + (haystack_len - needle_len);
++	int len = 0;
+ 
+-	while (haystack <= limit) {
+-		if (case_sensitive) {
+-			if (strncmp(haystack, needle, needle_len) == 0)
+-				return haystack;
+-		} else {
+-			if (strnicmp(haystack, needle, needle_len) == 0)
+-				return haystack;
+-		}
+-		haystack++;
++	while (dptr < limit && isalpha(*dptr)) {
++		dptr++;
++		len++;
+ 	}
+-	return NULL;
++	return len;
+ }
+-EXPORT_SYMBOL_GPL(ct_sip_search);
+ 
+ static int digits_len(const struct nf_conn *ct, const char *dptr,
+ 		      const char *limit, int *shift)
+ {
+ 	int len = 0;
+-	while (dptr <= limit && isdigit(*dptr)) {
++	while (dptr < limit && isdigit(*dptr)) {
+ 		dptr++;
+ 		len++;
+ 	}
+ 	return len;
+ }
+ 
+-/* get digits length, skipping blank spaces. */
+-static int skp_digits_len(const struct nf_conn *ct, const char *dptr,
+-			  const char *limit, int *shift)
++/* get media type + port length */
++static int media_len(const struct nf_conn *ct, const char *dptr,
++		     const char *limit, int *shift)
+ {
+-	for (; dptr <= limit && *dptr == ' '; dptr++)
+-		(*shift)++;
++	int len = string_len(ct, dptr, limit, shift);
++
++	dptr += len;
++	if (dptr >= limit || *dptr != ' ')
++		return 0;
++	len++;
++	dptr++;
+ 
+-	return digits_len(ct, dptr, limit, shift);
++	return len + digits_len(ct, dptr, limit, shift);
+ }
+ 
+ static int parse_addr(const struct nf_conn *ct, const char *cp,
+@@ -251,10 +142,10 @@ static int parse_addr(const struct nf_conn *ct, const char *cp,
+                       const char *limit)
+ {
+ 	const char *end;
+-	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ 	int ret = 0;
+ 
+-	switch (family) {
++	memset(addr, 0, sizeof(*addr));
++	switch (nf_ct_l3num(ct)) {
+ 	case AF_INET:
+ 		ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end);
+ 		break;
+@@ -302,13 +193,13 @@ static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
+ 	/* Search for @, but stop at the end of the line.
+ 	 * We are inside a sip: URI, so we don't need to worry about
+ 	 * continuation lines. */
+-	while (dptr <= limit &&
++	while (dptr < limit &&
+ 	       *dptr != '@' && *dptr != '\r' && *dptr != '\n') {
+ 		(*shift)++;
+ 		dptr++;
+ 	}
+ 
+-	if (dptr <= limit && *dptr == '@') {
++	if (dptr < limit && *dptr == '@') {
+ 		dptr++;
+ 		(*shift)++;
+ 	} else {
+@@ -319,74 +210,892 @@ static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
+ 	return epaddr_len(ct, dptr, limit, shift);
+ }
+ 
+-/* Returns 0 if not found, -1 error parsing. */
+-int ct_sip_get_info(const struct nf_conn *ct,
+-		    const char *dptr, size_t dlen,
+-		    unsigned int *matchoff,
+-		    unsigned int *matchlen,
+-		    enum sip_header_pos pos)
++/* Parse a SIP request line of the form:
++ *
++ * Request-Line = Method SP Request-URI SP SIP-Version CRLF
++ *
++ * and return the offset and length of the address contained in the Request-URI.
++ */
++int ct_sip_parse_request(const struct nf_conn *ct,
++			 const char *dptr, unsigned int datalen,
++			 unsigned int *matchoff, unsigned int *matchlen,
++			 union nf_inet_addr *addr, __be16 *port)
+ {
+-	const struct sip_header_nfo *hnfo = &ct_sip_hdrs[pos];
+-	const char *limit, *aux, *k = dptr;
++	const char *start = dptr, *limit = dptr + datalen, *end;
++	unsigned int mlen;
++	unsigned int p;
+ 	int shift = 0;
+ 
+-	limit = dptr + (dlen - hnfo->lnlen);
++	/* Skip method and following whitespace */
++	mlen = string_len(ct, dptr, limit, NULL);
++	if (!mlen)
++		return 0;
++	dptr += mlen;
++	if (++dptr >= limit)
++		return 0;
+ 
+-	while (dptr <= limit) {
+-		if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
+-		    (hnfo->sname == NULL ||
+-		     strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
+-			dptr++;
++	/* Find SIP URI */
++	limit -= strlen("sip:");
++	for (; dptr < limit; dptr++) {
++		if (*dptr == '\r' || *dptr == '\n')
++			return -1;
++		if (strnicmp(dptr, "sip:", strlen("sip:")) == 0)
++			break;
++	}
++	if (!skp_epaddr_len(ct, dptr, limit, &shift))
++		return 0;
++	dptr += shift;
++
++	if (!parse_addr(ct, dptr, &end, addr, limit))
++		return -1;
++	if (end < limit && *end == ':') {
++		end++;
++		p = simple_strtoul(end, (char **)&end, 10);
++		if (p < 1024 || p > 65535)
++			return -1;
++		*port = htons(p);
++	} else
++		*port = htons(SIP_PORT);
++
++	if (end == dptr)
++		return 0;
++	*matchoff = dptr - start;
++	*matchlen = end - dptr;
++	return 1;
++}
++EXPORT_SYMBOL_GPL(ct_sip_parse_request);
++
++/* SIP header parsing: SIP headers are located at the beginning of a line, but
++ * may span several lines, in which case the continuation lines begin with a
++ * whitespace character. RFC 2543 allows lines to be terminated with CR, LF or
++ * CRLF, RFC 3261 allows only CRLF, we support both.
++ *
++ * Headers are followed by (optionally) whitespace, a colon, again (optionally)
++ * whitespace and the values. Whitespace in this context means any amount of
++ * tabs, spaces and continuation lines, which are treated as a single whitespace
++ * character.
++ *
++ * Some headers may appear multiple times. A comma seperated list of values is
++ * equivalent to multiple headers.
++ */
++static const struct sip_header ct_sip_hdrs[] = {
++	[SIP_HDR_CSEQ]			= SIP_HDR("CSeq", NULL, NULL, digits_len),
++	[SIP_HDR_FROM]			= SIP_HDR("From", "f", "sip:", skp_epaddr_len),
++	[SIP_HDR_TO]			= SIP_HDR("To", "t", "sip:", skp_epaddr_len),
++	[SIP_HDR_CONTACT]		= SIP_HDR("Contact", "m", "sip:", skp_epaddr_len),
++	[SIP_HDR_VIA]			= SIP_HDR("Via", "v", "UDP ", epaddr_len),
++	[SIP_HDR_EXPIRES]		= SIP_HDR("Expires", NULL, NULL, digits_len),
++	[SIP_HDR_CONTENT_LENGTH]	= SIP_HDR("Content-Length", "l", NULL, digits_len),
++};
++
++static const char *sip_follow_continuation(const char *dptr, const char *limit)
++{
++	/* Walk past newline */
++	if (++dptr >= limit)
++		return NULL;
++
++	/* Skip '\n' in CR LF */
++	if (*(dptr - 1) == '\r' && *dptr == '\n') {
++		if (++dptr >= limit)
++			return NULL;
++	}
++
++	/* Continuation line? */
++	if (*dptr != ' ' && *dptr != '\t')
++		return NULL;
++
++	/* skip leading whitespace */
++	for (; dptr < limit; dptr++) {
++		if (*dptr != ' ' && *dptr != '\t')
++			break;
++	}
++	return dptr;
++}
++
++static const char *sip_skip_whitespace(const char *dptr, const char *limit)
++{
++	for (; dptr < limit; dptr++) {
++		if (*dptr == ' ')
++			continue;
++		if (*dptr != '\r' && *dptr != '\n')
++			break;
++		dptr = sip_follow_continuation(dptr, limit);
++		if (dptr == NULL)
++			return NULL;
++	}
++	return dptr;
++}
++
++/* Search within a SIP header value, dealing with continuation lines */
++static const char *ct_sip_header_search(const char *dptr, const char *limit,
++					const char *needle, unsigned int len)
++{
++	for (limit -= len; dptr < limit; dptr++) {
++		if (*dptr == '\r' || *dptr == '\n') {
++			dptr = sip_follow_continuation(dptr, limit);
++			if (dptr == NULL)
++				break;
+ 			continue;
+ 		}
+-		aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
+-				    ct_sip_lnlen(dptr, limit),
+-				    hnfo->case_sensitive);
+-		if (!aux) {
+-			pr_debug("'%s' not found in '%s'.\n", hnfo->ln_str,
+-				 hnfo->lname);
+-			return -1;
++
++		if (strnicmp(dptr, needle, len) == 0)
++			return dptr;
++	}
++	return NULL;
++}
++
++int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
++		      unsigned int dataoff, unsigned int datalen,
++		      enum sip_header_types type,
++		      unsigned int *matchoff, unsigned int *matchlen)
++{
++	const struct sip_header *hdr = &ct_sip_hdrs[type];
++	const char *start = dptr, *limit = dptr + datalen;
++	int shift = 0;
++
++	for (dptr += dataoff; dptr < limit; dptr++) {
++		/* Find beginning of line */
++		if (*dptr != '\r' && *dptr != '\n')
++			continue;
++		if (++dptr >= limit)
++			break;
++		if (*(dptr - 1) == '\r' && *dptr == '\n') {
++			if (++dptr >= limit)
++				break;
++		}
++
++		/* Skip continuation lines */
++		if (*dptr == ' ' || *dptr == '\t')
++			continue;
++
++		/* Find header. Compact headers must be followed by a
++		 * non-alphabetic character to avoid mismatches. */
++		if (limit - dptr >= hdr->len &&
++		    strnicmp(dptr, hdr->name, hdr->len) == 0)
++			dptr += hdr->len;
++		else if (hdr->cname && limit - dptr >= hdr->clen + 1 &&
++			 strnicmp(dptr, hdr->cname, hdr->clen) == 0 &&
++			 !isalpha(*(dptr + hdr->clen + 1)))
++			dptr += hdr->clen;
++		else
++			continue;
++
++		/* Find and skip colon */
++		dptr = sip_skip_whitespace(dptr, limit);
++		if (dptr == NULL)
++			break;
++		if (*dptr != ':' || ++dptr >= limit)
++			break;
++
++		/* Skip whitespace after colon */
++		dptr = sip_skip_whitespace(dptr, limit);
++		if (dptr == NULL)
++			break;
++
++		*matchoff = dptr - start;
++		if (hdr->search) {
++			dptr = ct_sip_header_search(dptr, limit, hdr->search,
++						    hdr->slen);
++			if (!dptr)
++				return -1;
++			dptr += hdr->slen;
+ 		}
+-		aux += hnfo->ln_strlen;
+ 
+-		*matchlen = hnfo->match_len(ct, aux, limit, &shift);
++		*matchlen = hdr->match_len(ct, dptr, limit, &shift);
+ 		if (!*matchlen)
+ 			return -1;
++		*matchoff = dptr - start + shift;
++		return 1;
++	}
++	return 0;
++}
++EXPORT_SYMBOL_GPL(ct_sip_get_header);
++
++/* Get next header field in a list of comma seperated values */
++static int ct_sip_next_header(const struct nf_conn *ct, const char *dptr,
++			      unsigned int dataoff, unsigned int datalen,
++			      enum sip_header_types type,
++			      unsigned int *matchoff, unsigned int *matchlen)
++{
++	const struct sip_header *hdr = &ct_sip_hdrs[type];
++	const char *start = dptr, *limit = dptr + datalen;
++	int shift = 0;
++
++	dptr += dataoff;
++
++	dptr = ct_sip_header_search(dptr, limit, ",", strlen(","));
++	if (!dptr)
++		return 0;
++
++	dptr = ct_sip_header_search(dptr, limit, hdr->search, hdr->slen);
++	if (!dptr)
++		return 0;
++	dptr += hdr->slen;
++
++	*matchoff = dptr - start;
++	*matchlen = hdr->match_len(ct, dptr, limit, &shift);
++	if (!*matchlen)
++		return -1;
++	*matchoff += shift;
++	return 1;
++}
++
++/* Walk through headers until a parsable one is found or no header of the
++ * given type is left. */
++static int ct_sip_walk_headers(const struct nf_conn *ct, const char *dptr,
++			       unsigned int dataoff, unsigned int datalen,
++			       enum sip_header_types type, int *in_header,
++			       unsigned int *matchoff, unsigned int *matchlen)
++{
++	int ret;
++
++	if (in_header && *in_header) {
++		while (1) {
++			ret = ct_sip_next_header(ct, dptr, dataoff, datalen,
++						 type, matchoff, matchlen);
++			if (ret > 0)
++				return ret;
++			if (ret == 0)
++				break;
++			dataoff += *matchoff;
++		}
++		*in_header = 0;
++	}
++
++	while (1) {
++		ret = ct_sip_get_header(ct, dptr, dataoff, datalen,
++					type, matchoff, matchlen);
++		if (ret > 0)
++			break;
++		if (ret == 0)
++			return ret;
++		dataoff += *matchoff;
++	}
++
++	if (in_header)
++		*in_header = 1;
++	return 1;
++}
++
++/* Locate a SIP header, parse the URI and return the offset and length of
++ * the address as well as the address and port themselves. A stream of
++ * headers can be parsed by handing in a non-NULL datalen and in_header
++ * pointer.
++ */
++int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
++			    unsigned int *dataoff, unsigned int datalen,
++			    enum sip_header_types type, int *in_header,
++			    unsigned int *matchoff, unsigned int *matchlen,
++			    union nf_inet_addr *addr, __be16 *port)
++{
++	const char *c, *limit = dptr + datalen;
++	unsigned int p;
++	int ret;
++
++	ret = ct_sip_walk_headers(ct, dptr, dataoff ? *dataoff : 0, datalen,
++				  type, in_header, matchoff, matchlen);
++	WARN_ON(ret < 0);
++	if (ret == 0)
++		return ret;
++
++	if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit))
++		return -1;
++	if (*c == ':') {
++		c++;
++		p = simple_strtoul(c, (char **)&c, 10);
++		if (p < 1024 || p > 65535)
++			return -1;
++		*port = htons(p);
++	} else
++		*port = htons(SIP_PORT);
++
++	if (dataoff)
++		*dataoff = c - dptr;
++	return 1;
++}
++EXPORT_SYMBOL_GPL(ct_sip_parse_header_uri);
++
++/* Parse address from header parameter and return address, offset and length */
++int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,
++			       unsigned int dataoff, unsigned int datalen,
++			       const char *name,
++			       unsigned int *matchoff, unsigned int *matchlen,
++			       union nf_inet_addr *addr)
++{
++	const char *limit = dptr + datalen;
++	const char *start, *end;
+ 
+-		*matchoff = (aux - k) + shift;
++	limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(","));
++	if (!limit)
++		limit = dptr + datalen;
+ 
+-		pr_debug("%s match succeeded! - len: %u\n", hnfo->lname,
+-			 *matchlen);
++	start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name));
++	if (!start)
++		return 0;
++
++	start += strlen(name);
++	if (!parse_addr(ct, start, &end, addr, limit))
++		return 0;
++	*matchoff = start - dptr;
++	*matchlen = end - start;
++	return 1;
++}
++EXPORT_SYMBOL_GPL(ct_sip_parse_address_param);
++
++/* Parse numerical header parameter and return value, offset and length */
++int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,
++				 unsigned int dataoff, unsigned int datalen,
++				 const char *name,
++				 unsigned int *matchoff, unsigned int *matchlen,
++				 unsigned int *val)
++{
++	const char *limit = dptr + datalen;
++	const char *start;
++	char *end;
++
++	limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(","));
++	if (!limit)
++		limit = dptr + datalen;
++
++	start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name));
++	if (!start)
++		return 0;
++
++	start += strlen(name);
++	*val = simple_strtoul(start, &end, 0);
++	if (start == end)
++		return 0;
++	if (matchoff && matchlen) {
++		*matchoff = start - dptr;
++		*matchlen = end - start;
++	}
++	return 1;
++}
++EXPORT_SYMBOL_GPL(ct_sip_parse_numerical_param);
++
++/* SDP header parsing: a SDP session description contains an ordered set of
++ * headers, starting with a section containing general session parameters,
++ * optionally followed by multiple media descriptions.
++ *
++ * SDP headers always start at the beginning of a line. According to RFC 2327:
++ * "The sequence CRLF (0x0d0a) is used to end a record, although parsers should
++ * be tolerant and also accept records terminated with a single newline
++ * character". We handle both cases.
++ */
++static const struct sip_header ct_sdp_hdrs[] = {
++	[SDP_HDR_VERSION]		= SDP_HDR("v=", NULL, digits_len),
++	[SDP_HDR_OWNER_IP4]		= SDP_HDR("o=", "IN IP4 ", epaddr_len),
++	[SDP_HDR_CONNECTION_IP4]	= SDP_HDR("c=", "IN IP4 ", epaddr_len),
++	[SDP_HDR_OWNER_IP6]		= SDP_HDR("o=", "IN IP6 ", epaddr_len),
++	[SDP_HDR_CONNECTION_IP6]	= SDP_HDR("c=", "IN IP6 ", epaddr_len),
++	[SDP_HDR_MEDIA]			= SDP_HDR("m=", NULL, media_len),
++};
++
++/* Linear string search within SDP header values */
++static const char *ct_sdp_header_search(const char *dptr, const char *limit,
++					const char *needle, unsigned int len)
++{
++	for (limit -= len; dptr < limit; dptr++) {
++		if (*dptr == '\r' || *dptr == '\n')
++			break;
++		if (strncmp(dptr, needle, len) == 0)
++			return dptr;
++	}
++	return NULL;
++}
++
++/* Locate a SDP header (optionally a substring within the header value),
++ * optionally stopping at the first occurence of the term header, parse
++ * it and return the offset and length of the data we're interested in.
++ */
++int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
++			  unsigned int dataoff, unsigned int datalen,
++			  enum sdp_header_types type,
++			  enum sdp_header_types term,
++			  unsigned int *matchoff, unsigned int *matchlen)
++{
++	const struct sip_header *hdr = &ct_sdp_hdrs[type];
++	const struct sip_header *thdr = &ct_sdp_hdrs[term];
++	const char *start = dptr, *limit = dptr + datalen;
++	int shift = 0;
++
++	for (dptr += dataoff; dptr < limit; dptr++) {
++		/* Find beginning of line */
++		if (*dptr != '\r' && *dptr != '\n')
++			continue;
++		if (++dptr >= limit)
++			break;
++		if (*(dptr - 1) == '\r' && *dptr == '\n') {
++			if (++dptr >= limit)
++				break;
++		}
++
++		if (term != SDP_HDR_UNSPEC &&
++		    limit - dptr >= thdr->len &&
++		    strnicmp(dptr, thdr->name, thdr->len) == 0)
++			break;
++		else if (limit - dptr >= hdr->len &&
++			 strnicmp(dptr, hdr->name, hdr->len) == 0)
++			dptr += hdr->len;
++		else
++			continue;
++
++		*matchoff = dptr - start;
++		if (hdr->search) {
++			dptr = ct_sdp_header_search(dptr, limit, hdr->search,
++						    hdr->slen);
++			if (!dptr)
++				return -1;
++			dptr += hdr->slen;
++		}
++
++		*matchlen = hdr->match_len(ct, dptr, limit, &shift);
++		if (!*matchlen)
++			return -1;
++		*matchoff = dptr - start + shift;
+ 		return 1;
+ 	}
+-	pr_debug("%s header not found.\n", hnfo->lname);
+ 	return 0;
+ }
+-EXPORT_SYMBOL_GPL(ct_sip_get_info);
++EXPORT_SYMBOL_GPL(ct_sip_get_sdp_header);
++
++static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr,
++				 unsigned int dataoff, unsigned int datalen,
++				 enum sdp_header_types type,
++				 enum sdp_header_types term,
++				 unsigned int *matchoff, unsigned int *matchlen,
++				 union nf_inet_addr *addr)
++{
++	int ret;
++
++	ret = ct_sip_get_sdp_header(ct, dptr, dataoff, datalen, type, term,
++				    matchoff, matchlen);
++	if (ret <= 0)
++		return ret;
++
++	if (!parse_addr(ct, dptr + *matchoff, NULL, addr,
++			dptr + *matchoff + *matchlen))
++		return -1;
++	return 1;
++}
++
++static int refresh_signalling_expectation(struct nf_conn *ct,
++					  union nf_inet_addr *addr,
++					  __be16 port,
++					  unsigned int expires)
++{
++	struct nf_conn_help *help = nfct_help(ct);
++	struct nf_conntrack_expect *exp;
++	struct hlist_node *n, *next;
++	int found = 0;
++
++	spin_lock_bh(&nf_conntrack_lock);
++	hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
++		if (exp->class != SIP_EXPECT_SIGNALLING ||
++		    !nf_inet_addr_cmp(&exp->tuple.dst.u3, addr) ||
++		    exp->tuple.dst.u.udp.port != port)
++			continue;
++		if (!del_timer(&exp->timeout))
++			continue;
++		exp->flags &= ~NF_CT_EXPECT_INACTIVE;
++		exp->timeout.expires = jiffies + expires * HZ;
++		add_timer(&exp->timeout);
++		found = 1;
++		break;
++	}
++	spin_unlock_bh(&nf_conntrack_lock);
++	return found;
++}
+ 
+-static int set_expected_rtp(struct sk_buff *skb,
+-			    struct nf_conn *ct,
+-			    enum ip_conntrack_info ctinfo,
+-			    union nf_inet_addr *addr,
+-			    __be16 port,
+-			    const char *dptr)
++static void flush_expectations(struct nf_conn *ct, bool media)
+ {
++	struct nf_conn_help *help = nfct_help(ct);
+ 	struct nf_conntrack_expect *exp;
++	struct hlist_node *n, *next;
++
++	spin_lock_bh(&nf_conntrack_lock);
++	hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
++		if ((exp->class != SIP_EXPECT_SIGNALLING) ^ media)
++			continue;
++		if (!del_timer(&exp->timeout))
++			continue;
++		nf_ct_unlink_expect(exp);
++		nf_ct_expect_put(exp);
++		if (!media)
++			break;
++	}
++	spin_unlock_bh(&nf_conntrack_lock);
++}
++
++static int set_expected_rtp_rtcp(struct sk_buff *skb,
++				 const char **dptr, unsigned int *datalen,
++				 union nf_inet_addr *daddr, __be16 port,
++				 enum sip_expectation_classes class,
++				 unsigned int mediaoff, unsigned int medialen)
++{
++	struct nf_conntrack_expect *exp, *rtp_exp, *rtcp_exp;
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++	union nf_inet_addr *saddr;
++	struct nf_conntrack_tuple tuple;
++	int direct_rtp = 0, skip_expect = 0, ret = NF_DROP;
++	u_int16_t base_port;
++	__be16 rtp_port, rtcp_port;
++	typeof(nf_nat_sdp_port_hook) nf_nat_sdp_port;
++	typeof(nf_nat_sdp_media_hook) nf_nat_sdp_media;
++
++	saddr = NULL;
++	if (sip_direct_media) {
++		if (!nf_inet_addr_cmp(daddr, &ct->tuplehash[dir].tuple.src.u3))
++			return NF_ACCEPT;
++		saddr = &ct->tuplehash[!dir].tuple.src.u3;
++	}
++
++	/* We need to check whether the registration exists before attempting
++	 * to register it since we can see the same media description multiple
++	 * times on different connections in case multiple endpoints receive
++	 * the same call.
++	 *
++	 * RTP optimization: if we find a matching media channel expectation
++	 * and both the expectation and this connection are SNATed, we assume
++	 * both sides can reach each other directly and use the final
++	 * destination address from the expectation. We still need to keep
++	 * the NATed expectations for media that might arrive from the
++	 * outside, and additionally need to expect the direct RTP stream
++	 * in case it passes through us even without NAT.
++	 */
++	memset(&tuple, 0, sizeof(tuple));
++	if (saddr)
++		tuple.src.u3 = *saddr;
++	tuple.src.l3num		= nf_ct_l3num(ct);
++	tuple.dst.protonum	= IPPROTO_UDP;
++	tuple.dst.u3		= *daddr;
++	tuple.dst.u.udp.port	= port;
++
++	rcu_read_lock();
++	do {
++		exp = __nf_ct_expect_find(&tuple);
++
++		if (!exp || exp->master == ct ||
++		    nfct_help(exp->master)->helper != nfct_help(ct)->helper ||
++		    exp->class != class)
++			break;
++#ifdef CONFIG_NF_NAT_NEEDED
++		if (exp->tuple.src.l3num == AF_INET && !direct_rtp &&
++		    (exp->saved_ip != exp->tuple.dst.u3.ip ||
++		     exp->saved_proto.udp.port != exp->tuple.dst.u.udp.port) &&
++		    ct->status & IPS_NAT_MASK) {
++			daddr->ip		= exp->saved_ip;
++			tuple.dst.u3.ip		= exp->saved_ip;
++			tuple.dst.u.udp.port	= exp->saved_proto.udp.port;
++			direct_rtp = 1;
++		} else
++#endif
++			skip_expect = 1;
++	} while (!skip_expect);
++	rcu_read_unlock();
++
++	base_port = ntohs(tuple.dst.u.udp.port) & ~1;
++	rtp_port = htons(base_port);
++	rtcp_port = htons(base_port + 1);
++
++	if (direct_rtp) {
++		nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook);
++		if (nf_nat_sdp_port &&
++		    !nf_nat_sdp_port(skb, dptr, datalen,
++				     mediaoff, medialen, ntohs(rtp_port)))
++			goto err1;
++	}
++
++	if (skip_expect)
++		return NF_ACCEPT;
++
++	rtp_exp = nf_ct_expect_alloc(ct);
++	if (rtp_exp == NULL)
++		goto err1;
++	nf_ct_expect_init(rtp_exp, class, nf_ct_l3num(ct), saddr, daddr,
++			  IPPROTO_UDP, NULL, &rtp_port);
++
++	rtcp_exp = nf_ct_expect_alloc(ct);
++	if (rtcp_exp == NULL)
++		goto err2;
++	nf_ct_expect_init(rtcp_exp, class, nf_ct_l3num(ct), saddr, daddr,
++			  IPPROTO_UDP, NULL, &rtcp_port);
++
++	nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
++	if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp)
++		ret = nf_nat_sdp_media(skb, dptr, datalen, rtp_exp, rtcp_exp,
++				       mediaoff, medialen, daddr);
++	else {
++		if (nf_ct_expect_related(rtp_exp) == 0) {
++			if (nf_ct_expect_related(rtcp_exp) != 0)
++				nf_ct_unexpect_related(rtp_exp);
++			else
++				ret = NF_ACCEPT;
++		}
++	}
++	nf_ct_expect_put(rtcp_exp);
++err2:
++	nf_ct_expect_put(rtp_exp);
++err1:
++	return ret;
++}
++
++static const struct sdp_media_type sdp_media_types[] = {
++	SDP_MEDIA_TYPE("audio ", SIP_EXPECT_AUDIO),
++	SDP_MEDIA_TYPE("video ", SIP_EXPECT_VIDEO),
++};
++
++static const struct sdp_media_type *sdp_media_type(const char *dptr,
++						   unsigned int matchoff,
++						   unsigned int matchlen)
++{
++	const struct sdp_media_type *t;
++	unsigned int i;
++
++	for (i = 0; i < ARRAY_SIZE(sdp_media_types); i++) {
++		t = &sdp_media_types[i];
++		if (matchlen < t->len ||
++		    strncmp(dptr + matchoff, t->name, t->len))
++			continue;
++		return t;
++	}
++	return NULL;
++}
++
++static int process_sdp(struct sk_buff *skb,
++		       const char **dptr, unsigned int *datalen,
++		       unsigned int cseq)
++{
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	unsigned int matchoff, matchlen;
++	unsigned int mediaoff, medialen;
++	unsigned int sdpoff;
++	unsigned int caddr_len, maddr_len;
++	unsigned int i;
++	union nf_inet_addr caddr, maddr, rtp_addr;
++	unsigned int port;
++	enum sdp_header_types c_hdr;
++	const struct sdp_media_type *t;
++	int ret = NF_ACCEPT;
++	typeof(nf_nat_sdp_addr_hook) nf_nat_sdp_addr;
++	typeof(nf_nat_sdp_session_hook) nf_nat_sdp_session;
++
++	nf_nat_sdp_addr = rcu_dereference(nf_nat_sdp_addr_hook);
++	c_hdr = nf_ct_l3num(ct) == AF_INET ? SDP_HDR_CONNECTION_IP4 :
++					     SDP_HDR_CONNECTION_IP6;
++
++	/* Find beginning of session description */
++	if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
++				  SDP_HDR_VERSION, SDP_HDR_UNSPEC,
++				  &matchoff, &matchlen) <= 0)
++		return NF_ACCEPT;
++	sdpoff = matchoff;
++
++	/* The connection information is contained in the session description
++	 * and/or once per media description. The first media description marks
++	 * the end of the session description. */
++	caddr_len = 0;
++	if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen,
++				  c_hdr, SDP_HDR_MEDIA,
++				  &matchoff, &matchlen, &caddr) > 0)
++		caddr_len = matchlen;
++
++	mediaoff = sdpoff;
++	for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) {
++		if (ct_sip_get_sdp_header(ct, *dptr, mediaoff, *datalen,
++					  SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
++					  &mediaoff, &medialen) <= 0)
++			break;
++
++		/* Get media type and port number. A media port value of zero
++		 * indicates an inactive stream. */
++		t = sdp_media_type(*dptr, mediaoff, medialen);
++		if (!t) {
++			mediaoff += medialen;
++			continue;
++		}
++		mediaoff += t->len;
++		medialen -= t->len;
++
++		port = simple_strtoul(*dptr + mediaoff, NULL, 10);
++		if (port == 0)
++			continue;
++		if (port < 1024 || port > 65535)
++			return NF_DROP;
++
++		/* The media description overrides the session description. */
++		maddr_len = 0;
++		if (ct_sip_parse_sdp_addr(ct, *dptr, mediaoff, *datalen,
++					  c_hdr, SDP_HDR_MEDIA,
++					  &matchoff, &matchlen, &maddr) > 0) {
++			maddr_len = matchlen;
++			memcpy(&rtp_addr, &maddr, sizeof(rtp_addr));
++		} else if (caddr_len)
++			memcpy(&rtp_addr, &caddr, sizeof(rtp_addr));
++		else
++			return NF_DROP;
++
++		ret = set_expected_rtp_rtcp(skb, dptr, datalen,
++					    &rtp_addr, htons(port), t->class,
++					    mediaoff, medialen);
++		if (ret != NF_ACCEPT)
++			return ret;
++
++		/* Update media connection address if present */
++		if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) {
++			ret = nf_nat_sdp_addr(skb, dptr, mediaoff, datalen,
++					      c_hdr, SDP_HDR_MEDIA, &rtp_addr);
++			if (ret != NF_ACCEPT)
++				return ret;
++		}
++		i++;
++	}
++
++	/* Update session connection and owner addresses */
++	nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook);
++	if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK)
++		ret = nf_nat_sdp_session(skb, dptr, sdpoff, datalen, &rtp_addr);
++
++	return ret;
++}
++static int process_invite_response(struct sk_buff *skb,
++				   const char **dptr, unsigned int *datalen,
++				   unsigned int cseq, unsigned int code)
++{
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++	if ((code >= 100 && code <= 199) ||
++	    (code >= 200 && code <= 299))
++		return process_sdp(skb, dptr, datalen, cseq);
++	else {
++		flush_expectations(ct, true);
++		return NF_ACCEPT;
++	}
++}
++
++static int process_update_response(struct sk_buff *skb,
++				   const char **dptr, unsigned int *datalen,
++				   unsigned int cseq, unsigned int code)
++{
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++	if ((code >= 100 && code <= 199) ||
++	    (code >= 200 && code <= 299))
++		return process_sdp(skb, dptr, datalen, cseq);
++	else {
++		flush_expectations(ct, true);
++		return NF_ACCEPT;
++	}
++}
++
++static int process_prack_response(struct sk_buff *skb,
++				  const char **dptr, unsigned int *datalen,
++				  unsigned int cseq, unsigned int code)
++{
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++	if ((code >= 100 && code <= 199) ||
++	    (code >= 200 && code <= 299))
++		return process_sdp(skb, dptr, datalen, cseq);
++	else {
++		flush_expectations(ct, true);
++		return NF_ACCEPT;
++	}
++}
++
++static int process_bye_request(struct sk_buff *skb,
++			       const char **dptr, unsigned int *datalen,
++			       unsigned int cseq)
++{
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++	flush_expectations(ct, true);
++	return NF_ACCEPT;
++}
++
++/* Parse a REGISTER request and create a permanent expectation for incoming
++ * signalling connections. The expectation is marked inactive and is activated
++ * when receiving a response indicating success from the registrar.
++ */
++static int process_register_request(struct sk_buff *skb,
++				    const char **dptr, unsigned int *datalen,
++				    unsigned int cseq)
++{
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	struct nf_conn_help *help = nfct_help(ct);
+ 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+-	int family = ct->tuplehash[!dir].tuple.src.l3num;
++	unsigned int matchoff, matchlen;
++	struct nf_conntrack_expect *exp;
++	union nf_inet_addr *saddr, daddr;
++	__be16 port;
++	unsigned int expires = 0;
+ 	int ret;
+-	typeof(nf_nat_sdp_hook) nf_nat_sdp;
++	typeof(nf_nat_sip_expect_hook) nf_nat_sip_expect;
++
++	/* Expected connections can not register again. */
++	if (ct->status & IPS_EXPECTED)
++		return NF_ACCEPT;
++
++	/* We must check the expiration time: a value of zero signals the
++	 * registrar to release the binding. We'll remove our expectation
++	 * when receiving the new bindings in the response, but we don't
++	 * want to create new ones.
++	 *
++	 * The expiration time may be contained in Expires: header, the
++	 * Contact: header parameters or the URI parameters.
++	 */
++	if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_EXPIRES,
++			      &matchoff, &matchlen) > 0)
++		expires = simple_strtoul(*dptr + matchoff, NULL, 10);
++
++	ret = ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
++				      SIP_HDR_CONTACT, NULL,
++				      &matchoff, &matchlen, &daddr, &port);
++	if (ret < 0)
++		return NF_DROP;
++	else if (ret == 0)
++		return NF_ACCEPT;
++
++	/* We don't support third-party registrations */
++	if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, &daddr))
++		return NF_ACCEPT;
++
++	if (ct_sip_parse_numerical_param(ct, *dptr,
++					 matchoff + matchlen, *datalen,
++					 "expires=", NULL, NULL, &expires) < 0)
++		return NF_DROP;
++
++	if (expires == 0) {
++		ret = NF_ACCEPT;
++		goto store_cseq;
++	}
+ 
+ 	exp = nf_ct_expect_alloc(ct);
+-	if (exp == NULL)
++	if (!exp)
+ 		return NF_DROP;
+-	nf_ct_expect_init(exp, family,
+-			  &ct->tuplehash[!dir].tuple.src.u3, addr,
+-			  IPPROTO_UDP, NULL, &port);
+ 
+-	nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
+-	if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
+-		ret = nf_nat_sdp(skb, ctinfo, exp, dptr);
++	saddr = NULL;
++	if (sip_direct_signalling)
++		saddr = &ct->tuplehash[!dir].tuple.src.u3;
++
++	nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct),
++			  saddr, &daddr, IPPROTO_UDP, NULL, &port);
++	exp->timeout.expires = sip_timeout * HZ;
++	exp->helper = nfct_help(ct)->helper;
++	exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
++
++	nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook);
++	if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK)
++		ret = nf_nat_sip_expect(skb, dptr, datalen, exp,
++					matchoff, matchlen);
+ 	else {
+ 		if (nf_ct_expect_related(exp) != 0)
+ 			ret = NF_DROP;
+@@ -395,22 +1104,160 @@ static int set_expected_rtp(struct sk_buff *skb,
+ 	}
+ 	nf_ct_expect_put(exp);
+ 
++store_cseq:
++	if (ret == NF_ACCEPT)
++		help->help.ct_sip_info.register_cseq = cseq;
+ 	return ret;
+ }
+ 
++static int process_register_response(struct sk_buff *skb,
++				     const char **dptr, unsigned int *datalen,
++				     unsigned int cseq, unsigned int code)
++{
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	struct nf_conn_help *help = nfct_help(ct);
++	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++	union nf_inet_addr addr;
++	__be16 port;
++	unsigned int matchoff, matchlen, dataoff = 0;
++	unsigned int expires = 0;
++	int in_contact = 0, ret;
++
++	/* According to RFC 3261, "UAs MUST NOT send a new registration until
++	 * they have received a final response from the registrar for the
++	 * previous one or the previous REGISTER request has timed out".
++	 *
++	 * However, some servers fail to detect retransmissions and send late
++	 * responses, so we store the sequence number of the last valid
++	 * request and compare it here.
++	 */
++	if (help->help.ct_sip_info.register_cseq != cseq)
++		return NF_ACCEPT;
++
++	if (code >= 100 && code <= 199)
++		return NF_ACCEPT;
++	if (code < 200 || code > 299)
++		goto flush;
++
++	if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_EXPIRES,
++			      &matchoff, &matchlen) > 0)
++		expires = simple_strtoul(*dptr + matchoff, NULL, 10);
++
++	while (1) {
++		unsigned int c_expires = expires;
++
++		ret = ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen,
++					      SIP_HDR_CONTACT, &in_contact,
++					      &matchoff, &matchlen,
++					      &addr, &port);
++		if (ret < 0)
++			return NF_DROP;
++		else if (ret == 0)
++			break;
++
++		/* We don't support third-party registrations */
++		if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, &addr))
++			continue;
++
++		ret = ct_sip_parse_numerical_param(ct, *dptr,
++						   matchoff + matchlen,
++						   *datalen, "expires=",
++						   NULL, NULL, &c_expires);
++		if (ret < 0)
++			return NF_DROP;
++		if (c_expires == 0)
++			break;
++		if (refresh_signalling_expectation(ct, &addr, port, c_expires))
++			return NF_ACCEPT;
++	}
++
++flush:
++	flush_expectations(ct, false);
++	return NF_ACCEPT;
++}
++
++static const struct sip_handler sip_handlers[] = {
++	SIP_HANDLER("INVITE", process_sdp, process_invite_response),
++	SIP_HANDLER("UPDATE", process_sdp, process_update_response),
++	SIP_HANDLER("ACK", process_sdp, NULL),
++	SIP_HANDLER("PRACK", process_sdp, process_prack_response),
++	SIP_HANDLER("BYE", process_bye_request, NULL),
++	SIP_HANDLER("REGISTER", process_register_request, process_register_response),
++};
++
++static int process_sip_response(struct sk_buff *skb,
++				const char **dptr, unsigned int *datalen)
++{
++	static const struct sip_handler *handler;
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	unsigned int matchoff, matchlen;
++	unsigned int code, cseq, dataoff, i;
++
++	if (*datalen < strlen("SIP/2.0 200"))
++		return NF_ACCEPT;
++	code = simple_strtoul(*dptr + strlen("SIP/2.0 "), NULL, 10);
++	if (!code)
++		return NF_DROP;
++
++	if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ,
++			      &matchoff, &matchlen) <= 0)
++		return NF_DROP;
++	cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
++	if (!cseq)
++		return NF_DROP;
++	dataoff = matchoff + matchlen + 1;
++
++	for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
++		handler = &sip_handlers[i];
++		if (handler->response == NULL)
++			continue;
++		if (*datalen < dataoff + handler->len ||
++		    strnicmp(*dptr + dataoff, handler->method, handler->len))
++			continue;
++		return handler->response(skb, dptr, datalen, cseq, code);
++	}
++	return NF_ACCEPT;
++}
++
++static int process_sip_request(struct sk_buff *skb,
++			       const char **dptr, unsigned int *datalen)
++{
++	static const struct sip_handler *handler;
++	enum ip_conntrack_info ctinfo;
++	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++	unsigned int matchoff, matchlen;
++	unsigned int cseq, i;
++
++	for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
++		handler = &sip_handlers[i];
++		if (handler->request == NULL)
++			continue;
++		if (*datalen < handler->len ||
++		    strnicmp(*dptr, handler->method, handler->len))
++			continue;
++
++		if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ,
++				      &matchoff, &matchlen) <= 0)
++			return NF_DROP;
++		cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
++		if (!cseq)
++			return NF_DROP;
++
++		return handler->request(skb, dptr, datalen, cseq);
++	}
++	return NF_ACCEPT;
++}
++
+ static int sip_help(struct sk_buff *skb,
+ 		    unsigned int protoff,
+ 		    struct nf_conn *ct,
+ 		    enum ip_conntrack_info ctinfo)
+ {
+-	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+-	union nf_inet_addr addr;
+ 	unsigned int dataoff, datalen;
+ 	const char *dptr;
+-	int ret = NF_ACCEPT;
+-	unsigned int matchoff, matchlen;
+-	u_int16_t port;
+-	enum sip_header_pos pos;
++	int ret;
+ 	typeof(nf_nat_sip_hook) nf_nat_sip;
+ 
+ 	/* No Data ? */
+@@ -424,58 +1271,45 @@ static int sip_help(struct sk_buff *skb,
+ 		dptr = skb->data + dataoff;
+ 	else {
+ 		pr_debug("Copy of skbuff not supported yet.\n");
+-		goto out;
+-	}
+-
+-	nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
+-	if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
+-		if (!nf_nat_sip(skb, ctinfo, ct, &dptr)) {
+-			ret = NF_DROP;
+-			goto out;
+-		}
++		return NF_ACCEPT;
+ 	}
+ 
+ 	datalen = skb->len - dataoff;
+-	if (datalen < sizeof("SIP/2.0 200") - 1)
+-		goto out;
+-
+-	/* RTP info only in some SDP pkts */
+-	if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
+-	    memcmp(dptr, "UPDATE", sizeof("UPDATE") - 1) != 0 &&
+-	    memcmp(dptr, "SIP/2.0 180", sizeof("SIP/2.0 180") - 1) != 0 &&
+-	    memcmp(dptr, "SIP/2.0 183", sizeof("SIP/2.0 183") - 1) != 0 &&
+-	    memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
+-		goto out;
+-	}
+-	/* Get address and port from SDP packet. */
+-	pos = family == AF_INET ? POS_CONNECTION_IP4 : POS_CONNECTION_IP6;
+-	if (ct_sip_get_info(ct, dptr, datalen, &matchoff, &matchlen, pos) > 0) {
+-
+-		/* We'll drop only if there are parse problems. */
+-		if (!parse_addr(ct, dptr + matchoff, NULL, &addr,
+-				dptr + datalen)) {
+-			ret = NF_DROP;
+-			goto out;
+-		}
+-		if (ct_sip_get_info(ct, dptr, datalen, &matchoff, &matchlen,
+-				    POS_MEDIA) > 0) {
++	if (datalen < strlen("SIP/2.0 200"))
++		return NF_ACCEPT;
+ 
+-			port = simple_strtoul(dptr + matchoff, NULL, 10);
+-			if (port < 1024) {
+-				ret = NF_DROP;
+-				goto out;
+-			}
+-			ret = set_expected_rtp(skb, ct, ctinfo, &addr,
+-					       htons(port), dptr);
+-		}
++	if (strnicmp(dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0)
++		ret = process_sip_request(skb, &dptr, &datalen);
++	else
++		ret = process_sip_response(skb, &dptr, &datalen);
++
++	if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
++		nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
++		if (nf_nat_sip && !nf_nat_sip(skb, &dptr, &datalen))
++			ret = NF_DROP;
+ 	}
+-out:
++
+ 	return ret;
+ }
+ 
+ static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly;
+ static char sip_names[MAX_PORTS][2][sizeof("sip-65535")] __read_mostly;
+ 
++static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = {
++	[SIP_EXPECT_SIGNALLING] = {
++		.max_expected	= 1,
++		.timeout	= 3 * 60,
++	},
++	[SIP_EXPECT_AUDIO] = {
++		.max_expected	= 2 * IP_CT_DIR_MAX,
++		.timeout	= 3 * 60,
++	},
++	[SIP_EXPECT_VIDEO] = {
++		.max_expected	= 2 * IP_CT_DIR_MAX,
++		.timeout	= 3 * 60,
++	},
++};
++
+ static void nf_conntrack_sip_fini(void)
+ {
+ 	int i, j;
+@@ -505,8 +1339,8 @@ static int __init nf_conntrack_sip_init(void)
+ 		for (j = 0; j < 2; j++) {
+ 			sip[i][j].tuple.dst.protonum = IPPROTO_UDP;
+ 			sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
+-			sip[i][j].max_expected = 2;
+-			sip[i][j].timeout = 3 * 60; /* 3 minutes */
++			sip[i][j].expect_policy = sip_exp_policy;
++			sip[i][j].expect_class_max = SIP_EXPECT_MAX;
+ 			sip[i][j].me = THIS_MODULE;
+ 			sip[i][j].help = sip_help;
+ 
+diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
+index 8599068..b59871f 100644
+--- a/net/netfilter/nf_conntrack_standalone.c
++++ b/net/netfilter/nf_conntrack_standalone.c
+@@ -127,21 +127,14 @@ static int ct_seq_show(struct seq_file *s, void *v)
+ 	if (NF_CT_DIRECTION(hash))
+ 		return 0;
+ 
+-	l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+-				       .tuple.src.l3num);
+-
++	l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
+ 	NF_CT_ASSERT(l3proto);
+-	l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+-				   .tuple.src.l3num,
+-				   ct->tuplehash[IP_CT_DIR_ORIGINAL]
+-				   .tuple.dst.protonum);
++	l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ 	NF_CT_ASSERT(l4proto);
+ 
+ 	if (seq_printf(s, "%-8s %u %-8s %u %ld ",
+-		       l3proto->name,
+-		       ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num,
+-		       l4proto->name,
+-		       ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
++		       l3proto->name, nf_ct_l3num(ct),
++		       l4proto->name, nf_ct_protonum(ct),
+ 		       timer_pending(&ct->timeout)
+ 		       ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0)
+ 		return -ENOSPC;
+@@ -293,8 +286,43 @@ static const struct file_operations ct_cpu_seq_fops = {
+ 	.open	 = ct_cpu_seq_open,
+ 	.read	 = seq_read,
+ 	.llseek	 = seq_lseek,
+-	.release = seq_release_private,
++	.release = seq_release,
+ };
++
++static int nf_conntrack_standalone_init_proc(void)
++{
++	struct proc_dir_entry *pde;
++
++	pde = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
++	if (!pde)
++		goto out_nf_conntrack;
++	pde = create_proc_entry("nf_conntrack", S_IRUGO, init_net.proc_net_stat);
++	if (!pde)
++		goto out_stat_nf_conntrack;
++	pde->proc_fops = &ct_cpu_seq_fops;
++	pde->owner = THIS_MODULE;
++	return 0;
++
++out_stat_nf_conntrack:
++	proc_net_remove(&init_net, "nf_conntrack");
++out_nf_conntrack:
++	return -ENOMEM;
++}
++
++static void nf_conntrack_standalone_fini_proc(void)
++{
++	remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
++	proc_net_remove(&init_net, "nf_conntrack");
++}
++#else
++static int nf_conntrack_standalone_init_proc(void)
++{
++	return 0;
++}
++
++static void nf_conntrack_standalone_fini_proc(void)
++{
++}
+ #endif /* CONFIG_PROC_FS */
+ 
+ /* Sysctl support */
+@@ -390,60 +418,61 @@ static struct ctl_path nf_ct_path[] = {
+ };
+ 
+ EXPORT_SYMBOL_GPL(nf_ct_log_invalid);
++
++static int nf_conntrack_standalone_init_sysctl(void)
++{
++	nf_ct_sysctl_header =
++		register_sysctl_paths(nf_ct_path, nf_ct_netfilter_table);
++	if (nf_ct_sysctl_header == NULL) {
++		printk("nf_conntrack: can't register to sysctl.\n");
++		return -ENOMEM;
++	}
++	return 0;
++
++}
++
++static void nf_conntrack_standalone_fini_sysctl(void)
++{
++	unregister_sysctl_table(nf_ct_sysctl_header);
++}
++#else
++static int nf_conntrack_standalone_init_sysctl(void)
++{
++	return 0;
++}
++
++static void nf_conntrack_standalone_fini_sysctl(void)
++{
++}
+ #endif /* CONFIG_SYSCTL */
+ 
+ static int __init nf_conntrack_standalone_init(void)
+ {
+-#ifdef CONFIG_PROC_FS
+-	struct proc_dir_entry *proc;
+-#endif
+-	int ret = 0;
++	int ret;
+ 
+ 	ret = nf_conntrack_init();
+ 	if (ret < 0)
+-		return ret;
+-
+-#ifdef CONFIG_PROC_FS
+-	proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
+-	if (!proc) goto cleanup_init;
+-
+-	if (!proc_create("nf_conntrack", S_IRUGO,
+-			 init_net.proc_net_stat, &ct_cpu_seq_fops))
+-		goto cleanup_proc;
+-#endif
+-#ifdef CONFIG_SYSCTL
+-	nf_ct_sysctl_header = register_sysctl_paths(nf_ct_path,
+-			nf_ct_netfilter_table);
+-	if (nf_ct_sysctl_header == NULL) {
+-		printk("nf_conntrack: can't register to sysctl.\n");
+-		ret = -ENOMEM;
+-		goto cleanup_proc_stat;
+-	}
+-#endif
+-	return ret;
++		goto out;
++	ret = nf_conntrack_standalone_init_proc();
++	if (ret < 0)
++		goto out_proc;
++	ret = nf_conntrack_standalone_init_sysctl();
++	if (ret < 0)
++		goto out_sysctl;
++	return 0;
+ 
+-#ifdef CONFIG_SYSCTL
+- cleanup_proc_stat:
+-#endif
+-#ifdef CONFIG_PROC_FS
+-	remove_proc_entry("nf_conntrack", init_net. proc_net_stat);
+- cleanup_proc:
+-	proc_net_remove(&init_net, "nf_conntrack");
+- cleanup_init:
+-#endif /* CNFIG_PROC_FS */
++out_sysctl:
++	nf_conntrack_standalone_fini_proc();
++out_proc:
+ 	nf_conntrack_cleanup();
++out:
+ 	return ret;
+ }
+ 
+ static void __exit nf_conntrack_standalone_fini(void)
+ {
+-#ifdef CONFIG_SYSCTL
+-	unregister_sysctl_table(nf_ct_sysctl_header);
+-#endif
+-#ifdef CONFIG_PROC_FS
+-	remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
+-	proc_net_remove(&init_net, "nf_conntrack");
+-#endif /* CNFIG_PROC_FS */
++	nf_conntrack_standalone_fini_sysctl();
++	nf_conntrack_standalone_fini_proc();
+ 	nf_conntrack_cleanup();
+ }
+ 
+diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
+index bd2e800..f57f6e7 100644
+--- a/net/netfilter/nf_conntrack_tftp.c
++++ b/net/netfilter/nf_conntrack_tftp.c
+@@ -44,7 +44,6 @@ static int tftp_help(struct sk_buff *skb,
+ 	struct nf_conntrack_expect *exp;
+ 	struct nf_conntrack_tuple *tuple;
+ 	unsigned int ret = NF_ACCEPT;
+-	int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ 	typeof(nf_nat_tftp_hook) nf_nat_tftp;
+ 
+ 	tfh = skb_header_pointer(skb, protoff + sizeof(struct udphdr),
+@@ -56,18 +55,20 @@ static int tftp_help(struct sk_buff *skb,
+ 	case TFTP_OPCODE_READ:
+ 	case TFTP_OPCODE_WRITE:
+ 		/* RRQ and WRQ works the same way */
+-		NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+-		NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
++		nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++		nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+ 
+ 		exp = nf_ct_expect_alloc(ct);
+ 		if (exp == NULL)
+ 			return NF_DROP;
+ 		tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+-		nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
++		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
++				  nf_ct_l3num(ct),
++				  &tuple->src.u3, &tuple->dst.u3,
+ 				  IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);
+ 
+ 		pr_debug("expect: ");
+-		NF_CT_DUMP_TUPLE(&exp->tuple);
++		nf_ct_dump_tuple(&exp->tuple);
+ 
+ 		nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
+ 		if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
+@@ -92,6 +93,11 @@ static int tftp_help(struct sk_buff *skb,
+ static struct nf_conntrack_helper tftp[MAX_PORTS][2] __read_mostly;
+ static char tftp_names[MAX_PORTS][2][sizeof("tftp-65535")] __read_mostly;
+ 
++static const struct nf_conntrack_expect_policy tftp_exp_policy = {
++	.max_expected	= 1,
++	.timeout	= 5 * 60,
++};
++
+ static void nf_conntrack_tftp_fini(void)
+ {
+ 	int i, j;
+@@ -118,8 +124,7 @@ static int __init nf_conntrack_tftp_init(void)
+ 		for (j = 0; j < 2; j++) {
+ 			tftp[i][j].tuple.dst.protonum = IPPROTO_UDP;
+ 			tftp[i][j].tuple.src.u.udp.port = htons(ports[i]);
+-			tftp[i][j].max_expected = 1;
+-			tftp[i][j].timeout = 5 * 60; /* 5 minutes */
++			tftp[i][j].expect_policy = &tftp_exp_policy;
+ 			tftp[i][j].me = THIS_MODULE;
+ 			tftp[i][j].help = tftp_help;
+ 
+diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
+index 3dd4b3c..69d699f 100644
+--- a/net/netfilter/nf_sockopt.c
++++ b/net/netfilter/nf_sockopt.c
+@@ -65,7 +65,7 @@ static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, int pf,
+ {
+ 	struct nf_sockopt_ops *ops;
+ 
+-	if (sk->sk_net != &init_net)
++	if (sock_net(sk) != &init_net)
+ 		return ERR_PTR(-ENOPROTOOPT);
+ 
+ 	if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
+diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
+index 10522c0..2c9fe5c 100644
+--- a/net/netfilter/nfnetlink_queue.c
++++ b/net/netfilter/nfnetlink_queue.c
+@@ -557,7 +557,7 @@ nfqnl_rcv_dev_event(struct notifier_block *this,
+ {
+ 	struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	/* Drop any packets associated with the downed device */
+diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
+index a679208..f52f7f8 100644
+--- a/net/netfilter/x_tables.c
++++ b/net/netfilter/x_tables.c
+@@ -58,7 +58,7 @@ static struct xt_af *xt;
+ #define duprintf(format, args...)
+ #endif
+ 
+-static const char *xt_prefix[NPROTO] = {
++static const char *const xt_prefix[NPROTO] = {
+ 	[AF_INET]	= "ip",
+ 	[AF_INET6]	= "ip6",
+ 	[NF_ARP]	= "arp",
+@@ -248,7 +248,7 @@ EXPORT_SYMBOL_GPL(xt_request_find_target);
+ 
+ static int match_revfn(int af, const char *name, u8 revision, int *bestp)
+ {
+-	struct xt_match *m;
++	const struct xt_match *m;
+ 	int have_rev = 0;
+ 
+ 	list_for_each_entry(m, &xt[af].match, list) {
+@@ -264,7 +264,7 @@ static int match_revfn(int af, const char *name, u8 revision, int *bestp)
+ 
+ static int target_revfn(int af, const char *name, u8 revision, int *bestp)
+ {
+-	struct xt_target *t;
++	const struct xt_target *t;
+ 	int have_rev = 0;
+ 
+ 	list_for_each_entry(t, &xt[af].target, list) {
+@@ -385,7 +385,7 @@ short xt_compat_calc_jump(int af, unsigned int offset)
+ }
+ EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
+ 
+-int xt_compat_match_offset(struct xt_match *match)
++int xt_compat_match_offset(const struct xt_match *match)
+ {
+ 	u_int16_t csize = match->compatsize ? : match->matchsize;
+ 	return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize);
+@@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(xt_compat_match_offset);
+ int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
+ 			      unsigned int *size)
+ {
+-	struct xt_match *match = m->u.kernel.match;
++	const struct xt_match *match = m->u.kernel.match;
+ 	struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
+ 	int pad, off = xt_compat_match_offset(match);
+ 	u_int16_t msize = cm->u.user.match_size;
+@@ -422,7 +422,7 @@ EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
+ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
+ 			    unsigned int *size)
+ {
+-	struct xt_match *match = m->u.kernel.match;
++	const struct xt_match *match = m->u.kernel.match;
+ 	struct compat_xt_entry_match __user *cm = *dstptr;
+ 	int off = xt_compat_match_offset(match);
+ 	u_int16_t msize = m->u.user.match_size - off;
+@@ -479,7 +479,7 @@ int xt_check_target(const struct xt_target *target, unsigned short family,
+ EXPORT_SYMBOL_GPL(xt_check_target);
+ 
+ #ifdef CONFIG_COMPAT
+-int xt_compat_target_offset(struct xt_target *target)
++int xt_compat_target_offset(const struct xt_target *target)
+ {
+ 	u_int16_t csize = target->compatsize ? : target->targetsize;
+ 	return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize);
+@@ -489,7 +489,7 @@ EXPORT_SYMBOL_GPL(xt_compat_target_offset);
+ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
+ 				unsigned int *size)
+ {
+-	struct xt_target *target = t->u.kernel.target;
++	const struct xt_target *target = t->u.kernel.target;
+ 	struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
+ 	int pad, off = xt_compat_target_offset(target);
+ 	u_int16_t tsize = ct->u.user.target_size;
+@@ -515,7 +515,7 @@ EXPORT_SYMBOL_GPL(xt_compat_target_from_user);
+ int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr,
+ 			     unsigned int *size)
+ {
+-	struct xt_target *target = t->u.kernel.target;
++	const struct xt_target *target = t->u.kernel.target;
+ 	struct compat_xt_entry_target __user *ct = *dstptr;
+ 	int off = xt_compat_target_offset(target);
+ 	u_int16_t tsize = t->u.user.target_size - off;
+@@ -727,7 +727,7 @@ struct xt_names_priv {
+ static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+ 	struct xt_names_priv *priv = seq->private;
+-	struct net *net = priv->p.net;
++	struct net *net = seq_file_net(seq);
+ 	int af = priv->af;
+ 
+ 	mutex_lock(&xt[af].mutex);
+@@ -737,7 +737,7 @@ static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos)
+ static void *xt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ 	struct xt_names_priv *priv = seq->private;
+-	struct net *net = priv->p.net;
++	struct net *net = seq_file_net(seq);
+ 	int af = priv->af;
+ 
+ 	return seq_list_next(v, &net->xt.tables[af], pos);
+diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
+index 1faa913..211189e 100644
+--- a/net/netfilter/xt_CONNSECMARK.c
++++ b/net/netfilter/xt_CONNSECMARK.c
+@@ -55,7 +55,7 @@ static void secmark_save(const struct sk_buff *skb)
+ static void secmark_restore(struct sk_buff *skb)
+ {
+ 	if (!skb->secmark) {
+-		struct nf_conn *ct;
++		const struct nf_conn *ct;
+ 		enum ip_conntrack_info ctinfo;
+ 
+ 		ct = nf_ct_get(skb, &ctinfo);
+diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
+index 24c73ba..64d6ad3 100644
+--- a/net/netfilter/xt_RATEEST.c
++++ b/net/netfilter/xt_RATEEST.c
+@@ -96,7 +96,7 @@ xt_rateest_tg_checkentry(const char *tablename,
+ 			 void *targinfo,
+ 			 unsigned int hook_mask)
+ {
+-	struct xt_rateest_target_info *info = (void *)targinfo;
++	struct xt_rateest_target_info *info = targinfo;
+ 	struct xt_rateest *est;
+ 	struct {
+ 		struct nlattr		opt;
+diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
+index 3b01119..2e89a00 100644
+--- a/net/netfilter/xt_connlimit.c
++++ b/net/netfilter/xt_connlimit.c
+@@ -72,9 +72,7 @@ connlimit_iphash6(const union nf_inet_addr *addr,
+ 
+ static inline bool already_closed(const struct nf_conn *conn)
+ {
+-	u_int16_t proto = conn->tuplehash[0].tuple.dst.protonum;
+-
+-	if (proto == IPPROTO_TCP)
++	if (nf_ct_protonum(conn) == IPPROTO_TCP)
+ 		return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT;
+ 	else
+ 		return 0;
+@@ -106,10 +104,10 @@ static int count_them(struct xt_connlimit_data *data,
+ 		      const union nf_inet_addr *mask,
+ 		      const struct xt_match *match)
+ {
+-	struct nf_conntrack_tuple_hash *found;
++	const struct nf_conntrack_tuple_hash *found;
+ 	struct xt_connlimit_conn *conn;
+ 	struct xt_connlimit_conn *tmp;
+-	struct nf_conn *found_ct;
++	const struct nf_conn *found_ct;
+ 	struct list_head *hash;
+ 	bool addit = true;
+ 	int matches = 0;
+@@ -256,7 +254,7 @@ connlimit_mt_check(const char *tablename, const void *ip,
+ static void
+ connlimit_mt_destroy(const struct xt_match *match, void *matchinfo)
+ {
+-	struct xt_connlimit_info *info = matchinfo;
++	const struct xt_connlimit_info *info = matchinfo;
+ 	struct xt_connlimit_conn *conn;
+ 	struct xt_connlimit_conn *tmp;
+ 	struct list_head *hash = info->data->iphash;
+diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
+index 0c50b28..d61412f 100644
+--- a/net/netfilter/xt_conntrack.c
++++ b/net/netfilter/xt_conntrack.c
+@@ -65,7 +65,7 @@ conntrack_mt_v0(const struct sk_buff *skb, const struct net_device *in,
+ 	}
+ 
+ 	if (sinfo->flags & XT_CONNTRACK_PROTO &&
+-	    FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
++	    FWINV(nf_ct_protonum(ct) !=
+ 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
+ 		  XT_CONNTRACK_PROTO))
+ 		return false;
+@@ -174,7 +174,7 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
+ 
+ 	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+ 	if ((info->match_flags & XT_CONNTRACK_PROTO) &&
+-	    (tuple->dst.protonum == info->l4proto) ^
++	    (nf_ct_protonum(ct) == info->l4proto) ^
+ 	    !(info->invert_flags & XT_CONNTRACK_PROTO))
+ 		return false;
+ 
+diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
+index 667f45e..8b65221 100644
+--- a/net/netfilter/xt_dccp.c
++++ b/net/netfilter/xt_dccp.c
+@@ -98,7 +98,8 @@ dccp_mt(const struct sk_buff *skb, const struct net_device *in,
+         const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+ 	const struct xt_dccp_info *info = matchinfo;
+-	struct dccp_hdr _dh, *dh;
++	const struct dccp_hdr *dh;
++	struct dccp_hdr _dh;
+ 
+ 	if (offset)
+ 		return false;
+diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
+index 71c7c37..a133eb9 100644
+--- a/net/netfilter/xt_esp.c
++++ b/net/netfilter/xt_esp.c
+@@ -47,7 +47,8 @@ esp_mt(const struct sk_buff *skb, const struct net_device *in,
+        const struct net_device *out, const struct xt_match *match,
+        const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+-	struct ip_esp_hdr _esp, *eh;
++	const struct ip_esp_hdr *eh;
++	struct ip_esp_hdr _esp;
+ 	const struct xt_esp *espinfo = matchinfo;
+ 
+ 	/* Must not be a fragment. */
+diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
+index 31daa81..fd88c48 100644
+--- a/net/netfilter/xt_multiport.c
++++ b/net/netfilter/xt_multiport.c
+@@ -100,7 +100,8 @@ multiport_mt_v0(const struct sk_buff *skb, const struct net_device *in,
+                 const void *matchinfo, int offset, unsigned int protoff,
+                 bool *hotdrop)
+ {
+-	__be16 _ports[2], *pptr;
++	const __be16 *pptr;
++	__be16 _ports[2];
+ 	const struct xt_multiport *multiinfo = matchinfo;
+ 
+ 	if (offset)
+@@ -126,7 +127,8 @@ multiport_mt(const struct sk_buff *skb, const struct net_device *in,
+              const void *matchinfo, int offset, unsigned int protoff,
+              bool *hotdrop)
+ {
+-	__be16 _ports[2], *pptr;
++	const __be16 *pptr;
++	__be16 _ports[2];
+ 	const struct xt_multiport_v1 *multiinfo = matchinfo;
+ 
+ 	if (offset)
+diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
+index 9e918ad..d351582 100644
+--- a/net/netfilter/xt_policy.c
++++ b/net/netfilter/xt_policy.c
+@@ -136,7 +136,7 @@ policy_mt_check(const char *tablename, const void *ip_void,
+                 const struct xt_match *match, void *matchinfo,
+                 unsigned int hook_mask)
+ {
+-	struct xt_policy_info *info = matchinfo;
++	const struct xt_policy_info *info = matchinfo;
+ 
+ 	if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
+ 		printk(KERN_ERR "xt_policy: neither incoming nor "
+diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c
+index fdb86a5..ebd84f1 100644
+--- a/net/netfilter/xt_rateest.c
++++ b/net/netfilter/xt_rateest.c
+@@ -86,7 +86,7 @@ static bool xt_rateest_mt_checkentry(const char *tablename,
+ 				     void *matchinfo,
+ 				     unsigned int hook_mask)
+ {
+-	struct xt_rateest_match_info *info = (void *)matchinfo;
++	struct xt_rateest_match_info *info = matchinfo;
+ 	struct xt_rateest *est1, *est2;
+ 
+ 	if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
+@@ -130,7 +130,7 @@ err1:
+ static void xt_rateest_mt_destroy(const struct xt_match *match,
+ 				  void *matchinfo)
+ {
+-	struct xt_rateest_match_info *info = (void *)matchinfo;
++	struct xt_rateest_match_info *info = matchinfo;
+ 
+ 	xt_rateest_put(info->est1);
+ 	if (info->est2)
+diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
+index b718ec6..e6e4681 100644
+--- a/net/netfilter/xt_sctp.c
++++ b/net/netfilter/xt_sctp.c
+@@ -46,7 +46,8 @@ match_packet(const struct sk_buff *skb,
+ 	     bool *hotdrop)
+ {
+ 	u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
+-	sctp_chunkhdr_t _sch, *sch;
++	const sctp_chunkhdr_t *sch;
++	sctp_chunkhdr_t _sch;
+ 	int chunk_match_type = info->chunk_match_type;
+ 	const struct xt_sctp_flag_info *flag_info = info->flag_info;
+ 	int flag_count = info->flag_count;
+@@ -121,7 +122,8 @@ sctp_mt(const struct sk_buff *skb, const struct net_device *in,
+         const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+ 	const struct xt_sctp_info *info = matchinfo;
+-	sctp_sctphdr_t _sh, *sh;
++	const sctp_sctphdr_t *sh;
++	sctp_sctphdr_t _sh;
+ 
+ 	if (offset) {
+ 		duprintf("Dropping non-first fragment.. FIXME\n");
+diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
+index d7a5b27..6771bf0 100644
+--- a/net/netfilter/xt_tcpmss.c
++++ b/net/netfilter/xt_tcpmss.c
+@@ -31,9 +31,11 @@ tcpmss_mt(const struct sk_buff *skb, const struct net_device *in,
+           bool *hotdrop)
+ {
+ 	const struct xt_tcpmss_match_info *info = matchinfo;
+-	struct tcphdr _tcph, *th;
++	const struct tcphdr *th;
++	struct tcphdr _tcph;
+ 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+-	u8 _opt[15 * 4 - sizeof(_tcph)], *op;
++	const u_int8_t *op;
++	u8 _opt[15 * 4 - sizeof(_tcph)];
+ 	unsigned int i, optlen;
+ 
+ 	/* If we don't have the whole header, drop packet. */
+diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
+index 4fa3b66..951b06b 100644
+--- a/net/netfilter/xt_tcpudp.c
++++ b/net/netfilter/xt_tcpudp.c
+@@ -42,7 +42,8 @@ tcp_find_option(u_int8_t option,
+ 		bool *hotdrop)
+ {
+ 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+-	u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
++	const u_int8_t *op;
++	u_int8_t _opt[60 - sizeof(struct tcphdr)];
+ 	unsigned int i;
+ 
+ 	duprintf("tcp_match: finding option\n");
+@@ -72,7 +73,8 @@ tcp_mt(const struct sk_buff *skb, const struct net_device *in,
+        const struct net_device *out, const struct xt_match *match,
+        const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+-	struct tcphdr _tcph, *th;
++	const struct tcphdr *th;
++	struct tcphdr _tcph;
+ 	const struct xt_tcp *tcpinfo = matchinfo;
+ 
+ 	if (offset) {
+@@ -144,7 +146,8 @@ udp_mt(const struct sk_buff *skb, const struct net_device *in,
+        const struct net_device *out, const struct xt_match *match,
+        const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+-	struct udphdr _udph, *uh;
++	const struct udphdr *uh;
++	struct udphdr _udph;
+ 	const struct xt_udp *udpinfo = matchinfo;
+ 
+ 	/* Must not be a fragment. */
+diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
+index 9fa2e08..ed76baa 100644
+--- a/net/netfilter/xt_time.c
++++ b/net/netfilter/xt_time.c
+@@ -223,7 +223,7 @@ time_mt_check(const char *tablename, const void *ip,
+               const struct xt_match *match, void *matchinfo,
+               unsigned int hook_mask)
+ {
+-	struct xt_time_info *info = matchinfo;
++	const struct xt_time_info *info = matchinfo;
+ 
+ 	if (info->daytime_start > XT_TIME_MAX_DAYTIME ||
+ 	    info->daytime_stop > XT_TIME_MAX_DAYTIME) {
+diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
+index 4478f2f..d282ad1 100644
+--- a/net/netlabel/netlabel_unlabeled.c
++++ b/net/netlabel/netlabel_unlabeled.c
+@@ -954,7 +954,7 @@ static int netlbl_unlhsh_netdev_handler(struct notifier_block *this,
+ 	struct net_device *dev = ptr;
+ 	struct netlbl_unlhsh_iface *iface = NULL;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	/* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */
+@@ -1339,6 +1339,10 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
+ 
+ 	if (iface->ifindex > 0) {
+ 		dev = dev_get_by_index(&init_net, iface->ifindex);
++		if (!dev) {
++			ret_val = -ENODEV;
++			goto list_cb_failure;
++		}
+ 		ret_val = nla_put_string(cb_arg->skb,
+ 					 NLBL_UNLABEL_A_IFACE, dev->name);
+ 		dev_put(dev);
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 1ab0da2..46f3e44 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -54,7 +54,6 @@
+ #include <linux/mm.h>
+ #include <linux/types.h>
+ #include <linux/audit.h>
+-#include <linux/selinux.h>
+ #include <linux/mutex.h>
+ 
+ #include <net/net_namespace.h>
+@@ -228,7 +227,7 @@ static inline struct sock *netlink_lookup(struct net *net, int protocol,
+ 	read_lock(&nl_table_lock);
+ 	head = nl_pid_hashfn(hash, pid);
+ 	sk_for_each(sk, node, head) {
+-		if ((sk->sk_net == net) && (nlk_sk(sk)->pid == pid)) {
++		if (net_eq(sock_net(sk), net) && (nlk_sk(sk)->pid == pid)) {
+ 			sock_hold(sk);
+ 			goto found;
+ 		}
+@@ -348,7 +347,7 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 pid)
+ 	head = nl_pid_hashfn(hash, pid);
+ 	len = 0;
+ 	sk_for_each(osk, node, head) {
+-		if ((osk->sk_net == net) && (nlk_sk(osk)->pid == pid))
++		if (net_eq(sock_net(osk), net) && (nlk_sk(osk)->pid == pid))
+ 			break;
+ 		len++;
+ 	}
+@@ -486,7 +485,7 @@ static int netlink_release(struct socket *sock)
+ 
+ 	if (nlk->pid && !nlk->subscriptions) {
+ 		struct netlink_notify n = {
+-						.net = sk->sk_net,
++						.net = sock_net(sk),
+ 						.protocol = sk->sk_protocol,
+ 						.pid = nlk->pid,
+ 					  };
+@@ -518,7 +517,7 @@ static int netlink_release(struct socket *sock)
+ static int netlink_autobind(struct socket *sock)
+ {
+ 	struct sock *sk = sock->sk;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 	struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
+ 	struct hlist_head *head;
+ 	struct sock *osk;
+@@ -532,7 +531,7 @@ retry:
+ 	netlink_table_grab();
+ 	head = nl_pid_hashfn(hash, pid);
+ 	sk_for_each(osk, node, head) {
+-		if ((osk->sk_net != net))
++		if (!net_eq(sock_net(osk), net))
+ 			continue;
+ 		if (nlk_sk(osk)->pid == pid) {
+ 			/* Bind collision, search negative pid values. */
+@@ -611,7 +610,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
+ 			int addr_len)
+ {
+ 	struct sock *sk = sock->sk;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 	struct netlink_sock *nlk = nlk_sk(sk);
+ 	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
+ 	int err;
+@@ -720,7 +719,7 @@ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
+ 	struct sock *sock;
+ 	struct netlink_sock *nlk;
+ 
+-	sock = netlink_lookup(ssk->sk_net, ssk->sk_protocol, pid);
++	sock = netlink_lookup(sock_net(ssk), ssk->sk_protocol, pid);
+ 	if (!sock)
+ 		return ERR_PTR(-ECONNREFUSED);
+ 
+@@ -886,6 +885,13 @@ retry:
+ 	if (netlink_is_kernel(sk))
+ 		return netlink_unicast_kernel(sk, skb);
+ 
++	if (sk_filter(sk, skb)) {
++		int err = skb->len;
++		kfree_skb(skb);
++		sock_put(sk);
++		return err;
++	}
++
+ 	err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk);
+ 	if (err == 1)
+ 		goto retry;
+@@ -955,7 +961,7 @@ static inline int do_one_broadcast(struct sock *sk,
+ 	    !test_bit(p->group - 1, nlk->groups))
+ 		goto out;
+ 
+-	if ((sk->sk_net != p->net))
++	if (!net_eq(sock_net(sk), p->net))
+ 		goto out;
+ 
+ 	if (p->failure) {
+@@ -980,6 +986,9 @@ static inline int do_one_broadcast(struct sock *sk,
+ 		netlink_overrun(sk);
+ 		/* Clone failed. Notify ALL listeners. */
+ 		p->failure = 1;
++	} else if (sk_filter(sk, p->skb2)) {
++		kfree_skb(p->skb2);
++		p->skb2 = NULL;
+ 	} else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
+ 		netlink_overrun(sk);
+ 	} else {
+@@ -996,7 +1005,7 @@ out:
+ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
+ 		      u32 group, gfp_t allocation)
+ {
+-	struct net *net = ssk->sk_net;
++	struct net *net = sock_net(ssk);
+ 	struct netlink_broadcast_data info;
+ 	struct hlist_node *node;
+ 	struct sock *sk;
+@@ -1054,7 +1063,7 @@ static inline int do_one_set_err(struct sock *sk,
+ 	if (sk == p->exclude_sk)
+ 		goto out;
+ 
+-	if (sk->sk_net != p->exclude_sk->sk_net)
++	if (sock_net(sk) != sock_net(p->exclude_sk))
+ 		goto out;
+ 
+ 	if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups ||
+@@ -1239,7 +1248,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
+ 	NETLINK_CB(skb).pid	= nlk->pid;
+ 	NETLINK_CB(skb).dst_group = dst_group;
+ 	NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
+-	selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
++	security_task_getsecid(current, &(NETLINK_CB(skb).sid));
+ 	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
+ 
+ 	/* What can I do? Netlink is asynchronous, so that
+@@ -1344,22 +1353,6 @@ static void netlink_data_ready(struct sock *sk, int len)
+  *	queueing.
+  */
+ 
+-static void __netlink_release(struct sock *sk)
+-{
+-	/*
+-	 * Last sock_put should drop referrence to sk->sk_net. It has already
+-	 * been dropped in netlink_kernel_create. Taking referrence to stopping
+-	 * namespace is not an option.
+-	 * Take referrence to a socket to remove it from netlink lookup table
+-	 * _alive_ and after that destroy it in the context of init_net.
+-	 */
+-
+-	sock_hold(sk);
+-	sock_release(sk->sk_socket);
+-	sk->sk_net = get_net(&init_net);
+-	sock_put(sk);
+-}
+-
+ struct sock *
+ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
+ 		      void (*input)(struct sk_buff *skb),
+@@ -1388,8 +1381,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
+ 		goto out_sock_release_nosk;
+ 
+ 	sk = sock->sk;
+-	put_net(sk->sk_net);
+-	sk->sk_net = net;
++	sk_change_net(sk, net);
+ 
+ 	if (groups < 32)
+ 		groups = 32;
+@@ -1424,7 +1416,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
+ 
+ out_sock_release:
+ 	kfree(listeners);
+-	__netlink_release(sk);
++	netlink_kernel_release(sk);
+ 	return NULL;
+ 
+ out_sock_release_nosk:
+@@ -1437,10 +1429,7 @@ EXPORT_SYMBOL(netlink_kernel_create);
+ void
+ netlink_kernel_release(struct sock *sk)
+ {
+-	if (sk == NULL || sk->sk_socket == NULL)
+-		return;
+-
+-	__netlink_release(sk);
++	sk_release_kernel(sk);
+ }
+ EXPORT_SYMBOL(netlink_kernel_release);
+ 
+@@ -1553,8 +1542,13 @@ static int netlink_dump(struct sock *sk)
+ 
+ 	if (len > 0) {
+ 		mutex_unlock(nlk->cb_mutex);
+-		skb_queue_tail(&sk->sk_receive_queue, skb);
+-		sk->sk_data_ready(sk, len);
++
++		if (sk_filter(sk, skb))
++			kfree_skb(skb);
++		else {
++			skb_queue_tail(&sk->sk_receive_queue, skb);
++			sk->sk_data_ready(sk, skb->len);
++		}
+ 		return 0;
+ 	}
+ 
+@@ -1564,8 +1558,12 @@ static int netlink_dump(struct sock *sk)
+ 
+ 	memcpy(nlmsg_data(nlh), &len, sizeof(len));
+ 
+-	skb_queue_tail(&sk->sk_receive_queue, skb);
+-	sk->sk_data_ready(sk, skb->len);
++	if (sk_filter(sk, skb))
++		kfree_skb(skb);
++	else {
++		skb_queue_tail(&sk->sk_receive_queue, skb);
++		sk->sk_data_ready(sk, skb->len);
++	}
+ 
+ 	if (cb->done)
+ 		cb->done(cb);
+@@ -1602,7 +1600,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+ 	atomic_inc(&skb->users);
+ 	cb->skb = skb;
+ 
+-	sk = netlink_lookup(ssk->sk_net, ssk->sk_protocol, NETLINK_CB(skb).pid);
++	sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).pid);
+ 	if (sk == NULL) {
+ 		netlink_destroy_callback(cb);
+ 		return -ECONNREFUSED;
+@@ -1644,7 +1642,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
+ 	if (!skb) {
+ 		struct sock *sk;
+ 
+-		sk = netlink_lookup(in_skb->sk->sk_net,
++		sk = netlink_lookup(sock_net(in_skb->sk),
+ 				    in_skb->sk->sk_protocol,
+ 				    NETLINK_CB(in_skb).pid);
+ 		if (sk) {
+@@ -1759,7 +1757,7 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos)
+ 
+ 		for (j = 0; j <= hash->mask; j++) {
+ 			sk_for_each(s, node, &hash->table[j]) {
+-				if (iter->p.net != s->sk_net)
++				if (sock_net(s) != seq_file_net(seq))
+ 					continue;
+ 				if (off == pos) {
+ 					iter->link = i;
+@@ -1795,7 +1793,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ 	s = v;
+ 	do {
+ 		s = sk_next(s);
+-	} while (s && (iter->p.net != s->sk_net));
++	} while (s && sock_net(s) != seq_file_net(seq));
+ 	if (s)
+ 		return s;
+ 
+@@ -1807,7 +1805,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ 
+ 		for (; j <= hash->mask; j++) {
+ 			s = sk_head(&hash->table[j]);
+-			while (s && (iter->p.net != s->sk_net))
++			while (s && sock_net(s) != seq_file_net(seq))
+ 				s = sk_next(s);
+ 			if (s) {
+ 				iter->link = i;
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index 972250c..4bae8b9 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -106,7 +106,7 @@ static int nr_device_event(struct notifier_block *this, unsigned long event, voi
+ {
+ 	struct net_device *dev = (struct net_device *)ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event != NETDEV_DOWN)
+@@ -466,7 +466,7 @@ static struct sock *nr_make_new(struct sock *osk)
+ 	if (osk->sk_type != SOCK_SEQPACKET)
+ 		return NULL;
+ 
+-	sk = sk_alloc(osk->sk_net, PF_NETROM, GFP_ATOMIC, osk->sk_prot);
++	sk = sk_alloc(sock_net(osk), PF_NETROM, GFP_ATOMIC, osk->sk_prot);
+ 	if (sk == NULL)
+ 		return NULL;
+ 
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index b8b827c..2507024 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -263,7 +263,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,  struct
+ 	if (skb->pkt_type == PACKET_LOOPBACK)
+ 		goto out;
+ 
+-	if (dev->nd_net != sk->sk_net)
++	if (dev_net(dev) != sock_net(sk))
+ 		goto out;
+ 
+ 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+@@ -337,7 +337,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
+ 	 */
+ 
+ 	saddr->spkt_device[13] = 0;
+-	dev = dev_get_by_name(sk->sk_net, saddr->spkt_device);
++	dev = dev_get_by_name(sock_net(sk), saddr->spkt_device);
+ 	err = -ENODEV;
+ 	if (dev == NULL)
+ 		goto out_unlock;
+@@ -451,7 +451,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
+ 	sk = pt->af_packet_priv;
+ 	po = pkt_sk(sk);
+ 
+-	if (dev->nd_net != sk->sk_net)
++	if (dev_net(dev) != sock_net(sk))
+ 		goto drop;
+ 
+ 	skb->dev = dev;
+@@ -568,7 +568,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
+ 	sk = pt->af_packet_priv;
+ 	po = pkt_sk(sk);
+ 
+-	if (dev->nd_net != sk->sk_net)
++	if (dev_net(dev) != sock_net(sk))
+ 		goto drop;
+ 
+ 	if (dev->header_ops) {
+@@ -728,7 +728,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
+ 	}
+ 
+ 
+-	dev = dev_get_by_index(sk->sk_net, ifindex);
++	dev = dev_get_by_index(sock_net(sk), ifindex);
+ 	err = -ENXIO;
+ 	if (dev == NULL)
+ 		goto out_unlock;
+@@ -800,7 +800,7 @@ static int packet_release(struct socket *sock)
+ 	if (!sk)
+ 		return 0;
+ 
+-	net = sk->sk_net;
++	net = sock_net(sk);
+ 	po = pkt_sk(sk);
+ 
+ 	write_lock_bh(&net->packet.sklist_lock);
+@@ -914,7 +914,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int add
+ 		return -EINVAL;
+ 	strlcpy(name,uaddr->sa_data,sizeof(name));
+ 
+-	dev = dev_get_by_name(sk->sk_net, name);
++	dev = dev_get_by_name(sock_net(sk), name);
+ 	if (dev) {
+ 		err = packet_do_bind(sk, dev, pkt_sk(sk)->num);
+ 		dev_put(dev);
+@@ -941,7 +941,7 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
+ 
+ 	if (sll->sll_ifindex) {
+ 		err = -ENODEV;
+-		dev = dev_get_by_index(sk->sk_net, sll->sll_ifindex);
++		dev = dev_get_by_index(sock_net(sk), sll->sll_ifindex);
+ 		if (dev == NULL)
+ 			goto out;
+ 	}
+@@ -1135,7 +1135,7 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
+ 		return -EOPNOTSUPP;
+ 
+ 	uaddr->sa_family = AF_PACKET;
+-	dev = dev_get_by_index(sk->sk_net, pkt_sk(sk)->ifindex);
++	dev = dev_get_by_index(sock_net(sk), pkt_sk(sk)->ifindex);
+ 	if (dev) {
+ 		strlcpy(uaddr->sa_data, dev->name, 15);
+ 		dev_put(dev);
+@@ -1160,7 +1160,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
+ 	sll->sll_family = AF_PACKET;
+ 	sll->sll_ifindex = po->ifindex;
+ 	sll->sll_protocol = po->num;
+-	dev = dev_get_by_index(sk->sk_net, po->ifindex);
++	dev = dev_get_by_index(sock_net(sk), po->ifindex);
+ 	if (dev) {
+ 		sll->sll_hatype = dev->type;
+ 		sll->sll_halen = dev->addr_len;
+@@ -1212,7 +1212,7 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq)
+ 	rtnl_lock();
+ 
+ 	err = -ENODEV;
+-	dev = __dev_get_by_index(sk->sk_net, mreq->mr_ifindex);
++	dev = __dev_get_by_index(sock_net(sk), mreq->mr_ifindex);
+ 	if (!dev)
+ 		goto done;
+ 
+@@ -1266,7 +1266,7 @@ static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq)
+ 			if (--ml->count == 0) {
+ 				struct net_device *dev;
+ 				*mlp = ml->next;
+-				dev = dev_get_by_index(sk->sk_net, ml->ifindex);
++				dev = dev_get_by_index(sock_net(sk), ml->ifindex);
+ 				if (dev) {
+ 					packet_dev_mc(dev, ml, -1);
+ 					dev_put(dev);
+@@ -1294,7 +1294,7 @@ static void packet_flush_mclist(struct sock *sk)
+ 		struct net_device *dev;
+ 
+ 		po->mclist = ml->next;
+-		if ((dev = dev_get_by_index(sk->sk_net, ml->ifindex)) != NULL) {
++		if ((dev = dev_get_by_index(sock_net(sk), ml->ifindex)) != NULL) {
+ 			packet_dev_mc(dev, ml, -1);
+ 			dev_put(dev);
+ 		}
+@@ -1450,7 +1450,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
+ 	struct sock *sk;
+ 	struct hlist_node *node;
+ 	struct net_device *dev = data;
+-	struct net *net = dev->nd_net;
++	struct net *net = dev_net(dev);
+ 
+ 	read_lock(&net->packet.sklist_lock);
+ 	sk_for_each(sk, node, &net->packet.sklist) {
+@@ -1540,7 +1540,7 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
+ 		case SIOCGIFDSTADDR:
+ 		case SIOCSIFDSTADDR:
+ 		case SIOCSIFFLAGS:
+-			if (sk->sk_net != &init_net)
++			if (sock_net(sk) != &init_net)
+ 				return -ENOIOCTLCMD;
+ 			return inet_dgram_ops.ioctl(sock, cmd, arg);
+ #endif
+@@ -1658,7 +1658,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
+ 	int err = 0;
+ 
+ 	if (req->tp_block_nr) {
+-		int i, l;
++		int i;
+ 
+ 		/* Sanity tests and some calculations */
+ 
+@@ -1687,7 +1687,6 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
+ 		if (unlikely(!pg_vec))
+ 			goto out;
+ 
+-		l = 0;
+ 		for (i = 0; i < req->tp_block_nr; i++) {
+ 			char *ptr = pg_vec[i];
+ 			struct tpacket_hdr *header;
+diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
+index 063cbc5..1ebf652 100644
+--- a/net/rose/af_rose.c
++++ b/net/rose/af_rose.c
+@@ -197,7 +197,7 @@ static int rose_device_event(struct notifier_block *this, unsigned long event,
+ {
+ 	struct net_device *dev = (struct net_device *)ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event != NETDEV_DOWN)
+@@ -551,7 +551,7 @@ static struct sock *rose_make_new(struct sock *osk)
+ 	if (osk->sk_type != SOCK_SEQPACKET)
+ 		return NULL;
+ 
+-	sk = sk_alloc(osk->sk_net, PF_ROSE, GFP_ATOMIC, &rose_proto);
++	sk = sk_alloc(sock_net(osk), PF_ROSE, GFP_ATOMIC, &rose_proto);
+ 	if (sk == NULL)
+ 		return NULL;
+ 
+@@ -760,8 +760,10 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
+ 
+ 	rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause,
+ 					 &diagnostic);
+-	if (!rose->neighbour)
+-		return -ENETUNREACH;
++	if (!rose->neighbour) {
++		err = -ENETUNREACH;
++		goto out_release;
++	}
+ 
+ 	rose->lci = rose_new_lci(rose->neighbour);
+ 	if (!rose->lci) {
+diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
+index fb9359f..5053a53 100644
+--- a/net/rose/rose_route.c
++++ b/net/rose/rose_route.c
+@@ -857,7 +857,6 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+ 	src_addr  = (rose_address *)(skb->data + 9);
+ 	dest_addr = (rose_address *)(skb->data + 4);
+ 
+-	spin_lock_bh(&rose_node_list_lock);
+ 	spin_lock_bh(&rose_neigh_list_lock);
+ 	spin_lock_bh(&rose_route_list_lock);
+ 
+@@ -1060,7 +1059,6 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+ out:
+ 	spin_unlock_bh(&rose_route_list_lock);
+ 	spin_unlock_bh(&rose_neigh_list_lock);
+-	spin_unlock_bh(&rose_node_list_lock);
+ 
+ 	return res;
+ }
+diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
+index 53fe94c..3e7318c 100644
+--- a/net/rxrpc/ar-internal.h
++++ b/net/rxrpc/ar-internal.h
+@@ -619,8 +619,8 @@ void _dbprintk(const char *fmt, ...)
+ {
+ }
+ 
+-#define kenter(FMT,...)	dbgprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__)
+-#define kleave(FMT,...)	dbgprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__)
++#define kenter(FMT,...)	dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__)
++#define kleave(FMT,...)	dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__)
+ #define kdebug(FMT,...)	dbgprintk("    "FMT ,##__VA_ARGS__)
+ #define kproto(FMT,...)	dbgprintk("### "FMT ,##__VA_ARGS__)
+ #define knet(FMT,...)	dbgprintk("@@@ "FMT ,##__VA_ARGS__)
+@@ -671,8 +671,8 @@ do {							\
+ } while (0)
+ 
+ #else
+-#define _enter(FMT,...)	_dbprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__)
+-#define _leave(FMT,...)	_dbprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__)
++#define _enter(FMT,...)	_dbprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__)
++#define _leave(FMT,...)	_dbprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__)
+ #define _debug(FMT,...)	_dbprintk("    "FMT ,##__VA_ARGS__)
+ #define _proto(FMT,...)	_dbprintk("### "FMT ,##__VA_ARGS__)
+ #define _net(FMT,...)	_dbprintk("@@@ "FMT ,##__VA_ARGS__)
+diff --git a/net/rxrpc/ar-proc.c b/net/rxrpc/ar-proc.c
+index 83eda24..017322e 100644
+--- a/net/rxrpc/ar-proc.c
++++ b/net/rxrpc/ar-proc.c
+@@ -103,7 +103,7 @@ const struct file_operations rxrpc_call_seq_fops = {
+ 	.open		= rxrpc_call_seq_open,
+ 	.read		= seq_read,
+ 	.llseek		= seq_lseek,
+-	.release	= seq_release_private,
++	.release	= seq_release,
+ };
+ 
+ /*
+@@ -188,5 +188,5 @@ const struct file_operations rxrpc_connection_seq_fops = {
+ 	.open		= rxrpc_connection_seq_open,
+ 	.read		= seq_read,
+ 	.llseek		= seq_lseek,
+-	.release	= seq_release_private,
++	.release	= seq_release,
+ };
+diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
+index 6d38a81..ba3f6e4 100644
+--- a/net/rxrpc/rxkad.c
++++ b/net/rxrpc/rxkad.c
+@@ -493,8 +493,8 @@ static int rxkad_verify_packet(const struct rxrpc_call *call,
+ 		__be32 x[2];
+ 	} tmpbuf __attribute__((aligned(8))); /* must all be in same page */
+ 	__be32 x;
+-	u16 y;
+ 	__be16 cksum;
++	u32 y;
+ 	int ret;
+ 
+ 	sp = rxrpc_skb(skb);
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index 0b8eb23..74e662c 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -951,7 +951,7 @@ done:
+ 
+ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct nlattr *tca[TCA_ACT_MAX + 1];
+ 	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
+ 	int ret = 0, ovr = 0;
+@@ -1029,7 +1029,7 @@ find_dump_kind(struct nlmsghdr *n)
+ static int
+ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct nlmsghdr *nlh;
+ 	unsigned char *b = skb_tail_pointer(skb);
+ 	struct nlattr *nest;
+diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
+index fbde461..64b2d13 100644
+--- a/net/sched/act_simple.c
++++ b/net/sched/act_simple.c
+@@ -115,7 +115,7 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
+ 		return -EINVAL;
+ 
+ 	datalen = nla_len(tb[TCA_DEF_DATA]);
+-	if (datalen <= 0)
++	if (datalen == 0)
+ 		return -EINVAL;
+ 
+ 	pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info);
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index 0fbedca..1086df7 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -118,7 +118,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
+ 
+ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct nlattr *tca[TCA_MAX + 1];
+ 	struct tcmsg *t;
+ 	u32 protocol;
+@@ -389,7 +389,7 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n,
+ 
+ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	int t;
+ 	int s_t;
+ 	struct net_device *dev;
+diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
+index 3da4129..72cf86e 100644
+--- a/net/sched/em_meta.c
++++ b/net/sched/em_meta.c
+@@ -256,10 +256,10 @@ META_COLLECTOR(int_rtclassid)
+ 
+ META_COLLECTOR(int_rtiif)
+ {
+-	if (unlikely(skb->dst == NULL))
++	if (unlikely(skb->rtable == NULL))
+ 		*err = -1;
+ 	else
+-		dst->value = ((struct rtable*) skb->dst)->fl.iif;
++		dst->value = skb->rtable->fl.iif;
+ }
+ 
+ /**************************************************************************
+diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
+index fc8708a..c40773c 100644
+--- a/net/sched/sch_api.c
++++ b/net/sched/sch_api.c
+@@ -608,7 +608,7 @@ check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w)
+ 
+ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct tcmsg *tcm = NLMSG_DATA(n);
+ 	struct nlattr *tca[TCA_MAX + 1];
+ 	struct net_device *dev;
+@@ -677,7 +677,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ 
+ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct tcmsg *tcm;
+ 	struct nlattr *tca[TCA_MAX + 1];
+ 	struct net_device *dev;
+@@ -896,7 +896,7 @@ err_out:
+ 
+ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	int idx, q_idx;
+ 	int s_idx, s_q_idx;
+ 	struct net_device *dev;
+@@ -948,7 +948,7 @@ done:
+ 
+ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	struct tcmsg *tcm = NLMSG_DATA(n);
+ 	struct nlattr *tca[TCA_MAX + 1];
+ 	struct net_device *dev;
+@@ -1142,7 +1142,7 @@ static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walk
+ 
+ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+-	struct net *net = skb->sk->sk_net;
++	struct net *net = sock_net(skb->sk);
+ 	int t;
+ 	int s_t;
+ 	struct net_device *dev;
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index d29f792..b4cd2b7 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -718,12 +718,11 @@ struct sctp_transport *sctp_assoc_lookup_paddr(
+ 					const union sctp_addr *address)
+ {
+ 	struct sctp_transport *t;
+-	struct list_head *pos;
+ 
+ 	/* Cycle through all transports searching for a peer address. */
+ 
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		t = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(t, &asoc->peer.transport_addr_list,
++			transports) {
+ 		if (sctp_cmp_addr_exact(address, &t->ipaddr))
+ 			return t;
+ 	}
+@@ -762,7 +761,6 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
+ 	struct sctp_transport *second;
+ 	struct sctp_ulpevent *event;
+ 	struct sockaddr_storage addr;
+-	struct list_head *pos;
+ 	int spc_state = 0;
+ 
+ 	/* Record the transition on the transport.  */
+@@ -814,8 +812,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
+ 	 */
+ 	first = NULL; second = NULL;
+ 
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		t = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(t, &asoc->peer.transport_addr_list,
++			transports) {
+ 
+ 		if ((t->state == SCTP_INACTIVE) ||
+ 		    (t->state == SCTP_UNCONFIRMED))
+@@ -932,7 +930,6 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
+ {
+ 	struct sctp_transport *active;
+ 	struct sctp_transport *match;
+-	struct list_head *entry, *pos;
+ 	struct sctp_transport *transport;
+ 	struct sctp_chunk *chunk;
+ 	__be32 key = htonl(tsn);
+@@ -956,8 +953,8 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
+ 
+ 	active = asoc->peer.active_path;
+ 
+-	list_for_each(entry, &active->transmitted) {
+-		chunk = list_entry(entry, struct sctp_chunk, transmitted_list);
++	list_for_each_entry(chunk, &active->transmitted,
++			transmitted_list) {
+ 
+ 		if (key == chunk->subh.data_hdr->tsn) {
+ 			match = active;
+@@ -966,14 +963,13 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
+ 	}
+ 
+ 	/* If not found, go search all the other transports. */
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		transport = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(transport, &asoc->peer.transport_addr_list,
++			transports) {
+ 
+ 		if (transport == active)
+ 			break;
+-		list_for_each(entry, &transport->transmitted) {
+-			chunk = list_entry(entry, struct sctp_chunk,
+-					   transmitted_list);
++		list_for_each_entry(chunk, &transport->transmitted,
++				transmitted_list) {
+ 			if (key == chunk->subh.data_hdr->tsn) {
+ 				match = transport;
+ 				goto out;
+@@ -1154,9 +1150,8 @@ void sctp_assoc_update(struct sctp_association *asoc,
+ 
+ 	} else {
+ 		/* Add any peer addresses from the new association. */
+-		list_for_each(pos, &new->peer.transport_addr_list) {
+-			trans = list_entry(pos, struct sctp_transport,
+-					   transports);
++		list_for_each_entry(trans, &new->peer.transport_addr_list,
++				transports) {
+ 			if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
+ 				sctp_assoc_add_peer(asoc, &trans->ipaddr,
+ 						    GFP_ATOMIC, trans->state);
+@@ -1306,15 +1301,14 @@ struct sctp_transport *sctp_assoc_choose_shutdown_transport(
+ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
+ {
+ 	struct sctp_transport *t;
+-	struct list_head *pos;
+ 	__u32 pmtu = 0;
+ 
+ 	if (!asoc)
+ 		return;
+ 
+ 	/* Get the lowest pmtu of all the transports. */
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		t = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(t, &asoc->peer.transport_addr_list,
++				transports) {
+ 		if (t->pmtu_pending && t->dst) {
+ 			sctp_transport_update_pmtu(t, dst_mtu(t->dst));
+ 			t->pmtu_pending = 0;
+@@ -1330,7 +1324,7 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
+ 	}
+ 
+ 	SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n",
+-			  __FUNCTION__, asoc, asoc->pathmtu, asoc->frag_point);
++			  __func__, asoc, asoc->pathmtu, asoc->frag_point);
+ }
+ 
+ /* Should we send a SACK to update our peer? */
+@@ -1370,7 +1364,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
+ 	}
+ 
+ 	SCTP_DEBUG_PRINTK("%s: asoc %p rwnd increased by %d to (%u, %u) "
+-			  "- %u\n", __FUNCTION__, asoc, len, asoc->rwnd,
++			  "- %u\n", __func__, asoc, len, asoc->rwnd,
+ 			  asoc->rwnd_over, asoc->a_rwnd);
+ 
+ 	/* Send a window update SACK if the rwnd has increased by at least the
+@@ -1381,7 +1375,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
+ 	if (sctp_peer_needs_update(asoc)) {
+ 		asoc->a_rwnd = asoc->rwnd;
+ 		SCTP_DEBUG_PRINTK("%s: Sending window update SACK- asoc: %p "
+-				  "rwnd: %u a_rwnd: %u\n", __FUNCTION__,
++				  "rwnd: %u a_rwnd: %u\n", __func__,
+ 				  asoc, asoc->rwnd, asoc->a_rwnd);
+ 		sack = sctp_make_sack(asoc);
+ 		if (!sack)
+@@ -1410,7 +1404,7 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len)
+ 		asoc->rwnd = 0;
+ 	}
+ 	SCTP_DEBUG_PRINTK("%s: asoc %p rwnd decreased by %d to (%u, %u)\n",
+-			  __FUNCTION__, asoc, len, asoc->rwnd,
++			  __func__, asoc, len, asoc->rwnd,
+ 			  asoc->rwnd_over);
+ }
+ 
+diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
+index ceefda0..80e6df0 100644
+--- a/net/sctp/bind_addr.c
++++ b/net/sctp/bind_addr.c
+@@ -67,15 +67,13 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
+ 			int flags)
+ {
+ 	struct sctp_sockaddr_entry *addr;
+-	struct list_head *pos;
+ 	int error = 0;
+ 
+ 	/* All addresses share the same port.  */
+ 	dest->port = src->port;
+ 
+ 	/* Extract the addresses which are relevant for this scope.  */
+-	list_for_each(pos, &src->address_list) {
+-		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
++	list_for_each_entry(addr, &src->address_list, list) {
+ 		error = sctp_copy_one_addr(dest, &addr->a, scope,
+ 					   gfp, flags);
+ 		if (error < 0)
+@@ -87,9 +85,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
+ 	 * the assumption that we must be sitting behind a NAT.
+ 	 */
+ 	if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
+-		list_for_each(pos, &src->address_list) {
+-			addr = list_entry(pos, struct sctp_sockaddr_entry,
+-					  list);
++		list_for_each_entry(addr, &src->address_list, list) {
+ 			error = sctp_copy_one_addr(dest, &addr->a,
+ 						   SCTP_SCOPE_LINK, gfp,
+ 						   flags);
+@@ -115,14 +111,12 @@ int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
+ 			gfp_t gfp)
+ {
+ 	struct sctp_sockaddr_entry *addr;
+-	struct list_head *pos;
+ 	int error = 0;
+ 
+ 	/* All addresses share the same port.  */
+ 	dest->port = src->port;
+ 
+-	list_for_each(pos, &src->address_list) {
+-		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
++	list_for_each_entry(addr, &src->address_list, list) {
+ 		error = sctp_add_bind_addr(dest, &addr->a, 1, gfp);
+ 		if (error < 0)
+ 			break;
+@@ -273,8 +267,7 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
+ 
+ 	addrparms = retval;
+ 
+-	list_for_each(pos, &bp->address_list) {
+-		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
++	list_for_each_entry(addr, &bp->address_list, list) {
+ 		af = sctp_get_af_specific(addr->a.v4.sin_family);
+ 		len = af->to_addr_param(&addr->a, &rawaddr);
+ 		memcpy(addrparms.v, &rawaddr, len);
+diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
+index 4d3128f..1748ef9 100644
+--- a/net/sctp/chunk.c
++++ b/net/sctp/chunk.c
+@@ -66,9 +66,10 @@ SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp)
+ {
+ 	struct sctp_datamsg *msg;
+ 	msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
+-	if (msg)
++	if (msg) {
+ 		sctp_datamsg_init(msg);
+-	SCTP_DBG_OBJCNT_INC(datamsg);
++		SCTP_DBG_OBJCNT_INC(datamsg);
++	}
+ 	return msg;
+ }
+ 
+@@ -136,20 +137,6 @@ void sctp_datamsg_put(struct sctp_datamsg *msg)
+ 		sctp_datamsg_destroy(msg);
+ }
+ 
+-/* Free a message.  Really just give up a reference, the
+- * really free happens in sctp_datamsg_destroy().
+- */
+-void sctp_datamsg_free(struct sctp_datamsg *msg)
+-{
+-	sctp_datamsg_put(msg);
+-}
+-
+-/* Hold on to all the fragments until all chunks have been sent. */
+-void sctp_datamsg_track(struct sctp_chunk *chunk)
+-{
+-	sctp_chunk_hold(chunk);
+-}
+-
+ /* Assign a chunk to this datamsg. */
+ static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
+ {
+@@ -189,7 +176,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
+ 				    msecs_to_jiffies(sinfo->sinfo_timetolive);
+ 		msg->can_abandon = 1;
+ 		SCTP_DEBUG_PRINTK("%s: msg:%p expires_at: %ld jiffies:%ld\n",
+-				  __FUNCTION__, msg, msg->expires_at, jiffies);
++				  __func__, msg, msg->expires_at, jiffies);
+ 	}
+ 
+ 	max = asoc->frag_point;
+@@ -295,7 +282,7 @@ errout:
+ 		chunk = list_entry(pos, struct sctp_chunk, frag_list);
+ 		sctp_chunk_free(chunk);
+ 	}
+-	sctp_datamsg_free(msg);
++	sctp_datamsg_put(msg);
+ 	return NULL;
+ }
+ 
+diff --git a/net/sctp/command.c b/net/sctp/command.c
+index bb97733..c004401 100644
+--- a/net/sctp/command.c
++++ b/net/sctp/command.c
+@@ -52,18 +52,12 @@ int sctp_init_cmd_seq(sctp_cmd_seq_t *seq)
+ /* Add a command to a sctp_cmd_seq_t.
+  * Return 0 if the command sequence is full.
+  */
+-int sctp_add_cmd(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj)
++void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj)
+ {
+-	if (seq->next_free_slot >= SCTP_MAX_NUM_COMMANDS)
+-		goto fail;
++	BUG_ON(seq->next_free_slot >= SCTP_MAX_NUM_COMMANDS);
+ 
+ 	seq->cmds[seq->next_free_slot].verb = verb;
+ 	seq->cmds[seq->next_free_slot++].obj = obj;
+-
+-	return 1;
+-
+-fail:
+-	return 0;
+ }
+ 
+ /* Return the next command structure in a sctp_cmd_seq.
+diff --git a/net/sctp/input.c b/net/sctp/input.c
+index 812ff17..ca6b022 100644
+--- a/net/sctp/input.c
++++ b/net/sctp/input.c
+@@ -409,7 +409,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
+ 			   struct sctp_association *asoc,
+ 			   struct sctp_transport *t)
+ {
+-	SCTP_DEBUG_PRINTK("%s\n",  __FUNCTION__);
++	SCTP_DEBUG_PRINTK("%s\n",  __func__);
+ 
+ 	sctp_do_sm(SCTP_EVENT_T_OTHER,
+ 		   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
+@@ -725,7 +725,6 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
+ 	}
+ 
+ 	ep = sctp_sk((sctp_get_ctl_sock()))->ep;
+-	epb = &ep->base;
+ 
+ hit:
+ 	sctp_endpoint_hold(ep);
+diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
+index 85f1495..e45e44c 100644
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -226,7 +226,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
+ 
+ 	SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
+ 			  "src:" NIP6_FMT " dst:" NIP6_FMT "\n",
+-			  __FUNCTION__, skb, skb->len,
++			  __func__, skb, skb->len,
+ 			  NIP6(fl.fl6_src), NIP6(fl.fl6_dst));
+ 
+ 	SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
+@@ -251,7 +251,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
+ 
+ 
+ 	SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ",
+-			  __FUNCTION__, NIP6(fl.fl6_dst));
++			  __func__, NIP6(fl.fl6_dst));
+ 
+ 	if (saddr) {
+ 		ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr);
+@@ -260,7 +260,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
+ 			NIP6(fl.fl6_src));
+ 	}
+ 
+-	dst = ip6_route_output(NULL, &fl);
++	dst = ip6_route_output(&init_net, NULL, &fl);
+ 	if (!dst->error) {
+ 		struct rt6_info *rt;
+ 		rt = (struct rt6_info *)dst;
+@@ -313,10 +313,13 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
+ 
+ 	SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
+ 			  "daddr:" NIP6_FMT " ",
+-			  __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr));
++			  __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));
+ 
+ 	if (!asoc) {
+-		ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr);
++		ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL,
++				   &daddr->v6.sin6_addr,
++				   inet6_sk(asoc->base.sk)->srcprefs,
++				   &saddr->v6.sin6_addr);
+ 		SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n",
+ 				  NIP6(saddr->v6.sin6_addr));
+ 		return;
+@@ -351,7 +354,7 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
+ 	} else {
+ 		printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
+ 		       "address for the dest:" NIP6_FMT "\n",
+-		       __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr));
++		       __func__, asoc, NIP6(daddr->v6.sin6_addr));
+ 	}
+ 
+ 	rcu_read_unlock();
+@@ -634,7 +637,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
+ 	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
+ 	struct sctp6_sock *newsctp6sk;
+ 
+-	newsk = sk_alloc(sk->sk_net, PF_INET6, GFP_KERNEL, sk->sk_prot);
++	newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot);
+ 	if (!newsk)
+ 		goto out;
+ 
+diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c
+index cfeb07e..f73ec0e 100644
+--- a/net/sctp/objcnt.c
++++ b/net/sctp/objcnt.c
+@@ -83,13 +83,12 @@ static sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
+  */
+ static int sctp_objcnt_seq_show(struct seq_file *seq, void *v)
+ {
+-	int i;
+-	char temp[128];
++	int i, len;
+ 
+ 	i = (int)*(loff_t *)v;
+-	sprintf(temp, "%s: %d", sctp_dbg_objcnt[i].label,
+-				atomic_read(sctp_dbg_objcnt[i].counter));
+-	seq_printf(seq, "%-127s\n", temp);
++	seq_printf(seq, "%s: %d%n", sctp_dbg_objcnt[i].label,
++				atomic_read(sctp_dbg_objcnt[i].counter), &len);
++	seq_printf(seq, "%*s\n", 127 - len, "");
+ 	return 0;
+ }
+ 
+diff --git a/net/sctp/output.c b/net/sctp/output.c
+index aa700fe..cf4f9fb 100644
+--- a/net/sctp/output.c
++++ b/net/sctp/output.c
+@@ -74,7 +74,7 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet,
+ {
+ 	struct sctp_chunk *chunk = NULL;
+ 
+-	SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __FUNCTION__,
++	SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__,
+ 			  packet, vtag);
+ 
+ 	packet->vtag = vtag;
+@@ -106,7 +106,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
+ 	struct sctp_association *asoc = transport->asoc;
+ 	size_t overhead;
+ 
+-	SCTP_DEBUG_PRINTK("%s: packet:%p transport:%p\n", __FUNCTION__,
++	SCTP_DEBUG_PRINTK("%s: packet:%p transport:%p\n", __func__,
+ 			  packet, transport);
+ 
+ 	packet->transport = transport;
+@@ -138,7 +138,7 @@ void sctp_packet_free(struct sctp_packet *packet)
+ {
+ 	struct sctp_chunk *chunk, *tmp;
+ 
+-	SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
++	SCTP_DEBUG_PRINTK("%s: packet:%p\n", __func__, packet);
+ 
+ 	list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
+ 		list_del_init(&chunk->list);
+@@ -162,7 +162,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
+ 	sctp_xmit_t retval;
+ 	int error = 0;
+ 
+-	SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__,
++	SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__,
+ 			  packet, chunk);
+ 
+ 	switch ((retval = (sctp_packet_append_chunk(packet, chunk)))) {
+@@ -264,7 +264,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
+ 	size_t pmtu;
+ 	int too_big;
+ 
+-	SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet,
++	SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__, packet,
+ 			  chunk);
+ 
+ 	/* Try to bundle AUTH chunk */
+@@ -372,7 +372,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
+ 	unsigned char *auth = NULL;	/* pointer to auth in skb data */
+ 	__u32 cksum_buf_len = sizeof(struct sctphdr);
+ 
+-	SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
++	SCTP_DEBUG_PRINTK("%s: packet:%p\n", __func__, packet);
+ 
+ 	/* Do NOT generate a chunkless packet. */
+ 	if (list_empty(&packet->chunk_list))
+@@ -677,7 +677,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
+ 				  "transport: %p, cwnd: %d, "
+ 				  "ssthresh: %d, flight_size: %d, "
+ 				  "pba: %d\n",
+-				  __FUNCTION__, transport,
++				  __func__, transport,
+ 				  transport->cwnd,
+ 				  transport->ssthresh,
+ 				  transport->flight_size,
+diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
+index c071446..59edfd2 100644
+--- a/net/sctp/outqueue.c
++++ b/net/sctp/outqueue.c
+@@ -221,12 +221,12 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
+ void sctp_outq_teardown(struct sctp_outq *q)
+ {
+ 	struct sctp_transport *transport;
+-	struct list_head *lchunk, *pos, *temp;
++	struct list_head *lchunk, *temp;
+ 	struct sctp_chunk *chunk, *tmp;
+ 
+ 	/* Throw away unacknowledged chunks. */
+-	list_for_each(pos, &q->asoc->peer.transport_addr_list) {
+-		transport = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(transport, &q->asoc->peer.transport_addr_list,
++			transports) {
+ 		while ((lchunk = sctp_list_dequeue(&transport->transmitted)) != NULL) {
+ 			chunk = list_entry(lchunk, struct sctp_chunk,
+ 					   transmitted_list);
+@@ -469,7 +469,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
+ 
+ 	SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, "
+ 			  "cwnd: %d, ssthresh: %d, flight_size: %d, "
+-			  "pba: %d\n", __FUNCTION__,
++			  "pba: %d\n", __func__,
+ 			  transport, reason,
+ 			  transport->cwnd, transport->ssthresh,
+ 			  transport->flight_size,
+@@ -494,6 +494,8 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
+ 		 */
+ 		if (transport == transport->asoc->peer.retran_path)
+ 			sctp_assoc_update_retran_path(transport->asoc);
++		transport->asoc->rtx_data_chunks +=
++			transport->asoc->unack_data;
+ 		break;
+ 	case SCTP_RTXR_FAST_RTX:
+ 		SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
+@@ -504,6 +506,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
+ 		break;
+ 	case SCTP_RTXR_T1_RTX:
+ 		SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
++		transport->asoc->init_retries++;
+ 		break;
+ 	default:
+ 		BUG();
+@@ -535,7 +538,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
+ 			       int rtx_timeout, int *start_timer)
+ {
+ 	struct list_head *lqueue;
+-	struct list_head *lchunk, *lchunk1;
++	struct list_head *lchunk;
+ 	struct sctp_transport *transport = pkt->transport;
+ 	sctp_xmit_t status;
+ 	struct sctp_chunk *chunk, *chunk1;
+@@ -646,9 +649,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
+ 		 * to be marked as ineligible for a subsequent fast retransmit.
+ 		 */
+ 		if (rtx_timeout && !lchunk) {
+-			list_for_each(lchunk1, lqueue) {
+-				chunk1 = list_entry(lchunk1, struct sctp_chunk,
+-						    transmitted_list);
++			list_for_each_entry(chunk1, lqueue, transmitted_list) {
+ 				if (chunk1->fast_retransmit > 0)
+ 					chunk1->fast_retransmit = -1;
+ 			}
+@@ -1037,7 +1038,6 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc,
+ static __u32 sctp_highest_new_tsn(struct sctp_sackhdr *sack,
+ 				  struct sctp_association *asoc)
+ {
+-	struct list_head *ltransport, *lchunk;
+ 	struct sctp_transport *transport;
+ 	struct sctp_chunk *chunk;
+ 	__u32 highest_new_tsn, tsn;
+@@ -1045,12 +1045,9 @@ static __u32 sctp_highest_new_tsn(struct sctp_sackhdr *sack,
+ 
+ 	highest_new_tsn = ntohl(sack->cum_tsn_ack);
+ 
+-	list_for_each(ltransport, transport_list) {
+-		transport = list_entry(ltransport, struct sctp_transport,
+-				       transports);
+-		list_for_each(lchunk, &transport->transmitted) {
+-			chunk = list_entry(lchunk, struct sctp_chunk,
+-					   transmitted_list);
++	list_for_each_entry(transport, transport_list, transports) {
++		list_for_each_entry(chunk, &transport->transmitted,
++				transmitted_list) {
+ 			tsn = ntohl(chunk->subh.data_hdr->tsn);
+ 
+ 			if (!chunk->tsn_gap_acked &&
+@@ -1073,7 +1070,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ 	struct sctp_association *asoc = q->asoc;
+ 	struct sctp_transport *transport;
+ 	struct sctp_chunk *tchunk = NULL;
+-	struct list_head *lchunk, *transport_list, *pos, *temp;
++	struct list_head *lchunk, *transport_list, *temp;
+ 	sctp_sack_variable_t *frags = sack->variable;
+ 	__u32 sack_ctsn, ctsn, tsn;
+ 	__u32 highest_tsn, highest_new_tsn;
+@@ -1099,9 +1096,8 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ 	 */
+ 	if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) {
+ 		primary->cacc.changeover_active = 0;
+-		list_for_each(pos, transport_list) {
+-			transport = list_entry(pos, struct sctp_transport,
+-					transports);
++		list_for_each_entry(transport, transport_list,
++				transports) {
+ 			transport->cacc.cycling_changeover = 0;
+ 		}
+ 	}
+@@ -1116,9 +1112,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ 	 */
+ 	if (sack->num_gap_ack_blocks &&
+ 	    primary->cacc.changeover_active) {
+-		list_for_each(pos, transport_list) {
+-			transport = list_entry(pos, struct sctp_transport,
+-					transports);
++		list_for_each_entry(transport, transport_list, transports) {
+ 			transport->cacc.cacc_saw_newack = 0;
+ 		}
+ 	}
+@@ -1147,9 +1141,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ 	 *
+ 	 * This is a MASSIVE candidate for optimization.
+ 	 */
+-	list_for_each(pos, transport_list) {
+-		transport  = list_entry(pos, struct sctp_transport,
+-					transports);
++	list_for_each_entry(transport, transport_list, transports) {
+ 		sctp_check_transmitted(q, &transport->transmitted,
+ 				       transport, sack, highest_new_tsn);
+ 		/*
+@@ -1161,9 +1153,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ 			count_of_newacks ++;
+ 	}
+ 
+-	list_for_each(pos, transport_list) {
+-		transport  = list_entry(pos, struct sctp_transport,
+-					transports);
++	list_for_each_entry(transport, transport_list, transports) {
+ 		sctp_mark_missing(q, &transport->transmitted, transport,
+ 				  highest_new_tsn, count_of_newacks);
+ 	}
+@@ -1206,10 +1196,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ 	sctp_generate_fwdtsn(q, sack_ctsn);
+ 
+ 	SCTP_DEBUG_PRINTK("%s: sack Cumulative TSN Ack is 0x%x.\n",
+-			  __FUNCTION__, sack_ctsn);
++			  __func__, sack_ctsn);
+ 	SCTP_DEBUG_PRINTK("%s: Cumulative TSN Ack of association, "
+ 			  "%p is 0x%x. Adv peer ack point: 0x%x\n",
+-			  __FUNCTION__, asoc, ctsn, asoc->adv_peer_ack_point);
++			  __func__, asoc, ctsn, asoc->adv_peer_ack_point);
+ 
+ 	/* See if all chunks are acked.
+ 	 * Make sure the empty queue handler will get run later.
+@@ -1220,9 +1210,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ 	if (!q->empty)
+ 		goto finish;
+ 
+-	list_for_each(pos, transport_list) {
+-		transport  = list_entry(pos, struct sctp_transport,
+-					transports);
++	list_for_each_entry(transport, transport_list, transports) {
+ 		q->empty = q->empty && list_empty(&transport->transmitted);
+ 		if (!q->empty)
+ 			goto finish;
+@@ -1444,7 +1432,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
+ 			if (tchunk->tsn_gap_acked) {
+ 				SCTP_DEBUG_PRINTK("%s: Receiver reneged on "
+ 						  "data TSN: 0x%x\n",
+-						  __FUNCTION__,
++						  __func__,
+ 						  tsn);
+ 				tchunk->tsn_gap_acked = 0;
+ 
+@@ -1544,6 +1532,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
+ 						  bytes_acked);
+ 
+ 			transport->flight_size -= bytes_acked;
++			if (transport->flight_size == 0)
++				transport->partial_bytes_acked = 0;
+ 			q->outstanding_bytes -= bytes_acked;
+ 		} else {
+ 			/* RFC 2960 6.1, sctpimpguide-06 2.15.2
+@@ -1561,7 +1551,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
+ 			    (sack_ctsn+2 == q->asoc->next_tsn)) {
+ 				SCTP_DEBUG_PRINTK("%s: SACK received for zero "
+ 						  "window probe: %u\n",
+-						  __FUNCTION__, sack_ctsn);
++						  __func__, sack_ctsn);
+ 				q->asoc->overall_error_count = 0;
+ 				transport->error_count = 0;
+ 			}
+@@ -1596,14 +1586,12 @@ static void sctp_mark_missing(struct sctp_outq *q,
+ 			      int count_of_newacks)
+ {
+ 	struct sctp_chunk *chunk;
+-	struct list_head *pos;
+ 	__u32 tsn;
+ 	char do_fast_retransmit = 0;
+ 	struct sctp_transport *primary = q->asoc->peer.primary_path;
+ 
+-	list_for_each(pos, transmitted_queue) {
++	list_for_each_entry(chunk, transmitted_queue, transmitted_list) {
+ 
+-		chunk = list_entry(pos, struct sctp_chunk, transmitted_list);
+ 		tsn = ntohl(chunk->subh.data_hdr->tsn);
+ 
+ 		/* RFC 2960 7.2.4, sctpimpguide-05 2.8.2 M3) Examine all
+@@ -1626,7 +1614,7 @@ static void sctp_mark_missing(struct sctp_outq *q,
+ 
+ 				SCTP_DEBUG_PRINTK(
+ 					"%s: TSN 0x%x missing counter: %d\n",
+-					__FUNCTION__, tsn,
++					__func__, tsn,
+ 					chunk->tsn_missing_report);
+ 			}
+ 		}
+@@ -1649,7 +1637,7 @@ static void sctp_mark_missing(struct sctp_outq *q,
+ 
+ 		SCTP_DEBUG_PRINTK("%s: transport: %p, cwnd: %d, "
+ 				  "ssthresh: %d, flight_size: %d, pba: %d\n",
+-				  __FUNCTION__, transport, transport->cwnd,
++				  __func__, transport, transport->cwnd,
+ 				  transport->ssthresh, transport->flight_size,
+ 				  transport->partial_bytes_acked);
+ 	}
+diff --git a/net/sctp/proc.c b/net/sctp/proc.c
+index 973f1db..0aba759 100644
+--- a/net/sctp/proc.c
++++ b/net/sctp/proc.c
+@@ -124,7 +124,6 @@ void sctp_snmp_proc_exit(void)
+ /* Dump local addresses of an association/endpoint. */
+ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
+ {
+-	struct list_head *pos;
+ 	struct sctp_association *asoc;
+ 	struct sctp_sockaddr_entry *laddr;
+ 	struct sctp_transport *peer;
+@@ -137,8 +136,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
+ 	    primary = &peer->saddr;
+ 	}
+ 
+-	list_for_each(pos, &epb->bind_addr.address_list) {
+-		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
++	list_for_each_entry(laddr, &epb->bind_addr.address_list, list) {
+ 		addr = &laddr->a;
+ 		af = sctp_get_af_specific(addr->sa.sa_family);
+ 		if (primary && af->cmp_addr(addr, primary)) {
+@@ -151,14 +149,13 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
+ /* Dump remote addresses of an association. */
+ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc)
+ {
+-	struct list_head *pos;
+ 	struct sctp_transport *transport;
+ 	union sctp_addr *addr, *primary;
+ 	struct sctp_af *af;
+ 
+ 	primary = &assoc->peer.primary_addr;
+-	list_for_each(pos, &assoc->peer.transport_addr_list) {
+-		transport = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(transport, &assoc->peer.transport_addr_list,
++			transports) {
+ 		addr = &transport->ipaddr;
+ 		af = sctp_get_af_specific(addr->sa.sa_family);
+ 		if (af->cmp_addr(addr, primary)) {
+@@ -279,8 +276,10 @@ static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
+ 		*pos = 0;
+ 
+ 	if (*pos == 0)
+-		seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
+-				"RPORT LADDRS <-> RADDRS\n");
++		seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT "
++				"ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
++				"RPORT LADDRS <-> RADDRS "
++				"HBINT INS OUTS MAXRT T1X T2X RTXC\n");
+ 
+ 	return (void *)pos;
+ }
+@@ -319,19 +318,25 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
+ 		assoc = sctp_assoc(epb);
+ 		sk = epb->sk;
+ 		seq_printf(seq,
+-			   "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
++			   "%8p %8p %-3d %-3d %-2d %-4d "
++			   "%4d %8d %8d %7d %5lu %-5d %5d ",
+ 			   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
+-			   assoc->state, hash, assoc->assoc_id,
++			   assoc->state, hash,
++			   assoc->assoc_id,
+ 			   assoc->sndbuf_used,
+ 			   atomic_read(&assoc->rmem_alloc),
+ 			   sock_i_uid(sk), sock_i_ino(sk),
+ 			   epb->bind_addr.port,
+ 			   assoc->peer.port);
+-
+ 		seq_printf(seq, " ");
+ 		sctp_seq_dump_local_addrs(seq, epb);
+ 		seq_printf(seq, "<-> ");
+ 		sctp_seq_dump_remote_addrs(seq, assoc);
++		seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d ",
++			assoc->hbinterval, assoc->c.sinit_max_instreams,
++			assoc->c.sinit_num_ostreams, assoc->max_retrans,
++			assoc->init_retries, assoc->shutdown_retries,
++			assoc->rtx_data_chunks);
+ 		seq_printf(seq, "\n");
+ 	}
+ 	read_unlock(&head->lock);
+diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
+index c2dd65d..0ec234b 100644
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -74,7 +74,7 @@ DEFINE_SPINLOCK(sctp_assocs_id_lock);
+  * the Out-of-the-blue (OOTB) packets.  A control sock will be created
+  * for this socket at the initialization time.
+  */
+-static struct socket *sctp_ctl_socket;
++static struct sock *sctp_ctl_sock;
+ 
+ static struct sctp_pf *sctp_pf_inet6_specific;
+ static struct sctp_pf *sctp_pf_inet_specific;
+@@ -91,7 +91,7 @@ int sysctl_sctp_wmem[3];
+ /* Return the address of the control sock. */
+ struct sock *sctp_get_ctl_sock(void)
+ {
+-	return sctp_ctl_socket->sk;
++	return sctp_ctl_sock;
+ }
+ 
+ /* Set up the proc fs entry for the SCTP protocol. */
+@@ -363,7 +363,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
+ 		return 0;
+ 
+ 	/* Is this a broadcast address? */
+-	if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST)
++	if (skb && skb->rtable->rt_flags & RTCF_BROADCAST)
+ 		return 0;
+ 
+ 	return 1;
+@@ -451,7 +451,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
+ 		fl.fl4_src = saddr->v4.sin_addr.s_addr;
+ 
+ 	SCTP_DEBUG_PRINTK("%s: DST:%u.%u.%u.%u, SRC:%u.%u.%u.%u - ",
+-			  __FUNCTION__, NIPQUAD(fl.fl4_dst),
++			  __func__, NIPQUAD(fl.fl4_dst),
+ 			  NIPQUAD(fl.fl4_src));
+ 
+ 	if (!ip_route_output_key(&init_net, &rt, &fl)) {
+@@ -539,7 +539,7 @@ static void sctp_v4_get_saddr(struct sctp_association *asoc,
+ /* What interface did this skb arrive on? */
+ static int sctp_v4_skb_iif(const struct sk_buff *skb)
+ {
+-	return ((struct rtable *)skb->dst)->rt_iif;
++	return skb->rtable->rt_iif;
+ }
+ 
+ /* Was this packet marked by Explicit Congestion Notification? */
+@@ -554,7 +554,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
+ {
+ 	struct inet_sock *inet = inet_sk(sk);
+ 	struct inet_sock *newinet;
+-	struct sock *newsk = sk_alloc(sk->sk_net, PF_INET, GFP_KERNEL,
++	struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL,
+ 			sk->sk_prot);
+ 
+ 	if (!newsk)
+@@ -630,6 +630,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
+ 	struct sctp_sockaddr_entry *temp;
+ 	int found = 0;
+ 
++	if (dev_net(ifa->ifa_dev->dev) != &init_net)
++		return NOTIFY_DONE;
++
+ 	switch (ev) {
+ 	case NETDEV_UP:
+ 		addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+@@ -679,16 +682,13 @@ static int sctp_ctl_sock_init(void)
+ 	else
+ 		family = PF_INET;
+ 
+-	err = sock_create_kern(family, SOCK_SEQPACKET, IPPROTO_SCTP,
+-			       &sctp_ctl_socket);
++	err = inet_ctl_sock_create(&sctp_ctl_sock, family,
++				   SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
+ 	if (err < 0) {
+ 		printk(KERN_ERR
+ 		       "SCTP: Failed to create the SCTP control socket.\n");
+ 		return err;
+ 	}
+-	sctp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
+-	inet_sk(sctp_ctl_socket->sk)->uc_ttl = -1;
+-
+ 	return 0;
+ }
+ 
+@@ -828,9 +828,9 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
+ {
+ 	SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
+ 			  "src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n",
+-			  __FUNCTION__, skb, skb->len,
+-			  NIPQUAD(((struct rtable *)skb->dst)->rt_src),
+-			  NIPQUAD(((struct rtable *)skb->dst)->rt_dst));
++			  __func__, skb, skb->len,
++			  NIPQUAD(skb->rtable->rt_src),
++			  NIPQUAD(skb->rtable->rt_dst));
+ 
+ 	SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
+ 	return ip_queue_xmit(skb, ipfragok);
+@@ -974,24 +974,14 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
+ 	return 1;
+ }
+ 
+-static int __init init_sctp_mibs(void)
++static inline int init_sctp_mibs(void)
+ {
+-	sctp_statistics[0] = alloc_percpu(struct sctp_mib);
+-	if (!sctp_statistics[0])
+-		return -ENOMEM;
+-	sctp_statistics[1] = alloc_percpu(struct sctp_mib);
+-	if (!sctp_statistics[1]) {
+-		free_percpu(sctp_statistics[0]);
+-		return -ENOMEM;
+-	}
+-	return 0;
+-
++	return snmp_mib_init((void**)sctp_statistics, sizeof(struct sctp_mib));
+ }
+ 
+-static void cleanup_sctp_mibs(void)
++static inline void cleanup_sctp_mibs(void)
+ {
+-	free_percpu(sctp_statistics[0]);
+-	free_percpu(sctp_statistics[1]);
++	snmp_mib_free((void**)sctp_statistics);
+ }
+ 
+ static void sctp_v4_pf_init(void)
+@@ -1286,7 +1276,7 @@ err_v6_add_protocol:
+ 	sctp_v6_del_protocol();
+ err_add_protocol:
+ 	sctp_v4_del_protocol();
+-	sock_release(sctp_ctl_socket);
++	inet_ctl_sock_destroy(sctp_ctl_sock);
+ err_ctl_sock_init:
+ 	sctp_v6_protosw_exit();
+ err_v6_protosw_init:
+@@ -1330,7 +1320,7 @@ SCTP_STATIC __exit void sctp_exit(void)
+ 	sctp_v4_del_protocol();
+ 
+ 	/* Free the control endpoint.  */
+-	sock_release(sctp_ctl_socket);
++	inet_ctl_sock_destroy(sctp_ctl_sock);
+ 
+ 	/* Free protosw registrations */
+ 	sctp_v6_protosw_exit();
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 36ebb39..81b6064 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -1782,7 +1782,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
+ 					const struct sctp_chunk *chunk,
+ 					struct sctp_chunk **errp)
+ {
+-	char		error[] = "The following parameter had invalid length:";
++	static const char error[] = "The following parameter had invalid length:";
+ 	size_t		payload_len = WORD_ROUND(sizeof(error)) +
+ 						sizeof(sctp_paramhdr_t);
+ 
+@@ -2269,8 +2269,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
+ 	 * high (for example, implementations MAY use the size of the receiver
+ 	 * advertised window).
+ 	 */
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		transport = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(transport, &asoc->peer.transport_addr_list,
++			transports) {
+ 		transport->ssthresh = asoc->peer.i.a_rwnd;
+ 	}
+ 
+@@ -3066,7 +3066,6 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
+ 	union sctp_addr	addr;
+ 	struct sctp_bind_addr *bp = &asoc->base.bind_addr;
+ 	union sctp_addr_param *addr_param;
+-	struct list_head *pos;
+ 	struct sctp_transport *transport;
+ 	struct sctp_sockaddr_entry *saddr;
+ 	int retval = 0;
+@@ -3094,9 +3093,8 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
+ 		local_bh_disable();
+ 		retval = sctp_del_bind_addr(bp, &addr);
+ 		local_bh_enable();
+-		list_for_each(pos, &asoc->peer.transport_addr_list) {
+-			transport = list_entry(pos, struct sctp_transport,
+-						 transports);
++		list_for_each_entry(transport, &asoc->peer.transport_addr_list,
++				transports) {
+ 			dst_release(transport->dst);
+ 			sctp_transport_route(transport, NULL,
+ 					     sctp_sk(asoc->base.sk));
+diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
+index a4763fd..23a9f1a 100644
+--- a/net/sctp/sm_sideeffect.c
++++ b/net/sctp/sm_sideeffect.c
+@@ -243,7 +243,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
+ 
+ 	sctp_bh_lock_sock(asoc->base.sk);
+ 	if (sock_owned_by_user(asoc->base.sk)) {
+-		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __FUNCTION__);
++		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
+ 
+ 		/* Try again later.  */
+ 		if (!mod_timer(&transport->T3_rtx_timer, jiffies + (HZ/20)))
+@@ -283,7 +283,7 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
+ 	sctp_bh_lock_sock(asoc->base.sk);
+ 	if (sock_owned_by_user(asoc->base.sk)) {
+ 		SCTP_DEBUG_PRINTK("%s:Sock is busy: timer %d\n",
+-				  __FUNCTION__,
++				  __func__,
+ 				  timeout_type);
+ 
+ 		/* Try again later.  */
+@@ -361,7 +361,7 @@ void sctp_generate_heartbeat_event(unsigned long data)
+ 
+ 	sctp_bh_lock_sock(asoc->base.sk);
+ 	if (sock_owned_by_user(asoc->base.sk)) {
+-		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __FUNCTION__);
++		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
+ 
+ 		/* Try again later.  */
+ 		if (!mod_timer(&transport->hb_timer, jiffies + (HZ/20)))
+@@ -545,14 +545,12 @@ static void sctp_cmd_hb_timers_start(sctp_cmd_seq_t *cmds,
+ 				     struct sctp_association *asoc)
+ {
+ 	struct sctp_transport *t;
+-	struct list_head *pos;
+ 
+ 	/* Start a heartbeat timer for each transport on the association.
+ 	 * hold a reference on the transport to make sure none of
+ 	 * the needed data structures go away.
+ 	 */
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		t = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) {
+ 
+ 		if (!mod_timer(&t->hb_timer, sctp_transport_timeout(t)))
+ 			sctp_transport_hold(t);
+@@ -563,12 +561,11 @@ static void sctp_cmd_hb_timers_stop(sctp_cmd_seq_t *cmds,
+ 				    struct sctp_association *asoc)
+ {
+ 	struct sctp_transport *t;
+-	struct list_head *pos;
+ 
+ 	/* Stop all heartbeat timers. */
+ 
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		t = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(t, &asoc->peer.transport_addr_list,
++			transports) {
+ 		if (del_timer(&t->hb_timer))
+ 			sctp_transport_put(t);
+ 	}
+@@ -579,10 +576,9 @@ static void sctp_cmd_t3_rtx_timers_stop(sctp_cmd_seq_t *cmds,
+ 					struct sctp_association *asoc)
+ {
+ 	struct sctp_transport *t;
+-	struct list_head *pos;
+ 
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		t = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(t, &asoc->peer.transport_addr_list,
++			transports) {
+ 		if (timer_pending(&t->T3_rtx_timer) &&
+ 		    del_timer(&t->T3_rtx_timer)) {
+ 			sctp_transport_put(t);
+@@ -593,7 +589,6 @@ static void sctp_cmd_t3_rtx_timers_stop(sctp_cmd_seq_t *cmds,
+ 
+ /* Helper function to update the heartbeat timer. */
+ static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds,
+-				     struct sctp_association *asoc,
+ 				     struct sctp_transport *t)
+ {
+ 	/* Update the heartbeat timer.  */
+@@ -1065,7 +1060,6 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
+ 	struct sctp_chunk *new_obj;
+ 	struct sctp_chunk *chunk = NULL;
+ 	struct sctp_packet *packet;
+-	struct list_head *pos;
+ 	struct timer_list *timer;
+ 	unsigned long timeout;
+ 	struct sctp_transport *t;
+@@ -1397,9 +1391,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
+ 			/* If we've sent any data bundled with
+ 			 * COOKIE-ECHO we need to resend.
+ 			 */
+-			list_for_each(pos, &asoc->peer.transport_addr_list) {
+-				t = list_entry(pos, struct sctp_transport,
+-					       transports);
++			list_for_each_entry(t, &asoc->peer.transport_addr_list,
++					transports) {
+ 				sctp_retransmit_mark(&asoc->outqueue, t,
+ 					    SCTP_RTXR_T1_RTX);
+ 			}
+@@ -1457,7 +1450,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
+ 
+ 		case SCTP_CMD_HB_TIMER_UPDATE:
+ 			t = cmd->obj.transport;
+-			sctp_cmd_hb_timer_update(commands, asoc, t);
++			sctp_cmd_hb_timer_update(commands, t);
+ 			break;
+ 
+ 		case SCTP_CMD_HB_TIMERS_STOP:
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 07194c2..0c9d5a6 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -1124,7 +1124,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
+ 				printk(KERN_WARNING
+ 				    "%s association %p could not find address "
+ 				    NIP6_FMT "\n",
+-				    __FUNCTION__,
++				    __func__,
+ 				    asoc,
+ 				    NIP6(from_addr.v6.sin6_addr));
+ 		} else {
+@@ -1132,7 +1132,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
+ 				printk(KERN_WARNING
+ 				    "%s association %p could not find address "
+ 				    NIPQUAD_FMT "\n",
+-				    __FUNCTION__,
++				    __func__,
+ 				    asoc,
+ 				    NIPQUAD(from_addr.v4.sin_addr.s_addr));
+ 		}
+@@ -1150,7 +1150,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
+ 	    time_after(jiffies, hbinfo->sent_at + max_interval)) {
+ 		SCTP_DEBUG_PRINTK("%s: HEARTBEAT ACK with invalid timestamp "
+ 				  "received for transport: %p\n",
+-				   __FUNCTION__, link);
++				   __func__, link);
+ 		return SCTP_DISPOSITION_DISCARD;
+ 	}
+ 
+@@ -1226,7 +1226,6 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
+ 				       sctp_cmd_seq_t *commands)
+ {
+ 	struct sctp_transport *new_addr, *addr;
+-	struct list_head *pos, *pos2;
+ 	int found;
+ 
+ 	/* Implementor's Guide - Sectin 5.2.2
+@@ -1243,12 +1242,11 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
+ 	new_addr = NULL;
+ 	found = 0;
+ 
+-	list_for_each(pos, &new_asoc->peer.transport_addr_list) {
+-		new_addr = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list,
++			transports) {
+ 		found = 0;
+-		list_for_each(pos2, &asoc->peer.transport_addr_list) {
+-			addr = list_entry(pos2, struct sctp_transport,
+-					  transports);
++		list_for_each_entry(addr, &asoc->peer.transport_addr_list,
++				transports) {
+ 			if (sctp_cmp_addr_exact(&new_addr->ipaddr,
+ 						&addr->ipaddr)) {
+ 				found = 1;
+@@ -3135,12 +3133,8 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
+ 		if (!ev)
+ 			goto nomem;
+ 
+-		if (!sctp_add_cmd(commands, SCTP_CMD_EVENT_ULP,
+-				  SCTP_ULPEVENT(ev))) {
+-			sctp_ulpevent_free(ev);
+-			goto nomem;
+-		}
+-
++		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
++				SCTP_ULPEVENT(ev));
+ 		sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
+ 				SCTP_CHUNK(chunk));
+ 	}
+@@ -3668,7 +3662,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
+ 	skb_pull(chunk->skb, len);
+ 
+ 	tsn = ntohl(fwdtsn_hdr->new_cum_tsn);
+-	SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __FUNCTION__, tsn);
++	SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __func__, tsn);
+ 
+ 	/* The TSN is too high--silently discard the chunk and count on it
+ 	 * getting retransmitted later.
+@@ -3728,7 +3722,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
+ 	skb_pull(chunk->skb, len);
+ 
+ 	tsn = ntohl(fwdtsn_hdr->new_cum_tsn);
+-	SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __FUNCTION__, tsn);
++	SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __func__, tsn);
+ 
+ 	/* The TSN is too high--silently discard the chunk and count on it
+ 	 * getting retransmitted later.
+@@ -4237,7 +4231,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
+ 				     void *arg,
+ 				     sctp_cmd_seq_t *commands)
+ {
+-	char err_str[]="The following chunk had invalid length:";
++	static const char err_str[]="The following chunk had invalid length:";
+ 
+ 	return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+ 					sizeof(err_str));
+@@ -4254,7 +4248,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
+ 				     const sctp_subtype_t type,
+ 				     void *arg,
+ 				     sctp_cmd_seq_t *commands) {
+-	char err_str[] = "The following parameter had invalid length:";
++	static const char err_str[] = "The following parameter had invalid length:";
+ 
+ 	return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+ 					sizeof(err_str));
+@@ -4273,7 +4267,7 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
+ 				     void *arg,
+ 				     sctp_cmd_seq_t *commands)
+ {
+-	char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:";
++	static const char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:";
+ 
+ 	return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+ 					sizeof(err_str));
+@@ -4292,7 +4286,7 @@ static sctp_disposition_t sctp_sf_violation_chunk(
+ 				     void *arg,
+ 				     sctp_cmd_seq_t *commands)
+ {
+-	char err_str[]="The following chunk violates protocol:";
++	static const char err_str[]="The following chunk violates protocol:";
+ 
+ 	if (!asoc)
+ 		return sctp_sf_violation(ep, asoc, type, arg, commands);
+@@ -5331,6 +5325,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
+ 	SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
+ 	SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
+ 
++	((struct sctp_association *)asoc)->shutdown_retries++;
++
+ 	if (asoc->overall_error_count >= asoc->max_retrans) {
+ 		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ 				SCTP_ERROR(ETIMEDOUT));
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 998e63a..e7e3baf 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -513,7 +513,6 @@ static int sctp_send_asconf_add_ip(struct sock		*sk,
+ 	union sctp_addr			saveaddr;
+ 	void				*addr_buf;
+ 	struct sctp_af			*af;
+-	struct list_head		*pos;
+ 	struct list_head		*p;
+ 	int 				i;
+ 	int 				retval = 0;
+@@ -525,10 +524,9 @@ static int sctp_send_asconf_add_ip(struct sock		*sk,
+ 	ep = sp->ep;
+ 
+ 	SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
+-			  __FUNCTION__, sk, addrs, addrcnt);
++			  __func__, sk, addrs, addrcnt);
+ 
+-	list_for_each(pos, &ep->asocs) {
+-		asoc = list_entry(pos, struct sctp_association, asocs);
++	list_for_each_entry(asoc, &ep->asocs, asocs) {
+ 
+ 		if (!asoc->peer.asconf_capable)
+ 			continue;
+@@ -699,7 +697,6 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
+ 	union sctp_addr		*laddr;
+ 	void			*addr_buf;
+ 	struct sctp_af		*af;
+-	struct list_head	*pos, *pos1;
+ 	struct sctp_sockaddr_entry *saddr;
+ 	int 			i;
+ 	int 			retval = 0;
+@@ -711,10 +708,9 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
+ 	ep = sp->ep;
+ 
+ 	SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
+-			  __FUNCTION__, sk, addrs, addrcnt);
++			  __func__, sk, addrs, addrcnt);
+ 
+-	list_for_each(pos, &ep->asocs) {
+-		asoc = list_entry(pos, struct sctp_association, asocs);
++	list_for_each_entry(asoc, &ep->asocs, asocs) {
+ 
+ 		if (!asoc->peer.asconf_capable)
+ 			continue;
+@@ -787,9 +783,8 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
+ 		 * as some of the addresses in the bind address list are
+ 		 * about to be deleted and cannot be used as source addresses.
+ 		 */
+-		list_for_each(pos1, &asoc->peer.transport_addr_list) {
+-			transport = list_entry(pos1, struct sctp_transport,
+-					       transports);
++		list_for_each_entry(transport, &asoc->peer.transport_addr_list,
++					transports) {
+ 			dst_release(transport->dst);
+ 			sctp_transport_route(transport, NULL,
+ 					     sctp_sk(asoc->base.sk));
+@@ -1197,7 +1192,7 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
+ 	struct sockaddr *kaddrs;
+ 
+ 	SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
+-			  __FUNCTION__, sk, addrs, addrs_size);
++			  __func__, sk, addrs, addrs_size);
+ 
+ 	if (unlikely(addrs_size <= 0))
+ 		return -EINVAL;
+@@ -1397,7 +1392,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
+ 	long timeo;
+ 	__u16 sinfo_flags = 0;
+ 	struct sctp_datamsg *datamsg;
+-	struct list_head *pos;
+ 	int msg_flags = msg->msg_flags;
+ 
+ 	SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %zu)\n",
+@@ -1727,9 +1721,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
+ 	}
+ 
+ 	/* Now send the (possibly) fragmented message. */
+-	list_for_each(pos, &datamsg->chunks) {
+-		chunk = list_entry(pos, struct sctp_chunk, frag_list);
+-		sctp_datamsg_track(chunk);
++	list_for_each_entry(chunk, &datamsg->chunks, frag_list) {
++		sctp_chunk_hold(chunk);
+ 
+ 		/* Do accounting for the write space.  */
+ 		sctp_set_owner_w(chunk);
+@@ -1748,7 +1741,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
+ 		SCTP_DEBUG_PRINTK("We sent primitively.\n");
+ 	}
+ 
+-	sctp_datamsg_free(datamsg);
++	sctp_datamsg_put(datamsg);
+ 	if (err)
+ 		goto out_free;
+ 	else
+@@ -2301,11 +2294,8 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
+ 	 * transport.
+ 	 */
+ 	if (!trans && asoc) {
+-		struct list_head *pos;
+-
+-		list_for_each(pos, &asoc->peer.transport_addr_list) {
+-			trans = list_entry(pos, struct sctp_transport,
+-					   transports);
++		list_for_each_entry(trans, &asoc->peer.transport_addr_list,
++				transports) {
+ 			sctp_apply_peer_addr_params(&params, trans, asoc, sp,
+ 						    hb_change, pmtud_change,
+ 						    sackdelay_change);
+@@ -2396,11 +2386,8 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
+ 
+ 	/* If change is for association, also apply to each transport. */
+ 	if (asoc) {
+-		struct list_head *pos;
+-
+-		list_for_each(pos, &asoc->peer.transport_addr_list) {
+-			trans = list_entry(pos, struct sctp_transport,
+-					   transports);
++		list_for_each_entry(trans, &asoc->peer.transport_addr_list,
++				transports) {
+ 			if (params.assoc_value) {
+ 				trans->sackdelay =
+ 					msecs_to_jiffies(params.assoc_value);
+@@ -2632,13 +2619,10 @@ static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, int o
+ 		if (assocparams.sasoc_asocmaxrxt != 0) {
+ 			__u32 path_sum = 0;
+ 			int   paths = 0;
+-			struct list_head *pos;
+ 			struct sctp_transport *peer_addr;
+ 
+-			list_for_each(pos, &asoc->peer.transport_addr_list) {
+-				peer_addr = list_entry(pos,
+-						struct sctp_transport,
+-						transports);
++			list_for_each_entry(peer_addr, &asoc->peer.transport_addr_list,
++					transports) {
+ 				path_sum += peer_addr->pathmaxrxt;
+ 				paths++;
+ 			}
+@@ -2716,7 +2700,6 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int op
+ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen)
+ {
+ 	struct sctp_association *asoc;
+-	struct list_head *pos;
+ 	struct sctp_sock *sp = sctp_sk(sk);
+ 	int val;
+ 
+@@ -2729,8 +2712,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl
+ 	sp->user_frag = val;
+ 
+ 	/* Update the frag_point of the existing associations. */
+-	list_for_each(pos, &(sp->ep->asocs)) {
+-		asoc = list_entry(pos, struct sctp_association, asocs);
++	list_for_each_entry(asoc, &(sp->ep->asocs), asocs) {
+ 		asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
+ 	}
+ 
+@@ -3302,7 +3284,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
+ 	sctp_lock_sock(sk);
+ 
+ 	SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
+-			  __FUNCTION__, sk, addr, addr_len);
++			  __func__, sk, addr, addr_len);
+ 
+ 	/* Validate addr_len before calling common connect/connectx routine. */
+ 	af = sctp_get_af_specific(addr->sa_family);
+@@ -3823,7 +3805,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
+ 		goto out;
+ 	}
+ 
+-	SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __FUNCTION__, sk, asoc);
++	SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __func__, sk, asoc);
+ 
+ 	retval = sctp_do_peeloff(asoc, &newsock);
+ 	if (retval < 0)
+@@ -3837,7 +3819,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
+ 	}
+ 
+ 	SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p newsk: %p sd: %d\n",
+-			  __FUNCTION__, sk, asoc, newsock->sk, retval);
++			  __func__, sk, asoc, newsock->sk, retval);
+ 
+ 	/* Return the fd mapped to the new socket.  */
+ 	peeloff.sd = retval;
+@@ -4151,7 +4133,6 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
+ 					  int __user *optlen)
+ {
+ 	struct sctp_association *asoc;
+-	struct list_head *pos;
+ 	int cnt = 0;
+ 	struct sctp_getaddrs_old getaddrs;
+ 	struct sctp_transport *from;
+@@ -4176,8 +4157,8 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
+ 		return -EINVAL;
+ 
+ 	to = (void __user *)getaddrs.addrs;
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		from = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(from, &asoc->peer.transport_addr_list,
++				transports) {
+ 		memcpy(&temp, &from->ipaddr, sizeof(temp));
+ 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
+ 		addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
+@@ -4200,7 +4181,6 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
+ 				      char __user *optval, int __user *optlen)
+ {
+ 	struct sctp_association *asoc;
+-	struct list_head *pos;
+ 	int cnt = 0;
+ 	struct sctp_getaddrs getaddrs;
+ 	struct sctp_transport *from;
+@@ -4225,8 +4205,8 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
+ 	to = optval + offsetof(struct sctp_getaddrs,addrs);
+ 	space_left = len - offsetof(struct sctp_getaddrs,addrs);
+ 
+-	list_for_each(pos, &asoc->peer.transport_addr_list) {
+-		from = list_entry(pos, struct sctp_transport, transports);
++	list_for_each_entry(from, &asoc->peer.transport_addr_list,
++				transports) {
+ 		memcpy(&temp, &from->ipaddr, sizeof(temp));
+ 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
+ 		addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
+@@ -5761,8 +5741,8 @@ static struct sctp_bind_bucket *sctp_bucket_create(
+ 	struct sctp_bind_bucket *pp;
+ 
+ 	pp = kmem_cache_alloc(sctp_bucket_cachep, GFP_ATOMIC);
+-	SCTP_DBG_OBJCNT_INC(bind_bucket);
+ 	if (pp) {
++		SCTP_DBG_OBJCNT_INC(bind_bucket);
+ 		pp->port = snum;
+ 		pp->fastreuse = 0;
+ 		INIT_HLIST_HEAD(&pp->owner);
+@@ -6194,11 +6174,9 @@ do_nonblock:
+ void sctp_write_space(struct sock *sk)
+ {
+ 	struct sctp_association *asoc;
+-	struct list_head *pos;
+ 
+ 	/* Wake up the tasks in each wait queue.  */
+-	list_for_each(pos, &((sctp_sk(sk))->ep->asocs)) {
+-		asoc = list_entry(pos, struct sctp_association, asocs);
++	list_for_each_entry(asoc, &((sctp_sk(sk))->ep->asocs), asocs) {
+ 		__sctp_write_space(asoc);
+ 	}
+ }
+@@ -6234,7 +6212,7 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
+ 	long current_timeo = *timeo_p;
+ 	DEFINE_WAIT(wait);
+ 
+-	SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc,
++	SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __func__, asoc,
+ 			  (long)(*timeo_p));
+ 
+ 	/* Increment the association's refcnt.  */
+@@ -6514,8 +6492,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
+ }
+ 
+ 
+-DEFINE_PROTO_INUSE(sctp)
+-
+ /* This proto struct describes the ULP interface for SCTP.  */
+ struct proto sctp_prot = {
+ 	.name        =	"SCTP",
+@@ -6545,11 +6521,9 @@ struct proto sctp_prot = {
+ 	.enter_memory_pressure = sctp_enter_memory_pressure,
+ 	.memory_allocated = &sctp_memory_allocated,
+ 	.sockets_allocated = &sctp_sockets_allocated,
+-	REF_PROTO_INUSE(sctp)
+ };
+ 
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+-DEFINE_PROTO_INUSE(sctpv6)
+ 
+ struct proto sctpv6_prot = {
+ 	.name		= "SCTPv6",
+@@ -6579,6 +6553,5 @@ struct proto sctpv6_prot = {
+ 	.enter_memory_pressure = sctp_enter_memory_pressure,
+ 	.memory_allocated = &sctp_memory_allocated,
+ 	.sockets_allocated = &sctp_sockets_allocated,
+-	REF_PROTO_INUSE(sctpv6)
+ };
+ #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+diff --git a/net/sctp/transport.c b/net/sctp/transport.c
+index d9f8af8..f4938f6 100644
+--- a/net/sctp/transport.c
++++ b/net/sctp/transport.c
+@@ -260,7 +260,7 @@ void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
+ 	if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
+ 		printk(KERN_WARNING "%s: Reported pmtu %d too low, "
+ 		       "using default minimum of %d\n",
+-		       __FUNCTION__, pmtu,
++		       __func__, pmtu,
+ 		       SCTP_DEFAULT_MINSEGMENT);
+ 		/* Use default minimum segment size and disable
+ 		 * pmtu discovery on this transport.
+@@ -388,7 +388,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
+ 	tp->rto_pending = 0;
+ 
+ 	SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d "
+-			  "rttvar: %d, rto: %ld\n", __FUNCTION__,
++			  "rttvar: %d, rto: %ld\n", __func__,
+ 			  tp, rtt, tp->srtt, tp->rttvar, tp->rto);
+ }
+ 
+@@ -434,7 +434,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
+ 		SCTP_DEBUG_PRINTK("%s: SLOW START: transport: %p, "
+ 				  "bytes_acked: %d, cwnd: %d, ssthresh: %d, "
+ 				  "flight_size: %d, pba: %d\n",
+-				  __FUNCTION__,
++				  __func__,
+ 				  transport, bytes_acked, cwnd,
+ 				  ssthresh, flight_size, pba);
+ 	} else {
+@@ -460,7 +460,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
+ 		SCTP_DEBUG_PRINTK("%s: CONGESTION AVOIDANCE: "
+ 				  "transport: %p, bytes_acked: %d, cwnd: %d, "
+ 				  "ssthresh: %d, flight_size: %d, pba: %d\n",
+-				  __FUNCTION__,
++				  __func__,
+ 				  transport, bytes_acked, cwnd,
+ 				  ssthresh, flight_size, pba);
+ 	}
+@@ -546,7 +546,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
+ 
+ 	transport->partial_bytes_acked = 0;
+ 	SCTP_DEBUG_PRINTK("%s: transport: %p reason: %d cwnd: "
+-			  "%d ssthresh: %d\n", __FUNCTION__,
++			  "%d ssthresh: %d\n", __func__,
+ 			  transport, reason,
+ 			  transport->cwnd, transport->ssthresh);
+ }
+diff --git a/net/socket.c b/net/socket.c
+index 9d3fbfb..66c4a8c 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -857,7 +857,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+ 
+ 	sock = file->private_data;
+ 	sk = sock->sk;
+-	net = sk->sk_net;
++	net = sock_net(sk);
+ 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
+ 		err = dev_ioctl(net, cmd, argp);
+ 	} else
+@@ -1375,7 +1375,7 @@ asmlinkage long sys_listen(int fd, int backlog)
+ 
+ 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
+ 	if (sock) {
+-		somaxconn = sock->sk->sk_net->sysctl_somaxconn;
++		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
+ 		if ((unsigned)backlog > somaxconn)
+ 			backlog = somaxconn;
+ 
+@@ -2327,9 +2327,6 @@ int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
+ 	return sock->ops->shutdown(sock, how);
+ }
+ 
+-/* ABI emulation layers need these two */
+-EXPORT_SYMBOL(move_addr_to_kernel);
+-EXPORT_SYMBOL(move_addr_to_user);
+ EXPORT_SYMBOL(sock_create);
+ EXPORT_SYMBOL(sock_create_kern);
+ EXPORT_SYMBOL(sock_create_lite);
+diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
+index 92e1dbe..5369aa3 100644
+--- a/net/sunrpc/Makefile
++++ b/net/sunrpc/Makefile
+@@ -8,7 +8,7 @@ obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
+ obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/
+ 
+ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
+-	    auth.o auth_null.o auth_unix.o \
++	    auth.o auth_null.o auth_unix.o auth_generic.o \
+ 	    svc.o svcsock.o svcauth.o svcauth_unix.o \
+ 	    rpcb_clnt.o timer.o xdr.o \
+ 	    sunrpc_syms.o cache.o rpc_pipe.o \
+diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
+index eca941c..6bfea9e 100644
+--- a/net/sunrpc/auth.c
++++ b/net/sunrpc/auth.c
+@@ -11,6 +11,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/errno.h>
++#include <linux/hash.h>
+ #include <linux/sunrpc/clnt.h>
+ #include <linux/spinlock.h>
+ 
+@@ -219,6 +220,9 @@ rpcauth_destroy_credcache(struct rpc_auth *auth)
+ }
+ EXPORT_SYMBOL_GPL(rpcauth_destroy_credcache);
+ 
++
++#define RPC_AUTH_EXPIRY_MORATORIUM (60 * HZ)
++
+ /*
+  * Remove stale credentials. Avoid sleeping inside the loop.
+  */
+@@ -227,6 +231,7 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
+ {
+ 	spinlock_t *cache_lock;
+ 	struct rpc_cred *cred;
++	unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM;
+ 
+ 	while (!list_empty(&cred_unused)) {
+ 		cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
+@@ -234,6 +239,10 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
+ 		number_cred_unused--;
+ 		if (atomic_read(&cred->cr_count) != 0)
+ 			continue;
++		/* Enforce a 5 second garbage collection moratorium */
++		if (time_in_range(cred->cr_expire, expired, jiffies) &&
++		    test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0)
++			continue;
+ 		cache_lock = &cred->cr_auth->au_credcache->lock;
+ 		spin_lock(cache_lock);
+ 		if (atomic_read(&cred->cr_count) == 0) {
+@@ -280,10 +289,9 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
+ 	struct hlist_node *pos;
+ 	struct rpc_cred	*cred = NULL,
+ 			*entry, *new;
+-	int		nr = 0;
++	unsigned int nr;
+ 
+-	if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
+-		nr = acred->uid & RPC_CREDCACHE_MASK;
++	nr = hash_long(acred->uid, RPC_CREDCACHE_HASHBITS);
+ 
+ 	rcu_read_lock();
+ 	hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
+@@ -356,7 +364,6 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags)
+ 	put_group_info(acred.group_info);
+ 	return ret;
+ }
+-EXPORT_SYMBOL_GPL(rpcauth_lookupcred);
+ 
+ void
+ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
+@@ -375,41 +382,58 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
+ }
+ EXPORT_SYMBOL_GPL(rpcauth_init_cred);
+ 
+-struct rpc_cred *
+-rpcauth_bindcred(struct rpc_task *task)
++void
++rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred)
++{
++	task->tk_msg.rpc_cred = get_rpccred(cred);
++	dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
++			cred->cr_auth->au_ops->au_name, cred);
++}
++EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred);
++
++static void
++rpcauth_bind_root_cred(struct rpc_task *task)
+ {
+ 	struct rpc_auth *auth = task->tk_client->cl_auth;
+ 	struct auth_cred acred = {
+-		.uid = current->fsuid,
+-		.gid = current->fsgid,
+-		.group_info = current->group_info,
++		.uid = 0,
++		.gid = 0,
+ 	};
+ 	struct rpc_cred *ret;
+-	int flags = 0;
+ 
+ 	dprintk("RPC: %5u looking up %s cred\n",
+ 		task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
+-	get_group_info(acred.group_info);
+-	if (task->tk_flags & RPC_TASK_ROOTCREDS)
+-		flags |= RPCAUTH_LOOKUP_ROOTCREDS;
+-	ret = auth->au_ops->lookup_cred(auth, &acred, flags);
++	ret = auth->au_ops->lookup_cred(auth, &acred, 0);
++	if (!IS_ERR(ret))
++		task->tk_msg.rpc_cred = ret;
++	else
++		task->tk_status = PTR_ERR(ret);
++}
++
++static void
++rpcauth_bind_new_cred(struct rpc_task *task)
++{
++	struct rpc_auth *auth = task->tk_client->cl_auth;
++	struct rpc_cred *ret;
++
++	dprintk("RPC: %5u looking up %s cred\n",
++		task->tk_pid, auth->au_ops->au_name);
++	ret = rpcauth_lookupcred(auth, 0);
+ 	if (!IS_ERR(ret))
+ 		task->tk_msg.rpc_cred = ret;
+ 	else
+ 		task->tk_status = PTR_ERR(ret);
+-	put_group_info(acred.group_info);
+-	return ret;
+ }
+ 
+ void
+-rpcauth_holdcred(struct rpc_task *task)
++rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags)
+ {
+-	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+-	if (cred != NULL) {
+-		get_rpccred(cred);
+-		dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
+-				cred->cr_auth->au_ops->au_name, cred);
+-	}
++	if (cred != NULL)
++		cred->cr_ops->crbind(task, cred);
++	else if (flags & RPC_TASK_ROOTCREDS)
++		rpcauth_bind_root_cred(task);
++	else
++		rpcauth_bind_new_cred(task);
+ }
+ 
+ void
+@@ -550,6 +574,7 @@ static struct shrinker rpc_cred_shrinker = {
+ void __init rpcauth_init_module(void)
+ {
+ 	rpc_init_authunix();
++	rpc_init_generic_auth();
+ 	register_shrinker(&rpc_cred_shrinker);
+ }
+ 
+diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
+new file mode 100644
+index 0000000..d927d9f
+--- /dev/null
++++ b/net/sunrpc/auth_generic.c
+@@ -0,0 +1,177 @@
++/*
++ * Generic RPC credential
++ *
++ * Copyright (C) 2008, Trond Myklebust <Trond.Myklebust at netapp.com>
++ */
++
++#include <linux/err.h>
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/sunrpc/auth.h>
++#include <linux/sunrpc/clnt.h>
++#include <linux/sunrpc/debug.h>
++#include <linux/sunrpc/sched.h>
++
++#ifdef RPC_DEBUG
++# define RPCDBG_FACILITY	RPCDBG_AUTH
++#endif
++
++#define RPC_ANONYMOUS_USERID	((uid_t)-2)
++#define RPC_ANONYMOUS_GROUPID	((gid_t)-2)
++
++struct generic_cred {
++	struct rpc_cred gc_base;
++	struct auth_cred acred;
++};
++
++static struct rpc_auth generic_auth;
++static struct rpc_cred_cache generic_cred_cache;
++static const struct rpc_credops generic_credops;
++
++/*
++ * Public call interface
++ */
++struct rpc_cred *rpc_lookup_cred(void)
++{
++	return rpcauth_lookupcred(&generic_auth, 0);
++}
++EXPORT_SYMBOL_GPL(rpc_lookup_cred);
++
++/*
++ * Public call interface for looking up machine creds.
++ */
++struct rpc_cred *rpc_lookup_machine_cred(void)
++{
++	struct auth_cred acred = {
++		.uid = RPC_ANONYMOUS_USERID,
++		.gid = RPC_ANONYMOUS_GROUPID,
++		.machine_cred = 1,
++	};
++
++	dprintk("RPC:       looking up machine cred\n");
++	return generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0);
++}
++EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred);
++
++static void
++generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred)
++{
++	struct rpc_auth *auth = task->tk_client->cl_auth;
++	struct auth_cred *acred = &container_of(cred, struct generic_cred, gc_base)->acred;
++	struct rpc_cred *ret;
++
++	ret = auth->au_ops->lookup_cred(auth, acred, 0);
++	if (!IS_ERR(ret))
++		task->tk_msg.rpc_cred = ret;
++	else
++		task->tk_status = PTR_ERR(ret);
++}
++
++/*
++ * Lookup generic creds for current process
++ */
++static struct rpc_cred *
++generic_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
++{
++	return rpcauth_lookup_credcache(&generic_auth, acred, flags);
++}
++
++static struct rpc_cred *
++generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
++{
++	struct generic_cred *gcred;
++
++	gcred = kmalloc(sizeof(*gcred), GFP_KERNEL);
++	if (gcred == NULL)
++		return ERR_PTR(-ENOMEM);
++
++	rpcauth_init_cred(&gcred->gc_base, acred, &generic_auth, &generic_credops);
++	gcred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
++
++	gcred->acred.uid = acred->uid;
++	gcred->acred.gid = acred->gid;
++	gcred->acred.group_info = acred->group_info;
++	if (gcred->acred.group_info != NULL)
++		get_group_info(gcred->acred.group_info);
++	gcred->acred.machine_cred = acred->machine_cred;
++
++	dprintk("RPC:       allocated %s cred %p for uid %d gid %d\n",
++			gcred->acred.machine_cred ? "machine" : "generic",
++			gcred, acred->uid, acred->gid);
++	return &gcred->gc_base;
++}
++
++static void
++generic_free_cred(struct rpc_cred *cred)
++{
++	struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
++
++	dprintk("RPC:       generic_free_cred %p\n", gcred);
++	if (gcred->acred.group_info != NULL)
++		put_group_info(gcred->acred.group_info);
++	kfree(gcred);
++}
++
++static void
++generic_free_cred_callback(struct rcu_head *head)
++{
++	struct rpc_cred *cred = container_of(head, struct rpc_cred, cr_rcu);
++	generic_free_cred(cred);
++}
++
++static void
++generic_destroy_cred(struct rpc_cred *cred)
++{
++	call_rcu(&cred->cr_rcu, generic_free_cred_callback);
++}
++
++/*
++ * Match credentials against current process creds.
++ */
++static int
++generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
++{
++	struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
++
++	if (gcred->acred.uid != acred->uid ||
++	    gcred->acred.gid != acred->gid ||
++	    gcred->acred.group_info != acred->group_info ||
++	    gcred->acred.machine_cred != acred->machine_cred)
++		return 0;
++	return 1;
++}
++
++void __init rpc_init_generic_auth(void)
++{
++	spin_lock_init(&generic_cred_cache.lock);
++}
++
++void __exit rpc_destroy_generic_auth(void)
++{
++	rpcauth_clear_credcache(&generic_cred_cache);
++}
++
++static struct rpc_cred_cache generic_cred_cache = {
++	{{ NULL, },},
++};
++
++static const struct rpc_authops generic_auth_ops = {
++	.owner = THIS_MODULE,
++	.au_name = "Generic",
++	.lookup_cred = generic_lookup_cred,
++	.crcreate = generic_create_cred,
++};
++
++static struct rpc_auth generic_auth = {
++	.au_ops = &generic_auth_ops,
++	.au_count = ATOMIC_INIT(0),
++	.au_credcache = &generic_cred_cache,
++};
++
++static const struct rpc_credops generic_credops = {
++	.cr_name = "Generic cred",
++	.crdestroy = generic_destroy_cred,
++	.crbind = generic_bind_cred,
++	.crmatch = generic_match,
++};
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 6dac387..cc12d5f 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -114,27 +114,14 @@ static void
+ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
+ {
+ 	struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+-	struct gss_cl_ctx *old;
+ 
+-	old = gss_cred->gc_ctx;
++	if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags))
++		return;
++	gss_get_ctx(ctx);
+ 	rcu_assign_pointer(gss_cred->gc_ctx, ctx);
+ 	set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
++	smp_mb__before_clear_bit();
+ 	clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
+-	if (old)
+-		gss_put_ctx(old);
+-}
+-
+-static int
+-gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
+-{
+-	struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+-	int res = 0;
+-
+-	rcu_read_lock();
+-	if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
+-		res = 1;
+-	rcu_read_unlock();
+-	return res;
+ }
+ 
+ static const void *
+@@ -266,6 +253,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
+ 	BUG_ON(!list_empty(&gss_msg->list));
+ 	if (gss_msg->ctx != NULL)
+ 		gss_put_ctx(gss_msg->ctx);
++	rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
+ 	kfree(gss_msg);
+ }
+ 
+@@ -339,7 +327,7 @@ gss_upcall_callback(struct rpc_task *task)
+ 
+ 	spin_lock(&inode->i_lock);
+ 	if (gss_msg->ctx)
+-		gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
++		gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
+ 	else
+ 		task->tk_status = gss_msg->msg.errno;
+ 	gss_cred->gc_upcall = NULL;
+@@ -370,9 +358,16 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+ static struct gss_upcall_msg *
+ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred)
+ {
++	struct gss_cred *gss_cred = container_of(cred,
++			struct gss_cred, gc_base);
+ 	struct gss_upcall_msg *gss_new, *gss_msg;
++	uid_t uid = cred->cr_uid;
+ 
+-	gss_new = gss_alloc_msg(gss_auth, cred->cr_uid);
++	/* Special case: rpc.gssd assumes that uid == 0 implies machine creds */
++	if (gss_cred->gc_machine_cred != 0)
++		uid = 0;
++
++	gss_new = gss_alloc_msg(gss_auth, uid);
+ 	if (gss_new == NULL)
+ 		return ERR_PTR(-ENOMEM);
+ 	gss_msg = gss_add_msg(gss_auth, gss_new);
+@@ -408,13 +403,17 @@ gss_refresh_upcall(struct rpc_task *task)
+ 	}
+ 	spin_lock(&inode->i_lock);
+ 	if (gss_cred->gc_upcall != NULL)
+-		rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
+-	else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
++		rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
++	else if (gss_msg->ctx != NULL) {
++		gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
++		gss_cred->gc_upcall = NULL;
++		rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
++	} else if (gss_msg->msg.errno >= 0) {
+ 		task->tk_timeout = 0;
+ 		gss_cred->gc_upcall = gss_msg;
+ 		/* gss_upcall_callback will release the reference to gss_upcall_msg */
+ 		atomic_inc(&gss_msg->count);
+-		rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
++		rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
+ 	} else
+ 		err = gss_msg->msg.errno;
+ 	spin_unlock(&inode->i_lock);
+@@ -454,7 +453,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
+ 		schedule();
+ 	}
+ 	if (gss_msg->ctx)
+-		gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
++		gss_cred_set_ctx(cred, gss_msg->ctx);
+ 	else
+ 		err = gss_msg->msg.errno;
+ 	spin_unlock(&inode->i_lock);
+@@ -625,7 +624,7 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+ 	gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
+ 	if (!gss_auth->mech) {
+ 		printk(KERN_WARNING "%s: Pseudoflavor %d not found!\n",
+-				__FUNCTION__, flavor);
++				__func__, flavor);
+ 		goto err_free;
+ 	}
+ 	gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
+@@ -709,7 +708,7 @@ gss_destroying_context(struct rpc_cred *cred)
+ 	struct rpc_task *task;
+ 
+ 	if (gss_cred->gc_ctx == NULL ||
+-			gss_cred->gc_ctx->gc_proc == RPC_GSS_PROC_DESTROY)
++	    test_and_clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
+ 		return 0;
+ 
+ 	gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY;
+@@ -719,7 +718,7 @@ gss_destroying_context(struct rpc_cred *cred)
+ 	 * by the RPC call or by the put_rpccred() below */
+ 	get_rpccred(cred);
+ 
+-	task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC);
++	task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC|RPC_TASK_SOFT);
+ 	if (!IS_ERR(task))
+ 		rpc_put_task(task);
+ 
+@@ -817,6 +816,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+ 	 */
+ 	cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
+ 	cred->gc_service = gss_auth->service;
++	cred->gc_machine_cred = acred->machine_cred;
+ 	kref_get(&gss_auth->kref);
+ 	return &cred->gc_base;
+ 
+@@ -843,17 +843,16 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
+ {
+ 	struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
+ 
+-	/*
+-	 * If the searchflags have set RPCAUTH_LOOKUP_NEW, then
+-	 * we don't really care if the credential has expired or not,
+-	 * since the caller should be prepared to reinitialise it.
+-	 */
+-	if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
++	if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
+ 		goto out;
+ 	/* Don't match with creds that have expired. */
+-	if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
++	if (time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
++		return 0;
++	if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags))
+ 		return 0;
+ out:
++	if (acred->machine_cred != gss_cred->gc_machine_cred)
++		return 0;
+ 	return (rc->cr_uid == acred->uid);
+ }
+ 
+@@ -917,16 +916,48 @@ out_put_ctx:
+ 	return NULL;
+ }
+ 
++static int gss_renew_cred(struct rpc_task *task)
++{
++	struct rpc_cred *oldcred = task->tk_msg.rpc_cred;
++	struct gss_cred *gss_cred = container_of(oldcred,
++						 struct gss_cred,
++						 gc_base);
++	struct rpc_auth *auth = oldcred->cr_auth;
++	struct auth_cred acred = {
++		.uid = oldcred->cr_uid,
++		.machine_cred = gss_cred->gc_machine_cred,
++	};
++	struct rpc_cred *new;
++
++	new = gss_lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW);
++	if (IS_ERR(new))
++		return PTR_ERR(new);
++	task->tk_msg.rpc_cred = new;
++	put_rpccred(oldcred);
++	return 0;
++}
++
+ /*
+ * Refresh credentials. XXX - finish
+ */
+ static int
+ gss_refresh(struct rpc_task *task)
+ {
++	struct rpc_cred *cred = task->tk_msg.rpc_cred;
++	int ret = 0;
++
++	if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
++			!test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) {
++		ret = gss_renew_cred(task);
++		if (ret < 0)
++			goto out;
++		cred = task->tk_msg.rpc_cred;
++	}
+ 
+-	if (!gss_cred_is_uptodate_ctx(task->tk_msg.rpc_cred))
+-		return gss_refresh_upcall(task);
+-	return 0;
++	if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags))
++		ret = gss_refresh_upcall(task);
++out:
++	return ret;
+ }
+ 
+ /* Dummy refresh routine: used only when destroying the context */
+@@ -1286,9 +1317,7 @@ out:
+ static const struct rpc_authops authgss_ops = {
+ 	.owner		= THIS_MODULE,
+ 	.au_flavor	= RPC_AUTH_GSS,
+-#ifdef RPC_DEBUG
+ 	.au_name	= "RPCSEC_GSS",
+-#endif
+ 	.create		= gss_create,
+ 	.destroy	= gss_destroy,
+ 	.lookup_cred	= gss_lookup_cred,
+@@ -1299,6 +1328,7 @@ static const struct rpc_credops gss_credops = {
+ 	.cr_name	= "AUTH_GSS",
+ 	.crdestroy	= gss_destroy_cred,
+ 	.cr_init	= gss_cred_init,
++	.crbind		= rpcauth_generic_bind_cred,
+ 	.crmatch	= gss_match,
+ 	.crmarshal	= gss_marshal,
+ 	.crrefresh	= gss_refresh,
+@@ -1310,6 +1340,7 @@ static const struct rpc_credops gss_credops = {
+ static const struct rpc_credops gss_nullops = {
+ 	.cr_name	= "AUTH_GSS",
+ 	.crdestroy	= gss_destroy_cred,
++	.crbind		= rpcauth_generic_bind_cred,
+ 	.crmatch	= gss_match,
+ 	.crmarshal	= gss_marshal,
+ 	.crrefresh	= gss_refresh_null,
+diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
+index ea8c92e..d83b881 100644
+--- a/net/sunrpc/auth_gss/gss_generic_token.c
++++ b/net/sunrpc/auth_gss/gss_generic_token.c
+@@ -148,7 +148,7 @@ int
+ g_token_size(struct xdr_netobj *mech, unsigned int body_size)
+ {
+ 	/* set body_size to sequence contents size */
+-	body_size += 4 + (int) mech->len;         /* NEED overflow check */
++	body_size += 2 + (int) mech->len;         /* NEED overflow check */
+ 	return(1 + der_length_size(body_size) + body_size);
+ }
+ 
+@@ -161,7 +161,7 @@ void
+ g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf)
+ {
+ 	*(*buf)++ = 0x60;
+-	der_write_length(buf, 4 + mech->len + body_size);
++	der_write_length(buf, 2 + mech->len + body_size);
+ 	*(*buf)++ = 0x06;
+ 	*(*buf)++ = (unsigned char) mech->len;
+ 	TWRITE_STR(*buf, mech->data, ((int) mech->len));
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index 0dd7923..1d52308 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -66,8 +66,8 @@ krb5_encrypt(
+ 		goto out;
+ 
+ 	if (crypto_blkcipher_ivsize(tfm) > 16) {
+-		dprintk("RPC:       gss_k5encrypt: tfm iv size to large %d\n",
+-			 crypto_blkcipher_ivsize(tfm));
++		dprintk("RPC:       gss_k5encrypt: tfm iv size too large %d\n",
++			crypto_blkcipher_ivsize(tfm));
+ 		goto out;
+ 	}
+ 
+@@ -102,7 +102,7 @@ krb5_decrypt(
+ 		goto out;
+ 
+ 	if (crypto_blkcipher_ivsize(tfm) > 16) {
+-		dprintk("RPC:       gss_k5decrypt: tfm iv size to large %d\n",
++		dprintk("RPC:       gss_k5decrypt: tfm iv size too large %d\n",
+ 			crypto_blkcipher_ivsize(tfm));
+ 		goto out;
+ 	}
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index dedcbd6..5f1d36d 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -87,10 +87,10 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 
+ 	now = get_seconds();
+ 
+-	token->len = g_token_size(&ctx->mech_used, 22);
++	token->len = g_token_size(&ctx->mech_used, 24);
+ 
+ 	ptr = token->data;
+-	g_make_token_header(&ctx->mech_used, 22, &ptr);
++	g_make_token_header(&ctx->mech_used, 24, &ptr);
+ 
+ 	*ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
+ 	*ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
+@@ -109,15 +109,14 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ 			  md5cksum.data, md5cksum.len))
+ 		return GSS_S_FAILURE;
+ 
+-	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+-	       KRB5_CKSUM_LENGTH);
++	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
+ 
+ 	spin_lock(&krb5_seq_lock);
+ 	seq_send = ctx->seq_send++;
+ 	spin_unlock(&krb5_seq_lock);
+ 
+ 	if (krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff,
+-			       ctx->seq_send, krb5_hdr + 16, krb5_hdr + 8))
++			      seq_send, krb5_hdr + 16, krb5_hdr + 8))
+ 		return GSS_S_FAILURE;
+ 
+ 	return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+index 43f3421..f160be6 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+@@ -43,7 +43,7 @@
+ s32
+ krb5_make_seq_num(struct crypto_blkcipher *key,
+ 		int direction,
+-		s32 seqnum,
++		u32 seqnum,
+ 		unsigned char *cksum, unsigned char *buf)
+ {
+ 	unsigned char plain[8];
+@@ -65,7 +65,7 @@ s32
+ krb5_get_seq_num(struct crypto_blkcipher *key,
+ 	       unsigned char *cksum,
+ 	       unsigned char *buf,
+-	       int *direction, s32 * seqnum)
++	       int *direction, u32 *seqnum)
+ {
+ 	s32 code;
+ 	unsigned char plain[8];
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index e30a993..d91a5d0 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -82,7 +82,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ 	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+ 	s32			now;
+ 	int			direction;
+-	s32			seqnum;
++	u32			seqnum;
+ 	unsigned char		*ptr = (unsigned char *)read_token->data;
+ 	int			bodysize;
+ 
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 3bdc527..b00b1b4 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -137,7 +137,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	BUG_ON((buf->len - offset) % blocksize);
+ 	plainlen = blocksize + buf->len - offset;
+ 
+-	headlen = g_token_size(&kctx->mech_used, 22 + plainlen) -
++	headlen = g_token_size(&kctx->mech_used, 24 + plainlen) -
+ 						(buf->len - offset);
+ 
+ 	ptr = buf->head[0].iov_base + offset;
+@@ -149,7 +149,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	buf->len += headlen;
+ 	BUG_ON((buf->len - offset - headlen) % blocksize);
+ 
+-	g_make_token_header(&kctx->mech_used, 22 + plainlen, &ptr);
++	g_make_token_header(&kctx->mech_used, 24 + plainlen, &ptr);
+ 
+ 
+ 	*ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
+@@ -176,9 +176,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ 	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+ 			  md5cksum.data, md5cksum.len))
+ 		return GSS_S_FAILURE;
+-	memcpy(krb5_hdr + 16,
+-	       md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+-	       KRB5_CKSUM_LENGTH);
++	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
+ 
+ 	spin_lock(&krb5_seq_lock);
+ 	seq_send = kctx->seq_send++;
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+index abf17ce..c832712 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+@@ -107,10 +107,10 @@ spkm3_make_token(struct spkm3_ctx *ctx,
+ 		tokenlen = 10 + ctxelen + 1 + md5elen + 1;
+ 
+ 		/* Create token header using generic routines */
+-		token->len = g_token_size(&ctx->mech_used, tokenlen);
++		token->len = g_token_size(&ctx->mech_used, tokenlen + 2);
+ 
+ 		ptr = token->data;
+-		g_make_token_header(&ctx->mech_used, tokenlen, &ptr);
++		g_make_token_header(&ctx->mech_used, tokenlen + 2, &ptr);
+ 
+ 		spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
+ 	} else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 481f984..5905d56 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1146,7 +1146,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 		case RPC_GSS_SVC_INTEGRITY:
+ 			if (unwrap_integ_data(&rqstp->rq_arg,
+ 					gc->gc_seq, rsci->mechctx))
+-				goto auth_err;
++				goto garbage_args;
+ 			/* placeholders for length and seq. number: */
+ 			svc_putnl(resv, 0);
+ 			svc_putnl(resv, 0);
+@@ -1154,7 +1154,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 		case RPC_GSS_SVC_PRIVACY:
+ 			if (unwrap_priv_data(rqstp, &rqstp->rq_arg,
+ 					gc->gc_seq, rsci->mechctx))
+-				goto auth_err;
++				goto garbage_args;
+ 			/* placeholders for length and seq. number: */
+ 			svc_putnl(resv, 0);
+ 			svc_putnl(resv, 0);
+@@ -1169,6 +1169,11 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ 		ret = SVC_OK;
+ 		goto out;
+ 	}
++garbage_args:
++	/* Restore write pointer to its original value: */
++	xdr_ressize_check(rqstp, reject_stat);
++	ret = SVC_GARBAGE;
++	goto out;
+ auth_err:
+ 	/* Restore write pointer to its original value: */
+ 	xdr_ressize_check(rqstp, reject_stat);
+diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
+index 537d0e8..c70dd7f 100644
+--- a/net/sunrpc/auth_null.c
++++ b/net/sunrpc/auth_null.c
+@@ -104,9 +104,7 @@ nul_validate(struct rpc_task *task, __be32 *p)
+ const struct rpc_authops authnull_ops = {
+ 	.owner		= THIS_MODULE,
+ 	.au_flavor	= RPC_AUTH_NULL,
+-#ifdef RPC_DEBUG
+ 	.au_name	= "NULL",
+-#endif
+ 	.create		= nul_create,
+ 	.destroy	= nul_destroy,
+ 	.lookup_cred	= nul_lookup_cred,
+@@ -125,6 +123,7 @@ static
+ const struct rpc_credops null_credops = {
+ 	.cr_name	= "AUTH_NULL",
+ 	.crdestroy	= nul_destroy_cred,
++	.crbind		= rpcauth_generic_bind_cred,
+ 	.crmatch	= nul_match,
+ 	.crmarshal	= nul_marshal,
+ 	.crrefresh	= nul_refresh,
+diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
+index 5ed91e5..44920b9 100644
+--- a/net/sunrpc/auth_unix.c
++++ b/net/sunrpc/auth_unix.c
+@@ -60,7 +60,8 @@ static struct rpc_cred *
+ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+ {
+ 	struct unx_cred	*cred;
+-	int		i;
++	unsigned int groups = 0;
++	unsigned int i;
+ 
+ 	dprintk("RPC:       allocating UNIX cred for uid %d gid %d\n",
+ 			acred->uid, acred->gid);
+@@ -70,21 +71,17 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+ 
+ 	rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
+ 	cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
+-	if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
+-		cred->uc_uid = 0;
+-		cred->uc_gid = 0;
+-		cred->uc_gids[0] = NOGROUP;
+-	} else {
+-		int groups = acred->group_info->ngroups;
+-		if (groups > NFS_NGROUPS)
+-			groups = NFS_NGROUPS;
+-
+-		cred->uc_gid = acred->gid;
+-		for (i = 0; i < groups; i++)
+-			cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
+-		if (i < NFS_NGROUPS)
+-		  cred->uc_gids[i] = NOGROUP;
+-	}
++
++	if (acred->group_info != NULL)
++		groups = acred->group_info->ngroups;
++	if (groups > NFS_NGROUPS)
++		groups = NFS_NGROUPS;
++
++	cred->uc_gid = acred->gid;
++	for (i = 0; i < groups; i++)
++		cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
++	if (i < NFS_NGROUPS)
++		cred->uc_gids[i] = NOGROUP;
+ 
+ 	return &cred->uc_base;
+ }
+@@ -118,26 +115,21 @@ static int
+ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
+ {
+ 	struct unx_cred	*cred = container_of(rcred, struct unx_cred, uc_base);
+-	int		i;
++	unsigned int groups = 0;
++	unsigned int i;
+ 
+-	if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) {
+-		int groups;
+ 
+-		if (cred->uc_uid != acred->uid
+-		 || cred->uc_gid != acred->gid)
+-			return 0;
++	if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid)
++		return 0;
+ 
++	if (acred->group_info != NULL)
+ 		groups = acred->group_info->ngroups;
+-		if (groups > NFS_NGROUPS)
+-			groups = NFS_NGROUPS;
+-		for (i = 0; i < groups ; i++)
+-			if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
+-				return 0;
+-		return 1;
+-	}
+-	return (cred->uc_uid == 0
+-	     && cred->uc_gid == 0
+-	     && cred->uc_gids[0] == (gid_t) NOGROUP);
++	if (groups > NFS_NGROUPS)
++		groups = NFS_NGROUPS;
++	for (i = 0; i < groups ; i++)
++		if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
++			return 0;
++	return 1;
+ }
+ 
+ /*
+@@ -218,9 +210,7 @@ void __init rpc_init_authunix(void)
+ const struct rpc_authops authunix_ops = {
+ 	.owner		= THIS_MODULE,
+ 	.au_flavor	= RPC_AUTH_UNIX,
+-#ifdef RPC_DEBUG
+ 	.au_name	= "UNIX",
+-#endif
+ 	.create		= unx_create,
+ 	.destroy	= unx_destroy,
+ 	.lookup_cred	= unx_lookup_cred,
+@@ -245,6 +235,7 @@ static
+ const struct rpc_credops unix_credops = {
+ 	.cr_name	= "AUTH_UNIX",
+ 	.crdestroy	= unx_destroy_cred,
++	.crbind		= rpcauth_generic_bind_cred,
+ 	.crmatch	= unx_match,
+ 	.crmarshal	= unx_marshal,
+ 	.crrefresh	= unx_refresh,
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index b5f2786..d75530f 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -571,7 +571,6 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
+ 		return -ETIMEDOUT;
+ 
+ 	dreq->item = item;
+-	dreq->recv_time = get_seconds();
+ 
+ 	spin_lock(&cache_defer_lock);
+ 
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 8834d68..8945307 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -43,7 +43,7 @@
+ 
+ #define dprint_status(t)					\
+ 	dprintk("RPC: %5u %s (status %d)\n", t->tk_pid,		\
+-			__FUNCTION__, t->tk_status)
++			__func__, t->tk_status)
+ 
+ /*
+  * All RPC clients are linked into this list
+@@ -368,7 +368,7 @@ out_no_path:
+ out_no_stats:
+ 	kfree(new);
+ out_no_clnt:
+-	dprintk("RPC:       %s: returned error %d\n", __FUNCTION__, err);
++	dprintk("RPC:       %s: returned error %d\n", __func__, err);
+ 	return ERR_PTR(err);
+ }
+ EXPORT_SYMBOL_GPL(rpc_clone_client);
+@@ -544,7 +544,7 @@ EXPORT_SYMBOL_GPL(rpc_run_task);
+  * @msg: RPC call parameters
+  * @flags: RPC call flags
+  */
+-int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
++int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags)
+ {
+ 	struct rpc_task	*task;
+ 	struct rpc_task_setup task_setup_data = {
+@@ -575,7 +575,7 @@ EXPORT_SYMBOL_GPL(rpc_call_sync);
+  * @data: user call data
+  */
+ int
+-rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
++rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
+ 	       const struct rpc_call_ops *tk_ops, void *data)
+ {
+ 	struct rpc_task	*task;
+@@ -752,7 +752,7 @@ call_reserveresult(struct rpc_task *task)
+ 		}
+ 
+ 		printk(KERN_ERR "%s: status=%d, but no request slot, exiting\n",
+-				__FUNCTION__, status);
++				__func__, status);
+ 		rpc_exit(task, -EIO);
+ 		return;
+ 	}
+@@ -763,7 +763,7 @@ call_reserveresult(struct rpc_task *task)
+ 	 */
+ 	if (task->tk_rqstp) {
+ 		printk(KERN_ERR "%s: status=%d, request allocated anyway\n",
+-				__FUNCTION__, status);
++				__func__, status);
+ 		xprt_release(task);
+ 	}
+ 
+@@ -775,7 +775,7 @@ call_reserveresult(struct rpc_task *task)
+ 		break;
+ 	default:
+ 		printk(KERN_ERR "%s: unrecognized error %d, exiting\n",
+-				__FUNCTION__, status);
++				__func__, status);
+ 		break;
+ 	}
+ 	rpc_exit(task, status);
+@@ -1062,7 +1062,7 @@ call_transmit(struct rpc_task *task)
+ 	if (task->tk_msg.rpc_proc->p_decode != NULL)
+ 		return;
+ 	task->tk_action = rpc_exit_task;
+-	rpc_wake_up_task(task);
++	rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
+ }
+ 
+ /*
+@@ -1116,7 +1116,8 @@ call_status(struct rpc_task *task)
+ 	case -ETIMEDOUT:
+ 		task->tk_action = call_timeout;
+ 		if (task->tk_client->cl_discrtry)
+-			xprt_force_disconnect(task->tk_xprt);
++			xprt_conditional_disconnect(task->tk_xprt,
++					req->rq_connect_cookie);
+ 		break;
+ 	case -ECONNREFUSED:
+ 	case -ENOTCONN:
+@@ -1168,6 +1169,11 @@ call_timeout(struct rpc_task *task)
+ 			clnt->cl_protname, clnt->cl_server);
+ 	}
+ 	rpc_force_rebind(clnt);
++	/*
++	 * Did our request time out due to an RPCSEC_GSS out-of-sequence
++	 * event? RFC2203 requires the server to drop all such requests.
++	 */
++	rpcauth_invalcred(task);
+ 
+ retry:
+ 	clnt->cl_stats->rpcretrans++;
+@@ -1195,18 +1201,6 @@ call_decode(struct rpc_task *task)
+ 		task->tk_flags &= ~RPC_CALL_MAJORSEEN;
+ 	}
+ 
+-	if (task->tk_status < 12) {
+-		if (!RPC_IS_SOFT(task)) {
+-			task->tk_action = call_bind;
+-			clnt->cl_stats->rpcretrans++;
+-			goto out_retry;
+-		}
+-		dprintk("RPC:       %s: too small RPC reply size (%d bytes)\n",
+-				clnt->cl_protname, task->tk_status);
+-		task->tk_action = call_timeout;
+-		goto out_retry;
+-	}
+-
+ 	/*
+ 	 * Ensure that we see all writes made by xprt_complete_rqst()
+ 	 * before it changed req->rq_received.
+@@ -1218,6 +1212,18 @@ call_decode(struct rpc_task *task)
+ 	WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf,
+ 				sizeof(req->rq_rcv_buf)) != 0);
+ 
++	if (req->rq_rcv_buf.len < 12) {
++		if (!RPC_IS_SOFT(task)) {
++			task->tk_action = call_bind;
++			clnt->cl_stats->rpcretrans++;
++			goto out_retry;
++		}
++		dprintk("RPC:       %s: too small RPC reply size (%d bytes)\n",
++				clnt->cl_protname, task->tk_status);
++		task->tk_action = call_timeout;
++		goto out_retry;
++	}
++
+ 	/* Verify the RPC header */
+ 	p = call_verify(task);
+ 	if (IS_ERR(p)) {
+@@ -1236,10 +1242,14 @@ call_decode(struct rpc_task *task)
+ 			task->tk_status);
+ 	return;
+ out_retry:
+-	req->rq_received = req->rq_private_buf.len = 0;
+ 	task->tk_status = 0;
+-	if (task->tk_client->cl_discrtry)
+-		xprt_force_disconnect(task->tk_xprt);
++	/* Note: call_verify() may have freed the RPC slot */
++	if (task->tk_rqstp == req) {
++		req->rq_received = req->rq_rcv_buf.len = 0;
++		if (task->tk_client->cl_discrtry)
++			xprt_conditional_disconnect(task->tk_xprt,
++					req->rq_connect_cookie);
++	}
+ }
+ 
+ /*
+@@ -1323,7 +1333,7 @@ call_verify(struct rpc_task *task)
+ 		 *   undefined results
+ 		 */
+ 		dprintk("RPC: %5u %s: XDR representation not a multiple of"
+-		       " 4 bytes: 0x%x\n", task->tk_pid, __FUNCTION__,
++		       " 4 bytes: 0x%x\n", task->tk_pid, __func__,
+ 		       task->tk_rqstp->rq_rcv_buf.len);
+ 		goto out_eio;
+ 	}
+@@ -1333,7 +1343,7 @@ call_verify(struct rpc_task *task)
+ 
+ 	if ((n = ntohl(*p++)) != RPC_REPLY) {
+ 		dprintk("RPC: %5u %s: not an RPC reply: %x\n",
+-				task->tk_pid, __FUNCTION__, n);
++				task->tk_pid, __func__, n);
+ 		goto out_garbage;
+ 	}
+ 	if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
+@@ -1345,13 +1355,13 @@ call_verify(struct rpc_task *task)
+ 			case RPC_MISMATCH:
+ 				dprintk("RPC: %5u %s: RPC call version "
+ 						"mismatch!\n",
+-						task->tk_pid, __FUNCTION__);
++						task->tk_pid, __func__);
+ 				error = -EPROTONOSUPPORT;
+ 				goto out_err;
+ 			default:
+ 				dprintk("RPC: %5u %s: RPC call rejected, "
+ 						"unknown error: %x\n",
+-						task->tk_pid, __FUNCTION__, n);
++						task->tk_pid, __func__, n);
+ 				goto out_eio;
+ 		}
+ 		if (--len < 0)
+@@ -1365,7 +1375,7 @@ call_verify(struct rpc_task *task)
+ 				break;
+ 			task->tk_cred_retry--;
+ 			dprintk("RPC: %5u %s: retry stale creds\n",
+-					task->tk_pid, __FUNCTION__);
++					task->tk_pid, __func__);
+ 			rpcauth_invalcred(task);
+ 			/* Ensure we obtain a new XID! */
+ 			xprt_release(task);
+@@ -1378,7 +1388,7 @@ call_verify(struct rpc_task *task)
+ 				break;
+ 			task->tk_garb_retry--;
+ 			dprintk("RPC: %5u %s: retry garbled creds\n",
+-					task->tk_pid, __FUNCTION__);
++					task->tk_pid, __func__);
+ 			task->tk_action = call_bind;
+ 			goto out_retry;
+ 		case RPC_AUTH_TOOWEAK:
+@@ -1387,16 +1397,16 @@ call_verify(struct rpc_task *task)
+ 			break;
+ 		default:
+ 			dprintk("RPC: %5u %s: unknown auth error: %x\n",
+-					task->tk_pid, __FUNCTION__, n);
++					task->tk_pid, __func__, n);
+ 			error = -EIO;
+ 		}
+ 		dprintk("RPC: %5u %s: call rejected %d\n",
+-				task->tk_pid, __FUNCTION__, n);
++				task->tk_pid, __func__, n);
+ 		goto out_err;
+ 	}
+ 	if (!(p = rpcauth_checkverf(task, p))) {
+ 		dprintk("RPC: %5u %s: auth check failed\n",
+-				task->tk_pid, __FUNCTION__);
++				task->tk_pid, __func__);
+ 		goto out_garbage;		/* bad verifier, retry */
+ 	}
+ 	len = p - (__be32 *)iov->iov_base - 1;
+@@ -1407,14 +1417,14 @@ call_verify(struct rpc_task *task)
+ 		return p;
+ 	case RPC_PROG_UNAVAIL:
+ 		dprintk("RPC: %5u %s: program %u is unsupported by server %s\n",
+-				task->tk_pid, __FUNCTION__,
++				task->tk_pid, __func__,
+ 				(unsigned int)task->tk_client->cl_prog,
+ 				task->tk_client->cl_server);
+ 		error = -EPFNOSUPPORT;
+ 		goto out_err;
+ 	case RPC_PROG_MISMATCH:
+ 		dprintk("RPC: %5u %s: program %u, version %u unsupported by "
+-				"server %s\n", task->tk_pid, __FUNCTION__,
++				"server %s\n", task->tk_pid, __func__,
+ 				(unsigned int)task->tk_client->cl_prog,
+ 				(unsigned int)task->tk_client->cl_vers,
+ 				task->tk_client->cl_server);
+@@ -1423,7 +1433,7 @@ call_verify(struct rpc_task *task)
+ 	case RPC_PROC_UNAVAIL:
+ 		dprintk("RPC: %5u %s: proc %p unsupported by program %u, "
+ 				"version %u on server %s\n",
+-				task->tk_pid, __FUNCTION__,
++				task->tk_pid, __func__,
+ 				task->tk_msg.rpc_proc,
+ 				task->tk_client->cl_prog,
+ 				task->tk_client->cl_vers,
+@@ -1432,11 +1442,11 @@ call_verify(struct rpc_task *task)
+ 		goto out_err;
+ 	case RPC_GARBAGE_ARGS:
+ 		dprintk("RPC: %5u %s: server saw garbage\n",
+-				task->tk_pid, __FUNCTION__);
++				task->tk_pid, __func__);
+ 		break;			/* retry */
+ 	default:
+ 		dprintk("RPC: %5u %s: server accept status: %x\n",
+-				task->tk_pid, __FUNCTION__, n);
++				task->tk_pid, __func__, n);
+ 		/* Also retry */
+ 	}
+ 
+@@ -1445,7 +1455,7 @@ out_garbage:
+ 	if (task->tk_garb_retry) {
+ 		task->tk_garb_retry--;
+ 		dprintk("RPC: %5u %s: retrying\n",
+-				task->tk_pid, __FUNCTION__);
++				task->tk_pid, __func__);
+ 		task->tk_action = call_bind;
+ out_retry:
+ 		return ERR_PTR(-EAGAIN);
+@@ -1455,11 +1465,11 @@ out_eio:
+ out_err:
+ 	rpc_exit(task, error);
+ 	dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid,
+-			__FUNCTION__, error);
++			__func__, error);
+ 	return ERR_PTR(error);
+ out_overflow:
+ 	dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid,
+-			__FUNCTION__);
++			__func__);
+ 	goto out_garbage;
+ }
+ 
+@@ -1531,7 +1541,7 @@ void rpc_show_tasks(void)
+ 				proc = -1;
+ 
+ 			if (RPC_IS_QUEUED(t))
+-				rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
++				rpc_waitq = rpc_qname(t->tk_waitqueue);
+ 
+ 			printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
+ 				t->tk_pid, proc,
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index 1b395a4..5a9b0e7 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -479,13 +479,13 @@ rpc_lookup_parent(char *path, struct nameidata *nd)
+ 	mnt = rpc_get_mount();
+ 	if (IS_ERR(mnt)) {
+ 		printk(KERN_WARNING "%s: %s failed to mount "
+-			       "pseudofilesystem \n", __FILE__, __FUNCTION__);
++			       "pseudofilesystem \n", __FILE__, __func__);
+ 		return PTR_ERR(mnt);
+ 	}
+ 
+ 	if (vfs_path_lookup(mnt->mnt_root, mnt, path, LOOKUP_PARENT, nd)) {
+ 		printk(KERN_WARNING "%s: %s failed to find path %s\n",
+-				__FILE__, __FUNCTION__, path);
++				__FILE__, __func__, path);
+ 		rpc_put_mount();
+ 		return -ENOENT;
+ 	}
+@@ -604,7 +604,7 @@ rpc_populate(struct dentry *parent,
+ out_bad:
+ 	mutex_unlock(&dir->i_mutex);
+ 	printk(KERN_WARNING "%s: %s failed to populate directory %s\n",
+-			__FILE__, __FUNCTION__, parent->d_name.name);
++			__FILE__, __func__, parent->d_name.name);
+ 	return -ENOMEM;
+ }
+ 
+@@ -623,7 +623,7 @@ __rpc_mkdir(struct inode *dir, struct dentry *dentry)
+ 	return 0;
+ out_err:
+ 	printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
+-			__FILE__, __FUNCTION__, dentry->d_name.name);
++			__FILE__, __func__, dentry->d_name.name);
+ 	return -ENOMEM;
+ }
+ 
+@@ -715,7 +715,7 @@ err_depopulate:
+ err_dput:
+ 	dput(dentry);
+ 	printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n",
+-			__FILE__, __FUNCTION__, path, error);
++			__FILE__, __func__, path, error);
+ 	dentry = ERR_PTR(error);
+ 	goto out;
+ }
+@@ -804,7 +804,7 @@ err_dput:
+ 	dput(dentry);
+ 	dentry = ERR_PTR(-ENOMEM);
+ 	printk(KERN_WARNING "%s: %s() failed to create pipe %s/%s (errno = %d)\n",
+-			__FILE__, __FUNCTION__, parent->d_name.name, name,
++			__FILE__, __func__, parent->d_name.name, name,
+ 			-ENOMEM);
+ 	goto out;
+ }
+diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
+index 3164a08..0517967 100644
+--- a/net/sunrpc/rpcb_clnt.c
++++ b/net/sunrpc/rpcb_clnt.c
+@@ -224,7 +224,7 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
+ 	int status;
+ 
+ 	dprintk("RPC:       %s(" NIPQUAD_FMT ", %u, %u, %d)\n",
+-		__FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
++		__func__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
+ 
+ 	rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
+ 				sizeof(*sin), prot, 2, 0);
+@@ -283,7 +283,7 @@ void rpcb_getport_async(struct rpc_task *task)
+ 	struct rpcb_info *info;
+ 
+ 	dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
+-		task->tk_pid, __FUNCTION__,
++		task->tk_pid, __func__,
+ 		clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
+ 
+ 	/* Autobind on cloned rpc clients is discouraged */
+@@ -292,19 +292,19 @@ void rpcb_getport_async(struct rpc_task *task)
+ 	if (xprt_test_and_set_binding(xprt)) {
+ 		status = -EAGAIN;	/* tell caller to check again */
+ 		dprintk("RPC: %5u %s: waiting for another binder\n",
+-			task->tk_pid, __FUNCTION__);
++			task->tk_pid, __func__);
+ 		goto bailout_nowake;
+ 	}
+ 
+ 	/* Put self on queue before sending rpcbind request, in case
+ 	 * rpcb_getport_done completes before we return from rpc_run_task */
+-	rpc_sleep_on(&xprt->binding, task, NULL, NULL);
++	rpc_sleep_on(&xprt->binding, task, NULL);
+ 
+ 	/* Someone else may have bound if we slept */
+ 	if (xprt_bound(xprt)) {
+ 		status = 0;
+ 		dprintk("RPC: %5u %s: already bound\n",
+-			task->tk_pid, __FUNCTION__);
++			task->tk_pid, __func__);
+ 		goto bailout_nofree;
+ 	}
+ 
+@@ -321,27 +321,27 @@ void rpcb_getport_async(struct rpc_task *task)
+ 	default:
+ 		status = -EAFNOSUPPORT;
+ 		dprintk("RPC: %5u %s: bad address family\n",
+-				task->tk_pid, __FUNCTION__);
++				task->tk_pid, __func__);
+ 		goto bailout_nofree;
+ 	}
+ 	if (info[xprt->bind_index].rpc_proc == NULL) {
+ 		xprt->bind_index = 0;
+ 		status = -EPFNOSUPPORT;
+ 		dprintk("RPC: %5u %s: no more getport versions available\n",
+-			task->tk_pid, __FUNCTION__);
++			task->tk_pid, __func__);
+ 		goto bailout_nofree;
+ 	}
+ 	bind_version = info[xprt->bind_index].rpc_vers;
+ 
+ 	dprintk("RPC: %5u %s: trying rpcbind version %u\n",
+-		task->tk_pid, __FUNCTION__, bind_version);
++		task->tk_pid, __func__, bind_version);
+ 
+ 	rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot,
+ 				bind_version, 0);
+ 	if (IS_ERR(rpcb_clnt)) {
+ 		status = PTR_ERR(rpcb_clnt);
+ 		dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
+-			task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt));
++			task->tk_pid, __func__, PTR_ERR(rpcb_clnt));
+ 		goto bailout_nofree;
+ 	}
+ 
+@@ -349,7 +349,7 @@ void rpcb_getport_async(struct rpc_task *task)
+ 	if (!map) {
+ 		status = -ENOMEM;
+ 		dprintk("RPC: %5u %s: no memory available\n",
+-			task->tk_pid, __FUNCTION__);
++			task->tk_pid, __func__);
+ 		goto bailout_nofree;
+ 	}
+ 	map->r_prog = clnt->cl_prog;
+@@ -366,7 +366,7 @@ void rpcb_getport_async(struct rpc_task *task)
+ 	if (IS_ERR(child)) {
+ 		status = -EIO;
+ 		dprintk("RPC: %5u %s: rpc_run_task failed\n",
+-			task->tk_pid, __FUNCTION__);
++			task->tk_pid, __func__);
+ 		goto bailout;
+ 	}
+ 	rpc_put_task(child);
+diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
+index 4c66912..6eab9bf 100644
+--- a/net/sunrpc/sched.c
++++ b/net/sunrpc/sched.c
+@@ -38,9 +38,9 @@ static struct kmem_cache	*rpc_buffer_slabp __read_mostly;
+ static mempool_t	*rpc_task_mempool __read_mostly;
+ static mempool_t	*rpc_buffer_mempool __read_mostly;
+ 
+-static void			__rpc_default_timer(struct rpc_task *task);
+ static void			rpc_async_schedule(struct work_struct *);
+ static void			 rpc_release_task(struct rpc_task *task);
++static void __rpc_queue_timer_fn(unsigned long ptr);
+ 
+ /*
+  * RPC tasks sit here while waiting for conditions to improve.
+@@ -57,41 +57,30 @@ struct workqueue_struct *rpciod_workqueue;
+  * queue->lock and bh_disabled in order to avoid races within
+  * rpc_run_timer().
+  */
+-static inline void
+-__rpc_disable_timer(struct rpc_task *task)
++static void
++__rpc_disable_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
++	if (task->tk_timeout == 0)
++		return;
+ 	dprintk("RPC: %5u disabling timer\n", task->tk_pid);
+-	task->tk_timeout_fn = NULL;
+ 	task->tk_timeout = 0;
++	list_del(&task->u.tk_wait.timer_list);
++	if (list_empty(&queue->timer_list.list))
++		del_timer(&queue->timer_list.timer);
+ }
+ 
+-/*
+- * Run a timeout function.
+- * We use the callback in order to allow __rpc_wake_up_task()
+- * and friends to disable the timer synchronously on SMP systems
+- * without calling del_timer_sync(). The latter could cause a
+- * deadlock if called while we're holding spinlocks...
+- */
+-static void rpc_run_timer(struct rpc_task *task)
++static void
++rpc_set_queue_timer(struct rpc_wait_queue *queue, unsigned long expires)
+ {
+-	void (*callback)(struct rpc_task *);
+-
+-	callback = task->tk_timeout_fn;
+-	task->tk_timeout_fn = NULL;
+-	if (callback && RPC_IS_QUEUED(task)) {
+-		dprintk("RPC: %5u running timer\n", task->tk_pid);
+-		callback(task);
+-	}
+-	smp_mb__before_clear_bit();
+-	clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
+-	smp_mb__after_clear_bit();
++	queue->timer_list.expires = expires;
++	mod_timer(&queue->timer_list.timer, expires);
+ }
+ 
+ /*
+  * Set up a timer for the current task.
+  */
+-static inline void
+-__rpc_add_timer(struct rpc_task *task, rpc_action timer)
++static void
++__rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+ 	if (!task->tk_timeout)
+ 		return;
+@@ -99,27 +88,10 @@ __rpc_add_timer(struct rpc_task *task, rpc_action timer)
+ 	dprintk("RPC: %5u setting alarm for %lu ms\n",
+ 			task->tk_pid, task->tk_timeout * 1000 / HZ);
+ 
+-	if (timer)
+-		task->tk_timeout_fn = timer;
+-	else
+-		task->tk_timeout_fn = __rpc_default_timer;
+-	set_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
+-	mod_timer(&task->tk_timer, jiffies + task->tk_timeout);
+-}
+-
+-/*
+- * Delete any timer for the current task. Because we use del_timer_sync(),
+- * this function should never be called while holding queue->lock.
+- */
+-static void
+-rpc_delete_timer(struct rpc_task *task)
+-{
+-	if (RPC_IS_QUEUED(task))
+-		return;
+-	if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) {
+-		del_singleshot_timer_sync(&task->tk_timer);
+-		dprintk("RPC: %5u deleting timer\n", task->tk_pid);
+-	}
++	task->u.tk_wait.expires = jiffies + task->tk_timeout;
++	if (list_empty(&queue->timer_list.list) || time_before(task->u.tk_wait.expires, queue->timer_list.expires))
++		rpc_set_queue_timer(queue, task->u.tk_wait.expires);
++	list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list);
+ }
+ 
+ /*
+@@ -161,7 +133,7 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *
+ 		list_add(&task->u.tk_wait.list, &queue->tasks[0]);
+ 	else
+ 		list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
+-	task->u.tk_wait.rpc_waitq = queue;
++	task->tk_waitqueue = queue;
+ 	queue->qlen++;
+ 	rpc_set_queued(task);
+ 
+@@ -181,22 +153,18 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
+ 		list_move(&t->u.tk_wait.list, &task->u.tk_wait.list);
+ 		list_splice_init(&task->u.tk_wait.links, &t->u.tk_wait.links);
+ 	}
+-	list_del(&task->u.tk_wait.list);
+ }
+ 
+ /*
+  * Remove request from queue.
+  * Note: must be called with spin lock held.
+  */
+-static void __rpc_remove_wait_queue(struct rpc_task *task)
++static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+-	struct rpc_wait_queue *queue;
+-	queue = task->u.tk_wait.rpc_waitq;
+-
++	__rpc_disable_timer(queue, task);
+ 	if (RPC_IS_PRIORITY(queue))
+ 		__rpc_remove_wait_queue_priority(task);
+-	else
+-		list_del(&task->u.tk_wait.list);
++	list_del(&task->u.tk_wait.list);
+ 	queue->qlen--;
+ 	dprintk("RPC: %5u removed from queue %p \"%s\"\n",
+ 			task->tk_pid, queue, rpc_qname(queue));
+@@ -229,6 +197,9 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c
+ 		INIT_LIST_HEAD(&queue->tasks[i]);
+ 	queue->maxpriority = nr_queues - 1;
+ 	rpc_reset_waitqueue_priority(queue);
++	queue->qlen = 0;
++	setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue);
++	INIT_LIST_HEAD(&queue->timer_list.list);
+ #ifdef RPC_DEBUG
+ 	queue->name = qname;
+ #endif
+@@ -245,6 +216,12 @@ void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname)
+ }
+ EXPORT_SYMBOL_GPL(rpc_init_wait_queue);
+ 
++void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
++{
++	del_timer_sync(&queue->timer_list.timer);
++}
++EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
++
+ static int rpc_wait_bit_killable(void *word)
+ {
+ 	if (fatal_signal_pending(current))
+@@ -313,7 +290,6 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task);
+  */
+ static void rpc_make_runnable(struct rpc_task *task)
+ {
+-	BUG_ON(task->tk_timeout_fn);
+ 	rpc_clear_queued(task);
+ 	if (rpc_test_and_set_running(task))
+ 		return;
+@@ -326,7 +302,7 @@ static void rpc_make_runnable(struct rpc_task *task)
+ 		int status;
+ 
+ 		INIT_WORK(&task->u.tk_work, rpc_async_schedule);
+-		status = queue_work(task->tk_workqueue, &task->u.tk_work);
++		status = queue_work(rpciod_workqueue, &task->u.tk_work);
+ 		if (status < 0) {
+ 			printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status);
+ 			task->tk_status = status;
+@@ -343,7 +319,7 @@ static void rpc_make_runnable(struct rpc_task *task)
+  * as it's on a wait queue.
+  */
+ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
+-			rpc_action action, rpc_action timer)
++			rpc_action action)
+ {
+ 	dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n",
+ 			task->tk_pid, rpc_qname(q), jiffies);
+@@ -357,11 +333,11 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
+ 
+ 	BUG_ON(task->tk_callback != NULL);
+ 	task->tk_callback = action;
+-	__rpc_add_timer(task, timer);
++	__rpc_add_timer(q, task);
+ }
+ 
+ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
+-				rpc_action action, rpc_action timer)
++				rpc_action action)
+ {
+ 	/* Mark the task as being activated if so needed */
+ 	rpc_set_active(task);
+@@ -370,18 +346,19 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
+ 	 * Protect the queue operations.
+ 	 */
+ 	spin_lock_bh(&q->lock);
+-	__rpc_sleep_on(q, task, action, timer);
++	__rpc_sleep_on(q, task, action);
+ 	spin_unlock_bh(&q->lock);
+ }
+ EXPORT_SYMBOL_GPL(rpc_sleep_on);
+ 
+ /**
+  * __rpc_do_wake_up_task - wake up a single rpc_task
++ * @queue: wait queue
+  * @task: task to be woken up
+  *
+  * Caller must hold queue->lock, and have cleared the task queued flag.
+  */
+-static void __rpc_do_wake_up_task(struct rpc_task *task)
++static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+ 	dprintk("RPC: %5u __rpc_wake_up_task (now %lu)\n",
+ 			task->tk_pid, jiffies);
+@@ -395,8 +372,7 @@ static void __rpc_do_wake_up_task(struct rpc_task *task)
+ 		return;
+ 	}
+ 
+-	__rpc_disable_timer(task);
+-	__rpc_remove_wait_queue(task);
++	__rpc_remove_wait_queue(queue, task);
+ 
+ 	rpc_make_runnable(task);
+ 
+@@ -404,48 +380,32 @@ static void __rpc_do_wake_up_task(struct rpc_task *task)
+ }
+ 
+ /*
+- * Wake up the specified task
++ * Wake up a queued task while the queue lock is being held
+  */
+-static void __rpc_wake_up_task(struct rpc_task *task)
++static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+-	if (rpc_start_wakeup(task)) {
+-		if (RPC_IS_QUEUED(task))
+-			__rpc_do_wake_up_task(task);
+-		rpc_finish_wakeup(task);
+-	}
++	if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue)
++		__rpc_do_wake_up_task(queue, task);
+ }
+ 
+ /*
+- * Default timeout handler if none specified by user
++ * Wake up a task on a specific queue
+  */
+-static void
+-__rpc_default_timer(struct rpc_task *task)
++void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+-	dprintk("RPC: %5u timeout (default timer)\n", task->tk_pid);
+-	task->tk_status = -ETIMEDOUT;
+-	rpc_wake_up_task(task);
++	spin_lock_bh(&queue->lock);
++	rpc_wake_up_task_queue_locked(queue, task);
++	spin_unlock_bh(&queue->lock);
+ }
++EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task);
+ 
+ /*
+  * Wake up the specified task
+  */
+-void rpc_wake_up_task(struct rpc_task *task)
++static void rpc_wake_up_task(struct rpc_task *task)
+ {
+-	rcu_read_lock_bh();
+-	if (rpc_start_wakeup(task)) {
+-		if (RPC_IS_QUEUED(task)) {
+-			struct rpc_wait_queue *queue = task->u.tk_wait.rpc_waitq;
+-
+-			/* Note: we're already in a bh-safe context */
+-			spin_lock(&queue->lock);
+-			__rpc_do_wake_up_task(task);
+-			spin_unlock(&queue->lock);
+-		}
+-		rpc_finish_wakeup(task);
+-	}
+-	rcu_read_unlock_bh();
++	rpc_wake_up_queued_task(task->tk_waitqueue, task);
+ }
+-EXPORT_SYMBOL_GPL(rpc_wake_up_task);
+ 
+ /*
+  * Wake up the next task on a priority queue.
+@@ -495,7 +455,7 @@ new_queue:
+ new_owner:
+ 	rpc_set_waitqueue_owner(queue, task->tk_owner);
+ out:
+-	__rpc_wake_up_task(task);
++	rpc_wake_up_task_queue_locked(queue, task);
+ 	return task;
+ }
+ 
+@@ -508,16 +468,14 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue)
+ 
+ 	dprintk("RPC:       wake_up_next(%p \"%s\")\n",
+ 			queue, rpc_qname(queue));
+-	rcu_read_lock_bh();
+-	spin_lock(&queue->lock);
++	spin_lock_bh(&queue->lock);
+ 	if (RPC_IS_PRIORITY(queue))
+ 		task = __rpc_wake_up_next_priority(queue);
+ 	else {
+ 		task_for_first(task, &queue->tasks[0])
+-			__rpc_wake_up_task(task);
++			rpc_wake_up_task_queue_locked(queue, task);
+ 	}
+-	spin_unlock(&queue->lock);
+-	rcu_read_unlock_bh();
++	spin_unlock_bh(&queue->lock);
+ 
+ 	return task;
+ }
+@@ -534,18 +492,16 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
+ 	struct rpc_task *task, *next;
+ 	struct list_head *head;
+ 
+-	rcu_read_lock_bh();
+-	spin_lock(&queue->lock);
++	spin_lock_bh(&queue->lock);
+ 	head = &queue->tasks[queue->maxpriority];
+ 	for (;;) {
+ 		list_for_each_entry_safe(task, next, head, u.tk_wait.list)
+-			__rpc_wake_up_task(task);
++			rpc_wake_up_task_queue_locked(queue, task);
+ 		if (head == &queue->tasks[0])
+ 			break;
+ 		head--;
+ 	}
+-	spin_unlock(&queue->lock);
+-	rcu_read_unlock_bh();
++	spin_unlock_bh(&queue->lock);
+ }
+ EXPORT_SYMBOL_GPL(rpc_wake_up);
+ 
+@@ -561,26 +517,48 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
+ 	struct rpc_task *task, *next;
+ 	struct list_head *head;
+ 
+-	rcu_read_lock_bh();
+-	spin_lock(&queue->lock);
++	spin_lock_bh(&queue->lock);
+ 	head = &queue->tasks[queue->maxpriority];
+ 	for (;;) {
+ 		list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
+ 			task->tk_status = status;
+-			__rpc_wake_up_task(task);
++			rpc_wake_up_task_queue_locked(queue, task);
+ 		}
+ 		if (head == &queue->tasks[0])
+ 			break;
+ 		head--;
+ 	}
+-	spin_unlock(&queue->lock);
+-	rcu_read_unlock_bh();
++	spin_unlock_bh(&queue->lock);
+ }
+ EXPORT_SYMBOL_GPL(rpc_wake_up_status);
+ 
++static void __rpc_queue_timer_fn(unsigned long ptr)
++{
++	struct rpc_wait_queue *queue = (struct rpc_wait_queue *)ptr;
++	struct rpc_task *task, *n;
++	unsigned long expires, now, timeo;
++
++	spin_lock(&queue->lock);
++	expires = now = jiffies;
++	list_for_each_entry_safe(task, n, &queue->timer_list.list, u.tk_wait.timer_list) {
++		timeo = task->u.tk_wait.expires;
++		if (time_after_eq(now, timeo)) {
++			dprintk("RPC: %5u timeout\n", task->tk_pid);
++			task->tk_status = -ETIMEDOUT;
++			rpc_wake_up_task_queue_locked(queue, task);
++			continue;
++		}
++		if (expires == now || time_after(expires, timeo))
++			expires = timeo;
++	}
++	if (!list_empty(&queue->timer_list.list))
++		rpc_set_queue_timer(queue, expires);
++	spin_unlock(&queue->lock);
++}
++
+ static void __rpc_atrun(struct rpc_task *task)
+ {
+-	rpc_wake_up_task(task);
++	task->tk_status = 0;
+ }
+ 
+ /*
+@@ -589,7 +567,7 @@ static void __rpc_atrun(struct rpc_task *task)
+ void rpc_delay(struct rpc_task *task, unsigned long delay)
+ {
+ 	task->tk_timeout = delay;
+-	rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun);
++	rpc_sleep_on(&delay_queue, task, __rpc_atrun);
+ }
+ EXPORT_SYMBOL_GPL(rpc_delay);
+ 
+@@ -644,10 +622,6 @@ static void __rpc_execute(struct rpc_task *task)
+ 	BUG_ON(RPC_IS_QUEUED(task));
+ 
+ 	for (;;) {
+-		/*
+-		 * Garbage collection of pending timers...
+-		 */
+-		rpc_delete_timer(task);
+ 
+ 		/*
+ 		 * Execute any pending callback.
+@@ -816,8 +790,6 @@ EXPORT_SYMBOL_GPL(rpc_free);
+ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data)
+ {
+ 	memset(task, 0, sizeof(*task));
+-	setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer,
+-			(unsigned long)task);
+ 	atomic_set(&task->tk_count, 1);
+ 	task->tk_flags  = task_setup_data->flags;
+ 	task->tk_ops = task_setup_data->callback_ops;
+@@ -832,7 +804,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
+ 	task->tk_owner = current->tgid;
+ 
+ 	/* Initialize workqueue for async tasks */
+-	task->tk_workqueue = rpciod_workqueue;
++	task->tk_workqueue = task_setup_data->workqueue;
+ 
+ 	task->tk_client = task_setup_data->rpc_client;
+ 	if (task->tk_client != NULL) {
+@@ -845,12 +817,11 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
+ 		task->tk_action = rpc_prepare_task;
+ 
+ 	if (task_setup_data->rpc_message != NULL) {
+-		memcpy(&task->tk_msg, task_setup_data->rpc_message, sizeof(task->tk_msg));
++		task->tk_msg.rpc_proc = task_setup_data->rpc_message->rpc_proc;
++		task->tk_msg.rpc_argp = task_setup_data->rpc_message->rpc_argp;
++		task->tk_msg.rpc_resp = task_setup_data->rpc_message->rpc_resp;
+ 		/* Bind the user cred */
+-		if (task->tk_msg.rpc_cred != NULL)
+-			rpcauth_holdcred(task);
+-		else
+-			rpcauth_bindcred(task);
++		rpcauth_bindcred(task, task_setup_data->rpc_message->rpc_cred, task_setup_data->flags);
+ 		if (task->tk_action == NULL)
+ 			rpc_call_start(task);
+ 	}
+@@ -868,13 +839,6 @@ rpc_alloc_task(void)
+ 	return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS);
+ }
+ 
+-static void rpc_free_task(struct rcu_head *rcu)
+-{
+-	struct rpc_task *task = container_of(rcu, struct rpc_task, u.tk_rcu);
+-	dprintk("RPC: %5u freeing task\n", task->tk_pid);
+-	mempool_free(task, rpc_task_mempool);
+-}
+-
+ /*
+  * Create a new task for the specified client.
+  */
+@@ -898,12 +862,25 @@ out:
+ 	return task;
+ }
+ 
+-
+-void rpc_put_task(struct rpc_task *task)
++static void rpc_free_task(struct rpc_task *task)
+ {
+ 	const struct rpc_call_ops *tk_ops = task->tk_ops;
+ 	void *calldata = task->tk_calldata;
+ 
++	if (task->tk_flags & RPC_TASK_DYNAMIC) {
++		dprintk("RPC: %5u freeing task\n", task->tk_pid);
++		mempool_free(task, rpc_task_mempool);
++	}
++	rpc_release_calldata(tk_ops, calldata);
++}
++
++static void rpc_async_release(struct work_struct *work)
++{
++	rpc_free_task(container_of(work, struct rpc_task, u.tk_work));
++}
++
++void rpc_put_task(struct rpc_task *task)
++{
+ 	if (!atomic_dec_and_test(&task->tk_count))
+ 		return;
+ 	/* Release resources */
+@@ -915,9 +892,11 @@ void rpc_put_task(struct rpc_task *task)
+ 		rpc_release_client(task->tk_client);
+ 		task->tk_client = NULL;
+ 	}
+-	if (task->tk_flags & RPC_TASK_DYNAMIC)
+-		call_rcu_bh(&task->u.tk_rcu, rpc_free_task);
+-	rpc_release_calldata(tk_ops, calldata);
++	if (task->tk_workqueue != NULL) {
++		INIT_WORK(&task->u.tk_work, rpc_async_release);
++		queue_work(task->tk_workqueue, &task->u.tk_work);
++	} else
++		rpc_free_task(task);
+ }
+ EXPORT_SYMBOL_GPL(rpc_put_task);
+ 
+@@ -937,9 +916,6 @@ static void rpc_release_task(struct rpc_task *task)
+ 	}
+ 	BUG_ON (RPC_IS_QUEUED(task));
+ 
+-	/* Synchronously delete any running timer */
+-	rpc_delete_timer(task);
+-
+ #ifdef RPC_DEBUG
+ 	task->tk_magic = 0;
+ #endif
+@@ -1029,11 +1005,20 @@ rpc_destroy_mempool(void)
+ 		kmem_cache_destroy(rpc_task_slabp);
+ 	if (rpc_buffer_slabp)
+ 		kmem_cache_destroy(rpc_buffer_slabp);
++	rpc_destroy_wait_queue(&delay_queue);
+ }
+ 
+ int
+ rpc_init_mempool(void)
+ {
++	/*
++	 * The following is not strictly a mempool initialisation,
++	 * but there is no harm in doing it here
++	 */
++	rpc_init_wait_queue(&delay_queue, "delayq");
++	if (!rpciod_start())
++		goto err_nomem;
++
+ 	rpc_task_slabp = kmem_cache_create("rpc_tasks",
+ 					     sizeof(struct rpc_task),
+ 					     0, SLAB_HWCACHE_ALIGN,
+@@ -1054,13 +1039,6 @@ rpc_init_mempool(void)
+ 						      rpc_buffer_slabp);
+ 	if (!rpc_buffer_mempool)
+ 		goto err_nomem;
+-	if (!rpciod_start())
+-		goto err_nomem;
+-	/*
+-	 * The following is not strictly a mempool initialisation,
+-	 * but there is no harm in doing it here
+-	 */
+-	rpc_init_wait_queue(&delay_queue, "delayq");
+ 	return 0;
+ err_nomem:
+ 	rpc_destroy_mempool();
+diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
+index a290e15..d74c2d2 100644
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -301,7 +301,6 @@ static inline int
+ svc_pool_map_set_cpumask(unsigned int pidx, cpumask_t *oldmask)
+ {
+ 	struct svc_pool_map *m = &svc_pool_map;
+-	unsigned int node; /* or cpu */
+ 
+ 	/*
+ 	 * The caller checks for sv_nrpools > 1, which
+@@ -314,16 +313,23 @@ svc_pool_map_set_cpumask(unsigned int pidx, cpumask_t *oldmask)
+ 	default:
+ 		return 0;
+ 	case SVC_POOL_PERCPU:
+-		node = m->pool_to[pidx];
++	{
++		unsigned int cpu = m->pool_to[pidx];
++
+ 		*oldmask = current->cpus_allowed;
+-		set_cpus_allowed(current, cpumask_of_cpu(node));
++		set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ 		return 1;
++	}
+ 	case SVC_POOL_PERNODE:
+-		node = m->pool_to[pidx];
++	{
++		unsigned int node = m->pool_to[pidx];
++		node_to_cpumask_ptr(nodecpumask, node);
++
+ 		*oldmask = current->cpus_allowed;
+-		set_cpus_allowed(current, node_to_cpumask(node));
++		set_cpus_allowed_ptr(current, nodecpumask);
+ 		return 1;
+ 	}
++	}
+ }
+ 
+ /*
+@@ -504,8 +510,7 @@ EXPORT_SYMBOL(svc_destroy);
+ static int
+ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
+ {
+-	int pages;
+-	int arghi;
++	unsigned int pages, arghi;
+ 
+ 	pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply.
+ 				       * We assume one is at most one page
+@@ -519,7 +524,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
+ 		rqstp->rq_pages[arghi++] = p;
+ 		pages--;
+ 	}
+-	return ! pages;
++	return pages == 0;
+ }
+ 
+ /*
+@@ -528,8 +533,9 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
+ static void
+ svc_release_buffer(struct svc_rqst *rqstp)
+ {
+-	int i;
+-	for (i=0; i<ARRAY_SIZE(rqstp->rq_pages); i++)
++	unsigned int i;
++
++	for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++)
+ 		if (rqstp->rq_pages[i])
+ 			put_page(rqstp->rq_pages[i]);
+ }
+@@ -584,7 +590,7 @@ __svc_create_thread(svc_thread_fn func, struct svc_serv *serv,
+ 	struct svc_rqst	*rqstp;
+ 	int		error = -ENOMEM;
+ 	int		have_oldmask = 0;
+-	cpumask_t	oldmask;
++	cpumask_t	uninitialized_var(oldmask);
+ 
+ 	rqstp = svc_prepare_thread(serv, pool);
+ 	if (IS_ERR(rqstp)) {
+@@ -613,16 +619,6 @@ out_thread:
+ }
+ 
+ /*
+- * Create a thread in the default pool.  Caller must hold BKL.
+- */
+-int
+-svc_create_thread(svc_thread_fn func, struct svc_serv *serv)
+-{
+-	return __svc_create_thread(func, serv, &serv->sv_pools[0]);
+-}
+-EXPORT_SYMBOL(svc_create_thread);
+-
+-/*
+  * Choose a pool in which to create a new thread, for svc_set_num_threads
+  */
+ static inline struct svc_pool *
+@@ -915,8 +911,7 @@ svc_process(struct svc_rqst *rqstp)
+ 	case SVC_OK:
+ 		break;
+ 	case SVC_GARBAGE:
+-		rpc_stat = rpc_garbage_args;
+-		goto err_bad;
++		goto err_garbage;
+ 	case SVC_SYSERR:
+ 		rpc_stat = rpc_system_err;
+ 		goto err_bad;
+diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
+index 332eb47..d8e8d79 100644
+--- a/net/sunrpc/svc_xprt.c
++++ b/net/sunrpc/svc_xprt.c
+@@ -18,6 +18,7 @@
+ #include <linux/skbuff.h>
+ #include <linux/file.h>
+ #include <linux/freezer.h>
++#include <linux/kthread.h>
+ #include <net/sock.h>
+ #include <net/checksum.h>
+ #include <net/ip.h>
+@@ -586,8 +587,12 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ 		while (rqstp->rq_pages[i] == NULL) {
+ 			struct page *p = alloc_page(GFP_KERNEL);
+ 			if (!p) {
+-				int j = msecs_to_jiffies(500);
+-				schedule_timeout_uninterruptible(j);
++				set_current_state(TASK_INTERRUPTIBLE);
++				if (signalled() || kthread_should_stop()) {
++					set_current_state(TASK_RUNNING);
++					return -EINTR;
++				}
++				schedule_timeout(msecs_to_jiffies(500));
+ 			}
+ 			rqstp->rq_pages[i] = p;
+ 		}
+@@ -607,7 +612,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ 
+ 	try_to_freeze();
+ 	cond_resched();
+-	if (signalled())
++	if (signalled() || kthread_should_stop())
+ 		return -EINTR;
+ 
+ 	spin_lock_bh(&pool->sp_lock);
+@@ -626,6 +631,20 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ 		 * to bring down the daemons ...
+ 		 */
+ 		set_current_state(TASK_INTERRUPTIBLE);
++
++		/*
++		 * checking kthread_should_stop() here allows us to avoid
++		 * locking and signalling when stopping kthreads that call
++		 * svc_recv. If the thread has already been woken up, then
++		 * we can exit here without sleeping. If not, then it
++		 * it'll be woken up quickly during the schedule_timeout
++		 */
++		if (kthread_should_stop()) {
++			set_current_state(TASK_RUNNING);
++			spin_unlock_bh(&pool->sp_lock);
++			return -EINTR;
++		}
++
+ 		add_wait_queue(&rqstp->rq_wait, &wait);
+ 		spin_unlock_bh(&pool->sp_lock);
+ 
+@@ -641,7 +660,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ 			svc_thread_dequeue(pool, rqstp);
+ 			spin_unlock_bh(&pool->sp_lock);
+ 			dprintk("svc: server %p, no data yet\n", rqstp);
+-			return signalled()? -EINTR : -EAGAIN;
++			if (signalled() || kthread_should_stop())
++				return -EINTR;
++			else
++				return -EAGAIN;
+ 		}
+ 	}
+ 	spin_unlock_bh(&pool->sp_lock);
+diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
+index 3c64051..3f30ee6 100644
+--- a/net/sunrpc/svcauth_unix.c
++++ b/net/sunrpc/svcauth_unix.c
+@@ -11,7 +11,8 @@
+ #include <linux/hash.h>
+ #include <linux/string.h>
+ #include <net/sock.h>
+-
++#include <net/ipv6.h>
++#include <linux/kernel.h>
+ #define RPCDBG_FACILITY	RPCDBG_AUTH
+ 
+ 
+@@ -85,7 +86,7 @@ static void svcauth_unix_domain_release(struct auth_domain *dom)
+ struct ip_map {
+ 	struct cache_head	h;
+ 	char			m_class[8]; /* e.g. "nfsd" */
+-	struct in_addr		m_addr;
++	struct in6_addr		m_addr;
+ 	struct unix_domain	*m_client;
+ 	int			m_add_change;
+ };
+@@ -113,12 +114,19 @@ static inline int hash_ip(__be32 ip)
+ 	return (hash ^ (hash>>8)) & 0xff;
+ }
+ #endif
++static inline int hash_ip6(struct in6_addr ip)
++{
++	return (hash_ip(ip.s6_addr32[0]) ^
++		hash_ip(ip.s6_addr32[1]) ^
++		hash_ip(ip.s6_addr32[2]) ^
++		hash_ip(ip.s6_addr32[3]));
++}
+ static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
+ {
+ 	struct ip_map *orig = container_of(corig, struct ip_map, h);
+ 	struct ip_map *new = container_of(cnew, struct ip_map, h);
+ 	return strcmp(orig->m_class, new->m_class) == 0
+-		&& orig->m_addr.s_addr == new->m_addr.s_addr;
++		&& ipv6_addr_equal(&orig->m_addr, &new->m_addr);
+ }
+ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
+ {
+@@ -126,7 +134,7 @@ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
+ 	struct ip_map *item = container_of(citem, struct ip_map, h);
+ 
+ 	strcpy(new->m_class, item->m_class);
+-	new->m_addr.s_addr = item->m_addr.s_addr;
++	ipv6_addr_copy(&new->m_addr, &item->m_addr);
+ }
+ static void update(struct cache_head *cnew, struct cache_head *citem)
+ {
+@@ -150,22 +158,24 @@ static void ip_map_request(struct cache_detail *cd,
+ 				  struct cache_head *h,
+ 				  char **bpp, int *blen)
+ {
+-	char text_addr[20];
++	char text_addr[40];
+ 	struct ip_map *im = container_of(h, struct ip_map, h);
+-	__be32 addr = im->m_addr.s_addr;
+-
+-	snprintf(text_addr, 20, "%u.%u.%u.%u",
+-		 ntohl(addr) >> 24 & 0xff,
+-		 ntohl(addr) >> 16 & 0xff,
+-		 ntohl(addr) >>  8 & 0xff,
+-		 ntohl(addr) >>  0 & 0xff);
+ 
++	if (ipv6_addr_v4mapped(&(im->m_addr))) {
++		snprintf(text_addr, 20, NIPQUAD_FMT,
++				ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
++				ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
++				ntohl(im->m_addr.s6_addr32[3]) >>  8 & 0xff,
++				ntohl(im->m_addr.s6_addr32[3]) >>  0 & 0xff);
++	} else {
++		snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
++	}
+ 	qword_add(bpp, blen, im->m_class);
+ 	qword_add(bpp, blen, text_addr);
+ 	(*bpp)[-1] = '\n';
+ }
+ 
+-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
++static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
+ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
+ 
+ static int ip_map_parse(struct cache_detail *cd,
+@@ -176,10 +186,10 @@ static int ip_map_parse(struct cache_detail *cd,
+ 	 * for scratch: */
+ 	char *buf = mesg;
+ 	int len;
+-	int b1,b2,b3,b4;
++	int b1, b2, b3, b4, b5, b6, b7, b8;
+ 	char c;
+ 	char class[8];
+-	struct in_addr addr;
++	struct in6_addr addr;
+ 	int err;
+ 
+ 	struct ip_map *ipmp;
+@@ -198,7 +208,23 @@ static int ip_map_parse(struct cache_detail *cd,
+ 	len = qword_get(&mesg, buf, mlen);
+ 	if (len <= 0) return -EINVAL;
+ 
+-	if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
++	if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
++		addr.s6_addr32[0] = 0;
++		addr.s6_addr32[1] = 0;
++		addr.s6_addr32[2] = htonl(0xffff);
++		addr.s6_addr32[3] =
++			htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
++       } else if (sscanf(buf, NIP6_FMT "%c",
++			&b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
++		addr.s6_addr16[0] = htons(b1);
++		addr.s6_addr16[1] = htons(b2);
++		addr.s6_addr16[2] = htons(b3);
++		addr.s6_addr16[3] = htons(b4);
++		addr.s6_addr16[4] = htons(b5);
++		addr.s6_addr16[5] = htons(b6);
++		addr.s6_addr16[6] = htons(b7);
++		addr.s6_addr16[7] = htons(b8);
++       } else
+ 		return -EINVAL;
+ 
+ 	expiry = get_expiry(&mesg);
+@@ -216,10 +242,7 @@ static int ip_map_parse(struct cache_detail *cd,
+ 	} else
+ 		dom = NULL;
+ 
+-	addr.s_addr =
+-		htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+-
+-	ipmp = ip_map_lookup(class,addr);
++	ipmp = ip_map_lookup(class, &addr);
+ 	if (ipmp) {
+ 		err = ip_map_update(ipmp,
+ 			     container_of(dom, struct unix_domain, h),
+@@ -239,7 +262,7 @@ static int ip_map_show(struct seq_file *m,
+ 		       struct cache_head *h)
+ {
+ 	struct ip_map *im;
+-	struct in_addr addr;
++	struct in6_addr addr;
+ 	char *dom = "-no-domain-";
+ 
+ 	if (h == NULL) {
+@@ -248,20 +271,24 @@ static int ip_map_show(struct seq_file *m,
+ 	}
+ 	im = container_of(h, struct ip_map, h);
+ 	/* class addr domain */
+-	addr = im->m_addr;
++	ipv6_addr_copy(&addr, &im->m_addr);
+ 
+ 	if (test_bit(CACHE_VALID, &h->flags) &&
+ 	    !test_bit(CACHE_NEGATIVE, &h->flags))
+ 		dom = im->m_client->h.name;
+ 
+-	seq_printf(m, "%s %d.%d.%d.%d %s\n",
+-		   im->m_class,
+-		   ntohl(addr.s_addr) >> 24 & 0xff,
+-		   ntohl(addr.s_addr) >> 16 & 0xff,
+-		   ntohl(addr.s_addr) >>  8 & 0xff,
+-		   ntohl(addr.s_addr) >>  0 & 0xff,
+-		   dom
+-		   );
++	if (ipv6_addr_v4mapped(&addr)) {
++		seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
++			im->m_class,
++			ntohl(addr.s6_addr32[3]) >> 24 & 0xff,
++			ntohl(addr.s6_addr32[3]) >> 16 & 0xff,
++			ntohl(addr.s6_addr32[3]) >>  8 & 0xff,
++			ntohl(addr.s6_addr32[3]) >>  0 & 0xff,
++			dom);
++	} else {
++		seq_printf(m, "%s" NIP6_FMT "%s\n",
++			im->m_class, NIP6(addr), dom);
++	}
+ 	return 0;
+ }
+ 
+@@ -281,16 +308,16 @@ struct cache_detail ip_map_cache = {
+ 	.alloc		= ip_map_alloc,
+ };
+ 
+-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
++static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
+ {
+ 	struct ip_map ip;
+ 	struct cache_head *ch;
+ 
+ 	strcpy(ip.m_class, class);
+-	ip.m_addr = addr;
++	ipv6_addr_copy(&ip.m_addr, addr);
+ 	ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
+ 				 hash_str(class, IP_HASHBITS) ^
+-				 hash_ip(addr.s_addr));
++				 hash_ip6(*addr));
+ 
+ 	if (ch)
+ 		return container_of(ch, struct ip_map, h);
+@@ -319,14 +346,14 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex
+ 	ch = sunrpc_cache_update(&ip_map_cache,
+ 				 &ip.h, &ipm->h,
+ 				 hash_str(ipm->m_class, IP_HASHBITS) ^
+-				 hash_ip(ipm->m_addr.s_addr));
++				 hash_ip6(ipm->m_addr));
+ 	if (!ch)
+ 		return -ENOMEM;
+ 	cache_put(ch, &ip_map_cache);
+ 	return 0;
+ }
+ 
+-int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
++int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
+ {
+ 	struct unix_domain *udom;
+ 	struct ip_map *ipmp;
+@@ -355,7 +382,7 @@ int auth_unix_forget_old(struct auth_domain *dom)
+ }
+ EXPORT_SYMBOL(auth_unix_forget_old);
+ 
+-struct auth_domain *auth_unix_lookup(struct in_addr addr)
++struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
+ {
+ 	struct ip_map *ipm;
+ 	struct auth_domain *rv;
+@@ -650,9 +677,24 @@ static int unix_gid_find(uid_t uid, struct group_info **gip,
+ int
+ svcauth_unix_set_client(struct svc_rqst *rqstp)
+ {
+-	struct sockaddr_in *sin = svc_addr_in(rqstp);
++	struct sockaddr_in *sin;
++	struct sockaddr_in6 *sin6, sin6_storage;
+ 	struct ip_map *ipm;
+ 
++	switch (rqstp->rq_addr.ss_family) {
++	case AF_INET:
++		sin = svc_addr_in(rqstp);
++		sin6 = &sin6_storage;
++		ipv6_addr_set(&sin6->sin6_addr, 0, 0,
++				htonl(0x0000FFFF), sin->sin_addr.s_addr);
++		break;
++	case AF_INET6:
++		sin6 = svc_addr_in6(rqstp);
++		break;
++	default:
++		BUG();
++	}
++
+ 	rqstp->rq_client = NULL;
+ 	if (rqstp->rq_proc == 0)
+ 		return SVC_OK;
+@@ -660,7 +702,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
+ 	ipm = ip_map_cached_get(rqstp);
+ 	if (ipm == NULL)
+ 		ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
+-				    sin->sin_addr);
++				    &sin6->sin6_addr);
+ 
+ 	if (ipm == NULL)
+ 		return SVC_DENIED;
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index c475977..3e65719 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -38,6 +38,7 @@
+ #include <net/checksum.h>
+ #include <net/ip.h>
+ #include <net/ipv6.h>
++#include <net/tcp.h>
+ #include <net/tcp_states.h>
+ #include <asm/uaccess.h>
+ #include <asm/ioctls.h>
+@@ -45,6 +46,7 @@
+ #include <linux/sunrpc/types.h>
+ #include <linux/sunrpc/clnt.h>
+ #include <linux/sunrpc/xdr.h>
++#include <linux/sunrpc/msg_prot.h>
+ #include <linux/sunrpc/svcsock.h>
+ #include <linux/sunrpc/stats.h>
+ 
+@@ -822,8 +824,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
+ 	 * the next four bytes. Otherwise try to gobble up as much as
+ 	 * possible up to the complete record length.
+ 	 */
+-	if (svsk->sk_tcplen < 4) {
+-		unsigned long	want = 4 - svsk->sk_tcplen;
++	if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
++		int		want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
+ 		struct kvec	iov;
+ 
+ 		iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen;
+@@ -833,32 +835,31 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
+ 		svsk->sk_tcplen += len;
+ 
+ 		if (len < want) {
+-			dprintk("svc: short recvfrom while reading record length (%d of %lu)\n",
+-				len, want);
++			dprintk("svc: short recvfrom while reading record "
++				"length (%d of %d)\n", len, want);
+ 			svc_xprt_received(&svsk->sk_xprt);
+ 			return -EAGAIN; /* record header not complete */
+ 		}
+ 
+ 		svsk->sk_reclen = ntohl(svsk->sk_reclen);
+-		if (!(svsk->sk_reclen & 0x80000000)) {
++		if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) {
+ 			/* FIXME: technically, a record can be fragmented,
+ 			 *  and non-terminal fragments will not have the top
+ 			 *  bit set in the fragment length header.
+ 			 *  But apparently no known nfs clients send fragmented
+ 			 *  records. */
+ 			if (net_ratelimit())
+-				printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
+-				       " (non-terminal)\n",
+-				       (unsigned long) svsk->sk_reclen);
++				printk(KERN_NOTICE "RPC: multiple fragments "
++					"per record not supported\n");
+ 			goto err_delete;
+ 		}
+-		svsk->sk_reclen &= 0x7fffffff;
++		svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK;
+ 		dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
+ 		if (svsk->sk_reclen > serv->sv_max_mesg) {
+ 			if (net_ratelimit())
+-				printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
+-				       " (large)\n",
+-				       (unsigned long) svsk->sk_reclen);
++				printk(KERN_NOTICE "RPC: "
++					"fragment too large: 0x%08lx\n",
++					(unsigned long)svsk->sk_reclen);
+ 			goto err_delete;
+ 		}
+ 	}
+@@ -1045,7 +1046,6 @@ void svc_cleanup_xprt_sock(void)
+ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
+ {
+ 	struct sock	*sk = svsk->sk_sk;
+-	struct tcp_sock *tp = tcp_sk(sk);
+ 
+ 	svc_xprt_init(&svc_tcp_class, &svsk->sk_xprt, serv);
+ 	set_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags);
+@@ -1063,7 +1063,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
+ 		svsk->sk_reclen = 0;
+ 		svsk->sk_tcplen = 0;
+ 
+-		tp->nonagle = 1;        /* disable Nagle's algorithm */
++		tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
+ 
+ 		/* initialise setting must have enough space to
+ 		 * receive and respond to one request.
+@@ -1101,6 +1101,7 @@ void svc_sock_update_bufs(struct svc_serv *serv)
+ 	}
+ 	spin_unlock_bh(&serv->sv_lock);
+ }
++EXPORT_SYMBOL(svc_sock_update_bufs);
+ 
+ /*
+  * Initialize socket for RPC use and create svc_sock struct
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index d5553b8..75d748e 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -188,9 +188,9 @@ out_sleep:
+ 	task->tk_timeout = 0;
+ 	task->tk_status = -EAGAIN;
+ 	if (req && req->rq_ntrans)
+-		rpc_sleep_on(&xprt->resend, task, NULL, NULL);
++		rpc_sleep_on(&xprt->resend, task, NULL);
+ 	else
+-		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
++		rpc_sleep_on(&xprt->sending, task, NULL);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(xprt_reserve_xprt);
+@@ -238,9 +238,9 @@ out_sleep:
+ 	task->tk_timeout = 0;
+ 	task->tk_status = -EAGAIN;
+ 	if (req && req->rq_ntrans)
+-		rpc_sleep_on(&xprt->resend, task, NULL, NULL);
++		rpc_sleep_on(&xprt->resend, task, NULL);
+ 	else
+-		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
++		rpc_sleep_on(&xprt->sending, task, NULL);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong);
+@@ -447,13 +447,13 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks);
+  * @task: task to be put to sleep
+  *
+  */
+-void xprt_wait_for_buffer_space(struct rpc_task *task)
++void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action)
+ {
+ 	struct rpc_rqst *req = task->tk_rqstp;
+ 	struct rpc_xprt *xprt = req->rq_xprt;
+ 
+ 	task->tk_timeout = req->rq_timeout;
+-	rpc_sleep_on(&xprt->pending, task, NULL, NULL);
++	rpc_sleep_on(&xprt->pending, task, action);
+ }
+ EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space);
+ 
+@@ -472,7 +472,7 @@ void xprt_write_space(struct rpc_xprt *xprt)
+ 	if (xprt->snd_task) {
+ 		dprintk("RPC:       write space: waking waiting task on "
+ 				"xprt %p\n", xprt);
+-		rpc_wake_up_task(xprt->snd_task);
++		rpc_wake_up_queued_task(&xprt->pending, xprt->snd_task);
+ 	}
+ 	spin_unlock_bh(&xprt->transport_lock);
+ }
+@@ -602,11 +602,37 @@ void xprt_force_disconnect(struct rpc_xprt *xprt)
+ 	/* Try to schedule an autoclose RPC call */
+ 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
+ 		queue_work(rpciod_workqueue, &xprt->task_cleanup);
+-	else if (xprt->snd_task != NULL)
+-		rpc_wake_up_task(xprt->snd_task);
++	xprt_wake_pending_tasks(xprt, -ENOTCONN);
++	spin_unlock_bh(&xprt->transport_lock);
++}
++
++/**
++ * xprt_conditional_disconnect - force a transport to disconnect
++ * @xprt: transport to disconnect
++ * @cookie: 'connection cookie'
++ *
++ * This attempts to break the connection if and only if 'cookie' matches
++ * the current transport 'connection cookie'. It ensures that we don't
++ * try to break the connection more than once when we need to retransmit
++ * a batch of RPC requests.
++ *
++ */
++void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie)
++{
++	/* Don't race with the test_bit() in xprt_clear_locked() */
++	spin_lock_bh(&xprt->transport_lock);
++	if (cookie != xprt->connect_cookie)
++		goto out;
++	if (test_bit(XPRT_CLOSING, &xprt->state) || !xprt_connected(xprt))
++		goto out;
++	set_bit(XPRT_CLOSE_WAIT, &xprt->state);
++	/* Try to schedule an autoclose RPC call */
++	if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
++		queue_work(rpciod_workqueue, &xprt->task_cleanup);
++	xprt_wake_pending_tasks(xprt, -ENOTCONN);
++out:
+ 	spin_unlock_bh(&xprt->transport_lock);
+ }
+-EXPORT_SYMBOL_GPL(xprt_force_disconnect);
+ 
+ static void
+ xprt_init_autodisconnect(unsigned long data)
+@@ -653,7 +679,7 @@ void xprt_connect(struct rpc_task *task)
+ 			task->tk_rqstp->rq_bytes_sent = 0;
+ 
+ 		task->tk_timeout = xprt->connect_timeout;
+-		rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
++		rpc_sleep_on(&xprt->pending, task, xprt_connect_status);
+ 		xprt->stat.connect_start = jiffies;
+ 		xprt->ops->connect(task);
+ 	}
+@@ -749,18 +775,20 @@ EXPORT_SYMBOL_GPL(xprt_update_rtt);
+ void xprt_complete_rqst(struct rpc_task *task, int copied)
+ {
+ 	struct rpc_rqst *req = task->tk_rqstp;
++	struct rpc_xprt *xprt = req->rq_xprt;
+ 
+ 	dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
+ 			task->tk_pid, ntohl(req->rq_xid), copied);
+ 
+-	task->tk_xprt->stat.recvs++;
++	xprt->stat.recvs++;
+ 	task->tk_rtt = (long)jiffies - req->rq_xtime;
+ 
+ 	list_del_init(&req->rq_list);
++	req->rq_private_buf.len = copied;
+ 	/* Ensure all writes are done before we update req->rq_received */
+ 	smp_wmb();
+-	req->rq_received = req->rq_private_buf.len = copied;
+-	rpc_wake_up_task(task);
++	req->rq_received = copied;
++	rpc_wake_up_queued_task(&xprt->pending, task);
+ }
+ EXPORT_SYMBOL_GPL(xprt_complete_rqst);
+ 
+@@ -769,17 +797,17 @@ static void xprt_timer(struct rpc_task *task)
+ 	struct rpc_rqst *req = task->tk_rqstp;
+ 	struct rpc_xprt *xprt = req->rq_xprt;
+ 
++	if (task->tk_status != -ETIMEDOUT)
++		return;
+ 	dprintk("RPC: %5u xprt_timer\n", task->tk_pid);
+ 
+-	spin_lock(&xprt->transport_lock);
++	spin_lock_bh(&xprt->transport_lock);
+ 	if (!req->rq_received) {
+ 		if (xprt->ops->timer)
+ 			xprt->ops->timer(task);
+-		task->tk_status = -ETIMEDOUT;
+-	}
+-	task->tk_timeout = 0;
+-	rpc_wake_up_task(task);
+-	spin_unlock(&xprt->transport_lock);
++	} else
++		task->tk_status = 0;
++	spin_unlock_bh(&xprt->transport_lock);
+ }
+ 
+ /**
+@@ -849,6 +877,7 @@ void xprt_transmit(struct rpc_task *task)
+ 	} else if (!req->rq_bytes_sent)
+ 		return;
+ 
++	req->rq_connect_cookie = xprt->connect_cookie;
+ 	status = xprt->ops->send_request(task);
+ 	if (status == 0) {
+ 		dprintk("RPC: %5u xmit complete\n", task->tk_pid);
+@@ -864,7 +893,7 @@ void xprt_transmit(struct rpc_task *task)
+ 		if (!xprt_connected(xprt))
+ 			task->tk_status = -ENOTCONN;
+ 		else if (!req->rq_received)
+-			rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
++			rpc_sleep_on(&xprt->pending, task, xprt_timer);
+ 		spin_unlock_bh(&xprt->transport_lock);
+ 		return;
+ 	}
+@@ -875,7 +904,7 @@ void xprt_transmit(struct rpc_task *task)
+ 	 */
+ 	task->tk_status = status;
+ 	if (status == -ECONNREFUSED)
+-		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
++		rpc_sleep_on(&xprt->sending, task, NULL);
+ }
+ 
+ static inline void do_xprt_reserve(struct rpc_task *task)
+@@ -895,7 +924,7 @@ static inline void do_xprt_reserve(struct rpc_task *task)
+ 	dprintk("RPC:       waiting for request slot\n");
+ 	task->tk_status = -EAGAIN;
+ 	task->tk_timeout = 0;
+-	rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
++	rpc_sleep_on(&xprt->backlog, task, NULL);
+ }
+ 
+ /**
+@@ -1052,6 +1081,11 @@ static void xprt_destroy(struct kref *kref)
+ 	xprt->shutdown = 1;
+ 	del_timer_sync(&xprt->timer);
+ 
++	rpc_destroy_wait_queue(&xprt->binding);
++	rpc_destroy_wait_queue(&xprt->pending);
++	rpc_destroy_wait_queue(&xprt->sending);
++	rpc_destroy_wait_queue(&xprt->resend);
++	rpc_destroy_wait_queue(&xprt->backlog);
+ 	/*
+ 	 * Tear down transport state and free the rpc_xprt
+ 	 */
+diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
+index 16fd3f6..af408fc 100644
+--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
++++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
+@@ -1036,6 +1036,8 @@ int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
+ 			wait_event(xprt->sc_send_wait,
+ 				   atomic_read(&xprt->sc_sq_count) <
+ 				   xprt->sc_sq_depth);
++			if (test_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags))
++				return 0;
+ 			continue;
+ 		}
+ 		/* Bumped used SQ WR count and post */
+diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
+index ffbf22a..8ea283e 100644
+--- a/net/sunrpc/xprtrdma/verbs.c
++++ b/net/sunrpc/xprtrdma/verbs.c
+@@ -1573,7 +1573,6 @@ rpcrdma_ep_post(struct rpcrdma_ia *ia,
+ 	send_wr.sg_list = req->rl_send_iov;
+ 	send_wr.num_sge = req->rl_niovs;
+ 	send_wr.opcode = IB_WR_SEND;
+-	send_wr.imm_data = 0;
+ 	if (send_wr.num_sge == 4)	/* no need to sync any pad (constant) */
+ 		ib_dma_sync_single_for_device(ia->ri_id->device,
+ 			req->rl_send_iov[3].addr, req->rl_send_iov[3].length,
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 30e7ac2..ddbe981 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -136,12 +136,6 @@ static ctl_table sunrpc_table[] = {
+ #endif
+ 
+ /*
+- * How many times to try sending a request on a socket before waiting
+- * for the socket buffer to clear.
+- */
+-#define XS_SENDMSG_RETRY	(10U)
+-
+-/*
+  * Time out for an RPC UDP socket connect.  UDP socket connects are
+  * synchronous, but we set a timeout anyway in case of resource
+  * exhaustion on the local host.
+@@ -516,6 +510,14 @@ out:
+ 	return sent;
+ }
+ 
++static void xs_nospace_callback(struct rpc_task *task)
++{
++	struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt);
++
++	transport->inet->sk_write_pending--;
++	clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
++}
++
+ /**
+  * xs_nospace - place task on wait queue if transmit was incomplete
+  * @task: task to put to sleep
+@@ -531,20 +533,27 @@ static void xs_nospace(struct rpc_task *task)
+ 			task->tk_pid, req->rq_slen - req->rq_bytes_sent,
+ 			req->rq_slen);
+ 
+-	if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
+-		/* Protect against races with write_space */
+-		spin_lock_bh(&xprt->transport_lock);
+-
+-		/* Don't race with disconnect */
+-		if (!xprt_connected(xprt))
+-			task->tk_status = -ENOTCONN;
+-		else if (test_bit(SOCK_NOSPACE, &transport->sock->flags))
+-			xprt_wait_for_buffer_space(task);
++	/* Protect against races with write_space */
++	spin_lock_bh(&xprt->transport_lock);
++
++	/* Don't race with disconnect */
++	if (xprt_connected(xprt)) {
++		if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
++			/*
++			 * Notify TCP that we're limited by the application
++			 * window size
++			 */
++			set_bit(SOCK_NOSPACE, &transport->sock->flags);
++			transport->inet->sk_write_pending++;
++			/* ...and wait for more buffer space */
++			xprt_wait_for_buffer_space(task, xs_nospace_callback);
++		}
++	} else {
++		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
++		task->tk_status = -ENOTCONN;
++	}
+ 
+-		spin_unlock_bh(&xprt->transport_lock);
+-	} else
+-		/* Keep holding the socket if it is blocked */
+-		rpc_delay(task, HZ>>4);
++	spin_unlock_bh(&xprt->transport_lock);
+ }
+ 
+ /**
+@@ -588,19 +597,20 @@ static int xs_udp_send_request(struct rpc_task *task)
+ 	}
+ 
+ 	switch (status) {
++	case -EAGAIN:
++		xs_nospace(task);
++		break;
+ 	case -ENETUNREACH:
+ 	case -EPIPE:
+ 	case -ECONNREFUSED:
+ 		/* When the server has died, an ICMP port unreachable message
+ 		 * prompts ECONNREFUSED. */
+-		break;
+-	case -EAGAIN:
+-		xs_nospace(task);
++		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+ 		break;
+ 	default:
++		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+ 		dprintk("RPC:       sendmsg returned unrecognized error %d\n",
+ 			-status);
+-		break;
+ 	}
+ 
+ 	return status;
+@@ -650,7 +660,6 @@ static int xs_tcp_send_request(struct rpc_task *task)
+ 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+ 	struct xdr_buf *xdr = &req->rq_snd_buf;
+ 	int status;
+-	unsigned int retry = 0;
+ 
+ 	xs_encode_tcp_record_marker(&req->rq_snd_buf);
+ 
+@@ -681,9 +690,10 @@ static int xs_tcp_send_request(struct rpc_task *task)
+ 			return 0;
+ 		}
+ 
++		if (status != 0)
++			continue;
+ 		status = -EAGAIN;
+-		if (retry++ > XS_SENDMSG_RETRY)
+-			break;
++		break;
+ 	}
+ 
+ 	switch (status) {
+@@ -695,12 +705,13 @@ static int xs_tcp_send_request(struct rpc_task *task)
+ 	case -ENOTCONN:
+ 	case -EPIPE:
+ 		status = -ENOTCONN;
++		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+ 		break;
+ 	default:
+ 		dprintk("RPC:       sendmsg returned unrecognized error %d\n",
+ 			-status);
++		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+ 		xs_tcp_shutdown(xprt);
+-		break;
+ 	}
+ 
+ 	return status;
+@@ -1073,6 +1084,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
+ {
+ 	struct rpc_xprt *xprt;
+ 	read_descriptor_t rd_desc;
++	int read;
+ 
+ 	dprintk("RPC:       xs_tcp_data_ready...\n");
+ 
+@@ -1084,8 +1096,10 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
+ 
+ 	/* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
+ 	rd_desc.arg.data = xprt;
+-	rd_desc.count = 65536;
+-	tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
++	do {
++		rd_desc.count = 65536;
++		read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
++	} while (read > 0);
+ out:
+ 	read_unlock(&sk->sk_callback_lock);
+ }
+@@ -1128,6 +1142,7 @@ static void xs_tcp_state_change(struct sock *sk)
+ 		break;
+ 	case TCP_FIN_WAIT1:
+ 		/* The client initiated a shutdown of the socket */
++		xprt->connect_cookie++;
+ 		xprt->reestablish_timeout = 0;
+ 		set_bit(XPRT_CLOSING, &xprt->state);
+ 		smp_mb__before_clear_bit();
+@@ -1140,6 +1155,7 @@ static void xs_tcp_state_change(struct sock *sk)
+ 		set_bit(XPRT_CLOSING, &xprt->state);
+ 		xprt_force_disconnect(xprt);
+ 	case TCP_SYN_SENT:
++		xprt->connect_cookie++;
+ 	case TCP_CLOSING:
+ 		/*
+ 		 * If the server closed down the connection, make sure that
+@@ -1186,9 +1202,11 @@ static void xs_udp_write_space(struct sock *sk)
+ 
+ 		if (unlikely(!(sock = sk->sk_socket)))
+ 			goto out;
++		clear_bit(SOCK_NOSPACE, &sock->flags);
++
+ 		if (unlikely(!(xprt = xprt_from_sock(sk))))
+ 			goto out;
+-		if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
++		if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0)
+ 			goto out;
+ 
+ 		xprt_write_space(xprt);
+@@ -1219,9 +1237,11 @@ static void xs_tcp_write_space(struct sock *sk)
+ 
+ 		if (unlikely(!(sock = sk->sk_socket)))
+ 			goto out;
++		clear_bit(SOCK_NOSPACE, &sock->flags);
++
+ 		if (unlikely(!(xprt = xprt_from_sock(sk))))
+ 			goto out;
+-		if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
++		if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0)
+ 			goto out;
+ 
+ 		xprt_write_space(xprt);
+@@ -1359,7 +1379,7 @@ static int xs_bind4(struct sock_xprt *transport, struct socket *sock)
+ 			nloop++;
+ 	} while (err == -EADDRINUSE && nloop != 2);
+ 	dprintk("RPC:       %s "NIPQUAD_FMT":%u: %s (%d)\n",
+-			__FUNCTION__, NIPQUAD(myaddr.sin_addr),
++			__func__, NIPQUAD(myaddr.sin_addr),
+ 			port, err ? "failed" : "ok", err);
+ 	return err;
+ }
+diff --git a/net/tipc/core.c b/net/tipc/core.c
+index d2d7d32..740aac5 100644
+--- a/net/tipc/core.c
++++ b/net/tipc/core.c
+@@ -48,16 +48,8 @@
+ #include "subscr.h"
+ #include "config.h"
+ 
+-int  tipc_eth_media_start(void);
+-void tipc_eth_media_stop(void);
+-int  tipc_handler_start(void);
+-void tipc_handler_stop(void);
+-int  tipc_socket_init(void);
+-void tipc_socket_stop(void);
+-int  tipc_netlink_start(void);
+-void tipc_netlink_stop(void);
+ 
+-#define TIPC_MOD_VER "1.6.2"
++#define TIPC_MOD_VER "1.6.3"
+ 
+ #ifndef CONFIG_TIPC_ZONES
+ #define CONFIG_TIPC_ZONES 3
+@@ -277,7 +269,6 @@ EXPORT_SYMBOL(tipc_register_media);
+ /* TIPC API for external APIs (see tipc_port.h) */
+ 
+ EXPORT_SYMBOL(tipc_createport_raw);
+-EXPORT_SYMBOL(tipc_set_msg_option);
+ EXPORT_SYMBOL(tipc_reject_msg);
+ EXPORT_SYMBOL(tipc_send_buf_fast);
+ EXPORT_SYMBOL(tipc_acknowledge);
+diff --git a/net/tipc/core.h b/net/tipc/core.h
+index feabca5..325404f 100644
+--- a/net/tipc/core.h
++++ b/net/tipc/core.h
+@@ -180,6 +180,12 @@ extern int  tipc_core_start(void);
+ extern void tipc_core_stop(void);
+ extern int  tipc_core_start_net(void);
+ extern void tipc_core_stop_net(void);
++extern int  tipc_handler_start(void);
++extern void tipc_handler_stop(void);
++extern int  tipc_netlink_start(void);
++extern void tipc_netlink_stop(void);
++extern int  tipc_socket_init(void);
++extern void tipc_socket_stop(void);
+ 
+ static inline int delimit(int val, int min, int max)
+ {
+@@ -310,7 +316,7 @@ static inline struct sk_buff *buf_acquire(u32 size)
+ 	struct sk_buff *skb;
+ 	unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
+ 
+-	skb = alloc_skb(buf_size, GFP_ATOMIC);
++	skb = alloc_skb_fclone(buf_size, GFP_ATOMIC);
+ 	if (skb) {
+ 		skb_reserve(skb, BUF_HEADROOM);
+ 		skb_put(skb, size);
+@@ -328,8 +334,19 @@ static inline struct sk_buff *buf_acquire(u32 size)
+ 
+ static inline void buf_discard(struct sk_buff *skb)
+ {
+-	if (likely(skb != NULL))
+-		kfree_skb(skb);
++	kfree_skb(skb);
++}
++
++/**
++ * buf_linearize - convert a TIPC message buffer into a single contiguous piece
++ * @skb: message buffer
++ *
++ * Returns 0 on success.
++ */
++
++static inline int buf_linearize(struct sk_buff *skb)
++{
++	return skb_linearize(skb);
+ }
+ 
+ #endif
+diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
+index 3bbef2a..9cd35ee 100644
+--- a/net/tipc/eth_media.c
++++ b/net/tipc/eth_media.c
+@@ -101,7 +101,7 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
+ 	struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
+ 	u32 size;
+ 
+-	if (dev->nd_net != &init_net) {
++	if (dev_net(dev) != &init_net) {
+ 		kfree_skb(buf);
+ 		return 0;
+ 	}
+@@ -198,7 +198,7 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
+ 	struct eth_bearer *eb_ptr = &eth_bearers[0];
+ 	struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	while ((eb_ptr->dev != dev)) {
+diff --git a/net/tipc/link.c b/net/tipc/link.c
+index cefa998..2a26a16 100644
+--- a/net/tipc/link.c
++++ b/net/tipc/link.c
+@@ -1785,6 +1785,56 @@ static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr,
+ 	return buf;
+ }
+ 
++/**
++ * link_recv_buf_validate - validate basic format of received message
++ *
++ * This routine ensures a TIPC message has an acceptable header, and at least
++ * as much data as the header indicates it should.  The routine also ensures
++ * that the entire message header is stored in the main fragment of the message
++ * buffer, to simplify future access to message header fields.
++ *
++ * Note: Having extra info present in the message header or data areas is OK.
++ * TIPC will ignore the excess, under the assumption that it is optional info
++ * introduced by a later release of the protocol.
++ */
++
++static int link_recv_buf_validate(struct sk_buff *buf)
++{
++	static u32 min_data_hdr_size[8] = {
++		SHORT_H_SIZE, MCAST_H_SIZE, LONG_H_SIZE, DIR_MSG_H_SIZE,
++		MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE
++		};
++
++	struct tipc_msg *msg;
++	u32 tipc_hdr[2];
++	u32 size;
++	u32 hdr_size;
++	u32 min_hdr_size;
++
++	if (unlikely(buf->len < MIN_H_SIZE))
++		return 0;
++
++	msg = skb_header_pointer(buf, 0, sizeof(tipc_hdr), tipc_hdr);
++	if (msg == NULL)
++		return 0;
++
++	if (unlikely(msg_version(msg) != TIPC_VERSION))
++		return 0;
++
++	size = msg_size(msg);
++	hdr_size = msg_hdr_sz(msg);
++	min_hdr_size = msg_isdata(msg) ?
++		min_data_hdr_size[msg_type(msg)] : INT_H_SIZE;
++
++	if (unlikely((hdr_size < min_hdr_size) ||
++		     (size < hdr_size) ||
++		     (buf->len < size) ||
++		     (size - hdr_size > TIPC_MAX_USER_MSG_SIZE)))
++		return 0;
++
++	return pskb_may_pull(buf, hdr_size);
++}
++
+ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ {
+ 	read_lock_bh(&tipc_net_lock);
+@@ -1794,9 +1844,9 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ 		struct link *l_ptr;
+ 		struct sk_buff *crs;
+ 		struct sk_buff *buf = head;
+-		struct tipc_msg *msg = buf_msg(buf);
+-		u32 seq_no = msg_seqno(msg);
+-		u32 ackd = msg_ack(msg);
++		struct tipc_msg *msg;
++		u32 seq_no;
++		u32 ackd;
+ 		u32 released = 0;
+ 		int type;
+ 
+@@ -1804,12 +1854,21 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ 		TIPC_SKB_CB(buf)->handle = b_ptr;
+ 
+ 		head = head->next;
+-		if (unlikely(msg_version(msg) != TIPC_VERSION))
++
++		/* Ensure message is well-formed */
++
++		if (unlikely(!link_recv_buf_validate(buf)))
+ 			goto cont;
+-#if 0
+-		if (msg_user(msg) != LINK_PROTOCOL)
+-#endif
+-			msg_dbg(msg,"<REC<");
++
++		/* Ensure message data is a single contiguous unit */
++
++		if (unlikely(buf_linearize(buf))) {
++			goto cont;
++		}
++
++		/* Handle arrival of a non-unicast link message */
++
++		msg = buf_msg(buf);
+ 
+ 		if (unlikely(msg_non_seq(msg))) {
+ 			link_recv_non_seq(buf);
+@@ -1820,19 +1879,26 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ 			     (msg_destnode(msg) != tipc_own_addr)))
+ 			goto cont;
+ 
++		/* Locate unicast link endpoint that should handle message */
++
+ 		n_ptr = tipc_node_find(msg_prevnode(msg));
+ 		if (unlikely(!n_ptr))
+ 			goto cont;
+-
+ 		tipc_node_lock(n_ptr);
++
+ 		l_ptr = n_ptr->links[b_ptr->identity];
+ 		if (unlikely(!l_ptr)) {
+ 			tipc_node_unlock(n_ptr);
+ 			goto cont;
+ 		}
+-		/*
+-		 * Release acked messages
+-		 */
++
++		/* Validate message sequence number info */
++
++		seq_no = msg_seqno(msg);
++		ackd = msg_ack(msg);
++
++		/* Release acked messages */
++
+ 		if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) {
+ 			if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported)
+ 				tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
+@@ -1851,6 +1917,9 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ 			l_ptr->first_out = crs;
+ 			l_ptr->out_queue_size -= released;
+ 		}
++
++		/* Try sending any messages link endpoint has pending */
++
+ 		if (unlikely(l_ptr->next_out))
+ 			tipc_link_push_queue(l_ptr);
+ 		if (unlikely(!list_empty(&l_ptr->waiting_ports)))
+@@ -1860,6 +1929,8 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ 			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
+ 		}
+ 
++		/* Now (finally!) process the incoming message */
++
+ protocol_check:
+ 		if (likely(link_working_working(l_ptr))) {
+ 			if (likely(seq_no == mod(l_ptr->next_in_no))) {
+@@ -2832,15 +2903,15 @@ static void link_set_supervision_props(struct link *l_ptr, u32 tolerance)
+ void tipc_link_set_queue_limits(struct link *l_ptr, u32 window)
+ {
+ 	/* Data messages from this node, inclusive FIRST_FRAGM */
+-	l_ptr->queue_limit[DATA_LOW] = window;
+-	l_ptr->queue_limit[DATA_MEDIUM] = (window / 3) * 4;
+-	l_ptr->queue_limit[DATA_HIGH] = (window / 3) * 5;
+-	l_ptr->queue_limit[DATA_CRITICAL] = (window / 3) * 6;
++	l_ptr->queue_limit[TIPC_LOW_IMPORTANCE] = window;
++	l_ptr->queue_limit[TIPC_MEDIUM_IMPORTANCE] = (window / 3) * 4;
++	l_ptr->queue_limit[TIPC_HIGH_IMPORTANCE] = (window / 3) * 5;
++	l_ptr->queue_limit[TIPC_CRITICAL_IMPORTANCE] = (window / 3) * 6;
+ 	/* Transiting data messages,inclusive FIRST_FRAGM */
+-	l_ptr->queue_limit[DATA_LOW + 4] = 300;
+-	l_ptr->queue_limit[DATA_MEDIUM + 4] = 600;
+-	l_ptr->queue_limit[DATA_HIGH + 4] = 900;
+-	l_ptr->queue_limit[DATA_CRITICAL + 4] = 1200;
++	l_ptr->queue_limit[TIPC_LOW_IMPORTANCE + 4] = 300;
++	l_ptr->queue_limit[TIPC_MEDIUM_IMPORTANCE + 4] = 600;
++	l_ptr->queue_limit[TIPC_HIGH_IMPORTANCE + 4] = 900;
++	l_ptr->queue_limit[TIPC_CRITICAL_IMPORTANCE + 4] = 1200;
+ 	l_ptr->queue_limit[CONN_MANAGER] = 1200;
+ 	l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200;
+ 	l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500;
+diff --git a/net/tipc/msg.c b/net/tipc/msg.c
+index 7824854..696a863 100644
+--- a/net/tipc/msg.c
++++ b/net/tipc/msg.c
+@@ -73,10 +73,10 @@ void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str
+ 		tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg),
+ 			    msg_fragm_no(msg));
+ 		break;
+-	case DATA_LOW:
+-	case DATA_MEDIUM:
+-	case DATA_HIGH:
+-	case DATA_CRITICAL:
++	case TIPC_LOW_IMPORTANCE:
++	case TIPC_MEDIUM_IMPORTANCE:
++	case TIPC_HIGH_IMPORTANCE:
++	case TIPC_CRITICAL_IMPORTANCE:
+ 		tipc_printf(buf, "DAT%u:", msg_user(msg));
+ 		if (msg_short(msg)) {
+ 			tipc_printf(buf, "CON:");
+@@ -229,10 +229,10 @@ void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str
+ 	switch (usr) {
+ 	case CONN_MANAGER:
+ 	case NAME_DISTRIBUTOR:
+-	case DATA_LOW:
+-	case DATA_MEDIUM:
+-	case DATA_HIGH:
+-	case DATA_CRITICAL:
++	case TIPC_LOW_IMPORTANCE:
++	case TIPC_MEDIUM_IMPORTANCE:
++	case TIPC_HIGH_IMPORTANCE:
++	case TIPC_CRITICAL_IMPORTANCE:
+ 		if (msg_short(msg))
+ 			break;	/* No error */
+ 		switch (msg_errcode(msg)) {
+diff --git a/net/tipc/msg.h b/net/tipc/msg.h
+index e9ef6df..6ad070d 100644
+--- a/net/tipc/msg.h
++++ b/net/tipc/msg.h
+@@ -40,18 +40,16 @@
+ #include "core.h"
+ 
+ #define TIPC_VERSION              2
+-#define DATA_LOW                  TIPC_LOW_IMPORTANCE
+-#define DATA_MEDIUM               TIPC_MEDIUM_IMPORTANCE
+-#define DATA_HIGH                 TIPC_HIGH_IMPORTANCE
+-#define DATA_CRITICAL             TIPC_CRITICAL_IMPORTANCE
+-#define SHORT_H_SIZE              24	/* Connected,in cluster */
++
++#define SHORT_H_SIZE              24	/* Connected, in-cluster messages */
+ #define DIR_MSG_H_SIZE            32	/* Directly addressed messages */
+-#define CONN_MSG_H_SIZE           36	/* Routed connected msgs*/
+-#define LONG_H_SIZE               40	/* Named Messages */
++#define LONG_H_SIZE               40	/* Named messages */
+ #define MCAST_H_SIZE              44	/* Multicast messages */
+-#define MAX_H_SIZE                60	/* Inclusive full options */
++#define INT_H_SIZE                40	/* Internal messages */
++#define MIN_H_SIZE                24	/* Smallest legal TIPC header size */
++#define MAX_H_SIZE                60	/* Largest possible TIPC header size */
++
+ #define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE)
+-#define LINK_CONFIG               13
+ 
+ 
+ /*
+@@ -72,8 +70,10 @@ static inline void msg_set_bits(struct tipc_msg *m, u32 w,
+ 				u32 pos, u32 mask, u32 val)
+ {
+ 	val = (val & mask) << pos;
+-	m->hdr[w] &= ~htonl(mask << pos);
+-	m->hdr[w] |= htonl(val);
++	val = htonl(val);
++	mask = htonl(mask << pos);
++	m->hdr[w] &= ~mask;
++	m->hdr[w] |= val;
+ }
+ 
+ /*
+@@ -87,7 +87,7 @@ static inline u32 msg_version(struct tipc_msg *m)
+ 
+ static inline void msg_set_version(struct tipc_msg *m)
+ {
+-	msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION);
++	msg_set_bits(m, 0, 29, 7, TIPC_VERSION);
+ }
+ 
+ static inline u32 msg_user(struct tipc_msg *m)
+@@ -97,7 +97,7 @@ static inline u32 msg_user(struct tipc_msg *m)
+ 
+ static inline u32 msg_isdata(struct tipc_msg *m)
+ {
+-	return (msg_user(m) <= DATA_CRITICAL);
++	return (msg_user(m) <= TIPC_CRITICAL_IMPORTANCE);
+ }
+ 
+ static inline void msg_set_user(struct tipc_msg *m, u32 n)
+@@ -190,18 +190,6 @@ static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
+ 	msg_set_bits(m, 1, 19, 0x3, n);
+ }
+ 
+-static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz)
+-{
+-	u32 hsz = msg_hdr_sz(m);
+-	char *to = (char *)&m->hdr[hsz/4];
+-
+-	if ((hsz < DIR_MSG_H_SIZE) || ((hsz + sz) > MAX_H_SIZE))
+-		return;
+-	msg_set_bits(m, 1, 16, 0x7, (hsz - 28)/4);
+-	msg_set_hdr_sz(m, hsz + sz);
+-	memcpy(to, opt, sz);
+-}
+-
+ static inline u32 msg_bcast_ack(struct tipc_msg *m)
+ {
+ 	return msg_bits(m, 1, 0, 0xffff);
+@@ -330,17 +318,6 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
+ 	return (struct tipc_msg *)msg_data(m);
+ }
+ 
+-static inline void msg_expand(struct tipc_msg *m, u32 destnode)
+-{
+-	if (!msg_short(m))
+-		return;
+-	msg_set_hdr_sz(m, LONG_H_SIZE);
+-	msg_set_orignode(m, msg_prevnode(m));
+-	msg_set_destnode(m, destnode);
+-	memset(&m->hdr[8], 0, 12);
+-}
+-
+-
+ 
+ /*
+ 		TIPC internal message header format, version 2
+@@ -388,7 +365,6 @@ static inline void msg_expand(struct tipc_msg *m, u32 destnode)
+ #define  NAME_DISTRIBUTOR     11
+ #define  MSG_FRAGMENTER       12
+ #define  LINK_CONFIG          13
+-#define  INT_H_SIZE           40
+ #define  DSC_H_SIZE           40
+ 
+ /*
+diff --git a/net/tipc/port.c b/net/tipc/port.c
+index f508614..2f58064 100644
+--- a/net/tipc/port.c
++++ b/net/tipc/port.c
+@@ -242,7 +242,8 @@ u32 tipc_createport_raw(void *usr_handle,
+ 	p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;
+ 	p_ptr->publ.ref = ref;
+ 	msg = &p_ptr->publ.phdr;
+-	msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0);
++	msg_init(msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE,
++		 0);
+ 	msg_set_orignode(msg, tipc_own_addr);
+ 	msg_set_prevnode(msg, tipc_own_addr);
+ 	msg_set_origport(msg, ref);
+@@ -413,13 +414,6 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
+ 	return buf;
+ }
+ 
+-int tipc_set_msg_option(struct tipc_port *tp_ptr, const char *opt, const u32 sz)
+-{
+-	msg_expand(&tp_ptr->phdr, msg_destnode(&tp_ptr->phdr));
+-	msg_set_options(&tp_ptr->phdr, opt, sz);
+-	return TIPC_OK;
+-}
+-
+ int tipc_reject_msg(struct sk_buff *buf, u32 err)
+ {
+ 	struct tipc_msg *msg = buf_msg(buf);
+@@ -632,7 +626,7 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf)
+ 					     msg_orignode(msg),
+ 					     msg_destport(msg),
+ 					     tipc_own_addr,
+-					     DATA_HIGH,
++					     TIPC_HIGH_IMPORTANCE,
+ 					     TIPC_CONN_MSG,
+ 					     err,
+ 					     0,
+@@ -1246,6 +1240,28 @@ exit:
+ 	return res;
+ }
+ 
++/**
++ * tipc_disconnect_port - disconnect port from peer
++ *
++ * Port must be locked.
++ */
++
++int tipc_disconnect_port(struct tipc_port *tp_ptr)
++{
++	int res;
++
++	if (tp_ptr->connected) {
++		tp_ptr->connected = 0;
++		/* let timer expire on it's own to avoid deadlock! */
++		tipc_nodesub_unsubscribe(
++			&((struct port *)tp_ptr)->subscription);
++		res = TIPC_OK;
++	} else {
++		res = -ENOTCONN;
++	}
++	return res;
++}
++
+ /*
+  * tipc_disconnect(): Disconnect port form peer.
+  *                    This is a node local operation.
+@@ -1254,17 +1270,12 @@ exit:
+ int tipc_disconnect(u32 ref)
+ {
+ 	struct port *p_ptr;
+-	int res = -ENOTCONN;
++	int res;
+ 
+ 	p_ptr = tipc_port_lock(ref);
+ 	if (!p_ptr)
+ 		return -EINVAL;
+-	if (p_ptr->publ.connected) {
+-		p_ptr->publ.connected = 0;
+-		/* let timer expire on it's own to avoid deadlock! */
+-		tipc_nodesub_unsubscribe(&p_ptr->subscription);
+-		res = TIPC_OK;
+-	}
++	res = tipc_disconnect_port((struct tipc_port *)p_ptr);
+ 	tipc_port_unlock(p_ptr);
+ 	return res;
+ }
+diff --git a/net/tipc/ref.c b/net/tipc/ref.c
+index c38744c..89cbab2 100644
+--- a/net/tipc/ref.c
++++ b/net/tipc/ref.c
+@@ -2,7 +2,7 @@
+  * net/tipc/ref.c: TIPC object registry code
+  *
+  * Copyright (c) 1991-2006, Ericsson AB
+- * Copyright (c) 2004-2005, Wind River Systems
++ * Copyright (c) 2004-2007, Wind River Systems
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -36,32 +36,60 @@
+ 
+ #include "core.h"
+ #include "ref.h"
+-#include "port.h"
+-#include "subscr.h"
+-#include "name_distr.h"
+-#include "name_table.h"
+-#include "config.h"
+-#include "discover.h"
+-#include "bearer.h"
+-#include "node.h"
+-#include "bcast.h"
++
++/**
++ * struct reference - TIPC object reference entry
++ * @object: pointer to object associated with reference entry
++ * @lock: spinlock controlling access to object
++ * @ref: reference value for object (combines instance & array index info)
++ */
++
++struct reference {
++	void *object;
++	spinlock_t lock;
++	u32 ref;
++};
++
++/**
++ * struct tipc_ref_table - table of TIPC object reference entries
++ * @entries: pointer to array of reference entries
++ * @capacity: array index of first unusable entry
++ * @init_point: array index of first uninitialized entry
++ * @first_free: array index of first unused object reference entry
++ * @last_free: array index of last unused object reference entry
++ * @index_mask: bitmask for array index portion of reference values
++ * @start_mask: initial value for instance value portion of reference values
++ */
++
++struct ref_table {
++	struct reference *entries;
++	u32 capacity;
++	u32 init_point;
++	u32 first_free;
++	u32 last_free;
++	u32 index_mask;
++	u32 start_mask;
++};
+ 
+ /*
+  * Object reference table consists of 2**N entries.
+  *
+- * A used entry has object ptr != 0, reference == XXXX|own index
+- *				     (XXXX changes each time entry is acquired)
+- * A free entry has object ptr == 0, reference == YYYY|next free index
+- *				     (YYYY is one more than last used XXXX)
++ * State	Object ptr	Reference
++ * -----        ----------      ---------
++ * In use        non-NULL       XXXX|own index
++ *				(XXXX changes each time entry is acquired)
++ * Free            NULL         YYYY|next free index
++ *				(YYYY is one more than last used XXXX)
++ * Uninitialized   NULL         0
+  *
+- * Free list is initially chained from entry (2**N)-1 to entry 1.
+- * Entry 0 is not used to allow index 0 to indicate the end of the free list.
++ * Entry 0 is not used; this allows index 0 to denote the end of the free list.
+  *
+- * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0
+- * because entry 0's reference field has the form XXXX|1--1.
++ * Note that a reference value of 0 does not necessarily indicate that an
++ * entry is uninitialized, since the last entry in the free list could also
++ * have a reference value of 0 (although this is unlikely).
+  */
+ 
+-struct ref_table tipc_ref_table = { NULL };
++static struct ref_table tipc_ref_table = { NULL };
+ 
+ static DEFINE_RWLOCK(ref_table_lock);
+ 
+@@ -72,29 +100,29 @@ static DEFINE_RWLOCK(ref_table_lock);
+ int tipc_ref_table_init(u32 requested_size, u32 start)
+ {
+ 	struct reference *table;
+-	u32 sz = 1 << 4;
+-	u32 index_mask;
+-	int i;
++	u32 actual_size;
+ 
+-	while (sz < requested_size) {
+-		sz <<= 1;
+-	}
+-	table = vmalloc(sz * sizeof(*table));
++	/* account for unused entry, then round up size to a power of 2 */
++
++	requested_size++;
++	for (actual_size = 16; actual_size < requested_size; actual_size <<= 1)
++		/* do nothing */ ;
++
++	/* allocate table & mark all entries as uninitialized */
++
++	table = __vmalloc(actual_size * sizeof(struct reference),
++			  GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+ 	if (table == NULL)
+ 		return -ENOMEM;
+ 
+-	write_lock_bh(&ref_table_lock);
+-	index_mask = sz - 1;
+-	for (i = sz - 1; i >= 0; i--) {
+-		table[i].object = NULL;
+-		spin_lock_init(&table[i].lock);
+-		table[i].data.next_plus_upper = (start & ~index_mask) + i - 1;
+-	}
+ 	tipc_ref_table.entries = table;
+-	tipc_ref_table.index_mask = index_mask;
+-	tipc_ref_table.first_free = sz - 1;
+-	tipc_ref_table.last_free = 1;
+-	write_unlock_bh(&ref_table_lock);
++	tipc_ref_table.capacity = requested_size;
++	tipc_ref_table.init_point = 1;
++	tipc_ref_table.first_free = 0;
++	tipc_ref_table.last_free = 0;
++	tipc_ref_table.index_mask = actual_size - 1;
++	tipc_ref_table.start_mask = start & ~tipc_ref_table.index_mask;
++
+ 	return TIPC_OK;
+ }
+ 
+@@ -125,7 +153,7 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
+ 	u32 index;
+ 	u32 index_mask;
+ 	u32 next_plus_upper;
+-	u32 reference = 0;
++	u32 ref;
+ 
+ 	if (!object) {
+ 		err("Attempt to acquire reference to non-existent object\n");
+@@ -136,6 +164,8 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
+ 		return 0;
+ 	}
+ 
++	/* take a free entry, if available; otherwise initialize a new entry */
++
+ 	write_lock_bh(&ref_table_lock);
+ 	if (tipc_ref_table.first_free) {
+ 		index = tipc_ref_table.first_free;
+@@ -143,17 +173,29 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
+ 		index_mask = tipc_ref_table.index_mask;
+ 		/* take lock in case a previous user of entry still holds it */
+ 		spin_lock_bh(&entry->lock);
+-		next_plus_upper = entry->data.next_plus_upper;
++		next_plus_upper = entry->ref;
+ 		tipc_ref_table.first_free = next_plus_upper & index_mask;
+-		reference = (next_plus_upper & ~index_mask) + index;
+-		entry->data.reference = reference;
++		ref = (next_plus_upper & ~index_mask) + index;
++		entry->ref = ref;
+ 		entry->object = object;
+-		if (lock != NULL)
+-			*lock = &entry->lock;
+ 		spin_unlock_bh(&entry->lock);
++		*lock = &entry->lock;
++	}
++	else if (tipc_ref_table.init_point < tipc_ref_table.capacity) {
++		index = tipc_ref_table.init_point++;
++		entry = &(tipc_ref_table.entries[index]);
++		spin_lock_init(&entry->lock);
++		ref = tipc_ref_table.start_mask + index;
++		entry->ref = ref;
++		entry->object = object;
++		*lock = &entry->lock;
++	}
++	else {
++		ref = 0;
+ 	}
+ 	write_unlock_bh(&ref_table_lock);
+-	return reference;
++
++	return ref;
+ }
+ 
+ /**
+@@ -169,42 +211,99 @@ void tipc_ref_discard(u32 ref)
+ 	u32 index;
+ 	u32 index_mask;
+ 
+-	if (!ref) {
+-		err("Attempt to discard reference 0\n");
+-		return;
+-	}
+ 	if (!tipc_ref_table.entries) {
+ 		err("Reference table not found during discard attempt\n");
+ 		return;
+ 	}
+ 
+-	write_lock_bh(&ref_table_lock);
+ 	index_mask = tipc_ref_table.index_mask;
+ 	index = ref & index_mask;
+ 	entry = &(tipc_ref_table.entries[index]);
+ 
++	write_lock_bh(&ref_table_lock);
++
+ 	if (!entry->object) {
+ 		err("Attempt to discard reference to non-existent object\n");
+ 		goto exit;
+ 	}
+-	if (entry->data.reference != ref) {
++	if (entry->ref != ref) {
+ 		err("Attempt to discard non-existent reference\n");
+ 		goto exit;
+ 	}
+ 
+-	/* mark entry as unused */
++	/*
++	 * mark entry as unused; increment instance part of entry's reference
++	 * to invalidate any subsequent references
++	 */
++
+ 	entry->object = NULL;
++	entry->ref = (ref & ~index_mask) + (index_mask + 1);
++
++	/* append entry to free entry list */
++
+ 	if (tipc_ref_table.first_free == 0)
+ 		tipc_ref_table.first_free = index;
+ 	else
+-		/* next_plus_upper is always XXXX|0--0 for last free entry */
+-		tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper
+-			|= index;
++		tipc_ref_table.entries[tipc_ref_table.last_free].ref |= index;
+ 	tipc_ref_table.last_free = index;
+ 
+-	/* increment upper bits of entry to invalidate subsequent references */
+-	entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
+ exit:
+ 	write_unlock_bh(&ref_table_lock);
+ }
+ 
++/**
++ * tipc_ref_lock - lock referenced object and return pointer to it
++ */
++
++void *tipc_ref_lock(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 != 0)) {
++			spin_lock_bh(&entry->lock);
++			if (likely((entry->ref == ref) && (entry->object)))
++				return entry->object;
++			spin_unlock_bh(&entry->lock);
++		}
++	}
++	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)
++ */
++
++void *tipc_ref_deref(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))
++			return entry->object;
++	}
++	return NULL;
++}
++
+diff --git a/net/tipc/ref.h b/net/tipc/ref.h
+index 38f3a7f..7e3798e 100644
+--- a/net/tipc/ref.h
++++ b/net/tipc/ref.h
+@@ -2,7 +2,7 @@
+  * net/tipc/ref.h: Include file for TIPC object registry code
+  *
+  * Copyright (c) 1991-2006, Ericsson AB
+- * Copyright (c) 2005, Wind River Systems
++ * Copyright (c) 2005-2006, Wind River Systems
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -37,95 +37,14 @@
+ #ifndef _TIPC_REF_H
+ #define _TIPC_REF_H
+ 
+-/**
+- * struct reference - TIPC object reference entry
+- * @object: pointer to object associated with reference entry
+- * @lock: spinlock controlling access to object
+- * @data: reference value associated with object (or link to next unused entry)
+- */
+-
+-struct reference {
+-	void *object;
+-	spinlock_t lock;
+-	union {
+-		u32 next_plus_upper;
+-		u32 reference;
+-	} data;
+-};
+-
+-/**
+- * struct tipc_ref_table - table of TIPC object reference entries
+- * @entries: pointer to array of reference entries
+- * @index_mask: bitmask for array index portion of reference values
+- * @first_free: array index of first unused object reference entry
+- * @last_free: array index of last unused object reference entry
+- */
+-
+-struct ref_table {
+-	struct reference *entries;
+-	u32 index_mask;
+-	u32 first_free;
+-	u32 last_free;
+-};
+-
+-extern struct ref_table tipc_ref_table;
+-
+ int tipc_ref_table_init(u32 requested_size, u32 start);
+ void tipc_ref_table_stop(void);
+ 
+ u32 tipc_ref_acquire(void *object, spinlock_t **lock);
+ void tipc_ref_discard(u32 ref);
+ 
+-
+-/**
+- * tipc_ref_lock - lock referenced object and return pointer to it
+- */
+-
+-static inline void *tipc_ref_lock(u32 ref)
+-{
+-	if (likely(tipc_ref_table.entries)) {
+-		struct reference *r =
+-			&tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+-
+-		spin_lock_bh(&r->lock);
+-		if (likely(r->data.reference == ref))
+-			return r->object;
+-		spin_unlock_bh(&r->lock);
+-	}
+-	return NULL;
+-}
+-
+-/**
+- * tipc_ref_unlock - unlock referenced object
+- */
+-
+-static inline void tipc_ref_unlock(u32 ref)
+-{
+-	if (likely(tipc_ref_table.entries)) {
+-		struct reference *r =
+-			&tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+-
+-		if (likely(r->data.reference == ref))
+-			spin_unlock_bh(&r->lock);
+-		else
+-			err("tipc_ref_unlock() invoked using obsolete reference\n");
+-	}
+-}
+-
+-/**
+- * tipc_ref_deref - return pointer referenced object (without locking it)
+- */
+-
+-static inline void *tipc_ref_deref(u32 ref)
+-{
+-	if (likely(tipc_ref_table.entries)) {
+-		struct reference *r =
+-			&tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+-
+-		if (likely(r->data.reference == ref))
+-			return r->object;
+-	}
+-	return NULL;
+-}
++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 2290903..230f9ca 100644
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -43,7 +43,6 @@
+ #include <linux/slab.h>
+ #include <linux/poll.h>
+ #include <linux/fcntl.h>
+-#include <asm/semaphore.h>
+ #include <asm/string.h>
+ #include <asm/atomic.h>
+ #include <net/sock.h>
+@@ -58,16 +57,18 @@
+ #define SS_LISTENING	-1	/* socket is listening */
+ #define SS_READY	-2	/* socket is connectionless */
+ 
+-#define OVERLOAD_LIMIT_BASE    5000
++#define OVERLOAD_LIMIT_BASE	5000
++#define CONN_TIMEOUT_DEFAULT	8000	/* default connect timeout = 8s */
+ 
+ struct tipc_sock {
+ 	struct sock sk;
+ 	struct tipc_port *p;
+-	struct semaphore sem;
+ };
+ 
+-#define tipc_sk(sk) ((struct tipc_sock*)sk)
++#define tipc_sk(sk) ((struct tipc_sock *)(sk))
++#define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))
+ 
++static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
+ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
+ static void wakeupdispatch(struct tipc_port *tport);
+ 
+@@ -81,93 +82,115 @@ static int sockets_enabled = 0;
+ 
+ static atomic_t tipc_queue_size = ATOMIC_INIT(0);
+ 
+-
+ /*
+- * sock_lock(): Lock a port/socket pair. lock_sock() can
+- * not be used here, since the same lock must protect ports
+- * with non-socket interfaces.
+- * See net.c for description of locking policy.
++ * Revised TIPC socket locking policy:
++ *
++ * Most socket operations take the standard socket lock when they start
++ * and hold it until they finish (or until they need to sleep).  Acquiring
++ * this lock grants the owner exclusive access to the fields of the socket
++ * data structures, with the exception of the backlog queue.  A few socket
++ * operations can be done without taking the socket lock because they only
++ * read socket information that never changes during the life of the socket.
++ *
++ * Socket operations may acquire the lock for the associated TIPC port if they
++ * need to perform an operation on the port.  If any routine needs to acquire
++ * both the socket lock and the port lock it must take the socket lock first
++ * to avoid the risk of deadlock.
++ *
++ * The dispatcher handling incoming messages cannot grab the socket lock in
++ * the standard fashion, since invoked it runs at the BH level and cannot block.
++ * Instead, it checks to see if the socket lock is currently owned by someone,
++ * and either handles the message itself or adds it to the socket's backlog
++ * queue; in the latter case the queued message is processed once the process
++ * owning the socket lock releases it.
++ *
++ * NOTE: Releasing the socket lock while an operation is sleeping overcomes
++ * the problem of a blocked socket operation preventing any other operations
++ * from occurring.  However, applications must be careful if they have
++ * multiple threads trying to send (or receive) on the same socket, as these
++ * operations might interfere with each other.  For example, doing a connect
++ * and a receive at the same time might allow the receive to consume the
++ * ACK message meant for the connect.  While additional work could be done
++ * to try and overcome this, it doesn't seem to be worthwhile at the present.
++ *
++ * NOTE: Releasing the socket lock while an operation is sleeping also ensures
++ * that another operation that must be performed in a non-blocking manner is
++ * not delayed for very long because the lock has already been taken.
++ *
++ * NOTE: This code assumes that certain fields of a port/socket pair are
++ * constant over its lifetime; such fields can be examined without taking
++ * the socket lock and/or port lock, and do not need to be re-read even
++ * after resuming processing after waiting.  These fields include:
++ *   - socket type
++ *   - pointer to socket sk structure (aka tipc_sock structure)
++ *   - pointer to port structure
++ *   - port reference
+  */
+-static void sock_lock(struct tipc_sock* tsock)
+-{
+-	spin_lock_bh(tsock->p->lock);
+-}
+ 
+-/*
+- * sock_unlock(): Unlock a port/socket pair
++/**
++ * advance_rx_queue - discard first buffer in socket receive queue
++ *
++ * Caller must hold socket lock
+  */
+-static void sock_unlock(struct tipc_sock* tsock)
++
++static void advance_rx_queue(struct sock *sk)
+ {
+-	spin_unlock_bh(tsock->p->lock);
++	buf_discard(__skb_dequeue(&sk->sk_receive_queue));
++	atomic_dec(&tipc_queue_size);
+ }
+ 
+ /**
+- * pollmask - determine the current set of poll() events for a socket
+- * @sock: socket structure
+- *
+- * 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!
++ * discard_rx_queue - discard all buffers in socket receive queue
+  *
+- * Returns pollmask value
++ * Caller must hold socket lock
+  */
+ 
+-static u32 pollmask(struct socket *sock)
++static void discard_rx_queue(struct sock *sk)
+ {
+-	u32 mask;
+-
+-	if ((skb_queue_len(&sock->sk->sk_receive_queue) != 0) ||
+-	    (sock->state == SS_UNCONNECTED) ||
+-	    (sock->state == SS_DISCONNECTING))
+-		mask = (POLLRDNORM | POLLIN);
+-	else
+-		mask = 0;
+-
+-	if (sock->state == SS_DISCONNECTING)
+-		mask |= POLLHUP;
+-	else
+-		mask |= POLLOUT;
++	struct sk_buff *buf;
+ 
+-	return mask;
++	while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
++		atomic_dec(&tipc_queue_size);
++		buf_discard(buf);
++	}
+ }
+ 
+-
+ /**
+- * advance_queue - discard first buffer in queue
+- * @tsock: TIPC socket
++ * reject_rx_queue - reject all buffers in socket receive queue
++ *
++ * Caller must hold socket lock
+  */
+ 
+-static void advance_queue(struct tipc_sock *tsock)
++static void reject_rx_queue(struct sock *sk)
+ {
+-	sock_lock(tsock);
+-	buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue));
+-	sock_unlock(tsock);
+-	atomic_dec(&tipc_queue_size);
++	struct sk_buff *buf;
++
++	while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
++		tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
++		atomic_dec(&tipc_queue_size);
++	}
+ }
+ 
+ /**
+  * tipc_create - create a TIPC socket
++ * @net: network namespace (must be default network)
+  * @sock: pre-allocated socket structure
+  * @protocol: protocol indicator (must be 0)
+  *
+- * This routine creates and attaches a 'struct sock' to the 'struct socket',
+- * then create and attaches a TIPC port to the 'struct sock' part.
++ * This routine creates additional data structures used by the TIPC socket,
++ * initializes them, and links them together.
+  *
+  * Returns 0 on success, errno otherwise
+  */
++
+ static int tipc_create(struct net *net, struct socket *sock, int protocol)
+ {
+-	struct tipc_sock *tsock;
+-	struct tipc_port *port;
++	const struct proto_ops *ops;
++	socket_state state;
+ 	struct sock *sk;
+-	u32 ref;
++	u32 portref;
++
++	/* Validate arguments */
+ 
+ 	if (net != &init_net)
+ 		return -EAFNOSUPPORT;
+@@ -175,54 +198,56 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
+ 	if (unlikely(protocol != 0))
+ 		return -EPROTONOSUPPORT;
+ 
+-	ref = tipc_createport_raw(NULL, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE);
+-	if (unlikely(!ref))
+-		return -ENOMEM;
+-
+-	sock->state = SS_UNCONNECTED;
+-
+ 	switch (sock->type) {
+ 	case SOCK_STREAM:
+-		sock->ops = &stream_ops;
++		ops = &stream_ops;
++		state = SS_UNCONNECTED;
+ 		break;
+ 	case SOCK_SEQPACKET:
+-		sock->ops = &packet_ops;
++		ops = &packet_ops;
++		state = SS_UNCONNECTED;
+ 		break;
+ 	case SOCK_DGRAM:
+-		tipc_set_portunreliable(ref, 1);
+-		/* fall through */
+ 	case SOCK_RDM:
+-		tipc_set_portunreturnable(ref, 1);
+-		sock->ops = &msg_ops;
+-		sock->state = SS_READY;
++		ops = &msg_ops;
++		state = SS_READY;
+ 		break;
+ 	default:
+-		tipc_deleteport(ref);
+ 		return -EPROTOTYPE;
+ 	}
+ 
++	/* Allocate socket's protocol area */
++
+ 	sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto);
+-	if (!sk) {
+-		tipc_deleteport(ref);
++	if (sk == NULL)
+ 		return -ENOMEM;
+-	}
+ 
+-	sock_init_data(sock, sk);
+-	init_waitqueue_head(sk->sk_sleep);
+-	sk->sk_rcvtimeo = 8 * HZ;   /* default connect timeout = 8s */
++	/* Allocate TIPC port for socket to use */
+ 
+-	tsock = tipc_sk(sk);
+-	port = tipc_get_port(ref);
++	portref = tipc_createport_raw(sk, &dispatch, &wakeupdispatch,
++				      TIPC_LOW_IMPORTANCE);
++	if (unlikely(portref == 0)) {
++		sk_free(sk);
++		return -ENOMEM;
++	}
+ 
+-	tsock->p = port;
+-	port->usr_handle = tsock;
++	/* Finish initializing socket data structures */
+ 
+-	init_MUTEX(&tsock->sem);
++	sock->ops = ops;
++	sock->state = state;
+ 
+-	dbg("sock_create: %x\n",tsock);
++	sock_init_data(sock, sk);
++	sk->sk_rcvtimeo = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);
++	sk->sk_backlog_rcv = backlog_rcv;
++	tipc_sk(sk)->p = tipc_get_port(portref);
+ 
+-	atomic_inc(&tipc_user_count);
++	if (sock->state == SS_READY) {
++		tipc_set_portunreturnable(portref, 1);
++		if (sock->type == SOCK_DGRAM)
++			tipc_set_portunreliable(portref, 1);
++	}
+ 
++	atomic_inc(&tipc_user_count);
+ 	return 0;
+ }
+ 
+@@ -245,52 +270,62 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
+ 
+ static int release(struct socket *sock)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
+ 	struct sock *sk = sock->sk;
+-	int res = TIPC_OK;
++	struct tipc_port *tport;
+ 	struct sk_buff *buf;
++	int res;
+ 
+-	dbg("sock_delete: %x\n",tsock);
+-	if (!tsock)
+-		return 0;
+-	down(&tsock->sem);
+-	if (!sock->sk) {
+-		up(&tsock->sem);
++	/*
++	 * Exit if socket isn't fully initialized (occurs when a failed accept()
++	 * releases a pre-allocated child socket that was never used)
++	 */
++
++	if (sk == NULL)
+ 		return 0;
+-	}
+ 
+-	/* Reject unreceived messages, unless no longer connected */
++	tport = tipc_sk_port(sk);
++	lock_sock(sk);
++
++	/*
++	 * Reject all unreceived messages, except on an active connection
++	 * (which disconnects locally & sends a 'FIN+' to peer)
++	 */
+ 
+ 	while (sock->state != SS_DISCONNECTING) {
+-		sock_lock(tsock);
+-		buf = skb_dequeue(&sk->sk_receive_queue);
+-		if (!buf)
+-			tsock->p->usr_handle = NULL;
+-		sock_unlock(tsock);
+-		if (!buf)
++		buf = __skb_dequeue(&sk->sk_receive_queue);
++		if (buf == NULL)
+ 			break;
++		atomic_dec(&tipc_queue_size);
+ 		if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
+ 			buf_discard(buf);
+-		else
++		else {
++			if ((sock->state == SS_CONNECTING) ||
++			    (sock->state == SS_CONNECTED)) {
++				sock->state = SS_DISCONNECTING;
++				tipc_disconnect(tport->ref);
++			}
+ 			tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
+-		atomic_dec(&tipc_queue_size);
++		}
+ 	}
+ 
+-	/* Delete TIPC port */
++	/*
++	 * Delete TIPC port; this ensures no more messages are queued
++	 * (also disconnects an active connection & sends a 'FIN-' to peer)
++	 */
+ 
+-	res = tipc_deleteport(tsock->p->ref);
+-	sock->sk = NULL;
++	res = tipc_deleteport(tport->ref);
+ 
+-	/* Discard any remaining messages */
++	/* Discard any remaining (connection-based) messages in receive queue */
+ 
+-	while ((buf = skb_dequeue(&sk->sk_receive_queue))) {
+-		buf_discard(buf);
+-		atomic_dec(&tipc_queue_size);
+-	}
++	discard_rx_queue(sk);
++
++	/* Reject any messages that accumulated in backlog queue */
+ 
+-	up(&tsock->sem);
++	sock->state = SS_DISCONNECTING;
++	release_sock(sk);
+ 
+ 	sock_put(sk);
++	sock->sk = NULL;
+ 
+ 	atomic_dec(&tipc_user_count);
+ 	return res;
+@@ -307,47 +342,32 @@ static int release(struct socket *sock)
+  * (i.e. a socket address length of 0) unbinds all names from the socket.
+  *
+  * Returns 0 on success, errno otherwise
++ *
++ * NOTE: This routine doesn't need to take the socket lock since it doesn't
++ *       access any non-constant socket information.
+  */
+ 
+ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
+ 	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
+-	int res;
++	u32 portref = tipc_sk_port(sock->sk)->ref;
+ 
+-	if (down_interruptible(&tsock->sem))
+-		return -ERESTARTSYS;
++	if (unlikely(!uaddr_len))
++		return tipc_withdraw(portref, 0, NULL);
+ 
+-	if (unlikely(!uaddr_len)) {
+-		res = tipc_withdraw(tsock->p->ref, 0, NULL);
+-		goto exit;
+-	}
+-
+-	if (uaddr_len < sizeof(struct sockaddr_tipc)) {
+-		res = -EINVAL;
+-		goto exit;
+-	}
++	if (uaddr_len < sizeof(struct sockaddr_tipc))
++		return -EINVAL;
++	if (addr->family != AF_TIPC)
++		return -EAFNOSUPPORT;
+ 
+-	if (addr->family != AF_TIPC) {
+-		res = -EAFNOSUPPORT;
+-		goto exit;
+-	}
+ 	if (addr->addrtype == TIPC_ADDR_NAME)
+ 		addr->addr.nameseq.upper = addr->addr.nameseq.lower;
+-	else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
+-		res = -EAFNOSUPPORT;
+-		goto exit;
+-	}
++	else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
++		return -EAFNOSUPPORT;
+ 
+-	if (addr->scope > 0)
+-		res = tipc_publish(tsock->p->ref, addr->scope,
+-				   &addr->addr.nameseq);
+-	else
+-		res = tipc_withdraw(tsock->p->ref, -addr->scope,
+-				    &addr->addr.nameseq);
+-exit:
+-	up(&tsock->sem);
+-	return res;
++	return (addr->scope > 0) ?
++		tipc_publish(portref, addr->scope, &addr->addr.nameseq) :
++		tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq);
+ }
+ 
+ /**
+@@ -358,30 +378,33 @@ exit:
+  * @peer: 0 to obtain socket name, 1 to obtain peer socket name
+  *
+  * Returns 0 on success, errno otherwise
++ *
++ * NOTE: This routine doesn't need to take the socket lock since it doesn't
++ *       access any non-constant socket information.
+  */
+ 
+ static int get_name(struct socket *sock, struct sockaddr *uaddr,
+ 		    int *uaddr_len, int peer)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
+ 	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
++	u32 portref = tipc_sk_port(sock->sk)->ref;
+ 	u32 res;
+ 
+-	if (down_interruptible(&tsock->sem))
+-		return -ERESTARTSYS;
++	if (peer) {
++		res = tipc_peer(portref, &addr->addr.id);
++		if (res)
++			return res;
++	} else {
++		tipc_ownidentity(portref, &addr->addr.id);
++	}
+ 
+ 	*uaddr_len = sizeof(*addr);
+ 	addr->addrtype = TIPC_ADDR_ID;
+ 	addr->family = AF_TIPC;
+ 	addr->scope = 0;
+-	if (peer)
+-		res = tipc_peer(tsock->p->ref, &addr->addr.id);
+-	else
+-		res = tipc_ownidentity(tsock->p->ref, &addr->addr.id);
+ 	addr->addr.name.domain = 0;
+ 
+-	up(&tsock->sem);
+-	return res;
++	return 0;
+ }
+ 
+ /**
+@@ -390,15 +413,47 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
+  * @sock: socket for which to calculate the poll bits
+  * @wait: ???
+  *
+- * Returns the pollmask
++ * Returns pollmask value
++ *
++ * COMMENTARY:
++ * It appears that the usual socket locking mechanisms are not useful here
++ * since the pollmask info is potentially out-of-date the moment this routine
++ * exits.  TCP and other protocols seem to rely on higher level poll routines
++ * 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!
+  */
+ 
+ static unsigned int poll(struct file *file, struct socket *sock,
+ 			 poll_table *wait)
+ {
+-	poll_wait(file, sock->sk->sk_sleep, wait);
+-	/* NEED LOCK HERE? */
+-	return pollmask(sock);
++	struct sock *sk = sock->sk;
++	u32 mask;
++
++	poll_wait(file, sk->sk_sleep, 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;
++
++	return mask;
+ }
+ 
+ /**
+@@ -420,7 +475,6 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
+ 		return 0;
+ 	if (likely(dest->addr.name.name.type == TIPC_TOP_SRV))
+ 		return 0;
+-
+ 	if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
+ 		return -EACCES;
+ 
+@@ -434,7 +488,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
+ 
+ /**
+  * send_msg - send message in connectionless manner
+- * @iocb: (unused)
++ * @iocb: if NULL, indicates that socket lock is already held
+  * @sock: socket structure
+  * @m: message to send
+  * @total_len: length of message
+@@ -450,9 +504,9 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
+ static int send_msg(struct kiocb *iocb, struct socket *sock,
+ 		    struct msghdr *m, size_t total_len)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
++	struct sock *sk = sock->sk;
++	struct tipc_port *tport = tipc_sk_port(sk);
+ 	struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
+-	struct sk_buff *buf;
+ 	int needs_conn;
+ 	int res = -EINVAL;
+ 
+@@ -462,48 +516,46 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
+ 		     (dest->family != AF_TIPC)))
+ 		return -EINVAL;
+ 
++	if (iocb)
++		lock_sock(sk);
++
+ 	needs_conn = (sock->state != SS_READY);
+ 	if (unlikely(needs_conn)) {
+-		if (sock->state == SS_LISTENING)
+-			return -EPIPE;
+-		if (sock->state != SS_UNCONNECTED)
+-			return -EISCONN;
+-		if ((tsock->p->published) ||
+-		    ((sock->type == SOCK_STREAM) && (total_len != 0)))
+-			return -EOPNOTSUPP;
++		if (sock->state == SS_LISTENING) {
++			res = -EPIPE;
++			goto exit;
++		}
++		if (sock->state != SS_UNCONNECTED) {
++			res = -EISCONN;
++			goto exit;
++		}
++		if ((tport->published) ||
++		    ((sock->type == SOCK_STREAM) && (total_len != 0))) {
++			res = -EOPNOTSUPP;
++			goto exit;
++		}
+ 		if (dest->addrtype == TIPC_ADDR_NAME) {
+-			tsock->p->conn_type = dest->addr.name.name.type;
+-			tsock->p->conn_instance = dest->addr.name.name.instance;
++			tport->conn_type = dest->addr.name.name.type;
++			tport->conn_instance = dest->addr.name.name.instance;
+ 		}
+-	}
+-
+-	if (down_interruptible(&tsock->sem))
+-		return -ERESTARTSYS;
+-
+-	if (needs_conn) {
+ 
+ 		/* Abort any pending connection attempts (very unlikely) */
+ 
+-		while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
+-			tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
+-			atomic_dec(&tipc_queue_size);
+-		}
+-
+-		sock->state = SS_CONNECTING;
++		reject_rx_queue(sk);
+ 	}
+ 
+ 	do {
+ 		if (dest->addrtype == TIPC_ADDR_NAME) {
+ 			if ((res = dest_name_check(dest, m)))
+-				goto exit;
+-			res = tipc_send2name(tsock->p->ref,
++				break;
++			res = tipc_send2name(tport->ref,
+ 					     &dest->addr.name.name,
+ 					     dest->addr.name.domain,
+ 					     m->msg_iovlen,
+ 					     m->msg_iov);
+ 		}
+ 		else if (dest->addrtype == TIPC_ADDR_ID) {
+-			res = tipc_send2port(tsock->p->ref,
++			res = tipc_send2port(tport->ref,
+ 					     &dest->addr.id,
+ 					     m->msg_iovlen,
+ 					     m->msg_iov);
+@@ -511,36 +563,43 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
+ 		else if (dest->addrtype == TIPC_ADDR_MCAST) {
+ 			if (needs_conn) {
+ 				res = -EOPNOTSUPP;
+-				goto exit;
++				break;
+ 			}
+ 			if ((res = dest_name_check(dest, m)))
+-				goto exit;
+-			res = tipc_multicast(tsock->p->ref,
++				break;
++			res = tipc_multicast(tport->ref,
+ 					     &dest->addr.nameseq,
+ 					     0,
+ 					     m->msg_iovlen,
+ 					     m->msg_iov);
+ 		}
+ 		if (likely(res != -ELINKCONG)) {
+-exit:
+-			up(&tsock->sem);
+-			return res;
++			if (needs_conn && (res >= 0)) {
++				sock->state = SS_CONNECTING;
++			}
++			break;
+ 		}
+ 		if (m->msg_flags & MSG_DONTWAIT) {
+ 			res = -EWOULDBLOCK;
+-			goto exit;
+-		}
+-		if (wait_event_interruptible(*sock->sk->sk_sleep,
+-					     !tsock->p->congested)) {
+-		    res = -ERESTARTSYS;
+-		    goto exit;
++			break;
+ 		}
++		release_sock(sk);
++		res = wait_event_interruptible(*sk->sk_sleep,
++					       !tport->congested);
++		lock_sock(sk);
++		if (res)
++			break;
+ 	} while (1);
++
++exit:
++	if (iocb)
++		release_sock(sk);
++	return res;
+ }
+ 
+ /**
+  * send_packet - send a connection-oriented message
+- * @iocb: (unused)
++ * @iocb: if NULL, indicates that socket lock is already held
+  * @sock: socket structure
+  * @m: message to send
+  * @total_len: length of message
+@@ -553,7 +612,8 @@ exit:
+ static int send_packet(struct kiocb *iocb, struct socket *sock,
+ 		       struct msghdr *m, size_t total_len)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
++	struct sock *sk = sock->sk;
++	struct tipc_port *tport = tipc_sk_port(sk);
+ 	struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
+ 	int res;
+ 
+@@ -562,9 +622,8 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
+ 	if (unlikely(dest))
+ 		return send_msg(iocb, sock, m, total_len);
+ 
+-	if (down_interruptible(&tsock->sem)) {
+-		return -ERESTARTSYS;
+-	}
++	if (iocb)
++		lock_sock(sk);
+ 
+ 	do {
+ 		if (unlikely(sock->state != SS_CONNECTED)) {
+@@ -572,25 +631,28 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
+ 				res = -EPIPE;
+ 			else
+ 				res = -ENOTCONN;
+-			goto exit;
++			break;
+ 		}
+ 
+-		res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov);
++		res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov);
+ 		if (likely(res != -ELINKCONG)) {
+-exit:
+-			up(&tsock->sem);
+-			return res;
++			break;
+ 		}
+ 		if (m->msg_flags & MSG_DONTWAIT) {
+ 			res = -EWOULDBLOCK;
+-			goto exit;
+-		}
+-		if (wait_event_interruptible(*sock->sk->sk_sleep,
+-					     !tsock->p->congested)) {
+-		    res = -ERESTARTSYS;
+-		    goto exit;
++			break;
+ 		}
++		release_sock(sk);
++		res = wait_event_interruptible(*sk->sk_sleep,
++			(!tport->congested || !tport->connected));
++		lock_sock(sk);
++		if (res)
++			break;
+ 	} while (1);
++
++	if (iocb)
++		release_sock(sk);
++	return res;
+ }
+ 
+ /**
+@@ -606,11 +668,11 @@ exit:
+  * or errno if no data sent
+  */
+ 
+-
+ static int send_stream(struct kiocb *iocb, struct socket *sock,
+ 		       struct msghdr *m, size_t total_len)
+ {
+-	struct tipc_port *tport;
++	struct sock *sk = sock->sk;
++	struct tipc_port *tport = tipc_sk_port(sk);
+ 	struct msghdr my_msg;
+ 	struct iovec my_iov;
+ 	struct iovec *curr_iov;
+@@ -622,19 +684,27 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
+ 	int bytes_sent;
+ 	int res;
+ 
++	lock_sock(sk);
++
+ 	/* Handle special cases where there is no connection */
+ 
+ 	if (unlikely(sock->state != SS_CONNECTED)) {
+-		if (sock->state == SS_UNCONNECTED)
+-			return send_packet(iocb, sock, m, total_len);
+-		else if (sock->state == SS_DISCONNECTING)
+-			return -EPIPE;
+-		else
+-			return -ENOTCONN;
++		if (sock->state == SS_UNCONNECTED) {
++			res = send_packet(NULL, sock, m, total_len);
++			goto exit;
++		} else if (sock->state == SS_DISCONNECTING) {
++			res = -EPIPE;
++			goto exit;
++		} else {
++			res = -ENOTCONN;
++			goto exit;
++		}
+ 	}
+ 
+-	if (unlikely(m->msg_name))
+-		return -EISCONN;
++	if (unlikely(m->msg_name)) {
++		res = -EISCONN;
++		goto exit;
++	}
+ 
+ 	/*
+ 	 * Send each iovec entry using one or more messages
+@@ -652,7 +722,6 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
+ 	my_msg.msg_name = NULL;
+ 	bytes_sent = 0;
+ 
+-	tport = tipc_sk(sock->sk)->p;
+ 	hdr_size = msg_hdr_sz(&tport->phdr);
+ 
+ 	while (curr_iovlen--) {
+@@ -667,10 +736,10 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
+ 				bytes_to_send = curr_left;
+ 			my_iov.iov_base = curr_start;
+ 			my_iov.iov_len = bytes_to_send;
+-			if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
+-				if (bytes_sent != 0)
++			if ((res = send_packet(NULL, sock, &my_msg, 0)) < 0) {
++				if (bytes_sent)
+ 					res = bytes_sent;
+-				return res;
++				goto exit;
+ 			}
+ 			curr_left -= bytes_to_send;
+ 			curr_start += bytes_to_send;
+@@ -679,22 +748,23 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
+ 
+ 		curr_iov++;
+ 	}
+-
+-	return bytes_sent;
++	res = bytes_sent;
++exit:
++	release_sock(sk);
++	return res;
+ }
+ 
+ /**
+  * auto_connect - complete connection setup to a remote port
+  * @sock: socket structure
+- * @tsock: TIPC-specific socket structure
+  * @msg: peer's response message
+  *
+  * Returns 0 on success, errno otherwise
+  */
+ 
+-static int auto_connect(struct socket *sock, struct tipc_sock *tsock,
+-			struct tipc_msg *msg)
++static int auto_connect(struct socket *sock, struct tipc_msg *msg)
+ {
++	struct tipc_port *tport = tipc_sk_port(sock->sk);
+ 	struct tipc_portid peer;
+ 
+ 	if (msg_errcode(msg)) {
+@@ -704,8 +774,8 @@ static int auto_connect(struct socket *sock, struct tipc_sock *tsock,
+ 
+ 	peer.ref = msg_origport(msg);
+ 	peer.node = msg_orignode(msg);
+-	tipc_connect2port(tsock->p->ref, &peer);
+-	tipc_set_portimportance(tsock->p->ref, msg_importance(msg));
++	tipc_connect2port(tport->ref, &peer);
++	tipc_set_portimportance(tport->ref, msg_importance(msg));
+ 	sock->state = SS_CONNECTED;
+ 	return 0;
+ }
+@@ -818,62 +888,54 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
+ static int recv_msg(struct kiocb *iocb, struct socket *sock,
+ 		    struct msghdr *m, size_t buf_len, int flags)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
++	struct sock *sk = sock->sk;
++	struct tipc_port *tport = tipc_sk_port(sk);
+ 	struct sk_buff *buf;
+ 	struct tipc_msg *msg;
+-	unsigned int q_len;
+ 	unsigned int sz;
+ 	u32 err;
+ 	int res;
+ 
+-	/* Currently doesn't support receiving into multiple iovec entries */
++	/* Catch invalid receive requests */
+ 
+ 	if (m->msg_iovlen != 1)
+-		return -EOPNOTSUPP;
+-
+-	/* Catch invalid receive attempts */
++		return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */
+ 
+ 	if (unlikely(!buf_len))
+ 		return -EINVAL;
+ 
+-	if (sock->type == SOCK_SEQPACKET) {
+-		if (unlikely(sock->state == SS_UNCONNECTED))
+-			return -ENOTCONN;
+-		if (unlikely((sock->state == SS_DISCONNECTING) &&
+-			     (skb_queue_len(&sock->sk->sk_receive_queue) == 0)))
+-			return -ENOTCONN;
+-	}
++	lock_sock(sk);
+ 
+-	/* Look for a message in receive queue; wait if necessary */
+-
+-	if (unlikely(down_interruptible(&tsock->sem)))
+-		return -ERESTARTSYS;
+-
+-restart:
+-	if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
+-		     (flags & MSG_DONTWAIT))) {
+-		res = -EWOULDBLOCK;
++	if (unlikely(sock->state == SS_UNCONNECTED)) {
++		res = -ENOTCONN;
+ 		goto exit;
+ 	}
+ 
+-	if ((res = wait_event_interruptible(
+-		*sock->sk->sk_sleep,
+-		((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
+-		 (sock->state == SS_DISCONNECTING))) )) {
+-		goto exit;
+-	}
++restart:
+ 
+-	/* Catch attempt to receive on an already terminated connection */
+-	/* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */
++	/* Look for a message in receive queue; wait if necessary */
+ 
+-	if (!q_len) {
+-		res = -ENOTCONN;
+-		goto exit;
++	while (skb_queue_empty(&sk->sk_receive_queue)) {
++		if (sock->state == SS_DISCONNECTING) {
++			res = -ENOTCONN;
++			goto exit;
++		}
++		if (flags & MSG_DONTWAIT) {
++			res = -EWOULDBLOCK;
++			goto exit;
++		}
++		release_sock(sk);
++		res = wait_event_interruptible(*sk->sk_sleep,
++			(!skb_queue_empty(&sk->sk_receive_queue) ||
++			 (sock->state == SS_DISCONNECTING)));
++		lock_sock(sk);
++		if (res)
++			goto exit;
+ 	}
+ 
+-	/* Get access to first message in receive queue */
++	/* Look at first message in receive queue */
+ 
+-	buf = skb_peek(&sock->sk->sk_receive_queue);
++	buf = skb_peek(&sk->sk_receive_queue);
+ 	msg = buf_msg(buf);
+ 	sz = msg_data_sz(msg);
+ 	err = msg_errcode(msg);
+@@ -881,14 +943,15 @@ restart:
+ 	/* Complete connection setup for an implied connect */
+ 
+ 	if (unlikely(sock->state == SS_CONNECTING)) {
+-		if ((res = auto_connect(sock, tsock, msg)))
++		res = auto_connect(sock, msg);
++		if (res)
+ 			goto exit;
+ 	}
+ 
+ 	/* Discard an empty non-errored message & try again */
+ 
+ 	if ((!sz) && (!err)) {
+-		advance_queue(tsock);
++		advance_rx_queue(sk);
+ 		goto restart;
+ 	}
+ 
+@@ -898,7 +961,8 @@ restart:
+ 
+ 	/* Capture ancillary data (optional) */
+ 
+-	if ((res = anc_data_recv(m, msg, tsock->p)))
++	res = anc_data_recv(m, msg, tport);
++	if (res)
+ 		goto exit;
+ 
+ 	/* Capture message data (if valid) & compute return value (always) */
+@@ -925,12 +989,13 @@ restart:
+ 	/* Consume received message (optional) */
+ 
+ 	if (likely(!(flags & MSG_PEEK))) {
+-		if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+-			tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
+-		advance_queue(tsock);
++		if ((sock->state != SS_READY) &&
++		    (++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
++			tipc_acknowledge(tport->ref, tport->conn_unacked);
++		advance_rx_queue(sk);
+ 	}
+ exit:
+-	up(&tsock->sem);
++	release_sock(sk);
+ 	return res;
+ }
+ 
+@@ -950,10 +1015,10 @@ exit:
+ static int recv_stream(struct kiocb *iocb, struct socket *sock,
+ 		       struct msghdr *m, size_t buf_len, int flags)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
++	struct sock *sk = sock->sk;
++	struct tipc_port *tport = tipc_sk_port(sk);
+ 	struct sk_buff *buf;
+ 	struct tipc_msg *msg;
+-	unsigned int q_len;
+ 	unsigned int sz;
+ 	int sz_to_copy;
+ 	int sz_copied = 0;
+@@ -961,54 +1026,49 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
+ 	char __user *crs = m->msg_iov->iov_base;
+ 	unsigned char *buf_crs;
+ 	u32 err;
+-	int res;
++	int res = 0;
+ 
+-	/* Currently doesn't support receiving into multiple iovec entries */
++	/* Catch invalid receive attempts */
+ 
+ 	if (m->msg_iovlen != 1)
+-		return -EOPNOTSUPP;
+-
+-	/* Catch invalid receive attempts */
++		return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */
+ 
+ 	if (unlikely(!buf_len))
+ 		return -EINVAL;
+ 
+-	if (unlikely(sock->state == SS_DISCONNECTING)) {
+-		if (skb_queue_len(&sock->sk->sk_receive_queue) == 0)
+-			return -ENOTCONN;
+-	} else if (unlikely(sock->state != SS_CONNECTED))
+-		return -ENOTCONN;
++	lock_sock(sk);
+ 
+-	/* Look for a message in receive queue; wait if necessary */
+-
+-	if (unlikely(down_interruptible(&tsock->sem)))
+-		return -ERESTARTSYS;
+-
+-restart:
+-	if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
+-		     (flags & MSG_DONTWAIT))) {
+-		res = -EWOULDBLOCK;
++	if (unlikely((sock->state == SS_UNCONNECTED) ||
++		     (sock->state == SS_CONNECTING))) {
++		res = -ENOTCONN;
+ 		goto exit;
+ 	}
+ 
+-	if ((res = wait_event_interruptible(
+-		*sock->sk->sk_sleep,
+-		((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
+-		 (sock->state == SS_DISCONNECTING))) )) {
+-		goto exit;
+-	}
++restart:
+ 
+-	/* Catch attempt to receive on an already terminated connection */
+-	/* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */
++	/* Look for a message in receive queue; wait if necessary */
+ 
+-	if (!q_len) {
+-		res = -ENOTCONN;
+-		goto exit;
++	while (skb_queue_empty(&sk->sk_receive_queue)) {
++		if (sock->state == SS_DISCONNECTING) {
++			res = -ENOTCONN;
++			goto exit;
++		}
++		if (flags & MSG_DONTWAIT) {
++			res = -EWOULDBLOCK;
++			goto exit;
++		}
++		release_sock(sk);
++		res = wait_event_interruptible(*sk->sk_sleep,
++			(!skb_queue_empty(&sk->sk_receive_queue) ||
++			 (sock->state == SS_DISCONNECTING)));
++		lock_sock(sk);
++		if (res)
++			goto exit;
+ 	}
+ 
+-	/* Get access to first message in receive queue */
++	/* Look at first message in receive queue */
+ 
+-	buf = skb_peek(&sock->sk->sk_receive_queue);
++	buf = skb_peek(&sk->sk_receive_queue);
+ 	msg = buf_msg(buf);
+ 	sz = msg_data_sz(msg);
+ 	err = msg_errcode(msg);
+@@ -1016,7 +1076,7 @@ restart:
+ 	/* Discard an empty non-errored message & try again */
+ 
+ 	if ((!sz) && (!err)) {
+-		advance_queue(tsock);
++		advance_rx_queue(sk);
+ 		goto restart;
+ 	}
+ 
+@@ -1024,7 +1084,8 @@ restart:
+ 
+ 	if (sz_copied == 0) {
+ 		set_orig_addr(m, msg);
+-		if ((res = anc_data_recv(m, msg, tsock->p)))
++		res = anc_data_recv(m, msg, tport);
++		if (res)
+ 			goto exit;
+ 	}
+ 
+@@ -1032,7 +1093,7 @@ restart:
+ 
+ 	if (!err) {
+ 		buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
+-		sz = skb_tail_pointer(buf) - buf_crs;
++		sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
+ 
+ 		needed = (buf_len - sz_copied);
+ 		sz_to_copy = (sz <= needed) ? sz : needed;
+@@ -1062,35 +1123,37 @@ restart:
+ 	/* Consume received message (optional) */
+ 
+ 	if (likely(!(flags & MSG_PEEK))) {
+-		if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+-			tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
+-		advance_queue(tsock);
++		if (unlikely(++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
++			tipc_acknowledge(tport->ref, tport->conn_unacked);
++		advance_rx_queue(sk);
+ 	}
+ 
+ 	/* Loop around if more data is required */
+ 
+ 	if ((sz_copied < buf_len)    /* didn't get all requested data */
+-	    && (flags & MSG_WAITALL) /* ... and need to wait for more */
++	    && (!skb_queue_empty(&sock->sk->sk_receive_queue) ||
++		(flags & MSG_WAITALL))
++				     /* ... 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;
+ 
+ exit:
+-	up(&tsock->sem);
++	release_sock(sk);
+ 	return sz_copied ? sz_copied : res;
+ }
+ 
+ /**
+- * queue_overloaded - test if queue overload condition exists
++ * rx_queue_full - determine if receive queue can accept another message
++ * @msg: message to be added to queue
+  * @queue_size: current size of queue
+  * @base: nominal maximum size of queue
+- * @msg: message to be added to queue
+  *
+- * Returns 1 if queue is currently overloaded, 0 otherwise
++ * Returns 1 if queue is unable to accept message, 0 otherwise
+  */
+ 
+-static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg)
++static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base)
+ {
+ 	u32 threshold;
+ 	u32 imp = msg_importance(msg);
+@@ -1107,41 +1170,28 @@ static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg)
+ 	if (msg_connected(msg))
+ 		threshold *= 4;
+ 
+-	return (queue_size > threshold);
+-}
+-
+-/**
+- * async_disconnect - wrapper function used to disconnect port
+- * @portref: TIPC port reference (passed as pointer-sized value)
+- */
+-
+-static void async_disconnect(unsigned long portref)
+-{
+-	tipc_disconnect((u32)portref);
++	return (queue_size >= threshold);
+ }
+ 
+ /**
+- * dispatch - handle arriving message
+- * @tport: TIPC port that received message
++ * filter_rcv - validate incoming message
++ * @sk: socket
+  * @buf: message
+  *
+- * Called with port locked.  Must not take socket lock to avoid deadlock risk.
++ * Enqueues message on receive queue if acceptable; optionally handles
++ * disconnect indication for a connected socket.
++ *
++ * Called with socket lock already taken; port lock may also be taken.
+  *
+  * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
+  */
+ 
+-static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
++static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
+ {
++	struct socket *sock = sk->sk_socket;
+ 	struct tipc_msg *msg = buf_msg(buf);
+-	struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
+-	struct socket *sock;
+ 	u32 recv_q_len;
+ 
+-	/* Reject message if socket is closing */
+-
+-	if (!tsock)
+-		return TIPC_ERR_NO_PORT;
+-
+ 	/* Reject message if it is wrong sort of message for socket */
+ 
+ 	/*
+@@ -1149,7 +1199,7 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
+ 	 * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY
+ 	 * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC
+ 	 */
+-	sock = tsock->sk.sk_socket;
++
+ 	if (sock->state == SS_READY) {
+ 		if (msg_connected(msg)) {
+ 			msg_dbg(msg, "dispatch filter 1\n");
+@@ -1192,52 +1242,103 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
+ 
+ 	/* Reject message if there isn't room to queue it */
+ 
+-	if (unlikely((u32)atomic_read(&tipc_queue_size) >
+-		     OVERLOAD_LIMIT_BASE)) {
+-		if (queue_overloaded(atomic_read(&tipc_queue_size),
+-				     OVERLOAD_LIMIT_BASE, msg))
++	recv_q_len = (u32)atomic_read(&tipc_queue_size);
++	if (unlikely(recv_q_len >= OVERLOAD_LIMIT_BASE)) {
++		if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE))
+ 			return TIPC_ERR_OVERLOAD;
+ 	}
+-	recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue);
+-	if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) {
+-		if (queue_overloaded(recv_q_len,
+-				     OVERLOAD_LIMIT_BASE / 2, msg))
++	recv_q_len = skb_queue_len(&sk->sk_receive_queue);
++	if (unlikely(recv_q_len >= (OVERLOAD_LIMIT_BASE / 2))) {
++		if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE / 2))
+ 			return TIPC_ERR_OVERLOAD;
+ 	}
+ 
++	/* Enqueue message (finally!) */
++
++	msg_dbg(msg, "<DISP<: ");
++	TIPC_SKB_CB(buf)->handle = msg_data(msg);
++	atomic_inc(&tipc_queue_size);
++	__skb_queue_tail(&sk->sk_receive_queue, buf);
++
+ 	/* Initiate connection termination for an incoming 'FIN' */
+ 
+ 	if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
+ 		sock->state = SS_DISCONNECTING;
+-		/* Note: Use signal since port lock is already taken! */
+-		tipc_k_signal((Handler)async_disconnect, tport->ref);
++		tipc_disconnect_port(tipc_sk_port(sk));
+ 	}
+ 
+-	/* Enqueue message (finally!) */
++	if (waitqueue_active(sk->sk_sleep))
++		wake_up_interruptible(sk->sk_sleep);
++	return TIPC_OK;
++}
+ 
+-	msg_dbg(msg,"<DISP<: ");
+-	TIPC_SKB_CB(buf)->handle = msg_data(msg);
+-	atomic_inc(&tipc_queue_size);
+-	skb_queue_tail(&sock->sk->sk_receive_queue, buf);
++/**
++ * backlog_rcv - handle incoming message from backlog queue
++ * @sk: socket
++ * @buf: message
++ *
++ * Caller must hold socket lock, but not port lock.
++ *
++ * Returns 0
++ */
+ 
+-	if (waitqueue_active(sock->sk->sk_sleep))
+-		wake_up_interruptible(sock->sk->sk_sleep);
+-	return TIPC_OK;
++static int backlog_rcv(struct sock *sk, struct sk_buff *buf)
++{
++	u32 res;
++
++	res = filter_rcv(sk, buf);
++	if (res)
++		tipc_reject_msg(buf, res);
++	return 0;
++}
++
++/**
++ * dispatch - handle incoming message
++ * @tport: TIPC port that received message
++ * @buf: message
++ *
++ * Called with port lock already taken.
++ *
++ * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
++ */
++
++static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
++{
++	struct sock *sk = (struct sock *)tport->usr_handle;
++	u32 res;
++
++	/*
++	 * Process message if socket is unlocked; otherwise add to backlog queue
++	 *
++	 * This code is based on sk_receive_skb(), but must be distinct from it
++	 * since a TIPC-specific filter/reject mechanism is utilized
++	 */
++
++	bh_lock_sock(sk);
++	if (!sock_owned_by_user(sk)) {
++		res = filter_rcv(sk, buf);
++	} else {
++		sk_add_backlog(sk, buf);
++		res = TIPC_OK;
++	}
++	bh_unlock_sock(sk);
++
++	return res;
+ }
+ 
+ /**
+  * wakeupdispatch - wake up port after congestion
+  * @tport: port to wakeup
+  *
+- * Called with port lock on.
++ * Called with port lock already taken.
+  */
+ 
+ static void wakeupdispatch(struct tipc_port *tport)
+ {
+-	struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
++	struct sock *sk = (struct sock *)tport->usr_handle;
+ 
+-	if (waitqueue_active(tsock->sk.sk_sleep))
+-		wake_up_interruptible(tsock->sk.sk_sleep);
++	if (waitqueue_active(sk->sk_sleep))
++		wake_up_interruptible(sk->sk_sleep);
+ }
+ 
+ /**
+@@ -1245,7 +1346,7 @@ static void wakeupdispatch(struct tipc_port *tport)
+  * @sock: socket structure
+  * @dest: socket address for destination port
+  * @destlen: size of socket address data structure
+- * @flags: (unused)
++ * @flags: file-related flags associated with socket
+  *
+  * Returns 0 on success, errno otherwise
+  */
+@@ -1253,72 +1354,105 @@ static void wakeupdispatch(struct tipc_port *tport)
+ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
+ 		   int flags)
+ {
+-   struct tipc_sock *tsock = tipc_sk(sock->sk);
+-   struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
+-   struct msghdr m = {NULL,};
+-   struct sk_buff *buf;
+-   struct tipc_msg *msg;
+-   int res;
+-
+-   /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */
+-
+-   if (sock->state == SS_READY)
+-	   return -EOPNOTSUPP;
+-
+-   /* Issue Posix-compliant error code if socket is in the wrong state */
+-
+-   if (sock->state == SS_LISTENING)
+-	   return -EOPNOTSUPP;
+-   if (sock->state == SS_CONNECTING)
+-	   return -EALREADY;
+-   if (sock->state != SS_UNCONNECTED)
+-	   return -EISCONN;
+-
+-   /*
+-    * Reject connection attempt using multicast address
+-    *
+-    * Note: send_msg() validates the rest of the address fields,
+-    *       so there's no need to do it here
+-    */
+-
+-   if (dst->addrtype == TIPC_ADDR_MCAST)
+-	   return -EINVAL;
+-
+-   /* Send a 'SYN-' to destination */
+-
+-   m.msg_name = dest;
+-   m.msg_namelen = destlen;
+-   if ((res = send_msg(NULL, sock, &m, 0)) < 0) {
+-	   sock->state = SS_DISCONNECTING;
+-	   return res;
+-   }
+-
+-   if (down_interruptible(&tsock->sem))
+-	   return -ERESTARTSYS;
+-
+-   /* Wait for destination's 'ACK' response */
+-
+-   res = wait_event_interruptible_timeout(*sock->sk->sk_sleep,
+-					  skb_queue_len(&sock->sk->sk_receive_queue),
+-					  sock->sk->sk_rcvtimeo);
+-   buf = skb_peek(&sock->sk->sk_receive_queue);
+-   if (res > 0) {
+-	   msg = buf_msg(buf);
+-	   res = auto_connect(sock, tsock, msg);
+-	   if (!res) {
+-		   if (!msg_data_sz(msg))
+-			   advance_queue(tsock);
+-	   }
+-   } else {
+-	   if (res == 0) {
+-		   res = -ETIMEDOUT;
+-	   } else
+-		   { /* leave "res" unchanged */ }
+-	   sock->state = SS_DISCONNECTING;
+-   }
+-
+-   up(&tsock->sem);
+-   return res;
++	struct sock *sk = sock->sk;
++	struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
++	struct msghdr m = {NULL,};
++	struct sk_buff *buf;
++	struct tipc_msg *msg;
++	int res;
++
++	lock_sock(sk);
++
++	/* For now, TIPC does not allow use of connect() with DGRAM/RDM types */
++
++	if (sock->state == SS_READY) {
++		res = -EOPNOTSUPP;
++		goto exit;
++	}
++
++	/* For now, TIPC does not support the non-blocking form of connect() */
++
++	if (flags & O_NONBLOCK) {
++		res = -EWOULDBLOCK;
++		goto exit;
++	}
++
++	/* Issue Posix-compliant error code if socket is in the wrong state */
++
++	if (sock->state == SS_LISTENING) {
++		res = -EOPNOTSUPP;
++		goto exit;
++	}
++	if (sock->state == SS_CONNECTING) {
++		res = -EALREADY;
++		goto exit;
++	}
++	if (sock->state != SS_UNCONNECTED) {
++		res = -EISCONN;
++		goto exit;
++	}
++
++	/*
++	 * Reject connection attempt using multicast address
++	 *
++	 * Note: send_msg() validates the rest of the address fields,
++	 *       so there's no need to do it here
++	 */
++
++	if (dst->addrtype == TIPC_ADDR_MCAST) {
++		res = -EINVAL;
++		goto exit;
++	}
++
++	/* Reject any messages already in receive queue (very unlikely) */
++
++	reject_rx_queue(sk);
++
++	/* Send a 'SYN-' to destination */
++
++	m.msg_name = dest;
++	m.msg_namelen = destlen;
++	res = send_msg(NULL, sock, &m, 0);
++	if (res < 0) {
++		goto exit;
++	}
++
++	/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
++
++	release_sock(sk);
++	res = wait_event_interruptible_timeout(*sk->sk_sleep,
++			(!skb_queue_empty(&sk->sk_receive_queue) ||
++			(sock->state != SS_CONNECTING)),
++			sk->sk_rcvtimeo);
++	lock_sock(sk);
++
++	if (res > 0) {
++		buf = skb_peek(&sk->sk_receive_queue);
++		if (buf != NULL) {
++			msg = buf_msg(buf);
++			res = auto_connect(sock, msg);
++			if (!res) {
++				if (!msg_data_sz(msg))
++					advance_rx_queue(sk);
++			}
++		} else {
++			if (sock->state == SS_CONNECTED) {
++				res = -EISCONN;
++			} else {
++				res = -ECONNREFUSED;
++			}
++		}
++	} else {
++		if (res == 0)
++			res = -ETIMEDOUT;
++		else
++			; /* leave "res" unchanged */
++		sock->state = SS_DISCONNECTING;
++	}
++
++exit:
++	release_sock(sk);
++	return res;
+ }
+ 
+ /**
+@@ -1331,14 +1465,22 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
+ 
+ static int listen(struct socket *sock, int len)
+ {
+-	/* REQUIRES SOCKET LOCKING OF SOME SORT? */
++	struct sock *sk = sock->sk;
++	int res;
++
++	lock_sock(sk);
+ 
+ 	if (sock->state == SS_READY)
+-		return -EOPNOTSUPP;
+-	if (sock->state != SS_UNCONNECTED)
+-		return -EINVAL;
+-	sock->state = SS_LISTENING;
+-	return 0;
++		res = -EOPNOTSUPP;
++	else if (sock->state != SS_UNCONNECTED)
++		res = -EINVAL;
++	else {
++		sock->state = SS_LISTENING;
++		res = 0;
++	}
++
++	release_sock(sk);
++	return res;
+ }
+ 
+ /**
+@@ -1350,50 +1492,69 @@ static int listen(struct socket *sock, int len)
+  * Returns 0 on success, errno otherwise
+  */
+ 
+-static int accept(struct socket *sock, struct socket *newsock, int flags)
++static int accept(struct socket *sock, struct socket *new_sock, int flags)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
++	struct sock *sk = sock->sk;
+ 	struct sk_buff *buf;
+-	int res = -EFAULT;
+-
+-	if (sock->state == SS_READY)
+-		return -EOPNOTSUPP;
+-	if (sock->state != SS_LISTENING)
+-		return -EINVAL;
+-
+-	if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
+-		     (flags & O_NONBLOCK)))
+-		return -EWOULDBLOCK;
++	int res;
+ 
+-	if (down_interruptible(&tsock->sem))
+-		return -ERESTARTSYS;
++	lock_sock(sk);
+ 
+-	if (wait_event_interruptible(*sock->sk->sk_sleep,
+-				     skb_queue_len(&sock->sk->sk_receive_queue))) {
+-		res = -ERESTARTSYS;
++	if (sock->state == SS_READY) {
++		res = -EOPNOTSUPP;
++		goto exit;
++	}
++	if (sock->state != SS_LISTENING) {
++		res = -EINVAL;
+ 		goto exit;
+ 	}
+-	buf = skb_peek(&sock->sk->sk_receive_queue);
+ 
+-	res = tipc_create(sock->sk->sk_net, newsock, 0);
++	while (skb_queue_empty(&sk->sk_receive_queue)) {
++		if (flags & O_NONBLOCK) {
++			res = -EWOULDBLOCK;
++			goto exit;
++		}
++		release_sock(sk);
++		res = wait_event_interruptible(*sk->sk_sleep,
++				(!skb_queue_empty(&sk->sk_receive_queue)));
++		lock_sock(sk);
++		if (res)
++			goto exit;
++	}
++
++	buf = skb_peek(&sk->sk_receive_queue);
++
++	res = tipc_create(sock_net(sock->sk), new_sock, 0);
+ 	if (!res) {
+-		struct tipc_sock *new_tsock = tipc_sk(newsock->sk);
++		struct sock *new_sk = new_sock->sk;
++		struct tipc_port *new_tport = tipc_sk_port(new_sk);
++		u32 new_ref = new_tport->ref;
+ 		struct tipc_portid id;
+ 		struct tipc_msg *msg = buf_msg(buf);
+-		u32 new_ref = new_tsock->p->ref;
++
++		lock_sock(new_sk);
++
++		/*
++		 * Reject any stray messages received by new socket
++		 * before the socket lock was taken (very, very unlikely)
++		 */
++
++		reject_rx_queue(new_sk);
++
++		/* Connect new socket to it's peer */
+ 
+ 		id.ref = msg_origport(msg);
+ 		id.node = msg_orignode(msg);
+ 		tipc_connect2port(new_ref, &id);
+-		newsock->state = SS_CONNECTED;
++		new_sock->state = SS_CONNECTED;
+ 
+ 		tipc_set_portimportance(new_ref, msg_importance(msg));
+ 		if (msg_named(msg)) {
+-			new_tsock->p->conn_type = msg_nametype(msg);
+-			new_tsock->p->conn_instance = msg_nameinst(msg);
++			new_tport->conn_type = msg_nametype(msg);
++			new_tport->conn_instance = msg_nameinst(msg);
+ 		}
+ 
+-	       /*
++		/*
+ 		 * Respond to 'SYN-' by discarding it & returning 'ACK'-.
+ 		 * Respond to 'SYN+' by queuing it on new socket.
+ 		 */
+@@ -1402,24 +1563,23 @@ static int accept(struct socket *sock, struct socket *newsock, int flags)
+ 		if (!msg_data_sz(msg)) {
+ 			struct msghdr m = {NULL,};
+ 
+-			send_packet(NULL, newsock, &m, 0);
+-			advance_queue(tsock);
++			advance_rx_queue(sk);
++			send_packet(NULL, new_sock, &m, 0);
+ 		} else {
+-			sock_lock(tsock);
+-			skb_dequeue(&sock->sk->sk_receive_queue);
+-			sock_unlock(tsock);
+-			skb_queue_head(&newsock->sk->sk_receive_queue, buf);
++			__skb_dequeue(&sk->sk_receive_queue);
++			__skb_queue_head(&new_sk->sk_receive_queue, buf);
+ 		}
++		release_sock(new_sk);
+ 	}
+ exit:
+-	up(&tsock->sem);
++	release_sock(sk);
+ 	return res;
+ }
+ 
+ /**
+  * shutdown - shutdown socket connection
+  * @sock: socket structure
+- * @how: direction to close (unused; always treated as read + write)
++ * @how: direction to close (must be SHUT_RDWR)
+  *
+  * Terminates connection (if necessary), then purges socket's receive queue.
+  *
+@@ -1428,53 +1588,46 @@ exit:
+ 
+ static int shutdown(struct socket *sock, int how)
+ {
+-	struct tipc_sock* tsock = tipc_sk(sock->sk);
++	struct sock *sk = sock->sk;
++	struct tipc_port *tport = tipc_sk_port(sk);
+ 	struct sk_buff *buf;
+ 	int res;
+ 
+-	/* Could return -EINVAL for an invalid "how", but why bother? */
+-
+-	if (down_interruptible(&tsock->sem))
+-		return -ERESTARTSYS;
++	if (how != SHUT_RDWR)
++		return -EINVAL;
+ 
+-	sock_lock(tsock);
++	lock_sock(sk);
+ 
+ 	switch (sock->state) {
++	case SS_CONNECTING:
+ 	case SS_CONNECTED:
+ 
+-		/* Send 'FIN+' or 'FIN-' message to peer */
+-
+-		sock_unlock(tsock);
++		/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
+ restart:
+-		if ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
++		buf = __skb_dequeue(&sk->sk_receive_queue);
++		if (buf) {
+ 			atomic_dec(&tipc_queue_size);
+ 			if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
+ 				buf_discard(buf);
+ 				goto restart;
+ 			}
++			tipc_disconnect(tport->ref);
+ 			tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
++		} else {
++			tipc_shutdown(tport->ref);
+ 		}
+-		else {
+-			tipc_shutdown(tsock->p->ref);
+-		}
+-		sock_lock(tsock);
++
++		sock->state = SS_DISCONNECTING;
+ 
+ 		/* fall through */
+ 
+ 	case SS_DISCONNECTING:
+ 
+-		/* Discard any unreceived messages */
++		/* Discard any unreceived messages; wake up sleeping tasks */
+ 
+-		while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
+-			atomic_dec(&tipc_queue_size);
+-			buf_discard(buf);
+-		}
+-		tsock->p->conn_unacked = 0;
+-
+-		/* fall through */
+-
+-	case SS_CONNECTING:
+-		sock->state = SS_DISCONNECTING;
++		discard_rx_queue(sk);
++		if (waitqueue_active(sk->sk_sleep))
++			wake_up_interruptible(sk->sk_sleep);
+ 		res = 0;
+ 		break;
+ 
+@@ -1482,9 +1635,7 @@ restart:
+ 		res = -ENOTCONN;
+ 	}
+ 
+-	sock_unlock(tsock);
+-
+-	up(&tsock->sem);
++	release_sock(sk);
+ 	return res;
+ }
+ 
+@@ -1505,7 +1656,8 @@ restart:
+ static int setsockopt(struct socket *sock,
+ 		      int lvl, int opt, char __user *ov, int ol)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
++	struct sock *sk = sock->sk;
++	struct tipc_port *tport = tipc_sk_port(sk);
+ 	u32 value;
+ 	int res;
+ 
+@@ -1518,30 +1670,31 @@ static int setsockopt(struct socket *sock,
+ 	if ((res = get_user(value, (u32 __user *)ov)))
+ 		return res;
+ 
+-	if (down_interruptible(&tsock->sem))
+-		return -ERESTARTSYS;
++	lock_sock(sk);
+ 
+ 	switch (opt) {
+ 	case TIPC_IMPORTANCE:
+-		res = tipc_set_portimportance(tsock->p->ref, value);
++		res = tipc_set_portimportance(tport->ref, value);
+ 		break;
+ 	case TIPC_SRC_DROPPABLE:
+ 		if (sock->type != SOCK_STREAM)
+-			res = tipc_set_portunreliable(tsock->p->ref, value);
++			res = tipc_set_portunreliable(tport->ref, value);
+ 		else
+ 			res = -ENOPROTOOPT;
+ 		break;
+ 	case TIPC_DEST_DROPPABLE:
+-		res = tipc_set_portunreturnable(tsock->p->ref, value);
++		res = tipc_set_portunreturnable(tport->ref, value);
+ 		break;
+ 	case TIPC_CONN_TIMEOUT:
+-		sock->sk->sk_rcvtimeo = (value * HZ / 1000);
++		sk->sk_rcvtimeo = msecs_to_jiffies(value);
++		/* no need to set "res", since already 0 at this point */
+ 		break;
+ 	default:
+ 		res = -EINVAL;
+ 	}
+ 
+-	up(&tsock->sem);
++	release_sock(sk);
++
+ 	return res;
+ }
+ 
+@@ -1562,7 +1715,8 @@ static int setsockopt(struct socket *sock,
+ static int getsockopt(struct socket *sock,
+ 		      int lvl, int opt, char __user *ov, int __user *ol)
+ {
+-	struct tipc_sock *tsock = tipc_sk(sock->sk);
++	struct sock *sk = sock->sk;
++	struct tipc_port *tport = tipc_sk_port(sk);
+ 	int len;
+ 	u32 value;
+ 	int res;
+@@ -1574,40 +1728,41 @@ static int getsockopt(struct socket *sock,
+ 	if ((res = get_user(len, ol)))
+ 		return res;
+ 
+-	if (down_interruptible(&tsock->sem))
+-		return -ERESTARTSYS;
++	lock_sock(sk);
+ 
+ 	switch (opt) {
+ 	case TIPC_IMPORTANCE:
+-		res = tipc_portimportance(tsock->p->ref, &value);
++		res = tipc_portimportance(tport->ref, &value);
+ 		break;
+ 	case TIPC_SRC_DROPPABLE:
+-		res = tipc_portunreliable(tsock->p->ref, &value);
++		res = tipc_portunreliable(tport->ref, &value);
+ 		break;
+ 	case TIPC_DEST_DROPPABLE:
+-		res = tipc_portunreturnable(tsock->p->ref, &value);
++		res = tipc_portunreturnable(tport->ref, &value);
+ 		break;
+ 	case TIPC_CONN_TIMEOUT:
+-		value = (sock->sk->sk_rcvtimeo * 1000) / HZ;
++		value = jiffies_to_msecs(sk->sk_rcvtimeo);
++		/* no need to set "res", since already 0 at this point */
+ 		break;
+ 	default:
+ 		res = -EINVAL;
+ 	}
+ 
++	release_sock(sk);
++
+ 	if (res) {
+ 		/* "get" failed */
+ 	}
+ 	else if (len < sizeof(value)) {
+ 		res = -EINVAL;
+ 	}
+-	else if ((res = copy_to_user(ov, &value, sizeof(value)))) {
+-		/* couldn't return value */
++	else if (copy_to_user(ov, &value, sizeof(value))) {
++		res = -EFAULT;
+ 	}
+ 	else {
+ 		res = put_user(sizeof(value), ol);
+ 	}
+ 
+-	up(&tsock->sem);
+ 	return res;
+ }
+ 
+@@ -1720,6 +1875,7 @@ int tipc_socket_init(void)
+ /**
+  * tipc_socket_stop - stop TIPC socket interface
+  */
++
+ void tipc_socket_stop(void)
+ {
+ 	if (!sockets_enabled)
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index b8788fd..e18cd36 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -252,7 +252,7 @@ static struct sock *__unix_find_socket_byname(struct net *net,
+ 	sk_for_each(s, node, &unix_socket_table[hash ^ type]) {
+ 		struct unix_sock *u = unix_sk(s);
+ 
+-		if (s->sk_net != net)
++		if (!net_eq(sock_net(s), net))
+ 			continue;
+ 
+ 		if (u->addr->len == len &&
+@@ -289,7 +289,7 @@ static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
+ 		    &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
+ 		struct dentry *dentry = unix_sk(s)->dentry;
+ 
+-		if (s->sk_net != net)
++		if (!net_eq(sock_net(s), net))
+ 			continue;
+ 
+ 		if(dentry && dentry->d_inode == i)
+@@ -654,7 +654,7 @@ static int unix_release(struct socket *sock)
+ static int unix_autobind(struct socket *sock)
+ {
+ 	struct sock *sk = sock->sk;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 	struct unix_sock *u = unix_sk(sk);
+ 	static u32 ordernum = 1;
+ 	struct unix_address * addr;
+@@ -758,7 +758,7 @@ fail:
+ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ {
+ 	struct sock *sk = sock->sk;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 	struct unix_sock *u = unix_sk(sk);
+ 	struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
+ 	struct dentry * dentry = NULL;
+@@ -819,7 +819,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 		 */
+ 		mode = S_IFSOCK |
+ 		       (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
++		err = mnt_want_write(nd.path.mnt);
++		if (err)
++			goto out_mknod_dput;
+ 		err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
++		mnt_drop_write(nd.path.mnt);
+ 		if (err)
+ 			goto out_mknod_dput;
+ 		mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -899,7 +903,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
+ 			      int alen, int flags)
+ {
+ 	struct sock *sk = sock->sk;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 	struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr;
+ 	struct sock *other;
+ 	unsigned hash;
+@@ -996,7 +1000,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ {
+ 	struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
+ 	struct sock *sk = sock->sk;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 	struct unix_sock *u = unix_sk(sk), *newu, *otheru;
+ 	struct sock *newsk = NULL;
+ 	struct sock *other = NULL;
+@@ -1025,7 +1029,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ 	err = -ENOMEM;
+ 
+ 	/* create new sock for complete connection */
+-	newsk = unix_create1(sk->sk_net, NULL);
++	newsk = unix_create1(sock_net(sk), NULL);
+ 	if (newsk == NULL)
+ 		goto out;
+ 
+@@ -1312,7 +1316,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
+ {
+ 	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
+ 	struct sock *sk = sock->sk;
+-	struct net *net = sk->sk_net;
++	struct net *net = sock_net(sk);
+ 	struct unix_sock *u = unix_sk(sk);
+ 	struct sockaddr_un *sunaddr=msg->msg_name;
+ 	struct sock *other = NULL;
+@@ -2016,13 +2020,14 @@ struct unix_iter_state {
+ 	struct seq_net_private p;
+ 	int i;
+ };
+-static struct sock *unix_seq_idx(struct unix_iter_state *iter, loff_t pos)
++static struct sock *unix_seq_idx(struct seq_file *seq, loff_t pos)
+ {
++	struct unix_iter_state *iter = seq->private;
+ 	loff_t off = 0;
+ 	struct sock *s;
+ 
+ 	for (s = first_unix_socket(&iter->i); s; s = next_unix_socket(&iter->i, s)) {
+-		if (s->sk_net != iter->p.net)
++		if (sock_net(s) != seq_file_net(seq))
+ 			continue;
+ 		if (off == pos)
+ 			return s;
+@@ -2035,9 +2040,8 @@ static struct sock *unix_seq_idx(struct unix_iter_state *iter, loff_t pos)
+ static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
+ 	__acquires(unix_table_lock)
+ {
+-	struct unix_iter_state *iter = seq->private;
+ 	spin_lock(&unix_table_lock);
+-	return *pos ? unix_seq_idx(iter, *pos - 1) : ((void *) 1);
++	return *pos ? unix_seq_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+ }
+ 
+ static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+@@ -2046,11 +2050,11 @@ static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ 	struct sock *sk = v;
+ 	++*pos;
+ 
+-	if (v == (void *)1)
++	if (v == SEQ_START_TOKEN)
+ 		sk = first_unix_socket(&iter->i);
+ 	else
+ 		sk = next_unix_socket(&iter->i, sk);
+-	while (sk && (sk->sk_net != iter->p.net))
++	while (sk && (sock_net(sk) != seq_file_net(seq)))
+ 		sk = next_unix_socket(&iter->i, sk);
+ 	return sk;
+ }
+@@ -2064,7 +2068,7 @@ static void unix_seq_stop(struct seq_file *seq, void *v)
+ static int unix_seq_show(struct seq_file *seq, void *v)
+ {
+ 
+-	if (v == (void *)1)
++	if (v == SEQ_START_TOKEN)
+ 		seq_puts(seq, "Num       RefCount Protocol Flags    Type St "
+ 			 "Inode Path\n");
+ 	else {
+@@ -2176,7 +2180,7 @@ static int __init af_unix_init(void)
+ 	rc = proto_register(&unix_proto, 1);
+ 	if (rc != 0) {
+ 		printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		goto out;
+ 	}
+ 
+@@ -2193,7 +2197,11 @@ static void __exit af_unix_exit(void)
+ 	unregister_pernet_subsys(&unix_net_ops);
+ }
+ 
+-module_init(af_unix_init);
++/* Earlier than device_initcall() so that other drivers invoking
++   request_module() don't end up in a loop when modprobe tries
++   to use a UNIX socket. But later than subsys_initcall() because
++   we depend on stuff initialised there */
++fs_initcall(af_unix_init);
+ module_exit(af_unix_exit);
+ 
+ MODULE_LICENSE("GPL");
+diff --git a/net/wireless/Makefile b/net/wireless/Makefile
+index 65710a4..b9f943c 100644
+--- a/net/wireless/Makefile
++++ b/net/wireless/Makefile
+@@ -1,5 +1,5 @@
+ obj-$(CONFIG_WIRELESS_EXT) += wext.o
+ obj-$(CONFIG_CFG80211) += cfg80211.o
+ 
+-cfg80211-y += core.o sysfs.o radiotap.o
++cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
+ cfg80211-$(CONFIG_NL80211) += nl80211.o
+diff --git a/net/wireless/core.c b/net/wireless/core.c
+index cfc5fc5..80afacd 100644
+--- a/net/wireless/core.c
++++ b/net/wireless/core.c
+@@ -232,6 +232,47 @@ int wiphy_register(struct wiphy *wiphy)
+ {
+ 	struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
+ 	int res;
++	enum ieee80211_band band;
++	struct ieee80211_supported_band *sband;
++	bool have_band = false;
++	int i;
++
++	/* sanity check supported bands/channels */
++	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
++		sband = wiphy->bands[band];
++		if (!sband)
++			continue;
++
++		sband->band = band;
++
++		if (!sband->n_channels || !sband->n_bitrates) {
++			WARN_ON(1);
++			return -EINVAL;
++		}
++
++		for (i = 0; i < sband->n_channels; i++) {
++			sband->channels[i].orig_flags =
++				sband->channels[i].flags;
++			sband->channels[i].orig_mag =
++				sband->channels[i].max_antenna_gain;
++			sband->channels[i].orig_mpwr =
++				sband->channels[i].max_power;
++			sband->channels[i].band = band;
++		}
++
++		have_band = true;
++	}
++
++	if (!have_band) {
++		WARN_ON(1);
++		return -EINVAL;
++	}
++
++	/* check and set up bitrates */
++	ieee80211_set_bitrate_flags(wiphy);
++
++	/* set up regulatory info */
++	wiphy_update_regulatory(wiphy);
+ 
+ 	mutex_lock(&cfg80211_drv_mutex);
+ 
+diff --git a/net/wireless/core.h b/net/wireless/core.h
+index eb0f846..7a02c35 100644
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -78,4 +78,7 @@ extern void cfg80211_dev_free(struct cfg80211_registered_device *drv);
+ extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv,
+ 			       char *newname);
+ 
++void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
++void wiphy_update_regulatory(struct wiphy *wiphy);
++
+ #endif /* __NET_WIRELESS_CORE_H */
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index f68a5c8..2bdd4dd 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -81,7 +81,12 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
+ 	[NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
+ 	[NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
+ 					       .len = NL80211_MAX_SUPP_RATES },
++	[NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
+ 	[NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
++	[NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
++	[NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
++				.len = IEEE80211_MAX_MESH_ID_LEN },
++	[NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
+ };
+ 
+ /* message building helper */
+@@ -98,6 +103,13 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
+ 			      struct cfg80211_registered_device *dev)
+ {
+ 	void *hdr;
++	struct nlattr *nl_bands, *nl_band;
++	struct nlattr *nl_freqs, *nl_freq;
++	struct nlattr *nl_rates, *nl_rate;
++	enum ieee80211_band band;
++	struct ieee80211_channel *chan;
++	struct ieee80211_rate *rate;
++	int i;
+ 
+ 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
+ 	if (!hdr)
+@@ -105,6 +117,73 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
+ 
+ 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
+ 	NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
++
++	nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
++	if (!nl_bands)
++		goto nla_put_failure;
++
++	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
++		if (!dev->wiphy.bands[band])
++			continue;
++
++		nl_band = nla_nest_start(msg, band);
++		if (!nl_band)
++			goto nla_put_failure;
++
++		/* add frequencies */
++		nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
++		if (!nl_freqs)
++			goto nla_put_failure;
++
++		for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
++			nl_freq = nla_nest_start(msg, i);
++			if (!nl_freq)
++				goto nla_put_failure;
++
++			chan = &dev->wiphy.bands[band]->channels[i];
++			NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
++				    chan->center_freq);
++
++			if (chan->flags & IEEE80211_CHAN_DISABLED)
++				NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
++			if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
++				NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
++			if (chan->flags & IEEE80211_CHAN_NO_IBSS)
++				NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
++			if (chan->flags & IEEE80211_CHAN_RADAR)
++				NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
++
++			nla_nest_end(msg, nl_freq);
++		}
++
++		nla_nest_end(msg, nl_freqs);
++
++		/* add bitrates */
++		nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
++		if (!nl_rates)
++			goto nla_put_failure;
++
++		for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
++			nl_rate = nla_nest_start(msg, i);
++			if (!nl_rate)
++				goto nla_put_failure;
++
++			rate = &dev->wiphy.bands[band]->bitrates[i];
++			NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
++				    rate->bitrate);
++			if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
++				NLA_PUT_FLAG(msg,
++					NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
++
++			nla_nest_end(msg, nl_rate);
++		}
++
++		nla_nest_end(msg, nl_rates);
++
++		nla_nest_end(msg, nl_band);
++	}
++	nla_nest_end(msg, nl_bands);
++
+ 	return genlmsg_end(msg, hdr);
+ 
+  nla_put_failure:
+@@ -262,12 +341,45 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
+ 	return -ENOBUFS;
+ }
+ 
++static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
++	[NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
++	[NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
++	[NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
++	[NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
++	[NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
++};
++
++static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
++{
++	struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
++	int flag;
++
++	*mntrflags = 0;
++
++	if (!nla)
++		return -EINVAL;
++
++	if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
++			     nla, mntr_flags_policy))
++		return -EINVAL;
++
++	for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
++		if (flags[flag])
++			*mntrflags |= (1<<flag);
++
++	return 0;
++}
++
+ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
+ {
+ 	struct cfg80211_registered_device *drv;
++	struct vif_params params;
+ 	int err, ifindex;
+ 	enum nl80211_iftype type;
+ 	struct net_device *dev;
++	u32 flags;
++
++	memset(&params, 0, sizeof(params));
+ 
+ 	if (info->attrs[NL80211_ATTR_IFTYPE]) {
+ 		type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
+@@ -287,8 +399,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
+ 		goto unlock;
+ 	}
+ 
++	if (type == NL80211_IFTYPE_MESH_POINT &&
++	    info->attrs[NL80211_ATTR_MESH_ID]) {
++		params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
++		params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
++	}
++
+ 	rtnl_lock();
+-	err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type);
++	err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
++				  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
++				  &flags);
++	err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
++					    type, err ? NULL : &flags, &params);
+ 	rtnl_unlock();
+ 
+  unlock:
+@@ -299,8 +421,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
+ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
+ {
+ 	struct cfg80211_registered_device *drv;
++	struct vif_params params;
+ 	int err;
+ 	enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
++	u32 flags;
++
++	memset(&params, 0, sizeof(params));
+ 
+ 	if (!info->attrs[NL80211_ATTR_IFNAME])
+ 		return -EINVAL;
+@@ -320,11 +446,22 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
+ 		goto unlock;
+ 	}
+ 
++	if (type == NL80211_IFTYPE_MESH_POINT &&
++	    info->attrs[NL80211_ATTR_MESH_ID]) {
++		params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
++		params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
++	}
++
+ 	rtnl_lock();
++	err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
++				  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
++				  &flags);
+ 	err = drv->ops->add_virtual_intf(&drv->wiphy,
+-		nla_data(info->attrs[NL80211_ATTR_IFNAME]), type);
++		nla_data(info->attrs[NL80211_ATTR_IFNAME]),
++		type, err ? NULL : &flags, &params);
+ 	rtnl_unlock();
+ 
++
+  unlock:
+ 	cfg80211_put_dev(drv);
+ 	return err;
+@@ -752,10 +889,10 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
+ 
+ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
+ 				int flags, struct net_device *dev,
+-				u8 *mac_addr, struct station_stats *stats)
++				u8 *mac_addr, struct station_info *sinfo)
+ {
+ 	void *hdr;
+-	struct nlattr *statsattr;
++	struct nlattr *sinfoattr;
+ 
+ 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
+ 	if (!hdr)
+@@ -764,20 +901,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
+ 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
+ 	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
+ 
+-	statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
+-	if (!statsattr)
++	sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
++	if (!sinfoattr)
+ 		goto nla_put_failure;
+-	if (stats->filled & STATION_STAT_INACTIVE_TIME)
+-		NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
+-			    stats->inactive_time);
+-	if (stats->filled & STATION_STAT_RX_BYTES)
+-		NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
+-			    stats->rx_bytes);
+-	if (stats->filled & STATION_STAT_TX_BYTES)
+-		NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
+-			    stats->tx_bytes);
+-
+-	nla_nest_end(msg, statsattr);
++	if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
++		NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
++			    sinfo->inactive_time);
++	if (sinfo->filled & STATION_INFO_RX_BYTES)
++		NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES,
++			    sinfo->rx_bytes);
++	if (sinfo->filled & STATION_INFO_TX_BYTES)
++		NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES,
++			    sinfo->tx_bytes);
++	if (sinfo->filled & STATION_INFO_LLID)
++		NLA_PUT_U16(msg, NL80211_STA_INFO_LLID,
++			    sinfo->llid);
++	if (sinfo->filled & STATION_INFO_PLID)
++		NLA_PUT_U16(msg, NL80211_STA_INFO_PLID,
++			    sinfo->plid);
++	if (sinfo->filled & STATION_INFO_PLINK_STATE)
++		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
++			    sinfo->plink_state);
++
++	nla_nest_end(msg, sinfoattr);
+ 
+ 	return genlmsg_end(msg, hdr);
+ 
+@@ -785,17 +931,80 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
+ 	return genlmsg_cancel(msg, hdr);
+ }
+ 
++static int nl80211_dump_station(struct sk_buff *skb,
++		struct netlink_callback *cb)
++{
++	int wp_idx = 0;
++	int if_idx = 0;
++	int sta_idx = cb->args[2];
++	int wp_start = cb->args[0];
++	int if_start = cb->args[1];
++	struct station_info sinfo;
++	struct cfg80211_registered_device *dev;
++	struct wireless_dev *wdev;
++	u8 mac_addr[ETH_ALEN];
++	int err;
++	int exit = 0;
++
++	/* TODO: filter by device */
++	mutex_lock(&cfg80211_drv_mutex);
++	list_for_each_entry(dev, &cfg80211_drv_list, list) {
++		if (exit)
++			break;
++		if (++wp_idx < wp_start)
++			continue;
++		if_idx = 0;
++
++		mutex_lock(&dev->devlist_mtx);
++		list_for_each_entry(wdev, &dev->netdev_list, list) {
++			if (exit)
++				break;
++			if (++if_idx < if_start)
++				continue;
++			if (!dev->ops->dump_station)
++				continue;
++
++			for (;; ++sta_idx) {
++				rtnl_lock();
++				err = dev->ops->dump_station(&dev->wiphy,
++						wdev->netdev, sta_idx, mac_addr,
++						&sinfo);
++				rtnl_unlock();
++				if (err) {
++					sta_idx = 0;
++					break;
++				}
++				if (nl80211_send_station(skb,
++						NETLINK_CB(cb->skb).pid,
++						cb->nlh->nlmsg_seq, NLM_F_MULTI,
++						wdev->netdev, mac_addr,
++						&sinfo) < 0) {
++					exit = 1;
++					break;
++				}
++			}
++		}
++		mutex_unlock(&dev->devlist_mtx);
++	}
++	mutex_unlock(&cfg80211_drv_mutex);
++
++	cb->args[0] = wp_idx;
++	cb->args[1] = if_idx;
++	cb->args[2] = sta_idx;
++
++	return skb->len;
++}
+ 
+ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
+ {
+ 	struct cfg80211_registered_device *drv;
+ 	int err;
+ 	struct net_device *dev;
+-	struct station_stats stats;
++	struct station_info sinfo;
+ 	struct sk_buff *msg;
+ 	u8 *mac_addr = NULL;
+ 
+-	memset(&stats, 0, sizeof(stats));
++	memset(&sinfo, 0, sizeof(sinfo));
+ 
+ 	if (!info->attrs[NL80211_ATTR_MAC])
+ 		return -EINVAL;
+@@ -812,15 +1021,18 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
+ 	}
+ 
+ 	rtnl_lock();
+-	err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
++	err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
+ 	rtnl_unlock();
+ 
++	if (err)
++		goto out;
++
+ 	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ 	if (!msg)
+ 		goto out;
+ 
+ 	if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
+-				 dev, mac_addr, &stats) < 0)
++				 dev, mac_addr, &sinfo) < 0)
+ 		goto out_free;
+ 
+ 	err = genlmsg_unicast(msg, info->snd_pid);
+@@ -891,6 +1103,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
+ 				&params.station_flags))
+ 		return -EINVAL;
+ 
++	if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
++		params.plink_action =
++		    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
++
+ 	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
+ 	if (err)
+ 		return err;
+@@ -1005,6 +1221,273 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
+ 	return err;
+ }
+ 
++static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
++				int flags, struct net_device *dev,
++				u8 *dst, u8 *next_hop,
++				struct mpath_info *pinfo)
++{
++	void *hdr;
++	struct nlattr *pinfoattr;
++
++	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
++	if (!hdr)
++		return -1;
++
++	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
++	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
++	NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
++
++	pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
++	if (!pinfoattr)
++		goto nla_put_failure;
++	if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
++		NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
++			    pinfo->frame_qlen);
++	if (pinfo->filled & MPATH_INFO_DSN)
++		NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN,
++			    pinfo->dsn);
++	if (pinfo->filled & MPATH_INFO_METRIC)
++		NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
++			    pinfo->metric);
++	if (pinfo->filled & MPATH_INFO_EXPTIME)
++		NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME,
++			    pinfo->exptime);
++	if (pinfo->filled & MPATH_INFO_FLAGS)
++		NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS,
++			    pinfo->flags);
++	if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT)
++		NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
++			    pinfo->discovery_timeout);
++	if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES)
++		NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
++			    pinfo->discovery_retries);
++
++	nla_nest_end(msg, pinfoattr);
++
++	return genlmsg_end(msg, hdr);
++
++ nla_put_failure:
++	return genlmsg_cancel(msg, hdr);
++}
++
++static int nl80211_dump_mpath(struct sk_buff *skb,
++		struct netlink_callback *cb)
++{
++	int wp_idx = 0;
++	int if_idx = 0;
++	int sta_idx = cb->args[2];
++	int wp_start = cb->args[0];
++	int if_start = cb->args[1];
++	struct mpath_info pinfo;
++	struct cfg80211_registered_device *dev;
++	struct wireless_dev *wdev;
++	u8 dst[ETH_ALEN];
++	u8 next_hop[ETH_ALEN];
++	int err;
++	int exit = 0;
++
++	/* TODO: filter by device */
++	mutex_lock(&cfg80211_drv_mutex);
++	list_for_each_entry(dev, &cfg80211_drv_list, list) {
++		if (exit)
++			break;
++		if (++wp_idx < wp_start)
++			continue;
++		if_idx = 0;
++
++		mutex_lock(&dev->devlist_mtx);
++		list_for_each_entry(wdev, &dev->netdev_list, list) {
++			if (exit)
++				break;
++			if (++if_idx < if_start)
++				continue;
++			if (!dev->ops->dump_mpath)
++				continue;
++
++			for (;; ++sta_idx) {
++				rtnl_lock();
++				err = dev->ops->dump_mpath(&dev->wiphy,
++						wdev->netdev, sta_idx, dst,
++						next_hop, &pinfo);
++				rtnl_unlock();
++				if (err) {
++					sta_idx = 0;
++					break;
++				}
++				if (nl80211_send_mpath(skb,
++						NETLINK_CB(cb->skb).pid,
++						cb->nlh->nlmsg_seq, NLM_F_MULTI,
++						wdev->netdev, dst, next_hop,
++						&pinfo) < 0) {
++					exit = 1;
++					break;
++				}
++			}
++		}
++		mutex_unlock(&dev->devlist_mtx);
++	}
++	mutex_unlock(&cfg80211_drv_mutex);
++
++	cb->args[0] = wp_idx;
++	cb->args[1] = if_idx;
++	cb->args[2] = sta_idx;
++
++	return skb->len;
++}
++
++static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
++{
++	struct cfg80211_registered_device *drv;
++	int err;
++	struct net_device *dev;
++	struct mpath_info pinfo;
++	struct sk_buff *msg;
++	u8 *dst = NULL;
++	u8 next_hop[ETH_ALEN];
++
++	memset(&pinfo, 0, sizeof(pinfo));
++
++	if (!info->attrs[NL80211_ATTR_MAC])
++		return -EINVAL;
++
++	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
++
++	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
++	if (err)
++		return err;
++
++	if (!drv->ops->get_mpath) {
++		err = -EOPNOTSUPP;
++		goto out;
++	}
++
++	rtnl_lock();
++	err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
++	rtnl_unlock();
++
++	if (err)
++		goto out;
++
++	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
++	if (!msg)
++		goto out;
++
++	if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
++				 dev, dst, next_hop, &pinfo) < 0)
++		goto out_free;
++
++	err = genlmsg_unicast(msg, info->snd_pid);
++	goto out;
++
++ out_free:
++	nlmsg_free(msg);
++
++ out:
++	cfg80211_put_dev(drv);
++	dev_put(dev);
++	return err;
++}
++
++static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
++{
++	struct cfg80211_registered_device *drv;
++	int err;
++	struct net_device *dev;
++	u8 *dst = NULL;
++	u8 *next_hop = NULL;
++
++	if (!info->attrs[NL80211_ATTR_MAC])
++		return -EINVAL;
++
++	if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
++		return -EINVAL;
++
++	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
++	next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
++
++	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
++	if (err)
++		return err;
++
++	if (!drv->ops->change_mpath) {
++		err = -EOPNOTSUPP;
++		goto out;
++	}
++
++	rtnl_lock();
++	err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
++	rtnl_unlock();
++
++ out:
++	cfg80211_put_dev(drv);
++	dev_put(dev);
++	return err;
++}
++static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
++{
++	struct cfg80211_registered_device *drv;
++	int err;
++	struct net_device *dev;
++	u8 *dst = NULL;
++	u8 *next_hop = NULL;
++
++	if (!info->attrs[NL80211_ATTR_MAC])
++		return -EINVAL;
++
++	if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
++		return -EINVAL;
++
++	dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
++	next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
++
++	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
++	if (err)
++		return err;
++
++	if (!drv->ops->add_mpath) {
++		err = -EOPNOTSUPP;
++		goto out;
++	}
++
++	rtnl_lock();
++	err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
++	rtnl_unlock();
++
++ out:
++	cfg80211_put_dev(drv);
++	dev_put(dev);
++	return err;
++}
++
++static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
++{
++	struct cfg80211_registered_device *drv;
++	int err;
++	struct net_device *dev;
++	u8 *dst = NULL;
++
++	if (info->attrs[NL80211_ATTR_MAC])
++		dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
++
++	err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
++	if (err)
++		return err;
++
++	if (!drv->ops->del_mpath) {
++		err = -EOPNOTSUPP;
++		goto out;
++	}
++
++	rtnl_lock();
++	err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
++	rtnl_unlock();
++
++ out:
++	cfg80211_put_dev(drv);
++	dev_put(dev);
++	return err;
++}
++
+ static struct genl_ops nl80211_ops[] = {
+ 	{
+ 		.cmd = NL80211_CMD_GET_WIPHY,
+@@ -1089,7 +1572,7 @@ static struct genl_ops nl80211_ops[] = {
+ 	{
+ 		.cmd = NL80211_CMD_GET_STATION,
+ 		.doit = nl80211_get_station,
+-		/* TODO: implement dumpit */
++		.dumpit = nl80211_dump_station,
+ 		.policy = nl80211_policy,
+ 		.flags = GENL_ADMIN_PERM,
+ 	},
+@@ -1111,6 +1594,31 @@ static struct genl_ops nl80211_ops[] = {
+ 		.policy = nl80211_policy,
+ 		.flags = GENL_ADMIN_PERM,
+ 	},
++	{
++		.cmd = NL80211_CMD_GET_MPATH,
++		.doit = nl80211_get_mpath,
++		.dumpit = nl80211_dump_mpath,
++		.policy = nl80211_policy,
++		.flags = GENL_ADMIN_PERM,
++	},
++	{
++		.cmd = NL80211_CMD_SET_MPATH,
++		.doit = nl80211_set_mpath,
++		.policy = nl80211_policy,
++		.flags = GENL_ADMIN_PERM,
++	},
++	{
++		.cmd = NL80211_CMD_NEW_MPATH,
++		.doit = nl80211_new_mpath,
++		.policy = nl80211_policy,
++		.flags = GENL_ADMIN_PERM,
++	},
++	{
++		.cmd = NL80211_CMD_DEL_MPATH,
++		.doit = nl80211_del_mpath,
++		.policy = nl80211_policy,
++		.flags = GENL_ADMIN_PERM,
++	},
+ };
+ 
+ /* multicast groups */
+diff --git a/net/wireless/reg.c b/net/wireless/reg.c
+new file mode 100644
+index 0000000..185488d
+--- /dev/null
++++ b/net/wireless/reg.c
+@@ -0,0 +1,162 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ * Copyright 2007	Johannes Berg <johannes at sipsolutions.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/*
++ * This regulatory domain control implementation is highly incomplete, it
++ * only exists for the purpose of not regressing mac80211.
++ *
++ * For now, drivers can restrict the set of allowed channels by either
++ * not registering those channels or setting the IEEE80211_CHAN_DISABLED
++ * flag; that flag will only be *set* by this code, never *cleared.
++ *
++ * The usual implementation is for a driver to read a device EEPROM to
++ * determine which regulatory domain it should be operating under, then
++ * looking up the allowable channels in a driver-local table and finally
++ * registering those channels in the wiphy structure.
++ *
++ * Alternatively, drivers that trust the regulatory domain control here
++ * will register a complete set of capabilities and the control code
++ * will restrict the set by setting the IEEE80211_CHAN_* flags.
++ */
++#include <linux/kernel.h>
++#include <net/wireless.h>
++#include "core.h"
++
++static char *ieee80211_regdom = "US";
++module_param(ieee80211_regdom, charp, 0444);
++MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
++
++struct ieee80211_channel_range {
++	short start_freq;
++	short end_freq;
++	int max_power;
++	int max_antenna_gain;
++	u32 flags;
++};
++
++struct ieee80211_regdomain {
++	const char *code;
++	const struct ieee80211_channel_range *ranges;
++	int n_ranges;
++};
++
++#define RANGE_PWR(_start, _end, _pwr, _ag, _flags)	\
++	{ _start, _end, _pwr, _ag, _flags }
++
++
++/*
++ * Ideally, in the future, these definitions will be loaded from a
++ * userspace table via some daemon.
++ */
++static const struct ieee80211_channel_range ieee80211_US_channels[] = {
++	/* IEEE 802.11b/g, channels 1..11 */
++	RANGE_PWR(2412, 2462, 27, 6, 0),
++	/* IEEE 802.11a, channel 36*/
++	RANGE_PWR(5180, 5180, 23, 6, 0),
++	/* IEEE 802.11a, channel 40*/
++	RANGE_PWR(5200, 5200, 23, 6, 0),
++	/* IEEE 802.11a, channel 44*/
++	RANGE_PWR(5220, 5220, 23, 6, 0),
++	/* IEEE 802.11a, channels 48..64 */
++	RANGE_PWR(5240, 5320, 23, 6, 0),
++	/* IEEE 802.11a, channels 149..165, outdoor */
++	RANGE_PWR(5745, 5825, 30, 6, 0),
++};
++
++static const struct ieee80211_channel_range ieee80211_JP_channels[] = {
++	/* IEEE 802.11b/g, channels 1..14 */
++	RANGE_PWR(2412, 2484, 20, 6, 0),
++	/* IEEE 802.11a, channels 34..48 */
++	RANGE_PWR(5170, 5240, 20, 6, IEEE80211_CHAN_PASSIVE_SCAN),
++	/* IEEE 802.11a, channels 52..64 */
++	RANGE_PWR(5260, 5320, 20, 6, IEEE80211_CHAN_NO_IBSS |
++				     IEEE80211_CHAN_RADAR),
++};
++
++#define REGDOM(_code)							\
++	{								\
++		.code = __stringify(_code),				\
++		.ranges = ieee80211_ ##_code## _channels,		\
++		.n_ranges = ARRAY_SIZE(ieee80211_ ##_code## _channels),	\
++	}
++
++static const struct ieee80211_regdomain ieee80211_regdoms[] = {
++	REGDOM(US),
++	REGDOM(JP),
++};
++
++
++static const struct ieee80211_regdomain *get_regdom(void)
++{
++	static const struct ieee80211_channel_range
++	ieee80211_world_channels[] = {
++		/* IEEE 802.11b/g, channels 1..11 */
++		RANGE_PWR(2412, 2462, 27, 6, 0),
++	};
++	static const struct ieee80211_regdomain regdom_world = REGDOM(world);
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(ieee80211_regdoms); i++)
++		if (strcmp(ieee80211_regdom, ieee80211_regdoms[i].code) == 0)
++			return &ieee80211_regdoms[i];
++
++	return &regdom_world;
++}
++
++
++static void handle_channel(struct ieee80211_channel *chan,
++			   const struct ieee80211_regdomain *rd)
++{
++	int i;
++	u32 flags = chan->orig_flags;
++	const struct ieee80211_channel_range *rg = NULL;
++
++	for (i = 0; i < rd->n_ranges; i++) {
++		if (rd->ranges[i].start_freq <= chan->center_freq &&
++		    chan->center_freq <= rd->ranges[i].end_freq) {
++			rg = &rd->ranges[i];
++			break;
++		}
++	}
++
++	if (!rg) {
++		/* not found */
++		flags |= IEEE80211_CHAN_DISABLED;
++		chan->flags = flags;
++		return;
++	}
++
++	chan->flags = flags;
++	chan->max_antenna_gain = min(chan->orig_mag,
++					 rg->max_antenna_gain);
++	if (chan->orig_mpwr)
++		chan->max_power = min(chan->orig_mpwr, rg->max_power);
++	else
++		chan->max_power = rg->max_power;
++}
++
++static void handle_band(struct ieee80211_supported_band *sband,
++			const struct ieee80211_regdomain *rd)
++{
++	int i;
++
++	for (i = 0; i < sband->n_channels; i++)
++		handle_channel(&sband->channels[i], rd);
++}
++
++void wiphy_update_regulatory(struct wiphy *wiphy)
++{
++	enum ieee80211_band band;
++	const struct ieee80211_regdomain *rd = get_regdom();
++
++	for (band = 0; band < IEEE80211_NUM_BANDS; band++)
++		if (wiphy->bands[band])
++			handle_band(wiphy->bands[band], rd);
++}
+diff --git a/net/wireless/util.c b/net/wireless/util.c
+new file mode 100644
+index 0000000..f544246
+--- /dev/null
++++ b/net/wireless/util.c
+@@ -0,0 +1,121 @@
++/*
++ * Wireless utility functions
++ *
++ * Copyright 2007	Johannes Berg <johannes at sipsolutions.net>
++ */
++#include <net/wireless.h>
++#include <asm/bitops.h>
++#include "core.h"
++
++int ieee80211_channel_to_frequency(int chan)
++{
++	if (chan < 14)
++		return 2407 + chan * 5;
++
++	if (chan == 14)
++		return 2484;
++
++	/* FIXME: 802.11j 17.3.8.3.2 */
++	return (chan + 1000) * 5;
++}
++EXPORT_SYMBOL(ieee80211_channel_to_frequency);
++
++int ieee80211_frequency_to_channel(int freq)
++{
++	if (freq == 2484)
++		return 14;
++
++	if (freq < 2484)
++		return (freq - 2407) / 5;
++
++	/* FIXME: 802.11j 17.3.8.3.2 */
++	return freq/5 - 1000;
++}
++EXPORT_SYMBOL(ieee80211_frequency_to_channel);
++
++struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
++						  int freq)
++{
++	enum ieee80211_band band;
++	struct ieee80211_supported_band *sband;
++	int i;
++
++	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
++		sband = wiphy->bands[band];
++
++		if (!sband)
++			continue;
++
++		for (i = 0; i < sband->n_channels; i++) {
++			if (sband->channels[i].center_freq == freq)
++				return &sband->channels[i];
++		}
++	}
++
++	return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_channel);
++
++static void set_mandatory_flags_band(struct ieee80211_supported_band *sband,
++				     enum ieee80211_band band)
++{
++	int i, want;
++
++	switch (band) {
++	case IEEE80211_BAND_5GHZ:
++		want = 3;
++		for (i = 0; i < sband->n_bitrates; i++) {
++			if (sband->bitrates[i].bitrate == 60 ||
++			    sband->bitrates[i].bitrate == 120 ||
++			    sband->bitrates[i].bitrate == 240) {
++				sband->bitrates[i].flags |=
++					IEEE80211_RATE_MANDATORY_A;
++				want--;
++			}
++		}
++		WARN_ON(want);
++		break;
++	case IEEE80211_BAND_2GHZ:
++		want = 7;
++		for (i = 0; i < sband->n_bitrates; i++) {
++			if (sband->bitrates[i].bitrate == 10) {
++				sband->bitrates[i].flags |=
++					IEEE80211_RATE_MANDATORY_B |
++					IEEE80211_RATE_MANDATORY_G;
++				want--;
++			}
++
++			if (sband->bitrates[i].bitrate == 20 ||
++			    sband->bitrates[i].bitrate == 55 ||
++			    sband->bitrates[i].bitrate == 110 ||
++			    sband->bitrates[i].bitrate == 60 ||
++			    sband->bitrates[i].bitrate == 120 ||
++			    sband->bitrates[i].bitrate == 240) {
++				sband->bitrates[i].flags |=
++					IEEE80211_RATE_MANDATORY_G;
++				want--;
++			}
++
++			if (sband->bitrates[i].bitrate != 10 &&
++			    sband->bitrates[i].bitrate != 20 &&
++			    sband->bitrates[i].bitrate != 55 &&
++			    sband->bitrates[i].bitrate != 110)
++				sband->bitrates[i].flags |=
++					IEEE80211_RATE_ERP_G;
++		}
++		WARN_ON(want != 0 && want != 3 && want != 6);
++		break;
++	case IEEE80211_NUM_BANDS:
++		WARN_ON(1);
++		break;
++	}
++}
++
++void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
++{
++	enum ieee80211_band band;
++
++	for (band = 0; band < IEEE80211_NUM_BANDS; band++)
++		if (wiphy->bands[band])
++			set_mandatory_flags_band(wiphy->bands[band], band);
++}
+diff --git a/net/wireless/wext.c b/net/wireless/wext.c
+index 2c569b6..947188a 100644
+--- a/net/wireless/wext.c
++++ b/net/wireless/wext.c
+@@ -1157,7 +1157,7 @@ static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
+ 	struct sk_buff *skb;
+ 	int err;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return;
+ 
+ 	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
+index 339ca4a..6ba67c5 100644
+--- a/net/x25/af_x25.c
++++ b/net/x25/af_x25.c
+@@ -191,7 +191,7 @@ static int x25_device_event(struct notifier_block *this, unsigned long event,
+ 	struct net_device *dev = ptr;
+ 	struct x25_neigh *nb;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (dev->type == ARPHRD_X25
+@@ -549,7 +549,7 @@ static struct sock *x25_make_new(struct sock *osk)
+ 	if (osk->sk_type != SOCK_SEQPACKET)
+ 		goto out;
+ 
+-	if ((sk = x25_alloc_socket(osk->sk_net)) == NULL)
++	if ((sk = x25_alloc_socket(sock_net(osk))) == NULL)
+ 		goto out;
+ 
+ 	x25 = x25_sk(sk);
+diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
+index f0679d2..3ff206c 100644
+--- a/net/x25/x25_dev.c
++++ b/net/x25/x25_dev.c
+@@ -95,7 +95,7 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev,
+ 	struct sk_buff *nskb;
+ 	struct x25_neigh *nb;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		goto drop;
+ 
+ 	nskb = skb_copy(skb, GFP_ATOMIC);
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+index 9fc4c31..e0c0390 100644
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -46,6 +46,7 @@ EXPORT_SYMBOL(xfrm_cfg_mutex);
+ 
+ static DEFINE_RWLOCK(xfrm_policy_lock);
+ 
++static struct list_head xfrm_policy_bytype[XFRM_POLICY_TYPE_MAX];
+ unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
+ EXPORT_SYMBOL(xfrm_policy_count);
+ 
+@@ -96,25 +97,52 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
+ 	return 0;
+ }
+ 
++static inline struct dst_entry *__xfrm_dst_lookup(int tos,
++						  xfrm_address_t *saddr,
++						  xfrm_address_t *daddr,
++						  int family)
++{
++	struct xfrm_policy_afinfo *afinfo;
++	struct dst_entry *dst;
++
++	afinfo = xfrm_policy_get_afinfo(family);
++	if (unlikely(afinfo == NULL))
++		return ERR_PTR(-EAFNOSUPPORT);
++
++	dst = afinfo->dst_lookup(tos, saddr, daddr);
++
++	xfrm_policy_put_afinfo(afinfo);
++
++	return dst;
++}
++
+ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos,
++						xfrm_address_t *prev_saddr,
++						xfrm_address_t *prev_daddr,
+ 						int family)
+ {
+ 	xfrm_address_t *saddr = &x->props.saddr;
+ 	xfrm_address_t *daddr = &x->id.daddr;
+-	struct xfrm_policy_afinfo *afinfo;
+ 	struct dst_entry *dst;
+ 
+-	if (x->type->flags & XFRM_TYPE_LOCAL_COADDR)
++	if (x->type->flags & XFRM_TYPE_LOCAL_COADDR) {
+ 		saddr = x->coaddr;
+-	if (x->type->flags & XFRM_TYPE_REMOTE_COADDR)
++		daddr = prev_daddr;
++	}
++	if (x->type->flags & XFRM_TYPE_REMOTE_COADDR) {
++		saddr = prev_saddr;
+ 		daddr = x->coaddr;
++	}
+ 
+-	afinfo = xfrm_policy_get_afinfo(family);
+-	if (unlikely(afinfo == NULL))
+-		return ERR_PTR(-EAFNOSUPPORT);
++	dst = __xfrm_dst_lookup(tos, saddr, daddr, family);
++
++	if (!IS_ERR(dst)) {
++		if (prev_saddr != saddr)
++			memcpy(prev_saddr, saddr,  sizeof(*prev_saddr));
++		if (prev_daddr != daddr)
++			memcpy(prev_daddr, daddr,  sizeof(*prev_daddr));
++	}
+ 
+-	dst = afinfo->dst_lookup(tos, saddr, daddr);
+-	xfrm_policy_put_afinfo(afinfo);
+ 	return dst;
+ }
+ 
+@@ -208,6 +236,7 @@ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp)
+ 	policy = kzalloc(sizeof(struct xfrm_policy), gfp);
+ 
+ 	if (policy) {
++		INIT_LIST_HEAD(&policy->bytype);
+ 		INIT_HLIST_NODE(&policy->bydst);
+ 		INIT_HLIST_NODE(&policy->byidx);
+ 		rwlock_init(&policy->lock);
+@@ -230,7 +259,11 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
+ 	if (del_timer(&policy->timer))
+ 		BUG();
+ 
+-	security_xfrm_policy_free(policy);
++	write_lock_bh(&xfrm_policy_lock);
++	list_del(&policy->bytype);
++	write_unlock_bh(&xfrm_policy_lock);
++
++	security_xfrm_policy_free(policy->security);
+ 	kfree(policy);
+ }
+ EXPORT_SYMBOL(xfrm_policy_destroy);
+@@ -584,6 +617,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
+ 	policy->curlft.use_time = 0;
+ 	if (!mod_timer(&policy->timer, jiffies + HZ))
+ 		xfrm_pol_hold(policy);
++	list_add_tail(&policy->bytype, &xfrm_policy_bytype[policy->type]);
+ 	write_unlock_bh(&xfrm_policy_lock);
+ 
+ 	if (delpol)
+@@ -642,7 +676,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
+ 		    xfrm_sec_ctx_match(ctx, pol->security)) {
+ 			xfrm_pol_hold(pol);
+ 			if (delete) {
+-				*err = security_xfrm_policy_delete(pol);
++				*err = security_xfrm_policy_delete(
++								pol->security);
+ 				if (*err) {
+ 					write_unlock_bh(&xfrm_policy_lock);
+ 					return pol;
+@@ -684,7 +719,8 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
+ 		if (pol->type == type && pol->index == id) {
+ 			xfrm_pol_hold(pol);
+ 			if (delete) {
+-				*err = security_xfrm_policy_delete(pol);
++				*err = security_xfrm_policy_delete(
++								pol->security);
+ 				if (*err) {
+ 					write_unlock_bh(&xfrm_policy_lock);
+ 					return pol;
+@@ -722,7 +758,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
+ 				     &xfrm_policy_inexact[dir], bydst) {
+ 			if (pol->type != type)
+ 				continue;
+-			err = security_xfrm_policy_delete(pol);
++			err = security_xfrm_policy_delete(pol->security);
+ 			if (err) {
+ 				xfrm_audit_policy_delete(pol, 0,
+ 							 audit_info->loginuid,
+@@ -736,7 +772,8 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
+ 					     bydst) {
+ 				if (pol->type != type)
+ 					continue;
+-				err = security_xfrm_policy_delete(pol);
++				err = security_xfrm_policy_delete(
++								pol->security);
+ 				if (err) {
+ 					xfrm_audit_policy_delete(pol, 0,
+ 							audit_info->loginuid,
+@@ -822,57 +859,60 @@ out:
+ }
+ EXPORT_SYMBOL(xfrm_policy_flush);
+ 
+-int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*),
++int xfrm_policy_walk(struct xfrm_policy_walk *walk,
++		     int (*func)(struct xfrm_policy *, int, int, void*),
+ 		     void *data)
+ {
+-	struct xfrm_policy *pol, *last = NULL;
+-	struct hlist_node *entry;
+-	int dir, last_dir = 0, count, error;
++	struct xfrm_policy *old, *pol, *last = NULL;
++	int error = 0;
+ 
++	if (walk->type >= XFRM_POLICY_TYPE_MAX &&
++	    walk->type != XFRM_POLICY_TYPE_ANY)
++		return -EINVAL;
++
++	if (walk->policy == NULL && walk->count != 0)
++		return 0;
++
++	old = pol = walk->policy;
++	walk->policy = NULL;
+ 	read_lock_bh(&xfrm_policy_lock);
+-	count = 0;
+ 
+-	for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
+-		struct hlist_head *table = xfrm_policy_bydst[dir].table;
+-		int i;
++	for (; walk->cur_type < XFRM_POLICY_TYPE_MAX; walk->cur_type++) {
++		if (walk->type != walk->cur_type &&
++		    walk->type != XFRM_POLICY_TYPE_ANY)
++			continue;
+ 
+-		hlist_for_each_entry(pol, entry,
+-				     &xfrm_policy_inexact[dir], bydst) {
+-			if (pol->type != type)
++		if (pol == NULL) {
++			pol = list_first_entry(&xfrm_policy_bytype[walk->cur_type],
++					       struct xfrm_policy, bytype);
++		}
++		list_for_each_entry_from(pol, &xfrm_policy_bytype[walk->cur_type], bytype) {
++			if (pol->dead)
+ 				continue;
+ 			if (last) {
+-				error = func(last, last_dir % XFRM_POLICY_MAX,
+-					     count, data);
+-				if (error)
++				error = func(last, xfrm_policy_id2dir(last->index),
++					     walk->count, data);
++				if (error) {
++					xfrm_pol_hold(last);
++					walk->policy = last;
+ 					goto out;
+-			}
+-			last = pol;
+-			last_dir = dir;
+-			count++;
+-		}
+-		for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
+-			hlist_for_each_entry(pol, entry, table + i, bydst) {
+-				if (pol->type != type)
+-					continue;
+-				if (last) {
+-					error = func(last, last_dir % XFRM_POLICY_MAX,
+-						     count, data);
+-					if (error)
+-						goto out;
+ 				}
+-				last = pol;
+-				last_dir = dir;
+-				count++;
+ 			}
++			last = pol;
++			walk->count++;
+ 		}
++		pol = NULL;
+ 	}
+-	if (count == 0) {
++	if (walk->count == 0) {
+ 		error = -ENOENT;
+ 		goto out;
+ 	}
+-	error = func(last, last_dir % XFRM_POLICY_MAX, 0, data);
++	if (last)
++		error = func(last, xfrm_policy_id2dir(last->index), 0, data);
+ out:
+ 	read_unlock_bh(&xfrm_policy_lock);
++	if (old != NULL)
++		xfrm_pol_put(old);
+ 	return error;
+ }
+ EXPORT_SYMBOL(xfrm_policy_walk);
+@@ -894,7 +934,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
+ 
+ 	match = xfrm_selector_match(sel, fl, family);
+ 	if (match)
+-		ret = security_xfrm_policy_lookup(pol, fl->secid, dir);
++		ret = security_xfrm_policy_lookup(pol->security, fl->secid,
++						  dir);
+ 
+ 	return ret;
+ }
+@@ -1011,8 +1052,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
+ 		int err = 0;
+ 
+ 		if (match) {
+-			err = security_xfrm_policy_lookup(pol, fl->secid,
+-					policy_to_flow_dir(dir));
++			err = security_xfrm_policy_lookup(pol->security,
++						      fl->secid,
++						      policy_to_flow_dir(dir));
+ 			if (!err)
+ 				xfrm_pol_hold(pol);
+ 			else if (err == -ESRCH)
+@@ -1101,7 +1143,8 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
+ 
+ 	if (newp) {
+ 		newp->selector = old->selector;
+-		if (security_xfrm_policy_clone(old, newp)) {
++		if (security_xfrm_policy_clone(old->security,
++					       &newp->security)) {
+ 			kfree(newp);
+ 			return NULL;  /* ENOMEM */
+ 		}
+@@ -1344,6 +1387,9 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
+ 	int trailer_len = 0;
+ 	int tos;
+ 	int family = policy->selector.family;
++	xfrm_address_t saddr, daddr;
++
++	xfrm_flowi_addr_get(fl, &saddr, &daddr, family);
+ 
+ 	tos = xfrm_get_tos(fl, family);
+ 	err = tos;
+@@ -1374,7 +1420,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
+ 
+ 		if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
+ 			family = xfrm[i]->props.family;
+-			dst = xfrm_dst_lookup(xfrm[i], tos, family);
++			dst = xfrm_dst_lookup(xfrm[i], tos, &saddr, &daddr,
++					      family);
+ 			err = PTR_ERR(dst);
+ 			if (IS_ERR(dst))
+ 				goto put_states;
+@@ -1772,7 +1819,7 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
+ 		(x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
+ 		(x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
+ 		x->props.mode == tmpl->mode &&
+-		((tmpl->aalgos & (1<<x->props.aalgo)) ||
++		(tmpl->allalgs || (tmpl->aalgos & (1<<x->props.aalgo)) ||
+ 		 !(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) &&
+ 		!(x->props.mode != XFRM_MODE_TRANSPORT &&
+ 		  xfrm_state_addr_cmp(tmpl, x, family));
+@@ -2038,7 +2085,7 @@ static int stale_bundle(struct dst_entry *dst)
+ void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
+ {
+ 	while ((dst = dst->child) && dst->xfrm && dst->dev == dev) {
+-		dst->dev = dev->nd_net->loopback_dev;
++		dst->dev = dev_net(dev)->loopback_dev;
+ 		dev_hold(dst->dev);
+ 		dev_put(dev);
+ 	}
+@@ -2309,7 +2356,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
+ {
+ 	struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	switch (event) {
+@@ -2365,6 +2412,9 @@ static void __init xfrm_policy_init(void)
+ 			panic("XFRM: failed to allocate bydst hash\n");
+ 	}
+ 
++	for (dir = 0; dir < XFRM_POLICY_TYPE_MAX; dir++)
++		INIT_LIST_HEAD(&xfrm_policy_bytype[dir]);
++
+ 	INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task);
+ 	register_netdevice_notifier(&xfrm_dev_notifier);
+ }
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 58f1f93..5dcc10b 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -50,6 +50,7 @@ static DEFINE_SPINLOCK(xfrm_state_lock);
+  * Main use is finding SA after policy selected tunnel or transport mode.
+  * Also, it can be used by ah/esp icmp error handler to find offending SA.
+  */
++static LIST_HEAD(xfrm_state_all);
+ static struct hlist_head *xfrm_state_bydst __read_mostly;
+ static struct hlist_head *xfrm_state_bysrc __read_mostly;
+ static struct hlist_head *xfrm_state_byspi __read_mostly;
+@@ -512,6 +513,7 @@ struct xfrm_state *xfrm_state_alloc(void)
+ 	if (x) {
+ 		atomic_set(&x->refcnt, 1);
+ 		atomic_set(&x->tunnel_users, 0);
++		INIT_LIST_HEAD(&x->all);
+ 		INIT_HLIST_NODE(&x->bydst);
+ 		INIT_HLIST_NODE(&x->bysrc);
+ 		INIT_HLIST_NODE(&x->byspi);
+@@ -537,6 +539,10 @@ void __xfrm_state_destroy(struct xfrm_state *x)
+ {
+ 	BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
+ 
++	spin_lock_bh(&xfrm_state_lock);
++	list_del(&x->all);
++	spin_unlock_bh(&xfrm_state_lock);
++
+ 	spin_lock_bh(&xfrm_state_gc_lock);
+ 	hlist_add_head(&x->bydst, &xfrm_state_gc_list);
+ 	spin_unlock_bh(&xfrm_state_gc_lock);
+@@ -913,6 +919,8 @@ static void __xfrm_state_insert(struct xfrm_state *x)
+ 
+ 	x->genid = ++xfrm_state_genid;
+ 
++	list_add_tail(&x->all, &xfrm_state_all);
++
+ 	h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
+ 			  x->props.reqid, x->props.family);
+ 	hlist_add_head(&x->bydst, xfrm_state_bydst+h);
+@@ -1522,36 +1530,47 @@ unlock:
+ }
+ EXPORT_SYMBOL(xfrm_alloc_spi);
+ 
+-int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
++int xfrm_state_walk(struct xfrm_state_walk *walk,
++		    int (*func)(struct xfrm_state *, int, void*),
+ 		    void *data)
+ {
+-	int i;
+-	struct xfrm_state *x, *last = NULL;
+-	struct hlist_node *entry;
+-	int count = 0;
++	struct xfrm_state *old, *x, *last = NULL;
+ 	int err = 0;
+ 
++	if (walk->state == NULL && walk->count != 0)
++		return 0;
++
++	old = x = walk->state;
++	walk->state = NULL;
+ 	spin_lock_bh(&xfrm_state_lock);
+-	for (i = 0; i <= xfrm_state_hmask; i++) {
+-		hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
+-			if (!xfrm_id_proto_match(x->id.proto, proto))
+-				continue;
+-			if (last) {
+-				err = func(last, count, data);
+-				if (err)
+-					goto out;
++	if (x == NULL)
++		x = list_first_entry(&xfrm_state_all, struct xfrm_state, all);
++	list_for_each_entry_from(x, &xfrm_state_all, all) {
++		if (x->km.state == XFRM_STATE_DEAD)
++			continue;
++		if (!xfrm_id_proto_match(x->id.proto, walk->proto))
++			continue;
++		if (last) {
++			err = func(last, walk->count, data);
++			if (err) {
++				xfrm_state_hold(last);
++				walk->state = last;
++				goto out;
+ 			}
+-			last = x;
+-			count++;
+ 		}
++		last = x;
++		walk->count++;
+ 	}
+-	if (count == 0) {
++	if (walk->count == 0) {
+ 		err = -ENOENT;
+ 		goto out;
+ 	}
+-	err = func(last, 0, data);
++	if (last)
++		err = func(last, 0, data);
+ out:
+ 	spin_unlock_bh(&xfrm_state_lock);
++	if (old != NULL)
++		xfrm_state_put(old);
+ 	return err;
+ }
+ EXPORT_SYMBOL(xfrm_state_walk);
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index 019d21d..22a30ae 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -529,8 +529,6 @@ struct xfrm_dump_info {
+ 	struct sk_buff *out_skb;
+ 	u32 nlmsg_seq;
+ 	u16 nlmsg_flags;
+-	int start_idx;
+-	int this_idx;
+ };
+ 
+ static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb)
+@@ -597,9 +595,6 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
+ 	struct nlmsghdr *nlh;
+ 	int err;
+ 
+-	if (sp->this_idx < sp->start_idx)
+-		goto out;
+-
+ 	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
+ 			XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags);
+ 	if (nlh == NULL)
+@@ -612,8 +607,6 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
+ 		goto nla_put_failure;
+ 
+ 	nlmsg_end(skb, nlh);
+-out:
+-	sp->this_idx++;
+ 	return 0;
+ 
+ nla_put_failure:
+@@ -621,18 +614,32 @@ nla_put_failure:
+ 	return err;
+ }
+ 
++static int xfrm_dump_sa_done(struct netlink_callback *cb)
++{
++	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
++	xfrm_state_walk_done(walk);
++	return 0;
++}
++
+ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
+ {
++	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
+ 	struct xfrm_dump_info info;
+ 
++	BUILD_BUG_ON(sizeof(struct xfrm_state_walk) >
++		     sizeof(cb->args) - sizeof(cb->args[0]));
++
+ 	info.in_skb = cb->skb;
+ 	info.out_skb = skb;
+ 	info.nlmsg_seq = cb->nlh->nlmsg_seq;
+ 	info.nlmsg_flags = NLM_F_MULTI;
+-	info.this_idx = 0;
+-	info.start_idx = cb->args[0];
+-	(void) xfrm_state_walk(0, dump_one_state, &info);
+-	cb->args[0] = info.this_idx;
++
++	if (!cb->args[0]) {
++		cb->args[0] = 1;
++		xfrm_state_walk_init(walk, 0);
++	}
++
++	(void) xfrm_state_walk(walk, dump_one_state, &info);
+ 
+ 	return skb->len;
+ }
+@@ -651,7 +658,6 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
+ 	info.out_skb = skb;
+ 	info.nlmsg_seq = seq;
+ 	info.nlmsg_flags = 0;
+-	info.this_idx = info.start_idx = 0;
+ 
+ 	if (dump_one_state(x, 0, &info)) {
+ 		kfree_skb(skb);
+@@ -953,7 +959,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs
+ 		return 0;
+ 
+ 	uctx = nla_data(rt);
+-	return security_xfrm_policy_alloc(pol, uctx);
++	return security_xfrm_policy_alloc(&pol->security, uctx);
+ }
+ 
+ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
+@@ -975,6 +981,8 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
+ 		t->aalgos = ut->aalgos;
+ 		t->ealgos = ut->ealgos;
+ 		t->calgos = ut->calgos;
++		/* If all masks are ~0, then we allow all algorithms. */
++		t->allalgs = !~(t->aalgos & t->ealgos & t->calgos);
+ 		t->encap_family = ut->family;
+ 	}
+ }
+@@ -1137,7 +1145,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ 			      NETLINK_CB(skb).sid);
+ 
+ 	if (err) {
+-		security_xfrm_policy_free(xp);
++		security_xfrm_policy_free(xp->security);
+ 		kfree(xp);
+ 		return err;
+ 	}
+@@ -1229,9 +1237,6 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
+ 	struct sk_buff *skb = sp->out_skb;
+ 	struct nlmsghdr *nlh;
+ 
+-	if (sp->this_idx < sp->start_idx)
+-		goto out;
+-
+ 	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
+ 			XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags);
+ 	if (nlh == NULL)
+@@ -1247,8 +1252,6 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
+ 		goto nlmsg_failure;
+ 
+ 	nlmsg_end(skb, nlh);
+-out:
+-	sp->this_idx++;
+ 	return 0;
+ 
+ nlmsg_failure:
+@@ -1256,21 +1259,33 @@ nlmsg_failure:
+ 	return -EMSGSIZE;
+ }
+ 
++static int xfrm_dump_policy_done(struct netlink_callback *cb)
++{
++	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
++
++	xfrm_policy_walk_done(walk);
++	return 0;
++}
++
+ static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
+ {
++	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
+ 	struct xfrm_dump_info info;
+ 
++	BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) >
++		     sizeof(cb->args) - sizeof(cb->args[0]));
++
+ 	info.in_skb = cb->skb;
+ 	info.out_skb = skb;
+ 	info.nlmsg_seq = cb->nlh->nlmsg_seq;
+ 	info.nlmsg_flags = NLM_F_MULTI;
+-	info.this_idx = 0;
+-	info.start_idx = cb->args[0];
+-	(void) xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_one_policy, &info);
+-#ifdef CONFIG_XFRM_SUB_POLICY
+-	(void) xfrm_policy_walk(XFRM_POLICY_TYPE_SUB, dump_one_policy, &info);
+-#endif
+-	cb->args[0] = info.this_idx;
++
++	if (!cb->args[0]) {
++		cb->args[0] = 1;
++		xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
++	}
++
++	(void) xfrm_policy_walk(walk, dump_one_policy, &info);
+ 
+ 	return skb->len;
+ }
+@@ -1290,7 +1305,6 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
+ 	info.out_skb = skb;
+ 	info.nlmsg_seq = seq;
+ 	info.nlmsg_flags = 0;
+-	info.this_idx = info.start_idx = 0;
+ 
+ 	if (dump_one_policy(xp, dir, 0, &info) < 0) {
+ 		kfree_skb(skb);
+@@ -1325,22 +1339,23 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ 		xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err);
+ 	else {
+ 		struct nlattr *rt = attrs[XFRMA_SEC_CTX];
+-		struct xfrm_policy tmp;
++		struct xfrm_sec_ctx *ctx;
+ 
+ 		err = verify_sec_ctx_len(attrs);
+ 		if (err)
+ 			return err;
+ 
+-		memset(&tmp, 0, sizeof(struct xfrm_policy));
++		ctx = NULL;
+ 		if (rt) {
+ 			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
+ 
+-			if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
++			err = security_xfrm_policy_alloc(&ctx, uctx);
++			if (err)
+ 				return err;
+ 		}
+-		xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
++		xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx,
+ 					   delete, &err);
+-		security_xfrm_policy_free(&tmp);
++		security_xfrm_policy_free(ctx);
+ 	}
+ 	if (xp == NULL)
+ 		return -ENOENT;
+@@ -1560,26 +1575,26 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
+ 		xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err);
+ 	else {
+ 		struct nlattr *rt = attrs[XFRMA_SEC_CTX];
+-		struct xfrm_policy tmp;
++		struct xfrm_sec_ctx *ctx;
+ 
+ 		err = verify_sec_ctx_len(attrs);
+ 		if (err)
+ 			return err;
+ 
+-		memset(&tmp, 0, sizeof(struct xfrm_policy));
++		ctx = NULL;
+ 		if (rt) {
+ 			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
+ 
+-			if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
++			err = security_xfrm_policy_alloc(&ctx, uctx);
++			if (err)
+ 				return err;
+ 		}
+-		xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
+-					   0, &err);
+-		security_xfrm_policy_free(&tmp);
++		xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, 0, &err);
++		security_xfrm_policy_free(ctx);
+ 	}
+-
+ 	if (xp == NULL)
+ 		return -ENOENT;
++
+ 	read_lock(&xp->lock);
+ 	if (xp->dead) {
+ 		read_unlock(&xp->lock);
+@@ -1888,15 +1903,18 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
+ static struct xfrm_link {
+ 	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
+ 	int (*dump)(struct sk_buff *, struct netlink_callback *);
++	int (*done)(struct netlink_callback *);
+ } xfrm_dispatch[XFRM_NR_MSGTYPES] = {
+ 	[XFRM_MSG_NEWSA       - XFRM_MSG_BASE] = { .doit = xfrm_add_sa        },
+ 	[XFRM_MSG_DELSA       - XFRM_MSG_BASE] = { .doit = xfrm_del_sa        },
+ 	[XFRM_MSG_GETSA       - XFRM_MSG_BASE] = { .doit = xfrm_get_sa,
+-						   .dump = xfrm_dump_sa       },
++						   .dump = xfrm_dump_sa,
++						   .done = xfrm_dump_sa_done  },
+ 	[XFRM_MSG_NEWPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_add_policy    },
+ 	[XFRM_MSG_DELPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy    },
+ 	[XFRM_MSG_GETPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy,
+-						   .dump = xfrm_dump_policy   },
++						   .dump = xfrm_dump_policy,
++						   .done = xfrm_dump_policy_done },
+ 	[XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
+ 	[XFRM_MSG_ACQUIRE     - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire   },
+ 	[XFRM_MSG_EXPIRE      - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire },
+@@ -1935,7 +1953,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ 		if (link->dump == NULL)
+ 			return -EINVAL;
+ 
+-		return netlink_dump_start(xfrm_nl, skb, nlh, link->dump, NULL);
++		return netlink_dump_start(xfrm_nl, skb, nlh, link->dump, link->done);
+ 	}
+ 
+ 	err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
+diff --git a/samples/firmware_class/firmware_sample_driver.c b/samples/firmware_class/firmware_sample_driver.c
+new file mode 100644
+index 0000000..11114f3
+--- /dev/null
++++ b/samples/firmware_class/firmware_sample_driver.c
+@@ -0,0 +1,121 @@
++/*
++ * firmware_sample_driver.c -
++ *
++ * Copyright (c) 2003 Manuel Estrada Sainz
++ *
++ * Sample code on how to use request_firmware() from drivers.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/string.h>
++#include <linux/firmware.h>
++
++static struct device ghost_device = {
++	.bus_id    = "ghost0",
++};
++
++
++static void sample_firmware_load(char *firmware, int size)
++{
++	u8 buf[size+1];
++	memcpy(buf, firmware, size);
++	buf[size] = '\0';
++	printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf);
++}
++
++static void sample_probe_default(void)
++{
++	/* uses the default method to get the firmware */
++	const struct firmware *fw_entry;
++	int retval;
++
++	printk(KERN_INFO "firmware_sample_driver: "
++		"a ghost device got inserted :)\n");
++
++	retval = request_firmware(&fw_entry, "sample_driver_fw", &ghost_device);
++	if (retval) {
++		printk(KERN_ERR
++		       "firmware_sample_driver: Firmware not available\n");
++		return;
++	}
++
++	sample_firmware_load(fw_entry->data, fw_entry->size);
++
++	release_firmware(fw_entry);
++
++	/* finish setting up the device */
++}
++
++static void sample_probe_specific(void)
++{
++	int retval;
++	/* Uses some specific hotplug support to get the firmware from
++	 * userspace  directly into the hardware, or via some sysfs file */
++
++	/* NOTE: This currently doesn't work */
++
++	printk(KERN_INFO "firmware_sample_driver: "
++		"a ghost device got inserted :)\n");
++
++	retval = request_firmware(NULL, "sample_driver_fw", &ghost_device);
++	if (retval) {
++		printk(KERN_ERR
++		       "firmware_sample_driver: Firmware load failed\n");
++		return;
++	}
++
++	/* request_firmware blocks until userspace finished, so at
++	 * this point the firmware should be already in the device */
++
++	/* finish setting up the device */
++}
++
++static void sample_probe_async_cont(const struct firmware *fw, void *context)
++{
++	if (!fw) {
++		printk(KERN_ERR
++		       "firmware_sample_driver: firmware load failed\n");
++		return;
++	}
++
++	printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n",
++	       (char *)context);
++	sample_firmware_load(fw->data, fw->size);
++}
++
++static void sample_probe_async(void)
++{
++	/* Let's say that I can't sleep */
++	int error;
++	error = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
++					"sample_driver_fw", &ghost_device,
++					"my device pointer",
++					sample_probe_async_cont);
++	if (error)
++		printk(KERN_ERR "firmware_sample_driver:"
++		       " request_firmware_nowait failed\n");
++}
++
++static int sample_init(void)
++{
++	device_initialize(&ghost_device);
++	/* since there is no real hardware insertion I just call the
++	 * sample probe functions here */
++	sample_probe_specific();
++	sample_probe_default();
++	sample_probe_async();
++	return 0;
++}
++
++static void __exit sample_exit(void)
++{
++}
++
++module_init(sample_init);
++module_exit(sample_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/samples/firmware_class/firmware_sample_firmware_class.c b/samples/firmware_class/firmware_sample_firmware_class.c
+new file mode 100644
+index 0000000..9392116
+--- /dev/null
++++ b/samples/firmware_class/firmware_sample_firmware_class.c
+@@ -0,0 +1,204 @@
++/*
++ * firmware_sample_firmware_class.c -
++ *
++ * Copyright (c) 2003 Manuel Estrada Sainz
++ *
++ * NOTE: This is just a probe of concept, if you think that your driver would
++ * be well served by this mechanism please contact me first.
++ *
++ * DON'T USE THIS CODE AS IS
++ *
++ */
++
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/timer.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/firmware.h>
++
++
++MODULE_AUTHOR("Manuel Estrada Sainz");
++MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
++MODULE_LICENSE("GPL");
++
++static inline struct class_device *to_class_dev(struct kobject *obj)
++{
++	return container_of(obj, struct class_device, kobj);
++}
++
++static inline
++struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
++{
++	return container_of(_attr, struct class_device_attribute, attr);
++}
++
++struct firmware_priv {
++	char fw_id[FIRMWARE_NAME_MAX];
++	s32 loading:2;
++	u32 abort:1;
++};
++
++static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf)
++{
++	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++	return sprintf(buf, "%d\n", fw_priv->loading);
++}
++
++static ssize_t firmware_loading_store(struct class_device *class_dev,
++				      const char *buf, size_t count)
++{
++	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++	int prev_loading = fw_priv->loading;
++
++	fw_priv->loading = simple_strtol(buf, NULL, 10);
++
++	switch (fw_priv->loading) {
++	case -1:
++		/* abort load an panic */
++		break;
++	case 1:
++		/* setup load */
++		break;
++	case 0:
++		if (prev_loading == 1) {
++			/* finish load and get the device back to working
++			 * state */
++		}
++		break;
++	}
++
++	return count;
++}
++static CLASS_DEVICE_ATTR(loading, 0644,
++			 firmware_loading_show, firmware_loading_store);
++
++static ssize_t firmware_data_read(struct kobject *kobj,
++				  struct bin_attribute *bin_attr,
++				  char *buffer, loff_t offset, size_t count)
++{
++	struct class_device *class_dev = to_class_dev(kobj);
++	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++
++	/* read from the devices firmware memory */
++
++	return count;
++}
++static ssize_t firmware_data_write(struct kobject *kobj,
++				   struct bin_attribute *bin_attr,
++				   char *buffer, loff_t offset, size_t count)
++{
++	struct class_device *class_dev = to_class_dev(kobj);
++	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++
++	/* write to the devices firmware memory */
++
++	return count;
++}
++static struct bin_attribute firmware_attr_data = {
++	.attr = {.name = "data", .mode = 0644},
++	.size = 0,
++	.read = firmware_data_read,
++	.write = firmware_data_write,
++};
++static int fw_setup_class_device(struct class_device *class_dev,
++				 const char *fw_name,
++				 struct device *device)
++{
++	int retval;
++	struct firmware_priv *fw_priv;
++
++	fw_priv = kzalloc(sizeof(struct firmware_priv),	GFP_KERNEL);
++	if (!fw_priv) {
++		retval = -ENOMEM;
++		goto out;
++	}
++
++	memset(class_dev, 0, sizeof(*class_dev));
++
++	strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
++	fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0';
++
++	strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE);
++	class_dev->class_id[BUS_ID_SIZE-1] = '\0';
++	class_dev->dev = device;
++
++	class_dev->class = &firmware_class,
++	class_set_devdata(class_dev, fw_priv);
++	retval = class_device_register(class_dev);
++	if (retval) {
++		printk(KERN_ERR "%s: class_device_register failed\n",
++		       __func__);
++		goto error_free_fw_priv;
++	}
++
++	retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data);
++	if (retval) {
++		printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
++		       __func__);
++		goto error_unreg_class_dev;
++	}
++
++	retval = class_device_create_file(class_dev,
++					  &class_device_attr_loading);
++	if (retval) {
++		printk(KERN_ERR "%s: class_device_create_file failed\n",
++		       __func__);
++		goto error_remove_data;
++	}
++
++	goto out;
++
++error_remove_data:
++	sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
++error_unreg_class_dev:
++	class_device_unregister(class_dev);
++error_free_fw_priv:
++	kfree(fw_priv);
++out:
++	return retval;
++}
++static void fw_remove_class_device(struct class_device *class_dev)
++{
++	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++
++	class_device_remove_file(class_dev, &class_device_attr_loading);
++	sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
++	class_device_unregister(class_dev);
++}
++
++static struct class_device *class_dev;
++
++static struct device my_device = {
++	.bus_id    = "my_dev0",
++};
++
++static int __init firmware_sample_init(void)
++{
++	int error;
++
++	device_initialize(&my_device);
++	class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
++	if (!class_dev)
++		return -ENOMEM;
++
++	error = fw_setup_class_device(class_dev, "my_firmware_image",
++				      &my_device);
++	if (error) {
++		kfree(class_dev);
++		return error;
++	}
++	return 0;
++
++}
++static void __exit firmware_sample_exit(void)
++{
++	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++	fw_remove_class_device(class_dev);
++	kfree(fw_priv);
++	kfree(class_dev);
++}
++
++module_init(firmware_sample_init);
++module_exit(firmware_sample_exit);
+diff --git a/scripts/Makefile.build b/scripts/Makefile.build
+index 67fb453..277cfe0 100644
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -27,12 +27,12 @@ ccflags-y  :=
+ cppflags-y :=
+ ldflags-y  :=
+ 
+-# Read .config if it exist, otherwise ignore
++# Read auto.conf if it exists, otherwise ignore
+ -include include/config/auto.conf
+ 
+ include scripts/Kbuild.include
+ 
+-# For backward compatibility check that these variables does not change
++# For backward compatibility check that these variables do not change
+ save-cflags := $(CFLAGS)
+ 
+ # The filename Kbuild has precedence over Makefile
+@@ -55,7 +55,7 @@ hostprogs-y += $(host-progs)
+ endif
+ endif
+ 
+-# Do not include host rules unles needed
++# Do not include host rules unless needed
+ ifneq ($(hostprogs-y)$(hostprogs-m),)
+ include scripts/Makefile.host
+ endif
+diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
+index 2c64710..6f89fbb 100644
+--- a/scripts/Makefile.clean
++++ b/scripts/Makefile.clean
+@@ -37,7 +37,7 @@ subdir-ymn      := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
+ 
+ subdir-ymn	:= $(addprefix $(obj)/,$(subdir-ymn))
+ 
+-# build a list of files to remove, usually releative to the current
++# build a list of files to remove, usually relative to the current
+ # directory
+ 
+ __clean-files	:= $(extra-y) $(always)                  \
+diff --git a/scripts/Makefile.host b/scripts/Makefile.host
+index 6943a7a..1ac414f 100644
+--- a/scripts/Makefile.host
++++ b/scripts/Makefile.host
+@@ -3,9 +3,9 @@
+ # Binaries are used during the compilation of the kernel, for example
+ # to preprocess a data file.
+ #
+-# Both C and C++ is supported, but preferred language is C for such utilities.
++# Both C and C++ are supported, but preferred language is C for such utilities.
+ #
+-# Samle syntax (see Documentation/kbuild/makefile.txt for reference)
++# Sample syntax (see Documentation/kbuild/makefiles.txt for reference)
+ # hostprogs-y := bin2hex
+ # Will compile bin2hex.c and create an executable named bin2hex
+ #
+@@ -23,10 +23,10 @@
+ # hostprogs-y := conf
+ # conf-objs  := conf.o libkconfig.so
+ # libkconfig-objs := expr.o type.o
+-# Will create a shared library named libkconfig.so that consist of
+-# expr.o and type.o (they are both compiled as C code and the object file
++# Will create a shared library named libkconfig.so that consists of
++# expr.o and type.o (they are both compiled as C code and the object files
+ # are made as position independent code).
+-# conf.c is compiled as a c program, and conf.o is linked together with
++# conf.c is compiled as a C program, and conf.o is linked together with
+ # libkconfig.so as the executable conf.
+ # Note: Shared libraries consisting of C++ files are not supported
+ 
+@@ -61,7 +61,7 @@ host-cobjs	:= $(filter-out %.so,$(host-cobjs))
+ host-cshobjs	:= $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
+ 
+ # output directory for programs/.o files
+-# hostprogs-y := tools/build may have been specified. Retreive directory
++# hostprogs-y := tools/build may have been specified. Retrieve directory
+ host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
+ # directory of .o files from prog-objs notation
+ host-objdirs += $(foreach f,$(host-cmulti),                  \
+diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
+index 2d20640..24b3c8f 100644
+--- a/scripts/Makefile.modpost
++++ b/scripts/Makefile.modpost
+@@ -42,6 +42,13 @@ _modpost: __modpost
+ 
+ include include/config/auto.conf
+ include scripts/Kbuild.include
++
++ifneq ($(KBUILD_EXTMOD),)
++# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
++include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
++             $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
++endif
++
+ include scripts/Makefile.lib
+ 
+ kernelsymfile := $(objtree)/Module.symvers
+@@ -69,6 +76,7 @@ modpost = scripts/mod/modpost                    \
+  $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,)       \
+  $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile)   \
+  $(if $(KBUILD_EXTMOD),-I $(modulesymfile))      \
++ $(if $(iKBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(EXTRA_SYMBOLS))) \
+  $(if $(KBUILD_EXTMOD),-o $(modulesymfile))      \
+  $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S)      \
+  $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
+diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
+index 58a9494..64ec4b8 100755
+--- a/scripts/checkpatch.pl
++++ b/scripts/checkpatch.pl
+@@ -1889,6 +1889,13 @@ sub process {
+ 				WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
+ 			}
+ 		}
++# check for needless usb_free_urb() checks
++		if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
++			my $expr = $1;
++			if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) {
++				WARN("usb_free_urb(NULL) is safe this check is probabally not required\n" . $hereprev);
++			}
++		}
+ 
+ # warn about #ifdefs in C files
+ #		if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
+diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
+index 32e8c5a..fa1a7d5 100644
+--- a/scripts/kconfig/Makefile
++++ b/scripts/kconfig/Makefile
+@@ -36,10 +36,10 @@ update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
+ 	    --output $(obj)/config.pot
+ 	$(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot
+ 	$(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch
+-	$(Q)(for i in `ls arch/`;                        \
++	$(Q)(for i in `ls arch/*/Kconfig`;               \
+ 	    do                                           \
+ 		echo "  GEN $$i";                        \
+-		$(obj)/kxgettext arch/$$i/Kconfig        \
++		$(obj)/kxgettext $$i                     \
+ 		     >> $(obj)/config.pot;               \
+ 	    done )
+ 	$(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \
+diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
+index 348d868..769b69d 100644
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -328,19 +328,52 @@ static int do_pnp_entry(const char *filename,
+ 	return 1;
+ }
+ 
+-/* looks like: "pnp:cCdD..." */
+-static int do_pnp_card_entry(const char *filename,
+-			struct pnp_card_device_id *id, char *alias)
++/* looks like: "pnp:dD" for every device of the card */
++static void do_pnp_card_entries(void *symval, unsigned long size,
++				struct module *mod)
+ {
+-	int i;
++	const unsigned long id_size = sizeof(struct pnp_card_device_id);
++	const unsigned int count = (size / id_size)-1;
++	const struct pnp_card_device_id *cards = symval;
++	unsigned int i;
+ 
+-	sprintf(alias, "pnp:c%s", id->id);
+-	for (i = 0; i < PNP_MAX_DEVICES; i++) {
+-		if (! *id->devs[i].id)
+-			break;
+-		sprintf(alias + strlen(alias), "d%s", id->devs[i].id);
++	device_id_check(mod->name, "pnp", size, id_size, symval);
++
++	for (i = 0; i < count; i++) {
++		unsigned int j;
++		const struct pnp_card_device_id *card = &cards[i];
++
++		for (j = 0; j < PNP_MAX_DEVICES; j++) {
++			const char *id = (char *)card->devs[j].id;
++			int i2, j2;
++			int dup = 0;
++
++			if (!id[0])
++				break;
++
++			/* find duplicate, already added value */
++			for (i2 = 0; i2 < i && !dup; i2++) {
++				const struct pnp_card_device_id *card2 = &cards[i2];
++
++				for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
++					const char *id2 = (char *)card2->devs[j2].id;
++
++					if (!id2[0])
++						break;
++
++					if (!strcmp(id, id2)) {
++						dup = 1;
++						break;
++					}
++				}
++			}
++
++			/* add an individual alias for every device entry */
++			if (!dup)
++				buf_printf(&mod->dev_table_buf,
++					   "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
++		}
+ 	}
+-	return 1;
+ }
+ 
+ /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
+@@ -634,9 +667,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
+ 			 sizeof(struct pnp_device_id), "pnp",
+ 			 do_pnp_entry, mod);
+ 	else if (sym_is(symname, "__mod_pnp_card_device_table"))
+-		do_table(symval, sym->st_size,
+-			 sizeof(struct pnp_card_device_id), "pnp_card",
+-			 do_pnp_card_entry, mod);
++		do_pnp_card_entries(symval, sym->st_size, mod);
+ 	else if (sym_is(symname, "__mod_pcmcia_device_table"))
+ 		do_table(symval, sym->st_size,
+ 			 sizeof(struct pcmcia_device_id), "pcmcia",
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index 110cf24..f8b42ab 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -1552,6 +1552,10 @@ static void read_symbols(char *modname)
+ 	}
+ 
+ 	license = get_modinfo(info.modinfo, info.modinfo_len, "license");
++	if (!license && !is_vmlinux(modname))
++		fatal("modpost: missing MODULE_LICENSE() in %s\n"
++		      "see include/linux/module.h for "
++		      "more information\n", modname);
+ 	while (license) {
+ 		if (license_is_gpl_compatible(license))
+ 			mod->gpl_compatible = 1;
+@@ -2015,6 +2019,11 @@ static void write_markers(const char *fname)
+ 	write_if_changed(&buf, fname);
+ }
+ 
++struct ext_sym_list {
++	struct ext_sym_list *next;
++	const char *file;
++};
++
+ int main(int argc, char **argv)
+ {
+ 	struct module *mod;
+@@ -2025,8 +2034,10 @@ int main(int argc, char **argv)
+ 	char *markers_write = NULL;
+ 	int opt;
+ 	int err;
++	struct ext_sym_list *extsym_iter;
++	struct ext_sym_list *extsym_start = NULL;
+ 
+-	while ((opt = getopt(argc, argv, "i:I:cmsSo:awM:K:")) != -1) {
++	while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) {
+ 		switch (opt) {
+ 		case 'i':
+ 			kernel_read = optarg;
+@@ -2038,6 +2049,14 @@ int main(int argc, char **argv)
+ 		case 'c':
+ 			cross_build = 1;
+ 			break;
++		case 'e':
++			external_module = 1;
++			extsym_iter =
++			   NOFAIL(malloc(sizeof(*extsym_iter)));
++			extsym_iter->next = extsym_start;
++			extsym_iter->file = optarg;
++			extsym_start = extsym_iter;
++			break;
+ 		case 'm':
+ 			modversions = 1;
+ 			break;
+@@ -2071,6 +2090,12 @@ int main(int argc, char **argv)
+ 		read_dump(kernel_read, 1);
+ 	if (module_read)
+ 		read_dump(module_read, 0);
++	while (extsym_start) {
++		read_dump(extsym_start->file, 0);
++		extsym_iter = extsym_start->next;
++		free(extsym_start);
++		extsym_start = extsym_iter;
++	}
+ 
+ 	while (optind < argc)
+ 		read_symbols(argv[optind++]);
+diff --git a/security/Kconfig b/security/Kconfig
+index 5dfc206..49b51f9 100644
+--- a/security/Kconfig
++++ b/security/Kconfig
+@@ -113,10 +113,12 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
+ 	  from userspace allocation.  Keeping a user from writing to low pages
+ 	  can help reduce the impact of kernel NULL pointer bugs.
+ 
+-	  For most users with lots of address space a value of 65536 is
+-	  reasonable and should cause no problems.  Programs which use vm86
+-	  functionality would either need additional permissions from either
+-	  the LSM or the capabilities module or have this protection disabled.
++	  For most ia64, ppc64 and x86 users with lots of address space
++	  a value of 65536 is reasonable and should cause no problems.
++	  On arm and other archs it should not be higher than 32768.
++	  Programs which use vm86 functionality would either need additional
++	  permissions from either the LSM or the capabilities module or have
++	  this protection disabled.
+ 
+ 	  This value can be changed after boot using the
+ 	  /proc/sys/vm/mmap_min_addr tunable.
+diff --git a/security/commoncap.c b/security/commoncap.c
+index 06d5c94..8529057 100644
+--- a/security/commoncap.c
++++ b/security/commoncap.c
+@@ -267,7 +267,7 @@ static int get_file_caps(struct linux_binprm *bprm)
+ 	rc = cap_from_disk(&vcaps, bprm, rc);
+ 	if (rc)
+ 		printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
+-			__FUNCTION__, rc, bprm->filename);
++			__func__, rc, bprm->filename);
+ 
+ out:
+ 	dput(dentry);
+@@ -302,7 +302,7 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
+ 	ret = get_file_caps(bprm);
+ 	if (ret)
+ 		printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
+-			__FUNCTION__, ret, bprm->filename);
++			__func__, ret, bprm->filename);
+ 
+ 	/*  To support inheritance of root-permissions and suid-root
+ 	 *  executables under compatibility mode, we raise all three
+diff --git a/security/dummy.c b/security/dummy.c
+index 78d8f92..b0232bb 100644
+--- a/security/dummy.c
++++ b/security/dummy.c
+@@ -196,13 +196,13 @@ static int dummy_sb_statfs (struct dentry *dentry)
+ 	return 0;
+ }
+ 
+-static int dummy_sb_mount (char *dev_name, struct nameidata *nd, char *type,
++static int dummy_sb_mount (char *dev_name, struct path *path, char *type,
+ 			   unsigned long flags, void *data)
+ {
+ 	return 0;
+ }
+ 
+-static int dummy_sb_check_sb (struct vfsmount *mnt, struct nameidata *nd)
++static int dummy_sb_check_sb (struct vfsmount *mnt, struct path *path)
+ {
+ 	return 0;
+ }
+@@ -229,17 +229,17 @@ static void dummy_sb_post_remount (struct vfsmount *mnt, unsigned long flags,
+ }
+ 
+ 
+-static void dummy_sb_post_addmount (struct vfsmount *mnt, struct nameidata *nd)
++static void dummy_sb_post_addmount (struct vfsmount *mnt, struct path *path)
+ {
+ 	return;
+ }
+ 
+-static int dummy_sb_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd)
++static int dummy_sb_pivotroot (struct path *old_path, struct path *new_path)
+ {
+ 	return 0;
+ }
+ 
+-static void dummy_sb_post_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd)
++static void dummy_sb_post_pivotroot (struct path *old_path, struct path *new_path)
+ {
+ 	return;
+ }
+@@ -424,6 +424,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
+ 	return 0;
+ }
+ 
++static void dummy_inode_getsecid(const struct inode *inode, u32 *secid)
++{
++	*secid = 0;
++}
++
+ static int dummy_file_permission (struct file *file, int mask)
+ {
+ 	return 0;
+@@ -542,7 +547,9 @@ static int dummy_task_getsid (struct task_struct *p)
+ }
+ 
+ static void dummy_task_getsecid (struct task_struct *p, u32 *secid)
+-{ }
++{
++	*secid = 0;
++}
+ 
+ static int dummy_task_setgroups (struct group_info *group_info)
+ {
+@@ -616,6 +623,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
+ 	return 0;
+ }
+ 
++static void dummy_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
++{
++	*secid = 0;
++}
++
+ static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
+ {
+ 	return 0;
+@@ -876,22 +888,23 @@ static inline void dummy_req_classify_flow(const struct request_sock *req,
+ #endif	/* CONFIG_SECURITY_NETWORK */
+ 
+ #ifdef CONFIG_SECURITY_NETWORK_XFRM
+-static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
+-		struct xfrm_user_sec_ctx *sec_ctx)
++static int dummy_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
++					    struct xfrm_user_sec_ctx *sec_ctx)
+ {
+ 	return 0;
+ }
+ 
+-static inline int dummy_xfrm_policy_clone_security(struct xfrm_policy *old, struct xfrm_policy *new)
++static inline int dummy_xfrm_policy_clone_security(struct xfrm_sec_ctx *old_ctx,
++					   struct xfrm_sec_ctx **new_ctxp)
+ {
+ 	return 0;
+ }
+ 
+-static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
++static void dummy_xfrm_policy_free_security(struct xfrm_sec_ctx *ctx)
+ {
+ }
+ 
+-static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
++static int dummy_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
+ {
+ 	return 0;
+ }
+@@ -911,7 +924,8 @@ static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
+ 	return 0;
+ }
+ 
+-static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
++static int dummy_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx,
++				    u32 sk_sid, u8 dir)
+ {
+ 	return 0;
+ }
+@@ -981,7 +995,33 @@ static inline int dummy_key_permission(key_ref_t key_ref,
+ }
+ #endif /* CONFIG_KEYS */
+ 
+-struct security_operations dummy_security_ops;
++#ifdef CONFIG_AUDIT
++static inline int dummy_audit_rule_init(u32 field, u32 op, char *rulestr,
++					void **lsmrule)
++{
++	return 0;
++}
++
++static inline int dummy_audit_rule_known(struct audit_krule *krule)
++{
++	return 0;
++}
++
++static inline int dummy_audit_rule_match(u32 secid, u32 field, u32 op,
++					 void *lsmrule,
++					 struct audit_context *actx)
++{
++	return 0;
++}
++
++static inline void dummy_audit_rule_free(void *lsmrule)
++{ }
++
++#endif /* CONFIG_AUDIT */
++
++struct security_operations dummy_security_ops = {
++	.name = "dummy",
++};
+ 
+ #define set_to_dummy_if_null(ops, function)				\
+ 	do {								\
+@@ -1058,6 +1098,7 @@ void security_fixup_ops (struct security_operations *ops)
+ 	set_to_dummy_if_null(ops, inode_getsecurity);
+ 	set_to_dummy_if_null(ops, inode_setsecurity);
+ 	set_to_dummy_if_null(ops, inode_listsecurity);
++	set_to_dummy_if_null(ops, inode_getsecid);
+ 	set_to_dummy_if_null(ops, file_permission);
+ 	set_to_dummy_if_null(ops, file_alloc_security);
+ 	set_to_dummy_if_null(ops, file_free_security);
+@@ -1094,6 +1135,7 @@ void security_fixup_ops (struct security_operations *ops)
+ 	set_to_dummy_if_null(ops, task_reparent_to_init);
+  	set_to_dummy_if_null(ops, task_to_inode);
+ 	set_to_dummy_if_null(ops, ipc_permission);
++	set_to_dummy_if_null(ops, ipc_getsecid);
+ 	set_to_dummy_if_null(ops, msg_msg_alloc_security);
+ 	set_to_dummy_if_null(ops, msg_msg_free_security);
+ 	set_to_dummy_if_null(ops, msg_queue_alloc_security);
+@@ -1168,6 +1210,11 @@ void security_fixup_ops (struct security_operations *ops)
+ 	set_to_dummy_if_null(ops, key_free);
+ 	set_to_dummy_if_null(ops, key_permission);
+ #endif	/* CONFIG_KEYS */
+-
++#ifdef CONFIG_AUDIT
++	set_to_dummy_if_null(ops, audit_rule_init);
++	set_to_dummy_if_null(ops, audit_rule_known);
++	set_to_dummy_if_null(ops, audit_rule_match);
++	set_to_dummy_if_null(ops, audit_rule_free);
++#endif
+ }
+ 
+diff --git a/security/keys/internal.h b/security/keys/internal.h
+index d36d693..7d894ef 100644
+--- a/security/keys/internal.h
++++ b/security/keys/internal.h
+@@ -22,16 +22,16 @@ void no_printk(const char *fmt, ...)
+ 
+ #ifdef __KDEBUG
+ #define kenter(FMT, ...) \
+-	printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
++	printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+ #define kleave(FMT, ...) \
+-	printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
++	printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+ #define kdebug(FMT, ...) \
+ 	printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__)
+ #else
+ #define kenter(FMT, ...) \
+-	no_printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
++	no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+ #define kleave(FMT, ...) \
+-	no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
++	no_printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+ #define kdebug(FMT, ...) \
+ 	no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
+ #endif
+diff --git a/security/root_plug.c b/security/root_plug.c
+index 870f130..6112d14 100644
+--- a/security/root_plug.c
++++ b/security/root_plug.c
+@@ -49,7 +49,7 @@ module_param(debug, bool, 0600);
+ 	do {							\
+ 		if (debug)					\
+ 			printk(KERN_DEBUG "%s: %s: " fmt ,	\
+-				MY_NAME , __FUNCTION__ , 	\
++				MY_NAME , __func__ , 	\
+ 				## arg);			\
+ 	} while (0)
+ 
+diff --git a/security/security.c b/security/security.c
+index b1387a6..8a285c7 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -17,6 +17,8 @@
+ #include <linux/kernel.h>
+ #include <linux/security.h>
+ 
++/* Boot-time LSM user choice */
++static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1];
+ 
+ /* things that live in dummy.c */
+ extern struct security_operations dummy_security_ops;
+@@ -57,7 +59,7 @@ int __init security_init(void)
+ 
+ 	if (verify(&dummy_security_ops)) {
+ 		printk(KERN_ERR "%s could not verify "
+-		       "dummy_security_ops structure.\n", __FUNCTION__);
++		       "dummy_security_ops structure.\n", __func__);
+ 		return -EIO;
+ 	}
+ 
+@@ -67,13 +69,47 @@ int __init security_init(void)
+ 	return 0;
+ }
+ 
++/* Save user chosen LSM */
++static int __init choose_lsm(char *str)
++{
++	strncpy(chosen_lsm, str, SECURITY_NAME_MAX);
++	return 1;
++}
++__setup("security=", choose_lsm);
++
++/**
++ * security_module_enable - Load given security module on boot ?
++ * @ops: a pointer to the struct security_operations that is to be checked.
++ *
++ * Each LSM must pass this method before registering its own operations
++ * to avoid security registration races. This method may also be used
++ * to check if your LSM is currently loaded during kernel initialization.
++ *
++ * Return true if:
++ *	-The passed LSM is the one chosen by user at boot time,
++ *	-or user didsn't specify a specific LSM and we're the first to ask
++ *	 for registeration permissoin,
++ *	-or the passed LSM is currently loaded.
++ * 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;
++}
++
+ /**
+  * register_security - registers a security framework with the kernel
+  * @ops: a pointer to the struct security_options that is to be registered
+  *
+  * This function is to allow a security module to register itself with the
+  * kernel security subsystem.  Some rudimentary checking is done on the @ops
+- * value passed to this function.
++ * value passed to this function. You'll need to check first if your LSM
++ * is allowed to register its @ops by calling security_module_enable(@ops).
+  *
+  * If there is already a security module registered with the kernel,
+  * an error will be returned.  Otherwise 0 is returned on success.
+@@ -82,7 +118,7 @@ int register_security(struct security_operations *ops)
+ {
+ 	if (verify(ops)) {
+ 		printk(KERN_DEBUG "%s could not verify "
+-		       "security_operations structure.\n", __FUNCTION__);
++		       "security_operations structure.\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -110,13 +146,13 @@ int mod_reg_security(const char *name, struct security_operations *ops)
+ {
+ 	if (verify(ops)) {
+ 		printk(KERN_INFO "%s could not verify "
+-		       "security operations.\n", __FUNCTION__);
++		       "security operations.\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (ops == security_ops) {
+ 		printk(KERN_INFO "%s security operations "
+-		       "already registered.\n", __FUNCTION__);
++		       "already registered.\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -260,15 +296,15 @@ int security_sb_statfs(struct dentry *dentry)
+ 	return security_ops->sb_statfs(dentry);
+ }
+ 
+-int security_sb_mount(char *dev_name, struct nameidata *nd,
++int security_sb_mount(char *dev_name, struct path *path,
+                        char *type, unsigned long flags, void *data)
+ {
+-	return security_ops->sb_mount(dev_name, nd, type, flags, data);
++	return security_ops->sb_mount(dev_name, path, type, flags, data);
+ }
+ 
+-int security_sb_check_sb(struct vfsmount *mnt, struct nameidata *nd)
++int security_sb_check_sb(struct vfsmount *mnt, struct path *path)
+ {
+-	return security_ops->sb_check_sb(mnt, nd);
++	return security_ops->sb_check_sb(mnt, path);
+ }
+ 
+ int security_sb_umount(struct vfsmount *mnt, int flags)
+@@ -291,19 +327,19 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d
+ 	security_ops->sb_post_remount(mnt, flags, data);
+ }
+ 
+-void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd)
++void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint)
+ {
+-	security_ops->sb_post_addmount(mnt, mountpoint_nd);
++	security_ops->sb_post_addmount(mnt, mountpoint);
+ }
+ 
+-int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
++int security_sb_pivotroot(struct path *old_path, struct path *new_path)
+ {
+-	return security_ops->sb_pivotroot(old_nd, new_nd);
++	return security_ops->sb_pivotroot(old_path, new_path);
+ }
+ 
+-void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
++void security_sb_post_pivotroot(struct path *old_path, struct path *new_path)
+ {
+-	security_ops->sb_post_pivotroot(old_nd, new_nd);
++	security_ops->sb_post_pivotroot(old_path, new_path);
+ }
+ 
+ int security_sb_get_mnt_opts(const struct super_block *sb,
+@@ -523,6 +559,11 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
+ 	return security_ops->inode_listsecurity(inode, buffer, buffer_size);
+ }
+ 
++void security_inode_getsecid(const struct inode *inode, u32 *secid)
++{
++	security_ops->inode_getsecid(inode, secid);
++}
++
+ int security_file_permission(struct file *file, int mask)
+ {
+ 	return security_ops->file_permission(file, mask);
+@@ -712,6 +753,11 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
+ 	return security_ops->ipc_permission(ipcp, flag);
+ }
+ 
++void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
++{
++	security_ops->ipc_getsecid(ipcp, secid);
++}
++
+ int security_msg_msg_alloc(struct msg_msg *msg)
+ {
+ 	return security_ops->msg_msg_alloc_security(msg);
+@@ -1014,26 +1060,27 @@ void security_inet_conn_established(struct sock *sk,
+ 
+ #ifdef CONFIG_SECURITY_NETWORK_XFRM
+ 
+-int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
++int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
+ {
+-	return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
++	return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx);
+ }
+ EXPORT_SYMBOL(security_xfrm_policy_alloc);
+ 
+-int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
++int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
++			      struct xfrm_sec_ctx **new_ctxp)
+ {
+-	return security_ops->xfrm_policy_clone_security(old, new);
++	return security_ops->xfrm_policy_clone_security(old_ctx, new_ctxp);
+ }
+ 
+-void security_xfrm_policy_free(struct xfrm_policy *xp)
++void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
+ {
+-	security_ops->xfrm_policy_free_security(xp);
++	security_ops->xfrm_policy_free_security(ctx);
+ }
+ EXPORT_SYMBOL(security_xfrm_policy_free);
+ 
+-int security_xfrm_policy_delete(struct xfrm_policy *xp)
++int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
+ {
+-	return security_ops->xfrm_policy_delete_security(xp);
++	return security_ops->xfrm_policy_delete_security(ctx);
+ }
+ 
+ int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
+@@ -1065,9 +1112,9 @@ void security_xfrm_state_free(struct xfrm_state *x)
+ 	security_ops->xfrm_state_free_security(x);
+ }
+ 
+-int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
++int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+ {
+-	return security_ops->xfrm_policy_lookup(xp, fl_secid, dir);
++	return security_ops->xfrm_policy_lookup(ctx, fl_secid, dir);
+ }
+ 
+ int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
+@@ -1110,3 +1157,28 @@ int security_key_permission(key_ref_t key_ref,
+ }
+ 
+ #endif	/* CONFIG_KEYS */
++
++#ifdef CONFIG_AUDIT
++
++int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
++{
++	return security_ops->audit_rule_init(field, op, rulestr, lsmrule);
++}
++
++int security_audit_rule_known(struct audit_krule *krule)
++{
++	return security_ops->audit_rule_known(krule);
++}
++
++void security_audit_rule_free(void *lsmrule)
++{
++	security_ops->audit_rule_free(lsmrule);
++}
++
++int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
++			      struct audit_context *actx)
++{
++	return security_ops->audit_rule_match(secid, field, op, lsmrule, actx);
++}
++
++#endif /* CONFIG_AUDIT */
+diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
+index 2b517d6..a436d1c 100644
+--- a/security/selinux/Kconfig
++++ b/security/selinux/Kconfig
+@@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
+ config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
+ 	int "NSA SELinux maximum supported policy format version value"
+ 	depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
+-	range 15 22
++	range 15 23
+ 	default 19
+ 	help
+ 	  This option sets the value for the maximum policy format version
+diff --git a/security/selinux/Makefile b/security/selinux/Makefile
+index 00afd85..d47fc5e 100644
+--- a/security/selinux/Makefile
++++ b/security/selinux/Makefile
+@@ -11,6 +11,7 @@ selinux-y := avc.o \
+ 	     nlmsgtab.o \
+ 	     netif.o \
+ 	     netnode.o \
++	     netport.o \
+ 	     exports.o
+ 
+ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
+diff --git a/security/selinux/avc.c b/security/selinux/avc.c
+index 187964e..95a8ef4 100644
+--- a/security/selinux/avc.c
++++ b/security/selinux/avc.c
+@@ -2,16 +2,16 @@
+  * Implementation of the kernel access vector cache (AVC).
+  *
+  * Authors:  Stephen Smalley, <sds at epoch.ncsc.mil>
+- *           James Morris <jmorris at redhat.com>
++ *	     James Morris <jmorris at redhat.com>
+  *
+  * Update:   KaiGai, Kohei <kaigai at ak.jp.nec.com>
+- *     Replaced the avc_lock spinlock by RCU.
++ *	Replaced the avc_lock spinlock by RCU.
+  *
+  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.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.
++ *	as published by the Free Software Foundation.
+  */
+ #include <linux/types.h>
+ #include <linux/stddef.h>
+@@ -44,7 +44,7 @@ static const char *class_to_string[] = {
+ #undef S_
+ };
+ 
+-#define TB_(s) static const char * s [] = {
++#define TB_(s) static const char *s[] = {
+ #define TE_(s) };
+ #define S_(s) s,
+ #include "common_perm_to_string.h"
+@@ -72,7 +72,7 @@ const struct selinux_class_perm selinux_class_perm = {
+ #define AVC_CACHE_RECLAIM		16
+ 
+ #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
+-#define avc_cache_stats_incr(field) 				\
++#define avc_cache_stats_incr(field)				\
+ do {								\
+ 	per_cpu(avc_cache_stats, get_cpu()).field++;		\
+ 	put_cpu();						\
+@@ -92,7 +92,7 @@ struct avc_entry {
+ struct avc_node {
+ 	struct avc_entry	ae;
+ 	struct list_head	list;
+-	struct rcu_head         rhead;
++	struct rcu_head		rhead;
+ };
+ 
+ struct avc_cache {
+@@ -105,8 +105,8 @@ struct avc_cache {
+ 
+ struct avc_callback_node {
+ 	int (*callback) (u32 event, u32 ssid, u32 tsid,
+-	                 u16 tclass, u32 perms,
+-	                 u32 *out_retained);
++			 u16 tclass, u32 perms,
++			 u32 *out_retained);
+ 	u32 events;
+ 	u32 ssid;
+ 	u32 tsid;
+@@ -202,7 +202,7 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla
+ 	char *scontext;
+ 	u32 scontext_len;
+ 
+- 	rc = security_sid_to_context(ssid, &scontext, &scontext_len);
++	rc = security_sid_to_context(ssid, &scontext, &scontext_len);
+ 	if (rc)
+ 		audit_log_format(ab, "ssid=%d", ssid);
+ 	else {
+@@ -306,12 +306,13 @@ static inline int avc_reclaim_node(void)
+ 	int hvalue, try, ecx;
+ 	unsigned long flags;
+ 
+-	for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++ ) {
++	for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
+ 		hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
+ 
+ 		if (!spin_trylock_irqsave(&avc_cache.slots_lock[hvalue], flags))
+ 			continue;
+ 
++		rcu_read_lock();
+ 		list_for_each_entry(node, &avc_cache.slots[hvalue], list) {
+ 			if (atomic_dec_and_test(&node->ae.used)) {
+ 				/* Recently Unused */
+@@ -319,11 +320,13 @@ static inline int avc_reclaim_node(void)
+ 				avc_cache_stats_incr(reclaims);
+ 				ecx++;
+ 				if (ecx >= AVC_CACHE_RECLAIM) {
++					rcu_read_unlock();
+ 					spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
+ 					goto out;
+ 				}
+ 			}
+ 		}
++		rcu_read_unlock();
+ 		spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
+ 	}
+ out:
+@@ -426,7 +429,7 @@ static int avc_latest_notif_update(int seqno, int is_insert)
+ 	spin_lock_irqsave(&notif_lock, flag);
+ 	if (is_insert) {
+ 		if (seqno < avc_cache.latest_notif) {
+-			printk(KERN_WARNING "avc:  seqno %d < latest_notif %d\n",
++			printk(KERN_WARNING "SELinux: avc:  seqno %d < latest_notif %d\n",
+ 			       seqno, avc_cache.latest_notif);
+ 			ret = -EAGAIN;
+ 		}
+@@ -475,7 +478,7 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_en
+ 			if (pos->ae.ssid == ssid &&
+ 			    pos->ae.tsid == tsid &&
+ 			    pos->ae.tclass == tclass) {
+-			    	avc_node_replace(node, pos);
++				avc_node_replace(node, pos);
+ 				goto found;
+ 			}
+ 		}
+@@ -526,8 +529,8 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
+  * before calling the auditing code.
+  */
+ void avc_audit(u32 ssid, u32 tsid,
+-               u16 tclass, u32 requested,
+-               struct av_decision *avd, int result, struct avc_audit_data *a)
++	       u16 tclass, u32 requested,
++	       struct av_decision *avd, int result, struct avc_audit_data *a)
+ {
+ 	struct task_struct *tsk = current;
+ 	struct inode *inode = NULL;
+@@ -541,7 +544,7 @@ void avc_audit(u32 ssid, u32 tsid,
+ 			return;
+ 	} else if (result) {
+ 		audited = denied = requested;
+-        } else {
++	} else {
+ 		audited = requested;
+ 		if (!(audited & avd->auditallow))
+ 			return;
+@@ -551,7 +554,7 @@ void avc_audit(u32 ssid, u32 tsid,
+ 	if (!ab)
+ 		return;		/* audit_panic has been called */
+ 	audit_log_format(ab, "avc:  %s ", denied ? "denied" : "granted");
+-	avc_dump_av(ab, tclass,audited);
++	avc_dump_av(ab, tclass, audited);
+ 	audit_log_format(ab, " for ");
+ 	if (a && a->tsk)
+ 		tsk = a->tsk;
+@@ -647,7 +650,7 @@ void avc_audit(u32 ssid, u32 tsid,
+ 					break;
+ 				}
+ 			}
+-			
++
+ 			switch (a->u.net.family) {
+ 			case AF_INET:
+ 				avc_print_ipv4_addr(ab, a->u.net.v4info.saddr,
+@@ -702,10 +705,10 @@ void avc_audit(u32 ssid, u32 tsid,
+  * -%ENOMEM if insufficient memory exists to add the callback.
+  */
+ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
+-                                     u16 tclass, u32 perms,
+-                                     u32 *out_retained),
+-                     u32 events, u32 ssid, u32 tsid,
+-                     u16 tclass, u32 perms)
++				     u16 tclass, u32 perms,
++				     u32 *out_retained),
++		     u32 events, u32 ssid, u32 tsid,
++		     u16 tclass, u32 perms)
+ {
+ 	struct avc_callback_node *c;
+ 	int rc = 0;
+@@ -759,10 +762,10 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass)
+ 	hvalue = avc_hash(ssid, tsid, tclass);
+ 	spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
+ 
+-	list_for_each_entry(pos, &avc_cache.slots[hvalue], list){
+-		if ( ssid==pos->ae.ssid &&
+-		     tsid==pos->ae.tsid &&
+-		     tclass==pos->ae.tclass ){
++	list_for_each_entry(pos, &avc_cache.slots[hvalue], list) {
++		if (ssid == pos->ae.ssid &&
++		    tsid == pos->ae.tsid &&
++		    tclass == pos->ae.tclass){
+ 			orig = pos;
+ 			break;
+ 		}
+@@ -821,15 +824,21 @@ int avc_ss_reset(u32 seqno)
+ 
+ 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
+ 		spin_lock_irqsave(&avc_cache.slots_lock[i], flag);
++		/*
++		 * With preemptable RCU, the outer spinlock does not
++		 * prevent RCU grace periods from ending.
++		 */
++		rcu_read_lock();
+ 		list_for_each_entry(node, &avc_cache.slots[i], list)
+ 			avc_node_delete(node);
++		rcu_read_unlock();
+ 		spin_unlock_irqrestore(&avc_cache.slots_lock[i], flag);
+ 	}
+ 
+ 	for (c = avc_callbacks; c; c = c->next) {
+ 		if (c->events & AVC_CALLBACK_RESET) {
+ 			tmprc = c->callback(AVC_CALLBACK_RESET,
+-			                    0, 0, 0, 0, NULL);
++					    0, 0, 0, 0, NULL);
+ 			/* save the first error encountered for the return
+ 			   value and continue processing the callbacks */
+ 			if (!rc)
+@@ -871,16 +880,18 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
+ 	int rc = 0;
+ 	u32 denied;
+ 
++	BUG_ON(!requested);
++
+ 	rcu_read_lock();
+ 
+ 	node = avc_lookup(ssid, tsid, tclass, requested);
+ 	if (!node) {
+ 		rcu_read_unlock();
+-		rc = security_compute_av(ssid,tsid,tclass,requested,&entry.avd);
++		rc = security_compute_av(ssid, tsid, tclass, requested, &entry.avd);
+ 		if (rc)
+ 			goto out;
+ 		rcu_read_lock();
+-		node = avc_insert(ssid,tsid,tclass,&entry);
++		node = avc_insert(ssid, tsid, tclass, &entry);
+ 	}
+ 
+ 	p_ae = node ? &node->ae : &entry;
+@@ -890,13 +901,14 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
+ 
+ 	denied = requested & ~(p_ae->avd.allowed);
+ 
+-	if (!requested || denied) {
+-		if (selinux_enforcing || (flags & AVC_STRICT))
++	if (denied) {
++		if (flags & AVC_STRICT)
+ 			rc = -EACCES;
++		else if (!selinux_enforcing || security_permissive_sid(ssid))
++			avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
++					tsid, tclass);
+ 		else
+-			if (node)
+-				avc_update_node(AVC_CALLBACK_GRANT,requested,
+-						ssid,tsid,tclass);
++			rc = -EACCES;
+ 	}
+ 
+ 	rcu_read_unlock();
+@@ -921,7 +933,7 @@ out:
+  * another -errno upon other errors.
+  */
+ int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
+-                 u32 requested, struct avc_audit_data *auditdata)
++		 u32 requested, struct avc_audit_data *auditdata)
+ {
+ 	struct av_decision avd;
+ 	int rc;
+diff --git a/security/selinux/exports.c b/security/selinux/exports.c
+index 87d2bb3..64af2d3 100644
+--- a/security/selinux/exports.c
++++ b/security/selinux/exports.c
+@@ -25,48 +25,6 @@
+ /* SECMARK reference count */
+ extern atomic_t selinux_secmark_refcount;
+ 
+-int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
+-{
+-	if (selinux_enabled)
+-		return security_sid_to_context(sid, ctx, ctxlen);
+-	else {
+-		*ctx = NULL;
+-		*ctxlen = 0;
+-	}
+-
+-	return 0;
+-}
+-
+-void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+-{
+-	if (selinux_enabled) {
+-		struct inode_security_struct *isec = inode->i_security;
+-		*sid = isec->sid;
+-		return;
+-	}
+-	*sid = 0;
+-}
+-
+-void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
+-{
+-	if (selinux_enabled) {
+-		struct ipc_security_struct *isec = ipcp->security;
+-		*sid = isec->sid;
+-		return;
+-	}
+-	*sid = 0;
+-}
+-
+-void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+-{
+-	if (selinux_enabled) {
+-		struct task_security_struct *tsec = tsk->security;
+-		*sid = tsec->sid;
+-		return;
+-	}
+-	*sid = 0;
+-}
+-
+ int selinux_string_to_sid(char *str, u32 *sid)
+ {
+ 	if (selinux_enabled)
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index d39b59c..308e2cf 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -4,22 +4,22 @@
+  *  This file contains the SELinux hook function implementations.
+  *
+  *  Authors:  Stephen Smalley, <sds at epoch.ncsc.mil>
+- *            Chris Vance, <cvance at nai.com>
+- *            Wayne Salamon, <wsalamon at nai.com>
+- *            James Morris <jmorris at redhat.com>
++ *	      Chris Vance, <cvance at nai.com>
++ *	      Wayne Salamon, <wsalamon at nai.com>
++ *	      James Morris <jmorris at redhat.com>
+  *
+  *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
+  *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.com>
+  *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+- *                          <dgoeddel at trustedcs.com>
++ *			    <dgoeddel at trustedcs.com>
+  *  Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
+- *                Paul Moore <paul.moore at hp.com>
++ *		Paul Moore <paul.moore at hp.com>
+  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
+- *                     Yuichi Nakamura <ynakam at hitachisoft.jp>
++ *		       Yuichi Nakamura <ynakam at hitachisoft.jp>
+  *
+  *	This program is free software; you can redistribute it and/or modify
+  *	it under the terms of the GNU General Public License version 2,
+- *      as published by the Free Software Foundation.
++ *	as published by the Free Software Foundation.
+  */
+ 
+ #include <linux/init.h>
+@@ -80,8 +80,10 @@
+ #include "objsec.h"
+ #include "netif.h"
+ #include "netnode.h"
++#include "netport.h"
+ #include "xfrm.h"
+ #include "netlabel.h"
++#include "audit.h"
+ 
+ #define XATTR_SELINUX_SUFFIX "selinux"
+ #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
+@@ -97,11 +99,11 @@ extern struct security_operations *security_ops;
+ atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
+ 
+ #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
+-int selinux_enforcing = 0;
++int selinux_enforcing;
+ 
+ static int __init enforcing_setup(char *str)
+ {
+-	selinux_enforcing = simple_strtol(str,NULL,0);
++	selinux_enforcing = simple_strtol(str, NULL, 0);
+ 	return 1;
+ }
+ __setup("enforcing=", enforcing_setup);
+@@ -121,13 +123,13 @@ int selinux_enabled = 1;
+ #endif
+ 
+ /* Original (dummy) security module. */
+-static struct security_operations *original_ops = NULL;
++static struct security_operations *original_ops;
+ 
+ /* Minimal support for a secondary security module,
+    just to allow the use of the dummy or capability modules.
+    The owlsm module can alternatively be used as a secondary
+    module as long as CONFIG_OWLSM_FD is not enabled. */
+-static struct security_operations *secondary_ops = NULL;
++static struct security_operations *secondary_ops;
+ 
+ /* Lists of inode and superblock security structures initialized
+    before the policy was loaded. */
+@@ -161,8 +163,7 @@ static int task_alloc_security(struct task_struct *task)
+ 	if (!tsec)
+ 		return -ENOMEM;
+ 
+-	tsec->task = task;
+-	tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
++	tsec->osid = tsec->sid = SECINITSID_UNLABELED;
+ 	task->security = tsec;
+ 
+ 	return 0;
+@@ -218,7 +219,6 @@ static int file_alloc_security(struct file *file)
+ 	if (!fsec)
+ 		return -ENOMEM;
+ 
+-	fsec->file = file;
+ 	fsec->sid = tsec->sid;
+ 	fsec->fown_sid = tsec->sid;
+ 	file->f_security = fsec;
+@@ -275,12 +275,11 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
+ 	if (!ssec)
+ 		return -ENOMEM;
+ 
+-	ssec->sk = sk;
+ 	ssec->peer_sid = SECINITSID_UNLABELED;
+ 	ssec->sid = SECINITSID_UNLABELED;
+ 	sk->sk_security = ssec;
+ 
+-	selinux_netlbl_sk_security_init(ssec, family);
++	selinux_netlbl_sk_security_reset(ssec, family);
+ 
+ 	return 0;
+ }
+@@ -324,10 +323,10 @@ enum {
+ };
+ 
+ static match_table_t tokens = {
+-	{Opt_context, "context=%s"},
+-	{Opt_fscontext, "fscontext=%s"},
+-	{Opt_defcontext, "defcontext=%s"},
+-	{Opt_rootcontext, "rootcontext=%s"},
++	{Opt_context, CONTEXT_STR "%s"},
++	{Opt_fscontext, FSCONTEXT_STR "%s"},
++	{Opt_defcontext, DEFCONTEXT_STR "%s"},
++	{Opt_rootcontext, ROOTCONTEXT_STR "%s"},
+ 	{Opt_error, NULL},
+ };
+ 
+@@ -576,8 +575,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
+ 			goto out;
+ 		}
+ 		rc = -EINVAL;
+-		printk(KERN_WARNING "Unable to set superblock options before "
+-		       "the security server is initialized\n");
++		printk(KERN_WARNING "SELinux: Unable to set superblock options "
++			"before the security server is initialized\n");
+ 		goto out;
+ 	}
+ 
+@@ -671,7 +670,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
+ 	rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
+ 	if (rc) {
+ 		printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
+-		       __FUNCTION__, sb->s_type->name, rc);
++		       __func__, sb->s_type->name, rc);
+ 		goto out;
+ 	}
+ 
+@@ -756,9 +755,18 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
+ 	int set_context =	(oldsbsec->flags & CONTEXT_MNT);
+ 	int set_rootcontext =	(oldsbsec->flags & ROOTCONTEXT_MNT);
+ 
+-	/* we can't error, we can't save the info, this shouldn't get called
+-	 * this early in the boot process. */
+-	BUG_ON(!ss_initialized);
++	/*
++	 * if the parent was able to be mounted it clearly had no special lsm
++	 * mount options.  thus we can safely put this sb on the list and deal
++	 * with it later
++	 */
++	if (!ss_initialized) {
++		spin_lock(&sb_security_lock);
++		if (list_empty(&newsbsec->list))
++			list_add(&newsbsec->list, &superblock_security_head);
++		spin_unlock(&sb_security_lock);
++		return;
++	}
+ 
+ 	/* how can we clone if the old one wasn't set up?? */
+ 	BUG_ON(!oldsbsec->initialized);
+@@ -1055,7 +1063,7 @@ static int selinux_proc_get_sid(struct proc_dir_entry *de,
+ 	int buflen, rc;
+ 	char *buffer, *path, *end;
+ 
+-	buffer = (char*)__get_free_page(GFP_KERNEL);
++	buffer = (char *)__get_free_page(GFP_KERNEL);
+ 	if (!buffer)
+ 		return -ENOMEM;
+ 
+@@ -1136,8 +1144,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
+ 			dentry = d_find_alias(inode);
+ 		}
+ 		if (!dentry) {
+-			printk(KERN_WARNING "%s:  no dentry for dev=%s "
+-			       "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
++			printk(KERN_WARNING "SELinux: %s:  no dentry for dev=%s "
++			       "ino=%ld\n", __func__, inode->i_sb->s_id,
+ 			       inode->i_ino);
+ 			goto out_unlock;
+ 		}
+@@ -1174,8 +1182,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
+ 		dput(dentry);
+ 		if (rc < 0) {
+ 			if (rc != -ENODATA) {
+-				printk(KERN_WARNING "%s:  getxattr returned "
+-				       "%d for dev=%s ino=%ld\n", __FUNCTION__,
++				printk(KERN_WARNING "SELinux: %s:  getxattr returned "
++				       "%d for dev=%s ino=%ld\n", __func__,
+ 				       -rc, inode->i_sb->s_id, inode->i_ino);
+ 				kfree(context);
+ 				goto out_unlock;
+@@ -1188,9 +1196,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
+ 							     sbsec->def_sid,
+ 							     GFP_NOFS);
+ 			if (rc) {
+-				printk(KERN_WARNING "%s:  context_to_sid(%s) "
++				printk(KERN_WARNING "SELinux: %s:  context_to_sid(%s) "
+ 				       "returned %d for dev=%s ino=%ld\n",
+-				       __FUNCTION__, context, -rc,
++				       __func__, context, -rc,
+ 				       inode->i_sb->s_id, inode->i_ino);
+ 				kfree(context);
+ 				/* Leave with the unlabeled SID */
+@@ -1306,7 +1314,7 @@ static int task_has_capability(struct task_struct *tsk,
+ 
+ 	tsec = tsk->security;
+ 
+-	AVC_AUDIT_DATA_INIT(&ad,CAP);
++	AVC_AUDIT_DATA_INIT(&ad, CAP);
+ 	ad.tsk = tsk;
+ 	ad.u.cap = cap;
+ 
+@@ -1349,7 +1357,7 @@ static int inode_has_perm(struct task_struct *tsk,
+ 	struct inode_security_struct *isec;
+ 	struct avc_audit_data ad;
+ 
+-	if (unlikely (IS_PRIVATE (inode)))
++	if (unlikely(IS_PRIVATE(inode)))
+ 		return 0;
+ 
+ 	tsec = tsk->security;
+@@ -1374,7 +1382,7 @@ static inline int dentry_has_perm(struct task_struct *tsk,
+ {
+ 	struct inode *inode = dentry->d_inode;
+ 	struct avc_audit_data ad;
+-	AVC_AUDIT_DATA_INIT(&ad,FS);
++	AVC_AUDIT_DATA_INIT(&ad, FS);
+ 	ad.u.fs.path.mnt = mnt;
+ 	ad.u.fs.path.dentry = dentry;
+ 	return inode_has_perm(tsk, inode, av, &ad);
+@@ -1471,9 +1479,9 @@ static int may_create_key(u32 ksid,
+ 	return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
+ }
+ 
+-#define MAY_LINK   0
+-#define MAY_UNLINK 1
+-#define MAY_RMDIR  2
++#define MAY_LINK	0
++#define MAY_UNLINK	1
++#define MAY_RMDIR	2
+ 
+ /* Check whether a task can link, unlink, or rmdir a file/directory. */
+ static int may_link(struct inode *dir,
+@@ -1511,7 +1519,8 @@ static int may_link(struct inode *dir,
+ 		av = DIR__RMDIR;
+ 		break;
+ 	default:
+-		printk(KERN_WARNING "may_link:  unrecognized kind %d\n", kind);
++		printk(KERN_WARNING "SELinux: %s:  unrecognized kind %d\n",
++			__func__, kind);
+ 		return 0;
+ 	}
+ 
+@@ -1618,6 +1627,35 @@ static inline u32 file_mask_to_av(int mode, int mask)
+ 	return av;
+ }
+ 
++/*
++ * Convert a file mask to an access vector and include the correct open
++ * open permission.
++ */
++static inline u32 open_file_mask_to_av(int mode, int mask)
++{
++	u32 av = file_mask_to_av(mode, mask);
++
++	if (selinux_policycap_openperm) {
++		/*
++		 * lnk files and socks do not really have an 'open'
++		 */
++		if (S_ISREG(mode))
++			av |= FILE__OPEN;
++		else if (S_ISCHR(mode))
++			av |= CHR_FILE__OPEN;
++		else if (S_ISBLK(mode))
++			av |= BLK_FILE__OPEN;
++		else if (S_ISFIFO(mode))
++			av |= FIFO_FILE__OPEN;
++		else if (S_ISDIR(mode))
++			av |= DIR__OPEN;
++		else
++			printk(KERN_ERR "SELinux: WARNING: inside %s with "
++				"unknown mode:%x\n", __func__, mode);
++	}
++	return av;
++}
++
+ /* Convert a Linux file to an access vector. */
+ static inline u32 file_to_av(struct file *file)
+ {
+@@ -1645,23 +1683,17 @@ static inline u32 file_to_av(struct file *file)
+ 
+ static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
+ {
+-	struct task_security_struct *psec = parent->security;
+-	struct task_security_struct *csec = child->security;
+ 	int rc;
+ 
+-	rc = secondary_ops->ptrace(parent,child);
++	rc = secondary_ops->ptrace(parent, child);
+ 	if (rc)
+ 		return rc;
+ 
+-	rc = task_has_perm(parent, child, PROCESS__PTRACE);
+-	/* Save the SID of the tracing process for later use in apply_creds. */
+-	if (!(child->ptrace & PT_PTRACED) && !rc)
+-		csec->ptrace_sid = psec->sid;
+-	return rc;
++	return task_has_perm(parent, child, PROCESS__PTRACE);
+ }
+ 
+ static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
+-                          kernel_cap_t *inheritable, kernel_cap_t *permitted)
++			  kernel_cap_t *inheritable, kernel_cap_t *permitted)
+ {
+ 	int error;
+ 
+@@ -1673,7 +1705,7 @@ static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
+ }
+ 
+ static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
+-                                kernel_cap_t *inheritable, kernel_cap_t *permitted)
++				kernel_cap_t *inheritable, kernel_cap_t *permitted)
+ {
+ 	int error;
+ 
+@@ -1685,7 +1717,7 @@ static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effect
+ }
+ 
+ static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
+-                               kernel_cap_t *inheritable, kernel_cap_t *permitted)
++			       kernel_cap_t *inheritable, kernel_cap_t *permitted)
+ {
+ 	secondary_ops->capset_set(target, effective, inheritable, permitted);
+ }
+@@ -1698,7 +1730,7 @@ static int selinux_capable(struct task_struct *tsk, int cap)
+ 	if (rc)
+ 		return rc;
+ 
+-	return task_has_capability(tsk,cap);
++	return task_has_capability(tsk, cap);
+ }
+ 
+ static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
+@@ -1707,7 +1739,7 @@ static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
+ 	char *buffer, *path, *end;
+ 
+ 	rc = -ENOMEM;
+-	buffer = (char*)__get_free_page(GFP_KERNEL);
++	buffer = (char *)__get_free_page(GFP_KERNEL);
+ 	if (!buffer)
+ 		goto out;
+ 
+@@ -1765,7 +1797,7 @@ static int selinux_sysctl(ctl_table *table, int op)
+ 
+ 	/* The op values are "defined" in sysctl.c, thereby creating
+ 	 * a bad coupling between this module and sysctl.c */
+-	if(op == 001) {
++	if (op == 001) {
+ 		error = avc_has_perm(tsec->sid, tsid,
+ 				     SECCLASS_DIR, DIR__SEARCH, NULL);
+ 	} else {
+@@ -1777,7 +1809,7 @@ static int selinux_sysctl(ctl_table *table, int op)
+ 		if (av)
+ 			error = avc_has_perm(tsec->sid, tsid,
+ 					     SECCLASS_FILE, av, NULL);
+-        }
++	}
+ 
+ 	return error;
+ }
+@@ -1790,25 +1822,23 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
+ 		return 0;
+ 
+ 	switch (cmds) {
+-		case Q_SYNC:
+-		case Q_QUOTAON:
+-		case Q_QUOTAOFF:
+-	        case Q_SETINFO:
+-		case Q_SETQUOTA:
+-			rc = superblock_has_perm(current,
+-						 sb,
+-						 FILESYSTEM__QUOTAMOD, NULL);
+-			break;
+-	        case Q_GETFMT:
+-	        case Q_GETINFO:
+-		case Q_GETQUOTA:
+-			rc = superblock_has_perm(current,
+-						 sb,
+-						 FILESYSTEM__QUOTAGET, NULL);
+-			break;
+-		default:
+-			rc = 0;  /* let the kernel handle invalid cmds */
+-			break;
++	case Q_SYNC:
++	case Q_QUOTAON:
++	case Q_QUOTAOFF:
++	case Q_SETINFO:
++	case Q_SETQUOTA:
++		rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD,
++					 NULL);
++		break;
++	case Q_GETFMT:
++	case Q_GETINFO:
++	case Q_GETQUOTA:
++		rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET,
++					 NULL);
++		break;
++	default:
++		rc = 0;  /* let the kernel handle invalid cmds */
++		break;
+ 	}
+ 	return rc;
+ }
+@@ -1827,23 +1857,23 @@ static int selinux_syslog(int type)
+ 		return rc;
+ 
+ 	switch (type) {
+-		case 3:         /* Read last kernel messages */
+-		case 10:        /* Return size of the log buffer */
+-			rc = task_has_system(current, SYSTEM__SYSLOG_READ);
+-			break;
+-		case 6:         /* Disable logging to console */
+-		case 7:         /* Enable logging to console */
+-		case 8:		/* Set level of messages printed to console */
+-			rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
+-			break;
+-		case 0:         /* Close log */
+-		case 1:         /* Open log */
+-		case 2:         /* Read from log */
+-		case 4:         /* Read/clear last kernel messages */
+-		case 5:         /* Clear ring buffer */
+-		default:
+-			rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
+-			break;
++	case 3:		/* Read last kernel messages */
++	case 10:	/* Return size of the log buffer */
++		rc = task_has_system(current, SYSTEM__SYSLOG_READ);
++		break;
++	case 6:		/* Disable logging to console */
++	case 7:		/* Enable logging to console */
++	case 8:		/* Set level of messages printed to console */
++		rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
++		break;
++	case 0:		/* Close log */
++	case 1:		/* Open log */
++	case 2:		/* Read from log */
++	case 4:		/* Read/clear last kernel messages */
++	case 5:		/* Clear ring buffer */
++	default:
++		rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
++		break;
+ 	}
+ 	return rc;
+ }
+@@ -1879,6 +1909,22 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
+ 	return __vm_enough_memory(mm, pages, cap_sys_admin);
+ }
+ 
++/**
++ * task_tracer_task - return the task that is tracing the given task
++ * @task:		task to consider
++ *
++ * Returns NULL if noone is tracing @task, or the &struct task_struct
++ * pointer to its tracer.
++ *
++ * Must be called under rcu_read_lock().
++ */
++static struct task_struct *task_tracer_task(struct task_struct *task)
++{
++	if (task->ptrace & PT_PTRACED)
++		return rcu_dereference(task->parent);
++	return NULL;
++}
++
+ /* binprm security operations */
+ 
+ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
+@@ -1889,7 +1935,6 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
+ 	if (!bsec)
+ 		return -ENOMEM;
+ 
+-	bsec->bprm = bprm;
+ 	bsec->sid = SECINITSID_UNLABELED;
+ 	bsec->set = 0;
+ 
+@@ -1934,7 +1979,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
+ 	} else {
+ 		/* Check for a default transition on this program. */
+ 		rc = security_transition_sid(tsec->sid, isec->sid,
+-		                             SECCLASS_PROCESS, &newsid);
++					     SECCLASS_PROCESS, &newsid);
+ 		if (rc)
+ 			return rc;
+ 	}
+@@ -1945,7 +1990,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
+ 	if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
+ 		newsid = tsec->sid;
+ 
+-        if (tsec->sid == newsid) {
++	if (tsec->sid == newsid) {
+ 		rc = avc_has_perm(tsec->sid, isec->sid,
+ 				  SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
+ 		if (rc)
+@@ -1973,13 +2018,13 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
+ 	return 0;
+ }
+ 
+-static int selinux_bprm_check_security (struct linux_binprm *bprm)
++static int selinux_bprm_check_security(struct linux_binprm *bprm)
+ {
+ 	return secondary_ops->bprm_check_security(bprm);
+ }
+ 
+ 
+-static int selinux_bprm_secureexec (struct linux_binprm *bprm)
++static int selinux_bprm_secureexec(struct linux_binprm *bprm)
+ {
+ 	struct task_security_struct *tsec = current->security;
+ 	int atsecure = 0;
+@@ -2006,7 +2051,7 @@ extern struct vfsmount *selinuxfs_mount;
+ extern struct dentry *selinux_null;
+ 
+ /* Derived from fs/exec.c:flush_old_files. */
+-static inline void flush_unauthorized_files(struct files_struct * files)
++static inline void flush_unauthorized_files(struct files_struct *files)
+ {
+ 	struct avc_audit_data ad;
+ 	struct file *file, *devnull = NULL;
+@@ -2041,7 +2086,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
+ 
+ 	/* Revalidate access to inherited open files. */
+ 
+-	AVC_AUDIT_DATA_INIT(&ad,FS);
++	AVC_AUDIT_DATA_INIT(&ad, FS);
+ 
+ 	spin_lock(&files->file_lock);
+ 	for (;;) {
+@@ -2057,7 +2102,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
+ 		if (!set)
+ 			continue;
+ 		spin_unlock(&files->file_lock);
+-		for ( ; set ; i++,set >>= 1) {
++		for ( ; set ; i++, set >>= 1) {
+ 			if (set & 1) {
+ 				file = fget(i);
+ 				if (!file)
+@@ -2126,12 +2171,25 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
+ 		/* Check for ptracing, and update the task SID if ok.
+ 		   Otherwise, leave SID unchanged and kill. */
+ 		if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
+-			rc = avc_has_perm(tsec->ptrace_sid, sid,
+-					  SECCLASS_PROCESS, PROCESS__PTRACE,
+-					  NULL);
+-			if (rc) {
+-				bsec->unsafe = 1;
+-				return;
++			struct task_struct *tracer;
++			struct task_security_struct *sec;
++			u32 ptsid = 0;
++
++			rcu_read_lock();
++			tracer = task_tracer_task(current);
++			if (likely(tracer != NULL)) {
++				sec = tracer->security;
++				ptsid = sec->sid;
++			}
++			rcu_read_unlock();
++
++			if (ptsid != 0) {
++				rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
++						  PROCESS__PTRACE, NULL);
++				if (rc) {
++					bsec->unsafe = 1;
++					return;
++				}
+ 			}
+ 		}
+ 		tsec->sid = sid;
+@@ -2201,7 +2259,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
+ 		for (i = 0; i < RLIM_NLIMITS; i++) {
+ 			rlim = current->signal->rlim + i;
+ 			initrlim = init_task.signal->rlim+i;
+-			rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
++			rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
+ 		}
+ 		if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+ 			/*
+@@ -2239,10 +2297,10 @@ static inline int match_prefix(char *prefix, int plen, char *option, int olen)
+ 
+ static inline int selinux_option(char *option, int len)
+ {
+-	return (match_prefix("context=", sizeof("context=")-1, option, len) ||
+-	        match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
+-	        match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
+-		match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
++	return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
++		match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
++		match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
++		match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
+ }
+ 
+ static inline void take_option(char **to, char *from, int *first, int len)
+@@ -2256,16 +2314,15 @@ static inline void take_option(char **to, char *from, int *first, int len)
+ 	*to += len;
+ }
+ 
+-static inline void take_selinux_option(char **to, char *from, int *first, 
+-		                       int len)
++static inline void take_selinux_option(char **to, char *from, int *first,
++				       int len)
+ {
+ 	int current_size = 0;
+ 
+ 	if (!*first) {
+ 		**to = '|';
+ 		*to += 1;
+-	}
+-	else
++	} else
+ 		*first = 0;
+ 
+ 	while (current_size < len) {
+@@ -2329,7 +2386,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, void *data)
+ 	if (rc)
+ 		return rc;
+ 
+-	AVC_AUDIT_DATA_INIT(&ad,FS);
++	AVC_AUDIT_DATA_INIT(&ad, FS);
+ 	ad.u.fs.path.dentry = sb->s_root;
+ 	return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
+ }
+@@ -2338,29 +2395,29 @@ static int selinux_sb_statfs(struct dentry *dentry)
+ {
+ 	struct avc_audit_data ad;
+ 
+-	AVC_AUDIT_DATA_INIT(&ad,FS);
++	AVC_AUDIT_DATA_INIT(&ad, FS);
+ 	ad.u.fs.path.dentry = dentry->d_sb->s_root;
+ 	return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
+ }
+ 
+-static int selinux_mount(char * dev_name,
+-                         struct nameidata *nd,
+-                         char * type,
+-                         unsigned long flags,
+-                         void * data)
++static int selinux_mount(char *dev_name,
++			 struct path *path,
++			 char *type,
++			 unsigned long flags,
++			 void *data)
+ {
+ 	int rc;
+ 
+-	rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
++	rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
+ 	if (rc)
+ 		return rc;
+ 
+ 	if (flags & MS_REMOUNT)
+-		return superblock_has_perm(current, nd->path.mnt->mnt_sb,
+-		                           FILESYSTEM__REMOUNT, NULL);
++		return superblock_has_perm(current, path->mnt->mnt_sb,
++					   FILESYSTEM__REMOUNT, NULL);
+ 	else
+-		return dentry_has_perm(current, nd->path.mnt, nd->path.dentry,
+-		                       FILE__MOUNTON);
++		return dentry_has_perm(current, path->mnt, path->dentry,
++				       FILE__MOUNTON);
+ }
+ 
+ static int selinux_umount(struct vfsmount *mnt, int flags)
+@@ -2371,8 +2428,8 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
+ 	if (rc)
+ 		return rc;
+ 
+-	return superblock_has_perm(current,mnt->mnt_sb,
+-	                           FILESYSTEM__UNMOUNT,NULL);
++	return superblock_has_perm(current, mnt->mnt_sb,
++				   FILESYSTEM__UNMOUNT, NULL);
+ }
+ 
+ /* inode security operations */
+@@ -2412,7 +2469,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
+ 			printk(KERN_WARNING "%s:  "
+ 			       "security_transition_sid failed, rc=%d (dev=%s "
+ 			       "ino=%ld)\n",
+-			       __FUNCTION__,
++			       __func__,
+ 			       -rc, inode->i_sb->s_id, inode->i_ino);
+ 			return rc;
+ 		}
+@@ -2458,7 +2515,7 @@ static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, stru
+ {
+ 	int rc;
+ 
+-	rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
++	rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
+ 	if (rc)
+ 		return rc;
+ 	return may_link(dir, old_dentry, MAY_LINK);
+@@ -2501,7 +2558,7 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mod
+ }
+ 
+ static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
+-                                struct inode *new_inode, struct dentry *new_dentry)
++				struct inode *new_inode, struct dentry *new_dentry)
+ {
+ 	return may_rename(old_inode, old_dentry, new_inode, new_dentry);
+ }
+@@ -2515,7 +2572,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
+ {
+ 	int rc;
+ 
+-	rc = secondary_ops->inode_follow_link(dentry,nameidata);
++	rc = secondary_ops->inode_follow_link(dentry, nameidata);
+ 	if (rc)
+ 		return rc;
+ 	return dentry_has_perm(current, NULL, dentry, FILE__READ);
+@@ -2536,7 +2593,7 @@ static int selinux_inode_permission(struct inode *inode, int mask,
+ 	}
+ 
+ 	return inode_has_perm(current, inode,
+-			       file_mask_to_av(inode->i_mode, mask), NULL);
++			       open_file_mask_to_av(inode->i_mode, mask), NULL);
+ }
+ 
+ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+@@ -2601,7 +2658,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
+ 	if (!is_owner_or_cap(inode))
+ 		return -EPERM;
+ 
+-	AVC_AUDIT_DATA_INIT(&ad,FS);
++	AVC_AUDIT_DATA_INIT(&ad, FS);
+ 	ad.u.fs.path.dentry = dentry;
+ 
+ 	rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
+@@ -2619,7 +2676,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
+ 		return rc;
+ 
+ 	rc = security_validate_transition(isec->sid, newsid, tsec->sid,
+-	                                  isec->sclass);
++					  isec->sclass);
+ 	if (rc)
+ 		return rc;
+ 
+@@ -2631,7 +2688,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
+ }
+ 
+ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+-                                        void *value, size_t size, int flags)
++					void *value, size_t size, int flags)
+ {
+ 	struct inode *inode = dentry->d_inode;
+ 	struct inode_security_struct *isec = inode->i_security;
+@@ -2646,7 +2703,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+ 	rc = security_context_to_sid(value, size, &newsid);
+ 	if (rc) {
+ 		printk(KERN_WARNING "%s:  unable to obtain SID for context "
+-		       "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
++		       "%s, rc=%d\n", __func__, (char *)value, -rc);
+ 		return;
+ 	}
+ 
+@@ -2654,17 +2711,17 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+ 	return;
+ }
+ 
+-static int selinux_inode_getxattr (struct dentry *dentry, char *name)
++static int selinux_inode_getxattr(struct dentry *dentry, char *name)
+ {
+ 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+ }
+ 
+-static int selinux_inode_listxattr (struct dentry *dentry)
++static int selinux_inode_listxattr(struct dentry *dentry)
+ {
+ 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+ }
+ 
+-static int selinux_inode_removexattr (struct dentry *dentry, char *name)
++static int selinux_inode_removexattr(struct dentry *dentry, char *name)
+ {
+ 	if (strcmp(name, XATTR_NAME_SELINUX))
+ 		return selinux_inode_setotherxattr(dentry, name);
+@@ -2705,7 +2762,7 @@ out_nofree:
+ }
+ 
+ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
+-                                     const void *value, size_t size, int flags)
++				     const void *value, size_t size, int flags)
+ {
+ 	struct inode_security_struct *isec = inode->i_security;
+ 	u32 newsid;
+@@ -2717,7 +2774,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
+ 	if (!value || !size)
+ 		return -EACCES;
+ 
+-	rc = security_context_to_sid((void*)value, size, &newsid);
++	rc = security_context_to_sid((void *)value, size, &newsid);
+ 	if (rc)
+ 		return rc;
+ 
+@@ -2743,6 +2800,12 @@ static int selinux_inode_killpriv(struct dentry *dentry)
+ 	return secondary_ops->inode_killpriv(dentry);
+ }
+ 
++static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
++{
++	struct inode_security_struct *isec = inode->i_security;
++	*secid = isec->sid;
++}
++
+ /* file security operations */
+ 
+ static int selinux_revalidate_file_permission(struct file *file, int mask)
+@@ -2802,42 +2865,41 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
+ 	int error = 0;
+ 
+ 	switch (cmd) {
+-		case FIONREAD:
+-		/* fall through */
+-		case FIBMAP:
+-		/* fall through */
+-		case FIGETBSZ:
+-		/* fall through */
+-		case EXT2_IOC_GETFLAGS:
+-		/* fall through */
+-		case EXT2_IOC_GETVERSION:
+-			error = file_has_perm(current, file, FILE__GETATTR);
+-			break;
+-
+-		case EXT2_IOC_SETFLAGS:
+-		/* fall through */
+-		case EXT2_IOC_SETVERSION:
+-			error = file_has_perm(current, file, FILE__SETATTR);
+-			break;
++	case FIONREAD:
++	/* fall through */
++	case FIBMAP:
++	/* fall through */
++	case FIGETBSZ:
++	/* fall through */
++	case EXT2_IOC_GETFLAGS:
++	/* fall through */
++	case EXT2_IOC_GETVERSION:
++		error = file_has_perm(current, file, FILE__GETATTR);
++		break;
+ 
+-		/* sys_ioctl() checks */
+-		case FIONBIO:
+-		/* fall through */
+-		case FIOASYNC:
+-			error = file_has_perm(current, file, 0);
+-			break;
++	case EXT2_IOC_SETFLAGS:
++	/* fall through */
++	case EXT2_IOC_SETVERSION:
++		error = file_has_perm(current, file, FILE__SETATTR);
++		break;
+ 
+-	        case KDSKBENT:
+-	        case KDSKBSENT:
+-			error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
+-			break;
++	/* sys_ioctl() checks */
++	case FIONBIO:
++	/* fall through */
++	case FIOASYNC:
++		error = file_has_perm(current, file, 0);
++		break;
+ 
+-		/* default case assumes that the command will go
+-		 * to the file's ioctl() function.
+-		 */
+-		default:
+-			error = file_has_perm(current, file, FILE__IOCTL);
++	case KDSKBENT:
++	case KDSKBSENT:
++		error = task_has_capability(current, CAP_SYS_TTY_CONFIG);
++		break;
+ 
++	/* default case assumes that the command will go
++	 * to the file's ioctl() function.
++	 */
++	default:
++		error = file_has_perm(current, file, FILE__IOCTL);
+ 	}
+ 	return error;
+ }
+@@ -2878,7 +2940,7 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
+ 			     unsigned long addr, unsigned long addr_only)
+ {
+ 	int rc = 0;
+-	u32 sid = ((struct task_security_struct*)(current->security))->sid;
++	u32 sid = ((struct task_security_struct *)(current->security))->sid;
+ 
+ 	if (addr < mmap_min_addr)
+ 		rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
+@@ -2947,39 +3009,39 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
+ 	int err = 0;
+ 
+ 	switch (cmd) {
+-	        case F_SETFL:
+-			if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
+-				err = -EINVAL;
+-				break;
+-			}
++	case F_SETFL:
++		if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
++			err = -EINVAL;
++			break;
++		}
+ 
+-			if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
+-				err = file_has_perm(current, file,FILE__WRITE);
+-				break;
+-			}
+-			/* fall through */
+-	        case F_SETOWN:
+-	        case F_SETSIG:
+-	        case F_GETFL:
+-	        case F_GETOWN:
+-	        case F_GETSIG:
+-			/* Just check FD__USE permission */
+-			err = file_has_perm(current, file, 0);
++		if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
++			err = file_has_perm(current, file, FILE__WRITE);
+ 			break;
+-		case F_GETLK:
+-		case F_SETLK:
+-	        case F_SETLKW:
++		}
++		/* fall through */
++	case F_SETOWN:
++	case F_SETSIG:
++	case F_GETFL:
++	case F_GETOWN:
++	case F_GETSIG:
++		/* Just check FD__USE permission */
++		err = file_has_perm(current, file, 0);
++		break;
++	case F_GETLK:
++	case F_SETLK:
++	case F_SETLKW:
+ #if BITS_PER_LONG == 32
+-	        case F_GETLK64:
+-		case F_SETLK64:
+-	        case F_SETLKW64:
++	case F_GETLK64:
++	case F_SETLK64:
++	case F_SETLKW64:
+ #endif
+-			if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
+-				err = -EINVAL;
+-				break;
+-			}
+-			err = file_has_perm(current, file, FILE__LOCK);
++		if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
++			err = -EINVAL;
+ 			break;
++		}
++		err = file_has_perm(current, file, FILE__LOCK);
++		break;
+ 	}
+ 
+ 	return err;
+@@ -3000,13 +3062,13 @@ static int selinux_file_set_fowner(struct file *file)
+ static int selinux_file_send_sigiotask(struct task_struct *tsk,
+ 				       struct fown_struct *fown, int signum)
+ {
+-        struct file *file;
++	struct file *file;
+ 	u32 perm;
+ 	struct task_security_struct *tsec;
+ 	struct file_security_struct *fsec;
+ 
+ 	/* struct fown_struct is never outside the context of a struct file */
+-        file = container_of(fown, struct file, f_owner);
++	file = container_of(fown, struct file, f_owner);
+ 
+ 	tsec = tsk->security;
+ 	fsec = file->f_security;
+@@ -3087,11 +3149,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
+ 	tsec2->keycreate_sid = tsec1->keycreate_sid;
+ 	tsec2->sockcreate_sid = tsec1->sockcreate_sid;
+ 
+-	/* Retain ptracer SID across fork, if any.
+-	   This will be reset by the ptrace hook upon any
+-	   subsequent ptrace_attach operations. */
+-	tsec2->ptrace_sid = tsec1->ptrace_sid;
+-
+ 	return 0;
+ }
+ 
+@@ -3113,7 +3170,7 @@ static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
+ 
+ static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
+ {
+-	return secondary_ops->task_post_setuid(id0,id1,id2,flags);
++	return secondary_ops->task_post_setuid(id0, id1, id2, flags);
+ }
+ 
+ static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
+@@ -3139,7 +3196,8 @@ static int selinux_task_getsid(struct task_struct *p)
+ 
+ static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
+ {
+-	selinux_get_task_sid(p, secid);
++	struct task_security_struct *tsec = p->security;
++	*secid = tsec->sid;
+ }
+ 
+ static int selinux_task_setgroups(struct group_info *group_info)
+@@ -3156,7 +3214,7 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
+ 	if (rc)
+ 		return rc;
+ 
+-	return task_has_perm(current,p, PROCESS__SETSCHED);
++	return task_has_perm(current, p, PROCESS__SETSCHED);
+ }
+ 
+ static int selinux_task_setioprio(struct task_struct *p, int ioprio)
+@@ -3260,7 +3318,7 @@ static int selinux_task_wait(struct task_struct *p)
+ 
+ static void selinux_task_reparent_to_init(struct task_struct *p)
+ {
+-  	struct task_security_struct *tsec;
++	struct task_security_struct *tsec;
+ 
+ 	secondary_ops->task_reparent_to_init(p);
+ 
+@@ -3305,11 +3363,11 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
+ 		*proto = ih->protocol;
+ 
+ 	switch (ih->protocol) {
+-        case IPPROTO_TCP: {
+-        	struct tcphdr _tcph, *th;
++	case IPPROTO_TCP: {
++		struct tcphdr _tcph, *th;
+ 
+-        	if (ntohs(ih->frag_off) & IP_OFFSET)
+-        		break;
++		if (ntohs(ih->frag_off) & IP_OFFSET)
++			break;
+ 
+ 		offset += ihlen;
+ 		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+@@ -3319,23 +3377,23 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
+ 		ad->u.net.sport = th->source;
+ 		ad->u.net.dport = th->dest;
+ 		break;
+-        }
+-        
+-        case IPPROTO_UDP: {
+-        	struct udphdr _udph, *uh;
+-        	
+-        	if (ntohs(ih->frag_off) & IP_OFFSET)
+-        		break;
+-        		
++	}
++
++	case IPPROTO_UDP: {
++		struct udphdr _udph, *uh;
++
++		if (ntohs(ih->frag_off) & IP_OFFSET)
++			break;
++
+ 		offset += ihlen;
+-        	uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
++		uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
+ 		if (uh == NULL)
+-			break;	
++			break;
+ 
+-        	ad->u.net.sport = uh->source;
+-        	ad->u.net.dport = uh->dest;
+-        	break;
+-        }
++		ad->u.net.sport = uh->source;
++		ad->u.net.dport = uh->dest;
++		break;
++	}
+ 
+ 	case IPPROTO_DCCP: {
+ 		struct dccp_hdr _dccph, *dh;
+@@ -3351,11 +3409,11 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
+ 		ad->u.net.sport = dh->dccph_sport;
+ 		ad->u.net.dport = dh->dccph_dport;
+ 		break;
+-        }
++	}
+ 
+-        default:
+-        	break;
+-        }
++	default:
++		break;
++	}
+ out:
+ 	return ret;
+ }
+@@ -3390,7 +3448,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
+ 
+ 	switch (nexthdr) {
+ 	case IPPROTO_TCP: {
+-        	struct tcphdr _tcph, *th;
++		struct tcphdr _tcph, *th;
+ 
+ 		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+ 		if (th == NULL)
+@@ -3423,7 +3481,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
+ 		ad->u.net.sport = dh->dccph_sport;
+ 		ad->u.net.dport = dh->dccph_dport;
+ 		break;
+-        }
++	}
+ 
+ 	/* includes fragments */
+ 	default:
+@@ -3521,7 +3579,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
+ 	if (isec->sid == SECINITSID_KERNEL)
+ 		goto out;
+ 
+-	AVC_AUDIT_DATA_INIT(&ad,NET);
++	AVC_AUDIT_DATA_INIT(&ad, NET);
+ 	ad.u.net.sk = sock->sk;
+ 	err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
+ 
+@@ -3627,13 +3685,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
+ 			inet_get_local_port_range(&low, &high);
+ 
+ 			if (snum < max(PROT_SOCK, low) || snum > high) {
+-				err = security_port_sid(sk->sk_family,
+-							sk->sk_type,
+-							sk->sk_protocol, snum,
+-							&sid);
++				err = sel_netport_sid(sk->sk_protocol,
++						      snum, &sid);
+ 				if (err)
+ 					goto out;
+-				AVC_AUDIT_DATA_INIT(&ad,NET);
++				AVC_AUDIT_DATA_INIT(&ad, NET);
+ 				ad.u.net.sport = htons(snum);
+ 				ad.u.net.family = family;
+ 				err = avc_has_perm(isec->sid, sid,
+@@ -3643,12 +3699,12 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
+ 					goto out;
+ 			}
+ 		}
+-		
+-		switch(isec->sclass) {
++
++		switch (isec->sclass) {
+ 		case SECCLASS_TCP_SOCKET:
+ 			node_perm = TCP_SOCKET__NODE_BIND;
+ 			break;
+-			
++
+ 		case SECCLASS_UDP_SOCKET:
+ 			node_perm = UDP_SOCKET__NODE_BIND;
+ 			break;
+@@ -3661,12 +3717,12 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
+ 			node_perm = RAWIP_SOCKET__NODE_BIND;
+ 			break;
+ 		}
+-		
++
+ 		err = sel_netnode_sid(addrp, family, &sid);
+ 		if (err)
+ 			goto out;
+-		
+-		AVC_AUDIT_DATA_INIT(&ad,NET);
++
++		AVC_AUDIT_DATA_INIT(&ad, NET);
+ 		ad.u.net.sport = htons(snum);
+ 		ad.u.net.family = family;
+ 
+@@ -3676,7 +3732,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
+ 			ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
+ 
+ 		err = avc_has_perm(isec->sid, sid,
+-		                   isec->sclass, node_perm, &ad);
++				   isec->sclass, node_perm, &ad);
+ 		if (err)
+ 			goto out;
+ 	}
+@@ -3718,15 +3774,14 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
+ 			snum = ntohs(addr6->sin6_port);
+ 		}
+ 
+-		err = security_port_sid(sk->sk_family, sk->sk_type,
+-					sk->sk_protocol, snum, &sid);
++		err = sel_netport_sid(sk->sk_protocol, snum, &sid);
+ 		if (err)
+ 			goto out;
+ 
+ 		perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
+ 		       TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
+ 
+-		AVC_AUDIT_DATA_INIT(&ad,NET);
++		AVC_AUDIT_DATA_INIT(&ad, NET);
+ 		ad.u.net.dport = htons(snum);
+ 		ad.u.net.family = sk->sk_family;
+ 		err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
+@@ -3764,7 +3819,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
+ }
+ 
+ static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
+- 				  int size)
++				  int size)
+ {
+ 	int rc;
+ 
+@@ -3791,7 +3846,7 @@ static int selinux_socket_getpeername(struct socket *sock)
+ 	return socket_has_perm(current, sock, SOCKET__GETATTR);
+ }
+ 
+-static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
++static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
+ {
+ 	int err;
+ 
+@@ -3830,7 +3885,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
+ 	isec = SOCK_INODE(sock)->i_security;
+ 	other_isec = SOCK_INODE(other)->i_security;
+ 
+-	AVC_AUDIT_DATA_INIT(&ad,NET);
++	AVC_AUDIT_DATA_INIT(&ad, NET);
+ 	ad.u.net.sk = other->sk;
+ 
+ 	err = avc_has_perm(isec->sid, other_isec->sid,
+@@ -3842,7 +3897,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
+ 	/* connecting socket */
+ 	ssec = sock->sk->sk_security;
+ 	ssec->peer_sid = other_isec->sid;
+-	
++
+ 	/* server child socket */
+ 	ssec = newsk->sk_security;
+ 	ssec->peer_sid = isec->sid;
+@@ -3862,7 +3917,7 @@ static int selinux_socket_unix_may_send(struct socket *sock,
+ 	isec = SOCK_INODE(sock)->i_security;
+ 	other_isec = SOCK_INODE(other)->i_security;
+ 
+-	AVC_AUDIT_DATA_INIT(&ad,NET);
++	AVC_AUDIT_DATA_INIT(&ad, NET);
+ 	ad.u.net.sk = other->sk;
+ 
+ 	err = avc_has_perm(isec->sid, other_isec->sid,
+@@ -3940,7 +3995,7 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
+ 	err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
+ 	if (err)
+ 		return err;
+-	
++
+ 	err = sel_netnode_sid(addrp, family, &node_sid);
+ 	if (err)
+ 		return err;
+@@ -3950,9 +4005,8 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
+ 
+ 	if (!recv_perm)
+ 		return 0;
+-	err = security_port_sid(sk->sk_family, sk->sk_type,
+-				sk->sk_protocol, ntohs(ad->u.net.sport),
+-				&port_sid);
++	err = sel_netport_sid(sk->sk_protocol,
++			      ntohs(ad->u.net.sport), &port_sid);
+ 	if (unlikely(err)) {
+ 		printk(KERN_WARNING
+ 		       "SELinux: failure in"
+@@ -4092,7 +4146,7 @@ out_len:
+ 		err = -EFAULT;
+ 
+ 	kfree(scontext);
+-out:	
++out:
+ 	return err;
+ }
+ 
+@@ -4109,7 +4163,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
+ 		goto out;
+ 
+ 	if (sock && family == PF_UNIX)
+-		selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
++		selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
+ 	else if (skb)
+ 		selinux_skb_peerlbl_sid(skb, family, &peer_secid);
+ 
+@@ -4139,7 +4193,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
+ 	newssec->peer_sid = ssec->peer_sid;
+ 	newssec->sclass = ssec->sclass;
+ 
+-	selinux_netlbl_sk_security_clone(ssec, newssec);
++	selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
+ }
+ 
+ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
+@@ -4153,7 +4207,7 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
+ 	}
+ }
+ 
+-static void selinux_sock_graft(struct sock* sk, struct socket *parent)
++static void selinux_sock_graft(struct sock *sk, struct socket *parent)
+ {
+ 	struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
+ 	struct sk_security_struct *sksec = sk->sk_security;
+@@ -4230,13 +4284,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
+ 	struct nlmsghdr *nlh;
+ 	struct socket *sock = sk->sk_socket;
+ 	struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
+-	
++
+ 	if (skb->len < NLMSG_SPACE(0)) {
+ 		err = -EINVAL;
+ 		goto out;
+ 	}
+ 	nlh = nlmsg_hdr(skb);
+-	
++
+ 	err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
+ 	if (err) {
+ 		if (err == -EINVAL) {
+@@ -4362,7 +4416,7 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
+ 		return err;
+ 	err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
+ 		return err;
+-		
++
+ 	err = sel_netnode_sid(addrp, family, &node_sid);
+ 	if (err)
+ 		return err;
+@@ -4373,9 +4427,8 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
+ 	if (send_perm != 0)
+ 		return 0;
+ 
+-	err = security_port_sid(sk->sk_family, sk->sk_type,
+-				sk->sk_protocol, ntohs(ad->u.net.dport),
+-				&port_sid);
++	err = sel_netport_sid(sk->sk_protocol,
++			      ntohs(ad->u.net.dport), &port_sid);
+ 	if (unlikely(err)) {
+ 		printk(KERN_WARNING
+ 		       "SELinux: failure in"
+@@ -4546,7 +4599,7 @@ static int selinux_netlink_recv(struct sk_buff *skb, int capability)
+ 	ad.u.cap = capability;
+ 
+ 	return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
+-	                    SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
++			    SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
+ }
+ 
+ static int ipc_alloc_security(struct task_struct *task,
+@@ -4561,7 +4614,6 @@ static int ipc_alloc_security(struct task_struct *task,
+ 		return -ENOMEM;
+ 
+ 	isec->sclass = sclass;
+-	isec->ipc_perm = perm;
+ 	isec->sid = tsec->sid;
+ 	perm->security = isec;
+ 
+@@ -4583,7 +4635,6 @@ static int msg_msg_alloc_security(struct msg_msg *msg)
+ 	if (!msec)
+ 		return -ENOMEM;
+ 
+-	msec->msg = msg;
+ 	msec->sid = SECINITSID_UNLABELED;
+ 	msg->security = msec;
+ 
+@@ -4640,7 +4691,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
+ 	isec = msq->q_perm.security;
+ 
+ 	AVC_AUDIT_DATA_INIT(&ad, IPC);
+- 	ad.u.ipc_id = msq->q_perm.key;
++	ad.u.ipc_id = msq->q_perm.key;
+ 
+ 	rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
+ 			  MSGQ__CREATE, &ad);
+@@ -4677,7 +4728,7 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+ 	int err;
+ 	int perms;
+ 
+-	switch(cmd) {
++	switch (cmd) {
+ 	case IPC_INFO:
+ 	case MSG_INFO:
+ 		/* No specific object, just general system-wide information. */
+@@ -4761,7 +4812,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+ 	msec = msg->security;
+ 
+ 	AVC_AUDIT_DATA_INIT(&ad, IPC);
+- 	ad.u.ipc_id = msq->q_perm.key;
++	ad.u.ipc_id = msq->q_perm.key;
+ 
+ 	rc = avc_has_perm(tsec->sid, isec->sid,
+ 			  SECCLASS_MSGQ, MSGQ__READ, &ad);
+@@ -4787,7 +4838,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
+ 	isec = shp->shm_perm.security;
+ 
+ 	AVC_AUDIT_DATA_INIT(&ad, IPC);
+- 	ad.u.ipc_id = shp->shm_perm.key;
++	ad.u.ipc_id = shp->shm_perm.key;
+ 
+ 	rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
+ 			  SHM__CREATE, &ad);
+@@ -4825,7 +4876,7 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
+ 	int perms;
+ 	int err;
+ 
+-	switch(cmd) {
++	switch (cmd) {
+ 	case IPC_INFO:
+ 	case SHM_INFO:
+ 		/* No specific object, just general system-wide information. */
+@@ -4886,7 +4937,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
+ 	isec = sma->sem_perm.security;
+ 
+ 	AVC_AUDIT_DATA_INIT(&ad, IPC);
+- 	ad.u.ipc_id = sma->sem_perm.key;
++	ad.u.ipc_id = sma->sem_perm.key;
+ 
+ 	rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
+ 			  SEM__CREATE, &ad);
+@@ -4924,7 +4975,7 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)
+ 	int err;
+ 	u32 perms;
+ 
+-	switch(cmd) {
++	switch (cmd) {
+ 	case IPC_INFO:
+ 	case SEM_INFO:
+ 		/* No specific object, just general system-wide information. */
+@@ -4989,25 +5040,31 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
+ 	return ipc_has_perm(ipcp, av);
+ }
+ 
++static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
++{
++	struct ipc_security_struct *isec = ipcp->security;
++	*secid = isec->sid;
++}
++
+ /* module stacking operations */
+-static int selinux_register_security (const char *name, struct security_operations *ops)
++static int selinux_register_security(const char *name, struct security_operations *ops)
+ {
+ 	if (secondary_ops != original_ops) {
+ 		printk(KERN_ERR "%s:  There is already a secondary security "
+-		       "module registered.\n", __FUNCTION__);
++		       "module registered.\n", __func__);
+ 		return -EINVAL;
+- 	}
++	}
+ 
+ 	secondary_ops = ops;
+ 
+ 	printk(KERN_INFO "%s:  Registering secondary module %s\n",
+-	       __FUNCTION__,
++	       __func__,
+ 	       name);
+ 
+ 	return 0;
+ }
+ 
+-static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
++static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
+ {
+ 	if (inode)
+ 		inode_doinit_with_dentry(inode, dentry);
+@@ -5057,6 +5114,7 @@ static int selinux_setprocattr(struct task_struct *p,
+ 			       char *name, void *value, size_t size)
+ {
+ 	struct task_security_struct *tsec;
++	struct task_struct *tracer;
+ 	u32 sid = 0;
+ 	int error;
+ 	char *str = value;
+@@ -5134,34 +5192,39 @@ static int selinux_setprocattr(struct task_struct *p,
+ 				}
+ 			while_each_thread(g, t);
+ 			read_unlock(&tasklist_lock);
+-                }
++		}
+ 
+ 		/* Check permissions for the transition. */
+ 		error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
+-		                     PROCESS__DYNTRANSITION, NULL);
++				     PROCESS__DYNTRANSITION, NULL);
+ 		if (error)
+ 			return error;
+ 
+ 		/* Check for ptracing, and update the task SID if ok.
+ 		   Otherwise, leave SID unchanged and fail. */
+ 		task_lock(p);
+-		if (p->ptrace & PT_PTRACED) {
+-			error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
++		rcu_read_lock();
++		tracer = task_tracer_task(p);
++		if (tracer != NULL) {
++			struct task_security_struct *ptsec = tracer->security;
++			u32 ptsid = ptsec->sid;
++			rcu_read_unlock();
++			error = avc_has_perm_noaudit(ptsid, sid,
+ 						     SECCLASS_PROCESS,
+ 						     PROCESS__PTRACE, 0, &avd);
+ 			if (!error)
+ 				tsec->sid = sid;
+ 			task_unlock(p);
+-			avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
++			avc_audit(ptsid, sid, SECCLASS_PROCESS,
+ 				  PROCESS__PTRACE, &avd, error, NULL);
+ 			if (error)
+ 				return error;
+ 		} else {
++			rcu_read_unlock();
+ 			tsec->sid = sid;
+ 			task_unlock(p);
+ 		}
+-	}
+-	else
++	} else
+ 		return -EINVAL;
+ 
+ 	return size;
+@@ -5194,7 +5257,6 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
+ 	if (!ksec)
+ 		return -ENOMEM;
+ 
+-	ksec->obj = k;
+ 	if (tsec->keycreate_sid)
+ 		ksec->sid = tsec->keycreate_sid;
+ 	else
+@@ -5238,6 +5300,8 @@ static int selinux_key_permission(key_ref_t key_ref,
+ #endif
+ 
+ static struct security_operations selinux_ops = {
++	.name =				"selinux",
++
+ 	.ptrace =			selinux_ptrace,
+ 	.capget =			selinux_capget,
+ 	.capset_check =			selinux_capset_check,
+@@ -5250,7 +5314,7 @@ static struct security_operations selinux_ops = {
+ 	.vm_enough_memory =		selinux_vm_enough_memory,
+ 
+ 	.netlink_send =			selinux_netlink_send,
+-        .netlink_recv =			selinux_netlink_recv,
++	.netlink_recv =			selinux_netlink_recv,
+ 
+ 	.bprm_alloc_security =		selinux_bprm_alloc_security,
+ 	.bprm_free_security =		selinux_bprm_free_security,
+@@ -5263,13 +5327,13 @@ static struct security_operations selinux_ops = {
+ 	.sb_alloc_security =		selinux_sb_alloc_security,
+ 	.sb_free_security =		selinux_sb_free_security,
+ 	.sb_copy_data =			selinux_sb_copy_data,
+-	.sb_kern_mount =	        selinux_sb_kern_mount,
++	.sb_kern_mount =		selinux_sb_kern_mount,
+ 	.sb_statfs =			selinux_sb_statfs,
+ 	.sb_mount =			selinux_mount,
+ 	.sb_umount =			selinux_umount,
+ 	.sb_get_mnt_opts =		selinux_get_mnt_opts,
+ 	.sb_set_mnt_opts =		selinux_set_mnt_opts,
+-	.sb_clone_mnt_opts = 		selinux_sb_clone_mnt_opts,
++	.sb_clone_mnt_opts =		selinux_sb_clone_mnt_opts,
+ 	.sb_parse_opts_str = 		selinux_parse_opts_str,
+ 
+ 
+@@ -5294,11 +5358,12 @@ static struct security_operations selinux_ops = {
+ 	.inode_getxattr =		selinux_inode_getxattr,
+ 	.inode_listxattr =		selinux_inode_listxattr,
+ 	.inode_removexattr =		selinux_inode_removexattr,
+-	.inode_getsecurity =            selinux_inode_getsecurity,
+-	.inode_setsecurity =            selinux_inode_setsecurity,
+-	.inode_listsecurity =           selinux_inode_listsecurity,
++	.inode_getsecurity =		selinux_inode_getsecurity,
++	.inode_setsecurity =		selinux_inode_setsecurity,
++	.inode_listsecurity =		selinux_inode_listsecurity,
+ 	.inode_need_killpriv =		selinux_inode_need_killpriv,
+ 	.inode_killpriv =		selinux_inode_killpriv,
++	.inode_getsecid =               selinux_inode_getsecid,
+ 
+ 	.file_permission =		selinux_file_permission,
+ 	.file_alloc_security =		selinux_file_alloc_security,
+@@ -5312,7 +5377,7 @@ static struct security_operations selinux_ops = {
+ 	.file_send_sigiotask =		selinux_file_send_sigiotask,
+ 	.file_receive =			selinux_file_receive,
+ 
+-	.dentry_open =                  selinux_dentry_open,
++	.dentry_open =			selinux_dentry_open,
+ 
+ 	.task_create =			selinux_task_create,
+ 	.task_alloc_security =		selinux_task_alloc_security,
+@@ -5322,7 +5387,7 @@ static struct security_operations selinux_ops = {
+ 	.task_setgid =			selinux_task_setgid,
+ 	.task_setpgid =			selinux_task_setpgid,
+ 	.task_getpgid =			selinux_task_getpgid,
+-	.task_getsid =		        selinux_task_getsid,
++	.task_getsid =			selinux_task_getsid,
+ 	.task_getsecid =		selinux_task_getsecid,
+ 	.task_setgroups =		selinux_task_setgroups,
+ 	.task_setnice =			selinux_task_setnice,
+@@ -5336,9 +5401,10 @@ static struct security_operations selinux_ops = {
+ 	.task_wait =			selinux_task_wait,
+ 	.task_prctl =			selinux_task_prctl,
+ 	.task_reparent_to_init =	selinux_task_reparent_to_init,
+-	.task_to_inode =                selinux_task_to_inode,
++	.task_to_inode =		selinux_task_to_inode,
+ 
+ 	.ipc_permission =		selinux_ipc_permission,
++	.ipc_getsecid =                 selinux_ipc_getsecid,
+ 
+ 	.msg_msg_alloc_security =	selinux_msg_msg_alloc_security,
+ 	.msg_msg_free_security =	selinux_msg_msg_free_security,
+@@ -5356,24 +5422,24 @@ static struct security_operations selinux_ops = {
+ 	.shm_shmctl =			selinux_shm_shmctl,
+ 	.shm_shmat =			selinux_shm_shmat,
+ 
+-	.sem_alloc_security = 		selinux_sem_alloc_security,
+-	.sem_free_security =  		selinux_sem_free_security,
++	.sem_alloc_security =		selinux_sem_alloc_security,
++	.sem_free_security =		selinux_sem_free_security,
+ 	.sem_associate =		selinux_sem_associate,
+ 	.sem_semctl =			selinux_sem_semctl,
+ 	.sem_semop =			selinux_sem_semop,
+ 
+ 	.register_security =		selinux_register_security,
+ 
+-	.d_instantiate =                selinux_d_instantiate,
++	.d_instantiate =		selinux_d_instantiate,
+ 
+-	.getprocattr =                  selinux_getprocattr,
+-	.setprocattr =                  selinux_setprocattr,
++	.getprocattr =			selinux_getprocattr,
++	.setprocattr =			selinux_setprocattr,
+ 
+ 	.secid_to_secctx =		selinux_secid_to_secctx,
+ 	.secctx_to_secid =		selinux_secctx_to_secid,
+ 	.release_secctx =		selinux_release_secctx,
+ 
+-        .unix_stream_connect =		selinux_socket_unix_stream_connect,
++	.unix_stream_connect =		selinux_socket_unix_stream_connect,
+ 	.unix_may_send =		selinux_socket_unix_may_send,
+ 
+ 	.socket_create =		selinux_socket_create,
+@@ -5395,7 +5461,7 @@ static struct security_operations selinux_ops = {
+ 	.sk_alloc_security =		selinux_sk_alloc_security,
+ 	.sk_free_security =		selinux_sk_free_security,
+ 	.sk_clone_security =		selinux_sk_clone_security,
+-	.sk_getsecid = 			selinux_sk_getsecid,
++	.sk_getsecid =			selinux_sk_getsecid,
+ 	.sock_graft =			selinux_sock_graft,
+ 	.inet_conn_request =		selinux_inet_conn_request,
+ 	.inet_csk_clone =		selinux_inet_csk_clone,
+@@ -5410,15 +5476,22 @@ static struct security_operations selinux_ops = {
+ 	.xfrm_state_alloc_security =	selinux_xfrm_state_alloc,
+ 	.xfrm_state_free_security =	selinux_xfrm_state_free,
+ 	.xfrm_state_delete_security =	selinux_xfrm_state_delete,
+-	.xfrm_policy_lookup = 		selinux_xfrm_policy_lookup,
++	.xfrm_policy_lookup =		selinux_xfrm_policy_lookup,
+ 	.xfrm_state_pol_flow_match =	selinux_xfrm_state_pol_flow_match,
+ 	.xfrm_decode_session =		selinux_xfrm_decode_session,
+ #endif
+ 
+ #ifdef CONFIG_KEYS
+-	.key_alloc =                    selinux_key_alloc,
+-	.key_free =                     selinux_key_free,
+-	.key_permission =               selinux_key_permission,
++	.key_alloc =			selinux_key_alloc,
++	.key_free =			selinux_key_free,
++	.key_permission =		selinux_key_permission,
++#endif
++
++#ifdef CONFIG_AUDIT
++	.audit_rule_init =		selinux_audit_rule_init,
++	.audit_rule_known =		selinux_audit_rule_known,
++	.audit_rule_match =		selinux_audit_rule_match,
++	.audit_rule_free =		selinux_audit_rule_free,
+ #endif
+ };
+ 
+@@ -5426,6 +5499,11 @@ static __init int selinux_init(void)
+ {
+ 	struct task_security_struct *tsec;
+ 
++	if (!security_module_enable(&selinux_ops)) {
++		selinux_enabled = 0;
++		return 0;
++	}
++
+ 	if (!selinux_enabled) {
+ 		printk(KERN_INFO "SELinux:  Disabled at boot.\n");
+ 		return 0;
+@@ -5446,15 +5524,14 @@ static __init int selinux_init(void)
+ 
+ 	original_ops = secondary_ops = security_ops;
+ 	if (!secondary_ops)
+-		panic ("SELinux: No initial security operations\n");
+-	if (register_security (&selinux_ops))
++		panic("SELinux: No initial security operations\n");
++	if (register_security(&selinux_ops))
+ 		panic("SELinux: Unable to register with kernel.\n");
+ 
+-	if (selinux_enforcing) {
++	if (selinux_enforcing)
+ 		printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");
+-	} else {
++	else
+ 		printk(KERN_DEBUG "SELinux:  Starting in permissive mode\n");
+-	}
+ 
+ #ifdef CONFIG_KEYS
+ 	/* Add security information to initial keyrings */
+@@ -5479,8 +5556,8 @@ next_sb:
+ 	if (!list_empty(&superblock_security_head)) {
+ 		struct superblock_security_struct *sbsec =
+ 				list_entry(superblock_security_head.next,
+-				           struct superblock_security_struct,
+-				           list);
++					   struct superblock_security_struct,
++					   list);
+ 		struct super_block *sb = sbsec->sb;
+ 		sb->s_count++;
+ 		spin_unlock(&sb_security_lock);
+@@ -5599,10 +5676,11 @@ static void selinux_nf_ip_exit(void)
+ #endif /* CONFIG_NETFILTER */
+ 
+ #ifdef CONFIG_SECURITY_SELINUX_DISABLE
++static int selinux_disabled;
++
+ int selinux_disable(void)
+ {
+ 	extern void exit_sel_fs(void);
+-	static int selinux_disabled = 0;
+ 
+ 	if (ss_initialized) {
+ 		/* Not permitted after initial policy load. */
+@@ -5631,5 +5709,3 @@ int selinux_disable(void)
+ 	return 0;
+ }
+ #endif
+-
+-
+diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h
+new file mode 100644
+index 0000000..6c8b9ef
+--- /dev/null
++++ b/security/selinux/include/audit.h
+@@ -0,0 +1,65 @@
++/*
++ * SELinux support for the Audit LSM hooks
++ *
++ * Most of below header was moved from include/linux/selinux.h which 
++ * is released under below copyrights:
++ *
++ * Author: James Morris <jmorris at redhat.com>
++ *
++ * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris at redhat.com>
++ * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel at trustedcs.com>
++ * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim at us.ibm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2,
++ * as published by the Free Software Foundation.
++ */
++
++#ifndef _SELINUX_AUDIT_H
++#define _SELINUX_AUDIT_H
++
++/**
++ *	selinux_audit_rule_init - alloc/init an selinux audit rule structure.
++ *	@field: the field this rule refers to
++ *	@op: the operater the rule uses
++ *	@rulestr: the text "target" of the rule
++ *	@rule: pointer to the new rule structure returned via this
++ *
++ *	Returns 0 if successful, -errno if not.  On success, the rule structure
++ *	will be allocated internally.  The caller must free this structure with
++ *	selinux_audit_rule_free() after use.
++ */
++int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **rule);
++
++/**
++ *	selinux_audit_rule_free - free an selinux audit rule structure.
++ *	@rule: pointer to the audit rule to be freed
++ *
++ *	This will free all memory associated with the given rule.
++ *	If @rule is NULL, no operation is performed.
++ */
++void selinux_audit_rule_free(void *rule);
++
++/**
++ *	selinux_audit_rule_match - determine if a context ID matches a rule.
++ *	@sid: the context ID to check
++ *	@field: the field this rule refers to
++ *	@op: the operater the rule uses
++ *	@rule: pointer to the audit rule to check against
++ *	@actx: the audit context (can be NULL) associated with the check
++ *
++ *	Returns 1 if the context id matches the rule, 0 if it does not, and
++ *	-errno on failure.
++ */
++int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule,
++                             struct audit_context *actx);
++
++/**
++ *	selinux_audit_rule_known - check to see if rule contains selinux fields.
++ *	@rule: rule to be checked
++ *	Returns 1 if there are selinux fields specified in the rule, 0 otherwise.
++ */
++int selinux_audit_rule_known(struct audit_krule *krule);
++
++#endif /* _SELINUX_AUDIT_H */
++
+diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
+index d569669..1223b4f 100644
+--- a/security/selinux/include/av_perm_to_string.h
++++ b/security/selinux/include/av_perm_to_string.h
+@@ -14,12 +14,17 @@
+    S_(SECCLASS_DIR, DIR__REPARENT, "reparent")
+    S_(SECCLASS_DIR, DIR__SEARCH, "search")
+    S_(SECCLASS_DIR, DIR__RMDIR, "rmdir")
++   S_(SECCLASS_DIR, DIR__OPEN, "open")
+    S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans")
+    S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
+    S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
++   S_(SECCLASS_FILE, FILE__OPEN, "open")
+    S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
+    S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
+    S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
++   S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open")
++   S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open")
++   S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open")
+    S_(SECCLASS_FD, FD__USE, "use")
+    S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
+    S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
+diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
+index 75b4131..c4c5116 100644
+--- a/security/selinux/include/av_permissions.h
++++ b/security/selinux/include/av_permissions.h
+@@ -79,6 +79,7 @@
+ #define DIR__REPARENT                             0x00080000UL
+ #define DIR__SEARCH                               0x00100000UL
+ #define DIR__RMDIR                                0x00200000UL
++#define DIR__OPEN                                 0x00400000UL
+ #define FILE__IOCTL                               0x00000001UL
+ #define FILE__READ                                0x00000002UL
+ #define FILE__WRITE                               0x00000004UL
+@@ -99,6 +100,7 @@
+ #define FILE__EXECUTE_NO_TRANS                    0x00020000UL
+ #define FILE__ENTRYPOINT                          0x00040000UL
+ #define FILE__EXECMOD                             0x00080000UL
++#define FILE__OPEN                                0x00100000UL
+ #define LNK_FILE__IOCTL                           0x00000001UL
+ #define LNK_FILE__READ                            0x00000002UL
+ #define LNK_FILE__WRITE                           0x00000004UL
+@@ -136,6 +138,7 @@
+ #define CHR_FILE__EXECUTE_NO_TRANS                0x00020000UL
+ #define CHR_FILE__ENTRYPOINT                      0x00040000UL
+ #define CHR_FILE__EXECMOD                         0x00080000UL
++#define CHR_FILE__OPEN                            0x00100000UL
+ #define BLK_FILE__IOCTL                           0x00000001UL
+ #define BLK_FILE__READ                            0x00000002UL
+ #define BLK_FILE__WRITE                           0x00000004UL
+@@ -153,6 +156,7 @@
+ #define BLK_FILE__SWAPON                          0x00004000UL
+ #define BLK_FILE__QUOTAON                         0x00008000UL
+ #define BLK_FILE__MOUNTON                         0x00010000UL
++#define BLK_FILE__OPEN                            0x00020000UL
+ #define SOCK_FILE__IOCTL                          0x00000001UL
+ #define SOCK_FILE__READ                           0x00000002UL
+ #define SOCK_FILE__WRITE                          0x00000004UL
+@@ -187,6 +191,7 @@
+ #define FIFO_FILE__SWAPON                         0x00004000UL
+ #define FIFO_FILE__QUOTAON                        0x00008000UL
+ #define FIFO_FILE__MOUNTON                        0x00010000UL
++#define FIFO_FILE__OPEN                           0x00020000UL
+ #define FD__USE                                   0x00000001UL
+ #define SOCKET__IOCTL                             0x00000001UL
+ #define SOCKET__READ                              0x00000002UL
+diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
+index 00a2809..9a9e7cd 100644
+--- a/security/selinux/include/netlabel.h
++++ b/security/selinux/include/netlabel.h
+@@ -41,10 +41,6 @@ void selinux_netlbl_cache_invalidate(void);
+ 
+ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
+ 				      int family);
+-void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
+-				     int family);
+-void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
+-				      struct sk_security_struct *newssec);
+ 
+ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
+ 				 u16 family,
+@@ -73,18 +69,6 @@ static inline void selinux_netlbl_sk_security_reset(
+ {
+ 	return;
+ }
+-static inline void selinux_netlbl_sk_security_init(
+-	                                       struct sk_security_struct *ssec,
+-					       int family)
+-{
+-	return;
+-}
+-static inline void selinux_netlbl_sk_security_clone(
+-	                                    struct sk_security_struct *ssec,
+-					    struct sk_security_struct *newssec)
+-{
+-	return;
+-}
+ 
+ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
+ 					       u16 family,
+diff --git a/security/selinux/include/netport.h b/security/selinux/include/netport.h
+new file mode 100644
+index 0000000..8991752
+--- /dev/null
++++ b/security/selinux/include/netport.h
+@@ -0,0 +1,31 @@
++/*
++ * Network port table
++ *
++ * SELinux must keep a mapping of network ports to labels/SIDs.  This
++ * mapping is maintained as part of the normal policy but a fast cache is
++ * needed to reduce the lookup overhead.
++ *
++ * Author: Paul Moore <paul.moore at hp.com>
++ *
++ */
++
++/*
++ * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
++ *
++ * 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.
++ *
++ */
++
++#ifndef _SELINUX_NETPORT_H
++#define _SELINUX_NETPORT_H
++
++int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid);
++
++#endif
+diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
+index c6c2bb4..300b61b 100644
+--- a/security/selinux/include/objsec.h
++++ b/security/selinux/include/objsec.h
+@@ -28,14 +28,12 @@
+ #include "avc.h"
+ 
+ struct task_security_struct {
+-	struct task_struct *task;      /* back pointer to task object */
+ 	u32 osid;            /* SID prior to last execve */
+ 	u32 sid;             /* current SID */
+ 	u32 exec_sid;        /* exec SID */
+ 	u32 create_sid;      /* fscreate SID */
+ 	u32 keycreate_sid;   /* keycreate SID */
+ 	u32 sockcreate_sid;  /* fscreate SID */
+-	u32 ptrace_sid;      /* SID of ptrace parent */
+ };
+ 
+ struct inode_security_struct {
+@@ -50,7 +48,6 @@ struct inode_security_struct {
+ };
+ 
+ struct file_security_struct {
+-	struct file *file;              /* back pointer to file object */
+ 	u32 sid;              /* SID of open file description */
+ 	u32 fown_sid;         /* SID of file owner (for SIGIO) */
+ 	u32 isid;             /* SID of inode at the time of file open */
+@@ -73,18 +70,15 @@ struct superblock_security_struct {
+ };
+ 
+ struct msg_security_struct {
+-	struct msg_msg *msg;		/* back pointer */
+ 	u32 sid;              /* SID of message */
+ };
+ 
+ struct ipc_security_struct {
+-	struct kern_ipc_perm *ipc_perm; /* back pointer */
+ 	u16 sclass;	/* security class of this object */
+ 	u32 sid;              /* SID of IPC resource */
+ };
+ 
+ struct bprm_security_struct {
+-	struct linux_binprm *bprm;     /* back pointer to bprm object */
+ 	u32 sid;                       /* SID for transformed process */
+ 	unsigned char set;
+ 
+@@ -109,8 +103,13 @@ struct netnode_security_struct {
+ 	u16 family;			/* address family */
+ };
+ 
++struct netport_security_struct {
++	u32 sid;			/* SID for this node */
++	u16 port;			/* port number */
++	u8 protocol;			/* transport protocol */
++};
++
+ struct sk_security_struct {
+-	struct sock *sk;		/* back pointer to sk object */
+ 	u32 sid;			/* SID of this object */
+ 	u32 peer_sid;			/* SID of peer */
+ 	u16 sclass;			/* sock security class */
+@@ -120,12 +119,10 @@ struct sk_security_struct {
+ 		NLBL_REQUIRE,
+ 		NLBL_LABELED,
+ 	} nlbl_state;
+-	spinlock_t nlbl_lock;		/* protects nlbl_state */
+ #endif
+ };
+ 
+ struct key_security_struct {
+-	struct key *obj; /* back pointer */
+ 	u32 sid;         /* SID of key */
+ };
+ 
+diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
+index 44e12ec..1904c46 100644
+--- a/security/selinux/include/security.h
++++ b/security/selinux/include/security.h
+@@ -26,13 +26,14 @@
+ #define POLICYDB_VERSION_AVTAB		20
+ #define POLICYDB_VERSION_RANGETRANS	21
+ #define POLICYDB_VERSION_POLCAP		22
++#define POLICYDB_VERSION_PERMISSIVE	23
+ 
+ /* Range of policy versions we understand*/
+ #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
+ #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
+ #define POLICYDB_VERSION_MAX	CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
+ #else
+-#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_POLCAP
++#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_PERMISSIVE
+ #endif
+ 
+ #define CONTEXT_MNT	0x01
+@@ -40,6 +41,11 @@
+ #define ROOTCONTEXT_MNT	0x04
+ #define DEFCONTEXT_MNT	0x08
+ 
++#define CONTEXT_STR	"context="
++#define FSCONTEXT_STR	"fscontext="
++#define ROOTCONTEXT_STR	"rootcontext="
++#define DEFCONTEXT_STR	"defcontext="
++
+ struct netlbl_lsm_secattr;
+ 
+ extern int selinux_enabled;
+@@ -48,11 +54,13 @@ extern int selinux_mls_enabled;
+ /* Policy capabilities */
+ enum {
+ 	POLICYDB_CAPABILITY_NETPEER,
++	POLICYDB_CAPABILITY_OPENPERM,
+ 	__POLICYDB_CAPABILITY_MAX
+ };
+ #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
+ 
+ extern int selinux_policycap_netpeer;
++extern int selinux_policycap_openperm;
+ 
+ int security_load_policy(void * data, size_t len);
+ 
+@@ -67,6 +75,8 @@ struct av_decision {
+ 	u32 seqno;
+ };
+ 
++int security_permissive_sid(u32 sid);
++
+ int security_compute_av(u32 ssid, u32 tsid,
+ 	u16 tclass, u32 requested,
+ 	struct av_decision *avd);
+@@ -92,8 +102,7 @@ int security_context_to_sid_default(char *scontext, u32 scontext_len,
+ int security_get_user_sids(u32 callsid, char *username,
+ 			   u32 **sids, u32 *nel);
+ 
+-int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port,
+-	u32 *out_sid);
++int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
+ 
+ int security_netif_sid(char *name, u32 *if_sid);
+ 
+diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
+index 36b0510..289e24b 100644
+--- a/security/selinux/include/xfrm.h
++++ b/security/selinux/include/xfrm.h
+@@ -7,16 +7,17 @@
+ #ifndef _SELINUX_XFRM_H_
+ #define _SELINUX_XFRM_H_
+ 
+-int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
+-		struct xfrm_user_sec_ctx *sec_ctx);
+-int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
+-void selinux_xfrm_policy_free(struct xfrm_policy *xp);
+-int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
++int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
++			      struct xfrm_user_sec_ctx *sec_ctx);
++int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
++			      struct xfrm_sec_ctx **new_ctxp);
++void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
++int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
+ int selinux_xfrm_state_alloc(struct xfrm_state *x,
+ 	struct xfrm_user_sec_ctx *sec_ctx, u32 secid);
+ void selinux_xfrm_state_free(struct xfrm_state *x);
+ int selinux_xfrm_state_delete(struct xfrm_state *x);
+-int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
++int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
+ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
+ 			struct xfrm_policy *xp, struct flowi *fl);
+ 
+diff --git a/security/selinux/netif.c b/security/selinux/netif.c
+index 013d311..b4e14bc 100644
+--- a/security/selinux/netif.c
++++ b/security/selinux/netif.c
+@@ -8,7 +8,7 @@
+  *
+  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.com>
+  * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+- *                    Paul Moore <paul.moore at hp.com>
++ *		      Paul Moore <paul.moore at hp.com>
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2,
+@@ -31,8 +31,7 @@
+ #define SEL_NETIF_HASH_SIZE	64
+ #define SEL_NETIF_HASH_MAX	1024
+ 
+-struct sel_netif
+-{
++struct sel_netif {
+ 	struct list_head list;
+ 	struct netif_security_struct nsec;
+ 	struct rcu_head rcu_head;
+@@ -92,10 +91,10 @@ static inline struct sel_netif *sel_netif_find(int ifindex)
+ static int sel_netif_insert(struct sel_netif *netif)
+ {
+ 	int idx;
+-	
++
+ 	if (sel_netif_total >= SEL_NETIF_HASH_MAX)
+ 		return -ENOSPC;
+-	
++
+ 	idx = sel_netif_hashfn(netif->nsec.ifindex);
+ 	list_add_rcu(&netif->list, &sel_netif_hash[idx]);
+ 	sel_netif_total++;
+@@ -240,11 +239,13 @@ static void sel_netif_kill(int ifindex)
+ {
+ 	struct sel_netif *netif;
+ 
++	rcu_read_lock();
+ 	spin_lock_bh(&sel_netif_lock);
+ 	netif = sel_netif_find(ifindex);
+ 	if (netif)
+ 		sel_netif_destroy(netif);
+ 	spin_unlock_bh(&sel_netif_lock);
++	rcu_read_unlock();
+ }
+ 
+ /**
+@@ -267,7 +268,7 @@ static void sel_netif_flush(void)
+ }
+ 
+ static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid,
+-                                  u16 class, u32 perms, u32 *retained)
++				  u16 class, u32 perms, u32 *retained)
+ {
+ 	if (event == AVC_CALLBACK_RESET) {
+ 		sel_netif_flush();
+@@ -277,11 +278,11 @@ static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid,
+ }
+ 
+ static int sel_netif_netdev_notifier_handler(struct notifier_block *this,
+-                                             unsigned long event, void *ptr)
++					     unsigned long event, void *ptr)
+ {
+ 	struct net_device *dev = ptr;
+ 
+-	if (dev->nd_net != &init_net)
++	if (dev_net(dev) != &init_net)
+ 		return NOTIFY_DONE;
+ 
+ 	if (event == NETDEV_DOWN)
+@@ -297,7 +298,7 @@ static struct notifier_block sel_netif_netdev_notifier = {
+ static __init int sel_netif_init(void)
+ {
+ 	int i, err;
+-	
++
+ 	if (!selinux_enabled)
+ 		return 0;
+ 
+@@ -305,9 +306,9 @@ static __init int sel_netif_init(void)
+ 		INIT_LIST_HEAD(&sel_netif_hash[i]);
+ 
+ 	register_netdevice_notifier(&sel_netif_netdev_notifier);
+-	
++
+ 	err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET,
+-	                       SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
++			       SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ 	if (err)
+ 		panic("avc_add_callback() failed, error %d\n", err);
+ 
+diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
+index 0fa2be4..89b4183 100644
+--- a/security/selinux/netlabel.c
++++ b/security/selinux/netlabel.c
+@@ -34,6 +34,7 @@
+ 
+ #include "objsec.h"
+ #include "security.h"
++#include "netlabel.h"
+ 
+ /**
+  * selinux_netlbl_sidlookup_cached - Cache a SID lookup
+@@ -69,9 +70,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
+  *
+  * Description:
+  * Attempt to label a socket using the NetLabel mechanism using the given
+- * SID.  Returns zero values on success, negative values on failure.  The
+- * caller is responsibile for calling rcu_read_lock() before calling this
+- * this function and rcu_read_unlock() after this function returns.
++ * SID.  Returns zero values on success, negative values on failure.
+  *
+  */
+ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
+@@ -86,11 +85,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
+ 	if (rc != 0)
+ 		goto sock_setsid_return;
+ 	rc = netlbl_sock_setattr(sk, &secattr);
+-	if (rc == 0) {
+-		spin_lock_bh(&sksec->nlbl_lock);
++	if (rc == 0)
+ 		sksec->nlbl_state = NLBL_LABELED;
+-		spin_unlock_bh(&sksec->nlbl_lock);
+-	}
+ 
+ sock_setsid_return:
+ 	netlbl_secattr_destroy(&secattr);
+@@ -122,52 +118,13 @@ void selinux_netlbl_cache_invalidate(void)
+ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
+ 				      int family)
+ {
+-        if (family == PF_INET)
++	if (family == PF_INET)
+ 		ssec->nlbl_state = NLBL_REQUIRE;
+ 	else
+ 		ssec->nlbl_state = NLBL_UNSET;
+ }
+ 
+ /**
+- * selinux_netlbl_sk_security_init - Setup the NetLabel fields
+- * @ssec: the sk_security_struct
+- * @family: the socket family
+- *
+- * Description:
+- * Called when a new sk_security_struct is allocated to initialize the NetLabel
+- * fields.
+- *
+- */
+-void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
+-				     int family)
+-{
+-	/* No locking needed, we are the only one who has access to ssec */
+-	selinux_netlbl_sk_security_reset(ssec, family);
+-	spin_lock_init(&ssec->nlbl_lock);
+-}
+-
+-/**
+- * selinux_netlbl_sk_security_clone - Copy the NetLabel fields
+- * @ssec: the original sk_security_struct
+- * @newssec: the cloned sk_security_struct
+- *
+- * Description:
+- * Clone the NetLabel specific sk_security_struct fields from @ssec to
+- * @newssec.
+- *
+- */
+-void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
+-				      struct sk_security_struct *newssec)
+-{
+-	/* We don't need to take newssec->nlbl_lock because we are the only
+-	 * thread with access to newssec, but we do need to take the RCU read
+-	 * lock as other threads could have access to ssec */
+-	rcu_read_lock();
+-	selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
+-	rcu_read_unlock();
+-}
+-
+-/**
+  * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
+  * @skb: the packet
+  * @family: protocol family
+@@ -221,12 +178,8 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
+ 	struct netlbl_lsm_secattr secattr;
+ 	u32 nlbl_peer_sid;
+ 
+-	rcu_read_lock();
+-
+-	if (sksec->nlbl_state != NLBL_REQUIRE) {
+-		rcu_read_unlock();
++	if (sksec->nlbl_state != NLBL_REQUIRE)
+ 		return;
+-	}
+ 
+ 	netlbl_secattr_init(&secattr);
+ 	if (netlbl_sock_getattr(sk, &secattr) == 0 &&
+@@ -239,8 +192,6 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
+ 	 * here we will pick up the pieces in later calls to
+ 	 * selinux_netlbl_inode_permission(). */
+ 	selinux_netlbl_sock_setsid(sk, sksec->sid);
+-
+-	rcu_read_unlock();
+ }
+ 
+ /**
+@@ -254,16 +205,13 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
+  */
+ int selinux_netlbl_socket_post_create(struct socket *sock)
+ {
+-	int rc = 0;
+ 	struct sock *sk = sock->sk;
+ 	struct sk_security_struct *sksec = sk->sk_security;
+ 
+-	rcu_read_lock();
+-	if (sksec->nlbl_state == NLBL_REQUIRE)
+-		rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
+-	rcu_read_unlock();
++	if (sksec->nlbl_state != NLBL_REQUIRE)
++		return 0;
+ 
+-	return rc;
++	return selinux_netlbl_sock_setsid(sk, sksec->sid);
+ }
+ 
+ /**
+@@ -288,21 +236,21 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
+ 	if (!S_ISSOCK(inode->i_mode) ||
+ 	    ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
+ 		return 0;
++
+ 	sock = SOCKET_I(inode);
+ 	sk = sock->sk;
+ 	sksec = sk->sk_security;
+-
+-	rcu_read_lock();
+-	if (sksec->nlbl_state != NLBL_REQUIRE) {
+-		rcu_read_unlock();
++	if (sksec->nlbl_state != NLBL_REQUIRE)
+ 		return 0;
+-	}
++
+ 	local_bh_disable();
+ 	bh_lock_sock_nested(sk);
+-	rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
++	if (likely(sksec->nlbl_state == NLBL_REQUIRE))
++		rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
++	else
++		rc = 0;
+ 	bh_unlock_sock(sk);
+ 	local_bh_enable();
+-	rcu_read_unlock();
+ 
+ 	return rc;
+ }
+@@ -385,7 +333,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
+ 	struct sk_security_struct *sksec = sk->sk_security;
+ 	struct netlbl_lsm_secattr secattr;
+ 
+-	rcu_read_lock();
+ 	if (level == IPPROTO_IP && optname == IP_OPTIONS &&
+ 	    sksec->nlbl_state == NLBL_LABELED) {
+ 		netlbl_secattr_init(&secattr);
+@@ -396,7 +343,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
+ 			rc = -EACCES;
+ 		netlbl_secattr_destroy(&secattr);
+ 	}
+-	rcu_read_unlock();
+ 
+ 	return rc;
+ }
+diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c
+index b59871d..1ae5564 100644
+--- a/security/selinux/netlink.c
++++ b/security/selinux/netlink.c
+@@ -24,16 +24,16 @@ static struct sock *selnl;
+ static int selnl_msglen(int msgtype)
+ {
+ 	int ret = 0;
+-	
++
+ 	switch (msgtype) {
+ 	case SELNL_MSG_SETENFORCE:
+ 		ret = sizeof(struct selnl_msg_setenforce);
+ 		break;
+-	
++
+ 	case SELNL_MSG_POLICYLOAD:
+ 		ret = sizeof(struct selnl_msg_policyload);
+ 		break;
+-		
++
+ 	default:
+ 		BUG();
+ 	}
+@@ -45,15 +45,15 @@ static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *
+ 	switch (msgtype) {
+ 	case SELNL_MSG_SETENFORCE: {
+ 		struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
+-		
++
+ 		memset(msg, 0, len);
+ 		msg->val = *((int *)data);
+ 		break;
+ 	}
+-	
++
+ 	case SELNL_MSG_POLICYLOAD: {
+ 		struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
+-		
++
+ 		memset(msg, 0, len);
+ 		msg->seqno = *((u32 *)data);
+ 		break;
+@@ -70,9 +70,9 @@ static void selnl_notify(int msgtype, void *data)
+ 	sk_buff_data_t tmp;
+ 	struct sk_buff *skb;
+ 	struct nlmsghdr *nlh;
+-	
++
+ 	len = selnl_msglen(msgtype);
+-	
++
+ 	skb = alloc_skb(NLMSG_SPACE(len), GFP_USER);
+ 	if (!skb)
+ 		goto oom;
+@@ -85,11 +85,11 @@ static void selnl_notify(int msgtype, void *data)
+ 	netlink_broadcast(selnl, skb, 0, SELNLGRP_AVC, GFP_USER);
+ out:
+ 	return;
+-	
++
+ nlmsg_failure:
+ 	kfree_skb(skb);
+ oom:
+-	printk(KERN_ERR "SELinux:  OOM in %s\n", __FUNCTION__);
++	printk(KERN_ERR "SELinux:  OOM in %s\n", __func__);
+ 	goto out;
+ }
+ 
+@@ -109,7 +109,7 @@ static int __init selnl_init(void)
+ 				      SELNLGRP_MAX, NULL, NULL, THIS_MODULE);
+ 	if (selnl == NULL)
+ 		panic("SELinux:  Cannot create netlink socket.");
+-	netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);	
++	netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);
+ 	return 0;
+ }
+ 
+diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
+index f3c526f..2edc4c5 100644
+--- a/security/selinux/netnode.c
++++ b/security/selinux/netnode.c
+@@ -344,7 +344,7 @@ static __init int sel_netnode_init(void)
+ 		INIT_LIST_HEAD(&sel_netnode_hash[iter]);
+ 
+ 	ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET,
+-	                       SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
++			       SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ 	if (ret != 0)
+ 		panic("avc_add_callback() failed, error %d\n", ret);
+ 
+diff --git a/security/selinux/netport.c b/security/selinux/netport.c
+new file mode 100644
+index 0000000..68ede3c
+--- /dev/null
++++ b/security/selinux/netport.c
+@@ -0,0 +1,286 @@
++/*
++ * Network port table
++ *
++ * SELinux must keep a mapping of network ports to labels/SIDs.  This
++ * mapping is maintained as part of the normal policy but a fast cache is
++ * needed to reduce the lookup overhead.
++ *
++ * Author: Paul Moore <paul.moore at hp.com>
++ *
++ * This code is heavily based on the "netif" concept originally developed by
++ * James Morris <jmorris at redhat.com>
++ *   (see security/selinux/netif.c for more information)
++ *
++ */
++
++/*
++ * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
++ *
++ * 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.
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/rcupdate.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/in.h>
++#include <linux/in6.h>
++#include <linux/ip.h>
++#include <linux/ipv6.h>
++#include <net/ip.h>
++#include <net/ipv6.h>
++#include <asm/bug.h>
++
++#include "netport.h"
++#include "objsec.h"
++
++#define SEL_NETPORT_HASH_SIZE       256
++#define SEL_NETPORT_HASH_BKT_LIMIT   16
++
++struct sel_netport_bkt {
++	int size;
++	struct list_head list;
++};
++
++struct sel_netport {
++	struct netport_security_struct psec;
++
++	struct list_head list;
++	struct rcu_head rcu;
++};
++
++/* NOTE: we are using a combined hash table for both IPv4 and IPv6, the reason
++ * for this is that I suspect most users will not make heavy use of both
++ * address families at the same time so one table will usually end up wasted,
++ * if this becomes a problem we can always add a hash table for each address
++ * family later */
++
++static LIST_HEAD(sel_netport_list);
++static DEFINE_SPINLOCK(sel_netport_lock);
++static struct sel_netport_bkt sel_netport_hash[SEL_NETPORT_HASH_SIZE];
++
++/**
++ * sel_netport_free - Frees a port entry
++ * @p: the entry's RCU field
++ *
++ * Description:
++ * This function is designed to be used as a callback to the call_rcu()
++ * function so that memory allocated to a hash table port entry can be
++ * released safely.
++ *
++ */
++static void sel_netport_free(struct rcu_head *p)
++{
++	struct sel_netport *port = container_of(p, struct sel_netport, rcu);
++	kfree(port);
++}
++
++/**
++ * sel_netport_hashfn - Hashing function for the port table
++ * @pnum: port number
++ *
++ * Description:
++ * This is the hashing function for the port table, it returns the bucket
++ * number for the given port.
++ *
++ */
++static unsigned int sel_netport_hashfn(u16 pnum)
++{
++	return (pnum & (SEL_NETPORT_HASH_SIZE - 1));
++}
++
++/**
++ * sel_netport_find - Search for a port record
++ * @protocol: protocol
++ * @port: pnum
++ *
++ * Description:
++ * Search the network port table and return the matching record.  If an entry
++ * can not be found in the table return NULL.
++ *
++ */
++static struct sel_netport *sel_netport_find(u8 protocol, u16 pnum)
++{
++	unsigned int idx;
++	struct sel_netport *port;
++
++	idx = sel_netport_hashfn(pnum);
++	list_for_each_entry_rcu(port, &sel_netport_hash[idx].list, list)
++		if (port->psec.port == pnum &&
++		    port->psec.protocol == protocol)
++			return port;
++
++	return NULL;
++}
++
++/**
++ * sel_netport_insert - Insert a new port into the table
++ * @port: the new port record
++ *
++ * Description:
++ * Add a new port record to the network address hash table.  Returns zero on
++ * success, negative values on failure.
++ *
++ */
++static int sel_netport_insert(struct sel_netport *port)
++{
++	unsigned int idx;
++
++	/* we need to impose a limit on the growth of the hash table so check
++	 * this bucket to make sure it is within the specified bounds */
++	idx = sel_netport_hashfn(port->psec.port);
++	list_add_rcu(&port->list, &sel_netport_hash[idx].list);
++	if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) {
++		struct sel_netport *tail;
++		tail = list_entry(port->list.prev, struct sel_netport, list);
++		list_del_rcu(port->list.prev);
++		call_rcu(&tail->rcu, sel_netport_free);
++	} else
++		sel_netport_hash[idx].size++;
++
++	return 0;
++}
++
++/**
++ * sel_netport_sid_slow - Lookup the SID of a network address using the policy
++ * @protocol: protocol
++ * @pnum: port
++ * @sid: port SID
++ *
++ * Description:
++ * This function determines the SID of a network port by quering the security
++ * policy.  The result is added to the network port table to speedup future
++ * queries.  Returns zero on success, negative values on failure.
++ *
++ */
++static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
++{
++	int ret;
++	struct sel_netport *port;
++	struct sel_netport *new = NULL;
++
++	spin_lock_bh(&sel_netport_lock);
++	port = sel_netport_find(protocol, pnum);
++	if (port != NULL) {
++		*sid = port->psec.sid;
++		ret = 0;
++		goto out;
++	}
++	new = kzalloc(sizeof(*new), GFP_ATOMIC);
++	if (new == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++	ret = security_port_sid(protocol, pnum, &new->psec.sid);
++	if (ret != 0)
++		goto out;
++	new->psec.port = pnum;
++	new->psec.protocol = protocol;
++	ret = sel_netport_insert(new);
++	if (ret != 0)
++		goto out;
++	*sid = new->psec.sid;
++
++out:
++	spin_unlock_bh(&sel_netport_lock);
++	if (unlikely(ret)) {
++		printk(KERN_WARNING
++		       "SELinux: failure in sel_netport_sid_slow(),"
++		       " unable to determine network port label\n");
++		kfree(new);
++	}
++	return ret;
++}
++
++/**
++ * sel_netport_sid - Lookup the SID of a network port
++ * @protocol: protocol
++ * @pnum: port
++ * @sid: port SID
++ *
++ * Description:
++ * This function determines the SID of a network port using the fastest method
++ * possible.  First the port table is queried, but if an entry can't be found
++ * then the policy is queried and the result is added to the table to speedup
++ * future queries.  Returns zero on success, negative values on failure.
++ *
++ */
++int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid)
++{
++	struct sel_netport *port;
++
++	rcu_read_lock();
++	port = sel_netport_find(protocol, pnum);
++	if (port != NULL) {
++		*sid = port->psec.sid;
++		rcu_read_unlock();
++		return 0;
++	}
++	rcu_read_unlock();
++
++	return sel_netport_sid_slow(protocol, pnum, sid);
++}
++
++/**
++ * sel_netport_flush - Flush the entire network port table
++ *
++ * Description:
++ * Remove all entries from the network address table.
++ *
++ */
++static void sel_netport_flush(void)
++{
++	unsigned int idx;
++	struct sel_netport *port;
++
++	spin_lock_bh(&sel_netport_lock);
++	for (idx = 0; idx < SEL_NETPORT_HASH_SIZE; idx++) {
++		list_for_each_entry(port, &sel_netport_hash[idx].list, list) {
++			list_del_rcu(&port->list);
++			call_rcu(&port->rcu, sel_netport_free);
++		}
++		sel_netport_hash[idx].size = 0;
++	}
++	spin_unlock_bh(&sel_netport_lock);
++}
++
++static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid,
++				    u16 class, u32 perms, u32 *retained)
++{
++	if (event == AVC_CALLBACK_RESET) {
++		sel_netport_flush();
++		synchronize_net();
++	}
++	return 0;
++}
++
++static __init int sel_netport_init(void)
++{
++	int iter;
++	int ret;
++
++	if (!selinux_enabled)
++		return 0;
++
++	for (iter = 0; iter < SEL_NETPORT_HASH_SIZE; iter++) {
++		INIT_LIST_HEAD(&sel_netport_hash[iter].list);
++		sel_netport_hash[iter].size = 0;
++	}
++
++	ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET,
++	                       SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
++	if (ret != 0)
++		panic("avc_add_callback() failed, error %d\n", ret);
++
++	return ret;
++}
++
++__initcall(sel_netport_init);
+diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
+index eddc7b4..ff59c0c 100644
+--- a/security/selinux/nlmsgtab.c
++++ b/security/selinux/nlmsgtab.c
+@@ -23,8 +23,7 @@
+ #include "flask.h"
+ #include "av_permissions.h"
+ 
+-struct nlmsg_perm
+-{
++struct nlmsg_perm {
+ 	u16	nlmsg_type;
+ 	u32	perm;
+ };
+@@ -159,7 +158,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
+ 		if ((nlmsg_type >= AUDIT_FIRST_USER_MSG &&
+ 		     nlmsg_type <= AUDIT_LAST_USER_MSG) ||
+ 		    (nlmsg_type >= AUDIT_FIRST_USER_MSG2 &&
+-                     nlmsg_type <= AUDIT_LAST_USER_MSG2)) {
++		     nlmsg_type <= AUDIT_LAST_USER_MSG2)) {
+ 			*perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY;
+ 		} else {
+ 			err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
+diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
+index 0341567..ac1ccc1 100644
+--- a/security/selinux/selinuxfs.c
++++ b/security/selinux/selinuxfs.c
+@@ -1,16 +1,16 @@
+ /* Updated: Karl MacMillan <kmacmillan at tresys.com>
+  *
+- * 	Added conditional policy language extensions
++ *	Added conditional policy language extensions
+  *
+  *  Updated: Hewlett-Packard <paul.moore at hp.com>
+  *
+- *      Added support for the policy capability bitmap
++ *	Added support for the policy capability bitmap
+  *
+  * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+  * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris at redhat.com>
+  *	This program is free software; you can redistribute it and/or modify
+- *  	it under the terms of the GNU General Public License as published by
++ *	it under the terms of the GNU General Public License as published by
+  *	the Free Software Foundation, version 2.
+  */
+ 
+@@ -28,7 +28,6 @@
+ #include <linux/percpu.h>
+ #include <linux/audit.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ 
+ /* selinuxfs pseudo filesystem for exporting the security policy API.
+    Based on the proc code and the fs/nfsd/nfsctl.c code. */
+@@ -42,7 +41,8 @@
+ 
+ /* Policy capability filenames */
+ static char *policycap_names[] = {
+-	"network_peer_controls"
++	"network_peer_controls",
++	"open_perms"
+ };
+ 
+ unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
+@@ -57,14 +57,14 @@ int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
+ 
+ static int __init checkreqprot_setup(char *str)
+ {
+-	selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
++	selinux_checkreqprot = simple_strtoul(str, NULL, 0) ? 1 : 0;
+ 	return 1;
+ }
+ __setup("checkreqprot=", checkreqprot_setup);
+ 
+ static int __init selinux_compat_net_setup(char *str)
+ {
+-	selinux_compat_net = simple_strtoul(str,NULL,0) ? 1 : 0;
++	selinux_compat_net = simple_strtoul(str, NULL, 0) ? 1 : 0;
+ 	return 1;
+ }
+ __setup("selinux_compat_net=", selinux_compat_net_setup);
+@@ -73,17 +73,17 @@ __setup("selinux_compat_net=", selinux_compat_net_setup);
+ static DEFINE_MUTEX(sel_mutex);
+ 
+ /* global data for booleans */
+-static struct dentry *bool_dir = NULL;
+-static int bool_num = 0;
++static struct dentry *bool_dir;
++static int bool_num;
+ static char **bool_pending_names;
+-static int *bool_pending_values = NULL;
++static int *bool_pending_values;
+ 
+ /* global data for classes */
+-static struct dentry *class_dir = NULL;
++static struct dentry *class_dir;
+ static unsigned long last_class_ino;
+ 
+ /* global data for policy capabilities */
+-static struct dentry *policycap_dir = NULL;
++static struct dentry *policycap_dir;
+ 
+ extern void selnl_notify_setenforce(int val);
+ 
+@@ -142,7 +142,7 @@ static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
+ }
+ 
+ #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
+-static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
++static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
+ 				 size_t count, loff_t *ppos)
+ 
+ {
+@@ -156,7 +156,7 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
+ 		/* No partial writes. */
+ 		return -EINVAL;
+ 	}
+-	page = (char*)get_zeroed_page(GFP_KERNEL);
++	page = (char *)get_zeroed_page(GFP_KERNEL);
+ 	if (!page)
+ 		return -ENOMEM;
+ 	length = -EFAULT;
+@@ -213,7 +213,7 @@ static const struct file_operations sel_handle_unknown_ops = {
+ };
+ 
+ #ifdef CONFIG_SECURITY_SELINUX_DISABLE
+-static ssize_t sel_write_disable(struct file * file, const char __user * buf,
++static ssize_t sel_write_disable(struct file *file, const char __user *buf,
+ 				 size_t count, loff_t *ppos)
+ 
+ {
+@@ -228,7 +228,7 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf,
+ 		/* No partial writes. */
+ 		return -EINVAL;
+ 	}
+-	page = (char*)get_zeroed_page(GFP_KERNEL);
++	page = (char *)get_zeroed_page(GFP_KERNEL);
+ 	if (!page)
+ 		return -ENOMEM;
+ 	length = -EFAULT;
+@@ -263,7 +263,7 @@ static const struct file_operations sel_disable_ops = {
+ };
+ 
+ static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
+-                                   size_t count, loff_t *ppos)
++				   size_t count, loff_t *ppos)
+ {
+ 	char tmpbuf[TMPBUFLEN];
+ 	ssize_t length;
+@@ -299,7 +299,7 @@ static const struct file_operations sel_mls_ops = {
+ 	.read		= sel_read_mls,
+ };
+ 
+-static ssize_t sel_write_load(struct file * file, const char __user * buf,
++static ssize_t sel_write_load(struct file *file, const char __user *buf,
+ 			      size_t count, loff_t *ppos)
+ 
+ {
+@@ -371,7 +371,7 @@ static const struct file_operations sel_load_ops = {
+ 	.write		= sel_write_load,
+ };
+ 
+-static ssize_t sel_write_context(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_context(struct file *file, char *buf, size_t size)
+ {
+ 	char *canon;
+ 	u32 sid, len;
+@@ -390,8 +390,8 @@ static ssize_t sel_write_context(struct file * file, char *buf, size_t size)
+ 		return length;
+ 
+ 	if (len > SIMPLE_TRANSACTION_LIMIT) {
+-		printk(KERN_ERR "%s:  context size (%u) exceeds payload "
+-		       "max\n", __FUNCTION__, len);
++		printk(KERN_ERR "SELinux: %s:  context size (%u) exceeds "
++			"payload max\n", __func__, len);
+ 		length = -ERANGE;
+ 		goto out;
+ 	}
+@@ -413,7 +413,7 @@ static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
+ 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+ }
+ 
+-static ssize_t sel_write_checkreqprot(struct file * file, const char __user * buf,
++static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
+ 				      size_t count, loff_t *ppos)
+ {
+ 	char *page;
+@@ -430,7 +430,7 @@ static ssize_t sel_write_checkreqprot(struct file * file, const char __user * bu
+ 		/* No partial writes. */
+ 		return -EINVAL;
+ 	}
+-	page = (char*)get_zeroed_page(GFP_KERNEL);
++	page = (char *)get_zeroed_page(GFP_KERNEL);
+ 	if (!page)
+ 		return -ENOMEM;
+ 	length = -EFAULT;
+@@ -462,7 +462,7 @@ static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
+ 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+ }
+ 
+-static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
++static ssize_t sel_write_compat_net(struct file *file, const char __user *buf,
+ 				    size_t count, loff_t *ppos)
+ {
+ 	char *page;
+@@ -479,7 +479,7 @@ static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
+ 		/* No partial writes. */
+ 		return -EINVAL;
+ 	}
+-	page = (char*)get_zeroed_page(GFP_KERNEL);
++	page = (char *)get_zeroed_page(GFP_KERNEL);
+ 	if (!page)
+ 		return -ENOMEM;
+ 	length = -EFAULT;
+@@ -504,11 +504,11 @@ static const struct file_operations sel_compat_net_ops = {
+ /*
+  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
+  */
+-static ssize_t sel_write_access(struct file * file, char *buf, size_t size);
+-static ssize_t sel_write_create(struct file * file, char *buf, size_t size);
+-static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size);
+-static ssize_t sel_write_user(struct file * file, char *buf, size_t size);
+-static ssize_t sel_write_member(struct file * file, char *buf, size_t size);
++static ssize_t sel_write_access(struct file *file, char *buf, size_t size);
++static ssize_t sel_write_create(struct file *file, char *buf, size_t size);
++static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size);
++static ssize_t sel_write_user(struct file *file, char *buf, size_t size);
++static ssize_t sel_write_member(struct file *file, char *buf, size_t size);
+ 
+ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 	[SEL_ACCESS] = sel_write_access,
+@@ -521,7 +521,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ 
+ static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+ {
+-	ino_t ino =  file->f_path.dentry->d_inode->i_ino;
++	ino_t ino = file->f_path.dentry->d_inode->i_ino;
+ 	char *data;
+ 	ssize_t rv;
+ 
+@@ -532,8 +532,8 @@ static ssize_t selinux_transaction_write(struct file *file, const char __user *b
+ 	if (IS_ERR(data))
+ 		return PTR_ERR(data);
+ 
+-	rv =  write_op[ino](file, data, size);
+-	if (rv>0) {
++	rv = write_op[ino](file, data, size);
++	if (rv > 0) {
+ 		simple_transaction_set(file, rv);
+ 		rv = size;
+ 	}
+@@ -552,7 +552,7 @@ static const struct file_operations transaction_ops = {
+  * and the length returned.  Otherwise return 0 or and -error.
+  */
+ 
+-static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
+ {
+ 	char *scon, *tcon;
+ 	u32 ssid, tsid;
+@@ -601,7 +601,7 @@ out:
+ 	return length;
+ }
+ 
+-static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
+ {
+ 	char *scon, *tcon;
+ 	u32 ssid, tsid, newsid;
+@@ -643,8 +643,8 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
+ 		goto out2;
+ 
+ 	if (len > SIMPLE_TRANSACTION_LIMIT) {
+-		printk(KERN_ERR "%s:  context size (%u) exceeds payload "
+-		       "max\n", __FUNCTION__, len);
++		printk(KERN_ERR "SELinux: %s:  context size (%u) exceeds "
++			"payload max\n", __func__, len);
+ 		length = -ERANGE;
+ 		goto out3;
+ 	}
+@@ -660,7 +660,7 @@ out:
+ 	return length;
+ }
+ 
+-static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
+ {
+ 	char *scon, *tcon;
+ 	u32 ssid, tsid, newsid;
+@@ -717,7 +717,7 @@ out:
+ 	return length;
+ }
+ 
+-static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
+ {
+ 	char *con, *user, *ptr;
+ 	u32 sid, *sids;
+@@ -778,7 +778,7 @@ out:
+ 	return length;
+ }
+ 
+-static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
+ {
+ 	char *scon, *tcon;
+ 	u32 ssid, tsid, newsid;
+@@ -820,8 +820,8 @@ static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
+ 		goto out2;
+ 
+ 	if (len > SIMPLE_TRANSACTION_LIMIT) {
+-		printk(KERN_ERR "%s:  context size (%u) exceeds payload "
+-		       "max\n", __FUNCTION__, len);
++		printk(KERN_ERR "SELinux: %s:  context size (%u) exceeds "
++			"payload max\n", __func__, len);
+ 		length = -ERANGE;
+ 		goto out3;
+ 	}
+@@ -872,7 +872,8 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
+ 		ret = -EINVAL;
+ 		goto out;
+ 	}
+-	if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) {
++	page = (char *)get_zeroed_page(GFP_KERNEL);
++	if (!page) {
+ 		ret = -ENOMEM;
+ 		goto out;
+ 	}
+@@ -923,7 +924,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
+ 		length = -EINVAL;
+ 		goto out;
+ 	}
+-	page = (char*)get_zeroed_page(GFP_KERNEL);
++	page = (char *)get_zeroed_page(GFP_KERNEL);
+ 	if (!page) {
+ 		length = -ENOMEM;
+ 		goto out;
+@@ -951,8 +952,8 @@ out:
+ }
+ 
+ static const struct file_operations sel_bool_ops = {
+-	.read           = sel_read_bool,
+-	.write          = sel_write_bool,
++	.read		= sel_read_bool,
++	.write		= sel_write_bool,
+ };
+ 
+ static ssize_t sel_commit_bools_write(struct file *filep,
+@@ -977,7 +978,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
+ 		/* No partial writes. */
+ 		goto out;
+ 	}
+-	page = (char*)get_zeroed_page(GFP_KERNEL);
++	page = (char *)get_zeroed_page(GFP_KERNEL);
+ 	if (!page) {
+ 		length = -ENOMEM;
+ 		goto out;
+@@ -991,9 +992,8 @@ static ssize_t sel_commit_bools_write(struct file *filep,
+ 	if (sscanf(page, "%d", &new_value) != 1)
+ 		goto out;
+ 
+-	if (new_value && bool_pending_values) {
++	if (new_value && bool_pending_values)
+ 		security_set_bools(bool_num, bool_pending_values);
+-	}
+ 
+ 	length = count;
+ 
+@@ -1005,7 +1005,7 @@ out:
+ }
+ 
+ static const struct file_operations sel_commit_bools_ops = {
+-	.write          = sel_commit_bools_write,
++	.write		= sel_commit_bools_write,
+ };
+ 
+ static void sel_remove_entries(struct dentry *de)
+@@ -1055,7 +1055,8 @@ static int sel_make_bools(void)
+ 
+ 	sel_remove_entries(dir);
+ 
+-	if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
++	page = (char *)get_zeroed_page(GFP_KERNEL);
++	if (!page)
+ 		return -ENOMEM;
+ 
+ 	ret = security_get_bools(&num, &names, &values);
+@@ -1082,8 +1083,9 @@ static int sel_make_bools(void)
+ 			ret = -ENAMETOOLONG;
+ 			goto err;
+ 		}
+-		isec = (struct inode_security_struct*)inode->i_security;
+-		if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
++		isec = (struct inode_security_struct *)inode->i_security;
++		ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid);
++		if (ret)
+ 			goto err;
+ 		isec->sid = sid;
+ 		isec->initialized = 1;
+@@ -1111,7 +1113,7 @@ err:
+ 
+ #define NULL_FILE_NAME "null"
+ 
+-struct dentry *selinux_null = NULL;
++struct dentry *selinux_null;
+ 
+ static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
+ 					    size_t count, loff_t *ppos)
+@@ -1123,8 +1125,8 @@ static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
+ 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+ }
+ 
+-static ssize_t sel_write_avc_cache_threshold(struct file * file,
+-					     const char __user * buf,
++static ssize_t sel_write_avc_cache_threshold(struct file *file,
++					     const char __user *buf,
+ 					     size_t count, loff_t *ppos)
+ 
+ {
+@@ -1143,7 +1145,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file * file,
+ 		goto out;
+ 	}
+ 
+-	page = (char*)get_zeroed_page(GFP_KERNEL);
++	page = (char *)get_zeroed_page(GFP_KERNEL);
+ 	if (!page) {
+ 		ret = -ENOMEM;
+ 		goto out;
+@@ -1301,7 +1303,7 @@ out:
+ 	return ret;
+ }
+ 
+-static ssize_t sel_read_initcon(struct file * file, char __user *buf,
++static ssize_t sel_read_initcon(struct file *file, char __user *buf,
+ 				size_t count, loff_t *ppos)
+ {
+ 	struct inode *inode;
+@@ -1375,7 +1377,7 @@ static inline u32 sel_ino_to_perm(unsigned long ino)
+ 	return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
+ }
+ 
+-static ssize_t sel_read_class(struct file * file, char __user *buf,
++static ssize_t sel_read_class(struct file *file, char __user *buf,
+ 				size_t count, loff_t *ppos)
+ {
+ 	ssize_t rc, len;
+@@ -1399,7 +1401,7 @@ static const struct file_operations sel_class_ops = {
+ 	.read		= sel_read_class,
+ };
+ 
+-static ssize_t sel_read_perm(struct file * file, char __user *buf,
++static ssize_t sel_read_perm(struct file *file, char __user *buf,
+ 				size_t count, loff_t *ppos)
+ {
+ 	ssize_t rc, len;
+@@ -1412,7 +1414,7 @@ static ssize_t sel_read_perm(struct file * file, char __user *buf,
+ 		goto out;
+ 	}
+ 
+-	len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
++	len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino));
+ 	rc = simple_read_from_buffer(buf, count, ppos, page, len);
+ 	free_page((unsigned long)page);
+ out:
+@@ -1640,7 +1642,7 @@ out:
+ 	return ret;
+ }
+ 
+-static int sel_fill_super(struct super_block * sb, void * data, int silent)
++static int sel_fill_super(struct super_block *sb, void *data, int silent)
+ {
+ 	int ret;
+ 	struct dentry *dentry;
+@@ -1696,7 +1698,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
+ 		goto err;
+ 	}
+ 	inode->i_ino = ++sel_last_ino;
+-	isec = (struct inode_security_struct*)inode->i_security;
++	isec = (struct inode_security_struct *)inode->i_security;
+ 	isec->sid = SECINITSID_DEVNULL;
+ 	isec->sclass = SECCLASS_CHR_FILE;
+ 	isec->initialized = 1;
+@@ -1760,7 +1762,8 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
+ out:
+ 	return ret;
+ err:
+-	printk(KERN_ERR "%s:  failed while creating inodes\n", __FUNCTION__);
++	printk(KERN_ERR "SELinux: %s:  failed while creating inodes\n",
++		__func__);
+ 	goto out;
+ }
+ 
+diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
+index cd10e27..9e66263 100644
+--- a/security/selinux/ss/avtab.c
++++ b/security/selinux/ss/avtab.c
+@@ -6,15 +6,15 @@
+ 
+ /* Updated: Frank Mayer <mayerf at tresys.com> and Karl MacMillan <kmacmillan at tresys.com>
+  *
+- * 	Added conditional policy language extensions
++ *	Added conditional policy language extensions
+  *
+  * Copyright (C) 2003 Tresys Technology, LLC
+  *	This program is free software; you can redistribute it and/or modify
+- *  	it under the terms of the GNU General Public License as published by
++ *	it under the terms of the GNU General Public License as published by
+  *	the Free Software Foundation, version 2.
+  *
+  * Updated: Yuichi Nakamura <ynakam at hitachisoft.jp>
+- * 	Tuned number of hash slots for avtab to reduce memory usage
++ *	Tuned number of hash slots for avtab to reduce memory usage
+  */
+ 
+ #include <linux/kernel.h>
+@@ -33,10 +33,10 @@ static inline int avtab_hash(struct avtab_key *keyp, u16 mask)
+ 
+ static struct avtab_node*
+ avtab_insert_node(struct avtab *h, int hvalue,
+-		  struct avtab_node * prev, struct avtab_node * cur,
++		  struct avtab_node *prev, struct avtab_node *cur,
+ 		  struct avtab_key *key, struct avtab_datum *datum)
+ {
+-	struct avtab_node * newnode;
++	struct avtab_node *newnode;
+ 	newnode = kmem_cache_zalloc(avtab_node_cachep, GFP_KERNEL);
+ 	if (newnode == NULL)
+ 		return NULL;
+@@ -84,7 +84,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
+ 	}
+ 
+ 	newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
+-	if(!newnode)
++	if (!newnode)
+ 		return -ENOMEM;
+ 
+ 	return 0;
+@@ -95,7 +95,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
+  * It also returns a pointer to the node inserted.
+  */
+ struct avtab_node *
+-avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_datum * datum)
++avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
+ {
+ 	int hvalue;
+ 	struct avtab_node *prev, *cur, *newnode;
+@@ -280,8 +280,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
+ 	h->nel = 0;
+ 	h->nslot = nslot;
+ 	h->mask = mask;
+-	printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated. "
+-	       "Num of rules:%d\n", h->nslot, nrules);
++	printk(KERN_DEBUG "SELinux: %d avtab hash slots, %d rules.\n",
++	       h->nslot, nrules);
+ 	return 0;
+ }
+ 
+@@ -310,8 +310,8 @@ void avtab_hash_eval(struct avtab *h, char *tag)
+ 		}
+ 	}
+ 
+-	printk(KERN_DEBUG "%s:  %d entries and %d/%d buckets used, longest "
+-	       "chain length %d sum of chain length^2 %Lu\n",
++	printk(KERN_DEBUG "SELinux: %s:  %d entries and %d/%d buckets used, "
++	       "longest chain length %d sum of chain length^2 %Lu\n",
+ 	       tag, h->nel, slots_used, h->nslot, max_chain_len,
+ 	       chain2_len_sum);
+ }
+@@ -326,7 +326,7 @@ static uint16_t spec_order[] = {
+ };
+ 
+ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+-	            int (*insertf)(struct avtab *a, struct avtab_key *k,
++		    int (*insertf)(struct avtab *a, struct avtab_key *k,
+ 				   struct avtab_datum *d, void *p),
+ 		    void *p)
+ {
+@@ -345,18 +345,18 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ 	if (vers < POLICYDB_VERSION_AVTAB) {
+ 		rc = next_entry(buf32, fp, sizeof(u32));
+ 		if (rc < 0) {
+-			printk(KERN_ERR "security: avtab: truncated entry\n");
++			printk(KERN_ERR "SELinux: avtab: truncated entry\n");
+ 			return -1;
+ 		}
+ 		items2 = le32_to_cpu(buf32[0]);
+ 		if (items2 > ARRAY_SIZE(buf32)) {
+-			printk(KERN_ERR "security: avtab: entry overflow\n");
++			printk(KERN_ERR "SELinux: avtab: entry overflow\n");
+ 			return -1;
+ 
+ 		}
+ 		rc = next_entry(buf32, fp, sizeof(u32)*items2);
+ 		if (rc < 0) {
+-			printk(KERN_ERR "security: avtab: truncated entry\n");
++			printk(KERN_ERR "SELinux: avtab: truncated entry\n");
+ 			return -1;
+ 		}
+ 		items = 0;
+@@ -364,19 +364,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ 		val = le32_to_cpu(buf32[items++]);
+ 		key.source_type = (u16)val;
+ 		if (key.source_type != val) {
+-			printk("security: avtab: truncated source type\n");
++			printk(KERN_ERR "SELinux: avtab: truncated source type\n");
+ 			return -1;
+ 		}
+ 		val = le32_to_cpu(buf32[items++]);
+ 		key.target_type = (u16)val;
+ 		if (key.target_type != val) {
+-			printk("security: avtab: truncated target type\n");
++			printk(KERN_ERR "SELinux: avtab: truncated target type\n");
+ 			return -1;
+ 		}
+ 		val = le32_to_cpu(buf32[items++]);
+ 		key.target_class = (u16)val;
+ 		if (key.target_class != val) {
+-			printk("security: avtab: truncated target class\n");
++			printk(KERN_ERR "SELinux: avtab: truncated target class\n");
+ 			return -1;
+ 		}
+ 
+@@ -384,12 +384,12 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ 		enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
+ 
+ 		if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
+-			printk("security: avtab: null entry\n");
++			printk(KERN_ERR "SELinux: avtab: null entry\n");
+ 			return -1;
+ 		}
+ 		if ((val & AVTAB_AV) &&
+ 		    (val & AVTAB_TYPE)) {
+-			printk("security: avtab: entry has both access vectors and types\n");
++			printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n");
+ 			return -1;
+ 		}
+ 
+@@ -398,12 +398,13 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ 				key.specified = spec_order[i] | enabled;
+ 				datum.data = le32_to_cpu(buf32[items++]);
+ 				rc = insertf(a, &key, &datum, p);
+-				if (rc) return rc;
++				if (rc)
++					return rc;
+ 			}
+ 		}
+ 
+ 		if (items != items2) {
+-			printk("security: avtab: entry only had %d items, expected %d\n", items2, items);
++			printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items);
+ 			return -1;
+ 		}
+ 		return 0;
+@@ -411,7 +412,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ 
+ 	rc = next_entry(buf16, fp, sizeof(u16)*4);
+ 	if (rc < 0) {
+-		printk("security: avtab: truncated entry\n");
++		printk(KERN_ERR "SELinux: avtab: truncated entry\n");
+ 		return -1;
+ 	}
+ 
+@@ -424,7 +425,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ 	if (!policydb_type_isvalid(pol, key.source_type) ||
+ 	    !policydb_type_isvalid(pol, key.target_type) ||
+ 	    !policydb_class_isvalid(pol, key.target_class)) {
+-		printk(KERN_WARNING "security: avtab: invalid type or class\n");
++		printk(KERN_ERR "SELinux: avtab: invalid type or class\n");
+ 		return -1;
+ 	}
+ 
+@@ -434,20 +435,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ 			set++;
+ 	}
+ 	if (!set || set > 1) {
+-		printk(KERN_WARNING
+-			"security:  avtab:  more than one specifier\n");
++		printk(KERN_ERR "SELinux:  avtab:  more than one specifier\n");
+ 		return -1;
+ 	}
+ 
+ 	rc = next_entry(buf32, fp, sizeof(u32));
+ 	if (rc < 0) {
+-		printk("security: avtab: truncated entry\n");
++		printk(KERN_ERR "SELinux: avtab: truncated entry\n");
+ 		return -1;
+ 	}
+ 	datum.data = le32_to_cpu(*buf32);
+ 	if ((key.specified & AVTAB_TYPE) &&
+ 	    !policydb_type_isvalid(pol, datum.data)) {
+-		printk(KERN_WARNING "security: avtab: invalid type\n");
++		printk(KERN_ERR "SELinux: avtab: invalid type\n");
+ 		return -1;
+ 	}
+ 	return insertf(a, &key, &datum, p);
+@@ -468,12 +468,12 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
+ 
+ 	rc = next_entry(buf, fp, sizeof(u32));
+ 	if (rc < 0) {
+-		printk(KERN_ERR "security: avtab: truncated table\n");
++		printk(KERN_ERR "SELinux: avtab: truncated table\n");
+ 		goto bad;
+ 	}
+ 	nel = le32_to_cpu(buf[0]);
+ 	if (!nel) {
+-		printk(KERN_ERR "security: avtab: table is empty\n");
++		printk(KERN_ERR "SELinux: avtab: table is empty\n");
+ 		rc = -EINVAL;
+ 		goto bad;
+ 	}
+@@ -486,9 +486,9 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
+ 		rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
+ 		if (rc) {
+ 			if (rc == -ENOMEM)
+-				printk(KERN_ERR "security: avtab: out of memory\n");
++				printk(KERN_ERR "SELinux: avtab: out of memory\n");
+ 			else if (rc == -EEXIST)
+-				printk(KERN_ERR "security: avtab: duplicate entry\n");
++				printk(KERN_ERR "SELinux: avtab: duplicate entry\n");
+ 			else
+ 				rc = -EINVAL;
+ 			goto bad;
+@@ -513,5 +513,5 @@ void avtab_cache_init(void)
+ 
+ void avtab_cache_destroy(void)
+ {
+-	kmem_cache_destroy (avtab_node_cachep);
++	kmem_cache_destroy(avtab_node_cachep);
+ }
+diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
+index 50ad85d..fb4efe4 100644
+--- a/security/selinux/ss/conditional.c
++++ b/security/selinux/ss/conditional.c
+@@ -1,9 +1,9 @@
+ /* Authors: Karl MacMillan <kmacmillan at tresys.com>
+- *          Frank Mayer <mayerf at tresys.com>
++ *	    Frank Mayer <mayerf at tresys.com>
+  *
+  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+  *	This program is free software; you can redistribute it and/or modify
+- *  	it under the terms of the GNU General Public License as published by
++ *	it under the terms of the GNU General Public License as published by
+  *	the Free Software Foundation, version 2.
+  */
+ 
+@@ -11,7 +11,6 @@
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/spinlock.h>
+-#include <asm/semaphore.h>
+ #include <linux/slab.h>
+ 
+ #include "security.h"
+@@ -90,29 +89,27 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
+ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
+ {
+ 	int new_state;
+-	struct cond_av_list* cur;
++	struct cond_av_list *cur;
+ 
+ 	new_state = cond_evaluate_expr(p, node->expr);
+ 	if (new_state != node->cur_state) {
+ 		node->cur_state = new_state;
+ 		if (new_state == -1)
+-			printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n");
++			printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
+ 		/* turn the rules on or off */
+ 		for (cur = node->true_list; cur != NULL; cur = cur->next) {
+-			if (new_state <= 0) {
++			if (new_state <= 0)
+ 				cur->node->key.specified &= ~AVTAB_ENABLED;
+-			} else {
++			else
+ 				cur->node->key.specified |= AVTAB_ENABLED;
+-			}
+ 		}
+ 
+ 		for (cur = node->false_list; cur != NULL; cur = cur->next) {
+ 			/* -1 or 1 */
+-			if (new_state) {
++			if (new_state)
+ 				cur->node->key.specified &= ~AVTAB_ENABLED;
+-			} else {
++			else
+ 				cur->node->key.specified |= AVTAB_ENABLED;
+-			}
+ 		}
+ 	}
+ 	return 0;
+@@ -174,8 +171,8 @@ void cond_policydb_destroy(struct policydb *p)
+ int cond_init_bool_indexes(struct policydb *p)
+ {
+ 	kfree(p->bool_val_to_struct);
+-	p->bool_val_to_struct = (struct cond_bool_datum**)
+-		kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL);
++	p->bool_val_to_struct = (struct cond_bool_datum **)
++		kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum *), GFP_KERNEL);
+ 	if (!p->bool_val_to_struct)
+ 		return -1;
+ 	return 0;
+@@ -200,7 +197,7 @@ int cond_index_bool(void *key, void *datum, void *datap)
+ 		return -EINVAL;
+ 
+ 	p->p_bool_val_to_name[booldatum->value - 1] = key;
+-	p->bool_val_to_struct[booldatum->value -1] = booldatum;
++	p->bool_val_to_struct[booldatum->value - 1] = booldatum;
+ 
+ 	return 0;
+ }
+@@ -252,8 +249,7 @@ err:
+ 	return -1;
+ }
+ 
+-struct cond_insertf_data
+-{
++struct cond_insertf_data {
+ 	struct policydb *p;
+ 	struct cond_av_list *other;
+ 	struct cond_av_list *head;
+@@ -276,7 +272,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
+ 	 */
+ 	if (k->specified & AVTAB_TYPE) {
+ 		if (avtab_search(&p->te_avtab, k)) {
+-			printk("security: type rule already exists outside of a conditional.");
++			printk(KERN_ERR "SELinux: type rule already exists outside of a conditional.\n");
+ 			goto err;
+ 		}
+ 		/*
+@@ -291,7 +287,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
+ 			node_ptr = avtab_search_node(&p->te_cond_avtab, k);
+ 			if (node_ptr) {
+ 				if (avtab_search_node_next(node_ptr, k->specified)) {
+-					printk("security: too many conflicting type rules.");
++					printk(KERN_ERR "SELinux: too many conflicting type rules.\n");
+ 					goto err;
+ 				}
+ 				found = 0;
+@@ -302,13 +298,13 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
+ 					}
+ 				}
+ 				if (!found) {
+-					printk("security: conflicting type rules.\n");
++					printk(KERN_ERR "SELinux: conflicting type rules.\n");
+ 					goto err;
+ 				}
+ 			}
+ 		} else {
+ 			if (avtab_search(&p->te_cond_avtab, k)) {
+-				printk("security: conflicting type rules when adding type rule for true.\n");
++				printk(KERN_ERR "SELinux: conflicting type rules when adding type rule for true.\n");
+ 				goto err;
+ 			}
+ 		}
+@@ -316,7 +312,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
+ 
+ 	node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
+ 	if (!node_ptr) {
+-		printk("security: could not insert rule.");
++		printk(KERN_ERR "SELinux: could not insert rule.\n");
+ 		goto err;
+ 	}
+ 
+@@ -353,9 +349,8 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
+ 		return -1;
+ 
+ 	len = le32_to_cpu(buf[0]);
+-	if (len == 0) {
++	if (len == 0)
+ 		return 0;
+-	}
+ 
+ 	data.p = p;
+ 	data.other = other;
+@@ -376,12 +371,12 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
+ static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
+ {
+ 	if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
+-		printk("security: conditional expressions uses unknown operator.\n");
++		printk(KERN_ERR "SELinux: conditional expressions uses unknown operator.\n");
+ 		return 0;
+ 	}
+ 
+ 	if (expr->bool > p->p_bools.nprim) {
+-		printk("security: conditional expressions uses unknown bool.\n");
++		printk(KERN_ERR "SELinux: conditional expressions uses unknown bool.\n");
+ 		return 0;
+ 	}
+ 	return 1;
+@@ -408,15 +403,14 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
+ 	/* expr */
+ 	len = le32_to_cpu(buf[0]);
+ 
+-	for (i = 0; i < len; i++ ) {
++	for (i = 0; i < len; i++) {
+ 		rc = next_entry(buf, fp, sizeof(u32) * 2);
+ 		if (rc < 0)
+ 			goto err;
+ 
+ 		expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL);
+-		if (!expr) {
++		if (!expr)
+ 			goto err;
+-		}
+ 
+ 		expr->expr_type = le32_to_cpu(buf[0]);
+ 		expr->bool = le32_to_cpu(buf[1]);
+@@ -426,11 +420,10 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
+ 			goto err;
+ 		}
+ 
+-		if (i == 0) {
++		if (i == 0)
+ 			node->expr = expr;
+-		} else {
++		else
+ 			last->next = expr;
+-		}
+ 		last = expr;
+ 	}
+ 
+@@ -469,11 +462,10 @@ int cond_read_list(struct policydb *p, void *fp)
+ 		if (cond_read_node(p, node, fp) != 0)
+ 			goto err;
+ 
+-		if (i == 0) {
++		if (i == 0)
+ 			p->cond_list = node;
+-		} else {
++		else
+ 			last->next = node;
+-		}
+ 		last = node;
+ 	}
+ 	return 0;
+@@ -490,24 +482,24 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
+ {
+ 	struct avtab_node *node;
+ 
+-	if(!ctab || !key || !avd)
++	if (!ctab || !key || !avd)
+ 		return;
+ 
+-	for(node = avtab_search_node(ctab, key); node != NULL;
++	for (node = avtab_search_node(ctab, key); node != NULL;
+ 				node = avtab_search_node_next(node, key->specified)) {
+-		if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
+-		     (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
++		if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) ==
++		    (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
+ 			avd->allowed |= node->datum.data;
+-		if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
+-		     (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
++		if ((u16)(AVTAB_AUDITDENY|AVTAB_ENABLED) ==
++		    (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
+ 			/* Since a '0' in an auditdeny mask represents a
+ 			 * permission we do NOT want to audit (dontaudit), we use
+ 			 * the '&' operand to ensure that all '0's in the mask
+ 			 * are retained (much unlike the allow and auditallow cases).
+ 			 */
+ 			avd->auditdeny &= node->datum.data;
+-		if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
+-		     (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
++		if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
++		    (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
+ 			avd->auditallow |= node->datum.data;
+ 	}
+ 	return;
+diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
+index 920b5e3..ddc2754 100644
+--- a/security/selinux/ss/ebitmap.c
++++ b/security/selinux/ss/ebitmap.c
+@@ -364,7 +364,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
+ 	count = le32_to_cpu(buf[2]);
+ 
+ 	if (mapunit != sizeof(u64) * 8) {
+-		printk(KERN_ERR "security: ebitmap: map size %u does not "
++		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);
+ 		goto bad;
+@@ -382,19 +382,19 @@ int ebitmap_read(struct ebitmap *e, void *fp)
+ 	for (i = 0; i < count; i++) {
+ 		rc = next_entry(&startbit, fp, sizeof(u32));
+ 		if (rc < 0) {
+-			printk(KERN_ERR "security: ebitmap: truncated map\n");
++			printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
+ 			goto bad;
+ 		}
+ 		startbit = le32_to_cpu(startbit);
+ 
+ 		if (startbit & (mapunit - 1)) {
+-			printk(KERN_ERR "security: ebitmap start bit (%d) is "
++			printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
+ 			       "not a multiple of the map unit size (%u)\n",
+ 			       startbit, mapunit);
+ 			goto bad;
+ 		}
+ 		if (startbit > e->highbit - mapunit) {
+-			printk(KERN_ERR "security: ebitmap start bit (%d) is "
++			printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
+ 			       "beyond the end of the bitmap (%u)\n",
+ 			       startbit, (e->highbit - mapunit));
+ 			goto bad;
+@@ -405,20 +405,19 @@ int ebitmap_read(struct ebitmap *e, void *fp)
+ 			tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ 			if (!tmp) {
+ 				printk(KERN_ERR
+-				       "security: ebitmap: out of memory\n");
++				       "SELinux: ebitmap: out of memory\n");
+ 				rc = -ENOMEM;
+ 				goto bad;
+ 			}
+ 			/* round down */
+ 			tmp->startbit = startbit - (startbit % EBITMAP_SIZE);
+-			if (n) {
++			if (n)
+ 				n->next = tmp;
+-			} else {
++			else
+ 				e->node = tmp;
+-			}
+ 			n = tmp;
+ 		} else if (startbit <= n->startbit) {
+-			printk(KERN_ERR "security: ebitmap: start bit %d"
++			printk(KERN_ERR "SELinux: ebitmap: start bit %d"
+ 			       " comes after start bit %d\n",
+ 			       startbit, n->startbit);
+ 			goto bad;
+@@ -426,7 +425,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
+ 
+ 		rc = next_entry(&map, fp, sizeof(u64));
+ 		if (rc < 0) {
+-			printk(KERN_ERR "security: ebitmap: truncated map\n");
++			printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
+ 			goto bad;
+ 		}
+ 		map = le64_to_cpu(map);
+diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
+index 77b530c..2e7788e 100644
+--- a/security/selinux/ss/hashtab.c
++++ b/security/selinux/ss/hashtab.c
+@@ -9,8 +9,8 @@
+ #include "hashtab.h"
+ 
+ struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
+-                               int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
+-                               u32 size)
++			       int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
++			       u32 size)
+ {
+ 	struct hashtab *p;
+ 	u32 i;
+diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
+index feaf0a5..8b1706b 100644
+--- a/security/selinux/ss/mls.c
++++ b/security/selinux/ss/mls.c
+@@ -32,7 +32,7 @@
+  * Return the length in bytes for the MLS fields of the
+  * security context string representation of `context'.
+  */
+-int mls_compute_context_len(struct context * context)
++int mls_compute_context_len(struct context *context)
+ {
+ 	int i, l, len, head, prev;
+ 	char *nm;
+@@ -86,7 +86,7 @@ int mls_compute_context_len(struct context * context)
+  * Update `*scontext' to point to the end of the MLS fields.
+  */
+ void mls_sid_to_context(struct context *context,
+-                        char **scontext)
++			char **scontext)
+ {
+ 	char *scontextp, *nm;
+ 	int i, l, head, prev;
+@@ -146,7 +146,7 @@ void mls_sid_to_context(struct context *context,
+ 
+ 		if (l == 0) {
+ 			if (mls_level_eq(&context->range.level[0],
+-			                 &context->range.level[1]))
++					 &context->range.level[1]))
+ 				break;
+ 			else
+ 				*scontextp++ = '-';
+@@ -305,20 +305,21 @@ int mls_context_to_sid(char oldc,
+ 					*p++ = 0;
+ 
+ 				/* Separate into range if exists */
+-				if ((rngptr = strchr(scontextp, '.')) != NULL) {
++				rngptr = strchr(scontextp, '.');
++				if (rngptr != NULL) {
+ 					/* Remove '.' */
+ 					*rngptr++ = 0;
+ 				}
+ 
+ 				catdatum = hashtab_search(policydb.p_cats.table,
+-				                          scontextp);
++							  scontextp);
+ 				if (!catdatum) {
+ 					rc = -EINVAL;
+ 					goto out;
+ 				}
+ 
+ 				rc = ebitmap_set_bit(&context->range.level[l].cat,
+-				                     catdatum->value - 1, 1);
++						     catdatum->value - 1, 1);
+ 				if (rc)
+ 					goto out;
+ 
+@@ -395,7 +396,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+ 		rc = -ENOMEM;
+ 	} else {
+ 		rc = mls_context_to_sid(':', &tmpstr, context,
+-		                        NULL, SECSID_NULL);
++					NULL, SECSID_NULL);
+ 		kfree(freestr);
+ 	}
+ 
+@@ -406,7 +407,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+  * Copies the MLS range `range' into `context'.
+  */
+ static inline int mls_range_set(struct context *context,
+-                                struct mls_range *range)
++				struct mls_range *range)
+ {
+ 	int l, rc = 0;
+ 
+@@ -423,7 +424,7 @@ static inline int mls_range_set(struct context *context,
+ }
+ 
+ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+-                         struct context *usercon)
++			 struct context *usercon)
+ {
+ 	if (selinux_mls_enabled) {
+ 		struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
+@@ -449,11 +450,11 @@ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+ 		   that of the user's default clearance (but
+ 		   only if the "fromcon" clearance dominates
+ 		   the user's computed sensitivity level) */
+-		if (mls_level_dom(user_clr, fromcon_clr)) {
++		if (mls_level_dom(user_clr, fromcon_clr))
+ 			*usercon_clr = *fromcon_clr;
+-		} else if (mls_level_dom(fromcon_clr, user_clr)) {
++		else if (mls_level_dom(fromcon_clr, user_clr))
+ 			*usercon_clr = *user_clr;
+-		} else
++		else
+ 			return -EINVAL;
+ 	}
+ 
+@@ -525,7 +526,7 @@ int mls_compute_sid(struct context *scontext,
+ 			    rtr->target_class == tclass) {
+ 				/* Set the range from the rule */
+ 				return mls_range_set(newcontext,
+-				                     &rtr->target_range);
++						     &rtr->target_range);
+ 			}
+ 		}
+ 		/* Fallthrough */
+diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
+index bd7d6a0..84f8cc7 100644
+--- a/security/selinux/ss/policydb.c
++++ b/security/selinux/ss/policydb.c
+@@ -11,7 +11,7 @@
+  *
+  * Updated: Frank Mayer <mayerf at tresys.com> and Karl MacMillan <kmacmillan at tresys.com>
+  *
+- * 	Added conditional policy language extensions
++ *	Added conditional policy language extensions
+  *
+  * Updated: Hewlett-Packard <paul.moore at hp.com>
+  *
+@@ -21,7 +21,7 @@
+  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+  *	This program is free software; you can redistribute it and/or modify
+- *  	it under the terms of the GNU General Public License as published by
++ *	it under the terms of the GNU General Public License as published by
+  *	the Free Software Foundation, version 2.
+  */
+ 
+@@ -51,7 +51,7 @@ static char *symtab_name[SYM_NUM] = {
+ };
+ #endif
+ 
+-int selinux_mls_enabled = 0;
++int selinux_mls_enabled;
+ 
+ static unsigned int symtab_sizes[SYM_NUM] = {
+ 	2,
+@@ -73,44 +73,49 @@ struct policydb_compat_info {
+ /* These need to be updated if SYM_NUM or OCON_NUM changes */
+ static struct policydb_compat_info policydb_compat[] = {
+ 	{
+-		.version        = POLICYDB_VERSION_BASE,
+-		.sym_num        = SYM_NUM - 3,
+-		.ocon_num       = OCON_NUM - 1,
++		.version	= POLICYDB_VERSION_BASE,
++		.sym_num	= SYM_NUM - 3,
++		.ocon_num	= OCON_NUM - 1,
+ 	},
+ 	{
+-		.version        = POLICYDB_VERSION_BOOL,
+-		.sym_num        = SYM_NUM - 2,
+-		.ocon_num       = OCON_NUM - 1,
++		.version	= POLICYDB_VERSION_BOOL,
++		.sym_num	= SYM_NUM - 2,
++		.ocon_num	= OCON_NUM - 1,
+ 	},
+ 	{
+-		.version        = POLICYDB_VERSION_IPV6,
+-		.sym_num        = SYM_NUM - 2,
+-		.ocon_num       = OCON_NUM,
++		.version	= POLICYDB_VERSION_IPV6,
++		.sym_num	= SYM_NUM - 2,
++		.ocon_num	= OCON_NUM,
+ 	},
+ 	{
+-		.version        = POLICYDB_VERSION_NLCLASS,
+-		.sym_num        = SYM_NUM - 2,
+-		.ocon_num       = OCON_NUM,
++		.version	= POLICYDB_VERSION_NLCLASS,
++		.sym_num	= SYM_NUM - 2,
++		.ocon_num	= OCON_NUM,
+ 	},
+ 	{
+-		.version        = POLICYDB_VERSION_MLS,
+-		.sym_num        = SYM_NUM,
+-		.ocon_num       = OCON_NUM,
++		.version	= POLICYDB_VERSION_MLS,
++		.sym_num	= SYM_NUM,
++		.ocon_num	= OCON_NUM,
+ 	},
+ 	{
+-		.version        = POLICYDB_VERSION_AVTAB,
+-		.sym_num        = SYM_NUM,
+-		.ocon_num       = OCON_NUM,
++		.version	= POLICYDB_VERSION_AVTAB,
++		.sym_num	= SYM_NUM,
++		.ocon_num	= OCON_NUM,
+ 	},
+ 	{
+-		.version        = POLICYDB_VERSION_RANGETRANS,
+-		.sym_num        = SYM_NUM,
+-		.ocon_num       = OCON_NUM,
++		.version	= POLICYDB_VERSION_RANGETRANS,
++		.sym_num	= SYM_NUM,
++		.ocon_num	= OCON_NUM,
+ 	},
+ 	{
+ 		.version	= POLICYDB_VERSION_POLCAP,
+ 		.sym_num	= SYM_NUM,
+ 		.ocon_num	= OCON_NUM,
++	},
++	{
++		.version	= POLICYDB_VERSION_PERMISSIVE,
++		.sym_num	= SYM_NUM,
++		.ocon_num	= OCON_NUM,
+ 	}
+ };
+ 
+@@ -147,7 +152,7 @@ static int roles_init(struct policydb *p)
+ 		rc = -EINVAL;
+ 		goto out_free_role;
+ 	}
+-	key = kmalloc(strlen(OBJECT_R)+1,GFP_KERNEL);
++	key = kmalloc(strlen(OBJECT_R)+1, GFP_KERNEL);
+ 	if (!key) {
+ 		rc = -ENOMEM;
+ 		goto out_free_role;
+@@ -194,6 +199,7 @@ static int policydb_init(struct policydb *p)
+ 		goto out_free_symtab;
+ 
+ 	ebitmap_init(&p->policycaps);
++	ebitmap_init(&p->permissive_map);
+ 
+ out:
+ 	return rc;
+@@ -384,7 +390,7 @@ static void symtab_hash_eval(struct symtab *s)
+ 		struct hashtab_info info;
+ 
+ 		hashtab_stat(h, &info);
+-		printk(KERN_DEBUG "%s:  %d entries and %d/%d buckets used, "
++		printk(KERN_DEBUG "SELinux: %s:  %d entries and %d/%d buckets used, "
+ 		       "longest chain length %d\n", symtab_name[i], h->nel,
+ 		       info.slots_used, h->size, info.max_chain_len);
+ 	}
+@@ -401,14 +407,14 @@ static int policydb_index_others(struct policydb *p)
+ {
+ 	int i, rc = 0;
+ 
+-	printk(KERN_DEBUG "security:  %d users, %d roles, %d types, %d bools",
++	printk(KERN_DEBUG "SELinux:  %d users, %d roles, %d types, %d bools",
+ 	       p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
+ 	if (selinux_mls_enabled)
+ 		printk(", %d sens, %d cats", p->p_levels.nprim,
+ 		       p->p_cats.nprim);
+ 	printk("\n");
+ 
+-	printk(KERN_DEBUG "security:  %d classes, %d rules\n",
++	printk(KERN_DEBUG "SELinux:  %d classes, %d rules\n",
+ 	       p->p_classes.nprim, p->te_avtab.nel);
+ 
+ #ifdef DEBUG_HASHES
+@@ -418,7 +424,7 @@ static int policydb_index_others(struct policydb *p)
+ 
+ 	p->role_val_to_struct =
+ 		kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),
+-		        GFP_KERNEL);
++			GFP_KERNEL);
+ 	if (!p->role_val_to_struct) {
+ 		rc = -ENOMEM;
+ 		goto out;
+@@ -426,7 +432,7 @@ static int policydb_index_others(struct policydb *p)
+ 
+ 	p->user_val_to_struct =
+ 		kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),
+-		        GFP_KERNEL);
++			GFP_KERNEL);
+ 	if (!p->user_val_to_struct) {
+ 		rc = -ENOMEM;
+ 		goto out;
+@@ -628,7 +634,7 @@ void policydb_destroy(struct policydb *p)
+ 		while (c) {
+ 			ctmp = c;
+ 			c = c->next;
+-			ocontext_destroy(ctmp,i);
++			ocontext_destroy(ctmp, i);
+ 		}
+ 		p->ocontexts[i] = NULL;
+ 	}
+@@ -641,7 +647,7 @@ void policydb_destroy(struct policydb *p)
+ 		while (c) {
+ 			ctmp = c;
+ 			c = c->next;
+-			ocontext_destroy(ctmp,OCON_FSUSE);
++			ocontext_destroy(ctmp, OCON_FSUSE);
+ 		}
+ 		gtmp = g;
+ 		g = g->next;
+@@ -658,14 +664,14 @@ void policydb_destroy(struct policydb *p)
+ 	}
+ 	kfree(ltr);
+ 
+-	for (ra = p->role_allow; ra; ra = ra -> next) {
++	for (ra = p->role_allow; ra; ra = ra->next) {
+ 		cond_resched();
+ 		kfree(lra);
+ 		lra = ra;
+ 	}
+ 	kfree(lra);
+ 
+-	for (rt = p->range_tr; rt; rt = rt -> next) {
++	for (rt = p->range_tr; rt; rt = rt->next) {
+ 		cond_resched();
+ 		if (lrt) {
+ 			ebitmap_destroy(&lrt->target_range.level[0].cat);
+@@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p)
+ 	kfree(p->type_attr_map);
+ 	kfree(p->undefined_perms);
+ 	ebitmap_destroy(&p->policycaps);
++	ebitmap_destroy(&p->permissive_map);
+ 
+ 	return;
+ }
+@@ -702,20 +709,20 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s)
+ 
+ 	rc = sidtab_init(s);
+ 	if (rc) {
+-		printk(KERN_ERR "security:  out of memory on SID table init\n");
++		printk(KERN_ERR "SELinux:  out of memory on SID table init\n");
+ 		goto out;
+ 	}
+ 
+ 	head = p->ocontexts[OCON_ISID];
+ 	for (c = head; c; c = c->next) {
+ 		if (!c->context[0].user) {
+-			printk(KERN_ERR "security:  SID %s was never "
++			printk(KERN_ERR "SELinux:  SID %s was never "
+ 			       "defined.\n", c->u.name);
+ 			rc = -EINVAL;
+ 			goto out;
+ 		}
+ 		if (sidtab_insert(s, c->sid[0], &c->context[0])) {
+-			printk(KERN_ERR "security:  unable to load initial "
++			printk(KERN_ERR "SELinux:  unable to load initial "
+ 			       "SID %s.\n", c->u.name);
+ 			rc = -EINVAL;
+ 			goto out;
+@@ -809,13 +816,13 @@ static int mls_read_range_helper(struct mls_range *r, void *fp)
+ 
+ 	items = le32_to_cpu(buf[0]);
+ 	if (items > ARRAY_SIZE(buf)) {
+-		printk(KERN_ERR "security: mls:  range overflow\n");
++		printk(KERN_ERR "SELinux: mls:  range overflow\n");
+ 		rc = -EINVAL;
+ 		goto out;
+ 	}
+ 	rc = next_entry(buf, fp, sizeof(u32) * items);
+ 	if (rc < 0) {
+-		printk(KERN_ERR "security: mls:  truncated range\n");
++		printk(KERN_ERR "SELinux: mls:  truncated range\n");
+ 		goto out;
+ 	}
+ 	r->level[0].sens = le32_to_cpu(buf[0]);
+@@ -826,21 +833,21 @@ static int mls_read_range_helper(struct mls_range *r, void *fp)
+ 
+ 	rc = ebitmap_read(&r->level[0].cat, fp);
+ 	if (rc) {
+-		printk(KERN_ERR "security: mls:  error reading low "
++		printk(KERN_ERR "SELinux: mls:  error reading low "
+ 		       "categories\n");
+ 		goto out;
+ 	}
+ 	if (items > 1) {
+ 		rc = ebitmap_read(&r->level[1].cat, fp);
+ 		if (rc) {
+-			printk(KERN_ERR "security: mls:  error reading high "
++			printk(KERN_ERR "SELinux: mls:  error reading high "
+ 			       "categories\n");
+ 			goto bad_high;
+ 		}
+ 	} else {
+ 		rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
+ 		if (rc) {
+-			printk(KERN_ERR "security: mls:  out of memory\n");
++			printk(KERN_ERR "SELinux: mls:  out of memory\n");
+ 			goto bad_high;
+ 		}
+ 	}
+@@ -866,7 +873,7 @@ static int context_read_and_validate(struct context *c,
+ 
+ 	rc = next_entry(buf, fp, sizeof buf);
+ 	if (rc < 0) {
+-		printk(KERN_ERR "security: context truncated\n");
++		printk(KERN_ERR "SELinux: context truncated\n");
+ 		goto out;
+ 	}
+ 	c->user = le32_to_cpu(buf[0]);
+@@ -874,7 +881,7 @@ static int context_read_and_validate(struct context *c,
+ 	c->type = le32_to_cpu(buf[2]);
+ 	if (p->policyvers >= POLICYDB_VERSION_MLS) {
+ 		if (mls_read_range_helper(&c->range, fp)) {
+-			printk(KERN_ERR "security: error reading MLS range of "
++			printk(KERN_ERR "SELinux: error reading MLS range of "
+ 			       "context\n");
+ 			rc = -EINVAL;
+ 			goto out;
+@@ -882,7 +889,7 @@ static int context_read_and_validate(struct context *c,
+ 	}
+ 
+ 	if (!policydb_context_isvalid(p, c)) {
+-		printk(KERN_ERR "security:  invalid security context\n");
++		printk(KERN_ERR "SELinux:  invalid security context\n");
+ 		context_destroy(c);
+ 		rc = -EINVAL;
+ 	}
+@@ -917,7 +924,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
+ 	len = le32_to_cpu(buf[0]);
+ 	perdatum->value = le32_to_cpu(buf[1]);
+ 
+-	key = kmalloc(len + 1,GFP_KERNEL);
++	key = kmalloc(len + 1, GFP_KERNEL);
+ 	if (!key) {
+ 		rc = -ENOMEM;
+ 		goto bad;
+@@ -964,7 +971,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
+ 	comdatum->permissions.nprim = le32_to_cpu(buf[2]);
+ 	nel = le32_to_cpu(buf[3]);
+ 
+-	key = kmalloc(len + 1,GFP_KERNEL);
++	key = kmalloc(len + 1, GFP_KERNEL);
+ 	if (!key) {
+ 		rc = -ENOMEM;
+ 		goto bad;
+@@ -991,7 +998,7 @@ bad:
+ }
+ 
+ static int read_cons_helper(struct constraint_node **nodep, int ncons,
+-                            int allowxtarget, void *fp)
++			    int allowxtarget, void *fp)
+ {
+ 	struct constraint_node *c, *lc;
+ 	struct constraint_expr *e, *le;
+@@ -1005,11 +1012,10 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
+ 		if (!c)
+ 			return -ENOMEM;
+ 
+-		if (lc) {
++		if (lc)
+ 			lc->next = c;
+-		} else {
++		else
+ 			*nodep = c;
+-		}
+ 
+ 		rc = next_entry(buf, fp, (sizeof(u32) * 2));
+ 		if (rc < 0)
+@@ -1023,11 +1029,10 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
+ 			if (!e)
+ 				return -ENOMEM;
+ 
+-			if (le) {
++			if (le)
+ 				le->next = e;
+-			} else {
++			else
+ 				c->expr = e;
+-			}
+ 
+ 			rc = next_entry(buf, fp, (sizeof(u32) * 3));
+ 			if (rc < 0)
+@@ -1104,7 +1109,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
+ 
+ 	ncons = le32_to_cpu(buf[5]);
+ 
+-	key = kmalloc(len + 1,GFP_KERNEL);
++	key = kmalloc(len + 1, GFP_KERNEL);
+ 	if (!key) {
+ 		rc = -ENOMEM;
+ 		goto bad;
+@@ -1115,7 +1120,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
+ 	key[len] = 0;
+ 
+ 	if (len2) {
+-		cladatum->comkey = kmalloc(len2 + 1,GFP_KERNEL);
++		cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
+ 		if (!cladatum->comkey) {
+ 			rc = -ENOMEM;
+ 			goto bad;
+@@ -1128,7 +1133,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
+ 		cladatum->comdatum = hashtab_search(p->p_commons.table,
+ 						    cladatum->comkey);
+ 		if (!cladatum->comdatum) {
+-			printk(KERN_ERR "security:  unknown common %s\n",
++			printk(KERN_ERR "SELinux:  unknown common %s\n",
+ 			       cladatum->comkey);
+ 			rc = -EINVAL;
+ 			goto bad;
+@@ -1188,7 +1193,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
+ 	len = le32_to_cpu(buf[0]);
+ 	role->value = le32_to_cpu(buf[1]);
+ 
+-	key = kmalloc(len + 1,GFP_KERNEL);
++	key = kmalloc(len + 1, GFP_KERNEL);
+ 	if (!key) {
+ 		rc = -ENOMEM;
+ 		goto bad;
+@@ -1208,7 +1213,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
+ 
+ 	if (strcmp(key, OBJECT_R) == 0) {
+ 		if (role->value != OBJECT_R_VAL) {
+-			printk(KERN_ERR "Role %s has wrong value %d\n",
++			printk(KERN_ERR "SELinux: Role %s has wrong value %d\n",
+ 			       OBJECT_R, role->value);
+ 			rc = -EINVAL;
+ 			goto bad;
+@@ -1235,7 +1240,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
+ 	__le32 buf[3];
+ 	u32 len;
+ 
+-	typdatum = kzalloc(sizeof(*typdatum),GFP_KERNEL);
++	typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
+ 	if (!typdatum) {
+ 		rc = -ENOMEM;
+ 		return rc;
+@@ -1249,7 +1254,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
+ 	typdatum->value = le32_to_cpu(buf[1]);
+ 	typdatum->primary = le32_to_cpu(buf[2]);
+ 
+-	key = kmalloc(len + 1,GFP_KERNEL);
++	key = kmalloc(len + 1, GFP_KERNEL);
+ 	if (!key) {
+ 		rc = -ENOMEM;
+ 		goto bad;
+@@ -1283,13 +1288,13 @@ static int mls_read_level(struct mls_level *lp, void *fp)
+ 
+ 	rc = next_entry(buf, fp, sizeof buf);
+ 	if (rc < 0) {
+-		printk(KERN_ERR "security: mls: truncated level\n");
++		printk(KERN_ERR "SELinux: mls: truncated level\n");
+ 		goto bad;
+ 	}
+ 	lp->sens = le32_to_cpu(buf[0]);
+ 
+ 	if (ebitmap_read(&lp->cat, fp)) {
+-		printk(KERN_ERR "security: mls:  error reading level "
++		printk(KERN_ERR "SELinux: mls:  error reading level "
+ 		       "categories\n");
+ 		goto bad;
+ 	}
+@@ -1321,7 +1326,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
+ 	len = le32_to_cpu(buf[0]);
+ 	usrdatum->value = le32_to_cpu(buf[1]);
+ 
+-	key = kmalloc(len + 1,GFP_KERNEL);
++	key = kmalloc(len + 1, GFP_KERNEL);
+ 	if (!key) {
+ 		rc = -ENOMEM;
+ 		goto bad;
+@@ -1375,7 +1380,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
+ 	len = le32_to_cpu(buf[0]);
+ 	levdatum->isalias = le32_to_cpu(buf[1]);
+ 
+-	key = kmalloc(len + 1,GFP_ATOMIC);
++	key = kmalloc(len + 1, GFP_ATOMIC);
+ 	if (!key) {
+ 		rc = -ENOMEM;
+ 		goto bad;
+@@ -1427,7 +1432,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
+ 	catdatum->value = le32_to_cpu(buf[1]);
+ 	catdatum->isalias = le32_to_cpu(buf[2]);
+ 
+-	key = kmalloc(len + 1,GFP_ATOMIC);
++	key = kmalloc(len + 1, GFP_ATOMIC);
+ 	if (!key) {
+ 		rc = -ENOMEM;
+ 		goto bad;
+@@ -1486,12 +1491,12 @@ int policydb_read(struct policydb *p, void *fp)
+ 		goto out;
+ 
+ 	/* Read the magic number and string length. */
+-	rc = next_entry(buf, fp, sizeof(u32)* 2);
++	rc = next_entry(buf, fp, sizeof(u32) * 2);
+ 	if (rc < 0)
+ 		goto bad;
+ 
+ 	if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
+-		printk(KERN_ERR "security:  policydb magic number 0x%x does "
++		printk(KERN_ERR "SELinux:  policydb magic number 0x%x does "
+ 		       "not match expected magic number 0x%x\n",
+ 		       le32_to_cpu(buf[0]), POLICYDB_MAGIC);
+ 		goto bad;
+@@ -1499,27 +1504,27 @@ int policydb_read(struct policydb *p, void *fp)
+ 
+ 	len = le32_to_cpu(buf[1]);
+ 	if (len != strlen(POLICYDB_STRING)) {
+-		printk(KERN_ERR "security:  policydb string length %d does not "
++		printk(KERN_ERR "SELinux:  policydb string length %d does not "
+ 		       "match expected length %Zu\n",
+ 		       len, strlen(POLICYDB_STRING));
+ 		goto bad;
+ 	}
+-	policydb_str = kmalloc(len + 1,GFP_KERNEL);
++	policydb_str = kmalloc(len + 1, GFP_KERNEL);
+ 	if (!policydb_str) {
+-		printk(KERN_ERR "security:  unable to allocate memory for policydb "
++		printk(KERN_ERR "SELinux:  unable to allocate memory for policydb "
+ 		       "string of length %d\n", len);
+ 		rc = -ENOMEM;
+ 		goto bad;
+ 	}
+ 	rc = next_entry(policydb_str, fp, len);
+ 	if (rc < 0) {
+-		printk(KERN_ERR "security:  truncated policydb string identifier\n");
++		printk(KERN_ERR "SELinux:  truncated policydb string identifier\n");
+ 		kfree(policydb_str);
+ 		goto bad;
+ 	}
+ 	policydb_str[len] = 0;
+ 	if (strcmp(policydb_str, POLICYDB_STRING)) {
+-		printk(KERN_ERR "security:  policydb string %s does not match "
++		printk(KERN_ERR "SELinux:  policydb string %s does not match "
+ 		       "my string %s\n", policydb_str, POLICYDB_STRING);
+ 		kfree(policydb_str);
+ 		goto bad;
+@@ -1536,30 +1541,31 @@ int policydb_read(struct policydb *p, void *fp)
+ 	p->policyvers = le32_to_cpu(buf[0]);
+ 	if (p->policyvers < POLICYDB_VERSION_MIN ||
+ 	    p->policyvers > POLICYDB_VERSION_MAX) {
+-	    	printk(KERN_ERR "security:  policydb version %d does not match "
+-	    	       "my version range %d-%d\n",
+-	    	       le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
+-	    	goto bad;
++		printk(KERN_ERR "SELinux:  policydb version %d does not match "
++		       "my version range %d-%d\n",
++		       le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
++		goto bad;
+ 	}
+ 
+ 	if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
+ 		if (ss_initialized && !selinux_mls_enabled) {
+-			printk(KERN_ERR "Cannot switch between non-MLS and MLS "
+-			       "policies\n");
++			printk(KERN_ERR "SELinux: Cannot switch between non-MLS"
++				" and MLS policies\n");
+ 			goto bad;
+ 		}
+ 		selinux_mls_enabled = 1;
+ 		config |= POLICYDB_CONFIG_MLS;
+ 
+ 		if (p->policyvers < POLICYDB_VERSION_MLS) {
+-			printk(KERN_ERR "security policydb version %d (MLS) "
+-			       "not backwards compatible\n", p->policyvers);
++			printk(KERN_ERR "SELinux: security policydb version %d "
++				"(MLS) not backwards compatible\n",
++				p->policyvers);
+ 			goto bad;
+ 		}
+ 	} else {
+ 		if (ss_initialized && selinux_mls_enabled) {
+-			printk(KERN_ERR "Cannot switch between MLS and non-MLS "
+-			       "policies\n");
++			printk(KERN_ERR "SELinux: Cannot switch between MLS and"
++				" non-MLS policies\n");
+ 			goto bad;
+ 		}
+ 	}
+@@ -1570,16 +1576,20 @@ int policydb_read(struct policydb *p, void *fp)
+ 	    ebitmap_read(&p->policycaps, fp) != 0)
+ 		goto bad;
+ 
++	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
++	    ebitmap_read(&p->permissive_map, fp) != 0)
++		goto bad;
++
+ 	info = policydb_lookup_compat(p->policyvers);
+ 	if (!info) {
+-		printk(KERN_ERR "security:  unable to find policy compat info "
++		printk(KERN_ERR "SELinux:  unable to find policy compat info "
+ 		       "for version %d\n", p->policyvers);
+ 		goto bad;
+ 	}
+ 
+ 	if (le32_to_cpu(buf[2]) != info->sym_num ||
+ 		le32_to_cpu(buf[3]) != info->ocon_num) {
+-		printk(KERN_ERR "security:  policydb table sizes (%d,%d) do "
++		printk(KERN_ERR "SELinux:  policydb table sizes (%d,%d) do "
+ 		       "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
+ 			le32_to_cpu(buf[3]),
+ 		       info->sym_num, info->ocon_num);
+@@ -1622,11 +1632,10 @@ int policydb_read(struct policydb *p, void *fp)
+ 			rc = -ENOMEM;
+ 			goto bad;
+ 		}
+-		if (ltr) {
++		if (ltr)
+ 			ltr->next = tr;
+-		} else {
++		else
+ 			p->role_tr = tr;
+-		}
+ 		rc = next_entry(buf, fp, sizeof(u32)*3);
+ 		if (rc < 0)
+ 			goto bad;
+@@ -1653,11 +1662,10 @@ int policydb_read(struct policydb *p, void *fp)
+ 			rc = -ENOMEM;
+ 			goto bad;
+ 		}
+-		if (lra) {
++		if (lra)
+ 			lra->next = ra;
+-		} else {
++		else
+ 			p->role_allow = ra;
+-		}
+ 		rc = next_entry(buf, fp, sizeof(u32)*2);
+ 		if (rc < 0)
+ 			goto bad;
+@@ -1691,11 +1699,10 @@ int policydb_read(struct policydb *p, void *fp)
+ 				rc = -ENOMEM;
+ 				goto bad;
+ 			}
+-			if (l) {
++			if (l)
+ 				l->next = c;
+-			} else {
++			else
+ 				p->ocontexts[i] = c;
+-			}
+ 			l = c;
+ 			rc = -EINVAL;
+ 			switch (i) {
+@@ -1714,7 +1721,7 @@ int policydb_read(struct policydb *p, void *fp)
+ 				if (rc < 0)
+ 					goto bad;
+ 				len = le32_to_cpu(buf[0]);
+-				c->u.name = kmalloc(len + 1,GFP_KERNEL);
++				c->u.name = kmalloc(len + 1, GFP_KERNEL);
+ 				if (!c->u.name) {
+ 					rc = -ENOMEM;
+ 					goto bad;
+@@ -1742,7 +1749,7 @@ int policydb_read(struct policydb *p, void *fp)
+ 					goto bad;
+ 				break;
+ 			case OCON_NODE:
+-				rc = next_entry(buf, fp, sizeof(u32)* 2);
++				rc = next_entry(buf, fp, sizeof(u32) * 2);
+ 				if (rc < 0)
+ 					goto bad;
+ 				c->u.node.addr = le32_to_cpu(buf[0]);
+@@ -1759,7 +1766,7 @@ int policydb_read(struct policydb *p, void *fp)
+ 				if (c->v.behavior > SECURITY_FS_USE_NONE)
+ 					goto bad;
+ 				len = le32_to_cpu(buf[1]);
+-				c->u.name = kmalloc(len + 1,GFP_KERNEL);
++				c->u.name = kmalloc(len + 1, GFP_KERNEL);
+ 				if (!c->u.name) {
+ 					rc = -ENOMEM;
+ 					goto bad;
+@@ -1807,7 +1814,7 @@ int policydb_read(struct policydb *p, void *fp)
+ 			goto bad;
+ 		}
+ 
+-		newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL);
++		newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL);
+ 		if (!newgenfs->fstype) {
+ 			rc = -ENOMEM;
+ 			kfree(newgenfs);
+@@ -1823,7 +1830,7 @@ int policydb_read(struct policydb *p, void *fp)
+ 		for (genfs_p = NULL, genfs = p->genfs; genfs;
+ 		     genfs_p = genfs, genfs = genfs->next) {
+ 			if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
+-				printk(KERN_ERR "security:  dup genfs "
++				printk(KERN_ERR "SELinux:  dup genfs "
+ 				       "fstype %s\n", newgenfs->fstype);
+ 				kfree(newgenfs->fstype);
+ 				kfree(newgenfs);
+@@ -1853,7 +1860,7 @@ int policydb_read(struct policydb *p, void *fp)
+ 				goto bad;
+ 			}
+ 
+-			newc->u.name = kmalloc(len + 1,GFP_KERNEL);
++			newc->u.name = kmalloc(len + 1, GFP_KERNEL);
+ 			if (!newc->u.name) {
+ 				rc = -ENOMEM;
+ 				goto bad_newc;
+@@ -1873,7 +1880,7 @@ int policydb_read(struct policydb *p, void *fp)
+ 				if (!strcmp(newc->u.name, c->u.name) &&
+ 				    (!c->v.sclass || !newc->v.sclass ||
+ 				     newc->v.sclass == c->v.sclass)) {
+-					printk(KERN_ERR "security:  dup genfs "
++					printk(KERN_ERR "SELinux:  dup genfs "
+ 					       "entry (%s,%s)\n",
+ 					       newgenfs->fstype, c->u.name);
+ 					goto bad_newc;
+@@ -1931,7 +1938,7 @@ int policydb_read(struct policydb *p, void *fp)
+ 			if (rc)
+ 				goto bad;
+ 			if (!mls_range_isvalid(p, &rt->target_range)) {
+-				printk(KERN_WARNING "security:  rangetrans:  invalid range\n");
++				printk(KERN_WARNING "SELinux:  rangetrans:  invalid range\n");
+ 				goto bad;
+ 			}
+ 			lrt = rt;
+@@ -1957,7 +1964,7 @@ int policydb_read(struct policydb *p, void *fp)
+ out:
+ 	return rc;
+ bad_newc:
+-	ocontext_destroy(newc,OCON_FSUSE);
++	ocontext_destroy(newc, OCON_FSUSE);
+ bad:
+ 	if (!rc)
+ 		rc = -EINVAL;
+diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
+index c4ce996..ba593a3 100644
+--- a/security/selinux/ss/policydb.h
++++ b/security/selinux/ss/policydb.h
+@@ -243,6 +243,8 @@ struct policydb {
+ 
+ 	struct ebitmap policycaps;
+ 
++	struct ebitmap permissive_map;
++
+ 	unsigned int policyvers;
+ 
+ 	unsigned int reject_unknown : 1;
+diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
+index 3f2bad2..2daaddb 100644
+--- a/security/selinux/ss/services.c
++++ b/security/selinux/ss/services.c
+@@ -2,7 +2,7 @@
+  * Implementation of the security services.
+  *
+  * Authors : Stephen Smalley, <sds at epoch.ncsc.mil>
+- *           James Morris <jmorris at redhat.com>
++ *	     James Morris <jmorris at redhat.com>
+  *
+  * Updated: Trusted Computer Solutions, Inc. <dgoeddel at trustedcs.com>
+  *
+@@ -11,7 +11,7 @@
+  *
+  * Updated: Frank Mayer <mayerf at tresys.com> and Karl MacMillan <kmacmillan at tresys.com>
+  *
+- * 	Added conditional policy language extensions
++ *	Added conditional policy language extensions
+  *
+  * Updated: Hewlett-Packard <paul.moore at hp.com>
+  *
+@@ -27,7 +27,7 @@
+  * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
+  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.com>
+  *	This program is free software; you can redistribute it and/or modify
+- *  	it under the terms of the GNU General Public License as published by
++ *	it under the terms of the GNU General Public License as published by
+  *	the Free Software Foundation, version 2.
+  */
+ #include <linux/kernel.h>
+@@ -40,6 +40,7 @@
+ #include <linux/sched.h>
+ #include <linux/audit.h>
+ #include <linux/mutex.h>
++#include <linux/selinux.h>
+ #include <net/netlabel.h>
+ 
+ #include "flask.h"
+@@ -56,11 +57,13 @@
+ #include "netlabel.h"
+ #include "xfrm.h"
+ #include "ebitmap.h"
++#include "audit.h"
+ 
+ extern void selnl_notify_policyload(u32 seqno);
+ unsigned int policydb_loaded_version;
+ 
+ int selinux_policycap_netpeer;
++int selinux_policycap_openperm;
+ 
+ /*
+  * This is declared in avc.c
+@@ -79,7 +82,7 @@ static DEFINE_MUTEX(load_mutex);
+ 
+ static struct sidtab sidtab;
+ struct policydb policydb;
+-int ss_initialized = 0;
++int ss_initialized;
+ 
+ /*
+  * The largest sequence number that has been used when
+@@ -87,7 +90,7 @@ int ss_initialized = 0;
+  * The sequence number only changes when a policy change
+  * occurs.
+  */
+-static u32 latest_granting = 0;
++static u32 latest_granting;
+ 
+ /* Forward declaration. */
+ static int context_struct_to_string(struct context *context, char **scontext,
+@@ -160,10 +163,10 @@ static int constraint_expr_eval(struct context *scontext,
+ 								  val1 - 1);
+ 					continue;
+ 				case CEXPR_INCOMP:
+-					s[++sp] = ( !ebitmap_get_bit(&r1->dominates,
+-								     val2 - 1) &&
+-						    !ebitmap_get_bit(&r2->dominates,
+-								     val1 - 1) );
++					s[++sp] = (!ebitmap_get_bit(&r1->dominates,
++								    val2 - 1) &&
++						   !ebitmap_get_bit(&r2->dominates,
++								    val1 - 1));
+ 					continue;
+ 				default:
+ 					break;
+@@ -406,20 +409,46 @@ static int context_struct_compute_av(struct context *scontext,
+ 		}
+ 		if (!ra)
+ 			avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
+-			                                PROCESS__DYNTRANSITION);
++							PROCESS__DYNTRANSITION);
+ 	}
+ 
+ 	return 0;
+ 
+ inval_class:
+-	printk(KERN_ERR "%s:  unrecognized class %d\n", __FUNCTION__, tclass);
++	printk(KERN_ERR "SELinux: %s:  unrecognized class %d\n", __func__,
++		tclass);
+ 	return -EINVAL;
+ }
+ 
++/*
++ * Given a sid find if the type has the permissive flag set
++ */
++int security_permissive_sid(u32 sid)
++{
++	struct context *context;
++	u32 type;
++	int rc;
++
++	POLICY_RDLOCK;
++
++	context = sidtab_search(&sidtab, sid);
++	BUG_ON(!context);
++
++	type = context->type;
++	/*
++	 * we are intentionally using type here, not type-1, the 0th bit may
++	 * someday indicate that we are globally setting permissive in policy.
++	 */
++	rc = ebitmap_get_bit(&policydb.permissive_map, type);
++
++	POLICY_RDUNLOCK;
++	return rc;
++}
++
+ static int security_validtrans_handle_fail(struct context *ocontext,
+-                                           struct context *ncontext,
+-                                           struct context *tcontext,
+-                                           u16 tclass)
++					   struct context *ncontext,
++					   struct context *tcontext,
++					   u16 tclass)
+ {
+ 	char *o = NULL, *n = NULL, *t = NULL;
+ 	u32 olen, nlen, tlen;
+@@ -431,9 +460,9 @@ static int security_validtrans_handle_fail(struct context *ocontext,
+ 	if (context_struct_to_string(tcontext, &t, &tlen) < 0)
+ 		goto out;
+ 	audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+-	          "security_validate_transition:  denied for"
+-	          " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
+-	          o, n, t, policydb.p_class_val_to_name[tclass-1]);
++		  "security_validate_transition:  denied for"
++		  " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
++		  o, n, t, policydb.p_class_val_to_name[tclass-1]);
+ out:
+ 	kfree(o);
+ 	kfree(n);
+@@ -445,7 +474,7 @@ out:
+ }
+ 
+ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+-                                 u16 tclass)
++				 u16 tclass)
+ {
+ 	struct context *ocontext;
+ 	struct context *ncontext;
+@@ -471,8 +500,8 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+ 			tclass = SECCLASS_NETLINK_SOCKET;
+ 
+ 	if (!tclass || tclass > policydb.p_classes.nprim) {
+-		printk(KERN_ERR "security_validate_transition:  "
+-		       "unrecognized class %d\n", tclass);
++		printk(KERN_ERR "SELinux: %s:  unrecognized class %d\n",
++			__func__, tclass);
+ 		rc = -EINVAL;
+ 		goto out;
+ 	}
+@@ -480,24 +509,24 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+ 
+ 	ocontext = sidtab_search(&sidtab, oldsid);
+ 	if (!ocontext) {
+-		printk(KERN_ERR "security_validate_transition: "
+-		       " unrecognized SID %d\n", oldsid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++			__func__, oldsid);
+ 		rc = -EINVAL;
+ 		goto out;
+ 	}
+ 
+ 	ncontext = sidtab_search(&sidtab, newsid);
+ 	if (!ncontext) {
+-		printk(KERN_ERR "security_validate_transition: "
+-		       " unrecognized SID %d\n", newsid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++			__func__, newsid);
+ 		rc = -EINVAL;
+ 		goto out;
+ 	}
+ 
+ 	tcontext = sidtab_search(&sidtab, tasksid);
+ 	if (!tcontext) {
+-		printk(KERN_ERR "security_validate_transition: "
+-		       " unrecognized SID %d\n", tasksid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++			__func__, tasksid);
+ 		rc = -EINVAL;
+ 		goto out;
+ 	}
+@@ -505,9 +534,9 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+ 	constraint = tclass_datum->validatetrans;
+ 	while (constraint) {
+ 		if (!constraint_expr_eval(ocontext, ncontext, tcontext,
+-		                          constraint->expr)) {
++					  constraint->expr)) {
+ 			rc = security_validtrans_handle_fail(ocontext, ncontext,
+-			                                     tcontext, tclass);
++							     tcontext, tclass);
+ 			goto out;
+ 		}
+ 		constraint = constraint->next;
+@@ -553,15 +582,15 @@ int security_compute_av(u32 ssid,
+ 
+ 	scontext = sidtab_search(&sidtab, ssid);
+ 	if (!scontext) {
+-		printk(KERN_ERR "security_compute_av:  unrecognized SID %d\n",
+-		       ssid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++		       __func__, ssid);
+ 		rc = -EINVAL;
+ 		goto out;
+ 	}
+ 	tcontext = sidtab_search(&sidtab, tsid);
+ 	if (!tcontext) {
+-		printk(KERN_ERR "security_compute_av:  unrecognized SID %d\n",
+-		       tsid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++		       __func__, tsid);
+ 		rc = -EINVAL;
+ 		goto out;
+ 	}
+@@ -595,9 +624,8 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
+ 
+ 	/* Allocate space for the context; caller must free this space. */
+ 	scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
+-	if (!scontextp) {
++	if (!scontextp)
+ 		return -ENOMEM;
+-	}
+ 	*scontext = scontextp;
+ 
+ 	/*
+@@ -608,8 +636,8 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
+ 		policydb.p_role_val_to_name[context->role - 1],
+ 		policydb.p_type_val_to_name[context->type - 1]);
+ 	scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
+-	             1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
+-	             1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
++		     1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
++		     1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
+ 
+ 	mls_sid_to_context(context, &scontextp);
+ 
+@@ -650,7 +678,7 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
+ 			char *scontextp;
+ 
+ 			*scontext_len = strlen(initial_sid_to_string[sid]) + 1;
+-			scontextp = kmalloc(*scontext_len,GFP_ATOMIC);
++			scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
+ 			if (!scontextp) {
+ 				rc = -ENOMEM;
+ 				goto out;
+@@ -659,16 +687,16 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
+ 			*scontext = scontextp;
+ 			goto out;
+ 		}
+-		printk(KERN_ERR "security_sid_to_context:  called before initial "
+-		       "load_policy on unknown SID %d\n", sid);
++		printk(KERN_ERR "SELinux: %s:  called before initial "
++		       "load_policy on unknown SID %d\n", __func__, sid);
+ 		rc = -EINVAL;
+ 		goto out;
+ 	}
+ 	POLICY_RDLOCK;
+ 	context = sidtab_search(&sidtab, sid);
+ 	if (!context) {
+-		printk(KERN_ERR "security_sid_to_context:  unrecognized SID "
+-		       "%d\n", sid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++			__func__, sid);
+ 		rc = -EINVAL;
+ 		goto out_unlock;
+ 	}
+@@ -898,15 +926,15 @@ static int security_compute_sid(u32 ssid,
+ 
+ 	scontext = sidtab_search(&sidtab, ssid);
+ 	if (!scontext) {
+-		printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n",
+-		       ssid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++		       __func__, ssid);
+ 		rc = -EINVAL;
+ 		goto out_unlock;
+ 	}
+ 	tcontext = sidtab_search(&sidtab, tsid);
+ 	if (!tcontext) {
+-		printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n",
+-		       tsid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++		       __func__, tsid);
+ 		rc = -EINVAL;
+ 		goto out_unlock;
+ 	}
+@@ -946,7 +974,7 @@ static int security_compute_sid(u32 ssid,
+ 	avdatum = avtab_search(&policydb.te_avtab, &avkey);
+ 
+ 	/* If no permanent rule, also check for enabled conditional rules */
+-	if(!avdatum) {
++	if (!avdatum) {
+ 		node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
+ 		for (; node != NULL; node = avtab_search_node_next(node, specified)) {
+ 			if (node->key.specified & AVTAB_ENABLED) {
+@@ -1096,7 +1124,7 @@ static int validate_classes(struct policydb *p)
+ 			continue;
+ 		if (i > p->p_classes.nprim) {
+ 			printk(KERN_INFO
+-			       "security:  class %s not defined in policy\n",
++			       "SELinux:  class %s not defined in policy\n",
+ 			       def_class);
+ 			if (p->reject_unknown)
+ 				return -EINVAL;
+@@ -1107,7 +1135,7 @@ static int validate_classes(struct policydb *p)
+ 		pol_class = p->p_class_val_to_name[i-1];
+ 		if (strcmp(pol_class, def_class)) {
+ 			printk(KERN_ERR
+-			       "security:  class %d is incorrect, found %s but should be %s\n",
++			       "SELinux:  class %d is incorrect, found %s but should be %s\n",
+ 			       i, pol_class, def_class);
+ 			return -EINVAL;
+ 		}
+@@ -1125,7 +1153,7 @@ static int validate_classes(struct policydb *p)
+ 		nprim = 1 << (perms->nprim - 1);
+ 		if (perm_val > nprim) {
+ 			printk(KERN_INFO
+-			       "security:  permission %s in class %s not defined in policy\n",
++			       "SELinux:  permission %s in class %s not defined in policy\n",
+ 			       def_perm, pol_class);
+ 			if (p->reject_unknown)
+ 				return -EINVAL;
+@@ -1136,14 +1164,14 @@ static int validate_classes(struct policydb *p)
+ 		perdatum = hashtab_search(perms->table, def_perm);
+ 		if (perdatum == NULL) {
+ 			printk(KERN_ERR
+-			       "security:  permission %s in class %s not found in policy, bad policy\n",
++			       "SELinux:  permission %s in class %s not found in policy, bad policy\n",
+ 			       def_perm, pol_class);
+ 			return -EINVAL;
+ 		}
+ 		pol_val = 1 << (perdatum->value - 1);
+ 		if (pol_val != perm_val) {
+ 			printk(KERN_ERR
+-			       "security:  permission %s in class %s has incorrect value\n",
++			       "SELinux:  permission %s in class %s has incorrect value\n",
+ 			       def_perm, pol_class);
+ 			return -EINVAL;
+ 		}
+@@ -1157,7 +1185,7 @@ static int validate_classes(struct policydb *p)
+ 		BUG_ON(!cladatum);
+ 		if (!cladatum->comdatum) {
+ 			printk(KERN_ERR
+-			       "security:  class %s should have an inherits clause but does not\n",
++			       "SELinux:  class %s should have an inherits clause but does not\n",
+ 			       pol_class);
+ 			return -EINVAL;
+ 		}
+@@ -1172,7 +1200,7 @@ static int validate_classes(struct policydb *p)
+ 			def_perm = kdefs->av_inherit[i].common_pts[j];
+ 			if (j >= perms->nprim) {
+ 				printk(KERN_INFO
+-				       "security:  permission %s in class %s not defined in policy\n",
++				       "SELinux:  permission %s in class %s not defined in policy\n",
+ 				       def_perm, pol_class);
+ 				if (p->reject_unknown)
+ 					return -EINVAL;
+@@ -1183,13 +1211,13 @@ static int validate_classes(struct policydb *p)
+ 			perdatum = hashtab_search(perms->table, def_perm);
+ 			if (perdatum == NULL) {
+ 				printk(KERN_ERR
+-				       "security:  permission %s in class %s not found in policy, bad policy\n",
++				       "SELinux:  permission %s in class %s not found in policy, bad policy\n",
+ 				       def_perm, pol_class);
+ 				return -EINVAL;
+ 			}
+ 			if (perdatum->value != j + 1) {
+ 				printk(KERN_ERR
+-				       "security:  permission %s in class %s has incorrect value\n",
++				       "SELinux:  permission %s in class %s has incorrect value\n",
+ 				       def_perm, pol_class);
+ 				return -EINVAL;
+ 			}
+@@ -1219,7 +1247,7 @@ static inline int convert_context_handle_invalid_context(struct context *context
+ 		u32 len;
+ 
+ 		context_struct_to_string(context, &s, &len);
+-		printk(KERN_ERR "security:  context %s is invalid\n", s);
++		printk(KERN_ERR "SELinux:  context %s is invalid\n", s);
+ 		kfree(s);
+ 	}
+ 	return rc;
+@@ -1260,26 +1288,23 @@ static int convert_context(u32 key,
+ 
+ 	/* Convert the user. */
+ 	usrdatum = hashtab_search(args->newp->p_users.table,
+-	                          args->oldp->p_user_val_to_name[c->user - 1]);
+-	if (!usrdatum) {
++				  args->oldp->p_user_val_to_name[c->user - 1]);
++	if (!usrdatum)
+ 		goto bad;
+-	}
+ 	c->user = usrdatum->value;
+ 
+ 	/* Convert the role. */
+ 	role = hashtab_search(args->newp->p_roles.table,
+-	                      args->oldp->p_role_val_to_name[c->role - 1]);
+-	if (!role) {
++			      args->oldp->p_role_val_to_name[c->role - 1]);
++	if (!role)
+ 		goto bad;
+-	}
+ 	c->role = role->value;
+ 
+ 	/* Convert the type. */
+ 	typdatum = hashtab_search(args->newp->p_types.table,
+-	                          args->oldp->p_type_val_to_name[c->type - 1]);
+-	if (!typdatum) {
++				  args->oldp->p_type_val_to_name[c->type - 1]);
++	if (!typdatum)
+ 		goto bad;
+-	}
+ 	c->type = typdatum->value;
+ 
+ 	rc = mls_convert_context(args->oldp, args->newp, c);
+@@ -1299,7 +1324,7 @@ out:
+ bad:
+ 	context_struct_to_string(&oldc, &s, &len);
+ 	context_destroy(&oldc);
+-	printk(KERN_ERR "security:  invalidating context %s\n", s);
++	printk(KERN_ERR "SELinux:  invalidating context %s\n", s);
+ 	kfree(s);
+ 	goto out;
+ }
+@@ -1308,6 +1333,8 @@ static void security_load_policycaps(void)
+ {
+ 	selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
+ 						  POLICYDB_CAPABILITY_NETPEER);
++	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
++						  POLICYDB_CAPABILITY_OPENPERM);
+ }
+ 
+ extern void selinux_complete_init(void);
+@@ -1350,7 +1377,7 @@ int security_load_policy(void *data, size_t len)
+ 		/* Verify that the kernel defined classes are correct. */
+ 		if (validate_classes(&policydb)) {
+ 			printk(KERN_ERR
+-			       "security:  the definition of a class is incorrect\n");
++			       "SELinux:  the definition of a class is incorrect\n");
+ 			LOAD_UNLOCK;
+ 			sidtab_destroy(&sidtab);
+ 			policydb_destroy(&policydb);
+@@ -1384,14 +1411,14 @@ int security_load_policy(void *data, size_t len)
+ 	/* Verify that the kernel defined classes are correct. */
+ 	if (validate_classes(&newpolicydb)) {
+ 		printk(KERN_ERR
+-		       "security:  the definition of a class is incorrect\n");
++		       "SELinux:  the definition of a class is incorrect\n");
+ 		rc = -EINVAL;
+ 		goto err;
+ 	}
+ 
+ 	rc = security_preserve_bools(&newpolicydb);
+ 	if (rc) {
+-		printk(KERN_ERR "security:  unable to preserve booleans\n");
++		printk(KERN_ERR "SELinux:  unable to preserve booleans\n");
+ 		goto err;
+ 	}
+ 
+@@ -1443,17 +1470,11 @@ err:
+ 
+ /**
+  * security_port_sid - Obtain the SID for a port.
+- * @domain: communication domain aka address family
+- * @type: socket type
+  * @protocol: protocol number
+  * @port: port number
+  * @out_sid: security identifier
+  */
+-int security_port_sid(u16 domain,
+-		      u16 type,
+-		      u8 protocol,
+-		      u16 port,
+-		      u32 *out_sid)
++int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
+ {
+ 	struct ocontext *c;
+ 	int rc = 0;
+@@ -1532,8 +1553,8 @@ static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask)
+ {
+ 	int i, fail = 0;
+ 
+-	for(i = 0; i < 4; i++)
+-		if(addr[i] != (input[i] & mask[i])) {
++	for (i = 0; i < 4; i++)
++		if (addr[i] != (input[i] & mask[i])) {
+ 			fail = 1;
+ 			break;
+ 		}
+@@ -1632,7 +1653,7 @@ out:
+  */
+ 
+ int security_get_user_sids(u32 fromsid,
+-	                   char *username,
++			   char *username,
+ 			   u32 **sids,
+ 			   u32 *nel)
+ {
+@@ -1742,7 +1763,7 @@ out:
+  * transition SIDs or task SIDs.
+  */
+ int security_genfs_sid(const char *fstype,
+-	               char *path,
++		       char *path,
+ 		       u16 sclass,
+ 		       u32 *sid)
+ {
+@@ -1857,7 +1878,7 @@ int security_get_bools(int *len, char ***names, int **values)
+ 		goto out;
+ 	}
+ 
+-       *names = kcalloc(*len, sizeof(char*), GFP_ATOMIC);
++       *names = kcalloc(*len, sizeof(char *), GFP_ATOMIC);
+ 	if (!*names)
+ 		goto err;
+ 
+@@ -1869,7 +1890,7 @@ int security_get_bools(int *len, char ***names, int **values)
+ 		size_t name_len;
+ 		(*values)[i] = policydb.bool_val_to_struct[i]->state;
+ 		name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
+-               (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
++	       (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
+ 		if (!(*names)[i])
+ 			goto err;
+ 		strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
+@@ -1914,11 +1935,10 @@ int security_set_bools(int len, int *values)
+ 				audit_get_loginuid(current),
+ 				audit_get_sessionid(current));
+ 		}
+-		if (values[i]) {
++		if (values[i])
+ 			policydb.bool_val_to_struct[i]->state = 1;
+-		} else {
++		else
+ 			policydb.bool_val_to_struct[i]->state = 0;
+-		}
+ 	}
+ 
+ 	for (cur = policydb.cond_list; cur != NULL; cur = cur->next) {
+@@ -2012,16 +2032,16 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
+ 	POLICY_RDLOCK;
+ 	context1 = sidtab_search(&sidtab, sid);
+ 	if (!context1) {
+-		printk(KERN_ERR "security_sid_mls_copy:  unrecognized SID "
+-		       "%d\n", sid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++			__func__, sid);
+ 		rc = -EINVAL;
+ 		goto out_unlock;
+ 	}
+ 
+ 	context2 = sidtab_search(&sidtab, mls_sid);
+ 	if (!context2) {
+-		printk(KERN_ERR "security_sid_mls_copy:  unrecognized SID "
+-		       "%d\n", mls_sid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++			__func__, mls_sid);
+ 		rc = -EINVAL;
+ 		goto out_unlock;
+ 	}
+@@ -2112,17 +2132,15 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
+ 
+ 	nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
+ 	if (!nlbl_ctx) {
+-		printk(KERN_ERR
+-		       "security_sid_mls_cmp:  unrecognized SID %d\n",
+-		       nlbl_sid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++		       __func__, nlbl_sid);
+ 		rc = -EINVAL;
+ 		goto out_slowpath;
+ 	}
+ 	xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);
+ 	if (!xfrm_ctx) {
+-		printk(KERN_ERR
+-		       "security_sid_mls_cmp:  unrecognized SID %d\n",
+-		       xfrm_sid);
++		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
++		       __func__, xfrm_sid);
+ 		rc = -EINVAL;
+ 		goto out_slowpath;
+ 	}
+@@ -2202,8 +2220,8 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
+ 
+ 	match = hashtab_search(policydb.p_classes.table, class);
+ 	if (!match) {
+-		printk(KERN_ERR "%s:  unrecognized class %s\n",
+-			__FUNCTION__, class);
++		printk(KERN_ERR "SELinux: %s:  unrecognized class %s\n",
++			__func__, class);
+ 		rc = -EINVAL;
+ 		goto out;
+ 	}
+@@ -2273,21 +2291,23 @@ struct selinux_audit_rule {
+ 	struct context au_ctxt;
+ };
+ 
+-void selinux_audit_rule_free(struct selinux_audit_rule *rule)
++void selinux_audit_rule_free(void *vrule)
+ {
++	struct selinux_audit_rule *rule = vrule;
++
+ 	if (rule) {
+ 		context_destroy(&rule->au_ctxt);
+ 		kfree(rule);
+ 	}
+ }
+ 
+-int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+-                            struct selinux_audit_rule **rule)
++int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
+ {
+ 	struct selinux_audit_rule *tmprule;
+ 	struct role_datum *roledatum;
+ 	struct type_datum *typedatum;
+ 	struct user_datum *userdatum;
++	struct selinux_audit_rule **rule = (struct selinux_audit_rule **)vrule;
+ 	int rc = 0;
+ 
+ 	*rule = NULL;
+@@ -2374,17 +2394,42 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+ 	return rc;
+ }
+ 
+-int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+-                             struct selinux_audit_rule *rule,
++/* Check to see if the rule contains any selinux fields */
++int selinux_audit_rule_known(struct audit_krule *rule)
++{
++	int i;
++
++	for (i = 0; i < rule->field_count; i++) {
++		struct audit_field *f = &rule->fields[i];
++		switch (f->type) {
++		case AUDIT_SUBJ_USER:
++		case AUDIT_SUBJ_ROLE:
++		case AUDIT_SUBJ_TYPE:
++		case AUDIT_SUBJ_SEN:
++		case AUDIT_SUBJ_CLR:
++		case AUDIT_OBJ_USER:
++		case AUDIT_OBJ_ROLE:
++		case AUDIT_OBJ_TYPE:
++		case AUDIT_OBJ_LEV_LOW:
++		case AUDIT_OBJ_LEV_HIGH:
++			return 1;
++		}
++	}
++
++	return 0;
++}
++
++int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
+                              struct audit_context *actx)
+ {
+ 	struct context *ctxt;
+ 	struct mls_level *level;
++	struct selinux_audit_rule *rule = vrule;
+ 	int match = 0;
+ 
+ 	if (!rule) {
+ 		audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+-		          "selinux_audit_rule_match: missing rule\n");
++			  "selinux_audit_rule_match: missing rule\n");
+ 		return -ENOENT;
+ 	}
+ 
+@@ -2392,7 +2437,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+ 
+ 	if (rule->au_seqno < latest_granting) {
+ 		audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+-		          "selinux_audit_rule_match: stale rule\n");
++			  "selinux_audit_rule_match: stale rule\n");
+ 		match = -ESTALE;
+ 		goto out;
+ 	}
+@@ -2400,8 +2445,8 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+ 	ctxt = sidtab_search(&sidtab, sid);
+ 	if (!ctxt) {
+ 		audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+-		          "selinux_audit_rule_match: unrecognized SID %d\n",
+-		          sid);
++			  "selinux_audit_rule_match: unrecognized SID %d\n",
++			  sid);
+ 		match = -ENOENT;
+ 		goto out;
+ 	}
+@@ -2447,36 +2492,36 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+ 	case AUDIT_OBJ_LEV_LOW:
+ 	case AUDIT_OBJ_LEV_HIGH:
+ 		level = ((field == AUDIT_SUBJ_SEN ||
+-		          field == AUDIT_OBJ_LEV_LOW) ?
+-		         &ctxt->range.level[0] : &ctxt->range.level[1]);
++			  field == AUDIT_OBJ_LEV_LOW) ?
++			 &ctxt->range.level[0] : &ctxt->range.level[1]);
+ 		switch (op) {
+ 		case AUDIT_EQUAL:
+ 			match = mls_level_eq(&rule->au_ctxt.range.level[0],
+-			                     level);
++					     level);
+ 			break;
+ 		case AUDIT_NOT_EQUAL:
+ 			match = !mls_level_eq(&rule->au_ctxt.range.level[0],
+-			                      level);
++					      level);
+ 			break;
+ 		case AUDIT_LESS_THAN:
+ 			match = (mls_level_dom(&rule->au_ctxt.range.level[0],
+-			                       level) &&
+-			         !mls_level_eq(&rule->au_ctxt.range.level[0],
+-			                       level));
++					       level) &&
++				 !mls_level_eq(&rule->au_ctxt.range.level[0],
++					       level));
+ 			break;
+ 		case AUDIT_LESS_THAN_OR_EQUAL:
+ 			match = mls_level_dom(&rule->au_ctxt.range.level[0],
+-			                      level);
++					      level);
+ 			break;
+ 		case AUDIT_GREATER_THAN:
+ 			match = (mls_level_dom(level,
+-			                      &rule->au_ctxt.range.level[0]) &&
+-			         !mls_level_eq(level,
+-			                       &rule->au_ctxt.range.level[0]));
++					      &rule->au_ctxt.range.level[0]) &&
++				 !mls_level_eq(level,
++					       &rule->au_ctxt.range.level[0]));
+ 			break;
+ 		case AUDIT_GREATER_THAN_OR_EQUAL:
+ 			match = mls_level_dom(level,
+-			                      &rule->au_ctxt.range.level[0]);
++					      &rule->au_ctxt.range.level[0]);
+ 			break;
+ 		}
+ 	}
+@@ -2486,7 +2531,7 @@ out:
+ 	return match;
+ }
+ 
+-static int (*aurule_callback)(void) = NULL;
++static int (*aurule_callback)(void) = audit_update_lsm_rules;
+ 
+ static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
+                                u16 class, u32 perms, u32 *retained)
+@@ -2503,7 +2548,7 @@ static int __init aurule_init(void)
+ 	int err;
+ 
+ 	err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET,
+-	                       SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
++			       SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ 	if (err)
+ 		panic("avc_add_callback() failed, error %d\n", err);
+ 
+@@ -2511,11 +2556,6 @@ static int __init aurule_init(void)
+ }
+ __initcall(aurule_init);
+ 
+-void selinux_audit_set_callback(int (*callback)(void))
+-{
+-	aurule_callback = callback;
+-}
+-
+ #ifdef CONFIG_NETLABEL
+ /**
+  * security_netlbl_cache_add - Add an entry to the NetLabel cache
+@@ -2651,7 +2691,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
+ 		goto netlbl_sid_to_secattr_failure;
+ 	secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
+ 				  GFP_ATOMIC);
+-	secattr->flags |= NETLBL_SECATTR_DOMAIN;
++	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY;
+ 	mls_export_netlbl_lvl(ctx, secattr);
+ 	rc = mls_export_netlbl_cat(ctx, secattr);
+ 	if (rc != 0)
+diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
+index 53a54a7..4a516ff 100644
+--- a/security/selinux/ss/sidtab.c
++++ b/security/selinux/ss/sidtab.c
+@@ -156,12 +156,10 @@ void sidtab_map_remove_on_error(struct sidtab *s,
+ 		while (cur != NULL) {
+ 			ret = apply(cur->sid, &cur->context, args);
+ 			if (ret) {
+-				if (last) {
++				if (last)
+ 					last->next = cur->next;
+-				} else {
++				else
+ 					s->htable[i] = cur->next;
+-				}
+-
+ 				temp = cur;
+ 				cur = cur->next;
+ 				context_destroy(&temp->context);
+diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
+index 7e15820..8f17f54 100644
+--- a/security/selinux/xfrm.c
++++ b/security/selinux/xfrm.c
+@@ -45,7 +45,6 @@
+ #include <net/xfrm.h>
+ #include <net/checksum.h>
+ #include <net/udp.h>
+-#include <asm/semaphore.h>
+ #include <asm/atomic.h>
+ 
+ #include "avc.h"
+@@ -77,20 +76,18 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
+  * LSM hook implementation that authorizes that a flow can use
+  * a xfrm policy rule.
+  */
+-int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
++int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+ {
+ 	int rc;
+ 	u32 sel_sid;
+-	struct xfrm_sec_ctx *ctx;
+ 
+ 	/* Context sid is either set to label or ANY_ASSOC */
+-	if ((ctx = xp->security)) {
++	if (ctx) {
+ 		if (!selinux_authorizable_ctx(ctx))
+ 			return -EINVAL;
+ 
+ 		sel_sid = ctx->ctx_sid;
+-	}
+-	else
++	} else
+ 		/*
+ 		 * All flows should be treated as polmatch'ing an
+ 		 * otherwise applicable "non-labeled" policy. This
+@@ -103,7 +100,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
+ 			  NULL);
+ 
+ 	if (rc == -EACCES)
+-		rc = -ESRCH;
++		return -ESRCH;
+ 
+ 	return rc;
+ }
+@@ -183,8 +180,7 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
+ 
+ 					if (!ckall)
+ 						break;
+-				}
+-				else if (*sid != ctx->ctx_sid)
++				} else if (*sid != ctx->ctx_sid)
+ 					return -EINVAL;
+ 			}
+ 		}
+@@ -287,15 +283,14 @@ out2:
+  * LSM hook implementation that allocs and transfers uctx spec to
+  * xfrm_policy.
+  */
+-int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
+-		struct xfrm_user_sec_ctx *uctx)
++int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
++			      struct xfrm_user_sec_ctx *uctx)
+ {
+ 	int err;
+ 
+-	BUG_ON(!xp);
+ 	BUG_ON(!uctx);
+ 
+-	err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
++	err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
+ 	if (err == 0)
+ 		atomic_inc(&selinux_xfrm_refcount);
+ 
+@@ -307,43 +302,38 @@ int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
+  * LSM hook implementation that copies security data structure from old to
+  * new for policy cloning.
+  */
+-int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
++int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
++			      struct xfrm_sec_ctx **new_ctxp)
+ {
+-	struct xfrm_sec_ctx *old_ctx, *new_ctx;
+-
+-	old_ctx = old->security;
++	struct xfrm_sec_ctx *new_ctx;
+ 
+ 	if (old_ctx) {
+-		new_ctx = new->security = kmalloc(sizeof(*new_ctx) +
+-						  old_ctx->ctx_len,
+-						  GFP_KERNEL);
+-
++		new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
++				  GFP_KERNEL);
+ 		if (!new_ctx)
+ 			return -ENOMEM;
+ 
+ 		memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
+ 		memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
++		*new_ctxp = new_ctx;
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+- * LSM hook implementation that frees xfrm_policy security information.
++ * LSM hook implementation that frees xfrm_sec_ctx security information.
+  */
+-void selinux_xfrm_policy_free(struct xfrm_policy *xp)
++void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
+ {
+-	struct xfrm_sec_ctx *ctx = xp->security;
+-	if (ctx)
+-		kfree(ctx);
++	kfree(ctx);
+ }
+ 
+ /*
+  * LSM hook implementation that authorizes deletion of labeled policies.
+  */
+-int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
++int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
+ {
+ 	struct task_security_struct *tsec = current->security;
+-	struct xfrm_sec_ctx *ctx = xp->security;
+ 	int rc = 0;
+ 
+ 	if (ctx) {
+@@ -380,8 +370,7 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
+ void selinux_xfrm_state_free(struct xfrm_state *x)
+ {
+ 	struct xfrm_sec_ctx *ctx = x->security;
+-	if (ctx)
+-		kfree(ctx);
++	kfree(ctx);
+ }
+ 
+  /*
+diff --git a/security/smack/smack.h b/security/smack/smack.h
+index 62c1e98..4a4477f 100644
+--- a/security/smack/smack.h
++++ b/security/smack/smack.h
+@@ -15,6 +15,7 @@
+ 
+ #include <linux/capability.h>
+ #include <linux/spinlock.h>
++#include <linux/security.h>
+ #include <net/netlabel.h>
+ 
+ /*
+@@ -187,6 +188,7 @@ extern struct smack_known smack_known_star;
+ extern struct smack_known smack_known_unset;
+ 
+ extern struct smk_list_entry *smack_list;
++extern struct security_operations smack_ops;
+ 
+ /*
+  * Stricly for CIPSO level manipulation.
+diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
+index 732ba27..4215971 100644
+--- a/security/smack/smack_lsm.c
++++ b/security/smack/smack_lsm.c
+@@ -315,10 +315,10 @@ static int smack_sb_statfs(struct dentry *dentry)
+  * Returns 0 if current can write the floor of the filesystem
+  * being mounted on, an error code otherwise.
+  */
+-static int smack_sb_mount(char *dev_name, struct nameidata *nd,
++static int smack_sb_mount(char *dev_name, struct path *path,
+ 			  char *type, unsigned long flags, void *data)
+ {
+-	struct superblock_smack *sbp = nd->path.mnt->mnt_sb->s_security;
++	struct superblock_smack *sbp = path->mnt->mnt_sb->s_security;
+ 
+ 	return smk_curacc(sbp->smk_floor, MAY_WRITE);
+ }
+@@ -1275,7 +1275,7 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
+ 
+ 	switch (smack_net_nltype) {
+ 	case NETLBL_NLTYPE_CIPSOV4:
+-		nlsp->domain = kstrdup(smack, GFP_ATOMIC);
++		nlsp->domain = smack;
+ 		nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
+ 
+ 		rc = smack_to_cipso(smack, &cipso);
+@@ -2424,7 +2424,9 @@ static void smack_release_secctx(char *secdata, u32 seclen)
+ {
+ }
+ 
+-static struct security_operations smack_ops = {
++struct security_operations smack_ops = {
++	.name =				"smack",
++
+ 	.ptrace = 			smack_ptrace,
+ 	.capget = 			cap_capget,
+ 	.capset_check = 		cap_capset_check,
+@@ -2557,6 +2559,9 @@ static struct security_operations smack_ops = {
+  */
+ static __init int smack_init(void)
+ {
++	if (!security_module_enable(&smack_ops))
++		return 0;
++
+ 	printk(KERN_INFO "Smack:  Initializing.\n");
+ 
+ 	/*
+diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
+index cfae8af..6ba2837 100644
+--- a/security/smack/smackfs.c
++++ b/security/smack/smackfs.c
+@@ -965,12 +965,21 @@ static struct vfsmount *smackfs_mount;
+  *
+  * register the smackfs
+  *
+- * Returns 0 unless the registration fails.
++ * Do not register smackfs if Smack wasn't enabled
++ * on boot. We can not put this method normally under the
++ * smack_init() code path since the security subsystem get
++ * initialized before the vfs caches.
++ *
++ * Returns true if we were not chosen on boot or if
++ * we were chosen and filesystem registration succeeded.
+  */
+ static int __init init_smk_fs(void)
+ {
+ 	int err;
+ 
++	if (!security_module_enable(&smack_ops))
++		return 0;
++
+ 	err = register_filesystem(&smk_fs_type);
+ 	if (!err) {
+ 		smackfs_mount = kern_mount(&smk_fs_type);
+diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
+index 5d86e68..5b3274b 100644
+--- a/sound/arm/pxa2xx-ac97.c
++++ b/sound/arm/pxa2xx-ac97.c
+@@ -16,6 +16,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+ #include <linux/wait.h>
++#include <linux/clk.h>
+ #include <linux/delay.h>
+ 
+ #include <sound/core.h>
+@@ -27,6 +28,7 @@
+ #include <linux/mutex.h>
+ #include <asm/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/audio.h>
+ 
+ #include "pxa2xx-pcm.h"
+@@ -35,6 +37,10 @@
+ static DEFINE_MUTEX(car_mutex);
+ static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
+ static volatile long gsr_bits;
++static struct clk *ac97_clk;
++#ifdef CONFIG_PXA27x
++static struct clk *ac97conf_clk;
++#endif
+ 
+ /*
+  * Beware PXA27x bugs:
+@@ -66,7 +72,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg
+ 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
+ 	    !((GSR | gsr_bits) & GSR_SDONE)) {
+ 		printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
+-				__FUNCTION__, reg, GSR | gsr_bits);
++				__func__, reg, GSR | gsr_bits);
+ 		val = -1;
+ 		goto out;
+ 	}
+@@ -98,7 +104,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne
+ 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
+ 	    !((GSR | gsr_bits) & GSR_CDONE))
+ 		printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
+-				__FUNCTION__, reg, GSR | gsr_bits);
++				__func__, reg, GSR | gsr_bits);
+ 
+ 	mutex_unlock(&car_mutex);
+ }
+@@ -106,17 +112,35 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne
+ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
+ {
+ 	/* First, try cold reset */
++#ifdef CONFIG_PXA3xx
++	int timeout;
++
++	/* Hold CLKBPB for 100us */
++	GCR = 0;
++	GCR = GCR_CLKBPB;
++	udelay(100);
++	GCR = 0;
++#endif
++
+ 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
+ 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
+ 
+ 	gsr_bits = 0;
+ #ifdef CONFIG_PXA27x
+ 	/* PXA27x Developers Manual section 13.5.2.2.1 */
+-	pxa_set_cken(CKEN_AC97CONF, 1);
++	clk_enable(ac97conf_clk);
+ 	udelay(5);
+-	pxa_set_cken(CKEN_AC97CONF, 0);
++	clk_disable(ac97conf_clk);
+ 	GCR = GCR_COLD_RST;
+ 	udelay(50);
++#elif defined(CONFIG_PXA3xx)
++	timeout = 1000;
++	/* Can't use interrupts on PXA3xx */
++	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
++
++	GCR = GCR_WARM_RST | GCR_COLD_RST;
++	while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
++		mdelay(10);
+ #else
+ 	GCR = GCR_COLD_RST;
+ 	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
+@@ -125,7 +149,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
+ 
+ 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
+ 		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
+-				 __FUNCTION__, gsr_bits);
++				 __func__, gsr_bits);
+ 
+ 		/* let's try warm reset */
+ 		gsr_bits = 0;
+@@ -137,6 +161,12 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
+ 		GCR |= GCR_WARM_RST;
+ 		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+ 		udelay(500);
++#elif defined(CONFIG_PXA3xx)
++		timeout = 100;
++		/* Can't use interrupts */
++		GCR |= GCR_WARM_RST;
++		while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
++			mdelay(1);
+ #else
+ 		GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;
+ 		wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
+@@ -144,7 +174,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
+ 
+ 		if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
+ 			printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
+-					 __FUNCTION__, gsr_bits);
++					 __func__, gsr_bits);
+ 	}
+ 
+ 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+@@ -259,7 +289,7 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state)
+ 	if (platform_ops && platform_ops->suspend)
+ 		platform_ops->suspend(platform_ops->priv);
+ 	GCR |= GCR_ACLINK_OFF;
+-	pxa_set_cken(CKEN_AC97, 0);
++	clk_disable(ac97_clk);
+ 
+ 	return 0;
+ }
+@@ -268,7 +298,7 @@ static int pxa2xx_ac97_do_resume(struct snd_card *card)
+ {
+ 	pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
+ 
+-	pxa_set_cken(CKEN_AC97, 1);
++	clk_enable(ac97_clk);
+ 	if (platform_ops && platform_ops->resume)
+ 		platform_ops->resume(platform_ops->priv);
+ 	snd_ac97_resume(pxa2xx_ac97_ac97);
+@@ -335,8 +365,21 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
+ #ifdef CONFIG_PXA27x
+ 	/* Use GPIO 113 as AC97 Reset on Bulverde */
+ 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
++	ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
++	if (IS_ERR(ac97conf_clk)) {
++		ret = PTR_ERR(ac97conf_clk);
++		ac97conf_clk = NULL;
++		goto err;
++	}
+ #endif
+-	pxa_set_cken(CKEN_AC97, 1);
++
++	ac97_clk = clk_get(&dev->dev, "AC97CLK");
++	if (IS_ERR(ac97_clk)) {
++		ret = PTR_ERR(ac97_clk);
++		ac97_clk = NULL;
++		goto err;
++	}
++	clk_enable(ac97_clk);
+ 
+ 	ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
+ 	if (ret)
+@@ -361,11 +404,19 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
+  err:
+ 	if (card)
+ 		snd_card_free(card);
+-	if (CKEN & (1 << CKEN_AC97)) {
++	if (ac97_clk) {
+ 		GCR |= GCR_ACLINK_OFF;
+ 		free_irq(IRQ_AC97, NULL);
+-		pxa_set_cken(CKEN_AC97, 0);
++		clk_disable(ac97_clk);
++		clk_put(ac97_clk);
++		ac97_clk = NULL;
++	}
++#ifdef CONFIG_PXA27x
++	if (ac97conf_clk) {
++		clk_put(ac97conf_clk);
++		ac97conf_clk = NULL;
+ 	}
++#endif
+ 	return ret;
+ }
+ 
+@@ -378,7 +429,13 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
+ 		platform_set_drvdata(dev, NULL);
+ 		GCR |= GCR_ACLINK_OFF;
+ 		free_irq(IRQ_AC97, NULL);
+-		pxa_set_cken(CKEN_AC97, 0);
++		clk_disable(ac97_clk);
++		clk_put(ac97_clk);
++		ac97_clk = NULL;
++#ifdef CONFIG_PXA27x
++		clk_put(ac97conf_clk);
++		ac97conf_clk = NULL;
++#endif
+ 	}
+ 
+ 	return 0;
+@@ -391,6 +448,7 @@ static struct platform_driver pxa2xx_ac97_driver = {
+ 	.resume		= pxa2xx_ac97_resume,
+ 	.driver		= {
+ 		.name	= "pxa2xx-ac97",
++		.owner	= THIS_MODULE,
+ 	},
+ };
+ 
+@@ -410,3 +468,4 @@ module_exit(pxa2xx_ac97_exit);
+ MODULE_AUTHOR("Nicolas Pitre");
+ MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pxa2xx-ac97");
+diff --git a/sound/core/Kconfig b/sound/core/Kconfig
+index 829ca38..a8d71c6 100644
+--- a/sound/core/Kconfig
++++ b/sound/core/Kconfig
+@@ -181,3 +181,7 @@ config SND_PCM_XRUN_DEBUG
+ 	  It is usually not required, but if you have trouble with
+ 	  sound clicking when system is loaded, it may help to determine
+ 	  the process or driver which causes the scheduling gaps.
++
++config SND_VMASTER
++	bool
++	depends on SND
+diff --git a/sound/core/Makefile b/sound/core/Makefile
+index 267039a..da8e685 100644
+--- a/sound/core/Makefile
++++ b/sound/core/Makefile
+@@ -6,6 +6,7 @@
+ snd-y     := sound.o init.o memory.o info.o control.o misc.o device.o
+ snd-$(CONFIG_ISA_DMA_API) += isadma.o
+ snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o
++snd-$(CONFIG_SND_VMASTER) += vmaster.o
+ 
+ snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
+ 		pcm_memory.o
+diff --git a/sound/core/init.c b/sound/core/init.c
+index e3338d6..ac05734 100644
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -254,7 +254,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file)
+ 	if (likely(df))
+ 		return df->disconnected_f_op->release(inode, file);
+ 
+-	panic("%s(%p, %p) failed!", __FUNCTION__, inode, file);
++	panic("%s(%p, %p) failed!", __func__, inode, file);
+ }
+ 
+ static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
+@@ -311,6 +311,9 @@ int snd_card_disconnect(struct snd_card *card)
+ 	struct file *file;
+ 	int err;
+ 
++	if (!card)
++		return -EINVAL;
++
+ 	spin_lock(&card->files_lock);
+ 	if (card->shutdown) {
+ 		spin_unlock(&card->files_lock);
+@@ -322,6 +325,7 @@ int snd_card_disconnect(struct snd_card *card)
+ 	/* phase 1: disable fops (user space) operations for ALSA API */
+ 	mutex_lock(&snd_card_mutex);
+ 	snd_cards[card->number] = NULL;
++	snd_cards_lock &= ~(1 << card->number);
+ 	mutex_unlock(&snd_card_mutex);
+ 	
+ 	/* phase 2: replace file->f_op with special dummy operations */
+@@ -360,6 +364,15 @@ int snd_card_disconnect(struct snd_card *card)
+ 		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
+ 	return 0;	
+ }
+ 
+@@ -401,33 +414,14 @@ static int snd_card_do_free(struct snd_card *card)
+ 		snd_printk(KERN_WARNING "unable to free card info\n");
+ 		/* Not fatal error */
+ 	}
+-#ifndef CONFIG_SYSFS_DEPRECATED
+-	if (card->card_dev)
+-		device_unregister(card->card_dev);
+-#endif
+ 	kfree(card);
+ 	return 0;
+ }
+ 
+-static int snd_card_free_prepare(struct snd_card *card)
+-{
+-	if (card == NULL)
+-		return -EINVAL;
+-	(void) snd_card_disconnect(card);
+-	mutex_lock(&snd_card_mutex);
+-	snd_cards[card->number] = NULL;
+-	snd_cards_lock &= ~(1 << card->number);
+-	mutex_unlock(&snd_card_mutex);
+-#ifdef CONFIG_PM
+-	wake_up(&card->power_sleep);
+-#endif
+-	return 0;
+-}
+-
+ int snd_card_free_when_closed(struct snd_card *card)
+ {
+ 	int free_now = 0;
+-	int ret = snd_card_free_prepare(card);
++	int ret = snd_card_disconnect(card);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -447,7 +441,7 @@ EXPORT_SYMBOL(snd_card_free_when_closed);
+ 
+ int snd_card_free(struct snd_card *card)
+ {
+-	int ret = snd_card_free_prepare(card);
++	int ret = snd_card_disconnect(card);
+ 	if (ret)
+ 		return ret;
+ 
+diff --git a/sound/core/misc.c b/sound/core/misc.c
+index 102d1c3..38524f6 100644
+--- a/sound/core/misc.c
++++ b/sound/core/misc.c
+@@ -39,7 +39,7 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...)
+ {
+ 	va_list args;
+ 	
+-	if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
++	if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
+ 		char tmp[] = "<0>";
+ 		tmp[1] = format[1];
+ 		printk("%sALSA %s:%d: ", tmp, file, line);
+@@ -60,7 +60,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
+ {
+ 	va_list args;
+ 	
+-	if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
++	if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
+ 		char tmp[] = "<0>";
+ 		tmp[1] = format[1];
+ 		printk("%sALSA %s:%d: ", tmp, file, line);
+diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
+index 75daed2..581aa2c 100644
+--- a/sound/core/oss/mixer_oss.c
++++ b/sound/core/oss/mixer_oss.c
+@@ -1257,6 +1257,8 @@ static void snd_mixer_oss_build(struct snd_mixer_oss *mixer)
+ 		{ SOUND_MIXER_DIGITAL3,	"Digital",		2 },
+ 		{ SOUND_MIXER_PHONEIN,	"Phone",		0 },
+ 		{ SOUND_MIXER_PHONEOUT,	"Master Mono",		0 },
++		{ SOUND_MIXER_PHONEOUT,	"Speaker",		0 }, /*fallback*/
++		{ SOUND_MIXER_PHONEOUT,	"Mono",			0 }, /*fallback*/
+ 		{ SOUND_MIXER_PHONEOUT,	"Phone",		0 }, /* fallback */
+ 		{ SOUND_MIXER_VIDEO,	"Video",		0 },
+ 		{ SOUND_MIXER_RADIO,	"Radio",		0 },
+diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
+index ab570a0..558dadb 100644
+--- a/sound/core/seq/oss/seq_oss_synth.c
++++ b/sound/core/seq/oss/seq_oss_synth.c
+@@ -245,8 +245,13 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
+ 		info->nr_voices = rec->nr_voices;
+ 		if (info->nr_voices > 0) {
+ 			info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
+-			if (!info->ch)
+-				BUG();
++			if (!info->ch) {
++				snd_printk(KERN_ERR "Cannot malloc\n");
++				rec->oper.close(&info->arg);
++				module_put(rec->oper.owner);
++				snd_use_lock_free(&rec->use_lock);
++				continue;
++			}
+ 			reset_channels(info);
+ 		}
+ 		debug_printk(("synth %d assigned\n", i));
+diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
+new file mode 100644
+index 0000000..4cc57f9
+--- /dev/null
++++ b/sound/core/vmaster.c
+@@ -0,0 +1,371 @@
++/*
++ * Virtual master and slave controls
++ *
++ *  Copyright (c) 2008 by Takashi Iwai <tiwai at 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, version 2.
++ *
++ */
++
++#include <linux/slab.h>
++#include <sound/core.h>
++#include <sound/control.h>
++#include <sound/tlv.h>
++
++/*
++ * a subset of information returned via ctl info callback
++ */
++struct link_ctl_info {
++	int type;		/* value type */
++	int count;		/* item count */
++	int min_val, max_val;	/* min, max values */
++};
++
++/*
++ * link master - this contains a list of slave controls that are
++ * identical types, i.e. info returns the same value type and value
++ * ranges, but may have different number of counts.
++ *
++ * The master control is so far only mono volume/switch for simplicity.
++ * The same value will be applied to all slaves.
++ */
++struct link_master {
++	struct list_head slaves;
++	struct link_ctl_info info;
++	int val;		/* the master value */
++	unsigned int tlv[4];
++};
++
++/*
++ * link slave - this contains a slave control element
++ *
++ * It fakes the control callbacsk with additional attenuation by the
++ * master control.  A slave may have either one or two channels.
++ */
++
++struct link_slave {
++	struct list_head list;
++	struct link_master *master;
++	struct link_ctl_info info;
++	int vals[2];		/* current values */
++	struct snd_kcontrol slave; /* the copy of original control entry */
++};
++
++/* get the slave ctl info and save the initial values */
++static int slave_init(struct link_slave *slave)
++{
++	struct snd_ctl_elem_info *uinfo;
++	struct snd_ctl_elem_value *uctl;
++	int err, ch;
++
++	if (slave->info.count)
++		return 0; /* already initialized */
++
++	uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
++	if (!uinfo)
++		return -ENOMEM;
++	uinfo->id = slave->slave.id;
++	err = slave->slave.info(&slave->slave, uinfo);
++	if (err < 0) {
++		kfree(uinfo);
++		return err;
++	}
++	slave->info.type = uinfo->type;
++	slave->info.count = uinfo->count;
++	if (slave->info.count > 2  ||
++	    (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER &&
++	     slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) {
++		snd_printk(KERN_ERR "invalid slave element\n");
++		kfree(uinfo);
++		return -EINVAL;
++	}
++	slave->info.min_val = uinfo->value.integer.min;
++	slave->info.max_val = uinfo->value.integer.max;
++	kfree(uinfo);
++
++	uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
++	if (!uctl)
++		return -ENOMEM;
++	uctl->id = slave->slave.id;
++	err = slave->slave.get(&slave->slave, uctl);
++	for (ch = 0; ch < slave->info.count; ch++)
++		slave->vals[ch] = uctl->value.integer.value[ch];
++	kfree(uctl);
++	return 0;
++}
++
++/* initialize master volume */
++static int master_init(struct link_master *master)
++{
++	struct link_slave *slave;
++
++	if (master->info.count)
++		return 0; /* already initialized */
++
++	list_for_each_entry(slave, &master->slaves, list) {
++		int err = slave_init(slave);
++		if (err < 0)
++			return err;
++		master->info = slave->info;
++		master->info.count = 1; /* always mono */
++		/* set full volume as default (= no attenuation) */
++		master->val = master->info.max_val;
++		return 0;
++	}
++	return -ENOENT;
++}
++
++static int slave_get_val(struct link_slave *slave,
++			 struct snd_ctl_elem_value *ucontrol)
++{
++	int err, ch;
++
++	err = slave_init(slave);
++	if (err < 0)
++		return err;
++	for (ch = 0; ch < slave->info.count; ch++)
++		ucontrol->value.integer.value[ch] = slave->vals[ch];
++	return 0;
++}
++
++static int slave_put_val(struct link_slave *slave,
++			 struct snd_ctl_elem_value *ucontrol)
++{
++	int err, ch, vol;
++
++	err = master_init(slave->master);
++	if (err < 0)
++		return err;
++
++	switch (slave->info.type) {
++	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
++		for (ch = 0; ch < slave->info.count; ch++)
++			ucontrol->value.integer.value[ch] &=
++				!!slave->master->val;
++		break;
++	case SNDRV_CTL_ELEM_TYPE_INTEGER:
++		for (ch = 0; ch < slave->info.count; ch++) {
++			/* max master volume is supposed to be 0 dB */
++			vol = ucontrol->value.integer.value[ch];
++			vol += slave->master->val - slave->master->info.max_val;
++			if (vol < slave->info.min_val)
++				vol = slave->info.min_val;
++			else if (vol > slave->info.max_val)
++				vol = slave->info.max_val;
++			ucontrol->value.integer.value[ch] = vol;
++		}
++		break;
++	}
++	return slave->slave.put(&slave->slave, ucontrol);
++}
++
++/*
++ * ctl callbacks for slaves
++ */
++static int slave_info(struct snd_kcontrol *kcontrol,
++		      struct snd_ctl_elem_info *uinfo)
++{
++	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++	return slave->slave.info(&slave->slave, uinfo);
++}
++
++static int slave_get(struct snd_kcontrol *kcontrol,
++		     struct snd_ctl_elem_value *ucontrol)
++{
++	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++	return slave_get_val(slave, ucontrol);
++}
++
++static int slave_put(struct snd_kcontrol *kcontrol,
++		     struct snd_ctl_elem_value *ucontrol)
++{
++	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++	int err, ch, changed = 0;
++
++	err = slave_init(slave);
++	if (err < 0)
++		return err;
++	for (ch = 0; ch < slave->info.count; ch++) {
++		if (slave->vals[ch] != ucontrol->value.integer.value[ch]) {
++			changed = 1;
++			slave->vals[ch] = ucontrol->value.integer.value[ch];
++		}
++	}
++	if (!changed)
++		return 0;
++	return slave_put_val(slave, ucontrol);
++}
++
++static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
++			 int op_flag, unsigned int size,
++			 unsigned int __user *tlv)
++{
++	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++	/* FIXME: this assumes that the max volume is 0 dB */
++	return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv);
++}
++
++static void slave_free(struct snd_kcontrol *kcontrol)
++{
++	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++	if (slave->slave.private_free)
++		slave->slave.private_free(&slave->slave);
++	if (slave->master)
++		list_del(&slave->list);
++	kfree(slave);
++}
++
++/*
++ * Add a slave control to the group with the given master control
++ *
++ * All slaves must be the same type (returning the same information
++ * via info callback).  The fucntion doesn't check it, so it's your
++ * responsibility.
++ *
++ * Also, some additional limitations:
++ * - at most two channels
++ * - logarithmic volume control (dB level), no linear volume
++ * - master can only attenuate the volume, no gain
++ */
++int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
++{
++	struct link_master *master_link = snd_kcontrol_chip(master);
++	struct link_slave *srec;
++
++	srec = kzalloc(sizeof(*srec) +
++		       slave->count * sizeof(*slave->vd), GFP_KERNEL);
++	if (!srec)
++		return -ENOMEM;
++	srec->slave = *slave;
++	memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
++	srec->master = master_link;
++
++	/* override callbacks */
++	slave->info = slave_info;
++	slave->get = slave_get;
++	slave->put = slave_put;
++	if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)
++		slave->tlv.c = slave_tlv_cmd;
++	slave->private_data = srec;
++	slave->private_free = slave_free;
++
++	list_add_tail(&srec->list, &master_link->slaves);
++	return 0;
++}
++
++EXPORT_SYMBOL(snd_ctl_add_slave);
++
++/*
++ * ctl callbacks for master controls
++ */
++static int master_info(struct snd_kcontrol *kcontrol,
++		      struct snd_ctl_elem_info *uinfo)
++{
++	struct link_master *master = snd_kcontrol_chip(kcontrol);
++	int ret;
++
++	ret = master_init(master);
++	if (ret < 0)
++		return ret;
++	uinfo->type = master->info.type;
++	uinfo->count = master->info.count;
++	uinfo->value.integer.min = master->info.min_val;
++	uinfo->value.integer.max = master->info.max_val;
++	return 0;
++}
++
++static int master_get(struct snd_kcontrol *kcontrol,
++		      struct snd_ctl_elem_value *ucontrol)
++{
++	struct link_master *master = snd_kcontrol_chip(kcontrol);
++	int err = master_init(master);
++	if (err < 0)
++		return err;
++	ucontrol->value.integer.value[0] = master->val;
++	return 0;
++}
++
++static int master_put(struct snd_kcontrol *kcontrol,
++		      struct snd_ctl_elem_value *ucontrol)
++{
++	struct link_master *master = snd_kcontrol_chip(kcontrol);
++	struct link_slave *slave;
++	struct snd_ctl_elem_value *uval;
++	int err, old_val;
++
++	err = master_init(master);
++	if (err < 0)
++		return err;
++	old_val = master->val;
++	if (ucontrol->value.integer.value[0] == old_val)
++		return 0;
++
++	uval = kmalloc(sizeof(*uval), GFP_KERNEL);
++	if (!uval)
++		return -ENOMEM;
++	list_for_each_entry(slave, &master->slaves, list) {
++		master->val = old_val;
++		uval->id = slave->slave.id;
++		slave_get_val(slave, uval);
++		master->val = ucontrol->value.integer.value[0];
++		slave_put_val(slave, uval);
++	}
++	kfree(uval);
++	return 1;
++}
++
++static void master_free(struct snd_kcontrol *kcontrol)
++{
++	struct link_master *master = snd_kcontrol_chip(kcontrol);
++	struct link_slave *slave;
++
++	list_for_each_entry(slave, &master->slaves, list)
++		slave->master = NULL;
++	kfree(master);
++}
++
++
++/*
++ * Create a virtual master control with the given name
++ */
++struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
++						 const unsigned int *tlv)
++{
++	struct link_master *master;
++	struct snd_kcontrol *kctl;
++	struct snd_kcontrol_new knew;
++
++	memset(&knew, 0, sizeof(knew));
++	knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++	knew.name = name;
++	knew.info = master_info;
++
++	master = kzalloc(sizeof(*master), GFP_KERNEL);
++	if (!master)
++		return NULL;
++	INIT_LIST_HEAD(&master->slaves);
++
++	kctl = snd_ctl_new1(&knew, master);
++	if (!kctl) {
++		kfree(master);
++		return NULL;
++	}
++	/* override some callbacks */
++	kctl->info = master_info;
++	kctl->get = master_get;
++	kctl->put = master_put;
++	kctl->private_free = master_free;
++
++	/* additional (constant) TLV read */
++	if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
++		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
++		memcpy(master->tlv, tlv, sizeof(master->tlv));
++		kctl->tlv.p = master->tlv;
++	}
++
++	return kctl;
++}
++
++EXPORT_SYMBOL(snd_ctl_make_virtual_master);
+diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
+index 75d4fe0..fe85af1 100644
+--- a/sound/drivers/Kconfig
++++ b/sound/drivers/Kconfig
+@@ -4,6 +4,24 @@ menu "Generic devices"
+ 	depends on SND!=n
+ 
+ 
++config SND_PCSP
++	tristate "Internal PC speaker support"
++	depends on X86_PC && HIGH_RES_TIMERS
++	depends on INPUT
++	help
++	  If you don't have a sound card in your computer, you can include a
++	  driver for the PC speaker which allows it to act like a primitive
++	  sound card.
++	  This driver also replaces the pcspkr driver for beeps.
++
++	  You can compile this as a module which will be called snd-pcsp.
++
++	  You don't need this driver if you only want your pc-speaker to beep.
++	  You don't need this driver if you have a tablet piezo beeper
++	  in your PC instead of the real speaker.
++
++	  It should not hurt to say Y or M here in all other cases.
++
+ config SND_MPU401_UART
+         tristate
+         select SND_RAWMIDI
+diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile
+index 8e55300..d4a07f9 100644
+--- a/sound/drivers/Makefile
++++ b/sound/drivers/Makefile
+@@ -20,4 +20,4 @@ obj-$(CONFIG_SND_MTS64) += snd-mts64.o
+ obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o
+ obj-$(CONFIG_SND_ML403_AC97CR) += snd-ml403-ac97cr.o
+ 
+-obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/
++obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ pcsp/
+diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
+index a240eae..4e4c69e 100644
+--- a/sound/drivers/dummy.c
++++ b/sound/drivers/dummy.c
+@@ -181,10 +181,10 @@ struct snd_dummy_pcm {
+ 	struct snd_dummy *dummy;
+ 	spinlock_t lock;
+ 	struct timer_list timer;
+-	unsigned int pcm_size;
+-	unsigned int pcm_count;
++	unsigned int pcm_buffer_size;
++	unsigned int pcm_period_size;
+ 	unsigned int pcm_bps;		/* bytes per second */
+-	unsigned int pcm_jiffie;	/* bytes per one jiffie */
++	unsigned int pcm_hz;		/* HZ */
+ 	unsigned int pcm_irq_pos;	/* IRQ position */
+ 	unsigned int pcm_buf_pos;	/* position in buffer */
+ 	struct snd_pcm_substream *substream;
+@@ -230,19 +230,24 @@ static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
+ {
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
+ 	struct snd_dummy_pcm *dpcm = runtime->private_data;
+-	unsigned int bps;
++	int bps;
++
++	bps = snd_pcm_format_width(runtime->format) * runtime->rate *
++		runtime->channels / 8;
+ 
+-	bps = runtime->rate * runtime->channels;
+-	bps *= snd_pcm_format_width(runtime->format);
+-	bps /= 8;
+ 	if (bps <= 0)
+ 		return -EINVAL;
++
+ 	dpcm->pcm_bps = bps;
+-	dpcm->pcm_jiffie = bps / HZ;
+-	dpcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+-	dpcm->pcm_count = snd_pcm_lib_period_bytes(substream);
++	dpcm->pcm_hz = HZ;
++	dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
++	dpcm->pcm_period_size = snd_pcm_lib_period_bytes(substream);
+ 	dpcm->pcm_irq_pos = 0;
+ 	dpcm->pcm_buf_pos = 0;
++
++	snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
++			bytes_to_samples(runtime, runtime->dma_bytes));
++
+ 	return 0;
+ }
+ 
+@@ -254,11 +259,11 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data)
+ 	spin_lock_irqsave(&dpcm->lock, flags);
+ 	dpcm->timer.expires = 1 + jiffies;
+ 	add_timer(&dpcm->timer);
+-	dpcm->pcm_irq_pos += dpcm->pcm_jiffie;
+-	dpcm->pcm_buf_pos += dpcm->pcm_jiffie;
+-	dpcm->pcm_buf_pos %= dpcm->pcm_size;
+-	if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
+-		dpcm->pcm_irq_pos %= dpcm->pcm_count;
++	dpcm->pcm_irq_pos += dpcm->pcm_bps;
++	dpcm->pcm_buf_pos += dpcm->pcm_bps;
++	dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size * dpcm->pcm_hz;
++	if (dpcm->pcm_irq_pos >= dpcm->pcm_period_size * dpcm->pcm_hz) {
++		dpcm->pcm_irq_pos %= dpcm->pcm_period_size * dpcm->pcm_hz;
+ 		spin_unlock_irqrestore(&dpcm->lock, flags);
+ 		snd_pcm_period_elapsed(dpcm->substream);
+ 	} else
+@@ -270,7 +275,7 @@ static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *su
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
+ 	struct snd_dummy_pcm *dpcm = runtime->private_data;
+ 
+-	return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
++	return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz);
+ }
+ 
+ static struct snd_pcm_hardware snd_card_dummy_playback =
+diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
+index 05a871a..ecdbeb6 100644
+--- a/sound/drivers/ml403-ac97cr.c
++++ b/sound/drivers/ml403-ac97cr.c
+@@ -1191,8 +1191,6 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
+ 		return err;
+ 	}
+ 
+-	snd_card_set_dev(card, &pfdev->dev);
+-
+ 	*rml403_ac97cr = ml403_ac97cr;
+ 	return 0;
+ }
+@@ -1330,11 +1328,15 @@ static int snd_ml403_ac97cr_remove(struct platform_device *pfdev)
+ 	return 0;
+ }
+ 
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:" SND_ML403_AC97CR_DRIVER);
++
+ static struct platform_driver snd_ml403_ac97cr_driver = {
+ 	.probe = snd_ml403_ac97cr_probe,
+ 	.remove = snd_ml403_ac97cr_remove,
+ 	.driver = {
+ 		.name = SND_ML403_AC97CR_DRIVER,
++		.owner = THIS_MODULE,
+ 	},
+ };
+ 
+diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
+index 5993864..18cca24 100644
+--- a/sound/drivers/mpu401/mpu401_uart.c
++++ b/sound/drivers/mpu401/mpu401_uart.c
+@@ -49,12 +49,10 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu);
+ 
+  */
+ 
+-#define snd_mpu401_input_avail(mpu)	(!(mpu->read(mpu, MPU401C(mpu)) & 0x80))
+-#define snd_mpu401_output_ready(mpu)	(!(mpu->read(mpu, MPU401C(mpu)) & 0x40))
+-
+-#define MPU401_RESET		0xff
+-#define MPU401_ENTER_UART	0x3f
+-#define MPU401_ACK		0xfe
++#define snd_mpu401_input_avail(mpu) \
++	(!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY))
++#define snd_mpu401_output_ready(mpu) \
++	(!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL))
+ 
+ /* Build in lowlevel io */
+ static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data,
+@@ -425,16 +423,17 @@ static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
+ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
+ {
+ 	unsigned char byte;
+-	int max = 256, timeout;
++	int max = 256;
+ 
+ 	do {
+ 		if (snd_rawmidi_transmit_peek(mpu->substream_output,
+ 					      &byte, 1) == 1) {
+-			for (timeout = 100; timeout > 0; timeout--) {
+-				if (snd_mpu401_output_ready(mpu))
+-					break;
+-			}
+-			if (timeout == 0)
++			/*
++			 * Try twice because there is hardware that insists on
++			 * setting the output busy bit after each write.
++			 */
++			if (!snd_mpu401_output_ready(mpu) &&
++			    !snd_mpu401_output_ready(mpu))
+ 				break;	/* Tx FIFO full - try again later */
+ 			mpu->write(mpu, byte, MPU401D(mpu));
+ 			snd_rawmidi_transmit_ack(mpu->substream_output, 1);
+diff --git a/sound/drivers/pcsp/Makefile b/sound/drivers/pcsp/Makefile
+new file mode 100644
+index 0000000..b19555b
+--- /dev/null
++++ b/sound/drivers/pcsp/Makefile
+@@ -0,0 +1,2 @@
++snd-pcsp-objs := pcsp.o pcsp_lib.o pcsp_mixer.o pcsp_input.o
++obj-$(CONFIG_SND_PCSP) += snd-pcsp.o
+diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
+new file mode 100644
+index 0000000..5920351
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp.c
+@@ -0,0 +1,235 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Copyright (C) 1997-2001  David Woodhouse
++ * Copyright (C) 2001-2008  Stas Sergeev
++ */
++
++#include <linux/init.h>
++#include <linux/moduleparam.h>
++#include <linux/platform_device.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <asm/bitops.h>
++#include "pcsp_input.h"
++#include "pcsp.h"
++
++MODULE_AUTHOR("Stas Sergeev <stsp at users.sourceforge.net>");
++MODULE_DESCRIPTION("PC-Speaker driver");
++MODULE_LICENSE("GPL");
++MODULE_SUPPORTED_DEVICE("{{PC-Speaker, pcsp}}");
++MODULE_ALIAS("platform:pcspkr");
++
++static int index = SNDRV_DEFAULT_IDX1;	/* Index 0-MAX */
++static char *id = SNDRV_DEFAULT_STR1;	/* ID for this card */
++static int enable = SNDRV_DEFAULT_ENABLE1;	/* Enable this card */
++
++module_param(index, int, 0444);
++MODULE_PARM_DESC(index, "Index value for pcsp soundcard.");
++module_param(id, charp, 0444);
++MODULE_PARM_DESC(id, "ID string for pcsp soundcard.");
++module_param(enable, bool, 0444);
++MODULE_PARM_DESC(enable, "Enable PC-Speaker sound.");
++
++struct snd_pcsp pcsp_chip;
++
++static int __devinit snd_pcsp_create(struct snd_card *card)
++{
++	static struct snd_device_ops ops = { };
++	struct timespec tp;
++	int err;
++	int div, min_div, order;
++
++	hrtimer_get_res(CLOCK_MONOTONIC, &tp);
++	if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) {
++		printk(KERN_ERR "PCSP: Timer resolution is not sufficient "
++		       "(%linS)\n", tp.tv_nsec);
++		printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI "
++		       "enabled.\n");
++		return -EIO;
++	}
++
++	if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS)
++		min_div = MIN_DIV;
++	else
++		min_div = MAX_DIV;
++#if PCSP_DEBUG
++	printk("PCSP: lpj=%li, min_div=%i, res=%li\n",
++	       loops_per_jiffy, min_div, tp.tv_nsec);
++#endif
++
++	div = MAX_DIV / min_div;
++	order = fls(div) - 1;
++
++	pcsp_chip.max_treble = min(order, PCSP_MAX_TREBLE);
++	pcsp_chip.treble = min(pcsp_chip.max_treble, PCSP_DEFAULT_TREBLE);
++	pcsp_chip.playback_ptr = 0;
++	pcsp_chip.period_ptr = 0;
++	atomic_set(&pcsp_chip.timer_active, 0);
++	pcsp_chip.enable = 1;
++	pcsp_chip.pcspkr = 1;
++
++	spin_lock_init(&pcsp_chip.substream_lock);
++
++	pcsp_chip.card = card;
++	pcsp_chip.port = 0x61;
++	pcsp_chip.irq = -1;
++	pcsp_chip.dma = -1;
++
++	/* Register device */
++	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, &pcsp_chip, &ops);
++	if (err < 0)
++		return err;
++
++	return 0;
++}
++
++static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
++{
++	struct snd_card *card;
++	int err;
++
++	if (devnum != 0)
++		return -EINVAL;
++
++	hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++	pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE;
++	pcsp_chip.timer.function = pcsp_do_timer;
++
++	card = snd_card_new(index, id, THIS_MODULE, 0);
++	if (!card)
++		return -ENOMEM;
++
++	err = snd_pcsp_create(card);
++	if (err < 0) {
++		snd_card_free(card);
++		return err;
++	}
++	err = snd_pcsp_new_pcm(&pcsp_chip);
++	if (err < 0) {
++		snd_card_free(card);
++		return err;
++	}
++	err = snd_pcsp_new_mixer(&pcsp_chip);
++	if (err < 0) {
++		snd_card_free(card);
++		return err;
++	}
++
++	snd_card_set_dev(pcsp_chip.card, dev);
++
++	strcpy(card->driver, "PC-Speaker");
++	strcpy(card->shortname, "pcsp");
++	sprintf(card->longname, "Internal PC-Speaker at port 0x%x",
++		pcsp_chip.port);
++
++	err = snd_card_register(card);
++	if (err < 0) {
++		snd_card_free(card);
++		return err;
++	}
++
++	return 0;
++}
++
++static int __devinit alsa_card_pcsp_init(struct device *dev)
++{
++	int err;
++
++	err = snd_card_pcsp_probe(0, dev);
++	if (err) {
++		printk(KERN_ERR "PC-Speaker initialization failed.\n");
++		return err;
++	}
++
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	/* Well, CONFIG_DEBUG_PAGEALLOC makes the sound horrible. Lets alert */
++	printk(KERN_WARNING "PCSP: CONFIG_DEBUG_PAGEALLOC is enabled, "
++	       "which may make the sound noisy.\n");
++#endif
++
++	return 0;
++}
++
++static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip)
++{
++	snd_card_free(chip->card);
++}
++
++static int __devinit pcsp_probe(struct platform_device *dev)
++{
++	int err;
++
++	err = pcspkr_input_init(&pcsp_chip.input_dev, &dev->dev);
++	if (err < 0)
++		return err;
++
++	err = alsa_card_pcsp_init(&dev->dev);
++	if (err < 0) {
++		pcspkr_input_remove(pcsp_chip.input_dev);
++		return err;
++	}
++
++	platform_set_drvdata(dev, &pcsp_chip);
++	return 0;
++}
++
++static int __devexit pcsp_remove(struct platform_device *dev)
++{
++	struct snd_pcsp *chip = platform_get_drvdata(dev);
++	alsa_card_pcsp_exit(chip);
++	pcspkr_input_remove(chip->input_dev);
++	platform_set_drvdata(dev, NULL);
++	return 0;
++}
++
++static void pcsp_stop_beep(struct snd_pcsp *chip)
++{
++	spin_lock_irq(&chip->substream_lock);
++	if (!chip->playback_substream)
++		pcspkr_stop_sound();
++	spin_unlock_irq(&chip->substream_lock);
++}
++
++static int pcsp_suspend(struct platform_device *dev, pm_message_t state)
++{
++	struct snd_pcsp *chip = platform_get_drvdata(dev);
++	pcsp_stop_beep(chip);
++	snd_pcm_suspend_all(chip->pcm);
++	return 0;
++}
++
++static void pcsp_shutdown(struct platform_device *dev)
++{
++	struct snd_pcsp *chip = platform_get_drvdata(dev);
++	pcsp_stop_beep(chip);
++}
++
++static struct platform_driver pcsp_platform_driver = {
++	.driver		= {
++		.name	= "pcspkr",
++		.owner	= THIS_MODULE,
++	},
++	.probe		= pcsp_probe,
++	.remove		= __devexit_p(pcsp_remove),
++	.suspend	= pcsp_suspend,
++	.shutdown	= pcsp_shutdown,
++};
++
++static int __init pcsp_init(void)
++{
++	if (!enable)
++		return -ENODEV;
++	return platform_driver_register(&pcsp_platform_driver);
++}
++
++static void __exit pcsp_exit(void)
++{
++	platform_driver_unregister(&pcsp_platform_driver);
++}
++
++module_init(pcsp_init);
++module_exit(pcsp_exit);
+diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
+new file mode 100644
+index 0000000..f07cc1e
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp.h
+@@ -0,0 +1,82 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Copyright (C) 1993-1997  Michael Beck
++ * Copyright (C) 1997-2001  David Woodhouse
++ * Copyright (C) 2001-2008  Stas Sergeev
++ */
++
++#ifndef __PCSP_H__
++#define __PCSP_H__
++
++#include <linux/hrtimer.h>
++#if defined(CONFIG_MIPS) || defined(CONFIG_X86)
++/* Use the global PIT lock ! */
++#include <asm/i8253.h>
++#else
++#include <asm/8253pit.h>
++static DEFINE_SPINLOCK(i8253_lock);
++#endif
++
++#define PCSP_SOUND_VERSION 0x400	/* read 4.00 */
++#define PCSP_DEBUG 0
++
++/* default timer freq for PC-Speaker: 18643 Hz */
++#define DIV_18KHZ 64
++#define MAX_DIV DIV_18KHZ
++#define CUR_DIV() (MAX_DIV >> chip->treble)
++#define PCSP_MAX_TREBLE 1
++
++/* unfortunately, with hrtimers 37KHz does not work very well :( */
++#define PCSP_DEFAULT_TREBLE 0
++#define MIN_DIV (MAX_DIV >> PCSP_MAX_TREBLE)
++
++/* wild guess */
++#define PCSP_MIN_LPJ 1000000
++#define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1)
++#define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV)
++#define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble))
++#define PCSP_RATE() (PIT_TICK_RATE / CUR_DIV())
++#define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE
++#define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE
++#define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1)
++#define PCSP_MIN_PERIOD_NS (1000000000ULL * PCSP_MAX_RATE__1)
++#define PCSP_CALC_NS(div) ({ \
++	u64 __val = 1000000000ULL * (div); \
++	do_div(__val, PIT_TICK_RATE); \
++	__val; \
++})
++#define PCSP_PERIOD_NS() PCSP_CALC_NS(CUR_DIV())
++
++#define PCSP_MAX_PERIOD_SIZE	(64*1024)
++#define PCSP_MAX_PERIODS	512
++#define PCSP_BUFFER_SIZE	(128*1024)
++
++struct snd_pcsp {
++	struct snd_card *card;
++	struct snd_pcm *pcm;
++	struct input_dev *input_dev;
++	struct hrtimer timer;
++	unsigned short port, irq, dma;
++	spinlock_t substream_lock;
++	struct snd_pcm_substream *playback_substream;
++	size_t playback_ptr;
++	size_t period_ptr;
++	atomic_t timer_active;
++	int thalf;
++	u64 ns_rem;
++	unsigned char val61;
++	int enable;
++	int max_treble;
++	int treble;
++	int pcspkr;
++};
++
++extern struct snd_pcsp pcsp_chip;
++
++extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
++
++extern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
++extern int snd_pcsp_new_mixer(struct snd_pcsp *chip);
++
++#endif
+diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
+new file mode 100644
+index 0000000..cd9b83e
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp_input.c
+@@ -0,0 +1,116 @@
++/*
++ *  PC Speaker beeper driver for Linux
++ *
++ *  Copyright (c) 2002 Vojtech Pavlik
++ *  Copyright (c) 1992 Orest Zborowski
++ *
++ */
++
++/*
++ * This program is free software; you can redistribute it 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/input.h>
++#include <asm/io.h>
++#include "pcsp.h"
++
++static void pcspkr_do_sound(unsigned int count)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&i8253_lock, flags);
++
++	if (count) {
++		/* enable counter 2 */
++		outb_p(inb_p(0x61) | 3, 0x61);
++		/* set command for counter 2, 2 byte write */
++		outb_p(0xB6, 0x43);
++		/* select desired HZ */
++		outb_p(count & 0xff, 0x42);
++		outb((count >> 8) & 0xff, 0x42);
++	} else {
++		/* disable counter 2 */
++		outb(inb_p(0x61) & 0xFC, 0x61);
++	}
++
++	spin_unlock_irqrestore(&i8253_lock, flags);
++}
++
++void pcspkr_stop_sound(void)
++{
++	pcspkr_do_sound(0);
++}
++
++static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
++			      unsigned int code, int value)
++{
++	unsigned int count = 0;
++
++	if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)
++		return 0;
++
++	switch (type) {
++	case EV_SND:
++		switch (code) {
++		case SND_BELL:
++			if (value)
++				value = 1000;
++		case SND_TONE:
++			break;
++		default:
++			return -1;
++		}
++		break;
++
++	default:
++		return -1;
++	}
++
++	if (value > 20 && value < 32767)
++		count = PIT_TICK_RATE / value;
++
++	pcspkr_do_sound(count);
++
++	return 0;
++}
++
++int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev)
++{
++	int err;
++
++	struct input_dev *input_dev = input_allocate_device();
++	if (!input_dev)
++		return -ENOMEM;
++
++	input_dev->name = "PC Speaker";
++	input_dev->phys = "isa0061/input0";
++	input_dev->id.bustype = BUS_ISA;
++	input_dev->id.vendor = 0x001f;
++	input_dev->id.product = 0x0001;
++	input_dev->id.version = 0x0100;
++	input_dev->dev.parent = dev;
++
++	input_dev->evbit[0] = BIT(EV_SND);
++	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
++	input_dev->event = pcspkr_input_event;
++
++	err = input_register_device(input_dev);
++	if (err) {
++		input_free_device(input_dev);
++		return err;
++	}
++
++	*rdev = input_dev;
++	return 0;
++}
++
++int pcspkr_input_remove(struct input_dev *dev)
++{
++	pcspkr_stop_sound();
++	input_unregister_device(dev);	/* this also does kfree() */
++
++	return 0;
++}
+diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h
+new file mode 100644
+index 0000000..e66738c
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp_input.h
+@@ -0,0 +1,14 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Copyright (C) 2001-2008  Stas Sergeev
++ */
++
++#ifndef __PCSP_INPUT_H__
++#define __PCSP_INPUT_H__
++
++int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev);
++int pcspkr_input_remove(struct input_dev *dev);
++void pcspkr_stop_sound(void);
++
++#endif
+diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
+new file mode 100644
+index 0000000..ac6238e
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp_lib.c
+@@ -0,0 +1,338 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Copyright (C) 1993-1997  Michael Beck
++ * Copyright (C) 1997-2001  David Woodhouse
++ * Copyright (C) 2001-2008  Stas Sergeev
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <sound/pcm.h>
++#include <linux/interrupt.h>
++#include <asm/io.h>
++#include "pcsp.h"
++
++static int nforce_wa;
++module_param(nforce_wa, bool, 0444);
++MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
++		"(expect bad sound)");
++
++static void pcsp_start_timer(unsigned long dummy)
++{
++	hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL);
++}
++
++/*
++ * We need the hrtimer_start as a tasklet to avoid
++ * the nasty locking problem. :(
++ * The problem:
++ * - The timer handler is called with the cpu_base->lock
++ *   already held by hrtimer code.
++ * - snd_pcm_period_elapsed() takes the
++ *   substream->self_group.lock.
++ * So far so good.
++ * But the snd_pcsp_trigger() is called with the
++ * substream->self_group.lock held, and it calls
++ * hrtimer_start(), which takes the cpu_base->lock.
++ * You see the problem. We have the code pathes
++ * which take two locks in a reverse order. This
++ * can deadlock and the lock validator complains.
++ * The only solution I could find was to move the
++ * hrtimer_start() into a tasklet. -stsp
++ */
++static DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0);
++
++enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
++{
++	unsigned long flags;
++	unsigned char timer_cnt, val;
++	int periods_elapsed;
++	u64 ns;
++	size_t period_bytes, buffer_bytes;
++	struct snd_pcm_substream *substream;
++	struct snd_pcm_runtime *runtime;
++	struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
++
++	if (chip->thalf) {
++		outb(chip->val61, 0x61);
++		chip->thalf = 0;
++		if (!atomic_read(&chip->timer_active))
++			return HRTIMER_NORESTART;
++		hrtimer_forward(&chip->timer, chip->timer.expires,
++				ktime_set(0, chip->ns_rem));
++		return HRTIMER_RESTART;
++	}
++
++	/* hrtimer calls us from both hardirq and softirq contexts,
++	 * so irqsave :( */
++	spin_lock_irqsave(&chip->substream_lock, flags);
++	/* Takashi Iwai says regarding this extra lock:
++
++	If the irq handler handles some data on the DMA buffer, it should
++	do snd_pcm_stream_lock().
++	That protects basically against all races among PCM callbacks, yes.
++	However, there are two remaining issues:
++	1. The substream pointer you try to lock isn't protected _before_
++	  this lock yet.
++	2. snd_pcm_period_elapsed() itself acquires the lock.
++	The requirement of another lock is because of 1.  When you get
++	chip->playback_substream, it's not protected.
++	Keeping this lock while snd_pcm_period_elapsed() assures the substream
++	is still protected (at least, not released).  And the other status is
++	handled properly inside snd_pcm_stream_lock() in
++	snd_pcm_period_elapsed().
++
++	*/
++	if (!chip->playback_substream)
++		goto exit_nr_unlock1;
++	substream = chip->playback_substream;
++	snd_pcm_stream_lock(substream);
++	if (!atomic_read(&chip->timer_active))
++		goto exit_nr_unlock2;
++
++	runtime = substream->runtime;
++	/* assume it is u8 mono */
++	val = runtime->dma_area[chip->playback_ptr];
++	timer_cnt = val * CUR_DIV() / 256;
++
++	if (timer_cnt && chip->enable) {
++		spin_lock(&i8253_lock);
++		if (!nforce_wa) {
++			outb_p(chip->val61, 0x61);
++			outb_p(timer_cnt, 0x42);
++			outb(chip->val61 ^ 1, 0x61);
++		} else {
++			outb(chip->val61 ^ 2, 0x61);
++			chip->thalf = 1;
++		}
++		spin_unlock(&i8253_lock);
++	}
++
++	period_bytes = snd_pcm_lib_period_bytes(substream);
++	buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
++	chip->playback_ptr += PCSP_INDEX_INC();
++	periods_elapsed = chip->playback_ptr - chip->period_ptr;
++	if (periods_elapsed < 0) {
++		printk(KERN_WARNING "PCSP: playback_ptr inconsistent "
++			"(%zi %zi %zi)\n",
++			chip->playback_ptr, period_bytes, buffer_bytes);
++		periods_elapsed += buffer_bytes;
++	}
++	periods_elapsed /= period_bytes;
++	/* wrap the pointer _before_ calling snd_pcm_period_elapsed(),
++	 * or ALSA will BUG on us. */
++	chip->playback_ptr %= buffer_bytes;
++
++	snd_pcm_stream_unlock(substream);
++
++	if (periods_elapsed) {
++		snd_pcm_period_elapsed(substream);
++		chip->period_ptr += periods_elapsed * period_bytes;
++		chip->period_ptr %= buffer_bytes;
++	}
++
++	spin_unlock_irqrestore(&chip->substream_lock, flags);
++
++	if (!atomic_read(&chip->timer_active))
++		return HRTIMER_NORESTART;
++
++	chip->ns_rem = PCSP_PERIOD_NS();
++	ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem);
++	chip->ns_rem -= ns;
++	hrtimer_forward(&chip->timer, chip->timer.expires, ktime_set(0, ns));
++	return HRTIMER_RESTART;
++
++exit_nr_unlock2:
++	snd_pcm_stream_unlock(substream);
++exit_nr_unlock1:
++	spin_unlock_irqrestore(&chip->substream_lock, flags);
++	return HRTIMER_NORESTART;
++}
++
++static void pcsp_start_playing(struct snd_pcsp *chip)
++{
++#if PCSP_DEBUG
++	printk(KERN_INFO "PCSP: start_playing called\n");
++#endif
++	if (atomic_read(&chip->timer_active)) {
++		printk(KERN_ERR "PCSP: Timer already active\n");
++		return;
++	}
++
++	spin_lock(&i8253_lock);
++	chip->val61 = inb(0x61) | 0x03;
++	outb_p(0x92, 0x43);	/* binary, mode 1, LSB only, ch 2 */
++	spin_unlock(&i8253_lock);
++	atomic_set(&chip->timer_active, 1);
++	chip->thalf = 0;
++
++	tasklet_schedule(&pcsp_start_timer_tasklet);
++}
++
++static void pcsp_stop_playing(struct snd_pcsp *chip)
++{
++#if PCSP_DEBUG
++	printk(KERN_INFO "PCSP: stop_playing called\n");
++#endif
++	if (!atomic_read(&chip->timer_active))
++		return;
++
++	atomic_set(&chip->timer_active, 0);
++	spin_lock(&i8253_lock);
++	/* restore the timer */
++	outb_p(0xb6, 0x43);	/* binary, mode 3, LSB/MSB, ch 2 */
++	outb(chip->val61 & 0xFC, 0x61);
++	spin_unlock(&i8253_lock);
++}
++
++static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)
++{
++	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++#if PCSP_DEBUG
++	printk(KERN_INFO "PCSP: close called\n");
++#endif
++	if (atomic_read(&chip->timer_active)) {
++		printk(KERN_ERR "PCSP: timer still active\n");
++		pcsp_stop_playing(chip);
++	}
++	spin_lock_irq(&chip->substream_lock);
++	chip->playback_substream = NULL;
++	spin_unlock_irq(&chip->substream_lock);
++	return 0;
++}
++
++static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
++				       struct snd_pcm_hw_params *hw_params)
++{
++	int err;
++	err = snd_pcm_lib_malloc_pages(substream,
++				      params_buffer_bytes(hw_params));
++	if (err < 0)
++		return err;
++	return 0;
++}
++
++static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
++{
++#if PCSP_DEBUG
++	printk(KERN_INFO "PCSP: hw_free called\n");
++#endif
++	return snd_pcm_lib_free_pages(substream);
++}
++
++static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++#if PCSP_DEBUG
++	printk(KERN_INFO "PCSP: prepare called, "
++			"size=%zi psize=%zi f=%zi f1=%i\n",
++			snd_pcm_lib_buffer_bytes(substream),
++			snd_pcm_lib_period_bytes(substream),
++			snd_pcm_lib_buffer_bytes(substream) /
++			snd_pcm_lib_period_bytes(substream),
++			substream->runtime->periods);
++#endif
++	chip->playback_ptr = 0;
++	chip->period_ptr = 0;
++	return 0;
++}
++
++static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++#if PCSP_DEBUG
++	printk(KERN_INFO "PCSP: trigger called\n");
++#endif
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++	case SNDRV_PCM_TRIGGER_RESUME:
++		pcsp_start_playing(chip);
++		break;
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++		pcsp_stop_playing(chip);
++		break;
++	default:
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream
++						   *substream)
++{
++	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++	return bytes_to_frames(substream->runtime, chip->playback_ptr);
++}
++
++static struct snd_pcm_hardware snd_pcsp_playback = {
++	.info = (SNDRV_PCM_INFO_INTERLEAVED |
++		 SNDRV_PCM_INFO_HALF_DUPLEX |
++		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
++	.formats = SNDRV_PCM_FMTBIT_U8,
++	.rates = SNDRV_PCM_RATE_KNOT,
++	.rate_min = PCSP_DEFAULT_SRATE,
++	.rate_max = PCSP_DEFAULT_SRATE,
++	.channels_min = 1,
++	.channels_max = 1,
++	.buffer_bytes_max = PCSP_BUFFER_SIZE,
++	.period_bytes_min = 64,
++	.period_bytes_max = PCSP_MAX_PERIOD_SIZE,
++	.periods_min = 2,
++	.periods_max = PCSP_MAX_PERIODS,
++	.fifo_size = 0,
++};
++
++static int snd_pcsp_playback_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++	struct snd_pcm_runtime *runtime = substream->runtime;
++#if PCSP_DEBUG
++	printk(KERN_INFO "PCSP: open called\n");
++#endif
++	if (atomic_read(&chip->timer_active)) {
++		printk(KERN_ERR "PCSP: still active!!\n");
++		return -EBUSY;
++	}
++	runtime->hw = snd_pcsp_playback;
++	spin_lock_irq(&chip->substream_lock);
++	chip->playback_substream = substream;
++	spin_unlock_irq(&chip->substream_lock);
++	return 0;
++}
++
++static struct snd_pcm_ops snd_pcsp_playback_ops = {
++	.open = snd_pcsp_playback_open,
++	.close = snd_pcsp_playback_close,
++	.ioctl = snd_pcm_lib_ioctl,
++	.hw_params = snd_pcsp_playback_hw_params,
++	.hw_free = snd_pcsp_playback_hw_free,
++	.prepare = snd_pcsp_playback_prepare,
++	.trigger = snd_pcsp_trigger,
++	.pointer = snd_pcsp_playback_pointer,
++};
++
++int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip)
++{
++	int err;
++
++	err = snd_pcm_new(chip->card, "pcspeaker", 0, 1, 0, &chip->pcm);
++	if (err < 0)
++		return err;
++
++	snd_pcm_set_ops(chip->pcm, SNDRV_PCM_STREAM_PLAYBACK,
++			&snd_pcsp_playback_ops);
++
++	chip->pcm->private_data = chip;
++	chip->pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
++	strcpy(chip->pcm->name, "pcsp");
++
++	snd_pcm_lib_preallocate_pages_for_all(chip->pcm,
++					      SNDRV_DMA_TYPE_CONTINUOUS,
++					      snd_dma_continuous_data
++					      (GFP_KERNEL), PCSP_BUFFER_SIZE,
++					      PCSP_BUFFER_SIZE);
++
++	return 0;
++}
+diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c
+new file mode 100644
+index 0000000..64a695f
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp_mixer.c
+@@ -0,0 +1,143 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Mixer implementation.
++ * Copyright (C) 2001-2008  Stas Sergeev
++ */
++
++#include <sound/core.h>
++#include <sound/control.h>
++#include "pcsp.h"
++
++
++static int pcsp_enable_info(struct snd_kcontrol *kcontrol,
++			    struct snd_ctl_elem_info *uinfo)
++{
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++	uinfo->count = 1;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = 1;
++	return 0;
++}
++
++static int pcsp_enable_get(struct snd_kcontrol *kcontrol,
++			   struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++	ucontrol->value.integer.value[0] = chip->enable;
++	return 0;
++}
++
++static int pcsp_enable_put(struct snd_kcontrol *kcontrol,
++			   struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++	int changed = 0;
++	int enab = ucontrol->value.integer.value[0];
++	if (enab != chip->enable) {
++		chip->enable = enab;
++		changed = 1;
++	}
++	return changed;
++}
++
++static int pcsp_treble_info(struct snd_kcontrol *kcontrol,
++			    struct snd_ctl_elem_info *uinfo)
++{
++	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
++	uinfo->count = 1;
++	uinfo->value.enumerated.items = chip->max_treble + 1;
++	if (uinfo->value.enumerated.item > chip->max_treble)
++		uinfo->value.enumerated.item = chip->max_treble;
++	sprintf(uinfo->value.enumerated.name, "%d", PCSP_RATE());
++	return 0;
++}
++
++static int pcsp_treble_get(struct snd_kcontrol *kcontrol,
++			   struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++	ucontrol->value.enumerated.item[0] = chip->treble;
++	return 0;
++}
++
++static int pcsp_treble_put(struct snd_kcontrol *kcontrol,
++			   struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++	int changed = 0;
++	int treble = ucontrol->value.enumerated.item[0];
++	if (treble != chip->treble) {
++		chip->treble = treble;
++#if PCSP_DEBUG
++		printk(KERN_INFO "PCSP: rate set to %i\n", PCSP_RATE());
++#endif
++		changed = 1;
++	}
++	return changed;
++}
++
++static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol,
++			    struct snd_ctl_elem_info *uinfo)
++{
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++	uinfo->count = 1;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = 1;
++	return 0;
++}
++
++static int pcsp_pcspkr_get(struct snd_kcontrol *kcontrol,
++			   struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++	ucontrol->value.integer.value[0] = chip->pcspkr;
++	return 0;
++}
++
++static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
++			   struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++	int changed = 0;
++	int spkr = ucontrol->value.integer.value[0];
++	if (spkr != chip->pcspkr) {
++		chip->pcspkr = spkr;
++		changed = 1;
++	}
++	return changed;
++}
++
++#define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \
++{ \
++	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER, \
++	.name =		ctl_name, \
++	.info =		pcsp_##ctl_type##_info, \
++	.get =		pcsp_##ctl_type##_get, \
++	.put =		pcsp_##ctl_type##_put, \
++}
++
++static struct snd_kcontrol_new __devinitdata snd_pcsp_controls[] = {
++	PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
++	PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
++	PCSP_MIXER_CONTROL(pcspkr, "PC Speaker Playback Switch"),
++};
++
++int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip)
++{
++	struct snd_card *card = chip->card;
++	int i, err;
++
++	for (i = 0; i < ARRAY_SIZE(snd_pcsp_controls); i++) {
++		err = snd_ctl_add(card,
++				 snd_ctl_new1(snd_pcsp_controls + i,
++					      chip));
++		if (err < 0)
++			return err;
++	}
++
++	strcpy(card->mixername, "PC-Speaker");
++
++	return 0;
++}
+diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
+index 15061bd..d20d893 100644
+--- a/sound/i2c/other/ak4114.c
++++ b/sound/i2c/other/ak4114.c
+@@ -27,6 +27,7 @@
+ #include <sound/pcm.h>
+ #include <sound/ak4114.h>
+ #include <sound/asoundef.h>
++#include <sound/info.h>
+ 
+ MODULE_AUTHOR("Jaroslav Kysela <perex at perex.cz>");
+ MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei");
+@@ -446,6 +447,26 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
+ }
+ };
+ 
++
++static void snd_ak4114_proc_regs_read(struct snd_info_entry *entry,
++		struct snd_info_buffer *buffer)
++{
++	struct ak4114 *ak4114 = entry->private_data;
++	int reg, val;
++	/* all ak4114 registers 0x00 - 0x1f */
++	for (reg = 0; reg < 0x20; reg++) {
++		val = reg_read(ak4114, reg);
++		snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
++	}
++}
++
++static void snd_ak4114_proc_init(struct ak4114 *ak4114)
++{
++	struct snd_info_entry *entry;
++	if (!snd_card_proc_new(ak4114->card, "ak4114", &entry))
++		snd_info_set_text_ops(entry, ak4114, snd_ak4114_proc_regs_read);
++}
++
+ int snd_ak4114_build(struct ak4114 *ak4114,
+ 		     struct snd_pcm_substream *ply_substream,
+ 		     struct snd_pcm_substream *cap_substream)
+@@ -478,6 +499,7 @@ int snd_ak4114_build(struct ak4114 *ak4114,
+ 			return err;
+ 		ak4114->kctls[idx] = kctl;
+ 	}
++	snd_ak4114_proc_init(ak4114);
+ 	/* trigger workq */
+ 	schedule_delayed_work(&ak4114->work, HZ / 10);
+ 	return 0;
+@@ -590,7 +612,7 @@ static void ak4114_stats(struct work_struct *work)
+ 	struct ak4114 *chip = container_of(work, struct ak4114, work.work);
+ 
+ 	if (!chip->init)
+-		snd_ak4114_check_rate_and_errors(chip, 0);
++		snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
+ 
+ 	schedule_delayed_work(&chip->work, HZ / 10);
+ }
+diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
+index 35fbbf2..288926d 100644
+--- a/sound/i2c/other/ak4xxx-adda.c
++++ b/sound/i2c/other/ak4xxx-adda.c
+@@ -70,7 +70,8 @@ static void ak4524_reset(struct snd_akm4xxx *ak, int state)
+ }
+ 
+ /* reset procedure for AK4355 and AK4358 */
+-static void ak4355_reset(struct snd_akm4xxx *ak, int state)
++static void ak435X_reset(struct snd_akm4xxx *ak, int state,
++		unsigned char total_regs)
+ {
+ 	unsigned char reg;
+ 
+@@ -78,7 +79,7 @@ static void ak4355_reset(struct snd_akm4xxx *ak, int state)
+ 		snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
+ 		return;
+ 	}
+-	for (reg = 0x00; reg < 0x0b; reg++)
++	for (reg = 0x00; reg < total_regs; reg++)
+ 		if (reg != 0x01)
+ 			snd_akm4xxx_write(ak, 0, reg,
+ 					  snd_akm4xxx_get(ak, 0, reg));
+@@ -118,8 +119,10 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
+ 		/* FIXME: needed for ak4529? */
+ 		break;
+ 	case SND_AK4355:
++		ak435X_reset(ak, state, 0x0b);
++		break;
+ 	case SND_AK4358:
+-		ak4355_reset(ak, state);
++		ak435X_reset(ak, state, 0x10);
+ 		break;
+ 	case SND_AK4381:
+ 		ak4381_reset(ak, state);
+@@ -292,11 +295,6 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
+ 	case SND_AK5365:
+ 		/* FIXME: any init sequence? */
+ 		return;
+-	case NON_AKM:
+-		/* fake value for non-akm codecs using akm infrastructure
+-		 * (e.g. of ice1724) - certainly FIXME
+-		 */
+-		return;
+ 	default:
+ 		snd_BUG();
+ 		return;
+@@ -374,6 +372,8 @@ static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr,
+ 		nval = mask - nval;
+ 	if (AK_GET_NEEDSMSB(kcontrol->private_value))
+ 		nval |= 0x80;
++	/* printk(KERN_DEBUG "DEBUG - AK writing reg: chip %x addr %x,
++	   nval %x\n", chip, addr, nval); */
+ 	snd_akm4xxx_write(ak, chip, addr, nval);
+ 	return 1;
+ }
+diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
+index bed29ca..f3fd7b4 100644
+--- a/sound/isa/sb/sb16_csp.c
++++ b/sound/isa/sb/sb16_csp.c
+@@ -331,7 +331,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ 		return -EFAULT;
+ 	if ((file_h.name != RIFF_HEADER) ||
+ 	    (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
+-		snd_printd("%s: Invalid RIFF header\n", __FUNCTION__);
++		snd_printd("%s: Invalid RIFF header\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 	data_ptr += sizeof(file_h);
+@@ -340,7 +340,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ 	if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
+ 		return -EFAULT;
+ 	if (item_type != CSP__HEADER) {
+-		snd_printd("%s: Invalid RIFF file type\n", __FUNCTION__);
++		snd_printd("%s: Invalid RIFF file type\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 	data_ptr += sizeof (item_type);
+@@ -395,7 +395,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ 				return -EFAULT;
+ 
+ 			if (code_h.name != MAIN_HEADER) {
+-				snd_printd("%s: Missing 'main' microcode\n", __FUNCTION__);
++				snd_printd("%s: Missing 'main' microcode\n", __func__);
+ 				return -EINVAL;
+ 			}
+ 			data_ptr += sizeof(code_h);
+@@ -439,7 +439,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ 				p->acc_format = p->acc_width = p->acc_rates = 0;
+ 				p->mode = 0;
+ 				snd_printd("%s: Unsupported CSP codec type: 0x%04x\n",
+-					   __FUNCTION__,
++					   __func__,
+ 					   le16_to_cpu(funcdesc_h.VOC_type));
+ 				return -EINVAL;
+ 			}
+@@ -458,7 +458,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ 			return 0;
+ 		}
+ 	}
+-	snd_printd("%s: Function #%d not found\n", __FUNCTION__, info.func_req);
++	snd_printd("%s: Function #%d not found\n", __func__, info.func_req);
+ 	return -EINVAL;
+ }
+ 
+@@ -612,7 +612,7 @@ static int get_version(struct snd_sb *chip)
+ static int snd_sb_csp_check_version(struct snd_sb_csp * p)
+ {
+ 	if (p->version < 0x10 || p->version > 0x1f) {
+-		snd_printd("%s: Invalid CSP version: 0x%x\n", __FUNCTION__, p->version);
++		snd_printd("%s: Invalid CSP version: 0x%x\n", __func__, p->version);
+ 		return 1;
+ 	}
+ 	return 0;
+@@ -631,7 +631,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int
+ 	spin_lock_irqsave(&p->chip->reg_lock, flags);
+ 	snd_sbdsp_command(p->chip, 0x01);	/* CSP download command */
+ 	if (snd_sbdsp_get_byte(p->chip)) {
+-		snd_printd("%s: Download command failed\n", __FUNCTION__);
++		snd_printd("%s: Download command failed\n", __func__);
+ 		goto __fail;
+ 	}
+ 	/* Send CSP low byte (size - 1) */
+@@ -658,7 +658,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int
+ 			udelay (10);
+ 		}
+ 		if (status != 0x55) {
+-			snd_printd("%s: Microcode initialization failed\n", __FUNCTION__);
++			snd_printd("%s: Microcode initialization failed\n", __func__);
+ 			goto __fail;
+ 		}
+ 	} else {
+@@ -824,19 +824,19 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
+ 	unsigned long flags;
+ 
+ 	if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) {
+-		snd_printd("%s: Microcode not loaded\n", __FUNCTION__);
++		snd_printd("%s: Microcode not loaded\n", __func__);
+ 		return -ENXIO;
+ 	}
+ 	if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
+-		snd_printd("%s: CSP already running\n", __FUNCTION__);
++		snd_printd("%s: CSP already running\n", __func__);
+ 		return -EBUSY;
+ 	}
+ 	if (!(sample_width & p->acc_width)) {
+-		snd_printd("%s: Unsupported PCM sample width\n", __FUNCTION__);
++		snd_printd("%s: Unsupported PCM sample width\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 	if (!(channels & p->acc_channels)) {
+-		snd_printd("%s: Invalid number of channels\n", __FUNCTION__);
++		snd_printd("%s: Invalid number of channels\n", __func__);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -858,11 +858,11 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
+ 		s_type |= 0x22;	/* 00dX 00dX    (d = 1 if 8 bit samples) */
+ 
+ 	if (set_codec_parameter(p->chip, 0x81, s_type)) {
+-		snd_printd("%s: Set sample type command failed\n", __FUNCTION__);
++		snd_printd("%s: Set sample type command failed\n", __func__);
+ 		goto __fail;
+ 	}
+ 	if (set_codec_parameter(p->chip, 0x80, 0x00)) {
+-		snd_printd("%s: Codec start command failed\n", __FUNCTION__);
++		snd_printd("%s: Codec start command failed\n", __func__);
+ 		goto __fail;
+ 	}
+ 	p->run_width = sample_width;
+diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
+index d63c1af..b432d9a 100644
+--- a/sound/isa/sb/sb_common.c
++++ b/sound/isa/sb/sb_common.c
+@@ -51,7 +51,7 @@ int snd_sbdsp_command(struct snd_sb *chip, unsigned char val)
+ 			outb(val, SBP(chip, COMMAND));
+ 			return 1;
+ 		}
+-	snd_printd("%s [0x%lx]: timeout (0x%x)\n", __FUNCTION__, chip->port, val);
++	snd_printd("%s [0x%lx]: timeout (0x%x)\n", __func__, chip->port, val);
+ 	return 0;
+ }
+ 
+@@ -68,7 +68,7 @@ int snd_sbdsp_get_byte(struct snd_sb *chip)
+ 			return val;
+ 		}
+ 	}
+-	snd_printd("%s [0x%lx]: timeout\n", __FUNCTION__, chip->port);
++	snd_printd("%s [0x%lx]: timeout\n", __func__, chip->port);
+ 	return -ENODEV;
+ }
+ 
+@@ -87,7 +87,7 @@ int snd_sbdsp_reset(struct snd_sb *chip)
+ 			else
+ 				break;
+ 		}
+-	snd_printdd("%s [0x%lx] failed...\n", __FUNCTION__, chip->port);
++	snd_printdd("%s [0x%lx] failed...\n", __func__, chip->port);
+ 	return -ENODEV;
+ }
+ 
+diff --git a/sound/oss/dmabuf.c b/sound/oss/dmabuf.c
+index eaf6997..1e90d76 100644
+--- a/sound/oss/dmabuf.c
++++ b/sound/oss/dmabuf.c
+@@ -795,9 +795,9 @@ static int find_output_space(int dev, char **buf, int *size)
+ #ifdef BE_CONSERVATIVE
+ 	active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size;
+ #else
+-	active_offs = DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT);
++	active_offs = max(DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT), 0);
+ 	/* Check for pointer wrapping situation */
+-	if (active_offs < 0 || active_offs >= dmap->bytes_in_use)
++	if (active_offs >= dmap->bytes_in_use)
+ 		active_offs = 0;
+ 	active_offs += dmap->byte_counter;
+ #endif
+diff --git a/sound/oss/trident.c b/sound/oss/trident.c
+index d6af906..f43f91e 100644
+--- a/sound/oss/trident.c
++++ b/sound/oss/trident.c
+@@ -3076,8 +3076,7 @@ ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
+ 	u16 wcontrol;
+ 	unsigned long flags;
+ 
+-	if (!card)
+-		BUG();
++	BUG_ON(!card);
+ 
+ 	address = ALI_AC97_READ;
+ 	if (card->revision == ALI_5451_V02) {
+@@ -3148,8 +3147,7 @@ ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
+ 
+ 	data = ((u32) val) << 16;
+ 
+-	if (!card)
+-		BUG();
++	BUG_ON(!card);
+ 
+ 	address = ALI_AC97_WRITE;
+ 	mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
+@@ -3213,8 +3211,7 @@ ali_ac97_read(struct ac97_codec *codec, u8 reg)
+ 	struct trident_card *card = NULL;
+ 
+ 	/* Added by Matt Wu */
+-	if (!codec)
+-		BUG();
++	BUG_ON(!codec);
+ 
+ 	card = (struct trident_card *) codec->private_data;
+ 
+@@ -3240,8 +3237,7 @@ ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
+ 	struct trident_card *card;
+ 
+ 	/*  Added by Matt Wu */
+-	if (!codec)
+-		BUG();
++	BUG_ON(!codec);
+ 
+ 	card = (struct trident_card *) codec->private_data;
+ 
+diff --git a/sound/oss/trident.h b/sound/oss/trident.h
+index 4713b49..ff30a1d 100644
+--- a/sound/oss/trident.h
++++ b/sound/oss/trident.h
+@@ -322,7 +322,7 @@ enum miscint_bits {
+ #define VALIDATE_MAGIC(FOO,MAG)				\
+ ({						  	\
+ 	if (!(FOO) || (FOO)->magic != MAG) { 		\
+-		printk(invalid_magic,__FUNCTION__);	\
++		printk(invalid_magic,__func__);	\
+ 		return -ENXIO;			  	\
+ 	}					  	\
+ })
+diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
+index d25249a..2c5aaa5 100644
+--- a/sound/oss/vwsnd.c
++++ b/sound/oss/vwsnd.c
+@@ -194,11 +194,11 @@ static void dbgassert(const char *fcn, int line, const char *expr)
+  *	DBGRV	- debug print function return when verbose
+  */
+ 
+-#define ASSERT(e)      ((e) ? (void) 0 : dbgassert(__FUNCTION__, __LINE__, #e))
++#define ASSERT(e)      ((e) ? (void) 0 : dbgassert(__func__, __LINE__, #e))
+ #define DBGDO(x)            x
+ #define DBGX(fmt, args...)  (in_interrupt() ? 0 : printk(KERN_ERR fmt, ##args))
+-#define DBGP(fmt, args...)  (DBGX("%s: " fmt, __FUNCTION__ , ##args))
+-#define DBGE(fmt, args...)  (DBGX("%s" fmt, __FUNCTION__ , ##args))
++#define DBGP(fmt, args...)  (DBGX("%s: " fmt, __func__ , ##args))
++#define DBGE(fmt, args...)  (DBGX("%s" fmt, __func__ , ##args))
+ #define DBGC(rtn)           (DBGP("calling %s\n", rtn))
+ #define DBGR()              (DBGP("returning\n"))
+ #define DBGXV(fmt, args...) (shut_up ? 0 : DBGX(fmt, ##args))
+diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
+index 812085d..581debf 100644
+--- a/sound/pci/Kconfig
++++ b/sound/pci/Kconfig
+@@ -122,6 +122,21 @@ config SND_AU8830
+ 	  To compile this driver as a module, choose M here: the module
+ 	  will be called snd-au8830.
+ 
++config SND_AW2
++	tristate "Emagic Audiowerk 2"
++	depends on SND
++	help
++	  Say Y here to include support for Emagic Audiowerk 2 soundcards.
++
++	  Supported features: Analog and SPDIF output. Analog or SPDIF input.
++	  Note: Switch between analog and digital input does not always work.
++	  It can produce continuous noise. The workaround is to switch again
++	  (and again) between digital and analog input until it works.
++
++	  To compile this driver as a module, choose M here: the module
++	  will be called snd-aw2.
++
++
+ config SND_AZT3328
+ 	tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
+ 	depends on SND && EXPERIMENTAL
+@@ -162,6 +177,7 @@ config SND_CA0106
+ 	depends on SND
+ 	select SND_AC97_CODEC
+ 	select SND_RAWMIDI
++	select SND_VMASTER
+ 	help
+ 	  Say Y here to include support for the Sound Blaster Audigy LS
+ 	  and Live 24bit.
+@@ -517,6 +533,7 @@ config SND_HDA_INTEL
+ 	tristate "Intel HD Audio"
+ 	depends on SND
+ 	select SND_PCM
++	select SND_VMASTER
+ 	help
+ 	  Say Y here to include support for Intel "High Definition
+ 	  Audio" (Azalia) motherboard devices.
+@@ -680,6 +697,7 @@ config SND_ICE1724
+ 	depends on SND
+ 	select SND_MPU401_UART
+ 	select SND_AC97_CODEC
++	select SND_VMASTER
+ 	help
+ 	  Say Y here to include support for soundcards based on
+ 	  ICE/VT1724/1720 (Envy24HT/PT) chips.
+@@ -896,12 +914,12 @@ config SND_VIA82XX_MODEM
+ 	  will be called snd-via82xx-modem.
+ 
+ config SND_VIRTUOSO
+-	tristate "Asus Virtuoso 200 (Xonar)"
++	tristate "Asus Virtuoso 100/200 (Xonar)"
+ 	depends on SND
+ 	select SND_OXYGEN_LIB
+ 	help
+ 	  Say Y here to include support for sound cards based on the
+-	  Asus AV200 chip, i.e., Xonar D2 and Xonar D2X.
++	  Asus AV100/AV200 chips, i.e., Xonar D2, DX and D2X.
+ 
+ 	  To compile this driver as a module, choose M here: the module
+ 	  will be called snd-virtuoso.
+diff --git a/sound/pci/Makefile b/sound/pci/Makefile
+index 2d42fd2..85ef14b 100644
+--- a/sound/pci/Makefile
++++ b/sound/pci/Makefile
+@@ -58,6 +58,7 @@ obj-$(CONFIG_SND) += \
+ 	ac97/ \
+ 	ali5451/ \
+ 	au88x0/ \
++	aw2/ \
+ 	ca0106/ \
+ 	cs46xx/ \
+ 	cs5535audio/ \
+diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
+index 50c637e..39198e5 100644
+--- a/sound/pci/ac97/ac97_patch.c
++++ b/sound/pci/ac97/ac97_patch.c
+@@ -114,10 +114,9 @@ static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd
+ 
+ static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+ {
+-	static const char *texts[] = { "2ch", "4ch", "6ch" };
+-	if (kcontrol->private_value)
+-		return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */
+-	return ac97_enum_text_info(kcontrol, uinfo, texts, 3);
++	static const char *texts[] = { "2ch", "4ch", "6ch", "8ch" };
++	return ac97_enum_text_info(kcontrol, uinfo, texts,
++		kcontrol->private_value);
+ }
+ 
+ static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+@@ -133,13 +132,8 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
+ 	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+ 	unsigned char mode = ucontrol->value.enumerated.item[0];
+ 
+-	if (kcontrol->private_value) {
+-		if (mode >= 2)
+-			return -EINVAL;
+-	} else {
+-		if (mode >= 3)
+-			return -EINVAL;
+-	}
++	if (mode >= kcontrol->private_value)
++		return -EINVAL;
+ 
+ 	if (mode != ac97->channel_mode) {
+ 		ac97->channel_mode = mode;
+@@ -158,6 +152,7 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
+ 		.get = ac97_surround_jack_mode_get, \
+ 		.put = ac97_surround_jack_mode_put, \
+ 	}
++/* 6ch */
+ #define AC97_CHANNEL_MODE_CTL \
+ 	{ \
+ 		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, \
+@@ -165,7 +160,9 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
+ 		.info = ac97_channel_mode_info, \
+ 		.get = ac97_channel_mode_get, \
+ 		.put = ac97_channel_mode_put, \
++		.private_value = 3, \
+ 	}
++/* 4ch */
+ #define AC97_CHANNEL_MODE_4CH_CTL \
+ 	{ \
+ 		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, \
+@@ -173,7 +170,17 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
+ 		.info = ac97_channel_mode_info, \
+ 		.get = ac97_channel_mode_get, \
+ 		.put = ac97_channel_mode_put, \
+-		.private_value = 1, \
++		.private_value = 2, \
++	}
++/* 8ch */
++#define AC97_CHANNEL_MODE_8CH_CTL \
++	{ \
++		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
++		.name   = "Channel Mode", \
++		.info = ac97_channel_mode_info, \
++		.get = ac97_channel_mode_get, \
++		.put = ac97_channel_mode_put, \
++		.private_value = 4, \
+ 	}
+ 
+ static inline int is_surround_on(struct snd_ac97 *ac97)
+@@ -210,6 +217,10 @@ static inline int is_shared_micin(struct snd_ac97 *ac97)
+ 	return !ac97->indep_surround && !is_clfe_on(ac97);
+ }
+ 
++static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97)
++{
++	return is_surround_on(ac97);
++}
+ 
+ /* The following snd_ac97_ymf753_... items added by David Shust (dshust at shustring.com) */
+ /* Modified for YMF743 by Keita Maehara <maehara at debian.org> */
+@@ -2816,10 +2827,12 @@ static int patch_alc655(struct snd_ac97 * ac97)
+ 
+ #define AC97_ALC850_JACK_SELECT	0x76
+ #define AC97_ALC850_MISC1	0x7a
++#define AC97_ALC850_MULTICH    0x6a
+ 
+ static void alc850_update_jacks(struct snd_ac97 *ac97)
+ {
+ 	int shared;
++	int aux_is_back_surround;
+ 	
+ 	/* shared Line-In / Surround Out */
+ 	shared = is_shared_surrout(ac97);
+@@ -2837,13 +2850,18 @@ static void alc850_update_jacks(struct snd_ac97 *ac97)
+ 	/* MIC-IN = 1, CENTER-LFE = 5 */
+ 	snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
+ 			     shared ? (5<<4) : (1<<4));
++
++	aux_is_back_surround = alc850_is_aux_back_surround(ac97);
++	/* Aux is Back Surround */
++	snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
++				 aux_is_back_surround ? (1<<10) : (0<<10));
+ }
+ 
+ static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
+ 	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
+ 	AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
+ 	AC97_SURROUND_JACK_MODE_CTL,
+-	AC97_CHANNEL_MODE_CTL,
++	AC97_CHANNEL_MODE_8CH_CTL,
+ };
+ 
+ static int patch_alc850_specific(struct snd_ac97 *ac97)
+@@ -2869,6 +2887,7 @@ static int patch_alc850(struct snd_ac97 *ac97)
+ 	ac97->build_ops = &patch_alc850_ops;
+ 
+ 	ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
++	ac97->flags |= AC97_HAS_8CH;
+ 
+ 	/* assume only page 0 for writing cache */
+ 	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+@@ -2878,6 +2897,7 @@ static int patch_alc850(struct snd_ac97 *ac97)
+ 	   spdif-in monitor off, spdif-in PCM off
+ 	   center on mic off, surround on line-in off
+ 	   duplicate front off
++	   NB default bit 10=0 = Aux is Capture, not Back Surround
+ 	*/
+ 	snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
+ 	/* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
+diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
+index 3674f35..48cbda9 100644
+--- a/sound/pci/ac97/ac97_pcm.c
++++ b/sound/pci/ac97/ac97_pcm.c
+@@ -574,7 +574,6 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
+ 	r = rate > 48000;
+ 	bus = pcm->bus;
+ 	if (cfg == AC97_PCM_CFG_SPDIF) {
+-		int err;
+ 		for (cidx = 0; cidx < 4; cidx++)
+ 			if (bus->codec[cidx] && (bus->codec[cidx]->ext_id & AC97_EI_SPDIF)) {
+ 				err = set_spdif_rate(bus->codec[cidx], rate);
+diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
+index a66d515..39ec55b 100644
+--- a/sound/pci/ad1889.c
++++ b/sound/pci/ad1889.c
+@@ -264,10 +264,10 @@ snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
+ 		mdelay(1);
+ 	if (!retry) {
+ 		snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n",
+-		       __FUNCTION__);
++		       __func__);
+ 		return -EIO;
+ 	}
+-	ad1889_debug("[%s] ready after %d ms\n", __FUNCTION__, 400 - retry);
++	ad1889_debug("[%s] ready after %d ms\n", __func__, 400 - retry);
+ 
+ 	return 0;
+ }
+@@ -854,8 +854,6 @@ snd_ad1889_free(struct snd_ad1889 *chip)
+ 
+ 	spin_unlock_irq(&chip->lock);
+ 
+-	synchronize_irq(chip->irq);
+-	
+ 	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+ 
+diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
+index 6a905ed..1a0fd65 100644
+--- a/sound/pci/ali5451/ali5451.c
++++ b/sound/pci/ali5451/ali5451.c
+@@ -1809,26 +1809,26 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,
+ 				 struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_ali *codec = kcontrol->private_data;
+-	unsigned int enable;
++	unsigned int spdif_enable;
+ 
+-	enable = ucontrol->value.integer.value[0] ? 1 : 0;
++	spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
+ 
+ 	spin_lock_irq(&codec->reg_lock);
+ 	switch (kcontrol->private_value) {
+ 	case 0:
+-		enable = (codec->spdif_mask & 0x02) ? 1 : 0;
++		spdif_enable = (codec->spdif_mask & 0x02) ? 1 : 0;
+ 		break;
+ 	case 1:
+-		enable = ((codec->spdif_mask & 0x02) &&
++		spdif_enable = ((codec->spdif_mask & 0x02) &&
+ 			  (codec->spdif_mask & 0x04)) ? 1 : 0;
+ 		break;
+ 	case 2:
+-		enable = (codec->spdif_mask & 0x01) ? 1 : 0;
++		spdif_enable = (codec->spdif_mask & 0x01) ? 1 : 0;
+ 		break;
+ 	default:
+ 		break;
+ 	}
+-	ucontrol->value.integer.value[0] = enable;
++	ucontrol->value.integer.value[0] = spdif_enable;
+ 	spin_unlock_irq(&codec->reg_lock);
+ 	return 0;
+ }
+@@ -1837,17 +1837,17 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
+ 				 struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_ali *codec = kcontrol->private_data;
+-	unsigned int change = 0, enable = 0;
++	unsigned int change = 0, spdif_enable = 0;
+ 
+-	enable = ucontrol->value.integer.value[0] ? 1 : 0;
++	spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
+ 
+ 	spin_lock_irq(&codec->reg_lock);
+ 	switch (kcontrol->private_value) {
+ 	case 0:
+ 		change = (codec->spdif_mask & 0x02) ? 1 : 0;
+-		change = change ^ enable;
++		change = change ^ spdif_enable;
+ 		if (change) {
+-			if (enable) {
++			if (spdif_enable) {
+ 				codec->spdif_mask |= 0x02;
+ 				snd_ali_enable_spdif_out(codec);
+ 			} else {
+@@ -1859,9 +1859,9 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
+ 		break;
+ 	case 1: 
+ 		change = (codec->spdif_mask & 0x04) ? 1 : 0;
+-		change = change ^ enable;
++		change = change ^ spdif_enable;
+ 		if (change && (codec->spdif_mask & 0x02)) {
+-			if (enable) {
++			if (spdif_enable) {
+ 				codec->spdif_mask |= 0x04;
+ 				snd_ali_enable_spdif_chnout(codec);
+ 			} else {
+@@ -1872,9 +1872,9 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
+ 		break;
+ 	case 2:
+ 		change = (codec->spdif_mask & 0x01) ? 1 : 0;
+-		change = change ^ enable;
++		change = change ^ spdif_enable;
+ 		if (change) {
+-			if (enable) {
++			if (spdif_enable) {
+ 				codec->spdif_mask |= 0x01;
+ 				snd_ali_enable_spdif_in(codec);
+ 			} else {
+@@ -2047,10 +2047,8 @@ static int snd_ali_free(struct snd_ali * codec)
+ {
+ 	if (codec->hw_initialized)
+ 		snd_ali_disable_address_interrupt(codec);
+-	if (codec->irq >= 0) {
+-		synchronize_irq(codec->irq);
++	if (codec->irq >= 0)
+ 		free_irq(codec->irq, codec);
+-	}
+ 	if (codec->port)
+ 		pci_release_regions(codec->pci);
+ 	pci_disable_device(codec->pci);
+diff --git a/sound/pci/als300.c b/sound/pci/als300.c
+index 0e990a7..8df6824 100644
+--- a/sound/pci/als300.c
++++ b/sound/pci/als300.c
+@@ -92,8 +92,8 @@
+ 
+ #if DEBUG_CALLS
+ #define snd_als300_dbgcalls(format, args...) printk(format, ##args)
+-#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
+-#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
++#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
++#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
+ #else
+ #define snd_als300_dbgcalls(format, args...)
+ #define snd_als300_dbgcallenter()
+diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
+index 4594186..457228f 100644
+--- a/sound/pci/atiixp.c
++++ b/sound/pci/atiixp.c
+@@ -1553,7 +1553,7 @@ static int snd_atiixp_free(struct atiixp *chip)
+ 	if (chip->irq < 0)
+ 		goto __hw_end;
+ 	snd_atiixp_chip_stop(chip);
+-	synchronize_irq(chip->irq);
++
+       __hw_end:
+ 	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
+index a67a869..d457a32 100644
+--- a/sound/pci/atiixp_modem.c
++++ b/sound/pci/atiixp_modem.c
+@@ -1197,7 +1197,7 @@ static int snd_atiixp_free(struct atiixp_modem *chip)
+ 	if (chip->irq < 0)
+ 		goto __hw_end;
+ 	snd_atiixp_chip_stop(chip);
+-	synchronize_irq(chip->irq);
++
+       __hw_end:
+ 	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
+index 26819e2..68368e4 100644
+--- a/sound/pci/au88x0/au88x0.c
++++ b/sound/pci/au88x0/au88x0.c
+@@ -126,7 +126,6 @@ static int snd_vortex_dev_free(struct snd_device *device)
+ 	vortex_gameport_unregister(vortex);
+ 	vortex_core_shutdown(vortex);
+ 	// Take down PCI interface.
+-	synchronize_irq(vortex->irq);
+ 	free_irq(vortex->irq, vortex);
+ 	iounmap(vortex->mmio);
+ 	pci_release_regions(vortex->pci_dev);
+@@ -220,7 +219,6 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
+ 	return 0;
+ 
+       alloc_out:
+-	synchronize_irq(chip->irq);
+ 	free_irq(chip->irq, chip);
+       irq_out:
+ 	vortex_core_shutdown(chip);
+diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
+index 526c6c5..f9a58b4 100644
+--- a/sound/pci/au88x0/au88x0_pcm.c
++++ b/sound/pci/au88x0/au88x0_pcm.c
+@@ -498,14 +498,14 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
+ };
+ 
+ /* create a pcm device */
+-static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
++static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
+ {
+ 	struct snd_pcm *pcm;
+ 	struct snd_kcontrol *kctl;
+ 	int i;
+ 	int err, nr_capt;
+ 
+-	if ((chip == 0) || (idx < 0) || (idx >= VORTEX_PCM_LAST))
++	if (!chip || idx < 0 || idx >= VORTEX_PCM_LAST)
+ 		return -ENODEV;
+ 
+ 	/* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the 
+@@ -514,9 +514,9 @@ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
+ 		nr_capt = nr;
+ 	else
+ 		nr_capt = 0;
+-	if ((err =
+-	     snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
+-			 nr_capt, &pcm)) < 0)
++	err = snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
++			  nr_capt, &pcm);
++	if (err < 0)
+ 		return err;
+ 	strcpy(pcm->name, vortex_pcm_name[idx]);
+ 	chip->pcm[idx] = pcm;
+diff --git a/sound/pci/aw2/Makefile b/sound/pci/aw2/Makefile
+new file mode 100644
+index 0000000..842335d
+--- /dev/null
++++ b/sound/pci/aw2/Makefile
+@@ -0,0 +1,3 @@
++snd-aw2-objs := aw2-alsa.o aw2-saa7146.o
++
++obj-$(CONFIG_SND_AW2) += snd-aw2.o
+diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
+new file mode 100644
+index 0000000..56f87cd
+--- /dev/null
++++ b/sound/pci/aw2/aw2-alsa.c
+@@ -0,0 +1,794 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/control.h>
++
++#include "saa7146.h"
++#include "aw2-saa7146.h"
++
++MODULE_AUTHOR("Cedric Bregardis <cedric.bregardis at free.fr>, "
++	      "Jean-Christian Hassler <jhassler at free.fr>");
++MODULE_DESCRIPTION("Emagic Audiowerk 2 sound driver");
++MODULE_LICENSE("GPL");
++
++/*********************************
++ * DEFINES
++ ********************************/
++#define PCI_VENDOR_ID_SAA7146		  0x1131
++#define PCI_DEVICE_ID_SAA7146		  0x7146
++
++#define CTL_ROUTE_ANALOG 0
++#define CTL_ROUTE_DIGITAL 1
++
++/*********************************
++ * TYPEDEFS
++ ********************************/
++  /* hardware definition */
++static struct snd_pcm_hardware snd_aw2_playback_hw = {
++	.info = (SNDRV_PCM_INFO_MMAP |
++		 SNDRV_PCM_INFO_INTERLEAVED |
++		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
++	.formats = SNDRV_PCM_FMTBIT_S16_LE,
++	.rates = SNDRV_PCM_RATE_44100,
++	.rate_min = 44100,
++	.rate_max = 44100,
++	.channels_min = 2,
++	.channels_max = 4,
++	.buffer_bytes_max = 32768,
++	.period_bytes_min = 4096,
++	.period_bytes_max = 32768,
++	.periods_min = 1,
++	.periods_max = 1024,
++};
++
++static struct snd_pcm_hardware snd_aw2_capture_hw = {
++	.info = (SNDRV_PCM_INFO_MMAP |
++		 SNDRV_PCM_INFO_INTERLEAVED |
++		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
++	.formats = SNDRV_PCM_FMTBIT_S16_LE,
++	.rates = SNDRV_PCM_RATE_44100,
++	.rate_min = 44100,
++	.rate_max = 44100,
++	.channels_min = 2,
++	.channels_max = 2,
++	.buffer_bytes_max = 32768,
++	.period_bytes_min = 4096,
++	.period_bytes_max = 32768,
++	.periods_min = 1,
++	.periods_max = 1024,
++};
++
++struct aw2_pcm_device {
++	struct snd_pcm *pcm;
++	unsigned int stream_number;
++	struct aw2 *chip;
++};
++
++struct aw2 {
++	struct snd_aw2_saa7146 saa7146;
++
++	struct pci_dev *pci;
++	int irq;
++	spinlock_t reg_lock;
++	struct mutex mtx;
++
++	unsigned long iobase_phys;
++	void __iomem *iobase_virt;
++
++	struct snd_card *card;
++
++	struct aw2_pcm_device device_playback[NB_STREAM_PLAYBACK];
++	struct aw2_pcm_device device_capture[NB_STREAM_CAPTURE];
++};
++
++/*********************************
++ * FUNCTION DECLARATIONS
++ ********************************/
++static int __init alsa_card_aw2_init(void);
++static void __exit alsa_card_aw2_exit(void);
++static int snd_aw2_dev_free(struct snd_device *device);
++static int __devinit snd_aw2_create(struct snd_card *card,
++				    struct pci_dev *pci, struct aw2 **rchip);
++static int __devinit snd_aw2_probe(struct pci_dev *pci,
++				   const struct pci_device_id *pci_id);
++static void __devexit snd_aw2_remove(struct pci_dev *pci);
++static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
++				 struct snd_pcm_hw_params *hw_params);
++static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
++					int cmd);
++static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
++				       int cmd);
++static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
++						      *substream);
++static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
++						     *substream);
++static int __devinit snd_aw2_new_pcm(struct aw2 *chip);
++
++static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
++					       struct snd_ctl_elem_info *uinfo);
++static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
++					      struct snd_ctl_elem_value
++					      *ucontrol);
++static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
++					      struct snd_ctl_elem_value
++					      *ucontrol);
++
++/*********************************
++ * VARIABLES
++ ********************************/
++static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
++static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
++static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
++
++module_param_array(index, int, NULL, 0444);
++MODULE_PARM_DESC(index, "Index value for Audiowerk2 soundcard.");
++module_param_array(id, charp, NULL, 0444);
++MODULE_PARM_DESC(id, "ID string for the Audiowerk2 soundcard.");
++module_param_array(enable, bool, NULL, 0444);
++MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard.");
++
++static struct pci_device_id snd_aw2_ids[] = {
++	{PCI_VENDOR_ID_SAA7146, PCI_DEVICE_ID_SAA7146, PCI_ANY_ID, PCI_ANY_ID,
++	 0, 0, 0},
++	{0}
++};
++
++MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
++
++/* pci_driver definition */
++static struct pci_driver driver = {
++	.name = "Emagic Audiowerk 2",
++	.id_table = snd_aw2_ids,
++	.probe = snd_aw2_probe,
++	.remove = __devexit_p(snd_aw2_remove),
++};
++
++/* operators for playback PCM alsa interface */
++static struct snd_pcm_ops snd_aw2_playback_ops = {
++	.open = snd_aw2_pcm_playback_open,
++	.close = snd_aw2_pcm_playback_close,
++	.ioctl = snd_pcm_lib_ioctl,
++	.hw_params = snd_aw2_pcm_hw_params,
++	.hw_free = snd_aw2_pcm_hw_free,
++	.prepare = snd_aw2_pcm_prepare_playback,
++	.trigger = snd_aw2_pcm_trigger_playback,
++	.pointer = snd_aw2_pcm_pointer_playback,
++};
++
++/* operators for capture PCM alsa interface */
++static struct snd_pcm_ops snd_aw2_capture_ops = {
++	.open = snd_aw2_pcm_capture_open,
++	.close = snd_aw2_pcm_capture_close,
++	.ioctl = snd_pcm_lib_ioctl,
++	.hw_params = snd_aw2_pcm_hw_params,
++	.hw_free = snd_aw2_pcm_hw_free,
++	.prepare = snd_aw2_pcm_prepare_capture,
++	.trigger = snd_aw2_pcm_trigger_capture,
++	.pointer = snd_aw2_pcm_pointer_capture,
++};
++
++static struct snd_kcontrol_new aw2_control __devinitdata = {
++	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++	.name = "PCM Capture Route",
++	.index = 0,
++	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++	.private_value = 0xffff,
++	.info = snd_aw2_control_switch_capture_info,
++	.get = snd_aw2_control_switch_capture_get,
++	.put = snd_aw2_control_switch_capture_put
++};
++
++/*********************************
++ * FUNCTION IMPLEMENTATIONS
++ ********************************/
++
++/* initialization of the module */
++static int __init alsa_card_aw2_init(void)
++{
++	snd_printdd(KERN_DEBUG "aw2: Load aw2 module\n");
++	return pci_register_driver(&driver);
++}
++
++/* clean up the module */
++static void __exit alsa_card_aw2_exit(void)
++{
++	snd_printdd(KERN_DEBUG "aw2: Unload aw2 module\n");
++	pci_unregister_driver(&driver);
++}
++
++module_init(alsa_card_aw2_init);
++module_exit(alsa_card_aw2_exit);
++
++/* component-destructor */
++static int snd_aw2_dev_free(struct snd_device *device)
++{
++	struct aw2 *chip = device->device_data;
++
++	/* Free hardware */
++	snd_aw2_saa7146_free(&chip->saa7146);
++
++	/* release the irq */
++	if (chip->irq >= 0)
++		free_irq(chip->irq, (void *)chip);
++	/* release the i/o ports & memory */
++	if (chip->iobase_virt)
++		iounmap(chip->iobase_virt);
++
++	pci_release_regions(chip->pci);
++	/* disable the PCI entry */
++	pci_disable_device(chip->pci);
++	/* release the data */
++	kfree(chip);
++
++	return 0;
++}
++
++/* chip-specific constructor */
++static int __devinit snd_aw2_create(struct snd_card *card,
++				    struct pci_dev *pci, struct aw2 **rchip)
++{
++	struct aw2 *chip;
++	int err;
++	static struct snd_device_ops ops = {
++		.dev_free = snd_aw2_dev_free,
++	};
++
++	*rchip = NULL;
++
++	/* initialize the PCI entry */
++	err = pci_enable_device(pci);
++	if (err < 0)
++		return err;
++	pci_set_master(pci);
++
++	/* check PCI availability (32bit DMA) */
++	if ((pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) ||
++	    (pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0)) {
++		printk(KERN_ERR "aw2: Impossible to set 32bit mask DMA\n");
++		pci_disable_device(pci);
++		return -ENXIO;
++	}
++	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
++	if (chip == NULL) {
++		pci_disable_device(pci);
++		return -ENOMEM;
++	}
++
++	/* initialize the stuff */
++	chip->card = card;
++	chip->pci = pci;
++	chip->irq = -1;
++
++	/* (1) PCI resource allocation */
++	err = pci_request_regions(pci, "Audiowerk2");
++	if (err < 0) {
++		pci_disable_device(pci);
++		kfree(chip);
++		return err;
++	}
++	chip->iobase_phys = pci_resource_start(pci, 0);
++	chip->iobase_virt =
++		ioremap_nocache(chip->iobase_phys,
++				pci_resource_len(pci, 0));
++
++	if (chip->iobase_virt == NULL) {
++		printk(KERN_ERR "aw2: unable to remap memory region");
++		pci_release_regions(pci);
++		pci_disable_device(pci);
++		kfree(chip);
++		return -ENOMEM;
++	}
++
++
++	if (request_irq(pci->irq, snd_aw2_saa7146_interrupt,
++			IRQF_SHARED, "Audiowerk2", chip)) {
++		printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq);
++
++		iounmap(chip->iobase_virt);
++		pci_release_regions(chip->pci);
++		pci_disable_device(chip->pci);
++		kfree(chip);
++		return -EBUSY;
++	}
++	chip->irq = pci->irq;
++
++	/* (2) initialization of the chip hardware */
++	snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
++	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
++	if (err < 0) {
++		free_irq(chip->irq, (void *)chip);
++		iounmap(chip->iobase_virt);
++		pci_release_regions(chip->pci);
++		pci_disable_device(chip->pci);
++		kfree(chip);
++		return err;
++	}
++
++	snd_card_set_dev(card, &pci->dev);
++	*rchip = chip;
++
++	printk(KERN_INFO
++	       "Audiowerk 2 sound card (saa7146 chipset) detected and "
++	       "managed\n");
++	return 0;
++}
++
++/* constructor */
++static int __devinit snd_aw2_probe(struct pci_dev *pci,
++				   const struct pci_device_id *pci_id)
++{
++	static int dev;
++	struct snd_card *card;
++	struct aw2 *chip;
++	int err;
++
++	/* (1) Continue if device is not enabled, else inc dev */
++	if (dev >= SNDRV_CARDS)
++		return -ENODEV;
++	if (!enable[dev]) {
++		dev++;
++		return -ENOENT;
++	}
++
++	/* (2) Create card instance */
++	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
++	if (card == NULL)
++		return -ENOMEM;
++
++	/* (3) Create main component */
++	err = snd_aw2_create(card, pci, &chip);
++	if (err < 0) {
++		snd_card_free(card);
++		return err;
++	}
++
++	/* initialize mutex */
++	mutex_init(&chip->mtx);
++	/* init spinlock */
++	spin_lock_init(&chip->reg_lock);
++	/* (4) Define driver ID and name string */
++	strcpy(card->driver, "aw2");
++	strcpy(card->shortname, "Audiowerk2");
++
++	sprintf(card->longname, "%s with SAA7146 irq %i",
++		card->shortname, chip->irq);
++
++	/* (5) Create other components */
++	snd_aw2_new_pcm(chip);
++
++	/* (6) Register card instance */
++	err = snd_card_register(card);
++	if (err < 0) {
++		snd_card_free(card);
++		return err;
++	}
++
++	/* (7) Set PCI driver data */
++	pci_set_drvdata(pci, card);
++
++	dev++;
++	return 0;
++}
++
++/* destructor */
++static void __devexit snd_aw2_remove(struct pci_dev *pci)
++{
++	snd_card_free(pci_get_drvdata(pci));
++	pci_set_drvdata(pci, NULL);
++}
++
++/* open callback */
++static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++
++	snd_printdd(KERN_DEBUG "aw2: Playback_open \n");
++	runtime->hw = snd_aw2_playback_hw;
++	return 0;
++}
++
++/* close callback */
++static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream)
++{
++	return 0;
++
++}
++
++static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++
++	snd_printdd(KERN_DEBUG "aw2: Capture_open \n");
++	runtime->hw = snd_aw2_capture_hw;
++	return 0;
++}
++
++/* close callback */
++static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream)
++{
++	/* TODO: something to do ? */
++	return 0;
++}
++
++ /* hw_params callback */
++static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
++				 struct snd_pcm_hw_params *hw_params)
++{
++	return snd_pcm_lib_malloc_pages(substream,
++					params_buffer_bytes(hw_params));
++}
++
++/* hw_free callback */
++static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++	return snd_pcm_lib_free_pages(substream);
++}
++
++/* prepare callback for playback */
++static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream)
++{
++	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++	struct aw2 *chip = pcm_device->chip;
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	unsigned long period_size, buffer_size;
++
++	mutex_lock(&chip->mtx);
++
++	period_size = snd_pcm_lib_period_bytes(substream);
++	buffer_size = snd_pcm_lib_buffer_bytes(substream);
++
++	snd_aw2_saa7146_pcm_init_playback(&chip->saa7146,
++					  pcm_device->stream_number,
++					  runtime->dma_addr, period_size,
++					  buffer_size);
++
++	/* Define Interrupt callback */
++	snd_aw2_saa7146_define_it_playback_callback(pcm_device->stream_number,
++						    (snd_aw2_saa7146_it_cb)
++						    snd_pcm_period_elapsed,
++						    (void *)substream);
++
++	mutex_unlock(&chip->mtx);
++
++	return 0;
++}
++
++/* prepare callback for capture */
++static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream)
++{
++	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++	struct aw2 *chip = pcm_device->chip;
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	unsigned long period_size, buffer_size;
++
++	mutex_lock(&chip->mtx);
++
++	period_size = snd_pcm_lib_period_bytes(substream);
++	buffer_size = snd_pcm_lib_buffer_bytes(substream);
++
++	snd_aw2_saa7146_pcm_init_capture(&chip->saa7146,
++					 pcm_device->stream_number,
++					 runtime->dma_addr, period_size,
++					 buffer_size);
++
++	/* Define Interrupt callback */
++	snd_aw2_saa7146_define_it_capture_callback(pcm_device->stream_number,
++						   (snd_aw2_saa7146_it_cb)
++						   snd_pcm_period_elapsed,
++						   (void *)substream);
++
++	mutex_unlock(&chip->mtx);
++
++	return 0;
++}
++
++/* playback trigger callback */
++static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
++					int cmd)
++{
++	int status = 0;
++	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++	struct aw2 *chip = pcm_device->chip;
++	spin_lock(&chip->reg_lock);
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		snd_aw2_saa7146_pcm_trigger_start_playback(&chip->saa7146,
++							   pcm_device->
++							   stream_number);
++		break;
++	case SNDRV_PCM_TRIGGER_STOP:
++		snd_aw2_saa7146_pcm_trigger_stop_playback(&chip->saa7146,
++							  pcm_device->
++							  stream_number);
++		break;
++	default:
++		status = -EINVAL;
++	}
++	spin_unlock(&chip->reg_lock);
++	return status;
++}
++
++/* capture trigger callback */
++static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
++				       int cmd)
++{
++	int status = 0;
++	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++	struct aw2 *chip = pcm_device->chip;
++	spin_lock(&chip->reg_lock);
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		snd_aw2_saa7146_pcm_trigger_start_capture(&chip->saa7146,
++							  pcm_device->
++							  stream_number);
++		break;
++	case SNDRV_PCM_TRIGGER_STOP:
++		snd_aw2_saa7146_pcm_trigger_stop_capture(&chip->saa7146,
++							 pcm_device->
++							 stream_number);
++		break;
++	default:
++		status = -EINVAL;
++	}
++	spin_unlock(&chip->reg_lock);
++	return status;
++}
++
++/* playback pointer callback */
++static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
++						      *substream)
++{
++	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++	struct aw2 *chip = pcm_device->chip;
++	unsigned int current_ptr;
++
++	/* get the current hardware pointer */
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	current_ptr =
++		snd_aw2_saa7146_get_hw_ptr_playback(&chip->saa7146,
++						    pcm_device->stream_number,
++						    runtime->dma_area,
++						    runtime->buffer_size);
++
++	return bytes_to_frames(substream->runtime, current_ptr);
++}
++
++/* capture pointer callback */
++static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
++						     *substream)
++{
++	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++	struct aw2 *chip = pcm_device->chip;
++	unsigned int current_ptr;
++
++	/* get the current hardware pointer */
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	current_ptr =
++		snd_aw2_saa7146_get_hw_ptr_capture(&chip->saa7146,
++						   pcm_device->stream_number,
++						   runtime->dma_area,
++						   runtime->buffer_size);
++
++	return bytes_to_frames(substream->runtime, current_ptr);
++}
++
++/* create a pcm device */
++static int __devinit snd_aw2_new_pcm(struct aw2 *chip)
++{
++	struct snd_pcm *pcm_playback_ana;
++	struct snd_pcm *pcm_playback_num;
++	struct snd_pcm *pcm_capture;
++	struct aw2_pcm_device *pcm_device;
++	int err = 0;
++
++	/* Create new Alsa PCM device */
++
++	err = snd_pcm_new(chip->card, "Audiowerk2 analog playback", 0, 1, 0,
++			  &pcm_playback_ana);
++	if (err < 0) {
++		printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
++		return err;
++	}
++
++	/* Creation ok */
++	pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_ANA];
++
++	/* Set PCM device name */
++	strcpy(pcm_playback_ana->name, "Analog playback");
++	/* Associate private data to PCM device */
++	pcm_playback_ana->private_data = pcm_device;
++	/* set operators of PCM device */
++	snd_pcm_set_ops(pcm_playback_ana, SNDRV_PCM_STREAM_PLAYBACK,
++			&snd_aw2_playback_ops);
++	/* store PCM device */
++	pcm_device->pcm = pcm_playback_ana;
++	/* give base chip pointer to our internal pcm device
++	   structure */
++	pcm_device->chip = chip;
++	/* Give stream number to PCM device */
++	pcm_device->stream_number = NUM_STREAM_PLAYBACK_ANA;
++
++	/* pre-allocation of buffers */
++	/* Preallocate continuous pages. */
++	err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_ana,
++						    SNDRV_DMA_TYPE_DEV,
++						    snd_dma_pci_data
++						    (chip->pci),
++						    64 * 1024, 64 * 1024);
++	if (err)
++		printk(KERN_ERR "aw2: snd_pcm_lib_preallocate_pages_for_all "
++		       "error (0x%X)\n", err);
++
++	err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0,
++			  &pcm_playback_num);
++
++	if (err < 0) {
++		printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
++		return err;
++	}
++	/* Creation ok */
++	pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_DIG];
++
++	/* Set PCM device name */
++	strcpy(pcm_playback_num->name, "Digital playback");
++	/* Associate private data to PCM device */
++	pcm_playback_num->private_data = pcm_device;
++	/* set operators of PCM device */
++	snd_pcm_set_ops(pcm_playback_num, SNDRV_PCM_STREAM_PLAYBACK,
++			&snd_aw2_playback_ops);
++	/* store PCM device */
++	pcm_device->pcm = pcm_playback_num;
++	/* give base chip pointer to our internal pcm device
++	   structure */
++	pcm_device->chip = chip;
++	/* Give stream number to PCM device */
++	pcm_device->stream_number = NUM_STREAM_PLAYBACK_DIG;
++
++	/* pre-allocation of buffers */
++	/* Preallocate continuous pages. */
++	err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_num,
++						    SNDRV_DMA_TYPE_DEV,
++						    snd_dma_pci_data
++						    (chip->pci),
++						    64 * 1024, 64 * 1024);
++	if (err)
++		printk(KERN_ERR
++		       "aw2: snd_pcm_lib_preallocate_pages_for_all error "
++		       "(0x%X)\n", err);
++
++
++
++	err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1,
++			  &pcm_capture);
++
++	if (err < 0) {
++		printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
++		return err;
++	}
++
++	/* Creation ok */
++	pcm_device = &chip->device_capture[NUM_STREAM_CAPTURE_ANA];
++
++	/* Set PCM device name */
++	strcpy(pcm_capture->name, "Capture");
++	/* Associate private data to PCM device */
++	pcm_capture->private_data = pcm_device;
++	/* set operators of PCM device */
++	snd_pcm_set_ops(pcm_capture, SNDRV_PCM_STREAM_CAPTURE,
++			&snd_aw2_capture_ops);
++	/* store PCM device */
++	pcm_device->pcm = pcm_capture;
++	/* give base chip pointer to our internal pcm device
++	   structure */
++	pcm_device->chip = chip;
++	/* Give stream number to PCM device */
++	pcm_device->stream_number = NUM_STREAM_CAPTURE_ANA;
++
++	/* pre-allocation of buffers */
++	/* Preallocate continuous pages. */
++	err = snd_pcm_lib_preallocate_pages_for_all(pcm_capture,
++						    SNDRV_DMA_TYPE_DEV,
++						    snd_dma_pci_data
++						    (chip->pci),
++						    64 * 1024, 64 * 1024);
++	if (err)
++		printk(KERN_ERR
++		       "aw2: snd_pcm_lib_preallocate_pages_for_all error "
++		       "(0x%X)\n", err);
++
++
++	/* Create control */
++	err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip));
++	if (err < 0) {
++		printk(KERN_ERR "aw2: snd_ctl_add error (0x%X)\n", err);
++		return err;
++	}
++
++	return 0;
++}
++
++static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
++					       struct snd_ctl_elem_info *uinfo)
++{
++	static char *texts[2] = {
++		"Analog", "Digital"
++	};
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
++	uinfo->count = 1;
++	uinfo->value.enumerated.items = 2;
++	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) {
++		uinfo->value.enumerated.item =
++		    uinfo->value.enumerated.items - 1;
++	}
++	strcpy(uinfo->value.enumerated.name,
++	       texts[uinfo->value.enumerated.item]);
++	return 0;
++}
++
++static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
++					      struct snd_ctl_elem_value
++					      *ucontrol)
++{
++	struct aw2 *chip = snd_kcontrol_chip(kcontrol);
++	if (snd_aw2_saa7146_is_using_digital_input(&chip->saa7146))
++		ucontrol->value.enumerated.item[0] = CTL_ROUTE_DIGITAL;
++	else
++		ucontrol->value.enumerated.item[0] = CTL_ROUTE_ANALOG;
++	return 0;
++}
++
++static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
++					      struct snd_ctl_elem_value
++					      *ucontrol)
++{
++	struct aw2 *chip = snd_kcontrol_chip(kcontrol);
++	int changed = 0;
++	int is_disgital =
++	    snd_aw2_saa7146_is_using_digital_input(&chip->saa7146);
++
++	if (((ucontrol->value.integer.value[0] == CTL_ROUTE_DIGITAL)
++	     && !is_disgital)
++	    || ((ucontrol->value.integer.value[0] == CTL_ROUTE_ANALOG)
++		&& is_disgital)) {
++		snd_aw2_saa7146_use_digital_input(&chip->saa7146, !is_disgital);
++		changed = 1;
++	}
++	return changed;
++}
+diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
+new file mode 100644
+index 0000000..6a3891a
+--- /dev/null
++++ b/sound/pci/aw2/aw2-saa7146.c
+@@ -0,0 +1,465 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++
++#define AW2_SAA7146_M
++
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++
++#include "saa7146.h"
++#include "aw2-saa7146.h"
++
++#include "aw2-tsl.c"
++
++#define WRITEREG(value, addr) writel((value), chip->base_addr + (addr))
++#define READREG(addr) readl(chip->base_addr + (addr))
++
++static struct snd_aw2_saa7146_cb_param
++ arr_substream_it_playback_cb[NB_STREAM_PLAYBACK];
++static struct snd_aw2_saa7146_cb_param
++ arr_substream_it_capture_cb[NB_STREAM_CAPTURE];
++
++static int snd_aw2_saa7146_get_limit(int size);
++
++/* chip-specific destructor */
++int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
++{
++	/* disable all irqs */
++	WRITEREG(0, IER);
++
++	/* reset saa7146 */
++	WRITEREG((MRST_N << 16), MC1);
++
++	/* Unset base addr */
++	chip->base_addr = NULL;
++
++	return 0;
++}
++
++void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
++			   void __iomem *pci_base_addr)
++{
++	/* set PCI burst/threshold
++
++	   Burst length definition
++	   VALUE    BURST LENGTH
++	   000      1 Dword
++	   001      2 Dwords
++	   010      4 Dwords
++	   011      8 Dwords
++	   100      16 Dwords
++	   101      32 Dwords
++	   110      64 Dwords
++	   111      128 Dwords
++
++	   Threshold definition
++	   VALUE    WRITE MODE              READ MODE
++	   00       1 Dword of valid data   1 empty Dword
++	   01       4 Dwords of valid data  4 empty Dwords
++	   10       8 Dwords of valid data  8 empty Dwords
++	   11       16 Dwords of valid data 16 empty Dwords */
++
++	unsigned int acon2;
++	unsigned int acon1 = 0;
++	int i;
++
++	/* Set base addr */
++	chip->base_addr = pci_base_addr;
++
++	/* disable all irqs */
++	WRITEREG(0, IER);
++
++	/* reset saa7146 */
++	WRITEREG((MRST_N << 16), MC1);
++
++	/* enable audio interface */
++#ifdef __BIG_ENDIAN
++	acon1 |= A1_SWAP;
++	acon1 |= A2_SWAP;
++#endif
++	/* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
++
++	/* At initialization WS1 and WS2 are disbaled (configured as input */
++	acon1 |= 0 * WS1_CTRL;
++	acon1 |= 0 * WS2_CTRL;
++
++	/* WS4 is not used. So it must not restart A2.
++	   This is why it is configured as output (force to low) */
++	acon1 |= 3 * WS4_CTRL;
++
++	/* WS3_CTRL, WS3_SYNC: output TSL2, I2S */
++	acon1 |= 2 * WS3_CTRL;
++
++	/* A1 and A2 are active and asynchronous */
++	acon1 |= 3 * AUDIO_MODE;
++	WRITEREG(acon1, ACON1);
++
++	/* The following comes from original windows driver.
++	   It is needed to have a correct behavior of input and output
++	   simultenously, but I don't know why ! */
++	WRITEREG(3 * (BurstA1_in) + 3 * (ThreshA1_in) +
++		 3 * (BurstA1_out) + 3 * (ThreshA1_out) +
++		 3 * (BurstA2_out) + 3 * (ThreshA2_out), PCI_BT_A);
++
++	/* enable audio port pins */
++	WRITEREG((EAP << 16) | EAP, MC1);
++
++	/* enable I2C */
++	WRITEREG((EI2C << 16) | EI2C, MC1);
++	/* enable interrupts */
++	WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
++
++	/* audio configuration */
++	acon2 = A2_CLKSRC | BCLK1_OEN;
++	WRITEREG(acon2, ACON2);
++
++	/* By default use analog input */
++	snd_aw2_saa7146_use_digital_input(chip, 0);
++
++	/* TSL setup */
++	for (i = 0; i < 8; ++i) {
++		WRITEREG(tsl1[i], TSL1 + (i * 4));
++		WRITEREG(tsl2[i], TSL2 + (i * 4));
++	}
++
++}
++
++void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
++				       int stream_number,
++				       unsigned long dma_addr,
++				       unsigned long period_size,
++				       unsigned long buffer_size)
++{
++	unsigned long dw_page, dw_limit;
++
++	/* Configure DMA for substream
++	   Configuration informations: ALSA has allocated continuous memory
++	   pages. So we don't need to use MMU of saa7146.
++	 */
++
++	/* No MMU -> nothing to do with PageA1, we only configure the limit of
++	   PageAx_out register */
++	/* Disable MMU */
++	dw_page = (0L << 11);
++
++	/* Configure Limit for DMA access.
++	   The limit register defines an address limit, which generates
++	   an interrupt if passed by the actual PCI address pointer.
++	   '0001' means an interrupt will be generated if the lower
++	   6 bits (64 bytes) of the PCI address are zero. '0010'
++	   defines a limit of 128 bytes, '0011' one of 256 bytes, and
++	   so on up to 1 Mbyte defined by '1111'. This interrupt range
++	   can be calculated as follows:
++	   Range = 2^(5 + Limit) bytes.
++	 */
++	dw_limit = snd_aw2_saa7146_get_limit(period_size);
++	dw_page |= (dw_limit << 4);
++
++	if (stream_number == 0) {
++		WRITEREG(dw_page, PageA2_out);
++
++		/* Base address for DMA transfert. */
++		/* This address has been reserved by ALSA. */
++		/* This is a physical address */
++		WRITEREG(dma_addr, BaseA2_out);
++
++		/* Define upper limit for DMA access */
++		WRITEREG(dma_addr + buffer_size, ProtA2_out);
++
++	} else if (stream_number == 1) {
++		WRITEREG(dw_page, PageA1_out);
++
++		/* Base address for DMA transfert. */
++		/* This address has been reserved by ALSA. */
++		/* This is a physical address */
++		WRITEREG(dma_addr, BaseA1_out);
++
++		/* Define upper limit for DMA access */
++		WRITEREG(dma_addr + buffer_size, ProtA1_out);
++	} else {
++		printk(KERN_ERR
++		       "aw2: snd_aw2_saa7146_pcm_init_playback: "
++		       "Substream number is not 0 or 1 -> not managed\n");
++	}
++}
++
++void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
++				      int stream_number, unsigned long dma_addr,
++				      unsigned long period_size,
++				      unsigned long buffer_size)
++{
++	unsigned long dw_page, dw_limit;
++
++	/* Configure DMA for substream
++	   Configuration informations: ALSA has allocated continuous memory
++	   pages. So we don't need to use MMU of saa7146.
++	 */
++
++	/* No MMU -> nothing to do with PageA1, we only configure the limit of
++	   PageAx_out register */
++	/* Disable MMU */
++	dw_page = (0L << 11);
++
++	/* Configure Limit for DMA access.
++	   The limit register defines an address limit, which generates
++	   an interrupt if passed by the actual PCI address pointer.
++	   '0001' means an interrupt will be generated if the lower
++	   6 bits (64 bytes) of the PCI address are zero. '0010'
++	   defines a limit of 128 bytes, '0011' one of 256 bytes, and
++	   so on up to 1 Mbyte defined by '1111'. This interrupt range
++	   can be calculated as follows:
++	   Range = 2^(5 + Limit) bytes.
++	 */
++	dw_limit = snd_aw2_saa7146_get_limit(period_size);
++	dw_page |= (dw_limit << 4);
++
++	if (stream_number == 0) {
++		WRITEREG(dw_page, PageA1_in);
++
++		/* Base address for DMA transfert. */
++		/* This address has been reserved by ALSA. */
++		/* This is a physical address */
++		WRITEREG(dma_addr, BaseA1_in);
++
++		/* Define upper limit for DMA access  */
++		WRITEREG(dma_addr + buffer_size, ProtA1_in);
++	} else {
++		printk(KERN_ERR
++		       "aw2: snd_aw2_saa7146_pcm_init_capture: "
++		       "Substream number is not 0 -> not managed\n");
++	}
++}
++
++void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
++						 snd_aw2_saa7146_it_cb
++						 p_it_callback,
++						 void *p_callback_param)
++{
++	if (stream_number < NB_STREAM_PLAYBACK) {
++		arr_substream_it_playback_cb[stream_number].p_it_callback =
++		    (snd_aw2_saa7146_it_cb) p_it_callback;
++		arr_substream_it_playback_cb[stream_number].p_callback_param =
++		    (void *)p_callback_param;
++	}
++}
++
++void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,
++						snd_aw2_saa7146_it_cb
++						p_it_callback,
++						void *p_callback_param)
++{
++	if (stream_number < NB_STREAM_CAPTURE) {
++		arr_substream_it_capture_cb[stream_number].p_it_callback =
++		    (snd_aw2_saa7146_it_cb) p_it_callback;
++		arr_substream_it_capture_cb[stream_number].p_callback_param =
++		    (void *)p_callback_param;
++	}
++}
++
++void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 *chip,
++						int stream_number)
++{
++	unsigned int acon1 = 0;
++	/* In aw8 driver, dma transfert is always active. It is
++	   started and stopped in a larger "space" */
++	acon1 = READREG(ACON1);
++	if (stream_number == 0) {
++		WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
++
++		/* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
++		acon1 |= 2 * WS2_CTRL;
++		WRITEREG(acon1, ACON1);
++
++	} else if (stream_number == 1) {
++		WRITEREG((TR_E_A1_OUT << 16) | TR_E_A1_OUT, MC1);
++
++		/* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
++		acon1 |= 1 * WS1_CTRL;
++		WRITEREG(acon1, ACON1);
++	}
++}
++
++void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 *chip,
++					       int stream_number)
++{
++	unsigned int acon1 = 0;
++	acon1 = READREG(ACON1);
++	if (stream_number == 0) {
++		/* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
++		acon1 &= ~(3 * WS2_CTRL);
++		WRITEREG(acon1, ACON1);
++
++		WRITEREG((TR_E_A2_OUT << 16), MC1);
++	} else if (stream_number == 1) {
++		/* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
++		acon1 &= ~(3 * WS1_CTRL);
++		WRITEREG(acon1, ACON1);
++
++		WRITEREG((TR_E_A1_OUT << 16), MC1);
++	}
++}
++
++void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 *chip,
++					       int stream_number)
++{
++	/* In aw8 driver, dma transfert is always active. It is
++	   started and stopped in a larger "space" */
++	if (stream_number == 0)
++		WRITEREG((TR_E_A1_IN << 16) | TR_E_A1_IN, MC1);
++}
++
++void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip,
++					      int stream_number)
++{
++	if (stream_number == 0)
++		WRITEREG((TR_E_A1_IN << 16), MC1);
++}
++
++irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id)
++{
++	unsigned int isr;
++	unsigned int iicsta;
++	struct snd_aw2_saa7146 *chip = dev_id;
++
++	isr = READREG(ISR);
++	if (!isr)
++		return IRQ_NONE;
++
++	WRITEREG(isr, ISR);
++
++	if (isr & (IIC_S | IIC_E)) {
++		iicsta = READREG(IICSTA);
++		WRITEREG(0x100, IICSTA);
++	}
++
++	if (isr & A1_out) {
++		if (arr_substream_it_playback_cb[1].p_it_callback != NULL) {
++			arr_substream_it_playback_cb[1].
++			    p_it_callback(arr_substream_it_playback_cb[1].
++					  p_callback_param);
++		}
++	}
++	if (isr & A2_out) {
++		if (arr_substream_it_playback_cb[0].p_it_callback != NULL) {
++			arr_substream_it_playback_cb[0].
++			    p_it_callback(arr_substream_it_playback_cb[0].
++					  p_callback_param);
++		}
++
++	}
++	if (isr & A1_in) {
++		if (arr_substream_it_capture_cb[0].p_it_callback != NULL) {
++			arr_substream_it_capture_cb[0].
++			    p_it_callback(arr_substream_it_capture_cb[0].
++					  p_callback_param);
++		}
++	}
++	return IRQ_HANDLED;
++}
++
++unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 *chip,
++						 int stream_number,
++						 unsigned char *start_addr,
++						 unsigned int buffer_size)
++{
++	long pci_adp = 0;
++	size_t ptr = 0;
++
++	if (stream_number == 0) {
++		pci_adp = READREG(PCI_ADP3);
++		ptr = pci_adp - (long)start_addr;
++
++		if (ptr == buffer_size)
++			ptr = 0;
++	}
++	if (stream_number == 1) {
++		pci_adp = READREG(PCI_ADP1);
++		ptr = pci_adp - (size_t) start_addr;
++
++		if (ptr == buffer_size)
++			ptr = 0;
++	}
++	return ptr;
++}
++
++unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 *chip,
++						int stream_number,
++						unsigned char *start_addr,
++						unsigned int buffer_size)
++{
++	size_t pci_adp = 0;
++	size_t ptr = 0;
++	if (stream_number == 0) {
++		pci_adp = READREG(PCI_ADP2);
++		ptr = pci_adp - (size_t) start_addr;
++
++		if (ptr == buffer_size)
++			ptr = 0;
++	}
++	return ptr;
++}
++
++void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
++				       int use_digital)
++{
++	/* FIXME: switch between analog and digital input does not always work.
++	   It can produce a kind of white noise. It seams that received data
++	   are inverted sometime (endian inversion). Why ? I don't know, maybe
++	   a problem of synchronization... However for the time being I have
++	   not found the problem. Workaround: switch again (and again) between
++	   digital and analog input until it works. */
++	if (use_digital)
++		WRITEREG(0x40, GPIO_CTRL);
++	else
++		WRITEREG(0x50, GPIO_CTRL);
++}
++
++int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 *chip)
++{
++	unsigned int reg_val = READREG(GPIO_CTRL);
++	if ((reg_val & 0xFF) == 0x40)
++		return 1;
++	else
++		return 0;
++}
++
++
++static int snd_aw2_saa7146_get_limit(int size)
++{
++	int limitsize = 32;
++	int limit = 0;
++	while (limitsize < size) {
++		limitsize *= 2;
++		limit++;
++	}
++	return limit;
++}
+diff --git a/sound/pci/aw2/aw2-saa7146.h b/sound/pci/aw2/aw2-saa7146.h
+new file mode 100644
+index 0000000..5b35e35
+--- /dev/null
++++ b/sound/pci/aw2/aw2-saa7146.h
+@@ -0,0 +1,105 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++
++#ifndef AW2_SAA7146_H
++#define AW2_SAA7146_H
++
++#define NB_STREAM_PLAYBACK 2
++#define NB_STREAM_CAPTURE 1
++
++#define NUM_STREAM_PLAYBACK_ANA 0
++#define NUM_STREAM_PLAYBACK_DIG 1
++
++#define NUM_STREAM_CAPTURE_ANA 0
++
++typedef void (*snd_aw2_saa7146_it_cb) (void *);
++
++struct snd_aw2_saa7146_cb_param {
++	snd_aw2_saa7146_it_cb p_it_callback;
++	void *p_callback_param;
++};
++
++/* definition of the chip-specific record */
++
++struct snd_aw2_saa7146 {
++	void __iomem *base_addr;
++};
++
++extern void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
++				  void __iomem *pci_base_addr);
++extern int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip);
++
++extern void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
++					      int stream_number,
++					      unsigned long dma_addr,
++					      unsigned long period_size,
++					      unsigned long buffer_size);
++extern void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
++					     int stream_number,
++					     unsigned long dma_addr,
++					     unsigned long period_size,
++					     unsigned long buffer_size);
++extern void snd_aw2_saa7146_define_it_playback_callback(unsigned int
++							stream_number,
++							snd_aw2_saa7146_it_cb
++							p_it_callback,
++							void *p_callback_param);
++extern void snd_aw2_saa7146_define_it_capture_callback(unsigned int
++						       stream_number,
++						       snd_aw2_saa7146_it_cb
++						       p_it_callback,
++						       void *p_callback_param);
++extern void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146
++						      *chip, int stream_number);
++extern void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146
++						     *chip, int stream_number);
++
++extern void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146
++						       *chip,
++						       int stream_number);
++extern void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146
++						      *chip, int stream_number);
++
++extern irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id);
++extern unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146
++							*chip,
++							int stream_number,
++							unsigned char
++							*start_addr,
++							unsigned int
++							buffer_size);
++extern unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146
++						       *chip,
++						       int stream_number,
++						       unsigned char
++						       *start_addr,
++						       unsigned int
++						       buffer_size);
++
++extern void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
++					      int use_digital);
++
++extern int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146
++						  *chip);
++
++#endif
+diff --git a/sound/pci/aw2/aw2-tsl.c b/sound/pci/aw2/aw2-tsl.c
+new file mode 100644
+index 0000000..459b031
+--- /dev/null
++++ b/sound/pci/aw2/aw2-tsl.c
+@@ -0,0 +1,110 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ * Copyright 1998 Emagic Soft- und Hardware GmbH
++ * Copyright 2002 Martijn Sipkema
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++
++#define TSL_WS0		(1UL << 31)
++#define	TSL_WS1		(1UL << 30)
++#define	TSL_WS2		(1UL << 29)
++#define TSL_WS3		(1UL << 28)
++#define TSL_WS4		(1UL << 27)
++#define	TSL_DIS_A1	(1UL << 24)
++#define TSL_SDW_A1	(1UL << 23)
++#define TSL_SIB_A1	(1UL << 22)
++#define TSL_SF_A1	(1UL << 21)
++#define	TSL_LF_A1	(1UL << 20)
++#define TSL_BSEL_A1	(1UL << 17)
++#define TSL_DOD_A1	(1UL << 15)
++#define TSL_LOW_A1	(1UL << 14)
++#define TSL_DIS_A2	(1UL << 11)
++#define TSL_SDW_A2	(1UL << 10)
++#define TSL_SIB_A2	(1UL << 9)
++#define TSL_SF_A2	(1UL << 8)
++#define TSL_LF_A2	(1UL << 7)
++#define TSL_BSEL_A2	(1UL << 4)
++#define TSL_DOD_A2	(1UL << 2)
++#define TSL_LOW_A2	(1UL << 1)
++#define TSL_EOS		(1UL << 0)
++
++    /* Audiowerk8 hardware setup: */
++    /*      WS0, SD4, TSL1  - Analog/ digital in */
++    /*      WS1, SD0, TSL1  - Analog out #1, digital out */
++    /*      WS2, SD2, TSL1  - Analog out #2 */
++    /*      WS3, SD1, TSL2  - Analog out #3 */
++    /*      WS4, SD3, TSL2  - Analog out #4 */
++
++    /* Audiowerk8 timing: */
++    /*      Timeslot:     | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... */
++
++    /*      A1_INPUT: */
++    /*      SD4:          <_ADC-L_>-------<_ADC-R_>-------< */
++    /*      WS0:          _______________/---------------\_ */
++
++    /*      A1_OUTPUT: */
++    /*      SD0:          <_1-L___>-------<_1-R___>-------< */
++    /*      WS1:          _______________/---------------\_ */
++    /*      SD2:          >-------<_2-L___>-------<_2-R___> */
++    /*      WS2:          -------\_______________/--------- */
++
++    /*      A2_OUTPUT: */
++    /*      SD1:          <_3-L___>-------<_3-R___>-------< */
++    /*      WS3:          _______________/---------------\_ */
++    /*      SD3:          >-------<_4-L___>-------<_4-R___> */
++    /*      WS4:          -------\_______________/--------- */
++
++static int tsl1[8] = {
++	1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
++	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1,
++
++	1 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
++	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
++
++	0 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
++	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
++
++	0 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
++	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
++
++	1 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
++	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
++
++	1 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 |
++	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
++
++	0 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
++	0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
++
++	0 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 | 0 * TSL_DIS_A1 |
++	0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0 | TSL_SF_A1 | TSL_EOS,
++};
++
++static int tsl2[8] = {
++	0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_LF_A2,
++	0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
++	0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
++	0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
++	0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
++	0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
++	0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
++	0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2 | TSL_EOS
++};
+diff --git a/sound/pci/aw2/saa7146.h b/sound/pci/aw2/saa7146.h
+new file mode 100644
+index 0000000..ce0ab5f
+--- /dev/null
++++ b/sound/pci/aw2/saa7146.h
+@@ -0,0 +1,168 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++
++/* SAA7146 registers */
++#define PCI_BT_A	0x4C
++#define IICTFR		0x8C
++#define IICSTA		0x90
++#define BaseA1_in	0x94
++#define ProtA1_in	0x98
++#define PageA1_in	0x9C
++#define BaseA1_out	0xA0
++#define ProtA1_out	0xA4
++#define PageA1_out	0xA8
++#define BaseA2_in	0xAC
++#define ProtA2_in	0xB0
++#define PageA2_in	0xB4
++#define BaseA2_out	0xB8
++#define ProtA2_out	0xBC
++#define PageA2_out	0xC0
++#define IER		0xDC
++#define GPIO_CTRL	0xE0
++#define ACON1		0xF4
++#define ACON2		0xF8
++#define MC1		0xFC
++#define MC2		0x100
++#define ISR		0x10C
++#define PSR		0x110
++#define SSR		0x114
++#define PCI_ADP1	0x12C
++#define PCI_ADP2	0x130
++#define PCI_ADP3	0x134
++#define PCI_ADP4	0x138
++#define LEVEL_REP	0x140
++#define FB_BUFFER1	0x144
++#define FB_BUFFER2	0x148
++#define TSL1		0x180
++#define TSL2		0x1C0
++
++#define ME	(1UL << 11)
++#define LIMIT	(1UL << 4)
++#define PV	(1UL << 3)
++
++/* PSR/ISR/IER */
++#define PPEF		(1UL << 31)
++#define PABO		(1UL << 30)
++#define IIC_S		(1UL << 17)
++#define IIC_E		(1UL << 16)
++#define A2_in		(1UL << 15)
++#define A2_out		(1UL << 14)
++#define A1_in		(1UL << 13)
++#define A1_out		(1UL << 12)
++#define AFOU		(1UL << 11)
++#define PIN3		(1UL << 6)
++#define PIN2		(1UL << 5)
++#define PIN1		(1UL << 4)
++#define PIN0		(1UL << 3)
++#define ECS		(1UL << 2)
++#define EC3S		(1UL << 1)
++#define EC0S		(1UL << 0)
++
++/* SSR */
++#define PRQ		(1UL << 31)
++#define PMA		(1UL << 30)
++#define IIC_EA		(1UL << 21)
++#define IIC_EW		(1UL << 20)
++#define IIC_ER		(1UL << 19)
++#define IIC_EL		(1UL << 18)
++#define IIC_EF		(1UL << 17)
++#define AF2_in		(1UL << 10)
++#define AF2_out		(1UL << 9)
++#define AF1_in		(1UL << 8)
++#define AF1_out		(1UL << 7)
++#define EC5S		(1UL << 3)
++#define EC4S		(1UL << 2)
++#define EC2S		(1UL << 1)
++#define EC1S		(1UL << 0)
++
++/* PCI_BT_A */
++#define BurstA1_in	(1UL << 26)
++#define ThreshA1_in	(1UL << 24)
++#define BurstA1_out	(1UL << 18)
++#define ThreshA1_out	(1UL << 16)
++#define BurstA2_in	(1UL << 10)
++#define ThreshA2_in	(1UL << 8)
++#define BurstA2_out	(1UL << 2)
++#define ThreshA2_out	(1UL << 0)
++
++/* MC1 */
++#define MRST_N		(1UL << 15)
++#define EAP		(1UL << 9)
++#define EI2C		(1UL << 8)
++#define TR_E_A2_OUT	(1UL << 3)
++#define TR_E_A2_IN	(1UL << 2)
++#define TR_E_A1_OUT	(1UL << 1)
++#define TR_E_A1_IN	(1UL << 0)
++
++/* MC2 */
++#define UPLD_IIC	(1UL << 0)
++
++/* ACON1 */
++#define AUDIO_MODE	(1UL << 29)
++#define MAXLEVEL	(1UL << 22)
++#define A1_SWAP		(1UL << 21)
++#define A2_SWAP		(1UL << 20)
++#define WS0_CTRL	(1UL << 18)
++#define WS0_SYNC	(1UL << 16)
++#define WS1_CTRL	(1UL << 14)
++#define WS1_SYNC	(1UL << 12)
++#define WS2_CTRL	(1UL << 10)
++#define WS2_SYNC	(1UL << 8)
++#define WS3_CTRL	(1UL << 6)
++#define WS3_SYNC	(1UL << 4)
++#define WS4_CTRL	(1UL << 2)
++#define WS4_SYNC	(1UL << 0)
++
++/* ACON2 */
++#define A1_CLKSRC	(1UL << 27)
++#define A2_CLKSRC	(1UL << 22)
++#define INVERT_BCLK1	(1UL << 21)
++#define INVERT_BCLK2	(1UL << 20)
++#define BCLK1_OEN	(1UL << 19)
++#define BCLK2_OEN	(1UL << 18)
++
++/* IICSTA */
++#define IICCC		(1UL << 8)
++#define ABORT		(1UL << 7)
++#define SPERR		(1UL << 6)
++#define APERR		(1UL << 5)
++#define DTERR		(1UL << 4)
++#define DRERR		(1UL << 3)
++#define AL		(1UL << 2)
++#define ERR		(1UL << 1)
++#define BUSY		(1UL << 0)
++
++/* IICTFR */
++#define BYTE2		(1UL << 24)
++#define BYTE1		(1UL << 16)
++#define BYTE0		(1UL << 8)
++#define ATRR2		(1UL << 6)
++#define ATRR1		(1UL << 4)
++#define ATRR0		(1UL << 2)
++#define ERR		(1UL << 1)
++#define BUSY		(1UL << 0)
++
++#define START	3
++#define CONT	2
++#define STOP	1
++#define NOP	0
+diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
+index 4e71a55..5f63af6 100644
+--- a/sound/pci/azt3328.c
++++ b/sound/pci/azt3328.c
+@@ -157,8 +157,8 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
+ 
+ #if DEBUG_CALLS
+ #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args)
+-#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
+-#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
++#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
++#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
+ #else
+ #define snd_azf3328_dbgcalls(format, args...)
+ #define snd_azf3328_dbgcallenter()
+@@ -1514,7 +1514,8 @@ snd_azf3328_free(struct snd_azf3328 *chip)
+ 	/* well, at least we know how to disable the timer IRQ */
+ 	snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00);
+ 
+-        synchronize_irq(chip->irq);
++	if (chip->irq >= 0)
++        	synchronize_irq(chip->irq);
+ __end_hw:
+ 	snd_azf3328_free_joystick(chip);
+         if (chip->irq >= 0)
+diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
+index 176e0f0..ecbe79b 100644
+--- a/sound/pci/ca0106/ca0106_main.c
++++ b/sound/pci/ca0106/ca0106_main.c
+@@ -435,22 +435,22 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
+ static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
+ {
+ 	unsigned long flags;
+-	unsigned int enable;
+-  
++	unsigned int intr_enable;
++
+ 	spin_lock_irqsave(&emu->emu_lock, flags);
+-	enable = inl(emu->port + INTE) | intrenb;
+-	outl(enable, emu->port + INTE);
++	intr_enable = inl(emu->port + INTE) | intrenb;
++	outl(intr_enable, emu->port + INTE);
+ 	spin_unlock_irqrestore(&emu->emu_lock, flags);
+ }
+ 
+ static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
+ {
+ 	unsigned long flags;
+-	unsigned int enable;
+-  
++	unsigned int intr_enable;
++
+ 	spin_lock_irqsave(&emu->emu_lock, flags);
+-	enable = inl(emu->port + INTE) & ~intrenb;
+-	outl(enable, emu->port + INTE);
++	intr_enable = inl(emu->port + INTE) & ~intrenb;
++	outl(intr_enable, emu->port + INTE);
+ 	spin_unlock_irqrestore(&emu->emu_lock, flags);
+ }
+ 
+@@ -1114,6 +1114,8 @@ static int snd_ca0106_free(struct snd_ca0106 *chip)
+ 		 * So we can fix: snd-malloc: Memory leak?  pages not freed = 8
+ 		 */
+ 	}
++	if (chip->irq >= 0)
++		free_irq(chip->irq, chip);
+ 	// release the data
+ #if 1
+ 	if (chip->buffer.area)
+@@ -1123,9 +1125,6 @@ static int snd_ca0106_free(struct snd_ca0106 *chip)
+ 	// release the i/o port
+ 	release_and_free_resource(chip->res_port);
+ 
+-	// release the irq
+-	if (chip->irq >= 0)
+-		free_irq(chip->irq, chip);
+ 	pci_disable_device(chip->pci);
+ 	kfree(chip);
+ 	return 0;
+diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
+index af73686..3025ed1 100644
+--- a/sound/pci/ca0106/ca0106_mixer.c
++++ b/sound/pci/ca0106/ca0106_mixer.c
+@@ -650,19 +650,55 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch
+ 
+ #define ADD_CTLS(emu, ctls)						\
+ 	do {								\
+-		int i, err;						\
++		int i, _err;						\
+ 		for (i = 0; i < ARRAY_SIZE(ctls); i++) {		\
+-			err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
+-			if (err < 0)					\
+-				return err;				\
++			_err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
++			if (_err < 0)					\
++				return _err;				\
+ 		}							\
+ 	} while (0)
+ 
++static __devinitdata
++DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 50, 1);
++
++static char *slave_vols[] __devinitdata = {
++	"Analog Front Playback Volume",
++        "Analog Rear Playback Volume",
++	"Analog Center/LFE Playback Volume",
++        "Analog Side Playback Volume",
++        "IEC958 Front Playback Volume",
++	"IEC958 Rear Playback Volume",
++	"IEC958 Center/LFE Playback Volume",
++	"IEC958 Unknown Playback Volume",
++        "CAPTURE feedback Playback Volume",
++	NULL
++};
++
++static char *slave_sws[] __devinitdata = {
++	"Analog Front Playback Switch",
++	"Analog Rear Playback Switch",
++	"Analog Center/LFE Playback Switch",
++	"Analog Side Playback Switch",
++	"IEC958 Playback Switch",
++	NULL
++};
++
++static void __devinit add_slaves(struct snd_card *card,
++				 struct snd_kcontrol *master, char **list)
++{
++	for (; *list; list++) {
++		struct snd_kcontrol *slave = ctl_find(card, *list);
++		if (slave)
++			snd_ctl_add_slave(master, slave);
++	}
++}
++
+ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
+ {
+ 	int err;
+         struct snd_card *card = emu->card;
+ 	char **c;
++	struct snd_kcontrol *vmaster;
+ 	static char *ca0106_remove_ctls[] = {
+ 		"Master Mono Playback Switch",
+ 		"Master Mono Playback Volume",
+@@ -719,6 +755,21 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
+ 	}
+ 	if (emu->details->spi_dac == 1)
+ 		ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
++
++	/* Create virtual master controls */
++	vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
++					      snd_ca0106_master_db_scale);
++	if (!vmaster)
++		return -ENOMEM;
++	add_slaves(card, vmaster, slave_vols);
++
++	if (emu->details->spi_dac == 1) {
++		vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
++						      NULL);
++		if (!vmaster)
++			return -ENOMEM;
++		add_slaves(card, vmaster, slave_sws);
++	}
+         return 0;
+ }
+ 
+diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
+index 135f308..9971b5b 100644
+--- a/sound/pci/cmipci.c
++++ b/sound/pci/cmipci.c
+@@ -2744,12 +2744,13 @@ static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_devic
+ 	}
+ 
+ 	for (idx = 0; idx < CM_SAVED_MIXERS; idx++) {
+-		struct snd_ctl_elem_id id;
++		struct snd_ctl_elem_id elem_id;
+ 		struct snd_kcontrol *ctl;
+-		memset(&id, 0, sizeof(id));
+-		id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+-		strcpy(id.name, cm_saved_mixer[idx].name);
+-		if ((ctl = snd_ctl_find_id(cm->card, &id)) != NULL)
++		memset(&elem_id, 0, sizeof(elem_id));
++		elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++		strcpy(elem_id.name, cm_saved_mixer[idx].name);
++		ctl = snd_ctl_find_id(cm->card, &elem_id);
++		if (ctl)
+ 			cm->mixer_res_ctl[idx] = ctl;
+ 	}
+ 
+@@ -2932,8 +2933,6 @@ static int snd_cmipci_free(struct cmipci *cm)
+ 		/* reset mixer */
+ 		snd_cmipci_mixer_write(cm, 0, 0);
+ 
+-		synchronize_irq(cm->irq);
+-
+ 		free_irq(cm->irq, cm);
+ 	}
+ 
+diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
+index 87ddffc..e214e56 100644
+--- a/sound/pci/cs46xx/cs46xx_lib.c
++++ b/sound/pci/cs46xx/cs46xx_lib.c
+@@ -2772,6 +2772,9 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
+ 	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+ 
++	if (chip->active_ctrl)
++		chip->active_ctrl(chip, -chip->amplifier);
++
+ 	for (idx = 0; idx < 5; idx++) {
+ 		struct snd_cs46xx_region *region = &chip->region.idx[idx];
+ 		if (region->remap_addr)
+@@ -2779,9 +2782,6 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
+ 		release_and_free_resource(region->resource);
+ 	}
+ 
+-	if (chip->active_ctrl)
+-		chip->active_ctrl(chip, -chip->amplifier);
+-	
+ #ifdef CONFIG_SND_CS46XX_NEW_DSP
+ 	if (chip->dsp_spos_instance) {
+ 		cs46xx_dsp_spos_destroy(chip);
+diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
+index 90ec090..e16dc92 100644
+--- a/sound/pci/echoaudio/echoaudio.c
++++ b/sound/pci/echoaudio/echoaudio.c
+@@ -1852,15 +1852,16 @@ static irqreturn_t snd_echo_interrupt(int irq, void *dev_id)
+ static int snd_echo_free(struct echoaudio *chip)
+ {
+ 	DE_INIT(("Stop DSP...\n"));
+-	if (chip->comm_page) {
++	if (chip->comm_page)
+ 		rest_in_peace(chip);
+-		snd_dma_free_pages(&chip->commpage_dma_buf);
+-	}
+ 	DE_INIT(("Stopped.\n"));
+ 
+ 	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+ 
++	if (chip->comm_page)
++		snd_dma_free_pages(&chip->commpage_dma_buf);
++
+ 	if (chip->dsp_registers)
+ 		iounmap(chip->dsp_registers);
+ 
+diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
+index 9a9b977..abde5b9 100644
+--- a/sound/pci/emu10k1/emu10k1_main.c
++++ b/sound/pci/emu10k1/emu10k1_main.c
+@@ -1249,11 +1249,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
+ 	if (emu->port) {	/* avoid access to already used hardware */
+ 	       	snd_emu10k1_fx8010_tram_setup(emu, 0);
+ 		snd_emu10k1_done(emu);
+-		/* remove reserved page */
+-		if (emu->reserved_page) {
+-			snd_emu10k1_synth_free(emu, (struct snd_util_memblk *)emu->reserved_page);
+-			emu->reserved_page = NULL;
+-		}
+ 		snd_emu10k1_free_efx(emu);
+        	}
+ 	if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
+@@ -1262,6 +1257,14 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
+ 	}
+ 	if (emu->emu1010.firmware_thread)
+ 		kthread_stop(emu->emu1010.firmware_thread);
++	if (emu->irq >= 0)
++		free_irq(emu->irq, emu);
++	/* remove reserved page */
++	if (emu->reserved_page) {
++		snd_emu10k1_synth_free(emu,
++			(struct snd_util_memblk *)emu->reserved_page);
++		emu->reserved_page = NULL;
++	}
+ 	if (emu->memhdr)
+ 		snd_util_memhdr_free(emu->memhdr);
+ 	if (emu->silent_page.area)
+@@ -1273,8 +1276,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
+ #ifdef CONFIG_PM
+ 	free_pm_buffer(emu);
+ #endif
+-	if (emu->irq >= 0)
+-		free_irq(emu->irq, emu);
+ 	if (emu->port)
+ 		pci_release_regions(emu->pci);
+ 	if (emu->card_capabilities->ca0151_chip) /* P16V */	
+diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
+index 5512abd..491a4a5 100644
+--- a/sound/pci/emu10k1/emu10k1x.c
++++ b/sound/pci/emu10k1/emu10k1x.c
+@@ -327,22 +327,22 @@ static void snd_emu10k1x_ptr_write(struct emu10k1x *emu,
+ static void snd_emu10k1x_intr_enable(struct emu10k1x *emu, unsigned int intrenb)
+ {
+ 	unsigned long flags;
+-	unsigned int enable;
+-  
++	unsigned int intr_enable;
++
+ 	spin_lock_irqsave(&emu->emu_lock, flags);
+-	enable = inl(emu->port + INTE) | intrenb;
+-	outl(enable, emu->port + INTE);
++	intr_enable = inl(emu->port + INTE) | intrenb;
++	outl(intr_enable, emu->port + INTE);
+ 	spin_unlock_irqrestore(&emu->emu_lock, flags);
+ }
+ 
+ static void snd_emu10k1x_intr_disable(struct emu10k1x *emu, unsigned int intrenb)
+ {
+ 	unsigned long flags;
+-	unsigned int enable;
+-  
++	unsigned int intr_enable;
++
+ 	spin_lock_irqsave(&emu->emu_lock, flags);
+-	enable = inl(emu->port + INTE) & ~intrenb;
+-	outl(enable, emu->port + INTE);
++	intr_enable = inl(emu->port + INTE) & ~intrenb;
++	outl(intr_enable, emu->port + INTE);
+ 	spin_unlock_irqrestore(&emu->emu_lock, flags);
+ }
+ 
+@@ -754,13 +754,13 @@ static int snd_emu10k1x_free(struct emu10k1x *chip)
+ 	// disable audio
+ 	outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
+ 
+-	// release the i/o port
+-	release_and_free_resource(chip->res_port);
+-
+-	// release the irq
++	/* release the irq */
+ 	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+ 
++	// release the i/o port
++	release_and_free_resource(chip->res_port);
++
+ 	// release the DMA
+ 	if (chip->dma_buffer.area) {
+ 		snd_dma_free_pages(&chip->dma_buffer);
+@@ -795,9 +795,9 @@ static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id)
+ 
+ 	// capture interrupt
+ 	if (status & (IPR_CAP_0_LOOP | IPR_CAP_0_HALF_LOOP)) {
+-		struct emu10k1x_voice *pvoice = &chip->capture_voice;
+-		if (pvoice->use)
+-			snd_emu10k1x_pcm_interrupt(chip, pvoice);
++		struct emu10k1x_voice *cap_voice = &chip->capture_voice;
++		if (cap_voice->use)
++			snd_emu10k1x_pcm_interrupt(chip, cap_voice);
+ 		else
+ 			snd_emu10k1x_intr_disable(chip, 
+ 						  INTE_CAP_0_LOOP |
+diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
+index f3caa3f..216f974 100644
+--- a/sound/pci/emu10k1/emuproc.c
++++ b/sound/pci/emu10k1/emuproc.c
+@@ -412,7 +412,7 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
+ 				     struct snd_info_buffer *buffer)
+ {
+ 	struct snd_emu10k1 *emu = entry->private_data;
+-	int value;
++	u32 value;
+ 	unsigned long flags;
+ 	int i;
+ 	snd_iprintf(buffer, "EMU1010 Registers:\n\n");
+diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
+index 72d85a5..fbf1124 100644
+--- a/sound/pci/ens1370.c
++++ b/sound/pci/ens1370.c
+@@ -1635,20 +1635,20 @@ static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
+ 	if (has_spdif > 0 ||
+ 	    (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) {
+ 		struct snd_kcontrol *kctl;
+-		int i, index = 0;
++		int i, is_spdif = 0;
+ 
+ 		ensoniq->spdif_default = ensoniq->spdif_stream =
+ 			SNDRV_PCM_DEFAULT_CON_SPDIF;
+ 		outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
+ 
+ 		if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
+-			index++;
++			is_spdif++;
+ 
+ 		for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) {
+ 			kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq);
+ 			if (!kctl)
+ 				return -ENOMEM;
+-			kctl->id.index = index;
++			kctl->id.index = is_spdif;
+ 			err = snd_ctl_add(card, kctl);
+ 			if (err < 0)
+ 				return err;
+@@ -1910,7 +1910,8 @@ static int snd_ensoniq_free(struct ensoniq *ensoniq)
+ 	outl(0, ES_REG(ensoniq, CONTROL));	/* switch everything off */
+ 	outl(0, ES_REG(ensoniq, SERIAL));	/* clear serial interface */
+ #endif
+-	synchronize_irq(ensoniq->irq);
++	if (ensoniq->irq >= 0)
++		synchronize_irq(ensoniq->irq);
+ 	pci_set_power_state(ensoniq->pci, 3);
+       __hw_end:
+ #ifdef CHIP1370
+diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
+index 1a314fa..84fac1f 100644
+--- a/sound/pci/es1938.c
++++ b/sound/pci/es1938.c
+@@ -1488,7 +1488,6 @@ static int es1938_suspend(struct pci_dev *pci, pm_message_t state)
+ 
+ 	outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */
+ 	if (chip->irq >= 0) {
+-		synchronize_irq(chip->irq);
+ 		free_irq(chip->irq, chip);
+ 		chip->irq = -1;
+ 	}
+@@ -1578,10 +1577,8 @@ static int snd_es1938_free(struct es1938 *chip)
+ 
+ 	snd_es1938_free_gameport(chip);
+ 
+-	if (chip->irq >= 0) {
+-		synchronize_irq(chip->irq);
++	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+-	}
+ 	pci_release_regions(chip->pci);
+ 	pci_disable_device(chip->pci);
+ 	kfree(chip);
+diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
+index 7d911a1..1bf298d 100644
+--- a/sound/pci/es1968.c
++++ b/sound/pci/es1968.c
+@@ -1827,6 +1827,22 @@ snd_es1968_pcm(struct es1968 *chip, int device)
+ 
+ 	return 0;
+ }
++/*
++ * suppress jitter on some maestros when playing stereo
++ */
++static void snd_es1968_suppress_jitter(struct es1968 *chip, struct esschan *es)
++{
++	unsigned int cp1;
++	unsigned int cp2;
++	unsigned int diff;
++
++	cp1 = __apu_get_register(chip, 0, 5);
++	cp2 = __apu_get_register(chip, 1, 5);
++	diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
++
++	if (diff > 1)
++		__maestro_write(chip, IDR0_DATA_PORT, cp1);
++}
+ 
+ /*
+  * update pointer
+@@ -1948,8 +1964,11 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
+ 		struct esschan *es;
+ 		spin_lock(&chip->substream_lock);
+ 		list_for_each_entry(es, &chip->substream_list, list) {
+-			if (es->running)
++			if (es->running) {
+ 				snd_es1968_update_pcm(chip, es);
++				if (es->fmt & ESS_FMT_STEREO)
++					snd_es1968_suppress_jitter(chip, es);
++			}
+ 		}
+ 		spin_unlock(&chip->substream_lock);
+ 		if (chip->in_measurement) {
+@@ -1972,7 +1991,7 @@ snd_es1968_mixer(struct es1968 *chip)
+ {
+ 	struct snd_ac97_bus *pbus;
+ 	struct snd_ac97_template ac97;
+-	struct snd_ctl_elem_id id;
++	struct snd_ctl_elem_id elem_id;
+ 	int err;
+ 	static struct snd_ac97_bus_ops ops = {
+ 		.write = snd_es1968_ac97_write,
+@@ -1989,14 +2008,14 @@ snd_es1968_mixer(struct es1968 *chip)
+ 		return err;
+ 
+ 	/* attach master switch / volumes for h/w volume control */
+-	memset(&id, 0, sizeof(id));
+-	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+-	strcpy(id.name, "Master Playback Switch");
+-	chip->master_switch = snd_ctl_find_id(chip->card, &id);
+-	memset(&id, 0, sizeof(id));
+-	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+-	strcpy(id.name, "Master Playback Volume");
+-	chip->master_volume = snd_ctl_find_id(chip->card, &id);
++	memset(&elem_id, 0, sizeof(elem_id));
++	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++	strcpy(elem_id.name, "Master Playback Switch");
++	chip->master_switch = snd_ctl_find_id(chip->card, &elem_id);
++	memset(&elem_id, 0, sizeof(elem_id));
++	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++	strcpy(elem_id.name, "Master Playback Volume");
++	chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
+ 
+ 	return 0;
+ }
+@@ -2456,7 +2475,8 @@ static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
+ static int snd_es1968_free(struct es1968 *chip)
+ {
+ 	if (chip->io_port) {
+-		synchronize_irq(chip->irq);
++		if (chip->irq >= 0)
++			synchronize_irq(chip->irq);
+ 		outw(1, chip->io_port + 0x04); /* clear WP interrupts */
+ 		outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
+ 	}
+diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
+index 4c300e6..c129f9e 100644
+--- a/sound/pci/fm801.c
++++ b/sound/pci/fm801.c
+@@ -1285,7 +1285,6 @@ static int wait_for_codec(struct fm801 *chip, unsigned int codec_id,
+ 
+ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
+ {
+-	int id;
+ 	unsigned short cmdw;
+ 
+ 	if (chip->tea575x_tuner & 0x0010)
+@@ -1310,13 +1309,14 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
+ 		} else {
+ 			/* my card has the secondary codec */
+ 			/* at address #3, so the loop is inverted */
+-			for (id = 3; id > 0; id--) {
+-				if (! wait_for_codec(chip, id, AC97_VENDOR_ID1,
++			int i;
++			for (i = 3; i > 0; i--) {
++				if (!wait_for_codec(chip, i, AC97_VENDOR_ID1,
+ 						     msecs_to_jiffies(50))) {
+ 					cmdw = inw(FM801_REG(chip, AC97_DATA));
+ 					if (cmdw != 0xffff && cmdw != 0) {
+ 						chip->secondary = 1;
+-						chip->secondary_addr = id;
++						chip->secondary_addr = i;
+ 						break;
+ 					}
+ 				}
+diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
+index 9e0d8a1..ab0c726 100644
+--- a/sound/pci/hda/Makefile
++++ b/sound/pci/hda/Makefile
+@@ -2,7 +2,7 @@ snd-hda-intel-y := hda_intel.o
+ # since snd-hda-intel is the only driver using hda-codec,
+ # merge it into a single module although it was originally
+ # designed to be individual modules
+-snd-hda-intel-y += hda_codec.o vmaster.o
++snd-hda-intel-y += hda_codec.o
+ snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o
+ snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
+ snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
+diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
+index 37c4139..a6be6e3 100644
+--- a/sound/pci/hda/hda_codec.c
++++ b/sound/pci/hda/hda_codec.c
+@@ -31,6 +31,7 @@
+ #include <sound/initval.h>
+ #include "hda_local.h"
+ #include <sound/hda_hwdep.h>
++#include "hda_patch.h"	/* codec presets */
+ 
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ /* define this option here to hide as static */
+@@ -51,21 +52,50 @@ struct hda_vendor_id {
+ 
+ /* codec vendor labels */
+ static struct hda_vendor_id hda_vendor_ids[] = {
+-	{ 0x10ec, "Realtek" },
++	{ 0x1002, "ATI" },
+ 	{ 0x1057, "Motorola" },
++	{ 0x1095, "Silicon Image" },
++	{ 0x10ec, "Realtek" },
+ 	{ 0x1106, "VIA" },
+ 	{ 0x111d, "IDT" },
++	{ 0x11c1, "LSI" },
+ 	{ 0x11d4, "Analog Devices" },
+ 	{ 0x13f6, "C-Media" },
+ 	{ 0x14f1, "Conexant" },
++	{ 0x17e8, "Chrontel" },
++	{ 0x1854, "LG" },
+ 	{ 0x434d, "C-Media" },
+ 	{ 0x8384, "SigmaTel" },
+ 	{} /* terminator */
+ };
+ 
+-/* codec presets */
+-#include "hda_patch.h"
+-
++static const struct hda_codec_preset *hda_preset_tables[] = {
++#ifdef CONFIG_SND_HDA_CODEC_REALTEK
++	snd_hda_preset_realtek,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_CMEDIA
++	snd_hda_preset_cmedia,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_ANALOG
++	snd_hda_preset_analog,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
++	snd_hda_preset_sigmatel,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_SI3054
++	snd_hda_preset_si3054,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
++	snd_hda_preset_atihdmi,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_CONEXANT
++	snd_hda_preset_conexant,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_VIA
++	snd_hda_preset_via,
++#endif
++	NULL
++};
+ 
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ static void hda_power_work(struct work_struct *work);
+@@ -690,6 +720,19 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+ 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
+ }
+ 
++void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
++{
++	if (!nid)
++		return;
++
++	snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
++	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
++#if 0 /* keep the format */
++	msleep(1);
++	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
++#endif
++}
++
+ /*
+  * amp access functions
+  */
+@@ -1037,16 +1080,24 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
+ }
+ 
+ /* find a mixer control element with the given name */
+-struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
+-					    const char *name)
++static struct snd_kcontrol *
++_snd_hda_find_mixer_ctl(struct hda_codec *codec,
++			const char *name, int idx)
+ {
+ 	struct snd_ctl_elem_id id;
+ 	memset(&id, 0, sizeof(id));
+ 	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++	id.index = idx;
+ 	strcpy(id.name, name);
+ 	return snd_ctl_find_id(codec->bus->card, &id);
+ }
+ 
++struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
++					    const char *name)
++{
++	return _snd_hda_find_mixer_ctl(codec, name, 0);
++}
++
+ /* create a virtual master control and add slaves */
+ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
+ 			unsigned int *tlv, const char **slaves)
+@@ -1481,6 +1532,8 @@ static struct snd_kcontrol_new dig_mixes[] = {
+ 	{ } /* end */
+ };
+ 
++#define SPDIF_MAX_IDX	4	/* 4 instances should be enough to probe */
++
+ /**
+  * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
+  * @codec: the HDA codec
+@@ -1496,9 +1549,20 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
+ 	int err;
+ 	struct snd_kcontrol *kctl;
+ 	struct snd_kcontrol_new *dig_mix;
++	int idx;
+ 
++	for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
++		if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
++					     idx))
++			break;
++	}
++	if (idx >= SPDIF_MAX_IDX) {
++		printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
++		return -EBUSY;
++	}
+ 	for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
+ 		kctl = snd_ctl_new1(dig_mix, codec);
++		kctl->id.index = idx;
+ 		kctl->private_value = nid;
+ 		err = snd_ctl_add(codec->bus->card, kctl);
+ 		if (err < 0)
+@@ -1512,6 +1576,43 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
+ }
+ 
+ /*
++ * SPDIF sharing with analog output
++ */
++static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
++			      struct snd_ctl_elem_value *ucontrol)
++{
++	struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
++	ucontrol->value.integer.value[0] = mout->share_spdif;
++	return 0;
++}
++
++static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
++			      struct snd_ctl_elem_value *ucontrol)
++{
++	struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
++	mout->share_spdif = !!ucontrol->value.integer.value[0];
++	return 0;
++}
++
++static struct snd_kcontrol_new spdif_share_sw = {
++	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++	.name = "IEC958 Default PCM Playback Switch",
++	.info = snd_ctl_boolean_mono_info,
++	.get = spdif_share_sw_get,
++	.put = spdif_share_sw_put,
++};
++
++int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
++				  struct hda_multi_out *mout)
++{
++	if (!mout->dig_out_nid)
++		return 0;
++	/* ATTENTION: here mout is passed as private_data, instead of codec */
++	return snd_ctl_add(codec->bus->card,
++			   snd_ctl_new1(&spdif_share_sw, mout));
++}
++
++/*
+  * SPDIF input
+  */
+ 
+@@ -1595,7 +1696,17 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
+ 	int err;
+ 	struct snd_kcontrol *kctl;
+ 	struct snd_kcontrol_new *dig_mix;
++	int idx;
+ 
++	for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
++		if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
++					     idx))
++			break;
++	}
++	if (idx >= SPDIF_MAX_IDX) {
++		printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
++		return -EBUSY;
++	}
+ 	for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
+ 		kctl = snd_ctl_new1(dig_mix, codec);
+ 		kctl->private_value = nid;
+@@ -2106,7 +2217,7 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
+ 				   struct hda_codec *codec,
+ 				   struct snd_pcm_substream *substream)
+ {
+-	snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
+ 	return 0;
+ }
+ 
+@@ -2491,7 +2602,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
+ 	mutex_lock(&codec->spdif_mutex);
+ 	if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
+ 		/* already opened as analog dup; reset it once */
+-		snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
++		snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
+ 	mout->dig_out_used = HDA_DIG_EXCLUSIVE;
+ 	mutex_unlock(&codec->spdif_mutex);
+ 	return 0;
+@@ -2526,9 +2637,36 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
+  */
+ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
+ 				  struct hda_multi_out *mout,
+-				  struct snd_pcm_substream *substream)
+-{
+-	substream->runtime->hw.channels_max = mout->max_channels;
++				  struct snd_pcm_substream *substream,
++				  struct hda_pcm_stream *hinfo)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	runtime->hw.channels_max = mout->max_channels;
++	if (mout->dig_out_nid) {
++		if (!mout->analog_rates) {
++			mout->analog_rates = hinfo->rates;
++			mout->analog_formats = hinfo->formats;
++			mout->analog_maxbps = hinfo->maxbps;
++		} else {
++			runtime->hw.rates = mout->analog_rates;
++			runtime->hw.formats = mout->analog_formats;
++			hinfo->maxbps = mout->analog_maxbps;
++		}
++		if (!mout->spdif_rates) {
++			snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
++						    &mout->spdif_rates,
++						    &mout->spdif_formats,
++						    &mout->spdif_maxbps);
++		}
++		mutex_lock(&codec->spdif_mutex);
++		if (mout->share_spdif) {
++			runtime->hw.rates &= mout->spdif_rates;
++			runtime->hw.formats &= mout->spdif_formats;
++			if (mout->spdif_maxbps < hinfo->maxbps)
++				hinfo->maxbps = mout->spdif_maxbps;
++		}
++		mutex_unlock(&codec->spdif_mutex);
++	}
+ 	return snd_pcm_hw_constraint_step(substream->runtime, 0,
+ 					  SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+ }
+@@ -2548,7 +2686,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
+ 	int i;
+ 
+ 	mutex_lock(&codec->spdif_mutex);
+-	if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
++	if (mout->dig_out_nid && mout->share_spdif &&
++	    mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
+ 		if (chs == 2 &&
+ 		    snd_hda_is_supported_format(codec, mout->dig_out_nid,
+ 						format) &&
+@@ -2558,8 +2697,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
+ 					     stream_tag, format);
+ 		} else {
+ 			mout->dig_out_used = 0;
+-			snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
+-						   0, 0, 0);
++			snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
+ 		}
+ 	}
+ 	mutex_unlock(&codec->spdif_mutex);
+@@ -2601,17 +2739,16 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
+ 	int i;
+ 
+ 	for (i = 0; i < mout->num_dacs; i++)
+-		snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
++		snd_hda_codec_cleanup_stream(codec, nids[i]);
+ 	if (mout->hp_nid)
+-		snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0);
++		snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
+ 	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
+ 		if (mout->extra_out_nid[i])
+-			snd_hda_codec_setup_stream(codec,
+-						   mout->extra_out_nid[i],
+-						   0, 0, 0);
++			snd_hda_codec_cleanup_stream(codec,
++						     mout->extra_out_nid[i]);
+ 	mutex_lock(&codec->spdif_mutex);
+ 	if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
+-		snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
++		snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
+ 		mout->dig_out_used = 0;
+ 	}
+ 	mutex_unlock(&codec->spdif_mutex);
+@@ -2790,6 +2927,30 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
+ 		}
+ 	}
+ 
++	/* FIX-UP:
++	 * If no line-out is defined but multiple HPs are found,
++	 * some of them might be the real line-outs.
++	 */
++	if (!cfg->line_outs && cfg->hp_outs > 1) {
++		int i = 0;
++		while (i < cfg->hp_outs) {
++			/* The real HPs should have the sequence 0x0f */
++			if ((sequences_hp[i] & 0x0f) == 0x0f) {
++				i++;
++				continue;
++			}
++			/* Move it to the line-out table */
++			cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
++			sequences_line_out[cfg->line_outs] = sequences_hp[i];
++			cfg->line_outs++;
++			cfg->hp_outs--;
++			memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
++				sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
++			memmove(sequences_hp + i - 1, sequences_hp + i,
++				sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
++		}
++	}
++
+ 	/* sort by sequence */
+ 	sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
+ 			      cfg->line_outs);
+diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
+index f148711..dcd390b 100644
+--- a/sound/pci/hda/hda_codec.h
++++ b/sound/pci/hda/hda_codec.h
+@@ -590,11 +590,21 @@ struct hda_pcm_stream {
+ 	struct hda_pcm_ops ops;
+ };
+ 
++/* PCM types */
++enum {
++	HDA_PCM_TYPE_AUDIO,
++	HDA_PCM_TYPE_SPDIF,
++	HDA_PCM_TYPE_HDMI,
++	HDA_PCM_TYPE_MODEM,
++	HDA_PCM_NTYPES
++};
++
+ /* for PCM creation */
+ struct hda_pcm {
+ 	char *name;
+ 	struct hda_pcm_stream stream[2];
+-	unsigned int is_modem;	/* modem codec? */
++	unsigned int pcm_type;	/* HDA_PCM_TYPE_XXX */
++	int device;	/* assigned device number */
+ };
+ 
+ /* codec information */
+@@ -712,6 +722,7 @@ int snd_hda_build_pcms(struct hda_bus *bus);
+ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+ 				u32 stream_tag,
+ 				int channel_id, int format);
++void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);
+ unsigned int snd_hda_calc_stream_format(unsigned int rate,
+ 					unsigned int channels,
+ 					unsigned int format,
+diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
+index f9de7c4..59e4389 100644
+--- a/sound/pci/hda/hda_generic.c
++++ b/sound/pci/hda/hda_generic.c
+@@ -1007,8 +1007,8 @@ static int generic_pcm2_cleanup(struct hda_pcm_stream *hinfo,
+ {
+ 	struct hda_gspec *spec = codec->spec;
+ 
+-	snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
+-	snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, 0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
++	snd_hda_codec_cleanup_stream(codec, spec->dac_node[1]->nid);
+ 	return 0;
+ }
+ 
+diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
+index 4be36c8..b3a618e 100644
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -39,6 +39,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/dma-mapping.h>
+ #include <linux/moduleparam.h>
+ #include <linux/init.h>
+ #include <linux/slab.h>
+@@ -185,35 +186,28 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
+ 
+ /* max number of SDs */
+ /* ICH, ATI and VIA have 4 playback and 4 capture */
+-#define ICH6_CAPTURE_INDEX	0
+ #define ICH6_NUM_CAPTURE	4
+-#define ICH6_PLAYBACK_INDEX	4
+ #define ICH6_NUM_PLAYBACK	4
+ 
+ /* ULI has 6 playback and 5 capture */
+-#define ULI_CAPTURE_INDEX	0
+ #define ULI_NUM_CAPTURE		5
+-#define ULI_PLAYBACK_INDEX	5
+ #define ULI_NUM_PLAYBACK	6
+ 
+ /* ATI HDMI has 1 playback and 0 capture */
+-#define ATIHDMI_CAPTURE_INDEX	0
+ #define ATIHDMI_NUM_CAPTURE	0
+-#define ATIHDMI_PLAYBACK_INDEX	0
+ #define ATIHDMI_NUM_PLAYBACK	1
+ 
+ /* this number is statically defined for simplicity */
+ #define MAX_AZX_DEV		16
+ 
+ /* max number of fragments - we may use more if allocating more pages for BDL */
+-#define BDL_SIZE		PAGE_ALIGN(8192)
+-#define AZX_MAX_FRAG		(BDL_SIZE / (MAX_AZX_DEV * 16))
++#define BDL_SIZE		4096
++#define AZX_MAX_BDL_ENTRIES	(BDL_SIZE / 16)
++#define AZX_MAX_FRAG		32
+ /* max buffer size - no h/w limit, you can increase as you like */
+ #define AZX_MAX_BUF_SIZE	(1024*1024*1024)
+ /* max number of PCM devics per card */
+-#define AZX_MAX_AUDIO_PCMS	6
+-#define AZX_MAX_MODEM_PCMS	2
+-#define AZX_MAX_PCMS		(AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS)
++#define AZX_MAX_PCMS		8
+ 
+ /* RIRB int mask: overrun[2], response[0] */
+ #define RIRB_INT_RESPONSE	0x01
+@@ -227,6 +221,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
+ /* SD_CTL bits */
+ #define SD_CTL_STREAM_RESET	0x01	/* stream reset bit */
+ #define SD_CTL_DMA_START	0x02	/* stream DMA start bit */
++#define SD_CTL_STRIPE		(3 << 16)	/* stripe control */
++#define SD_CTL_TRAFFIC_PRIO	(1 << 18)	/* traffic priority */
++#define SD_CTL_DIR		(1 << 19)	/* bi-directional stream */
+ #define SD_CTL_STREAM_TAG_MASK	(0xf << 20)
+ #define SD_CTL_STREAM_TAG_SHIFT	20
+ 
+@@ -284,12 +281,10 @@ enum {
+  */
+ 
+ struct azx_dev {
+-	u32 *bdl;		/* virtual address of the BDL */
+-	dma_addr_t bdl_addr;	/* physical address of the BDL */
++	struct snd_dma_buffer bdl; /* BDL buffer */
+ 	u32 *posbuf;		/* position buffer pointer */
+ 
+ 	unsigned int bufsize;	/* size of the play buffer in bytes */
+-	unsigned int fragsize;	/* size of each period in bytes */
+ 	unsigned int frags;	/* number for period in the play buffer */
+ 	unsigned int fifo_size;	/* FIFO size */
+ 
+@@ -350,7 +345,6 @@ struct azx {
+ 	struct azx_dev *azx_dev;
+ 
+ 	/* PCM */
+-	unsigned int pcm_devs;
+ 	struct snd_pcm *pcm[AZX_MAX_PCMS];
+ 
+ 	/* HD codec */
+@@ -361,8 +355,7 @@ struct azx {
+ 	struct azx_rb corb;
+ 	struct azx_rb rirb;
+ 
+-	/* BDL, CORB/RIRB and position buffers */
+-	struct snd_dma_buffer bdl;
++	/* CORB/RIRB and position buffers */
+ 	struct snd_dma_buffer rb;
+ 	struct snd_dma_buffer posbuf;
+ 
+@@ -546,8 +539,9 @@ static void azx_update_rirb(struct azx *chip)
+ 		if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
+ 			snd_hda_queue_unsol_event(chip->bus, res, res_ex);
+ 		else if (chip->rirb.cmds) {
+-			chip->rirb.cmds--;
+ 			chip->rirb.res = res;
++			smp_wmb();
++			chip->rirb.cmds--;
+ 		}
+ 	}
+ }
+@@ -566,8 +560,10 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
+ 			azx_update_rirb(chip);
+ 			spin_unlock_irq(&chip->reg_lock);
+ 		}
+-		if (!chip->rirb.cmds)
++		if (!chip->rirb.cmds) {
++			smp_rmb();
+ 			return chip->rirb.res; /* the last value */
++		}
+ 		if (time_after(jiffies, timeout))
+ 			break;
+ 		if (codec->bus->needs_damn_long_delay)
+@@ -965,30 +961,57 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
+ /*
+  * set up BDL entries
+  */
+-static void azx_setup_periods(struct azx_dev *azx_dev)
++static int azx_setup_periods(struct snd_pcm_substream *substream,
++			     struct azx_dev *azx_dev)
+ {
+-	u32 *bdl = azx_dev->bdl;
+-	dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr;
+-	int idx;
++	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
++	u32 *bdl;
++	int i, ofs, periods, period_bytes;
+ 
+ 	/* reset BDL address */
+ 	azx_sd_writel(azx_dev, SD_BDLPL, 0);
+ 	azx_sd_writel(azx_dev, SD_BDLPU, 0);
+ 
++	period_bytes = snd_pcm_lib_period_bytes(substream);
++	periods = azx_dev->bufsize / period_bytes;
++
+ 	/* program the initial BDL entries */
+-	for (idx = 0; idx < azx_dev->frags; idx++) {
+-		unsigned int off = idx << 2; /* 4 dword step */
+-		dma_addr_t addr = dma_addr + idx * azx_dev->fragsize;
+-		/* program the address field of the BDL entry */
+-		bdl[off] = cpu_to_le32((u32)addr);
+-		bdl[off+1] = cpu_to_le32(upper_32bit(addr));
+-
+-		/* program the size field of the BDL entry */
+-		bdl[off+2] = cpu_to_le32(azx_dev->fragsize);
+-
+-		/* program the IOC to enable interrupt when buffer completes */
+-		bdl[off+3] = cpu_to_le32(0x01);
++	bdl = (u32 *)azx_dev->bdl.area;
++	ofs = 0;
++	azx_dev->frags = 0;
++	for (i = 0; i < periods; i++) {
++		int size, rest;
++		if (i >= AZX_MAX_BDL_ENTRIES) {
++			snd_printk(KERN_ERR "Too many BDL entries: "
++				   "buffer=%d, period=%d\n",
++				   azx_dev->bufsize, period_bytes);
++			/* reset */
++			azx_sd_writel(azx_dev, SD_BDLPL, 0);
++			azx_sd_writel(azx_dev, SD_BDLPU, 0);
++			return -EINVAL;
++		}
++		rest = period_bytes;
++		do {
++			dma_addr_t addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
++			/* program the address field of the BDL entry */
++			bdl[0] = cpu_to_le32((u32)addr);
++			bdl[1] = cpu_to_le32(upper_32bit(addr));
++			/* program the size field of the BDL entry */
++			size = PAGE_SIZE - (ofs % PAGE_SIZE);
++			if (rest < size)
++				size = rest;
++			bdl[2] = cpu_to_le32(size);
++			/* program the IOC to enable interrupt
++			 * only when the whole fragment is processed
++			 */
++			rest -= size;
++			bdl[3] = rest ? 0 : cpu_to_le32(0x01);
++			bdl += 4;
++			azx_dev->frags++;
++			ofs += size;
++		} while (rest > 0);
+ 	}
++	return 0;
+ }
+ 
+ /*
+@@ -1037,14 +1060,17 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
+ 
+ 	/* program the BDL address */
+ 	/* lower BDL address */
+-	azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl_addr);
++	azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
+ 	/* upper BDL address */
+-	azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
++	azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr));
+ 
+ 	/* enable the position buffer */
+-	if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+-		azx_writel(chip, DPLBASE,
+-			   (u32)chip->posbuf.addr |ICH6_DPLBASE_ENABLE);
++	if (chip->position_fix == POS_FIX_POSBUF ||
++	    chip->position_fix == POS_FIX_AUTO) {
++		if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
++			azx_writel(chip, DPLBASE,
++				(u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
++	}
+ 
+ 	/* set the interrupt enable bits in the descriptor control register */
+ 	azx_sd_writel(azx_dev, SD_CTL,
+@@ -1157,7 +1183,8 @@ static struct snd_pcm_hardware azx_pcm_hw = {
+ 				 SNDRV_PCM_INFO_MMAP_VALID |
+ 				 /* No full-resume yet implemented */
+ 				 /* SNDRV_PCM_INFO_RESUME |*/
+-				 SNDRV_PCM_INFO_PAUSE),
++				 SNDRV_PCM_INFO_PAUSE |
++				 SNDRV_PCM_INFO_SYNC_START),
+ 	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
+ 	.rates =		SNDRV_PCM_RATE_48000,
+ 	.rate_min =		48000,
+@@ -1219,6 +1246,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
+ 	spin_unlock_irqrestore(&chip->reg_lock, flags);
+ 
+ 	runtime->private_data = azx_dev;
++	snd_pcm_set_sync(substream);
+ 	mutex_unlock(&chip->open_mutex);
+ 	return 0;
+ }
+@@ -1275,8 +1303,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
+ 
+ 	azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
+-	azx_dev->fragsize = snd_pcm_lib_period_bytes(substream);
+-	azx_dev->frags = azx_dev->bufsize / azx_dev->fragsize;
+ 	azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
+ 							 runtime->channels,
+ 							 runtime->format,
+@@ -1288,10 +1314,10 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
+ 		return -EINVAL;
+ 	}
+ 
+-	snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, "
+-		    "format=0x%x\n",
+-		    azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val);
+-	azx_setup_periods(azx_dev);
++	snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
++		    azx_dev->bufsize, azx_dev->format_val);
++	if (azx_setup_periods(substream, azx_dev) < 0)
++		return -EINVAL;
+ 	azx_setup_controller(chip, azx_dev);
+ 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ 		azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
+@@ -1305,37 +1331,94 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
+ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ {
+ 	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+-	struct azx_dev *azx_dev = get_azx_dev(substream);
+ 	struct azx *chip = apcm->chip;
+-	int err = 0;
++	struct azx_dev *azx_dev;
++	struct snd_pcm_substream *s;
++	int start, nsync = 0, sbits = 0;
++	int nwait, timeout;
+ 
+-	spin_lock(&chip->reg_lock);
+ 	switch (cmd) {
+ 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ 	case SNDRV_PCM_TRIGGER_RESUME:
+ 	case SNDRV_PCM_TRIGGER_START:
+-		azx_stream_start(chip, azx_dev);
+-		azx_dev->running = 1;
++		start = 1;
+ 		break;
+ 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ 	case SNDRV_PCM_TRIGGER_SUSPEND:
+ 	case SNDRV_PCM_TRIGGER_STOP:
+-		azx_stream_stop(chip, azx_dev);
+-		azx_dev->running = 0;
++		start = 0;
+ 		break;
+ 	default:
+-		err = -EINVAL;
++		return -EINVAL;
++	}
++
++	snd_pcm_group_for_each_entry(s, substream) {
++		if (s->pcm->card != substream->pcm->card)
++			continue;
++		azx_dev = get_azx_dev(s);
++		sbits |= 1 << azx_dev->index;
++		nsync++;
++		snd_pcm_trigger_done(s, substream);
++	}
++
++	spin_lock(&chip->reg_lock);
++	if (nsync > 1) {
++		/* first, set SYNC bits of corresponding streams */
++		azx_writel(chip, SYNC, azx_readl(chip, SYNC) | sbits);
++	}
++	snd_pcm_group_for_each_entry(s, substream) {
++		if (s->pcm->card != substream->pcm->card)
++			continue;
++		azx_dev = get_azx_dev(s);
++		if (start)
++			azx_stream_start(chip, azx_dev);
++		else
++			azx_stream_stop(chip, azx_dev);
++		azx_dev->running = start;
+ 	}
+ 	spin_unlock(&chip->reg_lock);
+-	if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH ||
+-	    cmd == SNDRV_PCM_TRIGGER_SUSPEND ||
+-	    cmd == SNDRV_PCM_TRIGGER_STOP) {
+-		int timeout = 5000;
+-		while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) &&
+-		       --timeout)
+-			;
++	if (start) {
++		if (nsync == 1)
++			return 0;
++		/* wait until all FIFOs get ready */
++		for (timeout = 5000; timeout; timeout--) {
++			nwait = 0;
++			snd_pcm_group_for_each_entry(s, substream) {
++				if (s->pcm->card != substream->pcm->card)
++					continue;
++				azx_dev = get_azx_dev(s);
++				if (!(azx_sd_readb(azx_dev, SD_STS) &
++				      SD_STS_FIFO_READY))
++					nwait++;
++			}
++			if (!nwait)
++				break;
++			cpu_relax();
++		}
++	} else {
++		/* wait until all RUN bits are cleared */
++		for (timeout = 5000; timeout; timeout--) {
++			nwait = 0;
++			snd_pcm_group_for_each_entry(s, substream) {
++				if (s->pcm->card != substream->pcm->card)
++					continue;
++				azx_dev = get_azx_dev(s);
++				if (azx_sd_readb(azx_dev, SD_CTL) &
++				    SD_CTL_DMA_START)
++					nwait++;
++			}
++			if (!nwait)
++				break;
++			cpu_relax();
++		}
+ 	}
+-	return err;
++	if (nsync > 1) {
++		spin_lock(&chip->reg_lock);
++		/* reset SYNC bits */
++		azx_writel(chip, SYNC, azx_readl(chip, SYNC) & ~sbits);
++		spin_unlock(&chip->reg_lock);
++	}
++	return 0;
+ }
+ 
+ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
+@@ -1378,6 +1461,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
+ 	.prepare = azx_pcm_prepare,
+ 	.trigger = azx_pcm_trigger,
+ 	.pointer = azx_pcm_pointer,
++	.page = snd_pcm_sgbuf_ops_page,
+ };
+ 
+ static void azx_pcm_free(struct snd_pcm *pcm)
+@@ -1386,7 +1470,7 @@ static void azx_pcm_free(struct snd_pcm *pcm)
+ }
+ 
+ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
+-				      struct hda_pcm *cpcm, int pcm_dev)
++				      struct hda_pcm *cpcm)
+ {
+ 	int err;
+ 	struct snd_pcm *pcm;
+@@ -1400,7 +1484,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
+ 
+ 	snd_assert(cpcm->name, return -EINVAL);
+ 
+-	err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
++	err = snd_pcm_new(chip->card, cpcm->name, cpcm->device,
+ 			  cpcm->stream[0].substreams,
+ 			  cpcm->stream[1].substreams,
+ 			  &pcm);
+@@ -1420,62 +1504,70 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
+ 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops);
+ 	if (cpcm->stream[1].substreams)
+ 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
+-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+ 					      snd_dma_pci_data(chip->pci),
+ 					      1024 * 64, 1024 * 1024);
+-	chip->pcm[pcm_dev] = pcm;
+-	if (chip->pcm_devs < pcm_dev + 1)
+-		chip->pcm_devs = pcm_dev + 1;
+-
++	chip->pcm[cpcm->device] = pcm;
+ 	return 0;
+ }
+ 
+ static int __devinit azx_pcm_create(struct azx *chip)
+ {
++	static const char *dev_name[HDA_PCM_NTYPES] = {
++		"Audio", "SPDIF", "HDMI", "Modem"
++	};
++	/* starting device index for each PCM type */
++	static int dev_idx[HDA_PCM_NTYPES] = {
++		[HDA_PCM_TYPE_AUDIO] = 0,
++		[HDA_PCM_TYPE_SPDIF] = 1,
++		[HDA_PCM_TYPE_HDMI] = 3,
++		[HDA_PCM_TYPE_MODEM] = 6
++	};
++	/* normal audio device indices; not linear to keep compatibility */
++	static int audio_idx[4] = { 0, 2, 4, 5 };
+ 	struct hda_codec *codec;
+ 	int c, err;
+-	int pcm_dev;
++	int num_devs[HDA_PCM_NTYPES];
+ 
+ 	err = snd_hda_build_pcms(chip->bus);
+ 	if (err < 0)
+ 		return err;
+ 
+ 	/* create audio PCMs */
+-	pcm_dev = 0;
+-	list_for_each_entry(codec, &chip->bus->codec_list, list) {
+-		for (c = 0; c < codec->num_pcms; c++) {
+-			if (codec->pcm_info[c].is_modem)
+-				continue; /* create later */
+-			if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
+-				snd_printk(KERN_ERR SFX
+-					   "Too many audio PCMs\n");
+-				return -EINVAL;
+-			}
+-			err = create_codec_pcm(chip, codec,
+-					       &codec->pcm_info[c], pcm_dev);
+-			if (err < 0)
+-				return err;
+-			pcm_dev++;
+-		}
+-	}
+-
+-	/* create modem PCMs */
+-	pcm_dev = AZX_MAX_AUDIO_PCMS;
++	memset(num_devs, 0, sizeof(num_devs));
+ 	list_for_each_entry(codec, &chip->bus->codec_list, list) {
+ 		for (c = 0; c < codec->num_pcms; c++) {
+-			if (!codec->pcm_info[c].is_modem)
+-				continue; /* already created */
+-			if (pcm_dev >= AZX_MAX_PCMS) {
+-				snd_printk(KERN_ERR SFX
+-					   "Too many modem PCMs\n");
+-				return -EINVAL;
++			struct hda_pcm *cpcm = &codec->pcm_info[c];
++			int type = cpcm->pcm_type;
++			switch (type) {
++			case HDA_PCM_TYPE_AUDIO:
++				if (num_devs[type] >= ARRAY_SIZE(audio_idx)) {
++					snd_printk(KERN_WARNING
++						   "Too many audio devices\n");
++					continue;
++				}
++				cpcm->device = audio_idx[num_devs[type]];
++				break;
++			case HDA_PCM_TYPE_SPDIF:
++			case HDA_PCM_TYPE_HDMI:
++			case HDA_PCM_TYPE_MODEM:
++				if (num_devs[type]) {
++					snd_printk(KERN_WARNING
++						   "%s already defined\n",
++						   dev_name[type]);
++					continue;
++				}
++				cpcm->device = dev_idx[type];
++				break;
++			default:
++				snd_printk(KERN_WARNING
++					   "Invalid PCM type %d\n", type);
++				continue;
+ 			}
+-			err = create_codec_pcm(chip, codec,
+-					       &codec->pcm_info[c], pcm_dev);
++			num_devs[type]++;
++			err = create_codec_pcm(chip, codec, cpcm);
+ 			if (err < 0)
+ 				return err;
+-			chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM;
+-			pcm_dev++;
+ 		}
+ 	}
+ 	return 0;
+@@ -1502,10 +1594,7 @@ static int __devinit azx_init_stream(struct azx *chip)
+ 	 * and initialize
+ 	 */
+ 	for (i = 0; i < chip->num_streams; i++) {
+-		unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
+ 		struct azx_dev *azx_dev = &chip->azx_dev[i];
+-		azx_dev->bdl = (u32 *)(chip->bdl.area + off);
+-		azx_dev->bdl_addr = chip->bdl.addr + off;
+ 		azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8);
+ 		/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
+ 		azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
+@@ -1587,13 +1676,12 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
+ 	int i;
+ 
+ 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+-	for (i = 0; i < chip->pcm_devs; i++)
++	for (i = 0; i < AZX_MAX_PCMS; i++)
+ 		snd_pcm_suspend_all(chip->pcm[i]);
+ 	if (chip->initialized)
+ 		snd_hda_suspend(chip->bus, state);
+ 	azx_stop_chip(chip);
+ 	if (chip->irq >= 0) {
+-		synchronize_irq(chip->irq);
+ 		free_irq(chip->irq, chip);
+ 		chip->irq = -1;
+ 	}
+@@ -1641,24 +1729,26 @@ static int azx_resume(struct pci_dev *pci)
+  */
+ static int azx_free(struct azx *chip)
+ {
++	int i;
++
+ 	if (chip->initialized) {
+-		int i;
+ 		for (i = 0; i < chip->num_streams; i++)
+ 			azx_stream_stop(chip, &chip->azx_dev[i]);
+ 		azx_stop_chip(chip);
+ 	}
+ 
+-	if (chip->irq >= 0) {
+-		synchronize_irq(chip->irq);
++	if (chip->irq >= 0)
+ 		free_irq(chip->irq, (void*)chip);
+-	}
+ 	if (chip->msi)
+ 		pci_disable_msi(chip->pci);
+ 	if (chip->remap_addr)
+ 		iounmap(chip->remap_addr);
+ 
+-	if (chip->bdl.area)
+-		snd_dma_free_pages(&chip->bdl);
++	if (chip->azx_dev) {
++		for (i = 0; i < chip->num_streams; i++)
++			if (chip->azx_dev[i].bdl.area)
++				snd_dma_free_pages(&chip->azx_dev[i].bdl);
++	}
+ 	if (chip->rb.area)
+ 		snd_dma_free_pages(&chip->rb);
+ 	if (chip->posbuf.area)
+@@ -1682,6 +1772,7 @@ static int azx_dev_free(struct snd_device *device)
+ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
+ 	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
+ 	SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE),
++	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_NONE),
+ 	{}
+ };
+ 
+@@ -1740,7 +1831,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+ 				struct azx **rchip)
+ {
+ 	struct azx *chip;
+-	int err;
++	int i, err;
+ 	unsigned short gcap;
+ 	static struct snd_device_ops ops = {
+ 		.dev_free = azx_dev_free,
+@@ -1812,38 +1903,35 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+ 	gcap = azx_readw(chip, GCAP);
+ 	snd_printdd("chipset global capabilities = 0x%x\n", gcap);
+ 
+-	if (gcap) {
+-		/* read number of streams from GCAP register instead of using
+-		 * hardcoded value
+-		 */
+-		chip->playback_streams = (gcap & (0xF << 12)) >> 12;
+-		chip->capture_streams = (gcap & (0xF << 8)) >> 8;
+-		chip->playback_index_offset = chip->capture_streams;
+-		chip->capture_index_offset = 0;
+-	} else {
++	/* allow 64bit DMA address if supported by H/W */
++	if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
++		pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
++
++	/* read number of streams from GCAP register instead of using
++	 * hardcoded value
++	 */
++	chip->capture_streams = (gcap >> 8) & 0x0f;
++	chip->playback_streams = (gcap >> 12) & 0x0f;
++	if (!chip->playback_streams && !chip->capture_streams) {
+ 		/* gcap didn't give any info, switching to old method */
+ 
+ 		switch (chip->driver_type) {
+ 		case AZX_DRIVER_ULI:
+ 			chip->playback_streams = ULI_NUM_PLAYBACK;
+ 			chip->capture_streams = ULI_NUM_CAPTURE;
+-			chip->playback_index_offset = ULI_PLAYBACK_INDEX;
+-			chip->capture_index_offset = ULI_CAPTURE_INDEX;
+ 			break;
+ 		case AZX_DRIVER_ATIHDMI:
+ 			chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
+ 			chip->capture_streams = ATIHDMI_NUM_CAPTURE;
+-			chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX;
+-			chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX;
+ 			break;
+ 		default:
+ 			chip->playback_streams = ICH6_NUM_PLAYBACK;
+ 			chip->capture_streams = ICH6_NUM_CAPTURE;
+-			chip->playback_index_offset = ICH6_PLAYBACK_INDEX;
+-			chip->capture_index_offset = ICH6_CAPTURE_INDEX;
+ 			break;
+ 		}
+ 	}
++	chip->capture_index_offset = 0;
++	chip->playback_index_offset = chip->capture_streams;
+ 	chip->num_streams = chip->playback_streams + chip->capture_streams;
+ 	chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
+ 				GFP_KERNEL);
+@@ -1852,13 +1940,15 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+ 		goto errout;
+ 	}
+ 
+-	/* allocate memory for the BDL for each stream */
+-	err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+-				  snd_dma_pci_data(chip->pci),
+-				  BDL_SIZE, &chip->bdl);
+-	if (err < 0) {
+-		snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
+-		goto errout;
++	for (i = 0; i < chip->num_streams; i++) {
++		/* allocate memory for the BDL for each stream */
++		err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
++					  snd_dma_pci_data(chip->pci),
++					  BDL_SIZE, &chip->azx_dev[i].bdl);
++		if (err < 0) {
++			snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
++			goto errout;
++		}
+ 	}
+ 	/* allocate memory for the position buffer */
+ 	err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+@@ -1994,48 +2084,63 @@ static void __devexit azx_remove(struct pci_dev *pci)
+ 
+ /* PCI IDs */
+ static struct pci_device_id azx_ids[] = {
+-	{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */
+-	{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
+-	{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
+-	{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
+-	{ 0x8086, 0x293e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
+-	{ 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
+-	{ 0x8086, 0x3a3e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
+-	{ 0x8086, 0x3a6e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
+-	{ 0x8086, 0x811b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SCH }, /* SCH*/
+-	{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
+-	{ 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
+-	{ 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
+-	{ 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */
+-	{ 0x1002, 0x960f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS780 HDMI */
+-	{ 0x1002, 0xaa00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI R600 HDMI */
+-	{ 0x1002, 0xaa08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV630 HDMI */
+-	{ 0x1002, 0xaa10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV610 HDMI */
+-	{ 0x1002, 0xaa18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV670 HDMI */
+-	{ 0x1002, 0xaa20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV635 HDMI */
+-	{ 0x1002, 0xaa28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV620 HDMI */
+-	{ 0x1002, 0xaa30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV770 HDMI */
+-	{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
+-	{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
+-	{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
+-	{ 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP51 */
+-	{ 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP55 */
+-	{ 0x10de, 0x03e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+-	{ 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+-	{ 0x10de, 0x044a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+-	{ 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+-	{ 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
+-	{ 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
+-	{ 0x10de, 0x07fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
+-	{ 0x10de, 0x07fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
+-	{ 0x10de, 0x0774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+-	{ 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+-	{ 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+-	{ 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+-	{ 0x10de, 0x0ac0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+-	{ 0x10de, 0x0ac1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+-	{ 0x10de, 0x0ac2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+-	{ 0x10de, 0x0ac3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
++	/* ICH 6..10 */
++	{ PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH },
++	{ PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
++	{ PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
++	{ PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
++	{ PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
++	{ PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
++	{ PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
++	{ PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
++	/* SCH */
++	{ PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
++	/* ATI SB 450/600 */
++	{ PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
++	{ PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
++	/* ATI HDMI */
++	{ PCI_DEVICE(0x1002, 0x793b), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0x7919), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0x960f), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa00), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa08), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa10), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa18), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa20), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa28), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa30), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa38), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa40), .driver_data = AZX_DRIVER_ATIHDMI },
++	{ PCI_DEVICE(0x1002, 0xaa48), .driver_data = AZX_DRIVER_ATIHDMI },
++	/* VIA VT8251/VT8237A */
++	{ PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
++	/* SIS966 */
++	{ PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS },
++	/* ULI M5461 */
++	{ PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI },
++	/* NVIDIA MCP */
++	{ PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0bd4), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA },
++	{ PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
+ 	{ 0, }
+ };
+ MODULE_DEVICE_TABLE(pci, azx_ids);
+diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
+index ad0014a..5c9e578 100644
+--- a/sound/pci/hda/hda_local.h
++++ b/sound/pci/hda/hda_local.h
+@@ -228,8 +228,18 @@ struct hda_multi_out {
+ 	int max_channels;	/* currently supported analog channels */
+ 	int dig_out_used;	/* current usage of digital out (HDA_DIG_XXX) */
+ 	int no_share_stream;	/* don't share a stream with multiple pins */
++	int share_spdif;	/* share SPDIF pin */
++	/* PCM information for both analog and SPDIF DACs */
++	unsigned int analog_rates;
++	unsigned int analog_maxbps;
++	u64 analog_formats;
++	unsigned int spdif_rates;
++	unsigned int spdif_maxbps;
++	u64 spdif_formats;
+ };
+ 
++int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
++				  struct hda_multi_out *mout);
+ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
+ 			       struct hda_multi_out *mout);
+ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
+@@ -241,7 +251,8 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
+ 				  struct snd_pcm_substream *substream);
+ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
+ 				  struct hda_multi_out *mout,
+-				  struct snd_pcm_substream *substream);
++				  struct snd_pcm_substream *substream,
++				  struct hda_pcm_stream *hinfo);
+ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
+ 				     struct hda_multi_out *mout,
+ 				     unsigned int stream_tag,
+@@ -407,11 +418,4 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
+ 				 hda_nid_t nid);
+ #endif /* CONFIG_SND_HDA_POWER_SAVE */
+ 
+-/*
+- * virtual master control
+- */
+-struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
+-						 const unsigned int *tlv);
+-int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave);
+-		      
+ #endif /* __SOUND_HDA_LOCAL_H */
+diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
+index f5c23bb..2fdf235 100644
+--- a/sound/pci/hda/hda_patch.h
++++ b/sound/pci/hda/hda_patch.h
+@@ -18,31 +18,3 @@ extern struct hda_codec_preset snd_hda_preset_atihdmi[];
+ extern struct hda_codec_preset snd_hda_preset_conexant[];
+ /* VIA codecs */
+ extern struct hda_codec_preset snd_hda_preset_via[];
+-
+-static const struct hda_codec_preset *hda_preset_tables[] = {
+-#ifdef CONFIG_SND_HDA_CODEC_REALTEK
+-	snd_hda_preset_realtek,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_CMEDIA
+-	snd_hda_preset_cmedia,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_ANALOG
+-	snd_hda_preset_analog,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
+-	snd_hda_preset_sigmatel,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_SI3054
+-	snd_hda_preset_si3054,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
+-	snd_hda_preset_atihdmi,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_CONEXANT
+-	snd_hda_preset_conexant,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_VIA
+-	snd_hda_preset_via,
+-#endif
+-	NULL
+-};
+diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
+index c864928..e0a605a 100644
+--- a/sound/pci/hda/patch_analog.c
++++ b/sound/pci/hda/patch_analog.c
+@@ -28,6 +28,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+ 
+ struct ad198x_spec {
+ 	struct snd_kcontrol_new *mixers[5];
+@@ -80,7 +81,6 @@ struct ad198x_spec {
+ #endif
+ 	/* for virtual master */
+ 	hda_nid_t vmaster_nid;
+-	u32 vmaster_tlv[4];
+ 	const char **slave_vols;
+ 	const char **slave_sws;
+ };
+@@ -171,6 +171,11 @@ static int ad198x_build_controls(struct hda_codec *codec)
+ 		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+ 		if (err < 0)
+ 			return err;
++		err = snd_hda_create_spdif_share_sw(codec,
++						    &spec->multiout);
++		if (err < 0)
++			return err;
++		spec->multiout.share_spdif = 1;
+ 	} 
+ 	if (spec->dig_in_nid) {
+ 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -180,10 +185,11 @@ static int ad198x_build_controls(struct hda_codec *codec)
+ 
+ 	/* if we have no master control, let's create it */
+ 	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
++		unsigned int vmaster_tlv[4];
+ 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
+-					HDA_OUTPUT, spec->vmaster_tlv);
++					HDA_OUTPUT, vmaster_tlv);
+ 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+-					  spec->vmaster_tlv,
++					  vmaster_tlv,
+ 					  (spec->slave_vols ?
+ 					   spec->slave_vols : ad_slave_vols));
+ 		if (err < 0)
+@@ -217,7 +223,8 @@ static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ 				    struct snd_pcm_substream *substream)
+ {
+ 	struct ad198x_spec *spec = codec->spec;
+-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++					     hinfo);
+ }
+ 
+ static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -289,8 +296,7 @@ static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ 				      struct snd_pcm_substream *substream)
+ {
+ 	struct ad198x_spec *spec = codec->spec;
+-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+-				   0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ 	return 0;
+ }
+ 
+@@ -359,6 +365,7 @@ static int ad198x_build_pcms(struct hda_codec *codec)
+ 		info++;
+ 		codec->num_pcms++;
+ 		info->name = "AD198x Digital";
++		info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
+ 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+ 		if (spec->dig_in_nid) {
+@@ -611,13 +618,19 @@ static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
+ 	},
+ };
+ 
++static struct hda_input_mux ad1986a_automic_capture_source = {
++	.num_items = 2,
++	.items = {
++		{ "Mic", 0x0 },
++		{ "Mix", 0x5 },
++	},
++};
++
+ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
+ 	HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
+ 	HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
+ 	HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
+@@ -641,6 +654,33 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
+ 	{ } /* end */
+ };
+ 
++/* re-connect the mic boost input according to the jack sensing */
++static void ad1986a_automic(struct hda_codec *codec)
++{
++	unsigned int present;
++	present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
++	/* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
++	snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
++			    (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
++}
++
++#define AD1986A_MIC_EVENT		0x36
++
++static void ad1986a_automic_unsol_event(struct hda_codec *codec,
++					    unsigned int res)
++{
++	if ((res >> 26) != AD1986A_MIC_EVENT)
++		return;
++	ad1986a_automic(codec);
++}
++
++static int ad1986a_automic_init(struct hda_codec *codec)
++{
++	ad198x_init(codec);
++	ad1986a_automic(codec);
++	return 0;
++}
++
+ /* laptop-automute - 2ch only */
+ 
+ static void ad1986a_update_hp(struct hda_codec *codec)
+@@ -844,6 +884,15 @@ static struct hda_verb ad1986a_eapd_init_verbs[] = {
+ 	{}
+ };
+ 
++static struct hda_verb ad1986a_automic_verbs[] = {
++	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++	/*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
++	{0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
++	{0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
++	{}
++};
++
+ /* Ultra initialization */
+ static struct hda_verb ad1986a_ultra_init[] = {
+ 	/* eapd initialization */
+@@ -986,14 +1035,17 @@ static int patch_ad1986a(struct hda_codec *codec)
+ 		break;
+ 	case AD1986A_LAPTOP_EAPD:
+ 		spec->mixers[0] = ad1986a_laptop_eapd_mixers;
+-		spec->num_init_verbs = 2;
++		spec->num_init_verbs = 3;
+ 		spec->init_verbs[1] = ad1986a_eapd_init_verbs;
++		spec->init_verbs[2] = ad1986a_automic_verbs;
+ 		spec->multiout.max_channels = 2;
+ 		spec->multiout.num_dacs = 1;
+ 		spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
+ 		if (!is_jack_available(codec, 0x25))
+ 			spec->multiout.dig_out_nid = 0;
+-		spec->input_mux = &ad1986a_laptop_eapd_capture_source;
++		spec->input_mux = &ad1986a_automic_capture_source;
++		codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
++		codec->patch_ops.init = ad1986a_automic_init;
+ 		break;
+ 	case AD1986A_LAPTOP_AUTOMUTE:
+ 		spec->mixers[0] = ad1986a_laptop_automute_mixers;
+@@ -1365,7 +1417,10 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+ 
+ 	if (! ad198x_eapd_put(kcontrol, ucontrol))
+ 		return 0;
+-
++	/* change speaker pin appropriately */
++	snd_hda_codec_write(codec, 0x05, 0,
++			    AC_VERB_SET_PIN_WIDGET_CONTROL,
++			    spec->cur_eapd ? PIN_OUT : 0);
+ 	/* toggle HP mute appropriately */
+ 	snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
+ 				 HDA_AMP_MUTE,
+@@ -2087,6 +2142,10 @@ static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
+ 	{ } /* end */
+ };
+ 
++static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
++	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
++	{ } /* end */
++};
+ 
+ /*
+  * initialization verbs
+@@ -2187,6 +2246,13 @@ static struct hda_verb ad1988_spdif_init_verbs[] = {
+ 	{ }
+ };
+ 
++/* AD1989 has no ADC -> SPDIF route */
++static struct hda_verb ad1989_spdif_init_verbs[] = {
++	/* SPDIF out pin */
++	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
++	{ }
++};
++
+ /*
+  * verbs for 3stack (+dig)
+  */
+@@ -2894,10 +2960,19 @@ static int patch_ad1988(struct hda_codec *codec)
+ 	spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
+ 	spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
+ 	if (spec->multiout.dig_out_nid) {
+-		spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
+-		spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
++		if (codec->vendor_id >= 0x11d4989a) {
++			spec->mixers[spec->num_mixers++] =
++				ad1989_spdif_out_mixers;
++			spec->init_verbs[spec->num_init_verbs++] =
++				ad1989_spdif_init_verbs;
++		} else {
++			spec->mixers[spec->num_mixers++] =
++				ad1988_spdif_out_mixers;
++			spec->init_verbs[spec->num_init_verbs++] =
++				ad1988_spdif_init_verbs;
++		}
+ 	}
+-	if (spec->dig_in_nid)
++	if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
+ 		spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
+ 
+ 	codec->patch_ops = ad198x_patch_ops;
+@@ -3133,11 +3208,12 @@ static int patch_ad1884(struct hda_codec *codec)
+  * Lenovo Thinkpad T61/X61
+  */
+ static struct hda_input_mux ad1984_thinkpad_capture_source = {
+-	.num_items = 3,
++	.num_items = 4,
+ 	.items = {
+ 		{ "Mic", 0x0 },
+ 		{ "Internal Mic", 0x1 },
+ 		{ "Mix", 0x3 },
++		{ "Docking-Station", 0x4 },
+ 	},
+ };
+ 
+@@ -3268,8 +3344,7 @@ static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
+ 				   struct hda_codec *codec,
+ 				   struct snd_pcm_substream *substream)
+ {
+-	snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
+-				   0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
+ 	return 0;
+ }
+ 
+@@ -3356,6 +3431,472 @@ static int patch_ad1984(struct hda_codec *codec)
+ 
+ 
+ /*
++ * AD1883 / AD1884A / AD1984A / AD1984B
++ *
++ * port-B (0x14) - front mic-in
++ * port-E (0x1c) - rear mic-in
++ * port-F (0x16) - CD / ext out
++ * port-C (0x15) - rear line-in
++ * port-D (0x12) - rear line-out
++ * port-A (0x11) - front hp-out
++ *
++ * AD1984A = AD1884A + digital-mic
++ * AD1883 = equivalent with AD1984A
++ * AD1984B = AD1984A + extra SPDIF-out
++ *
++ * FIXME:
++ * We share the single DAC for both HP and line-outs (see AD1884/1984).
++ */
++
++static hda_nid_t ad1884a_dac_nids[1] = {
++	0x03,
++};
++
++#define ad1884a_adc_nids	ad1884_adc_nids
++#define ad1884a_capsrc_nids	ad1884_capsrc_nids
++
++#define AD1884A_SPDIF_OUT	0x02
++
++static struct hda_input_mux ad1884a_capture_source = {
++	.num_items = 5,
++	.items = {
++		{ "Front Mic", 0x0 },
++		{ "Mic", 0x4 },
++		{ "Line", 0x1 },
++		{ "CD", 0x2 },
++		{ "Mix", 0x3 },
++	},
++};
++
++static struct snd_kcontrol_new ad1884a_base_mixers[] = {
++	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
++	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
++	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
++	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
++	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
++	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
++	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
++	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
++	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
++	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
++	HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		/* The multiple "Capture Source" controls confuse alsamixer
++		 * So call somewhat different..
++		 */
++		/* .name = "Capture Source", */
++		.name = "Input Source",
++		.count = 2,
++		.info = ad198x_mux_enum_info,
++		.get = ad198x_mux_enum_get,
++		.put = ad198x_mux_enum_put,
++	},
++	/* SPDIF controls */
++	HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
++		/* identical with ad1983 */
++		.info = ad1983_spdif_route_info,
++		.get = ad1983_spdif_route_get,
++		.put = ad1983_spdif_route_put,
++	},
++	{ } /* end */
++};
++
++/*
++ * initialization verbs
++ */
++static struct hda_verb ad1884a_init_verbs[] = {
++	/* DACs; unmute as default */
++	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
++	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
++	/* Port-A (HP) mixer - route only from analog mixer */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++	/* Port-A pin */
++	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	/* Port-D (Line-out) mixer - route only from analog mixer */
++	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++	/* Port-D pin */
++	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	/* Mono-out mixer - route only from analog mixer */
++	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++	/* Mono-out pin */
++	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	/* Port-B (front mic) pin */
++	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	/* Port-C (rear line-in) pin */
++	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	/* Port-E (rear mic) pin */
++	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
++	/* Port-F (CD) pin */
++	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	/* Analog mixer; mute as default */
++	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
++	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
++	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
++	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
++	/* Analog Mix output amp */
++	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	/* capture sources */
++	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
++	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
++	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	/* SPDIF output amp */
++	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
++	{ } /* end */
++};
++
++#ifdef CONFIG_SND_HDA_POWER_SAVE
++static struct hda_amp_list ad1884a_loopbacks[] = {
++	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
++	{ 0x20, HDA_INPUT, 1 }, /* Mic */
++	{ 0x20, HDA_INPUT, 2 }, /* CD */
++	{ 0x20, HDA_INPUT, 4 }, /* Docking */
++	{ } /* end */
++};
++#endif
++
++/*
++ * Laptop model
++ *
++ * Port A: Headphone jack
++ * Port B: MIC jack
++ * Port C: Internal MIC
++ * Port D: Dock Line Out (if enabled)
++ * Port E: Dock Line In (if enabled)
++ * Port F: Internal speakers
++ */
++
++static struct hda_input_mux ad1884a_laptop_capture_source = {
++	.num_items = 4,
++	.items = {
++		{ "Mic", 0x0 },		/* port-B */
++		{ "Internal Mic", 0x1 }, /* port-C */
++		{ "Dock Mic", 0x4 },	/* port-E */
++		{ "Mix", 0x3 },
++	},
++};
++
++static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
++	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
++	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
++	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
++	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
++	HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
++	HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
++	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
++	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		/* The multiple "Capture Source" controls confuse alsamixer
++		 * So call somewhat different..
++		 */
++		/* .name = "Capture Source", */
++		.name = "Input Source",
++		.count = 2,
++		.info = ad198x_mux_enum_info,
++		.get = ad198x_mux_enum_get,
++		.put = ad198x_mux_enum_put,
++	},
++	{ } /* end */
++};
++
++static struct hda_input_mux ad1884a_mobile_capture_source = {
++	.num_items = 2,
++	.items = {
++		{ "Mic", 0x1 }, /* port-C */
++		{ "Mix", 0x3 },
++	},
++};
++
++static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
++	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
++	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
++	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
++	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Capture Source",
++		.info = ad198x_mux_enum_info,
++		.get = ad198x_mux_enum_get,
++		.put = ad198x_mux_enum_put,
++	},
++	{ } /* end */
++};
++
++/* mute internal speaker if HP is plugged */
++static void ad1884a_hp_automute(struct hda_codec *codec)
++{
++	unsigned int present;
++
++	present = snd_hda_codec_read(codec, 0x11, 0,
++				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
++	snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
++				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
++	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
++			    present ? 0x00 : 0x02);
++}
++
++#define AD1884A_HP_EVENT		0x37
++
++/* unsolicited event for HP jack sensing */
++static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
++{
++	if ((res >> 26) != AD1884A_HP_EVENT)
++		return;
++	ad1884a_hp_automute(codec);
++}
++
++/* initialize jack-sensing, too */
++static int ad1884a_hp_init(struct hda_codec *codec)
++{
++	ad198x_init(codec);
++	ad1884a_hp_automute(codec);
++	return 0;
++}
++
++/* additional verbs for laptop model */
++static struct hda_verb ad1884a_laptop_verbs[] = {
++	/* Port-A (HP) pin - always unmuted */
++	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	/* Port-F (int speaker) mixer - route only from analog mixer */
++	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++	/* Port-F pin */
++	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	/* analog mix */
++	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
++	/* unsolicited event for pin-sense */
++	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
++	{ } /* end */
++};
++
++/*
++ * Thinkpad X300
++ * 0x11 - HP
++ * 0x12 - speaker
++ * 0x14 - mic-in
++ * 0x17 - built-in mic
++ */
++
++static struct hda_verb ad1984a_thinkpad_verbs[] = {
++	/* HP unmute */
++	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++	/* analog mix */
++	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
++	/* turn on EAPD */
++	{0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
++	/* unsolicited event for pin-sense */
++	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
++	/* internal mic - dmic */
++	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++	/* set magic COEFs for dmic */
++	{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
++	{0x01, AC_VERB_SET_PROC_COEF, 0x08},
++	{ } /* end */
++};
++
++static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
++	HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
++	HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
++	HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
++	HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Capture Source",
++		.info = ad198x_mux_enum_info,
++		.get = ad198x_mux_enum_get,
++		.put = ad198x_mux_enum_put,
++	},
++	{ } /* end */
++};
++
++static struct hda_input_mux ad1984a_thinkpad_capture_source = {
++	.num_items = 3,
++	.items = {
++		{ "Mic", 0x0 },
++		{ "Internal Mic", 0x5 },
++		{ "Mix", 0x3 },
++	},
++};
++
++/* mute internal speaker if HP is plugged */
++static void ad1984a_thinkpad_automute(struct hda_codec *codec)
++{
++	unsigned int present;
++
++	present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
++		& AC_PINSENSE_PRESENCE;
++	snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
++				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
++}
++
++/* unsolicited event for HP jack sensing */
++static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
++					 unsigned int res)
++{
++	if ((res >> 26) != AD1884A_HP_EVENT)
++		return;
++	ad1984a_thinkpad_automute(codec);
++}
++
++/* initialize jack-sensing, too */
++static int ad1984a_thinkpad_init(struct hda_codec *codec)
++{
++	ad198x_init(codec);
++	ad1984a_thinkpad_automute(codec);
++	return 0;
++}
++
++/*
++ */
++
++enum {
++	AD1884A_DESKTOP,
++	AD1884A_LAPTOP,
++	AD1884A_MOBILE,
++	AD1884A_THINKPAD,
++	AD1884A_MODELS
++};
++
++static const char *ad1884a_models[AD1884A_MODELS] = {
++	[AD1884A_DESKTOP]	= "desktop",
++	[AD1884A_LAPTOP]	= "laptop",
++	[AD1884A_MOBILE]	= "mobile",
++	[AD1884A_THINKPAD]	= "thinkpad",
++};
++
++static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
++	SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
++	SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
++	{}
++};
++
++static int patch_ad1884a(struct hda_codec *codec)
++{
++	struct ad198x_spec *spec;
++	int board_config;
++
++	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
++	if (spec == NULL)
++		return -ENOMEM;
++
++	mutex_init(&spec->amp_mutex);
++	codec->spec = spec;
++
++	spec->multiout.max_channels = 2;
++	spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
++	spec->multiout.dac_nids = ad1884a_dac_nids;
++	spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
++	spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
++	spec->adc_nids = ad1884a_adc_nids;
++	spec->capsrc_nids = ad1884a_capsrc_nids;
++	spec->input_mux = &ad1884a_capture_source;
++	spec->num_mixers = 1;
++	spec->mixers[0] = ad1884a_base_mixers;
++	spec->num_init_verbs = 1;
++	spec->init_verbs[0] = ad1884a_init_verbs;
++	spec->spdif_route = 0;
++#ifdef CONFIG_SND_HDA_POWER_SAVE
++	spec->loopback.amplist = ad1884a_loopbacks;
++#endif
++	codec->patch_ops = ad198x_patch_ops;
++
++	/* override some parameters */
++	board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
++						  ad1884a_models,
++						  ad1884a_cfg_tbl);
++	switch (board_config) {
++	case AD1884A_LAPTOP:
++		spec->mixers[0] = ad1884a_laptop_mixers;
++		spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
++		spec->multiout.dig_out_nid = 0;
++		spec->input_mux = &ad1884a_laptop_capture_source;
++		codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
++		codec->patch_ops.init = ad1884a_hp_init;
++		break;
++	case AD1884A_MOBILE:
++		spec->mixers[0] = ad1884a_mobile_mixers;
++		spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
++		spec->multiout.dig_out_nid = 0;
++		spec->input_mux = &ad1884a_mobile_capture_source;
++		codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
++		codec->patch_ops.init = ad1884a_hp_init;
++		break;
++	case AD1884A_THINKPAD:
++		spec->mixers[0] = ad1984a_thinkpad_mixers;
++		spec->init_verbs[spec->num_init_verbs++] =
++			ad1984a_thinkpad_verbs;
++		spec->multiout.dig_out_nid = 0;
++		spec->input_mux = &ad1984a_thinkpad_capture_source;
++		codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
++		codec->patch_ops.init = ad1984a_thinkpad_init;
++		break;
++	}
++
++	return 0;
++}
++
++
++/*
+  * AD1882
+  *
+  * port-A - front hp-out
+@@ -3654,13 +4195,19 @@ static int patch_ad1882(struct hda_codec *codec)
+  * patch entries
+  */
+ struct hda_codec_preset snd_hda_preset_analog[] = {
++	{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
+ 	{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
++	{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
+ 	{ .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
++	{ .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
++	{ .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
+ 	{ .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
+ 	{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
+ 	{ .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
+ 	{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
+ 	{ .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
+ 	{ .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
++	{ .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
++	{ .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
+ 	{} /* terminator */
+ };
+diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
+index 9a8bb4c..1227250 100644
+--- a/sound/pci/hda/patch_atihdmi.c
++++ b/sound/pci/hda/patch_atihdmi.c
+@@ -27,6 +27,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+ 
+ struct atihdmi_spec {
+ 	struct hda_multi_out multiout;
+@@ -58,6 +59,10 @@ static int atihdmi_build_controls(struct hda_codec *codec)
+ static int atihdmi_init(struct hda_codec *codec)
+ {
+ 	snd_hda_sequence_write(codec, atihdmi_basic_init);
++	/* SI codec requires to unmute the pin */
++	if (get_wcaps(codec, 0x03) & AC_WCAP_OUT_AMP)
++		snd_hda_codec_write(codec, 0x03, 0, AC_VERB_SET_AMP_GAIN_MUTE,
++				    AMP_OUT_UNMUTE);
+ 	return 0;
+ }
+ 
+@@ -112,6 +117,7 @@ static int atihdmi_build_pcms(struct hda_codec *codec)
+ 	codec->pcm_info = info;
+ 
+ 	info->name = "ATI HDMI";
++	info->pcm_type = HDA_PCM_TYPE_HDMI;
+ 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
+ 
+ 	return 0;
+@@ -158,5 +164,7 @@ struct hda_codec_preset snd_hda_preset_atihdmi[] = {
+ 	{ .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
+ 	{ .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
+ 	{ .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi },
++	{ .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi },
++	{ .id = 0x17e80047, .name = "Chrontel HDMI",  .patch = patch_atihdmi },
+ 	{} /* terminator */
+ };
+diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
+index 3d6097b..c73ce07 100644
+--- a/sound/pci/hda/patch_cmedia.c
++++ b/sound/pci/hda/patch_cmedia.c
+@@ -28,6 +28,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+ #define NUM_PINS	11
+ 
+ 
+@@ -329,6 +330,11 @@ static int cmi9880_build_controls(struct hda_codec *codec)
+ 		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+ 		if (err < 0)
+ 			return err;
++		err = snd_hda_create_spdif_share_sw(codec,
++						    &spec->multiout);
++		if (err < 0)
++			return err;
++		spec->multiout.share_spdif = 1;
+ 	}
+ 	if (spec->dig_in_nid) {
+ 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -432,7 +438,8 @@ static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ 				     struct snd_pcm_substream *substream)
+ {
+ 	struct cmi_spec *spec = codec->spec;
+-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++					     hinfo);
+ }
+ 
+ static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -506,7 +513,7 @@ static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ {
+ 	struct cmi_spec *spec = codec->spec;
+ 
+-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ 	return 0;
+ }
+ 
+@@ -571,6 +578,7 @@ static int cmi9880_build_pcms(struct hda_codec *codec)
+ 		codec->num_pcms++;
+ 		info++;
+ 		info->name = "CMI9880 Digital";
++		info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ 		if (spec->multiout.dig_out_nid) {
+ 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
+ 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+@@ -603,6 +611,7 @@ static const char *cmi9880_models[CMI_MODELS] = {
+ 
+ static struct snd_pci_quirk cmi9880_cfg_tbl[] = {
+ 	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
++	SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG),
+ 	{} /* terminator */
+ };
+ 
+diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
+index 7206b30..36fd852 100644
+--- a/sound/pci/hda/patch_conexant.c
++++ b/sound/pci/hda/patch_conexant.c
+@@ -27,6 +27,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+ 
+ #define CXT_PIN_DIR_IN              0x00
+ #define CXT_PIN_DIR_OUT             0x01
+@@ -98,7 +99,8 @@ static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ 				      struct snd_pcm_substream *substream)
+ {
+ 	struct conexant_spec *spec = codec->spec;
+-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++					     hinfo);
+ }
+ 
+ static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -172,8 +174,7 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ 				      struct snd_pcm_substream *substream)
+ {
+ 	struct conexant_spec *spec = codec->spec;
+-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+-				   0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ 	return 0;
+ }
+ 
+@@ -241,7 +242,7 @@ static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ 				      struct snd_pcm_substream *substream)
+ {
+ 	struct conexant_spec *spec = codec->spec;
+-	snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
+ 	spec->cur_adc = 0;
+ 	return 0;
+ }
+@@ -284,6 +285,7 @@ static int conexant_build_pcms(struct hda_codec *codec)
+ 		info++;
+ 		codec->num_pcms++;
+ 		info->name = "Conexant Digital";
++		info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+ 			conexant_pcm_digital_playback;
+ 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+@@ -371,6 +373,11 @@ static int conexant_build_controls(struct hda_codec *codec)
+ 						    spec->multiout.dig_out_nid);
+ 		if (err < 0)
+ 			return err;
++		err = snd_hda_create_spdif_share_sw(codec,
++						    &spec->multiout);
++		if (err < 0)
++			return err;
++		spec->multiout.share_spdif = 1;
+ 	} 
+ 	if (spec->dig_in_nid) {
+ 		err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
+@@ -511,6 +518,14 @@ static struct hda_input_mux cxt5045_capture_source_benq = {
+ 	}
+ };
+ 
++static struct hda_input_mux cxt5045_capture_source_hp530 = {
++	.num_items = 2,
++	.items = {
++		{ "ExtMic", 0x1 },
++		{ "IntMic", 0x2 },
++	}
++};
++
+ /* turn on/off EAPD (+ mute HP) as a master switch */
+ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+ 				    struct snd_ctl_elem_value *ucontrol)
+@@ -639,6 +654,37 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
+ 	{}
+ };
+ 
++static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Capture Source",
++		.info = conexant_mux_enum_info,
++		.get = conexant_mux_enum_get,
++		.put = conexant_mux_enum_put
++	},
++	HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
++	HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
++	HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
++	HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
++	HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
++	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
++	HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
++	HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
++	HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Master Playback Switch",
++		.info = cxt_eapd_info,
++		.get = cxt_eapd_get,
++		.put = cxt5045_hp_master_sw_put,
++		.private_value = 0x10,
++	},
++
++	{}
++};
++
+ static struct hda_verb cxt5045_init_verbs[] = {
+ 	/* Line in, Mic */
+ 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+@@ -833,6 +879,7 @@ enum {
+ 	CXT5045_LAPTOP_MICSENSE,
+ 	CXT5045_LAPTOP_HPMICSENSE,
+ 	CXT5045_BENQ,
++	CXT5045_LAPTOP_HP530,
+ #ifdef CONFIG_SND_DEBUG
+ 	CXT5045_TEST,
+ #endif
+@@ -844,6 +891,7 @@ static const char *cxt5045_models[CXT5045_MODELS] = {
+ 	[CXT5045_LAPTOP_MICSENSE]	= "laptop-micsense",
+ 	[CXT5045_LAPTOP_HPMICSENSE]	= "laptop-hpmicsense",
+ 	[CXT5045_BENQ]			= "benq",
++	[CXT5045_LAPTOP_HP530]		= "laptop-hp530",
+ #ifdef CONFIG_SND_DEBUG
+ 	[CXT5045_TEST]		= "test",
+ #endif
+@@ -857,7 +905,7 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
+ 	SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP_HPSENSE),
+ 	SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP_HPSENSE),
+ 	SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE),
+-	SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HPSENSE),
++	SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
+ 	SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE),
+ 	SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
+ 	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
+@@ -941,6 +989,14 @@ static int patch_cxt5045(struct hda_codec *codec)
+ 		spec->num_mixers = 2;
+ 		codec->patch_ops.init = cxt5045_init;
+ 		break;
++	case CXT5045_LAPTOP_HP530:
++		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
++		spec->input_mux = &cxt5045_capture_source_hp530;
++		spec->num_init_verbs = 2;
++		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
++		spec->mixers[0] = cxt5045_mixers_hp530;
++		codec->patch_ops.init = cxt5045_init;
++		break;
+ #ifdef CONFIG_SND_DEBUG
+ 	case CXT5045_TEST:
+ 		spec->input_mux = &cxt5045_test_capture_source;
+@@ -1537,7 +1593,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
+ 	new_adc = spec->adc_nids[spec->cur_adc_idx];
+ 	if (spec->cur_adc && spec->cur_adc != new_adc) {
+ 		/* stream is running, let's swap the current ADC */
+-		snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
++		snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
+ 		spec->cur_adc = new_adc;
+ 		snd_hda_codec_setup_stream(codec, new_adc,
+ 					   spec->cur_adc_stream_tag, 0,
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 33282f9..cdda64b 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -30,6 +30,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+ 
+ #define ALC880_FRONT_EVENT		0x01
+ #define ALC880_DCVOL_EVENT		0x02
+@@ -97,16 +98,19 @@ enum {
+ 	ALC262_SONY_ASSAMD,
+ 	ALC262_BENQ_T31,
+ 	ALC262_ULTRA,
++	ALC262_LENOVO_3000,
+ 	ALC262_AUTO,
+ 	ALC262_MODEL_LAST /* last tag */
+ };
+ 
+ /* ALC268 models */
+ enum {
++	ALC267_QUANTA_IL1,
+ 	ALC268_3ST,
+ 	ALC268_TOSHIBA,
+ 	ALC268_ACER,
+ 	ALC268_DELL,
++	ALC268_ZEPTO,
+ #ifdef CONFIG_SND_DEBUG
+ 	ALC268_TEST,
+ #endif
+@@ -195,10 +199,11 @@ enum {
+ 	ALC883_LENOVO_NB0763,
+ 	ALC888_LENOVO_MS7195_DIG,
+ 	ALC883_HAIER_W66,		
+-	ALC888_6ST_HP,
+ 	ALC888_3ST_HP,
+ 	ALC888_6ST_DELL,
+ 	ALC883_MITAC,
++	ALC883_CLEVO_M720,
++	ALC883_FUJITSU_PI2515,
+ 	ALC883_AUTO,
+ 	ALC883_MODEL_LAST,
+ };
+@@ -237,6 +242,7 @@ struct alc_spec {
+ 	/* capture */
+ 	unsigned int num_adc_nids;
+ 	hda_nid_t *adc_nids;
++	hda_nid_t *capsrc_nids;
+ 	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
+ 
+ 	/* capture source */
+@@ -270,7 +276,6 @@ struct alc_spec {
+ 
+ 	/* for virtual master */
+ 	hda_nid_t vmaster_nid;
+-	u32 vmaster_tlv[4];
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ 	struct hda_loopback_check loopback;
+ #endif
+@@ -290,6 +295,7 @@ struct alc_config_preset {
+ 	hda_nid_t hp_nid;		/* optional */
+ 	unsigned int num_adc_nids;
+ 	hda_nid_t *adc_nids;
++	hda_nid_t *capsrc_nids;
+ 	hda_nid_t dig_in_nid;
+ 	unsigned int num_channel_mode;
+ 	const struct hda_channel_mode *channel_mode;
+@@ -336,9 +342,10 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
+ 	struct alc_spec *spec = codec->spec;
+ 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ 	unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
++	hda_nid_t nid = spec->capsrc_nids ?
++		spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
+ 	return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
+-				     spec->adc_nids[adc_idx],
+-				     &spec->cur_mux[adc_idx]);
++				     nid, &spec->cur_mux[adc_idx]);
+ }
+ 
+ 
+@@ -707,6 +714,7 @@ static void setup_preset(struct alc_spec *spec,
+ 
+ 	spec->num_adc_nids = preset->num_adc_nids;
+ 	spec->adc_nids = preset->adc_nids;
++	spec->capsrc_nids = preset->capsrc_nids;
+ 	spec->dig_in_nid = preset->dig_in_nid;
+ 
+ 	spec->unsol_event = preset->unsol_event;
+@@ -741,7 +749,6 @@ static struct hda_verb alc_gpio3_init_verbs[] = {
+ static void alc_sku_automute(struct hda_codec *codec)
+ {
+ 	struct alc_spec *spec = codec->spec;
+-	unsigned int mute;
+ 	unsigned int present;
+ 	unsigned int hp_nid = spec->autocfg.hp_pins[0];
+ 	unsigned int sp_nid = spec->autocfg.speaker_pins[0];
+@@ -751,16 +758,8 @@ static void alc_sku_automute(struct hda_codec *codec)
+ 	present = snd_hda_codec_read(codec, hp_nid, 0,
+ 				     AC_VERB_GET_PIN_SENSE, 0);
+ 	spec->jack_present = (present & 0x80000000) != 0;
+-	if (spec->jack_present) {
+-		/* mute internal speaker */
+-		snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
+-					 HDA_AMP_MUTE, HDA_AMP_MUTE);
+-	} else {
+-		/* unmute internal speaker if necessary */
+-		mute = snd_hda_codec_amp_read(codec, hp_nid, 0, HDA_OUTPUT, 0);
+-		snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
+-					 HDA_AMP_MUTE, mute);
+-	}
++	snd_hda_codec_write(codec, sp_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
++			    spec->jack_present ? 0 : PIN_OUT);
+ }
+ 
+ /* unsolicited event for HP jack sensing */
+@@ -1319,11 +1318,19 @@ static struct snd_kcontrol_new alc880_f1734_mixer[] = {
+ 	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ 	{ } /* end */
+ };
+ 
++static struct hda_input_mux alc880_f1734_capture_source = {
++	.num_items = 2,
++	.items = {
++		{ "Mic", 0x1 },
++		{ "CD", 0x4 },
++	},
++};
++
+ 
+ /*
+  * ALC880 ASUS model
+@@ -1516,6 +1523,11 @@ static int alc_build_controls(struct hda_codec *codec)
+ 						    spec->multiout.dig_out_nid);
+ 		if (err < 0)
+ 			return err;
++		err = snd_hda_create_spdif_share_sw(codec,
++						    &spec->multiout);
++		if (err < 0)
++			return err;
++		spec->multiout.share_spdif = 1;
+ 	}
+ 	if (spec->dig_in_nid) {
+ 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -1525,10 +1537,11 @@ static int alc_build_controls(struct hda_codec *codec)
+ 
+ 	/* if we have no master control, let's create it */
+ 	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
++		unsigned int vmaster_tlv[4];
+ 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
+-					HDA_OUTPUT, spec->vmaster_tlv);
++					HDA_OUTPUT, vmaster_tlv);
+ 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+-					  spec->vmaster_tlv, alc_slave_vols);
++					  vmaster_tlv, alc_slave_vols);
+ 		if (err < 0)
+ 			return err;
+ 	}
+@@ -1882,7 +1895,7 @@ static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
+  	present = snd_hda_codec_read(codec, 0x14, 0,
+ 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ 	bits = present ? HDA_AMP_MUTE : 0;
+-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits);
++	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, bits);
+ }
+ 
+ static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
+@@ -1915,6 +1928,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
+  * HP = 0x14, speaker-out = 0x15, mic = 0x18
+  */
+ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
++	{0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
+ 	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+ 	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+ 	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+@@ -1927,7 +1941,7 @@ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+ 
+ 	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+ 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+@@ -1935,6 +1949,9 @@ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+ 	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ 	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ 
++	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
++	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
++
+ 	{ }
+ };
+ 
+@@ -2318,7 +2335,8 @@ static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ 				    struct snd_pcm_substream *substream)
+ {
+ 	struct alc_spec *spec = codec->spec;
+-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++					     hinfo);
+ }
+ 
+ static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -2392,8 +2410,8 @@ static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ {
+ 	struct alc_spec *spec = codec->spec;
+ 
+-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
+-				   0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec,
++				     spec->adc_nids[substream->number + 1]);
+ 	return 0;
+ }
+ 
+@@ -2498,6 +2516,7 @@ static int alc_build_pcms(struct hda_codec *codec)
+ 		codec->num_pcms = 2;
+ 		info = spec->pcm_rec + 1;
+ 		info->name = spec->stream_name_digital;
++		info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ 		if (spec->multiout.dig_out_nid &&
+ 		    spec->stream_digital_playback) {
+ 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
+@@ -2560,6 +2579,7 @@ static void alc_free(struct hda_codec *codec)
+ 		kfree(spec->kctl_alloc);
+ 	}
+ 	kfree(spec);
++	codec->spec = NULL; /* to be sure */
+ }
+ 
+ /*
+@@ -3057,7 +3077,9 @@ static struct alc_config_preset alc880_presets[] = {
+ 		.hp_nid = 0x02,
+ 		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+ 		.channel_mode = alc880_2_jack_modes,
+-		.input_mux = &alc880_capture_source,
++		.input_mux = &alc880_f1734_capture_source,
++		.unsol_event = alc880_uniwill_p53_unsol_event,
++		.init_hook = alc880_uniwill_p53_hp_automute,
+ 	},
+ 	[ALC880_ASUS] = {
+ 		.mixers = { alc880_asus_mixer },
+@@ -3467,15 +3489,21 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
+ 	return 0;
+ }
+ 
+-static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
+-					      hda_nid_t nid, int pin_type,
+-					      int dac_idx)
++static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
++			       unsigned int pin_type)
+ {
+-	/* set as output */
+ 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ 			    pin_type);
++	/* unmute pin */
+ 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ 			    AMP_OUT_UNMUTE);
++}
++
++static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
++					      hda_nid_t nid, int pin_type,
++					      int dac_idx)
++{
++	alc_set_pin_output(codec, nid, pin_type);
+ 	/* need the manual connection? */
+ 	if (alc880_is_multi_pin(nid)) {
+ 		struct alc_spec *spec = codec->spec;
+@@ -3597,9 +3625,12 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc880_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc880_auto_init_multi_out(codec);
+ 	alc880_auto_init_extra_out(codec);
+ 	alc880_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
+ /*
+@@ -4795,11 +4826,7 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
+ 					      hda_nid_t nid, int pin_type,
+ 					      int sel_idx)
+ {
+-	/* set as output */
+-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+-			    pin_type);
+-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+-			    AMP_OUT_UNMUTE);
++	alc_set_pin_output(codec, nid, pin_type);
+ 	/* need the manual connection? */
+ 	if (nid >= 0x12) {
+ 		int idx = nid - 0x12;
+@@ -4929,7 +4956,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
+ 	/* check whether NID 0x04 is valid */
+ 	wcap = get_wcaps(codec, 0x04);
+ 	wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+-	if (wcap != AC_WID_AUD_IN) {
++	if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
+ 		spec->adc_nids = alc260_adc_nids_alt;
+ 		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
+ 		spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
+@@ -4946,8 +4973,11 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc260_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc260_auto_init_multi_out(codec);
+ 	alc260_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+@@ -5204,6 +5234,9 @@ static hda_nid_t alc882_dac_nids[4] = {
+ #define alc882_adc_nids		alc880_adc_nids
+ #define alc882_adc_nids_alt	alc880_adc_nids_alt
+ 
++static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
++static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
++
+ /* input MUX */
+ /* FIXME: should be a matrix-type input source selection */
+ 
+@@ -5226,15 +5259,11 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
+ 	struct alc_spec *spec = codec->spec;
+ 	const struct hda_input_mux *imux = spec->input_mux;
+ 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+-	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
+-	hda_nid_t nid;
++	hda_nid_t nid = spec->capsrc_nids ?
++		spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
+ 	unsigned int *cur_val = &spec->cur_mux[adc_idx];
+ 	unsigned int i, idx;
+ 
+-	if (spec->num_adc_nids < 3)
+-		nid = capture_mixers[adc_idx + 1];
+-	else
+-		nid = capture_mixers[adc_idx];
+ 	idx = ucontrol->value.enumerated.item[0];
+ 	if (idx >= imux->num_items)
+ 		idx = imux->num_items - 1;
+@@ -6111,6 +6140,7 @@ static struct alc_config_preset alc882_presets[] = {
+ 		.dig_out_nid = ALC882_DIGOUT_NID,
+ 		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
+ 		.adc_nids = alc882_adc_nids,
++		.capsrc_nids = alc882_capsrc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
+ 		.channel_mode = alc882_3ST_6ch_modes,
+ 		.need_dac_fix = 1,
+@@ -6127,6 +6157,7 @@ static struct alc_config_preset alc882_presets[] = {
+ 		.dig_out_nid = ALC882_DIGOUT_NID,
+ 		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
+ 		.adc_nids = alc882_adc_nids,
++		.capsrc_nids = alc882_capsrc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
+ 		.channel_mode = alc882_3ST_6ch_modes,
+ 		.need_dac_fix = 1,
+@@ -6182,15 +6213,11 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
+ 	struct alc_spec *spec = codec->spec;
+ 	int idx;
+ 
++	alc_set_pin_output(codec, nid, pin_type);
+ 	if (spec->multiout.dac_nids[dac_idx] == 0x25)
+ 		idx = 4;
+ 	else
+ 		idx = spec->multiout.dac_nids[dac_idx] - 2;
+-
+-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+-			    pin_type);
+-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+-			    AMP_OUT_UNMUTE);
+ 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
+ 
+ }
+@@ -6219,6 +6246,9 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
+ 	if (pin) /* connect to front */
+ 		/* use dac 0 */
+ 		alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
++	pin = spec->autocfg.speaker_pins[0];
++	if (pin)
++		alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+ 
+ #define alc882_is_input_pin(nid)	alc880_is_input_pin(nid)
+@@ -6231,16 +6261,21 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec)
+ 
+ 	for (i = 0; i < AUTO_PIN_LAST; i++) {
+ 		hda_nid_t nid = spec->autocfg.input_pins[i];
+-		if (alc882_is_input_pin(nid)) {
+-			snd_hda_codec_write(codec, nid, 0,
+-					    AC_VERB_SET_PIN_WIDGET_CONTROL,
+-					    i <= AUTO_PIN_FRONT_MIC ?
+-					    PIN_VREF80 : PIN_IN);
+-			if (nid != ALC882_PIN_CD_NID)
+-				snd_hda_codec_write(codec, nid, 0,
+-						    AC_VERB_SET_AMP_GAIN_MUTE,
+-						    AMP_OUT_MUTE);
++		unsigned int vref;
++		if (!nid)
++			continue;
++		vref = PIN_IN;
++		if (1 /*i <= AUTO_PIN_FRONT_MIC*/) {
++			if (snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) &
++			    AC_PINCAP_VREF_80)
++				vref = PIN_VREF80;
+ 		}
++		snd_hda_codec_write(codec, nid, 0,
++				    AC_VERB_SET_PIN_WIDGET_CONTROL, vref);
++		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
++			snd_hda_codec_write(codec, nid, 0,
++					    AC_VERB_SET_AMP_GAIN_MUTE,
++					    AMP_OUT_MUTE);
+ 	}
+ }
+ 
+@@ -6294,11 +6329,16 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc882_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc882_auto_init_multi_out(codec);
+ 	alc882_auto_init_hp_out(codec);
+ 	alc882_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
++static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
++
+ static int patch_alc882(struct hda_codec *codec)
+ {
+ 	struct alc_spec *spec;
+@@ -6328,6 +6368,11 @@ static int patch_alc882(struct hda_codec *codec)
+ 			board_config = ALC885_MBP3;
+ 			break;
+ 		default:
++			/* ALC889A is handled better as ALC888-compatible */
++			if (codec->revision_id == 0x100103) {
++				alc_free(codec);
++				return patch_alc883(codec);
++			}
+ 			printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
+ 		       			 "trying auto-probe from BIOS...\n");
+ 			board_config = ALC882_AUTO;
+@@ -6372,12 +6417,14 @@ static int patch_alc882(struct hda_codec *codec)
+ 		if (wcap != AC_WID_AUD_IN) {
+ 			spec->adc_nids = alc882_adc_nids_alt;
+ 			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
++			spec->capsrc_nids = alc882_capsrc_nids_alt;
+ 			spec->mixers[spec->num_mixers] =
+ 				alc882_capture_alt_mixer;
+ 			spec->num_mixers++;
+ 		} else {
+ 			spec->adc_nids = alc882_adc_nids;
+ 			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
++			spec->capsrc_nids = alc882_capsrc_nids;
+ 			spec->mixers[spec->num_mixers] = alc882_capture_mixer;
+ 			spec->num_mixers++;
+ 		}
+@@ -6412,7 +6459,7 @@ static int patch_alc882(struct hda_codec *codec)
+ 
+ static hda_nid_t alc883_dac_nids[4] = {
+ 	/* front, rear, clfe, rear_surr */
+-	0x02, 0x04, 0x03, 0x05
++	0x02, 0x03, 0x04, 0x05
+ };
+ 
+ static hda_nid_t alc883_adc_nids[2] = {
+@@ -6420,6 +6467,8 @@ static hda_nid_t alc883_adc_nids[2] = {
+ 	0x08, 0x09,
+ };
+ 
++static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
++
+ /* input MUX */
+ /* FIXME: should be a matrix-type input source selection */
+ 
+@@ -6451,35 +6500,18 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
+ 	},
+ };
+ 
++static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
++	.num_items = 2,
++	.items = {
++		{ "Mic", 0x0 },
++		{ "Int Mic", 0x1 },
++	},
++};
++
+ #define alc883_mux_enum_info alc_mux_enum_info
+ #define alc883_mux_enum_get alc_mux_enum_get
+-
+-static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
+-			       struct snd_ctl_elem_value *ucontrol)
+-{
+-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+-	struct alc_spec *spec = codec->spec;
+-	const struct hda_input_mux *imux = spec->input_mux;
+-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+-	static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
+-	hda_nid_t nid = capture_mixers[adc_idx];
+-	unsigned int *cur_val = &spec->cur_mux[adc_idx];
+-	unsigned int i, idx;
+-
+-	idx = ucontrol->value.enumerated.item[0];
+-	if (idx >= imux->num_items)
+-		idx = imux->num_items - 1;
+-	if (*cur_val == idx)
+-		return 0;
+-	for (i = 0; i < imux->num_items; i++) {
+-		unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+-		snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+-					 imux->items[i].index,
+-					 HDA_AMP_MUTE, v);
+-	}
+-	*cur_val = idx;
+-	return 1;
+-}
++/* ALC883 has the ALC882-type input selection */
++#define alc883_mux_enum_put alc882_mux_enum_put
+ 
+ /*
+  * 2ch mode
+@@ -6638,6 +6670,60 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
+ 	{ } /* end */
+ };
+ 
++static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
++	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
++	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
++	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		/* .name = "Capture Source", */
++		.name = "Input Source",
++		.count = 2,
++		.info = alc883_mux_enum_info,
++		.get = alc883_mux_enum_get,
++		.put = alc883_mux_enum_put,
++	},
++	{ } /* end */
++};
++
++static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
++	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
++	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
++	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		/* .name = "Capture Source", */
++		.name = "Input Source",
++		.count = 2,
++		.info = alc883_mux_enum_info,
++		.get = alc883_mux_enum_get,
++		.put = alc883_mux_enum_put,
++	},
++	{ } /* end */
++};
++
+ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
+ 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+@@ -6787,6 +6873,9 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
+ 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ 	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ 	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+@@ -6878,124 +6967,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
+ 	{ } /* end */
+ };	
+ 
+-static struct snd_kcontrol_new alc888_6st_hp_mixer[] = {
+-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
+-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
+-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+-	{
+-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+-		/* .name = "Capture Source", */
+-		.name = "Input Source",
+-		.count = 2,
+-		.info = alc883_mux_enum_info,
+-		.get = alc883_mux_enum_get,
+-		.put = alc883_mux_enum_put,
+-	},
+-	{ } /* end */
+-};
+-
+-static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
+-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
+-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
+-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+-	{
+-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+-		/* .name = "Capture Source", */
+-		.name = "Input Source",
+-		.count = 2,
+-		.info = alc883_mux_enum_info,
+-		.get = alc883_mux_enum_get,
+-		.put = alc883_mux_enum_put,
+-	},
+-	{ } /* end */
+-};
+-
+-static struct snd_kcontrol_new alc888_6st_dell_mixer[] = {
+-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
+-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
+-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+-	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+-	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+-	{
+-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+-		/* .name = "Capture Source", */
+-		.name = "Input Source",
+-		.count = 2,
+-		.info = alc883_mux_enum_info,
+-		.get = alc883_mux_enum_get,
+-		.put = alc883_mux_enum_put,
+-	},
+-	{ } /* end */
+-};
+-
+ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
+ 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+@@ -7171,6 +7142,35 @@ static struct hda_verb alc883_mitac_verbs[] = {
+ 	{ } /* end */
+ };
+ 
++static struct hda_verb alc883_clevo_m720_verbs[] = {
++	/* HP */
++	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
++	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	/* Int speaker */
++	{0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++
++	/* enable unsolicited event */
++	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
++	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
++
++	{ } /* end */
++};
++
++static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
++	/* HP */
++	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
++	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	/* Subwoofer */
++	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++
++	/* enable unsolicited event */
++	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
++
++	{ } /* end */
++};
++
+ static struct hda_verb alc883_tagra_verbs[] = {
+ 	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ 	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+@@ -7227,26 +7227,14 @@ static struct hda_verb alc883_haier_w66_verbs[] = {
+ 	{ } /* end */
+ };
+ 
+-static struct hda_verb alc888_6st_hp_verbs[] = {
+-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
+-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x02},	/* Rear : output 2 (0x0e) */
+-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* CLFE : output 1 (0x0d) */
+-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},	/* Side : output 3 (0x0f) */
+-	{ }
+-};
+-
+ static struct hda_verb alc888_3st_hp_verbs[] = {
+ 	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
+-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Rear : output 1 (0x0d) */
+-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},	/* CLFE : output 2 (0x0e) */
++	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Rear : output 1 (0x0d) */
++	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},	/* CLFE : output 2 (0x0e) */
+ 	{ }
+ };
+ 
+ static struct hda_verb alc888_6st_dell_verbs[] = {
+-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
+-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x02},	/* Rear : output 1 (0x0e) */
+-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* CLFE : output 2 (0x0d) */
+-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},	/* Side : output 3 (0x0f) */
+ 	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ 	{ }
+ };
+@@ -7354,6 +7342,68 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
+ 		alc883_tagra_automute(codec);
+ }
+ 
++/* toggle speaker-output according to the hp-jack state */
++static void alc883_clevo_m720_hp_automute(struct hda_codec *codec)
++{
++	unsigned int present;
++	unsigned char bits;
++
++	present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
++		& AC_PINSENSE_PRESENCE;
++	bits = present ? HDA_AMP_MUTE : 0;
++	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++				 HDA_AMP_MUTE, bits);
++}
++
++static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
++{
++	unsigned int present;
++
++	present = snd_hda_codec_read(codec, 0x18, 0,
++				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
++	snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
++				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
++}
++
++static void alc883_clevo_m720_automute(struct hda_codec *codec)
++{
++	alc883_clevo_m720_hp_automute(codec);
++	alc883_clevo_m720_mic_automute(codec);
++}
++
++static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
++					   unsigned int res)
++{
++	switch (res >> 26) {
++	case ALC880_HP_EVENT:
++		alc883_clevo_m720_hp_automute(codec);
++		break;
++	case ALC880_MIC_EVENT:
++		alc883_clevo_m720_mic_automute(codec);
++		break;
++	}
++}
++
++/* toggle speaker-output according to the hp-jack state */
++static void alc883_2ch_fujitsu_pi2515_automute(struct hda_codec *codec)
++{
++ 	unsigned int present;
++	unsigned char bits;
++
++ 	present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0)
++		& AC_PINSENSE_PRESENCE;
++	bits = present ? HDA_AMP_MUTE : 0;
++	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
++				 HDA_AMP_MUTE, bits);
++}
++
++static void alc883_2ch_fujitsu_pi2515_unsol_event(struct hda_codec *codec,
++						  unsigned int res)
++{
++	if ((res >> 26) == ALC880_HP_EVENT)
++		alc883_2ch_fujitsu_pi2515_automute(codec);
++}
++
+ static void alc883_haier_w66_automute(struct hda_codec *codec)
+ {
+ 	unsigned int present;
+@@ -7587,10 +7637,11 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
+ 	[ALC883_LENOVO_NB0763]	= "lenovo-nb0763",
+ 	[ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
+ 	[ALC883_HAIER_W66] 	= "haier-w66",
+-	[ALC888_6ST_HP]		= "6stack-hp",
+ 	[ALC888_3ST_HP]		= "3stack-hp",
+ 	[ALC888_6ST_DELL]	= "6stack-dell",
+ 	[ALC883_MITAC]		= "mitac",
++	[ALC883_CLEVO_M720]	= "clevo-m720",
++	[ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
+ 	[ALC883_AUTO]		= "auto",
+ };
+ 
+@@ -7604,7 +7655,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+ 	SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
+ 	SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
+ 	SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
+-	SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP),
++	SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
+ 	SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
+ 	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
+ 	SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
+@@ -7614,7 +7665,9 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+ 	SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
++	SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
++	SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
+@@ -7627,13 +7680,17 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+ 	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
++	SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
+ 	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
+ 	SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
++	SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
++	SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
+ 	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
+ 	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
+ 	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
++	SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515),
+ 	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
+ 	SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
+ 	SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
+@@ -7652,8 +7709,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.dig_in_nid = ALC883_DIGIN_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+@@ -7665,8 +7720,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.dig_in_nid = ALC883_DIGIN_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ 		.channel_mode = alc883_3ST_6ch_modes,
+@@ -7678,8 +7731,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.init_verbs = { alc883_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ 		.channel_mode = alc883_3ST_6ch_modes,
+ 		.need_dac_fix = 1,
+@@ -7691,8 +7742,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.dig_in_nid = ALC883_DIGIN_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+ 		.channel_mode = alc883_sixstack_modes,
+@@ -7704,8 +7753,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ 		.channel_mode = alc883_3ST_6ch_modes,
+ 		.need_dac_fix = 1,
+@@ -7719,8 +7766,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+ 		.input_mux = &alc883_capture_source,
+@@ -7737,8 +7782,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+ 		.input_mux = &alc883_capture_source,
+@@ -7749,8 +7792,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+ 		.input_mux = &alc883_capture_source,
+@@ -7764,8 +7805,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 				alc883_medion_eapd_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+ 		.channel_mode = alc883_sixstack_modes,
+ 		.input_mux = &alc883_capture_source,
+@@ -7776,8 +7815,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+ 		.input_mux = &alc883_capture_source,
+@@ -7789,19 +7826,27 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+ 		.input_mux = &alc883_capture_source,
+ 	},
++	[ALC883_CLEVO_M720] = {
++		.mixers = { alc883_clevo_m720_mixer },
++		.init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
++		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
++		.dac_nids = alc883_dac_nids,
++		.dig_out_nid = ALC883_DIGOUT_NID,
++		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
++		.channel_mode = alc883_3ST_2ch_modes,
++		.input_mux = &alc883_capture_source,
++		.unsol_event = alc883_clevo_m720_unsol_event,
++		.init_hook = alc883_clevo_m720_automute,
++	},
+ 	[ALC883_LENOVO_101E_2ch] = {
+ 		.mixers = { alc883_lenovo_101e_2ch_mixer},
+ 		.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+ 		.input_mux = &alc883_lenovo_101e_capture_source,
+@@ -7813,8 +7858,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+ 		.need_dac_fix = 1,
+@@ -7828,8 +7871,6 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ 		.channel_mode = alc883_3ST_6ch_modes,
+ 		.need_dac_fix = 1,
+@@ -7843,47 +7884,28 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+ 		.input_mux = &alc883_capture_source,
+ 		.unsol_event = alc883_haier_w66_unsol_event,
+ 		.init_hook = alc883_haier_w66_automute,
+-	},	
+-	[ALC888_6ST_HP] = {
+-		.mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer },
+-		.init_verbs = { alc883_init_verbs, alc888_6st_hp_verbs },
+-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+-		.dac_nids = alc883_dac_nids,
+-		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+-		.dig_in_nid = ALC883_DIGIN_NID,
+-		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+-		.channel_mode = alc883_sixstack_modes,
+-		.input_mux = &alc883_capture_source,
+ 	},
+ 	[ALC888_3ST_HP] = {
+-		.mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer },
++		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
+ 		.init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
+ 		.channel_mode = alc888_3st_hp_modes,
+ 		.need_dac_fix = 1,
+ 		.input_mux = &alc883_capture_source,
+ 	},
+ 	[ALC888_6ST_DELL] = {
+-		.mixers = { alc888_6st_dell_mixer, alc883_chmode_mixer },
++		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
+ 		.init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+ 		.dig_out_nid = ALC883_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.dig_in_nid = ALC883_DIGIN_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+ 		.channel_mode = alc883_sixstack_modes,
+@@ -7896,14 +7918,25 @@ static struct alc_config_preset alc883_presets[] = {
+ 		.init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ 		.dac_nids = alc883_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+-		.adc_nids = alc883_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ 		.channel_mode = alc883_3ST_2ch_modes,
+ 		.input_mux = &alc883_capture_source,
+ 		.unsol_event = alc883_mitac_unsol_event,
+ 		.init_hook = alc883_mitac_automute,
+ 	},
++	[ALC883_FUJITSU_PI2515] = {
++		.mixers = { alc883_2ch_fujitsu_pi2515_mixer },
++		.init_verbs = { alc883_init_verbs,
++				alc883_2ch_fujitsu_pi2515_verbs},
++		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
++		.dac_nids = alc883_dac_nids,
++		.dig_out_nid = ALC883_DIGOUT_NID,
++		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
++		.channel_mode = alc883_3ST_2ch_modes,
++		.input_mux = &alc883_fujitsu_pi2515_capture_source,
++		.unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event,
++		.init_hook = alc883_2ch_fujitsu_pi2515_automute,
++	},
+ };
+ 
+ 
+@@ -7918,15 +7951,11 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
+ 	struct alc_spec *spec = codec->spec;
+ 	int idx;
+ 
++	alc_set_pin_output(codec, nid, pin_type);
+ 	if (spec->multiout.dac_nids[dac_idx] == 0x25)
+ 		idx = 4;
+ 	else
+ 		idx = spec->multiout.dac_nids[dac_idx] - 2;
+-
+-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+-			    pin_type);
+-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+-			    AMP_OUT_UNMUTE);
+ 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
+ 
+ }
+@@ -7955,6 +7984,9 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec)
+ 	if (pin) /* connect to front */
+ 		/* use dac 0 */
+ 		alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
++	pin = spec->autocfg.speaker_pins[0];
++	if (pin)
++		alc883_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+ 
+ #define alc883_is_input_pin(nid)	alc880_is_input_pin(nid)
+@@ -8006,9 +8038,12 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc883_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc883_auto_init_multi_out(codec);
+ 	alc883_auto_init_hp_out(codec);
+ 	alc883_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
+ static int patch_alc883(struct hda_codec *codec)
+@@ -8057,10 +8092,9 @@ static int patch_alc883(struct hda_codec *codec)
+ 	spec->stream_digital_playback = &alc883_pcm_digital_playback;
+ 	spec->stream_digital_capture = &alc883_pcm_digital_capture;
+ 
+-	if (!spec->adc_nids && spec->input_mux) {
+-		spec->adc_nids = alc883_adc_nids;
+-		spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
+-	}
++	spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
++	spec->adc_nids = alc883_adc_nids;
++	spec->capsrc_nids = alc883_capsrc_nids;
+ 
+ 	spec->vmaster_nid = 0x0c;
+ 
+@@ -8085,6 +8119,8 @@ static int patch_alc883(struct hda_codec *codec)
+ #define alc262_dac_nids		alc260_dac_nids
+ #define alc262_adc_nids		alc882_adc_nids
+ #define alc262_adc_nids_alt	alc882_adc_nids_alt
++#define alc262_capsrc_nids	alc882_capsrc_nids
++#define alc262_capsrc_nids_alt	alc882_capsrc_nids_alt
+ 
+ #define alc262_modes		alc260_modes
+ #define alc262_capture_source	alc882_capture_source
+@@ -8585,7 +8621,8 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
+ 
+ /*
+  * fujitsu model
+- *  0x14 = headphone/spdif-out, 0x15 = internal speaker
++ *  0x14 = headphone/spdif-out, 0x15 = internal speaker,
++ *  0x1b = port replicator headphone out
+  */
+ 
+ #define ALC_HP_EVENT	0x37
+@@ -8593,6 +8630,14 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
+ static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
+ 	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+ 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
++	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++	{}
++};
++
++static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
++	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
++	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ 	{}
+ };
+ 
+@@ -8633,12 +8678,16 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
+ 	unsigned int mute;
+ 
+ 	if (force || !spec->sense_updated) {
+-		unsigned int present;
++		unsigned int present_int_hp, present_dock_hp;
+ 		/* need to execute and sync at first */
+ 		snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
+-		present = snd_hda_codec_read(codec, 0x14, 0,
+-				    	 AC_VERB_GET_PIN_SENSE, 0);
+-		spec->jack_present = (present & 0x80000000) != 0;
++		present_int_hp = snd_hda_codec_read(codec, 0x14, 0,
++					AC_VERB_GET_PIN_SENSE, 0);
++		snd_hda_codec_read(codec, 0x1B, 0, AC_VERB_SET_PIN_SENSE, 0);
++		present_dock_hp = snd_hda_codec_read(codec, 0x1b, 0,
++					AC_VERB_GET_PIN_SENSE, 0);
++		spec->jack_present = (present_int_hp & 0x80000000) != 0;
++		spec->jack_present |= (present_dock_hp & 0x80000000) != 0;
+ 		spec->sense_updated = 1;
+ 	}
+ 	if (spec->jack_present) {
+@@ -8672,6 +8721,46 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
+ 	},
+ };
+ 
++/* mute/unmute internal speaker according to the hp jack and mute state */
++static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
++{
++	struct alc_spec *spec = codec->spec;
++	unsigned int mute;
++
++	if (force || !spec->sense_updated) {
++		unsigned int present_int_hp;
++		/* need to execute and sync at first */
++		snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
++		present_int_hp = snd_hda_codec_read(codec, 0x1b, 0,
++					AC_VERB_GET_PIN_SENSE, 0);
++		spec->jack_present = (present_int_hp & 0x80000000) != 0;
++		spec->sense_updated = 1;
++	}
++	if (spec->jack_present) {
++		/* mute internal speaker */
++		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++					 HDA_AMP_MUTE, HDA_AMP_MUTE);
++		snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
++					 HDA_AMP_MUTE, HDA_AMP_MUTE);
++	} else {
++		/* unmute internal speaker if necessary */
++		mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
++		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++					 HDA_AMP_MUTE, mute);
++		snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
++					 HDA_AMP_MUTE, mute);
++	}
++}
++
++/* unsolicited event for HP jack sensing */
++static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
++				       unsigned int res)
++{
++	if ((res >> 26) != ALC_HP_EVENT)
++		return;
++	alc262_lenovo_3000_automute(codec, 1);
++}
++
+ /* bind hp and internal speaker mute (with plug check) */
+ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
+ 					 struct snd_ctl_elem_value *ucontrol)
+@@ -8680,12 +8769,13 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
+ 	long *valp = ucontrol->value.integer.value;
+ 	int change;
+ 
+-	change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+-					  HDA_AMP_MUTE,
+-					  valp[0] ? 0 : HDA_AMP_MUTE);
+-	change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+-					   HDA_AMP_MUTE,
+-					   valp[1] ? 0 : HDA_AMP_MUTE);
++	change = snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++						 HDA_AMP_MUTE,
++						 valp ? 0 : HDA_AMP_MUTE);
++	change |= snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
++						 HDA_AMP_MUTE,
++						 valp ? 0 : HDA_AMP_MUTE);
++
+ 	if (change)
+ 		alc262_fujitsu_automute(codec, 0);
+ 	return change;
+@@ -8703,6 +8793,46 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
+ 	},
+ 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
++	HDA_CODEC_VOLUME("PC Speaker Volume", 0x0b, 0x05, HDA_INPUT),
++	HDA_CODEC_MUTE("PC Speaker Switch", 0x0b, 0x05, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
++	{ } /* end */
++};
++
++/* bind hp and internal speaker mute (with plug check) */
++static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
++					 struct snd_ctl_elem_value *ucontrol)
++{
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	long *valp = ucontrol->value.integer.value;
++	int change;
++
++	change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
++						 HDA_AMP_MUTE,
++						 valp ? 0 : HDA_AMP_MUTE);
++
++	if (change)
++		alc262_lenovo_3000_automute(codec, 0);
++	return change;
++}
++
++static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
++	HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Master Playback Switch",
++		.info = snd_hda_mixer_amp_switch_info,
++		.get = snd_hda_mixer_amp_switch_get,
++		.put = alc262_lenovo_3000_master_sw_put,
++		.private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
++	},
++	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
++	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+@@ -8730,59 +8860,72 @@ static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
+ 
+ /* Samsung Q1 Ultra Vista model setup */
+ static struct snd_kcontrol_new alc262_ultra_mixer[] = {
+-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+ 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT),
+ 	{ } /* end */
+ };
+ 
+ static struct hda_verb alc262_ultra_verbs[] = {
+-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
++	/* output mixer */
++	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
++	/* speaker */
++	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
++	/* HP */
+ 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+-	/* Mic is on Node 0x19 */
+-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
+-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+-	{0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
+-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+-	{0x24, AC_VERB_SET_CONNECT_SEL, 0x01},
+-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
++	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
++	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
++	/* internal mic */
++	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	/* ADC, choose mic */
++	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
++	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
++	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
++	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
++	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
++	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
++	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
+ 	{}
+ };
+ 
+-static struct hda_input_mux alc262_ultra_capture_source = {
+-	.num_items = 1,
+-	.items = {
+-		{ "Mic", 0x1 },
+-	},
+-};
+-
+ /* mute/unmute internal speaker according to the hp jack and mute state */
+ static void alc262_ultra_automute(struct hda_codec *codec)
+ {
+ 	struct alc_spec *spec = codec->spec;
+ 	unsigned int mute;
+-	unsigned int present;
+ 
+-	/* need to execute and sync at first */
+-	snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
+-	present = snd_hda_codec_read(codec, 0x15, 0,
+-				     AC_VERB_GET_PIN_SENSE, 0);
+-	spec->jack_present = (present & 0x80000000) != 0;
+-	if (spec->jack_present) {
+-		/* mute internal speaker */
+-		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+-					 HDA_AMP_MUTE, HDA_AMP_MUTE);
+-	} else {
+-		/* unmute internal speaker if necessary */
+-		mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
+-		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+-					 HDA_AMP_MUTE, mute);
++	mute = 0;
++	/* auto-mute only when HP is used as HP */
++	if (!spec->cur_mux[0]) {
++		unsigned int present;
++		/* need to execute and sync at first */
++		snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
++		present = snd_hda_codec_read(codec, 0x15, 0,
++					     AC_VERB_GET_PIN_SENSE, 0);
++		spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
++		if (spec->jack_present)
++			mute = HDA_AMP_MUTE;
+ 	}
++	/* mute/unmute internal speaker */
++	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++				 HDA_AMP_MUTE, mute);
++	/* mute/unmute HP */
++	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
++				 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
+ }
+ 
+ /* unsolicited event for HP jack sensing */
+@@ -8794,6 +8937,45 @@ static void alc262_ultra_unsol_event(struct hda_codec *codec,
+ 	alc262_ultra_automute(codec);
+ }
+ 
++static struct hda_input_mux alc262_ultra_capture_source = {
++	.num_items = 2,
++	.items = {
++		{ "Mic", 0x1 },
++		{ "Headphone", 0x7 },
++	},
++};
++
++static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
++				     struct snd_ctl_elem_value *ucontrol)
++{
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	struct alc_spec *spec = codec->spec;
++	int ret;
++
++	ret = alc882_mux_enum_put(kcontrol, ucontrol);
++	if (!ret)
++		return 0;
++	/* reprogram the HP pin as mic or HP according to the input source */
++	snd_hda_codec_write_cache(codec, 0x15, 0,
++				  AC_VERB_SET_PIN_WIDGET_CONTROL,
++				  spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
++	alc262_ultra_automute(codec); /* mute/unmute HP */
++	return ret;
++}
++
++static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
++	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Capture Source",
++		.info = alc882_mux_enum_info,
++		.get = alc882_mux_enum_get,
++		.put = alc262_ultra_mux_enum_put,
++	},
++	{ } /* end */
++};
++
+ /* add playback controls from the parsed DAC table */
+ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
+ 					     const struct auto_pin_cfg *cfg)
+@@ -9185,9 +9367,12 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
+ /* init callback for auto-configuration model -- overriding the default init */
+ static void alc262_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc262_auto_init_multi_out(codec);
+ 	alc262_auto_init_hp_out(codec);
+ 	alc262_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
+ /*
+@@ -9206,6 +9391,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = {
+ 	[ALC262_BENQ_T31]	= "benq-t31",
+ 	[ALC262_SONY_ASSAMD]	= "sony-assamd",
+ 	[ALC262_ULTRA]		= "ultra",
++	[ALC262_LENOVO_3000]	= "lenovo-3000",
+ 	[ALC262_AUTO]		= "auto",
+ };
+ 
+@@ -9241,6 +9427,8 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
+ 	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
+ 	SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
+ 	SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
++	SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA),
++	SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
+ 	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
+ 	SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
+ 	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
+@@ -9390,18 +9578,32 @@ static struct alc_config_preset alc262_presets[] = {
+ 		.init_hook = alc262_hippo_automute,
+ 	},	
+ 	[ALC262_ULTRA] = {
+-		.mixers = { alc262_ultra_mixer },
+-		.init_verbs = { alc262_init_verbs, alc262_ultra_verbs },
++		.mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer },
++		.init_verbs = { alc262_ultra_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+ 		.dac_nids = alc262_dac_nids,
+-		.hp_nid = 0x03,
+-		.dig_out_nid = ALC262_DIGOUT_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+ 		.channel_mode = alc262_modes,
+ 		.input_mux = &alc262_ultra_capture_source,
++		.adc_nids = alc262_adc_nids, /* ADC0 */
++		.capsrc_nids = alc262_capsrc_nids,
++		.num_adc_nids = 1, /* single ADC */
+ 		.unsol_event = alc262_ultra_unsol_event,
+ 		.init_hook = alc262_ultra_automute,
+ 	},
++	[ALC262_LENOVO_3000] = {
++		.mixers = { alc262_lenovo_3000_mixer },
++		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
++				alc262_lenovo_3000_unsol_verbs },
++		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
++		.dac_nids = alc262_dac_nids,
++		.hp_nid = 0x03,
++		.dig_out_nid = ALC262_DIGOUT_NID,
++		.num_channel_mode = ARRAY_SIZE(alc262_modes),
++		.channel_mode = alc262_modes,
++		.input_mux = &alc262_fujitsu_capture_source,
++		.unsol_event = alc262_lenovo_3000_unsol_event,
++	},
+ };
+ 
+ static int patch_alc262(struct hda_codec *codec)
+@@ -9472,12 +9674,14 @@ static int patch_alc262(struct hda_codec *codec)
+ 		if (wcap != AC_WID_AUD_IN) {
+ 			spec->adc_nids = alc262_adc_nids_alt;
+ 			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
++			spec->capsrc_nids = alc262_capsrc_nids_alt;
+ 			spec->mixers[spec->num_mixers] =
+ 				alc262_capture_alt_mixer;
+ 			spec->num_mixers++;
+ 		} else {
+ 			spec->adc_nids = alc262_adc_nids;
+ 			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
++			spec->capsrc_nids = alc262_capsrc_nids;
+ 			spec->mixers[spec->num_mixers] = alc262_capture_mixer;
+ 			spec->num_mixers++;
+ 		}
+@@ -9517,6 +9721,8 @@ static hda_nid_t alc268_adc_nids_alt[1] = {
+ 	0x08
+ };
+ 
++static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
++
+ static struct snd_kcontrol_new alc268_base_mixer[] = {
+ 	/* output mixer control */
+ 	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+@@ -9529,6 +9735,22 @@ static struct snd_kcontrol_new alc268_base_mixer[] = {
+ 	{ }
+ };
+ 
++/* bind Beep switches of both NID 0x0f and 0x10 */
++static struct hda_bind_ctls alc268_bind_beep_sw = {
++	.ops = &snd_hda_bind_sw,
++	.values = {
++		HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
++		HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
++		0
++	},
++};
++
++static struct snd_kcontrol_new alc268_beep_mixer[] = {
++	HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
++	HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
++	{ }
++};
++
+ static struct hda_verb alc268_eapd_verbs[] = {
+ 	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+ 	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+@@ -9613,8 +9835,12 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
+ };
+ 
+ static struct hda_verb alc268_acer_verbs[] = {
++	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
++	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ 
+ 	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ 	{ }
+@@ -9685,6 +9911,64 @@ static void alc268_dell_unsol_event(struct hda_codec *codec,
+ 
+ #define alc268_dell_init_hook	alc268_dell_automute
+ 
++static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
++	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
++	HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++	{ }
++};
++
++static struct hda_verb alc267_quanta_il1_verbs[] = {
++	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
++	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
++	{ }
++};
++
++static void alc267_quanta_il1_hp_automute(struct hda_codec *codec)
++{
++	unsigned int present;
++
++	present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
++		& AC_PINSENSE_PRESENCE;
++	snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
++			    present ? 0 : PIN_OUT);
++}
++
++static void alc267_quanta_il1_mic_automute(struct hda_codec *codec)
++{
++	unsigned int present;
++
++	present = snd_hda_codec_read(codec, 0x18, 0,
++				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
++	snd_hda_codec_write(codec, 0x23, 0,
++			    AC_VERB_SET_CONNECT_SEL,
++			    present ? 0x00 : 0x01);
++}
++
++static void alc267_quanta_il1_automute(struct hda_codec *codec)
++{
++	alc267_quanta_il1_hp_automute(codec);
++	alc267_quanta_il1_mic_automute(codec);
++}
++
++static void alc267_quanta_il1_unsol_event(struct hda_codec *codec,
++					   unsigned int res)
++{
++	switch (res >> 26) {
++	case ALC880_HP_EVENT:
++		alc267_quanta_il1_hp_automute(codec);
++		break;
++	case ALC880_MIC_EVENT:
++		alc267_quanta_il1_mic_automute(codec);
++		break;
++	}
++}
++
+ /*
+  * generic initialization of ADC, input mixers and output mixers
+  */
+@@ -9725,7 +10009,11 @@ static struct hda_verb alc268_base_init_verbs[] = {
+ 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ 	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
++
++	/* set PCBEEP vol = 0, mute connections */
++	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ 
+ 	/* Unmute Selector 23h,24h and set the default input to mic-in */
+ 	
+@@ -9764,29 +10052,17 @@ static struct hda_verb alc268_volume_init_verbs[] = {
+ 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ 	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ 
+-	/* set PCBEEP vol = 0 */
+-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))},
++	/* set PCBEEP vol = 0, mute connections */
++	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ 
+ 	{ }
+ };
+ 
+ #define alc268_mux_enum_info alc_mux_enum_info
+ #define alc268_mux_enum_get alc_mux_enum_get
+-
+-static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol,
+-			       struct snd_ctl_elem_value *ucontrol)
+-{
+-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+-	struct alc_spec *spec = codec->spec;
+-
+-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+-	static hda_nid_t capture_mixers[3] = { 0x23, 0x24 };
+-	hda_nid_t nid = capture_mixers[adc_idx];
+-
+-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+-				     nid,
+-				     &spec->cur_mux[adc_idx]);
+-}
++#define alc268_mux_enum_put alc_mux_enum_put
+ 
+ static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
+ 	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+@@ -9836,13 +10112,17 @@ static struct hda_input_mux alc268_capture_source = {
+ 	},
+ };
+ 
++static struct hda_input_mux alc268_acer_capture_source = {
++	.num_items = 3,
++	.items = {
++		{ "Mic", 0x0 },
++		{ "Internal Mic", 0x6 },
++		{ "Line", 0x2 },
++	},
++};
++
+ #ifdef CONFIG_SND_DEBUG
+ static struct snd_kcontrol_new alc268_test_mixer[] = {
+-	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+-
+ 	/* Volume widgets */
+ 	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+@@ -9981,6 +10261,10 @@ static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
+ 		case 0x1c:	
+ 			idx1 = 3;	/* CD */
+ 			break;
++		case 0x12:
++		case 0x13:
++			idx1 = 6;	/* digital mics */
++			break;
+ 		default:
+ 			continue;
+ 		}
+@@ -10073,6 +10357,9 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
+ 	if (spec->kctl_alloc)
+ 		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ 
++	if (spec->autocfg.speaker_pins[0] != 0x1d)
++		spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
++
+ 	spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;
+ 	spec->num_mux_defs = 1;
+ 	spec->input_mux = &spec->private_imux;
+@@ -10091,20 +10378,25 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
+ /* init callback for auto-configuration model -- overriding the default init */
+ static void alc268_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc268_auto_init_multi_out(codec);
+ 	alc268_auto_init_hp_out(codec);
+ 	alc268_auto_init_mono_speaker_out(codec);
+ 	alc268_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
+ /*
+  * configuration and preset
+  */
+ static const char *alc268_models[ALC268_MODEL_LAST] = {
++	[ALC267_QUANTA_IL1]	= "quanta-il1",
+ 	[ALC268_3ST]		= "3stack",
+ 	[ALC268_TOSHIBA]	= "toshiba",
+ 	[ALC268_ACER]		= "acer",
+ 	[ALC268_DELL]		= "dell",
++	[ALC268_ZEPTO]		= "zepto",
+ #ifdef CONFIG_SND_DEBUG
+ 	[ALC268_TEST]		= "test",
+ #endif
+@@ -10112,6 +10404,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
+ };
+ 
+ static struct snd_pci_quirk alc268_cfg_tbl[] = {
++	SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
+ 	SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
+ 	SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
+ 	SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
+@@ -10122,17 +10415,36 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
+ 	SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
+ 	SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA),
+ 	SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
++	SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
++	SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
+ 	{}
+ };
+ 
+ static struct alc_config_preset alc268_presets[] = {
++	[ALC267_QUANTA_IL1] = {
++		.mixers = { alc267_quanta_il1_mixer },
++		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
++				alc267_quanta_il1_verbs },
++		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
++		.dac_nids = alc268_dac_nids,
++		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
++		.adc_nids = alc268_adc_nids_alt,
++		.hp_nid = 0x03,
++		.num_channel_mode = ARRAY_SIZE(alc268_modes),
++		.channel_mode = alc268_modes,
++		.input_mux = &alc268_capture_source,
++		.unsol_event = alc267_quanta_il1_unsol_event,
++		.init_hook = alc267_quanta_il1_automute,
++	},
+ 	[ALC268_3ST] = {
+-		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
++		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
++			    alc268_beep_mixer },
+ 		.init_verbs = { alc268_base_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ 		.dac_nids = alc268_dac_nids,
+                 .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+                 .adc_nids = alc268_adc_nids_alt,
++		.capsrc_nids = alc268_capsrc_nids,
+ 		.hp_nid = 0x03,
+ 		.dig_out_nid = ALC268_DIGOUT_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+@@ -10140,13 +10452,15 @@ static struct alc_config_preset alc268_presets[] = {
+ 		.input_mux = &alc268_capture_source,
+ 	},
+ 	[ALC268_TOSHIBA] = {
+-		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
++		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
++			    alc268_beep_mixer },
+ 		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ 				alc268_toshiba_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ 		.dac_nids = alc268_dac_nids,
+ 		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ 		.adc_nids = alc268_adc_nids_alt,
++		.capsrc_nids = alc268_capsrc_nids,
+ 		.hp_nid = 0x03,
+ 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+ 		.channel_mode = alc268_modes,
+@@ -10155,22 +10469,24 @@ static struct alc_config_preset alc268_presets[] = {
+ 		.init_hook = alc268_toshiba_automute,
+ 	},
+ 	[ALC268_ACER] = {
+-		.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer },
++		.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
++			    alc268_beep_mixer },
+ 		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ 				alc268_acer_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ 		.dac_nids = alc268_dac_nids,
+ 		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ 		.adc_nids = alc268_adc_nids_alt,
++		.capsrc_nids = alc268_capsrc_nids,
+ 		.hp_nid = 0x02,
+ 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+ 		.channel_mode = alc268_modes,
+-		.input_mux = &alc268_capture_source,
++		.input_mux = &alc268_acer_capture_source,
+ 		.unsol_event = alc268_acer_unsol_event,
+ 		.init_hook = alc268_acer_init_hook,
+ 	},
+ 	[ALC268_DELL] = {
+-		.mixers = { alc268_dell_mixer },
++		.mixers = { alc268_dell_mixer, alc268_beep_mixer },
+ 		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ 				alc268_dell_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+@@ -10182,6 +10498,24 @@ static struct alc_config_preset alc268_presets[] = {
+ 		.init_hook = alc268_dell_init_hook,
+ 		.input_mux = &alc268_capture_source,
+ 	},
++	[ALC268_ZEPTO] = {
++		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
++			    alc268_beep_mixer },
++		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
++				alc268_toshiba_verbs },
++		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
++		.dac_nids = alc268_dac_nids,
++		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
++		.adc_nids = alc268_adc_nids_alt,
++		.capsrc_nids = alc268_capsrc_nids,
++		.hp_nid = 0x03,
++		.dig_out_nid = ALC268_DIGOUT_NID,
++		.num_channel_mode = ARRAY_SIZE(alc268_modes),
++		.channel_mode = alc268_modes,
++		.input_mux = &alc268_capture_source,
++		.unsol_event = alc268_toshiba_unsol_event,
++		.init_hook = alc268_toshiba_automute
++	},
+ #ifdef CONFIG_SND_DEBUG
+ 	[ALC268_TEST] = {
+ 		.mixers = { alc268_test_mixer, alc268_capture_mixer },
+@@ -10191,6 +10525,7 @@ static struct alc_config_preset alc268_presets[] = {
+ 		.dac_nids = alc268_dac_nids,
+ 		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ 		.adc_nids = alc268_adc_nids_alt,
++		.capsrc_nids = alc268_capsrc_nids,
+ 		.hp_nid = 0x03,
+ 		.dig_out_nid = ALC268_DIGOUT_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+@@ -10247,13 +10582,22 @@ static int patch_alc268(struct hda_codec *codec)
+ 	spec->stream_name_digital = "ALC268 Digital";
+ 	spec->stream_digital_playback = &alc268_pcm_digital_playback;
+ 
++	if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
++		/* override the amp caps for beep generator */
++		snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
++					  (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
++					  (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
++					  (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
++					  (0 << AC_AMPCAP_MUTE_SHIFT));
++
+ 	if (!spec->adc_nids && spec->input_mux) {
+ 		/* check whether NID 0x07 is valid */
+ 		unsigned int wcap = get_wcaps(codec, 0x07);
++		int i;
+ 
+ 		/* get type */
+ 		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+-		if (wcap != AC_WID_AUD_IN) {
++		if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
+ 			spec->adc_nids = alc268_adc_nids_alt;
+ 			spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
+ 			spec->mixers[spec->num_mixers] =
+@@ -10266,6 +10610,12 @@ static int patch_alc268(struct hda_codec *codec)
+ 				alc268_capture_mixer;
+ 			spec->num_mixers++;
+ 		}
++		spec->capsrc_nids = alc268_capsrc_nids;
++		/* set default input source */
++		for (i = 0; i < spec->num_adc_nids; i++)
++			snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
++				0, AC_VERB_SET_CONNECT_SEL,
++				spec->input_mux->items[0].index);
+ 	}
+ 
+ 	spec->vmaster_nid = 0x02;
+@@ -10539,9 +10889,12 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
+ /* init callback for auto-configuration model -- overriding the default init */
+ static void alc269_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc269_auto_init_multi_out(codec);
+ 	alc269_auto_init_hp_out(codec);
+ 	alc269_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
+ /*
+@@ -11463,13 +11816,7 @@ static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
+ 					      hda_nid_t nid,
+ 					      int pin_type, int dac_idx)
+ {
+-	/* set as output */
+-
+-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+-			    pin_type);
+-	snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+-			    AMP_OUT_UNMUTE);
+-
++	alc_set_pin_output(codec, nid, pin_type);
+ }
+ 
+ static void alc861_auto_init_multi_out(struct hda_codec *codec)
+@@ -11496,6 +11843,9 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec)
+ 	if (pin) /* connect to front */
+ 		alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,
+ 						  spec->multiout.dac_nids[0]);
++	pin = spec->autocfg.speaker_pins[0];
++	if (pin)
++		alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+ 
+ static void alc861_auto_init_analog_input(struct hda_codec *codec)
+@@ -11568,9 +11918,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc861_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc861_auto_init_multi_out(codec);
+ 	alc861_auto_init_hp_out(codec);
+ 	alc861_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+@@ -11822,6 +12175,8 @@ static hda_nid_t alc861vd_adc_nids[1] = {
+ 	0x09,
+ };
+ 
++static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
++
+ /* input MUX */
+ /* FIXME: should be a matrix-type input source selection */
+ static struct hda_input_mux alc861vd_capture_source = {
+@@ -11835,11 +12190,10 @@ static struct hda_input_mux alc861vd_capture_source = {
+ };
+ 
+ static struct hda_input_mux alc861vd_dallas_capture_source = {
+-	.num_items = 3,
++	.num_items = 2,
+ 	.items = {
+-		{ "Front Mic", 0x0 },
+-		{ "ATAPI Mic", 0x1 },
+-		{ "Line In", 0x5 },
++		{ "Ext Mic", 0x0 },
++		{ "Int Mic", 0x1 },
+ 	},
+ };
+ 
+@@ -11853,33 +12207,8 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
+ 
+ #define alc861vd_mux_enum_info alc_mux_enum_info
+ #define alc861vd_mux_enum_get alc_mux_enum_get
+-
+-static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
+-				struct snd_ctl_elem_value *ucontrol)
+-{
+-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+-	struct alc_spec *spec = codec->spec;
+-	const struct hda_input_mux *imux = spec->input_mux;
+-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+-	static hda_nid_t capture_mixers[1] = { 0x22 };
+-	hda_nid_t nid = capture_mixers[adc_idx];
+-	unsigned int *cur_val = &spec->cur_mux[adc_idx];
+-	unsigned int i, idx;
+-
+-	idx = ucontrol->value.enumerated.item[0];
+-	if (idx >= imux->num_items)
+-		idx = imux->num_items - 1;
+-	if (*cur_val == idx)
+-		return 0;
+-	for (i = 0; i < imux->num_items; i++) {
+-		unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+-		snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+-					 imux->items[i].index,
+-					 HDA_AMP_MUTE, v);
+-	}
+-	*cur_val = idx;
+-	return 1;
+-}
++/* ALC861VD has the ALC882-type input selection (but has only one ADC) */
++#define alc861vd_mux_enum_put alc882_mux_enum_put
+ 
+ /*
+  * 2ch mode
+@@ -12034,20 +12363,22 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
+ 	{ } /* end */
+ };
+ 
+-/* Pin assignment: Front=0x14, HP = 0x15,
+- *                 Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d
++/* Pin assignment: Speaker=0x14, HP = 0x15,
++ *                 Ext Mic=0x18, Int Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
+  */
+ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
+-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
++	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
++	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+ 	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+-	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+-	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT),
+-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT),
++	HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
++	HDA_CODEC_VOLUME("PC Beep Volume", 0x0b, 0x05, HDA_INPUT),
++	HDA_CODEC_MUTE("PC Beep Switch", 0x0b, 0x05, HDA_INPUT),
+ 	{ } /* end */
+ };
+ 
+@@ -12348,6 +12679,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
+ 	/*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
+ 	SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
+ 	SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
++	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
+ 	SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
+ 	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
+ 	SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
+@@ -12362,8 +12694,6 @@ static struct alc_config_preset alc861vd_presets[] = {
+ 				 alc861vd_3stack_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+ 		.dac_nids = alc660vd_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+-		.adc_nids = alc861vd_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ 		.channel_mode = alc861vd_3stack_2ch_modes,
+ 		.input_mux = &alc861vd_capture_source,
+@@ -12375,8 +12705,6 @@ static struct alc_config_preset alc861vd_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+ 		.dac_nids = alc660vd_dac_nids,
+ 		.dig_out_nid = ALC861VD_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+-		.adc_nids = alc861vd_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ 		.channel_mode = alc861vd_3stack_2ch_modes,
+ 		.input_mux = &alc861vd_capture_source,
+@@ -12421,8 +12749,6 @@ static struct alc_config_preset alc861vd_presets[] = {
+ 				alc861vd_lenovo_unsol_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+ 		.dac_nids = alc660vd_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+-		.adc_nids = alc861vd_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ 		.channel_mode = alc861vd_3stack_2ch_modes,
+ 		.input_mux = &alc861vd_capture_source,
+@@ -12434,8 +12760,6 @@ static struct alc_config_preset alc861vd_presets[] = {
+ 		.init_verbs = { alc861vd_dallas_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+ 		.dac_nids = alc861vd_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+-		.adc_nids = alc861vd_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ 		.channel_mode = alc861vd_3stack_2ch_modes,
+ 		.input_mux = &alc861vd_dallas_capture_source,
+@@ -12447,9 +12771,7 @@ static struct alc_config_preset alc861vd_presets[] = {
+ 		.init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+ 		.dac_nids = alc861vd_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+ 		.dig_out_nid = ALC861VD_DIGOUT_NID,
+-		.adc_nids = alc861vd_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ 		.channel_mode = alc861vd_3stack_2ch_modes,
+ 		.input_mux = &alc861vd_hp_capture_source,
+@@ -12464,11 +12786,7 @@ static struct alc_config_preset alc861vd_presets[] = {
+ static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
+ 				hda_nid_t nid, int pin_type, int dac_idx)
+ {
+-	/* set as output */
+-	snd_hda_codec_write(codec, nid, 0,
+-				AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+-	snd_hda_codec_write(codec, nid, 0,
+-				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
++	alc_set_pin_output(codec, nid, pin_type);
+ }
+ 
+ static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
+@@ -12495,6 +12813,9 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
+ 	pin = spec->autocfg.hp_pins[0];
+ 	if (pin) /* connect to front and  use dac 0 */
+ 		alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
++	pin = spec->autocfg.speaker_pins[0];
++	if (pin)
++		alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+ 
+ #define alc861vd_is_input_pin(nid)	alc880_is_input_pin(nid)
+@@ -12698,9 +13019,12 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc861vd_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc861vd_auto_init_multi_out(codec);
+ 	alc861vd_auto_init_hp_out(codec);
+ 	alc861vd_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
+ static int patch_alc861vd(struct hda_codec *codec)
+@@ -12751,6 +13075,7 @@ static int patch_alc861vd(struct hda_codec *codec)
+ 
+ 	spec->adc_nids = alc861vd_adc_nids;
+ 	spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
++	spec->capsrc_nids = alc861vd_capsrc_nids;
+ 
+ 	spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
+ 	spec->num_mixers++;
+@@ -12792,9 +13117,11 @@ static hda_nid_t alc662_adc_nids[1] = {
+ 	/* ADC1-2 */
+ 	0x09,
+ };
++
++static hda_nid_t alc662_capsrc_nids[1] = { 0x22 };
++
+ /* input MUX */
+ /* FIXME: should be a matrix-type input source selection */
+-
+ static struct hda_input_mux alc662_capture_source = {
+ 	.num_items = 4,
+ 	.items = {
+@@ -12823,33 +13150,8 @@ static struct hda_input_mux alc662_eeepc_capture_source = {
+ 
+ #define alc662_mux_enum_info alc_mux_enum_info
+ #define alc662_mux_enum_get alc_mux_enum_get
++#define alc662_mux_enum_put alc882_mux_enum_put
+ 
+-static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
+-			       struct snd_ctl_elem_value *ucontrol)
+-{
+-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+-	struct alc_spec *spec = codec->spec;
+-	const struct hda_input_mux *imux = spec->input_mux;
+-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+-	static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
+-	hda_nid_t nid = capture_mixers[adc_idx];
+-	unsigned int *cur_val = &spec->cur_mux[adc_idx];
+-	unsigned int i, idx;
+-
+-	idx = ucontrol->value.enumerated.item[0];
+-	if (idx >= imux->num_items)
+-		idx = imux->num_items - 1;
+-	if (*cur_val == idx)
+-		return 0;
+-	for (i = 0; i < imux->num_items; i++) {
+-		unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+-		snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+-					 imux->items[i].index,
+-					 HDA_AMP_MUTE, v);
+-	}
+-	*cur_val = idx;
+-	return 1;
+-}
+ /*
+  * 2ch mode
+  */
+@@ -12918,13 +13220,13 @@ static struct hda_channel_mode alc662_5stack_modes[2] = {
+ static struct snd_kcontrol_new alc662_base_mixer[] = {
+ 	/* output mixer control */
+ 	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+-	HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT),
++	HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
+ 	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
+-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
++	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
+ 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ 
+ 	/*Input mixer control */
+@@ -12941,7 +13243,7 @@ static struct snd_kcontrol_new alc662_base_mixer[] = {
+ 
+ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
+ 	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
++	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
+ 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+@@ -12958,13 +13260,13 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
+ 
+ static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
+ 	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
++	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
+ 	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),
++	HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
+ 	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
+-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
+-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
++	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
++	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
+ 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+@@ -13313,6 +13615,7 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
+ };
+ 
+ static struct snd_pci_quirk alc662_cfg_tbl[] = {
++	SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
+ 	SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
+ 	SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
+ 	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
+@@ -13326,8 +13629,6 @@ static struct alc_config_preset alc662_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ 		.dac_nids = alc662_dac_nids,
+ 		.dig_out_nid = ALC662_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+-		.adc_nids = alc662_adc_nids,
+ 		.dig_in_nid = ALC662_DIGIN_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+ 		.channel_mode = alc662_3ST_2ch_modes,
+@@ -13340,8 +13641,6 @@ static struct alc_config_preset alc662_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ 		.dac_nids = alc662_dac_nids,
+ 		.dig_out_nid = ALC662_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+-		.adc_nids = alc662_adc_nids,
+ 		.dig_in_nid = ALC662_DIGIN_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+ 		.channel_mode = alc662_3ST_6ch_modes,
+@@ -13354,8 +13653,6 @@ static struct alc_config_preset alc662_presets[] = {
+ 		.init_verbs = { alc662_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ 		.dac_nids = alc662_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+-		.adc_nids = alc662_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+ 		.channel_mode = alc662_3ST_6ch_modes,
+ 		.need_dac_fix = 1,
+@@ -13368,8 +13665,6 @@ static struct alc_config_preset alc662_presets[] = {
+ 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ 		.dac_nids = alc662_dac_nids,
+ 		.dig_out_nid = ALC662_DIGOUT_NID,
+-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+-		.adc_nids = alc662_adc_nids,
+ 		.dig_in_nid = ALC662_DIGIN_NID,
+ 		.num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
+ 		.channel_mode = alc662_5stack_modes,
+@@ -13380,8 +13675,6 @@ static struct alc_config_preset alc662_presets[] = {
+ 		.init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ 		.dac_nids = alc662_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+-		.adc_nids = alc662_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+ 		.channel_mode = alc662_3ST_2ch_modes,
+ 		.input_mux = &alc662_lenovo_101e_capture_source,
+@@ -13394,8 +13687,6 @@ static struct alc_config_preset alc662_presets[] = {
+ 				alc662_eeepc_sue_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ 		.dac_nids = alc662_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+-		.adc_nids = alc662_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+ 		.channel_mode = alc662_3ST_2ch_modes,
+ 		.input_mux = &alc662_eeepc_capture_source,
+@@ -13409,8 +13700,6 @@ static struct alc_config_preset alc662_presets[] = {
+ 				alc662_eeepc_ep20_sue_init_verbs },
+ 		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ 		.dac_nids = alc662_dac_nids,
+-		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+-		.adc_nids = alc662_adc_nids,
+ 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+ 		.channel_mode = alc662_3ST_6ch_modes,
+ 		.input_mux = &alc662_lenovo_101e_capture_source,
+@@ -13556,11 +13845,7 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
+ 					      hda_nid_t nid, int pin_type,
+ 					      int dac_idx)
+ {
+-	/* set as output */
+-	snd_hda_codec_write(codec, nid, 0,
+-			    AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+-	snd_hda_codec_write(codec, nid, 0,
+-			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
++	alc_set_pin_output(codec, nid, pin_type);
+ 	/* need the manual connection? */
+ 	if (alc880_is_multi_pin(nid)) {
+ 		struct alc_spec *spec = codec->spec;
+@@ -13595,6 +13880,9 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
+ 	if (pin) /* connect to front */
+ 		/* use dac 0 */
+ 		alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
++	pin = spec->autocfg.speaker_pins[0];
++	if (pin)
++		alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+ 
+ #define alc662_is_input_pin(nid)	alc880_is_input_pin(nid)
+@@ -13672,9 +13960,12 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc662_auto_init(struct hda_codec *codec)
+ {
++	struct alc_spec *spec = codec->spec;
+ 	alc662_auto_init_multi_out(codec);
+ 	alc662_auto_init_hp_out(codec);
+ 	alc662_auto_init_analog_input(codec);
++	if (spec->unsol_event)
++		alc_sku_automute(codec);
+ }
+ 
+ static int patch_alc662(struct hda_codec *codec)
+@@ -13722,10 +14013,9 @@ static int patch_alc662(struct hda_codec *codec)
+ 	spec->stream_digital_playback = &alc662_pcm_digital_playback;
+ 	spec->stream_digital_capture = &alc662_pcm_digital_capture;
+ 
+-	if (!spec->adc_nids && spec->input_mux) {
+-		spec->adc_nids = alc662_adc_nids;
+-		spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
+-	}
++	spec->adc_nids = alc662_adc_nids;
++	spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
++	spec->capsrc_nids = alc662_capsrc_nids;
+ 
+ 	spec->vmaster_nid = 0x02;
+ 
+@@ -13761,6 +14051,8 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
+ 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
+ 	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
+ 	{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
++	{ .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
++	  .patch = patch_alc882 }, /* should be patch_alc883() in future */
+ 	{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
+ 	{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
+ 	{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
+diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
+index d22f5a6..9332b63 100644
+--- a/sound/pci/hda/patch_si3054.c
++++ b/sound/pci/hda/patch_si3054.c
+@@ -28,7 +28,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
+-
++#include "hda_patch.h"
+ 
+ /* si3054 verbs */
+ #define SI3054_VERB_READ_NODE  0x900
+@@ -206,7 +206,7 @@ static int si3054_build_pcms(struct hda_codec *codec)
+ 	info->name = "Si3054 Modem";
+ 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
+ 	info->stream[SNDRV_PCM_STREAM_CAPTURE]  = si3054_pcm;
+-	info->is_modem = 1;
++	info->pcm_type = HDA_PCM_TYPE_MODEM;
+ 	return 0;
+ }
+ 
+diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
+index caf48ed..b3a15d6 100644
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -32,6 +32,7 @@
+ #include <sound/asoundef.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+ 
+ #define NUM_CONTROL_ALLOC	32
+ #define STAC_PWR_EVENT		0x20
+@@ -39,6 +40,7 @@
+ 
+ enum {
+ 	STAC_REF,
++	STAC_9200_OQO,
+ 	STAC_9200_DELL_D21,
+ 	STAC_9200_DELL_D22,
+ 	STAC_9200_DELL_D23,
+@@ -50,6 +52,7 @@ enum {
+ 	STAC_9200_DELL_M26,
+ 	STAC_9200_DELL_M27,
+ 	STAC_9200_GATEWAY,
++	STAC_9200_PANASONIC,
+ 	STAC_9200_MODELS
+ };
+ 
+@@ -63,11 +66,14 @@ enum {
+ 
+ enum {
+ 	STAC_92HD73XX_REF,
++	STAC_DELL_M6,
+ 	STAC_92HD73XX_MODELS
+ };
+ 
+ enum {
+ 	STAC_92HD71BXX_REF,
++	STAC_DELL_M4_1,
++	STAC_DELL_M4_2,
+ 	STAC_92HD71BXX_MODELS
+ };
+ 
+@@ -123,6 +129,7 @@ struct sigmatel_spec {
+ 	unsigned int hp_detect: 1;
+ 
+ 	/* gpio lines */
++	unsigned int eapd_mask;
+ 	unsigned int gpio_mask;
+ 	unsigned int gpio_dir;
+ 	unsigned int gpio_data;
+@@ -135,6 +142,7 @@ struct sigmatel_spec {
+ 	/* power management */
+ 	unsigned int num_pwrs;
+ 	hda_nid_t *pwr_nids;
++	hda_nid_t *dac_list;
+ 
+ 	/* playback */
+ 	struct hda_input_mux *mono_mux;
+@@ -173,6 +181,7 @@ struct sigmatel_spec {
+ 	/* i/o switches */
+ 	unsigned int io_switch[2];
+ 	unsigned int clfe_swap;
++	unsigned int hp_switch;
+ 	unsigned int aloopback;
+ 
+ 	struct hda_pcm pcm_rec[2];	/* PCM information */
+@@ -184,9 +193,6 @@ struct sigmatel_spec {
+ 	struct hda_input_mux private_dimux;
+ 	struct hda_input_mux private_imux;
+ 	struct hda_input_mux private_mono_mux;
+-
+-	/* virtual master */
+-	unsigned int vmaster_tlv[4];
+ };
+ 
+ static hda_nid_t stac9200_adc_nids[1] = {
+@@ -244,7 +250,7 @@ static hda_nid_t stac92hd71bxx_dmux_nids[1] = {
+ 	0x1c,
+ };
+ 
+-static hda_nid_t stac92hd71bxx_dac_nids[2] = {
++static hda_nid_t stac92hd71bxx_dac_nids[1] = {
+ 	0x10, /*0x11, */
+ };
+ 
+@@ -290,6 +296,10 @@ static hda_nid_t stac927x_mux_nids[3] = {
+         0x15, 0x16, 0x17
+ };
+ 
++static hda_nid_t stac927x_dac_nids[6] = {
++	0x02, 0x03, 0x04, 0x05, 0x06, 0
++};
++
+ static hda_nid_t stac927x_dmux_nids[1] = {
+ 	0x1b,
+ };
+@@ -331,10 +341,10 @@ static hda_nid_t stac922x_pin_nids[10] = {
+ 	0x0f, 0x10, 0x11, 0x15, 0x1b,
+ };
+ 
+-static hda_nid_t stac92hd73xx_pin_nids[12] = {
++static hda_nid_t stac92hd73xx_pin_nids[13] = {
+ 	0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 	0x0f, 0x10, 0x11, 0x12, 0x13,
+-	0x14, 0x22
++	0x14, 0x1e, 0x22
+ };
+ 
+ static hda_nid_t stac92hd71bxx_pin_nids[10] = {
+@@ -527,6 +537,43 @@ static struct hda_verb stac92hd73xx_6ch_core_init[] = {
+ 	{}
+ };
+ 
++static struct hda_verb dell_eq_core_init[] = {
++	/* set master volume to max value without distortion
++	 * and direct control */
++	{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec},
++	/* setup audio connections */
++	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
++	{ 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02},
++	/* setup adcs to point to mixer */
++	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
++	{ 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
++	/* setup import muxs */
++	{ 0x28, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{ 0x29, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{ 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{ 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00},
++	{}
++};
++
++static struct hda_verb dell_m6_core_init[] = {
++	/* set master volume and direct control */
++	{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
++	/* setup audio connections */
++	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
++	{ 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02},
++	/* setup adcs to point to mixer */
++	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
++	{ 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
++	/* setup import muxs */
++	{ 0x28, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{ 0x29, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{ 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01},
++	{ 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00},
++	{}
++};
++
+ static struct hda_verb stac92hd73xx_8ch_core_init[] = {
+ 	/* set master volume and direct control */
+ 	{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
+@@ -910,6 +957,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
+ 		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+ 		if (err < 0)
+ 			return err;
++		err = snd_hda_create_spdif_share_sw(codec,
++						    &spec->multiout);
++		if (err < 0)
++			return err;
++		spec->multiout.share_spdif = 1;
+ 	}
+ 	if (spec->dig_in_nid) {
+ 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -919,10 +971,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
+ 
+ 	/* if we have no master control, let's create it */
+ 	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
++		unsigned int vmaster_tlv[4];
+ 		snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
+-					HDA_OUTPUT, spec->vmaster_tlv);
++					HDA_OUTPUT, vmaster_tlv);
+ 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+-					  spec->vmaster_tlv, slave_vols);
++					  vmaster_tlv, slave_vols);
+ 		if (err < 0)
+ 			return err;
+ 	}
+@@ -1052,9 +1105,15 @@ static unsigned int dell9200_m27_pin_configs[8] = {
+ 	0x90170310, 0x04a11020, 0x90170310, 0x40f003fc,
+ };
+ 
++static unsigned int oqo9200_pin_configs[8] = {
++	0x40c000f0, 0x404000f1, 0x0221121f, 0x02211210,
++	0x90170111, 0x90a70120, 0x400000f2, 0x400000f3,
++};
++
+ 
+ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
+ 	[STAC_REF] = ref9200_pin_configs,
++	[STAC_9200_OQO] = oqo9200_pin_configs,
+ 	[STAC_9200_DELL_D21] = dell9200_d21_pin_configs,
+ 	[STAC_9200_DELL_D22] = dell9200_d22_pin_configs,
+ 	[STAC_9200_DELL_D23] = dell9200_d23_pin_configs,
+@@ -1065,10 +1124,12 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
+ 	[STAC_9200_DELL_M25] = dell9200_m25_pin_configs,
+ 	[STAC_9200_DELL_M26] = dell9200_m26_pin_configs,
+ 	[STAC_9200_DELL_M27] = dell9200_m27_pin_configs,
++	[STAC_9200_PANASONIC] = ref9200_pin_configs,
+ };
+ 
+ static const char *stac9200_models[STAC_9200_MODELS] = {
+ 	[STAC_REF] = "ref",
++	[STAC_9200_OQO] = "oqo",
+ 	[STAC_9200_DELL_D21] = "dell-d21",
+ 	[STAC_9200_DELL_D22] = "dell-d22",
+ 	[STAC_9200_DELL_D23] = "dell-d23",
+@@ -1080,6 +1141,7 @@ static const char *stac9200_models[STAC_9200_MODELS] = {
+ 	[STAC_9200_DELL_M26] = "dell-m26",
+ 	[STAC_9200_DELL_M27] = "dell-m27",
+ 	[STAC_9200_GATEWAY] = "gateway",
++	[STAC_9200_PANASONIC] = "panasonic",
+ };
+ 
+ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
+@@ -1146,13 +1208,15 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
+ 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6,
+ 		      "unknown Dell", STAC_9200_DELL_M26),
+ 	/* Panasonic */
+-	SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF),
++	SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC),
+ 	/* Gateway machines needs EAPD to be set on resume */
+ 	SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY),
+ 	SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*",
+ 		      STAC_9200_GATEWAY),
+ 	SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707",
+ 		      STAC_9200_GATEWAY),
++	/* OQO Mobile */
++	SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO),
+ 	{} /* terminator */
+ };
+ 
+@@ -1202,24 +1266,48 @@ static struct snd_pci_quirk stac925x_cfg_tbl[] = {
+ 	{} /* terminator */
+ };
+ 
+-static unsigned int ref92hd73xx_pin_configs[12] = {
++static unsigned int ref92hd73xx_pin_configs[13] = {
+ 	0x02214030, 0x02a19040, 0x01a19020, 0x02214030,
+ 	0x0181302e, 0x01014010, 0x01014020, 0x01014030,
+ 	0x02319040, 0x90a000f0, 0x90a000f0, 0x01452050,
++	0x01452050,
++};
++
++static unsigned int dell_m6_pin_configs[13] = {
++	0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110,
++	0x03a11020, 0x0321101f, 0x4f0000f0, 0x4f0000f0,
++	0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0,
++	0x4f0000f0,
+ };
+ 
+ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
+-	[STAC_92HD73XX_REF] = ref92hd73xx_pin_configs,
++	[STAC_92HD73XX_REF]	= ref92hd73xx_pin_configs,
++	[STAC_DELL_M6]	= dell_m6_pin_configs,
+ };
+ 
+ static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
+ 	[STAC_92HD73XX_REF] = "ref",
++	[STAC_DELL_M6] = "dell-m6",
+ };
+ 
+ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
+ 	/* SigmaTel reference board */
+ 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
+-		      "DFI LanParty", STAC_92HD73XX_REF),
++				"DFI LanParty", STAC_92HD73XX_REF),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
++				"unknown Dell", STAC_DELL_M6),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
++				"unknown Dell", STAC_DELL_M6),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256,
++				"unknown Dell", STAC_DELL_M6),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257,
++				"unknown Dell", STAC_DELL_M6),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e,
++				"unknown Dell", STAC_DELL_M6),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f,
++				"unknown Dell", STAC_DELL_M6),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271,
++				"unknown Dell", STAC_DELL_M6),
+ 	{} /* terminator */
+ };
+ 
+@@ -1229,18 +1317,56 @@ static unsigned int ref92hd71bxx_pin_configs[10] = {
+ 	0x90a000f0, 0x01452050,
+ };
+ 
++static unsigned int dell_m4_1_pin_configs[13] = {
++	0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
++	0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0,
++	0x40f000f0, 0x4f0000f0,
++};
++
++static unsigned int dell_m4_2_pin_configs[13] = {
++	0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
++	0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0,
++	0x40f000f0, 0x044413b0,
++};
++
+ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
+ 	[STAC_92HD71BXX_REF] = ref92hd71bxx_pin_configs,
++	[STAC_DELL_M4_1]	= dell_m4_1_pin_configs,
++	[STAC_DELL_M4_2]	= dell_m4_2_pin_configs,
+ };
+ 
+ static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
+ 	[STAC_92HD71BXX_REF] = "ref",
++	[STAC_DELL_M4_1] = "dell-m4-1",
++	[STAC_DELL_M4_2] = "dell-m4-2",
+ };
+ 
+ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
+ 	/* SigmaTel reference board */
+ 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
+ 		      "DFI LanParty", STAC_92HD71BXX_REF),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
++				"unknown Dell", STAC_DELL_M4_1),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234,
++				"unknown Dell", STAC_DELL_M4_1),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0250,
++				"unknown Dell", STAC_DELL_M4_1),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024f,
++				"unknown Dell", STAC_DELL_M4_1),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024d,
++				"unknown Dell", STAC_DELL_M4_1),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0251,
++				"unknown Dell", STAC_DELL_M4_1),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0277,
++				"unknown Dell", STAC_DELL_M4_1),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0263,
++				"unknown Dell", STAC_DELL_M4_2),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0265,
++				"unknown Dell", STAC_DELL_M4_2),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0262,
++				"unknown Dell", STAC_DELL_M4_2),
++	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264,
++				"unknown Dell", STAC_DELL_M4_2),
+ 	{} /* terminator */
+ };
+ 
+@@ -1733,7 +1859,8 @@ static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ 				      struct snd_pcm_substream *substream)
+ {
+ 	struct sigmatel_spec *spec = codec->spec;
+-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++					     hinfo);
+ }
+ 
+ static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -1807,7 +1934,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ {
+ 	struct sigmatel_spec *spec = codec->spec;
+ 
+-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ 	return 0;
+ }
+ 
+@@ -1889,6 +2016,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
+ 		codec->num_pcms++;
+ 		info++;
+ 		info->name = "STAC92xx Digital";
++		info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ 		if (spec->multiout.dig_out_nid) {
+ 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
+ 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+@@ -1925,6 +2053,34 @@ static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int
+ 				  AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ }
+ 
++#define stac92xx_hp_switch_info		snd_ctl_boolean_mono_info
++
++static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
++			struct snd_ctl_elem_value *ucontrol)
++{
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	struct sigmatel_spec *spec = codec->spec;
++
++	ucontrol->value.integer.value[0] = spec->hp_switch;
++	return 0;
++}
++
++static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
++			struct snd_ctl_elem_value *ucontrol)
++{
++	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++	struct sigmatel_spec *spec = codec->spec;
++
++	spec->hp_switch = ucontrol->value.integer.value[0];
++
++	/* check to be sure that the ports are upto date with
++	 * switch changes
++	 */
++	codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
++
++	return 1;
++}
++
+ #define stac92xx_io_switch_info		snd_ctl_boolean_mono_info
+ 
+ static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+@@ -1996,6 +2152,15 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
+ 	return 1;
+ }
+ 
++#define STAC_CODEC_HP_SWITCH(xname) \
++	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
++	  .name = xname, \
++	  .index = 0, \
++	  .info = stac92xx_hp_switch_info, \
++	  .get = stac92xx_hp_switch_get, \
++	  .put = stac92xx_hp_switch_put, \
++	}
++
+ #define STAC_CODEC_IO_SWITCH(xname, xpval) \
+ 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ 	  .name = xname, \
+@@ -2020,6 +2185,7 @@ enum {
+ 	STAC_CTL_WIDGET_VOL,
+ 	STAC_CTL_WIDGET_MUTE,
+ 	STAC_CTL_WIDGET_MONO_MUX,
++	STAC_CTL_WIDGET_HP_SWITCH,
+ 	STAC_CTL_WIDGET_IO_SWITCH,
+ 	STAC_CTL_WIDGET_CLFE_SWITCH
+ };
+@@ -2028,6 +2194,7 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
+ 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
+ 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
+ 	STAC_MONO_MUX,
++	STAC_CODEC_HP_SWITCH(NULL),
+ 	STAC_CODEC_IO_SWITCH(NULL, 0),
+ 	STAC_CODEC_CLFE_SWITCH(NULL, 0),
+ };
+@@ -2222,6 +2389,29 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_
+ 	return 0;
+ }
+ 
++static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
++{
++	if (!spec->multiout.hp_nid)
++		spec->multiout.hp_nid = nid;
++	else if (spec->multiout.num_dacs > 4) {
++		printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
++		return 1;
++	} else {
++		spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
++		spec->multiout.num_dacs++;
++	}
++	return 0;
++}
++
++static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
++{
++	if (is_in_dac_nids(spec, nid))
++		return 1;
++	if (spec->multiout.hp_nid == nid)
++		return 1;
++	return 0;
++}
++
+ /* add playback controls from the parsed DAC table */
+ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+ 					       const struct auto_pin_cfg *cfg)
+@@ -2236,7 +2426,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+ 	unsigned int wid_caps, pincap;
+ 
+ 
+-	for (i = 0; i < cfg->line_outs; i++) {
++	for (i = 0; i < cfg->line_outs && i < spec->multiout.num_dacs; i++) {
+ 		if (!spec->multiout.dac_nids[i])
+ 			continue;
+ 
+@@ -2269,6 +2459,14 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+ 		}
+ 	}
+ 
++	if (cfg->hp_outs > 1) {
++		err = stac92xx_add_control(spec,
++			STAC_CTL_WIDGET_HP_SWITCH,
++			"Headphone as Line Out Switch", 0);
++		if (err < 0)
++			return err;
++	}
++
+ 	if (spec->line_switch) {
+ 		nid = cfg->input_pins[AUTO_PIN_LINE];
+ 		pincap = snd_hda_param_read(codec, nid,
+@@ -2284,10 +2482,11 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+ 
+ 	if (spec->mic_switch) {
+ 		unsigned int def_conf;
+-		nid = cfg->input_pins[AUTO_PIN_MIC];
++		unsigned int mic_pin = AUTO_PIN_MIC;
++again:
++		nid = cfg->input_pins[mic_pin];
+ 		def_conf = snd_hda_codec_read(codec, nid, 0,
+ 						AC_VERB_GET_CONFIG_DEFAULT, 0);
+-
+ 		/* some laptops have an internal analog microphone
+ 		 * which can't be used as a output */
+ 		if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
+@@ -2297,38 +2496,22 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+ 				err = stac92xx_add_control(spec,
+ 					STAC_CTL_WIDGET_IO_SWITCH,
+ 					"Mic as Output Switch", (nid << 8) | 1);
++				nid = snd_hda_codec_read(codec, nid, 0,
++					 AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
++				if (!check_in_dac_nids(spec, nid))
++					add_spec_dacs(spec, nid);
+ 				if (err < 0)
+ 					return err;
+ 			}
++		} else if (mic_pin == AUTO_PIN_MIC) {
++			mic_pin = AUTO_PIN_FRONT_MIC;
++			goto again;
+ 		}
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
+-{
+-	if (is_in_dac_nids(spec, nid))
+-		return 1;
+-	if (spec->multiout.hp_nid == nid)
+-		return 1;
+-	return 0;
+-}
+-
+-static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
+-{
+-	if (!spec->multiout.hp_nid)
+-		spec->multiout.hp_nid = nid;
+-	else if (spec->multiout.num_dacs > 4) {
+-		printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
+-		return 1;
+-	} else {
+-		spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
+-		spec->multiout.num_dacs++;
+-	}
+-	return 0;
+-}
+-
+ /* add playback controls for Speaker and HP outputs */
+ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
+ 					struct auto_pin_cfg *cfg)
+@@ -2378,12 +2561,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
+ 			return err;
+ 	}
+ 	if (spec->multiout.hp_nid) {
+-		const char *pfx;
+-		if (old_num_dacs == spec->multiout.num_dacs)
+-			pfx = "Master";
+-		else
+-			pfx = "Headphone";
+-		err = create_controls(spec, pfx, spec->multiout.hp_nid, 3);
++		err = create_controls(spec, "Headphone",
++				      spec->multiout.hp_nid, 3);
+ 		if (err < 0)
+ 			return err;
+ 	}
+@@ -2745,7 +2924,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
+ 	 */
+ 	for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) {
+ 		hda_nid_t pin = spec->autocfg.speaker_pins[i];
+-		unsigned long wcaps = get_wcaps(codec, pin);
++		unsigned int wcaps = get_wcaps(codec, pin);
+ 		wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
+ 		if (wcaps == AC_WCAP_OUT_AMP)
+ 			/* found a mono speaker with an amp, must be lfe */
+@@ -2756,12 +2935,12 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
+ 	if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) {
+ 		for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {
+ 			hda_nid_t pin = spec->autocfg.line_out_pins[i];
+-			unsigned long cfg;
+-			cfg = snd_hda_codec_read(codec, pin, 0,
++			unsigned int defcfg;
++			defcfg = snd_hda_codec_read(codec, pin, 0,
+ 						 AC_VERB_GET_CONFIG_DEFAULT,
+ 						 0x00);
+-			if (get_defcfg_device(cfg) == AC_JACK_SPEAKER) {
+-				unsigned long wcaps = get_wcaps(codec, pin);
++			if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) {
++				unsigned int wcaps = get_wcaps(codec, pin);
+ 				wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
+ 				if (wcaps == AC_WCAP_OUT_AMP)
+ 					/* found a mono speaker with an amp,
+@@ -2866,6 +3045,19 @@ static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
+ 	return 0; /* nid is not a HP-Out */
+ };
+ 
++static void stac92xx_power_down(struct hda_codec *codec)
++{
++	struct sigmatel_spec *spec = codec->spec;
++
++	/* power down inactive DACs */
++	hda_nid_t *dac;
++	for (dac = spec->dac_list; *dac; dac++)
++		if (!is_in_dac_nids(spec, *dac) &&
++			spec->multiout.hp_nid != *dac)
++			snd_hda_codec_write_cache(codec, *dac, 0,
++					AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
++}
++
+ static int stac92xx_init(struct hda_codec *codec)
+ {
+ 	struct sigmatel_spec *spec = codec->spec;
+@@ -2909,16 +3101,21 @@ static int stac92xx_init(struct hda_codec *codec)
+ 					? STAC_HP_EVENT : STAC_PWR_EVENT;
+ 		int pinctl = snd_hda_codec_read(codec, spec->pwr_nids[i],
+ 					0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
++		int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i],
++					0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ 		/* outputs are only ports capable of power management
+ 		 * any attempts on powering down a input port cause the
+ 		 * referenced VREF to act quirky.
+ 		 */
+ 		if (pinctl & AC_PINCTL_IN_EN)
+ 			continue;
++		if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED)
++			continue;
+ 		enable_pin_detect(codec, spec->pwr_nids[i], event | i);
+ 		codec->patch_ops.unsol_event(codec, (event | i) << 26);
+ 	}
+-
++	if (spec->dac_list)
++		stac92xx_power_down(codec);
+ 	if (cfg->dig_out_pin)
+ 		stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
+ 					 AC_PINCTL_OUT_EN);
+@@ -3014,6 +3211,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
+ {
+ 	struct sigmatel_spec *spec = codec->spec;
+ 	struct auto_pin_cfg *cfg = &spec->autocfg;
++	int nid = cfg->hp_pins[cfg->hp_outs - 1];
+ 	int i, presence;
+ 
+ 	presence = 0;
+@@ -3024,26 +3222,42 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
+ 	for (i = 0; i < cfg->hp_outs; i++) {
+ 		if (presence)
+ 			break;
++		if (spec->hp_switch && cfg->hp_pins[i] == nid)
++			break;
+ 		presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
+ 	}
+ 
+ 	if (presence) {
+ 		/* disable lineouts, enable hp */
++		if (spec->hp_switch)
++			stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ 		for (i = 0; i < cfg->line_outs; i++)
+ 			stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
+ 						AC_PINCTL_OUT_EN);
+ 		for (i = 0; i < cfg->speaker_outs; i++)
+ 			stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
+ 						AC_PINCTL_OUT_EN);
++		if (spec->eapd_mask)
++			stac_gpio_set(codec, spec->gpio_mask,
++				spec->gpio_dir, spec->gpio_data &
++				~spec->eapd_mask);
+ 	} else {
+ 		/* enable lineouts, disable hp */
++		if (spec->hp_switch)
++			stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ 		for (i = 0; i < cfg->line_outs; i++)
+ 			stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
+ 						AC_PINCTL_OUT_EN);
+ 		for (i = 0; i < cfg->speaker_outs; i++)
+ 			stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
+ 						AC_PINCTL_OUT_EN);
++		if (spec->eapd_mask)
++			stac_gpio_set(codec, spec->gpio_mask,
++				spec->gpio_dir, spec->gpio_data |
++				spec->eapd_mask);
+ 	}
++	if (!spec->hp_switch && cfg->hp_outs > 1 && presence)
++		stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ } 
+ 
+ static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
+@@ -3091,6 +3305,9 @@ static int stac92xx_resume(struct hda_codec *codec)
+ 		spec->gpio_dir, spec->gpio_data);
+ 	snd_hda_codec_resume_amp(codec);
+ 	snd_hda_codec_resume_cache(codec);
++	/* power down inactive DACs */
++	if (spec->dac_list)
++		stac92xx_power_down(codec);
+ 	/* invoke unsolicited event to reset the HP state */
+ 	if (spec->hp_detect)
+ 		codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+@@ -3147,12 +3364,18 @@ static int patch_stac9200(struct hda_codec *codec)
+ 	spec->num_adcs = 1;
+ 	spec->num_pwrs = 0;
+ 
+-	if (spec->board_config == STAC_9200_GATEWAY)
++	if (spec->board_config == STAC_9200_GATEWAY ||
++	    spec->board_config == STAC_9200_OQO)
+ 		spec->init = stac9200_eapd_init;
+ 	else
+ 		spec->init = stac9200_core_init;
+ 	spec->mixer = stac9200_mixer;
+ 
++	if (spec->board_config == STAC_9200_PANASONIC) {
++		spec->gpio_mask = spec->gpio_dir = 0x09;
++		spec->gpio_data = 0x00;
++	}
++
+ 	err = stac9200_parse_auto_config(codec);
+ 	if (err < 0) {
+ 		stac92xx_free(codec);
+@@ -3293,6 +3516,7 @@ again:
+ 
+ 	switch (spec->multiout.num_dacs) {
+ 	case 0x3: /* 6 Channel */
++		spec->multiout.hp_nid = 0x17;
+ 		spec->mixer = stac92hd73xx_6ch_mixer;
+ 		spec->init = stac92hd73xx_6ch_core_init;
+ 		break;
+@@ -3318,13 +3542,42 @@ again:
+ 
+ 	spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids);
+ 	spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids);
+-	spec->num_dmics = STAC92HD73XX_NUM_DMICS;
+ 	spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids);
+ 	spec->dinput_mux = &stac92hd73xx_dmux;
+ 	/* GPIO0 High = Enable EAPD */
+-	spec->gpio_mask = spec->gpio_dir = 0x1;
++	spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
+ 	spec->gpio_data = 0x01;
+ 
++	switch (spec->board_config) {
++	case STAC_DELL_M6:
++		spec->init = dell_eq_core_init;
++		switch (codec->subsystem_id) {
++		case 0x1028025e: /* Analog Mics */
++		case 0x1028025f:
++			stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
++			spec->num_dmics = 0;
++			break;
++		case 0x10280271: /* Digital Mics */
++		case 0x10280272:
++			spec->init = dell_m6_core_init;
++			/* fall-through */
++		case 0x10280254:
++		case 0x10280255:
++			stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
++			spec->num_dmics = 1;
++			break;
++		case 0x10280256: /* Both */
++		case 0x10280057:
++			stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
++			stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
++			spec->num_dmics = 1;
++			break;
++		}
++		break;
++	default:
++		spec->num_dmics = STAC92HD73XX_NUM_DMICS;
++	}
++
+ 	spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids);
+ 	spec->pwr_nids = stac92hd73xx_pwr_nids;
+ 
+@@ -3398,7 +3651,10 @@ again:
+ 	spec->aloopback_shift = 0;
+ 
+ 	/* GPIO0 High = EAPD */
+-	spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0x1;
++	spec->gpio_mask = 0x01;
++	spec->gpio_dir = 0x01;
++	spec->gpio_mask = 0x01;
++	spec->gpio_data = 0x01;
+ 
+ 	spec->mux_nids = stac92hd71bxx_mux_nids;
+ 	spec->adc_nids = stac92hd71bxx_adc_nids;
+@@ -3413,7 +3669,7 @@ again:
+ 	spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
+ 	spec->pwr_nids = stac92hd71bxx_pwr_nids;
+ 
+-	spec->multiout.num_dacs = 2;
++	spec->multiout.num_dacs = 1;
+ 	spec->multiout.hp_nid = 0x11;
+ 	spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
+ 
+@@ -3577,13 +3833,14 @@ static int patch_stac927x(struct hda_codec *codec)
+ 	spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids);
+ 	spec->mux_nids = stac927x_mux_nids;
+ 	spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
++	spec->dac_list = stac927x_dac_nids;
+ 	spec->multiout.dac_nids = spec->dac_nids;
+ 
+ 	switch (spec->board_config) {
+ 	case STAC_D965_3ST:
+ 	case STAC_D965_5ST:
+ 		/* GPIO0 High = Enable EAPD */
+-		spec->gpio_mask = spec->gpio_dir = 0x01;
++		spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x01;
+ 		spec->gpio_data = 0x01;
+ 		spec->num_dmics = 0;
+ 
+@@ -3591,14 +3848,23 @@ static int patch_stac927x(struct hda_codec *codec)
+ 		spec->mixer = stac927x_mixer;
+ 		break;
+ 	case STAC_DELL_BIOS:
++		switch (codec->subsystem_id) {
++		case 0x10280209:
++		case 0x1028022e:
++			/* correct the device field to SPDIF out */
++			stac92xx_set_config_reg(codec, 0x21, 0x01442070);
++			break;
++		};
++		/* configure the analog microphone on some laptops */
++		stac92xx_set_config_reg(codec, 0x0c, 0x90a79130);
+ 		/* correct the front output jack as a hp out */
+-		stac92xx_set_config_reg(codec, 0x0f, 0x02270110);
++		stac92xx_set_config_reg(codec, 0x0f, 0x0227011f);
+ 		/* correct the front input jack as a mic */
+ 		stac92xx_set_config_reg(codec, 0x0e, 0x02a79130);
+ 		/* fallthru */
+ 	case STAC_DELL_3ST:
+ 		/* GPIO2 High = Enable EAPD */
+-		spec->gpio_mask = spec->gpio_dir = 0x04;
++		spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04;
+ 		spec->gpio_data = 0x04;
+ 		spec->dmic_nids = stac927x_dmic_nids;
+ 		spec->num_dmics = STAC927X_NUM_DMICS;
+@@ -3610,7 +3876,7 @@ static int patch_stac927x(struct hda_codec *codec)
+ 		break;
+ 	default:
+ 		/* GPIO0 High = Enable EAPD */
+-		spec->gpio_mask = spec->gpio_dir = 0x1;
++		spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
+ 		spec->gpio_data = 0x01;
+ 		spec->num_dmics = 0;
+ 
+@@ -3714,6 +3980,7 @@ static int patch_stac9205(struct hda_codec *codec)
+ 					  (AC_USRSP_EN | STAC_HP_EVENT));
+ 
+ 		spec->gpio_dir = 0x0b;
++		spec->eapd_mask = 0x01;
+ 		spec->gpio_mask = 0x1b;
+ 		spec->gpio_mute = 0x10;
+ 		/* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute,
+@@ -3723,7 +3990,7 @@ static int patch_stac9205(struct hda_codec *codec)
+ 		break;
+ 	default:
+ 		/* GPIO0 High = EAPD */
+-		spec->gpio_mask = spec->gpio_dir = 0x1;
++		spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
+ 		spec->gpio_data = 0x01;
+ 		break;
+ 	}
+diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
+index 4e5dd4c..52b1d81 100644
+--- a/sound/pci/hda/patch_via.c
++++ b/sound/pci/hda/patch_via.c
+@@ -39,7 +39,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
+-
++#include "hda_patch.h"
+ 
+ /* amp values */
+ #define AMP_VAL_IDX_SHIFT	19
+@@ -357,7 +357,8 @@ static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ 				 struct snd_pcm_substream *substream)
+ {
+ 	struct via_spec *spec = codec->spec;
+-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++					     hinfo);
+ }
+ 
+ static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -430,8 +431,7 @@ static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ 				   struct snd_pcm_substream *substream)
+ {
+ 	struct via_spec *spec = codec->spec;
+-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+-				   0, 0, 0);
++	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ 	return 0;
+ }
+ 
+@@ -493,6 +493,11 @@ static int via_build_controls(struct hda_codec *codec)
+ 						    spec->multiout.dig_out_nid);
+ 		if (err < 0)
+ 			return err;
++		err = snd_hda_create_spdif_share_sw(codec,
++						    &spec->multiout);
++		if (err < 0)
++			return err;
++		spec->multiout.share_spdif = 1;
+ 	}
+ 	if (spec->dig_in_nid) {
+ 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -523,6 +528,7 @@ static int via_build_pcms(struct hda_codec *codec)
+ 		codec->num_pcms++;
+ 		info++;
+ 		info->name = spec->stream_name_digital;
++		info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ 		if (spec->multiout.dig_out_nid) {
+ 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+ 				*(spec->stream_digital_playback);
+diff --git a/sound/pci/hda/vmaster.c b/sound/pci/hda/vmaster.c
+deleted file mode 100644
+index 2da49d2..0000000
+--- a/sound/pci/hda/vmaster.c
++++ /dev/null
+@@ -1,364 +0,0 @@
+-/*
+- * Virtual master and slave controls
+- *
+- *  Copyright (c) 2008 by Takashi Iwai <tiwai at 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, version 2.
+- *
+- */
+-
+-#include <linux/slab.h>
+-#include <sound/core.h>
+-#include <sound/control.h>
+-
+-/*
+- * a subset of information returned via ctl info callback
+- */
+-struct link_ctl_info {
+-	int type;		/* value type */
+-	int count;		/* item count */
+-	int min_val, max_val;	/* min, max values */
+-};
+-
+-/*
+- * link master - this contains a list of slave controls that are
+- * identical types, i.e. info returns the same value type and value
+- * ranges, but may have different number of counts.
+- *
+- * The master control is so far only mono volume/switch for simplicity.
+- * The same value will be applied to all slaves.
+- */
+-struct link_master {
+-	struct list_head slaves;
+-	struct link_ctl_info info;
+-	int val;		/* the master value */
+-};
+-
+-/*
+- * link slave - this contains a slave control element
+- *
+- * It fakes the control callbacsk with additional attenuation by the
+- * master control.  A slave may have either one or two channels.
+- */
+-
+-struct link_slave {
+-	struct list_head list;
+-	struct link_master *master;
+-	struct link_ctl_info info;
+-	int vals[2];		/* current values */
+-	struct snd_kcontrol slave; /* the copy of original control entry */
+-};
+-
+-/* get the slave ctl info and save the initial values */
+-static int slave_init(struct link_slave *slave)
+-{
+-	struct snd_ctl_elem_info *uinfo;
+-	struct snd_ctl_elem_value *uctl;
+-	int err, ch;
+-
+-	if (slave->info.count)
+-		return 0; /* already initialized */
+-
+-	uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
+-	if (!uinfo)
+-		return -ENOMEM;
+-	uinfo->id = slave->slave.id;
+-	err = slave->slave.info(&slave->slave, uinfo);
+-	if (err < 0) {
+-		kfree(uinfo);
+-		return err;
+-	}
+-	slave->info.type = uinfo->type;
+-	slave->info.count = uinfo->count;
+-	if (slave->info.count > 2  ||
+-	    (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER &&
+-	     slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) {
+-		snd_printk(KERN_ERR "invalid slave element\n");
+-		kfree(uinfo);
+-		return -EINVAL;
+-	}
+-	slave->info.min_val = uinfo->value.integer.min;
+-	slave->info.max_val = uinfo->value.integer.max;
+-	kfree(uinfo);
+-
+-	uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
+-	if (!uctl)
+-		return -ENOMEM;
+-	uctl->id = slave->slave.id;
+-	err = slave->slave.get(&slave->slave, uctl);
+-	for (ch = 0; ch < slave->info.count; ch++)
+-		slave->vals[ch] = uctl->value.integer.value[ch];
+-	kfree(uctl);
+-	return 0;
+-}
+-
+-/* initialize master volume */
+-static int master_init(struct link_master *master)
+-{
+-	struct link_slave *slave;
+-
+-	if (master->info.count)
+-		return 0; /* already initialized */
+-
+-	list_for_each_entry(slave, &master->slaves, list) {
+-		int err = slave_init(slave);
+-		if (err < 0)
+-			return err;
+-		master->info = slave->info;
+-		master->info.count = 1; /* always mono */
+-		/* set full volume as default (= no attenuation) */
+-		master->val = master->info.max_val;
+-		return 0;
+-	}
+-	return -ENOENT;
+-}
+-
+-static int slave_get_val(struct link_slave *slave,
+-			 struct snd_ctl_elem_value *ucontrol)
+-{
+-	int err, ch;
+-
+-	err = slave_init(slave);
+-	if (err < 0)
+-		return err;
+-	for (ch = 0; ch < slave->info.count; ch++)
+-		ucontrol->value.integer.value[ch] = slave->vals[ch];
+-	return 0;
+-}
+-
+-static int slave_put_val(struct link_slave *slave,
+-			 struct snd_ctl_elem_value *ucontrol)
+-{
+-	int err, ch, vol;
+-
+-	err = master_init(slave->master);
+-	if (err < 0)
+-		return err;
+-
+-	switch (slave->info.type) {
+-	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+-		for (ch = 0; ch < slave->info.count; ch++)
+-			ucontrol->value.integer.value[ch] &=
+-				!!slave->master->val;
+-		break;
+-	case SNDRV_CTL_ELEM_TYPE_INTEGER:
+-		for (ch = 0; ch < slave->info.count; ch++) {
+-			/* max master volume is supposed to be 0 dB */
+-			vol = ucontrol->value.integer.value[ch];
+-			vol += slave->master->val - slave->master->info.max_val;
+-			if (vol < slave->info.min_val)
+-				vol = slave->info.min_val;
+-			else if (vol > slave->info.max_val)
+-				vol = slave->info.max_val;
+-			ucontrol->value.integer.value[ch] = vol;
+-		}
+-		break;
+-	}
+-	return slave->slave.put(&slave->slave, ucontrol);
+-}
+-
+-/*
+- * ctl callbacks for slaves
+- */
+-static int slave_info(struct snd_kcontrol *kcontrol,
+-		      struct snd_ctl_elem_info *uinfo)
+-{
+-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+-	return slave->slave.info(&slave->slave, uinfo);
+-}
+-
+-static int slave_get(struct snd_kcontrol *kcontrol,
+-		     struct snd_ctl_elem_value *ucontrol)
+-{
+-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+-	return slave_get_val(slave, ucontrol);
+-}
+-
+-static int slave_put(struct snd_kcontrol *kcontrol,
+-		     struct snd_ctl_elem_value *ucontrol)
+-{
+-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+-	int err, ch, changed = 0;
+-
+-	err = slave_init(slave);
+-	if (err < 0)
+-		return err;
+-	for (ch = 0; ch < slave->info.count; ch++) {
+-		if (slave->vals[ch] != ucontrol->value.integer.value[ch]) {
+-			changed = 1;
+-			slave->vals[ch] = ucontrol->value.integer.value[ch];
+-		}
+-	}
+-	if (!changed)
+-		return 0;
+-	return slave_put_val(slave, ucontrol);
+-}
+-
+-static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
+-			 int op_flag, unsigned int size,
+-			 unsigned int __user *tlv)
+-{
+-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+-	/* FIXME: this assumes that the max volume is 0 dB */
+-	return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv);
+-}
+-
+-static void slave_free(struct snd_kcontrol *kcontrol)
+-{
+-	struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+-	if (slave->slave.private_free)
+-		slave->slave.private_free(&slave->slave);
+-	if (slave->master)
+-		list_del(&slave->list);
+-	kfree(slave);
+-}
+-
+-/*
+- * Add a slave control to the group with the given master control
+- *
+- * All slaves must be the same type (returning the same information
+- * via info callback).  The fucntion doesn't check it, so it's your
+- * responsibility.
+- *
+- * Also, some additional limitations:
+- * - at most two channels
+- * - logarithmic volume control (dB level), no linear volume
+- * - master can only attenuate the volume, no gain
+- */
+-int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
+-{
+-	struct link_master *master_link = snd_kcontrol_chip(master);
+-	struct link_slave *srec;
+-
+-	srec = kzalloc(sizeof(*srec) +
+-		       slave->count * sizeof(*slave->vd), GFP_KERNEL);
+-	if (!srec)
+-		return -ENOMEM;
+-	srec->slave = *slave;
+-	memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
+-	srec->master = master_link;
+-
+-	/* override callbacks */
+-	slave->info = slave_info;
+-	slave->get = slave_get;
+-	slave->put = slave_put;
+-	if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)
+-		slave->tlv.c = slave_tlv_cmd;
+-	slave->private_data = srec;
+-	slave->private_free = slave_free;
+-
+-	list_add_tail(&srec->list, &master_link->slaves);
+-	return 0;
+-}
+-
+-/*
+- * ctl callbacks for master controls
+- */
+-static int master_info(struct snd_kcontrol *kcontrol,
+-		      struct snd_ctl_elem_info *uinfo)
+-{
+-	struct link_master *master = snd_kcontrol_chip(kcontrol);
+-	int ret;
+-
+-	ret = master_init(master);
+-	if (ret < 0)
+-		return ret;
+-	uinfo->type = master->info.type;
+-	uinfo->count = master->info.count;
+-	uinfo->value.integer.min = master->info.min_val;
+-	uinfo->value.integer.max = master->info.max_val;
+-	return 0;
+-}
+-
+-static int master_get(struct snd_kcontrol *kcontrol,
+-		      struct snd_ctl_elem_value *ucontrol)
+-{
+-	struct link_master *master = snd_kcontrol_chip(kcontrol);
+-	int err = master_init(master);
+-	if (err < 0)
+-		return err;
+-	ucontrol->value.integer.value[0] = master->val;
+-	return 0;
+-}
+-
+-static int master_put(struct snd_kcontrol *kcontrol,
+-		      struct snd_ctl_elem_value *ucontrol)
+-{
+-	struct link_master *master = snd_kcontrol_chip(kcontrol);
+-	struct link_slave *slave;
+-	struct snd_ctl_elem_value *uval;
+-	int err, old_val;
+-
+-	err = master_init(master);
+-	if (err < 0)
+-		return err;
+-	old_val = master->val;
+-	if (ucontrol->value.integer.value[0] == old_val)
+-		return 0;
+-
+-	uval = kmalloc(sizeof(*uval), GFP_KERNEL);
+-	if (!uval)
+-		return -ENOMEM;
+-	list_for_each_entry(slave, &master->slaves, list) {
+-		master->val = old_val;
+-		uval->id = slave->slave.id;
+-		slave_get_val(slave, uval);
+-		master->val = ucontrol->value.integer.value[0];
+-		slave_put_val(slave, uval);
+-	}
+-	kfree(uval);
+-	return 1;
+-}
+-
+-static void master_free(struct snd_kcontrol *kcontrol)
+-{
+-	struct link_master *master = snd_kcontrol_chip(kcontrol);
+-	struct link_slave *slave;
+-
+-	list_for_each_entry(slave, &master->slaves, list)
+-		slave->master = NULL;
+-	kfree(master);
+-}
+-
+-
+-/*
+- * Create a virtual master control with the given name
+- */
+-struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
+-						 const unsigned int *tlv)
+-{
+-	struct link_master *master;
+-	struct snd_kcontrol *kctl;
+-	struct snd_kcontrol_new knew;
+-
+-	memset(&knew, 0, sizeof(knew));
+-	knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+-	knew.name = name;
+-	knew.info = master_info;
+-
+-	master = kzalloc(sizeof(*master), GFP_KERNEL);
+-	if (!master)
+-		return NULL;
+-	INIT_LIST_HEAD(&master->slaves);
+-
+-	kctl = snd_ctl_new1(&knew, master);
+-	if (!kctl) {
+-		kfree(master);
+-		return NULL;
+-	}
+-	/* override some callbacks */
+-	kctl->info = master_info;
+-	kctl->get = master_get;
+-	kctl->put = master_put;
+-	kctl->private_free = master_free;
+-
+-	/* additional (constant) TLV read */
+-	if (tlv) {
+-		/* FIXME: this assumes that the max volume is 0 dB */
+-		kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+-		kctl->tlv.p = tlv;
+-	}
+-	return kctl;
+-}
+diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
+index efd180b..0ed96c1 100644
+--- a/sound/pci/ice1712/delta.c
++++ b/sound/pci/ice1712/delta.c
+@@ -1,8 +1,8 @@
+ /*
+  *   ALSA driver for ICEnsemble ICE1712 (Envy24)
+  *
+- *   Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile
+- *                          Digigram VX442
++ *   Lowlevel functions for M-Audio Delta 1010, 1010E, 44, 66, 66E, Dio2496,
++ *			    Audiophile, Digigram VX442
+  *
+  *	Copyright (c) 2000 Jaroslav Kysela <perex at perex.cz>
+  *
+@@ -86,6 +86,7 @@ static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice)
+ 	unsigned char tmp;
+ 	tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
+ 	switch (ice->eeprom.subvendor) {
++	case ICE1712_SUBDEVICE_DELTA1010E:
+ 	case ICE1712_SUBDEVICE_DELTA1010LT:
+ 		tmp &= ~ICE1712_DELTA_1010LT_CS;
+ 		tmp |= ICE1712_DELTA_1010LT_CCLK | ICE1712_DELTA_1010LT_CS_CS8427;
+@@ -109,6 +110,7 @@ static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice)
+ static void ap_cs8427_codec_deassert(struct snd_ice1712 *ice, unsigned char tmp)
+ {
+ 	switch (ice->eeprom.subvendor) {
++	case ICE1712_SUBDEVICE_DELTA1010E:
+ 	case ICE1712_SUBDEVICE_DELTA1010LT:
+ 		tmp &= ~ICE1712_DELTA_1010LT_CS;
+ 		tmp |= ICE1712_DELTA_1010LT_CS_NONE;
+@@ -534,6 +536,14 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ 	int err;
+ 	struct snd_akm4xxx *ak;
+ 
++	if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA1010 &&
++	    ice->eeprom.gpiodir == 0x7b)
++		ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA1010E;
++
++	if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA66 &&
++	    ice->eeprom.gpiodir == 0xfb)
++	    	ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA66E;
++
+ 	/* determine I2C, DACs and ADCs */
+ 	switch (ice->eeprom.subvendor) {
+ 	case ICE1712_SUBDEVICE_AUDIOPHILE:
+@@ -550,6 +560,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ 		ice->num_total_adcs = ice->omni ? 8 : 4;
+ 		break;
+ 	case ICE1712_SUBDEVICE_DELTA1010:
++	case ICE1712_SUBDEVICE_DELTA1010E:
+ 	case ICE1712_SUBDEVICE_DELTA1010LT:
+ 	case ICE1712_SUBDEVICE_MEDIASTATION:
+ 		ice->num_total_dacs = 8;
+@@ -559,6 +570,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ 		ice->num_total_dacs = 4;	/* two AK4324 codecs */
+ 		break;
+ 	case ICE1712_SUBDEVICE_VX442:
++	case ICE1712_SUBDEVICE_DELTA66E:	/* omni not suported yet */
+ 		ice->num_total_dacs = 4;
+ 		ice->num_total_adcs = 4;
+ 		break;
+@@ -568,8 +580,10 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ 	switch (ice->eeprom.subvendor) {
+ 	case ICE1712_SUBDEVICE_AUDIOPHILE:
+ 	case ICE1712_SUBDEVICE_DELTA410:
++	case ICE1712_SUBDEVICE_DELTA1010E:
+ 	case ICE1712_SUBDEVICE_DELTA1010LT:
+ 	case ICE1712_SUBDEVICE_VX442:
++	case ICE1712_SUBDEVICE_DELTA66E:
+ 		if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) {
+ 			snd_printk(KERN_ERR "unable to create I2C bus\n");
+ 			return err;
+@@ -601,6 +615,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ 	/* no analog? */
+ 	switch (ice->eeprom.subvendor) {
+ 	case ICE1712_SUBDEVICE_DELTA1010:
++	case ICE1712_SUBDEVICE_DELTA1010E:
+ 	case ICE1712_SUBDEVICE_DELTADIO2496:
+ 	case ICE1712_SUBDEVICE_MEDIASTATION:
+ 		return 0;
+@@ -627,6 +642,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ 		err = snd_ice1712_akm4xxx_init(ak, &akm_delta44, &akm_delta44_priv, ice);
+ 		break;
+ 	case ICE1712_SUBDEVICE_VX442:
++	case ICE1712_SUBDEVICE_DELTA66E:
+ 		err = snd_ice1712_akm4xxx_init(ak, &akm_vx442, &akm_vx442_priv, ice);
+ 		break;
+ 	default:
+@@ -674,6 +690,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
+ 		if (err < 0)
+ 			return err;
+ 		break;
++	case ICE1712_SUBDEVICE_DELTA1010E:
+ 	case ICE1712_SUBDEVICE_DELTA1010LT:
+ 		err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_select, ice));
+ 		if (err < 0)
+@@ -716,6 +733,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
+ 	case ICE1712_SUBDEVICE_DELTA44:
+ 	case ICE1712_SUBDEVICE_DELTA66:
+ 	case ICE1712_SUBDEVICE_VX442:
++	case ICE1712_SUBDEVICE_DELTA66E:
+ 		err = snd_ice1712_akm4xxx_build_controls(ice);
+ 		if (err < 0)
+ 			return err;
+diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
+index 26ea05a..ea7116c 100644
+--- a/sound/pci/ice1712/delta.h
++++ b/sound/pci/ice1712/delta.h
+@@ -36,8 +36,10 @@
+ 		"{Lionstracs,Mediastation},"
+ 
+ #define ICE1712_SUBDEVICE_DELTA1010	0x121430d6
++#define ICE1712_SUBDEVICE_DELTA1010E	0xff1430d6
+ #define ICE1712_SUBDEVICE_DELTADIO2496	0x121431d6
+ #define ICE1712_SUBDEVICE_DELTA66	0x121432d6
++#define ICE1712_SUBDEVICE_DELTA66E	0xff1432d6
+ #define ICE1712_SUBDEVICE_DELTA44	0x121433d6
+ #define ICE1712_SUBDEVICE_AUDIOPHILE	0x121434d6
+ #define ICE1712_SUBDEVICE_DELTA410	0x121438d6
+diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
+index 064760d..013fc4f 100644
+--- a/sound/pci/ice1712/ews.c
++++ b/sound/pci/ice1712/ews.c
+@@ -238,6 +238,7 @@ static void snd_ice1712_ews_cs8404_spdif_write(struct snd_ice1712 *ice, unsigned
+ 	case ICE1712_SUBDEVICE_EWS88MT:
+ 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ 	case ICE1712_SUBDEVICE_PHASE88:
++	case ICE1712_SUBDEVICE_TS88:
+ 		if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_CS8404], &bits, 1)
+ 		    != 1)
+ 			goto _error;
+@@ -433,6 +434,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+ 	case ICE1712_SUBDEVICE_EWS88MT:
+ 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ 	case ICE1712_SUBDEVICE_PHASE88:
++	case ICE1712_SUBDEVICE_TS88:
+ 		ice->num_total_dacs = 8;
+ 		ice->num_total_adcs = 8;
+ 		break;
+@@ -475,6 +477,8 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+ 	case ICE1712_SUBDEVICE_EWS88MT:
+ 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ 	case ICE1712_SUBDEVICE_PHASE88:
++	case ICE1712_SUBDEVICE_TS88:
++
+ 		err = snd_i2c_device_create(ice->i2c, "CS8404",
+ 					    ICE1712_EWS88MT_CS8404_ADDR,
+ 					    &spec->i2cdevs[EWS_I2C_CS8404]);
+@@ -518,6 +522,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+ 	case ICE1712_SUBDEVICE_EWS88MT:
+ 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ 	case ICE1712_SUBDEVICE_PHASE88:
++	case ICE1712_SUBDEVICE_TS88:
+ 	case ICE1712_SUBDEVICE_EWS88D:
+ 		/* set up CS8404 */
+ 		ice->spdif.ops.open = ews88_open_spdif;
+@@ -547,6 +552,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+ 	case ICE1712_SUBDEVICE_EWS88MT:
+ 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ 	case ICE1712_SUBDEVICE_PHASE88:
++	case ICE1712_SUBDEVICE_TS88:
+ 		err = snd_ice1712_akm4xxx_init(ak, &akm_ews88mt, &akm_ews88mt_priv, ice);
+ 		break;
+ 	case ICE1712_SUBDEVICE_EWX2496:
+@@ -973,6 +979,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
+ 	case ICE1712_SUBDEVICE_EWS88MT:
+ 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ 	case ICE1712_SUBDEVICE_PHASE88:
++	case ICE1712_SUBDEVICE_TS88:
+ 	case ICE1712_SUBDEVICE_DMX6FIRE:
+ 		err = snd_ice1712_akm4xxx_build_controls(ice);
+ 		if (err < 0)
+@@ -992,6 +999,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
+ 	case ICE1712_SUBDEVICE_EWS88MT:
+ 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ 	case ICE1712_SUBDEVICE_PHASE88:
++	case ICE1712_SUBDEVICE_TS88:
+ 		err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ews88mt_input_sense, ice));
+ 		if (err < 0)
+ 			return err;
+@@ -1049,6 +1057,13 @@ struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
+ 		.build_controls = snd_ice1712_ews_add_controls,
+ 	},
+ 	{
++		.subvendor = ICE1712_SUBDEVICE_TS88,
++		.name = "terrasoniq TS88",
++		.model = "phase88",
++		.chip_init = snd_ice1712_ews_init,
++		.build_controls = snd_ice1712_ews_add_controls,
++	},
++	{
+ 		.subvendor = ICE1712_SUBDEVICE_EWS88D,
+ 		.name = "TerraTec EWS88D",
+ 		.model = "ews88d",
+diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h
+index e4ed1b4..1c44371 100644
+--- a/sound/pci/ice1712/ews.h
++++ b/sound/pci/ice1712/ews.h
+@@ -30,7 +30,8 @@
+ 		"{TerraTec,EWS 88MT},"\
+ 		"{TerraTec,EWS 88D},"\
+ 		"{TerraTec,DMX 6Fire},"\
+-		"{TerraTec,Phase 88},"
++		"{TerraTec,Phase 88}," \
++		"{terrasoniq,TS 88},"
+ 
+ #define ICE1712_SUBDEVICE_EWX2496	0x3b153011
+ #define ICE1712_SUBDEVICE_EWS88MT	0x3b151511
+@@ -38,6 +39,7 @@
+ #define ICE1712_SUBDEVICE_EWS88D	0x3b152b11
+ #define ICE1712_SUBDEVICE_DMX6FIRE	0x3b153811
+ #define ICE1712_SUBDEVICE_PHASE88	0x3b155111
++#define ICE1712_SUBDEVICE_TS88   	0x3b157c11
+ 
+ /* entry point */
+ extern struct snd_ice1712_card_info snd_ice1712_ews_cards[];
+diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
+index cf5c7c0..6914189 100644
+--- a/sound/pci/ice1712/hoontech.c
++++ b/sound/pci/ice1712/hoontech.c
+@@ -208,6 +208,19 @@ static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
+ 			    /* ICE1712_STDSP24_MUTE |
+ 			       ICE1712_STDSP24_INSEL |
+ 			       ICE1712_STDSP24_DAREAR; */
++	/*  These boxconfigs have caused problems in the past.
++	 *  The code is not optimal, but should now enable a working config to
++	 *  be achieved.
++	 *  ** MIDI IN can only be configured on one box **
++	 *  ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box.
++	 *  Tests on a ADAC2000 box suggest the box config flags do not
++	 *  work as would be expected, and the inputs are crossed.
++	 *  Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2
++	 *  on the same box connects MIDI-In to both 401 uarts; both outputs
++	 *  are then active on all boxes.
++	 *  The default config here sets up everything on the first box.
++	 *  Alan Horstmann  5.2.2008
++	 */
+ 	spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
+ 				     ICE1712_STDSP24_BOX_CHN2 |
+ 				     ICE1712_STDSP24_BOX_CHN3 |
+@@ -223,14 +236,14 @@ static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
+ 		(spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0);
+ 	snd_ice1712_stdsp24_insel(ice,
+ 		(spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0);
+-	for (box = 0; box < 1; box++) {
++	for (box = 0; box < 4; box++) {
+ 		if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
+                         snd_ice1712_stdsp24_midi2(ice, 1);
+ 		for (chn = 0; chn < 4; chn++)
+ 			snd_ice1712_stdsp24_box_channel(ice, box, chn,
+ 				(spec->boxconfig[box] & (1 << chn)) ? 1 : 0);
+-		snd_ice1712_stdsp24_box_midi(ice, box,
+-				(spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) ? 1 : 0);
++		if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1)
++			snd_ice1712_stdsp24_box_midi(ice, box, 1);
+ 	}
+ 
+ 	return 0;
+@@ -322,6 +335,8 @@ struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
+ 		.name = "Hoontech SoundTrack Audio DSP24",
+ 		.model = "dsp24",
+ 		.chip_init = snd_ice1712_hoontech_init,
++		.mpu401_1_name = "MIDI-1 Hoontech/STA DSP24",
++		.mpu401_2_name = "MIDI-2 Hoontech/STA DSP24",
+ 	},
+ 	{
+ 		.subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE,	/* a dummy id */
+diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
+index df292af..29d449d 100644
+--- a/sound/pci/ice1712/ice1712.c
++++ b/sound/pci/ice1712/ice1712.c
+@@ -1297,11 +1297,14 @@ static void snd_ice1712_update_volume(struct snd_ice1712 *ice, int index)
+ static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+-	int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
++	int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
++		kcontrol->private_value;
+ 	
+ 	spin_lock_irq(&ice->reg_lock);
+-	ucontrol->value.integer.value[0] = !((ice->pro_volumes[index] >> 15) & 1);
+-	ucontrol->value.integer.value[1] = !((ice->pro_volumes[index] >> 31) & 1);
++	ucontrol->value.integer.value[0] =
++		!((ice->pro_volumes[priv_idx] >> 15) & 1);
++	ucontrol->value.integer.value[1] =
++		!((ice->pro_volumes[priv_idx] >> 31) & 1);
+ 	spin_unlock_irq(&ice->reg_lock);
+ 	return 0;
+ }
+@@ -1309,16 +1312,17 @@ static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struc
+ static int snd_ice1712_pro_mixer_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+-	int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
++	int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
++		kcontrol->private_value;
+ 	unsigned int nval, change;
+ 
+ 	nval = (ucontrol->value.integer.value[0] ? 0 : 0x00008000) |
+ 	       (ucontrol->value.integer.value[1] ? 0 : 0x80000000);
+ 	spin_lock_irq(&ice->reg_lock);
+-	nval |= ice->pro_volumes[index] & ~0x80008000;
+-	change = nval != ice->pro_volumes[index];
+-	ice->pro_volumes[index] = nval;
+-	snd_ice1712_update_volume(ice, index);
++	nval |= ice->pro_volumes[priv_idx] & ~0x80008000;
++	change = nval != ice->pro_volumes[priv_idx];
++	ice->pro_volumes[priv_idx] = nval;
++	snd_ice1712_update_volume(ice, priv_idx);
+ 	spin_unlock_irq(&ice->reg_lock);
+ 	return change;
+ }
+@@ -1335,11 +1339,14 @@ static int snd_ice1712_pro_mixer_volume_info(struct snd_kcontrol *kcontrol, stru
+ static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+-	int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
++	int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
++		kcontrol->private_value;
+ 	
+ 	spin_lock_irq(&ice->reg_lock);
+-	ucontrol->value.integer.value[0] = (ice->pro_volumes[index] >> 0) & 127;
+-	ucontrol->value.integer.value[1] = (ice->pro_volumes[index] >> 16) & 127;
++	ucontrol->value.integer.value[0] =
++		(ice->pro_volumes[priv_idx] >> 0) & 127;
++	ucontrol->value.integer.value[1] =
++		(ice->pro_volumes[priv_idx] >> 16) & 127;
+ 	spin_unlock_irq(&ice->reg_lock);
+ 	return 0;
+ }
+@@ -1347,16 +1354,17 @@ static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struc
+ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+-	int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
++	int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
++		kcontrol->private_value;
+ 	unsigned int nval, change;
+ 
+ 	nval = (ucontrol->value.integer.value[0] & 127) |
+ 	       ((ucontrol->value.integer.value[1] & 127) << 16);
+ 	spin_lock_irq(&ice->reg_lock);
+-	nval |= ice->pro_volumes[index] & ~0x007f007f;
+-	change = nval != ice->pro_volumes[index];
+-	ice->pro_volumes[index] = nval;
+-	snd_ice1712_update_volume(ice, index);
++	nval |= ice->pro_volumes[priv_idx] & ~0x007f007f;
++	change = nval != ice->pro_volumes[priv_idx];
++	ice->pro_volumes[priv_idx] = nval;
++	snd_ice1712_update_volume(ice, priv_idx);
+ 	spin_unlock_irq(&ice->reg_lock);
+ 	return change;
+ }
+@@ -2482,10 +2490,9 @@ static int snd_ice1712_free(struct snd_ice1712 *ice)
+ 	outb(0xff, ICEREG(ice, IRQMASK));
+ 	/* --- */
+       __hw_end:
+-	if (ice->irq >= 0) {
+-		synchronize_irq(ice->irq);
++	if (ice->irq >= 0)
+ 		free_irq(ice->irq, ice);
+-	}
++
+ 	if (ice->port)
+ 		pci_release_regions(ice->pci);
+ 	snd_ice1712_akm4xxx_free(ice);
+diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
+index 303cffe..3208901 100644
+--- a/sound/pci/ice1712/ice1712.h
++++ b/sound/pci/ice1712/ice1712.h
+@@ -367,6 +367,15 @@ struct snd_ice1712 {
+ 
+ 	/* other board-specific data */
+ 	void *spec;
++
++	/* VT172x specific */
++	int pro_rate_default;
++	int (*is_spdif_master)(struct snd_ice1712 *ice);
++	unsigned int (*get_rate)(struct snd_ice1712 *ice);
++	void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate);
++	unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
++	void (*set_spdif_clock)(struct snd_ice1712 *ice);
++
+ };
+ 
+ 
+@@ -429,10 +438,14 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
+ static inline void snd_ice1712_gpio_write_bits(struct snd_ice1712 *ice,
+ 					       unsigned int mask, unsigned int bits)
+ {
++	unsigned val;
++
+ 	ice->gpio.direction |= mask;
+ 	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+-	snd_ice1712_gpio_set_mask(ice, ~mask);
+-	snd_ice1712_gpio_write(ice, mask & bits);
++	val = snd_ice1712_gpio_read(ice);
++	val &= ~mask;
++	val |= mask & bits;
++	snd_ice1712_gpio_write(ice, val);
+ }
+ 
+ static inline int snd_ice1712_gpio_read_bits(struct snd_ice1712 *ice,
+diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
+index f533850..4490422 100644
+--- a/sound/pci/ice1712/ice1724.c
++++ b/sound/pci/ice1712/ice1724.c
+@@ -106,15 +106,19 @@ static unsigned int PRO_RATE_DEFAULT = 44100;
+  *  Basic I/O
+  */
+  
++/*
++ *  default rates, default clock routines
++ */
++
+ /* check whether the clock mode is spdif-in */
+-static inline int is_spdif_master(struct snd_ice1712 *ice)
++static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice)
+ {
+ 	return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;
+ }
+ 
+ static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
+ {
+-	return is_spdif_master(ice) || PRO_RATE_LOCKED;
++	return ice->is_spdif_master(ice) || PRO_RATE_LOCKED;
+ }
+ 
+ /*
+@@ -219,6 +223,32 @@ static unsigned int snd_vt1724_get_gpio_data(struct snd_ice1712 *ice)
+ }
+ 
+ /*
++ * MPU401 accessor
++ */
++static unsigned char snd_vt1724_mpu401_read(struct snd_mpu401 *mpu,
++					    unsigned long addr)
++{
++	/* fix status bits to the standard position */
++	/* only RX_EMPTY and TX_FULL are checked */
++	if (addr == MPU401C(mpu))
++		return (inb(addr) & 0x0c) << 4;
++	else
++		return inb(addr);
++}
++
++static void snd_vt1724_mpu401_write(struct snd_mpu401 *mpu,
++				    unsigned char data, unsigned long addr)
++{
++	if (addr == MPU401C(mpu)) {
++		if (data == MPU401_ENTER_UART)
++			outb(0x01, addr);
++		/* what else? */
++	} else
++		outb(data, addr);
++}
++
++
++/*
+  *  Interrupt handler
+  */
+ 
+@@ -226,24 +256,53 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
+ {
+ 	struct snd_ice1712 *ice = dev_id;
+ 	unsigned char status;
++	unsigned char status_mask =
++		VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM;
+ 	int handled = 0;
++#ifdef CONFIG_SND_DEBUG
++	int timeout = 0;
++#endif
+ 
+ 	while (1) {
+ 		status = inb(ICEREG1724(ice, IRQSTAT));
++		status &= status_mask;
+ 		if (status == 0)
+ 			break;
+-
++#ifdef CONFIG_SND_DEBUG
++		if (++timeout > 10) {
++			printk(KERN_ERR
++			       "ice1724: Too long irq loop, status = 0x%x\n",
++			       status);
++			break;
++		}
++#endif
+ 		handled = 1;		
+-		/* these should probably be separated at some point, 
+-		 * but as we don't currently have MPU support on the board
+-		 * I will leave it
+-		 */
+-		if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
++		if (status & VT1724_IRQ_MPU_TX) {
++			if (ice->rmidi[0])
++				snd_mpu401_uart_interrupt_tx(irq,
++					ice->rmidi[0]->private_data);
++			else /* disable TX to be sure */
++				outb(inb(ICEREG1724(ice, IRQMASK)) |
++				     VT1724_IRQ_MPU_TX,
++				     ICEREG1724(ice, IRQMASK));
++			/* Due to mysterical reasons, MPU_TX is always
++			 * generated (and can't be cleared) when a PCM
++			 * playback is going.  So let's ignore at the
++			 * next loop.
++			 */
++			status_mask &= ~VT1724_IRQ_MPU_TX;
++		}
++		if (status & VT1724_IRQ_MPU_RX) {
+ 			if (ice->rmidi[0])
+-				snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data);
+-			outb(status & (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX), ICEREG1724(ice, IRQSTAT));
+-			status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX);
++				snd_mpu401_uart_interrupt(irq,
++					ice->rmidi[0]->private_data);
++			else /* disable RX to be sure */
++				outb(inb(ICEREG1724(ice, IRQMASK)) |
++				     VT1724_IRQ_MPU_RX,
++				     ICEREG1724(ice, IRQMASK));
+ 		}
++		/* ack MPU irq */
++		outb(status, ICEREG1724(ice, IRQSTAT));
+ 		if (status & VT1724_IRQ_MTPCM) {
+ 			/*
+ 			 * Multi-track PCM
+@@ -391,51 +450,61 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ #define DMA_PAUSES	(VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
+ 	VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)
+ 
+-static int get_max_rate(struct snd_ice1712 *ice)
++static const unsigned int stdclock_rate_list[16] = {
++	48000, 24000, 12000, 9600, 32000, 16000, 8000, 96000, 44100,
++	22050, 11025, 88200, 176400, 0, 192000, 64000
++};
++
++static unsigned int stdclock_get_rate(struct snd_ice1712 *ice)
+ {
++	unsigned int rate;
++	rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15];
++	return rate;
++}
++
++static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate)
++{
++	int i;
++	for (i = 0; i < ARRAY_SIZE(stdclock_rate_list); i++) {
++		if (stdclock_rate_list[i] == rate) {
++			outb(i, ICEMT1724(ice, RATE));
++			return;
++		}
++	}
++}
++
++static unsigned char stdclock_set_mclk(struct snd_ice1712 *ice,
++				       unsigned int rate)
++{
++	unsigned char val, old;
++	/* check MT02 */
+ 	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
+-		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
+-			return 192000;
++		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
++		if (rate > 96000)
++			val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
+ 		else
+-			return 96000;
+-	} else
+-		return 48000;
++			val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
++		if (val != old) {
++			outb(val, ICEMT1724(ice, I2S_FORMAT));
++			/* master clock changed */
++			return 1;
++		}
++	}
++	/* no change in master clock */
++	return 0;
+ }
+ 
+ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
+ 				    int force)
+ {
+ 	unsigned long flags;
+-	unsigned char val, old;
+-	unsigned int i, mclk_change;
++	unsigned char mclk_change;
++	unsigned int i, old_rate;
+ 
+-	if (rate > get_max_rate(ice))
++	if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
+ 		return;
+-
+-	switch (rate) {
+-	case 8000: val = 6; break;
+-	case 9600: val = 3; break;
+-	case 11025: val = 10; break;
+-	case 12000: val = 2; break;
+-	case 16000: val = 5; break;
+-	case 22050: val = 9; break;
+-	case 24000: val = 1; break;
+-	case 32000: val = 4; break;
+-	case 44100: val = 8; break;
+-	case 48000: val = 0; break;
+-	case 64000: val = 15; break;
+-	case 88200: val = 11; break;
+-	case 96000: val = 7; break;
+-	case 176400: val = 12; break;
+-	case 192000: val = 14; break;
+-	default:
+-		snd_BUG();
+-		val = 0;
+-		break;
+-	}
+-
+ 	spin_lock_irqsave(&ice->reg_lock, flags);
+-	if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || 
++	if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
+ 	    (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
+ 		/* running? we cannot change the rate now... */
+ 		spin_unlock_irqrestore(&ice->reg_lock, flags);
+@@ -446,9 +515,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
+ 		return;
+ 	}
+ 
+-	old = inb(ICEMT1724(ice, RATE));
+-	if (force || old != val)
+-		outb(val, ICEMT1724(ice, RATE));
++	old_rate = ice->get_rate(ice);
++	if (force || (old_rate != rate))
++		ice->set_rate(ice, rate);
+ 	else if (rate == ice->cur_rate) {
+ 		spin_unlock_irqrestore(&ice->reg_lock, flags);
+ 		return;
+@@ -456,19 +525,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
+ 
+ 	ice->cur_rate = rate;
+ 
+-	/* check MT02 */
+-	mclk_change = 0;
+-	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
+-		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
+-		if (rate > 96000)
+-			val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
+-		else
+-			val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
+-		if (val != old) {
+-			outb(val, ICEMT1724(ice, I2S_FORMAT));
+-			mclk_change = 1;
+-		}
+-	}
++	/* setting master clock */
++	mclk_change = ice->set_mclk(ice, rate);
++
+ 	spin_unlock_irqrestore(&ice->reg_lock, flags);
+ 
+ 	if (mclk_change && ice->gpio.i2s_mclk_changed)
+@@ -727,43 +786,32 @@ static const struct snd_pcm_hardware snd_vt1724_2ch_stereo =
+ /*
+  * set rate constraints
+  */
+-static int set_rate_constraints(struct snd_ice1712 *ice,
+-				struct snd_pcm_substream *substream)
++static void set_std_hw_rates(struct snd_ice1712 *ice)
+ {
+-	struct snd_pcm_runtime *runtime = substream->runtime;
+-	if (ice->hw_rates) {
+-		/* hardware specific */
+-		runtime->hw.rate_min = ice->hw_rates->list[0];
+-		runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
+-		runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
+-		return snd_pcm_hw_constraint_list(runtime, 0,
+-						  SNDRV_PCM_HW_PARAM_RATE,
+-						  ice->hw_rates);
+-	}
+ 	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
+ 		/* I2S */
+ 		/* VT1720 doesn't support more than 96kHz */
+ 		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
+-			return snd_pcm_hw_constraint_list(runtime, 0,
+-							  SNDRV_PCM_HW_PARAM_RATE,
+-							  &hw_constraints_rates_192);
+-		else {
+-			runtime->hw.rates = SNDRV_PCM_RATE_KNOT |
+-				SNDRV_PCM_RATE_8000_96000;
+-			runtime->hw.rate_max = 96000;
+-			return snd_pcm_hw_constraint_list(runtime, 0,
+-							  SNDRV_PCM_HW_PARAM_RATE,
+-							  &hw_constraints_rates_96);
+-		}
+-	} else if (ice->ac97) {
++			ice->hw_rates = &hw_constraints_rates_192;
++		else
++			ice->hw_rates = &hw_constraints_rates_96;
++	} else {
+ 		/* ACLINK */
+-		runtime->hw.rate_max = 48000;
+-		runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
+-		return snd_pcm_hw_constraint_list(runtime, 0,
+-						  SNDRV_PCM_HW_PARAM_RATE,
+-						  &hw_constraints_rates_48);
++		ice->hw_rates = &hw_constraints_rates_48;
+ 	}
+-	return 0;
++}
++
++static int set_rate_constraints(struct snd_ice1712 *ice,
++				struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++
++	runtime->hw.rate_min = ice->hw_rates->list[0];
++	runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
++	runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
++	return snd_pcm_hw_constraint_list(runtime, 0,
++					  SNDRV_PCM_HW_PARAM_RATE,
++					  ice->hw_rates);
+ }
+ 
+ /* multi-channel playback needs alignment 8x32bit regardless of the channels
+@@ -824,7 +872,7 @@ static int snd_vt1724_playback_pro_close(struct snd_pcm_substream *substream)
+ 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ 
+ 	if (PRO_RATE_RESET)
+-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ 	ice->playback_pro_substream = NULL;
+ 
+ 	return 0;
+@@ -835,7 +883,7 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream)
+ 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ 
+ 	if (PRO_RATE_RESET)
+-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ 	ice->capture_pro_substream = NULL;
+ 	return 0;
+ }
+@@ -970,6 +1018,8 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
+ 				   VT1724_BUFFER_ALIGN);
+ 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ 				   VT1724_BUFFER_ALIGN);
++	if (ice->spdif.ops.open)
++		ice->spdif.ops.open(ice, substream);
+ 	return 0;
+ }
+ 
+@@ -978,8 +1028,10 @@ static int snd_vt1724_playback_spdif_close(struct snd_pcm_substream *substream)
+ 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ 
+ 	if (PRO_RATE_RESET)
+-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ 	ice->playback_con_substream = NULL;
++	if (ice->spdif.ops.close)
++		ice->spdif.ops.close(ice, substream);
+ 
+ 	return 0;
+ }
+@@ -1002,6 +1054,8 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
+ 				   VT1724_BUFFER_ALIGN);
+ 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ 				   VT1724_BUFFER_ALIGN);
++	if (ice->spdif.ops.open)
++		ice->spdif.ops.open(ice, substream);
+ 	return 0;
+ }
+ 
+@@ -1010,8 +1064,10 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
+ 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ 
+ 	if (PRO_RATE_RESET)
+-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ 	ice->capture_con_substream = NULL;
++	if (ice->spdif.ops.close)
++		ice->spdif.ops.close(ice, substream);
+ 
+ 	return 0;
+ }
+@@ -1154,7 +1210,7 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream)
+ 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ 
+ 	if (PRO_RATE_RESET)
+-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ 	ice->playback_con_substream_ds[substream->number] = NULL;
+ 	ice->pcm_reserved[substream->number] = NULL;
+ 
+@@ -1572,50 +1628,18 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
+ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
+ 					      struct snd_ctl_elem_info *uinfo)
+ {
+-	static const char * const texts_1724[] = {
+-		"8000",		/* 0: 6 */
+-		"9600",		/* 1: 3 */
+-		"11025",	/* 2: 10 */
+-		"12000",	/* 3: 2 */
+-		"16000",	/* 4: 5 */
+-		"22050",	/* 5: 9 */
+-		"24000",	/* 6: 1 */
+-		"32000",	/* 7: 4 */
+-		"44100",	/* 8: 8 */
+-		"48000",	/* 9: 0 */
+-		"64000",	/* 10: 15 */
+-		"88200",	/* 11: 11 */
+-		"96000",	/* 12: 7 */
+-		"176400",	/* 13: 12 */
+-		"192000",	/* 14: 14 */
+-		"IEC958 Input",	/* 15: -- */
+-	};
+-	static const char * const texts_1720[] = {
+-		"8000",		/* 0: 6 */
+-		"9600",		/* 1: 3 */
+-		"11025",	/* 2: 10 */
+-		"12000",	/* 3: 2 */
+-		"16000",	/* 4: 5 */
+-		"22050",	/* 5: 9 */
+-		"24000",	/* 6: 1 */
+-		"32000",	/* 7: 4 */
+-		"44100",	/* 8: 8 */
+-		"48000",	/* 9: 0 */
+-		"64000",	/* 10: 15 */
+-		"88200",	/* 11: 11 */
+-		"96000",	/* 12: 7 */
+-		"IEC958 Input",	/* 13: -- */
+-	};
+ 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ 
+ 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ 	uinfo->count = 1;
+-	uinfo->value.enumerated.items = ice->vt1720 ? 14 : 16;
++	uinfo->value.enumerated.items = ice->hw_rates->count + 1;
+ 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+-	strcpy(uinfo->value.enumerated.name,
+-	       ice->vt1720 ? texts_1720[uinfo->value.enumerated.item] :
+-	       texts_1724[uinfo->value.enumerated.item]);
++	if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1)
++		strcpy(uinfo->value.enumerated.name, "IEC958 Input");
++	else
++		sprintf(uinfo->value.enumerated.name, "%d",
++			ice->hw_rates->list[uinfo->value.enumerated.item]);
+ 	return 0;
+ }
+ 
+@@ -1623,68 +1647,79 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
+ 					     struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+-	static const unsigned char xlate[16] = {
+-		9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10
+-	};
+-	unsigned char val;
++	unsigned int i, rate;
+ 	
+ 	spin_lock_irq(&ice->reg_lock);
+-	if (is_spdif_master(ice)) {
+-		ucontrol->value.enumerated.item[0] = ice->vt1720 ? 13 : 15;
++	if (ice->is_spdif_master(ice)) {
++		ucontrol->value.enumerated.item[0] = ice->hw_rates->count;
+ 	} else {
+-		val = xlate[inb(ICEMT1724(ice, RATE)) & 15];
+-		if (val == 255) {
+-			snd_BUG();
+-			val = 0;
++		rate = ice->get_rate(ice);
++		ucontrol->value.enumerated.item[0] = 0;
++		for (i = 0; i < ice->hw_rates->count; i++) {
++			if (ice->hw_rates->list[i] == rate) {
++				ucontrol->value.enumerated.item[0] = i;
++				break;
++			}
+ 		}
+-		ucontrol->value.enumerated.item[0] = val;
+ 	}
+ 	spin_unlock_irq(&ice->reg_lock);
+ 	return 0;
+ }
+ 
++/* setting clock to external - SPDIF */
++static void stdclock_set_spdif_clock(struct snd_ice1712 *ice)
++{
++	unsigned char oval;
++	unsigned char i2s_oval;
++	oval = inb(ICEMT1724(ice, RATE));
++	outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
++	/* setting 256fs */
++	i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
++	outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT));
++}
++
+ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
+ 					     struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+-	unsigned char oval;
+-	int rate;
+-	int change = 0;
+-	int spdif = ice->vt1720 ? 13 : 15;
++	unsigned int old_rate, new_rate;
++	unsigned int item = ucontrol->value.enumerated.item[0];
++	unsigned int spdif = ice->hw_rates->count;
++
++	if (item > spdif)
++		return -EINVAL;
+ 
+ 	spin_lock_irq(&ice->reg_lock);
+-	oval = inb(ICEMT1724(ice, RATE));
+-	if (ucontrol->value.enumerated.item[0] == spdif) {
+-		unsigned char i2s_oval;
+-		outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
+-		/* setting 256fs */
+-		i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
+-		outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X,
+-		     ICEMT1724(ice, I2S_FORMAT));
++	if (ice->is_spdif_master(ice))
++		old_rate = 0;
++	else
++		old_rate = ice->get_rate(ice);
++	if (item == spdif) {
++		/* switching to external clock via SPDIF */
++		ice->set_spdif_clock(ice);
++		new_rate = 0;
+ 	} else {
+-		rate = rates[ucontrol->value.integer.value[0] % 15];
+-		if (rate <= get_max_rate(ice)) {
+-			PRO_RATE_DEFAULT = rate;
+-			spin_unlock_irq(&ice->reg_lock);
+-			snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
+-			spin_lock_irq(&ice->reg_lock);
+-		}
++		/* internal on-card clock */
++		new_rate = ice->hw_rates->list[item];
++		ice->pro_rate_default = new_rate;
++		spin_unlock_irq(&ice->reg_lock);
++		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
++		spin_lock_irq(&ice->reg_lock);
+ 	}
+-	change = inb(ICEMT1724(ice, RATE)) != oval;
+ 	spin_unlock_irq(&ice->reg_lock);
+ 
+-	if ((oval & VT1724_SPDIF_MASTER) !=
+-	    (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER)) {
++	/* the first reset to the SPDIF master mode? */
++	if (old_rate != new_rate && !new_rate) {
+ 		/* notify akm chips as well */
+-		if (is_spdif_master(ice)) {
+-			unsigned int i;
+-			for (i = 0; i < ice->akm_codecs; i++) {
+-				if (ice->akm[i].ops.set_rate_val)
+-					ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
+-			}
++		unsigned int i;
++		if (ice->gpio.set_pro_rate)
++			ice->gpio.set_pro_rate(ice, 0);
++		for (i = 0; i < ice->akm_codecs; i++) {
++			if (ice->akm[i].ops.set_rate_val)
++				ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
+ 		}
+ 	}
+-	return change;
++	return old_rate != new_rate;
+ }
+ 
+ static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
+@@ -2065,12 +2100,16 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
+ 
+ 
+ 
+-static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
++static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice)
+ {
+ 	outb(VT1724_RESET , ICEREG1724(ice, CONTROL));
+-	udelay(200);
++	msleep(10);
+ 	outb(0, ICEREG1724(ice, CONTROL));
+-	udelay(200);
++	msleep(10);
++}
++
++static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
++{
+ 	outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG));
+ 	outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG));
+ 	outb(ice->eeprom.data[ICE_EEP2_I2S], ICEREG1724(ice, I2S_FEATURES));
+@@ -2169,10 +2208,8 @@ static int snd_vt1724_free(struct snd_ice1712 *ice)
+ 	outb(0xff, ICEREG1724(ice, IRQMASK));
+ 	/* --- */
+       __hw_end:
+-	if (ice->irq >= 0) {
+-		synchronize_irq(ice->irq);
++	if (ice->irq >= 0)
+ 		free_irq(ice->irq, ice);
+-	}
+ 	pci_release_regions(ice->pci);
+ 	snd_ice1712_akm4xxx_free(ice);
+ 	pci_disable_device(ice->pci);
+@@ -2243,6 +2280,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
+ 
+ 	ice->irq = pci->irq;
+ 
++	snd_vt1724_chip_reset(ice);
+ 	if (snd_vt1724_read_eeprom(ice, modelname) < 0) {
+ 		snd_vt1724_free(ice);
+ 		return -EIO;
+@@ -2253,10 +2291,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
+ 	}
+ 
+ 	/* unmask used interrupts */
+-	if (! (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401))
+-		mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
+-	else
+-		mask = 0;
++	mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
+ 	outb(mask, ICEREG1724(ice, IRQMASK));
+ 	/* don't handle FIFO overrun/underruns (just yet),
+ 	 * since they cause machine lockups
+@@ -2335,6 +2370,19 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
+         * was called so in ice1712 driver, and vt1724 driver is derived from
+         * ice1712 driver.
+         */
++	ice->pro_rate_default = PRO_RATE_DEFAULT;
++	if (!ice->is_spdif_master)
++		ice->is_spdif_master = stdclock_is_spdif_master;
++	if (!ice->get_rate)
++		ice->get_rate = stdclock_get_rate;
++	if (!ice->set_rate)
++		ice->set_rate = stdclock_set_rate;
++	if (!ice->set_mclk)
++		ice->set_mclk = stdclock_set_mclk;
++	if (!ice->set_spdif_clock)
++		ice->set_spdif_clock = stdclock_set_spdif_clock;
++	if (!ice->hw_rates)
++		set_std_hw_rates(ice);
+ 
+ 	if ((err = snd_vt1724_pcm_profi(ice, pcm_dev++)) < 0) {
+ 		snd_card_free(card);
+@@ -2377,14 +2425,29 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
+ 
+ 	if (! c->no_mpu401) {
+ 		if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
++			struct snd_mpu401 *mpu;
+ 			if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
+ 						       ICEREG1724(ice, MPU_CTRL),
+-						       MPU401_INFO_INTEGRATED,
++						       (MPU401_INFO_INTEGRATED |
++							MPU401_INFO_TX_IRQ),
+ 						       ice->irq, 0,
+ 						       &ice->rmidi[0])) < 0) {
+ 				snd_card_free(card);
+ 				return err;
+ 			}
++			mpu = ice->rmidi[0]->private_data;
++			mpu->read = snd_vt1724_mpu401_read;
++			mpu->write = snd_vt1724_mpu401_write;
++			/* unmask MPU RX/TX irqs */
++			outb(inb(ICEREG1724(ice, IRQMASK)) &
++			     ~(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX),
++			     ICEREG1724(ice, IRQMASK));
++#if 0 /* for testing */
++			/* set watermarks */
++			outb(VT1724_MPU_RX_FIFO | 0x1,
++			     ICEREG1724(ice, MPU_FIFO_WM));
++			outb(0x1, ICEREG1724(ice, MPU_FIFO_WM));
++#endif
+ 		}
+ 	}
+ 
+diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
+index e8038c0..b4e0c16 100644
+--- a/sound/pci/ice1712/juli.c
++++ b/sound/pci/ice1712/juli.c
+@@ -4,6 +4,8 @@
+  *   Lowlevel functions for ESI Juli@ cards
+  *
+  *	Copyright (c) 2004 Jaroslav Kysela <perex at perex.cz>
++ *	              2008 Pavel Hofman <dustin at seznam.cz>
++ *
+  *
+  *   This 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,11 +29,11 @@
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <sound/core.h>
++#include <sound/tlv.h>
+ 
+ #include "ice1712.h"
+ #include "envy24ht.h"
+ #include "juli.h"
+-
+ struct juli_spec {
+ 	struct ak4114 *ak4114;
+ 	unsigned int analog: 1;
+@@ -44,6 +46,32 @@ struct juli_spec {
+ #define AK4358_ADDR		0x22		/* DAC */
+ 
+ /*
++ * Juli does not use the standard ICE1724 clock scheme. Juli's ice1724 chip is
++ * supplied by external clock provided by Xilinx array and MK73-1 PLL frequency
++ * multiplier. Actual frequency is set by ice1724 GPIOs hooked to the Xilinx.
++ *
++ * The clock circuitry is supplied by the two ice1724 crystals. This
++ * arrangement allows to generate independent clock signal for AK4114's input
++ * rate detection circuit. As a result, Juli, unlike most other
++ * ice1724+ak4114-based cards, detects spdif input rate correctly.
++ * This fact is applied in the driver, allowing to modify PCM stream rate
++ * parameter according to the actual input rate.
++ *
++ * Juli uses the remaining three stereo-channels of its DAC to optionally
++ * monitor analog input, digital input, and digital output. The corresponding
++ * I2S signals are routed by Xilinx, controlled by GPIOs.
++ *
++ * The master mute is implemented using output muting transistors (GPIO) in
++ * combination with smuting the DAC.
++ *
++ * The card itself has no HW master volume control, implemented using the
++ * vmaster control.
++ *
++ * TODO:
++ * researching and fixing the input monitors
++ */
++
++/*
+  * GPIO pins
+  */
+ #define GPIO_FREQ_MASK		(3<<0)
+@@ -55,17 +83,82 @@ struct juli_spec {
+ #define GPIO_MULTI_2X		(1<<2)
+ #define GPIO_MULTI_1X		(2<<2)		/* also external */
+ #define GPIO_MULTI_HALF		(3<<2)
+-#define GPIO_INTERNAL_CLOCK	(1<<4)
++#define GPIO_INTERNAL_CLOCK	(1<<4)		/* 0 = external, 1 = internal */
++#define GPIO_CLOCK_MASK		(1<<4)
+ #define GPIO_ANALOG_PRESENT	(1<<5)		/* RO only: 0 = present */
+ #define GPIO_RXMCLK_SEL		(1<<7)		/* must be 0 */
+ #define GPIO_AK5385A_CKS0	(1<<8)
+-#define GPIO_AK5385A_DFS0	(1<<9)		/* swapped with DFS1 according doc? */
+-#define GPIO_AK5385A_DFS1	(1<<10)
++#define GPIO_AK5385A_DFS1	(1<<9)
++#define GPIO_AK5385A_DFS0	(1<<10)
+ #define GPIO_DIGOUT_MONITOR	(1<<11)		/* 1 = active */
+ #define GPIO_DIGIN_MONITOR	(1<<12)		/* 1 = active */
+ #define GPIO_ANAIN_MONITOR	(1<<13)		/* 1 = active */
+-#define GPIO_AK5385A_MCLK	(1<<14)		/* must be 0 */
+-#define GPIO_MUTE_CONTROL	(1<<15)		/* 0 = off, 1 = on */
++#define GPIO_AK5385A_CKS1	(1<<14)		/* must be 0 */
++#define GPIO_MUTE_CONTROL	(1<<15)		/* output mute, 1 = muted */
++
++#define GPIO_RATE_MASK		(GPIO_FREQ_MASK | GPIO_MULTI_MASK | \
++		GPIO_CLOCK_MASK)
++#define GPIO_AK5385A_MASK	(GPIO_AK5385A_CKS0 | GPIO_AK5385A_DFS0 | \
++		GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS1)
++
++#define JULI_PCM_RATE	(SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
++		SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
++		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
++		SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
++		SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
++
++#define GPIO_RATE_16000		(GPIO_FREQ_32KHZ | GPIO_MULTI_HALF | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_22050		(GPIO_FREQ_44KHZ | GPIO_MULTI_HALF | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_24000		(GPIO_FREQ_48KHZ | GPIO_MULTI_HALF | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_32000		(GPIO_FREQ_32KHZ | GPIO_MULTI_1X | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_44100		(GPIO_FREQ_44KHZ | GPIO_MULTI_1X | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_48000		(GPIO_FREQ_48KHZ | GPIO_MULTI_1X | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_64000		(GPIO_FREQ_32KHZ | GPIO_MULTI_2X | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_88200		(GPIO_FREQ_44KHZ | GPIO_MULTI_2X | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_96000		(GPIO_FREQ_48KHZ | GPIO_MULTI_2X | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_176400	(GPIO_FREQ_44KHZ | GPIO_MULTI_4X | \
++		GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_192000	(GPIO_FREQ_48KHZ | GPIO_MULTI_4X | \
++		GPIO_INTERNAL_CLOCK)
++
++/*
++ * Initial setup of the conversion array GPIO <-> rate
++ */
++static unsigned int juli_rates[] = {
++	16000, 22050, 24000, 32000,
++	44100, 48000, 64000, 88200,
++	96000, 176400, 192000,
++};
++
++static unsigned int gpio_vals[] = {
++	GPIO_RATE_16000, GPIO_RATE_22050, GPIO_RATE_24000, GPIO_RATE_32000,
++	GPIO_RATE_44100, GPIO_RATE_48000, GPIO_RATE_64000, GPIO_RATE_88200,
++	GPIO_RATE_96000, GPIO_RATE_176400, GPIO_RATE_192000,
++};
++
++static struct snd_pcm_hw_constraint_list juli_rates_info = {
++	.count = ARRAY_SIZE(juli_rates),
++	.list = juli_rates,
++	.mask = 0,
++};
++
++static int get_gpio_val(int rate)
++{
++	int i;
++	for (i = 0; i < ARRAY_SIZE(juli_rates); i++)
++		if (juli_rates[i] == rate)
++			return gpio_vals[i];
++	return 0;
++}
+ 
+ static void juli_ak4114_write(void *private_data, unsigned char reg, unsigned char val)
+ {
+@@ -78,6 +171,27 @@ static unsigned char juli_ak4114_read(void *private_data, unsigned char reg)
+ }
+ 
+ /*
++ * If SPDIF capture and slaved to SPDIF-IN, setting runtime rate
++ * to the external rate
++ */
++static void juli_spdif_in_open(struct snd_ice1712 *ice,
++			       struct snd_pcm_substream *substream)
++{
++	struct juli_spec *spec = ice->spec;
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	int rate;
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
++			!ice->is_spdif_master(ice))
++		return;
++	rate = snd_ak4114_external_rate(spec->ak4114);
++	if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) {
++		runtime->hw.rate_min = rate;
++		runtime->hw.rate_max = rate;
++	}
++}
++
++/*
+  * AK4358 section
+  */
+ 
+@@ -99,57 +213,285 @@ static void juli_akm_write(struct snd_akm4xxx *ak, int chip,
+ }
+ 
+ /*
+- * change the rate of envy24HT, AK4358
++ * change the rate of envy24HT, AK4358, AK5385
+  */
+ static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+ {
+-	unsigned char old, tmp, dfs;
++	unsigned char old, tmp, ak4358_dfs;
++	unsigned int ak5385_pins, old_gpio, new_gpio;
++	struct snd_ice1712 *ice = ak->private_data[0];
++	struct juli_spec *spec = ice->spec;
+ 
+-	if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
++	if (rate == 0)  /* no hint - S/PDIF input is master or the new spdif
++			   input rate undetected, simply return */
+ 		return;
+-	
++
+ 	/* adjust DFS on codecs */
+-	if (rate > 96000) 
+-		dfs = 2;
+-	else if (rate > 48000)
+-		dfs = 1;
+-	else
+-		dfs = 0;
+-	
++	if (rate > 96000)  {
++		ak4358_dfs = 2;
++		ak5385_pins = GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS0;
++	} else if (rate > 48000) {
++		ak4358_dfs = 1;
++		ak5385_pins = GPIO_AK5385A_DFS0;
++	} else {
++		ak4358_dfs = 0;
++		ak5385_pins = 0;
++	}
++	/* AK5385 first, since it requires cold reset affecting both codecs */
++	old_gpio = ice->gpio.get_data(ice);
++	new_gpio =  (old_gpio & ~GPIO_AK5385A_MASK) | ak5385_pins;
++	/* printk(KERN_DEBUG "JULI - ak5385 set_rate_val: new gpio 0x%x\n",
++		new_gpio); */
++	ice->gpio.set_data(ice, new_gpio);
++
++	/* cold reset */
++	old = inb(ICEMT1724(ice, AC97_CMD));
++	outb(old | VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD));
++	udelay(1);
++	outb(old & ~VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD));
++
++	/* AK4358 */
++	/* set new value, reset DFS */
+ 	tmp = snd_akm4xxx_get(ak, 0, 2);
+-	old = (tmp >> 4) & 0x03;
+-	if (old == dfs)
+-		return;
+-	/* reset DFS */
+ 	snd_akm4xxx_reset(ak, 1);
+ 	tmp = snd_akm4xxx_get(ak, 0, 2);
+ 	tmp &= ~(0x03 << 4);
+-	tmp |= dfs << 4;
++	tmp |= ak4358_dfs << 4;
+ 	snd_akm4xxx_set(ak, 0, 2, tmp);
+ 	snd_akm4xxx_reset(ak, 0);
++
++	/* reinit ak4114 */
++	snd_ak4114_reinit(spec->ak4114);
+ }
+ 
++#define AK_DAC(xname, xch)	{ .name = xname, .num_channels = xch }
++#define PCM_VOLUME		"PCM Playback Volume"
++#define MONITOR_AN_IN_VOLUME	"Monitor Analog In Volume"
++#define MONITOR_DIG_IN_VOLUME	"Monitor Digital In Volume"
++#define MONITOR_DIG_OUT_VOLUME	"Monitor Digital Out Volume"
++
++static const struct snd_akm4xxx_dac_channel juli_dac[] = {
++	AK_DAC(PCM_VOLUME, 2),
++	AK_DAC(MONITOR_AN_IN_VOLUME, 2),
++	AK_DAC(MONITOR_DIG_OUT_VOLUME, 2),
++	AK_DAC(MONITOR_DIG_IN_VOLUME, 2),
++};
++
++
+ static struct snd_akm4xxx akm_juli_dac __devinitdata = {
+ 	.type = SND_AK4358,
+-	.num_dacs = 2,
++	.num_dacs = 8,	/* DAC1 - analog out
++			   DAC2 - analog in monitor
++			   DAC3 - digital out monitor
++			   DAC4 - digital in monitor
++			 */
+ 	.ops = {
+ 		.lock = juli_akm_lock,
+ 		.unlock = juli_akm_unlock,
+ 		.write = juli_akm_write,
+ 		.set_rate_val = juli_akm_set_rate_val
++	},
++	.dac_info = juli_dac,
++};
++
++#define juli_mute_info		snd_ctl_boolean_mono_info
++
++static int juli_mute_get(struct snd_kcontrol *kcontrol,
++		struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
++	unsigned int val;
++	val = ice->gpio.get_data(ice) & (unsigned int) kcontrol->private_value;
++	if (kcontrol->private_value == GPIO_MUTE_CONTROL)
++		/* val 0 = signal on */
++		ucontrol->value.integer.value[0] = (val) ? 0 : 1;
++	else
++		/* val 1 = signal on */
++		ucontrol->value.integer.value[0] = (val) ? 1 : 0;
++	return 0;
++}
++
++static int juli_mute_put(struct snd_kcontrol *kcontrol,
++		struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
++	unsigned int old_gpio, new_gpio;
++	old_gpio = ice->gpio.get_data(ice);
++	if (ucontrol->value.integer.value[0]) {
++		/* unmute */
++		if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
++			/* 0 = signal on */
++			new_gpio = old_gpio & ~GPIO_MUTE_CONTROL;
++			/* un-smuting DAC */
++			snd_akm4xxx_write(ice->akm, 0, 0x01, 0x01);
++		} else
++			/* 1 = signal on */
++			new_gpio =  old_gpio |
++				(unsigned int) kcontrol->private_value;
++	} else {
++		/* mute */
++		if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
++			/* 1 = signal off */
++			new_gpio = old_gpio | GPIO_MUTE_CONTROL;
++			/* smuting DAC */
++			snd_akm4xxx_write(ice->akm, 0, 0x01, 0x03);
++		} else
++			/* 0 = signal off */
++			new_gpio =  old_gpio &
++				~((unsigned int) kcontrol->private_value);
++	}
++	/* printk("JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, \
++		new_gpio 0x%x\n",
++		(unsigned int)ucontrol->value.integer.value[0], old_gpio,
++		new_gpio); */
++	if (old_gpio != new_gpio) {
++		ice->gpio.set_data(ice, new_gpio);
++		return 1;
++	}
++	/* no change */
++	return 0;
++}
++
++static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Master Playback Switch",
++		.info = juli_mute_info,
++		.get = juli_mute_get,
++		.put = juli_mute_put,
++		.private_value = GPIO_MUTE_CONTROL,
++	},
++	/* Although the following functionality respects the succint NDA'd
++	 * documentation from the card manufacturer, and the same way of
++	 * operation is coded in OSS Juli driver, only Digital Out monitor
++	 * seems to work. Surprisingly, Analog input monitor outputs Digital
++	 * output data. The two are independent, as enabling both doubles
++	 * volume of the monitor sound.
++	 *
++	 * Checking traces on the board suggests the functionality described
++	 * by the manufacturer is correct - I2S from ADC and AK4114
++	 * go to ICE as well as to Xilinx, I2S inputs of DAC2,3,4 (the monitor
++	 * inputs) are fed from Xilinx.
++	 *
++	 * I even checked traces on board and coded a support in driver for
++	 * an alternative possiblity - the unused I2S ICE output channels
++	 * switched to HW-IN/SPDIF-IN and providing the monitoring signal to
++	 * the DAC - to no avail. The I2S outputs seem to be unconnected.
++	 *
++	 * The windows driver supports the monitoring correctly.
++	 */
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Monitor Analog In Switch",
++		.info = juli_mute_info,
++		.get = juli_mute_get,
++		.put = juli_mute_put,
++		.private_value = GPIO_ANAIN_MONITOR,
++	},
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Monitor Digital Out Switch",
++		.info = juli_mute_info,
++		.get = juli_mute_get,
++		.put = juli_mute_put,
++		.private_value = GPIO_DIGOUT_MONITOR,
++	},
++	{
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.name = "Monitor Digital In Switch",
++		.info = juli_mute_info,
++		.get = juli_mute_get,
++		.put = juli_mute_put,
++		.private_value = GPIO_DIGIN_MONITOR,
++	},
++};
++
++
++static void ak4358_proc_regs_read(struct snd_info_entry *entry,
++		struct snd_info_buffer *buffer)
++{
++	struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
++	int reg, val;
++	for (reg = 0; reg <= 0xf; reg++) {
++		val =  snd_akm4xxx_get(ice->akm, 0, reg);
++		snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
+ 	}
++}
++
++static void ak4358_proc_init(struct snd_ice1712 *ice)
++{
++	struct snd_info_entry *entry;
++	if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry))
++		snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read);
++}
++
++static char *slave_vols[] __devinitdata = {
++	PCM_VOLUME,
++	MONITOR_AN_IN_VOLUME,
++	MONITOR_DIG_IN_VOLUME,
++	MONITOR_DIG_OUT_VOLUME,
++	NULL
+ };
+ 
++static __devinitdata
++DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1);
++
++static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
++		const char *name)
++{
++	struct snd_ctl_elem_id sid;
++	memset(&sid, 0, sizeof(sid));
++	/* FIXME: strcpy is bad. */
++	strcpy(sid.name, name);
++	sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++	return snd_ctl_find_id(card, &sid);
++}
++
++static void __devinit add_slaves(struct snd_card *card,
++				 struct snd_kcontrol *master, char **list)
++{
++	for (; *list; list++) {
++		struct snd_kcontrol *slave = ctl_find(card, *list);
++		/* printk(KERN_DEBUG "add_slaves - %s\n", *list); */
++		if (slave) {
++			/* printk(KERN_DEBUG "slave %s found\n", *list); */
++			snd_ctl_add_slave(master, slave);
++		}
++	}
++}
++
+ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
+ {
+ 	struct juli_spec *spec = ice->spec;
+ 	int err;
++	unsigned int i;
++	struct snd_kcontrol *vmaster;
++
+ 	err = snd_ice1712_akm4xxx_build_controls(ice);
+ 	if (err < 0)
+ 		return err;
++
++	for (i = 0; i < ARRAY_SIZE(juli_mute_controls); i++) {
++		err = snd_ctl_add(ice->card,
++				snd_ctl_new1(&juli_mute_controls[i], ice));
++		if (err < 0)
++			return err;
++	}
++	/* Create virtual master control */
++	vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
++					      juli_master_db_scale);
++	if (!vmaster)
++		return -ENOMEM;
++	add_slaves(ice->card, vmaster, slave_vols);
++	err = snd_ctl_add(ice->card, vmaster);
++	if (err < 0)
++		return err;
++
+ 	/* only capture SPDIF over AK4114 */
+ 	err = snd_ak4114_build(spec->ak4114, NULL,
+-			       ice->pcm_pro->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
++			ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
++
++	ak4358_proc_init(ice);
+ 	if (err < 0)
+ 		return err;
+ 	return 0;
+@@ -158,6 +500,74 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
+ /*
+  * initialize the chip
+  */
++
++static inline int juli_is_spdif_master(struct snd_ice1712 *ice)
++{
++	return (ice->gpio.get_data(ice) & GPIO_INTERNAL_CLOCK) ? 0 : 1;
++}
++
++static unsigned int juli_get_rate(struct snd_ice1712 *ice)
++{
++	int i;
++	unsigned char result;
++
++	result =  ice->gpio.get_data(ice) & GPIO_RATE_MASK;
++	for (i = 0; i < ARRAY_SIZE(gpio_vals); i++)
++		if (gpio_vals[i] == result)
++			return juli_rates[i];
++	return 0;
++}
++
++/* setting new rate */
++static void juli_set_rate(struct snd_ice1712 *ice, unsigned int rate)
++{
++	unsigned int old, new;
++	unsigned char val;
++
++	old = ice->gpio.get_data(ice);
++	new =  (old & ~GPIO_RATE_MASK) | get_gpio_val(rate);
++	/* printk(KERN_DEBUG "JULI - set_rate: old %x, new %x\n",
++			old & GPIO_RATE_MASK,
++			new & GPIO_RATE_MASK); */
++
++	ice->gpio.set_data(ice, new);
++	/* switching to external clock - supplied by external circuits */
++	val = inb(ICEMT1724(ice, RATE));
++	outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
++}
++
++static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice,
++					  unsigned int rate)
++{
++	/* no change in master clock */
++	return 0;
++}
++
++/* setting clock to external - SPDIF */
++static void juli_set_spdif_clock(struct snd_ice1712 *ice)
++{
++	unsigned int old;
++	old = ice->gpio.get_data(ice);
++	/* external clock (= 0), multiply 1x, 48kHz */
++	ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X |
++			GPIO_FREQ_48KHZ);
++}
++
++/* Called when ak4114 detects change in the input SPDIF stream */
++static void juli_ak4114_change(struct ak4114 *ak4114, unsigned char c0,
++			       unsigned char c1)
++{
++	struct snd_ice1712 *ice = ak4114->change_callback_private;
++	int rate;
++	if (ice->is_spdif_master(ice) && c1) {
++		/* only for SPDIF master mode, rate was changed */
++		rate = snd_ak4114_external_rate(ak4114);
++		/* printk(KERN_DEBUG "ak4114 - input rate changed to %d\n",
++				rate); */
++		juli_akm_set_rate_val(ice->akm, rate);
++	}
++}
++
+ static int __devinit juli_init(struct snd_ice1712 *ice)
+ {
+ 	static const unsigned char ak4114_init_vals[] = {
+@@ -187,6 +597,11 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
+ 				ice, &spec->ak4114);
+ 	if (err < 0)
+ 		return err;
++	/* callback for codecs rate setting */
++	spec->ak4114->change_callback = juli_ak4114_change;
++	spec->ak4114->change_callback_private = ice;
++	/* AK4114 in Juli can detect external rate correctly */
++	spec->ak4114->check_flags = 0;
+ 
+ #if 0
+         /* it seems that the analog doughter board detection does not work
+@@ -210,6 +625,15 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
+ 			return err;
+ 	}
+ 	
++	/* juli is clocked by Xilinx array */
++	ice->hw_rates = &juli_rates_info;
++	ice->is_spdif_master = juli_is_spdif_master;
++	ice->get_rate = juli_get_rate;
++	ice->set_rate = juli_set_rate;
++	ice->set_mclk = juli_set_mclk;
++	ice->set_spdif_clock = juli_set_spdif_clock;
++
++	ice->spdif.ops.open = juli_spdif_in_open;
+ 	return 0;
+ }
+ 
+@@ -220,18 +644,20 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
+  */
+ 
+ static unsigned char juli_eeprom[] __devinitdata = {
+-	[ICE_EEP2_SYSCONF]     = 0x20,	/* clock 512, mpu401, 1xADC, 1xDACs */
++	[ICE_EEP2_SYSCONF]     = 0x2b,	/* clock 512, mpu401, 1xADC, 1xDACs,
++					   SPDIF in */
+ 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
+ 	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
+ 	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
+-	[ICE_EEP2_GPIO_DIR]    = 0x9f,
++	[ICE_EEP2_GPIO_DIR]    = 0x9f,	/* 5, 6:inputs; 7, 4-0 outputs*/
+ 	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+ 	[ICE_EEP2_GPIO_DIR2]   = 0x7f,
+-	[ICE_EEP2_GPIO_MASK]   = 0x9f,
+-	[ICE_EEP2_GPIO_MASK1]  = 0xff,
++	[ICE_EEP2_GPIO_MASK]   = 0x60,	/* 5, 6: locked; 7, 4-0 writable */
++	[ICE_EEP2_GPIO_MASK1]  = 0x00,  /* 0-7 writable */
+ 	[ICE_EEP2_GPIO_MASK2]  = 0x7f,
+-	[ICE_EEP2_GPIO_STATE]  = 0x16,	/* internal clock, multiple 1x, 48kHz */
+-	[ICE_EEP2_GPIO_STATE1] = 0x80,	/* mute */
++	[ICE_EEP2_GPIO_STATE]  = GPIO_FREQ_48KHZ | GPIO_MULTI_1X |
++	       GPIO_INTERNAL_CLOCK,	/* internal clock, multiple 1x, 48kHz*/
++	[ICE_EEP2_GPIO_STATE1] = 0x00,	/* unmuted */
+ 	[ICE_EEP2_GPIO_STATE2] = 0x00,
+ };
+ 
+diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
+index 4945c81..203cdc1 100644
+--- a/sound/pci/ice1712/pontis.c
++++ b/sound/pci/ice1712/pontis.c
+@@ -246,7 +246,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
+ 		wm_put(ice, WM_ADC_MUX, nval);
+ 	}
+ 	mutex_unlock(&ice->gpio_mutex);
+-	return 0;
++	return change;
+ }
+ 
+ /*
+@@ -450,7 +450,7 @@ static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
+ 		change = 1;
+ 	}
+ 	mutex_unlock(&ice->gpio_mutex);
+-	return 0;
++	return change;
+ }
+ 
+ 
+diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
+index 48cf40a..48d3679 100644
+--- a/sound/pci/ice1712/prodigy192.c
++++ b/sound/pci/ice1712/prodigy192.c
+@@ -319,12 +319,11 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
+ /*
+  * Handler for setting correct codec rate - called when rate change is detected
+  */
+-static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
++static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
+ {
+ 	unsigned char old, new;
+ 	int idx;
+ 	unsigned char changed[7];
+-	struct snd_ice1712 *ice = ak->private_data[0];
+ 	struct prodigy192_spec *spec = ice->spec;
+ 
+ 	if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
+@@ -357,16 +356,6 @@ static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+ 	mutex_unlock(&spec->mute_mutex);
+ }
+ 
+-/* using akm infrastructure for setting rate of the codec */
+-static struct snd_akm4xxx akmlike_stac9460 __devinitdata = {
+-	.type = NON_AKM,	/* special value */
+-	.num_adcs = 6,		/* not used in any way, just for completeness */
+-	.num_dacs = 2,
+-	.ops = {
+-		.set_rate_val = stac9460_set_rate_val
+-	}
+-};
+-
+ 
+ static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
+ static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
+@@ -642,12 +631,19 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
+ 		0x41, 0x02, 0x2c, 0x00, 0x00
+ 	};
+ 	struct prodigy192_spec *spec = ice->spec;
++	int err;
+ 
+-	return snd_ak4114_create(ice->card,
++	err = snd_ak4114_create(ice->card,
+ 				 prodigy192_ak4114_read,
+ 				 prodigy192_ak4114_write,
+ 				 ak4114_init_vals, ak4114_init_txcsb,
+ 				 ice, &spec->ak4114);
++	if (err < 0)
++		return err;
++	/* AK4114 in Prodigy192 cannot detect external rate correctly.
++	 * No reason to stop capture stream due to incorrect checks */
++	spec->ak4114->check_flags = AK4114_CHECK_NO_RATE;
++	return 0;
+ }
+ 
+ static void stac9460_proc_regs_read(struct snd_info_entry *entry,
+@@ -743,7 +739,6 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
+ 	};
+ 	const unsigned short *p;
+ 	int err = 0;
+-	struct snd_akm4xxx *ak;
+ 	struct prodigy192_spec *spec;
+ 
+ 	/* prodigy 192 */
+@@ -761,15 +756,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
+ 	p = stac_inits_prodigy;
+ 	for (; *p != (unsigned short)-1; p += 2)
+ 		stac9460_put(ice, p[0], p[1]);
+-	/* reusing the akm codecs infrastructure,
+-	 * for setting rate on stac9460 */
+-	ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
+-	if (!ak)
+-		return -ENOMEM;
+-	ice->akm_codecs = 1;
+-	err = snd_ice1712_akm4xxx_init(ak, &akmlike_stac9460, NULL, ice);
+-	if (err < 0)
+-		return err;
++	ice->gpio.set_pro_rate = stac9460_set_rate_val;
+ 
+ 	/* MI/ODI/O add on card with AK4114 */
+ 	if (prodigy192_miodio_exists(ice)) {
+@@ -825,10 +812,6 @@ struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
+ 		.build_controls = prodigy192_add_controls,
+ 		.eeprom_size = sizeof(prodigy71_eeprom),
+ 		.eeprom_data = prodigy71_eeprom,
+-		/* the current MPU401 code loops infinitely
+-		 * when opening midi device
+-		 */
+-		.no_mpu401 = 1,
+ 	},
+ 	{ } /* terminator */
+ };
+diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
+index 301bf92..4d26314 100644
+--- a/sound/pci/ice1712/revo.c
++++ b/sound/pci/ice1712/revo.c
+@@ -322,17 +322,23 @@ static struct snd_pt2258 ptc_revo51_volume;
+ static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+ {
+ 	struct snd_ice1712 *ice = ak->private_data[0];
++	int dfs;
+ 
+ 	revo_set_rate_val(ak, rate);
+ 
+-#if 1 /* FIXME: do we need this procedure? */
+-	/* reset DFS pin of AK5385A for ADC, too */
+-	/* DFS0 (pin 18) -- GPIO10 pin 77 */
+-	snd_ice1712_save_gpio_status(ice);
+-	snd_ice1712_gpio_write_bits(ice, 1 << 10,
+-				    rate > 48000 ? (1 << 10) : 0);
+-	snd_ice1712_restore_gpio_status(ice);
+-#endif
++	/* reset CKS */
++	snd_ice1712_gpio_write_bits(ice, 1 << 8, rate > 96000 ? 1 << 8 : 0);
++	/* reset DFS pins of AK5385A for ADC, too */
++	if (rate > 96000)
++		dfs = 2;
++	else if (rate > 48000)
++		dfs = 1;
++	else
++		dfs = 0;
++	snd_ice1712_gpio_write_bits(ice, 3 << 9, dfs << 9);
++	/* reset ADC */
++	snd_ice1712_gpio_write_bits(ice, 1 << 11, 0);
++	snd_ice1712_gpio_write_bits(ice, 1 << 11, 1 << 11);
+ }
+ 
+ static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
+@@ -353,28 +359,20 @@ static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
+ 	.cif = 0,
+ 	.data_mask = VT1724_REVO_CDOUT,
+ 	.clk_mask = VT1724_REVO_CCLK,
+-	.cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS3,
+-	.cs_addr = VT1724_REVO_CS3,
+-	.cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS3,
++	.cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
++	.cs_addr = VT1724_REVO_CS1,
++	.cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
+ 	.add_flags = VT1724_REVO_CCLK, /* high at init */
+ 	.mask_flags = 0,
+ };
+ 
+-#if 0
+-/* FIXME: ak4114 makes the sound much lower due to some confliction,
+- *        so let's disable it right now...
+- */
+-#define BUILD_AK4114_AP192
+-#endif
+-
+-#ifdef BUILD_AK4114_AP192
+ /* AK4114 support on Audiophile 192 */
+ /* CDTO (pin 32) -- GPIO2 pin 52
+  * CDTI (pin 33) -- GPIO3 pin 53 (shared with AK4358)
+  * CCLK (pin 34) -- GPIO1 pin 51 (shared with AK4358)
+  * CSN  (pin 35) -- GPIO7 pin 59
+  */
+-#define AK4114_ADDR	0x00
++#define AK4114_ADDR	0x02
+ 
+ static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
+ 		       unsigned int data, int idx)
+@@ -428,7 +426,7 @@ static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
+ 	tmp = snd_ice1712_gpio_read(ice);
+ 	tmp |= VT1724_REVO_CCLK; /* high at init */
+ 	tmp |= VT1724_REVO_CS0;
+-	tmp &= ~VT1724_REVO_CS3;
++	tmp &= ~VT1724_REVO_CS1;
+ 	snd_ice1712_gpio_write(ice, tmp);
+ 	udelay(1);
+ 	return tmp;
+@@ -436,7 +434,7 @@ static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
+ 
+ static void ap192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
+ {
+-	tmp |= VT1724_REVO_CS3;
++	tmp |= VT1724_REVO_CS1;
+ 	tmp |= VT1724_REVO_CS0;
+ 	snd_ice1712_gpio_write(ice, tmp);
+ 	udelay(1);
+@@ -485,13 +483,17 @@ static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
+ 	struct ak4114 *ak;
+ 	int err;
+ 
+-	return snd_ak4114_create(ice->card,
++	err = snd_ak4114_create(ice->card,
+ 				 ap192_ak4114_read,
+ 				 ap192_ak4114_write,
+ 				 ak4114_init_vals, ak4114_init_txcsb,
+ 				 ice, &ak);
++	/* AK4114 in Revo cannot detect external rate correctly.
++	 * No reason to stop capture stream due to incorrect checks */
++	ak->check_flags = AK4114_CHECK_NO_RATE;
++
++	return 0; /* error ignored; it's no fatal error */
+ }
+-#endif /* BUILD_AK4114_AP192 */
+ 
+ static int __devinit revo_init(struct snd_ice1712 *ice)
+ {
+@@ -557,6 +559,9 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
+ 		if (err < 0)
+ 			return err;
+ 		
++		/* unmute all codecs */
++		snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
++					    VT1724_REVO_MUTE);
+ 		break;
+ 	}
+ 
+@@ -588,11 +593,9 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
+ 		err = snd_ice1712_akm4xxx_build_controls(ice);
+ 		if (err < 0)
+ 			return err;
+-#ifdef BUILD_AK4114_AP192
+ 		err = ap192_ak4114_init(ice);
+ 		if (err < 0)
+ 			return err;
+-#endif
+ 		break;
+ 	}
+ 	return 0;
+diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
+index c52abd0..048d99e 100644
+--- a/sound/pci/intel8x0.c
++++ b/sound/pci/intel8x0.c
+@@ -155,7 +155,8 @@ DEFINE_REGSET(SP, 0x60);	/* SPDIF out */
+ #define   ICH_PCM_SPDIF_69	0x80000000	/* s/pdif pcm on slots 6&9 */
+ #define   ICH_PCM_SPDIF_1011	0xc0000000	/* s/pdif pcm on slots 10&11 */
+ #define   ICH_PCM_20BIT		0x00400000	/* 20-bit samples (ICH4) */
+-#define   ICH_PCM_246_MASK	0x00300000	/* 6 channels (not all chips) */
++#define   ICH_PCM_246_MASK	0x00300000	/* chan mask (not all chips) */
++#define   ICH_PCM_8		0x00300000      /* 8 channels (not all chips) */
+ #define   ICH_PCM_6		0x00200000	/* 6 channels (not all chips) */
+ #define   ICH_PCM_4		0x00100000	/* 4 channels (not all chips) */
+ #define   ICH_PCM_2		0x00000000	/* 2 channels (stereo) */
+@@ -382,6 +383,7 @@ struct intel8x0 {
+ 
+ 	unsigned multi4: 1,
+ 		 multi6: 1,
++		 multi8 :1,
+ 		 dra: 1,
+ 		 smp20bit: 1;
+ 	unsigned in_ac97_init: 1,
+@@ -997,6 +999,8 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
+ 			cnt |= ICH_PCM_4;
+ 		else if (runtime->channels == 6)
+ 			cnt |= ICH_PCM_6;
++		else if (runtime->channels == 8)
++			cnt |= ICH_PCM_8;
+ 		if (chip->device_type == DEVICE_NFORCE) {
+ 			/* reset to 2ch once to keep the 6 channel data in alignment,
+ 			 * to start from Front Left always
+@@ -1106,6 +1110,16 @@ static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = {
+ 	.mask = 0,
+ };
+ 
++static unsigned int channels8[] = {
++	2, 4, 6, 8,
++};
++
++static struct snd_pcm_hw_constraint_list hw_constraints_channels8 = {
++	.count = ARRAY_SIZE(channels8),
++	.list = channels8,
++	.mask = 0,
++};
++
+ static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev)
+ {
+ 	struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+@@ -1136,7 +1150,12 @@ static int snd_intel8x0_playback_open(struct snd_pcm_substream *substream)
+ 	if (err < 0)
+ 		return err;
+ 
+-	if (chip->multi6) {
++	if (chip->multi8) {
++		runtime->hw.channels_max = 8;
++		snd_pcm_hw_constraint_list(runtime, 0,
++						SNDRV_PCM_HW_PARAM_CHANNELS,
++						&hw_constraints_channels8);
++	} else if (chip->multi6) {
+ 		runtime->hw.channels_max = 6;
+ 		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ 					   &hw_constraints_channels6);
+@@ -2203,8 +2222,11 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
+ 	}
+ 	if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) {
+ 		chip->multi4 = 1;
+-		if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE))
++		if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) {
+ 			chip->multi6 = 1;
++			if (chip->ac97[0]->flags & AC97_HAS_8CH)
++				chip->multi8 = 1;
++		}
+ 	}
+ 	if (pbus->pcms[0].r[1].rslots[0]) {
+ 		chip->dra = 1;
+@@ -2446,7 +2468,7 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
+ 		pci_write_config_dword(chip->pci, 0x4c, val);
+ 	}
+ 	/* --- */
+-	synchronize_irq(chip->irq);
++
+       __hw_end:
+ 	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+@@ -2495,7 +2517,6 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state)
+ 		chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
+ 
+ 	if (chip->irq >= 0) {
+-		synchronize_irq(chip->irq);
+ 		free_irq(chip->irq, chip);
+ 		chip->irq = -1;
+ 	}
+@@ -2648,7 +2669,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
+ 	t = stop_time.tv_sec - start_time.tv_sec;
+ 	t *= 1000000;
+ 	t += stop_time.tv_usec - start_time.tv_usec;
+-	printk(KERN_INFO "%s: measured %lu usecs\n", __FUNCTION__, t);
++	printk(KERN_INFO "%s: measured %lu usecs\n", __func__, t);
+ 	if (t == 0) {
+ 		snd_printk(KERN_ERR "?? calculation error..\n");
+ 		return;
+diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
+index cadda8d..faf674e 100644
+--- a/sound/pci/intel8x0m.c
++++ b/sound/pci/intel8x0m.c
+@@ -985,17 +985,15 @@ static int snd_intel8x0_free(struct intel8x0m *chip)
+ 	/* reset channels */
+ 	for (i = 0; i < chip->bdbars_count; i++)
+ 		iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);
+-	/* --- */
+-	synchronize_irq(chip->irq);
+-      __hw_end:
++ __hw_end:
++	if (chip->irq >= 0)
++		free_irq(chip->irq, chip);
+ 	if (chip->bdbars.area)
+ 		snd_dma_free_pages(&chip->bdbars);
+ 	if (chip->addr)
+ 		pci_iounmap(chip->pci, chip->addr);
+ 	if (chip->bmaddr)
+ 		pci_iounmap(chip->pci, chip->bmaddr);
+-	if (chip->irq >= 0)
+-		free_irq(chip->irq, chip);
+ 	pci_release_regions(chip->pci);
+ 	pci_disable_device(chip->pci);
+ 	kfree(chip);
+@@ -1017,7 +1015,6 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state)
+ 		snd_pcm_suspend_all(chip->pcm[i]);
+ 	snd_ac97_suspend(chip->ac97);
+ 	if (chip->irq >= 0) {
+-		synchronize_irq(chip->irq);
+ 		free_irq(chip->irq, chip);
+ 		chip->irq = -1;
+ 	}
+diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
+index 10c713d..f4c85b5 100644
+--- a/sound/pci/korg1212/korg1212.c
++++ b/sound/pci/korg1212/korg1212.c
+@@ -2102,7 +2102,6 @@ snd_korg1212_free(struct snd_korg1212 *korg1212)
+         snd_korg1212_TurnOffIdleMonitor(korg1212);
+ 
+         if (korg1212->irq >= 0) {
+-                synchronize_irq(korg1212->irq);                
+                 snd_korg1212_DisableCardInterrupts(korg1212);
+                 free_irq(korg1212->irq, korg1212);
+                 korg1212->irq = -1;
+diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
+index 04fa0a6..a536c59 100644
+--- a/sound/pci/maestro3.c
++++ b/sound/pci/maestro3.c
+@@ -2068,7 +2068,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
+ {
+ 	struct snd_ac97_bus *pbus;
+ 	struct snd_ac97_template ac97;
+-	struct snd_ctl_elem_id id;
++	struct snd_ctl_elem_id elem_id;
+ 	int err;
+ 	static struct snd_ac97_bus_ops ops = {
+ 		.write = snd_m3_ac97_write,
+@@ -2088,14 +2088,14 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
+ 	schedule_timeout_uninterruptible(msecs_to_jiffies(100));
+ 	snd_ac97_write(chip->ac97, AC97_PCM, 0);
+ 
+-	memset(&id, 0, sizeof(id));
+-	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+-	strcpy(id.name, "Master Playback Switch");
+-	chip->master_switch = snd_ctl_find_id(chip->card, &id);
+-	memset(&id, 0, sizeof(id));
+-	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+-	strcpy(id.name, "Master Playback Volume");
+-	chip->master_volume = snd_ctl_find_id(chip->card, &id);
++	memset(&elem_id, 0, sizeof(elem_id));
++	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++	strcpy(elem_id.name, "Master Playback Switch");
++	chip->master_switch = snd_ctl_find_id(chip->card, &elem_id);
++	memset(&elem_id, 0, sizeof(elem_id));
++	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++	strcpy(elem_id.name, "Master Playback Volume");
++	chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
+ 
+ 	return 0;
+ }
+@@ -2542,10 +2542,8 @@ static int snd_m3_free(struct snd_m3 *chip)
+ 	vfree(chip->suspend_mem);
+ #endif
+ 
+-	if (chip->irq >= 0) {
+-		synchronize_irq(chip->irq);
++	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+-	}
+ 
+ 	if (chip->iobase)
+ 		pci_release_regions(chip->pci);
+@@ -2569,7 +2567,7 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
+ {
+ 	struct snd_card *card = pci_get_drvdata(pci);
+ 	struct snd_m3 *chip = card->private_data;
+-	int i, index;
++	int i, dsp_index;
+ 
+ 	if (chip->suspend_mem == NULL)
+ 		return 0;
+@@ -2583,12 +2581,12 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
+ 	snd_m3_assp_halt(chip);
+ 
+ 	/* save dsp image */
+-	index = 0;
++	dsp_index = 0;
+ 	for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
+-		chip->suspend_mem[index++] = 
++		chip->suspend_mem[dsp_index++] =
+ 			snd_m3_assp_read(chip, MEMTYPE_INTERNAL_CODE, i);
+ 	for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
+-		chip->suspend_mem[index++] = 
++		chip->suspend_mem[dsp_index++] =
+ 			snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i);
+ 
+ 	pci_disable_device(pci);
+@@ -2601,7 +2599,7 @@ static int m3_resume(struct pci_dev *pci)
+ {
+ 	struct snd_card *card = pci_get_drvdata(pci);
+ 	struct snd_m3 *chip = card->private_data;
+-	int i, index;
++	int i, dsp_index;
+ 
+ 	if (chip->suspend_mem == NULL)
+ 		return 0;
+@@ -2625,13 +2623,13 @@ static int m3_resume(struct pci_dev *pci)
+ 	snd_m3_ac97_reset(chip);
+ 
+ 	/* restore dsp image */
+-	index = 0;
++	dsp_index = 0;
+ 	for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
+ 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, i, 
+-				  chip->suspend_mem[index++]);
++				  chip->suspend_mem[dsp_index++]);
+ 	for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
+ 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, i, 
+-				  chip->suspend_mem[index++]);
++				  chip->suspend_mem[dsp_index++]);
+ 
+ 	/* tell the dma engine to restart itself */
+ 	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, 
+diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
+index 7ac654e..7efb838 100644
+--- a/sound/pci/nm256/nm256.c
++++ b/sound/pci/nm256/nm256.c
+@@ -1439,7 +1439,7 @@ static int snd_nm256_free(struct nm256 *chip)
+ 		snd_nm256_capture_stop(chip);
+ 
+ 	if (chip->irq >= 0)
+-		synchronize_irq(chip->irq);
++		free_irq(chip->irq, chip);
+ 
+ 	if (chip->cport)
+ 		iounmap(chip->cport);
+@@ -1447,8 +1447,6 @@ static int snd_nm256_free(struct nm256 *chip)
+ 		iounmap(chip->buffer);
+ 	release_and_free_resource(chip->res_cport);
+ 	release_and_free_resource(chip->res_buffer);
+-	if (chip->irq >= 0)
+-		free_irq(chip->irq, chip);
+ 
+ 	pci_disable_device(chip->pci);
+ 	kfree(chip->ac97_regs);
+diff --git a/sound/pci/oxygen/cs4362a.h b/sound/pci/oxygen/cs4362a.h
+new file mode 100644
+index 0000000..6a4fedf
+--- /dev/null
++++ b/sound/pci/oxygen/cs4362a.h
+@@ -0,0 +1,69 @@
++/* register 01h */
++#define CS4362A_PDN		0x01
++#define CS4362A_DAC1_DIS	0x02
++#define CS4362A_DAC2_DIS	0x04
++#define CS4362A_DAC3_DIS	0x08
++#define CS4362A_MCLKDIV		0x20
++#define CS4362A_FREEZE		0x40
++#define CS4362A_CPEN		0x80
++/* register 02h */
++#define CS4362A_DIF_MASK	0x70
++#define CS4362A_DIF_LJUST	0x00
++#define CS4362A_DIF_I2S		0x10
++#define CS4362A_DIF_RJUST_16	0x20
++#define CS4362A_DIF_RJUST_24	0x30
++#define CS4362A_DIF_RJUST_20	0x40
++#define CS4362A_DIF_RJUST_18	0x50
++/* register 03h */
++#define CS4362A_MUTEC_MASK	0x03
++#define CS4362A_MUTEC_6		0x00
++#define CS4362A_MUTEC_1		0x01
++#define CS4362A_MUTEC_3		0x03
++#define CS4362A_AMUTE		0x04
++#define CS4362A_MUTEC_POL	0x08
++#define CS4362A_RMP_UP		0x10
++#define CS4362A_SNGLVOL		0x20
++#define CS4362A_ZERO_CROSS	0x40
++#define CS4362A_SOFT_RAMP	0x80
++/* register 04h */
++#define CS4362A_RMP_DN		0x01
++#define CS4362A_DEM_MASK	0x06
++#define CS4362A_DEM_NONE	0x00
++#define CS4362A_DEM_44100	0x02
++#define CS4362A_DEM_48000	0x04
++#define CS4362A_DEM_32000	0x06
++#define CS4362A_FILT_SEL	0x10
++/* register 05h */
++#define CS4362A_INV_A1		0x01
++#define CS4362A_INV_B1		0x02
++#define CS4362A_INV_A2		0x04
++#define CS4362A_INV_B2		0x08
++#define CS4362A_INV_A3		0x10
++#define CS4362A_INV_B3		0x20
++/* register 06h */
++#define CS4362A_FM_MASK		0x03
++#define CS4362A_FM_SINGLE	0x00
++#define CS4362A_FM_DOUBLE	0x01
++#define CS4362A_FM_QUAD		0x02
++#define CS4362A_FM_DSD		0x03
++#define CS4362A_ATAPI_MASK	0x7c
++#define CS4362A_ATAPI_B_MUTE	0x00
++#define CS4362A_ATAPI_B_R	0x04
++#define CS4362A_ATAPI_B_L	0x08
++#define CS4362A_ATAPI_B_LR	0x0c
++#define CS4362A_ATAPI_A_MUTE	0x00
++#define CS4362A_ATAPI_A_R	0x10
++#define CS4362A_ATAPI_A_L	0x20
++#define CS4362A_ATAPI_A_LR	0x30
++#define CS4362A_ATAPI_MIX_LR_VOL 0x40
++#define CS4362A_A_EQ_B		0x80
++/* register 07h */
++#define CS4362A_VOL_MASK		0x7f
++#define CS4362A_MUTE			0x80
++/* register 08h: like 07h */
++/* registers 09h..0Bh: like 06h..08h */
++/* registers 0Ch..0Eh: like 06h..08h */
++/* register 12h */
++#define CS4362A_REV_MASK	0x07
++#define CS4362A_PART_MASK	0xf8
++#define CS4362A_PART_CS4362A	0x50
+diff --git a/sound/pci/oxygen/cs4398.h b/sound/pci/oxygen/cs4398.h
+new file mode 100644
+index 0000000..5faf5ef
+--- /dev/null
++++ b/sound/pci/oxygen/cs4398.h
+@@ -0,0 +1,69 @@
++/* register 1 */
++#define CS4398_REV_MASK		0x07
++#define CS4398_PART_MASK	0xf8
++#define CS4398_PART_CS4398	0x70
++/* register 2 */
++#define CS4398_FM_MASK		0x03
++#define CS4398_FM_SINGLE	0x00
++#define CS4398_FM_DOUBLE	0x01
++#define CS4398_FM_QUAD		0x02
++#define CS4398_FM_DSD		0x03
++#define CS4398_DEM_MASK		0x0c
++#define CS4398_DEM_NONE		0x00
++#define CS4398_DEM_44100	0x04
++#define CS4398_DEM_48000	0x08
++#define CS4398_DEM_32000	0x0c
++#define CS4398_DIF_MASK		0x70
++#define CS4398_DIF_LJUST	0x00
++#define CS4398_DIF_I2S		0x10
++#define CS4398_DIF_RJUST_16	0x20
++#define CS4398_DIF_RJUST_24	0x30
++#define CS4398_DIF_RJUST_20	0x40
++#define CS4398_DIF_RJUST_18	0x50
++#define CS4398_DSD_SRC		0x80
++/* register 3 */
++#define CS4398_ATAPI_MASK	0x1f
++#define CS4398_ATAPI_B_MUTE	0x00
++#define CS4398_ATAPI_B_R	0x01
++#define CS4398_ATAPI_B_L	0x02
++#define CS4398_ATAPI_B_LR	0x03
++#define CS4398_ATAPI_A_MUTE	0x00
++#define CS4398_ATAPI_A_R	0x04
++#define CS4398_ATAPI_A_L	0x08
++#define CS4398_ATAPI_A_LR	0x0c
++#define CS4398_ATAPI_MIX_LR_VOL	0x10
++#define CS4398_INVERT_B		0x20
++#define CS4398_INVERT_A		0x40
++#define CS4398_VOL_B_EQ_A	0x80
++/* register 4 */
++#define CS4398_MUTEP_MASK	0x03
++#define CS4398_MUTEP_AUTO	0x00
++#define CS4398_MUTEP_LOW	0x02
++#define CS4398_MUTEP_HIGH	0x03
++#define CS4398_MUTE_B		0x08
++#define CS4398_MUTE_A		0x10
++#define CS4398_MUTEC_A_EQ_B	0x20
++#define CS4398_DAMUTE		0x40
++#define CS4398_PAMUTE		0x80
++/* register 5 */
++#define CS4398_VOL_A_MASK	0xff
++/* register 6 */
++#define CS4398_VOL_B_MASK	0xff
++/* register 7 */
++#define CS4398_DIR_DSD		0x01
++#define CS4398_FILT_SEL		0x04
++#define CS4398_RMP_DN		0x10
++#define CS4398_RMP_UP		0x20
++#define CS4398_ZERO_CROSS	0x40
++#define CS4398_SOFT_RAMP	0x80
++/* register 8 */
++#define CS4398_MCLKDIV3		0x08
++#define CS4398_MCLKDIV2		0x10
++#define CS4398_FREEZE		0x20
++#define CS4398_CPEN		0x40
++#define CS4398_PDN		0x80
++/* register 9 */
++#define CS4398_DSD_PM_EN	0x01
++#define CS4398_DSD_PM_MODE	0x02
++#define CS4398_INVALID_DSD	0x04
++#define CS4398_STATIC_DSD	0x08
+diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
+index 666f69a..090dd43 100644
+--- a/sound/pci/oxygen/hifier.c
++++ b/sound/pci/oxygen/hifier.c
+@@ -66,12 +66,12 @@ static void hifier_init(struct oxygen *chip)
+ {
+ 	struct hifier_data *data = chip->model_data;
+ 
+-	data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL;
++	data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+ 	ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
+ 	ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2);
+ 	ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM);
+-	ak4396_write(chip, AK4396_LCH_ATT, 0xff);
+-	ak4396_write(chip, AK4396_RCH_ATT, 0xff);
++	ak4396_write(chip, AK4396_LCH_ATT, 0);
++	ak4396_write(chip, AK4396_RCH_ATT, 0);
+ 
+ 	snd_component_add(chip->card, "AK4396");
+ 	snd_component_add(chip->card, "CS5340");
+@@ -127,22 +127,8 @@ static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
+ 
+ static int hifier_control_filter(struct snd_kcontrol_new *template)
+ {
+-	if (!strcmp(template->name, "Master Playback Volume")) {
+-		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+-		template->tlv.p = ak4396_db_scale;
+-	} else if (!strcmp(template->name, "Stereo Upmixing")) {
++	if (!strcmp(template->name, "Stereo Upmixing"))
+ 		return 1; /* stereo only - we don't need upmixing */
+-	} else if (!strcmp(template->name,
+-			   SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK)) ||
+-		   !strcmp(template->name,
+-			   SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT))) {
+-		return 1; /* no digital input */
+-	}
+-	return 0;
+-}
+-
+-static int hifier_mixer_init(struct oxygen *chip)
+-{
+ 	return 0;
+ }
+ 
+@@ -153,18 +139,20 @@ static const struct oxygen_model model_hifier = {
+ 	.owner = THIS_MODULE,
+ 	.init = hifier_init,
+ 	.control_filter = hifier_control_filter,
+-	.mixer_init = hifier_mixer_init,
+ 	.cleanup = hifier_cleanup,
+ 	.set_dac_params = set_ak4396_params,
+ 	.set_adc_params = set_cs5340_params,
+ 	.update_dac_volume = update_ak4396_volume,
+ 	.update_dac_mute = update_ak4396_mute,
++	.dac_tlv = ak4396_db_scale,
+ 	.model_data_size = sizeof(struct hifier_data),
++	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++		       PLAYBACK_1_TO_SPDIF |
++		       CAPTURE_0_FROM_I2S_1,
+ 	.dac_channels = 2,
+-	.used_channels = OXYGEN_CHANNEL_A |
+-			 OXYGEN_CHANNEL_SPDIF |
+-			 OXYGEN_CHANNEL_MULTICH,
+-	.function_flags = 0,
++	.dac_volume_min = 0,
++	.dac_volume_max = 255,
++	.function_flags = OXYGEN_FUNCTION_SPI,
+ 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+@@ -181,7 +169,7 @@ static int __devinit hifier_probe(struct pci_dev *pci,
+ 		++dev;
+ 		return -ENOENT;
+ 	}
+-	err = oxygen_pci_probe(pci, index[dev], id[dev], 0, &model_hifier);
++	err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier);
+ 	if (err >= 0)
+ 		++dev;
+ 	return err;
+diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
+index 9a9941b..63f185c 100644
+--- a/sound/pci/oxygen/oxygen.c
++++ b/sound/pci/oxygen/oxygen.c
+@@ -39,7 +39,7 @@
+ #include <sound/tlv.h>
+ #include "oxygen.h"
+ #include "ak4396.h"
+-#include "cm9780.h"
++#include "wm8785.h"
+ 
+ MODULE_AUTHOR("Clemens Ladisch <clemens at ladisch.de>");
+ MODULE_DESCRIPTION("C-Media CMI8788 driver");
+@@ -78,49 +78,6 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
+ #define GPIO_AK5385_DFS_DOUBLE	0x0001
+ #define GPIO_AK5385_DFS_QUAD	0x0002
+ 
+-#define GPIO_LINE_MUTE		CM9780_GPO0
+-
+-#define WM8785_R0	0
+-#define WM8785_R1	1
+-#define WM8785_R2	2
+-#define WM8785_R7	7
+-
+-/* R0 */
+-#define WM8785_MCR_MASK		0x007
+-#define WM8785_MCR_SLAVE	0x000
+-#define WM8785_MCR_MASTER_128	0x001
+-#define WM8785_MCR_MASTER_192	0x002
+-#define WM8785_MCR_MASTER_256	0x003
+-#define WM8785_MCR_MASTER_384	0x004
+-#define WM8785_MCR_MASTER_512	0x005
+-#define WM8785_MCR_MASTER_768	0x006
+-#define WM8785_OSR_MASK		0x018
+-#define WM8785_OSR_SINGLE	0x000
+-#define WM8785_OSR_DOUBLE	0x008
+-#define WM8785_OSR_QUAD		0x010
+-#define WM8785_FORMAT_MASK	0x060
+-#define WM8785_FORMAT_RJUST	0x000
+-#define WM8785_FORMAT_LJUST	0x020
+-#define WM8785_FORMAT_I2S	0x040
+-#define WM8785_FORMAT_DSP	0x060
+-/* R1 */
+-#define WM8785_WL_MASK		0x003
+-#define WM8785_WL_16		0x000
+-#define WM8785_WL_20		0x001
+-#define WM8785_WL_24		0x002
+-#define WM8785_WL_32		0x003
+-#define WM8785_LRP		0x004
+-#define WM8785_BCLKINV		0x008
+-#define WM8785_LRSWAP		0x010
+-#define WM8785_DEVNO_MASK	0x0e0
+-/* R2 */
+-#define WM8785_HPFR		0x001
+-#define WM8785_HPFL		0x002
+-#define WM8785_SDODIS		0x004
+-#define WM8785_PWRDNR		0x008
+-#define WM8785_PWRDNL		0x010
+-#define WM8785_TDM_MASK		0x1c0
+-
+ struct generic_data {
+ 	u8 ak4396_ctl2;
+ };
+@@ -155,7 +112,7 @@ static void ak4396_init(struct oxygen *chip)
+ 	struct generic_data *data = chip->model_data;
+ 	unsigned int i;
+ 
+-	data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL;
++	data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+ 	for (i = 0; i < 4; ++i) {
+ 		ak4396_write(chip, i,
+ 			     AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
+@@ -163,8 +120,8 @@ static void ak4396_init(struct oxygen *chip)
+ 			     AK4396_CONTROL_2, data->ak4396_ctl2);
+ 		ak4396_write(chip, i,
+ 			     AK4396_CONTROL_3, AK4396_PCM);
+-		ak4396_write(chip, i, AK4396_LCH_ATT, 0xff);
+-		ak4396_write(chip, i, AK4396_RCH_ATT, 0xff);
++		ak4396_write(chip, i, AK4396_LCH_ATT, 0);
++		ak4396_write(chip, i, AK4396_RCH_ATT, 0);
+ 	}
+ 	snd_component_add(chip->card, "AK4396");
+ }
+@@ -185,23 +142,16 @@ static void wm8785_init(struct oxygen *chip)
+ 	snd_component_add(chip->card, "WM8785");
+ }
+ 
+-static void cmi9780_init(struct oxygen *chip)
+-{
+-	oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE);
+-}
+-
+ static void generic_init(struct oxygen *chip)
+ {
+ 	ak4396_init(chip);
+ 	wm8785_init(chip);
+-	cmi9780_init(chip);
+ }
+ 
+ static void meridian_init(struct oxygen *chip)
+ {
+ 	ak4396_init(chip);
+ 	ak5385_init(chip);
+-	cmi9780_init(chip);
+ }
+ 
+ static void generic_cleanup(struct oxygen *chip)
+@@ -297,59 +247,32 @@ static void set_ak5385_params(struct oxygen *chip,
+ 			      value, GPIO_AK5385_DFS_MASK);
+ }
+ 
+-static void cmi9780_switch_hook(struct oxygen *chip, unsigned int codec,
+-				unsigned int reg, int mute)
+-{
+-	if (codec != 0)
+-		return;
+-	switch (reg) {
+-	case AC97_LINE:
+-		oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
+-					 mute ? GPIO_LINE_MUTE : 0,
+-					 GPIO_LINE_MUTE);
+-		break;
+-	case AC97_MIC:
+-	case AC97_CD:
+-	case AC97_AUX:
+-		if (!mute)
+-			oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS,
+-					     GPIO_LINE_MUTE);
+-		break;
+-	}
+-}
+-
+ static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
+ 
+-static int ak4396_control_filter(struct snd_kcontrol_new *template)
+-{
+-	if (!strcmp(template->name, "Master Playback Volume")) {
+-		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+-		template->tlv.p = ak4396_db_scale;
+-	}
+-	return 0;
+-}
+-
+ static const struct oxygen_model model_generic = {
+ 	.shortname = "C-Media CMI8788",
+ 	.longname = "C-Media Oxygen HD Audio",
+ 	.chip = "CMI8788",
+ 	.owner = THIS_MODULE,
+ 	.init = generic_init,
+-	.control_filter = ak4396_control_filter,
+ 	.cleanup = generic_cleanup,
+ 	.set_dac_params = set_ak4396_params,
+ 	.set_adc_params = set_wm8785_params,
+ 	.update_dac_volume = update_ak4396_volume,
+ 	.update_dac_mute = update_ak4396_mute,
+-	.ac97_switch_hook = cmi9780_switch_hook,
++	.dac_tlv = ak4396_db_scale,
+ 	.model_data_size = sizeof(struct generic_data),
++	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++		       PLAYBACK_1_TO_SPDIF |
++		       PLAYBACK_2_TO_AC97_1 |
++		       CAPTURE_0_FROM_I2S_1 |
++		       CAPTURE_1_FROM_SPDIF |
++		       CAPTURE_2_FROM_AC97_1,
+ 	.dac_channels = 8,
+-	.used_channels = OXYGEN_CHANNEL_A |
+-			 OXYGEN_CHANNEL_C |
+-			 OXYGEN_CHANNEL_SPDIF |
+-			 OXYGEN_CHANNEL_MULTICH |
+-			 OXYGEN_CHANNEL_AC97,
+-	.function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
++	.dac_volume_min = 0,
++	.dac_volume_max = 255,
++	.function_flags = OXYGEN_FUNCTION_SPI |
++			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+ 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+@@ -359,21 +282,25 @@ static const struct oxygen_model model_meridian = {
+ 	.chip = "CMI8788",
+ 	.owner = THIS_MODULE,
+ 	.init = meridian_init,
+-	.control_filter = ak4396_control_filter,
+ 	.cleanup = generic_cleanup,
+ 	.set_dac_params = set_ak4396_params,
+ 	.set_adc_params = set_ak5385_params,
+ 	.update_dac_volume = update_ak4396_volume,
+ 	.update_dac_mute = update_ak4396_mute,
+-	.ac97_switch_hook = cmi9780_switch_hook,
++	.dac_tlv = ak4396_db_scale,
+ 	.model_data_size = sizeof(struct generic_data),
++	.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++		       PLAYBACK_1_TO_SPDIF |
++		       PLAYBACK_2_TO_AC97_1 |
++		       CAPTURE_0_FROM_I2S_2 |
++		       CAPTURE_1_FROM_SPDIF |
++		       CAPTURE_2_FROM_AC97_1,
+ 	.dac_channels = 8,
+-	.used_channels = OXYGEN_CHANNEL_B |
+-			 OXYGEN_CHANNEL_C |
+-			 OXYGEN_CHANNEL_SPDIF |
+-			 OXYGEN_CHANNEL_MULTICH |
+-			 OXYGEN_CHANNEL_AC97,
+-	.function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
++	.dac_volume_min = 0,
++	.dac_volume_max = 255,
++	.misc_flags = OXYGEN_MISC_MIDI,
++	.function_flags = OXYGEN_FUNCTION_SPI |
++			  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+ 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ 	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+@@ -392,7 +319,7 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci,
+ 		return -ENOENT;
+ 	}
+ 	is_meridian = pci_id->driver_data;
+-	err = oxygen_pci_probe(pci, index[dev], id[dev], is_meridian,
++	err = oxygen_pci_probe(pci, index[dev], id[dev],
+ 			       is_meridian ? &model_meridian : &model_generic);
+ 	if (err >= 0)
+ 		++dev;
+diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
+index ad50fb8..a71c6e0 100644
+--- a/sound/pci/oxygen/oxygen.h
++++ b/sound/pci/oxygen/oxygen.h
+@@ -16,6 +16,16 @@
+ #define PCM_AC97	5
+ #define PCM_COUNT	6
+ 
++/* model-specific configuration of outputs/inputs */
++#define PLAYBACK_0_TO_I2S	0x001
++#define PLAYBACK_1_TO_SPDIF	0x004
++#define PLAYBACK_2_TO_AC97_1	0x008
++#define CAPTURE_0_FROM_I2S_1	0x010
++#define CAPTURE_0_FROM_I2S_2	0x020
++#define CAPTURE_1_FROM_SPDIF	0x080
++#define CAPTURE_2_FROM_I2S_2	0x100
++#define CAPTURE_2_FROM_AC97_1	0x200
++
+ enum {
+ 	CONTROL_SPDIF_PCM,
+ 	CONTROL_SPDIF_INPUT_BITS,
+@@ -87,12 +97,16 @@ struct oxygen_model {
+ 			       struct snd_pcm_hw_params *params);
+ 	void (*update_dac_volume)(struct oxygen *chip);
+ 	void (*update_dac_mute)(struct oxygen *chip);
+-	void (*ac97_switch_hook)(struct oxygen *chip, unsigned int codec,
+-				 unsigned int reg, int mute);
+ 	void (*gpio_changed)(struct oxygen *chip);
++	void (*ac97_switch)(struct oxygen *chip,
++			    unsigned int reg, unsigned int mute);
++	const unsigned int *dac_tlv;
+ 	size_t model_data_size;
++	unsigned int pcm_dev_cfg;
+ 	u8 dac_channels;
+-	u8 used_channels;
++	u8 dac_volume_min;
++	u8 dac_volume_max;
++	u8 misc_flags;
+ 	u8 function_flags;
+ 	u16 dac_i2s_format;
+ 	u16 adc_i2s_format;
+@@ -100,7 +114,7 @@ struct oxygen_model {
+ 
+ /* oxygen_lib.c */
+ 
+-int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, int midi,
++int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+ 		     const struct oxygen_model *model);
+ void oxygen_pci_remove(struct pci_dev *pci);
+ 
+@@ -137,6 +151,7 @@ void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec,
+ 			      unsigned int index, u16 data, u16 mask);
+ 
+ void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data);
++void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data);
+ 
+ static inline void oxygen_set_bits8(struct oxygen *chip,
+ 				    unsigned int reg, u8 value)
+diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c
+index 74e23ef..5569606 100644
+--- a/sound/pci/oxygen/oxygen_io.c
++++ b/sound/pci/oxygen/oxygen_io.c
+@@ -190,12 +190,31 @@ void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data)
+ 		--count;
+ 	}
+ 
+-	spin_lock_irq(&chip->reg_lock);
+ 	oxygen_write8(chip, OXYGEN_SPI_DATA1, data);
+ 	oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8);
+ 	if (control & OXYGEN_SPI_DATA_LENGTH_3)
+ 		oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16);
+ 	oxygen_write8(chip, OXYGEN_SPI_CONTROL, control);
+-	spin_unlock_irq(&chip->reg_lock);
+ }
+ EXPORT_SYMBOL(oxygen_write_spi);
++
++void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data)
++{
++	unsigned long timeout;
++
++	/* should not need more than about 300 us */
++	timeout = jiffies + msecs_to_jiffies(1);
++	do {
++		if (!(oxygen_read16(chip, OXYGEN_2WIRE_BUS_STATUS)
++		      & OXYGEN_2WIRE_BUSY))
++			break;
++		udelay(1);
++		cond_resched();
++	} while (time_after_eq(timeout, jiffies));
++
++	oxygen_write8(chip, OXYGEN_2WIRE_MAP, map);
++	oxygen_write8(chip, OXYGEN_2WIRE_DATA, data);
++	oxygen_write8(chip, OXYGEN_2WIRE_CONTROL,
++		      device | OXYGEN_2WIRE_DIR_WRITE);
++}
++EXPORT_SYMBOL(oxygen_write_i2c);
+diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
+index 78c2115..897697d 100644
+--- a/sound/pci/oxygen/oxygen_lib.c
++++ b/sound/pci/oxygen/oxygen_lib.c
+@@ -221,7 +221,8 @@ static void oxygen_init(struct oxygen *chip)
+ 
+ 	chip->dac_routing = 1;
+ 	for (i = 0; i < 8; ++i)
+-		chip->dac_volume[i] = 0xff;
++		chip->dac_volume[i] = chip->model->dac_volume_min;
++	chip->dac_mute = 1;
+ 	chip->spdif_playback_enable = 1;
+ 	chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL |
+ 		(IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT);
+@@ -240,12 +241,12 @@ static void oxygen_init(struct oxygen *chip)
+ 	chip->has_ac97_0 = (i & OXYGEN_AC97_CODEC_0) != 0;
+ 	chip->has_ac97_1 = (i & OXYGEN_AC97_CODEC_1) != 0;
+ 
+-	oxygen_set_bits8(chip, OXYGEN_FUNCTION,
+-			 OXYGEN_FUNCTION_RESET_CODEC |
+-			 chip->model->function_flags);
+ 	oxygen_write8_masked(chip, OXYGEN_FUNCTION,
+-			     OXYGEN_FUNCTION_SPI,
+-			     OXYGEN_FUNCTION_2WIRE_SPI_MASK);
++			     OXYGEN_FUNCTION_RESET_CODEC |
++			     chip->model->function_flags,
++			     OXYGEN_FUNCTION_RESET_CODEC |
++			     OXYGEN_FUNCTION_2WIRE_SPI_MASK |
++			     OXYGEN_FUNCTION_ENABLE_SPI_4_5);
+ 	oxygen_write8(chip, OXYGEN_DMA_STATUS, 0);
+ 	oxygen_write8(chip, OXYGEN_DMA_PAUSE, 0);
+ 	oxygen_write8(chip, OXYGEN_PLAY_CHANNELS,
+@@ -253,11 +254,13 @@ static void oxygen_init(struct oxygen *chip)
+ 		      OXYGEN_DMA_A_BURST_8 |
+ 		      OXYGEN_DMA_MULTICH_BURST_8);
+ 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
+-	oxygen_write8_masked(chip, OXYGEN_MISC, 0,
++	oxygen_write8_masked(chip, OXYGEN_MISC,
++			     chip->model->misc_flags,
+ 			     OXYGEN_MISC_WRITE_PCI_SUBID |
+ 			     OXYGEN_MISC_REC_C_FROM_SPDIF |
+ 			     OXYGEN_MISC_REC_B_FROM_AC97 |
+-			     OXYGEN_MISC_REC_A_FROM_MULTICH);
++			     OXYGEN_MISC_REC_A_FROM_MULTICH |
++			     OXYGEN_MISC_MIDI);
+ 	oxygen_write8(chip, OXYGEN_REC_FORMAT,
+ 		      (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_A_SHIFT) |
+ 		      (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_B_SHIFT) |
+@@ -267,35 +270,49 @@ static void oxygen_init(struct oxygen *chip)
+ 		      (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT));
+ 	oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2);
+ 	oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT,
+-		       OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
+-		       OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+-		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+-	oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
+-		       OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
+-		       OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+-		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+-	oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
+-		       OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
+-		       OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
++		       OXYGEN_RATE_48000 | chip->model->dac_i2s_format |
++		       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
+ 		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
++	if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1)
++		oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
++			       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
++			       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
++			       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
++	else
++		oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
++			       OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
++	if (chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_2 |
++					CAPTURE_2_FROM_I2S_2))
++		oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
++			       OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
++			       OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
++			       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
++	else
++		oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
++			       OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
+ 	oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
+-		       OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
+-		       OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+-		       OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+-	oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
+-			      OXYGEN_SPDIF_SENSE_MASK |
+-			      OXYGEN_SPDIF_LOCK_MASK |
+-			      OXYGEN_SPDIF_RATE_MASK |
+-			      OXYGEN_SPDIF_LOCK_PAR |
+-			      OXYGEN_SPDIF_IN_CLOCK_96,
+-			      OXYGEN_SPDIF_OUT_ENABLE |
+-			      OXYGEN_SPDIF_LOOPBACK |
+-			      OXYGEN_SPDIF_SENSE_MASK |
+-			      OXYGEN_SPDIF_LOCK_MASK |
+-			      OXYGEN_SPDIF_RATE_MASK |
+-			      OXYGEN_SPDIF_SENSE_PAR |
+-			      OXYGEN_SPDIF_LOCK_PAR |
+-			      OXYGEN_SPDIF_IN_CLOCK_MASK);
++		       OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
++	oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
++			    OXYGEN_SPDIF_OUT_ENABLE |
++			    OXYGEN_SPDIF_LOOPBACK);
++	if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF)
++		oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
++				      OXYGEN_SPDIF_SENSE_MASK |
++				      OXYGEN_SPDIF_LOCK_MASK |
++				      OXYGEN_SPDIF_RATE_MASK |
++				      OXYGEN_SPDIF_LOCK_PAR |
++				      OXYGEN_SPDIF_IN_CLOCK_96,
++				      OXYGEN_SPDIF_SENSE_MASK |
++				      OXYGEN_SPDIF_LOCK_MASK |
++				      OXYGEN_SPDIF_RATE_MASK |
++				      OXYGEN_SPDIF_SENSE_PAR |
++				      OXYGEN_SPDIF_LOCK_PAR |
++				      OXYGEN_SPDIF_IN_CLOCK_MASK);
++	else
++		oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
++				    OXYGEN_SPDIF_SENSE_MASK |
++				    OXYGEN_SPDIF_LOCK_MASK |
++				    OXYGEN_SPDIF_RATE_MASK);
+ 	oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits);
+ 	oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK);
+ 	oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0);
+@@ -318,9 +335,12 @@ static void oxygen_init(struct oxygen *chip)
+ 		      (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) |
+ 		      (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT));
+ 
+-	oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
+-		      OXYGEN_AC97_INT_READ_DONE |
+-		      OXYGEN_AC97_INT_WRITE_DONE);
++	if (chip->has_ac97_0 | chip->has_ac97_1)
++		oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
++			      OXYGEN_AC97_INT_READ_DONE |
++			      OXYGEN_AC97_INT_WRITE_DONE);
++	else
++		oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, 0);
+ 	oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0);
+ 	oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0);
+ 	if (!(chip->has_ac97_0 | chip->has_ac97_1))
+@@ -351,6 +371,8 @@ static void oxygen_init(struct oxygen *chip)
+ 		oxygen_write_ac97(chip, 0, AC97_REC_GAIN, 0x8000);
+ 		oxygen_write_ac97(chip, 0, AC97_CENTER_LFE_MASTER, 0x8080);
+ 		oxygen_write_ac97(chip, 0, AC97_SURROUND_MASTER, 0x8080);
++		oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS,
++				       CM9780_GPO0);
+ 		/* power down unused ADCs and DACs */
+ 		oxygen_ac97_set_bits(chip, 0, AC97_POWERDOWN,
+ 				     AC97_PD_PR0 | AC97_PD_PR1);
+@@ -388,10 +410,8 @@ static void oxygen_card_free(struct snd_card *card)
+ 	oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
+ 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
+ 	spin_unlock_irq(&chip->reg_lock);
+-	if (chip->irq >= 0) {
++	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+-		synchronize_irq(chip->irq);
+-	}
+ 	flush_scheduled_work();
+ 	chip->model->cleanup(chip);
+ 	mutex_destroy(&chip->mutex);
+@@ -400,7 +420,7 @@ static void oxygen_card_free(struct snd_card *card)
+ }
+ 
+ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+-		     int midi, const struct oxygen_model *model)
++		     const struct oxygen_model *model)
+ {
+ 	struct snd_card *card;
+ 	struct oxygen *chip;
+@@ -472,9 +492,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+ 	if (err < 0)
+ 		goto err_card;
+ 
+-	oxygen_write8_masked(chip, OXYGEN_MISC,
+-			     midi ? OXYGEN_MISC_MIDI : 0, OXYGEN_MISC_MIDI);
+-	if (midi) {
++	if (model->misc_flags & OXYGEN_MISC_MIDI) {
+ 		err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
+ 					  chip->addr + OXYGEN_MPU401,
+ 					  MPU401_INFO_INTEGRATED, 0, 0,
+@@ -486,7 +504,10 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+ 	oxygen_proc_init(chip);
+ 
+ 	spin_lock_irq(&chip->reg_lock);
+-	chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT | OXYGEN_INT_AC97;
++	if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF)
++		chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT;
++	if (chip->has_ac97_0 | chip->has_ac97_1)
++		chip->interrupt_mask |= OXYGEN_INT_AC97;
+ 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
+ 	spin_unlock_irq(&chip->reg_lock);
+ 
+diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
+index a8e4623..cc0cdda 100644
+--- a/sound/pci/oxygen/oxygen_mixer.c
++++ b/sound/pci/oxygen/oxygen_mixer.c
+@@ -32,8 +32,8 @@ static int dac_volume_info(struct snd_kcontrol *ctl,
+ 
+ 	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ 	info->count = chip->model->dac_channels;
+-	info->value.integer.min = 0;
+-	info->value.integer.max = 0xff;
++	info->value.integer.min = chip->model->dac_volume_min;
++	info->value.integer.max = chip->model->dac_volume_max;
+ 	return 0;
+ }
+ 
+@@ -446,6 +446,50 @@ static int spdif_loopback_put(struct snd_kcontrol *ctl,
+ 	return changed;
+ }
+ 
++static int monitor_volume_info(struct snd_kcontrol *ctl,
++			       struct snd_ctl_elem_info *info)
++{
++	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++	info->count = 1;
++	info->value.integer.min = 0;
++	info->value.integer.max = 1;
++	return 0;
++}
++
++static int monitor_get(struct snd_kcontrol *ctl,
++		       struct snd_ctl_elem_value *value)
++{
++	struct oxygen *chip = ctl->private_data;
++	u8 bit = ctl->private_value;
++	int invert = ctl->private_value & (1 << 8);
++
++	value->value.integer.value[0] =
++		!!invert ^ !!(oxygen_read8(chip, OXYGEN_ADC_MONITOR) & bit);
++	return 0;
++}
++
++static int monitor_put(struct snd_kcontrol *ctl,
++		       struct snd_ctl_elem_value *value)
++{
++	struct oxygen *chip = ctl->private_data;
++	u8 bit = ctl->private_value;
++	int invert = ctl->private_value & (1 << 8);
++	u8 oldreg, newreg;
++	int changed;
++
++	spin_lock_irq(&chip->reg_lock);
++	oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR);
++	if ((!!value->value.integer.value[0] ^ !!invert) != 0)
++		newreg = oldreg | bit;
++	else
++		newreg = oldreg & ~bit;
++	changed = newreg != oldreg;
++	if (changed)
++		oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg);
++	spin_unlock_irq(&chip->reg_lock);
++	return changed;
++}
++
+ static int ac97_switch_get(struct snd_kcontrol *ctl,
+ 			   struct snd_ctl_elem_value *value)
+ {
+@@ -466,6 +510,21 @@ static int ac97_switch_get(struct snd_kcontrol *ctl,
+ 	return 0;
+ }
+ 
++static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
++{
++	unsigned int priv_idx = chip->controls[control]->private_value & 0xff;
++	u16 value;
++
++	value = oxygen_read_ac97(chip, 0, priv_idx);
++	if (!(value & 0x8000)) {
++		oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000);
++		if (chip->model->ac97_switch)
++			chip->model->ac97_switch(chip, priv_idx, 0x8000);
++		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
++			       &chip->controls[control]->id);
++	}
++}
++
+ static int ac97_switch_put(struct snd_kcontrol *ctl,
+ 			   struct snd_ctl_elem_value *value)
+ {
+@@ -487,9 +546,24 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
+ 	change = newreg != oldreg;
+ 	if (change) {
+ 		oxygen_write_ac97(chip, codec, index, newreg);
+-		if (bitnr == 15 && chip->model->ac97_switch_hook)
+-			chip->model->ac97_switch_hook(chip, codec, index,
+-						      newreg & 0x8000);
++		if (codec == 0 && chip->model->ac97_switch)
++			chip->model->ac97_switch(chip, index, newreg & 0x8000);
++		if (index == AC97_LINE) {
++			oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
++						 newreg & 0x8000 ?
++						 CM9780_GPO0 : 0, CM9780_GPO0);
++			if (!(newreg & 0x8000)) {
++				mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH);
++				mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH);
++				mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH);
++			}
++		} else if ((index == AC97_MIC || index == AC97_CD ||
++			    index == AC97_VIDEO || index == AC97_AUX) &&
++			   bitnr == 15 && !(newreg & 0x8000)) {
++			mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH);
++			oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
++						 CM9780_GPO0, CM9780_GPO0);
++		}
+ 	}
+ 	mutex_unlock(&chip->mutex);
+ 	return change;
+@@ -608,6 +682,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
+ 		.private_value = ((codec) << 24) | (index), \
+ 	}
+ 
++static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0);
+ static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);
+ static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);
+ 
+@@ -667,6 +742,9 @@ static const struct snd_kcontrol_new controls[] = {
+ 		.get = spdif_pcm_get,
+ 		.put = spdif_pcm_put,
+ 	},
++};
++
++static const struct snd_kcontrol_new spdif_input_controls[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ 		.device = 1,
+@@ -692,11 +770,118 @@ static const struct snd_kcontrol_new controls[] = {
+ 	},
+ };
+ 
++static const struct {
++	unsigned int pcm_dev;
++	struct snd_kcontrol_new controls[2];
++} monitor_controls[] = {
++	{
++		.pcm_dev = CAPTURE_0_FROM_I2S_1,
++		.controls = {
++			{
++				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++				.name = "Analog Input Monitor Switch",
++				.info = snd_ctl_boolean_mono_info,
++				.get = monitor_get,
++				.put = monitor_put,
++				.private_value = OXYGEN_ADC_MONITOR_A,
++			},
++			{
++				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++				.name = "Analog Input Monitor Volume",
++				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
++				.info = monitor_volume_info,
++				.get = monitor_get,
++				.put = monitor_put,
++				.private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL
++						| (1 << 8),
++				.tlv = { .p = monitor_db_scale, },
++			},
++		},
++	},
++	{
++		.pcm_dev = CAPTURE_0_FROM_I2S_2,
++		.controls = {
++			{
++				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++				.name = "Analog Input Monitor Switch",
++				.info = snd_ctl_boolean_mono_info,
++				.get = monitor_get,
++				.put = monitor_put,
++				.private_value = OXYGEN_ADC_MONITOR_B,
++			},
++			{
++				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++				.name = "Analog Input Monitor Volume",
++				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
++				.info = monitor_volume_info,
++				.get = monitor_get,
++				.put = monitor_put,
++				.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL
++						| (1 << 8),
++				.tlv = { .p = monitor_db_scale, },
++			},
++		},
++	},
++	{
++		.pcm_dev = CAPTURE_2_FROM_I2S_2,
++		.controls = {
++			{
++				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++				.name = "Analog Input Monitor Switch",
++				.index = 1,
++				.info = snd_ctl_boolean_mono_info,
++				.get = monitor_get,
++				.put = monitor_put,
++				.private_value = OXYGEN_ADC_MONITOR_B,
++			},
++			{
++				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++				.name = "Analog Input Monitor Volume",
++				.index = 1,
++				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
++				.info = monitor_volume_info,
++				.get = monitor_get,
++				.put = monitor_put,
++				.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL
++						| (1 << 8),
++				.tlv = { .p = monitor_db_scale, },
++			},
++		},
++	},
++	{
++		.pcm_dev = CAPTURE_1_FROM_SPDIF,
++		.controls = {
++			{
++				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++				.name = "Digital Input Monitor Switch",
++				.info = snd_ctl_boolean_mono_info,
++				.get = monitor_get,
++				.put = monitor_put,
++				.private_value = OXYGEN_ADC_MONITOR_C,
++			},
++			{
++				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++				.name = "Digital Input Monitor Volume",
++				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
++				.info = monitor_volume_info,
++				.get = monitor_get,
++				.put = monitor_put,
++				.private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL
++						| (1 << 8),
++				.tlv = { .p = monitor_db_scale, },
++			},
++		},
++	},
++};
++
+ static const struct snd_kcontrol_new ac97_controls[] = {
+ 	AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC),
+ 	AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
+ 	AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0),
+-	AC97_VOLUME("Line Capture Volume", 0, AC97_LINE),
+ 	AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),
+ 	AC97_VOLUME("CD Capture Volume", 0, AC97_CD),
+ 	AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1),
+@@ -756,6 +941,11 @@ static int add_controls(struct oxygen *chip,
+ 			return err;
+ 		if (err == 1)
+ 			continue;
++		if (!strcmp(template.name, "Master Playback Volume") &&
++		    chip->model->dac_tlv) {
++			template.tlv.p = chip->model->dac_tlv;
++			template.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
++		}
+ 		ctl = snd_ctl_new1(&template, chip);
+ 		if (!ctl)
+ 			return -ENOMEM;
+@@ -773,11 +963,26 @@ static int add_controls(struct oxygen *chip,
+ 
+ int oxygen_mixer_init(struct oxygen *chip)
+ {
++	unsigned int i;
+ 	int err;
+ 
+ 	err = add_controls(chip, controls, ARRAY_SIZE(controls));
+ 	if (err < 0)
+ 		return err;
++	if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF) {
++		err = add_controls(chip, spdif_input_controls,
++				   ARRAY_SIZE(spdif_input_controls));
++		if (err < 0)
++			return err;
++	}
++	for (i = 0; i < ARRAY_SIZE(monitor_controls); ++i) {
++		if (!(chip->model->pcm_dev_cfg & monitor_controls[i].pcm_dev))
++			continue;
++		err = add_controls(chip, monitor_controls[i].controls,
++				   ARRAY_SIZE(monitor_controls[i].controls));
++		if (err < 0)
++			return err;
++	}
+ 	if (chip->has_ac97_0) {
+ 		err = add_controls(chip, ac97_controls,
+ 				   ARRAY_SIZE(ac97_controls));
+diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c
+index b70046a..b17c405 100644
+--- a/sound/pci/oxygen/oxygen_pcm.c
++++ b/sound/pci/oxygen/oxygen_pcm.c
+@@ -119,7 +119,7 @@ static int oxygen_open(struct snd_pcm_substream *substream,
+ 
+ 	runtime->private_data = (void *)(uintptr_t)channel;
+ 	if (channel == PCM_B && chip->has_ac97_1 &&
+-	    (chip->model->used_channels & OXYGEN_CHANNEL_AC97))
++	    (chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1))
+ 		runtime->hw = oxygen_ac97_hardware;
+ 	else
+ 		runtime->hw = *oxygen_hardware[channel];
+@@ -365,7 +365,7 @@ static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream,
+ 		return err;
+ 
+ 	is_ac97 = chip->has_ac97_1 &&
+-		(chip->model->used_channels & OXYGEN_CHANNEL_AC97);
++		(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1);
+ 
+ 	spin_lock_irq(&chip->reg_lock);
+ 	oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
+@@ -640,34 +640,39 @@ int oxygen_pcm_init(struct oxygen *chip)
+ 	int outs, ins;
+ 	int err;
+ 
+-	outs = 1; /* OXYGEN_CHANNEL_MULTICH is always used */
+-	ins = !!(chip->model->used_channels & (OXYGEN_CHANNEL_A |
+-					       OXYGEN_CHANNEL_B));
+-	err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
+-	if (err < 0)
+-		return err;
+-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_multich_ops);
+-	if (chip->model->used_channels & OXYGEN_CHANNEL_A)
+-		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+-				&oxygen_rec_a_ops);
+-	else if (chip->model->used_channels & OXYGEN_CHANNEL_B)
+-		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+-				&oxygen_rec_b_ops);
+-	pcm->private_data = chip;
+-	pcm->private_free = oxygen_pcm_free;
+-	strcpy(pcm->name, "Analog");
+-	snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+-				      SNDRV_DMA_TYPE_DEV,
+-				      snd_dma_pci_data(chip->pci),
+-				      512 * 1024, 2048 * 1024);
+-	if (ins)
+-		snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+-					      SNDRV_DMA_TYPE_DEV,
+-					      snd_dma_pci_data(chip->pci),
+-					      128 * 1024, 256 * 1024);
+-
+-	outs = !!(chip->model->used_channels & OXYGEN_CHANNEL_SPDIF);
+-	ins = !!(chip->model->used_channels & OXYGEN_CHANNEL_C);
++	outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_0_TO_I2S);
++	ins = !!(chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_1 |
++					     CAPTURE_0_FROM_I2S_2));
++	if (outs | ins) {
++		err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
++		if (err < 0)
++			return err;
++		if (outs)
++			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++					&oxygen_multich_ops);
++		if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1)
++			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
++					&oxygen_rec_a_ops);
++		else if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_2)
++			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
++					&oxygen_rec_b_ops);
++		pcm->private_data = chip;
++		pcm->private_free = oxygen_pcm_free;
++		strcpy(pcm->name, "Analog");
++		if (outs)
++			snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
++						      SNDRV_DMA_TYPE_DEV,
++						      snd_dma_pci_data(chip->pci),
++						      512 * 1024, 2048 * 1024);
++		if (ins)
++			snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
++						      SNDRV_DMA_TYPE_DEV,
++						      snd_dma_pci_data(chip->pci),
++						      128 * 1024, 256 * 1024);
++	}
++
++	outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_1_TO_SPDIF);
++	ins = !!(chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF);
+ 	if (outs | ins) {
+ 		err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm);
+ 		if (err < 0)
+@@ -686,12 +691,13 @@ int oxygen_pcm_init(struct oxygen *chip)
+ 						      128 * 1024, 256 * 1024);
+ 	}
+ 
+-	outs = chip->has_ac97_1 &&
+-		(chip->model->used_channels & OXYGEN_CHANNEL_AC97);
+-	ins = outs ||
+-		(chip->model->used_channels & (OXYGEN_CHANNEL_A |
+-					       OXYGEN_CHANNEL_B))
+-		== (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B);
++	if (chip->has_ac97_1) {
++		outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_2_TO_AC97_1);
++		ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1);
++	} else {
++		outs = 0;
++		ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_I2S_2);
++	}
+ 	if (outs | ins) {
+ 		err = snd_pcm_new(chip->card, outs ? "AC97" : "Analog2",
+ 				  2, outs, ins, &pcm);
+diff --git a/sound/pci/oxygen/pcm1796.h b/sound/pci/oxygen/pcm1796.h
+new file mode 100644
+index 0000000..698bf46
+--- /dev/null
++++ b/sound/pci/oxygen/pcm1796.h
+@@ -0,0 +1,58 @@
++#ifndef PCM1796_H_INCLUDED
++#define PCM1796_H_INCLUDED
++
++/* register 16 */
++#define PCM1796_ATL_MASK	0xff
++/* register 17 */
++#define PCM1796_ATR_MASK	0xff
++/* register 18 */
++#define PCM1796_MUTE		0x01
++#define PCM1796_DME		0x02
++#define PCM1796_DMF_MASK	0x0c
++#define PCM1796_DMF_DISABLED	0x00
++#define PCM1796_DMF_48		0x04
++#define PCM1796_DMF_441		0x08
++#define PCM1796_DMF_32		0x0c
++#define PCM1796_FMT_MASK	0x70
++#define PCM1796_FMT_16_RJUST	0x00
++#define PCM1796_FMT_20_RJUST	0x10
++#define PCM1796_FMT_24_RJUST	0x20
++#define PCM1796_FMT_24_LJUST	0x30
++#define PCM1796_FMT_16_I2S	0x40
++#define PCM1796_FMT_24_I2S	0x50
++#define PCM1796_ATLD		0x80
++/* register 19 */
++#define PCM1796_INZD		0x01
++#define PCM1796_FLT_MASK	0x02
++#define PCM1796_FLT_SHARP	0x00
++#define PCM1796_FLT_SLOW	0x02
++#define PCM1796_DFMS		0x04
++#define PCM1796_OPE		0x10
++#define PCM1796_ATS_MASK	0x60
++#define PCM1796_ATS_1		0x00
++#define PCM1796_ATS_2		0x20
++#define PCM1796_ATS_4		0x40
++#define PCM1796_ATS_8		0x60
++#define PCM1796_REV		0x80
++/* register 20 */
++#define PCM1796_OS_MASK		0x03
++#define PCM1796_OS_64		0x00
++#define PCM1796_OS_32		0x01
++#define PCM1796_OS_128		0x02
++#define PCM1796_CHSL_MASK	0x04
++#define PCM1796_CHSL_LEFT	0x00
++#define PCM1796_CHSL_RIGHT	0x04
++#define PCM1796_MONO		0x08
++#define PCM1796_DFTH		0x10
++#define PCM1796_DSD		0x20
++#define PCM1796_SRST		0x40
++/* register 21 */
++#define PCM1796_PCMZ		0x01
++#define PCM1796_DZ_MASK		0x06
++/* register 22 */
++#define PCM1796_ZFGL		0x01
++#define PCM1796_ZFGR		0x02
++/* register 23 */
++#define PCM1796_ID_MASK		0x1f
++
++#endif
+diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
+index d163397..7f84fa5 100644
+--- a/sound/pci/oxygen/virtuoso.c
++++ b/sound/pci/oxygen/virtuoso.c
+@@ -18,6 +18,9 @@
+  */
+ 
+ /*
++ * Xonar D2/D2X
++ * ------------
++ *
+  * CMI8788:
+  *
+  * SPI 0 -> 1st PCM1796 (front)
+@@ -30,10 +33,33 @@
+  * GPIO 5 <- external power present (D2X only)
+  * GPIO 7 -> ALT
+  * GPIO 8 -> enable output to speakers
++ */
++
++/*
++ * Xonar DX
++ * --------
++ *
++ * CMI8788:
++ *
++ * I²C <-> CS4398 (front)
++ *     <-> CS4362A (surround, center/LFE, back)
++ *
++ * GPI 0 <- external power present
+  *
+- * CM9780:
++ * GPIO 0 -> enable output to speakers
++ * GPIO 1 -> enable front panel I/O
++ * GPIO 2 -> M0 of CS5361
++ * GPIO 3 -> M1 of CS5361
++ * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
+  *
+- * GPIO 0 -> enable AC'97 bypass (line in -> ADC)
++ * CS4398:
++ *
++ * AD0 <- 1
++ * AD1 <- 1
++ *
++ * CS4362A:
++ *
++ * AD0 <- 0
+  */
+ 
+ #include <linux/pci.h>
+@@ -47,11 +73,14 @@
+ #include <sound/tlv.h>
+ #include "oxygen.h"
+ #include "cm9780.h"
++#include "pcm1796.h"
++#include "cs4398.h"
++#include "cs4362a.h"
+ 
+ MODULE_AUTHOR("Clemens Ladisch <clemens at ladisch.de>");
+-MODULE_DESCRIPTION("Asus AV200 driver");
++MODULE_DESCRIPTION("Asus AVx00 driver");
+ MODULE_LICENSE("GPL");
+-MODULE_SUPPORTED_DEVICE("{{Asus,AV200}}");
++MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}");
+ 
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+@@ -64,80 +93,44 @@ MODULE_PARM_DESC(id, "ID string");
+ module_param_array(enable, bool, NULL, 0444);
+ MODULE_PARM_DESC(enable, "enable card");
+ 
++enum {
++	MODEL_D2,
++	MODEL_D2X,
++	MODEL_DX,
++};
++
+ static struct pci_device_id xonar_ids[] __devinitdata = {
+-	{ OXYGEN_PCI_SUBID(0x1043, 0x8269) }, /* Asus Xonar D2 */
+-	{ OXYGEN_PCI_SUBID(0x1043, 0x82b7) }, /* Asus Xonar D2X */
++	{ OXYGEN_PCI_SUBID(0x1043, 0x8269), .driver_data = MODEL_D2 },
++	{ OXYGEN_PCI_SUBID(0x1043, 0x8275), .driver_data = MODEL_DX },
++	{ OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
+ 	{ }
+ };
+ MODULE_DEVICE_TABLE(pci, xonar_ids);
+ 
+ 
+-#define GPIO_CS5381_M_MASK	0x000c
+-#define GPIO_CS5381_M_SINGLE	0x0000
+-#define GPIO_CS5381_M_DOUBLE	0x0004
+-#define GPIO_CS5381_M_QUAD	0x0008
+-#define GPIO_EXT_POWER		0x0020
+-#define GPIO_ALT		0x0080
+-#define GPIO_OUTPUT_ENABLE	0x0100
+-
+-#define GPIO_LINE_MUTE		CM9780_GPO0
+-
+-/* register 16 */
+-#define PCM1796_ATL_MASK	0xff
+-/* register 17 */
+-#define PCM1796_ATR_MASK	0xff
+-/* register 18 */
+-#define PCM1796_MUTE		0x01
+-#define PCM1796_DME		0x02
+-#define PCM1796_DMF_MASK	0x0c
+-#define PCM1796_DMF_DISABLED	0x00
+-#define PCM1796_DMF_48		0x04
+-#define PCM1796_DMF_441		0x08
+-#define PCM1796_DMF_32		0x0c
+-#define PCM1796_FMT_MASK	0x70
+-#define PCM1796_FMT_16_RJUST	0x00
+-#define PCM1796_FMT_20_RJUST	0x10
+-#define PCM1796_FMT_24_RJUST	0x20
+-#define PCM1796_FMT_24_LJUST	0x30
+-#define PCM1796_FMT_16_I2S	0x40
+-#define PCM1796_FMT_24_I2S	0x50
+-#define PCM1796_ATLD		0x80
+-/* register 19 */
+-#define PCM1796_INZD		0x01
+-#define PCM1796_FLT_MASK	0x02
+-#define PCM1796_FLT_SHARP	0x00
+-#define PCM1796_FLT_SLOW	0x02
+-#define PCM1796_DFMS		0x04
+-#define PCM1796_OPE		0x10
+-#define PCM1796_ATS_MASK	0x60
+-#define PCM1796_ATS_1		0x00
+-#define PCM1796_ATS_2		0x20
+-#define PCM1796_ATS_4		0x40
+-#define PCM1796_ATS_8		0x60
+-#define PCM1796_REV		0x80
+-/* register 20 */
+-#define PCM1796_OS_MASK		0x03
+-#define PCM1796_OS_64		0x00
+-#define PCM1796_OS_32		0x01
+-#define PCM1796_OS_128		0x02
+-#define PCM1796_CHSL_MASK	0x04
+-#define PCM1796_CHSL_LEFT	0x00
+-#define PCM1796_CHSL_RIGHT	0x04
+-#define PCM1796_MONO		0x08
+-#define PCM1796_DFTH		0x10
+-#define PCM1796_DSD		0x20
+-#define PCM1796_SRST		0x40
+-/* register 21 */
+-#define PCM1796_PCMZ		0x01
+-#define PCM1796_DZ_MASK		0x06
+-/* register 22 */
+-#define PCM1796_ZFGL		0x01
+-#define PCM1796_ZFGR		0x02
+-/* register 23 */
+-#define PCM1796_ID_MASK		0x1f
++#define GPIO_CS53x1_M_MASK	0x000c
++#define GPIO_CS53x1_M_SINGLE	0x0000
++#define GPIO_CS53x1_M_DOUBLE	0x0004
++#define GPIO_CS53x1_M_QUAD	0x0008
++
++#define GPIO_D2X_EXT_POWER	0x0020
++#define GPIO_D2_ALT		0x0080
++#define GPIO_D2_OUTPUT_ENABLE	0x0100
++
++#define GPI_DX_EXT_POWER	0x01
++#define GPIO_DX_OUTPUT_ENABLE	0x0001
++#define GPIO_DX_FRONT_PANEL	0x0002
++#define GPIO_DX_INPUT_ROUTE	0x0100
++
++#define I2C_DEVICE_CS4398	0x9e	/* 10011, AD1=1, AD0=1, /W=0 */
++#define I2C_DEVICE_CS4362A	0x30	/* 001100, AD0=0, /W=0 */
+ 
+ struct xonar_data {
+-	u8 is_d2x;
++	unsigned int anti_pop_delay;
++	u16 output_enable_bit;
++	u8 ext_power_reg;
++	u8 ext_power_int_reg;
++	u8 ext_power_bit;
+ 	u8 has_power;
+ };
+ 
+@@ -156,62 +149,157 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec,
+ 			 (reg << 8) | value);
+ }
+ 
+-static void xonar_init(struct oxygen *chip)
++static void cs4398_write(struct oxygen *chip, u8 reg, u8 value)
++{
++	oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value);
++}
++
++static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
++{
++	oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
++}
++
++static void xonar_common_init(struct oxygen *chip)
++{
++	struct xonar_data *data = chip->model_data;
++
++	if (data->ext_power_reg) {
++		oxygen_set_bits8(chip, data->ext_power_int_reg,
++				 data->ext_power_bit);
++		chip->interrupt_mask |= OXYGEN_INT_GPIO;
++		data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
++				     & data->ext_power_bit);
++	}
++	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK);
++	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
++			      GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK);
++	oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
++	msleep(data->anti_pop_delay);
++	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit);
++	oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
++}
++
++static void xonar_d2_init(struct oxygen *chip)
+ {
+ 	struct xonar_data *data = chip->model_data;
+ 	unsigned int i;
+ 
+-	data->is_d2x = chip->pci->subsystem_device == 0x82b7;
++	data->anti_pop_delay = 300;
++	data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
+ 
+ 	for (i = 0; i < 4; ++i) {
+-		pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD);
++		pcm1796_write(chip, i, 18, PCM1796_MUTE | PCM1796_DMF_DISABLED |
++			      PCM1796_FMT_24_LJUST | PCM1796_ATLD);
+ 		pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
+ 		pcm1796_write(chip, i, 20, PCM1796_OS_64);
+ 		pcm1796_write(chip, i, 21, 0);
+-		pcm1796_write(chip, i, 16, 0xff); /* set ATL/ATR after ATLD */
+-		pcm1796_write(chip, i, 17, 0xff);
++		pcm1796_write(chip, i, 16, 0x0f); /* set ATL/ATR after ATLD */
++		pcm1796_write(chip, i, 17, 0x0f);
+ 	}
+ 
+-	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+-			  GPIO_CS5381_M_MASK | GPIO_ALT);
+-	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+-			      GPIO_CS5381_M_SINGLE,
+-			      GPIO_CS5381_M_MASK | GPIO_ALT);
+-	if (data->is_d2x) {
+-		oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
+-				    GPIO_EXT_POWER);
+-		oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK,
+-				  GPIO_EXT_POWER);
+-		chip->interrupt_mask |= OXYGEN_INT_GPIO;
+-		data->has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
+-				     & GPIO_EXT_POWER);
+-	}
+-	oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
+-	oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE);
+-	msleep(300);
+-	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_OUTPUT_ENABLE);
+-	oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
++	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT);
++	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT);
++
++	xonar_common_init(chip);
+ 
+ 	snd_component_add(chip->card, "PCM1796");
+ 	snd_component_add(chip->card, "CS5381");
+ }
+ 
++static void xonar_d2x_init(struct oxygen *chip)
++{
++	struct xonar_data *data = chip->model_data;
++
++	data->ext_power_reg = OXYGEN_GPIO_DATA;
++	data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK;
++	data->ext_power_bit = GPIO_D2X_EXT_POWER;
++	oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER);
++	xonar_d2_init(chip);
++}
++
++static void xonar_dx_init(struct oxygen *chip)
++{
++	struct xonar_data *data = chip->model_data;
++
++	data->anti_pop_delay = 800;
++	data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
++	data->ext_power_reg = OXYGEN_GPI_DATA;
++	data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
++	data->ext_power_bit = GPI_DX_EXT_POWER;
++
++	oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
++		       OXYGEN_2WIRE_LENGTH_8 |
++		       OXYGEN_2WIRE_INTERRUPT_MASK |
++		       OXYGEN_2WIRE_SPEED_FAST);
++
++	/* set CPEN (control port mode) and power down */
++	cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
++	cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
++	/* configure */
++	cs4398_write(chip, 2, CS4398_FM_SINGLE |
++		     CS4398_DEM_NONE | CS4398_DIF_LJUST);
++	cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
++	cs4398_write(chip, 4, CS4398_MUTEP_LOW | CS4398_PAMUTE);
++	cs4398_write(chip, 5, 0xfe);
++	cs4398_write(chip, 6, 0xfe);
++	cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
++		     CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
++	cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
++	cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE |
++		      CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
++	cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE);
++	cs4362a_write(chip, 0x05, 0);
++	cs4362a_write(chip, 0x06, CS4362A_FM_SINGLE |
++		      CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
++	cs4362a_write(chip, 0x07, 0x7f | CS4362A_MUTE);
++	cs4362a_write(chip, 0x08, 0x7f | CS4362A_MUTE);
++	cs4362a_write(chip, 0x09, CS4362A_FM_SINGLE |
++		      CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
++	cs4362a_write(chip, 0x0a, 0x7f | CS4362A_MUTE);
++	cs4362a_write(chip, 0x0b, 0x7f | CS4362A_MUTE);
++	cs4362a_write(chip, 0x0c, CS4362A_FM_SINGLE |
++		      CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
++	cs4362a_write(chip, 0x0d, 0x7f | CS4362A_MUTE);
++	cs4362a_write(chip, 0x0e, 0x7f | CS4362A_MUTE);
++	/* clear power down */
++	cs4398_write(chip, 8, CS4398_CPEN);
++	cs4362a_write(chip, 0x01, CS4362A_CPEN);
++
++	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
++			  GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
++	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
++			    GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
++
++	xonar_common_init(chip);
++
++	snd_component_add(chip->card, "CS4398");
++	snd_component_add(chip->card, "CS4362A");
++	snd_component_add(chip->card, "CS5361");
++}
++
+ static void xonar_cleanup(struct oxygen *chip)
+ {
+-	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
++	struct xonar_data *data = chip->model_data;
++
++	oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
++}
++
++static void xonar_dx_cleanup(struct oxygen *chip)
++{
++	xonar_cleanup(chip);
++	cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
++	oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
+ }
+ 
+ static void set_pcm1796_params(struct oxygen *chip,
+ 			       struct snd_pcm_hw_params *params)
+ {
+-#if 0
+ 	unsigned int i;
+ 	u8 value;
+ 
+ 	value = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64;
+ 	for (i = 0; i < 4; ++i)
+ 		pcm1796_write(chip, i, 20, value);
+-#endif
+ }
+ 
+ static void update_pcm1796_volume(struct oxygen *chip)
+@@ -236,19 +324,73 @@ static void update_pcm1796_mute(struct oxygen *chip)
+ 		pcm1796_write(chip, i, 18, value);
+ }
+ 
+-static void set_cs5381_params(struct oxygen *chip,
++static void set_cs53x1_params(struct oxygen *chip,
+ 			      struct snd_pcm_hw_params *params)
+ {
+ 	unsigned int value;
+ 
+ 	if (params_rate(params) <= 54000)
+-		value = GPIO_CS5381_M_SINGLE;
++		value = GPIO_CS53x1_M_SINGLE;
+ 	else if (params_rate(params) <= 108000)
+-		value = GPIO_CS5381_M_DOUBLE;
++		value = GPIO_CS53x1_M_DOUBLE;
+ 	else
+-		value = GPIO_CS5381_M_QUAD;
++		value = GPIO_CS53x1_M_QUAD;
+ 	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+-			      value, GPIO_CS5381_M_MASK);
++			      value, GPIO_CS53x1_M_MASK);
++}
++
++static void set_cs43xx_params(struct oxygen *chip,
++			      struct snd_pcm_hw_params *params)
++{
++	u8 fm_cs4398, fm_cs4362a;
++
++	fm_cs4398 = CS4398_DEM_NONE | CS4398_DIF_LJUST;
++	fm_cs4362a = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
++	if (params_rate(params) <= 50000) {
++		fm_cs4398 |= CS4398_FM_SINGLE;
++		fm_cs4362a |= CS4362A_FM_SINGLE;
++	} else if (params_rate(params) <= 100000) {
++		fm_cs4398 |= CS4398_FM_DOUBLE;
++		fm_cs4362a |= CS4362A_FM_DOUBLE;
++	} else {
++		fm_cs4398 |= CS4398_FM_QUAD;
++		fm_cs4362a |= CS4362A_FM_QUAD;
++	}
++	cs4398_write(chip, 2, fm_cs4398);
++	cs4362a_write(chip, 0x06, fm_cs4362a);
++	cs4362a_write(chip, 0x09, fm_cs4362a);
++	cs4362a_write(chip, 0x0c, fm_cs4362a);
++}
++
++static void update_cs4362a_volumes(struct oxygen *chip)
++{
++	u8 mute;
++
++	mute = chip->dac_mute ? CS4362A_MUTE : 0;
++	cs4362a_write(chip, 7, (127 - chip->dac_volume[2]) | mute);
++	cs4362a_write(chip, 8, (127 - chip->dac_volume[3]) | mute);
++	cs4362a_write(chip, 10, (127 - chip->dac_volume[4]) | mute);
++	cs4362a_write(chip, 11, (127 - chip->dac_volume[5]) | mute);
++	cs4362a_write(chip, 13, (127 - chip->dac_volume[6]) | mute);
++	cs4362a_write(chip, 14, (127 - chip->dac_volume[7]) | mute);
++}
++
++static void update_cs43xx_volume(struct oxygen *chip)
++{
++	cs4398_write(chip, 5, (127 - chip->dac_volume[0]) * 2);
++	cs4398_write(chip, 6, (127 - chip->dac_volume[1]) * 2);
++	update_cs4362a_volumes(chip);
++}
++
++static void update_cs43xx_mute(struct oxygen *chip)
++{
++	u8 reg;
++
++	reg = CS4398_MUTEP_LOW | CS4398_PAMUTE;
++	if (chip->dac_mute)
++		reg |= CS4398_MUTE_B | CS4398_MUTE_A;
++	cs4398_write(chip, 4, reg);
++	update_cs4362a_volumes(chip);
+ }
+ 
+ static void xonar_gpio_changed(struct oxygen *chip)
+@@ -256,10 +398,8 @@ static void xonar_gpio_changed(struct oxygen *chip)
+ 	struct xonar_data *data = chip->model_data;
+ 	u8 has_power;
+ 
+-	if (!data->is_d2x)
+-		return;
+-	has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
+-		       & GPIO_EXT_POWER);
++	has_power = !!(oxygen_read8(chip, data->ext_power_reg)
++		       & data->ext_power_bit);
+ 	if (has_power != data->has_power) {
+ 		data->has_power = has_power;
+ 		if (has_power) {
+@@ -272,66 +412,13 @@ static void xonar_gpio_changed(struct oxygen *chip)
+ 	}
+ }
+ 
+-static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
+-{
+-	unsigned int index = chip->controls[control]->private_value & 0xff;
+-	u16 value;
+-
+-	value = oxygen_read_ac97(chip, 0, index);
+-	if (!(value & 0x8000)) {
+-		oxygen_write_ac97(chip, 0, index, value | 0x8000);
+-		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+-			       &chip->controls[control]->id);
+-	}
+-}
+-
+-static void xonar_ac97_switch_hook(struct oxygen *chip, unsigned int codec,
+-				   unsigned int reg, int mute)
+-{
+-	if (codec != 0)
+-		return;
+-	/* line-in is exclusive */
+-	switch (reg) {
+-	case AC97_LINE:
+-		oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
+-					 mute ? GPIO_LINE_MUTE : 0,
+-					 GPIO_LINE_MUTE);
+-		if (!mute) {
+-			mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH);
+-			mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH);
+-			mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH);
+-		}
+-		break;
+-	case AC97_MIC:
+-	case AC97_CD:
+-	case AC97_VIDEO:
+-	case AC97_AUX:
+-		if (!mute) {
+-			oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS,
+-					     GPIO_LINE_MUTE);
+-			mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH);
+-		}
+-		break;
+-	}
+-}
+-
+-static int pcm1796_volume_info(struct snd_kcontrol *ctl,
+-			       struct snd_ctl_elem_info *info)
+-{
+-	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+-	info->count = 8;
+-	info->value.integer.min = 0x0f;
+-	info->value.integer.max = 0xff;
+-	return 0;
+-}
+-
+ static int alt_switch_get(struct snd_kcontrol *ctl,
+ 			  struct snd_ctl_elem_value *value)
+ {
+ 	struct oxygen *chip = ctl->private_data;
+ 
+ 	value->value.integer.value[0] =
+-		!!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_ALT);
++		!!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_D2_ALT);
+ 	return 0;
+ }
+ 
+@@ -345,9 +432,9 @@ static int alt_switch_put(struct snd_kcontrol *ctl,
+ 	spin_lock_irq(&chip->reg_lock);
+ 	old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+ 	if (value->value.integer.value[0])
+-		new_bits = old_bits | GPIO_ALT;
++		new_bits = old_bits | GPIO_D2_ALT;
+ 	else
+-		new_bits = old_bits & ~GPIO_ALT;
++		new_bits = old_bits & ~GPIO_D2_ALT;
+ 	changed = new_bits != old_bits;
+ 	if (changed)
+ 		oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits);
+@@ -363,20 +450,68 @@ static const struct snd_kcontrol_new alt_switch = {
+ 	.put = alt_switch_put,
+ };
+ 
++static int front_panel_get(struct snd_kcontrol *ctl,
++			   struct snd_ctl_elem_value *value)
++{
++	struct oxygen *chip = ctl->private_data;
++
++	value->value.integer.value[0] =
++		!!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DX_FRONT_PANEL);
++	return 0;
++}
++
++static int front_panel_put(struct snd_kcontrol *ctl,
++			   struct snd_ctl_elem_value *value)
++{
++	struct oxygen *chip = ctl->private_data;
++	u16 old_reg, new_reg;
++
++	spin_lock_irq(&chip->reg_lock);
++	old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA);
++	if (value->value.integer.value[0])
++		new_reg = old_reg | GPIO_DX_FRONT_PANEL;
++	else
++		new_reg = old_reg & ~GPIO_DX_FRONT_PANEL;
++	oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg);
++	spin_unlock_irq(&chip->reg_lock);
++	return old_reg != new_reg;
++}
++
++static const struct snd_kcontrol_new front_panel_switch = {
++	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++	.name = "Front Panel Switch",
++	.info = snd_ctl_boolean_mono_info,
++	.get = front_panel_get,
++	.put = front_panel_put,
++};
++
++static void xonar_dx_ac97_switch(struct oxygen *chip,
++				 unsigned int reg, unsigned int mute)
++{
++	if (reg == AC97_LINE) {
++		spin_lock_irq(&chip->reg_lock);
++		oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
++				      mute ? GPIO_DX_INPUT_ROUTE : 0,
++				      GPIO_DX_INPUT_ROUTE);
++		spin_unlock_irq(&chip->reg_lock);
++	}
++}
++
+ static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0);
++static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0);
+ 
+-static int xonar_control_filter(struct snd_kcontrol_new *template)
++static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
+ {
+-	if (!strcmp(template->name, "Master Playback Volume")) {
+-		template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+-		template->info = pcm1796_volume_info,
+-		template->tlv.p = pcm1796_db_scale;
+-	} else if (!strncmp(template->name, "CD Capture ", 11)) {
++	if (!strncmp(template->name, "CD Capture ", 11))
+ 		/* CD in is actually connected to the video in pin */
+ 		template->private_value ^= AC97_CD ^ AC97_VIDEO;
+-	} else if (!strcmp(template->name, "Line Capture Volume")) {
+-		return 1; /* line-in bypasses the AC'97 mixer */
+-	}
++	return 0;
++}
++
++static int xonar_dx_control_filter(struct snd_kcontrol_new *template)
++{
++	if (!strncmp(template->name, "CD Capture ", 11))
++		return 1; /* no CD input */
+ 	return 0;
+ }
+ 
+@@ -385,30 +520,96 @@ static int xonar_mixer_init(struct oxygen *chip)
+ 	return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
+ }
+ 
+-static const struct oxygen_model model_xonar = {
+-	.shortname = "Asus AV200",
+-	.longname = "Asus Virtuoso 200",
+-	.chip = "AV200",
+-	.owner = THIS_MODULE,
+-	.init = xonar_init,
+-	.control_filter = xonar_control_filter,
+-	.mixer_init = xonar_mixer_init,
+-	.cleanup = xonar_cleanup,
+-	.set_dac_params = set_pcm1796_params,
+-	.set_adc_params = set_cs5381_params,
+-	.update_dac_volume = update_pcm1796_volume,
+-	.update_dac_mute = update_pcm1796_mute,
+-	.ac97_switch_hook = xonar_ac97_switch_hook,
+-	.gpio_changed = xonar_gpio_changed,
+-	.model_data_size = sizeof(struct xonar_data),
+-	.dac_channels = 8,
+-	.used_channels = OXYGEN_CHANNEL_B |
+-			 OXYGEN_CHANNEL_C |
+-			 OXYGEN_CHANNEL_SPDIF |
+-			 OXYGEN_CHANNEL_MULTICH,
+-	.function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+-	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+-	.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++static int xonar_dx_mixer_init(struct oxygen *chip)
++{
++	return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
++}
++
++static const struct oxygen_model xonar_models[] = {
++	[MODEL_D2] = {
++		.shortname = "Xonar D2",
++		.longname = "Asus Virtuoso 200",
++		.chip = "AV200",
++		.owner = THIS_MODULE,
++		.init = xonar_d2_init,
++		.control_filter = xonar_d2_control_filter,
++		.mixer_init = xonar_mixer_init,
++		.cleanup = xonar_cleanup,
++		.set_dac_params = set_pcm1796_params,
++		.set_adc_params = set_cs53x1_params,
++		.update_dac_volume = update_pcm1796_volume,
++		.update_dac_mute = update_pcm1796_mute,
++		.dac_tlv = pcm1796_db_scale,
++		.model_data_size = sizeof(struct xonar_data),
++		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++			       PLAYBACK_1_TO_SPDIF |
++			       CAPTURE_0_FROM_I2S_2 |
++			       CAPTURE_1_FROM_SPDIF,
++		.dac_channels = 8,
++		.dac_volume_min = 0x0f,
++		.dac_volume_max = 0xff,
++		.misc_flags = OXYGEN_MISC_MIDI,
++		.function_flags = OXYGEN_FUNCTION_SPI |
++				  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
++		.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++		.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++	},
++	[MODEL_D2X] = {
++		.shortname = "Xonar D2X",
++		.longname = "Asus Virtuoso 200",
++		.chip = "AV200",
++		.owner = THIS_MODULE,
++		.init = xonar_d2x_init,
++		.control_filter = xonar_d2_control_filter,
++		.mixer_init = xonar_mixer_init,
++		.cleanup = xonar_cleanup,
++		.set_dac_params = set_pcm1796_params,
++		.set_adc_params = set_cs53x1_params,
++		.update_dac_volume = update_pcm1796_volume,
++		.update_dac_mute = update_pcm1796_mute,
++		.gpio_changed = xonar_gpio_changed,
++		.dac_tlv = pcm1796_db_scale,
++		.model_data_size = sizeof(struct xonar_data),
++		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++			       PLAYBACK_1_TO_SPDIF |
++			       CAPTURE_0_FROM_I2S_2 |
++			       CAPTURE_1_FROM_SPDIF,
++		.dac_channels = 8,
++		.dac_volume_min = 0x0f,
++		.dac_volume_max = 0xff,
++		.misc_flags = OXYGEN_MISC_MIDI,
++		.function_flags = OXYGEN_FUNCTION_SPI |
++				  OXYGEN_FUNCTION_ENABLE_SPI_4_5,
++		.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++		.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++	},
++	[MODEL_DX] = {
++		.shortname = "Xonar DX",
++		.longname = "Asus Virtuoso 100",
++		.chip = "AV200",
++		.owner = THIS_MODULE,
++		.init = xonar_dx_init,
++		.control_filter = xonar_dx_control_filter,
++		.mixer_init = xonar_dx_mixer_init,
++		.cleanup = xonar_dx_cleanup,
++		.set_dac_params = set_cs43xx_params,
++		.set_adc_params = set_cs53x1_params,
++		.update_dac_volume = update_cs43xx_volume,
++		.update_dac_mute = update_cs43xx_mute,
++		.gpio_changed = xonar_gpio_changed,
++		.ac97_switch = xonar_dx_ac97_switch,
++		.dac_tlv = cs4362a_db_scale,
++		.model_data_size = sizeof(struct xonar_data),
++		.pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++			       PLAYBACK_1_TO_SPDIF |
++			       CAPTURE_0_FROM_I2S_2,
++		.dac_channels = 8,
++		.dac_volume_min = 0,
++		.dac_volume_max = 127,
++		.function_flags = OXYGEN_FUNCTION_2WIRE,
++		.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++		.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++	},
+ };
+ 
+ static int __devinit xonar_probe(struct pci_dev *pci,
+@@ -423,7 +624,8 @@ static int __devinit xonar_probe(struct pci_dev *pci,
+ 		++dev;
+ 		return -ENOENT;
+ 	}
+-	err = oxygen_pci_probe(pci, index[dev], id[dev], 1, &model_xonar);
++	err = oxygen_pci_probe(pci, index[dev], id[dev],
++			       &xonar_models[pci_id->driver_data]);
+ 	if (err >= 0)
+ 		++dev;
+ 	return err;
+diff --git a/sound/pci/oxygen/wm8785.h b/sound/pci/oxygen/wm8785.h
+new file mode 100644
+index 0000000..8c23e31
+--- /dev/null
++++ b/sound/pci/oxygen/wm8785.h
+@@ -0,0 +1,45 @@
++#ifndef WM8785_H_INCLUDED
++#define WM8785_H_INCLUDED
++
++#define WM8785_R0	0
++#define WM8785_R1	1
++#define WM8785_R2	2
++#define WM8785_R7	7
++
++/* R0 */
++#define WM8785_MCR_MASK		0x007
++#define WM8785_MCR_SLAVE	0x000
++#define WM8785_MCR_MASTER_128	0x001
++#define WM8785_MCR_MASTER_192	0x002
++#define WM8785_MCR_MASTER_256	0x003
++#define WM8785_MCR_MASTER_384	0x004
++#define WM8785_MCR_MASTER_512	0x005
++#define WM8785_MCR_MASTER_768	0x006
++#define WM8785_OSR_MASK		0x018
++#define WM8785_OSR_SINGLE	0x000
++#define WM8785_OSR_DOUBLE	0x008
++#define WM8785_OSR_QUAD		0x010
++#define WM8785_FORMAT_MASK	0x060
++#define WM8785_FORMAT_RJUST	0x000
++#define WM8785_FORMAT_LJUST	0x020
++#define WM8785_FORMAT_I2S	0x040
++#define WM8785_FORMAT_DSP	0x060
++/* R1 */
++#define WM8785_WL_MASK		0x003
++#define WM8785_WL_16		0x000
++#define WM8785_WL_20		0x001
++#define WM8785_WL_24		0x002
++#define WM8785_WL_32		0x003
++#define WM8785_LRP		0x004
++#define WM8785_BCLKINV		0x008
++#define WM8785_LRSWAP		0x010
++#define WM8785_DEVNO_MASK	0x0e0
++/* R2 */
++#define WM8785_HPFR		0x001
++#define WM8785_HPFL		0x002
++#define WM8785_SDODIS		0x004
++#define WM8785_PWRDNR		0x008
++#define WM8785_PWRDNL		0x010
++#define WM8785_TDM_MASK		0x1c0
++
++#endif
+diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
+index 9d5bb76..7fdcdc8 100644
+--- a/sound/pci/pcxhr/pcxhr.c
++++ b/sound/pci/pcxhr/pcxhr.c
+@@ -458,7 +458,7 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
+ 
+ 	snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
+ 		    is_capture ? 'c' : 'p',
+-		    chip->chip_idx, (void*)subs->runtime->dma_addr,
++		    chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
+ 		    subs->runtime->dma_bytes, subs->number);
+ 
+ 	pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS);
+@@ -626,7 +626,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
+ #ifdef CONFIG_SND_DEBUG_DETECT
+ 	do_gettimeofday(&my_tv2);
+ 	snd_printdd("***TRIGGER TASKLET*** TIME = %ld (err = %x)\n",
+-		    my_tv2.tv_usec - my_tv1.tv_usec, err);
++		    (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
+ #endif
+ }
+ 
+@@ -846,7 +846,6 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
+ 	struct pcxhr_mgr       *mgr = chip->mgr;
+ 	struct snd_pcm_runtime *runtime = subs->runtime;
+ 	struct pcxhr_stream    *stream;
+-	int                 is_capture;
+ 
+ 	mutex_lock(&mgr->setup_mutex);
+ 
+@@ -856,12 +855,10 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
+ 	if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) {
+ 		snd_printdd("pcxhr_open playback chip%d subs%d\n",
+ 			    chip->chip_idx, subs->number);
+-		is_capture = 0;
+ 		stream = &chip->playback_stream[subs->number];
+ 	} else {
+ 		snd_printdd("pcxhr_open capture chip%d subs%d\n",
+ 			    chip->chip_idx, subs->number);
+-		is_capture = 1;
+ 		if (mgr->mono_capture)
+ 			runtime->hw.channels_max = 1;
+ 		else
+diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
+index c4e415d..78aa81f 100644
+--- a/sound/pci/pcxhr/pcxhr_core.c
++++ b/sound/pci/pcxhr/pcxhr_core.c
+@@ -897,7 +897,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
+ #ifdef CONFIG_SND_DEBUG_DETECT
+ 	do_gettimeofday(&my_tv2);
+ 	snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n",
+-		    my_tv2.tv_usec - my_tv1.tv_usec, err);
++		    (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
+ #endif
+ 	return 0;
+ }
+@@ -1005,30 +1005,37 @@ void pcxhr_msg_tasklet(unsigned long arg)
+ 			int nb_stream = (prmh->stat[i] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD;
+ 			int pipe = prmh->stat[i] & MASK_FIRST_FIELD;
+ 			int is_capture = prmh->stat[i] & 0x400000;
+-			u32 err;
++			u32 err2;
+ 
+ 			if (prmh->stat[i] & 0x800000) {	/* if BIT_END */
+ 				snd_printdd("TASKLET : End%sPipe %d\n",
+ 					    is_capture ? "Record" : "Play", pipe);
+ 			}
+ 			i++;
+-			err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+-			if (err)
+-				pcxhr_handle_async_err(mgr, err, PCXHR_ERR_PIPE,
++			err2 = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
++			if (err2)
++				pcxhr_handle_async_err(mgr, err2,
++						       PCXHR_ERR_PIPE,
+ 						       pipe, is_capture);
+ 			i += 2;
+ 			for (j = 0; j < nb_stream; j++) {
+-				err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+-				if (err)
+-					pcxhr_handle_async_err(mgr, err, PCXHR_ERR_STREAM,
+-							       pipe, is_capture);
++				err2 = prmh->stat[i] ?
++					prmh->stat[i] : prmh->stat[i+1];
++				if (err2)
++					pcxhr_handle_async_err(mgr, err2,
++							       PCXHR_ERR_STREAM,
++							       pipe,
++							       is_capture);
+ 				i += 2;
+ 			}
+ 			for (j = 0; j < nb_audio; j++) {
+-				err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+-				if (err)
+-					pcxhr_handle_async_err(mgr, err, PCXHR_ERR_AUDIO,
+-							       pipe, is_capture);
++				err2 = prmh->stat[i] ?
++					prmh->stat[i] : prmh->stat[i+1];
++				if (err2)
++					pcxhr_handle_async_err(mgr, err2,
++							       PCXHR_ERR_AUDIO,
++							       pipe,
++							       is_capture);
+ 				i += 2;
+ 			}
+ 		}
+diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
+index 9408b1e..979f7da 100644
+--- a/sound/pci/riptide/riptide.c
++++ b/sound/pci/riptide/riptide.c
+@@ -1630,14 +1630,14 @@ static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
+ 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
+ 	struct pcmhw *data;
+-	int index = substream->number;
++	int sub_num = substream->number;
+ 
+-	chip->playback_substream[index] = substream;
++	chip->playback_substream[sub_num] = substream;
+ 	runtime->hw = snd_riptide_playback;
+ 	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+-	data->paths = lbus_play_paths[index];
+-	data->id = play_ids[index];
+-	data->source = play_sources[index];
++	data->paths = lbus_play_paths[sub_num];
++	data->id = play_ids[sub_num];
++	data->source = play_sources[sub_num];
+ 	data->intdec[0] = 0xff;
+ 	data->intdec[1] = 0xff;
+ 	data->state = ST_STOP;
+@@ -1670,10 +1670,10 @@ static int snd_riptide_playback_close(struct snd_pcm_substream *substream)
+ {
+ 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ 	struct pcmhw *data = get_pcmhwdev(substream);
+-	int index = substream->number;
++	int sub_num = substream->number;
+ 
+ 	substream->runtime->private_data = NULL;
+-	chip->playback_substream[index] = NULL;
++	chip->playback_substream[sub_num] = NULL;
+ 	kfree(data);
+ 	return 0;
+ }
+diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
+index df184aa..e7ef3a1 100644
+--- a/sound/pci/rme32.c
++++ b/sound/pci/rme32.c
+@@ -1350,7 +1350,8 @@ static int __devinit snd_rme32_create(struct rme32 * rme32)
+ 		return err;
+ 	rme32->port = pci_resource_start(rme32->pci, 0);
+ 
+-	if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
++	rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE);
++	if (!rme32->iobase) {
+ 		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n",
+ 			   rme32->port, rme32->port + RME32_IO_SIZE - 1);
+ 		return -ENOMEM;
+diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
+index fb0a4ee..3fdd488 100644
+--- a/sound/pci/rme96.c
++++ b/sound/pci/rme96.c
+@@ -1559,7 +1559,8 @@ snd_rme96_create(struct rme96 *rme96)
+ 		return err;
+ 	rme96->port = pci_resource_start(rme96->pci, 0);
+ 
+-	if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
++	rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE);
++	if (!rme96->iobase) {
+ 		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
+ 		return -ENOMEM;
+ 	}
+diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
+index 1be84f2..4d6fbb3 100644
+--- a/sound/pci/rme9652/hdsp.c
++++ b/sound/pci/rme9652/hdsp.c
+@@ -318,6 +318,10 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
+ #define HDSP_midi1IRQPending    (1<<31)
+ 
+ #define HDSP_spdifFrequencyMask    (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
++#define HDSP_spdifFrequencyMask_9632 (HDSP_spdifFrequency0|\
++				      HDSP_spdifFrequency1|\
++				      HDSP_spdifFrequency2|\
++				      HDSP_spdifFrequency3)
+ 
+ #define HDSP_spdifFrequency32KHz   (HDSP_spdifFrequency0)
+ #define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
+@@ -328,7 +332,9 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
+ #define HDSP_spdifFrequency96KHz   (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
+ 
+ /* This is for H9632 cards */
+-#define HDSP_spdifFrequency128KHz   HDSP_spdifFrequencyMask
++#define HDSP_spdifFrequency128KHz   (HDSP_spdifFrequency0|\
++				     HDSP_spdifFrequency1|\
++				     HDSP_spdifFrequency2)
+ #define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
+ #define HDSP_spdifFrequency192KHz   (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
+ 
+@@ -885,28 +891,15 @@ static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
+ 	return ret;
+ }
+ 
+-static int hdsp_external_sample_rate (struct hdsp *hdsp)
+-{
+-	unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
+-	unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
+-
+-	switch (rate_bits) {
+-	case HDSP_systemFrequency32:   return 32000;
+-	case HDSP_systemFrequency44_1: return 44100;
+-	case HDSP_systemFrequency48:   return 48000;
+-	case HDSP_systemFrequency64:   return 64000;
+-	case HDSP_systemFrequency88_2: return 88200;
+-	case HDSP_systemFrequency96:   return 96000;
+-	default:
+-		return 0;
+-	}
+-}
+-
+ static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
+ {
+ 	unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
+ 	unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
+ 
++	/* For the 9632, the mask is different */
++	if (hdsp->io_type == H9632)
++		 rate_bits = (status & HDSP_spdifFrequencyMask_9632);
++
+ 	if (status & HDSP_SPDIFErrorFlag)
+ 		return 0;
+ 	
+@@ -933,6 +926,31 @@ static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
+ 	return 0;
+ }
+ 
++static int hdsp_external_sample_rate(struct hdsp *hdsp)
++{
++	unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
++	unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
++
++	/* For the 9632 card, there seems to be no bit for indicating external
++	 * sample rate greater than 96kHz. The card reports the corresponding
++	 * single speed. So the best means seems to get spdif rate when
++	 * autosync reference is spdif */
++	if (hdsp->io_type == H9632 &&
++	    hdsp_autosync_ref(hdsp) == HDSP_AUTOSYNC_FROM_SPDIF)
++		 return hdsp_spdif_sample_rate(hdsp);
++
++	switch (rate_bits) {
++	case HDSP_systemFrequency32:   return 32000;
++	case HDSP_systemFrequency44_1: return 44100;
++	case HDSP_systemFrequency48:   return 48000;
++	case HDSP_systemFrequency64:   return 64000;
++	case HDSP_systemFrequency88_2: return 88200;
++	case HDSP_systemFrequency96:   return 96000;
++	default:
++		return 0;
++	}
++}
++
+ static void hdsp_compute_period_size(struct hdsp *hdsp)
+ {
+ 	hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
+diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
+index 9a19ae6..ab423bc 100644
+--- a/sound/pci/rme9652/hdspm.c
++++ b/sound/pci/rme9652/hdspm.c
+@@ -540,7 +540,8 @@ static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
+ 
+ static inline int HDSPM_bit2freq(int n)
+ {
+-	static int bit2freq_tab[] = { 0, 32000, 44100, 48000, 64000, 88200,
++	static const int bit2freq_tab[] = {
++		0, 32000, 44100, 48000, 64000, 88200,
+ 		96000, 128000, 176400, 192000 };
+ 	if (n < 1 || n > 9)
+ 		return 0;
+@@ -582,7 +583,7 @@ static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
+ 	return hdspm->mixer->ch[chan].pb[pb];
+ }
+ 
+-static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
++static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
+ 				      unsigned int in, unsigned short data)
+ {
+ 	if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
+@@ -595,7 +596,7 @@ static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
+ 	return 0;
+ }
+ 
+-static inline int hdspm_write_pb_gain(struct hdspm * hdspm, unsigned int chan,
++static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
+ 				      unsigned int pb, unsigned short data)
+ {
+ 	if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
+@@ -621,7 +622,7 @@ static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
+ }
+ 
+ /* check if same process is writing and reading */
+-static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
++static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
+ {
+ 	unsigned long flags;
+ 	int ret = 1;
+@@ -636,7 +637,7 @@ static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
+ }
+ 
+ /* check for external sample rate */
+-static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
++static int hdspm_external_sample_rate(struct hdspm *hdspm)
+ {
+ 	if (hdspm->is_aes32) {
+ 		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+@@ -787,7 +788,7 @@ static inline void hdspm_stop_audio(struct hdspm * s)
+ }
+ 
+ /* should I silence all or only opened ones ? doit all for first even is 4MB*/
+-static inline void hdspm_silence_playback(struct hdspm * hdspm)
++static void hdspm_silence_playback(struct hdspm *hdspm)
+ {
+ 	int i;
+ 	int n = hdspm->period_bytes;
+@@ -1028,9 +1029,9 @@ static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
+ {
+ 	/* the hardware already does the relevant bit-mask with 0xff */
+ 	if (id)
+-		return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
++		hdspm_write(hdspm, HDSPM_midiDataOut1, val);
+ 	else
+-		return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
++		hdspm_write(hdspm, HDSPM_midiDataOut0, val);
+ }
+ 
+ static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
+@@ -1057,7 +1058,7 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
+ 		return 0;
+ }
+ 
+-static inline void snd_hdspm_flush_midi_input (struct hdspm *hdspm, int id)
++static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
+ {
+ 	while (snd_hdspm_midi_input_available (hdspm, id))
+ 		snd_hdspm_midi_read_byte (hdspm, id);
+diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
+index dcd7cd0..df2007e 100644
+--- a/sound/pci/sis7019.c
++++ b/sound/pci/sis7019.c
+@@ -920,7 +920,7 @@ static unsigned short sis_ac97_rw(struct sis7019 *sis, int codec, u32 cmd)
+ 	u16 status;
+ 	u16 rdy;
+ 	int count;
+-	const static u16 codec_ready[3] = {
++	static const u16 codec_ready[3] = {
+ 		SIS_AC97_STATUS_CODEC_READY,
+ 		SIS_AC97_STATUS_CODEC2_READY,
+ 		SIS_AC97_STATUS_CODEC3_READY,
+@@ -984,7 +984,7 @@ timeout:
+ static void sis_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ 				unsigned short val)
+ {
+-	const static u32 cmd[3] = {
++	static const u32 cmd[3] = {
+ 		SIS_AC97_CMD_CODEC_WRITE,
+ 		SIS_AC97_CMD_CODEC2_WRITE,
+ 		SIS_AC97_CMD_CODEC3_WRITE,
+@@ -995,7 +995,7 @@ static void sis_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ 
+ static unsigned short sis_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
+ {
+-	const static u32 cmd[3] = {
++	static const u32 cmd[3] = {
+ 		SIS_AC97_CMD_CODEC_READ,
+ 		SIS_AC97_CMD_CODEC2_READ,
+ 		SIS_AC97_CMD_CODEC3_READ,
+@@ -1194,7 +1194,6 @@ static int sis_suspend(struct pci_dev *pci, pm_message_t state)
+ 	/* snd_pcm_suspend_all() stopped all channels, so we're quiescent.
+ 	 */
+ 	if (sis->irq >= 0) {
+-		synchronize_irq(sis->irq);
+ 		free_irq(sis->irq, sis);
+ 		sis->irq = -1;
+ 	}
+diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
+index 71138ff..bbcee2c 100644
+--- a/sound/pci/trident/trident_main.c
++++ b/sound/pci/trident/trident_main.c
+@@ -3676,6 +3676,8 @@ static int snd_trident_free(struct snd_trident *trident)
+ 	else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
+ 		outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
+ 	}
++	if (trident->irq >= 0)
++		free_irq(trident->irq, trident);
+ 	if (trident->tlb.buffer.area) {
+ 		outl(0, TRID_REG(trident, NX_TLBC));
+ 		if (trident->tlb.memhdr)
+@@ -3685,8 +3687,6 @@ static int snd_trident_free(struct snd_trident *trident)
+ 		vfree(trident->tlb.shadow_entries);
+ 		snd_dma_free_pages(&trident->tlb.buffer);
+ 	}
+-	if (trident->irq >= 0)
+-		free_irq(trident->irq, trident);
+ 	pci_release_regions(trident->pci);
+ 	pci_disable_device(trident->pci);
+ 	kfree(trident);
+diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
+index a756be6..b585cc3 100644
+--- a/sound/pci/via82xx.c
++++ b/sound/pci/via82xx.c
+@@ -2236,7 +2236,7 @@ static int snd_via82xx_free(struct via82xx *chip)
+ 	/* disable interrupts */
+ 	for (i = 0; i < chip->num_devs; i++)
+ 		snd_via82xx_channel_reset(chip, &chip->devs[i]);
+-	synchronize_irq(chip->irq);
++
+ 	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+  __end_hw:
+diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
+index f5df1c7..31f64ee 100644
+--- a/sound/pci/via82xx_modem.c
++++ b/sound/pci/via82xx_modem.c
+@@ -1075,7 +1075,7 @@ static int snd_via82xx_free(struct via82xx_modem *chip)
+ 	/* disable interrupts */
+ 	for (i = 0; i < chip->num_devs; i++)
+ 		snd_via82xx_channel_reset(chip, &chip->devs[i]);
+-	synchronize_irq(chip->irq);
++
+       __end_hw:
+ 	if (chip->irq >= 0)
+ 		free_irq(chip->irq, chip);
+diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
+index 42c1eb7..29b3056 100644
+--- a/sound/pci/ymfpci/ymfpci_main.c
++++ b/sound/pci/ymfpci/ymfpci_main.c
+@@ -2249,6 +2249,8 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
+ #ifdef CONFIG_PM
+ 	vfree(chip->saved_regs);
+ #endif
++	if (chip->irq >= 0)
++		free_irq(chip->irq, chip);
+ 	release_and_free_resource(chip->mpu_res);
+ 	release_and_free_resource(chip->fm_res);
+ 	snd_ymfpci_free_gameport(chip);
+@@ -2257,8 +2259,6 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
+ 	if (chip->work_ptr.area)
+ 		snd_dma_free_pages(&chip->work_ptr);
+ 	
+-	if (chip->irq >= 0)
+-		free_irq(chip->irq, chip);
+ 	release_and_free_resource(chip->res_reg_area);
+ 
+ 	pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
+diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
+index 8441e78..566a6d0 100644
+--- a/sound/ppc/awacs.c
++++ b/sound/ppc/awacs.c
+@@ -141,7 +141,7 @@ static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol,
+ 	uinfo->value.integer.max = 15;
+ 	return 0;
+ }
+- 
++
+ static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,
+ 				     struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -267,7 +267,8 @@ static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol,
+ static void awacs_set_cuda(int reg, int val)
+ {
+ 	struct adb_request req;
+-	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, reg, val);
++	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a,
++			reg, val);
+ 	while (! req.complete)
+ 		cuda_poll();
+ }
+@@ -289,11 +290,11 @@ static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble)
+ /*
+  * vol = 0 - 31 (attenuation), 32 = mute bit, stereo
+  */
+-static int awacs_amp_set_vol(struct awacs_amp *amp, int index, int lvol, int rvol,
+-			     int do_check)
++static int awacs_amp_set_vol(struct awacs_amp *amp, int index,
++			     int lvol, int rvol, int do_check)
+ {
+ 	if (do_check && amp->amp_vol[index][0] == lvol &&
+-	    amp->amp_vol[index][1] == rvol)
++			amp->amp_vol[index][1] == rvol)
+ 		return 0;
+ 	awacs_set_cuda(3 + index, lvol);
+ 	awacs_set_cuda(5 + index, rvol);
+@@ -337,7 +338,7 @@ static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol,
+ 	uinfo->value.integer.max = 31;
+ 	return 0;
+ }
+- 
++
+ static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,
+ 					 struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -361,8 +362,10 @@ static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol,
+ 	snd_assert(amp, return -EINVAL);
+ 	snd_assert(index >= 0 && index <= 1, return -EINVAL);
+ 
+-	vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) | (amp->amp_vol[index][0] & 32);
+-	vol[1] = (31 - (ucontrol->value.integer.value[1] & 31)) | (amp->amp_vol[index][1] & 32);
++	vol[0] = (31 - (ucontrol->value.integer.value[0] & 31))
++		| (amp->amp_vol[index][0] & 32);
++	vol[1] = (31 - (ucontrol->value.integer.value[1] & 31))
++		| (amp->amp_vol[index][1] & 32);
+ 	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
+ }
+ 
+@@ -374,8 +377,10 @@ static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol,
+ 	struct awacs_amp *amp = chip->mixer_data;
+ 	snd_assert(amp, return -EINVAL);
+ 	snd_assert(index >= 0 && index <= 1, return -EINVAL);
+-	ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) ? 0 : 1;
+-	ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) ? 0 : 1;
++	ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32)
++					? 0 : 1;
++	ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32)
++					? 0 : 1;
+ 	return 0;
+ }
+ 
+@@ -389,8 +394,10 @@ static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol,
+ 	snd_assert(amp, return -EINVAL);
+ 	snd_assert(index >= 0 && index <= 1, return -EINVAL);
+ 
+-	vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) | (amp->amp_vol[index][0] & 31);
+-	vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32) | (amp->amp_vol[index][1] & 31);
++	vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32)
++		| (amp->amp_vol[index][0] & 31);
++	vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32)
++		| (amp->amp_vol[index][1] & 31);
+ 	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
+ }
+ 
+@@ -403,7 +410,7 @@ static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol,
+ 	uinfo->value.integer.max = 14;
+ 	return 0;
+ }
+- 
++
+ static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,
+ 				       struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -445,7 +452,7 @@ static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol,
+ 	uinfo->value.integer.max = 99;
+ 	return 0;
+ }
+- 
++
+ static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,
+ 					 struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -544,7 +551,7 @@ static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol,
+ 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ 	uinfo->count = 1;
+ 	uinfo->value.integer.min = 0;
+-	uinfo->value.integer.max = 2;
++	uinfo->value.integer.max = 3;
+ 	return 0;
+ }
+ 
+@@ -552,16 +559,14 @@ static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol,
+ 					   struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+-	int val;
++	int val = 0;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&chip->reg_lock, flags);
+ 	if (chip->awacs_reg[6] & MASK_MIC_BOOST)
+-		val = 2;
+-	else if (chip->awacs_reg[0] & MASK_GAINLINE)
+-		val = 1;
+-	else
+-		val = 0;
++		val |= 2;
++	if (chip->awacs_reg[0] & MASK_GAINLINE)
++		val |= 1;
+ 	spin_unlock_irqrestore(&chip->reg_lock, flags);
+ 	ucontrol->value.integer.value[0] = val;
+ 	return 0;
+@@ -578,11 +583,10 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
+ 	spin_lock_irqsave(&chip->reg_lock, flags);
+ 	val0 = chip->awacs_reg[0] & ~MASK_GAINLINE;
+ 	val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST;
+-	if (ucontrol->value.integer.value[0] > 0) {
++	if (ucontrol->value.integer.value[0] & 1)
+ 		val0 |= MASK_GAINLINE;
+-		if (ucontrol->value.integer.value[0] > 1)
+-			val6 |= MASK_MIC_BOOST;
+-	}
++	if (ucontrol->value.integer.value[0] & 2)
++		val6 |= MASK_MIC_BOOST;
+ 	if (val0 != chip->awacs_reg[0]) {
+ 		snd_pmac_awacs_write_reg(chip, 0, val0);
+ 		changed = 1;
+@@ -599,9 +603,32 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
+  * lists of mixer elements
+  */
+ static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = {
+-	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+ 	AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
+-	AWACS_VOLUME("Capture Volume", 0, 4, 0),
++	AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
++/*	AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
++};
++
++static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __initdata = {
++	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
++	AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
++	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
++	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
++	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
++	AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
++	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = {
++	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
++	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
++	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = {
++	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+ 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+ };
+ 
+@@ -621,35 +648,61 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __initdata = {
+ static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
+ AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
+ 
++static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata =
++AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
++
+ static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
+-	AWACS_SWITCH("Mic Boost", 0, SHIFT_GAINLINE, 0),
++	AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+ };
+ 
+ static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = {
+ 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+-	  .name = "Mic Boost",
++	  .name = "Mic Boost Capture Volume",
+ 	  .info = snd_pmac_screamer_mic_boost_info,
+ 	  .get = snd_pmac_screamer_mic_boost_get,
+ 	  .put = snd_pmac_screamer_mic_boost_put,
+ 	},
+ };
+ 
++static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __initdata =
++{
++	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __initdata =
++{
++	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
++	AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __initdata =
++{
++	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
++	AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
++};
++
+ static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {
+ 	AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1),
+ };
++
+ static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
+ AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
+ 
++static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata =
++AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
++
+ 
+ /*
+  * add new mixer elements to the card
+  */
+-static int build_mixers(struct snd_pmac *chip, int nums, struct snd_kcontrol_new *mixers)
++static int build_mixers(struct snd_pmac *chip, int nums,
++			struct snd_kcontrol_new *mixers)
+ {
+ 	int i, err;
+ 
+ 	for (i = 0; i < nums; i++) {
+-		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip))) < 0)
++		err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip));
++		if (err < 0)
+ 			return err;
+ 	}
+ 	return 0;
+@@ -699,8 +752,10 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)
+ #ifdef PMAC_AMP_AVAIL
+ 	if (chip->mixer_data) {
+ 		struct awacs_amp *amp = chip->mixer_data;
+-		awacs_amp_set_vol(amp, 0, amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
+-		awacs_amp_set_vol(amp, 1, amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
++		awacs_amp_set_vol(amp, 0,
++				  amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
++		awacs_amp_set_vol(amp, 1,
++				  amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
+ 		awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
+ 		awacs_amp_set_master(amp, amp->amp_master);
+ 	}
+@@ -708,6 +763,14 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)
+ }
+ #endif /* CONFIG_PM */
+ 
++#define IS_PM7500 (machine_is_compatible("AAPL,7500"))
++#define IS_BEIGE (machine_is_compatible("AAPL,Gossamer"))
++#define IS_IMAC (machine_is_compatible("PowerMac2,1") \
++		|| machine_is_compatible("PowerMac2,2") \
++		|| machine_is_compatible("PowerMac4,1"))
++
++static int imac;
++
+ #ifdef PMAC_SUPPORT_AUTOMUTE
+ /*
+  * auto-mute stuffs
+@@ -750,9 +813,16 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
+ 		} else
+ #endif
+ 		{
+-			int reg = chip->awacs_reg[1] | (MASK_HDMUTE|MASK_SPKMUTE);
++			int reg = chip->awacs_reg[1]
++				| (MASK_HDMUTE | MASK_SPKMUTE);
++			if (imac) {
++				reg &= ~MASK_SPKMUTE;
++				reg &= ~MASK_PAROUT1;
++			}
+ 			if (snd_pmac_awacs_detect_headphone(chip))
+ 				reg &= ~MASK_HDMUTE;
++			else if (imac)
++				reg |= MASK_PAROUT1;
+ 			else
+ 				reg &= ~MASK_SPKMUTE;
+ 			if (do_notify && reg == chip->awacs_reg[1])
+@@ -778,8 +848,11 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
+ int __init
+ snd_pmac_awacs_init(struct snd_pmac *chip)
+ {
++	int pm7500 = IS_PM7500;
++	int beige = IS_BEIGE;
+ 	int err, vol;
+ 
++	imac = IS_IMAC;
+ 	/* looks like MASK_GAINLINE triggers something, so we set here
+ 	 * as start-up
+ 	 */
+@@ -787,7 +860,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ 	chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE;
+ 	/* FIXME: Only machines with external SRS module need MASK_PAROUT */
+ 	if (chip->has_iic || chip->device_id == 0x5 ||
+-	    /*chip->_device_id == 0x8 || */
++	    /* chip->_device_id == 0x8 || */
+ 	    chip->device_id == 0xb)
+ 		chip->awacs_reg[1] |= MASK_PAROUT;
+ 	/* get default volume from nvram */
+@@ -798,8 +871,10 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ 	chip->awacs_reg[2] = vol;
+ 	chip->awacs_reg[4] = vol;
+ 	if (chip->model == PMAC_SCREAMER) {
+-		chip->awacs_reg[5] = vol; /* FIXME: screamer has loopthru vol control */
+-		chip->awacs_reg[6] = MASK_MIC_BOOST; /* FIXME: maybe should be vol << 3 for PCMCIA speaker */
++		/* FIXME: screamer has loopthru vol control */
++		chip->awacs_reg[5] = vol;
++		/* FIXME: maybe should be vol << 3 for PCMCIA speaker */
++		chip->awacs_reg[6] = MASK_MIC_BOOST;
+ 		chip->awacs_reg[7] = 0;
+ 	}
+ 
+@@ -815,7 +890,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ 			return -ENOMEM;
+ 		chip->mixer_data = amp;
+ 		chip->mixer_free = awacs_amp_free;
+-		awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */
++		/* mute and zero vol */
++		awacs_amp_set_vol(amp, 0, 63, 63, 0);
+ 		awacs_amp_set_vol(amp, 1, 63, 63, 0);
+ 		awacs_amp_set_tone(amp, 7, 7); /* 0 dB */
+ 		awacs_amp_set_master(amp, 79); /* 0 dB */
+@@ -826,20 +902,25 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ 		/* set headphone-jack detection bit */
+ 		switch (chip->model) {
+ 		case PMAC_AWACS:
+-			chip->hp_stat_mask = 0x04;
++			chip->hp_stat_mask = pm7500 ? MASK_HDPCONN
++				: MASK_LOCONN;
+ 			break;
+ 		case PMAC_SCREAMER:
+ 			switch (chip->device_id) {
+ 			case 0x08:
+-				/* 1 = side jack, 2 = front jack */
+-				chip->hp_stat_mask = 0x03;
++			case 0x0B:
++				chip->hp_stat_mask = imac
++					? MASK_LOCONN_IMAC |
++					MASK_HDPLCONN_IMAC |
++					MASK_HDPRCONN_IMAC
++					: MASK_HDPCONN;
+ 				break;
+ 			case 0x00:
+ 			case 0x05:
+-				chip->hp_stat_mask = 0x04;
++				chip->hp_stat_mask = MASK_LOCONN;
+ 				break;
+ 			default:
+-				chip->hp_stat_mask = 0x08;
++				chip->hp_stat_mask = MASK_HDPCONN;
+ 				break;
+ 			}
+ 			break;
+@@ -854,19 +935,43 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ 	 */
+ 	strcpy(chip->card->mixername, "PowerMac AWACS");
+ 
+-	if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
+-				snd_pmac_awacs_mixers)) < 0)
++	err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
++				snd_pmac_awacs_mixers);
++	if (err < 0)
+ 		return err;
+-	if (chip->model == PMAC_SCREAMER)
++	if (beige)
++		;
++	else if (chip->model == PMAC_SCREAMER)
+ 		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
+ 				   snd_pmac_screamer_mixers2);
+-	else
++	else if (!pm7500)
+ 		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
+ 				   snd_pmac_awacs_mixers2);
+ 	if (err < 0)
+ 		return err;
+-	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
+-	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
++	if (pm7500)
++		err = build_mixers(chip,
++				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
++				   snd_pmac_awacs_mixers_pmac7500);
++	else if (beige)
++		err = build_mixers(chip,
++				   ARRAY_SIZE(snd_pmac_screamer_mixers_beige),
++				   snd_pmac_screamer_mixers_beige);
++	else if (imac)
++		err = build_mixers(chip,
++				   ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
++				   snd_pmac_screamer_mixers_imac);
++	else
++		err = build_mixers(chip,
++				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),
++				   snd_pmac_awacs_mixers_pmac);
++	if (err < 0)
++		return err;
++	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac)
++			? &snd_pmac_awacs_master_sw_imac
++			: &snd_pmac_awacs_master_sw, chip);
++	err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++	if (err < 0)
+ 		return err;
+ #ifdef PMAC_AMP_AVAIL
+ 	if (chip->mixer_data) {
+@@ -876,37 +981,58 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ 		 * screamer registers.
+ 		 * in this case, it seems the route C is not used.
+ 		 */
+-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
+-					snd_pmac_awacs_amp_vol)) < 0)
++		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
++					snd_pmac_awacs_amp_vol);
++		if (err < 0)
+ 			return err;
+ 		/* overwrite */
+-		chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw, chip);
+-		if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
++		chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw,
++							chip);
++		err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++		if (err < 0)
+ 			return err;
+-		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw, chip);
+-		if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
++		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw,
++							chip);
++		err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
++		if (err < 0)
+ 			return err;
+ 	} else
+ #endif /* PMAC_AMP_AVAIL */
+ 	{
+ 		/* route A = headphone, route C = speaker */
+-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
+-					snd_pmac_awacs_speaker_vol)) < 0)
++		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
++					snd_pmac_awacs_speaker_vol);
++		if (err < 0)
+ 			return err;
+-		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
+-		if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
++		chip->speaker_sw_ctl = snd_ctl_new1(imac
++				? &snd_pmac_awacs_speaker_sw_imac
++				: &snd_pmac_awacs_speaker_sw, chip);
++		err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
++		if (err < 0)
+ 			return err;
+ 	}
+ 
+-	if (chip->model == PMAC_SCREAMER) {
+-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
+-					snd_pmac_screamer_mic_boost)) < 0)
+-			return err;
+-	} else {
+-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
+-					snd_pmac_awacs_mic_boost)) < 0)
+-			return err;
+-	}
++	if (beige)
++		err = build_mixers(chip,
++				ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),
++				snd_pmac_screamer_mic_boost_beige);
++	else if (imac)
++		err = build_mixers(chip,
++				ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac),
++				snd_pmac_screamer_mic_boost_imac);
++	else if (chip->model == PMAC_SCREAMER)
++		err = build_mixers(chip,
++				ARRAY_SIZE(snd_pmac_screamer_mic_boost),
++				snd_pmac_screamer_mic_boost);
++	else if (pm7500)
++		err = build_mixers(chip,
++				ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500),
++				snd_pmac_awacs_mic_boost_pmac7500);
++	else
++		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
++				snd_pmac_awacs_mic_boost);
++	if (err < 0)
++		return err;
+ 
+ 	/*
+ 	 * set lowlevel callbacks
+@@ -917,7 +1043,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ 	chip->resume = snd_pmac_awacs_resume;
+ #endif
+ #ifdef PMAC_SUPPORT_AUTOMUTE
+-	if ((err = snd_pmac_add_automute(chip)) < 0)
++	err = snd_pmac_add_automute(chip);
++	if (err < 0)
+ 		return err;
+ 	chip->detect_headphone = snd_pmac_awacs_detect_headphone;
+ 	chip->update_automute = snd_pmac_awacs_update_automute;
+diff --git a/sound/ppc/awacs.h b/sound/ppc/awacs.h
+index 1b2cc44..c33e6a5 100644
+--- a/sound/ppc/awacs.h
++++ b/sound/ppc/awacs.h
+@@ -116,6 +116,11 @@ struct awacs_regs {
+ #define MASK_HDMUTE	MASK_AMUTE
+ #define SHIFT_HDMUTE	9
+ #define MASK_PAROUT	(0x3 << 10)	/* Parallel Out (???) */
++#define MASK_PAROUT0	(0x1 << 10)	/* Parallel Out (???) */
++#define MASK_PAROUT1	(0x1 << 11)	/* Parallel Out (enable speaker) */
++#define SHIFT_PAROUT	10
++#define SHIFT_PAROUT0	10
++#define SHIFT_PAROUT1	11
+ 
+ #define SAMPLERATE_48000	(0x0 << 3)	/* 48 or 44.1 kHz */
+ #define SAMPLERATE_32000	(0x1 << 3)	/* 32 or 29.4 kHz */
+@@ -139,7 +144,7 @@ struct awacs_regs {
+ #define VOLLEFT(x)	(((~(x)) << 6) & MASK_OUTVOLLEFT)
+ 
+ /* address 6 */
+-#define MASK_MIC_BOOST  (0x4)           /* screamer mic boost */
++#define MASK_MIC_BOOST  (0x4)		/* screamer mic boost */
+ #define SHIFT_MIC_BOOST	2
+ 
+ /* Audio Codec Status Reg Bit Masks */
+@@ -152,8 +157,15 @@ struct awacs_regs {
+ #define MASK_REVISION	(0xf << 12)	/* Revision Number */
+ #define MASK_MFGID	(0xf << 8)	/* Mfg. ID */
+ #define MASK_CODSTATRES	(0xf << 4)	/* bits 4 - 7 reserved */
+-#define MASK_INPPORT	(0xf)		/* Input Port */
+-#define MASK_HDPCONN	8		/* headphone plugged in */
++#define MASK_INSENSE	(0xf)		/* port sense bits: */
++#define MASK_HDPCONN		8	/* headphone plugged in */
++#define MASK_LOCONN		4	/* line-out plugged in */
++#define MASK_LICONN		2	/* line-in plugged in */
++#define MASK_MICCONN		1	/* microphone plugged in */
++#define MASK_LICONN_IMAC	8	/* line-in plugged in */
++#define MASK_HDPRCONN_IMAC	4	/* headphone right plugged in */
++#define MASK_HDPLCONN_IMAC	2	/* headphone left plugged in */
++#define MASK_LOCONN_IMAC	1	/* line-out plugged in */
+ 
+ /* Clipping Count Reg Bit Masks */
+ /* -------- ----- --- --- ----- */
+@@ -163,7 +175,8 @@ struct awacs_regs {
+ /* DBDMA ChannelStatus Bit Masks */
+ /* ----- ------------- --- ----- */
+ #define MASK_CSERR	(0x1 << 7)	/* Error */
+-#define MASK_EOI	(0x1 << 6)	/* End of Input -- only for Input Channel */
++#define MASK_EOI	(0x1 << 6)	/* End of Input --
++					   only for Input Channel */
+ #define MASK_CSUNUSED	(0x1f << 1)	/* bits 1-5 not used */
+ #define MASK_WAIT	(0x1)		/* Wait */
+ 
+diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
+index 1a545ac..f860d39 100644
+--- a/sound/ppc/burgundy.c
++++ b/sound/ppc/burgundy.c
+@@ -102,7 +102,8 @@ snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr)
+ }
+ 
+ static void
+-snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr, unsigned int val)
++snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr,
++		      unsigned int val)
+ {
+ 	out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
+ 	snd_pmac_burgundy_busy_wait(chip);
+@@ -126,8 +127,11 @@ snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr)
+ 	return val;
+ }
+ 
++#define BASE2ADDR(base)	((base) << 12)
++#define ADDR2BASE(addr)	((addr) >> 12)
++
+ /*
+- * Burgundy volume: 0 - 100, stereo
++ * Burgundy volume: 0 - 100, stereo, word reg
+  */
+ static void
+ snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
+@@ -168,13 +172,6 @@ snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address,
+ 		volume[1] = 0;
+ }
+ 
+-
+-/*
+- */
+-
+-#define BASE2ADDR(base)	((base) << 12)
+-#define ADDR2BASE(addr)	((addr) >> 12)
+-
+ static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol,
+ 					 struct snd_ctl_elem_info *uinfo)
+ {
+@@ -191,8 +188,8 @@ static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol,
+ 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ 	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+ 	int shift = (kcontrol->private_value >> 8) & 0xff;
+-	snd_pmac_burgundy_read_volume(chip, addr, ucontrol->value.integer.value,
+-				      shift);
++	snd_pmac_burgundy_read_volume(chip, addr,
++				      ucontrol->value.integer.value, shift);
+ 	return 0;
+ }
+ 
+@@ -204,24 +201,163 @@ static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol,
+ 	int shift = (kcontrol->private_value >> 8) & 0xff;
+ 	long nvoices[2];
+ 
+-	snd_pmac_burgundy_write_volume(chip, addr, ucontrol->value.integer.value,
+-				       shift);
++	snd_pmac_burgundy_write_volume(chip, addr,
++				       ucontrol->value.integer.value, shift);
+ 	snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift);
+ 	return (nvoices[0] != ucontrol->value.integer.value[0] ||
+ 		nvoices[1] != ucontrol->value.integer.value[1]);
+ }
+ 
+-#define BURGUNDY_VOLUME(xname, xindex, addr, shift) \
++#define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+   .info = snd_pmac_burgundy_info_volume,\
+   .get = snd_pmac_burgundy_get_volume,\
+   .put = snd_pmac_burgundy_put_volume,\
+   .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) }
+ 
+-/* lineout/speaker */
++/*
++ * Burgundy volume: 0 - 100, stereo, 2-byte reg
++ */
++static void
++snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address,
++				  long *volume, int off)
++{
++	int lvolume, rvolume;
+ 
+-static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
+-					     struct snd_ctl_elem_info *uinfo)
++	off |= off << 2;
++	lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
++	rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
++
++	snd_pmac_burgundy_wcb(chip, address + off, lvolume);
++	snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume);
++}
++
++static void
++snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address,
++				 long *volume, int off)
++{
++	volume[0] = snd_pmac_burgundy_rcb(chip, address + off);
++	if (volume[0] >= BURGUNDY_VOLUME_OFFSET)
++		volume[0] -= BURGUNDY_VOLUME_OFFSET;
++	else
++		volume[0] = 0;
++	volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100);
++	if (volume[1] >= BURGUNDY_VOLUME_OFFSET)
++		volume[1] -= BURGUNDY_VOLUME_OFFSET;
++	else
++		volume[1] = 0;
++}
++
++static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol,
++					    struct snd_ctl_elem_info *uinfo)
++{
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++	uinfo->count = 2;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = 100;
++	return 0;
++}
++
++static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol,
++					   struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
++	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++	int off = kcontrol->private_value & 0x300;
++	snd_pmac_burgundy_read_volume_2b(chip, addr,
++			ucontrol->value.integer.value, off);
++	return 0;
++}
++
++static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol,
++					   struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
++	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++	int off = kcontrol->private_value & 0x300;
++	long nvoices[2];
++
++	snd_pmac_burgundy_write_volume_2b(chip, addr,
++			ucontrol->value.integer.value, off);
++	snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off);
++	return (nvoices[0] != ucontrol->value.integer.value[0] ||
++		nvoices[1] != ucontrol->value.integer.value[1]);
++}
++
++#define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \
++{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
++  .info = snd_pmac_burgundy_info_volume_2b,\
++  .get = snd_pmac_burgundy_get_volume_2b,\
++  .put = snd_pmac_burgundy_put_volume_2b,\
++  .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) }
++
++/*
++ * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg
++ */
++static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol,
++				       struct snd_ctl_elem_info *uinfo)
++{
++	int stereo = (kcontrol->private_value >> 24) & 1;
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++	uinfo->count = stereo + 1;
++	uinfo->value.integer.min = 0;
++	uinfo->value.integer.max = 15;
++	return 0;
++}
++
++static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol,
++				      struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
++	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++	int stereo = (kcontrol->private_value >> 24) & 1;
++	int atten = (kcontrol->private_value >> 25) & 1;
++	int oval;
++
++	oval = snd_pmac_burgundy_rcb(chip, addr);
++	if (atten)
++		oval = ~oval & 0xff;
++	ucontrol->value.integer.value[0] = oval & 0xf;
++	if (stereo)
++		ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
++	return 0;
++}
++
++static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol,
++				      struct snd_ctl_elem_value *ucontrol)
++{
++	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
++	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++	int stereo = (kcontrol->private_value >> 24) & 1;
++	int atten = (kcontrol->private_value >> 25) & 1;
++	int oval, val;
++
++	oval = snd_pmac_burgundy_rcb(chip, addr);
++	if (atten)
++		oval = ~oval & 0xff;
++	val = ucontrol->value.integer.value[0];
++	if (stereo)
++		val |= ucontrol->value.integer.value[1] << 4;
++	else
++		val |= ucontrol->value.integer.value[0] << 4;
++	if (atten)
++		val = ~val & 0xff;
++	snd_pmac_burgundy_wcb(chip, addr, val);
++	return val != oval;
++}
++
++#define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \
++{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
++  .info = snd_pmac_burgundy_info_gain,\
++  .get = snd_pmac_burgundy_get_gain,\
++  .put = snd_pmac_burgundy_put_gain,\
++  .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) }
++
++/*
++ * Burgundy switch: 0/1, mono/stereo, word reg
++ */
++static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol,
++					   struct snd_ctl_elem_info *uinfo)
+ {
+ 	int stereo = (kcontrol->private_value >> 24) & 1;
+ 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+@@ -231,111 +367,207 @@ static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
+ 	return 0;
+ }
+ 
+-static int snd_pmac_burgundy_get_switch_out(struct snd_kcontrol *kcontrol,
+-					    struct snd_ctl_elem_value *ucontrol)
++static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol,
++					  struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+-	int lmask = kcontrol->private_value & 0xff;
+-	int rmask = (kcontrol->private_value >> 8) & 0xff;
++	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
++	int lmask = 1 << (kcontrol->private_value & 0xff);
++	int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
+ 	int stereo = (kcontrol->private_value >> 24) & 1;
+-	int val = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
++	int val = snd_pmac_burgundy_rcw(chip, addr);
+ 	ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
+ 	if (stereo)
+ 		ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
+ 	return 0;
+ }
+ 
+-static int snd_pmac_burgundy_put_switch_out(struct snd_kcontrol *kcontrol,
+-					    struct snd_ctl_elem_value *ucontrol)
++static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol,
++					  struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+-	int lmask = kcontrol->private_value & 0xff;
+-	int rmask = (kcontrol->private_value >> 8) & 0xff;
++	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
++	int lmask = 1 << (kcontrol->private_value & 0xff);
++	int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
+ 	int stereo = (kcontrol->private_value >> 24) & 1;
+ 	int val, oval;
+-	oval = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+-	val = oval & ~(lmask | rmask);
++	oval = snd_pmac_burgundy_rcw(chip, addr);
++	val = oval & ~(lmask | (stereo ? rmask : 0));
+ 	if (ucontrol->value.integer.value[0])
+ 		val |= lmask;
+ 	if (stereo && ucontrol->value.integer.value[1])
+ 		val |= rmask;
+-	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, val);
++	snd_pmac_burgundy_wcw(chip, addr, val);
+ 	return val != oval;
+ }
+ 
+-#define BURGUNDY_OUTPUT_SWITCH(xname, xindex, lmask, rmask, stereo) \
++#define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+-  .info = snd_pmac_burgundy_info_switch_out,\
+-  .get = snd_pmac_burgundy_get_switch_out,\
+-  .put = snd_pmac_burgundy_put_switch_out,\
+-  .private_value = ((lmask) | ((rmask) << 8) | ((stereo) << 24)) }
+-
+-/* line/speaker output volume */
+-static int snd_pmac_burgundy_info_volume_out(struct snd_kcontrol *kcontrol,
+-					     struct snd_ctl_elem_info *uinfo)
++  .info = snd_pmac_burgundy_info_switch_w,\
++  .get = snd_pmac_burgundy_get_switch_w,\
++  .put = snd_pmac_burgundy_put_switch_w,\
++  .private_value = ((lbit) | ((rbit) << 8)\
++		| (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
++
++/*
++ * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask
++ */
++static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol,
++					   struct snd_ctl_elem_info *uinfo)
+ {
+ 	int stereo = (kcontrol->private_value >> 24) & 1;
+-	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ 	uinfo->count = stereo + 1;
+ 	uinfo->value.integer.min = 0;
+-	uinfo->value.integer.max = 15;
++	uinfo->value.integer.max = 1;
+ 	return 0;
+ }
+ 
+-static int snd_pmac_burgundy_get_volume_out(struct snd_kcontrol *kcontrol,
+-					    struct snd_ctl_elem_value *ucontrol)
++static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol,
++					  struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+-	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
++	int lmask = kcontrol->private_value & 0xff;
++	int rmask = (kcontrol->private_value >> 8) & 0xff;
+ 	int stereo = (kcontrol->private_value >> 24) & 1;
+-	int oval;
+-
+-	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
+-	ucontrol->value.integer.value[0] = oval & 0xf;
++	int val = snd_pmac_burgundy_rcb(chip, addr);
++	ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
+ 	if (stereo)
+-		ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
++		ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
+ 	return 0;
+ }
+ 
+-static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol,
+-					    struct snd_ctl_elem_value *ucontrol)
++static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
++					  struct snd_ctl_elem_value *ucontrol)
+ {
+ 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+-	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
++	int lmask = kcontrol->private_value & 0xff;
++	int rmask = (kcontrol->private_value >> 8) & 0xff;
+ 	int stereo = (kcontrol->private_value >> 24) & 1;
+-	unsigned int oval, val;
+-
+-	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
+-	val = ucontrol->value.integer.value[0] & 15;
+-	if (stereo)
+-		val |= (ucontrol->value.integer.value[1] & 15) << 4;
+-	else
+-		val |= val << 4;
+-	val = ~val & 0xff;
++	int val, oval;
++	oval = snd_pmac_burgundy_rcb(chip, addr);
++	val = oval & ~(lmask | rmask);
++	if (ucontrol->value.integer.value[0])
++		val |= lmask;
++	if (stereo && ucontrol->value.integer.value[1])
++		val |= rmask;
+ 	snd_pmac_burgundy_wcb(chip, addr, val);
+ 	return val != oval;
+ }
+ 
+-#define BURGUNDY_OUTPUT_VOLUME(xname, xindex, addr, stereo) \
++#define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+-  .info = snd_pmac_burgundy_info_volume_out,\
+-  .get = snd_pmac_burgundy_get_volume_out,\
+-  .put = snd_pmac_burgundy_put_volume_out,\
+-  .private_value = (ADDR2BASE(addr) | ((stereo) << 24)) }
++  .info = snd_pmac_burgundy_info_switch_b,\
++  .get = snd_pmac_burgundy_get_switch_b,\
++  .put = snd_pmac_burgundy_put_switch_b,\
++  .private_value = ((lmask) | ((rmask) << 8)\
++		| (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
+ 
++/*
++ * Burgundy mixers
++ */
+ static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __initdata = {
+-	BURGUNDY_VOLUME("Master Playback Volume", 0, MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
+-	BURGUNDY_VOLUME("Line Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLLINE, 16),
+-	BURGUNDY_VOLUME("CD Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLCD, 16),
+-	BURGUNDY_VOLUME("Mic Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLMIC, 16),
+-	BURGUNDY_OUTPUT_VOLUME("PC Speaker Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENHP, 0),
+-	/*BURGUNDY_OUTPUT_VOLUME("PCM Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1),*/
+-	BURGUNDY_OUTPUT_VOLUME("Headphone Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1),
+-};	
+-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw __initdata = 
+-BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0, BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw __initdata = 
+-BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0);
++	BURGUNDY_VOLUME_W("Master Playback Volume", 0,
++			MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
++	BURGUNDY_VOLUME_W("CD Capture Volume", 0,
++			MASK_ADDR_BURGUNDY_VOLCD, 16),
++	BURGUNDY_VOLUME_2B("Input Capture Volume", 0,
++			MASK_ADDR_BURGUNDY_VOLMIX01, 2),
++	BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0,
++			MASK_ADDR_BURGUNDY_VOLMIX23, 0),
++	BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0,
++			MASK_ADDR_BURGUNDY_GAINCD, 1, 0),
++	BURGUNDY_SWITCH_W("Master Capture Switch", 0,
++			MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0),
++	BURGUNDY_SWITCH_W("CD Capture Switch", 0,
++			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1),
++	BURGUNDY_SWITCH_W("CD Playback Switch", 0,
++			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1),
++/*	BURGUNDY_SWITCH_W("Loop Capture Switch", 0,
++ *		MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1),
++ *	BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0,
++ *		MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0),
++ *	BURGUNDY_SWITCH_B("Mixer Capture Switch", 0,
++ *		MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0),
++ *	BURGUNDY_SWITCH_B("PCM out Capture Switch", 0,
++ *		MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0),
++ */	BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
++			MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
++};
++static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __initdata = {
++	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
++			MASK_ADDR_BURGUNDY_VOLLINE, 16),
++	BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
++			MASK_ADDR_BURGUNDY_VOLMIC, 16),
++	BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
++			MASK_ADDR_BURGUNDY_GAINLINE, 1, 0),
++	BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0,
++			MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
++	BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
++			MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
++	BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
++			MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1),
++	BURGUNDY_VOLUME_B("Headphone Playback Volume", 0,
++			MASK_ADDR_BURGUNDY_ATTENHP, 1, 1),
++	BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
++			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1),
++	BURGUNDY_SWITCH_W("Mic Capture Switch", 0,
++			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
++	BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
++			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1),
++	BURGUNDY_SWITCH_W("Mic Playback Switch", 0,
++			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
++	BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
++			MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
++};
++static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __initdata = {
++	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
++			MASK_ADDR_BURGUNDY_VOLMIC, 16),
++	BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
++			MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
++	BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
++			MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1),
++	BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
++			MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
++	BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
++			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
++	BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
++			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
++/*	BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
++ *		MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
++};
++static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __initdata =
++BURGUNDY_SWITCH_B("Master Playback Switch", 0,
++	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++	BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
++	BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __initdata =
++BURGUNDY_SWITCH_B("Master Playback Switch", 0,
++	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++	BURGUNDY_OUTPUT_INTERN
++	| BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __initdata =
++BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
++	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __initdata =
++BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
++	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++	BURGUNDY_OUTPUT_INTERN, 0, 0);
++static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __initdata =
++BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
++	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++	BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __initdata =
++BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
++	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __initdata =
++BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
++	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++	BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);
+ 
+ 
+ #ifdef PMAC_SUPPORT_AUTOMUTE
+@@ -350,16 +582,26 @@ static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip)
+ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify)
+ {
+ 	if (chip->auto_mute) {
++		int imac = machine_is_compatible("iMac");
+ 		int reg, oreg;
+-		reg = oreg = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+-		reg &= ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT | BURGUNDY_OUTPUT_INTERN);
++		reg = oreg = snd_pmac_burgundy_rcb(chip,
++				MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
++		reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
++				| BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
++			: ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
++				| BURGUNDY_OUTPUT_INTERN);
+ 		if (snd_pmac_burgundy_detect_headphone(chip))
+-			reg |= BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT;
++			reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
++				: (BURGUNDY_OUTPUT_LEFT
++					| BURGUNDY_OUTPUT_RIGHT);
+ 		else
+-			reg |= BURGUNDY_OUTPUT_INTERN;
++			reg |= imac ? (BURGUNDY_OUTPUT_LEFT
++					| BURGUNDY_OUTPUT_RIGHT)
++				: (BURGUNDY_OUTPUT_INTERN);
+ 		if (do_notify && reg == oreg)
+ 			return;
+-		snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
++		snd_pmac_burgundy_wcb(chip,
++				MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
+ 		if (do_notify) {
+ 			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ 				       &chip->master_sw_ctl->id);
+@@ -378,6 +620,7 @@ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_noti
+  */
+ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
+ {
++	int imac = machine_is_compatible("iMac");
+ 	int i, err;
+ 
+ 	/* Checks to see the chip is alive and kicking */
+@@ -386,7 +629,7 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
+ 		return 1;
+ 	}
+ 
+-	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
++	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
+ 			   DEF_BURGUNDY_OUTPUTENABLES);
+ 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ 			   DEF_BURGUNDY_MORE_OUTPUTENABLES);
+@@ -396,7 +639,8 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
+ 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21,
+ 			   DEF_BURGUNDY_INPSEL21);
+ 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3,
+-			   DEF_BURGUNDY_INPSEL3);
++			   imac ? DEF_BURGUNDY_INPSEL3_IMAC
++			   : DEF_BURGUNDY_INPSEL3_PMAC);
+ 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD,
+ 			   DEF_BURGUNDY_GAINCD);
+ 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE,
+@@ -422,27 +666,62 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
+ 	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC,
+ 			   DEF_BURGUNDY_VOLMIC);
+ 
+-	if (chip->hp_stat_mask == 0)
++	if (chip->hp_stat_mask == 0) {
+ 		/* set headphone-jack detection bit */
+-		chip->hp_stat_mask = 0x04;
+-
++		if (imac)
++			chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER
++				| BURGUNDY_HPDETECT_IMAC_LOWER
++				| BURGUNDY_HPDETECT_IMAC_SIDE;
++		else
++			chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK;
++	}
+ 	/*
+ 	 * build burgundy mixers
+ 	 */
+ 	strcpy(chip->card->mixername, "PowerMac Burgundy");
+ 
+ 	for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
+-		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
++		err = snd_ctl_add(chip->card,
++		    snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip));
++		if (err < 0)
++			return err;
++	}
++	for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac)
++			: ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) {
++		err = snd_ctl_add(chip->card,
++		    snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i]
++		    : &snd_pmac_burgundy_mixers_pmac[i], chip));
++		if (err < 0)
+ 			return err;
+ 	}
+-	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_master_sw, chip);
+-	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
++	chip->master_sw_ctl = snd_ctl_new1(imac
++			? &snd_pmac_burgundy_master_sw_imac
++			: &snd_pmac_burgundy_master_sw_pmac, chip);
++	err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++	if (err < 0)
++		return err;
++	chip->master_sw_ctl = snd_ctl_new1(imac
++			? &snd_pmac_burgundy_line_sw_imac
++			: &snd_pmac_burgundy_line_sw_pmac, chip);
++	err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++	if (err < 0)
+ 		return err;
+-	chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_speaker_sw, chip);
+-	if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
++	if (imac) {
++		chip->master_sw_ctl = snd_ctl_new1(
++				&snd_pmac_burgundy_hp_sw_imac, chip);
++		err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++		if (err < 0)
++			return err;
++	}
++	chip->speaker_sw_ctl = snd_ctl_new1(imac
++			? &snd_pmac_burgundy_speaker_sw_imac
++			: &snd_pmac_burgundy_speaker_sw_pmac, chip);
++	err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
++	if (err < 0)
+ 		return err;
+ #ifdef PMAC_SUPPORT_AUTOMUTE
+-	if ((err = snd_pmac_add_automute(chip)) < 0)
++	err = snd_pmac_add_automute(chip);
++	if (err < 0)
+ 		return err;
+ 
+ 	chip->detect_headphone = snd_pmac_burgundy_detect_headphone;
+diff --git a/sound/ppc/burgundy.h b/sound/ppc/burgundy.h
+index ebb457a..7a7f9cf 100644
+--- a/sound/ppc/burgundy.h
++++ b/sound/ppc/burgundy.h
+@@ -22,6 +22,7 @@
+ #ifndef __BURGUNDY_H
+ #define __BURGUNDY_H
+ 
++#define MASK_ADDR_BURGUNDY_INPBOOST (0x10 << 12)
+ #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12)
+ #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12)
+ 
+@@ -35,7 +36,10 @@
+ #define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12)
+ #define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12)
+ 
++#define MASK_ADDR_BURGUNDY_CAPTURESELECTS (0x2A << 12)
+ #define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12)
++#define MASK_ADDR_BURGUNDY_VOLMIX01 (0x2D << 12)
++#define MASK_ADDR_BURGUNDY_VOLMIX23 (0x2E << 12)
+ #define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12)
+ 
+ #define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12)
+@@ -45,6 +49,10 @@
+ #define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12)
+ #define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12)
+ #define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12)
++#define MASK_ADDR_BURGUNDY_ATTENMONO (0x65 << 12)
++
++#define MASK_ADDR_BURGUNDY_HOSTIFAD (0x78 << 12)
++#define MASK_ADDR_BURGUNDY_HOSTIFEH (0x79 << 12)
+ 
+ #define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1)
+ #define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2)
+@@ -59,21 +67,22 @@
+ 
+ /* These are all default values for the burgundy */
+ #define DEF_BURGUNDY_INPSEL21 (0xAA)
+-#define DEF_BURGUNDY_INPSEL3 (0x0A)
++#define DEF_BURGUNDY_INPSEL3_IMAC (0x0A)
++#define DEF_BURGUNDY_INPSEL3_PMAC (0x05)
+ 
+ #define DEF_BURGUNDY_GAINCD (0x33)
+ #define DEF_BURGUNDY_GAINLINE (0x44)
+ #define DEF_BURGUNDY_GAINMIC (0x44)
+ #define DEF_BURGUNDY_GAINMODEM (0x06)
+ 
+-/* Remember: lowest volume here is 0x9b */
++/* Remember: lowest volume here is 0x9B (155) */
+ #define DEF_BURGUNDY_VOLCD (0xCCCCCCCC)
+ #define DEF_BURGUNDY_VOLLINE (0x00000000)
+ #define DEF_BURGUNDY_VOLMIC (0x00000000)
+ #define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC)
+ 
+-#define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f)
+-#define DEF_BURGUNDY_OUTPUTENABLES (0x0A)
++#define DEF_BURGUNDY_OUTPUTSELECTS (0x010F010F)
++#define DEF_BURGUNDY_OUTPUTENABLES (0x0100000A)
+ 
+ /* #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) */ /* too loud */
+ #define DEF_BURGUNDY_MASTER_VOLUME (0xDDDDDDDD)
+@@ -84,12 +93,22 @@
+ #define DEF_BURGUNDY_ATTENLINEOUT (0xCC)
+ #define DEF_BURGUNDY_ATTENHP (0xCC)
+ 
+-/* OUTPUTENABLES bits */
++/* MORE_OUTPUTENABLES bits */
+ #define BURGUNDY_OUTPUT_LEFT	0x02
+ #define BURGUNDY_OUTPUT_RIGHT	0x04
++#define BURGUNDY_LINEOUT_LEFT	0x08
++#define BURGUNDY_LINEOUT_RIGHT	0x10
++#define BURGUNDY_HP_LEFT	0x20
++#define BURGUNDY_HP_RIGHT	0x40
+ #define BURGUNDY_OUTPUT_INTERN	0x80
+ 
+-/* volume offset */
++/* Headphone detection bits */
++#define BURGUNDY_HPDETECT_PMAC_BACK	0x04
++#define BURGUNDY_HPDETECT_IMAC_SIDE	0x04
++#define BURGUNDY_HPDETECT_IMAC_UPPER	0x08
++#define BURGUNDY_HPDETECT_IMAC_LOWER	0x01
++
++/* Volume offset */
+ #define BURGUNDY_VOLUME_OFFSET	155
+ 
+ #endif /* __BURGUNDY_H */
+diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
+index 613a565..a38c0c7 100644
+--- a/sound/ppc/pmac.c
++++ b/sound/ppc/pmac.c
+@@ -214,7 +214,7 @@ static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec,
+ 	int rate_index;
+ 	long offset;
+ 	struct pmac_stream *astr;
+-	
++
+ 	rec->dma_size = snd_pcm_lib_buffer_bytes(subs);
+ 	rec->period_size = snd_pcm_lib_period_bytes(subs);
+ 	rec->nperiods = rec->dma_size / rec->period_size;
+@@ -643,7 +643,7 @@ static int snd_pmac_pcm_close(struct snd_pmac *chip, struct pmac_stream *rec,
+ 	/* reset constraints */
+ 	astr->cur_freqs = chip->freqs_ok;
+ 	astr->cur_formats = chip->formats_ok;
+-	
++
+ 	return 0;
+ }
+ 
+@@ -1300,9 +1300,9 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
+ 
+ 	snd_pmac_sound_feature(chip, 1);
+ 
+-	/* reset */
+-	if (chip->model == PMAC_AWACS)
+-		out_le32(&chip->awacs->control, 0x11);
++	/* reset & enable interrupts */
++	if (chip->model <= PMAC_BURGUNDY)
++		out_le32(&chip->awacs->control, chip->control_mask);
+ 
+ 	/* Powerbooks have odd ways of enabling inputs such as
+ 	   an expansion-bay CD or sound from an internal modem
+diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
+index d8d0b4b..20d0e32 100644
+--- a/sound/ppc/snd_ps3.c
++++ b/sound/ppc/snd_ps3.c
+@@ -137,7 +137,7 @@ static inline void update_mask_reg(unsigned int reg, u32 mask, u32 or_val)
+ /*
+  * ALSA defs
+  */
+-const static struct snd_pcm_hardware snd_ps3_pcm_hw = {
++static const struct snd_pcm_hardware snd_ps3_pcm_hw = {
+ 	.info = (SNDRV_PCM_INFO_MMAP |
+ 		 SNDRV_PCM_INFO_NONINTERLEAVED |
+ 		 SNDRV_PCM_INFO_MMAP_VALID),
+diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
+index 2765852..a3b51df 100644
+--- a/sound/soc/Kconfig
++++ b/sound/soc/Kconfig
+@@ -29,6 +29,7 @@ source "sound/soc/pxa/Kconfig"
+ source "sound/soc/s3c24xx/Kconfig"
+ source "sound/soc/sh/Kconfig"
+ source "sound/soc/fsl/Kconfig"
++source "sound/soc/davinci/Kconfig"
+ 
+ # Supported codecs
+ source "sound/soc/codecs/Kconfig"
+diff --git a/sound/soc/Makefile b/sound/soc/Makefile
+index 4869c9a..e489dbd 100644
+--- a/sound/soc/Makefile
++++ b/sound/soc/Makefile
+@@ -1,4 +1,4 @@
+ snd-soc-core-objs := soc-core.o soc-dapm.o
+ 
+ obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
+-obj-$(CONFIG_SND_SOC)	+= codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/
++obj-$(CONFIG_SND_SOC)	+= codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
+diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
+index ad3ad9d..1347dcf 100644
+--- a/sound/soc/at91/eti_b1_wm8731.c
++++ b/sound/soc/at91/eti_b1_wm8731.c
+@@ -33,8 +33,7 @@
+ #include <sound/soc.h>
+ #include <sound/soc-dapm.h>
+ 
+-#include <asm/arch/hardware.h>
+-#include <asm/arch/at91_pio.h>
++#include <asm/hardware.h>
+ #include <asm/arch/gpio.h>
+ 
+ #include "../codecs/wm8731.h"
+@@ -47,13 +46,6 @@
+ #define	DBG(x...)
+ #endif
+ 
+-#define AT91_PIO_TF1	(1 << (AT91_PIN_PB6 - PIN_BASE) % 32)
+-#define AT91_PIO_TK1	(1 << (AT91_PIN_PB7 - PIN_BASE) % 32)
+-#define AT91_PIO_TD1	(1 << (AT91_PIN_PB8 - PIN_BASE) % 32)
+-#define AT91_PIO_RD1	(1 << (AT91_PIN_PB9 - PIN_BASE) % 32)
+-#define AT91_PIO_RK1	(1 << (AT91_PIN_PB10 - PIN_BASE) % 32)
+-#define AT91_PIO_RF1	(1 << (AT91_PIN_PB11 - PIN_BASE) % 32)
+-
+ static struct clk *pck1_clk;
+ static struct clk *pllb_clk;
+ 
+@@ -276,7 +268,6 @@ static struct platform_device *eti_b1_snd_device;
+ static int __init eti_b1_init(void)
+ {
+ 	int ret;
+-	u32 ssc_pio_lines;
+ 	struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
+ 
+ 	if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
+@@ -310,19 +301,12 @@ static int __init eti_b1_init(void)
+ 		goto fail_io_unmap;
+ 	}
+ 
+- 	ssc_pio_lines = AT91_PIO_TF1 | AT91_PIO_TK1 | AT91_PIO_TD1
+-			| AT91_PIO_RD1 /* | AT91_PIO_RK1 */ | AT91_PIO_RF1;
+-
+-	/* Reset all PIO registers and assign lines to peripheral A */
+- 	at91_sys_write(AT91_PIOB + PIO_PDR,  ssc_pio_lines);
+- 	at91_sys_write(AT91_PIOB + PIO_ODR,  ssc_pio_lines);
+- 	at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines);
+- 	at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines);
+- 	at91_sys_write(AT91_PIOB + PIO_IDR,  ssc_pio_lines);
+- 	at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines);
+- 	at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines);
+- 	at91_sys_write(AT91_PIOB + PIO_ASR,  ssc_pio_lines);
+- 	at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines);
++	at91_set_A_periph(AT91_PIN_PB6, 0);	/* TF1 */
++	at91_set_A_periph(AT91_PIN_PB7, 0);	/* TK1 */
++	at91_set_A_periph(AT91_PIN_PB8, 0);	/* TD1 */
++	at91_set_A_periph(AT91_PIN_PB9, 0);	/* RD1 */
++/*	at91_set_A_periph(AT91_PIN_PB10, 0);*/	/* RK1 */
++	at91_set_A_periph(AT91_PIN_PB11, 0);	/* RF1 */
+ 
+ 	/*
+ 	 * Set PCK1 parent to PLLB and its rate to 12 Mhz.
+diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
+index 898a7d3..3903ab7 100644
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -18,6 +18,10 @@ config SND_SOC_WM9712
+ 	tristate
+ 	depends on SND_SOC
+ 
++config SND_SOC_WM9713
++	tristate
++	depends on SND_SOC
++
+ # Cirrus Logic CS4270 Codec
+ config SND_SOC_CS4270
+ 	tristate
+diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
+index c6e5338..4e1314c 100644
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -3,6 +3,7 @@ snd-soc-wm8731-objs := wm8731.o
+ snd-soc-wm8750-objs := wm8750.o
+ snd-soc-wm8753-objs := wm8753.o
+ snd-soc-wm9712-objs := wm9712.o
++snd-soc-wm9713-objs := wm9713.o
+ snd-soc-cs4270-objs := cs4270.o
+ snd-soc-tlv320aic3x-objs := tlv320aic3x.o
+ 
+@@ -11,5 +12,6 @@ obj-$(CONFIG_SND_SOC_WM8731)	+= snd-soc-wm8731.o
+ obj-$(CONFIG_SND_SOC_WM8750)	+= snd-soc-wm8750.o
+ obj-$(CONFIG_SND_SOC_WM8753)	+= snd-soc-wm8753.o
+ obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
++obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
+ obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
+ obj-$(CONFIG_SND_SOC_TLV320AIC3X)	+= snd-soc-tlv320aic3x.o
+diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
+index 242130c..2a1ffe3 100644
+--- a/sound/soc/codecs/ac97.c
++++ b/sound/soc/codecs/ac97.c
+@@ -40,7 +40,8 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
+ }
+ 
+ #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+-		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
++		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
++		SNDRV_PCM_RATE_48000)
+ 
+ struct snd_soc_codec_dai ac97_dai = {
+ 	.name = "AC97 HiFi",
+@@ -86,7 +87,7 @@ static int ac97_soc_probe(struct platform_device *pdev)
+ 	printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
+ 
+ 	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+-	if (socdev->codec == NULL)
++	if (!socdev->codec)
+ 		return -ENOMEM;
+ 	codec = socdev->codec;
+ 	mutex_init(&codec->mutex);
+@@ -102,17 +103,17 @@ static int ac97_soc_probe(struct platform_device *pdev)
+ 
+ 	/* register pcms */
+ 	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+-	if(ret < 0)
++	if (ret < 0)
+ 		goto err;
+ 
+ 	/* add codec as bus device for standard ac97 */
+ 	ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
+-	if(ret < 0)
++	if (ret < 0)
+ 		goto bus_err;
+ 
+ 	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
+ 	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
+-	if(ret < 0)
++	if (ret < 0)
+ 		goto bus_err;
+ 
+ 	ret = snd_soc_register_card(socdev);
+@@ -135,7 +136,7 @@ static int ac97_soc_remove(struct platform_device *pdev)
+ 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ 	struct snd_soc_codec *codec = socdev->codec;
+ 
+-	if(codec == NULL)
++	if (!codec)
+ 		return 0;
+ 
+ 	snd_soc_free_pcms(socdev);
+@@ -145,11 +146,10 @@ static int ac97_soc_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
+-struct snd_soc_codec_device soc_codec_dev_ac97= {
++struct snd_soc_codec_device soc_codec_dev_ac97 = {
+ 	.probe = 	ac97_soc_probe,
+ 	.remove = 	ac97_soc_remove,
+ };
+-
+ EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
+ 
+ MODULE_DESCRIPTION("Soc Generic AC97 driver");
+diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
+index bf2ab72..e73fcfd 100644
+--- a/sound/soc/codecs/cs4270.c
++++ b/sound/soc/codecs/cs4270.c
+@@ -372,7 +372,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
+ 	struct snd_soc_device *socdev = rtd->socdev;
+ 	struct snd_soc_codec *codec = socdev->codec;
+ 	struct cs4270_private *cs4270 = codec->private_data;
+-	unsigned int ret = 0;
++	int ret;
+ 	unsigned int i;
+ 	unsigned int rate;
+ 	unsigned int ratio;
+diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
+index 889a897..630684f 100644
+--- a/sound/soc/codecs/tlv320aic3x.c
++++ b/sound/soc/codecs/tlv320aic3x.c
+@@ -660,33 +660,53 @@ struct aic3x_rate_divs {
+ /* AIC3X codec mclk clock divider coefficients */
+ static const struct aic3x_rate_divs aic3x_divs[] = {
+ 	/* 8k */
++	{12000000, 8000, 48000, 0xa, 16, 3840},
++	{19200000, 8000, 48000, 0xa, 10, 2400},
+ 	{22579200, 8000, 48000, 0xa, 8, 7075},
+ 	{33868800, 8000, 48000, 0xa, 5, 8049},
+ 	/* 11.025k */
++	{12000000, 11025, 44100, 0x6, 15, 528},
++	{19200000, 11025, 44100, 0x6, 9, 4080},
+ 	{22579200, 11025, 44100, 0x6, 8, 0},
+ 	{33868800, 11025, 44100, 0x6, 5, 3333},
+ 	/* 16k */
++	{12000000, 16000, 48000, 0x4, 16, 3840},
++	{19200000, 16000, 48000, 0x4, 10, 2400},
+ 	{22579200, 16000, 48000, 0x4, 8, 7075},
+ 	{33868800, 16000, 48000, 0x4, 5, 8049},
+ 	/* 22.05k */
++	{12000000, 22050, 44100, 0x2, 15, 528},
++	{19200000, 22050, 44100, 0x2, 9, 4080},
+ 	{22579200, 22050, 44100, 0x2, 8, 0},
+ 	{33868800, 22050, 44100, 0x2, 5, 3333},
+ 	/* 32k */
++	{12000000, 32000, 48000, 0x1, 16, 3840},
++	{19200000, 32000, 48000, 0x1, 10, 2400},
+ 	{22579200, 32000, 48000, 0x1, 8, 7075},
+ 	{33868800, 32000, 48000, 0x1, 5, 8049},
+ 	/* 44.1k */
++	{12000000, 44100, 44100, 0x0, 15, 528},
++	{19200000, 44100, 44100, 0x0, 9, 4080},
+ 	{22579200, 44100, 44100, 0x0, 8, 0},
+ 	{33868800, 44100, 44100, 0x0, 5, 3333},
+ 	/* 48k */
++	{12000000, 48000, 48000, 0x0, 16, 3840},
++	{19200000, 48000, 48000, 0x0, 10, 2400},
+ 	{22579200, 48000, 48000, 0x0, 8, 7075},
+ 	{33868800, 48000, 48000, 0x0, 5, 8049},
+ 	/* 64k */
++	{12000000, 64000, 96000, 0x1, 16, 3840},
++	{19200000, 64000, 96000, 0x1, 10, 2400},
+ 	{22579200, 64000, 96000, 0x1, 8, 7075},
+ 	{33868800, 64000, 96000, 0x1, 5, 8049},
+ 	/* 88.2k */
++	{12000000, 88200, 88200, 0x0, 15, 528},
++	{19200000, 88200, 88200, 0x0, 9, 4080},
+ 	{22579200, 88200, 88200, 0x0, 8, 0},
+ 	{33868800, 88200, 88200, 0x0, 5, 3333},
+ 	/* 96k */
++	{12000000, 96000, 96000, 0x0, 16, 3840},
++	{19200000, 96000, 96000, 0x0, 10, 2400},
+ 	{22579200, 96000, 96000, 0x0, 8, 7075},
+ 	{33868800, 96000, 96000, 0x0, 5, 8049},
+ };
+@@ -807,6 +827,8 @@ static int aic3x_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+ 	struct aic3x_priv *aic3x = codec->private_data;
+ 
+ 	switch (freq) {
++	case 12000000:
++	case 19200000:
+ 	case 22579200:
+ 	case 33868800:
+ 		aic3x->sysclk = freq;
+diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
+index 9c33fe8..0cf9265 100644
+--- a/sound/soc/codecs/wm8731.c
++++ b/sound/soc/codecs/wm8731.c
+@@ -110,7 +110,7 @@ static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
+ 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+ 	data[1] = value & 0x00ff;
+ 
+-	wm8731_write_reg_cache (codec, reg, value);
++	wm8731_write_reg_cache(codec, reg, value);
+ 	if (codec->hw_write(codec->control_data, data, 2) == 2)
+ 		return 0;
+ 	else
+@@ -154,8 +154,10 @@ static int wm8731_add_controls(struct snd_soc_codec *codec)
+ 	int err, i;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
+-		if ((err = snd_ctl_add(codec->card,
+-				snd_soc_cnew(&wm8731_snd_controls[i],codec, NULL))) < 0)
++		err = snd_ctl_add(codec->card,
++				  snd_soc_cnew(&wm8731_snd_controls[i],
++						codec, NULL));
++		if (err < 0)
+ 			return err;
+ 	}
+ 
+@@ -221,15 +223,13 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec)
+ {
+ 	int i;
+ 
+-	for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
++	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
+ 		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+-	}
+ 
+ 	/* set up audio path interconnects */
+-	for(i = 0; intercon[i][0] != NULL; i++) {
++	for (i = 0; intercon[i][0] != NULL; i++)
+ 		snd_soc_dapm_connect_input(codec, intercon[i][0],
+ 			intercon[i][1], intercon[i][2]);
+-	}
+ 
+ 	snd_soc_dapm_new_widgets(codec);
+ 	return 0;
+@@ -589,7 +589,7 @@ pcm_err:
+ 
+ static struct snd_soc_device *wm8731_socdev;
+ 
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ 
+ /*
+  * WM8731 2 wire address is determined by GPIO5
+@@ -651,7 +651,7 @@ err:
+ 
+ static int wm8731_i2c_detach(struct i2c_client *client)
+ {
+-	struct snd_soc_codec* codec = i2c_get_clientdata(client);
++	struct snd_soc_codec *codec = i2c_get_clientdata(client);
+ 	i2c_detach_client(client);
+ 	kfree(codec->reg_cache);
+ 	kfree(client);
+@@ -709,7 +709,7 @@ static int wm8731_probe(struct platform_device *pdev)
+ 	INIT_LIST_HEAD(&codec->dapm_paths);
+ 
+ 	wm8731_socdev = socdev;
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ 	if (setup->i2c_address) {
+ 		normal_i2c[0] = setup->i2c_address;
+ 		codec->hw_write = (hw_write_t)i2c_master_send;
+@@ -734,7 +734,7 @@ static int wm8731_remove(struct platform_device *pdev)
+ 
+ 	snd_soc_free_pcms(socdev);
+ 	snd_soc_dapm_free(socdev);
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ 	i2c_del_driver(&wm8731_i2c_driver);
+ #endif
+ 	kfree(codec->private_data);
+@@ -749,7 +749,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
+ 	.suspend = 	wm8731_suspend,
+ 	.resume =	wm8731_resume,
+ };
+-
+ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
+ 
+ MODULE_DESCRIPTION("ASoC WM8731 driver");
+diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
+index 77a857b..16cd5d4 100644
+--- a/sound/soc/codecs/wm8750.c
++++ b/sound/soc/codecs/wm8750.c
+@@ -110,7 +110,7 @@ static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
+ 	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+ 	data[1] = value & 0x00ff;
+ 
+-	wm8750_write_reg_cache (codec, reg, value);
++	wm8750_write_reg_cache(codec, reg, value);
+ 	if (codec->hw_write(codec->control_data, data, 2) == 2)
+ 		return 0;
+ 	else
+@@ -257,7 +257,8 @@ static int wm8750_add_controls(struct snd_soc_codec *codec)
+ 
+ 	for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) {
+ 		err = snd_ctl_add(codec->card,
+-				snd_soc_cnew(&wm8750_snd_controls[i],codec, NULL));
++				snd_soc_cnew(&wm8750_snd_controls[i],
++						codec, NULL));
+ 		if (err < 0)
+ 			return err;
+ 	}
+@@ -478,15 +479,13 @@ static int wm8750_add_widgets(struct snd_soc_codec *codec)
+ {
+ 	int i;
+ 
+-	for(i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
++	for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
+ 		snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
+-	}
+ 
+ 	/* set up audio path audio_mapnects */
+-	for(i = 0; audio_map[i][0] != NULL; i++) {
++	for (i = 0; audio_map[i][0] != NULL; i++)
+ 		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ 			audio_map[i][1], audio_map[i][2]);
+-	}
+ 
+ 	snd_soc_dapm_new_widgets(codec);
+ 	return 0;
+@@ -714,8 +713,8 @@ static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
+ }
+ 
+ #define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+-		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
+-		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++	SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
++	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+ 
+ #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ 	SNDRV_PCM_FMTBIT_S24_LE)
+@@ -784,7 +783,8 @@ static int wm8750_resume(struct platform_device *pdev)
+ 	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
+ 		wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
+ 		codec->dapm_state = SNDRV_CTL_POWER_D0;
+-		schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
++		schedule_delayed_work(&codec->delayed_work,
++					msecs_to_jiffies(1000));
+ 	}
+ 
+ 	return 0;
+@@ -864,7 +864,7 @@ pcm_err:
+    around */
+ static struct snd_soc_device *wm8750_socdev;
+ 
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ 
+ /*
+  * WM8731 2 wire address is determined by GPIO5
+@@ -979,8 +979,8 @@ static int wm8750_probe(struct platform_device *pdev)
+ 	INIT_LIST_HEAD(&codec->dapm_paths);
+ 	wm8750_socdev = socdev;
+ 	INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
+-	
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ 	if (setup->i2c_address) {
+ 		normal_i2c[0] = setup->i2c_address;
+ 		codec->hw_write = (hw_write_t)i2c_master_send;
+@@ -1025,7 +1025,7 @@ static int wm8750_remove(struct platform_device *pdev)
+ 	run_delayed_work(&codec->delayed_work);
+ 	snd_soc_free_pcms(socdev);
+ 	snd_soc_dapm_free(socdev);
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ 	i2c_del_driver(&wm8750_i2c_driver);
+ #endif
+ 	kfree(codec->private_data);
+@@ -1040,7 +1040,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8750 = {
+ 	.suspend = 	wm8750_suspend,
+ 	.resume =	wm8750_resume,
+ };
+-
+ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
+ 
+ MODULE_DESCRIPTION("ASoC WM8750 driver");
+diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
+index ddd9c71..76a5c7b 100644
+--- a/sound/soc/codecs/wm8753.c
++++ b/sound/soc/codecs/wm8753.c
+@@ -198,6 +198,7 @@ static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"};
+ static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"};
+ static const char *wm8753_dat_sel[] = {"Stereo", "Left ADC", "Right ADC",
+ 	"Channel Swap"};
++static const char *wm8753_rout2_phase[] = {"Non Inverted", "Inverted"};
+ 
+ static const struct soc_enum wm8753_enum[] = {
+ SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),
+@@ -228,6 +229,7 @@ SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),
+ SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),
+ SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode),
+ SOC_ENUM_SINGLE(WM8753_ADC, 7, 4, wm8753_dat_sel),
++SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase),
+ };
+ 
+ 
+@@ -279,7 +281,7 @@ SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0
+ 
+ SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1),
+ SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1),
+-SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 4, 7, 1),
++SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1),
+ SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
+ 
+ SOC_ENUM("Bass Boost", wm8753_enum[0]),
+@@ -330,6 +332,7 @@ SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0),
+ SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
+ 
+ SOC_ENUM("ADC Data Select", wm8753_enum[27]),
++SOC_ENUM("ROUT2 Phase", wm8753_enum[28]),
+ };
+ 
+ /* add non dapm controls */
+diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
+index 524f745..d2d79e1 100644
+--- a/sound/soc/codecs/wm9712.c
++++ b/sound/soc/codecs/wm9712.c
+@@ -581,22 +581,14 @@ static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
+ 
+ 	switch (event) {
+ 	case SNDRV_CTL_POWER_D0: /* full On */
+-		/* liam - maybe enable thermal shutdown */
+-		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xdfff;
+-		ac97_write(codec, AC97_EXTENDED_MID, reg);
+-		break;
+ 	case SNDRV_CTL_POWER_D1: /* partial On */
+ 	case SNDRV_CTL_POWER_D2: /* partial On */
+ 		break;
+ 	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+-		/* enable master bias and vmid */
+-		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xbbff;
+-		ac97_write(codec, AC97_EXTENDED_MID, reg);
+ 		ac97_write(codec, AC97_POWERDOWN, 0x0000);
+ 		break;
+ 	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+ 		/* disable everything including AC link */
+-		ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
+ 		ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
+ 		ac97_write(codec, AC97_POWERDOWN, 0xffff);
+ 		break;
+diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
+new file mode 100644
+index 0000000..1f24116
+--- /dev/null
++++ b/sound/soc/codecs/wm9713.c
+@@ -0,0 +1,1300 @@
++/*
++ * wm9713.c  --  ALSA Soc WM9713 codec support
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ *         liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ *  Revision history
++ *    4th Feb 2006   Initial version.
++ *
++ *  Features:-
++ *
++ *   o Support for AC97 Codec, Voice DAC and Aux DAC
++ *   o Support for DAPM
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/ac97_codec.h>
++#include <sound/initval.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include "wm9713.h"
++
++#define WM9713_VERSION "0.15"
++
++struct wm9713_priv {
++	u32 pll_in; /* PLL input frequency */
++	u32 pll_out; /* PLL output frequency */
++};
++
++static unsigned int ac97_read(struct snd_soc_codec *codec,
++	unsigned int reg);
++static int ac97_write(struct snd_soc_codec *codec,
++	unsigned int reg, unsigned int val);
++
++/*
++ * WM9713 register cache
++ * Reg 0x3c bit 15 is used by touch driver.
++ */
++static const u16 wm9713_reg[] = {
++	0x6174, 0x8080, 0x8080, 0x8080,
++	0xc880, 0xe808, 0xe808, 0x0808,
++	0x00da, 0x8000, 0xd600, 0xaaa0,
++	0xaaa0, 0xaaa0, 0x0000, 0x0000,
++	0x0f0f, 0x0040, 0x0000, 0x7f00,
++	0x0405, 0x0410, 0xbb80, 0xbb80,
++	0x0000, 0xbb80, 0x0000, 0x4523,
++	0x0000, 0x2000, 0x7eff, 0xffff,
++	0x0000, 0x0000, 0x0080, 0x0000,
++	0x0000, 0x0000, 0xfffe, 0xffff,
++	0x0000, 0x0000, 0x0000, 0xfffe,
++	0x4000, 0x0000, 0x0000, 0x0000,
++	0xb032, 0x3e00, 0x0000, 0x0000,
++	0x0000, 0x0000, 0x0000, 0x0000,
++	0x0000, 0x0000, 0x0000, 0x0006,
++	0x0001, 0x0000, 0x574d, 0x4c13,
++	0x0000, 0x0000, 0x0000
++};
++
++/* virtual HP mixers regs */
++#define HPL_MIXER	0x80
++#define HPR_MIXER	0x82
++#define MICB_MUX	0x82
++
++static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
++static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
++static const char *wm9713_rec_src[] =
++	{"Mic 1", "Mic 2", "Line", "Mono In", "Headphone", "Speaker",
++	"Mono Out", "Zh"};
++static const char *wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
++static const char *wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
++static const char *wm9713_mono_pga[] = {"Vmid", "Zh", "Mono", "Inv",
++	"Mono Vmid", "Inv Vmid"};
++static const char *wm9713_spk_pga[] =
++	{"Vmid", "Zh", "Headphone", "Speaker", "Inv", "Headphone Vmid",
++	"Speaker Vmid", "Inv Vmid"};
++static const char *wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone",
++	"Headphone Vmid"};
++static const char *wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "Inv 1 Vmid"};
++static const char *wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "Inv 2 Vmid"};
++static const char *wm9713_dac_inv[] =
++	{"Off", "Mono", "Speaker", "Left Headphone", "Right Headphone",
++	"Headphone Mono", "NC", "Vmid"};
++static const char *wm9713_bass[] = {"Linear Control", "Adaptive Boost"};
++static const char *wm9713_ng_type[] = {"Constant Gain", "Mute"};
++static const char *wm9713_mic_select[] = {"Mic 1", "Mic 2 A", "Mic 2 B"};
++static const char *wm9713_micb_select[] = {"MPB", "MPA"};
++
++static const struct soc_enum wm9713_enum[] = {
++SOC_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), /* record mic mixer 0 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux), /* record mux hp 1 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),  /* record mux mono 2 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src),  /* record mux left 3 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src),  /* record mux right 4*/
++SOC_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain), /* record step size 5 */
++SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select), /* alc source select 6*/
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga), /* mono input select 7 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 11, 8, wm9713_spk_pga), /* speaker left input select 8 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 8, 8, wm9713_spk_pga), /* speaker right input select 9 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 6, 3, wm9713_hp_pga), /* headphone left input 10 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 4, 3, wm9713_hp_pga), /* headphone right input 11 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga), /* out 3 source 12 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga), /* out 4 source 13 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 13, 8, wm9713_dac_inv), /* dac invert 1 14 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */
++SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */
++SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */
++SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */
++SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */
++};
++
++static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = {
++SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
++SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER, 15, 7, 1, 1),
++SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
++SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 7, 1, 1),
++SOC_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
++SOC_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
++SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
++SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
++
++SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
++SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
++
++SOC_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
++SOC_ENUM("Capture Volume Steps", wm9713_enum[5]),
++SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 31, 0),
++SOC_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
++
++SOC_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
++SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
++SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
++
++SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
++SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
++SOC_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
++SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
++SOC_ENUM("ALC Function", wm9713_enum[6]),
++SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
++SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
++SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
++SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
++SOC_ENUM("ALC NG Type", wm9713_enum[17]),
++SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
++
++SOC_DOUBLE("Speaker Playback ZC Switch", AC97_MASTER, 14, 6, 1, 0),
++SOC_DOUBLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
++
++SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
++SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO, 14, 1, 0),
++SOC_SINGLE("Out4 Playback Volume", AC97_MASTER_MONO, 8, 63, 1),
++
++SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO, 7, 1, 1),
++SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO, 6, 1, 0),
++SOC_SINGLE("Out3 Playback Volume", AC97_MASTER_MONO, 0, 63, 1),
++
++SOC_SINGLE("Mono Capture Volume", AC97_MASTER_TONE, 8, 31, 1),
++SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1),
++SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
++SOC_SINGLE("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1),
++
++SOC_SINGLE("PC Beep Playback Headphone Volume", AC97_AUX, 12, 7, 1),
++SOC_SINGLE("PC Beep Playback Speaker Volume", AC97_AUX, 8, 7, 1),
++SOC_SINGLE("PC Beep Playback Mono Volume", AC97_AUX, 4, 7, 1),
++
++SOC_SINGLE("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1),
++SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1),
++SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM, 4, 7, 1),
++
++SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL, 12, 7, 1),
++SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL, 8, 7, 1),
++SOC_SINGLE("Aux Playback Mono Volume", AC97_REC_SEL, 4, 7, 1),
++
++SOC_ENUM("Bass Control", wm9713_enum[16]),
++SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
++SOC_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
++SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
++SOC_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
++SOC_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
++
++SOC_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
++SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
++SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
++};
++
++/* add non dapm controls */
++static int wm9713_add_controls(struct snd_soc_codec *codec)
++{
++	int err, i;
++
++	for (i = 0; i < ARRAY_SIZE(wm9713_snd_ac97_controls); i++) {
++		err = snd_ctl_add(codec->card,
++				snd_soc_cnew(&wm9713_snd_ac97_controls[i],
++					codec, NULL));
++		if (err < 0)
++			return err;
++	}
++	return 0;
++}
++
++/* We have to create a fake left and right HP mixers because
++ * the codec only has a single control that is shared by both channels.
++ * This makes it impossible to determine the audio path using the current
++ * register map, thus we add a new (virtual) register to help determine the
++ * audio route within the device.
++ */
++static int mixer_event(struct snd_soc_dapm_widget *w,
++	struct snd_kcontrol *kcontrol, int event)
++{
++	u16 l, r, beep, tone, phone, rec, pcm, aux;
++
++	l = ac97_read(w->codec, HPL_MIXER);
++	r = ac97_read(w->codec, HPR_MIXER);
++	beep = ac97_read(w->codec, AC97_PC_BEEP);
++	tone = ac97_read(w->codec, AC97_MASTER_TONE);
++	phone = ac97_read(w->codec, AC97_PHONE);
++	rec = ac97_read(w->codec, AC97_REC_SEL);
++	pcm = ac97_read(w->codec, AC97_PCM);
++	aux = ac97_read(w->codec, AC97_AUX);
++
++	if (event & SND_SOC_DAPM_PRE_REG)
++		return 0;
++	if ((l & 0x1) || (r & 0x1))
++		ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
++
++	if ((l & 0x2) || (r & 0x2))
++		ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000);
++
++	if ((l & 0x4) || (r & 0x4))
++		ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
++
++	if ((l & 0x8) || (r & 0x8))
++		ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000);
++
++	if ((l & 0x10) || (r & 0x10))
++		ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
++
++	if ((l & 0x20) || (r & 0x20))
++		ac97_write(w->codec, AC97_AUX, aux & 0x7fff);
++	else
++		ac97_write(w->codec, AC97_AUX, aux | 0x8000);
++
++	return 0;
++}
++
++/* Left Headphone Mixers */
++static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", HPL_MIXER, 5, 1, 0),
++SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0),
++SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0),
++};
++
++/* Right Headphone Mixers */
++static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", HPR_MIXER, 5, 1, 0),
++SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0),
++SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0),
++};
++
++/* headphone capture mux */
++static const struct snd_kcontrol_new wm9713_hp_rec_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[1]);
++
++/* headphone mic mux */
++static const struct snd_kcontrol_new wm9713_hp_mic_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[0]);
++
++/* Speaker Mixer */
++static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 11, 1, 1),
++SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1),
++SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1),
++SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 14, 1, 1),
++SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 14, 1, 1),
++};
++
++/* Mono Mixer */
++static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 7, 1, 1),
++SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1),
++SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1),
++SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 13, 1, 1),
++SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 13, 1, 1),
++SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_LINE, 7, 1, 1),
++SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_LINE, 6, 1, 1),
++};
++
++/* mono mic mux */
++static const struct snd_kcontrol_new wm9713_mono_mic_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[2]);
++
++/* mono output mux */
++static const struct snd_kcontrol_new wm9713_mono_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[7]);
++
++/* speaker left output mux */
++static const struct snd_kcontrol_new wm9713_hp_spkl_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[8]);
++
++/* speaker right output mux */
++static const struct snd_kcontrol_new wm9713_hp_spkr_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[9]);
++
++/* headphone left output mux */
++static const struct snd_kcontrol_new wm9713_hpl_out_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[10]);
++
++/* headphone right output mux */
++static const struct snd_kcontrol_new wm9713_hpr_out_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[11]);
++
++/* Out3 mux */
++static const struct snd_kcontrol_new wm9713_out3_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[12]);
++
++/* Out4 mux */
++static const struct snd_kcontrol_new wm9713_out4_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[13]);
++
++/* DAC inv mux 1 */
++static const struct snd_kcontrol_new wm9713_dac_inv1_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[14]);
++
++/* DAC inv mux 2 */
++static const struct snd_kcontrol_new wm9713_dac_inv2_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[15]);
++
++/* Capture source left */
++static const struct snd_kcontrol_new wm9713_rec_srcl_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[3]);
++
++/* Capture source right */
++static const struct snd_kcontrol_new wm9713_rec_srcr_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[4]);
++
++/* mic source */
++static const struct snd_kcontrol_new wm9713_mic_sel_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[18]);
++
++/* mic source B virtual control */
++static const struct snd_kcontrol_new wm9713_micb_sel_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[19]);
++
++static const struct snd_soc_dapm_widget wm9713_dapm_widgets[] = {
++SND_SOC_DAPM_MUX("Capture Headphone Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hp_rec_mux_controls),
++SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hp_mic_mux_controls),
++SND_SOC_DAPM_MUX("Capture Mono Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_mono_mic_mux_controls),
++SND_SOC_DAPM_MUX("Mono Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_mono_mux_controls),
++SND_SOC_DAPM_MUX("Left Speaker Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hp_spkl_mux_controls),
++SND_SOC_DAPM_MUX("Right Speaker Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hp_spkr_mux_controls),
++SND_SOC_DAPM_MUX("Left Headphone Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hpl_out_mux_controls),
++SND_SOC_DAPM_MUX("Right Headphone Out Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_hpr_out_mux_controls),
++SND_SOC_DAPM_MUX("Out 3 Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_out3_mux_controls),
++SND_SOC_DAPM_MUX("Out 4 Mux", SND_SOC_NOPM, 0, 0,
++	&wm9713_out4_mux_controls),
++SND_SOC_DAPM_MUX("DAC Inv Mux 1", SND_SOC_NOPM, 0, 0,
++	&wm9713_dac_inv1_mux_controls),
++SND_SOC_DAPM_MUX("DAC Inv Mux 2", SND_SOC_NOPM, 0, 0,
++	&wm9713_dac_inv2_mux_controls),
++SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0,
++	&wm9713_rec_srcl_mux_controls),
++SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0,
++	&wm9713_rec_srcr_mux_controls),
++SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0,
++	&wm9713_mic_sel_mux_controls),
++SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0,
++	&wm9713_micb_sel_mux_controls),
++SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1,
++	&wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls),
++	mixer_event, SND_SOC_DAPM_POST_REG),
++SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1,
++	&wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls),
++	mixer_event, SND_SOC_DAPM_POST_REG),
++SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1,
++	&wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)),
++SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1,
++	&wm9713_speaker_mixer_controls[0],
++	ARRAY_SIZE(wm9713_speaker_mixer_controls)),
++SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_EXTENDED_MID, 7, 1),
++SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_EXTENDED_MID, 6, 1),
++SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1),
++SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
++SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_EXTENDED_MID, 5, 1),
++SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_EXTENDED_MID, 4, 1),
++SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS, 10, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS, 9, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS, 8, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Right Speaker", AC97_EXTENDED_MSTATUS, 7, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Out 3", AC97_EXTENDED_MSTATUS, 11, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Out 4", AC97_EXTENDED_MSTATUS, 12, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mono Out", AC97_EXTENDED_MSTATUS, 13, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Left Line In", AC97_EXTENDED_MSTATUS, 6, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Right Line In", AC97_EXTENDED_MSTATUS, 5, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mono In", AC97_EXTENDED_MSTATUS, 4, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic A PGA", AC97_EXTENDED_MSTATUS, 3, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic B PGA", AC97_EXTENDED_MSTATUS, 2, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic A Pre Amp", AC97_EXTENDED_MSTATUS, 1, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic B Pre Amp", AC97_EXTENDED_MSTATUS, 0, 1, NULL, 0),
++SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_EXTENDED_MSTATUS, 14, 1),
++SND_SOC_DAPM_OUTPUT("MONO"),
++SND_SOC_DAPM_OUTPUT("HPL"),
++SND_SOC_DAPM_OUTPUT("HPR"),
++SND_SOC_DAPM_OUTPUT("SPKL"),
++SND_SOC_DAPM_OUTPUT("SPKR"),
++SND_SOC_DAPM_OUTPUT("OUT3"),
++SND_SOC_DAPM_OUTPUT("OUT4"),
++SND_SOC_DAPM_INPUT("LINEL"),
++SND_SOC_DAPM_INPUT("LINER"),
++SND_SOC_DAPM_INPUT("MONOIN"),
++SND_SOC_DAPM_INPUT("PCBEEP"),
++SND_SOC_DAPM_INPUT("MIC1"),
++SND_SOC_DAPM_INPUT("MIC2A"),
++SND_SOC_DAPM_INPUT("MIC2B"),
++SND_SOC_DAPM_VMID("VMID"),
++};
++
++static const char *audio_map[][3] = {
++	/* left HP mixer */
++	{"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
++	{"Left HP Mixer", "Voice Playback Switch",   "Voice DAC"},
++	{"Left HP Mixer", "Aux Playback Switch",     "Aux DAC"},
++	{"Left HP Mixer", "Bypass Playback Switch",  "Left Line In"},
++	{"Left HP Mixer", "PCM Playback Switch",     "Left DAC"},
++	{"Left HP Mixer", "MonoIn Playback Switch",  "Mono In"},
++	{"Left HP Mixer", NULL,  "Capture Headphone Mux"},
++
++	/* right HP mixer */
++	{"Right HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
++	{"Right HP Mixer", "Voice Playback Switch",   "Voice DAC"},
++	{"Right HP Mixer", "Aux Playback Switch",     "Aux DAC"},
++	{"Right HP Mixer", "Bypass Playback Switch",  "Right Line In"},
++	{"Right HP Mixer", "PCM Playback Switch",     "Right DAC"},
++	{"Right HP Mixer", "MonoIn Playback Switch",  "Mono In"},
++	{"Right HP Mixer", NULL,  "Capture Headphone Mux"},
++
++	/* virtual mixer - mixes left & right channels for spk and mono */
++	{"AC97 Mixer", NULL, "Left DAC"},
++	{"AC97 Mixer", NULL, "Right DAC"},
++	{"Line Mixer", NULL, "Right Line In"},
++	{"Line Mixer", NULL, "Left Line In"},
++	{"HP Mixer", NULL, "Left HP Mixer"},
++	{"HP Mixer", NULL, "Right HP Mixer"},
++	{"Capture Mixer", NULL, "Left Capture Source"},
++	{"Capture Mixer", NULL, "Right Capture Source"},
++
++	/* speaker mixer */
++	{"Speaker Mixer", "PC Beep Playback Switch", "PCBEEP"},
++	{"Speaker Mixer", "Voice Playback Switch",   "Voice DAC"},
++	{"Speaker Mixer", "Aux Playback Switch",     "Aux DAC"},
++	{"Speaker Mixer", "Bypass Playback Switch",  "Line Mixer"},
++	{"Speaker Mixer", "PCM Playback Switch",     "AC97 Mixer"},
++	{"Speaker Mixer", "MonoIn Playback Switch",  "Mono In"},
++
++	/* mono mixer */
++	{"Mono Mixer", "PC Beep Playback Switch", "PCBEEP"},
++	{"Mono Mixer", "Voice Playback Switch",   "Voice DAC"},
++	{"Mono Mixer", "Aux Playback Switch",     "Aux DAC"},
++	{"Mono Mixer", "Bypass Playback Switch",  "Line Mixer"},
++	{"Mono Mixer", "PCM Playback Switch",     "AC97 Mixer"},
++	{"Mono Mixer", "Mic 1 Sidetone Switch", "Mic A PGA"},
++	{"Mono Mixer", "Mic 2 Sidetone Switch", "Mic B PGA"},
++	{"Mono Mixer", NULL,  "Capture Mono Mux"},
++
++	/* DAC inv mux 1 */
++	{"DAC Inv Mux 1", "Mono", "Mono Mixer"},
++	{"DAC Inv Mux 1", "Speaker", "Speaker Mixer"},
++	{"DAC Inv Mux 1", "Left Headphone", "Left HP Mixer"},
++	{"DAC Inv Mux 1", "Right Headphone", "Right HP Mixer"},
++	{"DAC Inv Mux 1", "Headphone Mono", "HP Mixer"},
++
++	/* DAC inv mux 2 */
++	{"DAC Inv Mux 2", "Mono", "Mono Mixer"},
++	{"DAC Inv Mux 2", "Speaker", "Speaker Mixer"},
++	{"DAC Inv Mux 2", "Left Headphone", "Left HP Mixer"},
++	{"DAC Inv Mux 2", "Right Headphone", "Right HP Mixer"},
++	{"DAC Inv Mux 2", "Headphone Mono", "HP Mixer"},
++
++	/* headphone left mux */
++	{"Left Headphone Out Mux", "Headphone", "Left HP Mixer"},
++
++	/* headphone right mux */
++	{"Right Headphone Out Mux", "Headphone", "Right HP Mixer"},
++
++	/* speaker left mux */
++	{"Left Speaker Out Mux", "Headphone", "Left HP Mixer"},
++	{"Left Speaker Out Mux", "Speaker", "Speaker Mixer"},
++	{"Left Speaker Out Mux", "Inv", "DAC Inv Mux 1"},
++
++	/* speaker right mux */
++	{"Right Speaker Out Mux", "Headphone", "Right HP Mixer"},
++	{"Right Speaker Out Mux", "Speaker", "Speaker Mixer"},
++	{"Right Speaker Out Mux", "Inv", "DAC Inv Mux 2"},
++
++	/* mono mux */
++	{"Mono Out Mux", "Mono", "Mono Mixer"},
++	{"Mono Out Mux", "Inv", "DAC Inv Mux 1"},
++
++	/* out 3 mux */
++	{"Out 3 Mux", "Inv 1", "DAC Inv Mux 1"},
++
++	/* out 4 mux */
++	{"Out 4 Mux", "Inv 2", "DAC Inv Mux 2"},
++
++	/* output pga */
++	{"HPL", NULL, "Left Headphone"},
++	{"Left Headphone", NULL, "Left Headphone Out Mux"},
++	{"HPR", NULL, "Right Headphone"},
++	{"Right Headphone", NULL, "Right Headphone Out Mux"},
++	{"OUT3", NULL, "Out 3"},
++	{"Out 3", NULL, "Out 3 Mux"},
++	{"OUT4", NULL, "Out 4"},
++	{"Out 4", NULL, "Out 4 Mux"},
++	{"SPKL", NULL, "Left Speaker"},
++	{"Left Speaker", NULL, "Left Speaker Out Mux"},
++	{"SPKR", NULL, "Right Speaker"},
++	{"Right Speaker", NULL, "Right Speaker Out Mux"},
++	{"MONO", NULL, "Mono Out"},
++	{"Mono Out", NULL, "Mono Out Mux"},
++
++	/* input pga */
++	{"Left Line In", NULL, "LINEL"},
++	{"Right Line In", NULL, "LINER"},
++	{"Mono In", NULL, "MONOIN"},
++	{"Mic A PGA", NULL, "Mic A Pre Amp"},
++	{"Mic B PGA", NULL, "Mic B Pre Amp"},
++
++	/* left capture select */
++	{"Left Capture Source", "Mic 1", "Mic A Pre Amp"},
++	{"Left Capture Source", "Mic 2", "Mic B Pre Amp"},
++	{"Left Capture Source", "Line", "LINEL"},
++	{"Left Capture Source", "Mono In", "MONOIN"},
++	{"Left Capture Source", "Headphone", "Left HP Mixer"},
++	{"Left Capture Source", "Speaker", "Speaker Mixer"},
++	{"Left Capture Source", "Mono Out", "Mono Mixer"},
++
++	/* right capture select */
++	{"Right Capture Source", "Mic 1", "Mic A Pre Amp"},
++	{"Right Capture Source", "Mic 2", "Mic B Pre Amp"},
++	{"Right Capture Source", "Line", "LINER"},
++	{"Right Capture Source", "Mono In", "MONOIN"},
++	{"Right Capture Source", "Headphone", "Right HP Mixer"},
++	{"Right Capture Source", "Speaker", "Speaker Mixer"},
++	{"Right Capture Source", "Mono Out", "Mono Mixer"},
++
++	/* left ADC */
++	{"Left ADC", NULL, "Left Capture Source"},
++
++	/* right ADC */
++	{"Right ADC", NULL, "Right Capture Source"},
++
++	/* mic */
++	{"Mic A Pre Amp", NULL, "Mic A Source"},
++	{"Mic A Source", "Mic 1", "MIC1"},
++	{"Mic A Source", "Mic 2 A", "MIC2A"},
++	{"Mic A Source", "Mic 2 B", "Mic B Source"},
++	{"Mic B Pre Amp", "MPB", "Mic B Source"},
++	{"Mic B Source", NULL, "MIC2B"},
++
++	/* headphone capture */
++	{"Capture Headphone Mux", "Stereo", "Capture Mixer"},
++	{"Capture Headphone Mux", "Left", "Left Capture Source"},
++	{"Capture Headphone Mux", "Right", "Right Capture Source"},
++
++	/* mono capture */
++	{"Capture Mono Mux", "Stereo", "Capture Mixer"},
++	{"Capture Mono Mux", "Left", "Left Capture Source"},
++	{"Capture Mono Mux", "Right", "Right Capture Source"},
++
++	{NULL, NULL, NULL},
++};
++
++static int wm9713_add_widgets(struct snd_soc_codec *codec)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(wm9713_dapm_widgets); i++)
++		snd_soc_dapm_new_control(codec, &wm9713_dapm_widgets[i]);
++
++	/* set up audio path audio_mapnects */
++	for (i = 0; audio_map[i][0] != NULL; i++)
++		snd_soc_dapm_connect_input(codec, audio_map[i][0],
++			audio_map[i][1], audio_map[i][2]);
++
++	snd_soc_dapm_new_widgets(codec);
++	return 0;
++}
++
++static unsigned int ac97_read(struct snd_soc_codec *codec,
++	unsigned int reg)
++{
++	u16 *cache = codec->reg_cache;
++
++	if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
++		reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
++		reg == AC97_CD)
++		return soc_ac97_ops.read(codec->ac97, reg);
++	else {
++		reg = reg >> 1;
++
++		if (reg > (ARRAY_SIZE(wm9713_reg)))
++			return -EIO;
++
++		return cache[reg];
++	}
++}
++
++static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
++	unsigned int val)
++{
++	u16 *cache = codec->reg_cache;
++	if (reg < 0x7c)
++		soc_ac97_ops.write(codec->ac97, reg, val);
++	reg = reg >> 1;
++	if (reg <= (ARRAY_SIZE(wm9713_reg)))
++		cache[reg] = val;
++
++	return 0;
++}
++
++/* PLL divisors */
++struct _pll_div {
++	u32 divsel:1;
++	u32 divctl:1;
++	u32 lf:1;
++	u32 n:4;
++	u32 k:24;
++};
++
++/* The size in bits of the PLL divide multiplied by 10
++ * to allow rounding later */
++#define FIXED_PLL_SIZE ((1 << 22) * 10)
++
++static void pll_factors(struct _pll_div *pll_div, unsigned int source)
++{
++	u64 Kpart;
++	unsigned int K, Ndiv, Nmod, target;
++
++	/* The the PLL output is always 98.304MHz. */
++	target = 98304000;
++
++	/* If the input frequency is over 14.4MHz then scale it down. */
++	if (source > 14400000) {
++		source >>= 1;
++		pll_div->divsel = 1;
++
++		if (source > 14400000) {
++			source >>= 1;
++			pll_div->divctl = 1;
++		} else
++			pll_div->divctl = 0;
++
++	} else {
++		pll_div->divsel = 0;
++		pll_div->divctl = 0;
++	}
++
++	/* Low frequency sources require an additional divide in the
++	 * loop.
++	 */
++	if (source < 8192000) {
++		pll_div->lf = 1;
++		target >>= 2;
++	} else
++		pll_div->lf = 0;
++
++	Ndiv = target / source;
++	if ((Ndiv < 5) || (Ndiv > 12))
++		printk(KERN_WARNING
++			"WM9713 PLL N value %d out of recommended range!\n",
++			Ndiv);
++
++	pll_div->n = Ndiv;
++	Nmod = target % source;
++	Kpart = FIXED_PLL_SIZE * (long long)Nmod;
++
++	do_div(Kpart, source);
++
++	K = Kpart & 0xFFFFFFFF;
++
++	/* Check if we need to round */
++	if ((K % 10) >= 5)
++		K += 5;
++
++	/* Move down to proper range now rounding is done */
++	K /= 10;
++
++	pll_div->k = K;
++}
++
++/**
++ * Please note that changing the PLL input frequency may require
++ * resynchronisation with the AC97 controller.
++ */
++static int wm9713_set_pll(struct snd_soc_codec *codec,
++	int pll_id, unsigned int freq_in, unsigned int freq_out)
++{
++	struct wm9713_priv *wm9713 = codec->private_data;
++	u16 reg, reg2;
++	struct _pll_div pll_div;
++
++	/* turn PLL off ? */
++	if (freq_in == 0 || freq_out == 0) {
++		/* disable PLL power and select ext source */
++		reg = ac97_read(codec, AC97_HANDSET_RATE);
++		ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080);
++		reg = ac97_read(codec, AC97_EXTENDED_MID);
++		ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200);
++		wm9713->pll_out = 0;
++		return 0;
++	}
++
++	pll_factors(&pll_div, freq_in);
++
++	if (pll_div.k == 0) {
++		reg = (pll_div.n << 12) | (pll_div.lf << 11) |
++			(pll_div.divsel << 9) | (pll_div.divctl << 8);
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++	} else {
++		/* write the fractional k to the reg 0x46 pages */
++		reg2 = (pll_div.n << 12) | (pll_div.lf << 11) | (1 << 10) |
++			(pll_div.divsel << 9) | (pll_div.divctl << 8);
++
++		/* K [21:20] */
++		reg = reg2 | (0x5 << 4) | (pll_div.k >> 20);
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		/* K [19:16] */
++		reg = reg2 | (0x4 << 4) | ((pll_div.k >> 16) & 0xf);
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		/* K [15:12] */
++		reg = reg2 | (0x3 << 4) | ((pll_div.k >> 12) & 0xf);
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		/* K [11:8] */
++		reg = reg2 | (0x2 << 4) | ((pll_div.k >> 8) & 0xf);
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		/* K [7:4] */
++		reg = reg2 | (0x1 << 4) | ((pll_div.k >> 4) & 0xf);
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++		reg = reg2 | (0x0 << 4) | (pll_div.k & 0xf); /* K [3:0] */
++		ac97_write(codec, AC97_LINE1_LEVEL, reg);
++	}
++
++	/* turn PLL on and select as source */
++	reg = ac97_read(codec, AC97_EXTENDED_MID);
++	ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff);
++	reg = ac97_read(codec, AC97_HANDSET_RATE);
++	ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f);
++	wm9713->pll_out = freq_out;
++	wm9713->pll_in = freq_in;
++
++	/* wait 10ms AC97 link frames for the link to stabilise */
++	schedule_timeout_interruptible(msecs_to_jiffies(10));
++	return 0;
++}
++
++static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
++		int pll_id, unsigned int freq_in, unsigned int freq_out)
++{
++	struct snd_soc_codec *codec = codec_dai->codec;
++	return wm9713_set_pll(codec, pll_id, freq_in, freq_out);
++}
++
++/*
++ * Tristate the PCM DAI lines, tristate can be disabled by calling
++ * wm9713_set_dai_fmt()
++ */
++static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai,
++	int tristate)
++{
++	struct snd_soc_codec *codec = codec_dai->codec;
++	u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0x9fff;
++
++	if (tristate)
++		ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
++
++	return 0;
++}
++
++/*
++ * Configure WM9713 clock dividers.
++ * Voice DAC needs 256 FS
++ */
++static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
++		int div_id, int div)
++{
++	struct snd_soc_codec *codec = codec_dai->codec;
++	u16 reg;
++
++	switch (div_id) {
++	case WM9713_PCMCLK_DIV:
++		reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xf0ff;
++		ac97_write(codec, AC97_HANDSET_RATE, reg | div);
++		break;
++	case WM9713_CLKA_MULT:
++		reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffd;
++		ac97_write(codec, AC97_HANDSET_RATE, reg | div);
++		break;
++	case WM9713_CLKB_MULT:
++		reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffb;
++		ac97_write(codec, AC97_HANDSET_RATE, reg | div);
++		break;
++	case WM9713_HIFI_DIV:
++		reg = ac97_read(codec, AC97_HANDSET_RATE) & 0x8fff;
++		ac97_write(codec, AC97_HANDSET_RATE, reg | div);
++		break;
++	case WM9713_PCMBCLK_DIV:
++		reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xf1ff;
++		ac97_write(codec, AC97_CENTER_LFE_MASTER, reg | div);
++		break;
++	case WM9713_PCMCLK_PLL_DIV:
++		reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
++		ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x60 | div);
++		break;
++	case WM9713_HIFI_PLL_DIV:
++		reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
++		ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x70 | div);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
++		unsigned int fmt)
++{
++	struct snd_soc_codec *codec = codec_dai->codec;
++	u16 gpio = ac97_read(codec, AC97_GPIO_CFG) & 0xffc5;
++	u16 reg = 0x8000;
++
++	/* clock masters */
++	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++	case SND_SOC_DAIFMT_CBM_CFM:
++		reg |= 0x4000;
++		gpio |= 0x0010;
++		break;
++	case SND_SOC_DAIFMT_CBM_CFS:
++		reg |= 0x6000;
++		gpio |= 0x0018;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFS:
++		reg |= 0x0200;
++		gpio |= 0x001a;
++		break;
++	case SND_SOC_DAIFMT_CBS_CFM:
++		gpio |= 0x0012;
++		break;
++	}
++
++	/* clock inversion */
++	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_IB_IF:
++		reg |= 0x00c0;
++		break;
++	case SND_SOC_DAIFMT_IB_NF:
++		reg |= 0x0080;
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		reg |= 0x0040;
++		break;
++	}
++
++	/* DAI format */
++	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++	case SND_SOC_DAIFMT_I2S:
++		reg |= 0x0002;
++		break;
++	case SND_SOC_DAIFMT_RIGHT_J:
++		break;
++	case SND_SOC_DAIFMT_LEFT_J:
++		reg |= 0x0001;
++		break;
++	case SND_SOC_DAIFMT_DSP_A:
++		reg |= 0x0003;
++		break;
++	case SND_SOC_DAIFMT_DSP_B:
++		reg |= 0x0043;
++		break;
++	}
++
++	ac97_write(codec, AC97_GPIO_CFG, gpio);
++	ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
++	return 0;
++}
++
++static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
++
++	switch (params_format(params)) {
++	case SNDRV_PCM_FORMAT_S16_LE:
++		break;
++	case SNDRV_PCM_FORMAT_S20_3LE:
++		reg |= 0x0004;
++		break;
++	case SNDRV_PCM_FORMAT_S24_LE:
++		reg |= 0x0008;
++		break;
++	case SNDRV_PCM_FORMAT_S32_LE:
++		reg |= 0x000c;
++		break;
++	}
++
++	/* enable PCM interface in master mode */
++	ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
++	return 0;
++}
++
++static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
++{
++    struct snd_soc_pcm_runtime *rtd = substream->private_data;
++    struct snd_soc_device *socdev = rtd->socdev;
++    struct snd_soc_codec *codec = socdev->codec;
++    u16 status;
++
++    /* Gracefully shut down the voice interface. */
++    status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
++    ac97_write(codec, AC97_HANDSET_RATE, 0x0280);
++    schedule_timeout_interruptible(msecs_to_jiffies(1));
++    ac97_write(codec, AC97_HANDSET_RATE, 0x0F80);
++    ac97_write(codec, AC97_EXTENDED_MID, status);
++}
++
++static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	int reg;
++	u16 vra;
++
++	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
++	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		reg = AC97_PCM_FRONT_DAC_RATE;
++	else
++		reg = AC97_PCM_LR_ADC_RATE;
++
++	return ac97_write(codec, reg, runtime->rate);
++}
++
++static int ac97_aux_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_device *socdev = rtd->socdev;
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 vra, xsle;
++
++	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
++	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
++	xsle = ac97_read(codec, AC97_PCI_SID);
++	ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
++
++	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
++		return -ENODEV;
++
++	return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
++}
++
++#define WM9713_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
++		SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
++		SNDRV_PCM_RATE_48000)
++
++#define WM9713_PCM_FORMATS \
++	(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
++	 SNDRV_PCM_FORMAT_S24_LE)
++
++struct snd_soc_codec_dai wm9713_dai[] = {
++{
++	.name = "AC97 HiFi",
++	.type = SND_SOC_DAI_AC97_BUS,
++	.playback = {
++		.stream_name = "HiFi Playback",
++		.channels_min = 1,
++		.channels_max = 2,
++		.rates = WM9713_RATES,
++		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
++	.capture = {
++		.stream_name = "HiFi Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++		.rates = WM9713_RATES,
++		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
++	.ops = {
++		.prepare = ac97_hifi_prepare,},
++	.dai_ops = {
++		.set_clkdiv = wm9713_set_dai_clkdiv,
++		.set_pll = wm9713_set_dai_pll,},
++	},
++	{
++	.name = "AC97 Aux",
++	.playback = {
++		.stream_name = "Aux Playback",
++		.channels_min = 1,
++		.channels_max = 1,
++		.rates = WM9713_RATES,
++		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
++	.ops = {
++		.prepare = ac97_aux_prepare,},
++	.dai_ops = {
++		.set_clkdiv = wm9713_set_dai_clkdiv,
++		.set_pll = wm9713_set_dai_pll,},
++	},
++	{
++	.name = "WM9713 Voice",
++	.playback = {
++		.stream_name = "Voice Playback",
++		.channels_min = 1,
++		.channels_max = 1,
++		.rates = WM9713_RATES,
++		.formats = WM9713_PCM_FORMATS,},
++	.capture = {
++		.stream_name = "Voice Capture",
++		.channels_min = 1,
++		.channels_max = 2,
++		.rates = WM9713_RATES,
++		.formats = WM9713_PCM_FORMATS,},
++	.ops = {
++		.hw_params = wm9713_pcm_hw_params,
++		.shutdown = wm9713_voiceshutdown,},
++	.dai_ops = {
++		.set_clkdiv = wm9713_set_dai_clkdiv,
++		.set_pll = wm9713_set_dai_pll,
++		.set_fmt = wm9713_set_dai_fmt,
++		.set_tristate = wm9713_set_dai_tristate,
++	},
++	},
++};
++EXPORT_SYMBOL_GPL(wm9713_dai);
++
++int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
++{
++	if (try_warm && soc_ac97_ops.warm_reset) {
++		soc_ac97_ops.warm_reset(codec->ac97);
++		if (!(ac97_read(codec, 0) & 0x8000))
++			return 1;
++	}
++
++	soc_ac97_ops.reset(codec->ac97);
++	if (ac97_read(codec, 0) & 0x8000)
++		return -EIO;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(wm9713_reset);
++
++static int wm9713_dapm_event(struct snd_soc_codec *codec, int event)
++{
++	u16 reg;
++
++	switch (event) {
++	case SNDRV_CTL_POWER_D0: /* full On */
++		/* enable thermal shutdown */
++		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff;
++		ac97_write(codec, AC97_EXTENDED_MID, reg);
++		break;
++	case SNDRV_CTL_POWER_D1: /* partial On */
++	case SNDRV_CTL_POWER_D2: /* partial On */
++		break;
++	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++		/* enable master bias and vmid */
++		reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff;
++		ac97_write(codec, AC97_EXTENDED_MID, reg);
++		ac97_write(codec, AC97_POWERDOWN, 0x0000);
++		break;
++	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++		/* disable everything including AC link */
++		ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
++		ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
++		ac97_write(codec, AC97_POWERDOWN, 0xffff);
++		break;
++	}
++	codec->dapm_state = event;
++	return 0;
++}
++
++static int wm9713_soc_suspend(struct platform_device *pdev,
++	pm_message_t state)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	u16 reg;
++
++	/* Disable everything except touchpanel - that will be handled
++	 * by the touch driver and left disabled if touch is not in
++	 * use. */
++	reg = ac97_read(codec, AC97_EXTENDED_MID);
++	ac97_write(codec, AC97_EXTENDED_MID, reg | 0x7fff);
++	ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
++	ac97_write(codec, AC97_POWERDOWN, 0x6f00);
++	ac97_write(codec, AC97_POWERDOWN, 0xffff);
++
++	return 0;
++}
++
++static int wm9713_soc_resume(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++	struct wm9713_priv *wm9713 = codec->private_data;
++	int i, ret;
++	u16 *cache = codec->reg_cache;
++
++	ret = wm9713_reset(codec, 1);
++	if (ret < 0) {
++		printk(KERN_ERR "could not reset AC97 codec\n");
++		return ret;
++	}
++
++	wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* do we need to re-start the PLL ? */
++	if (wm9713->pll_out)
++		wm9713_set_pll(codec, 0, wm9713->pll_in, wm9713->pll_out);
++
++	/* only synchronise the codec if warm reset failed */
++	if (ret == 0) {
++		for (i = 2; i < ARRAY_SIZE(wm9713_reg) << 1; i += 2) {
++			if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID ||
++				i == AC97_EXTENDED_MSTATUS || i > 0x66)
++				continue;
++			soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
++		}
++	}
++
++	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
++		wm9713_dapm_event(codec, SNDRV_CTL_POWER_D0);
++
++	return ret;
++}
++
++static int wm9713_soc_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec;
++	int ret = 0, reg;
++
++	printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION);
++
++	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
++	if (socdev->codec == NULL)
++		return -ENOMEM;
++	codec = socdev->codec;
++	mutex_init(&codec->mutex);
++
++	codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL);
++	if (codec->reg_cache == NULL) {
++		ret = -ENOMEM;
++		goto cache_err;
++	}
++	codec->reg_cache_size = sizeof(wm9713_reg);
++	codec->reg_cache_step = 2;
++
++	codec->private_data = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL);
++	if (codec->private_data == NULL) {
++		ret = -ENOMEM;
++		goto priv_err;
++	}
++
++	codec->name = "WM9713";
++	codec->owner = THIS_MODULE;
++	codec->dai = wm9713_dai;
++	codec->num_dai = ARRAY_SIZE(wm9713_dai);
++	codec->write = ac97_write;
++	codec->read = ac97_read;
++	codec->dapm_event = wm9713_dapm_event;
++	INIT_LIST_HEAD(&codec->dapm_widgets);
++	INIT_LIST_HEAD(&codec->dapm_paths);
++
++	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
++	if (ret < 0)
++		goto codec_err;
++
++	/* register pcms */
++	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++	if (ret < 0)
++		goto pcm_err;
++
++	/* do a cold reset for the controller and then try
++	 * a warm reset followed by an optional cold reset for codec */
++	wm9713_reset(codec, 0);
++	ret = wm9713_reset(codec, 1);
++	if (ret < 0) {
++		printk(KERN_ERR "AC97 link error\n");
++		goto reset_err;
++	}
++
++	wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++	/* unmute the adc - move to kcontrol */
++	reg = ac97_read(codec, AC97_CD) & 0x7fff;
++	ac97_write(codec, AC97_CD, reg);
++
++	wm9713_add_controls(codec);
++	wm9713_add_widgets(codec);
++	ret = snd_soc_register_card(socdev);
++	if (ret < 0)
++		goto reset_err;
++	return 0;
++
++reset_err:
++	snd_soc_free_pcms(socdev);
++
++pcm_err:
++	snd_soc_free_ac97_codec(codec);
++
++codec_err:
++	kfree(codec->private_data);
++
++priv_err:
++	kfree(codec->reg_cache);
++
++cache_err:
++	kfree(socdev->codec);
++	socdev->codec = NULL;
++	return ret;
++}
++
++static int wm9713_soc_remove(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_codec *codec = socdev->codec;
++
++	if (codec == NULL)
++		return 0;
++
++	snd_soc_dapm_free(socdev);
++	snd_soc_free_pcms(socdev);
++	snd_soc_free_ac97_codec(codec);
++	kfree(codec->private_data);
++	kfree(codec->reg_cache);
++	kfree(codec->dai);
++	kfree(codec);
++	return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm9713 = {
++	.probe = 	wm9713_soc_probe,
++	.remove = 	wm9713_soc_remove,
++	.suspend =	wm9713_soc_suspend,
++	.resume = 	wm9713_soc_resume,
++};
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713);
++
++MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h
+new file mode 100644
+index 0000000..d357b6c
+--- /dev/null
++++ b/sound/soc/codecs/wm9713.h
+@@ -0,0 +1,53 @@
++/*
++ * wm9713.h  --  WM9713 Soc Audio driver
++ */
++
++#ifndef _WM9713_H
++#define _WM9713_H
++
++/* clock inputs */
++#define WM9713_CLKA_PIN			0
++#define WM9713_CLKB_PIN			1
++
++/* clock divider ID's */
++#define WM9713_PCMCLK_DIV		0
++#define WM9713_CLKA_MULT		1
++#define WM9713_CLKB_MULT		2
++#define WM9713_HIFI_DIV			3
++#define WM9713_PCMBCLK_DIV		4
++#define WM9713_PCMCLK_PLL_DIV           5
++#define WM9713_HIFI_PLL_DIV             6
++
++/* Calculate the appropriate bit mask for the external PCM clock divider */
++#define WM9713_PCMDIV(x)	((x - 1) << 8)
++
++/* Calculate the appropriate bit mask for the external HiFi clock divider */
++#define WM9713_HIFIDIV(x)	((x - 1) << 12)
++
++/* MCLK clock mulitipliers */
++#define WM9713_CLKA_X1		(0 << 1)
++#define WM9713_CLKA_X2		(1 << 1)
++#define WM9713_CLKB_X1		(0 << 2)
++#define WM9713_CLKB_X2		(1 << 2)
++
++/* MCLK clock MUX */
++#define WM9713_CLK_MUX_A		(0 << 0)
++#define WM9713_CLK_MUX_B		(1 << 0)
++
++/* Voice DAI BCLK divider */
++#define WM9713_PCMBCLK_DIV_1	(0 << 9)
++#define WM9713_PCMBCLK_DIV_2	(1 << 9)
++#define WM9713_PCMBCLK_DIV_4	(2 << 9)
++#define WM9713_PCMBCLK_DIV_8	(3 << 9)
++#define WM9713_PCMBCLK_DIV_16	(4 << 9)
++
++#define WM9713_DAI_AC97_HIFI	0
++#define WM9713_DAI_AC97_AUX		1
++#define WM9713_DAI_PCM_VOICE	2
++
++extern struct snd_soc_codec_device soc_codec_dev_wm9713;
++extern struct snd_soc_codec_dai wm9713_dai[3];
++
++int wm9713_reset(struct snd_soc_codec *codec,  int try_warm);
++
++#endif
+diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
+new file mode 100644
+index 0000000..20680c5
+--- /dev/null
++++ b/sound/soc/davinci/Kconfig
+@@ -0,0 +1,19 @@
++config SND_DAVINCI_SOC
++	tristate "SoC Audio for the TI DAVINCI chip"
++	depends on ARCH_DAVINCI && SND_SOC
++	help
++	  Say Y or M if you want to add support for codecs attached to
++	  the DAVINCI AC97 or I2S interface. You will also need
++	  to select the audio interfaces to support below.
++
++config SND_DAVINCI_SOC_I2S
++	tristate
++
++config SND_DAVINCI_SOC_EVM
++	tristate "SoC Audio support for DaVinci EVM"
++	depends on SND_DAVINCI_SOC && MACH_DAVINCI_EVM
++	select SND_DAVINCI_SOC_I2S
++	select SND_SOC_TLV320AIC3X
++	help
++	  Say Y if you want to add support for SoC audio on TI
++	  DaVinci EVM platform.
+diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
+new file mode 100644
+index 0000000..ca772e5
+--- /dev/null
++++ b/sound/soc/davinci/Makefile
+@@ -0,0 +1,11 @@
++# DAVINCI Platform Support
++snd-soc-davinci-objs := davinci-pcm.o
++snd-soc-davinci-i2s-objs := davinci-i2s.o
++
++obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
++obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
++
++# DAVINCI Machine Support
++snd-soc-evm-objs := davinci-evm.o
++
++obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
+diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
+new file mode 100644
+index 0000000..fcd1652
+--- /dev/null
++++ b/sound/soc/davinci/davinci-evm.c
+@@ -0,0 +1,208 @@
++/*
++ * ASoC driver for TI DAVINCI EVM platform
++ *
++ * Author:      Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright:   (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/mach-types.h>
++#include <asm/dma.h>
++#include <asm/arch/hardware.h>
++
++#include "../codecs/tlv320aic3x.h"
++#include "davinci-pcm.h"
++#include "davinci-i2s.h"
++
++#define EVM_CODEC_CLOCK 22579200
++
++static int evm_hw_params(struct snd_pcm_substream *substream,
++			 struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
++	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
++	int ret = 0;
++
++	/* set codec DAI configuration */
++	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
++					 SND_SOC_DAIFMT_CBM_CFM);
++	if (ret < 0)
++		return ret;
++
++	/* set cpu DAI configuration */
++	ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
++				       SND_SOC_DAIFMT_IB_NF);
++	if (ret < 0)
++		return ret;
++
++	/* set the codec system clock */
++	ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK,
++					    SND_SOC_CLOCK_OUT);
++	if (ret < 0)
++		return ret;
++
++	return 0;
++}
++
++static struct snd_soc_ops evm_ops = {
++	.hw_params = evm_hw_params,
++};
++
++/* davinci-evm machine dapm widgets */
++static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
++	SND_SOC_DAPM_HP("Headphone Jack", NULL),
++	SND_SOC_DAPM_LINE("Line Out", NULL),
++	SND_SOC_DAPM_MIC("Mic Jack", NULL),
++	SND_SOC_DAPM_LINE("Line In", NULL),
++};
++
++/* davinci-evm machine audio_mapnections to the codec pins */
++static const char *audio_map[][3] = {
++	/* Headphone connected to HPLOUT, HPROUT */
++	{"Headphone Jack", NULL, "HPLOUT"},
++	{"Headphone Jack", NULL, "HPROUT"},
++
++	/* Line Out connected to LLOUT, RLOUT */
++	{"Line Out", NULL, "LLOUT"},
++	{"Line Out", NULL, "RLOUT"},
++
++	/* Mic connected to (MIC3L | MIC3R) */
++	{"MIC3L", NULL, "Mic Bias 2V"},
++	{"MIC3R", NULL, "Mic Bias 2V"},
++	{"Mic Bias 2V", NULL, "Mic Jack"},
++
++	/* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
++	{"LINE1L", NULL, "Line In"},
++	{"LINE2L", NULL, "Line In"},
++	{"LINE1R", NULL, "Line In"},
++	{"LINE2R", NULL, "Line In"},
++
++	{NULL, NULL, NULL},
++};
++
++/* Logic for a aic3x as connected on a davinci-evm */
++static int evm_aic3x_init(struct snd_soc_codec *codec)
++{
++	int i;
++
++	/* Add davinci-evm specific widgets */
++	for (i = 0; i < ARRAY_SIZE(aic3x_dapm_widgets); i++)
++		snd_soc_dapm_new_control(codec, &aic3x_dapm_widgets[i]);
++
++	/* Set up davinci-evm specific audio path audio_map */
++	for (i = 0; audio_map[i][0] != NULL; i++)
++		snd_soc_dapm_connect_input(codec, audio_map[i][0],
++					   audio_map[i][1], audio_map[i][2]);
++
++	/* not connected */
++	snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0);
++	snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0);
++	snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0);
++
++	/* always connected */
++	snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
++	snd_soc_dapm_set_endpoint(codec, "Line Out", 1);
++	snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
++	snd_soc_dapm_set_endpoint(codec, "Line In", 1);
++
++	snd_soc_dapm_sync_endpoints(codec);
++
++	return 0;
++}
++
++/* davinci-evm digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link evm_dai = {
++	.name = "TLV320AIC3X",
++	.stream_name = "AIC3X",
++	.cpu_dai = &davinci_i2s_dai,
++	.codec_dai = &aic3x_dai,
++	.init = evm_aic3x_init,
++	.ops = &evm_ops,
++};
++
++/* davinci-evm audio machine driver */
++static struct snd_soc_machine snd_soc_machine_evm = {
++	.name = "DaVinci EVM",
++	.dai_link = &evm_dai,
++	.num_links = 1,
++};
++
++/* evm audio private data */
++static struct aic3x_setup_data evm_aic3x_setup = {
++	.i2c_address = 0x1b,
++};
++
++/* evm audio subsystem */
++static struct snd_soc_device evm_snd_devdata = {
++	.machine = &snd_soc_machine_evm,
++	.platform = &davinci_soc_platform,
++	.codec_dev = &soc_codec_dev_aic3x,
++	.codec_data = &evm_aic3x_setup,
++};
++
++static struct resource evm_snd_resources[] = {
++	{
++		.start = DAVINCI_MCBSP_BASE,
++		.end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
++		.flags = IORESOURCE_MEM,
++	},
++};
++
++static struct evm_snd_platform_data evm_snd_data = {
++	.tx_dma_ch	= DM644X_DMACH_MCBSP_TX,
++	.rx_dma_ch	= DM644X_DMACH_MCBSP_RX,
++};
++
++static struct platform_device *evm_snd_device;
++
++static int __init evm_init(void)
++{
++	int ret;
++
++	evm_snd_device = platform_device_alloc("soc-audio", 0);
++	if (!evm_snd_device)
++		return -ENOMEM;
++
++	platform_set_drvdata(evm_snd_device, &evm_snd_devdata);
++	evm_snd_devdata.dev = &evm_snd_device->dev;
++	evm_snd_device->dev.platform_data = &evm_snd_data;
++
++	ret = platform_device_add_resources(evm_snd_device, evm_snd_resources,
++					    ARRAY_SIZE(evm_snd_resources));
++	if (ret) {
++		platform_device_put(evm_snd_device);
++		return ret;
++	}
++
++	ret = platform_device_add(evm_snd_device);
++	if (ret)
++		platform_device_put(evm_snd_device);
++
++	return ret;
++}
++
++static void __exit evm_exit(void)
++{
++	platform_device_unregister(evm_snd_device);
++}
++
++module_init(evm_init);
++module_exit(evm_exit);
++
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
+new file mode 100644
+index 0000000..c421774
+--- /dev/null
++++ b/sound/soc/davinci/davinci-i2s.c
+@@ -0,0 +1,407 @@
++/*
++ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
++ *
++ * Author:      Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright:   (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++
++#include "davinci-pcm.h"
++
++#define DAVINCI_MCBSP_DRR_REG	0x00
++#define DAVINCI_MCBSP_DXR_REG	0x04
++#define DAVINCI_MCBSP_SPCR_REG	0x08
++#define DAVINCI_MCBSP_RCR_REG	0x0c
++#define DAVINCI_MCBSP_XCR_REG	0x10
++#define DAVINCI_MCBSP_SRGR_REG	0x14
++#define DAVINCI_MCBSP_PCR_REG	0x24
++
++#define DAVINCI_MCBSP_SPCR_RRST		(1 << 0)
++#define DAVINCI_MCBSP_SPCR_RINTM(v)	((v) << 4)
++#define DAVINCI_MCBSP_SPCR_XRST		(1 << 16)
++#define DAVINCI_MCBSP_SPCR_XINTM(v)	((v) << 20)
++#define DAVINCI_MCBSP_SPCR_GRST		(1 << 22)
++#define DAVINCI_MCBSP_SPCR_FRST		(1 << 23)
++#define DAVINCI_MCBSP_SPCR_FREE		(1 << 25)
++
++#define DAVINCI_MCBSP_RCR_RWDLEN1(v)	((v) << 5)
++#define DAVINCI_MCBSP_RCR_RFRLEN1(v)	((v) << 8)
++#define DAVINCI_MCBSP_RCR_RDATDLY(v)	((v) << 16)
++#define DAVINCI_MCBSP_RCR_RWDLEN2(v)	((v) << 21)
++
++#define DAVINCI_MCBSP_XCR_XWDLEN1(v)	((v) << 5)
++#define DAVINCI_MCBSP_XCR_XFRLEN1(v)	((v) << 8)
++#define DAVINCI_MCBSP_XCR_XDATDLY(v)	((v) << 16)
++#define DAVINCI_MCBSP_XCR_XFIG		(1 << 18)
++#define DAVINCI_MCBSP_XCR_XWDLEN2(v)	((v) << 21)
++
++#define DAVINCI_MCBSP_SRGR_FWID(v)	((v) << 8)
++#define DAVINCI_MCBSP_SRGR_FPER(v)	((v) << 16)
++#define DAVINCI_MCBSP_SRGR_FSGM		(1 << 28)
++
++#define DAVINCI_MCBSP_PCR_CLKRP		(1 << 0)
++#define DAVINCI_MCBSP_PCR_CLKXP		(1 << 1)
++#define DAVINCI_MCBSP_PCR_FSRP		(1 << 2)
++#define DAVINCI_MCBSP_PCR_FSXP		(1 << 3)
++#define DAVINCI_MCBSP_PCR_CLKRM		(1 << 8)
++#define DAVINCI_MCBSP_PCR_CLKXM		(1 << 9)
++#define DAVINCI_MCBSP_PCR_FSRM		(1 << 10)
++#define DAVINCI_MCBSP_PCR_FSXM		(1 << 11)
++
++#define MOD_REG_BIT(val, mask, set) do { \
++	if (set) { \
++		val |= mask; \
++	} else { \
++		val &= ~mask; \
++	} \
++} while (0)
++
++enum {
++	DAVINCI_MCBSP_WORD_8 = 0,
++	DAVINCI_MCBSP_WORD_12,
++	DAVINCI_MCBSP_WORD_16,
++	DAVINCI_MCBSP_WORD_20,
++	DAVINCI_MCBSP_WORD_24,
++	DAVINCI_MCBSP_WORD_32,
++};
++
++static struct davinci_pcm_dma_params davinci_i2s_pcm_out = {
++	.name = "I2S PCM Stereo out",
++};
++
++static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
++	.name = "I2S PCM Stereo in",
++};
++
++struct davinci_mcbsp_dev {
++	void __iomem			*base;
++	struct clk			*clk;
++	struct davinci_pcm_dma_params	*dma_params[2];
++};
++
++static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
++					   int reg, u32 val)
++{
++	__raw_writel(val, dev->base + reg);
++}
++
++static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
++{
++	return __raw_readl(dev->base + reg);
++}
++
++static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
++	u32 w;
++
++	/* Start the sample generator and enable transmitter/receiver */
++	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
++	MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
++	else
++		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
++
++	/* Start frame sync */
++	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
++	MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1);
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
++}
++
++static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
++	u32 w;
++
++	/* Reset transmitter/receiver and sample rate/frame sync generators */
++	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
++	MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST |
++		       DAVINCI_MCBSP_SPCR_FRST, 0);
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
++	else
++		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0);
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
++}
++
++static int davinci_i2s_startup(struct snd_pcm_substream *substream)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
++	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
++
++	cpu_dai->dma_data = dev->dma_params[substream->stream];
++
++	return 0;
++}
++
++static int davinci_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
++				   unsigned int fmt)
++{
++	struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
++	u32 w;
++
++	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++	case SND_SOC_DAIFMT_CBS_CFS:
++		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG,
++					DAVINCI_MCBSP_PCR_FSXM |
++					DAVINCI_MCBSP_PCR_FSRM |
++					DAVINCI_MCBSP_PCR_CLKXM |
++					DAVINCI_MCBSP_PCR_CLKRM);
++		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG,
++					DAVINCI_MCBSP_SRGR_FSGM);
++		break;
++	case SND_SOC_DAIFMT_CBM_CFM:
++		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 0);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
++	case SND_SOC_DAIFMT_IB_NF:
++		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
++		MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP |
++			       DAVINCI_MCBSP_PCR_CLKRP, 1);
++		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
++		break;
++	case SND_SOC_DAIFMT_NB_IF:
++		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
++		MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_FSXP |
++			       DAVINCI_MCBSP_PCR_FSRP, 1);
++		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
++		break;
++	case SND_SOC_DAIFMT_IB_IF:
++		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
++		MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP |
++			       DAVINCI_MCBSP_PCR_CLKRP |
++			       DAVINCI_MCBSP_PCR_FSXP |
++			       DAVINCI_MCBSP_PCR_FSRP, 1);
++		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
++		break;
++	case SND_SOC_DAIFMT_NB_NF:
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
++				 struct snd_pcm_hw_params *params)
++{
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
++	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
++	struct snd_interval *i = NULL;
++	int mcbsp_word_length;
++	u32 w;
++
++	/* general line settings */
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
++				DAVINCI_MCBSP_SPCR_RINTM(3) |
++				DAVINCI_MCBSP_SPCR_XINTM(3) |
++				DAVINCI_MCBSP_SPCR_FREE);
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
++				DAVINCI_MCBSP_RCR_RFRLEN1(1) |
++				DAVINCI_MCBSP_RCR_RDATDLY(1));
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
++				DAVINCI_MCBSP_XCR_XFRLEN1(1) |
++				DAVINCI_MCBSP_XCR_XDATDLY(1) |
++				DAVINCI_MCBSP_XCR_XFIG);
++
++	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
++	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
++	MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1);
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
++
++	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
++	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
++	MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1);
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
++
++	/* Determine xfer data type */
++	switch (params_format(params)) {
++	case SNDRV_PCM_FORMAT_S8:
++		dma_params->data_type = 1;
++		mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
++		break;
++	case SNDRV_PCM_FORMAT_S16_LE:
++		dma_params->data_type = 2;
++		mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
++		break;
++	case SNDRV_PCM_FORMAT_S32_LE:
++		dma_params->data_type = 4;
++		mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
++		break;
++	default:
++		printk(KERN_WARNING "davinci-i2s: unsupported PCM format");
++		return -EINVAL;
++	}
++
++	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
++	MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
++		       DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
++
++	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
++	MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
++		       DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
++	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
++
++	return 0;
++}
++
++static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++	case SNDRV_PCM_TRIGGER_RESUME:
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		davinci_mcbsp_start(substream);
++		break;
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		davinci_mcbsp_stop(substream);
++		break;
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static int davinci_i2s_probe(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_machine *machine = socdev->machine;
++	struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
++	struct davinci_mcbsp_dev *dev;
++	struct resource *mem, *ioarea;
++	struct evm_snd_platform_data *pdata;
++	int ret;
++
++	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!mem) {
++		dev_err(&pdev->dev, "no mem resource?\n");
++		return -ENODEV;
++	}
++
++	ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
++				    pdev->name);
++	if (!ioarea) {
++		dev_err(&pdev->dev, "McBSP region already claimed\n");
++		return -EBUSY;
++	}
++
++	dev = kzalloc(sizeof(struct davinci_mcbsp_dev), GFP_KERNEL);
++	if (!dev) {
++		ret = -ENOMEM;
++		goto err_release_region;
++	}
++
++	cpu_dai->private_data = dev;
++
++	dev->clk = clk_get(&pdev->dev, "McBSPCLK");
++	if (IS_ERR(dev->clk)) {
++		ret = -ENODEV;
++		goto err_free_mem;
++	}
++	clk_enable(dev->clk);
++
++	dev->base = (void __iomem *)IO_ADDRESS(mem->start);
++	pdata = pdev->dev.platform_data;
++
++	dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out;
++	dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch;
++	dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr =
++	    (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
++
++	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in;
++	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch;
++	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr =
++	    (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
++
++	return 0;
++
++err_free_mem:
++	kfree(dev);
++err_release_region:
++	release_mem_region(mem->start, (mem->end - mem->start) + 1);
++
++	return ret;
++}
++
++static void davinci_i2s_remove(struct platform_device *pdev)
++{
++	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++	struct snd_soc_machine *machine = socdev->machine;
++	struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
++	struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
++	struct resource *mem;
++
++	clk_disable(dev->clk);
++	clk_put(dev->clk);
++	dev->clk = NULL;
++
++	kfree(dev);
++
++	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	release_mem_region(mem->start, (mem->end - mem->start) + 1);
++}
++
++#define DAVINCI_I2S_RATES	SNDRV_PCM_RATE_8000_96000
++
++struct snd_soc_cpu_dai davinci_i2s_dai = {
++	.name = "davinci-i2s",
++	.id = 0,
++	.type = SND_SOC_DAI_I2S,
++	.probe = davinci_i2s_probe,
++	.remove = davinci_i2s_remove,
++	.playback = {
++		.channels_min = 2,
++		.channels_max = 2,
++		.rates = DAVINCI_I2S_RATES,
++		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
++	.capture = {
++		.channels_min = 2,
++		.channels_max = 2,
++		.rates = DAVINCI_I2S_RATES,
++		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
++	.ops = {
++		.startup = davinci_i2s_startup,
++		.trigger = davinci_i2s_trigger,
++		.hw_params = davinci_i2s_hw_params,},
++	.dai_ops = {
++		.set_fmt = davinci_i2s_set_dai_fmt,
++	},
++};
++EXPORT_SYMBOL_GPL(davinci_i2s_dai);
++
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
+new file mode 100644
+index 0000000..9592d17
+--- /dev/null
++++ b/sound/soc/davinci/davinci-i2s.h
+@@ -0,0 +1,17 @@
++/*
++ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
++ *
++ * Author:      Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright:   (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _DAVINCI_I2S_H
++#define _DAVINCI_I2S_H
++
++extern struct snd_soc_cpu_dai davinci_i2s_dai;
++
++#endif
+diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
+new file mode 100644
+index 0000000..6a76927
+--- /dev/null
++++ b/sound/soc/davinci/davinci-pcm.c
+@@ -0,0 +1,389 @@
++/*
++ * ALSA PCM interface for the TI DAVINCI processor
++ *
++ * Author:      Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright:   (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++
++#include <asm/dma.h>
++
++#include "davinci-pcm.h"
++
++#define DAVINCI_PCM_DEBUG 0
++#if DAVINCI_PCM_DEBUG
++#define DPRINTK(x...) printk(KERN_DEBUG x)
++#else
++#define DPRINTK(x...)
++#endif
++
++static struct snd_pcm_hardware davinci_pcm_hardware = {
++	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
++		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
++		 SNDRV_PCM_INFO_PAUSE),
++	.formats = (SNDRV_PCM_FMTBIT_S16_LE),
++	.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
++		  SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
++		  SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
++		  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
++		  SNDRV_PCM_RATE_KNOT),
++	.rate_min = 8000,
++	.rate_max = 96000,
++	.channels_min = 2,
++	.channels_max = 2,
++	.buffer_bytes_max = 128 * 1024,
++	.period_bytes_min = 32,
++	.period_bytes_max = 8 * 1024,
++	.periods_min = 16,
++	.periods_max = 255,
++	.fifo_size = 0,
++};
++
++struct davinci_runtime_data {
++	spinlock_t lock;
++	int period;		/* current DMA period */
++	int master_lch;		/* Master DMA channel */
++	int slave_lch;		/* Slave DMA channel */
++	struct davinci_pcm_dma_params *params;	/* DMA params */
++};
++
++static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
++{
++	struct davinci_runtime_data *prtd = substream->runtime->private_data;
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	int lch = prtd->slave_lch;
++	unsigned int period_size;
++	unsigned int dma_offset;
++	dma_addr_t dma_pos;
++	dma_addr_t src, dst;
++	unsigned short src_bidx, dst_bidx;
++	unsigned int data_type;
++	unsigned int count;
++
++	period_size = snd_pcm_lib_period_bytes(substream);
++	dma_offset = prtd->period * period_size;
++	dma_pos = runtime->dma_addr + dma_offset;
++
++	DPRINTK("audio_set_dma_params_play channel = %d dma_ptr = %x "
++		"period_size=%x\n", lch, dma_pos, period_size);
++
++	data_type = prtd->params->data_type;
++	count = period_size / data_type;
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++		src = dma_pos;
++		dst = prtd->params->dma_addr;
++		src_bidx = data_type;
++		dst_bidx = 0;
++	} else {
++		src = prtd->params->dma_addr;
++		dst = dma_pos;
++		src_bidx = 0;
++		dst_bidx = data_type;
++	}
++
++	davinci_set_dma_src_params(lch, src, INCR, W8BIT);
++	davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
++	davinci_set_dma_src_index(lch, src_bidx, 0);
++	davinci_set_dma_dest_index(lch, dst_bidx, 0);
++	davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
++
++	prtd->period++;
++	if (unlikely(prtd->period >= runtime->periods))
++		prtd->period = 0;
++}
++
++static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
++{
++	struct snd_pcm_substream *substream = data;
++	struct davinci_runtime_data *prtd = substream->runtime->private_data;
++
++	DPRINTK("lch=%d, status=0x%x\n", lch, ch_status);
++
++	if (unlikely(ch_status != DMA_COMPLETE))
++		return;
++
++	if (snd_pcm_running(substream)) {
++		snd_pcm_period_elapsed(substream);
++
++		spin_lock(&prtd->lock);
++		davinci_pcm_enqueue_dma(substream);
++		spin_unlock(&prtd->lock);
++	}
++}
++
++static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
++{
++	struct davinci_runtime_data *prtd = substream->runtime->private_data;
++	struct snd_soc_pcm_runtime *rtd = substream->private_data;
++	struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
++	int tcc = TCC_ANY;
++	int ret;
++
++	if (!dma_data)
++		return -ENODEV;
++
++	prtd->params = dma_data;
++
++	/* Request master DMA channel */
++	ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
++				  davinci_pcm_dma_irq, substream,
++				  &prtd->master_lch, &tcc, EVENTQ_0);
++	if (ret)
++		return ret;
++
++	/* Request slave DMA channel */
++	ret = davinci_request_dma(PARAM_ANY, "Link",
++				  NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
++	if (ret) {
++		davinci_free_dma(prtd->master_lch);
++		return ret;
++	}
++
++	/* Link slave DMA channel in loopback */
++	davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
++
++	return 0;
++}
++
++static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct davinci_runtime_data *prtd = substream->runtime->private_data;
++	int ret = 0;
++
++	spin_lock(&prtd->lock);
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++	case SNDRV_PCM_TRIGGER_RESUME:
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		davinci_start_dma(prtd->master_lch);
++		break;
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		davinci_stop_dma(prtd->master_lch);
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	spin_unlock(&prtd->lock);
++
++	return ret;
++}
++
++static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
++{
++	struct davinci_runtime_data *prtd = substream->runtime->private_data;
++	struct paramentry_descriptor temp;
++
++	prtd->period = 0;
++	davinci_pcm_enqueue_dma(substream);
++
++	/* Get slave channel dma params for master channel startup */
++	davinci_get_dma_params(prtd->slave_lch, &temp);
++	davinci_set_dma_params(prtd->master_lch, &temp);
++
++	return 0;
++}
++
++static snd_pcm_uframes_t
++davinci_pcm_pointer(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct davinci_runtime_data *prtd = runtime->private_data;
++	unsigned int offset;
++	dma_addr_t count;
++	dma_addr_t src, dst;
++
++	spin_lock(&prtd->lock);
++
++	davinci_dma_getposition(prtd->master_lch, &src, &dst);
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		count = src - runtime->dma_addr;
++	else
++		count = dst - runtime->dma_addr;;
++
++	spin_unlock(&prtd->lock);
++
++	offset = bytes_to_frames(runtime, count);
++	if (offset >= runtime->buffer_size)
++		offset = 0;
++
++	return offset;
++}
++
++static int davinci_pcm_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct davinci_runtime_data *prtd;
++	int ret = 0;
++
++	snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);
++
++	prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
++	if (prtd == NULL)
++		return -ENOMEM;
++
++	spin_lock_init(&prtd->lock);
++
++	runtime->private_data = prtd;
++
++	ret = davinci_pcm_dma_request(substream);
++	if (ret) {
++		printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n");
++		kfree(prtd);
++	}
++
++	return ret;
++}
++
++static int davinci_pcm_close(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct davinci_runtime_data *prtd = runtime->private_data;
++
++	davinci_dma_unlink_lch(prtd->slave_lch, prtd->slave_lch);
++
++	davinci_free_dma(prtd->slave_lch);
++	davinci_free_dma(prtd->master_lch);
++
++	kfree(prtd);
++
++	return 0;
++}
++
++static int davinci_pcm_hw_params(struct snd_pcm_substream *substream,
++				 struct snd_pcm_hw_params *hw_params)
++{
++	return snd_pcm_lib_malloc_pages(substream,
++					params_buffer_bytes(hw_params));
++}
++
++static int davinci_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++	return snd_pcm_lib_free_pages(substream);
++}
++
++static int davinci_pcm_mmap(struct snd_pcm_substream *substream,
++			    struct vm_area_struct *vma)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++
++	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
++				     runtime->dma_area,
++				     runtime->dma_addr,
++				     runtime->dma_bytes);
++}
++
++struct snd_pcm_ops davinci_pcm_ops = {
++	.open = 	davinci_pcm_open,
++	.close = 	davinci_pcm_close,
++	.ioctl = 	snd_pcm_lib_ioctl,
++	.hw_params = 	davinci_pcm_hw_params,
++	.hw_free = 	davinci_pcm_hw_free,
++	.prepare = 	davinci_pcm_prepare,
++	.trigger = 	davinci_pcm_trigger,
++	.pointer = 	davinci_pcm_pointer,
++	.mmap = 	davinci_pcm_mmap,
++};
++
++static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
++{
++	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
++	struct snd_dma_buffer *buf = &substream->dma_buffer;
++	size_t size = davinci_pcm_hardware.buffer_bytes_max;
++
++	buf->dev.type = SNDRV_DMA_TYPE_DEV;
++	buf->dev.dev = pcm->card->dev;
++	buf->private_data = NULL;
++	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
++					   &buf->addr, GFP_KERNEL);
++
++	DPRINTK("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
++		(void *) buf->area, (void *) buf->addr, size);
++
++	if (!buf->area)
++		return -ENOMEM;
++
++	buf->bytes = size;
++	return 0;
++}
++
++static void davinci_pcm_free(struct snd_pcm *pcm)
++{
++	struct snd_pcm_substream *substream;
++	struct snd_dma_buffer *buf;
++	int stream;
++
++	for (stream = 0; stream < 2; stream++) {
++		substream = pcm->streams[stream].substream;
++		if (!substream)
++			continue;
++
++		buf = &substream->dma_buffer;
++		if (!buf->area)
++			continue;
++
++		dma_free_writecombine(pcm->card->dev, buf->bytes,
++				      buf->area, buf->addr);
++		buf->area = NULL;
++	}
++}
++
++static u64 davinci_pcm_dmamask = 0xffffffff;
++
++static int davinci_pcm_new(struct snd_card *card,
++			   struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
++{
++	int ret;
++
++	if (!card->dev->dma_mask)
++		card->dev->dma_mask = &davinci_pcm_dmamask;
++	if (!card->dev->coherent_dma_mask)
++		card->dev->coherent_dma_mask = 0xffffffff;
++
++	if (dai->playback.channels_min) {
++		ret = davinci_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_PLAYBACK);
++		if (ret)
++			return ret;
++	}
++
++	if (dai->capture.channels_min) {
++		ret = davinci_pcm_preallocate_dma_buffer(pcm,
++			SNDRV_PCM_STREAM_CAPTURE);
++		if (ret)
++			return ret;
++	}
++
++	return 0;
++}
++
++struct snd_soc_platform davinci_soc_platform = {
++	.name = 	"davinci-audio",
++	.pcm_ops = 	&davinci_pcm_ops,
++	.pcm_new = 	davinci_pcm_new,
++	.pcm_free = 	davinci_pcm_free,
++};
++EXPORT_SYMBOL_GPL(davinci_soc_platform);
++
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
+new file mode 100644
+index 0000000..8d6a45e
+--- /dev/null
++++ b/sound/soc/davinci/davinci-pcm.h
+@@ -0,0 +1,29 @@
++/*
++ * ALSA PCM interface for the TI DAVINCI processor
++ *
++ * Author:      Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright:   (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _DAVINCI_PCM_H
++#define _DAVINCI_PCM_H
++
++struct davinci_pcm_dma_params {
++	char *name;		/* stream identifier */
++	int channel;		/* sync dma channel ID */
++	dma_addr_t dma_addr;	/* device physical address for DMA */
++	unsigned int data_type;	/* xfer data type */
++};
++
++struct evm_snd_platform_data {
++	int tx_dma_ch;
++	int rx_dma_ch;
++};
++
++extern struct snd_soc_platform davinci_soc_platform;
++
++#endif
+diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
+index 652514f..78de716 100644
+--- a/sound/soc/fsl/fsl_dma.c
++++ b/sound/soc/fsl/fsl_dma.c
+@@ -20,7 +20,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+ 
+-#include <sound/driver.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
+index 145ad13..b2a11b0 100644
+--- a/sound/soc/fsl/fsl_ssi.c
++++ b/sound/soc/fsl/fsl_ssi.c
+@@ -15,7 +15,6 @@
+ #include <linux/device.h>
+ #include <linux/delay.h>
+ 
+-#include <sound/driver.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
+index 1a70a6a..7f32a11 100644
+--- a/sound/soc/pxa/corgi.c
++++ b/sound/soc/pxa/corgi.c
+@@ -297,21 +297,19 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
+ 	/* Add corgi specific controls */
+ 	for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
+ 		err = snd_ctl_add(codec->card,
+-			snd_soc_cnew(&wm8731_corgi_controls[i],codec, NULL));
++			snd_soc_cnew(&wm8731_corgi_controls[i], codec, NULL));
+ 		if (err < 0)
+ 			return err;
+ 	}
+ 
+ 	/* Add corgi specific widgets */
+-	for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
++	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
+ 		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+-	}
+ 
+ 	/* Set up corgi specific audio path audio_map */
+-	for(i = 0; audio_map[i][0] != NULL; i++) {
++	for (i = 0; audio_map[i][0] != NULL; i++)
+ 		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ 			audio_map[i][1], audio_map[i][2]);
+-	}
+ 
+ 	snd_soc_dapm_sync_endpoints(codec);
+ 	return 0;
+@@ -353,7 +351,8 @@ static int __init corgi_init(void)
+ {
+ 	int ret;
+ 
+-	if (!(machine_is_corgi() || machine_is_shepherd() || machine_is_husky()))
++	if (!(machine_is_corgi() || machine_is_shepherd() ||
++	      machine_is_husky()))
+ 		return -ENODEV;
+ 
+ 	corgi_snd_device = platform_device_alloc("soc-audio", -1);
+diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
+index 4fbf8bb..7e830b2 100644
+--- a/sound/soc/pxa/poodle.c
++++ b/sound/soc/pxa/poodle.c
+@@ -257,21 +257,19 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
+ 	/* Add poodle specific controls */
+ 	for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
+ 		err = snd_ctl_add(codec->card,
+-			snd_soc_cnew(&wm8731_poodle_controls[i],codec, NULL));
++			snd_soc_cnew(&wm8731_poodle_controls[i], codec, NULL));
+ 		if (err < 0)
+ 			return err;
+ 	}
+ 
+ 	/* Add poodle specific widgets */
+-	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
++	for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
+ 		snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+-	}
+ 
+ 	/* Set up poodle specific audio path audio_map */
+-	for (i = 0; audio_map[i][0] != NULL; i++) {
++	for (i = 0; audio_map[i][0] != NULL; i++)
+ 		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ 			audio_map[i][1], audio_map[i][2]);
+-	}
+ 
+ 	snd_soc_dapm_sync_endpoints(codec);
+ 	return 0;
+diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
+index 815c153..97ec2d9 100644
+--- a/sound/soc/pxa/pxa2xx-ac97.c
++++ b/sound/soc/pxa/pxa2xx-ac97.c
+@@ -15,6 +15,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+ #include <linux/wait.h>
++#include <linux/clk.h>
+ #include <linux/delay.h>
+ 
+ #include <sound/core.h>
+@@ -27,6 +28,7 @@
+ #include <linux/mutex.h>
+ #include <asm/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/audio.h>
+ 
+ #include "pxa2xx-pcm.h"
+@@ -35,6 +37,10 @@
+ static DEFINE_MUTEX(car_mutex);
+ static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
+ static volatile long gsr_bits;
++static struct clk *ac97_clk;
++#ifdef CONFIG_PXA27x
++static struct clk *ac97conf_clk;
++#endif
+ 
+ /*
+  * Beware PXA27x bugs:
+@@ -55,7 +61,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
+ 	mutex_lock(&car_mutex);
+ 
+ 	/* set up primary or secondary codec/modem space */
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ 	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+ #else
+ 	if (reg == AC97_GPIO_STATUS)
+@@ -81,7 +87,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
+ 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
+ 	if (!((GSR | gsr_bits) & GSR_SDONE)) {
+ 		printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
+-				__FUNCTION__, reg, GSR | gsr_bits);
++				__func__, reg, GSR | gsr_bits);
+ 		val = -1;
+ 		goto out;
+ 	}
+@@ -105,7 +111,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ 	mutex_lock(&car_mutex);
+ 
+ 	/* set up primary or secondary codec/modem space */
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ 	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+ #else
+ 	if (reg == AC97_GPIO_STATUS)
+@@ -121,13 +127,16 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
+ 	if (!((GSR | gsr_bits) & GSR_CDONE))
+ 		printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
+-				__FUNCTION__, reg, GSR | gsr_bits);
++				__func__, reg, GSR | gsr_bits);
+ 
+ 	mutex_unlock(&car_mutex);
+ }
+ 
+ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+ {
++#ifdef CONFIG_PXA3xx
++	int timeout = 100;
++#endif
+ 	gsr_bits = 0;
+ 
+ #ifdef CONFIG_PXA27x
+@@ -138,6 +147,11 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+ 	GCR |= GCR_WARM_RST;
+ 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+ 	udelay(500);
++#elif defined(CONFIG_PXA3xx)
++	/* Can't use interrupts */
++	GCR |= GCR_WARM_RST;
++	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
++		mdelay(1);
+ #else
+ 	GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
+ 	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
+@@ -145,7 +159,7 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+ 
+ 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
+ 		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
+-				 __FUNCTION__, gsr_bits);
++				 __func__, gsr_bits);
+ 
+ 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+ 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
+@@ -153,17 +167,34 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+ 
+ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
+ {
++#ifdef CONFIG_PXA3xx
++	int timeout = 1000;
++
++	/* Hold CLKBPB for 100us */
++	GCR = 0;
++	GCR = GCR_CLKBPB;
++	udelay(100);
++	GCR = 0;
++#endif
++
+ 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
+ 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
+ 
+ 	gsr_bits = 0;
+ #ifdef CONFIG_PXA27x
+ 	/* PXA27x Developers Manual section 13.5.2.2.1 */
+-	pxa_set_cken(CKEN_AC97CONF, 1);
++	clk_enable(ac97conf_clk);
+ 	udelay(5);
+-	pxa_set_cken(CKEN_AC97CONF, 0);
++	clk_disable(ac97conf_clk);
+ 	GCR = GCR_COLD_RST;
+ 	udelay(50);
++#elif defined(CONFIG_PXA3xx)
++	/* Can't use interrupts on PXA3xx */
++	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
++
++	GCR = GCR_WARM_RST | GCR_COLD_RST;
++	while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
++		mdelay(10);
+ #else
+ 	GCR = GCR_COLD_RST;
+ 	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
+@@ -172,7 +203,7 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
+ 
+ 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
+ 		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
+-				 __FUNCTION__, gsr_bits);
++				 __func__, gsr_bits);
+ 
+ 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+ 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
+@@ -255,7 +286,7 @@ static int pxa2xx_ac97_suspend(struct platform_device *pdev,
+ 	struct snd_soc_cpu_dai *dai)
+ {
+ 	GCR |= GCR_ACLINK_OFF;
+-	pxa_set_cken(CKEN_AC97, 0);
++	clk_disable(ac97_clk);
+ 	return 0;
+ }
+ 
+@@ -270,7 +301,7 @@ static int pxa2xx_ac97_resume(struct platform_device *pdev,
+ 	/* Use GPIO 113 as AC97 Reset on Bulverde */
+ 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+ #endif
+-	pxa_set_cken(CKEN_AC97, 1);
++	clk_enable(ac97_clk);
+ 	return 0;
+ }
+ 
+@@ -294,16 +325,33 @@ static int pxa2xx_ac97_probe(struct platform_device *pdev)
+ #ifdef CONFIG_PXA27x
+ 	/* Use GPIO 113 as AC97 Reset on Bulverde */
+ 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
++
++	ac97conf_clk = clk_get(&pdev->dev, "AC97CONFCLK");
++	if (IS_ERR(ac97conf_clk)) {
++		ret = PTR_ERR(ac97conf_clk);
++		ac97conf_clk = NULL;
++		goto err_irq;
++	}
+ #endif
+-	pxa_set_cken(CKEN_AC97, 1);
++	ac97_clk = clk_get(&pdev->dev, "AC97CLK");
++	if (IS_ERR(ac97_clk)) {
++		ret = PTR_ERR(ac97_clk);
++		ac97_clk = NULL;
++		goto err_irq;
++	}
++	clk_enable(ac97_clk);
+ 	return 0;
+ 
+- err:
+-	if (CKEN & (1 << CKEN_AC97)) {
+-		GCR |= GCR_ACLINK_OFF;
+-		free_irq(IRQ_AC97, NULL);
+-		pxa_set_cken(CKEN_AC97, 0);
++ err_irq:
++	GCR |= GCR_ACLINK_OFF;
++#ifdef CONFIG_PXA27x
++	if (ac97conf_clk) {
++		clk_put(ac97conf_clk);
++		ac97conf_clk = NULL;
+ 	}
++#endif
++	free_irq(IRQ_AC97, NULL);
++ err:
+ 	return ret;
+ }
+ 
+@@ -311,7 +359,13 @@ static void pxa2xx_ac97_remove(struct platform_device *pdev)
+ {
+ 	GCR |= GCR_ACLINK_OFF;
+ 	free_irq(IRQ_AC97, NULL);
+-	pxa_set_cken(CKEN_AC97, 0);
++#ifdef CONFIG_PXA27x
++	clk_put(ac97conf_clk);
++	ac97conf_clk = NULL;
++#endif
++	clk_disable(ac97_clk);
++	clk_put(ac97_clk);
++	ac97_clk = NULL;
+ }
+ 
+ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
+diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
+index 692b900..4250710 100644
+--- a/sound/soc/pxa/pxa2xx-i2s.c
++++ b/sound/soc/pxa/pxa2xx-i2s.c
+@@ -25,6 +25,7 @@
+ 
+ #include <asm/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/audio.h>
+ 
+ #include "pxa2xx-pcm.h"
+diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
+index daeaa4c..01ad7bf 100644
+--- a/sound/soc/pxa/pxa2xx-pcm.c
++++ b/sound/soc/pxa/pxa2xx-pcm.c
+@@ -64,8 +64,8 @@ static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
+ 	if (dcsr & DCSR_ENDINTR) {
+ 		snd_pcm_period_elapsed(substream);
+ 	} else {
+-		printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
+-			prtd->params->name, dma_ch, dcsr );
++		printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
++			prtd->params->name, dma_ch, dcsr);
+ 	}
+ }
+ 
+@@ -84,8 +84,8 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
+ 
+ 	/* return if this is a bufferless transfer e.g.
+ 	 * codec <--> BT codec or GSM modem -- lg FIXME */
+-	 if (!dma)
+-	 	return 0;
++	if (!dma)
++		return 0;
+ 
+ 	/* this may get called several times by oss emulation
+ 	 * with different params */
+@@ -363,7 +363,6 @@ struct snd_soc_platform pxa2xx_soc_platform = {
+ 	.pcm_new	= pxa2xx_pcm_new,
+ 	.pcm_free	= pxa2xx_pcm_free_dma_buffers,
+ };
+-
+ EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
+ 
+ MODULE_AUTHOR("Nicolas Pitre");
+diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
+index ecca390..d8b8372 100644
+--- a/sound/soc/pxa/spitz.c
++++ b/sound/soc/pxa/spitz.c
+@@ -313,15 +313,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
+ 	}
+ 
+ 	/* Add spitz specific widgets */
+-	for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
++	for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
+ 		snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
+-	}
+ 
+ 	/* Set up spitz specific audio path audio_map */
+-	for (i = 0; audio_map[i][0] != NULL; i++) {
++	for (i = 0; audio_map[i][0] != NULL; i++)
+ 		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ 			audio_map[i][1], audio_map[i][2]);
+-	}
+ 
+ 	snd_soc_dapm_sync_endpoints(codec);
+ 	return 0;
+diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
+index 6ee115c..962cc20 100644
+--- a/sound/soc/s3c24xx/neo1973_wm8753.c
++++ b/sound/soc/s3c24xx/neo1973_wm8753.c
+@@ -659,6 +659,7 @@ static int __init neo1973_init(void)
+ 
+ static void __exit neo1973_exit(void)
+ {
++	i2c_del_driver(&lm4857_i2c_driver);
+ 	platform_device_unregister(neo1973_snd_device);
+ }
+ 
+diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
+index 0a3c630..4ebcd6a 100644
+--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
++++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
+@@ -25,6 +25,7 @@
+ #include <linux/delay.h>
+ #include <linux/clk.h>
+ #include <linux/jiffies.h>
++#include <linux/io.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+@@ -32,7 +33,6 @@
+ #include <sound/soc.h>
+ 
+ #include <asm/hardware.h>
+-#include <asm/io.h>
+ #include <asm/arch/regs-gpio.h>
+ #include <asm/arch/regs-clock.h>
+ #include <asm/arch/audio.h>
+@@ -46,7 +46,7 @@
+ 
+ #define S3C24XX_I2S_DEBUG 0
+ #if S3C24XX_I2S_DEBUG
+-#define DBG(x...) printk(KERN_DEBUG x)
++#define DBG(x...) printk(KERN_DEBUG "s3c24xx-i2s: " x)
+ #else
+ #define DBG(x...)
+ #endif
+@@ -89,7 +89,7 @@ static void s3c24xx_snd_txctrl(int on)
+ 	u32 iiscon;
+ 	u32 iismod;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
+ 	iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+@@ -134,7 +134,7 @@ static void s3c24xx_snd_rxctrl(int on)
+ 	u32 iiscon;
+ 	u32 iismod;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
+ 	iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+@@ -159,10 +159,10 @@ static void s3c24xx_snd_rxctrl(int on)
+ 		 * DMA engine will simply freeze randomly.
+ 		 */
+ 
+-        iisfcon &= ~S3C2410_IISFCON_RXENABLE;
+-        iisfcon &= ~S3C2410_IISFCON_RXDMA;
+-        iiscon  |= S3C2410_IISCON_RXIDLE;
+-        iiscon  &= ~S3C2410_IISCON_RXDMAEN;
++		iisfcon &= ~S3C2410_IISFCON_RXENABLE;
++		iisfcon &= ~S3C2410_IISFCON_RXDMA;
++		iiscon  |= S3C2410_IISCON_RXIDLE;
++		iiscon  &= ~S3C2410_IISCON_RXDMAEN;
+ 		iismod  &= ~S3C2410_IISMOD_RXMODE;
+ 
+ 		writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
+@@ -182,7 +182,7 @@ static int s3c24xx_snd_lrsync(void)
+ 	u32 iiscon;
+ 	unsigned long timeout = jiffies + msecs_to_jiffies(5);
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	while (1) {
+ 		iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+@@ -201,7 +201,7 @@ static int s3c24xx_snd_lrsync(void)
+  */
+ static inline int s3c24xx_snd_is_clkmaster(void)
+ {
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1;
+ }
+@@ -214,7 +214,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai,
+ {
+ 	u32 iismod;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+ 	DBG("hw_params r: IISMOD: %lx \n", iismod);
+@@ -250,7 +250,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
+ 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ 	u32 iismod;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ 		rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out;
+@@ -278,7 +278,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+ {
+ 	int ret = 0;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	switch (cmd) {
+ 	case SNDRV_PCM_TRIGGER_START:
+@@ -320,7 +320,7 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+ {
+ 	u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	iismod &= ~S3C2440_IISMOD_MPLL;
+ 
+@@ -346,7 +346,7 @@ static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+ {
+ 	u32 reg;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	switch (div_id) {
+ 	case S3C24XX_DIV_BCLK:
+@@ -381,13 +381,13 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
+ 
+ static int s3c24xx_i2s_probe(struct platform_device *pdev)
+ {
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
+ 	if (s3c24xx_i2s.regs == NULL)
+ 		return -ENXIO;
+ 
+-	s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis");
++	s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis");
+ 	if (s3c24xx_i2s.iis_clk == NULL) {
+ 		DBG("failed to get iis_clock\n");
+ 		iounmap(s3c24xx_i2s.regs);
+@@ -411,9 +411,11 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
+ }
+ 
+ #ifdef CONFIG_PM
+-int s3c24xx_i2s_suspend(struct platform_device *pdev,
++static int s3c24xx_i2s_suspend(struct platform_device *pdev,
+ 		struct snd_soc_cpu_dai *cpu_dai)
+ {
++	DBG("Entered %s\n", __func__);
++
+ 	s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+ 	s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+ 	s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
+@@ -424,9 +426,10 @@ int s3c24xx_i2s_suspend(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-int s3c24xx_i2s_resume(struct platform_device *pdev,
++static int s3c24xx_i2s_resume(struct platform_device *pdev,
+ 		struct snd_soc_cpu_dai *cpu_dai)
+ {
++	DBG("Entered %s\n", __func__);
+ 	clk_enable(s3c24xx_i2s.iis_clk);
+ 
+ 	writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
+diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
+index 29a6c82..49580fb 100644
+--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
++++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
+@@ -39,7 +39,7 @@
+ 
+ #define S3C24XX_PCM_DEBUG 0
+ #if S3C24XX_PCM_DEBUG
+-#define DBG(x...) printk(KERN_DEBUG x)
++#define DBG(x...) printk(KERN_DEBUG "s3c24xx-pcm: " x)
+ #else
+ #define DBG(x...)
+ #endif
+@@ -88,7 +88,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
+ 	dma_addr_t pos = prtd->dma_pos;
+ 	int ret;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	while (prtd->dma_loaded < prtd->dma_limit) {
+ 		unsigned long len = prtd->dma_period;
+@@ -98,7 +98,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
+ 		if ((pos + len) > prtd->dma_end) {
+ 			len  = prtd->dma_end - pos;
+ 			DBG(KERN_DEBUG "%s: corrected dma len %ld\n",
+-			       __FUNCTION__, len);
++			       __func__, len);
+ 		}
+ 
+ 		ret = s3c2410_dma_enqueue(prtd->params->channel, 
+@@ -123,7 +123,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
+ 	struct snd_pcm_substream *substream = dev_id;
+ 	struct s3c24xx_runtime_data *prtd;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
+ 		return;
+@@ -152,7 +152,7 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
+ 	unsigned long totbytes = params_buffer_bytes(params);
+ 	int ret=0;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	/* return if this is a bufferless transfer e.g.
+ 	 * codec <--> BT codec or GSM modem -- lg FIXME */
+@@ -200,7 +200,7 @@ static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream)
+ {
+ 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	/* TODO - do we need to ensure DMA flushed */
+ 	snd_pcm_set_runtime_buffer(substream, NULL);
+@@ -218,7 +218,7 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
+ 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+ 	int ret = 0;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	/* return if this is a bufferless transfer e.g.
+ 	 * codec <--> BT codec or GSM modem -- lg FIXME */
+@@ -263,7 +263,7 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ 	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+ 	int ret = 0;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	spin_lock(&prtd->lock);
+ 
+@@ -301,7 +301,7 @@ static snd_pcm_uframes_t
+ 	unsigned long res;
+ 	dma_addr_t src, dst;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	spin_lock(&prtd->lock);
+ 	s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
+@@ -334,7 +334,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
+ 	struct s3c24xx_runtime_data *prtd;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
+ 
+@@ -353,7 +353,7 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
+ 	struct s3c24xx_runtime_data *prtd = runtime->private_data;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	if (prtd)
+ 		kfree(prtd);
+@@ -368,7 +368,7 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream,
+ {
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+                                      runtime->dma_area,
+@@ -394,7 +394,7 @@ static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+ 	struct snd_dma_buffer *buf = &substream->dma_buffer;
+ 	size_t size = s3c24xx_pcm_hardware.buffer_bytes_max;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ 	buf->dev.dev = pcm->card->dev;
+@@ -413,7 +413,7 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
+ 	struct snd_dma_buffer *buf;
+ 	int stream;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	for (stream = 0; stream < 2; stream++) {
+ 		substream = pcm->streams[stream].substream;
+@@ -437,7 +437,7 @@ static int s3c24xx_pcm_new(struct snd_card *card,
+ {
+ 	int ret = 0;
+ 
+-	DBG("Entered %s\n", __FUNCTION__);
++	DBG("Entered %s\n", __func__);
+ 
+ 	if (!card->dev->dma_mask)
+ 		card->dev->dma_mask = &s3c24xx_pcm_dmamask;
+diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
+index f03220d..4c1e013 100644
+--- a/sound/soc/sh/Kconfig
++++ b/sound/soc/sh/Kconfig
+@@ -1,4 +1,5 @@
+ menu "SoC Audio support for SuperH"
++	depends on SUPERH
+ 
+ config SND_SOC_PCM_SH7760
+ 	tristate "SoC Audio support for Renesas SH7760"
+diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
+index 9eb5479..e148db9 100644
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -839,6 +839,7 @@ static int soc_remove(struct platform_device *pdev)
+ static struct platform_driver soc_driver = {
+ 	.driver		= {
+ 		.name		= "soc-audio",
++		.owner		= THIS_MODULE,
+ 	},
+ 	.probe		= soc_probe,
+ 	.remove		= soc_remove,
+@@ -1601,3 +1602,4 @@ module_exit(snd_soc_exit);
+ MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
+ MODULE_DESCRIPTION("ALSA SoC Core");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:soc-audio");
+diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
+index 620d7ea..af3326c 100644
+--- a/sound/soc/soc-dapm.c
++++ b/sound/soc/soc-dapm.c
+@@ -226,7 +226,7 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
+ 		snd_soc_write(codec, widget->reg, new);
+ 		pop_wait(POP_TIME);
+ 	}
+-	dbg("reg old %x new %x change %d\n", old, new, change);
++	dbg("reg %x old %x new %x change %d\n", widget->reg, old, new, change);
+ 	return change;
+ }
+ 
+@@ -1288,7 +1288,7 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
+ 	mutex_unlock(&codec->mutex);
+ 
+ 	dapm_power_widgets(codec, event);
+-	dump_dapm(codec, __FUNCTION__);
++	dump_dapm(codec, __func__);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
+@@ -1334,10 +1334,11 @@ int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
+ 	list_for_each_entry(w, &codec->dapm_widgets, list) {
+ 		if (!strcmp(w->name, endpoint)) {
+ 			w->connected = status;
++			return 0;
+ 		}
+ 	}
+ 
+-	return 0;
++	return -ENODEV;
+ }
+ EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
+ 
+diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
+index 89d6e9c..09802e8 100644
+--- a/sound/spi/at73c213.c
++++ b/sound/spi/at73c213.c
+@@ -118,7 +118,7 @@ static struct snd_pcm_hardware snd_at73c213_playback_hw = {
+ 	.rates		= SNDRV_PCM_RATE_CONTINUOUS,
+ 	.rate_min	= 8000,  /* Replaced by chip->bitrate later. */
+ 	.rate_max	= 50000, /* Replaced by chip->bitrate later. */
+-	.channels_min	= 2,
++	.channels_min	= 1,
+ 	.channels_max	= 2,
+ 	.buffer_bytes_max = 64 * 1024 - 1,
+ 	.period_bytes_min = 512,
+@@ -133,7 +133,8 @@ static struct snd_pcm_hardware snd_at73c213_playback_hw = {
+ static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip)
+ {
+ 	unsigned long ssc_rate = clk_get_rate(chip->ssc->clk);
+-	unsigned long dac_rate_new, ssc_div, status;
++	unsigned long dac_rate_new, ssc_div;
++	int status;
+ 	unsigned long ssc_div_max, ssc_div_min;
+ 	int max_tries;
+ 
+@@ -209,7 +210,13 @@ static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream)
+ {
+ 	struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
++	int err;
+ 
++	/* ensure buffer_size is a multiple of period_size */
++	err = snd_pcm_hw_constraint_integer(runtime,
++					SNDRV_PCM_HW_PARAM_PERIODS);
++	if (err < 0)
++		return err;
+ 	snd_at73c213_playback_hw.rate_min = chip->bitrate;
+ 	snd_at73c213_playback_hw.rate_max = chip->bitrate;
+ 	runtime->hw = snd_at73c213_playback_hw;
+@@ -228,6 +235,14 @@ static int snd_at73c213_pcm_close(struct snd_pcm_substream *substream)
+ static int snd_at73c213_pcm_hw_params(struct snd_pcm_substream *substream,
+ 				 struct snd_pcm_hw_params *hw_params)
+ {
++	struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
++	int channels = params_channels(hw_params);
++	int val;
++
++	val = ssc_readl(chip->ssc->regs, TFMR);
++	val = SSC_BFINS(TFMR_DATNB, channels - 1, val);
++	ssc_writel(chip->ssc->regs, TFMR, val);
++
+ 	return snd_pcm_lib_malloc_pages(substream,
+ 					params_buffer_bytes(hw_params));
+ }
+@@ -249,10 +264,12 @@ static int snd_at73c213_pcm_prepare(struct snd_pcm_substream *substream)
+ 
+ 	ssc_writel(chip->ssc->regs, PDC_TPR,
+ 			(long)runtime->dma_addr);
+-	ssc_writel(chip->ssc->regs, PDC_TCR, runtime->period_size * 2);
++	ssc_writel(chip->ssc->regs, PDC_TCR,
++			runtime->period_size * runtime->channels);
+ 	ssc_writel(chip->ssc->regs, PDC_TNPR,
+ 			(long)runtime->dma_addr + block_size);
+-	ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
++	ssc_writel(chip->ssc->regs, PDC_TNCR,
++			runtime->period_size * runtime->channels);
+ 
+ 	return 0;
+ }
+@@ -314,15 +331,6 @@ static struct snd_pcm_ops at73c213_playback_ops = {
+ 	.pointer	= snd_at73c213_pcm_pointer,
+ };
+ 
+-static void snd_at73c213_pcm_free(struct snd_pcm *pcm)
+-{
+-	struct snd_at73c213 *chip = snd_pcm_chip(pcm);
+-	if (chip->pcm) {
+-		snd_pcm_lib_preallocate_free_for_all(chip->pcm);
+-		chip->pcm = NULL;
+-	}
+-}
+-
+ static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
+ {
+ 	struct snd_pcm *pcm;
+@@ -334,7 +342,6 @@ static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
+ 		goto out;
+ 
+ 	pcm->private_data = chip;
+-	pcm->private_free = snd_at73c213_pcm_free;
+ 	pcm->info_flags = SNDRV_PCM_INFO_BLOCK_TRANSFER;
+ 	strcpy(pcm->name, "at73c213");
+ 	chip->pcm = pcm;
+@@ -375,7 +382,8 @@ static irqreturn_t snd_at73c213_interrupt(int irq, void *dev_id)
+ 
+ 		ssc_writel(chip->ssc->regs, PDC_TNPR,
+ 				(long)runtime->dma_addr + offset);
+-		ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
++		ssc_writel(chip->ssc->regs, PDC_TNCR,
++				runtime->period_size * runtime->channels);
+ 		retval = IRQ_HANDLED;
+ 	}
+ 
+@@ -737,7 +745,7 @@ cleanup:
+ /*
+  * Device functions
+  */
+-static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
++static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+ {
+ 	/*
+ 	 * Continuous clock output.
+@@ -767,7 +775,7 @@ static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+ 	return 0;
+ }
+ 
+-static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
++static int __devinit snd_at73c213_chip_init(struct snd_at73c213 *chip)
+ {
+ 	int retval;
+ 	unsigned char dac_ctrl = 0;
+@@ -933,7 +941,7 @@ out:
+ 	return retval;
+ }
+ 
+-static int snd_at73c213_probe(struct spi_device *spi)
++static int __devinit snd_at73c213_probe(struct spi_device *spi)
+ {
+ 	struct snd_card			*card;
+ 	struct snd_at73c213		*chip;
+diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c
+index 9cc4cd8..24970a5 100644
+--- a/sound/usb/caiaq/caiaq-audio.c
++++ b/sound/usb/caiaq/caiaq-audio.c
+@@ -1,5 +1,5 @@
+ /*
+- *   Copyright (c) 2006,2007 Daniel Mack, Karsten Wiese
++ *   Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese
+  *
+  *   This program is free software; you can redistribute it and/or modify
+  *   it under the terms of the GNU General Public License as published by
+@@ -39,7 +39,8 @@
+ #define BYTES_PER_SAMPLE	3
+ #define BYTES_PER_SAMPLE_USB	4
+ #define MAX_BUFFER_SIZE		(128*1024)
+-				 
++#define MAX_ENDPOINT_SIZE	512
++
+ #define ENDPOINT_CAPTURE	2
+ #define ENDPOINT_PLAYBACK	6
+ 
+@@ -77,10 +78,15 @@ static void
+ deactivate_substream(struct snd_usb_caiaqdev *dev,
+ 		     struct snd_pcm_substream *sub)
+ {
++	unsigned long flags;
++	spin_lock_irqsave(&dev->spinlock, flags);
++
+ 	if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ 		dev->sub_playback[sub->number] = NULL;
+ 	else
+ 		dev->sub_capture[sub->number] = NULL;
++
++	spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+ 
+ static int
+@@ -97,13 +103,13 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
+ {
+ 	int i, ret;
+ 
+-	debug("stream_start(%p)\n", dev);
+-	spin_lock_irq(&dev->spinlock);
+-	if (dev->streaming) {
+-		spin_unlock_irq(&dev->spinlock);
++	debug("%s(%p)\n", __func__, dev);
++
++	if (dev->streaming)
+ 		return -EINVAL;
+-	}
+ 
++	memset(dev->sub_playback, 0, sizeof(dev->sub_playback));
++	memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
+ 	dev->input_panic = 0;
+ 	dev->output_panic = 0;
+ 	dev->first_packet = 1;
+@@ -112,37 +118,35 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
+ 	for (i = 0; i < N_URBS; i++) {
+ 		ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC);
+ 		if (ret) {
+-			log("unable to trigger initial read #%d! (ret = %d)\n",
+-				i, ret);
++			log("unable to trigger read #%d! (ret %d)\n", i, ret);
+ 			dev->streaming = 0;
+-			spin_unlock_irq(&dev->spinlock);
+ 			return -EPIPE;
+ 		}
+ 	}
+ 	
+-	spin_unlock_irq(&dev->spinlock);
+ 	return 0;
+ }
+ 
+ static void stream_stop(struct snd_usb_caiaqdev *dev)
+ {
+ 	int i;
+-	
+-	debug("stream_stop(%p)\n", dev);
++
++	debug("%s(%p)\n", __func__, dev);
+ 	if (!dev->streaming)
+ 		return;
+ 	
+ 	dev->streaming = 0;
++
+ 	for (i = 0; i < N_URBS; i++) {
+-		usb_unlink_urb(dev->data_urbs_in[i]);
+-		usb_unlink_urb(dev->data_urbs_out[i]);
++		usb_kill_urb(dev->data_urbs_in[i]);
++		usb_kill_urb(dev->data_urbs_out[i]);
+ 	}
+ }
+ 
+ static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
+ {
+ 	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+-	debug("snd_usb_caiaq_substream_open(%p)\n", substream);
++	debug("%s(%p)\n", __func__, substream);
+ 	substream->runtime->hw = dev->pcm_info;
+ 	snd_pcm_limit_hw_rates(substream->runtime);
+ 	return 0;
+@@ -152,7 +156,7 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
+ {
+ 	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+ 
+-	debug("snd_usb_caiaq_substream_close(%p)\n", substream);
++	debug("%s(%p)\n", __func__, substream);
+ 	if (all_substreams_zero(dev->sub_playback) &&
+ 	    all_substreams_zero(dev->sub_capture)) {
+ 		/* when the last client has stopped streaming, 
+@@ -160,24 +164,22 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
+ 		stream_stop(dev);
+ 		dev->pcm_info.rates = dev->samplerates;
+ 	}
+-	
++
+ 	return 0;
+ }
+ 
+ static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
+ 			     		struct snd_pcm_hw_params *hw_params)
+ {
+-	debug("snd_usb_caiaq_pcm_hw_params(%p)\n", sub);
++	debug("%s(%p)\n", __func__, sub);
+ 	return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
+ }
+ 
+ static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
+ {
+ 	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
+-	debug("snd_usb_caiaq_pcm_hw_free(%p)\n", sub);
+-	spin_lock_irq(&dev->spinlock);
++	debug("%s(%p)\n", __func__, sub);
+ 	deactivate_substream(dev, sub);
+-	spin_unlock_irq(&dev->spinlock);
+ 	return snd_pcm_lib_free_pages(sub);
+ }
+ 
+@@ -196,12 +198,12 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
+ 	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
+ 
+-	debug("snd_usb_caiaq_pcm_prepare(%p)\n", substream);
++	debug("%s(%p)\n", __func__, substream);
+ 	
+ 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ 		dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
+ 	else
+-		dev->audio_in_buf_pos[index] = 0;
++		dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE;
+ 	
+ 	if (dev->streaming)
+ 		return 0;
+@@ -220,7 +222,10 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
+ 	
+ 	bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
+ 		* bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams;
+-	
++
++	if (bpp > MAX_ENDPOINT_SIZE)
++		bpp = MAX_ENDPOINT_SIZE;
++
+ 	ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate,
+ 					     runtime->sample_bits, bpp);
+ 	if (ret)
+@@ -247,15 +252,11 @@ static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
+ 	switch (cmd) {
+ 	case SNDRV_PCM_TRIGGER_START:
+ 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+-		spin_lock(&dev->spinlock);
+ 		activate_substream(dev, sub);
+-		spin_unlock(&dev->spinlock);
+ 		break;
+ 	case SNDRV_PCM_TRIGGER_STOP:
+ 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+-		spin_lock(&dev->spinlock);
+ 		deactivate_substream(dev, sub);
+-		spin_unlock(&dev->spinlock);
+ 		break;
+ 	default:
+ 		return -EINVAL;
+@@ -328,8 +329,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
+ 	if (all_substreams_zero(dev->sub_capture))
+ 		return;
+ 
+-	spin_lock(&dev->spinlock);
+-	
+ 	for (i = 0; i < iso->actual_length;) {
+ 		for (stream = 0; stream < dev->n_streams; stream++, i++) {
+ 			sub = dev->sub_capture[stream];
+@@ -345,8 +344,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
+ 			}
+ 		}
+ 	}
+-	
+-	spin_unlock(&dev->spinlock);
+ }
+ 
+ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
+@@ -358,8 +355,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
+ 	struct snd_pcm_substream *sub;
+ 	int stream, i;
+ 
+-	spin_lock(&dev->spinlock);
+-	
+ 	for (i = 0; i < iso->actual_length;) {
+ 		if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) {
+ 			for (stream = 0; 
+@@ -393,8 +388,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
+ 			}
+ 		}
+ 	}
+-
+-	spin_unlock(&dev->spinlock);
+ }
+ 
+ static void read_in_urb(struct snd_usb_caiaqdev *dev,
+@@ -418,8 +411,6 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
+ 				dev->input_panic ? "(input)" : "",
+ 				dev->output_panic ? "(output)" : "");
+ 	}
+-
+-	check_for_elapsed_periods(dev, dev->sub_capture);
+ }
+ 
+ static void fill_out_urb(struct snd_usb_caiaqdev *dev, 
+@@ -429,8 +420,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
+ 	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+ 	struct snd_pcm_substream *sub;
+ 	int stream, i;
+-
+-	spin_lock(&dev->spinlock);
+ 	
+ 	for (i = 0; i < iso->length;) {
+ 		for (stream = 0; stream < dev->n_streams; stream++, i++) {
+@@ -456,9 +445,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
+ 		    for (stream = 0; stream < dev->n_streams; stream++, i++)
+ 		    	usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
+ 	}
+-
+-	spin_unlock(&dev->spinlock);
+-	check_for_elapsed_periods(dev, dev->sub_playback);
+ }
+ 
+ static void read_completed(struct urb *urb)
+@@ -472,6 +458,7 @@ static void read_completed(struct urb *urb)
+ 		return;
+ 
+ 	dev = info->dev;
++
+ 	if (!dev->streaming)
+ 		return;
+ 
+@@ -489,8 +476,12 @@ static void read_completed(struct urb *urb)
+ 		out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
+ 		
+ 		if (len > 0) {
++			spin_lock(&dev->spinlock);
+ 			fill_out_urb(dev, out, &out->iso_frame_desc[outframe]);
+ 			read_in_urb(dev, urb, &urb->iso_frame_desc[frame]);
++			spin_unlock(&dev->spinlock);
++			check_for_elapsed_periods(dev, dev->sub_playback);
++			check_for_elapsed_periods(dev, dev->sub_capture);
+ 			send_it = 1;
+ 		}
+ 
+@@ -696,7 +687,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
+ 
+ void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev)
+ {
+-	debug("snd_usb_caiaq_audio_free (%p)\n", dev);
++	debug("%s(%p)\n", __func__, dev);
+ 	stream_stop(dev);
+ 	free_urbs(dev->data_urbs_in);
+ 	free_urbs(dev->data_urbs_out);
+diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
+index 7c44a2c..e97d8b2 100644
+--- a/sound/usb/caiaq/caiaq-device.c
++++ b/sound/usb/caiaq/caiaq-device.c
+@@ -42,7 +42,7 @@
+ #endif
+ 
+ MODULE_AUTHOR("Daniel Mack <daniel at caiaq.de>");
+-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.2");
++MODULE_DESCRIPTION("caiaq USB audio, version 1.3.6");
+ MODULE_LICENSE("GPL");
+ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
+ 			 "{Native Instruments, RigKontrol3},"
+@@ -456,7 +456,7 @@ static void snd_disconnect(struct usb_interface *intf)
+ 	struct snd_usb_caiaqdev *dev;
+ 	struct snd_card *card = dev_get_drvdata(&intf->dev);
+ 
+-	debug("snd_disconnect(%p)\n", intf);
++	debug("%s(%p)\n", __func__, intf);
+ 
+ 	if (!card)
+ 		return;
+diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
+index f48838a..410be4a 100644
+--- a/sound/usb/usbaudio.c
++++ b/sound/usb/usbaudio.c
+@@ -64,9 +64,10 @@ MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
+ 
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
+-static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */
+-static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */
++static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
++/* Vendor/product IDs for this card */
++static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
++static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
+ static int nrpacks = 8;		/* max. number of packets per urb */
+ static int async_unlink = 1;
+ static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/
+@@ -687,7 +688,7 @@ static void snd_complete_urb(struct urb *urb)
+ 	int err = 0;
+ 
+ 	if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
+-	    ! subs->running || /* can be stopped during retire callback */
++	    !subs->running || /* can be stopped during retire callback */
+ 	    (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
+ 	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ 		clear_bit(ctx->index, &subs->active_mask);
+@@ -710,7 +711,7 @@ static void snd_complete_sync_urb(struct urb *urb)
+ 	int err = 0;
+ 
+ 	if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
+-	    ! subs->running || /* can be stopped during retire callback */
++	    !subs->running || /* can be stopped during retire callback */
+ 	    (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
+ 	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ 		clear_bit(ctx->index + 16, &subs->active_mask);
+@@ -740,7 +741,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s
+ 		vfree(runtime->dma_area);
+ 	}
+ 	runtime->dma_area = vmalloc(size);
+-	if (! runtime->dma_area)
++	if (!runtime->dma_area)
+ 		return -ENOMEM;
+ 	runtime->dma_bytes = size;
+ 	return 0;
+@@ -772,12 +773,12 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
+ 
+ 	async = !can_sleep && async_unlink;
+ 
+-	if (! async && in_interrupt())
++	if (!async && in_interrupt())
+ 		return 0;
+ 
+ 	for (i = 0; i < subs->nurbs; i++) {
+ 		if (test_bit(i, &subs->active_mask)) {
+-			if (! test_and_set_bit(i, &subs->unlink_mask)) {
++			if (!test_and_set_bit(i, &subs->unlink_mask)) {
+ 				struct urb *u = subs->dataurb[i].urb;
+ 				if (async)
+ 					usb_unlink_urb(u);
+@@ -789,7 +790,7 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
+ 	if (subs->syncpipe) {
+ 		for (i = 0; i < SYNC_URBS; i++) {
+ 			if (test_bit(i+16, &subs->active_mask)) {
+- 				if (! test_and_set_bit(i+16, &subs->unlink_mask)) {
++				if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
+ 					struct urb *u = subs->syncurb[i].urb;
+ 					if (async)
+ 						usb_unlink_urb(u);
+@@ -1137,12 +1138,12 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
+ 		if (subs->fmt_type == USB_FORMAT_TYPE_II)
+ 			u->packets++; /* for transfer delimiter */
+ 		u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+-		if (! u->urb)
++		if (!u->urb)
+ 			goto out_of_memory;
+ 		u->urb->transfer_buffer =
+ 			usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL,
+ 					 &u->urb->transfer_dma);
+-		if (! u->urb->transfer_buffer)
++		if (!u->urb->transfer_buffer)
+ 			goto out_of_memory;
+ 		u->urb->pipe = subs->datapipe;
+ 		u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+@@ -1155,7 +1156,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
+ 		/* allocate and initialize sync urbs */
+ 		subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4,
+ 						 GFP_KERNEL, &subs->sync_dma);
+-		if (! subs->syncbuf)
++		if (!subs->syncbuf)
+ 			goto out_of_memory;
+ 		for (i = 0; i < SYNC_URBS; i++) {
+ 			struct snd_urb_ctx *u = &subs->syncurb[i];
+@@ -1163,7 +1164,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
+ 			u->subs = subs;
+ 			u->packets = 1;
+ 			u->urb = usb_alloc_urb(1, GFP_KERNEL);
+-			if (! u->urb)
++			if (!u->urb)
+ 				goto out_of_memory;
+ 			u->urb->transfer_buffer = subs->syncbuf + i * 4;
+ 			u->urb->transfer_dma = subs->sync_dma + i * 4;
+@@ -1427,8 +1428,8 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
+ 	subs->cur_audiofmt = fmt;
+ 
+ #if 0
+-	printk("setting done: format = %d, rate = %d, channels = %d\n",
+-	       fmt->format, fmt->rate, fmt->channels);
++	printk("setting done: format = %d, rate = %d..%d, channels = %d\n",
++	       fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels);
+ 	printk("  datapipe = 0x%0x, syncpipe = 0x%0x\n",
+ 	       subs->datapipe, subs->syncpipe);
+ #endif
+@@ -1463,7 +1464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ 	rate = params_rate(hw_params);
+ 	channels = params_channels(hw_params);
+ 	fmt = find_format(subs, format, rate, channels);
+-	if (! fmt) {
++	if (!fmt) {
+ 		snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n",
+ 			   format, rate, channels);
+ 		return -EINVAL;
+@@ -1584,7 +1585,7 @@ static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audiof
+ 	struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ 
+ 	/* check the format */
+-	if (! snd_mask_test(fmts, fp->format)) {
++	if (!snd_mask_test(fmts, fp->format)) {
+ 		hwc_debug("   > check: no supported format %d\n", fp->format);
+ 		return 0;
+ 	}
+@@ -1620,7 +1621,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
+ 	list_for_each(p, &subs->fmt_list) {
+ 		struct audioformat *fp;
+ 		fp = list_entry(p, struct audioformat, list);
+-		if (! hw_check_valid_format(params, fp))
++		if (!hw_check_valid_format(params, fp))
+ 			continue;
+ 		if (changed++) {
+ 			if (rmin > fp->rate_min)
+@@ -1633,7 +1634,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
+ 		}
+ 	}
+ 
+-	if (! changed) {
++	if (!changed) {
+ 		hwc_debug("  --> get empty\n");
+ 		it->empty = 1;
+ 		return -EINVAL;
+@@ -1674,7 +1675,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
+ 	list_for_each(p, &subs->fmt_list) {
+ 		struct audioformat *fp;
+ 		fp = list_entry(p, struct audioformat, list);
+-		if (! hw_check_valid_format(params, fp))
++		if (!hw_check_valid_format(params, fp))
+ 			continue;
+ 		if (changed++) {
+ 			if (rmin > fp->channels)
+@@ -1687,7 +1688,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
+ 		}
+ 	}
+ 
+-	if (! changed) {
++	if (!changed) {
+ 		hwc_debug("  --> get empty\n");
+ 		it->empty = 1;
+ 		return -EINVAL;
+@@ -1727,7 +1728,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
+ 	list_for_each(p, &subs->fmt_list) {
+ 		struct audioformat *fp;
+ 		fp = list_entry(p, struct audioformat, list);
+-		if (! hw_check_valid_format(params, fp))
++		if (!hw_check_valid_format(params, fp))
+ 			continue;
+ 		fbits |= (1ULL << fp->format);
+ 	}
+@@ -1736,7 +1737,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
+ 	oldbits[1] = fmt->bits[1];
+ 	fmt->bits[0] &= (u32)fbits;
+ 	fmt->bits[1] &= (u32)(fbits >> 32);
+-	if (! fmt->bits[0] && ! fmt->bits[1]) {
++	if (!fmt->bits[0] && !fmt->bits[1]) {
+ 		hwc_debug("  --> get empty\n");
+ 		return -EINVAL;
+ 	}
+@@ -1762,8 +1763,10 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
+ 
+ 	channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
+ 	rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
+-	if (!channels || !rates)
++	if (!channels || !rates) {
++		err = -ENOMEM;
+ 		goto __out;
++	}
+ 
+ 	list_for_each(p, &subs->fmt_list) {
+ 		struct audioformat *f;
+@@ -1916,7 +1919,10 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
+ 				     1000 * MIN_PACKS_URB,
+ 				     /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
+ 
+-	if (check_hw_params_convention(subs)) {
++	err = check_hw_params_convention(subs);
++	if (err < 0)
++		return err;
++	else if (err) {
+ 		hwc_debug("setting extra hw constraints...\n");
+ 		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ 					       hw_rule_rate, subs,
+@@ -2222,7 +2228,7 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream)
+ 	struct snd_card *card = stream->chip->card;
+ 
+ 	sprintf(name, "stream%d", stream->pcm_index);
+-	if (! snd_card_proc_new(card, name, &entry))
++	if (!snd_card_proc_new(card, name, &entry))
+ 		snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
+ }
+ 
+@@ -2278,7 +2284,7 @@ static void free_substream(struct snd_usb_substream *subs)
+ {
+ 	struct list_head *p, *n;
+ 
+-	if (! subs->num_formats)
++	if (!subs->num_formats)
+ 		return; /* not initialized */
+ 	list_for_each_safe(p, n, &subs->fmt_list) {
+ 		struct audioformat *fp = list_entry(p, struct audioformat, list);
+@@ -2328,7 +2334,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
+ 		if (as->fmt_type != fp->fmt_type)
+ 			continue;
+ 		subs = &as->substream[stream];
+-		if (! subs->endpoint)
++		if (!subs->endpoint)
+ 			continue;
+ 		if (subs->endpoint == fp->endpoint) {
+ 			list_add_tail(&fp->list, &subs->fmt_list);
+@@ -2354,7 +2360,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
+ 
+ 	/* create a new pcm */
+ 	as = kzalloc(sizeof(*as), GFP_KERNEL);
+-	if (! as)
++	if (!as)
+ 		return -ENOMEM;
+ 	as->pcm_index = chip->pcm_devs;
+ 	as->chip = chip;
+@@ -2463,11 +2469,12 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audiofor
+ 		}
+ 		break;
+ 	case USB_AUDIO_FORMAT_PCM8:
+-		/* Dallas DS4201 workaround */
++		pcm_format = SNDRV_PCM_FORMAT_U8;
++
++		/* Dallas DS4201 workaround: it advertises U8 format, but really
++		   supports S8. */
+ 		if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+ 			pcm_format = SNDRV_PCM_FORMAT_S8;
+-		else
+-			pcm_format = SNDRV_PCM_FORMAT_U8;
+ 		break;
+ 	case USB_AUDIO_FORMAT_IEEE_FLOAT:
+ 		pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE;
+@@ -2671,12 +2678,23 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
+ 	int format;
+ 	struct audioformat *fp;
+ 	unsigned char *fmt, *csep;
++	int num;
+ 
+ 	dev = chip->dev;
+ 
+ 	/* parse the interface's altsettings */
+ 	iface = usb_ifnum_to_if(dev, iface_no);
+-	for (i = 0; i < iface->num_altsetting; i++) {
++
++	num = iface->num_altsetting;
++
++	/*
++	 * Dallas DS4201 workaround: It presents 5 altsettings, but the last
++	 * one misses syncpipe, and does not produce any sound.
++	 */
++	if (chip->usb_id == USB_ID(0x04fa, 0x4201))
++		num = 4;
++
++	for (i = 0; i < num; i++) {
+ 		alts = &iface->altsetting[i];
+ 		altsd = get_iface_desc(alts);
+ 		/* skip invalid one */
+@@ -3375,14 +3393,14 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
+ static void proc_audio_usbbus_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+ {
+ 	struct snd_usb_audio *chip = entry->private_data;
+-	if (! chip->shutdown)
++	if (!chip->shutdown)
+ 		snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
+ }
+ 
+ static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+ {
+ 	struct snd_usb_audio *chip = entry->private_data;
+-	if (! chip->shutdown)
++	if (!chip->shutdown)
+ 		snd_iprintf(buffer, "%04x:%04x\n", 
+ 			    USB_ID_VENDOR(chip->usb_id),
+ 			    USB_ID_PRODUCT(chip->usb_id));
+@@ -3391,9 +3409,9 @@ static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_
+ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
+ {
+ 	struct snd_info_entry *entry;
+-	if (! snd_card_proc_new(chip->card, "usbbus", &entry))
++	if (!snd_card_proc_new(chip->card, "usbbus", &entry))
+ 		snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
+-	if (! snd_card_proc_new(chip->card, "usbid", &entry))
++	if (!snd_card_proc_new(chip->card, "usbid", &entry))
+ 		snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
+ }
+ 
+@@ -3406,7 +3424,6 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
+ 
+ static int snd_usb_audio_free(struct snd_usb_audio *chip)
+ {
+-	usb_chip[chip->index] = NULL;
+ 	kfree(chip);
+ 	return 0;
+ }
+@@ -3600,8 +3617,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
+ 				snd_card_set_dev(chip->card, &intf->dev);
+ 				break;
+ 			}
+-		if (! chip) {
+-			snd_printk(KERN_ERR "no available usb audio device\n");
++		if (!chip) {
++			printk(KERN_ERR "no available usb audio device\n");
+ 			goto __error;
+ 		}
+ 	}
+@@ -3671,6 +3688,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
+ 		list_for_each(p, &chip->mixer_list) {
+ 			snd_usb_mixer_disconnect(p);
+ 		}
++		usb_chip[chip->index] = NULL;
+ 		mutex_unlock(&register_mutex);
+ 		snd_card_free_when_closed(card);
+ 	} else {
+diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
+index 938dff5..82a8d14 100644
+--- a/sound/usb/usbquirks.h
++++ b/sound/usb/usbquirks.h
+@@ -39,6 +39,30 @@
+ 	.idProduct = prod, \
+ 	.bInterfaceClass = USB_CLASS_VENDOR_SPEC
+ 
++/* Creative/E-Mu devices */
++{
++	USB_DEVICE(0x041e, 0x3010),
++	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++		.vendor_name = "Creative Labs",
++		.product_name = "Sound Blaster MP3+",
++		.ifnum = QUIRK_NO_INTERFACE
++	}
++},
++{
++	/* E-Mu 0202 USB */
++	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
++	.idVendor = 0x041e,
++	.idProduct = 0x3f02,
++	.bInterfaceClass = USB_CLASS_AUDIO,
++},
++{
++	/* E-Mu 0404 USB */
++	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
++	.idVendor = 0x041e,
++	.idProduct = 0x3f04,
++	.bInterfaceClass = USB_CLASS_AUDIO,
++},
++
+ /*
+  * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface
+  * class matches do not take effect without an explicit ID match.
+@@ -97,19 +121,7 @@
+ 	.bInterfaceClass = USB_CLASS_AUDIO,
+ 	.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
+ },
+-/* E-Mu devices */
+-{
+-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+-	.idVendor = 0x041e,
+-	.idProduct = 0x3f02,
+-	.bInterfaceClass = USB_CLASS_AUDIO,
+-},
+-{
+-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+-	.idVendor = 0x041e,
+-	.idProduct = 0x3f04,
+-	.bInterfaceClass = USB_CLASS_AUDIO,
+-},
++
+ /*
+  * Yamaha devices
+  */
+@@ -1165,19 +1177,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ 		}
+ 	}
+ },
+-{
+-	USB_DEVICE(0x582, 0x00a6),
+-	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-		.vendor_name = "Roland",
+-		.product_name = "Juno-G",
+-		.ifnum = 0,
+-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+-		.data = & (const struct snd_usb_midi_endpoint_info) {
+-			.out_cables = 0x0001,
+-			.in_cables  = 0x0001
+-		}
+-	}
+-},
+ {	/*
+ 	 * This quirk is for the "Advanced" modes of the Edirol UA-25.
+ 	 * If the switch is not in an advanced setting, the UA-25 has
+@@ -1336,6 +1335,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ 	/* TODO: add Edirol MD-P1 support */
+ {
++	USB_DEVICE(0x582, 0x00a6),
++	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++		.vendor_name = "Roland",
++		.product_name = "Juno-G",
++		.ifnum = 0,
++		.type = QUIRK_MIDI_FIXED_ENDPOINT,
++		.data = & (const struct snd_usb_midi_endpoint_info) {
++			.out_cables = 0x0001,
++			.in_cables  = 0x0001
++		}
++	}
++},
++{
+ 	/* Roland SH-201 */
+ 	USB_DEVICE(0x0582, 0x00ad),
+ 	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+@@ -1719,17 +1731,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ 	}
+ },
+ 
+-{
+-	/* Creative Sound Blaster MP3+ */
+-	USB_DEVICE(0x041e, 0x3010),
+-	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+-		.vendor_name = "Creative Labs",
+-		.product_name = "Sound Blaster MP3+",
+-		.ifnum = QUIRK_NO_INTERFACE
+-	}
+-	
+-},
+-
+ /* Emagic devices */
+ {
+ 	USB_DEVICE(0x086a, 0x0001),

Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	(original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	Sat Apr 26 21:59:14 2008
@@ -1,3 +1,4 @@
++ bugfix/all/patch-2.6.25-git9
 + debian/version.patch
 + debian/kernelvariables.patch
 + debian/doc-build-parallel.patch



More information about the Kernel-svn-changes mailing list